From 3628b9cdf6621560887b5dac13cecb92bd6710d1 Mon Sep 17 00:00:00 2001 From: justyy Date: Sat, 10 Jul 2021 16:17:35 +0000 Subject: [PATCH 0001/1197] Refactor Credentials.equal method and add unit tests --- .../java/org/tron/keystore/Credentials.java | 6 ++-- .../org/tron/keystroe/CredentialsTest.java | 34 +++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 framework/src/test/java/org/tron/keystroe/CredentialsTest.java diff --git a/framework/src/main/java/org/tron/keystore/Credentials.java b/framework/src/main/java/org/tron/keystore/Credentials.java index 687bbdaa5dc..1c44b21a80c 100644 --- a/framework/src/main/java/org/tron/keystore/Credentials.java +++ b/framework/src/main/java/org/tron/keystore/Credentials.java @@ -1,5 +1,6 @@ package org.tron.keystore; +import java.util.Objects; import org.tron.common.crypto.SignInterface; import org.tron.common.crypto.sm2.SM2; import org.tron.common.utils.StringUtil; @@ -46,12 +47,11 @@ public boolean equals(Object o) { Credentials that = (Credentials) o; - if (cryptoEngine != null ? !cryptoEngine - .equals(that.cryptoEngine) : that.cryptoEngine != null) { + if (!Objects.equals(cryptoEngine, that.cryptoEngine)) { return false; } - return address != null ? address.equals(that.address) : that.address == null; + return Objects.equals(address, that.address); } @Override diff --git a/framework/src/test/java/org/tron/keystroe/CredentialsTest.java b/framework/src/test/java/org/tron/keystroe/CredentialsTest.java new file mode 100644 index 00000000000..ce992c3443f --- /dev/null +++ b/framework/src/test/java/org/tron/keystroe/CredentialsTest.java @@ -0,0 +1,34 @@ +package org.tron.keystroe; + +import lombok.var; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; +import org.tron.common.crypto.SignInterface; +import org.tron.keystore.Credentials; + +public class CredentialsTest { + + @Test + public void test_equality() { + var aObject = new Object(); + var si = Mockito.mock(SignInterface.class); + var si2 = Mockito.mock(SignInterface.class); + var si3 = Mockito.mock(SignInterface.class); + var address = "TQhZ7W1RudxFdzJMw6FvMnujPxrS6sFfmj".getBytes(); + var address2 = "TNCmcTdyrYKMtmE1KU2itzeCX76jGm5Not".getBytes(); + Mockito.when(si.getAddress()).thenReturn(address); + Mockito.when(si2.getAddress()).thenReturn(address); + Mockito.when(si3.getAddress()).thenReturn(address2); + var aCredential = Credentials.create(si); + Assert.assertFalse(aObject.equals(aCredential)); + Assert.assertFalse(aCredential.equals(aObject)); + Assert.assertFalse(aCredential.equals(null)); + var anotherCredential = Credentials.create(si); + Assert.assertTrue(aCredential.equals(anotherCredential)); + var aCredential2 = Credentials.create(si2); + Assert.assertTrue(aCredential.equals(anotherCredential)); + var aCredential3 = Credentials.create(si3); + Assert.assertFalse(aCredential.equals(aCredential3)); + } +} From 2066989315c0ba12fe02abbed25eaee82225ddb0 Mon Sep 17 00:00:00 2001 From: hongdexiang <1090664234@qq.com> Date: Tue, 8 Mar 2022 14:25:43 +0800 Subject: [PATCH 0002/1197] add lru cache of contract and code --- .../UpdateEnergyLimitContractActuator.java | 2 ++ .../UpdateSettingContractActuator.java | 2 ++ .../org/tron/core/actuator/VMActuator.java | 5 ++++- .../core/vm/repository/RepositoryImpl.java | 20 +++++++++++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/UpdateEnergyLimitContractActuator.java b/actuator/src/main/java/org/tron/core/actuator/UpdateEnergyLimitContractActuator.java index 8de083f3fce..369b936a527 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UpdateEnergyLimitContractActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UpdateEnergyLimitContractActuator.java @@ -15,6 +15,7 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.store.AccountStore; import org.tron.core.store.ContractStore; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.SmartContractOuterClass.UpdateEnergyLimitContract; @@ -44,6 +45,7 @@ public boolean execute(Object object) throws ContractExeException { contractStore.put(contractAddress, new ContractCapsule( deployedContract.getInstance().toBuilder().setOriginEnergyLimit(newOriginEnergyLimit) .build())); + RepositoryImpl.removeLruCache(contractAddress); ret.setStatus(fee, code.SUCESS); } catch (InvalidProtocolBufferException e) { diff --git a/actuator/src/main/java/org/tron/core/actuator/UpdateSettingContractActuator.java b/actuator/src/main/java/org/tron/core/actuator/UpdateSettingContractActuator.java index f3d2e6f533d..d0025f14ef6 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UpdateSettingContractActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UpdateSettingContractActuator.java @@ -16,6 +16,7 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.store.AccountStore; import org.tron.core.store.ContractStore; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.SmartContractOuterClass.UpdateSettingContract; @@ -45,6 +46,7 @@ public boolean execute(Object object) throws ContractExeException { contractStore.put(contractAddress, new ContractCapsule( deployedContract.getInstance().toBuilder().setConsumeUserResourcePercent(newPercent) .build())); + RepositoryImpl.removeLruCache(contractAddress); ret.setStatus(fee, code.SUCESS); } catch (InvalidProtocolBufferException e) { diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index ff7d6f7e309..83f2c1c0367 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -21,6 +21,7 @@ import org.tron.common.runtime.InternalTransaction.ExecutorType; import org.tron.common.runtime.InternalTransaction.TrxType; import org.tron.common.runtime.ProgramResult; +import org.tron.common.runtime.vm.DataWord; import org.tron.common.utils.StorageUtils; import org.tron.common.utils.StringUtil; import org.tron.common.utils.WalletUtil; @@ -235,6 +236,9 @@ public void execute(Object object) throws ContractExeException { } else { rootRepository.commit(); } + for (DataWord account : result.getDeleteAccounts()) { + RepositoryImpl.removeLruCache(account.toTronAddress()); + } } catch (JVMStackOverFlowException e) { program.spendAllEnergy(); result = program.getResult(); @@ -715,5 +719,4 @@ private boolean isCheckTransaction() { .getWitnessSignature().isEmpty(); } - } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 807f267b9db..08dea07f93f 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -8,6 +8,7 @@ import java.util.Optional; import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.map.LRUMap; import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Hex; import org.tron.common.crypto.Hash; @@ -66,6 +67,9 @@ public class RepositoryImpl implements Repository { private static final byte[] TOTAL_NET_WEIGHT = "TOTAL_NET_WEIGHT".getBytes(); private static final byte[] TOTAL_ENERGY_WEIGHT = "TOTAL_ENERGY_WEIGHT".getBytes(); + private static final LRUMap contractLruCache = new LRUMap<>(); + private static final LRUMap codeLruCode = new LRUMap<>(); + private StoreFactory storeFactory; @Getter private DynamicPropertiesStore dynamicPropertiesStore; @@ -111,6 +115,12 @@ public class RepositoryImpl implements Repository { private HashMap votesCache = new HashMap<>(); private HashMap delegationCache = new HashMap<>(); + public static void removeLruCache(byte[] address) { + Key key = Key.create(address); + contractLruCache.remove(key); + codeLruCode.remove(key); + } + public RepositoryImpl(StoreFactory storeFactory, RepositoryImpl repository) { init(storeFactory, repository); } @@ -354,6 +364,10 @@ public void createContract(byte[] address, ContractCapsule contractCapsule) { @Override public ContractCapsule getContract(byte[] address) { Key key = Key.create(address); + if (contractLruCache.containsKey(key)) { + return contractLruCache.get(key); + } + if (contractCache.containsKey(key)) { return contractCache.get(key).getContract(); } @@ -367,6 +381,7 @@ public ContractCapsule getContract(byte[] address) { if (contractCapsule != null) { contractCache.put(key, Value.create(contractCapsule.getData())); + contractLruCache.put(key, contractCapsule); } return contractCapsule; } @@ -450,6 +465,10 @@ public void saveCode(byte[] address, byte[] code) { @Override public byte[] getCode(byte[] address) { Key key = Key.create(address); + if (codeLruCode.containsKey(key)) { + return codeLruCode.get(key); + } + if (codeCache.containsKey(key)) { return codeCache.get(key).getCode().getData(); } @@ -466,6 +485,7 @@ public byte[] getCode(byte[] address) { } if (code != null) { codeCache.put(key, Value.create(code)); + codeLruCode.put(key, code); } return code; } From 02058f79d7dc3fa6faf2ee2542404e699a583666 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 9 Mar 2022 11:31:31 +0800 Subject: [PATCH 0003/1197] gc perf: optimize transaction cache loading logic --- .../java/org/tron/core/ChainBaseManager.java | 12 +-- .../org/tron/core/db/RecentBlockStore.java | 1 - .../tron/core/db/RecentTransactionItem.java | 23 ++++ .../tron/core/db/RecentTransactionStore.java | 22 ++++ .../org/tron/core/db2/common/TxCacheDB.java | 100 +++++++++++++----- .../org/tron/core/config/DefaultConfig.java | 4 +- .../main/java/org/tron/core/db/Manager.java | 13 +++ .../org/tron/core/db/TransactionCache.java | 5 +- .../tool/litefullnode/LiteFullNodeTool.java | 1 + 9 files changed, 140 insertions(+), 41 deletions(-) create mode 100644 chainbase/src/main/java/org/tron/core/db/RecentTransactionItem.java create mode 100644 chainbase/src/main/java/org/tron/core/db/RecentTransactionStore.java diff --git a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java index 7cbb842f622..faf91d7671d 100644 --- a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java +++ b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java @@ -18,14 +18,7 @@ import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.utils.AssetUtil; import org.tron.core.capsule.utils.BlockUtil; -import org.tron.core.db.BlockIndexStore; -import org.tron.core.db.BlockStore; -import org.tron.core.db.CommonDataBase; -import org.tron.core.db.CommonStore; -import org.tron.core.db.KhaosDatabase; -import org.tron.core.db.PbftSignDataStore; -import org.tron.core.db.RecentBlockStore; -import org.tron.core.db.TransactionStore; +import org.tron.core.db.*; import org.tron.core.db2.core.ITronChainBase; import org.tron.core.exception.BadItemException; import org.tron.core.exception.HeaderNotFound; @@ -187,6 +180,9 @@ public class ChainBaseManager { private RecentBlockStore recentBlockStore; @Autowired @Getter + private RecentTransactionStore recentTransactionStore; + @Autowired + @Getter private TransactionHistoryStore transactionHistoryStore; @Getter diff --git a/chainbase/src/main/java/org/tron/core/db/RecentBlockStore.java b/chainbase/src/main/java/org/tron/core/db/RecentBlockStore.java index 53beed8bc6b..0b90cbc8ed0 100644 --- a/chainbase/src/main/java/org/tron/core/db/RecentBlockStore.java +++ b/chainbase/src/main/java/org/tron/core/db/RecentBlockStore.java @@ -17,7 +17,6 @@ private RecentBlockStore(@Value("recent-block") String dbName) { @Override public BytesCapsule get(byte[] key) throws ItemNotFoundException { byte[] value = revokingDB.get(key); - return new BytesCapsule(value); } } diff --git a/chainbase/src/main/java/org/tron/core/db/RecentTransactionItem.java b/chainbase/src/main/java/org/tron/core/db/RecentTransactionItem.java new file mode 100644 index 00000000000..150b1a9dfc0 --- /dev/null +++ b/chainbase/src/main/java/org/tron/core/db/RecentTransactionItem.java @@ -0,0 +1,23 @@ +package org.tron.core.db; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +public class RecentTransactionItem { + @Getter + @Setter + private long num; + + @Getter + @Setter + private List transactionIds; + + public RecentTransactionItem() {} + + public RecentTransactionItem(long num, List transactionIds) { + this.num = num; + this.transactionIds = transactionIds; + } +} diff --git a/chainbase/src/main/java/org/tron/core/db/RecentTransactionStore.java b/chainbase/src/main/java/org/tron/core/db/RecentTransactionStore.java new file mode 100644 index 00000000000..359a202351e --- /dev/null +++ b/chainbase/src/main/java/org/tron/core/db/RecentTransactionStore.java @@ -0,0 +1,22 @@ +package org.tron.core.db; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.tron.core.capsule.BytesCapsule; +import org.tron.core.exception.ItemNotFoundException; + +@Component +public class RecentTransactionStore extends TronStoreWithRevoking { + + @Autowired + private RecentTransactionStore(@Value("recent-transaction") String dbName) { + super(dbName); + } + + @Override + public BytesCapsule get(byte[] key) throws ItemNotFoundException { + byte[] value = revokingDB.get(key); + return new BytesCapsule(value); + } +} diff --git a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java index fcd31b5cad4..971f4099b24 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java @@ -6,18 +6,21 @@ import com.google.common.collect.Multimap; import com.google.common.primitives.Longs; import java.nio.file.Paths; -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Set; -import java.util.WeakHashMap; + import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import org.iq80.leveldb.WriteOptions; import org.tron.common.parameter.CommonParameter; import org.tron.common.storage.leveldb.LevelDbDataSourceImpl; import org.tron.common.storage.rocksdb.RocksDbDataSourceImpl; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.JsonUtil; import org.tron.common.utils.StorageUtils; +import org.tron.core.capsule.BytesCapsule; +import org.tron.core.db.RecentTransactionItem; +import org.tron.core.db.RecentTransactionStore; import org.tron.core.db.common.iterator.DBIterator; @Slf4j(topic = "DB") @@ -25,50 +28,51 @@ public class TxCacheDB implements DB, Flusher { // > 65_536(= 2^16) blocks, that is the number of the reference block private final int BLOCK_COUNT = 70_000; - + private final long MAX_SIZE = 65536; private Map db = new WeakHashMap<>(); private Multimap blockNumMap = ArrayListMultimap.create(); private String name; + private RecentTransactionStore recentTransactionStore; // add a persistent storage, the store name is: trans-cache // when fullnode startup, transactionCache initializes transactions from this store private DB persistentStore; - public TxCacheDB(String name) { + public TxCacheDB(String name, RecentTransactionStore recentTransactionStore) { this.name = name; - + this.recentTransactionStore = recentTransactionStore; int dbVersion = CommonParameter.getInstance().getStorage().getDbVersion(); String dbEngine = CommonParameter.getInstance().getStorage().getDbEngine(); if (dbVersion == 2) { if ("LEVELDB".equals(dbEngine.toUpperCase())) { this.persistentStore = new LevelDB( - new LevelDbDataSourceImpl(StorageUtils.getOutputDirectoryByDbName(name), - name, StorageUtils.getOptionsByDbName(name), - new WriteOptions().sync(CommonParameter.getInstance() - .getStorage().isDbSync()))); + new LevelDbDataSourceImpl(StorageUtils.getOutputDirectoryByDbName(name), + name, StorageUtils.getOptionsByDbName(name), + new WriteOptions().sync(CommonParameter.getInstance() + .getStorage().isDbSync()))); } else if ("ROCKSDB".equals(dbEngine.toUpperCase())) { String parentPath = Paths .get(StorageUtils.getOutputDirectoryByDbName(name), CommonParameter .getInstance().getStorage().getDbDirectory()).toString(); this.persistentStore = new RocksDB( - new RocksDbDataSourceImpl(parentPath, - name, CommonParameter.getInstance() - .getRocksDBCustomSettings())); + new RocksDbDataSourceImpl(parentPath, + name, CommonParameter.getInstance() + .getRocksDBCustomSettings())); } else { throw new RuntimeException("db type is not supported."); } } else { throw new RuntimeException("db version is not supported."); } - // init cache from persistent store init(); } /** * this method only used for init, put all data in tran-cache into the two maps. */ - private void init() { + private void initCache() { + long start = System.currentTimeMillis(); DBIterator iterator = (DBIterator) persistentStore.iterator(); while (iterator.hasNext()) { Entry entry = iterator.next(); @@ -82,10 +86,49 @@ private void init() { blockNumMap.put(v, k); db.put(k, v); } + logger.info("Transaction cache init-1 db-size:{}, blockNumMap-size:{}, cost:{}ms", + db.size(), blockNumMap.size(), System.currentTimeMillis() - start); } + private void init() { + long size = recentTransactionStore.size(); + if (size != MAX_SIZE) { + initCache(); + return; + } + + long start = System.currentTimeMillis(); + List l1 = new ArrayList<>(); + List l2 = new ArrayList<>(); + Iterator> iterator = recentTransactionStore.iterator(); + while (iterator.hasNext()) { + l1.add(iterator.next().getValue().getData()); + } + + l1.forEach(v -> l2.add(JsonUtil.json2Obj(new String(v), RecentTransactionItem.class))); + + l2.forEach(v -> v.getTransactionIds().forEach(tid -> put2(tid, v.getNum()))); + + logger.info("Transaction cache init-2 db-size:{}, blockNumMap-size:{}, cost:{}ms", + db.size(), blockNumMap.size(), System.currentTimeMillis() - start); + } + + public void put2(String key, long value) { + Key k = Key.copyOf(Hex.decode(key)); + Long v = Longs.fromByteArray(ByteArray.fromLong(value)); + blockNumMap.put(v, k); + db.put(k, v); + return; + } + + @Override public byte[] get(byte[] key) { + if (db == null || key == null) { + System.out.println("\n\n##### " + db + " ### " + key + "\n\n"); + logger.info("### {}, {}", db, key); + } + Long v = db.get(Key.of(key)); return v == null ? null : Longs.toByteArray(v); } @@ -109,15 +152,15 @@ private void removeEldest() { Set keys = blockNumMap.keySet(); if (keys.size() > BLOCK_COUNT) { keys.stream() - .min(Long::compareTo) - .ifPresent(k -> { - Collection trxHashs = blockNumMap.get(k); - // remove transaction from persistentStore, - // if foreach is inefficient, change remove-foreach to remove-batch - trxHashs.forEach(key -> persistentStore.remove(key.getBytes())); - blockNumMap.removeAll(k); - logger.debug("******removeEldest block number:{}, block count:{}", k, keys.size()); - }); + .min(Long::compareTo) + .ifPresent(k -> { + Collection trxHashs = blockNumMap.get(k); + // remove transaction from persistentStore, + // if foreach is inefficient, change remove-foreach to remove-batch + trxHashs.forEach(key -> persistentStore.remove(key.getBytes())); + blockNumMap.removeAll(k); + logger.debug("******removeEldest block number:{}, block count:{}", k, keys.size()); + }); } } @@ -146,7 +189,7 @@ public String getDbName() { @Override public Iterator> iterator() { return Iterators.transform(db.entrySet().iterator(), - e -> Maps.immutableEntry(e.getKey().getBytes(), Longs.toByteArray(e.getValue()))); + e -> Maps.immutableEntry(e.getKey().getBytes(), Longs.toByteArray(e.getValue()))); } @Override @@ -170,6 +213,7 @@ public void reset() { @Override public TxCacheDB newInstance() { - return new TxCacheDB(name); + return new TxCacheDB(name, recentTransactionStore); } } + diff --git a/framework/src/main/java/org/tron/core/config/DefaultConfig.java b/framework/src/main/java/org/tron/core/config/DefaultConfig.java index 2069c7b8215..aa2135b366d 100755 --- a/framework/src/main/java/org/tron/core/config/DefaultConfig.java +++ b/framework/src/main/java/org/tron/core/config/DefaultConfig.java @@ -10,6 +10,7 @@ import org.springframework.context.annotation.Import; import org.tron.common.utils.StorageUtils; import org.tron.core.config.args.Args; +import org.tron.core.db.RecentTransactionStore; import org.tron.core.db.RevokingDatabase; import org.tron.core.db.RevokingStore; import org.tron.core.db.TransactionCache; @@ -108,9 +109,8 @@ public HttpApiOnPBFTService getHttpApiOnPBFTService() { public TransactionCache transactionCache() { int dbVersion = Args.getInstance().getStorage().getDbVersion(); if (dbVersion == 2) { - return new TransactionCache("trans-cache"); + return new TransactionCache("trans-cache", appCtx.getBean(RecentTransactionStore.class)); } - return null; } diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 54db6c5c290..fbb39cd649e 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -62,6 +62,7 @@ import org.tron.common.parameter.CommonParameter; import org.tron.common.runtime.RuntimeImpl; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.JsonUtil; import org.tron.common.utils.Pair; import org.tron.common.utils.SessionOptional; import org.tron.common.utils.Sha256Hash; @@ -1516,6 +1517,7 @@ private void processBlock(BlockCapsule block, List txs) updateTransHashCache(block); updateRecentBlock(block); + updateRecentTransaction(block); updateDynamicProperties(block); chainBaseManager.getBalanceTraceStore().resetCurrentBlockTrace(); @@ -1623,6 +1625,17 @@ public void updateRecentBlock(BlockCapsule block) { new BytesCapsule(ByteArray.subArray(block.getBlockId().getBytes(), 8, 16))); } + public void updateRecentTransaction(BlockCapsule block) { + List list = new ArrayList<>(); + block.getTransactions().forEach(capsule -> { + list.add(capsule.getTransactionId().toString()); + }); + RecentTransactionItem item = new RecentTransactionItem(block.getNum(), list); + chainBaseManager.getRecentTransactionStore().put( + ByteArray.subArray(ByteArray.fromLong(block.getNum()), 6, 8), + new BytesCapsule(JsonUtil.obj2Json(item).getBytes())); + } + public void updateFork(BlockCapsule block) { int blockVersion = block.getInstance().getBlockHeader().getRawData().getVersion(); if (blockVersion > ChainConstant.BLOCK_VERSION) { diff --git a/framework/src/main/java/org/tron/core/db/TransactionCache.java b/framework/src/main/java/org/tron/core/db/TransactionCache.java index 496541d2fd4..715d82185d0 100644 --- a/framework/src/main/java/org/tron/core/db/TransactionCache.java +++ b/framework/src/main/java/org/tron/core/db/TransactionCache.java @@ -10,7 +10,8 @@ public class TransactionCache extends TronStoreWithRevoking { @Autowired - public TransactionCache(@Value("trans-cache") String dbName) { - super(new TxCacheDB(dbName)); + public TransactionCache(@Value("trans-cache") String dbName, + RecentTransactionStore recentTransactionStore) { + super(new TxCacheDB(dbName, recentTransactionStore)); } } diff --git a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java index fdf64ceb0ee..84473f8c119 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java @@ -79,6 +79,7 @@ public class LiteFullNodeTool { "properties", "proposal", "recent-block", + "recent-transaction", "storage-row", //TRANS_CACHE_DB_NAME, //"tree-block-index", From b2825bc09d3761b0ae4f88ca898d6df9b6150018 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Fri, 11 Mar 2022 18:05:07 +0800 Subject: [PATCH 0004/1197] perf(trx-cache): solve the sonar problem and remove test info --- .../java/org/tron/core/ChainBaseManager.java | 10 ++++++++- .../org/tron/core/db2/common/TxCacheDB.java | 21 ++++++++++--------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java index faf91d7671d..884fbeace15 100644 --- a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java +++ b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java @@ -18,7 +18,15 @@ import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.utils.AssetUtil; import org.tron.core.capsule.utils.BlockUtil; -import org.tron.core.db.*; +import org.tron.core.db.BlockIndexStore; +import org.tron.core.db.BlockStore; +import org.tron.core.db.CommonDataBase; +import org.tron.core.db.CommonStore; +import org.tron.core.db.KhaosDatabase; +import org.tron.core.db.PbftSignDataStore; +import org.tron.core.db.RecentBlockStore; +import org.tron.core.db.RecentTransactionStore; +import org.tron.core.db.TransactionStore; import org.tron.core.db2.core.ITronChainBase; import org.tron.core.exception.BadItemException; import org.tron.core.exception.HeaderNotFound; diff --git a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java index 971f4099b24..75f14d55b9d 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java @@ -5,9 +5,16 @@ import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.google.common.primitives.Longs; + import java.nio.file.Paths; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; import java.util.Map.Entry; +import java.util.Set; +import java.util.WeakHashMap; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; @@ -100,35 +107,29 @@ private void init() { long start = System.currentTimeMillis(); List l1 = new ArrayList<>(); List l2 = new ArrayList<>(); - Iterator> iterator = recentTransactionStore.iterator(); + Iterator> iterator = recentTransactionStore.iterator(); while (iterator.hasNext()) { l1.add(iterator.next().getValue().getData()); } l1.forEach(v -> l2.add(JsonUtil.json2Obj(new String(v), RecentTransactionItem.class))); - l2.forEach(v -> v.getTransactionIds().forEach(tid -> put2(tid, v.getNum()))); + l2.forEach(v -> v.getTransactionIds().forEach(tid -> putTransaction(tid, v.getNum()))); logger.info("Transaction cache init-2 db-size:{}, blockNumMap-size:{}, cost:{}ms", db.size(), blockNumMap.size(), System.currentTimeMillis() - start); } - public void put2(String key, long value) { + private void putTransaction(String key, long value) { Key k = Key.copyOf(Hex.decode(key)); Long v = Longs.fromByteArray(ByteArray.fromLong(value)); blockNumMap.put(v, k); db.put(k, v); - return; } @Override public byte[] get(byte[] key) { - if (db == null || key == null) { - System.out.println("\n\n##### " + db + " ### " + key + "\n\n"); - logger.info("### {}, {}", db, key); - } - Long v = db.get(Key.of(key)); return v == null ? null : Longs.toByteArray(v); } From a8f36c40f8eda9148a41b310a1a6393ed5b0c832 Mon Sep 17 00:00:00 2001 From: liukai Date: Mon, 14 Mar 2022 11:57:00 +0800 Subject: [PATCH 0005/1197] feat: optimize Optimised startup shell 1. add the startup parameter: * -p * -w * --witness 2. optimize the adaptation of any meaningful parameter incoming --- start.sh | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/start.sh b/start.sh index 17c23012956..797860ea25b 100644 --- a/start.sh +++ b/start.sh @@ -391,7 +391,6 @@ while [ -n "$1" ]; do case "$1" in -c) DEFAULT_FULL_NODE_CONFIG=$2 - FULL_START_OPT="$FULL_START_OPT $1 $2" shift 2 ;; -d) @@ -403,6 +402,18 @@ while [ -n "$1" ]; do JAR_NAME=$2 shift 2 ;; + -p) + FULL_START_OPT="$FULL_START_OPT $1 $2" + shift 2 + ;; + -w) + FULL_START_OPT="$FULL_START_OPT $1" + shift 1 + ;; + --witness) + FULL_START_OPT="$FULL_START_OPT $1" + shift 1 + ;; -m) REBUILD_MANIFEST_SIZE=$2 shift 2 @@ -487,8 +498,8 @@ while [ -n "$1" ]; do exit fi fi - echo "warn: option $1 does not exist" - exit + FULL_START_OPT="$FULL_START_OPT $@" + break ;; esac done @@ -533,3 +544,4 @@ if [[ $RUN == true ]]; then exit fi +restart From 10d707bd89a0294b0c4ccdd611cec29a779340e6 Mon Sep 17 00:00:00 2001 From: liukai Date: Mon, 14 Mar 2022 18:45:46 +0800 Subject: [PATCH 0006/1197] feat: optimize docker.shl usage instructions 1. add a parameter description --- docker.md | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/docker.md b/docker.md index 42c295e25db..b1af19d1f84 100644 --- a/docker.md +++ b/docker.md @@ -21,21 +21,29 @@ Get the `tronprotocol/java-tron` image from the DockerHub, this image contains t $ sh docker.sh --pull ``` -### Running the service -Before running the java-tron service, make sure the necessary ports are opened: -- `8090`: provides `HTTP` interface -- `50051`: provides `RPC` interface -- `18888`: P2P service listening interface +### Run the service +Before running the java-tron service, make sure some ports on your local machine are open,the image has the following ports automatically exposed: +- `8090`: used by the HTTP based JSON API +- `50051`: used by the GRPC based API +- `18888`: TCP and UDP, used by the P2P protocol running the network then start the java-tron service with the `--run` parameter ```shell $ sh docker.sh --run ``` +or you can use `-p` to customize the port mapping, more custom parameters, please refer to [Options](#Options) + +```shell +$ sh docker.sh --run -p 8080:8090 -p 40051:50051 +``` + +### View logs If you want to see the logs of the java-tron service, please use the `--log` parameter ```shell $ sh docker.sh --log | grep 'pushBlock' ``` +### Stop the service If you want to stop the container of java-tron, you can execute @@ -72,4 +80,7 @@ Parameters for all functions: * **`--stop`** stopping a running container -* **`--rm`** remove container,only deletes the container, not the image, the `config` and `output-directory` directories. +* **`--rm`** remove container,only deletes the container, not the image +* **`-p`** Publish a container's port to the host, format:`-p hostPort:containerPort` +* **`-c`** Specify other java-tron configuration file in the container +* **`-v`** Bind mount a volume for container,format: `-v host-src:container-dest`, the `host-src` is an absolute path From a68cee4991995d76c30e666b7048855b83357a16 Mon Sep 17 00:00:00 2001 From: liukai Date: Tue, 15 Mar 2022 14:52:33 +0800 Subject: [PATCH 0007/1197] feat: add docker run instructions 1. add docker run docker run parameters description --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 477b271a17f..406b885f0ba 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,19 @@ Here are some common use cases of the scripting tool For more details, please refer to the tool [guide](./shell.md). +## Run inside Docker container + +One of the quickest ways to get `java-tron` up and running on your machine is by using Docker: +```shell +$ docker run -d --name="java-tron" \ + -v /Users/tron/output-directory:/java-tron/output-directory \ + -v /Users/tron/logs:/java-tron/logs \ + -p 8090:8090 -p 18888:18888 -p 50051:50051 \ + tronprotocol/java-tron \ + -c /java-tron/config/main_net_config.conf +``` + +This will mount the `output-directory` and `logs` directories on the host, the docker.sh tool can also be used to simplify the use of docker, see more [here](docker.md). # Community [Tron Developers & SRs](https://discord.gg/hqKvyAM) is Tron's official Discord channel. Feel free to join this channel if you have any questions. From 741368a2cefae62da3e8050e24dfa471dbbde36c Mon Sep 17 00:00:00 2001 From: liukai Date: Tue, 15 Mar 2022 14:59:37 +0800 Subject: [PATCH 0008/1197] feat: modify docker the docker project structure 1. delete obsolete docker files 2. move dockerfile, docker.sh, docker.md to the docker directory --- Dockerfile | 43 ------------------- README.md | 2 +- docker/Dockerfile | 42 +++++++++++++++--- docker/README.md | 17 -------- .../docker-entrypoint.sh | 0 docker.md => docker/docker.md | 0 docker.sh => docker/docker.sh | 0 7 files changed, 36 insertions(+), 68 deletions(-) delete mode 100644 Dockerfile delete mode 100644 docker/README.md rename docker-entrypoint.sh => docker/docker-entrypoint.sh (100%) rename docker.md => docker/docker.md (100%) rename docker.sh => docker/docker.sh (100%) diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 1a6702c305e..00000000000 --- a/Dockerfile +++ /dev/null @@ -1,43 +0,0 @@ -FROM tronprotocol/centos7 - -ENV TMP_DIR="/tron-build" -ENV JDK_TAR="jdk-8u202-linux-x64.tar.gz" -ENV JDK_DIR="jdk1.8.0_202" -ENV JDK_MD5="0029351f7a946f6c05b582100c7d45b7" -ENV BASE_DIR="/java-tron" - - -RUN set -o errexit -o nounset \ - && yum -y install git wget \ - && wget -P /usr/local https://github.com/frekele/oracle-java/releases/download/8u202-b08/$JDK_TAR \ - && echo "$JDK_MD5 /usr/local/$JDK_TAR" | md5sum -c \ - && tar -zxf /usr/local/$JDK_TAR -C /usr/local\ - && rm /usr/local/$JDK_TAR \ - && export JAVA_HOME=/usr/local/$JDK_DIR \ - && export CLASSPATH=$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar \ - && export PATH=$PATH:$JAVA_HOME/bin \ - && echo "git clone" \ - && mkdir -p $TMP_DIR \ - && cd $TMP_DIR \ - && git clone https://github.com/tronprotocol/java-tron.git \ - && cd java-tron \ - && git checkout master \ - && ./gradlew build -x test \ - && cd build/distributions \ - && unzip -o java-tron-1.0.0.zip \ - && mv java-tron-1.0.0 $BASE_DIR \ - && wget -P $BASE_DIR/config https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/main_net_config.conf \ - && rm -rf $TMP_DIR \ - && rm -rf ~/.gradle \ - && mv $JAVA_HOME/jre /usr/local \ - && rm -rf $JAVA_HOME \ - && yum clean all - -ENV JAVA_HOME="/usr/local/jre" -ENV PATH=$PATH:$JAVA_HOME/bin - -COPY docker-entrypoint.sh $BASE_DIR/bin - -WORKDIR $BASE_DIR - -ENTRYPOINT ["./bin/docker-entrypoint.sh"] diff --git a/README.md b/README.md index 406b885f0ba..a8e28121d3b 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ $ docker run -d --name="java-tron" \ -c /java-tron/config/main_net_config.conf ``` -This will mount the `output-directory` and `logs` directories on the host, the docker.sh tool can also be used to simplify the use of docker, see more [here](docker.md). +This will mount the `output-directory` and `logs` directories on the host, the docker.sh tool can also be used to simplify the use of docker, see more [here](docker/docker.md). # Community [Tron Developers & SRs](https://discord.gg/hqKvyAM) is Tron's official Discord channel. Feel free to join this channel if you have any questions. diff --git a/docker/Dockerfile b/docker/Dockerfile index c6c757dadb8..1a6702c305e 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,15 +1,43 @@ -FROM tronprotocol/tron-gradle +FROM tronprotocol/centos7 + +ENV TMP_DIR="/tron-build" +ENV JDK_TAR="jdk-8u202-linux-x64.tar.gz" +ENV JDK_DIR="jdk1.8.0_202" +ENV JDK_MD5="0029351f7a946f6c05b582100c7d45b7" +ENV BASE_DIR="/java-tron" + RUN set -o errexit -o nounset \ -# Download and build java-tron + && yum -y install git wget \ + && wget -P /usr/local https://github.com/frekele/oracle-java/releases/download/8u202-b08/$JDK_TAR \ + && echo "$JDK_MD5 /usr/local/$JDK_TAR" | md5sum -c \ + && tar -zxf /usr/local/$JDK_TAR -C /usr/local\ + && rm /usr/local/$JDK_TAR \ + && export JAVA_HOME=/usr/local/$JDK_DIR \ + && export CLASSPATH=$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar \ + && export PATH=$PATH:$JAVA_HOME/bin \ && echo "git clone" \ + && mkdir -p $TMP_DIR \ + && cd $TMP_DIR \ && git clone https://github.com/tronprotocol/java-tron.git \ && cd java-tron \ - && gradle build + && git checkout master \ + && ./gradlew build -x test \ + && cd build/distributions \ + && unzip -o java-tron-1.0.0.zip \ + && mv java-tron-1.0.0 $BASE_DIR \ + && wget -P $BASE_DIR/config https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/main_net_config.conf \ + && rm -rf $TMP_DIR \ + && rm -rf ~/.gradle \ + && mv $JAVA_HOME/jre /usr/local \ + && rm -rf $JAVA_HOME \ + && yum clean all + +ENV JAVA_HOME="/usr/local/jre" +ENV PATH=$PATH:$JAVA_HOME/bin -# Change work directory -WORKDIR /java-tron +COPY docker-entrypoint.sh $BASE_DIR/bin -# open port 18888 -EXPOSE 18888 +WORKDIR $BASE_DIR +ENTRYPOINT ["./bin/docker-entrypoint.sh"] diff --git a/docker/README.md b/docker/README.md deleted file mode 100644 index 7103a4a4a04..00000000000 --- a/docker/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Quick Start - -> Note: To run docker you need start docker service. - -**Build a local docker image** - -```shell -> cd java-tron/docker -> docker image build -t tron-node . -``` - -**Run built image(refer to the home page)** - -```shell -> docker container run -p 18888:18888 -p 50051:50051 -it tronprotocol/tron-node /bin/bash -> ./gradlew run -Pwitness -``` \ No newline at end of file diff --git a/docker-entrypoint.sh b/docker/docker-entrypoint.sh similarity index 100% rename from docker-entrypoint.sh rename to docker/docker-entrypoint.sh diff --git a/docker.md b/docker/docker.md similarity index 100% rename from docker.md rename to docker/docker.md diff --git a/docker.sh b/docker/docker.sh similarity index 100% rename from docker.sh rename to docker/docker.sh From 6690a73de922b5a6dcc534431c3c85593c43080a Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 15 Mar 2022 15:14:01 +0800 Subject: [PATCH 0009/1197] perf(trx-cache): add update recent transaction cache test --- .../java/org/tron/core/db/ManagerTest.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index 47e506a808f..01d6486fc88 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -23,6 +23,7 @@ import org.tron.common.crypto.ECKey; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; +import org.tron.common.utils.JsonUtil; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.StringUtil; import org.tron.common.utils.Utils; @@ -126,6 +127,28 @@ public void removeDb() { FileUtil.deleteDir(new File(dbPath)); } + @Test + public void updateRecentTransaction() throws Exception { + TransferContract tc = + TransferContract.newBuilder() + .setAmount(10) + .setOwnerAddress(ByteString.copyFromUtf8("aaa")) + .setToAddress(ByteString.copyFromUtf8("bbb")) + .build(); + TransactionCapsule trx = new TransactionCapsule(tc, ContractType.TransferContract); + BlockCapsule b = new BlockCapsule(1, chainManager.getGenesisBlockId(), + 0, ByteString.copyFrom(new byte[64])); + b.addTransaction(trx); + dbManager.updateRecentTransaction(b); + Assert.assertEquals(1, chainManager.getRecentTransactionStore().size()); + byte[] key = ByteArray.subArray(ByteArray.fromLong(1), 6, 8); + byte[] value = chainManager.getRecentTransactionStore().get(key).getData(); + RecentTransactionItem item = JsonUtil.json2Obj(new String(value), RecentTransactionItem.class); + Assert.assertEquals(1, item.getNum()); + Assert.assertEquals(1, item.getTransactionIds().size()); + Assert.assertEquals(trx.getTransactionId().toString(), item.getTransactionIds().get(0)); + } + @Test public void setBlockReference() throws ContractExeException, UnLinkedBlockException, ValidateScheduleException, From d9f2c757d0c01369d27c8d33043fd3b4920a828f Mon Sep 17 00:00:00 2001 From: liukai Date: Tue, 15 Mar 2022 20:02:55 +0800 Subject: [PATCH 0010/1197] feat: optimize dockerfile 1. modify the way the configuration file is obtained --- docker/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 1a6702c305e..f19208f1816 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -26,13 +26,14 @@ RUN set -o errexit -o nounset \ && cd build/distributions \ && unzip -o java-tron-1.0.0.zip \ && mv java-tron-1.0.0 $BASE_DIR \ - && wget -P $BASE_DIR/config https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/main_net_config.conf \ && rm -rf $TMP_DIR \ && rm -rf ~/.gradle \ && mv $JAVA_HOME/jre /usr/local \ && rm -rf $JAVA_HOME \ && yum clean all +RUN wget -P $BASE_DIR/config https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/main_net_config.conf + ENV JAVA_HOME="/usr/local/jre" ENV PATH=$PATH:$JAVA_HOME/bin From ec41673f7662f47a66ae0b5d06b693a3089f70cc Mon Sep 17 00:00:00 2001 From: hongdexiang <1090664234@qq.com> Date: Wed, 16 Mar 2022 17:22:30 +0800 Subject: [PATCH 0011/1197] change : add parameter to set lru cache size --- .../core/vm/repository/RepositoryImpl.java | 19 ++++++++++++------- .../common/parameter/CommonParameter.java | 4 ++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 08dea07f93f..45f94b7a0a0 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -67,8 +67,9 @@ public class RepositoryImpl implements Repository { private static final byte[] TOTAL_NET_WEIGHT = "TOTAL_NET_WEIGHT".getBytes(); private static final byte[] TOTAL_ENERGY_WEIGHT = "TOTAL_ENERGY_WEIGHT".getBytes(); - private static final LRUMap contractLruCache = new LRUMap<>(); - private static final LRUMap codeLruCode = new LRUMap<>(); + private static final int lruCacheSize = CommonParameter.getInstance().lruCacheSize; + private static final LRUMap contractLruCache = new LRUMap<>(lruCacheSize); + private static final LRUMap codeLruCache = new LRUMap<>(lruCacheSize); private StoreFactory storeFactory; @Getter @@ -118,7 +119,7 @@ public class RepositoryImpl implements Repository { public static void removeLruCache(byte[] address) { Key key = Key.create(address); contractLruCache.remove(key); - codeLruCode.remove(key); + codeLruCache.remove(key); } public RepositoryImpl(StoreFactory storeFactory, RepositoryImpl repository) { @@ -381,7 +382,9 @@ public ContractCapsule getContract(byte[] address) { if (contractCapsule != null) { contractCache.put(key, Value.create(contractCapsule.getData())); - contractLruCache.put(key, contractCapsule); + if (!contractLruCache.containsKey(key)) { + contractLruCache.put(key, contractCapsule); + } } return contractCapsule; } @@ -465,8 +468,8 @@ public void saveCode(byte[] address, byte[] code) { @Override public byte[] getCode(byte[] address) { Key key = Key.create(address); - if (codeLruCode.containsKey(key)) { - return codeLruCode.get(key); + if (codeLruCache.containsKey(key)) { + return codeLruCache.get(key); } if (codeCache.containsKey(key)) { @@ -485,7 +488,9 @@ public byte[] getCode(byte[] address) { } if (code != null) { codeCache.put(key, Value.create(code)); - codeLruCode.put(key, code); + if (!codeLruCache.containsKey(key)) { + codeLruCache.put(key, code); + } } return code; } diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index f105eb6402d..4c9ad7a06a4 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -49,6 +49,10 @@ public class CommonParameter { public long maxEnergyLimitForConstant = 100_000_000L; @Getter @Setter + @Parameter(names = {"--lru-cache-size"}) + public int lruCacheSize = 100; + @Getter + @Setter @Parameter(names = {"--debug"}) public boolean debug = false; @Getter From c9bfec7bef500179521f651f3430ceeae185d52c Mon Sep 17 00:00:00 2001 From: wubin01 Date: Fri, 18 Mar 2022 11:22:49 +0800 Subject: [PATCH 0012/1197] perf(net): optimize light node synchronization logic --- .../common/overlay/message/HelloMessage.java | 43 +++++++++++--- .../common/overlay/server/ChannelManager.java | 5 ++ .../overlay/server/HandshakeHandler.java | 27 +++++++-- .../tron/common/overlay/server/SyncPool.java | 15 +++-- .../tool/litefullnode/LiteFullNodeTool.java | 7 +++ .../test/java/org/tron/core/net/TcpTest.java | 58 +++++++++++++------ protocol/src/main/protos/core/Tron.proto | 3 + 7 files changed, 123 insertions(+), 35 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java b/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java index 50ce2fa022a..b01d2dca534 100755 --- a/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java +++ b/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java @@ -3,9 +3,12 @@ import com.google.protobuf.ByteString; import lombok.Getter; import org.tron.common.overlay.discover.node.Node; +import org.tron.common.overlay.server.HandshakeHandler; import org.tron.common.utils.ByteArray; +import org.tron.core.ChainBaseManager; import org.tron.core.capsule.BlockCapsule; import org.tron.core.config.args.Args; +import org.tron.core.db.CommonStore; import org.tron.core.net.message.MessageTypes; import org.tron.protos.Discover.Endpoint; import org.tron.protos.Protocol; @@ -21,8 +24,7 @@ public HelloMessage(byte type, byte[] rawData) throws Exception { this.helloMessage = Protocol.HelloMessage.parseFrom(rawData); } - public HelloMessage(Node from, long timestamp, BlockCapsule.BlockId genesisBlockId, - BlockCapsule.BlockId solidBlockId, BlockCapsule.BlockId headBlockId) { + public HelloMessage(Node from, long timestamp, ChainBaseManager chainBaseManager) { Endpoint fromEndpoint = Endpoint.newBuilder() .setNodeId(ByteString.copyFrom(from.getId())) @@ -30,21 +32,36 @@ public HelloMessage(Node from, long timestamp, BlockCapsule.BlockId genesisBlock .setAddress(ByteString.copyFrom(ByteArray.fromString(from.getHost()))) .build(); + BlockCapsule.BlockId gid = chainBaseManager.getGenesisBlockId(); Protocol.HelloMessage.BlockId gBlockId = Protocol.HelloMessage.BlockId.newBuilder() - .setHash(genesisBlockId.getByteString()) - .setNumber(genesisBlockId.getNum()) + .setHash(gid.getByteString()) + .setNumber(gid.getNum()) .build(); + BlockCapsule.BlockId sid = chainBaseManager.getSolidBlockId(); Protocol.HelloMessage.BlockId sBlockId = Protocol.HelloMessage.BlockId.newBuilder() - .setHash(solidBlockId.getByteString()) - .setNumber(solidBlockId.getNum()) + .setHash(sid.getByteString()) + .setNumber(sid.getNum()) .build(); + BlockCapsule.BlockId hid = chainBaseManager.getHeadBlockId(); Protocol.HelloMessage.BlockId hBlockId = Protocol.HelloMessage.BlockId.newBuilder() - .setHash(headBlockId.getByteString()) - .setNumber(headBlockId.getNum()) + .setHash(hid.getByteString()) + .setNumber(hid.getNum()) .build(); + CommonStore commonStore = chainBaseManager.getCommonStore(); + int nodeType = HandshakeHandler.NODE_TYPE_FULL_NODE; + byte[] c1 = commonStore.get(HandshakeHandler.DB_KEY_NODE_TYPE).getData(); + if (c1 != null) { + nodeType = ByteArray.toInt(c1); + } + long lowestBlockNum = 0; + if (nodeType == HandshakeHandler.NODE_TYPE_LIGHT_NODE) { + byte[] c2 = commonStore.get(HandshakeHandler.DB_KEY_LOWEST_BLOCK_NUM).getData(); + lowestBlockNum = ByteArray.toLong(c2); + } + Builder builder = Protocol.HelloMessage.newBuilder(); builder.setFrom(fromEndpoint); @@ -53,6 +70,8 @@ public HelloMessage(Node from, long timestamp, BlockCapsule.BlockId genesisBlock builder.setGenesisBlockId(gBlockId); builder.setSolidBlockId(sBlockId); builder.setHeadBlockId(hBlockId); + builder.setNodeType(nodeType); + builder.setLowestBlockNum(lowestBlockNum); this.helloMessage = builder.build(); this.type = MessageTypes.P2P_HELLO.asByte(); @@ -68,6 +87,14 @@ public int getVersion() { return this.helloMessage.getVersion(); } + public int getNodeType() { + return this.helloMessage.getNodeType(); + } + + public long getLowestBlockNum() { + return this.helloMessage.getLowestBlockNum(); + } + public long getTimestamp() { return this.helloMessage.getTimestamp(); } diff --git a/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java b/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java index 3b8aef13353..21c754e6510 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java +++ b/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java @@ -24,6 +24,7 @@ import org.tron.core.db.ByteArrayWrapper; import org.tron.core.metrics.MetricsKey; import org.tron.core.metrics.MetricsUtil; +import org.tron.protos.Protocol; import org.tron.protos.Protocol.ReasonCode; @Slf4j(topic = "net") @@ -46,6 +47,10 @@ public class ChannelManager { private Cache recentlyDisconnected = CacheBuilder.newBuilder() .maximumSize(1000).expireAfterWrite(30, TimeUnit.SECONDS).recordStats().build(); + @Getter + private Cache helloMessageCache = CacheBuilder.newBuilder() + .maximumSize(2000).expireAfterWrite(24, TimeUnit.HOURS).recordStats().build(); + @Getter private Cache trustNodes = CacheBuilder.newBuilder().maximumSize(100).build(); diff --git a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java index 0858a383304..dd1c5be0921 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java @@ -72,6 +72,12 @@ public class HandshakeHandler extends ByteToMessageDecoder { @Autowired private SyncPool syncPool; + public static final byte[] DB_KEY_LOWEST_BLOCK_NUM = "lowest_block_num".getBytes(); + public static final byte[] DB_KEY_NODE_TYPE = "node_type".getBytes(); + + public static int NODE_TYPE_FULL_NODE = 0; + public static int NODE_TYPE_LIGHT_NODE = 1; + @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { logger.info("channel active, {}", ctx.channel().remoteAddress()); @@ -119,9 +125,8 @@ public void setChannel(Channel channel, String remoteId) { } protected void sendHelloMsg(ChannelHandlerContext ctx, long time) { - HelloMessage message = new HelloMessage(nodeManager.getPublicHomeNode(), time, - chainBaseManager.getGenesisBlockId(), chainBaseManager.getSolidBlockId(), - chainBaseManager.getHeadBlockId()); + HelloMessage message = new HelloMessage( + nodeManager.getPublicHomeNode(), time, chainBaseManager); fastForward.fillHelloMessage(message, channel); ((PeerConnection) channel).setHelloMessageSend(message); ctx.writeAndFlush(message.getSendData()); @@ -132,7 +137,6 @@ protected void sendHelloMsg(ChannelHandlerContext ctx, long time) { } private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { - channel.initNode(msg.getFrom().getId(), msg.getFrom().getPort()); if (!fastForward.checkHelloMessage(msg, channel)) { @@ -140,8 +144,8 @@ private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { return; } + InetAddress address = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress(); if (remoteId.length != 64) { - InetAddress address = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress(); if (channelManager.getTrustNodes().getIfPresent(address) == null && !syncPool .isCanConnect()) { channel.disconnect(ReasonCode.TOO_MANY_PEERS); @@ -149,6 +153,15 @@ private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { } } + long headBlockNum = chainBaseManager.getHeadBlockNum(); + long lowestBlockNum = msg.getLowestBlockNum(); + if (lowestBlockNum > headBlockNum) { + logger.info("Peer {} miss block, lowestBlockNum:{}, headBlockNum:{}", + ctx.channel().remoteAddress(), lowestBlockNum, headBlockNum); + channel.disconnect(ReasonCode.LIGHT_NODE_SYNC_FAIL); + return; + } + if (msg.getVersion() != Args.getInstance().getNodeP2pVersion()) { logger.info("Peer {} different p2p version, peer->{}, me->{}", ctx.channel().remoteAddress(), msg.getVersion(), Args.getInstance().getNodeP2pVersion()); @@ -175,6 +188,10 @@ private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { return; } + if (msg.getFrom().getHost().equals(address.getHostAddress())) { + channelManager.getHelloMessageCache().put(msg.getFrom().getHost(), msg.getHelloMessage()); + } + ((PeerConnection) channel).setHelloMessageReceive(msg); channel.getNodeStatistics().messageStatistics.addTcpInMessage(msg); diff --git a/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java b/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java index 7c8f2b1af52..8c0ac93a06c 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java +++ b/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java @@ -23,8 +23,10 @@ import org.tron.common.overlay.discover.node.NodeHandler; import org.tron.common.overlay.discover.node.NodeManager; import org.tron.common.parameter.CommonParameter; +import org.tron.core.ChainBaseManager; import org.tron.core.config.args.Args; import org.tron.core.net.peer.PeerConnection; +import org.tron.protos.Protocol; @Slf4j(topic = "net") @Component @@ -45,6 +47,9 @@ public class SyncPool { @Autowired private ApplicationContext ctx; + @Autowired + private ChainBaseManager chainBaseManager; + private ChannelManager channelManager; private CommonParameter commonParameter = CommonParameter.getInstance(); @@ -207,16 +212,18 @@ public NodeSelector(Set nodesInUse) { @Override public boolean test(NodeHandler handler) { - + long headNum = chainBaseManager.getHeadBlockNum(); InetAddress inetAddress = handler.getInetSocketAddress().getAddress(); - + Protocol.HelloMessage message = channelManager.getHelloMessageCache() + .getIfPresent(inetAddress.getHostAddress()); return !((handler.getNode().getHost().equals(nodeManager.getPublicHomeNode().getHost()) - && handler.getNode().getPort() == nodeManager.getPublicHomeNode().getPort()) + && handler.getNode().getPort() == nodeManager.getPublicHomeNode().getPort()) || (channelManager.getRecentlyDisconnected().getIfPresent(inetAddress) != null) || (channelManager.getBadPeers().getIfPresent(inetAddress) != null) || (channelManager.getConnectionNum(inetAddress) >= maxActivePeersWithSameIp) || (nodesInUse.contains(handler.getNode().getHexId())) - || (nodeHandlerCache.getIfPresent(handler) != null)); + || (nodeHandlerCache.getIfPresent(handler) != null) + || (message != null && headNum < message.getLowestBlockNum())); } } diff --git a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java index fdf64ceb0ee..370744ee702 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java @@ -22,6 +22,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.rocksdb.RocksDBException; +import org.tron.common.overlay.server.HandshakeHandler; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; @@ -49,6 +50,7 @@ public class LiteFullNodeTool { private static final String BLOCK_DB_NAME = "block"; private static final String BLOCK_INDEX_DB_NAME = "block-index"; private static final String TRANS_CACHE_DB_NAME = "trans-cache"; + private static final String COMMON_DB_NAME = "common"; private static final String DIR_FORMAT_STRING = "%s%s%s"; @@ -301,6 +303,11 @@ private void fillSnapshotBlockDb(String sourceDir, String snapshotDir) // put latest blocks into snapshot destBlockDb.put(blockId, block); }); + + DBInterface commonDb = DbTool.getDB(sourceDir, COMMON_DB_NAME); + commonDb.put(HandshakeHandler.DB_KEY_NODE_TYPE, + ByteArray.fromInt(HandshakeHandler.NODE_TYPE_LIGHT_NODE)); + commonDb.put(HandshakeHandler.DB_KEY_LOWEST_BLOCK_NUM, ByteArray.fromLong(startIndex)); } private void checkTranCacheStore(String sourceDir, String snapshotDir) diff --git a/framework/src/test/java/org/tron/core/net/TcpTest.java b/framework/src/test/java/org/tron/core/net/TcpTest.java index 32eb64c8e7e..5884efffd91 100644 --- a/framework/src/test/java/org/tron/core/net/TcpTest.java +++ b/framework/src/test/java/org/tron/core/net/TcpTest.java @@ -6,6 +6,7 @@ import static org.tron.protos.Protocol.ReasonCode.FORKED; import static org.tron.protos.Protocol.ReasonCode.INCOMPATIBLE_CHAIN; import static org.tron.protos.Protocol.ReasonCode.INCOMPATIBLE_VERSION; +import static org.tron.protos.Protocol.ReasonCode.LIGHT_NODE_SYNC_FAIL; import com.google.common.cache.CacheBuilder; import io.netty.buffer.ByteBuf; @@ -22,6 +23,7 @@ import org.junit.Assert; import org.tron.common.application.TronApplicationContext; import org.tron.common.overlay.discover.node.Node; +import org.tron.common.overlay.discover.node.NodeManager; import org.tron.common.overlay.message.DisconnectMessage; import org.tron.common.overlay.message.HelloMessage; import org.tron.common.overlay.message.Message; @@ -29,14 +31,17 @@ import org.tron.common.overlay.message.P2pMessageFactory; import org.tron.common.overlay.server.ChannelManager; import org.tron.common.overlay.server.SyncPool; +import org.tron.common.utils.ByteArray; import org.tron.common.utils.ReflectUtils; import org.tron.core.ChainBaseManager; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.BlockCapsule.BlockId; +import org.tron.core.capsule.BytesCapsule; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; import org.tron.core.net.message.BlockMessage; import org.tron.core.net.peer.PeerConnection; +import org.tron.protos.Protocol; import org.tron.protos.Protocol.Block; @Slf4j @@ -62,18 +67,20 @@ public TcpTest(TronApplicationContext context) { public void normalTest() throws InterruptedException { Channel channel = BaseNet.connect(new HandshakeHandler(TestType.normal)); - HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), - chainBaseManager.getGenesisBlockId(), chainBaseManager.getSolidBlockId(), - chainBaseManager.getHeadBlockId()); + HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), chainBaseManager); sendMessage(channel, message); validResultCloseConnect(channel); } public void errorGenesisBlockIdTest() throws InterruptedException { Channel channel = BaseNet.connect(new HandshakeHandler(TestType.errorGenesisBlock)); - BlockId genesisBlockId = new BlockId(); - HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), genesisBlockId, - chainBaseManager.getSolidBlockId(), chainBaseManager.getHeadBlockId()); + HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), chainBaseManager); + Protocol.HelloMessage.BlockId genesisBlockId = Protocol.HelloMessage.BlockId.newBuilder() + .setHash(new BlockId().getByteString()) + .setNumber(new BlockId().getNum()) + .build(); + message.setHelloMessage( + message.getHelloMessage().toBuilder().setGenesisBlockId(genesisBlockId).build()); sendMessage(channel, message); validResultCloseConnect(channel); } @@ -81,9 +88,7 @@ public void errorGenesisBlockIdTest() throws InterruptedException { public void errorVersionTest() throws InterruptedException { Channel channel = BaseNet.connect(new HandshakeHandler(TestType.errorVersion)); Args.getInstance().setNodeP2pVersion(1); - HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), - chainBaseManager.getGenesisBlockId(), chainBaseManager.getSolidBlockId(), - chainBaseManager.getHeadBlockId()); + HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), chainBaseManager); Args.getInstance().setNodeP2pVersion(2); sendMessage(channel, message); validResultCloseConnect(channel); @@ -91,17 +96,20 @@ public void errorVersionTest() throws InterruptedException { public void errorSolidBlockIdTest() throws InterruptedException { Channel channel = BaseNet.connect(new HandshakeHandler(TestType.errorSolid)); - HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), - chainBaseManager.getGenesisBlockId(), new BlockId(), chainBaseManager.getHeadBlockId()); + HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), chainBaseManager); + Protocol.HelloMessage.BlockId sBlockId = Protocol.HelloMessage.BlockId.newBuilder() + .setHash(new BlockId().getByteString()) + .setNumber(new BlockId().getNum()) + .build(); + message.setHelloMessage( + message.getHelloMessage().toBuilder().setSolidBlockId(sBlockId).build()); sendMessage(channel, message); validResultCloseConnect(channel); } public void repeatConnectTest() throws InterruptedException { Channel channel = BaseNet.connect(new HandshakeHandler(TestType.normal)); - HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), - chainBaseManager.getGenesisBlockId(), chainBaseManager.getSolidBlockId(), - chainBaseManager.getHeadBlockId()); + HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), chainBaseManager); sendMessage(channel, message); validResultUnCloseConnect(); Channel repeatChannel = BaseNet.connect(new HandshakeHandler(TestType.repeatConnect)); @@ -126,9 +134,7 @@ public void unHandshakeTest() throws InterruptedException { public void errorMsgTest() throws InterruptedException { Channel channel = BaseNet.connect(new HandshakeHandler(TestType.normal)); - HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), - chainBaseManager.getGenesisBlockId(), chainBaseManager.getSolidBlockId(), - chainBaseManager.getHeadBlockId()); + HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), chainBaseManager); sendMessage(channel, message); validResultUnCloseConnect(); List beforeActivePeers = @@ -153,6 +159,15 @@ public void errorMsgTest() throws InterruptedException { clearConnect(channel); } + public void errorLowestBlockNumTest() throws InterruptedException { + Channel channel = BaseNet.connect(new HandshakeHandler(TestType.errorLowestBlockNum)); + HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), chainBaseManager); + message.setHelloMessage( + message.getHelloMessage().toBuilder().setNodeType(1).setLowestBlockNum(100).build()); + sendMessage(channel, message); + validResultCloseConnect(channel); + } + private void sendMessage(Channel channel, Message message) { channel.writeAndFlush(message.getSendData()) .addListener((ChannelFutureListener) future -> { @@ -219,11 +234,14 @@ public void test() throws InterruptedException { logger.info("begin unHandshake test"); unHandshakeTest(); logger.info("begin errorMsg test"); + errorLowestBlockNumTest(); + logger.info("begin errorLowestBlockNum test"); errorMsgTest(); } private enum TestType { - normal, errorGenesisBlock, errorVersion, errorSolid, repeatConnect + normal, errorGenesisBlock, errorVersion, errorSolid, + repeatConnect, errorLowestBlockNum } private class HandshakeHandler extends ByteToMessageDecoder { @@ -262,6 +280,10 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List ou Assert.assertEquals(msg.getType(), P2P_DISCONNECT); Assert.assertEquals(((DisconnectMessage) msg).getReasonCode(), DUPLICATE_PEER); break; + case errorLowestBlockNum: + Assert.assertEquals(msg.getType(), P2P_DISCONNECT); + Assert.assertEquals(((DisconnectMessage) msg).getReasonCode(), LIGHT_NODE_SYNC_FAIL); + break; default: break; } diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index a4409923086..d29b4abdf43 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -599,6 +599,7 @@ enum ReasonCode { TIME_OUT = 0x20; CONNECT_FAIL = 0x21; TOO_MANY_PEERS_WITH_SAME_IP = 0x22; + LIGHT_NODE_SYNC_FAIL = 0x23; UNKNOWN = 0xFF; } @@ -620,6 +621,8 @@ message HelloMessage { BlockId headBlockId = 6; bytes address = 7; bytes signature = 8; + int32 nodeType = 9; + int64 lowestBlockNum = 10; } message InternalTransaction { From acda14f958251ffbaddbd61d3a2af0ddcf8820c1 Mon Sep 17 00:00:00 2001 From: hongdexiang <1090664234@qq.com> Date: Fri, 18 Mar 2022 13:58:18 +0800 Subject: [PATCH 0013/1197] change : add programPreCompile lru cache --- .../org/tron/core/vm/program/Program.java | 21 ++++++++++++++++++- .../core/vm/repository/RepositoryImpl.java | 4 +++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 9ac3619f416..5e5b67da3e3 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -17,6 +17,7 @@ import java.util.Map; import java.util.Objects; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.map.LRUMap; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.tuple.Pair; import org.bouncycastle.util.encoders.Hex; @@ -62,6 +63,7 @@ import org.tron.core.vm.program.listener.CompositeProgramListener; import org.tron.core.vm.program.listener.ProgramListenerAware; import org.tron.core.vm.program.listener.ProgramStorageChangeListener; +import org.tron.core.vm.repository.Key; import org.tron.core.vm.repository.Repository; import org.tron.core.vm.trace.ProgramTrace; import org.tron.core.vm.trace.ProgramTraceListener; @@ -84,6 +86,7 @@ public class Program { private static final String INVALID_TOKEN_ID_MSG = "not valid token id"; private static final String REFUND_ENERGY_FROM_MESSAGE_CALL = "refund energy from message call"; private static final String CALL_PRE_COMPILED = "call pre-compiled"; + private static final LRUMap programPrecompileLRUMap = new LRUMap<>(); private long nonce; private byte[] rootTransactionId; private InternalTransaction internalTransaction; @@ -167,7 +170,13 @@ public void setNonce(long nonceValue) { public ProgramPrecompile getProgramPrecompile() { if (programPrecompile == null) { - programPrecompile = ProgramPrecompile.compile(ops); + Key key = getCodeHashKey(); + if (programPrecompileLRUMap.containsKey(key)) { + programPrecompile = programPrecompileLRUMap.get(key); + } else { + programPrecompile = ProgramPrecompile.compile(ops); + programPrecompileLRUMap.put(key, programPrecompile); + } } return programPrecompile; } @@ -1032,6 +1041,16 @@ public byte[] getCodeHashAt(DataWord address) { } } + private byte[] getCodeHash() { + ContractCapsule contract = getContractState().getContract(getContextAddress()); + return contract.getCodeHash(); + } + + private Key getCodeHashKey() { + byte[] codeHash = getCodeHash(); + return Key.create(codeHash); + } + public byte[] getContextAddress() { return invoke.getContractAddress().toTronAddress(); } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 45f94b7a0a0..ad2774722e0 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -67,7 +67,9 @@ public class RepositoryImpl implements Repository { private static final byte[] TOTAL_NET_WEIGHT = "TOTAL_NET_WEIGHT".getBytes(); private static final byte[] TOTAL_ENERGY_WEIGHT = "TOTAL_ENERGY_WEIGHT".getBytes(); - private static final int lruCacheSize = CommonParameter.getInstance().lruCacheSize; + private static final int lruCacheSize = + CommonParameter.getInstance().lruCacheSize < 1 + ? 100 : CommonParameter.getInstance().lruCacheSize; private static final LRUMap contractLruCache = new LRUMap<>(lruCacheSize); private static final LRUMap codeLruCache = new LRUMap<>(lruCacheSize); From 59274b1f05a0044344efe622764f9c8a87449396 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 3 Aug 2021 19:07:17 +0800 Subject: [PATCH 0014/1197] feat(db): node conditionalized stop 1. given block time,block height,block sync count 2. add new method for query persistence db TIP:https://github.com/tronprotocol/tips/issues/370 --- .../java/org/tron/core/db/TronDatabase.java | 6 ++ .../tron/core/db/TronStoreWithRevoking.java | 6 ++ .../org/tron/core/db2/common/IRevokingDB.java | 2 + .../org/tron/core/db2/core/Chainbase.java | 9 ++ .../tron/core/db2/core/ITronChainBase.java | 3 + .../core/RevokingDBWithCachingOldValue.java | 5 + .../core/store/DynamicPropertiesStore.java | 15 +++ common/build.gradle | 2 + .../common/parameter/CommonParameter.java | 13 +++ .../src/main/java/org/tron/core/Constant.java | 4 + .../java/org/tron/core/config/args/Args.java | 92 ++++++++++++------- .../tron/core/consensus/ConsensusService.java | 2 + .../main/java/org/tron/core/db/Manager.java | 39 ++++++++ .../org/tron/core/net/TronNetDelegate.java | 36 ++++++++ .../org/tron/core/net/TronNetService.java | 1 + 15 files changed, 203 insertions(+), 32 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/db/TronDatabase.java b/chainbase/src/main/java/org/tron/core/db/TronDatabase.java index 5b8762ec9ad..ee608e4d5ad 100644 --- a/chainbase/src/main/java/org/tron/core/db/TronDatabase.java +++ b/chainbase/src/main/java/org/tron/core/db/TronDatabase.java @@ -75,6 +75,12 @@ public void close() { public abstract T get(byte[] key) throws InvalidProtocolBufferException, ItemNotFoundException, BadItemException; + @Override + public T getFromRoot(byte[] key) + throws InvalidProtocolBufferException, BadItemException, ItemNotFoundException { + return get(key); + } + public T getUnchecked(byte[] key) { return null; } diff --git a/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java b/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java index d6ff34e4d1e..c3425926379 100644 --- a/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java +++ b/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java @@ -148,6 +148,12 @@ public T getUnchecked(byte[] key) { } } + @Override + public T getFromRoot(byte[] key) throws ItemNotFoundException, BadItemException{ + return of(revokingDB.getFromRoot(key)) ; + + } + public T of(byte[] value) throws BadItemException { try { Constructor constructor = token.getRawType().getConstructor(byte[].class); diff --git a/chainbase/src/main/java/org/tron/core/db2/common/IRevokingDB.java b/chainbase/src/main/java/org/tron/core/db2/common/IRevokingDB.java index 445972417df..f1c777e50ed 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/IRevokingDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/IRevokingDB.java @@ -17,6 +17,8 @@ public interface IRevokingDB extends Iterable> { byte[] get(byte[] key) throws ItemNotFoundException; + byte[] getFromRoot(byte[] key) throws ItemNotFoundException; + byte[] getUnchecked(byte[] key); void close(); diff --git a/chainbase/src/main/java/org/tron/core/db2/core/Chainbase.java b/chainbase/src/main/java/org/tron/core/db2/core/Chainbase.java index ee77c6cbc1b..9361bdafb05 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/Chainbase.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/Chainbase.java @@ -137,6 +137,15 @@ public byte[] get(byte[] key) throws ItemNotFoundException { return value; } + @Override + public byte[] getFromRoot(byte[] key) throws ItemNotFoundException { + byte[] value = head().getRoot().get(key); + if (value == null) { + throw new ItemNotFoundException(); + } + return value; + } + @Override public byte[] getUnchecked(byte[] key) { return head().get(key); diff --git a/chainbase/src/main/java/org/tron/core/db2/core/ITronChainBase.java b/chainbase/src/main/java/org/tron/core/db2/core/ITronChainBase.java index 9baf647c989..e62c0520ac8 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/ITronChainBase.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/ITronChainBase.java @@ -24,6 +24,9 @@ public interface ITronChainBase extends Iterable>, Quitable T get(byte[] key) throws InvalidProtocolBufferException, ItemNotFoundException, BadItemException; + T getFromRoot(byte[] key) throws InvalidProtocolBufferException, ItemNotFoundException, + BadItemException; + T getUnchecked(byte[] key); boolean has(byte[] key); diff --git a/chainbase/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingOldValue.java b/chainbase/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingOldValue.java index 89dd75597af..d9f2cd5630e 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingOldValue.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingOldValue.java @@ -92,6 +92,11 @@ public byte[] get(byte[] key) throws ItemNotFoundException { return value; } + @Override + public byte[] getFromRoot(byte[] key) throws ItemNotFoundException { + return get(key); + } + @Override public byte[] getUnchecked(byte[] key) { try { diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 907d44a85aa..fd4354b96f0 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -17,6 +17,8 @@ import org.tron.core.config.Parameter; import org.tron.core.config.Parameter.ChainConstant; import org.tron.core.db.TronStoreWithRevoking; +import org.tron.core.exception.BadItemException; +import org.tron.core.exception.ItemNotFoundException; @Slf4j(topic = "DB") @Component @@ -1983,6 +1985,19 @@ public long getLatestBlockHeaderNumber() { () -> new IllegalArgumentException("not found latest block header number")); } + public long getLatestBlockHeaderNumberFromDB() { + try { + return Optional.ofNullable(getFromRoot(LATEST_BLOCK_HEADER_NUMBER)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException("not found latest block header number")); + } catch (ItemNotFoundException | BadItemException e) { + logger.error("{}", e); + } + return -1; + } + public int getStateFlag() { return Optional.ofNullable(getUnchecked(STATE_FLAG)) .map(BytesCapsule::getData) diff --git a/common/build.gradle b/common/build.gradle index c66a26f36e1..f270932b839 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -45,6 +45,8 @@ dependencies { compile group: 'com.typesafe', name: 'config', version: '1.3.2' compile group: leveldbGroup, name: leveldbName, version: leveldbVersion compile group: 'org.rocksdb', name: 'rocksdbjni', version: '5.15.10' + // https://mvnrepository.com/artifact/org.quartz-scheduler/quartz + compile group: 'org.quartz-scheduler', name: 'quartz', version: '2.3.2' compile project(":protocol") } diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index f105eb6402d..716d8f725e2 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -6,6 +6,7 @@ import java.util.Set; import lombok.Getter; import lombok.Setter; +import org.quartz.CronExpression; import org.tron.common.args.GenesisBlock; import org.tron.common.config.DbBackupConfig; import org.tron.common.logsfilter.EventPluginConfig; @@ -512,6 +513,18 @@ public class CommonParameter { @Setter public List disabledApiList; + @Getter + @Setter + public CronExpression shutdownBlockTime = null; + + @Getter + @Setter + public long shutdownBlockHeight = -1; + + @Getter + @Setter + public long shutdownBlockCount = -1; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index e542a12491e..2569506bc48 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -295,4 +295,8 @@ public class Constant { public static final String ALLOW_ACCOUNT_ASSET_OPTIMIZATION = "committee.allowAccountAssetOptimization"; public static final String LOCAL_HOST = "127.0.0.1"; + + public static final String NODE_SHUTDOWN_BLOCK_TIME = "node.shutdown.BlockTime"; + public static final String NODE_SHUTDOWN_BLOCK_HEIGHT = "node.shutdown.BlockHeight"; + public static final String NODE_SHUTDOWN_BLOCK_COUNT = "node.shutdown.BlockCount"; } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 7fcad9b75c1..1dd86345cf5 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -19,6 +19,7 @@ import java.net.Socket; import java.net.URL; import java.nio.file.Paths; +import java.text.ParseException; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -34,6 +35,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.quartz.CronExpression; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.common.args.Account; @@ -77,14 +79,15 @@ public class Args extends CommonParameter { @Autowired(required = false) @Getter - private static ConcurrentHashMap> + private static final ConcurrentHashMap> solidityContractLogTriggerMap = new ConcurrentHashMap<>(); @Autowired(required = false) @Getter - private static ConcurrentHashMap> + private static final ConcurrentHashMap> solidityContractEventTriggerMap = new ConcurrentHashMap<>(); + public static void clearParam() { PARAMETER.outputDirectory = "output-directory"; PARAMETER.help = false; @@ -198,6 +201,10 @@ public static void clearParam() { PARAMETER.openTransactionSort = false; PARAMETER.allowAccountAssetOptimization = 0; PARAMETER.disabledApiList = Collections.emptyList(); + PARAMETER.shutdownBlockTime = null; + PARAMETER.shutdownBlockHeight = -1; + PARAMETER.shutdownBlockCount = -1; + } /** @@ -341,7 +348,7 @@ public static void setParam(final String[] args, final String confFileName) { .filter(StringUtils::isNotEmpty) .orElse(Storage.getDbEngineFromConfig(config))); - if (Constant.ROCKSDB.equals(PARAMETER.storage.getDbEngine().toUpperCase()) + if (Constant.ROCKSDB.equalsIgnoreCase(PARAMETER.storage.getDbEngine()) && PARAMETER.storage.getDbVersion() == 1) { throw new RuntimeException("db.version = 1 is not supported by ROCKSDB engine."); } @@ -637,9 +644,8 @@ public static void setParam(final String[] args, final String confFileName) { ? config.getLong(Constant.NODE_PENDING_TRANSACTION_TIMEOUT) : 60_000; PARAMETER.needToUpdateAsset = - config.hasPath(Constant.STORAGE_NEEDTO_UPDATE_ASSET) ? config - .getBoolean(Constant.STORAGE_NEEDTO_UPDATE_ASSET) - : true; + !config.hasPath(Constant.STORAGE_NEEDTO_UPDATE_ASSET) || config + .getBoolean(Constant.STORAGE_NEEDTO_UPDATE_ASSET); PARAMETER.trxReferenceBlock = config.hasPath(Constant.TRX_REFERENCE_BLOCK) ? config.getString(Constant.TRX_REFERENCE_BLOCK) : "head"; @@ -653,7 +659,7 @@ public static void setParam(final String[] args, final String confFileName) { ? config.getInt(Constant.NODE_RPC_MIN_EFFECTIVE_CONNECTION) : 1; PARAMETER.trxCacheEnable = config.hasPath(Constant.NODE_RPC_TRX_CACHE_ENABLE) - && config.getBoolean(Constant.NODE_RPC_TRX_CACHE_ENABLE); + && config.getBoolean(Constant.NODE_RPC_TRX_CACHE_ENABLE); PARAMETER.blockNumForEnergyLimit = config.hasPath(Constant.ENERGY_LIMIT_BLOCK_NUM) ? config.getInt(Constant.ENERGY_LIMIT_BLOCK_NUM) : 4727890L; @@ -755,8 +761,8 @@ public static void setParam(final String[] args, final String confFileName) { } PARAMETER.allowTvmFreeze = - config.hasPath(Constant.COMMITTEE_ALLOW_TVM_FREEZE) ? config - .getInt(Constant.COMMITTEE_ALLOW_TVM_FREEZE) : 0; + config.hasPath(Constant.COMMITTEE_ALLOW_TVM_FREEZE) ? config + .getInt(Constant.COMMITTEE_ALLOW_TVM_FREEZE) : 0; PARAMETER.allowTvmVote = config.hasPath(Constant.COMMITTEE_ALLOW_TVM_VOTE) ? config @@ -771,8 +777,8 @@ public static void setParam(final String[] args, final String confFileName) { .getInt(Constant.COMMITTEE_ALLOW_TVM_COMPATIBLE_EVM) : 0; initBackupProperty(config); - if (Constant.ROCKSDB.equals(CommonParameter - .getInstance().getStorage().getDbEngine().toUpperCase())) { + if (Constant.ROCKSDB.equalsIgnoreCase(CommonParameter + .getInstance().getStorage().getDbEngine())) { initRocksDbBackupProperty(config); initRocksDbSettings(config); } @@ -787,21 +793,21 @@ public static void setParam(final String[] args, final String confFileName) { } PARAMETER.metricsStorageEnable = config.hasPath(Constant.METRICS_STORAGE_ENABLE) && config - .getBoolean(Constant.METRICS_STORAGE_ENABLE); + .getBoolean(Constant.METRICS_STORAGE_ENABLE); PARAMETER.influxDbIp = config.hasPath(Constant.METRICS_INFLUXDB_IP) ? config - .getString(Constant.METRICS_INFLUXDB_IP) : Constant.LOCAL_HOST; + .getString(Constant.METRICS_INFLUXDB_IP) : Constant.LOCAL_HOST; PARAMETER.influxDbPort = config.hasPath(Constant.METRICS_INFLUXDB_PORT) ? config - .getInt(Constant.METRICS_INFLUXDB_PORT) : 8086; + .getInt(Constant.METRICS_INFLUXDB_PORT) : 8086; PARAMETER.influxDbDatabase = config.hasPath(Constant.METRICS_INFLUXDB_DATABASE) ? config - .getString(Constant.METRICS_INFLUXDB_DATABASE) : "metrics"; + .getString(Constant.METRICS_INFLUXDB_DATABASE) : "metrics"; PARAMETER.metricsReportInterval = config.hasPath(Constant.METRICS_REPORT_INTERVAL) ? config - .getInt(Constant.METRICS_REPORT_INTERVAL) : 10; + .getInt(Constant.METRICS_REPORT_INTERVAL) : 10; // lite fullnode params PARAMETER.setLiteFullNode(checkIsLiteFullNode()); PARAMETER.setOpenHistoryQueryWhenLiteFN( - config.hasPath(Constant.NODE_OPEN_HISTORY_QUERY_WHEN_LITEFN) - && config.getBoolean(Constant.NODE_OPEN_HISTORY_QUERY_WHEN_LITEFN)); + config.hasPath(Constant.NODE_OPEN_HISTORY_QUERY_WHEN_LITEFN) + && config.getBoolean(Constant.NODE_OPEN_HISTORY_QUERY_WHEN_LITEFN)); PARAMETER.historyBalanceLookup = config.hasPath(Constant.HISTORY_BALANCE_LOOKUP) && config .getBoolean(Constant.HISTORY_BALANCE_LOOKUP); @@ -814,8 +820,8 @@ public static void setParam(final String[] args, final String confFileName) { .getBoolean(Constant.OPEN_TRANSACTION_SORT); PARAMETER.allowAccountAssetOptimization = config - .hasPath(Constant.ALLOW_ACCOUNT_ASSET_OPTIMIZATION) ? config - .getInt(Constant.ALLOW_ACCOUNT_ASSET_OPTIMIZATION) : 0; + .hasPath(Constant.ALLOW_ACCOUNT_ASSET_OPTIMIZATION) ? config + .getInt(Constant.ALLOW_ACCOUNT_ASSET_OPTIMIZATION) : 0; PARAMETER.disabledApiList = config.hasPath(Constant.NODE_DISABLED_API_LIST) @@ -823,6 +829,23 @@ public static void setParam(final String[] args, final String confFileName) { .stream().map(String::toLowerCase).collect(Collectors.toList()) : Collections.emptyList(); + if (config.hasPath(Constant.NODE_SHUTDOWN_BLOCK_TIME)) { + try { + PARAMETER.shutdownBlockTime = new CronExpression(config.getString( + Constant.NODE_SHUTDOWN_BLOCK_TIME)); + } catch (ParseException e) { + logger.error(e.getMessage(), e); + } + } + + if (config.hasPath(Constant.NODE_SHUTDOWN_BLOCK_HEIGHT)) { + PARAMETER.shutdownBlockHeight = config.getLong(Constant.NODE_SHUTDOWN_BLOCK_HEIGHT); + } + + if (config.hasPath(Constant.NODE_SHUTDOWN_BLOCK_COUNT)) { + PARAMETER.shutdownBlockCount = config.getLong(Constant.NODE_SHUTDOWN_BLOCK_COUNT); + } + logConfig(); } @@ -1167,6 +1190,11 @@ public static void logConfig() { logger.info("DB version : {}", parameter.getStorage().getDbVersion()); logger.info("DB engine : {}", parameter.getStorage().getDbEngine()); logger.info("***************************************************************"); + logger.info("************************ shutDown config *************************"); + logger.info("ShutDown blockTime : {}", parameter.getShutdownBlockTime()); + logger.info("ShutDown blockHeight : {}", parameter.getShutdownBlockHeight()); + logger.info("ShutDown blockCount : {}", parameter.getShutdownBlockCount()); + logger.info("***************************************************************"); logger.info("\n"); } @@ -1179,7 +1207,7 @@ public static void setFullNodeAllowShieldedTransaction(boolean fullNodeAllowShie */ public static boolean checkIsLiteFullNode() { String infoFile = Paths.get(PARAMETER.outputDirectory, - PARAMETER.storage.getDbDirectory(), Constant.INFO_FILE_NAME).toString(); + PARAMETER.storage.getDbDirectory(), Constant.INFO_FILE_NAME).toString(); if (FileUtil.isExists(infoFile)) { String value = PropUtil.readProperty(infoFile, Constant.SPLIT_BLOCK_NUM); return !"".equals(value) && Long.parseLong(value) > 0; @@ -1187,20 +1215,10 @@ public static boolean checkIsLiteFullNode() { return false; } - /** - * get output directory. - */ - public String getOutputDirectory() { - if (!this.outputDirectory.equals("") && !this.outputDirectory.endsWith(File.separator)) { - return this.outputDirectory + File.separator; - } - return this.outputDirectory; - } - private static void witnessAddressCheck(Config config) { if (config.hasPath(Constant.LOCAL_WITNESS_ACCOUNT_ADDRESS)) { byte[] bytes = Commons - .decodeFromBase58Check(config.getString(Constant.LOCAL_WITNESS_ACCOUNT_ADDRESS)); + .decodeFromBase58Check(config.getString(Constant.LOCAL_WITNESS_ACCOUNT_ADDRESS)); if (bytes != null) { localWitnesses.setWitnessAccountAddress(bytes); logger.debug("Got localWitnessAccountAddress from config.conf"); @@ -1209,5 +1227,15 @@ private static void witnessAddressCheck(Config config) { } } } + + /** + * get output directory. + */ + public String getOutputDirectory() { + if (!this.outputDirectory.equals("") && !this.outputDirectory.endsWith(File.separator)) { + return this.outputDirectory + File.separator; + } + return this.outputDirectory; + } } diff --git a/framework/src/main/java/org/tron/core/consensus/ConsensusService.java b/framework/src/main/java/org/tron/core/consensus/ConsensusService.java index 13239fe4e20..ce1f1f1cf08 100644 --- a/framework/src/main/java/org/tron/core/consensus/ConsensusService.java +++ b/framework/src/main/java/org/tron/core/consensus/ConsensusService.java @@ -85,7 +85,9 @@ public void start() { } public void stop() { + logger.info("consensus service closed start."); consensus.stop(); + logger.info("consensus service closed successfully."); } } diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 54db6c5c290..9475c5b6ad5 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -14,6 +14,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.Date; import java.util.HashSet; import java.util.LinkedList; import java.util.List; @@ -226,6 +227,9 @@ public class Manager { private boolean isRunFilterProcessThread = true; private BlockingQueue filterCapsuleQueue; + @Getter + private volatile long latestSolidityNumShutDown; + /** * Cycle thread to rePush Transactions */ @@ -494,6 +498,22 @@ public void init() { //initActuatorCreator ActuatorCreator.init(); TransactionRegister.registerActuator(); + + + long exitHeight = CommonParameter.getInstance().getShutdownBlockHeight(); + long exitCount = CommonParameter.getInstance().getShutdownBlockCount(); + + if (exitCount > 0 && (exitHeight < 0 || exitHeight > headNum + exitCount)) { + CommonParameter.getInstance().setShutdownBlockHeight(headNum + exitCount); + } + + if (CommonParameter.getInstance().getShutdownBlockHeight() < headNum) { + logger.info("ShutDownBlockHeight {} is less than headNum {},ignored.", + CommonParameter.getInstance().getShutdownBlockHeight(), headNum); + CommonParameter.getInstance().setShutdownBlockHeight(-1); + } + // init + latestSolidityNumShutDown = CommonParameter.getInstance().getShutdownBlockHeight(); } /** @@ -842,6 +862,17 @@ private void applyBlock(BlockCapsule block, List txs) updateFork(block); if (System.currentTimeMillis() - block.getTimeStamp() >= 60_000) { revokingStore.setMaxFlushCount(SnapshotManager.DEFAULT_MAX_FLUSH_COUNT); + if (Args.getInstance().getShutdownBlockTime() != null) { + if (Args.getInstance().getShutdownBlockTime().getNextValidTimeAfter( + new Date(block.getTimeStamp() - SnapshotManager.DEFAULT_MAX_FLUSH_COUNT * 1000 * 3)) + .compareTo(new Date(block.getTimeStamp())) <= 0) { + revokingStore.setMaxFlushCount(SnapshotManager.DEFAULT_MIN_FLUSH_COUNT); + } + } + if (latestSolidityNumShutDown > 0 && latestSolidityNumShutDown - block.getNum() + <= SnapshotManager.DEFAULT_MAX_FLUSH_COUNT) { + revokingStore.setMaxFlushCount(SnapshotManager.DEFAULT_MIN_FLUSH_COUNT); + } } else { revokingStore.setMaxFlushCount(SnapshotManager.DEFAULT_MIN_FLUSH_COUNT); } @@ -1004,6 +1035,14 @@ public synchronized void pushBlock(final BlockCapsule block) + "block-tx-size: {}, verify-tx-size: {}", block.getNum(), rePushTransactions.size(), pendingTransactions.size(), block.getTransactions().size(), txs.size()); + + if (CommonParameter.getInstance().getShutdownBlockTime() != null + && CommonParameter.getInstance().getShutdownBlockTime() + .isSatisfiedBy(new Date(block.getTimeStamp()))) { + latestSolidityNumShutDown = block.getNum(); + CommonParameter.getInstance().setShutdownBlockTime(null); + } + try (PendingManager pm = new PendingManager(this)) { if (!block.generatedByMyself) { diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index 4fb65a33462..a8c02d5b90f 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -6,6 +6,8 @@ import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.locks.LockSupport; +import javax.annotation.PostConstruct; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; @@ -88,6 +90,25 @@ public class TronNetDelegate { private long timeout = 1000; + private volatile boolean hitDown = false; + + private Thread hitThread; + + @PostConstruct + public void init() { + hitThread = new Thread(() -> { + LockSupport.park(); + // to Guarantee Some other thread invokes unpark with the current thread as the target + if (hitDown) { + System.exit(0); + } + }); + hitThread.setName("hit-thread"); + hitThread.start(); + } + + + private Queue freshBlockId = new ConcurrentLinkedQueue() { @Override public boolean offer(BlockId blockId) { @@ -192,6 +213,21 @@ public Message getData(Sha256Hash hash, InventoryType type) throws P2pException } public void processBlock(BlockCapsule block, boolean isSync) throws P2pException { + if (!hitDown && dbManager.getLatestSolidityNumShutDown() > 0 + && dbManager.getLatestSolidityNumShutDown() == dbManager.getDynamicPropertiesStore() + .getLatestBlockHeaderNumberFromDB()) { + + logger.info("begin shutdown, currentBlockNum:{}, DbBlockNum:{} ,solidifiedBlockNum:{}.", + dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber(), + dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumberFromDB(), + dbManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum()); + hitDown = true; + LockSupport.unpark(hitThread); + return; + } + if (hitDown) { + return; + } BlockId blockId = block.getBlockId(); synchronized (blockLock) { try { diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 0244051ccb3..626f54115e7 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -71,6 +71,7 @@ public void start() { } public void stop() { + logger.info("TronNetService closed start."); channelManager.close(); advService.close(); syncService.close(); From 6098c03419f8b09e81f9d265c0e3f5106cb3bd43 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 15 Mar 2022 18:44:43 +0800 Subject: [PATCH 0015/1197] test(block): add test case --- .../org/tron/core/net/TronNetDelegate.java | 9 +- .../services/stop/BlockHeightStopTest.java | 29 +++++++ .../services/stop/BlockSyncCountStopTest.java | 30 +++++++ .../core/services/stop/BlockTimeStopTest.java | 54 ++++++++++++ .../services/stop/ConditionallyStopTest.java | 86 +++++++++++++++++++ 5 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java create mode 100644 framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java create mode 100644 framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java create mode 100644 framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index a8c02d5b90f..77b1bd90772 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -9,6 +9,7 @@ import java.util.concurrent.locks.LockSupport; import javax.annotation.PostConstruct; import lombok.Getter; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; @@ -67,6 +68,7 @@ public class TronNetDelegate { private ChannelManager channelManager; @Autowired + @Getter // for test private Manager dbManager; @Autowired @@ -90,16 +92,21 @@ public class TronNetDelegate { private long timeout = 1000; + @Getter // for test private volatile boolean hitDown = false; private Thread hitThread; + // for Test + @Setter + private volatile boolean test = false; + @PostConstruct public void init() { hitThread = new Thread(() -> { LockSupport.park(); // to Guarantee Some other thread invokes unpark with the current thread as the target - if (hitDown) { + if (hitDown && !test) { System.exit(0); } }); diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java new file mode 100644 index 00000000000..23dba810545 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java @@ -0,0 +1,29 @@ +package org.tron.core.services.stop; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.tron.common.parameter.CommonParameter; + +@Slf4j +public class BlockHeightStopTest extends ConditionallyStopTest { + + private static final long height = 64; + + protected void initParameter(CommonParameter parameter) { + parameter.setShutdownBlockHeight(height); + // will ignore + parameter.setShutdownBlockCount(128); + } + + @Override + protected void check() { + Assert.assertEquals(height, tronNetDelegate.getDbManager().getDynamicPropertiesStore() + .getLatestBlockHeaderNumberFromDB()); + } + + @Override + protected void initDbPath() { + dbPath = "output-height-stop"; + } + +} diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java new file mode 100644 index 00000000000..e2877813bbb --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java @@ -0,0 +1,30 @@ +package org.tron.core.services.stop; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.tron.common.parameter.CommonParameter; + +@Slf4j +public class BlockSyncCountStopTest extends ConditionallyStopTest { + + private static final long sync = 512; + + protected void initParameter(CommonParameter parameter) { + parameter.setShutdownBlockCount(sync); + // will ignore + parameter.setShutdownBlockHeight(1024); + } + + @Override + protected void check() { + + Assert.assertEquals(sync + currentHeader, tronNetDelegate.getDbManager() + .getDynamicPropertiesStore().getLatestBlockHeaderNumberFromDB()); + } + + @Override + protected void initDbPath() { + dbPath = "output-sync-stop"; + } + +} diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java new file mode 100644 index 00000000000..3a84a337edd --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java @@ -0,0 +1,54 @@ +package org.tron.core.services.stop; + +import java.text.ParseException; +import java.util.Date; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.quartz.CronExpression; +import org.tron.common.parameter.CommonParameter; +import org.tron.core.exception.P2pException; + +@Slf4j +public class BlockTimeStopTest extends ConditionallyStopTest { + + // @see https://tronscan.org/#/block/12 + private static final String time = "00 52 09 25 06 ? 2018"; + + private static CronExpression cronExpression; + + + static { + try { + cronExpression = new CronExpression(time); + } catch (ParseException e) { + logger.error("{}", e.getMessage()); + } + } + + + protected void initParameter(CommonParameter parameter) { + parameter.setShutdownBlockTime(cronExpression); + // will ignore + parameter.setShutdownBlockHeight(48); + // will ignore + parameter.setShutdownBlockCount(32); + } + + @Override + protected void check() { + try { + long height = tronNetDelegate.getDbManager() + .getDynamicPropertiesStore().getLatestBlockHeaderNumberFromDB(); + Assert.assertTrue(cronExpression.isSatisfiedBy(new Date(tronNetDelegate + .getBlockTime(tronNetDelegate.getBlockIdByNum(height))))); + } catch (P2pException e) { + logger.error("{}", e.getMessage()); + } + } + + @Override + protected void initDbPath() { + dbPath = "output-time-stop"; + } + +} diff --git a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java new file mode 100644 index 00000000000..5b0bb659197 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java @@ -0,0 +1,86 @@ +package org.tron.core.services.stop; + +import java.io.File; +import java.util.Collection; +import lombok.extern.slf4j.Slf4j; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.application.Application; +import org.tron.common.application.ApplicationFactory; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.ReflectUtils; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.peer.PeerConnection; + +@Slf4j +public abstract class ConditionallyStopTest { + + + protected String dbPath; + protected TronNetDelegate tronNetDelegate; + protected long currentHeader = -1; + private TronApplicationContext context; + + protected abstract void initParameter(CommonParameter parameter); + + protected abstract void check(); + + protected abstract void initDbPath(); + + + @Before + public void init() throws Exception { + + initDbPath(); + FileUtil.deleteDir(new File(dbPath)); + logger.info("Full node running."); + Args.setParam( + new String[] { + "--output-directory", dbPath, + "--storage-db-directory", "database", + "--storage-index-directory", "index" + }, + "config.conf" + ); + CommonParameter parameter = Args.getInstance(); + parameter.setNodeListenPort(10000); + initParameter(parameter); + context = new TronApplicationContext(DefaultConfig.class); + Application appT = ApplicationFactory.create(context); + appT.initServices(parameter); + appT.startServices(); + appT.startup(); + tronNetDelegate = context.getBean(TronNetDelegate.class); + tronNetDelegate.setTest(true); + currentHeader = tronNetDelegate.getDbManager().getDynamicPropertiesStore() + .getLatestBlockHeaderNumberFromDB(); + } + + @After + public void destroy() { + Args.clearParam(); + Collection peerConnections = ReflectUtils + .invokeMethod(tronNetDelegate, "getActivePeer"); + for (PeerConnection peer : peerConnections) { + peer.close(); + } + context.destroy(); + FileUtil.deleteDir(new File(dbPath)); + } + + @Test + public void testStop() throws InterruptedException { + while (!tronNetDelegate.isHitDown()) { + Thread.sleep(1); + } + Assert.assertTrue(tronNetDelegate.isHitDown()); + check(); + } + +} From b31b0dd5c23d50732a382033d68cb97122e81b3c Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Sat, 19 Mar 2022 22:36:33 +0800 Subject: [PATCH 0016/1197] fix(*): sonar style and remove setShutdownBlockTime(null) for reset MaxFlushCount --- framework/src/main/java/org/tron/core/db/Manager.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 9475c5b6ad5..811a045e1d6 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -862,12 +862,11 @@ private void applyBlock(BlockCapsule block, List txs) updateFork(block); if (System.currentTimeMillis() - block.getTimeStamp() >= 60_000) { revokingStore.setMaxFlushCount(SnapshotManager.DEFAULT_MAX_FLUSH_COUNT); - if (Args.getInstance().getShutdownBlockTime() != null) { - if (Args.getInstance().getShutdownBlockTime().getNextValidTimeAfter( + if (Args.getInstance().getShutdownBlockTime() != null + && Args.getInstance().getShutdownBlockTime().getNextValidTimeAfter( new Date(block.getTimeStamp() - SnapshotManager.DEFAULT_MAX_FLUSH_COUNT * 1000 * 3)) .compareTo(new Date(block.getTimeStamp())) <= 0) { revokingStore.setMaxFlushCount(SnapshotManager.DEFAULT_MIN_FLUSH_COUNT); - } } if (latestSolidityNumShutDown > 0 && latestSolidityNumShutDown - block.getNum() <= SnapshotManager.DEFAULT_MAX_FLUSH_COUNT) { @@ -1040,7 +1039,6 @@ public synchronized void pushBlock(final BlockCapsule block) && CommonParameter.getInstance().getShutdownBlockTime() .isSatisfiedBy(new Date(block.getTimeStamp()))) { latestSolidityNumShutDown = block.getNum(); - CommonParameter.getInstance().setShutdownBlockTime(null); } try (PendingManager pm = new PendingManager(this)) { From 7d70dc4dbe4d34ee3f74876e111941168fc28652 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 21 Mar 2022 11:00:26 +0800 Subject: [PATCH 0017/1197] style(*): fix sonar check style --- framework/src/main/java/org/tron/core/db/Manager.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 811a045e1d6..a5f4d8899e2 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -863,10 +863,10 @@ private void applyBlock(BlockCapsule block, List txs) if (System.currentTimeMillis() - block.getTimeStamp() >= 60_000) { revokingStore.setMaxFlushCount(SnapshotManager.DEFAULT_MAX_FLUSH_COUNT); if (Args.getInstance().getShutdownBlockTime() != null - && Args.getInstance().getShutdownBlockTime().getNextValidTimeAfter( - new Date(block.getTimeStamp() - SnapshotManager.DEFAULT_MAX_FLUSH_COUNT * 1000 * 3)) - .compareTo(new Date(block.getTimeStamp())) <= 0) { - revokingStore.setMaxFlushCount(SnapshotManager.DEFAULT_MIN_FLUSH_COUNT); + && Args.getInstance().getShutdownBlockTime().getNextValidTimeAfter( + new Date(block.getTimeStamp() - SnapshotManager.DEFAULT_MAX_FLUSH_COUNT * 1000 * 3)) + .compareTo(new Date(block.getTimeStamp())) <= 0) { + revokingStore.setMaxFlushCount(SnapshotManager.DEFAULT_MIN_FLUSH_COUNT); } if (latestSolidityNumShutDown > 0 && latestSolidityNumShutDown - block.getNum() <= SnapshotManager.DEFAULT_MAX_FLUSH_COUNT) { From 6575c2a46a633728f31abf1d621cb0988bd47053 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 21 Mar 2022 11:55:35 +0800 Subject: [PATCH 0018/1197] perf(net): solve sonar problem and add DB test --- .../java/org/tron/core/db/CommonStore.java | 32 ++++++++++ .../src/main/java/org/tron/core/Constant.java | 3 + .../common/overlay/message/HelloMessage.java | 12 ++-- .../overlay/server/HandshakeHandler.java | 6 -- .../tool/litefullnode/LiteFullNodeTool.java | 8 ++- .../org/tron/core/db/CommonStoreTest.java | 59 +++++++++++++++++++ 6 files changed, 103 insertions(+), 17 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/db/CommonStoreTest.java diff --git a/chainbase/src/main/java/org/tron/core/db/CommonStore.java b/chainbase/src/main/java/org/tron/core/db/CommonStore.java index acc137bdb2a..a22406f5f90 100644 --- a/chainbase/src/main/java/org/tron/core/db/CommonStore.java +++ b/chainbase/src/main/java/org/tron/core/db/CommonStore.java @@ -3,11 +3,16 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; +import org.tron.common.utils.ByteArray; +import org.tron.core.Constant; import org.tron.core.capsule.BytesCapsule; @Component public class CommonStore extends TronDatabase { + private static final byte[] DB_KEY_LOWEST_BLOCK_NUM = "lowest_block_num".getBytes(); + private static final byte[] DB_KEY_NODE_TYPE = "node_type".getBytes(); + @Autowired public CommonStore(ApplicationContext ctx) { super("common"); @@ -32,4 +37,31 @@ public BytesCapsule get(byte[] key) { public boolean has(byte[] key) { return dbSource.getData(key) != null; } + + public int getNodeType() { + int nodeType = 0; + byte[] bytes = get(DB_KEY_NODE_TYPE).getData(); + if (bytes != null) { + nodeType = ByteArray.toInt(bytes); + } + return nodeType; + } + + public void setNodeType(int nodeType) { + put(DB_KEY_NODE_TYPE, new BytesCapsule(ByteArray.fromInt(nodeType))); + } + + public long getLowestBlockNum() { + long lowestBlockNum = 0; + byte[] bytes = get(DB_KEY_LOWEST_BLOCK_NUM).getData(); + if (bytes != null) { + lowestBlockNum = ByteArray.toLong(bytes); + } + return lowestBlockNum; + } + + public void setLowestBlockNum(long lowestBlockNum) { + put(DB_KEY_LOWEST_BLOCK_NUM, new BytesCapsule(ByteArray.fromLong(lowestBlockNum))); + } + } diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index e542a12491e..732a3b8d302 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -19,6 +19,9 @@ public class Constant { public static final byte ADD_PRE_FIX_BYTE_TESTNET = (byte) 0xa0; //a0 + address public static final String ADD_PRE_FIX_STRING_TESTNET = "a0"; + public static final int NODE_TYPE_FULL_NODE = 0; + public static final int NODE_TYPE_LIGHT_NODE = 1; + // config for transaction public static final long TRANSACTION_MAX_BYTE_SIZE = 500 * 1_024L; public static final long MAXIMUM_TIME_UNTIL_EXPIRATION = 24 * 60 * 60 * 1_000L; //one day diff --git a/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java b/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java index b01d2dca534..3609cc0949a 100755 --- a/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java +++ b/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java @@ -6,6 +6,7 @@ import org.tron.common.overlay.server.HandshakeHandler; import org.tron.common.utils.ByteArray; import org.tron.core.ChainBaseManager; +import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; import org.tron.core.config.args.Args; import org.tron.core.db.CommonStore; @@ -51,15 +52,10 @@ public HelloMessage(Node from, long timestamp, ChainBaseManager chainBaseManager .build(); CommonStore commonStore = chainBaseManager.getCommonStore(); - int nodeType = HandshakeHandler.NODE_TYPE_FULL_NODE; - byte[] c1 = commonStore.get(HandshakeHandler.DB_KEY_NODE_TYPE).getData(); - if (c1 != null) { - nodeType = ByteArray.toInt(c1); - } long lowestBlockNum = 0; - if (nodeType == HandshakeHandler.NODE_TYPE_LIGHT_NODE) { - byte[] c2 = commonStore.get(HandshakeHandler.DB_KEY_LOWEST_BLOCK_NUM).getData(); - lowestBlockNum = ByteArray.toLong(c2); + int nodeType = commonStore.getNodeType(); + if (nodeType == Constant.NODE_TYPE_LIGHT_NODE) { + lowestBlockNum = commonStore.getLowestBlockNum(); } Builder builder = Protocol.HelloMessage.newBuilder(); diff --git a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java index dd1c5be0921..45ef735797e 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java @@ -72,12 +72,6 @@ public class HandshakeHandler extends ByteToMessageDecoder { @Autowired private SyncPool syncPool; - public static final byte[] DB_KEY_LOWEST_BLOCK_NUM = "lowest_block_num".getBytes(); - public static final byte[] DB_KEY_NODE_TYPE = "node_type".getBytes(); - - public static int NODE_TYPE_FULL_NODE = 0; - public static int NODE_TYPE_LIGHT_NODE = 1; - @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { logger.info("channel active, {}", ctx.channel().remoteAddress()); diff --git a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java index 370744ee702..51b185a432e 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java @@ -38,6 +38,9 @@ @Slf4j(topic = "tool") public class LiteFullNodeTool { + private static final byte[] DB_KEY_LOWEST_BLOCK_NUM = "lowest_block_num".getBytes(); + private static final byte[] DB_KEY_NODE_TYPE = "node_type".getBytes(); + private static final long START_TIME = System.currentTimeMillis() / 1000; private static final String SNAPSHOT_DIR_NAME = "snapshot"; @@ -305,9 +308,8 @@ private void fillSnapshotBlockDb(String sourceDir, String snapshotDir) }); DBInterface commonDb = DbTool.getDB(sourceDir, COMMON_DB_NAME); - commonDb.put(HandshakeHandler.DB_KEY_NODE_TYPE, - ByteArray.fromInt(HandshakeHandler.NODE_TYPE_LIGHT_NODE)); - commonDb.put(HandshakeHandler.DB_KEY_LOWEST_BLOCK_NUM, ByteArray.fromLong(startIndex)); + commonDb.put(DB_KEY_NODE_TYPE, ByteArray.fromInt(Constant.NODE_TYPE_LIGHT_NODE)); + commonDb.put(DB_KEY_LOWEST_BLOCK_NUM, ByteArray.fromLong(startIndex)); } private void checkTranCacheStore(String sourceDir, String snapshotDir) diff --git a/framework/src/test/java/org/tron/core/db/CommonStoreTest.java b/framework/src/test/java/org/tron/core/db/CommonStoreTest.java new file mode 100644 index 00000000000..2c28047fd55 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/CommonStoreTest.java @@ -0,0 +1,59 @@ +package org.tron.core.db; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.FileUtil; +import org.tron.core.Constant; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; + +import java.io.File; + +public class CommonStoreTest { + private static String dbPath = "output_CommonStore_test"; + private static String dbDirectory = "db_CommonStore_test"; + private static String indexDirectory = "index_CommonStore_test"; + private static TronApplicationContext context; + private static CommonStore commonStore; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath, + "--storage-db-directory", dbDirectory, + "--storage-index-directory", indexDirectory + }, + Constant.TEST_CONF + ); + context = new TronApplicationContext(DefaultConfig.class); + } + + @AfterClass + public static void destroy() { + Args.clearParam(); + context.destroy(); + FileUtil.deleteDir(new File(dbPath)); + } + + @BeforeClass + public static void init() { + commonStore = context.getBean(CommonStore.class); + } + + @Test + public void nodeTypeTest() { + Assert.assertEquals(0, commonStore.getNodeType()); + commonStore.setNodeType(1); + Assert.assertEquals(1, commonStore.getNodeType()); + } + + @Test + public void lowestBlockNumTest() { + Assert.assertEquals(0, commonStore.getLowestBlockNum()); + commonStore.setLowestBlockNum(100); + Assert.assertEquals(100, commonStore.getLowestBlockNum()); + } +} From 8c1ad4bccb1cbf31806353a7ba574d8729aacf3e Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 21 Mar 2022 12:20:02 +0800 Subject: [PATCH 0019/1197] perf(net): solve sonar and check style problem --- .../common/overlay/server/HandshakeHandler.java | 11 +++++------ .../java/org/tron/core/db/CommonStoreTest.java | 15 ++++++--------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java index 45ef735797e..ff33175425e 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java @@ -139,12 +139,11 @@ private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { } InetAddress address = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress(); - if (remoteId.length != 64) { - if (channelManager.getTrustNodes().getIfPresent(address) == null && !syncPool - .isCanConnect()) { - channel.disconnect(ReasonCode.TOO_MANY_PEERS); - return; - } + if (remoteId.length != 64 + && channelManager.getTrustNodes().getIfPresent(address) == null + && !syncPool.isCanConnect()) { + channel.disconnect(ReasonCode.TOO_MANY_PEERS); + return; } long headBlockNum = chainBaseManager.getHeadBlockNum(); diff --git a/framework/src/test/java/org/tron/core/db/CommonStoreTest.java b/framework/src/test/java/org/tron/core/db/CommonStoreTest.java index 2c28047fd55..9304be0665e 100644 --- a/framework/src/test/java/org/tron/core/db/CommonStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/CommonStoreTest.java @@ -1,5 +1,6 @@ package org.tron.core.db; +import java.io.File; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -10,8 +11,6 @@ import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import java.io.File; - public class CommonStoreTest { private static String dbPath = "output_CommonStore_test"; private static String dbDirectory = "db_CommonStore_test"; @@ -20,13 +19,11 @@ public class CommonStoreTest { private static CommonStore commonStore; static { - Args.setParam( - new String[]{ - "--output-directory", dbPath, - "--storage-db-directory", dbDirectory, - "--storage-index-directory", indexDirectory - }, - Constant.TEST_CONF + Args.setParam(new String[] { + "--output-directory", dbPath, + "--storage-db-directory", dbDirectory, + "--storage-index-directory", indexDirectory}, + Constant.TEST_CONF ); context = new TronApplicationContext(DefaultConfig.class); } From 044111d8079fc35f1f0250cbae265d496f866b00 Mon Sep 17 00:00:00 2001 From: liukai Date: Tue, 22 Mar 2022 10:16:38 +0800 Subject: [PATCH 0020/1197] feat: modify example 1. modify the example path --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a8e28121d3b..b2a699b4451 100644 --- a/README.md +++ b/README.md @@ -121,8 +121,8 @@ For more details, please refer to the tool [guide](./shell.md). One of the quickest ways to get `java-tron` up and running on your machine is by using Docker: ```shell $ docker run -d --name="java-tron" \ - -v /Users/tron/output-directory:/java-tron/output-directory \ - -v /Users/tron/logs:/java-tron/logs \ + -v /your_path/output-directory:/java-tron/output-directory \ + -v /your_path/logs:/java-tron/logs \ -p 8090:8090 -p 18888:18888 -p 50051:50051 \ tronprotocol/java-tron \ -c /java-tron/config/main_net_config.conf From b88b86b830a70e402f3fc98b923583e2e3dbd1fe Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 23 Mar 2022 12:10:54 +0800 Subject: [PATCH 0021/1197] config(*): add config example for stop condition --- framework/src/main/resources/config-backup.conf | 7 +++++++ framework/src/main/resources/config-beta.conf | 7 +++++++ framework/src/main/resources/config-localtest.conf | 7 +++++++ framework/src/main/resources/config-test-net.conf | 7 +++++++ framework/src/main/resources/config.conf | 7 +++++++ 5 files changed, 35 insertions(+) diff --git a/framework/src/main/resources/config-backup.conf b/framework/src/main/resources/config-backup.conf index f69431259c0..b4d1b55551b 100644 --- a/framework/src/main/resources/config-backup.conf +++ b/framework/src/main/resources/config-backup.conf @@ -55,6 +55,13 @@ node.discovery = { external.ip = null } +# custom stop condition +#node.shutdown = { +# BlockTime = "54 59 08 * * ?" # if block header time in persistent db matched. +# BlockHeight = 33350800 # if block header height in persistent db matched. +# BlockCount = 12 # block sync count after node start. +#} + node.backup { port = 10001 priority = 8 diff --git a/framework/src/main/resources/config-beta.conf b/framework/src/main/resources/config-beta.conf index c7f241b32d6..278345e6072 100644 --- a/framework/src/main/resources/config-beta.conf +++ b/framework/src/main/resources/config-beta.conf @@ -55,6 +55,13 @@ node.discovery = { external.ip = null } +# custom stop condition +#node.shutdown = { +# BlockTime = "54 59 08 * * ?" # if block header time in persistent db matched. +# BlockHeight = 33350800 # if block header height in persistent db matched. +# BlockCount = 12 # block sync count after node start. +#} + node { # trust node for solidity node trustNode = "47.93.9.236:50051" diff --git a/framework/src/main/resources/config-localtest.conf b/framework/src/main/resources/config-localtest.conf index 5c9eb55e402..442c4be04b3 100644 --- a/framework/src/main/resources/config-localtest.conf +++ b/framework/src/main/resources/config-localtest.conf @@ -61,6 +61,13 @@ node.discovery = { external.ip = null } +# custom stop condition +#node.shutdown = { +# BlockTime = "54 59 08 * * ?" # if block header time in persistent db matched. +# BlockHeight = 33350800 # if block header height in persistent db matched. +# BlockCount = 12 # block sync count after node start. +#} + node.backup { port = 10001 priority = 8 diff --git a/framework/src/main/resources/config-test-net.conf b/framework/src/main/resources/config-test-net.conf index 07b77dbe6ca..167e0a7f8a9 100644 --- a/framework/src/main/resources/config-test-net.conf +++ b/framework/src/main/resources/config-test-net.conf @@ -57,6 +57,13 @@ node.discovery = { external.ip = null } +# custom stop condition +#node.shutdown = { +# BlockTime = "54 59 08 * * ?" # if block header time in persistent db matched. +# BlockHeight = 33350800 # if block header height in persistent db matched. +# BlockCount = 12 # block sync count after node start. +#} + node.backup { port = 10001 priority = 8 diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 46dcb2e375e..3682a26be13 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -83,6 +83,13 @@ node.discovery = { external.ip = null } +# custom stop condition +#node.shutdown = { +# BlockTime = "54 59 08 * * ?" # if block header time in persistent db matched. +# BlockHeight = 33350800 # if block header height in persistent db matched. +# BlockCount = 12 # block sync count after node start. +#} + node.backup { # my priority, each member should use different priority priority = 8 From b99c341717bef713f3782c94cea6e87a80383054 Mon Sep 17 00:00:00 2001 From: hongdexiang <1090664234@qq.com> Date: Thu, 24 Mar 2022 14:46:15 +0800 Subject: [PATCH 0022/1197] change : change lrucachesize default value --- .../src/main/java/org/tron/core/vm/program/Program.java | 4 +++- .../java/org/tron/core/vm/repository/RepositoryImpl.java | 4 +--- .../java/org/tron/common/parameter/CommonParameter.java | 6 +++++- common/src/main/java/org/tron/core/Constant.java | 1 + framework/src/main/java/org/tron/core/config/args/Args.java | 6 +++++- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 5e5b67da3e3..06502abe91f 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -86,7 +86,9 @@ public class Program { private static final String INVALID_TOKEN_ID_MSG = "not valid token id"; private static final String REFUND_ENERGY_FROM_MESSAGE_CALL = "refund energy from message call"; private static final String CALL_PRE_COMPILED = "call pre-compiled"; - private static final LRUMap programPrecompileLRUMap = new LRUMap<>(); + private static final int lruCacheSize = CommonParameter.getInstance().getLruCacheSize(); + private static final LRUMap programPrecompileLRUMap + = new LRUMap<>(lruCacheSize); private long nonce; private byte[] rootTransactionId; private InternalTransaction internalTransaction; diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index ad2774722e0..e9950796640 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -67,9 +67,7 @@ public class RepositoryImpl implements Repository { private static final byte[] TOTAL_NET_WEIGHT = "TOTAL_NET_WEIGHT".getBytes(); private static final byte[] TOTAL_ENERGY_WEIGHT = "TOTAL_ENERGY_WEIGHT".getBytes(); - private static final int lruCacheSize = - CommonParameter.getInstance().lruCacheSize < 1 - ? 100 : CommonParameter.getInstance().lruCacheSize; + private static final int lruCacheSize = CommonParameter.getInstance().getLruCacheSize(); private static final LRUMap contractLruCache = new LRUMap<>(lruCacheSize); private static final LRUMap codeLruCache = new LRUMap<>(lruCacheSize); diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 4c9ad7a06a4..b1a51779b0f 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -50,7 +50,7 @@ public class CommonParameter { @Getter @Setter @Parameter(names = {"--lru-cache-size"}) - public int lruCacheSize = 100; + public int lruCacheSize = 500; @Getter @Setter @Parameter(names = {"--debug"}) @@ -533,4 +533,8 @@ public boolean isECKeyCryptoEngine() { public boolean isJsonRpcFilterEnabled() { return jsonRpcHttpFullNodeEnable || jsonRpcHttpSolidityNodeEnable; } + + public int getLruCacheSize() { + return lruCacheSize < 1 ? 500 : lruCacheSize; + } } diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index e542a12491e..51801bebc32 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -61,6 +61,7 @@ public class Constant { public static final String LOCAL_WITNESS_KEYSTORE = "localwitnesskeystore"; public static final String VM_SUPPORT_CONSTANT = "vm.supportConstant"; public static final String VM_MAX_ENERGY_LIMIT_FOR_CONSTANT = "vm.maxEnergyLimitForConstant"; + public static final String VM_LRU_CACHE_SIZE = "vm.lruCacheSize"; public static final String VM_MIN_TIME_RATIO = "vm.minTimeRatio"; public static final String VM_MAX_TIME_RATIO = "vm.maxTimeRatio"; public static final String VM_LONG_RUNNING_TIME = "vm.longRunningTime"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 7fcad9b75c1..2cb768114cd 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -296,6 +296,10 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.maxEnergyLimitForConstant = max(3_000_000L, configLimit); } + if (config.hasPath(Constant.VM_LRU_CACHE_SIZE)) { + PARAMETER.lruCacheSize = config.getInt(Constant.VM_LRU_CACHE_SIZE); + } + if (config.hasPath(Constant.NODE_HTTP_FULLNODE_ENABLE)) { PARAMETER.fullNodeHttpEnable = config.getBoolean(Constant.NODE_HTTP_FULLNODE_ENABLE); } @@ -1196,7 +1200,7 @@ public String getOutputDirectory() { } return this.outputDirectory; } - + private static void witnessAddressCheck(Config config) { if (config.hasPath(Constant.LOCAL_WITNESS_ACCOUNT_ADDRESS)) { byte[] bytes = Commons From b57ea15e3a314f890263f79ca366cdffb9bd1389 Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 18 Mar 2022 17:50:41 +0800 Subject: [PATCH 0023/1197] perf(tvm): reduce serialization/deserialization for cache in VM Repository --- .../java/org/tron/core/vm/repository/Key.java | 21 - .../core/vm/repository/RepositoryImpl.java | 154 ++-- .../org/tron/core/vm/repository/Type.java | 97 +- .../org/tron/core/vm/repository/Value.java | 249 +----- .../java/org/tron/common/storage/Deposit.java | 119 --- .../org/tron/common/storage/DepositImpl.java | 827 ------------------ .../tron/common/runtime/InheritanceTest.java | 19 +- .../InternalTransactionComplexTest.java | 19 +- .../common/runtime/ProgramResultTest.java | 39 +- .../runtime/RuntimeTransferComplexTest.java | 43 +- .../org/tron/common/runtime/TvmTestUtils.java | 26 +- .../runtime/vm/AllowTvmCompatibleEvmTest.java | 8 +- .../common/runtime/vm/AllowTvmLondonTest.java | 4 +- .../vm/BandWidthRuntimeOutOfTimeTest.java | 3 - ...andWidthRuntimeOutOfTimeWithCheckTest.java | 2 - .../runtime/vm/BandWidthRuntimeTest.java | 5 +- .../vm/BandWidthRuntimeWithCheckTest.java | 6 +- .../tron/common/runtime/vm/BatchSendTest.java | 17 +- .../tron/common/runtime/vm/ChargeTest.java | 13 +- .../tron/common/runtime/vm/Create2Test.java | 2 +- .../runtime/vm/CreateContractSuicideTest.java | 35 +- .../runtime/vm/EnergyWhenAssertStyleTest.java | 13 +- .../vm/EnergyWhenRequireStyleTest.java | 13 +- .../vm/EnergyWhenSendAndTransferTest.java | 23 +- .../vm/EnergyWhenTimeoutStyleTest.java | 13 +- .../common/runtime/vm/ExtCodeHashTest.java | 2 +- .../tron/common/runtime/vm/FreezeTest.java | 14 +- .../vm/InternalTransactionCallTest.java | 45 +- .../common/runtime/vm/IsContractTest.java | 4 +- .../common/runtime/vm/IsSRCandidateTest.java | 2 +- .../tron/common/runtime/vm/IstanbulTest.java | 6 +- .../{DepositTest.java => RepositoryTest.java} | 35 +- .../common/runtime/vm/RewardBalanceTest.java | 2 +- .../tron/common/runtime/vm/StorageTest.java | 254 +++--- .../common/runtime/vm/TimeBenchmarkTest.java | 13 +- .../runtime/vm/TransferFailedEnergyTest.java | 8 +- .../runtime/vm/TransferToAccountTest.java | 16 +- .../common/runtime/vm/TransferTokenTest.java | 20 +- .../tron/common/runtime/vm/VMTestBase.java | 16 +- .../org/tron/common/runtime/vm/VoteTest.java | 14 +- .../core/actuator/TransferActuatorTest.java | 7 +- .../actuator/TransferAssetActuatorTest.java | 7 +- 42 files changed, 518 insertions(+), 1717 deletions(-) delete mode 100644 framework/src/main/java/org/tron/common/storage/Deposit.java delete mode 100644 framework/src/main/java/org/tron/common/storage/DepositImpl.java rename framework/src/test/java/org/tron/common/runtime/vm/{DepositTest.java => RepositoryTest.java} (95%) diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Key.java b/actuator/src/main/java/org/tron/core/vm/repository/Key.java index b23a22f7751..8639b55f4db 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Key.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Key.java @@ -10,10 +10,6 @@ public class Key { */ private byte[] data = new byte[0]; - /** - * - * @param data - */ public Key(byte[] data) { if (data != null && data.length != 0) { this.data = new byte[data.length]; @@ -21,36 +17,19 @@ public Key(byte[] data) { } } - /** - * - * @param key - */ private Key(Key key) { this.data = new byte[key.getData().length]; System.arraycopy(key.getData(), 0, this.data, 0, this.data.length); } - /** - * - * @param data - * @return - */ public static Key create(byte[] data) { return new Key(data); } - /** - * - * @return - */ public Key clone() { return new Key(this); } - /** - * - * @return - */ public byte[] getData() { return data; } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index e9950796640..01d9e84934d 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -27,6 +27,7 @@ import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.capsule.BytesCapsule; +import org.tron.core.capsule.CodeCapsule; import org.tron.core.capsule.ContractCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.VotesCapsule; @@ -56,7 +57,12 @@ import org.tron.core.vm.program.Program.IllegalOperationException; import org.tron.core.vm.program.Storage; import org.tron.protos.Protocol; +import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.AccountType; +import org.tron.protos.Protocol.DelegatedResource; +import org.tron.protos.Protocol.Votes; +import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; +import org.tron.protos.contract.SmartContractOuterClass.SmartContract; @Slf4j(topic = "Repository") public class RepositoryImpl implements Repository { @@ -105,16 +111,16 @@ public class RepositoryImpl implements Repository { private Repository parent = null; - private HashMap accountCache = new HashMap<>(); - private HashMap codeCache = new HashMap<>(); - private HashMap contractCache = new HashMap<>(); - private HashMap storageCache = new HashMap<>(); + private final HashMap> accountCache = new HashMap<>(); + private final HashMap> codeCache = new HashMap<>(); + private final HashMap> contractCache = new HashMap<>(); + private final HashMap storageCache = new HashMap<>(); - private HashMap assetIssueCache = new HashMap<>(); - private HashMap dynamicPropertiesCache = new HashMap<>(); - private HashMap delegatedResourceCache = new HashMap<>(); - private HashMap votesCache = new HashMap<>(); - private HashMap delegationCache = new HashMap<>(); + private final HashMap> assetIssueCache = new HashMap<>(); + private final HashMap> dynamicPropertiesCache = new HashMap<>(); + private final HashMap> delegatedResourceCache = new HashMap<>(); + private final HashMap> votesCache = new HashMap<>(); + private final HashMap> delegationCache = new HashMap<>(); public static void removeLruCache(byte[] address) { Key key = Key.create(address); @@ -176,7 +182,7 @@ public AssetIssueCapsule getAssetIssue(byte[] tokenId) { byte[] tokenIdWithoutLeadingZero = ByteUtil.stripLeadingZeroes(tokenId); Key key = Key.create(tokenIdWithoutLeadingZero); if (assetIssueCache.containsKey(key)) { - return assetIssueCache.get(key).getAssetIssue(); + return new AssetIssueCapsule(assetIssueCache.get(key).getValue()); } AssetIssueCapsule assetIssueCapsule; @@ -188,7 +194,7 @@ public AssetIssueCapsule getAssetIssue(byte[] tokenId) { .get(tokenIdWithoutLeadingZero); } if (assetIssueCapsule != null) { - assetIssueCache.put(key, Value.create(assetIssueCapsule.getData())); + assetIssueCache.put(key, Value.create(assetIssueCapsule)); } return assetIssueCapsule; } @@ -197,7 +203,7 @@ public AssetIssueCapsule getAssetIssue(byte[] tokenId) { public AccountCapsule createAccount(byte[] address, Protocol.AccountType type) { Key key = new Key(address); AccountCapsule account = new AccountCapsule(ByteString.copyFrom(address), type); - accountCache.put(key, new Value(account.getData(), Type.VALUE_TYPE_CREATE)); + accountCache.put(key, Value.create(account, Type.CREATE)); return account; } @@ -208,8 +214,7 @@ public AccountCapsule createAccount(byte[] address, String accountName, AccountCapsule account = new AccountCapsule(ByteString.copyFrom(address), ByteString.copyFromUtf8(accountName), type); - - accountCache.put(key, new Value(account.getData(), Type.VALUE_TYPE_CREATE)); + accountCache.put(key, Value.create(account, Type.CREATE)); return account; } @@ -217,7 +222,7 @@ public AccountCapsule createAccount(byte[] address, String accountName, public AccountCapsule getAccount(byte[] address) { Key key = new Key(address); if (accountCache.containsKey(key)) { - return accountCache.get(key).getAccount(); + return new AccountCapsule(accountCache.get(key).getValue()); } AccountCapsule accountCapsule; @@ -228,7 +233,7 @@ public AccountCapsule getAccount(byte[] address) { } if (accountCapsule != null) { - accountCache.put(key, Value.create(accountCapsule.getData())); + accountCache.put(key, Value.create(accountCapsule)); } return accountCapsule; } @@ -237,7 +242,7 @@ public AccountCapsule getAccount(byte[] address) { public BytesCapsule getDynamicProperty(byte[] word) { Key key = Key.create(word); if (dynamicPropertiesCache.containsKey(key)) { - return dynamicPropertiesCache.get(key).getDynamicProperties(); + return new BytesCapsule(dynamicPropertiesCache.get(key).getValue()); } BytesCapsule bytesCapsule; @@ -262,7 +267,7 @@ public BytesCapsule getDynamicProperty(byte[] word) { public DelegatedResourceCapsule getDelegatedResource(byte[] key) { Key cacheKey = new Key(key); if (delegatedResourceCache.containsKey(cacheKey)) { - return delegatedResourceCache.get(cacheKey).getDelegatedResource(); + return new DelegatedResourceCapsule(delegatedResourceCache.get(cacheKey).getValue()); } DelegatedResourceCapsule delegatedResourceCapsule; @@ -273,7 +278,7 @@ public DelegatedResourceCapsule getDelegatedResource(byte[] key) { } if (delegatedResourceCapsule != null) { - delegatedResourceCache.put(cacheKey, Value.create(delegatedResourceCapsule.getData())); + delegatedResourceCache.put(cacheKey, Value.create(delegatedResourceCapsule)); } return delegatedResourceCapsule; } @@ -282,7 +287,7 @@ public DelegatedResourceCapsule getDelegatedResource(byte[] key) { public VotesCapsule getVotes(byte[] address) { Key cacheKey = new Key(address); if (votesCache.containsKey(cacheKey)) { - return votesCache.get(cacheKey).getVotes(); + return new VotesCapsule(votesCache.get(cacheKey).getValue()); } VotesCapsule votesCapsule; @@ -293,7 +298,7 @@ public VotesCapsule getVotes(byte[] address) { } if (votesCapsule != null) { - votesCache.put(cacheKey, Value.create(votesCapsule.getData())); + votesCache.put(cacheKey, Value.create(votesCapsule)); } return votesCapsule; } @@ -333,7 +338,7 @@ public AccountCapsule getAccountVote(long cycle, byte[] address) { @Override public BytesCapsule getDelegation(Key key) { if (delegationCache.containsKey(key)) { - return delegationCache.get(key).getBytes(); + return new BytesCapsule(delegationCache.get(key).getValue()); } BytesCapsule bytesCapsule; if (parent != null) { @@ -357,9 +362,8 @@ public void deleteContract(byte[] address) { @Override public void createContract(byte[] address, ContractCapsule contractCapsule) { - Key key = Key.create(address); - Value value = Value.create(contractCapsule.getData(), Type.VALUE_TYPE_CREATE); - contractCache.put(key, value); + contractCache.put(Key.create(address), + Value.create(contractCapsule, Type.CREATE)); } @Override @@ -370,7 +374,7 @@ public ContractCapsule getContract(byte[] address) { } if (contractCache.containsKey(key)) { - return contractCache.get(key).getContract(); + return new ContractCapsule(contractCache.get(key).getValue()); } ContractCapsule contractCapsule; @@ -391,43 +395,38 @@ public ContractCapsule getContract(byte[] address) { @Override public void updateContract(byte[] address, ContractCapsule contractCapsule) { - Key key = Key.create(address); - Value value = Value.create(contractCapsule.getData(), Type.VALUE_TYPE_DIRTY); - contractCache.put(key, value); + contractCache.put(Key.create(address), + Value.create(contractCapsule, Type.DIRTY)); } @Override public void updateAccount(byte[] address, AccountCapsule accountCapsule) { - Key key = Key.create(address); - Value value = Value.create(accountCapsule.getData(), Type.VALUE_TYPE_DIRTY); - accountCache.put(key, value); + accountCache.put(Key.create(address), + Value.create(accountCapsule, Type.DIRTY)); } @Override public void updateDynamicProperty(byte[] word, BytesCapsule bytesCapsule) { - Key key = Key.create(word); - Value value = Value.create(bytesCapsule.getData(), Type.VALUE_TYPE_DIRTY); - dynamicPropertiesCache.put(key, value); + dynamicPropertiesCache.put(Key.create(word), + Value.create(bytesCapsule.getData(), Type.DIRTY)); } @Override - public void updateDelegatedResource(byte[] word, DelegatedResourceCapsule delegatedResourceCapsule) { - Key key = Key.create(word); - Value value = Value.create(delegatedResourceCapsule.getData(), Type.VALUE_TYPE_DIRTY); - delegatedResourceCache.put(key, value); + public void updateDelegatedResource(byte[] word, + DelegatedResourceCapsule delegatedResourceCapsule) { + delegatedResourceCache.put(Key.create(word), + Value.create(delegatedResourceCapsule, Type.DIRTY)); } @Override public void updateVotes(byte[] word, VotesCapsule votesCapsule) { - Key key = Key.create(word); - Value value = Value.create(votesCapsule.getData(), Type.VALUE_TYPE_DIRTY); - votesCache.put(key, value); + votesCache.put(Key.create(word), + Value.create(votesCapsule, Type.DIRTY)); } @Override public void updateBeginCycle(byte[] word, long cycle) { - BytesCapsule bytesCapsule = new BytesCapsule(ByteArray.fromLong(cycle)); - updateDelegation(word, bytesCapsule); + updateDelegation(word, new BytesCapsule(ByteArray.fromLong(cycle))); } @Override @@ -446,16 +445,13 @@ public void updateAccountVote(byte[] word, long cycle, AccountCapsule accountCap @Override public void updateDelegation(byte[] word, BytesCapsule bytesCapsule) { - Key key = Key.create(word); - Value value = Value.create(bytesCapsule.getData(), Type.VALUE_TYPE_DIRTY); - delegationCache.put(key, value); + delegationCache.put(Key.create(word), + Value.create(bytesCapsule.getData(), Type.DIRTY)); } @Override public void saveCode(byte[] address, byte[] code) { - Key key = Key.create(address); - Value value = Value.create(code, Type.VALUE_TYPE_CREATE); - codeCache.put(key, value); + codeCache.put(Key.create(address), Value.create(code, Type.CREATE)); if (VMConfig.allowTvmConstantinople()) { ContractCapsule contract = getContract(address); @@ -473,7 +469,7 @@ public byte[] getCode(byte[] address) { } if (codeCache.containsKey(key)) { - return codeCache.get(key).getCode().getData(); + return codeCache.get(key).getValue(); } byte[] code; @@ -497,23 +493,19 @@ public byte[] getCode(byte[] address) { @Override public void putStorageValue(byte[] address, DataWord key, DataWord value) { - address = TransactionTrace.convertToTronAddress(address); - if (getAccount(address) == null) { - return; - } - Key addressKey = Key.create(address); - Storage storage; - if (storageCache.containsKey(addressKey)) { - storage = storageCache.get(addressKey); - } else { - storage = getStorage(address); - storageCache.put(addressKey, storage); + Storage storage = getStorageInternal(address); + if (storage != null) { + storage.put(key, value); } - storage.put(key, value); } @Override public DataWord getStorageValue(byte[] address, DataWord key) { + Storage storage = getStorageInternal(address); + return storage == null ? null : storage.getValue(key); + } + + private Storage getStorageInternal(byte[] address) { address = TransactionTrace.convertToTronAddress(address); if (getAccount(address) == null) { return null; @@ -526,7 +518,7 @@ public DataWord getStorageValue(byte[] address, DataWord key) { storage = getStorage(address); storageCache.put(addressKey, storage); } - return storage.getValue(key); + return storage; } @Override @@ -582,9 +574,8 @@ public long addBalance(byte[] address, long value) { } accountCapsule.setBalance(Math.addExact(balance, value)); Key key = Key.create(address); - Value val = Value.create(accountCapsule.getData(), - Type.VALUE_TYPE_DIRTY | accountCache.get(key).getType().getType()); - accountCache.put(key, val); + accountCache.put(key, Value.create(accountCapsule, + accountCache.get(key).getType().addType(Type.DIRTY))); return accountCapsule.getBalance(); } @@ -631,8 +622,8 @@ public void putStorage(Key key, Storage cache) { @Override public void putAccountValue(byte[] address, AccountCapsule accountCapsule) { - Key key = new Key(address); - accountCache.put(key, new Value(accountCapsule.getData(), Type.VALUE_TYPE_CREATE)); + accountCache.put(new Key(address), + Value.create(accountCapsule, Type.CREATE)); } @Override @@ -662,8 +653,8 @@ public long addTokenBalance(byte[] address, byte[] tokenId, long value) { if (accountCapsule == null) { accountCapsule = createAccount(address, Protocol.AccountType.Normal); } - long balance = accountCapsule.getAssetMapV2() - .getOrDefault(new String(tokenIdWithoutLeadingZero), new Long(0)); + long balance = accountCapsule.getAssetMapV2().getOrDefault( + new String(tokenIdWithoutLeadingZero), 0L); if (value == 0) { return balance; } @@ -682,9 +673,8 @@ public long addTokenBalance(byte[] address, byte[] tokenId, long value) { getAssetIssueStore()); } Key key = Key.create(address); - Value V = Value.create(accountCapsule.getData(), - Type.VALUE_TYPE_DIRTY | accountCache.get(key).getType().getType()); - accountCache.put(key, V); + accountCache.put(key, Value.create(accountCapsule, + accountCache.get(key).getType().addType(Type.DIRTY))); return accountCapsule.getAssetMapV2().get(new String(tokenIdWithoutLeadingZero)); } @@ -774,7 +764,7 @@ private void commitAccountCache(Repository deposit) { if (deposit != null) { deposit.putAccount(key, value); } else { - getAccountStore().put(key.getData(), value.getAccount()); + getAccountStore().put(key.getData(), new AccountCapsule(value.getValue())); } } }); @@ -786,7 +776,7 @@ private void commitCodeCache(Repository deposit) { if (deposit != null) { deposit.putCode(key, value); } else { - getCodeStore().put(key.getData(), value.getCode()); + getCodeStore().put(key.getData(), new CodeCapsule(value.getValue())); } } })); @@ -798,7 +788,7 @@ private void commitContractCache(Repository deposit) { if (deposit != null) { deposit.putContract(key, value); } else { - ContractCapsule contractCapsule = value.getContract(); + ContractCapsule contractCapsule = new ContractCapsule(value.getValue()); if (!abiStore.has(key.getData())) { abiStore.put(key.getData(), new AbiCapsule(contractCapsule)); } @@ -827,7 +817,7 @@ private void commitDynamicCache(Repository deposit) { if (deposit != null) { deposit.putDynamicProperty(key, value); } else { - getDynamicPropertiesStore().put(key.getData(), value.getDynamicProperties()); + getDynamicPropertiesStore().put(key.getData(), new BytesCapsule(value.getValue())); } } })); @@ -839,7 +829,7 @@ private void commitDelegatedResourceCache(Repository deposit) { if (deposit != null) { deposit.putDelegatedResource(key, value); } else { - getDelegatedResourceStore().put(key.getData(), value.getDelegatedResource()); + getDelegatedResourceStore().put(key.getData(), new DelegatedResourceCapsule(value.getValue())); } } })); @@ -851,7 +841,7 @@ private void commitVotesCache(Repository deposit) { if (deposit != null) { deposit.putVotes(key, value); } else { - getVotesStore().put(key.getData(), value.getVotes()); + getVotesStore().put(key.getData(), new VotesCapsule(value.getValue())); } } })); @@ -863,7 +853,7 @@ private void commitDelegationCache(Repository deposit) { if (deposit != null) { deposit.putDelegation(key, value); } else { - getDelegationStore().put(key.getData(), value.getBytes()); + getDelegationStore().put(key.getData(), new BytesCapsule(value.getValue())); } } }); @@ -885,7 +875,7 @@ public AccountCapsule createNormalAccount(byte[] address) { getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(), withDefaultPermission, getDynamicPropertiesStore()); - accountCache.put(key, new Value(account.getData(), Type.VALUE_TYPE_CREATE)); + accountCache.put(key, Value.create(account, Type.CREATE)); return account; } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Type.java b/actuator/src/main/java/org/tron/core/vm/repository/Type.java index 6e822b2e996..e0842e6a593 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Type.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Type.java @@ -1,110 +1,61 @@ package org.tron.core.vm.repository; -public class Type { +public class Type implements Cloneable { - /** - * Default Mode : VALUE_TYPE_NORMAL - */ - public static final int VALUE_TYPE_NORMAL = 0; - public static final int VALUE_TYPE_DIRTY = 1 << 0; - public static final int VALUE_TYPE_CREATE = 1 << 1; - public static final int VALUE_TYPE_UNKNOWN = 0xFFFFFFFC; + // Default Mode : NORMAL + public static final int NORMAL = 0; + public static final int DIRTY = 1; + public static final int CREATE = 1 << 1; + public static final int UNKNOWN = 0xFFFFFFFC; - protected int type = VALUE_TYPE_NORMAL; + protected int type = NORMAL; + + public Type() {} - /** - * @param type - */ public Type(int type) { this.type |= type; } - /** - * default constructor - */ - public Type() { - } - - /** - * @param T - */ - private Type(Type T) { - this.type = T.getType(); + private Type(Type t) { + this.type = t.type; } - /** - * @return - */ public Type clone() { return new Type(this); } - /** - * @return - */ public boolean isDirty() { - return (this.type & VALUE_TYPE_DIRTY) == VALUE_TYPE_DIRTY; + return (this.type & DIRTY) == DIRTY; } - /** - * @return - */ public boolean isNormal() { - return this.type == VALUE_TYPE_NORMAL; + return this.type == NORMAL; } - /** - * @return - */ public boolean isCreate() { - return (this.type & VALUE_TYPE_CREATE) == VALUE_TYPE_CREATE; + return (this.type & CREATE) == CREATE; } - /** - * @return - */ public boolean shouldCommit() { - return this.type != VALUE_TYPE_NORMAL; + return this.type != NORMAL; } - /** - * @return - */ - public int getType() { - return type; - } - - /** - * @param type - */ - public void setType(int type) { + public Type setType(int type) { if (isValidType(type)) { this.type = type; } + return this; } - /** - * @param type - * @return - */ public boolean isValidType(int type) { - return (type & VALUE_TYPE_UNKNOWN) == VALUE_TYPE_NORMAL; + return (type & UNKNOWN) == NORMAL; } - /** - * @param type - */ - public void addType(int type) { + public int addType(int type) { if (isValidType(type)) { this.type |= type; } - } - - /** - * @param T - */ - public void addType(Type T) { - addType(T.getType()); + return this.type; } @Override @@ -116,8 +67,8 @@ public boolean equals(Object obj) { return false; } - Type T = (Type) obj; - return this.type == T.getType(); + Type other = (Type) obj; + return this.type == other.type; } @Override @@ -127,8 +78,6 @@ public int hashCode() { @Override public String toString() { - return "Type{" + - "type=" + type + - '}'; + return "Type{" + "type=" + type + '}'; } } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Value.java b/actuator/src/main/java/org/tron/core/vm/repository/Value.java index 88ae1d1f7b7..62828daacf1 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Value.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Value.java @@ -1,240 +1,46 @@ package org.tron.core.vm.repository; import java.util.Arrays; -import org.apache.commons.lang3.ArrayUtils; -import org.tron.core.capsule.AccountCapsule; -import org.tron.core.capsule.AssetIssueCapsule; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.BytesCapsule; -import org.tron.core.capsule.CodeCapsule; -import org.tron.core.capsule.ContractCapsule; -import org.tron.core.capsule.DelegatedResourceCapsule; -import org.tron.core.capsule.ProposalCapsule; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.capsule.VotesCapsule; -import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.exception.BadItemException; +import java.util.Objects; + +import lombok.Getter; +import org.tron.core.capsule.ProtoCapsule; import org.tron.core.vm.config.VMConfig; -public class Value { +public class Value { + @Getter private Type type; - private byte[] any = null; - /** - * @param any - */ - public Value(byte[] any, Type type) { - if (any != null && any.length > 0) { - this.any = new byte[any.length]; - System.arraycopy(any, 0, this.any, 0, any.length); - this.type = type.clone(); - } - } + @Getter + private T value; - /** - * @param any - * @param type - */ - public Value(byte[] any, int type) { - if (any != null && any.length > 0) { - this.any = new byte[any.length]; - System.arraycopy(any, 0, this.any, 0, any.length); + private Value(T value, int type) { + if (value != null) { + this.value = value; this.type = new Type(type); } else { if (VMConfig.allowMultiSign()) { - this.type = new Type(Type.VALUE_TYPE_UNKNOWN); - } - } - } - - /** - * @param value - */ - private Value(Value value) { - if (value.getAny() != null && value.getAny().length > 0) { - this.any = new byte[value.any.length]; - System.arraycopy(value.getAny(), 0, this.any, 0, value.getAny().length); - this.type = value.getType().clone(); - } else { - if (VMConfig.allowMultiSign()) { - this.type = new Type(Type.VALUE_TYPE_UNKNOWN); + this.type = new Type(Type.UNKNOWN); } } } - public static Value create(byte[] any, int type) { - return new Value(any, type); - } - - public static Value create(byte[] any) { - return new Value(any, Type.VALUE_TYPE_NORMAL); - } - - /** - * @return - */ - public Value clone() { - return new Value(this); - } - - /** - * @return - */ - public byte[] getAny() { - return any; - } - - /** - * @return - */ - public Type getType() { - return type; - } - - /** - * @param type - */ - public void setType(Type type) { - this.type = type; - } - - /** - * @param type - */ - public void addType(Type type) { - this.type.addType(type); - } - - /** - * @param type - */ - public void addType(int type) { - this.type.addType(type); - } - - /** - * @return - */ - public AccountCapsule getAccount() { - if (ArrayUtils.isEmpty(any)) { - return null; - } - return new AccountCapsule(any); - } - - /** - * @return - */ - public BytesCapsule getBytes() { - if (ArrayUtils.isEmpty(any)) { - return null; - } - return new BytesCapsule(any); - } - - /** - * - */ - public TransactionCapsule getTransaction() { - if (ArrayUtils.isEmpty(any)) { - return null; - } - try { - return new TransactionCapsule(any); - } catch (BadItemException e) { - return null; - } - } - - /** - * - */ - public BlockCapsule getBlock() { - if (ArrayUtils.isEmpty(any)) { - return null; - } - try { - return new BlockCapsule(any); - } catch (Exception e) { - return null; - } - } - - /** - * @return - */ - public WitnessCapsule getWitness() { - if (ArrayUtils.isEmpty(any)) { - return null; - } - return new WitnessCapsule(any); - - } - - public VotesCapsule getVotes() { - if (ArrayUtils.isEmpty(any)) { - return null; - } - return new VotesCapsule(any); + public static Value create(ProtoCapsule capsule, int type) { + return new Value<>(capsule.getInstance(), type); } - /** - * @return - */ - public BytesCapsule getBlockIndex() { - if (ArrayUtils.isEmpty(any)) { - return null; - } - return new BytesCapsule(any); + public static Value create(ProtoCapsule capsule) { + return create(capsule, Type.NORMAL); } - /** - * @return - */ - public CodeCapsule getCode() { - if (ArrayUtils.isEmpty(any)) { - return null; - } - return new CodeCapsule(any); + public static Value create(byte[] value, int type) { + return value == null ? new Value<>(null, type) : + new Value<>(Arrays.copyOf(value, value.length), type); } - /** - * @return - */ - public ContractCapsule getContract() { - if (ArrayUtils.isEmpty(any)) { - return null; - } - return new ContractCapsule(any); - } - - public AssetIssueCapsule getAssetIssue() { - if (ArrayUtils.isEmpty(any)) { - return null; - } - return new AssetIssueCapsule(any); - } - - public ProposalCapsule getProposal() { - if (ArrayUtils.isEmpty(any)) { - return null; - } - return new ProposalCapsule(any); - } - - public BytesCapsule getDynamicProperties() { - if (ArrayUtils.isEmpty(any)) { - return null; - } - return new BytesCapsule(any); - } - - public DelegatedResourceCapsule getDelegatedResource() { - if (ArrayUtils.isEmpty(any)) { - return null; - } - return new DelegatedResourceCapsule(any); + public static Value create(byte[] value) { + return create(value, Type.NORMAL); } @Override @@ -246,19 +52,12 @@ public boolean equals(Object obj) { return false; } - Value V = (Value) obj; - if (Arrays.equals(this.any, V.getAny())) { - return true; - } - return false; + Value other = (Value) obj; + return Objects.equals(this.getValue(), other.getValue()); } -// public static Value create(byte[] any, Type type) { -// return new Value(any, type); -// } - @Override public int hashCode() { - return new Integer(type.hashCode() + Arrays.hashCode(any)).hashCode(); + return new Integer(type.hashCode() + Objects.hashCode(value)).hashCode(); } } diff --git a/framework/src/main/java/org/tron/common/storage/Deposit.java b/framework/src/main/java/org/tron/common/storage/Deposit.java deleted file mode 100644 index 1f76cdfbbab..00000000000 --- a/framework/src/main/java/org/tron/common/storage/Deposit.java +++ /dev/null @@ -1,119 +0,0 @@ -package org.tron.common.storage; - -import org.tron.common.runtime.vm.DataWord; -import org.tron.core.capsule.AccountCapsule; -import org.tron.core.capsule.AssetIssueCapsule; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.BytesCapsule; -import org.tron.core.capsule.ContractCapsule; -import org.tron.core.capsule.ProposalCapsule; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.capsule.VotesCapsule; -import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.db.Manager; -import org.tron.core.vm.program.Storage; -import org.tron.core.vm.repository.Key; -import org.tron.core.vm.repository.Value; -import org.tron.protos.Protocol; - -public interface Deposit { - - Manager getDbManager(); - - AccountCapsule createAccount(byte[] address, Protocol.AccountType type); - - AccountCapsule createAccount(byte[] address, String accountName, Protocol.AccountType type); - - AccountCapsule getAccount(byte[] address); - - WitnessCapsule getWitness(byte[] address); - - VotesCapsule getVotesCapsule(byte[] address); - - ProposalCapsule getProposalCapsule(byte[] id); - - BytesCapsule getDynamic(byte[] bytesKey); - - void deleteContract(byte[] address); - - void createContract(byte[] address, ContractCapsule contractCapsule); - - ContractCapsule getContract(byte[] address); - - void updateContract(byte[] address, ContractCapsule contractCapsule); - - void updateAccount(byte[] address, AccountCapsule accountCapsule); - - void saveCode(byte[] address, byte[] code); - - byte[] getCode(byte[] address); - - void putStorageValue(byte[] address, DataWord key, DataWord value); - - DataWord getStorageValue(byte[] address, DataWord key); - - Storage getStorage(byte[] address); - - long getBalance(byte[] address); - - long addBalance(byte[] address, long value); - - Deposit newDepositChild(); - - void setParent(Deposit deposit); - - void commit(); - - void putAccount(Key key, Value value); - - void putTransaction(Key key, Value value); - - void putBlock(Key key, Value value); - - void putWitness(Key key, Value value); - - void putCode(Key key, Value value); - - void putContract(Key key, Value value); - - void putStorage(Key key, Storage cache); - - void putVotes(Key key, Value value); - - void putProposal(Key key, Value value); - - void putDynamicProperties(Key key, Value value); - - void putAccountValue(byte[] address, AccountCapsule accountCapsule); - - void putVoteValue(byte[] address, VotesCapsule votesCapsule); - - void putProposalValue(byte[] address, ProposalCapsule proposalCapsule); - - void putDynamicPropertiesWithLatestProposalNum(long num); - - long getLatestProposalNum(); - - long getWitnessAllowanceFrozenTime(); - - long getMaintenanceTimeInterval(); - - long getNextMaintenanceTime(); - - long addTokenBalance(byte[] address, byte[] tokenId, long value); - - long getTokenBalance(byte[] address, byte[] tokenId); - - AssetIssueCapsule getAssetIssue(byte[] tokenId); - - TransactionCapsule getTransaction(byte[] trxHash); - - BlockCapsule getBlock(byte[] blockHash); - - byte[] getBlackHoleAddress(); - - public AccountCapsule createNormalAccount(byte[] address); - - -} - diff --git a/framework/src/main/java/org/tron/common/storage/DepositImpl.java b/framework/src/main/java/org/tron/common/storage/DepositImpl.java deleted file mode 100644 index 7793c46a6e2..00000000000 --- a/framework/src/main/java/org/tron/common/storage/DepositImpl.java +++ /dev/null @@ -1,827 +0,0 @@ -package org.tron.common.storage; - -import com.google.common.primitives.Longs; -import com.google.protobuf.ByteString; -import java.util.HashMap; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.Strings; -import org.bouncycastle.util.encoders.Hex; -import org.tron.common.crypto.Hash; -import org.tron.common.runtime.vm.DataWord; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.Commons; -import org.tron.common.utils.StorageUtils; -import org.tron.common.utils.StringUtil; -import org.tron.core.capsule.AccountCapsule; -import org.tron.core.capsule.AssetIssueCapsule; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.BytesCapsule; -import org.tron.core.capsule.ContractCapsule; -import org.tron.core.capsule.ProposalCapsule; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.capsule.VotesCapsule; -import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.db.BlockStore; -import org.tron.core.db.Manager; -import org.tron.core.db.TransactionStore; -import org.tron.core.db.TransactionTrace; -import org.tron.core.exception.BadItemException; -import org.tron.core.exception.ItemNotFoundException; -import org.tron.core.store.AccountStore; -import org.tron.core.store.CodeStore; -import org.tron.core.store.ContractStore; -import org.tron.core.store.DelegatedResourceStore; -import org.tron.core.store.DynamicPropertiesStore; -import org.tron.core.store.ProposalStore; -import org.tron.core.store.VotesStore; -import org.tron.core.store.WitnessStore; -import org.tron.core.vm.config.VMConfig; -import org.tron.core.vm.program.Storage; -import org.tron.core.vm.repository.Key; -import org.tron.core.vm.repository.Type; -import org.tron.core.vm.repository.Value; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.AccountType; - -@Slf4j(topic = "deposit") -public class DepositImpl implements Deposit { - - private static final byte[] LATEST_PROPOSAL_NUM = "LATEST_PROPOSAL_NUM".getBytes(); - private static final byte[] WITNESS_ALLOWANCE_FROZEN_TIME = "WITNESS_ALLOWANCE_FROZEN_TIME" - .getBytes(); - private static final byte[] MAINTENANCE_TIME_INTERVAL = "MAINTENANCE_TIME_INTERVAL".getBytes(); - private static final byte[] NEXT_MAINTENANCE_TIME = "NEXT_MAINTENANCE_TIME".getBytes(); - - private Manager dbManager; - private Deposit parent = null; - - private HashMap accountCache = new HashMap<>(); - private HashMap transactionCache = new HashMap<>(); - private HashMap blockCache = new HashMap<>(); - private HashMap witnessCache = new HashMap<>(); - private HashMap codeCache = new HashMap<>(); - private HashMap contractCache = new HashMap<>(); - - private HashMap votesCache = new HashMap<>(); - private HashMap proposalCache = new HashMap<>(); - private HashMap dynamicPropertiesCache = new HashMap<>(); - private HashMap storageCache = new HashMap<>(); - private HashMap assetIssueCache = new HashMap<>(); - - private DepositImpl(Manager dbManager, DepositImpl parent) { - init(dbManager, parent); - } - - public static DepositImpl createRoot(Manager dbManager) { - return new DepositImpl(dbManager, null); - } - - protected void init(Manager dbManager, DepositImpl parent) { - this.dbManager = dbManager; - this.parent = parent; - } - - @Override - public Manager getDbManager() { - return dbManager; - } - - private BlockStore getBlockStore() { - return dbManager.getBlockStore(); - } - - private TransactionStore getTransactionStore() { - return dbManager.getTransactionStore(); - } - - private ContractStore getContractStore() { - return dbManager.getContractStore(); - } - - private WitnessStore getWitnessStore() { - return dbManager.getWitnessStore(); - } - - private VotesStore getVotesStore() { - return dbManager.getVotesStore(); - } - - private ProposalStore getProposalStore() { - return dbManager.getProposalStore(); - } - - private DynamicPropertiesStore getDynamicPropertiesStore() { - return dbManager.getDynamicPropertiesStore(); - } - - private AccountStore getAccountStore() { - return dbManager.getAccountStore(); - } - - private CodeStore getCodeStore() { - return dbManager.getCodeStore(); - } - - private DelegatedResourceStore getDelegatedResourceStore() { - return dbManager.getDelegatedResourceStore(); - } - - @Override - public Deposit newDepositChild() { - return new DepositImpl(dbManager, this); - } - - @Override - public synchronized AccountCapsule createAccount(byte[] address, Protocol.AccountType type) { - Key key = new Key(address); - AccountCapsule account = new AccountCapsule(ByteString.copyFrom(address), type); - accountCache.put(key, new Value(account.getData(), Type.VALUE_TYPE_CREATE)); - return account; - } - - @Override - public AccountCapsule createAccount(byte[] address, String accountName, AccountType type) { - Key key = new Key(address); - AccountCapsule account = new AccountCapsule(ByteString.copyFrom(address), - ByteString.copyFromUtf8(accountName), - type); - - accountCache.put(key, new Value(account.getData(), Type.VALUE_TYPE_CREATE)); - return account; - } - - @Override - public synchronized AccountCapsule getAccount(byte[] address) { - Key key = new Key(address); - if (accountCache.containsKey(key)) { - return accountCache.get(key).getAccount(); - } - - AccountCapsule accountCapsule; - if (parent != null) { - accountCapsule = parent.getAccount(address); - } else { - accountCapsule = getAccountStore().get(address); - } - - if (accountCapsule != null) { - accountCache.put(key, Value.create(accountCapsule.getData())); - } - return accountCapsule; - } - - @Override - public byte[] getBlackHoleAddress() { - // using dbManager directly, black hole address should not be changed - // when executing smart contract. - return getAccountStore().getBlackholeAddress(); - } - - @Override - public WitnessCapsule getWitness(byte[] address) { - Key key = new Key(address); - if (witnessCache.containsKey(key)) { - return witnessCache.get(key).getWitness(); - } - - WitnessCapsule witnessCapsule; - if (parent != null) { - witnessCapsule = parent.getWitness(address); - } else { - witnessCapsule = getWitnessStore().get(address); - } - - if (witnessCapsule != null) { - witnessCache.put(key, Value.create(witnessCapsule.getData())); - } - return witnessCapsule; - } - - @Override - public synchronized VotesCapsule getVotesCapsule(byte[] address) { - Key key = new Key(address); - if (votesCache.containsKey(key)) { - return votesCache.get(key).getVotes(); - } - - VotesCapsule votesCapsule; - if (parent != null) { - votesCapsule = parent.getVotesCapsule(address); - } else { - votesCapsule = getVotesStore().get(address); - } - - if (votesCapsule != null) { - votesCache.put(key, Value.create(votesCapsule.getData())); - } - return votesCapsule; - } - - @Override - public synchronized ProposalCapsule getProposalCapsule(byte[] id) { - Key key = new Key(id); - if (proposalCache.containsKey(key)) { - return proposalCache.get(key).getProposal(); - } - - ProposalCapsule proposalCapsule; - if (parent != null) { - proposalCapsule = parent.getProposalCapsule(id); - } else { - try { - proposalCapsule = getProposalStore().get(id); - } catch (ItemNotFoundException e) { - logger.warn("proposal not found, id:" + Hex.toHexString(id)); - proposalCapsule = null; - } - } - - if (proposalCapsule != null) { - proposalCache.put(key, Value.create(proposalCapsule.getData())); - } - return proposalCapsule; - } - - // just for depositRoot - @Override - public void deleteContract(byte[] address) { - getCodeStore().delete(address); - getAccountStore().delete(address); - getContractStore().delete(address); - } - - @Override - public synchronized void createContract(byte[] address, ContractCapsule contractCapsule) { - Key key = Key.create(address); - Value value = Value.create(contractCapsule.getData(), Type.VALUE_TYPE_CREATE); - contractCache.put(key, value); - } - - @Override - public void updateContract(byte[] address, ContractCapsule contractCapsule) { - Key key = Key.create(address); - Value value = Value.create(contractCapsule.getData(), Type.VALUE_TYPE_DIRTY); - contractCache.put(key, value); - } - - @Override - public void updateAccount(byte[] address, AccountCapsule accountCapsule) { - Key key = Key.create(address); - Value value = Value.create(accountCapsule.getData(), Type.VALUE_TYPE_DIRTY); - accountCache.put(key, value); - } - - @Override - public synchronized ContractCapsule getContract(byte[] address) { - Key key = Key.create(address); - if (contractCache.containsKey(key)) { - return contractCache.get(key).getContract(); - } - - ContractCapsule contractCapsule; - if (parent != null) { - contractCapsule = parent.getContract(address); - } else { - contractCapsule = getContractStore().get(address); - } - - if (contractCapsule != null) { - contractCache.put(key, Value.create(contractCapsule.getData())); - } - return contractCapsule; - } - - @Override - public synchronized void saveCode(byte[] address, byte[] code) { - Key key = Key.create(address); - Value value = Value.create(code, Type.VALUE_TYPE_CREATE); - codeCache.put(key, value); - - if (VMConfig.allowTvmConstantinople()) { - ContractCapsule contract = getContract(address); - byte[] codeHash = Hash.sha3(code); - contract.setCodeHash(codeHash); - updateContract(address, contract); - } - } - - @Override - public synchronized byte[] getCode(byte[] address) { - Key key = Key.create(address); - if (codeCache.containsKey(key)) { - return codeCache.get(key).getCode().getData(); - } - - byte[] code; - if (parent != null) { - code = parent.getCode(address); - } else { - if (null == getCodeStore().get(address)) { - code = null; - } else { - code = getCodeStore().get(address).getData(); - } - } - if (code != null) { - codeCache.put(key, Value.create(code)); - } - return code; - } - - @Override - public synchronized Storage getStorage(byte[] address) { - Key key = Key.create(address); - if (storageCache.containsKey(key)) { - return storageCache.get(key); - } - Storage storage; - if (this.parent != null) { - Storage parentStorage = parent.getStorage(address); - if (StorageUtils.getEnergyLimitHardFork()) { - // deep copy - storage = new Storage(parentStorage); - } else { - storage = parentStorage; - } - } else { - storage = new Storage(address, dbManager.getStorageRowStore()); - } - ContractCapsule contract = getContract(address); - if (contract != null && !ByteUtil.isNullOrZeroArray(contract.getTrxHash())) { - storage.generateAddrHash(contract.getTrxHash()); - } - return storage; - } - - @Override - public synchronized AssetIssueCapsule getAssetIssue(byte[] tokenId) { - byte[] tokenIdWithoutLeadingZero = ByteUtil.stripLeadingZeroes(tokenId); - Key key = Key.create(tokenIdWithoutLeadingZero); - if (assetIssueCache.containsKey(key)) { - return assetIssueCache.get(key).getAssetIssue(); - } - - AssetIssueCapsule assetIssueCapsule; - if (this.parent != null) { - assetIssueCapsule = parent.getAssetIssue(tokenIdWithoutLeadingZero); - } else { - assetIssueCapsule = Commons.getAssetIssueStoreFinal(dbManager.getDynamicPropertiesStore(), - dbManager.getAssetIssueStore(), dbManager.getAssetIssueV2Store()) - .get(tokenIdWithoutLeadingZero); - } - if (assetIssueCapsule != null) { - assetIssueCache.put(key, Value.create(assetIssueCapsule.getData())); - } - return assetIssueCapsule; - } - - @Override - public synchronized void putStorageValue(byte[] address, DataWord key, DataWord value) { - address = TransactionTrace.convertToTronAddress(address); - if (getAccount(address) == null) { - return; - } - Key addressKey = Key.create(address); - Storage storage; - if (storageCache.containsKey(addressKey)) { - storage = storageCache.get(addressKey); - } else { - storage = getStorage(address); - storageCache.put(addressKey, storage); - } - storage.put(key, value); - } - - @Override - public synchronized DataWord getStorageValue(byte[] address, DataWord key) { - address = TransactionTrace.convertToTronAddress(address); - if (getAccount(address) == null) { - return null; - } - Key addressKey = Key.create(address); - Storage storage; - if (storageCache.containsKey(addressKey)) { - storage = storageCache.get(addressKey); - } else { - storage = getStorage(address); - storageCache.put(addressKey, storage); - } - return storage.getValue(key); - } - - @Override - public synchronized long getBalance(byte[] address) { - AccountCapsule accountCapsule = getAccount(address); - return accountCapsule == null ? 0L : accountCapsule.getBalance(); - } - - @Override - public synchronized long addTokenBalance(byte[] address, byte[] tokenId, long value) { - byte[] tokenIdWithoutLeadingZero = ByteUtil.stripLeadingZeroes(tokenId); - AccountCapsule accountCapsule = getAccount(address); - if (accountCapsule == null) { - accountCapsule = createAccount(address, AccountType.Normal); - } - long balance = accountCapsule.getAssetMapV2() - .getOrDefault(new String(tokenIdWithoutLeadingZero), new Long(0)); - if (value == 0) { - return balance; - } - - if (value < 0 && balance < -value) { - throw new RuntimeException( - StringUtil.createReadableString(accountCapsule.createDbKey()) - + " insufficient balance"); - } - if (value >= 0) { - accountCapsule.addAssetAmountV2(tokenIdWithoutLeadingZero, value, - this.dbManager.getDynamicPropertiesStore(), this.dbManager.getAssetIssueStore()); - } else { - accountCapsule.reduceAssetAmountV2(tokenIdWithoutLeadingZero, -value, - this.dbManager.getDynamicPropertiesStore(), this.dbManager.getAssetIssueStore()); - } - - Key key = Key.create(address); - Value V = Value.create(accountCapsule.getData(), - Type.VALUE_TYPE_DIRTY | accountCache.get(key).getType().getType()); - accountCache.put(key, V); - return accountCapsule.getAssetMapV2().get(new String(tokenIdWithoutLeadingZero)); - } - - @Override - public synchronized long addBalance(byte[] address, long value) { - AccountCapsule accountCapsule = getAccount(address); - if (accountCapsule == null) { - accountCapsule = createAccount(address, Protocol.AccountType.Normal); - } - - long balance = accountCapsule.getBalance(); - if (value == 0) { - return balance; - } - - if (value < 0 && balance < -value) { - throw new RuntimeException( - StringUtil.createReadableString(accountCapsule.createDbKey()) - + " insufficient balance"); - } - accountCapsule.setBalance(Math.addExact(balance, value)); - Key key = Key.create(address); - Value val = Value.create(accountCapsule.getData(), - Type.VALUE_TYPE_DIRTY | accountCache.get(key).getType().getType()); - accountCache.put(key, val); - return accountCapsule.getBalance(); - } - - /** - * @param address address - * @param tokenId tokenIdstr in assetV2map is a string like "1000001". So before using this - * function, we need to do some conversion. usually we will use a DataWord as input. so the byte - * tokenId should be like DataWord.shortHexWithoutZeroX().getbytes(). - */ - @Override - public synchronized long getTokenBalance(byte[] address, byte[] tokenId) { - AccountCapsule accountCapsule = getAccount(address); - if (accountCapsule == null) { - return 0; - } - String tokenStr = new String(ByteUtil.stripLeadingZeroes(tokenId)); - return accountCapsule.getAssetMapV2().getOrDefault(tokenStr, 0L); - } - - @Override - public TransactionCapsule getTransaction(byte[] trxHash) { - Key key = Key.create(trxHash); - if (transactionCache.containsKey(key)) { - return transactionCache.get(key).getTransaction(); - } - - TransactionCapsule transactionCapsule; - if (parent != null) { - transactionCapsule = parent.getTransaction(trxHash); - } else { - try { - transactionCapsule = getTransactionStore().get(trxHash); - } catch (BadItemException e) { - transactionCapsule = null; - } - } - - if (transactionCapsule != null) { - transactionCache.put(key, Value.create(transactionCapsule.getData())); - } - return transactionCapsule; - } - - @Override - public BlockCapsule getBlock(byte[] blockHash) { - Key key = Key.create(blockHash); - if (blockCache.containsKey(key)) { - return blockCache.get(key).getBlock(); - } - - BlockCapsule ret; - try { - if (parent != null) { - ret = parent.getBlock(blockHash); - } else { - ret = getBlockStore().get(blockHash); - } - } catch (Exception e) { - ret = null; - } - - if (ret != null) { - blockCache.put(key, Value.create(ret.getData())); - } - return ret; - } - - @Override - public void putAccount(Key key, Value value) { - accountCache.put(key, value); - } - - @Override - public void putTransaction(Key key, Value value) { - transactionCache.put(key, value); - } - - @Override - public void putBlock(Key key, Value value) { - blockCache.put(key, value); - } - - @Override - public void putWitness(Key key, Value value) { - witnessCache.put(key, value); - } - - @Override - public void putCode(Key key, Value value) { - codeCache.put(key, value); - } - - @Override - public void putContract(Key key, Value value) { - contractCache.put(key, value); - } - - @Override - public void putStorage(Key key, Storage cache) { - storageCache.put(key, cache); - } - - @Override - public void putVotes(Key key, Value value) { - votesCache.put(key, value); - } - - @Override - public void putProposal(Key key, Value value) { - proposalCache.put(key, value); - } - - @Override - public void putDynamicProperties(Key key, Value value) { - dynamicPropertiesCache.put(key, value); - } - - @Override - public long getLatestProposalNum() { - return Longs.fromByteArray(getDynamic(LATEST_PROPOSAL_NUM).getData()); - } - - @Override - public long getWitnessAllowanceFrozenTime() { - byte[] frozenTime = getDynamic(WITNESS_ALLOWANCE_FROZEN_TIME).getData(); - if (frozenTime.length >= 8) { - return Longs.fromByteArray(getDynamic(WITNESS_ALLOWANCE_FROZEN_TIME).getData()); - } - - byte[] result = new byte[8]; - System.arraycopy(frozenTime, 0, result, 8 - frozenTime.length, frozenTime.length); - return Longs.fromByteArray(result); - - } - - @Override - public long getMaintenanceTimeInterval() { - return Longs.fromByteArray(getDynamic(MAINTENANCE_TIME_INTERVAL).getData()); - } - - @Override - public long getNextMaintenanceTime() { - return Longs.fromByteArray(getDynamic(NEXT_MAINTENANCE_TIME).getData()); - } - - public BytesCapsule getDynamic(byte[] word) { - Key key = Key.create(word); - if (dynamicPropertiesCache.containsKey(key)) { - return dynamicPropertiesCache.get(key).getDynamicProperties(); - } - - BytesCapsule bytesCapsule; - if (parent != null) { - bytesCapsule = parent.getDynamic(word); - } else { - try { - bytesCapsule = getDynamicPropertiesStore().get(word); - } catch (BadItemException | ItemNotFoundException e) { - logger.warn("Dynamic property not found:" + Strings.fromUTF8ByteArray(word)); - bytesCapsule = null; - } - } - - if (bytesCapsule != null) { - dynamicPropertiesCache.put(key, Value.create(bytesCapsule.getData())); - } - return bytesCapsule; - } - - private void commitAccountCache(Deposit deposit) { - accountCache.forEach((key, value) -> { - if (value.getType().isCreate() || value.getType().isDirty()) { - if (deposit != null) { - deposit.putAccount(key, value); - } else { - getAccountStore().put(key.getData(), value.getAccount()); - } - } - }); - } - - private void commitTransactionCache(Deposit deposit) { - transactionCache.forEach((key, value) -> { - if (value.getType().isDirty() || value.getType().isCreate()) { - if (deposit != null) { - deposit.putTransaction(key, value); - } else { - getTransactionStore().put(key.getData(), value.getTransaction()); - } - } - }); - } - - private void commitBlockCache(Deposit deposit) { - blockCache.forEach(((key, value) -> { - if (value.getType().isDirty() || value.getType().isCreate()) { - if (deposit != null) { - deposit.putBlock(key, value); - } else { - getBlockStore().put(key.getData(), value.getBlock()); - } - } - })); - } - - private void commitWitnessCache(Deposit deposit) { - witnessCache.forEach(((key, value) -> { - if (value.getType().isDirty() || value.getType().isCreate()) { - if (deposit != null) { - deposit.putWitness(key, value); - } else { - getWitnessStore().put(key.getData(), value.getWitness()); - } - } - })); - } - - private void commitCodeCache(Deposit deposit) { - codeCache.forEach(((key, value) -> { - if (value.getType().isDirty() || value.getType().isCreate()) { - if (deposit != null) { - deposit.putCode(key, value); - } else { - getCodeStore().put(key.getData(), value.getCode()); - } - } - })); - } - - private void commitContractCache(Deposit deposit) { - contractCache.forEach(((key, value) -> { - if (value.getType().isDirty() || value.getType().isCreate()) { - if (deposit != null) { - deposit.putContract(key, value); - } else { - getContractStore().put(key.getData(), value.getContract()); - } - } - })); - } - - private void commitStorageCache(Deposit deposit) { - storageCache.forEach((Key address, Storage storage) -> { - if (deposit != null) { - // write to parent cache - deposit.putStorage(address, storage); - } else { - // persistence - storage.commit(); - } - }); - - } - - private void commitVoteCache(Deposit deposit) { - votesCache.forEach(((key, value) -> { - if (value.getType().isDirty() || value.getType().isCreate()) { - if (deposit != null) { - deposit.putVotes(key, value); - } else { - getVotesStore().put(key.getData(), value.getVotes()); - } - } - })); - } - - private void commitProposalCache(Deposit deposit) { - proposalCache.forEach(((key, value) -> { - if (value.getType().isDirty() || value.getType().isCreate()) { - if (deposit != null) { - deposit.putProposal(key, value); - } else { - getProposalStore().put(key.getData(), value.getProposal()); - } - } - })); - } - - private void commitDynamicPropertiesCache(Deposit deposit) { - dynamicPropertiesCache.forEach(((key, value) -> { - if (value.getType().isDirty() || value.getType().isCreate()) { - if (deposit != null) { - deposit.putDynamicProperties(key, value); - } else { - getDynamicPropertiesStore().put(key.getData(), value.getDynamicProperties()); - } - } - })); - } - - @Override - public void putAccountValue(byte[] address, AccountCapsule accountCapsule) { - Key key = new Key(address); - accountCache.put(key, new Value(accountCapsule.getData(), Type.VALUE_TYPE_CREATE)); - } - - @Override - public void putVoteValue(byte[] address, VotesCapsule votesCapsule) { - Key key = new Key(address); - votesCache.put(key, new Value(votesCapsule.getData(), Type.VALUE_TYPE_CREATE)); - } - - @Override - public void putProposalValue(byte[] address, ProposalCapsule proposalCapsule) { - Key key = new Key(address); - proposalCache.put(key, new Value(proposalCapsule.getData(), Type.VALUE_TYPE_CREATE)); - } - - @Override - public void putDynamicPropertiesWithLatestProposalNum(long num) { - Key key = new Key(LATEST_PROPOSAL_NUM); - dynamicPropertiesCache.put(key, - new Value(new BytesCapsule(ByteArray.fromLong(num)).getData(), Type.VALUE_TYPE_CREATE)); - } - - @Override - public synchronized void commit() { - Deposit deposit = null; - if (parent != null) { - deposit = parent; - } - - commitAccountCache(deposit); - commitTransactionCache(deposit); - commitBlockCache(deposit); - commitWitnessCache(deposit); - commitCodeCache(deposit); - commitContractCache(deposit); - commitStorageCache(deposit); - commitVoteCache(deposit); - commitProposalCache(deposit); - commitDynamicPropertiesCache(deposit); - } - - @Override - public void setParent(Deposit deposit) { - parent = deposit; - } - - @Override - public AccountCapsule createNormalAccount(byte[] address) { - boolean withDefaultPermission = - getDynamicPropertiesStore().getAllowMultiSign() == 1; - Key key = new Key(address); - AccountCapsule account = new AccountCapsule(ByteString.copyFrom(address), AccountType.Normal, - getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(), withDefaultPermission, - getDynamicPropertiesStore()); - - accountCache.put(key, new Value(account.getData(), Type.VALUE_TYPE_CREATE)); - return account; - } - -} - diff --git a/framework/src/test/java/org/tron/common/runtime/InheritanceTest.java b/framework/src/test/java/org/tron/common/runtime/InheritanceTest.java index 386c53a4294..f5101af19af 100644 --- a/framework/src/test/java/org/tron/common/runtime/InheritanceTest.java +++ b/framework/src/test/java/org/tron/common/runtime/InheritanceTest.java @@ -10,7 +10,6 @@ import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -21,6 +20,8 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; +import org.tron.core.store.StoreFactory; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; @Slf4j @@ -32,7 +33,7 @@ public class InheritanceTest { private static Manager dbManager; private static TronApplicationContext context; private static Application appT; - private static DepositImpl deposit; + private static RepositoryImpl repository; static { Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); @@ -47,9 +48,9 @@ public class InheritanceTest { @BeforeClass public static void init() { dbManager = context.getBean(Manager.class); - deposit = DepositImpl.createRoot(dbManager); - deposit.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); - deposit.addBalance(Hex.decode(OWNER_ADDRESS), 100000000); + repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); + repository.addBalance(Hex.decode(OWNER_ADDRESS), 100000000); } /** @@ -113,14 +114,14 @@ public void inheritanceTest() byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, callerAddress, ABI, code, - value, fee, consumeUserResourcePercent, null, deposit, null); + value, fee, consumeUserResourcePercent, null, repository, null); /* ========================== CALL getName() return child value ============================= */ byte[] triggerData1 = TvmTestUtils.parseAbi("getName()", ""); runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(callerAddress, contractAddress, - triggerData1, 0, 1000000, deposit, null); + triggerData1, 0, 1000000, repository, null); //0x20 => pointer position, 0x3 => size, 626172 => "bar" Assert.assertEquals(Hex.toHexString(runtime.getResult().getHReturn()), @@ -132,7 +133,7 @@ public void inheritanceTest() byte[] triggerData2 = TvmTestUtils.parseAbi("getNumber()", ""); runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(callerAddress, contractAddress, - triggerData2, 0, 1000000, deposit, null); + triggerData2, 0, 1000000, repository, null); //0x64 =>100 Assert.assertEquals(Hex.toHexString(runtime.getResult().getHReturn()), @@ -142,7 +143,7 @@ public void inheritanceTest() byte[] triggerData3 = TvmTestUtils.parseAbi("getId()", ""); runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(callerAddress, contractAddress, - triggerData3, 0, 1000000, deposit, null); + triggerData3, 0, 1000000, repository, null); //0x64 =>100 Assert.assertEquals(Hex.toHexString(runtime.getResult().getHReturn()), diff --git a/framework/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java b/framework/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java index 281968b1122..22fb44bfacf 100644 --- a/framework/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java +++ b/framework/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java @@ -11,7 +11,6 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.vm.DataWord; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -22,6 +21,8 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; +import org.tron.core.store.StoreFactory; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; @Slf4j @@ -33,7 +34,7 @@ public class InternalTransactionComplexTest { private static Manager dbManager; private static TronApplicationContext context; private static Application appT; - private static DepositImpl deposit; + private static RepositoryImpl repository; static { Args.setParam(new String[]{"--output-directory", dbPath, "--debug", "--support-constant"}, @@ -49,9 +50,9 @@ public class InternalTransactionComplexTest { @BeforeClass public static void init() { dbManager = context.getBean(Manager.class); - deposit = DepositImpl.createRoot(dbManager); - deposit.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); - deposit.addBalance(Hex.decode(OWNER_ADDRESS), 100000000); + repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); + repository.addBalance(Hex.decode(OWNER_ADDRESS), 100000000); } /** @@ -99,13 +100,13 @@ public void internalTransactionAsInstanceTest() byte[] triggerData1 = TvmTestUtils.parseAbi("makeTheCall()", ""); runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), - callerContractAddress, triggerData1, 0, 100000000, deposit, null); + callerContractAddress, triggerData1, 0, 100000000, repository, null); /* =============== CALL testCallbackReturns_ to check data ====================== */ byte[] triggerData2 = TvmTestUtils.parseAbi("testCallbackReturns_()", ""); runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), - callerContractAddress, triggerData2, 0, 100000000, deposit, null); + callerContractAddress, triggerData2, 0, 100000000, repository, null); // bool true => 0000000000000000000000000000000000000000000000000000000000000001, // uint256 314159 =>000000000000000000000000000000000000000000000000000000000004cb2f, @@ -144,7 +145,7 @@ private byte[] deployCalledContractandGetItsAddress() return TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, - feeLimit, consumeUserResourcePercent, null, deposit, null); + feeLimit, consumeUserResourcePercent, null, repository, null); } // Just for the caller/called example above @@ -192,7 +193,7 @@ private byte[] deployCallerContractAndGetItsAddress(byte[] calledContractAddress return TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, - feeLimit, consumeUserResourcePercent, null, deposit, null); + feeLimit, consumeUserResourcePercent, null, repository, null); } } diff --git a/framework/src/test/java/org/tron/common/runtime/ProgramResultTest.java b/framework/src/test/java/org/tron/common/runtime/ProgramResultTest.java index 61b1024bc66..8fa590eb4d8 100644 --- a/framework/src/test/java/org/tron/common/runtime/ProgramResultTest.java +++ b/framework/src/test/java/org/tron/common/runtime/ProgramResultTest.java @@ -17,7 +17,6 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.vm.DataWord; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -33,6 +32,8 @@ import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.store.StoreFactory; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction; @@ -49,7 +50,7 @@ public class ProgramResultTest { private static Manager dbManager; private static TronApplicationContext context; private static Application appT; - private static DepositImpl deposit; + private static RepositoryImpl repository; static { Args.setParam(new String[]{"--output-directory", dbPath, "--debug", "--support-constant"}, @@ -66,12 +67,12 @@ public class ProgramResultTest { @BeforeClass public static void init() { dbManager = context.getBean(Manager.class); - deposit = DepositImpl.createRoot(dbManager); - deposit.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); - deposit.addBalance(Hex.decode(OWNER_ADDRESS), 100000000); - deposit.createAccount(Hex.decode(TRANSFER_TO), AccountType.Normal); - deposit.addBalance(Hex.decode(TRANSFER_TO), 0); - deposit.commit(); + repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); + repository.addBalance(Hex.decode(OWNER_ADDRESS), 100000000); + repository.createAccount(Hex.decode(TRANSFER_TO), AccountType.Normal); + repository.addBalance(Hex.decode(TRANSFER_TO), 0); + repository.commit(); } /** @@ -116,7 +117,7 @@ public void uniqueInternalTransactionHashTest() byte[] triggerData1 = TvmTestUtils.parseAbi("create()", ""); runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), - contractAAddress, triggerData1, 0, 100000000, deposit, null); + contractAAddress, triggerData1, 0, 100000000, repository, null); List internalTransactionsList = runtime.getResult() .getInternalTransactions(); // 15 internalTransactions in total @@ -153,7 +154,7 @@ private byte[] deployCalledContractAndGetItsAddress() return TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, - feeLimit, consumeUserResourcePercent, null, deposit, null); + feeLimit, consumeUserResourcePercent, null, repository, null); } private byte[] deployContractAAndGetItsAddress(byte[] calledContractAddress) @@ -262,7 +263,7 @@ private byte[] deployContractAAndGetItsAddress(byte[] calledContractAddress) return TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, - feeLimit, consumeUserResourcePercent, null, deposit, null); + feeLimit, consumeUserResourcePercent, null, repository, null); } /** @@ -295,7 +296,7 @@ public void successAndFailResultTest() .generateTriggerSmartContractAndGetTransaction(Hex.decode(OWNER_ADDRESS), aContract, triggerData1, 0, 100000000); TransactionTrace traceSuccess = TvmTestUtils - .processTransactionAndReturnTrace(trx1, deposit, null); + .processTransactionAndReturnTrace(trx1, repository, null); runtime = traceSuccess.getRuntime(); byte[] bContract = runtime.getResult().getHReturn(); List internalTransactionsList = runtime.getResult() @@ -338,7 +339,7 @@ public void successAndFailResultTest() .generateTriggerSmartContractAndGetTransaction(Hex.decode(OWNER_ADDRESS), aContract, triggerData2, 0, 100000000); TransactionTrace traceFailed = TvmTestUtils - .processTransactionAndReturnTrace(trx2, deposit, null); + .processTransactionAndReturnTrace(trx2, repository, null); runtime = traceFailed.getRuntime(); byte[] bContract2 = @@ -393,7 +394,7 @@ public void timeOutFeeTest() .generateTriggerSmartContractAndGetTransaction(Hex.decode(OWNER_ADDRESS), aContract, triggerData1, 0, 100000000); TransactionTrace traceSuccess = TvmTestUtils - .processTransactionAndReturnTrace(trx1, deposit, null); + .processTransactionAndReturnTrace(trx1, repository, null); Assert.assertEquals(traceSuccess.getReceipt().getEnergyFee(), 12705900L); @@ -438,7 +439,7 @@ private byte[] deployC(String contractName) return TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, - feeLimit, consumeUserResourcePercent, null, deposit, null); + feeLimit, consumeUserResourcePercent, null, repository, null); } private byte[] deployA(String contractName) @@ -490,7 +491,7 @@ private byte[] deployA(String contractName) return TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, - feeLimit, consumeUserResourcePercent, null, deposit, null); + feeLimit, consumeUserResourcePercent, null, repository, null); } /** @@ -504,7 +505,7 @@ public void suicideResultTest() throws ContractExeException, ReceiptCheckErrException, VMIllegalException, ContractValidateException { byte[] suicideContract = deploySuicide(); - Assert.assertEquals(deposit.getAccount(suicideContract).getBalance(), 1000); + Assert.assertEquals(repository.getAccount(suicideContract).getBalance(), 1000); String params = Hex .toHexString(new DataWord(new DataWord(TRANSFER_TO).getLast20Bytes()).getData()); @@ -513,7 +514,7 @@ public void suicideResultTest() Transaction trx = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(Hex.decode(OWNER_ADDRESS), suicideContract, triggerData1, 0, 100000000); - TransactionTrace trace = TvmTestUtils.processTransactionAndReturnTrace(trx, deposit, null); + TransactionTrace trace = TvmTestUtils.processTransactionAndReturnTrace(trx, repository, null); runtime = trace.getRuntime(); List internalTransactionsList = runtime.getResult() .getInternalTransactions(); @@ -554,7 +555,7 @@ private byte[] deploySuicide() return TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, - feeLimit, consumeUserResourcePercent, null, deposit, null); + feeLimit, consumeUserResourcePercent, null, repository, null); } public void checkTransactionInfo(TransactionTrace trace, Transaction trx, BlockCapsule block, diff --git a/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java b/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java index 2a14f52e487..e983ce12647 100644 --- a/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java +++ b/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java @@ -12,7 +12,6 @@ import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; import org.tron.common.utils.WalletUtil; import org.tron.core.Constant; @@ -24,6 +23,8 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; +import org.tron.core.store.StoreFactory; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction; import stest.tron.wallet.common.client.utils.DataWord; @@ -38,7 +39,7 @@ public class RuntimeTransferComplexTest { private static Manager dbManager; private static TronApplicationContext context; private static Application appT; - private static DepositImpl deposit; + private static RepositoryImpl repository; static { Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); @@ -54,12 +55,12 @@ public class RuntimeTransferComplexTest { @BeforeClass public static void init() { dbManager = context.getBean(Manager.class); - deposit = DepositImpl.createRoot(dbManager); - deposit.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); - deposit.addBalance(Hex.decode(OWNER_ADDRESS), 1000000000); - deposit.createAccount(Hex.decode(TRANSFER_TO), AccountType.Normal); - deposit.addBalance(Hex.decode(TRANSFER_TO), 10); - deposit.commit(); + repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); + repository.addBalance(Hex.decode(OWNER_ADDRESS), 1000000000); + repository.createAccount(Hex.decode(TRANSFER_TO), AccountType.Normal); + repository.addBalance(Hex.decode(TRANSFER_TO), 10); + repository.commit(); } /** @@ -99,7 +100,7 @@ public void TransferTrxToContractAccountWhenDeployAContract() .generateDeploySmartContractAndGetTransaction(contractName, address, ABI, code, value, fee, consumeUserResourcePercent, null); byte[] contractAddress = WalletUtil.generateContractAddress(trx); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, deposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, repository, null); Assert.assertNull(runtime.getRuntimeError()); Assert.assertEquals(dbManager.getAccountStore().get(contractAddress).getBalance(), 100); recoverDeposit(); @@ -130,7 +131,7 @@ public void TransferTrxToContractAccountFailIfNotPayable() .generateDeploySmartContractAndGetTransaction(contractName, address, ABI, code, value, fee, consumeUserResourcePercent, null); byte[] contractAddress = WalletUtil.generateContractAddress(trx); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, deposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, repository, null); Assert.assertNotNull(runtime.getRuntimeError().contains("REVERT")); Assert.assertNull(dbManager.getAccountStore().get(contractAddress)); recoverDeposit(); @@ -168,7 +169,7 @@ public void TransferTrxToContractAccountWhenTriggerAContract() byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, - feeLimit, consumeUserResourcePercent, null, deposit, null); + feeLimit, consumeUserResourcePercent, null, repository, null); String selectorStr = "transferTo(address)"; String params = @@ -180,7 +181,7 @@ public void TransferTrxToContractAccountWhenTriggerAContract() Transaction transaction = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(address, contractAddress, triggerData, triggerCallValue, feeLimit); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction, deposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction, repository, null); Assert.assertNull(runtime.getRuntimeError()); Assert.assertEquals(dbManager.getAccountStore().get(contractAddress).getBalance(), 100 - 5); Assert.assertEquals(dbManager.getAccountStore().get(Hex.decode(TRANSFER_TO)).getBalance(), @@ -249,7 +250,7 @@ public void TransferCallValueTestWhenUsingCallAndCreate() Transaction transaction1 = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(msgSenderAddress, callerAddress, triggerData1, triggerCallValue, feeLimit); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction1, deposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction1, repository, null); Assert.assertNull(runtime.getRuntimeError()); Assert.assertEquals(dbManager.getAccountStore().get(callerAddress).getBalance(), 1000); //Not changed @@ -268,7 +269,7 @@ public void TransferCallValueTestWhenUsingCallAndCreate() Transaction transaction2 = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(msgSenderAddress, callerAddress, triggerData2, triggerCallValue, feeLimit); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction2, deposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction2, repository, null); Assert.assertTrue(runtime.getRuntimeError().contains("REVERT")); Assert.assertEquals(dbManager.getAccountStore().get(callerAddress).getBalance(), 1000); //Not changed @@ -287,7 +288,7 @@ public void TransferCallValueTestWhenUsingCallAndCreate() Transaction transaction3 = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(msgSenderAddress, callerAddress, triggerData3, triggerCallValue, feeLimit); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction3, deposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction3, repository, null); Assert.assertTrue(runtime.getRuntimeError().contains("Invalid operation code: opCode[fe];")); Assert.assertEquals(dbManager.getAccountStore().get(callerAddress).getBalance(), 1000); //Not changed @@ -306,7 +307,7 @@ public void TransferCallValueTestWhenUsingCallAndCreate() Transaction transaction4 = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(msgSenderAddress, callerAddress, triggerData4, triggerCallValue, feeLimit); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction4, deposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction4, repository, null); byte[] createdAddress = convertToTronAddress( new DataWord(runtime.getResult().getHReturn()).getLast20Bytes()); Assert.assertNull(runtime.getRuntimeError()); @@ -327,7 +328,7 @@ public void TransferCallValueTestWhenUsingCallAndCreate() Transaction transaction5 = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(msgSenderAddress, callerAddress, triggerData5, triggerCallValue, feeLimit); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction5, deposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction5, repository, null); byte[] createdAddress2 = convertToTronAddress( new DataWord(runtime.getResult().getHReturn()).getLast20Bytes()); Assert.assertTrue(Hex.toHexString(new DataWord(createdAddress2).getLast20Bytes()) @@ -350,7 +351,7 @@ public void TransferCallValueTestWhenUsingCallAndCreate() Transaction transaction6 = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(msgSenderAddress, callerAddress, triggerData6, triggerCallValue, feeLimit); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction6, deposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction6, repository, null); byte[] createdAddress3 = convertToTronAddress( new DataWord(runtime.getResult().getHReturn()).getLast20Bytes()); Assert.assertTrue(Hex.toHexString(new DataWord(createdAddress2).getLast20Bytes()) @@ -395,7 +396,7 @@ private byte[] deployCalledContract() byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, - feeLimit, consumeUserResourcePercent, null, deposit, null); + feeLimit, consumeUserResourcePercent, null, repository, null); return contractAddress; } @@ -476,13 +477,13 @@ private byte[] deployCallerContract(byte[] calledAddress) long consumeUserResourcePercent = 0; byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, callerAddress, callerABI, - callerCode, value, feeLimit, consumeUserResourcePercent, null, deposit, null); + callerCode, value, feeLimit, consumeUserResourcePercent, null, repository, null); return contractAddress; } private void recoverDeposit() { dbManager = context.getBean(Manager.class); - deposit = DepositImpl.createRoot(dbManager); + repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); } diff --git a/framework/src/test/java/org/tron/common/runtime/TvmTestUtils.java b/framework/src/test/java/org/tron/common/runtime/TvmTestUtils.java index b4eac4936e9..a90010f3043 100644 --- a/framework/src/test/java/org/tron/common/runtime/TvmTestUtils.java +++ b/framework/src/test/java/org/tron/common/runtime/TvmTestUtils.java @@ -10,8 +10,6 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.tron.common.crypto.Hash; -import org.tron.common.storage.Deposit; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.WalletUtil; import org.tron.core.Wallet; import org.tron.core.capsule.BlockCapsule; @@ -23,6 +21,8 @@ import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; import org.tron.core.store.StoreFactory; +import org.tron.core.vm.repository.Repository; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; @@ -45,36 +45,36 @@ public class TvmTestUtils { public static byte[] deployContractWholeProcessReturnContractAddress(String contractName, byte[] callerAddress, String abi, String code, long value, long feeLimit, long consumeUserResourcePercent, - String libraryAddressPair, DepositImpl deposit, BlockCapsule block) + String libraryAddressPair, RepositoryImpl repository, BlockCapsule block) throws ContractExeException, ReceiptCheckErrException, ContractValidateException, VMIllegalException { Transaction trx = generateDeploySmartContractAndGetTransaction(contractName, callerAddress, abi, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair); - processTransactionAndReturnRuntime(trx, deposit, block); + processTransactionAndReturnRuntime(trx, repository, block); return WalletUtil.generateContractAddress(trx); } public static byte[] deployContractWholeProcessReturnContractAddress(String contractName, byte[] callerAddress, String abi, String code, long value, long feeLimit, long consumeUserResourcePercent, - String libraryAddressPair, long tokenValue, long tokenId, DepositImpl deposit, + String libraryAddressPair, long tokenValue, long tokenId, RepositoryImpl repository, BlockCapsule block) throws ContractExeException, ReceiptCheckErrException, ContractValidateException, VMIllegalException { Transaction trx = generateDeploySmartContractAndGetTransaction(contractName, callerAddress, abi, code, value, feeLimit, consumeUserResourcePercent, tokenValue, tokenId, libraryAddressPair); - processTransactionAndReturnRuntime(trx, deposit, block); + processTransactionAndReturnRuntime(trx, repository, block); return WalletUtil.generateContractAddress(trx); } public static Runtime triggerContractWholeProcessReturnContractAddress(byte[] callerAddress, - byte[] contractAddress, byte[] data, long callValue, long feeLimit, DepositImpl deposit, + byte[] contractAddress, byte[] data, long callValue, long feeLimit, RepositoryImpl repository, BlockCapsule block) throws ContractExeException, ReceiptCheckErrException, ContractValidateException, VMIllegalException { Transaction trx = generateTriggerSmartContractAndGetTransaction(callerAddress, contractAddress, data, callValue, feeLimit); - return processTransactionAndReturnRuntime(trx, deposit, block); + return processTransactionAndReturnRuntime(trx, repository, block); } /** @@ -163,16 +163,16 @@ public static Transaction generateDeploySmartContractWithCreatorEnergyLimitAndGe } /** - * use given input Transaction,deposit,block and execute TVM (for both Deploy and Trigger + * use given input Transaction,repository,block and execute TVM (for both Deploy and Trigger * contracts). */ public static Runtime processTransactionAndReturnRuntime(Transaction trx, - Deposit deposit, BlockCapsule block) + Repository repository, BlockCapsule block) throws ContractExeException, ContractValidateException, ReceiptCheckErrException, VMIllegalException { TransactionCapsule trxCap = new TransactionCapsule(trx); - deposit.commit(); + repository.commit(); TransactionTrace trace = new TransactionTrace(trxCap, StoreFactory.getInstance(), new RuntimeImpl()); // init trace.init(block); @@ -203,11 +203,11 @@ public static Runtime processTransactionAndReturnRuntime(Transaction trx, } public static TransactionTrace processTransactionAndReturnTrace(Transaction trx, - DepositImpl deposit, BlockCapsule block) + RepositoryImpl repository, BlockCapsule block) throws ContractExeException, ContractValidateException, ReceiptCheckErrException, VMIllegalException { TransactionCapsule trxCap = new TransactionCapsule(trx); - deposit.commit(); + repository.commit(); TransactionTrace trace = new TransactionTrace(trxCap, StoreFactory.getInstance(), new RuntimeImpl()); // init trace.init(block); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmCompatibleEvmTest.java b/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmCompatibleEvmTest.java index 0b24d357a8a..0f3cae8476a 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmCompatibleEvmTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmCompatibleEvmTest.java @@ -73,7 +73,7 @@ public void testEthRipemd160() throws ContractExeException, ReceiptCheckErrExcep contractName, address, abi, factoryCode, value, feeLimit, consumeUserResourcePercent, null); byte[] factoryAddress = WalletUtil.generateContractAddress(trx); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); // Trigger contract method: getRipemd160() @@ -198,7 +198,7 @@ public void testBlake2f() throws ContractExeException, ReceiptCheckErrException, contractName, address, abi, factoryCode, value, feeLimit, consumeUserResourcePercent, null); byte[] factoryAddress = WalletUtil.generateContractAddress(trx); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); // Trigger contract method: callF() @@ -244,7 +244,7 @@ public void testGasPrice() throws ContractExeException, ReceiptCheckErrException contractName, address, abi, factoryCode, value, feeLimit, consumeUserResourcePercent, null); byte[] factoryAddress = WalletUtil.generateContractAddress(trx); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); // Trigger contract method: getprice() @@ -279,7 +279,7 @@ public void testChainId() throws ContractExeException, ReceiptCheckErrException, Protocol.Transaction trx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( contractName, address, "[]", contractCode, 0, feeLimit, 0, null); byte[] factoryAddress = WalletUtil.generateContractAddress(trx); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); // Trigger contract method: getChainId() diff --git a/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmLondonTest.java b/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmLondonTest.java index c6b3ec10a98..42725d1cbd7 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmLondonTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmLondonTest.java @@ -61,7 +61,7 @@ public void testBaseFee() throws ContractExeException, ReceiptCheckErrException, contractName, address, abi, factoryCode, value, feeLimit, consumeUserResourcePercent, null); byte[] factoryAddress = WalletUtil.generateContractAddress(trx); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); // Trigger contract method: getbasefee() @@ -103,7 +103,7 @@ public void testStartWithEF() throws ContractExeException, ReceiptCheckErrExcept Protocol.Transaction trx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( contractName, address, abi, factoryCode, value, feeLimit, consumeUserResourcePercent, null); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootRepository, null); Assert.assertNotNull(runtime.getRuntimeError()); } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java index 843a102bfff..f8a4f1ef0bb 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java @@ -26,7 +26,6 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.RuntimeImpl; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.Commons; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; @@ -155,7 +154,6 @@ public void testSuccess() { new RuntimeImpl()); dbManager.consumeBandwidth(trxCap, trace); BlockCapsule blockCapsule = null; - DepositImpl deposit = DepositImpl.createRoot(dbManager); trace.init(blockCapsule); trace.exec(); trace.finalization(); @@ -219,7 +217,6 @@ private byte[] createContract() new RuntimeImpl()); dbManager.consumeBandwidth(trxCap, trace); BlockCapsule blockCapsule = null; - DepositImpl deposit = DepositImpl.createRoot(dbManager); trace.init(blockCapsule); trace.exec(); trace.finalization(); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java index 07906ef23f4..f378c01bceb 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java @@ -26,7 +26,6 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.RuntimeImpl; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.Commons; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; @@ -222,7 +221,6 @@ private byte[] createContract() new RuntimeImpl()); dbManager.consumeBandwidth(trxCap, trace); BlockCapsule blockCapsule = null; - DepositImpl deposit = DepositImpl.createRoot(dbManager); trace.init(blockCapsule); trace.exec(); trace.finalization(); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java index 2c9bda15e88..5e6663e8cfe 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java @@ -26,7 +26,6 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.RuntimeImpl; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.Commons; import org.tron.common.utils.FileUtil; import org.tron.core.ChainBaseManager; @@ -153,7 +152,6 @@ public void testSuccess() { new RuntimeImpl()); dbManager.consumeBandwidth(trxCap, trace); BlockCapsule blockCapsule = null; - DepositImpl deposit = DepositImpl.createRoot(dbManager); trace.init(blockCapsule); trace.exec(); @@ -187,7 +185,7 @@ public void testSuccessNoBandd() { dbManager.consumeBandwidth(trxCap, trace); long bandWidth = trxCap.getSerializedSize() + Constant.MAX_RESULT_SIZE_IN_TX; BlockCapsule blockCapsule = null; - DepositImpl deposit = DepositImpl.createRoot(dbManager); + trace.init(blockCapsule); trace.exec(); trace.finalization(); @@ -242,7 +240,6 @@ private byte[] createContract() new RuntimeImpl()); dbManager.consumeBandwidth(trxCap, trace); BlockCapsule blockCapsule = null; - DepositImpl deposit = DepositImpl.createRoot(dbManager); trace.init(blockCapsule); trace.exec(); trace.finalization(); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java index 2ac91063792..37e21b086ea 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java @@ -26,7 +26,6 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.RuntimeImpl; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.Commons; import org.tron.common.utils.FileUtil; import org.tron.core.ChainBaseManager; @@ -167,7 +166,7 @@ public void testSuccess() { new RuntimeImpl()); dbManager.consumeBandwidth(trxCap, trace); BlockCapsule blockCapsule = null; - DepositImpl deposit = DepositImpl.createRoot(dbManager); + trace.init(blockCapsule); trace.exec(); trace.finalization(); @@ -206,7 +205,6 @@ public void testSuccessNoBandWidth() { dbManager.consumeBandwidth(trxCap, trace); long bandWidth = trxCap.getSerializedSize() + Constant.MAX_RESULT_SIZE_IN_TX; BlockCapsule blockCapsule = null; - DepositImpl deposit = DepositImpl.createRoot(dbManager); trace.init(blockCapsule); trace.exec(); trace.finalization(); @@ -273,7 +271,7 @@ private byte[] createContract() new RuntimeImpl()); dbManager.consumeBandwidth(trxCap, trace); BlockCapsule blockCapsule = null; - DepositImpl deposit = DepositImpl.createRoot(dbManager); + trace.init(blockCapsule); trace.exec(); trace.finalization(); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java index 3af76597eb4..200df06f084 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java @@ -15,7 +15,6 @@ import org.tron.common.crypto.ECKey; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; @@ -30,6 +29,8 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; +import org.tron.core.store.StoreFactory; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction; import stest.tron.wallet.common.client.utils.AbiUtil; @@ -52,7 +53,7 @@ public class BatchSendTest { private static Manager dbManager; private static TronApplicationContext context; private static Application appT; - private static DepositImpl deposit; + private static RepositoryImpl repository; private static AccountCapsule ownerCapsule; static { @@ -62,10 +63,10 @@ public class BatchSendTest { OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; TRANSFER_TO = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; dbManager = context.getBean(Manager.class); - deposit = DepositImpl.createRoot(dbManager); - deposit.createAccount(Hex.decode(TRANSFER_TO), AccountType.Normal); - deposit.addBalance(Hex.decode(TRANSFER_TO), 10); - deposit.commit(); + repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + repository.createAccount(Hex.decode(TRANSFER_TO), AccountType.Normal); + repository.addBalance(Hex.decode(TRANSFER_TO), 10); + repository.commit(); ownerCapsule = new AccountCapsule( ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), @@ -115,7 +116,7 @@ public void TransferTokenTest() ContractValidateException { // 1. Deploy*/ byte[] contractAddress = deployTransferContract(); - deposit.commit(); + repository.commit(); Assert.assertEquals(1000, dbManager.getAccountStore().get(contractAddress).getBalance()); @@ -183,7 +184,7 @@ private byte[] deployTransferContract() byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, null, tokenValue, tokenId, - deposit, null); + repository, null); return contractAddress; } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/ChargeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/ChargeTest.java index 8538209f609..91378fdcb64 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/ChargeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/ChargeTest.java @@ -13,7 +13,6 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -24,6 +23,8 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; +import org.tron.core.store.StoreFactory; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; @Slf4j @@ -32,7 +33,7 @@ public class ChargeTest { private Manager dbManager; private TronApplicationContext context; - private DepositImpl deposit; + private RepositoryImpl repository; private String dbPath = "output_ChargeTest"; private String OWNER_ADDRESS; private Application AppT; @@ -49,10 +50,10 @@ public void init() { AppT = ApplicationFactory.create(context); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; dbManager = context.getBean(Manager.class); - deposit = DepositImpl.createRoot(dbManager); - deposit.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); - deposit.addBalance(Hex.decode(OWNER_ADDRESS), totalBalance); - deposit.commit(); + repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); + repository.addBalance(Hex.decode(OWNER_ADDRESS), totalBalance); + repository.commit(); } // pragma solidity ^0.4.16; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java index 9b470f2df50..137bb180dc0 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java @@ -144,7 +144,7 @@ public void testCreate2() null); byte[] factoryAddress = WalletUtil.generateContractAddress(trx); for (int i = 0; i < 3; i++) { - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootRepository, null); if (runtime.getRuntimeError() == null) { break; } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/CreateContractSuicideTest.java b/framework/src/test/java/org/tron/common/runtime/vm/CreateContractSuicideTest.java index bf0de449cbd..9fe5ac1eed1 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/CreateContractSuicideTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/CreateContractSuicideTest.java @@ -7,14 +7,15 @@ import org.testng.Assert; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.DepositImpl; import org.tron.core.config.Parameter.ForkBlockVersionEnum; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; +import org.tron.core.store.StoreFactory; import org.tron.core.vm.config.ConfigLoader; import org.tron.core.vm.program.Program.OutOfEnergyException; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.Transaction; @Slf4j @@ -143,26 +144,26 @@ public void testAAfterAllowMultiSignProposal() Transaction aTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( "testA", address, abi, aCode, value, fee, consumeUserResourcePercent, null, engeryLimit); - Runtime aRuntime = TvmTestUtils - .processTransactionAndReturnRuntime(aTrx, DepositImpl.createRoot(manager), null); + Runtime aRuntime = TvmTestUtils.processTransactionAndReturnRuntime(aTrx, + RepositoryImpl.createRoot(StoreFactory.getInstance()), null); Assert.assertEquals(aRuntime.getRuntimeError(), "REVERT opcode executed"); Transaction bTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( "testB", address, abi, bCode, value, fee, consumeUserResourcePercent, null, engeryLimit); - Runtime bRuntime = TvmTestUtils - .processTransactionAndReturnRuntime(bTrx, DepositImpl.createRoot(manager), null); + Runtime bRuntime = TvmTestUtils.processTransactionAndReturnRuntime(bTrx, + RepositoryImpl.createRoot(StoreFactory.getInstance()), null); Assert.assertEquals(bRuntime.getRuntimeError(), "REVERT opcode executed"); Transaction cTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( "testC", address, abi, cCode, value, fee, consumeUserResourcePercent, null, engeryLimit); - Runtime cRuntime = TvmTestUtils - .processTransactionAndReturnRuntime(cTrx, DepositImpl.createRoot(manager), null); + Runtime cRuntime = TvmTestUtils.processTransactionAndReturnRuntime(cTrx, + RepositoryImpl.createRoot(StoreFactory.getInstance()), null); Assert.assertTrue(cRuntime.getResult().getException() instanceof OutOfEnergyException); Transaction dTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( "testC", address, abi, dCode, value, fee, consumeUserResourcePercent, null, engeryLimit); - Runtime dRuntime = TvmTestUtils - .processTransactionAndReturnRuntime(dTrx, DepositImpl.createRoot(manager), null); + Runtime dRuntime = TvmTestUtils.processTransactionAndReturnRuntime(dTrx, + RepositoryImpl.createRoot(StoreFactory.getInstance()), null); Assert.assertEquals(dRuntime.getRuntimeError(), "REVERT opcode executed"); } @@ -179,26 +180,26 @@ public void testABeforeAllowMultiSignProposal() byte[] address = Hex.decode(OWNER_ADDRESS); Transaction aTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( "testA", address, abi, aCode, value, fee, consumeUserResourcePercent, null, engeryLimit); - Runtime aRuntime = TvmTestUtils - .processTransactionAndReturnRuntime(aTrx, DepositImpl.createRoot(manager), null); + Runtime aRuntime = TvmTestUtils.processTransactionAndReturnRuntime(aTrx, + RepositoryImpl.createRoot(StoreFactory.getInstance()), null); Assert.assertEquals(aRuntime.getRuntimeError(), "Unknown Exception"); Transaction bTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( "testB", address, abi, bCode, value, fee, consumeUserResourcePercent, null, engeryLimit); - Runtime bRuntime = TvmTestUtils - .processTransactionAndReturnRuntime(bTrx, DepositImpl.createRoot(manager), null); + Runtime bRuntime = TvmTestUtils.processTransactionAndReturnRuntime(bTrx, + RepositoryImpl.createRoot(StoreFactory.getInstance()), null); Assert.assertEquals(bRuntime.getRuntimeError(), "REVERT opcode executed"); Transaction cTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( "testC", address, abi, cCode, value, fee, consumeUserResourcePercent, null, engeryLimit); - Runtime cRuntime = TvmTestUtils - .processTransactionAndReturnRuntime(cTrx, DepositImpl.createRoot(manager), null); + Runtime cRuntime = TvmTestUtils.processTransactionAndReturnRuntime(cTrx, + RepositoryImpl.createRoot(StoreFactory.getInstance()), null); Assert.assertTrue(cRuntime.getResult().getException() instanceof OutOfEnergyException); Transaction dTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( "testC", address, abi, dCode, value, fee, consumeUserResourcePercent, null, engeryLimit); - Runtime dRuntime = TvmTestUtils - .processTransactionAndReturnRuntime(dTrx, DepositImpl.createRoot(manager), null); + Runtime dRuntime = TvmTestUtils.processTransactionAndReturnRuntime(dTrx, + RepositoryImpl.createRoot(StoreFactory.getInstance()), null); Assert.assertEquals(dRuntime.getRuntimeError(), "REVERT opcode executed"); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java index a2fbb5f0816..5fa63096b9f 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java @@ -13,7 +13,6 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -24,9 +23,11 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; +import org.tron.core.store.StoreFactory; import org.tron.core.vm.program.Program.IllegalOperationException; import org.tron.core.vm.program.Program.OutOfMemoryException; import org.tron.core.vm.program.Program.PrecompiledContractException; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; @@ -36,7 +37,7 @@ public class EnergyWhenAssertStyleTest { private Manager dbManager; private TronApplicationContext context; - private DepositImpl deposit; + private RepositoryImpl repository; private String dbPath = "output_EnergyWhenAssertStyleTest"; private String OWNER_ADDRESS; private Application AppT; @@ -53,10 +54,10 @@ public void init() { AppT = ApplicationFactory.create(context); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; dbManager = context.getBean(Manager.class); - deposit = DepositImpl.createRoot(dbManager); - deposit.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); - deposit.addBalance(Hex.decode(OWNER_ADDRESS), totalBalance); - deposit.commit(); + repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); + repository.addBalance(Hex.decode(OWNER_ADDRESS), totalBalance); + repository.commit(); } // An assert-style exception is generated in the following situations: diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java index ef9fc05f159..5ce9729393f 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java @@ -13,7 +13,6 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -24,7 +23,9 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; +import org.tron.core.store.StoreFactory; import org.tron.core.vm.program.Program.OutOfEnergyException; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; @Slf4j @@ -33,7 +34,7 @@ public class EnergyWhenRequireStyleTest { private Manager dbManager; private TronApplicationContext context; - private DepositImpl deposit; + private RepositoryImpl repository; private String dbPath = "output_EnergyWhenRequireStyleTest"; private String OWNER_ADDRESS; private Application AppT; @@ -50,10 +51,10 @@ public void init() { AppT = ApplicationFactory.create(context); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; dbManager = context.getBean(Manager.class); - deposit = DepositImpl.createRoot(dbManager); - deposit.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); - deposit.addBalance(Hex.decode(OWNER_ADDRESS), totalBalance); - deposit.commit(); + repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); + repository.addBalance(Hex.decode(OWNER_ADDRESS), totalBalance); + repository.commit(); } // A require-style exception is generated in the following situations: diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java index a012617fb12..b7384f53902 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java @@ -12,7 +12,6 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -23,6 +22,8 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; +import org.tron.core.store.StoreFactory; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; @Slf4j @@ -30,7 +31,7 @@ public class EnergyWhenSendAndTransferTest { private Manager dbManager; private TronApplicationContext context; - private DepositImpl deposit; + private RepositoryImpl repository; private String dbPath = "output_EnergyWhenSendAndTransferTest"; private String OWNER_ADDRESS; private Application AppT; @@ -46,10 +47,10 @@ public void init() { AppT = ApplicationFactory.create(context); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; dbManager = context.getBean(Manager.class); - deposit = DepositImpl.createRoot(dbManager); - deposit.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); - deposit.addBalance(Hex.decode(OWNER_ADDRESS), totalBalance); - deposit.commit(); + repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); + repository.addBalance(Hex.decode(OWNER_ADDRESS), totalBalance); + repository.commit(); } // solidity for callValueTest @@ -100,7 +101,7 @@ public void callValueTest() long expectEnergyUsageTotal = 174639; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); byte[] contractAddress = result.getContractAddress(); - Assert.assertEquals(deposit.getAccount(contractAddress).getBalance(), value); + Assert.assertEquals(repository.getAccount(contractAddress).getBalance(), value); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - value - expectEnergyUsageTotal * 100); @@ -176,7 +177,7 @@ public void sendTest() long expectEnergyUsageTotal = 140194; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); byte[] contractAddress = result.getContractAddress(); - Assert.assertEquals(deposit.getAccount(contractAddress).getBalance(), value); + Assert.assertEquals(repository.getAccount(contractAddress).getBalance(), value); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - value - expectEnergyUsageTotal * 100); @@ -190,7 +191,7 @@ public void sendTest() Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); Assert.assertEquals(result.getRuntime().getResult().getException(), null); Assert.assertEquals(result.getRuntime().getResult().isRevert(), false); - Assert.assertEquals(deposit.getAccount(contractAddress).getBalance(), value); + Assert.assertEquals(repository.getAccount(contractAddress).getBalance(), value); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - value - (expectEnergyUsageTotal + expectEnergyUsageTotal2) * 100); } @@ -211,7 +212,7 @@ public void transferTest() long expectEnergyUsageTotal = 140194; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); byte[] contractAddress = result.getContractAddress(); - Assert.assertEquals(deposit.getAccount(contractAddress).getBalance(), value); + Assert.assertEquals(repository.getAccount(contractAddress).getBalance(), value); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - value - expectEnergyUsageTotal * 100); @@ -225,7 +226,7 @@ public void transferTest() Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); Assert.assertEquals(result.getRuntime().getResult().getException(), null); Assert.assertEquals(result.getRuntime().getResult().isRevert(), true); - Assert.assertEquals(deposit.getAccount(contractAddress).getBalance(), value); + Assert.assertEquals(repository.getAccount(contractAddress).getBalance(), value); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - value - (expectEnergyUsageTotal + expectEnergyUsageTotal2) * 100); } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java index f4305769751..73b51c803f8 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java @@ -12,7 +12,6 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -23,8 +22,10 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; +import org.tron.core.store.StoreFactory; import org.tron.core.vm.program.Program.OutOfEnergyException; import org.tron.core.vm.program.Program.OutOfTimeException; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; @Slf4j @@ -32,7 +33,7 @@ public class EnergyWhenTimeoutStyleTest { private Manager dbManager; private TronApplicationContext context; - private DepositImpl deposit; + private RepositoryImpl repository; private String dbPath = "output_CPUTimeTest"; private String OWNER_ADDRESS; private Application AppT; @@ -50,10 +51,10 @@ public void init() { AppT = ApplicationFactory.create(context); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; dbManager = context.getBean(Manager.class); - deposit = DepositImpl.createRoot(dbManager); - deposit.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); - deposit.addBalance(Hex.decode(OWNER_ADDRESS), totalBalance); - deposit.commit(); + repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); + repository.addBalance(Hex.decode(OWNER_ADDRESS), totalBalance); + repository.commit(); } // solidity for endlessLoopTest diff --git a/framework/src/test/java/org/tron/common/runtime/vm/ExtCodeHashTest.java b/framework/src/test/java/org/tron/common/runtime/vm/ExtCodeHashTest.java index f3a3c13f8bd..8acc8ed494b 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/ExtCodeHashTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/ExtCodeHashTest.java @@ -50,7 +50,7 @@ public void testExtCodeHash() contractName, address, ABI, factoryCode, value, fee, consumeUserResourcePercent, null); byte[] factoryAddress = WalletUtil.generateContractAddress(trx); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); // Trigger contract method: getCodeHashByAddr(address) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java index 3b3168132f2..38928ab002e 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java @@ -20,8 +20,6 @@ import org.tron.common.runtime.RuntimeImpl; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.Deposit; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.Commons; import org.tron.common.utils.FastByteComparisons; import org.tron.common.utils.FileUtil; @@ -43,6 +41,8 @@ import org.tron.core.vm.EnergyCost; import org.tron.core.vm.config.ConfigLoader; import org.tron.core.vm.config.VMConfig; +import org.tron.core.vm.repository.Repository; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol; import org.tron.protos.Protocol.Transaction.Result.contractResult; import stest.tron.wallet.common.client.utils.AbiUtil; @@ -124,7 +124,7 @@ public class FreezeTest { private static TronApplicationContext context; private static Manager manager; private static byte[] owner; - private static Deposit rootDeposit; + private static Repository rootRepository; @Before public void init() throws Exception { @@ -134,10 +134,10 @@ public void init() throws Exception { manager = context.getBean(Manager.class); owner = Hex.decode(Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"); - rootDeposit = DepositImpl.createRoot(manager); - rootDeposit.createAccount(owner, Protocol.AccountType.Normal); - rootDeposit.addBalance(owner, 900_000_000_000_000_000L); - rootDeposit.commit(); + rootRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + rootRepository.createAccount(owner, Protocol.AccountType.Normal); + rootRepository.addBalance(owner, 900_000_000_000_000_000L); + rootRepository.commit(); ConfigLoader.disable = true; manager.getDynamicPropertiesStore().saveAllowTvmFreeze(1); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/InternalTransactionCallTest.java b/framework/src/test/java/org/tron/common/runtime/vm/InternalTransactionCallTest.java index 13269a783d0..18a279f8292 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/InternalTransactionCallTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/InternalTransactionCallTest.java @@ -12,7 +12,6 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -23,6 +22,8 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; +import org.tron.core.store.StoreFactory; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; @Slf4j @@ -31,7 +32,7 @@ public class InternalTransactionCallTest { private Runtime runtime; private Manager dbManager; private TronApplicationContext context; - private DepositImpl deposit; + private RepositoryImpl repository; private String dbPath = "output_InternalTransactionCallTest"; private String OWNER_ADDRESS; private Application AppT; @@ -49,9 +50,9 @@ public void init() { AppT = ApplicationFactory.create(context); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; dbManager = context.getBean(Manager.class); - deposit = DepositImpl.createRoot(dbManager); - deposit.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); - deposit.addBalance(Hex.decode(OWNER_ADDRESS), 100000000); + repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); + repository.addBalance(Hex.decode(OWNER_ADDRESS), 100000000); } @@ -94,13 +95,13 @@ public void callTest() + "0000000000000000000000000000000000000000000000000000000000000003"; byte[] triggerData = TvmTestUtils.parseAbi("callTest(address,uint256)", params); TvmTestUtils.triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), - contractAAddress, triggerData, 0, 1000000000, deposit, null); + contractAAddress, triggerData, 0, 1000000000, repository, null); /* =========== CALL numberForB() to check A's numberForB =================================== */ byte[] triggerData2 = TvmTestUtils.parseAbi("numberForB()", ""); runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), - contractAAddress, triggerData2, 0, 1000000000, deposit, null); + contractAAddress, triggerData2, 0, 1000000000, repository, null); // A should not be changed Assert.assertEquals(Hex.toHexString(runtime.getResult().getHReturn()), "0000000000000000000000000000000000000000000000000000000000000000"); @@ -109,7 +110,7 @@ public void callTest() byte[] triggerData3 = TvmTestUtils.parseAbi("senderForB()", ""); runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), - contractAAddress, triggerData3, 0, 1000000000, deposit, null); + contractAAddress, triggerData3, 0, 1000000000, repository, null); // A should be changed Assert.assertEquals(Hex.toHexString(runtime.getResult().getHReturn()), "0000000000000000000000000000000000000000000000000000000000000000"); @@ -118,7 +119,7 @@ public void callTest() byte[] triggerData4 = TvmTestUtils.parseAbi("numberForB()", ""); runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), - contractBAddress, triggerData4, 0, 1000000000, deposit, null); + contractBAddress, triggerData4, 0, 1000000000, repository, null); // B's numberForB should be changed to 3 Assert.assertEquals(Hex.toHexString(runtime.getResult().getHReturn()), "0000000000000000000000000000000000000000000000000000000000000003"); @@ -127,7 +128,7 @@ public void callTest() byte[] triggerData5 = TvmTestUtils.parseAbi("senderForB()", ""); runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), - contractBAddress, triggerData5, 0, 1000000000, deposit, null); + contractBAddress, triggerData5, 0, 1000000000, repository, null); // B 's senderForB should be A Assert.assertEquals(Hex.toHexString(runtime.getResult().getHReturn()), Hex.toHexString(new DataWord(new DataWord(contractAAddress).getLast20Bytes()).getData())); @@ -152,13 +153,13 @@ public void delegateCallTest() byte[] triggerData = TvmTestUtils.parseAbi("delegatecallTest(address,uint256)", params); TvmTestUtils.triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), - contractAAddress, triggerData, 0, 1000000000, deposit, null); + contractAAddress, triggerData, 0, 1000000000, repository, null); /* ============ CALL numberForB() to check A's numberForB =================================== */ byte[] triggerData2 = TvmTestUtils.parseAbi("numberForB()", ""); runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), - contractAAddress, triggerData2, 0, 1000000000, deposit, null); + contractAAddress, triggerData2, 0, 1000000000, repository, null); // A should be changed to 3 Assert.assertEquals(Hex.toHexString(runtime.getResult().getHReturn()), "0000000000000000000000000000000000000000000000000000000000000003"); @@ -167,7 +168,7 @@ public void delegateCallTest() byte[] triggerData3 = TvmTestUtils.parseAbi("senderForB()", ""); runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), - contractAAddress, triggerData3, 0, 1000000000, deposit, null); + contractAAddress, triggerData3, 0, 1000000000, repository, null); // A's senderForB should be changed to caller's contract Address (OWNER_ADDRESS) Assert.assertEquals(Hex.toHexString(runtime.getResult().getHReturn()), Hex.toHexString(new DataWord(new DataWord(OWNER_ADDRESS).getLast20Bytes()).getData())); @@ -176,7 +177,7 @@ public void delegateCallTest() byte[] triggerData4 = TvmTestUtils.parseAbi("numberForB()", ""); runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), - contractBAddress, triggerData4, 0, 1000000000, deposit, null); + contractBAddress, triggerData4, 0, 1000000000, repository, null); // B's numberForB should not be changed Assert.assertEquals(Hex.toHexString(runtime.getResult().getHReturn()), "0000000000000000000000000000000000000000000000000000000000000000"); @@ -185,7 +186,7 @@ public void delegateCallTest() byte[] triggerData5 = TvmTestUtils.parseAbi("senderForB()", ""); runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), - contractBAddress, triggerData5, 0, 1000000000, deposit, null); + contractBAddress, triggerData5, 0, 1000000000, repository, null); // B 's senderForB should not be changed Assert.assertEquals(Hex.toHexString(runtime.getResult().getHReturn()), "0000000000000000000000000000000000000000000000000000000000000000"); @@ -210,13 +211,13 @@ public void callCodeTest() + "0000000000000000000000000000000000000000000000000000000000000003"; byte[] triggerData = TvmTestUtils.parseAbi("callcodeTest(address,uint256)", params); TvmTestUtils.triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), - contractAAddress, triggerData, 0, 1000000000, deposit, null); + contractAAddress, triggerData, 0, 1000000000, repository, null); /* ========== CALL numberForB() to check A's numberForB =================================== */ byte[] triggerData2 = TvmTestUtils.parseAbi("numberForB()", ""); runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), - contractAAddress, triggerData2, 0, 1000000000, deposit, null); + contractAAddress, triggerData2, 0, 1000000000, repository, null); // A should be changed to 3 Assert.assertEquals(Hex.toHexString(runtime.getResult().getHReturn()), "0000000000000000000000000000000000000000000000000000000000000003"); @@ -225,7 +226,7 @@ public void callCodeTest() byte[] triggerData3 = TvmTestUtils.parseAbi("senderForB()", ""); runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), - contractAAddress, triggerData3, 0, 1000000000, deposit, null); + contractAAddress, triggerData3, 0, 1000000000, repository, null); // A's senderForB should be changed to A's contract Address Assert.assertEquals(Hex.toHexString(runtime.getResult().getHReturn()), Hex.toHexString(new DataWord(new DataWord(contractAAddress).getLast20Bytes()).getData())); @@ -234,7 +235,7 @@ public void callCodeTest() byte[] triggerData4 = TvmTestUtils.parseAbi("numberForB()", ""); runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), - contractBAddress, triggerData4, 0, 1000000000, deposit, null); + contractBAddress, triggerData4, 0, 1000000000, repository, null); // B's numberForB should not be changed Assert.assertEquals(Hex.toHexString(runtime.getResult().getHReturn()), "0000000000000000000000000000000000000000000000000000000000000000"); @@ -243,7 +244,7 @@ public void callCodeTest() byte[] triggerData5 = TvmTestUtils.parseAbi("senderForB()", ""); runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), - contractBAddress, triggerData5, 0, 1000000000, deposit, null); + contractBAddress, triggerData5, 0, 1000000000, repository, null); // B 's senderForB should not be changed Assert.assertEquals(Hex.toHexString(runtime.getResult().getHReturn()), "0000000000000000000000000000000000000000000000000000000000000000"); @@ -306,7 +307,7 @@ public byte[] deployAContractandGetItsAddress() byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, - feeLimit, consumeUserResourcePercent, libraryAddressPair, deposit, null); + feeLimit, consumeUserResourcePercent, libraryAddressPair, repository, null); return contractAddress; } @@ -343,7 +344,7 @@ public byte[] deployBContractAndGetItsAddress() byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, - feeLimit, consumeUserResourcePercent, libraryAddressPair, deposit, null); + feeLimit, consumeUserResourcePercent, libraryAddressPair, repository, null); return contractAddress; } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/IsContractTest.java b/framework/src/test/java/org/tron/common/runtime/vm/IsContractTest.java index cd5b6566646..d5d6a18b031 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/IsContractTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/IsContractTest.java @@ -170,7 +170,7 @@ public void testIsContract() null); byte[] factoryAddress = WalletUtil.generateContractAddress(trx); String factoryAddressStr = StringUtil.encode58Check(factoryAddress); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); trx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( @@ -178,7 +178,7 @@ public void testIsContract() null); byte[] factoryAddressOther = WalletUtil.generateContractAddress(trx); String factoryAddressStrOther = StringUtil.encode58Check(factoryAddressOther); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); // Trigger contract method: isTest(address) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/IsSRCandidateTest.java b/framework/src/test/java/org/tron/common/runtime/vm/IsSRCandidateTest.java index 46445e92826..272853dc6c9 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/IsSRCandidateTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/IsSRCandidateTest.java @@ -146,7 +146,7 @@ public void testIsSRCandidate() contractName, address, abi, factoryCode, value, fee, consumeUserResourcePercent, null); byte[] factoryAddress = WalletUtil.generateContractAddress(trx); String factoryAddressStr = StringUtil.encode58Check(factoryAddress); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); // Trigger contract method: isSRCandidateTest(address) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/IstanbulTest.java b/framework/src/test/java/org/tron/common/runtime/vm/IstanbulTest.java index 015f0f0e5e2..85fb918376d 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/IstanbulTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/IstanbulTest.java @@ -71,7 +71,7 @@ public void istanbulSelfBalanceChainIdTest() contractName, address, abi, factoryCode, value, fee, consumeUserResourcePercent, null); byte[] istanbulAddress = WalletUtil.generateContractAddress(tx); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(tx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(tx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); // SELFBALANCE Test @@ -217,7 +217,7 @@ public void altBn128AddMulEnergyChangeTest() contractName, address, abi, factoryCode, value, fee, consumeUserResourcePercent, null); byte[] istanbulAddress = WalletUtil.generateContractAddress(tx); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(tx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(tx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); // bn128 add @@ -447,7 +447,7 @@ public void altBn128PairingEnergyChangeTest() contractName, address, abi, factoryCode, value, fee, consumeUserResourcePercent, null); byte[] istanbulAddress = WalletUtil.generateContractAddress(tx); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(tx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(tx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); // bn128 add diff --git a/framework/src/test/java/org/tron/common/runtime/vm/DepositTest.java b/framework/src/test/java/org/tron/common/runtime/vm/RepositoryTest.java similarity index 95% rename from framework/src/test/java/org/tron/common/runtime/vm/DepositTest.java rename to framework/src/test/java/org/tron/common/runtime/vm/RepositoryTest.java index e88e2788f9d..6323ef4aa40 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/DepositTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/RepositoryTest.java @@ -14,8 +14,6 @@ import org.tron.common.runtime.Runtime; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.Deposit; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; import org.tron.common.utils.WalletUtil; import org.tron.core.Constant; @@ -28,17 +26,20 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; +import org.tron.core.store.StoreFactory; +import org.tron.core.vm.repository.Repository; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction; @Slf4j -public class DepositTest { +public class RepositoryTest { private Manager manager; private TronApplicationContext context; private String dbPath = "output_DepostitTest"; private String OWNER_ADDRESS; - private Deposit rootDeposit; + private Repository rootRepository; @Before public void init() { @@ -46,10 +47,10 @@ public void init() { context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; manager = context.getBean(Manager.class); - rootDeposit = DepositImpl.createRoot(manager); - rootDeposit.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); - rootDeposit.addBalance(Hex.decode(OWNER_ADDRESS), 30000000000000L); - rootDeposit.commit(); + rootRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + rootRepository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); + rootRepository.addBalance(Hex.decode(OWNER_ADDRESS), 30000000000000L); + rootRepository.commit(); } /* pragma solidity ^0.4.0; @@ -178,16 +179,15 @@ public void loopCallTest() Transaction aTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( contractA, address, aABI, aCode, value, fee, consumeUserResourcePercent, null, engeryLiimt); - Runtime runtime = TvmTestUtils - .processTransactionAndReturnRuntime(aTrx, DepositImpl.createRoot(manager), - null); + Runtime runtime = TvmTestUtils.processTransactionAndReturnRuntime(aTrx, + RepositoryImpl.createRoot(StoreFactory.getInstance()), null); Assert.assertNull(runtime.getRuntimeError()); Transaction bTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( contractB, address, bABI, bCode, value, fee, consumeUserResourcePercent, null, engeryLiimt); - runtime = TvmTestUtils - .processTransactionAndReturnRuntime(bTrx, DepositImpl.createRoot(manager), null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(bTrx, + RepositoryImpl.createRoot(StoreFactory.getInstance()), null); Assert.assertNull(runtime.getRuntimeError()); byte[] aAddress = WalletUtil.generateContractAddress(aTrx); @@ -334,16 +334,15 @@ public void loopCallTestOldVersion() Transaction aTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( contractA, address, aABI, aCode, value, fee, consumeUserResourcePercent, null); - Deposit rootDeposit = DepositImpl.createRoot(manager); - Runtime runtime = TvmTestUtils.processTransactionAndReturnRuntime(aTrx, rootDeposit, - null); + Repository rootRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + Runtime runtime = TvmTestUtils.processTransactionAndReturnRuntime(aTrx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); Transaction bTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( contractB, address, bABI, bCode, value, fee, consumeUserResourcePercent, null); - rootDeposit = DepositImpl.createRoot(manager); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(bTrx, rootDeposit, null); + rootRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(bTrx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); byte[] aAddress = WalletUtil.generateContractAddress(aTrx); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/RewardBalanceTest.java b/framework/src/test/java/org/tron/common/runtime/vm/RewardBalanceTest.java index 5fc95be728f..66d58871156 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/RewardBalanceTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/RewardBalanceTest.java @@ -149,7 +149,7 @@ public void testRewardBalance() null); byte[] factoryAddress = WalletUtil.generateContractAddress(trx); String factoryAddressStr = StringUtil.encode58Check(factoryAddress); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); // Trigger contract method: rewardBalanceTest(address) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/StorageTest.java b/framework/src/test/java/org/tron/common/runtime/vm/StorageTest.java index f4f339eb43e..fcef572ea99 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/StorageTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/StorageTest.java @@ -9,21 +9,21 @@ import org.tron.common.parameter.CommonParameter; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.Deposit; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.WalletUtil; import org.tron.core.config.Parameter.ForkBlockVersionConsts; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; +import org.tron.core.store.StoreFactory; import org.tron.core.vm.config.VMConfig; +import org.tron.core.vm.repository.Repository; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.Transaction; @Slf4j public class StorageTest extends VMTestBase { - @Test public void writeAndCommit() { byte[] address = Hex.decode(OWNER_ADDRESS); @@ -32,25 +32,25 @@ public void writeAndCommit() { DataWord nullKey = new DataWord("nullkey".getBytes()); DataWord nullValue = new DataWord(0); - rootDeposit.putStorageValue(address, storageKey1, storageVal1); - rootDeposit.putStorageValue(address, nullKey, nullValue); + rootRepository.putStorageValue(address, storageKey1, storageVal1); + rootRepository.putStorageValue(address, nullKey, nullValue); // test cache - Assert.assertEquals(rootDeposit.getStorageValue(address, storageKey1), storageVal1); - Assert.assertEquals(rootDeposit.getStorageValue(address, nullKey), nullValue); - rootDeposit.commit(); + Assert.assertEquals(rootRepository.getStorageValue(address, storageKey1), storageVal1); + Assert.assertEquals(rootRepository.getStorageValue(address, nullKey), nullValue); + rootRepository.commit(); // use a new rootDeposit - Deposit deposit1 = DepositImpl.createRoot(manager); - Assert.assertEquals(deposit1.getStorageValue(address, storageKey1), storageVal1); - Assert.assertNull(deposit1.getStorageValue(address, nullKey)); + Repository repository1 = RepositoryImpl.createRoot(StoreFactory.getInstance()); + Assert.assertEquals(repository1.getStorageValue(address, storageKey1), storageVal1); + Assert.assertNull(repository1.getStorageValue(address, nullKey)); // delete key - deposit1.putStorageValue(address, storageKey1, nullValue); - Assert.assertNotNull(deposit1.getStorageValue(address, storageKey1)); - deposit1.commit(); - Deposit deposit2 = DepositImpl.createRoot(manager); - Assert.assertNull(deposit2.getStorageValue(address, storageKey1)); + repository1.putStorageValue(address, storageKey1, nullValue); + Assert.assertNotNull(repository1.getStorageValue(address, storageKey1)); + repository1.commit(); + Repository repository2 = RepositoryImpl.createRoot(StoreFactory.getInstance()); + Assert.assertNull(repository2.getStorageValue(address, storageKey1)); } @Test @@ -61,14 +61,17 @@ public void writeWithoutCommit() { DataWord nullKey = new DataWord("nullkey".getBytes()); DataWord nullValue = new DataWord(0); - rootDeposit.putStorageValue(address, storageKey1, storageVal1); - rootDeposit.putStorageValue(address, nullKey, nullValue); - Assert.assertNull(DepositImpl.createRoot(manager).getStorageValue(address, storageKey1)); - Assert.assertNull(DepositImpl.createRoot(manager).getStorageValue(address, nullKey)); - rootDeposit.commit(); - Assert.assertEquals(DepositImpl.createRoot(manager).getStorageValue(address, storageKey1), - storageVal1); - Assert.assertNull(DepositImpl.createRoot(manager).getStorageValue(address, nullKey)); + rootRepository.putStorageValue(address, storageKey1, storageVal1); + rootRepository.putStorageValue(address, nullKey, nullValue); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageKey1)); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, nullKey)); + rootRepository.commit(); + Assert.assertEquals(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageKey1), storageVal1); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, nullKey)); } /* @@ -128,7 +131,7 @@ public void contractWriteAndDeleteStorage() Transaction trx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( contractName, address, ABI, code, value, fee, consumeUserResourcePercent, null); byte[] contractAddress = WalletUtil.generateContractAddress(trx); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); // write storage @@ -201,65 +204,77 @@ public void testParentChild() { DataWord storageParentVal1 = new DataWord("parent_val1".getBytes()); DataWord storageParentZeroKey = new DataWord("parent_zero_key1".getBytes()); - Deposit chlidDeposit = rootDeposit.newDepositChild(); + Repository childRepository = rootRepository.newRepositoryChild(); // write to root cache - rootDeposit.putStorageValue(address, storageParentKey1, storageParentVal1); - rootDeposit.putStorageValue(address, storageParentZeroKey, zeroValue); + rootRepository.putStorageValue(address, storageParentKey1, storageParentVal1); + rootRepository.putStorageValue(address, storageParentZeroKey, zeroValue); // write to child cache - chlidDeposit.putStorageValue(address, storageKey1, storageVal1); - chlidDeposit.putStorageValue(address, zeroKey, zeroValue); + childRepository.putStorageValue(address, storageKey1, storageVal1); + childRepository.putStorageValue(address, zeroKey, zeroValue); // check child cache - Assert.assertEquals(chlidDeposit.getStorageValue(address, storageKey1), storageVal1); - Assert.assertEquals(chlidDeposit.getStorageValue(address, zeroKey), zeroValue); + Assert.assertEquals(childRepository.getStorageValue(address, storageKey1), storageVal1); + Assert.assertEquals(childRepository.getStorageValue(address, zeroKey), zeroValue); Assert - .assertEquals(chlidDeposit.getStorageValue(address, storageParentKey1), storageParentVal1); - Assert.assertEquals(chlidDeposit.getStorageValue(address, storageParentZeroKey), zeroValue); + .assertEquals(childRepository.getStorageValue(address, storageParentKey1), + storageParentVal1); + Assert.assertEquals(childRepository.getStorageValue(address, storageParentZeroKey), zeroValue); - chlidDeposit.putStorageValue(address, storageParentKey1, parentChangedVal); + childRepository.putStorageValue(address, storageParentKey1, parentChangedVal); // check root cache - Assert.assertEquals(chlidDeposit.getStorageValue(address, storageParentKey1), parentChangedVal); - Assert.assertEquals(rootDeposit.getStorageValue(address, storageParentKey1), storageParentVal1); + Assert.assertEquals(childRepository.getStorageValue(address, storageParentKey1), + parentChangedVal); + Assert.assertEquals(rootRepository.getStorageValue(address, storageParentKey1), + storageParentVal1); - Assert.assertNull(rootDeposit.getStorageValue(address, storageKey1)); - Assert.assertNull(rootDeposit.getStorageValue(address, zeroKey)); - Assert.assertEquals(rootDeposit.getStorageValue(address, storageParentZeroKey), zeroValue); + Assert.assertNull(rootRepository.getStorageValue(address, storageKey1)); + Assert.assertNull(rootRepository.getStorageValue(address, zeroKey)); + Assert.assertEquals(rootRepository.getStorageValue(address, storageParentZeroKey), zeroValue); // check db - Assert.assertNull(DepositImpl.createRoot(manager).getStorageValue(address, storageKey1)); - Assert.assertNull(DepositImpl.createRoot(manager).getStorageValue(address, zeroKey)); - Assert.assertNull(DepositImpl.createRoot(manager).getStorageValue(address, storageParentKey1)); - Assert - .assertNull(DepositImpl.createRoot(manager).getStorageValue(address, storageParentZeroKey)); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageKey1)); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, zeroKey)); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageParentKey1)); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageParentZeroKey)); // commit child cache - chlidDeposit.commit(); + childRepository.commit(); // check root cache - Assert.assertEquals(rootDeposit.getStorageValue(address, storageKey1), storageVal1); - Assert.assertEquals(rootDeposit.getStorageValue(address, zeroKey), zeroValue); - Assert.assertEquals(chlidDeposit.getStorageValue(address, storageParentKey1), parentChangedVal); - Assert.assertEquals(rootDeposit.getStorageValue(address, storageParentKey1), parentChangedVal); - Assert.assertEquals(chlidDeposit.getStorageValue(address, storageParentZeroKey), zeroValue); + Assert.assertEquals(rootRepository.getStorageValue(address, storageKey1), storageVal1); + Assert.assertEquals(rootRepository.getStorageValue(address, zeroKey), zeroValue); + Assert.assertEquals(childRepository.getStorageValue(address, storageParentKey1), + parentChangedVal); + Assert.assertEquals(rootRepository.getStorageValue(address, storageParentKey1), + parentChangedVal); + Assert.assertEquals(childRepository.getStorageValue(address, storageParentZeroKey), zeroValue); // check db - Assert.assertNull(DepositImpl.createRoot(manager).getStorageValue(address, storageKey1)); - Assert.assertNull(DepositImpl.createRoot(manager).getStorageValue(address, zeroKey)); - Assert.assertNull(DepositImpl.createRoot(manager).getStorageValue(address, storageParentKey1)); - Assert - .assertNull(DepositImpl.createRoot(manager).getStorageValue(address, storageParentZeroKey)); - - rootDeposit.commit(); - Assert.assertEquals(DepositImpl.createRoot(manager).getStorageValue(address, storageKey1), - storageVal1); - Assert.assertNull(DepositImpl.createRoot(manager).getStorageValue(address, zeroKey)); - Assert.assertEquals(DepositImpl.createRoot(manager).getStorageValue(address, storageParentKey1), - parentChangedVal); - Assert - .assertNull(DepositImpl.createRoot(manager).getStorageValue(address, storageParentZeroKey)); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageKey1)); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, zeroKey)); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageParentKey1)); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageParentZeroKey)); + + rootRepository.commit(); + Assert.assertEquals(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageKey1), storageVal1); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, zeroKey)); + Assert.assertEquals(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageParentKey1), parentChangedVal); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageParentZeroKey)); CommonParameter.setENERGY_LIMIT_HARD_FORK(false); } @@ -280,76 +295,87 @@ public void testParentChildOldVersion() { DataWord storageParentVal1 = new DataWord("parent_val1".getBytes()); DataWord storageParentZeroKey = new DataWord("parent_zero_key1".getBytes()); - Deposit chlidDeposit = rootDeposit.newDepositChild(); + Repository childRepository = rootRepository.newRepositoryChild(); // write to root cache - rootDeposit.putStorageValue(address, storageParentKey1, storageParentVal1); - rootDeposit.putStorageValue(address, storageParentZeroKey, zeroValue); + rootRepository.putStorageValue(address, storageParentKey1, storageParentVal1); + rootRepository.putStorageValue(address, storageParentZeroKey, zeroValue); // write to child cache - chlidDeposit.putStorageValue(address, storageKey1, storageVal1); - chlidDeposit.putStorageValue(address, zeroKey, zeroValue); + childRepository.putStorageValue(address, storageKey1, storageVal1); + childRepository.putStorageValue(address, zeroKey, zeroValue); // check child cache - Assert.assertEquals(chlidDeposit.getStorageValue(address, storageKey1), storageVal1); - Assert.assertEquals(chlidDeposit.getStorageValue(address, zeroKey), zeroValue); - Assert - .assertEquals(chlidDeposit.getStorageValue(address, storageParentKey1), storageParentVal1); - Assert.assertEquals(chlidDeposit.getStorageValue(address, storageParentZeroKey), zeroValue); + Assert.assertEquals(childRepository.getStorageValue(address, storageKey1), storageVal1); + Assert.assertEquals(childRepository.getStorageValue(address, zeroKey), zeroValue); + Assert.assertEquals(childRepository.getStorageValue(address, storageParentKey1), + storageParentVal1); + Assert.assertEquals(childRepository.getStorageValue(address, storageParentZeroKey), zeroValue); - chlidDeposit.putStorageValue(address, storageParentKey1, parentChangedVal); + childRepository.putStorageValue(address, storageParentKey1, parentChangedVal); // check root cache - Assert.assertEquals(chlidDeposit.getStorageValue(address, storageParentKey1), parentChangedVal); - Assert.assertEquals(rootDeposit.getStorageValue(address, storageParentKey1), parentChangedVal); + Assert.assertEquals(childRepository.getStorageValue(address, storageParentKey1), + parentChangedVal); + Assert.assertEquals(rootRepository.getStorageValue(address, storageParentKey1), + parentChangedVal); - Assert.assertEquals(rootDeposit.getStorageValue(address, storageKey1), storageVal1); - Assert.assertEquals(rootDeposit.getStorageValue(address, zeroKey), zeroValue); - Assert.assertEquals(rootDeposit.getStorageValue(address, storageParentZeroKey), zeroValue); + Assert.assertEquals(rootRepository.getStorageValue(address, storageKey1), storageVal1); + Assert.assertEquals(rootRepository.getStorageValue(address, zeroKey), zeroValue); + Assert.assertEquals(rootRepository.getStorageValue(address, storageParentZeroKey), zeroValue); // check parent deposit == child deposit - Assert.assertEquals(rootDeposit.getStorageValue(address, storageKey1), - chlidDeposit.getStorageValue(address, storageKey1)); - Assert.assertEquals(rootDeposit.getStorageValue(address, zeroKey), - chlidDeposit.getStorageValue(address, zeroKey)); - Assert.assertEquals(rootDeposit.getStorageValue(address, storageParentKey1), - chlidDeposit.getStorageValue(address, storageParentKey1)); - Assert.assertEquals(rootDeposit.getStorageValue(address, storageParentZeroKey), - chlidDeposit.getStorageValue(address, storageParentZeroKey)); + Assert.assertEquals(rootRepository.getStorageValue(address, storageKey1), + childRepository.getStorageValue(address, storageKey1)); + Assert.assertEquals(rootRepository.getStorageValue(address, zeroKey), + childRepository.getStorageValue(address, zeroKey)); + Assert.assertEquals(rootRepository.getStorageValue(address, storageParentKey1), + childRepository.getStorageValue(address, storageParentKey1)); + Assert.assertEquals(rootRepository.getStorageValue(address, storageParentZeroKey), + childRepository.getStorageValue(address, storageParentZeroKey)); // check db - Assert.assertNull(DepositImpl.createRoot(manager).getStorageValue(address, storageKey1)); - Assert.assertNull(DepositImpl.createRoot(manager).getStorageValue(address, zeroKey)); - Assert.assertNull(DepositImpl.createRoot(manager).getStorageValue(address, storageParentKey1)); - Assert - .assertNull(DepositImpl.createRoot(manager).getStorageValue(address, storageParentZeroKey)); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageKey1)); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, zeroKey)); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageParentKey1)); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageParentZeroKey)); // didn't commit child cache - // chlidDeposit.commit(); + // childRepository.commit(); // check root cache - Assert.assertEquals(rootDeposit.getStorageValue(address, storageKey1), storageVal1); - Assert.assertEquals(rootDeposit.getStorageValue(address, zeroKey), zeroValue); - Assert.assertEquals(rootDeposit.getStorageValue(address, storageParentKey1), parentChangedVal); + Assert.assertEquals(rootRepository.getStorageValue(address, storageKey1), storageVal1); + Assert.assertEquals(rootRepository.getStorageValue(address, zeroKey), zeroValue); + Assert.assertEquals(rootRepository + .getStorageValue(address, storageParentKey1), parentChangedVal); - Assert.assertEquals(chlidDeposit.getStorageValue(address, storageParentKey1), parentChangedVal); - Assert.assertEquals(chlidDeposit.getStorageValue(address, storageParentZeroKey), zeroValue); + Assert.assertEquals(childRepository + .getStorageValue(address, storageParentKey1), parentChangedVal); + Assert.assertEquals(childRepository.getStorageValue(address, storageParentZeroKey), zeroValue); // check db - Assert.assertNull(DepositImpl.createRoot(manager).getStorageValue(address, storageKey1)); - Assert.assertNull(DepositImpl.createRoot(manager).getStorageValue(address, zeroKey)); - Assert.assertNull(DepositImpl.createRoot(manager).getStorageValue(address, storageParentKey1)); - Assert - .assertNull(DepositImpl.createRoot(manager).getStorageValue(address, storageParentZeroKey)); - - rootDeposit.commit(); - Assert.assertEquals(DepositImpl.createRoot(manager).getStorageValue(address, storageKey1), - storageVal1); - Assert.assertNull(DepositImpl.createRoot(manager).getStorageValue(address, zeroKey)); - Assert.assertEquals(DepositImpl.createRoot(manager).getStorageValue(address, storageParentKey1), - parentChangedVal); - Assert - .assertNull(DepositImpl.createRoot(manager).getStorageValue(address, storageParentZeroKey)); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageKey1)); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, zeroKey)); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageParentKey1)); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageParentZeroKey)); + + rootRepository.commit(); + Assert.assertEquals(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageKey1), storageVal1); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, zeroKey)); + Assert.assertEquals(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageParentKey1), parentChangedVal); + Assert.assertNull(RepositoryImpl.createRoot(StoreFactory.getInstance()) + .getStorageValue(address, storageParentZeroKey)); CommonParameter.setENERGY_LIMIT_HARD_FORK(false); } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java b/framework/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java index 4a588ae8646..c5ac42e93ce 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java @@ -13,7 +13,6 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -24,6 +23,8 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; +import org.tron.core.store.StoreFactory; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; @Slf4j @@ -32,7 +33,7 @@ public class TimeBenchmarkTest { private Manager dbManager; private TronApplicationContext context; - private DepositImpl deposit; + private RepositoryImpl repository; private String dbPath = "output_TimeBenchmarkTest"; private String OWNER_ADDRESS; private Application AppT; @@ -49,10 +50,10 @@ public void init() { AppT = ApplicationFactory.create(context); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; dbManager = context.getBean(Manager.class); - deposit = DepositImpl.createRoot(dbManager); - deposit.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); - deposit.addBalance(Hex.decode(OWNER_ADDRESS), totalBalance); - deposit.commit(); + repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); + repository.addBalance(Hex.decode(OWNER_ADDRESS), totalBalance); + repository.commit(); } // pragma solidity ^0.4.2; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/TransferFailedEnergyTest.java b/framework/src/test/java/org/tron/common/runtime/vm/TransferFailedEnergyTest.java index 8f9232dee07..51d8e8dafae 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/TransferFailedEnergyTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/TransferFailedEnergyTest.java @@ -281,7 +281,7 @@ public void testTransferFailedAfterAllowTvmConstantinopl() contractName, address, ABI, code, value, fee, consumeUserResourcePercent, null); byte[] addressWithSufficientBalance = WalletUtil.generateContractAddress(trx); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); for (TestCase testCase : testCasesAfterAllowTvmConstantinop) { @@ -292,7 +292,7 @@ public void testTransferFailedAfterAllowTvmConstantinopl() contractName, address, ABI, code, 0, fee, consumeUserResourcePercent, null); byte[] addressWithoutBalance = WalletUtil.generateContractAddress(trx); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); for (TestCase testCase : testCasesInsufficientBalance) { @@ -353,7 +353,7 @@ public void testTransferFailedBeforeAllowTvmConstantinopl() contractName, address, ABI, code, value, fee, consumeUserResourcePercent, null); byte[] addressWithSufficientBalance = WalletUtil.generateContractAddress(trx); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); for (TestCase testCase : testCasesBeforeAllowTvmConstantinop) { @@ -364,7 +364,7 @@ public void testTransferFailedBeforeAllowTvmConstantinopl() contractName, address, ABI, code, 0, fee, consumeUserResourcePercent, null); byte[] addressWithoutBalance = WalletUtil.generateContractAddress(trx); - runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootRepository, null); Assert.assertNull(runtime.getRuntimeError()); for (TestCase testCase : testCasesInsufficientBalance) { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java b/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java index 4d7fa13109d..4a724099411 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java @@ -14,7 +14,6 @@ import org.tron.common.runtime.ProgramResult; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; @@ -37,6 +36,7 @@ import org.tron.core.exception.VMIllegalException; import org.tron.core.store.StoreFactory; import org.tron.core.vm.EnergyCost; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction; import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; @@ -61,7 +61,7 @@ public class TransferToAccountTest { private static ChainBaseManager chainBaseManager; private static TronApplicationContext context; private static Application appT; - private static DepositImpl deposit; + private static RepositoryImpl repository; private static AccountCapsule ownerCapsule; static { @@ -72,10 +72,10 @@ public class TransferToAccountTest { TRANSFER_TO = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; dbManager = context.getBean(Manager.class); chainBaseManager = context.getBean(ChainBaseManager.class); - deposit = DepositImpl.createRoot(dbManager); - deposit.createAccount(Hex.decode(TRANSFER_TO), AccountType.Normal); - deposit.addBalance(Hex.decode(TRANSFER_TO), 10); - deposit.commit(); + repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + repository.createAccount(Hex.decode(TRANSFER_TO), AccountType.Normal); + repository.addBalance(Hex.decode(TRANSFER_TO), 10); + repository.commit(); ownerCapsule = new AccountCapsule( ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), @@ -144,7 +144,7 @@ public void TransferTokenTest() // 1. Test deploy with tokenValue and tokenId */ long id = createAsset("testToken1"); byte[] contractAddress = deployTransferContract(id); - deposit.commit(); + repository.commit(); Assert.assertEquals(100, chainBaseManager.getAccountStore() .get(contractAddress).getAssetMapV2().get(String.valueOf(id)).longValue()); @@ -321,7 +321,7 @@ private byte[] deployTransferContract(long id) byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, null, tokenValue, tokenId, - deposit, null); + repository, null); return contractAddress; } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java b/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java index 0a6e30f8897..84f2ab061eb 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java @@ -12,12 +12,10 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.capsule.AccountAssetCapsule; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.config.DefaultConfig; @@ -27,6 +25,8 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; +import org.tron.core.store.StoreFactory; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction; import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; @@ -49,7 +49,7 @@ public class TransferTokenTest { private static Manager dbManager; private static TronApplicationContext context; private static Application appT; - private static DepositImpl deposit; + private static RepositoryImpl repository; private static AccountCapsule ownerCapsule; @@ -60,10 +60,10 @@ public class TransferTokenTest { OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; TRANSFER_TO = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; dbManager = context.getBean(Manager.class); - deposit = DepositImpl.createRoot(dbManager); - deposit.createAccount(Hex.decode(TRANSFER_TO), AccountType.Normal); - deposit.addBalance(Hex.decode(TRANSFER_TO), 10); - deposit.commit(); + repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + repository.createAccount(Hex.decode(TRANSFER_TO), AccountType.Normal); + repository.addBalance(Hex.decode(TRANSFER_TO), 10); + repository.commit(); ownerCapsule = new AccountCapsule( ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), @@ -132,7 +132,7 @@ public void TransferTokenTest() /* 1. Test deploy with tokenValue and tokenId */ long id = createAsset("testToken1"); byte[] contractAddress = deployTransferTokenContract(id); - deposit.commit(); + repository.commit(); Assert.assertEquals(100, dbManager.getAccountStore().get(contractAddress).getAssetMapV2().get(String.valueOf(id)) .longValue()); @@ -216,7 +216,7 @@ private byte[] deployTransferTokenContract(long id) byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, null, tokenValue, tokenId, - deposit, null); + repository, null); return contractAddress; } @@ -278,7 +278,7 @@ private byte[] deployTransferTokenPerformanceContract(long id) byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, null, tokenValue, tokenId, - deposit, null); + repository, null); return contractAddress; } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/VMTestBase.java b/framework/src/test/java/org/tron/common/runtime/vm/VMTestBase.java index 92febb89ab1..1ceee84d634 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/VMTestBase.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/VMTestBase.java @@ -7,14 +7,15 @@ import org.junit.Before; import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.Runtime; -import org.tron.common.storage.Deposit; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; +import org.tron.core.store.StoreFactory; +import org.tron.core.vm.repository.Repository; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; @Slf4j @@ -23,7 +24,7 @@ public class VMTestBase { protected Manager manager; protected TronApplicationContext context; protected String dbPath; - protected Deposit rootDeposit; + protected Repository rootRepository; protected String OWNER_ADDRESS; protected Runtime runtime; @@ -34,11 +35,10 @@ public void init() { context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; manager = context.getBean(Manager.class); - rootDeposit = DepositImpl.createRoot(manager); - rootDeposit.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); - rootDeposit.addBalance(Hex.decode(OWNER_ADDRESS), 30000000000000L); - - rootDeposit.commit(); + rootRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + rootRepository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); + rootRepository.addBalance(Hex.decode(OWNER_ADDRESS), 30000000000000L); + rootRepository.commit(); } @After diff --git a/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java b/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java index 2beedfb3f13..805f767e7da 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java @@ -26,8 +26,6 @@ import org.tron.common.runtime.RuntimeImpl; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.Deposit; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.Commons; import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; @@ -46,6 +44,8 @@ import org.tron.core.store.StoreFactory; import org.tron.core.vm.config.ConfigLoader; import org.tron.core.vm.config.VMConfig; +import org.tron.core.vm.repository.Repository; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol; import stest.tron.wallet.common.client.utils.AbiUtil; import stest.tron.wallet.common.client.utils.DataWord; @@ -271,7 +271,7 @@ private static Consumer getSmallerConsumer(long expected) { private static ConsensusService consensusService; private static MortgageService mortgageService; private static byte[] owner; - private static Deposit rootDeposit; + private static Repository rootRepository; @Before public void init() throws Exception { @@ -286,10 +286,10 @@ public void init() throws Exception { mortgageService = context.getBean(MortgageService.class); owner = Hex.decode(Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"); - rootDeposit = DepositImpl.createRoot(manager); - rootDeposit.createAccount(owner, Protocol.AccountType.Normal); - rootDeposit.addBalance(owner, 900_000_000_000_000_000L); - rootDeposit.commit(); + rootRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + rootRepository.createAccount(owner, Protocol.AccountType.Normal); + rootRepository.addBalance(owner, 900_000_000_000_000_000L); + rootRepository.commit(); ConfigLoader.disable = true; VMConfig.initVmHardFork(true); diff --git a/framework/src/test/java/org/tron/core/actuator/TransferActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/TransferActuatorTest.java index 9a26a445e20..c8f55768910 100644 --- a/framework/src/test/java/org/tron/core/actuator/TransferActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/TransferActuatorTest.java @@ -16,7 +16,6 @@ import org.junit.Test; import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; @@ -31,6 +30,8 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; +import org.tron.core.store.StoreFactory; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.AssetIssueContractOuterClass; @@ -526,11 +527,11 @@ public void transferToSmartContractAddress() long value = 1; long feeLimit = 100000000; long consumeUserResourcePercent = 0; - DepositImpl deposit = DepositImpl.createRoot(dbManager); + RepositoryImpl repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, codes, value, feeLimit, consumeUserResourcePercent, null, 0, 0, - deposit, null); + repository, null); TransferActuator actuator = new TransferActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) diff --git a/framework/src/test/java/org/tron/core/actuator/TransferAssetActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/TransferAssetActuatorTest.java index d047ff4ce1c..7212edd7eaa 100755 --- a/framework/src/test/java/org/tron/core/actuator/TransferAssetActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/TransferAssetActuatorTest.java @@ -30,7 +30,6 @@ import org.junit.Test; import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.storage.DepositImpl; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; @@ -47,7 +46,9 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; +import org.tron.core.store.StoreFactory; import org.tron.core.vm.config.VMConfig; +import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.AssetIssueContractOuterClass; @@ -1426,11 +1427,11 @@ public void transferToContractAddress() long value = 1; long feeLimit = 1000000000L; long consumeUserResourcePercent = 0; - DepositImpl deposit = DepositImpl.createRoot(dbManager); + RepositoryImpl repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, codes, value, feeLimit, consumeUserResourcePercent, null, 0, 0, - deposit, null); + repository, null); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) From 696db57dcd14b701a6ed35a5a845b47b272d93fc Mon Sep 17 00:00:00 2001 From: hongdexiang <1090664234@qq.com> Date: Thu, 24 Mar 2022 16:26:25 +0800 Subject: [PATCH 0024/1197] change : change function name --- actuator/src/main/java/org/tron/core/vm/program/Program.java | 2 +- .../main/java/org/tron/core/vm/repository/RepositoryImpl.java | 2 +- .../main/java/org/tron/common/parameter/CommonParameter.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 06502abe91f..68834e72b34 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -86,7 +86,7 @@ public class Program { private static final String INVALID_TOKEN_ID_MSG = "not valid token id"; private static final String REFUND_ENERGY_FROM_MESSAGE_CALL = "refund energy from message call"; private static final String CALL_PRE_COMPILED = "call pre-compiled"; - private static final int lruCacheSize = CommonParameter.getInstance().getLruCacheSize(); + private static final int lruCacheSize = CommonParameter.getInstance().getSafeLruCacheSize(); private static final LRUMap programPrecompileLRUMap = new LRUMap<>(lruCacheSize); private long nonce; diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index e9950796640..c9178472552 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -67,7 +67,7 @@ public class RepositoryImpl implements Repository { private static final byte[] TOTAL_NET_WEIGHT = "TOTAL_NET_WEIGHT".getBytes(); private static final byte[] TOTAL_ENERGY_WEIGHT = "TOTAL_ENERGY_WEIGHT".getBytes(); - private static final int lruCacheSize = CommonParameter.getInstance().getLruCacheSize(); + private static final int lruCacheSize = CommonParameter.getInstance().getSafeLruCacheSize(); private static final LRUMap contractLruCache = new LRUMap<>(lruCacheSize); private static final LRUMap codeLruCache = new LRUMap<>(lruCacheSize); diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index b1a51779b0f..d7a1fbd889a 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -534,7 +534,7 @@ public boolean isJsonRpcFilterEnabled() { return jsonRpcHttpFullNodeEnable || jsonRpcHttpSolidityNodeEnable; } - public int getLruCacheSize() { + public int getSafeLruCacheSize() { return lruCacheSize < 1 ? 500 : lruCacheSize; } } From 8c6d684e22a9dbf14a6a2385c771d8a436ea36e1 Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 24 Mar 2022 17:02:00 +0800 Subject: [PATCH 0025/1197] fix(tvm): compiler error --- .../main/java/org/tron/core/vm/repository/RepositoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 01d9e84934d..26ed2efca0f 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -385,7 +385,7 @@ public ContractCapsule getContract(byte[] address) { } if (contractCapsule != null) { - contractCache.put(key, Value.create(contractCapsule.getData())); + contractCache.put(key, Value.create(contractCapsule)); if (!contractLruCache.containsKey(key)) { contractLruCache.put(key, contractCapsule); } From 5dffc5b05685037c82dffe8e417de500875613f8 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 24 Mar 2022 19:16:06 +0800 Subject: [PATCH 0026/1197] test(*): fix test time out. --- .../org/tron/core/net/TronNetDelegate.java | 1 - .../services/stop/BlockHeightStopTest.java | 4 +- .../services/stop/BlockSyncCountStopTest.java | 4 +- .../core/services/stop/BlockTimeStopTest.java | 23 ++- .../services/stop/ConditionallyStopTest.java | 137 ++++++++++++++---- 5 files changed, 119 insertions(+), 50 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index 77b1bd90772..16ad677fba0 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -68,7 +68,6 @@ public class TronNetDelegate { private ChannelManager channelManager; @Autowired - @Getter // for test private Manager dbManager; @Autowired diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java index 23dba810545..43eb4f5ba4e 100644 --- a/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java @@ -16,8 +16,8 @@ protected void initParameter(CommonParameter parameter) { } @Override - protected void check() { - Assert.assertEquals(height, tronNetDelegate.getDbManager().getDynamicPropertiesStore() + protected void check() throws Exception { + Assert.assertEquals(height, dbManager.getDynamicPropertiesStore() .getLatestBlockHeaderNumberFromDB()); } diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java index e2877813bbb..cd5010fabc9 100644 --- a/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java @@ -16,9 +16,9 @@ protected void initParameter(CommonParameter parameter) { } @Override - protected void check() { + protected void check() throws Exception { - Assert.assertEquals(sync + currentHeader, tronNetDelegate.getDbManager() + Assert.assertEquals(sync + currentHeader, dbManager .getDynamicPropertiesStore().getLatestBlockHeaderNumberFromDB()); } diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java index 3a84a337edd..240ab6365f4 100644 --- a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java @@ -1,18 +1,19 @@ package org.tron.core.services.stop; import java.text.ParseException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.Date; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; import org.quartz.CronExpression; import org.tron.common.parameter.CommonParameter; -import org.tron.core.exception.P2pException; @Slf4j public class BlockTimeStopTest extends ConditionallyStopTest { - - // @see https://tronscan.org/#/block/12 - private static final String time = "00 52 09 25 06 ? 2018"; + private static final DateTimeFormatter pattern = DateTimeFormatter + .ofPattern("ss mm HH dd MM ? yyyy"); + private static final String time = LocalDateTime.now().plusSeconds(12 * 3).format(pattern); private static CronExpression cronExpression; @@ -35,15 +36,11 @@ protected void initParameter(CommonParameter parameter) { } @Override - protected void check() { - try { - long height = tronNetDelegate.getDbManager() - .getDynamicPropertiesStore().getLatestBlockHeaderNumberFromDB(); - Assert.assertTrue(cronExpression.isSatisfiedBy(new Date(tronNetDelegate - .getBlockTime(tronNetDelegate.getBlockIdByNum(height))))); - } catch (P2pException e) { - logger.error("{}", e.getMessage()); - } + protected void check() throws Exception { + long height = dbManager + .getDynamicPropertiesStore().getLatestBlockHeaderNumberFromDB(); + Assert.assertTrue(cronExpression.isSatisfiedBy(new Date(chainManager + .getBlockById(chainManager.getBlockIdByNum(height)).getTimeStamp()))); } @Override diff --git a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java index 5b0bb659197..a723e00fd6d 100644 --- a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java @@ -1,35 +1,58 @@ package org.tron.core.services.stop; +import com.google.common.collect.Maps; +import com.google.protobuf.ByteString; import java.io.File; -import java.util.Collection; +import java.util.ArrayList; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; +import java.util.stream.IntStream; import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; +import org.tron.common.crypto.ECKey; import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; -import org.tron.common.utils.ReflectUtils; +import org.tron.common.utils.Sha256Hash; +import org.tron.common.utils.Utils; +import org.tron.consensus.dpos.DposSlot; +import org.tron.core.ChainBaseManager; +import org.tron.core.Constant; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; +import org.tron.core.consensus.ConsensusService; +import org.tron.core.db.BlockGenerate; +import org.tron.core.db.Manager; import org.tron.core.net.TronNetDelegate; -import org.tron.core.net.peer.PeerConnection; +import org.tron.protos.Protocol; @Slf4j -public abstract class ConditionallyStopTest { +public abstract class ConditionallyStopTest extends BlockGenerate { - protected String dbPath; - protected TronNetDelegate tronNetDelegate; + protected static ChainBaseManager chainManager; + protected static ConsensusService consensusService; + protected static DposSlot dposSlot; + private final String key = "f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62"; + private final byte[] privateKey = ByteArray.fromHexString(key); + private final AtomicInteger port = new AtomicInteger(0); + protected String dbPath; + protected Manager dbManager; protected long currentHeader = -1; + protected TronNetDelegate tronNetDelegate; private TronApplicationContext context; protected abstract void initParameter(CommonParameter parameter); - protected abstract void check(); + protected abstract void check() throws Exception; protected abstract void initDbPath(); @@ -40,47 +63,97 @@ public void init() throws Exception { initDbPath(); FileUtil.deleteDir(new File(dbPath)); logger.info("Full node running."); - Args.setParam( - new String[] { - "--output-directory", dbPath, - "--storage-db-directory", "database", - "--storage-index-directory", "index" - }, - "config.conf" - ); - CommonParameter parameter = Args.getInstance(); - parameter.setNodeListenPort(10000); - initParameter(parameter); + Args.setParam(new String[] {"-d", dbPath, "-w"}, Constant.TEST_CONF); + Args.getInstance().setNodeListenPort(10000 + port.incrementAndGet()); + initParameter(Args.getInstance()); context = new TronApplicationContext(DefaultConfig.class); - Application appT = ApplicationFactory.create(context); - appT.initServices(parameter); - appT.startServices(); - appT.startup(); + + dbManager = context.getBean(Manager.class); + setManager(dbManager); + dposSlot = context.getBean(DposSlot.class); + consensusService = context.getBean(ConsensusService.class); + consensusService.start(); + chainManager = dbManager.getChainBaseManager(); tronNetDelegate = context.getBean(TronNetDelegate.class); tronNetDelegate.setTest(true); - currentHeader = tronNetDelegate.getDbManager().getDynamicPropertiesStore() + currentHeader = dbManager.getDynamicPropertiesStore() .getLatestBlockHeaderNumberFromDB(); } @After public void destroy() { Args.clearParam(); - Collection peerConnections = ReflectUtils - .invokeMethod(tronNetDelegate, "getActivePeer"); - for (PeerConnection peer : peerConnections) { - peer.close(); - } context.destroy(); FileUtil.deleteDir(new File(dbPath)); } + public void generateBlock(Map witnessAndAccount) throws Exception { + + BlockCapsule block = + createTestBlockCapsule( + chainManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp() + 3000, + chainManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() + 1, + chainManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(), + witnessAndAccount); + + tronNetDelegate.processBlock(block, false); + } + @Test - public void testStop() throws InterruptedException { + public void testStop() throws Exception { + + + final ECKey ecKey = ECKey.fromPrivate(privateKey); + byte[] address = ecKey.getAddress(); + WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address)); + chainManager.getWitnessScheduleStore().saveActiveWitnesses(new ArrayList<>()); + chainManager.addWitness(ByteString.copyFrom(address)); + + Protocol.Block block = getSignedBlock(witnessCapsule.getAddress(), 0, privateKey); + + tronNetDelegate.processBlock(new BlockCapsule(block), false); + + Map witnessAndAccount = addTestWitnessAndAccount(); + witnessAndAccount.put(ByteString.copyFrom(address), key); while (!tronNetDelegate.isHitDown()) { - Thread.sleep(1); + generateBlock(witnessAndAccount); } Assert.assertTrue(tronNetDelegate.isHitDown()); check(); } + private Map addTestWitnessAndAccount() { + chainManager.getWitnesses().clear(); + return IntStream.range(0, 2) + .mapToObj( + i -> { + ECKey ecKey = new ECKey(Utils.getRandom()); + String privateKey = ByteArray.toHexString(ecKey.getPrivKey().toByteArray()); + ByteString address = ByteString.copyFrom(ecKey.getAddress()); + + WitnessCapsule witnessCapsule = new WitnessCapsule(address); + chainManager.getWitnessStore().put(address.toByteArray(), witnessCapsule); + chainManager.addWitness(address); + + AccountCapsule accountCapsule = + new AccountCapsule(Protocol.Account.newBuilder().setAddress(address).build()); + chainManager.getAccountStore().put(address.toByteArray(), accountCapsule); + + return Maps.immutableEntry(address, privateKey); + }) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + private BlockCapsule createTestBlockCapsule(long time, + long number, ByteString hash, + Map witnessAddressMap) { + ByteString witnessAddress = dposSlot.getScheduledWitness(dposSlot.getSlot(time)); + BlockCapsule blockCapsule = new BlockCapsule(number, Sha256Hash.wrap(hash), time, + witnessAddress); + blockCapsule.generatedByMyself = true; + blockCapsule.setMerkleRoot(); + blockCapsule.sign(ByteArray.fromHexString(witnessAddressMap.get(witnessAddress))); + return blockCapsule; + } + } From 0a7c1e297af8be48a00e27122919ad6841b2fc02 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 24 Mar 2022 20:45:55 +0800 Subject: [PATCH 0027/1197] test(*): fix build-on-debian-9-dot-8 block time stop test case. --- .../core/services/stop/BlockTimeStopTest.java | 2 +- .../services/stop/ConditionallyStopTest.java | 21 ++++++++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java index 240ab6365f4..8af74c1fdc5 100644 --- a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java @@ -13,7 +13,7 @@ public class BlockTimeStopTest extends ConditionallyStopTest { private static final DateTimeFormatter pattern = DateTimeFormatter .ofPattern("ss mm HH dd MM ? yyyy"); - private static final String time = LocalDateTime.now().plusSeconds(12 * 3).format(pattern); + private static final String time = localDateTime.plusSeconds(12 * 3).format(pattern); private static CronExpression cronExpression; diff --git a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java index a723e00fd6d..02829ee3ccf 100644 --- a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java @@ -3,6 +3,9 @@ import com.google.common.collect.Maps; import com.google.protobuf.ByteString; import java.io.File; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; @@ -38,18 +41,20 @@ public abstract class ConditionallyStopTest extends BlockGenerate { - protected static ChainBaseManager chainManager; - protected static ConsensusService consensusService; - protected static DposSlot dposSlot; + static ChainBaseManager chainManager; + private static DposSlot dposSlot; private final String key = "f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62"; private final byte[] privateKey = ByteArray.fromHexString(key); private final AtomicInteger port = new AtomicInteger(0); protected String dbPath; protected Manager dbManager; - protected long currentHeader = -1; - protected TronNetDelegate tronNetDelegate; + long currentHeader = -1; + private TronNetDelegate tronNetDelegate; private TronApplicationContext context; + static LocalDateTime localDateTime = LocalDateTime.now(); + private long time = ZonedDateTime.of(localDateTime, ZoneId.systemDefault()).toInstant().toEpochMilli(); + protected abstract void initParameter(CommonParameter parameter); protected abstract void check() throws Exception; @@ -71,7 +76,7 @@ public void init() throws Exception { dbManager = context.getBean(Manager.class); setManager(dbManager); dposSlot = context.getBean(DposSlot.class); - consensusService = context.getBean(ConsensusService.class); + ConsensusService consensusService = context.getBean(ConsensusService.class); consensusService.start(); chainManager = dbManager.getChainBaseManager(); tronNetDelegate = context.getBean(TronNetDelegate.class); @@ -87,7 +92,7 @@ public void destroy() { FileUtil.deleteDir(new File(dbPath)); } - public void generateBlock(Map witnessAndAccount) throws Exception { + private void generateBlock(Map witnessAndAccount) throws Exception { BlockCapsule block = createTestBlockCapsule( @@ -109,7 +114,7 @@ public void testStop() throws Exception { chainManager.getWitnessScheduleStore().saveActiveWitnesses(new ArrayList<>()); chainManager.addWitness(ByteString.copyFrom(address)); - Protocol.Block block = getSignedBlock(witnessCapsule.getAddress(), 0, privateKey); + Protocol.Block block = getSignedBlock(witnessCapsule.getAddress(), time, privateKey); tronNetDelegate.processBlock(new BlockCapsule(block), false); From 96318dacfb1bf1085b4f7fe065f1c5e609f670a4 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 24 Mar 2022 21:07:31 +0800 Subject: [PATCH 0028/1197] test(*): remove unused import. --- .../org/tron/core/services/stop/BlockTimeStopTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java index 8af74c1fdc5..22a660e4c09 100644 --- a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java @@ -1,14 +1,14 @@ package org.tron.core.services.stop; -import java.text.ParseException; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.Date; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; import org.quartz.CronExpression; import org.tron.common.parameter.CommonParameter; +import java.text.ParseException; +import java.time.format.DateTimeFormatter; +import java.util.Date; + @Slf4j public class BlockTimeStopTest extends ConditionallyStopTest { private static final DateTimeFormatter pattern = DateTimeFormatter From 1cc7a809ab7eb76f7eb6bfb432647b93893bcf32 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 25 Mar 2022 11:37:46 +0800 Subject: [PATCH 0029/1197] test(*): ConditionallyStopTest,require ecKey not null. --- .../java/org/tron/core/services/stop/ConditionallyStopTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java index 02829ee3ccf..13dc869d6bb 100644 --- a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java @@ -109,6 +109,7 @@ public void testStop() throws Exception { final ECKey ecKey = ECKey.fromPrivate(privateKey); + Assert.assertNotNull(ecKey); byte[] address = ecKey.getAddress(); WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address)); chainManager.getWitnessScheduleStore().saveActiveWitnesses(new ArrayList<>()); From 426d04f319abc9055a55b1ec148ef998d5715390 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 25 Mar 2022 11:59:39 +0800 Subject: [PATCH 0030/1197] config(db,trx): update config settings. 1. add leveldb settings demo 2. change transaction reference block default value from 'head' to 'solid' ,avoid tapos error --- .../java/org/tron/core/config/args/Args.java | 2 +- framework/src/main/resources/config.conf | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 7fcad9b75c1..1f231f2e34f 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -641,7 +641,7 @@ public static void setParam(final String[] args, final String confFileName) { .getBoolean(Constant.STORAGE_NEEDTO_UPDATE_ASSET) : true; PARAMETER.trxReferenceBlock = config.hasPath(Constant.TRX_REFERENCE_BLOCK) - ? config.getString(Constant.TRX_REFERENCE_BLOCK) : "head"; + ? config.getString(Constant.TRX_REFERENCE_BLOCK) : "solid"; PARAMETER.trxExpirationTimeInMilliseconds = config.hasPath(Constant.TRX_EXPIRATION_TIME_IN_MILLIS_SECONDS) diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 46dcb2e375e..a8c48057c3c 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -20,6 +20,21 @@ storage { # Otherwise, db configs will remain defualt and data will be stored in # the path of "output-directory" or which is set by "-d" ("--output-directory"). + # setting can impove leveldb performance .... start + # node: if this will increase process fds,you may be check your ulimit if 'too many open files' error occurs + # see https://github.com/tronprotocol/tips/blob/master/tip-343.md for detail + # if you find block sync has lower performance,you can try this settings + #default = { + # maxOpenFiles = 100 + #} + #defaultM = { + # maxOpenFiles = 500 + #} + #defaultL = { + # maxOpenFiles = 1000 + #} + # setting can impove leveldb performance .... end + # Attention: name is a required field that must be set !!! properties = [ // { @@ -521,8 +536,8 @@ block = { proposalExpireTime = 259200000 // 3 day: 259200000(ms) } -# Transaction reference block, default is "head", configure to "solid" can avoid TaPos error -# trx.reference.block = "head" // head;solid; +# Transaction reference block, default is "solid", configure to "head" may accur TaPos error +# trx.reference.block = "solid" // head;solid; # This property sets the number of milliseconds after the creation of the transaction that is expired, default value is 60000. # trx.expiration.timeInMilliseconds = 60000 From ca02a369850787ebba9112a0ee2fdfb417286c0a Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 25 Mar 2022 13:44:20 +0800 Subject: [PATCH 0031/1197] style(test): fix checkStyle. --- .../org/tron/core/services/stop/BlockTimeStopTest.java | 7 +++---- .../org/tron/core/services/stop/ConditionallyStopTest.java | 3 ++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java index 22a660e4c09..9dd34a577d6 100644 --- a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java @@ -1,14 +1,13 @@ package org.tron.core.services.stop; +import java.text.ParseException; +import java.time.format.DateTimeFormatter; +import java.util.Date; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; import org.quartz.CronExpression; import org.tron.common.parameter.CommonParameter; -import java.text.ParseException; -import java.time.format.DateTimeFormatter; -import java.util.Date; - @Slf4j public class BlockTimeStopTest extends ConditionallyStopTest { private static final DateTimeFormatter pattern = DateTimeFormatter diff --git a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java index 13dc869d6bb..88f2d1c04e0 100644 --- a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java @@ -53,7 +53,8 @@ public abstract class ConditionallyStopTest extends BlockGenerate { private TronApplicationContext context; static LocalDateTime localDateTime = LocalDateTime.now(); - private long time = ZonedDateTime.of(localDateTime, ZoneId.systemDefault()).toInstant().toEpochMilli(); + private long time = ZonedDateTime.of(localDateTime, + ZoneId.systemDefault()).toInstant().toEpochMilli(); protected abstract void initParameter(CommonParameter parameter); From 12c8ac722cb3c04b1d8bc6f773533e1b762a7655 Mon Sep 17 00:00:00 2001 From: liukai Date: Mon, 28 Mar 2022 00:19:58 +0800 Subject: [PATCH 0032/1197] feat(docker): add network selection parameters 1. add the select network parameter for switching between the main, test and private networks --- docker/docker.md | 54 +++++++++++----- docker/docker.sh | 159 +++++++++++++++++++++++++++++------------------ 2 files changed, 139 insertions(+), 74 deletions(-) diff --git a/docker/docker.md b/docker/docker.md index b1af19d1f84..29e4afad64d 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -6,7 +6,7 @@ java-tron support containerized processes, we maintain a Docker image with lates ## Prerequisites Requires docker to be installed on the system. Docker version >=20.10.12. - + ## Quick Start @@ -27,16 +27,37 @@ Before running the java-tron service, make sure some ports on your local machine - `50051`: used by the GRPC based API - `18888`: TCP and UDP, used by the P2P protocol running the network -then start the java-tron service with the `--run` parameter +#### Full node on the main network + ```shell -$ sh docker.sh --run +$ sh docker.sh --run --net main ``` or you can use `-p` to customize the port mapping, more custom parameters, please refer to [Options](#Options) ```shell -$ sh docker.sh --run -p 8080:8090 -p 40051:50051 +$ sh docker.sh --run --net main -p 8080:8090 -p 40051:50051 +``` + +#### Full node on the nile test network +```shell +$ sh docker.sh --run --net net +``` + +#### Full node on the private network +you can also build your own private-net and will download a configuration file from the network for your private network, which will be stored in your local config/ directory. +```shell +$ sh docker.sh --run --net private +``` +#### Configuration +The script will automatically download and use the corresponding configuration file from the github repository according to the `--net` parameter. if you don't want to update the configuration file every time you start the service, please add a startup parameter: + +```shell +$ sh docker.sh --run --update-config false ``` +Or use the `-c` parameter to specify your own configuration file, which will not automatically download a new configuration file from github repository. + + ### View logs If you want to see the logs of the java-tron service, please use the `--log` parameter @@ -53,9 +74,13 @@ $ sh docker.sh --stop ## Build Image -If you do not want to use the default official image, you can also compile your own local image, first you need to change some parameters in the shell script to specify your own mirror info,`DOCKER_REPOSITORY` is your repository name, `DOCKER_IMAGES` is the image name,`DOCKER_TARGET` is the version number, here is an example: +If you do not want to use the default official image, you can also compile your own local image, first you need to change some parameters in the shell script to specify your own mirror info. +`DOCKER_REPOSITORY` is your repository name +`DOCKER_IMAGES` is the image name +`DOCKER_TARGET` is the version number, here is an example: + ```shell -DOCKER_REPOSITORY="you_repository" +DOCKER_REPOSITORY="your_repository" DOCKER_IMAGES="java-tron" DOCKER_TARGET="1.0" ``` @@ -70,17 +95,16 @@ $ sh docker.sh --build Parameters for all functions: -* **`--build`** Building a local mirror image - +* **`--build`** building a local mirror image * **`--pull`** download a docker mirror from **DockerHub** - * **`--run`** run the docker mirror - * **`--log`** exporting the java-tron run log on the container - * **`--stop`** stopping a running container - * **`--rm`** remove container,only deletes the container, not the image -* **`-p`** Publish a container's port to the host, format:`-p hostPort:containerPort` -* **`-c`** Specify other java-tron configuration file in the container -* **`-v`** Bind mount a volume for container,format: `-v host-src:container-dest`, the `host-src` is an absolute path +* **`-p`** publish a container's port to the host, format:`-p hostPort:containerPort` +* **`-c`** specify other java-tron configuration file in the container +* **`-v`** bind mount a volume for container,format: `-v host-src:container-dest`, the `host-src` is an absolute path +* **`--net`** select the network, you can join the main-net, test-net +* **`--update-config`** update configuration file, default true + + diff --git a/docker/docker.sh b/docker/docker.sh index 51b09acf11d..bf4961f0620 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -37,6 +37,13 @@ OUTPUT_DIRECTORY="$VOLUME/output-directory" CONFIG_PATH="/java-tron/config/" CONFIG_FILE="main_net_config.conf" +MAIN_NET_CONFIG_FILE="main_net_config.conf" +TEST_NET_CONFIG_FILE="test_net_config.conf" +PRIVATE_NET_CONFIG_FILE="private_net_config.conf" + +# update the configuration file, if true, the configuration file will be fetched from the network every time you start +UPDATE_CONFIG=true + LOG_FILE="/logs/tron.log" JAVA_TRON_REPOSITORY="https://raw.githubusercontent.com/tronprotocol/java-tron/develop/" @@ -44,7 +51,7 @@ DOCKER_FILE="Dockerfile" ENDPOINT_SHELL="docker-entrypoint.sh" if test docker; then - docker -v + docker -v else echo "warning: docker must be installed, please install docker first." exit @@ -60,6 +67,27 @@ docker_image() { image=$image_name } +download_config() { + mkdir -p config + if test curl; then + curl -o config/$CONFIG_FILE -LO https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/$CONFIG_FILE -s + elif test wget; then + wget -P -q config/ https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/$CONFIG_FILE + fi +} + + +check_download_config() { + if [[ ! -d 'config' || ! -f "config/$CONFIG_FILE" ]]; then + mkdir -p config + if test curl; then + curl -o config/$CONFIG_FILE -LO https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/$CONFIG_FILE -s + elif test wget; then + wget -P -q config/ https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/$CONFIG_FILE + fi + fi +} + run() { docker_image @@ -75,15 +103,6 @@ run() { fi fi - if [[ ! -d 'config' || ! -f "config/$CONFIG_FILE" ]]; then - mkdir -p config - if test curl; then - curl -o config/$CONFIG_FILE -LO https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/main_net_config.conf - elif test wget; then - wget -P config/ https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/main_net_config.conf - fi - fi - volume="" parameter="" tron_parameter="" @@ -100,34 +119,56 @@ run() { ;; -c) tron_parameter="$tron_parameter -c $2" + UPDATE_CONFIG=false + shift 2 + ;; + --net) + if [[ "$2" = "main" ]]; then + CONFIG_FILE=$MAIN_NET_CONFIG_FILE + elif [[ "$2" = "test" ]]; then + CONFIG_FILE=$TEST_NET_CONFIG_FILE + elif [[ "$2" = "private" ]]; then + CONFIG_FILE=$PRIVATE_NET_CONFIG_FILE + fi + shift 2 + ;; + --update-config) + UPDATE_CONFIG=$2 shift 2 ;; *) - echo "arg: $1 is not a valid parameter" + echo "run: arg $1 is not a valid parameter" exit ;; esac done + if [ $UPDATE_CONFIG = true ]; then + download_config + fi - if [ -z "$volume" ]; then - volume=" -v $CONFIG:/java-tron/config -v $OUTPUT_DIRECTORY:/java-tron/output-directory" - fi + if [ -z "$volume" ]; then + volume=" -v $CONFIG:/java-tron/config -v $OUTPUT_DIRECTORY:/java-tron/output-directory" + fi - if [ -z "$parameter" ]; then - parameter=" -p $HOST_HTTP_PORT:$DOCKER_HTTP_PORT -p $HOST_RPC_PORT:$DOCKER_RPC_PORT -p $HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT" - fi + if [ -z "$parameter" ]; then + parameter=" -p $HOST_HTTP_PORT:$DOCKER_HTTP_PORT -p $HOST_RPC_PORT:$DOCKER_RPC_PORT -p $HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT" + fi - if [ -z "$tron_parameter" ]; then - tron_parameter=" -c $CONFIG_PATH$CONFIG_FILE" - fi - # Using custom parameters - docker run -d -it --name "$DOCKER_REPOSITORY-$DOCKER_IMAGES" \ - $volume \ - $parameter \ - --restart always \ - "$DOCKER_REPOSITORY/$DOCKER_IMAGES:$DOCKER_TARGET" \ - $tron_parameter + if [ -z "$tron_parameter" ]; then + tron_parameter=" -c $CONFIG_PATH$CONFIG_FILE" + fi + + # Using custom parameters + docker run -d -it --name "$DOCKER_REPOSITORY-$DOCKER_IMAGES" \ + $volume \ + $parameter \ + --restart always \ + "$DOCKER_REPOSITORY/$DOCKER_IMAGES:$DOCKER_TARGET" \ + $tron_parameter else + if [ $UPDATE_CONFIG = true ]; then + download_config + fi # Default parameters docker run -d -it --name "$DOCKER_REPOSITORY-$DOCKER_IMAGES" \ -v $CONFIG:/java-tron/config \ @@ -215,36 +256,36 @@ log() { } case "$1" in ---pull) - pull ${@: 2} - exit - ;; ---start) - start ${@: 2} - exit - ;; ---stop) - stop ${@: 2} - exit - ;; ---build) - build ${@: 2} - exit - ;; ---run) - run ${@: 2} - exit - ;; ---rm) - rm_container ${@: 2} - exit - ;; ---log) - log ${@: 2} - exit - ;; -*) - echo "arg: $1 is not a valid parameter" - exit - ;; + --pull) + pull ${@: 2} + exit + ;; + --start) + start ${@: 2} + exit + ;; + --stop) + stop ${@: 2} + exit + ;; + --build) + build ${@: 2} + exit + ;; + --run) + run ${@: 2} + exit + ;; + --rm) + rm_container ${@: 2} + exit + ;; + --log) + log ${@: 2} + exit + ;; + *) + echo "arg: $1 is not a valid parameter" + exit + ;; esac From f2475881723f19fd96ba989e4554f70948e5949e Mon Sep 17 00:00:00 2001 From: liukai Date: Mon, 28 Mar 2022 11:58:37 +0800 Subject: [PATCH 0033/1197] feat(docker): format documents 1. remove extra spaces 2. change the background colour of the config 3. modify the network specification --- docker/docker.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/docker/docker.md b/docker/docker.md index 29e4afad64d..3c32830b6c4 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -5,15 +5,15 @@ java-tron support containerized processes, we maintain a Docker image with lates ## Prerequisites -Requires docker to be installed on the system. Docker version >=20.10.12. +Requires a docker to be installed on the system. Docker version >=20.10.12. ## Quick Start Shell can be obtained from the java-tron project or independently, you can get the script from [here](https://github.com/tronprotocol/java-tron/docker.sh) or download via the wget: - ```shell - $ wget https://raw.githubusercontent.com/tronprotocol/java-tron/develop/docker.sh - ``` +```shell +$ wget https://raw.githubusercontent.com/tronprotocol/java-tron/develop/docker.sh +``` ### Pull the mirror image Get the `tronprotocol/java-tron` image from the DockerHub, this image contains the full JDK environment and the host network configuration file, using the script for simple docker operations. @@ -27,32 +27,32 @@ Before running the java-tron service, make sure some ports on your local machine - `50051`: used by the GRPC based API - `18888`: TCP and UDP, used by the P2P protocol running the network -#### Full node on the main network +#### Full node on the main network ```shell $ sh docker.sh --run --net main ``` -or you can use `-p` to customize the port mapping, more custom parameters, please refer to [Options](#Options) +or you can use `-p` to customize the port mapping, more custom parameters, please refer to [Options](#Options) ```shell -$ sh docker.sh --run --net main -p 8080:8090 -p 40051:50051 +$ sh docker.sh --run --net main -p 8080:8090 -p 40051:50051 ``` #### Full node on the nile test network ```shell -$ sh docker.sh --run --net net +$ sh docker.sh --run --net test ``` #### Full node on the private network -you can also build your own private-net and will download a configuration file from the network for your private network, which will be stored in your local config/ directory. +you can also build your own private-net and will download a configuration file from the network for your private network, which will be stored in your local `config` directory. ```shell $ sh docker.sh --run --net private ``` #### Configuration -The script will automatically download and use the corresponding configuration file from the github repository according to the `--net` parameter. if you don't want to update the configuration file every time you start the service, please add a startup parameter: +The script will automatically download and use the corresponding configuration file from the github repository according to the `--net` parameter. if you don't want to update the configuration file every time you start the service, please add a startup parameter. ```shell -$ sh docker.sh --run --update-config false +$ sh docker.sh --run --update-config false ``` Or use the `-c` parameter to specify your own configuration file, which will not automatically download a new configuration file from github repository. @@ -96,14 +96,14 @@ $ sh docker.sh --build Parameters for all functions: * **`--build`** building a local mirror image -* **`--pull`** download a docker mirror from **DockerHub** -* **`--run`** run the docker mirror -* **`--log`** exporting the java-tron run log on the container -* **`--stop`** stopping a running container +* **`--pull`** download a docker mirror from **DockerHub** +* **`--run`** run the docker mirror +* **`--log`** exporting the java-tron run log on the container +* **`--stop`** stopping a running container * **`--rm`** remove container,only deletes the container, not the image * **`-p`** publish a container's port to the host, format:`-p hostPort:containerPort` * **`-c`** specify other java-tron configuration file in the container -* **`-v`** bind mount a volume for container,format: `-v host-src:container-dest`, the `host-src` is an absolute path +* **`-v`** bind mount a volume for the container,format: `-v host-src:container-dest`, the `host-src` is an absolute path * **`--net`** select the network, you can join the main-net, test-net * **`--update-config`** update configuration file, default true From d99a5473726fd64cff90ac2aaa08c7f93b43c7aa Mon Sep 17 00:00:00 2001 From: hongdexiang <1090664234@qq.com> Date: Mon, 28 Mar 2022 14:47:39 +0800 Subject: [PATCH 0034/1197] change : add codeAddress parameter in program constructor --- .../org/tron/core/actuator/VMActuator.java | 4 +- .../org/tron/core/vm/program/Program.java | 28 +-- .../program/invoke/ProgramInvokeMockImpl.java | 12 +- .../common/runtime/vm/InterpreterTest.java | 13 +- .../common/runtime/vm/IsSRCandidateTest.java | 8 +- .../common/runtime/vm/OperationsTest.java | 164 +++++++++--------- .../common/runtime/vm/RewardBalanceTest.java | 10 +- 7 files changed, 132 insertions(+), 107 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 83f2c1c0367..c14857572f4 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -384,7 +384,7 @@ private void create() .createProgramInvoke(TrxType.TRX_CONTRACT_CREATION_TYPE, executorType, trx, tokenValue, tokenId, blockCap.getInstance(), rootRepository, vmStartInUs, vmShouldEndInUs, energyLimit); - this.program = new Program(ops, programInvoke, rootInternalTx); + this.program = new Program(ops, contractAddress, programInvoke, rootInternalTx); if (VMConfig.allowTvmCompatibleEvm()) { this.program.setContractVersion(1); } @@ -500,7 +500,7 @@ private void call() programInvoke.setConstantCall(); } rootInternalTx = new InternalTransaction(trx, trxType); - this.program = new Program(code, programInvoke, rootInternalTx); + this.program = new Program(code, contractAddress, programInvoke, rootInternalTx); if (VMConfig.allowTvmCompatibleEvm()) { this.program.setContractVersion(deployedContract.getContractVersion()); } diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 68834e72b34..fc7e39554a1 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -104,6 +104,7 @@ public class Program { private ProgramResult result = new ProgramResult(); private ProgramTrace trace = new ProgramTrace(); private byte[] ops; + private byte[] codeAddress; private int pc; private byte lastOp; private byte previouslyExecutedOp; @@ -112,14 +113,12 @@ public class Program { private int contractVersion; private DataWord adjustedCallEnergy; - public Program(byte[] ops, ProgramInvoke programInvoke) { - this(ops, programInvoke, null); - } - - public Program(byte[] ops, ProgramInvoke programInvoke, InternalTransaction internalTransaction) { + public Program(byte[] ops, byte[] codeAddress, ProgramInvoke programInvoke, + InternalTransaction internalTransaction) { this.invoke = programInvoke; this.internalTransaction = internalTransaction; this.ops = nullToEmpty(ops); + this.codeAddress = codeAddress; traceListener = new ProgramTraceListener(VMConfig.vmTrace()); this.memory = setupProgramListener(new Memory()); @@ -646,7 +645,7 @@ this, new DataWord(newAddress), getContractAddress(), value, DataWord.ZERO(), "Trying to create a contract with existing contract address: 0x" + Hex .toHexString(newAddress))); } else if (isNotEmpty(programCode)) { - Program program = new Program(programCode, programInvoke, internalTx); + Program program = new Program(programCode, newAddress, programInvoke, internalTx); program.setRootTransactionId(this.rootTransactionId); if (VMConfig.allowTvmCompatibleEvm()) { program.setContractVersion(getContractVersion()); @@ -877,7 +876,7 @@ this, new DataWord(contextAddress), if (isConstantCall()) { programInvoke.setConstantCall(); } - Program program = new Program(programCode, programInvoke, internalTx); + Program program = new Program(programCode, codeAddress, programInvoke, internalTx); program.setRootTransactionId(this.rootTransactionId); if (VMConfig.allowTvmCompatibleEvm()) { program.setContractVersion(invoke.getDeposit() @@ -1043,9 +1042,18 @@ public byte[] getCodeHashAt(DataWord address) { } } - private byte[] getCodeHash() { - ContractCapsule contract = getContractState().getContract(getContextAddress()); - return contract.getCodeHash(); + public byte[] getCodeHash() { + ContractCapsule contract = getContractState().getContract(codeAddress); + byte[] codeHash; + if (contract == null) { + codeHash = Hash.sha3(ops); + } else { + codeHash = contract.getCodeHash(); + if (ByteUtil.isNullOrZeroArray(codeHash)) { + codeHash = Hash.sha3(ops); + } + } + return codeHash; } private Key getCodeHashKey() { diff --git a/actuator/src/main/java/org/tron/core/vm/program/invoke/ProgramInvokeMockImpl.java b/actuator/src/main/java/org/tron/core/vm/program/invoke/ProgramInvokeMockImpl.java index 71fd484c7a3..8674608f22a 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/invoke/ProgramInvokeMockImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/program/invoke/ProgramInvokeMockImpl.java @@ -29,7 +29,6 @@ public ProgramInvokeMockImpl(byte[] msgDataRaw) { } public ProgramInvokeMockImpl() { - this.deposit = RepositoryImpl.createRoot(null); this.deposit.createAccount(ownerAddress, Protocol.AccountType.Normal); @@ -45,6 +44,17 @@ public ProgramInvokeMockImpl() { + "00603f556103e75660005460005360200235")); } + public ProgramInvokeMockImpl(byte[] op, byte[] opAddress) { + this.deposit = RepositoryImpl.createRoot(null); + this.deposit.createAccount(opAddress, Protocol.AccountType.Normal); + + this.deposit.createAccount(opAddress, Protocol.AccountType.Contract); + this.deposit.createContract(opAddress, + new ContractCapsule(SmartContract.newBuilder().setContractAddress( + ByteString.copyFrom(op)).build())); + this.deposit.saveCode(opAddress, op); + } + public ProgramInvokeMockImpl(boolean defaults) { } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/InterpreterTest.java b/framework/src/test/java/org/tron/common/runtime/vm/InterpreterTest.java index c2c5305df42..d54330b95fe 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/InterpreterTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/InterpreterTest.java @@ -54,14 +54,14 @@ public static void destroy() { @Test public void testVMException() throws ContractValidateException { - invoke = new ProgramInvokeMockImpl(); byte[] op = {0x5b, 0x60, 0x00, 0x56}; // 0x5b - JUMPTEST // 0x60 0x00 - PUSH 0x00 // 0x56 - JUMP to 0 Transaction trx = Transaction.getDefaultInstance(); InternalTransaction interTrx = new InternalTransaction(trx, TrxType.TRX_UNKNOWN_TYPE); - program = new Program(op, invoke, interTrx); + invoke = new ProgramInvokeMockImpl(op, op); + program = new Program(op, op, invoke, interTrx); boolean result = false; @@ -96,7 +96,8 @@ public void JumpSingleOperation() throws ContractValidateException { // 0x56 - JUMP Transaction trx = Transaction.getDefaultInstance(); InternalTransaction interTrx = new InternalTransaction(trx, TrxType.TRX_UNKNOWN_TYPE); - program = new Program(op, invoke, interTrx); + invoke = new ProgramInvokeMockImpl(op, op); + program = new Program(op, op, invoke, interTrx); boolean result = false; @@ -134,7 +135,8 @@ public void JumpToInvalidDestination() throws ContractValidateException { // 0x56 - JUMP Transaction trx = Transaction.getDefaultInstance(); InternalTransaction interTrx = new InternalTransaction(trx, TrxType.TRX_UNKNOWN_TYPE); - program = new Program(op, invoke, interTrx); + invoke = new ProgramInvokeMockImpl(op, op); + program = new Program(op, op, invoke, interTrx); boolean result = false; @@ -173,7 +175,8 @@ public void JumpToLargeNumberDestination() throws ContractValidateException { // 0x56 - JUMP Transaction trx = Transaction.getDefaultInstance(); InternalTransaction interTrx = new InternalTransaction(trx, TrxType.TRX_UNKNOWN_TYPE); - program = new Program(op, invoke, interTrx); + invoke = new ProgramInvokeMockImpl(op, op); + program = new Program(op, op, invoke, interTrx); boolean result = false; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/IsSRCandidateTest.java b/framework/src/test/java/org/tron/common/runtime/vm/IsSRCandidateTest.java index 46445e92826..f0895ac5500 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/IsSRCandidateTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/IsSRCandidateTest.java @@ -174,7 +174,7 @@ public void testIsSRCandidate() System.nanoTime() / 1000, System.nanoTime() / 1000 + 50000, 3_000_000L); - Program program = new Program(null, programInvoke, rootInternalTransaction); + Program program = new Program(null, null, programInvoke, rootInternalTransaction); byte[] programResult = program.isSRCandidate(new DataWord(nonexistentAddr)).getData(); Assert.assertEquals( Hex.toHexString(programResult), @@ -201,7 +201,7 @@ public void testIsSRCandidate() System.nanoTime() / 1000, System.nanoTime() / 1000 + 50000, 3_000_000L); - program = new Program(null, programInvoke, rootInternalTransaction); + program = new Program(null, null, programInvoke, rootInternalTransaction); programResult = program.isSRCandidate(new DataWord(factoryAddress)).getData(); Assert.assertEquals( Hex.toHexString(programResult), @@ -230,7 +230,7 @@ public void testIsSRCandidate() System.nanoTime() / 1000, System.nanoTime() / 1000 + 50000, 3_000_000L); - program = new Program(null, programInvoke, rootInternalTransaction); + program = new Program(null, null, programInvoke, rootInternalTransaction); programResult = program.isSRCandidate(new DataWord(witnessAddr)).getData(); Assert.assertEquals( Hex.toHexString(programResult), @@ -258,7 +258,7 @@ public void testIsSRCandidate() System.nanoTime() / 1000, System.nanoTime() / 1000 + 50000, 3_000_000L); - program = new Program(null, programInvoke, rootInternalTransaction); + program = new Program(null, null, programInvoke, rootInternalTransaction); programResult = program.isSRCandidate(new DataWord()).getData(); Assert.assertEquals( Hex.toHexString(programResult), diff --git a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java index abdf8d3db78..11126a798d9 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java @@ -93,8 +93,8 @@ public void testStackOverFlow() { @SneakyThrows private Program buildEmptyContext(byte[] ops) { Program context = new Program( - ops, - new ProgramInvokeMockImpl(), + ops, ops, + new ProgramInvokeMockImpl(ops, ops), new InternalTransaction( Protocol.Transaction.getDefaultInstance(), InternalTransaction.TrxType.TRX_UNKNOWN_TYPE)); @@ -112,77 +112,77 @@ public void testArithmeticOperations() throws ContractValidateException { // test ADD byte[] op = {0x60, 0x01, 0x60, 0x01, 0x01}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x02), program.getStack().pop()); // test MUL op = new byte[]{0x60, 0x01, 0x60, 0x01, 0x02}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(11, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x01), program.getStack().pop()); // test SUB op = new byte[]{0x60, 0x01, 0x60, 0x01, 0x03}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x00), program.getStack().pop()); // test DIV op = new byte[]{0x60, 0x01, 0x60, 0x02, 0x04}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(11, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x02), program.getStack().pop()); // test SDIV op = new byte[]{0x60, 0x01, 0x60, 0x01, 0x05}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(11, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x01),program.getStack().pop()); // test MOD op = new byte[]{0x60, 0x02, 0x60, 0x01, 0x06}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(11, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x01), program.getStack().pop()); // test SMOD op = new byte[]{0x60, 0x02, 0x60, 0x01, 0x07}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(11, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x01), program.getStack().pop()); // test ADDMOD op = new byte[]{0x60, 0x02, 0x60, 0x01, 0x60, 0x01, 0x08}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(17, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x00), program.getStack().pop()); // test MULMOD op = new byte[]{0x60, 0x02, 0x60, 0x01, 0x60, 0x01, 0x09}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx);; testOperations(program); Assert.assertEquals(17, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x01), program.getStack().pop()); // test EXP op = new byte[]{0x60, 0x02, 0x60, 0x02, 0x0a}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(26, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x04), program.getStack().pop()); // test SIGNEXTEND op = new byte[]{0x60, 0x02, 0x60, 0x02, 0x0b}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(11, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x02), program.getStack().pop()); @@ -198,98 +198,98 @@ public void testLogicAndComparisonOperations() throws ContractValidateException // test LT = 0x10 byte[] op = {0x60, 0x01, 0x60, 0x02, 0x10}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x00), program.getStack().pop()); // test GT = 0X11 op = new byte[]{0x60, 0x01, 0x60, 0x02, 0X11}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x01), program.getStack().pop()); // test SLT = 0X12 op = new byte[]{0x60, 0x01, 0x60, 0x02, 0X12}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x00), program.getStack().pop()); // test SGT = 0X13 op = new byte[]{0x60, 0x01, 0x60, 0x02, 0X13}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x01), program.getStack().pop()); // test EQ = 0X14 op = new byte[]{0x60, 0x01, 0x60, 0x02, 0X14}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx);; testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x00), program.getStack().pop()); // test ISZERO = 0x15 op = new byte[]{0x60, 0x01, 0x15}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(6, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x00), program.getStack().pop()); // test AND = 0x16 op = new byte[]{0x60, 0x01, 0x60, 0x02, 0x16}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x00), program.getStack().pop()); // test OR = 0x17 op = new byte[]{0x60, 0x01, 0x60, 0x02, 0x17}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx);; testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x03), program.getStack().pop()); // test XOR = 0x18 op = new byte[]{0x60, 0x01, 0x60, 0x02, 0x18}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x03), program.getStack().pop()); // test NOT = 0x19 op = new byte[]{0x60, 0x00, 0x19}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(6, program.getResult().getEnergyUsed()); Assert.assertEquals((byte) (-0x01), program.getStack().pop().getData()[31]); // test BYTE = 0x1a op = new byte[]{0x60, 0x01, 0x60, 0x01, 0x1a}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x00), program.getStack().pop()); // test SHL = 0x1b op = new byte[]{0x60, 0x01, 0x60, 0x01, 0x1b}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx);; testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x02), program.getStack().pop()); // test SHR = 0x1c op = new byte[]{0x60, 0x01, 0x60, 0x02, 0x1c}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x00), program.getStack().pop()); // test SAR = 0x1d op = new byte[]{0x60, 0x01, 0x60, 0x02, 0x1d}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x00), program.getStack().pop()); @@ -306,7 +306,7 @@ public void testCryptographicAndEnvironmentalOperations() throws ContractValidat // test SHA3 = 0x20 byte[] op = {0x60, 0x01, 0x60, 0x01, 0x20}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(45, program.getResult().getEnergyUsed()); Assert.assertEquals("bc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a", @@ -314,21 +314,21 @@ public void testCryptographicAndEnvironmentalOperations() throws ContractValidat // test ADDRESS = 0x30 op = new byte[]{0x30}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx);; testOperations(program); Assert.assertEquals(2, program.getResult().getEnergyUsed()); Assert.assertEquals(invoke.getContractAddress(), program.getStack().pop()); // test ORIGIN = 0x32 op = new byte[]{0x32}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(2, program.getResult().getEnergyUsed()); Assert.assertEquals(invoke.getOriginAddress(), program.getStack().pop()); // test CALLER = 0x33 op = new byte[]{0x33}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(2, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(invoke.getCallerAddress().getLast20Bytes()), @@ -336,28 +336,28 @@ public void testCryptographicAndEnvironmentalOperations() throws ContractValidat // CALLVALUE = 0x34 op = new byte[]{0x34}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(2, program.getResult().getEnergyUsed()); Assert.assertEquals(invoke.getCallValue(), program.getStack().pop()); // CALLDATALOAD = 0x35 op = new byte[]{0x60, 0x01, 0x35}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(6, program.getResult().getEnergyUsed()); Assert.assertEquals(invoke.getDataValue(new DataWord(0x01)), program.getStack().pop()); // CALLDATASIZE = 0x36 op = new byte[]{0x60, 0x01, 0x36}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(5, program.getResult().getEnergyUsed()); Assert.assertEquals(invoke.getDataSize(), program.getStack().pop()); // CALLDATACOPY = 0x37 op = new byte[]{0x60, 0x01, 0x60, 0x01, 0x60, 0x01, 0x37}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(15, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(invoke.getDataCopy(new DataWord(0x01), @@ -366,14 +366,14 @@ public void testCryptographicAndEnvironmentalOperations() throws ContractValidat // CODESIZE = 0x38 op = new byte[]{0x38}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(2, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x01), program.getStack().pop()); // CODECOPY = 0x39 op = new byte[]{0x60, 0x01, 0x60, 0x01, 0x60, 0x01, 0x39}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(15, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x00), new DataWord( @@ -381,14 +381,14 @@ public void testCryptographicAndEnvironmentalOperations() throws ContractValidat // RETURNDATASIZE = 0x3d op = new byte[]{0x3d}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(2, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x00), program.getStack().pop()); // RETURNDATACOPY = 0x3e op = new byte[]{0x60, 0x01, 0x60, 0x01, 0x60, 0x01, 0x3e}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(50, program.getResult().getEnergyUsed()); Assert.assertNull( @@ -396,7 +396,7 @@ public void testCryptographicAndEnvironmentalOperations() throws ContractValidat // GASPRICE = 0x3a op = new byte[]{0x3a}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(2, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0), program.getStack().pop()); @@ -412,7 +412,7 @@ public void testBlockInformationOperations() throws ContractValidateException { // BLOCKHASH = 0x40 byte[] op = {0x40}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); program.stackPush(new DataWord(33)); testOperations(program); Assert.assertEquals(20, program.getResult().getEnergyUsed()); @@ -420,7 +420,7 @@ public void testBlockInformationOperations() throws ContractValidateException { // COINBASE = 0x41 op = new byte[]{0x41}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(2, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(invoke.getCoinbase().getLast20Bytes()), @@ -428,28 +428,28 @@ public void testBlockInformationOperations() throws ContractValidateException { // TIMESTAMP = 0x42 op = new byte[]{0x42}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(2, program.getResult().getEnergyUsed()); Assert.assertEquals(invoke.getTimestamp(), program.getStack().pop()); // NUMBER = 0x43 op = new byte[]{0x43}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(2, program.getResult().getEnergyUsed()); Assert.assertEquals(invoke.getNumber(), program.getStack().pop()); // DIFFICULTY = 0x44 op = new byte[]{0x44}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(2, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0), program.getStack().pop()); // GASLIMIT = 0x45 op = new byte[]{0x45}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(2, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0), program.getStack().pop()); @@ -470,28 +470,28 @@ public void testMemoryStorageAndFlowOperations() throws ContractValidateExceptio // POP = 0x50 byte[] op = {0x60, 0x01, 0x50}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(5, program.getResult().getEnergyUsed()); Assert.assertEquals(0, program.getStack().size()); // MLOAD = 0x51 op = new byte[]{0x60, 0x01, 0x51}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x00), program.getStack().pop()); // MSTORE = 0x52 op = new byte[]{0x60, 0x01, 0x60, 0x01, 0x52}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(12, program.getResult().getEnergyUsed()); Assert.assertEquals(64, program.getMemSize()); // MSTORE8 = 0x53 op = new byte[]{0x60, 0x01, 0x60, 0x01, 0x53}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx);; testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed(), 41); Assert.assertEquals(32, program.getMemSize()); @@ -499,8 +499,10 @@ public void testMemoryStorageAndFlowOperations() throws ContractValidateExceptio // JUMP = 0x56 // JUMPI = 0x57 // JUMPDEST = 0x5b - program = new Program(compile( - "PUSH1 0x01 PUSH1 0x05 JUMPI JUMPDEST PUSH1 0xCC"), invoke, interTrx); + op = compile( + "PUSH1 0x01 PUSH1 0x05 JUMPI JUMPDEST PUSH1 0xCC"); + invoke = new ProgramInvokeMockImpl(op, op); + program = new Program(op, op, invoke, interTrx); testSingleOperation(program); testSingleOperation(program); testSingleOperation(program); @@ -512,21 +514,21 @@ public void testMemoryStorageAndFlowOperations() throws ContractValidateExceptio // PC = 0x58 op = new byte[]{0x60, 0x01, 0x60, 0x00, 0x58}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(8, program.getResult().getEnergyUsed()); Assert.assertEquals(5, program.getPC()); // MSIZE = 0x59 op = new byte[]{0x60, 0x01, 0x60, 0x00, 0x59}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(8, program.getResult().getEnergyUsed()); Assert.assertEquals(0, program.getMemSize()); // GAS = 0x5a op = new byte[]{0x60, 0x01, 0x60, 0x00, 0x5a}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(8, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x2a), program.getStack().pop()); @@ -559,7 +561,7 @@ public void testPushDupSwapAndLogOperations() throws ContractValidateException { for (int j = 0; j <= i; j++) { op[j + 1] = 0x01; } - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(3, program.getResult().getEnergyUsed()); byte[] result = new byte[i + 1]; @@ -591,7 +593,7 @@ public void testPushDupSwapAndLogOperations() throws ContractValidateException { op[2 * j] = 0x60; op[2 * j + 1] = (byte) i; } - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(3L * (i + 2), program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(i), program.getStack().pop()); @@ -619,7 +621,7 @@ public void testPushDupSwapAndLogOperations() throws ContractValidateException { op[2 * (j + 1)] = 0x60; op[2 * (j + 1) + 1] = (byte) i; } - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals((3L * (i + 3)), program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x01), program.getStack().pop()); @@ -627,8 +629,9 @@ public void testPushDupSwapAndLogOperations() throws ContractValidateException { // test log(0-4) invoke.setEnergyLimit(5000); - program = new Program(compile( - "PUSH2 0x1234 PUSH1 0x00 MSTORE PUSH1 0x20 PUSH1 0x00 LOG0"), invoke, interTrx); + byte[] op = compile( + "PUSH2 0x1234 PUSH1 0x00 MSTORE PUSH1 0x20 PUSH1 0x00 LOG0"); + program = new Program(op, op, invoke, interTrx); testSingleOperation(program); testSingleOperation(program); testSingleOperation(program); @@ -645,9 +648,9 @@ public void testPushDupSwapAndLogOperations() throws ContractValidateException { .getData())); Assert.assertEquals(646, program.getResult().getEnergyUsed()); - program = new Program(compile( - "PUSH2 0x1234 PUSH1 0x00 MSTORE PUSH2 0x9999 PUSH1 0x20 PUSH1 0x00 LOG1"), - invoke, interTrx); + op = compile( + "PUSH2 0x1234 PUSH1 0x00 MSTORE PUSH2 0x9999 PUSH1 0x20 PUSH1 0x00 LOG1"); + program = new Program(op, op, invoke, interTrx); testSingleOperation(program); testSingleOperation(program); testSingleOperation(program); @@ -665,9 +668,9 @@ public void testPushDupSwapAndLogOperations() throws ContractValidateException { .getData())); Assert.assertEquals(1024, program.getResult().getEnergyUsed()); - program = new Program(compile( - "PUSH2 0x1234 PUSH1 0x00 MSTORE PUSH2 0x9999 PUSH2 0x6666 PUSH1 0x20 PUSH1 0x00 LOG2"), - invoke, interTrx); + op = compile( + "PUSH2 0x1234 PUSH1 0x00 MSTORE PUSH2 0x9999 PUSH2 0x6666 PUSH1 0x20 PUSH1 0x00 LOG2"); + program = new Program(op, op, invoke, interTrx); testSingleOperation(program); testSingleOperation(program); testSingleOperation(program); @@ -686,8 +689,9 @@ public void testPushDupSwapAndLogOperations() throws ContractValidateException { .getData())); Assert.assertEquals(1402, program.getResult().getEnergyUsed()); - program = new Program(compile("PUSH2 0x1234 PUSH1 0x00 MSTORE PUSH2 0x9999" - + " PUSH2 0x6666 PUSH2 0x3333 PUSH1 0x20 PUSH1 0x00 LOG3"), invoke, interTrx); + op = compile("PUSH2 0x1234 PUSH1 0x00 MSTORE PUSH2 0x9999" + + " PUSH2 0x6666 PUSH2 0x3333 PUSH1 0x20 PUSH1 0x00 LOG3"); + program = new Program(op, op, invoke, interTrx); testSingleOperation(program); testSingleOperation(program); testSingleOperation(program); @@ -707,8 +711,9 @@ public void testPushDupSwapAndLogOperations() throws ContractValidateException { .getData())); Assert.assertEquals(1780, program.getResult().getEnergyUsed()); - program = new Program(compile("PUSH2 0x1234 PUSH1 0x00 MSTORE PUSH2 0x9999 PUSH2" - + " 0x6666 PUSH2 0x3333 PUSH2 0x5555 PUSH1 0x20 PUSH1 0x00 LOG4"), invoke, interTrx); + op = compile("PUSH2 0x1234 PUSH1 0x00 MSTORE PUSH2 0x9999 PUSH2" + + " 0x6666 PUSH2 0x3333 PUSH2 0x5555 PUSH1 0x20 PUSH1 0x00 LOG4"); + program = new Program(op, op, invoke, interTrx); testSingleOperation(program); testSingleOperation(program); testSingleOperation(program); @@ -738,14 +743,14 @@ public void testOtherOperations() throws ContractValidateException { // STOP = 0x00 byte[] op = {0x00}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(0, program.getResult().getEnergyUsed()); Assert.assertTrue(program.isStopped()); // return = 0xf3 op = new byte[]{0x60, 0x01, 0x60, 0x01, (byte) 0xf3}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(1, program.getResult().getHReturn().length); @@ -753,7 +758,7 @@ public void testOtherOperations() throws ContractValidateException { // revert = 0xfd op = new byte[]{0x60, 0x01, 0x60, 0x01, (byte) 0xfd}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(1, program.getResult().getHReturn().length); @@ -771,7 +776,7 @@ public void testComplexOperations() throws ContractValidateException { // test BALANCE = 0x31 byte[] op = new byte[]{0x31}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); program.stackPush(new DataWord("41471fd3ad3e9eeadeec4608b92d16ce6b500704cc")); testOperations(program); Assert.assertEquals(20, program.getResult().getEnergyUsed()); @@ -779,7 +784,7 @@ public void testComplexOperations() throws ContractValidateException { // SELFBALANCE = 0x47 op = new byte[]{0x47}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(5, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0),program.getStack().pop()); @@ -792,9 +797,8 @@ public void testComplexOperations() throws ContractValidateException { invoke.getDeposit().putStorageValue(Hex.decode( "41471fd3ad3e9eeadeec4608b92d16ce6b500704cc"), new DataWord(0xCC), new DataWord(0x01)); - program = new Program( - compile("PUSH1 0x22 PUSH1 0xAA SSTORE PUSH1 0x33 PUSH1 0xCC SSTORE PUSH1 0xCC SLOAD"), - invoke, interTrx); + op = compile("PUSH1 0x22 PUSH1 0xAA SSTORE PUSH1 0x33 PUSH1 0xCC SSTORE PUSH1 0xCC SLOAD"); + program = new Program(op, op, invoke, interTrx); testSingleOperation(program); testSingleOperation(program); testSingleOperation(program); @@ -809,7 +813,7 @@ public void testComplexOperations() throws ContractValidateException { // EXTCODESIZE = 0x3b op = new byte[]{0x3b}; - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); program.stackPush(new DataWord("471fd3ad3e9eeadeec4608b92d16ce6b500704cc")); testOperations(program); Assert.assertEquals(20, program.getResult().getEnergyUsed()); @@ -817,7 +821,7 @@ public void testComplexOperations() throws ContractValidateException { // EXTCODECOPY = 0x3c op = Hex.decode("60036007600073471FD3AD3E9EEADEEC4608B92D16CE6B500704CC3C123456"); - program = new Program(op, invoke, interTrx); + program = new Program(op, op, invoke, interTrx); testSingleOperation(program); testSingleOperation(program); testSingleOperation(program); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/RewardBalanceTest.java b/framework/src/test/java/org/tron/common/runtime/vm/RewardBalanceTest.java index 5fc95be728f..43f30126f20 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/RewardBalanceTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/RewardBalanceTest.java @@ -168,7 +168,7 @@ public void testRewardBalance() InternalTransaction.ExecutorType.ET_PRE_TYPE, trx, 0, 0, blockCap.getInstance(), repository, System.nanoTime() / 1000, System.nanoTime() / 1000 + 50000, 3_000_000L); - Program program = new Program(null, programInvoke, rootInternalTransaction); + Program program = new Program(null, null, programInvoke, rootInternalTransaction); byte[] result = program.getRewardBalance(new DataWord(Base58.decode(nonexistentAccount))) .getData(); @@ -188,7 +188,7 @@ public void testRewardBalance() InternalTransaction.ExecutorType.ET_PRE_TYPE, trx, 0, 0, blockCap.getInstance(), repository, System.nanoTime() / 1000, System.nanoTime() / 1000 + 50000, 3_000_000L); - program = new Program(null, programInvoke, rootInternalTransaction); + program = new Program(null, null, programInvoke, rootInternalTransaction); result = program.getRewardBalance(new DataWord(Base58.decode(factoryAddressStr))).getData(); Assert.assertEquals(Hex.toHexString(result), "0000000000000000000000000000000000000000000000000000000000000000"); @@ -207,7 +207,7 @@ public void testRewardBalance() InternalTransaction.ExecutorType.ET_PRE_TYPE, trx, 0, 0, blockCap.getInstance(), repository, System.nanoTime() / 1000, System.nanoTime() / 1000 + 50000, 3_000_000L); - program = new Program(null, programInvoke, rootInternalTransaction); + program = new Program(null, null, programInvoke, rootInternalTransaction); result = program.getRewardBalance(new DataWord(Base58.decode(witnessAccount))).getData(); Assert.assertEquals(Hex.toHexString(result), "0000000000000000000000000000000000000000000000000000000000000000"); @@ -226,7 +226,7 @@ public void testRewardBalance() InternalTransaction.ExecutorType.ET_PRE_TYPE, trx, 0, 0, blockCap.getInstance(), repository, System.nanoTime() / 1000, System.nanoTime() / 1000 + 50000, 3_000_000L); - program = new Program(null, programInvoke, rootInternalTransaction); + program = new Program(null, null, programInvoke, rootInternalTransaction); result = program.getRewardBalance(DataWord.ZERO()).getData(); Assert.assertEquals(Hex.toHexString(result), "0000000000000000000000000000000000000000000000000000000000000000"); @@ -245,7 +245,7 @@ public void testRewardBalance() InternalTransaction.ExecutorType.ET_PRE_TYPE, trx, 0, 0, blockCap.getInstance(), repository, System.nanoTime() / 1000, System.nanoTime() / 1000 + 50000, 3_000_000L); - program = new Program(null, programInvoke, rootInternalTransaction); + program = new Program(null, null, programInvoke, rootInternalTransaction); result = program.getRewardBalance(new DataWord(Base58.decode(factoryAddressStr))).getData(); Assert.assertEquals(Hex.toHexString(result), "0000000000000000000000000000000000000000000000000000000000000000"); From a01c82418f75e0a9eef04770c7c8da9a79d05592 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 29 Mar 2022 12:04:34 +0800 Subject: [PATCH 0035/1197] feature(api): add `detail` for block query,if trxs info needed. 1. http 2. grpc --- .../src/main/java/org/tron/core/Wallet.java | 42 +- .../org/tron/core/services/RpcApiService.java | 593 +++++++++--------- .../services/http/GetBlockByIdServlet.java | 11 +- .../http/GetBlockByLatestNumServlet.java | 9 +- .../http/GetBlockByLimitNextServlet.java | 10 +- .../services/http/GetBlockByNumServlet.java | 9 +- .../services/http/GetNowBlockServlet.java | 5 +- .../tron/core/services/http/PostParams.java | 14 +- .../org/tron/core/services/http/Util.java | 21 + protocol/src/main/protos/api/api.proto | 8 +- 10 files changed, 407 insertions(+), 315 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index cf4d416e56c..05f3fab11d1 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -645,18 +645,36 @@ public byte[] createAddress(byte[] passPhrase) { return ecKey.getAddress(); } + public Block dealBlock(Block block, boolean detail) { + if (Objects.isNull(block)) { + return null; + } + if (detail) { + return block; + } + return block.toBuilder().clearTransactions().build(); + } + public Block getNowBlock() { + return getNowBlock(true); + } + + public Block getNowBlock(boolean detail) { List blockList = chainBaseManager.getBlockStore().getBlockByLatestNum(1); if (CollectionUtils.isEmpty(blockList)) { return null; - } else { - return blockList.get(0).getInstance(); } + return dealBlock(blockList.get(0).getInstance(), detail); + } public Block getBlockByNum(long blockNum) { + return getBlockByNum(blockNum, true); + } + + public Block getBlockByNum(long blockNum, boolean detail) { try { - return chainBaseManager.getBlockByNum(blockNum).getInstance(); + return dealBlock(chainBaseManager.getBlockByNum(blockNum).getInstance(),detail); } catch (StoreException e) { logger.info(e.getMessage()); return null; @@ -1341,6 +1359,10 @@ public NumberMessage getNextMaintenanceTime() { } public Block getBlockById(ByteString blockId) { + return getBlockById(blockId, true); + } + + public Block getBlockById(ByteString blockId, boolean detail) { if (Objects.isNull(blockId)) { return null; } @@ -1350,23 +1372,31 @@ public Block getBlockById(ByteString blockId) { } catch (StoreException e) { logger.error(e.getMessage()); } - return block; + return dealBlock(block, detail); } public BlockList getBlocksByLimitNext(long number, long limit) { + return getBlocksByLimitNext(number, limit, true); + } + + public BlockList getBlocksByLimitNext(long number, long limit, boolean detail) { if (limit <= 0) { return null; } BlockList.Builder blockListBuilder = BlockList.newBuilder(); chainBaseManager.getBlockStore().getLimitNumber(number, limit).forEach( - blockCapsule -> blockListBuilder.addBlock(blockCapsule.getInstance())); + blockCapsule -> blockListBuilder.addBlock(dealBlock(blockCapsule.getInstance(), detail))); return blockListBuilder.build(); } public BlockList getBlockByLatestNum(long getNum) { + return getBlockByLatestNum(getNum, true); + } + + public BlockList getBlockByLatestNum(long getNum, boolean detail) { BlockList.Builder blockListBuilder = BlockList.newBuilder(); chainBaseManager.getBlockStore().getBlockByLatestNum(getNum).forEach( - blockCapsule -> blockListBuilder.addBlock(blockCapsule.getInstance())); + blockCapsule -> blockListBuilder.addBlock(dealBlock(blockCapsule.getInstance(), detail))); return blockListBuilder.build(); } diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 9c7fe772679..082f68649ac 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -180,7 +180,7 @@ public class RpcApiService implements Service { private static final String EXCEPTION_CAUGHT = "exception caught"; private static final long BLOCK_LIMIT_NUM = 100; private static final long TRANSACTION_LIMIT_NUM = 1000; - private int port = Args.getInstance().getRpcPort(); + private final int port = Args.getInstance().getRpcPort(); private Server apiServer; @Autowired private Manager dbManager; @@ -209,12 +209,12 @@ public class RpcApiService implements Service { private MetricsApiService metricsApiService; @Getter - private DatabaseApi databaseApi = new DatabaseApi(); - private WalletApi walletApi = new WalletApi(); + private final DatabaseApi databaseApi = new DatabaseApi(); + private final WalletApi walletApi = new WalletApi(); @Getter - private WalletSolidityApi walletSolidityApi = new WalletSolidityApi(); + private final WalletSolidityApi walletSolidityApi = new WalletSolidityApi(); @Getter - private MonitorApi monitorApi = new MonitorApi(); + private final MonitorApi monitorApi = new MonitorApi(); @Override public void init() { @@ -286,7 +286,8 @@ public void start() { private void callContract(TriggerSmartContract request, - StreamObserver responseObserver, boolean isConstant) { + StreamObserver responseObserver, + boolean isConstant) { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); try { @@ -324,7 +325,8 @@ private void callContract(TriggerSmartContract request, } private TransactionCapsule createTransactionCapsule(com.google.protobuf.Message message, - ContractType contractType) throws ContractValidateException { + ContractType contractType) + throws ContractValidateException { return wallet.createTransactionCapsule(message, contractType); } @@ -401,6 +403,112 @@ public void blockUntilShutdown() { } } + public void generateAddressCommon(EmptyMessage request, + StreamObserver responseObserver) { + SignInterface cryptoEngine = SignUtils.getGeneratedRandomSign(Utils.getRandom(), + Args.getInstance().isECKeyCryptoEngine()); + byte[] priKey = cryptoEngine.getPrivateKey(); + byte[] address = cryptoEngine.getAddress(); + String addressStr = StringUtil.encode58Check(address); + String priKeyStr = Hex.encodeHexString(priKey); + AddressPrKeyPairMessage.Builder builder = AddressPrKeyPairMessage.newBuilder(); + builder.setAddress(addressStr); + builder.setPrivateKey(priKeyStr); + responseObserver.onNext(builder.build()); + responseObserver.onCompleted(); + } + + public void getRewardInfoCommon(BytesMessage request, + StreamObserver responseObserver) { + try { + long value = dbManager.getMortgageService().queryReward(request.getValue().toByteArray()); + NumberMessage.Builder builder = NumberMessage.newBuilder(); + builder.setNum(value); + responseObserver.onNext(builder.build()); + } catch (Exception e) { + responseObserver.onError(e); + } + responseObserver.onCompleted(); + } + + public void getBurnTrxCommon(EmptyMessage request, + StreamObserver responseObserver) { + try { + long value = dbManager.getDynamicPropertiesStore().getBurnTrxAmount(); + NumberMessage.Builder builder = NumberMessage.newBuilder(); + builder.setNum(value); + responseObserver.onNext(builder.build()); + } catch (Exception e) { + responseObserver.onError(e); + } + responseObserver.onCompleted(); + } + + public void getBrokerageInfoCommon(BytesMessage request, + StreamObserver responseObserver) { + try { + long cycle = dbManager.getDynamicPropertiesStore().getCurrentCycleNumber(); + long value = dbManager.getDelegationStore() + .getBrokerage(cycle, request.getValue().toByteArray()); + NumberMessage.Builder builder = NumberMessage.newBuilder(); + builder.setNum(value); + responseObserver.onNext(builder.build()); + } catch (Exception e) { + responseObserver.onError(e); + } + responseObserver.onCompleted(); + } + + public void getTransactionCountByBlockNumCommon(NumberMessage request, + StreamObserver responseObserver) { + NumberMessage.Builder builder = NumberMessage.newBuilder(); + try { + Block block = chainBaseManager.getBlockByNum(request.getNum()).getInstance(); + builder.setNum(block.getTransactionsCount()); + } catch (StoreException e) { + logger.error(e.getMessage()); + builder.setNum(-1); + } + responseObserver.onNext(builder.build()); + responseObserver.onCompleted(); + } + + public void getTransactionFromPendingCommon(BytesMessage request, + StreamObserver responseObserver) { + try { + String txId = ByteArray.toHexString(request.getValue().toByteArray()); + TransactionCapsule transactionCapsule = dbManager.getTxFromPending(txId); + responseObserver.onNext(transactionCapsule == null ? null : transactionCapsule.getInstance()); + } catch (Exception e) { + responseObserver.onError(e); + } + responseObserver.onCompleted(); + } + + public void getTransactionListFromPendingCommon(EmptyMessage request, + StreamObserver responseObserver) { + try { + TransactionIdList.Builder builder = TransactionIdList.newBuilder(); + builder.addAllTxId(dbManager.getTxListFromPending()); + responseObserver.onNext(builder.build()); + } catch (Exception e) { + responseObserver.onError(e); + } + responseObserver.onCompleted(); + } + + public void getPendingSizeCommon(EmptyMessage request, + StreamObserver responseObserver) { + try { + NumberMessage.Builder builder = NumberMessage.newBuilder(); + builder.setNum(dbManager.getPendingSize()); + responseObserver.onNext(builder.build()); + } catch (Exception e) { + responseObserver.onError(e); + } + responseObserver.onCompleted(); + } + /** * DatabaseApi. */ @@ -408,7 +516,7 @@ public class DatabaseApi extends DatabaseImplBase { @Override public void getBlockReference(org.tron.api.GrpcAPI.EmptyMessage request, - io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.StreamObserver responseObserver) { long headBlockNum = dbManager.getDynamicPropertiesStore() .getLatestBlockHeaderNumber(); byte[] blockHeaderHash = dbManager.getDynamicPropertiesStore() @@ -424,30 +532,32 @@ public void getBlockReference(org.tron.api.GrpcAPI.EmptyMessage request, @Override public void getNowBlock(EmptyMessage request, StreamObserver responseObserver) { Block block = null; + boolean detail = !request.hasBase() || request.getBase().getDetail(); try { block = chainBaseManager.getHead().getInstance(); } catch (StoreException e) { logger.error(e.getMessage()); } - responseObserver.onNext(block); + responseObserver.onNext(wallet.dealBlock(block, detail)); responseObserver.onCompleted(); } @Override public void getBlockByNum(NumberMessage request, StreamObserver responseObserver) { Block block = null; + boolean detail = !request.hasBase() || request.getBase().getDetail(); try { block = chainBaseManager.getBlockByNum(request.getNum()).getInstance(); } catch (StoreException e) { logger.error(e.getMessage()); } - responseObserver.onNext(block); + responseObserver.onNext(wallet.dealBlock(block, detail)); responseObserver.onCompleted(); } @Override public void getDynamicProperties(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { DynamicProperties.Builder builder = DynamicProperties.newBuilder(); builder.setLastSolidityBlockNum( dbManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum()); @@ -494,21 +604,21 @@ public void listWitnesses(EmptyMessage request, StreamObserver resp @Override public void getAssetIssueList(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getAssetIssueList()); responseObserver.onCompleted(); } @Override public void getPaginatedAssetIssueList(PaginatedMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getAssetIssueList(request.getOffset(), request.getLimit())); responseObserver.onCompleted(); } @Override public void getAssetIssueByName(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString assetName = request.getValue(); if (assetName != null) { try { @@ -525,7 +635,7 @@ public void getAssetIssueByName(BytesMessage request, @Override public void getAssetIssueListByName(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString assetName = request.getValue(); if (assetName != null) { @@ -538,7 +648,7 @@ public void getAssetIssueListByName(BytesMessage request, @Override public void getAssetIssueById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString assetId = request.getValue(); if (assetId != null) { @@ -551,14 +661,16 @@ public void getAssetIssueById(BytesMessage request, @Override public void getNowBlock(EmptyMessage request, StreamObserver responseObserver) { - responseObserver.onNext(wallet.getNowBlock()); + boolean detail = !request.hasBase() || request.getBase().getDetail(); + responseObserver.onNext(wallet.getNowBlock(detail)); responseObserver.onCompleted(); } @Override public void getNowBlock2(EmptyMessage request, - StreamObserver responseObserver) { - responseObserver.onNext(block2Extention(wallet.getNowBlock())); + StreamObserver responseObserver) { + boolean detail = !request.hasBase() || request.getBase().getDetail(); + responseObserver.onNext(block2Extention(wallet.getNowBlock(detail))); responseObserver.onCompleted(); } @@ -566,7 +678,8 @@ public void getNowBlock2(EmptyMessage request, public void getBlockByNum(NumberMessage request, StreamObserver responseObserver) { long num = request.getNum(); if (num >= 0) { - Block reply = wallet.getBlockByNum(num); + boolean detail = !request.hasBase() || request.getBase().getDetail(); + Block reply = wallet.getBlockByNum(num, detail); responseObserver.onNext(reply); } else { responseObserver.onNext(null); @@ -576,10 +689,11 @@ public void getBlockByNum(NumberMessage request, StreamObserver responseO @Override public void getBlockByNum2(NumberMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long num = request.getNum(); if (num >= 0) { - Block reply = wallet.getBlockByNum(num); + boolean detail = !request.hasBase() || request.getBase().getDetail(); + Block reply = wallet.getBlockByNum(num, detail); responseObserver.onNext(block2Extention(reply)); } else { responseObserver.onNext(null); @@ -590,7 +704,7 @@ public void getBlockByNum2(NumberMessage request, @Override public void getDelegatedResource(DelegatedResourceMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver .onNext(wallet.getDelegatedResource(request.getFromAddress(), request.getToAddress())); responseObserver.onCompleted(); @@ -598,7 +712,7 @@ public void getDelegatedResource(DelegatedResourceMessage request, @Override public void getDelegatedResourceAccountIndex(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver .onNext(wallet.getDelegatedResourceAccountIndex(request.getValue())); responseObserver.onCompleted(); @@ -606,7 +720,7 @@ public void getDelegatedResourceAccountIndex(BytesMessage request, @Override public void getExchangeById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString exchangeId = request.getValue(); if (Objects.nonNull(exchangeId)) { @@ -619,20 +733,20 @@ public void getExchangeById(BytesMessage request, @Override public void listExchanges(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getExchangeList()); responseObserver.onCompleted(); } @Override public void getTransactionCountByBlockNum(NumberMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { getTransactionCountByBlockNumCommon(request, responseObserver); } @Override public void getTransactionById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString id = request.getValue(); if (null != id) { Transaction reply = wallet.getTransactionById(id); @@ -646,7 +760,7 @@ public void getTransactionById(BytesMessage request, @Override public void getTransactionInfoById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString id = request.getValue(); if (null != id) { TransactionInfo reply = wallet.getTransactionInfoById(id); @@ -660,19 +774,19 @@ public void getTransactionInfoById(BytesMessage request, @Override public void generateAddress(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { generateAddressCommon(request, responseObserver); } @Override public void getRewardInfo(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { getRewardInfoCommon(request, responseObserver); } @Override public void getBrokerageInfo(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { getBrokerageInfoCommon(request, responseObserver); } @@ -683,7 +797,7 @@ public void getBurnTrx(EmptyMessage request, StreamObserver respo @Override public void getMerkleTreeVoucherInfo(OutputPointInfo request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTransaction(); @@ -699,7 +813,7 @@ public void getMerkleTreeVoucherInfo(OutputPointInfo request, @Override public void scanNoteByIvk(GrpcAPI.IvkDecryptParameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartBlockIndex(); long endNum = request.getEndBlockIndex(); @@ -717,7 +831,7 @@ public void scanNoteByIvk(GrpcAPI.IvkDecryptParameters request, @Override public void scanAndMarkNoteByIvk(GrpcAPI.IvkDecryptAndMarkParameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartBlockIndex(); long endNum = request.getEndBlockIndex(); @@ -738,7 +852,7 @@ public void scanAndMarkNoteByIvk(GrpcAPI.IvkDecryptAndMarkParameters request, @Override public void scanNoteByOvk(GrpcAPI.OvkDecryptParameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartBlockIndex(); long endNum = request.getEndBlockIndex(); try { @@ -767,7 +881,7 @@ public void isSpend(NoteParameters request, StreamObserver response @Override public void scanShieldedTRC20NotesByIvk(IvkDecryptTRC20Parameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartBlockIndex(); long endNum = request.getEndBlockIndex(); byte[] contractAddress = request.getShieldedTRC20ContractAddress().toByteArray(); @@ -790,7 +904,7 @@ public void scanShieldedTRC20NotesByIvk(IvkDecryptTRC20Parameters request, @Override public void scanShieldedTRC20NotesByOvk(OvkDecryptTRC20Parameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartBlockIndex(); long endNum = request.getEndBlockIndex(); byte[] contractAddress = request.getShieldedTRC20ContractAddress().toByteArray(); @@ -809,7 +923,7 @@ public void scanShieldedTRC20NotesByOvk(OvkDecryptTRC20Parameters request, @Override public void isShieldedTRC20ContractNoteSpent(NfTRC20Parameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTRC20Transaction(); responseObserver.onNext(wallet.isShieldedTRC20ContractNoteSpent(request)); @@ -821,7 +935,7 @@ public void isShieldedTRC20ContractNoteSpent(NfTRC20Parameters request, @Override public void getMarketOrderByAccount(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { ByteString address = request.getValue(); @@ -836,7 +950,7 @@ public void getMarketOrderByAccount(BytesMessage request, @Override public void getMarketOrderById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { ByteString address = request.getValue(); @@ -851,7 +965,7 @@ public void getMarketOrderById(BytesMessage request, @Override public void getMarketPriceByPair(MarketOrderPair request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { MarketPriceList marketPriceList = wallet .getMarketPriceByPair(request.getSellTokenId().toByteArray(), @@ -865,7 +979,7 @@ public void getMarketPriceByPair(MarketOrderPair request, @Override public void getMarketOrderListByPair(org.tron.protos.Protocol.MarketOrderPair request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { MarketOrderList orderPairList = wallet .getMarketOrderListByPair(request.getSellTokenId().toByteArray(), @@ -879,7 +993,7 @@ public void getMarketOrderListByPair(org.tron.protos.Protocol.MarketOrderPair re @Override public void getMarketPairList(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { MarketOrderPairList pairList = wallet.getMarketPairList(); responseObserver.onNext(pairList); @@ -891,14 +1005,14 @@ public void getMarketPairList(EmptyMessage request, @Override public void triggerConstantContract(TriggerSmartContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { callContract(request, responseObserver, true); } @Override public void getTransactionInfoByBlockNum(NumberMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext(wallet.getTransactionInfoByBlockNum(request.getNum())); } catch (Exception e) { @@ -970,7 +1084,7 @@ public void getAccountById(Account req, StreamObserver responseObserver * */ public void getAccountBalance(AccountBalanceRequest request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { AccountBalanceResponse accountBalanceResponse = wallet.getAccountBalance(request); responseObserver.onNext(accountBalanceResponse); @@ -984,7 +1098,7 @@ public void getAccountBalance(AccountBalanceRequest request, * */ public void getBlockBalanceTrace(BlockBalanceTrace.BlockIdentifier request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { BlockBalanceTrace blockBalanceTrace = wallet.getBlockBalance(request); responseObserver.onNext(blockBalanceTrace); @@ -996,7 +1110,7 @@ public void getBlockBalanceTrace(BlockBalanceTrace.BlockIdentifier request, @Override public void createTransaction(TransferContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver .onNext( @@ -1011,12 +1125,12 @@ public void createTransaction(TransferContract request, @Override public void createTransaction2(TransferContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.TransferContract, responseObserver); } private void createTransactionExtention(Message request, ContractType contractType, - StreamObserver responseObserver) { + StreamObserver responseObserver) { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); try { @@ -1042,7 +1156,7 @@ private void createTransactionExtention(Message request, ContractType contractTy @Override public void getTransactionSign(TransactionSign req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { TransactionCapsule result = TransactionUtil.getTransactionSign(req); responseObserver.onNext(result.getInstance()); responseObserver.onCompleted(); @@ -1050,7 +1164,7 @@ public void getTransactionSign(TransactionSign req, @Override public void getTransactionSign2(TransactionSign req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); try { @@ -1070,7 +1184,7 @@ public void getTransactionSign2(TransactionSign req, @Override public void addSign(TransactionSign req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); try { @@ -1090,7 +1204,7 @@ public void addSign(TransactionSign req, @Override public void getTransactionSignWeight(Transaction req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { TransactionSignWeight tsw = transactionUtil.getTransactionSignWeight(req); responseObserver.onNext(tsw); responseObserver.onCompleted(); @@ -1098,7 +1212,7 @@ public void getTransactionSignWeight(Transaction req, @Override public void getTransactionApprovedList(Transaction req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { TransactionApprovedList tal = wallet.getTransactionApprovedList(req); responseObserver.onNext(tal); responseObserver.onCompleted(); @@ -1106,7 +1220,7 @@ public void getTransactionApprovedList(Transaction req, @Override public void createAddress(BytesMessage req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { byte[] address = wallet.createAddress(req.getValue().toByteArray()); BytesMessage.Builder builder = BytesMessage.newBuilder(); builder.setValue(ByteString.copyFrom(address)); @@ -1115,7 +1229,7 @@ public void createAddress(BytesMessage req, } private EasyTransferResponse easyTransfer(byte[] privateKey, ByteString toAddress, - long amount) { + long amount) { TransactionCapsule transactionCapsule; GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); @@ -1149,7 +1263,7 @@ private EasyTransferResponse easyTransfer(byte[] privateKey, ByteString toAddres @Override public void easyTransfer(EasyTransferMessage req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { byte[] privateKey = wallet.pass2Key(req.getPassPhrase().toByteArray()); EasyTransferResponse response = easyTransfer(privateKey, req.getToAddress(), req.getAmount()); responseObserver.onNext(response); @@ -1158,7 +1272,7 @@ public void easyTransfer(EasyTransferMessage req, @Override public void easyTransferAsset(EasyTransferAssetMessage req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { byte[] privateKey = wallet.pass2Key(req.getPassPhrase().toByteArray()); EasyTransferResponse response = easyTransferAsset(privateKey, req.getToAddress(), req.getAssetId(), req.getAmount()); @@ -1167,7 +1281,7 @@ public void easyTransferAsset(EasyTransferAssetMessage req, } private EasyTransferResponse easyTransferAsset(byte[] privateKey, ByteString toAddress, - String assetId, long amount) { + String assetId, long amount) { TransactionCapsule transactionCapsule; GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); @@ -1202,7 +1316,7 @@ private EasyTransferResponse easyTransferAsset(byte[] privateKey, ByteString toA @Override public void easyTransferByPrivate(EasyTransferByPrivateMessage req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { byte[] privateKey = req.getPrivateKey().toByteArray(); EasyTransferResponse response = easyTransfer(privateKey, req.getToAddress(), req.getAmount()); responseObserver.onNext(response); @@ -1211,7 +1325,7 @@ public void easyTransferByPrivate(EasyTransferByPrivateMessage req, @Override public void easyTransferAssetByPrivate(EasyTransferAssetByPrivateMessage req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { byte[] privateKey = req.getPrivateKey().toByteArray(); EasyTransferResponse response = easyTransferAsset(privateKey, req.getToAddress(), req.getAssetId(), req.getAmount()); @@ -1221,7 +1335,7 @@ public void easyTransferAssetByPrivate(EasyTransferAssetByPrivateMessage req, @Override public void broadcastTransaction(Transaction req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { GrpcAPI.Return result = wallet.broadcastTransaction(req); responseObserver.onNext(result); responseObserver.onCompleted(); @@ -1229,7 +1343,7 @@ public void broadcastTransaction(Transaction req, @Override public void createAssetIssue(AssetIssueContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.AssetIssueContract).getInstance()); @@ -1242,13 +1356,13 @@ public void createAssetIssue(AssetIssueContract request, @Override public void createAssetIssue2(AssetIssueContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.AssetIssueContract, responseObserver); } @Override public void unfreezeAsset(UnfreezeAssetContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.UnfreezeAssetContract).getInstance()); @@ -1261,7 +1375,7 @@ public void unfreezeAsset(UnfreezeAssetContract request, @Override public void unfreezeAsset2(UnfreezeAssetContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.UnfreezeAssetContract, responseObserver); } @@ -1300,7 +1414,7 @@ private void checkVoteWitnessAccount(VoteWitnessContract req) { @Override public void voteWitnessAccount(VoteWitnessContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.VoteWitnessContract).getInstance()); @@ -1314,34 +1428,34 @@ public void voteWitnessAccount(VoteWitnessContract request, @Override public void voteWitnessAccount2(VoteWitnessContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.VoteWitnessContract, responseObserver); } @Override public void updateSetting(UpdateSettingContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.UpdateSettingContract, responseObserver); } @Override public void updateEnergyLimit(UpdateEnergyLimitContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.UpdateEnergyLimitContract, responseObserver); } @Override public void clearContractABI(ClearABIContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.ClearABIContract, responseObserver); } @Override public void createWitness(WitnessCreateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.WitnessCreateContract).getInstance()); @@ -1355,13 +1469,13 @@ public void createWitness(WitnessCreateContract request, @Override public void createWitness2(WitnessCreateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.WitnessCreateContract, responseObserver); } @Override public void createAccount(AccountCreateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.AccountCreateContract).getInstance()); @@ -1375,13 +1489,13 @@ public void createAccount(AccountCreateContract request, @Override public void createAccount2(AccountCreateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.AccountCreateContract, responseObserver); } @Override public void updateWitness(WitnessUpdateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.WitnessUpdateContract).getInstance()); @@ -1395,13 +1509,13 @@ public void updateWitness(WitnessUpdateContract request, @Override public void updateWitness2(WitnessUpdateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.WitnessUpdateContract, responseObserver); } @Override public void updateAccount(AccountUpdateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.AccountUpdateContract).getInstance()); @@ -1415,7 +1529,7 @@ public void updateAccount(AccountUpdateContract request, @Override public void setAccountId(SetAccountIdContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.SetAccountIdContract).getInstance()); @@ -1429,13 +1543,13 @@ public void setAccountId(SetAccountIdContract request, @Override public void updateAccount2(AccountUpdateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.AccountUpdateContract, responseObserver); } @Override public void updateAsset(UpdateAssetContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, @@ -1450,13 +1564,13 @@ public void updateAsset(UpdateAssetContract request, @Override public void updateAsset2(UpdateAssetContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.UpdateAssetContract, responseObserver); } @Override public void freezeBalance(FreezeBalanceContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.FreezeBalanceContract).getInstance()); @@ -1470,13 +1584,13 @@ public void freezeBalance(FreezeBalanceContract request, @Override public void freezeBalance2(FreezeBalanceContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.FreezeBalanceContract, responseObserver); } @Override public void unfreezeBalance(UnfreezeBalanceContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.UnfreezeBalanceContract) @@ -1491,13 +1605,13 @@ public void unfreezeBalance(UnfreezeBalanceContract request, @Override public void unfreezeBalance2(UnfreezeBalanceContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.UnfreezeBalanceContract, responseObserver); } @Override public void withdrawBalance(WithdrawBalanceContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.WithdrawBalanceContract) @@ -1512,86 +1626,90 @@ public void withdrawBalance(WithdrawBalanceContract request, @Override public void withdrawBalance2(WithdrawBalanceContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.WithdrawBalanceContract, responseObserver); } @Override public void proposalCreate(ProposalCreateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.ProposalCreateContract, responseObserver); } @Override public void proposalApprove(ProposalApproveContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.ProposalApproveContract, responseObserver); } @Override public void proposalDelete(ProposalDeleteContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.ProposalDeleteContract, responseObserver); } @Override public void exchangeCreate(ExchangeCreateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.ExchangeCreateContract, responseObserver); } @Override public void exchangeInject(ExchangeInjectContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.ExchangeInjectContract, responseObserver); } @Override public void exchangeWithdraw(ExchangeWithdrawContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.ExchangeWithdrawContract, responseObserver); } @Override public void exchangeTransaction(ExchangeTransactionContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.ExchangeTransactionContract, responseObserver); } @Override public void getNowBlock(EmptyMessage request, StreamObserver responseObserver) { - responseObserver.onNext(wallet.getNowBlock()); + boolean detail = !request.hasBase() || request.getBase().getDetail(); + responseObserver.onNext(wallet.getNowBlock(detail)); responseObserver.onCompleted(); } @Override public void getNowBlock2(EmptyMessage request, - StreamObserver responseObserver) { - Block block = wallet.getNowBlock(); + StreamObserver responseObserver) { + boolean detail = !request.hasBase() || request.getBase().getDetail(); + Block block = wallet.getNowBlock(detail); responseObserver.onNext(block2Extention(block)); responseObserver.onCompleted(); } @Override public void getBlockByNum(NumberMessage request, StreamObserver responseObserver) { - responseObserver.onNext(wallet.getBlockByNum(request.getNum())); + boolean detail = !request.hasBase() || request.getBase().getDetail(); + responseObserver.onNext(wallet.getBlockByNum(request.getNum(), detail)); responseObserver.onCompleted(); } @Override public void getBlockByNum2(NumberMessage request, - StreamObserver responseObserver) { - Block block = wallet.getBlockByNum(request.getNum()); + StreamObserver responseObserver) { + boolean detail = !request.hasBase() || request.getBase().getDetail(); + Block block = wallet.getBlockByNum(request.getNum(), detail); responseObserver.onNext(block2Extention(block)); responseObserver.onCompleted(); } @Override public void getTransactionCountByBlockNum(NumberMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { getTransactionCountByBlockNumCommon(request, responseObserver); } @@ -1621,7 +1739,7 @@ public void listNodes(EmptyMessage request, StreamObserver responseObs @Override public void transferAsset(TransferAssetContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver .onNext(createTransactionCapsule(request, ContractType.TransferAssetContract) @@ -1636,13 +1754,13 @@ public void transferAsset(TransferAssetContract request, @Override public void transferAsset2(TransferAssetContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.TransferAssetContract, responseObserver); } @Override public void participateAssetIssue(ParticipateAssetIssueContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver .onNext(createTransactionCapsule(request, ContractType.ParticipateAssetIssueContract) @@ -1657,14 +1775,14 @@ public void participateAssetIssue(ParticipateAssetIssueContract request, @Override public void participateAssetIssue2(ParticipateAssetIssueContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.ParticipateAssetIssueContract, responseObserver); } @Override public void getAssetIssueByAccount(Account request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString fromBs = request.getAddress(); if (fromBs != null) { @@ -1677,7 +1795,7 @@ public void getAssetIssueByAccount(Account request, @Override public void getAccountNet(Account request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString fromBs = request.getAddress(); if (fromBs != null) { @@ -1690,7 +1808,7 @@ public void getAccountNet(Account request, @Override public void getAccountResource(Account request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString fromBs = request.getAddress(); if (fromBs != null) { @@ -1703,7 +1821,7 @@ public void getAccountResource(Account request, @Override public void getAssetIssueByName(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString assetName = request.getValue(); if (assetName != null) { try { @@ -1720,7 +1838,7 @@ public void getAssetIssueByName(BytesMessage request, @Override public void getAssetIssueListByName(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString assetName = request.getValue(); if (assetName != null) { @@ -1733,7 +1851,7 @@ public void getAssetIssueListByName(BytesMessage request, @Override public void getAssetIssueById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString assetId = request.getValue(); if (assetId != null) { @@ -1749,7 +1867,8 @@ public void getBlockById(BytesMessage request, StreamObserver responseObs ByteString blockId = request.getValue(); if (Objects.nonNull(blockId)) { - responseObserver.onNext(wallet.getBlockById(blockId)); + boolean detail = !request.hasBase() || request.getBase().getDetail(); + responseObserver.onNext(wallet.getBlockById(blockId, detail)); } else { responseObserver.onNext(null); } @@ -1758,7 +1877,7 @@ public void getBlockById(BytesMessage request, StreamObserver responseObs @Override public void getProposalById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString proposalId = request.getValue(); if (Objects.nonNull(proposalId)) { @@ -1771,7 +1890,7 @@ public void getProposalById(BytesMessage request, @Override public void getExchangeById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString exchangeId = request.getValue(); if (Objects.nonNull(exchangeId)) { @@ -1784,12 +1903,14 @@ public void getExchangeById(BytesMessage request, @Override public void getBlockByLimitNext(BlockLimit request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartNum(); long endNum = request.getEndNum(); if (endNum > 0 && endNum > startNum && endNum - startNum <= BLOCK_LIMIT_NUM) { - responseObserver.onNext(wallet.getBlocksByLimitNext(startNum, endNum - startNum)); + boolean detail = !request.hasBase() || request.getBase().getDetail(); + responseObserver.onNext(wallet.getBlocksByLimitNext(startNum, + endNum - startNum, detail)); } else { responseObserver.onNext(null); } @@ -1798,13 +1919,14 @@ public void getBlockByLimitNext(BlockLimit request, @Override public void getBlockByLimitNext2(BlockLimit request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartNum(); long endNum = request.getEndNum(); if (endNum > 0 && endNum > startNum && endNum - startNum <= BLOCK_LIMIT_NUM) { - responseObserver - .onNext(blockList2Extention(wallet.getBlocksByLimitNext(startNum, endNum - startNum))); + boolean detail = !request.hasBase() || request.getBase().getDetail(); + responseObserver.onNext(blockList2Extention(wallet.getBlocksByLimitNext(startNum, + endNum - startNum, detail))); } else { responseObserver.onNext(null); } @@ -1813,11 +1935,12 @@ public void getBlockByLimitNext2(BlockLimit request, @Override public void getBlockByLatestNum(NumberMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long getNum = request.getNum(); if (getNum > 0 && getNum < BLOCK_LIMIT_NUM) { - responseObserver.onNext(wallet.getBlockByLatestNum(getNum)); + boolean detail = !request.hasBase() || request.getBase().getDetail(); + responseObserver.onNext(wallet.getBlockByLatestNum(getNum, detail)); } else { responseObserver.onNext(null); } @@ -1826,11 +1949,12 @@ public void getBlockByLatestNum(NumberMessage request, @Override public void getBlockByLatestNum2(NumberMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long getNum = request.getNum(); if (getNum > 0 && getNum < BLOCK_LIMIT_NUM) { - responseObserver.onNext(blockList2Extention(wallet.getBlockByLatestNum(getNum))); + boolean detail = !request.hasBase() || request.getBase().getDetail(); + responseObserver.onNext(blockList2Extention(wallet.getBlockByLatestNum(getNum, detail))); } else { responseObserver.onNext(null); } @@ -1839,7 +1963,7 @@ public void getBlockByLatestNum2(NumberMessage request, @Override public void getTransactionById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString transactionId = request.getValue(); if (Objects.nonNull(transactionId)) { @@ -1852,46 +1976,47 @@ public void getTransactionById(BytesMessage request, @Override public void deployContract(CreateSmartContract request, - io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.StreamObserver responseObserver) { createTransactionExtention(request, ContractType.CreateSmartContract, responseObserver); } public void totalTransaction(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.totalTransaction()); responseObserver.onCompleted(); } @Override public void getNextMaintenanceTime(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getNextMaintenanceTime()); responseObserver.onCompleted(); } @Override public void getAssetIssueList(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getAssetIssueList()); responseObserver.onCompleted(); } @Override public void triggerContract(TriggerSmartContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { callContract(request, responseObserver, false); } @Override public void triggerConstantContract(TriggerSmartContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { callContract(request, responseObserver, true); } private void callContract(TriggerSmartContract request, - StreamObserver responseObserver, boolean isConstant) { + StreamObserver responseObserver, + boolean isConstant) { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); try { @@ -1930,14 +2055,14 @@ private void callContract(TriggerSmartContract request, } public void getPaginatedAssetIssueList(PaginatedMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getAssetIssueList(request.getOffset(), request.getLimit())); responseObserver.onCompleted(); } @Override public void getContract(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { SmartContract contract = wallet.getContract(request); responseObserver.onNext(contract); responseObserver.onCompleted(); @@ -1945,21 +2070,21 @@ public void getContract(BytesMessage request, @Override public void getContractInfo(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { SmartContractDataWrapper contract = wallet.getContractInfo(request); responseObserver.onNext(contract); responseObserver.onCompleted(); } public void listWitnesses(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getWitnessList()); responseObserver.onCompleted(); } @Override public void listProposals(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getProposalList()); responseObserver.onCompleted(); } @@ -1967,14 +2092,14 @@ public void listProposals(EmptyMessage request, @Override public void getDelegatedResource(DelegatedResourceMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver .onNext(wallet.getDelegatedResource(request.getFromAddress(), request.getToAddress())); responseObserver.onCompleted(); } public void getDelegatedResourceAccountIndex(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver .onNext(wallet.getDelegatedResourceAccountIndex(request.getValue())); responseObserver.onCompleted(); @@ -1982,7 +2107,7 @@ public void getDelegatedResourceAccountIndex(BytesMessage request, @Override public void getPaginatedProposalList(PaginatedMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver .onNext(wallet.getPaginatedProposalList(request.getOffset(), request.getLimit())); responseObserver.onCompleted(); @@ -1991,7 +2116,7 @@ public void getPaginatedProposalList(PaginatedMessage request, @Override public void getPaginatedExchangeList(PaginatedMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver .onNext(wallet.getPaginatedExchangeList(request.getOffset(), request.getLimit())); responseObserver.onCompleted(); @@ -2000,27 +2125,27 @@ public void getPaginatedExchangeList(PaginatedMessage request, @Override public void listExchanges(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getExchangeList()); responseObserver.onCompleted(); } @Override public void getChainParameters(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getChainParameters()); responseObserver.onCompleted(); } @Override public void generateAddress(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { generateAddressCommon(request, responseObserver); } @Override public void getTransactionInfoById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString id = request.getValue(); if (null != id) { TransactionInfo reply = wallet.getTransactionInfoById(id); @@ -2044,14 +2169,14 @@ public void getNodeInfo(EmptyMessage request, StreamObserver responseO @Override public void accountPermissionUpdate(AccountPermissionUpdateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.AccountPermissionUpdateContract, responseObserver); } @Override public void getMerkleTreeVoucherInfo(OutputPointInfo request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTransaction(); @@ -2069,7 +2194,7 @@ public void getMerkleTreeVoucherInfo(OutputPointInfo request, @Override public void createShieldedTransaction(PrivateParameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); @@ -2100,7 +2225,7 @@ public void createShieldedTransaction(PrivateParameters request, @Override public void createShieldedTransactionWithoutSpendAuthSig(PrivateParametersWithoutAsk request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); @@ -2132,7 +2257,7 @@ public void createShieldedTransactionWithoutSpendAuthSig(PrivateParametersWithou @Override public void getNewShieldedAddress(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTRC20Transaction(); @@ -2147,7 +2272,7 @@ public void getNewShieldedAddress(EmptyMessage request, @Override public void getSpendingKey(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTRC20Transaction(); @@ -2161,7 +2286,7 @@ public void getSpendingKey(EmptyMessage request, @Override public void getRcm(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTRC20Transaction(); @@ -2175,7 +2300,7 @@ public void getRcm(EmptyMessage request, @Override public void getExpandedSpendingKey(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString spendingKey = request.getValue(); try { @@ -2225,7 +2350,7 @@ public void getNkFromNsk(BytesMessage request, StreamObserver resp @Override public void getIncomingViewingKey(ViewingKeyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString ak = request.getAk(); ByteString nk = request.getNk(); @@ -2243,7 +2368,7 @@ public void getIncomingViewingKey(ViewingKeyMessage request, @Override public void getDiversifier(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTRC20Transaction(); @@ -2259,7 +2384,7 @@ public void getDiversifier(EmptyMessage request, @Override public void getZenPaymentAddress(IncomingViewingKeyDiversifierMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { IncomingViewingKeyMessage ivk = request.getIvk(); DiversifierMessage d = request.getD(); @@ -2281,7 +2406,7 @@ public void getZenPaymentAddress(IncomingViewingKeyDiversifierMessage request, @Override public void scanNoteByIvk(GrpcAPI.IvkDecryptParameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartBlockIndex(); long endNum = request.getEndBlockIndex(); @@ -2301,7 +2426,7 @@ public void scanNoteByIvk(GrpcAPI.IvkDecryptParameters request, @Override public void scanAndMarkNoteByIvk(GrpcAPI.IvkDecryptAndMarkParameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartBlockIndex(); long endNum = request.getEndBlockIndex(); @@ -2323,7 +2448,7 @@ public void scanAndMarkNoteByIvk(GrpcAPI.IvkDecryptAndMarkParameters request, @Override public void scanNoteByOvk(GrpcAPI.OvkDecryptParameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartBlockIndex(); long endNum = request.getEndBlockIndex(); @@ -2355,7 +2480,7 @@ public void isSpend(NoteParameters request, StreamObserver response @Override public void createShieldNullifier(GrpcAPI.NfParameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTransaction(); @@ -2371,7 +2496,7 @@ public void createShieldNullifier(GrpcAPI.NfParameters request, @Override public void createSpendAuthSig(SpendAuthSigParameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTRC20Transaction(); @@ -2386,7 +2511,7 @@ public void createSpendAuthSig(SpendAuthSigParameters request, @Override public void getShieldTransactionHash(Transaction request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTransaction(); @@ -2484,7 +2609,7 @@ public void scanShieldedTRC20NotesByOvk( @Override public void isShieldedTRC20ContractNoteSpent(NfTRC20Parameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTRC20Transaction(); @@ -2515,13 +2640,13 @@ public void getTriggerInputForShieldedTRC20Contract( @Override public void getRewardInfo(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { getRewardInfoCommon(request, responseObserver); } @Override public void getBrokerageInfo(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { getBrokerageInfoCommon(request, responseObserver); } @@ -2532,14 +2657,14 @@ public void getBurnTrx(EmptyMessage request, StreamObserver respo @Override public void updateBrokerage(UpdateBrokerageContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.UpdateBrokerageContract, responseObserver); } @Override public void createCommonTransaction(Transaction request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { Transaction.Contract contract = request.getRawData().getContract(0); createTransactionExtention(contract.getParameter(), contract.getType(), responseObserver); @@ -2547,7 +2672,7 @@ public void createCommonTransaction(Transaction request, @Override public void getTransactionInfoByBlockNum(NumberMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext(wallet.getTransactionInfoByBlockNum(request.getNum())); } catch (Exception e) { @@ -2559,20 +2684,20 @@ public void getTransactionInfoByBlockNum(NumberMessage request, @Override public void marketSellAsset(MarketSellAssetContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.MarketSellAssetContract, responseObserver); } @Override public void marketCancelOrder(MarketCancelOrderContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.MarketCancelOrderContract, responseObserver); } @Override public void getMarketOrderByAccount(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { ByteString address = request.getValue(); @@ -2587,7 +2712,7 @@ public void getMarketOrderByAccount(BytesMessage request, @Override public void getMarketOrderById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { ByteString address = request.getValue(); @@ -2602,7 +2727,7 @@ public void getMarketOrderById(BytesMessage request, @Override public void getMarketPriceByPair(MarketOrderPair request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { MarketPriceList marketPriceList = wallet .getMarketPriceByPair(request.getSellTokenId().toByteArray(), @@ -2616,7 +2741,7 @@ public void getMarketPriceByPair(MarketOrderPair request, @Override public void getMarketOrderListByPair(org.tron.protos.Protocol.MarketOrderPair request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { MarketOrderList orderPairList = wallet .getMarketOrderListByPair(request.getSellTokenId().toByteArray(), @@ -2630,7 +2755,7 @@ public void getMarketOrderListByPair(org.tron.protos.Protocol.MarketOrderPair re @Override public void getMarketPairList(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { MarketOrderPairList pairList = wallet.getMarketPairList(); responseObserver.onNext(pairList); @@ -2642,19 +2767,19 @@ public void getMarketPairList(EmptyMessage request, @Override public void getTransactionFromPending(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { getTransactionFromPendingCommon(request, responseObserver); } @Override public void getTransactionListFromPending(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { getTransactionListFromPendingCommon(request, responseObserver); } @Override public void getPendingSize(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { getPendingSizeCommon(request, responseObserver); } } @@ -2663,115 +2788,9 @@ public class MonitorApi extends MonitorGrpc.MonitorImplBase { @Override public void getStatsInfo(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(metricsApiService.getMetricProtoInfo()); responseObserver.onCompleted(); } } - - public void generateAddressCommon(EmptyMessage request, - StreamObserver responseObserver) { - SignInterface cryptoEngine = SignUtils.getGeneratedRandomSign(Utils.getRandom(), - Args.getInstance().isECKeyCryptoEngine()); - byte[] priKey = cryptoEngine.getPrivateKey(); - byte[] address = cryptoEngine.getAddress(); - String addressStr = StringUtil.encode58Check(address); - String priKeyStr = Hex.encodeHexString(priKey); - AddressPrKeyPairMessage.Builder builder = AddressPrKeyPairMessage.newBuilder(); - builder.setAddress(addressStr); - builder.setPrivateKey(priKeyStr); - responseObserver.onNext(builder.build()); - responseObserver.onCompleted(); - } - - public void getRewardInfoCommon(BytesMessage request, - StreamObserver responseObserver) { - try { - long value = dbManager.getMortgageService().queryReward(request.getValue().toByteArray()); - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(value); - responseObserver.onNext(builder.build()); - } catch (Exception e) { - responseObserver.onError(e); - } - responseObserver.onCompleted(); - } - - public void getBurnTrxCommon(EmptyMessage request, - StreamObserver responseObserver) { - try { - long value = dbManager.getDynamicPropertiesStore().getBurnTrxAmount(); - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(value); - responseObserver.onNext(builder.build()); - } catch (Exception e) { - responseObserver.onError(e); - } - responseObserver.onCompleted(); - } - - public void getBrokerageInfoCommon(BytesMessage request, - StreamObserver responseObserver) { - try { - long cycle = dbManager.getDynamicPropertiesStore().getCurrentCycleNumber(); - long value = dbManager.getDelegationStore() - .getBrokerage(cycle, request.getValue().toByteArray()); - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(value); - responseObserver.onNext(builder.build()); - } catch (Exception e) { - responseObserver.onError(e); - } - responseObserver.onCompleted(); - } - - public void getTransactionCountByBlockNumCommon(NumberMessage request, - StreamObserver responseObserver) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - try { - Block block = chainBaseManager.getBlockByNum(request.getNum()).getInstance(); - builder.setNum(block.getTransactionsCount()); - } catch (StoreException e) { - logger.error(e.getMessage()); - builder.setNum(-1); - } - responseObserver.onNext(builder.build()); - responseObserver.onCompleted(); - } - - public void getTransactionFromPendingCommon(BytesMessage request, - StreamObserver responseObserver) { - try { - String txId = ByteArray.toHexString(request.getValue().toByteArray()); - TransactionCapsule transactionCapsule = dbManager.getTxFromPending(txId); - responseObserver.onNext(transactionCapsule == null ? null : transactionCapsule.getInstance()); - } catch (Exception e) { - responseObserver.onError(e); - } - responseObserver.onCompleted(); - } - - public void getTransactionListFromPendingCommon(EmptyMessage request, - StreamObserver responseObserver) { - try { - TransactionIdList.Builder builder = TransactionIdList.newBuilder(); - builder.addAllTxId(dbManager.getTxListFromPending()); - responseObserver.onNext(builder.build()); - } catch (Exception e) { - responseObserver.onError(e); - } - responseObserver.onCompleted(); - } - - public void getPendingSizeCommon(EmptyMessage request, - StreamObserver responseObserver) { - try { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(dbManager.getPendingSize()); - responseObserver.onNext(builder.build()); - } catch (Exception e) { - responseObserver.onError(e); - } - responseObserver.onCompleted(); - } } diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java index f7e6ac0ff7d..7e88297b1d2 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java @@ -22,9 +22,9 @@ public class GetBlockByIdServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - boolean visible = Util.getVisible(request); String input = request.getParameter("value"); - fillResponse(visible, ByteString.copyFrom(ByteArray.fromHexString(input)), response); + fillResponse(Util.getVisible(request),Util.getDetail(request), + ByteString.copyFrom(ByteArray.fromHexString(input)), response); } catch (Exception e) { Util.processError(e, response); } @@ -35,15 +35,16 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) PostParams params = PostParams.getPostParams(request); BytesMessage.Builder build = BytesMessage.newBuilder(); JsonFormat.merge(params.getParams(), build, params.isVisible()); - fillResponse(params.isVisible(), build.getValue(), response); + fillResponse(params.isVisible(), params.isDetail(), build.getValue(), response); } catch (Exception e) { Util.processError(e, response); } } - private void fillResponse(boolean visible, ByteString blockId, HttpServletResponse response) + private void fillResponse(boolean visible, boolean detail, + ByteString blockId, HttpServletResponse response) throws IOException { - Block reply = wallet.getBlockById(blockId); + Block reply = wallet.getBlockById(blockId, detail); if (reply != null) { response.getWriter().println(Util.printBlock(reply, visible)); } else { diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java index 1f2eabdd8dc..adb35e71d9a 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java @@ -21,7 +21,8 @@ public class GetBlockByLatestNumServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - fillResponse(Util.getVisible(request), Long.parseLong(request.getParameter("num")), response); + fillResponse(Util.getVisible(request), Util.getDetail(request), + Long.parseLong(request.getParameter("num")), response); } catch (Exception e) { Util.processError(e, response); } @@ -32,16 +33,16 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) PostParams params = PostParams.getPostParams(request); NumberMessage.Builder build = NumberMessage.newBuilder(); JsonFormat.merge(params.getParams(), build, params.isVisible()); - fillResponse(params.isVisible(), build.getNum(), response); + fillResponse(params.isVisible(), params.isDetail(), build.getNum(), response); } catch (Exception e) { Util.processError(e, response); } } - private void fillResponse(boolean visible, long num, HttpServletResponse response) + private void fillResponse(boolean visible, boolean detail, long num, HttpServletResponse response) throws IOException { if (num > 0 && num < BLOCK_LIMIT_NUM) { - BlockList reply = wallet.getBlockByLatestNum(num); + BlockList reply = wallet.getBlockByLatestNum(num, detail); if (reply != null) { response.getWriter().println(Util.printBlockList(reply, visible)); return; diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java index 3e6700a1fae..9d8b89f0520 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java @@ -21,7 +21,8 @@ public class GetBlockByLimitNextServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - fillResponse(Util.getVisible(request), Long.parseLong(request.getParameter("startNum")), + fillResponse(Util.getVisible(request),Util.getDetail(request), + Long.parseLong(request.getParameter("startNum")), Long.parseLong(request.getParameter("endNum")), response); } catch (Exception e) { Util.processError(e, response); @@ -33,17 +34,18 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) PostParams params = PostParams.getPostParams(request); BlockLimit.Builder build = BlockLimit.newBuilder(); JsonFormat.merge(params.getParams(), build, params.isVisible()); - fillResponse(params.isVisible(), build.getStartNum(), build.getEndNum(), response); + fillResponse(params.isVisible(),params.isDetail(), + build.getStartNum(), build.getEndNum(), response); } catch (Exception e) { Util.processError(e, response); } } - private void fillResponse(boolean visible, long startNum, long endNum, + private void fillResponse(boolean visible, boolean detail, long startNum, long endNum, HttpServletResponse response) throws IOException { if (endNum > 0 && endNum > startNum && endNum - startNum <= BLOCK_LIMIT_NUM) { - BlockList reply = wallet.getBlocksByLimitNext(startNum, endNum - startNum); + BlockList reply = wallet.getBlocksByLimitNext(startNum, endNum - startNum, detail); if (reply != null) { response.getWriter().println(Util.printBlockList(reply, visible)); return; diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java index 44babc69551..5b9bcc54a25 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java @@ -20,7 +20,8 @@ public class GetBlockByNumServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - fillResponse(Util.getVisible(request), Long.parseLong(request.getParameter("num")), response); + fillResponse(Util.getVisible(request),Util.getDetail(request), + Long.parseLong(request.getParameter("num")), response); } catch (Exception e) { Util.processError(e, response); } @@ -31,15 +32,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) PostParams params = PostParams.getPostParams(request); NumberMessage.Builder build = NumberMessage.newBuilder(); JsonFormat.merge(params.getParams(), build, params.isVisible()); - fillResponse(params.isVisible(), build.getNum(), response); + fillResponse(params.isVisible(), params.isDetail(), build.getNum(), response); } catch (Exception e) { Util.processError(e, response); } } - private void fillResponse(boolean visible, long num, HttpServletResponse response) + private void fillResponse(boolean visible, boolean detail, long num, HttpServletResponse response) throws IOException { - Block reply = wallet.getBlockByNum(num); + Block reply = wallet.getBlockByNum(num, detail); if (reply != null) { response.getWriter().println(Util.printBlock(reply, visible)); } else { diff --git a/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java b/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java index f7d9700aeb9..bff8187bac4 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java @@ -18,10 +18,9 @@ public class GetNowBlockServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - boolean visible = Util.getVisible(request); - Block reply = wallet.getNowBlock(); + Block reply = wallet.getNowBlock(Util.getDetail(request)); if (reply != null) { - response.getWriter().println(Util.printBlock(reply, visible)); + response.getWriter().println(Util.printBlock(reply, Util.getVisible(request))); } else { response.getWriter().println("{}"); } diff --git a/framework/src/main/java/org/tron/core/services/http/PostParams.java b/framework/src/main/java/org/tron/core/services/http/PostParams.java index a2077fb3c78..2ff47a36407 100644 --- a/framework/src/main/java/org/tron/core/services/http/PostParams.java +++ b/framework/src/main/java/org/tron/core/services/http/PostParams.java @@ -13,15 +13,27 @@ public class PostParams { @Getter private boolean visible; + @Getter + private boolean detail = true; + public PostParams(String params, boolean visible) { this.params = params; this.visible = visible; } + public PostParams(String params, boolean visible, boolean detail) { + this.params = params; + this.visible = visible; + this.detail = detail; + } + + + public static PostParams getPostParams(HttpServletRequest request) throws Exception { String input = request.getReader().lines().collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); boolean visible = Util.getVisiblePost(input); - return new PostParams(input, visible); + boolean detail = Util.getDetailPost(input); + return new PostParams(input, visible, detail); } } diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 1a7e111dc59..a9cdff7c08c 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -61,6 +61,7 @@ public class Util { public static final String CONTRACT_TYPE = "contractType"; public static final String EXTRA_DATA = "extra_data"; public static final String PARAMETER = "parameter"; + public static final String DETAIL = "detail"; public static String printTransactionFee(String transactionFee) { JSONObject jsonObject = new JSONObject(); @@ -310,6 +311,14 @@ public static boolean getVisible(final HttpServletRequest request) { return visible; } + public static boolean getDetail(final HttpServletRequest request) { + boolean detail = true; + if (StringUtil.isNotBlank(request.getParameter(DETAIL))) { + detail = Boolean.parseBoolean(request.getParameter(DETAIL)); + } + return detail; + } + public static boolean getVisiblePost(final String input) { boolean visible = false; if (StringUtil.isNotBlank(input)) { @@ -322,6 +331,18 @@ public static boolean getVisiblePost(final String input) { return visible; } + public static boolean getDetailPost(final String input) { + boolean detail = true; + if (StringUtil.isNotBlank(input)) { + JSONObject jsonObject = JSON.parseObject(input); + if (jsonObject.containsKey(DETAIL)) { + detail = jsonObject.getBoolean(DETAIL); + } + } + + return detail; + } + public static String getContractType(final String input) { String contractType = null; JSONObject jsonObject = JSON.parseObject(input); diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 5f697026c10..c7c65e91413 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -1110,14 +1110,19 @@ message Address { bytes host = 1; int32 port = 2; } - +message BaseMessage { + bool detail = 1; +} message EmptyMessage { + oneof baseMessage {BaseMessage base_ = 1;} } message NumberMessage { int64 num = 1; + oneof baseMessage {BaseMessage base_ = 2;} } message BytesMessage { bytes value = 1; + oneof baseMessage {BaseMessage base_ = 2;} } message TimeMessage { int64 beginInMilliseconds = 1; @@ -1126,6 +1131,7 @@ message TimeMessage { message BlockLimit { int64 startNum = 1; int64 endNum = 2; + oneof baseMessage {BaseMessage base_ = 3;} } message TransactionLimit { bytes transactionId = 1; From 93107aba983a4fe7e080003e1da4197197c4955e Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 29 Mar 2022 14:38:29 +0800 Subject: [PATCH 0036/1197] dependency: upgrade for security. 1. protobuf-java: 3.5.1 -> 3.16.1, [CVE-2021-22569], [CVE-2020-15250] --- build.gradle | 6 ++++++ .../org/tron/common/overlay/message/Message.java | 4 +++- framework/build.gradle | 1 + protocol/build.gradle | 14 +++++++++----- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index 60ed31885e4..de4fb03e532 100644 --- a/build.gradle +++ b/build.gradle @@ -63,6 +63,12 @@ subprojects { preserveFileTimestamps = false reproducibleFileOrder = true } + + configurations.all { + resolutionStrategy { + force group: 'com.google.guava', name: 'guava', version: '30.1-jre' + } + } } task copyToParent(type: Copy) { diff --git a/chainbase/src/main/java/org/tron/common/overlay/message/Message.java b/chainbase/src/main/java/org/tron/common/overlay/message/Message.java index 8c7381b7dcc..bbaf77139e3 100644 --- a/chainbase/src/main/java/org/tron/common/overlay/message/Message.java +++ b/chainbase/src/main/java/org/tron/common/overlay/message/Message.java @@ -27,7 +27,9 @@ public abstract class Message { private static DynamicPropertiesStore dynamicPropertiesStore; static { - ReflectionUtils.makeAccessible(field); + if (field != null) { + ReflectionUtils.makeAccessible(field); + } } protected byte[] data; diff --git a/framework/build.gradle b/framework/build.gradle index 68f093c4d86..75d37122088 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -152,6 +152,7 @@ test { exclude 'org/tron/core/ShieldedTRC20BuilderTest.class' exclude 'org/tron/common/runtime/vm/WithdrawRewardTest.class' } + maxHeapSize = "1024m" } task stest(type: Test) { diff --git a/protocol/build.gradle b/protocol/build.gradle index b818008515f..37b0690f9af 100644 --- a/protocol/build.gradle +++ b/protocol/build.gradle @@ -1,15 +1,19 @@ apply plugin: 'com.google.protobuf' +def protobufVersion = "3.16.1" + +def grpcVersion = "1.14.0" + dependencies { - compile group: 'com.google.protobuf', name: 'protobuf-java', version: '3.4.0' - compile group: 'com.google.protobuf', name: 'protobuf-java-util', version: '3.4.0' + compile group: 'com.google.protobuf', name: 'protobuf-java', version: protobufVersion + compile group: 'com.google.protobuf', name: 'protobuf-java-util', version: protobufVersion compile group: 'net.jcip', name: 'jcip-annotations', version: '1.0' // checkstyleConfig "com.puppycrawl.tools:checkstyle:${versions.checkstyle}" // google grpc - compile group: 'io.grpc', name: 'grpc-netty', version: '1.14.0' - compile group: 'io.grpc', name: 'grpc-protobuf', version: '1.14.0' - compile group: 'io.grpc', name: 'grpc-stub', version: '1.14.0' + compile group: 'io.grpc', name: 'grpc-netty', version: grpcVersion + compile group: 'io.grpc', name: 'grpc-protobuf', version: grpcVersion + compile group: 'io.grpc', name: 'grpc-stub', version: grpcVersion // end google grpc compile group: 'com.google.api.grpc', name: 'googleapis-common-protos', version: '0.0.3' From b063d80ae5f718029dd6c4b3c1bb864e876619ca Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 29 Mar 2022 15:21:23 +0800 Subject: [PATCH 0037/1197] perf(net): optimize block broadcast logic --- .../common/parameter/CommonParameter.java | 2 + .../src/main/java/org/tron/core/Constant.java | 2 + .../tron/common/overlay/server/Channel.java | 5 + .../common/overlay/server/FastForward.java | 4 +- .../java/org/tron/core/config/args/Args.java | 13 ++ .../net/messagehandler/BlockMsgHandler.java | 16 +- .../org/tron/core/net/service/AdvService.java | 8 +- .../tron/core/net/service/RelayService.java | 85 ++++++++++ .../org/tron/common/config/args/ArgsTest.java | 1 + .../core/net/services/AdvServiceTest.java | 7 +- .../core/net/services/RelayServiceTest.java | 151 ++++++++++++++++++ 11 files changed, 287 insertions(+), 7 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/net/service/RelayService.java create mode 100644 framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index f105eb6402d..e0c22204b07 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -386,6 +386,8 @@ public class CommonParameter { @Getter public List fastForwardNodes; @Getter + public int maxFastForwardNum; + @Getter public Storage storage; @Getter public Overlay overlay; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index e542a12491e..3e517be51fd 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -219,6 +219,8 @@ public class Constant { public static final String NODE_FAST_FORWARD = "node.fastForward"; + public static final String NODE_MAX_FAST_FORWARD_NUM = "node.maxFastForwardNum"; + public static final String NODE_SHIELDED_TRANS_IN_PENDING_MAX_COUNTS = "node.shieldedTransInPendingMaxCounts"; public static final String RATE_LIMITER = "rate.limiter"; diff --git a/framework/src/main/java/org/tron/common/overlay/server/Channel.java b/framework/src/main/java/org/tron/common/overlay/server/Channel.java index 0d3358c3b61..0846ff61251 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/Channel.java +++ b/framework/src/main/java/org/tron/common/overlay/server/Channel.java @@ -1,5 +1,6 @@ package org.tron.common.overlay.server; +import com.google.protobuf.ByteString; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPipeline; import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; @@ -12,6 +13,7 @@ import java.util.concurrent.TimeUnit; import lombok.Getter; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; @@ -61,6 +63,9 @@ public class Channel { private long startTime; private TronState tronState = TronState.INIT; private boolean isActive; + @Getter + @Setter + private ByteString address; private volatile boolean isDisconnect; diff --git a/framework/src/main/java/org/tron/common/overlay/server/FastForward.java b/framework/src/main/java/org/tron/common/overlay/server/FastForward.java index b7e44713a16..bdfc1023ccc 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/FastForward.java +++ b/framework/src/main/java/org/tron/common/overlay/server/FastForward.java @@ -9,6 +9,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; @@ -107,12 +108,13 @@ public boolean checkHelloMessage(HelloMessage message, Channel channel) { Protocol.HelloMessage msg = message.getHelloMessage(); - // todo, just to solve the compatibility problem if (msg.getAddress() == null || msg.getAddress().isEmpty()) { logger.info("HelloMessage from {}, address is empty.", channel.getInetAddress()); return false; } + channel.setAddress(msg.getAddress()); + if (!witnessScheduleStore.getActiveWitnesses().contains(msg.getAddress())) { logger.error("HelloMessage from {}, {} is not a schedule witness.", channel.getInetAddress(), diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 7fcad9b75c1..57ee1c62afc 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -115,6 +115,7 @@ public static void clearParam() { PARAMETER.activeNodes = Collections.emptyList(); PARAMETER.passiveNodes = Collections.emptyList(); PARAMETER.fastForwardNodes = Collections.emptyList(); + PARAMETER.maxFastForwardNum = 3; PARAMETER.nodeChannelReadTimeout = 0; PARAMETER.nodeMaxActiveNodes = 30; PARAMETER.nodeMaxActiveNodesWithSameIp = 2; @@ -726,6 +727,16 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.passiveNodes = getNodes(config, Constant.NODE_PASSIVE); PARAMETER.fastForwardNodes = getNodes(config, Constant.NODE_FAST_FORWARD); + + PARAMETER.maxFastForwardNum = config.hasPath(Constant.NODE_MAX_FAST_FORWARD_NUM) ? config + .getInt(Constant.NODE_MAX_FAST_FORWARD_NUM) : 3; + if (PARAMETER.maxFastForwardNum > MAX_ACTIVE_WITNESS_NUM) { + PARAMETER.maxFastForwardNum = MAX_ACTIVE_WITNESS_NUM; + } + if (PARAMETER.maxFastForwardNum < 1) { + PARAMETER.maxFastForwardNum = 1; + } + PARAMETER.shieldedTransInPendingMaxCounts = config.hasPath(Constant.NODE_SHIELDED_TRANS_IN_PENDING_MAX_COUNTS) ? config .getInt(Constant.NODE_SHIELDED_TRANS_IN_PENDING_MAX_COUNTS) : 10; @@ -1151,10 +1162,12 @@ public static void logConfig() { logger.info("Active node size: {}", parameter.getActiveNodes().size()); logger.info("Passive node size: {}", parameter.getPassiveNodes().size()); logger.info("FastForward node size: {}", parameter.getFastForwardNodes().size()); + logger.info("FastForward node number: {}", parameter.getMaxFastForwardNum()); logger.info("Seed node size: {}", parameter.getSeedNode().getIpList().size()); logger.info("Max connection: {}", parameter.getNodeMaxActiveNodes()); logger.info("Max connection with same IP: {}", parameter.getNodeMaxActiveNodesWithSameIp()); logger.info("Solidity threads: {}", parameter.getSolidityThreads()); + logger.info("Trx reference block: {}", parameter.getTrxReferenceBlock()); logger.info("************************ Backup config ************************"); logger.info("Backup priority: {}", parameter.getBackupPriority()); logger.info("Backup listen port: {}", parameter.getBackupPort()); diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java index c464bec80f1..fdfda8af5ba 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java @@ -19,6 +19,7 @@ import org.tron.core.net.peer.Item; import org.tron.core.net.peer.PeerConnection; import org.tron.core.net.service.AdvService; +import org.tron.core.net.service.RelayService; import org.tron.core.net.service.SyncService; import org.tron.core.services.WitnessProductBlockService; import org.tron.protos.Protocol.Inventory.InventoryType; @@ -27,6 +28,9 @@ @Component public class BlockMsgHandler implements TronMsgHandler { + @Autowired + private RelayService relayService; + @Autowired private TronNetDelegate tronNetDelegate; @@ -108,13 +112,13 @@ private void processBlock(PeerConnection peer, BlockCapsule block) throws P2pExc boolean flag = tronNetDelegate.validBlock(block); if (flag) { - advService.broadcast(new BlockMessage(block)); + broadcast(new BlockMessage(block)); } try { tronNetDelegate.processBlock(block, false); if (!flag) { - advService.broadcast(new BlockMessage(block)); + broadcast(new BlockMessage(block)); } witnessProductBlockService.validWitnessProductTwoBlock(block); @@ -130,4 +134,12 @@ private void processBlock(PeerConnection peer, BlockCapsule block) throws P2pExc } } + private void broadcast(BlockMessage blockMessage) { + if (fastForward) { + relayService.broadcast(blockMessage); + } else { + advService.broadcast(blockMessage); + } + } + } diff --git a/framework/src/main/java/org/tron/core/net/service/AdvService.java b/framework/src/main/java/org/tron/core/net/service/AdvService.java index 8eda4513dad..7d2e5bee6fa 100644 --- a/framework/src/main/java/org/tron/core/net/service/AdvService.java +++ b/framework/src/main/java/org/tron/core/net/service/AdvService.java @@ -28,6 +28,7 @@ import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.Time; import org.tron.core.capsule.BlockCapsule.BlockId; +import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.args.Args; import org.tron.core.net.TronNetDelegate; import org.tron.core.net.message.BlockMessage; @@ -175,6 +176,10 @@ public int fastBroadcastTransaction(TransactionMessage msg) { public void broadcast(Message msg) { + if (fastForward) { + return; + } + if (invToSpread.size() > MAX_SPREAD_SIZE) { logger.warn("Drop message, type: {}, ID: {}.", msg.getType(), msg.getMessageId()); return; @@ -193,9 +198,6 @@ public void broadcast(Message msg) { }); blockCache.put(item, msg); } else if (msg instanceof TransactionMessage) { - if (fastForward) { - return; - } TransactionMessage trxMsg = (TransactionMessage) msg; item = new Item(trxMsg.getMessageId(), InventoryType.TRX); trxCount.add(); diff --git a/framework/src/main/java/org/tron/core/net/service/RelayService.java b/framework/src/main/java/org/tron/core/net/service/RelayService.java new file mode 100644 index 00000000000..54f2bdb2d86 --- /dev/null +++ b/framework/src/main/java/org/tron/core/net/service/RelayService.java @@ -0,0 +1,85 @@ +package org.tron.core.net.service; + +import com.google.protobuf.ByteString; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.ChainBaseManager; +import org.tron.core.capsule.WitnessCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.message.BlockMessage; +import org.tron.core.net.peer.Item; +import org.tron.core.net.peer.PeerConnection; +import org.tron.protos.Protocol; + +@Slf4j(topic = "net") +@Component +public class RelayService { + + @Autowired + private ChainBaseManager chainBaseManager; + + @Autowired + private TronNetDelegate tronNetDelegate; + + private int maxFastForwardNum = Args.getInstance().getMaxFastForwardNum(); + + private static volatile long nextMaintenanceTime = -1; + private static volatile List witnesses; + + private List getSortedScheduleWitness() { + long time = chainBaseManager.getDynamicPropertiesStore().getNextMaintenanceTime(); + if (time <= nextMaintenanceTime) { + nextMaintenanceTime = time; + return witnesses; + } + List l1 = new ArrayList<>(); + chainBaseManager.getWitnessScheduleStore().getActiveWitnesses().forEach(s -> { + l1.add(chainBaseManager.getWitnessStore().get(s.toByteArray())); + }); + l1.sort(Comparator.comparingLong(w -> -w.getVoteCount())); + List l2 = new ArrayList<>(); + l1.forEach(w -> l2.add(w.getAddress())); + nextMaintenanceTime = time; + witnesses = l2; + return witnesses; + } + + private List getNextWitnesses(ByteString key, Integer count) { + List l1 = getSortedScheduleWitness(); + int index = l1.indexOf(key); + if (index < 0) { + return l1; + } + List l2 = new ArrayList<>(); + for (; count > 0; count--) { + l2.add(l1.get(++index % l1.size())); + } + return l2; + } + + public void broadcast(BlockMessage msg) { + List witnesses = getNextWitnesses( + msg.getBlockCapsule().getWitnessAddress(), maxFastForwardNum); + Item item = new Item(msg.getBlockId(), Protocol.Inventory.InventoryType.BLOCK); + List peers = tronNetDelegate.getActivePeer().stream() + .filter(peer -> !peer.isNeedSyncFromPeer() && !peer.isNeedSyncFromUs()) + .filter(peer -> peer.getAdvInvReceive().getIfPresent(item) == null + && peer.getAdvInvSpread().getIfPresent(item) == null) + .filter(peer -> peer.getAddress() != null && witnesses.contains(peer.getAddress())) + .collect(Collectors.toList()); + + peers.forEach(peer -> { + peer.fastSend(msg); + peer.getAdvInvSpread().put(item, System.currentTimeMillis()); + peer.setFastForwardBlock(msg.getBlockId()); + }); + } + +} + diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index 0578b76136f..2732824779e 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -28,5 +28,6 @@ public void testConfig() { Assert.assertEquals(Args.getInstance().getMaxTransactionPendingSize(), 2000); Assert.assertEquals(Args.getInstance().getPendingTransactionTimeout(), 60_000); Assert.assertEquals(Args.getInstance().getNodeDiscoveryPingTimeout(), 15_000); + Assert.assertEquals(Args.getInstance().getMaxFastForwardNum(), 3); } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java b/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java index 194649774c5..d850ab66958 100644 --- a/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java @@ -1,6 +1,8 @@ package org.tron.core.net.services; import com.google.common.collect.Lists; + +import java.io.File; import java.util.List; import org.junit.After; import org.junit.Assert; @@ -9,6 +11,7 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.overlay.server.SyncPool; import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.FileUtil; import org.tron.common.utils.ReflectUtils; import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; @@ -30,13 +33,14 @@ public class AdvServiceTest { private AdvService service; private PeerConnection peer; private SyncPool syncPool; + private String dbPath = "output-adv-service-test"; /** * init context. */ @Before public void init() { - Args.setParam(new String[]{"--output-directory", "output-directory", "--debug"}, + Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); service = context.getBean(AdvService.class); @@ -49,6 +53,7 @@ public void init() { public void destroy() { Args.clearParam(); context.destroy(); + FileUtil.deleteDir(new File(dbPath)); } @Test diff --git a/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java b/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java new file mode 100644 index 00000000000..cf4178695a7 --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java @@ -0,0 +1,151 @@ +package org.tron.core.net.services; + +import com.google.common.collect.Lists; +import com.google.protobuf.ByteString; + +import java.io.File; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import org.bouncycastle.util.encoders.Hex; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.overlay.server.SyncPool; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.ReflectUtils; +import org.tron.core.ChainBaseManager; +import org.tron.core.Constant; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.WitnessCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.net.message.BlockMessage; +import org.tron.core.net.peer.Item; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.service.RelayService; +import org.tron.protos.Protocol; + +public class RelayServiceTest { + + protected TronApplicationContext context; + private RelayService service; + private ChainBaseManager chainBaseManager; + private PeerConnection peer; + private SyncPool syncPool; + private String dbPath = "output-relay-service-test"; + + /** + * init context. + */ + @Before + public void init() { + Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, + Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + service = context.getBean(RelayService.class); + chainBaseManager = context.getBean(ChainBaseManager.class); + } + + /** + * destroy. + */ + @After + public void destroy() { + Args.clearParam(); + context.destroy(); + FileUtil.deleteDir(new File(dbPath)); + } + + @Test + public void test() throws Exception { + testGetSortedScheduleWitness(); + testGetNextWitnesses(); + testBroadcast(); + } + + private void testGetSortedScheduleWitness() throws Exception { + Method method = service.getClass().getDeclaredMethod("getSortedScheduleWitness"); + method.setAccessible(true); + List list = new ArrayList<>(); + List witnesses = chainBaseManager.getWitnessStore().getAllWitnesses(); + witnesses.forEach(witness -> list.add(witness.getAddress())); + chainBaseManager.getWitnessScheduleStore().saveActiveWitnesses(list); + chainBaseManager.getDynamicPropertiesStore().saveNextMaintenanceTime(10); + List l1 = (List) method.invoke(service); + Assert.assertEquals(11, l1.size()); + assertEquals(l1.get(0), "A0299F3DB80A24B20A254B89CE639D59132F157F13"); + assertEquals(l1.get(10), "A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F"); + + byte[] key = Hex.decode("A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F"); + WitnessCapsule witness = chainBaseManager.getWitnessStore().get(key); + witness.setVoteCount(1000); + chainBaseManager.getWitnessStore().put(key, witness); + chainBaseManager.getDynamicPropertiesStore().saveNextMaintenanceTime(20); + List l2 = (List) method.invoke(service); + assertEquals(l2.get(0), "A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F"); + assertEquals(l2.get(1), "A0299F3DB80A24B20A254B89CE639D59132F157F13"); + } + + public void testGetNextWitnesses() throws Exception { + Method method = service.getClass().getDeclaredMethod( + "getNextWitnesses", ByteString.class, Integer.class); + method.setAccessible(true); + List l1 = (List) method.invoke( + service, getFromHexString("A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F"), 3); + Assert.assertEquals(l1.size(), 3); + assertEquals(l1.get(0), "A0299F3DB80A24B20A254B89CE639D59132F157F13"); + assertEquals(l1.get(1), "A0807337F180B62A77576377C1D0C9C24DF5C0DD62"); + assertEquals(l1.get(2), "A05430A3F089154E9E182DDD6FE136A62321AF22A7"); + + List l2 = (List) method.invoke( + service, getFromHexString("A0FAB5FBF6AFB681E4E37E9D33BDDB7E923D6132E5"), 3); + Assert.assertEquals(l2.size(), 3); + assertEquals(l2.get(0), "A014EEBE4D30A6ACB505C8B00B218BDC4733433C68"); + assertEquals(l2.get(1), "A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F"); + assertEquals(l2.get(2), "A0299F3DB80A24B20A254B89CE639D59132F157F13"); + + List l3 = (List) method.invoke( + service, getFromHexString("A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F"), 1); + Assert.assertEquals(l3.size(), 1); + assertEquals(l3.get(0), "A0299F3DB80A24B20A254B89CE639D59132F157F13"); + } + + private void testBroadcast() { + try { + peer = context.getBean(PeerConnection.class); + peer.setAddress(getFromHexString("A0299F3DB80A24B20A254B89CE639D59132F157F13")); + peer.setNeedSyncFromPeer(false); + peer.setNeedSyncFromUs(false); + syncPool = context.getBean(SyncPool.class); + + List peers = Lists.newArrayList(); + peers.add(peer); + ReflectUtils.setFieldValue(syncPool, "activePeers", peers); + BlockCapsule blockCapsule = new BlockCapsule(chainBaseManager.getHeadBlockNum() + 1, + chainBaseManager.getHeadBlockId(), + 0, getFromHexString("A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F")); + BlockMessage msg = new BlockMessage(blockCapsule); + service.broadcast(msg); + Item item = new Item(blockCapsule.getBlockId(), Protocol.Inventory.InventoryType.BLOCK); + Assert.assertEquals(1, peer.getAdvInvSpread().size()); + Assert.assertNotNull(peer.getAdvInvSpread().getIfPresent(item)); + peer.close(); + syncPool.close(); + } catch (NullPointerException e) { + System.out.println(e); + } + } + + private void assertEquals(ByteString byteString, String string) { + Assert.assertEquals(byteString, ByteString.copyFrom(Hex.decode(string))); + } + + private ByteString getFromHexString(String s) { + return ByteString.copyFrom(Hex.decode(s)); + } + +} From 35885c0a94942f5eba4fe544b0b26e950a990243 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 29 Mar 2022 16:31:20 +0800 Subject: [PATCH 0038/1197] dependency: upgrade for later arm64. 1. protobuf-java: 3.16.1 -> 3.19.2 2. fix DiscardUnknownFields --- .../java/org/tron/common/overlay/message/Message.java | 8 ++++---- protocol/build.gradle | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/overlay/message/Message.java b/chainbase/src/main/java/org/tron/common/overlay/message/Message.java index bbaf77139e3..a0269d0481f 100644 --- a/chainbase/src/main/java/org/tron/common/overlay/message/Message.java +++ b/chainbase/src/main/java/org/tron/common/overlay/message/Message.java @@ -21,15 +21,15 @@ public abstract class Message { protected static final Logger logger = LoggerFactory.getLogger("Message"); + // https://developers.google.com/protocol-buffers/docs/proto3#unknowns + // https://github.com/protocolbuffers/protobuf/issues/272 private static final Field field = ReflectionUtils - .findField(CodedInputStream.class, "explicitDiscardUnknownFields"); + .findField(CodedInputStream.class, "shouldDiscardUnknownFields"); @Setter private static DynamicPropertiesStore dynamicPropertiesStore; static { - if (field != null) { - ReflectionUtils.makeAccessible(field); - } + ReflectionUtils.makeAccessible(field); } protected byte[] data; diff --git a/protocol/build.gradle b/protocol/build.gradle index 37b0690f9af..acdb7f15187 100644 --- a/protocol/build.gradle +++ b/protocol/build.gradle @@ -1,6 +1,6 @@ apply plugin: 'com.google.protobuf' -def protobufVersion = "3.16.1" +def protobufVersion = "3.19.2" def grpcVersion = "1.14.0" From bbec2ecfa495418673e56b0dc70cec4b7635ad82 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 30 Mar 2022 11:03:02 +0800 Subject: [PATCH 0039/1197] perf(net): solve the sonar problem --- .../src/main/java/org/tron/core/net/service/AdvService.java | 1 - .../src/main/java/org/tron/core/net/service/RelayService.java | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/AdvService.java b/framework/src/main/java/org/tron/core/net/service/AdvService.java index 7d2e5bee6fa..0d8e1c1aade 100644 --- a/framework/src/main/java/org/tron/core/net/service/AdvService.java +++ b/framework/src/main/java/org/tron/core/net/service/AdvService.java @@ -28,7 +28,6 @@ import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.Time; import org.tron.core.capsule.BlockCapsule.BlockId; -import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.args.Args; import org.tron.core.net.TronNetDelegate; import org.tron.core.net.message.BlockMessage; diff --git a/framework/src/main/java/org/tron/core/net/service/RelayService.java b/framework/src/main/java/org/tron/core/net/service/RelayService.java index 54f2bdb2d86..17515dd4bd3 100644 --- a/framework/src/main/java/org/tron/core/net/service/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/RelayService.java @@ -29,8 +29,8 @@ public class RelayService { private int maxFastForwardNum = Args.getInstance().getMaxFastForwardNum(); - private static volatile long nextMaintenanceTime = -1; - private static volatile List witnesses; + private volatile long nextMaintenanceTime = -1; + private volatile List witnesses; private List getSortedScheduleWitness() { long time = chainBaseManager.getDynamicPropertiesStore().getNextMaintenanceTime(); From 59355415c01544f46291852d0fd73a39616c0cc3 Mon Sep 17 00:00:00 2001 From: Asuka Date: Wed, 30 Mar 2022 14:33:34 +0800 Subject: [PATCH 0040/1197] fix(tvm): adapt to history NPE fix --- actuator/src/main/java/org/tron/core/vm/repository/Value.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Value.java b/actuator/src/main/java/org/tron/core/vm/repository/Value.java index 62828daacf1..bf5d99c9c94 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Value.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Value.java @@ -35,7 +35,7 @@ public static Value create(ProtoCapsule capsule) { } public static Value create(byte[] value, int type) { - return value == null ? new Value<>(null, type) : + return (value == null || value.length ==0) ? new Value<>(null, type) : new Value<>(Arrays.copyOf(value, value.length), type); } From 9e0119cdf660669ae6e864f83cccc83dc81ceadc Mon Sep 17 00:00:00 2001 From: Asuka Date: Wed, 30 Mar 2022 16:33:08 +0800 Subject: [PATCH 0041/1197] fix(tvm,test): change salt for some tests --- .../src/test/java/org/tron/common/runtime/vm/FreezeTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java index 38928ab002e..60e7a3ffa9c 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java @@ -526,7 +526,7 @@ public void testCreate2SuicideToAccount() throws Exception { long frozenBalance = 1_000_000; freezeForSelf(contract, frozenBalance, 0); freezeForSelf(contract, frozenBalance, 1); - long salt = 1; + long salt = 2; byte[] predictedAddr = getCreate2Addr(factory, salt); freezeForOther(contract, predictedAddr, frozenBalance, 0); freezeForOther(contract, predictedAddr, frozenBalance, 1); From f19a8836365879ab09424b764e25340457cf34b0 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 30 Mar 2022 17:40:20 +0800 Subject: [PATCH 0042/1197] test(api): add test for block query. --- .../test/java/org/tron/core/WalletTest.java | 106 ++++++++++++++---- 1 file changed, 85 insertions(+), 21 deletions(-) diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 4c0ff5ed6c4..5965bf2e97e 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -21,14 +21,12 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static stest.tron.wallet.common.client.utils.PublicMethed.decode58Check; +import static org.junit.Assert.assertNotEquals; import com.google.protobuf.Any; import com.google.protobuf.ByteString; import java.io.File; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; import lombok.extern.slf4j.Slf4j; import org.joda.time.DateTime; import org.junit.AfterClass; @@ -45,21 +43,18 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; import org.tron.common.utils.Utils; -import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.ExchangeCapsule; import org.tron.core.capsule.ProposalCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.TransactionInfoCapsule; -import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.utils.ProposalUtil.ProposalType; import org.tron.core.utils.TransactionUtil; import org.tron.protos.Protocol; -import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.BlockHeader; import org.tron.protos.Protocol.BlockHeader.raw; @@ -105,10 +100,10 @@ public class WalletTest { public static final long TRANSACTION_TIMESTAMP_THREE = DateTime.now().minusDays(2).getMillis(); public static final long TRANSACTION_TIMESTAMP_FOUR = DateTime.now().minusDays(1).getMillis(); public static final long TRANSACTION_TIMESTAMP_FIVE = DateTime.now().getMillis(); - private static TronApplicationContext context; + private static final TronApplicationContext context; private static Wallet wallet; private static ChainBaseManager chainBaseManager; - private static String dbPath = "output_wallet_test"; + private static final String dbPath = "output_wallet_test"; private static Block block1; private static Block block2; private static Block block3; @@ -123,7 +118,7 @@ public class WalletTest { private static AssetIssueCapsule Asset1; static { - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[] {"-d", dbPath}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); } @@ -188,11 +183,11 @@ private static void addTransactionInfoToStore(Transaction transaction) { private static Transaction getBuildTransaction( TransferContract transferContract, long transactionTimestamp, long refBlockNum) { return Transaction.newBuilder().setRawData( - Transaction.raw.newBuilder().setTimestamp(transactionTimestamp) - .setRefBlockNum(refBlockNum) - .addContract( - Contract.newBuilder().setType(ContractType.TransferContract) - .setParameter(Any.pack(transferContract)).build()).build()) + Transaction.raw.newBuilder().setTimestamp(transactionTimestamp) + .setRefBlockNum(refBlockNum) + .addContract( + Contract.newBuilder().setType(ContractType.TransferContract) + .setParameter(Any.pack(transferContract)).build()).build()) .build(); } @@ -236,14 +231,16 @@ private static void initBlock() { private static void addBlockToStore(Block block) { BlockCapsule blockCapsule = new BlockCapsule(block); chainBaseManager.getBlockStore().put(blockCapsule.getBlockId().getBytes(), blockCapsule); + chainBaseManager.getBlockIndexStore().put(blockCapsule.getBlockId()); } private static Block getBuildBlock(long timestamp, long num, long witnessId, - String witnessAddress, Transaction transaction, Transaction transactionNext) { + String witnessAddress, Transaction transaction, + Transaction transactionNext) { return Block.newBuilder().setBlockHeader(BlockHeader.newBuilder().setRawData( - raw.newBuilder().setTimestamp(timestamp).setNumber(num).setWitnessId(witnessId) - .setWitnessAddress(ByteString.copyFrom(ByteArray.fromHexString(witnessAddress))) - .build()).build()).addTransactions(transaction).addTransactions(transactionNext) + raw.newBuilder().setTimestamp(timestamp).setNumber(num).setWitnessId(witnessId) + .setWitnessAddress(ByteString.copyFrom(ByteArray.fromHexString(witnessAddress))) + .build()).build()).addTransactions(transaction).addTransactions(transactionNext) .build(); } @@ -346,11 +343,27 @@ public void getBlockById() { .getBlockById(ByteString.copyFrom(new BlockCapsule(block3).getBlockId().getBytes())); assertEquals("getBlockById3", block3, blockById); blockById = wallet - .getBlockById(ByteString.copyFrom(new BlockCapsule(block4).getBlockId().getBytes())); + .getBlockById(ByteString.copyFrom(new BlockCapsule(block4).getBlockId().getBytes()), + true); assertEquals("getBlockById4", block4, blockById); blockById = wallet - .getBlockById(ByteString.copyFrom(new BlockCapsule(block5).getBlockId().getBytes())); - assertEquals("getBlockById5", block5, blockById); + .getBlockById(ByteString.copyFrom(new BlockCapsule(block5).getBlockId().getBytes()), + false); + assertNotEquals("getBlockById5", block5, blockById); + } + + @Test + public void getBlockByNum() { + Block blockById = wallet.getBlockByNum(BLOCK_NUM_ONE); + assertEquals("getBlockById1", block1, blockById); + blockById = wallet.getBlockByNum(BLOCK_NUM_TWO); + assertEquals("getBlockById2", block2, blockById); + blockById = wallet.getBlockByNum(BLOCK_NUM_THREE); + assertEquals("getBlockById3", block3, blockById); + blockById = wallet.getBlockByNum(BLOCK_NUM_FOUR, true); + assertEquals("getBlockById4", block4, blockById); + blockById = wallet.getBlockByNum(BLOCK_NUM_FIVE, false); + assertNotEquals("getBlockById5", block5, blockById); } @Test @@ -368,6 +381,38 @@ public void getBlocksByLimit() { Assert.assertFalse("getBlocksByLimit8", blocksByLimit.getBlockList().contains(block5)); } + @Test + public void getBlockHeadersByLimit() { + BlockList blocksByLimit = wallet.getBlocksByLimitNext(3, 2, false); + Assert.assertTrue("getBlockHeadersByLimit1", blocksByLimit.getBlockList().contains( + wallet.getBlockById(ByteString.copyFrom(new BlockCapsule(block3).getBlockId().getBytes()), + false))); + Assert.assertFalse("getBlockHeadersByLimit2", blocksByLimit.getBlockList().contains( + wallet.getBlockById(ByteString.copyFrom(new BlockCapsule(block4).getBlockId().getBytes()), + true))); + Assert.assertTrue("getBlockHeadersByLimit3", blocksByLimit.getBlockList().contains( + wallet.getBlockById(ByteString.copyFrom(new BlockCapsule(block4).getBlockId().getBytes()), + false))); + blocksByLimit = wallet.getBlocksByLimitNext(0, 5, false); + Assert.assertFalse("getBlockHeadersByLimit4", + blocksByLimit.getBlockList().contains(chainBaseManager.getGenesisBlock().getInstance())); + Assert.assertTrue("getBlockHeadersByLimit5", blocksByLimit.getBlockList().contains( + wallet.getBlockById(ByteString.copyFrom(new BlockCapsule(block1).getBlockId().getBytes()), + false))); + Assert.assertTrue("getBlockHeadersByLimit6", blocksByLimit.getBlockList().contains( + wallet.getBlockById(ByteString.copyFrom(new BlockCapsule(block2).getBlockId().getBytes()), + false))); + Assert.assertTrue("getBlockHeadersByLimit7", blocksByLimit.getBlockList().contains( + wallet.getBlockById(ByteString.copyFrom(new BlockCapsule(block3).getBlockId().getBytes()), + false))); + Assert.assertTrue("getBlockHeadersByLimit8", blocksByLimit.getBlockList().contains( + wallet.getBlockById(ByteString.copyFrom(new BlockCapsule(block4).getBlockId().getBytes()), + false))); + Assert.assertFalse("getBlockHeadersByLimit9", blocksByLimit.getBlockList().contains( + wallet.getBlockById(ByteString.copyFrom(new BlockCapsule(block5).getBlockId().getBytes()), + false))); + } + @Test public void getTransactionInfoById() { TransactionInfo transactionById1 = wallet.getTransactionInfoById( @@ -440,6 +485,25 @@ public void getBlockByLatestNum() { blockByLatestNum.getBlockList().contains(block4)); } + @Test + public void getBlockHeaderByLatestNum() { + BlockList blockByLatestNum = wallet.getBlockByLatestNum(2, false); + Assert.assertFalse("getBlockByLatestNum1", + blockByLatestNum.getBlockList().contains(block5)); + Assert.assertTrue("getBlockByLatestNum2", + blockByLatestNum.getBlockList().contains(wallet.getBlockByNum(BLOCK_NUM_FOUR, false))); + } + + @Test + public void getNowBlock() { + Block now = wallet.getNowBlock(); + Assert.assertEquals("getNowBlock1", now, block5); + now = wallet.getNowBlock(false); + Assert.assertEquals("getNowBlock2", + now, wallet.getBlockByNum(BLOCK_NUM_FIVE, false)); + Assert.assertNotEquals("getNowBlock3", now, block5); + } + @Test public void getPaginatedAssetIssueList() { buildAssetIssue(); From bb08f6d3f1f4fc32a3ab06bfe2bbd3c615690242 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 31 Mar 2022 11:01:16 +0800 Subject: [PATCH 0043/1197] style(api): fix sonar check for checkStyle Num 24. --- .../org/tron/core/services/RpcApiService.java | 75 ++++++++++++------- 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 082f68649ac..8e0f95b70ef 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -403,8 +403,9 @@ public void blockUntilShutdown() { } } - public void generateAddressCommon(EmptyMessage request, - StreamObserver responseObserver) { + public void generateAddressCommon( + EmptyMessage request, + StreamObserver responseObserver) { SignInterface cryptoEngine = SignUtils.getGeneratedRandomSign(Utils.getRandom(), Args.getInstance().isECKeyCryptoEngine()); byte[] priKey = cryptoEngine.getPrivateKey(); @@ -485,8 +486,9 @@ public void getTransactionFromPendingCommon(BytesMessage request, responseObserver.onCompleted(); } - public void getTransactionListFromPendingCommon(EmptyMessage request, - StreamObserver responseObserver) { + public void getTransactionListFromPendingCommon( + EmptyMessage request, + StreamObserver responseObserver) { try { TransactionIdList.Builder builder = TransactionIdList.newBuilder(); builder.addAllTxId(dbManager.getTxListFromPending()); @@ -515,8 +517,9 @@ public void getPendingSizeCommon(EmptyMessage request, public class DatabaseApi extends DatabaseImplBase { @Override - public void getBlockReference(org.tron.api.GrpcAPI.EmptyMessage request, - io.grpc.stub.StreamObserver responseObserver) { + public void getBlockReference( + org.tron.api.GrpcAPI.EmptyMessage request, + io.grpc.stub.StreamObserver responseObserver) { long headBlockNum = dbManager.getDynamicPropertiesStore() .getLatestBlockHeaderNumber(); byte[] blockHeaderHash = dbManager.getDynamicPropertiesStore() @@ -711,8 +714,9 @@ public void getDelegatedResource(DelegatedResourceMessage request, } @Override - public void getDelegatedResourceAccountIndex(BytesMessage request, - StreamObserver responseObserver) { + public void getDelegatedResourceAccountIndex( + BytesMessage request, + StreamObserver responseObserver) { responseObserver .onNext(wallet.getDelegatedResourceAccountIndex(request.getValue())); responseObserver.onCompleted(); @@ -796,8 +800,9 @@ public void getBurnTrx(EmptyMessage request, StreamObserver respo } @Override - public void getMerkleTreeVoucherInfo(OutputPointInfo request, - StreamObserver responseObserver) { + public void getMerkleTreeVoucherInfo( + OutputPointInfo request, + StreamObserver responseObserver) { try { checkSupportShieldedTransaction(); @@ -922,8 +927,9 @@ public void scanShieldedTRC20NotesByOvk(OvkDecryptTRC20Parameters request, } @Override - public void isShieldedTRC20ContractNoteSpent(NfTRC20Parameters request, - StreamObserver responseObserver) { + public void isShieldedTRC20ContractNoteSpent( + NfTRC20Parameters request, + StreamObserver responseObserver) { try { checkSupportShieldedTRC20Transaction(); responseObserver.onNext(wallet.isShieldedTRC20ContractNoteSpent(request)); @@ -1211,8 +1217,9 @@ public void getTransactionSignWeight(Transaction req, } @Override - public void getTransactionApprovedList(Transaction req, - StreamObserver responseObserver) { + public void getTransactionApprovedList( + Transaction req, + StreamObserver responseObserver) { TransactionApprovedList tal = wallet.getTransactionApprovedList(req); responseObserver.onNext(tal); responseObserver.onCompleted(); @@ -1387,16 +1394,20 @@ private void checkVoteWitnessAccount(VoteWitnessContract req) { AccountCapsule account = dbManager.getAccountStore().get(ownerAddress.toByteArray()); Preconditions.checkNotNull(account, - "OwnerAddress[" + StringUtil.createReadableString(ownerAddress) + "] not exists"); + "OwnerAddress[" + + StringUtil.createReadableString(ownerAddress) + "] not exists"); int votesCount = req.getVotesCount(); - Preconditions.checkArgument(votesCount <= 0, "VotesCount[" + votesCount + "] <= 0"); + Preconditions.checkArgument(votesCount <= 0, + "VotesCount[" + votesCount + "] <= 0"); if (dbManager.getDynamicPropertiesStore().supportAllowNewResourceModel()) { Preconditions.checkArgument(account.getAllTronPower() < votesCount, - "tron power[" + account.getAllTronPower() + "] < VotesCount[" + votesCount + "]"); + "tron power[" + account.getAllTronPower() + + "] < VotesCount[" + votesCount + "]"); } else { Preconditions.checkArgument(account.getTronPower() < votesCount, - "tron power[" + account.getTronPower() + "] < VotesCount[" + votesCount + "]"); + "tron power[" + account.getTronPower() + + "] < VotesCount[" + votesCount + "]"); } req.getVotesList().forEach(vote -> { @@ -1405,7 +1416,8 @@ private void checkVoteWitnessAccount(VoteWitnessContract req) { .get(voteAddress.toByteArray()); String readableWitnessAddress = StringUtil.createReadableString(voteAddress); - Preconditions.checkNotNull(witness, "witness[" + readableWitnessAddress + "] not exists"); + Preconditions.checkNotNull(witness, + "witness[" + readableWitnessAddress + "] not exists"); Preconditions.checkArgument(vote.getVoteCount() <= 0, "VoteAddress[" + readableWitnessAddress + "], VotesCount[" + vote .getVoteCount() + "] <= 0"); @@ -2098,8 +2110,9 @@ public void getDelegatedResource(DelegatedResourceMessage request, responseObserver.onCompleted(); } - public void getDelegatedResourceAccountIndex(BytesMessage request, - StreamObserver responseObserver) { + public void getDelegatedResourceAccountIndex( + BytesMessage request, + StreamObserver responseObserver) { responseObserver .onNext(wallet.getDelegatedResourceAccountIndex(request.getValue())); responseObserver.onCompleted(); @@ -2175,8 +2188,9 @@ public void accountPermissionUpdate(AccountPermissionUpdateContract request, } @Override - public void getMerkleTreeVoucherInfo(OutputPointInfo request, - StreamObserver responseObserver) { + public void getMerkleTreeVoucherInfo( + OutputPointInfo request, + StreamObserver responseObserver) { try { checkSupportShieldedTransaction(); @@ -2224,8 +2238,9 @@ public void createShieldedTransaction(PrivateParameters request, } @Override - public void createShieldedTransactionWithoutSpendAuthSig(PrivateParametersWithoutAsk request, - StreamObserver responseObserver) { + public void createShieldedTransactionWithoutSpendAuthSig( + PrivateParametersWithoutAsk request, + StreamObserver responseObserver) { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); @@ -2299,8 +2314,9 @@ public void getRcm(EmptyMessage request, } @Override - public void getExpandedSpendingKey(BytesMessage request, - StreamObserver responseObserver) { + public void getExpandedSpendingKey( + BytesMessage request, + StreamObserver responseObserver) { ByteString spendingKey = request.getValue(); try { @@ -2608,8 +2624,9 @@ public void scanShieldedTRC20NotesByOvk( } @Override - public void isShieldedTRC20ContractNoteSpent(NfTRC20Parameters request, - StreamObserver responseObserver) { + public void isShieldedTRC20ContractNoteSpent( + NfTRC20Parameters request, + StreamObserver responseObserver) { try { checkSupportShieldedTRC20Transaction(); From 4181891d6358c83fad24fc6045ba9e052aa7f161 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 1 Apr 2022 19:18:03 +0800 Subject: [PATCH 0044/1197] feature(api): Simplify the code. 1. change param from `detail` to `only_header` 2. clear trx move to api instead of Wallet.java --- .../src/main/java/org/tron/core/Wallet.java | 66 +++++++--------- .../org/tron/core/services/RpcApiService.java | 68 +++++++--------- .../services/http/GetBlockByIdServlet.java | 6 +- .../http/GetBlockByLatestNumServlet.java | 9 ++- .../http/GetBlockByLimitNextServlet.java | 11 +-- .../services/http/GetBlockByNumServlet.java | 6 +- .../services/http/GetNowBlockServlet.java | 14 +++- .../tron/core/services/http/PostParams.java | 8 +- .../org/tron/core/services/http/Util.java | 32 ++++---- .../test/java/org/tron/core/WalletTest.java | 79 ++----------------- protocol/src/main/protos/api/api.proto | 12 ++- 11 files changed, 120 insertions(+), 191 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 05f3fab11d1..c22f0379c66 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -645,36 +645,18 @@ public byte[] createAddress(byte[] passPhrase) { return ecKey.getAddress(); } - public Block dealBlock(Block block, boolean detail) { - if (Objects.isNull(block)) { - return null; - } - if (detail) { - return block; - } - return block.toBuilder().clearTransactions().build(); - } - public Block getNowBlock() { - return getNowBlock(true); - } - - public Block getNowBlock(boolean detail) { List blockList = chainBaseManager.getBlockStore().getBlockByLatestNum(1); if (CollectionUtils.isEmpty(blockList)) { return null; + } else { + return blockList.get(0).getInstance(); } - return dealBlock(blockList.get(0).getInstance(), detail); - } public Block getBlockByNum(long blockNum) { - return getBlockByNum(blockNum, true); - } - - public Block getBlockByNum(long blockNum, boolean detail) { try { - return dealBlock(chainBaseManager.getBlockByNum(blockNum).getInstance(),detail); + return chainBaseManager.getBlockByNum(blockNum).getInstance(); } catch (StoreException e) { logger.info(e.getMessage()); return null; @@ -1359,10 +1341,6 @@ public NumberMessage getNextMaintenanceTime() { } public Block getBlockById(ByteString blockId) { - return getBlockById(blockId, true); - } - - public Block getBlockById(ByteString blockId, boolean detail) { if (Objects.isNull(blockId)) { return null; } @@ -1372,31 +1350,23 @@ public Block getBlockById(ByteString blockId, boolean detail) { } catch (StoreException e) { logger.error(e.getMessage()); } - return dealBlock(block, detail); + return block; } public BlockList getBlocksByLimitNext(long number, long limit) { - return getBlocksByLimitNext(number, limit, true); - } - - public BlockList getBlocksByLimitNext(long number, long limit, boolean detail) { if (limit <= 0) { return null; } BlockList.Builder blockListBuilder = BlockList.newBuilder(); chainBaseManager.getBlockStore().getLimitNumber(number, limit).forEach( - blockCapsule -> blockListBuilder.addBlock(dealBlock(blockCapsule.getInstance(), detail))); + blockCapsule -> blockListBuilder.addBlock(blockCapsule.getInstance())); return blockListBuilder.build(); } public BlockList getBlockByLatestNum(long getNum) { - return getBlockByLatestNum(getNum, true); - } - - public BlockList getBlockByLatestNum(long getNum, boolean detail) { BlockList.Builder blockListBuilder = BlockList.newBuilder(); chainBaseManager.getBlockStore().getBlockByLatestNum(getNum).forEach( - blockCapsule -> blockListBuilder.addBlock(dealBlock(blockCapsule.getInstance(), detail))); + blockCapsule -> blockListBuilder.addBlock(blockCapsule.getInstance())); return blockListBuilder.build(); } @@ -3993,5 +3963,29 @@ public boolean isMining() { public Chainbase.Cursor getCursor() { return chainBaseManager.getBlockStore().getRevokingDB().getCursor(); } + + public Block clearTrxForBlock(Block block, boolean onlyHeader) { + if (Objects.isNull(block)) { + return null; + } + if (onlyHeader) { + return block.toBuilder().clearTransactions().build(); + } + return block; + } + + public BlockList clearTrxBlockList(BlockList blockList, boolean onlyHeader) { + if (Objects.isNull(blockList) || blockList.getBlockList().isEmpty()) { + return blockList; + } + if (onlyHeader) { + BlockList.Builder blockListBuilder = BlockList.newBuilder(); + blockList.getBlockList().forEach(block -> blockListBuilder.addBlock(clearTrxForBlock(block, + true))); + return blockListBuilder.build(); + } + return blockList; + + } } diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 8e0f95b70ef..959e57cd5a0 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -535,26 +535,24 @@ public void getBlockReference( @Override public void getNowBlock(EmptyMessage request, StreamObserver responseObserver) { Block block = null; - boolean detail = !request.hasBase() || request.getBase().getDetail(); try { block = chainBaseManager.getHead().getInstance(); } catch (StoreException e) { logger.error(e.getMessage()); } - responseObserver.onNext(wallet.dealBlock(block, detail)); + responseObserver.onNext(wallet.clearTrxForBlock(block, request.getOnlyHeader())); responseObserver.onCompleted(); } @Override public void getBlockByNum(NumberMessage request, StreamObserver responseObserver) { Block block = null; - boolean detail = !request.hasBase() || request.getBase().getDetail(); try { block = chainBaseManager.getBlockByNum(request.getNum()).getInstance(); } catch (StoreException e) { logger.error(e.getMessage()); } - responseObserver.onNext(wallet.dealBlock(block, detail)); + responseObserver.onNext(wallet.clearTrxForBlock(block, request.getOnlyHeader())); responseObserver.onCompleted(); } @@ -664,16 +662,16 @@ public void getAssetIssueById(BytesMessage request, @Override public void getNowBlock(EmptyMessage request, StreamObserver responseObserver) { - boolean detail = !request.hasBase() || request.getBase().getDetail(); - responseObserver.onNext(wallet.getNowBlock(detail)); + responseObserver.onNext(wallet.clearTrxForBlock(wallet.getNowBlock(), + request.getOnlyHeader())); responseObserver.onCompleted(); } @Override public void getNowBlock2(EmptyMessage request, StreamObserver responseObserver) { - boolean detail = !request.hasBase() || request.getBase().getDetail(); - responseObserver.onNext(block2Extention(wallet.getNowBlock(detail))); + responseObserver.onNext(block2Extention(wallet.clearTrxForBlock(wallet.getNowBlock(), + request.getOnlyHeader()))); responseObserver.onCompleted(); } @@ -681,9 +679,8 @@ public void getNowBlock2(EmptyMessage request, public void getBlockByNum(NumberMessage request, StreamObserver responseObserver) { long num = request.getNum(); if (num >= 0) { - boolean detail = !request.hasBase() || request.getBase().getDetail(); - Block reply = wallet.getBlockByNum(num, detail); - responseObserver.onNext(reply); + Block reply = wallet.getBlockByNum(num); + responseObserver.onNext(wallet.clearTrxForBlock(reply, request.getOnlyHeader())); } else { responseObserver.onNext(null); } @@ -695,9 +692,9 @@ public void getBlockByNum2(NumberMessage request, StreamObserver responseObserver) { long num = request.getNum(); if (num >= 0) { - boolean detail = !request.hasBase() || request.getBase().getDetail(); - Block reply = wallet.getBlockByNum(num, detail); - responseObserver.onNext(block2Extention(reply)); + Block reply = wallet.getBlockByNum(num); + responseObserver.onNext(block2Extention(wallet.clearTrxForBlock(reply, + request.getOnlyHeader()))); } else { responseObserver.onNext(null); } @@ -1689,32 +1686,31 @@ public void exchangeTransaction(ExchangeTransactionContract request, @Override public void getNowBlock(EmptyMessage request, StreamObserver responseObserver) { - boolean detail = !request.hasBase() || request.getBase().getDetail(); - responseObserver.onNext(wallet.getNowBlock(detail)); + responseObserver.onNext(wallet.clearTrxForBlock(wallet.getNowBlock(), + request.getOnlyHeader())); responseObserver.onCompleted(); } @Override public void getNowBlock2(EmptyMessage request, StreamObserver responseObserver) { - boolean detail = !request.hasBase() || request.getBase().getDetail(); - Block block = wallet.getNowBlock(detail); + Block block = wallet.clearTrxForBlock(wallet.getNowBlock(), request.getOnlyHeader()); responseObserver.onNext(block2Extention(block)); responseObserver.onCompleted(); } @Override public void getBlockByNum(NumberMessage request, StreamObserver responseObserver) { - boolean detail = !request.hasBase() || request.getBase().getDetail(); - responseObserver.onNext(wallet.getBlockByNum(request.getNum(), detail)); + responseObserver.onNext(wallet.clearTrxForBlock(wallet.getBlockByNum(request.getNum()), + request.getOnlyHeader())); responseObserver.onCompleted(); } @Override public void getBlockByNum2(NumberMessage request, StreamObserver responseObserver) { - boolean detail = !request.hasBase() || request.getBase().getDetail(); - Block block = wallet.getBlockByNum(request.getNum(), detail); + Block block = wallet.clearTrxForBlock(wallet.getBlockByNum(request.getNum()), + request.getOnlyHeader()); responseObserver.onNext(block2Extention(block)); responseObserver.onCompleted(); } @@ -1877,13 +1873,8 @@ public void getAssetIssueById(BytesMessage request, @Override public void getBlockById(BytesMessage request, StreamObserver responseObserver) { ByteString blockId = request.getValue(); - - if (Objects.nonNull(blockId)) { - boolean detail = !request.hasBase() || request.getBase().getDetail(); - responseObserver.onNext(wallet.getBlockById(blockId, detail)); - } else { - responseObserver.onNext(null); - } + responseObserver.onNext(wallet.clearTrxForBlock(wallet.getBlockById(blockId), + request.getOnlyHeader())); responseObserver.onCompleted(); } @@ -1920,9 +1911,8 @@ public void getBlockByLimitNext(BlockLimit request, long endNum = request.getEndNum(); if (endNum > 0 && endNum > startNum && endNum - startNum <= BLOCK_LIMIT_NUM) { - boolean detail = !request.hasBase() || request.getBase().getDetail(); - responseObserver.onNext(wallet.getBlocksByLimitNext(startNum, - endNum - startNum, detail)); + responseObserver.onNext(wallet.clearTrxBlockList(wallet.getBlocksByLimitNext(startNum, + endNum - startNum), request.getOnlyHeader())); } else { responseObserver.onNext(null); } @@ -1936,9 +1926,9 @@ public void getBlockByLimitNext2(BlockLimit request, long endNum = request.getEndNum(); if (endNum > 0 && endNum > startNum && endNum - startNum <= BLOCK_LIMIT_NUM) { - boolean detail = !request.hasBase() || request.getBase().getDetail(); - responseObserver.onNext(blockList2Extention(wallet.getBlocksByLimitNext(startNum, - endNum - startNum, detail))); + responseObserver.onNext(blockList2Extention(wallet.clearTrxBlockList( + wallet.getBlocksByLimitNext(startNum, endNum - startNum), + request.getOnlyHeader()))); } else { responseObserver.onNext(null); } @@ -1951,8 +1941,8 @@ public void getBlockByLatestNum(NumberMessage request, long getNum = request.getNum(); if (getNum > 0 && getNum < BLOCK_LIMIT_NUM) { - boolean detail = !request.hasBase() || request.getBase().getDetail(); - responseObserver.onNext(wallet.getBlockByLatestNum(getNum, detail)); + responseObserver.onNext(wallet.clearTrxBlockList(wallet.getBlockByLatestNum(getNum), + request.getOnlyHeader())); } else { responseObserver.onNext(null); } @@ -1965,8 +1955,8 @@ public void getBlockByLatestNum2(NumberMessage request, long getNum = request.getNum(); if (getNum > 0 && getNum < BLOCK_LIMIT_NUM) { - boolean detail = !request.hasBase() || request.getBase().getDetail(); - responseObserver.onNext(blockList2Extention(wallet.getBlockByLatestNum(getNum, detail))); + responseObserver.onNext(blockList2Extention(wallet.clearTrxBlockList( + wallet.getBlockByLatestNum(getNum), request.getOnlyHeader()))); } else { responseObserver.onNext(null); } diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java index 7e88297b1d2..74cc6684fe7 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java @@ -23,7 +23,7 @@ public class GetBlockByIdServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { String input = request.getParameter("value"); - fillResponse(Util.getVisible(request),Util.getDetail(request), + fillResponse(Util.getVisible(request), Util.getOnlyHeader(request), ByteString.copyFrom(ByteArray.fromHexString(input)), response); } catch (Exception e) { Util.processError(e, response); @@ -35,7 +35,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) PostParams params = PostParams.getPostParams(request); BytesMessage.Builder build = BytesMessage.newBuilder(); JsonFormat.merge(params.getParams(), build, params.isVisible()); - fillResponse(params.isVisible(), params.isDetail(), build.getValue(), response); + fillResponse(params.isVisible(), params.isOnlyHeader(), build.getValue(), response); } catch (Exception e) { Util.processError(e, response); } @@ -44,7 +44,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) private void fillResponse(boolean visible, boolean detail, ByteString blockId, HttpServletResponse response) throws IOException { - Block reply = wallet.getBlockById(blockId, detail); + Block reply = wallet.clearTrxForBlock(wallet.getBlockById(blockId), detail); if (reply != null) { response.getWriter().println(Util.printBlock(reply, visible)); } else { diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java index adb35e71d9a..ddb890540ac 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java @@ -21,7 +21,7 @@ public class GetBlockByLatestNumServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - fillResponse(Util.getVisible(request), Util.getDetail(request), + fillResponse(Util.getVisible(request), Util.getOnlyHeader(request), Long.parseLong(request.getParameter("num")), response); } catch (Exception e) { Util.processError(e, response); @@ -33,16 +33,17 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) PostParams params = PostParams.getPostParams(request); NumberMessage.Builder build = NumberMessage.newBuilder(); JsonFormat.merge(params.getParams(), build, params.isVisible()); - fillResponse(params.isVisible(), params.isDetail(), build.getNum(), response); + fillResponse(params.isVisible(), params.isOnlyHeader(), build.getNum(), response); } catch (Exception e) { Util.processError(e, response); } } - private void fillResponse(boolean visible, boolean detail, long num, HttpServletResponse response) + private void fillResponse(boolean visible, boolean onlyHeader, long num, + HttpServletResponse response) throws IOException { if (num > 0 && num < BLOCK_LIMIT_NUM) { - BlockList reply = wallet.getBlockByLatestNum(num, detail); + BlockList reply = wallet.clearTrxBlockList(wallet.getBlockByLatestNum(num), onlyHeader); if (reply != null) { response.getWriter().println(Util.printBlockList(reply, visible)); return; diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java index 9d8b89f0520..87341cdc575 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java @@ -21,7 +21,7 @@ public class GetBlockByLimitNextServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - fillResponse(Util.getVisible(request),Util.getDetail(request), + fillResponse(Util.getVisible(request), Util.getOnlyHeader(request), Long.parseLong(request.getParameter("startNum")), Long.parseLong(request.getParameter("endNum")), response); } catch (Exception e) { @@ -34,18 +34,19 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) PostParams params = PostParams.getPostParams(request); BlockLimit.Builder build = BlockLimit.newBuilder(); JsonFormat.merge(params.getParams(), build, params.isVisible()); - fillResponse(params.isVisible(),params.isDetail(), + fillResponse(params.isVisible(), params.isOnlyHeader(), build.getStartNum(), build.getEndNum(), response); } catch (Exception e) { Util.processError(e, response); } } - private void fillResponse(boolean visible, boolean detail, long startNum, long endNum, - HttpServletResponse response) + private void fillResponse(boolean visible, boolean onlyHeader, long startNum, long endNum, + HttpServletResponse response) throws IOException { if (endNum > 0 && endNum > startNum && endNum - startNum <= BLOCK_LIMIT_NUM) { - BlockList reply = wallet.getBlocksByLimitNext(startNum, endNum - startNum, detail); + BlockList reply = wallet.clearTrxBlockList( + wallet.getBlocksByLimitNext(startNum, endNum - startNum), onlyHeader); if (reply != null) { response.getWriter().println(Util.printBlockList(reply, visible)); return; diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java index 5b9bcc54a25..a6b9109871a 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java @@ -20,7 +20,7 @@ public class GetBlockByNumServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - fillResponse(Util.getVisible(request),Util.getDetail(request), + fillResponse(Util.getVisible(request), Util.getOnlyHeader(request), Long.parseLong(request.getParameter("num")), response); } catch (Exception e) { Util.processError(e, response); @@ -32,7 +32,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) PostParams params = PostParams.getPostParams(request); NumberMessage.Builder build = NumberMessage.newBuilder(); JsonFormat.merge(params.getParams(), build, params.isVisible()); - fillResponse(params.isVisible(), params.isDetail(), build.getNum(), response); + fillResponse(params.isVisible(), params.isOnlyHeader(), build.getNum(), response); } catch (Exception e) { Util.processError(e, response); } @@ -40,7 +40,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) private void fillResponse(boolean visible, boolean detail, long num, HttpServletResponse response) throws IOException { - Block reply = wallet.getBlockByNum(num, detail); + Block reply = wallet.clearTrxForBlock(wallet.getBlockByNum(num), detail); if (reply != null) { response.getWriter().println(Util.printBlock(reply, visible)); } else { diff --git a/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java b/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java index bff8187bac4..ba3db55e7e8 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java @@ -18,7 +18,7 @@ public class GetNowBlockServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - Block reply = wallet.getNowBlock(Util.getDetail(request)); + Block reply = wallet.clearTrxForBlock(wallet.getNowBlock(), Util.getOnlyHeader(request)); if (reply != null) { response.getWriter().println(Util.printBlock(reply, Util.getVisible(request))); } else { @@ -30,6 +30,16 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { } protected void doPost(HttpServletRequest request, HttpServletResponse response) { - doGet(request, response); + try { + PostParams params = PostParams.getPostParams(request); + Block reply = wallet.clearTrxForBlock(wallet.getNowBlock(), params.isOnlyHeader()); + if (reply != null) { + response.getWriter().println(Util.printBlock(reply, Util.getVisible(request))); + } else { + response.getWriter().println("{}"); + } + } catch (Exception e) { + Util.processError(e, response); + } } } \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/services/http/PostParams.java b/framework/src/main/java/org/tron/core/services/http/PostParams.java index 2ff47a36407..cf5575646f7 100644 --- a/framework/src/main/java/org/tron/core/services/http/PostParams.java +++ b/framework/src/main/java/org/tron/core/services/http/PostParams.java @@ -14,17 +14,17 @@ public class PostParams { private boolean visible; @Getter - private boolean detail = true; + private boolean onlyHeader; public PostParams(String params, boolean visible) { this.params = params; this.visible = visible; } - public PostParams(String params, boolean visible, boolean detail) { + public PostParams(String params, boolean visible, boolean onlyHeader) { this.params = params; this.visible = visible; - this.detail = detail; + this.onlyHeader = onlyHeader; } @@ -33,7 +33,7 @@ public static PostParams getPostParams(HttpServletRequest request) throws Except String input = request.getReader().lines().collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); boolean visible = Util.getVisiblePost(input); - boolean detail = Util.getDetailPost(input); + boolean detail = Util.getOnlyHeaderPost(input); return new PostParams(input, visible, detail); } } diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index a9cdff7c08c..74d14088a94 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -61,7 +61,7 @@ public class Util { public static final String CONTRACT_TYPE = "contractType"; public static final String EXTRA_DATA = "extra_data"; public static final String PARAMETER = "parameter"; - public static final String DETAIL = "detail"; + public static final String ONLY_HEADER = "only_header"; public static String printTransactionFee(String transactionFee) { JSONObject jsonObject = new JSONObject(); @@ -311,12 +311,12 @@ public static boolean getVisible(final HttpServletRequest request) { return visible; } - public static boolean getDetail(final HttpServletRequest request) { - boolean detail = true; - if (StringUtil.isNotBlank(request.getParameter(DETAIL))) { - detail = Boolean.parseBoolean(request.getParameter(DETAIL)); + public static boolean getOnlyHeader(final HttpServletRequest request) { + boolean onlyHeader = false; + if (StringUtil.isNotBlank(request.getParameter(ONLY_HEADER))) { + onlyHeader = Boolean.parseBoolean(request.getParameter(ONLY_HEADER)); } - return detail; + return onlyHeader; } public static boolean getVisiblePost(final String input) { @@ -324,23 +324,27 @@ public static boolean getVisiblePost(final String input) { if (StringUtil.isNotBlank(input)) { JSONObject jsonObject = JSON.parseObject(input); if (jsonObject.containsKey(VISIBLE)) { - visible = jsonObject.getBoolean(VISIBLE); + Boolean tmp = jsonObject.getBoolean(VISIBLE); + if (tmp != null) { + visible = tmp; + } } } - return visible; } - public static boolean getDetailPost(final String input) { - boolean detail = true; + public static boolean getOnlyHeaderPost(final String input) { + boolean onlyHeader = false; if (StringUtil.isNotBlank(input)) { JSONObject jsonObject = JSON.parseObject(input); - if (jsonObject.containsKey(DETAIL)) { - detail = jsonObject.getBoolean(DETAIL); + if (jsonObject.containsKey(ONLY_HEADER)) { + Boolean tmp = jsonObject.getBoolean(ONLY_HEADER); + if (tmp != null) { + onlyHeader = tmp; + } } } - - return detail; + return onlyHeader; } public static String getContractType(final String input) { diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 5965bf2e97e..31e42ad96aa 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -21,7 +21,6 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; import com.google.protobuf.Any; import com.google.protobuf.ByteString; @@ -100,10 +99,10 @@ public class WalletTest { public static final long TRANSACTION_TIMESTAMP_THREE = DateTime.now().minusDays(2).getMillis(); public static final long TRANSACTION_TIMESTAMP_FOUR = DateTime.now().minusDays(1).getMillis(); public static final long TRANSACTION_TIMESTAMP_FIVE = DateTime.now().getMillis(); - private static final TronApplicationContext context; + private static TronApplicationContext context; private static Wallet wallet; private static ChainBaseManager chainBaseManager; - private static final String dbPath = "output_wallet_test"; + private static String dbPath = "output_wallet_test"; private static Block block1; private static Block block2; private static Block block3; @@ -231,7 +230,6 @@ private static void initBlock() { private static void addBlockToStore(Block block) { BlockCapsule blockCapsule = new BlockCapsule(block); chainBaseManager.getBlockStore().put(blockCapsule.getBlockId().getBytes(), blockCapsule); - chainBaseManager.getBlockIndexStore().put(blockCapsule.getBlockId()); } private static Block getBuildBlock(long timestamp, long num, long witnessId, @@ -343,27 +341,11 @@ public void getBlockById() { .getBlockById(ByteString.copyFrom(new BlockCapsule(block3).getBlockId().getBytes())); assertEquals("getBlockById3", block3, blockById); blockById = wallet - .getBlockById(ByteString.copyFrom(new BlockCapsule(block4).getBlockId().getBytes()), - true); + .getBlockById(ByteString.copyFrom(new BlockCapsule(block4).getBlockId().getBytes())); assertEquals("getBlockById4", block4, blockById); blockById = wallet - .getBlockById(ByteString.copyFrom(new BlockCapsule(block5).getBlockId().getBytes()), - false); - assertNotEquals("getBlockById5", block5, blockById); - } - - @Test - public void getBlockByNum() { - Block blockById = wallet.getBlockByNum(BLOCK_NUM_ONE); - assertEquals("getBlockById1", block1, blockById); - blockById = wallet.getBlockByNum(BLOCK_NUM_TWO); - assertEquals("getBlockById2", block2, blockById); - blockById = wallet.getBlockByNum(BLOCK_NUM_THREE); - assertEquals("getBlockById3", block3, blockById); - blockById = wallet.getBlockByNum(BLOCK_NUM_FOUR, true); - assertEquals("getBlockById4", block4, blockById); - blockById = wallet.getBlockByNum(BLOCK_NUM_FIVE, false); - assertNotEquals("getBlockById5", block5, blockById); + .getBlockById(ByteString.copyFrom(new BlockCapsule(block5).getBlockId().getBytes())); + assertEquals("getBlockById5", block5, blockById); } @Test @@ -381,38 +363,6 @@ public void getBlocksByLimit() { Assert.assertFalse("getBlocksByLimit8", blocksByLimit.getBlockList().contains(block5)); } - @Test - public void getBlockHeadersByLimit() { - BlockList blocksByLimit = wallet.getBlocksByLimitNext(3, 2, false); - Assert.assertTrue("getBlockHeadersByLimit1", blocksByLimit.getBlockList().contains( - wallet.getBlockById(ByteString.copyFrom(new BlockCapsule(block3).getBlockId().getBytes()), - false))); - Assert.assertFalse("getBlockHeadersByLimit2", blocksByLimit.getBlockList().contains( - wallet.getBlockById(ByteString.copyFrom(new BlockCapsule(block4).getBlockId().getBytes()), - true))); - Assert.assertTrue("getBlockHeadersByLimit3", blocksByLimit.getBlockList().contains( - wallet.getBlockById(ByteString.copyFrom(new BlockCapsule(block4).getBlockId().getBytes()), - false))); - blocksByLimit = wallet.getBlocksByLimitNext(0, 5, false); - Assert.assertFalse("getBlockHeadersByLimit4", - blocksByLimit.getBlockList().contains(chainBaseManager.getGenesisBlock().getInstance())); - Assert.assertTrue("getBlockHeadersByLimit5", blocksByLimit.getBlockList().contains( - wallet.getBlockById(ByteString.copyFrom(new BlockCapsule(block1).getBlockId().getBytes()), - false))); - Assert.assertTrue("getBlockHeadersByLimit6", blocksByLimit.getBlockList().contains( - wallet.getBlockById(ByteString.copyFrom(new BlockCapsule(block2).getBlockId().getBytes()), - false))); - Assert.assertTrue("getBlockHeadersByLimit7", blocksByLimit.getBlockList().contains( - wallet.getBlockById(ByteString.copyFrom(new BlockCapsule(block3).getBlockId().getBytes()), - false))); - Assert.assertTrue("getBlockHeadersByLimit8", blocksByLimit.getBlockList().contains( - wallet.getBlockById(ByteString.copyFrom(new BlockCapsule(block4).getBlockId().getBytes()), - false))); - Assert.assertFalse("getBlockHeadersByLimit9", blocksByLimit.getBlockList().contains( - wallet.getBlockById(ByteString.copyFrom(new BlockCapsule(block5).getBlockId().getBytes()), - false))); - } - @Test public void getTransactionInfoById() { TransactionInfo transactionById1 = wallet.getTransactionInfoById( @@ -485,25 +435,6 @@ public void getBlockByLatestNum() { blockByLatestNum.getBlockList().contains(block4)); } - @Test - public void getBlockHeaderByLatestNum() { - BlockList blockByLatestNum = wallet.getBlockByLatestNum(2, false); - Assert.assertFalse("getBlockByLatestNum1", - blockByLatestNum.getBlockList().contains(block5)); - Assert.assertTrue("getBlockByLatestNum2", - blockByLatestNum.getBlockList().contains(wallet.getBlockByNum(BLOCK_NUM_FOUR, false))); - } - - @Test - public void getNowBlock() { - Block now = wallet.getNowBlock(); - Assert.assertEquals("getNowBlock1", now, block5); - now = wallet.getNowBlock(false); - Assert.assertEquals("getNowBlock2", - now, wallet.getBlockByNum(BLOCK_NUM_FIVE, false)); - Assert.assertNotEquals("getNowBlock3", now, block5); - } - @Test public void getPaginatedAssetIssueList() { buildAssetIssue(); diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index c7c65e91413..5118f5d7019 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -1110,19 +1110,17 @@ message Address { bytes host = 1; int32 port = 2; } -message BaseMessage { - bool detail = 1; -} + message EmptyMessage { - oneof baseMessage {BaseMessage base_ = 1;} + bool only_header = 1; } message NumberMessage { int64 num = 1; - oneof baseMessage {BaseMessage base_ = 2;} + bool only_header = 2; } message BytesMessage { bytes value = 1; - oneof baseMessage {BaseMessage base_ = 2;} + bool only_header = 2; } message TimeMessage { int64 beginInMilliseconds = 1; @@ -1131,7 +1129,7 @@ message TimeMessage { message BlockLimit { int64 startNum = 1; int64 endNum = 2; - oneof baseMessage {BaseMessage base_ = 3;} + bool only_header = 3; } message TransactionLimit { bytes transactionId = 1; From 20c1a1a83941e3a8e80ec78c491c258fa8f785ae Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Sat, 2 Apr 2022 14:23:36 +0800 Subject: [PATCH 0045/1197] feature(api): Simplify the code. 1. change param from `only_header` to `type` 2. use `enum` for `type` --- .../src/main/java/org/tron/core/Wallet.java | 10 +++--- .../org/tron/core/services/RpcApiService.java | 30 ++++++++--------- .../services/http/GetBlockByIdServlet.java | 9 +++--- .../http/GetBlockByLatestNumServlet.java | 9 +++--- .../http/GetBlockByLimitNextServlet.java | 9 +++--- .../services/http/GetBlockByNumServlet.java | 10 +++--- .../services/http/GetNowBlockServlet.java | 29 ++++++++++------- .../tron/core/services/http/PostParams.java | 14 +------- .../org/tron/core/services/http/Util.java | 32 +++++++------------ protocol/src/main/protos/api/api.proto | 13 +++++--- 10 files changed, 80 insertions(+), 85 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index c22f0379c66..ea2449b7de6 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -3964,24 +3964,24 @@ public Chainbase.Cursor getCursor() { return chainBaseManager.getBlockStore().getRevokingDB().getCursor(); } - public Block clearTrxForBlock(Block block, boolean onlyHeader) { + public Block clearTrxForBlock(Block block, GrpcAPI.BlockType type) { if (Objects.isNull(block)) { return null; } - if (onlyHeader) { + if (type == GrpcAPI.BlockType.HEADER) { return block.toBuilder().clearTransactions().build(); } return block; } - public BlockList clearTrxBlockList(BlockList blockList, boolean onlyHeader) { + public BlockList clearTrxBlockList(BlockList blockList, GrpcAPI.BlockType type) { if (Objects.isNull(blockList) || blockList.getBlockList().isEmpty()) { return blockList; } - if (onlyHeader) { + if (type == GrpcAPI.BlockType.HEADER) { BlockList.Builder blockListBuilder = BlockList.newBuilder(); blockList.getBlockList().forEach(block -> blockListBuilder.addBlock(clearTrxForBlock(block, - true))); + type))); return blockListBuilder.build(); } return blockList; diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 959e57cd5a0..250eb46987d 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -540,7 +540,7 @@ public void getNowBlock(EmptyMessage request, StreamObserver responseObse } catch (StoreException e) { logger.error(e.getMessage()); } - responseObserver.onNext(wallet.clearTrxForBlock(block, request.getOnlyHeader())); + responseObserver.onNext(wallet.clearTrxForBlock(block, request.getType())); responseObserver.onCompleted(); } @@ -552,7 +552,7 @@ public void getBlockByNum(NumberMessage request, StreamObserver responseO } catch (StoreException e) { logger.error(e.getMessage()); } - responseObserver.onNext(wallet.clearTrxForBlock(block, request.getOnlyHeader())); + responseObserver.onNext(wallet.clearTrxForBlock(block, request.getType())); responseObserver.onCompleted(); } @@ -663,7 +663,7 @@ public void getAssetIssueById(BytesMessage request, @Override public void getNowBlock(EmptyMessage request, StreamObserver responseObserver) { responseObserver.onNext(wallet.clearTrxForBlock(wallet.getNowBlock(), - request.getOnlyHeader())); + request.getType())); responseObserver.onCompleted(); } @@ -671,7 +671,7 @@ public void getNowBlock(EmptyMessage request, StreamObserver responseObse public void getNowBlock2(EmptyMessage request, StreamObserver responseObserver) { responseObserver.onNext(block2Extention(wallet.clearTrxForBlock(wallet.getNowBlock(), - request.getOnlyHeader()))); + request.getType()))); responseObserver.onCompleted(); } @@ -680,7 +680,7 @@ public void getBlockByNum(NumberMessage request, StreamObserver responseO long num = request.getNum(); if (num >= 0) { Block reply = wallet.getBlockByNum(num); - responseObserver.onNext(wallet.clearTrxForBlock(reply, request.getOnlyHeader())); + responseObserver.onNext(wallet.clearTrxForBlock(reply, request.getType())); } else { responseObserver.onNext(null); } @@ -694,7 +694,7 @@ public void getBlockByNum2(NumberMessage request, if (num >= 0) { Block reply = wallet.getBlockByNum(num); responseObserver.onNext(block2Extention(wallet.clearTrxForBlock(reply, - request.getOnlyHeader()))); + request.getType()))); } else { responseObserver.onNext(null); } @@ -1687,14 +1687,14 @@ public void exchangeTransaction(ExchangeTransactionContract request, @Override public void getNowBlock(EmptyMessage request, StreamObserver responseObserver) { responseObserver.onNext(wallet.clearTrxForBlock(wallet.getNowBlock(), - request.getOnlyHeader())); + request.getType())); responseObserver.onCompleted(); } @Override public void getNowBlock2(EmptyMessage request, StreamObserver responseObserver) { - Block block = wallet.clearTrxForBlock(wallet.getNowBlock(), request.getOnlyHeader()); + Block block = wallet.clearTrxForBlock(wallet.getNowBlock(), request.getType()); responseObserver.onNext(block2Extention(block)); responseObserver.onCompleted(); } @@ -1702,7 +1702,7 @@ public void getNowBlock2(EmptyMessage request, @Override public void getBlockByNum(NumberMessage request, StreamObserver responseObserver) { responseObserver.onNext(wallet.clearTrxForBlock(wallet.getBlockByNum(request.getNum()), - request.getOnlyHeader())); + request.getType())); responseObserver.onCompleted(); } @@ -1710,7 +1710,7 @@ public void getBlockByNum(NumberMessage request, StreamObserver responseO public void getBlockByNum2(NumberMessage request, StreamObserver responseObserver) { Block block = wallet.clearTrxForBlock(wallet.getBlockByNum(request.getNum()), - request.getOnlyHeader()); + request.getType()); responseObserver.onNext(block2Extention(block)); responseObserver.onCompleted(); } @@ -1874,7 +1874,7 @@ public void getAssetIssueById(BytesMessage request, public void getBlockById(BytesMessage request, StreamObserver responseObserver) { ByteString blockId = request.getValue(); responseObserver.onNext(wallet.clearTrxForBlock(wallet.getBlockById(blockId), - request.getOnlyHeader())); + request.getType())); responseObserver.onCompleted(); } @@ -1912,7 +1912,7 @@ public void getBlockByLimitNext(BlockLimit request, if (endNum > 0 && endNum > startNum && endNum - startNum <= BLOCK_LIMIT_NUM) { responseObserver.onNext(wallet.clearTrxBlockList(wallet.getBlocksByLimitNext(startNum, - endNum - startNum), request.getOnlyHeader())); + endNum - startNum), request.getType())); } else { responseObserver.onNext(null); } @@ -1928,7 +1928,7 @@ public void getBlockByLimitNext2(BlockLimit request, if (endNum > 0 && endNum > startNum && endNum - startNum <= BLOCK_LIMIT_NUM) { responseObserver.onNext(blockList2Extention(wallet.clearTrxBlockList( wallet.getBlocksByLimitNext(startNum, endNum - startNum), - request.getOnlyHeader()))); + request.getType()))); } else { responseObserver.onNext(null); } @@ -1942,7 +1942,7 @@ public void getBlockByLatestNum(NumberMessage request, if (getNum > 0 && getNum < BLOCK_LIMIT_NUM) { responseObserver.onNext(wallet.clearTrxBlockList(wallet.getBlockByLatestNum(getNum), - request.getOnlyHeader())); + request.getType())); } else { responseObserver.onNext(null); } @@ -1956,7 +1956,7 @@ public void getBlockByLatestNum2(NumberMessage request, if (getNum > 0 && getNum < BLOCK_LIMIT_NUM) { responseObserver.onNext(blockList2Extention(wallet.clearTrxBlockList( - wallet.getBlockByLatestNum(getNum), request.getOnlyHeader()))); + wallet.getBlockByLatestNum(getNum), request.getType()))); } else { responseObserver.onNext(null); } diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java index 74cc6684fe7..4871870980e 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java @@ -7,6 +7,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.BytesMessage; import org.tron.common.utils.ByteArray; import org.tron.core.Wallet; @@ -23,7 +24,7 @@ public class GetBlockByIdServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { String input = request.getParameter("value"); - fillResponse(Util.getVisible(request), Util.getOnlyHeader(request), + fillResponse(Util.getVisible(request), Util.getBlockType(request), ByteString.copyFrom(ByteArray.fromHexString(input)), response); } catch (Exception e) { Util.processError(e, response); @@ -35,16 +36,16 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) PostParams params = PostParams.getPostParams(request); BytesMessage.Builder build = BytesMessage.newBuilder(); JsonFormat.merge(params.getParams(), build, params.isVisible()); - fillResponse(params.isVisible(), params.isOnlyHeader(), build.getValue(), response); + fillResponse(params.isVisible(), build.getType(), build.getValue(), response); } catch (Exception e) { Util.processError(e, response); } } - private void fillResponse(boolean visible, boolean detail, + private void fillResponse(boolean visible, GrpcAPI.BlockType type, ByteString blockId, HttpServletResponse response) throws IOException { - Block reply = wallet.clearTrxForBlock(wallet.getBlockById(blockId), detail); + Block reply = wallet.clearTrxForBlock(wallet.getBlockById(blockId), type); if (reply != null) { response.getWriter().println(Util.printBlock(reply, visible)); } else { diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java index ddb890540ac..f62774be7b6 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java @@ -6,6 +6,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.BlockList; import org.tron.api.GrpcAPI.NumberMessage; import org.tron.core.Wallet; @@ -21,7 +22,7 @@ public class GetBlockByLatestNumServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - fillResponse(Util.getVisible(request), Util.getOnlyHeader(request), + fillResponse(Util.getVisible(request), Util.getBlockType(request), Long.parseLong(request.getParameter("num")), response); } catch (Exception e) { Util.processError(e, response); @@ -33,17 +34,17 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) PostParams params = PostParams.getPostParams(request); NumberMessage.Builder build = NumberMessage.newBuilder(); JsonFormat.merge(params.getParams(), build, params.isVisible()); - fillResponse(params.isVisible(), params.isOnlyHeader(), build.getNum(), response); + fillResponse(params.isVisible(), build.getType(), build.getNum(), response); } catch (Exception e) { Util.processError(e, response); } } - private void fillResponse(boolean visible, boolean onlyHeader, long num, + private void fillResponse(boolean visible, GrpcAPI.BlockType type, long num, HttpServletResponse response) throws IOException { if (num > 0 && num < BLOCK_LIMIT_NUM) { - BlockList reply = wallet.clearTrxBlockList(wallet.getBlockByLatestNum(num), onlyHeader); + BlockList reply = wallet.clearTrxBlockList(wallet.getBlockByLatestNum(num), type); if (reply != null) { response.getWriter().println(Util.printBlockList(reply, visible)); return; diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java index 87341cdc575..fc0a77a1cc5 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java @@ -6,6 +6,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.BlockLimit; import org.tron.api.GrpcAPI.BlockList; import org.tron.core.Wallet; @@ -21,7 +22,7 @@ public class GetBlockByLimitNextServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - fillResponse(Util.getVisible(request), Util.getOnlyHeader(request), + fillResponse(Util.getVisible(request), Util.getBlockType(request), Long.parseLong(request.getParameter("startNum")), Long.parseLong(request.getParameter("endNum")), response); } catch (Exception e) { @@ -34,19 +35,19 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) PostParams params = PostParams.getPostParams(request); BlockLimit.Builder build = BlockLimit.newBuilder(); JsonFormat.merge(params.getParams(), build, params.isVisible()); - fillResponse(params.isVisible(), params.isOnlyHeader(), + fillResponse(params.isVisible(), build.getType(), build.getStartNum(), build.getEndNum(), response); } catch (Exception e) { Util.processError(e, response); } } - private void fillResponse(boolean visible, boolean onlyHeader, long startNum, long endNum, + private void fillResponse(boolean visible, GrpcAPI.BlockType type, long startNum, long endNum, HttpServletResponse response) throws IOException { if (endNum > 0 && endNum > startNum && endNum - startNum <= BLOCK_LIMIT_NUM) { BlockList reply = wallet.clearTrxBlockList( - wallet.getBlocksByLimitNext(startNum, endNum - startNum), onlyHeader); + wallet.getBlocksByLimitNext(startNum, endNum - startNum), type); if (reply != null) { response.getWriter().println(Util.printBlockList(reply, visible)); return; diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java index a6b9109871a..f5e8f88d1ca 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java @@ -6,6 +6,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.NumberMessage; import org.tron.core.Wallet; import org.tron.protos.Protocol.Block; @@ -20,7 +21,7 @@ public class GetBlockByNumServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - fillResponse(Util.getVisible(request), Util.getOnlyHeader(request), + fillResponse(Util.getVisible(request), Util.getBlockType(request), Long.parseLong(request.getParameter("num")), response); } catch (Exception e) { Util.processError(e, response); @@ -32,15 +33,16 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) PostParams params = PostParams.getPostParams(request); NumberMessage.Builder build = NumberMessage.newBuilder(); JsonFormat.merge(params.getParams(), build, params.isVisible()); - fillResponse(params.isVisible(), params.isOnlyHeader(), build.getNum(), response); + fillResponse(params.isVisible(), build.getType(), build.getNum(), response); } catch (Exception e) { Util.processError(e, response); } } - private void fillResponse(boolean visible, boolean detail, long num, HttpServletResponse response) + private void fillResponse(boolean visible, GrpcAPI.BlockType type, long num, + HttpServletResponse response) throws IOException { - Block reply = wallet.clearTrxForBlock(wallet.getBlockByNum(num), detail); + Block reply = wallet.clearTrxForBlock(wallet.getBlockByNum(num), type); if (reply != null) { response.getWriter().println(Util.printBlock(reply, visible)); } else { diff --git a/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java b/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java index ba3db55e7e8..5f4528c7b0d 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java @@ -1,10 +1,12 @@ package org.tron.core.services.http; +import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.api.GrpcAPI; import org.tron.core.Wallet; import org.tron.protos.Protocol.Block; @@ -18,12 +20,7 @@ public class GetNowBlockServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - Block reply = wallet.clearTrxForBlock(wallet.getNowBlock(), Util.getOnlyHeader(request)); - if (reply != null) { - response.getWriter().println(Util.printBlock(reply, Util.getVisible(request))); - } else { - response.getWriter().println("{}"); - } + fillResponse(Util.getVisible(request), Util.getBlockType(request), response); } catch (Exception e) { Util.processError(e, response); } @@ -32,14 +29,22 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { protected void doPost(HttpServletRequest request, HttpServletResponse response) { try { PostParams params = PostParams.getPostParams(request); - Block reply = wallet.clearTrxForBlock(wallet.getNowBlock(), params.isOnlyHeader()); - if (reply != null) { - response.getWriter().println(Util.printBlock(reply, Util.getVisible(request))); - } else { - response.getWriter().println("{}"); - } + GrpcAPI.EmptyMessage.Builder build = GrpcAPI.EmptyMessage.newBuilder(); + JsonFormat.merge(params.getParams(), build, params.isVisible()); + fillResponse(params.isVisible(), build.getType(), response); } catch (Exception e) { Util.processError(e, response); } } + + private void fillResponse(boolean visible, GrpcAPI.BlockType type, HttpServletResponse response) + throws + IOException { + Block reply = wallet.clearTrxForBlock(wallet.getNowBlock(), type); + if (reply != null) { + response.getWriter().println(Util.printBlock(reply, visible)); + } else { + response.getWriter().println("{}"); + } + } } \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/services/http/PostParams.java b/framework/src/main/java/org/tron/core/services/http/PostParams.java index cf5575646f7..a2077fb3c78 100644 --- a/framework/src/main/java/org/tron/core/services/http/PostParams.java +++ b/framework/src/main/java/org/tron/core/services/http/PostParams.java @@ -13,27 +13,15 @@ public class PostParams { @Getter private boolean visible; - @Getter - private boolean onlyHeader; - public PostParams(String params, boolean visible) { this.params = params; this.visible = visible; } - public PostParams(String params, boolean visible, boolean onlyHeader) { - this.params = params; - this.visible = visible; - this.onlyHeader = onlyHeader; - } - - - public static PostParams getPostParams(HttpServletRequest request) throws Exception { String input = request.getReader().lines().collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); boolean visible = Util.getVisiblePost(input); - boolean detail = Util.getOnlyHeaderPost(input); - return new PostParams(input, visible, detail); + return new PostParams(input, visible); } } diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 74d14088a94..e99a9678720 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -24,6 +24,7 @@ import org.apache.commons.lang3.StringUtils; import org.bouncycastle.util.encoders.Hex; import org.eclipse.jetty.util.StringUtil; +import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.BlockList; import org.tron.api.GrpcAPI.EasyTransferResponse; import org.tron.api.GrpcAPI.TransactionApprovedList; @@ -61,7 +62,7 @@ public class Util { public static final String CONTRACT_TYPE = "contractType"; public static final String EXTRA_DATA = "extra_data"; public static final String PARAMETER = "parameter"; - public static final String ONLY_HEADER = "only_header"; + public static final String TYPE = "type"; public static String printTransactionFee(String transactionFee) { JSONObject jsonObject = new JSONObject(); @@ -311,12 +312,17 @@ public static boolean getVisible(final HttpServletRequest request) { return visible; } - public static boolean getOnlyHeader(final HttpServletRequest request) { - boolean onlyHeader = false; - if (StringUtil.isNotBlank(request.getParameter(ONLY_HEADER))) { - onlyHeader = Boolean.parseBoolean(request.getParameter(ONLY_HEADER)); + public static GrpcAPI.BlockType getBlockType(final HttpServletRequest request) { + int type = 0; + if (StringUtil.isNotBlank(request.getParameter(TYPE))) { + try { + type = Integer.parseInt(request.getParameter(TYPE)); + } catch (Exception e) { + logger.debug("GetType : {}", e.getMessage()); + return GrpcAPI.BlockType.valueOf(request.getParameter(TYPE)); + } } - return onlyHeader; + return GrpcAPI.BlockType.forNumber(type); } public static boolean getVisiblePost(final String input) { @@ -333,20 +339,6 @@ public static boolean getVisiblePost(final String input) { return visible; } - public static boolean getOnlyHeaderPost(final String input) { - boolean onlyHeader = false; - if (StringUtil.isNotBlank(input)) { - JSONObject jsonObject = JSON.parseObject(input); - if (jsonObject.containsKey(ONLY_HEADER)) { - Boolean tmp = jsonObject.getBoolean(ONLY_HEADER); - if (tmp != null) { - onlyHeader = tmp; - } - } - } - return onlyHeader; - } - public static String getContractType(final String input) { String contractType = null; JSONObject jsonObject = JSON.parseObject(input); diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 5118f5d7019..3bc72838cd9 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -1111,16 +1111,21 @@ message Address { int32 port = 2; } +enum BlockType { + ALL = 0; // 0 for all block msg + HEADER = 1; //1 for block header; +} + message EmptyMessage { - bool only_header = 1; + BlockType type = 1; } message NumberMessage { int64 num = 1; - bool only_header = 2; + BlockType type = 2; } message BytesMessage { bytes value = 1; - bool only_header = 2; + BlockType type = 2; } message TimeMessage { int64 beginInMilliseconds = 1; @@ -1129,7 +1134,7 @@ message TimeMessage { message BlockLimit { int64 startNum = 1; int64 endNum = 2; - bool only_header = 3; + BlockType type = 3; } message TransactionLimit { bytes transactionId = 1; From 6fca99ae8e8bbe7cc9feb8245f7de28e2246498c Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Sat, 2 Apr 2022 15:16:10 +0800 Subject: [PATCH 0046/1197] feature(api): Simplify the code. --- .../src/main/java/org/tron/core/Wallet.java | 25 ++++++++----------- .../org/tron/core/services/http/Util.java | 18 +++---------- 2 files changed, 14 insertions(+), 29 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index ea2449b7de6..28ab7bd5bfa 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -3965,27 +3965,22 @@ public Chainbase.Cursor getCursor() { } public Block clearTrxForBlock(Block block, GrpcAPI.BlockType type) { - if (Objects.isNull(block)) { - return null; - } - if (type == GrpcAPI.BlockType.HEADER) { - return block.toBuilder().clearTransactions().build(); + if (Objects.isNull(block) || block.getTransactionsList().isEmpty() + || type == GrpcAPI.BlockType.ALL) { + return block; } - return block; + return block.toBuilder().clearTransactions().build(); } public BlockList clearTrxBlockList(BlockList blockList, GrpcAPI.BlockType type) { - if (Objects.isNull(blockList) || blockList.getBlockList().isEmpty()) { + if (Objects.isNull(blockList) || blockList.getBlockList().isEmpty() + || type == GrpcAPI.BlockType.ALL) { return blockList; } - if (type == GrpcAPI.BlockType.HEADER) { - BlockList.Builder blockListBuilder = BlockList.newBuilder(); - blockList.getBlockList().forEach(block -> blockListBuilder.addBlock(clearTrxForBlock(block, - type))); - return blockListBuilder.build(); - } - return blockList; - + BlockList.Builder blockListBuilder = BlockList.newBuilder(); + blockList.getBlockList().forEach(block -> blockListBuilder.addBlock(clearTrxForBlock(block, + type))); + return blockListBuilder.build(); } } diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index e99a9678720..2290ae7e79a 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -313,16 +313,8 @@ public static boolean getVisible(final HttpServletRequest request) { } public static GrpcAPI.BlockType getBlockType(final HttpServletRequest request) { - int type = 0; - if (StringUtil.isNotBlank(request.getParameter(TYPE))) { - try { - type = Integer.parseInt(request.getParameter(TYPE)); - } catch (Exception e) { - logger.debug("GetType : {}", e.getMessage()); - return GrpcAPI.BlockType.valueOf(request.getParameter(TYPE)); - } - } - return GrpcAPI.BlockType.forNumber(type); + String type = request.getParameter(TYPE); + return GrpcAPI.BlockType.forNumber(StringUtil.isNotBlank(type) ? Integer.parseInt(type) : 0); } public static boolean getVisiblePost(final String input) { @@ -330,12 +322,10 @@ public static boolean getVisiblePost(final String input) { if (StringUtil.isNotBlank(input)) { JSONObject jsonObject = JSON.parseObject(input); if (jsonObject.containsKey(VISIBLE)) { - Boolean tmp = jsonObject.getBoolean(VISIBLE); - if (tmp != null) { - visible = tmp; - } + visible = jsonObject.getBoolean(VISIBLE); } } + return visible; } From 3342c7755251aad039c25846a3344d8eb96db443 Mon Sep 17 00:00:00 2001 From: vikingzzu Date: Tue, 22 Mar 2022 18:42:25 +0800 Subject: [PATCH 0047/1197] feat(net): optimize fetch block process 1. add FetchBlockService to record fetch block 2. calculate the average time to fetch block --- .../common/parameter/CommonParameter.java | 3 + .../src/main/java/org/tron/core/Constant.java | 1 + .../tron/common/overlay/server/SyncPool.java | 15 ++ .../java/org/tron/core/config/args/Args.java | 10 ++ .../org/tron/core/metrics/MetricsKey.java | 1 + .../org/tron/core/net/TronNetService.java | 6 + .../net/messagehandler/BlockMsgHandler.java | 11 ++ .../org/tron/core/net/service/AdvService.java | 4 + .../core/net/service/FetchBlockService.java | 166 ++++++++++++++++++ framework/src/main/resources/config.conf | 2 + 10 files changed, 219 insertions(+) create mode 100644 framework/src/main/java/org/tron/core/net/service/FetchBlockService.java diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index f105eb6402d..9ff7ed89901 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -118,6 +118,9 @@ public class CommonParameter { public int nodeConnectionTimeout; @Getter @Setter + public int fetchBlockTimeout; + @Getter + @Setter public int nodeChannelReadTimeout; @Getter @Setter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index e542a12491e..c950fb76fcf 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -77,6 +77,7 @@ public class Constant { public static final String NODE_DISCOVERY_ENABLE = "node.discovery.enable"; public static final String NODE_DISCOVERY_PERSIST = "node.discovery.persist"; public static final String NODE_CONNECTION_TIMEOUT = "node.connection.timeout"; + public static final String NODE_FETCH_BLOCK_TIMEOUT = "node.fetchBlock.timeout"; public static final String NODE_CHANNEL_READ_TIMEOUT = "node.channel.read.timeout"; public static final String NODE_MAX_ACTIVE_NODES = "node.maxActiveNodes"; public static final String NODE_MAX_ACTIVE_NODES_WITH_SAMEIP = "node.maxActiveNodesWithSameIp"; diff --git a/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java b/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java index 7c8f2b1af52..261b0470ebc 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java +++ b/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java @@ -1,5 +1,6 @@ package org.tron.common.overlay.server; +import com.codahale.metrics.Snapshot; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.collect.Lists; @@ -23,7 +24,10 @@ import org.tron.common.overlay.discover.node.NodeHandler; import org.tron.common.overlay.discover.node.NodeManager; import org.tron.common.parameter.CommonParameter; +import org.tron.core.Constant; import org.tron.core.config.args.Args; +import org.tron.core.metrics.MetricsKey; +import org.tron.core.metrics.MetricsUtil; import org.tron.core.net.peer.PeerConnection; @Slf4j(topic = "net") @@ -133,10 +137,21 @@ synchronized void logActivePeers() { StringBuilder sb = new StringBuilder(str); for (PeerConnection peer : new ArrayList<>(activePeers)) { sb.append(peer.log()).append('\n'); + appendPeerLatencyLog(sb, peer); } logger.info(sb.toString()); } + private void appendPeerLatencyLog(StringBuilder builder, PeerConnection peer) { + Snapshot peerSnapshot = MetricsUtil.getHistogram(MetricsKey.NET_LATENCY_FETCH_BLOCK + + peer.getNode().getHost()).getSnapshot(); + builder.append(String.format( + "top99 : %f, top95 : %f, top75 : %f, max : %d, min : %d, mean : %f, median : %f", + peerSnapshot.get99thPercentile(), peerSnapshot.get95thPercentile(), + peerSnapshot.get75thPercentile(), peerSnapshot.getMax(), peerSnapshot.getMin(), + peerSnapshot.getMean(), peerSnapshot.getMedian())).append("\n"); + } + public List getActivePeers() { List peers = Lists.newArrayList(); for (PeerConnection peer : new ArrayList<>(activePeers)) { diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 7fcad9b75c1..bc9d782991d 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -416,6 +416,16 @@ public static void setParam(final String[] args, final String confFileName) { ? config.getInt(Constant.NODE_CONNECTION_TIMEOUT) * 1000 : 0; + if (!config.hasPath(Constant.NODE_FETCH_BLOCK_TIMEOUT)) { + PARAMETER.fetchBlockTimeout = 200; + } else if (config.getInt(Constant.NODE_FETCH_BLOCK_TIMEOUT) > 1000) { + PARAMETER.fetchBlockTimeout = 1000; + } else if (config.getInt(Constant.NODE_FETCH_BLOCK_TIMEOUT) < 100) { + PARAMETER.fetchBlockTimeout = 100; + } else { + PARAMETER.fetchBlockTimeout = config.getInt(Constant.NODE_FETCH_BLOCK_TIMEOUT); + } + PARAMETER.nodeChannelReadTimeout = config.hasPath(Constant.NODE_CHANNEL_READ_TIMEOUT) ? config.getInt(Constant.NODE_CHANNEL_READ_TIMEOUT) diff --git a/framework/src/main/java/org/tron/core/metrics/MetricsKey.java b/framework/src/main/java/org/tron/core/metrics/MetricsKey.java index c4630994b3f..3ac7b5840d8 100644 --- a/framework/src/main/java/org/tron/core/metrics/MetricsKey.java +++ b/framework/src/main/java/org/tron/core/metrics/MetricsKey.java @@ -23,5 +23,6 @@ public class MetricsKey { public static final String NET_API_DETAIL_QPS = "net.api.detail.qps."; public static final String NET_API_DETAIL_FAIL_QPS = "net.api.detail.failQps."; public static final String NET_API_DETAIL_OUT_TRAFFIC = "net.api.detail.outTraffic."; + public static final String NET_LATENCY_FETCH_BLOCK = "net.latency.fetch.block."; } diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 0244051ccb3..9751675bd85 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -20,6 +20,7 @@ import org.tron.core.net.peer.PeerConnection; import org.tron.core.net.peer.PeerStatusCheck; import org.tron.core.net.service.AdvService; +import org.tron.core.net.service.FetchBlockService; import org.tron.core.net.service.SyncService; import org.tron.protos.Protocol.ReasonCode; @@ -61,12 +62,16 @@ public class TronNetService { @Autowired private PbftDataSyncHandler pbftDataSyncHandler; + @Autowired + private FetchBlockService fetchBlockService; + public void start() { channelManager.init(); advService.init(); syncService.init(); peerStatusCheck.init(); transactionsMsgHandler.init(); + fetchBlockService.init(); logger.info("TronNetService start successfully."); } @@ -76,6 +81,7 @@ public void stop() { syncService.close(); peerStatusCheck.close(); transactionsMsgHandler.close(); + fetchBlockService.close(); logger.info("TronNetService closed successfully."); } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java index c464bec80f1..bc5864b0275 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java @@ -13,12 +13,15 @@ import org.tron.core.config.args.Args; import org.tron.core.exception.P2pException; import org.tron.core.exception.P2pException.TypeEnum; +import org.tron.core.metrics.MetricsKey; +import org.tron.core.metrics.MetricsUtil; import org.tron.core.net.TronNetDelegate; import org.tron.core.net.message.BlockMessage; import org.tron.core.net.message.TronMessage; import org.tron.core.net.peer.Item; import org.tron.core.net.peer.PeerConnection; import org.tron.core.net.service.AdvService; +import org.tron.core.net.service.FetchBlockService; import org.tron.core.net.service.SyncService; import org.tron.core.services.WitnessProductBlockService; import org.tron.protos.Protocol.Inventory.InventoryType; @@ -36,6 +39,9 @@ public class BlockMsgHandler implements TronMsgHandler { @Autowired private SyncService syncService; + @Autowired + private FetchBlockService fetchBlockService; + @Autowired private WitnessProductBlockService witnessProductBlockService; @@ -59,6 +65,11 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep } else { Long time = peer.getAdvInvRequest().remove(new Item(blockId, InventoryType.BLOCK)); long now = System.currentTimeMillis(); + if (null != time) { + MetricsUtil.histogramUpdate(MetricsKey.NET_LATENCY_FETCH_BLOCK + peer.getNode().getHost(), + now - time); + } + fetchBlockService.blockFetchSuccess(blockId); long interval = blockId.getNum() - tronNetDelegate.getHeadBlockId().getNum(); processBlock(peer, blockMessage.getBlockCapsule()); logger.info( diff --git a/framework/src/main/java/org/tron/core/net/service/AdvService.java b/framework/src/main/java/org/tron/core/net/service/AdvService.java index 8eda4513dad..c982cf8085d 100644 --- a/framework/src/main/java/org/tron/core/net/service/AdvService.java +++ b/framework/src/main/java/org/tron/core/net/service/AdvService.java @@ -50,6 +50,9 @@ public class AdvService { @Autowired private TronNetDelegate tronNetDelegate; + @Autowired + private FetchBlockService fetchBlockService; + private ConcurrentHashMap invToFetch = new ConcurrentHashMap<>(); private ConcurrentHashMap invToSpread = new ConcurrentHashMap<>(); @@ -364,6 +367,7 @@ void sendFetch() { if (key.equals(InventoryType.BLOCK)) { value.sort(Comparator.comparingLong(value1 -> new BlockId(value1).getNum())); peer.fastSend(new FetchInvDataMessage(value, key)); + fetchBlockService.fetchBlock(value, peer); } else { peer.sendMessage(new FetchInvDataMessage(value, key)); } diff --git a/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java b/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java new file mode 100644 index 00000000000..1b517f6bb09 --- /dev/null +++ b/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java @@ -0,0 +1,166 @@ +package org.tron.core.net.service; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.concurrent.BasicThreadFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.ChainBaseManager; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.config.Parameter; +import org.tron.core.metrics.MetricsKey; +import org.tron.core.metrics.MetricsUtil; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.message.FetchInvDataMessage; +import org.tron.core.net.peer.Item; +import org.tron.core.net.peer.PeerConnection; +import org.tron.protos.Protocol.Inventory.InventoryType; + +/** + * @author kiven.miao + * @date 2022/3/17 3:50 下午 + */ +@Slf4j(topic = "net") +@Component +public class FetchBlockService { + + @Autowired + private TronNetDelegate tronNetDelegate; + + @Autowired + private ChainBaseManager chainBaseManager; + + private FetchBlockInfo fetchBlockInfo = null; + + private final long fetchTimeOut = CommonParameter.getInstance().fetchBlockTimeout; + + private static final int BLOCK_FETCH_TIME_OUT_LIMIT = + 2 * Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; + + private static final double BLOCK_FETCH_LEFT_TIME_PERCENT = 0.5; + + private final ScheduledExecutorService fetchBlockWorkerExecutor = + new ScheduledThreadPoolExecutor(1, + new BasicThreadFactory.Builder().namingPattern("FetchBlockWorkerSchedule-").build()); + + public void init() { + fetchBlockWorkerExecutor.scheduleWithFixedDelay(() -> { + try { + fetchBlockProcess(fetchBlockInfo); + } catch (Exception exception) { + logger.error("FetchBlockWorkerSchedule thread error. {}", exception.getMessage()); + } + }, 0L, 50L, TimeUnit.MILLISECONDS); + } + + public void close() { + fetchBlockWorkerExecutor.shutdown(); + } + + public void fetchBlock(List sha256HashList, PeerConnection peer) { + if (null != fetchBlockInfo) { + return; + } + sha256HashList.stream().filter(sha256Hash -> new BlockCapsule.BlockId(sha256Hash).getNum() + == chainBaseManager.getHeadBlockNum() + 1) + .findFirst().ifPresent(sha256Hash -> { + if (System.currentTimeMillis() - chainBaseManager.getHeadBlockTimeStamp() + < BLOCK_FETCH_TIME_OUT_LIMIT) { + fetchBlockInfo = new FetchBlockInfo(sha256Hash, peer, System.currentTimeMillis()); + } + }); + } + + + public void blockFetchSuccess(Sha256Hash sha256Hash) { + if (null == fetchBlockInfo || !fetchBlockInfo.getHash().equals(sha256Hash)) { + return; + } + fetchBlockInfo = null; + } + + private void fetchBlockProcess(FetchBlockInfo fetchBlock) { + if (null == fetchBlock) { + return; + } + if (System.currentTimeMillis() - chainBaseManager.getHeadBlockTimeStamp() + >= BLOCK_FETCH_TIME_OUT_LIMIT) { + this.fetchBlockInfo = null; + return; + } + Item item = new Item(fetchBlock.getHash(), InventoryType.BLOCK); + Optional optionalPeerConnection = tronNetDelegate.getActivePeer().stream() + .filter(PeerConnection::isIdle) + .filter(filterPeer -> !filterPeer.equals(fetchBlock.getPeer())) + .filter(filterPeer -> filterPeer.getAdvInvReceive().getIfPresent(item) != null) + .filter(filterPeer -> getPeerTop75(filterPeer) + <= CommonParameter.getInstance().fetchBlockTimeout) + .min(Comparator.comparingDouble(this::getPeerTop75)); + + if (optionalPeerConnection.isPresent()) { + optionalPeerConnection.ifPresent(firstPeer -> { + if (shouldFetchBlock(firstPeer, fetchBlock)) { + firstPeer.fastSend(new FetchInvDataMessage(Collections.singletonList(item.getHash()), + item.getType())); + this.fetchBlockInfo = null; + } + }); + } else { + if (System.currentTimeMillis() - fetchBlock.getTime() >= fetchTimeOut) { + this.fetchBlockInfo = null; + } + } + } + + private boolean shouldFetchBlock(PeerConnection newPeer, FetchBlockInfo fetchBlock) { + double newPeerTop75 = getPeerTop75(newPeer); + double oldPeerTop75 = getPeerTop75(fetchBlock.getPeer()); + long oldPeerSpendTime = System.currentTimeMillis() - fetchBlock.getTime(); + if (oldPeerTop75 > fetchTimeOut || oldPeerSpendTime >= fetchTimeOut) { + return true; + } + + double oldPeerLeftTime = oldPeerTop75 - oldPeerSpendTime; + return newPeerTop75 < oldPeerLeftTime * BLOCK_FETCH_LEFT_TIME_PERCENT + && oldPeerSpendTime + newPeerTop75 < fetchTimeOut; + } + + private double getPeerTop75(PeerConnection peerConnection) { + return MetricsUtil.getHistogram(MetricsKey.NET_LATENCY_FETCH_BLOCK + + peerConnection.getNode().getHost()).getSnapshot().get75thPercentile(); + } + + private static class FetchBlockInfo { + + @Getter + @Setter + private PeerConnection peer; + + @Getter + @Setter + private Sha256Hash hash; + + @Getter + @Setter + private long time; + + public FetchBlockInfo(Sha256Hash hash, PeerConnection peer, long time) { + this.peer = peer; + this.hash = hash; + this.time = time; + } + + } + +} \ No newline at end of file diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 46dcb2e375e..b9bd3b21ee1 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -116,6 +116,8 @@ node { connection.timeout = 2 + fetchBlock.timeout = 200 + tcpNettyWorkThreadNum = 0 udpNettyWorkThreadNum = 1 From 5c1e67fd54675167e1071b137bca7d760dae4b25 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 8 Apr 2022 15:10:52 +0800 Subject: [PATCH 0048/1197] feature(api): change clearTrxForBlock and clearTrxBlockList judgment logic. --- framework/src/main/java/org/tron/core/Wallet.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 28ab7bd5bfa..0dcaf98e322 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -3966,7 +3966,7 @@ public Chainbase.Cursor getCursor() { public Block clearTrxForBlock(Block block, GrpcAPI.BlockType type) { if (Objects.isNull(block) || block.getTransactionsList().isEmpty() - || type == GrpcAPI.BlockType.ALL) { + || type != GrpcAPI.BlockType.HEADER) { return block; } return block.toBuilder().clearTransactions().build(); @@ -3974,7 +3974,7 @@ public Block clearTrxForBlock(Block block, GrpcAPI.BlockType type) { public BlockList clearTrxBlockList(BlockList blockList, GrpcAPI.BlockType type) { if (Objects.isNull(blockList) || blockList.getBlockList().isEmpty() - || type == GrpcAPI.BlockType.ALL) { + || type != GrpcAPI.BlockType.HEADER) { return blockList; } BlockList.Builder blockListBuilder = BlockList.newBuilder(); From 4b0ab06721f9f340a55b3b8950905a1d99c9de6e Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 11 Apr 2022 15:36:48 +0800 Subject: [PATCH 0049/1197] perf(net): remove redundant logic for obtaining ordered witnesses --- .../tron/core/net/service/RelayService.java | 42 +++---------- .../core/net/services/RelayServiceTest.java | 61 ++++++++----------- 2 files changed, 35 insertions(+), 68 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/RelayService.java b/framework/src/main/java/org/tron/core/net/service/RelayService.java index 17515dd4bd3..b4abfc835ea 100644 --- a/framework/src/main/java/org/tron/core/net/service/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/RelayService.java @@ -1,15 +1,14 @@ package org.tron.core.net.service; import com.google.protobuf.ByteString; -import java.util.ArrayList; -import java.util.Comparator; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.core.ChainBaseManager; -import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.args.Args; import org.tron.core.net.TronNetDelegate; import org.tron.core.net.message.BlockMessage; @@ -29,42 +28,21 @@ public class RelayService { private int maxFastForwardNum = Args.getInstance().getMaxFastForwardNum(); - private volatile long nextMaintenanceTime = -1; - private volatile List witnesses; - - private List getSortedScheduleWitness() { - long time = chainBaseManager.getDynamicPropertiesStore().getNextMaintenanceTime(); - if (time <= nextMaintenanceTime) { - nextMaintenanceTime = time; - return witnesses; - } - List l1 = new ArrayList<>(); - chainBaseManager.getWitnessScheduleStore().getActiveWitnesses().forEach(s -> { - l1.add(chainBaseManager.getWitnessStore().get(s.toByteArray())); - }); - l1.sort(Comparator.comparingLong(w -> -w.getVoteCount())); - List l2 = new ArrayList<>(); - l1.forEach(w -> l2.add(w.getAddress())); - nextMaintenanceTime = time; - witnesses = l2; - return witnesses; - } - - private List getNextWitnesses(ByteString key, Integer count) { - List l1 = getSortedScheduleWitness(); - int index = l1.indexOf(key); + private Set getNextWitnesses(ByteString key, Integer count) { + List list = chainBaseManager.getWitnessScheduleStore().getActiveWitnesses(); + int index = list.indexOf(key); if (index < 0) { - return l1; + return new HashSet<>(list); } - List l2 = new ArrayList<>(); + Set set = new HashSet<>(); for (; count > 0; count--) { - l2.add(l1.get(++index % l1.size())); + set.add(list.get(++index % list.size())); } - return l2; + return set; } public void broadcast(BlockMessage msg) { - List witnesses = getNextWitnesses( + Set witnesses = getNextWitnesses( msg.getBlockCapsule().getWitnessAddress(), maxFastForwardNum); Item item = new Item(msg.getBlockId(), Protocol.Inventory.InventoryType.BLOCK); List peers = tronNetDelegate.getActivePeer().stream() diff --git a/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java b/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java index cf4178695a7..69dffe7ab29 100644 --- a/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java @@ -6,7 +6,9 @@ import java.io.File; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; +import java.util.Set; import org.bouncycastle.util.encoders.Hex; import org.junit.After; @@ -50,9 +52,6 @@ public void init() { chainBaseManager = context.getBean(ChainBaseManager.class); } - /** - * destroy. - */ @After public void destroy() { Args.clearParam(); @@ -62,56 +61,45 @@ public void destroy() { @Test public void test() throws Exception { - testGetSortedScheduleWitness(); + initWitness(); testGetNextWitnesses(); testBroadcast(); } - private void testGetSortedScheduleWitness() throws Exception { - Method method = service.getClass().getDeclaredMethod("getSortedScheduleWitness"); - method.setAccessible(true); + private void initWitness() { + byte[] key = Hex.decode("A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F"); + WitnessCapsule witnessCapsule = chainBaseManager.getWitnessStore().get(key); + witnessCapsule.setVoteCount(1000); + chainBaseManager.getWitnessStore().put(key, witnessCapsule); List list = new ArrayList<>(); List witnesses = chainBaseManager.getWitnessStore().getAllWitnesses(); + witnesses.sort(Comparator.comparingLong(w -> -w.getVoteCount())); witnesses.forEach(witness -> list.add(witness.getAddress())); chainBaseManager.getWitnessScheduleStore().saveActiveWitnesses(list); - chainBaseManager.getDynamicPropertiesStore().saveNextMaintenanceTime(10); - List l1 = (List) method.invoke(service); - Assert.assertEquals(11, l1.size()); - assertEquals(l1.get(0), "A0299F3DB80A24B20A254B89CE639D59132F157F13"); - assertEquals(l1.get(10), "A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F"); - - byte[] key = Hex.decode("A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F"); - WitnessCapsule witness = chainBaseManager.getWitnessStore().get(key); - witness.setVoteCount(1000); - chainBaseManager.getWitnessStore().put(key, witness); - chainBaseManager.getDynamicPropertiesStore().saveNextMaintenanceTime(20); - List l2 = (List) method.invoke(service); - assertEquals(l2.get(0), "A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F"); - assertEquals(l2.get(1), "A0299F3DB80A24B20A254B89CE639D59132F157F13"); } public void testGetNextWitnesses() throws Exception { Method method = service.getClass().getDeclaredMethod( "getNextWitnesses", ByteString.class, Integer.class); method.setAccessible(true); - List l1 = (List) method.invoke( + Set s1 = (Set) method.invoke( service, getFromHexString("A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F"), 3); - Assert.assertEquals(l1.size(), 3); - assertEquals(l1.get(0), "A0299F3DB80A24B20A254B89CE639D59132F157F13"); - assertEquals(l1.get(1), "A0807337F180B62A77576377C1D0C9C24DF5C0DD62"); - assertEquals(l1.get(2), "A05430A3F089154E9E182DDD6FE136A62321AF22A7"); + Assert.assertEquals(s1.size(), 3); + assertContains(s1, "A0299F3DB80A24B20A254B89CE639D59132F157F13"); + assertContains(s1, "A0807337F180B62A77576377C1D0C9C24DF5C0DD62"); + assertContains(s1, "A05430A3F089154E9E182DDD6FE136A62321AF22A7"); - List l2 = (List) method.invoke( + Set s2 = (Set) method.invoke( service, getFromHexString("A0FAB5FBF6AFB681E4E37E9D33BDDB7E923D6132E5"), 3); - Assert.assertEquals(l2.size(), 3); - assertEquals(l2.get(0), "A014EEBE4D30A6ACB505C8B00B218BDC4733433C68"); - assertEquals(l2.get(1), "A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F"); - assertEquals(l2.get(2), "A0299F3DB80A24B20A254B89CE639D59132F157F13"); + Assert.assertEquals(s2.size(), 3); + assertContains(s2, "A014EEBE4D30A6ACB505C8B00B218BDC4733433C68"); + assertContains(s2, "A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F"); + assertContains(s2, "A0299F3DB80A24B20A254B89CE639D59132F157F13"); - List l3 = (List) method.invoke( + Set s3 = (Set) method.invoke( service, getFromHexString("A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F"), 1); - Assert.assertEquals(l3.size(), 1); - assertEquals(l3.get(0), "A0299F3DB80A24B20A254B89CE639D59132F157F13"); + Assert.assertEquals(s3.size(), 1); + assertContains(s3, "A0299F3DB80A24B20A254B89CE639D59132F157F13"); } private void testBroadcast() { @@ -140,8 +128,9 @@ private void testBroadcast() { } } - private void assertEquals(ByteString byteString, String string) { - Assert.assertEquals(byteString, ByteString.copyFrom(Hex.decode(string))); + private void assertContains(Set set, String string) { + ByteString bytes = getFromHexString(string); + Assert.assertTrue(set.contains(bytes)); } private ByteString getFromHexString(String s) { From ca6d3a0b067c633f86914f62a6e0f757e418aff3 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Tue, 26 Apr 2022 18:10:15 +0800 Subject: [PATCH 0050/1197] fix: do not print unknown fields --- .../org/tron/core/services/http/JsonFormat.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/http/JsonFormat.java b/framework/src/main/java/org/tron/core/services/http/JsonFormat.java index c71d8e165e1..d74a6c8f291 100644 --- a/framework/src/main/java/org/tron/core/services/http/JsonFormat.java +++ b/framework/src/main/java/org/tron/core/services/http/JsonFormat.java @@ -147,10 +147,12 @@ protected static void print(Message message, JsonGenerator generator, boolean se generator.print(","); } } - if (message.getUnknownFields().asMap().size() > 0) { - generator.print(", "); - } - printUnknownFields(message.getUnknownFields(), generator, selfType); + + // do not print unknown fields + // if (message.getUnknownFields().asMap().size() > 0) { + // generator.print(", "); + // } + // printUnknownFields(message.getUnknownFields(), generator, selfType); } /** @@ -421,7 +423,9 @@ protected static void printUnknownFields(UnknownFieldSet unknownFields, JsonGene } else { generator.print(", "); } + generator.print("\""); generator.print(String.format((Locale) null, "0x%08x", value)); + generator.print("\""); } for (long value : field.getFixed64List()) { if (firstValue) { @@ -429,7 +433,9 @@ protected static void printUnknownFields(UnknownFieldSet unknownFields, JsonGene } else { generator.print(", "); } + generator.print("\""); generator.print(String.format((Locale) null, "0x%016x", value)); + generator.print("\""); } for (ByteString value : field.getLengthDelimitedList()) { if (firstValue) { From 7727aaced6820ba6ff032755e9112514112182ea Mon Sep 17 00:00:00 2001 From: vikingzzu Date: Thu, 14 Apr 2022 11:14:55 +0800 Subject: [PATCH 0051/1197] feat(net): optimize fetch block process 1. add FetchBlockService to record fetch block 2. calculate the average time to fetch block --- .../java/org/tron/core/net/service/FetchBlockService.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java b/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java index 1b517f6bb09..cfad7242471 100644 --- a/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java +++ b/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java @@ -84,10 +84,11 @@ public void fetchBlock(List sha256HashList, PeerConnection peer) { public void blockFetchSuccess(Sha256Hash sha256Hash) { - if (null == fetchBlockInfo || !fetchBlockInfo.getHash().equals(sha256Hash)) { + FetchBlockInfo fetchBlockInfoTemp = this.fetchBlockInfo; + if (null == fetchBlockInfoTemp || !fetchBlockInfoTemp.getHash().equals(sha256Hash)) { return; } - fetchBlockInfo = null; + this.fetchBlockInfo = null; } private void fetchBlockProcess(FetchBlockInfo fetchBlock) { @@ -111,6 +112,7 @@ private void fetchBlockProcess(FetchBlockInfo fetchBlock) { if (optionalPeerConnection.isPresent()) { optionalPeerConnection.ifPresent(firstPeer -> { if (shouldFetchBlock(firstPeer, fetchBlock)) { + firstPeer.getAdvInvRequest().put(item, System.currentTimeMillis()); firstPeer.fastSend(new FetchInvDataMessage(Collections.singletonList(item.getHash()), item.getType())); this.fetchBlockInfo = null; From a75e12aeb09b5bd7aa534b11611985a6f497a51e Mon Sep 17 00:00:00 2001 From: liukai Date: Tue, 26 Apr 2022 22:37:17 +0800 Subject: [PATCH 0052/1197] feat: update version 1. update version to 4.4.5 --- framework/src/main/java/org/tron/program/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 325a56bc3bb..66411053e36 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -4,7 +4,7 @@ public class Version { public static final String VERSION_NAME = "GreatVoyage-v4.4.2-94-g38dfe231c"; public static final String VERSION_CODE = "16676"; - private static final String VERSION = "4.4.4"; + private static final String VERSION = "4.4.5"; public static String getVersion() { return VERSION; From 045b7d0d9611be7c8a9c9a19a5dbe380e73e494b Mon Sep 17 00:00:00 2001 From: lvs007 Date: Tue, 26 Apr 2022 23:54:35 +0800 Subject: [PATCH 0053/1197] update a new version. version name:GreatVoyage-v4.4.4-3-g5f6660e30,version code:16681 --- framework/src/main/java/org/tron/program/Version.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 66411053e36..0f118134d97 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,8 +2,8 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.4.2-94-g38dfe231c"; - public static final String VERSION_CODE = "16676"; + public static final String VERSION_NAME = "GreatVoyage-v4.4.4-3-g5f6660e30"; + public static final String VERSION_CODE = "16681"; private static final String VERSION = "4.4.5"; public static String getVersion() { From 4120596b52d01ddb55bc96a0d703437605a4884d Mon Sep 17 00:00:00 2001 From: vikingzzu Date: Wed, 27 Apr 2022 11:59:58 +0800 Subject: [PATCH 0054/1197] fix sonar check style --- .../src/main/java/org/tron/common/overlay/server/SyncPool.java | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java b/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java index 0e537456e4a..09ce1496319 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java +++ b/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java @@ -24,7 +24,6 @@ import org.tron.common.overlay.discover.node.NodeHandler; import org.tron.common.overlay.discover.node.NodeManager; import org.tron.common.parameter.CommonParameter; -import org.tron.core.Constant; import org.tron.core.ChainBaseManager; import org.tron.core.config.args.Args; import org.tron.core.metrics.MetricsKey; From 7147fad4ed11b0e19a7ea5218a54432901ff6950 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 27 Apr 2022 17:11:01 +0800 Subject: [PATCH 0055/1197] fix(api): getnowblock post and getVisible method. --- .../core/services/http/GetNowBlockServlet.java | 4 +++- .../java/org/tron/core/services/http/Util.java | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java b/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java index 5f4528c7b0d..87a3fbb98a3 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.google.common.base.Strings; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -30,7 +31,8 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) try { PostParams params = PostParams.getPostParams(request); GrpcAPI.EmptyMessage.Builder build = GrpcAPI.EmptyMessage.newBuilder(); - JsonFormat.merge(params.getParams(), build, params.isVisible()); + JsonFormat.merge(Strings.isNullOrEmpty(params.getParams()) ? "{}" : params.getParams(), + build, params.isVisible()); fillResponse(params.isVisible(), build.getType(), response); } catch (Exception e) { Util.processError(e, response); diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 2290ae7e79a..d59ae7062a6 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -306,8 +306,20 @@ public static void checkBodySize(String body) throws Exception { public static boolean getVisible(final HttpServletRequest request) { boolean visible = false; - if (StringUtil.isNotBlank(request.getParameter(VISIBLE))) { - visible = Boolean.valueOf(request.getParameter(VISIBLE)); + String v = request.getParameter(VISIBLE); + if (StringUtil.isBlank(v)) { + try { + String input = request.getReader().lines() + .collect(Collectors.joining(System.lineSeparator())); + Util.checkBodySize(input); + if (StringUtil.isNotBlank(input)) { + visible = getVisiblePost(input); + } + } catch (Exception e) { + logger.debug("GetVisibleError: {}", e.getMessage()); + } + } else { + visible = Boolean.parseBoolean(v); } return visible; } From 14fa95f4bef8de05bd1a234ca79a0004ccde15e7 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 28 Apr 2022 12:32:17 +0800 Subject: [PATCH 0056/1197] fix(liteTool): remove recent-transaction from minimumDbsForLiteNode --- .../main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java index 925be49ef31..f7e8fb9f9c7 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java @@ -22,7 +22,6 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.rocksdb.RocksDBException; -import org.tron.common.overlay.server.HandshakeHandler; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; @@ -84,7 +83,7 @@ public class LiteFullNodeTool { "properties", "proposal", "recent-block", - "recent-transaction", + //"recent-transaction", "storage-row", //TRANS_CACHE_DB_NAME, //"tree-block-index", From 2c183e2f046459329b6c868fb9a005f65990ccb0 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 28 Apr 2022 17:55:59 +0800 Subject: [PATCH 0057/1197] fix(liteTool): set lite db node type to 1 --- .../java/org/tron/tool/litefullnode/LiteFullNodeTool.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java index f7e8fb9f9c7..82bc50ad3da 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java @@ -307,9 +307,9 @@ private void fillSnapshotBlockDb(String sourceDir, String snapshotDir) destBlockDb.put(blockId, block); }); - DBInterface commonDb = DbTool.getDB(sourceDir, COMMON_DB_NAME); - commonDb.put(DB_KEY_NODE_TYPE, ByteArray.fromInt(Constant.NODE_TYPE_LIGHT_NODE)); - commonDb.put(DB_KEY_LOWEST_BLOCK_NUM, ByteArray.fromLong(startIndex)); + DBInterface destCommonDb = DbTool.getDB(snapshotDir, COMMON_DB_NAME); + destCommonDb.put(DB_KEY_NODE_TYPE, ByteArray.fromInt(Constant.NODE_TYPE_LIGHT_NODE)); + destCommonDb.put(DB_KEY_LOWEST_BLOCK_NUM, ByteArray.fromLong(startIndex)); } private void checkTranCacheStore(String sourceDir, String snapshotDir) From c818441f64f13947d5a2f77b48ac12a0afca13c0 Mon Sep 17 00:00:00 2001 From: liukai Date: Fri, 29 Apr 2022 12:23:32 +0800 Subject: [PATCH 0058/1197] feat: optimize thread 1. set `rePushThread` as a daemon thread 2. set `triggerCapsuleProcessThread` as a daemon thread --- framework/src/main/java/org/tron/core/db/Manager.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 0b46382e9ef..9919d99c428 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -480,11 +480,13 @@ public void init() { validateSignService = Executors .newFixedThreadPool(Args.getInstance().getValidateSignThreadNum()); Thread rePushThread = new Thread(rePushLoop); + rePushThread.setDaemon(true); rePushThread.start(); // add contract event listener for subscribing if (Args.getInstance().isEventSubscribe()) { startEventSubscribing(); Thread triggerCapsuleProcessThread = new Thread(triggerCapsuleProcessLoop); + triggerCapsuleProcessThread.setDaemon(true); triggerCapsuleProcessThread.start(); } From d85fa331087cd1302eba813dc42875d452be8257 Mon Sep 17 00:00:00 2001 From: liukai Date: Sat, 7 May 2022 11:29:16 +0800 Subject: [PATCH 0059/1197] feat: optimize log out 1. modify the error level log for non-system exception output --- .../java/org/tron/common/overlay/server/MessageQueue.java | 4 ++-- .../common/overlay/server/PeerConnectionCheckService.java | 4 ++-- .../overlay/server/TrxProtobufVarint32FrameDecoder.java | 2 +- framework/src/main/java/org/tron/core/net/TronNetService.java | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java index 8449817066f..c9b3ac750a8 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java +++ b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java @@ -68,7 +68,7 @@ public void activate(ChannelHandlerContext ctx) { Message msg = msgQueue.take(); ctx.writeAndFlush(msg.getSendData()).addListener((ChannelFutureListener) future -> { if (!future.isSuccess() && !channel.isDisconnect()) { - logger.error("Failed to send to {}, {}", ctx.channel().remoteAddress(), msg); + logger.warn("Failed to send to {}, {}", ctx.channel().remoteAddress(), msg); } }); } catch (InterruptedException e) { @@ -189,7 +189,7 @@ private void send() { ctx.writeAndFlush(msg.getSendData()).addListener((ChannelFutureListener) future -> { if (!future.isSuccess()) { - logger.error("Fail send to {}, {}", ctx.channel().remoteAddress(), msg); + logger.warn("Fail send to {}, {}", ctx.channel().remoteAddress(), msg); } }); diff --git a/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java b/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java index 2a31788dc96..a02825e31e0 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java +++ b/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java @@ -77,7 +77,7 @@ public void run() { > Args.getInstance().getNodeMaxActiveNodes() * maxConnectNumberFactor) { Collections.shuffle(willDisconnectPeerList); for (int i = 0; i < willDisconnectPeerList.size() * disconnectNumberFactor; i++) { - logger.error("{} does not have data transfer, disconnect the peer", + logger.warn("{} does not have data transfer, disconnect the peer", willDisconnectPeerList.get(i).getInetAddress()); willDisconnectPeerList.get(i).disconnect(ReasonCode.TOO_MANY_PEERS); } @@ -111,4 +111,4 @@ public void run() { } } -} \ No newline at end of file +} diff --git a/framework/src/main/java/org/tron/common/overlay/server/TrxProtobufVarint32FrameDecoder.java b/framework/src/main/java/org/tron/common/overlay/server/TrxProtobufVarint32FrameDecoder.java index 614937b6764..8be89a178fe 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/TrxProtobufVarint32FrameDecoder.java +++ b/framework/src/main/java/org/tron/common/overlay/server/TrxProtobufVarint32FrameDecoder.java @@ -76,7 +76,7 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) t int preIndex = in.readerIndex(); int length = readRawVarint32(in); if (length >= maxMsgLength) { - logger.error("recv a big msg, host : {}, msg length is : {}", ctx.channel().remoteAddress(), + logger.warn("recv a big msg, host : {}, msg length is : {}", ctx.channel().remoteAddress(), length); in.clear(); channel.close(); diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 250a9a444b0..a80b6d498d4 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -153,7 +153,7 @@ private void processException(PeerConnection peer, TronMessage msg, Exception ex code = ReasonCode.UNKNOWN; break; } - logger.error("Message from {} process failed, {} \n type: {}, detail: {}.", + logger.warn("Message from {} process failed, {} \n type: {}, detail: {}.", peer.getInetAddress(), msg, type, ex.getMessage()); } else { code = ReasonCode.UNKNOWN; From ca5fd6e33c2d732d649024fdb4af8dc95f1dccc7 Mon Sep 17 00:00:00 2001 From: liukai Date: Sat, 7 May 2022 15:24:40 +0800 Subject: [PATCH 0060/1197] feat: optimize connection handshake message 1. add genesisBlockByte length validation --- .../org/tron/common/overlay/message/HelloMessage.java | 5 ++++- .../org/tron/common/overlay/server/HandshakeHandler.java | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java b/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java index 3609cc0949a..75f5b1fe87a 100755 --- a/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java +++ b/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java @@ -126,4 +126,7 @@ public String toString() { return new StringBuilder().append(super.toString()).append(helloMessage.toString()).toString(); } -} \ No newline at end of file + public Protocol.HelloMessage getInstance() { + return this.helloMessage; + } +} diff --git a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java index ff33175425e..0cf55c59766 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java @@ -162,6 +162,15 @@ private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { return; } + byte[] genesisBlockByte = msg.getInstance().getGenesisBlockId().getHash().toByteArray(); + + if (genesisBlockByte.length == 0) { + logger.info("Peer {} different genesis block, peer genesis block byte length is 0", + ctx.channel().remoteAddress()); + channel.disconnect(ReasonCode.INCOMPATIBLE_CHAIN); + return; + } + if (!Arrays .equals(chainBaseManager.getGenesisBlockId().getBytes(), msg.getGenesisBlockId().getBytes())) { From c7b4d92926af7762bd688edfdf83a609e17f67aa Mon Sep 17 00:00:00 2001 From: vikingzzu Date: Mon, 9 May 2022 15:25:32 +0800 Subject: [PATCH 0061/1197] feat(net): optimize fetch block process 1. add FetchBlockService to record fetch block 2. calculate the average time to fetch block --- .../org/tron/common/overlay/server/SyncPool.java | 3 ++- .../java/org/tron/core/metrics/MetricsUtil.java | 14 ++++++++++++++ .../core/net/messagehandler/BlockMsgHandler.java | 4 ++-- framework/src/main/resources/config-test-net.conf | 2 ++ 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java b/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java index 09ce1496319..7db1d32e5ff 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java +++ b/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java @@ -140,8 +140,9 @@ synchronized void logActivePeers() { channelManager.getActivePeers().size(), activePeersCount.get(), passivePeersCount.get()); StringBuilder sb = new StringBuilder(str); for (PeerConnection peer : new ArrayList<>(activePeers)) { - sb.append(peer.log()).append('\n'); + sb.append(peer.log()); appendPeerLatencyLog(sb, peer); + sb.append("\n"); } logger.info(sb.toString()); } diff --git a/framework/src/main/java/org/tron/core/metrics/MetricsUtil.java b/framework/src/main/java/org/tron/core/metrics/MetricsUtil.java index 6a40cf2d269..51a0182eed8 100644 --- a/framework/src/main/java/org/tron/core/metrics/MetricsUtil.java +++ b/framework/src/main/java/org/tron/core/metrics/MetricsUtil.java @@ -66,6 +66,20 @@ public static void histogramUpdate(String key, long value) { } } + /** + * Histogram update uncheck. + * + * @param key String + * @param value long + */ + public static void histogramUpdateUnCheck(String key, long value) { + try { + metricRegistry.histogram(key).update(value); + } catch (Exception e) { + logger.warn("update histogram uncheck failed, key:{}, value:{}", key, value); + } + } + public static Meter getMeter(String name) { return metricRegistry.meter(name); } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java index 902015031aa..13b72f32b07 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java @@ -70,8 +70,8 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep Long time = peer.getAdvInvRequest().remove(new Item(blockId, InventoryType.BLOCK)); long now = System.currentTimeMillis(); if (null != time) { - MetricsUtil.histogramUpdate(MetricsKey.NET_LATENCY_FETCH_BLOCK + peer.getNode().getHost(), - now - time); + MetricsUtil.histogramUpdateUnCheck(MetricsKey.NET_LATENCY_FETCH_BLOCK + + peer.getNode().getHost(), now - time); } fetchBlockService.blockFetchSuccess(blockId); long interval = blockId.getNum() - tronNetDelegate.getHeadBlockId().getNum(); diff --git a/framework/src/main/resources/config-test-net.conf b/framework/src/main/resources/config-test-net.conf index 07b77dbe6ca..21dbb91ce41 100644 --- a/framework/src/main/resources/config-test-net.conf +++ b/framework/src/main/resources/config-test-net.conf @@ -76,6 +76,8 @@ node { connection.timeout = 2 + fetchBlock.timeout = 200 + tcpNettyWorkThreadNum = 0 udpNettyWorkThreadNum = 1 From 1876c94991c6c8389b547137f3d7ee33c7fc6a3b Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 12 May 2022 16:59:51 +0800 Subject: [PATCH 0062/1197] feat(metrics): prometheus https://github.com/tronprotocol/tips/issues/369 1. tron metric 2. jvm metric 3. log metric --- .../leveldb/LevelDbDataSourceImpl.java | 37 +++- .../tron/common/storage/metric/DbStat.java | 34 ++++ .../common/storage/metric/DbStatService.java | 42 ++++ .../rocksdb/RocksDbDataSourceImpl.java | 40 +++- .../java/org/tron/core/ChainBaseManager.java | 5 + .../java/org/tron/core/db/TronDatabase.java | 11 + .../tron/core/db/TronStoreWithRevoking.java | 35 ++-- .../tron/core/db/common/DbSourceInter.java | 2 + .../core/db2/common/ConcurrentHashDB.java | 5 + .../java/org/tron/core/db2/common/DB.java | 2 + .../java/org/tron/core/db2/common/HashDB.java | 6 +- .../org/tron/core/db2/common/LevelDB.java | 5 + .../org/tron/core/db2/common/RocksDB.java | 5 + .../org/tron/core/db2/common/TxCacheDB.java | 5 + common/build.gradle | 6 + .../common/parameter/CommonParameter.java | 8 + .../prometheus/InstrumentedAppender.java | 32 +++ .../tron/common/prometheus/MetricAspect.java | 55 +++++ .../tron/common/prometheus/MetricKeys.java | 67 +++++++ .../tron/common/prometheus/MetricLabels.java | 78 ++++++++ .../tron/common/prometheus/MetricTime.java | 13 ++ .../org/tron/common/prometheus/Metrics.java | 68 +++++++ .../common/prometheus/MetricsCounter.java | 46 +++++ .../tron/common/prometheus/MetricsGauge.java | 59 ++++++ .../common/prometheus/MetricsHistogram.java | 89 +++++++++ .../prometheus/OperatingSystemExports.java | 131 ++++++++++++ .../src/main/java/org/tron/core/Constant.java | 2 + .../exception/DupTransactionException.java | 10 + .../org/tron/core/exception/P2pException.java | 12 ++ .../tron/core/exception/TaposException.java | 11 +- .../exception/TooBigTransactionException.java | 10 + .../TransactionExpirationException.java | 10 + .../tron/core/exception/TronException.java | 7 + .../exception/ValidateSignatureException.java | 9 + .../tron/consensus/dpos/StatisticManager.java | 14 +- framework/build.gradle | 3 - .../overlay/discover/node/NodeHandler.java | 4 + .../overlay/discover/node/NodeManager.java | 16 +- .../common/overlay/message/MessageCodec.java | 5 + .../common/overlay/server/ChannelManager.java | 5 + .../overlay/server/HandshakeHandler.java | 10 +- .../common/overlay/server/MessageQueue.java | 9 +- .../tron/common/overlay/server/SyncPool.java | 15 ++ .../java/org/tron/core/config/args/Args.java | 6 + .../main/java/org/tron/core/db/Manager.java | 103 ++++++++-- .../java/org/tron/core/db/PendingManager.java | 30 ++- .../storetrie/AccountStateStoreTrie.java | 6 + .../blockchain/BlockChainMetricManager.java | 13 +- .../org/tron/core/net/TronNetDelegate.java | 9 + .../tron/core/services/NodeInfoService.java | 2 + .../services/filter/CharResponseWrapper.java | 2 +- .../services/http/RateLimiterServlet.java | 14 ++ .../ratelimiter/RpcApiAccessInterceptor.java | 9 +- .../main/java/org/tron/program/FullNode.java | 4 + .../java/org/tron/program/SolidityNode.java | 4 + framework/src/main/resources/config.conf | 9 + framework/src/main/resources/logback.xml | 7 + .../prometheus/PrometheusApiServiceTest.java | 188 ++++++++++++++++++ 58 files changed, 1386 insertions(+), 58 deletions(-) create mode 100644 chainbase/src/main/java/org/tron/common/storage/metric/DbStat.java create mode 100644 chainbase/src/main/java/org/tron/common/storage/metric/DbStatService.java create mode 100644 common/src/main/java/org/tron/common/prometheus/InstrumentedAppender.java create mode 100644 common/src/main/java/org/tron/common/prometheus/MetricAspect.java create mode 100644 common/src/main/java/org/tron/common/prometheus/MetricKeys.java create mode 100644 common/src/main/java/org/tron/common/prometheus/MetricLabels.java create mode 100644 common/src/main/java/org/tron/common/prometheus/MetricTime.java create mode 100644 common/src/main/java/org/tron/common/prometheus/Metrics.java create mode 100644 common/src/main/java/org/tron/common/prometheus/MetricsCounter.java create mode 100644 common/src/main/java/org/tron/common/prometheus/MetricsGauge.java create mode 100644 common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java create mode 100644 common/src/main/java/org/tron/common/prometheus/OperatingSystemExports.java create mode 100644 framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java diff --git a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java index df75d0ecd68..5559b4d214c 100644 --- a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java @@ -24,6 +24,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -33,6 +34,7 @@ import java.util.Set; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; import lombok.NoArgsConstructor; @@ -46,6 +48,7 @@ import org.iq80.leveldb.WriteOptions; import org.tron.common.parameter.CommonParameter; import org.tron.common.storage.WriteOptionsWrapper; +import org.tron.common.storage.metric.DbStat; import org.tron.common.utils.FileUtil; import org.tron.common.utils.StorageUtils; import org.tron.core.db.common.DbSourceInter; @@ -54,8 +57,8 @@ @Slf4j(topic = "DB") @NoArgsConstructor -public class LevelDbDataSourceImpl implements DbSourceInter, - Iterable>, Instance { +public class LevelDbDataSourceImpl extends DbStat implements DbSourceInter, + Iterable>, Instance { private String dataBaseName; private DB database; @@ -64,6 +67,7 @@ public class LevelDbDataSourceImpl implements DbSourceInter, private Options options; private WriteOptions writeOptions; private ReadWriteLock resetDbLock = new ReentrantReadWriteLock(); + private static final String LEVELDB = "LEVELDB"; /** * constructor. @@ -486,4 +490,33 @@ private DBIterator getDBIterator() { return database.iterator(readOptions); } + + /** + * Compactions + * Level Files Size(MB) Time(sec) Read(MB) Write(MB) + * -------------------------------------------------- + * 1 2 2 0 0 2 + * 2 1 1 0 0 1 + */ + @Override + public List getStats() throws Exception { + String stat = database.getProperty("leveldb.stats"); + String[] stats = stat.split("\n"); + return Arrays.stream(stats).skip(3).collect(Collectors.toList()); + } + + @Override + public String getEngine() { + return LEVELDB; + } + + @Override + public String getName() { + return this.dataBaseName; + } + + @Override public void stat() { + this.statProperty(); + } + } diff --git a/chainbase/src/main/java/org/tron/common/storage/metric/DbStat.java b/chainbase/src/main/java/org/tron/common/storage/metric/DbStat.java new file mode 100644 index 00000000000..c7fecf2a351 --- /dev/null +++ b/chainbase/src/main/java/org/tron/common/storage/metric/DbStat.java @@ -0,0 +1,34 @@ +package org.tron.common.storage.metric; + +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.Metrics; + +@Slf4j(topic = "metrics") +public abstract class DbStat { + + protected void statProperty() { + try { + getStats().forEach(stat -> { + String[] tmp = stat.trim().replaceAll(" +", ",").split(","); + String level = tmp[0]; + double files = Double.parseDouble(tmp[1]); + double size = Double.parseDouble(tmp[2]) * 1048576.0; + Metrics.gaugeSet(MetricKeys.Gauge.DB_SST_LEVEL, files, getEngine(), getName(), level); + Metrics.gaugeSet(MetricKeys.Gauge.DB_SIZE_BYTES, size, getEngine(), getName(), level); + logger.info("DB {}, level:{},files:{},size:{} M", + getName(), level, files, size / 1048576.0); + }); + } catch (Exception e) { + logger.warn("DB {} stats error", getName(), e); + } + } + + public abstract List getStats() throws Exception; + + public abstract String getEngine(); + + public abstract String getName(); + +} diff --git a/chainbase/src/main/java/org/tron/common/storage/metric/DbStatService.java b/chainbase/src/main/java/org/tron/common/storage/metric/DbStatService.java new file mode 100644 index 00000000000..3cb4dcb488c --- /dev/null +++ b/chainbase/src/main/java/org/tron/common/storage/metric/DbStatService.java @@ -0,0 +1,42 @@ +package org.tron.common.storage.metric; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.tron.common.prometheus.Metrics; +import org.tron.core.db.common.DbSourceInter; +import org.tron.core.db2.common.DB; + +@Slf4j(topic = "metrics") +@Component +public class DbStatService { + private static final ScheduledExecutorService statExecutor = + Executors.newSingleThreadScheduledExecutor( + new ThreadFactoryBuilder().setNameFormat("db-stats-thread-%d").build()); + + + public void register(DB db) { + if (Metrics.initialized()) { + statExecutor.scheduleWithFixedDelay(db::stat, 0, 6, TimeUnit.HOURS); + } + } + + public void register(DbSourceInter db) { + if (Metrics.initialized()) { + statExecutor.scheduleWithFixedDelay(db::stat, 0, 6, TimeUnit.HOURS); + } + } + + public void shutdown() { + if (Metrics.initialized()) { + try { + statExecutor.shutdown(); + } catch (Exception e) { + logger.error("{}", e.getMessage()); + } + } + } +} diff --git a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java index eb85e624457..114fbb1dccd 100644 --- a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java @@ -7,6 +7,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -15,6 +16,7 @@ import java.util.Set; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.stream.Collectors; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.rocksdb.BlockBasedTableConfig; @@ -31,6 +33,7 @@ import org.rocksdb.WriteOptions; import org.tron.common.setting.RocksDbSettings; import org.tron.common.storage.WriteOptionsWrapper; +import org.tron.common.storage.metric.DbStat; import org.tron.common.utils.FileUtil; import org.tron.common.utils.PropUtil; import org.tron.core.db.common.DbSourceInter; @@ -40,7 +43,7 @@ @Slf4j @NoArgsConstructor -public class RocksDbDataSourceImpl implements DbSourceInter, +public class RocksDbDataSourceImpl extends DbStat implements DbSourceInter, Iterable>, Instance { ReadOptions readOpts; @@ -248,7 +251,6 @@ public void initDB(RocksDbSettings settings) { } alive = true; - } catch (IOException ioe) { logger.error(ioe.getMessage(), ioe); throw new RuntimeException(FAIL_TO_INIT_DATABASE, ioe); @@ -512,4 +514,38 @@ public boolean deleteDbBakPath(String dir) { public RocksDbDataSourceImpl newInstance() { return new RocksDbDataSourceImpl(parentPath, dataBaseName, RocksDbSettings.getSettings()); } + + + + /** + * Level Files Size(MB) + * -------------------- + * 0 5 10 + * 1 134 254 + * 2 1311 2559 + * 3 1976 4005 + * 4 0 0 + * 5 0 0 + * 6 0 0 + */ + @Override + public List getStats() throws Exception { + String stat = database.getProperty("rocksdb.levelstats"); + String[] stats = stat.split("\n"); + return Arrays.stream(stats).skip(2).collect(Collectors.toList()); + } + + @Override + public String getEngine() { + return ROCKSDB; + } + + @Override + public String getName() { + return this.dataBaseName; + } + + @Override public void stat() { + this.statProperty(); + } } diff --git a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java index 884fbeace15..0a746e6b410 100644 --- a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java +++ b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java @@ -10,6 +10,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.common.storage.metric.DbStatService; import org.tron.common.utils.ForkController; import org.tron.common.utils.Sha256Hash; import org.tron.common.zksnark.MerkleContainer; @@ -225,6 +226,9 @@ public class ChainBaseManager { @Getter private SectionBloomStore sectionBloomStore; + @Autowired + DbStatService dbStatService; + public void closeOneStore(ITronChainBase database) { logger.info("******** begin to close " + database.getName() + " ********"); try { @@ -237,6 +241,7 @@ public void closeOneStore(ITronChainBase database) { } public void closeAllStore() { + dbStatService.shutdown(); closeOneStore(transactionRetStore); closeOneStore(recentBlockStore); closeOneStore(transactionHistoryStore); diff --git a/chainbase/src/main/java/org/tron/core/db/TronDatabase.java b/chainbase/src/main/java/org/tron/core/db/TronDatabase.java index ee608e4d5ad..ad3e7b4fd67 100644 --- a/chainbase/src/main/java/org/tron/core/db/TronDatabase.java +++ b/chainbase/src/main/java/org/tron/core/db/TronDatabase.java @@ -4,11 +4,14 @@ import java.nio.file.Paths; import java.util.Iterator; import java.util.Map.Entry; +import javax.annotation.PostConstruct; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.iq80.leveldb.WriteOptions; +import org.springframework.beans.factory.annotation.Autowired; import org.tron.common.parameter.CommonParameter; import org.tron.common.storage.leveldb.LevelDbDataSourceImpl; +import org.tron.common.storage.metric.DbStatService; import org.tron.common.storage.rocksdb.RocksDbDataSourceImpl; import org.tron.common.utils.StorageUtils; import org.tron.core.db.common.DbSourceInter; @@ -23,6 +26,9 @@ public abstract class TronDatabase implements ITronChainBase { @Getter private String dbName; + @Autowired + DbStatService dbStatService; + protected TronDatabase(String dbName) { this.dbName = dbName; @@ -46,6 +52,11 @@ protected TronDatabase(String dbName) { dbSource.initDB(); } + @PostConstruct + private void init() { + dbStatService.register(dbSource); + } + protected TronDatabase() { } diff --git a/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java b/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java index c3425926379..b44a79e97f8 100644 --- a/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java +++ b/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java @@ -20,6 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.tron.common.parameter.CommonParameter; import org.tron.common.storage.leveldb.LevelDbDataSourceImpl; +import org.tron.common.storage.metric.DbStatService; import org.tron.common.storage.rocksdb.RocksDbDataSourceImpl; import org.tron.common.utils.StorageUtils; import org.tron.core.capsule.ProtoCapsule; @@ -47,6 +48,11 @@ public abstract class TronStoreWithRevoking implements I @Autowired private RevokingDatabase revokingDatabase; + @Autowired + DbStatService dbStatService; + + private DB db; + protected TronStoreWithRevoking(String dbName) { int dbVersion = CommonParameter.getInstance().getStorage().getDbVersion(); String dbEngine = CommonParameter.getInstance().getStorage().getDbEngine(); @@ -55,24 +61,25 @@ protected TronStoreWithRevoking(String dbName) { getOptionsByDbNameForLevelDB(dbName)); } else if (dbVersion == 2) { if ("LEVELDB".equals(dbEngine.toUpperCase())) { - this.revokingDB = new Chainbase(new SnapshotRoot( - new LevelDB( - new LevelDbDataSourceImpl(StorageUtils.getOutputDirectoryByDbName(dbName), - dbName, - getOptionsByDbNameForLevelDB(dbName), - new WriteOptions().sync(CommonParameter.getInstance() - .getStorage().isDbSync()))))); + this.db = new LevelDB( + new LevelDbDataSourceImpl(StorageUtils.getOutputDirectoryByDbName(dbName), + dbName, + getOptionsByDbNameForLevelDB(dbName), + new WriteOptions().sync(CommonParameter.getInstance() + .getStorage().isDbSync()))); } else if ("ROCKSDB".equals(dbEngine.toUpperCase())) { String parentPath = Paths .get(StorageUtils.getOutputDirectoryByDbName(dbName), CommonParameter .getInstance().getStorage().getDbDirectory()).toString(); - - this.revokingDB = new Chainbase(new SnapshotRoot( - new RocksDB( - new RocksDbDataSourceImpl(parentPath, - dbName, CommonParameter.getInstance() - .getRocksDBCustomSettings(), getDirectComparator())))); + this.db = new RocksDB( + new RocksDbDataSourceImpl(parentPath, + dbName, CommonParameter.getInstance() + .getRocksDBCustomSettings(), getDirectComparator())); + } else { + throw new RuntimeException("dbEngine is error."); } + this.revokingDB = new Chainbase(new SnapshotRoot(this.db)); + } else { throw new RuntimeException("db version is error."); } @@ -89,6 +96,7 @@ protected DirectComparator getDirectComparator() { protected TronStoreWithRevoking(DB db) { int dbVersion = CommonParameter.getInstance().getStorage().getDbVersion(); if (dbVersion == 2) { + this.db = db; this.revokingDB = new Chainbase(new SnapshotRoot(db)); } else { throw new RuntimeException("db version is only 2.(" + dbVersion + ")"); @@ -116,6 +124,7 @@ public String getDbName() { @PostConstruct private void init() { revokingDatabase.add(revokingDB); + dbStatService.register(db); } @Override diff --git a/chainbase/src/main/java/org/tron/core/db/common/DbSourceInter.java b/chainbase/src/main/java/org/tron/core/db/common/DbSourceInter.java index e823da1bde9..a5131047941 100755 --- a/chainbase/src/main/java/org/tron/core/db/common/DbSourceInter.java +++ b/chainbase/src/main/java/org/tron/core/db/common/DbSourceInter.java @@ -42,4 +42,6 @@ public interface DbSourceInter extends BatchSourceInter, long getTotal() throws RuntimeException; + void stat(); + } diff --git a/chainbase/src/main/java/org/tron/core/db2/common/ConcurrentHashDB.java b/chainbase/src/main/java/org/tron/core/db2/common/ConcurrentHashDB.java index d6492cc2eaf..ac5eb6d6580 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/ConcurrentHashDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/ConcurrentHashDB.java @@ -55,4 +55,9 @@ public void close() { public DB newInstance() { return null; } + + @Override + public void stat() { + + } } diff --git a/chainbase/src/main/java/org/tron/core/db2/common/DB.java b/chainbase/src/main/java/org/tron/core/db2/common/DB.java index e58ba6df3e5..fed5e52bb04 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/DB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/DB.java @@ -20,4 +20,6 @@ public interface DB extends Iterable>, Instance> void close(); String getDbName(); + + void stat(); } diff --git a/chainbase/src/main/java/org/tron/core/db2/common/HashDB.java b/chainbase/src/main/java/org/tron/core/db2/common/HashDB.java index 87612f1d81f..85b81ed37e8 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/HashDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/HashDB.java @@ -1,6 +1,5 @@ package org.tron.core.db2.common; -import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -58,4 +57,9 @@ public void close() { public HashDB newInstance() { return new HashDB(name); } + + @Override + public void stat() { + + } } diff --git a/chainbase/src/main/java/org/tron/core/db2/common/LevelDB.java b/chainbase/src/main/java/org/tron/core/db2/common/LevelDB.java index b0d885ce81f..b5616f87b8a 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/LevelDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/LevelDB.java @@ -77,4 +77,9 @@ public void reset() { public LevelDB newInstance() { return new LevelDB(db.newInstance()); } + + @Override + public void stat() { + this.db.stat(); + } } diff --git a/chainbase/src/main/java/org/tron/core/db2/common/RocksDB.java b/chainbase/src/main/java/org/tron/core/db2/common/RocksDB.java index 6855bc08a77..31970b185cc 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/RocksDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/RocksDB.java @@ -78,4 +78,9 @@ public void reset() { public DB newInstance() { return new RocksDB(db.newInstance()); } + + @Override + public void stat() { + this.db.stat(); + } } \ No newline at end of file diff --git a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java index 75f14d55b9d..23c36779149 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java @@ -216,5 +216,10 @@ public void reset() { public TxCacheDB newInstance() { return new TxCacheDB(name, recentTransactionStore); } + + @Override + public void stat() { + + } } diff --git a/common/build.gradle b/common/build.gradle index f270932b839..713e0a213e3 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -47,6 +47,12 @@ dependencies { compile group: 'org.rocksdb', name: 'rocksdbjni', version: '5.15.10' // https://mvnrepository.com/artifact/org.quartz-scheduler/quartz compile group: 'org.quartz-scheduler', name: 'quartz', version: '2.3.2' + compile group: 'io.prometheus', name: 'simpleclient', version: '0.15.0' + compile group: 'io.prometheus', name: 'simpleclient_httpserver', version: '0.15.0' + compile group: 'io.prometheus', name: 'simpleclient_hotspot', version: '0.15.0' + compile 'org.aspectj:aspectjrt:1.8.13' + compile 'org.aspectj:aspectjweaver:1.8.13' + compile 'org.aspectj:aspectjtools:1.8.13' compile project(":protocol") } diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index e5df4bc9d70..1cbabe9139e 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -449,6 +449,14 @@ public class CommonParameter { @Setter public int metricsReportInterval = 10; + @Getter + @Setter + public boolean metricsPrometheusEnable = false; + + @Getter + @Setter + public int metricsPrometheusPort; + @Getter @Setter public int agreeNodeCount; diff --git a/common/src/main/java/org/tron/common/prometheus/InstrumentedAppender.java b/common/src/main/java/org/tron/common/prometheus/InstrumentedAppender.java new file mode 100644 index 00000000000..8eff4815103 --- /dev/null +++ b/common/src/main/java/org/tron/common/prometheus/InstrumentedAppender.java @@ -0,0 +1,32 @@ +package org.tron.common.prometheus; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.UnsynchronizedAppenderBase; +import io.prometheus.client.Counter; + +/** + * a new instrumented appender using the default registry. + */ +public class InstrumentedAppender extends UnsynchronizedAppenderBase { + public static final String COUNTER_NAME = "tron:error_info"; + + private static final Counter defaultCounter = Counter.build().name(COUNTER_NAME) + .help("tron log statements at error type levels") + .labelNames("topic", "type") + .register(); + + @Override + protected void append(ILoggingEvent event) { + if (Metrics.initialized()) { + if (event.getLevel().toInt() == Level.ERROR_INT) { + String type = MetricLabels.UNDEFINED; + if (event.getThrowableProxy() != null) { + type = event.getThrowableProxy().getClassName(); + type = type.substring(type.lastIndexOf(".") + 1); + } + defaultCounter.labels(event.getLoggerName(), type).inc(); + } + } + } +} diff --git a/common/src/main/java/org/tron/common/prometheus/MetricAspect.java b/common/src/main/java/org/tron/common/prometheus/MetricAspect.java new file mode 100644 index 00000000000..c6f7a08f95c --- /dev/null +++ b/common/src/main/java/org/tron/common/prometheus/MetricAspect.java @@ -0,0 +1,55 @@ +package org.tron.common.prometheus; + +import io.prometheus.client.Histogram; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; + +@Aspect +@Component +public class MetricAspect { + + @Around("@annotation(metricTime)") + public Object aroundAdviceMetricTime(ProceedingJoinPoint pjp, MetricTime metricTime) + throws Throwable { + Object result; + Histogram.Timer requestTimer = Metrics.histogramStartTimer( + MetricKeys.Histogram.INTERNAL_SERVICE_LATENCY, + pjp.getSignature().getDeclaringType().getSimpleName(), + metricTime.value().isEmpty() ? pjp.getSignature().getName() : metricTime.value()); + try { + result = pjp.proceed(); + } catch (Throwable throwable) { + Metrics.counterInc( + MetricKeys.Counter.INTERNAL_SERVICE_FAIL, 1, + pjp.getSignature().getDeclaringType().getSimpleName(), + metricTime.value().isEmpty() ? pjp.getSignature().getName() : metricTime.value()); + throw throwable; + } finally { + Metrics.histogramObserve(requestTimer); + } + return result; + } + + @Around("execution(public * org.tron.core.Wallet.*(..))") + public Object walletAroundAdvice(ProceedingJoinPoint pjp) throws Throwable { + Object result; + Histogram.Timer requestTimer = Metrics.histogramStartTimer( + MetricKeys.Histogram.INTERNAL_SERVICE_LATENCY, + pjp.getSignature().getDeclaringType().getSimpleName(), + pjp.getSignature().getName()); + try { + result = pjp.proceed(); + } catch (Throwable throwable) { + Metrics.counterInc( + MetricKeys.Counter.INTERNAL_SERVICE_FAIL, 1, + pjp.getSignature().getDeclaringType().getSimpleName(), + pjp.getSignature().getName()); + throw throwable; + } finally { + Metrics.histogramObserve(requestTimer); + } + return result; + } +} \ No newline at end of file diff --git a/common/src/main/java/org/tron/common/prometheus/MetricKeys.java b/common/src/main/java/org/tron/common/prometheus/MetricKeys.java new file mode 100644 index 00000000000..8172eaffd8b --- /dev/null +++ b/common/src/main/java/org/tron/common/prometheus/MetricKeys.java @@ -0,0 +1,67 @@ +package org.tron.common.prometheus; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j(topic = "metrics") +public class MetricKeys { + + private MetricKeys() { + throw new IllegalStateException("MetricsKey"); + } + + // Counter + public static class Counter { + public static final String TXS = "tron:txs"; + public static final String MINER = "tron:miner"; + public static final String BLOCK_FORK = "tron:block_fork"; + public static final String P2P_ERROR = "tron:p2p_error"; + public static final String P2P_DISCONNECT = "tron:p2p_disconnect"; + public static final String INTERNAL_SERVICE_FAIL = "tron:internal_service_fail"; + + private Counter() { + throw new IllegalStateException("Counter"); + } + + } + + // Gauge + public static class Gauge { + public static final String HEADER_HEIGHT = "tron:header_height"; + public static final String HEADER_TIME = "tron:header_time"; + public static final String PEERS = "tron:peers"; + public static final String DB_SIZE_BYTES = "tron:db_size_bytes"; + public static final String DB_SST_LEVEL = "tron:db_sst_level"; + public static final String MANAGER_QUEUE = "tron:manager_queue_size"; + + private Gauge() { + throw new IllegalStateException("Gauge"); + } + + } + + // Histogram + public static class Histogram { + public static final String HTTP_SERVICE_LATENCY = "tron:http_service_latency_seconds"; + public static final String GRPC_SERVICE_LATENCY = "tron:grpc_service_latency_seconds"; + public static final String MINER_LATENCY = "tron:miner_latency_seconds"; + public static final String PING_PONG_LATENCY = "tron:ping_pong_latency_seconds"; + public static final String VERIFY_SIGN_LATENCY = "tron:verify_sign_latency_seconds"; + public static final String LOCK_ACQUIRE_LATENCY = "tron:lock_acquire_latency_seconds"; + public static final String BLOCK_PROCESS_LATENCY = "tron:block_process_latency_seconds"; + public static final String BLOCK_PUSH_LATENCY = "tron:block_push_latency_seconds"; + public static final String BLOCK_GENERATE_LATENCY = "tron:block_generate_latency_seconds"; + public static final String PROCESS_TRANSACTION_LATENCY = + "tron:process_transaction_latency_seconds"; + public static final String MINER_DELAY = "tron:miner_delay_seconds"; + public static final String UDP_BYTES = "tron:udp_bytes"; + public static final String TCP_BYTES = "tron:tcp_bytes"; + public static final String HTTP_BYTES = "tron:http_bytes"; + public static final String INTERNAL_SERVICE_LATENCY = "tron:internal_service_latency_seconds"; + + private Histogram() { + throw new IllegalStateException("Histogram"); + } + + } + +} diff --git a/common/src/main/java/org/tron/common/prometheus/MetricLabels.java b/common/src/main/java/org/tron/common/prometheus/MetricLabels.java new file mode 100644 index 00000000000..2aa3c1e3378 --- /dev/null +++ b/common/src/main/java/org/tron/common/prometheus/MetricLabels.java @@ -0,0 +1,78 @@ +package org.tron.common.prometheus; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j(topic = "metrics") +public class MetricLabels { + + public static final String SUCCESS = "success"; + public static final String FAIL = "fail"; + public static final String ALL = "all"; + public static final String UNDEFINED = "undefined"; + public static final String BLOCK = "block"; + public static final String TRX = "trx"; + + private MetricLabels() { + throw new IllegalStateException("MetricsLabels"); + } + + // Counter + public static class Counter { + + public static final String MINE_SUCCESS = SUCCESS; + public static final String MINE_MISS = "miss"; + public static final String MINE_DUP = "dup"; + public static final String TXS_SUCCESS = SUCCESS; + public static final String TXS_FAIL = FAIL; + public static final String TXS_FAIL_ERROR = "error"; + public static final String TXS_FAIL_BIG = "big"; + public static final String TXS_FAIL_EXPIRED = "expired"; + public static final String TXS_FAIL_TIMEOUT = "timeout"; + public static final String TXS_FAIL_SIG = "sig"; + public static final String TXS_FAIL_TAPOS = "tapos"; + public static final String TXS_FAIL_DUP = "dup"; + + private Counter() { + throw new IllegalStateException("Counter"); + } + + + } + + // Gauge + public static class Gauge { + public static final String QUEUE_PENDING = "pending"; + + public static final String QUEUE_REPUSH = "repush"; + + public static final String QUEUE_POPPED = "popped"; + + public static final String QUEUE_QUEUED = "queued"; + + public static final String PEERS_ACTIVE = "active"; + + public static final String PEERS_PASSIVE = "passive"; + + public static final String PEERS_ALL = "all"; + + public static final String PEERS_VALID = "valid"; + + private Gauge() { + throw new IllegalStateException("Gauge"); + } + + + } + + // Histogram + public static class Histogram { + public static final String TRAFFIC_IN = "in"; + public static final String TRAFFIC_OUT = "out"; + + private Histogram() { + throw new IllegalStateException("Histogram"); + } + + } + +} diff --git a/common/src/main/java/org/tron/common/prometheus/MetricTime.java b/common/src/main/java/org/tron/common/prometheus/MetricTime.java new file mode 100644 index 00000000000..47a66d194e8 --- /dev/null +++ b/common/src/main/java/org/tron/common/prometheus/MetricTime.java @@ -0,0 +1,13 @@ +package org.tron.common.prometheus; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Target(METHOD) +@Retention(RUNTIME) +public @interface MetricTime { + String value() default ""; +} diff --git a/common/src/main/java/org/tron/common/prometheus/Metrics.java b/common/src/main/java/org/tron/common/prometheus/Metrics.java new file mode 100644 index 00000000000..54654fad30a --- /dev/null +++ b/common/src/main/java/org/tron/common/prometheus/Metrics.java @@ -0,0 +1,68 @@ +package org.tron.common.prometheus; + +import io.prometheus.client.Collector; +import io.prometheus.client.CollectorRegistry; +import io.prometheus.client.Histogram; +import io.prometheus.client.exporter.HTTPServer; +import io.prometheus.client.hotspot.DefaultExports; +import java.io.IOException; +import lombok.extern.slf4j.Slf4j; +import org.tron.common.parameter.CommonParameter; + +@Slf4j(topic = "metrics") +public class Metrics { + + public static final double MILLISECONDS_PER_SECOND = Collector.MILLISECONDS_PER_SECOND; + private static volatile boolean initialized = false; + + private Metrics() { + throw new IllegalStateException("Metrics"); + } + + public static synchronized void init() { + if(initialized) { + return; + } + if (CommonParameter.getInstance().isMetricsPrometheusEnable()) { + try { + DefaultExports.initialize(); + new OperatingSystemExports().register(CollectorRegistry.defaultRegistry); + int port = CommonParameter.getInstance().getMetricsPrometheusPort(); + new HTTPServer.Builder().withPort(port).build(); + logger.info("prometheus exposed on port : {}", port); + initialized = true; + } catch (IOException e) { + CommonParameter.getInstance().setMetricsPrometheusEnable(false); + logger.error("{}", e.getMessage()); + } + } + } + + public static boolean initialized() { + return initialized; + } + + public static void counterInc(String key, double amt, String... labels) { + MetricsCounter.inc(key, amt, labels); + } + + public static void gaugeInc(String key, double amt, String... labels) { + MetricsGauge.inc(key, amt, labels); + } + + public static void gaugeSet(String key, double amt, String... labels) { + MetricsGauge.set(key, amt, labels); + } + + public static Histogram.Timer histogramStartTimer(String key, String... labels) { + return MetricsHistogram.startTimer(key, labels); + } + + public static void histogramObserve(Histogram.Timer startTimer) { + MetricsHistogram.observeDuration(startTimer); + } + + public static void histogramObserve(String key, double amt, String... labels) { + MetricsHistogram.observe(key, amt, labels); + } +} diff --git a/common/src/main/java/org/tron/common/prometheus/MetricsCounter.java b/common/src/main/java/org/tron/common/prometheus/MetricsCounter.java new file mode 100644 index 00000000000..8418e9fc76a --- /dev/null +++ b/common/src/main/java/org/tron/common/prometheus/MetricsCounter.java @@ -0,0 +1,46 @@ +package org.tron.common.prometheus; + +import io.prometheus.client.Counter; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import lombok.extern.slf4j.Slf4j; + +@Slf4j(topic = "metrics") +class MetricsCounter { + + private static final Map container = new ConcurrentHashMap<>(); + + static { + init(MetricKeys.Counter.TXS, "tron txs info .", "type", "detail"); + init(MetricKeys.Counter.MINER, "tron miner info .", "miner", "type"); + init(MetricKeys.Counter.BLOCK_FORK, "tron block fork info .", "type"); + init(MetricKeys.Counter.P2P_ERROR, "tron p2p error info .", "type"); + init(MetricKeys.Counter.P2P_DISCONNECT, "tron p2p disconnect .", "type"); + init(MetricKeys.Counter.INTERNAL_SERVICE_FAIL, "internal Service fail.", + "class", "method"); + } + + private MetricsCounter() { + throw new IllegalStateException("MetricsCounter"); + } + + private static void init(String name, String help, String... labels) { + container.put(name, Counter.build() + .name(name) + .help(help) + .labelNames(labels) + .register()); + } + + static void inc(String key, double amt, String... labels) { + if (Metrics.initialized()) { + Counter counter = container.get(key); + if (counter == null) { + logger.info("{} not exist", key); + return; + } + counter.labels(labels).inc(amt); + } + } +} + diff --git a/common/src/main/java/org/tron/common/prometheus/MetricsGauge.java b/common/src/main/java/org/tron/common/prometheus/MetricsGauge.java new file mode 100644 index 00000000000..2628c48c734 --- /dev/null +++ b/common/src/main/java/org/tron/common/prometheus/MetricsGauge.java @@ -0,0 +1,59 @@ +package org.tron.common.prometheus; + +import io.prometheus.client.Gauge; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import lombok.extern.slf4j.Slf4j; + +@Slf4j(topic = "metrics") +class MetricsGauge { + + + private static final Map container = new ConcurrentHashMap<>(); + + static { + init(MetricKeys.Gauge.MANAGER_QUEUE, "tron manager.queue.size .", "type"); + init(MetricKeys.Gauge.HEADER_HEIGHT, "header height ."); + init(MetricKeys.Gauge.HEADER_TIME, "header time ."); + init(MetricKeys.Gauge.PEERS, "tron peers.size .", "type"); + init(MetricKeys.Gauge.DB_SIZE_BYTES, "tron db size .", "type", "db", "level"); + init(MetricKeys.Gauge.DB_SST_LEVEL, "tron db files .", "type", "db", "level"); + } + + private MetricsGauge() { + throw new IllegalStateException("MetricsGauge"); + } + + private static void init(String name, String help, String... labels) { + container.put(name, Gauge.build() + .name(name) + .help(help) + .labelNames(labels) + .register()); + } + + + static void inc(String key, double delta, String... labels) { + if (Metrics.initialized()) { + Gauge gauge = container.get(key); + if (gauge == null) { + logger.info("{} not exist", key); + return; + } + gauge.labels(labels).inc(delta); + } + } + + static void set(String key, double v, String... labels) { + if (Metrics.initialized()) { + Gauge gauge = container.get(key); + if (gauge == null) { + logger.info("{} not exist", key); + return; + } + gauge.labels(labels).set(v); + } + } + +} + diff --git a/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java b/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java new file mode 100644 index 00000000000..ba090934d54 --- /dev/null +++ b/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java @@ -0,0 +1,89 @@ +package org.tron.common.prometheus; + +import io.prometheus.client.Histogram; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import lombok.extern.slf4j.Slf4j; + +@Slf4j(topic = "metrics") +public class MetricsHistogram { + + private static final Map container = new ConcurrentHashMap<>(); + + static { + init(MetricKeys.Histogram.INTERNAL_SERVICE_LATENCY, "Internal Service latency.", + "class", "method"); + init(MetricKeys.Histogram.HTTP_SERVICE_LATENCY, "Http Service latency.", + "url"); + init(MetricKeys.Histogram.GRPC_SERVICE_LATENCY, "Grpc Service latency.", + "endpoint"); + init(MetricKeys.Histogram.MINER_LATENCY, "miner latency.", + "miner"); + init(MetricKeys.Histogram.PING_PONG_LATENCY, "node ping pong latency."); + init(MetricKeys.Histogram.VERIFY_SIGN_LATENCY, "verify sign latency for trx , block.", + "type"); + init(MetricKeys.Histogram.LOCK_ACQUIRE_LATENCY, "lock acquire latency.", + "type"); + init(MetricKeys.Histogram.BLOCK_PROCESS_LATENCY, + "process block latency for TronNetDelegate.", + "sync"); + init(MetricKeys.Histogram.BLOCK_PUSH_LATENCY, "push block latency for Manager."); + init(MetricKeys.Histogram.BLOCK_GENERATE_LATENCY, "generate block latency.", + "address"); + + init(MetricKeys.Histogram.PROCESS_TRANSACTION_LATENCY, "process transaction latency.", + "type", "contract"); + init(MetricKeys.Histogram.MINER_DELAY, "miner delay time, actualTime - planTime.", + "miner"); + init(MetricKeys.Histogram.UDP_BYTES, "udp_bytes traffic.", + "type"); + init(MetricKeys.Histogram.TCP_BYTES, "tcp_bytes traffic.", + "type"); + init(MetricKeys.Histogram.HTTP_BYTES, "http_bytes traffic.", + "url", "status"); + } + + private MetricsHistogram() { + throw new IllegalStateException("MetricsHistogram"); + } + + private static void init(String name, String help, String... labels) { + container.put(name, Histogram.build() + .name(name) + .help(help) + .labelNames(labels) + .register()); + } + + static Histogram.Timer startTimer(String key, String... labels) { + if (Metrics.initialized()) { + Histogram histogram = container.get(key); + if (histogram == null) { + logger.info("{} not exist", key); + return null; + } + return histogram.labels(labels).startTimer(); + } + return null; + } + + static void observeDuration(Histogram.Timer startTimer) { + if (startTimer != null) { + startTimer.observeDuration(); + } + } + + + static void observe(String key, double amt, String... labels) { + if (Metrics.initialized()) { + Histogram histogram = container.get(key); + if (histogram == null) { + logger.info("{} not exist", key); + return; + } + histogram.labels(labels).observe(amt); + } + } + +} + diff --git a/common/src/main/java/org/tron/common/prometheus/OperatingSystemExports.java b/common/src/main/java/org/tron/common/prometheus/OperatingSystemExports.java new file mode 100644 index 00000000000..45cdad344b8 --- /dev/null +++ b/common/src/main/java/org/tron/common/prometheus/OperatingSystemExports.java @@ -0,0 +1,131 @@ +package org.tron.common.prometheus; + +import static io.prometheus.client.SampleNameFilter.ALLOW_ALL; + +import com.sun.management.OperatingSystemMXBean; +import io.prometheus.client.Collector; +import io.prometheus.client.GaugeMetricFamily; +import io.prometheus.client.Predicate; +import java.lang.management.ManagementFactory; +import java.util.ArrayList; +import java.util.List; + +/** + * Exports metrics about Operating System. + *

+ * Example usage: + *

+ * {@code
+ *  new OperatingSystemExports().register(CollectorRegistry.defaultRegistry);
+ * }
+ * 
+ * Example metrics being exported: + *
+ *   system_available_cpus 12.0
+ *   process_cpu_load{} 200
+ *   system_cpu_load 0.3876289375889973
+ *   system_free_physical_memory_bytes 1.96481024E8
+ * 
+ */ +public class OperatingSystemExports extends Collector { + + private static final String SYSTEM_AVAILABLE_CPUS = "system_available_cpus"; + private static final String PROCESS_CPU_LOAD = "process_cpu_load"; + private static final String SYSTEM_CPU_LOAD = "system_cpu_load"; + private static final String SYSTEM_LOAD_AVERAGE = "system_load_average"; + private static final String SYSTEM_TOTAL_PHYSICAL_MEMORY_BYTES = + "system_total_physical_memory_bytes"; + private static final String SYSTEM_FREE_PHYSICAL_MEMORY_BYTES = + "system_free_physical_memory_bytes"; + private static final String SYSTEM_TOTAL_SWAP_SPACES_BYTES = "system_total_swap_spaces_bytes"; + private static final String SYSTEM_FREE_SWAP_SPACES_BYTES = "system_free_swap_spaces_bytes"; + + + private final OperatingSystemMXBean operatingSystemMXBean; + + public OperatingSystemExports() { + this((OperatingSystemMXBean) ManagementFactory + .getOperatingSystemMXBean()); + } + + public OperatingSystemExports(OperatingSystemMXBean operatingSystemMXBean) { + this.operatingSystemMXBean = operatingSystemMXBean; + } + + void addOperatingSystemMetrics(List sampleFamilies, + Predicate nameFilter) { + if (nameFilter.test(SYSTEM_AVAILABLE_CPUS)) { + sampleFamilies.add( + new GaugeMetricFamily( + SYSTEM_AVAILABLE_CPUS, + "System available cpus", + operatingSystemMXBean.getAvailableProcessors())); + } + + if (nameFilter.test(PROCESS_CPU_LOAD)) { + sampleFamilies.add( + new GaugeMetricFamily( + PROCESS_CPU_LOAD, + "Process cpu load", + operatingSystemMXBean.getProcessCpuLoad())); + } + + if (nameFilter.test(SYSTEM_CPU_LOAD)) { + sampleFamilies.add( + new GaugeMetricFamily( + SYSTEM_CPU_LOAD, + "System cpu load", + operatingSystemMXBean.getSystemCpuLoad())); + } + + if (nameFilter.test(SYSTEM_LOAD_AVERAGE)) { + sampleFamilies.add( + new GaugeMetricFamily( + SYSTEM_LOAD_AVERAGE, + "System cpu load average", + operatingSystemMXBean.getSystemLoadAverage())); + } + + if (nameFilter.test(SYSTEM_TOTAL_PHYSICAL_MEMORY_BYTES)) { + sampleFamilies.add( + new GaugeMetricFamily( + SYSTEM_TOTAL_PHYSICAL_MEMORY_BYTES, + "System total physical memory bytes", + operatingSystemMXBean.getTotalPhysicalMemorySize())); + } + + if (nameFilter.test(SYSTEM_FREE_PHYSICAL_MEMORY_BYTES)) { + sampleFamilies.add( + new GaugeMetricFamily( + SYSTEM_FREE_PHYSICAL_MEMORY_BYTES, + "System free physical memory bytes", + operatingSystemMXBean.getFreePhysicalMemorySize())); + } + if (nameFilter.test(SYSTEM_TOTAL_SWAP_SPACES_BYTES)) { + sampleFamilies.add( + new GaugeMetricFamily( + SYSTEM_TOTAL_SWAP_SPACES_BYTES, + "System free swap spaces bytes", + operatingSystemMXBean.getTotalSwapSpaceSize())); + } + if (nameFilter.test(SYSTEM_FREE_SWAP_SPACES_BYTES)) { + sampleFamilies.add( + new GaugeMetricFamily( + SYSTEM_FREE_SWAP_SPACES_BYTES, + "System free swap spaces", + operatingSystemMXBean.getFreeSwapSpaceSize())); + } + } + + @Override + public List collect() { + return collect(null); + } + + @Override + public List collect(Predicate nameFilter) { + List mfs = new ArrayList(); + addOperatingSystemMetrics(mfs, nameFilter == null ? ALLOW_ALL : nameFilter); + return mfs; + } +} \ No newline at end of file diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 329cc0d8b70..27d6033d118 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -293,6 +293,8 @@ public class Constant { public static final String METRICS_INFLUXDB_PORT = "node.metrics.influxdb.port"; public static final String METRICS_INFLUXDB_DATABASE = "node.metrics.influxdb.database"; public static final String METRICS_REPORT_INTERVAL = "node.metrics.influxdb.metricsReportInterval"; + public static final String METRICS_PROMETHEUS_ENABLE = "node.metrics.prometheus.enable"; + public static final String METRICS_PROMETHEUS_PORT = "node.metrics.prometheus.port"; public static final String HISTORY_BALANCE_LOOKUP = "storage.balance.history.lookup"; public static final String OPEN_PRINT_LOG = "node.openPrintLog"; diff --git a/common/src/main/java/org/tron/core/exception/DupTransactionException.java b/common/src/main/java/org/tron/core/exception/DupTransactionException.java index 639025ebe81..295500e011f 100644 --- a/common/src/main/java/org/tron/core/exception/DupTransactionException.java +++ b/common/src/main/java/org/tron/core/exception/DupTransactionException.java @@ -1,5 +1,9 @@ package org.tron.core.exception; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; + public class DupTransactionException extends TronException { public DupTransactionException() { @@ -9,4 +13,10 @@ public DupTransactionException() { public DupTransactionException(String message) { super(message); } + + protected void report() { + Metrics.counterInc(MetricKeys.Counter.TXS, 1, + MetricLabels.Counter.TXS_FAIL, MetricLabels.Counter.TXS_FAIL_DUP); + } + } diff --git a/common/src/main/java/org/tron/core/exception/P2pException.java b/common/src/main/java/org/tron/core/exception/P2pException.java index 8931af3a179..d566b833d59 100644 --- a/common/src/main/java/org/tron/core/exception/P2pException.java +++ b/common/src/main/java/org/tron/core/exception/P2pException.java @@ -1,5 +1,9 @@ package org.tron.core.exception; +import java.util.Locale; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.Metrics; + public class P2pException extends Exception { private TypeEnum type; @@ -7,16 +11,24 @@ public class P2pException extends Exception { public P2pException(TypeEnum type, String errMsg) { super(errMsg); this.type = type; + report(); } public P2pException(TypeEnum type, Throwable throwable) { super(throwable); this.type = type; + report(); } public P2pException(TypeEnum type, String errMsg, Throwable throwable) { super(errMsg, throwable); this.type = type; + report(); + } + + private void report () { + Metrics.counterInc(MetricKeys.Counter.P2P_ERROR, 1, + type.name().toLowerCase(Locale.ROOT)); } public TypeEnum getType() { diff --git a/common/src/main/java/org/tron/core/exception/TaposException.java b/common/src/main/java/org/tron/core/exception/TaposException.java index 222e9c7e83e..234981a9484 100644 --- a/common/src/main/java/org/tron/core/exception/TaposException.java +++ b/common/src/main/java/org/tron/core/exception/TaposException.java @@ -1,6 +1,10 @@ package org.tron.core.exception; -public class TaposException extends Exception { +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; + +public class TaposException extends TronException { public TaposException() { super(); @@ -14,4 +18,9 @@ public TaposException(String message, Throwable cause) { super(message, cause); } + protected void report() { + Metrics.counterInc(MetricKeys.Counter.TXS, 1, + MetricLabels.Counter.TXS_FAIL, MetricLabels.Counter.TXS_FAIL_TAPOS); + } + } diff --git a/common/src/main/java/org/tron/core/exception/TooBigTransactionException.java b/common/src/main/java/org/tron/core/exception/TooBigTransactionException.java index fa8e3988cf5..cbbb00d7d2c 100644 --- a/common/src/main/java/org/tron/core/exception/TooBigTransactionException.java +++ b/common/src/main/java/org/tron/core/exception/TooBigTransactionException.java @@ -1,5 +1,9 @@ package org.tron.core.exception; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; + public class TooBigTransactionException extends TronException { public TooBigTransactionException() { @@ -9,4 +13,10 @@ public TooBigTransactionException() { public TooBigTransactionException(String message) { super(message); } + + protected void report() { + Metrics.counterInc(MetricKeys.Counter.TXS, 1, + MetricLabels.Counter.TXS_FAIL, MetricLabels.Counter.TXS_FAIL_BIG); + } + } diff --git a/common/src/main/java/org/tron/core/exception/TransactionExpirationException.java b/common/src/main/java/org/tron/core/exception/TransactionExpirationException.java index e8282a41f80..cac2cd7412b 100644 --- a/common/src/main/java/org/tron/core/exception/TransactionExpirationException.java +++ b/common/src/main/java/org/tron/core/exception/TransactionExpirationException.java @@ -1,5 +1,9 @@ package org.tron.core.exception; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; + public class TransactionExpirationException extends TronException { public TransactionExpirationException() { @@ -10,4 +14,10 @@ public TransactionExpirationException(String message) { super(message); } + protected void report() { + Metrics.counterInc(MetricKeys.Counter.TXS, 1, + MetricLabels.Counter.TXS_FAIL, MetricLabels.Counter.TXS_FAIL_EXPIRED); + + } + } \ No newline at end of file diff --git a/common/src/main/java/org/tron/core/exception/TronException.java b/common/src/main/java/org/tron/core/exception/TronException.java index 686d979b5ca..0447b28969e 100644 --- a/common/src/main/java/org/tron/core/exception/TronException.java +++ b/common/src/main/java/org/tron/core/exception/TronException.java @@ -4,14 +4,21 @@ public class TronException extends Exception { public TronException() { super(); + report(); } public TronException(String message) { super(message); + report(); } public TronException(String message, Throwable cause) { super(message, cause); + report(); + } + + protected void report(){ + } } diff --git a/common/src/main/java/org/tron/core/exception/ValidateSignatureException.java b/common/src/main/java/org/tron/core/exception/ValidateSignatureException.java index 9c85a5f8e3b..b146b7f3398 100644 --- a/common/src/main/java/org/tron/core/exception/ValidateSignatureException.java +++ b/common/src/main/java/org/tron/core/exception/ValidateSignatureException.java @@ -1,5 +1,9 @@ package org.tron.core.exception; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; + public class ValidateSignatureException extends TronException { public ValidateSignatureException() { @@ -10,4 +14,9 @@ public ValidateSignatureException(String message) { super(message); } + protected void report() { + Metrics.counterInc(MetricKeys.Counter.TXS, 1, + MetricLabels.Counter.TXS_FAIL, MetricLabels.Counter.TXS_FAIL_SIG); + } + } diff --git a/consensus/src/main/java/org/tron/consensus/dpos/StatisticManager.java b/consensus/src/main/java/org/tron/consensus/dpos/StatisticManager.java index c6a7d912277..6dfa40081fd 100644 --- a/consensus/src/main/java/org/tron/consensus/dpos/StatisticManager.java +++ b/consensus/src/main/java/org/tron/consensus/dpos/StatisticManager.java @@ -3,6 +3,10 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; +import org.tron.common.utils.StringUtil; import org.tron.consensus.ConsensusDelegate; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.WitnessCapsule; @@ -24,6 +28,8 @@ public void applyBlock(BlockCapsule blockCapsule) { byte[] blockWitness = blockCapsule.getWitnessAddress().toByteArray(); wc = consensusDelegate.getWitness(blockWitness); wc.setTotalProduced(wc.getTotalProduced() + 1); + Metrics.counterInc(MetricKeys.Counter.MINER, 1, StringUtil.encode58Check(blockWitness), + MetricLabels.Counter.MINE_SUCCESS); wc.setLatestBlockNum(blockNum); wc.setLatestSlotNum(dposSlot.getAbSlot(blockTime)); consensusDelegate.saveWitness(wc); @@ -36,9 +42,13 @@ public void applyBlock(BlockCapsule blockCapsule) { byte[] witness = dposSlot.getScheduledWitness(i).toByteArray(); wc = consensusDelegate.getWitness(witness); wc.setTotalMissed(wc.getTotalMissed() + 1); + Metrics.counterInc(MetricKeys.Counter.MINER, 1, StringUtil.encode58Check(wc.getAddress() + .toByteArray()), + MetricLabels.Counter.MINE_MISS); consensusDelegate.saveWitness(wc); - logger.info("Current block: {}, witness: {} totalMissed: {}", - blockNum, wc.createReadableString(), wc.getTotalMissed()); + logger.info("Current block: {}, witness: {},url: {}, totalMissed: {}", + blockNum, wc.createReadableString(), StringUtil.encode58Check(wc.getAddress() + .toByteArray()), wc.getTotalMissed()); consensusDelegate.applyBlock(false); } consensusDelegate.applyBlock(true); diff --git a/framework/build.gradle b/framework/build.gradle index 75d37122088..8b9663c9ed0 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -65,9 +65,6 @@ dependencies { compile group: 'com.carrotsearch', name: 'java-sizeof', version: '0.0.5' - compile 'org.aspectj:aspectjrt:1.8.13' - compile 'org.aspectj:aspectjweaver:1.8.13' - compile 'org.aspectj:aspectjtools:1.8.13' compile 'com.googlecode.cqengine:cqengine:2.12.4' compile group: 'com.google.api.grpc', name: 'googleapis-common-protos', version: '0.0.3' diff --git a/framework/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java b/framework/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java index aedf330e806..4fee405e6af 100644 --- a/framework/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java @@ -30,6 +30,8 @@ import org.tron.common.net.udp.message.discover.PingMessage; import org.tron.common.net.udp.message.discover.PongMessage; import org.tron.common.overlay.discover.node.statistics.NodeStatistics; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.Metrics; import org.tron.core.config.args.Args; @Slf4j(topic = "discover") @@ -160,6 +162,8 @@ public void handlePong(PongMessage msg) { if (waitForPong) { waitForPong = false; getNodeStatistics().discoverMessageLatency.add(System.currentTimeMillis() - pingSent); + Metrics.histogramObserve(MetricKeys.Histogram.PING_PONG_LATENCY, + (System.currentTimeMillis() - pingSent) / Metrics.MILLISECONDS_PER_SECOND); getNodeStatistics().lastPongReplyTime.set(System.currentTimeMillis()); node.setId(msg.getFrom().getId()); node.setP2pVersion(msg.getVersion()); diff --git a/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java b/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java index 60a15f92e62..5738057d23c 100644 --- a/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java +++ b/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java @@ -28,6 +28,9 @@ import org.tron.common.overlay.discover.node.statistics.NodeStatistics; import org.tron.common.overlay.discover.table.NodeTable; import org.tron.common.parameter.CommonParameter; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; import org.tron.common.utils.ByteArray; import org.tron.common.utils.CollectionUtils; import org.tron.common.utils.JsonUtil; @@ -233,8 +236,10 @@ public void handleEvent(UdpEvent udpEvent) { NodeHandler nodeHandler = getNodeHandler(n); nodeHandler.getNodeStatistics().messageStatistics.addUdpInMessage(m.getType()); - MetricsUtil.meterMark(MetricsKey.NET_UDP_IN_TRAFFIC, - udpEvent.getMessage().getData().length + 1); + int length = udpEvent.getMessage().getData().length + 1; + MetricsUtil.meterMark(MetricsKey.NET_UDP_IN_TRAFFIC, length); + Metrics.histogramObserve(MetricKeys.Histogram.UDP_BYTES, length, + MetricLabels.Histogram.TRAFFIC_IN); switch (m.getType()) { case DISCOVER_PING: @@ -257,8 +262,11 @@ public void handleEvent(UdpEvent udpEvent) { public void sendOutbound(UdpEvent udpEvent) { if (discoveryEnabled && messageSender != null) { messageSender.accept(udpEvent); - MetricsUtil.meterMark(MetricsKey.NET_UDP_OUT_TRAFFIC, - udpEvent.getMessage().getSendData().length); + int length = udpEvent.getMessage().getSendData().length; + MetricsUtil.meterMark(MetricsKey.NET_UDP_OUT_TRAFFIC, length); + Metrics.histogramObserve(MetricKeys.Histogram.UDP_BYTES, length, + MetricLabels.Histogram.TRAFFIC_OUT); + } } diff --git a/framework/src/main/java/org/tron/common/overlay/message/MessageCodec.java b/framework/src/main/java/org/tron/common/overlay/message/MessageCodec.java index f04289bdea9..30a2329131e 100644 --- a/framework/src/main/java/org/tron/common/overlay/message/MessageCodec.java +++ b/framework/src/main/java/org/tron/common/overlay/message/MessageCodec.java @@ -7,6 +7,9 @@ import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import org.tron.common.overlay.server.Channel; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; import org.tron.core.exception.P2pException; import org.tron.core.metrics.MetricsKey; import org.tron.core.metrics.MetricsUtil; @@ -33,6 +36,8 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List ou Message msg = createMessage(encoded); channel.getNodeStatistics().tcpFlow.add(length); MetricsUtil.meterMark(MetricsKey.NET_TCP_IN_TRAFFIC, length); + Metrics.histogramObserve(MetricKeys.Histogram.TCP_BYTES, length, + MetricLabels.Histogram.TRAFFIC_IN); out.add(msg); } catch (Exception e) { channel.processException(e); diff --git a/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java b/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java index 21c754e6510..dbcb73baa8b 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java +++ b/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java @@ -10,6 +10,7 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.Collection; +import java.util.Locale; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @@ -20,6 +21,8 @@ import org.tron.common.overlay.client.PeerClient; import org.tron.common.overlay.discover.node.Node; import org.tron.common.parameter.CommonParameter; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.Metrics; import org.tron.core.config.args.Args; import org.tron.core.db.ByteArrayWrapper; import org.tron.core.metrics.MetricsKey; @@ -112,6 +115,8 @@ public void processDisconnect(Channel channel, ReasonCode reason) { } MetricsUtil.counterInc(MetricsKey.NET_DISCONNECTION_COUNT); MetricsUtil.counterInc(MetricsKey.NET_DISCONNECTION_DETAIL + reason); + Metrics.counterInc(MetricKeys.Counter.P2P_DISCONNECT, 1, + reason.name().toLowerCase(Locale.ROOT)); } public void notifyDisconnect(Channel channel) { diff --git a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java index d7674165dd2..cacc03f426d 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java @@ -35,6 +35,9 @@ import org.tron.common.overlay.message.HelloMessage; import org.tron.common.overlay.message.P2pMessage; import org.tron.common.overlay.message.P2pMessageFactory; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; import org.tron.core.ChainBaseManager; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; @@ -124,9 +127,12 @@ protected void sendHelloMsg(ChannelHandlerContext ctx, long time) { fastForward.fillHelloMessage(message, channel); ((PeerConnection) channel).setHelloMessageSend(message); ctx.writeAndFlush(message.getSendData()); + int length = message.getSendData().readableBytes(); channel.getNodeStatistics().messageStatistics.addTcpOutMessage(message); - MetricsUtil.meterMark(MetricsKey.NET_TCP_OUT_TRAFFIC, - message.getSendData().readableBytes()); + MetricsUtil.meterMark(MetricsKey.NET_TCP_OUT_TRAFFIC, length); + Metrics.histogramObserve(MetricKeys.Histogram.TCP_BYTES, length, + MetricLabels.Histogram.TRAFFIC_OUT); + logger.info("Handshake send to {}, {} ", ctx.channel().remoteAddress(), message); } diff --git a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java index c9b3ac750a8..1919042232f 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java +++ b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java @@ -16,6 +16,9 @@ import org.tron.common.overlay.message.Message; import org.tron.common.overlay.message.PingMessage; import org.tron.common.overlay.message.PongMessage; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; import org.tron.consensus.pbft.message.PbftBaseMessage; import org.tron.core.metrics.MetricsKey; import org.tron.core.metrics.MetricsUtil; @@ -109,7 +112,11 @@ public boolean sendMessage(Message msg) { logger.info("Send to {}, {} ", ctx.channel().remoteAddress(), msg); } channel.getNodeStatistics().messageStatistics.addTcpOutMessage(msg); - MetricsUtil.meterMark(MetricsKey.NET_TCP_OUT_TRAFFIC, msg.getSendData().readableBytes()); + int length = msg.getSendData().readableBytes(); + MetricsUtil.meterMark(MetricsKey.NET_TCP_OUT_TRAFFIC, length); + Metrics.histogramObserve(MetricKeys.Histogram.TCP_BYTES, length, + MetricLabels.Histogram.TRAFFIC_OUT); + sendTime = System.currentTimeMillis(); if (msg.getAnswerMessage() != null) { requestQueue.add(new MessageRoundTrip(msg)); diff --git a/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java b/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java index 7db1d32e5ff..410266d07fa 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java +++ b/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java @@ -24,6 +24,9 @@ import org.tron.common.overlay.discover.node.NodeHandler; import org.tron.common.overlay.discover.node.NodeManager; import org.tron.common.parameter.CommonParameter; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; import org.tron.core.ChainBaseManager; import org.tron.core.config.args.Args; import org.tron.core.metrics.MetricsKey; @@ -138,15 +141,27 @@ private void fillUp() { synchronized void logActivePeers() { String str = String.format("\n\n============ Peer stats: all %d, active %d, passive %d\n\n", channelManager.getActivePeers().size(), activePeersCount.get(), passivePeersCount.get()); + metric(channelManager.getActivePeers().size(), MetricLabels.Gauge.PEERS_ALL); + metric(activePeersCount.get(), MetricLabels.Gauge.PEERS_ACTIVE); + metric(passivePeersCount.get(), MetricLabels.Gauge.PEERS_PASSIVE); StringBuilder sb = new StringBuilder(str); + int valid = 0; for (PeerConnection peer : new ArrayList<>(activePeers)) { sb.append(peer.log()); appendPeerLatencyLog(sb, peer); sb.append("\n"); + if (!(peer.isNeedSyncFromUs() || peer.isNeedSyncFromPeer())) { + valid++; + } } + metric(valid, MetricLabels.Gauge.PEERS_VALID); logger.info(sb.toString()); } + private void metric(double amt, String peerType) { + Metrics.gaugeSet(MetricKeys.Gauge.PEERS, amt, peerType); + } + private void appendPeerLatencyLog(StringBuilder builder, PeerConnection peer) { Snapshot peerSnapshot = MetricsUtil.getHistogram(MetricsKey.NET_LATENCY_FETCH_BLOCK + peer.getNode().getHost()).getSnapshot(); diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index abd9dd8c4ad..9349740d27a 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -185,6 +185,7 @@ public static void clearParam() { PARAMETER.jsonRpcHttpPBFTNodeEnable = false; PARAMETER.nodeMetricsEnable = false; PARAMETER.metricsStorageEnable = false; + PARAMETER.metricsPrometheusEnable = false; PARAMETER.agreeNodeCount = MAX_ACTIVE_WITNESS_NUM * 2 / 3 + 1; PARAMETER.allowPBFT = 0; PARAMETER.allowShieldedTRC20Transaction = 0; @@ -824,6 +825,11 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.metricsReportInterval = config.hasPath(Constant.METRICS_REPORT_INTERVAL) ? config .getInt(Constant.METRICS_REPORT_INTERVAL) : 10; + PARAMETER.metricsPrometheusEnable = config.hasPath(Constant.METRICS_PROMETHEUS_ENABLE) && config + .getBoolean(Constant.METRICS_PROMETHEUS_ENABLE); + PARAMETER.metricsPrometheusPort = config.hasPath(Constant.METRICS_PROMETHEUS_PORT) ? config + .getInt(Constant.METRICS_PROMETHEUS_PORT) : 9527; + // lite fullnode params PARAMETER.setLiteFullNode(checkIsLiteFullNode()); PARAMETER.setOpenHistoryQueryWhenLiteFN( diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 9919d99c428..ca1537577d0 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -9,6 +9,7 @@ import com.google.common.collect.Lists; import com.google.common.primitives.Longs; import com.google.protobuf.ByteString; +import io.prometheus.client.Histogram; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -61,12 +62,16 @@ import org.tron.common.logsfilter.trigger.Trigger; import org.tron.common.overlay.message.Message; import org.tron.common.parameter.CommonParameter; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; import org.tron.common.runtime.RuntimeImpl; import org.tron.common.utils.ByteArray; import org.tron.common.utils.JsonUtil; import org.tron.common.utils.Pair; import org.tron.common.utils.SessionOptional; import org.tron.common.utils.Sha256Hash; +import org.tron.common.utils.StringUtil; import org.tron.common.zksnark.MerkleContainer; import org.tron.consensus.Consensus; import org.tron.consensus.base.Param.Miner; @@ -231,6 +236,9 @@ public class Manager { @Getter private volatile long latestSolidityNumShutDown; + @Getter + private final ThreadLocal blockedTimer = new ThreadLocal<>(); + /** * Cycle thread to rePush Transactions */ @@ -250,9 +258,14 @@ public class Manager { Thread.currentThread().interrupt(); } logger.error("unknown exception happened in rePush loop", ex); - } finally { if (tx != null) { - getRePushTransactions().remove(tx); + Metrics.counterInc(MetricKeys.Counter.TXS, 1, + MetricLabels.Counter.TXS_FAIL, MetricLabels.Counter.TXS_FAIL_ERROR); + } + } finally { + if (tx != null && getRePushTransactions().remove(tx)) { + Metrics.gaugeInc(MetricKeys.Gauge.MANAGER_QUEUE, -1, + MetricLabels.Gauge.QUEUE_REPUSH); } } } @@ -734,7 +747,8 @@ public boolean pushTransaction(final TransactionCapsule trx) } pushTransactionQueue.add(trx); - + Metrics.gaugeInc(MetricKeys.Gauge.MANAGER_QUEUE, 1, + MetricLabels.Gauge.QUEUE_QUEUED); try { if (!trx.validateSignature(chainBaseManager.getAccountStore(), chainBaseManager.getDynamicPropertiesStore())) { @@ -754,6 +768,8 @@ public boolean pushTransaction(final TransactionCapsule trx) processTransaction(trx, null); trx.setTrxTrace(null); pendingTransactions.add(trx); + Metrics.gaugeInc(MetricKeys.Gauge.MANAGER_QUEUE, 1, + MetricLabels.Gauge.QUEUE_PENDING); tmpSession.merge(); } if (isShieldedTransaction(trx.getInstance())) { @@ -761,7 +777,10 @@ public boolean pushTransaction(final TransactionCapsule trx) } } } finally { - pushTransactionQueue.remove(trx); + if (pushTransactionQueue.remove(trx)) { + Metrics.gaugeInc(MetricKeys.Gauge.MANAGER_QUEUE, -1, + MetricLabels.Gauge.QUEUE_QUEUED); + } } return true; } @@ -816,6 +835,8 @@ public synchronized void eraseBlock() { revokingStore.fastPop(); logger.info("end to erase block:" + oldHeadBlock); poppedTransactions.addAll(oldHeadBlock.getTransactions()); + Metrics.gaugeInc(MetricKeys.Gauge.MANAGER_QUEUE, oldHeadBlock.getTransactions().size(), + MetricLabels.Gauge.QUEUE_POPPED); } catch (ItemNotFoundException | BadItemException e) { logger.warn(e.getMessage(), e); @@ -888,6 +909,7 @@ private void switchFork(BlockCapsule newHead) VMIllegalException, ZksnarkException, BadBlockException, EventBloomException { MetricsUtil.meterMark(MetricsKey.BLOCKCHAIN_FORK_COUNT); + Metrics.counterInc(MetricKeys.Counter.BLOCK_FORK, 1, MetricLabels.ALL); Pair, LinkedList> binaryTree; try { @@ -895,6 +917,7 @@ private void switchFork(BlockCapsule newHead) khaosDb.getBranch( newHead.getBlockId(), getDynamicPropertiesStore().getLatestBlockHeaderHash()); } catch (NonCommonBlockException e) { + Metrics.counterInc(MetricKeys.Counter.BLOCK_FORK, 1, MetricLabels.FAIL); MetricsUtil.meterMark(MetricsKey.BLOCKCHAIN_FAIL_FORK_COUNT); logger.info( "this is not the most recent common ancestor, " @@ -946,6 +969,7 @@ private void switchFork(BlockCapsule newHead) throw e; } finally { if (exception != null) { + Metrics.counterInc(MetricKeys.Counter.BLOCK_FORK, 1, MetricLabels.FAIL); MetricsUtil.meterMark(MetricsKey.BLOCKCHAIN_FAIL_FORK_COUNT); logger.warn("switch back because exception thrown while switching forks. " + exception .getMessage(), @@ -1031,6 +1055,10 @@ public synchronized void pushBlock(final BlockCapsule block) DupTransactionException, TransactionExpirationException, BadNumberBlockException, BadBlockException, NonCommonBlockException, ReceiptCheckErrException, VMIllegalException, ZksnarkException, EventBloomException { + Metrics.histogramObserve(blockedTimer.get()); + blockedTimer.remove(); + final Histogram.Timer timer = Metrics.histogramStartTimer( + MetricKeys.Histogram.BLOCK_PUSH_LATENCY); long start = System.currentTimeMillis(); List txs = getVerifyTxs(block); logger.info("Block num: {}, re-push-size: {}, pending-size: {}, " @@ -1176,6 +1204,7 @@ public synchronized void pushBlock(final BlockCapsule block) block.getNum(), System.currentTimeMillis() - start, block.getTransactions().size()); + Metrics.histogramObserve(timer); } public void updateDynamicProperties(BlockCapsule block) { @@ -1195,6 +1224,8 @@ public void updateDynamicProperties(BlockCapsule block) { (chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() - chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum() + 1)); + Metrics.gaugeSet(MetricKeys.Gauge.HEADER_HEIGHT, block.getNum()); + Metrics.gaugeSet(MetricKeys.Gauge.HEADER_TIME, block.getTimeStamp()); } /** @@ -1234,6 +1265,13 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block if (trxCap == null) { return null; } + long start = System.currentTimeMillis(); + Contract contract = trxCap.getInstance().getRawData().getContract(0); + + final Histogram.Timer requestTimer = Metrics.histogramStartTimer( + MetricKeys.Histogram.PROCESS_TRANSACTION_LATENCY, + Objects.nonNull(blockCap) ? MetricLabels.BLOCK : MetricLabels.TRX, + contract.getType().name()); if (Objects.nonNull(blockCap)) { chainBaseManager.getBalanceTraceStore().initCurrentTransactionBalanceTrace(trxCap); @@ -1302,7 +1340,7 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block postContractTrigger(trace, false, blockHash); } - Contract contract = trxCap.getInstance().getRawData().getContract(0); + if (isMultiSignTransaction(trxCap.getInstance())) { ownerAddressSet.add(ByteArray.toHexString(TransactionCapsule.getOwner(contract))); } @@ -1318,6 +1356,10 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block if (!eventPluginLoaded) { trxCap.setTrxTrace(null); } + Metrics.histogramObserve(requestTimer); + if (System.currentTimeMillis() - start >= 200) { + logger.info("Contract:{},trx:{}", contract.getType().name(), trxCap.getTransactionId()); + } return transactionInfo.getInstance(); } @@ -1325,8 +1367,13 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block * Generate a block. */ public synchronized BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { - + String address = StringUtil.encode58Check(miner.getWitnessAddress().toByteArray()); + final Histogram.Timer timer = Metrics.histogramStartTimer( + MetricKeys.Histogram.BLOCK_GENERATE_LATENCY, address); + Metrics.histogramObserve(MetricKeys.Histogram.MINER_LATENCY, + (System.currentTimeMillis() - blockTime) / Metrics.MILLISECONDS_PER_SECOND, address); long postponedTrxCount = 0; + logger.info("Generate block {} begin", chainBaseManager.getHeadBlockNum() + 1); BlockCapsule blockCapsule = new BlockCapsule(chainBaseManager.getHeadBlockNum() + 1, chainBaseManager.getHeadBlockId(), @@ -1362,12 +1409,16 @@ public synchronized BlockCapsule generateBlock(Miner miner, long blockTime, long fromPending = true; } else { trx = rePushTransactions.poll(); + Metrics.gaugeInc(MetricKeys.Gauge.MANAGER_QUEUE, -1, + MetricLabels.Gauge.QUEUE_REPUSH); } } else { fromPending = true; } } else { trx = rePushTransactions.poll(); + Metrics.gaugeInc(MetricKeys.Gauge.MANAGER_QUEUE, -1, + MetricLabels.Gauge.QUEUE_REPUSH); } if (System.currentTimeMillis() > timeout) { @@ -1412,6 +1463,8 @@ public synchronized BlockCapsule generateBlock(Miner miner, long blockTime, long } if (fromPending) { pendingTransactions.poll(); + Metrics.gaugeInc(MetricKeys.Gauge.MANAGER_QUEUE, -1, + MetricLabels.Gauge.QUEUE_PENDING); } } catch (Exception e) { logger.error("Process trx {} failed when generating block: {}", trx.getTransactionId(), @@ -1423,8 +1476,9 @@ public synchronized BlockCapsule generateBlock(Miner miner, long blockTime, long session.reset(); - logger.info("Generate block {} success, pendingCount: {}, rePushCount: {}, postponedCount: {}", - blockCapsule.getNum(), + logger.info("Generate block {} success, trxs:{}, pendingCount: {}, rePushCount: {}," + + " postponedCount: {}", + blockCapsule.getNum(), blockCapsule.getTransactions().size(), pendingTransactions.size(), rePushTransactions.size(), postponedTrxCount); blockCapsule.setMerkleRoot(); @@ -1432,6 +1486,7 @@ public synchronized BlockCapsule generateBlock(Miner miner, long blockTime, long BlockCapsule capsule = new BlockCapsule(blockCapsule.getInstance()); capsule.generatedByMyself = true; + Metrics.histogramObserve(timer); return capsule; } @@ -1742,22 +1797,28 @@ private void preValidateTransactionSign(List txs) if (transSize <= 0) { return; } - CountDownLatch countDownLatch = new CountDownLatch(transSize); - List> futures = new ArrayList<>(transSize); + Histogram.Timer requestTimer = Metrics.histogramStartTimer( + MetricKeys.Histogram.VERIFY_SIGN_LATENCY, MetricLabels.TRX); + try { + CountDownLatch countDownLatch = new CountDownLatch(transSize); + List> futures = new ArrayList<>(transSize); - for (TransactionCapsule transaction : txs) { - Future future = validateSignService - .submit(new ValidateSignTask(transaction, countDownLatch, chainBaseManager)); - futures.add(future); - } - countDownLatch.await(); + for (TransactionCapsule transaction : txs) { + Future future = validateSignService + .submit(new ValidateSignTask(transaction, countDownLatch, chainBaseManager)); + futures.add(future); + } + countDownLatch.await(); - for (Future future : futures) { - try { - future.get(); - } catch (ExecutionException e) { - throw new ValidateSignatureException(e.getCause().getMessage()); + for (Future future : futures) { + try { + future.get(); + } catch (ExecutionException e) { + throw new ValidateSignatureException(e.getCause().getMessage()); + } } + } finally { + Metrics.histogramObserve(requestTimer); } } diff --git a/framework/src/main/java/org/tron/core/db/PendingManager.java b/framework/src/main/java/org/tron/core/db/PendingManager.java index 9048925dda3..928b17ef03f 100644 --- a/framework/src/main/java/org/tron/core/db/PendingManager.java +++ b/framework/src/main/java/org/tron/core/db/PendingManager.java @@ -2,6 +2,9 @@ import java.util.Iterator; import lombok.extern.slf4j.Slf4j; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.config.args.Args; @@ -23,8 +26,14 @@ public void close() { long now = System.currentTimeMillis(); Iterator iterator = dbManager.getRePushTransactions().iterator(); while (iterator.hasNext()) { - if (now - iterator.next().getTime() > timeout) { + TransactionCapsule tx = iterator.next(); + if (now - tx.getTime() > timeout) { iterator.remove(); + metric(-1, MetricLabels.Gauge.QUEUE_REPUSH); + metric(1, MetricLabels.Counter.TXS_FAIL_TIMEOUT); + if (Args.getInstance().isOpenPrintLog()) { + logger.warn("[timeout] remove tx from repush, txId:{}", tx.getTransactionId()); + } } } @@ -33,26 +42,41 @@ public void close() { } dbManager.getPendingTransactions().clear(); + Metrics.gaugeSet(MetricKeys.Gauge.MANAGER_QUEUE, 0, + MetricLabels.Gauge.QUEUE_PENDING); for (TransactionCapsule tx : dbManager.getPoppedTransactions()) { tx.setTime(System.currentTimeMillis()); txIteration(tx); } dbManager.getPoppedTransactions().clear(); + Metrics.gaugeSet(MetricKeys.Gauge.MANAGER_QUEUE, 0, + MetricLabels.Gauge.QUEUE_POPPED); if (Args.getInstance().isOpenPrintLog()) { logger.warn("pending tx size:{}", dbManager.getRePushTransactions().size()); } + } private void txIteration(TransactionCapsule tx) { try { if (System.currentTimeMillis() - tx.getTime() < timeout) { dbManager.getRePushTransactions().put(tx); - } else if (Args.getInstance().isOpenPrintLog()) { - logger.warn("[timeout] remove tx from pending, txId:{}", tx.getTransactionId()); + metric(1, MetricLabels.Gauge.QUEUE_REPUSH); + } else { + metric(1, MetricLabels.Counter.TXS_FAIL_TIMEOUT); + if (Args.getInstance().isOpenPrintLog()) { + logger.warn("[timeout] remove tx from pending, txId:{}", tx.getTransactionId()); + } } } catch (InterruptedException e) { logger.error(e.getMessage()); Thread.currentThread().interrupt(); } } + + private void metric(long amt, String failType) { + Metrics.counterInc(MetricKeys.Counter.TXS, amt, + MetricLabels.Counter.TXS_FAIL, failType); + } + } diff --git a/framework/src/main/java/org/tron/core/db/accountstate/storetrie/AccountStateStoreTrie.java b/framework/src/main/java/org/tron/core/db/accountstate/storetrie/AccountStateStoreTrie.java index 84f619a3efc..811b96c15a0 100644 --- a/framework/src/main/java/org/tron/core/db/accountstate/storetrie/AccountStateStoreTrie.java +++ b/framework/src/main/java/org/tron/core/db/accountstate/storetrie/AccountStateStoreTrie.java @@ -70,4 +70,10 @@ public void put(byte[] key, BytesCapsule item) { public DB newInstance() { return null; } + + @Override + public void stat() { + + } + } diff --git a/framework/src/main/java/org/tron/core/metrics/blockchain/BlockChainMetricManager.java b/framework/src/main/java/org/tron/core/metrics/blockchain/BlockChainMetricManager.java index 21d6939cfc9..384f1d8add1 100644 --- a/framework/src/main/java/org/tron/core/metrics/blockchain/BlockChainMetricManager.java +++ b/framework/src/main/java/org/tron/core/metrics/blockchain/BlockChainMetricManager.java @@ -12,6 +12,10 @@ import org.bouncycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; +import org.tron.common.utils.StringUtil; import org.tron.core.ChainBaseManager; import org.tron.core.capsule.BlockCapsule; import org.tron.core.db.Manager; @@ -126,7 +130,8 @@ public Protocol.MetricsInfo.BlockChainInfo getBlockChainProtoInfo() { */ public void applyBlock(BlockCapsule block) { long nowTime = System.currentTimeMillis(); - String witnessAddress = Hex.toHexString(block.getWitnessAddress().toByteArray()); + byte[] address = block.getWitnessAddress().toByteArray(); + String witnessAddress = Hex.toHexString(address); //witness info if (witnessInfo.containsKey(witnessAddress)) { @@ -134,6 +139,8 @@ public void applyBlock(BlockCapsule block) { if ((!oldBlock.getBlockId().equals(block.getBlockId())) && oldBlock.getTimeStamp() == block.getTimeStamp()) { MetricsUtil.counterInc(MetricsKey.BLOCKCHAIN_DUP_WITNESS + witnessAddress); + Metrics.counterInc(MetricKeys.Counter.MINER, 1, + StringUtil.encode58Check(address), MetricLabels.Counter.MINE_DUP); dupWitnessBlockNum.put(witnessAddress, block.getNum()); } } @@ -141,6 +148,8 @@ public void applyBlock(BlockCapsule block) { //latency long netTime = nowTime - block.getTimeStamp(); + Metrics.histogramObserve(MetricKeys.Histogram.MINER_LATENCY, + netTime / Metrics.MILLISECONDS_PER_SECOND, StringUtil.encode58Check(address)); MetricsUtil.histogramUpdate(MetricsKey.NET_LATENCY, netTime); MetricsUtil.histogramUpdate(MetricsKey.NET_LATENCY_WITNESS + witnessAddress, netTime); if (netTime >= 3000) { @@ -157,6 +166,8 @@ public void applyBlock(BlockCapsule block) { //TPS if (block.getTransactions().size() > 0) { MetricsUtil.meterMark(MetricsKey.BLOCKCHAIN_TPS, block.getTransactions().size()); + Metrics.counterInc(MetricKeys.Counter.TXS, block.getTransactions().size(), + MetricLabels.Counter.TXS_SUCCESS, MetricLabels.Counter.TXS_SUCCESS); } } diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index 16ad677fba0..f0a75191c05 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -2,6 +2,7 @@ import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; +import io.prometheus.client.Histogram; import java.util.Collection; import java.util.List; import java.util.Queue; @@ -18,6 +19,9 @@ import org.tron.common.overlay.message.Message; import org.tron.common.overlay.server.ChannelManager; import org.tron.common.overlay.server.SyncPool; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; import org.tron.common.utils.Sha256Hash; import org.tron.core.ChainBaseManager; import org.tron.core.capsule.BlockCapsule; @@ -248,7 +252,12 @@ public void processBlock(BlockCapsule block, boolean isSync) throws P2pException //record metrics metricsService.applyBlock(block); } + dbManager.getBlockedTimer().set(Metrics.histogramStartTimer( + MetricKeys.Histogram.LOCK_ACQUIRE_LATENCY, MetricLabels.BLOCK)); + Histogram.Timer timer = Metrics.histogramStartTimer( + MetricKeys.Histogram.BLOCK_PROCESS_LATENCY, String.valueOf(isSync)); dbManager.pushBlock(block); + Metrics.histogramObserve(timer); freshBlockId.add(blockId); logger.info("Success process block {}.", blockId.getString()); if (!backupServerStartFlag diff --git a/framework/src/main/java/org/tron/core/services/NodeInfoService.java b/framework/src/main/java/org/tron/core/services/NodeInfoService.java index 8e011724774..acf7a29d052 100644 --- a/framework/src/main/java/org/tron/core/services/NodeInfoService.java +++ b/framework/src/main/java/org/tron/core/services/NodeInfoService.java @@ -24,6 +24,7 @@ import org.tron.common.overlay.discover.node.NodeManager; import org.tron.common.overlay.server.SyncPool; import org.tron.common.parameter.CommonParameter; +import org.tron.common.prometheus.MetricTime; import org.tron.core.ChainBaseManager; import org.tron.core.db.Manager; import org.tron.core.net.peer.PeerConnection; @@ -56,6 +57,7 @@ public class NodeInfoService { @Autowired private WitnessProductBlockService witnessProductBlockService; + @MetricTime public NodeInfo getNodeInfo() { NodeInfo nodeInfo = new NodeInfo(); setConnectInfo(nodeInfo); diff --git a/framework/src/main/java/org/tron/core/services/filter/CharResponseWrapper.java b/framework/src/main/java/org/tron/core/services/filter/CharResponseWrapper.java index 44b2b40eec4..db43c0bbc74 100644 --- a/framework/src/main/java/org/tron/core/services/filter/CharResponseWrapper.java +++ b/framework/src/main/java/org/tron/core/services/filter/CharResponseWrapper.java @@ -7,7 +7,7 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; -class CharResponseWrapper extends HttpServletResponseWrapper { +public class CharResponseWrapper extends HttpServletResponseWrapper { private ServletOutputStream outputStream; private PrintWriter writer; diff --git a/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java b/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java index e0f65fa09ba..1d8e1a3d628 100644 --- a/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java @@ -1,5 +1,7 @@ package org.tron.core.services.http; +import com.google.common.base.Strings; +import io.prometheus.client.Histogram; import java.io.IOException; import java.lang.reflect.Constructor; import javax.annotation.PostConstruct; @@ -10,7 +12,11 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.tron.common.parameter.RateLimiterInitialization; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; import org.tron.core.config.args.Args; +import org.tron.core.services.filter.CharResponseWrapper; import org.tron.core.services.ratelimiter.RateLimiterContainer; import org.tron.core.services.ratelimiter.RuntimeData; import org.tron.core.services.ratelimiter.adapter.DefaultBaseQqsAdapter; @@ -98,7 +104,15 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) resp.setContentType("application/json; charset=utf-8"); if (acquireResource) { + String url = Strings.isNullOrEmpty(req.getRequestURI()) + ? MetricLabels.UNDEFINED : req.getRequestURI(); + Histogram.Timer requestTimer = Metrics.histogramStartTimer( + MetricKeys.Histogram.HTTP_SERVICE_LATENCY, url); super.service(req, resp); + Metrics.histogramObserve(requestTimer); + Metrics.histogramObserve(MetricKeys.Histogram.HTTP_BYTES, + ((CharResponseWrapper) resp).getByteSize(), + url, String.valueOf(resp.getStatus())); } else { resp.getWriter() .println(Util.printErrorMsg(new IllegalAccessException("lack of computing resources"))); diff --git a/framework/src/main/java/org/tron/core/services/ratelimiter/RpcApiAccessInterceptor.java b/framework/src/main/java/org/tron/core/services/ratelimiter/RpcApiAccessInterceptor.java index c3471c2829c..8b5812129a2 100644 --- a/framework/src/main/java/org/tron/core/services/ratelimiter/RpcApiAccessInterceptor.java +++ b/framework/src/main/java/org/tron/core/services/ratelimiter/RpcApiAccessInterceptor.java @@ -6,10 +6,13 @@ import io.grpc.ServerCallHandler; import io.grpc.ServerInterceptor; import io.grpc.Status; +import io.prometheus.client.Histogram; import java.util.List; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.tron.common.parameter.CommonParameter; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.Metrics; @Slf4j @Component @@ -29,7 +32,11 @@ public Listener interceptCall(ServerCall call, return new ServerCall.Listener() {}; } else { - return next.startCall(call, headers); + Histogram.Timer requestTimer = Metrics.histogramStartTimer( + MetricKeys.Histogram.GRPC_SERVICE_LATENCY, endpoint); + Listener res = next.startCall(call, headers); + Metrics.histogramObserve(requestTimer); + return res; } } catch (Exception e) { logger.error("check rpc api access Error: {}", e.getMessage()); diff --git a/framework/src/main/java/org/tron/program/FullNode.java b/framework/src/main/java/org/tron/program/FullNode.java index 25de4259a00..03a0eef8e72 100644 --- a/framework/src/main/java/org/tron/program/FullNode.java +++ b/framework/src/main/java/org/tron/program/FullNode.java @@ -10,6 +10,7 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.parameter.CommonParameter; +import org.tron.common.prometheus.Metrics; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; @@ -67,6 +68,9 @@ public static void main(String[] args) { logger.info("not in debug mode, it will check energy time"); } + // init metrics first + Metrics.init(); + DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); beanFactory.setAllowCircularReferences(false); TronApplicationContext context = diff --git a/framework/src/main/java/org/tron/program/SolidityNode.java b/framework/src/main/java/org/tron/program/SolidityNode.java index 6f7cee90870..e0c1fcaa231 100644 --- a/framework/src/main/java/org/tron/program/SolidityNode.java +++ b/framework/src/main/java/org/tron/program/SolidityNode.java @@ -15,6 +15,7 @@ import org.tron.common.overlay.discover.DiscoverServer; import org.tron.common.overlay.discover.node.NodeManager; import org.tron.common.parameter.CommonParameter; +import org.tron.common.prometheus.Metrics; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; @@ -78,6 +79,9 @@ public static void main(String[] args) { logger.info("Here is the help message."); return; } + // init metrics first + Metrics.init(); + Application appT = ApplicationFactory.create(context); FullNode.shutdown(appT); diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 94908647938..e14680d6759 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -125,6 +125,15 @@ node.backup { crypto { engine = "eckey" } +# prometheus metrics start +#node.metrics = { +# prometheus{ +# enable=true +# port="9527" +# } +#} + +# prometheus metrics end node { # trust node for solidity node diff --git a/framework/src/main/resources/logback.xml b/framework/src/main/resources/logback.xml index c3986cee550..5f180be405b 100644 --- a/framework/src/main/resources/logback.xml +++ b/framework/src/main/resources/logback.xml @@ -50,6 +50,13 @@ + + + + + + + diff --git a/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java b/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java new file mode 100644 index 00000000000..dadc688e5bd --- /dev/null +++ b/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java @@ -0,0 +1,188 @@ +package org.tron.core.metrics.prometheus; + +import com.google.common.collect.Maps; +import com.google.protobuf.ByteString; +import io.prometheus.client.CollectorRegistry; +import java.io.File; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import lombok.extern.slf4j.Slf4j; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.crypto.ECKey; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.Sha256Hash; +import org.tron.common.utils.Utils; +import org.tron.consensus.dpos.DposSlot; +import org.tron.core.ChainBaseManager; +import org.tron.core.Constant; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.WitnessCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.consensus.ConsensusService; +import org.tron.core.db.BlockGenerate; +import org.tron.core.db.Manager; +import org.tron.core.net.TronNetDelegate; +import org.tron.protos.Protocol; + +@Slf4j(topic = "metric") +public class PrometheusApiServiceTest extends BlockGenerate { + + + static ChainBaseManager chainManager; + static LocalDateTime localDateTime = LocalDateTime.now(); + private static DposSlot dposSlot; + final int blocks = 512; + private final String key = "f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62"; + private final byte[] privateKey = ByteArray.fromHexString(key); + private final AtomicInteger port = new AtomicInteger(0); + private final long time = ZonedDateTime.of(localDateTime, + ZoneId.systemDefault()).toInstant().toEpochMilli(); + protected String dbPath; + protected String dbEngine; + protected Manager dbManager; + private TronNetDelegate tronNetDelegate; + private TronApplicationContext context; + + protected void initParameter(CommonParameter parameter) { + parameter.setMetricsPrometheusEnable(true); + } + + protected void check() throws Exception { + Double memoryBytes = CollectorRegistry.defaultRegistry.getSampleValue( + "system_total_physical_memory_bytes"); + Assert.assertNotNull(memoryBytes); + Assert.assertTrue(memoryBytes.intValue() > 0); + + Double cpus = CollectorRegistry.defaultRegistry.getSampleValue("system_available_cpus"); + Assert.assertNotNull(cpus); + Assert.assertEquals(cpus.intValue(), Runtime.getRuntime().availableProcessors()); + + Double pushBlock = CollectorRegistry.defaultRegistry.getSampleValue( + "tron:block_process_latency_seconds_count", + new String[] {"sync"}, new String[] {"false"}); + Assert.assertNotNull(pushBlock); + Assert.assertEquals(pushBlock.intValue(), blocks + 1); + Double errorLogs = CollectorRegistry.defaultRegistry.getSampleValue( + "tron:error_info_total", new String[] {"net"}, new String[] {MetricLabels.UNDEFINED}); + Assert.assertNull(errorLogs); + } + + protected void initDb() { + dbPath = "output-prometheus-metric"; + dbEngine = "LEVELDB"; + } + + + @Before + public void init() throws Exception { + + initDb(); + FileUtil.deleteDir(new File(dbPath)); + logger.info("Full node running."); + Args.setParam(new String[] {"-d", dbPath, "-w"}, Constant.TEST_CONF); + Args.getInstance().setNodeListenPort(10000 + port.incrementAndGet()); + initParameter(Args.getInstance()); + Metrics.init(); + context = new TronApplicationContext(DefaultConfig.class); + + dbManager = context.getBean(Manager.class); + setManager(dbManager); + dposSlot = context.getBean(DposSlot.class); + ConsensusService consensusService = context.getBean(ConsensusService.class); + consensusService.start(); + chainManager = dbManager.getChainBaseManager(); + tronNetDelegate = context.getBean(TronNetDelegate.class); + } + + @After + public void destroy() { + Args.clearParam(); + context.destroy(); + FileUtil.deleteDir(new File(dbPath)); + } + + private void generateBlock(Map witnessAndAccount) throws Exception { + + BlockCapsule block = + createTestBlockCapsule( + chainManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp() + 3000, + chainManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() + 1, + chainManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(), + witnessAndAccount); + + tronNetDelegate.processBlock(block, false); + } + + @Test + public void testMetric() throws Exception { + + final ECKey ecKey = ECKey.fromPrivate(privateKey); + Assert.assertNotNull(ecKey); + byte[] address = ecKey.getAddress(); + WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address)); + chainManager.getWitnessScheduleStore().saveActiveWitnesses(new ArrayList<>()); + chainManager.addWitness(ByteString.copyFrom(address)); + + Protocol.Block block = getSignedBlock(witnessCapsule.getAddress(), time, privateKey); + + tronNetDelegate.processBlock(new BlockCapsule(block), false); + + Map witnessAndAccount = addTestWitnessAndAccount(); + witnessAndAccount.put(ByteString.copyFrom(address), key); + for (int i = 0; i < blocks; i++) { + generateBlock(witnessAndAccount); + } + check(); + } + + private Map addTestWitnessAndAccount() { + chainManager.getWitnesses().clear(); + return IntStream.range(0, 2) + .mapToObj( + i -> { + ECKey ecKey = new ECKey(Utils.getRandom()); + String privateKey = ByteArray.toHexString(ecKey.getPrivKey().toByteArray()); + ByteString address = ByteString.copyFrom(ecKey.getAddress()); + + WitnessCapsule witnessCapsule = new WitnessCapsule(address); + chainManager.getWitnessStore().put(address.toByteArray(), witnessCapsule); + chainManager.addWitness(address); + + AccountCapsule accountCapsule = + new AccountCapsule(Protocol.Account.newBuilder().setAddress(address).build()); + chainManager.getAccountStore().put(address.toByteArray(), accountCapsule); + + return Maps.immutableEntry(address, privateKey); + }) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + private BlockCapsule createTestBlockCapsule(long time, + long number, ByteString hash, + Map witnessAddressMap) { + ByteString witnessAddress = dposSlot.getScheduledWitness(dposSlot.getSlot(time)); + BlockCapsule blockCapsule = new BlockCapsule(number, Sha256Hash.wrap(hash), time, + witnessAddress); + blockCapsule.generatedByMyself = true; + blockCapsule.setMerkleRoot(); + blockCapsule.sign(ByteArray.fromHexString(witnessAddressMap.get(witnessAddress))); + return blockCapsule; + } + +} \ No newline at end of file From 8fa889f5c5799c351af62b05ab1cec9986a1a2c9 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 13 May 2022 22:42:03 +0800 Subject: [PATCH 0063/1197] feat(metrics): fix sonar code smell. --- .../main/java/org/tron/core/ChainBaseManager.java | 2 +- .../main/java/org/tron/core/db/TronDatabase.java | 2 +- .../org/tron/core/db/TronStoreWithRevoking.java | 2 +- .../common/prometheus/InstrumentedAppender.java | 14 ++++++-------- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java index 0a746e6b410..188656738a2 100644 --- a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java +++ b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java @@ -227,7 +227,7 @@ public class ChainBaseManager { private SectionBloomStore sectionBloomStore; @Autowired - DbStatService dbStatService; + private DbStatService dbStatService; public void closeOneStore(ITronChainBase database) { logger.info("******** begin to close " + database.getName() + " ********"); diff --git a/chainbase/src/main/java/org/tron/core/db/TronDatabase.java b/chainbase/src/main/java/org/tron/core/db/TronDatabase.java index ad3e7b4fd67..5ff2904bcbf 100644 --- a/chainbase/src/main/java/org/tron/core/db/TronDatabase.java +++ b/chainbase/src/main/java/org/tron/core/db/TronDatabase.java @@ -27,7 +27,7 @@ public abstract class TronDatabase implements ITronChainBase { private String dbName; @Autowired - DbStatService dbStatService; + private DbStatService dbStatService; protected TronDatabase(String dbName) { this.dbName = dbName; diff --git a/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java b/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java index b44a79e97f8..1b327642212 100644 --- a/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java +++ b/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java @@ -49,7 +49,7 @@ public abstract class TronStoreWithRevoking implements I private RevokingDatabase revokingDatabase; @Autowired - DbStatService dbStatService; + private DbStatService dbStatService; private DB db; diff --git a/common/src/main/java/org/tron/common/prometheus/InstrumentedAppender.java b/common/src/main/java/org/tron/common/prometheus/InstrumentedAppender.java index 8eff4815103..33301371c3e 100644 --- a/common/src/main/java/org/tron/common/prometheus/InstrumentedAppender.java +++ b/common/src/main/java/org/tron/common/prometheus/InstrumentedAppender.java @@ -18,15 +18,13 @@ public class InstrumentedAppender extends UnsynchronizedAppenderBase Date: Fri, 13 May 2022 23:19:58 +0800 Subject: [PATCH 0064/1197] feat(metrics): fix repush metric. --- .../java/org/tron/core/db/PendingManager.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/PendingManager.java b/framework/src/main/java/org/tron/core/db/PendingManager.java index 928b17ef03f..2098ed2178b 100644 --- a/framework/src/main/java/org/tron/core/db/PendingManager.java +++ b/framework/src/main/java/org/tron/core/db/PendingManager.java @@ -29,8 +29,10 @@ public void close() { TransactionCapsule tx = iterator.next(); if (now - tx.getTime() > timeout) { iterator.remove(); - metric(-1, MetricLabels.Gauge.QUEUE_REPUSH); - metric(1, MetricLabels.Counter.TXS_FAIL_TIMEOUT); + Metrics.gaugeInc(MetricKeys.Gauge.MANAGER_QUEUE, -1, + MetricLabels.Gauge.QUEUE_REPUSH); + Metrics.counterInc(MetricKeys.Counter.TXS, 1, + MetricLabels.Counter.TXS_FAIL, MetricLabels.Counter.TXS_FAIL_TIMEOUT); if (Args.getInstance().isOpenPrintLog()) { logger.warn("[timeout] remove tx from repush, txId:{}", tx.getTransactionId()); } @@ -61,9 +63,11 @@ private void txIteration(TransactionCapsule tx) { try { if (System.currentTimeMillis() - tx.getTime() < timeout) { dbManager.getRePushTransactions().put(tx); - metric(1, MetricLabels.Gauge.QUEUE_REPUSH); + Metrics.gaugeInc(MetricKeys.Gauge.MANAGER_QUEUE, 1, + MetricLabels.Gauge.QUEUE_REPUSH); } else { - metric(1, MetricLabels.Counter.TXS_FAIL_TIMEOUT); + Metrics.counterInc(MetricKeys.Counter.TXS, 1, + MetricLabels.Counter.TXS_FAIL, MetricLabels.Counter.TXS_FAIL_TIMEOUT); if (Args.getInstance().isOpenPrintLog()) { logger.warn("[timeout] remove tx from pending, txId:{}", tx.getTransactionId()); } @@ -73,10 +77,4 @@ private void txIteration(TransactionCapsule tx) { Thread.currentThread().interrupt(); } } - - private void metric(long amt, String failType) { - Metrics.counterInc(MetricKeys.Counter.TXS, amt, - MetricLabels.Counter.TXS_FAIL, failType); - } - } From d2110c47712aa79b003937f0150f14e57ed14f3c Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Sat, 14 May 2022 00:51:01 +0800 Subject: [PATCH 0065/1197] feat(metrics): fix `trans-cache` db metric. --- chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java index 23c36779149..88adfaab00f 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java @@ -219,7 +219,7 @@ public TxCacheDB newInstance() { @Override public void stat() { - + this.persistentStore.stat(); } } From 0747912d84c927742bb115e7f142498b148aaaf9 Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 16 May 2022 09:31:47 +0800 Subject: [PATCH 0066/1197] func(proposal): add 65th network parameter --- .../org/tron/core/actuator/VMActuator.java | 2 +- .../org/tron/core/utils/ProposalUtil.java | 31 +++++++++++--- .../java/org/tron/core/vm/EnergyCost.java | 21 +++++++--- .../org/tron/core/vm/OperationRegistry.java | 41 +++++++++++++++---- .../org/tron/core/vm/config/ConfigLoader.java | 3 +- .../org/tron/core/vm/config/VMConfig.java | 13 +++++- .../org/tron/core/vm/program/Program.java | 4 +- .../core/store/DynamicPropertiesStore.java | 35 +++++++++++++--- .../common/parameter/CommonParameter.java | 4 ++ .../src/main/java/org/tron/core/Constant.java | 4 +- .../java/org/tron/core/config/Parameter.java | 3 +- .../src/main/java/org/tron/core/Wallet.java | 33 ++++++++------- .../java/org/tron/core/config/args/Args.java | 34 ++++++++------- .../tron/core/consensus/ProposalService.java | 6 ++- .../common/runtime/vm/OperationsTest.java | 2 +- 15 files changed, 174 insertions(+), 62 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index c14857572f4..10ae41f6327 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -173,7 +173,7 @@ public void execute(Object object) throws ContractExeException { throw e; } - VM.play(program, OperationRegistry.getTable(OperationRegistry.Version.TRON_V1)); + VM.play(program, OperationRegistry.getTable()); result = program.getResult(); if (TrxType.TRX_CONTRACT_CREATION_TYPE == trxType && !result.isRevert()) { diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 8ce040702c5..efa200d9c44 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -67,9 +67,16 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, case EXCHANGE_CREATE_FEE: break; case MAX_CPU_TIME_OF_ONE_TX: - if (value < 10 || value > 100) { - throw new ContractValidateException( - "Bad chain parameter value, valid range is [10,100]"); + if (dynamicPropertiesStore.getAllowHigherLimitForMaxCpuTimeOfOneTx() == 1) { + if (value < 10 || value > 400) { + throw new ContractValidateException( + "Bad chain parameter value, valid range is [10,400]"); + } + } else { + if (value < 10 || value > 100) { + throw new ContractValidateException( + "Bad chain parameter value, valid range is [10,100]"); + } } break; case ALLOW_UPDATE_ACCOUNT_NAME: { @@ -501,11 +508,11 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, case ALLOW_ACCOUNT_ASSET_OPTIMIZATION: { if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_3)) { throw new ContractValidateException( - "Bad chain parameter id [ALLOW_ACCOUNT_ASSET_OPTIMIZATION]"); + "Bad chain parameter id [ALLOW_ACCOUNT_ASSET_OPTIMIZATION]"); } if (value != 1) { throw new ContractValidateException( - "This value[ALLOW_ACCOUNT_ASSET_OPTIMIZATION] is only allowed to be 1"); + "This value[ALLOW_ACCOUNT_ASSET_OPTIMIZATION] is only allowed to be 1"); } break; } @@ -531,6 +538,17 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_5)) { + throw new ContractValidateException( + "Bad chain parameter id [ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX]"); + } + if (value != 1) { + throw new ContractValidateException( + "This value[ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX] is only allowed to be 1"); + } + break; + } default: break; } @@ -592,7 +610,8 @@ public enum ProposalType { // current value, value range ALLOW_TVM_COMPATIBLE_EVM(60), // 0, 1 FREE_NET_LIMIT(61), // 5000, [0, 100_000] TOTAL_NET_LIMIT(62), // 43_200_000_000L, [0, 1000_000_000_000L] - ALLOW_TVM_LONDON(63); // 0, 1 + ALLOW_TVM_LONDON(63), // 0, 1 + ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX(65); // 0, 1 private long code; diff --git a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java index 8962f5f1c64..8253e4bf7e6 100644 --- a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java +++ b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java @@ -150,28 +150,37 @@ public static long getExtCodeHashCost(Program ignored) { public static long getMloadCost(Program program) { Stack stack = program.getStack(); long oldMemSize = program.getMemSize(); - long energyCost = calcMemEnergy(oldMemSize, + return calcMemEnergy(oldMemSize, memNeeded(stack.peek(), new DataWord(32)), 0, Op.MLOAD); - return energyCost; + } + + public static long getMloadCost2(Program program) { + return SPECIAL_TIER + getMloadCost(program); } public static long getMStoreCost(Program program) { Stack stack = program.getStack(); long oldMemSize = program.getMemSize(); - long energyCost = calcMemEnergy(oldMemSize, + return calcMemEnergy(oldMemSize, memNeeded(stack.peek(), new DataWord(32)), 0, Op.MSTORE); - return energyCost; + } + + public static long getMStoreCost2(Program program) { + return SPECIAL_TIER + getMStoreCost(program); } public static long getMStore8Cost(Program program) { Stack stack = program.getStack(); long oldMemSize = program.getMemSize(); - long energyCost = calcMemEnergy(oldMemSize, + return calcMemEnergy(oldMemSize, memNeeded(stack.peek(), DataWord.ONE()), 0, Op.MSTORE8); - return energyCost; + } + + public static long getMStore8Cost2(Program program) { + return SPECIAL_TIER + getMStore8Cost(program); } public static long getSloadCost(Program ignored) { diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index 44b00e1a5a3..fb66f69d1e4 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -3,13 +3,13 @@ import java.util.HashMap; import java.util.Map; import java.util.function.BooleanSupplier; - import org.tron.core.vm.config.VMConfig; public class OperationRegistry { public enum Version { - TRON_V1, + TRON_V1_0, + TRON_V1_1, // add more // TRON_V2, // ETH @@ -18,10 +18,11 @@ public enum Version { private static final Map tableMap = new HashMap<>(); static { - tableMap.put(Version.TRON_V1, newTronV1OperationSet()); + tableMap.put(Version.TRON_V1_0, newTronV10OperationSet()); + tableMap.put(Version.TRON_V1_1, newTronV11OperationSet()); } - public static JumpTable newTronV1OperationSet() { + public static JumpTable newTronV10OperationSet() { JumpTable table = newBaseOperationSet(); appendTransferTrc10Operations(table); appendConstantinopleOperations(table); @@ -33,14 +34,24 @@ public static JumpTable newTronV1OperationSet() { return table; } + public static JumpTable newTronV11OperationSet() { + JumpTable table = newTronV10OperationSet(); + adjustMemOperations(table); + return table; + } + // Just for warming up class to avoid out_of_time - public static void init() {} + public static void init() { + } - public static JumpTable getTable(Version ver) { + public static JumpTable getTable() { // implement as needed // switch (tx.getType()) { // } - return tableMap.get(ver); + if (VMConfig.allowHigherLimitForMaxCpuTimeOfOneTx()) { + return tableMap.get(Version.TRON_V1_1); + } + return tableMap.get(Version.TRON_V1_0); } public static JumpTable newBaseOperationSet() { @@ -538,4 +549,20 @@ public static void appendLondonOperations(JumpTable table) { proposal)); } + public static void adjustMemOperations(JumpTable table) { + table.set(new Operation( + Op.MLOAD, 1, 1, + EnergyCost::getMloadCost2, + OperationActions::mLoadAction)); + + table.set(new Operation( + Op.MSTORE, 2, 0, + EnergyCost::getMStoreCost2, + OperationActions::mStoreAction)); + + table.set(new Operation( + Op.MSTORE8, 2, 0, + EnergyCost::getMStore8Cost2, + OperationActions::mStore8Action)); + } } diff --git a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java index 2a9cd42cf0a..71ff3cb92ed 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java +++ b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java @@ -28,7 +28,8 @@ public static void load(StoreFactory storeFactory) { VMConfig.initAllowTvmFreeze(ds.getAllowTvmFreeze()); VMConfig.initAllowTvmVote(ds.getAllowTvmVote()); VMConfig.initAllowTvmLondon(ds.getAllowTvmLondon()); - VMConfig.initAllowTvmCompatibleEvm(ds.getAllowTvmCompatibleEvm()); + VMConfig.initAllowHigherLimitForMaxCpuTimeOfOneTx( + ds.getAllowHigherLimitForMaxCpuTimeOfOneTx()); } } } diff --git a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java index 76eeb6199ba..aa7ca241df5 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java +++ b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java @@ -33,7 +33,10 @@ public class VMConfig { private static boolean ALLOW_TVM_COMPATIBLE_EVM = false; - private VMConfig() {} + private static boolean ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX = false; + + private VMConfig() { + } public static boolean vmTrace() { return vmTrace; @@ -87,6 +90,10 @@ public static void initAllowTvmCompatibleEvm(long allow) { ALLOW_TVM_COMPATIBLE_EVM = allow == 1; } + public static void initAllowHigherLimitForMaxCpuTimeOfOneTx(long allow) { + ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX = allow == 1; + } + public static boolean getEnergyLimitHardFork() { return CommonParameter.ENERGY_LIMIT_HARD_FORK; } @@ -130,4 +137,8 @@ public static boolean allowTvmLondon() { public static boolean allowTvmCompatibleEvm() { return ALLOW_TVM_COMPATIBLE_EVM; } + + public static boolean allowHigherLimitForMaxCpuTimeOfOneTx() { + return ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX; + } } diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index fc7e39554a1..7e60448e12f 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -650,7 +650,7 @@ this, new DataWord(newAddress), getContractAddress(), value, DataWord.ZERO(), if (VMConfig.allowTvmCompatibleEvm()) { program.setContractVersion(getContractVersion()); } - VM.play(program, OperationRegistry.getTable(OperationRegistry.Version.TRON_V1)); + VM.play(program, OperationRegistry.getTable()); createResult = program.getResult(); getTrace().merge(program.getTrace()); // always commit nonce @@ -882,7 +882,7 @@ this, new DataWord(contextAddress), program.setContractVersion(invoke.getDeposit() .getContract(codeAddress).getContractVersion()); } - VM.play(program, OperationRegistry.getTable(OperationRegistry.Version.TRON_V1)); + VM.play(program, OperationRegistry.getTable()); callResult = program.getResult(); getTrace().merge(program.getTrace()); diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 907d44a85aa..de8524eb3f1 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -169,6 +169,8 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ENERGY_PRICE_HISTORY_DONE = "ENERGY_PRICE_HISTORY_DONE".getBytes(); private static final byte[] SET_BLACKHOLE_ACCOUNT_PERMISSION = "SET_BLACKHOLE_ACCOUNT_PERMISSION".getBytes(); + private static final byte[] ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX = + "ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX".getBytes(); @Autowired @@ -742,7 +744,8 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { try { this.getAllowBlackHoleOptimization(); } catch (IllegalArgumentException e) { - this.saveAllowBlackHoleOptimization(CommonParameter.getInstance().getAllowBlackHoleOptimization()); + this.saveAllowBlackHoleOptimization( + CommonParameter.getInstance().getAllowBlackHoleOptimization()); } try { @@ -783,7 +786,7 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { this.getAllowAccountAssetOptimization(); } catch (IllegalArgumentException e) { this.setAllowAccountAssetOptimization(CommonParameter - .getInstance().getAllowAccountAssetOptimization()); + .getInstance().getAllowAccountAssetOptimization()); } try { @@ -803,6 +806,13 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { } catch (IllegalArgumentException e) { this.saveSetBlackholePermission(0); } + + try { + this.getAllowHigherLimitForMaxCpuTimeOfOneTx(); + } catch (IllegalArgumentException e) { + this.saveAllowHigherLimitForMaxCpuTimeOfOneTx( + CommonParameter.getInstance().getAllowHigherLimitForMaxCpuTimeOfOneTx()); + } } public String intArrayToString(int[] a) { @@ -2344,9 +2354,10 @@ public long getNewRewardAlgorithmEffectiveCycle() { // 1: enable public long getAllowAccountAssetOptimization() { return Optional.ofNullable(getUnchecked(ALLOW_ACCOUNT_ASSET_OPTIMIZATION)) - .map(BytesCapsule::getData) - .map(ByteArray::toLong) - .orElseThrow(() -> new IllegalArgumentException("not found ALLOW_ACCOUNT_ASSET_OPTIMIZATION")); + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException("not found ALLOW_ACCOUNT_ASSET_OPTIMIZATION")); } public void setAllowAccountAssetOptimization(long value) { @@ -2389,6 +2400,20 @@ public void saveSetBlackholePermission(long value) { this.put(SET_BLACKHOLE_ACCOUNT_PERMISSION, new BytesCapsule(ByteArray.fromLong(value))); } + public void saveAllowHigherLimitForMaxCpuTimeOfOneTx(long value) { + this.put(ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX, + new BytesCapsule(ByteArray.fromLong(value))); + } + + public long getAllowHigherLimitForMaxCpuTimeOfOneTx() { + String msg = "not found ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX"; + return Optional.ofNullable(getUnchecked(ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException(msg)); + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index d7a1fbd889a..14b10563632 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -488,6 +488,10 @@ public class CommonParameter { @Setter public long allowTvmCompatibleEvm; + @Getter + @Setter + public long allowHigherLimitForMaxCpuTimeOfOneTx; + @Getter @Setter public boolean openHistoryQueryWhenLiteFN = false; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 51801bebc32..88d4d94a7f5 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -282,6 +282,8 @@ public class Constant { public static final String COMMITTEE_ALLOW_TVM_LONDON = "committee.allowTvmLondon"; public static final String COMMITTEE_ALLOW_TVM_COMPATIBLE_EVM = "committee.allowTvmCompatibleEvm"; + public static final String COMMITTEE_ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX = + "committee.allowHigherLimitForMaxCpuTimeOfOneTx"; public static final String METRICS_STORAGE_ENABLE = "node.metrics.storageEnable"; public static final String METRICS_INFLUXDB_IP = "node.metrics.influxdb.ip"; @@ -293,7 +295,7 @@ public class Constant { public static final String OPEN_PRINT_LOG = "node.openPrintLog"; public static final String OPEN_TRANSACTION_SORT = "node.openTransactionSort"; - public static final String ALLOW_ACCOUNT_ASSET_OPTIMIZATION = "committee.allowAccountAssetOptimization"; + public static final String ALLOW_ACCOUNT_ASSET_OPTIMIZATION = "committee.allowAccountAssetOptimization"; public static final String LOCAL_HOST = "127.0.0.1"; } diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index 386289436f7..bb8c30ff5b1 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -17,7 +17,8 @@ public enum ForkBlockVersionEnum { VERSION_4_1_2(20, 1596780000000L, 80), VERSION_4_2(21, 1596780000000L, 80), VERSION_4_3(22, 1596780000000L, 80), - VERSION_4_4(23, 1596780000000L, 80); + VERSION_4_4(23, 1596780000000L, 80), + VERSION_4_5(24, 1596780000000L, 80); @Getter private int value; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index cf4d416e56c..7cf5c8c9e11 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1081,6 +1081,11 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getTotalNetLimit()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getAllowHigherLimitForMaxCpuTimeOfOneTx") + .setValue(dbManager.getDynamicPropertiesStore().getAllowHigherLimitForMaxCpuTimeOfOneTx()) + .build()); + return builder.build(); } @@ -2748,12 +2753,12 @@ public ProposalList getPaginatedProposalList(long offset, long limit) { .create(Range.openClosed(offset, end), DiscreteDomain.longs()) .asList(); rangeList.stream().map(ProposalCapsule::calculateDbKey).map(key -> { - try { - return chainBaseManager.getProposalStore().get(key); - } catch (Exception ex) { - return null; - } - }).filter(Objects::nonNull) + try { + return chainBaseManager.getProposalStore().get(key); + } catch (Exception ex) { + return null; + } + }).filter(Objects::nonNull) .forEach(proposalCapsule -> builder .addProposals(proposalCapsule.getInstance())); return builder.build(); @@ -2779,14 +2784,14 @@ public ExchangeList getPaginatedExchangeList(long offset, long limit) { .create(Range.openClosed(offset, end), DiscreteDomain.longs()) .asList(); rangeList.stream().map(ExchangeCapsule::calculateDbKey).map(key -> { - try { - return getExchangeStoreFinal(chainBaseManager.getDynamicPropertiesStore(), - chainBaseManager.getExchangeStore(), - chainBaseManager.getExchangeV2Store()).get(key); - } catch (Exception ex) { - return null; - } - }).filter(Objects::nonNull) + try { + return getExchangeStoreFinal(chainBaseManager.getDynamicPropertiesStore(), + chainBaseManager.getExchangeStore(), + chainBaseManager.getExchangeV2Store()).get(key); + } catch (Exception ex) { + return null; + } + }).filter(Objects::nonNull) .forEach(exchangeCapsule -> builder .addExchanges(exchangeCapsule.getInstance())); return builder.build(); diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 2cb768114cd..157a31bd746 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -657,7 +657,7 @@ public static void setParam(final String[] args, final String confFileName) { ? config.getInt(Constant.NODE_RPC_MIN_EFFECTIVE_CONNECTION) : 1; PARAMETER.trxCacheEnable = config.hasPath(Constant.NODE_RPC_TRX_CACHE_ENABLE) - && config.getBoolean(Constant.NODE_RPC_TRX_CACHE_ENABLE); + && config.getBoolean(Constant.NODE_RPC_TRX_CACHE_ENABLE); PARAMETER.blockNumForEnergyLimit = config.hasPath(Constant.ENERGY_LIMIT_BLOCK_NUM) ? config.getInt(Constant.ENERGY_LIMIT_BLOCK_NUM) : 4727890L; @@ -759,8 +759,8 @@ public static void setParam(final String[] args, final String confFileName) { } PARAMETER.allowTvmFreeze = - config.hasPath(Constant.COMMITTEE_ALLOW_TVM_FREEZE) ? config - .getInt(Constant.COMMITTEE_ALLOW_TVM_FREEZE) : 0; + config.hasPath(Constant.COMMITTEE_ALLOW_TVM_FREEZE) ? config + .getInt(Constant.COMMITTEE_ALLOW_TVM_FREEZE) : 0; PARAMETER.allowTvmVote = config.hasPath(Constant.COMMITTEE_ALLOW_TVM_VOTE) ? config @@ -774,9 +774,13 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.COMMITTEE_ALLOW_TVM_COMPATIBLE_EVM) ? config .getInt(Constant.COMMITTEE_ALLOW_TVM_COMPATIBLE_EVM) : 0; + PARAMETER.allowHigherLimitForMaxCpuTimeOfOneTx = + config.hasPath(Constant.COMMITTEE_ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX) ? config + .getInt(Constant.COMMITTEE_ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX) : 0; + initBackupProperty(config); if (Constant.ROCKSDB.equals(CommonParameter - .getInstance().getStorage().getDbEngine().toUpperCase())) { + .getInstance().getStorage().getDbEngine().toUpperCase())) { initRocksDbBackupProperty(config); initRocksDbSettings(config); } @@ -791,21 +795,21 @@ public static void setParam(final String[] args, final String confFileName) { } PARAMETER.metricsStorageEnable = config.hasPath(Constant.METRICS_STORAGE_ENABLE) && config - .getBoolean(Constant.METRICS_STORAGE_ENABLE); + .getBoolean(Constant.METRICS_STORAGE_ENABLE); PARAMETER.influxDbIp = config.hasPath(Constant.METRICS_INFLUXDB_IP) ? config - .getString(Constant.METRICS_INFLUXDB_IP) : Constant.LOCAL_HOST; + .getString(Constant.METRICS_INFLUXDB_IP) : Constant.LOCAL_HOST; PARAMETER.influxDbPort = config.hasPath(Constant.METRICS_INFLUXDB_PORT) ? config - .getInt(Constant.METRICS_INFLUXDB_PORT) : 8086; + .getInt(Constant.METRICS_INFLUXDB_PORT) : 8086; PARAMETER.influxDbDatabase = config.hasPath(Constant.METRICS_INFLUXDB_DATABASE) ? config - .getString(Constant.METRICS_INFLUXDB_DATABASE) : "metrics"; + .getString(Constant.METRICS_INFLUXDB_DATABASE) : "metrics"; PARAMETER.metricsReportInterval = config.hasPath(Constant.METRICS_REPORT_INTERVAL) ? config - .getInt(Constant.METRICS_REPORT_INTERVAL) : 10; + .getInt(Constant.METRICS_REPORT_INTERVAL) : 10; // lite fullnode params PARAMETER.setLiteFullNode(checkIsLiteFullNode()); PARAMETER.setOpenHistoryQueryWhenLiteFN( - config.hasPath(Constant.NODE_OPEN_HISTORY_QUERY_WHEN_LITEFN) - && config.getBoolean(Constant.NODE_OPEN_HISTORY_QUERY_WHEN_LITEFN)); + config.hasPath(Constant.NODE_OPEN_HISTORY_QUERY_WHEN_LITEFN) + && config.getBoolean(Constant.NODE_OPEN_HISTORY_QUERY_WHEN_LITEFN)); PARAMETER.historyBalanceLookup = config.hasPath(Constant.HISTORY_BALANCE_LOOKUP) && config .getBoolean(Constant.HISTORY_BALANCE_LOOKUP); @@ -818,8 +822,8 @@ public static void setParam(final String[] args, final String confFileName) { .getBoolean(Constant.OPEN_TRANSACTION_SORT); PARAMETER.allowAccountAssetOptimization = config - .hasPath(Constant.ALLOW_ACCOUNT_ASSET_OPTIMIZATION) ? config - .getInt(Constant.ALLOW_ACCOUNT_ASSET_OPTIMIZATION) : 0; + .hasPath(Constant.ALLOW_ACCOUNT_ASSET_OPTIMIZATION) ? config + .getInt(Constant.ALLOW_ACCOUNT_ASSET_OPTIMIZATION) : 0; PARAMETER.disabledApiList = config.hasPath(Constant.NODE_DISABLED_API_LIST) @@ -1183,7 +1187,7 @@ public static void setFullNodeAllowShieldedTransaction(boolean fullNodeAllowShie */ public static boolean checkIsLiteFullNode() { String infoFile = Paths.get(PARAMETER.outputDirectory, - PARAMETER.storage.getDbDirectory(), Constant.INFO_FILE_NAME).toString(); + PARAMETER.storage.getDbDirectory(), Constant.INFO_FILE_NAME).toString(); if (FileUtil.isExists(infoFile)) { String value = PropUtil.readProperty(infoFile, Constant.SPLIT_BLOCK_NUM); return !"".equals(value) && Long.parseLong(value) > 0; @@ -1204,7 +1208,7 @@ public String getOutputDirectory() { private static void witnessAddressCheck(Config config) { if (config.hasPath(Constant.LOCAL_WITNESS_ACCOUNT_ADDRESS)) { byte[] bytes = Commons - .decodeFromBase58Check(config.getString(Constant.LOCAL_WITNESS_ACCOUNT_ADDRESS)); + .decodeFromBase58Check(config.getString(Constant.LOCAL_WITNESS_ACCOUNT_ADDRESS)); if (bytes != null) { localWitnesses.setWitnessAccountAddress(bytes); logger.debug("Got localWitnessAccountAddress from config.conf"); diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index ad41472eacd..1803bb6811d 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -267,11 +267,15 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveTotalNetLimit(entry.getValue()); break; } - case ALLOW_ACCOUNT_ASSET_OPTIMIZATION: { manager.getDynamicPropertiesStore().setAllowAccountAssetOptimization(entry.getValue()); break; } + case ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX: { + manager.getDynamicPropertiesStore().saveAllowHigherLimitForMaxCpuTimeOfOneTx( + entry.getValue()); + break; + } default: find = false; break; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java index 11126a798d9..fe0b2cef0d6 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java @@ -31,7 +31,7 @@ public class OperationsTest { private ProgramInvokeMockImpl invoke; private Program program; - private final JumpTable jumpTable = OperationRegistry.newTronV1OperationSet(); + private final JumpTable jumpTable = OperationRegistry.newTronV10OperationSet(); @BeforeClass public static void init() { From 425bc092ee10f4884cd17e909e21687fec775d44 Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 16 May 2022 10:28:50 +0800 Subject: [PATCH 0067/1197] style(api): fix incorrect indents --- .../src/main/java/org/tron/core/Wallet.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 558eee84c59..12d749fee27 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2753,12 +2753,12 @@ public ProposalList getPaginatedProposalList(long offset, long limit) { .create(Range.openClosed(offset, end), DiscreteDomain.longs()) .asList(); rangeList.stream().map(ProposalCapsule::calculateDbKey).map(key -> { - try { - return chainBaseManager.getProposalStore().get(key); - } catch (Exception ex) { - return null; - } - }).filter(Objects::nonNull) + try { + return chainBaseManager.getProposalStore().get(key); + } catch (Exception ex) { + return null; + } + }).filter(Objects::nonNull) .forEach(proposalCapsule -> builder .addProposals(proposalCapsule.getInstance())); return builder.build(); @@ -2784,14 +2784,14 @@ public ExchangeList getPaginatedExchangeList(long offset, long limit) { .create(Range.openClosed(offset, end), DiscreteDomain.longs()) .asList(); rangeList.stream().map(ExchangeCapsule::calculateDbKey).map(key -> { - try { - return getExchangeStoreFinal(chainBaseManager.getDynamicPropertiesStore(), - chainBaseManager.getExchangeStore(), - chainBaseManager.getExchangeV2Store()).get(key); - } catch (Exception ex) { - return null; - } - }).filter(Objects::nonNull) + try { + return getExchangeStoreFinal(chainBaseManager.getDynamicPropertiesStore(), + chainBaseManager.getExchangeStore(), + chainBaseManager.getExchangeV2Store()).get(key); + } catch (Exception ex) { + return null; + } + }).filter(Objects::nonNull) .forEach(exchangeCapsule -> builder .addExchanges(exchangeCapsule.getInstance())); return builder.build(); From de627aa77adfb9f6d171ffb228221754a0720991 Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 16 May 2022 11:50:17 +0800 Subject: [PATCH 0068/1197] func(ver): update block version --- .../main/java/org/tron/core/config/Parameter.java | 2 +- .../runtime/vm/EnergyWhenSendAndTransferTest.java | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index bb8c30ff5b1..35a763f64c0 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -66,7 +66,7 @@ public class ChainConstant { public static final int SINGLE_REPEAT = 1; public static final int BLOCK_FILLED_SLOTS_NUMBER = 128; public static final int MAX_FROZEN_NUMBER = 1; - public static final int BLOCK_VERSION = 23; + public static final int BLOCK_VERSION = 24; public static final long FROZEN_PERIOD = 86_400_000L; public static final long TRX_PRECISION = 1000_000L; } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java index b7384f53902..194e03da85c 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java @@ -24,6 +24,7 @@ import org.tron.core.exception.VMIllegalException; import org.tron.core.store.StoreFactory; import org.tron.core.vm.repository.RepositoryImpl; +import org.tron.protos.Protocol; import org.tron.protos.Protocol.AccountType; @Slf4j @@ -171,10 +172,16 @@ public void sendTest() long feeLimit = 1000_000_000L; // sun long consumeUserResourcePercent = 100; byte[] address = Hex.decode(OWNER_ADDRESS); - TVMTestResult result = deploySendAndTransferTestContract(value, feeLimit, - consumeUserResourcePercent); - + TVMTestResult result = null; long expectEnergyUsageTotal = 140194; + for (int i = 0; i < 3; i++) { + result = deploySendAndTransferTestContract(value, feeLimit, + consumeUserResourcePercent); + if (result.getRuntime().getResult().getResultCode() + != Protocol.Transaction.Result.contractResult.OUT_OF_TIME) { + break; + } + } Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); byte[] contractAddress = result.getContractAddress(); Assert.assertEquals(repository.getAccount(contractAddress).getBalance(), value); From e4cc243b8a7979dbd3b8ff61a7c754a64ecf66ff Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 16 May 2022 14:34:09 +0800 Subject: [PATCH 0069/1197] test(vm): revert fixing out of time --- .../runtime/vm/EnergyWhenSendAndTransferTest.java | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java index 194e03da85c..b7384f53902 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java @@ -24,7 +24,6 @@ import org.tron.core.exception.VMIllegalException; import org.tron.core.store.StoreFactory; import org.tron.core.vm.repository.RepositoryImpl; -import org.tron.protos.Protocol; import org.tron.protos.Protocol.AccountType; @Slf4j @@ -172,16 +171,10 @@ public void sendTest() long feeLimit = 1000_000_000L; // sun long consumeUserResourcePercent = 100; byte[] address = Hex.decode(OWNER_ADDRESS); - TVMTestResult result = null; - long expectEnergyUsageTotal = 140194; - for (int i = 0; i < 3; i++) { - result = deploySendAndTransferTestContract(value, feeLimit, + TVMTestResult result = deploySendAndTransferTestContract(value, feeLimit, consumeUserResourcePercent); - if (result.getRuntime().getResult().getResultCode() - != Protocol.Transaction.Result.contractResult.OUT_OF_TIME) { - break; - } - } + + long expectEnergyUsageTotal = 140194; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); byte[] contractAddress = result.getContractAddress(); Assert.assertEquals(repository.getAccount(contractAddress).getBalance(), value); From 6d42cf22c97e11f4133e2ce5da4b464d6831dd31 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 16 May 2022 14:50:42 +0800 Subject: [PATCH 0070/1197] feat(metrics): fix shared static variable `initialized` in test case,use `MetricsPrometheusEnable`. --- .../java/org/tron/common/storage/metric/DbStatService.java | 6 +++--- .../org/tron/common/prometheus/InstrumentedAppender.java | 2 +- .../src/main/java/org/tron/common/prometheus/Metrics.java | 4 ++-- .../java/org/tron/common/prometheus/MetricsCounter.java | 2 +- .../main/java/org/tron/common/prometheus/MetricsGauge.java | 4 ++-- .../java/org/tron/common/prometheus/MetricsHistogram.java | 4 ++-- .../main/java/org/tron/consensus/dpos/StatisticManager.java | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/storage/metric/DbStatService.java b/chainbase/src/main/java/org/tron/common/storage/metric/DbStatService.java index 3cb4dcb488c..402ab087808 100644 --- a/chainbase/src/main/java/org/tron/common/storage/metric/DbStatService.java +++ b/chainbase/src/main/java/org/tron/common/storage/metric/DbStatService.java @@ -19,19 +19,19 @@ public class DbStatService { public void register(DB db) { - if (Metrics.initialized()) { + if (Metrics.enabled()) { statExecutor.scheduleWithFixedDelay(db::stat, 0, 6, TimeUnit.HOURS); } } public void register(DbSourceInter db) { - if (Metrics.initialized()) { + if (Metrics.enabled()) { statExecutor.scheduleWithFixedDelay(db::stat, 0, 6, TimeUnit.HOURS); } } public void shutdown() { - if (Metrics.initialized()) { + if (Metrics.enabled()) { try { statExecutor.shutdown(); } catch (Exception e) { diff --git a/common/src/main/java/org/tron/common/prometheus/InstrumentedAppender.java b/common/src/main/java/org/tron/common/prometheus/InstrumentedAppender.java index 33301371c3e..7b9972ebebe 100644 --- a/common/src/main/java/org/tron/common/prometheus/InstrumentedAppender.java +++ b/common/src/main/java/org/tron/common/prometheus/InstrumentedAppender.java @@ -18,7 +18,7 @@ public class InstrumentedAppender extends UnsynchronizedAppenderBase Date: Mon, 16 May 2022 15:38:22 +0800 Subject: [PATCH 0071/1197] test(vm): fix contract address conflict --- .../tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java index b7384f53902..3737ddde14b 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java @@ -167,7 +167,7 @@ public void sendTest() throws ContractExeException, ReceiptCheckErrException, ContractValidateException, VMIllegalException { - long value = 1000L; + long value = 10_000L; long feeLimit = 1000_000_000L; // sun long consumeUserResourcePercent = 100; byte[] address = Hex.decode(OWNER_ADDRESS); From 1909f966148b421a1c697aa6e3cbbf81141ceb10 Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 16 May 2022 16:39:29 +0800 Subject: [PATCH 0072/1197] test(vm): fix contract address conflict by modifying fee limit --- .../tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java index 3737ddde14b..b834f953eb4 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java @@ -167,8 +167,8 @@ public void sendTest() throws ContractExeException, ReceiptCheckErrException, ContractValidateException, VMIllegalException { - long value = 10_000L; - long feeLimit = 1000_000_000L; // sun + long value = 1000L; + long feeLimit = 100_000_000L; // sun long consumeUserResourcePercent = 100; byte[] address = Hex.decode(OWNER_ADDRESS); TVMTestResult result = deploySendAndTransferTestContract(value, feeLimit, From 9e2d394ac80e8b472c29ca24adbbfac19ef1c1ee Mon Sep 17 00:00:00 2001 From: liukai Date: Mon, 16 May 2022 17:46:35 +0800 Subject: [PATCH 0073/1197] feature: update logger level 1. modify TronNetService to handle exception log output --- framework/src/main/java/org/tron/core/net/TronNetService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index a80b6d498d4..250a9a444b0 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -153,7 +153,7 @@ private void processException(PeerConnection peer, TronMessage msg, Exception ex code = ReasonCode.UNKNOWN; break; } - logger.warn("Message from {} process failed, {} \n type: {}, detail: {}.", + logger.error("Message from {} process failed, {} \n type: {}, detail: {}.", peer.getInetAddress(), msg, type, ex.getMessage()); } else { code = ReasonCode.UNKNOWN; From 0e33a0f9a35f612bc49fc57811ad08a5f379fd90 Mon Sep 17 00:00:00 2001 From: Asuka Date: Tue, 17 May 2022 17:24:36 +0800 Subject: [PATCH 0074/1197] fix(vm): revert contract cache --- .../tron/core/vm/repository/RepositoryImpl.java | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 1f0943fe2c3..cd131b9c93a 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -123,9 +123,6 @@ public class RepositoryImpl implements Repository { private final HashMap> delegationCache = new HashMap<>(); public static void removeLruCache(byte[] address) { - Key key = Key.create(address); - contractLruCache.remove(key); - codeLruCache.remove(key); } public RepositoryImpl(StoreFactory storeFactory, RepositoryImpl repository) { @@ -369,10 +366,6 @@ public void createContract(byte[] address, ContractCapsule contractCapsule) { @Override public ContractCapsule getContract(byte[] address) { Key key = Key.create(address); - if (contractLruCache.containsKey(key)) { - return contractLruCache.get(key); - } - if (contractCache.containsKey(key)) { return new ContractCapsule(contractCache.get(key).getValue()); } @@ -386,9 +379,6 @@ public ContractCapsule getContract(byte[] address) { if (contractCapsule != null) { contractCache.put(key, Value.create(contractCapsule)); - if (!contractLruCache.containsKey(key)) { - contractLruCache.put(key, contractCapsule); - } } return contractCapsule; } @@ -464,10 +454,6 @@ public void saveCode(byte[] address, byte[] code) { @Override public byte[] getCode(byte[] address) { Key key = Key.create(address); - if (codeLruCache.containsKey(key)) { - return codeLruCache.get(key); - } - if (codeCache.containsKey(key)) { return codeCache.get(key).getValue(); } @@ -484,9 +470,6 @@ public byte[] getCode(byte[] address) { } if (code != null) { codeCache.put(key, Value.create(code)); - if (!codeLruCache.containsKey(key)) { - codeLruCache.put(key, code); - } } return code; } From bc8a09564b16b56df38a23c38a9dd70ef77ab249 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Tue, 17 May 2022 18:02:58 +0800 Subject: [PATCH 0075/1197] feat: check if input type valid and check if contracts valid --- .../org/tron/core/utils/TransactionUtil.java | 95 +++++++------ .../src/main/java/org/tron/core/Wallet.java | 71 +++++----- .../GetTransactionApprovedListServlet.java | 1 - .../http/GetTransactionSignWeightServlet.java | 1 - .../org/tron/core/services/http/Util.java | 12 +- .../org/tron/core/services/http/UtilTest.java | 128 ++++++++++++++++++ 6 files changed, 228 insertions(+), 80 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/services/http/UtilTest.java diff --git a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java index cb7c10a1fff..5ca4f36ab12 100644 --- a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java @@ -205,54 +205,61 @@ public TransactionSignWeight getTransactionSignWeight(Transaction trx) { trxExBuilder.setResult(retBuilder); tswBuilder.setTransaction(trxExBuilder); Result.Builder resultBuilder = Result.newBuilder(); - try { - Contract contract = trx.getRawData().getContract(0); - byte[] owner = TransactionCapsule.getOwner(contract); - AccountCapsule account = chainBaseManager.getAccountStore().get(owner); - if (Objects.isNull(account)) { - throw new PermissionException("Account does not exist!"); - } - int permissionId = contract.getPermissionId(); - Permission permission = account.getPermissionById(permissionId); - if (permission == null) { - throw new PermissionException("Permission for this, does not exist!"); - } - if (permissionId != 0) { - if (permission.getType() != PermissionType.Active) { - throw new PermissionException("Permission type is wrong!"); + + if (trx.getRawData().getContractCount() == 0) { + resultBuilder.setCode(Result.response_code.OTHER_ERROR); + resultBuilder.setMessage("Invalid transaction: no valid contract"); + } else { + try { + Contract contract = trx.getRawData().getContract(0); + byte[] owner = TransactionCapsule.getOwner(contract); + AccountCapsule account = chainBaseManager.getAccountStore().get(owner); + if (Objects.isNull(account)) { + throw new PermissionException("Account does not exist!"); } - //check operations - if (!checkPermissionOperations(permission, contract)) { - throw new PermissionException("Permission denied!"); + int permissionId = contract.getPermissionId(); + Permission permission = account.getPermissionById(permissionId); + if (permission == null) { + throw new PermissionException("Permission for this, does not exist!"); } + if (permissionId != 0) { + if (permission.getType() != PermissionType.Active) { + throw new PermissionException("Permission type is wrong!"); + } + //check operations + if (!checkPermissionOperations(permission, contract)) { + throw new PermissionException("Permission denied!"); + } + } + tswBuilder.setPermission(permission); + if (trx.getSignatureCount() > 0) { + List approveList = new ArrayList(); + long currentWeight = TransactionCapsule.checkWeight(permission, trx.getSignatureList(), + Sha256Hash.hash(CommonParameter.getInstance() + .isECKeyCryptoEngine(), trx.getRawData().toByteArray()), approveList); + tswBuilder.addAllApprovedList(approveList); + tswBuilder.setCurrentWeight(currentWeight); + } + if (tswBuilder.getCurrentWeight() >= permission.getThreshold()) { + resultBuilder.setCode(Result.response_code.ENOUGH_PERMISSION); + } else { + resultBuilder.setCode(Result.response_code.NOT_ENOUGH_PERMISSION); + } + } catch (SignatureFormatException signEx) { + resultBuilder.setCode(Result.response_code.SIGNATURE_FORMAT_ERROR); + resultBuilder.setMessage(signEx.getMessage()); + } catch (SignatureException signEx) { + resultBuilder.setCode(Result.response_code.COMPUTE_ADDRESS_ERROR); + resultBuilder.setMessage(signEx.getMessage()); + } catch (PermissionException permEx) { + resultBuilder.setCode(Result.response_code.PERMISSION_ERROR); + resultBuilder.setMessage(permEx.getMessage()); + } catch (Exception ex) { + resultBuilder.setCode(Result.response_code.OTHER_ERROR); + resultBuilder.setMessage(ex.getClass() + " : " + ex.getMessage()); } - tswBuilder.setPermission(permission); - if (trx.getSignatureCount() > 0) { - List approveList = new ArrayList(); - long currentWeight = TransactionCapsule.checkWeight(permission, trx.getSignatureList(), - Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), trx.getRawData().toByteArray()), approveList); - tswBuilder.addAllApprovedList(approveList); - tswBuilder.setCurrentWeight(currentWeight); - } - if (tswBuilder.getCurrentWeight() >= permission.getThreshold()) { - resultBuilder.setCode(Result.response_code.ENOUGH_PERMISSION); - } else { - resultBuilder.setCode(Result.response_code.NOT_ENOUGH_PERMISSION); - } - } catch (SignatureFormatException signEx) { - resultBuilder.setCode(Result.response_code.SIGNATURE_FORMAT_ERROR); - resultBuilder.setMessage(signEx.getMessage()); - } catch (SignatureException signEx) { - resultBuilder.setCode(Result.response_code.COMPUTE_ADDRESS_ERROR); - resultBuilder.setMessage(signEx.getMessage()); - } catch (PermissionException permEx) { - resultBuilder.setCode(Result.response_code.PERMISSION_ERROR); - resultBuilder.setMessage(permEx.getMessage()); - } catch (Exception ex) { - resultBuilder.setCode(Result.response_code.OTHER_ERROR); - resultBuilder.setMessage(ex.getClass() + " : " + ex.getMessage()); } + tswBuilder.setResult(resultBuilder); return tswBuilder.build(); } diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 12d749fee27..3b6dbfeee7f 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -594,41 +594,48 @@ public TransactionApprovedList getTransactionApprovedList(Transaction trx) { tswBuilder.setTransaction(trxExBuilder); TransactionApprovedList.Result.Builder resultBuilder = TransactionApprovedList.Result .newBuilder(); - try { - Contract contract = trx.getRawData().getContract(0); - byte[] owner = TransactionCapsule.getOwner(contract); - AccountCapsule account = chainBaseManager.getAccountStore().get(owner); - if (account == null) { - throw new PermissionException("Account does not exist!"); - } - - if (trx.getSignatureCount() > 0) { - List approveList = new ArrayList(); - byte[] hash = Sha256Hash.hash(CommonParameter - .getInstance().isECKeyCryptoEngine(), trx.getRawData().toByteArray()); - for (ByteString sig : trx.getSignatureList()) { - if (sig.size() < 65) { - throw new SignatureFormatException( - "Signature size is " + sig.size()); + + if (trx.getRawData().getContractCount() == 0) { + resultBuilder.setCode(TransactionApprovedList.Result.response_code.OTHER_ERROR); + resultBuilder.setMessage("Invalid transaction: no valid contract"); + } else { + try { + Contract contract = trx.getRawData().getContract(0); + byte[] owner = TransactionCapsule.getOwner(contract); + AccountCapsule account = chainBaseManager.getAccountStore().get(owner); + if (account == null) { + throw new PermissionException("Account does not exist!"); + } + + if (trx.getSignatureCount() > 0) { + List approveList = new ArrayList(); + byte[] hash = Sha256Hash.hash(CommonParameter + .getInstance().isECKeyCryptoEngine(), trx.getRawData().toByteArray()); + for (ByteString sig : trx.getSignatureList()) { + if (sig.size() < 65) { + throw new SignatureFormatException( + "Signature size is " + sig.size()); + } + String base64 = TransactionCapsule.getBase64FromByteString(sig); + byte[] address = SignUtils.signatureToAddress(hash, base64, Args.getInstance() + .isECKeyCryptoEngine()); + approveList.add(ByteString.copyFrom(address)); //out put approve list. } - String base64 = TransactionCapsule.getBase64FromByteString(sig); - byte[] address = SignUtils.signatureToAddress(hash, base64, Args.getInstance() - .isECKeyCryptoEngine()); - approveList.add(ByteString.copyFrom(address)); //out put approve list. + tswBuilder.addAllApprovedList(approveList); } - tswBuilder.addAllApprovedList(approveList); - } - resultBuilder.setCode(TransactionApprovedList.Result.response_code.SUCCESS); - } catch (SignatureFormatException signEx) { - resultBuilder.setCode(TransactionApprovedList.Result.response_code.SIGNATURE_FORMAT_ERROR); - resultBuilder.setMessage(signEx.getMessage()); - } catch (SignatureException signEx) { - resultBuilder.setCode(TransactionApprovedList.Result.response_code.COMPUTE_ADDRESS_ERROR); - resultBuilder.setMessage(signEx.getMessage()); - } catch (Exception ex) { - resultBuilder.setCode(TransactionApprovedList.Result.response_code.OTHER_ERROR); - resultBuilder.setMessage(ex.getClass() + " : " + ex.getMessage()); + resultBuilder.setCode(TransactionApprovedList.Result.response_code.SUCCESS); + } catch (SignatureFormatException signEx) { + resultBuilder.setCode(TransactionApprovedList.Result.response_code.SIGNATURE_FORMAT_ERROR); + resultBuilder.setMessage(signEx.getMessage()); + } catch (SignatureException signEx) { + resultBuilder.setCode(TransactionApprovedList.Result.response_code.COMPUTE_ADDRESS_ERROR); + resultBuilder.setMessage(signEx.getMessage()); + } catch (Exception ex) { + resultBuilder.setCode(TransactionApprovedList.Result.response_code.OTHER_ERROR); + resultBuilder.setMessage(ex.getClass() + " : " + ex.getMessage()); + } } + tswBuilder.setResult(resultBuilder); return tswBuilder.build(); } diff --git a/framework/src/main/java/org/tron/core/services/http/GetTransactionApprovedListServlet.java b/framework/src/main/java/org/tron/core/services/http/GetTransactionApprovedListServlet.java index b225a770c21..d4d123b7efe 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetTransactionApprovedListServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetTransactionApprovedListServlet.java @@ -1,6 +1,5 @@ package org.tron.core.services.http; -import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; diff --git a/framework/src/main/java/org/tron/core/services/http/GetTransactionSignWeightServlet.java b/framework/src/main/java/org/tron/core/services/http/GetTransactionSignWeightServlet.java index 3ff3368730f..bbd819d4e6d 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetTransactionSignWeightServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetTransactionSignWeightServlet.java @@ -1,6 +1,5 @@ package org.tron.core.services.http; -import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index d59ae7062a6..7d3da03097e 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -253,16 +253,22 @@ public static JSONObject printTransactionToJSON(Transaction transaction, boolean } public static Transaction packTransaction(String strTransaction, boolean selfType) { - JSONObject jsonTransaction = JSONObject.parseObject(strTransaction); + JSONObject jsonTransaction = JSON.parseObject(strTransaction); JSONObject rawData = jsonTransaction.getJSONObject("raw_data"); JSONArray contracts = new JSONArray(); JSONArray rawContractArray = rawData.getJSONArray("contract"); + String contractType = null; for (int i = 0; i < rawContractArray.size(); i++) { try { JSONObject contract = rawContractArray.getJSONObject(i); JSONObject parameter = contract.getJSONObject(PARAMETER); - String contractType = contract.getString("type"); + contractType = contract.getString("type"); + if (StringUtils.isEmpty(contractType)) { + logger.debug("no type in the transaction, ignore"); + continue; + } + Any any = null; Class clazz = TransactionFactory.getContract(ContractType.valueOf(contractType)); if (clazz != null) { @@ -279,6 +285,8 @@ public static Transaction packTransaction(String strTransaction, boolean selfTyp contract.put(PARAMETER, parameter); contracts.add(contract); } + } catch (IllegalArgumentException e) { + logger.debug("invalid contractType: {}", contractType); } catch (ParseException e) { logger.debug("ParseException: {}", e.getMessage()); } catch (Exception e) { diff --git a/framework/src/test/java/org/tron/core/services/http/UtilTest.java b/framework/src/test/java/org/tron/core/services/http/UtilTest.java new file mode 100644 index 00000000000..fed314ba44e --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/UtilTest.java @@ -0,0 +1,128 @@ +package org.tron.core.services.http; + +import java.io.File; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.tron.api.GrpcAPI.TransactionApprovedList; +import org.tron.api.GrpcAPI.TransactionSignWeight; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.FileUtil; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.utils.TransactionUtil; +import org.tron.protos.Protocol.Transaction; + +public class UtilTest { + + private static Wallet wallet; + private static String dbPath = "output_util_test"; + private static TronApplicationContext context; + private static TransactionUtil transactionUtil; + + static { + Args.setParam(new String[] {"-d", dbPath}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + } + + @BeforeClass + public static void init() { + wallet = context.getBean(Wallet.class); + transactionUtil = context.getBean(TransactionUtil.class); + } + + @AfterClass + public static void removeDb() { + Args.clearParam(); + context.destroy(); + FileUtil.deleteDir(new File(dbPath)); + } + + @Test + public void testPackTransactionWithInvalidType() { + + String strTransaction = "{\n" + + " \"visible\": false,\n" + + " \"signature\": [\n" + + " \"5c23bddabccd3e4e5ebdf7d2f21dc58af9f88e0b99620374c5354e0dd9efb3a436167d95b70d2" + + "d825180bf90bc84525acb13a203f209afd5d397316f6b2c387c01\"\n" + + " ],\n" + + " \"txID\": \"fc33817936b06e50d4b6f1797e62f52d69af6c0da580a607241a9c03a48e390e\",\n" + + " \"raw_data\": {\n" + + " \"contract\": [\n" + + " {\n" + + " \"parameter\": {\n" + + " \"value\": {\n" + + " \"amount\": 10,\n" + + " \"owner_address\":\"41c076305e35aea1fe45a772fcaaab8a36e87bdb55\"," + + " \"to_address\": \"415624c12e308b03a1a6b21d9b86e3942fac1ab92b\"\n" + + " },\n" + + " \"type_url\": \"type.googleapis.com/protocol.TransferContract\"\n" + + " },\n" + + " \"type\": \"TransferContract11111\"\n" + + " }\n" + + " ],\n" + + " \"ref_block_bytes\": \"d8ed\",\n" + + " \"ref_block_hash\": \"2e066c3259e756f5\",\n" + + " \"expiration\": 1651906644000,\n" + + " \"timestamp\": 1651906586162\n" + + " },\n" + + " \"raw_data_hex\": \"0a02d8ed22082e066c3259e756f540a090bcea89305a65080112610a2d747970" + + "652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e74726163741230" + + "0a1541c076305e35aea1fe45a772fcaaab8a36e87bdb551215415624c12e308b03a1a6b21d9b86e3942fac1a" + + "b92b180a70b2ccb8ea8930\"\n" + + "}"; + Transaction transaction = Util.packTransaction(strTransaction, false); + TransactionApprovedList transactionApprovedList = + wallet.getTransactionApprovedList(transaction); + Assert.assertEquals("Invalid transaction: no valid contract", + transactionApprovedList.getResult().getMessage()); + + TransactionSignWeight txSignWeight = transactionUtil.getTransactionSignWeight(transaction); + Assert.assertEquals("Invalid transaction: no valid contract", + txSignWeight.getResult().getMessage()); + + + strTransaction = "{\n" + + " \"visible\": false,\n" + + " \"signature\": [\n" + + " \"5c23bddabccd3e4e5ebdf7d2f21dc58af9f88e0b99620374c5354e0dd9efb3a436167d95b70d2d" + + "825180bf90bc84525acb13a203f209afd5d397316f6b2c387c01\"\n" + + " ],\n" + + " \"txID\": \"fc33817936b06e50d4b6f1797e62f52d69af6c0da580a607241a9c03a48e390e\",\n" + + " \"raw_data\": {\n" + + " \"contract\": [\n" + + " {\n" + + " \"parameter\": {\n" + + " \"value\": {\n" + + " \"amount\": 10,\n" + + " \"owner_address\":\"41c076305e35aea1fe45a772fcaaab8a36e87bdb55\"," + + " \"to_address\": \"415624c12e308b03a1a6b21d9b86e3942fac1ab92b\"\n" + + " },\n" + + " \"type_url\": \"type.googleapis.com/protocol.TransferContract\"\n" + + " }\n" + + " }\n" + + " ],\n" + + " \"ref_block_bytes\": \"d8ed\",\n" + + " \"ref_block_hash\": \"2e066c3259e756f5\",\n" + + " \"expiration\": 1651906644000,\n" + + " \"timestamp\": 1651906586162\n" + + " },\n" + + " \"raw_data_hex\": \"0a02d8ed22082e066c3259e756f540a090bcea89305a65080112610a2d747970" + + "652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e74726163741230" + + "0a1541c076305e35aea1fe45a772fcaaab8a36e87bdb551215415624c12e308b03a1a6b21d9b86e3942fac1a" + + "b92b180a70b2ccb8ea8930\"\n" + + "}"; + transaction = Util.packTransaction(strTransaction, false); + transactionApprovedList = wallet.getTransactionApprovedList(transaction); + Assert.assertEquals("Invalid transaction: no valid contract", + transactionApprovedList.getResult().getMessage()); + + txSignWeight = transactionUtil.getTransactionSignWeight(transaction); + Assert.assertEquals("Invalid transaction: no valid contract", + txSignWeight.getResult().getMessage()); + } +} From e8e064750a15f628f62778289bcf898fb49f9536 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Wed, 18 May 2022 00:13:53 +0800 Subject: [PATCH 0076/1197] feat: add note --- framework/src/main/java/org/tron/core/services/http/Util.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 7d3da03097e..66db8365099 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -252,6 +252,9 @@ public static JSONObject printTransactionToJSON(Transaction transaction, boolean return jsonTransaction; } + /** + * Note: the contracts of the returned transaction may be empty + * */ public static Transaction packTransaction(String strTransaction, boolean selfType) { JSONObject jsonTransaction = JSON.parseObject(strTransaction); JSONObject rawData = jsonTransaction.getJSONObject("raw_data"); From c3229034fdaeec1b38d4805944af9955eb1a05ee Mon Sep 17 00:00:00 2001 From: Asuka Date: Wed, 18 May 2022 09:20:43 +0800 Subject: [PATCH 0077/1197] code(vm): remove unused fields --- .../java/org/tron/core/vm/repository/RepositoryImpl.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index cd131b9c93a..d0c4d8416cc 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -8,7 +8,6 @@ import java.util.Optional; import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.map.LRUMap; import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Hex; import org.tron.common.crypto.Hash; @@ -73,10 +72,6 @@ public class RepositoryImpl implements Repository { private static final byte[] TOTAL_NET_WEIGHT = "TOTAL_NET_WEIGHT".getBytes(); private static final byte[] TOTAL_ENERGY_WEIGHT = "TOTAL_ENERGY_WEIGHT".getBytes(); - private static final int lruCacheSize = CommonParameter.getInstance().getSafeLruCacheSize(); - private static final LRUMap contractLruCache = new LRUMap<>(lruCacheSize); - private static final LRUMap codeLruCache = new LRUMap<>(lruCacheSize); - private StoreFactory storeFactory; @Getter private DynamicPropertiesStore dynamicPropertiesStore; From 013f8cd74aab801596ed2c5a2ef0d48aed8b9e9b Mon Sep 17 00:00:00 2001 From: Asuka Date: Wed, 18 May 2022 14:05:30 +0800 Subject: [PATCH 0078/1197] fix(vm,config): add missing proposal loader --- actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java | 1 + 1 file changed, 1 insertion(+) diff --git a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java index 71ff3cb92ed..93781e749a4 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java +++ b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java @@ -28,6 +28,7 @@ public static void load(StoreFactory storeFactory) { VMConfig.initAllowTvmFreeze(ds.getAllowTvmFreeze()); VMConfig.initAllowTvmVote(ds.getAllowTvmVote()); VMConfig.initAllowTvmLondon(ds.getAllowTvmLondon()); + VMConfig.initAllowTvmCompatibleEvm(ds.getAllowTvmCompatibleEvm()); VMConfig.initAllowHigherLimitForMaxCpuTimeOfOneTx( ds.getAllowHigherLimitForMaxCpuTimeOfOneTx()); } From 46ededca6c03abc9c6f4faec82585d0a238fc8fc Mon Sep 17 00:00:00 2001 From: liukai Date: Wed, 18 May 2022 16:15:59 +0800 Subject: [PATCH 0079/1197] feat: add parameter checks 1. add 'generateBlock','solidBlockId','headBlockId' parameter checksum --- .../overlay/server/HandshakeHandler.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java index 0cf55c59766..10b12c9ef16 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java @@ -41,6 +41,7 @@ import org.tron.core.metrics.MetricsKey; import org.tron.core.metrics.MetricsUtil; import org.tron.core.net.peer.PeerConnection; +import org.tron.protos.Protocol; import org.tron.protos.Protocol.ReasonCode; @Slf4j(topic = "net") @@ -138,6 +139,11 @@ private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { return; } + if (!checkHelloMsg(msg, ctx)) { + channel.disconnect(ReasonCode.UNEXPECTED_IDENTITY); + return; + } + InetAddress address = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress(); if (remoteId.length != 64 && channelManager.getTrustNodes().getIfPresent(address) == null @@ -209,4 +215,36 @@ private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { syncPool.onConnect(channel); } + + private boolean checkHelloMsg(HelloMessage msg, ChannelHandlerContext ctx) { + + Protocol.HelloMessage helloMessage = msg.getInstance(); + + byte[] genesisBlockByte = helloMessage.getGenesisBlockId().getHash().toByteArray(); + + if (genesisBlockByte.length == 0) { + logger.warn("Peer {} different genesis block, peer genesis block byte length is 0", + ctx.channel().remoteAddress()); + channel.disconnect(ReasonCode.INCOMPATIBLE_CHAIN); + return Boolean.FALSE; + } + + byte[] solidBlockId = helloMessage.getSolidBlockId().toByteArray(); + if (solidBlockId.length == 0) { + logger.warn("Peer {} solidBlockId byte length is 0", + ctx.channel().remoteAddress()); + channel.disconnect(ReasonCode.INCOMPATIBLE_CHAIN); + return Boolean.FALSE; + } + + byte[] headBlockId = helloMessage.getHeadBlockId().toByteArray(); + if (headBlockId.length == 0) { + logger.warn("Peer {} headBlockId byte length is 0", + ctx.channel().remoteAddress()); + channel.disconnect(ReasonCode.INCOMPATIBLE_CHAIN); + return Boolean.FALSE; + } + + return Boolean.TRUE; + } } From b1dd740342d6d9081a29a7310f9975b2241427ae Mon Sep 17 00:00:00 2001 From: liukai Date: Wed, 18 May 2022 17:08:54 +0800 Subject: [PATCH 0080/1197] feat: add parameter checks 1. add 'generateBlock','solidBlockId','headBlockId' parameter checksum --- .../tron/common/overlay/server/HandshakeHandler.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java index 10b12c9ef16..2f374d08aac 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java @@ -168,15 +168,6 @@ private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { return; } - byte[] genesisBlockByte = msg.getInstance().getGenesisBlockId().getHash().toByteArray(); - - if (genesisBlockByte.length == 0) { - logger.info("Peer {} different genesis block, peer genesis block byte length is 0", - ctx.channel().remoteAddress()); - channel.disconnect(ReasonCode.INCOMPATIBLE_CHAIN); - return; - } - if (!Arrays .equals(chainBaseManager.getGenesisBlockId().getBytes(), msg.getGenesisBlockId().getBytes())) { @@ -225,7 +216,6 @@ private boolean checkHelloMsg(HelloMessage msg, ChannelHandlerContext ctx) { if (genesisBlockByte.length == 0) { logger.warn("Peer {} different genesis block, peer genesis block byte length is 0", ctx.channel().remoteAddress()); - channel.disconnect(ReasonCode.INCOMPATIBLE_CHAIN); return Boolean.FALSE; } @@ -233,7 +223,6 @@ private boolean checkHelloMsg(HelloMessage msg, ChannelHandlerContext ctx) { if (solidBlockId.length == 0) { logger.warn("Peer {} solidBlockId byte length is 0", ctx.channel().remoteAddress()); - channel.disconnect(ReasonCode.INCOMPATIBLE_CHAIN); return Boolean.FALSE; } @@ -241,7 +230,6 @@ private boolean checkHelloMsg(HelloMessage msg, ChannelHandlerContext ctx) { if (headBlockId.length == 0) { logger.warn("Peer {} headBlockId byte length is 0", ctx.channel().remoteAddress()); - channel.disconnect(ReasonCode.INCOMPATIBLE_CHAIN); return Boolean.FALSE; } From b8722228d7803e951e702affb37f25c5bb95abcf Mon Sep 17 00:00:00 2001 From: liukai Date: Wed, 18 May 2022 17:11:05 +0800 Subject: [PATCH 0081/1197] feat: simplify the return code 1. simplify the return code --- .../org/tron/common/overlay/server/HandshakeHandler.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java index 2f374d08aac..15bc902c18c 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java @@ -216,23 +216,23 @@ private boolean checkHelloMsg(HelloMessage msg, ChannelHandlerContext ctx) { if (genesisBlockByte.length == 0) { logger.warn("Peer {} different genesis block, peer genesis block byte length is 0", ctx.channel().remoteAddress()); - return Boolean.FALSE; + return false; } byte[] solidBlockId = helloMessage.getSolidBlockId().toByteArray(); if (solidBlockId.length == 0) { logger.warn("Peer {} solidBlockId byte length is 0", ctx.channel().remoteAddress()); - return Boolean.FALSE; + return false; } byte[] headBlockId = helloMessage.getHeadBlockId().toByteArray(); if (headBlockId.length == 0) { logger.warn("Peer {} headBlockId byte length is 0", ctx.channel().remoteAddress()); - return Boolean.FALSE; + return false; } - return Boolean.TRUE; + return true; } } From 255874159e8f62490e0089573ad559a3dbb20e63 Mon Sep 17 00:00:00 2001 From: liukai Date: Wed, 18 May 2022 18:17:37 +0800 Subject: [PATCH 0082/1197] feat: add a verification method 1. add HelloMessage parameter checks --- .../common/overlay/message/HelloMessage.java | 21 +++++++++++ .../overlay/server/HandshakeHandler.java | 36 ++++--------------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java b/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java index 75f5b1fe87a..c5f5bdf2355 100755 --- a/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java +++ b/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java @@ -1,6 +1,7 @@ package org.tron.common.overlay.message; import com.google.protobuf.ByteString; +import io.netty.channel.ChannelHandlerContext; import lombok.Getter; import org.tron.common.overlay.discover.node.Node; import org.tron.common.overlay.server.HandshakeHandler; @@ -129,4 +130,24 @@ public String toString() { public Protocol.HelloMessage getInstance() { return this.helloMessage; } + + public boolean valid() { + byte[] genesisBlockByte = this.helloMessage.getGenesisBlockId().getHash().toByteArray(); + + if (genesisBlockByte.length == 0) { + return false; + } + + byte[] solidBlockId = this.helloMessage.getSolidBlockId().getHash().toByteArray(); + if (solidBlockId.length == 0) { + return false; + } + + byte[] headBlockId = this.helloMessage.getHeadBlockId().getHash().toByteArray(); + if (headBlockId.length == 0) { + return false; + } + + return true; + } } diff --git a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java index 15bc902c18c..b4758cd89fb 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java @@ -41,7 +41,6 @@ import org.tron.core.metrics.MetricsKey; import org.tron.core.metrics.MetricsUtil; import org.tron.core.net.peer.PeerConnection; -import org.tron.protos.Protocol; import org.tron.protos.Protocol.ReasonCode; @Slf4j(topic = "net") @@ -139,7 +138,12 @@ private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { return; } - if (!checkHelloMsg(msg, ctx)) { + if (!msg.valid()) { + logger.warn("Peer {} invalid hello message parameters, GenesisBlockId: {}, SolidBlockId: {}, HeadBlockId: {}", + ctx.channel().remoteAddress(), + msg.getInstance().getGenesisBlockId().getHash(), + msg.getInstance().getSolidBlockId().getHash(), + msg.getInstance().getHeadBlockId().getHash()); channel.disconnect(ReasonCode.UNEXPECTED_IDENTITY); return; } @@ -207,32 +211,4 @@ private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { syncPool.onConnect(channel); } - private boolean checkHelloMsg(HelloMessage msg, ChannelHandlerContext ctx) { - - Protocol.HelloMessage helloMessage = msg.getInstance(); - - byte[] genesisBlockByte = helloMessage.getGenesisBlockId().getHash().toByteArray(); - - if (genesisBlockByte.length == 0) { - logger.warn("Peer {} different genesis block, peer genesis block byte length is 0", - ctx.channel().remoteAddress()); - return false; - } - - byte[] solidBlockId = helloMessage.getSolidBlockId().toByteArray(); - if (solidBlockId.length == 0) { - logger.warn("Peer {} solidBlockId byte length is 0", - ctx.channel().remoteAddress()); - return false; - } - - byte[] headBlockId = helloMessage.getHeadBlockId().toByteArray(); - if (headBlockId.length == 0) { - logger.warn("Peer {} headBlockId byte length is 0", - ctx.channel().remoteAddress()); - return false; - } - - return true; - } } From 2a5821bff685cf7fc6f71854fedd176a6cf36145 Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 19 May 2022 14:55:45 +0800 Subject: [PATCH 0083/1197] feat: add a verification method 1. adjusting the order of validation --- .../tron/common/overlay/message/HelloMessage.java | 1 - .../common/overlay/server/HandshakeHandler.java | 14 +++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java b/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java index c5f5bdf2355..3fec2284fa2 100755 --- a/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java +++ b/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java @@ -133,7 +133,6 @@ public Protocol.HelloMessage getInstance() { public boolean valid() { byte[] genesisBlockByte = this.helloMessage.getGenesisBlockId().getHash().toByteArray(); - if (genesisBlockByte.length == 0) { return false; } diff --git a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java index b4758cd89fb..34f7ddc1cac 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java @@ -131,13 +131,6 @@ protected void sendHelloMsg(ChannelHandlerContext ctx, long time) { } private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { - channel.initNode(msg.getFrom().getId(), msg.getFrom().getPort()); - - if (!fastForward.checkHelloMessage(msg, channel)) { - channel.disconnect(ReasonCode.UNEXPECTED_IDENTITY); - return; - } - if (!msg.valid()) { logger.warn("Peer {} invalid hello message parameters, GenesisBlockId: {}, SolidBlockId: {}, HeadBlockId: {}", ctx.channel().remoteAddress(), @@ -148,6 +141,13 @@ private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { return; } + channel.initNode(msg.getFrom().getId(), msg.getFrom().getPort()); + + if (!fastForward.checkHelloMessage(msg, channel)) { + channel.disconnect(ReasonCode.UNEXPECTED_IDENTITY); + return; + } + InetAddress address = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress(); if (remoteId.length != 64 && channelManager.getTrustNodes().getIfPresent(address) == null From 831105b94a5399d2b699959bc6fd931f57581164 Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 19 May 2022 18:10:03 +0800 Subject: [PATCH 0084/1197] feat: add a verification method 1. optimized log --- .../org/tron/common/overlay/server/HandshakeHandler.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java index 34f7ddc1cac..ce445cc6ca0 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java @@ -35,6 +35,7 @@ import org.tron.common.overlay.message.HelloMessage; import org.tron.common.overlay.message.P2pMessage; import org.tron.common.overlay.message.P2pMessageFactory; +import org.tron.common.utils.ByteArray; import org.tron.core.ChainBaseManager; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; @@ -134,9 +135,9 @@ private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { if (!msg.valid()) { logger.warn("Peer {} invalid hello message parameters, GenesisBlockId: {}, SolidBlockId: {}, HeadBlockId: {}", ctx.channel().remoteAddress(), - msg.getInstance().getGenesisBlockId().getHash(), - msg.getInstance().getSolidBlockId().getHash(), - msg.getInstance().getHeadBlockId().getHash()); + ByteArray.toHexString(msg.getInstance().getGenesisBlockId().getHash().toByteArray()), + ByteArray.toHexString(msg.getInstance().getSolidBlockId().getHash().toByteArray()), + ByteArray.toHexString(msg.getInstance().getHeadBlockId().getHash().toByteArray())); channel.disconnect(ReasonCode.UNEXPECTED_IDENTITY); return; } From 4e7b572bdd5c26931a03013605d56099474b940f Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 19 May 2022 22:56:49 +0800 Subject: [PATCH 0085/1197] feat: modify code style 1. modify code style --- .../java/org/tron/common/overlay/server/HandshakeHandler.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java index 0bef64b6d9b..a72175e354a 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java @@ -139,7 +139,8 @@ protected void sendHelloMsg(ChannelHandlerContext ctx, long time) { private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { if (!msg.valid()) { - logger.warn("Peer {} invalid hello message parameters, GenesisBlockId: {}, SolidBlockId: {}, HeadBlockId: {}", + logger.warn("Peer {} invalid hello message parameters, " + + "GenesisBlockId: {}, SolidBlockId: {}, HeadBlockId: {}", ctx.channel().remoteAddress(), ByteArray.toHexString(msg.getInstance().getGenesisBlockId().getHash().toByteArray()), ByteArray.toHexString(msg.getInstance().getSolidBlockId().getHash().toByteArray()), From d7c6af7e326683523ee3e661181089cb2a81ccdf Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 20 May 2022 11:18:56 +0800 Subject: [PATCH 0086/1197] func(vm,storage): remove proposal check for contract version --- actuator/src/main/java/org/tron/core/vm/program/Storage.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Storage.java b/actuator/src/main/java/org/tron/core/vm/program/Storage.java index 7e21d187a37..572af048081 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Storage.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Storage.java @@ -11,7 +11,6 @@ import org.tron.common.utils.ByteUtil; import org.tron.core.capsule.StorageRowCapsule; import org.tron.core.store.StorageRowStore; -import org.tron.core.vm.config.VMConfig; public class Storage { @@ -45,7 +44,7 @@ public Storage(Storage storage) { } private byte[] compose(byte[] key, byte[] addrHash) { - if (VMConfig.allowTvmCompatibleEvm() && contractVersion == 1) { + if (contractVersion == 1) { key = Hash.sha3(key); } byte[] result = new byte[key.length]; From bc3de7e06d1e47096adde1cc954705d0384c9c63 Mon Sep 17 00:00:00 2001 From: liukai Date: Fri, 20 May 2022 14:55:22 +0800 Subject: [PATCH 0087/1197] feat: optimised log output 1. optimised log output --- .../java/org/tron/common/overlay/server/HandshakeHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java index a72175e354a..981984a6f04 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java @@ -139,8 +139,8 @@ protected void sendHelloMsg(ChannelHandlerContext ctx, long time) { private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { if (!msg.valid()) { - logger.warn("Peer {} invalid hello message parameters, " + - "GenesisBlockId: {}, SolidBlockId: {}, HeadBlockId: {}", + logger.warn("Peer {} invalid hello message parameters, " + + "GenesisBlockId: {}, SolidBlockId: {}, HeadBlockId: {}", ctx.channel().remoteAddress(), ByteArray.toHexString(msg.getInstance().getGenesisBlockId().getHash().toByteArray()), ByteArray.toHexString(msg.getInstance().getSolidBlockId().getHash().toByteArray()), From 93ed8565d4e48ee75d112d41ce1c72b9849944e2 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Fri, 20 May 2022 14:55:30 +0800 Subject: [PATCH 0088/1197] feat: remove Tvm config when get storage value --- .../java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index e062783043e..237c7fa08e6 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -70,7 +70,6 @@ import org.tron.core.services.jsonrpc.types.TransactionReceipt; import org.tron.core.services.jsonrpc.types.TransactionResult; import org.tron.core.store.StorageRowStore; -import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.program.Storage; import org.tron.program.Version; import org.tron.protos.Protocol.Account; @@ -455,10 +454,6 @@ public String getStorageAt(String address, String storageIdx, String blockNumOrT StorageRowStore store = manager.getStorageRowStore(); Storage storage = new Storage(addressByte, store); - // init Tvm config - storage.setContractVersion(smartContract.getVersion()); - VMConfig.initAllowTvmCompatibleEvm(1); - DataWord value = storage.getValue(new DataWord(ByteArray.fromHexString(storageIdx))); return ByteArray.toJsonHex(value == null ? new byte[32] : value.getData()); } else { From 85aaca4691b349401123c675f39a637dd7360b6a Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Fri, 20 May 2022 15:02:46 +0800 Subject: [PATCH 0089/1197] feat: set contract version before get value from storage --- .../java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 237c7fa08e6..0fec85718fa 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -453,6 +453,7 @@ public String getStorageAt(String address, String storageIdx, String blockNumOrT StorageRowStore store = manager.getStorageRowStore(); Storage storage = new Storage(addressByte, store); + storage.setContractVersion(smartContract.getVersion()); DataWord value = storage.getValue(new DataWord(ByteArray.fromHexString(storageIdx))); return ByteArray.toJsonHex(value == null ? new byte[32] : value.getData()); From 0c93fda8086013d6f57f1461ab656112e1163a66 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 19 May 2022 18:48:09 +0800 Subject: [PATCH 0090/1197] perf(db): optimize 10 asset storage logic --- .../actuator/ShieldedTransferActuator.java | 8 +- .../core/actuator/TransferAssetActuator.java | 19 +- .../org/tron/core/utils/ProposalUtil.java | 2 +- .../main/java/org/tron/core/vm/VMUtils.java | 20 +- .../core/vm/repository/RepositoryImpl.java | 7 +- .../java/org/tron/core/vm/utils/MUtil.java | 1 - .../leveldb/LevelDbDataSourceImpl.java | 23 + .../rocksdb/RocksDbDataSourceImpl.java | 23 + .../java/org/tron/core/ChainBaseManager.java | 8 + .../core/capsule/AccountAssetCapsule.java | 102 --- .../org/tron/core/capsule/AccountCapsule.java | 236 +++--- .../tron/core/capsule/utils/AssetUtil.java | 142 +--- .../java/org/tron/core/db/TronDatabase.java | 16 + .../tron/core/db/common/DbSourceInter.java | 2 + .../org/tron/core/db2/common/IRevokingDB.java | 2 + .../org/tron/core/db2/core/Chainbase.java | 39 + .../core/RevokingDBWithCachingOldValue.java | 7 + .../org/tron/core/db2/core/SnapshotRoot.java | 28 +- .../tron/core/store/AccountAssetStore.java | 67 +- .../org/tron/core/store/AccountStore.java | 17 +- .../java/org/tron/core/config/Parameter.java | 3 +- .../org/tron/common/storage/DepositImpl.java | 7 +- .../src/main/java/org/tron/core/Wallet.java | 4 +- .../main/java/org/tron/core/db/Manager.java | 17 +- .../runtime/vm/TransferToAccountTest.java | 10 +- .../common/runtime/vm/TransferTokenTest.java | 19 +- .../org/tron/core/BandwidthProcessorTest.java | 7 - .../core/actuator/AssetIssueActuatorTest.java | 42 +- .../actuator/ExchangeCreateActuatorTest.java | 27 +- .../actuator/ExchangeInjectActuatorTest.java | 24 +- .../ExchangeTransactionActuatorTest.java | 78 +- .../ExchangeWithdrawActuatorTest.java | 46 +- .../MarketCancelOrderActuatorTest.java | 17 +- .../actuator/MarketSellAssetActuatorTest.java | 100 ++- .../ParticipateAssetIssueActuatorTest.java | 174 ++--- .../ShieldedTransferActuatorTest.java | 4 +- .../actuator/TransferAssetActuatorTest.java | 733 +++++++++--------- .../actuator/UnfreezeAssetActuatorTest.java | 27 +- .../tron/core/capsule/AccountCapsuleTest.java | 93 +-- .../core/capsule/utils/AssetUtilTest.java | 59 -- .../tron/core/db/AccountAssetStoreTest.java | 64 -- .../org/tron/core/db/AccountStoreTest.java | 124 +++ .../java/org/tron/core/db/ManagerTest.java | 4 +- .../core/db/api/AssetUpdateHelperTest.java | 4 +- protocol/src/main/protos/core/Tron.proto | 32 - 45 files changed, 1122 insertions(+), 1366 deletions(-) delete mode 100644 chainbase/src/main/java/org/tron/core/capsule/AccountAssetCapsule.java delete mode 100644 framework/src/test/java/org/tron/core/db/AccountAssetStoreTest.java diff --git a/actuator/src/main/java/org/tron/core/actuator/ShieldedTransferActuator.java b/actuator/src/main/java/org/tron/core/actuator/ShieldedTransferActuator.java index 8b00126c684..284650f1ffb 100644 --- a/actuator/src/main/java/org/tron/core/actuator/ShieldedTransferActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/ShieldedTransferActuator.java @@ -462,13 +462,7 @@ private void validateTransparent(ShieldedTransferContract shieldedTransferContra } private long getZenBalance(AccountCapsule account) { - if (account.getAssetMapV2().get(CommonParameter - .getInstance().getZenTokenId()) == null) { - return 0L; - } else { - return account.getAssetMapV2().get(CommonParameter - .getInstance().getZenTokenId()); - } + return account.getAssetV2(CommonParameter.getInstance().getZenTokenId()); } @Override diff --git a/actuator/src/main/java/org/tron/core/actuator/TransferAssetActuator.java b/actuator/src/main/java/org/tron/core/actuator/TransferAssetActuator.java index cdc626d5a35..de2b2faec86 100644 --- a/actuator/src/main/java/org/tron/core/actuator/TransferAssetActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/TransferAssetActuator.java @@ -18,7 +18,6 @@ import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import java.util.Arrays; -import java.util.Map; import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.ByteArray; @@ -159,17 +158,7 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("No asset!"); } - Map asset; - if (dynamicStore.getAllowSameTokenName() == 0) { - asset = ownerAccount.getAssetMap(); - } else { - asset = ownerAccount.getAssetMapV2(); - } - if (asset.isEmpty()) { - throw new ContractValidateException("Owner has no asset!"); - } - - Long assetBalance = asset.get(ByteArray.toStr(assetName)); + Long assetBalance = ownerAccount.getAsset(dynamicStore, ByteArray.toStr(assetName)); if (null == assetBalance || assetBalance <= 0) { throw new ContractValidateException("assetBalance must be greater than 0."); } @@ -185,11 +174,7 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("Cannot transfer asset to smartContract."); } - if (dynamicStore.getAllowSameTokenName() == 0) { - assetBalance = toAccount.getAssetMap().get(ByteArray.toStr(assetName)); - } else { - assetBalance = toAccount.getAssetMapV2().get(ByteArray.toStr(assetName)); - } + assetBalance = toAccount.getAsset(dynamicStore, ByteArray.toStr(assetName)); if (assetBalance != null) { try { assetBalance = Math.addExact(assetBalance, amount); //check if overflow diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 8ce040702c5..d1a0ae6f291 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -499,7 +499,7 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } case ALLOW_ACCOUNT_ASSET_OPTIMIZATION: { - if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_3)) { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_5)) { throw new ContractValidateException( "Bad chain parameter id [ALLOW_ACCOUNT_ASSET_OPTIMIZATION]"); } diff --git a/actuator/src/main/java/org/tron/core/vm/VMUtils.java b/actuator/src/main/java/org/tron/core/vm/VMUtils.java index 7d080b23b37..abdf6c7fe4c 100644 --- a/actuator/src/main/java/org/tron/core/vm/VMUtils.java +++ b/actuator/src/main/java/org/tron/core/vm/VMUtils.java @@ -210,17 +210,8 @@ public static boolean validateForSmartContract(Repository deposit, byte[] ownerA throw new ContractValidateException("No asset !"); } - Map asset; - if (deposit.getDynamicPropertiesStore().getAllowSameTokenName() == 0) { - asset = ownerAccount.getAssetMap(); - } else { - asset = ownerAccount.getAssetMapV2(); - } - if (asset.isEmpty()) { - throw new ContractValidateException("Owner no asset!"); - } - - Long assetBalance = asset.get(ByteArray.toStr(tokenIdWithoutLeadingZero)); + Long assetBalance = ownerAccount.getAsset(deposit.getDynamicPropertiesStore(), + ByteArray.toStr(tokenIdWithoutLeadingZero)); if (null == assetBalance || assetBalance <= 0) { throw new ContractValidateException("assetBalance must greater than 0."); } @@ -230,11 +221,8 @@ public static boolean validateForSmartContract(Repository deposit, byte[] ownerA AccountCapsule toAccount = deposit.getAccount(toAddress); if (toAccount != null) { - if (deposit.getDynamicPropertiesStore().getAllowSameTokenName() == 0) { - assetBalance = toAccount.getAssetMap().get(ByteArray.toStr(tokenIdWithoutLeadingZero)); - } else { - assetBalance = toAccount.getAssetMapV2().get(ByteArray.toStr(tokenIdWithoutLeadingZero)); - } + assetBalance = toAccount.getAsset(deposit.getDynamicPropertiesStore(), + ByteArray.toStr(tokenIdWithoutLeadingZero)); if (assetBalance != null) { try { assetBalance = Math.addExact(assetBalance, amount); //check if overflow diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 807f267b9db..31d6a2bd404 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -637,8 +637,7 @@ public long addTokenBalance(byte[] address, byte[] tokenId, long value) { if (accountCapsule == null) { accountCapsule = createAccount(address, Protocol.AccountType.Normal); } - long balance = accountCapsule.getAssetMapV2() - .getOrDefault(new String(tokenIdWithoutLeadingZero), new Long(0)); + long balance = accountCapsule.getAssetV2(new String(tokenIdWithoutLeadingZero)); if (value == 0) { return balance; } @@ -660,7 +659,7 @@ public long addTokenBalance(byte[] address, byte[] tokenId, long value) { Value V = Value.create(accountCapsule.getData(), Type.VALUE_TYPE_DIRTY | accountCache.get(key).getType().getType()); accountCache.put(key, V); - return accountCapsule.getAssetMapV2().get(new String(tokenIdWithoutLeadingZero)); + return accountCapsule.getAssetV2(new String(tokenIdWithoutLeadingZero)); } @Override @@ -670,7 +669,7 @@ public long getTokenBalance(byte[] address, byte[] tokenId) { return 0; } String tokenStr = new String(ByteUtil.stripLeadingZeroes(tokenId)); - return accountCapsule.getAssetMapV2().getOrDefault(tokenStr, 0L); + return accountCapsule.getAssetV2(tokenStr); } @Override diff --git a/actuator/src/main/java/org/tron/core/vm/utils/MUtil.java b/actuator/src/main/java/org/tron/core/vm/utils/MUtil.java index 7207126a785..d0332b175d0 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/MUtil.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/MUtil.java @@ -26,7 +26,6 @@ public static void transferAllToken(Repository deposit, byte[] fromAddress, byte AccountCapsule fromAccountCap = deposit.getAccount(fromAddress); Protocol.Account.Builder fromBuilder = fromAccountCap.getInstance().toBuilder(); AccountCapsule toAccountCap = deposit.getAccount(toAddress); - toAccountCap.importAsset(); Protocol.Account.Builder toBuilder = toAccountCap.getInstance().toBuilder(); fromAccountCap.getAssetMapV2().forEach((tokenId, amount) -> { toBuilder.putAssetV2(tokenId, toBuilder.getAssetV2Map().getOrDefault(tokenId, 0L) + amount); diff --git a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java index df75d0ecd68..8766d8a554b 100644 --- a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java @@ -35,6 +35,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.stream.Stream; import java.util.stream.StreamSupport; + +import com.google.common.primitives.Bytes; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.iq80.leveldb.CompressionType; @@ -51,6 +53,7 @@ import org.tron.core.db.common.DbSourceInter; import org.tron.core.db.common.iterator.StoreIterator; import org.tron.core.db2.common.Instance; +import org.tron.core.db2.common.WrappedByteArray; @Slf4j(topic = "DB") @NoArgsConstructor @@ -345,6 +348,26 @@ public Map getNext(byte[] key, long limit) { } } + public Map prefixQuery(byte[] key) { + resetDbLock.readLock().lock(); + try (DBIterator iterator = getDBIterator()) { + Map result = new HashMap<>(); + for (iterator.seek(key); iterator.hasNext(); iterator.next()) { + Entry entry = iterator.peekNext(); + if (Bytes.indexOf(entry.getKey(), key) >= 0) { + result.put(WrappedByteArray.of(entry.getKey()), entry.getValue()); + } else { + return result; + } + } + return result; + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + resetDbLock.readLock().unlock(); + } + } + public Set getValuesPrev(byte[] key, long limit) { if (limit <= 0) { return Sets.newHashSet(); diff --git a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java index eb85e624457..62990e50294 100644 --- a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java @@ -15,6 +15,8 @@ import java.util.Set; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; + +import com.google.common.primitives.Bytes; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.rocksdb.BlockBasedTableConfig; @@ -36,6 +38,7 @@ import org.tron.core.db.common.DbSourceInter; import org.tron.core.db.common.iterator.RockStoreIterator; import org.tron.core.db2.common.Instance; +import org.tron.core.db2.common.WrappedByteArray; @Slf4j @@ -428,6 +431,26 @@ public Map getNext(byte[] key, long limit) { } } + public Map prefixQuery(byte[] key) { + if (quitIfNotAlive()) { + return null; + } + resetDbLock.readLock().lock(); + try (RocksIterator iterator = getRocksIterator()) { + Map result = new HashMap<>(); + for (iterator.seek(key); iterator.isValid(); iterator.next()) { + if (Bytes.indexOf(iterator.key(), key) >= 0) { + result.put(WrappedByteArray.of(iterator.key()), iterator.value()); + } else { + return result; + } + } + return result; + } finally { + resetDbLock.readLock().unlock(); + } + } + public Set getlatestValues(long limit) { if (quitIfNotAlive()) { return null; diff --git a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java index 7cbb842f622..8f1842aab1f 100644 --- a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java +++ b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java @@ -69,6 +69,9 @@ @Component public class ChainBaseManager { + @Getter + private static ChainBaseManager chainBaseManager; + // db store @Autowired @Getter @@ -388,7 +391,12 @@ public BlockCapsule getBlockByNum(final long num) throws return getBlockById(getBlockIdByNum(num)); } + public static ChainBaseManager getInstance() { + return chainBaseManager; + } + public void init() { + chainBaseManager = this; AssetUtil.setAccountAssetStore(accountAssetStore); AssetUtil.setDynamicPropertiesStore(dynamicPropertiesStore); } diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountAssetCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountAssetCapsule.java deleted file mode 100644 index 81a16f3afd8..00000000000 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountAssetCapsule.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.tron.core.capsule; - -import com.google.protobuf.ByteString; -import com.google.protobuf.InvalidProtocolBufferException; -import lombok.extern.slf4j.Slf4j; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.AccountAsset; -import org.tron.protos.Protocol.AccountAsset.Frozen; - -import java.util.List; -import java.util.Map; - -@Slf4j(topic = "capsule") -public class AccountAssetCapsule implements ProtoCapsule { - - private AccountAsset accountAsset; - - /** - * get accountAssetIssue from bytes data. - */ - public AccountAssetCapsule(byte[] data) { - try { - this.accountAsset = AccountAsset.parseFrom(data); - } catch (InvalidProtocolBufferException e) { - logger.debug(e.getMessage()); - } - } - - public AccountAssetCapsule(ByteString address) { - this.accountAsset = AccountAsset.newBuilder() - .setAddress(address) - .build(); - } - - public AccountAssetCapsule(AccountAsset accountAsset) { - this.accountAsset = accountAsset; - } - - @Override - public byte[] getData() { - return this.accountAsset.toByteArray(); - } - - @Override - public AccountAsset getInstance() { - return this.accountAsset; - } - - public ByteString getAddress() { - return this.accountAsset.getAddress(); - } - - public byte[] createDbKey() { - return getAddress().toByteArray(); - } - - public void setInstance(AccountAsset accountAsset) { - this.accountAsset = accountAsset; - } - - public Map getAssetMap() { - return this.accountAsset.getAssetMap(); - } - - public ByteString getAssetIssuedID() { - return getInstance().getAssetIssuedID(); - } - - public ByteString getAssetIssuedName() { - return getInstance().getAssetIssuedName(); - } - - public Map getAllFreeAssetNetUsage() { - return this.accountAsset.getFreeAssetNetUsageMap(); - } - - public Map getLatestAssetOperationTimeMap() { - return this.accountAsset.getLatestAssetOperationTimeMap(); - } - - public Map getAssetMapV2() { - return this.accountAsset.getAssetV2Map(); - } - - public Map getAllFreeAssetNetUsageV2() { - return this.accountAsset.getFreeAssetNetUsageV2Map(); - } - - public Map getLatestAssetOperationTimeMapV2() { - return this.accountAsset.getLatestAssetOperationTimeV2Map(); - } - - public List getFrozenSupplyList() { - return getInstance().getFrozenSupplyList(); - } - - @Override - public String toString() { - return this.accountAsset.toString(); - } - -} diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index 1888724bb5c..4d6100ecc1f 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -21,8 +21,6 @@ import com.google.protobuf.InvalidProtocolBufferException; import java.util.List; import java.util.Map; -import lombok.Getter; -import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.ByteArray; import org.tron.core.capsule.utils.AssetUtil; @@ -44,10 +42,7 @@ public class AccountCapsule implements ProtoCapsule, Comparable { private Account account; - - @Getter - @Setter - private Boolean isAssetImport = false; + private boolean flag = false; /** * get account from bytes data. @@ -453,22 +448,13 @@ public void addVotes(ByteString voteAddress, long voteAdd) { .build(); } - public void clearAssetV2() { - importAsset(); - this.account = this.account.toBuilder() - .clearAssetV2() - .build(); - } - public void clearLatestAssetOperationTimeV2() { - importAsset(); this.account = this.account.toBuilder() .clearLatestAssetOperationTimeV2() .build(); } public void clearFreeAssetNetUsageV2() { - importAsset(); this.account = this.account.toBuilder() .clearFreeAssetNetUsageV2() .build(); @@ -522,21 +508,11 @@ public long getAllTronPower() { } } - /** - * asset balance enough - */ - public boolean assetBalanceEnough(byte[] key, long amount) { - importAsset(); - Map assetMap = this.account.getAssetMap(); - String nameKey = ByteArray.toStr(key); - Long currentAmount = assetMap.get(nameKey); - - return amount > 0 && null != currentAmount && amount <= currentAmount; - } + /*************************** start asset ****************************************/ public boolean assetBalanceEnoughV2(byte[] key, long amount, DynamicPropertiesStore dynamicPropertiesStore) { - importAsset(); + importAsset(key); Map assetMap; String nameKey; Long currentAmount; @@ -553,82 +529,67 @@ public boolean assetBalanceEnoughV2(byte[] key, long amount, return amount > 0 && null != currentAmount && amount <= currentAmount; } - /** - * reduce asset amount. - */ - public boolean reduceAssetAmount(byte[] key, long amount) { - importAsset(); + public boolean addAssetAmount(byte[] key, long amount) { Map assetMap = this.account.getAssetMap(); String nameKey = ByteArray.toStr(key); Long currentAmount = assetMap.get(nameKey); - if (amount > 0 && null != currentAmount && amount <= currentAmount) { - this.account = this.account.toBuilder() - .putAsset(nameKey, Math.subtractExact(currentAmount, amount)).build(); - return true; + if (currentAmount == null) { + currentAmount = 0L; } - - return false; + this.account = this.account.toBuilder().putAsset(nameKey, Math.addExact(currentAmount, amount)) + .build(); + return true; } - /** - * reduce asset amount. - */ - public boolean reduceAssetAmountV2(byte[] key, long amount, + public boolean addAssetAmountV2(byte[] key, long amount, DynamicPropertiesStore dynamicPropertiesStore, AssetIssueStore assetIssueStore) { + importAsset(key); //key is token name - importAsset(); if (dynamicPropertiesStore.getAllowSameTokenName() == 0) { Map assetMap = this.account.getAssetMap(); AssetIssueCapsule assetIssueCapsule = assetIssueStore.get(key); String tokenID = assetIssueCapsule.getId(); String nameKey = ByteArray.toStr(key); Long currentAmount = assetMap.get(nameKey); - if (amount > 0 && null != currentAmount && amount <= currentAmount) { - this.account = this.account.toBuilder() - .putAsset(nameKey, Math.subtractExact(currentAmount, amount)) - .putAssetV2(tokenID, Math.subtractExact(currentAmount, amount)) - .build(); - return true; + if (currentAmount == null) { + currentAmount = 0L; } + this.account = this.account.toBuilder() + .putAsset(nameKey, Math.addExact(currentAmount, amount)) + .putAssetV2(tokenID, Math.addExact(currentAmount, amount)) + .build(); } //key is token id if (dynamicPropertiesStore.getAllowSameTokenName() == 1) { - String tokenID = ByteArray.toStr(key); + String tokenIDStr = ByteArray.toStr(key); Map assetMapV2 = this.account.getAssetV2Map(); - Long currentAmount = assetMapV2.get(tokenID); - if (amount > 0 && null != currentAmount && amount <= currentAmount) { - this.account = this.account.toBuilder() - .putAssetV2(tokenID, Math.subtractExact(currentAmount, amount)) - .build(); - return true; + Long currentAmount = assetMapV2.get(tokenIDStr); + if (currentAmount == null) { + currentAmount = 0L; } + this.account = this.account.toBuilder() + .putAssetV2(tokenIDStr, Math.addExact(currentAmount, amount)) + .build(); } - - return false; + return true; } - /** - * add asset amount. - */ - public boolean addAssetAmount(byte[] key, long amount) { - importAsset(); + public boolean reduceAssetAmount(byte[] key, long amount) { Map assetMap = this.account.getAssetMap(); String nameKey = ByteArray.toStr(key); Long currentAmount = assetMap.get(nameKey); - if (currentAmount == null) { - currentAmount = 0L; + if (amount > 0 && null != currentAmount && amount <= currentAmount) { + this.account = this.account.toBuilder() + .putAsset(nameKey, Math.subtractExact(currentAmount, amount)).build(); + return true; } - this.account = this.account.toBuilder().putAsset(nameKey, Math.addExact(currentAmount, amount)) - .build(); - return true; + + return false; } - /** - * add asset amount. - */ - public boolean addAssetAmountV2(byte[] key, long amount, - DynamicPropertiesStore dynamicPropertiesStore, AssetIssueStore assetIssueStore) { - importAsset(); + public boolean reduceAssetAmountV2(byte[] key, long amount, + DynamicPropertiesStore dynamicPropertiesStore, AssetIssueStore assetIssueStore) { + importAsset(key); //key is token name if (dynamicPropertiesStore.getAllowSameTokenName() == 0) { Map assetMap = this.account.getAssetMap(); @@ -636,34 +597,44 @@ public boolean addAssetAmountV2(byte[] key, long amount, String tokenID = assetIssueCapsule.getId(); String nameKey = ByteArray.toStr(key); Long currentAmount = assetMap.get(nameKey); - if (currentAmount == null) { - currentAmount = 0L; + if (amount > 0 && null != currentAmount && amount <= currentAmount) { + this.account = this.account.toBuilder() + .putAsset(nameKey, Math.subtractExact(currentAmount, amount)) + .putAssetV2(tokenID, Math.subtractExact(currentAmount, amount)) + .build(); + return true; } - this.account = this.account.toBuilder() - .putAsset(nameKey, Math.addExact(currentAmount, amount)) - .putAssetV2(tokenID, Math.addExact(currentAmount, amount)) - .build(); } //key is token id if (dynamicPropertiesStore.getAllowSameTokenName() == 1) { - String tokenIDStr = ByteArray.toStr(key); + String tokenID = ByteArray.toStr(key); Map assetMapV2 = this.account.getAssetV2Map(); - Long currentAmount = assetMapV2.get(tokenIDStr); - if (currentAmount == null) { - currentAmount = 0L; + Long currentAmount = assetMapV2.get(tokenID); + if (amount > 0 && null != currentAmount && amount <= currentAmount) { + this.account = this.account.toBuilder() + .putAssetV2(tokenID, Math.subtractExact(currentAmount, amount)) + .build(); + return true; } - this.account = this.account.toBuilder() - .putAssetV2(tokenIDStr, Math.addExact(currentAmount, amount)) - .build(); } - return true; + + return false; + } + + public void clearAssetV2() { + this.account = this.account.toBuilder() + .clearAssetV2() + .build(); + } + + public void clearAsset() { + this.account = this.account.toBuilder() + .clearAsset() + .clearAssetV2() + .build(); } - /** - * add asset. - */ public boolean addAsset(byte[] key, long value) { - importAsset(); Map assetMap = this.account.getAssetMap(); String nameKey = ByteArray.toStr(key); if (!assetMap.isEmpty() && assetMap.containsKey(nameKey)) { @@ -674,81 +645,91 @@ public boolean addAsset(byte[] key, long value) { } public boolean addAssetV2(byte[] key, long value) { - importAsset(); - String tokenID = ByteArray.toStr(key); - Map assetV2Map = this.account.getAssetV2Map(); - if (!assetV2Map.isEmpty() && assetV2Map.containsKey(tokenID)) { + if (AssetUtil.hasAssetV2(this.account, key)) { return false; } this.account = this.account.toBuilder() - .putAssetV2(tokenID, value) + .putAssetV2(ByteArray.toStr(key), value) .build(); return true; } - /** - * add asset. - */ public boolean addAssetMapV2(Map assetMap) { - importAsset(); this.account = this.account.toBuilder().putAllAssetV2(assetMap).build(); return true; } + public Long getAsset(DynamicPropertiesStore dynamicStore, String key) { + Long balance; + if (dynamicStore.getAllowSameTokenName() == 0) { + balance = this.account.getAssetMap().get(key); + } else { + importAsset(key.getBytes()); + balance = this.account.getAssetV2Map().get(key); + } + return balance; + } + + public long getAssetV2(String key) { + importAsset(key.getBytes()); + Long balance = this.account.getAssetV2Map().get(key); + return balance == null ? 0 : balance; + } + public Map getAssetMap() { - importAsset(); Map assetMap = this.account.getAssetMap(); if (assetMap.isEmpty()) { assetMap = Maps.newHashMap(); } - return assetMap; } public Map getAssetMapV2() { - importAsset(); + importAllAsset(); Map assetMap = this.account.getAssetV2Map(); if (assetMap.isEmpty()) { assetMap = Maps.newHashMap(); } - return assetMap; } + public Map getAssetMapForTest() { + return getAssetMap(); + } + + public Map getAssetV2MapForTest() { + return getAssetMapV2(); + } + + /*************************** end asset ****************************************/ + public boolean addAllLatestAssetOperationTimeV2(Map map) { - importAsset(); this.account = this.account.toBuilder().putAllLatestAssetOperationTimeV2(map).build(); return true; } public Map getLatestAssetOperationTimeMap() { - importAsset(); return this.account.getLatestAssetOperationTimeMap(); } public Map getLatestAssetOperationTimeMapV2() { - importAsset(); return this.account.getLatestAssetOperationTimeV2Map(); } public long getLatestAssetOperationTime(String assetName) { - importAsset(); return this.account.getLatestAssetOperationTimeOrDefault(assetName, 0); } public long getLatestAssetOperationTimeV2(String assetName) { - importAsset(); return this.account.getLatestAssetOperationTimeV2OrDefault(assetName, 0); } public void putLatestAssetOperationTimeMap(String key, Long value) { - importAsset(); this.account = this.account.toBuilder().putLatestAssetOperationTime(key, value).build(); } public void putLatestAssetOperationTimeMapV2(String key, Long value) { - importAsset(); this.account = this.account.toBuilder().putLatestAssetOperationTimeV2(key, value).build(); } @@ -773,12 +754,10 @@ public long getAllFrozenBalanceForBandwidth() { } public int getFrozenSupplyCount() { - importAsset(); return getInstance().getFrozenSupplyCount(); } public List getFrozenSupplyList() { - importAsset(); return getInstance().getFrozenSupplyList(); } @@ -791,23 +770,19 @@ public long getFrozenSupplyBalance() { } public ByteString getAssetIssuedName() { - importAsset(); return getInstance().getAssetIssuedName(); } public void setAssetIssuedName(byte[] nameKey) { - importAsset(); ByteString assetIssuedName = ByteString.copyFrom(nameKey); this.account = this.account.toBuilder().setAssetIssuedName(assetIssuedName).build(); } public ByteString getAssetIssuedID() { - importAsset(); return getInstance().getAssetIssuedID(); } public void setAssetIssuedID(byte[] id) { - importAsset(); ByteString assetIssuedID = ByteString.copyFrom(id); this.account = this.account.toBuilder().setAssetIssuedID(assetIssuedID).build(); } @@ -992,39 +967,32 @@ public void setFreeNetUsage(long freeNetUsage) { } public boolean addAllFreeAssetNetUsageV2(Map map) { - importAsset(); this.account = this.account.toBuilder().putAllFreeAssetNetUsageV2(map).build(); return true; } public long getFreeAssetNetUsage(String assetName) { - importAsset(); return this.account.getFreeAssetNetUsageOrDefault(assetName, 0); } public long getFreeAssetNetUsageV2(String assetName) { - importAsset(); return this.account.getFreeAssetNetUsageV2OrDefault(assetName, 0); } public Map getAllFreeAssetNetUsage() { - importAsset(); return this.account.getFreeAssetNetUsageMap(); } public Map getAllFreeAssetNetUsageV2() { - importAsset(); return this.account.getFreeAssetNetUsageV2Map(); } public void putFreeAssetNetUsage(String s, long freeAssetNetUsage) { - importAsset(); this.account = this.account.toBuilder() .putFreeAssetNetUsage(s, freeAssetNetUsage).build(); } public void putFreeAssetNetUsageV2(String s, long freeAssetNetUsage) { - importAsset(); this.account = this.account.toBuilder() .putFreeAssetNetUsageV2(s, freeAssetNetUsage).build(); } @@ -1141,16 +1109,14 @@ public void clearDelegatedResource() { this.account = builder.build(); } - public void importAsset() { - if (!AssetUtil.isAllowAssetOptimization()) { - return; - } - if (!this.isAssetImport) { - Account account = AssetUtil.importAsset(this.account); - if (null != account) { - this.account = account; - } - this.isAssetImport = true; + public void importAsset(byte[] key) { + this.account = AssetUtil.importAsset(this.account, key); + } + + public void importAllAsset() { + if (!flag) { + this.account = AssetUtil.importAllAsset(this.account); + flag = true; } } diff --git a/chainbase/src/main/java/org/tron/core/capsule/utils/AssetUtil.java b/chainbase/src/main/java/org/tron/core/capsule/utils/AssetUtil.java index 966cadae852..4b21571c7d1 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/utils/AssetUtil.java +++ b/chainbase/src/main/java/org/tron/core/capsule/utils/AssetUtil.java @@ -1,18 +1,12 @@ package org.tron.core.capsule.utils; -import com.google.protobuf.ByteString; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.MapUtils; -import org.tron.core.capsule.AccountAssetCapsule; +import com.google.common.primitives.Bytes; +import java.util.HashMap; +import java.util.Map; +import org.tron.common.utils.ByteArray; import org.tron.core.store.AccountAssetStore; import org.tron.core.store.DynamicPropertiesStore; import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.AccountAsset; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; public class AssetUtil { @@ -20,114 +14,41 @@ public class AssetUtil { private static DynamicPropertiesStore dynamicPropertiesStore; - public static AccountAsset getAsset(Account account) { - if (!hasAsset(account)) { - return null; + public static boolean hasAssetV2(Account account, byte[] key) { + if (!account.getAssetV2Map().isEmpty() + && account.getAssetV2Map().containsKey(ByteArray.toStr(key))) { + return true; } - return AccountAsset.newBuilder() - .setAddress(account.getAddress()) - .setAssetIssuedID(account.getAssetIssuedID()) - .setAssetIssuedName(account.getAssetIssuedName()) - .putAllAsset(account.getAssetMap()) - .putAllAssetV2(account.getAssetV2Map()) - .putAllFreeAssetNetUsage(account.getFreeAssetNetUsageMap()) - .putAllFreeAssetNetUsageV2(account.getFreeAssetNetUsageV2Map()) - .putAllLatestAssetOperationTime(account.getLatestAssetOperationTimeMap()) - .putAllLatestAssetOperationTimeV2( - account.getLatestAssetOperationTimeV2Map()) - .addAllFrozenSupply(getFrozen(account.getFrozenSupplyList())) - .build(); - } - - private static List getFrozen(List frozenSupplyList) { - return frozenSupplyList - .stream() - .map(frozen -> AccountAsset.Frozen.newBuilder() - .setExpireTime(frozen.getExpireTime()) - .setFrozenBalance(frozen.getFrozenBalance()) - .build()) - .collect(Collectors.toList()); + if (!isAllowAssetOptimization()) { + return false; + } + byte[] dbKey = Bytes.concat(account.getAddress().toByteArray(), key); + return accountAssetStore.getUnchecked(dbKey) != null; } - - public static Account importAsset(Account account) { - if (AssetUtil.hasAsset(account)) { - return null; + public static Account importAsset(Account account, byte[] key) { + if (!isAllowAssetOptimization()) { + return account; } - AccountAssetCapsule accountAssetCapsule = accountAssetStore.get(account.getAddress().toByteArray()); - if (accountAssetCapsule == null) { - return null; - } - - return account.toBuilder() - .setAssetIssuedID(accountAssetCapsule.getAssetIssuedID()) - .setAssetIssuedName(accountAssetCapsule.getAssetIssuedName()) - .putAllAsset(accountAssetCapsule.getAssetMap()) - .putAllAssetV2(accountAssetCapsule.getAssetMapV2()) - .putAllFreeAssetNetUsage(accountAssetCapsule.getAllFreeAssetNetUsage()) - .putAllFreeAssetNetUsageV2(accountAssetCapsule.getAllFreeAssetNetUsageV2()) - .putAllLatestAssetOperationTime(accountAssetCapsule.getLatestAssetOperationTimeMap()) - .putAllLatestAssetOperationTimeV2( - accountAssetCapsule.getLatestAssetOperationTimeMapV2()) - .addAllFrozenSupply(getAccountFrozenSupplyList(accountAssetCapsule.getFrozenSupplyList())) - .build(); - } - private static List getAccountFrozenSupplyList(List frozenSupplyList) { - return Optional.ofNullable(frozenSupplyList) - .orElseGet(ArrayList::new) - .stream() - .map(frozen -> Account.Frozen.newBuilder() - .setExpireTime(frozen.getExpireTime()) - .setFrozenBalance(frozen.getFrozenBalance()) - .build()) - .collect(Collectors.toList()); - } + String sKey = ByteArray.toStr(key); + if (account.getAssetV2Map().containsKey(sKey)) { + return account; + } - public static Account clearAsset(Account account) { - return account.toBuilder() - .clearAssetIssuedID() - .clearAssetIssuedName() - .clearAsset() - .clearAssetV2() - .clearFreeAssetNetUsage() - .clearFreeAssetNetUsageV2() - .clearLatestAssetOperationTime() - .clearLatestAssetOperationTimeV2() - .clearFrozenSupply() - .build(); + long balance = accountAssetStore.getBalance(account, key); + Map map = new HashMap<>(); + map.putAll(account.getAssetV2Map()); + map.put(sKey, balance); + return account.toBuilder().clearAssetV2().putAllAssetV2(map).build(); } - public static boolean hasAsset(Account account) { - if (MapUtils.isNotEmpty(account.getAssetMap()) || - MapUtils.isNotEmpty(account.getAssetV2Map())) { - return true; - } - ByteString assetIssuedName = account.getAssetIssuedName(); - if (assetIssuedName != null && !assetIssuedName.isEmpty()) { - return true; - } - ByteString assetIssuedID = account.getAssetIssuedID(); - if (assetIssuedID != null && !assetIssuedID.isEmpty()) { - return true; - } - if (MapUtils.isNotEmpty(account.getLatestAssetOperationTimeMap()) || - MapUtils.isNotEmpty(account.getLatestAssetOperationTimeV2Map())) { - return true; - } - if (MapUtils.isNotEmpty(account.getFreeAssetNetUsageMap())) { - return true; - } - if (MapUtils.isNotEmpty(account.getFreeAssetNetUsageV2Map())) { - return true; - } - List frozenSupplyList = - account.getFrozenSupplyList(); - if (CollectionUtils.isNotEmpty(frozenSupplyList) - && frozenSupplyList.size() > 0) { - return true; + public static Account importAllAsset(Account account) { + if (!isAllowAssetOptimization()) { + return account; } - return false; + Map map = accountAssetStore.getAllAssets(account); + return account.toBuilder().clearAssetV2().putAllAssetV2(map).build(); } public static void setAccountAssetStore( @@ -140,7 +61,8 @@ public static void setDynamicPropertiesStore(DynamicPropertiesStore dynamicPrope } public static boolean isAllowAssetOptimization() { - return dynamicPropertiesStore.supportAllowAccountAssetOptimization(); + return true; +// return dynamicPropertiesStore.supportAllowAccountAssetOptimization(); } } \ No newline at end of file diff --git a/chainbase/src/main/java/org/tron/core/db/TronDatabase.java b/chainbase/src/main/java/org/tron/core/db/TronDatabase.java index 5b8762ec9ad..042f5750e7b 100644 --- a/chainbase/src/main/java/org/tron/core/db/TronDatabase.java +++ b/chainbase/src/main/java/org/tron/core/db/TronDatabase.java @@ -2,7 +2,9 @@ import com.google.protobuf.InvalidProtocolBufferException; import java.nio.file.Paths; +import java.util.HashMap; import java.util.Iterator; +import java.util.Map; import java.util.Map.Entry; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -12,7 +14,11 @@ import org.tron.common.storage.rocksdb.RocksDbDataSourceImpl; import org.tron.common.utils.StorageUtils; import org.tron.core.db.common.DbSourceInter; +import org.tron.core.db2.common.LevelDB; +import org.tron.core.db2.common.RocksDB; +import org.tron.core.db2.common.WrappedByteArray; import org.tron.core.db2.core.ITronChainBase; +import org.tron.core.db2.core.SnapshotRoot; import org.tron.core.exception.BadItemException; import org.tron.core.exception.ItemNotFoundException; @@ -79,6 +85,16 @@ public T getUnchecked(byte[] key) { return null; } + public Map prefixQuery(byte[] key) { + Map result = new HashMap<>(); + if (dbSource.getClass() == LevelDbDataSourceImpl.class) { + result = ((LevelDbDataSourceImpl) dbSource).prefixQuery(key); + } else if (dbSource.getClass() == RocksDbDataSourceImpl.class) { + result = ((RocksDbDataSourceImpl) dbSource).prefixQuery(key); + } + return result; + } + public abstract boolean has(byte[] key); @Override diff --git a/chainbase/src/main/java/org/tron/core/db/common/DbSourceInter.java b/chainbase/src/main/java/org/tron/core/db/common/DbSourceInter.java index e823da1bde9..dd9bbbc8b46 100755 --- a/chainbase/src/main/java/org/tron/core/db/common/DbSourceInter.java +++ b/chainbase/src/main/java/org/tron/core/db/common/DbSourceInter.java @@ -17,6 +17,8 @@ */ package org.tron.core.db.common; +import org.tron.core.db2.common.WrappedByteArray; + import java.util.Map; import java.util.Set; diff --git a/chainbase/src/main/java/org/tron/core/db2/common/IRevokingDB.java b/chainbase/src/main/java/org/tron/core/db2/common/IRevokingDB.java index 445972417df..23405c61f16 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/IRevokingDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/IRevokingDB.java @@ -37,6 +37,8 @@ public interface IRevokingDB extends Iterable> { List getKeysNext(byte[] key, long limit); + Map prefixQuery(byte[] key); + default Map getNext(byte[] key, long limit) { return Collections.emptyMap(); } diff --git a/chainbase/src/main/java/org/tron/core/db2/core/Chainbase.java b/chainbase/src/main/java/org/tron/core/db2/core/Chainbase.java index ee77c6cbc1b..9872978484b 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/Chainbase.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/Chainbase.java @@ -11,6 +11,8 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; + +import com.google.common.primitives.Bytes; import org.tron.common.utils.ByteUtil; import org.tron.core.capsule.utils.MarketUtils; import org.tron.core.db2.common.IRevokingDB; @@ -337,4 +339,41 @@ private Map getNext(Snapshot head, byte[] key, long limit) { .limit(limit) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } + + + + public Map prefixQuery(byte[] key) { + Map resultSnapshot = prefixQuerySnapshot(key); + Map resultDB = prefixQueryDB(key); + resultDB.putAll(resultSnapshot); + return resultDB; + } + + private Map prefixQueryDB(byte[] key) { + Map result = new HashMap<>(); + if (((SnapshotRoot) head.getRoot()).db.getClass() == LevelDB.class) { + result = ((LevelDB) ((SnapshotRoot) head.getRoot()).db).getDb().prefixQuery(key); + } else if (((SnapshotRoot) head.getRoot()).db.getClass() == RocksDB.class) { + result = ((RocksDB) ((SnapshotRoot) head.getRoot()).db).getDb().prefixQuery(key); + } + return result; + } + + private Map prefixQuerySnapshot(byte[] key) { + Map result = new HashMap<>(); + Snapshot snapshot = head(); + while (!snapshot.equals(head.getRoot())) { + Iterator> iterator = snapshot.iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + WrappedByteArray ks = WrappedByteArray.of(entry.getKey()); + if (Bytes.indexOf(entry.getKey(), key) >= 0 && !result.containsKey(ks)) { + result.put(ks, entry.getValue()); + } + } + snapshot = snapshot.getPrevious(); + } + return result; + } + } diff --git a/chainbase/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingOldValue.java b/chainbase/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingOldValue.java index 89dd75597af..5a311587725 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingOldValue.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingOldValue.java @@ -16,6 +16,7 @@ import org.tron.core.db.AbstractRevokingStore; import org.tron.core.db.RevokingStore; import org.tron.core.db2.common.IRevokingDB; +import org.tron.core.db2.common.WrappedByteArray; import org.tron.core.db2.core.Chainbase.Cursor; import org.tron.core.exception.ItemNotFoundException; @@ -171,4 +172,10 @@ public Set getValuesNext(byte[] key, long limit) { public List getKeysNext(byte[] key, long limit) { return dbSource.getKeysNext(key, limit); } + + @Override + public Map prefixQuery(byte[] key) { + return dbSource.prefixQuery(key); + } + } diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java index b69d55098c8..1d399b09f5f 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java @@ -7,20 +7,28 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; + +import com.google.common.primitives.Longs; import lombok.Getter; +import org.tron.core.ChainBaseManager; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.utils.AssetUtil; import org.tron.core.db2.common.DB; import org.tron.core.db2.common.Flusher; import org.tron.core.db2.common.WrappedByteArray; +import org.tron.core.store.AccountAssetStore; public class SnapshotRoot extends AbstractSnapshot { @Getter private Snapshot solidity; + private boolean isAccountDB; public SnapshotRoot(DB db) { this.db = db; solidity = this; isOptimized = "properties".equalsIgnoreCase(db.getDbName()); + isAccountDB = "account".equalsIgnoreCase(db.getDbName()); } @Override @@ -30,11 +38,29 @@ public byte[] get(byte[] key) { @Override public void put(byte[] key, byte[] value) { - db.put(key, value); + if (isAccountDB && AssetUtil.isAllowAssetOptimization()) { + AccountAssetStore store = ChainBaseManager.getInstance().getAccountAssetStore(); + AccountCapsule item = new AccountCapsule(value); + item.getInstance().getAssetV2Map().forEach((k, v) -> + store.put(item, k.getBytes(), Longs.toByteArray(v))); + item.clearAsset(); + db.put(key, item.getData()); + } else { + db.put(key, value); + } } @Override public void remove(byte[] key) { + if (isAccountDB && AssetUtil.isAllowAssetOptimization()) { + AccountAssetStore store = ChainBaseManager.getInstance().getAccountAssetStore(); + byte[] vale = get(key); + if (vale.length > 0) { + AccountCapsule item = new AccountCapsule(get(key)); + item.getAssetMapV2().forEach((k, v) -> + store.put(item, k.getBytes(), Longs.toByteArray(0))); + } + } db.remove(key); } diff --git a/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java b/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java index 5d4e0d6f91a..fe5cb58c9c1 100644 --- a/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java +++ b/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java @@ -1,25 +1,78 @@ package org.tron.core.store; +import com.google.common.primitives.Bytes; +import com.google.common.primitives.Longs; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import org.tron.core.capsule.AccountAssetCapsule; -import org.tron.core.db.TronStoreWithRevoking; +import org.tron.common.utils.ByteArray; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.db.TronDatabase; +import org.tron.core.db2.common.WrappedByteArray; +import org.tron.protos.Protocol; + +import java.util.HashMap; +import java.util.Map; @Slf4j(topic = "DB") @Component -public class AccountAssetStore extends TronStoreWithRevoking { +public class AccountAssetStore extends TronDatabase { @Autowired - protected AccountAssetStore(@Value("account-asset-issue") String dbName) { + protected AccountAssetStore(@Value("account-asset") String dbName) { super(dbName); } @Override - public AccountAssetCapsule get(byte[] key) { - byte[] value = revokingDB.getUnchecked(key); - return ArrayUtils.isEmpty(value) ? null : new AccountAssetCapsule(value); + public void put(byte[] key, byte[] item) { + dbSource.putData(key, item); } + + @Override + public void delete(byte[] key) { + dbSource.deleteData(key); + } + + @Override + public byte[] get(byte[] key) { + return dbSource.getData(key); + } + + @Override + public boolean has(byte[] key) { + return dbSource.getData(key) != null; + } + + public void put(AccountCapsule account, byte[] key, byte[] value) { + byte[] k = Bytes.concat(account.createDbKey(), key); + if (Longs.fromByteArray(value) == 0) { + delete(k); + } else { + put(k, value); + } + } + + public long getBalance(Protocol.Account account, byte[] key) { + byte[] k = Bytes.concat(account.getAddress().toByteArray(), key); + byte[] value = getUnchecked(k); + if (ArrayUtils.isEmpty(value)) { + return 0; + } + return Longs.fromByteArray(value); + } + + public Map getAllAssets(Protocol.Account account) { + Map map = prefixQuery(account.getAddress().toByteArray()); + Map assets = new HashMap<>(); + map.forEach((k, v) -> { + byte[] assetID = ByteArray.subArray(k.getBytes(), + account.getAddress().toByteArray().length, k.getBytes().length); + assets.put(ByteArray.toStr(assetID), Longs.fromByteArray(v)); + }); + account.getAssetV2Map().forEach((k, v) -> assets.put(k, v)); + return assets; + } + } diff --git a/chainbase/src/main/java/org/tron/core/store/AccountStore.java b/chainbase/src/main/java/org/tron/core/store/AccountStore.java index d98a94a84b8..8b13ee47f6f 100644 --- a/chainbase/src/main/java/org/tron/core/store/AccountStore.java +++ b/chainbase/src/main/java/org/tron/core/store/AccountStore.java @@ -1,5 +1,6 @@ package org.tron.core.store; +import com.google.common.primitives.Longs; import com.google.protobuf.ByteString; import com.typesafe.config.ConfigObject; import lombok.extern.slf4j.Slf4j; @@ -9,14 +10,11 @@ import org.springframework.stereotype.Component; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.Commons; -import org.tron.core.capsule.AccountAssetCapsule; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.utils.AssetUtil; import org.tron.core.db.TronStoreWithRevoking; import org.tron.core.db.accountstate.AccountStateCallBackUtils; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.AccountAsset; import org.tron.protos.contract.BalanceContract.TransactionBalanceTrace; import org.tron.protos.contract.BalanceContract.TransactionBalanceTrace.Operation; @@ -87,18 +85,6 @@ public void put(byte[] key, AccountCapsule item) { } } } - - if (AssetUtil.isAllowAssetOptimization()) { - Account account = item.getInstance(); - AccountAsset accountAsset = AssetUtil.getAsset(account); - if (null != accountAsset) { - accountAssetStore.put(key, new AccountAssetCapsule( - accountAsset)); - account = AssetUtil.clearAsset(account); - item.setIsAssetImport(false); - item.setInstance(account); - } - } super.put(key, item); accountStateCallBackUtils.accountCallBack(key, item); } @@ -116,7 +102,6 @@ public void delete(byte[] key) { accountTraceStore.recordBalanceWithBlock(key, blockId.getNum(), 0); } } - super.delete(key); if (AssetUtil.isAllowAssetOptimization()) { diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index 386289436f7..bb8c30ff5b1 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -17,7 +17,8 @@ public enum ForkBlockVersionEnum { VERSION_4_1_2(20, 1596780000000L, 80), VERSION_4_2(21, 1596780000000L, 80), VERSION_4_3(22, 1596780000000L, 80), - VERSION_4_4(23, 1596780000000L, 80); + VERSION_4_4(23, 1596780000000L, 80), + VERSION_4_5(24, 1596780000000L, 80); @Getter private int value; diff --git a/framework/src/main/java/org/tron/common/storage/DepositImpl.java b/framework/src/main/java/org/tron/common/storage/DepositImpl.java index 7793c46a6e2..e44f942706c 100644 --- a/framework/src/main/java/org/tron/common/storage/DepositImpl.java +++ b/framework/src/main/java/org/tron/common/storage/DepositImpl.java @@ -423,8 +423,7 @@ public synchronized long addTokenBalance(byte[] address, byte[] tokenId, long va if (accountCapsule == null) { accountCapsule = createAccount(address, AccountType.Normal); } - long balance = accountCapsule.getAssetMapV2() - .getOrDefault(new String(tokenIdWithoutLeadingZero), new Long(0)); + long balance = accountCapsule.getAssetV2(new String(tokenIdWithoutLeadingZero)); if (value == 0) { return balance; } @@ -446,7 +445,7 @@ public synchronized long addTokenBalance(byte[] address, byte[] tokenId, long va Value V = Value.create(accountCapsule.getData(), Type.VALUE_TYPE_DIRTY | accountCache.get(key).getType().getType()); accountCache.put(key, V); - return accountCapsule.getAssetMapV2().get(new String(tokenIdWithoutLeadingZero)); + return accountCapsule.getAssetV2(new String(tokenIdWithoutLeadingZero)); } @Override @@ -487,7 +486,7 @@ public synchronized long getTokenBalance(byte[] address, byte[] tokenId) { return 0; } String tokenStr = new String(ByteUtil.stripLeadingZeroes(tokenId)); - return accountCapsule.getAssetMapV2().getOrDefault(tokenStr, 0L); + return accountCapsule.getAssetV2(tokenStr); } @Override diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index cf4d416e56c..fd999c0840e 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -332,7 +332,7 @@ public Account getAccount(Account account) { if (accountCapsule == null) { return null; } - accountCapsule.importAsset(); + accountCapsule.importAllAsset(); BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); processor.updateUsage(accountCapsule); @@ -363,7 +363,7 @@ public Account getAccountById(Account account) { if (accountCapsule == null) { return null; } - accountCapsule.importAsset(); + accountCapsule.importAllAsset(); BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); processor.updateUsage(accountCapsule); diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 54db6c5c290..dd9acb4ebcf 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1129,13 +1129,11 @@ public synchronized void pushBlock(final BlockCapsule block) ownerAddressSet.addAll(result); } - MetricsUtil.meterMark(MetricsKey.BLOCKCHAIN_BLOCK_PROCESS_TIME, - System.currentTimeMillis() - start); + long cost = System.currentTimeMillis() - start; + MetricsUtil.meterMark(MetricsKey.BLOCKCHAIN_BLOCK_PROCESS_TIME, cost); - logger.info("pushBlock block number:{}, cost/txs:{}/{}", - block.getNum(), - System.currentTimeMillis() - start, - block.getTransactions().size()); + logger.info("pushBlock block number:{}, cost/txs:{}/{} {}", + block.getNum(), cost, block.getTransactions().size(), cost > 1000); } public void updateDynamicProperties(BlockCapsule block) { @@ -1195,6 +1193,8 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block return null; } + long start = System.currentTimeMillis(); + if (Objects.nonNull(blockCap)) { chainBaseManager.getBalanceTraceStore().initCurrentTransactionBalanceTrace(trxCap); } @@ -1278,6 +1278,11 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block if (!eventPluginLoaded) { trxCap.setTrxTrace(null); } + long cost = System.currentTimeMillis() - start; + if (cost > 100) { + logger.info("Process transaction {} cost {}.", + Hex.toHexString(transactionInfo.getId()), cost); + } return transactionInfo.getInstance(); } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java b/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java index 4d7fa13109d..d434f31ea0f 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java @@ -147,7 +147,7 @@ public void TransferTokenTest() deposit.commit(); Assert.assertEquals(100, chainBaseManager.getAccountStore() - .get(contractAddress).getAssetMapV2().get(String.valueOf(id)).longValue()); + .get(contractAddress).getAssetV2MapForTest().get(String.valueOf(id)).longValue()); Assert.assertEquals(1000, chainBaseManager.getAccountStore().get(contractAddress).getBalance()); @@ -170,11 +170,11 @@ public void TransferTokenTest() Assert.assertNull(runtime.getRuntimeError()); Assert.assertEquals(9, - chainBaseManager.getAccountStore().get(Hex.decode(TRANSFER_TO)).getAssetMapV2() + chainBaseManager.getAccountStore().get(Hex.decode(TRANSFER_TO)).getAssetV2MapForTest() .get(String.valueOf(id)).longValue()); Assert.assertEquals(100 + tokenValue - 9, chainBaseManager.getAccountStore().get(contractAddress) - .getAssetMapV2().get(String.valueOf(id)).longValue()); + .getAssetV2MapForTest().get(String.valueOf(id)).longValue()); long energyCostWhenExist = runtime.getResult().getEnergyUsed(); // 3.Test transferToken To Non-exist address @@ -190,10 +190,10 @@ public void TransferTokenTest() Assert.assertNull(runtime.getRuntimeError()); Assert.assertEquals(100 + tokenValue * 2 - 18, - chainBaseManager.getAccountStore().get(contractAddress).getAssetMapV2() + chainBaseManager.getAccountStore().get(contractAddress).getAssetV2MapForTest() .get(String.valueOf(id)).longValue()); Assert.assertEquals(9, - chainBaseManager.getAccountStore().get(ecKey.getAddress()).getAssetMapV2() + chainBaseManager.getAccountStore().get(ecKey.getAddress()).getAssetV2MapForTest() .get(String.valueOf(id)).longValue()); long energyCostWhenNonExist = runtime.getResult().getEnergyUsed(); //4.Test Energy diff --git a/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java b/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java index 0a6e30f8897..77485b8f85e 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java @@ -17,7 +17,6 @@ import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.capsule.AccountAssetCapsule; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.config.DefaultConfig; @@ -134,8 +133,8 @@ public void TransferTokenTest() byte[] contractAddress = deployTransferTokenContract(id); deposit.commit(); Assert.assertEquals(100, - dbManager.getAccountStore().get(contractAddress).getAssetMapV2().get(String.valueOf(id)) - .longValue()); + dbManager.getAccountStore().get(contractAddress) + .getAssetV2MapForTest().get(String.valueOf(id)).longValue()); Assert.assertEquals(1000, dbManager.getAccountStore().get(contractAddress).getBalance()); String selectorStr = "TransferTokenTo(address,trcToken,uint256)"; @@ -158,10 +157,10 @@ public void TransferTokenTest() org.testng.Assert.assertNull(runtime.getRuntimeError()); Assert.assertEquals(100 + tokenValue - 9, - dbManager.getAccountStore().get(contractAddress).getAssetMapV2().get(String.valueOf(id)) - .longValue()); - Assert.assertEquals(9, dbManager.getAccountStore().get(Hex.decode(TRANSFER_TO)).getAssetMapV2() - .get(String.valueOf(id)).longValue()); + dbManager.getAccountStore().get(contractAddress).getAssetV2MapForTest() + .get(String.valueOf(id)).longValue()); + Assert.assertEquals(9, dbManager.getAccountStore().get(Hex.decode(TRANSFER_TO)) + .getAssetV2MapForTest().get(String.valueOf(id)).longValue()); /* suicide test */ // create new token: testToken2 @@ -183,10 +182,10 @@ public void TransferTokenTest() runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction2, dbManager, null); org.testng.Assert.assertNull(runtime.getRuntimeError()); Assert.assertEquals(100 + tokenValue - 9 + 9, - dbManager.getAccountStore().get(Hex.decode(TRANSFER_TO)).getAssetMapV2() + dbManager.getAccountStore().get(Hex.decode(TRANSFER_TO)).getAssetV2MapForTest() .get(String.valueOf(id)).longValue()); - Assert.assertEquals(99, dbManager.getAccountStore().get(Hex.decode(TRANSFER_TO)).getAssetMapV2() - .get(String.valueOf(id2)).longValue()); + Assert.assertEquals(99, dbManager.getAccountStore().get(Hex.decode(TRANSFER_TO)) + .getAssetV2MapForTest().get(String.valueOf(id2)).longValue()); } private byte[] deployTransferTokenContract(long id) diff --git a/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java b/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java index d52643a4237..db5e63b77a8 100755 --- a/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java +++ b/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java @@ -14,7 +14,6 @@ import org.tron.common.runtime.RuntimeImpl; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; -import org.tron.core.capsule.AccountAssetCapsule; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.TransactionCapsule; @@ -155,9 +154,6 @@ public void createCapsule() { .put(toAccountCapsule.getAddress().toByteArray(), toAccountCapsule); chainBaseManager.getAccountStore().put(assetCapsule.getAddress().toByteArray(), assetCapsule); chainBaseManager.getAccountStore().put(assetCapsule2.getAddress().toByteArray(), assetCapsule2); - - chainBaseManager.getAccountAssetStore().put(ownerCapsule.getAddress().toByteArray(), - new AccountAssetCapsule(ownerCapsule.getAddress())); } private TransferAssetContract getTransferAssetContract() { @@ -486,9 +482,6 @@ public void testConsumeOwner() throws Exception { .get(ByteArray.fromHexString(OWNER_ADDRESS)); ownerCapsule.setFrozen(10_000_000L, 0L); - AccountAssetCapsule ownerAssetCapsule = chainBaseManager.getAccountAssetStore() - .get(ByteArray.fromHexString(OWNER_ADDRESS)); - chainBaseManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); TransactionResultCapsule ret = new TransactionResultCapsule(); diff --git a/framework/src/test/java/org/tron/core/actuator/AssetIssueActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/AssetIssueActuatorTest.java index 728e46dd569..1fc858f0804 100755 --- a/framework/src/test/java/org/tron/core/actuator/AssetIssueActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/AssetIssueActuatorTest.java @@ -22,7 +22,6 @@ import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.capsule.AccountAssetCapsule; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.TransactionResultCapsule; @@ -94,17 +93,6 @@ public static void destroy() { */ @Before public void createCapsule() { - - AccountAssetCapsule ownerAddressFirstAsset = - new AccountAssetCapsule(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); - AccountAssetCapsule ownerAddressSecondAsset = - new AccountAssetCapsule( - ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS_SECOND))); - dbManager.getAccountAssetStore().put(ownerAddressFirstAsset.getAddress().toByteArray(), - ownerAddressFirstAsset); - dbManager.getAccountAssetStore().put(ownerAddressSecondAsset.getAddress().toByteArray(), - ownerAddressSecondAsset); - AccountCapsule ownerCapsule = new AccountCapsule(ByteString.copyFromUtf8("owner"), ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), AccountType.Normal, dbManager.getDynamicPropertiesStore().getAssetIssueFee()); @@ -169,7 +157,7 @@ public void SameTokenNameCloseAssetIssueSuccess() { Assert.assertEquals(6, assetIssueCapsule.getPrecision()); Assert.assertEquals(NUM, assetIssueCapsule.getNum()); Assert.assertEquals(TRX_NUM, assetIssueCapsule.getTrxNum()); - Assert.assertEquals(owner.getAssetMap().get(NAME).longValue(), TOTAL_SUPPLY); + Assert.assertEquals(owner.getAssetMapForTest().get(NAME).longValue(), TOTAL_SUPPLY); // check V2 long tokenIdNum = dbManager.getDynamicPropertiesStore().getTokenIdNum(); AssetIssueCapsule assetIssueCapsuleV2 = dbManager.getAssetIssueV2Store() @@ -178,7 +166,7 @@ public void SameTokenNameCloseAssetIssueSuccess() { Assert.assertEquals(0, assetIssueCapsuleV2.getPrecision()); Assert.assertEquals(NUM, assetIssueCapsuleV2.getNum()); Assert.assertEquals(TRX_NUM, assetIssueCapsuleV2.getTrxNum()); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), + Assert.assertEquals(owner.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), TOTAL_SUPPLY); } catch (ContractValidateException e) { @@ -222,7 +210,7 @@ public void oldNotUpdateAssetIssueSuccess() { Assert.assertEquals(6, assetIssueCapsuleV2.getPrecision()); Assert.assertEquals(NUM, assetIssueCapsuleV2.getNum()); Assert.assertEquals(TRX_NUM, assetIssueCapsuleV2.getTrxNum()); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), + Assert.assertEquals(owner.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), TOTAL_SUPPLY); } catch (ContractValidateException e) { @@ -265,7 +253,7 @@ public void SameTokenNameOpenAssetIssueSuccess() { Assert.assertEquals(6, assetIssueCapsuleV2.getPrecision()); Assert.assertEquals(NUM, assetIssueCapsuleV2.getNum()); Assert.assertEquals(TRX_NUM, assetIssueCapsuleV2.getTrxNum()); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), + Assert.assertEquals(owner.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), TOTAL_SUPPLY); } catch (ContractValidateException e) { @@ -732,8 +720,8 @@ public void assetNameTest() { Assert.assertEquals(owner.getBalance(), 0L); Assert.assertEquals(dbManager.getAccountStore().getBlackhole().getBalance(), blackholeBalance + dbManager.getDynamicPropertiesStore().getAssetIssueFee()); - Assert.assertEquals(owner.getAssetMap().get("testname0123456789abcdefghijgklm").longValue(), - TOTAL_SUPPLY); + Assert.assertEquals(owner.getAssetMapForTest() + .get("testname0123456789abcdefghijgklm").longValue(), TOTAL_SUPPLY); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -769,7 +757,7 @@ public void assetNameTest() { Assert.assertEquals(owner.getBalance(), 0L); Assert.assertEquals(dbManager.getAccountStore().getBlackhole().getBalance(), blackholeBalance + dbManager.getDynamicPropertiesStore().getAssetIssueFee()); - Assert.assertEquals(owner.getAssetMap().get("0").longValue(), TOTAL_SUPPLY); + Assert.assertEquals(owner.getAssetMapForTest().get("0").longValue(), TOTAL_SUPPLY); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -891,7 +879,7 @@ public void urlTest() { Assert.assertEquals(owner.getBalance(), 0L); Assert.assertEquals(dbManager.getAccountStore().getBlackhole().getBalance(), blackholeBalance + dbManager.getDynamicPropertiesStore().getAssetIssueFee()); - Assert.assertEquals(owner.getAssetMap().get(NAME).longValue(), TOTAL_SUPPLY); + Assert.assertEquals(owner.getAssetMapForTest().get(NAME).longValue(), TOTAL_SUPPLY); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -927,7 +915,7 @@ public void urlTest() { Assert.assertEquals(owner.getBalance(), 0L); Assert.assertEquals(dbManager.getAccountStore().getBlackhole().getBalance(), blackholeBalance + dbManager.getDynamicPropertiesStore().getAssetIssueFee()); - Assert.assertEquals(owner.getAssetMap().get(NAME).longValue(), TOTAL_SUPPLY); + Assert.assertEquals(owner.getAssetMapForTest().get(NAME).longValue(), TOTAL_SUPPLY); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -963,7 +951,7 @@ public void urlTest() { Assert.assertEquals(owner.getBalance(), 0L); Assert.assertEquals(dbManager.getAccountStore().getBlackhole().getBalance(), blackholeBalance + dbManager.getDynamicPropertiesStore().getAssetIssueFee()); - Assert.assertEquals(owner.getAssetMap().get(NAME).longValue(), TOTAL_SUPPLY); + Assert.assertEquals(owner.getAssetMapForTest().get(NAME).longValue(), TOTAL_SUPPLY); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -1048,7 +1036,7 @@ public void descriptionTest() { Assert.assertEquals(owner.getBalance(), 0L); Assert.assertEquals(dbManager.getAccountStore().getBlackhole().getBalance(), blackholeBalance + dbManager.getDynamicPropertiesStore().getAssetIssueFee()); - Assert.assertEquals(owner.getAssetMap().get(NAME).longValue(), TOTAL_SUPPLY); + Assert.assertEquals(owner.getAssetMapForTest().get(NAME).longValue(), TOTAL_SUPPLY); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -1084,7 +1072,7 @@ public void descriptionTest() { Assert.assertEquals(owner.getBalance(), 0L); Assert.assertEquals(dbManager.getAccountStore().getBlackhole().getBalance(), blackholeBalance + dbManager.getDynamicPropertiesStore().getAssetIssueFee()); - Assert.assertEquals(owner.getAssetMap().get(NAME).longValue(), TOTAL_SUPPLY); + Assert.assertEquals(owner.getAssetMapForTest().get(NAME).longValue(), TOTAL_SUPPLY); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -1120,7 +1108,7 @@ public void descriptionTest() { Assert.assertEquals(owner.getBalance(), 0L); Assert.assertEquals(dbManager.getAccountStore().getBlackhole().getBalance(), blackholeBalance + dbManager.getDynamicPropertiesStore().getAssetIssueFee()); - Assert.assertEquals(owner.getAssetMap().get(NAME).longValue(), TOTAL_SUPPLY); + Assert.assertEquals(owner.getAssetMapForTest().get(NAME).longValue(), TOTAL_SUPPLY); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -1505,7 +1493,7 @@ public void issueTimeTest() { .get(ByteArray.fromHexString(OWNER_ADDRESS)); Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); Assert.assertEquals(account.getAssetIssuedName().toStringUtf8(), NAME); - Assert.assertEquals(account.getAssetMap().size(), 1); + Assert.assertEquals(account.getAssetMapForTest().size(), 1); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -1789,7 +1777,7 @@ public void IssueSameTokenNameAssert() { Assert.assertEquals(owner.getBalance(), 0L); Assert.assertEquals(dbManager.getAccountStore().getBlackhole().getBalance(), blackholeBalance + dbManager.getDynamicPropertiesStore().getAssetIssueFee()); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), + Assert.assertEquals(owner.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), TOTAL_SUPPLY); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java index 517d64a3b6f..51f658bcbb4 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java @@ -18,7 +18,6 @@ import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.capsule.AccountAssetCapsule; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.ExchangeCapsule; @@ -92,18 +91,6 @@ public static void destroy() { @Before public void initTest() { - AccountAssetCapsule ownerAddressFirstAsset = - new AccountAssetCapsule(ByteString.copyFrom( - ByteArray.fromHexString(OWNER_ADDRESS_FIRST))); - AccountAssetCapsule ownerAddressSecondAsset = - new AccountAssetCapsule(ByteString.copyFrom( - ByteArray.fromHexString(OWNER_ADDRESS_SECOND))); - dbManager.getAccountAssetStore().put(ownerAddressFirstAsset.getAddress().toByteArray(), - ownerAddressFirstAsset); - dbManager.getAccountAssetStore().put(ownerAddressSecondAsset.getAddress().toByteArray(), - ownerAddressSecondAsset); - - AccountCapsule ownerAccountFirstCapsule = new AccountCapsule( ByteString.copyFromUtf8(ACCOUNT_NAME_FIRST), @@ -206,7 +193,7 @@ public void sameTokenNameCloseSuccessExchangeCreate() { Assert.assertEquals(secondTokenBalance, exchangeCapsule.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(10000_000000L - 1024_000000L, accountCapsule.getBalance()); Assert.assertEquals(0L, assetMap.get(firstTokenId).longValue()); Assert.assertEquals(0L, assetMap.get(secondTokenId).longValue()); @@ -229,7 +216,7 @@ public void sameTokenNameCloseSuccessExchangeCreate() { Assert.assertEquals(secondTokenBalance, exchangeCapsuleV2.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map getAssetV2Map = accountCapsule.getAssetMapV2(); + Map getAssetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(10000_000000L - 1024_000000L, accountCapsule.getBalance()); Assert.assertEquals(0L, getAssetV2Map.get(firstTokenId).longValue()); Assert.assertEquals(0L, getAssetV2Map.get(secondTokenId).longValue()); @@ -292,7 +279,7 @@ public void sameTokenNameCloseSuccessExchangeCreate2() { Assert.assertEquals(secondTokenBalance, exchangeCapsule.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(200_000_000_000000L - 1024_000000L - firstTokenBalance, accountCapsule.getBalance()); Assert.assertEquals(100_000_000L, assetMap.get(secondTokenId).longValue()); @@ -313,7 +300,7 @@ public void sameTokenNameCloseSuccessExchangeCreate2() { Assert.assertEquals(secondTokenBalance, exchangeCapsuleV2.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map getAssetV2Map = accountCapsule.getAssetMapV2(); + Map getAssetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(200_000_000_000000L - 1024_000000L - firstTokenBalance, accountCapsule.getBalance()); Assert.assertEquals(100_000_000L, getAssetV2Map.get(secondTokenId).longValue()); @@ -383,7 +370,7 @@ public void oldNotUpdateSuccessExchangeCreate2() { Assert.assertEquals(secondTokenBalance, exchangeCapsuleV2.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map getAssetV2Map = accountCapsule.getAssetMapV2(); + Map getAssetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(200_000_000_000000L - 1024_000000L - firstTokenBalance, accountCapsule.getBalance()); Assert.assertEquals(100_000_000L, getAssetV2Map.get(secondTokenId).longValue()); @@ -467,7 +454,7 @@ public void sameTokenNameOpenSuccessExchangeCreate() { Assert.assertEquals(secondTokenBalance, exchangeCapsuleV2.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map getAssetV2Map = accountCapsule.getAssetMapV2(); + Map getAssetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(10000_000000L - 1024_000000L, accountCapsule.getBalance()); Assert.assertEquals(0L, getAssetV2Map.get(firstTokenId).longValue()); Assert.assertEquals(0L, getAssetV2Map.get(secondTokenId).longValue()); @@ -537,7 +524,7 @@ public void sameTokenNameOpenSuccessExchangeCreate2() { Assert.assertEquals(secondTokenBalance, exchangeCapsuleV2.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map getAssetV2Map = accountCapsule.getAssetMapV2(); + Map getAssetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(200_000_000_000000L - 1024_000000L - firstTokenBalance, accountCapsule.getBalance()); Assert.assertEquals(100_000_000L, getAssetV2Map.get(secondTokenId).longValue()); diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java index 9f792e871ef..28d699a26e0 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java @@ -19,7 +19,6 @@ import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.capsule.AccountAssetCapsule; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.ExchangeCapsule; @@ -92,19 +91,6 @@ public static void destroy() { */ @Before public void initTest() { - AccountAssetCapsule ownerAddressFirstAsset = - new AccountAssetCapsule(ByteString.copyFrom( - ByteArray.fromHexString(OWNER_ADDRESS_FIRST))); - AccountAssetCapsule ownerAddressSecondAsset = - new AccountAssetCapsule(ByteString.copyFrom( - ByteArray.fromHexString(OWNER_ADDRESS_SECOND))); - dbManager.getAccountAssetStore().put( - ownerAddressFirstAsset.getAddress().toByteArray(), - ownerAddressFirstAsset); - dbManager.getAccountAssetStore().put( - ownerAddressSecondAsset.getAddress().toByteArray(), - ownerAddressSecondAsset); - AccountCapsule ownerAccountFirstCapsule = new AccountCapsule( ByteString.copyFromUtf8(ACCOUNT_NAME_FIRST), @@ -278,7 +264,7 @@ public void SameTokenNameCloseSuccessExchangeInject() { Assert.assertEquals(600000000L, exchangeCapsuleV2.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(0L, assetMap.get(firstTokenId).longValue()); Assert.assertEquals(0L, assetMap.get(secondTokenId).longValue()); @@ -372,7 +358,7 @@ public void OldNotUpdateSuccessExchangeInject() { Assert.assertEquals(600000000L, exchangeCapsuleV2.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetMap = accountCapsule.getAssetMapV2(); + Map assetMap = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(0L, assetMap.get(String.valueOf(1)).longValue()); Assert.assertEquals(0L, assetMap.get(String.valueOf(2)).longValue()); @@ -460,7 +446,7 @@ public void SameTokenNameOpenSuccessExchangeInject() { Assert.assertEquals(600000000L, exchangeCapsuleV2.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(0L, assetV2Map.get(firstTokenId).longValue()); Assert.assertEquals(0L, assetV2Map.get(secondTokenId).longValue()); @@ -538,7 +524,7 @@ public void SameTokenNameCloseSuccessExchangeInject2() { Assert.assertEquals(11_000_000L, exchangeCapsule2.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(0L, accountCapsule.getBalance()); Assert.assertEquals(3_000_000L, assetMap.get(secondTokenId).longValue()); @@ -614,7 +600,7 @@ public void SameTokenNameOpenSuccessExchangeInject2() { Assert.assertEquals(11_000_000L, exchangeV2Capsule.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(0L, accountCapsule.getBalance()); Assert.assertEquals(3_000_000L, assetV2Map.get(secondTokenId).longValue()); diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java index bb2dd131683..c3381da72df 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java @@ -20,7 +20,6 @@ import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.capsule.AccountAssetCapsule; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.ExchangeCapsule; @@ -93,19 +92,6 @@ public static void destroy() { */ @Before public void initTest() { - AccountAssetCapsule ownerAddressFirstAsset = - new AccountAssetCapsule(ByteString.copyFrom( - ByteArray.fromHexString(OWNER_ADDRESS_FIRST))); - AccountAssetCapsule ownerAddressSecondAsset = - new AccountAssetCapsule(ByteString.copyFrom( - ByteArray.fromHexString(OWNER_ADDRESS_SECOND))); - dbManager.getAccountAssetStore().put( - ownerAddressFirstAsset.getAddress().toByteArray(), - ownerAddressFirstAsset); - dbManager.getAccountAssetStore().put( - ownerAddressSecondAsset.getAddress().toByteArray(), - ownerAddressSecondAsset); - AccountCapsule ownerAccountFirstCapsule = new AccountCapsule( ByteString.copyFromUtf8(ACCOUNT_NAME_FIRST), @@ -247,7 +233,7 @@ public void SameTokenNameCloseSuccessExchangeTransaction() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get("def")); @@ -293,7 +279,7 @@ public void SameTokenNameCloseSuccessExchangeTransaction() { Assert.assertEquals(9999001L, exchangeCapsule2.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - assetMap = accountCapsule.getAssetMap(); + assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L - quant, accountCapsule.getBalance()); Assert.assertEquals(999L, assetMap.get("abc").longValue()); @@ -325,7 +311,7 @@ public void oldNotUpdateSuccessExchangeTransaction() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get("def")); @@ -372,7 +358,7 @@ public void oldNotUpdateSuccessExchangeTransaction() { Assert.assertEquals(9999001L, exchangeCapsule2.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - assetMap = accountCapsule.getAssetMapV2(); + assetMap = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(20000_000000L - quant, accountCapsule.getBalance()); Assert.assertEquals(999L, assetMap.get("1").longValue()); @@ -404,7 +390,7 @@ public void SameTokenNameOpenSuccessExchangeTransaction() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetV2Map.get("456")); @@ -445,7 +431,7 @@ public void SameTokenNameOpenSuccessExchangeTransaction() { Assert.assertEquals(9999001L, exchangeV2Capsule.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - assetV2Map = accountCapsule.getAssetMapV2(); + assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(20000_000000L - quant, accountCapsule.getBalance()); Assert.assertEquals(999L, assetV2Map.get("123").longValue()); @@ -481,7 +467,7 @@ public void SameTokenNameCloseSuccessExchangeTransaction2() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -528,7 +514,7 @@ public void SameTokenNameCloseSuccessExchangeTransaction2() { Assert.assertEquals(199998001L, exchangeCapsule2.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - assetMap = accountCapsule.getAssetMap(); + assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(9000L, assetMap.get("abc").longValue()); Assert.assertEquals(1999L, assetMap.get("def").longValue()); @@ -563,7 +549,7 @@ public void SameTokenNameOpenSuccessExchangeTransaction2() { AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.addAssetAmountV2(tokenId.getBytes(), 10000, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetV2Map.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -605,7 +591,7 @@ public void SameTokenNameOpenSuccessExchangeTransaction2() { Assert.assertEquals(199998001L, exchangeCapsuleV2.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - assetV2Map = accountCapsule.getAssetMapV2(); + assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(9000L, assetV2Map.get("123").longValue()); Assert.assertEquals(1999L, assetV2Map.get("456").longValue()); @@ -639,7 +625,7 @@ public void SameTokenNameCloseInvalidAddress() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -685,7 +671,7 @@ public void SameTokenNameOpenInvalidAddress() { accountCapsule.addAssetAmountV2(tokenId.getBytes(), 10000, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetV2Map.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -730,7 +716,7 @@ public void SameTokenNameCloseNoEnoughBalance() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -780,7 +766,7 @@ public void SameTokenNameOpenNoEnoughBalance() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -830,7 +816,7 @@ public void SameTokenNameCloseNoAccount() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -877,7 +863,7 @@ public void SameTokenNameOpenNoAccount() { accountCapsule.addAssetAmountV2(tokenId.getBytes(), 10000, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetV2Map.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -921,7 +907,7 @@ public void SameTokenNameCloseExchangeNotExist() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -966,7 +952,7 @@ public void SameTokenNameOpenExchangeNotExist() { AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.addAssetAmountV2(tokenId.getBytes(), 10000, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetV2Map.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -1010,7 +996,7 @@ public void SameTokenNameCloseTokenIsNotInExchange() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -1056,7 +1042,7 @@ public void SameTokenNameOpenTokenIsNotInExchange() { accountCapsule .addAssetAmountV2(tokenId.getBytes(), 10000, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetV2Map.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -1100,7 +1086,7 @@ public void SameTokenNameCloseTokenBalanceZero() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -1154,7 +1140,7 @@ public void SameTokenNameOpenTokenBalanceZero() { accountCapsule .addAssetAmountV2(tokenId.getBytes(), 10000, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetV2Map.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -1206,7 +1192,7 @@ public void SameTokenNameCloseTokenQuantLessThanZero() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -1252,7 +1238,7 @@ public void SameTokenNameOpenTokenQuantLessThanZero() { accountCapsule .addAssetAmountV2(tokenId.getBytes(), 10000, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetV2Map.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -1296,7 +1282,7 @@ public void SameTokenNameCloseTokenBalanceGreaterThanBalanceLimit() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -1342,7 +1328,7 @@ public void SameTokenNameOpenTokenBalanceGreaterThanBalanceLimit() { accountCapsule .addAssetAmountV2(tokenId.getBytes(), 10000, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetV2Map.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -1385,7 +1371,7 @@ public void SameTokenNameCloseBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); accountCapsule.setBalance(quant - 1); Assert.assertEquals(null, assetMap.get(buyTokenId)); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1428,7 +1414,7 @@ public void SameTokenNameOpenBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); accountCapsule.setBalance(quant - 1); Assert.assertEquals(null, assetV2Map.get(buyTokenId)); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1472,7 +1458,7 @@ public void SameTokenNameCloseTokenBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.addAssetAmount(tokenId.getBytes(), quant - 1); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -1517,7 +1503,7 @@ public void SameTokenNameOpenTokenBalanceNotEnough() { AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.addAssetAmountV2(tokenId.getBytes(), quant - 1, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetV2Map.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -1561,7 +1547,7 @@ public void SameTokenNameCloseTokenRequiredNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.addAssetAmount(tokenId.getBytes(), quant); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -1616,7 +1602,7 @@ public void SameTokenNameOpenTokenRequiredNotEnough() { accountCapsule .addAssetAmountV2(tokenId.getBytes(), quant, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetV2Map.get(buyTokenId)); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java index da23051a3c9..78b0c18294a 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java @@ -20,7 +20,6 @@ import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.capsule.AccountAssetCapsule; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.ExchangeCapsule; @@ -111,11 +110,6 @@ public void initTest() { dbManager.getAccountStore() .put(ownerAccountSecondCapsule.getAddress().toByteArray(), ownerAccountSecondCapsule); - dbManager.getAccountAssetStore().put(ownerAccountFirstCapsule.getAddress().toByteArray(), - new AccountAssetCapsule(ownerAccountFirstCapsule.getAddress())); - dbManager.getAccountAssetStore().put(ownerAccountSecondCapsule.getAddress().toByteArray(), - new AccountAssetCapsule(ownerAccountSecondCapsule.getAddress())); - dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(1000000); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(10); dbManager.getDynamicPropertiesStore().saveNextMaintenanceTime(2000000); @@ -278,7 +272,7 @@ public void SameTokenNameCloseSuccessExchangeWithdraw() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(firstTokenId)); Assert.assertEquals(null, assetMap.get(secondTokenId)); @@ -314,7 +308,7 @@ public void SameTokenNameCloseSuccessExchangeWithdraw() { Assert.assertEquals(0L, exchangeCapsule2.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - assetMap = accountCapsule.getAssetMap(); + assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(firstTokenQuant, assetMap.get(firstTokenId).longValue()); Assert.assertEquals(secondTokenQuant, assetMap.get(secondTokenId).longValue()); @@ -352,7 +346,7 @@ public void oldNotUpdateSuccessExchangeWithdraw() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(firstTokenId)); Assert.assertEquals(null, assetMap.get(secondTokenId)); @@ -389,7 +383,7 @@ public void oldNotUpdateSuccessExchangeWithdraw() { Assert.assertEquals(0L, exchangeCapsule2.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - assetMap = accountCapsule.getAssetMapV2(); + assetMap = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(firstTokenQuant, assetMap.get(String.valueOf(1)).longValue()); Assert.assertEquals(secondTokenQuant, assetMap.get(String.valueOf(2)).longValue()); @@ -426,7 +420,7 @@ public void SameTokenNameOpenSuccessExchangeWithdraw() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetV2Map.get(firstTokenId)); Assert.assertEquals(null, assetV2Map.get(secondTokenId)); @@ -458,7 +452,7 @@ public void SameTokenNameOpenSuccessExchangeWithdraw() { Assert.assertEquals(0L, exchangeCapsuleV2.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - assetV2Map = accountCapsule.getAssetMapV2(); + assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(firstTokenQuant, assetV2Map.get(firstTokenId).longValue()); Assert.assertEquals(secondTokenQuant, assetV2Map.get(secondTokenId).longValue()); @@ -493,7 +487,7 @@ public void SameTokenNameCloseSuccessExchangeWithdraw2() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(secondTokenId)); @@ -530,7 +524,7 @@ public void SameTokenNameCloseSuccessExchangeWithdraw2() { Assert.assertEquals(0L, exchangeCapsule2.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - assetMap = accountCapsule.getAssetMap(); + assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(firstTokenQuant + 10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(10_000_000L, assetMap.get(secondTokenId).longValue()); @@ -564,7 +558,7 @@ public void SameTokenNameOpenSuccessExchangeWithdraw2() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetV2Map.get(secondTokenId)); @@ -595,7 +589,7 @@ public void SameTokenNameOpenSuccessExchangeWithdraw2() { Assert.assertEquals(0L, exchangeCapsuleV2.getSecondTokenBalance()); accountCapsule = dbManager.getAccountStore().get(ownerAddress); - assetV2Map = accountCapsule.getAssetMapV2(); + assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(firstTokenQuant + 10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(10_000_000L, assetV2Map.get(secondTokenId).longValue()); @@ -629,7 +623,7 @@ public void SameTokenNameCloseInvalidAddress() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(firstTokenId)); Assert.assertEquals(null, assetMap.get(secondTokenId)); @@ -672,7 +666,7 @@ public void SameTokenNameOpenInvalidAddress() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetV2Map.get(firstTokenId)); Assert.assertEquals(null, assetV2Map.get(secondTokenId)); @@ -716,7 +710,7 @@ public void SameTokenNameCloseNoAccount() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(firstTokenId)); Assert.assertEquals(null, assetMap.get(secondTokenId)); @@ -761,7 +755,7 @@ public void SameTokenNameOpenNoAccount() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetV2Map.get(firstTokenId)); Assert.assertEquals(null, assetV2Map.get(secondTokenId)); @@ -805,7 +799,7 @@ public void SameTokenNameCloseExchangeNotExist() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(firstTokenId)); Assert.assertEquals(null, assetMap.get(secondTokenId)); @@ -849,7 +843,7 @@ public void SameTokenNameOpenExchangeNotExist() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetV2Map.get(firstTokenId)); Assert.assertEquals(null, assetV2Map.get(secondTokenId)); @@ -1580,7 +1574,7 @@ public void SameTokenNameCloseExchangeBalanceIsNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(firstTokenId)); Assert.assertEquals(null, assetMap.get(secondTokenId)); @@ -1624,7 +1618,7 @@ public void SameTokenNameOpenExchangeBalanceIsNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetV2Map.get(firstTokenId)); Assert.assertEquals(null, assetV2Map.get(secondTokenId)); @@ -1668,7 +1662,7 @@ public void SameTokenNameCloseExchangeBalanceIsNotEnough2() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetMap = accountCapsule.getAssetMap(); + Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(secondTokenId)); @@ -1711,7 +1705,7 @@ public void SameTokenNameOpenExchangeBalanceIsNotEnough2() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Map assetV2Map = accountCapsule.getAssetMapV2(); + Map assetV2Map = accountCapsule.getAssetV2MapForTest(); Assert.assertEquals(10000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetV2Map.get(secondTokenId)); diff --git a/framework/src/test/java/org/tron/core/actuator/MarketCancelOrderActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/MarketCancelOrderActuatorTest.java index 6ec03786345..ec6404b47a1 100644 --- a/framework/src/test/java/org/tron/core/actuator/MarketCancelOrderActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/MarketCancelOrderActuatorTest.java @@ -18,7 +18,6 @@ import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.capsule.AccountAssetCapsule; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.MarketAccountOrderCapsule; @@ -108,16 +107,6 @@ public void initTest() { byte[] ownerAddressFirstBytes = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); byte[] ownerAddressSecondBytes = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); - AccountAssetCapsule ownerAddressFirstAsset = - new AccountAssetCapsule(ByteString.copyFrom(ownerAddressFirstBytes)); - AccountAssetCapsule ownerAddressSecondAsset = - new AccountAssetCapsule(ByteString.copyFrom(ownerAddressSecondBytes)); - - dbManager.getAccountAssetStore().put(ownerAddressFirstAsset.getAddress().toByteArray(), - ownerAddressFirstAsset); - dbManager.getAccountAssetStore().put(ownerAddressSecondAsset.getAddress().toByteArray(), - ownerAddressSecondAsset); - AccountCapsule ownerAccountFirstCapsule = new AccountCapsule( ByteString.copyFromUtf8(ACCOUNT_NAME_FIRST), @@ -514,7 +503,7 @@ public void multipleOrdersAtThisPrice1() throws Exception { dbManager.getDynamicPropertiesStore().getMarketCancelFee() + accountCapsule.getBalance()); //check token number return - Assert.assertEquals(100L,accountCapsule.getAssetMapV2().get(TOKEN_ID_ONE).longValue()); + Assert.assertEquals(100L,accountCapsule.getAssetV2MapForTest().get(TOKEN_ID_ONE).longValue()); //check accountOrder accountOrderCapsule = marketAccountStore.get(ByteArray.fromHexString(OWNER_ADDRESS_FIRST)); @@ -691,7 +680,7 @@ public void onlyOneOrderAtThisPriceAndHasMultiplePrices() throws Exception { +accountCapsule.getBalance()); //check token number return - Assert.assertEquals(100L, accountCapsule.getAssetMapV2().get(TOKEN_ID_ONE).longValue()); + Assert.assertEquals(100L, accountCapsule.getAssetV2MapForTest().get(TOKEN_ID_ONE).longValue()); //check accountOrder accountOrderCapsule = marketAccountStore.get(ByteArray.fromHexString(OWNER_ADDRESS_FIRST)); @@ -775,7 +764,7 @@ public void onlyOneOrderAtThisPriceAndHasOnlyOnePrice() throws Exception { +accountCapsule.getBalance()); //check token number return - Assert.assertEquals(100L,accountCapsule.getAssetMapV2().get(TOKEN_ID_ONE).longValue()); + Assert.assertEquals(100L,accountCapsule.getAssetV2MapForTest().get(TOKEN_ID_ONE).longValue()); //check accountOrder accountOrderCapsule = marketAccountStore.get(ByteArray.fromHexString(OWNER_ADDRESS_FIRST)); diff --git a/framework/src/test/java/org/tron/core/actuator/MarketSellAssetActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/MarketSellAssetActuatorTest.java index 9713f779b95..cf654af891d 100644 --- a/framework/src/test/java/org/tron/core/actuator/MarketSellAssetActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/MarketSellAssetActuatorTest.java @@ -19,7 +19,6 @@ import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.capsule.AccountAssetCapsule; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.MarketAccountOrderCapsule; @@ -108,17 +107,6 @@ public void initTest() { byte[] ownerAddressFirstBytes = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); byte[] ownerAddressSecondBytes = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); - AccountAssetCapsule ownerAddressFirstAsset = - new AccountAssetCapsule(ByteString.copyFrom( - ByteArray.fromHexString(OWNER_ADDRESS_FIRST))); - AccountAssetCapsule ownerAddressSecondAsset = - new AccountAssetCapsule( - ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS_SECOND))); - dbManager.getAccountAssetStore().put(ownerAddressFirstAsset.getAddress().toByteArray(), - ownerAddressFirstAsset); - dbManager.getAccountAssetStore().put(ownerAddressSecondAsset.getAddress().toByteArray(), - ownerAddressSecondAsset); - AccountCapsule ownerAccountFirstCapsule = new AccountCapsule( ByteString.copyFromUtf8(ACCOUNT_NAME_FIRST), @@ -552,7 +540,7 @@ public void exceedMakerBuyOrderNumLimit() throws Exception { dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); dbManager.getAccountStore().put(ownerAddress, accountCapsule); Assert.assertEquals(sellTokenQuant * orderNum, - (long) accountCapsule.getAssetMapV2().get(sellTokenId)); + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); // Initialize the order book @@ -618,7 +606,8 @@ private void prepareAccount(String sellTokenId, String buyTokenId, accountCapsule.addAssetAmountV2(sellTokenId.getBytes(), sellTokenQuant, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); dbManager.getAccountStore().put(ownerAddress, accountCapsule); - Assert.assertEquals(sellTokenQuant, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(sellTokenQuant, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); } @@ -760,7 +749,8 @@ public void noBuyAddFirstSellOrder2() throws Exception { dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); dbManager.getAccountStore().put(ownerAddress, accountCapsule); long balanceBefore = accountCapsule.getBalance(); - Assert.assertEquals(sellTokenQuant, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(sellTokenQuant, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); MarketSellAssetActuator actuator = new MarketSellAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny(getContract( @@ -782,7 +772,7 @@ public void noBuyAddFirstSellOrder2() throws Exception { accountCapsule = dbManager.getAccountStore().get(ownerAddress); Assert.assertEquals(balanceBefore, dbManager.getDynamicPropertiesStore().getMarketSellFee() + accountCapsule.getBalance()); - Assert.assertEquals(0L, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(0L, (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); //check accountOrder MarketAccountOrderCapsule accountOrderCapsule = marketAccountStore.get(ownerAddress); @@ -840,7 +830,8 @@ public void noBuyAddFirstSellOrder3() throws Exception { dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); dbManager.getAccountStore().put(ownerAddress, accountCapsule); long balanceBefore = accountCapsule.getBalance(); - Assert.assertEquals(sellTokenQuant, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(sellTokenQuant, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); MarketSellAssetActuator actuator = new MarketSellAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny(getContract( @@ -862,7 +853,8 @@ public void noBuyAddFirstSellOrder3() throws Exception { accountCapsule = dbManager.getAccountStore().get(ownerAddress); Assert.assertEquals(balanceBefore, dbManager.getDynamicPropertiesStore().getMarketSellFee() + accountCapsule.getBalance()); - Assert.assertEquals(0L, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(0L, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); //check accountOrder MarketAccountOrderCapsule accountOrderCapsule = marketAccountStore.get(ownerAddress); @@ -921,7 +913,8 @@ public void noBuyAddMultiSellOrder1() throws Exception { accountCapsule.addAssetAmountV2(sellTokenId.getBytes(), sellTokenQuant, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); dbManager.getAccountStore().put(ownerAddress, accountCapsule); - Assert.assertEquals(sellTokenQuant, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(sellTokenQuant, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); // Initialize the order book @@ -1006,7 +999,8 @@ public void noBuyAddMultiSellOrderSamePrice1() throws Exception { accountCapsule.addAssetAmountV2(sellTokenId.getBytes(), sellTokenQuant, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); dbManager.getAccountStore().put(ownerAddress, accountCapsule); - Assert.assertEquals(sellTokenQuant, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(sellTokenQuant, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); // Initialize the order book @@ -1092,7 +1086,8 @@ public void hasBuyAddFirstSellOrderNotMatch1() throws Exception { accountCapsule.addAssetAmountV2(sellTokenId.getBytes(), sellTokenQuant, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); dbManager.getAccountStore().put(ownerAddress, accountCapsule); - Assert.assertEquals(sellTokenQuant, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(sellTokenQuant, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); // Initialize the order book //add three order with different price by the same account @@ -1124,7 +1119,8 @@ public void hasBuyAddFirstSellOrderNotMatch1() throws Exception { //check balance and token accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Assert.assertEquals(0L, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(0L, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); //check accountOrder MarketAccountOrderCapsule accountOrderCapsule = marketAccountStore.get(ownerAddress); @@ -1185,7 +1181,8 @@ public void hasBuySellAddSellOrderNotMatch1() throws Exception { accountCapsule.addAssetAmountV2(sellTokenId.getBytes(), sellTokenQuant, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); dbManager.getAccountStore().put(ownerAddress, accountCapsule); - Assert.assertEquals(sellTokenQuant, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(sellTokenQuant, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); // Initialize the order book @@ -1227,7 +1224,8 @@ public void hasBuySellAddSellOrderNotMatch1() throws Exception { //check balance and token accountCapsule = dbManager.getAccountStore().get(ownerAddress); // Assert.assertTrue(accountCapsule.getAssetMapV2().get(sellTokenId) == 0L); - Assert.assertEquals(0L, accountCapsule.getAssetMapV2().get(sellTokenId).longValue()); + Assert.assertEquals(0L, + accountCapsule.getAssetV2MapForTest().get(sellTokenId).longValue()); //check accountOrder MarketAccountOrderCapsule accountOrderCapsule = marketAccountStore.get(ownerAddress); @@ -1296,7 +1294,8 @@ public long doMatchTimeTest(int num) throws Exception { accountCapsule.addAssetAmountV2(sellTokenId.getBytes(), sellTokenQuant, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); dbManager.getAccountStore().put(ownerAddress, accountCapsule); - Assert.assertEquals(sellTokenQuant, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(sellTokenQuant, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); // Initialize the order book @@ -1340,7 +1339,8 @@ public void matchAll2SamePriceBuyOrders1() throws Exception { accountCapsule.addAssetAmountV2(sellTokenId.getBytes(), sellTokenQuant, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); dbManager.getAccountStore().put(ownerAddress, accountCapsule); - Assert.assertEquals(sellTokenQuant, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(sellTokenQuant, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); // Initialize the order book @@ -1381,12 +1381,15 @@ public void matchAll2SamePriceBuyOrders1() throws Exception { //check balance and token accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Assert.assertEquals(0L, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); - Assert.assertEquals(200L, (long) accountCapsule.getAssetMapV2().get(buyTokenId)); + Assert.assertEquals(0L, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); + Assert.assertEquals(200L, + (long) accountCapsule.getAssetV2MapForTest().get(buyTokenId)); byte[] makerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule makerAccountCapsule = dbManager.getAccountStore().get(makerAddress); - Assert.assertEquals(400L, (long) makerAccountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(400L, + (long) makerAccountCapsule.getAssetV2MapForTest().get(sellTokenId)); //check accountOrder MarketAccountOrderCapsule accountOrderCapsule = marketAccountStore.get(ownerAddress); @@ -1488,7 +1491,8 @@ public void partMatchMakerBuyOrders1() throws Exception { accountCapsule.addAssetAmountV2(sellTokenId.getBytes(), sellTokenQuant, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); dbManager.getAccountStore().put(ownerAddress, accountCapsule); - Assert.assertEquals(sellTokenQuant, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(sellTokenQuant, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); //get storeDB instance ChainBaseManager chainBaseManager = dbManager.getChainBaseManager(); @@ -1523,12 +1527,15 @@ public void partMatchMakerBuyOrders1() throws Exception { //check balance and token accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Assert.assertEquals(0L, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); - Assert.assertEquals(200L, (long) accountCapsule.getAssetMapV2().get(buyTokenId)); + Assert.assertEquals(0L, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); + Assert.assertEquals(200L, + (long) accountCapsule.getAssetV2MapForTest().get(buyTokenId)); byte[] makerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule makerAccountCapsule = dbManager.getAccountStore().get(makerAddress); - Assert.assertEquals(500L, (long) makerAccountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(500L, + (long) makerAccountCapsule.getAssetV2MapForTest().get(sellTokenId)); //check accountOrder MarketAccountOrderCapsule accountOrderCapsule = marketAccountStore.get(ownerAddress); @@ -1632,7 +1639,8 @@ public void partMatchTakerBuyOrders1() throws Exception { accountCapsule.addAssetAmountV2(sellTokenId.getBytes(), sellTokenQuant, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); dbManager.getAccountStore().put(ownerAddress, accountCapsule); - Assert.assertEquals(sellTokenQuant, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(sellTokenQuant, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); // Initialize the order book @@ -1667,12 +1675,15 @@ public void partMatchTakerBuyOrders1() throws Exception { //check balance and token accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Assert.assertEquals(0L, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); - Assert.assertEquals(250L, (long) accountCapsule.getAssetMapV2().get(buyTokenId)); + Assert.assertEquals(0L, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); + Assert.assertEquals(250L, + (long) accountCapsule.getAssetV2MapForTest().get(buyTokenId)); byte[] makerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule makerAccountCapsule = dbManager.getAccountStore().get(makerAddress); - Assert.assertEquals(800L, (long) makerAccountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(800L, + (long) makerAccountCapsule.getAssetV2MapForTest().get(sellTokenId)); //check accountOrder MarketAccountOrderCapsule accountOrderCapsule = marketAccountStore.get(ownerAddress); @@ -1750,7 +1761,8 @@ public void partMatchMakerLeftNotEnoughBuyOrders1() throws Exception { accountCapsule.addAssetAmountV2(sellTokenId.getBytes(), sellTokenQuant, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); dbManager.getAccountStore().put(ownerAddress, accountCapsule); - Assert.assertEquals(sellTokenQuant, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(sellTokenQuant, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); // Initialize the order book @@ -1782,12 +1794,15 @@ public void partMatchMakerLeftNotEnoughBuyOrders1() throws Exception { //check balance and token accountCapsule = dbManager.getAccountStore().get(ownerAddress); - Assert.assertEquals(1L, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); - Assert.assertEquals(100L, (long) accountCapsule.getAssetMapV2().get(buyTokenId)); + Assert.assertEquals(1L, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); + Assert.assertEquals(100L, + (long) accountCapsule.getAssetV2MapForTest().get(buyTokenId)); byte[] makerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule makerAccountCapsule = dbManager.getAccountStore().get(makerAddress); - Assert.assertEquals(200L, (long) makerAccountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(200L, + (long) makerAccountCapsule.getAssetV2MapForTest().get(sellTokenId)); //check accountOrder MarketAccountOrderCapsule accountOrderCapsule = marketAccountStore.get(ownerAddress); @@ -1858,7 +1873,8 @@ public void exceedMaxMatchNumLimit() throws Exception { accountCapsule.addAssetAmountV2(sellTokenId.getBytes(), sellTokenQuant, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore()); dbManager.getAccountStore().put(ownerAddress, accountCapsule); - Assert.assertEquals(sellTokenQuant, (long) accountCapsule.getAssetMapV2().get(sellTokenId)); + Assert.assertEquals(sellTokenQuant, + (long) accountCapsule.getAssetV2MapForTest().get(sellTokenId)); // Initialize the order book diff --git a/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java index 23cf410a1fc..168725f9634 100755 --- a/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java @@ -17,7 +17,6 @@ import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.capsule.AccountAssetCapsule; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.TransactionResultCapsule; @@ -53,6 +52,7 @@ public class ParticipateAssetIssueActuatorTest { private static Manager dbManager; private static ChainBaseManager chainBaseManager; private static TronApplicationContext context; + private static long AMOUNT = TOTAL_SUPPLY - (1000L) / TRX_NUM * NUM; static { Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); @@ -94,19 +94,6 @@ public static void destroy() { */ @Before public void createCapsule() { - AccountAssetCapsule ownerAddressFirstAsset = - new AccountAssetCapsule(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); - AccountAssetCapsule ownerAddressSecondAsset = - new AccountAssetCapsule(ByteString.copyFrom(ByteArray.fromHexString(TO_ADDRESS))); - AccountAssetCapsule ownerAddressSecondAsset2 = - new AccountAssetCapsule(ByteString.copyFrom(ByteArray.fromHexString(TO_ADDRESS_2))); - dbManager.getAccountAssetStore().put(ownerAddressFirstAsset.getAddress().toByteArray(), - ownerAddressFirstAsset); - dbManager.getAccountAssetStore().put(ownerAddressSecondAsset.getAddress().toByteArray(), - ownerAddressSecondAsset); - dbManager.getAccountAssetStore().put(ownerAddressSecondAsset2.getAddress().toByteArray(), - ownerAddressSecondAsset2); - AccountCapsule ownerCapsule = new AccountCapsule( ByteString.copyFromUtf8("owner"), @@ -349,16 +336,16 @@ public void sameTokenNameCloseRightAssetIssue() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE - 1000); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE + 1000); //V1 - Assert.assertEquals(owner.getAssetMap().get(ASSET_NAME).longValue(), + Assert.assertEquals(owner.getAssetMapForTest().get(ASSET_NAME).longValue(), (1000L) / TRX_NUM * NUM); - Assert.assertEquals(toAccount.getAssetMap().get(ASSET_NAME).longValue(), - TOTAL_SUPPLY - (1000L) / TRX_NUM * NUM); + + Assert.assertEquals(toAccount.getAssetMapForTest().get(ASSET_NAME).longValue(), AMOUNT); //V2 long tokenId = chainBaseManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(tokenId)).longValue(), + Assert.assertEquals(owner.getAssetV2MapForTest().get(String.valueOf(tokenId)).longValue(), (1000L) / TRX_NUM * NUM); - Assert.assertEquals(toAccount.getAssetMapV2().get(String.valueOf(tokenId)).longValue(), - TOTAL_SUPPLY - (1000L) / TRX_NUM * NUM); + Assert.assertEquals(toAccount.getAssetV2MapForTest() + .get(String.valueOf(tokenId)).longValue(), AMOUNT); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); @@ -393,14 +380,14 @@ public void OldNotUpdateSuccessAssetIssue() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE - 1000); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE + 1000); //V1 data not update - Assert.assertNull(owner.getAssetMap().get(ASSET_NAME)); - Assert.assertEquals(toAccount.getAssetMap().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); + Assert.assertNull(owner.getAssetMapForTest().get(ASSET_NAME)); + Assert.assertEquals(toAccount.getAssetMapForTest().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); //V2 long tokenId = chainBaseManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(tokenId)).longValue(), + Assert.assertEquals(owner.getAssetV2MapForTest().get(String.valueOf(tokenId)).longValue(), (1000L) / TRX_NUM * NUM); - Assert.assertEquals(toAccount.getAssetMapV2().get(String.valueOf(tokenId)).longValue(), - TOTAL_SUPPLY - (1000L) / TRX_NUM * NUM); + Assert.assertEquals(toAccount.getAssetV2MapForTest() + .get(String.valueOf(tokenId)).longValue(), AMOUNT); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); @@ -433,14 +420,14 @@ public void sameTokenNameOpenRightAssetIssue() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE - 1000); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE + 1000); // V1, data is not exist - Assert.assertNull(owner.getAssetMap().get(ASSET_NAME)); - Assert.assertNull(toAccount.getAssetMap().get(ASSET_NAME)); + Assert.assertNull(owner.getAssetMapForTest().get(ASSET_NAME)); + Assert.assertNull(toAccount.getAssetMapForTest().get(ASSET_NAME)); //V2 long id = chainBaseManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(id)).longValue(), - (1000L) / TRX_NUM * NUM); + Assert.assertEquals(owner.getAssetV2MapForTest() + .get(String.valueOf(id)).longValue(), (1000L) / TRX_NUM * NUM); Assert.assertEquals( - toAccount.getAssetMapV2().get(String.valueOf(id)).longValue(), + toAccount.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), TOTAL_SUPPLY - (1000L) / TRX_NUM * NUM); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); @@ -474,8 +461,8 @@ public void sameTokenNameCloseAssetIssueTimeRight() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); - Assert.assertTrue(isNullOrZero(owner.getAssetMap().get(ASSET_NAME))); - Assert.assertEquals(toAccount.getAssetMap().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); + Assert.assertTrue(isNullOrZero(owner.getAssetMapForTest().get(ASSET_NAME))); + Assert.assertEquals(toAccount.getAssetMapForTest().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -508,8 +495,8 @@ public void sameTokenNameOpenAssetIssueTimeRight() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); long id = chainBaseManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertTrue(isNullOrZero(owner.getAssetMapV2().get(String.valueOf(id)))); - Assert.assertEquals(toAccount.getAssetMapV2().get(String.valueOf(id)).longValue(), + Assert.assertTrue(isNullOrZero(owner.getAssetV2MapForTest().get(String.valueOf(id)))); + Assert.assertEquals(toAccount.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); @@ -541,8 +528,9 @@ public void sameTokenNameCloseAssetIssueTimeLeft() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); - Assert.assertTrue(isNullOrZero(owner.getAssetMap().get(ASSET_NAME))); - Assert.assertEquals(toAccount.getAssetMap().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); + Assert.assertTrue(isNullOrZero(owner.getAssetMapForTest().get(ASSET_NAME))); + Assert.assertEquals(toAccount.getAssetMapForTest() + .get(ASSET_NAME).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -575,9 +563,9 @@ public void sameTokenNameOpenAssetIssueTimeLeft() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); long id = chainBaseManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertTrue(isNullOrZero(owner.getAssetMapV2().get(String.valueOf(id)))); - Assert.assertEquals(toAccount.getAssetMapV2().get(String.valueOf(id)).longValue(), - TOTAL_SUPPLY); + Assert.assertTrue(isNullOrZero(owner.getAssetV2MapForTest().get(String.valueOf(id)))); + Assert.assertEquals(toAccount.getAssetV2MapForTest() + .get(String.valueOf(id)).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -604,10 +592,10 @@ public void sameTokenNameCloseExchangeDevisibleTest() { AccountCapsule toAccount = chainBaseManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); - Assert.assertEquals(owner.getAssetMap().get(ASSET_NAME).longValue(), + Assert.assertEquals(owner.getAssetMapForTest().get(ASSET_NAME).longValue(), (999L * NUM) / TRX_NUM); Assert.assertEquals( - toAccount.getAssetMap().get(ASSET_NAME).longValue(), + toAccount.getAssetMapForTest().get(ASSET_NAME).longValue(), TOTAL_SUPPLY - (999L * NUM) / TRX_NUM); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); @@ -638,10 +626,10 @@ public void sameTokenNameOpenExchangeDevisibleTest() { AccountCapsule toAccount = chainBaseManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); long id = chainBaseManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(id)).longValue(), + Assert.assertEquals(owner.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), (999L * NUM) / TRX_NUM); Assert.assertEquals( - toAccount.getAssetMapV2().get(String.valueOf(id)).longValue(), + toAccount.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), TOTAL_SUPPLY - (999L * NUM) / TRX_NUM); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); @@ -676,8 +664,8 @@ public void sameTokenNameCloseNegativeAmountTest() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); - Assert.assertTrue(isNullOrZero(owner.getAssetMap().get(ASSET_NAME))); - Assert.assertEquals(toAccount.getAssetMap().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); + Assert.assertTrue(isNullOrZero(owner.getAssetMapForTest().get(ASSET_NAME))); + Assert.assertEquals(toAccount.getAssetMapForTest().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -712,9 +700,9 @@ public void sameTokenNameOpenNegativeAmountTest() { Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); long id = chainBaseManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertTrue(isNullOrZero(owner.getAssetMapV2().get(String.valueOf(id)))); - Assert.assertEquals(toAccount.getAssetMapV2().get(String.valueOf(id)).longValue(), - TOTAL_SUPPLY); + Assert.assertTrue(isNullOrZero(owner.getAssetV2MapForTest().get(String.valueOf(id)))); + Assert.assertEquals(toAccount.getAssetV2MapForTest() + .get(String.valueOf(id)).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -746,8 +734,8 @@ public void sameTokenNameCloseZeroAmountTest() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); - Assert.assertTrue(isNullOrZero(owner.getAssetMap().get(ASSET_NAME))); - Assert.assertEquals(toAccount.getAssetMap().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); + Assert.assertTrue(isNullOrZero(owner.getAssetMapForTest().get(ASSET_NAME))); + Assert.assertEquals(toAccount.getAssetMapForTest().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -782,9 +770,9 @@ public void sameTokenNameOpenZeroAmountTest() { Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); long id = chainBaseManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertTrue(isNullOrZero(owner.getAssetMapV2().get(String.valueOf(id)))); - Assert.assertEquals(toAccount.getAssetMapV2().get(String.valueOf(id)).longValue(), - TOTAL_SUPPLY); + Assert.assertTrue(isNullOrZero(owner.getAssetV2MapForTest().get(String.valueOf(id)))); + Assert.assertEquals(toAccount.getAssetV2MapForTest() + .get(String.valueOf(id)).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -818,8 +806,8 @@ public void sameTokenNameCloseNoExitOwnerTest() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); - Assert.assertTrue(isNullOrZero(owner.getAssetMap().get(ASSET_NAME))); - Assert.assertEquals(toAccount.getAssetMap().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); + Assert.assertTrue(isNullOrZero(owner.getAssetMapForTest().get(ASSET_NAME))); + Assert.assertEquals(toAccount.getAssetMapForTest().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -855,8 +843,8 @@ public void sameTokenNameOpenNoExitOwnerTest() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); long id = chainBaseManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertTrue(isNullOrZero(owner.getAssetMapV2().get(String.valueOf(id)))); - Assert.assertEquals(toAccount.getAssetMapV2().get(String.valueOf(id)).longValue(), + Assert.assertTrue(isNullOrZero(owner.getAssetV2MapForTest().get(String.valueOf(id)))); + Assert.assertEquals(toAccount.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); @@ -894,8 +882,8 @@ public void sameTokenNameCloseNoExitToTest() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); - Assert.assertTrue(isNullOrZero(owner.getAssetMap().get(ASSET_NAME))); - Assert.assertEquals(toAccount.getAssetMap().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); + Assert.assertTrue(isNullOrZero(owner.getAssetMapForTest().get(ASSET_NAME))); + Assert.assertEquals(toAccount.getAssetMapForTest().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -935,8 +923,8 @@ public void sameTokenNameOpenNoExitToTest() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); long id = chainBaseManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertTrue(isNullOrZero(owner.getAssetMapV2().get(String.valueOf(id)))); - Assert.assertEquals(toAccount.getAssetMapV2().get(String.valueOf(id)).longValue(), + Assert.assertTrue(isNullOrZero(owner.getAssetV2MapForTest().get(String.valueOf(id)))); + Assert.assertEquals(toAccount.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); @@ -974,8 +962,8 @@ public void sameTokenNameCloseParticipateAssetSelf() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); - Assert.assertTrue(isNullOrZero(owner.getAssetMap().get(ASSET_NAME))); - Assert.assertEquals(toAccount.getAssetMap().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); + Assert.assertTrue(isNullOrZero(owner.getAssetMapForTest().get(ASSET_NAME))); + Assert.assertEquals(toAccount.getAssetMapForTest().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -1014,8 +1002,8 @@ public void sameTokenNameOpenParticipateAssetSelf() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); long id = chainBaseManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertTrue(isNullOrZero(owner.getAssetMapV2().get(String.valueOf(id)))); - Assert.assertEquals(toAccount.getAssetMapV2().get(String.valueOf(id)).longValue(), + Assert.assertTrue(isNullOrZero(owner.getAssetV2MapForTest().get(String.valueOf(id)))); + Assert.assertEquals(toAccount.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); @@ -1050,8 +1038,8 @@ public void sameTokenNameCloseParticipateAssetToThird() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); - Assert.assertTrue(isNullOrZero(owner.getAssetMap().get(ASSET_NAME))); - Assert.assertEquals(toAccount.getAssetMap().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); + Assert.assertTrue(isNullOrZero(owner.getAssetMapForTest().get(ASSET_NAME))); + Assert.assertEquals(toAccount.getAssetMapForTest().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -1087,8 +1075,8 @@ public void sameTokenNameOpenParticipateAssetToThird() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); long id = chainBaseManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertTrue(isNullOrZero(owner.getAssetMapV2().get(String.valueOf(id)))); - Assert.assertEquals(toAccount.getAssetMapV2().get(String.valueOf(id)).longValue(), + Assert.assertTrue(isNullOrZero(owner.getAssetV2MapForTest().get(String.valueOf(id)))); + Assert.assertEquals(toAccount.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); @@ -1144,9 +1132,9 @@ public void assetNameTest() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE - 1000); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE + 1000); - Assert.assertEquals(owner.getAssetMap().get(assetName).longValue(), + Assert.assertEquals(owner.getAssetMapForTest().get(assetName).longValue(), (1000L) / TRX_NUM * NUM); - Assert.assertEquals(toAccount.getAssetMap().get(assetName).longValue(), + Assert.assertEquals(toAccount.getAssetMapForTest().get(assetName).longValue(), TOTAL_SUPPLY - (1000L) / TRX_NUM * NUM); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); @@ -1176,9 +1164,9 @@ public void assetNameTest() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE - 2000); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE + 2000); - Assert.assertEquals(owner.getAssetMap().get(assetName).longValue(), + Assert.assertEquals(owner.getAssetMapForTest().get(assetName).longValue(), (1000L) / TRX_NUM * NUM); - Assert.assertEquals(toAccount.getAssetMap().get(assetName).longValue(), + Assert.assertEquals(toAccount.getAssetMapForTest().get(assetName).longValue(), TOTAL_SUPPLY - (1000L) / TRX_NUM * NUM); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); @@ -1219,8 +1207,8 @@ public void sameTokenNameCloseNotEnoughTrxTest() { Assert.assertEquals(owner.getBalance(), 100); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); - Assert.assertTrue(isNullOrZero(owner.getAssetMap().get(ASSET_NAME))); - Assert.assertEquals(toAccount.getAssetMap().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); + Assert.assertTrue(isNullOrZero(owner.getAssetMapForTest().get(ASSET_NAME))); + Assert.assertEquals(toAccount.getAssetMapForTest().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -1260,8 +1248,8 @@ public void sameTokenNameOpenNotEnoughTrxTest() { Assert.assertEquals(owner.getBalance(), 100); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); long id = chainBaseManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertTrue(isNullOrZero(owner.getAssetMapV2().get(String.valueOf(id)))); - Assert.assertEquals(toAccount.getAssetMapV2().get(String.valueOf(id)).longValue(), + Assert.assertTrue(isNullOrZero(owner.getAssetV2MapForTest().get(String.valueOf(id)))); + Assert.assertEquals(toAccount.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); @@ -1301,8 +1289,8 @@ public void sameTokenNameCloseNotEnoughAssetTest() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); - Assert.assertTrue(isNullOrZero(owner.getAssetMap().get(ASSET_NAME))); - Assert.assertEquals(toAccount.getAssetMap().get(ASSET_NAME).longValue(), 10000); + Assert.assertTrue(isNullOrZero(owner.getAssetMapForTest().get(ASSET_NAME))); + Assert.assertEquals(toAccount.getAssetMapForTest().get(ASSET_NAME).longValue(), 10000); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -1347,9 +1335,9 @@ public void sameTokenNameOpenNotEnoughAssetTest() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); - Assert.assertTrue(isNullOrZero(owner.getAssetMapV2().get(String.valueOf(id)))); + Assert.assertTrue(isNullOrZero(owner.getAssetV2MapForTest().get(String.valueOf(id)))); Assert.assertEquals( - toAccount.getAssetMapV2().get(String.valueOf(id)).longValue(), 10000); + toAccount.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), 10000); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -1382,8 +1370,8 @@ public void sameTokenNameCloseNoneExistAssetTest() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); - Assert.assertTrue(isNullOrZero(owner.getAssetMap().get(ASSET_NAME))); - Assert.assertEquals(toAccount.getAssetMap().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); + Assert.assertTrue(isNullOrZero(owner.getAssetMapForTest().get(ASSET_NAME))); + Assert.assertEquals(toAccount.getAssetMapForTest().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -1419,8 +1407,8 @@ public void sameTokenNameOpenNoneExistAssetTest() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); long id = chainBaseManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertTrue(isNullOrZero(owner.getAssetMapV2().get(String.valueOf(id)))); - Assert.assertEquals(toAccount.getAssetMapV2().get(String.valueOf(id)).longValue(), + Assert.assertTrue(isNullOrZero(owner.getAssetV2MapForTest().get(String.valueOf(id)))); + Assert.assertEquals(toAccount.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); @@ -1463,8 +1451,8 @@ public void sameTokenNameCloseAddOverflowTest() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); - Assert.assertEquals(owner.getAssetMap().get(ASSET_NAME).longValue(), Long.MAX_VALUE); - Assert.assertEquals(toAccount.getAssetMap().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); + Assert.assertEquals(owner.getAssetMapForTest().get(ASSET_NAME).longValue(), Long.MAX_VALUE); + Assert.assertEquals(toAccount.getAssetMapForTest().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); } } @@ -1507,9 +1495,9 @@ public void sameTokenNameOpenAddOverflowTest() { Assert.assertEquals(owner.getBalance(), OWNER_BALANCE); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(id)).longValue(), + Assert.assertEquals(owner.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), Long.MAX_VALUE); - Assert.assertEquals(toAccount.getAssetMapV2().get(String.valueOf(id)).longValue(), + Assert.assertEquals(toAccount.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), TOTAL_SUPPLY); } } @@ -1554,8 +1542,8 @@ public void sameTokenNameCloseMultiplyOverflowTest() { Assert.assertEquals(owner.getBalance(), 100000000000000L); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); - Assert.assertTrue(isNullOrZero(owner.getAssetMap().get(ASSET_NAME))); - Assert.assertEquals(toAccount.getAssetMap().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); + Assert.assertTrue(isNullOrZero(owner.getAssetMapForTest().get(ASSET_NAME))); + Assert.assertEquals(toAccount.getAssetMapForTest().get(ASSET_NAME).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -1604,8 +1592,8 @@ public void sameTokenNameOpenMultiplyOverflowTest() { Assert.assertEquals(owner.getBalance(), 100000000000000L); Assert.assertEquals(toAccount.getBalance(), TO_BALANCE); long id = chainBaseManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertTrue(isNullOrZero(owner.getAssetMapV2().get(String.valueOf(id)))); - Assert.assertEquals(toAccount.getAssetMapV2().get(String.valueOf(id)).longValue(), + Assert.assertTrue(isNullOrZero(owner.getAssetV2MapForTest().get(String.valueOf(id)))); + Assert.assertEquals(toAccount.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), TOTAL_SUPPLY); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); diff --git a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java index 9ba4809bede..3042a745d94 100755 --- a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java @@ -192,8 +192,8 @@ private IncrementalMerkleVoucherContainer createSimpleMerkleVoucherContainer(byt private long getAssertBalance(AccountCapsule accountCapsule) { String token = String.valueOf(tokenId); - if (accountCapsule != null && accountCapsule.getAssetMapV2().containsKey(token)) { - return accountCapsule.getAssetMapV2().get(token); + if (accountCapsule != null && accountCapsule.getAssetV2MapForTest().containsKey(token)) { + return accountCapsule.getAssetV2MapForTest().get(token); } else { return 0; } diff --git a/framework/src/test/java/org/tron/core/actuator/TransferAssetActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/TransferAssetActuatorTest.java index d047ff4ce1c..070adac4829 100755 --- a/framework/src/test/java/org/tron/core/actuator/TransferAssetActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/TransferAssetActuatorTest.java @@ -20,7 +20,9 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; + import java.io.File; + import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.junit.AfterClass; @@ -35,7 +37,6 @@ import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.capsule.AccountAssetCapsule; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.TransactionResultCapsule; @@ -88,9 +89,9 @@ public class TransferAssetActuatorTest { TO_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a146a"; NOT_EXIT_ADDRESS = Wallet.getAddressPreFixString() + "B56446E617E924805E4D6CA021D341FEF6E2013B"; NOT_EXIT_ADDRESS_2 = Wallet.getAddressPreFixString() - + "B56446E617E924805E4D6CA021D341FEF6E21234"; + + "B56446E617E924805E4D6CA021D341FEF6E21234"; ownerAsset_ADDRESS = - Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049010"; + Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049010"; } /** @@ -121,14 +122,12 @@ public static void destroy() { @Before public void createCapsule() { AccountCapsule toAccountCapsule = - new AccountCapsule( - ByteString.copyFrom(ByteArray.fromHexString(TO_ADDRESS)), - ByteString.copyFromUtf8("toAccount"), - AccountType.Normal); + new AccountCapsule( + ByteString.copyFrom(ByteArray.fromHexString(TO_ADDRESS)), + ByteString.copyFromUtf8("toAccount"), + AccountType.Normal); dbManager.getAccountStore().put(toAccountCapsule.getAddress().toByteArray(), toAccountCapsule); - dbManager.getAccountAssetStore().put(toAccountCapsule.getAddress().toByteArray(), - new AccountAssetCapsule(toAccountCapsule.getAddress())); } private boolean isNullOrZero(Long value) { @@ -140,29 +139,29 @@ private boolean isNullOrZero(Long value) { public void createAsset(String assetName) { AccountCapsule ownerCapsule = dbManager.getAccountStore() - .get(ByteArray.fromHexString(OWNER_ADDRESS)); + .get(ByteArray.fromHexString(OWNER_ADDRESS)); ownerCapsule.addAsset(assetName.getBytes(), OWNER_ASSET_BALANCE); long id = dbManager.getDynamicPropertiesStore().getTokenIdNum() + 1; dbManager.getDynamicPropertiesStore().saveTokenIdNum(id); AssetIssueContract assetIssueContract = - AssetIssueContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) - .setName(ByteString.copyFrom(ByteArray.fromString(assetName))) - .setId(Long.toString(id)) - .setTotalSupply(TOTAL_SUPPLY) - .setTrxNum(TRX_NUM) - .setNum(NUM) - .setStartTime(START_TIME) - .setEndTime(END_TIME) - .setVoteScore(VOTE_SCORE) - .setDescription(ByteString.copyFrom(ByteArray.fromString(DESCRIPTION))) - .setUrl(ByteString.copyFrom(ByteArray.fromString(URL))) - .build(); + AssetIssueContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setName(ByteString.copyFrom(ByteArray.fromString(assetName))) + .setId(Long.toString(id)) + .setTotalSupply(TOTAL_SUPPLY) + .setTrxNum(TRX_NUM) + .setNum(NUM) + .setStartTime(START_TIME) + .setEndTime(END_TIME) + .setVoteScore(VOTE_SCORE) + .setDescription(ByteString.copyFrom(ByteArray.fromString(DESCRIPTION))) + .setUrl(ByteString.copyFrom(ByteArray.fromString(URL))) + .build(); AssetIssueCapsule assetIssueCapsule = new AssetIssueCapsule(assetIssueContract); dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); dbManager.getAssetIssueStore() - .put(assetIssueCapsule.createDbKey(), assetIssueCapsule); + .put(assetIssueCapsule.createDbKey(), assetIssueCapsule); } private Any getContract(long sendCoin) { @@ -173,32 +172,32 @@ private Any getContract(long sendCoin) { } return Any.pack( - TransferAssetContract.newBuilder() - .setAssetName(ByteString.copyFrom(ByteArray.fromString(assertName))) - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) - .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(TO_ADDRESS))) - .setAmount(sendCoin) - .build()); + TransferAssetContract.newBuilder() + .setAssetName(ByteString.copyFrom(ByteArray.fromString(assertName))) + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(TO_ADDRESS))) + .setAmount(sendCoin) + .build()); } private Any getContract(long sendCoin, ByteString assetName) { return Any.pack( - TransferAssetContract.newBuilder() - .setAssetName(assetName) - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) - .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(TO_ADDRESS))) - .setAmount(sendCoin) - .build()); + TransferAssetContract.newBuilder() + .setAssetName(assetName) + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(TO_ADDRESS))) + .setAmount(sendCoin) + .build()); } private Any getContract(long sendCoin, String assetName) { return Any.pack( - TransferAssetContract.newBuilder() - .setAssetName(ByteString.copyFrom(ByteArray.fromString(assetName))) - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) - .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(TO_ADDRESS))) - .setAmount(sendCoin) - .build()); + TransferAssetContract.newBuilder() + .setAssetName(ByteString.copyFrom(ByteArray.fromString(assetName))) + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(TO_ADDRESS))) + .setAmount(sendCoin) + .build()); } private Any getContract(long sendCoin, String owner, String to) { @@ -208,12 +207,12 @@ private Any getContract(long sendCoin, String owner, String to) { assertName = String.valueOf(tokenIdNum); } return Any.pack( - TransferAssetContract.newBuilder() - .setAssetName(ByteString.copyFrom(ByteArray.fromString(assertName))) - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(owner))) - .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(to))) - .setAmount(sendCoin) - .build()); + TransferAssetContract.newBuilder() + .setAssetName(ByteString.copyFrom(ByteArray.fromString(assertName))) + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(owner))) + .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(to))) + .setAmount(sendCoin) + .build()); } private Any getContract(long sendCoin, byte[] toAddress) { @@ -224,12 +223,12 @@ private Any getContract(long sendCoin, byte[] toAddress) { } return Any.pack( - TransferAssetContract.newBuilder() - .setAssetName(ByteString.copyFrom(ByteArray.fromString(assertName))) - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) - .setToAddress(ByteString.copyFrom(toAddress)) - .setAmount(sendCoin) - .build()); + TransferAssetContract.newBuilder() + .setAssetName(ByteString.copyFrom(ByteArray.fromString(assertName))) + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setToAddress(ByteString.copyFrom(toAddress)) + .setAmount(sendCoin) + .build()); } private void createAssertBeforSameTokenNameActive() { @@ -237,33 +236,28 @@ private void createAssertBeforSameTokenNameActive() { long id = dbManager.getDynamicPropertiesStore().getTokenIdNum() + 1; dbManager.getDynamicPropertiesStore().saveTokenIdNum(id); AssetIssueContract assetIssueContract = - AssetIssueContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) - .setName(ByteString.copyFrom(ByteArray.fromString(ASSET_NAME))) - .setId(Long.toString(id)) - .setTotalSupply(TOTAL_SUPPLY) - .setTrxNum(TRX_NUM) - .setNum(NUM) - .setStartTime(START_TIME) - .setEndTime(END_TIME) - .setVoteScore(VOTE_SCORE) - .setDescription(ByteString.copyFrom(ByteArray.fromString(DESCRIPTION))) - .setUrl(ByteString.copyFrom(ByteArray.fromString(URL))) - .build(); + AssetIssueContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setName(ByteString.copyFrom(ByteArray.fromString(ASSET_NAME))) + .setId(Long.toString(id)) + .setTotalSupply(TOTAL_SUPPLY) + .setTrxNum(TRX_NUM) + .setNum(NUM) + .setStartTime(START_TIME) + .setEndTime(END_TIME) + .setVoteScore(VOTE_SCORE) + .setDescription(ByteString.copyFrom(ByteArray.fromString(DESCRIPTION))) + .setUrl(ByteString.copyFrom(ByteArray.fromString(URL))) + .build(); AssetIssueCapsule assetIssueCapsule = new AssetIssueCapsule(assetIssueContract); dbManager.getAssetIssueStore().put(assetIssueCapsule.createDbKey(), assetIssueCapsule); dbManager.getAssetIssueV2Store().put(assetIssueCapsule.createDbV2Key(), assetIssueCapsule); - AccountAssetCapsule ownerAssetCapsule = new AccountAssetCapsule( - ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); - dbManager.getAccountAssetStore().put(ownerAssetCapsule.getAddress().toByteArray(), - ownerAssetCapsule); - AccountCapsule ownerCapsule = - new AccountCapsule( - ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), - ByteString.copyFromUtf8("owner"), - AccountType.AssetIssue); + new AccountCapsule( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + ByteString.copyFromUtf8("owner"), + AccountType.AssetIssue); ownerCapsule.addAsset(ASSET_NAME.getBytes(), OWNER_ASSET_BALANCE); ownerCapsule.addAssetV2(ByteArray.fromString(String.valueOf(id)), OWNER_ASSET_BALANCE); @@ -275,32 +269,27 @@ private void createAssertSameTokenNameActive() { long id = dbManager.getDynamicPropertiesStore().getTokenIdNum() + 1; dbManager.getDynamicPropertiesStore().saveTokenIdNum(id); AssetIssueContract assetIssueContract = - AssetIssueContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) - .setName(ByteString.copyFrom(ByteArray.fromString(ASSET_NAME))) - .setId(Long.toString(id)) - .setTotalSupply(TOTAL_SUPPLY) - .setTrxNum(TRX_NUM) - .setNum(NUM) - .setStartTime(START_TIME) - .setEndTime(END_TIME) - .setVoteScore(VOTE_SCORE) - .setDescription(ByteString.copyFrom(ByteArray.fromString(DESCRIPTION))) - .setUrl(ByteString.copyFrom(ByteArray.fromString(URL))) - .build(); + AssetIssueContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setName(ByteString.copyFrom(ByteArray.fromString(ASSET_NAME))) + .setId(Long.toString(id)) + .setTotalSupply(TOTAL_SUPPLY) + .setTrxNum(TRX_NUM) + .setNum(NUM) + .setStartTime(START_TIME) + .setEndTime(END_TIME) + .setVoteScore(VOTE_SCORE) + .setDescription(ByteString.copyFrom(ByteArray.fromString(DESCRIPTION))) + .setUrl(ByteString.copyFrom(ByteArray.fromString(URL))) + .build(); AssetIssueCapsule assetIssueCapsule = new AssetIssueCapsule(assetIssueContract); dbManager.getAssetIssueV2Store().put(assetIssueCapsule.createDbV2Key(), assetIssueCapsule); - AccountAssetCapsule ownerAccountAssetCapsule = new AccountAssetCapsule( - ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); - - dbManager.getAccountAssetStore().put(ownerAccountAssetCapsule.getAddress().toByteArray(), - ownerAccountAssetCapsule); AccountCapsule ownerCapsule = - new AccountCapsule( - ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), - ByteString.copyFromUtf8("owner"), - AccountType.AssetIssue); + new AccountCapsule( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + ByteString.copyFromUtf8("owner"), + AccountType.AssetIssue); ownerCapsule.addAssetV2(ByteArray.fromString(String.valueOf(id)), OWNER_ASSET_BALANCE); dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); @@ -321,21 +310,21 @@ public void SameTokenNameCloseSuccessTransfer() { actuator.execute(ret); Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); // check V1 - Assert.assertEquals(owner.getAssetMap().get(ASSET_NAME).longValue(), - OWNER_ASSET_BALANCE - 100); - Assert.assertEquals(toAccount.getAssetMap().get(ASSET_NAME).longValue(), 100L); + Assert.assertEquals(owner.getAssetMapForTest().get(ASSET_NAME).longValue(), + OWNER_ASSET_BALANCE - 100); + Assert.assertEquals(toAccount.getAssetMapForTest().get(ASSET_NAME).longValue(), 100L); // check V2 long tokenIdNum = dbManager.getDynamicPropertiesStore().getTokenIdNum(); Assert.assertEquals( - owner.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), - OWNER_ASSET_BALANCE - 100); + owner.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), + OWNER_ASSET_BALANCE - 100); Assert.assertEquals( - toAccount.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), - 100L); + toAccount.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), + 100L); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); @@ -359,20 +348,20 @@ public void SameTokenNameOpenSuccessTransfer() { actuator.execute(ret); Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); // V1, data is not exist - Assert.assertNull(owner.getAssetMap().get(ASSET_NAME)); - Assert.assertNull(toAccount.getAssetMap().get(ASSET_NAME)); + Assert.assertNull(owner.getAssetMapForTest().get(ASSET_NAME)); + Assert.assertNull(toAccount.getAssetMapForTest().get(ASSET_NAME)); // check V2 long tokenIdNum = dbManager.getDynamicPropertiesStore().getTokenIdNum(); Assert.assertEquals( - owner.getInstance().getAssetV2Map().get(String.valueOf(tokenIdNum)).longValue(), - OWNER_ASSET_BALANCE - 100); + owner.getInstance().getAssetV2Map().get(String.valueOf(tokenIdNum)).longValue(), + OWNER_ASSET_BALANCE - 100); Assert.assertEquals( - toAccount.getInstance().getAssetV2Map().get(String.valueOf(tokenIdNum)).longValue(), - 100L); + toAccount.getInstance().getAssetV2Map().get(String.valueOf(tokenIdNum)).longValue(), + 100L); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); @@ -389,7 +378,7 @@ public void SameTokenNameCloseSuccessTransfer2() { createAssertBeforSameTokenNameActive(); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(OWNER_ASSET_BALANCE)); + .setAny(getContract(OWNER_ASSET_BALANCE)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -397,20 +386,20 @@ public void SameTokenNameCloseSuccessTransfer2() { actuator.execute(ret); Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); //check V1 - Assert.assertEquals(owner.getAssetMap().get(ASSET_NAME).longValue(), 0L); + Assert.assertEquals(owner.getAssetMapForTest().get(ASSET_NAME).longValue(), 0L); Assert.assertEquals( - toAccount.getAssetMap().get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); + toAccount.getAssetMapForTest().get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); //check V2 long tokenIdNum = dbManager.getDynamicPropertiesStore().getTokenIdNum(); Assert.assertEquals( - owner.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), 0L); + owner.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), 0L); Assert.assertEquals( - toAccount.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), - OWNER_ASSET_BALANCE); + toAccount.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), + OWNER_ASSET_BALANCE); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -428,7 +417,7 @@ public void OldNotUpdateSuccessTransfer2() { dbManager.getDynamicPropertiesStore().saveAllowSameTokenName(1); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(OWNER_ASSET_BALANCE)); + .setAny(getContract(OWNER_ASSET_BALANCE)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -436,20 +425,20 @@ public void OldNotUpdateSuccessTransfer2() { actuator.execute(ret); Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); //check V1 - Assert.assertEquals(owner.getAssetMap().get(ASSET_NAME).longValue(), - OWNER_ASSET_BALANCE); - Assert.assertNull(toAccount.getAssetMap().get(ASSET_NAME)); + Assert.assertEquals(owner.getAssetMapForTest().get(ASSET_NAME).longValue(), + OWNER_ASSET_BALANCE); + Assert.assertNull(toAccount.getAssetMapForTest().get(ASSET_NAME)); //check V2 long tokenIdNum = dbManager.getDynamicPropertiesStore().getTokenIdNum(); Assert.assertEquals( - owner.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), 0L); + owner.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), 0L); Assert.assertEquals( - toAccount.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), - OWNER_ASSET_BALANCE); + toAccount.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), + OWNER_ASSET_BALANCE); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -465,7 +454,7 @@ public void SameTokenNameOpenSuccessTransfer2() { createAssertSameTokenNameActive(); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(OWNER_ASSET_BALANCE)); + .setAny(getContract(OWNER_ASSET_BALANCE)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -473,19 +462,19 @@ public void SameTokenNameOpenSuccessTransfer2() { actuator.execute(ret); Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); // V1, data is not exist - Assert.assertNull(owner.getAssetMap().get(ASSET_NAME)); - Assert.assertNull(toAccount.getAssetMap().get(ASSET_NAME)); + Assert.assertNull(owner.getAssetMapForTest().get(ASSET_NAME)); + Assert.assertNull(toAccount.getAssetMapForTest().get(ASSET_NAME)); //check V2 long tokenIdNum = dbManager.getDynamicPropertiesStore().getTokenIdNum(); Assert.assertEquals( - owner.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), 0L); + owner.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), 0L); Assert.assertEquals( - toAccount.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), - OWNER_ASSET_BALANCE); + toAccount.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), + OWNER_ASSET_BALANCE); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -500,12 +489,11 @@ public void SameTokenNameOpenSuccessTransfer2() { public void SameTokenNameCloseOwnerNoAssetTest() { createAssertBeforSameTokenNameActive(); AccountCapsule owner = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); - owner.importAsset(); owner.setInstance(owner.getInstance().toBuilder().clearAsset().build()); dbManager.getAccountStore().put(owner.createDbKey(), owner); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(OWNER_ASSET_BALANCE)); + .setAny(getContract(OWNER_ASSET_BALANCE)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -514,11 +502,10 @@ public void SameTokenNameCloseOwnerNoAssetTest() { Assert.assertTrue(false); } catch (ContractValidateException e) { Assert.assertTrue(e instanceof ContractValidateException); - Assert.assertEquals("Owner has no asset!", e.getMessage()); Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); - Assert.assertTrue(isNullOrZero(toAccount.getAssetMap().get(ASSET_NAME))); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + Assert.assertTrue(isNullOrZero(toAccount.getAssetMapForTest().get(ASSET_NAME))); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -535,7 +522,7 @@ public void SameTokenNameOpenOwnerNoAssetTest() { dbManager.getAccountStore().put(owner.createDbKey(), owner); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(OWNER_ASSET_BALANCE)); + .setAny(getContract(OWNER_ASSET_BALANCE)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -544,12 +531,12 @@ public void SameTokenNameOpenOwnerNoAssetTest() { Assert.assertTrue(false); } catch (ContractValidateException e) { Assert.assertTrue(e instanceof ContractValidateException); - Assert.assertEquals("Owner has no asset!", e.getMessage()); Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); long tokenIdNum = dbManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertTrue(isNullOrZero(toAccount.getAssetMapV2().get(String.valueOf(tokenIdNum)))); + Assert.assertTrue(isNullOrZero( + toAccount.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)))); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -563,7 +550,7 @@ public void SameTokenNameCloseNotEnoughAssetTest() { createAssertBeforSameTokenNameActive(); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(OWNER_ASSET_BALANCE + 1)); + .setAny(getContract(OWNER_ASSET_BALANCE + 1)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -575,11 +562,12 @@ public void SameTokenNameCloseNotEnoughAssetTest() { Assert.assertTrue("assetBalance is not sufficient.".equals(e.getMessage())); Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); - Assert.assertEquals(owner.getAssetMap().get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); - Assert.assertTrue(isNullOrZero(toAccount.getAssetMap().get(ASSET_NAME))); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + Assert.assertEquals(owner.getAssetMapForTest().get(ASSET_NAME).longValue(), + OWNER_ASSET_BALANCE); + Assert.assertTrue(isNullOrZero(toAccount.getAssetMapForTest().get(ASSET_NAME))); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -593,7 +581,7 @@ public void SameTokenNameOpenNotEnoughAssetTest() { createAssertSameTokenNameActive(); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(OWNER_ASSET_BALANCE + 1)); + .setAny(getContract(OWNER_ASSET_BALANCE + 1)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -605,13 +593,14 @@ public void SameTokenNameOpenNotEnoughAssetTest() { Assert.assertTrue("assetBalance is not sufficient.".equals(e.getMessage())); Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); long tokenIdNum = dbManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), - OWNER_ASSET_BALANCE); - Assert.assertTrue(isNullOrZero(toAccount.getAssetMapV2().get(String.valueOf(tokenIdNum)))); + Assert.assertEquals(owner.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), + OWNER_ASSET_BALANCE); + Assert.assertTrue(isNullOrZero(toAccount.getAssetV2MapForTest() + .get(String.valueOf(tokenIdNum)))); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -635,11 +624,12 @@ public void SameTokenNameCloseZeroAmountTest() { Assert.assertTrue("Amount must be greater than 0.".equals(e.getMessage())); Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); - Assert.assertEquals(owner.getAssetMap().get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); - Assert.assertTrue(isNullOrZero(toAccount.getAssetMap().get(ASSET_NAME))); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + Assert.assertEquals(owner.getAssetMapForTest() + .get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); + Assert.assertTrue(isNullOrZero(toAccount.getAssetMapForTest().get(ASSET_NAME))); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -665,13 +655,14 @@ public void SameTokenNameOpenZeroAmountTest() { Assert.assertTrue("Amount must be greater than 0.".equals(e.getMessage())); Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); long tokenIdNum = dbManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), - OWNER_ASSET_BALANCE); - Assert.assertTrue(isNullOrZero(toAccount.getAssetMapV2().get(String.valueOf(tokenIdNum)))); + Assert.assertEquals(owner.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), + OWNER_ASSET_BALANCE); + Assert.assertTrue(isNullOrZero(toAccount + .getAssetV2MapForTest().get(String.valueOf(tokenIdNum)))); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -696,11 +687,12 @@ public void SameTokenNameCloseNegativeAmountTest() { Assert.assertTrue("Amount must be greater than 0.".equals(e.getMessage())); Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); - Assert.assertEquals(owner.getAssetMap().get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); - Assert.assertTrue(isNullOrZero(toAccount.getAssetMap().get(ASSET_NAME))); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + Assert.assertEquals(owner.getAssetMapForTest() + .get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); + Assert.assertTrue(isNullOrZero(toAccount.getAssetMapForTest().get(ASSET_NAME))); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -726,13 +718,14 @@ public void SameTokenNameOpenNegativeAmountTest() { Assert.assertTrue("Amount must be greater than 0.".equals(e.getMessage())); Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); long tokenIdNum = dbManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), - OWNER_ASSET_BALANCE); - Assert.assertTrue(isNullOrZero(toAccount.getAssetMapV2().get(String.valueOf(tokenIdNum)))); + Assert.assertEquals(owner.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), + OWNER_ASSET_BALANCE); + Assert.assertTrue(isNullOrZero(toAccount + .getAssetV2MapForTest().get(String.valueOf(tokenIdNum)))); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -746,7 +739,7 @@ public void SameTokenNameCloseNoneExistAssetTest() { createAssertBeforSameTokenNameActive(); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(1, "TTTTTTTTTTTT")); + .setAny(getContract(1, "TTTTTTTTTTTT")); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -758,11 +751,12 @@ public void SameTokenNameCloseNoneExistAssetTest() { Assert.assertTrue("No asset!".equals(e.getMessage())); Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); - Assert.assertEquals(owner.getAssetMap().get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); - Assert.assertTrue(isNullOrZero(toAccount.getAssetMap().get(ASSET_NAME))); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + Assert.assertEquals(owner.getAssetMapForTest() + .get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); + Assert.assertTrue(isNullOrZero(toAccount.getAssetMapForTest().get(ASSET_NAME))); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -776,7 +770,7 @@ public void SameTokenNameOpenNoneExistAssetTest() { createAssertSameTokenNameActive(); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(1, "TTTTTTTTTTTT")); + .setAny(getContract(1, "TTTTTTTTTTTT")); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -788,13 +782,14 @@ public void SameTokenNameOpenNoneExistAssetTest() { Assert.assertTrue("No asset!".equals(e.getMessage())); Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); long tokenIdNum = dbManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), - OWNER_ASSET_BALANCE); - Assert.assertTrue(isNullOrZero(toAccount.getAssetMapV2().get(String.valueOf(tokenIdNum)))); + Assert.assertEquals(owner.getAssetV2MapForTest() + .get(String.valueOf(tokenIdNum)).longValue(), OWNER_ASSET_BALANCE); + Assert.assertTrue(isNullOrZero(toAccount + .getAssetV2MapForTest().get(String.valueOf(tokenIdNum)))); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -809,30 +804,30 @@ public void SameTokenNameCloseNoExitToAccount() { createAssertBeforSameTokenNameActive(); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(100L, OWNER_ADDRESS, NOT_EXIT_ADDRESS)); + .setAny(getContract(100L, OWNER_ADDRESS, NOT_EXIT_ADDRESS)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { AccountCapsule noExitAccount = dbManager.getAccountStore() - .get(ByteArray.fromHexString(NOT_EXIT_ADDRESS)); + .get(ByteArray.fromHexString(NOT_EXIT_ADDRESS)); Assert.assertTrue(null == noExitAccount); actuator.validate(); actuator.execute(ret); noExitAccount = dbManager.getAccountStore() - .get(ByteArray.fromHexString(NOT_EXIT_ADDRESS)); + .get(ByteArray.fromHexString(NOT_EXIT_ADDRESS)); Assert.assertFalse(null == noExitAccount); //Had created. Assert.assertEquals(noExitAccount.getBalance(), 0); actuator.execute(ret); } catch (ContractValidateException e) { Assert.assertTrue(e instanceof ContractValidateException); - Assert - .assertEquals("Validate TransferAssetActuator error, insufficient fee.", e.getMessage()); + Assert.assertEquals( + "Validate TransferAssetActuator error, insufficient fee.", e.getMessage()); AccountCapsule owner = dbManager.getAccountStore() - .get(ByteArray.fromHexString(OWNER_ADDRESS)); - Assert - .assertEquals(owner.getAssetMap().get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + Assert.assertEquals(owner.getAssetMapForTest() + .get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); AccountCapsule noExitAccount = dbManager.getAccountStore() - .get(ByteArray.fromHexString(NOT_EXIT_ADDRESS)); + .get(ByteArray.fromHexString(NOT_EXIT_ADDRESS)); Assert.assertTrue(noExitAccount == null); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); @@ -847,31 +842,31 @@ public void SameTokenNameOpenNoExitToAccount() { createAssertSameTokenNameActive(); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(100L, OWNER_ADDRESS, NOT_EXIT_ADDRESS_2)); + .setAny(getContract(100L, OWNER_ADDRESS, NOT_EXIT_ADDRESS_2)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { AccountCapsule noExitAccount = dbManager.getAccountStore() - .get(ByteArray.fromHexString(NOT_EXIT_ADDRESS_2)); + .get(ByteArray.fromHexString(NOT_EXIT_ADDRESS_2)); Assert.assertTrue(null == noExitAccount); actuator.validate(); actuator.execute(ret); noExitAccount = dbManager.getAccountStore() - .get(ByteArray.fromHexString(NOT_EXIT_ADDRESS_2)); + .get(ByteArray.fromHexString(NOT_EXIT_ADDRESS_2)); Assert.assertFalse(null == noExitAccount); //Had created. Assert.assertEquals(noExitAccount.getBalance(), 0); actuator.execute(ret); } catch (ContractValidateException e) { Assert.assertTrue(e instanceof ContractValidateException); - Assert - .assertEquals("Validate TransferAssetActuator error, insufficient fee.", e.getMessage()); + Assert.assertEquals( + "Validate TransferAssetActuator error, insufficient fee.", e.getMessage()); AccountCapsule owner = dbManager.getAccountStore() - .get(ByteArray.fromHexString(OWNER_ADDRESS)); + .get(ByteArray.fromHexString(OWNER_ADDRESS)); long tokenIdNum = dbManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), - OWNER_ASSET_BALANCE); + Assert.assertEquals(owner.getAssetV2MapForTest() + .get(String.valueOf(tokenIdNum)).longValue(), OWNER_ASSET_BALANCE); AccountCapsule noExitAccount = dbManager.getAccountStore() - .get(ByteArray.fromHexString(NOT_EXIT_ADDRESS_2)); + .get(ByteArray.fromHexString(NOT_EXIT_ADDRESS_2)); Assert.assertTrue(noExitAccount == null); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); @@ -900,11 +895,13 @@ public void SameTokenNameCloseAddOverflowTest() { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertTrue("long overflow".equals(e.getMessage())); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); - Assert.assertEquals(owner.getAssetMap().get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); - Assert.assertEquals(toAccount.getAssetMap().get(ASSET_NAME).longValue(), Long.MAX_VALUE); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + Assert.assertEquals(owner.getAssetMapForTest() + .get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); + Assert.assertEquals(toAccount.getAssetMapForTest() + .get(ASSET_NAME).longValue(), Long.MAX_VALUE); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -934,13 +931,13 @@ public void SameTokenNameOpenAddOverflowTest() { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertTrue("long overflow".equals(e.getMessage())); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); toAccount = dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), - OWNER_ASSET_BALANCE); - Assert.assertEquals(toAccount.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), - Long.MAX_VALUE); + Assert.assertEquals(owner.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), + OWNER_ASSET_BALANCE); + Assert.assertEquals(toAccount.getAssetV2MapForTest() + .get(String.valueOf(tokenIdNum)).longValue(), Long.MAX_VALUE); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -954,7 +951,7 @@ public void SameTokenNameCloseTransferToYourself() { createAssertBeforSameTokenNameActive(); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(100L, OWNER_ADDRESS, OWNER_ADDRESS)); + .setAny(getContract(100L, OWNER_ADDRESS, OWNER_ADDRESS)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -966,11 +963,12 @@ public void SameTokenNameCloseTransferToYourself() { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Cannot transfer asset to yourself.", e.getMessage()); AccountCapsule owner = dbManager.getAccountStore() - .get(ByteArray.fromHexString(OWNER_ADDRESS)); + .get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = dbManager.getAccountStore() - .get(ByteArray.fromHexString(TO_ADDRESS)); - Assert.assertEquals(owner.getAssetMap().get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); - Assert.assertTrue(isNullOrZero(toAccount.getAssetMap().get(ASSET_NAME))); + .get(ByteArray.fromHexString(TO_ADDRESS)); + Assert.assertEquals(owner.getAssetMapForTest() + .get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); + Assert.assertTrue(isNullOrZero(toAccount.getAssetMapForTest().get(ASSET_NAME))); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -985,7 +983,7 @@ public void SameTokenNameOpenTransferToYourself() { createAssertSameTokenNameActive(); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(100L, OWNER_ADDRESS, OWNER_ADDRESS)); + .setAny(getContract(100L, OWNER_ADDRESS, OWNER_ADDRESS)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -997,13 +995,14 @@ public void SameTokenNameOpenTransferToYourself() { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Cannot transfer asset to yourself.", e.getMessage()); AccountCapsule owner = dbManager.getAccountStore() - .get(ByteArray.fromHexString(OWNER_ADDRESS)); + .get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = dbManager.getAccountStore() - .get(ByteArray.fromHexString(TO_ADDRESS)); + .get(ByteArray.fromHexString(TO_ADDRESS)); long tokenIdNum = dbManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), - OWNER_ASSET_BALANCE); - Assert.assertTrue(isNullOrZero(toAccount.getAssetMapV2().get(String.valueOf(tokenIdNum)))); + Assert.assertEquals(owner.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), + OWNER_ASSET_BALANCE); + Assert.assertTrue(isNullOrZero(toAccount + .getAssetV2MapForTest().get(String.valueOf(tokenIdNum)))); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -1017,7 +1016,7 @@ public void SameTokenNameCloseInvalidOwnerAddress() { createAssertBeforSameTokenNameActive(); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(100L, OWNER_ADDRESS_INVALID, TO_ADDRESS)); + .setAny(getContract(100L, OWNER_ADDRESS_INVALID, TO_ADDRESS)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -1028,11 +1027,12 @@ public void SameTokenNameCloseInvalidOwnerAddress() { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Invalid ownerAddress", e.getMessage()); AccountCapsule owner = dbManager.getAccountStore() - .get(ByteArray.fromHexString(OWNER_ADDRESS)); + .get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = dbManager.getAccountStore() - .get(ByteArray.fromHexString(TO_ADDRESS)); - Assert.assertEquals(owner.getAssetMap().get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); - Assert.assertTrue(isNullOrZero(toAccount.getAssetMap().get(ASSET_NAME))); + .get(ByteArray.fromHexString(TO_ADDRESS)); + Assert.assertEquals(owner.getAssetMapForTest() + .get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); + Assert.assertTrue(isNullOrZero(toAccount.getAssetMapForTest().get(ASSET_NAME))); } catch (ContractExeException e) { Assert.assertTrue(e instanceof ContractExeException); } @@ -1046,7 +1046,7 @@ public void SameTokenNameOpenInvalidOwnerAddress() { createAssertSameTokenNameActive(); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(100L, OWNER_ADDRESS_INVALID, TO_ADDRESS)); + .setAny(getContract(100L, OWNER_ADDRESS_INVALID, TO_ADDRESS)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -1057,13 +1057,14 @@ public void SameTokenNameOpenInvalidOwnerAddress() { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Invalid ownerAddress", e.getMessage()); AccountCapsule owner = dbManager.getAccountStore() - .get(ByteArray.fromHexString(OWNER_ADDRESS)); + .get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = dbManager.getAccountStore() - .get(ByteArray.fromHexString(TO_ADDRESS)); + .get(ByteArray.fromHexString(TO_ADDRESS)); long tokenIdNum = dbManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), - OWNER_ASSET_BALANCE); - Assert.assertTrue(isNullOrZero(toAccount.getAssetMapV2().get(String.valueOf(tokenIdNum)))); + Assert.assertEquals(owner.getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), + OWNER_ASSET_BALANCE); + Assert.assertTrue(isNullOrZero(toAccount + .getAssetV2MapForTest().get(String.valueOf(tokenIdNum)))); } catch (ContractExeException e) { Assert.assertTrue(e instanceof ContractExeException); } @@ -1077,7 +1078,7 @@ public void SameTokenNameCloseInvalidToAddress() { createAssertBeforSameTokenNameActive(); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(100L, OWNER_ADDRESS, TO_ADDRESS_INVALID)); + .setAny(getContract(100L, OWNER_ADDRESS, TO_ADDRESS_INVALID)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -1088,11 +1089,12 @@ public void SameTokenNameCloseInvalidToAddress() { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Invalid toAddress", e.getMessage()); AccountCapsule owner = dbManager.getAccountStore() - .get(ByteArray.fromHexString(OWNER_ADDRESS)); + .get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = dbManager.getAccountStore() - .get(ByteArray.fromHexString(TO_ADDRESS)); - Assert.assertEquals(owner.getAssetMap().get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); - Assert.assertTrue(isNullOrZero(toAccount.getAssetMap().get(ASSET_NAME))); + .get(ByteArray.fromHexString(TO_ADDRESS)); + Assert.assertEquals(owner.getAssetMapForTest() + .get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); + Assert.assertTrue(isNullOrZero(toAccount.getAssetMapForTest().get(ASSET_NAME))); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -1106,7 +1108,7 @@ public void SameTokenNameOpenInvalidToAddress() { createAssertSameTokenNameActive(); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(100L, OWNER_ADDRESS, TO_ADDRESS_INVALID)); + .setAny(getContract(100L, OWNER_ADDRESS, TO_ADDRESS_INVALID)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -1117,13 +1119,14 @@ public void SameTokenNameOpenInvalidToAddress() { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Invalid toAddress", e.getMessage()); AccountCapsule owner = dbManager.getAccountStore() - .get(ByteArray.fromHexString(OWNER_ADDRESS)); + .get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = dbManager.getAccountStore() - .get(ByteArray.fromHexString(TO_ADDRESS)); + .get(ByteArray.fromHexString(TO_ADDRESS)); long tokenIdNum = dbManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), - OWNER_ASSET_BALANCE); - Assert.assertTrue(isNullOrZero(toAccount.getAssetMapV2().get(String.valueOf(tokenIdNum)))); + Assert.assertEquals(owner.getAssetV2MapForTest() + .get(String.valueOf(tokenIdNum)).longValue(), OWNER_ASSET_BALANCE); + Assert.assertTrue(isNullOrZero(toAccount + .getAssetV2MapForTest().get(String.valueOf(tokenIdNum)))); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -1136,33 +1139,34 @@ public void SameTokenNameOpenInvalidToAddress() { public void SameTokenNameCloseOwnerNoThisAsset() { createAssertBeforSameTokenNameActive(); AccountCapsule ownerAssetCapsule = - new AccountCapsule( - ByteString.copyFrom(ByteArray.fromHexString(ownerAsset_ADDRESS)), - ByteString.copyFromUtf8("ownerAsset"), - AccountType.AssetIssue); + new AccountCapsule( + ByteString.copyFrom(ByteArray.fromHexString(ownerAsset_ADDRESS)), + ByteString.copyFromUtf8("ownerAsset"), + AccountType.AssetIssue); ownerAssetCapsule.addAsset(ownerASSET_NAME.getBytes(), OWNER_ASSET_Test_BALANCE); AssetIssueContract assetIssueTestContract = - AssetIssueContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAsset_ADDRESS))) - .setName(ByteString.copyFrom(ByteArray.fromString(ownerASSET_NAME))) - .setTotalSupply(TOTAL_SUPPLY) - .setTrxNum(TRX_NUM) - .setNum(NUM) - .setStartTime(START_TIME) - .setEndTime(END_TIME) - .setVoteScore(VOTE_SCORE) - .setDescription(ByteString.copyFrom(ByteArray.fromString(DESCRIPTION))) - .setUrl(ByteString.copyFrom(ByteArray.fromString(URL))) - .build(); + AssetIssueContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom( + ByteArray.fromHexString(ownerAsset_ADDRESS))) + .setName(ByteString.copyFrom(ByteArray.fromString(ownerASSET_NAME))) + .setTotalSupply(TOTAL_SUPPLY) + .setTrxNum(TRX_NUM) + .setNum(NUM) + .setStartTime(START_TIME) + .setEndTime(END_TIME) + .setVoteScore(VOTE_SCORE) + .setDescription(ByteString.copyFrom(ByteArray.fromString(DESCRIPTION))) + .setUrl(ByteString.copyFrom(ByteArray.fromString(URL))) + .build(); AssetIssueCapsule assetIssueCapsule = new AssetIssueCapsule(assetIssueTestContract); dbManager.getAccountStore() - .put(ownerAssetCapsule.getAddress().toByteArray(), ownerAssetCapsule); + .put(ownerAssetCapsule.getAddress().toByteArray(), ownerAssetCapsule); dbManager - .getAssetIssueStore() - .put(assetIssueCapsule.createDbKey(), assetIssueCapsule); + .getAssetIssueStore() + .put(assetIssueCapsule.createDbKey(), assetIssueCapsule); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(1, ownerASSET_NAME)); + .setAny(getContract(1, ownerASSET_NAME)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -1173,15 +1177,16 @@ public void SameTokenNameCloseOwnerNoThisAsset() { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertTrue("assetBalance must be greater than 0.".equals(e.getMessage())); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); - Assert.assertEquals(owner.getAssetMap().get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); - Assert.assertTrue(isNullOrZero(toAccount.getAssetMap().get(ASSET_NAME))); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + Assert.assertEquals(owner.getAssetMapForTest() + .get(ASSET_NAME).longValue(), OWNER_ASSET_BALANCE); + Assert.assertTrue(isNullOrZero(toAccount.getAssetMapForTest().get(ASSET_NAME))); AccountCapsule ownerAsset = - dbManager.getAccountStore().get(ByteArray.fromHexString(ownerAsset_ADDRESS)); - Assert.assertEquals(ownerAsset.getAssetMap().get(ownerASSET_NAME).longValue(), - OWNER_ASSET_Test_BALANCE); + dbManager.getAccountStore().get(ByteArray.fromHexString(ownerAsset_ADDRESS)); + Assert.assertEquals(ownerAsset.getAssetMapForTest() + .get(ownerASSET_NAME).longValue(), OWNER_ASSET_Test_BALANCE); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -1195,36 +1200,37 @@ public void SameTokenNameOpenOwnerNoThisAsset() { createAssertSameTokenNameActive(); long tokenIdNum = 2000000; AccountCapsule ownerAssetCapsule = - new AccountCapsule( - ByteString.copyFrom(ByteArray.fromHexString(ownerAsset_ADDRESS)), - ByteString.copyFromUtf8("ownerAsset"), - AccountType.AssetIssue); + new AccountCapsule( + ByteString.copyFrom(ByteArray.fromHexString(ownerAsset_ADDRESS)), + ByteString.copyFromUtf8("ownerAsset"), + AccountType.AssetIssue); ownerAssetCapsule.addAssetV2(ByteArray.fromString(String.valueOf(tokenIdNum)), - OWNER_ASSET_Test_BALANCE); + OWNER_ASSET_Test_BALANCE); AssetIssueContract assetIssueTestContract = - AssetIssueContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAsset_ADDRESS))) - .setName(ByteString.copyFrom(ByteArray.fromString(ownerASSET_NAME))) - .setTotalSupply(TOTAL_SUPPLY) - .setTrxNum(TRX_NUM) - .setId(String.valueOf(tokenIdNum)) - .setNum(NUM) - .setStartTime(START_TIME) - .setEndTime(END_TIME) - .setVoteScore(VOTE_SCORE) - .setDescription(ByteString.copyFrom(ByteArray.fromString(DESCRIPTION))) - .setUrl(ByteString.copyFrom(ByteArray.fromString(URL))) - .build(); + AssetIssueContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom( + ByteArray.fromHexString(ownerAsset_ADDRESS))) + .setName(ByteString.copyFrom(ByteArray.fromString(ownerASSET_NAME))) + .setTotalSupply(TOTAL_SUPPLY) + .setTrxNum(TRX_NUM) + .setId(String.valueOf(tokenIdNum)) + .setNum(NUM) + .setStartTime(START_TIME) + .setEndTime(END_TIME) + .setVoteScore(VOTE_SCORE) + .setDescription(ByteString.copyFrom(ByteArray.fromString(DESCRIPTION))) + .setUrl(ByteString.copyFrom(ByteArray.fromString(URL))) + .build(); AssetIssueCapsule assetIssueCapsule = new AssetIssueCapsule(assetIssueTestContract); dbManager.getAccountStore() - .put(ownerAssetCapsule.getAddress().toByteArray(), ownerAssetCapsule); + .put(ownerAssetCapsule.getAddress().toByteArray(), ownerAssetCapsule); dbManager.getAssetIssueV2Store() - .put(assetIssueCapsule.createDbV2Key(), assetIssueCapsule); + .put(assetIssueCapsule.createDbV2Key(), assetIssueCapsule); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(1, String.valueOf(tokenIdNum))); + .setAny(getContract(1, String.valueOf(tokenIdNum))); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -1235,17 +1241,19 @@ public void SameTokenNameOpenOwnerNoThisAsset() { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertTrue("assetBalance must be greater than 0.".equals(e.getMessage())); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); long secondTokenIdNum = dbManager.getDynamicPropertiesStore().getTokenIdNum(); - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(secondTokenIdNum)).longValue(), - OWNER_ASSET_BALANCE); - Assert.assertTrue(isNullOrZero(toAccount.getAssetMapV2().get(String.valueOf(tokenIdNum)))); + Assert.assertEquals(owner.getAssetV2MapForTest() + .get(String.valueOf(secondTokenIdNum)).longValue(), OWNER_ASSET_BALANCE); + Assert.assertTrue(isNullOrZero(toAccount + .getAssetV2MapForTest().get(String.valueOf(tokenIdNum)))); AccountCapsule ownerAsset = - dbManager.getAccountStore().get(ByteArray.fromHexString(ownerAsset_ADDRESS)); - Assert.assertEquals(ownerAsset.getAssetMapV2().get(String.valueOf(tokenIdNum)).longValue(), - OWNER_ASSET_Test_BALANCE); + dbManager.getAccountStore().get(ByteArray.fromHexString(ownerAsset_ADDRESS)); + Assert.assertEquals(ownerAsset + .getAssetV2MapForTest().get(String.valueOf(tokenIdNum)).longValue(), + OWNER_ASSET_Test_BALANCE); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } @@ -1260,19 +1268,19 @@ public void sameTokenNameCloseNoOwnerAccount() { long id = dbManager.getDynamicPropertiesStore().getTokenIdNum() + 1; dbManager.getDynamicPropertiesStore().saveTokenIdNum(id); AssetIssueContract assetIssueContract = - AssetIssueContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) - .setName(ByteString.copyFrom(ByteArray.fromString(ASSET_NAME))) - .setId(Long.toString(id)) - .setTotalSupply(TOTAL_SUPPLY) - .setTrxNum(TRX_NUM) - .setNum(NUM) - .setStartTime(START_TIME) - .setEndTime(END_TIME) - .setVoteScore(VOTE_SCORE) - .setDescription(ByteString.copyFrom(ByteArray.fromString(DESCRIPTION))) - .setUrl(ByteString.copyFrom(ByteArray.fromString(URL))) - .build(); + AssetIssueContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setName(ByteString.copyFrom(ByteArray.fromString(ASSET_NAME))) + .setId(Long.toString(id)) + .setTotalSupply(TOTAL_SUPPLY) + .setTrxNum(TRX_NUM) + .setNum(NUM) + .setStartTime(START_TIME) + .setEndTime(END_TIME) + .setVoteScore(VOTE_SCORE) + .setDescription(ByteString.copyFrom(ByteArray.fromString(DESCRIPTION))) + .setUrl(ByteString.copyFrom(ByteArray.fromString(URL))) + .build(); AssetIssueCapsule assetIssueCapsule = new AssetIssueCapsule(assetIssueContract); dbManager.getAssetIssueStore().put(assetIssueCapsule.createDbKey(), assetIssueCapsule); @@ -1308,7 +1316,7 @@ public void SameTokenNameCloseAssetNameTest() { ByteString emptyName = ByteString.EMPTY; TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(100L, emptyName)); + .setAny(getContract(100L, emptyName)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -1330,18 +1338,18 @@ public void SameTokenNameCloseAssetNameTest() { createAsset(assetName); actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(100L, assetName)); + .setAny(getContract(100L, assetName)); try { actuator.validate(); actuator.execute(ret); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); - Assert.assertEquals(owner.getAssetMap().get(assetName).longValue(), - OWNER_ASSET_BALANCE - 100); - Assert.assertEquals(toAccount.getAssetMap().get(assetName).longValue(), 100L); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + Assert.assertEquals(owner.getAssetMapForTest().get(assetName).longValue(), + OWNER_ASSET_BALANCE - 100); + Assert.assertEquals(toAccount.getAssetMapForTest().get(assetName).longValue(), 100L); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -1353,18 +1361,18 @@ public void SameTokenNameCloseAssetNameTest() { createAsset(assetName); actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(100L, assetName)); + .setAny(getContract(100L, assetName)); try { actuator.validate(); actuator.execute(ret); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = - dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); - Assert.assertEquals(owner.getAssetMap().get(assetName).longValue(), - OWNER_ASSET_BALANCE - 100); - Assert.assertEquals(toAccount.getAssetMap().get(assetName).longValue(), 100L); + dbManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); + Assert.assertEquals(owner.getAssetMapForTest().get(assetName).longValue(), + OWNER_ASSET_BALANCE - 100); + Assert.assertEquals(toAccount.getAssetMapForTest().get(assetName).longValue(), 100L); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -1380,10 +1388,10 @@ public void commonErrorCheck() { actuatorTest.noContract(); Any invalidContractTypes = Any.pack(AssetIssueContractOuterClass.AssetIssueContract.newBuilder() - .build()); + .build()); actuatorTest.setInvalidContract(invalidContractTypes); actuatorTest.setInvalidContractTypeMsg("contract type error", - "contract type error, expected type [TransferAssetContract], real type["); + "contract type error, expected type [TransferAssetContract], real type["); actuatorTest.invalidContractType(); actuatorTest.setContract(getContract(100L)); @@ -1398,8 +1406,8 @@ public void commonErrorCheck() { */ @Test public void transferToContractAddress() - throws ContractExeException, ReceiptCheckErrException, VMIllegalException, - ContractValidateException, BalanceInsufficientException { + throws ContractExeException, ReceiptCheckErrException, VMIllegalException, + ContractValidateException, BalanceInsufficientException { dbManager.getDynamicPropertiesStore().saveForbidTransferToContract(1); createAssertSameTokenNameActive(); VMConfig.initAllowMultiSign(1); @@ -1408,53 +1416,56 @@ public void transferToContractAddress() VMConfig.initAllowTvmSolidity059(1); String contractName = "testContract"; byte[] address = Hex.decode(OWNER_ADDRESS); - adjustBalance(dbManager.getChainBaseManager().getAccountStore(), address, 1000000000L); - - String ABI = - "[]"; - String codes = "608060405261019c806100136000396000f3fe608060405260043610610045577c0100000000000" - + "00000000000000000000000000000000000000000000060003504632a205edf811461004a5780634cd2270c" - + "146100c8575b600080fd5b34801561005657600080fd5b50d3801561006357600080fd5b50d2801561007057" - + "600080fd5b506100c6600480360360c081101561008757600080fd5b5073ffffffffffffffffffffffffffff" - + "ffffffffffff813581169160208101358216916040820135169060608101359060808101359060a001356100" - + "d0565b005b6100c661016e565b60405173ffffffffffffffffffffffffffffffffffffffff87169084156108" - + "fc029085906000818181858888f1505060405173ffffffffffffffffffffffffffffffffffffffff89169350" - + "85156108fc0292508591506000818181858888f1505060405173ffffffffffffffffffffffffffffffffffff" - + "ffff8816935084156108fc0292508491506000818181858888f15050505050505050505050565b56fea16562" - + "7a7a72305820cc2d598d1b3f968bbdc7825ce83d22dad48192f4bf95bda7f9e4ddf61669ba830029"; + adjustBalance(dbManager.getChainBaseManager() + .getAccountStore(), address, 1000000000L); + + String ABI = "[]"; + String codes = "608060405261019c806100136000396000f3fe6080604052600436106100455" + + "77c01000000000000000000000000000000000000000000000000000000006000350" + + "4632a205edf811461004a5780634cd2270c146100c8575b600080fd5b34801561005" + + "657600080fd5b50d3801561006357600080fd5b50d2801561007057600080fd5b506" + + "100c6600480360360c081101561008757600080fd5b5073fffffffffffffffffffff" + + "fffffffffffffffffff8135811691602081013582169160408201351690606081013" + + "59060808101359060a001356100d0565b005b6100c661016e565b60405173fffffff" + + "fffffffffffffffffffffffffffffffff87169084156108fc0290859060008181818" + + "58888f1505060405173ffffffffffffffffffffffffffffffffffffffff891693508" + + "5156108fc0292508591506000818181858888f1505060405173fffffffffffffffff" + + "fffffffffffffffffffffff8816935084156108fc029250849150600081818185888" + + "8f15050505050505050505050565b56fea165627a7a72305820cc2d598d1b3f968bb" + + "dc7825ce83d22dad48192f4bf95bda7f9e4ddf61669ba830029"; long value = 1; long feeLimit = 1000000000L; long consumeUserResourcePercent = 0; DepositImpl deposit = DepositImpl.createRoot(dbManager); byte[] contractAddress = TvmTestUtils - .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, codes, value, - feeLimit, consumeUserResourcePercent, null, 0, 0, - deposit, null); + .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, + codes, value, feeLimit, consumeUserResourcePercent, + null, 0, 0, deposit, null); TransferAssetActuator actuator = new TransferAssetActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(100L, contractAddress)); + .setAny(getContract(100L, contractAddress)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { actuator.validate(); actuator.execute(ret); Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); AccountCapsule toAccount = - dbManager.getAccountStore().get(contractAddress); + dbManager.getAccountStore().get(contractAddress); // V1, data is not exist - Assert.assertNull(owner.getAssetMap().get(ASSET_NAME)); - Assert.assertNull(toAccount.getAssetMap().get(ASSET_NAME)); + Assert.assertNull(owner.getAssetMapForTest().get(ASSET_NAME)); + Assert.assertNull(toAccount.getAssetMapForTest().get(ASSET_NAME)); // check V2 long tokenIdNum = dbManager.getDynamicPropertiesStore().getTokenIdNum(); Assert.assertEquals( - owner.getInstance().getAssetV2Map().get(String.valueOf(tokenIdNum)).longValue(), - OWNER_ASSET_BALANCE - 100); + owner.getInstance().getAssetV2Map().get(String.valueOf(tokenIdNum)).longValue(), + OWNER_ASSET_BALANCE - 100); Assert.assertEquals( - toAccount.getInstance().getAssetV2Map().get(String.valueOf(tokenIdNum)).longValue(), - 100L); + toAccount.getInstance().getAssetV2Map().get(String.valueOf(tokenIdNum)).longValue(), + 100L); } catch (ContractValidateException e) { Assert.assertTrue(e.getMessage().contains("Cannot transfer")); } catch (ContractExeException e) { diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeAssetActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeAssetActuatorTest.java index f83260256a7..70437a890df 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeAssetActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeAssetActuatorTest.java @@ -15,7 +15,6 @@ import org.tron.common.utils.StringUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.capsule.AccountAssetCapsule; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.TransactionResultCapsule; @@ -106,11 +105,6 @@ private void createAssertBeforSameTokenNameActive() { dbManager.getAssetIssueStore().put(assetIssueCapsule.createDbKey(), assetIssueCapsule); dbManager.getAssetIssueV2Store().put(assetIssueCapsule.createDbV2Key(), assetIssueCapsule); - AccountAssetCapsule ownerAddressAsset = - new AccountAssetCapsule(StringUtil.hexString2ByteString(OWNER_ADDRESS)); - dbManager.getAccountAssetStore().put(ownerAddressAsset.getAddress().toByteArray(), - ownerAddressAsset); - AccountCapsule ownerCapsule = new AccountCapsule( ByteString.copyFromUtf8("owner"), @@ -132,11 +126,6 @@ private void createAssertSameTokenNameActive() { AssetIssueCapsule assetIssueCapsule = new AssetIssueCapsule(builder.build()); dbManager.getAssetIssueV2Store().put(assetIssueCapsule.createDbV2Key(), assetIssueCapsule); - AccountAssetCapsule ownerAddressAsset = - new AccountAssetCapsule(StringUtil.hexString2ByteString(OWNER_ADDRESS)); - dbManager.getAccountAssetStore().put(ownerAddressAsset.getAddress().toByteArray(), - ownerAddressAsset); - AccountCapsule ownerCapsule = new AccountCapsule( ByteString.copyFromUtf8("owner"), @@ -159,7 +148,6 @@ public void SameTokenNameCloseUnfreezeAsset() { dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); AccountCapsule ownerAccount = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); - ownerAccount.importAsset(); Account account = ownerAccount .getInstance(); Frozen newFrozen0 = Frozen.newBuilder() @@ -185,9 +173,9 @@ public void SameTokenNameCloseUnfreezeAsset() { AccountCapsule owner = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); //V1 - Assert.assertEquals(owner.getAssetMap().get(assetName).longValue(), frozenBalance); + Assert.assertEquals(owner.getAssetMapForTest().get(assetName).longValue(), frozenBalance); //V2 - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(tokenId)).longValue(), + Assert.assertEquals(owner.getAssetV2MapForTest().get(String.valueOf(tokenId)).longValue(), frozenBalance); Assert.assertEquals(owner.getFrozenSupplyCount(), 1); } catch (ContractValidateException e) { @@ -209,7 +197,6 @@ public void SameTokenNameActiveUnfreezeAsset() { AccountCapsule ownerAccount = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); - ownerAccount.importAsset(); Account account = ownerAccount.getInstance(); Frozen newFrozen0 = Frozen.newBuilder() .setFrozenBalance(frozenBalance) @@ -233,9 +220,9 @@ public void SameTokenNameActiveUnfreezeAsset() { AccountCapsule owner = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); //V1 assert not exist - Assert.assertNull(owner.getAssetMap().get(assetName)); + Assert.assertNull(owner.getAssetMapForTest().get(assetName)); //V2 - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(tokenId)).longValue(), + Assert.assertEquals(owner.getAssetV2MapForTest().get(String.valueOf(tokenId)).longValue(), frozenBalance); Assert.assertEquals(owner.getFrozenSupplyCount(), 1); } catch (ContractValidateException e) { @@ -259,7 +246,6 @@ public void SameTokenNameActiveInitAndAcitveUnfreezeAsset() { AccountCapsule ownerAccount = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); - ownerAccount.importAsset(); Account account = ownerAccount .getInstance(); Frozen newFrozen0 = Frozen.newBuilder() @@ -285,9 +271,9 @@ public void SameTokenNameActiveInitAndAcitveUnfreezeAsset() { AccountCapsule owner = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); //V1 assert not exist - Assert.assertNull(owner.getAssetMap().get(assetName)); + Assert.assertNull(owner.getAssetMapForTest().get(assetName)); //V2 - Assert.assertEquals(owner.getAssetMapV2().get(String.valueOf(tokenId)).longValue(), + Assert.assertEquals(owner.getAssetV2MapForTest().get(String.valueOf(tokenId)).longValue(), frozenBalance); Assert.assertEquals(owner.getFrozenSupplyCount(), 1); } catch (ContractValidateException e) { @@ -399,7 +385,6 @@ public void notTimeToUnfreeze() { AccountCapsule ownerAccount = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); - ownerAccount.importAsset(); Account account = ownerAccount.getInstance(); Frozen newFrozen = Frozen.newBuilder() diff --git a/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java index e0a9e188b06..6c97848cd70 100644 --- a/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java @@ -9,20 +9,15 @@ import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.tron.common.application.TronApplicationContext; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.capsule.utils.AssetUtil; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; -import org.tron.core.store.AccountAssetStore; -import org.tron.core.store.AccountStore; -import org.tron.protos.Protocol; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Key; import org.tron.protos.Protocol.Permission; @@ -118,7 +113,7 @@ public void AssetAmountTest() { Assert.assertTrue(addBoolean); - Map assetMap = accountCapsuleTest.getAssetMap(); + Map assetMap = accountCapsuleTest.getAssetMapForTest(); for (Map.Entry entry : assetMap.entrySet()) { Assert.assertEquals(nameAdd, entry.getKey()); Assert.assertEquals(amountAdd, entry.getValue().longValue()); @@ -129,7 +124,7 @@ public void AssetAmountTest() { .reduceAssetAmount(ByteArray.fromString("TokenX"), amountReduce); Assert.assertTrue(reduceBoolean); - Map assetMapAfter = accountCapsuleTest.getAssetMap(); + Map assetMapAfter = accountCapsuleTest.getAssetMapForTest(); for (Map.Entry entry : assetMapAfter.entrySet()) { Assert.assertEquals(nameAdd, entry.getKey()); Assert.assertEquals(amountAdd - amountReduce, entry.getValue().longValue()); @@ -198,8 +193,8 @@ public void sameTokenNameCloseAssertAmountV2test() { dbManager.getAccountStore().put(accountCapsule.getAddress().toByteArray(), accountCapsule); accountCapsule.addAssetV2(ByteArray.fromString(String.valueOf(id)), 1000L); - Assert.assertEquals(accountCapsule.getAssetMap().get(ASSET_NAME).longValue(), 1000L); - Assert.assertEquals(accountCapsule.getAssetMapV2().get(String.valueOf(id)).longValue(), + Assert.assertEquals(accountCapsule.getAssetMapForTest().get(ASSET_NAME).longValue(), 1000L); + Assert.assertEquals(accountCapsule.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), 1000L); //assetBalanceEnoughV2 @@ -222,10 +217,10 @@ public void sameTokenNameCloseAssertAmountV2test() { Assert.assertTrue(accountCapsule.addAssetAmountV2(ByteArray.fromString(ASSET_NAME), 500, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore())); // 1000-999 +500 - Assert.assertEquals(accountCapsule.getAssetMap().get(ASSET_NAME).longValue(), 501L); + Assert.assertEquals(accountCapsule.getAssetMapForTest().get(ASSET_NAME).longValue(), 501L); Assert.assertTrue(accountCapsule.addAssetAmountV2(ByteArray.fromString("abc"), 500, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore())); - Assert.assertEquals(accountCapsule.getAssetMap().get("abc").longValue(), 500L); + Assert.assertEquals(accountCapsule.getAssetMapForTest().get("abc").longValue(), 500L); } /** @@ -279,7 +274,7 @@ public void sameTokenNameOpenAssertAmountV2test() { 10000); accountCapsule.addAssetV2(ByteArray.fromString(String.valueOf(id)), 1000L); dbManager.getAccountStore().put(accountCapsule.getAddress().toByteArray(), accountCapsule); - Assert.assertEquals(accountCapsule.getAssetMapV2().get(String.valueOf(id)).longValue(), + Assert.assertEquals(accountCapsule.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), 1000L); //assetBalanceEnoughV2 @@ -305,13 +300,13 @@ public void sameTokenNameOpenAssertAmountV2test() { Assert.assertTrue(accountCapsule.addAssetAmountV2(ByteArray.fromString(String.valueOf(id)), 500, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore())); // 1000-999 +500 - Assert.assertEquals(accountCapsule.getAssetMapV2().get(String.valueOf(id)).longValue(), + Assert.assertEquals(accountCapsule.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), 501L); //abc Assert.assertTrue(accountCapsule.addAssetAmountV2(ByteArray.fromString(String.valueOf(id + 1)), 500, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore())); Assert - .assertEquals(accountCapsule.getAssetMapV2().get(String.valueOf(id + 1)).longValue(), + .assertEquals(accountCapsule.getAssetV2MapForTest().get(String.valueOf(id + 1)).longValue(), 500L); } @@ -339,74 +334,4 @@ public void witnessPermissionTest() { Arrays.equals(ByteArray.fromHexString(witnessPermissionAddress), accountCapsule.getWitnessPermissionAddress())); } - - @Test - public void importAssetTest() { - AccountAssetStore accountAssetStore = dbManager.getAccountAssetStore(); - AccountStore accountStore = dbManager.getAccountStore(); - - dbManager.getDynamicPropertiesStore().saveAllowSameTokenName(1); - long id = dbManager.getDynamicPropertiesStore().getTokenIdNum() + 1; - dbManager.getDynamicPropertiesStore().saveTokenIdNum(id); - - AssetIssueContract assetIssueContract = - AssetIssueContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) - .setName(ByteString.copyFrom(ByteArray.fromString(ASSET_NAME))) - .setId(Long.toString(id)) - .setTotalSupply(TOTAL_SUPPLY) - .setTrxNum(TRX_NUM) - .setNum(NUM) - .setStartTime(START_TIME) - .setEndTime(END_TIME) - .setVoteScore(VOTE_SCORE) - .setDescription(ByteString.copyFrom(ByteArray.fromString(DESCRIPTION))) - .setUrl(ByteString.copyFrom(ByteArray.fromString(URL))) - .build(); - AssetIssueCapsule assetIssueCapsule = new AssetIssueCapsule(assetIssueContract); - dbManager.getAssetIssueV2Store().put(assetIssueCapsule.createDbV2Key(), assetIssueCapsule); - - AssetIssueContract assetIssueContract2 = - AssetIssueContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) - .setName(ByteString.copyFrom(ByteArray.fromString("abc"))) - .setId(Long.toString(id + 1)) - .setTotalSupply(TOTAL_SUPPLY) - .setTrxNum(TRX_NUM) - .setNum(NUM) - .setStartTime(START_TIME) - .setEndTime(END_TIME) - .setVoteScore(VOTE_SCORE) - .setDescription(ByteString.copyFrom(ByteArray.fromString(DESCRIPTION))) - .setUrl(ByteString.copyFrom(ByteArray.fromString(URL))) - .build(); - AssetIssueCapsule assetIssueCapsule2 = new AssetIssueCapsule(assetIssueContract2); - dbManager.getAssetIssueV2Store().put(assetIssueCapsule2.createDbV2Key(), assetIssueCapsule2); - - AccountCapsule accountCapsule = - new AccountCapsule( - ByteString.copyFromUtf8("owner"), - ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), - AccountType.Normal, - 10000); - accountCapsule.addAssetV2(ByteArray.fromString(String.valueOf(id)), 1000L); - byte[] address = accountCapsule.getAddress().toByteArray(); - accountStore.put(address, accountCapsule); - - Protocol.Account account = accountCapsule.getInstance(); - Protocol.AccountAsset accountAsset = AssetUtil.getAsset(account); - if (null != accountAsset) { - accountAssetStore.put(accountCapsule.getAddress().toByteArray(), new AccountAssetCapsule( - accountAsset)); - account = AssetUtil.clearAsset(account); - accountCapsule.setIsAssetImport(false); - accountCapsule.setInstance(account); - } - - accountStore.put(address, accountCapsule); - Assert.assertEquals(accountCapsule.getAssetMapV2().size(), 0); - AccountAssetCapsule accountAssetCapsule = accountAssetStore.get(address); - Assert.assertNotNull(accountAssetCapsule); - Assert.assertEquals(accountAssetCapsule.getAssetMapV2().size(), 1); - } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java b/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java index 11e77097baa..b649c270eae 100644 --- a/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java +++ b/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java @@ -1,18 +1,3 @@ -/* - * java-tron is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * java-tron is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - package org.tron.core.capsule.utils; import com.google.common.collect.Lists; @@ -25,10 +10,8 @@ import org.junit.Assert; import org.junit.Test; import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; -import org.tron.core.capsule.AccountAssetCapsule; import org.tron.core.capsule.AccountCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; @@ -36,9 +19,6 @@ import org.tron.core.store.AccountAssetStore; import org.tron.protos.Protocol; - - - @Slf4j public class AssetUtilTest { @@ -65,22 +45,6 @@ public static byte[] randomBytes(int length) { return result; } - private static AccountCapsule createAccount() { - com.google.protobuf.ByteString accountName = - com.google.protobuf.ByteString.copyFrom(randomBytes(16)); - com.google.protobuf.ByteString address = - ByteString.copyFrom(randomBytes(32)); - Protocol.AccountType accountType = Protocol.AccountType.forNumber(1); - AccountCapsule accountCapsule = new AccountCapsule(accountName, address, accountType); - accountCapsule.addAssetV2(ByteArray.fromString(String.valueOf(1)), 1000L); - Protocol.Account build = accountCapsule.getInstance().toBuilder() - .addAllFrozenSupply(getFrozenList()) - .build(); - accountCapsule.setInstance(build); - - return accountCapsule; - } - private static AccountCapsule createAccount2() { AccountAssetStore accountAssetStore = dbManager.getAccountAssetStore(); com.google.protobuf.ByteString accountName = @@ -88,32 +52,9 @@ private static AccountCapsule createAccount2() { com.google.protobuf.ByteString address = ByteString.copyFrom(randomBytes(32)); Protocol.AccountType accountType = Protocol.AccountType.forNumber(1); AccountCapsule accountCapsule = new AccountCapsule(accountName, address, accountType); - Protocol.AccountAsset accountAsset = - Protocol.AccountAsset.newBuilder() - .setAddress(accountCapsule.getInstance().getAddress()) - .setAssetIssuedID(accountCapsule.getAssetIssuedID()) - .setAssetIssuedName(accountCapsule.getAssetIssuedName()) - .build(); - accountAssetStore.put(accountCapsule.createDbKey(), - new AccountAssetCapsule( - accountAsset)); return accountCapsule; } - @Test - public void testGetAsset() { - AccountCapsule account = createAccount(); - Protocol.AccountAsset asset = AssetUtil.getAsset(account.getInstance()); - Assert.assertNotNull(asset); - } - - @Test - public void testImport() { - AccountCapsule account = createAccount2(); - Protocol.Account asset = AssetUtil.importAsset(account.getInstance()); - Assert.assertNotNull(asset); - } - @Test public void tetGetFrozen() { AccountCapsule account = createAccount2(); diff --git a/framework/src/test/java/org/tron/core/db/AccountAssetStoreTest.java b/framework/src/test/java/org/tron/core/db/AccountAssetStoreTest.java deleted file mode 100644 index 47c6723067d..00000000000 --- a/framework/src/test/java/org/tron/core/db/AccountAssetStoreTest.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.tron.core.db; - -import com.google.protobuf.ByteString; -import java.io.File; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; -import org.tron.core.Constant; -import org.tron.core.capsule.AccountAssetCapsule; -import org.tron.core.config.DefaultConfig; -import org.tron.core.config.args.Args; -import org.tron.core.store.AccountAssetStore; - - -public class AccountAssetStoreTest { - - private static final byte[] data = TransactionStoreTest.randomBytes(32); - private static String dbPath = "output_AccountAssetStore_test"; - private static String dbDirectory = "db_AccountAssetStore_test"; - private static String indexDirectory = "index_AccountAssetStore_test"; - private static TronApplicationContext context; - private static AccountAssetStore accountAssetStore; - private static byte[] address = TransactionStoreTest.randomBytes(32); - - static { - Args.setParam( - new String[]{ - "--output-directory", dbPath, - "--storage-db-directory", dbDirectory, - "--storage-index-directory", indexDirectory - }, - Constant.TEST_CONF - ); - context = new TronApplicationContext(DefaultConfig.class); - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } - - @BeforeClass - public static void init() { - accountAssetStore = context.getBean(AccountAssetStore.class); - AccountAssetCapsule accountCapsule = new AccountAssetCapsule( - ByteString.copyFrom(address)); - accountAssetStore.put(data, accountCapsule); - } - - @Test - public void get() { - Assert.assertEquals(ByteArray.toHexString(address), - ByteArray.toHexString(accountAssetStore.get(data) - .getInstance().getAddress().toByteArray())); - Assert.assertTrue(accountAssetStore.has(data)); - } - -} diff --git a/framework/src/test/java/org/tron/core/db/AccountStoreTest.java b/framework/src/test/java/org/tron/core/db/AccountStoreTest.java index a64b71f411e..b4b8a6cd84c 100755 --- a/framework/src/test/java/org/tron/core/db/AccountStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/AccountStoreTest.java @@ -1,7 +1,11 @@ package org.tron.core.db; +import static org.junit.Assert.assertEquals; + import com.google.protobuf.ByteString; import java.io.File; +import java.util.HashMap; +import java.util.Map; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -9,11 +13,16 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; +import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; +import org.tron.core.db2.ISession; +import org.tron.core.store.AccountAssetStore; import org.tron.core.store.AccountStore; +import org.tron.core.store.AssetIssueStore; +import org.tron.core.store.DynamicPropertiesStore; import org.tron.protos.Protocol.AccountType; public class AccountStoreTest { @@ -24,6 +33,11 @@ public class AccountStoreTest { private static String indexDirectory = "index_AccountStore_test"; private static TronApplicationContext context; private static AccountStore accountStore; + private static AccountAssetStore accountAssetStore; + private static Manager manager; + private static DynamicPropertiesStore dynamicPropertiesStore; + private static AssetIssueStore assetIssueStore; + private static ChainBaseManager chainBaseManager; private static byte[] address = TransactionStoreTest.randomBytes(32); private static byte[] accountName = TransactionStoreTest.randomBytes(32); @@ -49,9 +63,16 @@ public static void destroy() { @BeforeClass public static void init() { accountStore = context.getBean(AccountStore.class); + accountAssetStore = context.getBean(AccountAssetStore.class); + dynamicPropertiesStore = context.getBean(DynamicPropertiesStore.class); + manager = context.getBean(Manager.class); + chainBaseManager = context.getBean(ChainBaseManager.class); + assetIssueStore = chainBaseManager.getAssetIssueStore(); + dynamicPropertiesStore.saveAllowBlackHoleOptimization(1); AccountCapsule accountCapsule = new AccountCapsule(ByteString.copyFrom(address), ByteString.copyFrom(accountName), AccountType.forNumber(1)); + accountStore.put(data, accountCapsule); } @@ -76,4 +97,107 @@ public void put() { AccountType.forNumber(1)); accountStore.put(data, accountCapsule); } + + @Test + public void assetTest() { + dynamicPropertiesStore.setAllowAccountAssetOptimization(1); + dynamicPropertiesStore.saveAllowSameTokenName(1); + AccountCapsule accountCapsule = new AccountCapsule(ByteString.copyFrom(address), + ByteString.copyFrom(accountName), + AccountType.forNumber(1)); + + accountCapsule.addAsset("100".getBytes(), 1); + accountCapsule.addAssetAmountV2("100".getBytes(), 1, + dynamicPropertiesStore, assetIssueStore); + accountCapsule.addAssetAmountV2("200".getBytes(), 1, + dynamicPropertiesStore, assetIssueStore); + accountCapsule = saveAccount(accountCapsule); + assertEquals(0, accountCapsule.getAssetMap().size()); + assertEquals(1, accountCapsule.getAssetV2("100")); + assertEquals(1, accountCapsule.getAssetV2("200")); + assertEquals(2, accountCapsule.getAssetMapV2().size()); + assertEquals(0, accountCapsule.getAssetV2("300")); + + accountCapsule.clearAsset(); + accountCapsule.reduceAssetAmountV2("100".getBytes(), 1, + dynamicPropertiesStore, assetIssueStore); + accountCapsule = saveAccount(accountCapsule); + assertEquals(1, accountCapsule.getAssetMapV2().size()); + assertEquals(0, accountCapsule.getAssetV2("100")); + assertEquals(1, accountCapsule.getAssetV2("200")); + + accountCapsule.clearAsset(); + accountStore.delete(accountCapsule.createDbKey()); + accountCapsule = saveAccount(accountCapsule); + assertEquals(0, accountCapsule.getAssetMapV2().size()); + + Map map = new HashMap<>(); + map.put("100", 100L); + map.put("200", 100L); + accountCapsule.addAssetMapV2(map); + accountCapsule = saveAccount(accountCapsule); + assertEquals(100, accountCapsule.getAssetV2("100")); + assertEquals(100, accountCapsule.getAssetV2("200")); + + accountCapsule.clearAsset(); + Map assets = accountCapsule.getAssetV2MapForTest(); + assertEquals(2, assets.size()); + assertEquals(100, (long)assets.get("100")); + assertEquals(100, (long)assets.get("200")); + + accountCapsule.clearAsset(); + try (ISession tmpSession = manager.getRevokingStore().buildSession()) { + accountCapsule.addAssetAmountV2("100".getBytes(), 1, + dynamicPropertiesStore, assetIssueStore); + accountCapsule.reduceAssetAmountV2("200".getBytes(), 1, + dynamicPropertiesStore, assetIssueStore); + accountCapsule = saveAccount(accountCapsule); + tmpSession.commit(); + } + assertEquals(101, accountCapsule.getAssetV2("100")); + assertEquals(99, accountCapsule.getAssetV2("200")); + + try (ISession tmpSession = manager.getRevokingStore().buildSession()) { + tmpSession.commit(); + } + + accountCapsule.clearAsset(); + try (ISession tmpSession = manager.getRevokingStore().buildSession()) { + map = new HashMap<>(); + map.put("200", 10L); + map.put("300", 10L); + accountCapsule.addAssetMapV2(map); + accountCapsule = saveAccount(accountCapsule); + tmpSession.commit(); + } + assets = accountCapsule.getAssetV2MapForTest(); + assertEquals(3, assets.size()); + assertEquals(101, (long)assets.get("100")); + assertEquals(10, (long)assets.get("200")); + assertEquals(10, (long)assets.get("300")); + + accountCapsule.clearAsset(); + try (ISession tmpSession = manager.getRevokingStore().buildSession()) { + map = new HashMap<>(); + map.put("100", 10L); + map.put("200", 20L); + map.put("400", 10L); + accountCapsule.addAssetMapV2(map); + accountCapsule = saveAccount(accountCapsule); + tmpSession.commit(); + } + assets = accountCapsule.getAssetV2MapForTest(); + assertEquals(4, assets.size()); + assertEquals(10, (long)assets.get("100")); + assertEquals(20, (long)assets.get("200")); + assertEquals(10, (long)assets.get("300")); + assertEquals(10, (long)assets.get("400")); + } + + private AccountCapsule saveAccount(AccountCapsule accountCapsule) { + accountStore.put(accountCapsule.createDbKey(), accountCapsule); + accountCapsule = accountStore.get(accountCapsule.createDbKey()); + return accountCapsule; + } + } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index 47e506a808f..3bba1564348 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -342,8 +342,8 @@ public void adjustAssetBalanceV2Test() { chainManager.getAccountStore(), chainManager.getAssetIssueStore(), chainManager.getDynamicPropertiesStore()); AccountCapsule copyAccount = chainManager.getAccountStore().get(ownerAddress); - Assert.assertEquals(copyAccount.getAssetMap().size(), 1); - copyAccount.getAssetMap().forEach((k, v) -> { + Assert.assertEquals(copyAccount.getAssetMapForTest().size(), 1); + copyAccount.getAssetMapForTest().forEach((k, v) -> { Assert.assertEquals(k, assetID); Assert.assertEquals(v.compareTo(10L), 0); }); diff --git a/framework/src/test/java/org/tron/core/db/api/AssetUpdateHelperTest.java b/framework/src/test/java/org/tron/core/db/api/AssetUpdateHelperTest.java index dcb899dde19..34ce5d7d6ec 100644 --- a/framework/src/test/java/org/tron/core/db/api/AssetUpdateHelperTest.java +++ b/framework/src/test/java/org/tron/core/db/api/AssetUpdateHelperTest.java @@ -141,9 +141,9 @@ public void test() { Assert.assertEquals( ByteString.copyFrom(ByteArray.fromString("1000001")), accountCapsule.getAssetIssuedID()); - Assert.assertEquals(1, accountCapsule.getAssetMapV2().size()); + Assert.assertEquals(1, accountCapsule.getAssetV2MapForTest().size()); - Assert.assertEquals(100L, accountCapsule.getAssetMapV2().get("1000001").longValue()); + Assert.assertEquals(100L, accountCapsule.getAssetV2MapForTest().get("1000001").longValue()); Assert.assertEquals(1, accountCapsule.getAllFreeAssetNetUsageV2().size()); diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index a4409923086..fb4530cd704 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -214,38 +214,6 @@ message Account { repeated Permission active_permission = 33; } -/* AccountAsset */ -message AccountAsset { - - /* frozen balance */ - message Frozen { - int64 frozen_balance = 1; // the frozen trx balance - int64 expire_time = 2; // the expire time - } - - // the create address - bytes address = 1; - - // the other asset owned by this account - map asset = 2; - - // the other asset owned by this account,key is assetId - map assetV2 = 3; - - bytes asset_issued_name = 4; - bytes asset_issued_ID = 5; - - map latest_asset_operation_time = 6; - map latest_asset_operation_timeV2 = 7; - - map free_asset_net_usage = 8; - map free_asset_net_usageV2 = 9; - - // frozen asset(for asset issuer) - repeated Frozen frozen_supply = 10; -} - - message Key { bytes address = 1; int64 weight = 2; From f00cc199f325f6a42f8430e7ab9a8ab091391a08 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 23 May 2022 09:21:34 +0800 Subject: [PATCH 0091/1197] perf(db): optimize 10 asset storage logic --- .../leveldb/LevelDbDataSourceImpl.java | 2 +- .../rocksdb/RocksDbDataSourceImpl.java | 2 +- .../tron/core/capsule/utils/AssetUtil.java | 3 +-- .../org/tron/core/db2/core/Chainbase.java | 4 +-- .../org/tron/core/db2/core/SnapshotRoot.java | 26 +++++++++++++++---- .../tron/core/store/AccountAssetStore.java | 4 +-- .../org/tron/core/store/AccountStore.java | 11 -------- .../org/tron/core/db/AccountStoreTest.java | 26 +++++++++---------- 8 files changed, 39 insertions(+), 39 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java index 8766d8a554b..048a96b2809 100644 --- a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java @@ -354,7 +354,7 @@ public Map prefixQuery(byte[] key) { Map result = new HashMap<>(); for (iterator.seek(key); iterator.hasNext(); iterator.next()) { Entry entry = iterator.peekNext(); - if (Bytes.indexOf(entry.getKey(), key) >= 0) { + if (Bytes.indexOf(entry.getKey(), key) == 0) { result.put(WrappedByteArray.of(entry.getKey()), entry.getValue()); } else { return result; diff --git a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java index 62990e50294..56033490a38 100644 --- a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java @@ -439,7 +439,7 @@ public Map prefixQuery(byte[] key) { try (RocksIterator iterator = getRocksIterator()) { Map result = new HashMap<>(); for (iterator.seek(key); iterator.isValid(); iterator.next()) { - if (Bytes.indexOf(iterator.key(), key) >= 0) { + if (Bytes.indexOf(iterator.key(), key) == 0) { result.put(WrappedByteArray.of(iterator.key()), iterator.value()); } else { return result; diff --git a/chainbase/src/main/java/org/tron/core/capsule/utils/AssetUtil.java b/chainbase/src/main/java/org/tron/core/capsule/utils/AssetUtil.java index 4b21571c7d1..fff204ebdf2 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/utils/AssetUtil.java +++ b/chainbase/src/main/java/org/tron/core/capsule/utils/AssetUtil.java @@ -61,8 +61,7 @@ public static void setDynamicPropertiesStore(DynamicPropertiesStore dynamicPrope } public static boolean isAllowAssetOptimization() { - return true; -// return dynamicPropertiesStore.supportAllowAccountAssetOptimization(); + return dynamicPropertiesStore.supportAllowAccountAssetOptimization(); } } \ No newline at end of file diff --git a/chainbase/src/main/java/org/tron/core/db2/core/Chainbase.java b/chainbase/src/main/java/org/tron/core/db2/core/Chainbase.java index 9872978484b..7d0783e0a76 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/Chainbase.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/Chainbase.java @@ -340,8 +340,6 @@ private Map getNext(Snapshot head, byte[] key, long limit) { .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } - - public Map prefixQuery(byte[] key) { Map resultSnapshot = prefixQuerySnapshot(key); Map resultDB = prefixQueryDB(key); @@ -367,7 +365,7 @@ private Map prefixQuerySnapshot(byte[] key) { while (iterator.hasNext()) { Map.Entry entry = iterator.next(); WrappedByteArray ks = WrappedByteArray.of(entry.getKey()); - if (Bytes.indexOf(entry.getKey(), key) >= 0 && !result.containsKey(ks)) { + if (Bytes.indexOf(entry.getKey(), key) == 0 && !result.containsKey(ks)) { result.put(ks, entry.getValue()); } } diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java index 1d399b09f5f..17d4c30b45e 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java @@ -2,13 +2,12 @@ import com.google.common.collect.Maps; import com.google.common.collect.Streams; +import com.google.common.primitives.Longs; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; - -import com.google.common.primitives.Longs; import lombok.Getter; import org.tron.core.ChainBaseManager; import org.tron.core.capsule.AccountCapsule; @@ -56,7 +55,7 @@ public void remove(byte[] key) { AccountAssetStore store = ChainBaseManager.getInstance().getAccountAssetStore(); byte[] vale = get(key); if (vale.length > 0) { - AccountCapsule item = new AccountCapsule(get(key)); + AccountCapsule item = new AccountCapsule(vale); item.getAssetMapV2().forEach((k, v) -> store.put(item, k.getBytes(), Longs.toByteArray(0))); } @@ -71,7 +70,11 @@ public void merge(Snapshot from) { .map(e -> Maps.immutableEntry(WrappedByteArray.of(e.getKey().getBytes()), WrappedByteArray.of(e.getValue().getBytes()))) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - ((Flusher) db).flush(batch); + if (isAccountDB && AssetUtil.isAllowAssetOptimization()) { + processAccount(batch); + } else { + ((Flusher) db).flush(batch); + } } public void merge(List snapshots) { @@ -83,8 +86,21 @@ public void merge(List snapshots) { WrappedByteArray.of(e.getValue().getBytes()))) .forEach(e -> batch.put(e.getKey(), e.getValue())); } + if (isAccountDB && AssetUtil.isAllowAssetOptimization()) { + processAccount(batch); + } else { + ((Flusher) db).flush(batch); + } + } - ((Flusher) db).flush(batch); + private void processAccount(Map batch) { + batch.forEach((k, v) -> { + if (v.getBytes() == null || v.getBytes().length == 0) { + remove(k.getBytes()); + } else { + put(k.getBytes(), v.getBytes()); + } + }); } @Override diff --git a/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java b/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java index fe5cb58c9c1..176398d6f26 100644 --- a/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java +++ b/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java @@ -2,7 +2,6 @@ import com.google.common.primitives.Bytes; import com.google.common.primitives.Longs; -import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -16,7 +15,6 @@ import java.util.HashMap; import java.util.Map; -@Slf4j(topic = "DB") @Component public class AccountAssetStore extends TronDatabase { @@ -56,7 +54,7 @@ public void put(AccountCapsule account, byte[] key, byte[] value) { public long getBalance(Protocol.Account account, byte[] key) { byte[] k = Bytes.concat(account.getAddress().toByteArray(), key); - byte[] value = getUnchecked(k); + byte[] value = get(k); if (ArrayUtils.isEmpty(value)) { return 0; } diff --git a/chainbase/src/main/java/org/tron/core/store/AccountStore.java b/chainbase/src/main/java/org/tron/core/store/AccountStore.java index 8b13ee47f6f..4d39049ee79 100644 --- a/chainbase/src/main/java/org/tron/core/store/AccountStore.java +++ b/chainbase/src/main/java/org/tron/core/store/AccountStore.java @@ -1,9 +1,7 @@ package org.tron.core.store; -import com.google.common.primitives.Longs; import com.google.protobuf.ByteString; import com.typesafe.config.ConfigObject; -import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -12,7 +10,6 @@ import org.tron.common.utils.Commons; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.utils.AssetUtil; import org.tron.core.db.TronStoreWithRevoking; import org.tron.core.db.accountstate.AccountStateCallBackUtils; import org.tron.protos.contract.BalanceContract.TransactionBalanceTrace; @@ -23,7 +20,6 @@ import java.util.Map; import java.util.OptionalLong; -@Slf4j(topic = "DB") @Component public class AccountStore extends TronStoreWithRevoking { @@ -38,9 +34,6 @@ public class AccountStore extends TronStoreWithRevoking { @Autowired private AccountTraceStore accountTraceStore; - @Autowired - private AccountAssetStore accountAssetStore; - @Autowired private DynamicPropertiesStore dynamicPropertiesStore; @@ -103,10 +96,6 @@ public void delete(byte[] key) { } } super.delete(key); - - if (AssetUtil.isAllowAssetOptimization()) { - accountAssetStore.delete(key); - } } /** diff --git a/framework/src/test/java/org/tron/core/db/AccountStoreTest.java b/framework/src/test/java/org/tron/core/db/AccountStoreTest.java index b4b8a6cd84c..0bc9785d3e2 100755 --- a/framework/src/test/java/org/tron/core/db/AccountStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/AccountStoreTest.java @@ -6,6 +6,7 @@ import java.io.File; import java.util.HashMap; import java.util.Map; + import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -100,12 +101,12 @@ public void put() { @Test public void assetTest() { + dynamicPropertiesStore.setAllowAccountAssetOptimization(1); dynamicPropertiesStore.saveAllowSameTokenName(1); AccountCapsule accountCapsule = new AccountCapsule(ByteString.copyFrom(address), ByteString.copyFrom(accountName), AccountType.forNumber(1)); - accountCapsule.addAsset("100".getBytes(), 1); accountCapsule.addAssetAmountV2("100".getBytes(), 1, dynamicPropertiesStore, assetIssueStore); @@ -161,12 +162,11 @@ public void assetTest() { tmpSession.commit(); } - accountCapsule.clearAsset(); try (ISession tmpSession = manager.getRevokingStore().buildSession()) { - map = new HashMap<>(); - map.put("200", 10L); - map.put("300", 10L); - accountCapsule.addAssetMapV2(map); + accountCapsule.reduceAssetAmountV2("200".getBytes(), 89, + dynamicPropertiesStore, assetIssueStore); + accountCapsule.addAssetAmountV2("300".getBytes(), 10, + dynamicPropertiesStore, assetIssueStore); accountCapsule = saveAccount(accountCapsule); tmpSession.commit(); } @@ -176,20 +176,20 @@ public void assetTest() { assertEquals(10, (long)assets.get("200")); assertEquals(10, (long)assets.get("300")); - accountCapsule.clearAsset(); try (ISession tmpSession = manager.getRevokingStore().buildSession()) { - map = new HashMap<>(); - map.put("100", 10L); - map.put("200", 20L); - map.put("400", 10L); - accountCapsule.addAssetMapV2(map); + accountCapsule.reduceAssetAmountV2("100".getBytes(), 91, + dynamicPropertiesStore, assetIssueStore); + accountCapsule.addAssetAmountV2("200".getBytes(), 0, + dynamicPropertiesStore, assetIssueStore); + accountCapsule.addAssetAmountV2("400".getBytes(), 10, + dynamicPropertiesStore, assetIssueStore); accountCapsule = saveAccount(accountCapsule); tmpSession.commit(); } assets = accountCapsule.getAssetV2MapForTest(); assertEquals(4, assets.size()); assertEquals(10, (long)assets.get("100")); - assertEquals(20, (long)assets.get("200")); + assertEquals(10, (long)assets.get("200")); assertEquals(10, (long)assets.get("300")); assertEquals(10, (long)assets.get("400")); } From ce7a8d10ee4e6e2116639f933a40a042e095c33e Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 23 May 2022 17:04:58 +0800 Subject: [PATCH 0092/1197] feat(db): rethrow db error for rocksdb. 1. rethrow db error for rocksdb when get,set,delete.Keep same with leveldb. --- .../tron/common/storage/rocksdb/RocksDbDataSourceImpl.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java index 56033490a38..a19184a4550 100644 --- a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java @@ -273,7 +273,7 @@ public void putData(byte[] key, byte[] value) { try { database.put(key, value); } catch (RocksDBException e) { - logger.error("RocksDBException:{}", e); + throw new RuntimeException(e); } finally { resetDbLock.readLock().unlock(); } @@ -288,11 +288,10 @@ public byte[] getData(byte[] key) { try { return database.get(key); } catch (RocksDBException e) { - logger.error("RocksDBException: {}", e); + throw new RuntimeException(e); } finally { resetDbLock.readLock().unlock(); } - return null; } @Override @@ -304,7 +303,7 @@ public void deleteData(byte[] key) { try { database.delete(key); } catch (RocksDBException e) { - logger.error("RocksDBException:{}", e); + throw new RuntimeException(e); } finally { resetDbLock.readLock().unlock(); } From 9956583b2c872780377c81ab35d3ebd85c781fc3 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 23 May 2022 21:59:33 +0800 Subject: [PATCH 0093/1197] perf(db): modify transfer all token logic --- actuator/src/main/java/org/tron/core/vm/utils/MUtil.java | 1 + 1 file changed, 1 insertion(+) diff --git a/actuator/src/main/java/org/tron/core/vm/utils/MUtil.java b/actuator/src/main/java/org/tron/core/vm/utils/MUtil.java index d0332b175d0..6d002c4db81 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/MUtil.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/MUtil.java @@ -26,6 +26,7 @@ public static void transferAllToken(Repository deposit, byte[] fromAddress, byte AccountCapsule fromAccountCap = deposit.getAccount(fromAddress); Protocol.Account.Builder fromBuilder = fromAccountCap.getInstance().toBuilder(); AccountCapsule toAccountCap = deposit.getAccount(toAddress); + toAccountCap.importAllAsset(); Protocol.Account.Builder toBuilder = toAccountCap.getInstance().toBuilder(); fromAccountCap.getAssetMapV2().forEach((tokenId, amount) -> { toBuilder.putAssetV2(tokenId, toBuilder.getAssetV2Map().getOrDefault(tokenId, 0L) + amount); From abc150be134904d50a6b0ef7c414e4fd2bf9e17e Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 24 May 2022 15:43:19 +0800 Subject: [PATCH 0094/1197] perf(db): modify asset split conditions --- .../java/org/tron/core/db2/core/SnapshotRoot.java | 15 ++++++++++----- .../tron/core/store/DynamicPropertiesStore.java | 13 +++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java index 56d60306a37..db1767a3319 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java @@ -11,11 +11,11 @@ import lombok.Getter; import org.tron.core.ChainBaseManager; import org.tron.core.capsule.AccountCapsule; -import org.tron.core.capsule.utils.AssetUtil; import org.tron.core.db2.common.DB; import org.tron.core.db2.common.Flusher; import org.tron.core.db2.common.WrappedByteArray; import org.tron.core.store.AccountAssetStore; +import org.tron.core.store.DynamicPropertiesStore; public class SnapshotRoot extends AbstractSnapshot { @@ -30,6 +30,11 @@ public SnapshotRoot(DB db) { isAccountDB = "account".equalsIgnoreCase(db.getDbName()); } + private boolean needOptAsset() { + DynamicPropertiesStore s = ChainBaseManager.getInstance().getDynamicPropertiesStore(); + return isAccountDB && s.getAllowAccountAssetOptimizationFromRoot() == 1; + } + @Override public byte[] get(byte[] key) { return db.get(key); @@ -37,7 +42,7 @@ public byte[] get(byte[] key) { @Override public void put(byte[] key, byte[] value) { - if (isAccountDB && AssetUtil.isAllowAssetOptimization()) { + if (needOptAsset()) { if (value == null || value.length == 0) { remove(key); return; @@ -55,7 +60,7 @@ public void put(byte[] key, byte[] value) { @Override public void remove(byte[] key) { - if (isAccountDB && AssetUtil.isAllowAssetOptimization()) { + if (needOptAsset()) { AccountAssetStore store = ChainBaseManager.getInstance().getAccountAssetStore(); byte[] value = get(key); if (value != null && value.length > 0) { @@ -74,7 +79,7 @@ public void merge(Snapshot from) { .map(e -> Maps.immutableEntry(WrappedByteArray.of(e.getKey().getBytes()), WrappedByteArray.of(e.getValue().getBytes()))) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - if (isAccountDB && AssetUtil.isAllowAssetOptimization()) { + if (needOptAsset()) { processAccount(batch); } else { ((Flusher) db).flush(batch); @@ -90,7 +95,7 @@ public void merge(List snapshots) { WrappedByteArray.of(e.getValue().getBytes()))) .forEach(e -> batch.put(e.getKey(), e.getValue())); } - if (isAccountDB && AssetUtil.isAllowAssetOptimization()) { + if (needOptAsset()) { processAccount(batch); } else { ((Flusher) db).flush(batch); diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 39392ec16b2..08215bb12eb 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -2366,6 +2366,19 @@ public long getNewRewardAlgorithmEffectiveCycle() { .orElse(Long.MAX_VALUE); } + public long getAllowAccountAssetOptimizationFromRoot() { + try { + return Optional.ofNullable(getFromRoot(ALLOW_ACCOUNT_ASSET_OPTIMIZATION)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException("not found ALLOW_ACCOUNT_ASSET_OPTIMIZATION")); + } catch (Exception e) { + logger.debug("{}", e.getMessage()); + return CommonParameter.getInstance().getAllowAccountAssetOptimization(); + } + } + // 1: enable public long getAllowAccountAssetOptimization() { return Optional.ofNullable(getUnchecked(ALLOW_ACCOUNT_ASSET_OPTIMIZATION)) From e086266e1fe0c79d0671b02a2418865406104496 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 24 May 2022 16:46:36 +0800 Subject: [PATCH 0095/1197] dependency: upgrade for security. 1. fastjson: 1.2.70 -> 1.2.83 2. enable SafeMode --- framework/build.gradle | 2 +- framework/src/main/java/org/tron/core/config/DefaultConfig.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/framework/build.gradle b/framework/build.gradle index 68f093c4d86..999dcc77d11 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -74,7 +74,7 @@ dependencies { // http compile 'org.eclipse.jetty:jetty-server:9.4.11.v20180605' compile 'org.eclipse.jetty:jetty-servlet:9.4.11.v20180605' - compile 'com.alibaba:fastjson:1.2.70' + compile 'com.alibaba:fastjson:1.2.83' compile group: 'org.apache.httpcomponents', name: 'httpasyncclient', version: '4.1.1' // end http diff --git a/framework/src/main/java/org/tron/core/config/DefaultConfig.java b/framework/src/main/java/org/tron/core/config/DefaultConfig.java index 2069c7b8215..12fdbdbeda2 100755 --- a/framework/src/main/java/org/tron/core/config/DefaultConfig.java +++ b/framework/src/main/java/org/tron/core/config/DefaultConfig.java @@ -1,5 +1,6 @@ package org.tron.core.config; +import com.alibaba.fastjson.parser.ParserConfig; import lombok.extern.slf4j.Slf4j; import org.rocksdb.RocksDB; import org.springframework.beans.factory.annotation.Autowired; @@ -28,6 +29,7 @@ public class DefaultConfig { static { RocksDB.loadLibrary(); + ParserConfig.getGlobalInstance().setSafeMode(true); } @Autowired From 875bda17ca0c631e2b30dfc362e3c08a153e4c05 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 24 May 2022 17:52:51 +0800 Subject: [PATCH 0096/1197] perf(db): modify chainBaseManager init logic --- chainbase/src/main/java/org/tron/core/ChainBaseManager.java | 2 +- .../src/main/java/org/tron/core/db2/core/SnapshotRoot.java | 5 ++--- framework/src/main/java/org/tron/core/db/Manager.java | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java index 592bfd558d9..a96a47e5fa3 100644 --- a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java +++ b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java @@ -72,7 +72,7 @@ public class ChainBaseManager { @Getter - private static ChainBaseManager chainBaseManager; + private static volatile ChainBaseManager chainBaseManager; // db store @Autowired diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java index db1767a3319..e3fec257fe4 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java @@ -15,7 +15,6 @@ import org.tron.core.db2.common.Flusher; import org.tron.core.db2.common.WrappedByteArray; import org.tron.core.store.AccountAssetStore; -import org.tron.core.store.DynamicPropertiesStore; public class SnapshotRoot extends AbstractSnapshot { @@ -31,8 +30,8 @@ public SnapshotRoot(DB db) { } private boolean needOptAsset() { - DynamicPropertiesStore s = ChainBaseManager.getInstance().getDynamicPropertiesStore(); - return isAccountDB && s.getAllowAccountAssetOptimizationFromRoot() == 1; + return isAccountDB && ChainBaseManager.getInstance().getDynamicPropertiesStore() + .getAllowAccountAssetOptimizationFromRoot() == 1; } @Override diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 48d1179c25b..aee01d83c17 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -422,7 +422,7 @@ public void stopFilterProcessThread() { @PostConstruct public void init() { - chainBaseManager.init(chainBaseManager); + ChainBaseManager.init(chainBaseManager); Message.setDynamicPropertiesStore(this.getDynamicPropertiesStore()); mortgageService .initStore(chainBaseManager.getWitnessStore(), chainBaseManager.getDelegationStore(), From 23b393ec3986764017eb5eaacb4cff6c97ad1e93 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 25 May 2022 21:36:03 +0800 Subject: [PATCH 0097/1197] perf(db): asset storage uses batch writes --- .../java/org/tron/core/db/TronDatabase.java | 7 ++++ .../org/tron/core/db2/core/SnapshotRoot.java | 32 +++++++------- .../tron/core/store/AccountAssetStore.java | 42 ++++++++++++++++--- .../org/tron/core/db/AccountStoreTest.java | 4 +- 4 files changed, 63 insertions(+), 22 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/db/TronDatabase.java b/chainbase/src/main/java/org/tron/core/db/TronDatabase.java index cd492d62b4a..f373fcd3df3 100644 --- a/chainbase/src/main/java/org/tron/core/db/TronDatabase.java +++ b/chainbase/src/main/java/org/tron/core/db/TronDatabase.java @@ -12,6 +12,7 @@ import org.iq80.leveldb.WriteOptions; import org.springframework.beans.factory.annotation.Autowired; import org.tron.common.parameter.CommonParameter; +import org.tron.common.storage.WriteOptionsWrapper; import org.tron.common.storage.leveldb.LevelDbDataSourceImpl; import org.tron.common.storage.metric.DbStatService; import org.tron.common.storage.rocksdb.RocksDbDataSourceImpl; @@ -31,6 +32,8 @@ public abstract class TronDatabase implements ITronChainBase { protected DbSourceInter dbSource; @Getter private String dbName; + private WriteOptionsWrapper writeOptions = WriteOptionsWrapper.getInstance() + .sync(CommonParameter.getInstance().getStorage().isDbSync()); @Autowired private DbStatService dbStatService; @@ -70,6 +73,10 @@ public DbSourceInter getDbSource() { return dbSource; } + public void updateByBatch(Map rows) { + this.dbSource.updateByBatch(rows, writeOptions); + } + /** * reset the database. */ diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java index e3fec257fe4..fe17cbd6274 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java @@ -1,14 +1,15 @@ package org.tron.core.db2.core; +import ch.qos.logback.core.encoder.ByteArrayUtil; import com.google.common.collect.Maps; import com.google.common.collect.Streams; -import com.google.common.primitives.Longs; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import lombok.Getter; +import org.tron.common.utils.ByteArray; import org.tron.core.ChainBaseManager; import org.tron.core.capsule.AccountCapsule; import org.tron.core.db2.common.DB; @@ -42,14 +43,12 @@ public byte[] get(byte[] key) { @Override public void put(byte[] key, byte[] value) { if (needOptAsset()) { - if (value == null || value.length == 0) { + if (ByteArray.isEmpty(value)) { remove(key); return; } - AccountAssetStore store = ChainBaseManager.getInstance().getAccountAssetStore(); AccountCapsule item = new AccountCapsule(value); - item.getInstance().getAssetV2Map().forEach((k, v) -> - store.put(item, k.getBytes(), Longs.toByteArray(v))); + ChainBaseManager.getInstance().getAccountAssetStore().putAccount(item.getInstance()); item.clearAsset(); db.put(key, item.getData()); } else { @@ -60,13 +59,7 @@ public void put(byte[] key, byte[] value) { @Override public void remove(byte[] key) { if (needOptAsset()) { - AccountAssetStore store = ChainBaseManager.getInstance().getAccountAssetStore(); - byte[] value = get(key); - if (value != null && value.length > 0) { - AccountCapsule item = new AccountCapsule(value); - item.getAssetMapV2().forEach((k, v) -> - store.put(item, k.getBytes(), Longs.toByteArray(0))); - } + ChainBaseManager.getInstance().getAccountAssetStore().deleteAccount(this, key); } db.remove(key); } @@ -102,13 +95,22 @@ public void merge(List snapshots) { } private void processAccount(Map batch) { + AccountAssetStore assetStore = ChainBaseManager.getInstance().getAccountAssetStore(); + Map accounts = new HashMap<>(); + Map assets = new HashMap<>(); batch.forEach((k, v) -> { - if (v.getBytes() == null || v.getBytes().length == 0) { - remove(k.getBytes()); + if (ByteArray.isEmpty(v.getBytes())) { + accounts.put(k, v); + assets.putAll(assetStore.getDeletedAssets(this, k.getBytes())); } else { - put(k.getBytes(), v.getBytes()); + AccountCapsule item = new AccountCapsule(v.getBytes()); + assets.putAll(assetStore.getAssets(item.getInstance())); + item.clearAsset(); + accounts.put(k, WrappedByteArray.of(item.getData())); } }); + ((Flusher) db).flush(accounts); + assetStore.updateByBatch(assets); } @Override diff --git a/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java b/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java index 176398d6f26..3474449667f 100644 --- a/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java +++ b/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java @@ -10,6 +10,7 @@ import org.tron.core.capsule.AccountCapsule; import org.tron.core.db.TronDatabase; import org.tron.core.db2.common.WrappedByteArray; +import org.tron.core.db2.core.SnapshotRoot; import org.tron.protos.Protocol; import java.util.HashMap; @@ -43,15 +44,44 @@ public boolean has(byte[] key) { return dbSource.getData(key) != null; } - public void put(AccountCapsule account, byte[] key, byte[] value) { - byte[] k = Bytes.concat(account.createDbKey(), key); - if (Longs.fromByteArray(value) == 0) { - delete(k); - } else { - put(k, value); + public void putAccount(Protocol.Account account) { + Map assets = getAssets(account); + if (!assets.isEmpty()) { + updateByBatch(assets); } } + public void deleteAccount(SnapshotRoot accountSnapshotRoot, byte[] key) { + Map assets = getDeletedAssets(accountSnapshotRoot, key); + if (!assets.isEmpty()) { + updateByBatch(assets); + } + } + + public Map getAssets(Protocol.Account account) { + Map assets = new HashMap<>(); + account.getAssetV2Map().forEach((k, v) -> { + byte[] key = Bytes.concat(account.getAddress().toByteArray(), k.getBytes()); + if (v == 0) { + assets.put(key, null); + } else { + assets.put(key, Longs.toByteArray(v)); + } + }); + return assets; + } + + public Map getDeletedAssets(SnapshotRoot accountSnapshotRoot, byte[] key) { + Map assets = new HashMap<>(); + byte[] value = accountSnapshotRoot.get(key); + if (value != null && value.length > 0) { + AccountCapsule item = new AccountCapsule(value); + new AccountCapsule(value).getAssetMapV2().keySet().forEach(assetKey -> + assets.put(Bytes.concat(item.createDbKey(), assetKey.getBytes()), null)); + } + return assets; + } + public long getBalance(Protocol.Account account, byte[] key) { byte[] k = Bytes.concat(account.getAddress().toByteArray(), key); byte[] value = get(k); diff --git a/framework/src/test/java/org/tron/core/db/AccountStoreTest.java b/framework/src/test/java/org/tron/core/db/AccountStoreTest.java index 0bc9785d3e2..a8c5cd2589e 100755 --- a/framework/src/test/java/org/tron/core/db/AccountStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/AccountStoreTest.java @@ -123,9 +123,11 @@ public void assetTest() { accountCapsule.reduceAssetAmountV2("100".getBytes(), 1, dynamicPropertiesStore, assetIssueStore); accountCapsule = saveAccount(accountCapsule); - assertEquals(1, accountCapsule.getAssetMapV2().size()); + assertEquals(2, accountCapsule.getAssetMapV2().size()); assertEquals(0, accountCapsule.getAssetV2("100")); assertEquals(1, accountCapsule.getAssetV2("200")); + assertEquals(0, accountCapsule.getAssetV2("300")); + assertEquals(3, accountCapsule.getAssetMapV2().size()); accountCapsule.clearAsset(); accountStore.delete(accountCapsule.createDbKey()); From 98030cd8e56ff473d14257fd031f8cf5e6e9f0c0 Mon Sep 17 00:00:00 2001 From: liukai Date: Wed, 25 May 2022 22:28:00 +0800 Subject: [PATCH 0098/1197] update a new version. version name:GreatVoyage-v4.4.5-2-g64396866d,version code:16685 --- framework/src/main/java/org/tron/program/Version.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 0f118134d97..ce2a81b71eb 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,9 +2,9 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.4.4-3-g5f6660e30"; - public static final String VERSION_CODE = "16681"; - private static final String VERSION = "4.4.5"; + public static final String VERSION_NAME = "GreatVoyage-v4.4.5-2-g64396866d"; + public static final String VERSION_CODE = "16685"; + private static final String VERSION = "4.4.6"; public static String getVersion() { return VERSION; From a320fc4134f10f6c32a1adad90198d9ebfc5c4ec Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 26 May 2022 11:31:56 +0800 Subject: [PATCH 0099/1197] feat: add new proposal 1. add proposal 66 --- .../java/org/tron/core/utils/ProposalUtil.java | 14 +++++++++++++- .../tron/core/store/DynamicPropertiesStore.java | 14 +++++++------- .../org/tron/core/consensus/ProposalService.java | 12 ++++++++---- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index f4220002f3a..d931feee056 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -549,6 +549,17 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case ALLOW_ASSET_OPTIMIZATION: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_5)) { + throw new ContractValidateException( + "Bad chain parameter id [ALLOW_ASSET_OPTIMIZATION]"); + } + if (value != 1) { + throw new ContractValidateException( + "This value[ALLOW_ASSET_OPTIMIZATION] is only allowed to be 1"); + } + break; + } default: break; } @@ -611,7 +622,8 @@ public enum ProposalType { // current value, value range FREE_NET_LIMIT(61), // 5000, [0, 100_000] TOTAL_NET_LIMIT(62), // 43_200_000_000L, [0, 1000_000_000_000L] ALLOW_TVM_LONDON(63), // 0, 1 - ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX(65); // 0, 1 + ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX(65), // 0, 1 + ALLOW_ASSET_OPTIMIZATION(66); // 0, 1 private long code; diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 08215bb12eb..46c2b0d3cd2 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -165,8 +165,8 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE = "NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE".getBytes(); //This value is only allowed to be 1 - private static final byte[] ALLOW_ACCOUNT_ASSET_OPTIMIZATION = - "ALLOW_ACCOUNT_ASSET_OPTIMIZATION".getBytes(); + private static final byte[] ALLOW_ASSET_OPTIMIZATION = + "ALLOW_ASSET_OPTIMIZATION".getBytes(); private static final byte[] ENERGY_PRICE_HISTORY = "ENERGY_PRICE_HISTORY".getBytes(); private static final byte[] ENERGY_PRICE_HISTORY_DONE = "ENERGY_PRICE_HISTORY_DONE".getBytes(); private static final byte[] SET_BLACKHOLE_ACCOUNT_PERMISSION = @@ -2368,11 +2368,11 @@ public long getNewRewardAlgorithmEffectiveCycle() { public long getAllowAccountAssetOptimizationFromRoot() { try { - return Optional.ofNullable(getFromRoot(ALLOW_ACCOUNT_ASSET_OPTIMIZATION)) + return Optional.ofNullable(getFromRoot(ALLOW_ASSET_OPTIMIZATION)) .map(BytesCapsule::getData) .map(ByteArray::toLong) .orElseThrow( - () -> new IllegalArgumentException("not found ALLOW_ACCOUNT_ASSET_OPTIMIZATION")); + () -> new IllegalArgumentException("not found ALLOW_ASSET_OPTIMIZATION")); } catch (Exception e) { logger.debug("{}", e.getMessage()); return CommonParameter.getInstance().getAllowAccountAssetOptimization(); @@ -2381,15 +2381,15 @@ public long getAllowAccountAssetOptimizationFromRoot() { // 1: enable public long getAllowAccountAssetOptimization() { - return Optional.ofNullable(getUnchecked(ALLOW_ACCOUNT_ASSET_OPTIMIZATION)) + return Optional.ofNullable(getUnchecked(ALLOW_ASSET_OPTIMIZATION)) .map(BytesCapsule::getData) .map(ByteArray::toLong) .orElseThrow( - () -> new IllegalArgumentException("not found ALLOW_ACCOUNT_ASSET_OPTIMIZATION")); + () -> new IllegalArgumentException("not found ALLOW_ASSET_OPTIMIZATION")); } public void setAllowAccountAssetOptimization(long value) { - this.put(ALLOW_ACCOUNT_ASSET_OPTIMIZATION, new BytesCapsule(ByteArray.fromLong(value))); + this.put(ALLOW_ASSET_OPTIMIZATION, new BytesCapsule(ByteArray.fromLong(value))); } public void saveEnergyPriceHistoryDone(long value) { diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 1803bb6811d..7c4f43c9973 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -267,15 +267,19 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveTotalNetLimit(entry.getValue()); break; } - case ALLOW_ACCOUNT_ASSET_OPTIMIZATION: { - manager.getDynamicPropertiesStore().setAllowAccountAssetOptimization(entry.getValue()); - break; - } +// case ALLOW_ACCOUNT_ASSET_OPTIMIZATION: { +// manager.getDynamicPropertiesStore().setAllowAccountAssetOptimization(entry.getValue()); +// break; +// } case ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX: { manager.getDynamicPropertiesStore().saveAllowHigherLimitForMaxCpuTimeOfOneTx( entry.getValue()); break; } + case ALLOW_ASSET_OPTIMIZATION: { + manager.getDynamicPropertiesStore().setAllowAccountAssetOptimization(entry.getValue()); + break; + } default: find = false; break; From a721a7131318bda7a9937a99ba29c98ead857554 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 26 May 2022 11:49:46 +0800 Subject: [PATCH 0100/1197] perf(db): optimize the getDeletedAssets function --- .../java/org/tron/core/db2/core/SnapshotRoot.java | 4 ++-- .../org/tron/core/store/AccountAssetStore.java | 15 ++++----------- .../java/org/tron/core/db/AccountStoreTest.java | 2 +- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java index fe17cbd6274..e7a10aa43b5 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java @@ -59,7 +59,7 @@ public void put(byte[] key, byte[] value) { @Override public void remove(byte[] key) { if (needOptAsset()) { - ChainBaseManager.getInstance().getAccountAssetStore().deleteAccount(this, key); + ChainBaseManager.getInstance().getAccountAssetStore().deleteAccount(key); } db.remove(key); } @@ -101,7 +101,7 @@ private void processAccount(Map batch) { batch.forEach((k, v) -> { if (ByteArray.isEmpty(v.getBytes())) { accounts.put(k, v); - assets.putAll(assetStore.getDeletedAssets(this, k.getBytes())); + assets.putAll(assetStore.getDeletedAssets(k.getBytes())); } else { AccountCapsule item = new AccountCapsule(v.getBytes()); assets.putAll(assetStore.getAssets(item.getInstance())); diff --git a/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java b/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java index 3474449667f..72e750c09b7 100644 --- a/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java +++ b/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java @@ -7,10 +7,8 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.tron.common.utils.ByteArray; -import org.tron.core.capsule.AccountCapsule; import org.tron.core.db.TronDatabase; import org.tron.core.db2.common.WrappedByteArray; -import org.tron.core.db2.core.SnapshotRoot; import org.tron.protos.Protocol; import java.util.HashMap; @@ -51,8 +49,8 @@ public void putAccount(Protocol.Account account) { } } - public void deleteAccount(SnapshotRoot accountSnapshotRoot, byte[] key) { - Map assets = getDeletedAssets(accountSnapshotRoot, key); + public void deleteAccount(byte[] key) { + Map assets = getDeletedAssets(key); if (!assets.isEmpty()) { updateByBatch(assets); } @@ -71,14 +69,9 @@ public Map getAssets(Protocol.Account account) { return assets; } - public Map getDeletedAssets(SnapshotRoot accountSnapshotRoot, byte[] key) { + public Map getDeletedAssets(byte[] key) { Map assets = new HashMap<>(); - byte[] value = accountSnapshotRoot.get(key); - if (value != null && value.length > 0) { - AccountCapsule item = new AccountCapsule(value); - new AccountCapsule(value).getAssetMapV2().keySet().forEach(assetKey -> - assets.put(Bytes.concat(item.createDbKey(), assetKey.getBytes()), null)); - } + prefixQuery(key).forEach((k, v) -> assets.put(k.getBytes(), null)); return assets; } diff --git a/framework/src/test/java/org/tron/core/db/AccountStoreTest.java b/framework/src/test/java/org/tron/core/db/AccountStoreTest.java index a8c5cd2589e..22e1d70d301 100755 --- a/framework/src/test/java/org/tron/core/db/AccountStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/AccountStoreTest.java @@ -123,7 +123,7 @@ public void assetTest() { accountCapsule.reduceAssetAmountV2("100".getBytes(), 1, dynamicPropertiesStore, assetIssueStore); accountCapsule = saveAccount(accountCapsule); - assertEquals(2, accountCapsule.getAssetMapV2().size()); + assertEquals(1, accountCapsule.getAssetMapV2().size()); assertEquals(0, accountCapsule.getAssetV2("100")); assertEquals(1, accountCapsule.getAssetV2("200")); assertEquals(0, accountCapsule.getAssetV2("300")); From 3d88b9154b27642efc698d83ee5663b72d647db8 Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 26 May 2022 11:57:24 +0800 Subject: [PATCH 0101/1197] feat: add new proposal 1. add proposal 66 --- .../core/store/DynamicPropertiesStore.java | 35 ++++++++++++++++--- .../common/parameter/CommonParameter.java | 4 +++ .../src/main/java/org/tron/core/Wallet.java | 4 +++ .../tron/core/consensus/ProposalService.java | 10 +++--- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 46c2b0d3cd2..89edd822a7b 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -165,8 +165,13 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE = "NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE".getBytes(); //This value is only allowed to be 1 + private static final byte[] ALLOW_ACCOUNT_ASSET_OPTIMIZATION = + "ALLOW_ACCOUNT_ASSET_OPTIMIZATION".getBytes(); + private static final byte[] ALLOW_ASSET_OPTIMIZATION = - "ALLOW_ASSET_OPTIMIZATION".getBytes(); + "ALLOW_ASSET_OPTIMIZATION".getBytes(); + + private static final byte[] ENERGY_PRICE_HISTORY = "ENERGY_PRICE_HISTORY".getBytes(); private static final byte[] ENERGY_PRICE_HISTORY_DONE = "ENERGY_PRICE_HISTORY_DONE".getBytes(); private static final byte[] SET_BLACKHOLE_ACCOUNT_PERMISSION = @@ -791,6 +796,13 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { .getInstance().getAllowAccountAssetOptimization()); } + try { + this.getAllowAssetOptimization(); + } catch (IllegalArgumentException e) { + this.setAllowAssetOptimization(CommonParameter + .getInstance().getAllowAssetOptimization()); + } + try { this.getEnergyPriceHistoryDone(); } catch (IllegalArgumentException e) { @@ -2368,11 +2380,11 @@ public long getNewRewardAlgorithmEffectiveCycle() { public long getAllowAccountAssetOptimizationFromRoot() { try { - return Optional.ofNullable(getFromRoot(ALLOW_ASSET_OPTIMIZATION)) + return Optional.ofNullable(getFromRoot(ALLOW_ACCOUNT_ASSET_OPTIMIZATION)) .map(BytesCapsule::getData) .map(ByteArray::toLong) .orElseThrow( - () -> new IllegalArgumentException("not found ALLOW_ASSET_OPTIMIZATION")); + () -> new IllegalArgumentException("not found ALLOW_ACCOUNT_ASSET_OPTIMIZATION")); } catch (Exception e) { logger.debug("{}", e.getMessage()); return CommonParameter.getInstance().getAllowAccountAssetOptimization(); @@ -2381,14 +2393,27 @@ public long getAllowAccountAssetOptimizationFromRoot() { // 1: enable public long getAllowAccountAssetOptimization() { - return Optional.ofNullable(getUnchecked(ALLOW_ASSET_OPTIMIZATION)) + return Optional.ofNullable(getUnchecked(ALLOW_ACCOUNT_ASSET_OPTIMIZATION)) .map(BytesCapsule::getData) .map(ByteArray::toLong) .orElseThrow( - () -> new IllegalArgumentException("not found ALLOW_ASSET_OPTIMIZATION")); + () -> new IllegalArgumentException("not found ALLOW_ACCOUNT_ASSET_OPTIMIZATION")); } public void setAllowAccountAssetOptimization(long value) { + this.put(ALLOW_ACCOUNT_ASSET_OPTIMIZATION, new BytesCapsule(ByteArray.fromLong(value))); + } + + // 1: enable + public long getAllowAssetOptimization() { + return Optional.ofNullable(getUnchecked(ALLOW_ASSET_OPTIMIZATION)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException("not found ALLOW_ASSET_OPTIMIZATION")); + } + + public void setAllowAssetOptimization(long value) { this.put(ALLOW_ASSET_OPTIMIZATION, new BytesCapsule(ByteArray.fromLong(value))); } diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index adc9f36eee0..df4cf35f71c 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -530,6 +530,10 @@ public class CommonParameter { @Setter public long allowAccountAssetOptimization; + @Getter + @Setter + public long allowAssetOptimization; + @Getter @Setter public List disabledApiList; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 3282922714e..7015afe2405 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1092,6 +1092,10 @@ public Protocol.ChainParameters getChainParameters() { .setKey("getAllowHigherLimitForMaxCpuTimeOfOneTx") .setValue(dbManager.getDynamicPropertiesStore().getAllowHigherLimitForMaxCpuTimeOfOneTx()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getAllowAssetOptimization") + .setValue(dbManager.getDynamicPropertiesStore().getAllowAssetOptimization()) + .build()); return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 7c4f43c9973..21c3e70896f 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -267,17 +267,17 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveTotalNetLimit(entry.getValue()); break; } -// case ALLOW_ACCOUNT_ASSET_OPTIMIZATION: { -// manager.getDynamicPropertiesStore().setAllowAccountAssetOptimization(entry.getValue()); -// break; -// } + case ALLOW_ACCOUNT_ASSET_OPTIMIZATION: { + manager.getDynamicPropertiesStore().setAllowAccountAssetOptimization(entry.getValue()); + break; + } case ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX: { manager.getDynamicPropertiesStore().saveAllowHigherLimitForMaxCpuTimeOfOneTx( entry.getValue()); break; } case ALLOW_ASSET_OPTIMIZATION: { - manager.getDynamicPropertiesStore().setAllowAccountAssetOptimization(entry.getValue()); + manager.getDynamicPropertiesStore().setAllowAssetOptimization(entry.getValue()); break; } default: From 5e1e7d0da3ff9334a548be720d1d2db98f9aa65b Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 26 May 2022 12:10:01 +0800 Subject: [PATCH 0102/1197] feat: add new proposal 1. update ALLOW_ACCOUNT_ASSET_OPTIMIZATION to VERSION_4_3 --- actuator/src/main/java/org/tron/core/utils/ProposalUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index d931feee056..4f128884dfd 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -506,7 +506,7 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } case ALLOW_ACCOUNT_ASSET_OPTIMIZATION: { - if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_5)) { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_3)) { throw new ContractValidateException( "Bad chain parameter id [ALLOW_ACCOUNT_ASSET_OPTIMIZATION]"); } From 6c9ce154eaea1514edc33d0711568fded77d6e41 Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 26 May 2022 12:21:57 +0800 Subject: [PATCH 0103/1197] feat: add proposal restrictions 1. add Proposition 53 restrictions --- .../tron/core/store/DynamicPropertiesStore.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 89edd822a7b..8944d983a2b 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -790,17 +790,17 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { } try { - this.getAllowAccountAssetOptimization(); + this.getAllowAssetOptimization(); } catch (IllegalArgumentException e) { - this.setAllowAccountAssetOptimization(CommonParameter - .getInstance().getAllowAccountAssetOptimization()); + this.setAllowAssetOptimization(CommonParameter + .getInstance().getAllowAssetOptimization()); } try { - this.getAllowAssetOptimization(); + this.getAllowAccountAssetOptimization(); } catch (IllegalArgumentException e) { - this.setAllowAssetOptimization(CommonParameter - .getInstance().getAllowAssetOptimization()); + this.setAllowAccountAssetOptimization(CommonParameter + .getInstance().getAllowAccountAssetOptimization()); } try { @@ -2401,7 +2401,10 @@ public long getAllowAccountAssetOptimization() { } public void setAllowAccountAssetOptimization(long value) { - this.put(ALLOW_ACCOUNT_ASSET_OPTIMIZATION, new BytesCapsule(ByteArray.fromLong(value))); + long allowAssetOptimization = getAllowAssetOptimization(); + if (allowAssetOptimization != 1) { + this.put(ALLOW_ACCOUNT_ASSET_OPTIMIZATION, new BytesCapsule(ByteArray.fromLong(value))); + } } // 1: enable From f41f02c7e7de1c8202bb52256147986d3c4c02a4 Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 26 May 2022 12:25:29 +0800 Subject: [PATCH 0104/1197] feat: add proposal restrictions 1. add profile parameters --- common/src/main/java/org/tron/core/Constant.java | 1 + framework/src/main/java/org/tron/core/config/args/Args.java | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 679d27461c7..d0a557ccf44 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -304,6 +304,7 @@ public class Constant { public static final String OPEN_TRANSACTION_SORT = "node.openTransactionSort"; public static final String ALLOW_ACCOUNT_ASSET_OPTIMIZATION = "committee.allowAccountAssetOptimization"; + public static final String ALLOW_ASSET_OPTIMIZATION = "committee.allowAssetOptimization"; public static final String LOCAL_HOST = "127.0.0.1"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 4fb4beb98ac..f35b10c8034 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -202,6 +202,7 @@ public static void clearParam() { PARAMETER.openPrintLog = true; PARAMETER.openTransactionSort = false; PARAMETER.allowAccountAssetOptimization = 0; + PARAMETER.allowAssetOptimization = 0; PARAMETER.disabledApiList = Collections.emptyList(); PARAMETER.shutdownBlockTime = null; PARAMETER.shutdownBlockHeight = -1; @@ -858,6 +859,10 @@ public static void setParam(final String[] args, final String confFileName) { .hasPath(Constant.ALLOW_ACCOUNT_ASSET_OPTIMIZATION) ? config .getInt(Constant.ALLOW_ACCOUNT_ASSET_OPTIMIZATION) : 0; + PARAMETER.allowAssetOptimization = config + .hasPath(Constant.ALLOW_ASSET_OPTIMIZATION) ? config + .getInt(Constant.ALLOW_ASSET_OPTIMIZATION) : 0; + PARAMETER.disabledApiList = config.hasPath(Constant.NODE_DISABLED_API_LIST) ? config.getStringList(Constant.NODE_DISABLED_API_LIST) From ca01c2aab1bd5baf67190e6ee527bd594aa8c505 Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 26 May 2022 13:10:02 +0800 Subject: [PATCH 0105/1197] feat: modify of asset proposal parameters 1. modify the asset proposal parameter to ALLOW_ASSET_OPTIMIZATION --- .../main/java/org/tron/core/store/DynamicPropertiesStore.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 8944d983a2b..4255c66ddf0 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -2380,7 +2380,7 @@ public long getNewRewardAlgorithmEffectiveCycle() { public long getAllowAccountAssetOptimizationFromRoot() { try { - return Optional.ofNullable(getFromRoot(ALLOW_ACCOUNT_ASSET_OPTIMIZATION)) + return Optional.ofNullable(getFromRoot(ALLOW_ASSET_OPTIMIZATION)) .map(BytesCapsule::getData) .map(ByteArray::toLong) .orElseThrow( From 1c5d577ed133822b1d4da4b90e7c0c7cfe5b16f9 Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 26 May 2022 14:12:08 +0800 Subject: [PATCH 0106/1197] feat: modify asset comparison 1. modify asset comparison parameters tool class method --- .../src/main/java/org/tron/core/capsule/utils/AssetUtil.java | 4 ++-- .../main/java/org/tron/core/store/DynamicPropertiesStore.java | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/utils/AssetUtil.java b/chainbase/src/main/java/org/tron/core/capsule/utils/AssetUtil.java index fff204ebdf2..7638ac0bb69 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/utils/AssetUtil.java +++ b/chainbase/src/main/java/org/tron/core/capsule/utils/AssetUtil.java @@ -61,7 +61,7 @@ public static void setDynamicPropertiesStore(DynamicPropertiesStore dynamicPrope } public static boolean isAllowAssetOptimization() { - return dynamicPropertiesStore.supportAllowAccountAssetOptimization(); + return dynamicPropertiesStore.supportAllowAssetOptimization(); } -} \ No newline at end of file +} diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 4255c66ddf0..721eb80d14d 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -2291,6 +2291,10 @@ public boolean supportAllowAccountAssetOptimization() { return getAllowAccountAssetOptimization() == 1L; } + public boolean supportAllowAssetOptimization() { + return getAllowAssetOptimization() == 1L; + } + public void saveAllowNewResourceModel(long value) { this.put(ALLOW_NEW_RESOURCE_MODEL, new BytesCapsule(ByteArray.fromLong(value))); } From b38f22a78653c7aa4e7140758a4c99a9b565573b Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 26 May 2022 14:49:10 +0800 Subject: [PATCH 0107/1197] feat: modify test case 1. modify AccountStoreTest case --- .../src/test/java/org/tron/core/db/AccountStoreTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/test/java/org/tron/core/db/AccountStoreTest.java b/framework/src/test/java/org/tron/core/db/AccountStoreTest.java index 0bc9785d3e2..6795f8cb225 100755 --- a/framework/src/test/java/org/tron/core/db/AccountStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/AccountStoreTest.java @@ -102,7 +102,7 @@ public void put() { @Test public void assetTest() { - dynamicPropertiesStore.setAllowAccountAssetOptimization(1); + dynamicPropertiesStore.setAllowAssetOptimization(1); dynamicPropertiesStore.saveAllowSameTokenName(1); AccountCapsule accountCapsule = new AccountCapsule(ByteString.copyFrom(address), ByteString.copyFrom(accountName), @@ -200,4 +200,4 @@ private AccountCapsule saveAccount(AccountCapsule accountCapsule) { return accountCapsule; } -} \ No newline at end of file +} From e7d363ee3b55903aef162e3fe4fd45961afc35b0 Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 26 May 2022 17:37:59 +0800 Subject: [PATCH 0108/1197] feat: modify init param 1. modify ALLOW_ACCOUNT_ASSET_OPTIMIZATION init param --- .../java/org/tron/core/store/DynamicPropertiesStore.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 721eb80d14d..efdd59b8f3a 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -2405,10 +2405,7 @@ public long getAllowAccountAssetOptimization() { } public void setAllowAccountAssetOptimization(long value) { - long allowAssetOptimization = getAllowAssetOptimization(); - if (allowAssetOptimization != 1) { - this.put(ALLOW_ACCOUNT_ASSET_OPTIMIZATION, new BytesCapsule(ByteArray.fromLong(value))); - } + this.put(ALLOW_ACCOUNT_ASSET_OPTIMIZATION, new BytesCapsule(ByteArray.fromLong(value))); } // 1: enable From 052be9cfe0c180a4ad9124711ce06749c9a21af8 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Fri, 27 May 2022 11:41:03 +0800 Subject: [PATCH 0109/1197] perf(db): modify get asset net usage logic --- .../java/org/tron/core/db/BandwidthProcessor.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java b/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java index fcf57e31bb8..c826b8893a0 100644 --- a/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -5,6 +5,8 @@ import static org.tron.protos.Protocol.Transaction.Contract.ContractType.TransferAssetContract; import com.google.protobuf.ByteString; + +import java.util.HashMap; import java.util.List; import java.util.Map; import lombok.extern.slf4j.Slf4j; @@ -56,7 +58,14 @@ private void updateUsage(AccountCapsule accountCapsule, long now) { }); } Map assetMapV2 = accountCapsule.getAssetMapV2(); - assetMapV2.forEach((assetName, balance) -> { + Map map = new HashMap<>(); + map.putAll(assetMapV2); + accountCapsule.getAllFreeAssetNetUsageV2().forEach((k, v) -> { + if (!map.containsKey(k)) { + map.put(k, 0l); + } + }); + map.forEach((assetName, balance) -> { long oldFreeAssetNetUsage = accountCapsule.getFreeAssetNetUsageV2(assetName); long latestAssetOperationTime = accountCapsule.getLatestAssetOperationTimeV2(assetName); accountCapsule.putFreeAssetNetUsageV2(assetName, From aa792eb23ebfc8e7aba4efd982a301923dc6c5ea Mon Sep 17 00:00:00 2001 From: wubin01 Date: Fri, 27 May 2022 12:15:07 +0800 Subject: [PATCH 0110/1197] solve sonar problem --- .../src/main/java/org/tron/core/db/BandwidthProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java b/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java index c826b8893a0..b7aba36cc08 100644 --- a/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -62,7 +62,7 @@ private void updateUsage(AccountCapsule accountCapsule, long now) { map.putAll(assetMapV2); accountCapsule.getAllFreeAssetNetUsageV2().forEach((k, v) -> { if (!map.containsKey(k)) { - map.put(k, 0l); + map.put(k, 0L); } }); map.forEach((assetName, balance) -> { From 4e223a0d4c87d16a9cdbd179c952c3bd24772e04 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Fri, 27 May 2022 12:34:37 +0800 Subject: [PATCH 0111/1197] modify has asset logic --- .../src/main/java/org/tron/core/capsule/utils/AssetUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/utils/AssetUtil.java b/chainbase/src/main/java/org/tron/core/capsule/utils/AssetUtil.java index 7638ac0bb69..abdb8098643 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/utils/AssetUtil.java +++ b/chainbase/src/main/java/org/tron/core/capsule/utils/AssetUtil.java @@ -23,7 +23,7 @@ public static boolean hasAssetV2(Account account, byte[] key) { return false; } byte[] dbKey = Bytes.concat(account.getAddress().toByteArray(), key); - return accountAssetStore.getUnchecked(dbKey) != null; + return accountAssetStore.get(dbKey) != null; } public static Account importAsset(Account account, byte[] key) { From ba1734bc2a39c0a9ff9417775bbd9e38d3aa546e Mon Sep 17 00:00:00 2001 From: liukai Date: Fri, 27 May 2022 15:23:50 +0800 Subject: [PATCH 0112/1197] feat: optimize start.sh 1.add network options --- start.sh | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 68 insertions(+), 8 deletions(-) diff --git a/start.sh b/start.sh index 17c23012956..809a2e8f0b3 100644 --- a/start.sh +++ b/start.sh @@ -19,11 +19,21 @@ # Build FullNode config FULL_NODE_DIR="FullNode" -FULL_NODE_CONFIG="main_net_config.conf" +FULL_NODE_CONFIG_DIR="config" +# config file +FULL_NODE_CONFIG_MAIN_NET="main_net_config.conf" +FULL_NODE_CONFIG_TEST_NET="test_net_config.conf.conf" +FULL_NODE_CONFIG_PRIVATE_NET="private_net_config.conf" DEFAULT_FULL_NODE_CONFIG='config.conf' JAR_NAME="FullNode.jar" FULL_START_OPT='' + +# Github GITHUB_BRANCH='master' +GITHUB_CLONE_TYPE='HTTPS' +GITHUB_REPOSITORY='' +GITHUB_REPOSITORY_HTTPS_URL='https://github.com/tronprotocol/java-tron.git' +GITHUB_REPOSITORY_SSH_URL='git@github.com:tronprotocol/java-tron.git' # Shell option ALL_OPT_LENGTH=$# @@ -53,6 +63,12 @@ RELEASE_URL='https://github.com/tronprotocol/java-tron/releases' QUICK_START=false CLONE_BUILD=false +if [[ $GITHUB_CLONE_TYPE == 'HTTPS' ]]; then + GITHUB_REPOSITORY=$GITHUB_REPOSITORY_HTTPS_URL +else + GITHUB_REPOSITORY=$GITHUB_REPOSITORY_SSH_URL +fi + # Determine the Java command to use to start the JVM. if [ -z "$JAVA_HOME" ]; then javaExecutable="`which javac`" @@ -99,7 +115,7 @@ fi getLatestReleaseVersion() { - full_node_version=`git ls-remote --tags git@github.com:tronprotocol/java-tron.git |grep GreatVoyage- | awk -F '/' 'END{print $3}'` + full_node_version=`git ls-remote --tags $GITHUB_REPOSITORY |grep GreatVoyage- | awk -F '/' 'END{print $3}'` if [[ -n $full_node_version ]]; then echo $full_node_version else @@ -166,8 +182,8 @@ quickStart() { mkdirFullNode echo "info: check latest version: $full_node_version" echo 'info: download config' - download https://raw.githubusercontent.com/tronprotocol/tron-deployment/$GITHUB_BRANCH/$FULL_NODE_CONFIG $FULL_NODE_CONFIG - mv $FULL_NODE_CONFIG 'config.conf' + download https://raw.githubusercontent.com/tronprotocol/tron-deployment/$GITHUB_BRANCH/$FULL_NODE_CONFIG_MAIN_NET $FULL_NODE_CONFIG_MAIN_NET + mv $FULL_NODE_CONFIG_MAIN_NET 'config.conf' echo "info: download $full_node_version" download $RELEASE_URL/download/$full_node_version/$JAR_NAME $JAR_NAME @@ -180,7 +196,7 @@ quickStart() { cloneCode() { if type git >/dev/null 2>&1; then - git_clone=$(git clone -b $GITHUB_BRANCH git@github.com:tronprotocol/java-tron.git) + git_clone=$(git clone -b $GITHUB_BRANCH $GITHUB_REPOSITORY) if [[ git_clone == 0 ]]; then echo 'info: git clone java-tron success' fi @@ -353,6 +369,35 @@ rebuildManifest() { fi } +specifyConfig(){ + echo "info: specify the net: $1" + local netType=$1 + local configName; + if [[ "$netType" = 'test' ]]; then + configName=$FULL_NODE_CONFIG_TEST_NET + elif [[ "$netType" = 'private' ]]; then + configName=$FULL_NODE_CONFIG_PRIVATE_NET + else + echo "warn: no support config $nodeType" + exit + fi + + if [[ ! -d $FULL_NODE_CONFIG_DIR ]]; then + mkdir -p $FULL_NODE_CONFIG_DIR + fi + + if [[ -d $FULL_NODE_CONFIG_DIR/$configName ]]; then + DEFAULT_FULL_NODE_CONFIG=$FULL_NODE_CONFIG_DIR/$configName + break + fi + + if [[ ! -f $FULL_NODE_CONFIG_DIR/$configName ]]; then + download https://raw.githubusercontent.com/tronprotocol/tron-deployment/$GITHUB_BRANCH/$configName $configName + mv $configName $FULL_NODE_CONFIG_DIR/$configName + DEFAULT_FULL_NODE_CONFIG=$FULL_NODE_CONFIG_DIR/$configName + fi +} + checkSign() { echo 'info: verify signature' local latest_version=$(`echo getLatestReleaseVersion`) @@ -391,7 +436,6 @@ while [ -n "$1" ]; do case "$1" in -c) DEFAULT_FULL_NODE_CONFIG=$2 - FULL_START_OPT="$FULL_START_OPT $1 $2" shift 2 ;; -d) @@ -403,6 +447,22 @@ while [ -n "$1" ]; do JAR_NAME=$2 shift 2 ;; + -p) + FULL_START_OPT="$FULL_START_OPT $1 $2" + shift 2 + ;; + -w) + FULL_START_OPT="$FULL_START_OPT $1" + shift 1 + ;; + --witness) + FULL_START_OPT="$FULL_START_OPT $1" + shift 1 + ;; + --net) + specifyConfig $2 + shift 2 + ;; -m) REBUILD_MANIFEST_SIZE=$2 shift 2 @@ -487,8 +547,8 @@ while [ -n "$1" ]; do exit fi fi - echo "warn: option $1 does not exist" - exit + FULL_START_OPT="$FULL_START_OPT $@" + break ;; esac done From 77eaa222362165e40fe738444b24482f21d4304b Mon Sep 17 00:00:00 2001 From: liukai Date: Fri, 27 May 2022 15:56:09 +0800 Subject: [PATCH 0113/1197] feat: update asset 1. update exception log 2. update return method --- .../main/java/org/tron/core/store/DynamicPropertiesStore.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index efdd59b8f3a..e084f3ee6ed 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -2388,10 +2388,10 @@ public long getAllowAccountAssetOptimizationFromRoot() { .map(BytesCapsule::getData) .map(ByteArray::toLong) .orElseThrow( - () -> new IllegalArgumentException("not found ALLOW_ACCOUNT_ASSET_OPTIMIZATION")); + () -> new IllegalArgumentException("not found ALLOW_ASSET_OPTIMIZATION")); } catch (Exception e) { logger.debug("{}", e.getMessage()); - return CommonParameter.getInstance().getAllowAccountAssetOptimization(); + return CommonParameter.getInstance().getAllowAssetOptimization(); } } From d1358ba10459e14143ae0c6b7ea16494914b4ed6 Mon Sep 17 00:00:00 2001 From: liukai Date: Fri, 27 May 2022 17:05:39 +0800 Subject: [PATCH 0114/1197] feat: update shell.md 1. add network parameter descriptions --- shell.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/shell.md b/shell.md index df7d01e7cd9..0354adfddf8 100644 --- a/shell.md +++ b/shell.md @@ -44,6 +44,10 @@ The script is available in the java-tron project at [github](https://github.com/ sh start.sh -cb --run ``` +* Select a supported network,default network `main_net`, optional network `test_net`,`private` + ``` + sh start.sh --net test + ``` ## Options @@ -73,6 +77,9 @@ The script is available in the java-tron project at [github](https://github.com/ * `-mem` Specify the maximum memory of the `FullNode.jar` service in`MB`, jvm's startup maximum memory will be adjusted according to this parameter. + +* `--net` + Select test and private networks. ### build project @@ -226,4 +233,4 @@ sh start.sh --run -d /tmp/db/database -m 128 -b 64000 sh start.sh --release --run -d /tmp/db/database -m 128 -b 64000 ``` -For more design details, please refer to: [TIP298](https://github.com/tronprotocol/tips/issues/298) | [Leveldb Startup Optimization Plugins](https://github.com/tronprotocol/documentation-en/blob/master/docs/developers/archive-manifest.md) \ No newline at end of file +For more design details, please refer to: [TIP298](https://github.com/tronprotocol/tips/issues/298) | [Leveldb Startup Optimization Plugins](https://github.com/tronprotocol/documentation-en/blob/master/docs/developers/archive-manifest.md) From c5d6d98dc9e8a6a79f8ecacf91fdd2e3ffee2046 Mon Sep 17 00:00:00 2001 From: liukai Date: Fri, 27 May 2022 17:09:02 +0800 Subject: [PATCH 0115/1197] feat: update start.sh 1. add network parameter descriptions 2. add network parameter descriptions --- shell.md | 10 +++++++++- start.sh | 18 +++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/shell.md b/shell.md index df7d01e7cd9..2942343883f 100644 --- a/shell.md +++ b/shell.md @@ -44,6 +44,10 @@ The script is available in the java-tron project at [github](https://github.com/ sh start.sh -cb --run ``` +* Select a supported network,default network `main_net`, optional network `test_net`,`private` + ``` + sh start.sh --net test + ``` ## Options @@ -73,6 +77,9 @@ The script is available in the java-tron project at [github](https://github.com/ * `-mem` Specify the maximum memory of the `FullNode.jar` service in`MB`, jvm's startup maximum memory will be adjusted according to this parameter. + +* `--net` + Select test and private networks. ### build project @@ -226,4 +233,5 @@ sh start.sh --run -d /tmp/db/database -m 128 -b 64000 sh start.sh --release --run -d /tmp/db/database -m 128 -b 64000 ``` -For more design details, please refer to: [TIP298](https://github.com/tronprotocol/tips/issues/298) | [Leveldb Startup Optimization Plugins](https://github.com/tronprotocol/documentation-en/blob/master/docs/developers/archive-manifest.md) \ No newline at end of file +For more design details, please refer to: [TIP298](https://github.com/tronprotocol/tips/issues/298) | [Leveldb Startup Optimization Plugins](https://github.com/tronprotocol/documentation-en/blob/master/docs/developers/archive-manifest.md) + diff --git a/start.sh b/start.sh index 17c23012956..797860ea25b 100644 --- a/start.sh +++ b/start.sh @@ -391,7 +391,6 @@ while [ -n "$1" ]; do case "$1" in -c) DEFAULT_FULL_NODE_CONFIG=$2 - FULL_START_OPT="$FULL_START_OPT $1 $2" shift 2 ;; -d) @@ -403,6 +402,18 @@ while [ -n "$1" ]; do JAR_NAME=$2 shift 2 ;; + -p) + FULL_START_OPT="$FULL_START_OPT $1 $2" + shift 2 + ;; + -w) + FULL_START_OPT="$FULL_START_OPT $1" + shift 1 + ;; + --witness) + FULL_START_OPT="$FULL_START_OPT $1" + shift 1 + ;; -m) REBUILD_MANIFEST_SIZE=$2 shift 2 @@ -487,8 +498,8 @@ while [ -n "$1" ]; do exit fi fi - echo "warn: option $1 does not exist" - exit + FULL_START_OPT="$FULL_START_OPT $@" + break ;; esac done @@ -533,3 +544,4 @@ if [[ $RUN == true ]]; then exit fi +restart From 84027de8df51880aeafdd003bb6f37df84fc1bdf Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 19 May 2022 21:26:19 +0800 Subject: [PATCH 0116/1197] feature(block ): Optimize pack transaction into block. 1.retry exec transaction when pack block when the transaction is executed for the first time it does not time out, but probably time out due to gc. --- .../main/java/org/tron/core/db/Manager.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index ca1537577d0..028401b60d8 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1305,23 +1305,23 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block if (Objects.nonNull(blockCap)) { trace.setResult(); + if (trace.checkNeedRetry()) { + String txId = Hex.toHexString(trxCap.getTransactionId().getBytes()); + logger.info("Retry for tx id: {}", txId); + trace.init(blockCap, eventPluginLoaded); + trace.checkIsConstant(); + trace.exec(); + trace.setResult(); + logger.info("Retry result when push:{}, for tx id: {}, tx resultCode in receipt: {}", + blockCap.hasWitnessSignature(), txId, trace.getReceipt().getResult()); + } if (blockCap.hasWitnessSignature()) { - if (trace.checkNeedRetry()) { - String txId = Hex.toHexString(trxCap.getTransactionId().getBytes()); - logger.info("Retry for tx id: {}", txId); - trace.init(blockCap, eventPluginLoaded); - trace.checkIsConstant(); - trace.exec(); - trace.setResult(); - logger.info("Retry result for tx id: {}, tx resultCode in receipt: {}", - txId, trace.getReceipt().getResult()); - } trace.check(); } } trace.finalization(); - if (Objects.nonNull(blockCap) && getDynamicPropertiesStore().supportVM()) { + if (getDynamicPropertiesStore().supportVM()) { trxCap.setResult(trace.getTransactionContext()); } chainBaseManager.getTransactionStore().put(trxCap.getTransactionId().getBytes(), trxCap); From e7922f325ece7e1d1befe969a3f45fab25491ecc Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 30 May 2022 12:21:28 +0800 Subject: [PATCH 0117/1197] perf(net): optimize node comparison logic --- .../org/tron/common/overlay/discover/node/NodeHandler.java | 7 +++++++ .../org/tron/common/overlay/discover/node/NodeManager.java | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java b/framework/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java index 4fee405e6af..90ecff8cbab 100644 --- a/framework/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java @@ -22,6 +22,9 @@ import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; + +import lombok.Getter; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.tron.common.net.udp.handler.UdpEvent; import org.tron.common.net.udp.message.Message; @@ -49,6 +52,10 @@ public class NodeHandler { private volatile boolean waitForPong = false; private volatile boolean waitForNeighbors = false; private volatile long pingSent; + @Getter + @Setter + private int reputation; + public NodeHandler(Node node, NodeManager nodeManager) { this.node = node; diff --git a/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java b/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java index 5738057d23c..5efb94a4386 100644 --- a/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java +++ b/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java @@ -275,10 +275,11 @@ public List getNodes(Predicate predicate, int limit) { for (NodeHandler handler : nodeHandlerMap.values()) { if (handler.getNode().isConnectible(Args.getInstance().getNodeP2pVersion()) && predicate.test(handler)) { + handler.setReputation(handler.getNodeStatistics().getReputation()); filtered.add(handler); } } - filtered.sort(Comparator.comparingInt(handler -> -handler.getNodeStatistics().getReputation())); + filtered.sort(Comparator.comparingInt(handler -> -handler.getReputation())); return CollectionUtils.truncate(filtered, limit); } From 3dcd2bcc88ef9ff9943bd4038a941325ab6b139a Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Mon, 30 May 2022 16:47:55 +0800 Subject: [PATCH 0118/1197] feat: update netusage when get assetissue --- .../src/main/java/org/tron/core/Wallet.java | 59 ++++++++++++++++--- .../org/tron/core/db/BandwidthProcessor.java | 11 ++++ 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 3b6dbfeee7f..b21b165e750 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1097,12 +1097,18 @@ public Protocol.ChainParameters getChainParameters() { } public AssetIssueList getAssetIssueList() { + BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); AssetIssueList.Builder builder = AssetIssueList.newBuilder(); getAssetIssueStoreFinal(chainBaseManager.getDynamicPropertiesStore(), chainBaseManager.getAssetIssueStore(), chainBaseManager.getAssetIssueV2Store()).getAllAssetIssues() - .forEach(issueCapsule -> builder.addAssetIssue(issueCapsule.getInstance())); + .forEach( + issueCapsule -> { + processor.updateUsage(issueCapsule); + builder.addAssetIssue(issueCapsule.getInstance()); + } + ); return builder.build(); } @@ -1119,7 +1125,13 @@ public AssetIssueList getAssetIssueList(long offset, long limit) { return null; } - assetIssueList.forEach(issueCapsule -> builder.addAssetIssue(issueCapsule.getInstance())); + BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); + assetIssueList.forEach( + issueCapsule -> { + processor.updateUsage(issueCapsule); + builder.addAssetIssue(issueCapsule.getInstance()); + } + ); return builder.build(); } @@ -1133,10 +1145,16 @@ public AssetIssueList getAssetIssueByAccount(ByteString accountAddress) { chainBaseManager.getAssetIssueStore(), chainBaseManager.getAssetIssueV2Store()).getAllAssetIssues(); + BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); AssetIssueList.Builder builder = AssetIssueList.newBuilder(); assetIssueCapsuleList.stream() .filter(assetIssueCapsule -> assetIssueCapsule.getOwnerAddress().equals(accountAddress)) - .forEach(issueCapsule -> builder.addAssetIssue(issueCapsule.getInstance())); + .forEach( + issueCapsule -> { + processor.updateUsage(issueCapsule); + builder.addAssetIssue(issueCapsule.getInstance()); + } + ); return builder.build(); } @@ -1263,11 +1281,17 @@ public AssetIssueContract getAssetIssueByName(ByteString assetName) return null; } + BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); if (chainBaseManager.getDynamicPropertiesStore().getAllowSameTokenName() == 0) { // fetch from old DB, same as old logic ops AssetIssueCapsule assetIssueCapsule = chainBaseManager.getAssetIssueStore().get(assetName.toByteArray()); - return assetIssueCapsule != null ? assetIssueCapsule.getInstance() : null; + if (assetIssueCapsule != null) { + processor.updateUsage(assetIssueCapsule); + return assetIssueCapsule.getInstance(); + } else { + return null; + } } else { // get asset issue by name from new DB List assetIssueCapsuleList = @@ -1277,18 +1301,24 @@ public AssetIssueContract getAssetIssueByName(ByteString assetName) .stream() .filter(assetIssueCapsule -> assetIssueCapsule.getName().equals(assetName)) .forEach( - issueCapsule -> builder.addAssetIssue(issueCapsule.getInstance())); + issueCapsule -> { + processor.updateUsage(issueCapsule); + builder.addAssetIssue(issueCapsule.getInstance()); + } + ); // check count if (builder.getAssetIssueCount() > 1) { throw new NonUniqueObjectException( - "To get more than one asset, please use getAssetIssuebyid syntax"); + "To get more than one asset, please use getAssetIssueById syntax"); } else { // fetch from DB by assetName as id AssetIssueCapsule assetIssueCapsule = chainBaseManager.getAssetIssueV2Store().get(assetName.toByteArray()); if (assetIssueCapsule != null) { + processor.updateUsage(assetIssueCapsule); + // check already fetch if (builder.getAssetIssueCount() > 0 && builder.getAssetIssue(0).getId() @@ -1323,10 +1353,16 @@ public AssetIssueList getAssetIssueListByName(ByteString assetName) { chainBaseManager.getAssetIssueStore(), chainBaseManager.getAssetIssueV2Store()).getAllAssetIssues(); + BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); AssetIssueList.Builder builder = AssetIssueList.newBuilder(); assetIssueCapsuleList.stream() .filter(assetIssueCapsule -> assetIssueCapsule.getName().equals(assetName)) - .forEach(issueCapsule -> builder.addAssetIssue(issueCapsule.getInstance())); + .forEach( + issueCapsule -> { + processor.updateUsage(issueCapsule); + builder.addAssetIssue(issueCapsule.getInstance()); + } + ); return builder.build(); } @@ -1337,7 +1373,14 @@ public AssetIssueContract getAssetIssueById(String assetId) { } AssetIssueCapsule assetIssueCapsule = chainBaseManager.getAssetIssueV2Store() .get(ByteArray.fromString(assetId)); - return assetIssueCapsule != null ? assetIssueCapsule.getInstance() : null; + if (assetIssueCapsule != null) { + BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); + processor.updateUsage(assetIssueCapsule); + + return assetIssueCapsule.getInstance(); + } else { + return null; + } } public NumberMessage totalTransaction() { diff --git a/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java b/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java index fcf57e31bb8..0341e587474 100644 --- a/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -64,6 +64,17 @@ private void updateUsage(AccountCapsule accountCapsule, long now) { }); } + // update usage for asset issue + public void updateUsage(AssetIssueCapsule assetIssueCapsule) { + long now = chainBaseManager.getHeadSlot(); + + long publicFreeAssetNetUsage = assetIssueCapsule.getPublicFreeAssetNetUsage(); + long publicLatestFreeNetTime = assetIssueCapsule.getPublicLatestFreeNetTime(); + + assetIssueCapsule.setPublicFreeAssetNetUsage(increase(publicFreeAssetNetUsage, 0, + publicLatestFreeNetTime, now)); + } + @Override public void consume(TransactionCapsule trx, TransactionTrace trace) throws ContractValidateException, AccountResourceInsufficientException, From 68a5ba9585bfc62550d84e141f7392503becf204 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Mon, 30 May 2022 17:37:52 +0800 Subject: [PATCH 0119/1197] feat: add test for updateusage --- .../org/tron/core/db/BandwidthProcessor.java | 5 +- .../core/capsule/utils/AssetUtilTest.java | 51 ++++++++++++++++--- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java b/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java index 5c7870937a7..e39865e95ed 100644 --- a/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -5,7 +5,6 @@ import static org.tron.protos.Protocol.Transaction.Contract.ContractType.TransferAssetContract; import com.google.protobuf.ByteString; - import java.util.HashMap; import java.util.List; import java.util.Map; @@ -76,7 +75,10 @@ private void updateUsage(AccountCapsule accountCapsule, long now) { // update usage for asset issue public void updateUsage(AssetIssueCapsule assetIssueCapsule) { long now = chainBaseManager.getHeadSlot(); + updateUsage(assetIssueCapsule, now); + } + public void updateUsage(AssetIssueCapsule assetIssueCapsule, long now) { long publicFreeAssetNetUsage = assetIssueCapsule.getPublicFreeAssetNetUsage(); long publicLatestFreeNetTime = assetIssueCapsule.getPublicLatestFreeNetTime(); @@ -84,6 +86,7 @@ public void updateUsage(AssetIssueCapsule assetIssueCapsule) { publicLatestFreeNetTime, now)); } + @Override public void consume(TransactionCapsule trx, TransactionTrace trace) throws ContractValidateException, AccountResourceInsufficientException, diff --git a/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java b/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java index b649c270eae..b07061dc696 100644 --- a/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java +++ b/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java @@ -3,21 +3,28 @@ import com.google.common.collect.Lists; import com.google.protobuf.ByteString; import java.io.File; +import java.util.ArrayList; import java.util.List; import java.util.Random; import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Test; +import org.tron.api.GrpcAPI.AssetIssueList; import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; +import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; +import org.tron.core.db.BandwidthProcessor; import org.tron.core.db.Manager; import org.tron.core.store.AccountAssetStore; import org.tron.protos.Protocol; +import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; @Slf4j public class AssetUtilTest { @@ -25,11 +32,13 @@ public class AssetUtilTest { private static String dbPath = "output_AssetUtil_test"; private static Manager dbManager; private static TronApplicationContext context; + private static ChainBaseManager chainBaseManager; static { - Args.setParam(new String[]{"-d", dbPath, "-w"}, Constant.TEST_CONF); + Args.setParam(new String[] {"-d", dbPath, "-w"}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); dbManager = context.getBean(Manager.class); + chainBaseManager = context.getBean(ChainBaseManager.class); } @AfterClass @@ -48,7 +57,7 @@ public static byte[] randomBytes(int length) { private static AccountCapsule createAccount2() { AccountAssetStore accountAssetStore = dbManager.getAccountAssetStore(); com.google.protobuf.ByteString accountName = - com.google.protobuf.ByteString.copyFrom(randomBytes(16)); + com.google.protobuf.ByteString.copyFrom(randomBytes(16)); com.google.protobuf.ByteString address = ByteString.copyFrom(randomBytes(32)); Protocol.AccountType accountType = Protocol.AccountType.forNumber(1); AccountCapsule accountCapsule = new AccountCapsule(accountName, address, accountType); @@ -59,8 +68,8 @@ private static AccountCapsule createAccount2() { public void tetGetFrozen() { AccountCapsule account = createAccount2(); Protocol.Account build = account.getInstance().toBuilder() - .addAllFrozenSupply(getFrozenList()) - .build(); + .addAllFrozenSupply(getFrozenList()) + .build(); account.setInstance(build); Assert.assertNotNull(account.getFrozenSupplyList()); } @@ -69,12 +78,40 @@ private static List getFrozenList() { List frozenList = Lists.newArrayList(); for (int i = 0; i < 3; i++) { Protocol.Account.Frozen newFrozen = Protocol.Account.Frozen.newBuilder() - .setFrozenBalance(i * 1000 + 1) - .setExpireTime(1000) - .build(); + .setFrozenBalance(i * 1000 + 1) + .setExpireTime(1000) + .build(); frozenList.add(newFrozen); } return frozenList; } + + @Test + public void testUpdateUsage() { + List assetIssueCapsuleList = new ArrayList<>(); + + AssetIssueContract assetIssueContract = + AssetIssueContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString("111"))) + .setId(Long.toString(1)) + .build(); + AssetIssueCapsule capsule1 = new AssetIssueCapsule(assetIssueContract); + capsule1.setPublicFreeAssetNetUsage(60); + capsule1.setPublicLatestFreeNetTime(14400L); + + assetIssueCapsuleList.add(capsule1); + + BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); + AssetIssueList.Builder builder = AssetIssueList.newBuilder(); + assetIssueCapsuleList.forEach( + issueCapsule -> { + processor.updateUsage(issueCapsule, 28800); + builder.addAssetIssue(issueCapsule.getInstance()); + } + ); + + Assert.assertEquals(30L, + builder.build().getAssetIssue(0).getPublicFreeAssetNetUsage()); + } } From 6e3d81048ac60e693addaa81bae42154251dc1df Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Mon, 30 May 2022 18:18:56 +0800 Subject: [PATCH 0120/1197] typo --- .../src/main/java/org/tron/core/Wallet.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index db7627b3f04..95ff1642976 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1093,9 +1093,9 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getAllowHigherLimitForMaxCpuTimeOfOneTx()) .build()); builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() - .setKey("getAllowAssetOptimization") - .setValue(dbManager.getDynamicPropertiesStore().getAllowAssetOptimization()) - .build()); + .setKey("getAllowAssetOptimization") + .setValue(dbManager.getDynamicPropertiesStore().getAllowAssetOptimization()) + .build()); return builder.build(); } @@ -1111,8 +1111,7 @@ public AssetIssueList getAssetIssueList() { issueCapsule -> { processor.updateUsage(issueCapsule); builder.addAssetIssue(issueCapsule.getInstance()); - } - ); + }); return builder.build(); } @@ -1157,8 +1156,7 @@ public AssetIssueList getAssetIssueByAccount(ByteString accountAddress) { issueCapsule -> { processor.updateUsage(issueCapsule); builder.addAssetIssue(issueCapsule.getInstance()); - } - ); + }); return builder.build(); } @@ -1308,8 +1306,7 @@ public AssetIssueContract getAssetIssueByName(ByteString assetName) issueCapsule -> { processor.updateUsage(issueCapsule); builder.addAssetIssue(issueCapsule.getInstance()); - } - ); + }); // check count if (builder.getAssetIssueCount() > 1) { @@ -1365,8 +1362,7 @@ public AssetIssueList getAssetIssueListByName(ByteString assetName) { issueCapsule -> { processor.updateUsage(issueCapsule); builder.addAssetIssue(issueCapsule.getInstance()); - } - ); + }); return builder.build(); } From a8eae460544f498820a935d482caea03c0c1220f Mon Sep 17 00:00:00 2001 From: liukai Date: Mon, 30 May 2022 19:16:51 +0800 Subject: [PATCH 0121/1197] feat: modify init 1. modify the init sequence --- .../java/org/tron/common/overlay/server/HandshakeHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java index 981984a6f04..7bb195b2ca8 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java @@ -138,6 +138,8 @@ protected void sendHelloMsg(ChannelHandlerContext ctx, long time) { } private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { + channel.initNode(msg.getFrom().getId(), msg.getFrom().getPort()); + if (!msg.valid()) { logger.warn("Peer {} invalid hello message parameters, " + "GenesisBlockId: {}, SolidBlockId: {}, HeadBlockId: {}", @@ -149,8 +151,6 @@ private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { return; } - channel.initNode(msg.getFrom().getId(), msg.getFrom().getPort()); - channel.setAddress(msg.getHelloMessage().getAddress()); if (!fastForward.checkHelloMessage(msg, channel)) { From 4e55f4c710231e74d402d1fd01af4704ca707d2c Mon Sep 17 00:00:00 2001 From: liukai Date: Wed, 1 Jun 2022 15:22:21 +0800 Subject: [PATCH 0122/1197] feat: update the documentation 1. update network selection --- shell.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell.md b/shell.md index 0354adfddf8..e457be3c790 100644 --- a/shell.md +++ b/shell.md @@ -44,7 +44,7 @@ The script is available in the java-tron project at [github](https://github.com/ sh start.sh -cb --run ``` -* Select a supported network,default network `main_net`, optional network `test_net`,`private` +* Select a supported network,default network `main`, optional network `test`,`private` ``` sh start.sh --net test ``` From 8204bdaf1fa243d7becfc10655870dd239f0e217 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 1 Jun 2022 18:54:43 +0800 Subject: [PATCH 0123/1197] perf(db): optimize push block logic --- framework/src/main/java/org/tron/core/db/Manager.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index aee01d83c17..fec8a381d80 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1055,6 +1055,11 @@ public synchronized void pushBlock(final BlockCapsule block) DupTransactionException, TransactionExpirationException, BadNumberBlockException, BadBlockException, NonCommonBlockException, ReceiptCheckErrException, VMIllegalException, ZksnarkException, EventBloomException { + long headerNumber = getDynamicPropertiesStore().getLatestBlockHeaderNumber(); + if (block.getNum() <= headerNumber && khaosDb.getBlock(block.getBlockId()) != null) { + logger.info("Block {} is already exist.", block.getBlockId().getString()); + return; + } Metrics.histogramObserve(blockedTimer.get()); blockedTimer.remove(); final Histogram.Timer timer = Metrics.histogramStartTimer( @@ -1110,7 +1115,7 @@ public synchronized void pushBlock(final BlockCapsule block) return; } } else { - if (newBlock.getNum() <= getDynamicPropertiesStore().getLatestBlockHeaderNumber()) { + if (newBlock.getNum() <= headerNumber) { return; } From c254a5cc67567474c6c5a9129809976fb2da9c90 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 1 Jun 2022 19:46:43 +0800 Subject: [PATCH 0124/1197] perf(db): optimize push block logic --- framework/src/main/java/org/tron/core/db/Manager.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index fec8a381d80..d6b1ada162f 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1055,13 +1055,13 @@ public synchronized void pushBlock(final BlockCapsule block) DupTransactionException, TransactionExpirationException, BadNumberBlockException, BadBlockException, NonCommonBlockException, ReceiptCheckErrException, VMIllegalException, ZksnarkException, EventBloomException { + Metrics.histogramObserve(blockedTimer.get()); + blockedTimer.remove(); long headerNumber = getDynamicPropertiesStore().getLatestBlockHeaderNumber(); - if (block.getNum() <= headerNumber && khaosDb.getBlock(block.getBlockId()) != null) { + if (block.getNum() <= headerNumber && khaosDb.containBlockInMiniStore(block.getBlockId())) { logger.info("Block {} is already exist.", block.getBlockId().getString()); return; } - Metrics.histogramObserve(blockedTimer.get()); - blockedTimer.remove(); final Histogram.Timer timer = Metrics.histogramStartTimer( MetricKeys.Histogram.BLOCK_PUSH_LATENCY); long start = System.currentTimeMillis(); From 48104c7bf682960257ef95c3eb7ef699e123f9e9 Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 2 Jun 2022 12:18:00 +0800 Subject: [PATCH 0125/1197] feat: update protobuf doc 1. modify withdraw spelling error --- Tron protobuf protocol document.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tron protobuf protocol document.md b/Tron protobuf protocol document.md index 115b897c020..6a97805b22e 100644 --- a/Tron protobuf protocol document.md +++ b/Tron protobuf protocol document.md @@ -90,7 +90,7 @@ enum AccountType { `allowance`: the allowance of this account. - `latest_withdrew_time`: the latest operation time of this account. + `latest_withdraw_time`: the latest operation time of this account. `code`: reserved From e7e0bca439cad3e4a31bf1c2c71254f862d4e31e Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 6 Jun 2022 11:29:02 +0800 Subject: [PATCH 0126/1197] perf: set the block cache to be valid for one hour --- .../org/tron/core/net/TronNetDelegate.java | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index f0a75191c05..69c7c8af61c 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -2,11 +2,12 @@ import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import io.prometheus.client.Histogram; import java.util.Collection; import java.util.List; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; import javax.annotation.PostConstruct; import lombok.Getter; @@ -104,6 +105,10 @@ public class TronNetDelegate { @Setter private volatile boolean test = false; + private Cache freshBlockId = CacheBuilder.newBuilder() + .maximumSize(blockIdCacheSize).expireAfterWrite(1, TimeUnit.HOURS) + .recordStats().build(); + @PostConstruct public void init() { hitThread = new Thread(() -> { @@ -117,18 +122,6 @@ public void init() { hitThread.start(); } - - - private Queue freshBlockId = new ConcurrentLinkedQueue() { - @Override - public boolean offer(BlockId blockId) { - if (size() > blockIdCacheSize) { - super.poll(); - } - return super.offer(blockId); - } - }; - public Collection getActivePeer() { return syncPool.getActivePeers(); } @@ -241,7 +234,7 @@ public void processBlock(BlockCapsule block, boolean isSync) throws P2pException BlockId blockId = block.getBlockId(); synchronized (blockLock) { try { - if (!freshBlockId.contains(blockId)) { + if (freshBlockId.getIfPresent(blockId) == null) { if (block.getNum() <= getHeadBlockId().getNum()) { logger.warn("Receive a fork block {} witness {}, head {}", block.getBlockId().getString(), @@ -258,7 +251,7 @@ public void processBlock(BlockCapsule block, boolean isSync) throws P2pException MetricKeys.Histogram.BLOCK_PROCESS_LATENCY, String.valueOf(isSync)); dbManager.pushBlock(block); Metrics.histogramObserve(timer); - freshBlockId.add(blockId); + freshBlockId.put(blockId, System.currentTimeMillis()); logger.info("Success process block {}.", blockId.getString()); if (!backupServerStartFlag && System.currentTimeMillis() - block.getTimeStamp() < BLOCK_PRODUCED_INTERVAL) { @@ -344,4 +337,5 @@ public PbftSignCapsule getSRLPbftCommitData(long epoch) { public boolean allowPBFT() { return chainBaseManager.getDynamicPropertiesStore().allowPBFT(); } + } From 1ef8e4c27e252ad3c6135600a87692311306129a Mon Sep 17 00:00:00 2001 From: liukai Date: Mon, 6 Jun 2022 17:19:51 +0800 Subject: [PATCH 0127/1197] feat: add exception log 1. add spreadExecutor exception log --- .../src/main/java/org/tron/core/net/service/AdvService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/AdvService.java b/framework/src/main/java/org/tron/core/net/service/AdvService.java index 893ba622fdc..611e0f47a1f 100644 --- a/framework/src/main/java/org/tron/core/net/service/AdvService.java +++ b/framework/src/main/java/org/tron/core/net/service/AdvService.java @@ -41,7 +41,7 @@ @Slf4j(topic = "net") @Component public class AdvService { - + private final int MAX_INV_TO_FETCH_CACHE_SIZE = 100_000; private final int MAX_TRX_CACHE_SIZE = 50_000; private final int MAX_BLOCK_CACHE_SIZE = 10; @@ -84,7 +84,7 @@ public void init() { try { consumerInvToSpread(); } catch (Exception exception) { - logger.error("Spread thread error. {}", exception.getMessage()); + logger.error("Spread thread error. {}", exception.getMessage(), exception); } }, 100, 30, TimeUnit.MILLISECONDS); @@ -92,7 +92,7 @@ public void init() { try { consumerInvToFetch(); } catch (Exception exception) { - logger.error("Fetch thread error. {}", exception.getMessage()); + logger.error("Fetch thread error. {}", exception.getMessage(), exception); } }, 100, 30, TimeUnit.MILLISECONDS); } From 129f6ce652a6e128414475b332807d8c5eae5340 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 9 Jun 2022 15:10:16 +0800 Subject: [PATCH 0128/1197] Revert "Merge pull request #4354 from tronprotocol/fix/api_query_block" This reverts commit 69707c33203cc63d2bdde70d9e4c1f0a96d13dc2, reversing changes made to 7243cc7d3dcc129b0da9b0142956e94ade5edf40. --- .../core/services/http/GetNowBlockServlet.java | 4 +--- .../java/org/tron/core/services/http/Util.java | 16 ++-------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java b/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java index 87a3fbb98a3..5f4528c7b0d 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java @@ -1,6 +1,5 @@ package org.tron.core.services.http; -import com.google.common.base.Strings; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -31,8 +30,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) try { PostParams params = PostParams.getPostParams(request); GrpcAPI.EmptyMessage.Builder build = GrpcAPI.EmptyMessage.newBuilder(); - JsonFormat.merge(Strings.isNullOrEmpty(params.getParams()) ? "{}" : params.getParams(), - build, params.isVisible()); + JsonFormat.merge(params.getParams(), build, params.isVisible()); fillResponse(params.isVisible(), build.getType(), response); } catch (Exception e) { Util.processError(e, response); diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 66db8365099..35a56600a52 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -317,20 +317,8 @@ public static void checkBodySize(String body) throws Exception { public static boolean getVisible(final HttpServletRequest request) { boolean visible = false; - String v = request.getParameter(VISIBLE); - if (StringUtil.isBlank(v)) { - try { - String input = request.getReader().lines() - .collect(Collectors.joining(System.lineSeparator())); - Util.checkBodySize(input); - if (StringUtil.isNotBlank(input)) { - visible = getVisiblePost(input); - } - } catch (Exception e) { - logger.debug("GetVisibleError: {}", e.getMessage()); - } - } else { - visible = Boolean.parseBoolean(v); + if (StringUtil.isNotBlank(request.getParameter(VISIBLE))) { + visible = Boolean.valueOf(request.getParameter(VISIBLE)); } return visible; } From 533739b959116aaa0cf1bafc888b9b0f23f64a9a Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 9 Jun 2022 15:11:26 +0800 Subject: [PATCH 0129/1197] Revert "Merge pull request #4339 from halibobo1205/feature/api_query_block" This reverts commit aca69bb87a4b3cbc3d768b0ae0f741048aedf8f6, reversing changes made to 7e66c559441b54a16a1bd513aef5f733bd152844. --- .../src/main/java/org/tron/core/Wallet.java | 19 - .../org/tron/core/services/RpcApiService.java | 620 +++++++++--------- .../services/http/GetBlockByIdServlet.java | 12 +- .../http/GetBlockByLatestNumServlet.java | 11 +- .../http/GetBlockByLimitNextServlet.java | 14 +- .../services/http/GetBlockByNumServlet.java | 11 +- .../services/http/GetNowBlockServlet.java | 30 +- .../org/tron/core/services/http/Util.java | 7 - .../test/java/org/tron/core/WalletTest.java | 27 +- protocol/src/main/protos/api/api.proto | 9 - 10 files changed, 339 insertions(+), 421 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 95ff1642976..9150e4e0528 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -4018,24 +4018,5 @@ public boolean isMining() { public Chainbase.Cursor getCursor() { return chainBaseManager.getBlockStore().getRevokingDB().getCursor(); } - - public Block clearTrxForBlock(Block block, GrpcAPI.BlockType type) { - if (Objects.isNull(block) || block.getTransactionsList().isEmpty() - || type != GrpcAPI.BlockType.HEADER) { - return block; - } - return block.toBuilder().clearTransactions().build(); - } - - public BlockList clearTrxBlockList(BlockList blockList, GrpcAPI.BlockType type) { - if (Objects.isNull(blockList) || blockList.getBlockList().isEmpty() - || type != GrpcAPI.BlockType.HEADER) { - return blockList; - } - BlockList.Builder blockListBuilder = BlockList.newBuilder(); - blockList.getBlockList().forEach(block -> blockListBuilder.addBlock(clearTrxForBlock(block, - type))); - return blockListBuilder.build(); - } } diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 250eb46987d..9c7fe772679 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -180,7 +180,7 @@ public class RpcApiService implements Service { private static final String EXCEPTION_CAUGHT = "exception caught"; private static final long BLOCK_LIMIT_NUM = 100; private static final long TRANSACTION_LIMIT_NUM = 1000; - private final int port = Args.getInstance().getRpcPort(); + private int port = Args.getInstance().getRpcPort(); private Server apiServer; @Autowired private Manager dbManager; @@ -209,12 +209,12 @@ public class RpcApiService implements Service { private MetricsApiService metricsApiService; @Getter - private final DatabaseApi databaseApi = new DatabaseApi(); - private final WalletApi walletApi = new WalletApi(); + private DatabaseApi databaseApi = new DatabaseApi(); + private WalletApi walletApi = new WalletApi(); @Getter - private final WalletSolidityApi walletSolidityApi = new WalletSolidityApi(); + private WalletSolidityApi walletSolidityApi = new WalletSolidityApi(); @Getter - private final MonitorApi monitorApi = new MonitorApi(); + private MonitorApi monitorApi = new MonitorApi(); @Override public void init() { @@ -286,8 +286,7 @@ public void start() { private void callContract(TriggerSmartContract request, - StreamObserver responseObserver, - boolean isConstant) { + StreamObserver responseObserver, boolean isConstant) { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); try { @@ -325,8 +324,7 @@ private void callContract(TriggerSmartContract request, } private TransactionCapsule createTransactionCapsule(com.google.protobuf.Message message, - ContractType contractType) - throws ContractValidateException { + ContractType contractType) throws ContractValidateException { return wallet.createTransactionCapsule(message, contractType); } @@ -403,122 +401,13 @@ public void blockUntilShutdown() { } } - public void generateAddressCommon( - EmptyMessage request, - StreamObserver responseObserver) { - SignInterface cryptoEngine = SignUtils.getGeneratedRandomSign(Utils.getRandom(), - Args.getInstance().isECKeyCryptoEngine()); - byte[] priKey = cryptoEngine.getPrivateKey(); - byte[] address = cryptoEngine.getAddress(); - String addressStr = StringUtil.encode58Check(address); - String priKeyStr = Hex.encodeHexString(priKey); - AddressPrKeyPairMessage.Builder builder = AddressPrKeyPairMessage.newBuilder(); - builder.setAddress(addressStr); - builder.setPrivateKey(priKeyStr); - responseObserver.onNext(builder.build()); - responseObserver.onCompleted(); - } - - public void getRewardInfoCommon(BytesMessage request, - StreamObserver responseObserver) { - try { - long value = dbManager.getMortgageService().queryReward(request.getValue().toByteArray()); - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(value); - responseObserver.onNext(builder.build()); - } catch (Exception e) { - responseObserver.onError(e); - } - responseObserver.onCompleted(); - } - - public void getBurnTrxCommon(EmptyMessage request, - StreamObserver responseObserver) { - try { - long value = dbManager.getDynamicPropertiesStore().getBurnTrxAmount(); - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(value); - responseObserver.onNext(builder.build()); - } catch (Exception e) { - responseObserver.onError(e); - } - responseObserver.onCompleted(); - } - - public void getBrokerageInfoCommon(BytesMessage request, - StreamObserver responseObserver) { - try { - long cycle = dbManager.getDynamicPropertiesStore().getCurrentCycleNumber(); - long value = dbManager.getDelegationStore() - .getBrokerage(cycle, request.getValue().toByteArray()); - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(value); - responseObserver.onNext(builder.build()); - } catch (Exception e) { - responseObserver.onError(e); - } - responseObserver.onCompleted(); - } - - public void getTransactionCountByBlockNumCommon(NumberMessage request, - StreamObserver responseObserver) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - try { - Block block = chainBaseManager.getBlockByNum(request.getNum()).getInstance(); - builder.setNum(block.getTransactionsCount()); - } catch (StoreException e) { - logger.error(e.getMessage()); - builder.setNum(-1); - } - responseObserver.onNext(builder.build()); - responseObserver.onCompleted(); - } - - public void getTransactionFromPendingCommon(BytesMessage request, - StreamObserver responseObserver) { - try { - String txId = ByteArray.toHexString(request.getValue().toByteArray()); - TransactionCapsule transactionCapsule = dbManager.getTxFromPending(txId); - responseObserver.onNext(transactionCapsule == null ? null : transactionCapsule.getInstance()); - } catch (Exception e) { - responseObserver.onError(e); - } - responseObserver.onCompleted(); - } - - public void getTransactionListFromPendingCommon( - EmptyMessage request, - StreamObserver responseObserver) { - try { - TransactionIdList.Builder builder = TransactionIdList.newBuilder(); - builder.addAllTxId(dbManager.getTxListFromPending()); - responseObserver.onNext(builder.build()); - } catch (Exception e) { - responseObserver.onError(e); - } - responseObserver.onCompleted(); - } - - public void getPendingSizeCommon(EmptyMessage request, - StreamObserver responseObserver) { - try { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(dbManager.getPendingSize()); - responseObserver.onNext(builder.build()); - } catch (Exception e) { - responseObserver.onError(e); - } - responseObserver.onCompleted(); - } - /** * DatabaseApi. */ public class DatabaseApi extends DatabaseImplBase { @Override - public void getBlockReference( - org.tron.api.GrpcAPI.EmptyMessage request, + public void getBlockReference(org.tron.api.GrpcAPI.EmptyMessage request, io.grpc.stub.StreamObserver responseObserver) { long headBlockNum = dbManager.getDynamicPropertiesStore() .getLatestBlockHeaderNumber(); @@ -540,7 +429,7 @@ public void getNowBlock(EmptyMessage request, StreamObserver responseObse } catch (StoreException e) { logger.error(e.getMessage()); } - responseObserver.onNext(wallet.clearTrxForBlock(block, request.getType())); + responseObserver.onNext(block); responseObserver.onCompleted(); } @@ -552,13 +441,13 @@ public void getBlockByNum(NumberMessage request, StreamObserver responseO } catch (StoreException e) { logger.error(e.getMessage()); } - responseObserver.onNext(wallet.clearTrxForBlock(block, request.getType())); + responseObserver.onNext(block); responseObserver.onCompleted(); } @Override public void getDynamicProperties(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { DynamicProperties.Builder builder = DynamicProperties.newBuilder(); builder.setLastSolidityBlockNum( dbManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum()); @@ -605,21 +494,21 @@ public void listWitnesses(EmptyMessage request, StreamObserver resp @Override public void getAssetIssueList(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getAssetIssueList()); responseObserver.onCompleted(); } @Override public void getPaginatedAssetIssueList(PaginatedMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getAssetIssueList(request.getOffset(), request.getLimit())); responseObserver.onCompleted(); } @Override public void getAssetIssueByName(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString assetName = request.getValue(); if (assetName != null) { try { @@ -636,7 +525,7 @@ public void getAssetIssueByName(BytesMessage request, @Override public void getAssetIssueListByName(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString assetName = request.getValue(); if (assetName != null) { @@ -649,7 +538,7 @@ public void getAssetIssueListByName(BytesMessage request, @Override public void getAssetIssueById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString assetId = request.getValue(); if (assetId != null) { @@ -662,16 +551,14 @@ public void getAssetIssueById(BytesMessage request, @Override public void getNowBlock(EmptyMessage request, StreamObserver responseObserver) { - responseObserver.onNext(wallet.clearTrxForBlock(wallet.getNowBlock(), - request.getType())); + responseObserver.onNext(wallet.getNowBlock()); responseObserver.onCompleted(); } @Override public void getNowBlock2(EmptyMessage request, - StreamObserver responseObserver) { - responseObserver.onNext(block2Extention(wallet.clearTrxForBlock(wallet.getNowBlock(), - request.getType()))); + StreamObserver responseObserver) { + responseObserver.onNext(block2Extention(wallet.getNowBlock())); responseObserver.onCompleted(); } @@ -680,7 +567,7 @@ public void getBlockByNum(NumberMessage request, StreamObserver responseO long num = request.getNum(); if (num >= 0) { Block reply = wallet.getBlockByNum(num); - responseObserver.onNext(wallet.clearTrxForBlock(reply, request.getType())); + responseObserver.onNext(reply); } else { responseObserver.onNext(null); } @@ -689,12 +576,11 @@ public void getBlockByNum(NumberMessage request, StreamObserver responseO @Override public void getBlockByNum2(NumberMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long num = request.getNum(); if (num >= 0) { Block reply = wallet.getBlockByNum(num); - responseObserver.onNext(block2Extention(wallet.clearTrxForBlock(reply, - request.getType()))); + responseObserver.onNext(block2Extention(reply)); } else { responseObserver.onNext(null); } @@ -704,15 +590,14 @@ public void getBlockByNum2(NumberMessage request, @Override public void getDelegatedResource(DelegatedResourceMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver .onNext(wallet.getDelegatedResource(request.getFromAddress(), request.getToAddress())); responseObserver.onCompleted(); } @Override - public void getDelegatedResourceAccountIndex( - BytesMessage request, + public void getDelegatedResourceAccountIndex(BytesMessage request, StreamObserver responseObserver) { responseObserver .onNext(wallet.getDelegatedResourceAccountIndex(request.getValue())); @@ -721,7 +606,7 @@ public void getDelegatedResourceAccountIndex( @Override public void getExchangeById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString exchangeId = request.getValue(); if (Objects.nonNull(exchangeId)) { @@ -734,20 +619,20 @@ public void getExchangeById(BytesMessage request, @Override public void listExchanges(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getExchangeList()); responseObserver.onCompleted(); } @Override public void getTransactionCountByBlockNum(NumberMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { getTransactionCountByBlockNumCommon(request, responseObserver); } @Override public void getTransactionById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString id = request.getValue(); if (null != id) { Transaction reply = wallet.getTransactionById(id); @@ -761,7 +646,7 @@ public void getTransactionById(BytesMessage request, @Override public void getTransactionInfoById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString id = request.getValue(); if (null != id) { TransactionInfo reply = wallet.getTransactionInfoById(id); @@ -775,19 +660,19 @@ public void getTransactionInfoById(BytesMessage request, @Override public void generateAddress(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { generateAddressCommon(request, responseObserver); } @Override public void getRewardInfo(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { getRewardInfoCommon(request, responseObserver); } @Override public void getBrokerageInfo(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { getBrokerageInfoCommon(request, responseObserver); } @@ -797,8 +682,7 @@ public void getBurnTrx(EmptyMessage request, StreamObserver respo } @Override - public void getMerkleTreeVoucherInfo( - OutputPointInfo request, + public void getMerkleTreeVoucherInfo(OutputPointInfo request, StreamObserver responseObserver) { try { @@ -815,7 +699,7 @@ public void getMerkleTreeVoucherInfo( @Override public void scanNoteByIvk(GrpcAPI.IvkDecryptParameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartBlockIndex(); long endNum = request.getEndBlockIndex(); @@ -833,7 +717,7 @@ public void scanNoteByIvk(GrpcAPI.IvkDecryptParameters request, @Override public void scanAndMarkNoteByIvk(GrpcAPI.IvkDecryptAndMarkParameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartBlockIndex(); long endNum = request.getEndBlockIndex(); @@ -854,7 +738,7 @@ public void scanAndMarkNoteByIvk(GrpcAPI.IvkDecryptAndMarkParameters request, @Override public void scanNoteByOvk(GrpcAPI.OvkDecryptParameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartBlockIndex(); long endNum = request.getEndBlockIndex(); try { @@ -883,7 +767,7 @@ public void isSpend(NoteParameters request, StreamObserver response @Override public void scanShieldedTRC20NotesByIvk(IvkDecryptTRC20Parameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartBlockIndex(); long endNum = request.getEndBlockIndex(); byte[] contractAddress = request.getShieldedTRC20ContractAddress().toByteArray(); @@ -906,7 +790,7 @@ public void scanShieldedTRC20NotesByIvk(IvkDecryptTRC20Parameters request, @Override public void scanShieldedTRC20NotesByOvk(OvkDecryptTRC20Parameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartBlockIndex(); long endNum = request.getEndBlockIndex(); byte[] contractAddress = request.getShieldedTRC20ContractAddress().toByteArray(); @@ -924,8 +808,7 @@ public void scanShieldedTRC20NotesByOvk(OvkDecryptTRC20Parameters request, } @Override - public void isShieldedTRC20ContractNoteSpent( - NfTRC20Parameters request, + public void isShieldedTRC20ContractNoteSpent(NfTRC20Parameters request, StreamObserver responseObserver) { try { checkSupportShieldedTRC20Transaction(); @@ -938,7 +821,7 @@ public void isShieldedTRC20ContractNoteSpent( @Override public void getMarketOrderByAccount(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { ByteString address = request.getValue(); @@ -953,7 +836,7 @@ public void getMarketOrderByAccount(BytesMessage request, @Override public void getMarketOrderById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { ByteString address = request.getValue(); @@ -968,7 +851,7 @@ public void getMarketOrderById(BytesMessage request, @Override public void getMarketPriceByPair(MarketOrderPair request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { MarketPriceList marketPriceList = wallet .getMarketPriceByPair(request.getSellTokenId().toByteArray(), @@ -982,7 +865,7 @@ public void getMarketPriceByPair(MarketOrderPair request, @Override public void getMarketOrderListByPair(org.tron.protos.Protocol.MarketOrderPair request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { MarketOrderList orderPairList = wallet .getMarketOrderListByPair(request.getSellTokenId().toByteArray(), @@ -996,7 +879,7 @@ public void getMarketOrderListByPair(org.tron.protos.Protocol.MarketOrderPair re @Override public void getMarketPairList(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { MarketOrderPairList pairList = wallet.getMarketPairList(); responseObserver.onNext(pairList); @@ -1008,14 +891,14 @@ public void getMarketPairList(EmptyMessage request, @Override public void triggerConstantContract(TriggerSmartContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { callContract(request, responseObserver, true); } @Override public void getTransactionInfoByBlockNum(NumberMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext(wallet.getTransactionInfoByBlockNum(request.getNum())); } catch (Exception e) { @@ -1087,7 +970,7 @@ public void getAccountById(Account req, StreamObserver responseObserver * */ public void getAccountBalance(AccountBalanceRequest request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { AccountBalanceResponse accountBalanceResponse = wallet.getAccountBalance(request); responseObserver.onNext(accountBalanceResponse); @@ -1101,7 +984,7 @@ public void getAccountBalance(AccountBalanceRequest request, * */ public void getBlockBalanceTrace(BlockBalanceTrace.BlockIdentifier request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { BlockBalanceTrace blockBalanceTrace = wallet.getBlockBalance(request); responseObserver.onNext(blockBalanceTrace); @@ -1113,7 +996,7 @@ public void getBlockBalanceTrace(BlockBalanceTrace.BlockIdentifier request, @Override public void createTransaction(TransferContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver .onNext( @@ -1128,12 +1011,12 @@ public void createTransaction(TransferContract request, @Override public void createTransaction2(TransferContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.TransferContract, responseObserver); } private void createTransactionExtention(Message request, ContractType contractType, - StreamObserver responseObserver) { + StreamObserver responseObserver) { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); try { @@ -1159,7 +1042,7 @@ private void createTransactionExtention(Message request, ContractType contractTy @Override public void getTransactionSign(TransactionSign req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { TransactionCapsule result = TransactionUtil.getTransactionSign(req); responseObserver.onNext(result.getInstance()); responseObserver.onCompleted(); @@ -1167,7 +1050,7 @@ public void getTransactionSign(TransactionSign req, @Override public void getTransactionSign2(TransactionSign req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); try { @@ -1187,7 +1070,7 @@ public void getTransactionSign2(TransactionSign req, @Override public void addSign(TransactionSign req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); try { @@ -1207,15 +1090,14 @@ public void addSign(TransactionSign req, @Override public void getTransactionSignWeight(Transaction req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { TransactionSignWeight tsw = transactionUtil.getTransactionSignWeight(req); responseObserver.onNext(tsw); responseObserver.onCompleted(); } @Override - public void getTransactionApprovedList( - Transaction req, + public void getTransactionApprovedList(Transaction req, StreamObserver responseObserver) { TransactionApprovedList tal = wallet.getTransactionApprovedList(req); responseObserver.onNext(tal); @@ -1224,7 +1106,7 @@ public void getTransactionApprovedList( @Override public void createAddress(BytesMessage req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { byte[] address = wallet.createAddress(req.getValue().toByteArray()); BytesMessage.Builder builder = BytesMessage.newBuilder(); builder.setValue(ByteString.copyFrom(address)); @@ -1233,7 +1115,7 @@ public void createAddress(BytesMessage req, } private EasyTransferResponse easyTransfer(byte[] privateKey, ByteString toAddress, - long amount) { + long amount) { TransactionCapsule transactionCapsule; GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); @@ -1267,7 +1149,7 @@ private EasyTransferResponse easyTransfer(byte[] privateKey, ByteString toAddres @Override public void easyTransfer(EasyTransferMessage req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { byte[] privateKey = wallet.pass2Key(req.getPassPhrase().toByteArray()); EasyTransferResponse response = easyTransfer(privateKey, req.getToAddress(), req.getAmount()); responseObserver.onNext(response); @@ -1276,7 +1158,7 @@ public void easyTransfer(EasyTransferMessage req, @Override public void easyTransferAsset(EasyTransferAssetMessage req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { byte[] privateKey = wallet.pass2Key(req.getPassPhrase().toByteArray()); EasyTransferResponse response = easyTransferAsset(privateKey, req.getToAddress(), req.getAssetId(), req.getAmount()); @@ -1285,7 +1167,7 @@ public void easyTransferAsset(EasyTransferAssetMessage req, } private EasyTransferResponse easyTransferAsset(byte[] privateKey, ByteString toAddress, - String assetId, long amount) { + String assetId, long amount) { TransactionCapsule transactionCapsule; GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); @@ -1320,7 +1202,7 @@ private EasyTransferResponse easyTransferAsset(byte[] privateKey, ByteString toA @Override public void easyTransferByPrivate(EasyTransferByPrivateMessage req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { byte[] privateKey = req.getPrivateKey().toByteArray(); EasyTransferResponse response = easyTransfer(privateKey, req.getToAddress(), req.getAmount()); responseObserver.onNext(response); @@ -1329,7 +1211,7 @@ public void easyTransferByPrivate(EasyTransferByPrivateMessage req, @Override public void easyTransferAssetByPrivate(EasyTransferAssetByPrivateMessage req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { byte[] privateKey = req.getPrivateKey().toByteArray(); EasyTransferResponse response = easyTransferAsset(privateKey, req.getToAddress(), req.getAssetId(), req.getAmount()); @@ -1339,7 +1221,7 @@ public void easyTransferAssetByPrivate(EasyTransferAssetByPrivateMessage req, @Override public void broadcastTransaction(Transaction req, - StreamObserver responseObserver) { + StreamObserver responseObserver) { GrpcAPI.Return result = wallet.broadcastTransaction(req); responseObserver.onNext(result); responseObserver.onCompleted(); @@ -1347,7 +1229,7 @@ public void broadcastTransaction(Transaction req, @Override public void createAssetIssue(AssetIssueContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.AssetIssueContract).getInstance()); @@ -1360,13 +1242,13 @@ public void createAssetIssue(AssetIssueContract request, @Override public void createAssetIssue2(AssetIssueContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.AssetIssueContract, responseObserver); } @Override public void unfreezeAsset(UnfreezeAssetContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.UnfreezeAssetContract).getInstance()); @@ -1379,7 +1261,7 @@ public void unfreezeAsset(UnfreezeAssetContract request, @Override public void unfreezeAsset2(UnfreezeAssetContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.UnfreezeAssetContract, responseObserver); } @@ -1391,20 +1273,16 @@ private void checkVoteWitnessAccount(VoteWitnessContract req) { AccountCapsule account = dbManager.getAccountStore().get(ownerAddress.toByteArray()); Preconditions.checkNotNull(account, - "OwnerAddress[" - + StringUtil.createReadableString(ownerAddress) + "] not exists"); + "OwnerAddress[" + StringUtil.createReadableString(ownerAddress) + "] not exists"); int votesCount = req.getVotesCount(); - Preconditions.checkArgument(votesCount <= 0, - "VotesCount[" + votesCount + "] <= 0"); + Preconditions.checkArgument(votesCount <= 0, "VotesCount[" + votesCount + "] <= 0"); if (dbManager.getDynamicPropertiesStore().supportAllowNewResourceModel()) { Preconditions.checkArgument(account.getAllTronPower() < votesCount, - "tron power[" + account.getAllTronPower() - + "] < VotesCount[" + votesCount + "]"); + "tron power[" + account.getAllTronPower() + "] < VotesCount[" + votesCount + "]"); } else { Preconditions.checkArgument(account.getTronPower() < votesCount, - "tron power[" + account.getTronPower() - + "] < VotesCount[" + votesCount + "]"); + "tron power[" + account.getTronPower() + "] < VotesCount[" + votesCount + "]"); } req.getVotesList().forEach(vote -> { @@ -1413,8 +1291,7 @@ private void checkVoteWitnessAccount(VoteWitnessContract req) { .get(voteAddress.toByteArray()); String readableWitnessAddress = StringUtil.createReadableString(voteAddress); - Preconditions.checkNotNull(witness, - "witness[" + readableWitnessAddress + "] not exists"); + Preconditions.checkNotNull(witness, "witness[" + readableWitnessAddress + "] not exists"); Preconditions.checkArgument(vote.getVoteCount() <= 0, "VoteAddress[" + readableWitnessAddress + "], VotesCount[" + vote .getVoteCount() + "] <= 0"); @@ -1423,7 +1300,7 @@ private void checkVoteWitnessAccount(VoteWitnessContract req) { @Override public void voteWitnessAccount(VoteWitnessContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.VoteWitnessContract).getInstance()); @@ -1437,34 +1314,34 @@ public void voteWitnessAccount(VoteWitnessContract request, @Override public void voteWitnessAccount2(VoteWitnessContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.VoteWitnessContract, responseObserver); } @Override public void updateSetting(UpdateSettingContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.UpdateSettingContract, responseObserver); } @Override public void updateEnergyLimit(UpdateEnergyLimitContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.UpdateEnergyLimitContract, responseObserver); } @Override public void clearContractABI(ClearABIContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.ClearABIContract, responseObserver); } @Override public void createWitness(WitnessCreateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.WitnessCreateContract).getInstance()); @@ -1478,13 +1355,13 @@ public void createWitness(WitnessCreateContract request, @Override public void createWitness2(WitnessCreateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.WitnessCreateContract, responseObserver); } @Override public void createAccount(AccountCreateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.AccountCreateContract).getInstance()); @@ -1498,13 +1375,13 @@ public void createAccount(AccountCreateContract request, @Override public void createAccount2(AccountCreateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.AccountCreateContract, responseObserver); } @Override public void updateWitness(WitnessUpdateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.WitnessUpdateContract).getInstance()); @@ -1518,13 +1395,13 @@ public void updateWitness(WitnessUpdateContract request, @Override public void updateWitness2(WitnessUpdateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.WitnessUpdateContract, responseObserver); } @Override public void updateAccount(AccountUpdateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.AccountUpdateContract).getInstance()); @@ -1538,7 +1415,7 @@ public void updateAccount(AccountUpdateContract request, @Override public void setAccountId(SetAccountIdContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.SetAccountIdContract).getInstance()); @@ -1552,13 +1429,13 @@ public void setAccountId(SetAccountIdContract request, @Override public void updateAccount2(AccountUpdateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.AccountUpdateContract, responseObserver); } @Override public void updateAsset(UpdateAssetContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, @@ -1573,13 +1450,13 @@ public void updateAsset(UpdateAssetContract request, @Override public void updateAsset2(UpdateAssetContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.UpdateAssetContract, responseObserver); } @Override public void freezeBalance(FreezeBalanceContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.FreezeBalanceContract).getInstance()); @@ -1593,13 +1470,13 @@ public void freezeBalance(FreezeBalanceContract request, @Override public void freezeBalance2(FreezeBalanceContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.FreezeBalanceContract, responseObserver); } @Override public void unfreezeBalance(UnfreezeBalanceContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.UnfreezeBalanceContract) @@ -1614,13 +1491,13 @@ public void unfreezeBalance(UnfreezeBalanceContract request, @Override public void unfreezeBalance2(UnfreezeBalanceContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.UnfreezeBalanceContract, responseObserver); } @Override public void withdrawBalance(WithdrawBalanceContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext( createTransactionCapsule(request, ContractType.WithdrawBalanceContract) @@ -1635,89 +1512,86 @@ public void withdrawBalance(WithdrawBalanceContract request, @Override public void withdrawBalance2(WithdrawBalanceContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.WithdrawBalanceContract, responseObserver); } @Override public void proposalCreate(ProposalCreateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.ProposalCreateContract, responseObserver); } @Override public void proposalApprove(ProposalApproveContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.ProposalApproveContract, responseObserver); } @Override public void proposalDelete(ProposalDeleteContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.ProposalDeleteContract, responseObserver); } @Override public void exchangeCreate(ExchangeCreateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.ExchangeCreateContract, responseObserver); } @Override public void exchangeInject(ExchangeInjectContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.ExchangeInjectContract, responseObserver); } @Override public void exchangeWithdraw(ExchangeWithdrawContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.ExchangeWithdrawContract, responseObserver); } @Override public void exchangeTransaction(ExchangeTransactionContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.ExchangeTransactionContract, responseObserver); } @Override public void getNowBlock(EmptyMessage request, StreamObserver responseObserver) { - responseObserver.onNext(wallet.clearTrxForBlock(wallet.getNowBlock(), - request.getType())); + responseObserver.onNext(wallet.getNowBlock()); responseObserver.onCompleted(); } @Override public void getNowBlock2(EmptyMessage request, - StreamObserver responseObserver) { - Block block = wallet.clearTrxForBlock(wallet.getNowBlock(), request.getType()); + StreamObserver responseObserver) { + Block block = wallet.getNowBlock(); responseObserver.onNext(block2Extention(block)); responseObserver.onCompleted(); } @Override public void getBlockByNum(NumberMessage request, StreamObserver responseObserver) { - responseObserver.onNext(wallet.clearTrxForBlock(wallet.getBlockByNum(request.getNum()), - request.getType())); + responseObserver.onNext(wallet.getBlockByNum(request.getNum())); responseObserver.onCompleted(); } @Override public void getBlockByNum2(NumberMessage request, - StreamObserver responseObserver) { - Block block = wallet.clearTrxForBlock(wallet.getBlockByNum(request.getNum()), - request.getType()); + StreamObserver responseObserver) { + Block block = wallet.getBlockByNum(request.getNum()); responseObserver.onNext(block2Extention(block)); responseObserver.onCompleted(); } @Override public void getTransactionCountByBlockNum(NumberMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { getTransactionCountByBlockNumCommon(request, responseObserver); } @@ -1747,7 +1621,7 @@ public void listNodes(EmptyMessage request, StreamObserver responseObs @Override public void transferAsset(TransferAssetContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver .onNext(createTransactionCapsule(request, ContractType.TransferAssetContract) @@ -1762,13 +1636,13 @@ public void transferAsset(TransferAssetContract request, @Override public void transferAsset2(TransferAssetContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.TransferAssetContract, responseObserver); } @Override public void participateAssetIssue(ParticipateAssetIssueContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver .onNext(createTransactionCapsule(request, ContractType.ParticipateAssetIssueContract) @@ -1783,14 +1657,14 @@ public void participateAssetIssue(ParticipateAssetIssueContract request, @Override public void participateAssetIssue2(ParticipateAssetIssueContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.ParticipateAssetIssueContract, responseObserver); } @Override public void getAssetIssueByAccount(Account request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString fromBs = request.getAddress(); if (fromBs != null) { @@ -1803,7 +1677,7 @@ public void getAssetIssueByAccount(Account request, @Override public void getAccountNet(Account request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString fromBs = request.getAddress(); if (fromBs != null) { @@ -1816,7 +1690,7 @@ public void getAccountNet(Account request, @Override public void getAccountResource(Account request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString fromBs = request.getAddress(); if (fromBs != null) { @@ -1829,7 +1703,7 @@ public void getAccountResource(Account request, @Override public void getAssetIssueByName(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString assetName = request.getValue(); if (assetName != null) { try { @@ -1846,7 +1720,7 @@ public void getAssetIssueByName(BytesMessage request, @Override public void getAssetIssueListByName(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString assetName = request.getValue(); if (assetName != null) { @@ -1859,7 +1733,7 @@ public void getAssetIssueListByName(BytesMessage request, @Override public void getAssetIssueById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString assetId = request.getValue(); if (assetId != null) { @@ -1873,14 +1747,18 @@ public void getAssetIssueById(BytesMessage request, @Override public void getBlockById(BytesMessage request, StreamObserver responseObserver) { ByteString blockId = request.getValue(); - responseObserver.onNext(wallet.clearTrxForBlock(wallet.getBlockById(blockId), - request.getType())); + + if (Objects.nonNull(blockId)) { + responseObserver.onNext(wallet.getBlockById(blockId)); + } else { + responseObserver.onNext(null); + } responseObserver.onCompleted(); } @Override public void getProposalById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString proposalId = request.getValue(); if (Objects.nonNull(proposalId)) { @@ -1893,7 +1771,7 @@ public void getProposalById(BytesMessage request, @Override public void getExchangeById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString exchangeId = request.getValue(); if (Objects.nonNull(exchangeId)) { @@ -1906,13 +1784,12 @@ public void getExchangeById(BytesMessage request, @Override public void getBlockByLimitNext(BlockLimit request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartNum(); long endNum = request.getEndNum(); if (endNum > 0 && endNum > startNum && endNum - startNum <= BLOCK_LIMIT_NUM) { - responseObserver.onNext(wallet.clearTrxBlockList(wallet.getBlocksByLimitNext(startNum, - endNum - startNum), request.getType())); + responseObserver.onNext(wallet.getBlocksByLimitNext(startNum, endNum - startNum)); } else { responseObserver.onNext(null); } @@ -1921,14 +1798,13 @@ public void getBlockByLimitNext(BlockLimit request, @Override public void getBlockByLimitNext2(BlockLimit request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartNum(); long endNum = request.getEndNum(); if (endNum > 0 && endNum > startNum && endNum - startNum <= BLOCK_LIMIT_NUM) { - responseObserver.onNext(blockList2Extention(wallet.clearTrxBlockList( - wallet.getBlocksByLimitNext(startNum, endNum - startNum), - request.getType()))); + responseObserver + .onNext(blockList2Extention(wallet.getBlocksByLimitNext(startNum, endNum - startNum))); } else { responseObserver.onNext(null); } @@ -1937,12 +1813,11 @@ public void getBlockByLimitNext2(BlockLimit request, @Override public void getBlockByLatestNum(NumberMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long getNum = request.getNum(); if (getNum > 0 && getNum < BLOCK_LIMIT_NUM) { - responseObserver.onNext(wallet.clearTrxBlockList(wallet.getBlockByLatestNum(getNum), - request.getType())); + responseObserver.onNext(wallet.getBlockByLatestNum(getNum)); } else { responseObserver.onNext(null); } @@ -1951,12 +1826,11 @@ public void getBlockByLatestNum(NumberMessage request, @Override public void getBlockByLatestNum2(NumberMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long getNum = request.getNum(); if (getNum > 0 && getNum < BLOCK_LIMIT_NUM) { - responseObserver.onNext(blockList2Extention(wallet.clearTrxBlockList( - wallet.getBlockByLatestNum(getNum), request.getType()))); + responseObserver.onNext(blockList2Extention(wallet.getBlockByLatestNum(getNum))); } else { responseObserver.onNext(null); } @@ -1965,7 +1839,7 @@ public void getBlockByLatestNum2(NumberMessage request, @Override public void getTransactionById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString transactionId = request.getValue(); if (Objects.nonNull(transactionId)) { @@ -1978,47 +1852,46 @@ public void getTransactionById(BytesMessage request, @Override public void deployContract(CreateSmartContract request, - io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.StreamObserver responseObserver) { createTransactionExtention(request, ContractType.CreateSmartContract, responseObserver); } public void totalTransaction(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.totalTransaction()); responseObserver.onCompleted(); } @Override public void getNextMaintenanceTime(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getNextMaintenanceTime()); responseObserver.onCompleted(); } @Override public void getAssetIssueList(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getAssetIssueList()); responseObserver.onCompleted(); } @Override public void triggerContract(TriggerSmartContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { callContract(request, responseObserver, false); } @Override public void triggerConstantContract(TriggerSmartContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { callContract(request, responseObserver, true); } private void callContract(TriggerSmartContract request, - StreamObserver responseObserver, - boolean isConstant) { + StreamObserver responseObserver, boolean isConstant) { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); try { @@ -2057,14 +1930,14 @@ private void callContract(TriggerSmartContract request, } public void getPaginatedAssetIssueList(PaginatedMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getAssetIssueList(request.getOffset(), request.getLimit())); responseObserver.onCompleted(); } @Override public void getContract(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { SmartContract contract = wallet.getContract(request); responseObserver.onNext(contract); responseObserver.onCompleted(); @@ -2072,21 +1945,21 @@ public void getContract(BytesMessage request, @Override public void getContractInfo(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { SmartContractDataWrapper contract = wallet.getContractInfo(request); responseObserver.onNext(contract); responseObserver.onCompleted(); } public void listWitnesses(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getWitnessList()); responseObserver.onCompleted(); } @Override public void listProposals(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getProposalList()); responseObserver.onCompleted(); } @@ -2094,14 +1967,13 @@ public void listProposals(EmptyMessage request, @Override public void getDelegatedResource(DelegatedResourceMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver .onNext(wallet.getDelegatedResource(request.getFromAddress(), request.getToAddress())); responseObserver.onCompleted(); } - public void getDelegatedResourceAccountIndex( - BytesMessage request, + public void getDelegatedResourceAccountIndex(BytesMessage request, StreamObserver responseObserver) { responseObserver .onNext(wallet.getDelegatedResourceAccountIndex(request.getValue())); @@ -2110,7 +1982,7 @@ public void getDelegatedResourceAccountIndex( @Override public void getPaginatedProposalList(PaginatedMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver .onNext(wallet.getPaginatedProposalList(request.getOffset(), request.getLimit())); responseObserver.onCompleted(); @@ -2119,7 +1991,7 @@ public void getPaginatedProposalList(PaginatedMessage request, @Override public void getPaginatedExchangeList(PaginatedMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver .onNext(wallet.getPaginatedExchangeList(request.getOffset(), request.getLimit())); responseObserver.onCompleted(); @@ -2128,27 +2000,27 @@ public void getPaginatedExchangeList(PaginatedMessage request, @Override public void listExchanges(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getExchangeList()); responseObserver.onCompleted(); } @Override public void getChainParameters(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(wallet.getChainParameters()); responseObserver.onCompleted(); } @Override public void generateAddress(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { generateAddressCommon(request, responseObserver); } @Override public void getTransactionInfoById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString id = request.getValue(); if (null != id) { TransactionInfo reply = wallet.getTransactionInfoById(id); @@ -2172,14 +2044,13 @@ public void getNodeInfo(EmptyMessage request, StreamObserver responseO @Override public void accountPermissionUpdate(AccountPermissionUpdateContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.AccountPermissionUpdateContract, responseObserver); } @Override - public void getMerkleTreeVoucherInfo( - OutputPointInfo request, + public void getMerkleTreeVoucherInfo(OutputPointInfo request, StreamObserver responseObserver) { try { @@ -2198,7 +2069,7 @@ public void getMerkleTreeVoucherInfo( @Override public void createShieldedTransaction(PrivateParameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); @@ -2228,8 +2099,7 @@ public void createShieldedTransaction(PrivateParameters request, } @Override - public void createShieldedTransactionWithoutSpendAuthSig( - PrivateParametersWithoutAsk request, + public void createShieldedTransactionWithoutSpendAuthSig(PrivateParametersWithoutAsk request, StreamObserver responseObserver) { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); @@ -2262,7 +2132,7 @@ public void createShieldedTransactionWithoutSpendAuthSig( @Override public void getNewShieldedAddress(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTRC20Transaction(); @@ -2277,7 +2147,7 @@ public void getNewShieldedAddress(EmptyMessage request, @Override public void getSpendingKey(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTRC20Transaction(); @@ -2291,7 +2161,7 @@ public void getSpendingKey(EmptyMessage request, @Override public void getRcm(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTRC20Transaction(); @@ -2304,8 +2174,7 @@ public void getRcm(EmptyMessage request, } @Override - public void getExpandedSpendingKey( - BytesMessage request, + public void getExpandedSpendingKey(BytesMessage request, StreamObserver responseObserver) { ByteString spendingKey = request.getValue(); @@ -2356,7 +2225,7 @@ public void getNkFromNsk(BytesMessage request, StreamObserver resp @Override public void getIncomingViewingKey(ViewingKeyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { ByteString ak = request.getAk(); ByteString nk = request.getNk(); @@ -2374,7 +2243,7 @@ public void getIncomingViewingKey(ViewingKeyMessage request, @Override public void getDiversifier(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTRC20Transaction(); @@ -2390,7 +2259,7 @@ public void getDiversifier(EmptyMessage request, @Override public void getZenPaymentAddress(IncomingViewingKeyDiversifierMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { IncomingViewingKeyMessage ivk = request.getIvk(); DiversifierMessage d = request.getD(); @@ -2412,7 +2281,7 @@ public void getZenPaymentAddress(IncomingViewingKeyDiversifierMessage request, @Override public void scanNoteByIvk(GrpcAPI.IvkDecryptParameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartBlockIndex(); long endNum = request.getEndBlockIndex(); @@ -2432,7 +2301,7 @@ public void scanNoteByIvk(GrpcAPI.IvkDecryptParameters request, @Override public void scanAndMarkNoteByIvk(GrpcAPI.IvkDecryptAndMarkParameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartBlockIndex(); long endNum = request.getEndBlockIndex(); @@ -2454,7 +2323,7 @@ public void scanAndMarkNoteByIvk(GrpcAPI.IvkDecryptAndMarkParameters request, @Override public void scanNoteByOvk(GrpcAPI.OvkDecryptParameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { long startNum = request.getStartBlockIndex(); long endNum = request.getEndBlockIndex(); @@ -2486,7 +2355,7 @@ public void isSpend(NoteParameters request, StreamObserver response @Override public void createShieldNullifier(GrpcAPI.NfParameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTransaction(); @@ -2502,7 +2371,7 @@ public void createShieldNullifier(GrpcAPI.NfParameters request, @Override public void createSpendAuthSig(SpendAuthSigParameters request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTRC20Transaction(); @@ -2517,7 +2386,7 @@ public void createSpendAuthSig(SpendAuthSigParameters request, @Override public void getShieldTransactionHash(Transaction request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTransaction(); @@ -2614,8 +2483,7 @@ public void scanShieldedTRC20NotesByOvk( } @Override - public void isShieldedTRC20ContractNoteSpent( - NfTRC20Parameters request, + public void isShieldedTRC20ContractNoteSpent(NfTRC20Parameters request, StreamObserver responseObserver) { try { checkSupportShieldedTRC20Transaction(); @@ -2647,13 +2515,13 @@ public void getTriggerInputForShieldedTRC20Contract( @Override public void getRewardInfo(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { getRewardInfoCommon(request, responseObserver); } @Override public void getBrokerageInfo(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { getBrokerageInfoCommon(request, responseObserver); } @@ -2664,14 +2532,14 @@ public void getBurnTrx(EmptyMessage request, StreamObserver respo @Override public void updateBrokerage(UpdateBrokerageContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.UpdateBrokerageContract, responseObserver); } @Override public void createCommonTransaction(Transaction request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { Transaction.Contract contract = request.getRawData().getContract(0); createTransactionExtention(contract.getParameter(), contract.getType(), responseObserver); @@ -2679,7 +2547,7 @@ public void createCommonTransaction(Transaction request, @Override public void getTransactionInfoByBlockNum(NumberMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { responseObserver.onNext(wallet.getTransactionInfoByBlockNum(request.getNum())); } catch (Exception e) { @@ -2691,20 +2559,20 @@ public void getTransactionInfoByBlockNum(NumberMessage request, @Override public void marketSellAsset(MarketSellAssetContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.MarketSellAssetContract, responseObserver); } @Override public void marketCancelOrder(MarketCancelOrderContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.MarketCancelOrderContract, responseObserver); } @Override public void getMarketOrderByAccount(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { ByteString address = request.getValue(); @@ -2719,7 +2587,7 @@ public void getMarketOrderByAccount(BytesMessage request, @Override public void getMarketOrderById(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { ByteString address = request.getValue(); @@ -2734,7 +2602,7 @@ public void getMarketOrderById(BytesMessage request, @Override public void getMarketPriceByPair(MarketOrderPair request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { MarketPriceList marketPriceList = wallet .getMarketPriceByPair(request.getSellTokenId().toByteArray(), @@ -2748,7 +2616,7 @@ public void getMarketPriceByPair(MarketOrderPair request, @Override public void getMarketOrderListByPair(org.tron.protos.Protocol.MarketOrderPair request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { MarketOrderList orderPairList = wallet .getMarketOrderListByPair(request.getSellTokenId().toByteArray(), @@ -2762,7 +2630,7 @@ public void getMarketOrderListByPair(org.tron.protos.Protocol.MarketOrderPair re @Override public void getMarketPairList(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { try { MarketOrderPairList pairList = wallet.getMarketPairList(); responseObserver.onNext(pairList); @@ -2774,19 +2642,19 @@ public void getMarketPairList(EmptyMessage request, @Override public void getTransactionFromPending(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { getTransactionFromPendingCommon(request, responseObserver); } @Override public void getTransactionListFromPending(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { getTransactionListFromPendingCommon(request, responseObserver); } @Override public void getPendingSize(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { getPendingSizeCommon(request, responseObserver); } } @@ -2795,9 +2663,115 @@ public class MonitorApi extends MonitorGrpc.MonitorImplBase { @Override public void getStatsInfo(EmptyMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(metricsApiService.getMetricProtoInfo()); responseObserver.onCompleted(); } } + + public void generateAddressCommon(EmptyMessage request, + StreamObserver responseObserver) { + SignInterface cryptoEngine = SignUtils.getGeneratedRandomSign(Utils.getRandom(), + Args.getInstance().isECKeyCryptoEngine()); + byte[] priKey = cryptoEngine.getPrivateKey(); + byte[] address = cryptoEngine.getAddress(); + String addressStr = StringUtil.encode58Check(address); + String priKeyStr = Hex.encodeHexString(priKey); + AddressPrKeyPairMessage.Builder builder = AddressPrKeyPairMessage.newBuilder(); + builder.setAddress(addressStr); + builder.setPrivateKey(priKeyStr); + responseObserver.onNext(builder.build()); + responseObserver.onCompleted(); + } + + public void getRewardInfoCommon(BytesMessage request, + StreamObserver responseObserver) { + try { + long value = dbManager.getMortgageService().queryReward(request.getValue().toByteArray()); + NumberMessage.Builder builder = NumberMessage.newBuilder(); + builder.setNum(value); + responseObserver.onNext(builder.build()); + } catch (Exception e) { + responseObserver.onError(e); + } + responseObserver.onCompleted(); + } + + public void getBurnTrxCommon(EmptyMessage request, + StreamObserver responseObserver) { + try { + long value = dbManager.getDynamicPropertiesStore().getBurnTrxAmount(); + NumberMessage.Builder builder = NumberMessage.newBuilder(); + builder.setNum(value); + responseObserver.onNext(builder.build()); + } catch (Exception e) { + responseObserver.onError(e); + } + responseObserver.onCompleted(); + } + + public void getBrokerageInfoCommon(BytesMessage request, + StreamObserver responseObserver) { + try { + long cycle = dbManager.getDynamicPropertiesStore().getCurrentCycleNumber(); + long value = dbManager.getDelegationStore() + .getBrokerage(cycle, request.getValue().toByteArray()); + NumberMessage.Builder builder = NumberMessage.newBuilder(); + builder.setNum(value); + responseObserver.onNext(builder.build()); + } catch (Exception e) { + responseObserver.onError(e); + } + responseObserver.onCompleted(); + } + + public void getTransactionCountByBlockNumCommon(NumberMessage request, + StreamObserver responseObserver) { + NumberMessage.Builder builder = NumberMessage.newBuilder(); + try { + Block block = chainBaseManager.getBlockByNum(request.getNum()).getInstance(); + builder.setNum(block.getTransactionsCount()); + } catch (StoreException e) { + logger.error(e.getMessage()); + builder.setNum(-1); + } + responseObserver.onNext(builder.build()); + responseObserver.onCompleted(); + } + + public void getTransactionFromPendingCommon(BytesMessage request, + StreamObserver responseObserver) { + try { + String txId = ByteArray.toHexString(request.getValue().toByteArray()); + TransactionCapsule transactionCapsule = dbManager.getTxFromPending(txId); + responseObserver.onNext(transactionCapsule == null ? null : transactionCapsule.getInstance()); + } catch (Exception e) { + responseObserver.onError(e); + } + responseObserver.onCompleted(); + } + + public void getTransactionListFromPendingCommon(EmptyMessage request, + StreamObserver responseObserver) { + try { + TransactionIdList.Builder builder = TransactionIdList.newBuilder(); + builder.addAllTxId(dbManager.getTxListFromPending()); + responseObserver.onNext(builder.build()); + } catch (Exception e) { + responseObserver.onError(e); + } + responseObserver.onCompleted(); + } + + public void getPendingSizeCommon(EmptyMessage request, + StreamObserver responseObserver) { + try { + NumberMessage.Builder builder = NumberMessage.newBuilder(); + builder.setNum(dbManager.getPendingSize()); + responseObserver.onNext(builder.build()); + } catch (Exception e) { + responseObserver.onError(e); + } + responseObserver.onCompleted(); + } } diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java index 4871870980e..f7e6ac0ff7d 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java @@ -7,7 +7,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.BytesMessage; import org.tron.common.utils.ByteArray; import org.tron.core.Wallet; @@ -23,9 +22,9 @@ public class GetBlockByIdServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String input = request.getParameter("value"); - fillResponse(Util.getVisible(request), Util.getBlockType(request), - ByteString.copyFrom(ByteArray.fromHexString(input)), response); + fillResponse(visible, ByteString.copyFrom(ByteArray.fromHexString(input)), response); } catch (Exception e) { Util.processError(e, response); } @@ -36,16 +35,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) PostParams params = PostParams.getPostParams(request); BytesMessage.Builder build = BytesMessage.newBuilder(); JsonFormat.merge(params.getParams(), build, params.isVisible()); - fillResponse(params.isVisible(), build.getType(), build.getValue(), response); + fillResponse(params.isVisible(), build.getValue(), response); } catch (Exception e) { Util.processError(e, response); } } - private void fillResponse(boolean visible, GrpcAPI.BlockType type, - ByteString blockId, HttpServletResponse response) + private void fillResponse(boolean visible, ByteString blockId, HttpServletResponse response) throws IOException { - Block reply = wallet.clearTrxForBlock(wallet.getBlockById(blockId), type); + Block reply = wallet.getBlockById(blockId); if (reply != null) { response.getWriter().println(Util.printBlock(reply, visible)); } else { diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java index f62774be7b6..1f2eabdd8dc 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java @@ -6,7 +6,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.BlockList; import org.tron.api.GrpcAPI.NumberMessage; import org.tron.core.Wallet; @@ -22,8 +21,7 @@ public class GetBlockByLatestNumServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - fillResponse(Util.getVisible(request), Util.getBlockType(request), - Long.parseLong(request.getParameter("num")), response); + fillResponse(Util.getVisible(request), Long.parseLong(request.getParameter("num")), response); } catch (Exception e) { Util.processError(e, response); } @@ -34,17 +32,16 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) PostParams params = PostParams.getPostParams(request); NumberMessage.Builder build = NumberMessage.newBuilder(); JsonFormat.merge(params.getParams(), build, params.isVisible()); - fillResponse(params.isVisible(), build.getType(), build.getNum(), response); + fillResponse(params.isVisible(), build.getNum(), response); } catch (Exception e) { Util.processError(e, response); } } - private void fillResponse(boolean visible, GrpcAPI.BlockType type, long num, - HttpServletResponse response) + private void fillResponse(boolean visible, long num, HttpServletResponse response) throws IOException { if (num > 0 && num < BLOCK_LIMIT_NUM) { - BlockList reply = wallet.clearTrxBlockList(wallet.getBlockByLatestNum(num), type); + BlockList reply = wallet.getBlockByLatestNum(num); if (reply != null) { response.getWriter().println(Util.printBlockList(reply, visible)); return; diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java index fc0a77a1cc5..3e6700a1fae 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java @@ -6,7 +6,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.BlockLimit; import org.tron.api.GrpcAPI.BlockList; import org.tron.core.Wallet; @@ -22,8 +21,7 @@ public class GetBlockByLimitNextServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - fillResponse(Util.getVisible(request), Util.getBlockType(request), - Long.parseLong(request.getParameter("startNum")), + fillResponse(Util.getVisible(request), Long.parseLong(request.getParameter("startNum")), Long.parseLong(request.getParameter("endNum")), response); } catch (Exception e) { Util.processError(e, response); @@ -35,19 +33,17 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) PostParams params = PostParams.getPostParams(request); BlockLimit.Builder build = BlockLimit.newBuilder(); JsonFormat.merge(params.getParams(), build, params.isVisible()); - fillResponse(params.isVisible(), build.getType(), - build.getStartNum(), build.getEndNum(), response); + fillResponse(params.isVisible(), build.getStartNum(), build.getEndNum(), response); } catch (Exception e) { Util.processError(e, response); } } - private void fillResponse(boolean visible, GrpcAPI.BlockType type, long startNum, long endNum, - HttpServletResponse response) + private void fillResponse(boolean visible, long startNum, long endNum, + HttpServletResponse response) throws IOException { if (endNum > 0 && endNum > startNum && endNum - startNum <= BLOCK_LIMIT_NUM) { - BlockList reply = wallet.clearTrxBlockList( - wallet.getBlocksByLimitNext(startNum, endNum - startNum), type); + BlockList reply = wallet.getBlocksByLimitNext(startNum, endNum - startNum); if (reply != null) { response.getWriter().println(Util.printBlockList(reply, visible)); return; diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java index f5e8f88d1ca..44babc69551 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java @@ -6,7 +6,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.NumberMessage; import org.tron.core.Wallet; import org.tron.protos.Protocol.Block; @@ -21,8 +20,7 @@ public class GetBlockByNumServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - fillResponse(Util.getVisible(request), Util.getBlockType(request), - Long.parseLong(request.getParameter("num")), response); + fillResponse(Util.getVisible(request), Long.parseLong(request.getParameter("num")), response); } catch (Exception e) { Util.processError(e, response); } @@ -33,16 +31,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) PostParams params = PostParams.getPostParams(request); NumberMessage.Builder build = NumberMessage.newBuilder(); JsonFormat.merge(params.getParams(), build, params.isVisible()); - fillResponse(params.isVisible(), build.getType(), build.getNum(), response); + fillResponse(params.isVisible(), build.getNum(), response); } catch (Exception e) { Util.processError(e, response); } } - private void fillResponse(boolean visible, GrpcAPI.BlockType type, long num, - HttpServletResponse response) + private void fillResponse(boolean visible, long num, HttpServletResponse response) throws IOException { - Block reply = wallet.clearTrxForBlock(wallet.getBlockByNum(num), type); + Block reply = wallet.getBlockByNum(num); if (reply != null) { response.getWriter().println(Util.printBlock(reply, visible)); } else { diff --git a/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java b/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java index 5f4528c7b0d..f7d9700aeb9 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java @@ -1,12 +1,10 @@ package org.tron.core.services.http; -import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI; import org.tron.core.Wallet; import org.tron.protos.Protocol.Block; @@ -20,31 +18,19 @@ public class GetNowBlockServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - fillResponse(Util.getVisible(request), Util.getBlockType(request), response); + boolean visible = Util.getVisible(request); + Block reply = wallet.getNowBlock(); + if (reply != null) { + response.getWriter().println(Util.printBlock(reply, visible)); + } else { + response.getWriter().println("{}"); + } } catch (Exception e) { Util.processError(e, response); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) { - try { - PostParams params = PostParams.getPostParams(request); - GrpcAPI.EmptyMessage.Builder build = GrpcAPI.EmptyMessage.newBuilder(); - JsonFormat.merge(params.getParams(), build, params.isVisible()); - fillResponse(params.isVisible(), build.getType(), response); - } catch (Exception e) { - Util.processError(e, response); - } - } - - private void fillResponse(boolean visible, GrpcAPI.BlockType type, HttpServletResponse response) - throws - IOException { - Block reply = wallet.clearTrxForBlock(wallet.getNowBlock(), type); - if (reply != null) { - response.getWriter().println(Util.printBlock(reply, visible)); - } else { - response.getWriter().println("{}"); - } + doGet(request, response); } } \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 35a56600a52..49b50e3356b 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -24,7 +24,6 @@ import org.apache.commons.lang3.StringUtils; import org.bouncycastle.util.encoders.Hex; import org.eclipse.jetty.util.StringUtil; -import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.BlockList; import org.tron.api.GrpcAPI.EasyTransferResponse; import org.tron.api.GrpcAPI.TransactionApprovedList; @@ -62,7 +61,6 @@ public class Util { public static final String CONTRACT_TYPE = "contractType"; public static final String EXTRA_DATA = "extra_data"; public static final String PARAMETER = "parameter"; - public static final String TYPE = "type"; public static String printTransactionFee(String transactionFee) { JSONObject jsonObject = new JSONObject(); @@ -323,11 +321,6 @@ public static boolean getVisible(final HttpServletRequest request) { return visible; } - public static GrpcAPI.BlockType getBlockType(final HttpServletRequest request) { - String type = request.getParameter(TYPE); - return GrpcAPI.BlockType.forNumber(StringUtil.isNotBlank(type) ? Integer.parseInt(type) : 0); - } - public static boolean getVisiblePost(final String input) { boolean visible = false; if (StringUtil.isNotBlank(input)) { diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 31e42ad96aa..4c0ff5ed6c4 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -21,11 +21,14 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static stest.tron.wallet.common.client.utils.PublicMethed.decode58Check; import com.google.protobuf.Any; import com.google.protobuf.ByteString; import java.io.File; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import lombok.extern.slf4j.Slf4j; import org.joda.time.DateTime; import org.junit.AfterClass; @@ -42,18 +45,21 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; import org.tron.common.utils.Utils; +import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.ExchangeCapsule; import org.tron.core.capsule.ProposalCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.TransactionInfoCapsule; +import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.utils.ProposalUtil.ProposalType; import org.tron.core.utils.TransactionUtil; import org.tron.protos.Protocol; +import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.BlockHeader; import org.tron.protos.Protocol.BlockHeader.raw; @@ -117,7 +123,7 @@ public class WalletTest { private static AssetIssueCapsule Asset1; static { - Args.setParam(new String[] {"-d", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); } @@ -182,11 +188,11 @@ private static void addTransactionInfoToStore(Transaction transaction) { private static Transaction getBuildTransaction( TransferContract transferContract, long transactionTimestamp, long refBlockNum) { return Transaction.newBuilder().setRawData( - Transaction.raw.newBuilder().setTimestamp(transactionTimestamp) - .setRefBlockNum(refBlockNum) - .addContract( - Contract.newBuilder().setType(ContractType.TransferContract) - .setParameter(Any.pack(transferContract)).build()).build()) + Transaction.raw.newBuilder().setTimestamp(transactionTimestamp) + .setRefBlockNum(refBlockNum) + .addContract( + Contract.newBuilder().setType(ContractType.TransferContract) + .setParameter(Any.pack(transferContract)).build()).build()) .build(); } @@ -233,12 +239,11 @@ private static void addBlockToStore(Block block) { } private static Block getBuildBlock(long timestamp, long num, long witnessId, - String witnessAddress, Transaction transaction, - Transaction transactionNext) { + String witnessAddress, Transaction transaction, Transaction transactionNext) { return Block.newBuilder().setBlockHeader(BlockHeader.newBuilder().setRawData( - raw.newBuilder().setTimestamp(timestamp).setNumber(num).setWitnessId(witnessId) - .setWitnessAddress(ByteString.copyFrom(ByteArray.fromHexString(witnessAddress))) - .build()).build()).addTransactions(transaction).addTransactions(transactionNext) + raw.newBuilder().setTimestamp(timestamp).setNumber(num).setWitnessId(witnessId) + .setWitnessAddress(ByteString.copyFrom(ByteArray.fromHexString(witnessAddress))) + .build()).build()).addTransactions(transaction).addTransactions(transactionNext) .build(); } diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 3bc72838cd9..5f697026c10 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -1111,21 +1111,13 @@ message Address { int32 port = 2; } -enum BlockType { - ALL = 0; // 0 for all block msg - HEADER = 1; //1 for block header; -} - message EmptyMessage { - BlockType type = 1; } message NumberMessage { int64 num = 1; - BlockType type = 2; } message BytesMessage { bytes value = 1; - BlockType type = 2; } message TimeMessage { int64 beginInMilliseconds = 1; @@ -1134,7 +1126,6 @@ message TimeMessage { message BlockLimit { int64 startNum = 1; int64 endNum = 2; - BlockType type = 3; } message TransactionLimit { bytes transactionId = 1; From c9044100a8edb1e415355a1cbdf3cdf78b64442b Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 9 Jun 2022 16:00:32 +0800 Subject: [PATCH 0130/1197] perf:optimize ChainInventoryMsgHandler processing logic --- .../messagehandler/ChainInventoryMsgHandler.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java index 276ba7b21db..94c3868b9c7 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java @@ -5,6 +5,8 @@ import java.util.Deque; import java.util.LinkedList; import java.util.List; +import java.util.NoSuchElementException; + import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -63,9 +65,16 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep synchronized (tronNetDelegate.getBlockLock()) { while (!peer.getSyncBlockToFetch().isEmpty() && tronNetDelegate .containBlock(peer.getSyncBlockToFetch().peek())) { - BlockId blockId = peer.getSyncBlockToFetch().pop(); - peer.setBlockBothHave(blockId); - logger.info("Block {} from {} is processed", blockId.getString(), peer.getNode().getHost()); + try { + BlockId blockId = peer.getSyncBlockToFetch().pop(); + peer.setBlockBothHave(blockId); + logger.info("Block {} from {} is processed", + blockId.getString(), peer.getNode().getHost()); + } catch (NoSuchElementException e) { + logger.warn("Process ChainInventoryMessage failed, peer {}, isDisconnect:{}", + peer.getNode().getHost(), peer.isDisconnect()); + return; + } } } From e6d4db34f1efaf59a0e5332a9a0a1fe78a8cf553 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 9 Jun 2022 18:39:15 +0800 Subject: [PATCH 0131/1197] log(api):add log for http api error --- .../java/org/tron/core/services/http/RateLimiterServlet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java b/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java index 1d8e1a3d628..d05f0434581 100644 --- a/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java @@ -120,7 +120,7 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) } catch (ServletException | IOException e) { throw e; } catch (Exception unexpected) { - logger.error("Http Api Error: {}", unexpected.getMessage()); + logger.error("Http Api Error: {}", unexpected.getMessage(), unexpected); } finally { if (rateLimiter instanceof IPreemptibleRateLimiter && acquireResource) { ((IPreemptibleRateLimiter) rateLimiter).release(); From 20d732907ebe299087ebda6563b366f7fa15a669 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Fri, 10 Jun 2022 14:35:25 +0800 Subject: [PATCH 0132/1197] perf(db): optimize asset query logic --- .../org/tron/core/capsule/AccountCapsule.java | 8 ++++ .../org/tron/core/db2/core/SnapshotRoot.java | 18 ++++++-- .../tron/core/store/AccountAssetStore.java | 41 ++++++++++++------- protocol/src/main/protos/core/Tron.proto | 2 + 4 files changed, 51 insertions(+), 18 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index 4d6100ecc1f..a01a0f6f35b 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -510,6 +510,14 @@ public long getAllTronPower() { /*************************** start asset ****************************************/ + public boolean getExistInDb() { + return this.account.getExistInDb(); + } + + public void setExistInDb(boolean flag) { + this.account = this.account.toBuilder().setExistInDb(flag).build(); + } + public boolean assetBalanceEnoughV2(byte[] key, long amount, DynamicPropertiesStore dynamicPropertiesStore) { importAsset(key); diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java index e7a10aa43b5..4972666c780 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java @@ -47,8 +47,14 @@ public void put(byte[] key, byte[] value) { remove(key); return; } + AccountAssetStore assetStore = + ChainBaseManager.getInstance().getAccountAssetStore(); AccountCapsule item = new AccountCapsule(value); - ChainBaseManager.getInstance().getAccountAssetStore().putAccount(item.getInstance()); + if (!item.getExistInDb()) { + assetStore.deleteAccount(item.createDbKey()); + item.setExistInDb(true); + } + assetStore.putAccount(item.getInstance()); item.clearAsset(); db.put(key, item.getData()); } else { @@ -97,20 +103,26 @@ public void merge(List snapshots) { private void processAccount(Map batch) { AccountAssetStore assetStore = ChainBaseManager.getInstance().getAccountAssetStore(); Map accounts = new HashMap<>(); - Map assets = new HashMap<>(); + Map assets = new HashMap<>(); batch.forEach((k, v) -> { if (ByteArray.isEmpty(v.getBytes())) { accounts.put(k, v); assets.putAll(assetStore.getDeletedAssets(k.getBytes())); } else { AccountCapsule item = new AccountCapsule(v.getBytes()); + if (!item.getExistInDb()) { + assets.putAll(assetStore.getDeletedAssets(k.getBytes())); + item.setExistInDb(true); + } assets.putAll(assetStore.getAssets(item.getInstance())); item.clearAsset(); accounts.put(k, WrappedByteArray.of(item.getData())); } }); ((Flusher) db).flush(accounts); - assetStore.updateByBatch(assets); + if (assets.size() > 0) { + assetStore.updateByBatch(AccountAssetStore.convert(assets)); + } } @Override diff --git a/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java b/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java index 72e750c09b7..fb5f58de3b8 100644 --- a/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java +++ b/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java @@ -43,39 +43,49 @@ public boolean has(byte[] key) { } public void putAccount(Protocol.Account account) { - Map assets = getAssets(account); + Map assets = convert(getAssets(account)); if (!assets.isEmpty()) { updateByBatch(assets); } } public void deleteAccount(byte[] key) { - Map assets = getDeletedAssets(key); + Map assets = convert(getDeletedAssets(key)); if (!assets.isEmpty()) { updateByBatch(assets); } } - public Map getAssets(Protocol.Account account) { - Map assets = new HashMap<>(); + public Map getAssets(Protocol.Account account) { + Map assets = new HashMap<>(); account.getAssetV2Map().forEach((k, v) -> { byte[] key = Bytes.concat(account.getAddress().toByteArray(), k.getBytes()); if (v == 0) { - assets.put(key, null); + assets.put(WrappedByteArray.of(key), WrappedByteArray.of(null)); } else { - assets.put(key, Longs.toByteArray(v)); + assets.put(WrappedByteArray.of(key), WrappedByteArray.of(Longs.toByteArray(v))); } }); return assets; } - public Map getDeletedAssets(byte[] key) { + public Map getDeletedAssets(byte[] key) { + Map assets = new HashMap<>(); + prefixQuery(key).forEach((k, v) -> + assets.put(WrappedByteArray.of(k.getBytes()), WrappedByteArray.of(null))); + return assets; + } + + public static Map convert(Map map) { Map assets = new HashMap<>(); - prefixQuery(key).forEach((k, v) -> assets.put(k.getBytes(), null)); + map.forEach((k, v) -> assets.put(k.getBytes(), v.getBytes())); return assets; } public long getBalance(Protocol.Account account, byte[] key) { + if (!account.getExistInDb()) { + return 0; + } byte[] k = Bytes.concat(account.getAddress().toByteArray(), key); byte[] value = get(k); if (ArrayUtils.isEmpty(value)) { @@ -85,15 +95,16 @@ public long getBalance(Protocol.Account account, byte[] key) { } public Map getAllAssets(Protocol.Account account) { - Map map = prefixQuery(account.getAddress().toByteArray()); Map assets = new HashMap<>(); - map.forEach((k, v) -> { - byte[] assetID = ByteArray.subArray(k.getBytes(), - account.getAddress().toByteArray().length, k.getBytes().length); - assets.put(ByteArray.toStr(assetID), Longs.fromByteArray(v)); - }); + if (account.getExistInDb()) { + Map map = prefixQuery(account.getAddress().toByteArray()); + map.forEach((k, v) -> { + byte[] assetID = ByteArray.subArray(k.getBytes(), + account.getAddress().toByteArray().length, k.getBytes().length); + assets.put(ByteArray.toStr(assetID), Longs.fromByteArray(v)); + }); + } account.getAssetV2Map().forEach((k, v) -> assets.put(k, v)); return assets; } - } diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index c3f3fd7e5e7..7363f3086f4 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -161,6 +161,8 @@ message Account { int64 old_tron_power = 46; Frozen tron_power = 47; + bool exist_in_db = 60; + // this account create time int64 create_time = 0x09; // this last operation time, including transfer, voting and so on. //FIXME fix grammar From 74d96735736616e67609b5eca5dc62b5340f0937 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Fri, 10 Jun 2022 14:45:48 +0800 Subject: [PATCH 0133/1197] perf(db): close account asset store --- chainbase/src/main/java/org/tron/core/ChainBaseManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java index a96a47e5fa3..b2a9f643a42 100644 --- a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java +++ b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java @@ -276,6 +276,7 @@ public void closeAllStore() { closeOneStore(commonDataBase); closeOneStore(pbftSignDataStore); closeOneStore(sectionBloomStore); + closeOneStore(accountAssetStore); } // for test only From 212e7b7e9551cdbdbebce1c15ed9ee3a4fd46cb4 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Fri, 10 Jun 2022 15:35:39 +0800 Subject: [PATCH 0134/1197] optimize account field name --- .../main/java/org/tron/core/capsule/AccountCapsule.java | 8 ++++---- .../main/java/org/tron/core/db2/core/SnapshotRoot.java | 8 ++++---- .../main/java/org/tron/core/store/AccountAssetStore.java | 4 ++-- protocol/src/main/protos/core/Tron.proto | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index a01a0f6f35b..2c30baa8d4e 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -510,12 +510,12 @@ public long getAllTronPower() { /*************************** start asset ****************************************/ - public boolean getExistInDb() { - return this.account.getExistInDb(); + public boolean getAssetOptimized() { + return this.account.getAssetOptimized(); } - public void setExistInDb(boolean flag) { - this.account = this.account.toBuilder().setExistInDb(flag).build(); + public void setAssetOptimized(boolean flag) { + this.account = this.account.toBuilder().setAssetOptimized(flag).build(); } public boolean assetBalanceEnoughV2(byte[] key, long amount, diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java index 4972666c780..9afb5277b9c 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java @@ -50,9 +50,9 @@ public void put(byte[] key, byte[] value) { AccountAssetStore assetStore = ChainBaseManager.getInstance().getAccountAssetStore(); AccountCapsule item = new AccountCapsule(value); - if (!item.getExistInDb()) { + if (!item.getAssetOptimized()) { assetStore.deleteAccount(item.createDbKey()); - item.setExistInDb(true); + item.setAssetOptimized(true); } assetStore.putAccount(item.getInstance()); item.clearAsset(); @@ -110,9 +110,9 @@ private void processAccount(Map batch) { assets.putAll(assetStore.getDeletedAssets(k.getBytes())); } else { AccountCapsule item = new AccountCapsule(v.getBytes()); - if (!item.getExistInDb()) { + if (!item.getAssetOptimized()) { assets.putAll(assetStore.getDeletedAssets(k.getBytes())); - item.setExistInDb(true); + item.setAssetOptimized(true); } assets.putAll(assetStore.getAssets(item.getInstance())); item.clearAsset(); diff --git a/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java b/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java index fb5f58de3b8..6e970a136d3 100644 --- a/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java +++ b/chainbase/src/main/java/org/tron/core/store/AccountAssetStore.java @@ -83,7 +83,7 @@ public static Map convert(Map getAllAssets(Protocol.Account account) { Map assets = new HashMap<>(); - if (account.getExistInDb()) { + if (account.getAssetOptimized()) { Map map = prefixQuery(account.getAddress().toByteArray()); map.forEach((k, v) -> { byte[] assetID = ByteArray.subArray(k.getBytes(), diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 7363f3086f4..37079e0504d 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -161,7 +161,7 @@ message Account { int64 old_tron_power = 46; Frozen tron_power = 47; - bool exist_in_db = 60; + bool asset_optimized = 60; // this account create time int64 create_time = 0x09; From b441b6e0599c2e3a9a29e683767355c643374690 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Sat, 11 Jun 2022 00:57:02 +0800 Subject: [PATCH 0135/1197] fix(api):http net traffic metric. --- .../core/services/filter/CharResponseWrapper.java | 2 +- .../tron/core/services/filter/HttpInterceptor.java | 9 ++++++++- .../tron/core/services/http/RateLimiterServlet.java | 11 +++-------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/filter/CharResponseWrapper.java b/framework/src/main/java/org/tron/core/services/filter/CharResponseWrapper.java index db43c0bbc74..e6421c6a257 100644 --- a/framework/src/main/java/org/tron/core/services/filter/CharResponseWrapper.java +++ b/framework/src/main/java/org/tron/core/services/filter/CharResponseWrapper.java @@ -58,7 +58,7 @@ public void flushBuffer() throws IOException { // flush both stream } public int getByteSize() { - return streamCopy.getStreamByteSize(); + return streamCopy == null ? 0 : streamCopy.getStreamByteSize(); } } \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java index 4401f18cebf..51b4d60f856 100644 --- a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java +++ b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java @@ -1,5 +1,6 @@ package org.tron.core.services.filter; +import com.google.common.base.Strings; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -8,6 +9,9 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; import org.tron.core.metrics.MetricsKey; import org.tron.core.metrics.MetricsUtil; @@ -54,7 +58,10 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha MetricsUtil.meterMark(MetricsKey.NET_API_QPS); MetricsUtil.meterMark(MetricsKey.NET_API_FAIL_QPS); } - + Metrics.histogramObserve(MetricKeys.Histogram.HTTP_BYTES, + responseWrapper.getByteSize(), + Strings.isNullOrEmpty(endpoint) ? MetricLabels.UNDEFINED : endpoint, + String.valueOf(responseWrapper.getStatus())); } else { chain.doFilter(request, response); } diff --git a/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java b/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java index d05f0434581..53eb1067fd3 100644 --- a/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java @@ -16,7 +16,6 @@ import org.tron.common.prometheus.MetricLabels; import org.tron.common.prometheus.Metrics; import org.tron.core.config.args.Args; -import org.tron.core.services.filter.CharResponseWrapper; import org.tron.core.services.ratelimiter.RateLimiterContainer; import org.tron.core.services.ratelimiter.RuntimeData; import org.tron.core.services.ratelimiter.adapter.DefaultBaseQqsAdapter; @@ -99,20 +98,16 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) if (rateLimiter != null) { acquireResource = rateLimiter.acquire(new RuntimeData(req)); } - + String url = Strings.isNullOrEmpty(req.getRequestURI()) + ? MetricLabels.UNDEFINED : req.getRequestURI(); try { resp.setContentType("application/json; charset=utf-8"); if (acquireResource) { - String url = Strings.isNullOrEmpty(req.getRequestURI()) - ? MetricLabels.UNDEFINED : req.getRequestURI(); Histogram.Timer requestTimer = Metrics.histogramStartTimer( MetricKeys.Histogram.HTTP_SERVICE_LATENCY, url); super.service(req, resp); Metrics.histogramObserve(requestTimer); - Metrics.histogramObserve(MetricKeys.Histogram.HTTP_BYTES, - ((CharResponseWrapper) resp).getByteSize(), - url, String.valueOf(resp.getStatus())); } else { resp.getWriter() .println(Util.printErrorMsg(new IllegalAccessException("lack of computing resources"))); @@ -120,7 +115,7 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) } catch (ServletException | IOException e) { throw e; } catch (Exception unexpected) { - logger.error("Http Api Error: {}", unexpected.getMessage(), unexpected); + logger.error("Http Api {}, Method:{}. Error:", url, req.getMethod(), unexpected); } finally { if (rateLimiter instanceof IPreemptibleRateLimiter && acquireResource) { ((IPreemptibleRateLimiter) rateLimiter).release(); From 1c92f4557aee3adf486d6d7abd92e3291db8a9b4 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 13 Jun 2022 22:18:57 +0800 Subject: [PATCH 0136/1197] fix(block): fix rePushTransactions may be empty due to repushLoop. --- framework/src/main/java/org/tron/core/db/Manager.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index d6b1ada162f..2a30cadd5b0 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1428,6 +1428,12 @@ public synchronized BlockCapsule generateBlock(Miner miner, long blockTime, long MetricLabels.Gauge.QUEUE_REPUSH); } + if (trx == null) { + // transaction may be removed by rePushLoop. + logger.warn("Trx is null,fromPending:{},pending:{},repush:{}.", + fromPending, pendingTransactions.size(), rePushTransactions.size()); + continue; + } if (System.currentTimeMillis() > timeout) { logger.warn("Processing transaction time exceeds the producing time."); break; From 1cdc6b54dff10dde14659dae980c722333f1d64c Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 16 Jun 2022 11:31:51 +0800 Subject: [PATCH 0137/1197] feature: update version 1. update version to 4.5.0 --- framework/src/main/java/org/tron/program/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 0f118134d97..75efbf976d6 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -4,7 +4,7 @@ public class Version { public static final String VERSION_NAME = "GreatVoyage-v4.4.4-3-g5f6660e30"; public static final String VERSION_CODE = "16681"; - private static final String VERSION = "4.4.5"; + private static final String VERSION = "4.5.0"; public static String getVersion() { return VERSION; From 4e75445ad2280b57909f05d10c7ac0a6b98a1181 Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 16 Jun 2022 15:19:48 +0800 Subject: [PATCH 0138/1197] update a new version. version name:GreatVoyage-v4.4.6-241-g7045f0659,version code:16928 --- framework/src/main/java/org/tron/program/Version.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 514d62b8af0..eefcc77c78b 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,8 +2,8 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.4.5-2-g64396866d"; - public static final String VERSION_CODE = "16685"; + public static final String VERSION_NAME = "GreatVoyage-v4.4.6-241-g7045f0659"; + public static final String VERSION_CODE = "16928"; private static final String VERSION = "4.5.0"; public static String getVersion() { From 7866be8d92d51a1388892ee4b516a12b51ec0de0 Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 17 Jun 2022 18:59:05 +0800 Subject: [PATCH 0139/1197] fix(vm,api): fix constant trigger smart contract over pre cache --- .../main/java/org/tron/core/actuator/VMActuator.java | 6 ++++++ .../main/java/org/tron/core/vm/program/Program.java | 12 +++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 10ae41f6327..c910086818d 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -303,6 +303,9 @@ private void create() } else { newSmartContract = contract.getNewContract().toBuilder().clearVersion().build(); } + if (VMConfig.allowHigherLimitForMaxCpuTimeOfOneTx()) { + newSmartContract = newSmartContract.toBuilder().clearCodeHash().build(); + } if (!contract.getOwnerAddress().equals(newSmartContract.getOriginAddress())) { logger.info("OwnerAddress not equals OriginAddress"); throw new ContractValidateException("OwnerAddress is not equals OriginAddress"); @@ -384,6 +387,9 @@ private void create() .createProgramInvoke(TrxType.TRX_CONTRACT_CREATION_TYPE, executorType, trx, tokenValue, tokenId, blockCap.getInstance(), rootRepository, vmStartInUs, vmShouldEndInUs, energyLimit); + if (isConstantCall) { + programInvoke.setConstantCall(); + } this.program = new Program(ops, contractAddress, programInvoke, rootInternalTx); if (VMConfig.allowTvmCompatibleEvm()) { this.program.setContractVersion(1); diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 7e60448e12f..653155f15f8 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -170,8 +170,14 @@ public void setNonce(long nonceValue) { } public ProgramPrecompile getProgramPrecompile() { + if (isConstantCall()) { + if (programPrecompile == null) { + programPrecompile = ProgramPrecompile.compile(ops); + } + return programPrecompile; + } if (programPrecompile == null) { - Key key = getCodeHashKey(); + Key key = getJumpDestAnalysisCacheKey(); if (programPrecompileLRUMap.containsKey(key)) { programPrecompile = programPrecompileLRUMap.get(key); } else { @@ -1061,6 +1067,10 @@ private Key getCodeHashKey() { return Key.create(codeHash); } + private Key getJumpDestAnalysisCacheKey() { + return Key.create(ByteUtil.merge(codeAddress, getCodeHash())); + } + public byte[] getContextAddress() { return invoke.getContractAddress().toTronAddress(); } From f5520db49bb72e1cc41cbe6fe13c39e4b7ce4794 Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 17 Jun 2022 19:58:36 +0800 Subject: [PATCH 0140/1197] fix(vm): revert code hash --- actuator/src/main/java/org/tron/core/actuator/VMActuator.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index c910086818d..84b31a9297e 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -303,9 +303,6 @@ private void create() } else { newSmartContract = contract.getNewContract().toBuilder().clearVersion().build(); } - if (VMConfig.allowHigherLimitForMaxCpuTimeOfOneTx()) { - newSmartContract = newSmartContract.toBuilder().clearCodeHash().build(); - } if (!contract.getOwnerAddress().equals(newSmartContract.getOriginAddress())) { logger.info("OwnerAddress not equals OriginAddress"); throw new ContractValidateException("OwnerAddress is not equals OriginAddress"); From 9afbc5dd5386a64b3d9cee3a3021d3b25b1e9424 Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 17 Jun 2022 22:51:02 +0800 Subject: [PATCH 0141/1197] code(vm): remove unused method --- actuator/src/main/java/org/tron/core/vm/program/Program.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 653155f15f8..cfb42fcde6a 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -1062,11 +1062,6 @@ public byte[] getCodeHash() { return codeHash; } - private Key getCodeHashKey() { - byte[] codeHash = getCodeHash(); - return Key.create(codeHash); - } - private Key getJumpDestAnalysisCacheKey() { return Key.create(ByteUtil.merge(codeAddress, getCodeHash())); } From 80caef639b02f763c63f45f021c59141cd7603a0 Mon Sep 17 00:00:00 2001 From: liukai Date: Sun, 19 Jun 2022 16:02:06 +0800 Subject: [PATCH 0142/1197] feature: update version 1. update version to 4.5.1 --- framework/src/main/java/org/tron/program/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index eefcc77c78b..3988f989aa8 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -4,7 +4,7 @@ public class Version { public static final String VERSION_NAME = "GreatVoyage-v4.4.6-241-g7045f0659"; public static final String VERSION_CODE = "16928"; - private static final String VERSION = "4.5.0"; + private static final String VERSION = "4.5.1"; public static String getVersion() { return VERSION; From dd172a8317b47f52a38a3556d43e325341b12191 Mon Sep 17 00:00:00 2001 From: liukai Date: Sun, 19 Jun 2022 18:02:23 +0800 Subject: [PATCH 0143/1197] update a new version. version name:GreatVoyage-v4.4.6-257-ge06abd15c,version code:16944 --- framework/src/main/java/org/tron/program/Version.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 3988f989aa8..944511cbd4e 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,8 +2,8 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.4.6-241-g7045f0659"; - public static final String VERSION_CODE = "16928"; + public static final String VERSION_NAME = "GreatVoyage-v4.4.6-257-ge06abd15c"; + public static final String VERSION_CODE = "16944"; private static final String VERSION = "4.5.1"; public static String getVersion() { From 39feab6d7926794ef00a0e171112f40822a50061 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 21 Jun 2022 18:41:07 +0800 Subject: [PATCH 0144/1197] perf(db): optimize generate block logic --- framework/src/main/java/org/tron/core/db/Manager.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 2a30cadd5b0..3f996737a9b 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1428,6 +1428,12 @@ public synchronized BlockCapsule generateBlock(Miner miner, long blockTime, long MetricLabels.Gauge.QUEUE_REPUSH); } + if (fromPending) { + pendingTransactions.poll(); + Metrics.gaugeInc(MetricKeys.Gauge.MANAGER_QUEUE, -1, + MetricLabels.Gauge.QUEUE_PENDING); + } + if (trx == null) { // transaction may be removed by rePushLoop. logger.warn("Trx is null,fromPending:{},pending:{},repush:{}.", @@ -1474,11 +1480,6 @@ public synchronized BlockCapsule generateBlock(Miner miner, long blockTime, long if (Objects.nonNull(result)) { transactionRetCapsule.addTransactionInfo(result); } - if (fromPending) { - pendingTransactions.poll(); - Metrics.gaugeInc(MetricKeys.Gauge.MANAGER_QUEUE, -1, - MetricLabels.Gauge.QUEUE_PENDING); - } } catch (Exception e) { logger.error("Process trx {} failed when generating block: {}", trx.getTransactionId(), e.getMessage()); From 14cca93678c98365e32ee4da95b05c12a86680ca Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 5 Jul 2022 14:35:43 +0800 Subject: [PATCH 0145/1197] doc(readme): update `Running java-tron`. 1. Add prerequisites 2. Optimize startup script --- README.md | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index b2a699b4451..0a547c5c5c7 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ TRON is a project dedicated to building the infrastructure for a truly decentral TRON enables large-scale development and engagement. With over 2000 transactions per second (TPS), high concurrency, low latency, and massive data transmission. It is ideal for building decentralized entertainment applications. Free features and incentive systems allow developers to create premium app experiences for users. # Building the source -Building java-tron requires `git` and `Oracle JDK 1.8` to be installed, other JDK versions are not supported yet. It is recommended to operate on `Linux` and `OSX` operating systems. +Building java-tron requires `git` and `Oracle JDK 1.8` to be installed, other JDK versions are not supported yet. Make sure you operate on `Linux` and `MacOS` operating systems. ## Getting the Source Code @@ -85,13 +85,33 @@ The `FullNode.jar` file can be found in `java-tron/build/libs/FullNode.jar` afte Get the mainnet configurate file: [main_net_config.conf](https://github.com/tronprotocol/tron-deployment/blob/master/main_net_config.conf), other network configuration files can be find [here](https://github.com/tronprotocol/tron-deployment). +Running java-tron requires `Oracle JDK 1.8` to be installed, other JDK versions are not supported yet. Make sure you operate on `Linux` and `MacOS` operating systems. -* **Running a full node for mainnet** +## Hardware Requirements +* Minimum: + * CPU with 8 cores + * 16GB RAM + * 1TB free storage space to sync the Mainnet +* Recommended: + * CPU with 16+ cores(32+ cores for a super representative) + * 32+ GB RAM(64+ GB for a super representative) + * High Performance SSD with at least 1.5TB free space + * 100+ MB/s download Internet service + + +## Running a full node for mainnet Full node has full historical data, it is the entry point into the TRON network , it can be used by other processes as a gateway into the TRON network via HTTP and GRPC endpoints. You can interact with the TRON network through full node:transfer assets, deploy contracts, interact with contracts and so on. `-c ` parameter specifies a configuration file to run a full node: ```bash - $ java -jar FullNode.jar -c main_net_config.conf + $ nohup java -Xms9G -Xmx9G -XX:ReservedCodeCacheSize=256m \ + -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -XX:MaxDirectMemorySize=1G \ + -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log \ + -XX:+UseConcMarkSweepGC -XX:NewRatio=2 \ + -XX:+CMSScavengeBeforeRemark -XX:+ParallelRefProcEnabled \ + -XX:+HeapDumpOnOutOfMemoryError \ + -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 \ + -jar FullNode.jar -c main_net_config.conf >> start.log 2>&1 & ``` -* **Running a super representative node for mainnet** +## Running a super representative node for mainnet Adding the `--witness` parameter to the startup command, full node will run as a super representative node. The super representative node supports all the functions of the full node and also supports block production. Before running, make sure you have a super representative account and get votes from others,once the number of obtained votes ranks in the top 27, your super representative node will participate in block production. Fill in the private key of super representative address into the `localwitness` list in the `main_net_config.conf`, here is an example: @@ -102,9 +122,16 @@ Get the mainnet configurate file: [main_net_config.conf](https://github.com/tron ``` then run the following command to start the node: - ```bash - $ java -jar FullNode.jar --witness -c main_net_config.conf - ``` + ```bash + $ nohup java -Xms9G -Xmx9G -XX:ReservedCodeCacheSize=256m \ + -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -XX:MaxDirectMemorySize=1G \ + -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log \ + -XX:+UseConcMarkSweepGC -XX:NewRatio=2 \ + -XX:+CMSScavengeBeforeRemark -XX:+ParallelRefProcEnabled \ + -XX:+HeapDumpOnOutOfMemoryError \ + -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 \ + -jar FullNode.jar --witness -c main_net_config.conf >> start.log 2>&1 & + ``` ## Quick Start Tool An easier way to build and run java-tron is to use `start.sh`, `start.sh` is a quick start script written in shell language, you can use it to build and run java-tron quickly and easily. From 16888bef9c8ce2913b0f1d07fd7a4f5c9f690bd3 Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 7 Jul 2022 18:57:51 +0800 Subject: [PATCH 0146/1197] feat(issues template): add new issues 1. add issue templates --- .../{ => ISSUE_TEMPLATE}/ISSUE_TEMPLATE.md | 34 ++++++++++++------- .github/ISSUE_TEMPLATE/report-a-bug.md | 31 +++++++++++++++++ .github/ISSUE_TEMPLATE/request-a-feature.md | 18 ++++++++++ 3 files changed, 70 insertions(+), 13 deletions(-) rename .github/{ => ISSUE_TEMPLATE}/ISSUE_TEMPLATE.md (70%) create mode 100644 .github/ISSUE_TEMPLATE/report-a-bug.md create mode 100644 .github/ISSUE_TEMPLATE/request-a-feature.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE/ISSUE_TEMPLATE.md similarity index 70% rename from .github/ISSUE_TEMPLATE.md rename to .github/ISSUE_TEMPLATE/ISSUE_TEMPLATE.md index 6d82a3ae6a9..2efa22290ea 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE/ISSUE_TEMPLATE.md @@ -1,13 +1,21 @@ - - -### 1. What did you do? - - - -### 2. What did you expect to see? - - - -### 3. What did you see instead? - - +--- +name: Ask a question +about: Something is unclear +title: '' +labels: 'type:docs' +assignees: '' +-- + + + +### 1. What did you do? + + + +### 2. What did you expect to see? + + + +### 3. What did you see instead? + + diff --git a/.github/ISSUE_TEMPLATE/report-a-bug.md b/.github/ISSUE_TEMPLATE/report-a-bug.md new file mode 100644 index 00000000000..1c6ac7b5a68 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/report-a-bug.md @@ -0,0 +1,31 @@ +--- +name: Report a bug +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +#### System information + +Geth version: `geth version` +OS & Version: Windows/Linux/OSX +Commit hash : (if `develop`) + +#### Expected behaviour + + +#### Actual behaviour + + +#### Steps to reproduce the behaviour + + +#### Backtrace + +```` +[backtrace] +```` + +When submitting logs: please submit them as text and not screenshots. diff --git a/.github/ISSUE_TEMPLATE/request-a-feature.md b/.github/ISSUE_TEMPLATE/request-a-feature.md new file mode 100644 index 00000000000..9047b7e6a87 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/request-a-feature.md @@ -0,0 +1,18 @@ +--- +name: Request a feature +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +# Rationale + +Why should this feature exist? +What are the use-cases? + +# Implementation + +Do you have ideas regarding the implementation of this feature? +Are you willing to implement this feature? From 096317a0f363b8c062d53aca4e0fd0772a17cfc7 Mon Sep 17 00:00:00 2001 From: guoquanqu Date: Thu, 7 Jul 2022 14:59:51 +0800 Subject: [PATCH 0147/1197] fix(ci): fix lock compete in RevokingDbWithCacheNewValueTest --- .../core/db2/RevokingDbWithCacheNewValueTest.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/framework/src/test/java/org/tron/core/db2/RevokingDbWithCacheNewValueTest.java b/framework/src/test/java/org/tron/core/db2/RevokingDbWithCacheNewValueTest.java index 28a45be7868..2290df86978 100644 --- a/framework/src/test/java/org/tron/core/db2/RevokingDbWithCacheNewValueTest.java +++ b/framework/src/test/java/org/tron/core/db2/RevokingDbWithCacheNewValueTest.java @@ -7,6 +7,7 @@ import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.RandomStringUtils; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -34,9 +35,12 @@ public class RevokingDbWithCacheNewValueTest { private Application appT; private TestRevokingTronStore tronDatabase; + private String databasePath = ""; + @Before public void init() { - Args.setParam(new String[]{"-d", "output_revokingStore_test"}, + databasePath = "output_revokingStore_test_" + RandomStringUtils.randomAlphanumeric(10); + Args.setParam(new String[]{"-d", databasePath}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); appT = ApplicationFactory.create(context); @@ -47,7 +51,7 @@ public void removeDb() { Args.clearParam(); context.destroy(); tronDatabase.close(); - FileUtil.deleteDir(new File("output_revokingStore_test")); + FileUtil.deleteDir(new File(databasePath)); } @Test @@ -384,7 +388,8 @@ public synchronized void testGetKeysNextWithSameKey() { public synchronized void testGetKeysNextWithSameKeyOrderCheck() { revokingDatabase = context.getBean(SnapshotManager.class); revokingDatabase.enable(); - tronDatabase = new TestRevokingTronStore("testSnapshotManager-testGetKeysNextWithSameKey"); + tronDatabase = new TestRevokingTronStore( + "testSnapshotManager-testGetKeysNextWithSameKeyOrderCheck"); revokingDatabase.add(tronDatabase.getRevokingDB()); while (revokingDatabase.size() != 0) { revokingDatabase.pop(); From 9909ea46a2dc9804ce272c24861b5b3f4053c05f Mon Sep 17 00:00:00 2001 From: liukai Date: Fri, 8 Jul 2022 11:20:49 +0800 Subject: [PATCH 0148/1197] feat(issues template): optimized templates 1. optimised text descriptions --- .github/ISSUE_TEMPLATE/report-a-bug.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/report-a-bug.md b/.github/ISSUE_TEMPLATE/report-a-bug.md index 1c6ac7b5a68..8828a86ee62 100644 --- a/.github/ISSUE_TEMPLATE/report-a-bug.md +++ b/.github/ISSUE_TEMPLATE/report-a-bug.md @@ -9,7 +9,7 @@ assignees: '' #### System information -Geth version: `geth version` +java-tron version: `java-tron release version` OS & Version: Windows/Linux/OSX Commit hash : (if `develop`) From eb76cd57be3cd8bafb5e749f5336e473ef2086cf Mon Sep 17 00:00:00 2001 From: liukai Date: Fri, 8 Jul 2022 11:23:17 +0800 Subject: [PATCH 0149/1197] feat(issues template): optimized templates 1. optimised text descriptions --- .github/ISSUE_TEMPLATE/report-a-bug.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/report-a-bug.md b/.github/ISSUE_TEMPLATE/report-a-bug.md index 8828a86ee62..649d7e97ed1 100644 --- a/.github/ISSUE_TEMPLATE/report-a-bug.md +++ b/.github/ISSUE_TEMPLATE/report-a-bug.md @@ -9,7 +9,7 @@ assignees: '' #### System information -java-tron version: `java-tron release version` +java-tron version: `java -jar FullNode.jar -v` OS & Version: Windows/Linux/OSX Commit hash : (if `develop`) From 64090038ab626ae7719dfd3a2ed4dab5ae34e524 Mon Sep 17 00:00:00 2001 From: liukai Date: Fri, 8 Jul 2022 15:13:20 +0800 Subject: [PATCH 0150/1197] feat(issues template): optimized templates 1. optimised text descriptions --- .../ISSUE_TEMPLATE/{ISSUE_TEMPLATE.md => ask-a-question.md} | 6 ++++++ 1 file changed, 6 insertions(+) rename .github/ISSUE_TEMPLATE/{ISSUE_TEMPLATE.md => ask-a-question.md} (76%) diff --git a/.github/ISSUE_TEMPLATE/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE/ask-a-question.md similarity index 76% rename from .github/ISSUE_TEMPLATE/ISSUE_TEMPLATE.md rename to .github/ISSUE_TEMPLATE/ask-a-question.md index 2efa22290ea..458b790bef7 100644 --- a/.github/ISSUE_TEMPLATE/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE/ask-a-question.md @@ -8,6 +8,12 @@ assignees: '' +### System information + +java-tron version: `java -jar FullNode.jar -v` +OS & Version: Windows/Linux/OSX + + ### 1. What did you do? From 60ecd0bf8832b247e719db8c1f12cbfa5fd30ed8 Mon Sep 17 00:00:00 2001 From: liukai Date: Fri, 8 Jul 2022 16:47:11 +0800 Subject: [PATCH 0151/1197] feat(issues template): optimized templates 1. optimised text descriptions --- .github/ISSUE_TEMPLATE/ask-a-question.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/ask-a-question.md b/.github/ISSUE_TEMPLATE/ask-a-question.md index 458b790bef7..6abae335494 100644 --- a/.github/ISSUE_TEMPLATE/ask-a-question.md +++ b/.github/ISSUE_TEMPLATE/ask-a-question.md @@ -2,7 +2,7 @@ name: Ask a question about: Something is unclear title: '' -labels: 'type:docs' +labels: '' assignees: '' -- From 38d9af6c999ed35cfb2e6a2690ea35495872aa00 Mon Sep 17 00:00:00 2001 From: liukai Date: Fri, 8 Jul 2022 16:50:56 +0800 Subject: [PATCH 0152/1197] feat(issues template): optimized templates 1. optimised text descriptions --- .github/ISSUE_TEMPLATE/ask-a-question.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/ask-a-question.md b/.github/ISSUE_TEMPLATE/ask-a-question.md index 6abae335494..a92239b39eb 100644 --- a/.github/ISSUE_TEMPLATE/ask-a-question.md +++ b/.github/ISSUE_TEMPLATE/ask-a-question.md @@ -4,7 +4,8 @@ about: Something is unclear title: '' labels: '' assignees: '' --- + +--- From ee8f9aec4149c153fff86447e63f1632ef241ad8 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 14 Jul 2022 11:03:56 +0800 Subject: [PATCH 0153/1197] optimize blockLock; MessageQueue does not send message if channel is disconnected --- .../common/overlay/server/ChannelManager.java | 16 ++++++++-------- .../tron/common/overlay/server/MessageQueue.java | 10 ++++++++++ .../org/tron/core/net/service/SyncService.java | 8 ++++---- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java b/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java index dbcb73baa8b..8c452a2f880 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java +++ b/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java @@ -34,7 +34,7 @@ @Component public class ChannelManager { - private final Map activePeers = new ConcurrentHashMap<>(); + private final Map activeChannels = new ConcurrentHashMap<>(); @Autowired private PeerServer peerServer; @Autowired @@ -121,7 +121,7 @@ public void processDisconnect(Channel channel, ReasonCode reason) { public void notifyDisconnect(Channel channel) { syncPool.onDisconnect(channel); - activePeers.values().remove(channel); + activeChannels.values().remove(channel); if (channel != null) { if (channel.getNodeStatistics() != null) { channel.getNodeStatistics().notifyDisconnect(); @@ -146,7 +146,7 @@ public synchronized boolean processPeer(Channel peer) { return false; } - if (!peer.isActive() && activePeers.size() >= maxActivePeers) { + if (!peer.isActive() && activeChannels.size() >= maxActivePeers) { peer.disconnect(TOO_MANY_PEERS); return false; } @@ -157,7 +157,7 @@ public synchronized boolean processPeer(Channel peer) { } } - Channel channel = activePeers.get(peer.getNodeIdWrapper()); + Channel channel = activeChannels.get(peer.getNodeIdWrapper()); if (channel != null) { if (channel.getStartTime() > peer.getStartTime()) { logger.info("Disconnect connection established later, {}", channel.getNode()); @@ -167,14 +167,14 @@ public synchronized boolean processPeer(Channel peer) { return false; } } - activePeers.put(peer.getNodeIdWrapper(), peer); - logger.info("Add active peer {}, total active peers: {}", peer, activePeers.size()); + activeChannels.put(peer.getNodeIdWrapper(), peer); + logger.info("Add active peer {}, total active peers: {}", peer, activeChannels.size()); return true; } public int getConnectionNum(InetAddress inetAddress) { int cnt = 0; - for (Channel channel : activePeers.values()) { + for (Channel channel : activeChannels.values()) { if (channel.getInetAddress().equals(inetAddress)) { cnt++; } @@ -183,7 +183,7 @@ public int getConnectionNum(InetAddress inetAddress) { } public Collection getActivePeers() { - return activePeers.values(); + return activeChannels.values(); } public Cache getRecentlyDisconnected() { diff --git a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java index 1919042232f..3e3fc3b2c44 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java +++ b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java @@ -69,6 +69,11 @@ public void activate(ChannelHandlerContext ctx) { continue; } Message msg = msgQueue.take(); + if (channel.isDisconnect()) { + logger.warn("Failed to send to {} as channel has closed, {}", + ctx.channel().remoteAddress(), msg); + return; + } ctx.writeAndFlush(msg.getSendData()).addListener((ChannelFutureListener) future -> { if (!future.isSuccess() && !channel.isDisconnect()) { logger.warn("Failed to send to {}, {}", ctx.channel().remoteAddress(), msg); @@ -92,6 +97,11 @@ public void setChannel(Channel channel) { } public void fastSend(Message msg) { + if (channel.isDisconnect()) { + logger.warn("Fast send to {} failed as channel has closed, {} ", + ctx.channel().remoteAddress(), msg); + return; + } logger.info("Fast send to {}, {} ", ctx.channel().remoteAddress(), msg); ctx.writeAndFlush(msg.getSendData()).addListener((ChannelFutureListener) future -> { if (!future.isSuccess() && !channel.isDisconnect()) { diff --git a/framework/src/main/java/org/tron/core/net/service/SyncService.java b/framework/src/main/java/org/tron/core/net/service/SyncService.java index 64a721bf014..67c3629d22b 100644 --- a/framework/src/main/java/org/tron/core/net/service/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/SyncService.java @@ -234,8 +234,8 @@ private synchronized void handleSyncBlock() { isProcessed[0] = false; - synchronized (tronNetDelegate.getBlockLock()) { - blockWaitToProcess.forEach((msg, peerConnection) -> { + blockWaitToProcess.forEach((msg, peerConnection) -> { + synchronized (tronNetDelegate.getBlockLock()) { if (peerConnection.isDisconnect()) { blockWaitToProcess.remove(msg); invalid(msg.getBlockId()); @@ -254,8 +254,8 @@ private synchronized void handleSyncBlock() { isProcessed[0] = true; processSyncBlock(msg.getBlockCapsule()); } - }); - } + } + }); } } From 1ceeb014e6bfbfdb95b197779a449e00efb9fbf9 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Thu, 14 Jul 2022 15:27:51 +0800 Subject: [PATCH 0154/1197] feat(version): add jvm & os info to version command --- framework/build.gradle | 1 + .../java/org/tron/core/config/args/Args.java | 26 ++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/framework/build.gradle b/framework/build.gradle index e656c73b01a..7df08a90eb9 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -1,5 +1,6 @@ plugins { id "org.sonarqube" version "2.6" + id "com.gorylenko.gradle-git-properties" version "2.4.1" } apply plugin: 'application' diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index f35b10c8034..c84e013f707 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -14,6 +14,7 @@ import java.io.BufferedReader; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.net.InetAddress; import java.net.Socket; @@ -26,6 +27,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.Properties; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -210,15 +212,33 @@ public static void clearParam() { } + /** + * print Version. + */ + private static void printVersion() { + Properties properties = new Properties(); + try { + InputStream in = Thread.currentThread() + .getContextClassLoader().getResourceAsStream("git.properties"); + properties.load(in); + } catch (IOException e) { + logger.error(e.getMessage()); + } + JCommander.getConsole().println("OS : " + System.getProperty("os.name")); + JCommander.getConsole().println("JVM : " + System.getProperty("java.vendor") + " " + + System.getProperty("java.version") + " " + System.getProperty("os.arch")); + JCommander.getConsole().println("Git : " + properties.getProperty("git.commit.id")); + JCommander.getConsole().println("Version : " + Version.getVersion()); + JCommander.getConsole().println("Code : " + Version.VERSION_CODE); + } + /** * set parameters. */ public static void setParam(final String[] args, final String confFileName) { JCommander.newBuilder().addObject(PARAMETER).build().parse(args); if (PARAMETER.version) { - JCommander.getConsole() - .println(Version.getVersion() - + "\n" + Version.VERSION_NAME + "\n" + Version.VERSION_CODE); + printVersion(); exit(0); } From fe8efd137da3c330e2caa36fa9b222e4490fabb8 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 15 Jul 2022 13:01:06 +0800 Subject: [PATCH 0155/1197] clear message from MessageQueue before channel close --- .../main/java/org/tron/common/overlay/server/MessageQueue.java | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java index 3e3fc3b2c44..a8db0225be4 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java +++ b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java @@ -72,6 +72,7 @@ public void activate(ChannelHandlerContext ctx) { if (channel.isDisconnect()) { logger.warn("Failed to send to {} as channel has closed, {}", ctx.channel().remoteAddress(), msg); + msgQueue.clear(); return; } ctx.writeAndFlush(msg.getSendData()).addListener((ChannelFutureListener) future -> { From 6ccb55406513f8182b01a5c53e930b51f3fc0172 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 18 Jul 2022 15:21:18 +0800 Subject: [PATCH 0156/1197] rollback --- .../org/tron/common/overlay/server/MessageQueue.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java index 3e3fc3b2c44..1919042232f 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java +++ b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java @@ -69,11 +69,6 @@ public void activate(ChannelHandlerContext ctx) { continue; } Message msg = msgQueue.take(); - if (channel.isDisconnect()) { - logger.warn("Failed to send to {} as channel has closed, {}", - ctx.channel().remoteAddress(), msg); - return; - } ctx.writeAndFlush(msg.getSendData()).addListener((ChannelFutureListener) future -> { if (!future.isSuccess() && !channel.isDisconnect()) { logger.warn("Failed to send to {}, {}", ctx.channel().remoteAddress(), msg); @@ -97,11 +92,6 @@ public void setChannel(Channel channel) { } public void fastSend(Message msg) { - if (channel.isDisconnect()) { - logger.warn("Fast send to {} failed as channel has closed, {} ", - ctx.channel().remoteAddress(), msg); - return; - } logger.info("Fast send to {}, {} ", ctx.channel().remoteAddress(), msg); ctx.writeAndFlush(msg.getSendData()).addListener((ChannelFutureListener) future -> { if (!future.isSuccess() && !channel.isDisconnect()) { From 5bcb4e1a413aab400ac7998b08145580a0317a0e Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 18 Jul 2022 15:11:06 +0800 Subject: [PATCH 0157/1197] doc(readme): format docs. --- README.md | 95 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 50 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 0a547c5c5c7..f128ca37dae 100644 --- a/README.md +++ b/README.md @@ -65,72 +65,70 @@ TRON enables large-scale development and engagement. With over 2000 transactions # Building the source Building java-tron requires `git` and `Oracle JDK 1.8` to be installed, other JDK versions are not supported yet. Make sure you operate on `Linux` and `MacOS` operating systems. -## Getting the Source Code +Clone the repo and switch to the `master` branch ```bash $ git clone https://github.com/tronprotocol/java-tron.git + $ cd java-tron $ git checkout -t origin/master ``` - -## Build - +then run the following command to build java-tron, the `FullNode.jar` file can be found in `java-tron/build/libs/` after build successful. ```bash -$ cd java-tron $ ./gradlew clean build -x test ``` -The `FullNode.jar` file can be found in `java-tron/build/libs/FullNode.jar` after build successful. # Running java-tron - -Get the mainnet configurate file: [main_net_config.conf](https://github.com/tronprotocol/tron-deployment/blob/master/main_net_config.conf), other network configuration files can be find [here](https://github.com/tronprotocol/tron-deployment). - Running java-tron requires `Oracle JDK 1.8` to be installed, other JDK versions are not supported yet. Make sure you operate on `Linux` and `MacOS` operating systems. +Get the mainnet configurate file: [main_net_config.conf](https://github.com/tronprotocol/tron-deployment/blob/master/main_net_config.conf), other network configuration files can be find [here](https://github.com/tronprotocol/tron-deployment). ## Hardware Requirements -* Minimum: - * CPU with 8 cores - * 16GB RAM - * 1TB free storage space to sync the Mainnet -* Recommended: - * CPU with 16+ cores(32+ cores for a super representative) - * 32+ GB RAM(64+ GB for a super representative) - * High Performance SSD with at least 1.5TB free space - * 100+ MB/s download Internet service +Minimum: +* CPU with 8 cores +* 16GB RAM +* 1TB free storage space to sync the Mainnet + +Recommended: +* CPU with 16+ cores(32+ cores for a super representative) +* 32GB+ RAM(64GB+ for a super representative) +* High Performance SSD with at least 1.5TB free space +* 100+ MB/s download Internet service ## Running a full node for mainnet - Full node has full historical data, it is the entry point into the TRON network , it can be used by other processes as a gateway into the TRON network via HTTP and GRPC endpoints. You can interact with the TRON network through full node:transfer assets, deploy contracts, interact with contracts and so on. `-c ` parameter specifies a configuration file to run a full node: +Full node has full historical data, it is the entry point into the TRON network , it can be used by other processes as a gateway into the TRON network via HTTP and GRPC endpoints. You can interact with the TRON network through full node:transfer assets, deploy contracts, interact with contracts and so on. `-c ` parameter specifies a configuration file to run a full node: ```bash $ nohup java -Xms9G -Xmx9G -XX:ReservedCodeCacheSize=256m \ - -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -XX:MaxDirectMemorySize=1G \ - -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log \ - -XX:+UseConcMarkSweepGC -XX:NewRatio=2 \ - -XX:+CMSScavengeBeforeRemark -XX:+ParallelRefProcEnabled \ - -XX:+HeapDumpOnOutOfMemoryError \ - -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 \ - -jar FullNode.jar -c main_net_config.conf >> start.log 2>&1 & + -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m \ + -XX:MaxDirectMemorySize=1G -XX:+PrintGCDetails \ + -XX:+PrintGCDateStamps -Xloggc:gc.log \ + -XX:+UseConcMarkSweepGC -XX:NewRatio=2 \ + -XX:+CMSScavengeBeforeRemark -XX:+ParallelRefProcEnabled \ + -XX:+HeapDumpOnOutOfMemoryError \ + -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 \ + -jar FullNode.jar -c main_net_config.conf >> start.log 2>&1 & ``` -## Running a super representative node for mainnet - Adding the `--witness` parameter to the startup command, full node will run as a super representative node. The super representative node supports all the functions of the full node and also supports block production. Before running, make sure you have a super representative account and get votes from others,once the number of obtained votes ranks in the top 27, your super representative node will participate in block production. +## Running a super representative node for mainnet +Adding the `--witness` parameter to the startup command, full node will run as a super representative node. The super representative node supports all the functions of the full node and also supports block production. Before running, make sure you have a super representative account and get votes from others,once the number of obtained votes ranks in the top 27, your super representative node will participate in block production. - Fill in the private key of super representative address into the `localwitness` list in the `main_net_config.conf`, here is an example: +Fill in the private key of super representative address into the `localwitness` list in the `main_net_config.conf`, here is an example: ``` localwitness = [ 650950B193DDDDB35B6E48912DD28F7AB0E7140C1BFDEFD493348F02295BD812 ] ``` - then run the following command to start the node: +then run the following command to start the node: ```bash $ nohup java -Xms9G -Xmx9G -XX:ReservedCodeCacheSize=256m \ - -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -XX:MaxDirectMemorySize=1G \ - -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log \ - -XX:+UseConcMarkSweepGC -XX:NewRatio=2 \ - -XX:+CMSScavengeBeforeRemark -XX:+ParallelRefProcEnabled \ - -XX:+HeapDumpOnOutOfMemoryError \ - -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 \ - -jar FullNode.jar --witness -c main_net_config.conf >> start.log 2>&1 & + -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m \ + -XX:MaxDirectMemorySize=1G -XX:+PrintGCDetails \ + -XX:+PrintGCDateStamps -Xloggc:gc.log \ + -XX:+UseConcMarkSweepGC -XX:NewRatio=2 \ + -XX:+CMSScavengeBeforeRemark -XX:+ParallelRefProcEnabled \ + -XX:+HeapDumpOnOutOfMemoryError \ + -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 \ + -jar FullNode.jar --witness -c main_net_config.conf >> start.log 2>&1 & ``` ## Quick Start Tool @@ -143,16 +141,16 @@ Here are some common use cases of the scripting tool For more details, please refer to the tool [guide](./shell.md). -## Run inside Docker container +## Run inside Docker container One of the quickest ways to get `java-tron` up and running on your machine is by using Docker: ```shell $ docker run -d --name="java-tron" \ - -v /your_path/output-directory:/java-tron/output-directory \ - -v /your_path/logs:/java-tron/logs \ - -p 8090:8090 -p 18888:18888 -p 50051:50051 \ - tronprotocol/java-tron \ - -c /java-tron/config/main_net_config.conf + -v /your_path/output-directory:/java-tron/output-directory \ + -v /your_path/logs:/java-tron/logs \ + -p 8090:8090 -p 18888:18888 -p 50051:50051 \ + tronprotocol/java-tron \ + -c /java-tron/config/main_net_config.conf ``` This will mount the `output-directory` and `logs` directories on the host, the docker.sh tool can also be used to simplify the use of docker, see more [here](docker/docker.md). @@ -165,9 +163,8 @@ This will mount the `output-directory` and `logs` directories on the host, the d [tronprotocol/allcoredev](https://gitter.im/tronprotocol/allcoredev) is the official Gitter channel for developers. # Contribution -If you'd like to contribute to java-tron, please read the following instructions. +Thank you for considering to help out with the source code! If you'd like to contribute to java-tron, please see the [Contribution Guide](./CONTRIBUTING.md) for more details. -- [Contribution](./CONTRIBUTING.md) # Resources * [Medium](https://medium.com/@coredevs) java-tron's official technical articles are published there. @@ -180,3 +177,11 @@ If you'd like to contribute to java-tron, please read the following instructions # License java-tron is released under the [LGPLv3 license](https://github.com/tronprotocol/java-tron/blob/master/LICENSE). + + + +The minimum hardware requirements are `CPU with 8 cores`,`16GB RAM` and `1TB free storage space` to sync the Mainnet, the recommended hardware requirements: +* CPU with 16+ cores(32+ cores for a super representative) +* 32+ GB RAM(64+ GB for a super representative) +* High Performance SSD with at least 1.5TB free space +* 100+ MB/s download Internet service From cfec5b1fd571eacb7b343a483e0acd88ed4238b8 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 18 Jul 2022 15:32:32 +0800 Subject: [PATCH 0158/1197] rollback --- .../common/overlay/server/ChannelManager.java | 16 ++++++++-------- .../org/tron/core/net/service/SyncService.java | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java b/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java index 8c452a2f880..dbcb73baa8b 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java +++ b/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java @@ -34,7 +34,7 @@ @Component public class ChannelManager { - private final Map activeChannels = new ConcurrentHashMap<>(); + private final Map activePeers = new ConcurrentHashMap<>(); @Autowired private PeerServer peerServer; @Autowired @@ -121,7 +121,7 @@ public void processDisconnect(Channel channel, ReasonCode reason) { public void notifyDisconnect(Channel channel) { syncPool.onDisconnect(channel); - activeChannels.values().remove(channel); + activePeers.values().remove(channel); if (channel != null) { if (channel.getNodeStatistics() != null) { channel.getNodeStatistics().notifyDisconnect(); @@ -146,7 +146,7 @@ public synchronized boolean processPeer(Channel peer) { return false; } - if (!peer.isActive() && activeChannels.size() >= maxActivePeers) { + if (!peer.isActive() && activePeers.size() >= maxActivePeers) { peer.disconnect(TOO_MANY_PEERS); return false; } @@ -157,7 +157,7 @@ public synchronized boolean processPeer(Channel peer) { } } - Channel channel = activeChannels.get(peer.getNodeIdWrapper()); + Channel channel = activePeers.get(peer.getNodeIdWrapper()); if (channel != null) { if (channel.getStartTime() > peer.getStartTime()) { logger.info("Disconnect connection established later, {}", channel.getNode()); @@ -167,14 +167,14 @@ public synchronized boolean processPeer(Channel peer) { return false; } } - activeChannels.put(peer.getNodeIdWrapper(), peer); - logger.info("Add active peer {}, total active peers: {}", peer, activeChannels.size()); + activePeers.put(peer.getNodeIdWrapper(), peer); + logger.info("Add active peer {}, total active peers: {}", peer, activePeers.size()); return true; } public int getConnectionNum(InetAddress inetAddress) { int cnt = 0; - for (Channel channel : activeChannels.values()) { + for (Channel channel : activePeers.values()) { if (channel.getInetAddress().equals(inetAddress)) { cnt++; } @@ -183,7 +183,7 @@ public int getConnectionNum(InetAddress inetAddress) { } public Collection getActivePeers() { - return activeChannels.values(); + return activePeers.values(); } public Cache getRecentlyDisconnected() { diff --git a/framework/src/main/java/org/tron/core/net/service/SyncService.java b/framework/src/main/java/org/tron/core/net/service/SyncService.java index 67c3629d22b..64a721bf014 100644 --- a/framework/src/main/java/org/tron/core/net/service/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/SyncService.java @@ -234,8 +234,8 @@ private synchronized void handleSyncBlock() { isProcessed[0] = false; - blockWaitToProcess.forEach((msg, peerConnection) -> { - synchronized (tronNetDelegate.getBlockLock()) { + synchronized (tronNetDelegate.getBlockLock()) { + blockWaitToProcess.forEach((msg, peerConnection) -> { if (peerConnection.isDisconnect()) { blockWaitToProcess.remove(msg); invalid(msg.getBlockId()); @@ -254,8 +254,8 @@ private synchronized void handleSyncBlock() { isProcessed[0] = true; processSyncBlock(msg.getBlockCapsule()); } - } - }); + }); + } } } From 9c9efdf4bfa30cd7d0cd5a5a9f34c9e445ecc926 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 29 Jun 2022 17:27:45 +0800 Subject: [PATCH 0159/1197] fix(db): Chainbase::prefixQuerySnapshot. --- .../leveldb/LevelDbDataSourceImpl.java | 1 + .../rocksdb/RocksDbDataSourceImpl.java | 1 + .../java/org/tron/core/db/TronDatabase.java | 8 +- .../tron/core/db/common/DbSourceInter.java | 2 + .../org/tron/core/db2/core/Chainbase.java | 27 ++- .../org/tron/core/db2/core/SnapshotImpl.java | 13 ++ .../leveldb/LevelDbDataSourceImplTest.java | 38 ++++ .../leveldb/RocksDbDataSourceImplTest.java | 38 ++++ .../java/org/tron/core/db2/ChainbaseTest.java | 171 ++++++++++++++++++ 9 files changed, 276 insertions(+), 23 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/db2/ChainbaseTest.java diff --git a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java index 41c5b165739..936d089573e 100644 --- a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java @@ -352,6 +352,7 @@ public Map getNext(byte[] key, long limit) { } } + @Override public Map prefixQuery(byte[] key) { resetDbLock.readLock().lock(); try (DBIterator iterator = getDBIterator()) { diff --git a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java index 42ca5ce2b5c..82bd8505e52 100644 --- a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java @@ -431,6 +431,7 @@ public Map getNext(byte[] key, long limit) { } } + @Override public Map prefixQuery(byte[] key) { if (quitIfNotAlive()) { return null; diff --git a/chainbase/src/main/java/org/tron/core/db/TronDatabase.java b/chainbase/src/main/java/org/tron/core/db/TronDatabase.java index f373fcd3df3..9373189941a 100644 --- a/chainbase/src/main/java/org/tron/core/db/TronDatabase.java +++ b/chainbase/src/main/java/org/tron/core/db/TronDatabase.java @@ -110,13 +110,7 @@ public T getUnchecked(byte[] key) { } public Map prefixQuery(byte[] key) { - Map result = new HashMap<>(); - if (dbSource.getClass() == LevelDbDataSourceImpl.class) { - result = ((LevelDbDataSourceImpl) dbSource).prefixQuery(key); - } else if (dbSource.getClass() == RocksDbDataSourceImpl.class) { - result = ((RocksDbDataSourceImpl) dbSource).prefixQuery(key); - } - return result; + return dbSource.prefixQuery(key); } public abstract boolean has(byte[] key); diff --git a/chainbase/src/main/java/org/tron/core/db/common/DbSourceInter.java b/chainbase/src/main/java/org/tron/core/db/common/DbSourceInter.java index 3b1f266b8a2..0823b7a7cf4 100755 --- a/chainbase/src/main/java/org/tron/core/db/common/DbSourceInter.java +++ b/chainbase/src/main/java/org/tron/core/db/common/DbSourceInter.java @@ -46,4 +46,6 @@ public interface DbSourceInter extends BatchSourceInter, void stat(); + Map prefixQuery(byte[] key); + } diff --git a/chainbase/src/main/java/org/tron/core/db2/core/Chainbase.java b/chainbase/src/main/java/org/tron/core/db2/core/Chainbase.java index 8489e4e8532..17a047f78ae 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/Chainbase.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/Chainbase.java @@ -12,8 +12,8 @@ import java.util.Set; import java.util.stream.Collectors; -import com.google.common.primitives.Bytes; import org.tron.common.utils.ByteUtil; +import org.tron.common.utils.Pair; import org.tron.core.capsule.utils.MarketUtils; import org.tron.core.db2.common.IRevokingDB; import org.tron.core.db2.common.LevelDB; @@ -350,13 +350,14 @@ private Map getNext(Snapshot head, byte[] key, long limit) { } public Map prefixQuery(byte[] key) { - Map resultSnapshot = prefixQuerySnapshot(key); - Map resultDB = prefixQueryDB(key); - resultDB.putAll(resultSnapshot); - return resultDB; + Map result = prefixQueryRoot(key); + Map snapshot = prefixQuerySnapshot(key); + result.putAll(snapshot); + result.entrySet().removeIf(e -> e.getValue() == null); + return result; } - private Map prefixQueryDB(byte[] key) { + private Map prefixQueryRoot(byte[] key) { Map result = new HashMap<>(); if (((SnapshotRoot) head.getRoot()).db.getClass() == LevelDB.class) { result = ((LevelDB) ((SnapshotRoot) head.getRoot()).db).getDb().prefixQuery(key); @@ -369,16 +370,10 @@ private Map prefixQueryDB(byte[] key) { private Map prefixQuerySnapshot(byte[] key) { Map result = new HashMap<>(); Snapshot snapshot = head(); - while (!snapshot.equals(head.getRoot())) { - Iterator> iterator = snapshot.iterator(); - while (iterator.hasNext()) { - Map.Entry entry = iterator.next(); - WrappedByteArray ks = WrappedByteArray.of(entry.getKey()); - if (Bytes.indexOf(entry.getKey(), key) == 0 && !result.containsKey(ks)) { - result.put(ks, entry.getValue()); - } - } - snapshot = snapshot.getPrevious(); + if (!snapshot.equals(head.getRoot())) { + Map all = new HashMap<>(); + ((SnapshotImpl) snapshot).collect(all, key); + all.forEach((k, v) -> result.put(k, v.getBytes())); } return result; } diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotImpl.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotImpl.java index d71c97ccf73..83c55c238ea 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotImpl.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotImpl.java @@ -4,10 +4,12 @@ import com.google.common.collect.Iterators; import com.google.common.collect.Maps; import com.google.common.collect.Streams; +import com.google.common.primitives.Bytes; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; +import java.util.Objects; import java.util.Set; import lombok.Getter; import org.tron.core.db2.common.HashDB; @@ -129,6 +131,17 @@ synchronized void collect(Map all) { } } + synchronized void collect(Map all, byte[] prefix) { + Snapshot next = getRoot().getNext(); + while (next != null) { + Streams.stream(((SnapshotImpl) next).db).filter(e -> Bytes.indexOf( + Objects.requireNonNull(e.getKey().getBytes()), prefix) == 0) + .forEach(e -> all.put(WrappedByteArray.of(e.getKey().getBytes()), + WrappedByteArray.of(e.getValue().getBytes()))); + next = next.getNext(); + } + } + /** * Note: old --> new * In the snapshot, there may be same keys. diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java index f19f927c953..7cc85c37be1 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; import org.junit.Assert; @@ -41,6 +42,7 @@ import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.config.args.Args; +import org.tron.core.db2.common.WrappedByteArray; @Slf4j public class LevelDbDataSourceImplTest { @@ -312,4 +314,40 @@ public void getKeysNext() { dataSource.resetDb(); dataSource.closeDB(); } + + @Test + public void prefixQueryTest() { + LevelDbDataSourceImpl dataSource = new LevelDbDataSourceImpl( + Args.getInstance().getOutputDirectory(), "test_prefixQuery"); + dataSource.initDB(); + dataSource.resetDb(); + + putSomeKeyValue(dataSource); + // put a kv that will not be queried. + byte[] key7 = "0000001".getBytes(); + byte[] value7 = "0000001v".getBytes(); + dataSource.putData(key7, value7); + + byte[] prefix = "0000000".getBytes(); + + List result = dataSource.prefixQuery(prefix) + .keySet() + .stream() + .map(WrappedByteArray::getBytes) + .map(ByteArray::toStr) + .collect(Collectors.toList()); + List list = Arrays.asList( + ByteArray.toStr(key1), + ByteArray.toStr(key2), + ByteArray.toStr(key3), + ByteArray.toStr(key4), + ByteArray.toStr(key5), + ByteArray.toStr(key6)); + + Assert.assertEquals(list.size(), result.size()); + list.forEach(entry -> Assert.assertTrue(result.contains(entry))); + + dataSource.resetDb(); + dataSource.closeDB(); + } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java index e872b4ddfab..0e628500870 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java @@ -14,6 +14,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; import org.junit.Assert; @@ -25,6 +26,7 @@ import org.tron.common.utils.FileUtil; import org.tron.common.utils.PropUtil; import org.tron.core.config.args.Args; +import org.tron.core.db2.common.WrappedByteArray; @Slf4j public class RocksDbDataSourceImplTest { @@ -360,4 +362,40 @@ public void getKeysNext() { dataSource.resetDb(); dataSource.closeDB(); } + + @Test + public void prefixQueryTest() { + RocksDbDataSourceImpl dataSource = new RocksDbDataSourceImpl( + Args.getInstance().getOutputDirectory(), "test_prefixQuery"); + dataSource.initDB(); + dataSource.resetDb(); + + putSomeKeyValue(dataSource); + // put a kv that will not be queried. + byte[] key7 = "0000001".getBytes(); + byte[] value7 = "0000001v".getBytes(); + dataSource.putData(key7, value7); + + byte[] prefix = "0000000".getBytes(); + + List result = dataSource.prefixQuery(prefix) + .keySet() + .stream() + .map(WrappedByteArray::getBytes) + .map(ByteArray::toStr) + .collect(Collectors.toList()); + List list = Arrays.asList( + ByteArray.toStr(key1), + ByteArray.toStr(key2), + ByteArray.toStr(key3), + ByteArray.toStr(key4), + ByteArray.toStr(key5), + ByteArray.toStr(key6)); + + Assert.assertEquals(list.size(), result.size()); + list.forEach(entry -> Assert.assertTrue(result.contains(entry))); + + dataSource.resetDb(); + dataSource.closeDB(); + } } diff --git a/framework/src/test/java/org/tron/core/db2/ChainbaseTest.java b/framework/src/test/java/org/tron/core/db2/ChainbaseTest.java new file mode 100644 index 00000000000..86e3bfefe6b --- /dev/null +++ b/framework/src/test/java/org/tron/core/db2/ChainbaseTest.java @@ -0,0 +1,171 @@ +package org.tron.core.db2; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.rocksdb.RocksDB; +import org.tron.common.storage.leveldb.LevelDbDataSourceImpl; +import org.tron.common.storage.rocksdb.RocksDbDataSourceImpl; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.core.Constant; +import org.tron.core.config.args.Args; +import org.tron.core.db.common.DbSourceInter; +import org.tron.core.db2.common.LevelDB; +import org.tron.core.db2.core.Chainbase; +import org.tron.core.db2.core.Snapshot; +import org.tron.core.db2.core.SnapshotRoot; + +@Slf4j +public class ChainbaseTest { + + private static final String dbPath = "output-chainbase-test"; + private Chainbase chainbase = null; + + private final byte[] value0 = "00000".getBytes(); + private final byte[] value1 = "10000".getBytes(); + private final byte[] value2 = "20000".getBytes(); + private final byte[] value3 = "30000".getBytes(); + private final byte[] value4 = "40000".getBytes(); + private final byte[] value5 = "50000".getBytes(); + private final byte[] value6 = "60000".getBytes(); + private final byte[] value7 = "70000".getBytes(); + private final byte[] value8 = "80000".getBytes(); + private final byte[] valueRoot7 = "root70000".getBytes(); + private final byte[] valueRoot8 = "root80000".getBytes(); + private final byte[] value9 = "90000".getBytes(); + + private final byte[] key0 = "0aa".getBytes(); + private final byte[] key1 = "10000001aa".getBytes(); + private final byte[] key2 = "10000002aa".getBytes(); + private final byte[] key3 = "10000003aa".getBytes(); + private final byte[] key4 = "10000004aa".getBytes(); + private final byte[] key5 = "10000005aa".getBytes(); + private final byte[] key6 = "10000006aa".getBytes(); + private final byte[] key7 = "10000006ac".getBytes(); + private final byte[] key8 = "10000006ab".getBytes(); + private final byte[] key9 = "10000006dd".getBytes(); + + private final byte[] prefix = "1000000".getBytes(); + private final byte[] prefix2 = "2000000".getBytes(); + private final byte[] prefix3 = "0000000".getBytes(); + + /** + * Release resources. + */ + @AfterClass + public static void destroy() { + Args.clearParam(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.info("Release resources failure."); + } + } + + @Before + public void initDb() { + RocksDB.loadLibrary(); + Args.setParam(new String[] {"--output-directory", dbPath}, Constant.TEST_CONF); + } + + @Test + public void testPrefixQueryForLeveldb() { + LevelDbDataSourceImpl dataSource = new LevelDbDataSourceImpl( + Args.getInstance().getOutputDirectory(), "testPrefixQueryForLeveldb"); + dataSource.initDB(); + this.chainbase = new Chainbase(new SnapshotRoot( + new LevelDB(dataSource))); + testDb(chainbase); + testRoot(dataSource); + chainbase.reset(); + chainbase.close(); + } + + @Test + public void testPrefixQueryForRocksdb() { + RocksDbDataSourceImpl dataSource = new RocksDbDataSourceImpl( + Args.getInstance().getOutputDirectory(), "testPrefixQueryForRocksdb"); + dataSource.initDB(); + this.chainbase = new Chainbase(new SnapshotRoot( + new org.tron.core.db2.common.RocksDB(dataSource))); + testDb(chainbase); + testRoot(dataSource); + chainbase.reset(); + chainbase.close(); + } + + + private void testRoot(DbSourceInter dbSource) { + Map result = new HashMap<>(); + dbSource.prefixQuery(prefix).forEach((k, v) -> + result.put(ByteArray.toStr(k.getBytes()), ByteArray.toStr(v))); + + Map expect = new HashMap<>(); + expect.put(ByteArray.toStr(key2),ByteArray.toStr(value2)); + expect.put(ByteArray.toStr(key6),ByteArray.toStr(value6)); + expect.put(ByteArray.toStr(key7),ByteArray.toStr(valueRoot7)); + expect.put(ByteArray.toStr(key8),ByteArray.toStr(valueRoot8)); + Assert.assertEquals(expect, result); + Assert.assertTrue(dbSource.prefixQuery(prefix2).isEmpty()); + Assert.assertTrue(dbSource.prefixQuery(prefix3).isEmpty()); + } + + private void testDb(Chainbase chainbase) { + byte[] keyNotQuery1 = "123".getBytes(); + byte[] keyNotQuery2 = "0000001".getBytes(); + byte[] valueNotQuery1 = "v123".getBytes(); + byte[] valueNotQuery2 = "v0000001".getBytes(); + + chainbase.setHead(chainbase.getHead().advance()); + Snapshot head = chainbase.getHead(); + Snapshot root = head.getRoot(); + // put some data in head + head.put(key0, value0); + head.put(key1, value1); + head.put(key7, value7); + head.put(key3, value3); + head.put(key8, value8); + head.remove(key7); + // put some data in root + root.put(key2, value2); + root.put(key6, value6); + root.put(key3, value3); + root.put(key7, valueRoot7); + root.put(key8, valueRoot8); + root.put(keyNotQuery1, valueNotQuery1); + // advance head and put some data again + head = head.advance(); + head.put(key4, value4); + head.put(key5, value5); + head.put(key9,value9); + head.remove(key8); + head.put(keyNotQuery2, valueNotQuery2); + + head = head.advance(); + head.remove(key9); + root.remove(key3); + + // test for all, both in snapshotImpl and leveldb + Map result = new HashMap<>(); + chainbase.prefixQuery(prefix).forEach((k, v) -> + result.put(ByteArray.toStr(k.getBytes()), ByteArray.toStr(v))); + + Map expect = new HashMap<>(); + expect.put(ByteArray.toStr(key1),ByteArray.toStr(value1)); + expect.put(ByteArray.toStr(key2),ByteArray.toStr(value2)); + expect.put(ByteArray.toStr(key3),ByteArray.toStr(value3)); + expect.put(ByteArray.toStr(key4),ByteArray.toStr(value4)); + expect.put(ByteArray.toStr(key5),ByteArray.toStr(value5)); + expect.put(ByteArray.toStr(key6),ByteArray.toStr(value6)); + Assert.assertEquals(expect, result); + Assert.assertTrue(chainbase.prefixQuery(prefix2).isEmpty()); + Assert.assertTrue(chainbase.prefixQuery(prefix3).isEmpty()); + } + +} \ No newline at end of file From f8e3289bce79569515f65f1e3dedf508d1898502 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 19 Jul 2022 12:07:19 +0800 Subject: [PATCH 0160/1197] fix(net): solve DB item not fund problem when process sync message --- .../messagehandler/SyncBlockChainMsgHandler.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java index 65702c435f8..9f392b11e40 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java @@ -92,13 +92,19 @@ private LinkedList getLostBlockIds(List blockIds) throws P2pEx throw new P2pException(TypeEnum.SYNC_FAILED, "unForkId is null"); } - long len = Math.min(tronNetDelegate.getHeadBlockId().getNum(), - unForkId.getNum() + NetConstants.SYNC_FETCH_BATCH_NUM); + BlockId headID = tronNetDelegate.getHeadBlockId(); + long headNum = headID.getNum(); + + long len = Math.min(headNum, unForkId.getNum() + NetConstants.SYNC_FETCH_BATCH_NUM); LinkedList ids = new LinkedList<>(); for (long i = unForkId.getNum(); i <= len; i++) { - BlockId id = tronNetDelegate.getBlockIdByNum(i); - ids.add(id); + if (i == headNum) { + ids.add(headID); + } else { + BlockId id = tronNetDelegate.getBlockIdByNum(i); + ids.add(id); + } } return ids; } From 2c690054fe73e220ff466f3d4c6e509cef33ad77 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 14 Jul 2022 10:42:00 +0800 Subject: [PATCH 0161/1197] api(block):add query header --- .../org/tron/common/utils/WalletUtil.java | 8 ++ .../src/main/java/org/tron/core/Wallet.java | 44 ++++++++++ .../org/tron/core/services/RpcApiService.java | 29 +++++++ .../services/http/FullNodeHttpApiService.java | 5 +- .../core/services/http/GetBlockServlet.java | 86 +++++++++++++++++++ .../solidity/SolidityNodeHttpApiService.java | 6 +- .../interfaceOnPBFT/RpcApiServiceOnPBFT.java | 7 ++ .../http/PBFT/GetBlockOnPBFTServlet.java | 26 ++++++ .../http/PBFT/HttpApiOnPBFTService.java | 5 ++ .../RpcApiServiceOnSolidity.java | 7 ++ .../http/GetBlockOnSolidityServlet.java | 26 ++++++ .../solidity/HttpApiOnSolidityService.java | 7 ++ protocol/src/main/protos/api/api.proto | 9 ++ 13 files changed, 263 insertions(+), 2 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/services/http/GetBlockServlet.java create mode 100644 framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/GetBlockOnPBFTServlet.java create mode 100644 framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetBlockOnSolidityServlet.java diff --git a/chainbase/src/main/java/org/tron/common/utils/WalletUtil.java b/chainbase/src/main/java/org/tron/common/utils/WalletUtil.java index bd367393405..36f09ba6cc7 100644 --- a/chainbase/src/main/java/org/tron/common/utils/WalletUtil.java +++ b/chainbase/src/main/java/org/tron/common/utils/WalletUtil.java @@ -131,4 +131,12 @@ public static byte[] getSelector(byte[] data) { return ret; } + public static Long isLong(String s) { + try { + return Long.parseLong(s); + } catch (NumberFormatException ignored) { + return null; + } + } + } diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 9150e4e0528..29c61082681 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -53,6 +53,7 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; +import org.bouncycastle.util.encoders.DecoderException; import org.bouncycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -4018,5 +4019,48 @@ public boolean isMining() { public Chainbase.Cursor getCursor() { return chainBaseManager.getBlockStore().getRevokingDB().getCursor(); } + + public Block getBlock(GrpcAPI.BlockMessage request) { + Block block; + long head = chainBaseManager.getHeadBlockNum(); + if (!request.getIdOrNum().isEmpty()) { + Long num = WalletUtil.isLong(request.getIdOrNum()); + if (num != null) { + // quickly check + if (num > head) { + return null; + } + if (num < 0) { + throw new IllegalArgumentException("num must be non-positive number."); + } + block = getBlockByNum(num); + } else { + RuntimeException e = new IllegalArgumentException("id must be legal block hash."); + try { + ByteString id = ByteString.copyFrom(ByteArray.fromHexString(request.getIdOrNum())); + if (id.size() == Sha256Hash.LENGTH) { + num = new BlockId(Sha256Hash.wrap(id)).getNum(); + // quickly check + if (num > head || num < 0) { + throw e; + } + block = getBlockById(id); + } else { + throw e; + } + } catch (DecoderException ignored) { + throw e; + } + } + } else { + block = getNowBlock(); + } + if (Objects.isNull(block) || block.getTransactionsList().isEmpty() + || request.getDetail()) { + return block; + } + return block.toBuilder().clearTransactions().build(); + } + } diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 9c7fe772679..ac791428999 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -907,6 +907,12 @@ public void getTransactionInfoByBlockNum(NumberMessage request, responseObserver.onCompleted(); } + + @Override + public void getBlock(GrpcAPI.BlockMessage request, + StreamObserver responseObserver) { + getBlockCommon(request, responseObserver); + } } /** @@ -2657,6 +2663,13 @@ public void getPendingSize(EmptyMessage request, StreamObserver responseObserver) { getPendingSizeCommon(request, responseObserver); } + + + @Override + public void getBlock(GrpcAPI.BlockMessage request, + StreamObserver responseObserver) { + getBlockCommon(request, responseObserver); + } } public class MonitorApi extends MonitorGrpc.MonitorImplBase { @@ -2774,4 +2787,20 @@ public void getPendingSizeCommon(EmptyMessage request, } responseObserver.onCompleted(); } + + public void getBlockCommon(GrpcAPI.BlockMessage request, + StreamObserver responseObserver) { + try { + responseObserver.onNext(block2Extention(wallet.getBlock(request))); + } catch (Exception e) { + if (e instanceof IllegalArgumentException) { + responseObserver.onError(Status.INVALID_ARGUMENT.withDescription(e.getMessage()) + .withCause(e).asRuntimeException()); + } else { + responseObserver.onError(getRunTimeException(e)); + } + } + responseObserver.onCompleted(); + } + } diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index 40890fc7c79..98e8bc88614 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -290,6 +290,9 @@ public class FullNodeHttpApiService implements Service { @Autowired private GetEnergyPricesServlet getEnergyPricesServlet; + @Autowired + private GetBlockServlet getBlockServlet; + private static String getParamsFile(String fileName) { InputStream in = Thread.currentThread().getContextClassLoader() .getResourceAsStream("params" + File.separator + fileName); @@ -535,7 +538,7 @@ public void start() { "/wallet/gettransactionlistfrompending"); context.addServlet(new ServletHolder(getPendingSizeServlet), "/wallet/getpendingsize"); context.addServlet(new ServletHolder(getEnergyPricesServlet), "/wallet/getenergyprices"); - + context.addServlet(new ServletHolder(getBlockServlet), "/wallet/getblock"); int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { server.addBean(new ConnectionLimit(maxHttpConnectNumber, server)); diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockServlet.java new file mode 100644 index 00000000000..4856946a8ed --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockServlet.java @@ -0,0 +1,86 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.google.common.base.Strings; +import java.io.IOException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.eclipse.jetty.http.HttpMethod; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.api.GrpcAPI.BlockMessage; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Block; + + +@Component +@Slf4j(topic = "API") +public class GetBlockServlet extends RateLimiterServlet { + + @Autowired + private Wallet wallet; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + handle(request, response); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + handle(request, response); + } + + private void handle(HttpServletRequest request, HttpServletResponse response) { + try { + PostParams params = parseParams(request); + BlockMessage message = buildRequest(params.getParams(), params.isVisible()); + fillResponse(params.isVisible(), message, response); + } catch (Exception e) { + Util.processError(e, response); + } + } + + private PostParams parseParams(HttpServletRequest request) throws Exception { + HttpMethod m = HttpMethod.fromString(request.getMethod()); + if (HttpMethod.GET.equals(m)) { + String idOrNum = request.getParameter("idOrNum"); + JSONObject params = new JSONObject(); + if (!Strings.isNullOrEmpty(idOrNum)) { + params.put("idOrNum", idOrNum); + } + params.put("detail", Boolean.parseBoolean(request.getParameter("detail"))); + return new PostParams(JSON.toJSONString(params), + Boolean.parseBoolean(request.getParameter(Util.VISIBLE))); + } + if (HttpMethod.POST.equals(m)) { + return PostParams.getPostParams(request); + } + throw new UnsupportedOperationException(); + } + + private BlockMessage buildRequest(String params, boolean visible) + throws JsonFormat.ParseException { + BlockMessage.Builder build = BlockMessage.newBuilder(); + if (!Strings.isNullOrEmpty(params)) { + JsonFormat.merge(params, build, visible); + } + return build.build(); + } + + private void fillResponse(boolean visible, BlockMessage request, HttpServletResponse response) + throws IOException { + try { + Block reply = wallet.getBlock(request); + if (reply != null) { + response.getWriter().println(Util.printBlock(reply, visible)); + } else { + response.getWriter().println("{}"); + } + } catch (IllegalArgumentException e) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("Error", e.getMessage()); + response.getWriter().println(jsonObject.toJSONString()); + } + } + +} diff --git a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java index 6210f542370..7453c833c10 100644 --- a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java @@ -27,6 +27,7 @@ import org.tron.core.services.http.GetBlockByLatestNumServlet; import org.tron.core.services.http.GetBlockByLimitNextServlet; import org.tron.core.services.http.GetBlockByNumServlet; +import org.tron.core.services.http.GetBlockServlet; import org.tron.core.services.http.GetBrokerageServlet; import org.tron.core.services.http.GetBurnTrxServlet; import org.tron.core.services.http.GetDelegatedResourceAccountIndexServlet; @@ -149,6 +150,9 @@ public class SolidityNodeHttpApiService implements Service { @Autowired private HttpApiAccessFilter httpApiAccessFilter; + @Autowired + private GetBlockServlet getBlockServlet; + @Override public void init() { } @@ -250,7 +254,7 @@ public void start() { context.addServlet(new ServletHolder(getBrokerageServlet), "/walletsolidity/getBrokerage"); context.addServlet(new ServletHolder(getRewardServlet), "/walletsolidity/getReward"); context.addServlet(new ServletHolder(getBurnTrxServlet), "/walletsolidity/getburntrx"); - + context.addServlet(new ServletHolder(getBlockServlet), "/walletsolidity/getblock"); // http access filter context.addFilter(new FilterHolder(httpApiAccessFilter), "/walletsolidity/*", EnumSet.allOf(DispatcherType.class)); diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java index 01a06b4eb34..b92cd4d3041 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java @@ -503,5 +503,12 @@ public void getBurnTrx(EmptyMessage request, StreamObserver respo ); } + @Override + public void getBlock(GrpcAPI.BlockMessage request, + StreamObserver responseObserver) { + walletOnPBFT.futureGet( + () -> rpcApiService.getWalletSolidityApi().getBlock(request, responseObserver)); + } + } } diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/GetBlockOnPBFTServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/GetBlockOnPBFTServlet.java new file mode 100644 index 00000000000..3207ebcf161 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/GetBlockOnPBFTServlet.java @@ -0,0 +1,26 @@ +package org.tron.core.services.interfaceOnPBFT.http.PBFT; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetBlockServlet; +import org.tron.core.services.interfaceOnPBFT.WalletOnPBFT; + + +@Component +@Slf4j(topic = "API") +public class GetBlockOnPBFTServlet extends GetBlockServlet { + + @Autowired + private WalletOnPBFT walletOnPBFT; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java index 9a953a2adb2..13b356deba1 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java @@ -151,6 +151,9 @@ public class HttpApiOnPBFTService implements Service { @Autowired private GetEnergyPricesOnPBFTServlet getEnergyPricesOnPBFTServlet; + @Autowired + private GetBlockOnPBFTServlet getBlockOnPBFTServlet; + @Override public void init() { @@ -237,6 +240,8 @@ public void start() { "/getburntrx"); context.addServlet(new ServletHolder(getEnergyPricesOnPBFTServlet), "/getenergyprices"); + context.addServlet(new ServletHolder(getBlockOnPBFTServlet), + "/getblock"); int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java index 71438de0670..1e37fdb0e8f 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java @@ -499,5 +499,12 @@ public void getBurnTrx(EmptyMessage request, StreamObserver respo ); } + @Override + public void getBlock(GrpcAPI.BlockMessage request, + StreamObserver responseObserver) { + walletOnSolidity.futureGet( + () -> rpcApiService.getWalletSolidityApi().getBlock(request, responseObserver)); + } + } } diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetBlockOnSolidityServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetBlockOnSolidityServlet.java new file mode 100644 index 00000000000..e00f8e91e62 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetBlockOnSolidityServlet.java @@ -0,0 +1,26 @@ +package org.tron.core.services.interfaceOnSolidity.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetBlockServlet; +import org.tron.core.services.interfaceOnSolidity.WalletOnSolidity; + + +@Component +@Slf4j(topic = "API") +public class GetBlockOnSolidityServlet extends GetBlockServlet { + + @Autowired + private WalletOnSolidity walletOnSolidity; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doPost(request, response)); + } +} \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java index 2541773876a..8f6d293a28b 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java @@ -26,6 +26,7 @@ import org.tron.core.services.interfaceOnSolidity.http.GetBlockByLatestNumOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetBlockByLimitNextOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetBlockByNumOnSolidityServlet; +import org.tron.core.services.interfaceOnSolidity.http.GetBlockOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetBrokerageOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetBurnTrxOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetDelegatedResourceAccountIndexOnSolidityServlet; @@ -156,6 +157,9 @@ public class HttpApiOnSolidityService implements Service { @Autowired private HttpApiAccessFilter httpApiAccessFilter; + @Autowired + private GetBlockOnSolidityServlet getBlockOnSolidityServlet; + @Override public void init() { @@ -258,6 +262,9 @@ public void start() { context.addServlet(new ServletHolder(getEnergyPricesOnSolidityServlet), "/walletsolidity/getenergyprices"); + context.addServlet(new ServletHolder(getBlockOnSolidityServlet), + "/walletsolidity/getblock"); + // filters the specified APIs // when node is lite fullnode and openHistoryQueryWhenLiteFN is false context.addFilter(new FilterHolder(liteFnQueryHttpFilter), "/*", diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 5f697026c10..63eca1a4a29 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -789,6 +789,9 @@ service Wallet { rpc GetPendingSize (EmptyMessage) returns (NumberMessage) { } + + rpc GetBlock (BlockMessage) returns (BlockExtention) { + } }; service WalletSolidity { @@ -974,6 +977,8 @@ service WalletSolidity { rpc GetBurnTrx (EmptyMessage) returns (NumberMessage) { } + rpc GetBlock (BlockMessage) returns (BlockExtention) { + } }; service WalletExtension { @@ -1123,6 +1128,10 @@ message TimeMessage { int64 beginInMilliseconds = 1; int64 endInMilliseconds = 2; } +message BlockMessage { + string idOrNum = 1; + bool detail = 2; +} message BlockLimit { int64 startNum = 1; int64 endNum = 2; From 11989068126304661d8c9e2bc15b3db17479aec9 Mon Sep 17 00:00:00 2001 From: liukai Date: Wed, 20 Jul 2022 14:55:50 +0800 Subject: [PATCH 0162/1197] feat(p2p): modify process message 1. modify exception capture range --- .../messagehandler/ChainInventoryMsgHandler.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java index 94c3868b9c7..3f4b3baaa25 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java @@ -63,18 +63,18 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep peer.getSyncBlockToFetch().addAll(blockIdWeGet); synchronized (tronNetDelegate.getBlockLock()) { - while (!peer.getSyncBlockToFetch().isEmpty() && tronNetDelegate - .containBlock(peer.getSyncBlockToFetch().peek())) { - try { + try { + while (!peer.getSyncBlockToFetch().isEmpty() && tronNetDelegate + .containBlock(peer.getSyncBlockToFetch().peek())) { BlockId blockId = peer.getSyncBlockToFetch().pop(); peer.setBlockBothHave(blockId); logger.info("Block {} from {} is processed", blockId.getString(), peer.getNode().getHost()); - } catch (NoSuchElementException e) { - logger.warn("Process ChainInventoryMessage failed, peer {}, isDisconnect:{}", - peer.getNode().getHost(), peer.isDisconnect()); - return; } + } catch (NoSuchElementException e) { + logger.warn("Process ChainInventoryMessage failed, peer {}, isDisconnect:{}", + peer.getNode().getHost(), peer.isDisconnect()); + return; } } From af0b86fb1269a739131f3a9d139b9a050464e5c8 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 20 Jul 2022 17:32:50 +0800 Subject: [PATCH 0163/1197] perf(net): optimize block synchronization logic --- .../src/main/java/org/tron/common/overlay/server/Channel.java | 1 + .../core/net/messagehandler/ChainInventoryMsgHandler.java | 2 ++ .../src/main/java/org/tron/core/net/service/SyncService.java | 4 ++++ 3 files changed, 7 insertions(+) diff --git a/framework/src/main/java/org/tron/common/overlay/server/Channel.java b/framework/src/main/java/org/tron/common/overlay/server/Channel.java index 0846ff61251..68ff3174f22 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/Channel.java +++ b/framework/src/main/java/org/tron/common/overlay/server/Channel.java @@ -61,6 +61,7 @@ public class Channel { private InetSocketAddress inetSocketAddress; private Node node; private long startTime; + @Getter private TronState tronState = TronState.INIT; private boolean isActive; @Getter diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java index 94c3868b9c7..a8a541d7804 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java @@ -11,6 +11,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.common.overlay.server.Channel; import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.config.Parameter.ChainConstant; import org.tron.core.config.Parameter.NetConstants; @@ -46,6 +47,7 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep Deque blockIdWeGet = new LinkedList<>(chainInventoryMessage.getBlockIds()); if (blockIdWeGet.size() == 1 && tronNetDelegate.containBlock(blockIdWeGet.peek())) { + peer.setTronState(Channel.TronState.SYNC_COMPLETED); peer.setNeedSyncFromPeer(false); return; } diff --git a/framework/src/main/java/org/tron/core/net/service/SyncService.java b/framework/src/main/java/org/tron/core/net/service/SyncService.java index 64a721bf014..49dc9ce2d7a 100644 --- a/framework/src/main/java/org/tron/core/net/service/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/SyncService.java @@ -92,6 +92,10 @@ public void close() { } public void startSync(PeerConnection peer) { + if (peer.getTronState().equals(TronState.SYNCING)) { + logger.warn("Start sync failed, peer {} is in sync.", peer.getNode().getHost()); + return; + } peer.setTronState(TronState.SYNCING); peer.setNeedSyncFromPeer(true); peer.getSyncBlockToFetch().clear(); From 3f6b1db07d176b3c7ce0cb71ba8b6ef074ad3913 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 22 Jul 2022 10:42:02 +0800 Subject: [PATCH 0164/1197] fix error that use ZMQ.Socket to send data may fail in multithreads with rare rates --- .../logsfilter/nativequeue/NativeMessageQueue.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java b/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java index 61be8e84fb7..cf2fe6dce0a 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java +++ b/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java @@ -1,10 +1,12 @@ package org.tron.common.logsfilter.nativequeue; import java.util.Objects; +import lombok.extern.slf4j.Slf4j; import org.zeromq.SocketType; import org.zeromq.ZContext; import org.zeromq.ZMQ; +@Slf4j public class NativeMessageQueue { private static final int DEFAULT_BIND_PORT = 5555; @@ -61,7 +63,12 @@ public void publishTrigger(String data, String topic) { return; } - publisher.sendMore(topic); - publisher.send(data); + try { + publisher.sendMore(topic); + publisher.send(data); + } catch (RuntimeException e) { + logger.error("write data to zeromq failed, data:{}, topic:{}, error:{}", data, topic, + e.getMessage()); + } } } From b927f739557dd2a0f690657b1249569507981509 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 22 Jul 2022 10:49:43 +0800 Subject: [PATCH 0165/1197] rollback --- .../org/tron/common/overlay/server/MessageQueue.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java index a8db0225be4..1919042232f 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java +++ b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java @@ -69,12 +69,6 @@ public void activate(ChannelHandlerContext ctx) { continue; } Message msg = msgQueue.take(); - if (channel.isDisconnect()) { - logger.warn("Failed to send to {} as channel has closed, {}", - ctx.channel().remoteAddress(), msg); - msgQueue.clear(); - return; - } ctx.writeAndFlush(msg.getSendData()).addListener((ChannelFutureListener) future -> { if (!future.isSuccess() && !channel.isDisconnect()) { logger.warn("Failed to send to {}, {}", ctx.channel().remoteAddress(), msg); @@ -98,11 +92,6 @@ public void setChannel(Channel channel) { } public void fastSend(Message msg) { - if (channel.isDisconnect()) { - logger.warn("Fast send to {} failed as channel has closed, {} ", - ctx.channel().remoteAddress(), msg); - return; - } logger.info("Fast send to {}, {} ", ctx.channel().remoteAddress(), msg); ctx.writeAndFlush(msg.getSendData()).addListener((ChannelFutureListener) future -> { if (!future.isSuccess() && !channel.isDisconnect()) { From 78864562d6aedd7e2113625f56499a6dfdcc3594 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 25 Jul 2022 17:09:59 +0800 Subject: [PATCH 0166/1197] fix(lite):fix merge function. --- framework/src/main/java/org/tron/core/db/Manager.java | 2 ++ .../org/tron/tool/litefullnode/LiteFullNodeTool.java | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 2d0f85a94d0..09812092d66 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -489,6 +489,8 @@ public void init() { long headNum = chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber(); logger.info("current headNum is: {}", headNum); + int nodeType = chainBaseManager.getCommonStore().getNodeType(); + logger.info("node type is: {}", Constant.NODE_TYPE_LIGHT_NODE == nodeType ? "lite" : "full"); revokingStore.enable(); validateSignService = Executors .newFixedThreadPool(Args.getInstance().getValidateSignThreadNum()); diff --git a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java index 82bc50ad3da..17f4a4d81e4 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java @@ -209,7 +209,7 @@ private void split(String sourceDir, String destDir, List dbs) throws IO if (new File(destDir).exists()) { throw new RuntimeException("destDir is already exist, please remove it first"); } - if (!destPath.mkdir()) { + if (!destPath.mkdirs()) { throw new RuntimeException("destDir create failed, please check"); } Util.copyDatabases(Paths.get(sourceDir), Paths.get(destDir), dbs); @@ -486,9 +486,15 @@ private static boolean isEmptyBytes(byte[] b) { return true; } - private void deleteSnapshotFlag(String databaseDir) throws IOException { + private void deleteSnapshotFlag(String databaseDir) throws IOException, RocksDBException { logger.info("-- delete the info file to identify this node is a real fullnode."); Files.delete(Paths.get(databaseDir, INFO_FILE_NAME)); + + DBInterface destCommonDb = DbTool.getDB(databaseDir, COMMON_DB_NAME); + destCommonDb.delete(DB_KEY_NODE_TYPE); + destCommonDb.delete(DB_KEY_LOWEST_BLOCK_NUM); + logger.info("-- deleted node_type and lowest_block_num from " + + "common to identify this node is a real fullnode."); } private void run(Args argv) { From d83b65ce4fc919473fda4ad2b6d924c2488b7c65 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 26 Jul 2022 11:10:00 +0800 Subject: [PATCH 0167/1197] resolve sonarlint error of tronState --- .../src/main/java/org/tron/common/overlay/server/Channel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/main/java/org/tron/common/overlay/server/Channel.java b/framework/src/main/java/org/tron/common/overlay/server/Channel.java index 0846ff61251..68ff3174f22 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/Channel.java +++ b/framework/src/main/java/org/tron/common/overlay/server/Channel.java @@ -61,6 +61,7 @@ public class Channel { private InetSocketAddress inetSocketAddress; private Node node; private long startTime; + @Getter private TronState tronState = TronState.INIT; private boolean isActive; @Getter From 2eb91bfa09153237ad7bc75069af880f50a03a7a Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 26 Jul 2022 11:28:44 +0800 Subject: [PATCH 0168/1197] perf(net): speed up TCP connection establishment --- Tron protobuf protocol document.md | 2 +- .../common/parameter/CommonParameter.java | 22 ++- .../src/main/java/org/tron/core/Constant.java | 15 +-- .../common/overlay/server/ChannelManager.java | 12 +- .../server/PeerConnectionCheckService.java | 127 ++++++------------ .../tron/common/overlay/server/SyncPool.java | 24 ++-- .../java/org/tron/core/config/args/Args.java | 45 +++---- .../tron/core/services/NodeInfoService.java | 4 +- .../src/main/resources/config-backup.conf | 2 - framework/src/main/resources/config-beta.conf | 3 - .../src/main/resources/config-localtest.conf | 10 +- .../src/main/resources/config-test-net.conf | 10 +- framework/src/main/resources/config.conf | 17 +-- .../org/tron/core/config/args/ArgsTest.java | 2 +- .../src/test/resources/config-localtest.conf | 10 +- .../test/resources/config-test-dbbackup.conf | 10 +- .../src/test/resources/config-test-index.conf | 2 - .../test/resources/config-test-mainnet.conf | 4 +- .../resources/config-test-storagetest.conf | 4 +- framework/src/test/resources/config-test.conf | 2 - ...inese version of TRON Protocol document.md | 4 +- ...glish version of TRON Protocol document.md | 4 +- protocol/src/main/protos/core/Tron.proto | 2 +- 23 files changed, 118 insertions(+), 219 deletions(-) diff --git a/Tron protobuf protocol document.md b/Tron protobuf protocol document.md index 6a97805b22e..be9558a1d93 100644 --- a/Tron protobuf protocol document.md +++ b/Tron protobuf protocol document.md @@ -2019,7 +2019,7 @@ message `SmartContract` has mutiple attributes and nested message `ABI` TOO_MANY_PEERS = 0x04; DUPLICATE_PEER = 0x05; INCOMPATIBLE_PROTOCOL = 0x06; - NULL_IDENTITY = 0x07; + RANDOM_ELIMINATION = 0x07; PEER_QUITING = 0x08; UNEXPECTED_IDENTITY = 0x09; LOCAL_IDENTITY = 0x0A; diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index df4cf35f71c..6daf213e672 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -129,10 +129,16 @@ public class CommonParameter { public int nodeChannelReadTimeout; @Getter @Setter - public int nodeMaxActiveNodes; + public int maxConnections; @Getter @Setter - public int nodeMaxActiveNodesWithSameIp; + public int minConnections; + @Getter + @Setter + public int minActiveConnections; + @Getter + @Setter + public int maxConnectionsWithSameIp; @Getter @Setter public int minParticipationRate; @@ -286,18 +292,6 @@ public class CommonParameter { public List backupMembers; @Getter @Setter - public double connectFactor; - @Getter - @Setter - public double activeConnectFactor; - @Getter - @Setter - public double disconnectNumberFactor; - @Getter - @Setter - public double maxConnectNumberFactor; - @Getter - @Setter public long receiveTcpMinDataLength; @Getter @Setter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index d0a557ccf44..1eb10792600 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -83,8 +83,11 @@ public class Constant { public static final String NODE_CONNECTION_TIMEOUT = "node.connection.timeout"; public static final String NODE_FETCH_BLOCK_TIMEOUT = "node.fetchBlock.timeout"; public static final String NODE_CHANNEL_READ_TIMEOUT = "node.channel.read.timeout"; - public static final String NODE_MAX_ACTIVE_NODES = "node.maxActiveNodes"; - public static final String NODE_MAX_ACTIVE_NODES_WITH_SAMEIP = "node.maxActiveNodesWithSameIp"; + public static final String NODE_MAX_CONNECTIONS = "node.maxConnections"; + public static final String NODE_MIN_CONNECTIONS = "node.minConnections"; + public static final String NODE_MIN_ACTIVE_CONNECTIONS = "node.minActiveConnections"; + + public static final String NODE_MAX_ACTIVE_NODES_WITH_SAMEIP = "node.maxConnectionsWithSameIp"; public static final String NODE_MIN_PARTICIPATION_RATE = "node.minParticipationRate"; public static final String NODE_LISTEN_PORT = "node.listen.port"; public static final String NODE_DISCOVERY_PUBLIC_HOME_NODE = "node.discovery.public.home.node"; @@ -160,14 +163,6 @@ public class Constant { public static final String NODE_WALLET_EXTENSION_API = "node.walletExtensionApi"; - public static final String NODE_CONNECT_FACTOR = "node.connectFactor"; - - public static final String NODE_ACTIVE_CONNECT_FACTOR = "node.activeConnectFactor"; - - public static final String NODE_DISCONNECT_NUMBER_FACTOR = "node.disconnectNumberFactor"; - - public static final String NODE_MAX_CONNECT_NUMBER_FACTOR = "node.maxConnectNumberFactor"; - public static final String NODE_RECEIVE_TCP_MIN_DATA_LENGTH = "node.receiveTcpMinDataLength"; public static final String NODE_IS_OPEN_FULL_TCP_DISCONNECT = "node.isOpenFullTcpDisconnect"; diff --git a/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java b/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java index dbcb73baa8b..114df13d847 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java +++ b/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java @@ -42,6 +42,8 @@ public class ChannelManager { @Autowired private SyncPool syncPool; @Autowired + private PeerConnectionCheckService peerConnectionCheckService; + @Autowired private FastForward fastForward; private CommonParameter parameter = CommonParameter.getInstance(); private Cache badPeers = CacheBuilder.newBuilder().maximumSize(10000) @@ -63,9 +65,9 @@ public class ChannelManager { @Getter private Map fastForwardNodes = new ConcurrentHashMap(); - private int maxActivePeers = parameter.getNodeMaxActiveNodes(); + private int maxConnections = parameter.getMaxConnections(); - private int getMaxActivePeersWithSameIp = parameter.getNodeMaxActiveNodesWithSameIp(); + private int maxConnectionsWithSameIp = parameter.getMaxConnectionsWithSameIp(); public void init() { if (this.parameter.getNodeListenPort() > 0) { @@ -94,6 +96,7 @@ public void init() { logger.info("Node config, trust {}, active {}, forward {}.", trustNodes.size(), activeNodes.size(), fastForwardNodes.size()); + peerConnectionCheckService.init(); syncPool.init(); fastForward.init(); } @@ -146,12 +149,12 @@ public synchronized boolean processPeer(Channel peer) { return false; } - if (!peer.isActive() && activePeers.size() >= maxActivePeers) { + if (!peer.isActive() && activePeers.size() >= maxConnections) { peer.disconnect(TOO_MANY_PEERS); return false; } - if (getConnectionNum(peer.getInetAddress()) >= getMaxActivePeersWithSameIp) { + if (getConnectionNum(peer.getInetAddress()) >= maxConnectionsWithSameIp) { peer.disconnect(TOO_MANY_PEERS_WITH_SAME_IP); return false; } @@ -195,6 +198,7 @@ public Cache getBadPeers() { } public void close() { + peerConnectionCheckService.close(); syncPool.close(); peerServer.close(); peerClient.close(); diff --git a/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java b/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java index a02825e31e0..edd18bd9ed0 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java +++ b/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java @@ -1,114 +1,69 @@ package org.tron.common.overlay.server; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; +import java.util.Collection; import java.util.List; +import java.util.Random; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.tron.common.overlay.discover.node.statistics.NodeStatistics; -import org.tron.common.utils.CollectionUtils; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.net.peer.PeerConnection; -import org.tron.protos.Protocol.ReasonCode; +import org.tron.protos.Protocol; @Slf4j(topic = "net") @Service public class PeerConnectionCheckService { - - public static final long CHECK_TIME = 5 * 60 * 1000L; - private double disconnectNumberFactor = Args.getInstance().getDisconnectNumberFactor(); - private double maxConnectNumberFactor = Args.getInstance().getMaxConnectNumberFactor(); - - @Autowired - private SyncPool pool; - - @Autowired - private ChannelManager channelManager; + private int p2pVersion = Args.getInstance().getNodeP2pVersion(); + private int maxConnections = Args.getInstance().getMaxConnections(); + private int minActiveConnections = Args.getInstance().getMinActiveConnections(); + private boolean isFastForward = Args.getInstance().isFastForward(); + private boolean isOpenFullTcpDisconnect = Args.getInstance().isOpenFullTcpDisconnect(); + private ScheduledExecutorService poolLoopExecutor = Executors.newSingleThreadScheduledExecutor(); @Autowired - private Manager manager; + private SyncPool syncPool; - private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2, - r -> new Thread(r, "check-peer-connect")); - - @PostConstruct - public void check() { - logger.info("start the PeerConnectionCheckService"); - scheduledExecutorService - .scheduleWithFixedDelay(new CheckDataTransferTask(), 5, 5, TimeUnit.MINUTES); - if (Args.getInstance().isOpenFullTcpDisconnect()) { - scheduledExecutorService - .scheduleWithFixedDelay(new CheckConnectNumberTask(), 4, 1, TimeUnit.MINUTES); + public void init() { + if (isFastForward || !isOpenFullTcpDisconnect) { + return; } + logger.info("Start peer connection check service."); + poolLoopExecutor.scheduleWithFixedDelay(() -> { + try { + check(); + } catch (Throwable t) { + logger.error("Exception in peer connection check.", t); + } + }, 10, 30, TimeUnit.SECONDS); } - @PreDestroy - public void destroy() { - scheduledExecutorService.shutdown(); + public void close() { + logger.info("Close peer connection check service."); + poolLoopExecutor.shutdown(); } - private class CheckDataTransferTask implements Runnable { - - @Override - public void run() { - List peerConnectionList = pool.getActivePeers(); - List willDisconnectPeerList = new ArrayList<>(); - for (PeerConnection peerConnection : peerConnectionList) { - NodeStatistics nodeStatistics = peerConnection.getNodeStatistics(); - if (!nodeStatistics.nodeIsHaveDataTransfer() - && System.currentTimeMillis() - peerConnection.getStartTime() >= CHECK_TIME - && !peerConnection.isTrustPeer() - && !nodeStatistics.isPredefined()) { - //if xxx minutes not have data transfer,disconnect the peer, - //exclude trust peer and active peer - willDisconnectPeerList.add(peerConnection); - } - nodeStatistics.resetTcpFlow(); - } - if (!willDisconnectPeerList.isEmpty() && peerConnectionList.size() - > Args.getInstance().getNodeMaxActiveNodes() * maxConnectNumberFactor) { - Collections.shuffle(willDisconnectPeerList); - for (int i = 0; i < willDisconnectPeerList.size() * disconnectNumberFactor; i++) { - logger.warn("{} does not have data transfer, disconnect the peer", - willDisconnectPeerList.get(i).getInetAddress()); - willDisconnectPeerList.get(i).disconnect(ReasonCode.TOO_MANY_PEERS); - } - } + public void check() { + if (syncPool.getActivePeers().size() < maxConnections) { + return; } - } - - private class CheckConnectNumberTask implements Runnable { - - @Override - public void run() { - if (pool.getActivePeers().size() >= Args.getInstance().getNodeMaxActiveNodes()) { - logger.warn("connection pool is full"); - List peerList = new ArrayList<>(); - for (PeerConnection peer : pool.getActivePeers()) { - if (!peer.isTrustPeer() && !peer.getNodeStatistics().isPredefined()) { - peerList.add(peer); - } - } - if (peerList.size() >= 2) { - peerList.sort( - Comparator.comparingInt((PeerConnection o) -> o.getNodeStatistics().getReputation())); - peerList = CollectionUtils.truncateRandom(peerList, 2, 1); - } - for (PeerConnection peerConnection : peerList) { - logger.warn("connection pool is full, disconnect the peer: {}", - peerConnection.getInetAddress()); - peerConnection.disconnect(ReasonCode.RESET); - } - } + boolean flag = syncPool.getActivePeersCount().get() > minActiveConnections * 2; + Collection peers = syncPool.getActivePeers().stream() + .filter(peer -> peer.isIdle()) + .filter(peer -> !peer.isTrustPeer()) + .filter(peer -> !peer.getNode().isConnectible(p2pVersion)) + .filter(peer -> peer.isActive() == flag) + .collect(Collectors.toList()); + if (peers.size() == 0) { + return; } + List list = new ArrayList(); + peers.forEach(p -> list.add(p)); + PeerConnection peer = list.get(new Random().nextInt(peers.size())); + peer.disconnect(Protocol.ReasonCode.RANDOM_ELIMINATION); } - } diff --git a/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java b/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java index 410266d07fa..4c35f6b628d 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java +++ b/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java @@ -16,6 +16,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Predicate; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; @@ -37,15 +38,12 @@ @Slf4j(topic = "net") @Component public class SyncPool { - private final List activePeers = Collections .synchronizedList(new ArrayList<>()); - private final AtomicInteger passivePeersCount = new AtomicInteger(0); - private final AtomicInteger activePeersCount = new AtomicInteger(0); - private double factor = Args.getInstance().getConnectFactor(); - private double activeFactor = Args.getInstance().getActiveConnectFactor(); private Cache nodeHandlerCache = CacheBuilder.newBuilder() .maximumSize(1000).expireAfterWrite(180, TimeUnit.SECONDS).recordStats().build(); + private final AtomicInteger passivePeersCount = new AtomicInteger(0); + private final AtomicInteger activePeersCount = new AtomicInteger(0); @Autowired private NodeManager nodeManager; @@ -60,9 +58,7 @@ public class SyncPool { private CommonParameter commonParameter = CommonParameter.getInstance(); - private int maxActiveNodes = commonParameter.getNodeMaxActiveNodes(); - - private int maxActivePeersWithSameIp = commonParameter.getNodeMaxActiveNodesWithSameIp(); + private int maxConnectionsWithSameIp = commonParameter.getMaxConnectionsWithSameIp(); private ScheduledExecutorService poolLoopExecutor = Executors.newSingleThreadScheduledExecutor(); @@ -72,6 +68,10 @@ public class SyncPool { private int disconnectTimeout = 60_000; + private int maxConnections = Args.getInstance().getMaxConnections(); + private int minConnections = Args.getInstance().getMinConnections(); + private int minActiveConnections = Args.getInstance().getMinActiveConnections(); + public void init() { channelManager = ctx.getBean(ChannelManager.class); @@ -123,8 +123,8 @@ private void fillUp() { } }); - int size = Math.max((int) (maxActiveNodes * factor) - activePeers.size(), - (int) (maxActiveNodes * activeFactor - activePeersCount.get())); + int size = Math.max(minConnections - activePeers.size(), + minActiveConnections - activePeersCount.get()); int lackSize = size - connectNodes.size(); if (lackSize > 0) { nodesInUse.add(nodeManager.getPublicHomeNode().getHexId()); @@ -212,7 +212,7 @@ public synchronized void onDisconnect(Channel peer) { } public boolean isCanConnect() { - return passivePeersCount.get() < maxActiveNodes * (1 - activeFactor); + return passivePeersCount.get() < maxConnections - minActiveConnections; } public void close() { @@ -250,7 +250,7 @@ public boolean test(NodeHandler handler) { && handler.getNode().getPort() == nodeManager.getPublicHomeNode().getPort()) || (channelManager.getRecentlyDisconnected().getIfPresent(inetAddress) != null) || (channelManager.getBadPeers().getIfPresent(inetAddress) != null) - || (channelManager.getConnectionNum(inetAddress) >= maxActivePeersWithSameIp) + || (channelManager.getConnectionNum(inetAddress) >= maxConnectionsWithSameIp) || (nodesInUse.contains(handler.getNode().getHexId())) || (nodeHandlerCache.getIfPresent(handler) != null) || (message != null && headNum < message.getLowestBlockNum())); diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index c84e013f707..0e2482e7f37 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -116,14 +116,16 @@ public static void clearParam() { PARAMETER.needSyncCheck = false; PARAMETER.nodeDiscoveryEnable = false; PARAMETER.nodeDiscoveryPersist = false; - PARAMETER.nodeConnectionTimeout = 0; + PARAMETER.nodeConnectionTimeout = 2000; PARAMETER.activeNodes = Collections.emptyList(); PARAMETER.passiveNodes = Collections.emptyList(); PARAMETER.fastForwardNodes = Collections.emptyList(); PARAMETER.maxFastForwardNum = 3; PARAMETER.nodeChannelReadTimeout = 0; - PARAMETER.nodeMaxActiveNodes = 30; - PARAMETER.nodeMaxActiveNodesWithSameIp = 2; + PARAMETER.maxConnections = 30; + PARAMETER.minConnections = 8; + PARAMETER.minActiveConnections = 3; + PARAMETER.maxConnectionsWithSameIp = 2; PARAMETER.minParticipationRate = 0; PARAMETER.nodeListenPort = 0; PARAMETER.nodeDiscoveryBindIp = ""; @@ -158,10 +160,6 @@ public static void clearParam() { PARAMETER.solidityNode = false; PARAMETER.trustNodeAddr = ""; PARAMETER.walletExtensionApi = false; - PARAMETER.connectFactor = 0.3; - PARAMETER.activeConnectFactor = 0.1; - PARAMETER.disconnectNumberFactor = 0.4; - PARAMETER.maxConnectNumberFactor = 0.8; PARAMETER.receiveTcpMinDataLength = 2048; PARAMETER.isOpenFullTcpDisconnect = false; PARAMETER.supportConstant = false; @@ -448,7 +446,7 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.nodeConnectionTimeout = config.hasPath(Constant.NODE_CONNECTION_TIMEOUT) ? config.getInt(Constant.NODE_CONNECTION_TIMEOUT) * 1000 - : 0; + : 2000; if (!config.hasPath(Constant.NODE_FETCH_BLOCK_TIMEOUT)) { PARAMETER.fetchBlockTimeout = 200; @@ -465,11 +463,19 @@ public static void setParam(final String[] args, final String confFileName) { ? config.getInt(Constant.NODE_CHANNEL_READ_TIMEOUT) : 0; - PARAMETER.nodeMaxActiveNodes = - config.hasPath(Constant.NODE_MAX_ACTIVE_NODES) - ? config.getInt(Constant.NODE_MAX_ACTIVE_NODES) : 30; + PARAMETER.maxConnections = + config.hasPath(Constant.NODE_MAX_CONNECTIONS) + ? config.getInt(Constant.NODE_MAX_CONNECTIONS) : 30; + + PARAMETER.minConnections = + config.hasPath(Constant.NODE_MIN_CONNECTIONS) + ? config.getInt(Constant.NODE_MIN_CONNECTIONS) : 8; + + PARAMETER.minActiveConnections = + config.hasPath(Constant.NODE_MIN_ACTIVE_CONNECTIONS) + ? config.getInt(Constant.NODE_MIN_ACTIVE_CONNECTIONS) : 3; - PARAMETER.nodeMaxActiveNodesWithSameIp = + PARAMETER.maxConnectionsWithSameIp = config.hasPath(Constant.NODE_MAX_ACTIVE_NODES_WITH_SAMEIP) ? config .getInt(Constant.NODE_MAX_ACTIVE_NODES_WITH_SAMEIP) : 2; @@ -659,17 +665,6 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.NODE_WALLET_EXTENSION_API) && config.getBoolean(Constant.NODE_WALLET_EXTENSION_API); - PARAMETER.connectFactor = - config.hasPath(Constant.NODE_CONNECT_FACTOR) - ? config.getDouble(Constant.NODE_CONNECT_FACTOR) : 0.3; - - PARAMETER.activeConnectFactor = config.hasPath(Constant.NODE_ACTIVE_CONNECT_FACTOR) - ? config.getDouble(Constant.NODE_ACTIVE_CONNECT_FACTOR) : 0.1; - - PARAMETER.disconnectNumberFactor = config.hasPath(Constant.NODE_DISCONNECT_NUMBER_FACTOR) - ? config.getDouble(Constant.NODE_DISCONNECT_NUMBER_FACTOR) : 0.4; - PARAMETER.maxConnectNumberFactor = config.hasPath(Constant.NODE_MAX_CONNECT_NUMBER_FACTOR) - ? config.getDouble(Constant.NODE_MAX_CONNECT_NUMBER_FACTOR) : 0.8; PARAMETER.receiveTcpMinDataLength = config.hasPath(Constant.NODE_RECEIVE_TCP_MIN_DATA_LENGTH) ? config.getLong(Constant.NODE_RECEIVE_TCP_MIN_DATA_LENGTH) : 2048; PARAMETER.isOpenFullTcpDisconnect = config.hasPath(Constant.NODE_IS_OPEN_FULL_TCP_DISCONNECT) @@ -1236,8 +1231,8 @@ public static void logConfig() { logger.info("FastForward node size: {}", parameter.getFastForwardNodes().size()); logger.info("FastForward node number: {}", parameter.getMaxFastForwardNum()); logger.info("Seed node size: {}", parameter.getSeedNode().getIpList().size()); - logger.info("Max connection: {}", parameter.getNodeMaxActiveNodes()); - logger.info("Max connection with same IP: {}", parameter.getNodeMaxActiveNodesWithSameIp()); + logger.info("Max connection: {}", parameter.getMaxConnections()); + logger.info("Max connection with same IP: {}", parameter.getMaxConnectionsWithSameIp()); logger.info("Solidity threads: {}", parameter.getSolidityThreads()); logger.info("Trx reference block: {}", parameter.getTrxReferenceBlock()); logger.info("************************ Backup config ************************"); diff --git a/framework/src/main/java/org/tron/core/services/NodeInfoService.java b/framework/src/main/java/org/tron/core/services/NodeInfoService.java index acf7a29d052..79aff5b8a71 100644 --- a/framework/src/main/java/org/tron/core/services/NodeInfoService.java +++ b/framework/src/main/java/org/tron/core/services/NodeInfoService.java @@ -178,8 +178,8 @@ private void setConfigNodeInfo(NodeInfo nodeInfo) { configNodeInfo.setActiveNodeSize(parameter.getActiveNodes().size()); configNodeInfo.setPassiveNodeSize(parameter.getPassiveNodes().size()); configNodeInfo.setSendNodeSize(parameter.getSeedNodes().size()); - configNodeInfo.setMaxConnectCount(parameter.getNodeMaxActiveNodes()); - configNodeInfo.setSameIpMaxConnectCount(parameter.getNodeMaxActiveNodesWithSameIp()); + configNodeInfo.setMaxConnectCount(parameter.getMaxConnections()); + configNodeInfo.setSameIpMaxConnectCount(parameter.getMaxConnectionsWithSameIp()); configNodeInfo.setBackupListenPort(parameter.getBackupPort()); configNodeInfo.setBackupMemberSize(parameter.getBackupMembers().size()); configNodeInfo.setBackupPriority(parameter.getBackupPriority()); diff --git a/framework/src/main/resources/config-backup.conf b/framework/src/main/resources/config-backup.conf index b4d1b55551b..2a1579fdc18 100644 --- a/framework/src/main/resources/config-backup.conf +++ b/framework/src/main/resources/config-backup.conf @@ -88,8 +88,6 @@ node { # Number of validate sign thread, default availableProcessors / 2 # validateSignThreadNum = 16 - maxActiveNodes = 30 - minParticipationRate = 33 p2p { diff --git a/framework/src/main/resources/config-beta.conf b/framework/src/main/resources/config-beta.conf index 278345e6072..1d4a914ce20 100644 --- a/framework/src/main/resources/config-beta.conf +++ b/framework/src/main/resources/config-beta.conf @@ -70,9 +70,6 @@ node { connection.timeout = 2 - - maxActiveNodes = 30 - active = [ "47.93.9.236:18888", "47.93.33.201:18888", diff --git a/framework/src/main/resources/config-localtest.conf b/framework/src/main/resources/config-localtest.conf index 442c4be04b3..239b55d7b4f 100644 --- a/framework/src/main/resources/config-localtest.conf +++ b/framework/src/main/resources/config-localtest.conf @@ -94,19 +94,11 @@ node { # Number of validate sign thread, default availableProcessors / 2 # validateSignThreadNum = 16 - connectFactor = 0.3 - activeConnectFactor = 0.1 - - maxActiveNodes = 30 - - maxActiveNodesWithSameIp = 10 + maxConnectionsWithSameIp = 10 minParticipationRate = 0 # check the peer data transfer ,disconnect factor - disconnectNumberFactor = 0.4 - maxConnectNumberFactor = 0.8 - receiveTcpMinDataLength = 2048 isOpenFullTcpDisconnect = true p2p { diff --git a/framework/src/main/resources/config-test-net.conf b/framework/src/main/resources/config-test-net.conf index 3eed8149686..58c40587fcc 100644 --- a/framework/src/main/resources/config-test-net.conf +++ b/framework/src/main/resources/config-test-net.conf @@ -92,19 +92,11 @@ node { # Number of validate sign thread, default availableProcessors / 2 # validateSignThreadNum = 16 - connectFactor = 0.3 - activeConnectFactor = 0.1 - - maxActiveNodes = 30 - - maxActiveNodesWithSameIp = 2 + maxConnectionsWithSameIp = 2 minParticipationRate = 30 # check the peer data transfer ,disconnect factor - disconnectNumberFactor = 0.4 - maxConnectNumberFactor = 0.8 - receiveTcpMinDataLength = 2048 isOpenFullTcpDisconnect = true p2p { diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index e14680d6759..74f148e1405 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -94,8 +94,6 @@ storage { node.discovery = { enable = true persist = true - bind.ip = "" - external.ip = null } # custom stop condition @@ -153,24 +151,19 @@ node { udpNettyWorkThreadNum = 1 + maxConnections = 30 + minConnections = 8 + minActiveConnections = 3 + # Number of validate sign thread, default availableProcessors / 2 # validateSignThreadNum = 16 - connectFactor = 0.3 - activeConnectFactor = 0.1 - - maxActiveNodes = 30 - - maxActiveNodesWithSameIp = 2 + maxConnectionsWithSameIp = 2 maxHttpConnectNumber = 50 minParticipationRate = 15 - # check the peer data transfer ,disconnect factor - disconnectNumberFactor = 0.4 - maxConnectNumberFactor = 0.8 - receiveTcpMinDataLength = 2048 isOpenFullTcpDisconnect = true p2p { diff --git a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java index ed79bd5c855..5768fc0b1d8 100644 --- a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java @@ -75,7 +75,7 @@ public void get() { Assert.assertEquals(18888, parameter.getNodeListenPort()); Assert.assertEquals(2000, parameter.getNodeConnectionTimeout()); Assert.assertEquals(0, parameter.getActiveNodes().size()); - Assert.assertEquals(30, parameter.getNodeMaxActiveNodes()); + Assert.assertEquals(30, parameter.getMaxConnections()); Assert.assertEquals(43, parameter.getNodeP2pVersion()); //Assert.assertEquals(30, args.getSyncNodeCount()); diff --git a/framework/src/test/resources/config-localtest.conf b/framework/src/test/resources/config-localtest.conf index 22a41d22564..280e06b4af2 100644 --- a/framework/src/test/resources/config-localtest.conf +++ b/framework/src/test/resources/config-localtest.conf @@ -88,12 +88,7 @@ node { # Number of validate sign thread, default availableProcessors / 2 # validateSignThreadNum = 16 - connectFactor = 0.3 - activeConnectFactor = 0.1 - - maxActiveNodes = 30 - - maxActiveNodesWithSameIp = 10 + maxConnectionsWithSameIp = 10 minParticipationRate = 0 @@ -102,9 +97,6 @@ node { zenTokenId = 1000001 # check the peer data transfer ,disconnect factor - disconnectNumberFactor = 0.4 - maxConnectNumberFactor = 0.8 - receiveTcpMinDataLength = 2048 isOpenFullTcpDisconnect = true p2p { diff --git a/framework/src/test/resources/config-test-dbbackup.conf b/framework/src/test/resources/config-test-dbbackup.conf index b39cb54d354..02c1aae36c2 100644 --- a/framework/src/test/resources/config-test-dbbackup.conf +++ b/framework/src/test/resources/config-test-dbbackup.conf @@ -97,19 +97,11 @@ node { # Number of validate sign thread, default availableProcessors / 2 # validateSignThreadNum = 16 - connectFactor = 0.3 - activeConnectFactor = 0.1 - - maxActiveNodes = 30 - - maxActiveNodesWithSameIp = 2 + maxConnectionsWithSameIp = 2 minParticipationRate = 15 # check the peer data transfer ,disconnect factor - disconnectNumberFactor = 0.4 - maxConnectNumberFactor = 0.8 - receiveTcpMinDataLength = 2048 isOpenFullTcpDisconnect = true p2p { diff --git a/framework/src/test/resources/config-test-index.conf b/framework/src/test/resources/config-test-index.conf index d2feabff04e..b9fbf5b2c43 100644 --- a/framework/src/test/resources/config-test-index.conf +++ b/framework/src/test/resources/config-test-index.conf @@ -73,8 +73,6 @@ node { # } ] - maxActiveNodes = 30 - p2p { version = 43 # 43: testnet; 101: debug } diff --git a/framework/src/test/resources/config-test-mainnet.conf b/framework/src/test/resources/config-test-mainnet.conf index 82d64a466ab..5bcc27b398d 100644 --- a/framework/src/test/resources/config-test-mainnet.conf +++ b/framework/src/test/resources/config-test-mainnet.conf @@ -75,7 +75,9 @@ node { # } ] - maxActiveNodes = 30 + maxConnections = 30 + minConnections = 8 + minActiveConnections = 3 p2p { version = 43 # 43: testnet; 101: debug diff --git a/framework/src/test/resources/config-test-storagetest.conf b/framework/src/test/resources/config-test-storagetest.conf index 1a551b23be3..ef8bfe906fa 100644 --- a/framework/src/test/resources/config-test-storagetest.conf +++ b/framework/src/test/resources/config-test-storagetest.conf @@ -99,7 +99,9 @@ node { # } ] - maxActiveNodes = 30 + maxConnections = 30 + minConnections = 8 + minActiveConnections = 3 p2p { version = 43 # 43: testnet; 101: debug diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index 4f851e84bcf..886438cac57 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -90,8 +90,6 @@ node { # } ] - maxActiveNodes = 30 - p2p { version = 43 # 43: testnet; 101: debug } diff --git a/protocol/src/main/protos/Chinese version of TRON Protocol document.md b/protocol/src/main/protos/Chinese version of TRON Protocol document.md index 283bd5fb8af..f393447e42e 100644 --- a/protocol/src/main/protos/Chinese version of TRON Protocol document.md +++ b/protocol/src/main/protos/Chinese version of TRON Protocol document.md @@ -442,7 +442,7 @@ `TOO_MANY_PEERS` `DUPLICATE_PEER` `INCOMPATIBLE_PROTOCOL` - `NULL_IDENTITY` + `RANDOM_ELIMINATION` `PEER_QUITING` `UNEXPECTED_IDENTITY` `LOCAL_IDENTITY` @@ -459,7 +459,7 @@ TOO_MANY_PEERS = 4; DUPLICATE_PEER = 5; INCOMPATIBLE_PROTOCOL = 6; - NULL_IDENTITY = 7; + RANDOM_ELIMINATION = 7; PEER_QUITING = 8; UNEXPECTED_IDENTITY = 9; LOCAL_IDENTITY = 10; diff --git a/protocol/src/main/protos/English version of TRON Protocol document.md b/protocol/src/main/protos/English version of TRON Protocol document.md index 87a61acd119..7d23f5c1f49 100644 --- a/protocol/src/main/protos/English version of TRON Protocol document.md +++ b/protocol/src/main/protos/English version of TRON Protocol document.md @@ -456,7 +456,7 @@ Input, transaction and head block all require signature. `TOO_MANY_PEERS` `DUPLICATE_PEER` `INCOMPATIBLE_PROTOCOL` - `NULL_IDENTITY` + `RANDOM_ELIMINATION` `PEER_QUITING` `UNEXPECTED_IDENTITY` `LOCAL_IDENTITY` @@ -473,7 +473,7 @@ Input, transaction and head block all require signature. TOO_MANY_PEERS = 4; DUPLICATE_PEER = 5; INCOMPATIBLE_PROTOCOL = 6; - NULL_IDENTITY = 7; + RANDOM_ELIMINATION = 7; PEER_QUITING = 8; UNEXPECTED_IDENTITY = 9; LOCAL_IDENTITY = 10; diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 37079e0504d..9d4af0a3151 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -551,7 +551,7 @@ enum ReasonCode { TOO_MANY_PEERS = 0x04; DUPLICATE_PEER = 0x05; INCOMPATIBLE_PROTOCOL = 0x06; - NULL_IDENTITY = 0x07; + RANDOM_ELIMINATION = 0x07; PEER_QUITING = 0x08; UNEXPECTED_IDENTITY = 0x09; LOCAL_IDENTITY = 0x0A; From aee957f757b13fb4c302ece412ccfabf0b9ea773 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 22 Jul 2022 14:12:30 +0800 Subject: [PATCH 0169/1197] tool(db):add db path move function. mv db to new path according to storage.properties settings. --- .../java/org/tron/tool/litefullnode/Util.java | 3 +- plugins/build.gradle | 11 +- .../org/tron/plugins/ArchiveManifest.java | 34 ++-- .../src/main/java/org/tron/plugins/Db.java | 25 +++ .../main/java/org/tron/plugins/DbMove.java | 163 ++++++++++++++++++ .../main/java/org/tron/plugins/Toolkit.java | 19 ++ 6 files changed, 235 insertions(+), 20 deletions(-) create mode 100644 plugins/src/main/java/org/tron/plugins/Db.java create mode 100644 plugins/src/main/java/org/tron/plugins/DbMove.java create mode 100644 plugins/src/main/java/org/tron/plugins/Toolkit.java diff --git a/framework/src/main/java/org/tron/tool/litefullnode/Util.java b/framework/src/main/java/org/tron/tool/litefullnode/Util.java index 1bb00599887..227ce5c5de4 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/Util.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/Util.java @@ -2,6 +2,7 @@ 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; @@ -31,7 +32,7 @@ public static void copyDatabases(Path src, Path dest, List subDirs) subDirs.forEach(dir -> { if (FileUtil.isExists(Paths.get(src.toString(), dir).toString())) { try { - Files.walk(Paths.get(src.toString(), dir)) + 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: {}", diff --git a/plugins/build.gradle b/plugins/build.gradle index 494694dee59..f6815e606b3 100644 --- a/plugins/build.gradle +++ b/plugins/build.gradle @@ -30,8 +30,10 @@ dependencies { testCompile group: 'org.mockito', name: 'mockito-core', version: '2.13.0' testCompile group: 'org.hamcrest', name: 'hamcrest-junit', version: '1.0.0.1' testCompile group: 'org.testng', name: 'testng', version: '6.14.3' - // https://mvnrepository.com/artifact/com.beust/jcommander - compile group: 'com.beust', name: 'jcommander', version: '1.78' + compile group: 'info.picocli', name: 'picocli', version: '4.6.3' + compile group: 'com.typesafe', name: 'config', version: '1.3.2' + compile group: 'me.tongfei', name: 'progressbar', version: '0.9.3' + compile 'com.github.halibobo1205.leveldb-java:leveldb:v0.12.5' compile 'com.github.halibobo1205.leveldb-java:leveldb-api:v0.12.5' @@ -127,11 +129,14 @@ applicationDistribution.from("../gradle/java-tron.vmoptions") { into "bin" } createScript(project, 'org.tron.plugins.ArchiveManifest', 'ArchiveManifest') +createScript(project, 'org.tron.plugins.Toolkit', 'Toolkit') def releaseBinary = hasProperty('binaryRelease') ? getProperty('binaryRelease') : 'true' if (releaseBinary == 'true') { artifacts { - archives(binaryRelease('buildArchiveManifestJar', 'ArchiveManifest', 'org.tron.plugins.ArchiveManifest')) + archives( + binaryRelease('buildArchiveManifestJar', 'ArchiveManifest', 'org.tron.plugins.ArchiveManifest'), + binaryRelease('buildToolkitJar', 'Toolkit', 'org.tron.plugins.Toolkit')) } } diff --git a/plugins/src/main/java/org/tron/plugins/ArchiveManifest.java b/plugins/src/main/java/org/tron/plugins/ArchiveManifest.java index caf2cc0dac6..5771323138f 100644 --- a/plugins/src/main/java/org/tron/plugins/ArchiveManifest.java +++ b/plugins/src/main/java/org/tron/plugins/ArchiveManifest.java @@ -3,8 +3,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static org.iq80.leveldb.impl.Iq80DBFactory.factory; -import com.beust.jcommander.JCommander; -import com.beust.jcommander.Parameter; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -37,6 +35,8 @@ import org.iq80.leveldb.DB; import org.iq80.leveldb.Options; import org.iq80.leveldb.impl.Filename; +import picocli.CommandLine; +import picocli.CommandLine.Option; @Slf4j(topic = "archive") /* @@ -95,12 +95,10 @@ public static void main(String[] args) { public static int run(String[] args) { Args parameters = new Args(); - JCommander jc = JCommander.newBuilder() - .addObject(parameters) - .build(); - jc.parse(args); + CommandLine commandLine = new CommandLine(parameters); + commandLine.parseArgs(args); if (parameters.help) { - jc.usage(); + commandLine.usage(System.out); return 0; } @@ -247,19 +245,23 @@ public static boolean writeProperty(String file, String key, String value) { } public static class Args { - @Parameter - private List parameters = new ArrayList<>(); - @Parameter(names = {"-d", "--database-directory"}, description = "java-tron database directory") - private String databaseDirectory = "output-directory/database"; + @Option(names = {"-d", "--database-directory"}, + defaultValue = "output-directory/database", + description = "java-tron database directory. Default: ${DEFAULT-VALUE}") + private String databaseDirectory; - @Parameter(names = {"-b", "--batch-size" }, description = "deal manifest batch size") - private int maxBatchSize = 80_000; + @Option(names = {"-b", "--batch-size" }, + defaultValue = "80000", + description = "deal manifest batch size. Default: ${DEFAULT-VALUE}") + private int maxBatchSize; - @Parameter(names = {"-m", "--manifest-size" }, description = "manifest min size(M) to archive") - private int maxManifestSize = 0; + @Option(names = {"-m", "--manifest-size" }, + defaultValue = "0", + description = "manifest min size(M) to archive. Default: ${DEFAULT-VALUE}") + private int maxManifestSize; - @Parameter(names = {"-h", "--help"}, help = true) + @Option(names = {"-h", "--help"}, help = true) private boolean help; } } \ No newline at end of file diff --git a/plugins/src/main/java/org/tron/plugins/Db.java b/plugins/src/main/java/org/tron/plugins/Db.java new file mode 100644 index 00000000000..a886d717c6d --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/Db.java @@ -0,0 +1,25 @@ +package org.tron.plugins; + +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; +import java.nio.file.Paths; +import picocli.CommandLine; + +@CommandLine.Command(name = "db", + mixinStandardHelpOptions = true, + version = "db command 1.0", + description = "An rich command set that provides high-level operations for dbs.", + subcommands = {CommandLine.HelpCommand.class, DbMove.class}, + commandListHeading = "%nCommands:%n%nThe most commonly used git commands are:%n" +) +public class Db { + + static class ConfigConverter implements CommandLine.ITypeConverter { + ConfigConverter() { + } + + public Config convert(String value) { + return ConfigFactory.parseFile(Paths.get(value).toFile()); + } + } +} diff --git a/plugins/src/main/java/org/tron/plugins/DbMove.java b/plugins/src/main/java/org/tron/plugins/DbMove.java new file mode 100644 index 00000000000..67bc3a57706 --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/DbMove.java @@ -0,0 +1,163 @@ +package org.tron.plugins; + +import com.typesafe.config.Config; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.Callable; +import java.util.stream.Collectors; +import me.tongfei.progressbar.ProgressBar; +import picocli.CommandLine; +import picocli.CommandLine.Command; + +@Command(name = "mv", aliases = "move", + description = "mv db to pre-set new path . For example HDD,reduce storage expenses.") +public class DbMove implements Callable { + + private static final String PROPERTIES_CONFIG_KEY = "storage.properties"; + private static final String DB_DIRECTORY_CONFIG_KEY = "storage.db.directory"; + private static final String DEFAULT_DB_DIRECTORY = "database"; + private static final String NAME_CONFIG_KEY = "name"; + private static final String PATH_CONFIG_KEY = "path"; + private static final String NOT_FIND = "The database to be moved cannot be found."; + + @CommandLine.Spec + CommandLine.Model.CommandSpec spec; + + @CommandLine.Option(names = {"-d", "--database-directory"}, + defaultValue = "output-directory", + description = "database directory path. Default: ${DEFAULT-VALUE}") + String database; + + @CommandLine.Option(names = {"-c", "--config"}, + defaultValue = "config.conf", + converter = Db.ConfigConverter.class, + description = " config file. Default: ${DEFAULT-VALUE}") + Config config; + + @CommandLine.Option(names = {"-h", "--help"}, help = true, description = "display a help message") + boolean help; + + @Override + public Integer call() throws Exception { + if (help) { + spec.commandLine().usage(System.out); + return 0; + } + if (config.hasPath(PROPERTIES_CONFIG_KEY)) { + List dbs = config.getConfigList(PROPERTIES_CONFIG_KEY); + if (dbs.isEmpty()) { + spec.commandLine().getOut().println(NOT_FIND); + return 0; + } + String dbPath = config.hasPath(DB_DIRECTORY_CONFIG_KEY) + ? config.getString(DB_DIRECTORY_CONFIG_KEY) : DEFAULT_DB_DIRECTORY; + + dbs = dbs.stream() + .filter(c -> c.hasPath(NAME_CONFIG_KEY) && c.hasPath(PATH_CONFIG_KEY)) + .collect(Collectors.toList()); + + if (dbs.isEmpty()) { + spec.commandLine().getOut().println(NOT_FIND); + return 0; + } + List toBeMove = dbs.stream() + .map(c -> { + try { + return new Property(c.getString(NAME_CONFIG_KEY), + Paths.get(database, dbPath, c.getString(NAME_CONFIG_KEY)), + Paths.get(c.getString(PATH_CONFIG_KEY), dbPath, c.getString(NAME_CONFIG_KEY))); + } catch (IOException e) { + spec.commandLine().getErr().println(e); + } + return null; + }).filter(Objects::nonNull) + .filter(p -> !p.destination.equals(p.original)).collect(Collectors.toList()); + + if (toBeMove.isEmpty()) { + spec.commandLine().getOut().println(NOT_FIND); + return 0; + } + toBeMove = toBeMove.stream() + .filter(property -> { + if (property.destination.toFile().exists()) { + spec.commandLine().getOut().println(String.format("%s already exist,skip.", + property.destination)); + return false; + } else { + return true; + } + }).collect(Collectors.toList()); + + if (toBeMove.isEmpty()) { + spec.commandLine().getOut().println(NOT_FIND); + return 0; + } + ProgressBar.wrap(toBeMove.stream(), "mv task").forEach(this::run); + spec.commandLine().getOut().println("move db done."); + + } else { + spec.commandLine().getOut().println(NOT_FIND); + } + return 0; + } + + private void run(Property p) { + if (p.destination.toFile().mkdirs()) { + ProgressBar.wrap(Arrays.stream(Objects.requireNonNull(p.original.toFile().listFiles())) + .filter(File::isFile).map(File::getName).parallel(), p.name).forEach(file -> { + Path original = Paths.get(p.original.toString(), file); + Path destination = Paths.get(p.destination.toString(), file); + try { + Files.copy(original, destination, + StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + spec.commandLine().getErr().println(e); + } + }); + try { + if (deleteDir(p.original.toFile())) { + Files.createSymbolicLink(p.original, p.destination); + } + } catch (IOException | UnsupportedOperationException x) { + spec.commandLine().getErr().println(x); + } + } else { + spec.commandLine().getErr().println(String.format("%s create failed.", p.destination)); + } + } + + /** + * delete directory. + */ + public static boolean deleteDir(File dir) { + if (dir.isDirectory()) { + String[] children = dir.list(); + if (children != null) { + for (String child : children) { + deleteDir(new File(dir, child)); + } + } + } + return dir.delete(); + } + + static class Property { + + private final String name; + private final Path original; + final Path destination; + + public Property(String name, Path original, Path destination) throws IOException { + this.name = name; + this.original = original.toFile().getCanonicalFile().toPath(); + this.destination = destination.toFile().getCanonicalFile().toPath(); + } + } +} diff --git a/plugins/src/main/java/org/tron/plugins/Toolkit.java b/plugins/src/main/java/org/tron/plugins/Toolkit.java new file mode 100644 index 00000000000..4a087e40b34 --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/Toolkit.java @@ -0,0 +1,19 @@ +package org.tron.plugins; + +import java.util.concurrent.Callable; +import picocli.CommandLine; + +@CommandLine.Command(name = "tron", subcommands = { CommandLine.HelpCommand.class, Db.class}) +public class Toolkit implements Callable { + + + public static void main(String[] args) { + int exitCode = new CommandLine(new Toolkit()).execute(args); + System.exit(exitCode); + } + + @Override + public Integer call() throws Exception { + return 0; + } +} From 72375d70fcd6a1cc6fc118f026ece571cff4e420 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Tue, 26 Jul 2022 12:04:58 +0800 Subject: [PATCH 0170/1197] feat: catch error if param address is not base58 --- .../src/main/java/org/tron/core/services/http/JsonFormat.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/framework/src/main/java/org/tron/core/services/http/JsonFormat.java b/framework/src/main/java/org/tron/core/services/http/JsonFormat.java index d74a6c8f291..96dedb1e20c 100644 --- a/framework/src/main/java/org/tron/core/services/http/JsonFormat.java +++ b/framework/src/main/java/org/tron/core/services/http/JsonFormat.java @@ -1595,6 +1595,8 @@ public ByteString consumeByteString(final String fieldName, boolean selfType) return result; } catch (InvalidEscapeSequence e) { throw parseException(e.getMessage()); + } catch (IllegalArgumentException e) { + throw parseException("INVALID base58 String, " + e.getMessage()); } } From a50938368bacf09cd4071673d36671f0e42f429d Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 26 Jul 2022 16:10:55 +0800 Subject: [PATCH 0171/1197] feat(block): increase the probability that the block processing thread acquires the lock --- .../org/tron/consensus/base/BlockHandle.java | 2 + .../org/tron/consensus/dpos/DposTask.java | 55 +-- .../tron/core/consensus/BlockHandleImpl.java | 8 + .../main/java/org/tron/core/db/Manager.java | 358 ++++++++++-------- 4 files changed, 236 insertions(+), 187 deletions(-) diff --git a/consensus/src/main/java/org/tron/consensus/base/BlockHandle.java b/consensus/src/main/java/org/tron/consensus/base/BlockHandle.java index a36722b9083..f1887359f44 100644 --- a/consensus/src/main/java/org/tron/consensus/base/BlockHandle.java +++ b/consensus/src/main/java/org/tron/consensus/base/BlockHandle.java @@ -11,4 +11,6 @@ public interface BlockHandle { BlockCapsule produce(Miner miner, long blockTime, long timeout); + void setBlockWaitLock(boolean flag); + } \ No newline at end of file diff --git a/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java b/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java index 4486aad2d89..dcfa85ca5f3 100644 --- a/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java +++ b/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java @@ -87,36 +87,41 @@ private State produceBlock() { return state; } - synchronized (dposService.getBlockHandle().getLock()) { + dposService.getBlockHandle().setBlockWaitLock(true); + try { + synchronized (dposService.getBlockHandle().getLock()) { - long slot = dposSlot.getSlot(System.currentTimeMillis() + 50); - if (slot == 0) { - return State.NOT_TIME_YET; - } + long slot = dposSlot.getSlot(System.currentTimeMillis() + 50); + if (slot == 0) { + return State.NOT_TIME_YET; + } - ByteString pWitness = dposSlot.getScheduledWitness(slot); + ByteString pWitness = dposSlot.getScheduledWitness(slot); - Miner miner = dposService.getMiners().get(pWitness); - if (miner == null) { - return State.NOT_MY_TURN; - } + Miner miner = dposService.getMiners().get(pWitness); + if (miner == null) { + return State.NOT_MY_TURN; + } - long pTime = dposSlot.getTime(slot); - long timeout = - pTime + BLOCK_PRODUCED_INTERVAL / 2 * dposService.getBlockProduceTimeoutPercent() / 100; - BlockCapsule blockCapsule = dposService.getBlockHandle().produce(miner, pTime, timeout); - if (blockCapsule == null) { - return State.PRODUCE_BLOCK_FAILED; - } + long pTime = dposSlot.getTime(slot); + long timeout = + pTime + BLOCK_PRODUCED_INTERVAL / 2 * dposService.getBlockProduceTimeoutPercent() / 100; + BlockCapsule blockCapsule = dposService.getBlockHandle().produce(miner, pTime, timeout); + if (blockCapsule == null) { + return State.PRODUCE_BLOCK_FAILED; + } - BlockHeader.raw raw = blockCapsule.getInstance().getBlockHeader().getRawData(); - logger.info("Produce block successfully, num: {}, time: {}, witness: {}, ID:{}, parentID:{}", - raw.getNumber(), - new DateTime(raw.getTimestamp()), - ByteArray.toHexString(raw.getWitnessAddress().toByteArray()), - new Sha256Hash(raw.getNumber(), Sha256Hash.of(CommonParameter - .getInstance().isECKeyCryptoEngine(), raw.toByteArray())), - ByteArray.toHexString(raw.getParentHash().toByteArray())); + BlockHeader.raw raw = blockCapsule.getInstance().getBlockHeader().getRawData(); + logger.info("Produce block successfully, num: {}, time: {}, witness: {}, ID:{}, parentID:{}", + raw.getNumber(), + new DateTime(raw.getTimestamp()), + ByteArray.toHexString(raw.getWitnessAddress().toByteArray()), + new Sha256Hash(raw.getNumber(), Sha256Hash.of(CommonParameter + .getInstance().isECKeyCryptoEngine(), raw.toByteArray())), + ByteArray.toHexString(raw.getParentHash().toByteArray())); + } + } finally { + dposService.getBlockHandle().setBlockWaitLock(false); } return State.OK; diff --git a/framework/src/main/java/org/tron/core/consensus/BlockHandleImpl.java b/framework/src/main/java/org/tron/core/consensus/BlockHandleImpl.java index 9c039800ff9..03452546a9b 100644 --- a/framework/src/main/java/org/tron/core/consensus/BlockHandleImpl.java +++ b/framework/src/main/java/org/tron/core/consensus/BlockHandleImpl.java @@ -58,4 +58,12 @@ public BlockCapsule produce(Miner miner, long blockTime, long timeout) { } return blockCapsule; } + + public void setBlockWaitLock(boolean flag) { + if (flag) { + manager.getBlockWaitLock().incrementAndGet(); + } else { + manager.getBlockWaitLock().decrementAndGet(); + } + } } diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 2d0f85a94d0..59fcd6f1ee6 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -239,6 +239,10 @@ public class Manager { @Getter private final ThreadLocal blockedTimer = new ThreadLocal<>(); + @Getter + private AtomicInteger blockWaitLock = new AtomicInteger(0); + private Object transactionLock = new Object(); + /** * Cycle thread to rePush Transactions */ @@ -755,25 +759,40 @@ public boolean pushTransaction(final TransactionCapsule trx) throw new ValidateSignatureException("trans sig validate failed"); } - synchronized (this) { - if (isShieldedTransaction(trx.getInstance()) - && shieldedTransInPendingCounts.get() >= shieldedTransInPendingMaxCounts) { - return false; - } - if (!session.valid()) { - session.setValue(revokingStore.buildSession()); + synchronized (transactionLock) { + while (true) { + try { + if (blockWaitLock.get() > 0) { + TimeUnit.MILLISECONDS.sleep(50); + logger.info("waiting for the block processing to complete"); + } else { + break; + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + logger.debug("the wait has been interrupted"); + } } + synchronized (this) { + if (isShieldedTransaction(trx.getInstance()) + && shieldedTransInPendingCounts.get() >= shieldedTransInPendingMaxCounts) { + return false; + } + if (!session.valid()) { + session.setValue(revokingStore.buildSession()); + } - try (ISession tmpSession = revokingStore.buildSession()) { - processTransaction(trx, null); - trx.setTrxTrace(null); - pendingTransactions.add(trx); - Metrics.gaugeInc(MetricKeys.Gauge.MANAGER_QUEUE, 1, - MetricLabels.Gauge.QUEUE_PENDING); - tmpSession.merge(); - } - if (isShieldedTransaction(trx.getInstance())) { - shieldedTransInPendingCounts.incrementAndGet(); + try (ISession tmpSession = revokingStore.buildSession()) { + processTransaction(trx, null); + trx.setTrxTrace(null); + pendingTransactions.add(trx); + Metrics.gaugeInc(MetricKeys.Gauge.MANAGER_QUEUE, 1, + MetricLabels.Gauge.QUEUE_PENDING); + tmpSession.merge(); + } + if (isShieldedTransaction(trx.getInstance())) { + shieldedTransInPendingCounts.incrementAndGet(); + } } } } finally { @@ -825,7 +844,7 @@ public void consumeBandwidth(TransactionCapsule trx, TransactionTrace trace) /** * when switch fork need erase blocks on fork branch. */ - public synchronized void eraseBlock() { + public void eraseBlock() { session.reset(); try { BlockCapsule oldHeadBlock = chainBaseManager.getBlockById( @@ -1048,167 +1067,182 @@ public List getVerifyTxs(BlockCapsule block) { /** * save a block. */ - public synchronized void pushBlock(final BlockCapsule block) + public void pushBlock(final BlockCapsule block) throws ValidateSignatureException, ContractValidateException, ContractExeException, UnLinkedBlockException, ValidateScheduleException, AccountResourceInsufficientException, TaposException, TooBigTransactionException, TooBigTransactionResultException, DupTransactionException, TransactionExpirationException, BadNumberBlockException, BadBlockException, NonCommonBlockException, ReceiptCheckErrException, VMIllegalException, ZksnarkException, EventBloomException { - Metrics.histogramObserve(blockedTimer.get()); - blockedTimer.remove(); - long headerNumber = getDynamicPropertiesStore().getLatestBlockHeaderNumber(); - if (block.getNum() <= headerNumber && khaosDb.containBlockInMiniStore(block.getBlockId())) { - logger.info("Block {} is already exist.", block.getBlockId().getString()); - return; - } - final Histogram.Timer timer = Metrics.histogramStartTimer( - MetricKeys.Histogram.BLOCK_PUSH_LATENCY); - long start = System.currentTimeMillis(); - List txs = getVerifyTxs(block); - logger.info("Block num: {}, re-push-size: {}, pending-size: {}, " - + "block-tx-size: {}, verify-tx-size: {}", - block.getNum(), rePushTransactions.size(), pendingTransactions.size(), - block.getTransactions().size(), txs.size()); - - if (CommonParameter.getInstance().getShutdownBlockTime() != null - && CommonParameter.getInstance().getShutdownBlockTime() - .isSatisfiedBy(new Date(block.getTimeStamp()))) { - latestSolidityNumShutDown = block.getNum(); - } - - try (PendingManager pm = new PendingManager(this)) { - - if (!block.generatedByMyself) { - if (!block.calcMerkleRoot().equals(block.getMerkleRoot())) { - logger.warn( - "The merkle root doesn't match, Calc result is " - + block.calcMerkleRoot() - + " , the headers is " - + block.getMerkleRoot()); - throw new BadBlockException("The merkle hash is not validated"); - } - consensus.receiveBlock(block); - } - - if (block.getTransactions().stream().filter(tran -> isShieldedTransaction(tran.getInstance())) - .count() > SHIELDED_TRANS_IN_BLOCK_COUNTS) { - throw new BadBlockException( - "shielded transaction count > " + SHIELDED_TRANS_IN_BLOCK_COUNTS); - } - - BlockCapsule newBlock; - try { - newBlock = this.khaosDb.push(block); - } catch (UnLinkedBlockException e) { - logger.error( - "latestBlockHeaderHash:{}, latestBlockHeaderNumber:{}, latestSolidifiedBlockNum:{}", - getDynamicPropertiesStore().getLatestBlockHeaderHash(), - getDynamicPropertiesStore().getLatestBlockHeaderNumber(), - getDynamicPropertiesStore().getLatestSolidifiedBlockNum()); - throw e; - } - - // DB don't need lower block - if (getDynamicPropertiesStore().getLatestBlockHeaderHash() == null) { - if (newBlock.getNum() != 0) { + blockWaitLock.incrementAndGet(); + try { + synchronized (this) { + Metrics.histogramObserve(blockedTimer.get()); + blockedTimer.remove(); + long headerNumber = getDynamicPropertiesStore().getLatestBlockHeaderNumber(); + if (block.getNum() <= headerNumber && khaosDb.containBlockInMiniStore(block.getBlockId())) { + logger.info("Block {} is already exist.", block.getBlockId().getString()); return; } - } else { - if (newBlock.getNum() <= headerNumber) { - return; + final Histogram.Timer timer = Metrics.histogramStartTimer( + MetricKeys.Histogram.BLOCK_PUSH_LATENCY); + long start = System.currentTimeMillis(); + List txs = getVerifyTxs(block); + logger.info("Block num: {}, re-push-size: {}, pending-size: {}, " + + "block-tx-size: {}, verify-tx-size: {}", + block.getNum(), rePushTransactions.size(), pendingTransactions.size(), + block.getTransactions().size(), txs.size()); + + if (CommonParameter.getInstance().getShutdownBlockTime() != null + && CommonParameter.getInstance().getShutdownBlockTime() + .isSatisfiedBy(new Date(block.getTimeStamp()))) { + latestSolidityNumShutDown = block.getNum(); } - // switch fork - if (!newBlock - .getParentHash() - .equals(getDynamicPropertiesStore().getLatestBlockHeaderHash())) { - logger.warn( - "switch fork! new head num = {}, block id = {}", - newBlock.getNum(), - newBlock.getBlockId()); - - logger.warn( - "******** before switchFork ******* push block: " - + block.toString() - + ", new block:" - + newBlock.toString() - + ", dynamic head num: " - + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() - + ", dynamic head hash: " - + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderHash() - + ", dynamic head timestamp: " - + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp() - + ", khaosDb head: " - + khaosDb.getHead() - + ", khaosDb miniStore size: " - + khaosDb.getMiniStore().size() - + ", khaosDb unlinkMiniStore size: " - + khaosDb.getMiniUnlinkedStore().size()); - - switchFork(newBlock); - logger.info(SAVE_BLOCK + newBlock); + try (PendingManager pm = new PendingManager(this)) { - logger.warn( - "******** after switchFork ******* push block: " - + block.toString() - + ", new block:" - + newBlock.toString() - + ", dynamic head num: " - + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() - + ", dynamic head hash: " - + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderHash() - + ", dynamic head timestamp: " - + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp() - + ", khaosDb head: " - + khaosDb.getHead() - + ", khaosDb miniStore size: " - + khaosDb.getMiniStore().size() - + ", khaosDb unlinkMiniStore size: " - + khaosDb.getMiniUnlinkedStore().size()); + if (!block.generatedByMyself) { + if (!block.calcMerkleRoot().equals(block.getMerkleRoot())) { + logger.warn( + "The merkle root doesn't match, Calc result is " + + block.calcMerkleRoot() + + " , the headers is " + + block.getMerkleRoot()); + throw new BadBlockException("The merkle hash is not validated"); + } + consensus.receiveBlock(block); + } - return; - } - try (ISession tmpSession = revokingStore.buildSession()) { + if (block.getTransactions().stream() + .filter(tran -> isShieldedTransaction(tran.getInstance())) + .count() > SHIELDED_TRANS_IN_BLOCK_COUNTS) { + throw new BadBlockException( + "shielded transaction count > " + SHIELDED_TRANS_IN_BLOCK_COUNTS); + } - long oldSolidNum = - chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); + BlockCapsule newBlock; + try { + newBlock = this.khaosDb.push(block); + } catch (UnLinkedBlockException e) { + logger.error( + "latestBlockHeaderHash:{}, latestBlockHeaderNumber:{}" + + ", latestSolidifiedBlockNum:{}", + getDynamicPropertiesStore().getLatestBlockHeaderHash(), + getDynamicPropertiesStore().getLatestBlockHeaderNumber(), + getDynamicPropertiesStore().getLatestSolidifiedBlockNum()); + throw e; + } - applyBlock(newBlock, txs); - tmpSession.commit(); - // if event subscribe is enabled, post block trigger to queue - postBlockTrigger(newBlock); - // if event subscribe is enabled, post solidity trigger to queue - postSolidityTrigger(oldSolidNum, - getDynamicPropertiesStore().getLatestSolidifiedBlockNum()); - } catch (Throwable throwable) { - logger.error(throwable.getMessage(), throwable); - khaosDb.removeBlk(block.getBlockId()); - throw throwable; + // DB don't need lower block + if (getDynamicPropertiesStore().getLatestBlockHeaderHash() == null) { + if (newBlock.getNum() != 0) { + return; + } + } else { + if (newBlock.getNum() <= headerNumber) { + return; + } + + // switch fork + if (!newBlock + .getParentHash() + .equals(getDynamicPropertiesStore().getLatestBlockHeaderHash())) { + logger.warn( + "switch fork! new head num = {}, block id = {}", + newBlock.getNum(), + newBlock.getBlockId()); + + logger.warn( + "******** before switchFork ******* push block: " + + block.toString() + + ", new block:" + + newBlock.toString() + + ", dynamic head num: " + + chainBaseManager.getDynamicPropertiesStore() + .getLatestBlockHeaderNumber() + + ", dynamic head hash: " + + chainBaseManager.getDynamicPropertiesStore() + .getLatestBlockHeaderHash() + + ", dynamic head timestamp: " + + chainBaseManager.getDynamicPropertiesStore() + .getLatestBlockHeaderTimestamp() + + ", khaosDb head: " + + khaosDb.getHead() + + ", khaosDb miniStore size: " + + khaosDb.getMiniStore().size() + + ", khaosDb unlinkMiniStore size: " + + khaosDb.getMiniUnlinkedStore().size()); + + switchFork(newBlock); + logger.info(SAVE_BLOCK + newBlock); + + logger.warn( + "******** after switchFork ******* push block: " + + block.toString() + + ", new block:" + + newBlock.toString() + + ", dynamic head num: " + + chainBaseManager.getDynamicPropertiesStore() + .getLatestBlockHeaderNumber() + + ", dynamic head hash: " + + chainBaseManager.getDynamicPropertiesStore() + .getLatestBlockHeaderHash() + + ", dynamic head timestamp: " + + chainBaseManager.getDynamicPropertiesStore() + .getLatestBlockHeaderTimestamp() + + ", khaosDb head: " + + khaosDb.getHead() + + ", khaosDb miniStore size: " + + khaosDb.getMiniStore().size() + + ", khaosDb unlinkMiniStore size: " + + khaosDb.getMiniUnlinkedStore().size()); + + return; + } + try (ISession tmpSession = revokingStore.buildSession()) { + + long oldSolidNum = + chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); + + applyBlock(newBlock, txs); + tmpSession.commit(); + // if event subscribe is enabled, post block trigger to queue + postBlockTrigger(newBlock); + // if event subscribe is enabled, post solidity trigger to queue + postSolidityTrigger(oldSolidNum, + getDynamicPropertiesStore().getLatestSolidifiedBlockNum()); + } catch (Throwable throwable) { + logger.error(throwable.getMessage(), throwable); + khaosDb.removeBlk(block.getBlockId()); + throw throwable; + } + } + logger.info(SAVE_BLOCK + newBlock); + } + //clear ownerAddressSet + if (CollectionUtils.isNotEmpty(ownerAddressSet)) { + Set result = new HashSet<>(); + for (TransactionCapsule transactionCapsule : rePushTransactions) { + filterOwnerAddress(transactionCapsule, result); + } + for (TransactionCapsule transactionCapsule : pushTransactionQueue) { + filterOwnerAddress(transactionCapsule, result); + } + ownerAddressSet.clear(); + ownerAddressSet.addAll(result); } - } - logger.info(SAVE_BLOCK + newBlock); - } - //clear ownerAddressSet - if (CollectionUtils.isNotEmpty(ownerAddressSet)) { - Set result = new HashSet<>(); - for (TransactionCapsule transactionCapsule : rePushTransactions) { - filterOwnerAddress(transactionCapsule, result); - } - for (TransactionCapsule transactionCapsule : pushTransactionQueue) { - filterOwnerAddress(transactionCapsule, result); - } - ownerAddressSet.clear(); - ownerAddressSet.addAll(result); - } - long cost = System.currentTimeMillis() - start; - MetricsUtil.meterMark(MetricsKey.BLOCKCHAIN_BLOCK_PROCESS_TIME, cost); + long cost = System.currentTimeMillis() - start; + MetricsUtil.meterMark(MetricsKey.BLOCKCHAIN_BLOCK_PROCESS_TIME, cost); - logger.info("pushBlock block number:{}, cost/txs:{}/{} {}", - block.getNum(), cost, block.getTransactions().size(), cost > 1000); + logger.info("pushBlock block number:{}, cost/txs:{}/{} {}", + block.getNum(), cost, block.getTransactions().size(), cost > 1000); - Metrics.histogramObserve(timer); + Metrics.histogramObserve(timer); + } + } finally { + blockWaitLock.decrementAndGet(); + } } public void updateDynamicProperties(BlockCapsule block) { @@ -1373,7 +1407,7 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block /** * Generate a block. */ - public synchronized BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { + public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { String address = StringUtil.encode58Check(miner.getWitnessAddress().toByteArray()); final Histogram.Timer timer = Metrics.histogramStartTimer( MetricKeys.Histogram.BLOCK_GENERATE_LATENCY, address); From 9445506df442124179e9b9e74fc9e1570bdff63d Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Tue, 26 Jul 2022 16:24:26 +0800 Subject: [PATCH 0172/1197] feat: catch ClassCastException when getJSONObject --- framework/src/main/java/org/tron/core/services/http/Util.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 49b50e3356b..1a4f738a334 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -252,7 +252,7 @@ public static JSONObject printTransactionToJSON(Transaction transaction, boolean /** * Note: the contracts of the returned transaction may be empty - * */ + */ public static Transaction packTransaction(String strTransaction, boolean selfType) { JSONObject jsonTransaction = JSON.parseObject(strTransaction); JSONObject rawData = jsonTransaction.getJSONObject("raw_data"); @@ -290,6 +290,8 @@ public static Transaction packTransaction(String strTransaction, boolean selfTyp logger.debug("invalid contractType: {}", contractType); } catch (ParseException e) { logger.debug("ParseException: {}", e.getMessage()); + } catch (ClassCastException e) { + logger.debug("ClassCastException: {}", e.getMessage()); } catch (Exception e) { logger.error("", e); } From ba09cbdf6c64ee51e01957c7fec1d371b57e7732 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 26 Jul 2022 17:46:29 +0800 Subject: [PATCH 0173/1197] feat(block): remove test log --- framework/src/main/java/org/tron/core/db/Manager.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 59fcd6f1ee6..ad1faa2faf6 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -763,8 +763,7 @@ public boolean pushTransaction(final TransactionCapsule trx) while (true) { try { if (blockWaitLock.get() > 0) { - TimeUnit.MILLISECONDS.sleep(50); - logger.info("waiting for the block processing to complete"); + TimeUnit.MILLISECONDS.sleep(10); } else { break; } From 3889e04801678b1ee9809eb6a54407d93b08f9b5 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Tue, 26 Jul 2022 18:49:38 +0800 Subject: [PATCH 0174/1197] feat: change implementation of web3_clientVersion, remove VERSION_NAME --- .../org/tron/core/services/jsonrpc/TronJsonRpcImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 0fec85718fa..1c6debb31b7 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -215,10 +215,10 @@ public String web3ClientVersion() { matcher.matches(); return String.join("/", Arrays.asList( - "TRON", "v" + Version.getVersion(), + "TRON", + "v" + Version.getVersion(), System.getProperty("os.name"), - "Java" + matcher.group(1), - Version.VERSION_NAME)); + "Java" + matcher.group(1))); } @Override From e8478b1c20aac98a9f11a5c8b088010fa01a5472 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 26 Jul 2022 17:21:04 +0800 Subject: [PATCH 0175/1197] api(getblock): rename params --- framework/src/main/java/org/tron/core/Wallet.java | 5 ++++- .../java/org/tron/core/services/RpcApiService.java | 6 +++--- .../tron/core/services/http/GetBlockServlet.java | 14 +++++++------- .../interfaceOnPBFT/RpcApiServiceOnPBFT.java | 2 +- .../RpcApiServiceOnSolidity.java | 2 +- protocol/src/main/protos/api/api.proto | 8 ++++---- 6 files changed, 20 insertions(+), 17 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 29c61082681..420e87fad40 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -4020,7 +4020,7 @@ public Chainbase.Cursor getCursor() { return chainBaseManager.getBlockStore().getRevokingDB().getCursor(); } - public Block getBlock(GrpcAPI.BlockMessage request) { + public Block getBlock(GrpcAPI.BlockReq request) { Block block; long head = chainBaseManager.getHeadBlockNum(); if (!request.getIdOrNum().isEmpty()) { @@ -4036,6 +4036,9 @@ public Block getBlock(GrpcAPI.BlockMessage request) { block = getBlockByNum(num); } else { RuntimeException e = new IllegalArgumentException("id must be legal block hash."); + if (request.getIdOrNum().length() != Sha256Hash.LENGTH * 2) { + throw e; + } try { ByteString id = ByteString.copyFrom(ByteArray.fromHexString(request.getIdOrNum())); if (id.size() == Sha256Hash.LENGTH) { diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index ac791428999..c964536aa33 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -909,7 +909,7 @@ public void getTransactionInfoByBlockNum(NumberMessage request, } @Override - public void getBlock(GrpcAPI.BlockMessage request, + public void getBlock(GrpcAPI.BlockReq request, StreamObserver responseObserver) { getBlockCommon(request, responseObserver); } @@ -2666,7 +2666,7 @@ public void getPendingSize(EmptyMessage request, @Override - public void getBlock(GrpcAPI.BlockMessage request, + public void getBlock(GrpcAPI.BlockReq request, StreamObserver responseObserver) { getBlockCommon(request, responseObserver); } @@ -2788,7 +2788,7 @@ public void getPendingSizeCommon(EmptyMessage request, responseObserver.onCompleted(); } - public void getBlockCommon(GrpcAPI.BlockMessage request, + public void getBlockCommon(GrpcAPI.BlockReq request, StreamObserver responseObserver) { try { responseObserver.onNext(block2Extention(wallet.getBlock(request))); diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockServlet.java index 4856946a8ed..0e0104e8014 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBlockServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockServlet.java @@ -10,7 +10,7 @@ import org.eclipse.jetty.http.HttpMethod; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI.BlockMessage; +import org.tron.api.GrpcAPI.BlockReq; import org.tron.core.Wallet; import org.tron.protos.Protocol.Block; @@ -33,7 +33,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) private void handle(HttpServletRequest request, HttpServletResponse response) { try { PostParams params = parseParams(request); - BlockMessage message = buildRequest(params.getParams(), params.isVisible()); + BlockReq message = buildRequest(params.getParams(), params.isVisible()); fillResponse(params.isVisible(), message, response); } catch (Exception e) { Util.processError(e, response); @@ -43,10 +43,10 @@ private void handle(HttpServletRequest request, HttpServletResponse response) { private PostParams parseParams(HttpServletRequest request) throws Exception { HttpMethod m = HttpMethod.fromString(request.getMethod()); if (HttpMethod.GET.equals(m)) { - String idOrNum = request.getParameter("idOrNum"); + String idOrNum = request.getParameter("id_or_num"); JSONObject params = new JSONObject(); if (!Strings.isNullOrEmpty(idOrNum)) { - params.put("idOrNum", idOrNum); + params.put("id_or_num", idOrNum); } params.put("detail", Boolean.parseBoolean(request.getParameter("detail"))); return new PostParams(JSON.toJSONString(params), @@ -58,16 +58,16 @@ private PostParams parseParams(HttpServletRequest request) throws Exception { throw new UnsupportedOperationException(); } - private BlockMessage buildRequest(String params, boolean visible) + private BlockReq buildRequest(String params, boolean visible) throws JsonFormat.ParseException { - BlockMessage.Builder build = BlockMessage.newBuilder(); + BlockReq.Builder build = BlockReq.newBuilder(); if (!Strings.isNullOrEmpty(params)) { JsonFormat.merge(params, build, visible); } return build.build(); } - private void fillResponse(boolean visible, BlockMessage request, HttpServletResponse response) + private void fillResponse(boolean visible, BlockReq request, HttpServletResponse response) throws IOException { try { Block reply = wallet.getBlock(request); diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java index b92cd4d3041..286613b14b9 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java @@ -504,7 +504,7 @@ public void getBurnTrx(EmptyMessage request, StreamObserver respo } @Override - public void getBlock(GrpcAPI.BlockMessage request, + public void getBlock(GrpcAPI.BlockReq request, StreamObserver responseObserver) { walletOnPBFT.futureGet( () -> rpcApiService.getWalletSolidityApi().getBlock(request, responseObserver)); diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java index 1e37fdb0e8f..4d9d0361d23 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java @@ -500,7 +500,7 @@ public void getBurnTrx(EmptyMessage request, StreamObserver respo } @Override - public void getBlock(GrpcAPI.BlockMessage request, + public void getBlock(GrpcAPI.BlockReq request, StreamObserver responseObserver) { walletOnSolidity.futureGet( () -> rpcApiService.getWalletSolidityApi().getBlock(request, responseObserver)); diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 63eca1a4a29..94219db1ec2 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -790,7 +790,7 @@ service Wallet { rpc GetPendingSize (EmptyMessage) returns (NumberMessage) { } - rpc GetBlock (BlockMessage) returns (BlockExtention) { + rpc GetBlock (BlockReq) returns (BlockExtention) { } }; @@ -977,7 +977,7 @@ service WalletSolidity { rpc GetBurnTrx (EmptyMessage) returns (NumberMessage) { } - rpc GetBlock (BlockMessage) returns (BlockExtention) { + rpc GetBlock (BlockReq) returns (BlockExtention) { } }; @@ -1128,8 +1128,8 @@ message TimeMessage { int64 beginInMilliseconds = 1; int64 endInMilliseconds = 2; } -message BlockMessage { - string idOrNum = 1; +message BlockReq { + string id_or_num = 1; bool detail = 2; } message BlockLimit { From fd836ba386f7c15ef1b322c88fe25f6e55133ff4 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Wed, 27 Jul 2022 17:37:00 +0800 Subject: [PATCH 0176/1197] feat: add api to get bandwidth price history --- .../core/store/DynamicPropertiesStore.java | 73 ++++-- .../src/main/java/org/tron/core/Wallet.java | 10 + .../tron/core/consensus/ProposalService.java | 4 + .../db/api/BandwidthPriceHistoryLoader.java | 61 +++++ .../services/http/FullNodeHttpApiService.java | 6 +- .../http/GetBandwidthPricesServlet.java | 37 ++++ .../db/BandwidthPriceHistoryLoaderTest.java | 208 ++++++++++++++++++ .../core/db/EnergyPriceHistoryLoaderTest.java | 1 - .../core/services/ProposalServiceTest.java | 21 ++ 9 files changed, 405 insertions(+), 16 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/db/api/BandwidthPriceHistoryLoader.java create mode 100644 framework/src/main/java/org/tron/core/services/http/GetBandwidthPricesServlet.java create mode 100644 framework/src/test/java/org/tron/core/db/BandwidthPriceHistoryLoaderTest.java diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index e084f3ee6ed..dce79515ad4 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -77,6 +77,9 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking "CREATE_NEW_ACCOUNT_BANDWIDTH_RATE" .getBytes(); private static final byte[] TRANSACTION_FEE = "TRANSACTION_FEE".getBytes(); // 1 byte + private static final long DEFAULT_TRANSACTION_FEE = 10L; + public static final String DEFAULT_BANDWIDTH_PRICE_HISTORY = "0:" + DEFAULT_TRANSACTION_FEE; + private static final byte[] ASSET_ISSUE_FEE = "ASSET_ISSUE_FEE".getBytes(); private static final byte[] UPDATE_ACCOUNT_PERMISSION_FEE = "UPDATE_ACCOUNT_PERMISSION_FEE" .getBytes(); @@ -156,7 +159,8 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] MAX_FEE_LIMIT = "MAX_FEE_LIMIT".getBytes(); private static final byte[] BURN_TRX_AMOUNT = "BURN_TRX_AMOUNT".getBytes(); - private static final byte[] ALLOW_BLACKHOLE_OPTIMIZATION = "ALLOW_BLACKHOLE_OPTIMIZATION".getBytes(); + private static final byte[] ALLOW_BLACKHOLE_OPTIMIZATION = + "ALLOW_BLACKHOLE_OPTIMIZATION".getBytes(); private static final byte[] ALLOW_NEW_RESOURCE_MODEL = "ALLOW_NEW_RESOURCE_MODEL".getBytes(); private static final byte[] ALLOW_TVM_FREEZE = "ALLOW_TVM_FREEZE".getBytes(); private static final byte[] ALLOW_TVM_VOTE = "ALLOW_TVM_VOTE".getBytes(); @@ -169,11 +173,15 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking "ALLOW_ACCOUNT_ASSET_OPTIMIZATION".getBytes(); private static final byte[] ALLOW_ASSET_OPTIMIZATION = - "ALLOW_ASSET_OPTIMIZATION".getBytes(); + "ALLOW_ASSET_OPTIMIZATION".getBytes(); private static final byte[] ENERGY_PRICE_HISTORY = "ENERGY_PRICE_HISTORY".getBytes(); private static final byte[] ENERGY_PRICE_HISTORY_DONE = "ENERGY_PRICE_HISTORY_DONE".getBytes(); + private static final byte[] BANDWIDTH_PRICE_HISTORY = "BANDWIDTH_PRICE_HISTORY".getBytes(); + private static final byte[] BANDWIDTH_PRICE_HISTORY_DONE = + "BANDWIDTH_PRICE_HISTORY_DONE".getBytes(); + private static final byte[] SET_BLACKHOLE_ACCOUNT_PERMISSION = "SET_BLACKHOLE_ACCOUNT_PERMISSION".getBytes(); private static final byte[] ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX = @@ -378,7 +386,6 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { this.saveTotalTronPowerWeight(0L); } - try { this.getAllowAdaptiveEnergy(); } catch (IllegalArgumentException e) { @@ -449,7 +456,7 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { try { this.getTransactionFee(); } catch (IllegalArgumentException e) { - this.saveTransactionFee(10L); // 10sun/byte + this.saveTransactionFee(DEFAULT_TRANSACTION_FEE); // 10sun/byte } try { @@ -793,7 +800,7 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { this.getAllowAssetOptimization(); } catch (IllegalArgumentException e) { this.setAllowAssetOptimization(CommonParameter - .getInstance().getAllowAssetOptimization()); + .getInstance().getAllowAssetOptimization()); } try { @@ -815,6 +822,18 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { this.saveEnergyPriceHistory(DEFAULT_ENERGY_PRICE_HISTORY); } + try { + this.getBandwidthPriceHistoryDone(); + } catch (IllegalArgumentException e) { + this.saveBandwidthPriceHistoryDone(0); + } + + try { + this.getBandwidthPriceHistory(); + } catch (IllegalArgumentException e) { + this.saveBandwidthPriceHistory(DEFAULT_BANDWIDTH_PRICE_HISTORY); + } + try { this.getSetBlackholeAccountPermission(); } catch (IllegalArgumentException e) { @@ -2015,7 +2034,7 @@ public long getLatestBlockHeaderNumberFromDB() { .orElseThrow( () -> new IllegalArgumentException("not found latest block header number")); } catch (ItemNotFoundException | BadItemException e) { - logger.error("{}", e); + logger.error("{}", e); } return -1; } @@ -2385,10 +2404,10 @@ public long getNewRewardAlgorithmEffectiveCycle() { public long getAllowAccountAssetOptimizationFromRoot() { try { return Optional.ofNullable(getFromRoot(ALLOW_ASSET_OPTIMIZATION)) - .map(BytesCapsule::getData) - .map(ByteArray::toLong) - .orElseThrow( - () -> new IllegalArgumentException("not found ALLOW_ASSET_OPTIMIZATION")); + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException("not found ALLOW_ASSET_OPTIMIZATION")); } catch (Exception e) { logger.debug("{}", e.getMessage()); return CommonParameter.getInstance().getAllowAssetOptimization(); @@ -2411,16 +2430,17 @@ public void setAllowAccountAssetOptimization(long value) { // 1: enable public long getAllowAssetOptimization() { return Optional.ofNullable(getUnchecked(ALLOW_ASSET_OPTIMIZATION)) - .map(BytesCapsule::getData) - .map(ByteArray::toLong) - .orElseThrow( - () -> new IllegalArgumentException("not found ALLOW_ASSET_OPTIMIZATION")); + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException("not found ALLOW_ASSET_OPTIMIZATION")); } public void setAllowAssetOptimization(long value) { this.put(ALLOW_ASSET_OPTIMIZATION, new BytesCapsule(ByteArray.fromLong(value))); } + // for energy price history public void saveEnergyPriceHistoryDone(long value) { this.put(ENERGY_PRICE_HISTORY_DONE, new BytesCapsule(ByteArray.fromLong(value))); @@ -2445,6 +2465,31 @@ public void saveEnergyPriceHistory(String value) { this.put(ENERGY_PRICE_HISTORY, new BytesCapsule(ByteArray.fromString(value))); } + // for bandwidth price history + public void saveBandwidthPriceHistoryDone(long value) { + this.put(BANDWIDTH_PRICE_HISTORY_DONE, + new BytesCapsule(ByteArray.fromLong(value))); + } + + public long getBandwidthPriceHistoryDone() { + return Optional.ofNullable(getUnchecked(BANDWIDTH_PRICE_HISTORY_DONE)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException("not found BANDWIDTH_PRICE_HISTORY_DONE")); + } + + public String getBandwidthPriceHistory() { + return Optional.ofNullable(getUnchecked(BANDWIDTH_PRICE_HISTORY)) + .map(BytesCapsule::getData) + .map(ByteArray::toStr) + .orElseThrow(() -> new IllegalArgumentException("not found BANDWIDTH_PRICE_HISTORY")); + } + + public void saveBandwidthPriceHistory(String value) { + this.put(BANDWIDTH_PRICE_HISTORY, new BytesCapsule(ByteArray.fromString(value))); + } + public long getSetBlackholeAccountPermission() { return Optional.of(getUnchecked(SET_BLACKHOLE_ACCOUNT_PERMISSION)) .map(BytesCapsule::getData) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 29c61082681..1c487fa5dc7 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -3954,6 +3954,16 @@ public String getEnergyPrices() { return null; } + public String getBandwidthPrices() { + try { + return chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistory(); + } catch (Exception e) { + logger.error("getBandwidthPrices failed, error is {}", e.getMessage()); + } + + return null; + } + public String getCoinbase() { if (!CommonParameter.getInstance().isWitness()) { return null; diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 21c3e70896f..f6f55b0097c 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -40,6 +40,10 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) } case TRANSACTION_FEE: { manager.getDynamicPropertiesStore().saveTransactionFee(entry.getValue()); + // update bandwidth price history + manager.getDynamicPropertiesStore().saveBandwidthPriceHistory( + manager.getDynamicPropertiesStore().getBandwidthPriceHistory() + + "," + proposalCapsule.getExpirationTime() + ":" + entry.getValue()); break; } case ASSET_ISSUE_FEE: { diff --git a/framework/src/main/java/org/tron/core/db/api/BandwidthPriceHistoryLoader.java b/framework/src/main/java/org/tron/core/db/api/BandwidthPriceHistoryLoader.java new file mode 100644 index 00000000000..e3df76450b1 --- /dev/null +++ b/framework/src/main/java/org/tron/core/db/api/BandwidthPriceHistoryLoader.java @@ -0,0 +1,61 @@ +package org.tron.core.db.api; + +import java.util.ArrayList; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.tron.core.ChainBaseManager; +import org.tron.core.capsule.ProposalCapsule; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.utils.ProposalUtil.ProposalType; +import org.tron.protos.Protocol.Proposal.State; + +@Slf4j(topic = "DB") +public class BandwidthPriceHistoryLoader { + + private final ChainBaseManager chainBaseManager; + private List proposalCapsuleList = new ArrayList<>(); + + public BandwidthPriceHistoryLoader(ChainBaseManager chainBaseManager) { + this.chainBaseManager = chainBaseManager; + } + + public void doWork() { + long start = System.currentTimeMillis(); + logger.info("Start to load bandwidth price"); + + getBandwidthProposals(); + if (!proposalCapsuleList.isEmpty()) { + String bandwidthPriceHistory = parseProposalsToStr(); + chainBaseManager.getDynamicPropertiesStore().saveBandwidthPriceHistory(bandwidthPriceHistory); + } + finish(); + + logger.info( + "Complete bandwidth price load, total time: {} milliseconds, total proposal count: {}", + System.currentTimeMillis() - start, proposalCapsuleList.size()); + } + + public void getBandwidthProposals() { + proposalCapsuleList = chainBaseManager.getProposalStore() + .getSpecifiedProposals(State.APPROVED, ProposalType.TRANSACTION_FEE.getCode()); + } + + public String parseProposalsToStr() { + StringBuilder builder = + new StringBuilder(DynamicPropertiesStore.DEFAULT_BANDWIDTH_PRICE_HISTORY); + + for (ProposalCapsule proposalCapsule : proposalCapsuleList) { + builder.append(",") + .append(proposalCapsule.getExpirationTime()) + .append(":") + .append(proposalCapsule.getParameters().get(ProposalType.TRANSACTION_FEE.getCode())); + } + + return builder.toString(); + } + + public void finish() { + chainBaseManager.getDynamicPropertiesStore().saveBandwidthPriceHistoryDone(1); + } + +} diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index 98e8bc88614..031bd38e50c 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -289,7 +289,8 @@ public class FullNodeHttpApiService implements Service { private GetPendingSizeServlet getPendingSizeServlet; @Autowired private GetEnergyPricesServlet getEnergyPricesServlet; - + @Autowired + private GetBandwidthPricesServlet getBandwidthPricesServlet; @Autowired private GetBlockServlet getBlockServlet; @@ -538,7 +539,10 @@ public void start() { "/wallet/gettransactionlistfrompending"); context.addServlet(new ServletHolder(getPendingSizeServlet), "/wallet/getpendingsize"); context.addServlet(new ServletHolder(getEnergyPricesServlet), "/wallet/getenergyprices"); + context.addServlet(new ServletHolder(getBandwidthPricesServlet), + "/wallet/getbandwidthprices"); context.addServlet(new ServletHolder(getBlockServlet), "/wallet/getblock"); + int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { server.addBean(new ConnectionLimit(maxHttpConnectNumber, server)); diff --git a/framework/src/main/java/org/tron/core/services/http/GetBandwidthPricesServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBandwidthPricesServlet.java new file mode 100644 index 00000000000..ea4b535af39 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/GetBandwidthPricesServlet.java @@ -0,0 +1,37 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; + + +@Component +@Slf4j(topic = "API") +public class GetBandwidthPricesServlet extends RateLimiterServlet { + + @Autowired + private Wallet wallet; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + try { + String reply = wallet.getBandwidthPrices(); + if (reply != null) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("prices", reply); + response.getWriter().println(jsonObject); + } else { + response.getWriter().println("{}"); + } + } catch (Exception e) { + Util.processError(e, response); + } + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + doGet(request, response); + } +} diff --git a/framework/src/test/java/org/tron/core/db/BandwidthPriceHistoryLoaderTest.java b/framework/src/test/java/org/tron/core/db/BandwidthPriceHistoryLoaderTest.java new file mode 100644 index 00000000000..2d72d36395d --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/BandwidthPriceHistoryLoaderTest.java @@ -0,0 +1,208 @@ +package org.tron.core.db; + +import static org.tron.core.store.DynamicPropertiesStore.DEFAULT_BANDWIDTH_PRICE_HISTORY; +import static org.tron.core.utils.ProposalUtil.ProposalType.ALLOW_CREATION_OF_CONTRACTS; +import static org.tron.core.utils.ProposalUtil.ProposalType.ALLOW_TVM_FREEZE; +import static org.tron.core.utils.ProposalUtil.ProposalType.ALLOW_TVM_LONDON; +import static org.tron.core.utils.ProposalUtil.ProposalType.ALLOW_TVM_VOTE; +import static org.tron.core.utils.ProposalUtil.ProposalType.ASSET_ISSUE_FEE; +import static org.tron.core.utils.ProposalUtil.ProposalType.CREATE_ACCOUNT_FEE; +import static org.tron.core.utils.ProposalUtil.ProposalType.CREATE_NEW_ACCOUNT_FEE_IN_SYSTEM_CONTRACT; +import static org.tron.core.utils.ProposalUtil.ProposalType.TRANSACTION_FEE; +import static org.tron.core.utils.ProposalUtil.ProposalType.WITNESS_127_PAY_PER_BLOCK; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.FileUtil; +import org.tron.core.ChainBaseManager; +import org.tron.core.Constant; +import org.tron.core.capsule.ProposalCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.db.api.BandwidthPriceHistoryLoader; +import org.tron.protos.Protocol.Proposal; +import org.tron.protos.Protocol.Proposal.State; + + +@Slf4j +public class BandwidthPriceHistoryLoaderTest { + + private static ChainBaseManager chainBaseManager; + private static TronApplicationContext context; + private static final String dbPath = "output-BandwidthPriceHistoryLoaderTest-test"; + private static long t1; + private static long price1; + private static long t2; + private static long price2; + private static long t5; + private static long price5; + + // Note, here use @Before and @After instead of @BeforeClass and @AfterClass, + // because it needs to initialize DB before the single test every time + @Before + public void init() { + Args.setParam(new String[] {"--output-directory", dbPath}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + chainBaseManager = context.getBean(ChainBaseManager.class); + } + + @After + public void destroy() { + Args.clearParam(); + context.destroy(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.info("Release resources failure."); + } + } + + public void initDB() { + t1 = 1606240800000L; + price1 = 40; + initProposal(TRANSACTION_FEE.getCode(), t1, price1, State.APPROVED); + + t2 = 1613044800000L; + price2 = 140; + initProposal(TRANSACTION_FEE.getCode(), t2, price2, State.APPROVED); + + long t3 = 1626501600000L; + long price3 = 1000; + Map parameters = new HashMap<>(); + parameters.put(TRANSACTION_FEE.getCode(), price3); + parameters.put(CREATE_NEW_ACCOUNT_FEE_IN_SYSTEM_CONTRACT.getCode(), 1000000L); + initProposal(parameters, t3, State.CANCELED); + + long t4 = 1626501600000L; + long price4 = 1000; + parameters = new HashMap<>(); + parameters.put(TRANSACTION_FEE.getCode(), price4); + parameters.put(CREATE_NEW_ACCOUNT_FEE_IN_SYSTEM_CONTRACT.getCode(), 1000000L); + initProposal(parameters, t4, State.DISAPPROVED); + + t5 = 1627279200000L; + price5 = 1000L; + parameters = new HashMap<>(); + parameters.put(TRANSACTION_FEE.getCode(), price4); + parameters.put(CREATE_NEW_ACCOUNT_FEE_IN_SYSTEM_CONTRACT.getCode(), 1000000L); + initProposal(parameters, t5, State.APPROVED); + + long t6 = 1634299200000L; + parameters = new HashMap<>(); + parameters.put(ALLOW_TVM_FREEZE.getCode(), 1L); + parameters.put(ALLOW_TVM_VOTE.getCode(), 1L); + initProposal(parameters, t6, State.DISAPPROVED); + + initProposal(ALLOW_TVM_LONDON.getCode(), 1647604800000L, 1, State.APPROVED); + + initProposal(ALLOW_CREATION_OF_CONTRACTS.getCode(), 1539259200000L, 1, State.APPROVED); + initProposal(CREATE_ACCOUNT_FEE.getCode(), 1621468800000L, 1, State.DISAPPROVED); + + parameters = new HashMap<>(); + parameters.put(ASSET_ISSUE_FEE.getCode(), 48000000L); + parameters.put(WITNESS_127_PAY_PER_BLOCK.getCode(), 128000000L); + initProposal(parameters, 1572609600000L, State.CANCELED); + } + + private static void initProposal(long code, long timestamp, long price, State state) { + long id = chainBaseManager.getDynamicPropertiesStore().getLatestProposalNum() + 1; + + Proposal proposal = Proposal.newBuilder().putParameters(code, price) + .setExpirationTime(timestamp) + .setState(state) + .setProposalId(id) + .build(); + ProposalCapsule proposalCapsule = new ProposalCapsule(proposal); + + chainBaseManager.getProposalStore().put(proposalCapsule.createDbKey(), proposalCapsule); + chainBaseManager.getDynamicPropertiesStore().saveLatestProposalNum(id); + } + + private static void initProposal(Map parameters, long timestamp, State state) { + long id = chainBaseManager.getDynamicPropertiesStore().getLatestProposalNum() + 1; + + Proposal proposal = Proposal.newBuilder().putAllParameters(parameters) + .setExpirationTime(timestamp) + .setState(state) + .setProposalId(id) + .build(); + ProposalCapsule proposalCapsule = new ProposalCapsule(proposal); + + chainBaseManager.getProposalStore().put(proposalCapsule.createDbKey(), proposalCapsule); + chainBaseManager.getDynamicPropertiesStore().saveLatestProposalNum(id); + } + + @Test + public void testLoaderWork() { + Assert.assertEquals(0L, + chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistoryDone()); + + initDB(); + + String preBandwidthPriceHistory = + chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistory(); + String expectedRes = preBandwidthPriceHistory + "," + t1 + ":" + price1 + + "," + t2 + ":" + price2 + + "," + t5 + ":" + price5; + + BandwidthPriceHistoryLoader loader = new BandwidthPriceHistoryLoader(chainBaseManager); + loader.getBandwidthProposals(); + String historyStr = loader.parseProposalsToStr(); + + Assert.assertEquals(expectedRes, historyStr); + Assert.assertEquals(0L, + chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistoryDone()); + } + + @Test + public void testProposalEmpty() { + Assert.assertEquals(0L, + chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistoryDone()); + String preBandwidthPriceHistory = + chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistory(); + Assert.assertEquals(DEFAULT_BANDWIDTH_PRICE_HISTORY, preBandwidthPriceHistory); + + // loader work + BandwidthPriceHistoryLoader loader = new BandwidthPriceHistoryLoader(chainBaseManager); + loader.doWork(); + + // check result + String afterBandwidthPriceHistory = + chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistory(); + Assert.assertEquals(DEFAULT_BANDWIDTH_PRICE_HISTORY, afterBandwidthPriceHistory); + Assert.assertEquals(1L, + chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistoryDone()); + } + + @Test + public void testLoaderWithProposals() { + String preBandwidthPriceHistory = + chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistory(); + Assert.assertEquals(DEFAULT_BANDWIDTH_PRICE_HISTORY, preBandwidthPriceHistory); + + // init proposals + initDB(); + + // loader work + BandwidthPriceHistoryLoader loader = new BandwidthPriceHistoryLoader(chainBaseManager); + loader.doWork(); + + // check result + String afterBandwidthPriceHistory = + chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistory(); + String expectedRes = preBandwidthPriceHistory + "," + t1 + ":" + price1 + + "," + t2 + ":" + price2 + + "," + t5 + ":" + price5; + + Assert.assertEquals(expectedRes, afterBandwidthPriceHistory); + Assert.assertEquals(1L, + chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistoryDone()); + } +} diff --git a/framework/src/test/java/org/tron/core/db/EnergyPriceHistoryLoaderTest.java b/framework/src/test/java/org/tron/core/db/EnergyPriceHistoryLoaderTest.java index 7700dbdead2..13107480bf5 100644 --- a/framework/src/test/java/org/tron/core/db/EnergyPriceHistoryLoaderTest.java +++ b/framework/src/test/java/org/tron/core/db/EnergyPriceHistoryLoaderTest.java @@ -15,7 +15,6 @@ import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.tron.common.application.TronApplicationContext; import org.tron.common.utils.FileUtil; diff --git a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java index 10faf6e19ca..7978d98a9fe 100644 --- a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java @@ -1,6 +1,7 @@ package org.tron.core.services; import static org.tron.core.utils.ProposalUtil.ProposalType.ENERGY_FEE; +import static org.tron.core.utils.ProposalUtil.ProposalType.TRANSACTION_FEE; import static org.tron.core.utils.ProposalUtil.ProposalType.WITNESS_127_PAY_PER_BLOCK; import java.io.File; @@ -84,6 +85,26 @@ public void testUpdateEnergyFee() { currentHistory); } + @Test + public void testUpdateTransactionFee() { + String preHistory = manager.getDynamicPropertiesStore().getBandwidthPriceHistory(); + + long newPrice = 1500; + Proposal proposal = + Proposal.newBuilder().putParameters(TRANSACTION_FEE.getCode(), newPrice).build(); + ProposalCapsule proposalCapsule = new ProposalCapsule(proposal); + proposalCapsule.setExpirationTime(1627279200000L); + boolean result = ProposalService.process(manager, proposalCapsule); + Assert.assertTrue(result); + + long currentPrice = manager.getDynamicPropertiesStore().getTransactionFee(); + Assert.assertEquals(currentPrice, newPrice); + + String expResult = preHistory + "," + proposalCapsule.getExpirationTime() + ":" + newPrice; + String currentHistory = manager.getDynamicPropertiesStore().getBandwidthPriceHistory(); + Assert.assertEquals(expResult, currentHistory); + } + @AfterClass public static void removeDb() { Args.clearParam(); From f219feef4fc7b18e8fa3c11ad2bfd2f8057ec437 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Wed, 27 Jul 2022 18:42:12 +0800 Subject: [PATCH 0177/1197] feat(bandwidth_prices): load bandwidth prices when init --- framework/src/main/java/org/tron/core/db/Manager.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 2d0f85a94d0..d2cfb33669b 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -96,6 +96,7 @@ import org.tron.core.db.accountstate.TrieService; import org.tron.core.db.accountstate.callback.AccountStateCallBack; import org.tron.core.db.api.AssetUpdateHelper; +import org.tron.core.db.api.BandwidthPriceHistoryLoader; import org.tron.core.db.api.EnergyPriceHistoryLoader; import org.tron.core.db.api.MoveAbiHelper; import org.tron.core.db2.ISession; @@ -323,6 +324,10 @@ private boolean needToLoadEnergyPriceHistory() { return getDynamicPropertiesStore().getEnergyPriceHistoryDone() == 0L; } + private boolean needToLoadBandwidthPriceHistory() { + return getDynamicPropertiesStore().getBandwidthPriceHistoryDone() == 0L; + } + public boolean needToSetBlackholePermission() { return getDynamicPropertiesStore().getSetBlackholeAccountPermission() == 0L; } @@ -480,6 +485,10 @@ public void init() { new EnergyPriceHistoryLoader(chainBaseManager).doWork(); } + if (needToLoadBandwidthPriceHistory()) { + new BandwidthPriceHistoryLoader(chainBaseManager).doWork(); + } + if (needToSetBlackholePermission()) { resetBlackholeAccountPermission(); } From ad4bf2fe8559547812731321437125746f4e3aa0 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Wed, 27 Jul 2022 21:52:44 +0800 Subject: [PATCH 0178/1197] feat: set saveBandwidthPriceHistoryDone as 0 before test --- .../org/tron/core/db/BandwidthPriceHistoryLoaderTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/framework/src/test/java/org/tron/core/db/BandwidthPriceHistoryLoaderTest.java b/framework/src/test/java/org/tron/core/db/BandwidthPriceHistoryLoaderTest.java index 2d72d36395d..a91c3f96c70 100644 --- a/framework/src/test/java/org/tron/core/db/BandwidthPriceHistoryLoaderTest.java +++ b/framework/src/test/java/org/tron/core/db/BandwidthPriceHistoryLoaderTest.java @@ -141,8 +141,6 @@ private static void initProposal(Map parameters, long timestamp, Sta @Test public void testLoaderWork() { - Assert.assertEquals(0L, - chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistoryDone()); initDB(); @@ -163,12 +161,12 @@ public void testLoaderWork() { @Test public void testProposalEmpty() { - Assert.assertEquals(0L, - chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistoryDone()); String preBandwidthPriceHistory = chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistory(); Assert.assertEquals(DEFAULT_BANDWIDTH_PRICE_HISTORY, preBandwidthPriceHistory); + chainBaseManager.getDynamicPropertiesStore().saveBandwidthPriceHistoryDone(0); + // loader work BandwidthPriceHistoryLoader loader = new BandwidthPriceHistoryLoader(chainBaseManager); loader.doWork(); @@ -187,6 +185,8 @@ public void testLoaderWithProposals() { chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistory(); Assert.assertEquals(DEFAULT_BANDWIDTH_PRICE_HISTORY, preBandwidthPriceHistory); + chainBaseManager.getDynamicPropertiesStore().saveBandwidthPriceHistoryDone(0); + // init proposals initDB(); From d8a09e1ca8b1d7f95526688d56a659d8b996aef1 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Thu, 28 Jul 2022 10:56:50 +0800 Subject: [PATCH 0179/1197] feat: remove check andwidthPriceHistoryDone --- .../java/org/tron/core/db/BandwidthPriceHistoryLoaderTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/framework/src/test/java/org/tron/core/db/BandwidthPriceHistoryLoaderTest.java b/framework/src/test/java/org/tron/core/db/BandwidthPriceHistoryLoaderTest.java index a91c3f96c70..4c7af2b31fe 100644 --- a/framework/src/test/java/org/tron/core/db/BandwidthPriceHistoryLoaderTest.java +++ b/framework/src/test/java/org/tron/core/db/BandwidthPriceHistoryLoaderTest.java @@ -155,8 +155,6 @@ public void testLoaderWork() { String historyStr = loader.parseProposalsToStr(); Assert.assertEquals(expectedRes, historyStr); - Assert.assertEquals(0L, - chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistoryDone()); } @Test From 25ab12561e47d9b8c26138c778bdab1fbe2a5caa Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Fri, 29 Jul 2022 14:32:08 +0800 Subject: [PATCH 0180/1197] perf(block): optimize block processing thread acquires the lock code --- .../tron/core/consensus/BlockHandleImpl.java | 6 +---- .../main/java/org/tron/core/db/Manager.java | 23 +++++++++++++++---- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/framework/src/main/java/org/tron/core/consensus/BlockHandleImpl.java b/framework/src/main/java/org/tron/core/consensus/BlockHandleImpl.java index 03452546a9b..fcfb801d1ce 100644 --- a/framework/src/main/java/org/tron/core/consensus/BlockHandleImpl.java +++ b/framework/src/main/java/org/tron/core/consensus/BlockHandleImpl.java @@ -60,10 +60,6 @@ public BlockCapsule produce(Miner miner, long blockTime, long timeout) { } public void setBlockWaitLock(boolean flag) { - if (flag) { - manager.getBlockWaitLock().incrementAndGet(); - } else { - manager.getBlockWaitLock().decrementAndGet(); - } + manager.setBlockWaitLock(flag); } } diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 539c6d4c700..da8b7491248 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -169,6 +169,8 @@ public class Manager { private static final String SAVE_BLOCK = "save block: "; private static final int SLEEP_TIME_OUT = 50; private static final int TX_ID_CACHE_SIZE = 100_000; + private static final int SLEEP_FOR_WAIT_LOCK = 10; + private static final int NO_BLOCK_WAITING_LOCK = 0; private final int shieldedTransInPendingMaxCounts = Args.getInstance().getShieldedTransInPendingMaxCounts(); @Getter @@ -240,7 +242,6 @@ public class Manager { @Getter private final ThreadLocal blockedTimer = new ThreadLocal<>(); - @Getter private AtomicInteger blockWaitLock = new AtomicInteger(0); private Object transactionLock = new Object(); @@ -773,8 +774,8 @@ public boolean pushTransaction(final TransactionCapsule trx) synchronized (transactionLock) { while (true) { try { - if (blockWaitLock.get() > 0) { - TimeUnit.MILLISECONDS.sleep(10); + if (isBlockWaitingLock()) { + TimeUnit.MILLISECONDS.sleep(SLEEP_FOR_WAIT_LOCK); } else { break; } @@ -1084,7 +1085,7 @@ public void pushBlock(final BlockCapsule block) DupTransactionException, TransactionExpirationException, BadNumberBlockException, BadBlockException, NonCommonBlockException, ReceiptCheckErrException, VMIllegalException, ZksnarkException, EventBloomException { - blockWaitLock.incrementAndGet(); + setBlockWaitLock(true); try { synchronized (this) { Metrics.histogramObserve(blockedTimer.get()); @@ -1251,7 +1252,7 @@ public void pushBlock(final BlockCapsule block) Metrics.histogramObserve(timer); } } finally { - blockWaitLock.decrementAndGet(); + setBlockWaitLock(false); } } @@ -2270,6 +2271,18 @@ public long getPendingSize() { return value; } + public void setBlockWaitLock(boolean waitFlag) { + if (waitFlag) { + blockWaitLock.incrementAndGet(); + } else { + blockWaitLock.decrementAndGet(); + } + } + + private boolean isBlockWaitingLock() { + return blockWaitLock.get() > NO_BLOCK_WAITING_LOCK; + } + private static class ValidateSignTask implements Callable { private TransactionCapsule trx; From d56d5b5261364bc16fa618852a53e2657193fa33 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Fri, 29 Jul 2022 19:15:52 +0800 Subject: [PATCH 0181/1197] feat: catch DecoderException when address is not base58 in GetRewardServlet --- .../org/tron/core/services/http/GetRewardServlet.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/framework/src/main/java/org/tron/core/services/http/GetRewardServlet.java b/framework/src/main/java/org/tron/core/services/http/GetRewardServlet.java index d1903a0fb2c..390f7973bc3 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetRewardServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetRewardServlet.java @@ -4,6 +4,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.DecoderException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.core.db.Manager; @@ -24,6 +25,13 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { value = manager.getMortgageService().queryReward(address); } response.getWriter().println("{\"reward\": " + value + "}"); + } catch (DecoderException e) { + try { + response.getWriter() + .println("{\"Error\": " + "\"INVALID base58 String, " + e.getMessage() + "\"}"); + } catch (IOException ioe) { + logger.debug("IOException: {}", ioe.getMessage()); + } } catch (Exception e) { logger.error("", e); try { From 294b63218f88837bd02468a1494b1b62a596cd67 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Fri, 29 Jul 2022 19:19:42 +0800 Subject: [PATCH 0182/1197] feat: update error msg --- .../main/java/org/tron/core/services/http/GetRewardServlet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/http/GetRewardServlet.java b/framework/src/main/java/org/tron/core/services/http/GetRewardServlet.java index 390f7973bc3..14d6f11770d 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetRewardServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetRewardServlet.java @@ -28,7 +28,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { } catch (DecoderException e) { try { response.getWriter() - .println("{\"Error\": " + "\"INVALID base58 String, " + e.getMessage() + "\"}"); + .println("{\"Error\": " + "\"INVALID address, " + e.getMessage() + "\"}"); } catch (IOException ioe) { logger.debug("IOException: {}", ioe.getMessage()); } From 0e74efc5a3c8228da02834b8072d51f495d856e9 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 29 Jul 2022 17:56:32 +0800 Subject: [PATCH 0183/1197] tool(db):db path move function. 1. print help if no params. 2. remove toolkit name. 3. if config or path not exist,print error --- .../src/main/java/org/tron/plugins/Db.java | 26 +++++++++++++++-- .../main/java/org/tron/plugins/DbMove.java | 29 ++++++++++++++----- .../main/java/org/tron/plugins/Toolkit.java | 11 +++++-- 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/plugins/src/main/java/org/tron/plugins/Db.java b/plugins/src/main/java/org/tron/plugins/Db.java index a886d717c6d..e03a412c1a9 100644 --- a/plugins/src/main/java/org/tron/plugins/Db.java +++ b/plugins/src/main/java/org/tron/plugins/Db.java @@ -2,6 +2,9 @@ import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory; +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; import java.nio.file.Paths; import picocli.CommandLine; @@ -18,8 +21,27 @@ static class ConfigConverter implements CommandLine.ITypeConverter { ConfigConverter() { } - public Config convert(String value) { - return ConfigFactory.parseFile(Paths.get(value).toFile()); + public Config convert(String value) throws IOException { + File file = Paths.get(value).toFile(); + if (file.exists() && file.isFile()) { + return ConfigFactory.parseFile(Paths.get(value).toFile()); + } else { + throw new IOException("DB config [" + value + "] not exist!"); + } + } + } + + static class PathConverter implements CommandLine.ITypeConverter { + PathConverter() { + } + + public Path convert(String value) throws IOException { + File file = Paths.get(value).toFile(); + if (file.exists() && file.isDirectory()) { + return file.toPath(); + } else { + throw new IOException("DB path [" + value + "] not exist!"); + } } } } diff --git a/plugins/src/main/java/org/tron/plugins/DbMove.java b/plugins/src/main/java/org/tron/plugins/DbMove.java index 67bc3a57706..d9a2a8b4831 100644 --- a/plugins/src/main/java/org/tron/plugins/DbMove.java +++ b/plugins/src/main/java/org/tron/plugins/DbMove.java @@ -25,15 +25,16 @@ public class DbMove implements Callable { private static final String DEFAULT_DB_DIRECTORY = "database"; private static final String NAME_CONFIG_KEY = "name"; private static final String PATH_CONFIG_KEY = "path"; - private static final String NOT_FIND = "The database to be moved cannot be found."; + private static final String NOT_FIND = "There is no database to be moved, exist."; @CommandLine.Spec CommandLine.Model.CommandSpec spec; @CommandLine.Option(names = {"-d", "--database-directory"}, defaultValue = "output-directory", + converter = Db.PathConverter.class, description = "database directory path. Default: ${DEFAULT-VALUE}") - String database; + Path database; @CommandLine.Option(names = {"-c", "--config"}, defaultValue = "config.conf", @@ -50,10 +51,11 @@ public Integer call() throws Exception { spec.commandLine().usage(System.out); return 0; } + if (config.hasPath(PROPERTIES_CONFIG_KEY)) { List dbs = config.getConfigList(PROPERTIES_CONFIG_KEY); if (dbs.isEmpty()) { - spec.commandLine().getOut().println(NOT_FIND); + printNotExist(); return 0; } String dbPath = config.hasPath(DB_DIRECTORY_CONFIG_KEY) @@ -64,14 +66,14 @@ public Integer call() throws Exception { .collect(Collectors.toList()); if (dbs.isEmpty()) { - spec.commandLine().getOut().println(NOT_FIND); + printNotExist(); return 0; } List toBeMove = dbs.stream() .map(c -> { try { return new Property(c.getString(NAME_CONFIG_KEY), - Paths.get(database, dbPath, c.getString(NAME_CONFIG_KEY)), + Paths.get(database.toString(), dbPath, c.getString(NAME_CONFIG_KEY)), Paths.get(c.getString(PATH_CONFIG_KEY), dbPath, c.getString(NAME_CONFIG_KEY))); } catch (IOException e) { spec.commandLine().getErr().println(e); @@ -81,7 +83,7 @@ public Integer call() throws Exception { .filter(p -> !p.destination.equals(p.original)).collect(Collectors.toList()); if (toBeMove.isEmpty()) { - spec.commandLine().getOut().println(NOT_FIND); + printNotExist(); return 0; } toBeMove = toBeMove.stream() @@ -96,14 +98,15 @@ public Integer call() throws Exception { }).collect(Collectors.toList()); if (toBeMove.isEmpty()) { - spec.commandLine().getOut().println(NOT_FIND); + printNotExist(); return 0; } ProgressBar.wrap(toBeMove.stream(), "mv task").forEach(this::run); spec.commandLine().getOut().println("move db done."); } else { - spec.commandLine().getOut().println(NOT_FIND); + printNotExist(); + return 0; } return 0; } @@ -133,6 +136,10 @@ private void run(Property p) { } } + private void printNotExist() { + spec.commandLine().getErr().println(NOT_FIND); + } + /** * delete directory. */ @@ -157,6 +164,12 @@ static class Property { public Property(String name, Path original, Path destination) throws IOException { this.name = name; this.original = original.toFile().getCanonicalFile().toPath(); + if (!this.original.toFile().exists()) { + throw new IOException(this.original + " not exist!"); + } + if (this.original.toFile().isFile()) { + throw new IOException(this.original + " is a file!"); + } this.destination = destination.toFile().getCanonicalFile().toPath(); } } diff --git a/plugins/src/main/java/org/tron/plugins/Toolkit.java b/plugins/src/main/java/org/tron/plugins/Toolkit.java index 4a087e40b34..3b9972de1c5 100644 --- a/plugins/src/main/java/org/tron/plugins/Toolkit.java +++ b/plugins/src/main/java/org/tron/plugins/Toolkit.java @@ -3,13 +3,18 @@ import java.util.concurrent.Callable; import picocli.CommandLine; -@CommandLine.Command(name = "tron", subcommands = { CommandLine.HelpCommand.class, Db.class}) +@CommandLine.Command(subcommands = { CommandLine.HelpCommand.class, Db.class}) public class Toolkit implements Callable { public static void main(String[] args) { - int exitCode = new CommandLine(new Toolkit()).execute(args); - System.exit(exitCode); + CommandLine cli = new CommandLine(new Toolkit()); + if (args == null || args.length == 0) { + cli.usage(System.out); + } else { + int exitCode = cli.execute(args); + System.exit(exitCode); + } } @Override From cac3e60a556c77fdc8aed2386a30bf2d0492a3e2 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 1 Aug 2022 18:09:57 +0800 Subject: [PATCH 0184/1197] fix(net): solve the null pointer problem caused by the change of peer ID --- .../org/tron/core/net/service/AdvService.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/AdvService.java b/framework/src/main/java/org/tron/core/net/service/AdvService.java index 611e0f47a1f..2df3598f611 100644 --- a/framework/src/main/java/org/tron/core/net/service/AdvService.java +++ b/framework/src/main/java/org/tron/core/net/service/AdvService.java @@ -333,13 +333,19 @@ public void add(Entry id, PeerConnection peer) { } public void add(Item id, PeerConnection peer) { - if (send.containsKey(peer) && !send.get(peer).containsKey(id.getType())) { - send.get(peer).put(id.getType(), new LinkedList<>()); - } else if (!send.containsKey(peer)) { - send.put(peer, new HashMap<>()); - send.get(peer).put(id.getType(), new LinkedList<>()); + HashMap> map = send.get(peer); + if (map == null) { + map = new HashMap<>(); + send.put(peer, map); } - send.get(peer).get(id.getType()).offer(id.getHash()); + + LinkedList list = map.get(id.getType()); + if (list == null) { + list = new LinkedList<>(); + map.put(id.getType(), list); + } + + list.offer(id.getHash()); } public int getSize(PeerConnection peer) { From 44a5ce275dda08f2da751ed7310a43f44374e158 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 1 Aug 2022 18:48:02 +0800 Subject: [PATCH 0185/1197] merge pr 4536 4537 --- .../common/overlay/server/ChannelManager.java | 16 ++++++++-------- .../tron/common/overlay/server/MessageQueue.java | 11 +++++++++++ .../org/tron/core/net/service/SyncService.java | 8 ++++---- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java b/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java index 114df13d847..1bed907c270 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java +++ b/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java @@ -34,7 +34,7 @@ @Component public class ChannelManager { - private final Map activePeers = new ConcurrentHashMap<>(); + private final Map activeChannels = new ConcurrentHashMap<>(); @Autowired private PeerServer peerServer; @Autowired @@ -124,7 +124,7 @@ public void processDisconnect(Channel channel, ReasonCode reason) { public void notifyDisconnect(Channel channel) { syncPool.onDisconnect(channel); - activePeers.values().remove(channel); + activeChannels.values().remove(channel); if (channel != null) { if (channel.getNodeStatistics() != null) { channel.getNodeStatistics().notifyDisconnect(); @@ -149,7 +149,7 @@ public synchronized boolean processPeer(Channel peer) { return false; } - if (!peer.isActive() && activePeers.size() >= maxConnections) { + if (!peer.isActive() && activeChannels.size() >= maxConnections) { peer.disconnect(TOO_MANY_PEERS); return false; } @@ -160,7 +160,7 @@ public synchronized boolean processPeer(Channel peer) { } } - Channel channel = activePeers.get(peer.getNodeIdWrapper()); + Channel channel = activeChannels.get(peer.getNodeIdWrapper()); if (channel != null) { if (channel.getStartTime() > peer.getStartTime()) { logger.info("Disconnect connection established later, {}", channel.getNode()); @@ -170,14 +170,14 @@ public synchronized boolean processPeer(Channel peer) { return false; } } - activePeers.put(peer.getNodeIdWrapper(), peer); - logger.info("Add active peer {}, total active peers: {}", peer, activePeers.size()); + activeChannels.put(peer.getNodeIdWrapper(), peer); + logger.info("Add active peer {}, total active peers: {}", peer, activeChannels.size()); return true; } public int getConnectionNum(InetAddress inetAddress) { int cnt = 0; - for (Channel channel : activePeers.values()) { + for (Channel channel : activeChannels.values()) { if (channel.getInetAddress().equals(inetAddress)) { cnt++; } @@ -186,7 +186,7 @@ public int getConnectionNum(InetAddress inetAddress) { } public Collection getActivePeers() { - return activePeers.values(); + return activeChannels.values(); } public Cache getRecentlyDisconnected() { diff --git a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java index 1919042232f..a8db0225be4 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java +++ b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java @@ -69,6 +69,12 @@ public void activate(ChannelHandlerContext ctx) { continue; } Message msg = msgQueue.take(); + if (channel.isDisconnect()) { + logger.warn("Failed to send to {} as channel has closed, {}", + ctx.channel().remoteAddress(), msg); + msgQueue.clear(); + return; + } ctx.writeAndFlush(msg.getSendData()).addListener((ChannelFutureListener) future -> { if (!future.isSuccess() && !channel.isDisconnect()) { logger.warn("Failed to send to {}, {}", ctx.channel().remoteAddress(), msg); @@ -92,6 +98,11 @@ public void setChannel(Channel channel) { } public void fastSend(Message msg) { + if (channel.isDisconnect()) { + logger.warn("Fast send to {} failed as channel has closed, {} ", + ctx.channel().remoteAddress(), msg); + return; + } logger.info("Fast send to {}, {} ", ctx.channel().remoteAddress(), msg); ctx.writeAndFlush(msg.getSendData()).addListener((ChannelFutureListener) future -> { if (!future.isSuccess() && !channel.isDisconnect()) { diff --git a/framework/src/main/java/org/tron/core/net/service/SyncService.java b/framework/src/main/java/org/tron/core/net/service/SyncService.java index 49dc9ce2d7a..a845636784f 100644 --- a/framework/src/main/java/org/tron/core/net/service/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/SyncService.java @@ -238,8 +238,8 @@ private synchronized void handleSyncBlock() { isProcessed[0] = false; - synchronized (tronNetDelegate.getBlockLock()) { - blockWaitToProcess.forEach((msg, peerConnection) -> { + blockWaitToProcess.forEach((msg, peerConnection) -> { + synchronized (tronNetDelegate.getBlockLock()) { if (peerConnection.isDisconnect()) { blockWaitToProcess.remove(msg); invalid(msg.getBlockId()); @@ -258,8 +258,8 @@ private synchronized void handleSyncBlock() { isProcessed[0] = true; processSyncBlock(msg.getBlockCapsule()); } - }); - } + } + }); } } From e5f84fc0a3204d2f0446cf883b4a774816e081cc Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 2 Aug 2022 17:46:04 +0800 Subject: [PATCH 0186/1197] tool(db):db path move, print error and exit if path or config error. --- .../main/java/org/tron/plugins/DbMove.java | 79 ++++++++++++++++++- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/plugins/src/main/java/org/tron/plugins/DbMove.java b/plugins/src/main/java/org/tron/plugins/DbMove.java index d9a2a8b4831..77c3dca26f8 100644 --- a/plugins/src/main/java/org/tron/plugins/DbMove.java +++ b/plugins/src/main/java/org/tron/plugins/DbMove.java @@ -1,6 +1,7 @@ package org.tron.plugins; import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; import java.io.File; import java.io.IOException; import java.nio.file.Files; @@ -8,8 +9,10 @@ import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.Set; import java.util.concurrent.Callable; import java.util.stream.Collectors; import me.tongfei.progressbar.ProgressBar; @@ -34,11 +37,12 @@ public class DbMove implements Callable { defaultValue = "output-directory", converter = Db.PathConverter.class, description = "database directory path. Default: ${DEFAULT-VALUE}") - Path database; + static Path database; @CommandLine.Option(names = {"-c", "--config"}, defaultValue = "config.conf", - converter = Db.ConfigConverter.class, + converter = ConfigConverter.class, + order = Integer.MAX_VALUE, description = " config file. Default: ${DEFAULT-VALUE}") Config config; @@ -170,7 +174,78 @@ public Property(String name, Path original, Path destination) throws IOException if (this.original.toFile().isFile()) { throw new IOException(this.original + " is a file!"); } + if (isSymbolicLink(original.toFile())) { + throw new IOException(original + " is symbolicLink!"); + } this.destination = destination.toFile().getCanonicalFile().toPath(); + if (this.destination.toFile().exists()) { + throw new IOException(this.destination + " already exist!"); + } + if (this.destination.equals(this.original)) { + throw new IOException("destination and original can not be same:[" + this.original + "]!"); + } + } + + public boolean isSymbolicLink(File file) throws IOException { + if (file == null) { + throw new NullPointerException("File must not be null"); + } + + File canon; + if (file.getParent() == null) { + canon = file; + } else { + File canonDir = file.getParentFile().getCanonicalFile(); + canon = new File(canonDir, file.getName()); + } + return !canon.getCanonicalFile().equals(canon.getAbsoluteFile()); + } + } + + static class ConfigConverter implements CommandLine.ITypeConverter { + private final Exception notFind = + new IllegalArgumentException("There is no database to be moved,please check."); + + ConfigConverter() { + } + + public Config convert(String value) throws Exception { + File file = Paths.get(value).toFile(); + if (file.exists() && file.isFile()) { + Config config = ConfigFactory.parseFile(Paths.get(value).toFile()); + if (config.hasPath(PROPERTIES_CONFIG_KEY)) { + List dbs = config.getConfigList(PROPERTIES_CONFIG_KEY); + if (dbs.isEmpty()) { + throw notFind; + } + String dbPath = config.hasPath(DB_DIRECTORY_CONFIG_KEY) + ? config.getString(DB_DIRECTORY_CONFIG_KEY) : DEFAULT_DB_DIRECTORY; + + dbs = dbs.stream() + .filter(c -> c.hasPath(NAME_CONFIG_KEY) && c.hasPath(PATH_CONFIG_KEY)) + .collect(Collectors.toList()); + + if (dbs.isEmpty()) { + throw notFind; + } + Set toBeMove = new HashSet<>(); + for (Config c : dbs) { + if (!toBeMove.add(new Property(c.getString(NAME_CONFIG_KEY), + Paths.get(database.toString(), dbPath, c.getString(NAME_CONFIG_KEY)), + Paths.get(c.getString(PATH_CONFIG_KEY), dbPath, + c.getString(NAME_CONFIG_KEY))).name)) { + throw new IllegalArgumentException( + "DB config has duplicate key:[" + c.getString(NAME_CONFIG_KEY) + + "],please check! "); + } + } + } else { + throw notFind; + } + return config; + } else { + throw new IOException("DB config [" + value + "] not exist!"); + } } } } From 2b7db1b714e17ce9d83892256997ebf10e8c6267 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Thu, 14 Jul 2022 18:46:57 +0800 Subject: [PATCH 0187/1197] refactor(tx-cache): use Bloom filters to refactor txCacheDB to reduce memory usage --- .../org/tron/core/db2/common/TxCacheDB.java | 192 +++++++++--------- .../tron/common/prometheus/MetricKeys.java | 1 + .../tron/common/prometheus/MetricsGauge.java | 1 + .../org/tron/core/config/args/Storage.java | 13 ++ .../java/org/tron/core/config/args/Args.java | 3 + .../main/java/org/tron/core/db/Manager.java | 5 +- framework/src/main/resources/config.conf | 9 +- .../java/org/tron/core/db/TxCacheDBTest.java | 74 +++++++ 8 files changed, 203 insertions(+), 95 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/db/TxCacheDBTest.java diff --git a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java index 88adfaab00f..e72a5fc898e 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java @@ -1,25 +1,19 @@ package org.tron.core.db2.common; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Iterators; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; +import com.google.common.hash.BloomFilter; +import com.google.common.hash.Funnels; import com.google.common.primitives.Longs; - import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Collection; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Set; -import java.util.WeakHashMap; - import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; import org.bouncycastle.util.encoders.Hex; import org.iq80.leveldb.WriteOptions; import org.tron.common.parameter.CommonParameter; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.Metrics; import org.tron.common.storage.leveldb.LevelDbDataSourceImpl; import org.tron.common.storage.rocksdb.RocksDbDataSourceImpl; import org.tron.common.utils.ByteArray; @@ -34,44 +28,68 @@ public class TxCacheDB implements DB, Flusher { // > 65_536(= 2^16) blocks, that is the number of the reference block - private final int BLOCK_COUNT = 70_000; - private final long MAX_SIZE = 65536; - private Map db = new WeakHashMap<>(); - private Multimap blockNumMap = ArrayListMultimap.create(); - private String name; - private RecentTransactionStore recentTransactionStore; + private static final long MAX_BLOCK_SIZE = 65536; + // estimated number transactions in one block + private final int TRANSACTION_COUNT; + + // Since the filter cannot query for specific record information, + // FAKE_TRANSACTION represent the record presence. + private final byte[] FAKE_TRANSACTION = ByteArray.fromLong(0); + + // a pair of bloom filters record the recent transactions + private BloomFilter[] bloomFilters = new BloomFilter[2]; + // filterStartBlock record the start block of the active filter + private long filterStartBlock = 0; + // currentFilterIndex records the index of the active filter + private int currentFilterIndex = 0; + + // record the last metric block to avoid duplication + private long lastMetricBlock = 0; + + private final String name; // add a persistent storage, the store name is: trans-cache // when fullnode startup, transactionCache initializes transactions from this store private DB persistentStore; + // replace persistentStore and optimizes startup performance + private RecentTransactionStore recentTransactionStore; + public TxCacheDB(String name, RecentTransactionStore recentTransactionStore) { this.name = name; + this.TRANSACTION_COUNT = + CommonParameter.getInstance().getStorage().getEstimatedBlockTransactions(); this.recentTransactionStore = recentTransactionStore; int dbVersion = CommonParameter.getInstance().getStorage().getDbVersion(); String dbEngine = CommonParameter.getInstance().getStorage().getDbEngine(); if (dbVersion == 2) { if ("LEVELDB".equals(dbEngine.toUpperCase())) { this.persistentStore = new LevelDB( - new LevelDbDataSourceImpl(StorageUtils.getOutputDirectoryByDbName(name), - name, StorageUtils.getOptionsByDbName(name), - new WriteOptions().sync(CommonParameter.getInstance() - .getStorage().isDbSync()))); + new LevelDbDataSourceImpl(StorageUtils.getOutputDirectoryByDbName(name), + name, StorageUtils.getOptionsByDbName(name), + new WriteOptions().sync(CommonParameter.getInstance() + .getStorage().isDbSync()))); } else if ("ROCKSDB".equals(dbEngine.toUpperCase())) { String parentPath = Paths - .get(StorageUtils.getOutputDirectoryByDbName(name), CommonParameter - .getInstance().getStorage().getDbDirectory()).toString(); + .get(StorageUtils.getOutputDirectoryByDbName(name), CommonParameter + .getInstance().getStorage().getDbDirectory()).toString(); this.persistentStore = new RocksDB( - new RocksDbDataSourceImpl(parentPath, - name, CommonParameter.getInstance() - .getRocksDBCustomSettings())); + new RocksDbDataSourceImpl(parentPath, + name, CommonParameter.getInstance() + .getRocksDBCustomSettings())); } else { throw new RuntimeException("db type is not supported."); } } else { throw new RuntimeException("db version is not supported."); } + + this.bloomFilters[0] = BloomFilter.create(Funnels.byteArrayFunnel(), + MAX_BLOCK_SIZE * TRANSACTION_COUNT); + this.bloomFilters[1] = BloomFilter.create(Funnels.byteArrayFunnel(), + MAX_BLOCK_SIZE * TRANSACTION_COUNT); + init(); } @@ -81,57 +99,52 @@ public TxCacheDB(String name, RecentTransactionStore recentTransactionStore) { private void initCache() { long start = System.currentTimeMillis(); DBIterator iterator = (DBIterator) persistentStore.iterator(); + long persistentSize = 0; while (iterator.hasNext()) { Entry entry = iterator.next(); - byte[] key = entry.getKey(); - byte[] value = entry.getValue(); - if (key == null || value == null) { + if (ArrayUtils.isEmpty(entry.getKey()) || ArrayUtils.isEmpty(entry.getValue())) { return; } - Key k = Key.copyOf(key); - Long v = Longs.fromByteArray(value); - blockNumMap.put(v, k); - db.put(k, v); + bloomFilters[1].put(entry.getKey()); + persistentSize++; } - logger.info("Transaction cache init-1 db-size:{}, blockNumMap-size:{}, cost:{}ms", - db.size(), blockNumMap.size(), System.currentTimeMillis() - start); + logger.info("load transaction cache from persistentStore " + + "db-size:{}, filter-size:{}, filter-fpp:{}, cost:{}ms", + persistentSize, + bloomFilters[1].approximateElementCount(), bloomFilters[1].expectedFpp(), + System.currentTimeMillis() - start); } private void init() { long size = recentTransactionStore.size(); - if (size != MAX_SIZE) { + if (size != MAX_BLOCK_SIZE) { + // 0. load from persistentStore initCache(); - return; } + // 1. load from recentTransactionStore long start = System.currentTimeMillis(); - List l1 = new ArrayList<>(); - List l2 = new ArrayList<>(); - Iterator> iterator = recentTransactionStore.iterator(); - while (iterator.hasNext()) { - l1.add(iterator.next().getValue().getData()); - } - - l1.forEach(v -> l2.add(JsonUtil.json2Obj(new String(v), RecentTransactionItem.class))); + for (Entry bytesCapsuleEntry : recentTransactionStore) { + byte[] data = bytesCapsuleEntry.getValue().getData(); + RecentTransactionItem trx = + JsonUtil.json2Obj(new String(data), RecentTransactionItem.class); - l2.forEach(v -> v.getTransactionIds().forEach(tid -> putTransaction(tid, v.getNum()))); - - logger.info("Transaction cache init-2 db-size:{}, blockNumMap-size:{}, cost:{}ms", - db.size(), blockNumMap.size(), System.currentTimeMillis() - start); - } + trx.getTransactionIds().forEach(tid -> bloomFilters[1].put(Hex.decode(tid))); + } - private void putTransaction(String key, long value) { - Key k = Key.copyOf(Hex.decode(key)); - Long v = Longs.fromByteArray(ByteArray.fromLong(value)); - blockNumMap.put(v, k); - db.put(k, v); + logger.info("load transaction cache from recentTransactionStore" + + " filter-size:{}, filter-fpp:{}, cost:{}ms", + bloomFilters[1].approximateElementCount(), bloomFilters[1].expectedFpp(), + System.currentTimeMillis() - start); } - @Override public byte[] get(byte[] key) { - Long v = db.get(Key.of(key)); - return v == null ? null : Longs.toByteArray(v); + if (!bloomFilters[0].mightContain(key) && !bloomFilters[1].mightContain(key)) { + return null; + } + // this means exist + return FAKE_TRANSACTION; } @Override @@ -140,46 +153,46 @@ public void put(byte[] key, byte[] value) { return; } - Key k = Key.copyOf(key); - Long v = Longs.fromByteArray(value); - blockNumMap.put(v, k); - db.put(k, v); - // put the data into persistent storage - persistentStore.put(key, value); - removeEldest(); - } - - private void removeEldest() { - Set keys = blockNumMap.keySet(); - if (keys.size() > BLOCK_COUNT) { - keys.stream() - .min(Long::compareTo) - .ifPresent(k -> { - Collection trxHashs = blockNumMap.get(k); - // remove transaction from persistentStore, - // if foreach is inefficient, change remove-foreach to remove-batch - trxHashs.forEach(key -> persistentStore.remove(key.getBytes())); - blockNumMap.removeAll(k); - logger.debug("******removeEldest block number:{}, block count:{}", k, keys.size()); - }); + long blockNum = Longs.fromByteArray(value); + if (filterStartBlock == 0) { + // init active filter start block + filterStartBlock = blockNum; + currentFilterIndex = 0; + } else if (blockNum - filterStartBlock > MAX_BLOCK_SIZE) { + // active filter is full + logger.info("active bloomFilters is full (size={} fpp={}), create a new one", + bloomFilters[currentFilterIndex].approximateElementCount(), + bloomFilters[currentFilterIndex].expectedFpp()); + currentFilterIndex ^= 1; + filterStartBlock = blockNum; + bloomFilters[currentFilterIndex] = + BloomFilter.create(Funnels.byteArrayFunnel(), + MAX_BLOCK_SIZE * TRANSACTION_COUNT); + } + bloomFilters[currentFilterIndex].put(key); + + if (lastMetricBlock != blockNum) { + lastMetricBlock = blockNum; + Metrics.gaugeSet(MetricKeys.Gauge.TX_CACHE, + bloomFilters[currentFilterIndex].approximateElementCount(), "count"); + Metrics.gaugeSet(MetricKeys.Gauge.TX_CACHE, + bloomFilters[currentFilterIndex].expectedFpp(), "fpp"); } } @Override public long size() { - return db.size(); + throw new UnsupportedOperationException("TxCacheDB size"); } @Override public boolean isEmpty() { - return db.isEmpty(); + throw new UnsupportedOperationException("TxCacheDB isEmpty"); } @Override public void remove(byte[] key) { - if (key != null) { - db.remove(Key.of(key)); - } + throw new UnsupportedOperationException("TxCacheDB remove"); } @Override @@ -189,8 +202,7 @@ public String getDbName() { @Override public Iterator> iterator() { - return Iterators.transform(db.entrySet().iterator(), - e -> Maps.immutableEntry(e.getKey().getBytes(), Longs.toByteArray(e.getValue()))); + throw new UnsupportedOperationException("TxCacheDB iterator"); } @Override @@ -201,15 +213,13 @@ public void flush(Map batch) { @Override public void close() { reset(); - db = null; - blockNumMap = null; + bloomFilters[0] = null; + bloomFilters[1] = null; persistentStore.close(); } @Override public void reset() { - db.clear(); - blockNumMap.clear(); } @Override diff --git a/common/src/main/java/org/tron/common/prometheus/MetricKeys.java b/common/src/main/java/org/tron/common/prometheus/MetricKeys.java index 8172eaffd8b..a68f379f394 100644 --- a/common/src/main/java/org/tron/common/prometheus/MetricKeys.java +++ b/common/src/main/java/org/tron/common/prometheus/MetricKeys.java @@ -32,6 +32,7 @@ public static class Gauge { public static final String DB_SIZE_BYTES = "tron:db_size_bytes"; public static final String DB_SST_LEVEL = "tron:db_sst_level"; public static final String MANAGER_QUEUE = "tron:manager_queue_size"; + public static final String TX_CACHE = "tron:tx_cache"; private Gauge() { throw new IllegalStateException("Gauge"); diff --git a/common/src/main/java/org/tron/common/prometheus/MetricsGauge.java b/common/src/main/java/org/tron/common/prometheus/MetricsGauge.java index 57461375b75..dc1e5447540 100644 --- a/common/src/main/java/org/tron/common/prometheus/MetricsGauge.java +++ b/common/src/main/java/org/tron/common/prometheus/MetricsGauge.java @@ -18,6 +18,7 @@ class MetricsGauge { init(MetricKeys.Gauge.PEERS, "tron peers.size .", "type"); init(MetricKeys.Gauge.DB_SIZE_BYTES, "tron db size .", "type", "db", "level"); init(MetricKeys.Gauge.DB_SST_LEVEL, "tron db files .", "type", "db", "level"); + init(MetricKeys.Gauge.TX_CACHE, "tron tx cache info.", "type"); } private MetricsGauge() { diff --git a/common/src/main/java/org/tron/core/config/args/Storage.java b/common/src/main/java/org/tron/core/config/args/Storage.java index 021accb808a..75f8d9b0ddb 100644 --- a/common/src/main/java/org/tron/core/config/args/Storage.java +++ b/common/src/main/java/org/tron/core/config/args/Storage.java @@ -48,6 +48,8 @@ public class Storage { private static final String INDEX_DIRECTORY_CONFIG_KEY = "storage.index.directory"; private static final String INDEX_SWITCH_CONFIG_KEY = "storage.index.switch"; private static final String TRANSACTIONHISTORY_SWITCH_CONFIG_KEY = "storage.transHistory.switch"; + private static final String ESTIMATED_TRANSACTIONS_CONFIG_KEY = + "storage.txCache.estimatedTransactions"; private static final String PROPERTIES_CONFIG_KEY = "storage.properties"; private static final String PROPERTIES_CONFIG_DB_KEY = "storage"; private static final String PROPERTIES_CONFIG_DEFAULT_KEY = "default"; @@ -77,6 +79,7 @@ public class Storage { private static final String DEFAULT_DB_DIRECTORY = "database"; private static final String DEFAULT_INDEX_DIRECTORY = "index"; private static final String DEFAULT_INDEX_SWITCH = "on"; + private static final int DEFAULT_ESTIMATED_TRANSACTIONS = 500; private Config storage; /** @@ -119,6 +122,10 @@ public class Storage { private Options defaultDbOptions; + @Getter + @Setter + private int estimatedBlockTransactions; + /** * Key: dbName, Value: Property object of that database */ @@ -168,6 +175,12 @@ public static String getTransactionHistorySwitchFromConfig(final Config config) : DEFAULT_TRANSACTIONHISTORY_SWITCH; } + public static int getEstimatedTransactionsFromConfig(final Config config) { + return config.hasPath(ESTIMATED_TRANSACTIONS_CONFIG_KEY) + ? config.getInt(ESTIMATED_TRANSACTIONS_CONFIG_KEY) + : DEFAULT_ESTIMATED_TRANSACTIONS; + } + private Property createProperty(final ConfigObject conf) { Property property = new Property(); diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 0e2482e7f37..a66f56e6067 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -406,6 +406,9 @@ public static void setParam(final String[] args, final String confFileName) { .filter(StringUtils::isNotEmpty) .orElse(Storage.getTransactionHistorySwitchFromConfig(config))); + PARAMETER.storage.setEstimatedBlockTransactions( + Storage.getEstimatedTransactionsFromConfig(config)); + PARAMETER.storage.setDefaultDbOptions(config); PARAMETER.storage.setPropertyMapFromConfig(config); diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index da8b7491248..06fe9c62d4e 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -740,8 +740,9 @@ private boolean containsTransaction(TransactionCapsule transactionCapsule) { private boolean containsTransaction(byte[] transactionId) { - if (transactionCache != null) { - return transactionCache.has(transactionId); + if (transactionCache != null && !transactionCache.has(transactionId)) { + // using the bloom filter only determines non-existent transaction + return false; } return chainBaseManager.getTransactionStore() diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 74f148e1405..c12a2740b76 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -89,6 +89,11 @@ storage { } balance.history.lookup = false + + # the estimated number of block transactions (default 500). + # so the total number of cached transactions is 65536 * txCache.estimatedTransactions + # txCache.estimatedTransactions = 500 + } node.discovery = { @@ -124,12 +129,12 @@ crypto { engine = "eckey" } # prometheus metrics start -#node.metrics = { +# node.metrics = { # prometheus{ # enable=true # port="9527" # } -#} +# } # prometheus metrics end diff --git a/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java b/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java new file mode 100644 index 00000000000..6f627ab535e --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java @@ -0,0 +1,74 @@ +package org.tron.core.db; + +import java.io.File; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.tron.common.application.Application; +import org.tron.common.application.ApplicationFactory; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.core.Constant; +import org.tron.core.capsule.BytesCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.keystore.Wallet; + +public class TxCacheDBTest { + private static final String dbPath = "output_TransactionCache_test"; + + private static TronApplicationContext context; + private static Manager dbManager; + + /** + * Init data. + */ + @BeforeClass + public static void init() { + String dbDirectory = "db_TransactionCache_test"; + String indexDirectory = "index_TransactionCache_test"; + Args.setParam(new String[]{"--output-directory", dbPath, "--storage-db-directory", + dbDirectory, "--storage-index-directory", indexDirectory, "-w"}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + Application appT = ApplicationFactory.create(context); + dbManager = context.getBean(Manager.class); + } + + /** + * release resources. + */ + @AfterClass + public static void destroy() { + Args.clearParam(); + context.destroy(); + FileUtil.deleteDir(new File(dbPath)); + } + + @Test + public void putTransactionTest() { + TransactionCache db = dbManager.getTransactionCache(); + byte[][] hash = new byte[140000][64]; + for (int i = 1; i < 140000; i++) { + hash[i] = Wallet.generateRandomBytes(64); + db.put(hash[i], new BytesCapsule(ByteArray.fromLong(i))); + } + // [1,63357] are expired + for (int i = 1; i < 65538; i++) { + try { + Assert.assertFalse("index = " + i, db.has(hash[i])); + } catch (Exception e) { + Assert.fail("transaction should be expired index = " + i); + } + } + // [63358,140000] are in cache + for (int i = 65538; i < 140000; i++) { + try { + Assert.assertTrue("index = " + i, db.has(hash[i])); + } catch (Exception e) { + Assert.fail("transaction should not be expired index = " + i); + } + } + } +} \ No newline at end of file From 8f3410da114c8be89a1efc7e35edc379f6d642ec Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Thu, 21 Jul 2022 14:08:57 +0800 Subject: [PATCH 0188/1197] refactor(tx-cache): add log information and modify default parameters --- .../java/org/tron/core/db2/common/TxCacheDB.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java index e72a5fc898e..fb38208d2ac 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java @@ -32,6 +32,8 @@ public class TxCacheDB implements DB, Flusher { // estimated number transactions in one block private final int TRANSACTION_COUNT; + private static final long INVALID_BLOCK = -1; + // Since the filter cannot query for specific record information, // FAKE_TRANSACTION represent the record presence. private final byte[] FAKE_TRANSACTION = ByteArray.fromLong(0); @@ -39,7 +41,7 @@ public class TxCacheDB implements DB, Flusher { // a pair of bloom filters record the recent transactions private BloomFilter[] bloomFilters = new BloomFilter[2]; // filterStartBlock record the start block of the active filter - private long filterStartBlock = 0; + private long filterStartBlock = INVALID_BLOCK; // currentFilterIndex records the index of the active filter private int currentFilterIndex = 0; @@ -154,15 +156,17 @@ public void put(byte[] key, byte[] value) { } long blockNum = Longs.fromByteArray(value); - if (filterStartBlock == 0) { + if (filterStartBlock == INVALID_BLOCK) { // init active filter start block filterStartBlock = blockNum; currentFilterIndex = 0; + logger.info("init tx cache bloomFilters at {}",blockNum); } else if (blockNum - filterStartBlock > MAX_BLOCK_SIZE) { // active filter is full - logger.info("active bloomFilters is full (size={} fpp={}), create a new one", + logger.info("active bloomFilters is full (size={} fpp={}), create a new one (start={})", bloomFilters[currentFilterIndex].approximateElementCount(), - bloomFilters[currentFilterIndex].expectedFpp()); + bloomFilters[currentFilterIndex].expectedFpp(), + blockNum); currentFilterIndex ^= 1; filterStartBlock = blockNum; bloomFilters[currentFilterIndex] = @@ -228,8 +232,6 @@ public TxCacheDB newInstance() { } @Override - public void stat() { - this.persistentStore.stat(); - } + public void stat() {} } From e0be5999c7c6f387b7f4860e47c3046aa1704dd1 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Thu, 21 Jul 2022 17:44:31 +0800 Subject: [PATCH 0189/1197] refactor(tx-cache): recover partial transaction db for light nodes --- .../org/tron/core/db/TransactionStore.java | 3 ++ .../main/java/org/tron/core/db/Manager.java | 40 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionStore.java b/chainbase/src/main/java/org/tron/core/db/TransactionStore.java index 342550ecb4a..c0067b77934 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionStore.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionStore.java @@ -52,6 +52,9 @@ private TransactionCapsule getTransactionFromBlockStore(byte[] key, long blockNu private TransactionCapsule getTransactionFromKhaosDatabase(byte[] key, long high) { List khaosBlocks = khaosDatabase.getMiniStore().getBlockByNum(high); + if (khaosBlocks == null) { + return null; + } for (KhaosBlock bl : khaosBlocks) { for (TransactionCapsule e : bl.getBlk().getTransactions()) { if (e.getTransactionId().equals(Sha256Hash.wrap(key))) { diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 06fe9c62d4e..57adaa14df2 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -19,6 +19,7 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -501,6 +502,9 @@ public void init() { //for test only chainBaseManager.getDynamicPropertiesStore().updateDynamicStoreByConfig(); + // init liteFullNode + initLiteNode(); + long headNum = chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber(); logger.info("current headNum is: {}", headNum); int nodeType = chainBaseManager.getCommonStore().getNodeType(); @@ -2272,6 +2276,42 @@ public long getPendingSize() { return value; } + private void initLiteNode() { + // When using bloom filter for transaction de-duplication, + // it is possible to use trans for secondary confirmation. + // Init trans db for liteNode, + long headNum = chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber(); + long recentBlockCount = chainBaseManager.getRecentBlockStore().size(); + long recentBlockStart = headNum - recentBlockCount + 1; + try { + chainBaseManager.getBlockByNum(recentBlockStart); + } catch (ItemNotFoundException | BadItemException e) { + // copy transaction from recent-transaction to trans + logger.info("load trans for lite node. from={},to={}", recentBlockStart, headNum); + + TransactionCapsule item = new TransactionCapsule(Transaction.newBuilder().build()); + // add a fake number, tx Cache check if transaction exist + item.setBlockNum(0); + + long transactionCount = 0; + for (Map.Entry entry : + chainBaseManager.getRecentTransactionStore()) { + byte[] data = entry.getValue().getData(); + RecentTransactionItem trx = + JsonUtil.json2Obj(new String(data), RecentTransactionItem.class); + if (trx == null) { + continue; + } + transactionCount += trx.getTransactionIds().size(); + + trx.getTransactionIds().forEach( + tid -> chainBaseManager.getTransactionStore().put(Hex.decode(tid), item)); + } + logger.info("load trans complete, trans:{}.", transactionCount); + } + } + + public void setBlockWaitLock(boolean waitFlag) { if (waitFlag) { blockWaitLock.incrementAndGet(); From 8198fb9434d288e6424ce9a78f81c6b54ef69caa Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Mon, 1 Aug 2022 18:00:21 +0800 Subject: [PATCH 0190/1197] refactor(tx-cache): add volatile to increase multi-threaded safety --- .../org/tron/core/db2/common/TxCacheDB.java | 18 ++++++++++++------ .../java/org/tron/core/db/TxCacheDBTest.java | 4 ++-- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java index fb38208d2ac..02f8f06fd2e 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java @@ -41,9 +41,9 @@ public class TxCacheDB implements DB, Flusher { // a pair of bloom filters record the recent transactions private BloomFilter[] bloomFilters = new BloomFilter[2]; // filterStartBlock record the start block of the active filter - private long filterStartBlock = INVALID_BLOCK; + private volatile long filterStartBlock = INVALID_BLOCK; // currentFilterIndex records the index of the active filter - private int currentFilterIndex = 0; + private volatile int currentFilterIndex = 0; // record the last metric block to avoid duplication private long lastMetricBlock = 0; @@ -86,7 +86,6 @@ public TxCacheDB(String name, RecentTransactionStore recentTransactionStore) { } else { throw new RuntimeException("db version is not supported."); } - this.bloomFilters[0] = BloomFilter.create(Funnels.byteArrayFunnel(), MAX_BLOCK_SIZE * TRANSACTION_COUNT); this.bloomFilters[1] = BloomFilter.create(Funnels.byteArrayFunnel(), @@ -160,14 +159,20 @@ public void put(byte[] key, byte[] value) { // init active filter start block filterStartBlock = blockNum; currentFilterIndex = 0; - logger.info("init tx cache bloomFilters at {}",blockNum); + logger.info("init tx cache bloomFilters at {}", blockNum); } else if (blockNum - filterStartBlock > MAX_BLOCK_SIZE) { // active filter is full logger.info("active bloomFilters is full (size={} fpp={}), create a new one (start={})", bloomFilters[currentFilterIndex].approximateElementCount(), bloomFilters[currentFilterIndex].expectedFpp(), blockNum); - currentFilterIndex ^= 1; + + if (currentFilterIndex == 0) { + currentFilterIndex = 1; + } else { + currentFilterIndex = 0; + } + filterStartBlock = blockNum; bloomFilters[currentFilterIndex] = BloomFilter.create(Funnels.byteArrayFunnel(), @@ -232,6 +237,7 @@ public TxCacheDB newInstance() { } @Override - public void stat() {} + public void stat() { + } } diff --git a/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java b/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java index 6f627ab535e..7d9bbcd5ad2 100644 --- a/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java +++ b/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java @@ -54,7 +54,7 @@ public void putTransactionTest() { hash[i] = Wallet.generateRandomBytes(64); db.put(hash[i], new BytesCapsule(ByteArray.fromLong(i))); } - // [1,63357] are expired + // [1,65537] are expired for (int i = 1; i < 65538; i++) { try { Assert.assertFalse("index = " + i, db.has(hash[i])); @@ -62,7 +62,7 @@ public void putTransactionTest() { Assert.fail("transaction should be expired index = " + i); } } - // [63358,140000] are in cache + // [65538,140000] are in cache for (int i = 65538; i < 140000; i++) { try { Assert.assertTrue("index = " + i, db.has(hash[i])); From 7d17172761fb1507dbf86151a36f4b407926c863 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Tue, 2 Aug 2022 19:30:21 +0800 Subject: [PATCH 0191/1197] refactor(tx-cache): limit param estimatedBlockTransactions --- .../java/org/tron/core/config/args/Storage.java | 13 ++++++++++--- .../src/main/java/org/tron/core/db/Manager.java | 14 +++++++++----- framework/src/main/resources/config.conf | 2 +- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/common/src/main/java/org/tron/core/config/args/Storage.java b/common/src/main/java/org/tron/core/config/args/Storage.java index 75f8d9b0ddb..60e3cd9ba6d 100644 --- a/common/src/main/java/org/tron/core/config/args/Storage.java +++ b/common/src/main/java/org/tron/core/config/args/Storage.java @@ -176,9 +176,16 @@ public static String getTransactionHistorySwitchFromConfig(final Config config) } public static int getEstimatedTransactionsFromConfig(final Config config) { - return config.hasPath(ESTIMATED_TRANSACTIONS_CONFIG_KEY) - ? config.getInt(ESTIMATED_TRANSACTIONS_CONFIG_KEY) - : DEFAULT_ESTIMATED_TRANSACTIONS; + if (!config.hasPath(ESTIMATED_TRANSACTIONS_CONFIG_KEY)) { + return DEFAULT_ESTIMATED_TRANSACTIONS; + } + int estimatedTransactions = config.getInt(ESTIMATED_TRANSACTIONS_CONFIG_KEY); + if (estimatedTransactions > 10000) { + estimatedTransactions = 10000; + } else if (estimatedTransactions < 100) { + estimatedTransactions = 100; + } + return estimatedTransactions; } private Property createProperty(final ConfigObject conf) { diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 57adaa14df2..0d25dadf48e 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -2287,13 +2287,13 @@ private void initLiteNode() { chainBaseManager.getBlockByNum(recentBlockStart); } catch (ItemNotFoundException | BadItemException e) { // copy transaction from recent-transaction to trans - logger.info("load trans for lite node. from={},to={}", recentBlockStart, headNum); + logger.info("load trans for lite node."); TransactionCapsule item = new TransactionCapsule(Transaction.newBuilder().build()); - // add a fake number, tx Cache check if transaction exist - item.setBlockNum(0); long transactionCount = 0; + long minBlock = Long.MAX_VALUE; + long maxBlock = Long.MIN_VALUE; for (Map.Entry entry : chainBaseManager.getRecentTransactionStore()) { byte[] data = entry.getValue().getData(); @@ -2303,11 +2303,15 @@ private void initLiteNode() { continue; } transactionCount += trx.getTransactionIds().size(); - + long blockNum = trx.getNum(); + maxBlock = Math.max(maxBlock, blockNum); + minBlock = Math.min(minBlock, blockNum); + item.setBlockNum(blockNum); trx.getTransactionIds().forEach( tid -> chainBaseManager.getTransactionStore().put(Hex.decode(tid), item)); } - logger.info("load trans complete, trans:{}.", transactionCount); + logger.info("load trans complete, trans:{},from={},to={}", + transactionCount, minBlock, maxBlock); } } diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index c12a2740b76..93259dfffa6 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -90,7 +90,7 @@ storage { balance.history.lookup = false - # the estimated number of block transactions (default 500). + # the estimated number of block transactions (default 500, min 100, max 10000). # so the total number of cached transactions is 65536 * txCache.estimatedTransactions # txCache.estimatedTransactions = 500 From 299d68573d0a3d4fc3433b79795bdbb0dd07166f Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 3 Aug 2022 11:00:57 +0800 Subject: [PATCH 0192/1197] perf(net): compatible network configuration --- .../src/main/java/org/tron/core/Constant.java | 7 ++- .../java/org/tron/core/config/args/Args.java | 45 ++++++++++++++----- framework/src/main/resources/config.conf | 2 +- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 1eb10792600..883e4cd3f6a 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -87,7 +87,12 @@ public class Constant { public static final String NODE_MIN_CONNECTIONS = "node.minConnections"; public static final String NODE_MIN_ACTIVE_CONNECTIONS = "node.minActiveConnections"; - public static final String NODE_MAX_ACTIVE_NODES_WITH_SAMEIP = "node.maxConnectionsWithSameIp"; + public static final String NODE_MAX_ACTIVE_NODES = "node.maxActiveNodes"; + public static final String NODE_MAX_ACTIVE_NODES_WITH_SAME_IP = "node.maxActiveNodesWithSameIp"; + public static final String NODE_CONNECT_FACTOR = "node.connectFactor"; + public static final String NODE_ACTIVE_CONNECT_FACTOR = "node.activeConnectFactor"; + + public static final String NODE_MAX_CONNECTIONS_WITH_SAME_IP = "node.maxConnectionsWithSameIp"; public static final String NODE_MIN_PARTICIPATION_RATE = "node.minParticipationRate"; public static final String NODE_LISTEN_PORT = "node.listen.port"; public static final String NODE_DISCOVERY_PUBLIC_HOME_NODE = "node.discovery.public.home.node"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 0e2482e7f37..dd53ac7e220 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -463,21 +463,42 @@ public static void setParam(final String[] args, final String confFileName) { ? config.getInt(Constant.NODE_CHANNEL_READ_TIMEOUT) : 0; - PARAMETER.maxConnections = - config.hasPath(Constant.NODE_MAX_CONNECTIONS) - ? config.getInt(Constant.NODE_MAX_CONNECTIONS) : 30; + if (config.hasPath(Constant.NODE_MAX_ACTIVE_NODES)) { + PARAMETER.maxConnections = config.getInt(Constant.NODE_MAX_ACTIVE_NODES); + } else { + PARAMETER.maxConnections = + config.hasPath(Constant.NODE_MAX_CONNECTIONS) + ? config.getInt(Constant.NODE_MAX_CONNECTIONS) : 30; + } - PARAMETER.minConnections = - config.hasPath(Constant.NODE_MIN_CONNECTIONS) - ? config.getInt(Constant.NODE_MIN_CONNECTIONS) : 8; + if (config.hasPath(Constant.NODE_MAX_ACTIVE_NODES) + && config.hasPath(Constant.NODE_CONNECT_FACTOR)) { + PARAMETER.minConnections = (int) (PARAMETER.maxConnections + * config.getDouble(Constant.NODE_CONNECT_FACTOR)); + } else { + PARAMETER.minConnections = + config.hasPath(Constant.NODE_MIN_CONNECTIONS) + ? config.getInt(Constant.NODE_MIN_CONNECTIONS) : 8; + } - PARAMETER.minActiveConnections = - config.hasPath(Constant.NODE_MIN_ACTIVE_CONNECTIONS) - ? config.getInt(Constant.NODE_MIN_ACTIVE_CONNECTIONS) : 3; + if (config.hasPath(Constant.NODE_MAX_ACTIVE_NODES) + && config.hasPath(Constant.NODE_ACTIVE_CONNECT_FACTOR)) { + PARAMETER.minActiveConnections = (int) (PARAMETER.maxConnections + * config.getDouble(Constant.NODE_ACTIVE_CONNECT_FACTOR)); + } else { + PARAMETER.minActiveConnections = + config.hasPath(Constant.NODE_MIN_ACTIVE_CONNECTIONS) + ? config.getInt(Constant.NODE_MIN_ACTIVE_CONNECTIONS) : 3; + } - PARAMETER.maxConnectionsWithSameIp = - config.hasPath(Constant.NODE_MAX_ACTIVE_NODES_WITH_SAMEIP) ? config - .getInt(Constant.NODE_MAX_ACTIVE_NODES_WITH_SAMEIP) : 2; + if (config.hasPath(Constant.NODE_MAX_ACTIVE_NODES_WITH_SAME_IP)) { + PARAMETER.maxConnectionsWithSameIp = + config.getInt(Constant.NODE_MAX_ACTIVE_NODES_WITH_SAME_IP); + } else { + PARAMETER.maxConnectionsWithSameIp = + config.hasPath(Constant.NODE_MAX_CONNECTIONS_WITH_SAME_IP) ? config + .getInt(Constant.NODE_MAX_CONNECTIONS_WITH_SAME_IP) : 2; + } PARAMETER.minParticipationRate = config.hasPath(Constant.NODE_MIN_PARTICIPATION_RATE) diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 74f148e1405..e5534594a2b 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -164,7 +164,7 @@ node { minParticipationRate = 15 - isOpenFullTcpDisconnect = true + isOpenFullTcpDisconnect = false p2p { version = 11111 # 11111: mainnet; 20180622: testnet From 45f01193197906241bf23c16e00297767e6765ac Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 4 Aug 2022 14:45:27 +0800 Subject: [PATCH 0193/1197] feat(log): modify log output level 1. modify unnecessary error log output --- .../java/org/tron/common/overlay/server/MessageQueue.java | 2 +- framework/src/main/java/org/tron/core/Wallet.java | 8 ++++---- .../src/main/java/org/tron/core/net/TronNetService.java | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java index a8db0225be4..9b702dac915 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java +++ b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java @@ -106,7 +106,7 @@ public void fastSend(Message msg) { logger.info("Fast send to {}, {} ", ctx.channel().remoteAddress(), msg); ctx.writeAndFlush(msg.getSendData()).addListener((ChannelFutureListener) future -> { if (!future.isSuccess() && !channel.isDisconnect()) { - logger.error("Fast send to {} failed, {}", ctx.channel().remoteAddress(), msg); + logger.warn("Fast send to {} failed, {}", ctx.channel().remoteAddress(), msg); } }); } diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 4f473f79d24..ac88a898ed9 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -536,17 +536,17 @@ public GrpcAPI.Return broadcastTransaction(Transaction signedTransaction) { return builder.setResult(true).setCode(response_code.SUCCESS).build(); } } catch (ValidateSignatureException e) { - logger.error(BROADCAST_TRANS_FAILED, txID, e.getMessage()); + logger.warn(BROADCAST_TRANS_FAILED, txID, e.getMessage()); return builder.setResult(false).setCode(response_code.SIGERROR) .setMessage(ByteString.copyFromUtf8("Validate signature error: " + e.getMessage())) .build(); } catch (ContractValidateException e) { - logger.error(BROADCAST_TRANS_FAILED, txID, e.getMessage()); + logger.warn(BROADCAST_TRANS_FAILED, txID, e.getMessage()); return builder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) .setMessage(ByteString.copyFromUtf8(CONTRACT_VALIDATE_ERROR + e.getMessage())) .build(); } catch (ContractExeException e) { - logger.error(BROADCAST_TRANS_FAILED, txID, e.getMessage()); + logger.warn(BROADCAST_TRANS_FAILED, txID, e.getMessage()); return builder.setResult(false).setCode(response_code.CONTRACT_EXE_ERROR) .setMessage(ByteString.copyFromUtf8("Contract execute error : " + e.getMessage())) .build(); @@ -556,7 +556,7 @@ public GrpcAPI.Return broadcastTransaction(Transaction signedTransaction) { .setMessage(ByteString.copyFromUtf8("Account resource insufficient error.")) .build(); } catch (DupTransactionException e) { - logger.error(BROADCAST_TRANS_FAILED, txID, e.getMessage()); + logger.warn(BROADCAST_TRANS_FAILED, txID, e.getMessage()); return builder.setResult(false).setCode(response_code.DUP_TRANSACTION_ERROR) .setMessage(ByteString.copyFromUtf8("Dup transaction.")) .build(); diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 250a9a444b0..69d1bc0cebe 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -153,11 +153,11 @@ private void processException(PeerConnection peer, TronMessage msg, Exception ex code = ReasonCode.UNKNOWN; break; } - logger.error("Message from {} process failed, {} \n type: {}, detail: {}.", + logger.warn("Message from {} process failed, {} \n type: {}, detail: {}.", peer.getInetAddress(), msg, type, ex.getMessage()); } else { code = ReasonCode.UNKNOWN; - logger.error("Message from {} process failed, {}", + logger.warn("Message from {} process failed, {}", peer.getInetAddress(), msg, ex); } From a077c5daa43dbba162ea290f3d4f5c7b176be10d Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 4 Aug 2022 16:03:13 +0800 Subject: [PATCH 0194/1197] perf(net): optimize disconnect logic --- .../common/overlay/server/PeerConnectionCheckService.java | 6 +----- framework/src/main/java/org/tron/core/config/args/Args.java | 2 ++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java b/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java index edd18bd9ed0..3aafa4a8e95 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java +++ b/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java @@ -18,9 +18,7 @@ @Slf4j(topic = "net") @Service public class PeerConnectionCheckService { - private int p2pVersion = Args.getInstance().getNodeP2pVersion(); private int maxConnections = Args.getInstance().getMaxConnections(); - private int minActiveConnections = Args.getInstance().getMinActiveConnections(); private boolean isFastForward = Args.getInstance().isFastForward(); private boolean isOpenFullTcpDisconnect = Args.getInstance().isOpenFullTcpDisconnect(); private ScheduledExecutorService poolLoopExecutor = Executors.newSingleThreadScheduledExecutor(); @@ -51,12 +49,10 @@ public void check() { if (syncPool.getActivePeers().size() < maxConnections) { return; } - boolean flag = syncPool.getActivePeersCount().get() > minActiveConnections * 2; Collection peers = syncPool.getActivePeers().stream() .filter(peer -> peer.isIdle()) .filter(peer -> !peer.isTrustPeer()) - .filter(peer -> !peer.getNode().isConnectible(p2pVersion)) - .filter(peer -> peer.isActive() == flag) + .filter(peer -> !peer.isActive()) .collect(Collectors.toList()); if (peers.size() == 0) { return; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index fa00f42fc32..38ae934877e 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1256,6 +1256,8 @@ public static void logConfig() { logger.info("FastForward node number: {}", parameter.getMaxFastForwardNum()); logger.info("Seed node size: {}", parameter.getSeedNode().getIpList().size()); logger.info("Max connection: {}", parameter.getMaxConnections()); + logger.info("Min connection: {}", parameter.getMinConnections()); + logger.info("Min active connection: {}", parameter.getMinActiveConnections()); logger.info("Max connection with same IP: {}", parameter.getMaxConnectionsWithSameIp()); logger.info("Solidity threads: {}", parameter.getSolidityThreads()); logger.info("Trx reference block: {}", parameter.getTrxReferenceBlock()); From 078943e6c544c5256016a33ead0e0a0b21ffe619 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Fri, 5 Aug 2022 17:07:01 +0800 Subject: [PATCH 0195/1197] feat(jsonrpc): if revert happens when executing contract in eth_estimateGas and eth_call, return err msg --- .../logsfilter/ContractEventParser.java | 2 +- .../core/services/jsonrpc/TronJsonRpc.java | 4 +- .../services/jsonrpc/TronJsonRpcImpl.java | 40 ++++++++++++++++--- .../common/logsfilter/EventParserTest.java | 15 +++++++ 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/framework/src/main/java/org/tron/common/logsfilter/ContractEventParser.java b/framework/src/main/java/org/tron/common/logsfilter/ContractEventParser.java index e0e7961ebf0..b2d8a0d8d3a 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/ContractEventParser.java +++ b/framework/src/main/java/org/tron/common/logsfilter/ContractEventParser.java @@ -17,7 +17,7 @@ public class ContractEventParser { private static final int DATAWORD_UNIT_SIZE = 32; - protected static String parseDataBytes(byte[] data, String typeStr, int index) { + public static String parseDataBytes(byte[] data, String typeStr, int index) { try { byte[] startBytes = subBytes(data, index * DATAWORD_UNIT_SIZE, DATAWORD_UNIT_SIZE); Type type = basicType(typeStr); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpc.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpc.java index d082c7152ea..edbb9377988 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpc.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpc.java @@ -13,7 +13,6 @@ import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; -import lombok.Value; import org.springframework.stereotype.Component; import org.tron.common.runtime.vm.DataWord; import org.tron.common.utils.ByteArray; @@ -150,9 +149,10 @@ TransactionResult getTransactionByBlockNumberAndIndex(String blockNumOrTag, Stri @JsonRpcMethod("eth_call") @JsonRpcErrors({ @JsonRpcError(exception = JsonRpcInvalidParamsException.class, code = -32602, data = "{}"), + @JsonRpcError(exception = JsonRpcInternalException.class, code = -32000, data = "{}"), }) String getCall(CallArguments transactionCall, String blockNumOrTag) - throws JsonRpcInvalidParamsException; + throws JsonRpcInvalidParamsException, JsonRpcInternalException; @JsonRpcMethod("net_peerCount") String getPeerCount(); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 1c6debb31b7..503d42b295d 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -29,11 +29,13 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.tron.api.GrpcAPI.BytesMessage; import org.tron.api.GrpcAPI.Return; import org.tron.api.GrpcAPI.Return.response_code; import org.tron.api.GrpcAPI.TransactionExtention; import org.tron.common.crypto.Hash; +import org.tron.common.logsfilter.ContractEventParser; import org.tron.common.logsfilter.capsule.BlockFilterCapsule; import org.tron.common.logsfilter.capsule.LogsFilterCapsule; import org.tron.common.runtime.vm.DataWord; @@ -76,6 +78,7 @@ import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.Protocol.TransactionInfo; import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; import org.tron.protos.contract.BalanceContract.TransferContract; @@ -389,7 +392,7 @@ private void callTriggerConstantContract(byte[] ownerAddressByte, byte[] contrac * getMethodSign(methodName(uint256,uint256)) || data1 || data2 */ private String call(byte[] ownerAddressByte, byte[] contractAddressByte, long value, - byte[] data) { + byte[] data) throws JsonRpcInternalException { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); @@ -418,9 +421,8 @@ private String call(byte[] ownerAddressByte, byte[] contractAddressByte, long va trxExt = trxExtBuilder.build(); } - String result = "0x"; - String code = trxExt.getResult().getCode().toString(); - if ("SUCCESS".equals(code)) { + String result; + if (trxExtBuilder.getTransaction().getRet(0).getRet().equals(code.SUCESS)) { List list = trxExt.getConstantResultList(); byte[] listBytes = new byte[0]; for (ByteString bs : list) { @@ -429,6 +431,16 @@ private String call(byte[] ownerAddressByte, byte[] contractAddressByte, long va result = ByteArray.toJsonHex(listBytes); } else { logger.error("trigger contract failed."); + String errMsg = retBuilder.getMessage().toStringUtf8(); + byte[] resData = trxExtBuilder.getConstantResult(0).toByteArray(); + if (resData.length > 4 && Hex.toHexString(resData).startsWith("08c379a0")) { // Error(string) + String msg = ContractEventParser + .parseDataBytes(org.bouncycastle.util.Arrays.copyOfRange(resData, 4, resData.length), + "string", 0); + errMsg += ": " + msg; + } + + throw new JsonRpcInternalException(errMsg); } return result; @@ -545,7 +557,7 @@ public String estimateGas(CallArguments args) throws JsonRpcInvalidRequestExcept trxExtBuilder, retBuilder); - return ByteArray.toJsonHex(trxExtBuilder.getEnergyUsed()); + } catch (ContractValidateException e) { String errString = "invalid contract"; if (e.getMessage() != null) { @@ -561,6 +573,22 @@ public String estimateGas(CallArguments args) throws JsonRpcInvalidRequestExcept throw new JsonRpcInternalException(errString); } + + if (trxExtBuilder.getTransaction().getRet(0).getRet().equals(code.FAILED)) { + String errMsg = retBuilder.getMessage().toStringUtf8(); + + byte[] data = trxExtBuilder.getConstantResult(0).toByteArray(); + if (data.length > 4 && Hex.toHexString(data).startsWith("08c379a0")) { // Error(string) + String msg = ContractEventParser + .parseDataBytes(org.bouncycastle.util.Arrays.copyOfRange(data, 4, data.length), + "string", 0); + errMsg += ": " + msg; + } + + throw new JsonRpcInternalException(errMsg); + } else { + return ByteArray.toJsonHex(trxExtBuilder.getEnergyUsed()); + } } @Override @@ -689,7 +717,7 @@ public TransactionReceipt getTransactionReceipt(String txId) @Override public String getCall(CallArguments transactionCall, String blockNumOrTag) - throws JsonRpcInvalidParamsException { + throws JsonRpcInvalidParamsException, JsonRpcInternalException { if (EARLIEST_STR.equalsIgnoreCase(blockNumOrTag) || PENDING_STR.equalsIgnoreCase(blockNumOrTag)) { throw new JsonRpcInvalidParamsException(TAG_NOT_SUPPORT_ERROR); diff --git a/framework/src/test/java/org/tron/common/logsfilter/EventParserTest.java b/framework/src/test/java/org/tron/common/logsfilter/EventParserTest.java index 5745102156b..a9b06c0e039 100644 --- a/framework/src/test/java/org/tron/common/logsfilter/EventParserTest.java +++ b/framework/src/test/java/org/tron/common/logsfilter/EventParserTest.java @@ -5,6 +5,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import org.bouncycastle.util.Arrays; import org.junit.Test; import org.testng.Assert; import org.tron.common.crypto.Hash; @@ -96,4 +97,18 @@ public synchronized void testEventParser() { Assert.assertEquals(dataMap.get("str"), "abcdefg123"); } + + @Test + public void testParseRevert() { + String dataHex = "08c379a0" + + "0000000000000000000000000000000000000000000000000000000000000020" + + "0000000000000000000000000000000000000000000000000000000000000016" + + "6e6f7420656e6f75676820696e7075742076616c756500000000000000000000"; + + byte[] data = ByteArray.fromHexString(dataHex); + String msg = ContractEventParser.parseDataBytes(Arrays.copyOfRange(data, 4, data.length), + "string", 0); + Assert.assertEquals(msg, "not enough input value"); + + } } From 8afd14dab08551385c6df6cafe723eb1727fad72 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Fri, 5 Aug 2022 17:44:23 +0800 Subject: [PATCH 0196/1197] feat(jsonrpc): catch exception when call and return err msg --- .../core/services/jsonrpc/TronJsonRpc.java | 4 +- .../services/jsonrpc/TronJsonRpcImpl.java | 37 ++++++++++--------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpc.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpc.java index edbb9377988..caf0292a35c 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpc.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpc.java @@ -148,11 +148,13 @@ TransactionResult getTransactionByBlockNumberAndIndex(String blockNumOrTag, Stri @JsonRpcMethod("eth_call") @JsonRpcErrors({ + @JsonRpcError(exception = JsonRpcInvalidRequestException.class, code = -32600, data = "{}"), @JsonRpcError(exception = JsonRpcInvalidParamsException.class, code = -32602, data = "{}"), @JsonRpcError(exception = JsonRpcInternalException.class, code = -32000, data = "{}"), }) String getCall(CallArguments transactionCall, String blockNumOrTag) - throws JsonRpcInvalidParamsException, JsonRpcInternalException; + throws JsonRpcInvalidParamsException, JsonRpcInvalidRequestException, + JsonRpcInternalException; @JsonRpcMethod("net_peerCount") String getPeerCount(); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 503d42b295d..82568f09acd 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -1,7 +1,6 @@ package org.tron.core.services.jsonrpc; import static org.tron.core.Wallet.CONTRACT_VALIDATE_ERROR; -import static org.tron.core.Wallet.CONTRACT_VALIDATE_EXCEPTION; import static org.tron.core.services.http.Util.setTransactionExtraData; import static org.tron.core.services.http.Util.setTransactionPermissionId; import static org.tron.core.services.jsonrpc.JsonRpcApiUtil.addressCompatibleToByteArray; @@ -136,6 +135,7 @@ public enum RequestSource { private static final String QUANTITY_NOT_SUPPORT_ERROR = "QUANTITY not supported, just support TAG as latest"; + private static final String ERROR_SELECTOR = "08c379a0"; // Function selector for Error(string) /** * thread pool of query section bloom store */ @@ -392,7 +392,7 @@ private void callTriggerConstantContract(byte[] ownerAddressByte, byte[] contrac * getMethodSign(methodName(uint256,uint256)) || data1 || data2 */ private String call(byte[] ownerAddressByte, byte[] contractAddressByte, long value, - byte[] data) throws JsonRpcInternalException { + byte[] data) throws JsonRpcInvalidRequestException, JsonRpcInternalException { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); @@ -403,20 +403,20 @@ private String call(byte[] ownerAddressByte, byte[] contractAddressByte, long va trxExtBuilder, retBuilder); } catch (ContractValidateException | VMIllegalException e) { - retBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) - .setMessage(ByteString.copyFromUtf8(CONTRACT_VALIDATE_ERROR + e.getMessage())); - trxExtBuilder.setResult(retBuilder); - logger.warn(CONTRACT_VALIDATE_EXCEPTION, e.getMessage()); - } catch (RuntimeException e) { - retBuilder.setResult(false).setCode(response_code.CONTRACT_EXE_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); - trxExtBuilder.setResult(retBuilder); - logger.warn("When run constant call in VM, have RuntimeException: " + e.getMessage()); + String errString = CONTRACT_VALIDATE_ERROR; + if (e.getMessage() != null) { + errString = e.getMessage(); + } + + throw new JsonRpcInvalidRequestException(errString); } catch (Exception e) { - retBuilder.setResult(false).setCode(response_code.OTHER_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); - trxExtBuilder.setResult(retBuilder); - logger.warn("Unknown exception caught: " + e.getMessage(), e); + String errString = JSON_ERROR; + if (e.getMessage() != null) { + errString = e.getMessage().replaceAll("[\"]", "'"); + } + + throw new JsonRpcInternalException(errString); + } finally { trxExt = trxExtBuilder.build(); } @@ -433,7 +433,7 @@ private String call(byte[] ownerAddressByte, byte[] contractAddressByte, long va logger.error("trigger contract failed."); String errMsg = retBuilder.getMessage().toStringUtf8(); byte[] resData = trxExtBuilder.getConstantResult(0).toByteArray(); - if (resData.length > 4 && Hex.toHexString(resData).startsWith("08c379a0")) { // Error(string) + if (resData.length > 4 && Hex.toHexString(resData).startsWith(ERROR_SELECTOR)) { String msg = ContractEventParser .parseDataBytes(org.bouncycastle.util.Arrays.copyOfRange(resData, 4, resData.length), "string", 0); @@ -578,7 +578,7 @@ public String estimateGas(CallArguments args) throws JsonRpcInvalidRequestExcept String errMsg = retBuilder.getMessage().toStringUtf8(); byte[] data = trxExtBuilder.getConstantResult(0).toByteArray(); - if (data.length > 4 && Hex.toHexString(data).startsWith("08c379a0")) { // Error(string) + if (data.length > 4 && Hex.toHexString(data).startsWith(ERROR_SELECTOR)) { String msg = ContractEventParser .parseDataBytes(org.bouncycastle.util.Arrays.copyOfRange(data, 4, data.length), "string", 0); @@ -717,7 +717,8 @@ public TransactionReceipt getTransactionReceipt(String txId) @Override public String getCall(CallArguments transactionCall, String blockNumOrTag) - throws JsonRpcInvalidParamsException, JsonRpcInternalException { + throws JsonRpcInvalidParamsException, JsonRpcInvalidRequestException, + JsonRpcInternalException { if (EARLIEST_STR.equalsIgnoreCase(blockNumOrTag) || PENDING_STR.equalsIgnoreCase(blockNumOrTag)) { throw new JsonRpcInvalidParamsException(TAG_NOT_SUPPORT_ERROR); From bb1cb58e845d765682065308a70e627f071edce4 Mon Sep 17 00:00:00 2001 From: bladehan1 Date: Fri, 5 Aug 2022 17:55:54 +0800 Subject: [PATCH 0197/1197] fix(net): change process exception 1. avoid infinite loop when exception cause has loop --- .../main/java/org/tron/common/overlay/server/Channel.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/Channel.java b/framework/src/main/java/org/tron/common/overlay/server/Channel.java index 68ff3174f22..0a4c92a87a1 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/Channel.java +++ b/framework/src/main/java/org/tron/common/overlay/server/Channel.java @@ -1,5 +1,6 @@ package org.tron.common.overlay.server; +import com.google.common.base.Throwables; import com.google.protobuf.ByteString; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPipeline; @@ -148,8 +149,11 @@ public void disconnect(ReasonCode reason) { public void processException(Throwable throwable) { Throwable baseThrowable = throwable; - while (baseThrowable.getCause() != null) { - baseThrowable = baseThrowable.getCause(); + try { + baseThrowable = Throwables.getRootCause(baseThrowable); + } catch (IllegalArgumentException e) { + baseThrowable = e.getCause(); + logger.warn("Loop in causal chain detected"); } SocketAddress address = ctx.channel().remoteAddress(); if (throwable instanceof ReadTimeoutException From 77fb40fe80c921e230a54b69e9cf62335a8e0f0c Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 8 Aug 2022 11:53:54 +0800 Subject: [PATCH 0198/1197] perf(net): configurable block cache validity period --- .../java/org/tron/common/parameter/CommonParameter.java | 4 ++++ common/src/main/java/org/tron/core/Constant.java | 2 ++ framework/src/main/java/org/tron/core/config/args/Args.java | 6 +++++- .../src/main/java/org/tron/core/net/service/AdvService.java | 4 +++- .../main/java/org/tron/core/net/service/SyncService.java | 4 +++- .../src/test/java/org/tron/common/config/args/ArgsTest.java | 1 + 6 files changed, 18 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 6daf213e672..9a8117c4364 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -544,6 +544,10 @@ public class CommonParameter { @Setter public long shutdownBlockCount = -1; + @Getter + @Setter + public long blockCacheTimeout = 60; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 883e4cd3f6a..94eed9f9941 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -311,4 +311,6 @@ public class Constant { public static final String NODE_SHUTDOWN_BLOCK_TIME = "node.shutdown.BlockTime"; public static final String NODE_SHUTDOWN_BLOCK_HEIGHT = "node.shutdown.BlockHeight"; public static final String NODE_SHUTDOWN_BLOCK_COUNT = "node.shutdown.BlockCount"; + + public static final String BLOCK_CACHE_TIMEOUT = "node.blockCacheTimeout"; } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 38ae934877e..16ede8cdbaa 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -207,7 +207,7 @@ public static void clearParam() { PARAMETER.shutdownBlockTime = null; PARAMETER.shutdownBlockHeight = -1; PARAMETER.shutdownBlockCount = -1; - + PARAMETER.blockCacheTimeout = 60; } /** @@ -925,6 +925,10 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.shutdownBlockCount = config.getLong(Constant.NODE_SHUTDOWN_BLOCK_COUNT); } + if (config.hasPath(Constant.BLOCK_CACHE_TIMEOUT)) { + PARAMETER.blockCacheTimeout = config.getLong(Constant.BLOCK_CACHE_TIMEOUT); + } + logConfig(); } diff --git a/framework/src/main/java/org/tron/core/net/service/AdvService.java b/framework/src/main/java/org/tron/core/net/service/AdvService.java index 2df3598f611..e0dc4238ab7 100644 --- a/framework/src/main/java/org/tron/core/net/service/AdvService.java +++ b/framework/src/main/java/org/tron/core/net/service/AdvService.java @@ -57,8 +57,10 @@ public class AdvService { private ConcurrentHashMap invToSpread = new ConcurrentHashMap<>(); + private long blockCacheTimeout = Args.getInstance().getBlockCacheTimeout(); private Cache invToFetchCache = CacheBuilder.newBuilder() - .maximumSize(MAX_INV_TO_FETCH_CACHE_SIZE).expireAfterWrite(1, TimeUnit.HOURS) + .maximumSize(MAX_INV_TO_FETCH_CACHE_SIZE) + .expireAfterWrite(blockCacheTimeout, TimeUnit.MINUTES) .recordStats().build(); private Cache trxCache = CacheBuilder.newBuilder() diff --git a/framework/src/main/java/org/tron/core/net/service/SyncService.java b/framework/src/main/java/org/tron/core/net/service/SyncService.java index a845636784f..8e4d7a49b3d 100644 --- a/framework/src/main/java/org/tron/core/net/service/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/SyncService.java @@ -23,6 +23,7 @@ import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.config.Parameter.NetConstants; +import org.tron.core.config.args.Args; import org.tron.core.exception.P2pException; import org.tron.core.exception.P2pException.TypeEnum; import org.tron.core.net.TronNetDelegate; @@ -48,8 +49,9 @@ public class SyncService { private Map blockJustReceived = new ConcurrentHashMap<>(); + private long blockCacheTimeout = Args.getInstance().getBlockCacheTimeout(); private Cache requestBlockIds = CacheBuilder.newBuilder().maximumSize(10_000) - .expireAfterWrite(1, TimeUnit.HOURS).initialCapacity(10_000) + .expireAfterWrite(blockCacheTimeout, TimeUnit.MINUTES).initialCapacity(10_000) .recordStats().build(); private ScheduledExecutorService fetchExecutor = Executors.newSingleThreadScheduledExecutor(); diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index 2732824779e..5b391f0d38d 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -29,5 +29,6 @@ public void testConfig() { Assert.assertEquals(Args.getInstance().getPendingTransactionTimeout(), 60_000); Assert.assertEquals(Args.getInstance().getNodeDiscoveryPingTimeout(), 15_000); Assert.assertEquals(Args.getInstance().getMaxFastForwardNum(), 3); + Assert.assertEquals(Args.getInstance().getBlockCacheTimeout(), 60); } } \ No newline at end of file From b6a6b8303c21aa05c63b35c766ccfe97abe4e51f Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 8 Aug 2022 19:01:16 +0800 Subject: [PATCH 0199/1197] test(api):add test for query block header. --- .../test/java/org/tron/core/WalletTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 4c0ff5ed6c4..1b35a78bf82 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static stest.tron.wallet.common.client.utils.PublicMethed.decode58Check; import com.google.protobuf.Any; @@ -36,6 +37,7 @@ import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; +import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.AssetIssueList; import org.tron.api.GrpcAPI.BlockList; import org.tron.api.GrpcAPI.ExchangeList; @@ -503,6 +505,32 @@ public void getPaginatedExchangeList() { exchangeList.getExchangesList().get(1).getCreatorAddress().toStringUtf8()); } + @Test + public void getBlock() { + GrpcAPI.BlockReq req = GrpcAPI.BlockReq.getDefaultInstance(); + Block block = wallet.getBlock(req); + assertNotNull(block); + try { + req = req.toBuilder().setIdOrNum("-1").build(); + wallet.getBlock(req); + } catch (Exception e) { + Assert.assertTrue(e instanceof IllegalArgumentException); + } + try { + req = req.toBuilder().setIdOrNum("hash000001").build(); + wallet.getBlock(req); + } catch (Exception e) { + Assert.assertTrue(e instanceof IllegalArgumentException); + } + req = GrpcAPI.BlockReq.newBuilder().setIdOrNum("0").build(); + block = wallet.getBlock(req); + req = req.toBuilder().setDetail(true).build(); + assertEquals(block, wallet.getBlock(req).toBuilder().clearTransactions().build()); + req = req.toBuilder().clearDetail() + .setIdOrNum(new BlockCapsule(block).getBlockId().toString()).build(); + assertEquals(block, wallet.getBlock(req)); + } + //@Test public void testChainParameters() { From 8c91dd4d8b4cc6300c7fe68db415444580426532 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 8 Aug 2022 18:43:36 +0800 Subject: [PATCH 0200/1197] test(db-mv):add test for db mv func. --- .../java/org/tron/plugins/DbMoveTest.java | 157 ++++++++++++++++++ .../src/test/resources/config-duplicate.conf | 22 +++ plugins/src/test/resources/config.conf | 22 +++ 3 files changed, 201 insertions(+) create mode 100644 plugins/src/test/java/org/tron/plugins/DbMoveTest.java create mode 100644 plugins/src/test/resources/config-duplicate.conf create mode 100644 plugins/src/test/resources/config.conf diff --git a/plugins/src/test/java/org/tron/plugins/DbMoveTest.java b/plugins/src/test/java/org/tron/plugins/DbMoveTest.java new file mode 100644 index 00000000000..6bbac663c2c --- /dev/null +++ b/plugins/src/test/java/org/tron/plugins/DbMoveTest.java @@ -0,0 +1,157 @@ +package org.tron.plugins; + +import static org.iq80.leveldb.impl.Iq80DBFactory.factory; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Paths; +import java.util.Properties; +import java.util.UUID; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import picocli.CommandLine; + +@Slf4j +public class DbMoveTest { + + private static final String OUTPUT_DIRECTORY = "output-directory-toolkit"; + private static final String OUTPUT_DIRECTORY_DATABASE = + Paths.get(OUTPUT_DIRECTORY,"ori","database").toString(); + private static final String ENGINE = "ENGINE"; + private static final String LEVELDB = "LEVELDB"; + private static final String ACCOUNT = "account"; + private static final String TRANS = "trans"; + private static final String MARKET = "market_pair_price_to_order"; + private static final String ENGINE_FILE = "engine.properties"; + + + @BeforeClass + public static void init() throws IOException { + File file = new File(OUTPUT_DIRECTORY_DATABASE, ACCOUNT); + factory.open(file, ArchiveManifest.newDefaultLevelDbOptions()).close(); + writeProperty(file + File.separator + ENGINE_FILE, ENGINE, LEVELDB); + + file = new File(OUTPUT_DIRECTORY_DATABASE, MARKET); + factory.open(file, ArchiveManifest.newDefaultLevelDbOptions()).close(); + writeProperty(file + File.separator + ENGINE_FILE, ENGINE, LEVELDB); + + file = new File(OUTPUT_DIRECTORY_DATABASE, TRANS); + factory.open(file, ArchiveManifest.newDefaultLevelDbOptions()).close(); + writeProperty(file + File.separator + ENGINE_FILE, ENGINE, LEVELDB); + + } + + @AfterClass + public static void destroy() { + deleteDir(new File(OUTPUT_DIRECTORY)); + } + + private static void writeProperty(String filename, String key, String value) throws IOException { + File file = new File(filename); + if (!file.exists()) { + file.createNewFile(); + } + + try (FileInputStream fis = new FileInputStream(file); + OutputStream out = new FileOutputStream(file); + BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out, + StandardCharsets.UTF_8))) { + BufferedReader bf = new BufferedReader(new InputStreamReader(fis, StandardCharsets.UTF_8)); + Properties properties = new Properties(); + properties.load(bf); + properties.setProperty(key, value); + properties.store(bw, "Generated by the application. PLEASE DO NOT EDIT! "); + } catch (Exception e) { + logger.warn("{}", e); + } + } + + /** + * delete directory. + */ + private static boolean deleteDir(File dir) { + if (dir.isDirectory()) { + String[] children = dir.list(); + assert children != null; + for (String child : children) { + boolean success = deleteDir(new File(dir, child)); + if (!success) { + logger.warn("can't delete dir:" + dir); + return false; + } + } + } + return dir.delete(); + } + + private static String getConfig(String config) { + URL path = DbMoveTest.class.getClassLoader().getResource(config); + return path == null ? null : path.getPath(); + } + + @Test + public void testMv() { + String[] args = new String[] {"db", "mv", "-d", + Paths.get(OUTPUT_DIRECTORY,"ori").toString(), "-c", + getConfig("config.conf")}; + CommandLine cli = new CommandLine(new Toolkit()); + Assert.assertEquals(0, cli.execute(args)); + Assert.assertEquals(2, cli.execute(args)); + } + + @Test + public void testDuplicate() { + String[] args = new String[] {"db", "mv", "-d", + Paths.get(OUTPUT_DIRECTORY,"ori").toString(), "-c", + getConfig("config-duplicate.conf")}; + CommandLine cli = new CommandLine(new Toolkit()); + Assert.assertEquals(2, cli.execute(args)); + } + + @Test + public void testHelp() { + String[] args = new String[] {}; + CommandLine cli = new CommandLine(new Toolkit()); + Assert.assertEquals(0, cli.execute(args)); + } + + @Test + public void testDicNotExist() { + String[] args = new String[] {"db", "mv", "-d", "dicNotExist"}; + CommandLine cli = new CommandLine(new Toolkit()); + Assert.assertEquals(2, cli.execute(args)); + } + + @Test + public void testConfNotExist() { + String[] args = new String[] {"db", "mv", "-d", + Paths.get(OUTPUT_DIRECTORY,"ori").toString(), "-c", + "config.conf"}; + CommandLine cli = new CommandLine(new Toolkit()); + Assert.assertEquals(2, cli.execute(args)); + } + + @Test + public void testEmpty() { + File file = new File(OUTPUT_DIRECTORY_DATABASE + File.separator + UUID.randomUUID()); + file.mkdirs(); + file.deleteOnExit(); + String[] args = new String[] {"db", "mv", "-d", file.toString(), "-c", + getConfig("config.conf")}; + CommandLine cli = new CommandLine(new Toolkit()); + + Assert.assertEquals(2, cli.execute(args)); + } +} diff --git a/plugins/src/test/resources/config-duplicate.conf b/plugins/src/test/resources/config-duplicate.conf new file mode 100644 index 00000000000..758312ad05e --- /dev/null +++ b/plugins/src/test/resources/config-duplicate.conf @@ -0,0 +1,22 @@ + +storage { + # Directory for storing persistent data + db.version = 2, + db.engine = "LEVELDB", + db.sync = false, + db.directory = "database", + index.directory = "index", + transHistory.switch = "on", + properties = [ + { + name = "trans", + path = "output-directory-toolkit/dest", + }, + { + name = "trans", + path = "output-directory-toolkit/dest2", + }, + ] +} + + diff --git a/plugins/src/test/resources/config.conf b/plugins/src/test/resources/config.conf new file mode 100644 index 00000000000..be16d44c420 --- /dev/null +++ b/plugins/src/test/resources/config.conf @@ -0,0 +1,22 @@ + +storage { + # Directory for storing persistent data + db.version = 2, + db.engine = "LEVELDB", + db.sync = false, + db.directory = "database", + index.directory = "index", + transHistory.switch = "on", + properties = [ + { + name = "account", + path = "output-directory-toolkit/dest", + }, + { + name = "market_pair_price_to_order", + path = "output-directory-toolkit/dest", + }, + ] +} + + From e4175e5cfdc014e1162e962d448cec39d7435649 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 9 Aug 2022 17:56:03 +0800 Subject: [PATCH 0201/1197] fix(solidityNode): fix solidity node startup issue --- .../java/org/tron/common/overlay/server/ChannelManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java b/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java index 1bed907c270..d9da821f495 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java +++ b/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java @@ -70,7 +70,7 @@ public class ChannelManager { private int maxConnectionsWithSameIp = parameter.getMaxConnectionsWithSameIp(); public void init() { - if (this.parameter.getNodeListenPort() > 0) { + if (this.parameter.getNodeListenPort() > 0 && !this.parameter.isSolidityNode()) { new Thread(() -> peerServer.start(Args.getInstance().getNodeListenPort()), "PeerServerThread").start(); } From 42eec0d0ee86278f86023fce68fef0111b2f9833 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 9 Aug 2022 18:36:13 +0800 Subject: [PATCH 0202/1197] perf(solidityNode): optimize solidity node startup process --- .../java/org/tron/common/overlay/discover/DiscoverServer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java b/framework/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java index 4a0d49a9cb6..983be8543ef 100755 --- a/framework/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java +++ b/framework/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java @@ -59,7 +59,8 @@ public class DiscoverServer { @Autowired public DiscoverServer(final NodeManager nodeManager) { this.nodeManager = nodeManager; - if (parameter.isNodeDiscoveryEnable() && !parameter.isFastForward()) { + if (parameter.isNodeDiscoveryEnable() && !parameter.isFastForward() + && !parameter.isSolidityNode()) { if (port == 0) { logger.error("Discovery can't be started while listen port == 0"); } else { From 36305069cfd9980b1e76df27daaded41ed30e8e7 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 10 Aug 2022 12:04:22 +0800 Subject: [PATCH 0203/1197] fix(lite):fix merge function when split and merge base on liteNode. --- .../tron/tool/litefullnode/LiteFullNodeTool.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java index 17f4a4d81e4..2de9972f73c 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java @@ -489,12 +489,15 @@ private static boolean isEmptyBytes(byte[] b) { private void deleteSnapshotFlag(String databaseDir) throws IOException, RocksDBException { logger.info("-- delete the info file to identify this node is a real fullnode."); Files.delete(Paths.get(databaseDir, INFO_FILE_NAME)); + DBInterface destBlockIndexDb = DbTool.getDB(databaseDir, BLOCK_INDEX_DB_NAME); + if (destBlockIndexDb.get(ByteArray.fromLong(1)) != null) { + DBInterface destCommonDb = DbTool.getDB(databaseDir, COMMON_DB_NAME); + destCommonDb.delete(DB_KEY_NODE_TYPE); + destCommonDb.delete(DB_KEY_LOWEST_BLOCK_NUM); + logger.info("-- deleted node_type and lowest_block_num from " + + "common to identify this node is a real fullnode."); + } - DBInterface destCommonDb = DbTool.getDB(databaseDir, COMMON_DB_NAME); - destCommonDb.delete(DB_KEY_NODE_TYPE); - destCommonDb.delete(DB_KEY_LOWEST_BLOCK_NUM); - logger.info("-- deleted node_type and lowest_block_num from " - + "common to identify this node is a real fullnode."); } private void run(Args argv) { From 40b250cba9bc6d57a4786ba8cc780038476aa712 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Wed, 10 Aug 2022 15:42:18 +0800 Subject: [PATCH 0204/1197] fix(tx-cache): fix lite node init error. --- .../src/main/java/org/tron/core/db/Manager.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 0d25dadf48e..6152fa526da 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -2279,13 +2279,22 @@ public long getPendingSize() { private void initLiteNode() { // When using bloom filter for transaction de-duplication, // it is possible to use trans for secondary confirmation. - // Init trans db for liteNode, + // Init trans db for liteNode if needed. long headNum = chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber(); long recentBlockCount = chainBaseManager.getRecentBlockStore().size(); long recentBlockStart = headNum - recentBlockCount + 1; - try { - chainBaseManager.getBlockByNum(recentBlockStart); - } catch (ItemNotFoundException | BadItemException e) { + boolean needInit = false; + if (recentBlockStart == 0) { + needInit = true; + } else { + try { + chainBaseManager.getBlockByNum(recentBlockStart); + } catch (ItemNotFoundException | BadItemException e) { + needInit = true; + } + } + + if (needInit) { // copy transaction from recent-transaction to trans logger.info("load trans for lite node."); From afbd927388e77a93476f58a9da45272dd0ce62e0 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 10 Aug 2022 16:51:29 +0800 Subject: [PATCH 0205/1197] log(lite-tool):merge function. --- .../main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java index 2de9972f73c..037760e201a 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java @@ -487,7 +487,7 @@ private static boolean isEmptyBytes(byte[] b) { } private void deleteSnapshotFlag(String databaseDir) throws IOException, RocksDBException { - logger.info("-- delete the info file to identify this node is a real fullnode."); + logger.info("-- delete the info file."); Files.delete(Paths.get(databaseDir, INFO_FILE_NAME)); DBInterface destBlockIndexDb = DbTool.getDB(databaseDir, BLOCK_INDEX_DB_NAME); if (destBlockIndexDb.get(ByteArray.fromLong(1)) != null) { From f53fee84f2ed8acaa5828081ed484f1e96d58997 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Wed, 10 Aug 2022 18:39:21 +0800 Subject: [PATCH 0206/1197] feat(tx-cache): change the default value of the txCache.estimatedTransactions param. --- common/src/main/java/org/tron/core/config/args/Storage.java | 2 +- framework/src/main/resources/config.conf | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/org/tron/core/config/args/Storage.java b/common/src/main/java/org/tron/core/config/args/Storage.java index 60e3cd9ba6d..1ea7e00eb1f 100644 --- a/common/src/main/java/org/tron/core/config/args/Storage.java +++ b/common/src/main/java/org/tron/core/config/args/Storage.java @@ -79,7 +79,7 @@ public class Storage { private static final String DEFAULT_DB_DIRECTORY = "database"; private static final String DEFAULT_INDEX_DIRECTORY = "index"; private static final String DEFAULT_INDEX_SWITCH = "on"; - private static final int DEFAULT_ESTIMATED_TRANSACTIONS = 500; + private static final int DEFAULT_ESTIMATED_TRANSACTIONS = 1000; private Config storage; /** diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index eeca1172a3e..aa1f51507bf 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -90,9 +90,9 @@ storage { balance.history.lookup = false - # the estimated number of block transactions (default 500, min 100, max 10000). + # the estimated number of block transactions (default 1000, min 100, max 10000). # so the total number of cached transactions is 65536 * txCache.estimatedTransactions - # txCache.estimatedTransactions = 500 + # txCache.estimatedTransactions = 1000 } From f7f88b0aa7f79a02048e62b588f25f6c4bca8064 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 11 Aug 2022 11:43:05 +0800 Subject: [PATCH 0207/1197] fix(block): fix different result code when fork. 1.use deep copy for trx when put poppedTransactions. --- framework/src/main/java/org/tron/core/db/Manager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 6152fa526da..e5eee4eda7e 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -869,7 +869,8 @@ public void eraseBlock() { khaosDb.pop(); revokingStore.fastPop(); logger.info("end to erase block:" + oldHeadBlock); - poppedTransactions.addAll(oldHeadBlock.getTransactions()); + oldHeadBlock.getTransactions().forEach(tc -> + poppedTransactions.add(new TransactionCapsule(tc.getInstance()))); Metrics.gaugeInc(MetricKeys.Gauge.MANAGER_QUEUE, oldHeadBlock.getTransactions().size(), MetricLabels.Gauge.QUEUE_POPPED); From 8f1b4c2d1bc9da197fae717e2005d83511537457 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Fri, 12 Aug 2022 11:12:34 +0800 Subject: [PATCH 0208/1197] close the peer connection when the service is down --- .../main/java/org/tron/common/overlay/server/SyncPool.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java b/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java index 4c35f6b628d..d850a387d98 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java +++ b/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java @@ -217,6 +217,11 @@ public boolean isCanConnect() { public void close() { try { + activePeers.forEach(p -> { + if (!p.isDisconnect()) { + p.close(); + } + }); poolLoopExecutor.shutdownNow(); logExecutor.shutdownNow(); } catch (Exception e) { From 378dd3eb393e197775ecc1ee68164c06a7b50c2d Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 12 Aug 2022 16:01:38 +0800 Subject: [PATCH 0209/1197] fix(vm, hard_fork): init energy limit hard fork while init db manager --- framework/src/main/java/org/tron/core/db/Manager.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 6152fa526da..50e81ea602f 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -85,6 +85,7 @@ import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.capsule.BytesCapsule; +import org.tron.core.capsule.ReceiptCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.TransactionInfoCapsule; import org.tron.core.capsule.TransactionRetCapsule; @@ -154,6 +155,7 @@ import org.tron.core.store.WitnessScheduleStore; import org.tron.core.store.WitnessStore; import org.tron.core.utils.TransactionRegister; +import org.tron.core.vm.config.VMConfig; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Permission; import org.tron.protos.Protocol.Transaction; @@ -534,7 +536,9 @@ public void init() { //initActuatorCreator ActuatorCreator.init(); TransactionRegister.registerActuator(); - + //initEnergyLimitHardFork + VMConfig.initVmHardFork(ReceiptCapsule.checkForEnergyLimit( + chainBaseManager.getDynamicPropertiesStore())); long exitHeight = CommonParameter.getInstance().getShutdownBlockHeight(); long exitCount = CommonParameter.getInstance().getShutdownBlockCount(); From 6d8cea70677b875d7034130bbeb88894da8fba11 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Fri, 12 Aug 2022 17:33:35 +0800 Subject: [PATCH 0210/1197] perf(net): optimize message sending thread shutdown logic --- .../main/java/org/tron/common/overlay/server/MessageQueue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java index 9b702dac915..2edf84c8e32 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java +++ b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java @@ -155,7 +155,7 @@ public void receivedMessage(Message msg) { public void close() { sendMsgFlag = false; if (sendTask != null && !sendTask.isCancelled()) { - sendTask.cancel(false); + sendTask.cancel(true); sendTask = null; } if (sendMsgThread != null) { From 2cb7b7b4e9a084de28b0284ce0fc846976d1fedd Mon Sep 17 00:00:00 2001 From: liukai Date: Mon, 15 Aug 2022 10:51:07 +0800 Subject: [PATCH 0211/1197] feat(version): update Version 1. update version to 4.5.2 --- framework/src/main/java/org/tron/program/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 944511cbd4e..704ee0f2806 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -4,7 +4,7 @@ public class Version { public static final String VERSION_NAME = "GreatVoyage-v4.4.6-257-ge06abd15c"; public static final String VERSION_CODE = "16944"; - private static final String VERSION = "4.5.1"; + private static final String VERSION = "4.5.2"; public static String getVersion() { return VERSION; From 18fcccc7bb77924fb820e0771a380342dcdc3077 Mon Sep 17 00:00:00 2001 From: liukai Date: Tue, 16 Aug 2022 14:46:28 +0800 Subject: [PATCH 0212/1197] feat(version): modify error log 1. modify PacketDecoder decode log --- .../java/org/tron/common/net/udp/handler/PacketDecoder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/common/net/udp/handler/PacketDecoder.java b/framework/src/main/java/org/tron/common/net/udp/handler/PacketDecoder.java index 48f369462b4..4859dcd04f6 100644 --- a/framework/src/main/java/org/tron/common/net/udp/handler/PacketDecoder.java +++ b/framework/src/main/java/org/tron/common/net/udp/handler/PacketDecoder.java @@ -38,7 +38,7 @@ public void decode(ChannelHandlerContext ctx, DatagramPacket packet, List= MAXSIZE) { logger - .error("UDP rcv bad packet, from {} length = {}", ctx.channel().remoteAddress(), length); + .warn("UDP rcv bad packet, from {} length = {}", ctx.channel().remoteAddress(), length); return; } byte[] encoded = new byte[length]; From 4d8cb29ad39a71b0a12f47e9859bf28e94fbf49c Mon Sep 17 00:00:00 2001 From: lvs007 Date: Thu, 18 Aug 2022 14:50:17 +0800 Subject: [PATCH 0213/1197] update a new version. version name:GreatVoyage-v4.5.1-125-ga9809b5bb,version code:17071 --- framework/src/main/java/org/tron/program/Version.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 704ee0f2806..4296f5daf1a 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,8 +2,8 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.4.6-257-ge06abd15c"; - public static final String VERSION_CODE = "16944"; + public static final String VERSION_NAME = "GreatVoyage-v4.5.1-125-ga9809b5bb"; + public static final String VERSION_CODE = "17071"; private static final String VERSION = "4.5.2"; public static String getVersion() { From 94db8dc18b3b23ccadeabbd482051e803e07ad69 Mon Sep 17 00:00:00 2001 From: yingying Date: Mon, 22 Aug 2022 18:25:47 +0800 Subject: [PATCH 0214/1197] Update CONTRIBUTING.md --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 29368a646ab..b412bd4ee37 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -186,10 +186,10 @@ Message body use the imperative, present tense: "change" not "changed" nor "chan Here is an example: ``` -feat(block): optimize product block +feat(block): Optimize the block-producing logic -1. optimize the block production threads -2. improve transaction entry speed +1. increase the priority that block producing thread acquires synchronization lock +2. add the interruption exception handling in block-producing thread Closes #1234 ``` From b2782b38aad501f0b7c4934e5bd078e683be1210 Mon Sep 17 00:00:00 2001 From: yingying Date: Mon, 22 Aug 2022 18:35:25 +0800 Subject: [PATCH 0215/1197] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b412bd4ee37..c81587501f3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -186,7 +186,7 @@ Message body use the imperative, present tense: "change" not "changed" nor "chan Here is an example: ``` -feat(block): Optimize the block-producing logic +feat(block): optimize the block-producing logic 1. increase the priority that block producing thread acquires synchronization lock 2. add the interruption exception handling in block-producing thread From 8c0bf60c14eba98476087b7810aaae6a9546af62 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 22 Aug 2022 14:10:26 +0800 Subject: [PATCH 0216/1197] feat(db): remove method getValuesPrev 1. this method is not used, and is wrong in some case 2. re-add correct method if it may be used in the future --- .../leveldb/LevelDbDataSourceImpl.java | 24 ------------------- .../rocksdb/RocksDbDataSourceImpl.java | 24 ------------------- .../leveldb/LevelDbDataSourceImplTest.java | 19 --------------- .../leveldb/RocksDbDataSourceImplTest.java | 19 --------------- 4 files changed, 86 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java index 936d089573e..20ad57d4929 100644 --- a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java @@ -373,30 +373,6 @@ public Map prefixQuery(byte[] key) { } } - public Set getValuesPrev(byte[] key, long limit) { - if (limit <= 0) { - return Sets.newHashSet(); - } - resetDbLock.readLock().lock(); - try (DBIterator iterator = getDBIterator()) { - Set result = Sets.newHashSet(); - long i = 0; - byte[] data = getData(key); - if (Objects.nonNull(data)) { - result.add(data); - i++; - } - for (iterator.seek(key); iterator.hasPrev() && i++ < limit; iterator.prev()) { - result.add(iterator.peekPrev().getValue()); - } - return result; - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - resetDbLock.readLock().unlock(); - } - } - @Override public long getTotal() throws RuntimeException { resetDbLock.readLock().lock(); diff --git a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java index 82bd8505e52..0733094312f 100644 --- a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java @@ -472,30 +472,6 @@ public Set getlatestValues(long limit) { } } - public Set getValuesPrev(byte[] key, long limit) { - if (quitIfNotAlive()) { - return null; - } - if (limit <= 0) { - return Sets.newHashSet(); - } - resetDbLock.readLock().lock(); - try (RocksIterator iter = getRocksIterator()) { - Set result = Sets.newHashSet(); - long i = 0; - byte[] data = getData(key); - if (Objects.nonNull(data)) { - result.add(data); - i++; - } - for (iter.seekForPrev(key); iter.isValid() && i < limit; iter.prev(), i++) { - result.add(iter.value()); - } - return result; - } finally { - resetDbLock.readLock().unlock(); - } - } public Set getValuesNext(byte[] key, long limit) { if (quitIfNotAlive()) { diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java index 7cc85c37be1..e693b90c3fa 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java @@ -259,25 +259,6 @@ public void getValuesNext() { dataSource.closeDB(); } - @Test - public void getValuesPrev() { - LevelDbDataSourceImpl dataSource = new LevelDbDataSourceImpl( - Args.getInstance().getOutputDirectory(), "test_getValuesPrev_key"); - dataSource.initDB(); - dataSource.resetDb(); - - putSomeKeyValue(dataSource); - Set seekKeyLimitNext = dataSource.getValuesPrev("0000000300".getBytes(), 2); - HashSet hashSet = Sets.newHashSet(ByteArray.toStr(value1), ByteArray.toStr(value2)); - seekKeyLimitNext.forEach(valeu -> { - Assert.assertTrue("getValuesPrev1", hashSet.contains(ByteArray.toStr(valeu))); - }); - seekKeyLimitNext = dataSource.getValuesPrev("0000000100".getBytes(), 2); - Assert.assertEquals("getValuesPrev2", 0, seekKeyLimitNext.size()); - dataSource.resetDb(); - dataSource.closeDB(); - } - @Test public void testGetTotal() { LevelDbDataSourceImpl dataSource = new LevelDbDataSourceImpl( diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java index 0e628500870..a62c6bbefb9 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java @@ -247,25 +247,6 @@ public void getValuesNext() { dataSource.closeDB(); } - @Test - public void getValuesPrev() { - RocksDbDataSourceImpl dataSource = new RocksDbDataSourceImpl( - Args.getInstance().getOutputDirectory(), "test_getValuesPrev_key"); - dataSource.initDB(); - dataSource.resetDb(); - - putSomeKeyValue(dataSource); - Set seekKeyLimitNext = dataSource.getValuesPrev("0000000300".getBytes(), 2); - HashSet hashSet = Sets.newHashSet(ByteArray.toStr(value1), ByteArray.toStr(value2)); - seekKeyLimitNext.forEach(value -> { - Assert.assertTrue("getValuesPrev1", hashSet.contains(ByteArray.toStr(value))); - }); - seekKeyLimitNext = dataSource.getValuesPrev("0000000100".getBytes(), 2); - Assert.assertEquals("getValuesPrev2", 0, seekKeyLimitNext.size()); - dataSource.resetDb(); - dataSource.closeDB(); - } - @Test public void testCheckOrInitEngine() { String dir = From f827359ff5cbec337626918d5944c13b8528d88e Mon Sep 17 00:00:00 2001 From: bladehan1 Date: Fri, 19 Aug 2022 11:29:34 +0800 Subject: [PATCH 0217/1197] feat(command): show help message 1. show help information in groups, with version information --- .../common/parameter/CommonParameter.java | 45 +++++---- .../java/org/tron/core/config/args/Args.java | 95 +++++++++++++++++++ .../main/java/org/tron/program/FullNode.java | 5 +- 3 files changed, 126 insertions(+), 19 deletions(-) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 9a8117c4364..283ffd299e3 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -25,44 +25,51 @@ public class CommonParameter { public static CommonParameter PARAMETER = new CommonParameter(); @Setter public static boolean ENERGY_LIMIT_HARD_FORK = false; - @Parameter(names = {"-c", "--config"}, description = "Config File") + @Parameter(names = {"-c", "--config"}, description = "Config file (default:config.conf)") public String shellConfFileName = ""; @Getter - @Parameter(names = {"-d", "--output-directory"}, description = "Directory") + @Parameter(names = {"-d", "--output-directory"}, + description = "Data directory for the databases (default:output-directory)") public String outputDirectory = "output-directory"; @Getter - @Parameter(names = {"--log-config"}) + @Parameter(names = {"--log-config"}, description = "Logback config file") public String logbackPath = ""; @Getter - @Parameter(names = {"-h", "--help"}, help = true, description = "HELP message") + @Parameter(names = {"-h", "--help"}, help = true, description = "Show help message") public boolean help = false; @Getter @Setter - @Parameter(names = {"-w", "--witness"}) + @Parameter(names = {"-w", "--witness"}, description = "Is witness node") public boolean witness = false; @Getter @Setter - @Parameter(names = {"--support-constant"}) + @Parameter(names = {"--support-constant"}, description = "Support constant calling for TVM. " + + "(defalut: false)") public boolean supportConstant = false; @Getter @Setter - @Parameter(names = {"--max-energy-limit-for-constant"}) + @Parameter(names = {"--max-energy-limit-for-constant"}, description = "Max energy limit for " + + "constant calling. (default: 100,000,000)") public long maxEnergyLimitForConstant = 100_000_000L; @Getter @Setter - @Parameter(names = {"--lru-cache-size"}) + @Parameter(names = {"--lru-cache-size"}, description = "Max LRU size for caching bytecode and " + + "result of JUMPDEST analysis. (default: 500)") public int lruCacheSize = 500; @Getter @Setter - @Parameter(names = {"--debug"}) + @Parameter(names = {"--debug"}, description = "Switch for TVM debug mode. In debug model, TVM " + + "will not check for timeout. (default: false)") public boolean debug = false; @Getter @Setter - @Parameter(names = {"--min-time-ratio"}) + @Parameter(names = {"--min-time-ratio"}, description = "Maximum CPU tolerance when executing " + + "non-timeout transactions while synchronizing blocks. (default: 5.0)") public double minTimeRatio = 0.0; @Getter @Setter - @Parameter(names = {"--max-time-ratio"}) + @Parameter(names = {"--max-time-ratio"}, description = "Maximum CPU tolerance when executing " + + "timeout transactions while synchronizing blocks. (default: 0.0)") public double maxTimeRatio = calcMaxTimeRatio(); @Getter @Setter @@ -70,12 +77,13 @@ public class CommonParameter { public int longRunningTime = 10; @Getter @Setter - @Parameter(names = {"--max-connect-number"}) + @Parameter(names = {"--max-connect-number"}, description = "Http server max connect number " + + "(default:50)") public int maxHttpConnectNumber = 50; @Getter @Parameter(description = "--seed-nodes") public List seedNodes = new ArrayList<>(); - @Parameter(names = {"-p", "--private-key"}, description = "private-key") + @Parameter(names = {"-p", "--private-key"}, description = "Witness private key") public String privateKey = ""; @Parameter(names = {"--witness-address"}, description = "witness-address") public String witnessAddress = ""; @@ -92,8 +100,8 @@ public class CommonParameter { "--storage-db-synchronous"}, description = "Storage db is synchronous or not.(true or false)") public String storageDbSynchronous = ""; - @Parameter(names = {"--contract-parse-enable"}, - description = "enable contract parses in java-tron or not.(true or false)") + @Parameter(names = {"--contract-parse-enable"}, description = "Switch for contract parses in " + + "java-tron. (default: true)") public String contractParseEnable = ""; @Parameter(names = {"--storage-index-directory"}, description = "Storage index directory") @@ -162,7 +170,8 @@ public class CommonParameter { public long nodeP2pPingInterval; @Getter @Setter - @Parameter(names = {"--save-internaltx"}) + @Parameter(names = {"--save-internaltx"}, description = "Save internal transactions generated " + + "during TVM execution, such as create, call, suicide and so on. (default: false)") public boolean saveInternalTx; @Getter @Setter @@ -342,12 +351,12 @@ public class CommonParameter { public long blockNumForEnergyLimit; @Getter @Setter - @Parameter(names = {"--es"}) + @Parameter(names = {"--es"}, description = "Start event subscribe server") public boolean eventSubscribe = false; @Getter @Setter public long trxExpirationTimeInMilliseconds; // (ms) - @Parameter(names = {"-v", "--version"}, description = "output code version", help = true) + @Parameter(names = {"-v", "--version"}, description = "Output code version", help = true) public boolean version; @Getter @Setter diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 16ede8cdbaa..029e89d6cd6 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -7,6 +7,8 @@ import static org.tron.core.config.Parameter.ChainConstant.MAX_ACTIVE_WITNESS_NUM; import com.beust.jcommander.JCommander; +import com.beust.jcommander.ParameterDescription; +import com.google.common.base.Strings; import com.typesafe.config.Config; import com.typesafe.config.ConfigObject; import io.grpc.internal.GrpcUtil; @@ -22,9 +24,13 @@ import java.nio.file.Paths; import java.text.ParseException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Properties; @@ -230,6 +236,95 @@ private static void printVersion() { JCommander.getConsole().println("Code : " + Version.VERSION_CODE); } + public static void printHelp(JCommander jCommander) { + List parameterDescriptionList = jCommander.getParameters(); + Map stringParameterDescriptionMap = new HashMap<>(); + for (ParameterDescription parameterDescription : parameterDescriptionList) { + String parameterName = parameterDescription.getParameterized().getName(); + stringParameterDescriptionMap.put(parameterName, parameterDescription); + } + + StringBuilder helpStr = new StringBuilder(); + helpStr.append("Name:\n\tFullNode - the java-tron command line interface\n"); + String programName = Strings.isNullOrEmpty(jCommander.getProgramName()) ? "FullNode.jar" : + jCommander.getProgramName(); + helpStr.append(String.format("%nUsage: java -jar %s [options] [seedNode ...]%n", + programName)); + helpStr.append(String.format("%nVERSION: %n%s-%s%n", Version.getVersion(), + getCommitIdAbbrev())); + + Map groupOptionListMap = Args.getOptionGroup(); + for (Map.Entry entry : groupOptionListMap.entrySet()) { + String group = entry.getKey(); + helpStr.append(String.format("%n%s OPTIONS:%n", group.toUpperCase())); + int optionMaxLength = Arrays.stream(entry.getValue()).mapToInt(p -> { + ParameterDescription tmpParameterDescription = stringParameterDescriptionMap.get(p); + if (tmpParameterDescription == null) { + return 1; + } + return tmpParameterDescription.getNames().length(); + }).max().orElse(1); + + for (String option : groupOptionListMap.get(group)) { + ParameterDescription parameterDescription = stringParameterDescriptionMap.get(option); + if (parameterDescription == null) { + logger.warn("Miss option:{}", option); + continue; + } + String tmpOptionDesc = String.format("%s\t\t\t%s%n", + Strings.padEnd(parameterDescription.getNames(), optionMaxLength, ' '), + upperFirst(parameterDescription.getDescription())); + helpStr.append(tmpOptionDesc); + } + } + JCommander.getConsole().println(helpStr.toString()); + } + + public static String upperFirst(String name) { + if (name.length() <= 1) { + return name; + } + name = name.substring(0, 1).toUpperCase() + name.substring(1); + return name; + } + + private static String getCommitIdAbbrev() { + Properties properties = new Properties(); + try { + InputStream in = Thread.currentThread() + .getContextClassLoader().getResourceAsStream("git.properties"); + properties.load(in); + } catch (IOException e) { + logger.warn("Load resource failed,git.properties {}", e.getMessage()); + } + return properties.getProperty("git.commit.id.abbrev"); + } + + private static Map getOptionGroup() { + String[] tronOption = new String[] {"version", "help", "shellConfFileName", "logbackPath", + "eventSubscribe"}; + String[] dbOption = new String[] {"outputDirectory"}; + String[] witnessOption = new String[] {"witness", "privateKey"}; + String[] vmOption = new String[] {"debug"}; + + Map optionGroupMap = new LinkedHashMap<>(); + optionGroupMap.put("tron", tronOption); + optionGroupMap.put("db", dbOption); + optionGroupMap.put("witness", witnessOption); + optionGroupMap.put("virtual machine", vmOption); + + for (String[] optionList : optionGroupMap.values()) { + for (String option : optionList) { + try { + CommonParameter.class.getField(option); + } catch (NoSuchFieldException e) { + logger.warn("NoSuchFieldException:{},{}", option, e.getMessage()); + } + } + } + return optionGroupMap; + } + /** * set parameters. */ diff --git a/framework/src/main/java/org/tron/program/FullNode.java b/framework/src/main/java/org/tron/program/FullNode.java index 03a0eef8e72..63c1edaaecf 100644 --- a/framework/src/main/java/org/tron/program/FullNode.java +++ b/framework/src/main/java/org/tron/program/FullNode.java @@ -2,6 +2,7 @@ import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.joran.JoranConfigurator; +import com.beust.jcommander.JCommander; import java.io.File; import lombok.extern.slf4j.Slf4j; import org.slf4j.LoggerFactory; @@ -58,7 +59,9 @@ public static void main(String[] args) { load(parameter.getLogbackPath()); if (parameter.isHelp()) { - logger.info("Here is the help message."); + JCommander jCommander = JCommander.newBuilder().addObject(Args.PARAMETER).build(); + jCommander.parse(args); + Args.printHelp(jCommander); return; } From 8be00f28cb24c815ef755403f7cccc574cbe6bee Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 25 Aug 2022 12:23:31 +0800 Subject: [PATCH 0218/1197] perf(db): optimize getOwner function --- .../org/tron/core/capsule/TransactionCapsule.java | 11 ++++++++++- .../main/java/org/tron/core/db/TransactionTrace.java | 2 +- framework/src/main/java/org/tron/core/db/Manager.java | 10 ++++------ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java index cd35bf4a253..1a6cd54c131 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -105,6 +105,15 @@ public class TransactionCapsule implements ProtoCapsule { @Getter @Setter private long order; + private byte[] ownerAddress; + + public byte[] getOwnerAddress() { + if (this.ownerAddress == null) { + this.ownerAddress = getOwnerAddress(); + } + return this.ownerAddress; + } + /** * constructor TransactionCapsule. @@ -544,7 +553,7 @@ public void addSign(byte[] privateKey, AccountStore accountStore) throws PermissionException, SignatureException, SignatureFormatException { Transaction.Contract contract = this.transaction.getRawData().getContract(0); int permissionId = contract.getPermissionId(); - byte[] owner = getOwner(contract); + byte[] owner = getOwnerAddress(); AccountCapsule account = accountStore.get(owner); if (account == null) { throw new PermissionException("Account is not exist!"); diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java index 6a74d6d015f..c1b5da5650e 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java @@ -224,7 +224,7 @@ public void pay() throws BalanceInsufficientException { long originEnergyLimit = 0; switch (trxType) { case TRX_CONTRACT_CREATION_TYPE: - callerAccount = TransactionCapsule.getOwner(trx.getInstance().getRawData().getContract(0)); + callerAccount = trx.getOwnerAddress(); originAccount = callerAccount; break; case TRX_CONTRACT_CALL_TYPE: diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 457bcda999d..5b9223e398d 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1063,8 +1063,7 @@ public List getVerifyTxs(BlockCapsule block) { pendingTransactions.forEach(capsule -> { String txId = Hex.toHexString(capsule.getTransactionId().getBytes()); if (isMultiSignTransaction(capsule.getInstance())) { - Contract contract = capsule.getInstance().getRawData().getContract(0); - String address = Hex.toHexString(TransactionCapsule.getOwner(contract)); + String address = Hex.toHexString(capsule.getOwnerAddress()); multiAddresses.add(address); } else { txIds.add(txId); @@ -1402,7 +1401,7 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block if (isMultiSignTransaction(trxCap.getInstance())) { - ownerAddressSet.add(ByteArray.toHexString(TransactionCapsule.getOwner(contract))); + ownerAddressSet.add(ByteArray.toHexString(trxCap.getOwnerAddress())); } if (Objects.nonNull(blockCap)) { @@ -1513,7 +1512,7 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { } //multi sign transaction Contract contract = trx.getInstance().getRawData().getContract(0); - byte[] owner = TransactionCapsule.getOwner(contract); + byte[] owner = trx.getOwnerAddress(); String ownerAddress = ByteArray.toHexString(owner); if (accountSet.contains(ownerAddress)) { continue; @@ -1560,8 +1559,7 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { } private void filterOwnerAddress(TransactionCapsule transactionCapsule, Set result) { - Contract contract = transactionCapsule.getInstance().getRawData().getContract(0); - byte[] owner = TransactionCapsule.getOwner(contract); + byte[] owner = transactionCapsule.getOwnerAddress(); String ownerAddress = ByteArray.toHexString(owner); if (ownerAddressSet.contains(ownerAddress)) { result.add(ownerAddress); From 8b75822cbc3b15d9e78ae3603584cf6766cabedc Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 25 Aug 2022 14:40:26 +0800 Subject: [PATCH 0219/1197] perf(db): optimize getOwner function --- .../src/main/java/org/tron/core/capsule/TransactionCapsule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java index 1a6cd54c131..644a0b2c35e 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -109,7 +109,7 @@ public class TransactionCapsule implements ProtoCapsule { public byte[] getOwnerAddress() { if (this.ownerAddress == null) { - this.ownerAddress = getOwnerAddress(); + this.ownerAddress = getOwner(this.transaction.getRawData().getContract(0)); } return this.ownerAddress; } From e162e38836801c1761a39fcc08250f5930c8ab90 Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 25 Aug 2022 15:58:27 +0800 Subject: [PATCH 0220/1197] feat(log): update log level 1. update Wallet log level --- framework/src/main/java/org/tron/core/Wallet.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index ac88a898ed9..ae04f249e1e 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -551,7 +551,7 @@ public GrpcAPI.Return broadcastTransaction(Transaction signedTransaction) { .setMessage(ByteString.copyFromUtf8("Contract execute error : " + e.getMessage())) .build(); } catch (AccountResourceInsufficientException e) { - logger.error(BROADCAST_TRANS_FAILED, txID, e.getMessage()); + logger.warn(BROADCAST_TRANS_FAILED, txID, e.getMessage()); return builder.setResult(false).setCode(response_code.BANDWITH_ERROR) .setMessage(ByteString.copyFromUtf8("Account resource insufficient error.")) .build(); @@ -561,17 +561,17 @@ public GrpcAPI.Return broadcastTransaction(Transaction signedTransaction) { .setMessage(ByteString.copyFromUtf8("Dup transaction.")) .build(); } catch (TaposException e) { - logger.error(BROADCAST_TRANS_FAILED, txID, e.getMessage()); + logger.warn(BROADCAST_TRANS_FAILED, txID, e.getMessage()); return builder.setResult(false).setCode(response_code.TAPOS_ERROR) .setMessage(ByteString.copyFromUtf8("Tapos check error.")) .build(); } catch (TooBigTransactionException e) { - logger.error(BROADCAST_TRANS_FAILED, txID, e.getMessage()); + logger.warn(BROADCAST_TRANS_FAILED, txID, e.getMessage()); return builder.setResult(false).setCode(response_code.TOO_BIG_TRANSACTION_ERROR) .setMessage(ByteString.copyFromUtf8("Transaction size is too big.")) .build(); } catch (TransactionExpirationException e) { - logger.error(BROADCAST_TRANS_FAILED, txID, e.getMessage()); + logger.warn(BROADCAST_TRANS_FAILED, txID, e.getMessage()); return builder.setResult(false).setCode(response_code.TRANSACTION_EXPIRATION_ERROR) .setMessage(ByteString.copyFromUtf8("Transaction expired")) .build(); From d73c2b8871921830be35ff45d65414424e35c66a Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 25 Aug 2022 16:27:40 +0800 Subject: [PATCH 0221/1197] refactor(net): optimize network module log --- .../org/tron/common/backup/BackupManager.java | 2 +- .../common/net/udp/handler/MessageHandler.java | 2 +- .../common/net/udp/handler/PacketDecoder.java | 2 +- .../tron/common/overlay/client/PeerClient.java | 4 ++-- .../common/overlay/discover/DiscoverServer.java | 4 ++-- .../common/overlay/discover/DiscoverTask.java | 2 +- .../common/overlay/discover/node/NodeManager.java | 4 ++-- .../tron/common/overlay/server/FastForward.java | 4 ++-- .../common/overlay/server/HandshakeHandler.java | 6 +++--- .../tron/common/overlay/server/MessageQueue.java | 2 +- .../overlay/server/TronChannelInitializer.java | 2 +- .../server/TrxProtobufVarint32FrameDecoder.java | 2 +- .../src/main/java/org/tron/core/db/Manager.java | 8 -------- .../java/org/tron/core/net/TronNetDelegate.java | 3 +-- .../java/org/tron/core/net/TronNetService.java | 6 ++++++ .../core/net/message/ChainInventoryMessage.java | 2 +- .../messagehandler/ChainInventoryMsgHandler.java | 6 +++++- .../messagehandler/FetchInvDataMsgHandler.java | 15 ++++++++------- .../net/messagehandler/PbftDataSyncHandler.java | 4 ++-- .../messagehandler/SyncBlockChainMsgHandler.java | 2 +- .../messagehandler/TransactionsMsgHandler.java | 11 +++++++++-- .../org/tron/core/net/peer/PeerStatusCheck.java | 2 +- .../tron/core/net/service/FetchBlockService.java | 12 ++++++++++-- .../org/tron/core/net/service/SyncService.java | 5 ++++- 24 files changed, 66 insertions(+), 46 deletions(-) diff --git a/framework/src/main/java/org/tron/common/backup/BackupManager.java b/framework/src/main/java/org/tron/common/backup/BackupManager.java index abbdb6d380b..4e1a3762a3d 100644 --- a/framework/src/main/java/org/tron/common/backup/BackupManager.java +++ b/framework/src/main/java/org/tron/common/backup/BackupManager.java @@ -105,7 +105,7 @@ public void init() { .accept(new UdpEvent(new KeepAliveMessage(status.equals(MASTER), priority), new InetSocketAddress(member, port)))); } catch (Throwable t) { - logger.error("Exception in send keep alive message:{}", t.getMessage()); + logger.error("Exception in send keep alive message:{}", t.getMessage(), t); } }, 1000, keepAliveInterval, TimeUnit.MILLISECONDS); } diff --git a/framework/src/main/java/org/tron/common/net/udp/handler/MessageHandler.java b/framework/src/main/java/org/tron/common/net/udp/handler/MessageHandler.java index 41897e2eebc..c48ccc5752d 100644 --- a/framework/src/main/java/org/tron/common/net/udp/handler/MessageHandler.java +++ b/framework/src/main/java/org/tron/common/net/udp/handler/MessageHandler.java @@ -78,7 +78,7 @@ public void channelReadComplete(ChannelHandlerContext ctx) { @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.info("exception caught, {} {}", ctx.channel().remoteAddress(), cause.getMessage()); + logger.info("Exception caught, {} {}", ctx.channel().remoteAddress(), cause.getMessage()); ctx.close(); } } diff --git a/framework/src/main/java/org/tron/common/net/udp/handler/PacketDecoder.java b/framework/src/main/java/org/tron/common/net/udp/handler/PacketDecoder.java index 48f369462b4..4859dcd04f6 100644 --- a/framework/src/main/java/org/tron/common/net/udp/handler/PacketDecoder.java +++ b/framework/src/main/java/org/tron/common/net/udp/handler/PacketDecoder.java @@ -38,7 +38,7 @@ public void decode(ChannelHandlerContext ctx, DatagramPacket packet, List= MAXSIZE) { logger - .error("UDP rcv bad packet, from {} length = {}", ctx.channel().remoteAddress(), length); + .warn("UDP rcv bad packet, from {} length = {}", ctx.channel().remoteAddress(), length); return; } byte[] encoded = new byte[length]; diff --git a/framework/src/main/java/org/tron/common/overlay/client/PeerClient.java b/framework/src/main/java/org/tron/common/overlay/client/PeerClient.java index bdd5eb7606e..0414e2088c9 100644 --- a/framework/src/main/java/org/tron/common/overlay/client/PeerClient.java +++ b/framework/src/main/java/org/tron/common/overlay/client/PeerClient.java @@ -55,7 +55,7 @@ public ChannelFuture connectAsync(NodeHandler nodeHandler, boolean discoveryMode return connectAsync(node.getHost(), node.getPort(), node.getHexId(), discoveryMode) .addListener((ChannelFutureListener) future -> { if (!future.isSuccess()) { - logger.warn("connect to {}:{} fail,cause:{}", node.getHost(), node.getPort(), + logger.warn("Connect to {}:{} fail,cause:{}", node.getHost(), node.getPort(), future.cause().getMessage()); nodeHandler.getNodeStatistics().nodeDisconnectedLocal(ReasonCode.CONNECT_FAIL); nodeHandler.getNodeStatistics().notifyDisconnect(); @@ -67,7 +67,7 @@ public ChannelFuture connectAsync(NodeHandler nodeHandler, boolean discoveryMode private ChannelFuture connectAsync(String host, int port, String remoteId, boolean discoveryMode) { - logger.info("connect peer {} {} {}", host, port, remoteId); + logger.info("Connect peer {} {} {}", host, port, remoteId); TronChannelInitializer tronChannelInitializer = ctx .getBean(TronChannelInitializer.class, remoteId); diff --git a/framework/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java b/framework/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java index 983be8543ef..ddb6b912e6b 100755 --- a/framework/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java +++ b/framework/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java @@ -127,7 +127,7 @@ public void close() { try { channel.close().await(10, TimeUnit.SECONDS); } catch (Exception e) { - logger.info("Closing discovery server failed.", e); + logger.warn("Closing discovery server failed.", e); } } @@ -135,7 +135,7 @@ public void close() { try { discoveryExecutor.close(); } catch (Exception e) { - logger.info("Closing discovery executor failed.", e); + logger.warn("Closing discovery executor failed.", e); } } } diff --git a/framework/src/main/java/org/tron/common/overlay/discover/DiscoverTask.java b/framework/src/main/java/org/tron/common/overlay/discover/DiscoverTask.java index c1fb444e95a..8f105b6ee89 100644 --- a/framework/src/main/java/org/tron/common/overlay/discover/DiscoverTask.java +++ b/framework/src/main/java/org/tron/common/overlay/discover/DiscoverTask.java @@ -40,7 +40,7 @@ public synchronized void discover(byte[] nodeId, int round, List prevTried tried.add(n); wait(50); } catch (Exception ex) { - logger.error("Unexpected Exception " + ex, ex); + logger.error("Unexpected Exception", ex); } } if (tried.size() == KademliaOptions.ALPHA) { diff --git a/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java b/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java index 5efb94a4386..58dd6103489 100644 --- a/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java +++ b/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java @@ -78,7 +78,7 @@ public NodeManager(ChainBaseManager chainBaseManager) { bootNodes.add(Node.instanceOf(boot)); } - logger.info("homeNode : {}", homeNode); + logger.info("Home node is {}", homeNode); table = new NodeTable(homeNode); @@ -307,7 +307,7 @@ public void close() { nodeManagerTasksTimer.cancel(); pongTimer.shutdownNow(); } catch (Exception e) { - logger.warn("close failed.", e); + logger.warn("Close failed.", e); } } diff --git a/framework/src/main/java/org/tron/common/overlay/server/FastForward.java b/framework/src/main/java/org/tron/common/overlay/server/FastForward.java index 32b25eed1e1..0f3892e19ef 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/FastForward.java +++ b/framework/src/main/java/org/tron/common/overlay/server/FastForward.java @@ -113,7 +113,7 @@ public boolean checkHelloMessage(HelloMessage message, Channel channel) { } if (!witnessScheduleStore.getActiveWitnesses().contains(msg.getAddress())) { - logger.error("HelloMessage from {}, {} is not a schedule witness.", + logger.warn("HelloMessage from {}, {} is not a schedule witness.", channel.getInetAddress(), ByteArray.toHexString(msg.getAddress().toByteArray())); return false; @@ -139,7 +139,7 @@ public boolean checkHelloMessage(HelloMessage message, Channel channel) { } return flag; } catch (Exception e) { - logger.error("Check hello message failed, msg: {}, {}", message, e); + logger.warn("Check hello message failed, msg: {}, {}", message, e); return false; } } diff --git a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java index 7bb195b2ca8..d17eb4f0b97 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java @@ -78,7 +78,7 @@ public class HandshakeHandler extends ByteToMessageDecoder { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { - logger.info("channel active, {}", ctx.channel().remoteAddress()); + logger.info("Channel active, {}", ctx.channel().remoteAddress()); channel.setChannelHandlerContext(ctx); if (remoteId.length == 64) { channel.initNode(remoteId, ((InetSocketAddress) ctx.channel().remoteAddress()).getPort()); @@ -93,7 +93,7 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List ou buffer.readBytes(encoded); P2pMessage msg = messageFactory.create(encoded); - logger.info("Handshake receive from {}, {}", ctx.channel().remoteAddress(), msg); + logger.info("Handshake receive from {}", ctx.channel().remoteAddress()); switch (msg.getType()) { case P2P_HELLO: @@ -134,7 +134,7 @@ protected void sendHelloMsg(ChannelHandlerContext ctx, long time) { Metrics.histogramObserve(MetricKeys.Histogram.TCP_BYTES, length, MetricLabels.Histogram.TRAFFIC_OUT); - logger.info("Handshake send to {}, {} ", ctx.channel().remoteAddress(), message); + logger.info("Handshake send to {}", ctx.channel().remoteAddress()); } private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { diff --git a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java index 2edf84c8e32..cbc679b9f07 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java +++ b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java @@ -85,7 +85,7 @@ public void activate(ChannelHandlerContext ctx) { Thread.currentThread().interrupt(); } catch (Exception e) { logger.error("Failed to send to {}, error info: {}", ctx.channel().remoteAddress(), - e.getMessage()); + e.getMessage(), e); } } }); diff --git a/framework/src/main/java/org/tron/common/overlay/server/TronChannelInitializer.java b/framework/src/main/java/org/tron/common/overlay/server/TronChannelInitializer.java index 4ffefd92ae2..f6732adadd5 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/TronChannelInitializer.java +++ b/framework/src/main/java/org/tron/common/overlay/server/TronChannelInitializer.java @@ -45,7 +45,7 @@ public void initChannel(NioSocketChannel ch) throws Exception { // be aware of channel closing ch.closeFuture().addListener((ChannelFutureListener) future -> { - logger.info("Close channel:" + channel); + logger.info("Close channel: {}", channel); if (!peerDiscoveryMode) { channelManager.notifyDisconnect(channel); } diff --git a/framework/src/main/java/org/tron/common/overlay/server/TrxProtobufVarint32FrameDecoder.java b/framework/src/main/java/org/tron/common/overlay/server/TrxProtobufVarint32FrameDecoder.java index 8be89a178fe..b6696200aff 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/TrxProtobufVarint32FrameDecoder.java +++ b/framework/src/main/java/org/tron/common/overlay/server/TrxProtobufVarint32FrameDecoder.java @@ -76,7 +76,7 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) t int preIndex = in.readerIndex(); int length = readRawVarint32(in); if (length >= maxMsgLength) { - logger.warn("recv a big msg, host : {}, msg length is : {}", ctx.channel().remoteAddress(), + logger.warn("Recv a big msg, host : {}, msg length is : {}", ctx.channel().remoteAddress(), length); in.clear(); channel.close(); diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 457bcda999d..8eb474ad145 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1809,14 +1809,6 @@ public void updateFork(BlockCapsule block) { } public long getSyncBeginNumber() { - logger.info("headNumber:" - + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber()); - logger.info( - "syncBeginNumber:" - + (chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() - - revokingStore.size())); - logger.info("solidBlockNumber:" - + chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum()); return chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() - revokingStore.size(); } diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index 69c7c8af61c..ee3e36df84c 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -220,7 +220,7 @@ public void processBlock(BlockCapsule block, boolean isSync) throws P2pException && dbManager.getLatestSolidityNumShutDown() == dbManager.getDynamicPropertiesStore() .getLatestBlockHeaderNumberFromDB()) { - logger.info("begin shutdown, currentBlockNum:{}, DbBlockNum:{} ,solidifiedBlockNum:{}.", + logger.info("Begin shutdown, currentBlockNum:{}, DbBlockNum:{} ,solidifiedBlockNum:{}.", dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber(), dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumberFromDB(), dbManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum()); @@ -278,7 +278,6 @@ public void processBlock(BlockCapsule block, boolean isSync) throws P2pException | ZksnarkException | EventBloomException e) { metricsService.failProcessBlock(block.getNum(), e.getMessage()); - logger.error("Process block failed, {}, reason: {}.", blockId.getString(), e.getMessage()); throw new P2pException(TypeEnum.BAD_BLOCK, e); } } diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 69d1bc0cebe..19962740f25 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -95,6 +95,7 @@ public void broadcast(Message msg) { } protected void onMessage(PeerConnection peer, TronMessage msg) { + long startTime = System.currentTimeMillis(); try { switch (msg.getType()) { case SYNC_BLOCK_CHAIN: @@ -123,6 +124,8 @@ protected void onMessage(PeerConnection peer, TronMessage msg) { } } catch (Exception e) { processException(peer, msg, e); + } finally { + logger.info("Message processing costs {} ms", System.currentTimeMillis() - startTime); } } @@ -149,6 +152,9 @@ private void processException(PeerConnection peer, TronMessage msg, Exception ex case UNLINK_BLOCK: code = ReasonCode.UNLINKABLE; break; + case DB_ITEM_NOT_FOUND: + code = ReasonCode.FETCH_FAIL; + break; default: code = ReasonCode.UNKNOWN; break; diff --git a/framework/src/main/java/org/tron/core/net/message/ChainInventoryMessage.java b/framework/src/main/java/org/tron/core/net/message/ChainInventoryMessage.java index 5b0a0398778..b38961d2e51 100644 --- a/framework/src/main/java/org/tron/core/net/message/ChainInventoryMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/ChainInventoryMessage.java @@ -50,7 +50,7 @@ public List getBlockIds() { .map(blockId -> new BlockId(blockId.getHash(), blockId.getNumber())) .collect(Collectors.toCollection(ArrayList::new)); } catch (Exception e) { - logger.info("breakPoint"); + logger.info("Failed to get blockIds of chain inventory message"); } return null; } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java index 500d33904be..4f8f04656b3 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java @@ -66,12 +66,16 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep synchronized (tronNetDelegate.getBlockLock()) { try { + StringBuilder blockNums = new StringBuilder(); while (!peer.getSyncBlockToFetch().isEmpty() && tronNetDelegate .containBlock(peer.getSyncBlockToFetch().peek())) { BlockId blockId = peer.getSyncBlockToFetch().pop(); peer.setBlockBothHave(blockId); + blockNums.append(blockId.getNum()).append(","); + } + if (blockNums.length() > 0) { logger.info("Block {} from {} is processed", - blockId.getString(), peer.getNode().getHost()); + blockNums.toString(), peer.getNode().getHost()); } } catch (NoSuchElementException e) { logger.warn("Process ChainInventoryMessage failed, peer {}, isDisconnect:{}", diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java index 8e9daa8ddc9..c719674966d 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java @@ -34,7 +34,6 @@ import org.tron.core.net.service.SyncService; import org.tron.protos.Protocol.Inventory.InventoryType; import org.tron.protos.Protocol.PBFTMessage.Raw; -import org.tron.protos.Protocol.ReasonCode; import org.tron.protos.Protocol.Transaction; @Slf4j(topic = "net") @@ -73,9 +72,8 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep try { message = tronNetDelegate.getData(hash, type); } catch (Exception e) { - logger.error("Fetch item {} failed. reason: {}", item, hash, e.getMessage()); - peer.disconnect(ReasonCode.FETCH_FAIL); - return; + throw new P2pException(TypeEnum.DB_ITEM_NOT_FOUND, + "Fetch item " + item + " failed. reason: " + e.getMessage()); } } @@ -145,7 +143,9 @@ private void check(PeerConnection peer, FetchInvDataMessage fetchInvDataMsg) thr .getCount(10); int maxCount = advService.getTrxCount().getCount(60); if (fetchCount > maxCount) { - logger.error("maxCount: " + maxCount + ", fetchCount: " + fetchCount); + logger.warn("Peer fetch too more transactions in 10 seconds, " + + "maxCount: {}, fetchCount: {}, peer: {}", + maxCount, fetchCount, peer.getInetAddress()); } } else { boolean isAdv = true; @@ -161,8 +161,9 @@ private void check(PeerConnection peer, FetchInvDataMessage fetchInvDataMsg) thr int outBlockCountIn1min = tronOutAdvBlock.getCount(60); int producedBlockIn2min = 120_000 / BLOCK_PRODUCED_INTERVAL; if (outBlockCountIn1min > producedBlockIn2min) { - logger.error("producedBlockIn2min: " + producedBlockIn2min + ", outBlockCountIn1min: " - + outBlockCountIn1min); + logger.warn("Peer fetch too more blocks in a minute, producedBlockIn2min: {}," + + " outBlockCountIn1min: {}, peer: {}", + producedBlockIn2min, outBlockCountIn1min, peer.getInetAddress()); } } else { if (!peer.isNeedSyncFromUs()) { diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java index 3525e53fe9b..5f107c9958d 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java @@ -92,11 +92,11 @@ private void processPBFTCommitMessage(PbftCommitMessage pbftCommitMessage) { if (raw.getDataType() == DataType.BLOCK && pbftSignDataStore.getBlockSignData(raw.getViewN()) == null) { pbftSignDataStore.putBlockSignData(raw.getViewN(), pbftCommitMessage.getPbftSignCapsule()); - logger.info("save the block {} pbft commit data", raw.getViewN()); + logger.info("Save the block {} pbft commit data", raw.getViewN()); } else if (raw.getDataType() == DataType.SRL && pbftSignDataStore.getSrSignData(raw.getEpoch()) == null) { pbftSignDataStore.putSrSignData(raw.getEpoch(), pbftCommitMessage.getPbftSignCapsule()); - logger.info("save the srl {} pbft commit data", raw.getEpoch()); + logger.info("Save the srl {} pbft commit data", raw.getEpoch()); } } catch (InvalidProtocolBufferException e) { logger.error("", e); diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java index 9f392b11e40..4d2271a09c3 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java @@ -38,7 +38,7 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep LinkedList blockIds = getLostBlockIds(summaryChainIds); if (blockIds.size() == 0) { - logger.error("Can't get lost block Ids."); + logger.warn("Can't get lost block Ids."); peer.disconnect(Protocol.ReasonCode.INCOMPATIBLE_CHAIN); return; } else if (blockIds.size() == 1) { diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java index 8fc23196cd9..279df9e0735 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java @@ -64,18 +64,25 @@ public boolean isBusy() { public void processMessage(PeerConnection peer, TronMessage msg) throws P2pException { TransactionsMessage transactionsMessage = (TransactionsMessage) msg; check(peer, transactionsMessage); + int smartContractQueueSize = 0; + int trxHandlePoolQueueSize = 0; for (Transaction trx : transactionsMessage.getTransactions().getTransactionsList()) { int type = trx.getRawData().getContract(0).getType().getNumber(); if (type == ContractType.TriggerSmartContract_VALUE || type == ContractType.CreateSmartContract_VALUE) { if (!smartContractQueue.offer(new TrxEvent(peer, new TransactionMessage(trx)))) { - logger.warn("Add smart contract failed, queueSize {}:{}", smartContractQueue.size(), - queue.size()); + smartContractQueueSize = smartContractQueue.size(); + trxHandlePoolQueueSize = queue.size(); } } else { trxHandlePool.submit(() -> handleTransaction(peer, new TransactionMessage(trx))); } } + + if (smartContractQueueSize != 0 || trxHandlePoolQueueSize != 0) { + logger.warn("Add smart contract failed, queueSize {}:{}", smartContractQueueSize, + trxHandlePoolQueueSize); + } } private void check(PeerConnection peer, TransactionsMessage msg) throws P2pException { diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java b/framework/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java index 6600238fcc5..706eee7b421 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java @@ -27,7 +27,7 @@ public void init() { try { statusCheck(); } catch (Exception e) { - logger.error("", e); + logger.error("Check peers status processing failed", e); } }, 5, 2, TimeUnit.SECONDS); } diff --git a/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java b/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java index cfad7242471..e24fea55cfc 100644 --- a/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java +++ b/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java @@ -58,8 +58,8 @@ public void init() { fetchBlockWorkerExecutor.scheduleWithFixedDelay(() -> { try { fetchBlockProcess(fetchBlockInfo); - } catch (Exception exception) { - logger.error("FetchBlockWorkerSchedule thread error. {}", exception.getMessage()); + } catch (Exception e) { + logger.error("FetchBlockWorkerSchedule thread error. {}", e.getMessage(), e); } }, 0L, 50L, TimeUnit.MILLISECONDS); } @@ -80,6 +80,10 @@ public void fetchBlock(List sha256HashList, PeerConnection peer) { fetchBlockInfo = new FetchBlockInfo(sha256Hash, peer, System.currentTimeMillis()); } }); + if (null != fetchBlockInfo) { + logger.info("Set fetchBlockInfo, block: {}, peer: {}, time: {}", fetchBlockInfo.getHash(), + fetchBlockInfo.getPeer().getInetAddress(), fetchBlockInfo.getTime()); + } } @@ -98,6 +102,8 @@ private void fetchBlockProcess(FetchBlockInfo fetchBlock) { if (System.currentTimeMillis() - chainBaseManager.getHeadBlockTimeStamp() >= BLOCK_FETCH_TIME_OUT_LIMIT) { this.fetchBlockInfo = null; + logger.info("Clear fetchBlockInfo due to {} ms past head block time", + BLOCK_FETCH_TIME_OUT_LIMIT); return; } Item item = new Item(fetchBlock.getHash(), InventoryType.BLOCK); @@ -120,6 +126,8 @@ private void fetchBlockProcess(FetchBlockInfo fetchBlock) { }); } else { if (System.currentTimeMillis() - fetchBlock.getTime() >= fetchTimeOut) { + logger.info("Clear fetchBlockInfo due to fetch block {} timeout {}ms", + fetchBlock.getHash(), fetchTimeOut); this.fetchBlockInfo = null; } } diff --git a/framework/src/main/java/org/tron/core/net/service/SyncService.java b/framework/src/main/java/org/tron/core/net/service/SyncService.java index 8e4d7a49b3d..7f158142750 100644 --- a/framework/src/main/java/org/tron/core/net/service/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/SyncService.java @@ -115,8 +115,11 @@ public void syncNext(PeerConnection peer) { LinkedList chainSummary = getBlockChainSummary(peer); peer.setSyncChainRequested(new Pair<>(chainSummary, System.currentTimeMillis())); peer.sendMessage(new SyncBlockChainMessage(chainSummary)); + } catch (P2pException p) { + logger.warn("Peer {} sync failed, reason: {}", peer.getInetAddress(), p.getMessage()); + peer.disconnect(ReasonCode.SYNC_FAIL); } catch (Exception e) { - logger.error("Peer {} sync failed, reason: {}", peer.getInetAddress(), e.getMessage()); + logger.error("Peer {} sync failed, reason: {}", peer.getInetAddress(), e.getMessage(), e); peer.disconnect(ReasonCode.SYNC_FAIL); } } From 9ddcdf1c302e3fc1fc2c32a2c0fa6cdb9e3c0082 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Fri, 26 Aug 2022 18:13:07 +0800 Subject: [PATCH 0222/1197] feat(jsonrpc): modify TransactionResult and BlockResult to support graph node --- .../services/jsonrpc/types/BlockResult.java | 27 ++++++++++------- .../jsonrpc/types/TransactionResult.java | 30 +++++++++++-------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/types/BlockResult.java b/framework/src/main/java/org/tron/core/services/jsonrpc/types/BlockResult.java index 4d4d506502d..69c885be2bd 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/types/BlockResult.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/types/BlockResult.java @@ -79,10 +79,10 @@ public class BlockResult { @Getter @Setter - private String baseFeePerGas = null; + private String baseFeePerGas = "0x0"; @Getter @Setter - private String mixHash = null; + private String mixHash = ByteArray.toJsonHex(new byte[32]); public BlockResult(Block block, boolean fullTx, Wallet wallet) { BlockCapsule blockCapsule = new BlockCapsule(block); @@ -91,18 +91,23 @@ public BlockResult(Block block, boolean fullTx, Wallet wallet) { hash = ByteArray.toJsonHex(blockCapsule.getBlockId().getBytes()); parentHash = ByteArray.toJsonHex(block.getBlockHeader().getRawData().getParentHash().toByteArray()); - nonce = null; // no value - sha3Uncles = null; // no value + nonce = ByteArray.toJsonHex(new byte[8]); // no value + sha3Uncles = ByteArray.toJsonHex(new byte[32]); // no value logsBloom = ByteArray.toJsonHex(new byte[256]); // no value transactionsRoot = ByteArray .toJsonHex(block.getBlockHeader().getRawData().getTxTrieRoot().toByteArray()); - stateRoot = ByteArray - .toJsonHex(block.getBlockHeader().getRawData().getAccountStateRoot().toByteArray()); - receiptsRoot = null; // no value - miner = ByteArray.toJsonHexAddress(blockCapsule.getWitnessAddress().toByteArray()); - difficulty = null; // no value - totalDifficulty = null; // no value - extraData = null; // no value + stateRoot = ByteArray.toJsonHex(new byte[32]); + receiptsRoot = ByteArray.toJsonHex(new byte[32]); // no value + + if (blockCapsule.getNum() == 0) { + miner = ByteArray.toJsonHex(new byte[20]); + } else { + miner = ByteArray.toJsonHexAddress(blockCapsule.getWitnessAddress().toByteArray()); + } + + difficulty = "0x0"; // no value + totalDifficulty = "0x0"; // no value + extraData = "0x"; // no value size = ByteArray.toJsonHex(block.getSerializedSize()); timestamp = ByteArray.toJsonHex(blockCapsule.getTimeStamp()); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java b/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java index 091b8091113..9f0ee285ccc 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java @@ -56,9 +56,9 @@ public class TransactionResult { private void parseSignature(Transaction tx) { if (tx.getSignatureCount() == 0) { - v = null; - r = null; - s = null; + v = ByteArray.toJsonHex(new byte[1]); + r = ByteArray.toJsonHex(new byte[32]); + s = ByteArray.toJsonHex(new byte[32]); return; } @@ -79,7 +79,7 @@ public TransactionResult(BlockCapsule blockCapsule, int index, Protocol.Transact long energyUsageTotal, long energyFee, Wallet wallet) { byte[] txId = new TransactionCapsule(tx).getTransactionId().getBytes(); hash = ByteArray.toJsonHex(txId); - nonce = null; // no value + nonce = ByteArray.toJsonHex(new byte[8]); // no value blockHash = ByteArray.toJsonHex(blockCapsule.getBlockId().getBytes()); blockNumber = ByteArray.toJsonHex(blockCapsule.getNum()); transactionIndex = ByteArray.toJsonHex(index); @@ -88,13 +88,19 @@ public TransactionResult(BlockCapsule blockCapsule, int index, Protocol.Transact Contract contract = tx.getRawData().getContract(0); byte[] fromByte = TransactionCapsule.getOwner(contract); byte[] toByte = getToAddress(tx); - from = ByteArray.toJsonHexAddress(fromByte); + + if (blockCapsule.getNum() == 0) { + from = ByteArray.toJsonHex(new byte[20]); + } else { + from = ByteArray.toJsonHexAddress(fromByte); + } + to = ByteArray.toJsonHexAddress(toByte); value = ByteArray.toJsonHex(getTransactionAmount(contract, hash, wallet)); } else { - from = null; - to = null; - value = null; + from = ByteArray.toJsonHex(new byte[20]); + to = ByteArray.toJsonHex(new byte[20]); + value = "0x0"; } gas = ByteArray.toJsonHex(energyUsageTotal); @@ -107,7 +113,7 @@ public TransactionResult(BlockCapsule blockCapsule, int index, Protocol.Transact public TransactionResult(Transaction tx, Wallet wallet) { byte[] txid = new TransactionCapsule(tx).getTransactionId().getBytes(); hash = ByteArray.toJsonHex(txid); - nonce = null; // no value + nonce = ByteArray.toJsonHex(new byte[8]); // no value blockHash = "0x"; blockNumber = "0x"; transactionIndex = "0x"; @@ -120,9 +126,9 @@ public TransactionResult(Transaction tx, Wallet wallet) { to = ByteArray.toJsonHexAddress(toByte); value = ByteArray.toJsonHex(getTransactionAmount(contract, hash, wallet)); } else { - from = null; - to = null; - value = null; + from = ByteArray.toJsonHex(new byte[20]); + to = ByteArray.toJsonHex(new byte[20]); + value = "0x0"; } gas = "0x0"; From e35689126bbac9f2601bc32397e95d65551696d3 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Mon, 29 Aug 2022 15:21:38 +0800 Subject: [PATCH 0223/1197] feat(unfreeze): add freezeV2 & unfreezeV2 related protocols --- protocol/src/main/protos/core/Tron.proto | 23 +++++++++++++++++++ .../core/contract/balance_contract.proto | 18 +++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 9d4af0a3151..3d1e2330ce8 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -214,6 +214,26 @@ message Account { Permission owner_permission = 31; Permission witness_permission = 32; repeated Permission active_permission = 33; + + // FREEZE_TYPE is extended ResourceCode of the common package. + enum FREEZE_TYPE { + BANDWIDTH = 0; + ENERGY = 1; + POWER = 2; + DELEGATED_BANDWIDTH = 3; + DELEGATED_ENERGY = 4; + } + message FreezeV2 { + FREEZE_TYPE type = 1; + int64 amount = 2; + } + message UnFreezeV2 { + FREEZE_TYPE type = 1; + int64 unfreeze_amount = 3; + int64 unfreeze_expire_time = 4; + } + repeated FreezeV2 frozenV2 = 34; + repeated UnFreezeV2 unfrozenV2 = 35; } message Key { @@ -346,6 +366,9 @@ message Transaction { ShieldedTransferContract = 51; MarketSellAssetContract = 52; MarketCancelOrderContract = 53; + FreezeBalanceV2Contract = 54; + UnfreezeBalanceV2Contract = 55; + WithdrawBalanceV2Contract = 56; } ContractType type = 1; google.protobuf.Any parameter = 2; diff --git a/protocol/src/main/protos/core/contract/balance_contract.proto b/protocol/src/main/protos/core/contract/balance_contract.proto index 293f62bed5b..795f17a9d0b 100644 --- a/protocol/src/main/protos/core/contract/balance_contract.proto +++ b/protocol/src/main/protos/core/contract/balance_contract.proto @@ -80,3 +80,21 @@ message AccountBalanceResponse { int64 balance = 1; BlockBalanceTrace.BlockIdentifier block_identifier = 2; } + +message FreezeBalanceV2Contract { + bytes owner_address = 1; + int64 frozen_balance = 2; + ResourceCode resource = 3; + bytes receiver_address = 4; +} + +message UnfreezeBalanceV2Contract { + bytes owner_address = 1; + int64 unfreeze_balance = 2; + ResourceCode resource = 3; + bytes receiver_address = 4; +} + +message WithdrawBalanceV2Contract { + bytes owner_address = 1; +} \ No newline at end of file From 280fb2cbad078e57b08929a09e82555914e40306 Mon Sep 17 00:00:00 2001 From: liukai Date: Mon, 29 Aug 2022 17:14:52 +0800 Subject: [PATCH 0224/1197] feat(docker): update docker workflow 1. remote docker-publish.yml --- .github/workflows/docker-publish.yml | 83 ---------------------------- 1 file changed, 83 deletions(-) delete mode 100644 .github/workflows/docker-publish.yml diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml deleted file mode 100644 index 051bed60aa5..00000000000 --- a/.github/workflows/docker-publish.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: Docker - -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. - -on: - push: - tags: - - "GreatVoyage-v*" - -env: - # Use docker.io for Docker Hub if empty - REGISTRY: docker.io - # github.repository as / - IMAGE_NAME: ${{ github.repository }} - - -jobs: - build: - - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - # This is used to complete the identity challenge - # with sigstore/fulcio when running outside of PRs. - id-token: write - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - # Install the cosign tool except on PR - # https://github.com/sigstore/cosign-installer - - name: Install cosign - if: github.event_name != 'pull_request' - uses: sigstore/cosign-installer@1e95c1de343b5b0c23352d6417ee3e48d5bcd422 - with: - cosign-release: 'v1.4.0' - - - # Workaround: https://github.com/docker/build-push-action/issues/461 - - name: Setup Docker buildx - uses: docker/setup-buildx-action@79abd3f86f79a9d68a23c75a09a9a85889262adf - - # Login against a Docker registry except on PR - # https://github.com/docker/login-action - - name: Log into registry ${{ env.REGISTRY }} - if: github.event_name != 'pull_request' - uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c - with: - registry: ${{ env.REGISTRY }} - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - # Extract metadata (tags, labels) for Docker - # https://github.com/docker/metadata-action - - name: Extract Docker metadata - id: meta - uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - - # Build and push Docker image with Buildx (don't push on PR) - # https://github.com/docker/build-push-action - - name: Build and push Docker image - id: build-and-push - uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc - with: - context: . - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - - - name: Sign the published Docker image - if: ${{ github.event_name != 'pull_request' }} - env: - COSIGN_EXPERIMENTAL: "true" - # This step uses the identity token to provision an ephemeral certificate - # against the sigstore community Fulcio instance. - run: cosign sign ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build-and-push.outputs.digest }} From 96b7df6cee110436474cc02dc723c7290d1441d3 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 30 Aug 2022 15:57:47 +0800 Subject: [PATCH 0225/1197] refactor(net): optimize network module log --- .../org/tron/common/backup/BackupManager.java | 2 +- .../common/overlay/message/HelloMessage.java | 6 +++++- .../tron/common/overlay/server/FastForward.java | 2 +- .../common/overlay/server/HandshakeHandler.java | 4 ++-- .../tron/common/overlay/server/MessageQueue.java | 3 +-- .../src/main/java/org/tron/core/db/Manager.java | 8 ++++++++ .../java/org/tron/core/net/TronNetDelegate.java | 1 + .../java/org/tron/core/net/TronNetService.java | 16 +++++++++++++++- .../messagehandler/ChainInventoryMsgHandler.java | 8 ++++---- .../messagehandler/TransactionsMsgHandler.java | 8 +++++--- .../tron/core/net/service/FetchBlockService.java | 2 +- .../org/tron/core/net/service/SyncService.java | 5 +---- 12 files changed, 45 insertions(+), 20 deletions(-) diff --git a/framework/src/main/java/org/tron/common/backup/BackupManager.java b/framework/src/main/java/org/tron/common/backup/BackupManager.java index 4e1a3762a3d..2b7c1a17f3e 100644 --- a/framework/src/main/java/org/tron/common/backup/BackupManager.java +++ b/framework/src/main/java/org/tron/common/backup/BackupManager.java @@ -105,7 +105,7 @@ public void init() { .accept(new UdpEvent(new KeepAliveMessage(status.equals(MASTER), priority), new InetSocketAddress(member, port)))); } catch (Throwable t) { - logger.error("Exception in send keep alive message:{}", t.getMessage(), t); + logger.error("Exception in send keep alive.", t); } }, 1000, keepAliveInterval, TimeUnit.MILLISECONDS); } diff --git a/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java b/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java index 3fec2284fa2..0498bf610ca 100755 --- a/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java +++ b/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java @@ -124,7 +124,11 @@ public Class getAnswerMessage() { @Override public String toString() { - return new StringBuilder().append(super.toString()).append(helloMessage.toString()).toString(); + return new StringBuilder().append(super.toString()).append(", ") + .append("from: ").append(getFrom()).append(", ") + .append("timestamp: ").append(getTimestamp()).append(", ") + .append("headBlockId: {").append(getHeadBlockId().getString()).append("}") + .toString(); } public Protocol.HelloMessage getInstance() { diff --git a/framework/src/main/java/org/tron/common/overlay/server/FastForward.java b/framework/src/main/java/org/tron/common/overlay/server/FastForward.java index 0f3892e19ef..0ca7949c181 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/FastForward.java +++ b/framework/src/main/java/org/tron/common/overlay/server/FastForward.java @@ -139,7 +139,7 @@ public boolean checkHelloMessage(HelloMessage message, Channel channel) { } return flag; } catch (Exception e) { - logger.warn("Check hello message failed, msg: {}, {}", message, e); + logger.warn("Check hello message failed, msg: {}, {}", message, channel.getInetAddress(), e); return false; } } diff --git a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java index d17eb4f0b97..b36c7f31b5d 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java @@ -93,7 +93,7 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List ou buffer.readBytes(encoded); P2pMessage msg = messageFactory.create(encoded); - logger.info("Handshake receive from {}", ctx.channel().remoteAddress()); + logger.info("Handshake receive from {}, {}", ctx.channel().remoteAddress(), msg); switch (msg.getType()) { case P2P_HELLO: @@ -134,7 +134,7 @@ protected void sendHelloMsg(ChannelHandlerContext ctx, long time) { Metrics.histogramObserve(MetricKeys.Histogram.TCP_BYTES, length, MetricLabels.Histogram.TRAFFIC_OUT); - logger.info("Handshake send to {}", ctx.channel().remoteAddress()); + logger.info("Handshake send to {}, {} ", ctx.channel().remoteAddress(), message); } private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { diff --git a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java index cbc679b9f07..2b52c525b94 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java +++ b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java @@ -84,8 +84,7 @@ public void activate(ChannelHandlerContext ctx) { logger.warn("Send message server interrupted."); Thread.currentThread().interrupt(); } catch (Exception e) { - logger.error("Failed to send to {}, error info: {}", ctx.channel().remoteAddress(), - e.getMessage(), e); + logger.error("Failed to send to {}.", ctx.channel().remoteAddress(), e); } } }); diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 8eb474ad145..457bcda999d 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1809,6 +1809,14 @@ public void updateFork(BlockCapsule block) { } public long getSyncBeginNumber() { + logger.info("headNumber:" + + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber()); + logger.info( + "syncBeginNumber:" + + (chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() + - revokingStore.size())); + logger.info("solidBlockNumber:" + + chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum()); return chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() - revokingStore.size(); } diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index ee3e36df84c..02b1862a1e4 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -278,6 +278,7 @@ public void processBlock(BlockCapsule block, boolean isSync) throws P2pException | ZksnarkException | EventBloomException e) { metricsService.failProcessBlock(block.getNum(), e.getMessage()); + logger.error("Process block failed, {}, reason: {}.", blockId.getString(), e.getMessage()); throw new P2pException(TypeEnum.BAD_BLOCK, e); } } diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 19962740f25..ffe32bcbbd8 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -65,6 +65,9 @@ public class TronNetService { @Autowired private FetchBlockService fetchBlockService; + private static final String TAG = "~"; + private static final int DURATION_STEP = 50; + public void start() { channelManager.init(); advService.init(); @@ -125,7 +128,9 @@ protected void onMessage(PeerConnection peer, TronMessage msg) { } catch (Exception e) { processException(peer, msg, e); } finally { - logger.info("Message processing costs {} ms", System.currentTimeMillis() - startTime); + long costs = System.currentTimeMillis() - startTime; + logger.info("Message processing costs {} ms, peer: {}, type: {}, time tag: {}", + costs, peer.getInetAddress(), msg.getType(), getTimeTag(costs)); } } @@ -169,4 +174,13 @@ private void processException(PeerConnection peer, TronMessage msg, Exception ex peer.disconnect(code); } + + private String getTimeTag(long duration) { + StringBuilder tag = new StringBuilder(TAG); + long tagCount = duration / DURATION_STEP; + for (; tagCount > 0; tagCount--) { + tag.append(TAG); + } + return tag.toString(); + } } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java index 4f8f04656b3..ab4d92b8707 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java @@ -66,16 +66,16 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep synchronized (tronNetDelegate.getBlockLock()) { try { - StringBuilder blockNums = new StringBuilder(); + BlockId lastBlockId = null; while (!peer.getSyncBlockToFetch().isEmpty() && tronNetDelegate .containBlock(peer.getSyncBlockToFetch().peek())) { BlockId blockId = peer.getSyncBlockToFetch().pop(); peer.setBlockBothHave(blockId); - blockNums.append(blockId.getNum()).append(","); + lastBlockId = blockId; } - if (blockNums.length() > 0) { + if (lastBlockId != null) { logger.info("Block {} from {} is processed", - blockNums.toString(), peer.getNode().getHost()); + lastBlockId.getString(), peer.getNode().getHost()); } } catch (NoSuchElementException e) { logger.warn("Process ChainInventoryMessage failed, peer {}, isDisconnect:{}", diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java index 279df9e0735..3c2bab191fa 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java @@ -66,6 +66,7 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep check(peer, transactionsMessage); int smartContractQueueSize = 0; int trxHandlePoolQueueSize = 0; + int dropSmartContractCount = 0; for (Transaction trx : transactionsMessage.getTransactions().getTransactionsList()) { int type = trx.getRawData().getContract(0).getType().getNumber(); if (type == ContractType.TriggerSmartContract_VALUE @@ -73,15 +74,16 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep if (!smartContractQueue.offer(new TrxEvent(peer, new TransactionMessage(trx)))) { smartContractQueueSize = smartContractQueue.size(); trxHandlePoolQueueSize = queue.size(); + dropSmartContractCount++; } } else { trxHandlePool.submit(() -> handleTransaction(peer, new TransactionMessage(trx))); } } - if (smartContractQueueSize != 0 || trxHandlePoolQueueSize != 0) { - logger.warn("Add smart contract failed, queueSize {}:{}", smartContractQueueSize, - trxHandlePoolQueueSize); + if (dropSmartContractCount > 0) { + logger.warn("Add smart contract failed, drop count: {}, queueSize {}:{}", + dropSmartContractCount, smartContractQueueSize, trxHandlePoolQueueSize); } } diff --git a/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java b/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java index e24fea55cfc..0571564ae42 100644 --- a/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java +++ b/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java @@ -59,7 +59,7 @@ public void init() { try { fetchBlockProcess(fetchBlockInfo); } catch (Exception e) { - logger.error("FetchBlockWorkerSchedule thread error. {}", e.getMessage(), e); + logger.error("FetchBlockWorkerSchedule thread error.", e); } }, 0L, 50L, TimeUnit.MILLISECONDS); } diff --git a/framework/src/main/java/org/tron/core/net/service/SyncService.java b/framework/src/main/java/org/tron/core/net/service/SyncService.java index 7f158142750..0a415162509 100644 --- a/framework/src/main/java/org/tron/core/net/service/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/SyncService.java @@ -115,11 +115,8 @@ public void syncNext(PeerConnection peer) { LinkedList chainSummary = getBlockChainSummary(peer); peer.setSyncChainRequested(new Pair<>(chainSummary, System.currentTimeMillis())); peer.sendMessage(new SyncBlockChainMessage(chainSummary)); - } catch (P2pException p) { - logger.warn("Peer {} sync failed, reason: {}", peer.getInetAddress(), p.getMessage()); - peer.disconnect(ReasonCode.SYNC_FAIL); } catch (Exception e) { - logger.error("Peer {} sync failed, reason: {}", peer.getInetAddress(), e.getMessage(), e); + logger.warn("Peer {} sync failed, reason: {}", peer.getInetAddress(), e.getMessage()); peer.disconnect(ReasonCode.SYNC_FAIL); } } From 7c0070941134d1dc941b1f0e3ca3e78d46af4c52 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 30 Aug 2022 16:22:13 +0800 Subject: [PATCH 0226/1197] fix(net): solve the problem that K-bucket nodes cannot be deleted --- .../overlay/discover/table/NodeEntry.java | 10 +-- .../overlay/discover/table/NodeTable.java | 70 ++++++++----------- .../overlay/discover/table/NodeEntryTest.java | 8 +-- .../overlay/discover/table/NodeTableTest.java | 3 + .../discover/table/TimeComparatorTest.java | 4 +- 5 files changed, 37 insertions(+), 58 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/discover/table/NodeEntry.java b/framework/src/main/java/org/tron/common/overlay/discover/table/NodeEntry.java index 2a6c3fb27e1..3e58e6ac093 100644 --- a/framework/src/main/java/org/tron/common/overlay/discover/table/NodeEntry.java +++ b/framework/src/main/java/org/tron/common/overlay/discover/table/NodeEntry.java @@ -31,14 +31,6 @@ public class NodeEntry { private int distance; private long modified; - public NodeEntry(Node n) { - this.node = n; - this.ownerId = n.getId(); - entryId = n.getHost(); - distance = distance(ownerId, n.getId()); - touch(); - } - public NodeEntry(byte[] ownerId, Node n) { this.node = n; this.ownerId = ownerId; @@ -115,6 +107,6 @@ public boolean equals(Object o) { @Override public int hashCode() { - return this.node.hashCode(); + return this.entryId.hashCode(); } } diff --git a/framework/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java b/framework/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java index 2ad121fb238..f5ba7615736 100644 --- a/framework/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java +++ b/framework/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java @@ -49,48 +49,37 @@ public final void initialize() { } public synchronized Node addNode(Node n) { - NodeEntry e = new NodeEntry(node.getId(), n); - if (nodes.contains(e)) { - nodes.forEach(nodeEntry -> { - if (nodeEntry.equals(e)) { - nodeEntry.touch(); - } - }); + NodeEntry entry = getNodeEntry(n); + if (entry != null) { + entry.touch(); return null; } + + NodeEntry e = new NodeEntry(node.getId(), n); NodeEntry lastSeen = buckets[getBucketId(e)].addNode(e); if (lastSeen != null) { return lastSeen.getNode(); } - if (!nodes.contains(e)) { - nodes.add(e); - } + nodes.add(e); return null; } public synchronized void dropNode(Node n) { - NodeEntry e = new NodeEntry(node.getId(), n); - buckets[getBucketId(e)].dropNode(e); - nodes.remove(e); + NodeEntry entry = getNodeEntry(n); + if (entry != null) { + nodes.remove(entry); + buckets[getBucketId(entry)].dropNode(entry); + } } public synchronized boolean contains(Node n) { - NodeEntry e = new NodeEntry(node.getId(), n); - for (NodeBucket b : buckets) { - if (b.getNodes().contains(e)) { - return true; - } - } - return false; + return getNodeEntry(n) != null; } public synchronized void touchNode(Node n) { - NodeEntry e = new NodeEntry(node.getId(), n); - for (NodeBucket b : buckets) { - if (b.getNodes().contains(e)) { - b.getNodes().get(b.getNodes().indexOf(e)).touch(); - break; - } + NodeEntry entry = getNodeEntry(n); + if (entry != null) { + entry.touch(); } } @@ -104,10 +93,6 @@ public int getBucketsCount() { return i; } - public synchronized NodeBucket[] getBuckets() { - return buckets; - } - public int getBucketId(NodeEntry e) { int id = e.getDistance() - 1; return id < 0 ? 0 : id; @@ -118,17 +103,9 @@ public synchronized int getNodesCount() { } public synchronized List getAllNodes() { - List nodes = new ArrayList<>(); - - for (NodeBucket b : buckets) { - for (NodeEntry e : b.getNodes()) { - if (!e.getNode().equals(node)) { - nodes.add(e); - } - } - } - - return nodes; + List list = new ArrayList<>(nodes); + list.remove(new NodeEntry(node.getId(), node)); + return list; } public synchronized List getClosestNodes(byte[] targetId) { @@ -145,4 +122,15 @@ public synchronized List getClosestNodes(byte[] targetId) { } return closestNodes; } + + private NodeEntry getNodeEntry(Node n) { + NodeEntry entry = null; + for (NodeEntry e: nodes) { + if (e.getNode().getHost().equals(n.getHost())) { + entry = e; + break; + } + } + return entry; + } } diff --git a/framework/src/test/java/org/tron/common/overlay/discover/table/NodeEntryTest.java b/framework/src/test/java/org/tron/common/overlay/discover/table/NodeEntryTest.java index 76d2baae9bc..1a47dfd0e7e 100644 --- a/framework/src/test/java/org/tron/common/overlay/discover/table/NodeEntryTest.java +++ b/framework/src/test/java/org/tron/common/overlay/discover/table/NodeEntryTest.java @@ -9,20 +9,16 @@ public class NodeEntryTest { @Test public void test() throws InterruptedException { Node node1 = Node.instanceOf("127.0.0.1:10001"); - NodeEntry nodeEntry = new NodeEntry(node1); - int distance = nodeEntry.getDistance(); - Assert.assertEquals(-256, distance); + NodeEntry nodeEntry = new NodeEntry(Node.getNodeId(), node1); long lastModified = nodeEntry.getModified(); - //System.out.println(lastModified); Thread.sleep(1); nodeEntry.touch(); long nowModified = nodeEntry.getModified(); - //System.out.println(nowModified); Assert.assertNotEquals(lastModified, nowModified); Node node2 = Node.instanceOf("127.0.0.1:10002"); - NodeEntry nodeEntry2 = new NodeEntry(node2); + NodeEntry nodeEntry2 = new NodeEntry(Node.getNodeId(), node2); boolean isDif = nodeEntry.equals(nodeEntry2); Assert.assertTrue(isDif); } diff --git a/framework/src/test/java/org/tron/common/overlay/discover/table/NodeTableTest.java b/framework/src/test/java/org/tron/common/overlay/discover/table/NodeTableTest.java index ab0062f5d82..07d52849092 100644 --- a/framework/src/test/java/org/tron/common/overlay/discover/table/NodeTableTest.java +++ b/framework/src/test/java/org/tron/common/overlay/discover/table/NodeTableTest.java @@ -133,6 +133,9 @@ public void dropNodeTest() { Assert.assertTrue(nodeTable.contains(node)); nodeTable.dropNode(node); Assert.assertTrue(!nodeTable.contains(node)); + nodeTable.addNode(node); + nodeTable.dropNode(new Node(ids.get(1), ips[0], 10000, 10000)); + Assert.assertTrue(!nodeTable.contains(node)); } @Test diff --git a/framework/src/test/java/org/tron/common/overlay/discover/table/TimeComparatorTest.java b/framework/src/test/java/org/tron/common/overlay/discover/table/TimeComparatorTest.java index 616ec29b772..b1c3a82f50e 100644 --- a/framework/src/test/java/org/tron/common/overlay/discover/table/TimeComparatorTest.java +++ b/framework/src/test/java/org/tron/common/overlay/discover/table/TimeComparatorTest.java @@ -9,10 +9,10 @@ public class TimeComparatorTest { @Test public void test() throws InterruptedException { Node node1 = Node.instanceOf("127.0.0.1:10001"); - NodeEntry ne1 = new NodeEntry(node1); + NodeEntry ne1 = new NodeEntry(Node.getNodeId(), node1); Thread.sleep(1); Node node2 = Node.instanceOf("127.0.0.1:10002"); - NodeEntry ne2 = new NodeEntry(node2); + NodeEntry ne2 = new NodeEntry(Node.getNodeId(), node2); TimeComparator tc = new TimeComparator(); int result = tc.compare(ne1, ne2); Assert.assertEquals(1, result); From 6c2a5d3cf10694bb29d0a6ebd568d68241b603cb Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Tue, 30 Aug 2022 17:10:49 +0800 Subject: [PATCH 0227/1197] feat: modify second param of eth_call as Object --- .../core/services/jsonrpc/TronJsonRpc.java | 2 +- .../services/jsonrpc/TronJsonRpcImpl.java | 50 ++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpc.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpc.java index caf0292a35c..52a3a2380d1 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpc.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpc.java @@ -152,7 +152,7 @@ TransactionResult getTransactionByBlockNumberAndIndex(String blockNumOrTag, Stri @JsonRpcError(exception = JsonRpcInvalidParamsException.class, code = -32602, data = "{}"), @JsonRpcError(exception = JsonRpcInternalException.class, code = -32000, data = "{}"), }) - String getCall(CallArguments transactionCall, String blockNumOrTag) + String getCall(CallArguments transactionCall, Object blockNumOrTag) throws JsonRpcInvalidParamsException, JsonRpcInvalidRequestException, JsonRpcInternalException; diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 82568f09acd..c9e7534184b 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -14,6 +14,7 @@ import com.google.protobuf.ByteString; import com.google.protobuf.GeneratedMessageV3; import java.util.Arrays; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -134,6 +135,8 @@ public enum RequestSource { private static final String TAG_NOT_SUPPORT_ERROR = "TAG [earliest | pending] not supported"; private static final String QUANTITY_NOT_SUPPORT_ERROR = "QUANTITY not supported, just support TAG as latest"; + private static final String NO_BLOCK_HEADER = "header not found"; + private static final String NO_BLOCK_HEADER_BY_HASH = "header for hash not found"; private static final String ERROR_SELECTOR = "08c379a0"; // Function selector for Error(string) /** @@ -716,9 +719,54 @@ public TransactionReceipt getTransactionReceipt(String txId) } @Override - public String getCall(CallArguments transactionCall, String blockNumOrTag) + public String getCall(CallArguments transactionCall, Object blockParamObj) throws JsonRpcInvalidParamsException, JsonRpcInvalidRequestException, JsonRpcInternalException { + + String blockNumOrTag; + if (blockParamObj instanceof HashMap) { + HashMap paramMap; + paramMap = (HashMap) blockParamObj; + + if (paramMap.containsKey("blockNumber")) { + try { + blockNumOrTag = paramMap.get("blockNumber"); + } catch (Exception e) { + throw new JsonRpcInvalidRequestException(JSON_ERROR); + } + + long blockNumber; + try { + blockNumber = ByteArray.hexToBigInteger(blockNumOrTag).longValue(); + } catch (Exception e) { + throw new JsonRpcInvalidParamsException(BLOCK_NUM_ERROR); + } + + if (wallet.getBlockByNum(blockNumber) == null) { + throw new JsonRpcInternalException(NO_BLOCK_HEADER); + } + + } else if (paramMap.containsKey("blockHash")) { + try { + blockNumOrTag = paramMap.get("blockHash"); + } catch (Exception e) { + throw new JsonRpcInvalidRequestException(JSON_ERROR); + } + + if (getBlockByJsonHash(blockNumOrTag) == null) { + throw new JsonRpcInternalException(NO_BLOCK_HEADER_BY_HASH); + } + } else { + throw new JsonRpcInvalidRequestException(JSON_ERROR); + } + + blockNumOrTag = LATEST_STR; + } else if (blockParamObj instanceof String) { + blockNumOrTag = (String) blockParamObj; + } else { + throw new JsonRpcInvalidRequestException(JSON_ERROR); + } + if (EARLIEST_STR.equalsIgnoreCase(blockNumOrTag) || PENDING_STR.equalsIgnoreCase(blockNumOrTag)) { throw new JsonRpcInvalidParamsException(TAG_NOT_SUPPORT_ERROR); From 01a428f4c30da1a82c7f6b84b5696d62470efa46 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 30 Aug 2022 18:49:10 +0800 Subject: [PATCH 0228/1197] perf(net): remove the unused field 'ownerId' --- .../org/tron/common/overlay/discover/table/NodeEntry.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/discover/table/NodeEntry.java b/framework/src/main/java/org/tron/common/overlay/discover/table/NodeEntry.java index 3e58e6ac093..4d83f58734d 100644 --- a/framework/src/main/java/org/tron/common/overlay/discover/table/NodeEntry.java +++ b/framework/src/main/java/org/tron/common/overlay/discover/table/NodeEntry.java @@ -20,12 +20,7 @@ import org.tron.common.overlay.discover.node.Node; -/** - * Created by kest on 5/25/15. - */ public class NodeEntry { - - private byte[] ownerId; private Node node; private String entryId; private int distance; @@ -33,7 +28,6 @@ public class NodeEntry { public NodeEntry(byte[] ownerId, Node n) { this.node = n; - this.ownerId = ownerId; entryId = n.getHost(); distance = distance(ownerId, n.getId()); touch(); From 4186b8f0245436aa0d7a74d2604a707286c44533 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Wed, 31 Aug 2022 11:32:38 +0800 Subject: [PATCH 0229/1197] feat: update block.timestamp from millis to second --- .../java/org/tron/core/services/jsonrpc/types/BlockResult.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/types/BlockResult.java b/framework/src/main/java/org/tron/core/services/jsonrpc/types/BlockResult.java index 69c885be2bd..1217bc59ba6 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/types/BlockResult.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/types/BlockResult.java @@ -109,7 +109,7 @@ public BlockResult(Block block, boolean fullTx, Wallet wallet) { totalDifficulty = "0x0"; // no value extraData = "0x"; // no value size = ByteArray.toJsonHex(block.getSerializedSize()); - timestamp = ByteArray.toJsonHex(blockCapsule.getTimeStamp()); + timestamp = ByteArray.toJsonHex(blockCapsule.getTimeStamp() / 1000); long gasUsedInBlock = 0; long gasLimitInBlock = 0; From 046eab50ddbacf74b96e16edbc895b605e8738da Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 23 Aug 2022 14:21:31 +0800 Subject: [PATCH 0230/1197] feat(liteFullNodeTool): optimize liteFullNodeTool 1. disable light node data to split history data 2. disable history data splitted from light node data to merge 3. disable split if block is less than 65536 4. add latest 65536 blocks and related transactions into snapshot data 5. remove light node minimum dbs check --- .../tool/litefullnode/LiteFullNodeTool.java | 222 +++++++++--------- .../tron/program/LiteFullNodeToolTest.java | 111 +++++---- 2 files changed, 165 insertions(+), 168 deletions(-) diff --git a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java index 037760e201a..4f2f3d46ec0 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java @@ -4,6 +4,7 @@ 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; @@ -16,9 +17,9 @@ 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.LongStream; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.rocksdb.RocksDBException; @@ -47,50 +48,23 @@ public class LiteFullNodeTool { 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 long VM_NEED_RECENT_BLKS = 256; + private static long RECENT_BLKS = 65536; private static final String BLOCK_DB_NAME = "block"; private static final String BLOCK_INDEX_DB_NAME = "block-index"; - private static final String TRANS_CACHE_DB_NAME = "trans-cache"; + private static final String TRANS_DB_NAME = "trans"; private static final String COMMON_DB_NAME = "common"; + private static final String TRANSACTION_RET_DB_NAME = "transactionRetStore"; + private static final String TRANSACTION_HISTORY_DB_NAME = "transactionHistoryStore"; private static final String DIR_FORMAT_STRING = "%s%s%s"; private static List archiveDbs = Arrays.asList( BLOCK_DB_NAME, BLOCK_INDEX_DB_NAME, - "trans", - "transactionRetStore", - "transactionHistoryStore"); - private static List minimumDbsForLiteNode = Arrays.asList( - "DelegatedResource", - "DelegatedResourceAccountIndex", - "IncrementalMerkleTree", - "account", - "account-index", - "accountTrie", - "accountid-index", - "asset-issue", - "asset-issue-v2", - //"block_KDB", - "code", - //"common", - "contract", - "delegation", - "exchange", - "exchange-v2", - //"nullifier", - "properties", - "proposal", - "recent-block", - //"recent-transaction", - "storage-row", - //TRANS_CACHE_DB_NAME, - //"tree-block-index", - "votes", - "witness", - "witness_schedule" - ); + TRANS_DB_NAME, + TRANSACTION_RET_DB_NAME, + TRANSACTION_HISTORY_DB_NAME); /** * Create the snapshot dataset. @@ -104,13 +78,12 @@ public void generateSnapshot(String sourceDir, String snapshotDir) { 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 and latestBlock - fillSnapshotBlockDb(sourceDir, snapshotDir); - // create tran-cache if not exist, for compatible - checkTranCacheStore(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()); @@ -132,6 +105,11 @@ public void generateHistory(String sourceDir, String historyDir) { 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); @@ -155,6 +133,12 @@ public void completeHistoryData(String historyDir, String databaseDir) { 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); @@ -183,11 +167,6 @@ private List getSnapshotDbs(String sourceDir) { .filter(File::isDirectory) .filter(dir -> !archiveDbs.contains(dir.getName())) .forEach(dir -> snapshotDbs.add(dir.getName())); - for (String dir : minimumDbsForLiteNode) { - if (!snapshotDbs.contains(dir)) { - throw new RuntimeException("databaseDir does not contain all the necessary databases"); - } - } return snapshotDbs; } @@ -270,16 +249,16 @@ private long getLatestBlockHeaderNum(String databaseDir) throws IOException, Roc } /** - * Syncing block from peer that needs latest block and genesis block, - * also VM need recent blocks. + * recent blocks, trans and genesis block. */ - private void fillSnapshotBlockDb(String sourceDir, String snapshotDir) + private void fillSnapshotBlockAndTransDb(String sourceDir, String snapshotDir) throws IOException, RocksDBException { - logger.info("-- begin to fill latest block and genesis block to snapshot"); + 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)); @@ -287,71 +266,33 @@ private void fillSnapshotBlockDb(String sourceDir, String snapshotDir) destBlockDb.put(genesisBlockID, sourceBlockDb.get(genesisBlockID)); long latestBlockNum = getLatestBlockHeaderNum(sourceDir); - long startIndex = latestBlockNum > VM_NEED_RECENT_BLKS - ? latestBlockNum - VM_NEED_RECENT_BLKS : 0; - // put the recent blocks in snapshot, VM needs recent 256 blocks. - LongStream.rangeClosed(startIndex, latestBlockNum).forEach( - blockNum -> { - byte[] blockId = null; - byte[] block = null; - try { - blockId = getDataFromSourceDB(sourceDir, BLOCK_INDEX_DB_NAME, - Longs.toByteArray(blockNum)); - block = getDataFromSourceDB(sourceDir, BLOCK_DB_NAME, blockId); - } catch (IOException | RocksDBException e) { - throw new RuntimeException(e.getMessage()); - } - // put recent blocks index into snapshot - destBlockIndexDb.put(ByteArray.fromLong(blockNum), blockId); - // put latest blocks into snapshot - destBlockDb.put(blockId, block); - }); + 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()); + } + } DBInterface destCommonDb = DbTool.getDB(snapshotDir, COMMON_DB_NAME); destCommonDb.put(DB_KEY_NODE_TYPE, ByteArray.fromInt(Constant.NODE_TYPE_LIGHT_NODE)); destCommonDb.put(DB_KEY_LOWEST_BLOCK_NUM, ByteArray.fromLong(startIndex)); } - private void checkTranCacheStore(String sourceDir, String snapshotDir) - throws IOException, RocksDBException { - logger.info("-- create trans-cache db if not exists."); - if (FileUtil.isExists(String.format(DIR_FORMAT_STRING, snapshotDir, - File.separator, TRANS_CACHE_DB_NAME))) { - return; - } - // fullnode is old version, create trans-cache database - DBInterface recentBlockDb = DbTool.getDB(snapshotDir, "recent-block"); - DBInterface transCacheDb = DbTool.getDB(snapshotDir, TRANS_CACHE_DB_NAME); - long headNum = getLatestBlockHeaderNum(sourceDir); - long recentBlockCount = recentBlockDb.size(); - - LongStream.rangeClosed(headNum - recentBlockCount + 1, headNum).forEach( - blockNum -> { - byte[] blockId = null; - byte[] block = null; - try { - blockId = getDataFromSourceDB(sourceDir, BLOCK_INDEX_DB_NAME, - Longs.toByteArray(blockNum)); - block = getDataFromSourceDB(sourceDir, BLOCK_DB_NAME, blockId); - } catch (IOException | RocksDBException e) { - throw new RuntimeException(e.getMessage()); - } - BlockCapsule blockCapsule = null; - try { - blockCapsule = new BlockCapsule(block); - } catch (BadItemException e) { - throw new RuntimeException("construct block failed, num: " + blockNum); - } - if (blockCapsule.getTransactions().isEmpty()) { - return; - } - blockCapsule.getTransactions().stream() - .map(tc -> tc.getTransactionId().getBytes()) - .map(bytes -> Maps.immutableEntry(bytes, Longs.toByteArray(blockNum))) - .forEach(e -> transCacheDb.put(e.getKey(), e.getValue())); - }); - } - private byte[] getGenesisBlockHash(String parentDir) throws IOException, RocksDBException { long genesisBlockNum = 0L; DBInterface blockIndexDb = DbTool.getDB(parentDir, BLOCK_INDEX_DB_NAME); @@ -424,8 +365,8 @@ private void trimHistory(String databaseDir, BlockNumInfo blockNumInfo) 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"); - DBInterface tranRetDb = DbTool.getDB(databaseDir, "transactionRetStore"); + 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)); @@ -460,12 +401,15 @@ private void mergeBak2Database(String databaseDir) throws IOException, RocksDBEx private byte[] getDataFromSourceDB(String sourceDir, String dbName, byte[] key) throws IOException, RocksDBException { DBInterface sourceDb = DbTool.getDB(sourceDir, dbName); - DBInterface checkpointDb = DbTool.getDB(sourceDir, "tmp"); - byte[] value = sourceDb.get(key); - if (isEmptyBytes(value)) { - byte[] valueFromTmp = checkpointDb.get(Bytes.concat(simpleEncode(dbName), key)); + 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); + ? null : Arrays.copyOfRange(valueFromTmp, 1, valueFromTmp.length); } if (isEmptyBytes(value)) { throw new RuntimeException(String.format("data not found in store, dbName: %s, key: %s", @@ -489,8 +433,7 @@ private static boolean isEmptyBytes(byte[] b) { private void deleteSnapshotFlag(String databaseDir) throws IOException, RocksDBException { logger.info("-- delete the info file."); Files.delete(Paths.get(databaseDir, INFO_FILE_NAME)); - DBInterface destBlockIndexDb = DbTool.getDB(databaseDir, BLOCK_INDEX_DB_NAME); - if (destBlockIndexDb.get(ByteArray.fromLong(1)) != null) { + if (!isLite(databaseDir)) { DBInterface destCommonDb = DbTool.getDB(databaseDir, COMMON_DB_NAME); destCommonDb.delete(DB_KEY_NODE_TYPE); destCommonDb.delete(DB_KEY_LOWEST_BLOCK_NUM); @@ -500,6 +443,53 @@ private void deleteSnapshotFlag(String databaseDir) throws IOException, RocksDBE } + private void hasEnoughBlock(String sourceDir) throws RocksDBException, IOException { + // check latest + long latest = getLatestBlockHeaderNum(sourceDir); + // check first, not 0; + long first = 0; + DBInterface sourceBlockIndexDb = DbTool.getDB(sourceDir, BLOCK_INDEX_DB_NAME); + DBIterator iterator = sourceBlockIndexDb.iterator(); + iterator.seekToFirst(); + if (iterator.hasNext()) { + iterator.next(); + if (iterator.hasNext()) { + first = Longs.fromByteArray(iterator.getKey()); + } + } + + if (latest - first + 1 < RECENT_BLKS) { + throw new NoSuchElementException( + String.format("At least %d blocks in block store, actual latestBlock:%d, firstBlock:%d.", + RECENT_BLKS, latest, first)); + } + } + + private boolean isLite(String databaseDir) throws RocksDBException, IOException { + DBInterface sourceDb = DbTool.getDB(databaseDir, BLOCK_INDEX_DB_NAME); + DBInterface checkpointDb = DbTool.getDB(databaseDir, CHECKPOINT_DB); + byte[] key = ByteArray.fromLong(1); + byte[] valueFromTmp = checkpointDb.get(Bytes.concat(simpleEncode(BLOCK_INDEX_DB_NAME), key)); + byte[] value; + if (isEmptyBytes(valueFromTmp)) { + value = sourceDb.get(key); + } else { + value = valueFromTmp.length == 1 + ? null : Arrays.copyOfRange(valueFromTmp, 1, valueFromTmp.length); + } + return isEmptyBytes(value); + } + + @VisibleForTesting + public static void setRecentBlks(long recentBlks) { + RECENT_BLKS = recentBlks; + } + + @VisibleForTesting + public static void reSetRecentBlks() { + RECENT_BLKS = 65536; + } + private void run(Args argv) { if (StringUtils.isBlank(argv.fnDataPath) || StringUtils.isBlank(argv.datasetPath)) { throw new ParameterException("fnDataPath or datasetPath can't be null"); diff --git a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java index 174c708a7c7..f3dcd448ed2 100644 --- a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java +++ b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java @@ -6,15 +6,15 @@ import java.io.File; import java.math.BigInteger; import java.nio.file.Paths; +import org.junit.After; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.tron.api.DatabaseGrpc; import org.tron.api.GrpcAPI; import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; @@ -37,12 +37,7 @@ public class LiteFullNodeToolTest { private static final Logger logger = LoggerFactory.getLogger("Test"); private TronApplicationContext context; - private ManagedChannel channelFull = null; private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private DatabaseGrpc.DatabaseBlockingStub databaseBlockingStub = null; - private RpcApiService rpcApiService; - private RpcApiServiceOnSolidity rpcApiServiceOnSolidity; private Application appTest; private String databaseDir; @@ -50,38 +45,40 @@ public class LiteFullNodeToolTest { @Rule public ExpectedException thrown = ExpectedException.none(); + + private static final String DB_PATH = "output_lite_fn"; + /** * init logic. */ public void startApp() { context = new TronApplicationContext(DefaultConfig.class); appTest = ApplicationFactory.create(context); - rpcApiService = context.getBean(RpcApiService.class); - rpcApiServiceOnSolidity = context.getBean(RpcApiServiceOnSolidity.class); - appTest.addService(rpcApiService); - appTest.addService(rpcApiServiceOnSolidity); + appTest.addService(context.getBean(RpcApiService.class)); + appTest.addService(context.getBean(RpcApiServiceOnSolidity.class)); appTest.initServices(Args.getInstance()); appTest.startServices(); appTest.startup(); String fullnode = String.format("%s:%d", "127.0.0.1", Args.getInstance().getRpcPort()); - channelFull = ManagedChannelBuilder.forTarget(fullnode) + ManagedChannel channelFull = ManagedChannelBuilder.forTarget(fullnode) .usePlaintext(true) .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelFull); - databaseBlockingStub = DatabaseGrpc.newBlockingStub(channelFull); } /** * Delete the database when exit. */ - public static void destory(String dbPath) { - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); + 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."); + } } } @@ -94,84 +91,94 @@ public void shutdown() { context.destroy(); } - @Test - public void testToolsWithLevelDB() { - String dbPath = "output_lite_fn_leveldb_test"; - Args.setParam(new String[]{"-d", dbPath, "-w"}, "config-localtest.conf"); + @Before + public void init() { + destroy(DB_PATH); // delete if prev failed + Args.setParam(new String[]{"-d", DB_PATH, "-w"}, "config-localtest.conf"); // allow account root Args.getInstance().setAllowAccountStateRoot(1); databaseDir = Args.getInstance().getStorage().getDbDirectory(); - testTools("LEVELDB", dbPath); - destory(dbPath); + // init dbBackupConfig to avoid NPE + Args.getInstance().dbBackupConfig = DbBackupConfig.getInstance(); + } + + @After + public void clear() { + destroy(DB_PATH); + Args.clearParam(); + } + + @Test + public void testToolsWithLevelDB() { + logger.info("testToolsWithLevelDB start"); + testTools("LEVELDB"); + } @Test public void testToolsWithRocksDB() { - String dbPath = "output_lite_fn_rocksdb_test"; - Args.setParam(new String[]{"-d", dbPath, "-w"}, "config-localtest.conf"); - // allow account root - Args.getInstance().setAllowAccountStateRoot(1); - databaseDir = Args.getInstance().getStorage().getDbDirectory(); - // init dbBackupConfig to avoid NPE - Args.getInstance().dbBackupConfig = DbBackupConfig.getInstance(); - testTools("ROCKSDB", dbPath); - destory(dbPath); + logger.info("testToolsWithRocksDB start"); + testTools("ROCKSDB"); } - private void testTools(String dbType, String dbPath) { + private void testTools(String dbType) { final String[] argsForSnapshot = new String[]{"-o", "split", "-t", "snapshot", "--fn-data-path", - dbPath + File.separator + databaseDir, "--dataset-path", dbPath}; + DB_PATH + File.separator + databaseDir, "--dataset-path", + DB_PATH}; final String[] argsForHistory = new String[]{"-o", "split", "-t", "history", "--fn-data-path", - dbPath + File.separator + databaseDir, "--dataset-path", dbPath}; + DB_PATH + File.separator + databaseDir, "--dataset-path", + DB_PATH}; final String[] argsForMerge = - new String[]{"-o", "merge", "--fn-data-path", dbPath + File.separator + databaseDir, - "--dataset-path", dbPath + File.separator + "history"}; + new String[]{"-o", "merge", "--fn-data-path", DB_PATH + File.separator + databaseDir, + "--dataset-path", DB_PATH + File.separator + "history"}; Args.getInstance().getStorage().setDbEngine(dbType); + LiteFullNodeTool.setRecentBlks(3); // start fullnode startApp(); - // produce transactions for 10 seconds - generateSomeTransactions(10); + // produce transactions for 18 seconds + generateSomeTransactions(18); // stop the node shutdown(); // delete tran-cache - FileUtil.deleteDir(Paths.get(dbPath, databaseDir, "trans-cache").toFile()); + FileUtil.deleteDir(Paths.get(DB_PATH, databaseDir, "trans-cache").toFile()); // generate snapshot LiteFullNodeTool.main(argsForSnapshot); // start fullnode startApp(); - // produce transactions for 10 seconds - generateSomeTransactions(4); + // 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()))) { + File database = new File(Paths.get(DB_PATH, databaseDir).toString()); + if (!database.renameTo(new File(Paths.get(DB_PATH, databaseDir + "_bak").toString()))) { throw new RuntimeException( String.format("rename %s to %s failed", database.getPath(), - Paths.get(dbPath, databaseDir).toString())); + Paths.get(DB_PATH, databaseDir).toString())); } // 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()))) { + File snapshot = new File(Paths.get(DB_PATH, "snapshot").toString()); + if (!snapshot.renameTo(new File(Paths.get(DB_PATH, databaseDir).toString()))) { throw new RuntimeException( String.format("rename snapshot to %s failed", - Paths.get(dbPath, databaseDir).toString())); + Paths.get(DB_PATH, databaseDir).toString())); } // start and validate the snapshot startApp(); - generateSomeTransactions(4); + generateSomeTransactions(6); // stop the node shutdown(); // merge history LiteFullNodeTool.main(argsForMerge); // start and validate startApp(); - generateSomeTransactions(4); + generateSomeTransactions(6); shutdown(); + LiteFullNodeTool.reSetRecentBlks(); } private void generateSomeTransactions(int during) { From 371390f3f496b7053a2c4170bb8de973255789cd Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Wed, 31 Aug 2022 18:22:07 +0800 Subject: [PATCH 0231/1197] feat(net): add 3 prometheus metrics for network module --- .../main/java/org/tron/common/prometheus/MetricKeys.java | 3 +++ framework/src/main/java/org/tron/core/db/Manager.java | 2 +- .../src/main/java/org/tron/core/net/TronNetService.java | 6 ++++++ .../org/tron/core/net/messagehandler/BlockMsgHandler.java | 6 ++++++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/tron/common/prometheus/MetricKeys.java b/common/src/main/java/org/tron/common/prometheus/MetricKeys.java index a68f379f394..800c5cd3c62 100644 --- a/common/src/main/java/org/tron/common/prometheus/MetricKeys.java +++ b/common/src/main/java/org/tron/common/prometheus/MetricKeys.java @@ -58,6 +58,9 @@ public static class Histogram { public static final String TCP_BYTES = "tron:tcp_bytes"; public static final String HTTP_BYTES = "tron:http_bytes"; public static final String INTERNAL_SERVICE_LATENCY = "tron:internal_service_latency_seconds"; + public static final String MESSAGE_PROCESS_LATENCY = "tron:message_process_latency_seconds"; + public static final String BLOCK_FETCH_LATENCY = "tron:block_fetch_latency_seconds"; + public static final String BLOCK_RECEIVE_DELAY = "tron:block_receive_delay_seconds"; private Histogram() { throw new IllegalStateException("Histogram"); diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 457bcda999d..e227674cf52 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1432,7 +1432,7 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { String address = StringUtil.encode58Check(miner.getWitnessAddress().toByteArray()); final Histogram.Timer timer = Metrics.histogramStartTimer( MetricKeys.Histogram.BLOCK_GENERATE_LATENCY, address); - Metrics.histogramObserve(MetricKeys.Histogram.MINER_LATENCY, + Metrics.histogramObserve(MetricKeys.Histogram.MINER_DELAY, (System.currentTimeMillis() - blockTime) / Metrics.MILLISECONDS_PER_SECOND, address); long postponedTrxCount = 0; logger.info("Generate block {} begin", chainBaseManager.getHeadBlockNum() + 1); diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index ffe32bcbbd8..ed49fd8d8a5 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -5,6 +5,8 @@ import org.springframework.stereotype.Component; import org.tron.common.overlay.message.Message; import org.tron.common.overlay.server.ChannelManager; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.Metrics; import org.tron.core.exception.P2pException; import org.tron.core.exception.P2pException.TypeEnum; import org.tron.core.net.message.BlockMessage; @@ -131,6 +133,10 @@ protected void onMessage(PeerConnection peer, TronMessage msg) { long costs = System.currentTimeMillis() - startTime; logger.info("Message processing costs {} ms, peer: {}, type: {}, time tag: {}", costs, peer.getInetAddress(), msg.getType(), getTimeTag(costs)); + if (costs > DURATION_STEP) { + Metrics.histogramObserve(MetricKeys.Histogram.MESSAGE_PROCESS_LATENCY, + costs / Metrics.MILLISECONDS_PER_SECOND, msg.getType().name()); + } } } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java index 8e7eac91670..d6df46e1825 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java @@ -7,6 +7,8 @@ import org.bouncycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.Metrics; import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.BlockCapsule.BlockId; @@ -76,7 +78,11 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep if (null != time) { MetricsUtil.histogramUpdateUnCheck(MetricsKey.NET_LATENCY_FETCH_BLOCK + peer.getNode().getHost(), now - time); + Metrics.histogramObserve(MetricKeys.Histogram.BLOCK_FETCH_LATENCY, + (now - time) / Metrics.MILLISECONDS_PER_SECOND); } + Metrics.histogramObserve(MetricKeys.Histogram.BLOCK_RECEIVE_DELAY, + (now - blockMessage.getBlockCapsule().getTimeStamp()) / Metrics.MILLISECONDS_PER_SECOND); fetchBlockService.blockFetchSuccess(blockId); long interval = blockId.getNum() - tronNetDelegate.getHeadBlockId().getNum(); processBlock(peer, blockMessage.getBlockCapsule()); From ad1e9d43e3254094ecf351293dc431cda69cb4f9 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Thu, 1 Sep 2022 11:14:47 +0800 Subject: [PATCH 0232/1197] feat(jsonrpc): modify input as raw_data.contract[0].parameter.value.data --- .../jsonrpc/types/TransactionResult.java | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java b/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java index 9f0ee285ccc..c5a9e34523a 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java @@ -15,6 +15,8 @@ import org.tron.protos.Protocol; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; @JsonPropertyOrder(alphabetic = true) @ToString @@ -75,6 +77,28 @@ private void parseSignature(Transaction tx) { s = ByteArray.toJsonHex(sByte); } + private String parseInput(Transaction tx) { + String data; + if (tx.getRawData().getContractCount() == 0) { + data = "0x"; + } else { + Contract contract = tx.getRawData().getContract(0); + if (contract.getType() == ContractType.TriggerSmartContract) { + try { + TriggerSmartContract triggerSmartContract = contract.getParameter() + .unpack(TriggerSmartContract.class); + data = ByteArray.toJsonHex(triggerSmartContract.getData().toByteArray()); + } catch (Exception e) { + data = "0x"; + } + } else { + data = "0x"; + } + } + + return data; + } + public TransactionResult(BlockCapsule blockCapsule, int index, Protocol.Transaction tx, long energyUsageTotal, long energyFee, Wallet wallet) { byte[] txId = new TransactionCapsule(tx).getTransactionId().getBytes(); @@ -105,7 +129,7 @@ public TransactionResult(BlockCapsule blockCapsule, int index, Protocol.Transact gas = ByteArray.toJsonHex(energyUsageTotal); gasPrice = ByteArray.toJsonHex(energyFee); - input = ByteArray.toJsonHex(tx.getRawData().getData().toByteArray()); + input = parseInput(tx); parseSignature(tx); } @@ -133,7 +157,7 @@ public TransactionResult(Transaction tx, Wallet wallet) { gas = "0x0"; gasPrice = "0x"; - input = ByteArray.toJsonHex(tx.getRawData().getData().toByteArray()); + input = parseInput(tx); parseSignature(tx); } From 4a0bebd5a3a6f295608c0779e7b438262479a9dc Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 1 Sep 2022 11:32:34 +0800 Subject: [PATCH 0233/1197] fix(net): fix checkstyle issue --- .../java/org/tron/core/net/service/FetchBlockService.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java b/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java index 0571564ae42..751d92d185e 100644 --- a/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java +++ b/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java @@ -78,12 +78,10 @@ public void fetchBlock(List sha256HashList, PeerConnection peer) { if (System.currentTimeMillis() - chainBaseManager.getHeadBlockTimeStamp() < BLOCK_FETCH_TIME_OUT_LIMIT) { fetchBlockInfo = new FetchBlockInfo(sha256Hash, peer, System.currentTimeMillis()); + logger.info("Set fetchBlockInfo, block: {}, peer: {}, time: {}", sha256Hash, + fetchBlockInfo.getPeer().getInetAddress(), fetchBlockInfo.getTime()); } }); - if (null != fetchBlockInfo) { - logger.info("Set fetchBlockInfo, block: {}, peer: {}, time: {}", fetchBlockInfo.getHash(), - fetchBlockInfo.getPeer().getInetAddress(), fetchBlockInfo.getTime()); - } } From 51576b3436d5530b9a6c5253b13604bd098e84da Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 1 Sep 2022 19:25:08 +0800 Subject: [PATCH 0234/1197] refactor(net): add some necessary logs for fetch block service --- .../net/messagehandler/ChainInventoryMsgHandler.java | 9 ++++----- .../org/tron/core/net/service/FetchBlockService.java | 6 ++++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java index ab4d92b8707..81f0d2290a1 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java @@ -66,16 +66,15 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep synchronized (tronNetDelegate.getBlockLock()) { try { - BlockId lastBlockId = null; + BlockId blockId = null; while (!peer.getSyncBlockToFetch().isEmpty() && tronNetDelegate .containBlock(peer.getSyncBlockToFetch().peek())) { - BlockId blockId = peer.getSyncBlockToFetch().pop(); + blockId = peer.getSyncBlockToFetch().pop(); peer.setBlockBothHave(blockId); - lastBlockId = blockId; } - if (lastBlockId != null) { + if (blockId != null) { logger.info("Block {} from {} is processed", - lastBlockId.getString(), peer.getNode().getHost()); + blockId.getString(), peer.getNode().getHost()); } } catch (NoSuchElementException e) { logger.warn("Process ChainInventoryMessage failed, peer {}, isDisconnect:{}", diff --git a/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java b/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java index 751d92d185e..2c43b35ff2e 100644 --- a/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java +++ b/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java @@ -69,6 +69,11 @@ public void close() { } public void fetchBlock(List sha256HashList, PeerConnection peer) { + if (sha256HashList != null && sha256HashList.size() > 0) { + logger.info("Begin fetch block {} from {}", + new BlockCapsule.BlockId(sha256HashList.get(0)).getString(), + peer.getInetAddress()); + } if (null != fetchBlockInfo) { return; } @@ -86,6 +91,7 @@ public void fetchBlock(List sha256HashList, PeerConnection peer) { public void blockFetchSuccess(Sha256Hash sha256Hash) { + logger.info("Fetch block success, {}", new BlockCapsule.BlockId(sha256Hash).getString()); FetchBlockInfo fetchBlockInfoTemp = this.fetchBlockInfo; if (null == fetchBlockInfoTemp || !fetchBlockInfoTemp.getHash().equals(sha256Hash)) { return; From caea2ccbc6a497025a5a608328ee64068f0bb27c Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 1 Sep 2022 19:45:09 +0800 Subject: [PATCH 0235/1197] fix(net): fix checkstyle issue --- .../main/java/org/tron/core/net/service/FetchBlockService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java b/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java index 2c43b35ff2e..5c5f04f3bef 100644 --- a/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java +++ b/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java @@ -69,7 +69,7 @@ public void close() { } public void fetchBlock(List sha256HashList, PeerConnection peer) { - if (sha256HashList != null && sha256HashList.size() > 0) { + if (sha256HashList.size() > 0) { logger.info("Begin fetch block {} from {}", new BlockCapsule.BlockId(sha256HashList.get(0)).getString(), peer.getInetAddress()); From 172b37febe019c3fb09ade221dc6524ed6d5534c Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Mon, 5 Sep 2022 12:03:40 +0800 Subject: [PATCH 0236/1197] feat(net): initialize the newly added metrics --- .../java/org/tron/common/prometheus/MetricsHistogram.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java b/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java index 92be90eb65e..10cbf1d2979 100644 --- a/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java +++ b/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java @@ -41,6 +41,11 @@ public class MetricsHistogram { "type"); init(MetricKeys.Histogram.HTTP_BYTES, "http_bytes traffic.", "url", "status"); + init(MetricKeys.Histogram.MESSAGE_PROCESS_LATENCY, "process message latency.", + "type"); + init(MetricKeys.Histogram.BLOCK_FETCH_LATENCY, "fetch block latency."); + init(MetricKeys.Histogram.BLOCK_RECEIVE_DELAY, + "receive block delay time, receiveTime - blockTime."); } private MetricsHistogram() { From 33fd8fb049e1539934795e2b5ad85446324a9666 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 5 Sep 2022 17:22:20 +0800 Subject: [PATCH 0237/1197] perf: remove unused field --- framework/src/main/java/org/tron/core/db/Manager.java | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 5604dc898b9..cc7e8bb56f3 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1510,7 +1510,6 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { continue; } //multi sign transaction - Contract contract = trx.getInstance().getRawData().getContract(0); byte[] owner = trx.getOwnerAddress(); String ownerAddress = ByteArray.toHexString(owner); if (accountSet.contains(ownerAddress)) { From a5c7f15c00d6e51c9249e132fac3318708673171 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Mon, 5 Sep 2022 19:00:39 +0800 Subject: [PATCH 0238/1197] fix(net): add the log printing conditions --- framework/src/main/java/org/tron/core/net/TronNetService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index ed49fd8d8a5..3f6a0d82d16 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -131,9 +131,9 @@ protected void onMessage(PeerConnection peer, TronMessage msg) { processException(peer, msg, e); } finally { long costs = System.currentTimeMillis() - startTime; - logger.info("Message processing costs {} ms, peer: {}, type: {}, time tag: {}", - costs, peer.getInetAddress(), msg.getType(), getTimeTag(costs)); if (costs > DURATION_STEP) { + logger.info("Message processing costs {} ms, peer: {}, type: {}, time tag: {}", + costs, peer.getInetAddress(), msg.getType(), getTimeTag(costs)); Metrics.histogramObserve(MetricKeys.Histogram.MESSAGE_PROCESS_LATENCY, costs / Metrics.MILLISECONDS_PER_SECOND, msg.getType().name()); } From 8b62bc11eedb39bca7ab1f1c64f01716def3b969 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 5 Sep 2022 18:16:45 +0800 Subject: [PATCH 0239/1197] refactor(db): optimize logs for db module 1. update log levels 2. optimize log contents 3. add some necessary logs --- .../leveldb/LevelDbDataSourceImpl.java | 16 +- .../rocksdb/RocksDbDataSourceImpl.java | 34 +-- .../java/org/tron/common/utils/Commons.java | 14 +- .../org/tron/common/utils/ForkController.java | 4 +- .../org/tron/common/utils/LocalWitnesses.java | 8 +- .../org/tron/common/utils/WalletUtil.java | 3 +- .../java/org/tron/core/ChainBaseManager.java | 9 +- .../org/tron/core/db/BlockIndexStore.java | 5 +- .../java/org/tron/core/db/BlockStore.java | 41 ++- .../java/org/tron/core/db/CommonDataBase.java | 4 +- .../org/tron/core/db/EnergyProcessor.java | 5 +- .../java/org/tron/core/db/KhaosDatabase.java | 7 +- .../org/tron/core/db/PbftSignDataStore.java | 2 +- .../java/org/tron/core/db/StorageMarket.java | 67 ++--- .../org/tron/core/db/TransactionTrace.java | 22 +- .../tron/core/db/TronStoreWithRevoking.java | 8 +- .../db/accountstate/AccountStateEntity.java | 2 +- .../db/common/iterator/RockStoreIterator.java | 10 +- .../db/common/iterator/StoreIterator.java | 3 +- .../org/tron/core/db2/common/TxCacheDB.java | 15 +- .../tron/core/db2/core/SnapshotManager.java | 38 +-- .../tron/core/service/MortgageService.java | 19 +- .../org/tron/core/store/DelegationStore.java | 2 +- .../core/store/DynamicPropertiesStore.java | 20 +- .../tron/core/store/TreeBlockIndexStore.java | 5 +- .../tron/core/store/WitnessScheduleStore.java | 4 +- .../org/tron/core/config/args/Storage.java | 59 ++-- .../RevokingStoreIllegalStateException.java | 5 + .../common/application/ServiceContainer.java | 10 +- .../org/tron/core/db/BandwidthProcessor.java | 37 ++- .../main/java/org/tron/core/db/Manager.java | 278 ++++++++---------- .../java/org/tron/core/db/PendingManager.java | 6 +- .../db/accountstate/AccountStateEntity.java | 2 +- .../callback/AccountStateCallBack.java | 8 +- .../org/tron/core/db/backup/BackupDbUtil.java | 14 +- .../tool/litefullnode/LiteFullNodeTool.java | 71 ++--- .../leveldb/RocksDbDataSourceImplTest.java | 4 +- .../java/org/tron/core/db/ManagerTest.java | 14 +- 38 files changed, 426 insertions(+), 449 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java index 20ad57d4929..9cc0561a53c 100644 --- a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java @@ -102,22 +102,24 @@ public LevelDbDataSourceImpl(String parentPath, String dataBaseName) { public void initDB() { resetDbLock.writeLock().lock(); try { - logger.debug("~> LevelDbDataSourceImpl.initDB(): " + dataBaseName); + logger.debug("Init DB: {}.", dataBaseName); if (isAlive()) { return; } if (dataBaseName == null) { - throw new NullPointerException("no name set to the dbStore"); + throw new IllegalArgumentException("No name set to the dbStore"); } try { openDatabase(options); alive = true; } catch (IOException ioe) { - throw new RuntimeException("Can't initialize database", ioe); + throw new RuntimeException(String.format("Can't initialize database, %s", dataBaseName), + ioe); } + logger.debug("Init DB {} done.", dataBaseName); } finally { resetDbLock.writeLock().unlock(); } @@ -126,19 +128,21 @@ public void initDB() { private void openDatabase(Options dbOptions) throws IOException { final Path dbPath = getDbPath(); if (dbPath == null || dbPath.getParent() == null) { - return; + throw new IOException(String.format("db path is illegal, %s/%s", parentPath, dataBaseName)); } if (!Files.isSymbolicLink(dbPath.getParent())) { Files.createDirectories(dbPath.getParent()); } try { database = factory.open(dbPath.toFile(), dbOptions); - logger.info("DB {} open success with : writeBufferSize {}M,cacheSize {}M,maxOpenFiles {}.", + logger.info("DB {} open success with writeBufferSize {} M, cacheSize {} M, maxOpenFiles {}.", this.getDBName(), dbOptions.writeBufferSize() / 1024 / 1024, dbOptions.cacheSize() / 1024 / 1024, dbOptions.maxOpenFiles()); } catch (IOException e) { if (e.getMessage().contains("Corruption:")) { + logger.warn("DB {} corruption detected, try to repair it.", this.getDBName()); factory.repair(dbPath.toFile(), dbOptions); + logger.warn("DB {} corruption detected, repair done.", this.getDBName()); database = factory.open(dbPath.toFile(), dbOptions); } else { throw e; @@ -460,7 +464,7 @@ public void closeDB() { database.close(); alive = false; } catch (IOException e) { - logger.error("Failed to find the dbStore file on the closeDB: {} ", dataBaseName); + logger.error("Failed to find the dbStore file on the closeDB: {}.", dataBaseName, e); } finally { resetDbLock.writeLock().unlock(); } diff --git a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java index 0733094312f..35248619933 100644 --- a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java @@ -43,13 +43,12 @@ import org.tron.core.db2.common.WrappedByteArray; -@Slf4j +@Slf4j(topic = "DB") @NoArgsConstructor public class RocksDbDataSourceImpl extends DbStat implements DbSourceInter, Iterable>, Instance { ReadOptions readOpts; - private static final String FAIL_TO_INIT_DATABASE = "Failed to initialize database"; private String dataBaseName; private RocksDB database; private boolean alive; @@ -102,6 +101,7 @@ public void closeDB() { database.close(); alive = false; } catch (Exception e) { + logger.error("Failed to find the dbStore file on the closeDB: {}.", dataBaseName, e); } finally { resetDbLock.writeLock().unlock(); } @@ -116,7 +116,7 @@ public void resetDb() { private boolean quitIfNotAlive() { if (!isAlive()) { - logger.warn("db is not alive"); + logger.warn("DB {} is not alive.", dataBaseName); } return !isAlive(); } @@ -181,8 +181,8 @@ public boolean checkOrInitEngine() { public void initDB() { if (!checkOrInitEngine()) { - logger.error("database engine do not match"); - throw new RuntimeException(FAIL_TO_INIT_DATABASE); + throw new RuntimeException( + String.format("failed to check database: %s, engine do not match", dataBaseName)); } initDB(RocksDbSettings.getSettings()); } @@ -194,7 +194,7 @@ public void initDB(RocksDbSettings settings) { return; } if (dataBaseName == null) { - throw new NullPointerException("no name set to the dbStore"); + throw new IllegalArgumentException("No name set to the dbStore"); } try (Options options = new Options()) { @@ -238,7 +238,7 @@ public void initDB(RocksDbSettings settings) { .setVerifyChecksums(false); try { - logger.debug("Opening database"); + logger.debug("Opening database {}.", dataBaseName); final Path dbPath = getDbPath(); if (!Files.isSymbolicLink(dbPath.getParent())) { @@ -248,17 +248,17 @@ public void initDB(RocksDbSettings settings) { try { database = RocksDB.open(options, dbPath.toString()); } catch (RocksDBException e) { - logger.error(e.getMessage(), e); - throw new RuntimeException(FAIL_TO_INIT_DATABASE, e); + throw new RuntimeException( + String.format("failed to open database: %s", dataBaseName), e); } alive = true; } catch (IOException ioe) { - logger.error(ioe.getMessage(), ioe); - throw new RuntimeException(FAIL_TO_INIT_DATABASE, ioe); + throw new RuntimeException( + String.format("failed to init database: %s", dataBaseName), ioe); } - logger.debug("<~ RocksDbDataSource.initDB(): " + dataBaseName); + logger.debug("Init DB {} done.", dataBaseName); } } finally { resetDbLock.writeLock().unlock(); @@ -274,7 +274,7 @@ public void putData(byte[] key, byte[] value) { try { database.put(key, value); } catch (RocksDBException e) { - throw new RuntimeException(e); + throw new RuntimeException(dataBaseName, e); } finally { resetDbLock.readLock().unlock(); } @@ -289,7 +289,7 @@ public byte[] getData(byte[] key) { try { return database.get(key); } catch (RocksDBException e) { - throw new RuntimeException(e); + throw new RuntimeException(dataBaseName, e); } finally { resetDbLock.readLock().unlock(); } @@ -304,7 +304,7 @@ public void deleteData(byte[] key) { try { database.delete(key); } catch (RocksDBException e) { - throw new RuntimeException(e); + throw new RuntimeException(dataBaseName, e); } finally { resetDbLock.readLock().unlock(); } @@ -365,7 +365,7 @@ public void updateByBatch(Map rows, WriteOptionsWrapper optionsW try { updateByBatchInner(rows); } catch (Exception e1) { - throw new RuntimeException(e); + throw new RuntimeException(dataBaseName, e1); } } finally { resetDbLock.readLock().unlock(); @@ -384,7 +384,7 @@ public void updateByBatch(Map rows) { try { updateByBatchInner(rows); } catch (Exception e1) { - throw new RuntimeException(e); + throw new RuntimeException(dataBaseName, e1); } } finally { resetDbLock.readLock().unlock(); diff --git a/chainbase/src/main/java/org/tron/common/utils/Commons.java b/chainbase/src/main/java/org/tron/common/utils/Commons.java index f2f7578d200..55542d494b4 100644 --- a/chainbase/src/main/java/org/tron/common/utils/Commons.java +++ b/chainbase/src/main/java/org/tron/common/utils/Commons.java @@ -74,7 +74,8 @@ public static void adjustBalance(AccountStore accountStore, AccountCapsule accou if (amount < 0 && balance < -amount) { throw new BalanceInsufficientException( - StringUtil.createReadableString(account.createDbKey()) + " insufficient balance"); + String.format("%s insufficient balance, balance: %d, amount: %d", + StringUtil.createReadableString(account.createDbKey()), balance, -amount)); } account.setBalance(Math.addExact(balance, amount)); accountStore.put(account.getAddress().toByteArray(), account); @@ -120,12 +121,16 @@ public static void adjustAssetBalanceV2(AccountCapsule account, String AssetID, if (amount < 0) { if (!account.reduceAssetAmountV2(AssetID.getBytes(), -amount, dynamicPropertiesStore, assetIssueStore)) { - throw new BalanceInsufficientException("reduceAssetAmount failed !"); + throw new BalanceInsufficientException( + String.format("reduceAssetAmount failed! account: %s", + StringUtil.encode58Check(account.createDbKey()))); } } else if (amount > 0 && !account.addAssetAmountV2(AssetID.getBytes(), amount, dynamicPropertiesStore, assetIssueStore)) { - throw new BalanceInsufficientException("addAssetAmount failed !"); + throw new BalanceInsufficientException( + String.format("addAssetAmount failed! account: %s", + StringUtil.encode58Check(account.createDbKey()))); } accountStore.put(account.getAddress().toByteArray(), account); } @@ -135,7 +140,8 @@ public static void adjustTotalShieldedPoolValue(long valueBalance, long totalShieldedPoolValue = Math .subtractExact(dynamicPropertiesStore.getTotalShieldedPoolValue(), valueBalance); if (totalShieldedPoolValue < 0) { - throw new BalanceInsufficientException("Total shielded pool value can not below 0"); + throw new BalanceInsufficientException(String.format( + "total shielded pool value can not below 0, actual: %d", totalShieldedPoolValue)); } dynamicPropertiesStore.saveTotalShieldedPoolValue(totalShieldedPoolValue); } diff --git a/chainbase/src/main/java/org/tron/common/utils/ForkController.java b/chainbase/src/main/java/org/tron/common/utils/ForkController.java index b2cba4929dd..27ce4d95dc3 100644 --- a/chainbase/src/main/java/org/tron/common/utils/ForkController.java +++ b/chainbase/src/main/java/org/tron/common/utils/ForkController.java @@ -63,7 +63,7 @@ private boolean passOld(int version) { private boolean passNew(int version) { ForkBlockVersionEnum versionEnum = ForkBlockVersionEnum.getForkBlockVersionEnum(version); if (versionEnum == null) { - logger.error("not exist block version: {}", version); + logger.error("Not exist block version: {}.", version); return false; } long latestBlockTime = manager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); @@ -167,7 +167,7 @@ public synchronized void update(BlockCapsule blockCapsule) { stats[slot] = VERSION_UPGRADE; manager.getDynamicPropertiesStore().statsByVersion(version, stats); logger.info( - "*******update hard fork:{}, witness size:{}, solt:{}, witness:{}, version:{}", + "******* Update hard fork: {}, witness size: {}, solt: {}, witness: {}, version: {}.", Streams.zip(witnesses.stream(), Stream.of(ArrayUtils.toObject(stats)), Maps::immutableEntry) .map(e -> Maps .immutableEntry(encode58Check(e.getKey().toByteArray()), e.getValue())) diff --git a/chainbase/src/main/java/org/tron/common/utils/LocalWitnesses.java b/chainbase/src/main/java/org/tron/common/utils/LocalWitnesses.java index 00cd396143c..940a107a2ac 100644 --- a/chainbase/src/main/java/org/tron/common/utils/LocalWitnesses.java +++ b/chainbase/src/main/java/org/tron/common/utils/LocalWitnesses.java @@ -88,8 +88,8 @@ private void validate(String privateKey) { if (StringUtils.isNotBlank(privateKey) && privateKey.length() != ChainConstant.PRIVATE_KEY_LENGTH) { throw new IllegalArgumentException( - "Private key(" + privateKey + ") must be " + ChainConstant.PRIVATE_KEY_LENGTH - + "-bits hex string."); + String.format("private key must be %d-bits hex string, actual: %d", + ChainConstant.PRIVATE_KEY_LENGTH, privateKey.length())); } } @@ -101,7 +101,7 @@ public void addPrivateKeys(String privateKey) { //get the first one recently public String getPrivateKey() { if (CollectionUtils.isEmpty(privateKeys)) { - logger.warn("privateKey is null"); + logger.warn("PrivateKey is null."); return null; } return privateKeys.get(0); @@ -109,7 +109,7 @@ public String getPrivateKey() { public byte[] getPublicKey() { if (CollectionUtils.isEmpty(privateKeys)) { - logger.warn("privateKey is null"); + logger.warn("PrivateKey is null."); return null; } byte[] privateKey = ByteArray.fromHexString(getPrivateKey()); diff --git a/chainbase/src/main/java/org/tron/common/utils/WalletUtil.java b/chainbase/src/main/java/org/tron/common/utils/WalletUtil.java index 36f09ba6cc7..330ce35b6e9 100644 --- a/chainbase/src/main/java/org/tron/common/utils/WalletUtil.java +++ b/chainbase/src/main/java/org/tron/common/utils/WalletUtil.java @@ -28,7 +28,8 @@ public static boolean checkPermissionOperations(Permission permission, Contract throws PermissionException { ByteString operations = permission.getOperations(); if (operations.size() != 32) { - throw new PermissionException("operations size must 32"); + throw new PermissionException(String.format("operations size must 32, actual: %d", + operations.size())); } int contractType = contract.getTypeValue(); boolean b = (operations.byteAt(contractType / 8) & (1 << (contractType % 8))) != 0; diff --git a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java index b2a9f643a42..a2f3cd67b8e 100644 --- a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java +++ b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java @@ -233,13 +233,13 @@ public class ChainBaseManager { private DbStatService dbStatService; public void closeOneStore(ITronChainBase database) { - logger.info("******** begin to close " + database.getName() + " ********"); + logger.info("******** Begin to close {}. ********", database.getName()); try { database.close(); } catch (Exception e) { - logger.info("failed to close " + database.getName() + ". " + e); + logger.info("Failed to close {}.", database.getName(), e); } finally { - logger.info("******** end to close " + database.getName() + " ********"); + logger.info("******** End to close {}. ********", database.getName()); } } @@ -297,8 +297,7 @@ public BlockCapsule getHead() throws HeaderNotFound { if (CollectionUtils.isNotEmpty(blocks)) { return blocks.get(0); } else { - logger.info("Header block Not Found"); - throw new HeaderNotFound("Header block Not Found"); + throw new HeaderNotFound("header block not found"); } } diff --git a/chainbase/src/main/java/org/tron/core/db/BlockIndexStore.java b/chainbase/src/main/java/org/tron/core/db/BlockIndexStore.java index 2cfd3d7ae28..50402002f88 100644 --- a/chainbase/src/main/java/org/tron/core/db/BlockIndexStore.java +++ b/chainbase/src/main/java/org/tron/core/db/BlockIndexStore.java @@ -29,7 +29,7 @@ public BlockId get(Long num) throws ItemNotFoundException { BytesCapsule value = getUnchecked(ByteArray.fromLong(num)); if (value == null || value.getData() == null) { - throw new ItemNotFoundException("number: " + num + " is not found!"); + throw new ItemNotFoundException(String.format("number: %d is not found!", num)); } return new BlockId(Sha256Hash.wrap(value.getData()), num); } @@ -39,7 +39,8 @@ public BytesCapsule get(byte[] key) throws ItemNotFoundException { byte[] value = revokingDB.getUnchecked(key); if (ArrayUtils.isEmpty(value)) { - throw new ItemNotFoundException("number: " + Arrays.toString(key) + " is not found!"); + throw new ItemNotFoundException(String.format("number: %d is not found!", + ByteArray.toLong(key))); } return new BytesCapsule(value); } diff --git a/chainbase/src/main/java/org/tron/core/db/BlockStore.java b/chainbase/src/main/java/org/tron/core/db/BlockStore.java index e4efe388043..f2fdb5d247c 100644 --- a/chainbase/src/main/java/org/tron/core/db/BlockStore.java +++ b/chainbase/src/main/java/org/tron/core/db/BlockStore.java @@ -15,14 +15,15 @@ package org.tron.core.db; +import java.util.ArrayList; import java.util.Comparator; import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; +import java.util.Set; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import org.tron.common.error.TronDBException; import org.tron.common.utils.Sha256Hash; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.BlockCapsule.BlockId; @@ -39,31 +40,23 @@ private BlockStore(@Value("block") String dbName) { public List getLimitNumber(long startNumber, long limit) { BlockId startBlockId = new BlockId(Sha256Hash.ZERO_HASH, startNumber); - return revokingDB.getValuesNext(startBlockId.getBytes(), limit).stream() - .map(bytes -> { - try { - return new BlockCapsule(bytes); - } catch (BadItemException ignored) { - } - return null; - }) - .filter(Objects::nonNull) - .sorted(Comparator.comparing(BlockCapsule::getNum)) - .collect(Collectors.toList()); + return pack(revokingDB.getValuesNext(startBlockId.getBytes(), limit)); } public List getBlockByLatestNum(long getNum) { + return pack(revokingDB.getlatestValues(getNum)); + } - return revokingDB.getlatestValues(getNum).stream() - .map(bytes -> { - try { - return new BlockCapsule(bytes); - } catch (BadItemException ignored) { - } - return null; - }) - .filter(Objects::nonNull) - .sorted(Comparator.comparing(BlockCapsule::getNum)) - .collect(Collectors.toList()); + private List pack(Set values) { + List blocks = new ArrayList<>(); + for (byte[] bytes : values) { + try { + blocks.add(new BlockCapsule(bytes)); + } catch (BadItemException e) { + throw new TronDBException(e); + } + } + blocks.sort(Comparator.comparing(BlockCapsule::getNum)); + return blocks; } } diff --git a/chainbase/src/main/java/org/tron/core/db/CommonDataBase.java b/chainbase/src/main/java/org/tron/core/db/CommonDataBase.java index a607bb1e44f..a72b581a97c 100644 --- a/chainbase/src/main/java/org/tron/core/db/CommonDataBase.java +++ b/chainbase/src/main/java/org/tron/core/db/CommonDataBase.java @@ -5,7 +5,7 @@ import org.springframework.stereotype.Component; import org.tron.common.utils.ByteArray; -@Slf4j +@Slf4j(topic = "DB") @Component public class CommonDataBase extends TronDatabase { @@ -37,7 +37,7 @@ public boolean has(byte[] key) { public void saveLatestPbftBlockNum(long number) { if (number <= getLatestPbftBlockNum()) { - logger.warn("pbft number {} <= latest number {}", number, getLatestPbftBlockNum()); + logger.warn("PBFT number {} <= latest number {}.", number, getLatestPbftBlockNum()); return; } this.put(LATEST_PBFT_BLOCK_NUM, ByteArray.fromLong(number)); diff --git a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java index ff95f9058f1..4ebe6d603d9 100644 --- a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java @@ -83,9 +83,8 @@ public void updateAdaptiveTotalEnergyLimit() { ); dynamicPropertiesStore.saveTotalEnergyCurrentLimit(result); - logger.debug( - "adjust totalEnergyCurrentLimit, old[" + totalEnergyCurrentLimit + "], new[" + result - + "]"); + logger.debug("Adjust totalEnergyCurrentLimit, old: {}, new: {}.", + totalEnergyCurrentLimit, result); } @Override diff --git a/chainbase/src/main/java/org/tron/core/db/KhaosDatabase.java b/chainbase/src/main/java/org/tron/core/db/KhaosDatabase.java index 9c9c968aa73..c1d3bceeb4b 100644 --- a/chainbase/src/main/java/org/tron/core/db/KhaosDatabase.java +++ b/chainbase/src/main/java/org/tron/core/db/KhaosDatabase.java @@ -110,12 +110,13 @@ public BlockCapsule push(BlockCapsule blk) if (kblock != null) { if (blk.getNum() != kblock.num + 1) { throw new BadNumberBlockException( - "parent number :" + kblock.num + ",block number :" + blk.getNum()); + String.format("parent number: %d , block number: %d", kblock.num, blk.getNum()) + ); } block.setParent(kblock); } else { miniUnlinkedStore.insert(block); - logger.error("blk:{}, head:{}, miniStore:{}, miniUnlinkedStore:{}", + logger.error("Block: {}, head: {}, miniStore: {}, miniUnlinkedStore: {}.", blk, head, miniStore, @@ -327,7 +328,7 @@ protected boolean removeEldestEntry(Map.Entry> entry numKblkMap.remove(k); v.forEach(b -> { hashKblkMap.remove(b.id); - logger.info("remove from khaosDatabase:{}", b.id); + logger.info("Remove from khaosDatabase: {}.", b.id); }); }); diff --git a/chainbase/src/main/java/org/tron/core/db/PbftSignDataStore.java b/chainbase/src/main/java/org/tron/core/db/PbftSignDataStore.java index 784abca70aa..d65e24ce6de 100644 --- a/chainbase/src/main/java/org/tron/core/db/PbftSignDataStore.java +++ b/chainbase/src/main/java/org/tron/core/db/PbftSignDataStore.java @@ -6,7 +6,7 @@ import org.tron.core.capsule.PbftSignCapsule; import org.tron.protos.Protocol.PBFTMessage.DataType; -@Slf4j +@Slf4j(topic = "DB") @Component public class PbftSignDataStore extends TronDatabase { diff --git a/chainbase/src/main/java/org/tron/core/db/StorageMarket.java b/chainbase/src/main/java/org/tron/core/db/StorageMarket.java index 66c0904b622..10a3b656565 100644 --- a/chainbase/src/main/java/org/tron/core/db/StorageMarket.java +++ b/chainbase/src/main/java/org/tron/core/db/StorageMarket.java @@ -7,11 +7,8 @@ @Slf4j(topic = "DB") public class StorageMarket { - + private static final String LOG_MSG = "NewTotalPool: {}, newTotalReserved: {}."; private static final long MS_PER_YEAR = 365 * 24 * 3600 * 1000L; - private static final String NEW_TOTAL_RESERVED = " newTotalReserved: "; - private static final String NEW_STORAGE_LIMIT = " newStorageLimit: "; - private static final String NEW_TOTAL_POOL = "newTotalPool: "; private AccountStore accountStore; private DynamicPropertiesStore dynamicPropertiesStore; private long supply = 1_000_000_000_000_000L; @@ -23,12 +20,12 @@ public StorageMarket(AccountStore accountStore, DynamicPropertiesStore dynamicPr } private long exchangeToSupply(boolean isTRX, long quant) { - logger.info("isTRX: " + isTRX); + logger.info("IsTRX: {}.", isTRX); long balance = isTRX ? dynamicPropertiesStore.getTotalStoragePool() : dynamicPropertiesStore.getTotalStorageReserved(); - logger.info("balance: " + balance); + logger.info("Balance: {}.", balance); long newBalance = balance + quant; - logger.info("balance + quant: " + (balance + quant)); + logger.info("Balance + quant: {}.", balance + quant); // if (isTRX) { // dbManager.getDynamicPropertiesStore().saveTotalStoragePool(newBalance); @@ -37,7 +34,7 @@ private long exchangeToSupply(boolean isTRX, long quant) { // } double issuedSupply = -supply * (1.0 - Math.pow(1.0 + (double) quant / newBalance, 0.0005)); - logger.info("issuedSupply: " + issuedSupply); + logger.info("IssuedSupply: {}.", issuedSupply); long out = (long) issuedSupply; supply += out; @@ -45,12 +42,12 @@ private long exchangeToSupply(boolean isTRX, long quant) { } private long exchangeToSupply2(boolean isTRX, long quant) { - logger.info("isTRX: " + isTRX); + logger.info("IsTRX: {}.", isTRX); long balance = isTRX ? dynamicPropertiesStore.getTotalStoragePool() : dynamicPropertiesStore.getTotalStorageReserved(); - logger.info("balance: " + balance); + logger.info("Balance: {}.", balance); long newBalance = balance - quant; - logger.info("balance - quant: " + (balance - quant)); + logger.info("Balance - quant: {}.", balance - quant); // if (isTRX) { // dbManager.getDynamicPropertiesStore().saveTotalStoragePool(newBalance); @@ -59,7 +56,7 @@ private long exchangeToSupply2(boolean isTRX, long quant) { // } double issuedSupply = -supply * (1.0 - Math.pow(1.0 + (double) quant / newBalance, 0.0005)); - logger.info("issuedSupply: " + issuedSupply); + logger.info("IssuedSupply: {}.", issuedSupply); long out = (long) issuedSupply; supply += out; @@ -73,12 +70,12 @@ private long exchange_from_supply(boolean isTRX, long supplyQuant) { double exchangeBalance = balance * (Math.pow(1.0 + (double) supplyQuant / supply, 2000.0) - 1.0); - logger.info("exchangeBalance: " + exchangeBalance); + logger.info("ExchangeBalance: {}.", exchangeBalance); long out = (long) exchangeBalance; if (isTRX) { out = Math.round(exchangeBalance / 100000) * 100000; - logger.info("---out: " + out); + logger.info("Out: {}.", out); } return out; @@ -95,7 +92,7 @@ public long calculateTax(long duration, long limit) { double millisecondPerYear = MS_PER_YEAR; double feeRate = duration / millisecondPerYear * ratePerYear; long storageTax = (long) (limit * feeRate); - logger.info("storageTax: " + storageTax); + logger.info("StorageTax: {}.", storageTax); return storageTax; } @@ -103,18 +100,18 @@ public long calculateTax(long duration, long limit) { public long tryPayTax(long duration, long limit) { long storageTax = calculateTax(duration, limit); long tax = exchange(storageTax, false); - logger.info("tax: " + tax); + logger.info("Tax: {}.", tax); long newTotalTax = dynamicPropertiesStore.getTotalStorageTax() + tax; long newTotalPool = dynamicPropertiesStore.getTotalStoragePool() - tax; long newTotalReserved = dynamicPropertiesStore.getTotalStorageReserved() + storageTax; - logger.info("reserved: " + dynamicPropertiesStore.getTotalStorageReserved()); + logger.info("Reserved: {}.", dynamicPropertiesStore.getTotalStorageReserved()); boolean eq = dynamicPropertiesStore.getTotalStorageReserved() == 128L * 1024 * 1024 * 1024; - logger.info("reserved == 128GB: " + eq); - logger.info("newTotalTax: " + newTotalTax + " newTotalPool: " + newTotalPool - + NEW_TOTAL_RESERVED + newTotalReserved); + logger.info("Reserved == 128GB: {}.", eq); + logger.info("NewTotalTax: {}, newTotalPool: {}, newTotalReserved: {}.", + newTotalTax, newTotalPool, newTotalReserved); return storageTax; } @@ -122,18 +119,18 @@ public long tryPayTax(long duration, long limit) { public long payTax(long duration, long limit) { long storageTax = calculateTax(duration, limit); long tax = exchange(storageTax, false); - logger.info("tax: " + tax); + logger.info("Tax: {}.", tax); long newTotalTax = dynamicPropertiesStore.getTotalStorageTax() + tax; long newTotalPool = dynamicPropertiesStore.getTotalStoragePool() - tax; long newTotalReserved = dynamicPropertiesStore.getTotalStorageReserved() + storageTax; - logger.info("reserved: " + dynamicPropertiesStore.getTotalStorageReserved()); + logger.info("Reserved: {}.", dynamicPropertiesStore.getTotalStorageReserved()); boolean eq = dynamicPropertiesStore.getTotalStorageReserved() == 128L * 1024 * 1024 * 1024; - logger.info("reserved == 128GB: " + eq); - logger.info("newTotalTax: " + newTotalTax + " newTotalPool: " + newTotalPool - + NEW_TOTAL_RESERVED + newTotalReserved); + logger.info("Reserved == 128GB: {}.", eq); + logger.info("NewTotalTax: {}, newTotalPool: {}, newTotalReserved: {}.", + newTotalTax, newTotalPool, newTotalReserved); dynamicPropertiesStore.saveTotalStorageTax(newTotalTax); dynamicPropertiesStore.saveTotalStoragePool(newTotalPool); dynamicPropertiesStore.saveTotalStorageReserved(newTotalReserved); @@ -162,12 +159,10 @@ public AccountCapsule buyStorageBytes(AccountCapsule accountCapsule, long storag long quant = exchange_from_supply(true, relay); long newBalance = accountCapsule.getBalance() - quant; - logger.info("newBalance: " + newBalance); + logger.info("New balance: {}.", newBalance); long newStorageLimit = currentStorageLimit + storageBought; - logger.info( - "storageBought: " + storageBought + NEW_STORAGE_LIMIT - + newStorageLimit); + logger.info("StorageBought: {}, newStorageLimit: {}.", storageBought, newStorageLimit); accountCapsule.setLatestExchangeStorageTime(now); accountCapsule.setStorageLimit(newStorageLimit); @@ -177,7 +172,7 @@ public AccountCapsule buyStorageBytes(AccountCapsule accountCapsule, long storag long newTotalPool = dynamicPropertiesStore.getTotalStoragePool() + quant; long newTotalReserved = dynamicPropertiesStore.getTotalStorageReserved() - storageBought; - logger.info(NEW_TOTAL_POOL + newTotalPool + NEW_TOTAL_RESERVED + newTotalReserved); + logger.info(LOG_MSG, newTotalPool, newTotalReserved); dynamicPropertiesStore.saveTotalStoragePool(newTotalPool); dynamicPropertiesStore.saveTotalStorageReserved(newTotalReserved); return accountCapsule; @@ -189,13 +184,11 @@ public void buyStorage(AccountCapsule accountCapsule, long quant) { long currentStorageLimit = accountCapsule.getStorageLimit(); long newBalance = accountCapsule.getBalance() - quant; - logger.info("newBalance: " + newBalance); + logger.info("New balance: {}.", newBalance); long storageBought = exchange(quant, true); long newStorageLimit = currentStorageLimit + storageBought; - logger.info( - "storageBought: " + storageBought + NEW_STORAGE_LIMIT - + newStorageLimit); + logger.info("StorageBought: {}, newStorageLimit: {}.", storageBought, newStorageLimit); accountCapsule.setLatestExchangeStorageTime(now); accountCapsule.setStorageLimit(newStorageLimit); @@ -205,7 +198,7 @@ public void buyStorage(AccountCapsule accountCapsule, long quant) { long newTotalPool = dynamicPropertiesStore.getTotalStoragePool() + quant; long newTotalReserved = dynamicPropertiesStore.getTotalStorageReserved() - storageBought; - logger.info(NEW_TOTAL_POOL + newTotalPool + NEW_TOTAL_RESERVED + newTotalReserved); + logger.info(LOG_MSG, newTotalPool, newTotalReserved); dynamicPropertiesStore.saveTotalStoragePool(newTotalPool); dynamicPropertiesStore.saveTotalStorageReserved(newTotalReserved); @@ -219,7 +212,7 @@ public void sellStorage(AccountCapsule accountCapsule, long bytes) { long newBalance = accountCapsule.getBalance() + quant; long newStorageLimit = currentStorageLimit - bytes; - logger.info("quant: " + quant + NEW_STORAGE_LIMIT + newStorageLimit); + logger.info("Quant: {}, newStorageLimit: {}.", quant, newStorageLimit); accountCapsule.setLatestExchangeStorageTime(now); accountCapsule.setStorageLimit(newStorageLimit); @@ -229,7 +222,7 @@ public void sellStorage(AccountCapsule accountCapsule, long bytes) { long newTotalPool = dynamicPropertiesStore.getTotalStoragePool() - quant; long newTotalReserved = dynamicPropertiesStore.getTotalStorageReserved() + bytes; - logger.info(NEW_TOTAL_POOL + newTotalPool + NEW_TOTAL_RESERVED + newTotalReserved); + logger.info(LOG_MSG, newTotalPool, newTotalReserved); dynamicPropertiesStore.saveTotalStoragePool(newTotalPool); dynamicPropertiesStore.saveTotalStorageReserved(newTotalReserved); diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java index 6a74d6d015f..e4975979d36 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java @@ -41,7 +41,7 @@ import org.tron.protos.contract.SmartContractOuterClass.SmartContract.ABI; import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; -@Slf4j(topic = "TransactionTrace") +@Slf4j(topic = "DB") public class TransactionTrace { private TransactionCapsule trx; @@ -138,11 +138,10 @@ public void checkIsConstant() throws ContractValidateException, VMIllegalExcepti ContractCapsule contract = contractStore .get(triggerContractFromTransaction.getContractAddress().toByteArray()); if (contract == null) { - logger.info("contract: {} is not in contract store", StringUtil - .encode58Check(triggerContractFromTransaction.getContractAddress().toByteArray())); - throw new ContractValidateException("contract: " + StringUtil - .encode58Check(triggerContractFromTransaction.getContractAddress().toByteArray()) - + " is not in contract store"); + throw new ContractValidateException(String.format("contract: %s is not in contract store", + StringUtil.encode58Check(triggerContractFromTransaction + .getContractAddress().toByteArray()))); + } ABI abi = contract.getInstance().getAbi(); if (WalletUtil.isConstant(abi, triggerContractFromTransaction)) { @@ -269,14 +268,13 @@ public void check() throws ReceiptCheckErrException { return; } if (Objects.isNull(trx.getContractRet())) { - throw new ReceiptCheckErrException("null resultCode"); + throw new ReceiptCheckErrException( + String.format("null resultCode id: %s", trx.getTransactionId())); } if (!trx.getContractRet().equals(receipt.getResult())) { - logger.info( - "this tx id: {}, the resultCode in received block: {}, the resultCode in self: {}", - Hex.toHexString(trx.getTransactionId().getBytes()), trx.getContractRet(), - receipt.getResult()); - throw new ReceiptCheckErrException("Different resultCode"); + throw new ReceiptCheckErrException(String.format( + "different resultCode txId: %s, expect: %s, actual: %s", + trx.getTransactionId(), trx.getContractRet(), receipt.getResult())); } } diff --git a/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java b/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java index 1b327642212..d1bbed934d5 100644 --- a/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java +++ b/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java @@ -76,12 +76,12 @@ protected TronStoreWithRevoking(String dbName) { dbName, CommonParameter.getInstance() .getRocksDBCustomSettings(), getDirectComparator())); } else { - throw new RuntimeException("dbEngine is error."); + throw new RuntimeException(String.format("db engine %s is error", dbEngine)); } this.revokingDB = new Chainbase(new SnapshotRoot(this.db)); } else { - throw new RuntimeException("db version is error."); + throw new RuntimeException(String.format("db version %d is error", dbVersion)); } } @@ -99,7 +99,7 @@ protected TronStoreWithRevoking(DB db) { this.db = db; this.revokingDB = new Chainbase(new SnapshotRoot(db)); } else { - throw new RuntimeException("db version is only 2.(" + dbVersion + ")"); + throw new RuntimeException(String.format("db version is only 2, actual: %d", dbVersion)); } } @@ -196,7 +196,7 @@ private void closeJniIterator(Iterator iterator) { try { ((DBIterator) iterator).close(); } catch (IOException e) { - logger.error("", e); + logger.error("Close jni iterator.", e); } } } diff --git a/chainbase/src/main/java/org/tron/core/db/accountstate/AccountStateEntity.java b/chainbase/src/main/java/org/tron/core/db/accountstate/AccountStateEntity.java index 858543986fc..9b5601002f0 100644 --- a/chainbase/src/main/java/org/tron/core/db/accountstate/AccountStateEntity.java +++ b/chainbase/src/main/java/org/tron/core/db/accountstate/AccountStateEntity.java @@ -25,7 +25,7 @@ public static AccountStateEntity parse(byte[] data) { try { return new AccountStateEntity().setAccount(Account.parseFrom(data)); } catch (Exception e) { - logger.error("parse to AccountStateEntity error! reason: {}", e.getMessage()); + logger.error("Parse to AccountStateEntity error!", e); } return null; } diff --git a/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java b/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java index f095ec5ab5d..8bf2a022600 100644 --- a/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java +++ b/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java @@ -5,9 +5,10 @@ import java.util.NoSuchElementException; import lombok.extern.slf4j.Slf4j; import org.rocksdb.RocksIterator; +import org.tron.common.error.TronDBException; -@Slf4j +@Slf4j(topic = "DB") public final class RockStoreIterator implements DBIterator { private RocksIterator dbIterator; @@ -35,12 +36,7 @@ public boolean hasNext() { dbIterator.close(); } } catch (Exception e) { - System.out.println("e:" + e); - try { - dbIterator.close(); - } catch (Exception e1) { - System.out.println("e1:" + e1); - } + throw new TronDBException(e); } return hasNext; } diff --git a/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java b/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java index 997d13dd293..a0929616a4b 100755 --- a/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java +++ b/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java @@ -4,6 +4,7 @@ import java.util.Map.Entry; import lombok.extern.slf4j.Slf4j; import org.iq80.leveldb.DBIterator; +import org.tron.common.error.TronDBException; @Slf4j(topic = "DB") public final class StoreIterator implements org.tron.core.db.common.iterator.DBIterator { @@ -34,7 +35,7 @@ public boolean hasNext() { dbIterator.close(); } } catch (Exception e) { - logger.debug(e.getMessage(), e); + throw new TronDBException(e); } return hasNext; diff --git a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java index 02f8f06fd2e..f574520b222 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java @@ -81,10 +81,10 @@ public TxCacheDB(String name, RecentTransactionStore recentTransactionStore) { name, CommonParameter.getInstance() .getRocksDBCustomSettings())); } else { - throw new RuntimeException("db type is not supported."); + throw new RuntimeException(String.format("db type: %s is not supported", dbEngine)); } } else { - throw new RuntimeException("db version is not supported."); + throw new RuntimeException(String.format("db version: %d is not supported", dbVersion)); } this.bloomFilters[0] = BloomFilter.create(Funnels.byteArrayFunnel(), MAX_BLOCK_SIZE * TRANSACTION_COUNT); @@ -109,8 +109,7 @@ private void initCache() { bloomFilters[1].put(entry.getKey()); persistentSize++; } - logger.info("load transaction cache from persistentStore " - + "db-size:{}, filter-size:{}, filter-fpp:{}, cost:{}ms", + logger.info("Load cache from persistentStore, db: {}, filter: {}, filter-fpp: {}, cost: {} ms.", persistentSize, bloomFilters[1].approximateElementCount(), bloomFilters[1].expectedFpp(), System.currentTimeMillis() - start); @@ -133,8 +132,7 @@ private void init() { trx.getTransactionIds().forEach(tid -> bloomFilters[1].put(Hex.decode(tid))); } - logger.info("load transaction cache from recentTransactionStore" - + " filter-size:{}, filter-fpp:{}, cost:{}ms", + logger.info("Load cache from recentTransactionStore, filter: {}, filter-fpp: {}, cost: {} ms.", bloomFilters[1].approximateElementCount(), bloomFilters[1].expectedFpp(), System.currentTimeMillis() - start); } @@ -159,10 +157,11 @@ public void put(byte[] key, byte[] value) { // init active filter start block filterStartBlock = blockNum; currentFilterIndex = 0; - logger.info("init tx cache bloomFilters at {}", blockNum); + logger.info("Init tx cache bloomFilters at {}.", blockNum); } else if (blockNum - filterStartBlock > MAX_BLOCK_SIZE) { // active filter is full - logger.info("active bloomFilters is full (size={} fpp={}), create a new one (start={})", + logger.info( + "Active bloomFilters is full (size = {} fpp = {}), create a new one (start = {}).", bloomFilters[currentFilterIndex].approximateElementCount(), bloomFilters[currentFilterIndex].expectedFpp(), blockNum); diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java index 7e2d8f5074a..477631ab507 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java @@ -150,7 +150,7 @@ private void retreat() { public void merge() { if (activeSession <= 0) { - throw new RevokingStoreIllegalStateException("activeDialog has to be greater than 0"); + throw new RevokingStoreIllegalStateException(activeSession); } if (size < 2) { @@ -168,7 +168,7 @@ public synchronized void revoke() { } if (activeSession <= 0) { - throw new RevokingStoreIllegalStateException("activeSession has to be greater than 0"); + throw new RevokingStoreIllegalStateException(activeSession); } if (size <= 0) { @@ -187,7 +187,7 @@ public synchronized void revoke() { public synchronized void commit() { if (activeSession <= 0) { - throw new RevokingStoreIllegalStateException("activeSession has to be greater than 0"); + throw new RevokingStoreIllegalStateException(activeSession); } --activeSession; @@ -195,11 +195,13 @@ public synchronized void commit() { public synchronized void pop() { if (activeSession != 0) { - throw new RevokingStoreIllegalStateException("activeSession has to be equal 0"); + throw new RevokingStoreIllegalStateException( + String.format("activeSession has to be equal 0, current %d", activeSession)); } if (size <= 0) { - throw new RevokingStoreIllegalStateException("there is not snapshot to be popped"); + throw new RevokingStoreIllegalStateException( + String.format("there is not snapshot to be popped, current: %d", size)); } disabled = true; @@ -240,10 +242,10 @@ public synchronized void disable() { @Override public void shutdown() { - System.err.println("******** begin to pop revokingDb ********"); - System.err.println("******** before revokingDb size:" + size); + logger.info("******** Begin to pop revokingDb. ********"); + logger.info("******** Before revokingDb size: {}.", size); checkTmpStore.close(); - System.err.println("******** end to pop revokingDb ********"); + logger.info("******** End to pop revokingDb. ********"); } public void updateSolidity(int hops) { @@ -312,13 +314,13 @@ public void flush() { long checkPointEnd = System.currentTimeMillis(); refresh(); flushCount = 0; - logger.info("flush cost:{}, create checkpoint cost:{}, refresh cost:{}", + logger.info("Flush cost: {} ms, create checkpoint cost: {} ms, refresh cost: {} ms.", System.currentTimeMillis() - start, checkPointEnd - start, System.currentTimeMillis() - checkPointEnd ); } catch (TronDBException e) { - logger.error(" Find fatal error , program will be exited soon", e); + logger.error(" Find fatal error, program will be exited soon.", e); hitDown = true; LockSupport.unpark(exitThread); } @@ -380,7 +382,7 @@ private void deleteCheckpoint() { public void check() { for (Chainbase db : dbs) { if (!Snapshot.isRoot(db.getHead())) { - throw new IllegalStateException("first check."); + throw new IllegalStateException("First check."); } } @@ -471,7 +473,7 @@ public void destroy() { snapshotManager.revoke(); } } catch (Exception e) { - logger.error("revoke database error.", e); + throw new RevokingStoreIllegalStateException(e); } if (disableOnExit) { snapshotManager.disable(); @@ -480,17 +482,7 @@ public void destroy() { @Override public void close() { - try { - if (applySnapshot) { - snapshotManager.revoke(); - } - } catch (Exception e) { - logger.error("revoke database error.", e); - throw new RevokingStoreIllegalStateException(e); - } - if (disableOnExit) { - snapshotManager.disable(); - } + destroy(); } } diff --git a/chainbase/src/main/java/org/tron/core/service/MortgageService.java b/chainbase/src/main/java/org/tron/core/service/MortgageService.java index f11c0693a77..5dd99626930 100644 --- a/chainbase/src/main/java/org/tron/core/service/MortgageService.java +++ b/chainbase/src/main/java/org/tron/core/service/MortgageService.java @@ -74,19 +74,19 @@ public void payStandbyWitness() { for (ByteString b : witnessAddressList) { double eachVotePay = (double) totalPay / voteSum; long pay = (long) (witnessCapsuleMap.get(b).getVoteCount() * eachVotePay); - logger.debug("pay {} stand reward {}", Hex.toHexString(b.toByteArray()), pay); + logger.debug("Pay {} stand reward {}.", Hex.toHexString(b.toByteArray()), pay); payReward(b.toByteArray(), pay); } } } public void payBlockReward(byte[] witnessAddress, long value) { - logger.debug("pay {} block reward {}", Hex.toHexString(witnessAddress), value); + logger.debug("Pay {} block reward {}.", Hex.toHexString(witnessAddress), value); payReward(witnessAddress, value); } public void payTransactionFeeReward(byte[] witnessAddress, long value) { - logger.debug("pay {} transaction fee reward {}", Hex.toHexString(witnessAddress), value); + logger.debug("Pay {} transaction fee reward {}.", Hex.toHexString(witnessAddress), value); payReward(witnessAddress, value); } @@ -125,7 +125,7 @@ public void withdrawReward(byte[] address) { reward = computeReward(beginCycle, endCycle, account); adjustAllowance(address, reward); reward = 0; - logger.info("latest cycle reward {},{}", beginCycle, account.getVotesList()); + logger.info("Latest cycle reward {}, {}.", beginCycle, account.getVotesList()); } beginCycle += 1; } @@ -142,8 +142,8 @@ public void withdrawReward(byte[] address) { delegationStore.setBeginCycle(address, endCycle); delegationStore.setEndCycle(address, endCycle + 1); delegationStore.setAccountVote(endCycle, address, accountCapsule); - logger.info("adjust {} allowance {}, now currentCycle {}, beginCycle {}, endCycle {}, " - + "account vote {},", Hex.toHexString(address), reward, currentCycle, + logger.info("Adjust {} allowance {}, now currentCycle {}, beginCycle {}, endCycle {}, " + + "account vote {}.", Hex.toHexString(address), reward, currentCycle, beginCycle, endCycle, accountCapsule.getVotesList()); } @@ -194,7 +194,7 @@ private long computeReward(long cycle, AccountCapsule accountCapsule) { long userVote = vote.getVoteCount(); double voteRate = (double) userVote / totalVote; reward += voteRate * totalReward; - logger.debug("computeReward {} {} {} {},{},{},{}", cycle, + logger.debug("ComputeReward {}, {}, {}, {}, {}, {}, {}.", cycle, Hex.toHexString(accountCapsule.getAddress().toByteArray()), Hex.toHexString(srAddress), userVote, totalVote, totalReward, reward); } @@ -252,7 +252,7 @@ public void adjustAllowance(byte[] address, long amount) { } adjustAllowance(accountStore, address, amount); } catch (BalanceInsufficientException e) { - logger.error("withdrawReward error: {},{}", Hex.toHexString(address), address, e); + logger.error("WithdrawReward error: {}.", e.getMessage()); } } @@ -266,7 +266,8 @@ public void adjustAllowance(AccountStore accountStore, byte[] accountAddress, lo if (amount < 0 && allowance < -amount) { throw new BalanceInsufficientException( - StringUtil.createReadableString(accountAddress) + " insufficient balance"); + String.format("%s insufficient balance, amount: %d, allowance: %d", + StringUtil.createReadableString(accountAddress), amount, allowance)); } account.setAllowance(allowance + amount); accountStore.put(account.createDbKey(), account); diff --git a/chainbase/src/main/java/org/tron/core/store/DelegationStore.java b/chainbase/src/main/java/org/tron/core/store/DelegationStore.java index 8c799a4250b..4e95e480cfd 100644 --- a/chainbase/src/main/java/org/tron/core/store/DelegationStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DelegationStore.java @@ -13,7 +13,7 @@ import java.math.BigInteger; -@Slf4j +@Slf4j(topic = "DB") @Component public class DelegationStore extends TronStoreWithRevoking { diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index dce79515ad4..0e55b6cf7a7 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -905,7 +905,7 @@ public long getAbiMoveDone() { } public void saveBlockFilledSlotsIndex(int blockFilledSlotsIndex) { - logger.debug("blockFilledSlotsIndex:" + blockFilledSlotsIndex); + logger.debug("BlockFilledSlotsIndex: {}.", blockFilledSlotsIndex); this.put(BLOCK_FILLED_SLOTS_INDEX, new BytesCapsule(ByteArray.fromInt(blockFilledSlotsIndex))); } @@ -1936,7 +1936,7 @@ public boolean supportShieldedTRC20Transaction() { } public void saveBlockFilledSlots(int[] blockFilledSlots) { - logger.debug("blockFilledSlots:" + intArrayToString(blockFilledSlots)); + logger.debug("BlockFilledSlots: {}.", intArrayToString(blockFilledSlots)); this.put(BLOCK_FILLED_SLOTS, new BytesCapsule(ByteArray.fromString(intArrayToString(blockFilledSlots)))); } @@ -2034,7 +2034,7 @@ public long getLatestBlockHeaderNumberFromDB() { .orElseThrow( () -> new IllegalArgumentException("not found latest block header number")); } catch (ItemNotFoundException | BadItemException e) { - logger.error("{}", e); + logger.error("Get header from DB, {}.", e.getMessage()); } return -1; } @@ -2061,7 +2061,7 @@ public Sha256Hash getLatestBlockHeaderHash() { * save timestamp of creating global latest block. */ public void saveLatestBlockHeaderTimestamp(long t) { - logger.info("update latest block header timestamp = {}", t); + logger.info("Update latest block header timestamp = {}.", t); this.put(LATEST_BLOCK_HEADER_TIMESTAMP, new BytesCapsule(ByteArray.fromLong(t))); } @@ -2069,7 +2069,7 @@ public void saveLatestBlockHeaderTimestamp(long t) { * save number of global latest block. */ public void saveLatestBlockHeaderNumber(long n) { - logger.info("update latest block header number = {}", n); + logger.info("Update latest block header number = {}.", n); this.put(LATEST_BLOCK_HEADER_NUMBER, new BytesCapsule(ByteArray.fromLong(n))); } @@ -2077,12 +2077,12 @@ public void saveLatestBlockHeaderNumber(long n) { * save id of global latest block. */ public void saveLatestBlockHeaderHash(ByteString h) { - logger.info("update latest block header id = {}", ByteArray.toHexString(h.toByteArray())); + logger.info("Update latest block header id = {}.", ByteArray.toHexString(h.toByteArray())); this.put(LATEST_BLOCK_HEADER_HASH, new BytesCapsule(h.toByteArray())); } public void saveStateFlag(int n) { - logger.info("update state flag = {}", n); + logger.info("Update state flag = {}.", n); this.put(STATE_FLAG, new BytesCapsule(ByteArray.fromInt(n))); } @@ -2112,8 +2112,8 @@ public void updateNextMaintenanceTime(long blockTime) { saveNextMaintenanceTime(nextMaintenanceTime); logger.info( - "do update nextMaintenanceTime,currentMaintenanceTime:{}, blockTime:{}," - + "nextMaintenanceTime:{}", + "Do update nextMaintenanceTime, currentMaintenanceTime: {}, blockTime: {}, " + + "nextMaintenanceTime: {}.", new DateTime(currentMaintenanceTime), new DateTime(blockTime), new DateTime(nextMaintenanceTime) ); @@ -2190,7 +2190,7 @@ public long getAllowProtoFilterNum() { * save allow protobuf number. */ public void saveAllowProtoFilterNum(long num) { - logger.info("update allow protobuf number = {}", num); + logger.info("Update allow protobuf number = {}.", num); this.put(ALLOW_PROTO_FILTER_NUM, new BytesCapsule(ByteArray.fromLong(num))); } diff --git a/chainbase/src/main/java/org/tron/core/store/TreeBlockIndexStore.java b/chainbase/src/main/java/org/tron/core/store/TreeBlockIndexStore.java index 95ef3a3373c..fbeaecfda40 100644 --- a/chainbase/src/main/java/org/tron/core/store/TreeBlockIndexStore.java +++ b/chainbase/src/main/java/org/tron/core/store/TreeBlockIndexStore.java @@ -28,7 +28,7 @@ public byte[] get(Long num) throws ItemNotFoundException { BytesCapsule value = getUnchecked(ByteArray.fromLong(num)); if (value == null || value.getData() == null) { - throw new ItemNotFoundException("number: " + num + " is not found!"); + throw new ItemNotFoundException(String.format("number: %d is not found!", num)); } return value.getData(); @@ -39,7 +39,8 @@ public BytesCapsule get(byte[] key) throws ItemNotFoundException { byte[] value = revokingDB.getUnchecked(key); if (ArrayUtils.isEmpty(value)) { - throw new ItemNotFoundException("number: " + Arrays.toString(key) + " is not found!"); + throw new ItemNotFoundException(String.format("number: %d is not found!", + ByteArray.toLong(key))); } return new BytesCapsule(value); } diff --git a/chainbase/src/main/java/org/tron/core/store/WitnessScheduleStore.java b/chainbase/src/main/java/org/tron/core/store/WitnessScheduleStore.java index 227b65b6c98..285638c9f49 100644 --- a/chainbase/src/main/java/org/tron/core/store/WitnessScheduleStore.java +++ b/chainbase/src/main/java/org/tron/core/store/WitnessScheduleStore.java @@ -49,11 +49,11 @@ private List getData(byte[] species) { System.arraycopy(ba, i * ADDRESS_BYTE_ARRAY_LENGTH, b, 0, ADDRESS_BYTE_ARRAY_LENGTH); witnessesAddressList.add(ByteString.copyFrom(b)); } - logger.debug("getWitnesses:" + ByteArray.toStr(species) + witnessesAddressList); + logger.debug("GetWitnesses: {}, {}.", ByteArray.toStr(species), witnessesAddressList); return witnessesAddressList; }).orElseThrow( () -> new IllegalArgumentException( - "not found " + ByteArray.toStr(species) + "Witnesses")); + String.format("not found %s Witnesses", ByteArray.toStr(species)))); } public void saveActiveWitnesses(List witnessesAddressList) { diff --git a/common/src/main/java/org/tron/core/config/args/Storage.java b/common/src/main/java/org/tron/core/config/args/Storage.java index 1ea7e00eb1f..1b8bd595be0 100644 --- a/common/src/main/java/org/tron/core/config/args/Storage.java +++ b/common/src/main/java/org/tron/core/config/args/Storage.java @@ -205,12 +205,12 @@ private Property createProperty(final ConfigObject conf) { File file = new File(path); if (!file.exists() && !file.mkdirs()) { throw new IllegalArgumentException( - "[storage.properties] can not create storage path: " + path); + String.format("[storage.properties] can not create storage path: %s", path)); } if (!file.canWrite()) { throw new IllegalArgumentException( - "[storage.properties] permission denied to write to: " + path); + String.format("[storage.properties] permission denied to write to: %s ", path)); } property.setPath(path); @@ -251,71 +251,58 @@ private static void setIfNeeded(ConfigObject conf, Options dbOptions) { } if (conf.containsKey(COMPRESSION_TYPE_CONFIG_KEY)) { + String param = conf.get(COMPRESSION_TYPE_CONFIG_KEY).unwrapped().toString(); try { dbOptions.compressionType( - CompressionType.getCompressionTypeByPersistentId( - Integer.parseInt( - conf.get(COMPRESSION_TYPE_CONFIG_KEY).unwrapped().toString() - ) - ) - ); + CompressionType.getCompressionTypeByPersistentId(Integer.parseInt(param))); } catch (NumberFormatException e) { - throw new IllegalArgumentException( - "[storage.properties] compressionType must be Integer type."); + throwIllegalArgumentException(COMPRESSION_TYPE_CONFIG_KEY, Integer.class, param); } } if (conf.containsKey(BLOCK_SIZE_CONFIG_KEY)) { + String param = conf.get(BLOCK_SIZE_CONFIG_KEY).unwrapped().toString(); try { - dbOptions.blockSize( - Integer.parseInt( - conf.get(BLOCK_SIZE_CONFIG_KEY).unwrapped().toString() - ) - ); + dbOptions.blockSize(Integer.parseInt(param)); } catch (NumberFormatException e) { - throw new IllegalArgumentException("[storage.properties] blockSize must be Integer type."); + throwIllegalArgumentException(BLOCK_SIZE_CONFIG_KEY, Integer.class, param); } } if (conf.containsKey(WRITE_BUFFER_SIZE_CONFIG_KEY)) { + String param = conf.get(WRITE_BUFFER_SIZE_CONFIG_KEY).unwrapped().toString(); try { - dbOptions.writeBufferSize( - Integer.parseInt( - conf.get(WRITE_BUFFER_SIZE_CONFIG_KEY).unwrapped().toString() - ) - ); + dbOptions.writeBufferSize(Integer.parseInt(param)); } catch (NumberFormatException e) { - throw new IllegalArgumentException( - "[storage.properties] writeBufferSize must be Integer type."); + throwIllegalArgumentException(WRITE_BUFFER_SIZE_CONFIG_KEY, Integer.class, param); } } if (conf.containsKey(CACHE_SIZE_CONFIG_KEY)) { + String param = conf.get(CACHE_SIZE_CONFIG_KEY).unwrapped().toString(); try { - dbOptions.cacheSize( - Long.parseLong( - conf.get(CACHE_SIZE_CONFIG_KEY).unwrapped().toString() - ) - ); + dbOptions.cacheSize(Long.parseLong(param)); } catch (NumberFormatException e) { - throw new IllegalArgumentException("[storage.properties] cacheSize must be Long type."); + throwIllegalArgumentException(CACHE_SIZE_CONFIG_KEY, Long.class, param); } } if (conf.containsKey(MAX_OPEN_FILES_CONFIG_KEY)) { + String param = conf.get(MAX_OPEN_FILES_CONFIG_KEY).unwrapped().toString(); try { - dbOptions.maxOpenFiles( - Integer.parseInt( - conf.get(MAX_OPEN_FILES_CONFIG_KEY).unwrapped().toString() - ) - ); + dbOptions.maxOpenFiles(Integer.parseInt(param)); } catch (NumberFormatException e) { - throw new IllegalArgumentException( - "[storage.properties] maxOpenFiles must be Integer type."); + throwIllegalArgumentException(MAX_OPEN_FILES_CONFIG_KEY, Integer.class, param); } } } + private static void throwIllegalArgumentException(String param, Class type, String actual) { + throw new IllegalArgumentException( + String.format("[storage.properties] %s must be %s type, actual: %s.", + param, type.getSimpleName(), actual)); + } + /** * Set propertyMap of Storage object from Config * diff --git a/common/src/main/java/org/tron/core/exception/RevokingStoreIllegalStateException.java b/common/src/main/java/org/tron/core/exception/RevokingStoreIllegalStateException.java index fc0b2d56f23..480f850c111 100755 --- a/common/src/main/java/org/tron/core/exception/RevokingStoreIllegalStateException.java +++ b/common/src/main/java/org/tron/core/exception/RevokingStoreIllegalStateException.java @@ -51,4 +51,9 @@ public RevokingStoreIllegalStateException(String message, Throwable cause) { public RevokingStoreIllegalStateException(Throwable cause) { super("", cause); } + + public RevokingStoreIllegalStateException(int activeSession) { + this(String.format("activeSession %d has to be greater than 0", activeSession)); + } + } diff --git a/framework/src/main/java/org/tron/common/application/ServiceContainer.java b/framework/src/main/java/org/tron/common/application/ServiceContainer.java index 9692ce2da62..d194360c5ea 100644 --- a/framework/src/main/java/org/tron/common/application/ServiceContainer.java +++ b/framework/src/main/java/org/tron/common/application/ServiceContainer.java @@ -35,29 +35,29 @@ public void add(Service service) { public void init() { for (Service service : this.services) { - logger.debug("Initing " + service.getClass().getSimpleName()); + logger.debug("Initing {}.", service.getClass().getSimpleName()); service.init(); } } public void init(CommonParameter parameter) { for (Service service : this.services) { - logger.debug("Initing " + service.getClass().getSimpleName()); + logger.debug("Initing {}.", service.getClass().getSimpleName()); service.init(parameter); } } public void start() { - logger.debug("Starting services"); + logger.debug("Starting services."); for (Service service : this.services) { - logger.debug("Starting " + service.getClass().getSimpleName()); + logger.debug("Starting {}.", service.getClass().getSimpleName()); service.start(); } } public void stop() { for (Service service : this.services) { - logger.debug("Stopping " + service.getClass().getSimpleName()); + logger.debug("Stopping {}.", service.getClass().getSimpleName()); service.stop(); } } diff --git a/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java b/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java index e39865e95ed..92500285f88 100644 --- a/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -11,6 +11,7 @@ import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Commons; +import org.tron.common.utils.StringUtil; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; @@ -112,12 +113,13 @@ public void consume(TransactionCapsule trx, TransactionTrace trace) bytesSize += Constant.MAX_RESULT_SIZE_IN_TX; } - logger.debug("trxId {}, bandwidth cost: {}", trx.getTransactionId(), bytesSize); + logger.debug("TxId {}, bandwidth cost: {}.", trx.getTransactionId(), bytesSize); trace.setNetBill(bytesSize, 0); byte[] address = TransactionCapsule.getOwner(contract); AccountCapsule accountCapsule = chainBaseManager.getAccountStore().get(address); if (accountCapsule == null) { - throw new ContractValidateException("account does not exist"); + throw new ContractValidateException(String.format("account [%s] does not exist", + StringUtil.encode58Check(address))); } long now = chainBaseManager.getHeadSlot(); if (contractCreateNewAccount(contract)) { @@ -144,8 +146,9 @@ public void consume(TransactionCapsule trx, TransactionTrace trace) long fee = chainBaseManager.getDynamicPropertiesStore().getTransactionFee() * bytesSize; throw new AccountResourceInsufficientException( - "Account has insufficient bandwidth[" + bytesSize + "] and balance[" - + fee + "] to create new account"); + String.format( + "account [%s] has insufficient bandwidth[%d] and balance[%d] to create new account", + StringUtil.encode58Check(address), bytesSize, fee)); } } @@ -263,7 +266,7 @@ private boolean useAssetAccountNet(Contract contract, AccountCapsule accountCaps chainBaseManager.getAssetIssueStore(), chainBaseManager.getAssetIssueV2Store()) .get(assetName.toByteArray()); if (assetIssueCapsule == null) { - throw new ContractValidateException("asset does not exist"); + throw new ContractValidateException(String.format("asset [%s] does not exist", assetName)); } String tokenName = ByteArray.toStr(assetName.toByteArray()); @@ -280,7 +283,9 @@ private boolean useAssetAccountNet(Contract contract, AccountCapsule accountCaps publicLatestFreeNetTime, now); if (bytes > (publicFreeAssetNetLimit - newPublicFreeAssetNetUsage)) { - logger.debug("The " + tokenID + " public free bandwidth is not enough"); + logger.debug("The {} public free bandwidth is not enough." + + " Bytes: {}, publicFreeAssetNetLimit: {}, newPublicFreeAssetNetUsage: {}.", + tokenID, bytes, publicFreeAssetNetLimit, newPublicFreeAssetNetUsage); return false; } @@ -302,7 +307,9 @@ private boolean useAssetAccountNet(Contract contract, AccountCapsule accountCaps latestAssetOperationTime, now); if (bytes > (freeAssetNetLimit - newFreeAssetNetUsage)) { - logger.debug("The " + tokenID + " free bandwidth is not enough"); + logger.debug("The {} free bandwidth is not enough." + + " Bytes: {}, freeAssetNetLimit: {}, newFreeAssetNetUsage:{}.", + tokenID, bytes, freeAssetNetLimit, newFreeAssetNetUsage); return false; } @@ -316,7 +323,9 @@ private boolean useAssetAccountNet(Contract contract, AccountCapsule accountCaps long newIssuerNetUsage = increase(issuerNetUsage, 0, latestConsumeTime, now); if (bytes > (issuerNetLimit - newIssuerNetUsage)) { - logger.debug("The " + tokenID + " issuer's bandwidth is not enough"); + logger.debug("The {} issuer's bandwidth is not enough." + + " Bytes: {}, issuerNetLimit: {}, newIssuerNetUsage:{}.", + tokenID, bytes, issuerNetLimit, newIssuerNetUsage); return false; } @@ -393,7 +402,9 @@ private boolean useAccountNet(AccountCapsule accountCapsule, long bytes, long no long newNetUsage = increase(netUsage, 0, latestConsumeTime, now); if (bytes > (netLimit - newNetUsage)) { - logger.debug("net usage is running out, now use free net usage"); + logger.debug("Net usage is running out, now use free net usage." + + " Bytes: {}, netLimit: {}, newNetUsage: {}.", + bytes, netLimit, newNetUsage); return false; } @@ -416,7 +427,9 @@ private boolean useFreeNet(AccountCapsule accountCapsule, long bytes, long now) long newFreeNetUsage = increase(freeNetUsage, 0, latestConsumeFreeTime, now); if (bytes > (freeNetLimit - newFreeNetUsage)) { - logger.debug("free net usage is running out"); + logger.debug("Free net usage is running out." + + " Bytes: {}, freeNetLimit: {}, newFreeNetUsage: {}.", + bytes, freeNetLimit, newFreeNetUsage); return false; } @@ -427,7 +440,9 @@ private boolean useFreeNet(AccountCapsule accountCapsule, long bytes, long now) long newPublicNetUsage = increase(publicNetUsage, 0, publicNetTime, now); if (bytes > (publicNetLimit - newPublicNetUsage)) { - logger.debug("free public net usage is running out"); + logger.debug("Free public net usage is running out." + + " Bytes: {}, publicNetLimit: {}, newPublicNetUsage: {}.", + bytes, publicNetLimit, newPublicNetUsage); return false; } diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 457bcda999d..dd19c129cc0 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -169,7 +169,7 @@ public class Manager { private static final int SHIELDED_TRANS_IN_BLOCK_COUNTS = 1; - private static final String SAVE_BLOCK = "save block: "; + private static final String SAVE_BLOCK = "Save block: {}"; private static final int SLEEP_TIME_OUT = 50; private static final int TX_ID_CACHE_SIZE = 100_000; private static final int SLEEP_FOR_WAIT_LOCK = 10; @@ -266,7 +266,7 @@ public class Manager { if (ex instanceof InterruptedException) { Thread.currentThread().interrupt(); } - logger.error("unknown exception happened in rePush loop", ex); + logger.error("Unknown exception happened in rePush loop.", ex); if (tx != null) { Metrics.counterInc(MetricKeys.Counter.TXS, 1, MetricLabels.Counter.TXS_FAIL, MetricLabels.Counter.TXS_FAIL_ERROR); @@ -291,7 +291,7 @@ public class Manager { logger.info(ex.getMessage()); Thread.currentThread().interrupt(); } catch (Throwable throwable) { - logger.error("unknown throwable happened in process capsule loop", throwable); + logger.error("Unknown throwable happened in process capsule loop.", throwable); } } }; @@ -305,10 +305,11 @@ public class Manager { filterCapsule.processFilterTrigger(); } } catch (InterruptedException e) { - logger.error("filterProcessLoop get InterruptedException, error is {}", e.getMessage()); + logger.error("FilterProcessLoop get InterruptedException, error is {}.", + e.getMessage()); Thread.currentThread().interrupt(); } catch (Throwable throwable) { - logger.error("unknown throwable happened in filterProcessLoop: ", throwable); + logger.error("Unknown throwable happened in filterProcessLoop. ", throwable); } } }; @@ -473,9 +474,9 @@ public void init() { Args.getInstance().getOutputDirectory()); System.exit(1); } catch (BadItemException e) { - logger.error("DB data broken! {}", e); + logger.error("DB data broken {}.", e.getMessage()); logger.error( - "Please delete database directory({}) and restart", + "Please delete database directory({}) and restart.", Args.getInstance().getOutputDirectory()); System.exit(1); } @@ -508,9 +509,9 @@ public void init() { initLiteNode(); long headNum = chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber(); - logger.info("current headNum is: {}", headNum); + logger.info("Current headNum is: {}.", headNum); int nodeType = chainBaseManager.getCommonStore().getNodeType(); - logger.info("node type is: {}", Constant.NODE_TYPE_LIGHT_NODE == nodeType ? "lite" : "full"); + logger.info("Node type is: {}.", Constant.NODE_TYPE_LIGHT_NODE == nodeType ? "lite" : "full"); revokingStore.enable(); validateSignService = Executors .newFixedThreadPool(Args.getInstance().getValidateSignThreadNum()); @@ -548,7 +549,7 @@ public void init() { } if (CommonParameter.getInstance().getShutdownBlockHeight() < headNum) { - logger.info("ShutDownBlockHeight {} is less than headNum {},ignored.", + logger.info("ShutDownBlockHeight {} is less than headNum {}, ignored.", CommonParameter.getInstance().getShutdownBlockHeight(), headNum); CommonParameter.getInstance().setShutdownBlockHeight(-1); } @@ -568,17 +569,17 @@ public void initGenesis() { } else { if (chainBaseManager.hasBlocks()) { logger.error( - "genesis block modify, please delete database directory({}) and restart", + "Genesis block modify, please delete database directory({}) and restart.", Args.getInstance().getOutputDirectory()); System.exit(1); } else { - logger.info("create genesis block"); + logger.info("Create genesis block."); Args.getInstance().setChainId(genesisBlock.getBlockId().toString()); chainBaseManager.getBlockStore().put(genesisBlock.getBlockId().getBytes(), genesisBlock); chainBaseManager.getBlockIndexStore().put(genesisBlock.getBlockId()); - logger.info(SAVE_BLOCK + genesisBlock); + logger.info(SAVE_BLOCK, genesisBlock); // init Dynamic Properties Store chainBaseManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(0); chainBaseManager.getDynamicPropertiesStore().saveLatestBlockHeaderHash( @@ -704,8 +705,7 @@ void validateTapos(TransactionCapsule transactionCapsule) throws TaposException ByteArray.toLong(refBlockNumBytes), Hex.toHexString(refBlockHash), Hex.toHexString(blockHash), chainBaseManager.getSolidBlockId().getString(), - chainBaseManager.getHeadBlockId().getString()).toString(); - logger.info(str); + chainBaseManager.getHeadBlockId().getString()); throw new TaposException(str); } } catch (ItemNotFoundException e) { @@ -713,8 +713,7 @@ void validateTapos(TransactionCapsule transactionCapsule) throws TaposException .format("Tapos failed, block not found, ref block %s, %s , solid block %s head block %s", ByteArray.toLong(refBlockNumBytes), Hex.toHexString(refBlockHash), chainBaseManager.getSolidBlockId().getString(), - chainBaseManager.getHeadBlockId().getString()).toString(); - logger.info(str); + chainBaseManager.getHeadBlockId().getString()); throw new TaposException(str); } } @@ -722,23 +721,24 @@ void validateTapos(TransactionCapsule transactionCapsule) throws TaposException void validateCommon(TransactionCapsule transactionCapsule) throws TransactionExpirationException, TooBigTransactionException { if (transactionCapsule.getData().length > Constant.TRANSACTION_MAX_BYTE_SIZE) { - throw new TooBigTransactionException( - "too big transaction, the size is " + transactionCapsule.getData().length + " bytes"); + throw new TooBigTransactionException(String.format( + "Too big transaction, the size is %d bytes", transactionCapsule.getData().length)); } long transactionExpiration = transactionCapsule.getExpiration(); long headBlockTime = chainBaseManager.getHeadBlockTimeStamp(); if (transactionExpiration <= headBlockTime || transactionExpiration > headBlockTime + Constant.MAXIMUM_TIME_UNTIL_EXPIRATION) { throw new TransactionExpirationException( - "transaction expiration, transaction expiration time is " + transactionExpiration - + ", but headBlockTime is " + headBlockTime); + String.format( + "Transaction expiration, transaction expiration time is %d, but headBlockTime is %d", + transactionExpiration, headBlockTime)); } } void validateDup(TransactionCapsule transactionCapsule) throws DupTransactionException { if (containsTransaction(transactionCapsule)) { - logger.debug(ByteArray.toHexString(transactionCapsule.getTransactionId().getBytes())); - throw new DupTransactionException("dup trans"); + throw new DupTransactionException(String.format("dup trans : %s ", + transactionCapsule.getTransactionId())); } } @@ -777,7 +777,8 @@ public boolean pushTransaction(final TransactionCapsule trx) try { if (!trx.validateSignature(chainBaseManager.getAccountStore(), chainBaseManager.getDynamicPropertiesStore())) { - throw new ValidateSignatureException("trans sig validate failed"); + throw new ValidateSignatureException(String.format("trans sig validate failed, id: %s", + trx.getTransactionId())); } synchronized (transactionLock) { @@ -790,7 +791,7 @@ public boolean pushTransaction(final TransactionCapsule trx) } } catch (InterruptedException e) { Thread.currentThread().interrupt(); - logger.debug("the wait has been interrupted"); + logger.debug("The wait has been interrupted."); } } synchronized (this) { @@ -845,7 +846,8 @@ public void consumeMultiSignFee(TransactionCapsule trx, TransactionTrace trace) } } catch (BalanceInsufficientException e) { throw new AccountResourceInsufficientException( - "Account Insufficient balance[" + fee + "] to MultiSign"); + String.format("account %s insufficient balance[%d] to multiSign", + StringUtil.encode58Check(address), fee)); } } @@ -869,10 +871,10 @@ public void eraseBlock() { try { BlockCapsule oldHeadBlock = chainBaseManager.getBlockById( getDynamicPropertiesStore().getLatestBlockHeaderHash()); - logger.info("start to erase block:" + oldHeadBlock); + logger.info("Start to erase block: {}.", oldHeadBlock); khaosDb.pop(); revokingStore.fastPop(); - logger.info("end to erase block:" + oldHeadBlock); + logger.info("End to erase block: {}.", oldHeadBlock); oldHeadBlock.getTransactions().forEach(tc -> poppedTransactions.add(new TransactionCapsule(tc.getInstance()))); Metrics.gaugeInc(MetricKeys.Gauge.MANAGER_QUEUE, oldHeadBlock.getTransactions().size(), @@ -893,7 +895,7 @@ public void pushVerifiedBlock(BlockCapsule block) throws ContractValidateExcepti block.generatedByMyself = true; long start = System.currentTimeMillis(); pushBlock(block); - logger.info("push block cost:{}ms, blockNum:{}, blockHash:{}, trx count:{}", + logger.info("Push block cost: {} ms, blockNum: {}, blockHash: {}, trx count: {}.", System.currentTimeMillis() - start, block.getNum(), block.getBlockId(), @@ -960,7 +962,7 @@ private void switchFork(BlockCapsule newHead) Metrics.counterInc(MetricKeys.Counter.BLOCK_FORK, 1, MetricLabels.FAIL); MetricsUtil.meterMark(MetricsKey.BLOCKCHAIN_FAIL_FORK_COUNT); logger.info( - "this is not the most recent common ancestor, " + "This is not the most recent common ancestor, " + "need to remove all blocks in the fork chain."); BlockCapsule tmp = newHead; while (tmp != null) { @@ -1011,9 +1013,7 @@ private void switchFork(BlockCapsule newHead) if (exception != null) { Metrics.counterInc(MetricKeys.Counter.BLOCK_FORK, 1, MetricLabels.FAIL); MetricsUtil.meterMark(MetricsKey.BLOCKCHAIN_FAIL_FORK_COUNT); - logger.warn("switch back because exception thrown while switching forks. " + exception - .getMessage(), - exception); + logger.warn("Switch back because exception thrown while switching forks.", exception); first.forEach(khaosBlock -> khaosDb.removeBlk(khaosBlock.getBlk().getBlockId())); khaosDb.setHead(binaryTree.getValue().peekFirst()); @@ -1124,12 +1124,10 @@ public void pushBlock(final BlockCapsule block) if (!block.generatedByMyself) { if (!block.calcMerkleRoot().equals(block.getMerkleRoot())) { - logger.warn( - "The merkle root doesn't match, Calc result is " - + block.calcMerkleRoot() - + " , the headers is " - + block.getMerkleRoot()); - throw new BadBlockException("The merkle hash is not validated"); + logger.warn("Num: {}, the merkle root doesn't match, expect is {} , actual is {}.", + block.getNum(), block.getMerkleRoot(), block.calcMerkleRoot()); + throw new BadBlockException(String.format("The merkle hash is not validated for %d", + block.getNum())); } consensus.receiveBlock(block); } @@ -1138,7 +1136,8 @@ public void pushBlock(final BlockCapsule block) .filter(tran -> isShieldedTransaction(tran.getInstance())) .count() > SHIELDED_TRANS_IN_BLOCK_COUNTS) { throw new BadBlockException( - "shielded transaction count > " + SHIELDED_TRANS_IN_BLOCK_COUNTS); + String.format("num: %d, shielded transaction count > %d", + block.getNum(), SHIELDED_TRANS_IN_BLOCK_COUNTS)); } BlockCapsule newBlock; @@ -1146,8 +1145,8 @@ public void pushBlock(final BlockCapsule block) newBlock = this.khaosDb.push(block); } catch (UnLinkedBlockException e) { logger.error( - "latestBlockHeaderHash:{}, latestBlockHeaderNumber:{}" - + ", latestSolidifiedBlockNum:{}", + "LatestBlockHeaderHash: {}, latestBlockHeaderNumber: {}" + + ", latestSolidifiedBlockNum: {}.", getDynamicPropertiesStore().getLatestBlockHeaderHash(), getDynamicPropertiesStore().getLatestBlockHeaderNumber(), getDynamicPropertiesStore().getLatestSolidifiedBlockNum()); @@ -1168,55 +1167,35 @@ public void pushBlock(final BlockCapsule block) if (!newBlock .getParentHash() .equals(getDynamicPropertiesStore().getLatestBlockHeaderHash())) { - logger.warn( - "switch fork! new head num = {}, block id = {}", - newBlock.getNum(), - newBlock.getBlockId()); + logger.warn("Switch fork! new head num = {}, block id = {}.", + newBlock.getNum(), newBlock.getBlockId()); logger.warn( - "******** before switchFork ******* push block: " - + block.toString() - + ", new block:" - + newBlock.toString() - + ", dynamic head num: " - + chainBaseManager.getDynamicPropertiesStore() - .getLatestBlockHeaderNumber() - + ", dynamic head hash: " - + chainBaseManager.getDynamicPropertiesStore() - .getLatestBlockHeaderHash() - + ", dynamic head timestamp: " - + chainBaseManager.getDynamicPropertiesStore() - .getLatestBlockHeaderTimestamp() - + ", khaosDb head: " - + khaosDb.getHead() - + ", khaosDb miniStore size: " - + khaosDb.getMiniStore().size() - + ", khaosDb unlinkMiniStore size: " - + khaosDb.getMiniUnlinkedStore().size()); + "******** Before switchFork ******* push block: {}, new block: {}, " + + "dynamic head num: {}, dynamic head hash: {}, " + + "dynamic head timestamp: {}, khaosDb head: {}, " + + "khaosDb miniStore size: {}, khaosDb unlinkMiniStore size: {}.", + block, newBlock, + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber(), + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderHash(), + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(), + khaosDb.getHead(), khaosDb.getMiniStore().size(), + khaosDb.getMiniUnlinkedStore().size()); switchFork(newBlock); - logger.info(SAVE_BLOCK + newBlock); + logger.info(SAVE_BLOCK, newBlock); logger.warn( - "******** after switchFork ******* push block: " - + block.toString() - + ", new block:" - + newBlock.toString() - + ", dynamic head num: " - + chainBaseManager.getDynamicPropertiesStore() - .getLatestBlockHeaderNumber() - + ", dynamic head hash: " - + chainBaseManager.getDynamicPropertiesStore() - .getLatestBlockHeaderHash() - + ", dynamic head timestamp: " - + chainBaseManager.getDynamicPropertiesStore() - .getLatestBlockHeaderTimestamp() - + ", khaosDb head: " - + khaosDb.getHead() - + ", khaosDb miniStore size: " - + khaosDb.getMiniStore().size() - + ", khaosDb unlinkMiniStore size: " - + khaosDb.getMiniUnlinkedStore().size()); + "******** After switchFork ******* push block: {}, new block: {}, " + + "dynamic head num: {}, dynamic head hash: {}, " + + "dynamic head timestamp: {}, khaosDb head: {}, " + + "khaosDb miniStore size: {}, khaosDb unlinkMiniStore size: {}.", + block, newBlock, + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber(), + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderHash(), + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(), + khaosDb.getHead(), khaosDb.getMiniStore().size(), + khaosDb.getMiniUnlinkedStore().size()); return; } @@ -1238,7 +1217,7 @@ public void pushBlock(final BlockCapsule block) throw throwable; } } - logger.info(SAVE_BLOCK + newBlock); + logger.info(SAVE_BLOCK, newBlock); } //clear ownerAddressSet if (CollectionUtils.isNotEmpty(ownerAddressSet)) { @@ -1256,7 +1235,7 @@ public void pushBlock(final BlockCapsule block) long cost = System.currentTimeMillis() - start; MetricsUtil.meterMark(MetricsKey.BLOCKCHAIN_BLOCK_PROCESS_TIME, cost); - logger.info("pushBlock block number:{}, cost/txs:{}/{} {}", + logger.info("PushBlock block number: {}, cost/txs: {}/{} {}.", block.getNum(), cost, block.getTransactions().size(), cost > 1000); Metrics.histogramObserve(timer); @@ -1299,7 +1278,7 @@ public LinkedList getBlockChainHashesOnFork(final BlockId forkBlockHash LinkedList blockCapsules = branch.getValue(); if (blockCapsules.isEmpty()) { - logger.info("empty branch {}", forkBlockHash); + logger.info("Empty branch {}.", forkBlockHash); return Lists.newLinkedList(); } @@ -1325,7 +1304,7 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block return null; } Contract contract = trxCap.getInstance().getRawData().getContract(0); - + Sha256Hash txId = trxCap.getTransactionId(); final Histogram.Timer requestTimer = Metrics.histogramStartTimer( MetricKeys.Histogram.PROCESS_TRANSACTION_LATENCY, Objects.nonNull(blockCap) ? MetricLabels.BLOCK : MetricLabels.TRX, @@ -1342,14 +1321,17 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block if (trxCap.getInstance().getRawData().getContractList().size() != 1) { throw new ContractSizeNotEqualToOneException( - "act size should be exactly 1, this is extend feature"); + String.format( + "tx %s contract size should be exactly 1, this is extend feature ,actual :%d", + txId, trxCap.getInstance().getRawData().getContractList().size())); } validateDup(trxCap); if (!trxCap.validateSignature(chainBaseManager.getAccountStore(), chainBaseManager.getDynamicPropertiesStore())) { - throw new ValidateSignatureException("transaction signature validate failed"); + throw new ValidateSignatureException( + String.format(" %s transaction signature validate failed", txId)); } TransactionTrace trace = new TransactionTrace(trxCap, StoreFactory.getInstance(), @@ -1366,13 +1348,11 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block if (Objects.nonNull(blockCap)) { trace.setResult(); if (trace.checkNeedRetry()) { - String txId = Hex.toHexString(trxCap.getTransactionId().getBytes()); - logger.info("Retry for tx id: {}", txId); trace.init(blockCap, eventPluginLoaded); trace.checkIsConstant(); trace.exec(); trace.setResult(); - logger.info("Retry result when push:{}, for tx id: {}, tx resultCode in receipt: {}", + logger.info("Retry result when push: {}, for tx id: {}, tx resultCode in receipt: {}.", blockCap.hasWitnessSignature(), txId, trace.getReceipt().getResult()); } if (blockCap.hasWitnessSignature()) { @@ -1435,7 +1415,7 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { Metrics.histogramObserve(MetricKeys.Histogram.MINER_LATENCY, (System.currentTimeMillis() - blockTime) / Metrics.MILLISECONDS_PER_SECOND, address); long postponedTrxCount = 0; - logger.info("Generate block {} begin", chainBaseManager.getHeadBlockNum() + 1); + logger.info("Generate block {} begin.", chainBaseManager.getHeadBlockNum() + 1); BlockCapsule blockCapsule = new BlockCapsule(chainBaseManager.getHeadBlockNum() + 1, chainBaseManager.getHeadBlockId(), @@ -1451,7 +1431,7 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { AccountCapsule witnessAccount = getAccountStore() .get(miner.getWitnessAddress().toByteArray()); if (!Arrays.equals(privateKeyAddress, witnessAccount.getWitnessPermissionAddress())) { - logger.warn("Witness permission is wrong"); + logger.warn("Witness permission is wrong."); return null; } } @@ -1491,12 +1471,13 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { if (trx == null) { // transaction may be removed by rePushLoop. - logger.warn("Trx is null,fromPending:{},pending:{},repush:{}.", + logger.warn("Trx is null, fromPending: {}, pending: {}, repush: {}.", fromPending, pendingTransactions.size(), rePushTransactions.size()); continue; } if (System.currentTimeMillis() > timeout) { - logger.warn("Processing transaction time exceeds the producing time."); + logger.warn("Processing transaction time exceeds the producing time {}.", + System.currentTimeMillis()); break; } @@ -1536,8 +1517,8 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { transactionRetCapsule.addTransactionInfo(result); } } catch (Exception e) { - logger.error("Process trx {} failed when generating block: {}", trx.getTransactionId(), - e.getMessage()); + logger.error("Process trx {} failed when generating block {}, {}.", trx.getTransactionId(), + blockCapsule.getNum(), e.getMessage()); } } @@ -1545,8 +1526,8 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { session.reset(); - logger.info("Generate block {} success, trxs:{}, pendingCount: {}, rePushCount: {}," - + " postponedCount: {}", + logger.info("Generate block {} success, trxs: {}, pendingCount: {}, rePushCount: {}," + + " postponedCount: {}.", blockCapsule.getNum(), blockCapsule.getTransactions().size(), pendingTransactions.size(), rePushTransactions.size(), postponedTrxCount); @@ -1631,7 +1612,7 @@ private void processBlock(BlockCapsule block, List txs) try { preValidateTransactionSign(txs); } catch (InterruptedException e) { - logger.error("parallel check sign interrupted exception! block info: {}", block, e); + logger.error("Parallel check sign interrupted exception! block info: {}.", block, e); Thread.currentThread().interrupt(); } } @@ -1748,7 +1729,7 @@ private void postSolidityLogContractTrigger(Long blockNum, Long lastSolidityNum) triggerCapsule.setTriggerName(Trigger.SOLIDITYLOG_TRIGGER_NAME); EventPluginLoader.getInstance().postSolidityLogTrigger(triggerCapsule); } else { - logger.error("postSolidityLogContractTrigger txId={} not contains transaction", + logger.error("PostSolidityLogContractTrigger txId = {} not contains transaction.", triggerCapsule.getTransactionId()); } } @@ -1802,21 +1783,17 @@ public void updateRecentTransaction(BlockCapsule block) { public void updateFork(BlockCapsule block) { int blockVersion = block.getInstance().getBlockHeader().getRawData().getVersion(); if (blockVersion > ChainConstant.BLOCK_VERSION) { - logger.warn("newer block version found: " + blockVersion + ", YOU MUST UPGRADE java-tron!"); + logger.warn("Newer block version found: {}, YOU MUST UPGRADE java-tron!", blockVersion); } - chainBaseManager - .getForkController().update(block); + chainBaseManager.getForkController().update(block); } public long getSyncBeginNumber() { - logger.info("headNumber:" - + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber()); - logger.info( - "syncBeginNumber:" - + (chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() - - revokingStore.size())); - logger.info("solidBlockNumber:" - + chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum()); + logger.info("HeadNumber: {}, syncBeginNumber: {}, solidBlockNumber: {}.", + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber(), + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() + - revokingStore.size(), + chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum()); return chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() - revokingStore.size(); } @@ -1839,19 +1816,19 @@ public NullifierStore getNullifierStore() { } public void closeAllStore() { - logger.info("******** begin to close db ********"); + logger.info("******** Begin to close db. ********"); chainBaseManager.closeAllStore(); - logger.info("******** end to close db ********"); + logger.info("******** End to close db. ********"); } public void closeOneStore(ITronChainBase database) { - logger.info("******** begin to close " + database.getName() + " ********"); + logger.info("******** Begin to close {}. ********", database.getName()); try { database.close(); } catch (Exception e) { - logger.info("failed to close " + database.getName() + ". " + e); + logger.info("Failed to close {}.", database.getName(), e); } finally { - logger.info("******** end to close " + database.getName() + " ********"); + logger.info("******** End to close {}. ********", database.getName()); } } @@ -1902,17 +1879,17 @@ public void rePush(TransactionCapsule tx) { | AccountResourceInsufficientException | VMIllegalException e) { logger.debug(e.getMessage(), e); } catch (DupTransactionException e) { - logger.debug("pending manager: dup trans", e); + logger.debug("Pending manager: dup trans", e); } catch (TaposException e) { - logger.debug("pending manager: tapos exception", e); + logger.debug("Pending manager: tapos exception", e); } catch (TooBigTransactionException e) { - logger.debug("too big transaction"); + logger.debug("Pending manager: too big transaction", e); } catch (TransactionExpirationException e) { - logger.debug("expiration transaction"); + logger.debug("Pending manager: expiration transaction", e); } catch (ReceiptCheckErrException e) { - logger.debug("outOfSlotTime transaction"); + logger.debug("Pending manager: outOfSlotTime transaction", e); } catch (TooBigTransactionResultException e) { - logger.debug("too big transaction result"); + logger.debug("Pending manager: too big transaction result", e); } } @@ -1941,7 +1918,7 @@ private void startEventSubscribing() { .start(Args.getInstance().getEventPluginConfig()); if (!eventPluginLoaded) { - logger.error("failed to load eventPlugin"); + logger.error("Failed to load eventPlugin."); } FilterQuery eventFilter = Args.getInstance().getEventFilter(); @@ -1956,7 +1933,7 @@ private void startEventSubscribing() { private void postSolidityFilter(final long oldSolidNum, final long latestSolidifiedBlockNumber) { if (oldSolidNum >= latestSolidifiedBlockNumber) { - logger.warn("post solidity filter failed, oldSolidity: {} >= latestSolidity: {}", + logger.warn("Post solidity filter failed, oldSolidity: {} >= latestSolidity: {}.", oldSolidNum, latestSolidifiedBlockNumber); return; } @@ -1965,7 +1942,7 @@ private void postSolidityFilter(final long oldSolidNum, final long latestSolidif try { blockCapsule = chainBaseManager.getBlockByNum(latestSolidifiedBlockNumber); } catch (Exception e) { - logger.error("postSolidityFilter getBlockByNum={} except, {}", + logger.error("PostSolidityFilter getBlockByNum = {} except, {}.", latestSolidifiedBlockNumber, e.getMessage()); return; } @@ -1996,14 +1973,14 @@ private void postSolidityTrigger(final long oldSolidNum, final long latestSolidi blockCapsule = chainBaseManager.getBlockByNum(latestSolidifiedBlockNumber); solidityTriggerCapsule.setTimeStamp(blockCapsule.getTimeStamp()); } catch (Exception e) { - logger.error("postSolidityTrigger getBlockByNum={} except, {}", + logger.error("PostSolidityTrigger getBlockByNum = {} except, {}.", latestSolidifiedBlockNumber, e.getMessage()); } boolean result = triggerCapsuleQueue.offer(solidityTriggerCapsule); if (!result) { - logger.info("too many trigger, lost solidified trigger, " - + "block number: {}", latestSolidifiedBlockNumber); + logger.info("Too many trigger, lost solidified trigger, block number: {}.", + latestSolidifiedBlockNumber); } } @@ -2032,7 +2009,7 @@ private void processTransactionTrigger(BlockCapsule newBlock) { transactionInfoList = transactionInfoListBuilder.build(); } } catch (BadItemException e) { - logger.error("postBlockTrigger getTransactionInfoList blockNum={}, error is {}", + logger.error("PostBlockTrigger getTransactionInfoList blockNum = {}, error is {}.", newBlock.getNum(), e.getMessage()); } @@ -2053,9 +2030,8 @@ private void processTransactionTrigger(BlockCapsule newBlock) { cumulativeLogCount += transactionInfo.getLogCount(); } } else { - logger.error("postBlockTrigger blockNum={} has no transactions or " - + "the sizes of transactionInfoList and transactionCapsuleList are not equal", - newBlock.getNum()); + logger.error("PostBlockTrigger blockNum = {} has no transactions or {}.", newBlock.getNum(), + "the sizes of transactionInfoList and transactionCapsuleList are not equal"); for (TransactionCapsule e : newBlock.getTransactions()) { postTransactionTrigger(e, newBlock); } @@ -2069,14 +2045,14 @@ private void processTransactionTrigger(BlockCapsule newBlock) { private void reOrgLogsFilter() { if (CommonParameter.getInstance().isJsonRpcHttpFullNodeEnable()) { - logger.info("switch fork occurred, post reOrgLogsFilter"); + logger.info("Switch fork occurred, post reOrgLogsFilter."); try { BlockCapsule oldHeadBlock = chainBaseManager.getBlockById( getDynamicPropertiesStore().getLatestBlockHeaderHash()); postLogsFilter(oldHeadBlock, false, true); } catch (BadItemException | ItemNotFoundException e) { - logger.error("block header hash does not exist or is bad: {}", + logger.error("Block header hash does not exist or is bad: {}.", getDynamicPropertiesStore().getLatestBlockHeaderHash()); } } @@ -2085,7 +2061,7 @@ private void reOrgLogsFilter() { private void postBlockFilter(final BlockCapsule blockCapsule, boolean solidified) { BlockFilterCapsule blockFilterCapsule = new BlockFilterCapsule(blockCapsule, solidified); if (!filterCapsuleQueue.offer(blockFilterCapsule)) { - logger.info("too many filters, block filter lost: {}", blockCapsule.getBlockId()); + logger.info("Too many filters, block filter lost: {}.", blockCapsule.getBlockId()); } } @@ -2103,7 +2079,7 @@ private void postLogsFilter(final BlockCapsule blockCapsule, boolean solidified, transactionInfoList.addAll(result.getInstance().getTransactioninfoList()); } } catch (BadItemException e) { - logger.error("processLogsFilter getTransactionInfoList blockNum={}, error is {}", + logger.error("ProcessLogsFilter getTransactionInfoList blockNum = {}, error is {}.", blockNumber, e.getMessage()); return; } @@ -2113,7 +2089,7 @@ private void postLogsFilter(final BlockCapsule blockCapsule, boolean solidified, solidified, removed); if (!filterCapsuleQueue.offer(logsFilterCapsule)) { - logger.info("too many filters, logs filter lost: {}", blockNumber); + logger.info("Too many filters, logs filter lost: {}.", blockNumber); } } } @@ -2135,7 +2111,7 @@ private void postBlockTrigger(final BlockCapsule blockCapsule) { newBlock = chainBaseManager .getBlockByNum(solidityBlkNum); } catch (Exception e) { - logger.error("postBlockTrigger getBlockByNum blkNum={} except, error is {}", + logger.error("PostBlockTrigger getBlockByNum blkNum = {} except, error is {}.", solidityBlkNum, e.getMessage()); } } @@ -2144,7 +2120,7 @@ private void postBlockTrigger(final BlockCapsule blockCapsule) { blockLogTriggerCapsule.setLatestSolidifiedBlockNumber(getDynamicPropertiesStore() .getLatestSolidifiedBlockNum()); if (!triggerCapsuleQueue.offer(blockLogTriggerCapsule)) { - logger.info("too many triggers, block trigger lost: {}", newBlock.getBlockId()); + logger.info("Too many triggers, block trigger lost: {}.", newBlock.getBlockId()); } } @@ -2156,7 +2132,7 @@ private void postBlockTrigger(final BlockCapsule blockCapsule) { try { newBlock = chainBaseManager.getBlockByNum(solidityBlkNum); } catch (Exception e) { - logger.error("postBlockTrigger getBlockByNum blkNum={} except, error is {}", + logger.error("PostBlockTrigger getBlockByNum blkNum = {} except, error is {}.", solidityBlkNum, e.getMessage()); } } else { @@ -2178,7 +2154,7 @@ private long postTransactionTrigger(final TransactionCapsule trxCap, trx.setLatestSolidifiedBlockNumber(getDynamicPropertiesStore() .getLatestSolidifiedBlockNum()); if (!triggerCapsuleQueue.offer(trx)) { - logger.info("too many triggers, transaction trigger lost: {}", trxCap.getTransactionId()); + logger.info("Too many triggers, transaction trigger lost: {}.", trxCap.getTransactionId()); } return trx.getTransactionLogTrigger().getEnergyUsageTotal(); @@ -2191,7 +2167,7 @@ private void postTransactionTrigger(final TransactionCapsule trxCap, trx.setLatestSolidifiedBlockNumber(getDynamicPropertiesStore() .getLatestSolidifiedBlockNum()); if (!triggerCapsuleQueue.offer(trx)) { - logger.info("too many triggers, transaction trigger lost: {}", trxCap.getTransactionId()); + logger.info("Too many triggers, transaction trigger lost: {}.", trxCap.getTransactionId()); } } @@ -2199,7 +2175,7 @@ private void reOrgContractTrigger() { if (eventPluginLoaded && (EventPluginLoader.getInstance().isContractEventTriggerEnable() || EventPluginLoader.getInstance().isContractLogTriggerEnable())) { - logger.info("switchfork occurred, post reOrgContractTrigger"); + logger.info("Switch fork occurred, post reOrgContractTrigger."); try { BlockCapsule oldHeadBlock = chainBaseManager.getBlockById( getDynamicPropertiesStore().getLatestBlockHeaderHash()); @@ -2207,7 +2183,7 @@ private void reOrgContractTrigger() { postContractTrigger(trx.getTrxTrace(), true, oldHeadBlock.getBlockId().toString()); } } catch (BadItemException | ItemNotFoundException e) { - logger.error("block header hash does not exist or is bad: {}", + logger.error("Block header hash does not exist or is bad: {}.", getDynamicPropertiesStore().getLatestBlockHeaderHash()); } } @@ -2231,7 +2207,7 @@ private void postContractTrigger(final TransactionTrace trace, boolean remove, S contractTriggerCapsule.setBlockHash(blockHash); if (!triggerCapsuleQueue.offer(contractTriggerCapsule)) { - logger.info("too many triggers, contract log trigger lost: {}", + logger.info("Too many triggers, contract log trigger lost: {}.", trigger.getTransactionId()); } } @@ -2301,7 +2277,7 @@ private void initLiteNode() { if (needInit) { // copy transaction from recent-transaction to trans - logger.info("load trans for lite node."); + logger.info("Load trans for lite node."); TransactionCapsule item = new TransactionCapsule(Transaction.newBuilder().build()); @@ -2324,7 +2300,7 @@ private void initLiteNode() { trx.getTransactionIds().forEach( tid -> chainBaseManager.getTransactionStore().put(Hex.decode(tid), item)); } - logger.info("load trans complete, trans:{},from={},to={}", + logger.info("Load trans complete, trans: {}, from = {}, to = {}.", transactionCount, minBlock, maxBlock); } } diff --git a/framework/src/main/java/org/tron/core/db/PendingManager.java b/framework/src/main/java/org/tron/core/db/PendingManager.java index 2098ed2178b..0a79d5401e4 100644 --- a/framework/src/main/java/org/tron/core/db/PendingManager.java +++ b/framework/src/main/java/org/tron/core/db/PendingManager.java @@ -34,7 +34,7 @@ public void close() { Metrics.counterInc(MetricKeys.Counter.TXS, 1, MetricLabels.Counter.TXS_FAIL, MetricLabels.Counter.TXS_FAIL_TIMEOUT); if (Args.getInstance().isOpenPrintLog()) { - logger.warn("[timeout] remove tx from repush, txId:{}", tx.getTransactionId()); + logger.warn("Timeout remove tx from repush, txId: {}.", tx.getTransactionId()); } } } @@ -54,7 +54,7 @@ public void close() { Metrics.gaugeSet(MetricKeys.Gauge.MANAGER_QUEUE, 0, MetricLabels.Gauge.QUEUE_POPPED); if (Args.getInstance().isOpenPrintLog()) { - logger.warn("pending tx size:{}", dbManager.getRePushTransactions().size()); + logger.info("Pending tx size: {}.", dbManager.getRePushTransactions().size()); } } @@ -69,7 +69,7 @@ private void txIteration(TransactionCapsule tx) { Metrics.counterInc(MetricKeys.Counter.TXS, 1, MetricLabels.Counter.TXS_FAIL, MetricLabels.Counter.TXS_FAIL_TIMEOUT); if (Args.getInstance().isOpenPrintLog()) { - logger.warn("[timeout] remove tx from pending, txId:{}", tx.getTransactionId()); + logger.warn("Timeout remove tx from pending, txId: {}.", tx.getTransactionId()); } } } catch (InterruptedException e) { diff --git a/framework/src/main/java/org/tron/core/db/accountstate/AccountStateEntity.java b/framework/src/main/java/org/tron/core/db/accountstate/AccountStateEntity.java index 15764bb84d1..361cef82c32 100644 --- a/framework/src/main/java/org/tron/core/db/accountstate/AccountStateEntity.java +++ b/framework/src/main/java/org/tron/core/db/accountstate/AccountStateEntity.java @@ -24,7 +24,7 @@ public static AccountStateEntity parse(byte[] data) { try { return new AccountStateEntity().setAccount(Account.parseFrom(data)); } catch (Exception e) { - logger.error("parse to AccountStateEntity error! reason: {}", e.getMessage()); + logger.error("Parse to AccountStateEntity error!", e); } return null; } diff --git a/framework/src/main/java/org/tron/core/db/accountstate/callback/AccountStateCallBack.java b/framework/src/main/java/org/tron/core/db/accountstate/callback/AccountStateCallBack.java index 37eda516196..dda7fe0726b 100644 --- a/framework/src/main/java/org/tron/core/db/accountstate/callback/AccountStateCallBack.java +++ b/framework/src/main/java/org/tron/core/db/accountstate/callback/AccountStateCallBack.java @@ -84,10 +84,10 @@ public void executePushFinish() throws BadBlockException { newRoot = Hash.EMPTY_TRIE_HASH; } if (!oldRoot.isEmpty() && !Arrays.equals(oldRoot.toByteArray(), newRoot)) { - logger.error("the accountStateRoot hash is error. {}, oldRoot: {}, newRoot: {}", - blockCapsule, ByteArray.toHexString(oldRoot.toByteArray()), - ByteArray.toHexString(newRoot)); - throw new BadBlockException("the accountStateRoot hash is error"); + throw new BadBlockException( + String.format("accountStateRoot hash is error, %s, oldRoot: %s, newRoot: %s.", + blockCapsule, + ByteArray.toHexString(oldRoot.toByteArray()), ByteArray.toHexString(newRoot))); } } diff --git a/framework/src/main/java/org/tron/core/db/backup/BackupDbUtil.java b/framework/src/main/java/org/tron/core/db/backup/BackupDbUtil.java index 2feaa9ae2b7..ecaeb19d004 100644 --- a/framework/src/main/java/org/tron/core/db/backup/BackupDbUtil.java +++ b/framework/src/main/java/org/tron/core/db/backup/BackupDbUtil.java @@ -15,7 +15,7 @@ import org.tron.core.db2.core.SnapshotManager; import org.tron.core.db2.core.SnapshotRoot; -@Slf4j +@Slf4j(topic = "DB") @Component public class BackupDbUtil { @@ -95,16 +95,16 @@ public void doBackup(BlockCapsule block) { deleteBackup(DB_BACKUP_INDEX2); break; default: - logger.warn("invalid backup state"); + logger.warn("invalid backup state {}.", getBackupState()); } } catch (RocksDBException | SecurityException e) { - logger.warn("backup db error:" + e); + logger.warn("Backup db error.", e); } long timeUsed = System.currentTimeMillis() - t1; logger - .info("current block number is {}, backup all store use {} ms!", block.getNum(), timeUsed); + .info("Current block number is {}, backup all store use {} ms!", block.getNum(), timeUsed); if (timeUsed >= 3000) { - logger.warn("backing up db uses too much time."); + logger.warn("Backing up db uses too much time. {} ms.", timeUsed); } } @@ -115,7 +115,7 @@ private void backup(int i) throws RocksDBException { } else if (i == DB_BACKUP_INDEX2) { path = parameter.getDbBackupConfig().getBak2path(); } else { - throw new RuntimeException("Error backup with undefined index"); + throw new RuntimeException(String.format("error backup with undefined index %d", i)); } List stores = ((SnapshotManager) db).getDbs(); for (Chainbase store : stores) { @@ -134,7 +134,7 @@ private void deleteBackup(int i) { } else if (i == DB_BACKUP_INDEX2) { path = parameter.getDbBackupConfig().getBak2path(); } else { - throw new RuntimeException("Error deleteBackup with undefined index"); + throw new RuntimeException(String.format("error deleteBackup with undefined index %d", i)); } List stores = ((SnapshotManager) db).getDbs(); for (Chainbase store : stores) { diff --git a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java index 4f2f3d46ec0..e66fafaa477 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java @@ -74,7 +74,7 @@ public class LiteFullNodeTool { * @param snapshotDir the path that stores the snapshot dataset */ public void generateSnapshot(String sourceDir, String snapshotDir) { - logger.info("start create snapshot."); + logger.info("Start create snapshot."); long start = System.currentTimeMillis(); snapshotDir = Paths.get(snapshotDir, SNAPSHOT_DIR_NAME).toString(); try { @@ -86,11 +86,11 @@ public void generateSnapshot(String sourceDir, String snapshotDir) { fillSnapshotBlockAndTransDb(sourceDir, snapshotDir); generateInfoProperties(Paths.get(snapshotDir, INFO_FILE_NAME).toString(), sourceDir); } catch (IOException | RocksDBException e) { - logger.error("create snapshot failed, " + e.getMessage()); + logger.error("Create snapshot failed, {}.", e.getMessage()); return; } long end = System.currentTimeMillis(); - logger.info("create snapshot finished, take {}s.", (end - start) / 1000); + logger.info("Create snapshot finished, take {} s.\n", (end - start) / 1000); } /** @@ -101,7 +101,7 @@ public void generateSnapshot(String sourceDir, String snapshotDir) { * @param historyDir the path that stores the history dataset */ public void generateHistory(String sourceDir, String historyDir) { - logger.info("start create history."); + logger.info("Start create history."); long start = System.currentTimeMillis(); historyDir = Paths.get(historyDir, HISTORY_DIR_NAME).toString(); try { @@ -114,11 +114,11 @@ public void generateHistory(String sourceDir, String historyDir) { mergeCheckpoint2History(sourceDir, historyDir); generateInfoProperties(Paths.get(historyDir, INFO_FILE_NAME).toString(), sourceDir); } catch (IOException | RocksDBException e) { - logger.error("create history failed, " + e.getMessage()); + logger.error("Create history failed, {}.", e.getMessage()); return; } long end = System.currentTimeMillis(); - logger.info("create history finished, take {}s.\n", (end - start) / 1000); + logger.info("Create history finished, take {} s.\n", (end - start) / 1000); } /** @@ -129,7 +129,7 @@ public void generateHistory(String sourceDir, String historyDir) { * @param databaseDir lite fullnode database path */ public void completeHistoryData(String historyDir, String databaseDir) { - logger.info("start merge history to lite fullnode."); + logger.info("Start merge history to lite node."); long start = System.currentTimeMillis(); BlockNumInfo blockNumInfo = null; try { @@ -153,11 +153,11 @@ public void completeHistoryData(String historyDir, String databaseDir) { // 6. delete snapshot flag deleteSnapshotFlag(databaseDir); } catch (IOException | RocksDBException | BadItemException e) { - logger.error("merge history data to database failed, " + e.getMessage()); + 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); + logger.info("Merge history finished, take {} s. \n", (end - start) / 1000); } private List getSnapshotDbs(String sourceDir) { @@ -180,22 +180,23 @@ private void mergeCheckpoint2History(String sourceDir, String destDir) { } private void split(String sourceDir, String destDir, List dbs) throws IOException { - logger.info("-- begin to split the dbs."); + logger.info("Begin to split the dbs."); if (!new File(sourceDir).isDirectory()) { - throw new RuntimeException("sourceDir must be a directory, sourceDir: " + sourceDir); + 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("destDir is already exist, please remove it first"); + throw new RuntimeException(String.format( + "destDir: %s is already exist, please remove it first", destDir)); } if (!destPath.mkdirs()) { - throw new RuntimeException("destDir create failed, please check"); + 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"); + logger.info("Begin to merge checkpoint to dataset."); try { DBInterface tmpDb = DbTool.getDB(sourceDir, CHECKPOINT_DB); try (DBIterator iterator = tmpDb.iterator()) { @@ -222,13 +223,13 @@ private void mergeCheckpoint(String sourceDir, String destDir, List dest private void generateInfoProperties(String propertyfile, String databaseDir) throws IOException, RocksDBException { - logger.info("-- create {} for dataset", INFO_FILE_NAME); + logger.info("Create {} for dataset.", INFO_FILE_NAME); if (!FileUtil.createFileIfNotExists(propertyfile)) { - throw new RuntimeException("create properties file failed..."); + 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..."); + throw new RuntimeException("Write properties file failed."); } } @@ -253,7 +254,7 @@ private long getLatestBlockHeaderNum(String databaseDir) throws IOException, Roc */ private void fillSnapshotBlockAndTransDb(String sourceDir, String snapshotDir) throws IOException, RocksDBException { - logger.info("-- begin to fill {} block , genesis block and trans to snapshot", RECENT_BLKS); + 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); @@ -314,14 +315,14 @@ private static byte[] simpleEncode(String s) { private BlockNumInfo checkAndGetBlockNumInfo(String historyDir, String databaseDir) throws IOException, RocksDBException { - logger.info("-- check the compatibility of this history"); + 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?"); + "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."); @@ -331,15 +332,17 @@ private BlockNumInfo checkAndGetBlockNumInfo(String historyDir, String databaseD long historyBlkNum = Long.parseLong(PropUtil.readProperty(historyInfo, Constant .SPLIT_BLOCK_NUM)); if (historyBlkNum < snapshotBlkNum) { - logger.error("history latest block number is lower than snapshot, history: {}, snapshot: {}", - historyBlkNum, snapshotBlkNum); - throw new RuntimeException("history latest block number is lower than snapshot."); + 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))) { - logger.error("genesis block hash is not equal, history: {}, database: {}", - getGenesisBlockHash(historyDir), getGenesisBlockHash(databaseDir)); - throw new RuntimeException("genesis block is not equal."); + 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); } @@ -347,22 +350,22 @@ private BlockNumInfo checkAndGetBlockNumInfo(String historyDir, String databaseD 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); + logger.info("Backup the archive dbs to {}.", bakDir); if (!FileUtil.createDirIfNotExists(bakDir)) { - throw new RuntimeException("create bak dir failed"); + 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"); + 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."); + 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); @@ -386,7 +389,7 @@ private void trimHistory(String databaseDir, BlockNumInfo blockNumInfo) 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); + logger.info("Begin to merge {} to database.", bakDir); for (String dbName : archiveDbs) { DBInterface bakDb = DbTool.getDB(bakDir, dbName); DBInterface destDb = DbTool.getDB(databaseDir, dbName); @@ -431,14 +434,14 @@ private static boolean isEmptyBytes(byte[] b) { } private void deleteSnapshotFlag(String databaseDir) throws IOException, RocksDBException { - logger.info("-- delete the info file."); + logger.info("Delete the info file from {}.", databaseDir); Files.delete(Paths.get(databaseDir, INFO_FILE_NAME)); if (!isLite(databaseDir)) { DBInterface destCommonDb = DbTool.getDB(databaseDir, COMMON_DB_NAME); destCommonDb.delete(DB_KEY_NODE_TYPE); destCommonDb.delete(DB_KEY_LOWEST_BLOCK_NUM); - logger.info("-- deleted node_type and lowest_block_num from " - + "common to identify this node is a real fullnode."); + logger.info("Deleted {} and {} from {} to identify this node is a real fullnode.", + "node_type", "lowest_block_num", COMMON_DB_NAME); } } diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java index a62c6bbefb9..1b261fd8b98 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java @@ -271,7 +271,9 @@ public void testCheckOrInitEngine() { try { dataSource.initDB(); } catch (Exception e) { - Assert.assertTrue(e.getMessage().contains("Failed to")); + Assert.assertEquals(String.format("failed to check database: %s, engine do not match", + "test_engine"), + e.getMessage()); } Assert.assertNull(dataSource.getDatabase()); PropUtil.writeProperty(enginePath, "ENGINE", "ROCKSDB"); diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index 4407f4572aa..3812c2335c5 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -298,7 +298,8 @@ public void adjustBalanceTest() { Assert.assertTrue(false); } catch (BalanceInsufficientException e) { Assert.assertEquals( - StringUtil.createReadableString(account.createDbKey()) + " insufficient balance", + StringUtil.createReadableString(account.createDbKey()) + " insufficient balance" + + ", balance: " + account.getBalance() + ", amount: " + 40, e.getMessage()); } @@ -354,7 +355,8 @@ public void adjustAssetBalanceV2Test() { } catch (BalanceInsufficientException e) { Assert.assertTrue(e instanceof BalanceInsufficientException); Assert.assertEquals( - "reduceAssetAmount failed !", e.getMessage()); + "reduceAssetAmount failed! account: " + StringUtil.encode58Check(account.createDbKey()), + e.getMessage()); } account.setBalance(30); @@ -389,7 +391,8 @@ public void pushBlockInvalidMerkelRoot() { Assert.assertTrue(false); } catch (BadBlockException e) { Assert.assertTrue(e instanceof BadBlockException); - Assert.assertEquals("The merkle hash is not validated", e.getMessage()); + Assert.assertEquals("The merkle hash is not validated for " + + blockCapsule2.getNum(), e.getMessage()); } catch (Exception e) { Assert.assertFalse(e instanceof Exception); } @@ -403,7 +406,7 @@ public void adjustTotalShieldPoolValueTest() { Assert.assertTrue(false); } catch (BalanceInsufficientException e) { Assert.assertTrue(e instanceof BalanceInsufficientException); - Assert.assertEquals("Total shielded pool value can not below 0", e.getMessage()); + Assert.assertEquals("total shielded pool value can not below 0, actual: -1", e.getMessage()); } long beforeTotalShieldValue = chainManager.getDynamicPropertiesStore() @@ -444,7 +447,8 @@ public void pushBlockTooMuchShieldedTransactions() { Assert.assertTrue(false); } catch (BadBlockException e) { Assert.assertTrue(e instanceof BadBlockException); - Assert.assertEquals("shielded transaction count > " + SHIELDED_TRANS_IN_BLOCK_COUNTS, + Assert.assertEquals("num: " + blockCapsule2.getNum() + + ", shielded transaction count > " + SHIELDED_TRANS_IN_BLOCK_COUNTS, e.getMessage()); } catch (Exception e) { Assert.assertFalse(e instanceof Exception); From e09095c07ed025564033bd8352e136efb83cc3ab Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 22 Aug 2022 11:58:35 +0800 Subject: [PATCH 0240/1197] feat(toolkit): integrate manifestArchive into toolkit 1. integrate manifestArchive into toolkit 2. use toolkit.jar for leveldb to manifest archiving --- .../org/tron/plugins/ArchiveManifest.java | 5 + .../src/main/java/org/tron/plugins/Db.java | 2 +- .../main/java/org/tron/plugins/DbArchive.java | 248 ++++++++++++++++++ .../java/org/tron/plugins/DbArchiveTest.java | 135 ++++++++++ 4 files changed, 389 insertions(+), 1 deletion(-) create mode 100644 plugins/src/main/java/org/tron/plugins/DbArchive.java create mode 100644 plugins/src/test/java/org/tron/plugins/DbArchiveTest.java diff --git a/plugins/src/main/java/org/tron/plugins/ArchiveManifest.java b/plugins/src/main/java/org/tron/plugins/ArchiveManifest.java index 5771323138f..144d0c45579 100644 --- a/plugins/src/main/java/org/tron/plugins/ArchiveManifest.java +++ b/plugins/src/main/java/org/tron/plugins/ArchiveManifest.java @@ -108,6 +108,11 @@ public static int run(String[] args) { return 404; } + if (!dbDirectory.isDirectory()) { + logger.info("{} is not directory.", parameters.databaseDirectory); + return 405; + } + List files = Arrays.stream(Objects.requireNonNull(dbDirectory.listFiles())) .filter(File::isDirectory).collect( Collectors.toList()); diff --git a/plugins/src/main/java/org/tron/plugins/Db.java b/plugins/src/main/java/org/tron/plugins/Db.java index e03a412c1a9..702f505b147 100644 --- a/plugins/src/main/java/org/tron/plugins/Db.java +++ b/plugins/src/main/java/org/tron/plugins/Db.java @@ -12,7 +12,7 @@ mixinStandardHelpOptions = true, version = "db command 1.0", description = "An rich command set that provides high-level operations for dbs.", - subcommands = {CommandLine.HelpCommand.class, DbMove.class}, + subcommands = {CommandLine.HelpCommand.class, DbMove.class, DbArchive.class}, commandListHeading = "%nCommands:%n%nThe most commonly used git commands are:%n" ) public class Db { diff --git a/plugins/src/main/java/org/tron/plugins/DbArchive.java b/plugins/src/main/java/org/tron/plugins/DbArchive.java new file mode 100644 index 00000000000..333098949fe --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/DbArchive.java @@ -0,0 +1,248 @@ +package org.tron.plugins; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.iq80.leveldb.impl.Iq80DBFactory.factory; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.Properties; +import java.util.concurrent.Callable; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import me.tongfei.progressbar.ProgressBar; +import org.iq80.leveldb.CompressionType; +import org.iq80.leveldb.DB; +import org.iq80.leveldb.Options; +import org.iq80.leveldb.impl.Filename; +import picocli.CommandLine; +import picocli.CommandLine.Option; + +@Slf4j(topic = "archive") +@CommandLine.Command(name = "archive", description = "a helper to rewrite leveldb manifest.") +public class DbArchive implements Callable { + + @CommandLine.Spec + CommandLine.Model.CommandSpec spec; + + @Option(names = {"-d", "--database-directory"}, + defaultValue = "output-directory/database", + description = "java-tron database directory. Default: ${DEFAULT-VALUE}") + private String databaseDirectory; + + @Option(names = {"-b", "--batch-size"}, + defaultValue = "80000", + description = "deal manifest batch size. Default: ${DEFAULT-VALUE}") + private int maxBatchSize; + + @Option(names = {"-m", "--manifest-size"}, + defaultValue = "0", + description = "manifest min size(M) to archive. Default: ${DEFAULT-VALUE}") + private int maxManifestSize; + + @Option(names = {"-h", "--help"}, help = true) + private boolean help; + + + @Override + public Integer call() throws Exception { + if (help) { + spec.commandLine().usage(System.out); + return 0; + } + + File dbDirectory = new File(databaseDirectory); + if (!dbDirectory.exists()) { + spec.commandLine().getErr().format("Directory %s does not exist.", + databaseDirectory).println(); + logger.info("Directory {} does not exist.", databaseDirectory); + return 404; + } + + if (!dbDirectory.isDirectory()) { + spec.commandLine().getErr().format(" %s is not directory.", + databaseDirectory).println(); + logger.info("{} is not directory.", databaseDirectory); + return 405; + } + + List files = Arrays.stream(Objects.requireNonNull(dbDirectory.listFiles())) + .filter(File::isDirectory).collect( + Collectors.toList()); + + if (files.isEmpty()) { + spec.commandLine().getErr().format("Directory %s does not contain any database.", + databaseDirectory).println(); + logger.info("Directory {} does not contain any database.", databaseDirectory); + return 0; + } + final long time = System.currentTimeMillis(); + List services = new ArrayList<>(); + files.forEach(f -> services.add(new ArchiveManifest(databaseDirectory, f.getName(), + maxManifestSize, maxBatchSize))); + ProgressBar.wrap(services.stream(), "archive task").parallel().forEach(Archive::doArchive); + spec.commandLine().getOut().println("archive db done."); + + logger.info("DatabaseDirectory:{}, maxManifestSize:{}, maxBatchSize:{}," + + "database reopen use {} seconds total.", + databaseDirectory, maxManifestSize, maxBatchSize, + (System.currentTimeMillis() - time) / 1000); + + return 0; + } + + + interface Archive { + + default void doArchive() { + + } + } + + static class ArchiveManifest implements Archive { + + private static final String KEY_ENGINE = "ENGINE"; + private static final String LEVELDB = "LEVELDB"; + + private final Path srcDbPath; + private final String name; + private final Options options; + private final long startTime; + + public ArchiveManifest(String src, String name, int maxManifestSize, int maxBatchSize) { + this.name = name; + this.srcDbPath = Paths.get(src, name); + this.startTime = System.currentTimeMillis(); + this.options = newDefaultLevelDbOptions(); + this.options.maxManifestSize(maxManifestSize); + this.options.maxBatchSize(maxBatchSize); + } + + public static Options newDefaultLevelDbOptions() { + Options dbOptions = new Options(); + dbOptions.createIfMissing(true); + dbOptions.paranoidChecks(true); + dbOptions.verifyChecksums(true); + dbOptions.compressionType(CompressionType.SNAPPY); + dbOptions.blockSize(4 * 1024); + dbOptions.writeBufferSize(10 * 1024 * 1024); + dbOptions.cacheSize(10 * 1024 * 1024L); + dbOptions.maxOpenFiles(1000); + dbOptions.maxBatchSize(64_000); + dbOptions.maxManifestSize(128); + return dbOptions; + } + + public void open() throws IOException { + DB database = factory.open(this.srcDbPath.toFile(), this.options); + database.close(); + } + + public boolean checkManifest(String dir) throws IOException { + // Read "CURRENT" file, which contains a pointer to the current manifest file + File currentFile = new File(dir, Filename.currentFileName()); + if (!currentFile.exists()) { + return false; + } + String currentName = com.google.common.io.Files.asCharSource(currentFile, UTF_8).read(); + if (currentName.isEmpty() || currentName.charAt(currentName.length() - 1) != '\n') { + return false; + } + currentName = currentName.substring(0, currentName.length() - 1); + File current = new File(dir, currentName); + if (!current.isFile()) { + return false; + } + long maxSize = options.maxManifestSize(); + if (maxSize < 0) { + return false; + } + logger.info("CurrentName {}/{},size {} kb.", dir, currentName, current.length() / 1024); + if ("market_pair_price_to_order".equalsIgnoreCase(this.name)) { + logger.info("Db {} ignored.", this.name); + return false; + } + return current.length() >= maxSize * 1024 * 1024; + } + + @Override + public void doArchive() { + File levelDbFile = srcDbPath.toFile(); + if (!levelDbFile.exists()) { + logger.info("File {},does not exist, ignored.", srcDbPath); + return; + } + if (!checkEngine()) { + logger.info("Db {},not leveldb, ignored.", this.name); + return; + } + try { + if (checkManifest(levelDbFile.toString())) { + open(); + logger.info("Db {} archive use {} ms.", this.name, + (System.currentTimeMillis() - startTime)); + } else { + logger.info("Db {},no need, ignored.", levelDbFile); + } + } catch (Exception e) { + throw new RuntimeException("Db " + this.name + " archive failed.", e); + } + } + + public boolean checkEngine() { + String dir = this.srcDbPath.toString(); + String enginePath = dir + File.separator + "engine.properties"; + if (!new File(enginePath).exists() && !writeProperty(enginePath, KEY_ENGINE, LEVELDB)) { + return false; + } + String engine = readProperty(enginePath, KEY_ENGINE); + return LEVELDB.equals(engine); + } + + public static String readProperty(String file, String key) { + try (FileInputStream fileInputStream = new FileInputStream(file); + InputStream inputStream = new BufferedInputStream(fileInputStream)) { + Properties prop = new Properties(); + prop.load(inputStream); + return new String(prop.getProperty(key, "").getBytes(StandardCharsets.ISO_8859_1), + UTF_8); + } catch (Exception e) { + logger.error("readProperty", e); + return ""; + } + } + + public static boolean writeProperty(String file, String key, String value) { + try (OutputStream out = new FileOutputStream(file); + FileInputStream fis = new FileInputStream(file); + BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out, UTF_8))) { + BufferedReader bf = new BufferedReader(new InputStreamReader(fis, UTF_8)); + Properties properties = new Properties(); + properties.load(bf); + properties.setProperty(key, value); + properties.store(bw, "Generated by the application. PLEASE DO NOT EDIT! "); + } catch (Exception e) { + logger.warn("writeProperty", e); + return false; + } + return true; + } + + } + +} \ No newline at end of file diff --git a/plugins/src/test/java/org/tron/plugins/DbArchiveTest.java b/plugins/src/test/java/org/tron/plugins/DbArchiveTest.java new file mode 100644 index 00000000000..10bed418764 --- /dev/null +++ b/plugins/src/test/java/org/tron/plugins/DbArchiveTest.java @@ -0,0 +1,135 @@ +package org.tron.plugins; + +import static org.iq80.leveldb.impl.Iq80DBFactory.factory; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Paths; +import java.util.Properties; +import java.util.UUID; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import picocli.CommandLine; + +@Slf4j +public class DbArchiveTest { + + private static final String OUTPUT_DIRECTORY = "output-directory/database/dbArchive"; + + private static final String ENGINE = "ENGINE"; + private static final String LEVELDB = "LEVELDB"; + private static final String ROCKSDB = "ROCKSDB"; + private static final String ACCOUNT = "account"; + private static final String ACCOUNT_ROCKSDB = "account-rocksdb"; + private static final String MARKET = "market_pair_price_to_order"; + private static final String ENGINE_FILE = "engine.properties"; + + @BeforeClass + public static void init() throws IOException { + File file = new File(OUTPUT_DIRECTORY,ACCOUNT); + factory.open(file,ArchiveManifest.newDefaultLevelDbOptions()).close(); + writeProperty(file.toString() + File.separator + ENGINE_FILE,ENGINE,LEVELDB); + + file = new File(OUTPUT_DIRECTORY,MARKET); + factory.open(file,ArchiveManifest.newDefaultLevelDbOptions()).close(); + writeProperty(file.toString() + File.separator + ENGINE_FILE,ENGINE,LEVELDB); + + file = new File(OUTPUT_DIRECTORY,ACCOUNT_ROCKSDB); + factory.open(file,ArchiveManifest.newDefaultLevelDbOptions()).close(); + writeProperty(file.toString() + File.separator + ENGINE_FILE,ENGINE,ROCKSDB); + + } + + @AfterClass + public static void destroy() { + deleteDir(new File(OUTPUT_DIRECTORY)); + } + + @Test + public void testRun() { + String[] args = new String[] {"db", "archive", "-d", OUTPUT_DIRECTORY }; + CommandLine cli = new CommandLine(new Toolkit()); + Assert.assertEquals(0, cli.execute(args)); + } + + @Test + public void testHelp() { + String[] args = new String[] {"db", "archive", "-h"}; + CommandLine cli = new CommandLine(new Toolkit()); + Assert.assertEquals(0, cli.execute(args)); + } + + @Test + public void testMaxManifest() { + String[] args = new String[] {"db", "archive", "-d", OUTPUT_DIRECTORY, "-m", "128"}; + CommandLine cli = new CommandLine(new Toolkit()); + Assert.assertEquals(0, cli.execute(args)); + } + + @Test + public void testNotExist() { + String[] args = new String[] {"db", "archive", "-d", + OUTPUT_DIRECTORY + File.separator + UUID.randomUUID()}; + CommandLine cli = new CommandLine(new Toolkit()); + Assert.assertEquals(404, cli.execute(args)); + } + + @Test + public void testEmpty() { + File file = new File(OUTPUT_DIRECTORY + File.separator + UUID.randomUUID()); + file.mkdirs(); + file.deleteOnExit(); + String[] args = new String[] {"db", "archive", "-d", file.toString()}; + CommandLine cli = new CommandLine(new Toolkit()); + Assert.assertEquals(0, cli.execute(args)); + } + + private static void writeProperty(String filename, String key, String value) throws IOException { + File file = new File(filename); + if (!file.exists()) { + file.createNewFile(); + } + + try (FileInputStream fis = new FileInputStream(file); + OutputStream out = new FileOutputStream(file); + BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out, + StandardCharsets.UTF_8))) { + BufferedReader bf = new BufferedReader(new InputStreamReader(fis, StandardCharsets.UTF_8)); + Properties properties = new Properties(); + properties.load(bf); + properties.setProperty(key, value); + properties.store(bw, "Generated by the application. PLEASE DO NOT EDIT! "); + } catch (Exception e) { + logger.warn("{}", e); + } + } + + /** + * delete directory. + */ + private static boolean deleteDir(File dir) { + if (dir.isDirectory()) { + String[] children = dir.list(); + assert children != null; + for (String child : children) { + boolean success = deleteDir(new File(dir, child)); + if (!success) { + logger.warn("can't delete dir:" + dir); + return false; + } + } + } + return dir.delete(); + } +} From 5f2950106a455c868cffeed348cb01ade300416a Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 7 Sep 2022 19:18:36 +0800 Subject: [PATCH 0241/1197] refactor(net): when multi master occurs, the master with bigger blockId is elected to produce block --- .../org/tron/consensus/dpos/StateManager.java | 10 +++-- .../overlay/discover/table/NodeEntryTest.java | 43 +++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/consensus/src/main/java/org/tron/consensus/dpos/StateManager.java b/consensus/src/main/java/org/tron/consensus/dpos/StateManager.java index df74b64fec8..6e73d928904 100644 --- a/consensus/src/main/java/org/tron/consensus/dpos/StateManager.java +++ b/consensus/src/main/java/org/tron/consensus/dpos/StateManager.java @@ -90,12 +90,14 @@ public void receiveBlock(BlockCapsule blockCapsule) { return; } - if (dupBlockCount.get() == 0) { - dupBlockCount.set(new Random().nextInt(10)); - } else { - dupBlockCount.set(10); + //multi master occurs. If currentBlockId is bigger, we continue to produce block at next cycle. + if (null != currentBlockId + && currentBlockId.toString().compareTo(blockCapsule.getBlockId().toString()) > 0) { + return; } + //currentBlockId is smaller, we may pause one cycle + dupBlockCount.set(1); dupBlockTime.set(System.currentTimeMillis()); logger.warn("Dup block produced: {}", blockCapsule); diff --git a/framework/src/test/java/org/tron/common/overlay/discover/table/NodeEntryTest.java b/framework/src/test/java/org/tron/common/overlay/discover/table/NodeEntryTest.java index 1a47dfd0e7e..f30b02d3953 100644 --- a/framework/src/test/java/org/tron/common/overlay/discover/table/NodeEntryTest.java +++ b/framework/src/test/java/org/tron/common/overlay/discover/table/NodeEntryTest.java @@ -3,6 +3,7 @@ import org.junit.Assert; import org.junit.Test; import org.tron.common.overlay.discover.node.Node; +import org.tron.common.utils.ByteArray; public class NodeEntryTest { @@ -23,4 +24,46 @@ public void test() throws InterruptedException { Assert.assertTrue(isDif); } + @Test + public void testDistance() { + byte[] randomId = Node.getNodeId(); + String hexRandomIdStr = ByteArray.toHexString(randomId); + Assert.assertEquals(128, hexRandomIdStr.length()); + + byte[] nodeId1 = ByteArray.fromHexString( + "0000000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000000"); + byte[] nodeId2 = ByteArray.fromHexString( + "a000000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000000"); + Assert.assertEquals(256, NodeEntry.distance(nodeId1, nodeId2)); + + byte[] nodeId3 = ByteArray.fromHexString( + "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000000000000000000000"); + Assert.assertEquals(1, NodeEntry.distance(nodeId1, nodeId3)); + + byte[] nodeId4 = ByteArray.fromHexString( + "0000000000000000000000000000000000000000000000000000000000000000" + + "8000000000000000000000000000000000000000000000000000000000000000"); + Assert.assertEquals(0, NodeEntry.distance(nodeId1, nodeId4)); // => 0 + + byte[] nodeId5 = ByteArray.fromHexString( + "0000000000000000000000000000000000000000000000000000000000000000" + + "4000000000000000000000000000000000000000000000000000000000000000"); + Assert.assertEquals(-1, NodeEntry.distance(nodeId1, nodeId5)); // => 0 + + byte[] nodeId6 = ByteArray.fromHexString( + "0000000000000000000000000000000000000000000000000000000000000000" + + "2000000000000000000000000000000000000000000000000000000000000000"); + Assert.assertEquals(-2, NodeEntry.distance(nodeId1, nodeId6)); // => 0 + + byte[] nodeId7 = ByteArray.fromHexString( + "0000000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000001"); + Assert.assertEquals(-255, NodeEntry.distance(nodeId1, nodeId7)); // => 0 + + Assert.assertEquals(-256, NodeEntry.distance(nodeId1, nodeId1)); // => 0 + } + } From a3102a18566e962cf5dd3f6ec8da7446b2f6a4d4 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 8 Sep 2022 12:03:06 +0800 Subject: [PATCH 0242/1197] remove comment --- .../src/main/java/org/tron/consensus/dpos/StateManager.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/consensus/src/main/java/org/tron/consensus/dpos/StateManager.java b/consensus/src/main/java/org/tron/consensus/dpos/StateManager.java index 6e73d928904..19d1f88a243 100644 --- a/consensus/src/main/java/org/tron/consensus/dpos/StateManager.java +++ b/consensus/src/main/java/org/tron/consensus/dpos/StateManager.java @@ -90,13 +90,11 @@ public void receiveBlock(BlockCapsule blockCapsule) { return; } - //multi master occurs. If currentBlockId is bigger, we continue to produce block at next cycle. if (null != currentBlockId && currentBlockId.toString().compareTo(blockCapsule.getBlockId().toString()) > 0) { return; } - //currentBlockId is smaller, we may pause one cycle dupBlockCount.set(1); dupBlockTime.set(System.currentTimeMillis()); From f092a06ccc13394e400ff99fe0306f8ea192f3da Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 9 Sep 2022 14:43:46 +0800 Subject: [PATCH 0243/1197] reactor(log): enrich log printing 1. add essential info for insufficient exception --- .../main/java/org/tron/core/actuator/TransferActuator.java | 3 +++ .../core/exception/AccountResourceInsufficientException.java | 4 ---- .../src/main/java/org/tron/core/db/BandwidthProcessor.java | 5 ++++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/TransferActuator.java b/actuator/src/main/java/org/tron/core/actuator/TransferActuator.java index 94fef0b5c12..5e3d605aed7 100755 --- a/actuator/src/main/java/org/tron/core/actuator/TransferActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/TransferActuator.java @@ -9,6 +9,7 @@ import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.Commons; import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.ContractCapsule; import org.tron.core.capsule.TransactionResultCapsule; @@ -156,6 +157,8 @@ public boolean validate() throws ContractValidateException { } if (balance < Math.addExact(amount, fee)) { + logger.warn("Balance is not sufficient. Account: {}, balance: {}, amount: {}, fee: {}.", + StringUtil.encode58Check(ownerAddress), balance, amount, fee); throw new ContractValidateException( "Validate TransferContract error, balance is not sufficient."); } diff --git a/common/src/main/java/org/tron/core/exception/AccountResourceInsufficientException.java b/common/src/main/java/org/tron/core/exception/AccountResourceInsufficientException.java index 1318680d463..ba2807e10ab 100644 --- a/common/src/main/java/org/tron/core/exception/AccountResourceInsufficientException.java +++ b/common/src/main/java/org/tron/core/exception/AccountResourceInsufficientException.java @@ -2,10 +2,6 @@ public class AccountResourceInsufficientException extends TronException { - public AccountResourceInsufficientException() { - super("Insufficient bandwidth and balance to create new account"); - } - public AccountResourceInsufficientException(String message) { super(message); } diff --git a/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java b/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java index 92500285f88..64405a69f69 100644 --- a/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -172,7 +172,10 @@ private void consumeForCreateNewAccount(AccountCapsule accountCapsule, long byte if (!ret) { ret = consumeFeeForCreateNewAccount(accountCapsule, trace); if (!ret) { - throw new AccountResourceInsufficientException(); + throw new AccountResourceInsufficientException(String.format( + "account [%s] has insufficient bandwidth[%d] and balance[%d] to create new account", + StringUtil.encode58Check(accountCapsule.createDbKey()), bytes, + chainBaseManager.getDynamicPropertiesStore().getCreateAccountFee())); } } } From 4081f7b40455945f6a1f627df511bf81f094bd8c Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Tue, 13 Sep 2022 17:47:51 +0800 Subject: [PATCH 0244/1197] feat: catch IllegalArgumentException when decode base58 address for GetRewardServlet and GetBrokerageServlet --- .../main/java/org/tron/core/services/http/GetRewardServlet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/http/GetRewardServlet.java b/framework/src/main/java/org/tron/core/services/http/GetRewardServlet.java index 14d6f11770d..c4d97f46c57 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetRewardServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetRewardServlet.java @@ -25,7 +25,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { value = manager.getMortgageService().queryReward(address); } response.getWriter().println("{\"reward\": " + value + "}"); - } catch (DecoderException e) { + } catch (DecoderException | IllegalArgumentException e) { try { response.getWriter() .println("{\"Error\": " + "\"INVALID address, " + e.getMessage() + "\"}"); From 00d3bfb2e6fb484420a40de1d517a75936f60f59 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Tue, 13 Sep 2022 18:05:40 +0800 Subject: [PATCH 0245/1197] feat: add check for GetBrokerageServlet --- .../org/tron/core/services/http/GetBrokerageServlet.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/framework/src/main/java/org/tron/core/services/http/GetBrokerageServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBrokerageServlet.java index f36764d6489..1fbd94fe690 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBrokerageServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBrokerageServlet.java @@ -1,8 +1,10 @@ package org.tron.core.services.http; +import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.DecoderException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.core.db.Manager; @@ -24,6 +26,13 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { value = manager.getDelegationStore().getBrokerage(cycle, address); } response.getWriter().println("{\"brokerage\": " + value + "}"); + } catch (DecoderException | IllegalArgumentException e) { + try { + response.getWriter() + .println("{\"Error\": " + "\"INVALID address, " + e.getMessage() + "\"}"); + } catch (IOException ioe) { + logger.debug("IOException: {}", ioe.getMessage()); + } } catch (Exception e) { Util.processError(e, response); } From 0d1b6a813400b3248d5b5586873f1721e080da2a Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Wed, 14 Sep 2022 15:05:06 +0800 Subject: [PATCH 0246/1197] feat: catch JSONException in packTransaction --- framework/src/main/java/org/tron/core/services/http/Util.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 1a4f738a334..7500c685de4 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONException; import com.alibaba.fastjson.JSONObject; import com.google.protobuf.Any; import com.google.protobuf.ByteString; @@ -292,6 +293,8 @@ public static Transaction packTransaction(String strTransaction, boolean selfTyp logger.debug("ParseException: {}", e.getMessage()); } catch (ClassCastException e) { logger.debug("ClassCastException: {}", e.getMessage()); + } catch (JSONException e) { + logger.debug("JSONException: {}", e.getMessage()); } catch (Exception e) { logger.error("", e); } From 2d563eb2f3059b86a92fb8f60672412219718e02 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 14 Sep 2022 19:05:39 +0800 Subject: [PATCH 0247/1197] reactor(liteFullNodeTool): refactor code 1. optimize exception handling 2. extract common method --- .../tool/litefullnode/LiteFullNodeTool.java | 44 +++++++------------ 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java index 4f2f3d46ec0..3e42904b958 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java @@ -446,38 +446,28 @@ private void deleteSnapshotFlag(String databaseDir) throws IOException, RocksDBE private void hasEnoughBlock(String sourceDir) throws RocksDBException, IOException { // check latest long latest = getLatestBlockHeaderNum(sourceDir); - // check first, not 0; - long first = 0; - DBInterface sourceBlockIndexDb = DbTool.getDB(sourceDir, BLOCK_INDEX_DB_NAME); - DBIterator iterator = sourceBlockIndexDb.iterator(); - iterator.seekToFirst(); - if (iterator.hasNext()) { - iterator.next(); - if (iterator.hasNext()) { - first = Longs.fromByteArray(iterator.getKey()); - } - } - - if (latest - first + 1 < RECENT_BLKS) { + // 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, first)); + RECENT_BLKS, latest, second)); } } private boolean isLite(String databaseDir) throws RocksDBException, IOException { - DBInterface sourceDb = DbTool.getDB(databaseDir, BLOCK_INDEX_DB_NAME); - DBInterface checkpointDb = DbTool.getDB(databaseDir, CHECKPOINT_DB); - byte[] key = ByteArray.fromLong(1); - byte[] valueFromTmp = checkpointDb.get(Bytes.concat(simpleEncode(BLOCK_INDEX_DB_NAME), key)); - byte[] value; - if (isEmptyBytes(valueFromTmp)) { - value = sourceDb.get(key); - } else { - value = valueFromTmp.length == 1 - ? null : Arrays.copyOfRange(valueFromTmp, 1, valueFromTmp.length); + 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 isEmptyBytes(value); + return num; } @VisibleForTesting @@ -534,8 +524,8 @@ public static void main(String[] args) { } else { tool.run(argv); } - } catch (ParameterException parameterException) { - logger.error(parameterException.toString()); + } catch (Exception e) { + logger.error(e.getMessage()); jct.usage(); } } From f158f7c34b64767a0f2901b3ec21e4c3af53d03b Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 14 Sep 2022 19:53:37 +0800 Subject: [PATCH 0248/1197] refactor(db): recover the previous exception handling strategy 1. delete the exception throwing --- .../storage/leveldb/LevelDbDataSourceImpl.java | 2 +- .../java/org/tron/common/utils/ForkController.java | 2 +- .../src/main/java/org/tron/core/db/BlockStore.java | 3 ++- .../core/db/accountstate/AccountStateEntity.java | 5 +++-- .../core/db/common/iterator/RockStoreIterator.java | 7 ++++++- .../core/db/common/iterator/StoreIterator.java | 2 +- .../org/tron/core/db2/core/SnapshotManager.java | 14 ++++++++++++-- .../core/db/accountstate/AccountStateEntity.java | 5 +++-- 8 files changed, 29 insertions(+), 11 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java index 9cc0561a53c..e4ba36a84f9 100644 --- a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java @@ -128,7 +128,7 @@ public void initDB() { private void openDatabase(Options dbOptions) throws IOException { final Path dbPath = getDbPath(); if (dbPath == null || dbPath.getParent() == null) { - throw new IOException(String.format("db path is illegal, %s/%s", parentPath, dataBaseName)); + return; } if (!Files.isSymbolicLink(dbPath.getParent())) { Files.createDirectories(dbPath.getParent()); diff --git a/chainbase/src/main/java/org/tron/common/utils/ForkController.java b/chainbase/src/main/java/org/tron/common/utils/ForkController.java index 27ce4d95dc3..db4d77fd809 100644 --- a/chainbase/src/main/java/org/tron/common/utils/ForkController.java +++ b/chainbase/src/main/java/org/tron/common/utils/ForkController.java @@ -167,7 +167,7 @@ public synchronized void update(BlockCapsule blockCapsule) { stats[slot] = VERSION_UPGRADE; manager.getDynamicPropertiesStore().statsByVersion(version, stats); logger.info( - "******* Update hard fork: {}, witness size: {}, solt: {}, witness: {}, version: {}.", + "Update hard fork: {}, witness size: {}, solt: {}, witness: {}, version: {}.", Streams.zip(witnesses.stream(), Stream.of(ArrayUtils.toObject(stats)), Maps::immutableEntry) .map(e -> Maps .immutableEntry(encode58Check(e.getKey().toByteArray()), e.getValue())) diff --git a/chainbase/src/main/java/org/tron/core/db/BlockStore.java b/chainbase/src/main/java/org/tron/core/db/BlockStore.java index f2fdb5d247c..9198b1c5198 100644 --- a/chainbase/src/main/java/org/tron/core/db/BlockStore.java +++ b/chainbase/src/main/java/org/tron/core/db/BlockStore.java @@ -53,7 +53,8 @@ private List pack(Set values) { try { blocks.add(new BlockCapsule(bytes)); } catch (BadItemException e) { - throw new TronDBException(e); + logger.error("Find bad item: {}", e.getMessage()); + // throw new TronDBException(e); } } blocks.sort(Comparator.comparing(BlockCapsule::getNum)); diff --git a/chainbase/src/main/java/org/tron/core/db/accountstate/AccountStateEntity.java b/chainbase/src/main/java/org/tron/core/db/accountstate/AccountStateEntity.java index 9b5601002f0..d52eb7a0af2 100644 --- a/chainbase/src/main/java/org/tron/core/db/accountstate/AccountStateEntity.java +++ b/chainbase/src/main/java/org/tron/core/db/accountstate/AccountStateEntity.java @@ -1,5 +1,6 @@ package org.tron.core.db.accountstate; +import com.google.protobuf.InvalidProtocolBufferException; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.StringUtil; import org.tron.protos.Protocol.Account; @@ -24,8 +25,8 @@ public AccountStateEntity(Account account) { public static AccountStateEntity parse(byte[] data) { try { return new AccountStateEntity().setAccount(Account.parseFrom(data)); - } catch (Exception e) { - logger.error("Parse to AccountStateEntity error!", e); + } catch (InvalidProtocolBufferException e) { + logger.error("Parse to AccountStateEntity error! reason: {}", e.getMessage()); } return null; } diff --git a/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java b/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java index 8bf2a022600..a31ebca9409 100644 --- a/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java +++ b/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java @@ -36,7 +36,12 @@ public boolean hasNext() { dbIterator.close(); } } catch (Exception e) { - throw new TronDBException(e); + logger.error(e.getMessage(), e); + try { + dbIterator.close(); + } catch (Exception e1) { + logger.error(e.getMessage(), e); + } } return hasNext; } diff --git a/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java b/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java index a0929616a4b..74fe4a70ed0 100755 --- a/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java +++ b/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java @@ -35,7 +35,7 @@ public boolean hasNext() { dbIterator.close(); } } catch (Exception e) { - throw new TronDBException(e); + logger.error(e.getMessage(), e); } return hasNext; diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java index 477631ab507..d05b2d67468 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java @@ -473,7 +473,7 @@ public void destroy() { snapshotManager.revoke(); } } catch (Exception e) { - throw new RevokingStoreIllegalStateException(e); + logger.error("Revoke database error.", e); } if (disableOnExit) { snapshotManager.disable(); @@ -482,7 +482,17 @@ public void destroy() { @Override public void close() { - destroy(); + try { + if (applySnapshot) { + snapshotManager.revoke(); + } + } catch (Exception e) { + logger.error("Revoke database error.", e); + throw new RevokingStoreIllegalStateException(e); + } + if (disableOnExit) { + snapshotManager.disable(); + } } } diff --git a/framework/src/main/java/org/tron/core/db/accountstate/AccountStateEntity.java b/framework/src/main/java/org/tron/core/db/accountstate/AccountStateEntity.java index 361cef82c32..6a7307f477d 100644 --- a/framework/src/main/java/org/tron/core/db/accountstate/AccountStateEntity.java +++ b/framework/src/main/java/org/tron/core/db/accountstate/AccountStateEntity.java @@ -1,5 +1,6 @@ package org.tron.core.db.accountstate; +import com.google.protobuf.InvalidProtocolBufferException; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.StringUtil; import org.tron.protos.Protocol.Account; @@ -23,8 +24,8 @@ public AccountStateEntity(Account account) { public static AccountStateEntity parse(byte[] data) { try { return new AccountStateEntity().setAccount(Account.parseFrom(data)); - } catch (Exception e) { - logger.error("Parse to AccountStateEntity error!", e); + } catch (InvalidProtocolBufferException e) { + logger.error("Parse to AccountStateEntity error! reason: {}", e.getMessage()); } return null; } From 402a954d62292d80e3f9c2700d97b105f8ac534b Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Thu, 15 Sep 2022 11:47:14 +0800 Subject: [PATCH 0249/1197] feat(freezeV2): separate delegate resources from the freeze --- protocol/src/main/protos/core/Tron.proto | 15 +++++---------- .../protos/core/contract/balance_contract.proto | 16 ++++++++++++++-- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 3d1e2330ce8..ba0e7d1b414 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -2,6 +2,7 @@ syntax = "proto3"; import "google/protobuf/any.proto"; import "core/Discover.proto"; +import "core/contract/common.proto"; package protocol; @@ -215,20 +216,12 @@ message Account { Permission witness_permission = 32; repeated Permission active_permission = 33; - // FREEZE_TYPE is extended ResourceCode of the common package. - enum FREEZE_TYPE { - BANDWIDTH = 0; - ENERGY = 1; - POWER = 2; - DELEGATED_BANDWIDTH = 3; - DELEGATED_ENERGY = 4; - } message FreezeV2 { - FREEZE_TYPE type = 1; + ResourceCode type = 1; int64 amount = 2; } message UnFreezeV2 { - FREEZE_TYPE type = 1; + ResourceCode type = 1; int64 unfreeze_amount = 3; int64 unfreeze_expire_time = 4; } @@ -369,6 +362,8 @@ message Transaction { FreezeBalanceV2Contract = 54; UnfreezeBalanceV2Contract = 55; WithdrawBalanceV2Contract = 56; + DelegateResourceContract = 57; + UnDelegateResourceContract = 58; } ContractType type = 1; google.protobuf.Any parameter = 2; diff --git a/protocol/src/main/protos/core/contract/balance_contract.proto b/protocol/src/main/protos/core/contract/balance_contract.proto index 795f17a9d0b..db54939a3d4 100644 --- a/protocol/src/main/protos/core/contract/balance_contract.proto +++ b/protocol/src/main/protos/core/contract/balance_contract.proto @@ -85,16 +85,28 @@ message FreezeBalanceV2Contract { bytes owner_address = 1; int64 frozen_balance = 2; ResourceCode resource = 3; - bytes receiver_address = 4; } message UnfreezeBalanceV2Contract { bytes owner_address = 1; int64 unfreeze_balance = 2; ResourceCode resource = 3; - bytes receiver_address = 4; } message WithdrawBalanceV2Contract { bytes owner_address = 1; +} + +message DelegateResourceContract { + bytes owner_address = 1; + ResourceCode resource = 2; + int64 balance = 3; + bytes receiver_address = 4; +} + +message UnDelegateResourceContract { + bytes owner_address = 1; + ResourceCode resource = 2; + int64 balance = 3; + bytes receiver_address = 4; } \ No newline at end of file From 4c55c006e33fce2005d99b0502e129b6e68284af Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Thu, 15 Sep 2022 12:26:08 +0800 Subject: [PATCH 0250/1197] feat: check json object if null when get string --- .../src/main/java/org/tron/core/services/http/Util.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 7500c685de4..2fef8ff1425 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -496,8 +496,10 @@ public static byte[] getAddress(HttpServletRequest request) throws Exception { String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); - JSONObject jsonObject = JSONObject.parseObject(input); - addressStr = jsonObject.getString(addressParam); + JSONObject jsonObject = JSON.parseObject(input); + if (jsonObject != null) { + addressStr = jsonObject.getString(addressParam); + } } if (StringUtils.isNotBlank(addressStr)) { if (StringUtils.startsWith(addressStr, Constant.ADD_PRE_FIX_STRING_MAINNET)) { From 41f1c6efb0ca504b09c28b427c27756cec77827d Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Thu, 15 Sep 2022 14:33:10 +0800 Subject: [PATCH 0251/1197] feat: catch ClassCastException instead of Exception --- .../java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index c9e7534184b..55bb167e771 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -731,7 +731,7 @@ public String getCall(CallArguments transactionCall, Object blockParamObj) if (paramMap.containsKey("blockNumber")) { try { blockNumOrTag = paramMap.get("blockNumber"); - } catch (Exception e) { + } catch (ClassCastException e) { throw new JsonRpcInvalidRequestException(JSON_ERROR); } @@ -749,7 +749,7 @@ public String getCall(CallArguments transactionCall, Object blockParamObj) } else if (paramMap.containsKey("blockHash")) { try { blockNumOrTag = paramMap.get("blockHash"); - } catch (Exception e) { + } catch (ClassCastException e) { throw new JsonRpcInvalidRequestException(JSON_ERROR); } From 25094fe223f7a229b6ab4e8ab0edfd27e69ebaf7 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Thu, 15 Sep 2022 16:08:26 +0800 Subject: [PATCH 0252/1197] test: modify check nonce of blockresult --- .../test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java index 8ac70c4661e..143f257d85a 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java @@ -1,6 +1,5 @@ package org.tron.core.jsonrpc; -import com.google.protobuf.Any; import com.google.protobuf.ByteString; import java.io.File; import lombok.extern.slf4j.Slf4j; @@ -230,8 +229,7 @@ public void testGetBlockByNumber() { Assert.assertEquals(ByteArray.toJsonHex(blockCapsule.getNum()), blockResult.getNumber()); Assert .assertEquals(blockCapsule.getTransactions().size(), blockResult.getTransactions().length); - Assert.assertNull(blockResult.getNonce()); - + Assert.assertEquals("0x0000000000000000", blockResult.getNonce()); } From 34764e325d3f47aabe38e6093d8e850e0dc3cfcd Mon Sep 17 00:00:00 2001 From: guoquanwu Date: Mon, 29 Aug 2022 16:38:48 +0800 Subject: [PATCH 0253/1197] feat(db): add checkpoint v2 in case db inconsistent when ungraceful shutdown --- .../leveldb/LevelDbDataSourceImpl.java | 8 +- .../java/org/tron/core/db/TronDatabase.java | 17 +- .../tron/core/db2/core/SnapshotManager.java | 194 ++++++++++++++---- .../tron/core/store/CheckPointV2Store.java | 48 +++++ .../org/tron/core/store/CheckTmpStore.java | 1 - .../org/tron/core/config/args/Storage.java | 25 +++ .../common/application/ApplicationImpl.java | 1 + .../java/org/tron/core/config/args/Args.java | 5 + .../tool/litefullnode/LiteFullNodeTool.java | 87 +++++--- .../src/main/resources/config-localtest.conf | 3 +- framework/src/main/resources/config.conf | 4 +- .../org/tron/common/utils/PublicMethod.java | 105 ++++++++++ .../org/tron/core/db2/CheckpointV2Test.java | 106 ++++++++++ .../tron/core/db2/SnapshotManagerTest.java | 18 ++ .../tron/program/LiteFullNodeToolTest.java | 110 ++-------- 15 files changed, 560 insertions(+), 172 deletions(-) create mode 100644 chainbase/src/main/java/org/tron/core/store/CheckPointV2Store.java create mode 100644 framework/src/test/java/org/tron/common/utils/PublicMethod.java create mode 100644 framework/src/test/java/org/tron/core/db2/CheckpointV2Test.java diff --git a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java index 9cc0561a53c..7ed5a770799 100644 --- a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java @@ -135,9 +135,11 @@ private void openDatabase(Options dbOptions) throws IOException { } try { database = factory.open(dbPath.toFile(), dbOptions); - logger.info("DB {} open success with writeBufferSize {} M, cacheSize {} M, maxOpenFiles {}.", - this.getDBName(), dbOptions.writeBufferSize() / 1024 / 1024, - dbOptions.cacheSize() / 1024 / 1024, dbOptions.maxOpenFiles()); + if (!this.getDBName().startsWith("checkpoint")) { + logger.info("DB {} open success with writeBufferSize {} M, cacheSize {} M, maxOpenFiles {}.", + this.getDBName(), dbOptions.writeBufferSize() / 1024 / 1024, + dbOptions.cacheSize() / 1024 / 1024, dbOptions.maxOpenFiles()); + } } catch (IOException e) { if (e.getMessage().contains("Corruption:")) { logger.warn("DB {} corruption detected, try to repair it.", this.getDBName()); diff --git a/chainbase/src/main/java/org/tron/core/db/TronDatabase.java b/chainbase/src/main/java/org/tron/core/db/TronDatabase.java index 9373189941a..04e20af4fd6 100644 --- a/chainbase/src/main/java/org/tron/core/db/TronDatabase.java +++ b/chainbase/src/main/java/org/tron/core/db/TronDatabase.java @@ -2,7 +2,6 @@ import com.google.protobuf.InvalidProtocolBufferException; import java.nio.file.Paths; -import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; @@ -10,6 +9,7 @@ import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.iq80.leveldb.WriteOptions; +import org.rocksdb.DirectComparator; import org.springframework.beans.factory.annotation.Autowired; import org.tron.common.parameter.CommonParameter; import org.tron.common.storage.WriteOptionsWrapper; @@ -18,11 +18,8 @@ import org.tron.common.storage.rocksdb.RocksDbDataSourceImpl; import org.tron.common.utils.StorageUtils; import org.tron.core.db.common.DbSourceInter; -import org.tron.core.db2.common.LevelDB; -import org.tron.core.db2.common.RocksDB; import org.tron.core.db2.common.WrappedByteArray; import org.tron.core.db2.core.ITronChainBase; -import org.tron.core.db2.core.SnapshotRoot; import org.tron.core.exception.BadItemException; import org.tron.core.exception.ItemNotFoundException; @@ -46,7 +43,7 @@ protected TronDatabase(String dbName) { dbSource = new LevelDbDataSourceImpl(StorageUtils.getOutputDirectoryByDbName(dbName), dbName, - StorageUtils.getOptionsByDbName(dbName), + getOptionsByDbNameForLevelDB(dbName), new WriteOptions().sync(CommonParameter.getInstance() .getStorage().isDbSync())); } else if ("ROCKSDB".equals(CommonParameter.getInstance() @@ -55,7 +52,7 @@ protected TronDatabase(String dbName) { CommonParameter.getInstance().getStorage().getDbDirectory()).toString(); dbSource = new RocksDbDataSourceImpl(parentName, dbName, CommonParameter.getInstance() - .getRocksDBCustomSettings()); + .getRocksDBCustomSettings(), getDirectComparator()); } dbSource.initDB(); @@ -69,6 +66,14 @@ private void init() { protected TronDatabase() { } + protected org.iq80.leveldb.Options getOptionsByDbNameForLevelDB(String dbName) { + return StorageUtils.getOptionsByDbName(dbName); + } + + protected DirectComparator getDirectComparator() { + return null; + } + public DbSourceInter getDbSource() { return dbSource; } diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java index 477631ab507..d9040865775 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java @@ -7,6 +7,9 @@ import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; + +import java.io.File; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -15,10 +18,13 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.LockSupport; import java.util.stream.Collectors; import javax.annotation.PostConstruct; + import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @@ -26,7 +32,10 @@ import org.tron.common.error.TronDBException; import org.tron.common.parameter.CommonParameter; import org.tron.common.storage.WriteOptionsWrapper; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.StorageUtils; import org.tron.core.db.RevokingDatabase; +import org.tron.core.db.TronDatabase; import org.tron.core.db2.ISession; import org.tron.core.db2.common.DB; import org.tron.core.db2.common.IRevokingDB; @@ -34,6 +43,7 @@ import org.tron.core.db2.common.Value; import org.tron.core.db2.common.WrappedByteArray; import org.tron.core.exception.RevokingStoreIllegalStateException; +import org.tron.core.store.CheckPointV2Store; import org.tron.core.store.CheckTmpStore; @Slf4j(topic = "DB") @@ -42,6 +52,8 @@ public class SnapshotManager implements RevokingDatabase { public static final int DEFAULT_MAX_FLUSH_COUNT = 500; public static final int DEFAULT_MIN_FLUSH_COUNT = 1; private static final int DEFAULT_STACK_MAX_SIZE = 256; + private static final long ONE_MINUTE_MILLS = 60*1000L; + private static final String CHECKPOINT_V2_DIR = "checkpoint"; @Getter private List dbs = new ArrayList<>(); @Getter @@ -63,6 +75,8 @@ public class SnapshotManager implements RevokingDatabase { private Map flushServices = new HashMap<>(); + private ScheduledExecutorService pruneCheckpointThread = null; + @Autowired @Setter @Getter @@ -71,11 +85,27 @@ public class SnapshotManager implements RevokingDatabase { @Setter private volatile int maxFlushCount = DEFAULT_MIN_FLUSH_COUNT; + private int checkpointVersion = 1; // default v1 + public SnapshotManager(String checkpointPath) { } @PostConstruct public void init() { + checkpointVersion = CommonParameter.getInstance().getStorage().getCheckpointVersion(); + // prune checkpoint + if (isV2Open()) { + pruneCheckpointThread = Executors.newSingleThreadScheduledExecutor(); + pruneCheckpointThread.scheduleWithFixedDelay(() -> { + try { + if (!unChecked) { + pruneCheckpoint(); + } + } catch (Throwable t) { + logger.error("Exception in prune checkpoint", t); + } + }, 10000, 3600, TimeUnit.MILLISECONDS); + } exitThread = new Thread(() -> { LockSupport.park(); // to Guarantee Some other thread invokes unpark with the current thread as the target @@ -246,6 +276,9 @@ public void shutdown() { logger.info("******** Before revokingDb size: {}.", size); checkTmpStore.close(); logger.info("******** End to pop revokingDb. ********"); + if (pruneCheckpointThread != null) { + pruneCheckpointThread.shutdown(); + } } public void updateSolidity(int hops) { @@ -309,8 +342,11 @@ public void flush() { if (shouldBeRefreshed()) { try { long start = System.currentTimeMillis(); - deleteCheckpoint(); + if (!isV2Open()) { + deleteCheckpoint(); + } createCheckpoint(); + long checkPointEnd = System.currentTimeMillis(); refresh(); flushCount = 0; @@ -328,6 +364,8 @@ public void flush() { } private void createCheckpoint() { + TronDatabase checkPointStore = null; + boolean syncFlag; try { Map batch = new HashMap<>(); for (Chainbase db : dbs) { @@ -350,70 +388,148 @@ private void createCheckpoint() { } } } + if (isV2Open()) { + String dbName = String.valueOf(System.currentTimeMillis()); + checkPointStore = getCheckpointDB(dbName); + syncFlag = CommonParameter.getInstance().getStorage().isCheckpointSync(); + } else { + checkPointStore = checkTmpStore; + syncFlag = CommonParameter.getInstance().getStorage().isDbSync(); + } - checkTmpStore.getDbSource().updateByBatch(batch.entrySet().stream() + checkPointStore.getDbSource().updateByBatch(batch.entrySet().stream() .map(e -> Maps.immutableEntry(e.getKey().getBytes(), e.getValue().getBytes())) .collect(HashMap::new, (m, k) -> m.put(k.getKey(), k.getValue()), HashMap::putAll), - WriteOptionsWrapper.getInstance().sync(CommonParameter - .getInstance().getStorage().isDbSync())); + WriteOptionsWrapper.getInstance().sync(syncFlag)); - } catch ( Exception e) { + } catch (Exception e) { throw new TronDBException(e); + } finally { + if (isV2Open() && checkPointStore != null) { + checkPointStore.close(); + } } } - private void deleteCheckpoint() { - try { - Map hmap = new HashMap<>(); - if (!checkTmpStore.getDbSource().allKeys().isEmpty()) { - for (Map.Entry e : checkTmpStore.getDbSource()) { - hmap.put(e.getKey(), null); - } + private TronDatabase getCheckpointDB(String dbName) { + return new CheckPointV2Store(CHECKPOINT_V2_DIR+"/"+dbName); + } + + private List getCheckpointList() { + String dbPath = Paths.get(StorageUtils.getOutputDirectoryByDbName(CHECKPOINT_V2_DIR), + CommonParameter.getInstance().getStorage().getDbDirectory()).toString(); + File file = new File(Paths.get(dbPath, CHECKPOINT_V2_DIR).toString()); + if (file.exists() && file.isDirectory()) { + String[] subDirs = file.list(); + if (subDirs != null) { + return Arrays.stream(subDirs).sorted().collect(Collectors.toList()); } + } + return null; + } - checkTmpStore.getDbSource().updateByBatch(hmap); - } catch (Exception e) { - throw new TronDBException(e); + private void deleteCheckpoint() { + checkTmpStore.reset(); + } + + private void pruneCheckpoint() { + if (unChecked) { + return; + } + List cpList = getCheckpointList(); + if (cpList == null) { + return; + } + if (cpList.size() < 3) { + return; + } + for (String cp: cpList.subList(0, cpList.size()-3)) { + long timestamp = Long.parseLong(cp); + if (System.currentTimeMillis() - timestamp < ONE_MINUTE_MILLS*2) { + break; + } + String checkpointPath = Paths.get(StorageUtils.getOutputDirectoryByDbName(CHECKPOINT_V2_DIR), + CommonParameter.getInstance().getStorage().getDbDirectory(), CHECKPOINT_V2_DIR).toString(); + if (!FileUtil.recursiveDelete(Paths.get(checkpointPath, cp).toString())) { + logger.error("checkpoint prune failed, timestamp: {}", timestamp); + return; + } + logger.debug("checkpoint prune success, timestamp: {}", timestamp); } } // ensure run this method first after process start. @Override public void check() { - for (Chainbase db : dbs) { + if (!isV2Open()) { + List cpList = getCheckpointList(); + if (cpList != null && cpList.size() != 0) { + logger.error("checkpoint check failed, can't convert checkpoint from v2 to v1"); + System.exit(-1); + } + checkV1(); + } else { + checkV2(); + } + } + + private void checkV1() { + for (Chainbase db: dbs) { if (!Snapshot.isRoot(db.getHead())) { throw new IllegalStateException("First check."); } } + recover(checkTmpStore); + unChecked = false; + } - if (!checkTmpStore.getDbSource().allKeys().isEmpty()) { - Map dbMap = dbs.stream() - .map(db -> Maps.immutableEntry(db.getDbName(), db)) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - advance(); - for (Map.Entry e : checkTmpStore.getDbSource()) { - byte[] key = e.getKey(); - byte[] value = e.getValue(); - String db = simpleDecode(key); - if (dbMap.get(db) == null) { - continue; - } - byte[] realKey = Arrays.copyOfRange(key, db.getBytes().length + 4, key.length); + private void checkV2() { + logger.info("checkpoint version: {}", CommonParameter.getInstance().getStorage().getCheckpointVersion()); + logger.info("checkpoint sync: {}", CommonParameter.getInstance().getStorage().isCheckpointSync()); + List cpList = getCheckpointList(); + if (cpList == null || cpList.size() == 0) { + logger.info("checkpoint size is 0, using v1 recover"); + checkV1(); + deleteCheckpoint(); + return; + } - byte[] realValue = value.length == 1 ? null : Arrays.copyOfRange(value, 1, value.length); - if (realValue != null) { - dbMap.get(db).getHead().put(realKey, realValue); - } else { - dbMap.get(db).getHead().remove(realKey); - } + for (String cp: cpList) { + TronDatabase checkPointV2Store = getCheckpointDB(cp); + recover(checkPointV2Store); + checkPointV2Store.close(); + } + logger.info("checkpoint v2 recover success"); + unChecked = false; + } + private void recover(TronDatabase tronDatabase) { + Map dbMap = dbs.stream() + .map(db -> Maps.immutableEntry(db.getDbName(), db)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + advance(); + for (Map.Entry e: tronDatabase.getDbSource()) { + byte[] key = e.getKey(); + byte[] value = e.getValue(); + String db = simpleDecode(key); + if (dbMap.get(db) == null) { + continue; + } + byte[] realKey = Arrays.copyOfRange(key, db.getBytes().length + 4, key.length); + byte[] realValue = value.length == 1 ? null : Arrays.copyOfRange(value, 1, value.length); + if (realValue != null) { + dbMap.get(db).getHead().put(realKey, realValue); + } else { + dbMap.get(db).getHead().remove(realKey); } - - dbs.forEach(db -> db.getHead().getRoot().merge(db.getHead())); - retreat(); } - unChecked = false; + dbs.forEach(db -> db.getHead().getRoot().merge(db.getHead())); + retreat(); + } + + private boolean isV2Open() { + return checkpointVersion == 2; } private byte[] simpleEncode(String s) { diff --git a/chainbase/src/main/java/org/tron/core/store/CheckPointV2Store.java b/chainbase/src/main/java/org/tron/core/store/CheckPointV2Store.java new file mode 100644 index 00000000000..d5ffaaa9143 --- /dev/null +++ b/chainbase/src/main/java/org/tron/core/store/CheckPointV2Store.java @@ -0,0 +1,48 @@ +package org.tron.core.store; + +import com.google.protobuf.InvalidProtocolBufferException; +import org.springframework.beans.factory.annotation.Autowired; +import org.tron.core.db.TronDatabase; +import org.tron.core.exception.BadItemException; +import org.tron.core.exception.ItemNotFoundException; + +import java.util.Spliterator; +import java.util.function.Consumer; + +public class CheckPointV2Store extends TronDatabase { + + @Autowired + public CheckPointV2Store(String dbPath) { + super(dbPath); + } + + @Override + public void put(byte[] key, byte[] item) { + } + + @Override + public void delete(byte[] key) { + getDbSource().deleteData(key); + } + + @Override + public byte[] get(byte[] key) + throws InvalidProtocolBufferException, ItemNotFoundException, BadItemException { + return null; + } + + @Override + public boolean has(byte[] key) { + return false; + } + + @Override + public void forEach(Consumer action) { + + } + + @Override + public Spliterator spliterator() { + return null; + } +} \ No newline at end of file diff --git a/chainbase/src/main/java/org/tron/core/store/CheckTmpStore.java b/chainbase/src/main/java/org/tron/core/store/CheckTmpStore.java index 870aa9aa1b8..09f60c83898 100644 --- a/chainbase/src/main/java/org/tron/core/store/CheckTmpStore.java +++ b/chainbase/src/main/java/org/tron/core/store/CheckTmpStore.java @@ -24,7 +24,6 @@ public void put(byte[] key, byte[] item) { @Override public void delete(byte[] key) { - } @Override diff --git a/common/src/main/java/org/tron/core/config/args/Storage.java b/common/src/main/java/org/tron/core/config/args/Storage.java index 1b8bd595be0..6d911f3b0ac 100644 --- a/common/src/main/java/org/tron/core/config/args/Storage.java +++ b/common/src/main/java/org/tron/core/config/args/Storage.java @@ -69,6 +69,9 @@ public class Storage { private static final String MAX_OPEN_FILES_CONFIG_KEY = "maxOpenFiles"; private static final String EVENT_SUBSCRIBE_CONTRACT_PARSE = "event.subscribe.contractParse"; + private static final String CHECKPOINT_VERSION_KEY = "storage.checkpoint.version"; + private static final String CHECKPOINT_SYNC_KEY = "storage.checkpoint.sync"; + /** * Default values of directory */ @@ -79,6 +82,8 @@ public class Storage { private static final String DEFAULT_DB_DIRECTORY = "database"; private static final String DEFAULT_INDEX_DIRECTORY = "index"; private static final String DEFAULT_INDEX_SWITCH = "on"; + private static final int DEFAULT_CHECKPOINT_VERSION = 1; + private static final boolean DEFAULT_CHECKPOINT_SYNC = true; private static final int DEFAULT_ESTIMATED_TRANSACTIONS = 1000; private Config storage; @@ -120,6 +125,14 @@ public class Storage { @Setter private String transactionHistorySwitch; + @Getter + @Setter + private int checkpointVersion; + + @Getter + @Setter + private boolean checkpointSync; + private Options defaultDbOptions; @Getter @@ -175,6 +188,18 @@ public static String getTransactionHistorySwitchFromConfig(final Config config) : DEFAULT_TRANSACTIONHISTORY_SWITCH; } + public static int getCheckpointVersionFromConfig(final Config config) { + return config.hasPath(CHECKPOINT_VERSION_KEY) + ? config.getInt(CHECKPOINT_VERSION_KEY) + : DEFAULT_CHECKPOINT_VERSION; + } + + public static boolean getCheckpointSyncFromConfig(final Config config) { + return config.hasPath(CHECKPOINT_SYNC_KEY) + ? config.getBoolean(CHECKPOINT_SYNC_KEY) + : DEFAULT_CHECKPOINT_SYNC; + } + public static int getEstimatedTransactionsFromConfig(final Config config) { if (!config.hasPath(ESTIMATED_TRANSACTIONS_CONFIG_KEY)) { return DEFAULT_ESTIMATED_TRANSACTIONS; diff --git a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java index 1aa158d4be2..1be119f1be3 100644 --- a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java +++ b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java @@ -67,6 +67,7 @@ public void shutdown() { tronNetService.stop(); consensusService.stop(); synchronized (dbManager.getRevokingStore()) { + dbManager.getSession().reset(); closeRevokingStore(); closeAllStore(); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 029e89d6cd6..5fd20d2f8e5 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -501,6 +501,11 @@ public static void setParam(final String[] args, final String confFileName) { .filter(StringUtils::isNotEmpty) .orElse(Storage.getTransactionHistorySwitchFromConfig(config))); + PARAMETER.storage + .setCheckpointVersion(Storage.getCheckpointVersionFromConfig(config)); + PARAMETER.storage + .setCheckpointSync(Storage.getCheckpointSyncFromConfig(config)); + PARAMETER.storage.setEstimatedBlockTransactions( Storage.getEstimatedTransactionsFromConfig(config)); diff --git a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java index e66fafaa477..477a38dc71e 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java @@ -20,6 +20,7 @@ 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; @@ -43,19 +44,21 @@ 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 long RECENT_BLKS = 65536; - + 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 COMMON_DB_NAME = "common"; 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"; @@ -198,29 +201,43 @@ private void split(String sourceDir, String destDir, List dbs) throws IO private void mergeCheckpoint(String sourceDir, String destDir, List destDbs) { logger.info("Begin to merge checkpoint to dataset."); try { - DBInterface tmpDb = DbTool.getDB(sourceDir, CHECKPOINT_DB); - try (DBIterator iterator = tmpDb.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 { - destDb.delete(realKey); - } - } + 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 { + destDb.delete(realKey); + } + } + } + } + } + private void generateInfoProperties(String propertyfile, String databaseDir) throws IOException, RocksDBException { logger.info("Create {} for dataset.", INFO_FILE_NAME); @@ -236,19 +253,35 @@ private void generateInfoProperties(String propertyfile, String databaseDir) private long getLatestBlockHeaderNum(String databaseDir) throws IOException, RocksDBException { // query latest_block_header_number from checkpoint first final String latestBlockHeaderNumber = "latest_block_header_number"; - byte[] value = DbTool.getDB(databaseDir, CHECKPOINT_DB).get( - Bytes.concat(simpleEncode(CHECKPOINT_DB), latestBlockHeaderNumber.getBytes())); - if (value != null && value.length > 1) { - return ByteArray.toLong(Arrays.copyOfRange(value, 1, value.length)); + 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"); + 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. */ @@ -493,6 +526,14 @@ 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"); diff --git a/framework/src/main/resources/config-localtest.conf b/framework/src/main/resources/config-localtest.conf index 239b55d7b4f..15488c53743 100644 --- a/framework/src/main/resources/config-localtest.conf +++ b/framework/src/main/resources/config-localtest.conf @@ -51,7 +51,8 @@ storage { // maxOpenFiles = 100 // }, ] - + checkpoint.version = 2 + checkpoint.sync = true } node.discovery = { diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index aa1f51507bf..6a06f4ed0fe 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -90,10 +90,12 @@ storage { balance.history.lookup = false + # checkpoint.version = 2 + # checkpoint.sync = true + # the estimated number of block transactions (default 1000, min 100, max 10000). # so the total number of cached transactions is 65536 * txCache.estimatedTransactions # txCache.estimatedTransactions = 1000 - } node.discovery = { diff --git a/framework/src/test/java/org/tron/common/utils/PublicMethod.java b/framework/src/test/java/org/tron/common/utils/PublicMethod.java new file mode 100644 index 00000000000..b61ea6c8c4d --- /dev/null +++ b/framework/src/test/java/org/tron/common/utils/PublicMethod.java @@ -0,0 +1,105 @@ +package org.tron.common.utils; + +import com.google.protobuf.ByteString; +import java.math.BigInteger; +import org.tron.api.GrpcAPI; +import org.tron.api.WalletGrpc; +import org.tron.common.crypto.ECKey; +import org.tron.core.Wallet; +import org.tron.protos.Protocol; +import org.tron.protos.contract.BalanceContract; +import stest.tron.wallet.common.client.utils.TransactionUtils; + +public class PublicMethod { + + /** + * Convert to pub. + * @param priKey private key + * @return public addr + */ + public static byte[] getFinalAddress(String priKey) { + Wallet.setAddressPreFixByte((byte) 0x41); + ECKey key = ECKey.fromPrivate(new BigInteger(priKey, 16)); + return key.getAddress(); + } + + /** + * Transfer TRX. + * @param to addr receives the asset + * @param amount asset amount + * @param owner sender + * @param priKey private key of the sender + * @param blockingStubFull Grpc interface + * @return true or false + */ + public static Boolean sendcoin(byte[] to, long amount, byte[] owner, String priKey, + WalletGrpc.WalletBlockingStub blockingStubFull) { + Wallet.setAddressPreFixByte((byte) 0x41); + ECKey temKey = null; + try { + BigInteger priK = new BigInteger(priKey, 16); + temKey = ECKey.fromPrivate(priK); + } catch (Exception ex) { + ex.printStackTrace(); + } + final ECKey ecKey = temKey; + + int times = 0; + while (times++ <= 2) { + + BalanceContract.TransferContract.Builder builder = + BalanceContract.TransferContract.newBuilder(); + com.google.protobuf.ByteString bsTo = com.google.protobuf.ByteString.copyFrom(to); + com.google.protobuf.ByteString bsOwner = ByteString.copyFrom(owner); + builder.setToAddress(bsTo); + builder.setOwnerAddress(bsOwner); + builder.setAmount(amount); + + BalanceContract.TransferContract contract = builder.build(); + Protocol.Transaction transaction = blockingStubFull.createTransaction(contract); + if (transaction == null || transaction.getRawData().getContractCount() == 0) { + continue; + } + transaction = signTransaction(ecKey, transaction); + GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + return response.getResult(); + } + return false; + } + + /** + * Sign TX. + * @param ecKey ecKey of the private key + * @param transaction transaction object + */ + public static Protocol.Transaction signTransaction(ECKey ecKey, + Protocol.Transaction transaction) { + if (ecKey == null || ecKey.getPrivKey() == null) { + return null; + } + transaction = TransactionUtils.setTimestamp(transaction); + return TransactionUtils.sign(transaction, ecKey); + } + + /** + * Broadcast TX. + * @param transaction transaction object + * @param blockingStubFull Grpc interface + */ + public static GrpcAPI.Return broadcastTransaction( + Protocol.Transaction transaction, WalletGrpc.WalletBlockingStub blockingStubFull) { + int i = 10; + GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); + while (!response.getResult() && response.getCode() == GrpcAPI.Return.response_code.SERVER_BUSY + && i > 0) { + try { + Thread.sleep(300); + } catch (InterruptedException e) { + e.printStackTrace(); + } + i--; + response = blockingStubFull.broadcastTransaction(transaction); + } + return response; + } +} diff --git a/framework/src/test/java/org/tron/core/db2/CheckpointV2Test.java b/framework/src/test/java/org/tron/core/db2/CheckpointV2Test.java new file mode 100644 index 00000000000..dff2d376fd5 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db2/CheckpointV2Test.java @@ -0,0 +1,106 @@ +package org.tron.core.db2; + +import com.google.common.collect.Maps; +import com.google.common.primitives.Bytes; +import com.google.common.primitives.Longs; +import com.google.protobuf.ByteString; +import java.io.File; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.application.Application; +import org.tron.common.application.ApplicationFactory; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.Constant; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.db2.RevokingDbWithCacheNewValueTest.TestRevokingTronStore; +import org.tron.core.db2.core.Chainbase; +import org.tron.core.db2.core.SnapshotManager; + +@Slf4j +public class CheckpointV2Test { + + private SnapshotManager revokingDatabase; + private TronApplicationContext context; + private Application appT; + private TestRevokingTronStore tronDatabase; + + @Before + public void init() { + Args.setParam(new String[]{"-d", "output_SnapshotManager_test"}, + Constant.TEST_CONF); + Args.getInstance().getStorage().setCheckpointVersion(2); + Args.getInstance().getStorage().setCheckpointSync(true); + context = new TronApplicationContext(DefaultConfig.class); + appT = ApplicationFactory.create(context); + revokingDatabase = context.getBean(SnapshotManager.class); + revokingDatabase.enable(); + tronDatabase = new TestRevokingTronStore("testSnapshotManager-test"); + revokingDatabase.add(tronDatabase.getRevokingDB()); + } + + @After + public void removeDb() { + Args.clearParam(); + context.destroy(); + tronDatabase.close(); + FileUtil.deleteDir(new File("output_SnapshotManager_test")); + revokingDatabase.getCheckTmpStore().close(); + tronDatabase.close(); + } + + @Test + public void testCheckpointV2() { + while (revokingDatabase.size() != 0) { + revokingDatabase.pop(); + } + + revokingDatabase.setMaxFlushCount(0); + revokingDatabase.setUnChecked(false); + revokingDatabase.setMaxSize(0); + List dbList = revokingDatabase.getDbs(); + Map dbMap = dbList.stream() + .map(db -> Maps.immutableEntry(db.getDbName(), db)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + for (int i = 1; i <= 5; i++) { + BlockCapsule blockCapsule = new BlockCapsule(i, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), ByteString.EMPTY); + try (ISession tmpSession = revokingDatabase.buildSession()) { + dbMap.get("block").put(Longs.toByteArray(i), blockCapsule.getData()); + tmpSession.commit(); + } + } + revokingDatabase.buildSession(); + + Iterator> iterator = dbMap.get("block").iterator(); + Sha256Hash preDbHash = Sha256Hash.ZERO_HASH; + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + byte[] hashBytes = Bytes.concat(entry.getKey(), entry.getValue()); + preDbHash = Sha256Hash.of(true, Bytes.concat(preDbHash.getBytes(), hashBytes)); + } + + revokingDatabase.check(); + revokingDatabase.buildSession(); + + Iterator> iterator2 = dbMap.get("block").iterator(); + Sha256Hash afterDbHash = Sha256Hash.ZERO_HASH; + while (iterator2.hasNext()) { + Map.Entry entry = iterator2.next(); + byte[] hashBytes = Bytes.concat(entry.getKey(), entry.getValue()); + afterDbHash = Sha256Hash.of(true, Bytes.concat(afterDbHash.getBytes(), hashBytes)); + } + + Assert.assertEquals(0, preDbHash.compareTo(afterDbHash)); + } +} diff --git a/framework/src/test/java/org/tron/core/db2/SnapshotManagerTest.java b/framework/src/test/java/org/tron/core/db2/SnapshotManagerTest.java index 81681346799..966e947d828 100644 --- a/framework/src/test/java/org/tron/core/db2/SnapshotManagerTest.java +++ b/framework/src/test/java/org/tron/core/db2/SnapshotManagerTest.java @@ -1,6 +1,14 @@ package org.tron.core.db2; +import com.google.common.collect.Maps; +import com.google.common.primitives.Bytes; +import com.google.common.primitives.Longs; +import com.google.protobuf.ByteString; import java.io.File; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; @@ -10,11 +18,14 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.utils.FileUtil; +import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; +import org.tron.core.capsule.BlockCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.db2.RevokingDbWithCacheNewValueTest.TestRevokingTronStore; import org.tron.core.db2.SnapshotRootTest.ProtoCapsuleTest; +import org.tron.core.db2.core.Chainbase; import org.tron.core.db2.core.SnapshotManager; import org.tron.core.exception.BadItemException; import org.tron.core.exception.ItemNotFoundException; @@ -59,11 +70,18 @@ public synchronized void testRefresh() revokingDatabase.setMaxFlushCount(0); revokingDatabase.setUnChecked(false); revokingDatabase.setMaxSize(5); + List dbList = revokingDatabase.getDbs(); + Map dbMap = dbList.stream() + .map(db -> Maps.immutableEntry(db.getDbName(), db)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); ProtoCapsuleTest protoCapsule = new ProtoCapsuleTest("refresh".getBytes()); for (int i = 1; i < 11; i++) { ProtoCapsuleTest testProtoCapsule = new ProtoCapsuleTest(("refresh" + i).getBytes()); try (ISession tmpSession = revokingDatabase.buildSession()) { tronDatabase.put(protoCapsule.getData(), testProtoCapsule); + BlockCapsule blockCapsule = new BlockCapsule(i, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), ByteString.EMPTY); + dbMap.get("block").put(Longs.toByteArray(i), blockCapsule.getData()); tmpSession.commit(); } } diff --git a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java index f3dcd448ed2..4549b2cde4d 100644 --- a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java +++ b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java @@ -21,6 +21,7 @@ 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.Wallet; import org.tron.core.config.DefaultConfig; @@ -111,17 +112,22 @@ public void clear() { @Test public void testToolsWithLevelDB() { logger.info("testToolsWithLevelDB start"); - testTools("LEVELDB"); + testTools("LEVELDB", 1); + } + @Test + public void testToolsWithLevelDBV2() { + logger.info("testToolsWithLevelDB start"); + testTools("LEVELDB", 2); } @Test public void testToolsWithRocksDB() { logger.info("testToolsWithRocksDB start"); - testTools("ROCKSDB"); + testTools("ROCKSDB", 1); } - private void testTools(String dbType) { + private void testTools(String dbType, int checkpointVersion) { final String[] argsForSnapshot = new String[]{"-o", "split", "-t", "snapshot", "--fn-data-path", DB_PATH + File.separator + databaseDir, "--dataset-path", @@ -134,6 +140,7 @@ private void testTools(String dbType) { new String[]{"-o", "merge", "--fn-data-path", DB_PATH + File.separator + databaseDir, "--dataset-path", DB_PATH + File.separator + "history"}; Args.getInstance().getStorage().setDbEngine(dbType); + Args.getInstance().getStorage().setCheckpointVersion(checkpointVersion); LiteFullNodeTool.setRecentBlks(3); // start fullnode startApp(); @@ -190,8 +197,8 @@ private void generateSomeTransactions(int during) { byte[] address = ecKey2.getAddress(); String sunPri = "cba92a516ea09f620a16ff7ee95ce0df1d56550a8babe9964981a7144c8a784a"; - byte[] sunAddress = getFinalAddress(sunPri); - sendcoin(address, 1L, + byte[] sunAddress = PublicMethod.getFinalAddress(sunPri); + PublicMethod.sendcoin(address, 1L, sunAddress, sunPri, blockingStubFull); try { Thread.sleep(sleepOnce); @@ -203,97 +210,4 @@ private void generateSomeTransactions(int during) { } } } - - /** - * Set public for future use. - * @param priKey private key - * @return public addr - */ - public static byte[] getFinalAddress(String priKey) { - Wallet.setAddressPreFixByte((byte) 0x41); - ECKey key = ECKey.fromPrivate(new BigInteger(priKey, 16)); - return key.getAddress(); - } - - /** - * Set public for future use. - * @param to addr receives the asset - * @param amount asset amount - * @param owner sender - * @param priKey private key of the sender - * @param blockingStubFull Grpc interface - * @return true or false - */ - public static Boolean sendcoin(byte[] to, long amount, byte[] owner, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte((byte) 0x41); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - int times = 0; - while (times++ <= 2) { - - BalanceContract.TransferContract.Builder builder = - BalanceContract.TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - BalanceContract.TransferContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createTransaction(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - continue; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - return false; - } - - /** - * Set public for future use. - * @param ecKey ecKey of the private key - * @param transaction transaction object - */ - public static Protocol.Transaction signTransaction(ECKey ecKey, - Protocol.Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * Set public for future use. - * @param transaction transaction object - * @param blockingStubFull Grpc interface - */ - public static GrpcAPI.Return broadcastTransaction( - Protocol.Transaction transaction, WalletGrpc.WalletBlockingStub blockingStubFull) { - int i = 10; - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - while (!response.getResult() && response.getCode() == GrpcAPI.Return.response_code.SERVER_BUSY - && i > 0) { - try { - Thread.sleep(300); - } catch (InterruptedException e) { - e.printStackTrace(); - } - i--; - response = blockingStubFull.broadcastTransaction(transaction); - } - return response; - } - } From b59e694cecd9bf8429723f1c9db08f3f2288347b Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Thu, 11 Aug 2022 16:21:41 +0800 Subject: [PATCH 0254/1197] feat(reward): add a proposal for new reward algorithm --- .../java/org/tron/core/utils/ProposalUtil.java | 18 +++++++++++++++++- .../core/store/DynamicPropertiesStore.java | 3 +-- .../java/org/tron/core/config/Parameter.java | 5 +++-- .../src/main/java/org/tron/core/Wallet.java | 5 +++++ .../tron/core/consensus/ProposalService.java | 6 +++++- 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 4f128884dfd..0fc7adba674 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -560,6 +560,21 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case ALLOW_NEW_REWARD_ALGO: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_6)) { + throw new ContractValidateException( + "Bad chain parameter id [ALLOW_NEW_REWARD_ALGO]"); + } + if (dynamicPropertiesStore.useNewRewardAlgorithm()) { + throw new ContractValidateException( + "New reward algorithm has been valid."); + } + if (value != 1) { + throw new ContractValidateException( + "This value[ALLOW_NEW_REWARD_ALGO] is only allowed to be 1"); + } + break; + } default: break; } @@ -623,7 +638,8 @@ public enum ProposalType { // current value, value range TOTAL_NET_LIMIT(62), // 43_200_000_000L, [0, 1000_000_000_000L] ALLOW_TVM_LONDON(63), // 0, 1 ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX(65), // 0, 1 - ALLOW_ASSET_OPTIMIZATION(66); // 0, 1 + ALLOW_ASSET_OPTIMIZATION(66), // 0, 1 + ALLOW_NEW_REWARD_ALGO(67); // 0, 1 private long code; diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index dce79515ad4..f65236c6047 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -187,7 +187,6 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX = "ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX".getBytes(); - @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { super(dbName); @@ -2383,7 +2382,7 @@ public long getAllowTvmCompatibleEvm() { } public boolean useNewRewardAlgorithm() { - return getAllowTvmVote() == 1; + return getNewRewardAlgorithmEffectiveCycle() != Long.MAX_VALUE; } public void saveNewRewardAlgorithmEffectiveCycle() { diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index 35a763f64c0..1a4f9cf3dd7 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -18,7 +18,8 @@ public enum ForkBlockVersionEnum { VERSION_4_2(21, 1596780000000L, 80), VERSION_4_3(22, 1596780000000L, 80), VERSION_4_4(23, 1596780000000L, 80), - VERSION_4_5(24, 1596780000000L, 80); + VERSION_4_5(24, 1596780000000L, 80), + VERSION_4_6(25, 1596780000000L, 80); @Getter private int value; @@ -66,7 +67,7 @@ public class ChainConstant { public static final int SINGLE_REPEAT = 1; public static final int BLOCK_FILLED_SLOTS_NUMBER = 128; public static final int MAX_FROZEN_NUMBER = 1; - public static final int BLOCK_VERSION = 24; + public static final int BLOCK_VERSION = 25; public static final long FROZEN_PERIOD = 86_400_000L; public static final long TRX_PRECISION = 1000_000L; } diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index ac88a898ed9..002f64d7c86 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1098,6 +1098,11 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getAllowAssetOptimization()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getNewRewardAlgorithm") + .setValue(dbManager.getDynamicPropertiesStore().useNewRewardAlgorithm() ? 1 : 0) + .build()); + return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index f6f55b0097c..92472335d20 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -251,8 +251,8 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) break; } case ALLOW_TVM_VOTE: { - manager.getDynamicPropertiesStore().saveAllowTvmVote(entry.getValue()); manager.getDynamicPropertiesStore().saveNewRewardAlgorithmEffectiveCycle(); + manager.getDynamicPropertiesStore().saveAllowTvmVote(entry.getValue()); break; } case ALLOW_TVM_LONDON: { @@ -284,6 +284,10 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().setAllowAssetOptimization(entry.getValue()); break; } + case ALLOW_NEW_REWARD_ALGO: { + manager.getDynamicPropertiesStore().saveNewRewardAlgorithmEffectiveCycle(); + break; + } default: find = false; break; From b148e52da8150dc286eaf1530f2b3a9d258749db Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Fri, 16 Sep 2022 12:29:47 +0800 Subject: [PATCH 0255/1197] refactor(net): optimize some logs for network module --- .../java/org/tron/common/backup/BackupManager.java | 6 +++--- .../tron/common/net/udp/handler/MessageHandler.java | 3 ++- .../org/tron/common/overlay/client/PeerClient.java | 7 +++---- .../tron/common/overlay/discover/DiscoverServer.java | 10 +++++----- .../common/overlay/discover/node/NodeHandler.java | 4 ++-- .../common/overlay/discover/node/NodeManager.java | 10 +++++----- .../tron/common/overlay/message/HelloMessage.java | 4 +++- .../java/org/tron/common/overlay/server/Channel.java | 4 ++-- .../tron/common/overlay/server/ChannelManager.java | 4 ++-- .../org/tron/common/overlay/server/FastForward.java | 2 +- .../org/tron/common/overlay/server/MessageQueue.java | 10 +++++----- .../overlay/server/PeerConnectionCheckService.java | 6 +++--- .../org/tron/common/overlay/server/PeerServer.java | 4 ++-- .../org/tron/common/overlay/server/SyncPool.java | 2 +- .../main/java/org/tron/core/net/TronNetDelegate.java | 6 +++--- .../main/java/org/tron/core/net/TronNetService.java | 8 ++++---- .../core/net/messagehandler/BlockMsgHandler.java | 2 +- .../core/net/messagehandler/InventoryMsgHandler.java | 6 +++--- .../net/messagehandler/SyncBlockChainMsgHandler.java | 2 +- .../net/messagehandler/TransactionsMsgHandler.java | 8 ++++---- .../java/org/tron/core/net/peer/PeerStatusCheck.java | 2 +- .../java/org/tron/core/net/service/AdvService.java | 12 ++++++------ .../org/tron/core/net/service/FetchBlockService.java | 2 +- .../java/org/tron/core/net/service/SyncService.java | 10 +++++----- 24 files changed, 68 insertions(+), 66 deletions(-) diff --git a/framework/src/main/java/org/tron/common/backup/BackupManager.java b/framework/src/main/java/org/tron/common/backup/BackupManager.java index 2b7c1a17f3e..1d78dd234ad 100644 --- a/framework/src/main/java/org/tron/common/backup/BackupManager.java +++ b/framework/src/main/java/org/tron/common/backup/BackupManager.java @@ -72,7 +72,7 @@ public void init() { try { localIp = InetAddress.getLocalHost().getHostAddress(); } catch (Exception e) { - logger.warn("Failed to get local ip."); + logger.warn("Failed to get local ip"); } for (String member : parameter.getBackupMembers()) { @@ -105,7 +105,7 @@ public void init() { .accept(new UdpEvent(new KeepAliveMessage(status.equals(MASTER), priority), new InetSocketAddress(member, port)))); } catch (Throwable t) { - logger.error("Exception in send keep alive.", t); + logger.error("Exception in send keep alive", t); } }, 1000, keepAliveInterval, TimeUnit.MILLISECONDS); } @@ -120,7 +120,7 @@ public void handleEvent(UdpEvent udpEvent) { return; } if (!members.contains(sender.getHostString())) { - logger.warn("Receive keep alive message from {} is not my member.", sender.getHostString()); + logger.warn("Receive keep alive message from {} is not my member", sender.getHostString()); return; } diff --git a/framework/src/main/java/org/tron/common/net/udp/handler/MessageHandler.java b/framework/src/main/java/org/tron/common/net/udp/handler/MessageHandler.java index c48ccc5752d..6d9524bc23b 100644 --- a/framework/src/main/java/org/tron/common/net/udp/handler/MessageHandler.java +++ b/framework/src/main/java/org/tron/common/net/udp/handler/MessageHandler.java @@ -78,7 +78,8 @@ public void channelReadComplete(ChannelHandlerContext ctx) { @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.info("Exception caught, {} {}", ctx.channel().remoteAddress(), cause.getMessage()); + logger.info("Exception caught in udp message handler, {} {}", + ctx.channel().remoteAddress(), cause.getMessage()); ctx.close(); } } diff --git a/framework/src/main/java/org/tron/common/overlay/client/PeerClient.java b/framework/src/main/java/org/tron/common/overlay/client/PeerClient.java index 0414e2088c9..60f73eb3fb3 100644 --- a/framework/src/main/java/org/tron/common/overlay/client/PeerClient.java +++ b/framework/src/main/java/org/tron/common/overlay/client/PeerClient.java @@ -45,8 +45,7 @@ public void connect(String host, int port, String remoteId) { ChannelFuture f = connectAsync(host, port, remoteId, false); f.sync().channel().closeFuture().sync(); } catch (Exception e) { - logger - .info("PeerClient: Can't connect to " + host + ":" + port + " (" + e.getMessage() + ")"); + logger.info("Can't connect to {}:{}, cause:{})", host, port, e.getMessage()); } } @@ -55,7 +54,7 @@ public ChannelFuture connectAsync(NodeHandler nodeHandler, boolean discoveryMode return connectAsync(node.getHost(), node.getPort(), node.getHexId(), discoveryMode) .addListener((ChannelFutureListener) future -> { if (!future.isSuccess()) { - logger.warn("Connect to {}:{} fail,cause:{}", node.getHost(), node.getPort(), + logger.warn("Connect to {}:{} fail, cause:{}", node.getHost(), node.getPort(), future.cause().getMessage()); nodeHandler.getNodeStatistics().nodeDisconnectedLocal(ReasonCode.CONNECT_FAIL); nodeHandler.getNodeStatistics().notifyDisconnect(); @@ -67,7 +66,7 @@ public ChannelFuture connectAsync(NodeHandler nodeHandler, boolean discoveryMode private ChannelFuture connectAsync(String host, int port, String remoteId, boolean discoveryMode) { - logger.info("Connect peer {} {} {}", host, port, remoteId); + logger.info("Connect peer {}:{}, remoteId:{}", host, port, remoteId); TronChannelInitializer tronChannelInitializer = ctx .getBean(TronChannelInitializer.class, remoteId); diff --git a/framework/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java b/framework/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java index ddb6b912e6b..ce8d577caf2 100755 --- a/framework/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java +++ b/framework/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java @@ -68,7 +68,7 @@ public DiscoverServer(final NodeManager nodeManager) { try { start(); } catch (Exception e) { - logger.error("Discovery server start failed.", e); + logger.error("Discovery server start failed", e); } }, "DiscoverServer").start(); } @@ -111,10 +111,10 @@ public void initChannel(NioDatagramChannel ch) Thread.sleep(5000); } } catch (InterruptedException e) { - logger.warn("Discover server interrupted."); + logger.warn("Discover server interrupted"); Thread.currentThread().interrupt(); } catch (Exception e) { - logger.error("Start discovery server with port {} failed.", port, e); + logger.error("Start discovery server with port {} failed", port, e); } finally { group.shutdownGracefully().sync(); } @@ -127,7 +127,7 @@ public void close() { try { channel.close().await(10, TimeUnit.SECONDS); } catch (Exception e) { - logger.warn("Closing discovery server failed.", e); + logger.error("Closing discovery server failed", e); } } @@ -135,7 +135,7 @@ public void close() { try { discoveryExecutor.close(); } catch (Exception e) { - logger.warn("Closing discovery executor failed.", e); + logger.error("Closing discovery executor failed", e); } } } diff --git a/framework/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java b/framework/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java index 90ecff8cbab..44e8761c29a 100644 --- a/framework/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java +++ b/framework/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java @@ -184,7 +184,7 @@ public void handlePong(PongMessage msg) { public void handleNeighbours(NeighborsMessage msg) { if (!waitForNeighbors) { - logger.warn("Receive neighbors from {} without send find nodes.", node.getHost()); + logger.warn("Receive neighbors from {} without send find nodes", node.getHost()); return; } waitForNeighbors = false; @@ -231,7 +231,7 @@ public void sendPing() { handleTimedOut(); } } catch (Exception e) { - logger.error("Unhandled exception", e); + logger.error("Unhandled exception in pong timer schedule", e); } }, pingTimeout, TimeUnit.MILLISECONDS); } diff --git a/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java b/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java index 58dd6103489..e8f2870fe98 100644 --- a/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java +++ b/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java @@ -123,13 +123,13 @@ private void dbRead() { return; } DBNode dbNode = JsonUtil.json2Obj(new String(nodeBytes), DBNode.class); - logger.info("Reading node statistics from store: {} nodes.", dbNode.getNodes().size()); + logger.info("Reading node statistics from store: {} nodes", dbNode.getNodes().size()); dbNode.getNodes().forEach(n -> { Node node = new Node(n.getId(), n.getHost(), n.getPort()); getNodeHandler(node).getNodeStatistics().setPersistedReputation(n.getReputation()); }); } catch (Exception e) { - logger.error("DB read node failed.", e); + logger.error("DB read node failed", e); } } @@ -153,13 +153,13 @@ private void dbWrite() { dbNode.setNodes(batch); - logger.info("Write node statistics to store: m:{}/t:{}/{}/{} nodes.", + logger.info("Write node statistics to store: m:{}/t:{}/{}/{} nodes", nodeHandlerMap.size(), getTable().getAllNodes().size(), size, batch.size()); chainBaseManager.getCommonStore() .put(DB_KEY_PEERS, new BytesCapsule(JsonUtil.obj2Json(dbNode).getBytes())); } catch (Exception e) { - logger.error("DB write node failed.", e); + logger.error("DB write node failed", e); } } @@ -307,7 +307,7 @@ public void close() { nodeManagerTasksTimer.cancel(); pongTimer.shutdownNow(); } catch (Exception e) { - logger.warn("Close failed.", e); + logger.error("Close nodeManagerTasksTimer or pongTimer failed", e); } } diff --git a/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java b/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java index 0498bf610ca..86c01725aed 100755 --- a/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java +++ b/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java @@ -127,7 +127,9 @@ public String toString() { return new StringBuilder().append(super.toString()).append(", ") .append("from: ").append(getFrom()).append(", ") .append("timestamp: ").append(getTimestamp()).append(", ") - .append("headBlockId: {").append(getHeadBlockId().getString()).append("}") + .append("headBlockId: {").append(getHeadBlockId().getString()).append("}, ") + .append("nodeType: ").append(helloMessage.getNodeType()).append(", ") + .append("lowestBlockNum: ").append(helloMessage.getLowestBlockNum()) .toString(); } diff --git a/framework/src/main/java/org/tron/common/overlay/server/Channel.java b/framework/src/main/java/org/tron/common/overlay/server/Channel.java index 0a4c92a87a1..f67cd8ba43b 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/Channel.java +++ b/framework/src/main/java/org/tron/common/overlay/server/Channel.java @@ -120,7 +120,7 @@ public void publicHandshakeFinished(ChannelHandlerContext ctx, HelloMessage msg) setStartTime(msg.getTimestamp()); setTronState(TronState.HANDSHAKE_FINISHED); getNodeStatistics().p2pHandShake.add(); - logger.info("Finish handshake with {}.", ctx.channel().remoteAddress()); + logger.info("Finish handshake with {}", ctx.channel().remoteAddress()); } /** @@ -215,7 +215,7 @@ public void setStartTime(long startTime) { public void setTronState(TronState tronState) { this.tronState = tronState; - logger.info("Peer {} status change to {}.", inetSocketAddress, tronState); + logger.info("Peer {} status change to {}", inetSocketAddress, tronState); } public boolean isActive() { diff --git a/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java b/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java index d9da821f495..68c5ee78d97 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java +++ b/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java @@ -93,7 +93,7 @@ public void init() { fastForwardNodes.put(address, node); } - logger.info("Node config, trust {}, active {}, forward {}.", + logger.info("Node config, trust {}, active {}, forward {}", trustNodes.size(), activeNodes.size(), fastForwardNodes.size()); peerConnectionCheckService.init(); @@ -140,7 +140,7 @@ public synchronized boolean processPeer(Channel peer) { if (trustNodes.getIfPresent(peer.getInetAddress()) == null) { if (recentlyDisconnected.getIfPresent(peer) != null) { - logger.info("Peer {} recently disconnected.", peer.getInetAddress()); + logger.info("Peer {} recently disconnected", peer.getInetAddress()); return false; } diff --git a/framework/src/main/java/org/tron/common/overlay/server/FastForward.java b/framework/src/main/java/org/tron/common/overlay/server/FastForward.java index 0ca7949c181..bc19fa206d9 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/FastForward.java +++ b/framework/src/main/java/org/tron/common/overlay/server/FastForward.java @@ -139,7 +139,7 @@ public boolean checkHelloMessage(HelloMessage message, Channel channel) { } return flag; } catch (Exception e) { - logger.warn("Check hello message failed, msg: {}, {}", message, channel.getInetAddress(), e); + logger.error("Check hello message failed, msg: {}, {}", message, channel.getInetAddress(), e); return false; } } diff --git a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java index 2b52c525b94..de59cb85736 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java +++ b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java @@ -77,14 +77,14 @@ public void activate(ChannelHandlerContext ctx) { } ctx.writeAndFlush(msg.getSendData()).addListener((ChannelFutureListener) future -> { if (!future.isSuccess() && !channel.isDisconnect()) { - logger.warn("Failed to send to {}, {}", ctx.channel().remoteAddress(), msg); + logger.warn("Failed to send to {}, {} ", ctx.channel().remoteAddress(), msg); } }); } catch (InterruptedException e) { - logger.warn("Send message server interrupted."); + logger.warn("Send message server interrupted"); Thread.currentThread().interrupt(); } catch (Exception e) { - logger.error("Failed to send to {}.", ctx.channel().remoteAddress(), e); + logger.error("Failed to send to {} ", ctx.channel().remoteAddress(), e); } } }); @@ -162,7 +162,7 @@ public void close() { sendMsgThread.join(20); sendMsgThread = null; } catch (InterruptedException e) { - logger.warn("Send message join interrupted."); + logger.warn("Send message join interrupted"); Thread.currentThread().interrupt(); } catch (Exception e) { logger.warn("Join send thread failed, peer {}", ctx.channel().remoteAddress()); @@ -196,7 +196,7 @@ private void send() { } if (rt.getRetryTimes() > 0) { channel.getNodeStatistics().nodeDisconnectedLocal(ReasonCode.PING_TIMEOUT); - logger.warn("Wait {} timeout. close channel {}.", + logger.warn("Wait {} timeout. close channel {}", rt.getMsg().getAnswerMessage(), ctx.channel().remoteAddress()); channel.close(); return; diff --git a/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java b/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java index 3aafa4a8e95..e0d9d39b4a7 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java +++ b/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java @@ -30,18 +30,18 @@ public void init() { if (isFastForward || !isOpenFullTcpDisconnect) { return; } - logger.info("Start peer connection check service."); + logger.info("Start peer connection check service"); poolLoopExecutor.scheduleWithFixedDelay(() -> { try { check(); } catch (Throwable t) { - logger.error("Exception in peer connection check.", t); + logger.error("Exception in peer connection check", t); } }, 10, 30, TimeUnit.SECONDS); } public void close() { - logger.info("Close peer connection check service."); + logger.info("Close peer connection check service"); poolLoopExecutor.shutdown(); } diff --git a/framework/src/main/java/org/tron/common/overlay/server/PeerServer.java b/framework/src/main/java/org/tron/common/overlay/server/PeerServer.java index bdff4ccebf7..e00372e9a5d 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/PeerServer.java +++ b/framework/src/main/java/org/tron/common/overlay/server/PeerServer.java @@ -63,7 +63,7 @@ public void start(int port) { logger.info("TCP listener closed"); } catch (Exception e) { - logger.error("Start TCP server failed.", e); + logger.error("Start TCP server failed", e); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); @@ -77,7 +77,7 @@ public void close() { logger.info("Closing TCP server..."); channelFuture.channel().close().sync(); } catch (Exception e) { - logger.warn("Closing TCP server failed.", e); + logger.error("Closing TCP server failed", e); } } } diff --git a/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java b/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java index d850a387d98..e4b28494404 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java +++ b/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java @@ -225,7 +225,7 @@ public void close() { poolLoopExecutor.shutdownNow(); logExecutor.shutdownNow(); } catch (Exception e) { - logger.warn("Problems shutting down executor", e); + logger.error("Problems shutting down executor", e); } } diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index 02b1862a1e4..7a0c361165e 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -220,7 +220,7 @@ public void processBlock(BlockCapsule block, boolean isSync) throws P2pException && dbManager.getLatestSolidityNumShutDown() == dbManager.getDynamicPropertiesStore() .getLatestBlockHeaderNumberFromDB()) { - logger.info("Begin shutdown, currentBlockNum:{}, DbBlockNum:{} ,solidifiedBlockNum:{}.", + logger.info("Begin shutdown, currentBlockNum:{}, DbBlockNum:{}, solidifiedBlockNum:{}", dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber(), dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumberFromDB(), dbManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum()); @@ -252,7 +252,7 @@ public void processBlock(BlockCapsule block, boolean isSync) throws P2pException dbManager.pushBlock(block); Metrics.histogramObserve(timer); freshBlockId.put(blockId, System.currentTimeMillis()); - logger.info("Success process block {}.", blockId.getString()); + logger.info("Success process block {}", blockId.getString()); if (!backupServerStartFlag && System.currentTimeMillis() - block.getTimeStamp() < BLOCK_PRODUCED_INTERVAL) { backupServerStartFlag = true; @@ -278,7 +278,7 @@ public void processBlock(BlockCapsule block, boolean isSync) throws P2pException | ZksnarkException | EventBloomException e) { metricsService.failProcessBlock(block.getNum(), e.getMessage()); - logger.error("Process block failed, {}, reason: {}.", blockId.getString(), e.getMessage()); + logger.error("Process block failed, {}, reason: {}", blockId.getString(), e.getMessage()); throw new P2pException(TypeEnum.BAD_BLOCK, e); } } diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 3f6a0d82d16..82568d6a7c0 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -77,18 +77,18 @@ public void start() { peerStatusCheck.init(); transactionsMsgHandler.init(); fetchBlockService.init(); - logger.info("TronNetService start successfully."); + logger.info("TronNetService start successfully"); } public void stop() { - logger.info("TronNetService closed start."); + logger.info("TronNetService closed start"); channelManager.close(); advService.close(); syncService.close(); peerStatusCheck.close(); transactionsMsgHandler.close(); fetchBlockService.close(); - logger.info("TronNetService closed successfully."); + logger.info("TronNetService closed successfully"); } public int fastBroadcastTransaction(TransactionMessage msg) { @@ -170,7 +170,7 @@ private void processException(PeerConnection peer, TronMessage msg, Exception ex code = ReasonCode.UNKNOWN; break; } - logger.warn("Message from {} process failed, {} \n type: {}, detail: {}.", + logger.warn("Message from {} process failed, {} \n type: {}, detail: {}", peer.getInetAddress(), msg, type, ex.getMessage()); } else { code = ReasonCode.UNKNOWN; diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java index d6df46e1825..5d6d4eb7f75 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java @@ -119,7 +119,7 @@ private void check(PeerConnection peer, BlockMessage msg) throws P2pException { private void processBlock(PeerConnection peer, BlockCapsule block) throws P2pException { BlockId blockId = block.getBlockId(); if (!tronNetDelegate.containBlock(block.getParentBlockId())) { - logger.warn("Get unlink block {} from {}, head is {}.", blockId.getString(), + logger.warn("Get unlink block {} from {}, head is {}", blockId.getString(), peer.getInetAddress(), tronNetDelegate.getHeadBlockId().getString()); syncService.startSync(peer); return; diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java index 6b8a8d85c92..96f022543f2 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java @@ -49,7 +49,7 @@ private boolean check(PeerConnection peer, InventoryMessage inventoryMessage) { int size = inventoryMessage.getHashList().size(); if (peer.isNeedSyncFromPeer() || peer.isNeedSyncFromUs()) { - logger.warn("Drop inv: {} size: {} from Peer {}, syncFromUs: {}, syncFromPeer: {}.", + logger.warn("Drop inv: {} size: {} from Peer {}, syncFromUs: {}, syncFromPeer: {}", type, size, peer.getInetAddress(), peer.isNeedSyncFromUs(), peer.isNeedSyncFromPeer()); return false; } @@ -57,7 +57,7 @@ private boolean check(PeerConnection peer, InventoryMessage inventoryMessage) { if (type.equals(InventoryType.TRX)) { int count = peer.getNodeStatistics().messageStatistics.tronInTrxInventoryElement.getCount(10); if (count > maxCountIn10s) { - logger.warn("Drop inv: {} size: {} from Peer {}, Inv count: {} is overload.", + logger.warn("Drop inv: {} size: {} from Peer {}, Inv count: {} is overload", type, size, peer.getInetAddress(), count); if (Args.getInstance().isOpenPrintLog()) { logger.warn("[overload]Drop tx list is: {}", inventoryMessage.getHashList()); @@ -66,7 +66,7 @@ private boolean check(PeerConnection peer, InventoryMessage inventoryMessage) { } if (transactionsMsgHandler.isBusy()) { - logger.warn("Drop inv: {} size: {} from Peer {}, transactionsMsgHandler is busy.", + logger.warn("Drop inv: {} size: {} from Peer {}, transactionsMsgHandler is busy", type, size, peer.getInetAddress()); if (Args.getInstance().isOpenPrintLog()) { logger.warn("[isBusy]Drop tx list is: {}", inventoryMessage.getHashList()); diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java index 4d2271a09c3..d9fc767ac6c 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java @@ -38,7 +38,7 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep LinkedList blockIds = getLostBlockIds(summaryChainIds); if (blockIds.size() == 0) { - logger.warn("Can't get lost block Ids."); + logger.warn("Can't get lost block Ids"); peer.disconnect(Protocol.ReasonCode.INCOMPATIBLE_CHAIN); return; } else if (blockIds.size() == 1) { diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java index 3c2bab191fa..28cc68c2e44 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java @@ -106,17 +106,17 @@ private void handleSmartContract() { trxHandlePool.submit(() -> handleTransaction(event.getPeer(), event.getMsg())); } } catch (InterruptedException e) { - logger.warn("Handle smart server interrupted."); + logger.warn("Handle smart server interrupted"); Thread.currentThread().interrupt(); } catch (Exception e) { - logger.error("Handle smart contract exception.", e); + logger.error("Handle smart contract exception", e); } }, 1000, 20, TimeUnit.MILLISECONDS); } private void handleTransaction(PeerConnection peer, TransactionMessage trx) { if (peer.isDisconnect()) { - logger.warn("Drop trx {} from {}, peer is disconnect.", trx.getMessageId(), + logger.warn("Drop trx {} from {}, peer is disconnect", trx.getMessageId(), peer.getInetAddress()); return; } @@ -135,7 +135,7 @@ private void handleTransaction(PeerConnection peer, TransactionMessage trx) { peer.disconnect(ReasonCode.BAD_TX); } } catch (Exception e) { - logger.error("Trx {} from peer {} process failed.", trx.getMessageId(), peer.getInetAddress(), + logger.error("Trx {} from peer {} process failed", trx.getMessageId(), peer.getInetAddress(), e); } } diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java b/framework/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java index 706eee7b421..993d9e94781 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java @@ -46,7 +46,7 @@ public void statusCheck() { if (peer.isNeedSyncFromPeer() && peer.getBlockBothHaveUpdateTime() < now - blockUpdateTimeout) { - logger.warn("Peer {} not sync for a long time.", peer.getInetAddress()); + logger.warn("Peer {} not sync for a long time", peer.getInetAddress()); isDisconnected = true; } diff --git a/framework/src/main/java/org/tron/core/net/service/AdvService.java b/framework/src/main/java/org/tron/core/net/service/AdvService.java index e0dc4238ab7..b10e0542919 100644 --- a/framework/src/main/java/org/tron/core/net/service/AdvService.java +++ b/framework/src/main/java/org/tron/core/net/service/AdvService.java @@ -86,7 +86,7 @@ public void init() { try { consumerInvToSpread(); } catch (Exception exception) { - logger.error("Spread thread error. {}", exception.getMessage(), exception); + logger.error("Spread thread error", exception); } }, 100, 30, TimeUnit.MILLISECONDS); @@ -94,7 +94,7 @@ public void init() { try { consumerInvToFetch(); } catch (Exception exception) { - logger.error("Fetch thread error. {}", exception.getMessage(), exception); + logger.error("Fetch thread error", exception); } }, 100, 30, TimeUnit.MILLISECONDS); } @@ -151,7 +151,7 @@ public int fastBroadcastTransaction(TransactionMessage msg) { .collect(Collectors.toList()); if (peers.size() == 0) { - logger.warn("Broadcast transaction {} failed, no connection.", msg.getMessageId()); + logger.warn("Broadcast transaction {} failed, no connection", msg.getMessageId()); return 0; } @@ -173,7 +173,7 @@ public int fastBroadcastTransaction(TransactionMessage msg) { } } if (peersCount == 0) { - logger.warn("Broadcast transaction {} failed, no peers.", msg.getMessageId()); + logger.warn("Broadcast transaction {} failed, no peers", msg.getMessageId()); } return peersCount; } @@ -185,7 +185,7 @@ public void broadcast(Message msg) { } if (invToSpread.size() > MAX_SPREAD_SIZE) { - logger.warn("Drop message, type: {}, ID: {}.", msg.getType(), msg.getMessageId()); + logger.warn("Drop message, type: {}, ID: {}", msg.getType(), msg.getMessageId()); return; } @@ -269,7 +269,7 @@ private void consumerInvToFetch() { } invToFetch.forEach((item, time) -> { if (time < now - MSG_CACHE_DURATION_IN_BLOCKS * BLOCK_PRODUCED_INTERVAL) { - logger.info("This obj is too late to fetch, type: {} hash: {}.", item.getType(), + logger.info("This obj is too late to fetch, type: {} hash: {}", item.getType(), item.getHash()); invToFetch.remove(item); invToFetchCache.invalidate(item); diff --git a/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java b/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java index 5c5f04f3bef..ef541eb3559 100644 --- a/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java +++ b/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java @@ -59,7 +59,7 @@ public void init() { try { fetchBlockProcess(fetchBlockInfo); } catch (Exception e) { - logger.error("FetchBlockWorkerSchedule thread error.", e); + logger.error("FetchBlockWorkerSchedule thread error", e); } }, 0L, 50L, TimeUnit.MILLISECONDS); } diff --git a/framework/src/main/java/org/tron/core/net/service/SyncService.java b/framework/src/main/java/org/tron/core/net/service/SyncService.java index 0a415162509..79697d7459f 100644 --- a/framework/src/main/java/org/tron/core/net/service/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/SyncService.java @@ -72,7 +72,7 @@ public void init() { startFetchSyncBlock(); } } catch (Exception e) { - logger.error("Fetch sync block error.", e); + logger.error("Fetch sync block error", e); } }, 10, 1, TimeUnit.SECONDS); @@ -83,7 +83,7 @@ public void init() { handleSyncBlock(); } } catch (Exception e) { - logger.error("Handle sync block error.", e); + logger.error("Handle sync block error", e); } }, 10, 1, TimeUnit.SECONDS); } @@ -95,7 +95,7 @@ public void close() { public void startSync(PeerConnection peer) { if (peer.getTronState().equals(TronState.SYNCING)) { - logger.warn("Start sync failed, peer {} is in sync.", peer.getNode().getHost()); + logger.warn("Start sync failed, peer {} is in sync", peer.getNode().getHost()); return; } peer.setTronState(TronState.SYNCING); @@ -109,7 +109,7 @@ public void startSync(PeerConnection peer) { public void syncNext(PeerConnection peer) { try { if (peer.getSyncChainRequested() != null) { - logger.warn("Peer {} is in sync.", peer.getNode().getHost()); + logger.warn("Peer {} is in sync", peer.getNode().getHost()); return; } LinkedList chainSummary = getBlockChainSummary(peer); @@ -273,7 +273,7 @@ private void processSyncBlock(BlockCapsule block) { tronNetDelegate.processBlock(block, true); pbftDataSyncHandler.processPBFTCommitData(block); } catch (Exception e) { - logger.error("Process sync block {} failed.", blockId.getString(), e); + logger.error("Process sync block {} failed", blockId.getString(), e); flag = false; } for (PeerConnection peer : tronNetDelegate.getActivePeer()) { From 8154d8fb0a0bb131ff9ec28e7e40135dfdd7c857 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Fri, 16 Sep 2022 15:23:07 +0800 Subject: [PATCH 0256/1197] refactor(net): change the exception log level of udp message handler --- .../java/org/tron/common/net/udp/handler/MessageHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/common/net/udp/handler/MessageHandler.java b/framework/src/main/java/org/tron/common/net/udp/handler/MessageHandler.java index 6d9524bc23b..656dd9fb667 100644 --- a/framework/src/main/java/org/tron/common/net/udp/handler/MessageHandler.java +++ b/framework/src/main/java/org/tron/common/net/udp/handler/MessageHandler.java @@ -78,7 +78,7 @@ public void channelReadComplete(ChannelHandlerContext ctx) { @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.info("Exception caught in udp message handler, {} {}", + logger.warn("Exception caught in udp message handler, {} {}", ctx.channel().remoteAddress(), cause.getMessage()); ctx.close(); } From 56eae01710e87b18ab3cbc725a8507588a320c30 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 16 Sep 2022 16:29:11 +0800 Subject: [PATCH 0257/1197] refactor(db): optimize log printing 1. add new parameters when printing timeout transactions --- framework/src/main/java/org/tron/core/db/Manager.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index dd19c129cc0..ab6e7c98731 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1398,8 +1398,12 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block } long cost = System.currentTimeMillis() - start; if (cost > 100) { - logger.info("Process transaction {} cost {}.", - Hex.toHexString(transactionInfo.getId()), cost); + String type = "broadcast"; + if (Objects.nonNull(blockCap)) { + type = blockCap.hasWitnessSignature() ? "apply" : "pack"; + } + logger.info("Process transaction {} cost {} ms during {}, {}", + Hex.toHexString(transactionInfo.getId()), cost, type, contract.getType().name()); } Metrics.histogramObserve(requestTimer); return transactionInfo.getInstance(); From 03777fa2104d0501e4833babf69236bad70475c1 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Mon, 19 Sep 2022 11:53:59 +0800 Subject: [PATCH 0258/1197] feat: modify state root --- .../java/org/tron/core/services/jsonrpc/types/BlockResult.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/types/BlockResult.java b/framework/src/main/java/org/tron/core/services/jsonrpc/types/BlockResult.java index 1217bc59ba6..65d0dd56ca9 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/types/BlockResult.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/types/BlockResult.java @@ -96,7 +96,8 @@ public BlockResult(Block block, boolean fullTx, Wallet wallet) { logsBloom = ByteArray.toJsonHex(new byte[256]); // no value transactionsRoot = ByteArray .toJsonHex(block.getBlockHeader().getRawData().getTxTrieRoot().toByteArray()); - stateRoot = ByteArray.toJsonHex(new byte[32]); + stateRoot = ByteArray + .toJsonHex(block.getBlockHeader().getRawData().getAccountStateRoot().toByteArray()); receiptsRoot = ByteArray.toJsonHex(new byte[32]); // no value if (blockCapsule.getNum() == 0) { From 02782349067162c4379744c243ea5fe4ecc62a98 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 19 Sep 2022 12:10:25 +0800 Subject: [PATCH 0259/1197] perf(net): optimize the k-bucket data structure to improve performance --- .../overlay/discover/table/NodeTable.java | 35 ++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java b/framework/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java index f5ba7615736..adff37d80c6 100644 --- a/framework/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java +++ b/framework/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java @@ -20,7 +20,10 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; + import lombok.extern.slf4j.Slf4j; import org.tron.common.overlay.discover.node.Node; @@ -29,7 +32,7 @@ public class NodeTable { private final Node node; // our node private transient NodeBucket[] buckets; - private transient List nodes; + private transient Map nodes; public NodeTable(Node n) { this.node = n; @@ -41,7 +44,7 @@ public Node getNode() { } public final void initialize() { - nodes = new ArrayList<>(); + nodes = new HashMap<>(); buckets = new NodeBucket[KademliaOptions.BINS]; for (int i = 0; i < KademliaOptions.BINS; i++) { buckets[i] = new NodeBucket(i); @@ -49,7 +52,11 @@ public final void initialize() { } public synchronized Node addNode(Node n) { - NodeEntry entry = getNodeEntry(n); + if (n.getHost().equals(node.getHost())) { + return null; + } + + NodeEntry entry = nodes.get(n.getHost()); if (entry != null) { entry.touch(); return null; @@ -60,12 +67,12 @@ public synchronized Node addNode(Node n) { if (lastSeen != null) { return lastSeen.getNode(); } - nodes.add(e); + nodes.put(n.getHost(), e); return null; } public synchronized void dropNode(Node n) { - NodeEntry entry = getNodeEntry(n); + NodeEntry entry = nodes.get(n.getHost()); if (entry != null) { nodes.remove(entry); buckets[getBucketId(entry)].dropNode(entry); @@ -73,11 +80,11 @@ public synchronized void dropNode(Node n) { } public synchronized boolean contains(Node n) { - return getNodeEntry(n) != null; + return nodes.containsKey(n.getHost()); } public synchronized void touchNode(Node n) { - NodeEntry entry = getNodeEntry(n); + NodeEntry entry = nodes.get(n.getHost()); if (entry != null) { entry.touch(); } @@ -103,9 +110,7 @@ public synchronized int getNodesCount() { } public synchronized List getAllNodes() { - List list = new ArrayList<>(nodes); - list.remove(new NodeEntry(node.getId(), node)); - return list; + return new ArrayList<>(nodes.values()); } public synchronized List getClosestNodes(byte[] targetId) { @@ -123,14 +128,4 @@ public synchronized List getClosestNodes(byte[] targetId) { return closestNodes; } - private NodeEntry getNodeEntry(Node n) { - NodeEntry entry = null; - for (NodeEntry e: nodes) { - if (e.getNode().getHost().equals(n.getHost())) { - entry = e; - break; - } - } - return entry; - } } From c16e21a16bbfcf34210db0501a60fcdaa1fba94e Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Mon, 19 Sep 2022 17:00:30 +0800 Subject: [PATCH 0260/1197] fix(reward): fix vote test --- framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java b/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java index 805f767e7da..9622c8a1b25 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java @@ -301,6 +301,7 @@ public void init() throws Exception { VMConfig.initAllowTvmVote(1); manager.getDynamicPropertiesStore().saveChangeDelegation(1); manager.getDynamicPropertiesStore().saveAllowTvmVote(1); + manager.getDynamicPropertiesStore().saveNewRewardAlgorithmEffectiveCycle(); } @After From 01d81a23ecf80fd9aeece63b640134046f8100c2 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 19 Sep 2022 17:25:10 +0800 Subject: [PATCH 0261/1197] fix(net): modify drop node function --- .../java/org/tron/common/overlay/discover/table/NodeTable.java | 2 +- .../org/tron/common/overlay/discover/table/NodeTableTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java b/framework/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java index adff37d80c6..3846dbaf94d 100644 --- a/framework/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java +++ b/framework/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java @@ -74,7 +74,7 @@ public synchronized Node addNode(Node n) { public synchronized void dropNode(Node n) { NodeEntry entry = nodes.get(n.getHost()); if (entry != null) { - nodes.remove(entry); + nodes.remove(n.getHost()); buckets[getBucketId(entry)].dropNode(entry); } } diff --git a/framework/src/test/java/org/tron/common/overlay/discover/table/NodeTableTest.java b/framework/src/test/java/org/tron/common/overlay/discover/table/NodeTableTest.java index 07d52849092..ed43aea43a2 100644 --- a/framework/src/test/java/org/tron/common/overlay/discover/table/NodeTableTest.java +++ b/framework/src/test/java/org/tron/common/overlay/discover/table/NodeTableTest.java @@ -21,7 +21,7 @@ public class NodeTableTest { @Test public void test() { - Node node1 = Node.instanceOf("127.0.0.1:10002"); + Node node1 = Node.instanceOf("127.0.0.5:10002"); NodeTable table = new NodeTable(node1); Node nodeTemp = table.getNode(); From 6dc92b4a95417a7fa77676322b419f4489210271 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 19 Sep 2022 17:46:25 +0800 Subject: [PATCH 0262/1197] fix(db): fix leveldb manifest rewrite 1. stop generate engine.properties if it is not a db path --- .../src/main/java/org/tron/plugins/ArchiveManifest.java | 8 ++++---- plugins/src/main/java/org/tron/plugins/DbArchive.java | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/src/main/java/org/tron/plugins/ArchiveManifest.java b/plugins/src/main/java/org/tron/plugins/ArchiveManifest.java index 144d0c45579..793404ddc2c 100644 --- a/plugins/src/main/java/org/tron/plugins/ArchiveManifest.java +++ b/plugins/src/main/java/org/tron/plugins/ArchiveManifest.java @@ -197,14 +197,14 @@ public boolean doArchive() throws IOException { logger.info("File {},does not exist, ignored.", srcDbPath.toString()); return true; } - if (!checkEngine()) { - logger.info("Db {},not leveldb, ignored.", this.name); - return true; - } if (!checkManifest(levelDbFile.toString())) { logger.info("Db {},no need, ignored.", levelDbFile.toString()); return true; } + if (!checkEngine()) { + logger.info("Db {},not leveldb, ignored.", this.name); + return true; + } open(); logger.info("Db {} archive use {} ms.", this.name, (System.currentTimeMillis() - startTime)); return true; diff --git a/plugins/src/main/java/org/tron/plugins/DbArchive.java b/plugins/src/main/java/org/tron/plugins/DbArchive.java index 333098949fe..2339fc9590b 100644 --- a/plugins/src/main/java/org/tron/plugins/DbArchive.java +++ b/plugins/src/main/java/org/tron/plugins/DbArchive.java @@ -187,12 +187,12 @@ public void doArchive() { logger.info("File {},does not exist, ignored.", srcDbPath); return; } - if (!checkEngine()) { - logger.info("Db {},not leveldb, ignored.", this.name); - return; - } try { if (checkManifest(levelDbFile.toString())) { + if (!checkEngine()) { + logger.info("Db {},not leveldb, ignored.", this.name); + return; + } open(); logger.info("Db {} archive use {} ms.", this.name, (System.currentTimeMillis() - startTime)); From ff32a9d541dd7bbf3c42edb952f2fbf3c0e14b7b Mon Sep 17 00:00:00 2001 From: chaozhu Date: Mon, 19 Sep 2022 16:33:17 -0700 Subject: [PATCH 0263/1197] feat(freezeV2): new unfreeze program 1. add UNFREEZE_DELAY_DAYS proposal 2. add new freeze/unfreeze actuator Closes # --- .../core/actuator/FreezeBalanceActuator.java | 5 + .../actuator/FreezeBalanceV2Actuator.java | 163 ++++ .../actuator/UnfreezeBalanceV2Actuator.java | 320 +++++++ .../org/tron/core/utils/ProposalUtil.java | 16 +- .../org/tron/core/capsule/AccountCapsule.java | 159 +++- .../core/store/DynamicPropertiesStore.java | 21 + .../common/parameter/CommonParameter.java | 4 + .../java/org/tron/core/config/Parameter.java | 6 +- .../src/main/java/org/tron/core/Wallet.java | 5 + .../tron/core/consensus/ProposalService.java | 7 + .../org/tron/core/services/RpcApiService.java | 13 + .../services/http/FreezeBalanceV2Servlet.java | 36 + .../http/UnFreezeBalanceV2Servlet.java | 38 + .../http/WithdrawBalanceV2Servlet.java | 43 + .../actuator/FreezeBalanceV2ActuatorTest.java | 546 ++++++++++++ .../UnfreezeBalanceV2ActuatorTest.java | 836 ++++++++++++++++++ protocol/src/main/protos/api/api.proto | 8 + 17 files changed, 2218 insertions(+), 8 deletions(-) create mode 100755 actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java create mode 100755 actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java create mode 100644 framework/src/main/java/org/tron/core/services/http/FreezeBalanceV2Servlet.java create mode 100644 framework/src/main/java/org/tron/core/services/http/UnFreezeBalanceV2Servlet.java create mode 100644 framework/src/main/java/org/tron/core/services/http/WithdrawBalanceV2Servlet.java create mode 100644 framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java create mode 100644 framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java index f026a8769e6..e194999a25f 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java @@ -249,6 +249,11 @@ public boolean validate() throws ContractValidateException { } + if (dynamicStore.getUnfreezeDelayDays() > 0) { + throw new ContractValidateException( + "freeze v2 is open, old freeze is closed"); + } + return true; } diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java new file mode 100755 index 00000000000..743aaff6824 --- /dev/null +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java @@ -0,0 +1,163 @@ +package org.tron.core.actuator; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import lombok.extern.slf4j.Slf4j; +import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.AccountStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.BalanceContract.FreezeBalanceV2Contract; +import java.util.Objects; + +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +@Slf4j(topic = "actuator") +public class FreezeBalanceV2Actuator extends AbstractActuator { + + public FreezeBalanceV2Actuator() { + super(ContractType.FreezeBalanceV2Contract, FreezeBalanceV2Contract.class); + } + + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + + long fee = calcFee(); + final FreezeBalanceV2Contract freezeBalanceV2Contract; + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + try { + freezeBalanceV2Contract = any.unpack(FreezeBalanceV2Contract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + AccountCapsule accountCapsule = accountStore.get(freezeBalanceV2Contract.getOwnerAddress().toByteArray()); + + if (dynamicStore.supportAllowNewResourceModel() + && accountCapsule.oldTronPowerIsNotInitialized()) { + accountCapsule.initializeOldTronPower(); + } + + long newBalance = accountCapsule.getBalance() - freezeBalanceV2Contract.getFrozenBalance(); + long frozenBalance = freezeBalanceV2Contract.getFrozenBalance(); + + switch (freezeBalanceV2Contract.getResource()) { + case BANDWIDTH: + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + dynamicStore.addTotalNetWeight(frozenBalance / TRX_PRECISION); + break; + case ENERGY: + accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); + dynamicStore.addTotalEnergyWeight(frozenBalance / TRX_PRECISION); + break; + case TRON_POWER: + accountCapsule.addFrozenForTronPowerV2(frozenBalance); + dynamicStore.addTotalTronPowerWeight(frozenBalance / TRX_PRECISION); + break; + default: + logger.debug("Resource Code Error."); + } + + accountCapsule.setBalance(newBalance); + accountStore.put(accountCapsule.createDbKey(), accountCapsule); + + ret.setStatus(fee, code.SUCESS); + + return true; + } + + + @Override + public boolean validate() throws ContractValidateException { + if (this.any == null) { + throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); + } + if (chainBaseManager == null) { + throw new ContractValidateException(ActuatorConstant.STORE_NOT_EXIST); + } + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + if (!any.is(FreezeBalanceV2Contract.class)) { + throw new ContractValidateException( + "contract type error,expected type [FreezeBalanceV2Contract],real type[" + any + .getClass() + "]"); + } + + final FreezeBalanceV2Contract freezeBalanceV2Contract; + try { + freezeBalanceV2Contract = this.any.unpack(FreezeBalanceV2Contract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + throw new ContractValidateException(e.getMessage()); + } + byte[] ownerAddress = freezeBalanceV2Contract.getOwnerAddress().toByteArray(); + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + + AccountCapsule accountCapsule = accountStore.get(ownerAddress); + if (accountCapsule == null) { + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + throw new ContractValidateException( + ActuatorConstant.ACCOUNT_EXCEPTION_STR + readableOwnerAddress + NOT_EXIST_STR); + } + + long frozenBalance = freezeBalanceV2Contract.getFrozenBalance(); + if (frozenBalance <= 0) { + throw new ContractValidateException("frozenBalance must be positive"); + } + if (frozenBalance < TRX_PRECISION) { + throw new ContractValidateException("frozenBalance must be more than 1TRX"); + } + + if (frozenBalance > accountCapsule.getBalance()) { + throw new ContractValidateException("frozenBalance must be less than accountBalance"); + } + + switch (freezeBalanceV2Contract.getResource()) { + case BANDWIDTH: + case ENERGY: + break; + case TRON_POWER: + if (!dynamicStore.supportAllowNewResourceModel()) { + throw new ContractValidateException( + "ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]"); + } + break; + default: + if (dynamicStore.supportAllowNewResourceModel()) { + throw new ContractValidateException( + "ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY、TRON_POWER]"); + } else { + throw new ContractValidateException( + "ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]"); + } + } + + return true; + } + + @Override + public ByteString getOwnerAddress() throws InvalidProtocolBufferException { + return any.unpack(FreezeBalanceV2Contract.class).getOwnerAddress(); + } + + @Override + public long calcFee() { + return 0; + } + +} \ No newline at end of file diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java new file mode 100755 index 00000000000..09c2b90e6ef --- /dev/null +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java @@ -0,0 +1,320 @@ +package org.tron.core.actuator; + +import com.google.common.collect.Lists; +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import lombok.extern.slf4j.Slf4j; +import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.capsule.VotesCapsule; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.service.MortgageService; +import org.tron.core.store.AccountStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.store.VotesStore; +import org.tron.protos.Protocol; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.BalanceContract.UnfreezeBalanceV2Contract; +import org.tron.protos.contract.Common; + +import java.util.Iterator; +import java.util.List; +import java.util.Objects; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +@Slf4j(topic = "actuator") +public class UnfreezeBalanceV2Actuator extends AbstractActuator { + + private static final int UNFREEZE_MAX_TIMES = 32; + + public UnfreezeBalanceV2Actuator() { + super(ContractType.UnfreezeBalanceV2Contract, UnfreezeBalanceV2Contract.class); + } + + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + + long fee = calcFee(); + final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract; + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + MortgageService mortgageService = chainBaseManager.getMortgageService(); + try { + unfreezeBalanceV2Contract = any.unpack(UnfreezeBalanceV2Contract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + byte[] ownerAddress = unfreezeBalanceV2Contract.getOwnerAddress().toByteArray(); + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + + mortgageService.withdrawReward(ownerAddress); + + AccountCapsule accountCapsule = accountStore.get(ownerAddress); + this.unfreezeExpire(accountCapsule, now); + long unfreezeBalance = unfreezeBalanceV2Contract.getUnfreezeBalance(); + + if (dynamicStore.supportAllowNewResourceModel() + && accountCapsule.oldTronPowerIsNotInitialized()) { + accountCapsule.initializeOldTronPower(); + } + + Common.ResourceCode freezeType = unfreezeBalanceV2Contract.getResource(); + + this.updateAccountFrozenInfo(freezeType, accountCapsule, unfreezeBalance); + + long expireTime = this.calcUnfreezeExpireTime(now); + accountCapsule.addUnfrozenV2List(freezeType, unfreezeBalance, expireTime); + + this.updateTotalResourceWeight(unfreezeBalanceV2Contract, unfreezeBalance); + this.clearVotes(accountCapsule,unfreezeBalanceV2Contract, ownerAddress); + + if (dynamicStore.supportAllowNewResourceModel() + && !accountCapsule.oldTronPowerIsInvalid()) { + accountCapsule.invalidateOldTronPower(); + } + + accountStore.put(ownerAddress, accountCapsule); + + ret.setUnfreezeAmount(unfreezeBalance); + ret.setStatus(fee, code.SUCESS); + return true; + } + + @Override + public boolean validate() throws ContractValidateException { + if (this.any == null) { + throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); + } + if (chainBaseManager == null) { + throw new ContractValidateException(ActuatorConstant.STORE_NOT_EXIST); + } + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + if (!this.any.is(UnfreezeBalanceV2Contract.class)) { + throw new ContractValidateException( + "contract type error, expected type [UnfreezeBalanceContract], real type[" + any + .getClass() + "]"); + } + final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract; + try { + unfreezeBalanceV2Contract = this.any.unpack(UnfreezeBalanceV2Contract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + throw new ContractValidateException(e.getMessage()); + } + + byte[] ownerAddress = unfreezeBalanceV2Contract.getOwnerAddress().toByteArray(); + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + + AccountCapsule accountCapsule = accountStore.get(ownerAddress); + if (accountCapsule == null) { + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + throw new ContractValidateException( + ACCOUNT_EXCEPTION_STR + readableOwnerAddress + "] does not exist"); + } + + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + switch (unfreezeBalanceV2Contract.getResource()) { + case BANDWIDTH: + if (!this.checkExistFreezedBalance(accountCapsule, Common.ResourceCode.BANDWIDTH)) { + throw new ContractValidateException("no frozenBalance(BANDWIDTH)"); + } + break; + case ENERGY: + if (!this.checkExistFreezedBalance(accountCapsule, Common.ResourceCode.ENERGY)) { + throw new ContractValidateException("no frozenBalance(Energy)"); + } + break; + case TRON_POWER: + if (dynamicStore.supportAllowNewResourceModel()) { + if (!this.checkExistFreezedBalance(accountCapsule, Common.ResourceCode.TRON_POWER)) { + throw new ContractValidateException("no frozenBalance(TronPower)"); + } + } else { + throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + } + break; + default: + if (dynamicStore.supportAllowNewResourceModel()) { + throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、Energy、TRON_POWER]"); + } else { + throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + } + } + + if (!checkUnfreezeBalance(accountCapsule, unfreezeBalanceV2Contract, unfreezeBalanceV2Contract.getResource())) { + throw new ContractValidateException( + "Invalid unfreeze_balance, freezing resource[" + unfreezeBalanceV2Contract.getResource() + "] is not enough" + ); + } + + int unfreezingCount = accountCapsule.getUnfreezingV2Count(now); + if (UNFREEZE_MAX_TIMES <= unfreezingCount) { + throw new ContractValidateException("Invalid unfreeze operation, unfreezing times is over limit"); + } + + return true; + } + + @Override + public ByteString getOwnerAddress() throws InvalidProtocolBufferException { + return any.unpack(UnfreezeBalanceV2Contract.class).getOwnerAddress(); + } + + @Override + public long calcFee() { + return 0; + } + + public boolean checkExistFreezedBalance(AccountCapsule accountCapsule, Common.ResourceCode freezeType) { + boolean checkOk = false; + + long frozenAmount = 0; + List frozenV2List = accountCapsule.getFrozenV2List(); + for (Protocol.Account.FreezeV2 frozenV2 : frozenV2List) { + if (frozenV2.getType().equals(freezeType)) { + frozenAmount = frozenV2.getAmount(); + if (frozenAmount > 0) { + checkOk = true; + break; + } + } + } + + return checkOk; + } + + public boolean checkUnfreezeBalance(AccountCapsule accountCapsule, + final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract, + Common.ResourceCode freezeType) { + boolean checkOk = false; + + long frozenAmount = 0L; + List freezeV2List = accountCapsule.getFrozenV2List(); + for (Protocol.Account.FreezeV2 freezeV2 : freezeV2List) { + if (freezeV2.getType().equals(freezeType)) { + frozenAmount = freezeV2.getAmount(); + break; + } + } + + if (unfreezeBalanceV2Contract.getUnfreezeBalance() <= frozenAmount) { + checkOk = true; + } + + return checkOk; + } + + public long calcUnfreezeExpireTime(long now) { + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + long unfreezeDelayDays = dynamicStore.getUnfreezeDelayDays(); + + return now + unfreezeDelayDays * FROZEN_PERIOD; + } + + public void updateAccountFrozenInfo(Common.ResourceCode freezeType, AccountCapsule accountCapsule, long unfreezeBalance) { + List freezeV2List = accountCapsule.getFrozenV2List(); + for (int i = 0; i < freezeV2List.size(); i++) { + if (freezeV2List.get(i).getType().equals(freezeType)) { + Protocol.Account.FreezeV2 freezeV2 = Protocol.Account.FreezeV2.newBuilder() + .setAmount(freezeV2List.get(i).getAmount() - unfreezeBalance) + .setType(freezeV2List.get(i).getType()) + .build(); + accountCapsule.updateFrozenV2List(i, freezeV2); + break; + } + } + } + + public void unfreezeExpire(AccountCapsule accountCapsule, long now) { + long unfreezeBalance = 0L; + + List unFrozenV2List = Lists.newArrayList(); + unFrozenV2List.addAll(accountCapsule.getUnfrozenV2List()); + Iterator iterator = unFrozenV2List.iterator(); + + while (iterator.hasNext()) { + Protocol.Account.UnFreezeV2 next = iterator.next(); + if (next.getUnfreezeExpireTime() <= now) { + unfreezeBalance += next.getUnfreezeAmount(); + iterator.remove(); + } + } + + accountCapsule.setInstance( + accountCapsule.getInstance().toBuilder() + .setBalance(accountCapsule.getBalance() + unfreezeBalance) + .clearUnfrozenV2() + .addAllUnfrozenV2(unFrozenV2List).build() + ); + } + + public void updateTotalResourceWeight(final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract, + long unfreezeBalance) { + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + switch (unfreezeBalanceV2Contract.getResource()) { + case BANDWIDTH: + dynamicStore.addTotalNetWeight(-unfreezeBalance / TRX_PRECISION); + break; + case ENERGY: + dynamicStore.addTotalEnergyWeight(-unfreezeBalance / TRX_PRECISION); + break; + case TRON_POWER: + dynamicStore.addTotalTronPowerWeight(-unfreezeBalance / TRX_PRECISION); + break; + default: + //this should never happen + break; + } + } + + private void clearVotes(AccountCapsule accountCapsule, + final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract, + byte[] ownerAddress) { + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + VotesStore votesStore = chainBaseManager.getVotesStore(); + + boolean needToClearVote = true; + if (dynamicStore.supportAllowNewResourceModel() + && accountCapsule.oldTronPowerIsInvalid()) { + switch (unfreezeBalanceV2Contract.getResource()) { + case BANDWIDTH: + case ENERGY: + needToClearVote = false; + break; + default: + break; + } + } + + if (needToClearVote) { + VotesCapsule votesCapsule; + if (!votesStore.has(ownerAddress)) { + votesCapsule = new VotesCapsule( + unfreezeBalanceV2Contract.getOwnerAddress(), + accountCapsule.getVotesList() + ); + } else { + votesCapsule = votesStore.get(ownerAddress); + } + accountCapsule.clearVotes(); + votesCapsule.clearNewVotes(); + votesStore.put(ownerAddress, votesCapsule); + } + } +} \ No newline at end of file diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 4f128884dfd..3f45ff21a13 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -560,6 +560,18 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case UNFREEZE_DELAY_DAYS: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_6)) { + throw new ContractValidateException( + "Bad chain parameter id [UNFREEZE_DELAY_DAYS]"); + } + if (value < 1 || value > 365) { + throw new ContractValidateException( + "This value[UNFREEZE_DELAY_DAYS] is only allowed to be in the range 1-365"); + } + break; + } + default: break; } @@ -623,7 +635,9 @@ public enum ProposalType { // current value, value range TOTAL_NET_LIMIT(62), // 43_200_000_000L, [0, 1000_000_000_000L] ALLOW_TVM_LONDON(63), // 0, 1 ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX(65), // 0, 1 - ALLOW_ASSET_OPTIMIZATION(66); // 0, 1 + ALLOW_ASSET_OPTIMIZATION(66), // 0, 1 + UNFREEZE_DELAY_DAYS(67); // 0, [1, 365] + private long code; diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index 2c30baa8d4e..bffbc08d653 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -37,6 +37,7 @@ import org.tron.protos.Protocol.Vote; import org.tron.protos.contract.AccountContract.AccountCreateContract; import org.tron.protos.contract.AccountContract.AccountUpdateContract; +import org.tron.protos.contract.Common; @Slf4j(topic = "capsule") public class AccountCapsule implements ProtoCapsule, Comparable { @@ -350,6 +351,11 @@ public long getAcquiredDelegatedFrozenBalanceForBandwidth() { return this.account.getAcquiredDelegatedFrozenBalanceForBandwidth(); } + public void addFrozenBalanceForBandwidthV2(long balance) { + Common.ResourceCode type = Common.ResourceCode.BANDWIDTH; + this.addFrozenBalanceForResource(type, balance); + } + public void setAcquiredDelegatedFrozenBalanceForBandwidth(long balance) { this.account = this.account.toBuilder().setAcquiredDelegatedFrozenBalanceForBandwidth(balance) .build(); @@ -434,6 +440,35 @@ public void addDelegatedFrozenBalanceForEnergy(long balance) { .build(); } + public void addFrozenBalanceForEnergyV2(long balance) { + Common.ResourceCode type = Common.ResourceCode.ENERGY; + this.addFrozenBalanceForResource(type, balance); + } + + private void addFrozenBalanceForResource(Common.ResourceCode type, long balance) { + boolean doUpdate = false; + for (int i = 0; i < this.account.getFrozenV2List().size(); i++) { + if (this.account.getFrozenV2List().get(i).getType().equals(type)) { + long newAmount = this.account.getFrozenV2(i).getAmount() + balance; + Account.FreezeV2 freezeV2 = Account.FreezeV2.newBuilder() + .setType(type) + .setAmount(newAmount) + .build(); + this.updateFrozenV2List(i, freezeV2); + doUpdate = true; + break; + } + } + + if (!doUpdate) { + Account.FreezeV2 freezeV2 = Account.FreezeV2.newBuilder() + .setType(type) + .setAmount(balance) + .build(); + this.addFrozenV2List(freezeV2); + } + } + @Override public String toString() { return this.account.toString(); @@ -495,19 +530,82 @@ public long getTronPower() { tp += account.getAccountResource().getFrozenBalanceForEnergy().getFrozenBalance(); tp += account.getDelegatedFrozenBalanceForBandwidth(); tp += account.getAccountResource().getDelegatedFrozenBalanceForEnergy(); + + // add v2 tron power + for (Account.FreezeV2 freezeV2 : account.getFrozenV2List()) { + // type: BANDWIDTH,ENERGY + if (freezeV2.getType() != Common.ResourceCode.TRON_POWER) { + tp += freezeV2.getAmount(); + } + } + return tp; } public long getAllTronPower() { if (account.getOldTronPower() == -1) { - return getTronPowerFrozenBalance(); + return getTronPowerFrozenBalance() + getTronPowerFrozenBalanceV2(); } else if (account.getOldTronPower() == 0) { - return getTronPower() + getTronPowerFrozenBalance(); + return getTronPower() + getTronPowerFrozenBalance() + getTronPowerFrozenBalanceV2(); } else { - return account.getOldTronPower() + getTronPowerFrozenBalance(); + return account.getOldTronPower() + getTronPowerFrozenBalance() + getTronPowerFrozenBalanceV2(); } } + + + public List getFrozenV2List() { + return account.getFrozenV2List(); + } + + public List getUnfrozenV2List() { + return account.getUnfrozenV2List(); + } + + public void updateFrozenV2List(int i, Account.FreezeV2 frozenV2) { + this.account = this.account.toBuilder() + .setFrozenV2(i, frozenV2) + .build(); + } + + public void addFrozenV2List(Account.FreezeV2 frozenV2) { + this.account = this.account.toBuilder().addFrozenV2(frozenV2).build(); + } + + /** + * + * @param type + * @param unfreezeAmount + * @param expireTime + * @return + */ + public void addUnfrozenV2List(Common.ResourceCode type, long unfreezeAmount, long expireTime) { + + Account.UnFreezeV2 unFreezeV2 = Account.UnFreezeV2.newBuilder() + .setType(type) + .setUnfreezeAmount(unfreezeAmount) + .setUnfreezeExpireTime(expireTime) + .build(); + this.account = this.account.toBuilder() + .addUnfrozenV2(unFreezeV2) + .build(); + } + + + public int getUnfreezingV2Count(long now) { + int count = 0; + + List unFreezeV2List = account.getUnfrozenV2List(); + for (Account.UnFreezeV2 item : unFreezeV2List) { + if (item.getUnfreezeExpireTime() > now) { + count++; + } + } + + return count; + } + + /*************************** start asset ****************************************/ public boolean getAssetOptimized() { @@ -757,8 +855,21 @@ public long getFrozenBalance() { return frozenBalance[0]; } + /** + * only for test + * @return + */ + public long getFrozenBalanceV2() { + List freezeV2List = getFrozenV2List(); + long amount = 0L; + for (Account.FreezeV2 freezeV2 : freezeV2List) { + amount += freezeV2.getAmount(); + } + return amount; + } + public long getAllFrozenBalanceForBandwidth() { - return getFrozenBalance() + getAcquiredDelegatedFrozenBalanceForBandwidth(); + return getFrozenBalance() + getAcquiredDelegatedFrozenBalanceForBandwidth() + getBandWidthFrozenBalanceV2(); } public int getFrozenSupplyCount() { @@ -893,6 +1004,28 @@ public long getEnergyFrozenBalance() { return this.account.getAccountResource().getFrozenBalanceForEnergy().getFrozenBalance(); } + + private long getBandWidthFrozenBalanceV2() { + List freezeV2List = this.account.getFrozenV2List(); + for (Account.FreezeV2 freezeV2 : freezeV2List) { + if(freezeV2.getType().equals(Common.ResourceCode.BANDWIDTH)) { + return freezeV2.getAmount(); + } + } + return 0L; + } + + private long getEnergyFrozenBalanceV2() { + List freezeV2List = this.account.getFrozenV2List(); + for (Account.FreezeV2 freezeV2 : freezeV2List) { + if(freezeV2.getType().equals(Common.ResourceCode.ENERGY)) { + return freezeV2.getAmount(); + } + } + return 0L; + } + + public boolean oldTronPowerIsNotInitialized() { return this.account.getOldTronPower() == 0; } @@ -935,10 +1068,26 @@ public void setFrozenForTronPower(long frozenBalance, long expireTime) { .build()); } + public void addFrozenForTronPowerV2(long balance) { + Common.ResourceCode type = Common.ResourceCode.TRON_POWER; + this.addFrozenBalanceForResource(type, balance); + } + public long getTronPowerFrozenBalance() { return this.account.getTronPower().getFrozenBalance(); } + public long getTronPowerFrozenBalanceV2() { + List freezeV2List = this.account.getFrozenV2List(); + for (Account.FreezeV2 freezeV2 : freezeV2List) { + if(freezeV2.getType().equals(Common.ResourceCode.TRON_POWER)) { + return freezeV2.getAmount(); + } + } + return 0L; + } + + public long getEnergyUsage() { return this.account.getAccountResource().getEnergyUsage(); } @@ -951,7 +1100,7 @@ public void setEnergyUsage(long energyUsage) { } public long getAllFrozenBalanceForEnergy() { - return getEnergyFrozenBalance() + getAcquiredDelegatedFrozenBalanceForEnergy(); + return getEnergyFrozenBalance() + getAcquiredDelegatedFrozenBalanceForEnergy() + getEnergyFrozenBalanceV2(); } public long getLatestConsumeTimeForEnergy() { diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index dce79515ad4..b523ed7527c 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -187,6 +187,8 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX = "ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX".getBytes(); + private static final byte[] UNFREEZE_DELAY_DAYS = "UNFREEZE_DELAY_DAYS".getBytes(); + @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { @@ -846,6 +848,14 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { this.saveAllowHigherLimitForMaxCpuTimeOfOneTx( CommonParameter.getInstance().getAllowHigherLimitForMaxCpuTimeOfOneTx()); } + + try { + this.getUnfreezeDelayDays(); + } catch (IllegalArgumentException e) { + this.saveUnfreezeDelayDays( + CommonParameter.getInstance().getUnfreezeDelayDays() + ); + } } public String intArrayToString(int[] a) { @@ -2516,6 +2526,17 @@ public long getAllowHigherLimitForMaxCpuTimeOfOneTx() { () -> new IllegalArgumentException(msg)); } + public long getUnfreezeDelayDays() { + return Optional.ofNullable(getUnchecked(UNFREEZE_DELAY_DAYS)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow(() -> new IllegalArgumentException("not found UNFREEZE_DELAY_DAYS")); + } + + public void saveUnfreezeDelayDays(long value) { + this.put(UNFREEZE_DELAY_DAYS, new BytesCapsule(ByteArray.fromLong(value))); + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 283ffd299e3..f84706e6851 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -557,6 +557,10 @@ public class CommonParameter { @Setter public long blockCacheTimeout = 60; + @Getter + @Setter + public long unfreezeDelayDays = 0L; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index 35a763f64c0..c826cc2dd44 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -18,7 +18,9 @@ public enum ForkBlockVersionEnum { VERSION_4_2(21, 1596780000000L, 80), VERSION_4_3(22, 1596780000000L, 80), VERSION_4_4(23, 1596780000000L, 80), - VERSION_4_5(24, 1596780000000L, 80); + VERSION_4_5(24, 1596780000000L, 80), + VERSION_4_6(25, 1596780000000L, 80); + @Getter private int value; @@ -66,7 +68,7 @@ public class ChainConstant { public static final int SINGLE_REPEAT = 1; public static final int BLOCK_FILLED_SLOTS_NUMBER = 128; public static final int MAX_FROZEN_NUMBER = 1; - public static final int BLOCK_VERSION = 24; + public static final int BLOCK_VERSION = 25; public static final long FROZEN_PERIOD = 86_400_000L; public static final long TRX_PRECISION = 1000_000L; } diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index ae04f249e1e..b8f8aac35ec 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1098,6 +1098,11 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getAllowAssetOptimization()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getUnfreezeDelayDays") + .setValue(dbManager.getDynamicPropertiesStore().getUnfreezeDelayDays()) + .build()); + return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index f6f55b0097c..51e20307084 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -284,6 +284,13 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().setAllowAssetOptimization(entry.getValue()); break; } + + case UNFREEZE_DELAY_DAYS: { + manager.getDynamicPropertiesStore().saveUnfreezeDelayDays(entry.getValue()); + manager.getDynamicPropertiesStore().addSystemContractAndSetPermission(54); + manager.getDynamicPropertiesStore().addSystemContractAndSetPermission(55); + break; + } default: find = false; break; diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index c964536aa33..c3184a46307 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -142,6 +142,7 @@ import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; import org.tron.protos.contract.AssetIssueContractOuterClass.UnfreezeAssetContract; import org.tron.protos.contract.AssetIssueContractOuterClass.UpdateAssetContract; +import org.tron.protos.contract.BalanceContract; import org.tron.protos.contract.BalanceContract.AccountBalanceRequest; import org.tron.protos.contract.BalanceContract.AccountBalanceResponse; import org.tron.protos.contract.BalanceContract.BlockBalanceTrace; @@ -1480,6 +1481,12 @@ public void freezeBalance2(FreezeBalanceContract request, createTransactionExtention(request, ContractType.FreezeBalanceContract, responseObserver); } + @Override + public void freezeBalanceV2(BalanceContract.FreezeBalanceV2Contract request, + StreamObserver responseObserver) { + createTransactionExtention(request, ContractType.FreezeBalanceV2Contract, responseObserver); + } + @Override public void unfreezeBalance(UnfreezeBalanceContract request, StreamObserver responseObserver) { @@ -1501,6 +1508,12 @@ public void unfreezeBalance2(UnfreezeBalanceContract request, createTransactionExtention(request, ContractType.UnfreezeBalanceContract, responseObserver); } + @Override + public void unfreezeBalanceV2(BalanceContract.UnfreezeBalanceV2Contract request, + StreamObserver responseObserver) { + createTransactionExtention(request, ContractType.UnfreezeBalanceV2Contract, responseObserver); + } + @Override public void withdrawBalance(WithdrawBalanceContract request, StreamObserver responseObserver) { diff --git a/framework/src/main/java/org/tron/core/services/http/FreezeBalanceV2Servlet.java b/framework/src/main/java/org/tron/core/services/http/FreezeBalanceV2Servlet.java new file mode 100644 index 00000000000..f1687a5bbb1 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/FreezeBalanceV2Servlet.java @@ -0,0 +1,36 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.contract.BalanceContract.FreezeBalanceV2Contract; + +@Component +@Slf4j(topic = "API") +public class FreezeBalanceV2Servlet extends RateLimiterServlet { + + @Autowired + private Wallet wallet; + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + PostParams params = PostParams.getPostParams(request); + FreezeBalanceV2Contract.Builder build = FreezeBalanceV2Contract.newBuilder(); + JsonFormat.merge(params.getParams(), build, params.isVisible()); + Transaction tx = wallet + .createTransactionCapsule(build.build(), ContractType.FreezeBalanceV2Contract) + .getInstance(); + JSONObject jsonObject = JSONObject.parseObject(params.getParams()); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, params.isVisible())); + } catch (Exception e) { + Util.processError(e, response); + } + } +} diff --git a/framework/src/main/java/org/tron/core/services/http/UnFreezeBalanceV2Servlet.java b/framework/src/main/java/org/tron/core/services/http/UnFreezeBalanceV2Servlet.java new file mode 100644 index 00000000000..614a7ca6b7a --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/UnFreezeBalanceV2Servlet.java @@ -0,0 +1,38 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.contract.BalanceContract.UnfreezeBalanceV2Contract; + +@Component +@Slf4j(topic = "API") +public class UnFreezeBalanceV2Servlet extends RateLimiterServlet { + @Autowired + private Wallet wallet; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + PostParams params = PostParams.getPostParams(request); + UnfreezeBalanceV2Contract.Builder build = UnfreezeBalanceV2Contract.newBuilder(); + JsonFormat.merge(params.getParams(), build, params.isVisible()); + Transaction tx = wallet + .createTransactionCapsule(build.build(), ContractType.UnfreezeBalanceV2Contract) + .getInstance(); + JSONObject jsonObject = JSONObject.parseObject(params.getParams()); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, params.isVisible())); + } catch (Exception e) { + Util.processError(e, response); + } + } +} \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/services/http/WithdrawBalanceV2Servlet.java b/framework/src/main/java/org/tron/core/services/http/WithdrawBalanceV2Servlet.java new file mode 100644 index 00000000000..1696fa8863b --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/WithdrawBalanceV2Servlet.java @@ -0,0 +1,43 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.contract.BalanceContract.WithdrawBalanceV2Contract; + +@Component +@Slf4j(topic = "API") +public class WithdrawBalanceV2Servlet extends RateLimiterServlet { + + @Autowired + private Wallet wallet; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + String contract = request.getReader().lines() + .collect(Collectors.joining(System.lineSeparator())); + Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); + WithdrawBalanceV2Contract.Builder build = WithdrawBalanceV2Contract.newBuilder(); + JsonFormat.merge(contract, build, visible); + Transaction tx = wallet + .createTransactionCapsule(build.build(), ContractType.WithdrawBalanceV2Contract) + .getInstance(); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); + } catch (Exception e) { + Util.processError(e, response); + } + } +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java new file mode 100644 index 00000000000..3a06ef7f8d9 --- /dev/null +++ b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java @@ -0,0 +1,546 @@ +package org.tron.core.actuator; + +import static junit.framework.TestCase.fail; +import static org.tron.core.config.Parameter.ChainConstant.TRANSFER_FEE; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import java.io.File; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.core.ChainBaseManager; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; +import org.tron.core.capsule.DelegatedResourceCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.Parameter.ChainConstant; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.protos.Protocol.AccountType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.AssetIssueContractOuterClass; +import org.tron.protos.contract.BalanceContract; +import org.tron.protos.contract.Common.ResourceCode; + + + +@Slf4j +public class FreezeBalanceV2ActuatorTest { + + private static final String dbPath = "output_freeze_balance_test"; + private static final String OWNER_ADDRESS; + private static final String RECEIVER_ADDRESS; + private static final String OWNER_ADDRESS_INVALID = "aaaa"; + private static final String OWNER_ACCOUNT_INVALID; + private static final long initBalance = 10_000_000_000L; + private static Manager dbManager; + private static TronApplicationContext context; + + static { + Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; + OWNER_ACCOUNT_INVALID = + Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; + } + + /** + * Init data. + */ + @BeforeClass + public static void init() { + dbManager = context.getBean(Manager.class); + // Args.setParam(new String[]{"--output-directory", dbPath}, + // "config-junit.conf"); + // dbManager = new Manager(); + // dbManager.init(); + } + + /** + * Release resources. + */ + @AfterClass + public static void destroy() { + Args.clearParam(); + context.destroy(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.info("Release resources failure."); + } + } + + /** + * create temp Capsule test need. + */ + @Before + public void createAccountCapsule() { + AccountCapsule ownerCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + + AccountCapsule receiverCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), + AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); + } + + private Any getContractV2ForBandwidth(String ownerAddress, long frozenBalance) { + return Any.pack( + BalanceContract.FreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setFrozenBalance(frozenBalance) + .setResource(ResourceCode.BANDWIDTH) + .build()); + } + + private Any getContractForCpuV2(String ownerAddress, long frozenBalance) { + return Any.pack( + BalanceContract.FreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setFrozenBalance(frozenBalance) + .setResource(ResourceCode.ENERGY) + .build()); + } + + + private Any getContractForTronPowerV2(String ownerAddress, long frozenBalance) { + return Any.pack( + BalanceContract.FreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setFrozenBalance(frozenBalance) + .setResource(ResourceCode.TRON_POWER) + .build()); + } + + private Any getDelegatedContractForBandwidthV2(String ownerAddress, + long frozenBalance) { + return Any.pack( + BalanceContract.FreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + //.setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiverAddress))) + .setFrozenBalance(frozenBalance) + .build()); + } + + private Any getDelegatedContractForCpuV2(String ownerAddress, + long frozenBalance) { + return Any.pack( + BalanceContract.FreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + //.setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiverAddress))) + .setFrozenBalance(frozenBalance) + .setResource(ResourceCode.ENERGY) + .build()); + } + + @Test + public void testFreezeBalanceForBandwidth() { + long frozenBalance = 1_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractV2ForBandwidth(OWNER_ADDRESS, frozenBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule owner = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(owner.getBalance(), initBalance - frozenBalance + - TRANSFER_FEE); + Assert.assertEquals(owner.getFrozenBalanceV2(), frozenBalance); + Assert.assertEquals(frozenBalance, owner.getTronPower()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void testFreezeBalanceForEnergy() { + long frozenBalance = 1_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForCpuV2(OWNER_ADDRESS, frozenBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule owner = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(owner.getBalance(), initBalance - frozenBalance + - TRANSFER_FEE); + Assert.assertEquals(0L, owner.getAllFrozenBalanceForBandwidth()); + Assert.assertEquals(frozenBalance, owner.getAllFrozenBalanceForEnergy()); + Assert.assertEquals(frozenBalance, owner.getTronPower()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void testFreezeDelegatedBalanceForBandwidthWithContractAddress() { + AccountCapsule receiverCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), + AccountType.Contract, + initBalance); + dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); + + dbManager.getDynamicPropertiesStore().saveAllowTvmConstantinople(1); + + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + long frozenBalance = 1_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegatedContractForBandwidthV2(OWNER_ADDRESS, frozenBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + + AccountCapsule owner = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(owner.getBalance(), initBalance - frozenBalance + - TRANSFER_FEE); + Assert.assertEquals(0L, owner.getAllFrozenBalanceForBandwidth()); + Assert.assertEquals(0L, owner.getAllFrozenBalanceForEnergy()); + Assert.assertEquals(frozenBalance, owner.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(frozenBalance, owner.getTronPower()); + + } catch (ContractValidateException e) { + Assert.assertEquals(e.getMessage(), "Do not allow delegate resources to contract addresses"); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + + } + + + @Test + public void testFreezeDelegatedBalanceForCpuSameNameTokenClose() { + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(0); + long frozenBalance = 1_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegatedContractForCpuV2(OWNER_ADDRESS, frozenBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + long totalEnergyWeightBefore = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule owner = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + Assert.assertEquals(owner.getBalance(), initBalance - frozenBalance + - TRANSFER_FEE); + Assert.assertEquals(0L, owner.getAllFrozenBalanceForBandwidth()); + Assert.assertEquals(frozenBalance, owner.getAllFrozenBalanceForEnergy()); + Assert.assertEquals(0L, owner.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0L, owner.getDelegatedFrozenBalanceForEnergy()); + + + AccountCapsule receiver = + dbManager.getAccountStore().get(ByteArray.fromHexString(RECEIVER_ADDRESS)); + Assert.assertEquals(0L, receiver.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0L, receiver.getAcquiredDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0L, receiver.getTronPower()); + + long totalEnergyWeightAfter = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); + Assert.assertEquals(totalEnergyWeightBefore + frozenBalance / 1000_000L, + totalEnergyWeightAfter); + + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void freezeLessThanZero() { + long frozenBalance = -1_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractV2ForBandwidth(OWNER_ADDRESS, frozenBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("frozenBalance must be positive", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void freezeMoreThanBalance() { + long frozenBalance = 11_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractV2ForBandwidth(OWNER_ADDRESS, frozenBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("frozenBalance must be less than accountBalance", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void invalidOwnerAddress() { + long frozenBalance = 1_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractV2ForBandwidth(OWNER_ADDRESS_INVALID, frozenBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + + Assert.assertEquals("Invalid address", e.getMessage()); + + } catch (ContractExeException e) { + Assert.assertTrue(e instanceof ContractExeException); + } + + } + + @Test + public void invalidOwnerAccount() { + long frozenBalance = 1_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractV2ForBandwidth(OWNER_ACCOUNT_INVALID, frozenBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Account[" + OWNER_ACCOUNT_INVALID + "] not exists", + e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void lessThan1TrxTest() { + long frozenBalance = 1; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractV2ForBandwidth(OWNER_ADDRESS, frozenBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("frozenBalance must be more than 1TRX", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + //@Test + public void moreThanFrozenNumber() { + long frozenBalance = 1_000_000_000L; + FreezeBalanceActuator actuator = new FreezeBalanceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractV2ForBandwidth(OWNER_ADDRESS, frozenBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + } catch (ContractValidateException e) { + long maxFrozenNumber = ChainConstant.MAX_FROZEN_NUMBER; + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("max frozen number is: " + maxFrozenNumber, e.getMessage()); + + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void commonErrorCheck() { + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + ActuatorTest actuatorTest = new ActuatorTest(actuator, dbManager); + actuatorTest.noContract(); + + Any invalidContractTypes = Any.pack(AssetIssueContractOuterClass.AssetIssueContract.newBuilder() + .build()); + actuatorTest.setInvalidContract(invalidContractTypes); + actuatorTest.setInvalidContractTypeMsg("contract type error", + "contract type error,expected type [FreezeBalanceV2Contract],real type["); + actuatorTest.invalidContractType(); + + long frozenBalance = 1_000_000_000L; + actuatorTest.setContract(getContractV2ForBandwidth(OWNER_ADDRESS, frozenBalance)); + actuatorTest.nullTransationResult(); + + actuatorTest.setNullDBManagerMsg("No account store or dynamic store!"); + actuatorTest.nullDBManger(); + } + + + @Test + public void testFreezeBalanceForEnergyWithoutOldTronPowerAfterNewResourceModel() { + long frozenBalance = 1_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + ChainBaseManager chainBaseManager = dbManager.getChainBaseManager(); + chainBaseManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + actuator.setChainBaseManager(chainBaseManager) + .setAny(getContractForCpuV2(OWNER_ADDRESS, frozenBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule owner = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(-1L, owner.getInstance().getOldTronPower()); + Assert.assertEquals(0L, owner.getAllTronPower()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void testFreezeBalanceForEnergyWithOldTronPowerAfterNewResourceModel() { + long frozenBalance = 1_000_000_000L; + long duration = 3; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + ChainBaseManager chainBaseManager = dbManager.getChainBaseManager(); + chainBaseManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + actuator.setChainBaseManager(chainBaseManager) + .setAny(getContractForCpuV2(OWNER_ADDRESS, frozenBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + AccountCapsule owner = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + owner.setFrozenForEnergy(100L,0L); + chainBaseManager.getAccountStore().put(ByteArray.fromHexString(OWNER_ADDRESS),owner); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + owner = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(100L, owner.getInstance().getOldTronPower()); + Assert.assertEquals(100L, owner.getAllTronPower()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void testFreezeBalanceForTronPowerWithOldTronPowerAfterNewResourceModel() { + long frozenBalance = 1_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + ChainBaseManager chainBaseManager = dbManager.getChainBaseManager(); + chainBaseManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + actuator.setChainBaseManager(chainBaseManager) + .setAny(getContractForTronPowerV2(OWNER_ADDRESS, frozenBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + AccountCapsule owner = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + owner.setFrozenForEnergy(100L,0L); + chainBaseManager.getAccountStore().put(ByteArray.fromHexString(OWNER_ADDRESS),owner); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + owner = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(100L, owner.getInstance().getOldTronPower()); + Assert.assertEquals(100L, owner.getTronPower()); + Assert.assertEquals(frozenBalance + 100, owner.getAllTronPower()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + +} diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java new file mode 100644 index 00000000000..d165307b524 --- /dev/null +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java @@ -0,0 +1,836 @@ +package org.tron.core.actuator; + +import static junit.framework.TestCase.fail; +import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; +import org.tron.core.capsule.DelegatedResourceCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.capsule.VotesCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.protos.Protocol.AccountType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.Protocol.Vote; +import org.tron.protos.contract.AssetIssueContractOuterClass; +import org.tron.protos.contract.BalanceContract; +import org.tron.protos.contract.Common.ResourceCode; + +@Slf4j +public class UnfreezeBalanceV2ActuatorTest { + + private static final String dbPath = "output_unfreeze_balance_test"; + private static final String OWNER_ADDRESS; + private static final String RECEIVER_ADDRESS; + private static final String OWNER_ADDRESS_INVALID = "aaaa"; + private static final String OWNER_ACCOUNT_INVALID; + private static final long initBalance = 10_000_000_000L; + private static final long frozenBalance = 1_000_000_000L; + private static final long smallTatalResource = 100L; + private static Manager dbManager; + private static TronApplicationContext context; + + static { + Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; + OWNER_ACCOUNT_INVALID = + Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; + } + + /** + * Init data. + */ + @BeforeClass + public static void init() { + dbManager = context.getBean(Manager.class); + // Args.setParam(new String[]{"--output-directory", dbPath}, + // "config-junit.conf"); + // dbManager = new Manager(); + // dbManager.init(); + } + + /** + * Release resources. + */ + @AfterClass + public static void destroy() { + Args.clearParam(); + context.destroy(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.info("Release resources failure."); + } + } + + /** + * create temp Capsule test need. + */ + @Before + public void createAccountCapsule() { + AccountCapsule ownerCapsule = new AccountCapsule(ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); + + AccountCapsule receiverCapsule = new AccountCapsule(ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); + } + + private Any getContractForBandwidthV2(String ownerAddress, long unfreezeBalance) { + return Any.pack( + BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress( + ByteString.copyFrom(ByteArray.fromHexString(ownerAddress)) + ) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.BANDWIDTH) + .build() + ); + } + + private Any getContractForCpuV2(String ownerAddress, long unfreezeBalance) { + return Any.pack(BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.ENERGY).build()); + } + + private Any getContractForTronPowerV2(String ownerAddress, long unfreezeBalance) { + return Any.pack(BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.TRON_POWER).build()); + } + + private Any getDelegatedContractForBandwidth( + String ownerAddress, long unfreezeBalance + ) { + return Any.pack(BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.BANDWIDTH).build()); + } + + private Any getDelegatedContractForCpu( + String ownerAddress, String receiverAddress, long unfreezeBalance + ) { + return Any.pack(BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.ENERGY).build()); + } + + private Any getContract(String ownerAddress, ResourceCode resourceCode, long unfreezeBalance) { + return Any.pack(BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(resourceCode).build()); + } + + + private Any getContractForTronPowerV2_001(String ownerAddress, long unfreezeBalance) { + return Any.pack(BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setUnfreezeBalance(unfreezeBalance).build()); + } + + @Test + public void testUnfreezeBalanceForBandwidth() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + long unfreezeBalance = frozenBalance - 100; + + Assert.assertEquals(accountCapsule.getFrozenBalanceV2(), frozenBalance); + Assert.assertEquals(accountCapsule.getTronPower(), frozenBalance); + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + long totalNetWeightBefore = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule owner = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + + //Assert.assertEquals(owner.getBalance(), initBalance + frozenBalance); + Assert.assertEquals(owner.getFrozenBalanceV2(), 100); + Assert.assertEquals(owner.getTronPower(), 100L); + + long totalNetWeightAfter = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); + Assert.assertEquals(totalNetWeightBefore, + totalNetWeightAfter + (frozenBalance - 100) / 1000_000L); + + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void testUnfreezeBalanceForEnergy() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + long unfreezeBalance = frozenBalance - 100; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); + Assert.assertEquals(accountCapsule.getAllFrozenBalanceForEnergy(), frozenBalance); + Assert.assertEquals(accountCapsule.getTronPower(), frozenBalance); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForCpuV2(OWNER_ADDRESS, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + long totalEnergyWeightBefore = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule owner = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + + //Assert.assertEquals(owner.getBalance(), initBalance + frozenBalance); + Assert.assertEquals(owner.getAllFrozenBalanceForEnergy(), 100); + Assert.assertEquals(owner.getTronPower(), 100); + long totalEnergyWeightAfter = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); + Assert.assertEquals(totalEnergyWeightBefore, + totalEnergyWeightAfter + (frozenBalance - 100) / 1000_000L); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void invalidOwnerAddress() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + long unfreezeBalance = frozenBalance; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.setFrozen(1_000_000_000L, now); + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS_INVALID, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + + Assert.assertEquals("Invalid address", e.getMessage()); + + } catch (ContractExeException e) { + Assert.assertTrue(e instanceof ContractExeException); + } + + } + + @Test + public void invalidOwnerAccount() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + long unfreezeBalance = frozenBalance; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.setFrozen(1_000_000_000L, now); + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ACCOUNT_INVALID, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Account[" + OWNER_ACCOUNT_INVALID + "] does not exist", + e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void noFrozenBalance() { + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + long unfreezeBalance = frozenBalance; + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("no frozenBalance(BANDWIDTH)", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void testClearVotes() { + byte[] ownerAddressBytes = ByteArray.fromHexString(OWNER_ADDRESS); + ByteString ownerAddress = ByteString.copyFrom(ownerAddressBytes); + long unfreezeBalance = frozenBalance; + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddressBytes); + accountCapsule.addFrozenBalanceForBandwidthV2(1_000_000_000L); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + dbManager.getVotesStore().reset(); + Assert.assertNull(dbManager.getVotesStore().get(ownerAddressBytes)); + try { + actuator.validate(); + actuator.execute(ret); + VotesCapsule votesCapsule = dbManager.getVotesStore().get(ownerAddressBytes); + Assert.assertNotNull(votesCapsule); + Assert.assertEquals(0, votesCapsule.getNewVotes().size()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + // if had votes + List oldVotes = new ArrayList(); + VotesCapsule votesCapsule = new VotesCapsule( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), oldVotes); + votesCapsule.addNewVotes( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), 100); + dbManager.getVotesStore().put(ByteArray.fromHexString(OWNER_ADDRESS), votesCapsule); + accountCapsule.addFrozenBalanceForBandwidthV2(1_000_000_000L); + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + try { + actuator.validate(); + actuator.execute(ret); + votesCapsule = dbManager.getVotesStore().get(ownerAddressBytes); + Assert.assertNotNull(votesCapsule); + Assert.assertEquals(0, votesCapsule.getNewVotes().size()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + } + + @Test + public void commonErrorCheck() { + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + ActuatorTest actuatorTest = new ActuatorTest(actuator, dbManager); + actuatorTest.noContract(); + long unfreezeBalance = frozenBalance; + + Any invalidContractTypes = Any.pack( + AssetIssueContractOuterClass.AssetIssueContract.newBuilder().build() + ); + actuatorTest.setInvalidContract(invalidContractTypes); + actuatorTest.setInvalidContractTypeMsg("contract type error", + "contract type error, expected type [UnfreezeBalanceContract], real type["); + actuatorTest.invalidContractType(); + + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + Assert.assertEquals(accountCapsule.getAllFrozenBalanceForBandwidth(), frozenBalance); + Assert.assertEquals(accountCapsule.getTronPower(), frozenBalance); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + + actuatorTest.setContract(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + actuatorTest.nullTransationResult(); + + actuatorTest.setNullDBManagerMsg("No account store or dynamic store!"); + actuatorTest.nullDBManger(); + } + + + @Test + public void testUnfreezeBalanceForEnergyWithOldTronPowerAfterNewResourceModel() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + long unfreezeBalance = frozenBalance; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); + accountCapsule.setOldTronPower(frozenBalance); + accountCapsule.addVotes( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), 100L); + Assert.assertEquals(accountCapsule.getAllFrozenBalanceForEnergy(), frozenBalance); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForCpuV2(OWNER_ADDRESS, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule owner = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(owner.getVotesList().size(), 0L); + Assert.assertEquals(owner.getInstance().getOldTronPower(), -1L); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void testUnfreezeBalanceForEnergyWithoutOldTronPowerAfterNewResourceModel() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + long unfreezeBalance = frozenBalance; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); + accountCapsule.setOldTronPower(-1L); + accountCapsule.addVotes( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), 100L); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForCpuV2(OWNER_ADDRESS, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule owner = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(owner.getVotesList().size(), 1L); + Assert.assertEquals(owner.getInstance().getOldTronPower(), -1L); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void testUnfreezeBalanceForTronPowerWithOldTronPowerAfterNewResourceModel() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + long unfreezeBalance = frozenBalance - 100; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); + accountCapsule.addFrozenForTronPowerV2(frozenBalance); + accountCapsule.addVotes( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), 100L); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForTronPowerV2(OWNER_ADDRESS, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule owner = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(owner.getVotesList().size(), 0L); + Assert.assertEquals(owner.getInstance().getOldTronPower(), -1L); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void testUnfreezeBalanceForTronPowerWithOldTronPowerAfterNewResourceModelError() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + long unfreezeBalance = frozenBalance - 100; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); + accountCapsule.addFrozenForTronPowerV2(frozenBalance); + accountCapsule.addVotes( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), 100L); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForTronPowerV2(OWNER_ADDRESS, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + //Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + } + } + + + @Test + public void testUnfreezeBalanceCheckExistFreezedBalance() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + long unfreezeBalance = frozenBalance - 100; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); + accountCapsule.addFrozenForTronPowerV2(frozenBalance); + //accountCapsule.addDelegatedFrozenBalanceForBandwidthV2(frozenBalance); + //accountCapsule.addDelegatedFrozenBalanceForEnergyV2(frozenBalance); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + + boolean bret1 = actuator.checkExistFreezedBalance( + accountCapsule, ResourceCode.BANDWIDTH); + Assert.assertTrue(true == bret1); + boolean bret2 = actuator.checkExistFreezedBalance( + accountCapsule, ResourceCode.ENERGY); + Assert.assertTrue(true == bret2); + boolean bret3 = actuator.checkExistFreezedBalance( + accountCapsule, ResourceCode.TRON_POWER); + Assert.assertTrue(true == bret3); + + } + + + @Test + public void testUnfreezeBalanceCheckUnfreezeBalance() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + long unfreezeBalance = frozenBalance - 1; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + + BalanceContract.UnfreezeBalanceV2Contract unfreezeBalanceV2Contract = + BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.BANDWIDTH) + .build(); + boolean bret1 = actuator.checkUnfreezeBalance( + accountCapsule, unfreezeBalanceV2Contract, ResourceCode.BANDWIDTH + ); + Assert.assertTrue(true == bret1); + } + + + @Test + public void testUnfreezeBalanceGetFreezeType() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + long unfreezeBalance = frozenBalance - 1; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + + BalanceContract.UnfreezeBalanceV2Contract unfreezeBalanceV2Contract = + BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.TRON_POWER) + //.setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))) + .build(); + + ResourceCode freezeType = unfreezeBalanceV2Contract.getResource(); + + Assert.assertTrue(ResourceCode.TRON_POWER.equals(freezeType)); + } + + @Test + public void testUnfreezeBalanceCalcUnfreezeExpireTime() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(30); + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + long unfreezeBalance = frozenBalance - 1; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + + BalanceContract.UnfreezeBalanceV2Contract unfreezeBalanceV2Contract = + BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.TRON_POWER) + //.setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))) + .build(); + + long ret = actuator.calcUnfreezeExpireTime(now); + + Assert.assertTrue(true); + } + + @Test + public void testUnfreezeBalanceUpdateAccountFrozenInfo() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(30); + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + long unfreezeBalance = frozenBalance - 1; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + + BalanceContract.UnfreezeBalanceV2Contract unfreezeBalanceV2Contract = + BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.TRON_POWER) + //.setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))) + .build(); + + actuator.updateAccountFrozenInfo( + ResourceCode.BANDWIDTH, accountCapsule, unfreezeBalance + ); + + Assert.assertTrue(accountCapsule.getAllFrozenBalanceForBandwidth() == 1); + } + + + @Test + public void testUnfreezeBalanceUnfreezeExpire() { + + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(30); + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + + long unfreezeBalance = frozenBalance - 1; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + + long balance = accountCapsule.getBalance(); + accountCapsule.addUnfrozenV2List( + ResourceCode.BANDWIDTH, + 1, + now + 19 * FROZEN_PERIOD + ); + accountCapsule.addUnfrozenV2List( + ResourceCode.BANDWIDTH, + 10, + now + 31 * FROZEN_PERIOD + ); + accountCapsule.addUnfrozenV2List( + ResourceCode.ENERGY, + 20, + now + 32 * FROZEN_PERIOD + ); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now + 31 * FROZEN_PERIOD); + actuator.unfreezeExpire(accountCapsule, + dbManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp()); + + Assert.assertEquals(accountCapsule.getBalance(), balance + 11); + Assert.assertEquals(accountCapsule.getUnfrozenV2List().size(), 1); + Assert.assertEquals(accountCapsule.getUnfrozenV2List().get(0).getUnfreezeAmount(), 20); + } + + + @Test + public void testAddTotalResourceWeight() { + + long now = System.currentTimeMillis(); + long total = frozenBalance; + dbManager.getDynamicPropertiesStore().saveTotalTronPowerWeight(total); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(30); + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + + long unfreezeBalance = frozenBalance; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + + long balance = accountCapsule.getBalance(); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + BalanceContract.UnfreezeBalanceV2Contract unfreezeBalanceV2Contract = + BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.TRON_POWER) + .build(); + + actuator.updateTotalResourceWeight(unfreezeBalanceV2Contract, unfreezeBalance); + + Assert.assertEquals(total - unfreezeBalance / TRX_PRECISION, + dbManager.getDynamicPropertiesStore().getTotalTronPowerWeight()); + + } + + @Test + public void testUnfreezeBalanceUnfreezeCount() { + + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(30); + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + + long unfreezeBalance = frozenBalance - 1; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + + long balance = accountCapsule.getBalance(); + accountCapsule.addUnfrozenV2List( + ResourceCode.BANDWIDTH, + 1, + now + 19 * FROZEN_PERIOD + ); + accountCapsule.addUnfrozenV2List( + ResourceCode.BANDWIDTH, + 10, + now + 31 * FROZEN_PERIOD + ); + accountCapsule.addUnfrozenV2List( + ResourceCode.ENERGY, + 20, + now + 32 * FROZEN_PERIOD + ); + + int count = accountCapsule.getUnfreezingV2Count(now); + Assert.assertEquals(3, count); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + + dbManager.getDynamicPropertiesStore() + .saveLatestBlockHeaderTimestamp(now + 32 * FROZEN_PERIOD); + actuator.unfreezeExpire(accountCapsule, + dbManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp()); + + + int after_count = accountCapsule.getUnfreezingV2Count(now); + Assert.assertEquals(0, after_count); + + } + + +} + diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 94219db1ec2..baa4a5fad78 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -224,6 +224,10 @@ service Wallet { //Use this function instead of FreezeBalance. rpc FreezeBalance2 (FreezeBalanceContract) returns (TransactionExtention) { } + //Use this function when FreezeBalanceV2. + rpc FreezeBalanceV2 (FreezeBalanceV2Contract) returns (TransactionExtention) { + } + //Please use UnfreezeBalance2 instead of this function. rpc UnfreezeBalance (UnfreezeBalanceContract) returns (Transaction) { option (google.api.http) = { @@ -237,6 +241,10 @@ service Wallet { //Use this function instead of UnfreezeBalance. rpc UnfreezeBalance2 (UnfreezeBalanceContract) returns (TransactionExtention) { } + //Use this function when UnfreezeBalanceV2. + rpc UnfreezeBalanceV2 (UnfreezeBalanceV2Contract) returns (TransactionExtention) { + } + //Please use UnfreezeAsset2 instead of this function. rpc UnfreezeAsset (UnfreezeAssetContract) returns (Transaction) { option (google.api.http) = { From a9173547a9a70bd75a061a37753ddb1df7c9486d Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 16 Sep 2022 16:29:11 +0800 Subject: [PATCH 0264/1197] refactor(db): add detail for init db 1. print log detail when corruption error happens --- .../org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java index e4ba36a84f9..0a98ebdb030 100644 --- a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java @@ -140,7 +140,7 @@ private void openDatabase(Options dbOptions) throws IOException { dbOptions.cacheSize() / 1024 / 1024, dbOptions.maxOpenFiles()); } catch (IOException e) { if (e.getMessage().contains("Corruption:")) { - logger.warn("DB {} corruption detected, try to repair it.", this.getDBName()); + logger.warn("DB {} corruption detected, try to repair it.", this.getDBName(), e); factory.repair(dbPath.toFile(), dbOptions); logger.warn("DB {} corruption detected, repair done.", this.getDBName()); database = factory.open(dbPath.toFile(), dbOptions); From a5f2584f5c86647bb3689d455da1185877b2c936 Mon Sep 17 00:00:00 2001 From: chaozhu Date: Mon, 19 Sep 2022 19:16:26 -0700 Subject: [PATCH 0265/1197] fix(freezeV2): fix some test failed cases --- .../AccountPermissionUpdateActuatorTest.java | 8 +- .../actuator/FreezeBalanceV2ActuatorTest.java | 87 ------------------- .../UnfreezeBalanceV2ActuatorTest.java | 2 - 3 files changed, 4 insertions(+), 93 deletions(-) diff --git a/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java index b5d1d7e0ac0..ab0847ff072 100644 --- a/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java @@ -969,7 +969,7 @@ public void checkAvailableContractTypeCorrespondingToCode() { // and you will get the value from the output, // then update the value to checkAvailableContractType // and checkActiveDefaultOperations - String validContractType = "7fff1fc0037e3800000000000000000000000000000000000000000000000000"; + String validContractType = "7fff1fc0037ef807000000000000000000000000000000000000000000000000"; byte[] availableContractType = new byte[32]; for (ContractType contractType : ContractType.values()) { @@ -996,7 +996,7 @@ public void checkActiveDefaultOperationsCorrespondingToCode() { // 7fff1fc0033e0000000000000000000000000000000000000000000000000000, // and it should call the addSystemContractAndSetPermission to add new contract // type - String validContractType = "7fff1fc0033e3800000000000000000000000000000000000000000000000000"; + String validContractType = "7fff1fc0033ef807000000000000000000000000000000000000000000000000"; byte[] availableContractType = new byte[32]; for (ContractType contractType : ContractType.values()) { @@ -1019,7 +1019,7 @@ public void checkActiveDefaultOperationsCorrespondingToCode() { @Test public void checkAvailableContractType() { - String validContractType = "7fff1fc0037e3900000000000000000000000000000000000000000000000000"; + String validContractType = "7fff1fc0037ef907000000000000000000000000000000000000000000000000"; byte[] availableContractType = new byte[32]; for (ContractType contractType : ContractType.values()) { @@ -1040,7 +1040,7 @@ public void checkAvailableContractType() { @Test public void checkActiveDefaultOperations() { - String validContractType = "7fff1fc0033e3900000000000000000000000000000000000000000000000000"; + String validContractType = "7fff1fc0033ef907000000000000000000000000000000000000000000000000"; byte[] availableContractType = new byte[32]; for (ContractType contractType : ContractType.values()) { diff --git a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java index 3a06ef7f8d9..f4118fbef90 100644 --- a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java @@ -19,8 +19,6 @@ import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; -import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; -import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.Parameter.ChainConstant; @@ -208,91 +206,6 @@ public void testFreezeBalanceForEnergy() { } - @Test - public void testFreezeDelegatedBalanceForBandwidthWithContractAddress() { - AccountCapsule receiverCapsule = - new AccountCapsule( - ByteString.copyFromUtf8("receiver"), - ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), - AccountType.Contract, - initBalance); - dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); - - dbManager.getDynamicPropertiesStore().saveAllowTvmConstantinople(1); - - dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); - long frozenBalance = 1_000_000_000L; - FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); - actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getDelegatedContractForBandwidthV2(OWNER_ADDRESS, frozenBalance)); - - TransactionResultCapsule ret = new TransactionResultCapsule(); - - try { - actuator.validate(); - actuator.execute(ret); - - AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); - - Assert.assertEquals(owner.getBalance(), initBalance - frozenBalance - - TRANSFER_FEE); - Assert.assertEquals(0L, owner.getAllFrozenBalanceForBandwidth()); - Assert.assertEquals(0L, owner.getAllFrozenBalanceForEnergy()); - Assert.assertEquals(frozenBalance, owner.getDelegatedFrozenBalanceForBandwidth()); - Assert.assertEquals(frozenBalance, owner.getTronPower()); - - } catch (ContractValidateException e) { - Assert.assertEquals(e.getMessage(), "Do not allow delegate resources to contract addresses"); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); - } - - - } - - - @Test - public void testFreezeDelegatedBalanceForCpuSameNameTokenClose() { - dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(0); - long frozenBalance = 1_000_000_000L; - FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); - actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getDelegatedContractForCpuV2(OWNER_ADDRESS, frozenBalance)); - - TransactionResultCapsule ret = new TransactionResultCapsule(); - long totalEnergyWeightBefore = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); - try { - actuator.validate(); - actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); - AccountCapsule owner = dbManager.getAccountStore() - .get(ByteArray.fromHexString(OWNER_ADDRESS)); - Assert.assertEquals(owner.getBalance(), initBalance - frozenBalance - - TRANSFER_FEE); - Assert.assertEquals(0L, owner.getAllFrozenBalanceForBandwidth()); - Assert.assertEquals(frozenBalance, owner.getAllFrozenBalanceForEnergy()); - Assert.assertEquals(0L, owner.getDelegatedFrozenBalanceForBandwidth()); - Assert.assertEquals(0L, owner.getDelegatedFrozenBalanceForEnergy()); - - - AccountCapsule receiver = - dbManager.getAccountStore().get(ByteArray.fromHexString(RECEIVER_ADDRESS)); - Assert.assertEquals(0L, receiver.getAcquiredDelegatedFrozenBalanceForBandwidth()); - Assert.assertEquals(0L, receiver.getAcquiredDelegatedFrozenBalanceForEnergy()); - Assert.assertEquals(0L, receiver.getTronPower()); - - long totalEnergyWeightAfter = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); - Assert.assertEquals(totalEnergyWeightBefore + frozenBalance / 1000_000L, - totalEnergyWeightAfter); - - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); - } - } - @Test public void freezeLessThanZero() { long frozenBalance = -1_000_000_000L; diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java index d165307b524..3633d1cba08 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java @@ -21,8 +21,6 @@ import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; -import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; -import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.VotesCapsule; import org.tron.core.config.DefaultConfig; From 07a92b30f2ab5f0083665e3478126beaf2829359 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Mon, 19 Sep 2022 15:18:35 +0800 Subject: [PATCH 0266/1197] feat(freezeV2): modify unfreezebalance --- .../WithdrawExpireUnfreezeActuator.java | 153 ++++++++++ .../org/tron/core/capsule/AccountCapsule.java | 107 +++---- .../org/tron/core/services/RpcApiService.java | 12 +- .../services/http/FullNodeHttpApiService.java | 5 + ...ava => WithdrawExpireUnfreezeServlet.java} | 15 +- .../actuator/FreezeBalanceV2ActuatorTest.java | 2 +- .../UnfreezeBalanceV2ActuatorTest.java | 4 +- .../WithdrawExpireUnfreezeActuatorTest.java | 275 ++++++++++++++++++ protocol/src/main/protos/api/api.proto | 4 + protocol/src/main/protos/core/Tron.proto | 2 +- .../core/contract/balance_contract.proto | 2 +- 11 files changed, 507 insertions(+), 74 deletions(-) create mode 100755 actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java rename framework/src/main/java/org/tron/core/services/http/{WithdrawBalanceV2Servlet.java => WithdrawExpireUnfreezeServlet.java} (78%) create mode 100644 framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java diff --git a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java new file mode 100755 index 00000000000..5ba0a32e2be --- /dev/null +++ b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java @@ -0,0 +1,153 @@ +package org.tron.core.actuator; + +import com.google.common.math.LongMath; +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import lombok.extern.slf4j.Slf4j; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.AccountStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.Protocol.Account.UnFreezeV2; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.BalanceContract.WithdrawExpireUnfreezeContract; + +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; + + +@Slf4j(topic = "actuator") +public class WithdrawExpireUnfreezeActuator extends AbstractActuator { + + public WithdrawExpireUnfreezeActuator() { + super(ContractType.WithdrawExpireUnfreezeContract, WithdrawExpireUnfreezeContract.class); + } + + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + long fee = calcFee(); + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + final WithdrawExpireUnfreezeContract withdrawExpireUnfreezeContract; + try { + withdrawExpireUnfreezeContract = any.unpack(WithdrawExpireUnfreezeContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + AccountCapsule accountCapsule = accountStore. + get(withdrawExpireUnfreezeContract.getOwnerAddress().toByteArray()); + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); + long totalWithdrawUnfreeze = getTotalWithdrawUnfreeze(unfrozenV2List, now); + accountCapsule.setInstance(accountCapsule.getInstance().toBuilder() + .setBalance(accountCapsule.getBalance() + totalWithdrawUnfreeze) + .setLatestWithdrawTime(now) + .build()); + List newUnFreezeList = getRemainWithdrawList(unfrozenV2List, now); + accountCapsule.clearUnfrozenV2(); + newUnFreezeList.forEach(accountCapsule::addUnfrozenV2); + accountStore.put(accountCapsule.createDbKey(), accountCapsule); + ret.setStatus(fee, code.SUCESS); + return true; + } + + @Override + public boolean validate() throws ContractValidateException { + if (Objects.isNull(this.any)) { + throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); + } + if (Objects.isNull(chainBaseManager)) { + throw new ContractValidateException(ActuatorConstant.STORE_NOT_EXIST); + } + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + if (!this.any.is(WithdrawExpireUnfreezeContract.class)) { + throw new ContractValidateException( + "contract type error, expected type [WithdrawExpireUnfreezeContract], real type[" + any + .getClass() + "]"); + } + final WithdrawExpireUnfreezeContract withdrawExpireUnfreezeContract; + try { + withdrawExpireUnfreezeContract = this.any.unpack(WithdrawExpireUnfreezeContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + throw new ContractValidateException(e.getMessage()); + } + byte[] ownerAddress = withdrawExpireUnfreezeContract.getOwnerAddress().toByteArray(); + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + AccountCapsule accountCapsule = accountStore.get(ownerAddress); + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + if (Objects.isNull(accountCapsule)) { + throw new ContractValidateException(ACCOUNT_EXCEPTION_STR + + readableOwnerAddress + NOT_EXIST_STR); + } + + boolean isGP = CommonParameter.getInstance() + .getGenesisBlock().getWitnesses().stream().anyMatch(witness -> + Arrays.equals(ownerAddress, witness.getAddress())); + if (isGP) { + throw new ContractValidateException( + ACCOUNT_EXCEPTION_STR + readableOwnerAddress + + "] is a guard representative and is not allowed to withdraw Balance"); + } + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); + long totalWithdrawUnfreeze = getTotalWithdrawUnfreeze(unfrozenV2List, now); + if (totalWithdrawUnfreeze <= 0) { + throw new ContractValidateException("no unFreeze balance to withdraw "); + } + try { + LongMath.checkedAdd(accountCapsule.getBalance(), totalWithdrawUnfreeze); + } catch (ArithmeticException e) { + logger.debug(e.getMessage(), e); + throw new ContractValidateException(e.getMessage()); + } + return true; + } + + private long getTotalWithdrawUnfreeze(List unfrozenV2List, long now) { + return getTotalWithdrawList(unfrozenV2List, now).stream() + .mapToLong(UnFreezeV2::getUnfreezeAmount).sum(); + } + + private List getTotalWithdrawList(List unfrozenV2List, long now) { + return unfrozenV2List.stream().filter(unfrozenV2 -> (unfrozenV2.getUnfreezeAmount() > 0 + && unfrozenV2.getUnfreezeExpireTime() <= now)).collect(Collectors.toList()); + } + + private List getRemainWithdrawList(List unfrozenV2List, long now) { + return unfrozenV2List.stream() + .filter(unfrozenV2 -> unfrozenV2.getUnfreezeExpireTime() > now) + .collect(Collectors.toList()); + } + + @Override + public ByteString getOwnerAddress() throws InvalidProtocolBufferException { + return any.unpack(WithdrawExpireUnfreezeContract.class).getOwnerAddress(); + } + + @Override + public long calcFee() { + return 0; + } + +} diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index bffbc08d653..919e7a411d8 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -19,8 +19,6 @@ import com.google.common.collect.Maps; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; -import java.util.List; -import java.util.Map; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.ByteArray; import org.tron.core.capsule.utils.AssetUtil; @@ -30,6 +28,8 @@ import org.tron.protos.Protocol.Account.AccountResource; import org.tron.protos.Protocol.Account.Builder; import org.tron.protos.Protocol.Account.Frozen; +import org.tron.protos.Protocol.Account.FreezeV2; +import org.tron.protos.Protocol.Account.UnFreezeV2; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Key; import org.tron.protos.Protocol.Permission; @@ -39,6 +39,14 @@ import org.tron.protos.contract.AccountContract.AccountUpdateContract; import org.tron.protos.contract.Common; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; +import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; + @Slf4j(topic = "capsule") public class AccountCapsule implements ProtoCapsule, Comparable { @@ -530,25 +538,19 @@ public long getTronPower() { tp += account.getAccountResource().getFrozenBalanceForEnergy().getFrozenBalance(); tp += account.getDelegatedFrozenBalanceForBandwidth(); tp += account.getAccountResource().getDelegatedFrozenBalanceForEnergy(); - - // add v2 tron power - for (Account.FreezeV2 freezeV2 : account.getFrozenV2List()) { - // type: BANDWIDTH,ENERGY - if (freezeV2.getType() != Common.ResourceCode.TRON_POWER) { - tp += freezeV2.getAmount(); - } - } - + tp += getFrozenV2List().stream().filter(o -> o.getType() != TRON_POWER) + .mapToLong(FreezeV2::getAmount).sum(); return tp; } public long getAllTronPower() { if (account.getOldTronPower() == -1) { - return getTronPowerFrozenBalance() + getTronPowerFrozenBalanceV2(); + return getTronPowerFrozenBalance() + getTronPowerFrozenV2Balance(); } else if (account.getOldTronPower() == 0) { - return getTronPower() + getTronPowerFrozenBalance() + getTronPowerFrozenBalanceV2(); + return getTronPower() + getTronPowerFrozenBalance() + getTronPowerFrozenV2Balance(); } else { - return account.getOldTronPower() + getTronPowerFrozenBalance() + getTronPowerFrozenBalanceV2(); + return account.getOldTronPower() + getTronPowerFrozenBalance() + + getTronPowerFrozenV2Balance(); } } @@ -572,13 +574,6 @@ public void addFrozenV2List(Account.FreezeV2 frozenV2) { this.account = this.account.toBuilder().addFrozenV2(frozenV2).build(); } - /** - * - * @param type - * @param unfreezeAmount - * @param expireTime - * @return - */ public void addUnfrozenV2List(Common.ResourceCode type, long unfreezeAmount, long expireTime) { Account.UnFreezeV2 unFreezeV2 = Account.UnFreezeV2.newBuilder() @@ -855,21 +850,18 @@ public long getFrozenBalance() { return frozenBalance[0]; } - /** - * only for test - * @return - */ - public long getFrozenBalanceV2() { - List freezeV2List = getFrozenV2List(); - long amount = 0L; - for (Account.FreezeV2 freezeV2 : freezeV2List) { - amount += freezeV2.getAmount(); + public long getFrozenV2BalanceForBandwidth() { + List frozenList = getFrozenV2List(); + if (frozenList.isEmpty()) { + return 0; } - return amount; + return frozenList.stream().filter(o -> o.getType() == BANDWIDTH) + .mapToLong(FreezeV2::getAmount).sum(); } public long getAllFrozenBalanceForBandwidth() { - return getFrozenBalance() + getAcquiredDelegatedFrozenBalanceForBandwidth() + getBandWidthFrozenBalanceV2(); + return getFrozenBalance() + getAcquiredDelegatedFrozenBalanceForBandwidth() + + getFrozenV2BalanceForBandwidth(); } public int getFrozenSupplyCount() { @@ -1004,28 +996,15 @@ public long getEnergyFrozenBalance() { return this.account.getAccountResource().getFrozenBalanceForEnergy().getFrozenBalance(); } - - private long getBandWidthFrozenBalanceV2() { - List freezeV2List = this.account.getFrozenV2List(); - for (Account.FreezeV2 freezeV2 : freezeV2List) { - if(freezeV2.getType().equals(Common.ResourceCode.BANDWIDTH)) { - return freezeV2.getAmount(); - } - } - return 0L; - } - - private long getEnergyFrozenBalanceV2() { - List freezeV2List = this.account.getFrozenV2List(); - for (Account.FreezeV2 freezeV2 : freezeV2List) { - if(freezeV2.getType().equals(Common.ResourceCode.ENERGY)) { - return freezeV2.getAmount(); - } + public long getFrozenV2BalanceForEnergy() { + List frozenList = getFrozenV2List(); + if (frozenList.isEmpty()) { + return 0; } - return 0L; + return frozenList.stream().filter(o -> o.getType() == ENERGY) + .mapToLong(FreezeV2::getAmount).sum(); } - public boolean oldTronPowerIsNotInitialized() { return this.account.getOldTronPower() == 0; } @@ -1077,17 +1056,11 @@ public long getTronPowerFrozenBalance() { return this.account.getTronPower().getFrozenBalance(); } - public long getTronPowerFrozenBalanceV2() { - List freezeV2List = this.account.getFrozenV2List(); - for (Account.FreezeV2 freezeV2 : freezeV2List) { - if(freezeV2.getType().equals(Common.ResourceCode.TRON_POWER)) { - return freezeV2.getAmount(); - } - } - return 0L; + public long getTronPowerFrozenV2Balance() { + return getFrozenV2List().stream().filter(o-> o.getType() == TRON_POWER) + .mapToLong(FreezeV2::getAmount).sum(); } - public long getEnergyUsage() { return this.account.getAccountResource().getEnergyUsage(); } @@ -1100,7 +1073,8 @@ public void setEnergyUsage(long energyUsage) { } public long getAllFrozenBalanceForEnergy() { - return getEnergyFrozenBalance() + getAcquiredDelegatedFrozenBalanceForEnergy() + getEnergyFrozenBalanceV2(); + return getEnergyFrozenBalance() + getAcquiredDelegatedFrozenBalanceForEnergy() + + getFrozenV2BalanceForEnergy(); } public long getLatestConsumeTimeForEnergy() { @@ -1277,4 +1251,15 @@ public void importAllAsset() { } } + public void addUnfrozenV2(UnFreezeV2 unfrozenV2) { + if (Objects.isNull(unfrozenV2)) { + return; + } + this.account = this.account.toBuilder().addUnfrozenV2(unfrozenV2).build(); + } + + public void clearUnfrozenV2() { + this.account = this.account.toBuilder().clearUnfrozenV2().build(); + } + } diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index c3184a46307..c3528237b98 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -150,6 +150,7 @@ import org.tron.protos.contract.BalanceContract.TransferContract; import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; import org.tron.protos.contract.BalanceContract.WithdrawBalanceContract; +import org.tron.protos.contract.BalanceContract.WithdrawExpireUnfreezeContract; import org.tron.protos.contract.ExchangeContract.ExchangeCreateContract; import org.tron.protos.contract.ExchangeContract.ExchangeInjectContract; import org.tron.protos.contract.ExchangeContract.ExchangeTransactionContract; @@ -1535,6 +1536,13 @@ public void withdrawBalance2(WithdrawBalanceContract request, createTransactionExtention(request, ContractType.WithdrawBalanceContract, responseObserver); } + @Override + public void withdrawExpireUnfreeze(WithdrawExpireUnfreezeContract request, + StreamObserver responseObserver) { + createTransactionExtention(request, ContractType.WithdrawExpireUnfreezeContract, + responseObserver); + } + @Override public void proposalCreate(ProposalCreateContract request, StreamObserver responseObserver) { @@ -1871,7 +1879,7 @@ public void getTransactionById(BytesMessage request, @Override public void deployContract(CreateSmartContract request, - io.grpc.stub.StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.CreateSmartContract, responseObserver); } @@ -2520,7 +2528,7 @@ public void isShieldedTRC20ContractNoteSpent(NfTRC20Parameters request, @Override public void getTriggerInputForShieldedTRC20Contract( ShieldedTRC20TriggerContractParameters request, - io.grpc.stub.StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTRC20Transaction(); diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index 031bd38e50c..26a5256fcc2 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -293,6 +293,8 @@ public class FullNodeHttpApiService implements Service { private GetBandwidthPricesServlet getBandwidthPricesServlet; @Autowired private GetBlockServlet getBlockServlet; + @Autowired + private WithdrawExpireUnfreezeServlet withdrawExpireUnfreezeServlet; private static String getParamsFile(String fileName) { InputStream in = Thread.currentThread().getContextClassLoader() @@ -543,6 +545,9 @@ public void start() { "/wallet/getbandwidthprices"); context.addServlet(new ServletHolder(getBlockServlet), "/wallet/getblock"); + context.addServlet(new ServletHolder(withdrawExpireUnfreezeServlet), + "/wallet/withdrawExpireUnfreeze"); + int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { server.addBean(new ConnectionLimit(maxHttpConnectNumber, server)); diff --git a/framework/src/main/java/org/tron/core/services/http/WithdrawBalanceV2Servlet.java b/framework/src/main/java/org/tron/core/services/http/WithdrawExpireUnfreezeServlet.java similarity index 78% rename from framework/src/main/java/org/tron/core/services/http/WithdrawBalanceV2Servlet.java rename to framework/src/main/java/org/tron/core/services/http/WithdrawExpireUnfreezeServlet.java index 1696fa8863b..4888ee42de4 100644 --- a/framework/src/main/java/org/tron/core/services/http/WithdrawBalanceV2Servlet.java +++ b/framework/src/main/java/org/tron/core/services/http/WithdrawExpireUnfreezeServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; @@ -10,16 +11,18 @@ import org.tron.core.Wallet; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.contract.BalanceContract.WithdrawBalanceV2Contract; +import org.tron.protos.contract.BalanceContract.WithdrawExpireUnfreezeContract; + @Component @Slf4j(topic = "API") -public class WithdrawBalanceV2Servlet extends RateLimiterServlet { +public class WithdrawExpireUnfreezeServlet extends RateLimiterServlet { @Autowired private Wallet wallet; protected void doGet(HttpServletRequest request, HttpServletResponse response) { + } protected void doPost(HttpServletRequest request, HttpServletResponse response) { @@ -28,16 +31,16 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); boolean visible = Util.getVisiblePost(contract); - WithdrawBalanceV2Contract.Builder build = WithdrawBalanceV2Contract.newBuilder(); + WithdrawExpireUnfreezeContract.Builder build = WithdrawExpireUnfreezeContract.newBuilder(); JsonFormat.merge(contract, build, visible); Transaction tx = wallet - .createTransactionCapsule(build.build(), ContractType.WithdrawBalanceV2Contract) + .createTransactionCapsule(build.build(), ContractType.WithdrawExpireUnfreezeContract) .getInstance(); - JSONObject jsonObject = JSONObject.parseObject(contract); + JSONObject jsonObject = JSON.parseObject(contract); tx = Util.setTransactionPermissionId(jsonObject, tx); response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { Util.processError(e, response); } } -} \ No newline at end of file +} diff --git a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java index f4118fbef90..87708196143 100644 --- a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java @@ -169,7 +169,7 @@ public void testFreezeBalanceForBandwidth() { Assert.assertEquals(owner.getBalance(), initBalance - frozenBalance - TRANSFER_FEE); - Assert.assertEquals(owner.getFrozenBalanceV2(), frozenBalance); + Assert.assertEquals(owner.getFrozenV2BalanceForBandwidth(), frozenBalance); Assert.assertEquals(frozenBalance, owner.getTronPower()); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java index 3633d1cba08..f174dbb782f 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java @@ -168,7 +168,7 @@ public void testUnfreezeBalanceForBandwidth() { accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); long unfreezeBalance = frozenBalance - 100; - Assert.assertEquals(accountCapsule.getFrozenBalanceV2(), frozenBalance); + Assert.assertEquals(accountCapsule.getFrozenV2BalanceForBandwidth(), frozenBalance); Assert.assertEquals(accountCapsule.getTronPower(), frozenBalance); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -187,7 +187,7 @@ public void testUnfreezeBalanceForBandwidth() { .get(ByteArray.fromHexString(OWNER_ADDRESS)); //Assert.assertEquals(owner.getBalance(), initBalance + frozenBalance); - Assert.assertEquals(owner.getFrozenBalanceV2(), 100); + Assert.assertEquals(owner.getFrozenV2BalanceForBandwidth(), 100); Assert.assertEquals(owner.getTronPower(), 100L); long totalNetWeightAfter = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); diff --git a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java new file mode 100644 index 00000000000..83d4dcbe7cc --- /dev/null +++ b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java @@ -0,0 +1,275 @@ +package org.tron.core.actuator; + +import static junit.framework.TestCase.fail; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import java.io.File; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.args.Witness; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.capsule.WitnessCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.exception.BalanceInsufficientException; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.protos.Protocol.Account.UnFreezeV2; +import org.tron.protos.Protocol.AccountType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.AssetIssueContractOuterClass; +import org.tron.protos.contract.BalanceContract.WithdrawExpireUnfreezeContract; + +@Slf4j +public class WithdrawExpireUnfreezeActuatorTest { + + private static final String dbPath = "output_withdraw_expire_unfreeze_test"; + private static final String OWNER_ADDRESS; + private static final String OWNER_ADDRESS_INVALID = "aaaa"; + private static final String OWNER_ACCOUNT_INVALID; + private static final long initBalance = 10_000_000_000L; + private static final long allowance = 32_000_000L; + private static Manager dbManager; + private static TronApplicationContext context; + + static { + Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + OWNER_ACCOUNT_INVALID = + Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; + } + + /** + * Init data. + */ + @BeforeClass + public static void init() { + dbManager = context.getBean(Manager.class); + } + + /** + * Release resources. + */ + @AfterClass + public static void destroy() { + Args.clearParam(); + context.destroy(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.info("Release resources failure."); + } + } + + /** + * create temp Capsule test need. + */ + @Before + public void createAccountCapsule() { + AccountCapsule ownerCapsule = new AccountCapsule(ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), AccountType.Normal, + initBalance); + UnFreezeV2 unFreezeV2_1 = UnFreezeV2.newBuilder().setType(BANDWIDTH) + .setUnfreezeAmount(16_000_000L).setUnfreezeExpireTime(1).build(); + UnFreezeV2 unFreezeV2_2 = UnFreezeV2.newBuilder().setType(ENERGY) + .setUnfreezeAmount(16_000_000L).setUnfreezeExpireTime(1).build(); + UnFreezeV2 unFreezeV2_3 = UnFreezeV2.newBuilder().setType(ENERGY) + .setUnfreezeAmount(0).setUnfreezeExpireTime(Long.MAX_VALUE).build(); + ownerCapsule.addUnfrozenV2(unFreezeV2_1); + ownerCapsule.addUnfrozenV2(unFreezeV2_2); + ownerCapsule.addUnfrozenV2(unFreezeV2_3); + dbManager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); + } + + private Any getContract(String ownerAddress) { + return Any.pack(WithdrawExpireUnfreezeContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))).build()); + } + + @Test + public void testWithdrawExpireUnfreeze() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + byte[] address = ByteArray.fromHexString(OWNER_ADDRESS); + + AccountCapsule accountCapsule = dbManager.getAccountStore().get(address); + Assert.assertEquals(accountCapsule.getLatestWithdrawTime(), 0); + + WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address), 100, + "http://baidu.com/"); + dbManager.getWitnessStore().put(address, witnessCapsule); + + WithdrawExpireUnfreezeActuator actuator = new WithdrawExpireUnfreezeActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContract(OWNER_ADDRESS)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); + AccountCapsule owner = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + List unfrozenV2List = owner.getInstance().getUnfrozenV2List(); + Assert.assertEquals(1, unfrozenV2List.size()); + Assert.assertEquals(Long.MAX_VALUE, unfrozenV2List.get(0).getUnfreezeExpireTime()); + Assert.assertEquals(initBalance + 32_000_000L, owner.getBalance()); + Assert.assertEquals(0, owner.getAllowance()); + Assert.assertNotEquals(0, owner.getLatestWithdrawTime()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void invalidOwnerAddress() { + WithdrawExpireUnfreezeActuator actuator = new WithdrawExpireUnfreezeActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContract(OWNER_ADDRESS_INVALID)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + + Assert.assertEquals("Invalid address", e.getMessage()); + + } catch (ContractExeException e) { + Assert.assertTrue(e instanceof ContractExeException); + } + + } + + @Test + public void invalidOwnerAccount() { + WithdrawExpireUnfreezeActuator actuator = new WithdrawExpireUnfreezeActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContract(OWNER_ACCOUNT_INVALID)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Account[" + OWNER_ACCOUNT_INVALID + "] not exists", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void isGR() { + Witness w = Args.getInstance().getGenesisBlock().getWitnesses().get(0); + byte[] address = w.getAddress(); + AccountCapsule grCapsule = new AccountCapsule(ByteString.copyFromUtf8("gr"), + ByteString.copyFrom(address), AccountType.Normal, initBalance); + dbManager.getAccountStore().put(grCapsule.createDbKey(), grCapsule); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + try { + dbManager.getMortgageService() + .adjustAllowance(dbManager.getAccountStore(), address, allowance); + } catch (BalanceInsufficientException e) { + fail("BalanceInsufficientException"); + } + AccountCapsule accountCapsule = dbManager.getAccountStore().get(address); + Assert.assertEquals(accountCapsule.getAllowance(), allowance); + + WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address), 100, + "http://google.com/"); + + dbManager.getAccountStore().put(address, accountCapsule); + dbManager.getWitnessStore().put(address, witnessCapsule); + + WithdrawExpireUnfreezeActuator actuator = new WithdrawExpireUnfreezeActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContract(ByteArray.toHexString(address))); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + Assert.assertTrue(dbManager.getWitnessStore().has(address)); + + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + + } catch (ContractValidateException e) { + String readableOwnerAddress = StringUtil.createReadableString(address); + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Account[" + readableOwnerAddress + + "] is a guard representative and is not allowed to withdraw Balance", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void commonErrorCheck() { + + WithdrawExpireUnfreezeActuator actuator = new WithdrawExpireUnfreezeActuator(); + ActuatorTest actuatorTest = new ActuatorTest(actuator, dbManager); + actuatorTest.noContract(); + + Any invalidContractTypes = Any.pack(AssetIssueContractOuterClass.AssetIssueContract.newBuilder() + .build()); + actuatorTest.setInvalidContract(invalidContractTypes); + actuatorTest.setInvalidContractTypeMsg("contract type error", + "contract type error, expected type [WithdrawExpireUnfreezeContract], real type["); + actuatorTest.invalidContractType(); + + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + byte[] address = ByteArray.fromHexString(OWNER_ADDRESS); + try { + dbManager.getMortgageService() + .adjustAllowance(dbManager.getAccountStore(), address, allowance); + } catch (BalanceInsufficientException e) { + fail("BalanceInsufficientException"); + } + AccountCapsule accountCapsule = dbManager.getAccountStore().get(address); + Assert.assertEquals(accountCapsule.getAllowance(), allowance); + Assert.assertEquals(accountCapsule.getLatestWithdrawTime(), 0); + + WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address), 100, + "http://google.com/"); + dbManager.getWitnessStore().put(address, witnessCapsule); + + actuatorTest.setContract(getContract(OWNER_ADDRESS)); + actuatorTest.nullTransationResult(); + + actuatorTest.setNullDBManagerMsg("No account store or dynamic store!"); + actuatorTest.nullDBManger(); + } + +} + diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index baa4a5fad78..b3ce3d56e51 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -271,6 +271,10 @@ service Wallet { //Use this function instead of WithdrawBalance. rpc WithdrawBalance2 (WithdrawBalanceContract) returns (TransactionExtention) { } + + rpc WithdrawExpireUnfreeze (WithdrawExpireUnfreezeContract) returns (TransactionExtention) { + } + //Please use UpdateAsset2 instead of this function. rpc UpdateAsset (UpdateAssetContract) returns (Transaction) { option (google.api.http) = { diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index ba0e7d1b414..194a0d95a74 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -361,7 +361,7 @@ message Transaction { MarketCancelOrderContract = 53; FreezeBalanceV2Contract = 54; UnfreezeBalanceV2Contract = 55; - WithdrawBalanceV2Contract = 56; + WithdrawExpireUnfreezeContract = 56; DelegateResourceContract = 57; UnDelegateResourceContract = 58; } diff --git a/protocol/src/main/protos/core/contract/balance_contract.proto b/protocol/src/main/protos/core/contract/balance_contract.proto index db54939a3d4..284e43a03e6 100644 --- a/protocol/src/main/protos/core/contract/balance_contract.proto +++ b/protocol/src/main/protos/core/contract/balance_contract.proto @@ -93,7 +93,7 @@ message UnfreezeBalanceV2Contract { ResourceCode resource = 3; } -message WithdrawBalanceV2Contract { +message WithdrawExpireUnfreezeContract { bytes owner_address = 1; } From 91bc21281699d57488c3ff6a56842f38d2c0c925 Mon Sep 17 00:00:00 2001 From: guoquanwu Date: Tue, 20 Sep 2022 20:08:37 +0800 Subject: [PATCH 0267/1197] fix(db): DBConvert tool compatible with CheckpointV2 --- .../main/java/org/tron/program/DBConvert.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/program/DBConvert.java b/framework/src/main/java/org/tron/program/DBConvert.java index 8dd2ad04793..6e052dcb5d7 100644 --- a/framework/src/main/java/org/tron/program/DBConvert.java +++ b/framework/src/main/java/org/tron/program/DBConvert.java @@ -58,6 +58,7 @@ public class DBConvert implements Callable { private final long startTime; private static final int CPUS = Runtime.getRuntime().availableProcessors(); private static final int BATCH = 256; + private static final String CHECKPOINT_V2_DIR_NAME = "checkpoint"; @Override @@ -110,8 +111,18 @@ public static int run(String[] args) { return 404; } List files = Arrays.stream(Objects.requireNonNull(dbDirectory.listFiles())) - .filter(File::isDirectory).collect( - Collectors.toList()); + .filter(File::isDirectory) + .filter(e -> !CHECKPOINT_V2_DIR_NAME.equals(e.getName())) + .collect(Collectors.toList()); + + // add checkpoint v2 convert + File cpV2Dir = new File(Paths.get(dbSrc, CHECKPOINT_V2_DIR_NAME).toString()); + List cpList = null; + if (cpV2Dir.exists()) { + cpList = Arrays.stream(Objects.requireNonNull(cpV2Dir.listFiles())) + .filter(File::isDirectory) + .collect(Collectors.toList()); + } if (files.isEmpty()) { logger.info("{} does not contain any database.", dbSrc); @@ -128,6 +139,12 @@ public static int run(String[] args) { esDb.allowCoreThreadTimeOut(true); files.forEach(f -> res.add(esDb.submit(new DBConvert(dbSrc, dbDst, f.getName())))); + // convert v2 + if (cpList != null) { + cpList.forEach(f -> res.add(esDb.submit( + new DBConvert(dbSrc+"/"+CHECKPOINT_V2_DIR_NAME, + dbDst+"/"+CHECKPOINT_V2_DIR_NAME, f.getName())))); + } int fails = res.size(); From cadba1e82f470f312549592a4b95234c07df23c3 Mon Sep 17 00:00:00 2001 From: guoquanwu Date: Wed, 21 Sep 2022 10:57:06 +0800 Subject: [PATCH 0268/1197] fix(db): fix sonar check --- framework/src/main/java/org/tron/program/DBConvert.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/program/DBConvert.java b/framework/src/main/java/org/tron/program/DBConvert.java index 6e052dcb5d7..a13a2ffefb5 100644 --- a/framework/src/main/java/org/tron/program/DBConvert.java +++ b/framework/src/main/java/org/tron/program/DBConvert.java @@ -142,8 +142,8 @@ public static int run(String[] args) { // convert v2 if (cpList != null) { cpList.forEach(f -> res.add(esDb.submit( - new DBConvert(dbSrc+"/"+CHECKPOINT_V2_DIR_NAME, - dbDst+"/"+CHECKPOINT_V2_DIR_NAME, f.getName())))); + new DBConvert(dbSrc + "/" + CHECKPOINT_V2_DIR_NAME, + dbDst + "/" + CHECKPOINT_V2_DIR_NAME, f.getName())))); } int fails = res.size(); From 60e434ce78131e8d6c6920daed6ec025a78903c1 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 21 Sep 2022 18:13:44 +0800 Subject: [PATCH 0269/1197] perf(net): optimize peer connect function --- .../common/overlay/client/PeerClient.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/framework/src/main/java/org/tron/common/overlay/client/PeerClient.java b/framework/src/main/java/org/tron/common/overlay/client/PeerClient.java index 60f73eb3fb3..d6a8b224c84 100644 --- a/framework/src/main/java/org/tron/common/overlay/client/PeerClient.java +++ b/framework/src/main/java/org/tron/common/overlay/client/PeerClient.java @@ -45,22 +45,27 @@ public void connect(String host, int port, String remoteId) { ChannelFuture f = connectAsync(host, port, remoteId, false); f.sync().channel().closeFuture().sync(); } catch (Exception e) { - logger.info("Can't connect to {}:{}, cause:{})", host, port, e.getMessage()); + logger.warn("Can't connect to {}:{}, cause:{})", host, port, e.getMessage()); } } - public ChannelFuture connectAsync(NodeHandler nodeHandler, boolean discoveryMode) { + public void connectAsync(NodeHandler nodeHandler, boolean discoveryMode) { Node node = nodeHandler.getNode(); - return connectAsync(node.getHost(), node.getPort(), node.getHexId(), discoveryMode) - .addListener((ChannelFutureListener) future -> { - if (!future.isSuccess()) { - logger.warn("Connect to {}:{} fail, cause:{}", node.getHost(), node.getPort(), - future.cause().getMessage()); - nodeHandler.getNodeStatistics().nodeDisconnectedLocal(ReasonCode.CONNECT_FAIL); - nodeHandler.getNodeStatistics().notifyDisconnect(); - future.channel().close(); - } - }); + try { + connectAsync(node.getHost(), node.getPort(), node.getHexId(), discoveryMode) + .addListener((ChannelFutureListener) future -> { + if (!future.isSuccess()) { + logger.warn("Connect to {}:{} fail, cause:{}", node.getHost(), node.getPort(), + future.cause().getMessage()); + nodeHandler.getNodeStatistics().nodeDisconnectedLocal(ReasonCode.CONNECT_FAIL); + nodeHandler.getNodeStatistics().notifyDisconnect(); + future.channel().close(); + } + }); + } catch (Exception e) { + logger.warn("Connect to peer {} failed, reason: {}", + node.getHost(), e.getMessage()); + } } private ChannelFuture connectAsync(String host, int port, String remoteId, From dd5c0a070655bccd3a3e31e4b0dd3624810f7310 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Thu, 22 Sep 2022 14:49:39 +0800 Subject: [PATCH 0270/1197] feat(freezeV2): add delegate resource 1. add delegate resource contract 2. add undelegate resource contract 3. add test cases for delegate and undelegate resource --- .../actuator/DelegateResourceActuator.java | 268 ++++++ .../actuator/UnDelegateResourceActuator.java | 299 +++++++ .../DelegatedResourceAccountIndexCapsule.java | 9 + .../capsule/DelegatedResourceCapsule.java | 9 + .../org/tron/core/db/BandwidthProcessor.java | 0 .../DelegateResourceActuatorTest.java | 485 ++++++++++ .../UnDelegateResourceActuatorTest.java | 836 ++++++++++++++++++ 7 files changed, 1906 insertions(+) create mode 100755 actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java create mode 100755 actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java rename {framework => chainbase}/src/main/java/org/tron/core/db/BandwidthProcessor.java (100%) create mode 100644 framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java create mode 100644 framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java new file mode 100755 index 00000000000..156581342ad --- /dev/null +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -0,0 +1,268 @@ +package org.tron.core.actuator; + +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; +import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; +import org.tron.core.capsule.DelegatedResourceCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.db.BandwidthProcessor; +import org.tron.core.db.EnergyProcessor; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.AccountStore; +import org.tron.core.store.DelegatedResourceAccountIndexStore; +import org.tron.core.store.DelegatedResourceStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.Protocol.AccountType; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.BalanceContract.DelegateResourceContract; + +@Slf4j(topic = "actuator") +public class DelegateResourceActuator extends AbstractActuator { + + public DelegateResourceActuator() { + super(ContractType.DelegateResourceContract, DelegateResourceContract.class); + } + + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + + long fee = calcFee(); + final DelegateResourceContract delegateResourceContract; + AccountStore accountStore = chainBaseManager.getAccountStore(); + try { + delegateResourceContract = any.unpack(DelegateResourceContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + + AccountCapsule ownerCapsule = accountStore + .get(delegateResourceContract.getOwnerAddress().toByteArray()); + + // TODO remove + // if (dynamicStore.supportAllowNewResourceModel() + // && accountCapsule.oldTronPowerIsNotInitialized()) { + // accountCapsule.initializeOldTronPower(); + // } + + long delegateBalance = delegateResourceContract.getBalance(); + byte[] ownerAddress = delegateResourceContract.getOwnerAddress().toByteArray(); + byte[] receiverAddress = delegateResourceContract.getReceiverAddress().toByteArray(); + + // delegate resource to receiver + switch (delegateResourceContract.getResource()) { + case BANDWIDTH: + delegateResource(ownerAddress, receiverAddress, true, + delegateBalance); + + ownerCapsule.addDelegatedFrozenBalanceForBandwidth(delegateBalance); + ownerCapsule.addFrozenBalanceForBandwidthV2(-delegateBalance); + break; + case ENERGY: + delegateResource(ownerAddress, receiverAddress, false, + delegateBalance); + + ownerCapsule.addDelegatedFrozenBalanceForEnergy(delegateBalance); + ownerCapsule.addFrozenBalanceForEnergyV2(-delegateBalance); + break; + default: + logger.debug("Resource Code Error."); + } + + accountStore.put(ownerCapsule.createDbKey(), ownerCapsule); + + ret.setStatus(fee, code.SUCESS); + + return true; + } + + + @Override + public boolean validate() throws ContractValidateException { + if (this.any == null) { + throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); + } + if (chainBaseManager == null) { + throw new ContractValidateException(ActuatorConstant.STORE_NOT_EXIST); + } + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + if (!any.is(DelegateResourceContract.class)) { + throw new ContractValidateException( + "contract type error,expected type [DelegateResourceContract],real type[" + + any.getClass() + "]"); + } + + if (!dynamicStore.supportDR()) { + throw new ContractValidateException("No support for resource delegate"); + } + + final DelegateResourceContract delegateResourceContract; + try { + delegateResourceContract = this.any.unpack(DelegateResourceContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + throw new ContractValidateException(e.getMessage()); + } + byte[] ownerAddress = delegateResourceContract.getOwnerAddress().toByteArray(); + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + + AccountCapsule ownerCapsule = accountStore.get(ownerAddress); + if (ownerCapsule == null) { + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + throw new ContractValidateException( + ActuatorConstant.ACCOUNT_EXCEPTION_STR + readableOwnerAddress + NOT_EXIST_STR); + } + + long delegateBalance = delegateResourceContract.getBalance(); + if (delegateBalance < TRX_PRECISION) { + throw new ContractValidateException("delegateBalance must be more than 1TRX"); + } + + switch (delegateResourceContract.getResource()) { + case BANDWIDTH: { + BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); + processor.updateUsage(ownerCapsule); + long netBalanceUsage = (long) (ownerCapsule.getNetUsage() + * ((double) (dynamicStore.getTotalNetLimit()) / dynamicStore.getTotalNetWeight())); + if (ownerCapsule.getFrozenV2BalanceForBandwidth() - netBalanceUsage < delegateBalance) { + throw new ContractValidateException("delegateBalance must be less than accountFreezeBandwidthBalance"); + } + } + break; + case ENERGY: { + EnergyProcessor processor = new EnergyProcessor(dynamicStore, accountStore); + processor.updateUsage(ownerCapsule); + long energyBalanceUsage = (long) (ownerCapsule.getEnergyUsage() + * ((double) (dynamicStore.getTotalEnergyCurrentLimit()) / dynamicStore.getTotalEnergyWeight())); + if (ownerCapsule.getFrozenV2BalanceForEnergy() - energyBalanceUsage < delegateBalance) { + throw new ContractValidateException("delegateBalance must be less than accountFreezeEnergyBalance"); + } + } + break; + default: + throw new ContractValidateException( + "ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]"); + } + + byte[] receiverAddress = delegateResourceContract.getReceiverAddress().toByteArray(); + + if (ArrayUtils.isEmpty(receiverAddress) || !DecodeUtil.addressValid(receiverAddress)) { + throw new ContractValidateException("Invalid receiverAddress"); + } + + + if (Arrays.equals(receiverAddress, ownerAddress)) { + throw new ContractValidateException( + "receiverAddress must not be the same as ownerAddress"); + } + + AccountCapsule receiverCapsule = accountStore.get(receiverAddress); + if (receiverCapsule == null) { + String readableOwnerAddress = StringUtil.createReadableString(receiverAddress); + throw new ContractValidateException( + ActuatorConstant.ACCOUNT_EXCEPTION_STR + + readableOwnerAddress + NOT_EXIST_STR); + } + + if (receiverCapsule.getType() == AccountType.Contract) { + throw new ContractValidateException( + "Do not allow delegate resources to contract addresses"); + } + + return true; + } + + @Override + public ByteString getOwnerAddress() throws InvalidProtocolBufferException { + return any.unpack(DelegateResourceContract.class).getOwnerAddress(); + } + + @Override + public long calcFee() { + return 0; + } + + private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boolean isBandwidth, + long balance) { + AccountStore accountStore = chainBaseManager.getAccountStore(); + DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore(); + DelegatedResourceAccountIndexStore delegatedResourceAccountIndexStore = chainBaseManager + .getDelegatedResourceAccountIndexStore(); + + //modify DelegatedResourceStore + byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress); + DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore + .get(key); + if (delegatedResourceCapsule == null) { + delegatedResourceCapsule = new DelegatedResourceCapsule( + ByteString.copyFrom(ownerAddress), + ByteString.copyFrom(receiverAddress)); + } + if (isBandwidth) { + delegatedResourceCapsule.addFrozenBalanceForBandwidth(balance, 0); + } else { + delegatedResourceCapsule.addFrozenBalanceForEnergy(balance, 0); + } + delegatedResourceStore.put(key, delegatedResourceCapsule); + + //modify DelegatedResourceAccountIndexStore owner + byte[] ownerKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(ownerAddress); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = delegatedResourceAccountIndexStore + .get(ownerKey); + if (ownerIndexCapsule == null) { + ownerIndexCapsule = new DelegatedResourceAccountIndexCapsule( + ByteString.copyFrom(ownerAddress)); + } + List toAccountsList = ownerIndexCapsule.getToAccountsList(); + if (!toAccountsList.contains(ByteString.copyFrom(receiverAddress))) { + ownerIndexCapsule.addToAccount(ByteString.copyFrom(receiverAddress)); + delegatedResourceAccountIndexStore.put(ownerKey, ownerIndexCapsule); + } + + //modify DelegatedResourceAccountIndexStore receiver + byte[] receiverKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiverAddress); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = delegatedResourceAccountIndexStore + .get(receiverKey); + if (receiverIndexCapsule == null) { + receiverIndexCapsule = new DelegatedResourceAccountIndexCapsule( + ByteString.copyFrom(receiverAddress)); + } + List fromAccountsList = receiverIndexCapsule + .getFromAccountsList(); + if (!fromAccountsList.contains(ByteString.copyFrom(ownerAddress))) { + receiverIndexCapsule.addFromAccount(ByteString.copyFrom(ownerAddress)); + delegatedResourceAccountIndexStore.put(receiverKey, receiverIndexCapsule); + } + + //modify AccountStore for receiver + AccountCapsule receiverCapsule = accountStore.get(receiverAddress); + if (isBandwidth) { + receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(balance); + } else { + receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(balance); + } + accountStore.put(receiverCapsule.createDbKey(), receiverCapsule); + } + +} diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java new file mode 100755 index 00000000000..4140f9cfb73 --- /dev/null +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -0,0 +1,299 @@ +package org.tron.core.actuator; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; +import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; +import org.tron.core.capsule.DelegatedResourceCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.db.BandwidthProcessor; +import org.tron.core.db.EnergyProcessor; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.AccountStore; +import org.tron.core.store.DelegatedResourceAccountIndexStore; +import org.tron.core.store.DelegatedResourceStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.BalanceContract.UnDelegateResourceContract; + +@Slf4j(topic = "actuator") +public class UnDelegateResourceActuator extends AbstractActuator { + + public UnDelegateResourceActuator() { + super(ContractType.UnDelegateResourceContract, UnDelegateResourceContract.class); + } + + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + + long fee = calcFee(); + final UnDelegateResourceContract unDelegateResourceContract; + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore(); + DelegatedResourceAccountIndexStore delegatedResourceAccountIndexStore = chainBaseManager + .getDelegatedResourceAccountIndexStore(); + try { + unDelegateResourceContract = any.unpack(UnDelegateResourceContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + + + final long unDelegateBalance = unDelegateResourceContract.getBalance(); + byte[] ownerAddress = unDelegateResourceContract.getOwnerAddress().toByteArray(); + byte[] receiverAddress = unDelegateResourceContract.getReceiverAddress().toByteArray(); + + AccountCapsule receiverCapsule = accountStore.get(receiverAddress); + + long transferUsage = 0; + // modify receiver Account + if (receiverCapsule != null) { + switch (unDelegateResourceContract.getResource()) { + case BANDWIDTH: + BandwidthProcessor bandwidthProcessor = new BandwidthProcessor(chainBaseManager); + bandwidthProcessor.updateUsage(receiverCapsule); + + if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() + < unDelegateBalance) { + // A TVM contract suicide, re-create will produce this situation + transferUsage = receiverCapsule.getNetUsage(); + + receiverCapsule.setAcquiredDelegatedFrozenBalanceForBandwidth(0); + } else { + // calculate usage + long unDelegateBandwidth = (long) (unDelegateBalance / TRX_PRECISION + * ((double) (dynamicStore.getTotalNetLimit()) / dynamicStore.getTotalNetWeight())); + transferUsage = (long) (receiverCapsule.getNetUsage() + * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForBandwidth())); + transferUsage = Math.min(unDelegateBandwidth, transferUsage); + + receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(-unDelegateBalance); + } + + long newNetUsage = receiverCapsule.getNetUsage() - transferUsage; + receiverCapsule.setNetUsage(newNetUsage); + break; + case ENERGY: + EnergyProcessor energyProcessor = new EnergyProcessor(dynamicStore, accountStore); + energyProcessor.updateUsage(receiverCapsule); + + if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() + < unDelegateBalance) { + // A TVM contract receiver, re-create will produce this situation + transferUsage = receiverCapsule.getEnergyUsage(); + receiverCapsule.setAcquiredDelegatedFrozenBalanceForEnergy(0); + } else { + long unDelegateEnergy = (long) (unDelegateBalance / TRX_PRECISION + * ((double) (dynamicStore.getTotalEnergyCurrentLimit()) / dynamicStore.getTotalEnergyWeight())); + transferUsage = (long) (receiverCapsule.getEnergyUsage() + * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForEnergy())); + transferUsage = Math.min(unDelegateEnergy, transferUsage); + + receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(-unDelegateBalance); + } + + long newEnergyUsage = receiverCapsule.getEnergyUsage() - transferUsage; + receiverCapsule.setEnergyUsage(newEnergyUsage); + break; + default: + //this should never happen + break; + } + accountStore.put(receiverCapsule.createDbKey(), receiverCapsule); + } + + // modify owner Account + AccountCapsule accountCapsule = accountStore.get(ownerAddress); + byte[] key = DelegatedResourceCapsule + .createDbKeyV2(unDelegateResourceContract.getOwnerAddress().toByteArray(), + unDelegateResourceContract.getReceiverAddress().toByteArray()); + DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore + .get(key); + switch (unDelegateResourceContract.getResource()) { + case BANDWIDTH: { + long delegateBalance = delegatedResourceCapsule.getFrozenBalanceForBandwidth(); + delegatedResourceCapsule.setFrozenBalanceForBandwidth(delegateBalance - unDelegateBalance, 0); + accountCapsule.addDelegatedFrozenBalanceForBandwidth(-unDelegateBalance); + accountCapsule.addFrozenBalanceForBandwidthV2(unDelegateBalance); + + long newNetUsage = accountCapsule.getNetUsage() + transferUsage; + accountCapsule.setNetUsage(newNetUsage); + accountCapsule.setLatestConsumeTime(chainBaseManager.getHeadSlot()); + } + break; + case ENERGY: { + long delegateBalance = delegatedResourceCapsule.getFrozenBalanceForEnergy(); + delegatedResourceCapsule.setFrozenBalanceForEnergy(delegateBalance - unDelegateBalance, 0); + accountCapsule.addDelegatedFrozenBalanceForEnergy(-unDelegateBalance); + accountCapsule.addFrozenBalanceForEnergyV2(unDelegateBalance); + + long newEnergyUsage = accountCapsule.getEnergyUsage() + transferUsage; + accountCapsule.setEnergyUsage(newEnergyUsage); + accountCapsule.setLatestConsumeTimeForEnergy(chainBaseManager.getHeadSlot()); + } + break; + default: + //this should never happen + break; + } + + if (delegatedResourceCapsule.getFrozenBalanceForBandwidth() == 0 + && delegatedResourceCapsule.getFrozenBalanceForEnergy() == 0) { + delegatedResourceStore.delete(key); + + //modify DelegatedResourceAccountIndexStore for owner + byte[] ownerKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(ownerAddress); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = delegatedResourceAccountIndexStore + .get(ownerKey); + if (ownerIndexCapsule != null) { + List toAccountsList = new ArrayList<>(ownerIndexCapsule + .getToAccountsList()); + toAccountsList.remove(ByteString.copyFrom(receiverAddress)); + ownerIndexCapsule.setAllToAccounts(toAccountsList); + delegatedResourceAccountIndexStore + .put(ownerKey, ownerIndexCapsule); + } + + //modify DelegatedResourceAccountIndexStore for receive + byte[] receiverKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiverAddress); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = delegatedResourceAccountIndexStore + .get(receiverKey); + if (receiverIndexCapsule != null) { + List fromAccountsList = new ArrayList<>(receiverIndexCapsule + .getFromAccountsList()); + fromAccountsList.remove(ByteString.copyFrom(ownerAddress)); + receiverIndexCapsule.setAllFromAccounts(fromAccountsList); + delegatedResourceAccountIndexStore + .put(receiverKey, receiverIndexCapsule); + } + + } else { + delegatedResourceStore.put(key, delegatedResourceCapsule); + } + + accountStore.put(ownerAddress, accountCapsule); + + ret.setStatus(fee, code.SUCESS); + + return true; + } + + @Override + public boolean validate() throws ContractValidateException { + if (this.any == null) { + throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); + } + if (chainBaseManager == null) { + throw new ContractValidateException(ActuatorConstant.STORE_NOT_EXIST); + } + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore(); + if (!dynamicStore.supportDR()) { + throw new ContractValidateException("No support for resource delegate"); + } + + if (!this.any.is(UnDelegateResourceContract.class)) { + throw new ContractValidateException( + "contract type error, expected type [UnDelegateResourceContract], real type[" + any + .getClass() + "]"); + } + final UnDelegateResourceContract unDelegateResourceContract; + try { + unDelegateResourceContract = this.any.unpack(UnDelegateResourceContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + throw new ContractValidateException(e.getMessage()); + } + + byte[] ownerAddress = unDelegateResourceContract.getOwnerAddress().toByteArray(); + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + AccountCapsule ownerCapsule = accountStore.get(ownerAddress); + if (ownerCapsule == null) { + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + throw new ContractValidateException( + ACCOUNT_EXCEPTION_STR + readableOwnerAddress + "] does not exist"); + } + + byte[] receiverAddress = unDelegateResourceContract.getReceiverAddress().toByteArray(); + if (ArrayUtils.isEmpty(receiverAddress) || !DecodeUtil.addressValid(receiverAddress)) { + throw new ContractValidateException("Invalid receiverAddress"); + } + if (Arrays.equals(receiverAddress, ownerAddress)) { + throw new ContractValidateException( + "receiverAddress must not be the same as ownerAddress"); + } + + // TVM contract suicide can result in no receiving account + // AccountCapsule receiverCapsule = accountStore.get(receiverAddress); + // if (receiverCapsule == null) { + // String readableReceiverAddress = StringUtil.createReadableString(receiverAddress); + // throw new ContractValidateException( + // "Receiver Account[" + readableReceiverAddress + "] does not exist"); + // } + + byte[] key = DelegatedResourceCapsule + .createDbKeyV2(unDelegateResourceContract.getOwnerAddress().toByteArray(), + unDelegateResourceContract.getReceiverAddress().toByteArray()); + DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore.get(key); + if (delegatedResourceCapsule == null) { + throw new ContractValidateException( + "delegated Resource does not exist"); + } + + long unDelegateBalance = unDelegateResourceContract.getBalance(); + switch (unDelegateResourceContract.getResource()) { + case BANDWIDTH: + if (delegatedResourceCapsule.getFrozenBalanceForBandwidth() < unDelegateBalance) { + throw new ContractValidateException("insufficient delegatedFrozenBalance(BANDWIDTH), request=" + + unDelegateBalance + ", balance=" + delegatedResourceCapsule.getFrozenBalanceForBandwidth()); + } + break; + case ENERGY: + if (delegatedResourceCapsule.getFrozenBalanceForEnergy() < unDelegateBalance) { + throw new ContractValidateException("insufficient delegateFrozenBalance(Energy), request=" + + unDelegateBalance + ", balance=" + delegatedResourceCapsule.getFrozenBalanceForEnergy()); + } + break; + default: + throw new ContractValidateException( + "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + } + + + return true; + } + + @Override + public ByteString getOwnerAddress() throws InvalidProtocolBufferException { + return any.unpack(UnDelegateResourceContract.class).getOwnerAddress(); + } + + @Override + public long calcFee() { + return 0; + } + +} diff --git a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java index 7c7a37fa609..2ff6495b2cf 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java @@ -98,6 +98,15 @@ public byte[] createDbKey() { return getAccount().toByteArray(); } + public static byte[] createDbKeyV2(byte[] account) { + byte[] v2Prefix = "v2_".getBytes(); + byte[] key = new byte[v2Prefix.length + account.length]; + System.arraycopy(v2Prefix, 0, key, 0, v2Prefix.length); + System.arraycopy(account, 0, key, v2Prefix.length, account.length); + return key; + } + + public String createReadableString() { return ByteArray.toHexString(getAccount().toByteArray()); } diff --git a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java index 0eb6dc8ec09..b33e47a2406 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java @@ -37,6 +37,15 @@ public static byte[] createDbKey(byte[] from, byte[] to) { return key; } + public static byte[] createDbKeyV2(byte[] from, byte[] to) { + byte[] v2Prefix = "v2_".getBytes(); + byte[] key = new byte[v2Prefix.length + from.length + to.length]; + System.arraycopy(v2Prefix, 0, key, 0, v2Prefix.length); + System.arraycopy(from, 0, key, v2Prefix.length, from.length); + System.arraycopy(to, 0, key, v2Prefix.length+from.length, to.length); + return key; + } + public ByteString getFrom() { return this.delegatedResource.getFrom(); } diff --git a/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java similarity index 100% rename from framework/src/main/java/org/tron/core/db/BandwidthProcessor.java rename to chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java diff --git a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java new file mode 100644 index 00000000000..ebe491454e4 --- /dev/null +++ b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java @@ -0,0 +1,485 @@ +package org.tron.core.actuator; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import java.io.File; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; +import org.tron.core.capsule.DelegatedResourceCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.protos.Protocol.AccountType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.AssetIssueContractOuterClass; +import org.tron.protos.contract.BalanceContract.DelegateResourceContract; +import org.tron.protos.contract.Common.ResourceCode; + +@Slf4j +public class DelegateResourceActuatorTest { + + private static final String dbPath = "output_delegate_resource_test"; + private static final String OWNER_ADDRESS; + private static final String RECEIVER_ADDRESS; + private static final String OWNER_ADDRESS_INVALID = "aaaa"; + private static final String OWNER_ACCOUNT_INVALID; + private static final long initBalance = 10_000_000_000L; + private static Manager dbManager; + private static TronApplicationContext context; + + static { + Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; + OWNER_ACCOUNT_INVALID = + Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; + } + + /** + * Init data. + */ + @BeforeClass + public static void init() { + dbManager = context.getBean(Manager.class); + } + + /** + * Release resources. + */ + @AfterClass + public static void destroy() { + Args.clearParam(); + context.destroy(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.info("Release resources failure."); + } + } + + /** + * create temp Capsule test need. + */ + @Before + public void createAccountCapsule() { + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + AccountCapsule ownerCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(owner), + AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + + AccountCapsule receiverCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(receiver), + AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); + + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + + // clear delegate + dbManager.getDelegatedResourceStore().delete(DelegatedResourceCapsule.createDbKeyV2( + owner, receiver)); + dbManager.getDelegatedResourceAccountIndexStore().delete( + DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner)); + dbManager.getDelegatedResourceAccountIndexStore().delete( + DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver)); + } + + public void freezeBandwidthForOwner() { + AccountCapsule ownerCapsule = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + ownerCapsule.addFrozenBalanceForBandwidthV2(initBalance); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + } + + public void freezeCpuForOwner() { + AccountCapsule ownerCapsule = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + ownerCapsule.addFrozenBalanceForEnergyV2(initBalance); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + } + + private Any getDelegateContractForBandwidth( + String ownerAddress, String receiveAddress, long unfreezeBalance) { + return Any.pack( + DelegateResourceContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiveAddress))) + .setBalance(unfreezeBalance) + .setResource(ResourceCode.BANDWIDTH) + .build()); + } + + private Any getDelegateContractForCpu( + String ownerAddress, String receiveAddress, long unfreezeBalance) { + return Any.pack( + DelegateResourceContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiveAddress))) + .setBalance(unfreezeBalance) + .setResource(ResourceCode.ENERGY) + .build()); + } + + private Any getDelegateContractForTronPower( + String ownerAddress, String receiveAddress, long unfreezeBalance) { + return Any.pack( + DelegateResourceContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiveAddress))) + .setBalance(unfreezeBalance) + .setResource(ResourceCode.TRON_POWER) + .build()); + } + + @Test + public void testDelegateResourceWithNoFreeze() { + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForBandwidth( + OWNER_ADDRESS, + RECEIVER_ADDRESS, + 1_000_000_000L)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertEquals("delegateBalance must be less than accountFreezeBandwidthBalance", + e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(); + } + + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, 1_000_000_000L)); + try { + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertEquals("delegateBalance must be less than accountFreezeEnergyBalance", + e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testDelegateResourceWithContractAddress() { + freezeBandwidthForOwner(); + AccountCapsule receiverCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), + AccountType.Contract, + initBalance); + dbManager.getAccountStore().put(ByteArray.fromHexString(RECEIVER_ADDRESS), receiverCapsule); + + + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, 1_000_000_000L)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertEquals("Do not allow delegate resources to contract addresses", e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testDelegateResourceToSelf() { + freezeBandwidthForOwner(); + + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForBandwidth(OWNER_ADDRESS, OWNER_ADDRESS, 1_000_000_000L)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertEquals("receiverAddress must not be the same as ownerAddress", e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testDelegateResourceForBandwidth() { + freezeBandwidthForOwner(); + long delegateBalance = 1_000_000_000L; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + long totalNetWeightBefore = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule ownerCapsule = + dbManager.getAccountStore().get(owner); + + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(initBalance - delegateBalance, + ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(initBalance, ownerCapsule.getTronPower()); + + AccountCapsule receiverCapsule = + dbManager.getAccountStore().get(receiver); + Assert.assertEquals(delegateBalance, + receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0L, receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0L, receiverCapsule.getTronPower()); + + DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule + .createDbKeyV2(ByteArray.fromHexString(OWNER_ADDRESS), + ByteArray.fromHexString(RECEIVER_ADDRESS))); + + Assert.assertEquals(delegateBalance, delegatedResourceCapsule.getFrozenBalanceForBandwidth()); + long totalNetWeightAfter = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); + Assert.assertEquals(totalNetWeightBefore, totalNetWeightAfter); + + //check DelegatedResourceAccountIndex + byte[] key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); + Assert.assertTrue(ownerIndexCapsule.getToAccountsList() + .contains(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)))); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiveCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, receiveCapsule.getToAccountsList().size()); + Assert.assertEquals(1, receiveCapsule.getFromAccountsList().size()); + Assert.assertTrue(receiveCapsule.getFromAccountsList() + .contains(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)))); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testDelegateResourceForCpu() { + freezeCpuForOwner(); + long delegateBalance = 1_000_000_000L; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + long totalEnergyWeightBefore = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); + AccountCapsule ownerCapsule = + dbManager.getAccountStore().get(owner); + + Assert.assertEquals(initBalance, ownerCapsule.getBalance()); + Assert.assertEquals(0L, ownerCapsule.getFrozenBalance()); + Assert.assertEquals(0L, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(initBalance, ownerCapsule.getTronPower()); + + AccountCapsule receiverCapsule = + dbManager.getAccountStore().get(receiver); + Assert.assertEquals(0L, receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, + receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0L, receiverCapsule.getTronPower()); + + DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule.createDbKeyV2(owner, receiver)); + + Assert.assertEquals(0L, delegatedResourceCapsule.getFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, delegatedResourceCapsule.getFrozenBalanceForEnergy()); + + long totalEnergyWeightAfter = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); + Assert.assertEquals(totalEnergyWeightBefore, totalEnergyWeightAfter); + + //check DelegatedResourceAccountIndex + byte[] key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert + .assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); + Assert.assertTrue(ownerIndexCapsule.getToAccountsList() + .contains(ByteString.copyFrom(receiver))); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert + .assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + Assert + .assertEquals(1, + receiverIndexCapsule.getFromAccountsList().size()); + Assert.assertTrue(receiverIndexCapsule.getFromAccountsList() + .contains(ByteString.copyFrom(owner))); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void delegateLessThanZero() { + long delegateBalance = -1_000_000_000L; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegateContractForBandwidth( + OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertEquals("delegateBalance must be more than 1TRX", e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void delegateTronPower() { + long delegateBalance = 1_000_000_000L; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegateContractForTronPower( + OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertEquals("ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]", + e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + + @Test + public void delegateMoreThanBalance() { + long delegateBalance = 11_000_000_000L; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegateContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertEquals("delegateBalance must be less than accountFreezeBandwidthBalance", + e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void invalidOwnerAddress() { + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegateContractForBandwidth( + OWNER_ADDRESS_INVALID, RECEIVER_ADDRESS, 1_000_000_000L)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.fail("cannot run here."); + + } catch (ContractValidateException e) { + Assert.assertEquals("Invalid address", e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void invalidOwnerAccount() { + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegateContractForBandwidth( + OWNER_ACCOUNT_INVALID, RECEIVER_ADDRESS, 1_000_000_000L)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertEquals("Account[" + OWNER_ACCOUNT_INVALID + "] not exists", + e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void commonErrorCheck() { + freezeBandwidthForOwner(); + DelegateResourceActuator actuator = new DelegateResourceActuator(); + ActuatorTest actuatorTest = new ActuatorTest(actuator, dbManager); + actuatorTest.noContract(); + + Any invalidContractTypes = Any.pack(AssetIssueContractOuterClass.AssetIssueContract.newBuilder() + .build()); + actuatorTest.setInvalidContract(invalidContractTypes); + actuatorTest.setInvalidContractTypeMsg("contract type error", + "contract type error,expected type [DelegateResourceContract],real type["); + actuatorTest.invalidContractType(); + + actuatorTest.setContract( + getDelegateContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, 1_000_000_000L)); + actuatorTest.nullTransationResult(); + + actuatorTest.setNullDBManagerMsg("No account store or dynamic store!"); + actuatorTest.nullDBManger(); + } +} diff --git a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java new file mode 100644 index 00000000000..0abe5df3356 --- /dev/null +++ b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java @@ -0,0 +1,836 @@ +package org.tron.core.actuator; + +import static junit.framework.TestCase.fail; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import java.io.File; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; +import org.tron.core.capsule.DelegatedResourceCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.protos.Protocol.AccountType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.AssetIssueContractOuterClass; +import org.tron.protos.contract.BalanceContract.UnDelegateResourceContract; +import org.tron.protos.contract.Common.ResourceCode; + +@Slf4j +public class UnDelegateResourceActuatorTest { + + private static final String dbPath = "output_undelegate_resource_test"; + private static final String OWNER_ADDRESS; + private static final String RECEIVER_ADDRESS; + private static final String OWNER_ADDRESS_INVALID = "aaaa"; + private static final String OWNER_ACCOUNT_INVALID; + private static final long initBalance = 10_000_000_000L; + private static final long delegateBalance = 1_000_000_000L; + private static Manager dbManager; + private static TronApplicationContext context; + + static { + Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; + OWNER_ACCOUNT_INVALID = + Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; + } + + /** + * Init data. + */ + @BeforeClass + public static void init() { + dbManager = context.getBean(Manager.class); + } + + /** + * Release resources. + */ + @AfterClass + public static void destroy() { + Args.clearParam(); + context.destroy(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.info("Release resources failure."); + } + } + + /** + * create temp Capsule test need. + */ + @Before + public void createAccountCapsule() { + AccountCapsule ownerCapsule = new AccountCapsule(ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); + + AccountCapsule receiverCapsule = new AccountCapsule(ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); + + // clear delegate + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + dbManager.getDelegatedResourceStore().delete(DelegatedResourceCapsule.createDbKeyV2( + owner, receiver)); + dbManager.getDelegatedResourceAccountIndexStore().delete( + DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner)); + dbManager.getDelegatedResourceAccountIndexStore().delete( + DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver)); + + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + } + + public void delegateBandwidthForOwner() { + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + ownerCapsule.addDelegatedFrozenBalanceForBandwidth(delegateBalance); + dbManager.getAccountStore().put(owner, ownerCapsule); + AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); + receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(delegateBalance); + dbManager.getAccountStore().put(receiver, receiverCapsule); + dbManager.getDynamicPropertiesStore().addTotalNetWeight(delegateBalance / TRX_PRECISION); + + DelegatedResourceCapsule delegatedResourceCapsule = new DelegatedResourceCapsule( + ByteString.copyFrom(owner), + ByteString.copyFrom(receiver)); + delegatedResourceCapsule.setFrozenBalanceForBandwidth(delegateBalance, 0); + dbManager.getDelegatedResourceStore().put( + DelegatedResourceCapsule.createDbKeyV2(owner, receiver), delegatedResourceCapsule); + + + byte[] ownerKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = + new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(owner)); + + List toAccountsList = delegatedResourceAccountIndexCapsule.getToAccountsList(); + if (!toAccountsList.contains(ByteString.copyFrom(receiver))) { + delegatedResourceAccountIndexCapsule.addToAccount(ByteString.copyFrom(receiver)); + } + dbManager.getDelegatedResourceAccountIndexStore() + .put(ownerKey, delegatedResourceAccountIndexCapsule); + + + byte[] receiverKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + delegatedResourceAccountIndexCapsule = new DelegatedResourceAccountIndexCapsule( + ByteString.copyFrom(receiver)); + + List fromAccountsList = delegatedResourceAccountIndexCapsule + .getFromAccountsList(); + if (!fromAccountsList.contains(ByteString.copyFrom(owner))) { + delegatedResourceAccountIndexCapsule.addFromAccount(ByteString.copyFrom(owner)); + } + dbManager.getDelegatedResourceAccountIndexStore() + .put(receiverKey, delegatedResourceAccountIndexCapsule); + } + + public void delegateCpuForOwner() { + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + ownerCapsule.addDelegatedFrozenBalanceForEnergy(delegateBalance); + dbManager.getAccountStore().put(owner, ownerCapsule); + AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); + receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(delegateBalance); + dbManager.getAccountStore().put(receiver, receiverCapsule); + dbManager.getDynamicPropertiesStore().addTotalEnergyWeight(delegateBalance / TRX_PRECISION); + + DelegatedResourceCapsule delegatedResourceCapsule = new DelegatedResourceCapsule( + ByteString.copyFrom(owner), + ByteString.copyFrom(receiver)); + delegatedResourceCapsule.setFrozenBalanceForEnergy(delegateBalance, 0); + dbManager.getDelegatedResourceStore().put( + DelegatedResourceCapsule.createDbKeyV2(owner, receiver), delegatedResourceCapsule); + + + byte[] ownerKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = + new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(owner)); + + List toAccountsList = delegatedResourceAccountIndexCapsule.getToAccountsList(); + if (!toAccountsList.contains(ByteString.copyFrom(receiver))) { + delegatedResourceAccountIndexCapsule.addToAccount(ByteString.copyFrom(receiver)); + } + dbManager.getDelegatedResourceAccountIndexStore() + .put(ownerKey, delegatedResourceAccountIndexCapsule); + + + byte[] receiverKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + delegatedResourceAccountIndexCapsule = new DelegatedResourceAccountIndexCapsule( + ByteString.copyFrom(receiver)); + + List fromAccountsList = delegatedResourceAccountIndexCapsule + .getFromAccountsList(); + if (!fromAccountsList.contains(ByteString.copyFrom(owner))) { + delegatedResourceAccountIndexCapsule.addFromAccount(ByteString.copyFrom(owner)); + } + dbManager.getDelegatedResourceAccountIndexStore() + .put(receiverKey, delegatedResourceAccountIndexCapsule); + } + + private Any getDelegatedContractForBandwidth( + String ownerAddress, String receiverAddress, long balance) { + return Any.pack(UnDelegateResourceContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiverAddress))) + .setBalance(balance).build()); + } + + private Any getDelegatedContractForCpu( + String ownerAddress, String receiverAddress, long balance) { + return Any.pack(UnDelegateResourceContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiverAddress))) + .setResource(ResourceCode.ENERGY) + .setBalance(balance).build()); + } + + // test start + @Test + public void testUnDelegateForBandwidth() { + delegateBandwidthForOwner(); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); + receiverCapsule.setNetUsage(1_000_000_000); + receiverCapsule.setLatestConsumeTime(dbManager.getChainBaseManager().getHeadSlot()); + dbManager.getAccountStore().put(receiver, receiverCapsule); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(delegateBalance, + receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); + Assert.assertEquals(0, ownerCapsule.getNetUsage()); + Assert.assertEquals(1_000_000_000, receiverCapsule.getNetUsage()); + + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + + // check owner + ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(1000000000, ownerCapsule.getNetUsage()); + Assert.assertEquals(dbManager.getChainBaseManager().getHeadSlot(), + ownerCapsule.getLatestConsumeTime()); + + // check receiver + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0, receiverCapsule.getNetUsage()); + + //check DelegatedResource + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + DelegatedResourceCapsule delegatedCapsule = dbManager.getDelegatedResourceStore().get(key); + Assert.assertNull(delegatedCapsule); + + //check DelegatedResourceAccountIndex + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(0, ownerIndexCapsule.getToAccountsList().size()); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + Assert.assertEquals(0, receiverIndexCapsule.getFromAccountsList().size()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testPartialUnDelegateForBandwidth() { + delegateBandwidthForOwner(); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); + receiverCapsule.setNetUsage(1_000_000_000); + receiverCapsule.setLatestConsumeTime(dbManager.getChainBaseManager().getHeadSlot()); + dbManager.getAccountStore().put(receiver, receiverCapsule); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance / 2)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(delegateBalance, + receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); + Assert.assertEquals(0, ownerCapsule.getNetUsage()); + Assert.assertEquals(1_000_000_000, receiverCapsule.getNetUsage()); + + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + + // check owner + ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(delegateBalance / 2, + ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance / 2, + ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(1000000000 / 2, ownerCapsule.getNetUsage()); + Assert.assertEquals(dbManager.getChainBaseManager().getHeadSlot(), + ownerCapsule.getLatestConsumeTime()); + + // check receiver + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(delegateBalance / 2, + receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(1000000000 / 2, receiverCapsule.getNetUsage()); + + //check DelegatedResource + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + DelegatedResourceCapsule delegatedResourceCapsule = + dbManager.getDelegatedResourceStore().get(key); + Assert.assertEquals(delegateBalance / 2, + delegatedResourceCapsule.getFrozenBalanceForBandwidth()); + + //check DelegatedResourceAccountIndex + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + Assert.assertEquals(1, receiverIndexCapsule.getFromAccountsList().size()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testUnDelegatedForBandwidthWithDeletedReceiver() { + delegateBandwidthForOwner(); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + dbManager.getAccountStore().delete(receiver); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + + // check owner + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(0, ownerCapsule.getNetUsage()); + + // check receiver + Assert.assertNull(dbManager.getAccountStore().get(receiver)); + + //check DelegatedResource + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + DelegatedResourceCapsule delegatedResourceCapsule = + dbManager.getDelegatedResourceStore().get(key); + Assert.assertNull(delegatedResourceCapsule); + + //check DelegatedResourceAccountIndex + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(0, ownerIndexCapsule.getToAccountsList().size()); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + Assert.assertEquals(0, receiverIndexCapsule.getFromAccountsList().size()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + + } + + @Test + public void testUnDelegatedForBandwidthWithRecreatedReceiver() { + delegateBandwidthForOwner(); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + dbManager.getAccountStore().delete(receiver); + + AccountCapsule receiverCapsule = new AccountCapsule(ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), AccountType.Normal, + initBalance); + receiverCapsule.setAcquiredDelegatedFrozenBalanceForBandwidth(10L); + dbManager.getAccountStore().put(receiver, receiverCapsule); + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(10, receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + + // check owner + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(0, ownerCapsule.getNetUsage()); + + // check receiver + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + + //check DelegatedResource + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + DelegatedResourceCapsule delegatedCapsule = dbManager.getDelegatedResourceStore().get(key); + Assert.assertNull(delegatedCapsule); + + //check DelegatedResourceAccountIndex + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(0, ownerIndexCapsule.getToAccountsList().size()); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + Assert.assertEquals(0, receiverIndexCapsule.getFromAccountsList().size()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + + } + + @Test + public void testUnDelegatedForCpu() { + delegateCpuForOwner(); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); + receiverCapsule.setEnergyUsage(1_000_000_000); + receiverCapsule.setLatestConsumeTimeForEnergy(dbManager.getChainBaseManager().getHeadSlot()); + dbManager.getAccountStore().put(receiver, receiverCapsule); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(delegateBalance, + receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForEnergy()); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); + Assert.assertEquals(0, ownerCapsule.getEnergyUsage()); + Assert.assertEquals(1_000_000_000, receiverCapsule.getEnergyUsage()); + + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + + // check owner + ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForEnergy()); + Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(1_000_000_000, ownerCapsule.getEnergyUsage()); + Assert.assertEquals(dbManager.getChainBaseManager().getHeadSlot(), + ownerCapsule.getLatestConsumeTimeForEnergy()); + + // check receiver + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0, receiverCapsule.getEnergyUsage()); + + //check DelegatedResource + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + DelegatedResourceCapsule delegatedCapsule = dbManager.getDelegatedResourceStore().get(key); + Assert.assertNull(delegatedCapsule); + + //check DelegatedResourceAccountIndex + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(0, ownerIndexCapsule.getToAccountsList().size()); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + Assert.assertEquals(0, receiverIndexCapsule.getFromAccountsList().size()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testPartialUnDelegatedForCpu() { + delegateCpuForOwner(); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); + receiverCapsule.setEnergyUsage(1_000_000_000); + receiverCapsule.setLatestConsumeTimeForEnergy(dbManager.getChainBaseManager().getHeadSlot()); + dbManager.getAccountStore().put(receiver, receiverCapsule); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance / 2)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(delegateBalance, + receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForEnergy()); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); + Assert.assertEquals(0, ownerCapsule.getEnergyUsage()); + Assert.assertEquals(1_000_000_000, receiverCapsule.getEnergyUsage()); + + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + + // check owner + ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(delegateBalance / 2, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(delegateBalance / 2, ownerCapsule.getFrozenV2BalanceForEnergy()); + Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(1_000_000_000 / 2, ownerCapsule.getEnergyUsage()); + Assert.assertEquals(dbManager.getChainBaseManager().getHeadSlot(), + ownerCapsule.getLatestConsumeTimeForEnergy()); + + // check receiver + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(delegateBalance / 2, + receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(1_000_000_000 / 2, receiverCapsule.getEnergyUsage()); + + //check DelegatedResource + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + DelegatedResourceCapsule delegatedCapsule = dbManager.getDelegatedResourceStore().get(key); + Assert.assertEquals(delegateBalance / 2, + delegatedCapsule.getFrozenBalanceForEnergy()); + + //check DelegatedResourceAccountIndex + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + Assert.assertEquals(1, receiverIndexCapsule.getFromAccountsList().size()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testUnDelegatedForCpuWithDeletedReceiver() { + delegateCpuForOwner(); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + dbManager.getAccountStore().delete(receiver); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + + // check owner + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForEnergy()); + Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(0, ownerCapsule.getEnergyUsage()); + + // check receiver + Assert.assertNull(dbManager.getAccountStore().get(receiver)); + + //check DelegatedResource + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + DelegatedResourceCapsule delegatedCapsule = dbManager.getDelegatedResourceStore().get(key); + Assert.assertNull(delegatedCapsule); + + //check DelegatedResourceAccountIndex + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(0, ownerIndexCapsule.getToAccountsList().size()); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + Assert.assertEquals(0, receiverIndexCapsule.getFromAccountsList().size()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + + } + + @Test + public void testUnDelegatedForCpuWithRecreatedReceiver() { + delegateCpuForOwner(); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + dbManager.getAccountStore().delete(receiver); + + AccountCapsule receiverCapsule = new AccountCapsule(ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), AccountType.Normal, + initBalance); + receiverCapsule.setAcquiredDelegatedFrozenBalanceForEnergy(10L); + dbManager.getAccountStore().put(receiver, receiverCapsule); + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(10, receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + + // check owner + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForEnergy()); + Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(0, ownerCapsule.getEnergyUsage()); + + // check receiver + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + + //check DelegatedResource + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + DelegatedResourceCapsule delegatedResourceCapsule = + dbManager.getDelegatedResourceStore().get(key); + Assert.assertNull(delegatedResourceCapsule); + + //check DelegatedResourceAccountIndex + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(0, ownerIndexCapsule.getToAccountsList().size()); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + Assert.assertEquals(0, receiverIndexCapsule.getFromAccountsList().size()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + + } + + @Test + public void invalidOwnerAddress() { + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForBandwidth( + OWNER_ADDRESS_INVALID, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + + } catch (ContractValidateException e) { + Assert.assertEquals("Invalid address", e.getMessage()); + + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + + } + + @Test + public void invalidOwnerAccount() { + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegatedContractForBandwidth(OWNER_ACCOUNT_INVALID, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertEquals("Account[" + OWNER_ACCOUNT_INVALID + "] does not exist", + e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void noDelegateBalance() { + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertEquals("delegated Resource does not exist", e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + try { + actuator.validate(); + actuator.execute(ret); + Assert.fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertEquals("delegated Resource does not exist", e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void commonErrorCheck() { + delegateBandwidthForOwner(); + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + ActuatorTest actuatorTest = new ActuatorTest(actuator, dbManager); + actuatorTest.noContract(); + + Any invalidContractTypes = Any.pack(AssetIssueContractOuterClass.AssetIssueContract.newBuilder() + .build()); + actuatorTest.setInvalidContract(invalidContractTypes); + actuatorTest.setInvalidContractTypeMsg("contract type error", + "contract type error, expected type [UnDelegateResourceContract], real type["); + actuatorTest.invalidContractType(); + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + Assert.assertEquals(0, accountCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(delegateBalance, accountCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, accountCapsule.getTronPower()); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + + actuatorTest.setContract(getDelegatedContractForBandwidth( + OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + actuatorTest.nullTransationResult(); + + actuatorTest.setNullDBManagerMsg("No account store or dynamic store!"); + actuatorTest.nullDBManger(); + } +} + From 3355563b5165cbcca48a59314ceb25e7c30fc221 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Thu, 22 Sep 2022 16:04:29 +0800 Subject: [PATCH 0271/1197] feat(freezeV2): add freezeV2 contract api --- .../tron/core/consensus/ProposalService.java | 17 +++++++-- .../org/tron/core/services/RpcApiService.java | 16 ++++++++ .../http/DelegateResourceServlet.java | 36 ++++++++++++++++++ .../services/http/FullNodeHttpApiService.java | 17 +++++++++ .../http/UnDelegateResourceServlet.java | 38 +++++++++++++++++++ protocol/src/main/protos/api/api.proto | 6 +++ 6 files changed, 127 insertions(+), 3 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/services/http/DelegateResourceServlet.java create mode 100644 framework/src/main/java/org/tron/core/services/http/UnDelegateResourceServlet.java diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 51e20307084..5a67f092c87 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -5,7 +5,9 @@ import org.tron.core.capsule.ProposalCapsule; import org.tron.core.config.Parameter.ForkBlockVersionEnum; import org.tron.core.db.Manager; +import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.utils.ProposalUtil; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; /** * Notice: @@ -286,9 +288,18 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) } case UNFREEZE_DELAY_DAYS: { - manager.getDynamicPropertiesStore().saveUnfreezeDelayDays(entry.getValue()); - manager.getDynamicPropertiesStore().addSystemContractAndSetPermission(54); - manager.getDynamicPropertiesStore().addSystemContractAndSetPermission(55); + DynamicPropertiesStore dynamicStore = manager.getDynamicPropertiesStore(); + dynamicStore.saveUnfreezeDelayDays(entry.getValue()); + dynamicStore.addSystemContractAndSetPermission( + ContractType.FreezeBalanceV2Contract_VALUE); + dynamicStore.addSystemContractAndSetPermission( + ContractType.UnfreezeBalanceV2Contract_VALUE); + dynamicStore.addSystemContractAndSetPermission( + ContractType.WithdrawExpireUnfreezeContract_VALUE); + dynamicStore.addSystemContractAndSetPermission( + ContractType.DelegateResourceContract_VALUE); + dynamicStore.addSystemContractAndSetPermission( + ContractType.UnDelegateResourceContract_VALUE); break; } default: diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index c3528237b98..c535950cffa 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -146,8 +146,10 @@ import org.tron.protos.contract.BalanceContract.AccountBalanceRequest; import org.tron.protos.contract.BalanceContract.AccountBalanceResponse; import org.tron.protos.contract.BalanceContract.BlockBalanceTrace; +import org.tron.protos.contract.BalanceContract.DelegateResourceContract; import org.tron.protos.contract.BalanceContract.FreezeBalanceContract; import org.tron.protos.contract.BalanceContract.TransferContract; +import org.tron.protos.contract.BalanceContract.UnDelegateResourceContract; import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; import org.tron.protos.contract.BalanceContract.WithdrawBalanceContract; import org.tron.protos.contract.BalanceContract.WithdrawExpireUnfreezeContract; @@ -1543,6 +1545,20 @@ public void withdrawExpireUnfreeze(WithdrawExpireUnfreezeContract request, responseObserver); } + @Override + public void delegateResource(DelegateResourceContract request, + StreamObserver responseObserver) { + createTransactionExtention(request, ContractType.DelegateResourceContract, + responseObserver); + } + + @Override + public void unDelegateResource(UnDelegateResourceContract request, + StreamObserver responseObserver) { + createTransactionExtention(request, ContractType.UnDelegateResourceContract, + responseObserver); + } + @Override public void proposalCreate(ProposalCreateContract request, StreamObserver responseObserver) { diff --git a/framework/src/main/java/org/tron/core/services/http/DelegateResourceServlet.java b/framework/src/main/java/org/tron/core/services/http/DelegateResourceServlet.java new file mode 100644 index 00000000000..221cc34cf7c --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/DelegateResourceServlet.java @@ -0,0 +1,36 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.contract.BalanceContract.DelegateResourceContract; + +@Component +@Slf4j(topic = "API") +public class DelegateResourceServlet extends RateLimiterServlet { + + @Autowired + private Wallet wallet; + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + PostParams params = PostParams.getPostParams(request); + DelegateResourceContract.Builder build = DelegateResourceContract.newBuilder(); + JsonFormat.merge(params.getParams(), build, params.isVisible()); + Transaction tx = wallet + .createTransactionCapsule(build.build(), ContractType.DelegateResourceContract) + .getInstance(); + JSONObject jsonObject = JSONObject.parseObject(params.getParams()); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, params.isVisible())); + } catch (Exception e) { + Util.processError(e, response); + } + } +} diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index 26a5256fcc2..43a0d87661b 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -293,8 +293,17 @@ public class FullNodeHttpApiService implements Service { private GetBandwidthPricesServlet getBandwidthPricesServlet; @Autowired private GetBlockServlet getBlockServlet; + + @Autowired + private FreezeBalanceV2Servlet freezeBalanceV2Servlet; + @Autowired + private UnFreezeBalanceV2Servlet unFreezeBalanceV2Servlet; @Autowired private WithdrawExpireUnfreezeServlet withdrawExpireUnfreezeServlet; + @Autowired + private DelegateResourceServlet delegateResourceServlet; + @Autowired + private UnDelegateResourceServlet unDelegateResourceServlet; private static String getParamsFile(String fileName) { InputStream in = Thread.currentThread().getContextClassLoader() @@ -545,8 +554,16 @@ public void start() { "/wallet/getbandwidthprices"); context.addServlet(new ServletHolder(getBlockServlet), "/wallet/getblock"); + context.addServlet(new ServletHolder(freezeBalanceV2Servlet), + "/wallet/freezebalancev2"); + context.addServlet(new ServletHolder(unFreezeBalanceV2Servlet), + "/wallet/unfreezebalancev2"); context.addServlet(new ServletHolder(withdrawExpireUnfreezeServlet), "/wallet/withdrawExpireUnfreeze"); + context.addServlet(new ServletHolder(delegateResourceServlet), + "/wallet/delegateresource"); + context.addServlet(new ServletHolder(unDelegateResourceServlet), + "/wallet/undelegateresource"); int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { diff --git a/framework/src/main/java/org/tron/core/services/http/UnDelegateResourceServlet.java b/framework/src/main/java/org/tron/core/services/http/UnDelegateResourceServlet.java new file mode 100644 index 00000000000..cf9c2c95dcd --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/UnDelegateResourceServlet.java @@ -0,0 +1,38 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.contract.BalanceContract.UnDelegateResourceContract; + +@Component +@Slf4j(topic = "API") +public class UnDelegateResourceServlet extends RateLimiterServlet { + @Autowired + private Wallet wallet; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + PostParams params = PostParams.getPostParams(request); + UnDelegateResourceContract.Builder build = UnDelegateResourceContract.newBuilder(); + JsonFormat.merge(params.getParams(), build, params.isVisible()); + Transaction tx = wallet + .createTransactionCapsule(build.build(), ContractType.UnDelegateResourceContract) + .getInstance(); + JSONObject jsonObject = JSONObject.parseObject(params.getParams()); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, params.isVisible())); + } catch (Exception e) { + Util.processError(e, response); + } + } +} \ No newline at end of file diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index b3ce3d56e51..037f137c79e 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -275,6 +275,12 @@ service Wallet { rpc WithdrawExpireUnfreeze (WithdrawExpireUnfreezeContract) returns (TransactionExtention) { } + rpc DelegateResource (DelegateResourceContract) returns (TransactionExtention) { + } + + rpc UnDelegateResource (UnDelegateResourceContract) returns (TransactionExtention) { + } + //Please use UpdateAsset2 instead of this function. rpc UpdateAsset (UpdateAssetContract) returns (Transaction) { option (google.api.http) = { From 8d27c0f56dce6d0a858e8f37b58665db74f57f5b Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 22 Sep 2022 12:16:06 +0800 Subject: [PATCH 0272/1197] fix(db): fix concurrent error 1. add write lock for resetDb 2. add read lock for getStats 3. disable db metric for checkpointV2 db --- .../leveldb/LevelDbDataSourceImpl.java | 25 ++++++++++++++----- .../rocksdb/RocksDbDataSourceImpl.java | 25 ++++++++++++++----- .../java/org/tron/core/db/TronDatabase.java | 2 +- .../tron/core/store/CheckPointV2Store.java | 7 +++++- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java index abf90770b98..054648eb467 100644 --- a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java @@ -174,9 +174,14 @@ public Path getDbPath() { * reset database. */ public void resetDb() { - closeDB(); - FileUtil.recursiveDelete(getDbPath().toString()); - initDB(); + resetDbLock.writeLock().lock(); + try { + closeDB(); + FileUtil.recursiveDelete(getDbPath().toString()); + initDB(); + } finally { + resetDbLock.writeLock().unlock(); + } } @Override @@ -506,9 +511,17 @@ private DBIterator getDBIterator() { */ @Override public List getStats() throws Exception { - String stat = database.getProperty("leveldb.stats"); - String[] stats = stat.split("\n"); - return Arrays.stream(stats).skip(3).collect(Collectors.toList()); + resetDbLock.readLock().lock(); + try { + if (!isAlive()) { + return Collections.emptyList(); + } + String stat = database.getProperty("leveldb.stats"); + String[] stats = stat.split("\n"); + return Arrays.stream(stats).skip(3).collect(Collectors.toList()); + } finally { + resetDbLock.readLock().unlock(); + } } @Override diff --git a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java index 35248619933..10c8060ca8d 100644 --- a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java @@ -109,9 +109,14 @@ public void closeDB() { @Override public void resetDb() { - closeDB(); - FileUtil.recursiveDelete(getDbPath().toString()); - initDB(); + resetDbLock.writeLock().lock(); + try { + closeDB(); + FileUtil.recursiveDelete(getDbPath().toString()); + initDB(); + } finally { + resetDbLock.writeLock().unlock(); + } } private boolean quitIfNotAlive() { @@ -528,9 +533,17 @@ public RocksDbDataSourceImpl newInstance() { */ @Override public List getStats() throws Exception { - String stat = database.getProperty("rocksdb.levelstats"); - String[] stats = stat.split("\n"); - return Arrays.stream(stats).skip(2).collect(Collectors.toList()); + resetDbLock.readLock().lock(); + try { + if (!isAlive()) { + return Collections.emptyList(); + } + String stat = database.getProperty("rocksdb.levelstats"); + String[] stats = stat.split("\n"); + return Arrays.stream(stats).skip(2).collect(Collectors.toList()); + } finally { + resetDbLock.readLock().unlock(); + } } @Override diff --git a/chainbase/src/main/java/org/tron/core/db/TronDatabase.java b/chainbase/src/main/java/org/tron/core/db/TronDatabase.java index 04e20af4fd6..b96d7543302 100644 --- a/chainbase/src/main/java/org/tron/core/db/TronDatabase.java +++ b/chainbase/src/main/java/org/tron/core/db/TronDatabase.java @@ -59,7 +59,7 @@ protected TronDatabase(String dbName) { } @PostConstruct - private void init() { + protected void init() { dbStatService.register(dbSource); } diff --git a/chainbase/src/main/java/org/tron/core/store/CheckPointV2Store.java b/chainbase/src/main/java/org/tron/core/store/CheckPointV2Store.java index d5ffaaa9143..046df7f6643 100644 --- a/chainbase/src/main/java/org/tron/core/store/CheckPointV2Store.java +++ b/chainbase/src/main/java/org/tron/core/store/CheckPointV2Store.java @@ -45,4 +45,9 @@ public void forEach(Consumer action) { public Spliterator spliterator() { return null; } -} \ No newline at end of file + + @Override + protected void init() { + } + +} From 6cbbd6ba344419c18c4a0454bee1a5675066df5e Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Thu, 22 Sep 2022 17:44:28 +0800 Subject: [PATCH 0273/1197] fix(freezeV2): fix resource usage bug --- .../actuator/DelegateResourceActuator.java | 32 ++++---- .../actuator/UnDelegateResourceActuator.java | 55 +++++++------- .../WithdrawExpireUnfreezeActuator.java | 39 ++++------ .../DelegateResourceActuatorTest.java | 75 ++++++++++++++++++- .../UnDelegateResourceActuatorTest.java | 28 ++++--- .../WithdrawExpireUnfreezeActuatorTest.java | 47 ------------ 6 files changed, 152 insertions(+), 124 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 156581342ad..152c4fb2a7a 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -57,12 +57,6 @@ public boolean execute(Object result) throws ContractExeException { AccountCapsule ownerCapsule = accountStore .get(delegateResourceContract.getOwnerAddress().toByteArray()); - // TODO remove - // if (dynamicStore.supportAllowNewResourceModel() - // && accountCapsule.oldTronPowerIsNotInitialized()) { - // accountCapsule.initializeOldTronPower(); - // } - long delegateBalance = delegateResourceContract.getBalance(); byte[] ownerAddress = delegateResourceContract.getOwnerAddress().toByteArray(); byte[] receiverAddress = delegateResourceContract.getReceiverAddress().toByteArray(); @@ -143,20 +137,30 @@ public boolean validate() throws ContractValidateException { case BANDWIDTH: { BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); processor.updateUsage(ownerCapsule); - long netBalanceUsage = (long) (ownerCapsule.getNetUsage() - * ((double) (dynamicStore.getTotalNetLimit()) / dynamicStore.getTotalNetWeight())); - if (ownerCapsule.getFrozenV2BalanceForBandwidth() - netBalanceUsage < delegateBalance) { - throw new ContractValidateException("delegateBalance must be less than accountFreezeBandwidthBalance"); + + //The unit is trx + long netTrxUsage = (long) (ownerCapsule.getNetUsage() + * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); + + if (ownerCapsule.getFrozenV2BalanceForBandwidth() - netTrxUsage * TRX_PRECISION + < delegateBalance) { + throw new ContractValidateException( + "delegateBalance must be less than available FreezeBandwidthV2 balance"); } } break; case ENERGY: { EnergyProcessor processor = new EnergyProcessor(dynamicStore, accountStore); processor.updateUsage(ownerCapsule); - long energyBalanceUsage = (long) (ownerCapsule.getEnergyUsage() - * ((double) (dynamicStore.getTotalEnergyCurrentLimit()) / dynamicStore.getTotalEnergyWeight())); - if (ownerCapsule.getFrozenV2BalanceForEnergy() - energyBalanceUsage < delegateBalance) { - throw new ContractValidateException("delegateBalance must be less than accountFreezeEnergyBalance"); + + //The unit is trx + long energyTrxUsage = (long) (ownerCapsule.getEnergyUsage() + * ((double) (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); + + if (ownerCapsule.getFrozenV2BalanceForEnergy() - energyTrxUsage * TRX_PRECISION + < delegateBalance) { + throw new ContractValidateException( + "delegateBalance must be less than available FreezeEnergyV2Balance balance"); } } break; diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index 4140f9cfb73..f18083f77d2 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -76,16 +76,14 @@ public boolean execute(Object result) throws ContractExeException { if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() < unDelegateBalance) { // A TVM contract suicide, re-create will produce this situation - transferUsage = receiverCapsule.getNetUsage(); - receiverCapsule.setAcquiredDelegatedFrozenBalanceForBandwidth(0); } else { // calculate usage - long unDelegateBandwidth = (long) (unDelegateBalance / TRX_PRECISION + long unDelegateMaxUsage = (long) (unDelegateBalance / TRX_PRECISION * ((double) (dynamicStore.getTotalNetLimit()) / dynamicStore.getTotalNetWeight())); transferUsage = (long) (receiverCapsule.getNetUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForBandwidth())); - transferUsage = Math.min(unDelegateBandwidth, transferUsage); + transferUsage = Math.min(unDelegateMaxUsage, transferUsage); receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(-unDelegateBalance); } @@ -100,14 +98,14 @@ public boolean execute(Object result) throws ContractExeException { if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() < unDelegateBalance) { // A TVM contract receiver, re-create will produce this situation - transferUsage = receiverCapsule.getEnergyUsage(); receiverCapsule.setAcquiredDelegatedFrozenBalanceForEnergy(0); } else { - long unDelegateEnergy = (long) (unDelegateBalance / TRX_PRECISION + // calculate usage + long unDelegateMaxUsage = (long) (unDelegateBalance / TRX_PRECISION * ((double) (dynamicStore.getTotalEnergyCurrentLimit()) / dynamicStore.getTotalEnergyWeight())); transferUsage = (long) (receiverCapsule.getEnergyUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForEnergy())); - transferUsage = Math.min(unDelegateEnergy, transferUsage); + transferUsage = Math.min(unDelegateMaxUsage, transferUsage); receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(-unDelegateBalance); } @@ -123,7 +121,7 @@ public boolean execute(Object result) throws ContractExeException { } // modify owner Account - AccountCapsule accountCapsule = accountStore.get(ownerAddress); + AccountCapsule ownerCapsule = accountStore.get(ownerAddress); byte[] key = DelegatedResourceCapsule .createDbKeyV2(unDelegateResourceContract.getOwnerAddress().toByteArray(), unDelegateResourceContract.getReceiverAddress().toByteArray()); @@ -131,25 +129,29 @@ public boolean execute(Object result) throws ContractExeException { .get(key); switch (unDelegateResourceContract.getResource()) { case BANDWIDTH: { - long delegateBalance = delegatedResourceCapsule.getFrozenBalanceForBandwidth(); - delegatedResourceCapsule.setFrozenBalanceForBandwidth(delegateBalance - unDelegateBalance, 0); - accountCapsule.addDelegatedFrozenBalanceForBandwidth(-unDelegateBalance); - accountCapsule.addFrozenBalanceForBandwidthV2(unDelegateBalance); - - long newNetUsage = accountCapsule.getNetUsage() + transferUsage; - accountCapsule.setNetUsage(newNetUsage); - accountCapsule.setLatestConsumeTime(chainBaseManager.getHeadSlot()); + delegatedResourceCapsule.addFrozenBalanceForBandwidth(-unDelegateBalance, 0); + + ownerCapsule.addDelegatedFrozenBalanceForBandwidth(-unDelegateBalance); + ownerCapsule.addFrozenBalanceForBandwidthV2(unDelegateBalance); + + BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); + processor.updateUsage(ownerCapsule); + long newNetUsage = ownerCapsule.getNetUsage() + transferUsage; + ownerCapsule.setNetUsage(newNetUsage); + ownerCapsule.setLatestConsumeTime(chainBaseManager.getHeadSlot()); } break; case ENERGY: { - long delegateBalance = delegatedResourceCapsule.getFrozenBalanceForEnergy(); - delegatedResourceCapsule.setFrozenBalanceForEnergy(delegateBalance - unDelegateBalance, 0); - accountCapsule.addDelegatedFrozenBalanceForEnergy(-unDelegateBalance); - accountCapsule.addFrozenBalanceForEnergyV2(unDelegateBalance); - - long newEnergyUsage = accountCapsule.getEnergyUsage() + transferUsage; - accountCapsule.setEnergyUsage(newEnergyUsage); - accountCapsule.setLatestConsumeTimeForEnergy(chainBaseManager.getHeadSlot()); + delegatedResourceCapsule.addFrozenBalanceForEnergy(-unDelegateBalance, 0); + + ownerCapsule.addDelegatedFrozenBalanceForEnergy(-unDelegateBalance); + ownerCapsule.addFrozenBalanceForEnergyV2(unDelegateBalance); + + EnergyProcessor processor = new EnergyProcessor(dynamicStore, accountStore); + processor.updateUsage(ownerCapsule); + long newEnergyUsage = ownerCapsule.getEnergyUsage() + transferUsage; + ownerCapsule.setEnergyUsage(newEnergyUsage); + ownerCapsule.setLatestConsumeTimeForEnergy(chainBaseManager.getHeadSlot()); } break; default: @@ -191,7 +193,7 @@ public boolean execute(Object result) throws ContractExeException { delegatedResourceStore.put(key, delegatedResourceCapsule); } - accountStore.put(ownerAddress, accountCapsule); + accountStore.put(ownerAddress, ownerCapsule); ret.setStatus(fee, code.SUCESS); @@ -264,6 +266,9 @@ public boolean validate() throws ContractValidateException { } long unDelegateBalance = unDelegateResourceContract.getBalance(); + if (unDelegateBalance < TRX_PRECISION) { + throw new ContractValidateException("unDelegateBalance must be more than 1TRX"); + } switch (unDelegateResourceContract.getResource()) { case BANDWIDTH: if (delegatedResourceCapsule.getFrozenBalanceForBandwidth() < unDelegateBalance) { diff --git a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java index 5ba0a32e2be..5d49701ef92 100755 --- a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java @@ -1,10 +1,15 @@ package org.tron.core.actuator; +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; + import com.google.common.math.LongMath; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; -import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; @@ -18,14 +23,6 @@ import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.BalanceContract.WithdrawExpireUnfreezeContract; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; - @Slf4j(topic = "actuator") public class WithdrawExpireUnfreezeActuator extends AbstractActuator { @@ -51,8 +48,8 @@ public boolean execute(Object result) throws ContractExeException { ret.setStatus(fee, code.FAILED); throw new ContractExeException(e.getMessage()); } - AccountCapsule accountCapsule = accountStore. - get(withdrawExpireUnfreezeContract.getOwnerAddress().toByteArray()); + AccountCapsule accountCapsule = accountStore.get( + withdrawExpireUnfreezeContract.getOwnerAddress().toByteArray()); long now = dynamicStore.getLatestBlockHeaderTimestamp(); List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); long totalWithdrawUnfreeze = getTotalWithdrawUnfreeze(unfrozenV2List, now); @@ -97,18 +94,10 @@ public boolean validate() throws ContractValidateException { AccountCapsule accountCapsule = accountStore.get(ownerAddress); String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); if (Objects.isNull(accountCapsule)) { - throw new ContractValidateException(ACCOUNT_EXCEPTION_STR + - readableOwnerAddress + NOT_EXIST_STR); + throw new ContractValidateException(ACCOUNT_EXCEPTION_STR + + readableOwnerAddress + NOT_EXIST_STR); } - boolean isGP = CommonParameter.getInstance() - .getGenesisBlock().getWitnesses().stream().anyMatch(witness -> - Arrays.equals(ownerAddress, witness.getAddress())); - if (isGP) { - throw new ContractValidateException( - ACCOUNT_EXCEPTION_STR + readableOwnerAddress - + "] is a guard representative and is not allowed to withdraw Balance"); - } long now = dynamicStore.getLatestBlockHeaderTimestamp(); List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); long totalWithdrawUnfreeze = getTotalWithdrawUnfreeze(unfrozenV2List, now); @@ -126,18 +115,18 @@ public boolean validate() throws ContractValidateException { private long getTotalWithdrawUnfreeze(List unfrozenV2List, long now) { return getTotalWithdrawList(unfrozenV2List, now).stream() - .mapToLong(UnFreezeV2::getUnfreezeAmount).sum(); + .mapToLong(UnFreezeV2::getUnfreezeAmount).sum(); } private List getTotalWithdrawList(List unfrozenV2List, long now) { return unfrozenV2List.stream().filter(unfrozenV2 -> (unfrozenV2.getUnfreezeAmount() > 0 - && unfrozenV2.getUnfreezeExpireTime() <= now)).collect(Collectors.toList()); + && unfrozenV2.getUnfreezeExpireTime() <= now)).collect(Collectors.toList()); } private List getRemainWithdrawList(List unfrozenV2List, long now) { return unfrozenV2List.stream() - .filter(unfrozenV2 -> unfrozenV2.getUnfreezeExpireTime() > now) - .collect(Collectors.toList()); + .filter(unfrozenV2 -> unfrozenV2.getUnfreezeExpireTime() > now) + .collect(Collectors.toList()); } @Override diff --git a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java index ebe491454e4..6bfd885dc46 100644 --- a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java @@ -1,5 +1,7 @@ package org.tron.core.actuator; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + import com.google.protobuf.Any; import com.google.protobuf.ByteString; import java.io.File; @@ -23,6 +25,7 @@ import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.DynamicPropertiesStore; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.AssetIssueContractOuterClass; @@ -110,6 +113,7 @@ public void freezeBandwidthForOwner() { AccountCapsule ownerCapsule = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); ownerCapsule.addFrozenBalanceForBandwidthV2(initBalance); + dbManager.getDynamicPropertiesStore().addTotalNetWeight(initBalance / TRX_PRECISION); dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); } @@ -117,6 +121,7 @@ public void freezeCpuForOwner() { AccountCapsule ownerCapsule = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); ownerCapsule.addFrozenBalanceForEnergyV2(initBalance); + dbManager.getDynamicPropertiesStore().addTotalEnergyWeight(initBalance / TRX_PRECISION); dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); } @@ -167,8 +172,9 @@ public void testDelegateResourceWithNoFreeze() { try { actuator.validate(); actuator.execute(ret); + Assert.fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertEquals("delegateBalance must be less than accountFreezeBandwidthBalance", + Assert.assertEquals("delegateBalance must be less than available FreezeBandwidthV2 balance", e.getMessage()); } catch (ContractExeException e) { Assert.fail(); @@ -179,14 +185,77 @@ public void testDelegateResourceWithNoFreeze() { try { actuator.validate(); actuator.execute(ret); + Assert.fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertEquals( + "delegateBalance must be less than available FreezeEnergyV2Balance balance", + e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testDelegateBandwidthWithUsage() { + freezeBandwidthForOwner(); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + DynamicPropertiesStore dynamicPropertiesStore = dbManager.getDynamicPropertiesStore(); + ownerCapsule.setNetUsage(dynamicPropertiesStore.getTotalNetLimit() / 4); + ownerCapsule.setLatestConsumeTime(dbManager.getChainBaseManager().getHeadSlot()); + dbManager.getAccountStore().put(owner, ownerCapsule); + + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, initBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertEquals("delegateBalance must be less than accountFreezeEnergyBalance", + Assert.assertEquals("delegateBalance must be less than available FreezeBandwidthV2 balance", e.getMessage()); } catch (ContractExeException e) { Assert.fail(e.getMessage()); } } + + @Test + public void testDelegateCpuWithUsage() { + freezeCpuForOwner(); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + DynamicPropertiesStore dynamicPropertiesStore = dbManager.getDynamicPropertiesStore(); + ownerCapsule.setEnergyUsage(dynamicPropertiesStore.getTotalEnergyCurrentLimit() / 4); + ownerCapsule.setLatestConsumeTimeForEnergy(dbManager.getChainBaseManager().getHeadSlot()); + dbManager.getAccountStore().put(owner, ownerCapsule); + + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, initBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertEquals( + "delegateBalance must be less than available FreezeEnergyV2Balance balance", + e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test public void testDelegateResourceWithContractAddress() { freezeBandwidthForOwner(); @@ -414,7 +483,7 @@ public void delegateMoreThanBalance() { actuator.execute(ret); Assert.fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertEquals("delegateBalance must be less than accountFreezeBandwidthBalance", + Assert.assertEquals("delegateBalance must be less than available FreezeBandwidthV2 balance", e.getMessage()); } catch (ContractExeException e) { Assert.fail(e.getMessage()); diff --git a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java index 0abe5df3356..c235de57a3a 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java @@ -222,8 +222,13 @@ public void testUnDelegateForBandwidth() { AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); receiverCapsule.setNetUsage(1_000_000_000); - receiverCapsule.setLatestConsumeTime(dbManager.getChainBaseManager().getHeadSlot()); + long nowSlot = dbManager.getChainBaseManager().getHeadSlot(); + receiverCapsule.setLatestConsumeTime(nowSlot - 14400); dbManager.getAccountStore().put(receiver, receiverCapsule); + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + ownerCapsule.setNetUsage(1_000_000_000); + ownerCapsule.setLatestConsumeTime(nowSlot - 14400); + dbManager.getAccountStore().put(owner, ownerCapsule); UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( @@ -231,13 +236,13 @@ public void testUnDelegateForBandwidth() { TransactionResultCapsule ret = new TransactionResultCapsule(); try { - AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + ownerCapsule = dbManager.getAccountStore().get(owner); Assert.assertEquals(delegateBalance, receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForBandwidth()); Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); - Assert.assertEquals(0, ownerCapsule.getNetUsage()); + Assert.assertEquals(1_000_000_000, ownerCapsule.getNetUsage()); Assert.assertEquals(1_000_000_000, receiverCapsule.getNetUsage()); actuator.validate(); @@ -250,8 +255,7 @@ public void testUnDelegateForBandwidth() { Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForBandwidth()); Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); Assert.assertEquals(1000000000, ownerCapsule.getNetUsage()); - Assert.assertEquals(dbManager.getChainBaseManager().getHeadSlot(), - ownerCapsule.getLatestConsumeTime()); + Assert.assertEquals(nowSlot, ownerCapsule.getLatestConsumeTime()); // check receiver receiverCapsule = dbManager.getAccountStore().get(receiver); @@ -483,10 +487,15 @@ public void testUnDelegatedForCpu() { long now = System.currentTimeMillis(); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + long nowSlot = dbManager.getChainBaseManager().getHeadSlot(); AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); receiverCapsule.setEnergyUsage(1_000_000_000); - receiverCapsule.setLatestConsumeTimeForEnergy(dbManager.getChainBaseManager().getHeadSlot()); + receiverCapsule.setLatestConsumeTimeForEnergy(nowSlot - 14400); dbManager.getAccountStore().put(receiver, receiverCapsule); + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + ownerCapsule.setEnergyUsage(1_000_000_000); + ownerCapsule.setLatestConsumeTimeForEnergy(nowSlot - 14400); + dbManager.getAccountStore().put(owner, ownerCapsule); UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) @@ -494,13 +503,13 @@ public void testUnDelegatedForCpu() { TransactionResultCapsule ret = new TransactionResultCapsule(); try { - AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + ownerCapsule = dbManager.getAccountStore().get(owner); Assert.assertEquals(delegateBalance, receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForEnergy()); Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); - Assert.assertEquals(0, ownerCapsule.getEnergyUsage()); + Assert.assertEquals(1_000_000_000, ownerCapsule.getEnergyUsage()); Assert.assertEquals(1_000_000_000, receiverCapsule.getEnergyUsage()); actuator.validate(); @@ -513,8 +522,7 @@ public void testUnDelegatedForCpu() { Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForEnergy()); Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); Assert.assertEquals(1_000_000_000, ownerCapsule.getEnergyUsage()); - Assert.assertEquals(dbManager.getChainBaseManager().getHeadSlot(), - ownerCapsule.getLatestConsumeTimeForEnergy()); + Assert.assertEquals(nowSlot, ownerCapsule.getLatestConsumeTimeForEnergy()); // check receiver receiverCapsule = dbManager.getAccountStore().get(receiver); diff --git a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java index 83d4dcbe7cc..e9dc144b0d1 100644 --- a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java @@ -186,53 +186,6 @@ public void invalidOwnerAccount() { } } - @Test - public void isGR() { - Witness w = Args.getInstance().getGenesisBlock().getWitnesses().get(0); - byte[] address = w.getAddress(); - AccountCapsule grCapsule = new AccountCapsule(ByteString.copyFromUtf8("gr"), - ByteString.copyFrom(address), AccountType.Normal, initBalance); - dbManager.getAccountStore().put(grCapsule.createDbKey(), grCapsule); - long now = System.currentTimeMillis(); - dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); - - try { - dbManager.getMortgageService() - .adjustAllowance(dbManager.getAccountStore(), address, allowance); - } catch (BalanceInsufficientException e) { - fail("BalanceInsufficientException"); - } - AccountCapsule accountCapsule = dbManager.getAccountStore().get(address); - Assert.assertEquals(accountCapsule.getAllowance(), allowance); - - WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address), 100, - "http://google.com/"); - - dbManager.getAccountStore().put(address, accountCapsule); - dbManager.getWitnessStore().put(address, witnessCapsule); - - WithdrawExpireUnfreezeActuator actuator = new WithdrawExpireUnfreezeActuator(); - actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(ByteArray.toHexString(address))); - - TransactionResultCapsule ret = new TransactionResultCapsule(); - Assert.assertTrue(dbManager.getWitnessStore().has(address)); - - try { - actuator.validate(); - actuator.execute(ret); - fail("cannot run here."); - - } catch (ContractValidateException e) { - String readableOwnerAddress = StringUtil.createReadableString(address); - Assert.assertTrue(e instanceof ContractValidateException); - Assert.assertEquals("Account[" + readableOwnerAddress - + "] is a guard representative and is not allowed to withdraw Balance", e.getMessage()); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); - } - } - @Test public void commonErrorCheck() { From f947f83fa38be74cd291c0c03b8ed080520e9245 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 23 Sep 2022 18:22:12 +0800 Subject: [PATCH 0274/1197] fix(db): db iterator error --- .../db/common/iterator/RockStoreIterator.java | 11 ++- .../db/common/iterator/StoreIterator.java | 15 +++- .../java/org/tron/core/db/DBIteratorTest.java | 90 +++++++++++++++++++ 3 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/db/DBIteratorTest.java diff --git a/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java b/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java index a31ebca9409..a8c4cff2066 100644 --- a/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java +++ b/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java @@ -5,15 +5,16 @@ import java.util.NoSuchElementException; import lombok.extern.slf4j.Slf4j; import org.rocksdb.RocksIterator; -import org.tron.common.error.TronDBException; @Slf4j(topic = "DB") public final class RockStoreIterator implements DBIterator { - private RocksIterator dbIterator; + private final RocksIterator dbIterator; private boolean first = true; + private boolean valid = true; + public RockStoreIterator(RocksIterator dbIterator) { this.dbIterator = dbIterator; } @@ -25,6 +26,9 @@ public void close() throws IOException { @Override public boolean hasNext() { + if (!valid) { + return false; + } boolean hasNext = false; // true is first item try { @@ -34,6 +38,7 @@ public boolean hasNext() { } if (!(hasNext = dbIterator.isValid())) { // false is last item dbIterator.close(); + valid = false; } } catch (Exception e) { logger.error(e.getMessage(), e); @@ -48,7 +53,7 @@ public boolean hasNext() { @Override public Entry next() { - if (!dbIterator.isValid()) { + if (!valid) { throw new NoSuchElementException(); } byte[] key = dbIterator.key(); diff --git a/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java b/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java index 74fe4a70ed0..292bb421e54 100755 --- a/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java +++ b/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java @@ -2,16 +2,19 @@ import java.io.IOException; import java.util.Map.Entry; +import java.util.NoSuchElementException; import lombok.extern.slf4j.Slf4j; import org.iq80.leveldb.DBIterator; -import org.tron.common.error.TronDBException; + @Slf4j(topic = "DB") public final class StoreIterator implements org.tron.core.db.common.iterator.DBIterator { - private DBIterator dbIterator; + private final DBIterator dbIterator; private boolean first = true; + private boolean valid = true; + public StoreIterator(DBIterator dbIterator) { this.dbIterator = dbIterator; } @@ -23,6 +26,10 @@ public void close() throws IOException { @Override public boolean hasNext() { + if (!valid) { + return false; + } + boolean hasNext = false; // true is first item try { @@ -33,6 +40,7 @@ public boolean hasNext() { if (!(hasNext = dbIterator.hasNext())) { // false is last item dbIterator.close(); + valid = false; } } catch (Exception e) { logger.error(e.getMessage(), e); @@ -43,6 +51,9 @@ public boolean hasNext() { @Override public Entry next() { + if (!valid) { + throw new NoSuchElementException(); + } return dbIterator.next(); } diff --git a/framework/src/test/java/org/tron/core/db/DBIteratorTest.java b/framework/src/test/java/org/tron/core/db/DBIteratorTest.java new file mode 100644 index 00000000000..a55d1b04d4d --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/DBIteratorTest.java @@ -0,0 +1,90 @@ +package org.tron.core.db; + +import static org.fusesource.leveldbjni.JniDBFactory.factory; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Paths; +import java.util.NoSuchElementException; +import org.iq80.leveldb.DB; +import org.iq80.leveldb.Options; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.rocksdb.RocksDB; +import org.rocksdb.RocksDBException; +import org.tron.common.utils.FileUtil; +import org.tron.core.db.common.iterator.RockStoreIterator; +import org.tron.core.db.common.iterator.StoreIterator; + +public class DBIteratorTest { + + @BeforeClass + public static void init() { + File file = Paths.get("database-iterator").toFile(); + if (!file.exists()) { + file.mkdirs(); + } + } + + @AfterClass + public static void clear() { + File file = Paths.get("database-iterator").toFile(); + if (file.exists()) { + FileUtil.deleteDir(Paths.get("database-iterator").toFile()); + } + } + + + @Test + public void testLevelDb() throws IOException { + File file = new File("database-iterator/testLevelDb"); + try { + DB db = factory.open(file, new Options().createIfMissing(true)); + db.put("1".getBytes(StandardCharsets.UTF_8), "1".getBytes(StandardCharsets.UTF_8)); + db.put("2".getBytes(StandardCharsets.UTF_8), "2".getBytes(StandardCharsets.UTF_8)); + StoreIterator iterator = new StoreIterator(db.iterator()); + while (iterator.hasNext()) { + iterator.next(); + } + Assert.assertFalse(iterator.hasNext()); + try { + iterator.next(); + } catch (Exception e) { + Assert.assertTrue(e instanceof NoSuchElementException); + } + db.close(); + } finally { + factory.destroy(file, new Options()); + } + + + } + + @Test + public void testRocksDb() throws RocksDBException { + File file = new File("database-iterator/testRocksDb"); + try (org.rocksdb.Options options = new org.rocksdb.Options().setCreateIfMissing(true)) { + RocksDB db = RocksDB.open(options, file.toString()); + db.put("1".getBytes(StandardCharsets.UTF_8), "1".getBytes(StandardCharsets.UTF_8)); + db.put("2".getBytes(StandardCharsets.UTF_8), "2".getBytes(StandardCharsets.UTF_8)); + RockStoreIterator iterator = new RockStoreIterator(db.newIterator()); + while (iterator.hasNext()) { + iterator.next(); + } + Assert.assertFalse(iterator.hasNext()); + try { + iterator.next(); + } catch (Exception e) { + Assert.assertTrue(e instanceof NoSuchElementException); + } + db.close(); + } finally { + RocksDB.destroyDB(file.toString(), new org.rocksdb.Options()); + } + + } + +} From 109dea5fd75df348cefb5fae99614ee34a81e027 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Mon, 26 Sep 2022 17:38:00 +0800 Subject: [PATCH 0275/1197] feat(freezeV2): add api for freezing and delegation --- .../actuator/DelegateResourceActuator.java | 5 ++++ .../actuator/FreezeBalanceV2Actuator.java | 5 ++++ .../actuator/UnDelegateResourceActuator.java | 5 ++++ .../actuator/UnfreezeBalanceV2Actuator.java | 6 ++++ .../WithdrawExpireUnfreezeActuator.java | 6 ++++ .../services/http/FullNodeHttpApiService.java | 2 +- .../solidity/SolidityNodeHttpApiService.java | 28 +++++++++++++++++-- 7 files changed, 54 insertions(+), 3 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 152c4fb2a7a..46aeb77e40b 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -109,6 +109,11 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("No support for resource delegate"); } + if (dynamicStore.getUnfreezeDelayDays() == 0) { + throw new ContractValidateException("Not support Delegate resource transaction," + + " need to be opened by the committee"); + } + final DelegateResourceContract delegateResourceContract; try { delegateResourceContract = this.any.unpack(DelegateResourceContract.class); diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java index 743aaff6824..60981f00588 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java @@ -96,6 +96,11 @@ public boolean validate() throws ContractValidateException { .getClass() + "]"); } + if (dynamicStore.getUnfreezeDelayDays() == 0) { + throw new ContractValidateException("Not support FreezeV2 transaction," + + " need to be opened by the committee"); + } + final FreezeBalanceV2Contract freezeBalanceV2Contract; try { freezeBalanceV2Contract = this.any.unpack(FreezeBalanceV2Contract.class); diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index f18083f77d2..414b9e44dc1 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -215,6 +215,11 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("No support for resource delegate"); } + if (dynamicStore.getUnfreezeDelayDays() == 0) { + throw new ContractValidateException("Not support Delegate resource transaction," + + " need to be opened by the committee"); + } + if (!this.any.is(UnDelegateResourceContract.class)) { throw new ContractValidateException( "contract type error, expected type [UnDelegateResourceContract], real type[" + any diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java index 09c2b90e6ef..c4edbf6d957 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java @@ -108,6 +108,12 @@ public boolean validate() throws ContractValidateException { "contract type error, expected type [UnfreezeBalanceContract], real type[" + any .getClass() + "]"); } + + if (dynamicStore.getUnfreezeDelayDays() == 0) { + throw new ContractValidateException("Not support UnfreezeV2 transaction," + + " need to be opened by the committee"); + } + final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract; try { unfreezeBalanceV2Contract = this.any.unpack(UnfreezeBalanceV2Contract.class); diff --git a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java index 5d49701ef92..11b991585f6 100755 --- a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java @@ -80,6 +80,12 @@ public boolean validate() throws ContractValidateException { "contract type error, expected type [WithdrawExpireUnfreezeContract], real type[" + any .getClass() + "]"); } + + if (dynamicStore.getUnfreezeDelayDays() == 0) { + throw new ContractValidateException("Not support WithdrawExpireUnfreeze transaction," + + " need to be opened by the committee"); + } + final WithdrawExpireUnfreezeContract withdrawExpireUnfreezeContract; try { withdrawExpireUnfreezeContract = this.any.unpack(WithdrawExpireUnfreezeContract.class); diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index 43a0d87661b..2c2a4f8797c 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -559,7 +559,7 @@ public void start() { context.addServlet(new ServletHolder(unFreezeBalanceV2Servlet), "/wallet/unfreezebalancev2"); context.addServlet(new ServletHolder(withdrawExpireUnfreezeServlet), - "/wallet/withdrawExpireUnfreeze"); + "/wallet/withdrawexpireunfreeze"); context.addServlet(new ServletHolder(delegateResourceServlet), "/wallet/delegateresource"); context.addServlet(new ServletHolder(unDelegateResourceServlet), diff --git a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java index 7453c833c10..e4ad276782e 100644 --- a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java @@ -2,13 +2,11 @@ import java.util.EnumSet; import javax.servlet.DispatcherType; -import javax.servlet.Filter; import lombok.extern.slf4j.Slf4j; import org.eclipse.jetty.server.ConnectionLimit; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -16,6 +14,8 @@ import org.tron.common.parameter.CommonParameter; import org.tron.core.config.args.Args; import org.tron.core.services.filter.HttpApiAccessFilter; +import org.tron.core.services.http.DelegateResourceServlet; +import org.tron.core.services.http.FreezeBalanceV2Servlet; import org.tron.core.services.http.FullNodeHttpApiService; import org.tron.core.services.http.GetAccountByIdServlet; import org.tron.core.services.http.GetAccountServlet; @@ -55,6 +55,9 @@ import org.tron.core.services.http.ScanShieldedTRC20NotesByIvkServlet; import org.tron.core.services.http.ScanShieldedTRC20NotesByOvkServlet; import org.tron.core.services.http.TriggerConstantContractServlet; +import org.tron.core.services.http.UnDelegateResourceServlet; +import org.tron.core.services.http.UnFreezeBalanceV2Servlet; +import org.tron.core.services.http.WithdrawExpireUnfreezeServlet; @Component @@ -153,6 +156,17 @@ public class SolidityNodeHttpApiService implements Service { @Autowired private GetBlockServlet getBlockServlet; + @Autowired + private FreezeBalanceV2Servlet freezeBalanceV2Servlet; + @Autowired + private UnFreezeBalanceV2Servlet unFreezeBalanceV2Servlet; + @Autowired + private WithdrawExpireUnfreezeServlet withdrawExpireUnfreezeServlet; + @Autowired + private DelegateResourceServlet delegateResourceServlet; + @Autowired + private UnDelegateResourceServlet unDelegateResourceServlet; + @Override public void init() { } @@ -255,6 +269,16 @@ public void start() { context.addServlet(new ServletHolder(getRewardServlet), "/walletsolidity/getReward"); context.addServlet(new ServletHolder(getBurnTrxServlet), "/walletsolidity/getburntrx"); context.addServlet(new ServletHolder(getBlockServlet), "/walletsolidity/getblock"); + context.addServlet(new ServletHolder(freezeBalanceV2Servlet), + "/walletsolidity/freezebalancev2"); + context.addServlet(new ServletHolder(unFreezeBalanceV2Servlet), + "/walletsolidity/unfreezebalancev2"); + context.addServlet(new ServletHolder(withdrawExpireUnfreezeServlet), + "/walletsolidity/withdrawexpireunfreeze"); + context.addServlet(new ServletHolder(delegateResourceServlet), + "/walletsolidity/delegateresource"); + context.addServlet(new ServletHolder(unDelegateResourceServlet), + "/walletsolidity/undelegateresource"); // http access filter context.addFilter(new FilterHolder(httpApiAccessFilter), "/walletsolidity/*", EnumSet.allOf(DispatcherType.class)); From 53f0b3eb81ed5feb5532f9b50a6147c6a1710d53 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Mon, 26 Sep 2022 18:37:12 +0800 Subject: [PATCH 0276/1197] feat(freezeV2): add the config param for unfreezeDelayDays --- common/src/main/java/org/tron/core/Constant.java | 1 + .../src/main/java/org/tron/core/config/args/Args.java | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 94eed9f9941..b00546a54e8 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -285,6 +285,7 @@ public class Constant { public static final String COMMITTEE_ALLOW_TVM_FREEZE = "committee.allowTvmFreeze"; public static final String COMMITTEE_ALLOW_TVM_VOTE = "committee.allowTvmVote"; + public static final String COMMITTEE_UNFREEZE_DELAY_DAYS = "committee.unfreezeDelayDays"; public static final String COMMITTEE_ALLOW_TVM_LONDON = "committee.allowTvmLondon"; public static final String COMMITTEE_ALLOW_TVM_COMPATIBLE_EVM = "committee.allowTvmCompatibleEvm"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 029e89d6cd6..3fec975d5ba 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1024,6 +1024,16 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.blockCacheTimeout = config.getLong(Constant.BLOCK_CACHE_TIMEOUT); } + if (config.hasPath(Constant.COMMITTEE_UNFREEZE_DELAY_DAYS)) { + PARAMETER.unfreezeDelayDays = config.getLong(Constant.COMMITTEE_UNFREEZE_DELAY_DAYS); + if (PARAMETER.unfreezeDelayDays > 365) { + PARAMETER.unfreezeDelayDays = 365; + } + if (PARAMETER.unfreezeDelayDays < 0) { + PARAMETER.unfreezeDelayDays = 0; + } + } + logConfig(); } From 84d2a217fca798109b59e08c53b71a876af96a7b Mon Sep 17 00:00:00 2001 From: guoquanwu Date: Tue, 27 Sep 2022 18:15:43 +0800 Subject: [PATCH 0277/1197] fix: make delete operation atomic when cleaning tmp db --- .../java/org/tron/core/db2/core/SnapshotManager.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java index 3810667e465..2466ad08c7e 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java @@ -429,7 +429,17 @@ private List getCheckpointList() { } private void deleteCheckpoint() { - checkTmpStore.reset(); + try { + Map hmap = new HashMap<>(); + for (Map.Entry e : checkTmpStore.getDbSource()) { + hmap.put(e.getKey(), null); + } + if (hmap.size() != 0) { + checkTmpStore.getDbSource().updateByBatch(hmap); + } + } catch (Exception e) { + throw new TronDBException(e); + } } private void pruneCheckpoint() { From 0db37bfed6f986d3f3a4e91799cd4e710af06276 Mon Sep 17 00:00:00 2001 From: Wenhua Zhang Date: Fri, 30 Sep 2022 15:11:49 +0800 Subject: [PATCH 0278/1197] feat: return err code 32602 when param is not valid --- .../java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 55bb167e771..4da6fe4b1e2 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -732,7 +732,7 @@ public String getCall(CallArguments transactionCall, Object blockParamObj) try { blockNumOrTag = paramMap.get("blockNumber"); } catch (ClassCastException e) { - throw new JsonRpcInvalidRequestException(JSON_ERROR); + throw new JsonRpcInvalidParamsException(JSON_ERROR); } long blockNumber; @@ -750,7 +750,7 @@ public String getCall(CallArguments transactionCall, Object blockParamObj) try { blockNumOrTag = paramMap.get("blockHash"); } catch (ClassCastException e) { - throw new JsonRpcInvalidRequestException(JSON_ERROR); + throw new JsonRpcInvalidParamsException(JSON_ERROR); } if (getBlockByJsonHash(blockNumOrTag) == null) { From 86524afbef63a63dec242b2695a562c9b7832da7 Mon Sep 17 00:00:00 2001 From: bladehan1 Date: Fri, 30 Sep 2022 16:08:42 +0800 Subject: [PATCH 0279/1197] feat(reward): add config for new reward algorithm proposal --- .../tron/core/store/DynamicPropertiesStore.java | 15 ++++++++++++++- .../tron/common/parameter/CommonParameter.java | 4 ++++ common/src/main/java/org/tron/core/Constant.java | 2 ++ .../main/java/org/tron/core/config/args/Args.java | 5 +++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 07baabdbb2a..df37059f2ad 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -845,6 +845,18 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { this.saveAllowHigherLimitForMaxCpuTimeOfOneTx( CommonParameter.getInstance().getAllowHigherLimitForMaxCpuTimeOfOneTx()); } + + try { + this.getNewRewardAlgorithmEffectiveCycle(); + } catch (IllegalArgumentException e) { + if (CommonParameter.getInstance().getAllowNewRewardAlgorithm() == 1) { + this.put(NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE, + new BytesCapsule(ByteArray.fromLong(getCurrentCycleNumber()))); + } else { + this.put(NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE, + new BytesCapsule(ByteArray.fromLong(Long.MAX_VALUE))); + } + } } public String intArrayToString(int[] a) { @@ -2397,7 +2409,8 @@ public long getNewRewardAlgorithmEffectiveCycle() { return Optional.ofNullable(getUnchecked(NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE)) .map(BytesCapsule::getData) .map(ByteArray::toLong) - .orElse(Long.MAX_VALUE); + .orElseThrow( + () -> new IllegalArgumentException("not found NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE")); } public long getAllowAccountAssetOptimizationFromRoot() { diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 283ffd299e3..26aa7d44834 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -557,6 +557,10 @@ public class CommonParameter { @Setter public long blockCacheTimeout = 60; + @Getter + @Setter + public long allowNewRewardAlgorithm; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 94eed9f9941..af96fbea859 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -290,6 +290,8 @@ public class Constant { public static final String COMMITTEE_ALLOW_TVM_COMPATIBLE_EVM = "committee.allowTvmCompatibleEvm"; public static final String COMMITTEE_ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX = "committee.allowHigherLimitForMaxCpuTimeOfOneTx"; + public static final String COMMITTEE_ALLOW_NEW_REWARD_ALGORITHM = "committee.allowNewRewardAlgorithm"; + public static final String METRICS_STORAGE_ENABLE = "node.metrics.storageEnable"; public static final String METRICS_INFLUXDB_IP = "node.metrics.influxdb.ip"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 5fd20d2f8e5..b75664ed3c1 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -214,6 +214,7 @@ public static void clearParam() { PARAMETER.shutdownBlockHeight = -1; PARAMETER.shutdownBlockCount = -1; PARAMETER.blockCacheTimeout = 60; + PARAMETER.allowNewRewardAlgorithm = 0; } /** @@ -946,6 +947,10 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.COMMITTEE_ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX) ? config .getInt(Constant.COMMITTEE_ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX) : 0; + PARAMETER.allowNewRewardAlgorithm = + config.hasPath(Constant.COMMITTEE_ALLOW_NEW_REWARD_ALGORITHM) ? config + .getInt(Constant.COMMITTEE_ALLOW_NEW_REWARD_ALGORITHM) : 0; + initBackupProperty(config); if (Constant.ROCKSDB.equalsIgnoreCase(CommonParameter .getInstance().getStorage().getDbEngine())) { From 3a71631984e5cd77ad411f4ba17880ef583fad53 Mon Sep 17 00:00:00 2001 From: didbit Date: Sat, 8 Oct 2022 08:47:40 -0300 Subject: [PATCH 0280/1197] Update docker.md --- docker/docker.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/docker.md b/docker/docker.md index 3c32830b6c4..7d9e6ba5ad5 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -12,7 +12,7 @@ Requires a docker to be installed on the system. Docker version >=20.10.12. Shell can be obtained from the java-tron project or independently, you can get the script from [here](https://github.com/tronprotocol/java-tron/docker.sh) or download via the wget: ```shell -$ wget https://raw.githubusercontent.com/tronprotocol/java-tron/develop/docker.sh +$ wget https://raw.githubusercontent.com/tronprotocol/java-tron/develop/docker/docker.sh ``` ### Pull the mirror image From d9076ffbea26f3195c33b19b1312eb0f28d28c3c Mon Sep 17 00:00:00 2001 From: didbit Date: Sat, 8 Oct 2022 09:02:30 -0300 Subject: [PATCH 0281/1197] Update docker.md --- docker/docker.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/docker.md b/docker/docker.md index 7d9e6ba5ad5..a187f04631b 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -10,7 +10,7 @@ Requires a docker to be installed on the system. Docker version >=20.10.12. ## Quick Start -Shell can be obtained from the java-tron project or independently, you can get the script from [here](https://github.com/tronprotocol/java-tron/docker.sh) or download via the wget: +Shell can be obtained from the java-tron project or independently, you can get the script from [here](https://github.com/tronprotocol/java-tron/blob/develop/docker/docker.sh) or download via the wget: ```shell $ wget https://raw.githubusercontent.com/tronprotocol/java-tron/develop/docker/docker.sh ``` From 0cc07dbd3fceaf4661f03dd568fc195467c02c41 Mon Sep 17 00:00:00 2001 From: guoquanwu Date: Sun, 9 Oct 2022 11:33:59 +0800 Subject: [PATCH 0282/1197] fix(db): the operation of putting byte[0] should be reserved instead of deleting --- .../main/java/org/tron/core/db2/core/SnapshotManager.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java index 2466ad08c7e..f41e1490d87 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java @@ -530,7 +530,12 @@ private void recover(TronDatabase tronDatabase) { if (realValue != null) { dbMap.get(db).getHead().put(realKey, realValue); } else { - dbMap.get(db).getHead().remove(realKey); + byte op = value[0]; + if (Value.Operator.DELETE.getValue() == op) { + dbMap.get(db).getHead().remove(realKey); + } else { + dbMap.get(db).getHead().put(realKey, new byte[0]); + } } } From 96869646c57ed9c0a02730a3bdd8707ccdb745f3 Mon Sep 17 00:00:00 2001 From: chaozhu Date: Tue, 27 Sep 2022 18:16:57 -0700 Subject: [PATCH 0283/1197] fix(freezeV2): fix http request address params --- .../core/services/http/HttpSelfFormatFieldName.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java b/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java index 99fa55d9241..2526a9cfabe 100644 --- a/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java +++ b/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java @@ -142,6 +142,18 @@ public class HttpSelfFormatFieldName { AddressFieldNameMap.put("protocol.ShieldedTransferContract.transparent_to_address", 1); //UpdateBrokerageContract AddressFieldNameMap.put("protocol.UpdateBrokerageContract.owner_address", 1); + //FreezeBalanceV2Contract + AddressFieldNameMap.put("protocol.FreezeBalanceV2Contract.owner_address", 1); + //UnfreezeBalanceV2Contract + AddressFieldNameMap.put("protocol.UnfreezeBalanceV2Contract.owner_address", 1); + //WithdrawExpireUnfreezeContract + AddressFieldNameMap.put("protocol.WithdrawExpireUnfreezeContract.owner_address", 1); + //DelegateResourceContract + AddressFieldNameMap.put("protocol.DelegateResourceContract.owner_address", 1); + AddressFieldNameMap.put("protocol.DelegateResourceContract.receiver_address", 1); + //UnDelegateResourceContract + AddressFieldNameMap.put("protocol.UnDelegateResourceContract.owner_address", 1); + AddressFieldNameMap.put("protocol.UnDelegateResourceContract.receiver_address", 1); //***** Tron.proto ***** //AccountId From 9a4be62108eb69154016ddb130626c11aec27ef0 Mon Sep 17 00:00:00 2001 From: chaozhu Date: Thu, 29 Sep 2022 12:07:33 -0700 Subject: [PATCH 0284/1197] docs(proto): update Tron protobuf protocol document.md --- Tron protobuf protocol document.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Tron protobuf protocol document.md b/Tron protobuf protocol document.md index be9558a1d93..f6fa2219ce3 100644 --- a/Tron protobuf protocol document.md +++ b/Tron protobuf protocol document.md @@ -620,6 +620,13 @@ Transaction and transaction-related messages. ClearABIContract = 48; UpdateBrokerageContract = 49; ShieldedTransferContract = 51; + MarketSellAssetContract = 52; + MarketCancelOrderContract = 53; + FreezeBalanceV2Contract = 54; + UnfreezeBalanceV2Contract = 55; + WithdrawExpireUnfreezeContract = 56; + DelegateResourceContract = 57; + UnDelegateResourceContract = 58; } ContractType type = 1; google.protobuf.Any parameter = 2; @@ -873,6 +880,13 @@ Contract and contract-related messages. ClearABIContract = 48; UpdateBrokerageContract = 49; ShieldedTransferContract = 51; + MarketSellAssetContract = 52; + MarketCancelOrderContract = 53; + FreezeBalanceV2Contract = 54; + UnfreezeBalanceV2Contract = 55; + WithdrawExpireUnfreezeContract = 56; + DelegateResourceContract = 57; + UnDelegateResourceContract = 58; } ContractType type = 1; google.protobuf.Any parameter = 2; From 104460be169472bc455e365717863f8277e15b47 Mon Sep 17 00:00:00 2001 From: Liulei Date: Fri, 14 Oct 2022 10:56:41 +0800 Subject: [PATCH 0285/1197] feat(freezeV2): add freeze and delegate vm operations --- .../java/org/tron/core/vm/EnergyCost.java | 35 +++ .../src/main/java/org/tron/core/vm/Op.java | 6 + .../org/tron/core/vm/OperationActions.java | 71 +++++ .../org/tron/core/vm/OperationRegistry.java | 43 +++ .../DelegateResourceProcessor.java | 174 ++++++++++++ .../ExpireFreezeV2BalanceProcessor.java | 55 ++++ .../FreezeBalanceV2Processor.java | 102 +++++++ .../UnDelegateResourceProcessor.java | 198 ++++++++++++++ .../UnfreezeBalanceV2Processor.java | 248 ++++++++++++++++++ .../WithdrawExpireUnfreezeProcessor.java | 95 +++++++ .../param/DelegateResourceParam.java | 46 ++++ .../param/ExpireFreezeV2BalanceParam.java | 26 ++ .../param/FreezeBalanceV2Param.java | 46 ++++ .../param/UnDelegateResourceParam.java | 46 ++++ .../param/UnfreezeBalanceV2Param.java | 36 +++ .../param/WithdrawExpireUnfreezeParam.java | 26 ++ .../org/tron/core/vm/program/Program.java | 188 ++++++++++++- 17 files changed, 1440 insertions(+), 1 deletion(-) create mode 100644 actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java create mode 100644 actuator/src/main/java/org/tron/core/vm/nativecontract/ExpireFreezeV2BalanceProcessor.java create mode 100644 actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java create mode 100644 actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java create mode 100644 actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java create mode 100644 actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java create mode 100644 actuator/src/main/java/org/tron/core/vm/nativecontract/param/DelegateResourceParam.java create mode 100644 actuator/src/main/java/org/tron/core/vm/nativecontract/param/ExpireFreezeV2BalanceParam.java create mode 100644 actuator/src/main/java/org/tron/core/vm/nativecontract/param/FreezeBalanceV2Param.java create mode 100644 actuator/src/main/java/org/tron/core/vm/nativecontract/param/UnDelegateResourceParam.java create mode 100644 actuator/src/main/java/org/tron/core/vm/nativecontract/param/UnfreezeBalanceV2Param.java create mode 100644 actuator/src/main/java/org/tron/core/vm/nativecontract/param/WithdrawExpireUnfreezeParam.java diff --git a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java index 8253e4bf7e6..cafe86bbc05 100644 --- a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java +++ b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java @@ -36,6 +36,12 @@ public class EnergyCost { private static final long NEW_ACCT_CALL = 25000; private static final long UNFREEZE = 20000; private static final long FREEZE_EXPIRE_TIME = 50; + private static final long FREEZE_V2 = 20000; + private static final long UNFREEZE_V2 = 20000; + private static final long EXPIRE_FREEZE_V2_BALANCE = 50; + private static final long WITHDRAW_EXPIRE_UNFREEZE = 20000; + private static final long DELEGATE_RESOURCE = 20000; + private static final long UN_DELEGATE_RESOURCE = 20000; private static final long VOTE_WITNESS = 30000; private static final long WITHDRAW_REWARD = 20000; private static final long CREATE = 32000; @@ -272,6 +278,35 @@ public static long getFreezeExpireTimeCost(Program ignored) { return FREEZE_EXPIRE_TIME; } + public static long getFreezeBalanceV2Cost(Program ignored) { + return FREEZE_V2; + } + + public static long getUnfreezeBalanceV2Cost(Program ignored) { + return UNFREEZE_V2; + } + + public static long getWithdrawExpireUnfreezeCost(Program ignored) { + return WITHDRAW_EXPIRE_UNFREEZE; + } + + public static long getExpireFreezeV2BalanceCost(Program ignored) { + return EXPIRE_FREEZE_V2_BALANCE; + } + + public static long getDelegateResourceCost(Program program) { + Stack stack = program.getStack(); + DataWord receiverAddressWord = stack.get(stack.size() - 3); + if (isDeadAccount(program, receiverAddressWord)) { + return DELEGATE_RESOURCE + NEW_ACCT_CALL; + } + return DELEGATE_RESOURCE; + } + + public static long getUnDelegateResourceCost(Program ignored) { + return UN_DELEGATE_RESOURCE; + } + public static long getVoteWitnessCost(Program program) { Stack stack = program.getStack(); diff --git a/actuator/src/main/java/org/tron/core/vm/Op.java b/actuator/src/main/java/org/tron/core/vm/Op.java index 6abf6a04632..5c5b8ea21d4 100644 --- a/actuator/src/main/java/org/tron/core/vm/Op.java +++ b/actuator/src/main/java/org/tron/core/vm/Op.java @@ -236,6 +236,12 @@ public class Op { public static final int FREEZEEXPIRETIME = 0xd7; public static final int VOTEWITNESS = 0xd8; public static final int WITHDRAWREWARD = 0xd9; + public static final int FREEZEBALANCEV2 = 0xd10; + public static final int UNFREEZEBALANCEV2 = 0xd11; + public static final int EXPIREFREEZEV2BALANCE = 0xd12; + public static final int WITHDRAWEXPIREUNFREEZE = 0xd13; + public static final int DELEGATERESOURCE = 0xd14; + public static final int UNDELEGATERESOURCE = 0xd15; // (0xf0) Create a new account with associated code public static final int CREATE = 0xf0; diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index c7a9c2cc2e3..94bd8e6b7ca 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -764,6 +764,77 @@ public static void freezeExpireTimeAction(Program program) { program.step(); } + public static void freezeBalanceV2Action(Program program) { + // after allow vote, check static + if (VMConfig.allowTvmVote() && program.isStaticCall()) { + throw new Program.StaticCallModificationException(); + } + DataWord resourceType = program.stackPop(); + DataWord frozenBalance = program.stackPop(); + + boolean result = program.freezeBalanceV2(frozenBalance, resourceType); + program.stackPush(result ? DataWord.ONE() : DataWord.ZERO()); + program.step(); + } + + public static void unfreezeBalanceV2Action(Program program) { + if (VMConfig.allowTvmVote() && program.isStaticCall()) { + throw new Program.StaticCallModificationException(); + } + + DataWord resourceType = program.stackPop(); + DataWord unfreezeBalance = program.stackPop(); + + boolean result = program.unfreezeBalanceV2(unfreezeBalance, resourceType); + program.stackPush(result ? DataWord.ONE() : DataWord.ZERO()); + program.step(); + } + + public static void withdrawExpireUnfreezeAction(Program program) { + if (program.isStaticCall()) { + throw new Program.StaticCallModificationException(); + } + + long expireUnfreezeBalance = program.withdrawExpireUnfreeze(); + program.stackPush(new DataWord(expireUnfreezeBalance)); + program.step(); + } + + public static void expireFreezeV2BalanceAction(Program program) { + DataWord resourceType = program.stackPop(); + DataWord ownerAddress = program.stackPop(); + + long balance = program.expireFreezeV2Balance(ownerAddress, resourceType); + program.stackPush(new DataWord(balance)); + program.step(); + } + + public static void delegateResourceAction(Program program) { + if (program.isStaticCall()) { + throw new Program.StaticCallModificationException(); + } + DataWord resourceType = program.stackPop(); + DataWord delegateBalance = program.stackPop(); + DataWord receiverAddress = program.stackPop(); + + boolean result = program.delegateResource(receiverAddress, delegateBalance, resourceType); + program.stackPush(result ? DataWord.ONE() : DataWord.ZERO()); + program.step(); + } + + public static void unDelegateResourceAction(Program program) { + if (program.isStaticCall()) { + throw new Program.StaticCallModificationException(); + } + DataWord resourceType = program.stackPop(); + DataWord unDelegateBalance = program.stackPop(); + DataWord receiverAddress = program.stackPop(); + + boolean result = program.unDelegateResource(receiverAddress, unDelegateBalance, resourceType); + program.stackPush(result ? DataWord.ONE() : DataWord.ZERO()); + program.step(); + } + public static void voteWitnessAction(Program program) { if (program.isStaticCall()) { throw new Program.StaticCallModificationException(); diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index fb66f69d1e4..bd1ff3b48af 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -37,6 +37,8 @@ public static JumpTable newTronV10OperationSet() { public static JumpTable newTronV11OperationSet() { JumpTable table = newTronV10OperationSet(); adjustMemOperations(table); + appendFreezeV2Operations(table); + appendDelegateOperations(table); return table; } @@ -565,4 +567,45 @@ public static void adjustMemOperations(JumpTable table) { EnergyCost::getMStore8Cost2, OperationActions::mStore8Action)); } + + public static void appendFreezeV2Operations(JumpTable table) { + BooleanSupplier proposal = VMConfig::allowTvmFreeze; + + table.set(new Operation( + Op.FREEZEBALANCEV2, 2, 1, + EnergyCost::getFreezeBalanceV2Cost, + OperationActions::freezeBalanceV2Action, + proposal)); + + table.set(new Operation( + Op.UNFREEZEBALANCEV2, 2, 1, + EnergyCost::getUnfreezeBalanceV2Cost, + OperationActions::unfreezeBalanceV2Action, + proposal)); + + table.set(new Operation( + Op.WITHDRAWEXPIREUNFREEZE, 0, 1, + EnergyCost::getWithdrawExpireUnfreezeCost, + OperationActions::withdrawExpireUnfreezeAction, + proposal)); + + table.set(new Operation( + Op.EXPIREFREEZEV2BALANCE, 2, 1, + EnergyCost::getExpireFreezeV2BalanceCost, + OperationActions::expireFreezeV2BalanceAction, + proposal)); + } + + public static void appendDelegateOperations(JumpTable table) { + + table.set(new Operation( + Op.DELEGATERESOURCE, 3, 1, + EnergyCost::getDelegateResourceCost, + OperationActions::delegateResourceAction)); + + table.set(new Operation( + Op.UNDELEGATERESOURCE, 3, 1, + EnergyCost::getUnDelegateResourceCost, + OperationActions::unDelegateResourceAction)); + } } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java new file mode 100644 index 00000000000..5ccbfd99b01 --- /dev/null +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -0,0 +1,174 @@ +package org.tron.core.vm.nativecontract; + +import com.google.protobuf.ByteString; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; +import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.ChainBaseManager; +import org.tron.core.actuator.ActuatorConstant; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceCapsule; +import org.tron.core.db.BandwidthProcessor; +import org.tron.core.db.EnergyProcessor; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.vm.nativecontract.param.DelegateResourceParam; +import org.tron.core.vm.repository.Repository; +import org.tron.protos.Protocol; + +import java.util.Arrays; + +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +@Slf4j(topic = "VMProcessor") +public class DelegateResourceProcessor { + + public void validate(DelegateResourceParam param, Repository repo) throws ContractValidateException { + if (repo == null) { + throw new ContractValidateException(STORE_NOT_EXIST); + } + + byte[] ownerAddress = param.getOwnerAddress(); + AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); + DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); + if (!dynamicStore.supportDR()) { + throw new ContractValidateException("No support for resource delegate"); + } + if (dynamicStore.getUnfreezeDelayDays() == 0) { + throw new ContractValidateException("Not support Delegate resource transaction," + + " need to be opened by the committee"); + } + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + if (ownerCapsule == null) { + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + throw new ContractValidateException( + ActuatorConstant.ACCOUNT_EXCEPTION_STR + readableOwnerAddress + NOT_EXIST_STR); + } + long delegateBalance = param.getDelegateBalance(); + if (delegateBalance < TRX_PRECISION) { + throw new ContractValidateException("delegateBalance must be more than 1TRX"); + } + + switch (param.getResourceType()) { + case BANDWIDTH: { + BandwidthProcessor processor = new BandwidthProcessor(ChainBaseManager.getInstance()); + processor.updateUsage(ownerCapsule); + //The unit is trx + long netTrxUsage = (long) (ownerCapsule.getNetUsage() + * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); + + if (ownerCapsule.getFrozenV2BalanceForBandwidth() - netTrxUsage * TRX_PRECISION + < delegateBalance) { + throw new ContractValidateException( + "delegateBalance must be less than available FreezeBandwidthV2 balance"); + } + } + break; + case ENERGY: { + EnergyProcessor processor = + new EnergyProcessor(dynamicStore, ChainBaseManager.getInstance().getAccountStore()); + processor.updateUsage(ownerCapsule); + + //The unit is trx + long energyTrxUsage = (long) (ownerCapsule.getEnergyUsage() + * ((double) (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); + + if (ownerCapsule.getFrozenV2BalanceForEnergy() - energyTrxUsage * TRX_PRECISION + < delegateBalance) { + throw new ContractValidateException( + "delegateBalance must be less than available FreezeEnergyV2Balance balance"); + } + } + break; + default: + throw new ContractValidateException( + "ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]"); + } + + byte[] receiverAddress = param.getReceiverAddress(); + + if (ArrayUtils.isEmpty(receiverAddress) || !DecodeUtil.addressValid(receiverAddress)) { + throw new ContractValidateException("Invalid receiverAddress"); + } + if (Arrays.equals(receiverAddress, ownerAddress)) { + throw new ContractValidateException( + "receiverAddress must not be the same as ownerAddress"); + } + AccountCapsule receiverCapsule = repo.getAccount(receiverAddress); + if (receiverCapsule == null) { + String readableOwnerAddress = StringUtil.createReadableString(receiverAddress); + throw new ContractValidateException( + ActuatorConstant.ACCOUNT_EXCEPTION_STR + + readableOwnerAddress + NOT_EXIST_STR); + } + if (receiverCapsule.getType() == Protocol.AccountType.Contract) { + throw new ContractValidateException( + "Do not allow delegate resources to contract addresses"); + } + } + + public void execute(DelegateResourceParam param, Repository repo) { + byte[] ownerAddress = param.getOwnerAddress(); + AccountCapsule ownerCapsule = repo.getAccount(param.getOwnerAddress()); + long delegateBalance = param.getDelegateBalance(); + byte[] receiverAddress = param.getReceiverAddress(); + + // delegate resource to receiver + switch (param.getResourceType()) { + case BANDWIDTH: + delegateResource(ownerAddress, receiverAddress, true, + delegateBalance, repo); + + ownerCapsule.addDelegatedFrozenBalanceForBandwidth(delegateBalance); + ownerCapsule.addFrozenBalanceForBandwidthV2(-delegateBalance); + break; + case ENERGY: + delegateResource(ownerAddress, receiverAddress, false, + delegateBalance,repo); + + ownerCapsule.addDelegatedFrozenBalanceForEnergy(delegateBalance); + ownerCapsule.addFrozenBalanceForEnergyV2(-delegateBalance); + break; + default: + logger.debug("Resource Code Error."); + } + + repo.updateAccount(ownerCapsule.createDbKey(), ownerCapsule); + } + + private void delegateResource( + byte[] ownerAddress, + byte[] receiverAddress, + boolean isBandwidth, + long delegateBalance, + Repository repo) { + //modify DelegatedResourceStore + byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress); + DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); + if (delegatedResourceCapsule == null) { + delegatedResourceCapsule = new DelegatedResourceCapsule( + ByteString.copyFrom(ownerAddress), + ByteString.copyFrom(receiverAddress)); + } + if (isBandwidth) { + delegatedResourceCapsule.addFrozenBalanceForBandwidth(delegateBalance, 0); + } else { + delegatedResourceCapsule.addFrozenBalanceForEnergy(delegateBalance, 0); + } + + //update Account for receiver + AccountCapsule receiverCapsule = repo.getAccount(receiverAddress); + if (isBandwidth) { + receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(delegateBalance); + } else { + receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(delegateBalance); + } + repo.updateDelegatedResource(key, delegatedResourceCapsule); + repo.updateAccount(receiverCapsule.createDbKey(), receiverCapsule); + } +} diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/ExpireFreezeV2BalanceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/ExpireFreezeV2BalanceProcessor.java new file mode 100644 index 00000000000..3d02064d2ad --- /dev/null +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/ExpireFreezeV2BalanceProcessor.java @@ -0,0 +1,55 @@ +package org.tron.core.vm.nativecontract; + +import lombok.extern.slf4j.Slf4j; +import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.vm.nativecontract.param.ExpireFreezeV2BalanceParam; +import org.tron.core.vm.repository.Repository; +import org.tron.protos.Protocol; +import org.tron.protos.contract.Common; + +import java.util.List; +import java.util.stream.Collectors; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; + +@Slf4j(topic = "VMProcessor") +public class ExpireFreezeV2BalanceProcessor { + + public void validate(ExpireFreezeV2BalanceParam param, Repository repo) throws ContractValidateException { + if (repo == null) { + throw new ContractValidateException(STORE_NOT_EXIST); + } + + byte[] ownerAddress = param.getOwnerAddress(); + AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + if (ownerCapsule == null) { + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + throw new ContractValidateException( + ACCOUNT_EXCEPTION_STR + readableOwnerAddress + "] does not exist"); + } + } + + public long execute(ExpireFreezeV2BalanceParam param, Repository repo) { + byte[] ownerAddress = param.getOwnerAddress(); + AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); + Common.ResourceCode resourceType = param.getResourceType(); + + DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + List unfrozenV2List = ownerCapsule.getInstance().getUnfrozenV2List(); + List expireFreezeV2List = unfrozenV2List.stream() + .filter(unFreezeV2 -> unFreezeV2.getType().equals(resourceType)) + .filter(unFreezeV2 -> unFreezeV2.getUnfreezeAmount() > 0) + .filter(unFreezeV2 -> unFreezeV2.getUnfreezeExpireTime() <= now) + .collect(Collectors.toList()); + return expireFreezeV2List.stream().mapToLong(Protocol.Account.UnFreezeV2::getUnfreezeAmount).sum(); + } +} diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java new file mode 100644 index 00000000000..07590a1524b --- /dev/null +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java @@ -0,0 +1,102 @@ +package org.tron.core.vm.nativecontract; + +import lombok.extern.slf4j.Slf4j; +import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.vm.nativecontract.param.FreezeBalanceV2Param; +import org.tron.core.vm.repository.Repository; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +@Slf4j(topic = "VMProcessor") +public class FreezeBalanceV2Processor { + + public void validate(FreezeBalanceV2Param param, Repository repo) throws ContractValidateException { + if (repo == null) { + throw new ContractValidateException(STORE_NOT_EXIST); + } + + byte[] ownerAddress = param.getOwnerAddress(); + AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); + if (repo.getDynamicPropertiesStore().getUnfreezeDelayDays() == 0) { + throw new ContractValidateException("Not support FreezeV2 transaction," + + " need to be opened by the committee"); + } + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + if (ownerCapsule == null) { + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + throw new ContractValidateException( + ACCOUNT_EXCEPTION_STR + readableOwnerAddress + "] does not exist"); + } + long frozenBalance = param.getFrozenBalance(); + if (frozenBalance <= 0) { + throw new ContractValidateException("FrozenBalance must be positive"); + } else if (frozenBalance < TRX_PRECISION) { + throw new ContractValidateException("FrozenBalance must be more than 1TRX"); + } else if (frozenBalance > ownerCapsule.getBalance()) { + throw new ContractValidateException("FrozenBalance must be less than accountBalance"); + } + + // validate frozen count of owner account + int frozenCount = ownerCapsule.getFrozenCount(); + if (frozenCount != 0 && frozenCount != 1) { + throw new ContractValidateException("FrozenCount must be 0 or 1"); + } + + // validate arg @resourceType + switch (param.getResourceType()) { + case BANDWIDTH: + case ENERGY: + break; + case TRON_POWER: + if (!repo.getDynamicPropertiesStore().supportAllowNewResourceModel()) { + throw new ContractValidateException( + "ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]"); + } + break; + default: + throw new ContractValidateException( + "ResourceCode error,valid ResourceCode[BANDWIDTH、ENERGY]"); + } + } + + public void execute(FreezeBalanceV2Param param, Repository repo) { + DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); + + byte[] ownerAddress = param.getOwnerAddress(); + long frozenBalance = param.getFrozenBalance(); + AccountCapsule accountCapsule = repo.getAccount(ownerAddress); + if (dynamicStore.supportAllowNewResourceModel() + && accountCapsule.oldTronPowerIsNotInitialized()) { + accountCapsule.initializeOldTronPower(); + } + switch (param.getResourceType()) { + case BANDWIDTH: + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + dynamicStore.addTotalNetWeight(frozenBalance / TRX_PRECISION); + break; + case ENERGY: + accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); + dynamicStore.addTotalEnergyWeight(frozenBalance / TRX_PRECISION); + break; + case TRON_POWER: + accountCapsule.addFrozenForTronPowerV2(frozenBalance); + dynamicStore.addTotalTronPowerWeight(frozenBalance / TRX_PRECISION); + break; + default: + logger.debug("Resource Code Error."); + } + + // deduce balance of owner account + long newBalance = accountCapsule.getBalance() - frozenBalance; + accountCapsule.setBalance(newBalance); + repo.updateAccount(accountCapsule.createDbKey(), accountCapsule); + } +} diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java new file mode 100644 index 00000000000..b1be81af520 --- /dev/null +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -0,0 +1,198 @@ +package org.tron.core.vm.nativecontract; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; +import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.ChainBaseManager; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceCapsule; +import org.tron.core.db.BandwidthProcessor; +import org.tron.core.db.EnergyProcessor; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.vm.nativecontract.param.UnDelegateResourceParam; +import org.tron.core.vm.repository.Repository; + +import java.util.Arrays; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +@Slf4j(topic = "VMProcessor") +public class UnDelegateResourceProcessor { + + public void validate(UnDelegateResourceParam param, Repository repo) throws ContractValidateException { + if (repo == null) { + throw new ContractValidateException(STORE_NOT_EXIST); + } + + byte[] ownerAddress = param.getOwnerAddress(); + AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); + DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); + if (!dynamicStore.supportDR()) { + throw new ContractValidateException("No support for resource delegate"); + } + if (dynamicStore.getUnfreezeDelayDays() == 0) { + throw new ContractValidateException("Not support Delegate resource transaction," + + " need to be opened by the committee"); + } + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + if (ownerCapsule == null) { + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + throw new ContractValidateException( + ACCOUNT_EXCEPTION_STR + readableOwnerAddress + "] does not exist"); + } + + byte[] receiverAddress = param.getReceiverAddress(); + if (ArrayUtils.isEmpty(receiverAddress) || !DecodeUtil.addressValid(receiverAddress)) { + throw new ContractValidateException("Invalid receiverAddress"); + } + if (Arrays.equals(receiverAddress, ownerAddress)) { + throw new ContractValidateException( + "receiverAddress must not be the same as ownerAddress"); + } + AccountCapsule receiverCapsule = repo.getAccount(receiverAddress); + if (receiverCapsule == null) { + String readableReceiverAddress = StringUtil.createReadableString(receiverAddress); + throw new ContractValidateException( + "Receiver Account[" + readableReceiverAddress + "] does not exist"); + } + + byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress); + DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); + if (delegatedResourceCapsule == null) { + throw new ContractValidateException( + "delegated Resource does not exist"); + } + + long unDelegateBalance = param.getUnDelegateBalance(); + if (unDelegateBalance < TRX_PRECISION) { + throw new ContractValidateException("unDelegateBalance must be more than 1TRX"); + } + switch (param.getResourceType()) { + case BANDWIDTH: + if (delegatedResourceCapsule.getFrozenBalanceForBandwidth() < unDelegateBalance) { + throw new ContractValidateException("insufficient delegatedFrozenBalance(BANDWIDTH), request=" + + unDelegateBalance + ", balance=" + delegatedResourceCapsule.getFrozenBalanceForBandwidth()); + } + break; + case ENERGY: + if (delegatedResourceCapsule.getFrozenBalanceForEnergy() < unDelegateBalance) { + throw new ContractValidateException("insufficient delegateFrozenBalance(Energy), request=" + + unDelegateBalance + ", balance=" + delegatedResourceCapsule.getFrozenBalanceForEnergy()); + } + break; + default: + throw new ContractValidateException( + "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + } + } + + public void execute(UnDelegateResourceParam param, Repository repo) { + byte[] ownerAddress = param.getOwnerAddress(); + AccountCapsule ownerCapsule = repo.getAccount(param.getOwnerAddress()); + DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); + long unDelegateBalance = param.getUnDelegateBalance(); + byte[] receiverAddress = param.getReceiverAddress(); + AccountCapsule receiverCapsule = repo.getAccount(receiverAddress); + + long transferUsage = 0; + // modify receiver Account + if (receiverCapsule != null) { + switch (param.getResourceType()) { + case BANDWIDTH: + BandwidthProcessor bandwidthProcessor = new BandwidthProcessor(ChainBaseManager.getInstance()); + // todo update usage time? + bandwidthProcessor.updateUsage(receiverCapsule); + + if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() + < unDelegateBalance) { + // A TVM contract suicide, re-create will produce this situation + receiverCapsule.setAcquiredDelegatedFrozenBalanceForBandwidth(0); + } else { + // calculate usage + long unDelegateMaxUsage = (long) (unDelegateBalance / TRX_PRECISION + * ((double) (dynamicStore.getTotalNetLimit()) / dynamicStore.getTotalNetWeight())); + transferUsage = (long) (receiverCapsule.getNetUsage() + * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForBandwidth())); + transferUsage = Math.min(unDelegateMaxUsage, transferUsage); + + receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(-unDelegateBalance); + } + + long newNetUsage = receiverCapsule.getNetUsage() - transferUsage; + receiverCapsule.setNetUsage(newNetUsage); + break; + case ENERGY: + EnergyProcessor energyProcessor = + new EnergyProcessor(dynamicStore, ChainBaseManager.getInstance().getAccountStore()); + energyProcessor.updateUsage(receiverCapsule); + + if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() + < unDelegateBalance) { + // A TVM contract receiver, re-create will produce this situation + receiverCapsule.setAcquiredDelegatedFrozenBalanceForEnergy(0); + } else { + // calculate usage + long unDelegateMaxUsage = (long) (unDelegateBalance / TRX_PRECISION + * ((double) (dynamicStore.getTotalEnergyCurrentLimit()) / dynamicStore.getTotalEnergyWeight())); + transferUsage = (long) (receiverCapsule.getEnergyUsage() + * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForEnergy())); + transferUsage = Math.min(unDelegateMaxUsage, transferUsage); + + receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(-unDelegateBalance); + } + + long newEnergyUsage = receiverCapsule.getEnergyUsage() - transferUsage; + receiverCapsule.setEnergyUsage(newEnergyUsage); + break; + default: + //this should never happen + break; + } + repo.updateAccount(receiverCapsule.createDbKey(), receiverCapsule); + } + + // modify owner Account + byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress); + DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); + switch (param.getResourceType()) { + case BANDWIDTH: { + delegatedResourceCapsule.addFrozenBalanceForBandwidth(-unDelegateBalance, 0); + + ownerCapsule.addDelegatedFrozenBalanceForBandwidth(-unDelegateBalance); + ownerCapsule.addFrozenBalanceForBandwidthV2(unDelegateBalance); + + BandwidthProcessor processor = new BandwidthProcessor(ChainBaseManager.getInstance()); + processor.updateUsage(ownerCapsule); + long newNetUsage = ownerCapsule.getNetUsage() + transferUsage; + ownerCapsule.setNetUsage(newNetUsage); + ownerCapsule.setLatestConsumeTime(ChainBaseManager.getInstance().getHeadSlot()); + } + break; + case ENERGY: { + delegatedResourceCapsule.addFrozenBalanceForEnergy(-unDelegateBalance, 0); + + ownerCapsule.addDelegatedFrozenBalanceForEnergy(-unDelegateBalance); + ownerCapsule.addFrozenBalanceForEnergyV2(unDelegateBalance); + + EnergyProcessor processor = + new EnergyProcessor(dynamicStore, ChainBaseManager.getInstance().getAccountStore()); + processor.updateUsage(ownerCapsule); + long newEnergyUsage = ownerCapsule.getEnergyUsage() + transferUsage; + ownerCapsule.setEnergyUsage(newEnergyUsage); + ownerCapsule.setLatestConsumeTimeForEnergy(ChainBaseManager.getInstance().getHeadSlot()); + } + break; + default: + //this should never happen + break; + } + repo.updateDelegatedResource(key, delegatedResourceCapsule); + repo.updateAccount(ownerCapsule.createDbKey(), ownerCapsule); + } +} diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java new file mode 100644 index 00000000000..ed2b4561a67 --- /dev/null +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -0,0 +1,248 @@ +package org.tron.core.vm.nativecontract; + +import com.google.common.collect.Lists; +import com.google.protobuf.ByteString; +import lombok.extern.slf4j.Slf4j; +import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.VotesCapsule; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.vm.nativecontract.param.UnfreezeBalanceV2Param; +import org.tron.core.vm.repository.Repository; +import org.tron.protos.Protocol; +import org.tron.protos.contract.Common; + +import java.util.Iterator; +import java.util.List; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +@Slf4j(topic = "VMProcessor") +public class UnfreezeBalanceV2Processor { + + private static final int UNFREEZE_MAX_TIMES = 16; + + public void validate(UnfreezeBalanceV2Param param, Repository repo) + throws ContractValidateException { + if (repo == null) { + throw new ContractValidateException(STORE_NOT_EXIST); + } + + byte[] ownerAddress = param.getOwnerAddress(); + AccountCapsule accountCapsule = repo.getAccount(ownerAddress); + DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); + if (dynamicStore.getUnfreezeDelayDays() == 0) { + throw new ContractValidateException("Not support UnfreezeV2 transaction," + + " need to be opened by the committee"); + } + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + if (accountCapsule == null) { + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + throw new ContractValidateException( + ACCOUNT_EXCEPTION_STR + readableOwnerAddress + "] does not exist"); + } + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + int unfreezingCount = accountCapsule.getUnfreezingV2Count(now); + if (UNFREEZE_MAX_TIMES <= unfreezingCount) { + throw new ContractValidateException("Invalid unfreeze operation, unfreezing times is over limit"); + } + switch (param.getResourceType()) { + case BANDWIDTH: + // validate frozen balance + if (!this.checkExistFrozenBalance(accountCapsule, Common.ResourceCode.BANDWIDTH)) { + throw new ContractValidateException("no frozenBalance(BANDWIDTH)"); + } + // check if it is time to unfreeze + long allowedUnfreezeCount = accountCapsule.getFrozenList().stream() + .filter(frozen -> frozen.getExpireTime() <= now).count(); + if (allowedUnfreezeCount <= 0) { + throw new ContractValidateException("It's not time to unfreeze(BANDWIDTH)."); + } + break; + case ENERGY: + Protocol.Account.Frozen frozenForEnergy = accountCapsule.getAccountResource() + .getFrozenBalanceForEnergy(); + // validate frozen balance + if (!this.checkExistFrozenBalance(accountCapsule, Common.ResourceCode.ENERGY)) { + throw new ContractValidateException("no frozenBalance(Energy)"); + } + // check if it is time to unfreeze + if (frozenForEnergy.getExpireTime() > now) { + throw new ContractValidateException("It's not time to unfreeze(Energy)."); + } + break; + case TRON_POWER: + if (dynamicStore.supportAllowNewResourceModel()) { + if (!this.checkExistFrozenBalance(accountCapsule, Common.ResourceCode.TRON_POWER)) { + throw new ContractValidateException("no frozenBalance(TronPower)"); + } + } else { + throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + } + break; + default: + throw new ContractValidateException("ResourceCode error." + + "valid ResourceCode[BANDWIDTH、Energy]"); + } + + if (!checkUnfreezeBalance(accountCapsule, param.getUnfreezeBalance(), param.getResourceType())) { + throw new ContractValidateException( + "Invalid unfreeze_balance, freezing resource[" + param.getResourceType() + "] is not enough" + ); + } + } + + private boolean checkUnfreezeBalance( + AccountCapsule accountCapsule, long unfreezeBalance, Common.ResourceCode freezeType) { + long frozenBalance = 0L; + List freezeV2List = accountCapsule.getFrozenV2List(); + for (Protocol.Account.FreezeV2 freezeV2 : freezeV2List) { + if (freezeV2.getType().equals(freezeType)) { + frozenBalance = freezeV2.getAmount(); + break; + } + } + + return unfreezeBalance <= frozenBalance; + } + + public boolean checkExistFrozenBalance(AccountCapsule accountCapsule, Common.ResourceCode freezeType) { + boolean checkOk = false; + long frozenBalance; + List frozenV2List = accountCapsule.getFrozenV2List(); + for (Protocol.Account.FreezeV2 frozenV2 : frozenV2List) { + if (frozenV2.getType().equals(freezeType)) { + frozenBalance = frozenV2.getAmount(); + if (frozenBalance > 0) { + checkOk = true; + break; + } + } + } + return checkOk; + } + + public void execute(UnfreezeBalanceV2Param param, Repository repo) { + byte[] ownerAddress = param.getOwnerAddress(); + long unfreezeBalance = param.getUnfreezeBalance(); + + AccountCapsule accountCapsule = repo.getAccount(ownerAddress); + long now = repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); + + this.unfreezeExpire(accountCapsule, now); + + this.updateAccountFrozenInfo(param.getResourceType(), accountCapsule, unfreezeBalance); + + long expireTime = this.calcUnfreezeExpireTime(now, repo); + accountCapsule.addUnfrozenV2List(param.getResourceType(), unfreezeBalance, expireTime); + + this.updateTotalResourceWeight(param.getResourceType(), unfreezeBalance, repo); + this.clearVotes(accountCapsule, param.getResourceType(), ownerAddress, repo); + + if (repo.getDynamicPropertiesStore().supportAllowNewResourceModel() + && !accountCapsule.oldTronPowerIsInvalid()) { + accountCapsule.invalidateOldTronPower(); + } + + repo.updateAccount(accountCapsule.createDbKey(), accountCapsule); + } + + private void unfreezeExpire(AccountCapsule accountCapsule, long now) { + long unfreezeBalance = 0L; + + List unFrozenV2List = Lists.newArrayList(); + unFrozenV2List.addAll(accountCapsule.getUnfrozenV2List()); + Iterator iterator = unFrozenV2List.iterator(); + + while (iterator.hasNext()) { + Protocol.Account.UnFreezeV2 next = iterator.next(); + if (next.getUnfreezeExpireTime() <= now) { + unfreezeBalance += next.getUnfreezeAmount(); + iterator.remove(); + } + } + + accountCapsule.setInstance( + accountCapsule.getInstance().toBuilder() + .setBalance(accountCapsule.getBalance() + unfreezeBalance) + .clearUnfrozenV2() + .addAllUnfrozenV2(unFrozenV2List).build() + ); + } + + private void updateAccountFrozenInfo( + Common.ResourceCode freezeType, AccountCapsule accountCapsule, long unfreezeBalance) { + List freezeV2List = accountCapsule.getFrozenV2List(); + for (int i = 0; i < freezeV2List.size(); i++) { + if (freezeV2List.get(i).getType().equals(freezeType)) { + Protocol.Account.FreezeV2 freezeV2 = Protocol.Account.FreezeV2.newBuilder() + .setAmount(freezeV2List.get(i).getAmount() - unfreezeBalance) + .setType(freezeV2List.get(i).getType()) + .build(); + accountCapsule.updateFrozenV2List(i, freezeV2); + break; + } + } + } + + private long calcUnfreezeExpireTime(long now, Repository repo) { + long unfreezeDelayDays = repo.getDynamicPropertiesStore().getUnfreezeDelayDays(); + + return now + unfreezeDelayDays * FROZEN_PERIOD; + } + + public void updateTotalResourceWeight(Common.ResourceCode freezeType, + long unfreezeBalance, + Repository repo) { + DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); + switch (freezeType) { + case BANDWIDTH: + dynamicStore.addTotalNetWeight(-unfreezeBalance / TRX_PRECISION); + break; + case ENERGY: + dynamicStore.addTotalEnergyWeight(-unfreezeBalance / TRX_PRECISION); + break; + case TRON_POWER: + dynamicStore.addTotalTronPowerWeight(-unfreezeBalance / TRX_PRECISION); + break; + default: + //this should never happen + break; + } + } + + private void clearVotes( + AccountCapsule accountCapsule, Common.ResourceCode freezeType, byte[] ownerAddress, Repository repo) { + + boolean needToClearVote = true; + if (repo.getDynamicPropertiesStore().supportAllowNewResourceModel() + && accountCapsule.oldTronPowerIsInvalid()) { + switch (freezeType) { + case BANDWIDTH: + case ENERGY: + needToClearVote = false; + break; + default: + break; + } + } + + if (needToClearVote) { + VotesCapsule votesCapsule = repo.getVotes(ownerAddress); + if (votesCapsule == null) { + votesCapsule = new VotesCapsule(ByteString.copyFrom(ownerAddress), + accountCapsule.getVotesList()); + } + accountCapsule.clearVotes(); + votesCapsule.clearNewVotes(); + repo.updateVotes(ownerAddress, votesCapsule); + } + } +} diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java new file mode 100644 index 00000000000..20bc1bd6b6d --- /dev/null +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java @@ -0,0 +1,95 @@ +package org.tron.core.vm.nativecontract; + +import com.google.common.math.LongMath; +import lombok.extern.slf4j.Slf4j; +import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.vm.nativecontract.param.WithdrawExpireUnfreezeParam; +import org.tron.core.vm.repository.Repository; +import org.tron.protos.Protocol; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; + +@Slf4j(topic = "VMProcessor") +public class WithdrawExpireUnfreezeProcessor { + + public void validate(WithdrawExpireUnfreezeParam param, Repository repo) throws ContractValidateException { + if (repo == null) { + throw new ContractValidateException(STORE_NOT_EXIST); + } + + byte[] ownerAddress = param.getOwnerAddress(); + AccountCapsule accountCapsule = repo.getAccount(ownerAddress); + DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); + if (dynamicStore.getUnfreezeDelayDays() == 0) { + throw new ContractValidateException("Not support WithdrawExpireUnfreeze transaction," + + " need to be opened by the committee"); + } + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + if (Objects.isNull(accountCapsule)) { + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + throw new ContractValidateException(ACCOUNT_EXCEPTION_STR + + readableOwnerAddress + NOT_EXIST_STR); + } + + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); + long totalWithdrawUnfreeze = getTotalWithdrawUnfreeze(unfrozenV2List, now); + if (totalWithdrawUnfreeze <= 0) { + throw new ContractValidateException("no unFreeze balance to withdraw "); + } + try { + LongMath.checkedAdd(accountCapsule.getBalance(), totalWithdrawUnfreeze); + } catch (ArithmeticException e) { + logger.debug(e.getMessage(), e); + throw new ContractValidateException(e.getMessage()); + } + } + + private long getTotalWithdrawUnfreeze(List unfrozenV2List, long now) { + return getTotalWithdrawList(unfrozenV2List, now).stream() + .mapToLong(Protocol.Account.UnFreezeV2::getUnfreezeAmount).sum(); + } + + private List getTotalWithdrawList(List unfrozenV2List, long now) { + return unfrozenV2List.stream().filter(unfrozenV2 -> (unfrozenV2.getUnfreezeAmount() > 0 + && unfrozenV2.getUnfreezeExpireTime() <= now)).collect(Collectors.toList()); + } + + public long execute(WithdrawExpireUnfreezeParam param, Repository repo) throws ContractExeException { + byte[] ownerAddress = param.getOwnerAddress(); + DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); + + AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + List unfrozenV2List = ownerCapsule.getInstance().getUnfrozenV2List(); + long totalWithdrawUnfreeze = getTotalWithdrawUnfreeze(unfrozenV2List, now); + ownerCapsule.setInstance(ownerCapsule.getInstance().toBuilder() + .setBalance(ownerCapsule.getBalance() + totalWithdrawUnfreeze) + .setLatestWithdrawTime(now) + .build()); + List newUnFreezeList = getRemainWithdrawList(unfrozenV2List, now); + ownerCapsule.clearUnfrozenV2(); + newUnFreezeList.forEach(ownerCapsule::addUnfrozenV2); + repo.updateAccount(ownerCapsule.createDbKey(), ownerCapsule); + return totalWithdrawUnfreeze; + } + + private List getRemainWithdrawList(List unfrozenV2List, long now) { + return unfrozenV2List.stream() + .filter(unfrozenV2 -> unfrozenV2.getUnfreezeExpireTime() > now) + .collect(Collectors.toList()); + } +} diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/DelegateResourceParam.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/DelegateResourceParam.java new file mode 100644 index 00000000000..f7d897800b5 --- /dev/null +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/DelegateResourceParam.java @@ -0,0 +1,46 @@ +package org.tron.core.vm.nativecontract.param; + +import org.tron.protos.contract.Common; + +public class DelegateResourceParam { + + private byte[] ownerAddress; + + private byte[] receiverAddress; + + private long delegateBalance; + + private Common.ResourceCode resourceType; + + public byte[] getOwnerAddress() { + return ownerAddress; + } + + public void setOwnerAddress(byte[] ownerAddress) { + this.ownerAddress = ownerAddress; + } + + public byte[] getReceiverAddress() { + return receiverAddress; + } + + public void setReceiverAddress(byte[] receiverAddress) { + this.receiverAddress = receiverAddress; + } + + public long getDelegateBalance() { + return delegateBalance; + } + + public void setDelegateBalance(long delegateBalance) { + this.delegateBalance = delegateBalance; + } + + public Common.ResourceCode getResourceType() { + return resourceType; + } + + public void setResourceType(Common.ResourceCode resourceType) { + this.resourceType = resourceType; + } +} diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/ExpireFreezeV2BalanceParam.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/ExpireFreezeV2BalanceParam.java new file mode 100644 index 00000000000..e49f27b7556 --- /dev/null +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/ExpireFreezeV2BalanceParam.java @@ -0,0 +1,26 @@ +package org.tron.core.vm.nativecontract.param; + +import org.tron.protos.contract.Common; + +public class ExpireFreezeV2BalanceParam { + + private byte[] ownerAddress; + + private Common.ResourceCode resourceType; + + public byte[] getOwnerAddress() { + return ownerAddress; + } + + public void setOwnerAddress(byte[] ownerAddress) { + this.ownerAddress = ownerAddress; + } + + public Common.ResourceCode getResourceType() { + return resourceType; + } + + public void setResourceType(Common.ResourceCode resourceType) { + this.resourceType = resourceType; + } +} diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/FreezeBalanceV2Param.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/FreezeBalanceV2Param.java new file mode 100644 index 00000000000..b6f2c7c4aeb --- /dev/null +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/FreezeBalanceV2Param.java @@ -0,0 +1,46 @@ +package org.tron.core.vm.nativecontract.param; + +import org.tron.protos.contract.Common; + +public class FreezeBalanceV2Param { + + private byte[] ownerAddress; + + private long frozenBalance; + + private long frozenDuration; + + private Common.ResourceCode resourceType; + + public byte[] getOwnerAddress() { + return ownerAddress; + } + + public void setOwnerAddress(byte[] ownerAddress) { + this.ownerAddress = ownerAddress; + } + + public long getFrozenBalance() { + return frozenBalance; + } + + public void setFrozenBalance(long frozenBalance) { + this.frozenBalance = frozenBalance; + } + + public long getFrozenDuration() { + return frozenDuration; + } + + public void setFrozenDuration(long frozenDuration) { + this.frozenDuration = frozenDuration; + } + + public Common.ResourceCode getResourceType() { + return resourceType; + } + + public void setResourceType(Common.ResourceCode resourceType) { + this.resourceType = resourceType; + } +} diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/UnDelegateResourceParam.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/UnDelegateResourceParam.java new file mode 100644 index 00000000000..7a1c76b3c32 --- /dev/null +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/UnDelegateResourceParam.java @@ -0,0 +1,46 @@ +package org.tron.core.vm.nativecontract.param; + +import org.tron.protos.contract.Common; + +public class UnDelegateResourceParam { + + private byte[] ownerAddress; + + private byte[] receiverAddress; + + private long unDelegateBalance; + + private Common.ResourceCode resourceType; + + public byte[] getOwnerAddress() { + return ownerAddress; + } + + public void setOwnerAddress(byte[] ownerAddress) { + this.ownerAddress = ownerAddress; + } + + public byte[] getReceiverAddress() { + return receiverAddress; + } + + public void setReceiverAddress(byte[] receiverAddress) { + this.receiverAddress = receiverAddress; + } + + public long getUnDelegateBalance() { + return unDelegateBalance; + } + + public void setUnDelegateBalance(long unDelegateBalance) { + this.unDelegateBalance = unDelegateBalance; + } + + public Common.ResourceCode getResourceType() { + return resourceType; + } + + public void setResourceType(Common.ResourceCode resourceType) { + this.resourceType = resourceType; + } +} diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/UnfreezeBalanceV2Param.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/UnfreezeBalanceV2Param.java new file mode 100644 index 00000000000..81ae0f8d222 --- /dev/null +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/UnfreezeBalanceV2Param.java @@ -0,0 +1,36 @@ +package org.tron.core.vm.nativecontract.param; + +import org.tron.protos.contract.Common; + +public class UnfreezeBalanceV2Param { + + private byte[] ownerAddress; + + private long unfreezeBalance; + + private Common.ResourceCode resourceType; + + public byte[] getOwnerAddress() { + return ownerAddress; + } + + public void setOwnerAddress(byte[] ownerAddress) { + this.ownerAddress = ownerAddress; + } + + public long getUnfreezeBalance() { + return unfreezeBalance; + } + + public void setUnfreezeBalance(long unfreezeBalance) { + this.unfreezeBalance = unfreezeBalance; + } + + public Common.ResourceCode getResourceType() { + return resourceType; + } + + public void setResourceType(Common.ResourceCode resourceType) { + this.resourceType = resourceType; + } +} diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/WithdrawExpireUnfreezeParam.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/WithdrawExpireUnfreezeParam.java new file mode 100644 index 00000000000..6fe371be510 --- /dev/null +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/WithdrawExpireUnfreezeParam.java @@ -0,0 +1,26 @@ +package org.tron.core.vm.nativecontract.param; + +public class WithdrawExpireUnfreezeParam { + + // Account address which want to withdraw its reward + private byte[] ownerAddress; + + // Latest block timestamp + private long nowInMs; + + public byte[] getOwnerAddress() { + return ownerAddress; + } + + public void setOwnerAddress(byte[] ownerAddress) { + this.ownerAddress = ownerAddress; + } + + public long getNowInMs() { + return nowInMs; + } + + public void setNowInMs(long nowInMs) { + this.nowInMs = nowInMs; + } +} diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index cfb42fcde6a..946b7547483 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -50,13 +50,25 @@ import org.tron.core.vm.VMConstant; import org.tron.core.vm.VMUtils; import org.tron.core.vm.config.VMConfig; +import org.tron.core.vm.nativecontract.DelegateResourceProcessor; +import org.tron.core.vm.nativecontract.ExpireFreezeV2BalanceProcessor; import org.tron.core.vm.nativecontract.FreezeBalanceProcessor; +import org.tron.core.vm.nativecontract.FreezeBalanceV2Processor; +import org.tron.core.vm.nativecontract.UnDelegateResourceProcessor; import org.tron.core.vm.nativecontract.UnfreezeBalanceProcessor; +import org.tron.core.vm.nativecontract.UnfreezeBalanceV2Processor; import org.tron.core.vm.nativecontract.VoteWitnessProcessor; +import org.tron.core.vm.nativecontract.WithdrawExpireUnfreezeProcessor; import org.tron.core.vm.nativecontract.WithdrawRewardProcessor; +import org.tron.core.vm.nativecontract.param.DelegateResourceParam; +import org.tron.core.vm.nativecontract.param.ExpireFreezeV2BalanceParam; import org.tron.core.vm.nativecontract.param.FreezeBalanceParam; +import org.tron.core.vm.nativecontract.param.FreezeBalanceV2Param; +import org.tron.core.vm.nativecontract.param.UnDelegateResourceParam; import org.tron.core.vm.nativecontract.param.UnfreezeBalanceParam; +import org.tron.core.vm.nativecontract.param.UnfreezeBalanceV2Param; import org.tron.core.vm.nativecontract.param.VoteWitnessParam; +import org.tron.core.vm.nativecontract.param.WithdrawExpireUnfreezeParam; import org.tron.core.vm.nativecontract.param.WithdrawRewardParam; import org.tron.core.vm.program.invoke.ProgramInvoke; import org.tron.core.vm.program.invoke.ProgramInvokeFactory; @@ -1734,6 +1746,180 @@ public long freezeExpireTime(DataWord targetAddress, DataWord resourceType) { return 0; } + public boolean freezeBalanceV2(DataWord frozenBalance, DataWord resourceType) { + Repository repository = getContractState().newRepositoryChild(); + byte[] owner = getContextAddress(); + + increaseNonce(); + InternalTransaction internalTx = addInternalTx(null, owner, owner, + frozenBalance.longValue(), null, + "freezeBalanceV2For" + convertResourceToString(resourceType), nonce, null); + + FreezeBalanceV2Param param = new FreezeBalanceV2Param(); + param.setOwnerAddress(owner); + boolean needCheckFrozenTime = CommonParameter.getInstance() + .getCheckFrozenTime() == 1; // for test + param.setFrozenDuration(needCheckFrozenTime + ? repository.getDynamicPropertiesStore().getMinFrozenTime() : 0); + param.setResourceType(parseResourceCode(resourceType)); + try { + FreezeBalanceV2Processor processor = new FreezeBalanceV2Processor(); + param.setFrozenBalance(frozenBalance.sValue().longValueExact()); + processor.validate(param, repository); + processor.execute(param, repository); + repository.commit(); + return true; + } catch (ContractValidateException e) { + logger.error("TVM FreezeBalanceV2: validate failure. Reason: {}", e.getMessage()); + } catch (ArithmeticException e) { + logger.error("TVM FreezeBalanceV2: frozenBalance out of long range."); + } + if (internalTx != null) { + internalTx.reject(); + } + return false; + } + + public boolean unfreezeBalanceV2(DataWord unfreezeBalance, DataWord resourceType) { + Repository repository = getContractState().newRepositoryChild(); + byte[] owner = getContextAddress(); + + increaseNonce(); + InternalTransaction internalTx = addInternalTx(null, owner, owner, + unfreezeBalance.longValue(), null, + "unfreezeBalanceV2For" + convertResourceToString(resourceType), nonce, null); + + UnfreezeBalanceV2Param param = new UnfreezeBalanceV2Param(); + param.setOwnerAddress(owner); + param.setUnfreezeBalance(unfreezeBalance.sValue().longValueExact()); + param.setResourceType(parseResourceCode(resourceType)); + try { + UnfreezeBalanceV2Processor processor = new UnfreezeBalanceV2Processor(); + processor.validate(param, repository); + processor.execute(param, repository); + repository.commit(); + return true; + } catch (ContractValidateException e) { + logger.error("TVM UnfreezeBalanceV2: validate failure. Reason: {}", e.getMessage()); + } + if (internalTx != null) { + internalTx.reject(); + } + return false; + } + + public long withdrawExpireUnfreeze() { + Repository repository = getContractState().newRepositoryChild(); + byte[] owner = getContextAddress(); + + increaseNonce(); + InternalTransaction internalTx = addInternalTx(null, owner, owner, 0, null, + "withdrawExpireUnfreeze", nonce, null); + + WithdrawExpireUnfreezeParam param = new WithdrawExpireUnfreezeParam(); + param.setOwnerAddress(owner); + param.setNowInMs(getTimestamp().longValue() * 1000); + try { + WithdrawExpireUnfreezeProcessor processor = new WithdrawExpireUnfreezeProcessor(); + processor.validate(param, repository); + long expireUnfreezeBalance = processor.execute(param, repository); + repository.commit(); + if (internalTx != null) { + internalTx.setValue(expireUnfreezeBalance); + } + return expireUnfreezeBalance; + } catch (ContractValidateException e) { + logger.error("TVM WithdrawExpireUnfreeze: validate failure. Reason: {}", e.getMessage()); + } catch (ContractExeException e) { + logger.error("TVM WithdrawExpireUnfreeze: execute failure. Reason: {}", e.getMessage()); + } + if (internalTx != null) { + internalTx.reject(); + } + return 0; + } + + public long expireFreezeV2Balance(DataWord ownerAddress, DataWord resourceType) { + Repository repository = getContractState().newRepositoryChild(); + ExpireFreezeV2BalanceParam param = new ExpireFreezeV2BalanceParam(); + param.setOwnerAddress(ownerAddress.toTronAddress()); + param.setResourceType(parseResourceCode(resourceType)); + try { + ExpireFreezeV2BalanceProcessor processor = new ExpireFreezeV2BalanceProcessor(); + processor.validate(param, repository); + long balance = processor.execute(param, repository); + repository.commit(); + return balance; + } catch (ContractValidateException e) { + logger.error("TVM expireFreezeV2Balance: validate failure. Reason: {}", e.getMessage()); + } + return 0; + } + + public boolean delegateResource( + DataWord receiverAddress, DataWord delegateBalance, DataWord resourceType) { + Repository repository = getContractState().newRepositoryChild(); + byte[] owner = getContextAddress(); + byte[] receiver = receiverAddress.toTronAddress(); + + increaseNonce(); + InternalTransaction internalTx = addInternalTx(null, owner, receiver, + delegateBalance.longValue(), null, + "delegateResource" + convertResourceToString(resourceType), nonce, null); + + DelegateResourceParam param = new DelegateResourceParam(); + param.setOwnerAddress(owner); + param.setReceiverAddress(receiver); + param.setDelegateBalance(delegateBalance.sValue().longValueExact()); + param.setResourceType(parseResourceCode(resourceType)); + try { + DelegateResourceProcessor processor = new DelegateResourceProcessor(); + processor.validate(param, repository); + processor.execute(param, repository); + repository.commit(); + return true; + } catch (ContractValidateException e) { + logger.error("TVM delegateResource: validate failure. Reason: {}", e.getMessage()); + } catch (ArithmeticException e) { + logger.error("TVM delegateResource: balance out of long range."); + } + if (internalTx != null) { + internalTx.reject(); + } + return false; + } + + public boolean unDelegateResource( + DataWord receiverAddress, DataWord unDelegateBalance, DataWord resourceType) { + Repository repository = getContractState().newRepositoryChild(); + byte[] owner = getContextAddress(); + byte[] receiver = receiverAddress.toTronAddress(); + + increaseNonce(); + InternalTransaction internalTx = addInternalTx(null, owner, receiver, + unDelegateBalance.longValue(), null, + "unDelegateResource" + convertResourceToString(resourceType), nonce, null); + + UnDelegateResourceParam param = new UnDelegateResourceParam(); + param.setOwnerAddress(owner); + param.setReceiverAddress(receiver); + param.setUnDelegateBalance(unDelegateBalance.sValue().longValueExact()); + param.setResourceType(parseResourceCode(resourceType)); + try { + UnDelegateResourceProcessor processor = new UnDelegateResourceProcessor(); + processor.validate(param, repository); + processor.execute(param, repository); + repository.commit(); + return true; + } catch (ContractValidateException e) { + logger.error("TVM UnfreezeBalanceV2: validate failure. Reason: {}", e.getMessage()); + } + if (internalTx != null) { + internalTx.reject(); + } + return false; + } + private Common.ResourceCode parseResourceCode(DataWord resourceType) { switch (resourceType.intValue()) { case 0: @@ -1757,7 +1943,7 @@ private String convertResourceToString(DataWord resourceType) { } public boolean voteWitness(int witnessArrayOffset, int witnessArrayLength, - int amountArrayOffset, int amountArrayLength) { + int amountArrayOffset, int amountArrayLength) { Repository repository = getContractState().newRepositoryChild(); byte[] owner = getContextAddress(); From 3fd948bdb2d8dcdd8d43c3d982be69c9097333ff Mon Sep 17 00:00:00 2001 From: Liulei Date: Fri, 14 Oct 2022 11:04:25 +0800 Subject: [PATCH 0286/1197] feat(freezeV2): format --- .../nativecontract/DelegateResourceProcessor.java | 11 +++++------ .../ExpireFreezeV2BalanceProcessor.java | 12 ++++++------ .../nativecontract/FreezeBalanceV2Processor.java | 8 ++++---- .../UnDelegateResourceProcessor.java | 11 +++++------ .../UnfreezeBalanceV2Processor.java | 15 +++++++-------- .../WithdrawExpireUnfreezeProcessor.java | 15 +++++++-------- .../java/org/tron/core/vm/program/Program.java | 2 +- 7 files changed, 35 insertions(+), 39 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index 5ccbfd99b01..1eef0d0ebd6 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -1,6 +1,11 @@ package org.tron.core.vm.nativecontract; +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + import com.google.protobuf.ByteString; +import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.tron.common.utils.DecodeUtil; @@ -17,12 +22,6 @@ import org.tron.core.vm.repository.Repository; import org.tron.protos.Protocol; -import java.util.Arrays; - -import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; -import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; - @Slf4j(topic = "VMProcessor") public class DelegateResourceProcessor { diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/ExpireFreezeV2BalanceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/ExpireFreezeV2BalanceProcessor.java index 3d02064d2ad..a406874f924 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/ExpireFreezeV2BalanceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/ExpireFreezeV2BalanceProcessor.java @@ -1,5 +1,11 @@ package org.tron.core.vm.nativecontract; +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; + +import java.util.List; +import java.util.stream.Collectors; + import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; @@ -11,12 +17,6 @@ import org.tron.protos.Protocol; import org.tron.protos.contract.Common; -import java.util.List; -import java.util.stream.Collectors; - -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; - @Slf4j(topic = "VMProcessor") public class ExpireFreezeV2BalanceProcessor { diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java index 07590a1524b..c0fa9ef66f2 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java @@ -1,5 +1,9 @@ package org.tron.core.vm.nativecontract; +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; @@ -9,10 +13,6 @@ import org.tron.core.vm.nativecontract.param.FreezeBalanceV2Param; import org.tron.core.vm.repository.Repository; -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; - @Slf4j(topic = "VMProcessor") public class FreezeBalanceV2Processor { diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index b1be81af520..bbf6ed95004 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -1,5 +1,10 @@ package org.tron.core.vm.nativecontract; +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.tron.common.utils.DecodeUtil; @@ -14,12 +19,6 @@ import org.tron.core.vm.nativecontract.param.UnDelegateResourceParam; import org.tron.core.vm.repository.Repository; -import java.util.Arrays; - -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; - @Slf4j(topic = "VMProcessor") public class UnDelegateResourceProcessor { diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index ed2b4561a67..070ed20436c 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -1,7 +1,14 @@ package org.tron.core.vm.nativecontract; +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + import com.google.common.collect.Lists; import com.google.protobuf.ByteString; +import java.util.Iterator; +import java.util.List; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; @@ -14,14 +21,6 @@ import org.tron.protos.Protocol; import org.tron.protos.contract.Common; -import java.util.Iterator; -import java.util.List; - -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; -import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; - @Slf4j(topic = "VMProcessor") public class UnfreezeBalanceV2Processor { diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java index 20bc1bd6b6d..578e78c13b4 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java @@ -1,6 +1,13 @@ package org.tron.core.vm.nativecontract; +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; + import com.google.common.math.LongMath; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; @@ -12,14 +19,6 @@ import org.tron.core.vm.repository.Repository; import org.tron.protos.Protocol; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; -import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; - @Slf4j(topic = "VMProcessor") public class WithdrawExpireUnfreezeProcessor { diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 946b7547483..683a29a45b6 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -1943,7 +1943,7 @@ private String convertResourceToString(DataWord resourceType) { } public boolean voteWitness(int witnessArrayOffset, int witnessArrayLength, - int amountArrayOffset, int amountArrayLength) { + int amountArrayOffset, int amountArrayLength) { Repository repository = getContractState().newRepositoryChild(); byte[] owner = getContextAddress(); From d35a569a0e2d3c5f937b820454a859dac26ee9d1 Mon Sep 17 00:00:00 2001 From: Liulei Date: Fri, 14 Oct 2022 17:41:18 +0800 Subject: [PATCH 0287/1197] fix(freezeV2): fix operation code --- actuator/src/main/java/org/tron/core/vm/Op.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/Op.java b/actuator/src/main/java/org/tron/core/vm/Op.java index 5c5b8ea21d4..d28e6704c80 100644 --- a/actuator/src/main/java/org/tron/core/vm/Op.java +++ b/actuator/src/main/java/org/tron/core/vm/Op.java @@ -236,12 +236,12 @@ public class Op { public static final int FREEZEEXPIRETIME = 0xd7; public static final int VOTEWITNESS = 0xd8; public static final int WITHDRAWREWARD = 0xd9; - public static final int FREEZEBALANCEV2 = 0xd10; - public static final int UNFREEZEBALANCEV2 = 0xd11; - public static final int EXPIREFREEZEV2BALANCE = 0xd12; - public static final int WITHDRAWEXPIREUNFREEZE = 0xd13; - public static final int DELEGATERESOURCE = 0xd14; - public static final int UNDELEGATERESOURCE = 0xd15; + public static final int FREEZEBALANCEV2 = 0xda; + public static final int UNFREEZEBALANCEV2 = 0xdb; + public static final int EXPIREFREEZEV2BALANCE = 0xdc; + public static final int WITHDRAWEXPIREUNFREEZE = 0xdd; + public static final int DELEGATERESOURCE = 0xde; + public static final int UNDELEGATERESOURCE = 0xdf; // (0xf0) Create a new account with associated code public static final int CREATE = 0xf0; From 04508e271d5bdd3daa8d532fff516d86afe6500c Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Fri, 14 Oct 2022 19:27:50 +0800 Subject: [PATCH 0288/1197] feat(freezeV2): add freezeV2 related precompiledContracts --- .../tron/core/vm/PrecompiledContracts.java | 142 ++++++++++++++++++ .../org/tron/core/vm/config/ConfigLoader.java | 1 + .../org/tron/core/vm/config/VMConfig.java | 10 ++ .../tron/core/vm/program/ContractState.java | 10 ++ .../tron/core/vm/repository/Repository.java | 4 + .../core/vm/repository/RepositoryImpl.java | 44 ++++++ .../org/tron/core/vm/utils/FreezeV2Util.java | 137 +++++++++++++++++ 7 files changed, 348 insertions(+) create mode 100644 actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 437ecdd1d8f..b4f79cef441 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -62,6 +62,7 @@ import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.program.Program; import org.tron.core.vm.repository.Repository; +import org.tron.core.vm.utils.FreezeV2Util; import org.tron.core.vm.utils.VoteRewardUtil; import org.tron.protos.Protocol; @@ -98,6 +99,12 @@ public class PrecompiledContracts { private static final EthRipemd160 ethRipemd160 = new EthRipemd160(); private static final Blake2F blake2F = new Blake2F(); + private static final GetChainParameter getChainParameter = new GetChainParameter(); + private static final ExpireFreezeV2Balance expireFreezeV2Balance = new ExpireFreezeV2Balance(); + private static final TotalFrozenBalance totalFrozenBalance = new TotalFrozenBalance(); + private static final FrozenBalance frozenBalance = new FrozenBalance(); + private static final FrozenBalanceUsage frozenBalanceUsage = new FrozenBalanceUsage(); + private static final DataWord ecRecoverAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000000000001"); private static final DataWord sha256Addr = new DataWord( @@ -138,6 +145,22 @@ public class PrecompiledContracts { "0000000000000000000000000000000000000000000000000000000001000009"); private static final DataWord totalVoteCountAddr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000a"); + + private static final DataWord getChainParameterAddr = new DataWord( + "000000000000000000000000000000000000000000000000000000000100000b"); + + private static final DataWord expireFreezeV2BalanceAddr = new DataWord( + "000000000000000000000000000000000000000000000000000000000100000c"); + + private static final DataWord totalFrozenBalanceAddr = new DataWord( + "000000000000000000000000000000000000000000000000000000000100000d"); + + private static final DataWord frozenBalanceAddr = new DataWord( + "000000000000000000000000000000000000000000000000000000000100000e"); + + private static final DataWord fronzenBalanceUsageAddr = new DataWord( + "000000000000000000000000000000000000000000000000000000000100000f"); + private static final DataWord ethRipemd160Addr = new DataWord( "0000000000000000000000000000000000000000000000000000000000020003"); private static final DataWord blake2FAddr = new DataWord( @@ -217,6 +240,24 @@ public static PrecompiledContract getContractForAddress(DataWord address) { return blake2F; } + if (VMConfig.allowTvmFreezeV2()) { + if (address.equals(getChainParameterAddr)) { + return getChainParameter; + } + if (address.equals(expireFreezeV2BalanceAddr)) { + return expireFreezeV2Balance; + } + if (address.equals(totalFrozenBalanceAddr)) { + return totalFrozenBalance; + } + if (address.equals(frozenBalanceAddr)) { + return frozenBalance; + } + if (address.equals(fronzenBalanceUsageAddr)) { + return frozenBalanceUsage; + } + } + return null; } @@ -1744,4 +1785,105 @@ public Pair execute(byte[] data) { return Pair.of(true, result); } } + + public static class GetChainParameter extends PrecompiledContract { + + @Override + public long getEnergyForData(byte[] data) { + return 0; + } + + @Override + public Pair execute(byte[] data) { + return Pair.of(true, DataWord.ZERO().getData()); + } + } + + public static class ExpireFreezeV2Balance extends PrecompiledContract { + + @Override + public long getEnergyForData(byte[] data) { + return 100; + } + + @Override + public Pair execute(byte[] data) { + if (data == null || data.length != WORD_SIZE) { + return Pair.of(true, DataWord.ZERO().getData()); + } + + byte[] caller = TransactionTrace.convertToTronAddress(getCallerAddress()); + long time = new DataWord(data).longValueSafe(); + long balance = FreezeV2Util.queryExpireFreezeV2Balance(caller, time, getDeposit()); + return Pair.of(true, longTo32Bytes(balance)); + } + } + + public static class TotalFrozenBalance extends PrecompiledContract { + + @Override + public long getEnergyForData(byte[] data) { + return 100; + } + + @Override + public Pair execute(byte[] data) { + if (data == null || data.length != 2 * WORD_SIZE) { + return Pair.of(true, DataWord.ZERO().getData()); + } + + DataWord[] words = DataWord.parseArray(data); + byte[] address = words[0].toTronAddress(); + long type = words[1].longValueSafe(); + + long balance = FreezeV2Util.queryTotalFrozenBalance(address, type, getDeposit()); + return Pair.of(true, longTo32Bytes(balance)); + } + } + + public static class FrozenBalance extends PrecompiledContract { + + @Override + public long getEnergyForData(byte[] data) { + return 100; + } + + @Override + public Pair execute(byte[] data) { + if (data == null || data.length != 3 * WORD_SIZE) { + return Pair.of(true, DataWord.ZERO().getData()); + } + + DataWord[] words = DataWord.parseArray(data); + byte[] from = words[0].toTronAddress(); + byte[] to = words[1].toTronAddress(); + long type = words[2].longValueSafe(); + + long balance = FreezeV2Util.queryFrozenBalance(from, to, type, getDeposit()); + return Pair.of(true, longTo32Bytes(balance)); + } + } + + public static class FrozenBalanceUsage extends PrecompiledContract { + + @Override + public long getEnergyForData(byte[] data) { + return 100; + } + + @Override + public Pair execute(byte[] data) { + if (data == null || data.length != 2 * WORD_SIZE) { + return Pair.of(true, DataWord.ZERO().getData()); + } + + DataWord[] words = DataWord.parseArray(data); + byte[] address = words[0].toTronAddress(); + long type = words[1].longValueSafe(); + + long[] values = FreezeV2Util.queryFrozenBalanceUsage(address, type, getDeposit()); + return Pair.of(true, encodeRes(longTo32Bytes(values[0]), longTo32Bytes(values[1]))); + } + } + } diff --git a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java index 93781e749a4..b2fa1876940 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java +++ b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java @@ -31,6 +31,7 @@ public static void load(StoreFactory storeFactory) { VMConfig.initAllowTvmCompatibleEvm(ds.getAllowTvmCompatibleEvm()); VMConfig.initAllowHigherLimitForMaxCpuTimeOfOneTx( ds.getAllowHigherLimitForMaxCpuTimeOfOneTx()); + VMConfig.initAllowTvmFreezeV2(ds.getUnfreezeDelayDays() > 0 ? 1 : 0); } } } diff --git a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java index aa7ca241df5..cd94409878d 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java +++ b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java @@ -35,6 +35,8 @@ public class VMConfig { private static boolean ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX = false; + private static boolean ALLOW_TVM_FREEZE_V2 = false; + private VMConfig() { } @@ -94,6 +96,10 @@ public static void initAllowHigherLimitForMaxCpuTimeOfOneTx(long allow) { ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX = allow == 1; } + public static void initAllowTvmFreezeV2(long allow) { + ALLOW_TVM_FREEZE_V2 = allow == 1; + } + public static boolean getEnergyLimitHardFork() { return CommonParameter.ENERGY_LIMIT_HARD_FORK; } @@ -141,4 +147,8 @@ public static boolean allowTvmCompatibleEvm() { public static boolean allowHigherLimitForMaxCpuTimeOfOneTx() { return ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX; } + + public static boolean allowTvmFreezeV2() { + return ALLOW_TVM_FREEZE_V2; + } } diff --git a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java index 458d83f5110..b450717a250 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java +++ b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java @@ -222,6 +222,16 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { return repository.getAccountLeftEnergyFromFreeze(accountCapsule); } + @Override + public long[] getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { + return repository.getAccountEnergyUsageBalanceAndRestoreSeconds(accountCapsule); + } + + @Override + public long[] getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { + return repository.getAccountNetUsageBalanceAndRestoreSeconds(accountCapsule); + } + @Override public long calculateGlobalEnergyLimit(AccountCapsule accountCapsule) { return repository.calculateGlobalEnergyLimit(accountCapsule); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java index efbbdac1a05..c6781ecfebb 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java @@ -106,6 +106,10 @@ public interface Repository { long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule); + long[] getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule); + + long[] getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule); + long calculateGlobalEnergyLimit(AccountCapsule accountCapsule); byte[] getBlackHoleAddress(); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 10c81d3bae1..5a8f02904da 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -169,6 +169,50 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { return max(energyLimit - newEnergyUsage, 0); // us } + public long[] getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { + long now = getHeadSlot(); + + long energyUsage = accountCapsule.getEnergyUsage(); + long latestConsumeTime = accountCapsule.getAccountResource().getLatestConsumeTimeForEnergy(); + + if (now >= latestConsumeTime + windowSize) { + return new long[]{0L, 0L}; + } + + long diff = latestConsumeTime + windowSize - now; + + long newEnergyUsage = increase(energyUsage, 0, latestConsumeTime, now); + + long totalEnergyLimit = getDynamicPropertiesStore().getTotalEnergyCurrentLimit(); + long totalEnergyWeight = getDynamicPropertiesStore().getTotalEnergyWeight(); + + long balance = (long) ((double) newEnergyUsage * totalEnergyWeight / totalEnergyLimit) * 1_000_000L; + + return new long[]{balance, Long.max(0L, diff)}; + } + + public long[] getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { + long now = getHeadSlot(); + + long netUsage = accountCapsule.getNetUsage(); + long latestConsumeTime = accountCapsule.getLatestConsumeTime(); + + if (now >= latestConsumeTime + windowSize) { + return new long[]{0L, 0L}; + } + + long diff = latestConsumeTime + windowSize - now; + + long newNetUsage = increase(netUsage, 0, latestConsumeTime, now); + + long totalNetLimit = getDynamicPropertiesStore().getTotalNetLimit(); + long totalNetWeight = getDynamicPropertiesStore().getTotalNetWeight(); + + long balance = (long) ((double) newNetUsage * totalNetWeight / totalNetLimit) * 1_000_000L; + + return new long[]{balance, Long.max(0L, diff)}; + } + @Override public AssetIssueCapsule getAssetIssue(byte[] tokenId) { byte[] tokenIdWithoutLeadingZero = ByteUtil.stripLeadingZeroes(tokenId); diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java new file mode 100644 index 00000000000..3f9fe25abdc --- /dev/null +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -0,0 +1,137 @@ +package org.tron.core.vm.utils; + +import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; +import static org.tron.core.config.Parameter.ChainConstant.PRECISION; + +import java.util.*; +import java.util.stream.Collectors; + +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceCapsule; +import org.tron.core.config.Parameter; +import org.tron.core.vm.config.VMConfig; +import org.tron.core.vm.repository.Repository; +import org.tron.protos.Protocol; + +public class FreezeV2Util { + + private static final long WINDOW_SIZE = + Parameter.ChainConstant.WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL; + + private FreezeV2Util() { + } + + public static long queryExpireFreezeV2Balance(byte[] address, long time, Repository repository) { + if (!VMConfig.allowTvmFreezeV2()) { + return 0; + } + + AccountCapsule accountCapsule = repository.getAccount(address); + List unfrozenV2List = + accountCapsule.getInstance().getUnfrozenV2List(); + + return getTotalWithdrawUnfreeze(unfrozenV2List, time); + } + + // v1 included. + public static long queryTotalFrozenBalance(byte[] address, long type, Repository repository) { + if (!VMConfig.allowTvmFreezeV2()) { + return 0; + } + + AccountCapsule accountCapsule = repository.getAccount(address); + + // BANDWIDTH + if (type == 0) { + return accountCapsule.getAllFrozenBalanceForBandwidth(); + } + + // ENERGY + if (type == 1) { + return accountCapsule.getAllFrozenBalanceForEnergy(); + } + + // POWER + if (type == 2) { + return accountCapsule.getAllTronPower(); + } + + return 0; + } + + // only freezeV2. + public static long queryFrozenBalance(byte[] from, byte[] to, long type, Repository repository) { + if (!VMConfig.allowTvmFreezeV2()) { + return 0; + } + + byte[] key = DelegatedResourceCapsule.createDbKeyV2(from, to); + DelegatedResourceCapsule delegatedResource = repository.getDelegatedResource(key); + if (delegatedResource == null) { + return 0; + } + + // BANDWIDTH + if (type == 0) { + return delegatedResource.getFrozenBalanceForBandwidth(); + } + + // ENERGY + if (type == 1) { + return delegatedResource.getFrozenBalanceForEnergy(); + } + + return 0; + } + + public static long[] queryFrozenBalanceUsage(byte[] address, long type, Repository repository) { + if (!VMConfig.allowTvmFreezeV2()) { + return new long[]{0L, 0L}; + } + + AccountCapsule accountCapsule = repository.getAccount(address); + + if (type == 0) { + return repository.getAccountNetUsageBalanceAndRestoreSeconds(accountCapsule); + } else if (type == 1) { + return repository.getAccountEnergyUsageBalanceAndRestoreSeconds(accountCapsule); + } + + return new long[]{0L, 0L}; + } + + private static long getTotalWithdrawUnfreeze(List unfrozenV2List, long time) { + return getTotalWithdrawList(unfrozenV2List, time).stream() + .mapToLong(Protocol.Account.UnFreezeV2::getUnfreezeAmount).sum(); + } + + private static List getTotalWithdrawList(List unfrozenV2List, long now) { + return unfrozenV2List.stream().filter(unfrozenV2 -> (unfrozenV2.getUnfreezeAmount() > 0 + && unfrozenV2.getUnfreezeExpireTime() <= now)).collect(Collectors.toList()); + } + + private static long recover(long lastUsage, long lastTime, long now, long windowSize) { + long averageLastUsage = divideCeil(lastUsage * PRECISION, windowSize); + + if (lastTime != now) { + assert now > lastTime; + if (lastTime + windowSize > now) { + long delta = now - lastTime; + double decay = (windowSize - delta) / (double) windowSize; + averageLastUsage = Math.round(averageLastUsage * decay); + } else { + averageLastUsage = 0; + } + } + return getUsage(averageLastUsage, windowSize); + } + + private static long divideCeil(long numerator, long denominator) { + return (numerator / denominator) + ((numerator % denominator) > 0 ? 1 : 0); + } + + private static long getUsage(long usage, long windowSize) { + return usage * windowSize / PRECISION; + } + +} From f2874c51e6464486023b8ee87f541eba9e488ea5 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Sun, 16 Oct 2022 12:08:48 +0800 Subject: [PATCH 0289/1197] feat(freezeV2): optimize and unify precompileContract time meanings to seconds --- .../tron/core/vm/PrecompiledContracts.java | 11 +++++++ .../core/vm/repository/RepositoryImpl.java | 12 +++---- .../org/tron/core/vm/utils/FreezeV2Util.java | 31 ------------------- 3 files changed, 17 insertions(+), 37 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index b4f79cef441..3bcaae77abf 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -1814,6 +1814,17 @@ public Pair execute(byte[] data) { byte[] caller = TransactionTrace.convertToTronAddress(getCallerAddress()); long time = new DataWord(data).longValueSafe(); + + if (time < 0) { + return Pair.of(true, DataWord.ZERO().getData()); + } + + if (time >= Long.MAX_VALUE / 1_000) { + time = Long.MAX_VALUE; + } else { + time = time * 1_000; + } + long balance = FreezeV2Util.queryExpireFreezeV2Balance(caller, time, getDeposit()); return Pair.of(true, longTo32Bytes(balance)); } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 5a8f02904da..3f5bc48c2a9 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -179,16 +179,16 @@ public long[] getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accou return new long[]{0L, 0L}; } - long diff = latestConsumeTime + windowSize - now; + long restoreSlots = latestConsumeTime + windowSize - now; long newEnergyUsage = increase(energyUsage, 0, latestConsumeTime, now); long totalEnergyLimit = getDynamicPropertiesStore().getTotalEnergyCurrentLimit(); - long totalEnergyWeight = getDynamicPropertiesStore().getTotalEnergyWeight(); + long totalEnergyWeight = getTotalEnergyWeight(); long balance = (long) ((double) newEnergyUsage * totalEnergyWeight / totalEnergyLimit) * 1_000_000L; - return new long[]{balance, Long.max(0L, diff)}; + return new long[]{balance, Long.max(0L, restoreSlots * BLOCK_PRODUCED_INTERVAL / 1_000)}; } public long[] getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { @@ -201,16 +201,16 @@ public long[] getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsule accountC return new long[]{0L, 0L}; } - long diff = latestConsumeTime + windowSize - now; + long restoreSlots = latestConsumeTime + windowSize - now; long newNetUsage = increase(netUsage, 0, latestConsumeTime, now); long totalNetLimit = getDynamicPropertiesStore().getTotalNetLimit(); - long totalNetWeight = getDynamicPropertiesStore().getTotalNetWeight(); + long totalNetWeight = getTotalNetWeight(); long balance = (long) ((double) newNetUsage * totalNetWeight / totalNetLimit) * 1_000_000L; - return new long[]{balance, Long.max(0L, diff)}; + return new long[]{balance, Long.max(0L, restoreSlots * BLOCK_PRODUCED_INTERVAL / 1_000)}; } @Override diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index 3f9fe25abdc..1d611f78992 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -1,23 +1,16 @@ package org.tron.core.vm.utils; -import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; -import static org.tron.core.config.Parameter.ChainConstant.PRECISION; - import java.util.*; import java.util.stream.Collectors; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; -import org.tron.core.config.Parameter; import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.repository.Repository; import org.tron.protos.Protocol; public class FreezeV2Util { - private static final long WINDOW_SIZE = - Parameter.ChainConstant.WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL; - private FreezeV2Util() { } @@ -110,28 +103,4 @@ private static List getTotalWithdrawList(List lastTime; - if (lastTime + windowSize > now) { - long delta = now - lastTime; - double decay = (windowSize - delta) / (double) windowSize; - averageLastUsage = Math.round(averageLastUsage * decay); - } else { - averageLastUsage = 0; - } - } - return getUsage(averageLastUsage, windowSize); - } - - private static long divideCeil(long numerator, long denominator) { - return (numerator / denominator) + ((numerator % denominator) > 0 ? 1 : 0); - } - - private static long getUsage(long usage, long windowSize) { - return usage * windowSize / PRECISION; - } - } From 6e2a08ec8b9725a9b26a1c6a342e1dffe114b5e5 Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 17 Oct 2022 10:21:26 +0800 Subject: [PATCH 0290/1197] fix(freezeV2): fix freezeV2 processor --- .../java/org/tron/core/vm/EnergyCost.java | 5 -- .../src/main/java/org/tron/core/vm/Op.java | 7 +- .../org/tron/core/vm/OperationActions.java | 13 +--- .../org/tron/core/vm/OperationRegistry.java | 16 +++-- .../DelegateResourceProcessor.java | 10 +-- .../ExpireFreezeV2BalanceProcessor.java | 55 --------------- .../FreezeBalanceV2Processor.java | 21 +++--- .../UnDelegateResourceProcessor.java | 30 ++++---- .../UnfreezeBalanceV2Processor.java | 20 +----- .../WithdrawExpireUnfreezeProcessor.java | 6 +- .../param/ExpireFreezeV2BalanceParam.java | 26 ------- .../param/FreezeBalanceV2Param.java | 10 --- .../param/WithdrawExpireUnfreezeParam.java | 11 --- .../org/tron/core/vm/program/Program.java | 69 +++++++------------ 14 files changed, 68 insertions(+), 231 deletions(-) delete mode 100644 actuator/src/main/java/org/tron/core/vm/nativecontract/ExpireFreezeV2BalanceProcessor.java delete mode 100644 actuator/src/main/java/org/tron/core/vm/nativecontract/param/ExpireFreezeV2BalanceParam.java diff --git a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java index cafe86bbc05..73490b3fd98 100644 --- a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java +++ b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java @@ -38,7 +38,6 @@ public class EnergyCost { private static final long FREEZE_EXPIRE_TIME = 50; private static final long FREEZE_V2 = 20000; private static final long UNFREEZE_V2 = 20000; - private static final long EXPIRE_FREEZE_V2_BALANCE = 50; private static final long WITHDRAW_EXPIRE_UNFREEZE = 20000; private static final long DELEGATE_RESOURCE = 20000; private static final long UN_DELEGATE_RESOURCE = 20000; @@ -290,10 +289,6 @@ public static long getWithdrawExpireUnfreezeCost(Program ignored) { return WITHDRAW_EXPIRE_UNFREEZE; } - public static long getExpireFreezeV2BalanceCost(Program ignored) { - return EXPIRE_FREEZE_V2_BALANCE; - } - public static long getDelegateResourceCost(Program program) { Stack stack = program.getStack(); DataWord receiverAddressWord = stack.get(stack.size() - 3); diff --git a/actuator/src/main/java/org/tron/core/vm/Op.java b/actuator/src/main/java/org/tron/core/vm/Op.java index d28e6704c80..cd34c4dc4ae 100644 --- a/actuator/src/main/java/org/tron/core/vm/Op.java +++ b/actuator/src/main/java/org/tron/core/vm/Op.java @@ -238,10 +238,9 @@ public class Op { public static final int WITHDRAWREWARD = 0xd9; public static final int FREEZEBALANCEV2 = 0xda; public static final int UNFREEZEBALANCEV2 = 0xdb; - public static final int EXPIREFREEZEV2BALANCE = 0xdc; - public static final int WITHDRAWEXPIREUNFREEZE = 0xdd; - public static final int DELEGATERESOURCE = 0xde; - public static final int UNDELEGATERESOURCE = 0xdf; + public static final int WITHDRAWEXPIREUNFREEZE = 0xdc; + public static final int DELEGATERESOURCE = 0xdd; + public static final int UNDELEGATERESOURCE = 0xde; // (0xf0) Create a new account with associated code public static final int CREATE = 0xf0; diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index 94bd8e6b7ca..443a67f63eb 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -766,7 +766,7 @@ public static void freezeExpireTimeAction(Program program) { public static void freezeBalanceV2Action(Program program) { // after allow vote, check static - if (VMConfig.allowTvmVote() && program.isStaticCall()) { + if (program.isStaticCall()) { throw new Program.StaticCallModificationException(); } DataWord resourceType = program.stackPop(); @@ -778,7 +778,7 @@ public static void freezeBalanceV2Action(Program program) { } public static void unfreezeBalanceV2Action(Program program) { - if (VMConfig.allowTvmVote() && program.isStaticCall()) { + if (program.isStaticCall()) { throw new Program.StaticCallModificationException(); } @@ -800,15 +800,6 @@ public static void withdrawExpireUnfreezeAction(Program program) { program.step(); } - public static void expireFreezeV2BalanceAction(Program program) { - DataWord resourceType = program.stackPop(); - DataWord ownerAddress = program.stackPop(); - - long balance = program.expireFreezeV2Balance(ownerAddress, resourceType); - program.stackPush(new DataWord(balance)); - program.step(); - } - public static void delegateResourceAction(Program program) { if (program.isStaticCall()) { throw new Program.StaticCallModificationException(); diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index bd1ff3b48af..59747464bd4 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -10,6 +10,7 @@ public class OperationRegistry { public enum Version { TRON_V1_0, TRON_V1_1, + TRON_V1_2, // add more // TRON_V2, // ETH @@ -20,6 +21,7 @@ public enum Version { static { tableMap.put(Version.TRON_V1_0, newTronV10OperationSet()); tableMap.put(Version.TRON_V1_1, newTronV11OperationSet()); + tableMap.put(Version.TRON_V1_2, newTronV12OperationSet()); } public static JumpTable newTronV10OperationSet() { @@ -37,6 +39,11 @@ public static JumpTable newTronV10OperationSet() { public static JumpTable newTronV11OperationSet() { JumpTable table = newTronV10OperationSet(); adjustMemOperations(table); + return table; + } + + public static JumpTable newTronV12OperationSet() { + JumpTable table = newTronV11OperationSet(); appendFreezeV2Operations(table); appendDelegateOperations(table); return table; @@ -53,6 +60,9 @@ public static JumpTable getTable() { if (VMConfig.allowHigherLimitForMaxCpuTimeOfOneTx()) { return tableMap.get(Version.TRON_V1_1); } + if (VMConfig.allowTvmFreezeV2()) { + return tableMap.get(Version.TRON_V1_2); + } return tableMap.get(Version.TRON_V1_0); } @@ -588,12 +598,6 @@ public static void appendFreezeV2Operations(JumpTable table) { EnergyCost::getWithdrawExpireUnfreezeCost, OperationActions::withdrawExpireUnfreezeAction, proposal)); - - table.set(new Operation( - Op.EXPIREFREEZEV2BALANCE, 2, 1, - EnergyCost::getExpireFreezeV2BalanceCost, - OperationActions::expireFreezeV2BalanceAction, - proposal)); } public static void appendDelegateOperations(JumpTable table) { diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index 1eef0d0ebd6..e090cdfe303 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -31,18 +31,14 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra } byte[] ownerAddress = param.getOwnerAddress(); - AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); if (!dynamicStore.supportDR()) { throw new ContractValidateException("No support for resource delegate"); } - if (dynamicStore.getUnfreezeDelayDays() == 0) { - throw new ContractValidateException("Not support Delegate resource transaction," - + " need to be opened by the committee"); - } if (!DecodeUtil.addressValid(ownerAddress)) { throw new ContractValidateException("Invalid address"); } + AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); if (ownerCapsule == null) { String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); throw new ContractValidateException( @@ -59,7 +55,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra processor.updateUsage(ownerCapsule); //The unit is trx long netTrxUsage = (long) (ownerCapsule.getNetUsage() - * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); + * ((double) (repo.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); if (ownerCapsule.getFrozenV2BalanceForBandwidth() - netTrxUsage * TRX_PRECISION < delegateBalance) { @@ -75,7 +71,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra //The unit is trx long energyTrxUsage = (long) (ownerCapsule.getEnergyUsage() - * ((double) (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); + * ((double) (repo.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); if (ownerCapsule.getFrozenV2BalanceForEnergy() - energyTrxUsage * TRX_PRECISION < delegateBalance) { diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/ExpireFreezeV2BalanceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/ExpireFreezeV2BalanceProcessor.java deleted file mode 100644 index a406874f924..00000000000 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/ExpireFreezeV2BalanceProcessor.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.tron.core.vm.nativecontract; - -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; - -import java.util.List; -import java.util.stream.Collectors; - -import lombok.extern.slf4j.Slf4j; -import org.tron.common.utils.DecodeUtil; -import org.tron.common.utils.StringUtil; -import org.tron.core.capsule.AccountCapsule; -import org.tron.core.exception.ContractValidateException; -import org.tron.core.store.DynamicPropertiesStore; -import org.tron.core.vm.nativecontract.param.ExpireFreezeV2BalanceParam; -import org.tron.core.vm.repository.Repository; -import org.tron.protos.Protocol; -import org.tron.protos.contract.Common; - -@Slf4j(topic = "VMProcessor") -public class ExpireFreezeV2BalanceProcessor { - - public void validate(ExpireFreezeV2BalanceParam param, Repository repo) throws ContractValidateException { - if (repo == null) { - throw new ContractValidateException(STORE_NOT_EXIST); - } - - byte[] ownerAddress = param.getOwnerAddress(); - AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); - if (!DecodeUtil.addressValid(ownerAddress)) { - throw new ContractValidateException("Invalid address"); - } - if (ownerCapsule == null) { - String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); - throw new ContractValidateException( - ACCOUNT_EXCEPTION_STR + readableOwnerAddress + "] does not exist"); - } - } - - public long execute(ExpireFreezeV2BalanceParam param, Repository repo) { - byte[] ownerAddress = param.getOwnerAddress(); - AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); - Common.ResourceCode resourceType = param.getResourceType(); - - DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); - long now = dynamicStore.getLatestBlockHeaderTimestamp(); - List unfrozenV2List = ownerCapsule.getInstance().getUnfrozenV2List(); - List expireFreezeV2List = unfrozenV2List.stream() - .filter(unFreezeV2 -> unFreezeV2.getType().equals(resourceType)) - .filter(unFreezeV2 -> unFreezeV2.getUnfreezeAmount() > 0) - .filter(unFreezeV2 -> unFreezeV2.getUnfreezeExpireTime() <= now) - .collect(Collectors.toList()); - return expireFreezeV2List.stream().mapToLong(Protocol.Account.UnFreezeV2::getUnfreezeAmount).sum(); - } -} diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java index c0fa9ef66f2..349e6746e5e 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java @@ -22,14 +22,10 @@ public void validate(FreezeBalanceV2Param param, Repository repo) throws Contrac } byte[] ownerAddress = param.getOwnerAddress(); - AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); - if (repo.getDynamicPropertiesStore().getUnfreezeDelayDays() == 0) { - throw new ContractValidateException("Not support FreezeV2 transaction," - + " need to be opened by the committee"); - } if (!DecodeUtil.addressValid(ownerAddress)) { throw new ContractValidateException("Invalid address"); } + AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); if (ownerCapsule == null) { String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); throw new ContractValidateException( @@ -44,12 +40,6 @@ public void validate(FreezeBalanceV2Param param, Repository repo) throws Contrac throw new ContractValidateException("FrozenBalance must be less than accountBalance"); } - // validate frozen count of owner account - int frozenCount = ownerCapsule.getFrozenCount(); - if (frozenCount != 0 && frozenCount != 1) { - throw new ContractValidateException("FrozenCount must be 0 or 1"); - } - // validate arg @resourceType switch (param.getResourceType()) { case BANDWIDTH: @@ -62,8 +52,13 @@ public void validate(FreezeBalanceV2Param param, Repository repo) throws Contrac } break; default: - throw new ContractValidateException( - "ResourceCode error,valid ResourceCode[BANDWIDTH、ENERGY]"); + if (repo.getDynamicPropertiesStore().supportAllowNewResourceModel()) { + throw new ContractValidateException( + "ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY、TRON_POWER]"); + } else { + throw new ContractValidateException( + "ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]"); + } } } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index bbf6ed95004..f336abd6e6a 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -28,18 +28,14 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont } byte[] ownerAddress = param.getOwnerAddress(); - AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); if (!dynamicStore.supportDR()) { throw new ContractValidateException("No support for resource delegate"); } - if (dynamicStore.getUnfreezeDelayDays() == 0) { - throw new ContractValidateException("Not support Delegate resource transaction," - + " need to be opened by the committee"); - } if (!DecodeUtil.addressValid(ownerAddress)) { throw new ContractValidateException("Invalid address"); } + AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); if (ownerCapsule == null) { String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); throw new ContractValidateException( @@ -54,12 +50,14 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont throw new ContractValidateException( "receiverAddress must not be the same as ownerAddress"); } - AccountCapsule receiverCapsule = repo.getAccount(receiverAddress); - if (receiverCapsule == null) { - String readableReceiverAddress = StringUtil.createReadableString(receiverAddress); - throw new ContractValidateException( - "Receiver Account[" + readableReceiverAddress + "] does not exist"); - } + + // TVM contract suicide can result in no receiving account +// AccountCapsule receiverCapsule = repo.getAccount(receiverAddress); +// if (receiverCapsule == null) { +// String readableReceiverAddress = StringUtil.createReadableString(receiverAddress); +// throw new ContractValidateException( +// "Receiver Account[" + readableReceiverAddress + "] does not exist"); +// } byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress); DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); @@ -93,11 +91,11 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont public void execute(UnDelegateResourceParam param, Repository repo) { byte[] ownerAddress = param.getOwnerAddress(); - AccountCapsule ownerCapsule = repo.getAccount(param.getOwnerAddress()); - DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); - long unDelegateBalance = param.getUnDelegateBalance(); byte[] receiverAddress = param.getReceiverAddress(); + long unDelegateBalance = param.getUnDelegateBalance(); + AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); AccountCapsule receiverCapsule = repo.getAccount(receiverAddress); + DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); long transferUsage = 0; // modify receiver Account @@ -115,7 +113,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { } else { // calculate usage long unDelegateMaxUsage = (long) (unDelegateBalance / TRX_PRECISION - * ((double) (dynamicStore.getTotalNetLimit()) / dynamicStore.getTotalNetWeight())); + * ((double) (dynamicStore.getTotalNetLimit()) / repo.getTotalNetWeight())); transferUsage = (long) (receiverCapsule.getNetUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForBandwidth())); transferUsage = Math.min(unDelegateMaxUsage, transferUsage); @@ -138,7 +136,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { } else { // calculate usage long unDelegateMaxUsage = (long) (unDelegateBalance / TRX_PRECISION - * ((double) (dynamicStore.getTotalEnergyCurrentLimit()) / dynamicStore.getTotalEnergyWeight())); + * ((double) (dynamicStore.getTotalEnergyCurrentLimit()) / repo.getTotalEnergyWeight())); transferUsage = (long) (receiverCapsule.getEnergyUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForEnergy())); transferUsage = Math.min(unDelegateMaxUsage, transferUsage); diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index 070ed20436c..93be714e62c 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -33,15 +33,11 @@ public void validate(UnfreezeBalanceV2Param param, Repository repo) } byte[] ownerAddress = param.getOwnerAddress(); - AccountCapsule accountCapsule = repo.getAccount(ownerAddress); DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); - if (dynamicStore.getUnfreezeDelayDays() == 0) { - throw new ContractValidateException("Not support UnfreezeV2 transaction," - + " need to be opened by the committee"); - } if (!DecodeUtil.addressValid(ownerAddress)) { throw new ContractValidateException("Invalid address"); } + AccountCapsule accountCapsule = repo.getAccount(ownerAddress); if (accountCapsule == null) { String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); throw new ContractValidateException( @@ -58,24 +54,12 @@ public void validate(UnfreezeBalanceV2Param param, Repository repo) if (!this.checkExistFrozenBalance(accountCapsule, Common.ResourceCode.BANDWIDTH)) { throw new ContractValidateException("no frozenBalance(BANDWIDTH)"); } - // check if it is time to unfreeze - long allowedUnfreezeCount = accountCapsule.getFrozenList().stream() - .filter(frozen -> frozen.getExpireTime() <= now).count(); - if (allowedUnfreezeCount <= 0) { - throw new ContractValidateException("It's not time to unfreeze(BANDWIDTH)."); - } break; case ENERGY: - Protocol.Account.Frozen frozenForEnergy = accountCapsule.getAccountResource() - .getFrozenBalanceForEnergy(); // validate frozen balance if (!this.checkExistFrozenBalance(accountCapsule, Common.ResourceCode.ENERGY)) { throw new ContractValidateException("no frozenBalance(Energy)"); } - // check if it is time to unfreeze - if (frozenForEnergy.getExpireTime() > now) { - throw new ContractValidateException("It's not time to unfreeze(Energy)."); - } break; case TRON_POWER: if (dynamicStore.supportAllowNewResourceModel()) { @@ -112,7 +96,7 @@ private boolean checkUnfreezeBalance( return unfreezeBalance <= frozenBalance; } - public boolean checkExistFrozenBalance(AccountCapsule accountCapsule, Common.ResourceCode freezeType) { + private boolean checkExistFrozenBalance(AccountCapsule accountCapsule, Common.ResourceCode freezeType) { boolean checkOk = false; long frozenBalance; List frozenV2List = accountCapsule.getFrozenV2List(); diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java index 578e78c13b4..b754fb2cc01 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java @@ -28,15 +28,11 @@ public void validate(WithdrawExpireUnfreezeParam param, Repository repo) throws } byte[] ownerAddress = param.getOwnerAddress(); - AccountCapsule accountCapsule = repo.getAccount(ownerAddress); DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); - if (dynamicStore.getUnfreezeDelayDays() == 0) { - throw new ContractValidateException("Not support WithdrawExpireUnfreeze transaction," - + " need to be opened by the committee"); - } if (!DecodeUtil.addressValid(ownerAddress)) { throw new ContractValidateException("Invalid address"); } + AccountCapsule accountCapsule = repo.getAccount(ownerAddress); if (Objects.isNull(accountCapsule)) { String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); throw new ContractValidateException(ACCOUNT_EXCEPTION_STR diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/ExpireFreezeV2BalanceParam.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/ExpireFreezeV2BalanceParam.java deleted file mode 100644 index e49f27b7556..00000000000 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/ExpireFreezeV2BalanceParam.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.tron.core.vm.nativecontract.param; - -import org.tron.protos.contract.Common; - -public class ExpireFreezeV2BalanceParam { - - private byte[] ownerAddress; - - private Common.ResourceCode resourceType; - - public byte[] getOwnerAddress() { - return ownerAddress; - } - - public void setOwnerAddress(byte[] ownerAddress) { - this.ownerAddress = ownerAddress; - } - - public Common.ResourceCode getResourceType() { - return resourceType; - } - - public void setResourceType(Common.ResourceCode resourceType) { - this.resourceType = resourceType; - } -} diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/FreezeBalanceV2Param.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/FreezeBalanceV2Param.java index b6f2c7c4aeb..8aaf00da975 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/FreezeBalanceV2Param.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/FreezeBalanceV2Param.java @@ -8,8 +8,6 @@ public class FreezeBalanceV2Param { private long frozenBalance; - private long frozenDuration; - private Common.ResourceCode resourceType; public byte[] getOwnerAddress() { @@ -28,14 +26,6 @@ public void setFrozenBalance(long frozenBalance) { this.frozenBalance = frozenBalance; } - public long getFrozenDuration() { - return frozenDuration; - } - - public void setFrozenDuration(long frozenDuration) { - this.frozenDuration = frozenDuration; - } - public Common.ResourceCode getResourceType() { return resourceType; } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/WithdrawExpireUnfreezeParam.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/WithdrawExpireUnfreezeParam.java index 6fe371be510..db3cece4126 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/WithdrawExpireUnfreezeParam.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/WithdrawExpireUnfreezeParam.java @@ -5,9 +5,6 @@ public class WithdrawExpireUnfreezeParam { // Account address which want to withdraw its reward private byte[] ownerAddress; - // Latest block timestamp - private long nowInMs; - public byte[] getOwnerAddress() { return ownerAddress; } @@ -15,12 +12,4 @@ public byte[] getOwnerAddress() { public void setOwnerAddress(byte[] ownerAddress) { this.ownerAddress = ownerAddress; } - - public long getNowInMs() { - return nowInMs; - } - - public void setNowInMs(long nowInMs) { - this.nowInMs = nowInMs; - } } diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 683a29a45b6..bcd94f89e67 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -51,7 +51,6 @@ import org.tron.core.vm.VMUtils; import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.nativecontract.DelegateResourceProcessor; -import org.tron.core.vm.nativecontract.ExpireFreezeV2BalanceProcessor; import org.tron.core.vm.nativecontract.FreezeBalanceProcessor; import org.tron.core.vm.nativecontract.FreezeBalanceV2Processor; import org.tron.core.vm.nativecontract.UnDelegateResourceProcessor; @@ -61,7 +60,6 @@ import org.tron.core.vm.nativecontract.WithdrawExpireUnfreezeProcessor; import org.tron.core.vm.nativecontract.WithdrawRewardProcessor; import org.tron.core.vm.nativecontract.param.DelegateResourceParam; -import org.tron.core.vm.nativecontract.param.ExpireFreezeV2BalanceParam; import org.tron.core.vm.nativecontract.param.FreezeBalanceParam; import org.tron.core.vm.nativecontract.param.FreezeBalanceV2Param; import org.tron.core.vm.nativecontract.param.UnDelegateResourceParam; @@ -1755,16 +1753,13 @@ public boolean freezeBalanceV2(DataWord frozenBalance, DataWord resourceType) { frozenBalance.longValue(), null, "freezeBalanceV2For" + convertResourceToString(resourceType), nonce, null); - FreezeBalanceV2Param param = new FreezeBalanceV2Param(); - param.setOwnerAddress(owner); - boolean needCheckFrozenTime = CommonParameter.getInstance() - .getCheckFrozenTime() == 1; // for test - param.setFrozenDuration(needCheckFrozenTime - ? repository.getDynamicPropertiesStore().getMinFrozenTime() : 0); - param.setResourceType(parseResourceCode(resourceType)); try { - FreezeBalanceV2Processor processor = new FreezeBalanceV2Processor(); + FreezeBalanceV2Param param = new FreezeBalanceV2Param(); + param.setOwnerAddress(owner); + param.setResourceType(parseResourceCode(resourceType)); param.setFrozenBalance(frozenBalance.sValue().longValueExact()); + + FreezeBalanceV2Processor processor = new FreezeBalanceV2Processor(); processor.validate(param, repository); processor.execute(param, repository); repository.commit(); @@ -1789,11 +1784,12 @@ public boolean unfreezeBalanceV2(DataWord unfreezeBalance, DataWord resourceType unfreezeBalance.longValue(), null, "unfreezeBalanceV2For" + convertResourceToString(resourceType), nonce, null); - UnfreezeBalanceV2Param param = new UnfreezeBalanceV2Param(); - param.setOwnerAddress(owner); - param.setUnfreezeBalance(unfreezeBalance.sValue().longValueExact()); - param.setResourceType(parseResourceCode(resourceType)); try { + UnfreezeBalanceV2Param param = new UnfreezeBalanceV2Param(); + param.setOwnerAddress(owner); + param.setUnfreezeBalance(unfreezeBalance.sValue().longValueExact()); + param.setResourceType(parseResourceCode(resourceType)); + UnfreezeBalanceV2Processor processor = new UnfreezeBalanceV2Processor(); processor.validate(param, repository); processor.execute(param, repository); @@ -1816,10 +1812,10 @@ public long withdrawExpireUnfreeze() { InternalTransaction internalTx = addInternalTx(null, owner, owner, 0, null, "withdrawExpireUnfreeze", nonce, null); - WithdrawExpireUnfreezeParam param = new WithdrawExpireUnfreezeParam(); - param.setOwnerAddress(owner); - param.setNowInMs(getTimestamp().longValue() * 1000); try { + WithdrawExpireUnfreezeParam param = new WithdrawExpireUnfreezeParam(); + param.setOwnerAddress(owner); + WithdrawExpireUnfreezeProcessor processor = new WithdrawExpireUnfreezeProcessor(); processor.validate(param, repository); long expireUnfreezeBalance = processor.execute(param, repository); @@ -1839,23 +1835,6 @@ public long withdrawExpireUnfreeze() { return 0; } - public long expireFreezeV2Balance(DataWord ownerAddress, DataWord resourceType) { - Repository repository = getContractState().newRepositoryChild(); - ExpireFreezeV2BalanceParam param = new ExpireFreezeV2BalanceParam(); - param.setOwnerAddress(ownerAddress.toTronAddress()); - param.setResourceType(parseResourceCode(resourceType)); - try { - ExpireFreezeV2BalanceProcessor processor = new ExpireFreezeV2BalanceProcessor(); - processor.validate(param, repository); - long balance = processor.execute(param, repository); - repository.commit(); - return balance; - } catch (ContractValidateException e) { - logger.error("TVM expireFreezeV2Balance: validate failure. Reason: {}", e.getMessage()); - } - return 0; - } - public boolean delegateResource( DataWord receiverAddress, DataWord delegateBalance, DataWord resourceType) { Repository repository = getContractState().newRepositoryChild(); @@ -1867,12 +1846,13 @@ public boolean delegateResource( delegateBalance.longValue(), null, "delegateResource" + convertResourceToString(resourceType), nonce, null); - DelegateResourceParam param = new DelegateResourceParam(); - param.setOwnerAddress(owner); - param.setReceiverAddress(receiver); - param.setDelegateBalance(delegateBalance.sValue().longValueExact()); - param.setResourceType(parseResourceCode(resourceType)); try { + DelegateResourceParam param = new DelegateResourceParam(); + param.setOwnerAddress(owner); + param.setReceiverAddress(receiver); + param.setDelegateBalance(delegateBalance.sValue().longValueExact()); + param.setResourceType(parseResourceCode(resourceType)); + DelegateResourceProcessor processor = new DelegateResourceProcessor(); processor.validate(param, repository); processor.execute(param, repository); @@ -1900,12 +1880,13 @@ public boolean unDelegateResource( unDelegateBalance.longValue(), null, "unDelegateResource" + convertResourceToString(resourceType), nonce, null); - UnDelegateResourceParam param = new UnDelegateResourceParam(); - param.setOwnerAddress(owner); - param.setReceiverAddress(receiver); - param.setUnDelegateBalance(unDelegateBalance.sValue().longValueExact()); - param.setResourceType(parseResourceCode(resourceType)); try { + UnDelegateResourceParam param = new UnDelegateResourceParam(); + param.setOwnerAddress(owner); + param.setReceiverAddress(receiver); + param.setUnDelegateBalance(unDelegateBalance.sValue().longValueExact()); + param.setResourceType(parseResourceCode(resourceType)); + UnDelegateResourceProcessor processor = new UnDelegateResourceProcessor(); processor.validate(param, repository); processor.execute(param, repository); From 4df199452ae116336be34294935c2fb1fa64f679 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Mon, 17 Oct 2022 10:45:50 +0800 Subject: [PATCH 0291/1197] feat(freezeV2): optimize for review comments --- .../org/tron/core/vm/PrecompiledContracts.java | 10 +++++++--- .../tron/core/vm/program/ContractState.java | 5 +++-- .../tron/core/vm/repository/Repository.java | 5 +++-- .../core/vm/repository/RepositoryImpl.java | 18 ++++++++++-------- .../org/tron/core/vm/utils/FreezeV2Util.java | 7 ++++--- 5 files changed, 27 insertions(+), 18 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 3bcaae77abf..96fd12f689e 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -1885,15 +1885,19 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { if (data == null || data.length != 2 * WORD_SIZE) { - return Pair.of(true, DataWord.ZERO().getData()); + return Pair.of(true, encodeRes(DataWord.ZERO().getData(), DataWord.ZERO().getData())); } DataWord[] words = DataWord.parseArray(data); byte[] address = words[0].toTronAddress(); long type = words[1].longValueSafe(); - long[] values = FreezeV2Util.queryFrozenBalanceUsage(address, type, getDeposit()); - return Pair.of(true, encodeRes(longTo32Bytes(values[0]), longTo32Bytes(values[1]))); + Pair values = FreezeV2Util.queryFrozenBalanceUsage(address, type, getDeposit()); + if (values == null || values.getLeft() == null || values.getRight() == null) { + return Pair.of(true, encodeRes(DataWord.ZERO().getData(), DataWord.ZERO().getData())); + } + + return Pair.of(true, encodeRes(longTo32Bytes(values.getLeft()), longTo32Bytes(values.getRight()))); } } diff --git a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java index b450717a250..b19d663e8b4 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java +++ b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java @@ -1,5 +1,6 @@ package org.tron.core.vm.program; +import org.apache.commons.lang3.tuple.Pair; import org.tron.common.runtime.vm.DataWord; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; @@ -223,12 +224,12 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { } @Override - public long[] getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { + public Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { return repository.getAccountEnergyUsageBalanceAndRestoreSeconds(accountCapsule); } @Override - public long[] getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { + public Pair getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { return repository.getAccountNetUsageBalanceAndRestoreSeconds(accountCapsule); } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java index c6781ecfebb..9e9bdac8db6 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java @@ -1,5 +1,6 @@ package org.tron.core.vm.repository; +import org.apache.commons.lang3.tuple.Pair; import org.tron.common.runtime.vm.DataWord; import org.tron.core.capsule.*; import org.tron.core.store.*; @@ -106,9 +107,9 @@ public interface Repository { long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule); - long[] getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule); + Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule); - long[] getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule); + Pair getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule); long calculateGlobalEnergyLimit(AccountCapsule accountCapsule); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 3f5bc48c2a9..a84f103146c 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -2,12 +2,14 @@ import static java.lang.Long.max; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import com.google.protobuf.ByteString; import java.util.HashMap; import java.util.Optional; import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.tuple.Pair; import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Hex; import org.tron.common.crypto.Hash; @@ -169,14 +171,14 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { return max(energyLimit - newEnergyUsage, 0); // us } - public long[] getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { + public Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { long now = getHeadSlot(); long energyUsage = accountCapsule.getEnergyUsage(); long latestConsumeTime = accountCapsule.getAccountResource().getLatestConsumeTimeForEnergy(); if (now >= latestConsumeTime + windowSize) { - return new long[]{0L, 0L}; + return Pair.of(0L, 0L); } long restoreSlots = latestConsumeTime + windowSize - now; @@ -186,19 +188,19 @@ public long[] getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accou long totalEnergyLimit = getDynamicPropertiesStore().getTotalEnergyCurrentLimit(); long totalEnergyWeight = getTotalEnergyWeight(); - long balance = (long) ((double) newEnergyUsage * totalEnergyWeight / totalEnergyLimit) * 1_000_000L; + long balance = (long) ((double) newEnergyUsage * totalEnergyWeight / totalEnergyLimit) * TRX_PRECISION; - return new long[]{balance, Long.max(0L, restoreSlots * BLOCK_PRODUCED_INTERVAL / 1_000)}; + return Pair.of(balance, restoreSlots * BLOCK_PRODUCED_INTERVAL / 1_000); } - public long[] getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { + public Pair getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { long now = getHeadSlot(); long netUsage = accountCapsule.getNetUsage(); long latestConsumeTime = accountCapsule.getLatestConsumeTime(); if (now >= latestConsumeTime + windowSize) { - return new long[]{0L, 0L}; + return Pair.of(0L, 0L); } long restoreSlots = latestConsumeTime + windowSize - now; @@ -208,9 +210,9 @@ public long[] getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsule accountC long totalNetLimit = getDynamicPropertiesStore().getTotalNetLimit(); long totalNetWeight = getTotalNetWeight(); - long balance = (long) ((double) newNetUsage * totalNetWeight / totalNetLimit) * 1_000_000L; + long balance = (long) ((double) newNetUsage * totalNetWeight / totalNetLimit) * TRX_PRECISION; - return new long[]{balance, Long.max(0L, restoreSlots * BLOCK_PRODUCED_INTERVAL / 1_000)}; + return Pair.of(balance, restoreSlots * BLOCK_PRODUCED_INTERVAL / 1_000); } @Override diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index 1d611f78992..0ebdf21e2a4 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -3,6 +3,7 @@ import java.util.*; import java.util.stream.Collectors; +import org.apache.commons.lang3.tuple.Pair; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.vm.config.VMConfig; @@ -77,9 +78,9 @@ public static long queryFrozenBalance(byte[] from, byte[] to, long type, Reposit return 0; } - public static long[] queryFrozenBalanceUsage(byte[] address, long type, Repository repository) { + public static Pair queryFrozenBalanceUsage(byte[] address, long type, Repository repository) { if (!VMConfig.allowTvmFreezeV2()) { - return new long[]{0L, 0L}; + return Pair.of(0L, 0L); } AccountCapsule accountCapsule = repository.getAccount(address); @@ -90,7 +91,7 @@ public static long[] queryFrozenBalanceUsage(byte[] address, long type, Reposito return repository.getAccountEnergyUsageBalanceAndRestoreSeconds(accountCapsule); } - return new long[]{0L, 0L}; + return Pair.of(0L, 0L); } private static long getTotalWithdrawUnfreeze(List unfrozenV2List, long time) { From 7eff1161b09d0230043399211586e6498bb8e301 Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 17 Oct 2022 11:04:54 +0800 Subject: [PATCH 0292/1197] fix(freezeV2): fix freezeV2 comments --- .../src/main/java/org/tron/core/vm/OperationActions.java | 3 +-- .../main/java/org/tron/core/vm/OperationRegistry.java | 6 +++--- .../vm/nativecontract/DelegateResourceProcessor.java | 4 ++-- .../core/vm/nativecontract/FreezeBalanceV2Processor.java | 2 +- .../vm/nativecontract/UnfreezeBalanceV2Processor.java | 9 ++++++--- .../src/main/java/org/tron/core/vm/program/Program.java | 1 - 6 files changed, 13 insertions(+), 12 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index 443a67f63eb..13585c24539 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -6,7 +6,6 @@ import java.math.BigInteger; import java.util.ArrayList; import java.util.List; - import org.tron.common.runtime.vm.DataWord; import org.tron.common.runtime.vm.LogInfo; import org.tron.core.vm.config.VMConfig; @@ -953,7 +952,7 @@ public static void staticCallAction(Program program) { } public static void exeCall(Program program, DataWord adjustedCallEnergy, - DataWord codeAddress, DataWord value, DataWord tokenId, boolean isTokenTransferMsg) { + DataWord codeAddress, DataWord value, DataWord tokenId, boolean isTokenTransferMsg) { DataWord inDataOffs = program.stackPop(); DataWord inDataSize = program.stackPop(); diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index 59747464bd4..7a736454146 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -57,12 +57,12 @@ public static JumpTable getTable() { // implement as needed // switch (tx.getType()) { // } - if (VMConfig.allowHigherLimitForMaxCpuTimeOfOneTx()) { - return tableMap.get(Version.TRON_V1_1); - } if (VMConfig.allowTvmFreezeV2()) { return tableMap.get(Version.TRON_V1_2); } + if (VMConfig.allowHigherLimitForMaxCpuTimeOfOneTx()) { + return tableMap.get(Version.TRON_V1_1); + } return tableMap.get(Version.TRON_V1_0); } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index e090cdfe303..17b8f1db4c0 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -107,7 +107,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra } } - public void execute(DelegateResourceParam param, Repository repo) { + public void execute(DelegateResourceParam param, Repository repo) { byte[] ownerAddress = param.getOwnerAddress(); AccountCapsule ownerCapsule = repo.getAccount(param.getOwnerAddress()); long delegateBalance = param.getDelegateBalance(); @@ -124,7 +124,7 @@ public void execute(DelegateResourceParam param, Repository repo) { break; case ENERGY: delegateResource(ownerAddress, receiverAddress, false, - delegateBalance,repo); + delegateBalance, repo); ownerCapsule.addDelegatedFrozenBalanceForEnergy(delegateBalance); ownerCapsule.addFrozenBalanceForEnergyV2(-delegateBalance); diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java index 349e6746e5e..1337a428f27 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java @@ -62,7 +62,7 @@ public void validate(FreezeBalanceV2Param param, Repository repo) throws Contrac } } - public void execute(FreezeBalanceV2Param param, Repository repo) { + public void execute(FreezeBalanceV2Param param, Repository repo) { DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); byte[] ownerAddress = param.getOwnerAddress(); diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index 93be714e62c..75f06245cbc 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -71,8 +71,11 @@ public void validate(UnfreezeBalanceV2Param param, Repository repo) } break; default: - throw new ContractValidateException("ResourceCode error." - + "valid ResourceCode[BANDWIDTH、Energy]"); + if (dynamicStore.supportAllowNewResourceModel()) { + throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、Energy、TRON_POWER]"); + } else { + throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + } } if (!checkUnfreezeBalance(accountCapsule, param.getUnfreezeBalance(), param.getResourceType())) { @@ -165,7 +168,7 @@ private void updateAccountFrozenInfo( List freezeV2List = accountCapsule.getFrozenV2List(); for (int i = 0; i < freezeV2List.size(); i++) { if (freezeV2List.get(i).getType().equals(freezeType)) { - Protocol.Account.FreezeV2 freezeV2 = Protocol.Account.FreezeV2.newBuilder() + Protocol.Account.FreezeV2 freezeV2 = Protocol.Account.FreezeV2.newBuilder() .setAmount(freezeV2List.get(i).getAmount() - unfreezeBalance) .setType(freezeV2List.get(i).getType()) .build(); diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index bcd94f89e67..85fd786c1bc 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -1399,7 +1399,6 @@ public void callToPrecompiledAddress(MessageCall msg, return; } - Repository deposit = getContractState().newRepositoryChild(); byte[] senderAddress = getContextAddress(); From 754d478c8d4b33151aa884dce5dc45ddaff870f4 Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 17 Oct 2022 11:22:50 +0800 Subject: [PATCH 0293/1197] fix(freezeV2): fix freezeV2 comments --- .../main/java/org/tron/core/vm/OperationRegistry.java | 3 +-- .../nativecontract/WithdrawExpireUnfreezeProcessor.java | 9 ++++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index 7a736454146..f9e4c650827 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -59,8 +59,7 @@ public static JumpTable getTable() { // } if (VMConfig.allowTvmFreezeV2()) { return tableMap.get(Version.TRON_V1_2); - } - if (VMConfig.allowHigherLimitForMaxCpuTimeOfOneTx()) { + } else if (VMConfig.allowHigherLimitForMaxCpuTimeOfOneTx()) { return tableMap.get(Version.TRON_V1_1); } return tableMap.get(Version.TRON_V1_0); diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java index b754fb2cc01..10ca7de5745 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java @@ -40,9 +40,10 @@ public void validate(WithdrawExpireUnfreezeParam param, Repository repo) throws } long now = dynamicStore.getLatestBlockHeaderTimestamp(); - List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); + List unfrozenV2List = accountCapsule.getInstance() + .getUnfrozenV2List(); long totalWithdrawUnfreeze = getTotalWithdrawUnfreeze(unfrozenV2List, now); - if (totalWithdrawUnfreeze <= 0) { + if (totalWithdrawUnfreeze < 0) { throw new ContractValidateException("no unFreeze balance to withdraw "); } try { @@ -66,11 +67,13 @@ private List getTotalWithdrawList(List unfrozenV2List = ownerCapsule.getInstance().getUnfrozenV2List(); long totalWithdrawUnfreeze = getTotalWithdrawUnfreeze(unfrozenV2List, now); + if (totalWithdrawUnfreeze <= 0) { + return 0; + } ownerCapsule.setInstance(ownerCapsule.getInstance().toBuilder() .setBalance(ownerCapsule.getBalance() + totalWithdrawUnfreeze) .setLatestWithdrawTime(now) From e935e2f71e2ddbff9132a6f9fee4e46036a51a13 Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 17 Oct 2022 11:24:37 +0800 Subject: [PATCH 0294/1197] func(tvm,freezev1): disable freeze v1 after v2 activated --- .../org/tron/core/vm/OperationActions.java | 16 ++++++++++++++- .../org/tron/core/vm/OperationRegistry.java | 20 ++++++++++--------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index 443a67f63eb..bf2ac3e8532 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -6,7 +6,6 @@ import java.math.BigInteger; import java.util.ArrayList; import java.util.List; - import org.tron.common.runtime.vm.DataWord; import org.tron.common.runtime.vm.LogInfo; import org.tron.core.vm.config.VMConfig; @@ -742,6 +741,21 @@ public static void freezeAction(Program program) { program.step(); } + public static void disabledFreezeAction(Program program) { + // after allow vote, check static + if (VMConfig.allowTvmVote() && program.isStaticCall()) { + throw new Program.StaticCallModificationException(); + } + // 0 as bandwidth, 1 as energy + DataWord ignoredResourceType = program.stackPop(); + DataWord ignoredFrozenBalance = program.stackPop(); + DataWord ignoredReceiverAddress = program.stackPop(); + + // here we just push zero to stack and do nothing + program.stackPush(DataWord.ZERO()); + program.step(); + } + public static void unfreezeAction(Program program) { if (VMConfig.allowTvmVote() && program.isStaticCall()) { throw new Program.StaticCallModificationException(); diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index 59747464bd4..dccfa8588c9 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -46,6 +46,7 @@ public static JumpTable newTronV12OperationSet() { JumpTable table = newTronV11OperationSet(); appendFreezeV2Operations(table); appendDelegateOperations(table); + disableFreezeOperation(table); return table; } @@ -579,29 +580,23 @@ public static void adjustMemOperations(JumpTable table) { } public static void appendFreezeV2Operations(JumpTable table) { - BooleanSupplier proposal = VMConfig::allowTvmFreeze; - table.set(new Operation( Op.FREEZEBALANCEV2, 2, 1, EnergyCost::getFreezeBalanceV2Cost, - OperationActions::freezeBalanceV2Action, - proposal)); + OperationActions::freezeBalanceV2Action)); table.set(new Operation( Op.UNFREEZEBALANCEV2, 2, 1, EnergyCost::getUnfreezeBalanceV2Cost, - OperationActions::unfreezeBalanceV2Action, - proposal)); + OperationActions::unfreezeBalanceV2Action)); table.set(new Operation( Op.WITHDRAWEXPIREUNFREEZE, 0, 1, EnergyCost::getWithdrawExpireUnfreezeCost, - OperationActions::withdrawExpireUnfreezeAction, - proposal)); + OperationActions::withdrawExpireUnfreezeAction)); } public static void appendDelegateOperations(JumpTable table) { - table.set(new Operation( Op.DELEGATERESOURCE, 3, 1, EnergyCost::getDelegateResourceCost, @@ -612,4 +607,11 @@ public static void appendDelegateOperations(JumpTable table) { EnergyCost::getUnDelegateResourceCost, OperationActions::unDelegateResourceAction)); } + + public static void disableFreezeOperation(JumpTable table) { + table.set(new Operation( + Op.FREEZE, 3, 1, + EnergyCost::getExtTierCost, + OperationActions::disabledFreezeAction)); + } } From d63c647d80f6eca77f8998f25dc31bd277eba309 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Mon, 17 Oct 2022 12:17:14 +0800 Subject: [PATCH 0295/1197] feat(freezeV2): add GetChainParameter precompileContract --- .../org/tron/core/vm/ChainParameterEnum.java | 45 +++++++++++++++++++ .../tron/core/vm/PrecompiledContracts.java | 12 ++++- 2 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 actuator/src/main/java/org/tron/core/vm/ChainParameterEnum.java diff --git a/actuator/src/main/java/org/tron/core/vm/ChainParameterEnum.java b/actuator/src/main/java/org/tron/core/vm/ChainParameterEnum.java new file mode 100644 index 00000000000..8fb6b5a9836 --- /dev/null +++ b/actuator/src/main/java/org/tron/core/vm/ChainParameterEnum.java @@ -0,0 +1,45 @@ +package org.tron.core.vm; + +import java.util.function.Function; + +import org.tron.core.store.DynamicPropertiesStore; + +public enum ChainParameterEnum { + + INVALID_PARAMETER_KEY(0, (any) -> 0L), + + TOTAL_ENERGY_CURRENT_LIMIT(1, DynamicPropertiesStore::getTotalEnergyCurrentLimit), + + TOTAL_ENERGY_WEIGHT(2, DynamicPropertiesStore::getTotalEnergyWeight), + + UNFREEZE_DELAY_DAYS(3, DynamicPropertiesStore::getUnfreezeDelayDays), + + ; + + private final long code; + + private final Function action; + + ChainParameterEnum(long code, Function action) { + this.code = code; + this.action = action; + } + + public static ChainParameterEnum fromCode(long code) { + for (ChainParameterEnum each : values()) { + if (each.code == code) { + return each; + } + } + + return INVALID_PARAMETER_KEY; + } + + public long getCode() { + return code; + } + + public Function getAction() { + return action; + } +} diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 96fd12f689e..eeddb4cbb71 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -1790,12 +1790,20 @@ public static class GetChainParameter extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { - return 0; + return 50; } @Override public Pair execute(byte[] data) { - return Pair.of(true, DataWord.ZERO().getData()); + if (data == null || data.length != WORD_SIZE) { + return Pair.of(true, DataWord.ZERO().getData()); + } + long code = new DataWord(data).longValueSafe(); + + long res = ChainParameterEnum.fromCode(code).getAction().apply( + getDeposit().getDynamicPropertiesStore()); + + return Pair.of(true, longTo32Bytes(res)); } } From c5a3403996783d1e75a749a9a75b871c6384fd7a Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 17 Oct 2022 14:27:32 +0800 Subject: [PATCH 0296/1197] fix(freezeV2): fix freezeV2 log --- actuator/src/main/java/org/tron/core/vm/program/Program.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 85fd786c1bc..60b9cb00cbe 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -1892,7 +1892,7 @@ public boolean unDelegateResource( repository.commit(); return true; } catch (ContractValidateException e) { - logger.error("TVM UnfreezeBalanceV2: validate failure. Reason: {}", e.getMessage()); + logger.error("TVM unDelegateResource: validate failure. Reason: {}", e.getMessage()); } if (internalTx != null) { internalTx.reject(); From ad2bc35112bcc870fb81910b8f6e3c613706c235 Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 17 Oct 2022 17:34:19 +0800 Subject: [PATCH 0297/1197] feat(freezeV2): freezeV2 update usage and suicide --- .../org/tron/core/actuator/VMActuator.java | 5 +++ .../org/tron/core/vm/program/Program.java | 38 ++++++++++++++++++- .../org/tron/core/capsule/ReceiptCapsule.java | 4 ++ .../org/tron/core/db/TransactionTrace.java | 2 + 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 84b31a9297e..dd9c3d62756 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -545,7 +545,9 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi long energyFromBalance = max(account.getBalance() - callValue, 0) / sunPerEnergy; long availableEnergy = Math.addExact(leftFrozenEnergy, energyFromBalance); + receipt.setCallerEnergyUsage(account.getEnergyUsage()); long energyFromFeeLimit = feeLimit / sunPerEnergy; + account.setEnergyUsage(min(leftFrozenEnergy, energyFromFeeLimit)); return min(availableEnergy, energyFromFeeLimit); } @@ -674,6 +676,7 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu if (VMConfig.allowTvmFreeze()) { receipt.setOriginEnergyLeft(originEnergyLeft); } + receipt.setOriginEnergyUsage(creator.getEnergyUsage()); } if (consumeUserResourcePercent <= 0) { creatorEnergyLimit = min(originEnergyLeft, originEnergyLimit); @@ -691,6 +694,8 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu ); } } + creator.setEnergyUsage(creator.getEnergyUsage() + creatorEnergyLimit); + return Math.addExact(callerEnergyLimit, creatorEnergyLimit); } diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 60b9cb00cbe..90e55892c03 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -8,7 +8,9 @@ import static org.apache.commons.lang3.ArrayUtils.isNotEmpty; import static org.apache.commons.lang3.ArrayUtils.nullToEmpty; import static org.tron.common.utils.ByteUtil.stripLeadingZeroes; +import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_MS; import com.google.protobuf.ByteString; import java.math.BigInteger; @@ -17,6 +19,7 @@ import java.util.Map; import java.util.Objects; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.map.LRUMap; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.tuple.Pair; @@ -31,6 +34,7 @@ import org.tron.common.utils.FastByteComparisons; import org.tron.common.utils.Utils; import org.tron.common.utils.WalletUtil; +import org.tron.core.ChainBaseManager; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.ContractCapsule; @@ -467,6 +471,14 @@ public void suicide(DataWord obtainerAddress) { transferDelegatedResourceToInheritor(owner, obtainer, getContractState()); } } + if (VMConfig.allowTvmFreezeV2()) { + byte[] blackHoleAddress = getContractState().getBlackHoleAddress(); + if (FastByteComparisons.isEqual(owner, obtainer)) { + transferDelegatedResourceToInheritorV2(owner, blackHoleAddress, getContractState()); + } else { + transferDelegatedResourceToInheritorV2(owner, obtainer, getContractState()); + } + } getResult().addDeleteAccount(this.getContractAddress()); } @@ -501,6 +513,14 @@ private void transferDelegatedResourceToInheritor(byte[] ownerAddr, byte[] inher repo.addBalance(inheritorAddr, frozenBalanceForBandwidthOfOwner + frozenBalanceForEnergyOfOwner); } + private void transferDelegatedResourceToInheritorV2(byte[] ownerAddr, byte[] inheritorAddr, Repository repo) { + AccountCapsule ownerCapsule = repo.getAccount(ownerAddr); + + // transfer owner`s frozen balance for bandwidth to inheritor + + // todo + } + private void withdrawRewardAndCancelVote(byte[] owner, Repository repo) { VoteRewardUtil.withdrawReward(owner, repo); @@ -533,9 +553,25 @@ private void withdrawRewardAndCancelVote(byte[] owner, Repository repo) { public boolean canSuicide() { byte[] owner = getContextAddress(); AccountCapsule accountCapsule = getContractState().getAccount(owner); - return !VMConfig.allowTvmFreeze() + + boolean freezeCheck = !VMConfig.allowTvmFreeze() || (accountCapsule.getDelegatedFrozenBalanceForBandwidth() == 0 && accountCapsule.getDelegatedFrozenBalanceForEnergy() == 0); + + long now = ChainBaseManager.getInstance().getHeadSlot(); + long oneDayTime = WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL; + boolean freezeV2Check = + !VMConfig.allowTvmFreezeV2() + || (accountCapsule.getDelegatedFrozenBalanceForBandwidth() == 0 + && accountCapsule.getDelegatedFrozenBalanceForEnergy() == 0 + && CollectionUtils.isEmpty(accountCapsule.getUnfrozenV2List()) + && (accountCapsule.getEnergyUsage() == 0 + || (accountCapsule.getEnergyUsage() > 0 + && (now - accountCapsule.getLatestConsumeTimeForEnergy() >= oneDayTime))) + && (accountCapsule.getNetUsage() == 0 + || (accountCapsule.getEnergyUsage() > 0 + && (now - accountCapsule.getLatestConsumeTime() >= oneDayTime)))); + return freezeCheck && freezeV2Check; // boolean voteCheck = !VMConfig.allowTvmVote() // || (accountCapsule.getVotesList().size() == 0 // && VoteRewardUtil.queryReward(owner, getContractState()) == 0 diff --git a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index 3124494c67e..f315176c2ba 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -36,6 +36,10 @@ public class ReceiptCapsule { @Setter private long callerEnergyLeft; + @Getter + @Setter + private long callerEnergyUsage; + private Sha256Hash receiptAddress; public ReceiptCapsule(ResourceReceipt data, Sha256Hash receiptAddress) { diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java index 6a74d6d015f..c58ca78316f 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java @@ -247,6 +247,8 @@ public void pay() throws BalanceInsufficientException { // originAccount Percent = 30% AccountCapsule origin = accountStore.get(originAccount); AccountCapsule caller = accountStore.get(callerAccount); + origin.setEnergyUsage(receipt.getOriginEnergyUsage()); + caller.setEnergyUsage(receipt.getCallerEnergyUsage()); receipt.payEnergyBill( dynamicPropertiesStore, accountStore, forkController, origin, From 612f7e84647525c85df0ddecf642bab4511de77f Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 17 Oct 2022 17:59:33 +0800 Subject: [PATCH 0298/1197] feat(freezeV2): suicide transfer freezeV2 balance --- .../org/tron/core/vm/program/Program.java | 24 ++++++++++++------- .../org/tron/core/capsule/AccountCapsule.java | 2 +- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 90e55892c03..b260bcee626 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -16,6 +16,7 @@ import java.math.BigInteger; import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Objects; import lombok.extern.slf4j.Slf4j; @@ -472,12 +473,11 @@ public void suicide(DataWord obtainerAddress) { } } if (VMConfig.allowTvmFreezeV2()) { - byte[] blackHoleAddress = getContractState().getBlackHoleAddress(); - if (FastByteComparisons.isEqual(owner, obtainer)) { - transferDelegatedResourceToInheritorV2(owner, blackHoleAddress, getContractState()); - } else { - transferDelegatedResourceToInheritorV2(owner, obtainer, getContractState()); - } + byte[] Inheritor = + FastByteComparisons.isEqual(owner, obtainer) + ? getContractState().getBlackHoleAddress() + : obtainer; + transferFrozenV2BalanceToInheritor(owner, Inheritor, getContractState()); } getResult().addDeleteAccount(this.getContractAddress()); } @@ -513,12 +513,18 @@ private void transferDelegatedResourceToInheritor(byte[] ownerAddr, byte[] inher repo.addBalance(inheritorAddr, frozenBalanceForBandwidthOfOwner + frozenBalanceForEnergyOfOwner); } - private void transferDelegatedResourceToInheritorV2(byte[] ownerAddr, byte[] inheritorAddr, Repository repo) { + private void transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inheritorAddr, Repository repo) { AccountCapsule ownerCapsule = repo.getAccount(ownerAddr); + AccountCapsule inheritorCapsule = repo.getAccount(inheritorAddr); - // transfer owner`s frozen balance for bandwidth to inheritor + ownerCapsule.getFrozenV2List().stream() + .filter(freezeV2 -> freezeV2.getAmount() > 0) + .forEach( + freezeV2 -> + inheritorCapsule.addFrozenBalanceForResource( + freezeV2.getType(), freezeV2.getAmount())); - // todo + repo.updateAccount(inheritorCapsule.createDbKey(), inheritorCapsule); } private void withdrawRewardAndCancelVote(byte[] owner, Repository repo) { diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index 919e7a411d8..17698e98600 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -453,7 +453,7 @@ public void addFrozenBalanceForEnergyV2(long balance) { this.addFrozenBalanceForResource(type, balance); } - private void addFrozenBalanceForResource(Common.ResourceCode type, long balance) { + public void addFrozenBalanceForResource(Common.ResourceCode type, long balance) { boolean doUpdate = false; for (int i = 0; i < this.account.getFrozenV2List().size(); i++) { if (this.account.getFrozenV2List().get(i).getType().equals(type)) { From 1bab55850c325ba0706881028c26505a9559b47c Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 17 Oct 2022 18:04:31 +0800 Subject: [PATCH 0299/1197] fix(freezeV2): fix can suicide check --- actuator/src/main/java/org/tron/core/vm/program/Program.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index b260bcee626..96b969a1738 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -575,7 +575,7 @@ public boolean canSuicide() { || (accountCapsule.getEnergyUsage() > 0 && (now - accountCapsule.getLatestConsumeTimeForEnergy() >= oneDayTime))) && (accountCapsule.getNetUsage() == 0 - || (accountCapsule.getEnergyUsage() > 0 + || (accountCapsule.getNetUsage() > 0 && (now - accountCapsule.getLatestConsumeTime() >= oneDayTime)))); return freezeCheck && freezeV2Check; // boolean voteCheck = !VMConfig.allowTvmVote() From f68f12f1f454d937d018cca65ab1b10077e09cc9 Mon Sep 17 00:00:00 2001 From: liukai Date: Tue, 18 Oct 2022 11:21:43 +0800 Subject: [PATCH 0300/1197] feat(shell): update start.sh 1. add backup gc log function --- start.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/start.sh b/start.sh index 809a2e8f0b3..fac6284bcc7 100644 --- a/start.sh +++ b/start.sh @@ -46,6 +46,7 @@ ALLOW_MIN_MEMORY=8192 MAX_DIRECT_MEMORY=1g JVM_MS=4g JVM_MX=4g +IS_BACKUP_GC_LOG=true SPECIFY_MEMORY=0 RUN=false @@ -113,6 +114,32 @@ if [ -z "$JAVA_HOME" ] ; then echo "Warning: JAVA_HOME environment variable is not set." fi +backupGCLog() { + local maxFile=5 + local gcLogDir=logs/gc_logs/ + if [ ! -d "$gcLogDir" ];then + mkdir -p 'logs/gc_logs' + fi + + if [ -f 'gc.log' ]; then + echo '[info] backup gc.log' + local dateformat=`date "+%Y-%m-%d_%H-%M-%S"` + tar -czvf gc.log_$dateformat'.tar.gz' gc.log + mv gc.log_$dateformat'.tar.gz' $gcLogDir + rm -rf gc.log + + # checking the number of backups + local currentDirCount=`ls -l $gcLogDir | grep "gc.log*" | wc -l` + if [ $currentDirCount -gt $maxFile ]; then + local oldFileSize=`expr $currentDirCount - $maxFile` + local oldGcLogFiles=(`ls -1 $gcLogDir |head -n $oldFileSize`) + fi + + for fileName in ${oldGcLogFiles[@]}; do + rm -rf $gcLogDir$fileName + done + fi +} getLatestReleaseVersion() { full_node_version=`git ls-remote --tags $GITHUB_REPOSITORY |grep GreatVoyage- | awk -F '/' 'END{print $3}'` @@ -553,6 +580,10 @@ while [ -n "$1" ]; do esac done +if [[ $IS_BACKUP_GC_LOG = true ]]; then + backupGCLog +fi + if [[ $CLONE_BUILD == true ]];then cloneBuild fi From 9e405bee35e9056f85b1698c3f622f174e974969 Mon Sep 17 00:00:00 2001 From: Liulei Date: Tue, 18 Oct 2022 12:04:35 +0800 Subject: [PATCH 0301/1197] feat(freezeV2): optimize freezeV2 processor via comments --- .../org/tron/core/actuator/VMActuator.java | 16 +++-- .../tron/core/vm/program/ContractState.java | 10 +++ .../org/tron/core/vm/program/Program.java | 62 ++++++++++++++----- .../tron/core/vm/repository/Repository.java | 4 ++ .../core/vm/repository/RepositoryImpl.java | 9 +++ .../org/tron/core/capsule/ReceiptCapsule.java | 3 +- 6 files changed, 85 insertions(+), 19 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index dd9c3d62756..0a765256979 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -545,9 +545,14 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi long energyFromBalance = max(account.getBalance() - callValue, 0) / sunPerEnergy; long availableEnergy = Math.addExact(leftFrozenEnergy, energyFromBalance); - receipt.setCallerEnergyUsage(account.getEnergyUsage()); long energyFromFeeLimit = feeLimit / sunPerEnergy; - account.setEnergyUsage(min(leftFrozenEnergy, energyFromFeeLimit)); + long newEnergyUsage = rootRepository.getAccountEnergyUsageFromFreeze(account); + long now = rootRepository.getHeadSlot(); + receipt.setCallerEnergyUsage(newEnergyUsage); + account.setEnergyUsage(newEnergyUsage + min(leftFrozenEnergy, energyFromFeeLimit)); + account.setLatestConsumeTimeForEnergy(now); + rootRepository.updateAccount(account.createDbKey(), account); + return min(availableEnergy, energyFromFeeLimit); } @@ -676,7 +681,6 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu if (VMConfig.allowTvmFreeze()) { receipt.setOriginEnergyLeft(originEnergyLeft); } - receipt.setOriginEnergyUsage(creator.getEnergyUsage()); } if (consumeUserResourcePercent <= 0) { creatorEnergyLimit = min(originEnergyLeft, originEnergyLimit); @@ -694,8 +698,12 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu ); } } + long newEnergyUsage = rootRepository.getAccountEnergyUsageFromFreeze(creator); + receipt.setOriginEnergyUsage(newEnergyUsage); + long now = rootRepository.getHeadSlot(); + creator.setLatestConsumeTimeForEnergy(now); creator.setEnergyUsage(creator.getEnergyUsage() + creatorEnergyLimit); - + rootRepository.updateAccount(creator.createDbKey(), creator); return Math.addExact(callerEnergyLimit, creatorEnergyLimit); } diff --git a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java index b19d663e8b4..f47e9250f76 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java +++ b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java @@ -223,6 +223,11 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { return repository.getAccountLeftEnergyFromFreeze(accountCapsule); } + @Override + public long getAccountEnergyUsageFromFreeze(AccountCapsule accountCapsule) { + return repository.getAccountEnergyUsageFromFreeze(accountCapsule); + } + @Override public Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { return repository.getAccountEnergyUsageBalanceAndRestoreSeconds(accountCapsule); @@ -358,4 +363,9 @@ public long getTotalEnergyWeight() { return repository.getTotalEnergyWeight(); } + @Override + public long getHeadSlot() { + return repository.getHeadSlot(); + } + } diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 96b969a1738..5cf1fa10419 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -16,9 +16,9 @@ import java.math.BigInteger; import java.util.Arrays; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.map.LRUMap; @@ -516,7 +516,9 @@ private void transferDelegatedResourceToInheritor(byte[] ownerAddr, byte[] inher private void transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inheritorAddr, Repository repo) { AccountCapsule ownerCapsule = repo.getAccount(ownerAddr); AccountCapsule inheritorCapsule = repo.getAccount(inheritorAddr); + long now = repo.getHeadSlot(); + // transfer frozen resource ownerCapsule.getFrozenV2List().stream() .filter(freezeV2 -> freezeV2.getAmount() > 0) .forEach( @@ -524,6 +526,18 @@ private void transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit inheritorCapsule.addFrozenBalanceForResource( freezeV2.getType(), freezeV2.getAmount())); + // withdraw expire unfrozen balance + long expireUnfrozenBalance = + ownerCapsule.getUnfrozenV2List().stream() + .filter( + unFreezeV2 -> + unFreezeV2.getUnfreezeAmount() > 0 && unFreezeV2.getUnfreezeExpireTime() <= now) + .mapToLong(Protocol.Account.UnFreezeV2::getUnfreezeAmount) + .sum(); + if (expireUnfrozenBalance > 0) { + inheritorCapsule.setBalance(inheritorCapsule.getBalance() + expireUnfrozenBalance); + } + repo.updateAccount(inheritorCapsule.createDbKey(), inheritorCapsule); } @@ -564,19 +578,7 @@ public boolean canSuicide() { || (accountCapsule.getDelegatedFrozenBalanceForBandwidth() == 0 && accountCapsule.getDelegatedFrozenBalanceForEnergy() == 0); - long now = ChainBaseManager.getInstance().getHeadSlot(); - long oneDayTime = WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL; - boolean freezeV2Check = - !VMConfig.allowTvmFreezeV2() - || (accountCapsule.getDelegatedFrozenBalanceForBandwidth() == 0 - && accountCapsule.getDelegatedFrozenBalanceForEnergy() == 0 - && CollectionUtils.isEmpty(accountCapsule.getUnfrozenV2List()) - && (accountCapsule.getEnergyUsage() == 0 - || (accountCapsule.getEnergyUsage() > 0 - && (now - accountCapsule.getLatestConsumeTimeForEnergy() >= oneDayTime))) - && (accountCapsule.getNetUsage() == 0 - || (accountCapsule.getNetUsage() > 0 - && (now - accountCapsule.getLatestConsumeTime() >= oneDayTime)))); + boolean freezeV2Check = freezeV2Check(accountCapsule); return freezeCheck && freezeV2Check; // boolean voteCheck = !VMConfig.allowTvmVote() // || (accountCapsule.getVotesList().size() == 0 @@ -586,6 +588,34 @@ public boolean canSuicide() { // return freezeCheck && voteCheck; } + private boolean freezeV2Check(AccountCapsule accountCapsule) { + long now = ChainBaseManager.getInstance().getHeadSlot(); + long oneDayTime = WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL; + + boolean isDelegatedResourceEmpty = + accountCapsule.getDelegatedFrozenBalanceForBandwidth() == 0 + && accountCapsule.getDelegatedFrozenBalanceForEnergy() == 0; + boolean isUnFrozenV2ListEmpty = + CollectionUtils.isEmpty( + accountCapsule.getUnfrozenV2List().stream() + .filter(unFreezeV2 -> unFreezeV2.getUnfreezeExpireTime() > now) + .collect(Collectors.toList())); + boolean isEnergyUsageEmpty = + accountCapsule.getEnergyUsage() == 0 + || (accountCapsule.getEnergyUsage() > 0 + && (now - accountCapsule.getLatestConsumeTimeForEnergy() >= oneDayTime)); + boolean isNetUsageEmpty = + accountCapsule.getNetUsage() == 0 + || (accountCapsule.getNetUsage() > 0 + && (now - accountCapsule.getLatestConsumeTime() >= oneDayTime)); + + return !VMConfig.allowTvmFreezeV2() + || (isDelegatedResourceEmpty + && isUnFrozenV2ListEmpty + && isEnergyUsageEmpty + && isNetUsageEmpty); + } + @SuppressWarnings("ThrowableResultOfMethodCallIgnored") public void createContract(DataWord value, DataWord memStart, DataWord memSize) { returnDataBuffer = null; // reset return buffer right before the call @@ -1838,6 +1868,8 @@ public boolean unfreezeBalanceV2(DataWord unfreezeBalance, DataWord resourceType return true; } catch (ContractValidateException e) { logger.error("TVM UnfreezeBalanceV2: validate failure. Reason: {}", e.getMessage()); + } catch (ArithmeticException e) { + logger.error("TVM UnfreezeBalanceV2: balance out of long range."); } if (internalTx != null) { internalTx.reject(); @@ -1935,6 +1967,8 @@ public boolean unDelegateResource( return true; } catch (ContractValidateException e) { logger.error("TVM unDelegateResource: validate failure. Reason: {}", e.getMessage()); + } catch (ArithmeticException e) { + logger.error("TVM unDelegateResource: balance out of long range."); } if (internalTx != null) { internalTx.reject(); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java index 9e9bdac8db6..7eb617e71ae 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java @@ -107,6 +107,8 @@ public interface Repository { long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule); + long getAccountEnergyUsageFromFreeze(AccountCapsule accountCapsule); + Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule); Pair getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule); @@ -133,4 +135,6 @@ public interface Repository { long getTotalEnergyWeight(); + long getHeadSlot(); + } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index a84f103146c..a607e79789b 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -171,6 +171,15 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { return max(energyLimit - newEnergyUsage, 0); // us } + @Override + public long getAccountEnergyUsageFromFreeze(AccountCapsule accountCapsule) { + long now = getHeadSlot(); + long energyUsage = accountCapsule.getEnergyUsage(); + long latestConsumeTime = accountCapsule.getAccountResource().getLatestConsumeTimeForEnergy(); + + return increase(energyUsage, 0, latestConsumeTime, now); + } + public Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { long now = getHeadSlot(); diff --git a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index f315176c2ba..b0debe0f80b 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -185,7 +185,8 @@ private void payEnergyBill( EnergyProcessor energyProcessor, long now) throws BalanceInsufficientException { long accountEnergyLeft; - if (dynamicPropertiesStore.getAllowTvmFreeze() == 1) { + if (dynamicPropertiesStore.getAllowTvmFreeze() == 1 + || dynamicPropertiesStore.getUnfreezeDelayDays() > 0) { accountEnergyLeft = callerEnergyLeft; } else { accountEnergyLeft = energyProcessor.getAccountLeftEnergyFromFreeze(account); From bbe74d5ef5d54355140f1cbc979303b00077b1cc Mon Sep 17 00:00:00 2001 From: Liulei Date: Tue, 18 Oct 2022 14:41:02 +0800 Subject: [PATCH 0302/1197] feat(freezeV2): optimize freezeV2 processor error message --- .../vm/nativecontract/UnDelegateResourceProcessor.java | 4 ++-- .../vm/nativecontract/UnfreezeBalanceV2Processor.java | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index f336abd6e6a..e440c6218a9 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -79,13 +79,13 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont break; case ENERGY: if (delegatedResourceCapsule.getFrozenBalanceForEnergy() < unDelegateBalance) { - throw new ContractValidateException("insufficient delegateFrozenBalance(Energy), request=" + throw new ContractValidateException("insufficient delegateFrozenBalance(ENERGY), request=" + unDelegateBalance + ", balance=" + delegatedResourceCapsule.getFrozenBalanceForEnergy()); } break; default: throw new ContractValidateException( - "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + "ResourceCode error.valid ResourceCode[BANDWIDTH、ENERGY]"); } } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index 75f06245cbc..a372f6f89d6 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -58,23 +58,23 @@ public void validate(UnfreezeBalanceV2Param param, Repository repo) case ENERGY: // validate frozen balance if (!this.checkExistFrozenBalance(accountCapsule, Common.ResourceCode.ENERGY)) { - throw new ContractValidateException("no frozenBalance(Energy)"); + throw new ContractValidateException("no frozenBalance(ENERGY)"); } break; case TRON_POWER: if (dynamicStore.supportAllowNewResourceModel()) { if (!this.checkExistFrozenBalance(accountCapsule, Common.ResourceCode.TRON_POWER)) { - throw new ContractValidateException("no frozenBalance(TronPower)"); + throw new ContractValidateException("no frozenBalance(TRON_POWER)"); } } else { - throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、ENERGY]"); } break; default: if (dynamicStore.supportAllowNewResourceModel()) { - throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、Energy、TRON_POWER]"); + throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、ENERGY、TRON_POWER]"); } else { - throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、ENERGY]"); } } From 04979344dfbe7960a5d902f087c3caba4b6c99f0 Mon Sep 17 00:00:00 2001 From: Asuka Date: Tue, 18 Oct 2022 15:16:15 +0800 Subject: [PATCH 0303/1197] fix(tvm,jump-table): the logic to modify the instruction should be independent --- .../org/tron/core/vm/OperationRegistry.java | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index d082e5c9b91..f6122b131c6 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -37,16 +37,13 @@ public static JumpTable newTronV10OperationSet() { } public static JumpTable newTronV11OperationSet() { - JumpTable table = newTronV10OperationSet(); - adjustMemOperations(table); - return table; + return newTronV10OperationSet(); } public static JumpTable newTronV12OperationSet() { JumpTable table = newTronV11OperationSet(); appendFreezeV2Operations(table); appendDelegateOperations(table); - disableFreezeOperation(table); return table; } @@ -55,15 +52,18 @@ public static void init() { } public static JumpTable getTable() { - // implement as needed - // switch (tx.getType()) { - // } + // always get the table which has the newest version + JumpTable table = tableMap.get(Version.TRON_V1_2); + + // next make the corresponding changes, exclude activating opcode + if (VMConfig.allowHigherLimitForMaxCpuTimeOfOneTx()) { + adjustMemOperations(table); + } if (VMConfig.allowTvmFreezeV2()) { - return tableMap.get(Version.TRON_V1_2); - } else if (VMConfig.allowHigherLimitForMaxCpuTimeOfOneTx()) { - return tableMap.get(Version.TRON_V1_1); + disableFreezeOperation(table); } - return tableMap.get(Version.TRON_V1_0); + + return table; } public static JumpTable newBaseOperationSet() { @@ -579,38 +579,48 @@ public static void adjustMemOperations(JumpTable table) { } public static void appendFreezeV2Operations(JumpTable table) { + BooleanSupplier proposal = VMConfig::allowTvmFreezeV2; + table.set(new Operation( Op.FREEZEBALANCEV2, 2, 1, EnergyCost::getFreezeBalanceV2Cost, - OperationActions::freezeBalanceV2Action)); + OperationActions::freezeBalanceV2Action, + proposal)); table.set(new Operation( Op.UNFREEZEBALANCEV2, 2, 1, EnergyCost::getUnfreezeBalanceV2Cost, - OperationActions::unfreezeBalanceV2Action)); + OperationActions::unfreezeBalanceV2Action, + proposal)); table.set(new Operation( Op.WITHDRAWEXPIREUNFREEZE, 0, 1, EnergyCost::getWithdrawExpireUnfreezeCost, - OperationActions::withdrawExpireUnfreezeAction)); + OperationActions::withdrawExpireUnfreezeAction, + proposal)); } public static void appendDelegateOperations(JumpTable table) { + BooleanSupplier proposal = VMConfig::allowTvmFreezeV2; + table.set(new Operation( Op.DELEGATERESOURCE, 3, 1, EnergyCost::getDelegateResourceCost, - OperationActions::delegateResourceAction)); + OperationActions::delegateResourceAction, + proposal)); table.set(new Operation( Op.UNDELEGATERESOURCE, 3, 1, EnergyCost::getUnDelegateResourceCost, - OperationActions::unDelegateResourceAction)); + OperationActions::unDelegateResourceAction, + proposal)); } public static void disableFreezeOperation(JumpTable table) { table.set(new Operation( Op.FREEZE, 3, 1, EnergyCost::getExtTierCost, - OperationActions::disabledFreezeAction)); + OperationActions::disabledFreezeAction, + VMConfig::allowTvmFreeze)); } } From cd2779b26bcae8e5ba88ce62d7db01a1de664c1d Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Thu, 13 Oct 2022 17:54:43 +0800 Subject: [PATCH 0304/1197] feat(freezeV2): optimize usage merging Signed-off-by: liuxincheng --- .../actuator/DelegateResourceActuator.java | 2 +- .../core/actuator/FreezeBalanceActuator.java | 2 +- .../actuator/FreezeBalanceV2Actuator.java | 2 +- .../actuator/UnDelegateResourceActuator.java | 26 +++++--- .../actuator/UnfreezeBalanceV2Actuator.java | 2 +- .../WithdrawExpireUnfreezeActuator.java | 2 +- .../org/tron/core/capsule/AccountCapsule.java | 37 +++++++++++ .../org/tron/core/db/BandwidthProcessor.java | 20 ++++-- .../org/tron/core/db/EnergyProcessor.java | 12 ++-- .../org/tron/core/db/ResourceProcessor.java | 64 +++++++++++++++++++ .../core/store/DynamicPropertiesStore.java | 4 ++ .../tron/common/runtime/vm/FreezeTest.java | 5 ++ .../DelegateResourceActuatorTest.java | 2 + .../actuator/FreezeBalanceV2ActuatorTest.java | 8 +-- .../UnDelegateResourceActuatorTest.java | 2 + .../UnfreezeBalanceV2ActuatorTest.java | 6 +- .../WithdrawExpireUnfreezeActuatorTest.java | 4 +- protocol/src/main/protos/core/Tron.proto | 3 + 18 files changed, 168 insertions(+), 35 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 46aeb77e40b..8abe753b6a2 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -109,7 +109,7 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("No support for resource delegate"); } - if (dynamicStore.getUnfreezeDelayDays() == 0) { + if (!dynamicStore.supportUnfreezeDelay()) { throw new ContractValidateException("Not support Delegate resource transaction," + " need to be opened by the committee"); } diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java index e194999a25f..5d630d0f115 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java @@ -249,7 +249,7 @@ public boolean validate() throws ContractValidateException { } - if (dynamicStore.getUnfreezeDelayDays() > 0) { + if (dynamicStore.supportUnfreezeDelay()) { throw new ContractValidateException( "freeze v2 is open, old freeze is closed"); } diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java index 60981f00588..3d4a8c8fae7 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java @@ -96,7 +96,7 @@ public boolean validate() throws ContractValidateException { .getClass() + "]"); } - if (dynamicStore.getUnfreezeDelayDays() == 0) { + if (!dynamicStore.supportUnfreezeDelay()) { throw new ContractValidateException("Not support FreezeV2 transaction," + " need to be opened by the committee"); } diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index 414b9e44dc1..6926d0d060f 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -2,6 +2,8 @@ import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; @@ -135,10 +137,13 @@ public boolean execute(Object result) throws ContractExeException { ownerCapsule.addFrozenBalanceForBandwidthV2(unDelegateBalance); BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); - processor.updateUsage(ownerCapsule); - long newNetUsage = ownerCapsule.getNetUsage() + transferUsage; - ownerCapsule.setNetUsage(newNetUsage); - ownerCapsule.setLatestConsumeTime(chainBaseManager.getHeadSlot()); + + long now = chainBaseManager.getHeadSlot(); + if (Objects.nonNull(receiverCapsule) && transferUsage > 0) { + ownerCapsule.setNetUsage(processor.unDelegateIncrease(ownerCapsule, receiverCapsule, + transferUsage, BANDWIDTH, now)); + ownerCapsule.setLatestConsumeTime(now); + } } break; case ENERGY: { @@ -148,10 +153,13 @@ public boolean execute(Object result) throws ContractExeException { ownerCapsule.addFrozenBalanceForEnergyV2(unDelegateBalance); EnergyProcessor processor = new EnergyProcessor(dynamicStore, accountStore); - processor.updateUsage(ownerCapsule); - long newEnergyUsage = ownerCapsule.getEnergyUsage() + transferUsage; - ownerCapsule.setEnergyUsage(newEnergyUsage); - ownerCapsule.setLatestConsumeTimeForEnergy(chainBaseManager.getHeadSlot()); + + long now = chainBaseManager.getHeadSlot(); + if (Objects.nonNull(receiverCapsule) && transferUsage > 0) { + ownerCapsule.setEnergyUsage(processor.unDelegateIncrease(ownerCapsule, receiverCapsule, + transferUsage, ENERGY, now)); + ownerCapsule.setLatestConsumeTimeForEnergy(now); + } } break; default: @@ -215,7 +223,7 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("No support for resource delegate"); } - if (dynamicStore.getUnfreezeDelayDays() == 0) { + if (!dynamicStore.supportUnfreezeDelay()) { throw new ContractValidateException("Not support Delegate resource transaction," + " need to be opened by the committee"); } diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java index c4edbf6d957..bcc64f2121c 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java @@ -109,7 +109,7 @@ public boolean validate() throws ContractValidateException { .getClass() + "]"); } - if (dynamicStore.getUnfreezeDelayDays() == 0) { + if (!dynamicStore.supportUnfreezeDelay()) { throw new ContractValidateException("Not support UnfreezeV2 transaction," + " need to be opened by the committee"); } diff --git a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java index 11b991585f6..57b6668ff66 100755 --- a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java @@ -81,7 +81,7 @@ public boolean validate() throws ContractValidateException { .getClass() + "]"); } - if (dynamicStore.getUnfreezeDelayDays() == 0) { + if (!dynamicStore.supportUnfreezeDelay()) { throw new ContractValidateException("Not support WithdrawExpireUnfreeze transaction," + " need to be opened by the committee"); } diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index 919e7a411d8..684d582ade8 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -43,9 +43,12 @@ import java.util.Map; import java.util.Objects; +import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; +import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_MS; import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; +import static org.tron.protos.contract.Common.ResourceCode; @Slf4j(topic = "capsule") public class AccountCapsule implements ProtoCapsule, Comparable { @@ -969,6 +972,14 @@ public long getNetUsage() { return this.account.getNetUsage(); } + public long getUsage(ResourceCode resourceCode) { + if (resourceCode == BANDWIDTH) { + return this.account.getNetUsage(); + } else { + return this.account.getAccountResource().getEnergyUsage(); + } + } + public void setNetUsage(long netUsage) { this.account = this.account.toBuilder() .setNetUsage(netUsage).build(); @@ -1262,4 +1273,30 @@ public void clearUnfrozenV2() { this.account = this.account.toBuilder().clearUnfrozenV2().build(); } + public void setNewWindowSize(ResourceCode resourceCode, long newWindowSize) { + if (resourceCode == BANDWIDTH) { + this.account = this.account.toBuilder().setNetWindowSize(newWindowSize).build(); + } else { + this.account = this.account.toBuilder().setAccountResource(this.account.getAccountResource() + .toBuilder().setEnergyWindowSize(newWindowSize).build()).build(); + } + } + + public long getWindowSize(ResourceCode resourceCode) { + long windowSize; + if (resourceCode == BANDWIDTH) { + windowSize = this.account.getNetWindowSize(); + } else { + windowSize = this.account.getAccountResource().getEnergyWindowSize(); + } + return windowSize == 0 ? WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL : windowSize; + } + + public long getLastConsumeTime(ResourceCode resourceCode) { + if (resourceCode == BANDWIDTH) { + return this.account.getLatestConsumeTime(); + } else { + return this.account.getAccountResource().getLatestConsumeTimeForEnergy(); + } + } } diff --git a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java index e39865e95ed..324e3bbf5ac 100644 --- a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -23,6 +23,8 @@ import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; import org.tron.protos.contract.BalanceContract.TransferContract; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; + @Slf4j(topic = "DB") public class BandwidthProcessor extends ResourceProcessor { @@ -42,7 +44,8 @@ public void updateUsage(AccountCapsule accountCapsule) { private void updateUsage(AccountCapsule accountCapsule, long now) { long oldNetUsage = accountCapsule.getNetUsage(); long latestConsumeTime = accountCapsule.getLatestConsumeTime(); - accountCapsule.setNetUsage(increase(oldNetUsage, 0, latestConsumeTime, now)); + accountCapsule.setNetUsage(increase(accountCapsule, BANDWIDTH, + oldNetUsage, 0, latestConsumeTime, now)); long oldFreeNetUsage = accountCapsule.getFreeNetUsage(); long latestConsumeFreeTime = accountCapsule.getLatestConsumeFreeTime(); accountCapsule.setFreeNetUsage(increase(oldFreeNetUsage, 0, latestConsumeFreeTime, now)); @@ -183,13 +186,14 @@ public boolean consumeBandwidthForCreateNewAccount(AccountCapsule accountCapsule long netUsage = accountCapsule.getNetUsage(); long latestConsumeTime = accountCapsule.getLatestConsumeTime(); long netLimit = calculateGlobalNetLimit(accountCapsule); - long newNetUsage = increase(netUsage, 0, latestConsumeTime, now); + long newNetUsage = increase(accountCapsule, BANDWIDTH, netUsage, 0, latestConsumeTime, now); long netCost = bytes * createNewAccountBandwidthRatio; if (netCost <= (netLimit - newNetUsage)) { latestConsumeTime = now; long latestOperationTime = chainBaseManager.getHeadBlockTimeStamp(); - newNetUsage = increase(newNetUsage, netCost, latestConsumeTime, now); + newNetUsage = increase(accountCapsule, BANDWIDTH, + newNetUsage, netCost, latestConsumeTime, now); accountCapsule.setLatestConsumeTime(latestConsumeTime); accountCapsule.setLatestOperationTime(latestOperationTime); accountCapsule.setNetUsage(newNetUsage); @@ -313,7 +317,8 @@ private boolean useAssetAccountNet(Contract contract, AccountCapsule accountCaps long latestConsumeTime = issuerAccountCapsule.getLatestConsumeTime(); long issuerNetLimit = calculateGlobalNetLimit(issuerAccountCapsule); - long newIssuerNetUsage = increase(issuerNetUsage, 0, latestConsumeTime, now); + long newIssuerNetUsage = increase(issuerAccountCapsule, BANDWIDTH, + issuerNetUsage, 0, latestConsumeTime, now); if (bytes > (issuerNetLimit - newIssuerNetUsage)) { logger.debug("The " + tokenID + " issuer's bandwidth is not enough"); @@ -325,7 +330,8 @@ private boolean useAssetAccountNet(Contract contract, AccountCapsule accountCaps publicLatestFreeNetTime = now; long latestOperationTime = chainBaseManager.getHeadBlockTimeStamp(); - newIssuerNetUsage = increase(newIssuerNetUsage, bytes, latestConsumeTime, now); + newIssuerNetUsage = increase(issuerAccountCapsule, BANDWIDTH, + newIssuerNetUsage, bytes, latestConsumeTime, now); newFreeAssetNetUsage = increase(newFreeAssetNetUsage, bytes, latestAssetOperationTime, now); newPublicFreeAssetNetUsage = increase(newPublicFreeAssetNetUsage, bytes, @@ -390,7 +396,7 @@ private boolean useAccountNet(AccountCapsule accountCapsule, long bytes, long no long latestConsumeTime = accountCapsule.getLatestConsumeTime(); long netLimit = calculateGlobalNetLimit(accountCapsule); - long newNetUsage = increase(netUsage, 0, latestConsumeTime, now); + long newNetUsage = increase(accountCapsule, BANDWIDTH, netUsage, 0, latestConsumeTime, now); if (bytes > (netLimit - newNetUsage)) { logger.debug("net usage is running out, now use free net usage"); @@ -399,7 +405,7 @@ private boolean useAccountNet(AccountCapsule accountCapsule, long bytes, long no latestConsumeTime = now; long latestOperationTime = chainBaseManager.getHeadBlockTimeStamp(); - newNetUsage = increase(newNetUsage, bytes, latestConsumeTime, now); + newNetUsage = increase(accountCapsule, BANDWIDTH, newNetUsage, bytes, latestConsumeTime, now); accountCapsule.setNetUsage(newNetUsage); accountCapsule.setLatestOperationTime(latestOperationTime); accountCapsule.setLatestConsumeTime(latestConsumeTime); diff --git a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java index ff95f9058f1..20e2c94b2d2 100644 --- a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java @@ -15,6 +15,8 @@ import org.tron.core.store.DynamicPropertiesStore; import org.tron.protos.Protocol.Account.AccountResource; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; + @Slf4j(topic = "DB") public class EnergyProcessor extends ResourceProcessor { @@ -41,7 +43,8 @@ private void updateUsage(AccountCapsule accountCapsule, long now) { long oldEnergyUsage = accountResource.getEnergyUsage(); long latestConsumeTime = accountResource.getLatestConsumeTimeForEnergy(); - accountCapsule.setEnergyUsage(increase(oldEnergyUsage, 0, latestConsumeTime, now)); + accountCapsule.setEnergyUsage(increase(accountCapsule, ENERGY, + oldEnergyUsage, 0, latestConsumeTime, now)); } public void updateTotalEnergyAverageUsage() { @@ -101,7 +104,7 @@ public boolean useEnergy(AccountCapsule accountCapsule, long energy, long now) { long latestConsumeTime = accountCapsule.getAccountResource().getLatestConsumeTimeForEnergy(); long energyLimit = calculateGlobalEnergyLimit(accountCapsule); - long newEnergyUsage = increase(energyUsage, 0, latestConsumeTime, now); + long newEnergyUsage = increase(accountCapsule, ENERGY, energyUsage, 0, latestConsumeTime, now); if (energy > (energyLimit - newEnergyUsage) && dynamicPropertiesStore.getAllowTvmFreeze() == 0) { @@ -110,7 +113,8 @@ public boolean useEnergy(AccountCapsule accountCapsule, long energy, long now) { latestConsumeTime = now; long latestOperationTime = dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); - newEnergyUsage = increase(newEnergyUsage, energy, latestConsumeTime, now); + newEnergyUsage = increase(accountCapsule, ENERGY, + newEnergyUsage, energy, latestConsumeTime, now); accountCapsule.setEnergyUsage(newEnergyUsage); accountCapsule.setLatestOperationTime(latestOperationTime); accountCapsule.setLatestConsumeTimeForEnergy(latestConsumeTime); @@ -146,7 +150,7 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { long latestConsumeTime = accountCapsule.getAccountResource().getLatestConsumeTimeForEnergy(); long energyLimit = calculateGlobalEnergyLimit(accountCapsule); - long newEnergyUsage = increase(energyUsage, 0, latestConsumeTime, now); + long newEnergyUsage = increase(accountCapsule, ENERGY, energyUsage, 0, latestConsumeTime, now); return max(energyLimit - newEnergyUsage, 0); // us } diff --git a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java index 09bac96e0ae..e9aa35f696e 100644 --- a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java @@ -13,6 +13,7 @@ import org.tron.core.exception.TooBigTransactionResultException; import org.tron.core.store.AccountStore; import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.contract.Common.ResourceCode; abstract class ResourceProcessor { @@ -59,6 +60,69 @@ protected long increase(long lastUsage, long usage, long lastTime, long now, lon return getUsage(averageLastUsage, windowSize); } + protected long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, + long lastUsage, long usage, long lastTime, long now) { + long oldWindowSize = accountCapsule.getWindowSize(resourceCode); + /* old logic */ + long averageLastUsage = divideCeil(lastUsage * this.precision, oldWindowSize); + long averageUsage = divideCeil(usage * this.precision, this.windowSize); + + if (lastTime != now) { + assert now > lastTime; + if (lastTime + oldWindowSize > now) { + long delta = now - lastTime; + double decay = (oldWindowSize - delta) / (double) oldWindowSize; + averageLastUsage = Math.round(averageLastUsage * decay); + } else { + averageLastUsage = 0; + } + } + /* new logic */ + long newUsage = getUsage(averageLastUsage, oldWindowSize) + + getUsage(averageUsage, this.windowSize); + if (dynamicPropertiesStore.supportUnfreezeDelay()) { + long remainUsage = getUsage(averageLastUsage, oldWindowSize); + if (remainUsage == 0) { + accountCapsule.setNewWindowSize(resourceCode, this.windowSize); + return newUsage; + } + long remainWindowSize = oldWindowSize - (now - lastTime); + long newWindowSize = (remainWindowSize * remainUsage + this.windowSize * usage) + / newUsage; + accountCapsule.setNewWindowSize(resourceCode, newWindowSize); + } + return newUsage; + } + + public long unDelegateIncrease(AccountCapsule owner, AccountCapsule receiver, + long transferUsage, ResourceCode resourceCode, long now) { + long lastOwnerTime = owner.getLastConsumeTime(resourceCode); + long lastReceiverTime = receiver.getLastConsumeTime(resourceCode); + long ownerWindowSize = owner.getWindowSize(resourceCode); + long receiverWindowSize = receiver.getWindowSize(resourceCode); + long ownerUsage = owner.getUsage(resourceCode); + // Update itself first + ownerUsage = increase(owner, resourceCode, ownerUsage, 0, lastOwnerTime, now); + + long remainOwnerWindowSize = ownerWindowSize - (now - lastOwnerTime); + long remainReceiverWindowSize = receiverWindowSize - (now - lastReceiverTime); + remainOwnerWindowSize = remainOwnerWindowSize < 0 ? 0 : remainOwnerWindowSize; + remainReceiverWindowSize = remainReceiverWindowSize < 0 ? 0 : remainReceiverWindowSize; + + long newOwnerUsage = ownerUsage + transferUsage; + // mean ownerUsage == 0 and transferUsage == 0 + if (newOwnerUsage == 0) { + owner.setNewWindowSize(resourceCode, this.windowSize); + return newOwnerUsage; + } + // calculate new windowSize + long newOwnerWindowSize = (ownerUsage * remainOwnerWindowSize + + transferUsage * remainReceiverWindowSize) + / newOwnerUsage; + owner.setNewWindowSize(resourceCode, newOwnerWindowSize); + return newOwnerUsage; + } + private long divideCeil(long numerator, long denominator) { return (numerator / denominator) + ((numerator % denominator) > 0 ? 1 : 0); } diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index b523ed7527c..1c12ac47767 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -2533,6 +2533,10 @@ public long getUnfreezeDelayDays() { .orElseThrow(() -> new IllegalArgumentException("not found UNFREEZE_DELAY_DAYS")); } + public boolean supportUnfreezeDelay() { + return getUnfreezeDelayDays() > 0; + } + public void saveUnfreezeDelayDays(long value) { this.put(UNFREEZE_DELAY_DAYS, new BytesCapsule(ByteArray.fromLong(value))); } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java index 60e7a3ffa9c..ba5456080e7 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java @@ -4,6 +4,7 @@ import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import static org.tron.protos.Protocol.Transaction.Result.contractResult.REVERT; import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import com.google.protobuf.ByteString; import java.io.File; @@ -798,7 +799,9 @@ private TVMTestResult freezeForOther(byte[] callerAddr, if (oldReceiver != null) { newReceiver.setBalance(oldReceiver.getBalance()); oldReceiver.setEnergyUsage(0); + oldReceiver.setNewWindowSize(ENERGY, 28800); newReceiver.setEnergyUsage(0); + newReceiver.setNewWindowSize(ENERGY,28800); if (res == 0) { oldReceiver.setAcquiredDelegatedFrozenBalanceForBandwidth(0); newReceiver.setAcquiredDelegatedFrozenBalanceForBandwidth(0); @@ -912,7 +915,9 @@ private TVMTestResult unfreezeForOther(byte[] callerAddr, || acquiredBalance - newAcquiredBalance == delegatedFrozenBalance); newReceiver.setBalance(oldReceiver.getBalance()); newReceiver.setEnergyUsage(0); + newReceiver.setNewWindowSize(ENERGY,28800); oldReceiver.setEnergyUsage(0); + oldReceiver.setNewWindowSize(ENERGY,28800); if (res == 0) { oldReceiver.setAcquiredDelegatedFrozenBalanceForBandwidth(0); newReceiver.setAcquiredDelegatedFrozenBalanceForBandwidth(0); diff --git a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java index 6bfd885dc46..e76d979cd1f 100644 --- a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java @@ -59,6 +59,8 @@ public class DelegateResourceActuatorTest { @BeforeClass public static void init() { dbManager = context.getBean(Manager.class); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); } /** diff --git a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java index 87708196143..1296886637d 100644 --- a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java @@ -61,10 +61,8 @@ public class FreezeBalanceV2ActuatorTest { @BeforeClass public static void init() { dbManager = context.getBean(Manager.class); - // Args.setParam(new String[]{"--output-directory", dbPath}, - // "config-junit.conf"); - // dbManager = new Manager(); - // dbManager.init(); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); } /** @@ -369,6 +367,7 @@ public void testFreezeBalanceForEnergyWithoutOldTronPowerAfterNewResourceModel() long frozenBalance = 1_000_000_000L; FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); ChainBaseManager chainBaseManager = dbManager.getChainBaseManager(); + chainBaseManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); chainBaseManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); actuator.setChainBaseManager(chainBaseManager) .setAny(getContractForCpuV2(OWNER_ADDRESS, frozenBalance)); @@ -396,6 +395,7 @@ public void testFreezeBalanceForEnergyWithOldTronPowerAfterNewResourceModel() { long duration = 3; FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); ChainBaseManager chainBaseManager = dbManager.getChainBaseManager(); + chainBaseManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); chainBaseManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); actuator.setChainBaseManager(chainBaseManager) .setAny(getContractForCpuV2(OWNER_ADDRESS, frozenBalance)); diff --git a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java index c235de57a3a..8ac20aa5e66 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java @@ -61,6 +61,8 @@ public class UnDelegateResourceActuatorTest { @BeforeClass public static void init() { dbManager = context.getBean(Manager.class); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); } /** diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java index f174dbb782f..004a9476ff1 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java @@ -64,10 +64,8 @@ public class UnfreezeBalanceV2ActuatorTest { @BeforeClass public static void init() { dbManager = context.getBean(Manager.class); - // Args.setParam(new String[]{"--output-directory", dbPath}, - // "config-junit.conf"); - // dbManager = new Manager(); - // dbManager.init(); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); } /** diff --git a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java index e9dc144b0d1..52b075a1454 100644 --- a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java @@ -15,10 +15,8 @@ import org.junit.BeforeClass; import org.junit.Test; import org.tron.common.application.TronApplicationContext; -import org.tron.common.args.Witness; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; -import org.tron.common.utils.StringUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; @@ -62,6 +60,8 @@ public class WithdrawExpireUnfreezeActuatorTest { @BeforeClass public static void init() { dbManager = context.getBean(Manager.class); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); } /** diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 194a0d95a74..67427214477 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -192,6 +192,8 @@ message Account { // the identity of this account, case insensitive bytes account_id = 23; + int64 net_window_size = 24; + message AccountResource { // energy resource, get from frozen int64 energy_usage = 1; @@ -209,6 +211,7 @@ message Account { int64 storage_usage = 7; int64 latest_exchange_storage_time = 8; + int64 energy_window_size = 9; } AccountResource account_resource = 26; bytes codeHash = 30; From 3aaf0c8cd3d295e04c8260a84af78838ff0da85f Mon Sep 17 00:00:00 2001 From: Asuka Date: Wed, 19 Oct 2022 11:12:13 +0800 Subject: [PATCH 0305/1197] fix(test): low probability of failure for some uint tests --- .../runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java | 3 ++- .../test/java/org/tron/common/runtime/vm/OperationsTest.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java index f378c01bceb..68fa9e12fa7 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java @@ -86,7 +86,8 @@ public class BandWidthRuntimeOutOfTimeWithCheckTest { "--output-directory", dbPath, "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory, - "-w" + "-w", + "--debug" }, "config-test-mainnet.conf" ); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java index fe0b2cef0d6..765a8b6222c 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java @@ -317,7 +317,8 @@ public void testCryptographicAndEnvironmentalOperations() throws ContractValidat program = new Program(op, op, invoke, interTrx);; testOperations(program); Assert.assertEquals(2, program.getResult().getEnergyUsed()); - Assert.assertEquals(invoke.getContractAddress(), program.getStack().pop()); + Assert.assertArrayEquals(invoke.getContractAddress().getLast20Bytes(), + program.getStack().pop().getLast20Bytes()); // test ORIGIN = 0x32 op = new byte[]{0x32}; From 034a3d3dc46b93b4045d57e14210763c59241c28 Mon Sep 17 00:00:00 2001 From: Liulei Date: Wed, 19 Oct 2022 15:08:54 +0800 Subject: [PATCH 0306/1197] feat(freezeV2): optimize freezeV2 processor via code review --- .../java/org/tron/core/vm/EnergyCost.java | 5 ++ .../src/main/java/org/tron/core/vm/Op.java | 1 + .../org/tron/core/vm/OperationActions.java | 10 +++ .../org/tron/core/vm/OperationRegistry.java | 6 ++ .../CancelUnfreezeProcessor.java | 82 +++++++++++++++++++ .../DelegateResourceProcessor.java | 12 ++- .../param/CancelUnfreezeParam.java | 14 ++++ .../tron/core/vm/program/ContractState.java | 6 ++ .../org/tron/core/vm/program/Program.java | 72 ++++++++++++---- .../tron/core/vm/repository/Repository.java | 4 + .../core/vm/repository/RepositoryImpl.java | 40 +++++++++ 11 files changed, 231 insertions(+), 21 deletions(-) create mode 100644 actuator/src/main/java/org/tron/core/vm/nativecontract/CancelUnfreezeProcessor.java create mode 100644 actuator/src/main/java/org/tron/core/vm/nativecontract/param/CancelUnfreezeParam.java diff --git a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java index 73490b3fd98..5f44cadfe77 100644 --- a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java +++ b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java @@ -39,6 +39,7 @@ public class EnergyCost { private static final long FREEZE_V2 = 20000; private static final long UNFREEZE_V2 = 20000; private static final long WITHDRAW_EXPIRE_UNFREEZE = 20000; + private static final long CANCEL_UNFREEZE = 20000; private static final long DELEGATE_RESOURCE = 20000; private static final long UN_DELEGATE_RESOURCE = 20000; private static final long VOTE_WITNESS = 30000; @@ -289,6 +290,10 @@ public static long getWithdrawExpireUnfreezeCost(Program ignored) { return WITHDRAW_EXPIRE_UNFREEZE; } + public static long getCancelUnfreezeCost(Program ignored) { + return CANCEL_UNFREEZE; + } + public static long getDelegateResourceCost(Program program) { Stack stack = program.getStack(); DataWord receiverAddressWord = stack.get(stack.size() - 3); diff --git a/actuator/src/main/java/org/tron/core/vm/Op.java b/actuator/src/main/java/org/tron/core/vm/Op.java index cd34c4dc4ae..31be9b19ed0 100644 --- a/actuator/src/main/java/org/tron/core/vm/Op.java +++ b/actuator/src/main/java/org/tron/core/vm/Op.java @@ -241,6 +241,7 @@ public class Op { public static final int WITHDRAWEXPIREUNFREEZE = 0xdc; public static final int DELEGATERESOURCE = 0xdd; public static final int UNDELEGATERESOURCE = 0xde; + public static final int CANCELUNFREEZE = 0xdf; // (0xf0) Create a new account with associated code public static final int CREATE = 0xf0; diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index 7b37814f481..83fabe311b1 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -814,6 +814,16 @@ public static void withdrawExpireUnfreezeAction(Program program) { program.step(); } + public static void cancelUnfreezeAction(Program program) { + if (program.isStaticCall()) { + throw new Program.StaticCallModificationException(); + } + + boolean result = program.cancelUnfreezeAction(); + program.stackPush(result ? DataWord.ONE() : DataWord.ZERO()); + program.step(); + } + public static void delegateResourceAction(Program program) { if (program.isStaticCall()) { throw new Program.StaticCallModificationException(); diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index f6122b131c6..93caa0e00e2 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -598,6 +598,12 @@ public static void appendFreezeV2Operations(JumpTable table) { EnergyCost::getWithdrawExpireUnfreezeCost, OperationActions::withdrawExpireUnfreezeAction, proposal)); + + table.set(new Operation( + Op.CANCELUNFREEZE, 0, 1, + EnergyCost::getCancelUnfreezeCost, + OperationActions::cancelUnfreezeAction, + proposal)); } public static void appendDelegateOperations(JumpTable table) { diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelUnfreezeProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelUnfreezeProcessor.java new file mode 100644 index 00000000000..fd4655c9cc8 --- /dev/null +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelUnfreezeProcessor.java @@ -0,0 +1,82 @@ +package org.tron.core.vm.nativecontract; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import lombok.extern.slf4j.Slf4j; +import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.vm.nativecontract.param.CancelUnfreezeParam; +import org.tron.core.vm.repository.Repository; +import org.tron.protos.Protocol; + +@Slf4j(topic = "VMProcessor") +public class CancelUnfreezeProcessor { + + public void validate(CancelUnfreezeParam param, Repository repo) throws ContractValidateException { + if (repo == null) { + throw new ContractValidateException(STORE_NOT_EXIST); + } + + byte[] ownerAddress = param.getOwnerAddress(); + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + AccountCapsule accountCapsule = repo.getAccount(ownerAddress); + if (Objects.isNull(accountCapsule)) { + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + throw new ContractValidateException(ACCOUNT_EXCEPTION_STR + + readableOwnerAddress + NOT_EXIST_STR); + } + } + + public void execute(CancelUnfreezeParam param, Repository repo) throws ContractExeException { + byte[] ownerAddress = param.getOwnerAddress(); + AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); + long now = repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); + List unfrozenV2List = + new ArrayList<>(ownerCapsule.getUnfrozenV2List()); + ownerCapsule.clearUnfrozenV2(); + for (Protocol.Account.UnFreezeV2 unFreezeV2: unfrozenV2List) { + if (unFreezeV2.getUnfreezeExpireTime() > now) { + updateFrozenInfoAndTotalResourceWeight(ownerCapsule, unFreezeV2, repo); + } else { + ownerCapsule.addUnfrozenV2(unFreezeV2); + } + } + + repo.updateAccount(ownerCapsule.createDbKey(), ownerCapsule); + } + + public void updateFrozenInfoAndTotalResourceWeight( + AccountCapsule accountCapsule, Protocol.Account.UnFreezeV2 unFreezeV2, Repository repo) { + DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); + switch (unFreezeV2.getType()) { + case BANDWIDTH: + accountCapsule.addFrozenBalanceForBandwidthV2(unFreezeV2.getUnfreezeAmount()); + dynamicStore.addTotalNetWeight(unFreezeV2.getUnfreezeAmount() / TRX_PRECISION); + break; + case ENERGY: + accountCapsule.addFrozenBalanceForEnergyV2(unFreezeV2.getUnfreezeAmount()); + dynamicStore.addTotalEnergyWeight(unFreezeV2.getUnfreezeAmount() / TRX_PRECISION); + break; + case TRON_POWER: + accountCapsule.addFrozenForTronPowerV2(unFreezeV2.getUnfreezeAmount()); + dynamicStore.addTotalTronPowerWeight(unFreezeV2.getUnfreezeAmount() / TRX_PRECISION); + break; + default: + // this should never happen + break; + } + } +} diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index 17b8f1db4c0..7a88a0e6116 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -53,8 +53,10 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra case BANDWIDTH: { BandwidthProcessor processor = new BandwidthProcessor(ChainBaseManager.getInstance()); processor.updateUsage(ownerCapsule); - //The unit is trx - long netTrxUsage = (long) (ownerCapsule.getNetUsage() + // The unit is trx + double netUsageRatio = (double) ownerCapsule.getFrozenV2BalanceForBandwidth() + / ownerCapsule.getAllFrozenBalanceForBandwidth(); + long netTrxUsage = (long) (ownerCapsule.getNetUsage() * netUsageRatio * ((double) (repo.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); if (ownerCapsule.getFrozenV2BalanceForBandwidth() - netTrxUsage * TRX_PRECISION @@ -69,8 +71,10 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra new EnergyProcessor(dynamicStore, ChainBaseManager.getInstance().getAccountStore()); processor.updateUsage(ownerCapsule); - //The unit is trx - long energyTrxUsage = (long) (ownerCapsule.getEnergyUsage() + // The unit is trx + double energyUsageRatio = (double) ownerCapsule.getFrozenV2BalanceForEnergy() + / ownerCapsule.getAllFrozenBalanceForEnergy(); + long energyTrxUsage = (long) (ownerCapsule.getEnergyUsage() * energyUsageRatio * ((double) (repo.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); if (ownerCapsule.getFrozenV2BalanceForEnergy() - energyTrxUsage * TRX_PRECISION diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/CancelUnfreezeParam.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/CancelUnfreezeParam.java new file mode 100644 index 00000000000..12f774a044b --- /dev/null +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/CancelUnfreezeParam.java @@ -0,0 +1,14 @@ +package org.tron.core.vm.nativecontract.param; + +public class CancelUnfreezeParam { + + private byte[] ownerAddress; + + public byte[] getOwnerAddress() { + return ownerAddress; + } + + public void setOwnerAddress(byte[] ownerAddress) { + this.ownerAddress = ownerAddress; + } +} diff --git a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java index f47e9250f76..ec3cdce5a1f 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java +++ b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java @@ -21,6 +21,7 @@ import org.tron.core.vm.repository.Repository; import org.tron.core.vm.repository.Value; import org.tron.protos.Protocol.AccountType; +import org.tron.protos.contract.Common; public class ContractState implements Repository, ProgramListenerAware { @@ -228,6 +229,11 @@ public long getAccountEnergyUsageFromFreeze(AccountCapsule accountCapsule) { return repository.getAccountEnergyUsageFromFreeze(accountCapsule); } + @Override + public long increaseV2(AccountCapsule accountCapsule, Common.ResourceCode resourceCode, long lastUsage, long usage, long lastTime, long now) { + return repository.increaseV2(accountCapsule, resourceCode, lastUsage, usage, lastTime, now); + } + @Override public Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { return repository.getAccountEnergyUsageBalanceAndRestoreSeconds(accountCapsule); diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 5cf1fa10419..a4565e1af6f 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -8,9 +8,7 @@ import static org.apache.commons.lang3.ArrayUtils.isNotEmpty; import static org.apache.commons.lang3.ArrayUtils.nullToEmpty; import static org.tron.common.utils.ByteUtil.stripLeadingZeroes; -import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; -import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_MS; import com.google.protobuf.ByteString; import java.math.BigInteger; @@ -55,6 +53,7 @@ import org.tron.core.vm.VMConstant; import org.tron.core.vm.VMUtils; import org.tron.core.vm.config.VMConfig; +import org.tron.core.vm.nativecontract.CancelUnfreezeProcessor; import org.tron.core.vm.nativecontract.DelegateResourceProcessor; import org.tron.core.vm.nativecontract.FreezeBalanceProcessor; import org.tron.core.vm.nativecontract.FreezeBalanceV2Processor; @@ -64,6 +63,7 @@ import org.tron.core.vm.nativecontract.VoteWitnessProcessor; import org.tron.core.vm.nativecontract.WithdrawExpireUnfreezeProcessor; import org.tron.core.vm.nativecontract.WithdrawRewardProcessor; +import org.tron.core.vm.nativecontract.param.CancelUnfreezeParam; import org.tron.core.vm.nativecontract.param.DelegateResourceParam; import org.tron.core.vm.nativecontract.param.FreezeBalanceParam; import org.tron.core.vm.nativecontract.param.FreezeBalanceV2Param; @@ -526,6 +526,26 @@ private void transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit inheritorCapsule.addFrozenBalanceForResource( freezeV2.getType(), freezeV2.getAmount())); + // merge usage + long newNetUsage = + repo.increaseV2( + inheritorCapsule, + Common.ResourceCode.BANDWIDTH, + inheritorCapsule.getNetUsage(), + ownerCapsule.getNetUsage(), + inheritorCapsule.getLatestConsumeTime(), + now); + inheritorCapsule.setNetUsage(newNetUsage); + long newEnergyUsage = + repo.increaseV2( + inheritorCapsule, + Common.ResourceCode.ENERGY, + inheritorCapsule.getEnergyUsage(), + ownerCapsule.getEnergyUsage(), + inheritorCapsule.getLatestConsumeTimeForEnergy(), + now); + inheritorCapsule.setEnergyUsage(newEnergyUsage); + // withdraw expire unfrozen balance long expireUnfrozenBalance = ownerCapsule.getUnfrozenV2List().stream() @@ -589,8 +609,10 @@ public boolean canSuicide() { } private boolean freezeV2Check(AccountCapsule accountCapsule) { + if (!VMConfig.allowTvmFreezeV2()) { + return true; + } long now = ChainBaseManager.getInstance().getHeadSlot(); - long oneDayTime = WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL; boolean isDelegatedResourceEmpty = accountCapsule.getDelegatedFrozenBalanceForBandwidth() == 0 @@ -600,20 +622,8 @@ private boolean freezeV2Check(AccountCapsule accountCapsule) { accountCapsule.getUnfrozenV2List().stream() .filter(unFreezeV2 -> unFreezeV2.getUnfreezeExpireTime() > now) .collect(Collectors.toList())); - boolean isEnergyUsageEmpty = - accountCapsule.getEnergyUsage() == 0 - || (accountCapsule.getEnergyUsage() > 0 - && (now - accountCapsule.getLatestConsumeTimeForEnergy() >= oneDayTime)); - boolean isNetUsageEmpty = - accountCapsule.getNetUsage() == 0 - || (accountCapsule.getNetUsage() > 0 - && (now - accountCapsule.getLatestConsumeTime() >= oneDayTime)); - - return !VMConfig.allowTvmFreezeV2() - || (isDelegatedResourceEmpty - && isUnFrozenV2ListEmpty - && isEnergyUsageEmpty - && isNetUsageEmpty); + + return isDelegatedResourceEmpty && isUnFrozenV2ListEmpty; } @SuppressWarnings("ThrowableResultOfMethodCallIgnored") @@ -1908,6 +1918,34 @@ public long withdrawExpireUnfreeze() { return 0; } + public boolean cancelUnfreezeAction() { + Repository repository = getContractState().newRepositoryChild(); + byte[] owner = getContextAddress(); + + increaseNonce(); + InternalTransaction internalTx = addInternalTx(null, owner, owner, 0, null, + "cancelUnfreeze", nonce, null); + + try { + CancelUnfreezeParam param = new CancelUnfreezeParam(); + param.setOwnerAddress(owner); + + CancelUnfreezeProcessor processor = new CancelUnfreezeProcessor(); + processor.validate(param, repository); + processor.execute(param, repository); + repository.commit(); + return true; + } catch (ContractValidateException e) { + logger.error("TVM cancelUnfreezeV2Action: validate failure. Reason: {}", e.getMessage()); + } catch (ContractExeException e) { + logger.error("TVM cancelUnfreezeV2Action: execute failure. Reason: {}", e.getMessage()); + } + if (internalTx != null) { + internalTx.reject(); + } + return false; + } + public boolean delegateResource( DataWord receiverAddress, DataWord delegateBalance, DataWord resourceType) { Repository repository = getContractState().newRepositoryChild(); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java index 7eb617e71ae..7e076901b37 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java @@ -6,6 +6,7 @@ import org.tron.core.store.*; import org.tron.core.vm.program.Storage; import org.tron.protos.Protocol; +import org.tron.protos.contract.Common; public interface Repository { @@ -109,6 +110,9 @@ public interface Repository { long getAccountEnergyUsageFromFreeze(AccountCapsule accountCapsule); + long increaseV2(AccountCapsule accountCapsule, Common.ResourceCode resourceCode, + long lastUsage, long usage, long lastTime, long now); + Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule); Pair getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index a607e79789b..866605cafab 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -63,6 +63,7 @@ import org.tron.protos.Protocol.DelegatedResource; import org.tron.protos.Protocol.Votes; import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; +import org.tron.protos.contract.Common; import org.tron.protos.contract.SmartContractOuterClass.SmartContract; @Slf4j(topic = "Repository") @@ -180,6 +181,45 @@ public long getAccountEnergyUsageFromFreeze(AccountCapsule accountCapsule) { return increase(energyUsage, 0, latestConsumeTime, now); } + public long increaseV2( + AccountCapsule accountCapsule, + Common.ResourceCode resourceCode, + long lastUsage, + long usage, + long lastTime, + long now) { + long oldWindowSize = accountCapsule.getWindowSize(resourceCode); + /* old logic */ + long averageLastUsage = divideCeil(lastUsage * this.precision, oldWindowSize); + long averageUsage = divideCeil(usage * this.precision, this.windowSize); + + if (lastTime != now) { + assert now > lastTime; + if (lastTime + oldWindowSize > now) { + long delta = now - lastTime; + double decay = (oldWindowSize - delta) / (double) oldWindowSize; + averageLastUsage = Math.round(averageLastUsage * decay); + } else { + averageLastUsage = 0; + } + } + /* new logic */ + long newUsage = getUsage(averageLastUsage, oldWindowSize) + + getUsage(averageUsage, this.windowSize); + if (dynamicPropertiesStore.supportUnfreezeDelay()) { + long remainUsage = getUsage(averageLastUsage, oldWindowSize); + if (remainUsage == 0) { + accountCapsule.setNewWindowSize(resourceCode, this.windowSize); + return newUsage; + } + long remainWindowSize = oldWindowSize - (now - lastTime); + long newWindowSize = (remainWindowSize * remainUsage + this.windowSize * usage) + / newUsage; + accountCapsule.setNewWindowSize(resourceCode, newWindowSize); + } + return newUsage; + } + public Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { long now = getHeadSlot(); From 53cd00d9dc4786387270ecbad8d0305cc2fec9df Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Wed, 19 Oct 2022 15:17:57 +0800 Subject: [PATCH 0307/1197] feat(freezeV2): temporary add freezeV2 PrecompileContracts --- .../tron/core/vm/PrecompiledContracts.java | 156 ++++++++++++++++-- .../UnfreezeBalanceV2Processor.java | 3 + .../tron/core/vm/program/ContractState.java | 5 + .../tron/core/vm/repository/Repository.java | 2 + .../core/vm/repository/RepositoryImpl.java | 38 ++++- .../org/tron/core/vm/utils/FreezeV2Util.java | 140 +++++++++++++++- .../runtime/vm/PrecompiledContractsTest.java | 110 +++++++++++- 7 files changed, 421 insertions(+), 33 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index eeddb4cbb71..006d868da26 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -35,6 +35,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.lang3.tuple.Triple; import org.tron.common.crypto.Blake2bfMessageDigest; import org.tron.common.crypto.Hash; import org.tron.common.crypto.SignUtils; @@ -101,9 +102,15 @@ public class PrecompiledContracts { private static final GetChainParameter getChainParameter = new GetChainParameter(); private static final ExpireFreezeV2Balance expireFreezeV2Balance = new ExpireFreezeV2Balance(); - private static final TotalFrozenBalance totalFrozenBalance = new TotalFrozenBalance(); - private static final FrozenBalance frozenBalance = new FrozenBalance(); - private static final FrozenBalanceUsage frozenBalanceUsage = new FrozenBalanceUsage(); + private static final TotalFrozenBalanceV2 totalFrozenBalanceV2 = new TotalFrozenBalanceV2(); + private static final ResourceV2 resourceV2 = new ResourceV2(); + private static final ResourceUsage resourceUsage = new ResourceUsage(); + + private static final AvailableUnfreezeV2Size availableUnfreezeSize = new AvailableUnfreezeV2Size(); + + private static final DelegatableResource delegatableResource = new DelegatableResource(); + + private static final CheckDelegatedResource checkDelegatedResource = new CheckDelegatedResource(); private static final DataWord ecRecoverAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000000000001"); @@ -152,15 +159,34 @@ public class PrecompiledContracts { private static final DataWord expireFreezeV2BalanceAddr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000c"); - private static final DataWord totalFrozenBalanceAddr = new DataWord( + private static final DataWord totalFrozenBalanceV2Addr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000d"); - private static final DataWord frozenBalanceAddr = new DataWord( + private static final DataWord resourceV2Addr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000e"); - private static final DataWord fronzenBalanceUsageAddr = new DataWord( + private static final DataWord resourceUsageAddr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000f"); + private static final DataWord availableUnfreezeSizeAddr = new DataWord( + "0000000000000000000000000000000000000000000000000000000001000010"); + + private static final DataWord delegatableResourceAddr = new DataWord( + "0000000000000000000000000000000000000000000000000000000001000011"); + + private static final DataWord totalResourceAddr = new DataWord( + "0000000000000000000000000000000000000000000000000000000001000012"); + + private static final DataWord totalDelegatedResourceAddr = new DataWord( + "0000000000000000000000000000000000000000000000000000000001000013"); + + private static final DataWord totalAcquiredResourceAddr = new DataWord( + "0000000000000000000000000000000000000000000000000000000001000014"); + + private static final DataWord checkDelegatedResourceAddr = new DataWord( + "0000000000000000000000000000000000000000000000000000000001000015"); + + private static final DataWord ethRipemd160Addr = new DataWord( "0000000000000000000000000000000000000000000000000000000000020003"); private static final DataWord blake2FAddr = new DataWord( @@ -247,15 +273,25 @@ public static PrecompiledContract getContractForAddress(DataWord address) { if (address.equals(expireFreezeV2BalanceAddr)) { return expireFreezeV2Balance; } - if (address.equals(totalFrozenBalanceAddr)) { - return totalFrozenBalance; + if (address.equals(totalFrozenBalanceV2Addr)) { + return totalFrozenBalanceV2; } - if (address.equals(frozenBalanceAddr)) { - return frozenBalance; + if (address.equals(resourceV2Addr)) { + return resourceV2; } - if (address.equals(fronzenBalanceUsageAddr)) { - return frozenBalanceUsage; + if (address.equals(resourceUsageAddr)) { + return resourceUsage; } + if (address.equals(availableUnfreezeSizeAddr)) { + return availableUnfreezeSize; + } + if (address.equals(delegatableResourceAddr)) { + return delegatableResource; + } + if (address.equals(checkDelegatedResourceAddr)) { + return checkDelegatedResource; + } + } return null; @@ -274,6 +310,25 @@ private static byte[] encodeRes(byte[] w1, byte[] w2) { return res; } + private static byte[] encodeMultiRes(byte[]... words) { + if (words == null) { + return null; + } + if (words.length == 1) { + return words[0]; + } + + byte[] res = new byte[words.length * 32]; + + for (int i = 0; i < words.length; i++) { + byte[] word = stripLeadingZeroes(words[i]); + + System.arraycopy(word, 0, res, 32 * (i + 1) - word.length, word.length); + } + + return res; + } + private static byte[] recoverAddrBySign(byte[] sign, byte[] hash) { byte v; byte[] r; @@ -1838,7 +1893,7 @@ public Pair execute(byte[] data) { } } - public static class TotalFrozenBalance extends PrecompiledContract { + public static class TotalFrozenBalanceV2 extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { @@ -1855,12 +1910,12 @@ public Pair execute(byte[] data) { byte[] address = words[0].toTronAddress(); long type = words[1].longValueSafe(); - long balance = FreezeV2Util.queryTotalFrozenBalance(address, type, getDeposit()); + long balance = FreezeV2Util.queryTotalFrozenBalanceV2(address, type, getDeposit()); return Pair.of(true, longTo32Bytes(balance)); } } - public static class FrozenBalance extends PrecompiledContract { + public static class ResourceV2 extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { @@ -1883,7 +1938,7 @@ public Pair execute(byte[] data) { } } - public static class FrozenBalanceUsage extends PrecompiledContract { + public static class ResourceUsage extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { @@ -1909,4 +1964,73 @@ public Pair execute(byte[] data) { } } + public static class AvailableUnfreezeV2Size extends PrecompiledContract { + + @Override + public long getEnergyForData(byte[] data) { + return 100; + } + + @Override + public Pair execute(byte[] data) { + if (data == null || data.length != WORD_SIZE) { + return Pair.of(true, DataWord.ZERO().getData()); + } + + byte[] address = new DataWord(data).toTronAddress(); + + long result = FreezeV2Util.queryAvailableUnfreezeV2Size(address, getDeposit()); + return Pair.of(true, longTo32Bytes(result)); + } + } + + public static class DelegatableResource extends PrecompiledContract { + + @Override + public long getEnergyForData(byte[] data) { + return 100; + } + + @Override + public Pair execute(byte[] data) { + if (data == null || data.length != 2 * WORD_SIZE) { + return Pair.of(true, DataWord.ZERO().getData()); + } + + DataWord[] words = DataWord.parseArray(data); + byte[] address = words[0].toTronAddress(); + long type = words[1].longValueSafe(); + + long result = FreezeV2Util.queryDelegatableResource(address, type, getDeposit()); + return Pair.of(true, longTo32Bytes(result)); + } + } + + public static class CheckDelegatedResource extends PrecompiledContract { + + @Override + public long getEnergyForData(byte[] data) { + return 100; + } + + @Override + public Pair execute(byte[] data) { + if (data == null || data.length != 3 * WORD_SIZE) { + return Pair.of(true, encodeMultiRes(DataWord.ZERO().getData(), DataWord.ZERO().getData(), DataWord.ZERO().getData())); + } + + DataWord[] words = DataWord.parseArray(data); + byte[] target = words[0].toTronAddress(); + long amount = words[1].longValueSafe(); + long type = words[2].longValueSafe(); + + Triple values = FreezeV2Util.checkUndelegateResource(target, amount, type, getDeposit()); + if (values == null || values.getLeft() == null || values.getMiddle() == null || values.getRight() == null) { + return Pair.of(true, encodeMultiRes(DataWord.ZERO().getData(), DataWord.ZERO().getData(), DataWord.ZERO().getData())); + } + + return Pair.of(true, encodeMultiRes(longTo32Bytes(values.getLeft()), longTo32Bytes(values.getMiddle()), longTo32Bytes(values.getRight()))); + } + } + } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index a372f6f89d6..4d43450cdf0 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -9,6 +9,8 @@ import com.google.protobuf.ByteString; import java.util.Iterator; import java.util.List; + +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; @@ -24,6 +26,7 @@ @Slf4j(topic = "VMProcessor") public class UnfreezeBalanceV2Processor { + @Getter private static final int UNFREEZE_MAX_TIMES = 16; public void validate(UnfreezeBalanceV2Param param, Repository repo) diff --git a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java index ec3cdce5a1f..b7211cfc92f 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java +++ b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java @@ -234,6 +234,11 @@ public long increaseV2(AccountCapsule accountCapsule, Common.ResourceCode resour return repository.increaseV2(accountCapsule, resourceCode, lastUsage, usage, lastTime, now); } + @Override + public long getAccountNetUsageFromFreeze(AccountCapsule accountCapsule) { + return repository.getAccountNetUsageFromFreeze(accountCapsule); + } + @Override public Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { return repository.getAccountEnergyUsageBalanceAndRestoreSeconds(accountCapsule); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java index 7e076901b37..ee296bd4449 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java @@ -113,6 +113,8 @@ public interface Repository { long increaseV2(AccountCapsule accountCapsule, Common.ResourceCode resourceCode, long lastUsage, long usage, long lastTime, long now); + long getAccountNetUsageFromFreeze(AccountCapsule accountCapsule); + Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule); Pair getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 866605cafab..c2aba02c390 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -167,7 +167,9 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { long latestConsumeTime = accountCapsule.getAccountResource().getLatestConsumeTimeForEnergy(); long energyLimit = calculateGlobalEnergyLimit(accountCapsule); - long newEnergyUsage = increase(energyUsage, 0, latestConsumeTime, now); + long windowSize = accountCapsule.getWindowSize(Common.ResourceCode.ENERGY); + + long newEnergyUsage = recover(energyUsage, latestConsumeTime, now, windowSize); return max(energyLimit - newEnergyUsage, 0); // us } @@ -178,7 +180,20 @@ public long getAccountEnergyUsageFromFreeze(AccountCapsule accountCapsule) { long energyUsage = accountCapsule.getEnergyUsage(); long latestConsumeTime = accountCapsule.getAccountResource().getLatestConsumeTimeForEnergy(); - return increase(energyUsage, 0, latestConsumeTime, now); + long accountWindowSize = accountCapsule.getWindowSize(Common.ResourceCode.ENERGY); + + return recover(energyUsage, latestConsumeTime, now, accountWindowSize); + } + + @Override + public long getAccountNetUsageFromFreeze(AccountCapsule accountCapsule) { + long now = getHeadSlot(); + long netUsage = accountCapsule.getNetUsage(); + long latestConsumeTime = accountCapsule.getLatestConsumeTime(); + + long accountWindowSize = accountCapsule.getWindowSize(Common.ResourceCode.BANDWIDTH); + + return recover(netUsage, latestConsumeTime, now, accountWindowSize); } public long increaseV2( @@ -225,14 +240,15 @@ public Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCap long energyUsage = accountCapsule.getEnergyUsage(); long latestConsumeTime = accountCapsule.getAccountResource().getLatestConsumeTimeForEnergy(); + long accountWindowSize = accountCapsule.getWindowSize(Common.ResourceCode.ENERGY); - if (now >= latestConsumeTime + windowSize) { + if (now >= latestConsumeTime + accountWindowSize) { return Pair.of(0L, 0L); } - long restoreSlots = latestConsumeTime + windowSize - now; + long restoreSlots = latestConsumeTime + accountWindowSize - now; - long newEnergyUsage = increase(energyUsage, 0, latestConsumeTime, now); + long newEnergyUsage = recover(energyUsage, latestConsumeTime, now, accountWindowSize); long totalEnergyLimit = getDynamicPropertiesStore().getTotalEnergyCurrentLimit(); long totalEnergyWeight = getTotalEnergyWeight(); @@ -247,14 +263,15 @@ public Pair getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsul long netUsage = accountCapsule.getNetUsage(); long latestConsumeTime = accountCapsule.getLatestConsumeTime(); + long accountWindowSize = accountCapsule.getWindowSize(Common.ResourceCode.BANDWIDTH); - if (now >= latestConsumeTime + windowSize) { + if (now >= latestConsumeTime + accountWindowSize) { return Pair.of(0L, 0L); } - long restoreSlots = latestConsumeTime + windowSize - now; + long restoreSlots = latestConsumeTime + accountWindowSize - now; - long newNetUsage = increase(netUsage, 0, latestConsumeTime, now); + long newNetUsage = recover(netUsage, latestConsumeTime, now, accountWindowSize); long totalNetLimit = getDynamicPropertiesStore().getTotalNetLimit(); long totalNetWeight = getTotalNetWeight(); @@ -783,6 +800,11 @@ private long increase(long lastUsage, long usage, long lastTime, long now) { return increase(lastUsage, usage, lastTime, now, windowSize); } + // new recover method, use personal window size. + private long recover(long lastUsage, long lastTime, long now, long personalWindowSize) { + return increase(lastUsage, 0, lastTime, now, personalWindowSize); + } + private long increase(long lastUsage, long usage, long lastTime, long now, long windowSize) { long averageLastUsage = divideCeil(lastUsage * precision, windowSize); long averageUsage = divideCeil(usage * precision, windowSize); diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index 0ebdf21e2a4..1ab85396a23 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -4,9 +4,12 @@ import java.util.stream.Collectors; import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.lang3.tuple.Triple; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; +import org.tron.core.db.EnergyProcessor; import org.tron.core.vm.config.VMConfig; +import org.tron.core.vm.nativecontract.UnfreezeBalanceV2Processor; import org.tron.core.vm.repository.Repository; import org.tron.protos.Protocol; @@ -21,33 +24,39 @@ public static long queryExpireFreezeV2Balance(byte[] address, long time, Reposit } AccountCapsule accountCapsule = repository.getAccount(address); + if (accountCapsule == null) { + return 0; + } + List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); return getTotalWithdrawUnfreeze(unfrozenV2List, time); } - // v1 included. - public static long queryTotalFrozenBalance(byte[] address, long type, Repository repository) { + public static long queryTotalFrozenBalanceV2(byte[] address, long type, Repository repository) { if (!VMConfig.allowTvmFreezeV2()) { return 0; } AccountCapsule accountCapsule = repository.getAccount(address); + if (accountCapsule == null) { + return 0; + } // BANDWIDTH if (type == 0) { - return accountCapsule.getAllFrozenBalanceForBandwidth(); + return accountCapsule.getFrozenV2BalanceForBandwidth(); } // ENERGY if (type == 1) { - return accountCapsule.getAllFrozenBalanceForEnergy(); + return accountCapsule.getFrozenV2BalanceForEnergy(); } // POWER if (type == 2) { - return accountCapsule.getAllTronPower(); + return accountCapsule.getTronPowerFrozenV2Balance(); } return 0; @@ -84,6 +93,9 @@ public static Pair queryFrozenBalanceUsage(byte[] address, long type } AccountCapsule accountCapsule = repository.getAccount(address); + if (accountCapsule == null) { + return Pair.of(0L, 0L); + } if (type == 0) { return repository.getAccountNetUsageBalanceAndRestoreSeconds(accountCapsule); @@ -94,6 +106,124 @@ public static Pair queryFrozenBalanceUsage(byte[] address, long type return Pair.of(0L, 0L); } + public static long queryAvailableUnfreezeV2Size(byte[] address, Repository repository) { + if (!VMConfig.allowTvmFreezeV2()) { + return 0L; + } + + AccountCapsule accountCapsule = repository.getAccount(address); + if (accountCapsule == null) { + return 0L; + } + + long now = repository.getHeadSlot(); + int unfreezingV2Count = accountCapsule.getUnfreezingV2Count(now); + return Long.max(UnfreezeBalanceV2Processor.getUNFREEZE_MAX_TIMES() - unfreezingV2Count, 0L); + } + + public static long queryDelegatableResource(byte[] address, long type, Repository repository) { + if (!VMConfig.allowTvmFreezeV2()) { + return 0L; + } + + AccountCapsule accountCapsule = repository.getAccount(address); + if (accountCapsule == null) { + return 0L; + } + + if (type == 0) { + // self frozenV2 resource + long frozenV2Resource = accountCapsule.getFrozenV2BalanceForBandwidth(); + + // total Usage. + Pair usagePair = + repository.getAccountNetUsageBalanceAndRestoreSeconds(accountCapsule); + if (usagePair == null || usagePair.getLeft() == null) { + return frozenV2Resource; + } + + long usage = usagePair.getLeft(); + if (usage <= 0) { + return frozenV2Resource; + } + + // total resource + long totalResource = accountCapsule.getAllFrozenBalanceForBandwidth(); + if (totalResource <= usage) { + return 0L; + } + + return frozenV2Resource * (totalResource - usage) / totalResource; + } + + if (type == 1) { + // self frozenV2 resource + long frozenV2Resource = accountCapsule.getFrozenV2BalanceForEnergy(); + + // total Usage. + Pair usagePair = + repository.getAccountEnergyUsageBalanceAndRestoreSeconds(accountCapsule); + if (usagePair == null || usagePair.getLeft() == null) { + return frozenV2Resource; + } + + long usage = usagePair.getLeft(); + if (usage <= 0) { + return frozenV2Resource; + } + + // total resource + long totalResource = accountCapsule.getAllFrozenBalanceForEnergy(); + if (totalResource <= usage) { + return 0L; + } + + return frozenV2Resource * (totalResource - usage) / totalResource; + } + + return 0L; + } + + public static Triple checkUndelegateResource(byte[] address, long amount, long type, Repository repository) { + if (!VMConfig.allowTvmFreezeV2()) { + return Triple.of(0L, 0L, 0L); + } + + if (amount <= 0) { + return Triple.of(0L, 0L, 0L); + } + + AccountCapsule accountCapsule = repository.getAccount(address); + if (accountCapsule == null) { + return Triple.of(0L, 0L, 0L); + } + + Pair usagePair; + long resourceLimit; + if (type == 0) { + usagePair = repository.getAccountNetUsageBalanceAndRestoreSeconds(accountCapsule); + resourceLimit = accountCapsule.getAllFrozenBalanceForBandwidth(); + } else if (type == 1) { + usagePair = repository.getAccountEnergyUsageBalanceAndRestoreSeconds(accountCapsule); + resourceLimit = accountCapsule.getAllFrozenBalanceForEnergy(); + } else { + return Triple.of(0L, 0L, 0L); + } + + if (usagePair == null || usagePair.getLeft() == null || usagePair.getRight() == null) { + return Triple.of(0L, 0L, 0L); + } + + amount = Math.min(amount, resourceLimit); + if (resourceLimit <= usagePair.getLeft()) { + return Triple.of(0L, amount, usagePair.getRight()); + } + + long clean = amount * (resourceLimit - usagePair.getLeft()) / resourceLimit; + + return Triple.of(clean, amount - clean, usagePair.getRight()); + } + private static long getTotalWithdrawUnfreeze(List unfrozenV2List, long time) { return getTotalWithdrawList(unfrozenV2List, time).stream() .mapToLong(Protocol.Account.UnFreezeV2::getUnfreezeAmount).sum(); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index fe658d7ab68..8d95948b97f 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -8,6 +8,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.tuple.Pair; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.encoders.Hex; import org.junit.AfterClass; @@ -26,10 +27,7 @@ import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.actuator.FreezeBalanceActuator; -import org.tron.core.capsule.AccountCapsule; -import org.tron.core.capsule.ProposalCapsule; -import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.capsule.WitnessCapsule; +import org.tron.core.capsule.*; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; @@ -39,6 +37,7 @@ import org.tron.core.store.StoreFactory; import org.tron.core.vm.PrecompiledContracts; import org.tron.core.vm.PrecompiledContracts.PrecompiledContract; +import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.repository.Repository; import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; @@ -63,6 +62,22 @@ public class PrecompiledContractsTest { "0000000000000000000000000000000000000000000000000000000000010008"); private static final DataWord convertFromTronBase58AddressAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000000010009"); + + private static final DataWord getChainParameterAddr = new DataWord( + "000000000000000000000000000000000000000000000000000000000100000b"); + + private static final DataWord expireFreezeV2BalanceAddr = new DataWord( + "000000000000000000000000000000000000000000000000000000000100000c"); + + private static final DataWord totalFrozenBalanceAddr = new DataWord( + "000000000000000000000000000000000000000000000000000000000100000d"); + + private static final DataWord frozenBalanceAddr = new DataWord( + "000000000000000000000000000000000000000000000000000000000100000e"); + + private static final DataWord fronzenBalanceUsageAddr = new DataWord( + "000000000000000000000000000000000000000000000000000000000100000f"); + private static final String dbPath = "output_PrecompiledContracts_test"; private static final String ACCOUNT_NAME = "account"; private static final String OWNER_ADDRESS; @@ -284,6 +299,93 @@ public void proposalTest() { } } + @Test + public void tvmFreezeV2SwitchTest() { + VMConfig.initAllowTvmFreezeV2(0L); + PrecompiledContract getChainParameterPcc = PrecompiledContracts.getContractForAddress(getChainParameterAddr); + PrecompiledContract expireFreezeV2BalancePcc = PrecompiledContracts.getContractForAddress(expireFreezeV2BalanceAddr); + PrecompiledContract totalFrozenBalancePcc = PrecompiledContracts.getContractForAddress(totalFrozenBalanceAddr); + PrecompiledContract frozenBalancePcc = PrecompiledContracts.getContractForAddress(frozenBalanceAddr); + PrecompiledContract frozenBalanceUsagePcc = PrecompiledContracts.getContractForAddress(fronzenBalanceUsageAddr); + + Assert.assertNull(getChainParameterPcc); + Assert.assertNull(expireFreezeV2BalancePcc); + Assert.assertNull(totalFrozenBalancePcc); + Assert.assertNull(frozenBalancePcc); + Assert.assertNull(frozenBalanceUsagePcc); + + VMConfig.initAllowTvmFreezeV2(1L); + getChainParameterPcc = PrecompiledContracts.getContractForAddress(getChainParameterAddr); + expireFreezeV2BalancePcc = PrecompiledContracts.getContractForAddress(expireFreezeV2BalanceAddr); + totalFrozenBalancePcc = PrecompiledContracts.getContractForAddress(totalFrozenBalanceAddr); + frozenBalancePcc = PrecompiledContracts.getContractForAddress(frozenBalanceAddr); + frozenBalanceUsagePcc = PrecompiledContracts.getContractForAddress(fronzenBalanceUsageAddr); + + Assert.assertNotNull(getChainParameterPcc); + Assert.assertNotNull(expireFreezeV2BalancePcc); + Assert.assertNotNull(totalFrozenBalancePcc); + Assert.assertNotNull(frozenBalancePcc); + Assert.assertNotNull(frozenBalanceUsagePcc); + } + + @Test + public void getChainParameterTest() { + VMConfig.initAllowTvmFreezeV2(1L); + + PrecompiledContract getChainParameterPcc = createPrecompiledContract(getChainParameterAddr, OWNER_ADDRESS); + Repository tempRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + getChainParameterPcc.setRepository(tempRepository); + + byte[] TOTAL_ENERGY_CURRENT_LIMIT = "TOTAL_ENERGY_CURRENT_LIMIT".getBytes(); + byte[] TOTAL_ENERGY_WEIGHT = "TOTAL_ENERGY_WEIGHT".getBytes(); + byte[] UNFREEZE_DELAY_DAYS = "UNFREEZE_DELAY_DAYS".getBytes(); + + DataWord totalEnergyCurrentLimitId = new DataWord( + "0000000000000000000000000000000000000000000000000000000000000001"); + + DataWord totalEnergyWeightId = new DataWord( + "0000000000000000000000000000000000000000000000000000000000000002"); + + DataWord unfreezeDelayDaysId = new DataWord( + "0000000000000000000000000000000000000000000000000000000000000003"); + + DataWord invalidId = new DataWord( + "0000000000000000000000000000000000000000000000000000000000FFFFFF"); + + long energyLimit = 9_000_000_000_000_000L; + tempRepository.getDynamicPropertiesStore().put(TOTAL_ENERGY_CURRENT_LIMIT, new BytesCapsule(ByteArray.fromLong(energyLimit))); + Pair totalEnergyCurrentLimitRes = getChainParameterPcc.execute(totalEnergyCurrentLimitId.getData()); + Assert.assertTrue(totalEnergyCurrentLimitRes.getLeft()); + Assert.assertEquals(ByteArray.toLong(totalEnergyCurrentLimitRes.getRight()), energyLimit); + + long energyWeight = 1_000_000_000L; + tempRepository.getDynamicPropertiesStore().put(TOTAL_ENERGY_WEIGHT, new BytesCapsule(ByteArray.fromLong(energyWeight))); + Pair totalEnergyWeightRes = getChainParameterPcc.execute(totalEnergyWeightId.getData()); + Assert.assertTrue(totalEnergyWeightRes.getLeft()); + Assert.assertEquals(ByteArray.toLong(totalEnergyWeightRes.getRight()), energyWeight); + + long delayDays = 3L; + tempRepository.getDynamicPropertiesStore().put(UNFREEZE_DELAY_DAYS, new BytesCapsule(ByteArray.fromLong(delayDays))); + Pair delayDaysRes = getChainParameterPcc.execute(unfreezeDelayDaysId.getData()); + Assert.assertTrue(delayDaysRes.getLeft()); + Assert.assertEquals(ByteArray.toLong(delayDaysRes.getRight()), delayDays); + + long zero = 0L; + Pair invalidParamRes = getChainParameterPcc.execute(invalidId.getData()); + Assert.assertTrue(invalidParamRes.getLeft()); + Assert.assertEquals(ByteArray.toLong(invalidParamRes.getRight()), zero); + + } + + @Test + public void getExpireFreezeV2BalanceTest() { + VMConfig.initAllowTvmFreezeV2(1L); + + PrecompiledContract expireFreezeV2BalancePcc = createPrecompiledContract(expireFreezeV2BalanceAddr, OWNER_ADDRESS); + + + } + @Test public void convertFromTronBytesAddressNativeTest() { } From f9040b74df77007ac269b49d9c9ad612b904d789 Mon Sep 17 00:00:00 2001 From: Liulei Date: Wed, 19 Oct 2022 15:42:41 +0800 Subject: [PATCH 0308/1197] feat(freezeV2): optimize unDelegateResource return values --- .../org/tron/core/vm/OperationActions.java | 14 +++++++++++-- .../CancelUnfreezeProcessor.java | 20 +++++++++---------- .../UnDelegateResourceProcessor.java | 6 +++++- .../org/tron/core/vm/program/Program.java | 9 +++++---- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index 83fabe311b1..123162ddeea 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -6,6 +6,8 @@ import java.math.BigInteger; import java.util.ArrayList; import java.util.List; +import java.util.Objects; +import org.apache.commons.lang3.tuple.Triple; import org.tron.common.runtime.vm.DataWord; import org.tron.common.runtime.vm.LogInfo; import org.tron.core.vm.config.VMConfig; @@ -845,8 +847,16 @@ public static void unDelegateResourceAction(Program program) { DataWord unDelegateBalance = program.stackPop(); DataWord receiverAddress = program.stackPop(); - boolean result = program.unDelegateResource(receiverAddress, unDelegateBalance, resourceType); - program.stackPush(result ? DataWord.ONE() : DataWord.ZERO()); + Triple result = + program.unDelegateResource(receiverAddress, unDelegateBalance, resourceType); + if (Objects.isNull(result)) { + program.stackPush(DataWord.ZERO()); + } else { + program.stackPush(new DataWord(result.getLeft())); + program.stackPush(new DataWord(result.getMiddle())); + program.stackPush(new DataWord(result.getRight())); + program.stackPush(DataWord.ONE()); + } program.step(); } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelUnfreezeProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelUnfreezeProcessor.java index fd4655c9cc8..1c30835c234 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelUnfreezeProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelUnfreezeProcessor.java @@ -5,10 +5,7 @@ import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; -import java.util.ArrayList; -import java.util.List; import java.util.Objects; - import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; @@ -35,8 +32,8 @@ public void validate(CancelUnfreezeParam param, Repository repo) throws Contract AccountCapsule accountCapsule = repo.getAccount(ownerAddress); if (Objects.isNull(accountCapsule)) { String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); - throw new ContractValidateException(ACCOUNT_EXCEPTION_STR - + readableOwnerAddress + NOT_EXIST_STR); + throw new ContractValidateException( + ACCOUNT_EXCEPTION_STR + readableOwnerAddress + NOT_EXIST_STR); } } @@ -44,16 +41,19 @@ public void execute(CancelUnfreezeParam param, Repository repo) throws ContractE byte[] ownerAddress = param.getOwnerAddress(); AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); long now = repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); - List unfrozenV2List = - new ArrayList<>(ownerCapsule.getUnfrozenV2List()); - ownerCapsule.clearUnfrozenV2(); - for (Protocol.Account.UnFreezeV2 unFreezeV2: unfrozenV2List) { + long withdrawExpireBalance = 0L; + for (Protocol.Account.UnFreezeV2 unFreezeV2: ownerCapsule.getUnfrozenV2List()) { if (unFreezeV2.getUnfreezeExpireTime() > now) { updateFrozenInfoAndTotalResourceWeight(ownerCapsule, unFreezeV2, repo); } else { - ownerCapsule.addUnfrozenV2(unFreezeV2); + // withdraw + withdrawExpireBalance += unFreezeV2.getUnfreezeAmount(); } } + if (withdrawExpireBalance > 0) { + ownerCapsule.setBalance(ownerCapsule.getBalance() + withdrawExpireBalance); + } + ownerCapsule.clearUnfrozenV2(); repo.updateAccount(ownerCapsule.createDbKey(), ownerCapsule); } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index e440c6218a9..8dea507d994 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -7,6 +7,7 @@ import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.tuple.Triple; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.ChainBaseManager; @@ -18,6 +19,7 @@ import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.vm.nativecontract.param.UnDelegateResourceParam; import org.tron.core.vm.repository.Repository; +import org.tron.core.vm.utils.FreezeV2Util; @Slf4j(topic = "VMProcessor") public class UnDelegateResourceProcessor { @@ -89,7 +91,7 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont } } - public void execute(UnDelegateResourceParam param, Repository repo) { + public Triple execute(UnDelegateResourceParam param, Repository repo) { byte[] ownerAddress = param.getOwnerAddress(); byte[] receiverAddress = param.getReceiverAddress(); long unDelegateBalance = param.getUnDelegateBalance(); @@ -191,5 +193,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { } repo.updateDelegatedResource(key, delegatedResourceCapsule); repo.updateAccount(ownerCapsule.createDbKey(), ownerCapsule); + return FreezeV2Util.checkUndelegateResource( + ownerAddress, unDelegateBalance, param.getResourceType().getNumber(), repo); } } diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index a4565e1af6f..dc25cf1ba6c 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -22,6 +22,7 @@ import org.apache.commons.collections4.map.LRUMap; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.lang3.tuple.Triple; import org.bouncycastle.util.encoders.Hex; import org.tron.common.crypto.Hash; import org.tron.common.parameter.CommonParameter; @@ -1980,7 +1981,7 @@ public boolean delegateResource( return false; } - public boolean unDelegateResource( + public Triple unDelegateResource( DataWord receiverAddress, DataWord unDelegateBalance, DataWord resourceType) { Repository repository = getContractState().newRepositoryChild(); byte[] owner = getContextAddress(); @@ -2000,9 +2001,9 @@ public boolean unDelegateResource( UnDelegateResourceProcessor processor = new UnDelegateResourceProcessor(); processor.validate(param, repository); - processor.execute(param, repository); + Triple result = processor.execute(param, repository); repository.commit(); - return true; + return result; } catch (ContractValidateException e) { logger.error("TVM unDelegateResource: validate failure. Reason: {}", e.getMessage()); } catch (ArithmeticException e) { @@ -2011,7 +2012,7 @@ public boolean unDelegateResource( if (internalTx != null) { internalTx.reject(); } - return false; + return null; } private Common.ResourceCode parseResourceCode(DataWord resourceType) { From 3b65c91ddc742c8b0b663d5d63cdb5febf130d05 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 19 Oct 2022 15:22:08 +0800 Subject: [PATCH 0309/1197] feat(freezeV2): optimize usage merging --- .../actuator/DelegateResourceActuator.java | 22 +++++++++++-------- .../actuator/UnDelegateResourceActuator.java | 4 ++-- .../actuator/UnfreezeBalanceV2Actuator.java | 5 +++-- .../WithdrawExpireUnfreezeActuator.java | 1 - .../WithdrawExpireUnfreezeActuatorTest.java | 1 - 5 files changed, 18 insertions(+), 15 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 8abe753b6a2..ec36c2c4b90 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -143,11 +143,14 @@ public boolean validate() throws ContractValidateException { BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); processor.updateUsage(ownerCapsule); - //The unit is trx - long netTrxUsage = (long) (ownerCapsule.getNetUsage() - * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); + long netUsage = (long) (ownerCapsule.getNetUsage() * TRX_PRECISION * ((double) + (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); - if (ownerCapsule.getFrozenV2BalanceForBandwidth() - netTrxUsage * TRX_PRECISION + long ownerNetUsage = (long) (netUsage * ((double)(ownerCapsule + .getFrozenV2BalanceForBandwidth()) / + ownerCapsule.getAllFrozenBalanceForBandwidth())); + + if (ownerCapsule.getFrozenV2BalanceForBandwidth() - ownerNetUsage < delegateBalance) { throw new ContractValidateException( "delegateBalance must be less than available FreezeBandwidthV2 balance"); @@ -158,12 +161,13 @@ public boolean validate() throws ContractValidateException { EnergyProcessor processor = new EnergyProcessor(dynamicStore, accountStore); processor.updateUsage(ownerCapsule); - //The unit is trx - long energyTrxUsage = (long) (ownerCapsule.getEnergyUsage() - * ((double) (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); + long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) + (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); - if (ownerCapsule.getFrozenV2BalanceForEnergy() - energyTrxUsage * TRX_PRECISION - < delegateBalance) { + long ownerEnergyUsage = (long) (energyUsage * ((double)(ownerCapsule + .getFrozenV2BalanceForEnergy()) / ownerCapsule.getAllFrozenBalanceForEnergy())); + + if (ownerCapsule.getFrozenV2BalanceForEnergy() - ownerEnergyUsage < delegateBalance) { throw new ContractValidateException( "delegateBalance must be less than available FreezeEnergyV2Balance balance"); } diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index 6926d0d060f..56ad722533a 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -279,8 +279,8 @@ public boolean validate() throws ContractValidateException { } long unDelegateBalance = unDelegateResourceContract.getBalance(); - if (unDelegateBalance < TRX_PRECISION) { - throw new ContractValidateException("unDelegateBalance must be more than 1TRX"); + if (unDelegateBalance <= 0) { + throw new ContractValidateException("unDelegateBalance must be more than 0 TRX"); } switch (unDelegateResourceContract.getResource()) { case BANDWIDTH: diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java index bcc64f2121c..2c50875d298 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java @@ -165,7 +165,7 @@ public boolean validate() throws ContractValidateException { if (!checkUnfreezeBalance(accountCapsule, unfreezeBalanceV2Contract, unfreezeBalanceV2Contract.getResource())) { throw new ContractValidateException( - "Invalid unfreeze_balance, freezing resource[" + unfreezeBalanceV2Contract.getResource() + "] is not enough" + "Invalid unfreeze_balance, [" + unfreezeBalanceV2Contract.getUnfreezeBalance() + "] is error" ); } @@ -219,7 +219,8 @@ public boolean checkUnfreezeBalance(AccountCapsule accountCapsule, } } - if (unfreezeBalanceV2Contract.getUnfreezeBalance() <= frozenAmount) { + if (unfreezeBalanceV2Contract.getUnfreezeBalance() > 0 + && unfreezeBalanceV2Contract.getUnfreezeBalance() <= frozenAmount) { checkOk = true; } diff --git a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java index 57b6668ff66..606c18028d5 100755 --- a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java @@ -55,7 +55,6 @@ public boolean execute(Object result) throws ContractExeException { long totalWithdrawUnfreeze = getTotalWithdrawUnfreeze(unfrozenV2List, now); accountCapsule.setInstance(accountCapsule.getInstance().toBuilder() .setBalance(accountCapsule.getBalance() + totalWithdrawUnfreeze) - .setLatestWithdrawTime(now) .build()); List newUnFreezeList = getRemainWithdrawList(unfrozenV2List, now); accountCapsule.clearUnfrozenV2(); diff --git a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java index 52b075a1454..455c8ba8a92 100644 --- a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java @@ -133,7 +133,6 @@ public void testWithdrawExpireUnfreeze() { Assert.assertEquals(Long.MAX_VALUE, unfrozenV2List.get(0).getUnfreezeExpireTime()); Assert.assertEquals(initBalance + 32_000_000L, owner.getBalance()); Assert.assertEquals(0, owner.getAllowance()); - Assert.assertNotEquals(0, owner.getLatestWithdrawTime()); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { From 0dc24e075e5d67e7e2dfeeb557407ecf85dcd495 Mon Sep 17 00:00:00 2001 From: Liulei Date: Wed, 19 Oct 2022 16:27:49 +0800 Subject: [PATCH 0310/1197] fix(freezeV2): fix freezeV2 processor validation --- .../DelegateResourceProcessor.java | 27 ++++++++++--------- .../UnDelegateResourceProcessor.java | 4 +-- .../UnfreezeBalanceV2Processor.java | 6 +++-- .../WithdrawExpireUnfreezeProcessor.java | 1 - .../org/tron/core/vm/program/Program.java | 2 ++ 5 files changed, 22 insertions(+), 18 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index 7a88a0e6116..fad2833b147 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -53,13 +53,15 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra case BANDWIDTH: { BandwidthProcessor processor = new BandwidthProcessor(ChainBaseManager.getInstance()); processor.updateUsage(ownerCapsule); - // The unit is trx - double netUsageRatio = (double) ownerCapsule.getFrozenV2BalanceForBandwidth() - / ownerCapsule.getAllFrozenBalanceForBandwidth(); - long netTrxUsage = (long) (ownerCapsule.getNetUsage() * netUsageRatio - * ((double) (repo.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); - if (ownerCapsule.getFrozenV2BalanceForBandwidth() - netTrxUsage * TRX_PRECISION + long netUsage = (long) (ownerCapsule.getNetUsage() * TRX_PRECISION * ((double) + (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); + + long ownerNetUsage = (long) (netUsage * ((double)(ownerCapsule + .getFrozenV2BalanceForBandwidth()) / + ownerCapsule.getAllFrozenBalanceForBandwidth())); + + if (ownerCapsule.getFrozenV2BalanceForBandwidth() - ownerNetUsage < delegateBalance) { throw new ContractValidateException( "delegateBalance must be less than available FreezeBandwidthV2 balance"); @@ -71,14 +73,13 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra new EnergyProcessor(dynamicStore, ChainBaseManager.getInstance().getAccountStore()); processor.updateUsage(ownerCapsule); - // The unit is trx - double energyUsageRatio = (double) ownerCapsule.getFrozenV2BalanceForEnergy() - / ownerCapsule.getAllFrozenBalanceForEnergy(); - long energyTrxUsage = (long) (ownerCapsule.getEnergyUsage() * energyUsageRatio - * ((double) (repo.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); + long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) + (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); - if (ownerCapsule.getFrozenV2BalanceForEnergy() - energyTrxUsage * TRX_PRECISION - < delegateBalance) { + long ownerEnergyUsage = (long) (energyUsage * ((double)(ownerCapsule + .getFrozenV2BalanceForEnergy()) / ownerCapsule.getAllFrozenBalanceForEnergy())); + + if (ownerCapsule.getFrozenV2BalanceForEnergy() - ownerEnergyUsage < delegateBalance) { throw new ContractValidateException( "delegateBalance must be less than available FreezeEnergyV2Balance balance"); } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index 8dea507d994..8917701d39f 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -69,8 +69,8 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont } long unDelegateBalance = param.getUnDelegateBalance(); - if (unDelegateBalance < TRX_PRECISION) { - throw new ContractValidateException("unDelegateBalance must be more than 1TRX"); + if (unDelegateBalance <= 0) { + throw new ContractValidateException("unDelegateBalance must be more than 0 TRX"); } switch (param.getResourceType()) { case BANDWIDTH: diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index 4d43450cdf0..c7c34049d4f 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -83,13 +83,15 @@ public void validate(UnfreezeBalanceV2Param param, Repository repo) if (!checkUnfreezeBalance(accountCapsule, param.getUnfreezeBalance(), param.getResourceType())) { throw new ContractValidateException( - "Invalid unfreeze_balance, freezing resource[" + param.getResourceType() + "] is not enough" - ); + "Invalid unfreeze_balance, [" + param.getUnfreezeBalance() + "] is error"); } } private boolean checkUnfreezeBalance( AccountCapsule accountCapsule, long unfreezeBalance, Common.ResourceCode freezeType) { + if (unfreezeBalance < 0) { + return false; + } long frozenBalance = 0L; List freezeV2List = accountCapsule.getFrozenV2List(); for (Protocol.Account.FreezeV2 freezeV2 : freezeV2List) { diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java index 10ca7de5745..7b8e5398862 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java @@ -76,7 +76,6 @@ public long execute(WithdrawExpireUnfreezeParam param, Repository repo) throws C } ownerCapsule.setInstance(ownerCapsule.getInstance().toBuilder() .setBalance(ownerCapsule.getBalance() + totalWithdrawUnfreeze) - .setLatestWithdrawTime(now) .build()); List newUnFreezeList = getRemainWithdrawList(unfrozenV2List, now); ownerCapsule.clearUnfrozenV2(); diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index dc25cf1ba6c..df7c3647f43 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -537,6 +537,7 @@ private void transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit inheritorCapsule.getLatestConsumeTime(), now); inheritorCapsule.setNetUsage(newNetUsage); + inheritorCapsule.setLatestConsumeTime(now); long newEnergyUsage = repo.increaseV2( inheritorCapsule, @@ -546,6 +547,7 @@ private void transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit inheritorCapsule.getLatestConsumeTimeForEnergy(), now); inheritorCapsule.setEnergyUsage(newEnergyUsage); + inheritorCapsule.setLatestConsumeTimeForEnergy(now); // withdraw expire unfrozen balance long expireUnfrozenBalance = From 059d0695e505bebf1c72b10b6bb10a7aa968f6bd Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Wed, 19 Oct 2022 16:47:44 +0800 Subject: [PATCH 0311/1197] feat(freezeV2): optimize freezeV2 precompiledContracts addresses --- .../tron/core/vm/PrecompiledContracts.java | 219 +++++++++++++----- .../org/tron/core/vm/utils/FreezeV2Util.java | 7 +- .../runtime/vm/PrecompiledContractsTest.java | 64 +++-- 3 files changed, 210 insertions(+), 80 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 006d868da26..7df714599cf 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -100,17 +100,18 @@ public class PrecompiledContracts { private static final EthRipemd160 ethRipemd160 = new EthRipemd160(); private static final Blake2F blake2F = new Blake2F(); + // FreezeV2 PrecompileContracts private static final GetChainParameter getChainParameter = new GetChainParameter(); - private static final ExpireFreezeV2Balance expireFreezeV2Balance = new ExpireFreezeV2Balance(); - private static final TotalFrozenBalanceV2 totalFrozenBalanceV2 = new TotalFrozenBalanceV2(); - private static final ResourceV2 resourceV2 = new ResourceV2(); - private static final ResourceUsage resourceUsage = new ResourceUsage(); - private static final AvailableUnfreezeV2Size availableUnfreezeSize = new AvailableUnfreezeV2Size(); - + private static final TotalFrozenBalanceV2 totalFrozenBalanceV2 = new TotalFrozenBalanceV2(); + private static final ExpireFrozenBalanceV2 expireFrozenBalanceV2 = new ExpireFrozenBalanceV2(); private static final DelegatableResource delegatableResource = new DelegatableResource(); - + private static final ResourceV2 resourceV2 = new ResourceV2(); private static final CheckDelegatedResource checkDelegatedResource = new CheckDelegatedResource(); + private static final ResourceUsage resourceUsage = new ResourceUsage(); + private static final TotalResource totalResource = new TotalResource(); + private static final TotalDelegatedResource totalDelegatedResource = new TotalDelegatedResource(); + private static final TotalAcquiredResource totalAcquiredResource = new TotalAcquiredResource(); private static final DataWord ecRecoverAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000000000001"); @@ -153,40 +154,40 @@ public class PrecompiledContracts { private static final DataWord totalVoteCountAddr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000a"); + // FreezeV2 PrecompileContracts private static final DataWord getChainParameterAddr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000b"); - private static final DataWord expireFreezeV2BalanceAddr = new DataWord( + private static final DataWord availableUnfreezeSizeAddr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000c"); private static final DataWord totalFrozenBalanceV2Addr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000d"); - private static final DataWord resourceV2Addr = new DataWord( + private static final DataWord expireFrozenBalanceV2Addr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000e"); - private static final DataWord resourceUsageAddr = new DataWord( + private static final DataWord delegatableResourceAddr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000f"); - private static final DataWord availableUnfreezeSizeAddr = new DataWord( + private static final DataWord resourceV2Addr = new DataWord( "0000000000000000000000000000000000000000000000000000000001000010"); - private static final DataWord delegatableResourceAddr = new DataWord( + private static final DataWord checkDelegatedResourceAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000001000011"); - private static final DataWord totalResourceAddr = new DataWord( + private static final DataWord resourceUsageAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000001000012"); - private static final DataWord totalDelegatedResourceAddr = new DataWord( + private static final DataWord totalResourceAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000001000013"); - private static final DataWord totalAcquiredResourceAddr = new DataWord( + private static final DataWord totalDelegatedResourceAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000001000014"); - private static final DataWord checkDelegatedResourceAddr = new DataWord( + private static final DataWord totalAcquiredResourceAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000001000015"); - private static final DataWord ethRipemd160Addr = new DataWord( "0000000000000000000000000000000000000000000000000000000000020003"); private static final DataWord blake2FAddr = new DataWord( @@ -270,28 +271,36 @@ public static PrecompiledContract getContractForAddress(DataWord address) { if (address.equals(getChainParameterAddr)) { return getChainParameter; } - if (address.equals(expireFreezeV2BalanceAddr)) { - return expireFreezeV2Balance; + if (address.equals(availableUnfreezeSizeAddr)) { + return availableUnfreezeSize; } if (address.equals(totalFrozenBalanceV2Addr)) { return totalFrozenBalanceV2; } + if (address.equals(expireFrozenBalanceV2Addr)) { + return expireFrozenBalanceV2; + } + if (address.equals(delegatableResourceAddr)) { + return delegatableResource; + } if (address.equals(resourceV2Addr)) { return resourceV2; } + if (address.equals(checkDelegatedResourceAddr)) { + return checkDelegatedResource; + } if (address.equals(resourceUsageAddr)) { return resourceUsage; } - if (address.equals(availableUnfreezeSizeAddr)) { - return availableUnfreezeSize; + if (address.equals(totalResourceAddr)) { + return totalResource; } - if (address.equals(delegatableResourceAddr)) { - return delegatableResource; + if (address.equals(totalDelegatedResourceAddr)) { + return totalDelegatedResource; } - if (address.equals(checkDelegatedResourceAddr)) { - return checkDelegatedResource; + if (address.equals(totalAcquiredResourceAddr)) { + return totalAcquiredResource; } - } return null; @@ -1862,7 +1871,49 @@ public Pair execute(byte[] data) { } } - public static class ExpireFreezeV2Balance extends PrecompiledContract { + public static class AvailableUnfreezeV2Size extends PrecompiledContract { + + @Override + public long getEnergyForData(byte[] data) { + return 100; + } + + @Override + public Pair execute(byte[] data) { + if (data == null || data.length != WORD_SIZE) { + return Pair.of(true, DataWord.ZERO().getData()); + } + + byte[] address = new DataWord(data).toTronAddress(); + + long result = FreezeV2Util.queryAvailableUnfreezeV2Size(address, getDeposit()); + return Pair.of(true, longTo32Bytes(result)); + } + } + + public static class TotalFrozenBalanceV2 extends PrecompiledContract { + + @Override + public long getEnergyForData(byte[] data) { + return 100; + } + + @Override + public Pair execute(byte[] data) { + if (data == null || data.length != 2 * WORD_SIZE) { + return Pair.of(true, DataWord.ZERO().getData()); + } + + DataWord[] words = DataWord.parseArray(data); + byte[] address = words[0].toTronAddress(); + long type = words[1].longValueSafe(); + + long balance = FreezeV2Util.queryTotalFrozenBalanceV2(address, type, getDeposit()); + return Pair.of(true, longTo32Bytes(balance)); + } + } + + public static class ExpireFrozenBalanceV2 extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { @@ -1888,12 +1939,12 @@ public Pair execute(byte[] data) { time = time * 1_000; } - long balance = FreezeV2Util.queryExpireFreezeV2Balance(caller, time, getDeposit()); + long balance = FreezeV2Util.queryExpireFrozenBalanceV2(caller, time, getDeposit()); return Pair.of(true, longTo32Bytes(balance)); } } - public static class TotalFrozenBalanceV2 extends PrecompiledContract { + public static class DelegatableResource extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { @@ -1910,8 +1961,8 @@ public Pair execute(byte[] data) { byte[] address = words[0].toTronAddress(); long type = words[1].longValueSafe(); - long balance = FreezeV2Util.queryTotalFrozenBalanceV2(address, type, getDeposit()); - return Pair.of(true, longTo32Bytes(balance)); + long result = FreezeV2Util.queryDelegatableResource(address, type, getDeposit()); + return Pair.of(true, longTo32Bytes(result)); } } @@ -1933,11 +1984,43 @@ public Pair execute(byte[] data) { byte[] to = words[1].toTronAddress(); long type = words[2].longValueSafe(); - long balance = FreezeV2Util.queryFrozenBalance(from, to, type, getDeposit()); + long balance; + if (Arrays.equals(from, to)) { + balance = FreezeV2Util.queryTotalFrozenBalanceV2(from, type, getDeposit()); + } else { + balance = FreezeV2Util.queryFrozenBalanceV2(from, to, type, getDeposit()); + } return Pair.of(true, longTo32Bytes(balance)); } } + public static class CheckDelegatedResource extends PrecompiledContract { + + @Override + public long getEnergyForData(byte[] data) { + return 100; + } + + @Override + public Pair execute(byte[] data) { + if (data == null || data.length != 3 * WORD_SIZE) { + return Pair.of(true, encodeMultiRes(DataWord.ZERO().getData(), DataWord.ZERO().getData(), DataWord.ZERO().getData())); + } + + DataWord[] words = DataWord.parseArray(data); + byte[] target = words[0].toTronAddress(); + long amount = words[1].longValueSafe(); + long type = words[2].longValueSafe(); + + Triple values = FreezeV2Util.checkUndelegateResource(target, amount, type, getDeposit()); + if (values == null || values.getLeft() == null || values.getMiddle() == null || values.getRight() == null) { + return Pair.of(true, encodeMultiRes(DataWord.ZERO().getData(), DataWord.ZERO().getData(), DataWord.ZERO().getData())); + } + + return Pair.of(true, encodeMultiRes(longTo32Bytes(values.getLeft()), longTo32Bytes(values.getMiddle()), longTo32Bytes(values.getRight()))); + } + } + public static class ResourceUsage extends PrecompiledContract { @Override @@ -1964,31 +2047,44 @@ public Pair execute(byte[] data) { } } - public static class AvailableUnfreezeV2Size extends PrecompiledContract { + public static class TotalResource extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { - return 100; + return 50; } @Override public Pair execute(byte[] data) { - if (data == null || data.length != WORD_SIZE) { + if (data == null || data.length != 2 * WORD_SIZE) { return Pair.of(true, DataWord.ZERO().getData()); } - byte[] address = new DataWord(data).toTronAddress(); + DataWord[] words = DataWord.parseArray(data); + byte[] address = words[0].toTronAddress(); + long type = words[1].longValueSafe(); - long result = FreezeV2Util.queryAvailableUnfreezeV2Size(address, getDeposit()); - return Pair.of(true, longTo32Bytes(result)); + AccountCapsule accountCapsule = getDeposit().getAccount(address); + if (accountCapsule == null) { + return Pair.of(true, DataWord.ZERO().getData()); + } + + long totalResource = 0; + if (type == 0) { + totalResource = accountCapsule.getAllFrozenBalanceForBandwidth(); + } else if (type == 1) { + totalResource = accountCapsule.getAllFrozenBalanceForEnergy(); + } + + return Pair.of(true, longTo32Bytes(totalResource)); } } - public static class DelegatableResource extends PrecompiledContract { + public static class TotalDelegatedResource extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { - return 100; + return 50; } @Override @@ -2001,35 +2097,52 @@ public Pair execute(byte[] data) { byte[] address = words[0].toTronAddress(); long type = words[1].longValueSafe(); - long result = FreezeV2Util.queryDelegatableResource(address, type, getDeposit()); - return Pair.of(true, longTo32Bytes(result)); + AccountCapsule accountCapsule = getDeposit().getAccount(address); + if (accountCapsule == null) { + return Pair.of(true, DataWord.ZERO().getData()); + } + + long delegatedResource = 0; + if (type == 0) { + delegatedResource = accountCapsule.getDelegatedFrozenBalanceForBandwidth(); + } else if (type == 1) { + delegatedResource = accountCapsule.getDelegatedFrozenBalanceForEnergy(); + } + + return Pair.of(true, longTo32Bytes(delegatedResource)); } } - public static class CheckDelegatedResource extends PrecompiledContract { + public static class TotalAcquiredResource extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { - return 100; + return 50; } @Override public Pair execute(byte[] data) { - if (data == null || data.length != 3 * WORD_SIZE) { - return Pair.of(true, encodeMultiRes(DataWord.ZERO().getData(), DataWord.ZERO().getData(), DataWord.ZERO().getData())); + if (data == null || data.length != 2 * WORD_SIZE) { + return Pair.of(true, DataWord.ZERO().getData()); } DataWord[] words = DataWord.parseArray(data); - byte[] target = words[0].toTronAddress(); - long amount = words[1].longValueSafe(); - long type = words[2].longValueSafe(); + byte[] address = words[0].toTronAddress(); + long type = words[1].longValueSafe(); - Triple values = FreezeV2Util.checkUndelegateResource(target, amount, type, getDeposit()); - if (values == null || values.getLeft() == null || values.getMiddle() == null || values.getRight() == null) { - return Pair.of(true, encodeMultiRes(DataWord.ZERO().getData(), DataWord.ZERO().getData(), DataWord.ZERO().getData())); + AccountCapsule accountCapsule = getDeposit().getAccount(address); + if (accountCapsule == null) { + return Pair.of(true, DataWord.ZERO().getData()); } - return Pair.of(true, encodeMultiRes(longTo32Bytes(values.getLeft()), longTo32Bytes(values.getMiddle()), longTo32Bytes(values.getRight()))); + long acquiredResource = 0; + if (type == 0) { + acquiredResource = accountCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth(); + } else if (type == 1) { + acquiredResource = accountCapsule.getAcquiredDelegatedFrozenBalanceForEnergy(); + } + + return Pair.of(true, longTo32Bytes(acquiredResource)); } } diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index 1ab85396a23..c3f93471db5 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -1,13 +1,12 @@ package org.tron.core.vm.utils; -import java.util.*; +import java.util.List; import java.util.stream.Collectors; import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Triple; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; -import org.tron.core.db.EnergyProcessor; import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.nativecontract.UnfreezeBalanceV2Processor; import org.tron.core.vm.repository.Repository; @@ -18,7 +17,7 @@ public class FreezeV2Util { private FreezeV2Util() { } - public static long queryExpireFreezeV2Balance(byte[] address, long time, Repository repository) { + public static long queryExpireFrozenBalanceV2(byte[] address, long time, Repository repository) { if (!VMConfig.allowTvmFreezeV2()) { return 0; } @@ -63,7 +62,7 @@ public static long queryTotalFrozenBalanceV2(byte[] address, long type, Reposito } // only freezeV2. - public static long queryFrozenBalance(byte[] from, byte[] to, long type, Repository repository) { + public static long queryFrozenBalanceV2(byte[] from, byte[] to, long type, Repository repository) { if (!VMConfig.allowTvmFreezeV2()) { return 0; } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index 8d95948b97f..297789e8d08 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -63,21 +63,40 @@ public class PrecompiledContractsTest { private static final DataWord convertFromTronBase58AddressAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000000010009"); + // FreezeV2 PrecompileContracts private static final DataWord getChainParameterAddr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000b"); - private static final DataWord expireFreezeV2BalanceAddr = new DataWord( + private static final DataWord availableUnfreezeSizeAddr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000c"); - private static final DataWord totalFrozenBalanceAddr = new DataWord( + private static final DataWord totalFrozenBalanceV2Addr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000d"); - private static final DataWord frozenBalanceAddr = new DataWord( + private static final DataWord expireFrozenBalanceV2Addr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000e"); - private static final DataWord fronzenBalanceUsageAddr = new DataWord( + private static final DataWord delegatableResourceAddr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000f"); + private static final DataWord resourceV2Addr = new DataWord( + "0000000000000000000000000000000000000000000000000000000001000010"); + + private static final DataWord checkDelegatedResourceAddr = new DataWord( + "0000000000000000000000000000000000000000000000000000000001000011"); + + private static final DataWord resourceUsageAddr = new DataWord( + "0000000000000000000000000000000000000000000000000000000001000012"); + + private static final DataWord totalResourceAddr = new DataWord( + "0000000000000000000000000000000000000000000000000000000001000013"); + + private static final DataWord totalDelegatedResourceAddr = new DataWord( + "0000000000000000000000000000000000000000000000000000000001000014"); + + private static final DataWord totalAcquiredResourceAddr = new DataWord( + "0000000000000000000000000000000000000000000000000000000001000015"); + private static final String dbPath = "output_PrecompiledContracts_test"; private static final String ACCOUNT_NAME = "account"; private static final String OWNER_ADDRESS; @@ -303,29 +322,29 @@ public void proposalTest() { public void tvmFreezeV2SwitchTest() { VMConfig.initAllowTvmFreezeV2(0L); PrecompiledContract getChainParameterPcc = PrecompiledContracts.getContractForAddress(getChainParameterAddr); - PrecompiledContract expireFreezeV2BalancePcc = PrecompiledContracts.getContractForAddress(expireFreezeV2BalanceAddr); - PrecompiledContract totalFrozenBalancePcc = PrecompiledContracts.getContractForAddress(totalFrozenBalanceAddr); - PrecompiledContract frozenBalancePcc = PrecompiledContracts.getContractForAddress(frozenBalanceAddr); - PrecompiledContract frozenBalanceUsagePcc = PrecompiledContracts.getContractForAddress(fronzenBalanceUsageAddr); + PrecompiledContract expireFrozenBalanceV2Pcc = PrecompiledContracts.getContractForAddress(expireFrozenBalanceV2Addr); + PrecompiledContract totalFrozenBalanceV2Pcc = PrecompiledContracts.getContractForAddress(totalFrozenBalanceV2Addr); + PrecompiledContract resourceV2Pcc = PrecompiledContracts.getContractForAddress(resourceV2Addr); + PrecompiledContract resourceUsagePcc = PrecompiledContracts.getContractForAddress(resourceUsageAddr); Assert.assertNull(getChainParameterPcc); - Assert.assertNull(expireFreezeV2BalancePcc); - Assert.assertNull(totalFrozenBalancePcc); - Assert.assertNull(frozenBalancePcc); - Assert.assertNull(frozenBalanceUsagePcc); + Assert.assertNull(expireFrozenBalanceV2Pcc); + Assert.assertNull(totalFrozenBalanceV2Pcc); + Assert.assertNull(resourceV2Pcc); + Assert.assertNull(resourceUsagePcc); VMConfig.initAllowTvmFreezeV2(1L); getChainParameterPcc = PrecompiledContracts.getContractForAddress(getChainParameterAddr); - expireFreezeV2BalancePcc = PrecompiledContracts.getContractForAddress(expireFreezeV2BalanceAddr); - totalFrozenBalancePcc = PrecompiledContracts.getContractForAddress(totalFrozenBalanceAddr); - frozenBalancePcc = PrecompiledContracts.getContractForAddress(frozenBalanceAddr); - frozenBalanceUsagePcc = PrecompiledContracts.getContractForAddress(fronzenBalanceUsageAddr); + expireFrozenBalanceV2Pcc = PrecompiledContracts.getContractForAddress(expireFrozenBalanceV2Addr); + totalFrozenBalanceV2Pcc = PrecompiledContracts.getContractForAddress(totalFrozenBalanceV2Addr); + resourceV2Pcc = PrecompiledContracts.getContractForAddress(resourceV2Addr); + resourceUsagePcc = PrecompiledContracts.getContractForAddress(resourceUsageAddr); Assert.assertNotNull(getChainParameterPcc); - Assert.assertNotNull(expireFreezeV2BalancePcc); - Assert.assertNotNull(totalFrozenBalancePcc); - Assert.assertNotNull(frozenBalancePcc); - Assert.assertNotNull(frozenBalanceUsagePcc); + Assert.assertNotNull(expireFrozenBalanceV2Pcc); + Assert.assertNotNull(totalFrozenBalanceV2Pcc); + Assert.assertNotNull(resourceV2Pcc); + Assert.assertNotNull(resourceUsagePcc); } @Test @@ -378,11 +397,10 @@ public void getChainParameterTest() { } @Test - public void getExpireFreezeV2BalanceTest() { + public void getExpireFrozenBalanceV2Test() { VMConfig.initAllowTvmFreezeV2(1L); - PrecompiledContract expireFreezeV2BalancePcc = createPrecompiledContract(expireFreezeV2BalanceAddr, OWNER_ADDRESS); - + PrecompiledContract expireFrozenBalanceV2Pcc = createPrecompiledContract(expireFrozenBalanceV2Addr, OWNER_ADDRESS); } From 006e724fcca9ce93c391118a135363b94d9a5f06 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Wed, 19 Oct 2022 17:18:40 +0800 Subject: [PATCH 0312/1197] feat(freezeV2): optimize freezeV2 precompiledContracts function name and param orders --- .../java/org/tron/core/vm/PrecompiledContracts.java | 8 ++++---- .../java/org/tron/core/vm/program/ContractState.java | 5 ----- .../java/org/tron/core/vm/repository/Repository.java | 2 -- .../org/tron/core/vm/repository/RepositoryImpl.java | 11 ----------- .../java/org/tron/core/vm/utils/FreezeV2Util.java | 2 +- 5 files changed, 5 insertions(+), 23 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 7df714599cf..108c386aee9 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -1980,15 +1980,15 @@ public Pair execute(byte[] data) { } DataWord[] words = DataWord.parseArray(data); - byte[] from = words[0].toTronAddress(); - byte[] to = words[1].toTronAddress(); + byte[] target = words[0].toTronAddress(); + byte[] from = words[1].toTronAddress(); long type = words[2].longValueSafe(); long balance; - if (Arrays.equals(from, to)) { + if (Arrays.equals(from, target)) { balance = FreezeV2Util.queryTotalFrozenBalanceV2(from, type, getDeposit()); } else { - balance = FreezeV2Util.queryFrozenBalanceV2(from, to, type, getDeposit()); + balance = FreezeV2Util.queryResourceV2(from, target, type, getDeposit()); } return Pair.of(true, longTo32Bytes(balance)); } diff --git a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java index b7211cfc92f..ec3cdce5a1f 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java +++ b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java @@ -234,11 +234,6 @@ public long increaseV2(AccountCapsule accountCapsule, Common.ResourceCode resour return repository.increaseV2(accountCapsule, resourceCode, lastUsage, usage, lastTime, now); } - @Override - public long getAccountNetUsageFromFreeze(AccountCapsule accountCapsule) { - return repository.getAccountNetUsageFromFreeze(accountCapsule); - } - @Override public Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { return repository.getAccountEnergyUsageBalanceAndRestoreSeconds(accountCapsule); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java index ee296bd4449..7e076901b37 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java @@ -113,8 +113,6 @@ public interface Repository { long increaseV2(AccountCapsule accountCapsule, Common.ResourceCode resourceCode, long lastUsage, long usage, long lastTime, long now); - long getAccountNetUsageFromFreeze(AccountCapsule accountCapsule); - Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule); Pair getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index c2aba02c390..fc65abdf443 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -185,17 +185,6 @@ public long getAccountEnergyUsageFromFreeze(AccountCapsule accountCapsule) { return recover(energyUsage, latestConsumeTime, now, accountWindowSize); } - @Override - public long getAccountNetUsageFromFreeze(AccountCapsule accountCapsule) { - long now = getHeadSlot(); - long netUsage = accountCapsule.getNetUsage(); - long latestConsumeTime = accountCapsule.getLatestConsumeTime(); - - long accountWindowSize = accountCapsule.getWindowSize(Common.ResourceCode.BANDWIDTH); - - return recover(netUsage, latestConsumeTime, now, accountWindowSize); - } - public long increaseV2( AccountCapsule accountCapsule, Common.ResourceCode resourceCode, diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index c3f93471db5..f4cbc2ad9e7 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -62,7 +62,7 @@ public static long queryTotalFrozenBalanceV2(byte[] address, long type, Reposito } // only freezeV2. - public static long queryFrozenBalanceV2(byte[] from, byte[] to, long type, Repository repository) { + public static long queryResourceV2(byte[] from, byte[] to, long type, Repository repository) { if (!VMConfig.allowTvmFreezeV2()) { return 0; } From 5ea35477afd7a650738071dd635085131e5d9e52 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 19 Oct 2022 18:12:58 +0800 Subject: [PATCH 0313/1197] feat(freezeV2): optimize usage merging --- framework/build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/framework/build.gradle b/framework/build.gradle index 7df08a90eb9..09b83647499 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -151,6 +151,10 @@ test { exclude 'org/tron/common/runtime/vm/WithdrawRewardTest.class' } maxHeapSize = "1024m" + doFirst { + forkEvery = 5 + jvmArgs "-XX:MetaspaceSize=128m","-XX:MaxMetaspaceSize=256m" + } } task stest(type: Test) { From 1b4a447034d4dcc06977cd03f057cc3357cfeae8 Mon Sep 17 00:00:00 2001 From: Liulei Date: Wed, 19 Oct 2022 19:00:01 +0800 Subject: [PATCH 0314/1197] fix(freezeV2): fix unDelegateResource return --- .../src/main/java/org/tron/core/actuator/VMActuator.java | 3 ++- .../vm/nativecontract/UnDelegateResourceProcessor.java | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 0a765256979..1846eb6da68 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -116,7 +116,8 @@ public void validate(Object object) throws ContractValidateException { OperationRegistry.init(); trx = context.getTrxCap().getInstance(); blockCap = context.getBlockCap(); - if (VMConfig.allowTvmFreeze() && context.getTrxCap().getTrxTrace() != null) { + if ((VMConfig.allowTvmFreeze() || VMConfig.allowTvmFreezeV2()) + && context.getTrxCap().getTrxTrace() != null) { receipt = context.getTrxCap().getTrxTrace().getReceipt(); } //Route Type diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index 8917701d39f..52650864e53 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -91,7 +91,7 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont } } - public Triple execute(UnDelegateResourceParam param, Repository repo) { + public Triple execute (UnDelegateResourceParam param, Repository repo) { byte[] ownerAddress = param.getOwnerAddress(); byte[] receiverAddress = param.getReceiverAddress(); long unDelegateBalance = param.getUnDelegateBalance(); @@ -99,6 +99,10 @@ public Triple execute(UnDelegateResourceParam param, Reposito AccountCapsule receiverCapsule = repo.getAccount(receiverAddress); DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); + Triple unDelegateResourceIndo = + FreezeV2Util.checkUndelegateResource( + receiverAddress, unDelegateBalance, param.getResourceType().getNumber(), repo); + long transferUsage = 0; // modify receiver Account if (receiverCapsule != null) { @@ -193,7 +197,6 @@ public Triple execute(UnDelegateResourceParam param, Reposito } repo.updateDelegatedResource(key, delegatedResourceCapsule); repo.updateAccount(ownerCapsule.createDbKey(), ownerCapsule); - return FreezeV2Util.checkUndelegateResource( - ownerAddress, unDelegateBalance, param.getResourceType().getNumber(), repo); + return unDelegateResourceIndo; } } From 96b82a26338ea822419ded5142063d2fb7022a7b Mon Sep 17 00:00:00 2001 From: Liulei Date: Wed, 19 Oct 2022 19:00:38 +0800 Subject: [PATCH 0315/1197] fix(freezeV2): fix unDelegateResource return --- actuator/src/main/java/org/tron/core/vm/OperationRegistry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index 93caa0e00e2..c57fd5744f3 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -616,7 +616,7 @@ public static void appendDelegateOperations(JumpTable table) { proposal)); table.set(new Operation( - Op.UNDELEGATERESOURCE, 3, 1, + Op.UNDELEGATERESOURCE, 3, 4, EnergyCost::getUnDelegateResourceCost, OperationActions::unDelegateResourceAction, proposal)); From 91580a1ab93f497dc7701dff5a7ef36f3fd4dade Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 19 Oct 2022 18:12:58 +0800 Subject: [PATCH 0316/1197] feat(freezeV2): optimize usage merging --- framework/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/build.gradle b/framework/build.gradle index 09b83647499..95c2ec681a6 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -152,7 +152,7 @@ test { } maxHeapSize = "1024m" doFirst { - forkEvery = 5 + forkEvery = 100 jvmArgs "-XX:MetaspaceSize=128m","-XX:MaxMetaspaceSize=256m" } } From 3e94c7cd0e9f44786d9fa65d53ac2526b384270e Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 19 Oct 2022 19:23:27 +0800 Subject: [PATCH 0317/1197] feat(freezeV2): optimize usage merging --- framework/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/build.gradle b/framework/build.gradle index 95c2ec681a6..6573f4afdf2 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -155,6 +155,7 @@ test { forkEvery = 100 jvmArgs "-XX:MetaspaceSize=128m","-XX:MaxMetaspaceSize=256m" } + maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 } task stest(type: Test) { From bfd2558efeeae2197fbc190f79332ebab17c8394 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Wed, 19 Oct 2022 19:26:44 +0800 Subject: [PATCH 0318/1197] feat(freezeV2): optimize freezeV2 precompiledContract function names --- .../tron/core/vm/PrecompiledContracts.java | 36 +++++++++---------- .../org/tron/core/vm/utils/FreezeV2Util.java | 4 +-- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 108c386aee9..07c9558b129 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -103,11 +103,11 @@ public class PrecompiledContracts { // FreezeV2 PrecompileContracts private static final GetChainParameter getChainParameter = new GetChainParameter(); private static final AvailableUnfreezeV2Size availableUnfreezeSize = new AvailableUnfreezeV2Size(); - private static final TotalFrozenBalanceV2 totalFrozenBalanceV2 = new TotalFrozenBalanceV2(); - private static final ExpireFrozenBalanceV2 expireFrozenBalanceV2 = new ExpireFrozenBalanceV2(); + private static final FrozenBalanceV2 frozenBalanceV2 = new FrozenBalanceV2(); + private static final ExpireUnfreezeBalanceV2 expireUnfreezeBalanceV2 = new ExpireUnfreezeBalanceV2(); private static final DelegatableResource delegatableResource = new DelegatableResource(); private static final ResourceV2 resourceV2 = new ResourceV2(); - private static final CheckDelegatedResource checkDelegatedResource = new CheckDelegatedResource(); + private static final CheckUndelegateResource checkUndelegateResource = new CheckUndelegateResource(); private static final ResourceUsage resourceUsage = new ResourceUsage(); private static final TotalResource totalResource = new TotalResource(); private static final TotalDelegatedResource totalDelegatedResource = new TotalDelegatedResource(); @@ -161,10 +161,10 @@ public class PrecompiledContracts { private static final DataWord availableUnfreezeSizeAddr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000c"); - private static final DataWord totalFrozenBalanceV2Addr = new DataWord( + private static final DataWord frozenBalanceV2Addr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000d"); - private static final DataWord expireFrozenBalanceV2Addr = new DataWord( + private static final DataWord expireUnfreezeBalanceV2Addr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000e"); private static final DataWord delegatableResourceAddr = new DataWord( @@ -173,7 +173,7 @@ public class PrecompiledContracts { private static final DataWord resourceV2Addr = new DataWord( "0000000000000000000000000000000000000000000000000000000001000010"); - private static final DataWord checkDelegatedResourceAddr = new DataWord( + private static final DataWord checkUndelegateResourceAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000001000011"); private static final DataWord resourceUsageAddr = new DataWord( @@ -274,11 +274,11 @@ public static PrecompiledContract getContractForAddress(DataWord address) { if (address.equals(availableUnfreezeSizeAddr)) { return availableUnfreezeSize; } - if (address.equals(totalFrozenBalanceV2Addr)) { - return totalFrozenBalanceV2; + if (address.equals(frozenBalanceV2Addr)) { + return frozenBalanceV2; } - if (address.equals(expireFrozenBalanceV2Addr)) { - return expireFrozenBalanceV2; + if (address.equals(expireUnfreezeBalanceV2Addr)) { + return expireUnfreezeBalanceV2; } if (address.equals(delegatableResourceAddr)) { return delegatableResource; @@ -286,8 +286,8 @@ public static PrecompiledContract getContractForAddress(DataWord address) { if (address.equals(resourceV2Addr)) { return resourceV2; } - if (address.equals(checkDelegatedResourceAddr)) { - return checkDelegatedResource; + if (address.equals(checkUndelegateResourceAddr)) { + return checkUndelegateResource; } if (address.equals(resourceUsageAddr)) { return resourceUsage; @@ -1891,7 +1891,7 @@ public Pair execute(byte[] data) { } } - public static class TotalFrozenBalanceV2 extends PrecompiledContract { + public static class FrozenBalanceV2 extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { @@ -1908,12 +1908,12 @@ public Pair execute(byte[] data) { byte[] address = words[0].toTronAddress(); long type = words[1].longValueSafe(); - long balance = FreezeV2Util.queryTotalFrozenBalanceV2(address, type, getDeposit()); + long balance = FreezeV2Util.queryFrozenBalanceV2(address, type, getDeposit()); return Pair.of(true, longTo32Bytes(balance)); } } - public static class ExpireFrozenBalanceV2 extends PrecompiledContract { + public static class ExpireUnfreezeBalanceV2 extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { @@ -1939,7 +1939,7 @@ public Pair execute(byte[] data) { time = time * 1_000; } - long balance = FreezeV2Util.queryExpireFrozenBalanceV2(caller, time, getDeposit()); + long balance = FreezeV2Util.queryExpireUnfreezeBalanceV2(caller, time, getDeposit()); return Pair.of(true, longTo32Bytes(balance)); } } @@ -1986,7 +1986,7 @@ public Pair execute(byte[] data) { long balance; if (Arrays.equals(from, target)) { - balance = FreezeV2Util.queryTotalFrozenBalanceV2(from, type, getDeposit()); + balance = FreezeV2Util.queryFrozenBalanceV2(from, type, getDeposit()); } else { balance = FreezeV2Util.queryResourceV2(from, target, type, getDeposit()); } @@ -1994,7 +1994,7 @@ public Pair execute(byte[] data) { } } - public static class CheckDelegatedResource extends PrecompiledContract { + public static class CheckUndelegateResource extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index f4cbc2ad9e7..835f131280a 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -17,7 +17,7 @@ public class FreezeV2Util { private FreezeV2Util() { } - public static long queryExpireFrozenBalanceV2(byte[] address, long time, Repository repository) { + public static long queryExpireUnfreezeBalanceV2(byte[] address, long time, Repository repository) { if (!VMConfig.allowTvmFreezeV2()) { return 0; } @@ -33,7 +33,7 @@ public static long queryExpireFrozenBalanceV2(byte[] address, long time, Reposit return getTotalWithdrawUnfreeze(unfrozenV2List, time); } - public static long queryTotalFrozenBalanceV2(byte[] address, long type, Repository repository) { + public static long queryFrozenBalanceV2(byte[] address, long type, Repository repository) { if (!VMConfig.allowTvmFreezeV2()) { return 0; } From 46947fc92435efdaa68263a0b722eca14e7ffd9a Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 19 Oct 2022 20:46:20 +0800 Subject: [PATCH 0319/1197] feat(freezeV2): optimize usage merging --- framework/build.gradle | 5 ----- 1 file changed, 5 deletions(-) diff --git a/framework/build.gradle b/framework/build.gradle index 6573f4afdf2..7df08a90eb9 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -151,11 +151,6 @@ test { exclude 'org/tron/common/runtime/vm/WithdrawRewardTest.class' } maxHeapSize = "1024m" - doFirst { - forkEvery = 100 - jvmArgs "-XX:MetaspaceSize=128m","-XX:MaxMetaspaceSize=256m" - } - maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 } task stest(type: Test) { From befbdd1d17e5c9eab7f4c6f5adb67fe33636dee7 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Thu, 20 Oct 2022 12:31:48 +0800 Subject: [PATCH 0320/1197] feat(freezeV2): optimize UNFREEZE_MAX_TIMES getter --- .../org/tron/core/actuator/UnfreezeBalanceV2Actuator.java | 2 ++ .../core/vm/nativecontract/UnfreezeBalanceV2Processor.java | 7 ++----- .../src/main/java/org/tron/core/vm/utils/FreezeV2Util.java | 3 ++- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java index 2c50875d298..43b61ad125b 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java @@ -3,6 +3,7 @@ import com.google.common.collect.Lists; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; @@ -32,6 +33,7 @@ @Slf4j(topic = "actuator") public class UnfreezeBalanceV2Actuator extends AbstractActuator { + @Getter private static final int UNFREEZE_MAX_TIMES = 32; public UnfreezeBalanceV2Actuator() { diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index c7c34049d4f..6c211c8d218 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -10,10 +10,10 @@ import java.util.Iterator; import java.util.List; -import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; +import org.tron.core.actuator.UnfreezeBalanceV2Actuator; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.VotesCapsule; import org.tron.core.exception.ContractValidateException; @@ -26,9 +26,6 @@ @Slf4j(topic = "VMProcessor") public class UnfreezeBalanceV2Processor { - @Getter - private static final int UNFREEZE_MAX_TIMES = 16; - public void validate(UnfreezeBalanceV2Param param, Repository repo) throws ContractValidateException { if (repo == null) { @@ -48,7 +45,7 @@ public void validate(UnfreezeBalanceV2Param param, Repository repo) } long now = dynamicStore.getLatestBlockHeaderTimestamp(); int unfreezingCount = accountCapsule.getUnfreezingV2Count(now); - if (UNFREEZE_MAX_TIMES <= unfreezingCount) { + if (UnfreezeBalanceV2Actuator.getUNFREEZE_MAX_TIMES() <= unfreezingCount) { throw new ContractValidateException("Invalid unfreeze operation, unfreezing times is over limit"); } switch (param.getResourceType()) { diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index 835f131280a..256366579a9 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -5,6 +5,7 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Triple; +import org.tron.core.actuator.UnfreezeBalanceV2Actuator; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.vm.config.VMConfig; @@ -117,7 +118,7 @@ public static long queryAvailableUnfreezeV2Size(byte[] address, Repository repos long now = repository.getHeadSlot(); int unfreezingV2Count = accountCapsule.getUnfreezingV2Count(now); - return Long.max(UnfreezeBalanceV2Processor.getUNFREEZE_MAX_TIMES() - unfreezingV2Count, 0L); + return Long.max(UnfreezeBalanceV2Actuator.getUNFREEZE_MAX_TIMES() - unfreezingV2Count, 0L); } public static long queryDelegatableResource(byte[] address, long type, Repository repository) { From fce15f9f808c5b44dbe1529d5a3042fd20f832ff Mon Sep 17 00:00:00 2001 From: Liulei Date: Thu, 20 Oct 2022 12:34:07 +0800 Subject: [PATCH 0321/1197] feat(freezeV2): optimize freezeV2 processor --- .../java/org/tron/core/vm/EnergyCost.java | 6 +-- .../src/main/java/org/tron/core/vm/Op.java | 2 +- .../org/tron/core/vm/OperationActions.java | 4 +- .../org/tron/core/vm/OperationRegistry.java | 6 +-- ...java => CancelAllUnfreezeV2Processor.java} | 8 ++-- .../UnfreezeBalanceV2Processor.java | 2 +- ...ram.java => CancelAllUnfreezeV2Param.java} | 2 +- .../tron/core/vm/program/ContractState.java | 5 --- .../org/tron/core/vm/program/Program.java | 21 ++++++---- .../tron/core/vm/repository/Repository.java | 3 -- .../core/vm/repository/RepositoryImpl.java | 39 ------------------- .../org/tron/core/db/ResourceProcessor.java | 2 +- 12 files changed, 30 insertions(+), 70 deletions(-) rename actuator/src/main/java/org/tron/core/vm/nativecontract/{CancelUnfreezeProcessor.java => CancelAllUnfreezeV2Processor.java} (90%) rename actuator/src/main/java/org/tron/core/vm/nativecontract/param/{CancelUnfreezeParam.java => CancelAllUnfreezeV2Param.java} (85%) diff --git a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java index 5f44cadfe77..f60de7e8a62 100644 --- a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java +++ b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java @@ -39,7 +39,7 @@ public class EnergyCost { private static final long FREEZE_V2 = 20000; private static final long UNFREEZE_V2 = 20000; private static final long WITHDRAW_EXPIRE_UNFREEZE = 20000; - private static final long CANCEL_UNFREEZE = 20000; + private static final long CANCEL_ALL_UNFREEZE_V2 = 20000; private static final long DELEGATE_RESOURCE = 20000; private static final long UN_DELEGATE_RESOURCE = 20000; private static final long VOTE_WITNESS = 30000; @@ -290,8 +290,8 @@ public static long getWithdrawExpireUnfreezeCost(Program ignored) { return WITHDRAW_EXPIRE_UNFREEZE; } - public static long getCancelUnfreezeCost(Program ignored) { - return CANCEL_UNFREEZE; + public static long getCancelAllUnfreezeV2Cost(Program ignored) { + return CANCEL_ALL_UNFREEZE_V2; } public static long getDelegateResourceCost(Program program) { diff --git a/actuator/src/main/java/org/tron/core/vm/Op.java b/actuator/src/main/java/org/tron/core/vm/Op.java index 31be9b19ed0..50e95f19efe 100644 --- a/actuator/src/main/java/org/tron/core/vm/Op.java +++ b/actuator/src/main/java/org/tron/core/vm/Op.java @@ -241,7 +241,7 @@ public class Op { public static final int WITHDRAWEXPIREUNFREEZE = 0xdc; public static final int DELEGATERESOURCE = 0xdd; public static final int UNDELEGATERESOURCE = 0xde; - public static final int CANCELUNFREEZE = 0xdf; + public static final int CANCELALLUNFREEZEV2 = 0xdf; // (0xf0) Create a new account with associated code public static final int CREATE = 0xf0; diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index 123162ddeea..ecf3063007f 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -816,12 +816,12 @@ public static void withdrawExpireUnfreezeAction(Program program) { program.step(); } - public static void cancelUnfreezeAction(Program program) { + public static void cancelAllUnfreezeV2Action(Program program) { if (program.isStaticCall()) { throw new Program.StaticCallModificationException(); } - boolean result = program.cancelUnfreezeAction(); + boolean result = program.cancelAllUnfreezeV2Action(); program.stackPush(result ? DataWord.ONE() : DataWord.ZERO()); program.step(); } diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index c57fd5744f3..ea11556761c 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -600,9 +600,9 @@ public static void appendFreezeV2Operations(JumpTable table) { proposal)); table.set(new Operation( - Op.CANCELUNFREEZE, 0, 1, - EnergyCost::getCancelUnfreezeCost, - OperationActions::cancelUnfreezeAction, + Op.CANCELALLUNFREEZEV2, 0, 1, + EnergyCost::getCancelAllUnfreezeV2Cost, + OperationActions::cancelAllUnfreezeV2Action, proposal)); } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelUnfreezeProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java similarity index 90% rename from actuator/src/main/java/org/tron/core/vm/nativecontract/CancelUnfreezeProcessor.java rename to actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java index 1c30835c234..f3f4a3163c6 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelUnfreezeProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java @@ -13,14 +13,14 @@ import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.store.DynamicPropertiesStore; -import org.tron.core.vm.nativecontract.param.CancelUnfreezeParam; +import org.tron.core.vm.nativecontract.param.CancelAllUnfreezeV2Param; import org.tron.core.vm.repository.Repository; import org.tron.protos.Protocol; @Slf4j(topic = "VMProcessor") -public class CancelUnfreezeProcessor { +public class CancelAllUnfreezeV2Processor { - public void validate(CancelUnfreezeParam param, Repository repo) throws ContractValidateException { + public void validate(CancelAllUnfreezeV2Param param, Repository repo) throws ContractValidateException { if (repo == null) { throw new ContractValidateException(STORE_NOT_EXIST); } @@ -37,7 +37,7 @@ public void validate(CancelUnfreezeParam param, Repository repo) throws Contract } } - public void execute(CancelUnfreezeParam param, Repository repo) throws ContractExeException { + public void execute(CancelAllUnfreezeV2Param param, Repository repo) throws ContractExeException { byte[] ownerAddress = param.getOwnerAddress(); AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); long now = repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index 6c211c8d218..5a7283f7620 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -86,7 +86,7 @@ public void validate(UnfreezeBalanceV2Param param, Repository repo) private boolean checkUnfreezeBalance( AccountCapsule accountCapsule, long unfreezeBalance, Common.ResourceCode freezeType) { - if (unfreezeBalance < 0) { + if (unfreezeBalance <= 0) { return false; } long frozenBalance = 0L; diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/CancelUnfreezeParam.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/CancelAllUnfreezeV2Param.java similarity index 85% rename from actuator/src/main/java/org/tron/core/vm/nativecontract/param/CancelUnfreezeParam.java rename to actuator/src/main/java/org/tron/core/vm/nativecontract/param/CancelAllUnfreezeV2Param.java index 12f774a044b..f345fa0b344 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/CancelUnfreezeParam.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/CancelAllUnfreezeV2Param.java @@ -1,6 +1,6 @@ package org.tron.core.vm.nativecontract.param; -public class CancelUnfreezeParam { +public class CancelAllUnfreezeV2Param { private byte[] ownerAddress; diff --git a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java index ec3cdce5a1f..5ead8fda7c8 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java +++ b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java @@ -229,11 +229,6 @@ public long getAccountEnergyUsageFromFreeze(AccountCapsule accountCapsule) { return repository.getAccountEnergyUsageFromFreeze(accountCapsule); } - @Override - public long increaseV2(AccountCapsule accountCapsule, Common.ResourceCode resourceCode, long lastUsage, long usage, long lastTime, long now) { - return repository.increaseV2(accountCapsule, resourceCode, lastUsage, usage, lastTime, now); - } - @Override public Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { return repository.getAccountEnergyUsageBalanceAndRestoreSeconds(accountCapsule); diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index df7c3647f43..5c341fbbf5c 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -41,6 +41,8 @@ import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.VotesCapsule; import org.tron.core.capsule.WitnessCapsule; +import org.tron.core.db.BandwidthProcessor; +import org.tron.core.db.EnergyProcessor; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.TronException; @@ -54,7 +56,7 @@ import org.tron.core.vm.VMConstant; import org.tron.core.vm.VMUtils; import org.tron.core.vm.config.VMConfig; -import org.tron.core.vm.nativecontract.CancelUnfreezeProcessor; +import org.tron.core.vm.nativecontract.CancelAllUnfreezeV2Processor; import org.tron.core.vm.nativecontract.DelegateResourceProcessor; import org.tron.core.vm.nativecontract.FreezeBalanceProcessor; import org.tron.core.vm.nativecontract.FreezeBalanceV2Processor; @@ -64,7 +66,7 @@ import org.tron.core.vm.nativecontract.VoteWitnessProcessor; import org.tron.core.vm.nativecontract.WithdrawExpireUnfreezeProcessor; import org.tron.core.vm.nativecontract.WithdrawRewardProcessor; -import org.tron.core.vm.nativecontract.param.CancelUnfreezeParam; +import org.tron.core.vm.nativecontract.param.CancelAllUnfreezeV2Param; import org.tron.core.vm.nativecontract.param.DelegateResourceParam; import org.tron.core.vm.nativecontract.param.FreezeBalanceParam; import org.tron.core.vm.nativecontract.param.FreezeBalanceV2Param; @@ -528,8 +530,9 @@ private void transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit freezeV2.getType(), freezeV2.getAmount())); // merge usage + BandwidthProcessor bandwidthProcessor = new BandwidthProcessor(ChainBaseManager.getInstance()); long newNetUsage = - repo.increaseV2( + bandwidthProcessor.increase( inheritorCapsule, Common.ResourceCode.BANDWIDTH, inheritorCapsule.getNetUsage(), @@ -538,8 +541,12 @@ private void transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit now); inheritorCapsule.setNetUsage(newNetUsage); inheritorCapsule.setLatestConsumeTime(now); + + EnergyProcessor energyProcessor = + new EnergyProcessor( + repo.getDynamicPropertiesStore(), ChainBaseManager.getInstance().getAccountStore()); long newEnergyUsage = - repo.increaseV2( + energyProcessor.increase( inheritorCapsule, Common.ResourceCode.ENERGY, inheritorCapsule.getEnergyUsage(), @@ -1921,7 +1928,7 @@ public long withdrawExpireUnfreeze() { return 0; } - public boolean cancelUnfreezeAction() { + public boolean cancelAllUnfreezeV2Action() { Repository repository = getContractState().newRepositoryChild(); byte[] owner = getContextAddress(); @@ -1930,10 +1937,10 @@ public boolean cancelUnfreezeAction() { "cancelUnfreeze", nonce, null); try { - CancelUnfreezeParam param = new CancelUnfreezeParam(); + CancelAllUnfreezeV2Param param = new CancelAllUnfreezeV2Param(); param.setOwnerAddress(owner); - CancelUnfreezeProcessor processor = new CancelUnfreezeProcessor(); + CancelAllUnfreezeV2Processor processor = new CancelAllUnfreezeV2Processor(); processor.validate(param, repository); processor.execute(param, repository); repository.commit(); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java index 7e076901b37..410742c02fb 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java @@ -110,9 +110,6 @@ public interface Repository { long getAccountEnergyUsageFromFreeze(AccountCapsule accountCapsule); - long increaseV2(AccountCapsule accountCapsule, Common.ResourceCode resourceCode, - long lastUsage, long usage, long lastTime, long now); - Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule); Pair getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index fc65abdf443..84ae48637d4 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -185,45 +185,6 @@ public long getAccountEnergyUsageFromFreeze(AccountCapsule accountCapsule) { return recover(energyUsage, latestConsumeTime, now, accountWindowSize); } - public long increaseV2( - AccountCapsule accountCapsule, - Common.ResourceCode resourceCode, - long lastUsage, - long usage, - long lastTime, - long now) { - long oldWindowSize = accountCapsule.getWindowSize(resourceCode); - /* old logic */ - long averageLastUsage = divideCeil(lastUsage * this.precision, oldWindowSize); - long averageUsage = divideCeil(usage * this.precision, this.windowSize); - - if (lastTime != now) { - assert now > lastTime; - if (lastTime + oldWindowSize > now) { - long delta = now - lastTime; - double decay = (oldWindowSize - delta) / (double) oldWindowSize; - averageLastUsage = Math.round(averageLastUsage * decay); - } else { - averageLastUsage = 0; - } - } - /* new logic */ - long newUsage = getUsage(averageLastUsage, oldWindowSize) + - getUsage(averageUsage, this.windowSize); - if (dynamicPropertiesStore.supportUnfreezeDelay()) { - long remainUsage = getUsage(averageLastUsage, oldWindowSize); - if (remainUsage == 0) { - accountCapsule.setNewWindowSize(resourceCode, this.windowSize); - return newUsage; - } - long remainWindowSize = oldWindowSize - (now - lastTime); - long newWindowSize = (remainWindowSize * remainUsage + this.windowSize * usage) - / newUsage; - accountCapsule.setNewWindowSize(resourceCode, newWindowSize); - } - return newUsage; - } - public Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule) { long now = getHeadSlot(); diff --git a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java index e9aa35f696e..eb0ab0eba7a 100644 --- a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java @@ -60,7 +60,7 @@ protected long increase(long lastUsage, long usage, long lastTime, long now, lon return getUsage(averageLastUsage, windowSize); } - protected long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, + public long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, long lastUsage, long usage, long lastTime, long now) { long oldWindowSize = accountCapsule.getWindowSize(resourceCode); /* old logic */ From 2ef0208db48d59413448688d14561bb1f6fba299 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Thu, 20 Oct 2022 14:38:02 +0800 Subject: [PATCH 0322/1197] feat(freezeV2): optimize freezeV2 precompiledContracts functions --- .../tron/core/vm/PrecompiledContracts.java | 41 ++++++------ .../org/tron/core/vm/utils/FreezeV2Util.java | 3 +- .../runtime/vm/PrecompiledContractsTest.java | 63 ++++++++++++++----- 3 files changed, 71 insertions(+), 36 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 07c9558b129..6d009cc94ef 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -102,12 +102,12 @@ public class PrecompiledContracts { // FreezeV2 PrecompileContracts private static final GetChainParameter getChainParameter = new GetChainParameter(); - private static final AvailableUnfreezeV2Size availableUnfreezeSize = new AvailableUnfreezeV2Size(); - private static final FrozenBalanceV2 frozenBalanceV2 = new FrozenBalanceV2(); + private static final AvailableUnfreezeV2Size availableUnfreezeV2Size = new AvailableUnfreezeV2Size(); + private static final UnfreezableBalanceV2 unfreezableBalanceV2 = new UnfreezableBalanceV2(); private static final ExpireUnfreezeBalanceV2 expireUnfreezeBalanceV2 = new ExpireUnfreezeBalanceV2(); private static final DelegatableResource delegatableResource = new DelegatableResource(); private static final ResourceV2 resourceV2 = new ResourceV2(); - private static final CheckUndelegateResource checkUndelegateResource = new CheckUndelegateResource(); + private static final CheckUnDelegateResource checkUnDelegateResource = new CheckUnDelegateResource(); private static final ResourceUsage resourceUsage = new ResourceUsage(); private static final TotalResource totalResource = new TotalResource(); private static final TotalDelegatedResource totalDelegatedResource = new TotalDelegatedResource(); @@ -158,10 +158,10 @@ public class PrecompiledContracts { private static final DataWord getChainParameterAddr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000b"); - private static final DataWord availableUnfreezeSizeAddr = new DataWord( + private static final DataWord availableUnfreezeV2SizeAddr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000c"); - private static final DataWord frozenBalanceV2Addr = new DataWord( + private static final DataWord unfreezableBalanceV2Addr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000d"); private static final DataWord expireUnfreezeBalanceV2Addr = new DataWord( @@ -173,7 +173,7 @@ public class PrecompiledContracts { private static final DataWord resourceV2Addr = new DataWord( "0000000000000000000000000000000000000000000000000000000001000010"); - private static final DataWord checkUndelegateResourceAddr = new DataWord( + private static final DataWord checkUnDelegateResourceAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000001000011"); private static final DataWord resourceUsageAddr = new DataWord( @@ -271,11 +271,11 @@ public static PrecompiledContract getContractForAddress(DataWord address) { if (address.equals(getChainParameterAddr)) { return getChainParameter; } - if (address.equals(availableUnfreezeSizeAddr)) { - return availableUnfreezeSize; + if (address.equals(availableUnfreezeV2SizeAddr)) { + return availableUnfreezeV2Size; } - if (address.equals(frozenBalanceV2Addr)) { - return frozenBalanceV2; + if (address.equals(unfreezableBalanceV2Addr)) { + return unfreezableBalanceV2; } if (address.equals(expireUnfreezeBalanceV2Addr)) { return expireUnfreezeBalanceV2; @@ -286,8 +286,8 @@ public static PrecompiledContract getContractForAddress(DataWord address) { if (address.equals(resourceV2Addr)) { return resourceV2; } - if (address.equals(checkUndelegateResourceAddr)) { - return checkUndelegateResource; + if (address.equals(checkUnDelegateResourceAddr)) { + return checkUnDelegateResource; } if (address.equals(resourceUsageAddr)) { return resourceUsage; @@ -1891,7 +1891,7 @@ public Pair execute(byte[] data) { } } - public static class FrozenBalanceV2 extends PrecompiledContract { + public static class UnfreezableBalanceV2 extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { @@ -1908,7 +1908,7 @@ public Pair execute(byte[] data) { byte[] address = words[0].toTronAddress(); long type = words[1].longValueSafe(); - long balance = FreezeV2Util.queryFrozenBalanceV2(address, type, getDeposit()); + long balance = FreezeV2Util.queryUnfreezableBalanceV2(address, type, getDeposit()); return Pair.of(true, longTo32Bytes(balance)); } } @@ -1922,12 +1922,13 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { - if (data == null || data.length != WORD_SIZE) { + if (data == null || data.length != 2 * WORD_SIZE) { return Pair.of(true, DataWord.ZERO().getData()); } - byte[] caller = TransactionTrace.convertToTronAddress(getCallerAddress()); - long time = new DataWord(data).longValueSafe(); + DataWord[] words = DataWord.parseArray(data); + byte[] address = words[0].toTronAddress(); + long time = words[1].longValueSafe(); if (time < 0) { return Pair.of(true, DataWord.ZERO().getData()); @@ -1939,7 +1940,7 @@ public Pair execute(byte[] data) { time = time * 1_000; } - long balance = FreezeV2Util.queryExpireUnfreezeBalanceV2(caller, time, getDeposit()); + long balance = FreezeV2Util.queryExpireUnfreezeBalanceV2(address, time, getDeposit()); return Pair.of(true, longTo32Bytes(balance)); } } @@ -1986,7 +1987,7 @@ public Pair execute(byte[] data) { long balance; if (Arrays.equals(from, target)) { - balance = FreezeV2Util.queryFrozenBalanceV2(from, type, getDeposit()); + balance = FreezeV2Util.queryUnfreezableBalanceV2(from, type, getDeposit()); } else { balance = FreezeV2Util.queryResourceV2(from, target, type, getDeposit()); } @@ -1994,7 +1995,7 @@ public Pair execute(byte[] data) { } } - public static class CheckUndelegateResource extends PrecompiledContract { + public static class CheckUnDelegateResource extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index 256366579a9..2da14360a78 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -9,7 +9,6 @@ import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.vm.config.VMConfig; -import org.tron.core.vm.nativecontract.UnfreezeBalanceV2Processor; import org.tron.core.vm.repository.Repository; import org.tron.protos.Protocol; @@ -34,7 +33,7 @@ public static long queryExpireUnfreezeBalanceV2(byte[] address, long time, Repos return getTotalWithdrawUnfreeze(unfrozenV2List, time); } - public static long queryFrozenBalanceV2(byte[] address, long type, Repository repository) { + public static long queryUnfreezableBalanceV2(byte[] address, long type, Repository repository) { if (!VMConfig.allowTvmFreezeV2()) { return 0; } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index 297789e8d08..be8bb239b6d 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -67,13 +67,13 @@ public class PrecompiledContractsTest { private static final DataWord getChainParameterAddr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000b"); - private static final DataWord availableUnfreezeSizeAddr = new DataWord( + private static final DataWord availableUnfreezeV2SizeAddr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000c"); - private static final DataWord totalFrozenBalanceV2Addr = new DataWord( + private static final DataWord unfreezableBalanceV2Addr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000d"); - private static final DataWord expireFrozenBalanceV2Addr = new DataWord( + private static final DataWord expireUnfreezeBalanceV2Addr = new DataWord( "000000000000000000000000000000000000000000000000000000000100000e"); private static final DataWord delegatableResourceAddr = new DataWord( @@ -82,7 +82,7 @@ public class PrecompiledContractsTest { private static final DataWord resourceV2Addr = new DataWord( "0000000000000000000000000000000000000000000000000000000001000010"); - private static final DataWord checkDelegatedResourceAddr = new DataWord( + private static final DataWord checkUnDelegateResourceAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000001000011"); private static final DataWord resourceUsageAddr = new DataWord( @@ -321,30 +321,65 @@ public void proposalTest() { @Test public void tvmFreezeV2SwitchTest() { VMConfig.initAllowTvmFreezeV2(0L); + PrecompiledContract getChainParameterPcc = PrecompiledContracts.getContractForAddress(getChainParameterAddr); - PrecompiledContract expireFrozenBalanceV2Pcc = PrecompiledContracts.getContractForAddress(expireFrozenBalanceV2Addr); - PrecompiledContract totalFrozenBalanceV2Pcc = PrecompiledContracts.getContractForAddress(totalFrozenBalanceV2Addr); + PrecompiledContract availableUnfreezeV2SizePcc = PrecompiledContracts.getContractForAddress(availableUnfreezeV2SizeAddr); + PrecompiledContract unfreezableBalanceV2Pcc = PrecompiledContracts.getContractForAddress(unfreezableBalanceV2Addr); + PrecompiledContract expireUnfreezeBalanceV2Pcc = PrecompiledContracts.getContractForAddress(expireUnfreezeBalanceV2Addr); + + PrecompiledContract delegatableResourcePcc = PrecompiledContracts.getContractForAddress(delegatableResourceAddr); PrecompiledContract resourceV2Pcc = PrecompiledContracts.getContractForAddress(resourceV2Addr); + PrecompiledContract checkUnDelegateResourcePcc = PrecompiledContracts.getContractForAddress(checkUnDelegateResourceAddr); + PrecompiledContract resourceUsagePcc = PrecompiledContracts.getContractForAddress(resourceUsageAddr); + PrecompiledContract totalResourcePcc = PrecompiledContracts.getContractForAddress(totalResourceAddr); + PrecompiledContract totalDelegatedResourcePcc = PrecompiledContracts.getContractForAddress(totalDelegatedResourceAddr); + PrecompiledContract totalAcquiredResourcePcc = PrecompiledContracts.getContractForAddress(totalAcquiredResourceAddr); Assert.assertNull(getChainParameterPcc); - Assert.assertNull(expireFrozenBalanceV2Pcc); - Assert.assertNull(totalFrozenBalanceV2Pcc); + Assert.assertNull(availableUnfreezeV2SizePcc); + Assert.assertNull(expireUnfreezeBalanceV2Pcc); + Assert.assertNull(unfreezableBalanceV2Pcc); + + Assert.assertNull(delegatableResourcePcc); Assert.assertNull(resourceV2Pcc); + Assert.assertNull(checkUnDelegateResourcePcc); + Assert.assertNull(resourceUsagePcc); + Assert.assertNull(totalResourcePcc); + Assert.assertNull(totalDelegatedResourcePcc); + Assert.assertNull(totalAcquiredResourcePcc); + // enable TvmFreezeV2. VMConfig.initAllowTvmFreezeV2(1L); + getChainParameterPcc = PrecompiledContracts.getContractForAddress(getChainParameterAddr); - expireFrozenBalanceV2Pcc = PrecompiledContracts.getContractForAddress(expireFrozenBalanceV2Addr); - totalFrozenBalanceV2Pcc = PrecompiledContracts.getContractForAddress(totalFrozenBalanceV2Addr); + availableUnfreezeV2SizePcc = PrecompiledContracts.getContractForAddress(availableUnfreezeV2SizeAddr); + unfreezableBalanceV2Pcc = PrecompiledContracts.getContractForAddress(unfreezableBalanceV2Addr); + expireUnfreezeBalanceV2Pcc = PrecompiledContracts.getContractForAddress(expireUnfreezeBalanceV2Addr); + + delegatableResourcePcc = PrecompiledContracts.getContractForAddress(delegatableResourceAddr); resourceV2Pcc = PrecompiledContracts.getContractForAddress(resourceV2Addr); + checkUnDelegateResourcePcc = PrecompiledContracts.getContractForAddress(checkUnDelegateResourceAddr); + resourceUsagePcc = PrecompiledContracts.getContractForAddress(resourceUsageAddr); + totalResourcePcc = PrecompiledContracts.getContractForAddress(totalResourceAddr); + totalDelegatedResourcePcc = PrecompiledContracts.getContractForAddress(totalDelegatedResourceAddr); + totalAcquiredResourcePcc = PrecompiledContracts.getContractForAddress(totalAcquiredResourceAddr); Assert.assertNotNull(getChainParameterPcc); - Assert.assertNotNull(expireFrozenBalanceV2Pcc); - Assert.assertNotNull(totalFrozenBalanceV2Pcc); + Assert.assertNotNull(availableUnfreezeV2SizePcc); + Assert.assertNotNull(expireUnfreezeBalanceV2Pcc); + Assert.assertNotNull(unfreezableBalanceV2Pcc); + + Assert.assertNotNull(delegatableResourcePcc); Assert.assertNotNull(resourceV2Pcc); + Assert.assertNotNull(checkUnDelegateResourcePcc); + Assert.assertNotNull(resourceUsagePcc); + Assert.assertNotNull(totalResourcePcc); + Assert.assertNotNull(totalDelegatedResourcePcc); + Assert.assertNotNull(totalAcquiredResourcePcc); } @Test @@ -397,10 +432,10 @@ public void getChainParameterTest() { } @Test - public void getExpireFrozenBalanceV2Test() { + public void expireUnfreezeBalanceV2Test() { VMConfig.initAllowTvmFreezeV2(1L); - PrecompiledContract expireFrozenBalanceV2Pcc = createPrecompiledContract(expireFrozenBalanceV2Addr, OWNER_ADDRESS); + PrecompiledContract expireUnfreezeBalanceV2Pcc = createPrecompiledContract(expireUnfreezeBalanceV2Addr, OWNER_ADDRESS); } From 7786450c58610ef33ee7431ada3c12a901df36aa Mon Sep 17 00:00:00 2001 From: Liulei Date: Thu, 20 Oct 2022 14:39:20 +0800 Subject: [PATCH 0323/1197] feat(freezeV2): otw: add freezeV2 test --- .../org/tron/core/vm/program/Program.java | 6 +- .../tron/common/runtime/vm/FreezeV2Test.java | 493 ++++++++++++++++++ 2 files changed, 496 insertions(+), 3 deletions(-) create mode 100644 framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 5c341fbbf5c..b9a3d13da17 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -1934,7 +1934,7 @@ public boolean cancelAllUnfreezeV2Action() { increaseNonce(); InternalTransaction internalTx = addInternalTx(null, owner, owner, 0, null, - "cancelUnfreeze", nonce, null); + "cancelAllUnfreezeV2", nonce, null); try { CancelAllUnfreezeV2Param param = new CancelAllUnfreezeV2Param(); @@ -1946,9 +1946,9 @@ public boolean cancelAllUnfreezeV2Action() { repository.commit(); return true; } catch (ContractValidateException e) { - logger.error("TVM cancelUnfreezeV2Action: validate failure. Reason: {}", e.getMessage()); + logger.error("TVM cancelAllUnfreezeV2Action: validate failure. Reason: {}", e.getMessage()); } catch (ContractExeException e) { - logger.error("TVM cancelUnfreezeV2Action: execute failure. Reason: {}", e.getMessage()); + logger.error("TVM cancelAllUnfreezeV2Action: execute failure. Reason: {}", e.getMessage()); } if (internalTx != null) { internalTx.reject(); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java new file mode 100644 index 00000000000..6c2a6af45e9 --- /dev/null +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -0,0 +1,493 @@ +package org.tron.common.runtime.vm; + +import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.Protocol.Transaction.Result.contractResult.REVERT; +import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS; + +import com.google.protobuf.ByteString; +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.runtime.Runtime; +import org.tron.common.runtime.RuntimeImpl; +import org.tron.common.runtime.TVMTestResult; +import org.tron.common.runtime.TvmTestUtils; +import org.tron.common.utils.Commons; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.StringUtil; +import org.tron.common.utils.WalletUtil; +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.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.db.TransactionTrace; +import org.tron.core.store.AccountStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.store.StoreFactory; +import org.tron.core.vm.config.ConfigLoader; +import org.tron.core.vm.config.VMConfig; +import org.tron.core.vm.repository.Repository; +import org.tron.core.vm.repository.RepositoryImpl; +import org.tron.protos.Protocol; +import org.tron.protos.Protocol.Transaction.Result.contractResult; +import stest.tron.wallet.common.client.utils.AbiUtil; + +@Slf4j +public class FreezeV2Test { + + private static final String FREEZE_V2_CODE = + "60806040526111a6806100136000396000f3fe608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b50600436106101245760003560e01c80633dcba6fc116100bc578063a1243ded1161008b578063a1243ded1461030f578063a465bb191461033f578063b335634e1461035d578063c1a98a371461038d578063c8115bb7146103bd57610124565b80633dcba6fc146102715780635f5437741461028f57806385510c71146102bf5780639eb506e2146102df57610124565b80632fe36be5116100f85780632fe36be5146101c35780633160a6fc146101df57806333e7645d1461020f578063350a02341461023f57610124565b8062a73f7b14610129578063089480871461015b57806308bee6c414610177578063236051ed14610193575b600080fd5b610143600480360381019061013e9190610c73565b6103ee565b60405161015293929190610cd5565b60405180910390f35b61017560048036038101906101709190610d55565b610470565b005b610191600480360381019061018c9190610da8565b6104dc565b005b6101ad60048036038101906101a89190610de8565b61052e565b6040516101ba9190610e28565b60405180910390f35b6101dd60048036038101906101d89190610da8565b6105a4565b005b6101f960048036038101906101f49190610e43565b6105f6565b6040516102069190610e28565b60405180910390f35b61022960048036038101906102249190610de8565b610669565b6040516102369190610e28565b60405180910390f35b61025960048036038101906102549190610d55565b6106df565b60405161026893929190610cd5565b60405180910390f35b610279610760565b6040516102869190610e28565b60405180910390f35b6102a960048036038101906102a49190610e70565b61079f565b6040516102b69190610e28565b60405180910390f35b6102c76107fb565b6040516102d693929190610cd5565b60405180910390f35b6102f960048036038101906102f49190610de8565b610918565b6040516103069190610e28565b60405180910390f35b61032960048036038101906103249190610de8565b61098e565b6040516103369190610e28565b60405180910390f35b610347610a04565b6040516103549190610e28565b60405180910390f35b61037760048036038101906103729190610e9d565b610a43565b6040516103849190610e28565b60405180910390f35b6103a760048036038101906103a29190610de8565b610abc565b6040516103b49190610e28565b60405180910390f35b6103d760048036038101906103d29190610e9d565b610b32565b6040516103e5929190610ef0565b60405180910390f35b60008060008573ffffffffffffffffffffffffffffffffffffffff16630100001190868660405161042193929190610f28565b606060405180830381855afa15801561043e573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906104619190610f74565b92509250925093509350939050565b8073ffffffffffffffffffffffffffffffffffffffff168383de15801561049b573d6000803e3d6000fd5b507f025526dfa15721b77133358f4ef9591e878434240705071b580f0f8f955153be8383836040516104cf93929190611026565b60405180910390a1505050565b8181da1580156104f0573d6000803e3d6000fd5b507fc20c50cd22b066cd9d0cbbe9adbdee2f66da283d9971f5ff840fb01af79d98088282604051610522929190610ef0565b60405180910390a15050565b60008273ffffffffffffffffffffffffffffffffffffffff166301000014908360405161055c92919061105d565b602060405180830381855afa158015610579573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061059c9190611086565b905092915050565b8181db1580156105b8573d6000803e3d6000fd5b507fa2339ebec95cc02eea0ca9e15e5b1b4dd568105de8c4e47d2c6b96b1969348e882826040516105ea929190610ef0565b60405180910390a15050565b60008173ffffffffffffffffffffffffffffffffffffffff16630100000c9060405161062291906110b3565b602060405180830381855afa15801561063f573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906106629190611086565b9050919050565b60008273ffffffffffffffffffffffffffffffffffffffff16630100000f908360405161069792919061105d565b602060405180830381855afa1580156106b4573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906106d79190611086565b905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff168686df15801561070f573d6000803e3d6000fd5b508093508194508295505050507f42fddce307cf00fa55a23fcc80c1d2ba08ddce9776bbced3d1657321ed2b7bbe86868660405161074f93929190611026565b60405180910390a193509350939050565b6000dc90507f6f00343c17c6cb3178a14fe2a1b401a5ebaede910e21ee237af268c641450153816040516107949190610e28565b60405180910390a190565b6000630100000e826040516107b49190610e28565b602060405180830381855afa1580156107d1573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906107f49190611086565b9050919050565b600080600080600160405181601f820153602081602083630100000b5afa610829576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff8316831461084a57600080fd5b50506000600260405181601f820153602081602083630100000b5afa610876576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff8316831461089757600080fd5b50506000600360405181601f820153602081602083630100000b5afa6108c3576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff831683146108e457600080fd5b50508267ffffffffffffffff1692508167ffffffffffffffff1691508067ffffffffffffffff169050925092509250909192565b60008273ffffffffffffffffffffffffffffffffffffffff166301000013908360405161094692919061105d565b602060405180830381855afa158015610963573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906109869190611086565b905092915050565b60008273ffffffffffffffffffffffffffffffffffffffff16630100000d90836040516109bc92919061105d565b602060405180830381855afa1580156109d9573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906109fc9190611086565b905092915050565b6000dd90507f6a5f656ed489ef1dec34a7317ceb95e7363440f72efdb653107e66982370f06181604051610a389190610e28565b60405180910390a190565b60008373ffffffffffffffffffffffffffffffffffffffff166301000010908484604051610a73939291906110ce565b602060405180830381855afa158015610a90573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610ab39190611086565b90509392505050565b60008273ffffffffffffffffffffffffffffffffffffffff1663010000159083604051610aea92919061105d565b602060405180830381855afa158015610b07573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610b2a9190611086565b905092915050565b6000808473ffffffffffffffffffffffffffffffffffffffff166301000012908585604051610b63939291906110ce565b6040805180830381855afa158015610b7f573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610ba29190611105565b91509150935093915050565b600080fd5b600074ffffffffffffffffffffffffffffffffffffffffff82169050919050565b610bdd81610bb3565b8114610be857600080fd5b50565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610c1682610beb565b9050919050565b600081359050610c2c81610bd4565b610c3581610c0b565b905092915050565b6000819050919050565b610c5081610c3d565b8114610c5b57600080fd5b50565b600081359050610c6d81610c47565b92915050565b600080600060608486031215610c8c57610c8b610bae565b5b6000610c9a86828701610c1d565b9350506020610cab86828701610c5e565b9250506040610cbc86828701610c5e565b9150509250925092565b610ccf81610c3d565b82525050565b6000606082019050610cea6000830186610cc6565b610cf76020830185610cc6565b610d046040830184610cc6565b949350505050565b610d1581610bb3565b8114610d2057600080fd5b50565b6000610d2e82610beb565b9050919050565b600081359050610d4481610d0c565b610d4d81610d23565b905092915050565b600080600060608486031215610d6e57610d6d610bae565b5b6000610d7c86828701610c5e565b9350506020610d8d86828701610c5e565b9250506040610d9e86828701610d35565b9150509250925092565b60008060408385031215610dbf57610dbe610bae565b5b6000610dcd85828601610c5e565b9250506020610dde85828601610c5e565b9150509250929050565b60008060408385031215610dff57610dfe610bae565b5b6000610e0d85828601610c1d565b9250506020610e1e85828601610c5e565b9150509250929050565b6000602082019050610e3d6000830184610cc6565b92915050565b600060208284031215610e5957610e58610bae565b5b6000610e6784828501610c1d565b91505092915050565b600060208284031215610e8657610e85610bae565b5b6000610e9484828501610c5e565b91505092915050565b600080600060608486031215610eb657610eb5610bae565b5b6000610ec486828701610c1d565b9350506020610ed586828701610c1d565b9250506040610ee686828701610c5e565b9150509250925092565b6000604082019050610f056000830185610cc6565b610f126020830184610cc6565b9392505050565b610f2281610c0b565b82525050565b6000606082019050610f3d6000830186610f19565b610f4a6020830185610cc6565b610f576040830184610cc6565b949350505050565b600081519050610f6e81610c47565b92915050565b600080600060608486031215610f8d57610f8c610bae565b5b6000610f9b86828701610f5f565b9350506020610fac86828701610f5f565b9250506040610fbd86828701610f5f565b9150509250925092565b6000819050919050565b6000610fec610fe7610fe284610beb565b610fc7565b610beb565b9050919050565b6000610ffe82610fd1565b9050919050565b600061101082610ff3565b9050919050565b61102081611005565b82525050565b600060608201905061103b6000830186610cc6565b6110486020830185610cc6565b6110556040830184611017565b949350505050565b60006040820190506110726000830185610f19565b61107f6020830184610cc6565b9392505050565b60006020828403121561109c5761109b610bae565b5b60006110aa84828501610f5f565b91505092915050565b60006020820190506110c86000830184610f19565b92915050565b60006060820190506110e36000830186610f19565b6110f06020830185610f19565b6110fd6040830184610cc6565b949350505050565b6000806040838503121561111c5761111b610bae565b5b600061112a85828601610f5f565b925050602061113b85828601610f5f565b915050925092905056fea26474726f6e58221220cd9e546d3bedc2f439b615ab724a0cb6f44e676c635038b29a20a7f3c712c64f64736f6c63782d302e382e31372d646576656c6f702e323032322e31302e31392b636f6d6d69742e34313134656332632e6d6f64005e"; + + private static final long value = 100_000_000_000_000_000L; + private static final long fee = 1_000_000_000; + private static final String userAStr = "27k66nycZATHzBasFT9782nTsYWqVtxdtAc"; + private static final byte[] userA = Commons.decode58Check(userAStr); + private static final String userBStr = "27jzp7nVEkH4Hf3H1PHPp4VDY7DxTy5eydL"; + private static final byte[] userB = Commons.decode58Check(userBStr); + private static final String userCStr = "27juXSbMvL6pb8VgmKRgW6ByCfw5RqZjUuo"; + private static final byte[] userC = Commons.decode58Check(userCStr); + + private static String dbPath; + private static TronApplicationContext context; + private static Manager manager; + private static byte[] owner; + private static Repository rootRepository; + + @Before + public void init() throws Exception { + dbPath = "output_" + FreezeV2Test.class.getName(); + Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + manager = context.getBean(Manager.class); + owner = Hex.decode(Wallet.getAddressPreFixString() + + "abd4b9367799eaa3197fecb144eb71de1e049abc"); + rootRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + rootRepository.createAccount(owner, Protocol.AccountType.Normal); + rootRepository.addBalance(owner, 900_000_000_000_000_000L); + rootRepository.commit(); + + ConfigLoader.disable = true; + manager.getDynamicPropertiesStore().saveAllowTvmFreeze(1); + VMConfig.initVmHardFork(true); + VMConfig.initAllowTvmTransferTrc10(1); + VMConfig.initAllowTvmConstantinople(1); + VMConfig.initAllowTvmSolidity059(1); + VMConfig.initAllowTvmIstanbul(1); + VMConfig.initAllowTvmFreezeV2(1); + } + + private byte[] deployContract(String contractName, String code) throws Exception { + return deployContract(owner, contractName, code, 0, 100_000); + } + + private byte[] deployContract(byte[] deployer, + String contractName, + String code, + long consumeUserResourcePercent, + long originEnergyLimit) throws Exception { + Protocol.Transaction trx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( + contractName, deployer, "[]", code, value, fee, consumeUserResourcePercent, + null, originEnergyLimit); + byte[] contractAddr = WalletUtil.generateContractAddress(trx); + //String contractAddrStr = StringUtil.encode58Check(contractAddr); + TransactionCapsule trxCap = new TransactionCapsule(trx); + TransactionTrace trace = new TransactionTrace(trxCap, StoreFactory.getInstance(), + new RuntimeImpl()); + trxCap.setTrxTrace(trace); + trace.init(null); + trace.exec(); + trace.finalization(); + Runtime runtime = trace.getRuntime(); + Assert.assertEquals(SUCCESS, runtime.getResult().getResultCode()); + Assert.assertEquals(value, manager.getAccountStore().get(contractAddr).getBalance()); + + return contractAddr; + } + + private TVMTestResult triggerContract(byte[] callerAddr, + byte[] contractAddr, + long feeLimit, + contractResult expectedResult, + Consumer check, + String method, + Object... args) throws Exception { + String hexInput = AbiUtil.parseMethod(method, Arrays.asList(args)); + TransactionCapsule trxCap = new TransactionCapsule( + TvmTestUtils.generateTriggerSmartContractAndGetTransaction( + callerAddr, contractAddr, Hex.decode(hexInput), 0, feeLimit)); + TransactionTrace trace = new TransactionTrace(trxCap, StoreFactory.getInstance(), + new RuntimeImpl()); + trxCap.setTrxTrace(trace); + trace.init(null); + trace.exec(); + trace.finalization(); + trace.setResult(); + TVMTestResult result = new TVMTestResult(trace.getRuntime(), trace.getReceipt(), null); + Assert.assertEquals(expectedResult, result.getReceipt().getResult()); + if (check != null) { + check.accept(result.getRuntime().getResult().getHReturn()); + } + return result; + } + + private TVMTestResult triggerFreeze(byte[] callerAddr, + byte[] contractAddr, + long frozenBalance, + long res, + contractResult expectedResult, + Consumer check) throws Exception { + return triggerContract(callerAddr, contractAddr, fee, expectedResult, check, + "freezeBalanceV2(uint256,uint256)", frozenBalance, res); + } + + private TVMTestResult triggerUnfreeze(byte[] callerAddr, + byte[] contractAddr, + long unfreezeBalance, + long res, + contractResult expectedResult, + Consumer check) throws Exception { + return triggerContract(callerAddr, contractAddr, fee, expectedResult, check, + "unfreezeBalanceV2(uint256,uint256)", unfreezeBalance, res); + } + + private TVMTestResult triggerWithdrawExpireUnfreeze( + byte[] callerAddr, byte[] contractAddr, contractResult expectedResult, Consumer check) + throws Exception { + return triggerContract( + callerAddr, contractAddr, fee, expectedResult, check, "withdrawExpireUnfreeze()"); + } + + private TVMTestResult triggerCancelAllUnfreezeV2( + byte[] callerAddr, byte[] contractAddr, contractResult expectedResult, Consumer check) + throws Exception { + return triggerContract( + callerAddr, contractAddr, fee, expectedResult, check, "cancelAllUnfreezeV2()"); + } + + private TVMTestResult triggerDelegateResource( + byte[] callerAddr, byte[] contractAddr, contractResult expectedResult, + Consumer check, byte[] receiverAddr, long amount, long res) + throws Exception { + return triggerContract( + callerAddr, contractAddr, fee, expectedResult, check, + "delegateResource(uint,uint,address)", amount, res, receiverAddr); + } + + private TVMTestResult triggerUnDelegateResource( + byte[] callerAddr, byte[] contractAddr, contractResult expectedResult, + Consumer check, byte[] receiverAddr, long amount, long res) + throws Exception { + return triggerContract( + callerAddr, contractAddr, fee, expectedResult, check, + "unDelegateResource(uint,uint,address)", amount, res, receiverAddr); + } + + @Test + public void testFreezeUnfreezeWithdrawAndCancel() throws Exception { + byte[] contract = deployContract("TestNewFreeze", FREEZE_V2_CODE); + long frozenBalance = 1_000_000; + + // trigger freezeBalanceV2(uint256,uint256) to get bandwidth + freezeV2(owner, contract, frozenBalance, 0); + + // trigger freezeBalanceV2(uint256,uint256) to get energy + freezeV2(owner, contract, frozenBalance, 1); + + // trigger freezeBalanceV2(uint256,uint256) to get tp + freezeV2(owner, contract, frozenBalance, 2); + + // tests of freezeBalanceV2(uint256,uint256) with invalid args + freezeV2WithException(owner, contract, frozenBalance, 3); + freezeV2WithException(owner, contract, 0, 0); + freezeV2WithException(owner, contract, -frozenBalance, 0); + freezeV2WithException(owner, contract, frozenBalance - 1, 1); + freezeV2WithException(owner, contract, value, 0); + + // not time to unfreeze + unfreezeV2WithException(owner, contract, frozenBalance, 0); + unfreezeV2WithException(owner, contract, frozenBalance, 1); + unfreezeV2WithException(owner, contract, frozenBalance, 2); + // invalid args + unfreezeV2WithException(owner, contract, frozenBalance, 3); + unfreezeV2WithException(owner, contract, -frozenBalance, 2); + unfreezeV2WithException(owner, contract, 0, 2); + + clearExpireTime(contract); + + // unfreeze + unfreezeV2(owner, contract, frozenBalance, 0); + unfreezeV2(owner, contract, frozenBalance, 1); + unfreezeV2(owner, contract, frozenBalance, 2); + // no enough balance + unfreezeV2WithException(owner, contract, frozenBalance, 0); + unfreezeV2WithException(owner, contract, frozenBalance, 1); + unfreezeV2WithException(owner, contract, frozenBalance, 2); + + // withdrawExpireUnfreeze + withdrawExpireUnfreezeWithException(owner, contract); + clearUnfreezeV2ExpireTime(contract, 0); + withdrawExpireUnfreeze(owner, contract, frozenBalance); + + withdrawExpireUnfreezeWithException(owner, contract); + clearUnfreezeV2ExpireTime(contract, 1); + withdrawExpireUnfreeze(owner, contract, frozenBalance); + + withdrawExpireUnfreezeWithException(owner, contract); + clearUnfreezeV2ExpireTime(contract, 2); + withdrawExpireUnfreeze(owner, contract, frozenBalance); + + // cancelAllUnfreezeV2 +// freezeV2(owner, contract, frozenBalance, 0); +// cancelAllUnfreezeV2(owner, contract, 0); +// clearUnfreezeV2ExpireTime(contract, 0); +// unfreezeV2(owner, contract, frozenBalance, 0); +// cancelAllUnfreezeV2(owner, contract, frozenBalance); + } + + @Test + public void testDelegateAndUnDelegateResource() throws Exception { + byte[] contract = deployContract("TestNewFreeze", FREEZE_V2_CODE); + long frozenBalance = 1_000_000; + // trigger freezeBalanceV2(uint256,uint256) to get bandwidth + freezeV2(owner, contract, frozenBalance, 0); + // trigger freezeBalanceV2(uint256,uint256) to get energy + freezeV2(owner, contract, frozenBalance, 1); + // trigger freezeBalanceV2(uint256,uint256) to get tp + freezeV2(owner, contract, frozenBalance, 2); + } + + private TVMTestResult freezeV2( + byte[] callerAddr, byte[] contractAddr, long frozenBalance, long res) throws Exception { + DynamicPropertiesStore dynamicStore = manager.getDynamicPropertiesStore(); + long oldTotalNetWeight = dynamicStore.getTotalNetWeight(); + long oldTotalEnergyWeight = dynamicStore.getTotalEnergyWeight(); + + AccountStore accountStore = manager.getAccountStore(); + AccountCapsule oldOwner = accountStore.get(contractAddr); + + TVMTestResult result = triggerFreeze(callerAddr, contractAddr, frozenBalance, res, + SUCCESS, + returnValue -> Assert.assertEquals(dynamicStore.getMinFrozenTime() * FROZEN_PERIOD, + new DataWord(returnValue).longValue() * 1000)); + + AccountCapsule newOwner = accountStore.get(contractAddr); + Assert.assertEquals(oldOwner.getBalance() - frozenBalance, newOwner.getBalance()); + newOwner.setBalance(oldOwner.getBalance()); + if (res == 0) { + Assert.assertEquals(1, newOwner.getFrozenCount()); + Assert.assertEquals(oldOwner.getFrozenBalance() + frozenBalance, newOwner.getFrozenBalance()); + Assert.assertEquals(oldTotalNetWeight + frozenBalance / TRX_PRECISION, + dynamicStore.getTotalNetWeight()); + Assert.assertEquals(oldTotalEnergyWeight, dynamicStore.getTotalEnergyWeight()); + oldOwner.setFrozenForBandwidth(0, 0); + newOwner.setFrozenForBandwidth(0, 0); + } else { + Assert.assertEquals(oldOwner.getEnergyFrozenBalance() + frozenBalance, + newOwner.getEnergyFrozenBalance()); + Assert.assertEquals(oldTotalNetWeight, dynamicStore.getTotalNetWeight()); + Assert.assertEquals(oldTotalEnergyWeight + frozenBalance / TRX_PRECISION, + dynamicStore.getTotalEnergyWeight()); + oldOwner.setFrozenForEnergy(0, 0); + newOwner.setFrozenForEnergy(0, 0); + } + Assert.assertArrayEquals(oldOwner.getData(), newOwner.getData()); + + return result; + } + + private TVMTestResult freezeV2WithException( + byte[] callerAddr, byte[] contractAddr, long frozenBalance, long res) throws Exception { + return triggerFreeze(callerAddr, contractAddr, frozenBalance, res, REVERT, null); + } + + private TVMTestResult unfreezeV2WithException( + byte[] callerAddr, byte[] contractAddr, long unfreezeBalance, long res) throws Exception { + return triggerUnfreeze(callerAddr, contractAddr, unfreezeBalance, res, REVERT, null); + } + + private void clearExpireTime(byte[] owner) { + AccountCapsule accountCapsule = manager.getAccountStore().get(owner); + long now = manager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); + accountCapsule.setFrozenForBandwidth(accountCapsule.getFrozenBalance(), now); + accountCapsule.setFrozenForEnergy(accountCapsule.getEnergyFrozenBalance(), now); + manager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + } + + private TVMTestResult unfreezeV2( + byte[] callerAddr, byte[] contractAddr, long unfreezeBalance, long res) throws Exception { + DynamicPropertiesStore dynamicStore = manager.getDynamicPropertiesStore(); + long oldTotalNetWeight = dynamicStore.getTotalNetWeight(); + long oldTotalEnergyWeight = dynamicStore.getTotalEnergyWeight(); + + AccountStore accountStore = manager.getAccountStore(); + AccountCapsule oldOwner = accountStore.get(contractAddr); + long frozenBalance = res == 0 ? oldOwner.getFrozenBalance() : oldOwner.getEnergyFrozenBalance(); + Assert.assertTrue(frozenBalance > 0); + + TVMTestResult result = triggerUnfreeze(callerAddr, contractAddr, unfreezeBalance, res, SUCCESS, + returnValue -> + Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001", + Hex.toHexString(returnValue))); + + AccountCapsule newOwner = accountStore.get(contractAddr); + Assert.assertEquals(oldOwner.getBalance() + frozenBalance, newOwner.getBalance()); + oldOwner.setBalance(newOwner.getBalance()); + if (res == 0) { + Assert.assertEquals(0, newOwner.getFrozenCount()); + Assert.assertEquals(0, newOwner.getFrozenBalance()); + Assert.assertEquals(oldTotalNetWeight - frozenBalance / TRX_PRECISION, + dynamicStore.getTotalNetWeight()); + Assert.assertEquals(oldTotalEnergyWeight, dynamicStore.getTotalEnergyWeight()); + oldOwner.setFrozenForBandwidth(0, 0); + newOwner.setFrozenForBandwidth(0, 0); + } else { + Assert.assertEquals(0, newOwner.getEnergyFrozenBalance()); + Assert.assertEquals(oldTotalNetWeight, dynamicStore.getTotalNetWeight()); + Assert.assertEquals(oldTotalEnergyWeight - frozenBalance / TRX_PRECISION, + dynamicStore.getTotalEnergyWeight()); + oldOwner.setFrozenForEnergy(0, 0); + newOwner.setFrozenForEnergy(0, 0); + } + Assert.assertArrayEquals(oldOwner.getData(), newOwner.getData()); + + return result; + } + + private void clearUnfreezeV2ExpireTime(byte[] owner, long res) { + AccountCapsule accountCapsule = manager.getAccountStore().get(owner); + long now = manager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); + List newUnfreezeV2List = new ArrayList<>(); + accountCapsule.getUnfrozenV2List().forEach(unFreezeV2 -> { + if (unFreezeV2.getType().getNumber() == res) { + newUnfreezeV2List.add(unFreezeV2.toBuilder().setUnfreezeExpireTime(now).build()); + } else { + newUnfreezeV2List.add(unFreezeV2); + } + }); + accountCapsule.clearUnfrozenV2(); + newUnfreezeV2List.forEach(accountCapsule::addUnfrozenV2); + manager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + } + + private TVMTestResult withdrawExpireUnfreeze( + byte[] callerAddr, byte[] contractAddr, long expectedWithdrawBalance) throws Exception { + AccountStore accountStore = manager.getAccountStore(); + AccountCapsule oldOwner = accountStore.get(contractAddr); + long oldBalance = oldOwner.getBalance(); + + TVMTestResult result = triggerWithdrawExpireUnfreeze(callerAddr, contractAddr, SUCCESS, + returnValue -> + Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001", + Hex.toHexString(returnValue))); + + AccountCapsule newOwner = accountStore.get(contractAddr); + Assert.assertEquals(oldBalance + expectedWithdrawBalance, newOwner.getBalance()); + oldOwner.setBalance(newOwner.getBalance()); + Assert.assertArrayEquals(oldOwner.getData(), newOwner.getData()); + + return result; + } + + private TVMTestResult withdrawExpireUnfreezeWithException(byte[] callerAddr, byte[] contractAddr) + throws Exception { + return triggerWithdrawExpireUnfreeze(callerAddr, contractAddr, REVERT, null); + } + + private TVMTestResult cancelAllUnfreezeV2( + byte[] callerAddr, byte[] contractAddr, long expectedWithdrawBalance) throws Exception { + AccountStore accountStore = manager.getAccountStore(); + AccountCapsule oldOwner = accountStore.get(contractAddr); + long oldBalance = oldOwner.getBalance(); + long now = manager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); + + TVMTestResult result = triggerCancelAllUnfreezeV2(callerAddr, contractAddr, SUCCESS, + returnValue -> + Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001", + Hex.toHexString(returnValue))); + + AccountCapsule newOwner = accountStore.get(contractAddr); + long unfreezeV2Amount = newOwner.getUnfreezingV2Count(now); + Assert.assertEquals(0, unfreezeV2Amount); + Assert.assertEquals(expectedWithdrawBalance, newOwner.getBalance() - oldBalance); + oldOwner.setBalance(newOwner.getBalance()); + Assert.assertArrayEquals(oldOwner.getData(), newOwner.getData()); + + return result; + } + +// private TVMTestResult delegateResource( +// byte[] callerAddr, byte[] contractAddr, long expectedWithdrawBalance) throws Exception { +// AccountStore accountStore = manager.getAccountStore(); +// AccountCapsule oldOwner = accountStore.get(contractAddr); +// long oldBalance = oldOwner.getBalance(); +// +// TVMTestResult result = triggerWithdrawExpireUnfreeze(callerAddr, contractAddr, SUCCESS, +// returnValue -> +// Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001", +// Hex.toHexString(returnValue))); +// +// AccountCapsule newOwner = accountStore.get(contractAddr); +// Assert.assertEquals(oldBalance + expectedWithdrawBalance, newOwner.getBalance()); +// oldOwner.setBalance(newOwner.getBalance()); +// Assert.assertArrayEquals(oldOwner.getData(), newOwner.getData()); +// +// return result; +// } +// +// private TVMTestResult delegateResourceWithException(byte[] callerAddr, byte[] contractAddr) +// throws Exception { +// return triggerDelegateResource(callerAddr, contractAddr, REVERT, null); +// } +// +// private TVMTestResult unDelegateResource( +// byte[] callerAddr, byte[] contractAddr, long expectedWithdrawBalance) throws Exception { +// AccountStore accountStore = manager.getAccountStore(); +// AccountCapsule oldOwner = accountStore.get(contractAddr); +// long oldBalance = oldOwner.getBalance(); +// +// TVMTestResult result = triggerWithdrawExpireUnfreeze(callerAddr, contractAddr, SUCCESS, +// returnValue -> +// Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001", +// Hex.toHexString(returnValue))); +// +// AccountCapsule newOwner = accountStore.get(contractAddr); +// Assert.assertEquals(oldBalance + expectedWithdrawBalance, newOwner.getBalance()); +// oldOwner.setBalance(newOwner.getBalance()); +// Assert.assertArrayEquals(oldOwner.getData(), newOwner.getData()); +// +// return result; +// } +// +// private TVMTestResult unDelegateResourceWithException(byte[] callerAddr, byte[] contractAddr) +// throws Exception { +// return triggerUnDelegateResource(callerAddr, contractAddr, REVERT, null); +// } + + @After + public void destroy() { + ConfigLoader.disable = false; + VMConfig.initVmHardFork(false); + Args.clearParam(); + context.destroy(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.error("Release resources failure."); + } + } +} From 770cfba7980865a4e5d72d028f9f7031bd4b2a12 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Mon, 29 Aug 2022 15:21:38 +0800 Subject: [PATCH 0324/1197] feat(unfreeze): add freezeV2 & unfreezeV2 related protocols --- protocol/src/main/protos/core/Tron.proto | 23 +++++++++++++++++++ .../core/contract/balance_contract.proto | 18 +++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 9d4af0a3151..3d1e2330ce8 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -214,6 +214,26 @@ message Account { Permission owner_permission = 31; Permission witness_permission = 32; repeated Permission active_permission = 33; + + // FREEZE_TYPE is extended ResourceCode of the common package. + enum FREEZE_TYPE { + BANDWIDTH = 0; + ENERGY = 1; + POWER = 2; + DELEGATED_BANDWIDTH = 3; + DELEGATED_ENERGY = 4; + } + message FreezeV2 { + FREEZE_TYPE type = 1; + int64 amount = 2; + } + message UnFreezeV2 { + FREEZE_TYPE type = 1; + int64 unfreeze_amount = 3; + int64 unfreeze_expire_time = 4; + } + repeated FreezeV2 frozenV2 = 34; + repeated UnFreezeV2 unfrozenV2 = 35; } message Key { @@ -346,6 +366,9 @@ message Transaction { ShieldedTransferContract = 51; MarketSellAssetContract = 52; MarketCancelOrderContract = 53; + FreezeBalanceV2Contract = 54; + UnfreezeBalanceV2Contract = 55; + WithdrawBalanceV2Contract = 56; } ContractType type = 1; google.protobuf.Any parameter = 2; diff --git a/protocol/src/main/protos/core/contract/balance_contract.proto b/protocol/src/main/protos/core/contract/balance_contract.proto index 293f62bed5b..795f17a9d0b 100644 --- a/protocol/src/main/protos/core/contract/balance_contract.proto +++ b/protocol/src/main/protos/core/contract/balance_contract.proto @@ -80,3 +80,21 @@ message AccountBalanceResponse { int64 balance = 1; BlockBalanceTrace.BlockIdentifier block_identifier = 2; } + +message FreezeBalanceV2Contract { + bytes owner_address = 1; + int64 frozen_balance = 2; + ResourceCode resource = 3; + bytes receiver_address = 4; +} + +message UnfreezeBalanceV2Contract { + bytes owner_address = 1; + int64 unfreeze_balance = 2; + ResourceCode resource = 3; + bytes receiver_address = 4; +} + +message WithdrawBalanceV2Contract { + bytes owner_address = 1; +} \ No newline at end of file From 56a32ada7ce56559933d3e44fdfcb91096b03243 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Thu, 15 Sep 2022 11:47:14 +0800 Subject: [PATCH 0325/1197] feat(freezeV2): separate delegate resources from the freeze --- protocol/src/main/protos/core/Tron.proto | 15 +++++---------- .../protos/core/contract/balance_contract.proto | 16 ++++++++++++++-- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 3d1e2330ce8..ba0e7d1b414 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -2,6 +2,7 @@ syntax = "proto3"; import "google/protobuf/any.proto"; import "core/Discover.proto"; +import "core/contract/common.proto"; package protocol; @@ -215,20 +216,12 @@ message Account { Permission witness_permission = 32; repeated Permission active_permission = 33; - // FREEZE_TYPE is extended ResourceCode of the common package. - enum FREEZE_TYPE { - BANDWIDTH = 0; - ENERGY = 1; - POWER = 2; - DELEGATED_BANDWIDTH = 3; - DELEGATED_ENERGY = 4; - } message FreezeV2 { - FREEZE_TYPE type = 1; + ResourceCode type = 1; int64 amount = 2; } message UnFreezeV2 { - FREEZE_TYPE type = 1; + ResourceCode type = 1; int64 unfreeze_amount = 3; int64 unfreeze_expire_time = 4; } @@ -369,6 +362,8 @@ message Transaction { FreezeBalanceV2Contract = 54; UnfreezeBalanceV2Contract = 55; WithdrawBalanceV2Contract = 56; + DelegateResourceContract = 57; + UnDelegateResourceContract = 58; } ContractType type = 1; google.protobuf.Any parameter = 2; diff --git a/protocol/src/main/protos/core/contract/balance_contract.proto b/protocol/src/main/protos/core/contract/balance_contract.proto index 795f17a9d0b..db54939a3d4 100644 --- a/protocol/src/main/protos/core/contract/balance_contract.proto +++ b/protocol/src/main/protos/core/contract/balance_contract.proto @@ -85,16 +85,28 @@ message FreezeBalanceV2Contract { bytes owner_address = 1; int64 frozen_balance = 2; ResourceCode resource = 3; - bytes receiver_address = 4; } message UnfreezeBalanceV2Contract { bytes owner_address = 1; int64 unfreeze_balance = 2; ResourceCode resource = 3; - bytes receiver_address = 4; } message WithdrawBalanceV2Contract { bytes owner_address = 1; +} + +message DelegateResourceContract { + bytes owner_address = 1; + ResourceCode resource = 2; + int64 balance = 3; + bytes receiver_address = 4; +} + +message UnDelegateResourceContract { + bytes owner_address = 1; + ResourceCode resource = 2; + int64 balance = 3; + bytes receiver_address = 4; } \ No newline at end of file From 8f42ab4eabc84ff78b4ab4b612bc2994e4e58e8a Mon Sep 17 00:00:00 2001 From: chaozhu Date: Mon, 19 Sep 2022 16:33:17 -0700 Subject: [PATCH 0326/1197] feat(freezeV2): new unfreeze program 1. add UNFREEZE_DELAY_DAYS proposal 2. add new freeze/unfreeze actuator Closes # --- .../core/actuator/FreezeBalanceActuator.java | 5 + .../actuator/FreezeBalanceV2Actuator.java | 163 ++++ .../actuator/UnfreezeBalanceV2Actuator.java | 320 +++++++ .../org/tron/core/utils/ProposalUtil.java | 15 +- .../org/tron/core/capsule/AccountCapsule.java | 159 +++- .../core/store/DynamicPropertiesStore.java | 22 + .../common/parameter/CommonParameter.java | 4 + .../src/main/java/org/tron/core/Wallet.java | 5 + .../tron/core/consensus/ProposalService.java | 7 + .../org/tron/core/services/RpcApiService.java | 13 + .../services/http/FreezeBalanceV2Servlet.java | 36 + .../http/UnFreezeBalanceV2Servlet.java | 38 + .../http/WithdrawBalanceV2Servlet.java | 43 + .../actuator/FreezeBalanceV2ActuatorTest.java | 546 ++++++++++++ .../UnfreezeBalanceV2ActuatorTest.java | 836 ++++++++++++++++++ protocol/src/main/protos/api/api.proto | 8 + 16 files changed, 2214 insertions(+), 6 deletions(-) create mode 100755 actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java create mode 100755 actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java create mode 100644 framework/src/main/java/org/tron/core/services/http/FreezeBalanceV2Servlet.java create mode 100644 framework/src/main/java/org/tron/core/services/http/UnFreezeBalanceV2Servlet.java create mode 100644 framework/src/main/java/org/tron/core/services/http/WithdrawBalanceV2Servlet.java create mode 100644 framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java create mode 100644 framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java index f026a8769e6..e194999a25f 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java @@ -249,6 +249,11 @@ public boolean validate() throws ContractValidateException { } + if (dynamicStore.getUnfreezeDelayDays() > 0) { + throw new ContractValidateException( + "freeze v2 is open, old freeze is closed"); + } + return true; } diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java new file mode 100755 index 00000000000..743aaff6824 --- /dev/null +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java @@ -0,0 +1,163 @@ +package org.tron.core.actuator; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import lombok.extern.slf4j.Slf4j; +import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.AccountStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.BalanceContract.FreezeBalanceV2Contract; +import java.util.Objects; + +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +@Slf4j(topic = "actuator") +public class FreezeBalanceV2Actuator extends AbstractActuator { + + public FreezeBalanceV2Actuator() { + super(ContractType.FreezeBalanceV2Contract, FreezeBalanceV2Contract.class); + } + + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + + long fee = calcFee(); + final FreezeBalanceV2Contract freezeBalanceV2Contract; + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + try { + freezeBalanceV2Contract = any.unpack(FreezeBalanceV2Contract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + AccountCapsule accountCapsule = accountStore.get(freezeBalanceV2Contract.getOwnerAddress().toByteArray()); + + if (dynamicStore.supportAllowNewResourceModel() + && accountCapsule.oldTronPowerIsNotInitialized()) { + accountCapsule.initializeOldTronPower(); + } + + long newBalance = accountCapsule.getBalance() - freezeBalanceV2Contract.getFrozenBalance(); + long frozenBalance = freezeBalanceV2Contract.getFrozenBalance(); + + switch (freezeBalanceV2Contract.getResource()) { + case BANDWIDTH: + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + dynamicStore.addTotalNetWeight(frozenBalance / TRX_PRECISION); + break; + case ENERGY: + accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); + dynamicStore.addTotalEnergyWeight(frozenBalance / TRX_PRECISION); + break; + case TRON_POWER: + accountCapsule.addFrozenForTronPowerV2(frozenBalance); + dynamicStore.addTotalTronPowerWeight(frozenBalance / TRX_PRECISION); + break; + default: + logger.debug("Resource Code Error."); + } + + accountCapsule.setBalance(newBalance); + accountStore.put(accountCapsule.createDbKey(), accountCapsule); + + ret.setStatus(fee, code.SUCESS); + + return true; + } + + + @Override + public boolean validate() throws ContractValidateException { + if (this.any == null) { + throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); + } + if (chainBaseManager == null) { + throw new ContractValidateException(ActuatorConstant.STORE_NOT_EXIST); + } + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + if (!any.is(FreezeBalanceV2Contract.class)) { + throw new ContractValidateException( + "contract type error,expected type [FreezeBalanceV2Contract],real type[" + any + .getClass() + "]"); + } + + final FreezeBalanceV2Contract freezeBalanceV2Contract; + try { + freezeBalanceV2Contract = this.any.unpack(FreezeBalanceV2Contract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + throw new ContractValidateException(e.getMessage()); + } + byte[] ownerAddress = freezeBalanceV2Contract.getOwnerAddress().toByteArray(); + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + + AccountCapsule accountCapsule = accountStore.get(ownerAddress); + if (accountCapsule == null) { + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + throw new ContractValidateException( + ActuatorConstant.ACCOUNT_EXCEPTION_STR + readableOwnerAddress + NOT_EXIST_STR); + } + + long frozenBalance = freezeBalanceV2Contract.getFrozenBalance(); + if (frozenBalance <= 0) { + throw new ContractValidateException("frozenBalance must be positive"); + } + if (frozenBalance < TRX_PRECISION) { + throw new ContractValidateException("frozenBalance must be more than 1TRX"); + } + + if (frozenBalance > accountCapsule.getBalance()) { + throw new ContractValidateException("frozenBalance must be less than accountBalance"); + } + + switch (freezeBalanceV2Contract.getResource()) { + case BANDWIDTH: + case ENERGY: + break; + case TRON_POWER: + if (!dynamicStore.supportAllowNewResourceModel()) { + throw new ContractValidateException( + "ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]"); + } + break; + default: + if (dynamicStore.supportAllowNewResourceModel()) { + throw new ContractValidateException( + "ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY、TRON_POWER]"); + } else { + throw new ContractValidateException( + "ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]"); + } + } + + return true; + } + + @Override + public ByteString getOwnerAddress() throws InvalidProtocolBufferException { + return any.unpack(FreezeBalanceV2Contract.class).getOwnerAddress(); + } + + @Override + public long calcFee() { + return 0; + } + +} \ No newline at end of file diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java new file mode 100755 index 00000000000..09c2b90e6ef --- /dev/null +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java @@ -0,0 +1,320 @@ +package org.tron.core.actuator; + +import com.google.common.collect.Lists; +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import lombok.extern.slf4j.Slf4j; +import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.capsule.VotesCapsule; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.service.MortgageService; +import org.tron.core.store.AccountStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.store.VotesStore; +import org.tron.protos.Protocol; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.BalanceContract.UnfreezeBalanceV2Contract; +import org.tron.protos.contract.Common; + +import java.util.Iterator; +import java.util.List; +import java.util.Objects; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +@Slf4j(topic = "actuator") +public class UnfreezeBalanceV2Actuator extends AbstractActuator { + + private static final int UNFREEZE_MAX_TIMES = 32; + + public UnfreezeBalanceV2Actuator() { + super(ContractType.UnfreezeBalanceV2Contract, UnfreezeBalanceV2Contract.class); + } + + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + + long fee = calcFee(); + final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract; + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + MortgageService mortgageService = chainBaseManager.getMortgageService(); + try { + unfreezeBalanceV2Contract = any.unpack(UnfreezeBalanceV2Contract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + byte[] ownerAddress = unfreezeBalanceV2Contract.getOwnerAddress().toByteArray(); + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + + mortgageService.withdrawReward(ownerAddress); + + AccountCapsule accountCapsule = accountStore.get(ownerAddress); + this.unfreezeExpire(accountCapsule, now); + long unfreezeBalance = unfreezeBalanceV2Contract.getUnfreezeBalance(); + + if (dynamicStore.supportAllowNewResourceModel() + && accountCapsule.oldTronPowerIsNotInitialized()) { + accountCapsule.initializeOldTronPower(); + } + + Common.ResourceCode freezeType = unfreezeBalanceV2Contract.getResource(); + + this.updateAccountFrozenInfo(freezeType, accountCapsule, unfreezeBalance); + + long expireTime = this.calcUnfreezeExpireTime(now); + accountCapsule.addUnfrozenV2List(freezeType, unfreezeBalance, expireTime); + + this.updateTotalResourceWeight(unfreezeBalanceV2Contract, unfreezeBalance); + this.clearVotes(accountCapsule,unfreezeBalanceV2Contract, ownerAddress); + + if (dynamicStore.supportAllowNewResourceModel() + && !accountCapsule.oldTronPowerIsInvalid()) { + accountCapsule.invalidateOldTronPower(); + } + + accountStore.put(ownerAddress, accountCapsule); + + ret.setUnfreezeAmount(unfreezeBalance); + ret.setStatus(fee, code.SUCESS); + return true; + } + + @Override + public boolean validate() throws ContractValidateException { + if (this.any == null) { + throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); + } + if (chainBaseManager == null) { + throw new ContractValidateException(ActuatorConstant.STORE_NOT_EXIST); + } + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + if (!this.any.is(UnfreezeBalanceV2Contract.class)) { + throw new ContractValidateException( + "contract type error, expected type [UnfreezeBalanceContract], real type[" + any + .getClass() + "]"); + } + final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract; + try { + unfreezeBalanceV2Contract = this.any.unpack(UnfreezeBalanceV2Contract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + throw new ContractValidateException(e.getMessage()); + } + + byte[] ownerAddress = unfreezeBalanceV2Contract.getOwnerAddress().toByteArray(); + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + + AccountCapsule accountCapsule = accountStore.get(ownerAddress); + if (accountCapsule == null) { + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + throw new ContractValidateException( + ACCOUNT_EXCEPTION_STR + readableOwnerAddress + "] does not exist"); + } + + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + switch (unfreezeBalanceV2Contract.getResource()) { + case BANDWIDTH: + if (!this.checkExistFreezedBalance(accountCapsule, Common.ResourceCode.BANDWIDTH)) { + throw new ContractValidateException("no frozenBalance(BANDWIDTH)"); + } + break; + case ENERGY: + if (!this.checkExistFreezedBalance(accountCapsule, Common.ResourceCode.ENERGY)) { + throw new ContractValidateException("no frozenBalance(Energy)"); + } + break; + case TRON_POWER: + if (dynamicStore.supportAllowNewResourceModel()) { + if (!this.checkExistFreezedBalance(accountCapsule, Common.ResourceCode.TRON_POWER)) { + throw new ContractValidateException("no frozenBalance(TronPower)"); + } + } else { + throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + } + break; + default: + if (dynamicStore.supportAllowNewResourceModel()) { + throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、Energy、TRON_POWER]"); + } else { + throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + } + } + + if (!checkUnfreezeBalance(accountCapsule, unfreezeBalanceV2Contract, unfreezeBalanceV2Contract.getResource())) { + throw new ContractValidateException( + "Invalid unfreeze_balance, freezing resource[" + unfreezeBalanceV2Contract.getResource() + "] is not enough" + ); + } + + int unfreezingCount = accountCapsule.getUnfreezingV2Count(now); + if (UNFREEZE_MAX_TIMES <= unfreezingCount) { + throw new ContractValidateException("Invalid unfreeze operation, unfreezing times is over limit"); + } + + return true; + } + + @Override + public ByteString getOwnerAddress() throws InvalidProtocolBufferException { + return any.unpack(UnfreezeBalanceV2Contract.class).getOwnerAddress(); + } + + @Override + public long calcFee() { + return 0; + } + + public boolean checkExistFreezedBalance(AccountCapsule accountCapsule, Common.ResourceCode freezeType) { + boolean checkOk = false; + + long frozenAmount = 0; + List frozenV2List = accountCapsule.getFrozenV2List(); + for (Protocol.Account.FreezeV2 frozenV2 : frozenV2List) { + if (frozenV2.getType().equals(freezeType)) { + frozenAmount = frozenV2.getAmount(); + if (frozenAmount > 0) { + checkOk = true; + break; + } + } + } + + return checkOk; + } + + public boolean checkUnfreezeBalance(AccountCapsule accountCapsule, + final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract, + Common.ResourceCode freezeType) { + boolean checkOk = false; + + long frozenAmount = 0L; + List freezeV2List = accountCapsule.getFrozenV2List(); + for (Protocol.Account.FreezeV2 freezeV2 : freezeV2List) { + if (freezeV2.getType().equals(freezeType)) { + frozenAmount = freezeV2.getAmount(); + break; + } + } + + if (unfreezeBalanceV2Contract.getUnfreezeBalance() <= frozenAmount) { + checkOk = true; + } + + return checkOk; + } + + public long calcUnfreezeExpireTime(long now) { + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + long unfreezeDelayDays = dynamicStore.getUnfreezeDelayDays(); + + return now + unfreezeDelayDays * FROZEN_PERIOD; + } + + public void updateAccountFrozenInfo(Common.ResourceCode freezeType, AccountCapsule accountCapsule, long unfreezeBalance) { + List freezeV2List = accountCapsule.getFrozenV2List(); + for (int i = 0; i < freezeV2List.size(); i++) { + if (freezeV2List.get(i).getType().equals(freezeType)) { + Protocol.Account.FreezeV2 freezeV2 = Protocol.Account.FreezeV2.newBuilder() + .setAmount(freezeV2List.get(i).getAmount() - unfreezeBalance) + .setType(freezeV2List.get(i).getType()) + .build(); + accountCapsule.updateFrozenV2List(i, freezeV2); + break; + } + } + } + + public void unfreezeExpire(AccountCapsule accountCapsule, long now) { + long unfreezeBalance = 0L; + + List unFrozenV2List = Lists.newArrayList(); + unFrozenV2List.addAll(accountCapsule.getUnfrozenV2List()); + Iterator iterator = unFrozenV2List.iterator(); + + while (iterator.hasNext()) { + Protocol.Account.UnFreezeV2 next = iterator.next(); + if (next.getUnfreezeExpireTime() <= now) { + unfreezeBalance += next.getUnfreezeAmount(); + iterator.remove(); + } + } + + accountCapsule.setInstance( + accountCapsule.getInstance().toBuilder() + .setBalance(accountCapsule.getBalance() + unfreezeBalance) + .clearUnfrozenV2() + .addAllUnfrozenV2(unFrozenV2List).build() + ); + } + + public void updateTotalResourceWeight(final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract, + long unfreezeBalance) { + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + switch (unfreezeBalanceV2Contract.getResource()) { + case BANDWIDTH: + dynamicStore.addTotalNetWeight(-unfreezeBalance / TRX_PRECISION); + break; + case ENERGY: + dynamicStore.addTotalEnergyWeight(-unfreezeBalance / TRX_PRECISION); + break; + case TRON_POWER: + dynamicStore.addTotalTronPowerWeight(-unfreezeBalance / TRX_PRECISION); + break; + default: + //this should never happen + break; + } + } + + private void clearVotes(AccountCapsule accountCapsule, + final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract, + byte[] ownerAddress) { + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + VotesStore votesStore = chainBaseManager.getVotesStore(); + + boolean needToClearVote = true; + if (dynamicStore.supportAllowNewResourceModel() + && accountCapsule.oldTronPowerIsInvalid()) { + switch (unfreezeBalanceV2Contract.getResource()) { + case BANDWIDTH: + case ENERGY: + needToClearVote = false; + break; + default: + break; + } + } + + if (needToClearVote) { + VotesCapsule votesCapsule; + if (!votesStore.has(ownerAddress)) { + votesCapsule = new VotesCapsule( + unfreezeBalanceV2Contract.getOwnerAddress(), + accountCapsule.getVotesList() + ); + } else { + votesCapsule = votesStore.get(ownerAddress); + } + accountCapsule.clearVotes(); + votesCapsule.clearNewVotes(); + votesStore.put(ownerAddress, votesCapsule); + } + } +} \ No newline at end of file diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 0fc7adba674..44376dcd223 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -575,6 +575,18 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case UNFREEZE_DELAY_DAYS: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_6)) { + throw new ContractValidateException( + "Bad chain parameter id [UNFREEZE_DELAY_DAYS]"); + } + if (value < 1 || value > 365) { + throw new ContractValidateException( + "This value[UNFREEZE_DELAY_DAYS] is only allowed to be in the range 1-365"); + } + break; + } + default: break; } @@ -639,7 +651,8 @@ public enum ProposalType { // current value, value range ALLOW_TVM_LONDON(63), // 0, 1 ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX(65), // 0, 1 ALLOW_ASSET_OPTIMIZATION(66), // 0, 1 - ALLOW_NEW_REWARD_ALGO(67); // 0, 1 + ALLOW_NEW_REWARD_ALGO(67), // 0, 1 + UNFREEZE_DELAY_DAYS(68); // 0, [1, 365] private long code; diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index 2c30baa8d4e..bffbc08d653 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -37,6 +37,7 @@ import org.tron.protos.Protocol.Vote; import org.tron.protos.contract.AccountContract.AccountCreateContract; import org.tron.protos.contract.AccountContract.AccountUpdateContract; +import org.tron.protos.contract.Common; @Slf4j(topic = "capsule") public class AccountCapsule implements ProtoCapsule, Comparable { @@ -350,6 +351,11 @@ public long getAcquiredDelegatedFrozenBalanceForBandwidth() { return this.account.getAcquiredDelegatedFrozenBalanceForBandwidth(); } + public void addFrozenBalanceForBandwidthV2(long balance) { + Common.ResourceCode type = Common.ResourceCode.BANDWIDTH; + this.addFrozenBalanceForResource(type, balance); + } + public void setAcquiredDelegatedFrozenBalanceForBandwidth(long balance) { this.account = this.account.toBuilder().setAcquiredDelegatedFrozenBalanceForBandwidth(balance) .build(); @@ -434,6 +440,35 @@ public void addDelegatedFrozenBalanceForEnergy(long balance) { .build(); } + public void addFrozenBalanceForEnergyV2(long balance) { + Common.ResourceCode type = Common.ResourceCode.ENERGY; + this.addFrozenBalanceForResource(type, balance); + } + + private void addFrozenBalanceForResource(Common.ResourceCode type, long balance) { + boolean doUpdate = false; + for (int i = 0; i < this.account.getFrozenV2List().size(); i++) { + if (this.account.getFrozenV2List().get(i).getType().equals(type)) { + long newAmount = this.account.getFrozenV2(i).getAmount() + balance; + Account.FreezeV2 freezeV2 = Account.FreezeV2.newBuilder() + .setType(type) + .setAmount(newAmount) + .build(); + this.updateFrozenV2List(i, freezeV2); + doUpdate = true; + break; + } + } + + if (!doUpdate) { + Account.FreezeV2 freezeV2 = Account.FreezeV2.newBuilder() + .setType(type) + .setAmount(balance) + .build(); + this.addFrozenV2List(freezeV2); + } + } + @Override public String toString() { return this.account.toString(); @@ -495,19 +530,82 @@ public long getTronPower() { tp += account.getAccountResource().getFrozenBalanceForEnergy().getFrozenBalance(); tp += account.getDelegatedFrozenBalanceForBandwidth(); tp += account.getAccountResource().getDelegatedFrozenBalanceForEnergy(); + + // add v2 tron power + for (Account.FreezeV2 freezeV2 : account.getFrozenV2List()) { + // type: BANDWIDTH,ENERGY + if (freezeV2.getType() != Common.ResourceCode.TRON_POWER) { + tp += freezeV2.getAmount(); + } + } + return tp; } public long getAllTronPower() { if (account.getOldTronPower() == -1) { - return getTronPowerFrozenBalance(); + return getTronPowerFrozenBalance() + getTronPowerFrozenBalanceV2(); } else if (account.getOldTronPower() == 0) { - return getTronPower() + getTronPowerFrozenBalance(); + return getTronPower() + getTronPowerFrozenBalance() + getTronPowerFrozenBalanceV2(); } else { - return account.getOldTronPower() + getTronPowerFrozenBalance(); + return account.getOldTronPower() + getTronPowerFrozenBalance() + getTronPowerFrozenBalanceV2(); } } + + + public List getFrozenV2List() { + return account.getFrozenV2List(); + } + + public List getUnfrozenV2List() { + return account.getUnfrozenV2List(); + } + + public void updateFrozenV2List(int i, Account.FreezeV2 frozenV2) { + this.account = this.account.toBuilder() + .setFrozenV2(i, frozenV2) + .build(); + } + + public void addFrozenV2List(Account.FreezeV2 frozenV2) { + this.account = this.account.toBuilder().addFrozenV2(frozenV2).build(); + } + + /** + * + * @param type + * @param unfreezeAmount + * @param expireTime + * @return + */ + public void addUnfrozenV2List(Common.ResourceCode type, long unfreezeAmount, long expireTime) { + + Account.UnFreezeV2 unFreezeV2 = Account.UnFreezeV2.newBuilder() + .setType(type) + .setUnfreezeAmount(unfreezeAmount) + .setUnfreezeExpireTime(expireTime) + .build(); + this.account = this.account.toBuilder() + .addUnfrozenV2(unFreezeV2) + .build(); + } + + + public int getUnfreezingV2Count(long now) { + int count = 0; + + List unFreezeV2List = account.getUnfrozenV2List(); + for (Account.UnFreezeV2 item : unFreezeV2List) { + if (item.getUnfreezeExpireTime() > now) { + count++; + } + } + + return count; + } + + /*************************** start asset ****************************************/ public boolean getAssetOptimized() { @@ -757,8 +855,21 @@ public long getFrozenBalance() { return frozenBalance[0]; } + /** + * only for test + * @return + */ + public long getFrozenBalanceV2() { + List freezeV2List = getFrozenV2List(); + long amount = 0L; + for (Account.FreezeV2 freezeV2 : freezeV2List) { + amount += freezeV2.getAmount(); + } + return amount; + } + public long getAllFrozenBalanceForBandwidth() { - return getFrozenBalance() + getAcquiredDelegatedFrozenBalanceForBandwidth(); + return getFrozenBalance() + getAcquiredDelegatedFrozenBalanceForBandwidth() + getBandWidthFrozenBalanceV2(); } public int getFrozenSupplyCount() { @@ -893,6 +1004,28 @@ public long getEnergyFrozenBalance() { return this.account.getAccountResource().getFrozenBalanceForEnergy().getFrozenBalance(); } + + private long getBandWidthFrozenBalanceV2() { + List freezeV2List = this.account.getFrozenV2List(); + for (Account.FreezeV2 freezeV2 : freezeV2List) { + if(freezeV2.getType().equals(Common.ResourceCode.BANDWIDTH)) { + return freezeV2.getAmount(); + } + } + return 0L; + } + + private long getEnergyFrozenBalanceV2() { + List freezeV2List = this.account.getFrozenV2List(); + for (Account.FreezeV2 freezeV2 : freezeV2List) { + if(freezeV2.getType().equals(Common.ResourceCode.ENERGY)) { + return freezeV2.getAmount(); + } + } + return 0L; + } + + public boolean oldTronPowerIsNotInitialized() { return this.account.getOldTronPower() == 0; } @@ -935,10 +1068,26 @@ public void setFrozenForTronPower(long frozenBalance, long expireTime) { .build()); } + public void addFrozenForTronPowerV2(long balance) { + Common.ResourceCode type = Common.ResourceCode.TRON_POWER; + this.addFrozenBalanceForResource(type, balance); + } + public long getTronPowerFrozenBalance() { return this.account.getTronPower().getFrozenBalance(); } + public long getTronPowerFrozenBalanceV2() { + List freezeV2List = this.account.getFrozenV2List(); + for (Account.FreezeV2 freezeV2 : freezeV2List) { + if(freezeV2.getType().equals(Common.ResourceCode.TRON_POWER)) { + return freezeV2.getAmount(); + } + } + return 0L; + } + + public long getEnergyUsage() { return this.account.getAccountResource().getEnergyUsage(); } @@ -951,7 +1100,7 @@ public void setEnergyUsage(long energyUsage) { } public long getAllFrozenBalanceForEnergy() { - return getEnergyFrozenBalance() + getAcquiredDelegatedFrozenBalanceForEnergy(); + return getEnergyFrozenBalance() + getAcquiredDelegatedFrozenBalanceForEnergy() + getEnergyFrozenBalanceV2(); } public long getLatestConsumeTimeForEnergy() { diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index df37059f2ad..f7fd022f311 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -187,6 +187,9 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX = "ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX".getBytes(); + private static final byte[] UNFREEZE_DELAY_DAYS = "UNFREEZE_DELAY_DAYS".getBytes(); + + @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { super(dbName); @@ -857,6 +860,14 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { new BytesCapsule(ByteArray.fromLong(Long.MAX_VALUE))); } } + + try { + this.getUnfreezeDelayDays(); + } catch (IllegalArgumentException e) { + this.saveUnfreezeDelayDays( + CommonParameter.getInstance().getUnfreezeDelayDays() + ); + } } public String intArrayToString(int[] a) { @@ -2528,6 +2539,17 @@ public long getAllowHigherLimitForMaxCpuTimeOfOneTx() { () -> new IllegalArgumentException(msg)); } + public long getUnfreezeDelayDays() { + return Optional.ofNullable(getUnchecked(UNFREEZE_DELAY_DAYS)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow(() -> new IllegalArgumentException("not found UNFREEZE_DELAY_DAYS")); + } + + public void saveUnfreezeDelayDays(long value) { + this.put(UNFREEZE_DELAY_DAYS, new BytesCapsule(ByteArray.fromLong(value))); + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 26aa7d44834..91325d44a9d 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -561,6 +561,10 @@ public class CommonParameter { @Setter public long allowNewRewardAlgorithm; + @Getter + @Setter + public long unfreezeDelayDays = 0L; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 33bd411c28f..c53943a4b1f 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1103,6 +1103,11 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().useNewRewardAlgorithm() ? 1 : 0) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getUnfreezeDelayDays") + .setValue(dbManager.getDynamicPropertiesStore().getUnfreezeDelayDays()) + .build()); + return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 92472335d20..3bb2abddc38 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -288,6 +288,13 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveNewRewardAlgorithmEffectiveCycle(); break; } + + case UNFREEZE_DELAY_DAYS: { + manager.getDynamicPropertiesStore().saveUnfreezeDelayDays(entry.getValue()); + manager.getDynamicPropertiesStore().addSystemContractAndSetPermission(54); + manager.getDynamicPropertiesStore().addSystemContractAndSetPermission(55); + break; + } default: find = false; break; diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index c964536aa33..c3184a46307 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -142,6 +142,7 @@ import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; import org.tron.protos.contract.AssetIssueContractOuterClass.UnfreezeAssetContract; import org.tron.protos.contract.AssetIssueContractOuterClass.UpdateAssetContract; +import org.tron.protos.contract.BalanceContract; import org.tron.protos.contract.BalanceContract.AccountBalanceRequest; import org.tron.protos.contract.BalanceContract.AccountBalanceResponse; import org.tron.protos.contract.BalanceContract.BlockBalanceTrace; @@ -1480,6 +1481,12 @@ public void freezeBalance2(FreezeBalanceContract request, createTransactionExtention(request, ContractType.FreezeBalanceContract, responseObserver); } + @Override + public void freezeBalanceV2(BalanceContract.FreezeBalanceV2Contract request, + StreamObserver responseObserver) { + createTransactionExtention(request, ContractType.FreezeBalanceV2Contract, responseObserver); + } + @Override public void unfreezeBalance(UnfreezeBalanceContract request, StreamObserver responseObserver) { @@ -1501,6 +1508,12 @@ public void unfreezeBalance2(UnfreezeBalanceContract request, createTransactionExtention(request, ContractType.UnfreezeBalanceContract, responseObserver); } + @Override + public void unfreezeBalanceV2(BalanceContract.UnfreezeBalanceV2Contract request, + StreamObserver responseObserver) { + createTransactionExtention(request, ContractType.UnfreezeBalanceV2Contract, responseObserver); + } + @Override public void withdrawBalance(WithdrawBalanceContract request, StreamObserver responseObserver) { diff --git a/framework/src/main/java/org/tron/core/services/http/FreezeBalanceV2Servlet.java b/framework/src/main/java/org/tron/core/services/http/FreezeBalanceV2Servlet.java new file mode 100644 index 00000000000..f1687a5bbb1 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/FreezeBalanceV2Servlet.java @@ -0,0 +1,36 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.contract.BalanceContract.FreezeBalanceV2Contract; + +@Component +@Slf4j(topic = "API") +public class FreezeBalanceV2Servlet extends RateLimiterServlet { + + @Autowired + private Wallet wallet; + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + PostParams params = PostParams.getPostParams(request); + FreezeBalanceV2Contract.Builder build = FreezeBalanceV2Contract.newBuilder(); + JsonFormat.merge(params.getParams(), build, params.isVisible()); + Transaction tx = wallet + .createTransactionCapsule(build.build(), ContractType.FreezeBalanceV2Contract) + .getInstance(); + JSONObject jsonObject = JSONObject.parseObject(params.getParams()); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, params.isVisible())); + } catch (Exception e) { + Util.processError(e, response); + } + } +} diff --git a/framework/src/main/java/org/tron/core/services/http/UnFreezeBalanceV2Servlet.java b/framework/src/main/java/org/tron/core/services/http/UnFreezeBalanceV2Servlet.java new file mode 100644 index 00000000000..614a7ca6b7a --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/UnFreezeBalanceV2Servlet.java @@ -0,0 +1,38 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.contract.BalanceContract.UnfreezeBalanceV2Contract; + +@Component +@Slf4j(topic = "API") +public class UnFreezeBalanceV2Servlet extends RateLimiterServlet { + @Autowired + private Wallet wallet; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + PostParams params = PostParams.getPostParams(request); + UnfreezeBalanceV2Contract.Builder build = UnfreezeBalanceV2Contract.newBuilder(); + JsonFormat.merge(params.getParams(), build, params.isVisible()); + Transaction tx = wallet + .createTransactionCapsule(build.build(), ContractType.UnfreezeBalanceV2Contract) + .getInstance(); + JSONObject jsonObject = JSONObject.parseObject(params.getParams()); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, params.isVisible())); + } catch (Exception e) { + Util.processError(e, response); + } + } +} \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/services/http/WithdrawBalanceV2Servlet.java b/framework/src/main/java/org/tron/core/services/http/WithdrawBalanceV2Servlet.java new file mode 100644 index 00000000000..1696fa8863b --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/WithdrawBalanceV2Servlet.java @@ -0,0 +1,43 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.contract.BalanceContract.WithdrawBalanceV2Contract; + +@Component +@Slf4j(topic = "API") +public class WithdrawBalanceV2Servlet extends RateLimiterServlet { + + @Autowired + private Wallet wallet; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + String contract = request.getReader().lines() + .collect(Collectors.joining(System.lineSeparator())); + Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); + WithdrawBalanceV2Contract.Builder build = WithdrawBalanceV2Contract.newBuilder(); + JsonFormat.merge(contract, build, visible); + Transaction tx = wallet + .createTransactionCapsule(build.build(), ContractType.WithdrawBalanceV2Contract) + .getInstance(); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); + } catch (Exception e) { + Util.processError(e, response); + } + } +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java new file mode 100644 index 00000000000..3a06ef7f8d9 --- /dev/null +++ b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java @@ -0,0 +1,546 @@ +package org.tron.core.actuator; + +import static junit.framework.TestCase.fail; +import static org.tron.core.config.Parameter.ChainConstant.TRANSFER_FEE; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import java.io.File; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.core.ChainBaseManager; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; +import org.tron.core.capsule.DelegatedResourceCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.Parameter.ChainConstant; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.protos.Protocol.AccountType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.AssetIssueContractOuterClass; +import org.tron.protos.contract.BalanceContract; +import org.tron.protos.contract.Common.ResourceCode; + + + +@Slf4j +public class FreezeBalanceV2ActuatorTest { + + private static final String dbPath = "output_freeze_balance_test"; + private static final String OWNER_ADDRESS; + private static final String RECEIVER_ADDRESS; + private static final String OWNER_ADDRESS_INVALID = "aaaa"; + private static final String OWNER_ACCOUNT_INVALID; + private static final long initBalance = 10_000_000_000L; + private static Manager dbManager; + private static TronApplicationContext context; + + static { + Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; + OWNER_ACCOUNT_INVALID = + Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; + } + + /** + * Init data. + */ + @BeforeClass + public static void init() { + dbManager = context.getBean(Manager.class); + // Args.setParam(new String[]{"--output-directory", dbPath}, + // "config-junit.conf"); + // dbManager = new Manager(); + // dbManager.init(); + } + + /** + * Release resources. + */ + @AfterClass + public static void destroy() { + Args.clearParam(); + context.destroy(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.info("Release resources failure."); + } + } + + /** + * create temp Capsule test need. + */ + @Before + public void createAccountCapsule() { + AccountCapsule ownerCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + + AccountCapsule receiverCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), + AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); + } + + private Any getContractV2ForBandwidth(String ownerAddress, long frozenBalance) { + return Any.pack( + BalanceContract.FreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setFrozenBalance(frozenBalance) + .setResource(ResourceCode.BANDWIDTH) + .build()); + } + + private Any getContractForCpuV2(String ownerAddress, long frozenBalance) { + return Any.pack( + BalanceContract.FreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setFrozenBalance(frozenBalance) + .setResource(ResourceCode.ENERGY) + .build()); + } + + + private Any getContractForTronPowerV2(String ownerAddress, long frozenBalance) { + return Any.pack( + BalanceContract.FreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setFrozenBalance(frozenBalance) + .setResource(ResourceCode.TRON_POWER) + .build()); + } + + private Any getDelegatedContractForBandwidthV2(String ownerAddress, + long frozenBalance) { + return Any.pack( + BalanceContract.FreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + //.setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiverAddress))) + .setFrozenBalance(frozenBalance) + .build()); + } + + private Any getDelegatedContractForCpuV2(String ownerAddress, + long frozenBalance) { + return Any.pack( + BalanceContract.FreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + //.setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiverAddress))) + .setFrozenBalance(frozenBalance) + .setResource(ResourceCode.ENERGY) + .build()); + } + + @Test + public void testFreezeBalanceForBandwidth() { + long frozenBalance = 1_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractV2ForBandwidth(OWNER_ADDRESS, frozenBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule owner = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(owner.getBalance(), initBalance - frozenBalance + - TRANSFER_FEE); + Assert.assertEquals(owner.getFrozenBalanceV2(), frozenBalance); + Assert.assertEquals(frozenBalance, owner.getTronPower()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void testFreezeBalanceForEnergy() { + long frozenBalance = 1_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForCpuV2(OWNER_ADDRESS, frozenBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule owner = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(owner.getBalance(), initBalance - frozenBalance + - TRANSFER_FEE); + Assert.assertEquals(0L, owner.getAllFrozenBalanceForBandwidth()); + Assert.assertEquals(frozenBalance, owner.getAllFrozenBalanceForEnergy()); + Assert.assertEquals(frozenBalance, owner.getTronPower()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void testFreezeDelegatedBalanceForBandwidthWithContractAddress() { + AccountCapsule receiverCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), + AccountType.Contract, + initBalance); + dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); + + dbManager.getDynamicPropertiesStore().saveAllowTvmConstantinople(1); + + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + long frozenBalance = 1_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegatedContractForBandwidthV2(OWNER_ADDRESS, frozenBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + + AccountCapsule owner = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(owner.getBalance(), initBalance - frozenBalance + - TRANSFER_FEE); + Assert.assertEquals(0L, owner.getAllFrozenBalanceForBandwidth()); + Assert.assertEquals(0L, owner.getAllFrozenBalanceForEnergy()); + Assert.assertEquals(frozenBalance, owner.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(frozenBalance, owner.getTronPower()); + + } catch (ContractValidateException e) { + Assert.assertEquals(e.getMessage(), "Do not allow delegate resources to contract addresses"); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + + } + + + @Test + public void testFreezeDelegatedBalanceForCpuSameNameTokenClose() { + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(0); + long frozenBalance = 1_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegatedContractForCpuV2(OWNER_ADDRESS, frozenBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + long totalEnergyWeightBefore = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule owner = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + Assert.assertEquals(owner.getBalance(), initBalance - frozenBalance + - TRANSFER_FEE); + Assert.assertEquals(0L, owner.getAllFrozenBalanceForBandwidth()); + Assert.assertEquals(frozenBalance, owner.getAllFrozenBalanceForEnergy()); + Assert.assertEquals(0L, owner.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0L, owner.getDelegatedFrozenBalanceForEnergy()); + + + AccountCapsule receiver = + dbManager.getAccountStore().get(ByteArray.fromHexString(RECEIVER_ADDRESS)); + Assert.assertEquals(0L, receiver.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0L, receiver.getAcquiredDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0L, receiver.getTronPower()); + + long totalEnergyWeightAfter = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); + Assert.assertEquals(totalEnergyWeightBefore + frozenBalance / 1000_000L, + totalEnergyWeightAfter); + + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void freezeLessThanZero() { + long frozenBalance = -1_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractV2ForBandwidth(OWNER_ADDRESS, frozenBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("frozenBalance must be positive", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void freezeMoreThanBalance() { + long frozenBalance = 11_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractV2ForBandwidth(OWNER_ADDRESS, frozenBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("frozenBalance must be less than accountBalance", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void invalidOwnerAddress() { + long frozenBalance = 1_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractV2ForBandwidth(OWNER_ADDRESS_INVALID, frozenBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + + Assert.assertEquals("Invalid address", e.getMessage()); + + } catch (ContractExeException e) { + Assert.assertTrue(e instanceof ContractExeException); + } + + } + + @Test + public void invalidOwnerAccount() { + long frozenBalance = 1_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractV2ForBandwidth(OWNER_ACCOUNT_INVALID, frozenBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Account[" + OWNER_ACCOUNT_INVALID + "] not exists", + e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void lessThan1TrxTest() { + long frozenBalance = 1; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractV2ForBandwidth(OWNER_ADDRESS, frozenBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("frozenBalance must be more than 1TRX", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + //@Test + public void moreThanFrozenNumber() { + long frozenBalance = 1_000_000_000L; + FreezeBalanceActuator actuator = new FreezeBalanceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractV2ForBandwidth(OWNER_ADDRESS, frozenBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + } catch (ContractValidateException e) { + long maxFrozenNumber = ChainConstant.MAX_FROZEN_NUMBER; + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("max frozen number is: " + maxFrozenNumber, e.getMessage()); + + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void commonErrorCheck() { + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + ActuatorTest actuatorTest = new ActuatorTest(actuator, dbManager); + actuatorTest.noContract(); + + Any invalidContractTypes = Any.pack(AssetIssueContractOuterClass.AssetIssueContract.newBuilder() + .build()); + actuatorTest.setInvalidContract(invalidContractTypes); + actuatorTest.setInvalidContractTypeMsg("contract type error", + "contract type error,expected type [FreezeBalanceV2Contract],real type["); + actuatorTest.invalidContractType(); + + long frozenBalance = 1_000_000_000L; + actuatorTest.setContract(getContractV2ForBandwidth(OWNER_ADDRESS, frozenBalance)); + actuatorTest.nullTransationResult(); + + actuatorTest.setNullDBManagerMsg("No account store or dynamic store!"); + actuatorTest.nullDBManger(); + } + + + @Test + public void testFreezeBalanceForEnergyWithoutOldTronPowerAfterNewResourceModel() { + long frozenBalance = 1_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + ChainBaseManager chainBaseManager = dbManager.getChainBaseManager(); + chainBaseManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + actuator.setChainBaseManager(chainBaseManager) + .setAny(getContractForCpuV2(OWNER_ADDRESS, frozenBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule owner = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(-1L, owner.getInstance().getOldTronPower()); + Assert.assertEquals(0L, owner.getAllTronPower()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void testFreezeBalanceForEnergyWithOldTronPowerAfterNewResourceModel() { + long frozenBalance = 1_000_000_000L; + long duration = 3; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + ChainBaseManager chainBaseManager = dbManager.getChainBaseManager(); + chainBaseManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + actuator.setChainBaseManager(chainBaseManager) + .setAny(getContractForCpuV2(OWNER_ADDRESS, frozenBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + AccountCapsule owner = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + owner.setFrozenForEnergy(100L,0L); + chainBaseManager.getAccountStore().put(ByteArray.fromHexString(OWNER_ADDRESS),owner); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + owner = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(100L, owner.getInstance().getOldTronPower()); + Assert.assertEquals(100L, owner.getAllTronPower()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void testFreezeBalanceForTronPowerWithOldTronPowerAfterNewResourceModel() { + long frozenBalance = 1_000_000_000L; + FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); + ChainBaseManager chainBaseManager = dbManager.getChainBaseManager(); + chainBaseManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + actuator.setChainBaseManager(chainBaseManager) + .setAny(getContractForTronPowerV2(OWNER_ADDRESS, frozenBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + AccountCapsule owner = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + owner.setFrozenForEnergy(100L,0L); + chainBaseManager.getAccountStore().put(ByteArray.fromHexString(OWNER_ADDRESS),owner); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + owner = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(100L, owner.getInstance().getOldTronPower()); + Assert.assertEquals(100L, owner.getTronPower()); + Assert.assertEquals(frozenBalance + 100, owner.getAllTronPower()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + +} diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java new file mode 100644 index 00000000000..d165307b524 --- /dev/null +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java @@ -0,0 +1,836 @@ +package org.tron.core.actuator; + +import static junit.framework.TestCase.fail; +import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; +import org.tron.core.capsule.DelegatedResourceCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.capsule.VotesCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.protos.Protocol.AccountType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.Protocol.Vote; +import org.tron.protos.contract.AssetIssueContractOuterClass; +import org.tron.protos.contract.BalanceContract; +import org.tron.protos.contract.Common.ResourceCode; + +@Slf4j +public class UnfreezeBalanceV2ActuatorTest { + + private static final String dbPath = "output_unfreeze_balance_test"; + private static final String OWNER_ADDRESS; + private static final String RECEIVER_ADDRESS; + private static final String OWNER_ADDRESS_INVALID = "aaaa"; + private static final String OWNER_ACCOUNT_INVALID; + private static final long initBalance = 10_000_000_000L; + private static final long frozenBalance = 1_000_000_000L; + private static final long smallTatalResource = 100L; + private static Manager dbManager; + private static TronApplicationContext context; + + static { + Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; + OWNER_ACCOUNT_INVALID = + Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; + } + + /** + * Init data. + */ + @BeforeClass + public static void init() { + dbManager = context.getBean(Manager.class); + // Args.setParam(new String[]{"--output-directory", dbPath}, + // "config-junit.conf"); + // dbManager = new Manager(); + // dbManager.init(); + } + + /** + * Release resources. + */ + @AfterClass + public static void destroy() { + Args.clearParam(); + context.destroy(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.info("Release resources failure."); + } + } + + /** + * create temp Capsule test need. + */ + @Before + public void createAccountCapsule() { + AccountCapsule ownerCapsule = new AccountCapsule(ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); + + AccountCapsule receiverCapsule = new AccountCapsule(ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); + } + + private Any getContractForBandwidthV2(String ownerAddress, long unfreezeBalance) { + return Any.pack( + BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress( + ByteString.copyFrom(ByteArray.fromHexString(ownerAddress)) + ) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.BANDWIDTH) + .build() + ); + } + + private Any getContractForCpuV2(String ownerAddress, long unfreezeBalance) { + return Any.pack(BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.ENERGY).build()); + } + + private Any getContractForTronPowerV2(String ownerAddress, long unfreezeBalance) { + return Any.pack(BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.TRON_POWER).build()); + } + + private Any getDelegatedContractForBandwidth( + String ownerAddress, long unfreezeBalance + ) { + return Any.pack(BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.BANDWIDTH).build()); + } + + private Any getDelegatedContractForCpu( + String ownerAddress, String receiverAddress, long unfreezeBalance + ) { + return Any.pack(BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.ENERGY).build()); + } + + private Any getContract(String ownerAddress, ResourceCode resourceCode, long unfreezeBalance) { + return Any.pack(BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(resourceCode).build()); + } + + + private Any getContractForTronPowerV2_001(String ownerAddress, long unfreezeBalance) { + return Any.pack(BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setUnfreezeBalance(unfreezeBalance).build()); + } + + @Test + public void testUnfreezeBalanceForBandwidth() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + long unfreezeBalance = frozenBalance - 100; + + Assert.assertEquals(accountCapsule.getFrozenBalanceV2(), frozenBalance); + Assert.assertEquals(accountCapsule.getTronPower(), frozenBalance); + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + long totalNetWeightBefore = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule owner = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + + //Assert.assertEquals(owner.getBalance(), initBalance + frozenBalance); + Assert.assertEquals(owner.getFrozenBalanceV2(), 100); + Assert.assertEquals(owner.getTronPower(), 100L); + + long totalNetWeightAfter = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); + Assert.assertEquals(totalNetWeightBefore, + totalNetWeightAfter + (frozenBalance - 100) / 1000_000L); + + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void testUnfreezeBalanceForEnergy() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + long unfreezeBalance = frozenBalance - 100; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); + Assert.assertEquals(accountCapsule.getAllFrozenBalanceForEnergy(), frozenBalance); + Assert.assertEquals(accountCapsule.getTronPower(), frozenBalance); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForCpuV2(OWNER_ADDRESS, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + long totalEnergyWeightBefore = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule owner = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + + //Assert.assertEquals(owner.getBalance(), initBalance + frozenBalance); + Assert.assertEquals(owner.getAllFrozenBalanceForEnergy(), 100); + Assert.assertEquals(owner.getTronPower(), 100); + long totalEnergyWeightAfter = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); + Assert.assertEquals(totalEnergyWeightBefore, + totalEnergyWeightAfter + (frozenBalance - 100) / 1000_000L); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void invalidOwnerAddress() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + long unfreezeBalance = frozenBalance; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.setFrozen(1_000_000_000L, now); + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS_INVALID, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + + Assert.assertEquals("Invalid address", e.getMessage()); + + } catch (ContractExeException e) { + Assert.assertTrue(e instanceof ContractExeException); + } + + } + + @Test + public void invalidOwnerAccount() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + long unfreezeBalance = frozenBalance; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.setFrozen(1_000_000_000L, now); + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ACCOUNT_INVALID, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Account[" + OWNER_ACCOUNT_INVALID + "] does not exist", + e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void noFrozenBalance() { + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + long unfreezeBalance = frozenBalance; + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("no frozenBalance(BANDWIDTH)", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void testClearVotes() { + byte[] ownerAddressBytes = ByteArray.fromHexString(OWNER_ADDRESS); + ByteString ownerAddress = ByteString.copyFrom(ownerAddressBytes); + long unfreezeBalance = frozenBalance; + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddressBytes); + accountCapsule.addFrozenBalanceForBandwidthV2(1_000_000_000L); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + dbManager.getVotesStore().reset(); + Assert.assertNull(dbManager.getVotesStore().get(ownerAddressBytes)); + try { + actuator.validate(); + actuator.execute(ret); + VotesCapsule votesCapsule = dbManager.getVotesStore().get(ownerAddressBytes); + Assert.assertNotNull(votesCapsule); + Assert.assertEquals(0, votesCapsule.getNewVotes().size()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + // if had votes + List oldVotes = new ArrayList(); + VotesCapsule votesCapsule = new VotesCapsule( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), oldVotes); + votesCapsule.addNewVotes( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), 100); + dbManager.getVotesStore().put(ByteArray.fromHexString(OWNER_ADDRESS), votesCapsule); + accountCapsule.addFrozenBalanceForBandwidthV2(1_000_000_000L); + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + try { + actuator.validate(); + actuator.execute(ret); + votesCapsule = dbManager.getVotesStore().get(ownerAddressBytes); + Assert.assertNotNull(votesCapsule); + Assert.assertEquals(0, votesCapsule.getNewVotes().size()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + } + + @Test + public void commonErrorCheck() { + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + ActuatorTest actuatorTest = new ActuatorTest(actuator, dbManager); + actuatorTest.noContract(); + long unfreezeBalance = frozenBalance; + + Any invalidContractTypes = Any.pack( + AssetIssueContractOuterClass.AssetIssueContract.newBuilder().build() + ); + actuatorTest.setInvalidContract(invalidContractTypes); + actuatorTest.setInvalidContractTypeMsg("contract type error", + "contract type error, expected type [UnfreezeBalanceContract], real type["); + actuatorTest.invalidContractType(); + + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + Assert.assertEquals(accountCapsule.getAllFrozenBalanceForBandwidth(), frozenBalance); + Assert.assertEquals(accountCapsule.getTronPower(), frozenBalance); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + + actuatorTest.setContract(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + actuatorTest.nullTransationResult(); + + actuatorTest.setNullDBManagerMsg("No account store or dynamic store!"); + actuatorTest.nullDBManger(); + } + + + @Test + public void testUnfreezeBalanceForEnergyWithOldTronPowerAfterNewResourceModel() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + long unfreezeBalance = frozenBalance; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); + accountCapsule.setOldTronPower(frozenBalance); + accountCapsule.addVotes( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), 100L); + Assert.assertEquals(accountCapsule.getAllFrozenBalanceForEnergy(), frozenBalance); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForCpuV2(OWNER_ADDRESS, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule owner = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(owner.getVotesList().size(), 0L); + Assert.assertEquals(owner.getInstance().getOldTronPower(), -1L); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void testUnfreezeBalanceForEnergyWithoutOldTronPowerAfterNewResourceModel() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + long unfreezeBalance = frozenBalance; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); + accountCapsule.setOldTronPower(-1L); + accountCapsule.addVotes( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), 100L); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForCpuV2(OWNER_ADDRESS, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule owner = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(owner.getVotesList().size(), 1L); + Assert.assertEquals(owner.getInstance().getOldTronPower(), -1L); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void testUnfreezeBalanceForTronPowerWithOldTronPowerAfterNewResourceModel() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + long unfreezeBalance = frozenBalance - 100; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); + accountCapsule.addFrozenForTronPowerV2(frozenBalance); + accountCapsule.addVotes( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), 100L); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForTronPowerV2(OWNER_ADDRESS, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule owner = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(owner.getVotesList().size(), 0L); + Assert.assertEquals(owner.getInstance().getOldTronPower(), -1L); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void testUnfreezeBalanceForTronPowerWithOldTronPowerAfterNewResourceModelError() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + long unfreezeBalance = frozenBalance - 100; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); + accountCapsule.addFrozenForTronPowerV2(frozenBalance); + accountCapsule.addVotes( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), 100L); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForTronPowerV2(OWNER_ADDRESS, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + //Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + } + } + + + @Test + public void testUnfreezeBalanceCheckExistFreezedBalance() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + long unfreezeBalance = frozenBalance - 100; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); + accountCapsule.addFrozenForTronPowerV2(frozenBalance); + //accountCapsule.addDelegatedFrozenBalanceForBandwidthV2(frozenBalance); + //accountCapsule.addDelegatedFrozenBalanceForEnergyV2(frozenBalance); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + + boolean bret1 = actuator.checkExistFreezedBalance( + accountCapsule, ResourceCode.BANDWIDTH); + Assert.assertTrue(true == bret1); + boolean bret2 = actuator.checkExistFreezedBalance( + accountCapsule, ResourceCode.ENERGY); + Assert.assertTrue(true == bret2); + boolean bret3 = actuator.checkExistFreezedBalance( + accountCapsule, ResourceCode.TRON_POWER); + Assert.assertTrue(true == bret3); + + } + + + @Test + public void testUnfreezeBalanceCheckUnfreezeBalance() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + long unfreezeBalance = frozenBalance - 1; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + + BalanceContract.UnfreezeBalanceV2Contract unfreezeBalanceV2Contract = + BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.BANDWIDTH) + .build(); + boolean bret1 = actuator.checkUnfreezeBalance( + accountCapsule, unfreezeBalanceV2Contract, ResourceCode.BANDWIDTH + ); + Assert.assertTrue(true == bret1); + } + + + @Test + public void testUnfreezeBalanceGetFreezeType() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + long unfreezeBalance = frozenBalance - 1; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + + BalanceContract.UnfreezeBalanceV2Contract unfreezeBalanceV2Contract = + BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.TRON_POWER) + //.setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))) + .build(); + + ResourceCode freezeType = unfreezeBalanceV2Contract.getResource(); + + Assert.assertTrue(ResourceCode.TRON_POWER.equals(freezeType)); + } + + @Test + public void testUnfreezeBalanceCalcUnfreezeExpireTime() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(30); + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + long unfreezeBalance = frozenBalance - 1; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + + BalanceContract.UnfreezeBalanceV2Contract unfreezeBalanceV2Contract = + BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.TRON_POWER) + //.setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))) + .build(); + + long ret = actuator.calcUnfreezeExpireTime(now); + + Assert.assertTrue(true); + } + + @Test + public void testUnfreezeBalanceUpdateAccountFrozenInfo() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(30); + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + long unfreezeBalance = frozenBalance - 1; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + + BalanceContract.UnfreezeBalanceV2Contract unfreezeBalanceV2Contract = + BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.TRON_POWER) + //.setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))) + .build(); + + actuator.updateAccountFrozenInfo( + ResourceCode.BANDWIDTH, accountCapsule, unfreezeBalance + ); + + Assert.assertTrue(accountCapsule.getAllFrozenBalanceForBandwidth() == 1); + } + + + @Test + public void testUnfreezeBalanceUnfreezeExpire() { + + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(30); + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + + long unfreezeBalance = frozenBalance - 1; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + + long balance = accountCapsule.getBalance(); + accountCapsule.addUnfrozenV2List( + ResourceCode.BANDWIDTH, + 1, + now + 19 * FROZEN_PERIOD + ); + accountCapsule.addUnfrozenV2List( + ResourceCode.BANDWIDTH, + 10, + now + 31 * FROZEN_PERIOD + ); + accountCapsule.addUnfrozenV2List( + ResourceCode.ENERGY, + 20, + now + 32 * FROZEN_PERIOD + ); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now + 31 * FROZEN_PERIOD); + actuator.unfreezeExpire(accountCapsule, + dbManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp()); + + Assert.assertEquals(accountCapsule.getBalance(), balance + 11); + Assert.assertEquals(accountCapsule.getUnfrozenV2List().size(), 1); + Assert.assertEquals(accountCapsule.getUnfrozenV2List().get(0).getUnfreezeAmount(), 20); + } + + + @Test + public void testAddTotalResourceWeight() { + + long now = System.currentTimeMillis(); + long total = frozenBalance; + dbManager.getDynamicPropertiesStore().saveTotalTronPowerWeight(total); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(30); + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + + long unfreezeBalance = frozenBalance; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + + long balance = accountCapsule.getBalance(); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + BalanceContract.UnfreezeBalanceV2Contract unfreezeBalanceV2Contract = + BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setUnfreezeBalance(unfreezeBalance) + .setResource(ResourceCode.TRON_POWER) + .build(); + + actuator.updateTotalResourceWeight(unfreezeBalanceV2Contract, unfreezeBalance); + + Assert.assertEquals(total - unfreezeBalance / TRX_PRECISION, + dbManager.getDynamicPropertiesStore().getTotalTronPowerWeight()); + + } + + @Test + public void testUnfreezeBalanceUnfreezeCount() { + + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(30); + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + + long unfreezeBalance = frozenBalance - 1; + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + + long balance = accountCapsule.getBalance(); + accountCapsule.addUnfrozenV2List( + ResourceCode.BANDWIDTH, + 1, + now + 19 * FROZEN_PERIOD + ); + accountCapsule.addUnfrozenV2List( + ResourceCode.BANDWIDTH, + 10, + now + 31 * FROZEN_PERIOD + ); + accountCapsule.addUnfrozenV2List( + ResourceCode.ENERGY, + 20, + now + 32 * FROZEN_PERIOD + ); + + int count = accountCapsule.getUnfreezingV2Count(now); + Assert.assertEquals(3, count); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + + dbManager.getDynamicPropertiesStore() + .saveLatestBlockHeaderTimestamp(now + 32 * FROZEN_PERIOD); + actuator.unfreezeExpire(accountCapsule, + dbManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp()); + + + int after_count = accountCapsule.getUnfreezingV2Count(now); + Assert.assertEquals(0, after_count); + + } + + +} + diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 94219db1ec2..baa4a5fad78 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -224,6 +224,10 @@ service Wallet { //Use this function instead of FreezeBalance. rpc FreezeBalance2 (FreezeBalanceContract) returns (TransactionExtention) { } + //Use this function when FreezeBalanceV2. + rpc FreezeBalanceV2 (FreezeBalanceV2Contract) returns (TransactionExtention) { + } + //Please use UnfreezeBalance2 instead of this function. rpc UnfreezeBalance (UnfreezeBalanceContract) returns (Transaction) { option (google.api.http) = { @@ -237,6 +241,10 @@ service Wallet { //Use this function instead of UnfreezeBalance. rpc UnfreezeBalance2 (UnfreezeBalanceContract) returns (TransactionExtention) { } + //Use this function when UnfreezeBalanceV2. + rpc UnfreezeBalanceV2 (UnfreezeBalanceV2Contract) returns (TransactionExtention) { + } + //Please use UnfreezeAsset2 instead of this function. rpc UnfreezeAsset (UnfreezeAssetContract) returns (Transaction) { option (google.api.http) = { From 29fafbc047c83440283b0739e5f4ffbee55f6792 Mon Sep 17 00:00:00 2001 From: chaozhu Date: Mon, 19 Sep 2022 19:16:26 -0700 Subject: [PATCH 0327/1197] fix(freezeV2): fix some test failed cases --- .../AccountPermissionUpdateActuatorTest.java | 8 +- .../actuator/FreezeBalanceV2ActuatorTest.java | 87 ------------------- .../UnfreezeBalanceV2ActuatorTest.java | 2 - 3 files changed, 4 insertions(+), 93 deletions(-) diff --git a/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java index b5d1d7e0ac0..ab0847ff072 100644 --- a/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java @@ -969,7 +969,7 @@ public void checkAvailableContractTypeCorrespondingToCode() { // and you will get the value from the output, // then update the value to checkAvailableContractType // and checkActiveDefaultOperations - String validContractType = "7fff1fc0037e3800000000000000000000000000000000000000000000000000"; + String validContractType = "7fff1fc0037ef807000000000000000000000000000000000000000000000000"; byte[] availableContractType = new byte[32]; for (ContractType contractType : ContractType.values()) { @@ -996,7 +996,7 @@ public void checkActiveDefaultOperationsCorrespondingToCode() { // 7fff1fc0033e0000000000000000000000000000000000000000000000000000, // and it should call the addSystemContractAndSetPermission to add new contract // type - String validContractType = "7fff1fc0033e3800000000000000000000000000000000000000000000000000"; + String validContractType = "7fff1fc0033ef807000000000000000000000000000000000000000000000000"; byte[] availableContractType = new byte[32]; for (ContractType contractType : ContractType.values()) { @@ -1019,7 +1019,7 @@ public void checkActiveDefaultOperationsCorrespondingToCode() { @Test public void checkAvailableContractType() { - String validContractType = "7fff1fc0037e3900000000000000000000000000000000000000000000000000"; + String validContractType = "7fff1fc0037ef907000000000000000000000000000000000000000000000000"; byte[] availableContractType = new byte[32]; for (ContractType contractType : ContractType.values()) { @@ -1040,7 +1040,7 @@ public void checkAvailableContractType() { @Test public void checkActiveDefaultOperations() { - String validContractType = "7fff1fc0033e3900000000000000000000000000000000000000000000000000"; + String validContractType = "7fff1fc0033ef907000000000000000000000000000000000000000000000000"; byte[] availableContractType = new byte[32]; for (ContractType contractType : ContractType.values()) { diff --git a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java index 3a06ef7f8d9..f4118fbef90 100644 --- a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java @@ -19,8 +19,6 @@ import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; -import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; -import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.Parameter.ChainConstant; @@ -208,91 +206,6 @@ public void testFreezeBalanceForEnergy() { } - @Test - public void testFreezeDelegatedBalanceForBandwidthWithContractAddress() { - AccountCapsule receiverCapsule = - new AccountCapsule( - ByteString.copyFromUtf8("receiver"), - ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), - AccountType.Contract, - initBalance); - dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); - - dbManager.getDynamicPropertiesStore().saveAllowTvmConstantinople(1); - - dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); - long frozenBalance = 1_000_000_000L; - FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); - actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getDelegatedContractForBandwidthV2(OWNER_ADDRESS, frozenBalance)); - - TransactionResultCapsule ret = new TransactionResultCapsule(); - - try { - actuator.validate(); - actuator.execute(ret); - - AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); - - Assert.assertEquals(owner.getBalance(), initBalance - frozenBalance - - TRANSFER_FEE); - Assert.assertEquals(0L, owner.getAllFrozenBalanceForBandwidth()); - Assert.assertEquals(0L, owner.getAllFrozenBalanceForEnergy()); - Assert.assertEquals(frozenBalance, owner.getDelegatedFrozenBalanceForBandwidth()); - Assert.assertEquals(frozenBalance, owner.getTronPower()); - - } catch (ContractValidateException e) { - Assert.assertEquals(e.getMessage(), "Do not allow delegate resources to contract addresses"); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); - } - - - } - - - @Test - public void testFreezeDelegatedBalanceForCpuSameNameTokenClose() { - dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(0); - long frozenBalance = 1_000_000_000L; - FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); - actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getDelegatedContractForCpuV2(OWNER_ADDRESS, frozenBalance)); - - TransactionResultCapsule ret = new TransactionResultCapsule(); - long totalEnergyWeightBefore = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); - try { - actuator.validate(); - actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); - AccountCapsule owner = dbManager.getAccountStore() - .get(ByteArray.fromHexString(OWNER_ADDRESS)); - Assert.assertEquals(owner.getBalance(), initBalance - frozenBalance - - TRANSFER_FEE); - Assert.assertEquals(0L, owner.getAllFrozenBalanceForBandwidth()); - Assert.assertEquals(frozenBalance, owner.getAllFrozenBalanceForEnergy()); - Assert.assertEquals(0L, owner.getDelegatedFrozenBalanceForBandwidth()); - Assert.assertEquals(0L, owner.getDelegatedFrozenBalanceForEnergy()); - - - AccountCapsule receiver = - dbManager.getAccountStore().get(ByteArray.fromHexString(RECEIVER_ADDRESS)); - Assert.assertEquals(0L, receiver.getAcquiredDelegatedFrozenBalanceForBandwidth()); - Assert.assertEquals(0L, receiver.getAcquiredDelegatedFrozenBalanceForEnergy()); - Assert.assertEquals(0L, receiver.getTronPower()); - - long totalEnergyWeightAfter = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); - Assert.assertEquals(totalEnergyWeightBefore + frozenBalance / 1000_000L, - totalEnergyWeightAfter); - - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); - } - } - @Test public void freezeLessThanZero() { long frozenBalance = -1_000_000_000L; diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java index d165307b524..3633d1cba08 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java @@ -21,8 +21,6 @@ import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; -import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; -import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.VotesCapsule; import org.tron.core.config.DefaultConfig; From d4d7fcd62e23bf33e07a6bdeffd65ab5c2ae70cb Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Mon, 19 Sep 2022 15:18:35 +0800 Subject: [PATCH 0328/1197] feat(freezeV2): modify unfreezebalance --- .../WithdrawExpireUnfreezeActuator.java | 153 ++++++++++ .../org/tron/core/capsule/AccountCapsule.java | 107 +++---- .../org/tron/core/services/RpcApiService.java | 12 +- .../services/http/FullNodeHttpApiService.java | 5 + ...ava => WithdrawExpireUnfreezeServlet.java} | 15 +- .../actuator/FreezeBalanceV2ActuatorTest.java | 2 +- .../UnfreezeBalanceV2ActuatorTest.java | 4 +- .../WithdrawExpireUnfreezeActuatorTest.java | 275 ++++++++++++++++++ protocol/src/main/protos/api/api.proto | 4 + protocol/src/main/protos/core/Tron.proto | 2 +- .../core/contract/balance_contract.proto | 2 +- 11 files changed, 507 insertions(+), 74 deletions(-) create mode 100755 actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java rename framework/src/main/java/org/tron/core/services/http/{WithdrawBalanceV2Servlet.java => WithdrawExpireUnfreezeServlet.java} (78%) create mode 100644 framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java diff --git a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java new file mode 100755 index 00000000000..5ba0a32e2be --- /dev/null +++ b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java @@ -0,0 +1,153 @@ +package org.tron.core.actuator; + +import com.google.common.math.LongMath; +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import lombok.extern.slf4j.Slf4j; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.AccountStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.Protocol.Account.UnFreezeV2; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.BalanceContract.WithdrawExpireUnfreezeContract; + +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; + + +@Slf4j(topic = "actuator") +public class WithdrawExpireUnfreezeActuator extends AbstractActuator { + + public WithdrawExpireUnfreezeActuator() { + super(ContractType.WithdrawExpireUnfreezeContract, WithdrawExpireUnfreezeContract.class); + } + + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + long fee = calcFee(); + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + final WithdrawExpireUnfreezeContract withdrawExpireUnfreezeContract; + try { + withdrawExpireUnfreezeContract = any.unpack(WithdrawExpireUnfreezeContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + AccountCapsule accountCapsule = accountStore. + get(withdrawExpireUnfreezeContract.getOwnerAddress().toByteArray()); + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); + long totalWithdrawUnfreeze = getTotalWithdrawUnfreeze(unfrozenV2List, now); + accountCapsule.setInstance(accountCapsule.getInstance().toBuilder() + .setBalance(accountCapsule.getBalance() + totalWithdrawUnfreeze) + .setLatestWithdrawTime(now) + .build()); + List newUnFreezeList = getRemainWithdrawList(unfrozenV2List, now); + accountCapsule.clearUnfrozenV2(); + newUnFreezeList.forEach(accountCapsule::addUnfrozenV2); + accountStore.put(accountCapsule.createDbKey(), accountCapsule); + ret.setStatus(fee, code.SUCESS); + return true; + } + + @Override + public boolean validate() throws ContractValidateException { + if (Objects.isNull(this.any)) { + throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); + } + if (Objects.isNull(chainBaseManager)) { + throw new ContractValidateException(ActuatorConstant.STORE_NOT_EXIST); + } + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + if (!this.any.is(WithdrawExpireUnfreezeContract.class)) { + throw new ContractValidateException( + "contract type error, expected type [WithdrawExpireUnfreezeContract], real type[" + any + .getClass() + "]"); + } + final WithdrawExpireUnfreezeContract withdrawExpireUnfreezeContract; + try { + withdrawExpireUnfreezeContract = this.any.unpack(WithdrawExpireUnfreezeContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + throw new ContractValidateException(e.getMessage()); + } + byte[] ownerAddress = withdrawExpireUnfreezeContract.getOwnerAddress().toByteArray(); + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + AccountCapsule accountCapsule = accountStore.get(ownerAddress); + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + if (Objects.isNull(accountCapsule)) { + throw new ContractValidateException(ACCOUNT_EXCEPTION_STR + + readableOwnerAddress + NOT_EXIST_STR); + } + + boolean isGP = CommonParameter.getInstance() + .getGenesisBlock().getWitnesses().stream().anyMatch(witness -> + Arrays.equals(ownerAddress, witness.getAddress())); + if (isGP) { + throw new ContractValidateException( + ACCOUNT_EXCEPTION_STR + readableOwnerAddress + + "] is a guard representative and is not allowed to withdraw Balance"); + } + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); + long totalWithdrawUnfreeze = getTotalWithdrawUnfreeze(unfrozenV2List, now); + if (totalWithdrawUnfreeze <= 0) { + throw new ContractValidateException("no unFreeze balance to withdraw "); + } + try { + LongMath.checkedAdd(accountCapsule.getBalance(), totalWithdrawUnfreeze); + } catch (ArithmeticException e) { + logger.debug(e.getMessage(), e); + throw new ContractValidateException(e.getMessage()); + } + return true; + } + + private long getTotalWithdrawUnfreeze(List unfrozenV2List, long now) { + return getTotalWithdrawList(unfrozenV2List, now).stream() + .mapToLong(UnFreezeV2::getUnfreezeAmount).sum(); + } + + private List getTotalWithdrawList(List unfrozenV2List, long now) { + return unfrozenV2List.stream().filter(unfrozenV2 -> (unfrozenV2.getUnfreezeAmount() > 0 + && unfrozenV2.getUnfreezeExpireTime() <= now)).collect(Collectors.toList()); + } + + private List getRemainWithdrawList(List unfrozenV2List, long now) { + return unfrozenV2List.stream() + .filter(unfrozenV2 -> unfrozenV2.getUnfreezeExpireTime() > now) + .collect(Collectors.toList()); + } + + @Override + public ByteString getOwnerAddress() throws InvalidProtocolBufferException { + return any.unpack(WithdrawExpireUnfreezeContract.class).getOwnerAddress(); + } + + @Override + public long calcFee() { + return 0; + } + +} diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index bffbc08d653..919e7a411d8 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -19,8 +19,6 @@ import com.google.common.collect.Maps; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; -import java.util.List; -import java.util.Map; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.ByteArray; import org.tron.core.capsule.utils.AssetUtil; @@ -30,6 +28,8 @@ import org.tron.protos.Protocol.Account.AccountResource; import org.tron.protos.Protocol.Account.Builder; import org.tron.protos.Protocol.Account.Frozen; +import org.tron.protos.Protocol.Account.FreezeV2; +import org.tron.protos.Protocol.Account.UnFreezeV2; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Key; import org.tron.protos.Protocol.Permission; @@ -39,6 +39,14 @@ import org.tron.protos.contract.AccountContract.AccountUpdateContract; import org.tron.protos.contract.Common; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; +import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; + @Slf4j(topic = "capsule") public class AccountCapsule implements ProtoCapsule, Comparable { @@ -530,25 +538,19 @@ public long getTronPower() { tp += account.getAccountResource().getFrozenBalanceForEnergy().getFrozenBalance(); tp += account.getDelegatedFrozenBalanceForBandwidth(); tp += account.getAccountResource().getDelegatedFrozenBalanceForEnergy(); - - // add v2 tron power - for (Account.FreezeV2 freezeV2 : account.getFrozenV2List()) { - // type: BANDWIDTH,ENERGY - if (freezeV2.getType() != Common.ResourceCode.TRON_POWER) { - tp += freezeV2.getAmount(); - } - } - + tp += getFrozenV2List().stream().filter(o -> o.getType() != TRON_POWER) + .mapToLong(FreezeV2::getAmount).sum(); return tp; } public long getAllTronPower() { if (account.getOldTronPower() == -1) { - return getTronPowerFrozenBalance() + getTronPowerFrozenBalanceV2(); + return getTronPowerFrozenBalance() + getTronPowerFrozenV2Balance(); } else if (account.getOldTronPower() == 0) { - return getTronPower() + getTronPowerFrozenBalance() + getTronPowerFrozenBalanceV2(); + return getTronPower() + getTronPowerFrozenBalance() + getTronPowerFrozenV2Balance(); } else { - return account.getOldTronPower() + getTronPowerFrozenBalance() + getTronPowerFrozenBalanceV2(); + return account.getOldTronPower() + getTronPowerFrozenBalance() + + getTronPowerFrozenV2Balance(); } } @@ -572,13 +574,6 @@ public void addFrozenV2List(Account.FreezeV2 frozenV2) { this.account = this.account.toBuilder().addFrozenV2(frozenV2).build(); } - /** - * - * @param type - * @param unfreezeAmount - * @param expireTime - * @return - */ public void addUnfrozenV2List(Common.ResourceCode type, long unfreezeAmount, long expireTime) { Account.UnFreezeV2 unFreezeV2 = Account.UnFreezeV2.newBuilder() @@ -855,21 +850,18 @@ public long getFrozenBalance() { return frozenBalance[0]; } - /** - * only for test - * @return - */ - public long getFrozenBalanceV2() { - List freezeV2List = getFrozenV2List(); - long amount = 0L; - for (Account.FreezeV2 freezeV2 : freezeV2List) { - amount += freezeV2.getAmount(); + public long getFrozenV2BalanceForBandwidth() { + List frozenList = getFrozenV2List(); + if (frozenList.isEmpty()) { + return 0; } - return amount; + return frozenList.stream().filter(o -> o.getType() == BANDWIDTH) + .mapToLong(FreezeV2::getAmount).sum(); } public long getAllFrozenBalanceForBandwidth() { - return getFrozenBalance() + getAcquiredDelegatedFrozenBalanceForBandwidth() + getBandWidthFrozenBalanceV2(); + return getFrozenBalance() + getAcquiredDelegatedFrozenBalanceForBandwidth() + + getFrozenV2BalanceForBandwidth(); } public int getFrozenSupplyCount() { @@ -1004,28 +996,15 @@ public long getEnergyFrozenBalance() { return this.account.getAccountResource().getFrozenBalanceForEnergy().getFrozenBalance(); } - - private long getBandWidthFrozenBalanceV2() { - List freezeV2List = this.account.getFrozenV2List(); - for (Account.FreezeV2 freezeV2 : freezeV2List) { - if(freezeV2.getType().equals(Common.ResourceCode.BANDWIDTH)) { - return freezeV2.getAmount(); - } - } - return 0L; - } - - private long getEnergyFrozenBalanceV2() { - List freezeV2List = this.account.getFrozenV2List(); - for (Account.FreezeV2 freezeV2 : freezeV2List) { - if(freezeV2.getType().equals(Common.ResourceCode.ENERGY)) { - return freezeV2.getAmount(); - } + public long getFrozenV2BalanceForEnergy() { + List frozenList = getFrozenV2List(); + if (frozenList.isEmpty()) { + return 0; } - return 0L; + return frozenList.stream().filter(o -> o.getType() == ENERGY) + .mapToLong(FreezeV2::getAmount).sum(); } - public boolean oldTronPowerIsNotInitialized() { return this.account.getOldTronPower() == 0; } @@ -1077,17 +1056,11 @@ public long getTronPowerFrozenBalance() { return this.account.getTronPower().getFrozenBalance(); } - public long getTronPowerFrozenBalanceV2() { - List freezeV2List = this.account.getFrozenV2List(); - for (Account.FreezeV2 freezeV2 : freezeV2List) { - if(freezeV2.getType().equals(Common.ResourceCode.TRON_POWER)) { - return freezeV2.getAmount(); - } - } - return 0L; + public long getTronPowerFrozenV2Balance() { + return getFrozenV2List().stream().filter(o-> o.getType() == TRON_POWER) + .mapToLong(FreezeV2::getAmount).sum(); } - public long getEnergyUsage() { return this.account.getAccountResource().getEnergyUsage(); } @@ -1100,7 +1073,8 @@ public void setEnergyUsage(long energyUsage) { } public long getAllFrozenBalanceForEnergy() { - return getEnergyFrozenBalance() + getAcquiredDelegatedFrozenBalanceForEnergy() + getEnergyFrozenBalanceV2(); + return getEnergyFrozenBalance() + getAcquiredDelegatedFrozenBalanceForEnergy() + + getFrozenV2BalanceForEnergy(); } public long getLatestConsumeTimeForEnergy() { @@ -1277,4 +1251,15 @@ public void importAllAsset() { } } + public void addUnfrozenV2(UnFreezeV2 unfrozenV2) { + if (Objects.isNull(unfrozenV2)) { + return; + } + this.account = this.account.toBuilder().addUnfrozenV2(unfrozenV2).build(); + } + + public void clearUnfrozenV2() { + this.account = this.account.toBuilder().clearUnfrozenV2().build(); + } + } diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index c3184a46307..c3528237b98 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -150,6 +150,7 @@ import org.tron.protos.contract.BalanceContract.TransferContract; import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; import org.tron.protos.contract.BalanceContract.WithdrawBalanceContract; +import org.tron.protos.contract.BalanceContract.WithdrawExpireUnfreezeContract; import org.tron.protos.contract.ExchangeContract.ExchangeCreateContract; import org.tron.protos.contract.ExchangeContract.ExchangeInjectContract; import org.tron.protos.contract.ExchangeContract.ExchangeTransactionContract; @@ -1535,6 +1536,13 @@ public void withdrawBalance2(WithdrawBalanceContract request, createTransactionExtention(request, ContractType.WithdrawBalanceContract, responseObserver); } + @Override + public void withdrawExpireUnfreeze(WithdrawExpireUnfreezeContract request, + StreamObserver responseObserver) { + createTransactionExtention(request, ContractType.WithdrawExpireUnfreezeContract, + responseObserver); + } + @Override public void proposalCreate(ProposalCreateContract request, StreamObserver responseObserver) { @@ -1871,7 +1879,7 @@ public void getTransactionById(BytesMessage request, @Override public void deployContract(CreateSmartContract request, - io.grpc.stub.StreamObserver responseObserver) { + StreamObserver responseObserver) { createTransactionExtention(request, ContractType.CreateSmartContract, responseObserver); } @@ -2520,7 +2528,7 @@ public void isShieldedTRC20ContractNoteSpent(NfTRC20Parameters request, @Override public void getTriggerInputForShieldedTRC20Contract( ShieldedTRC20TriggerContractParameters request, - io.grpc.stub.StreamObserver responseObserver) { + StreamObserver responseObserver) { try { checkSupportShieldedTRC20Transaction(); diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index 031bd38e50c..26a5256fcc2 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -293,6 +293,8 @@ public class FullNodeHttpApiService implements Service { private GetBandwidthPricesServlet getBandwidthPricesServlet; @Autowired private GetBlockServlet getBlockServlet; + @Autowired + private WithdrawExpireUnfreezeServlet withdrawExpireUnfreezeServlet; private static String getParamsFile(String fileName) { InputStream in = Thread.currentThread().getContextClassLoader() @@ -543,6 +545,9 @@ public void start() { "/wallet/getbandwidthprices"); context.addServlet(new ServletHolder(getBlockServlet), "/wallet/getblock"); + context.addServlet(new ServletHolder(withdrawExpireUnfreezeServlet), + "/wallet/withdrawExpireUnfreeze"); + int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { server.addBean(new ConnectionLimit(maxHttpConnectNumber, server)); diff --git a/framework/src/main/java/org/tron/core/services/http/WithdrawBalanceV2Servlet.java b/framework/src/main/java/org/tron/core/services/http/WithdrawExpireUnfreezeServlet.java similarity index 78% rename from framework/src/main/java/org/tron/core/services/http/WithdrawBalanceV2Servlet.java rename to framework/src/main/java/org/tron/core/services/http/WithdrawExpireUnfreezeServlet.java index 1696fa8863b..4888ee42de4 100644 --- a/framework/src/main/java/org/tron/core/services/http/WithdrawBalanceV2Servlet.java +++ b/framework/src/main/java/org/tron/core/services/http/WithdrawExpireUnfreezeServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; @@ -10,16 +11,18 @@ import org.tron.core.Wallet; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.contract.BalanceContract.WithdrawBalanceV2Contract; +import org.tron.protos.contract.BalanceContract.WithdrawExpireUnfreezeContract; + @Component @Slf4j(topic = "API") -public class WithdrawBalanceV2Servlet extends RateLimiterServlet { +public class WithdrawExpireUnfreezeServlet extends RateLimiterServlet { @Autowired private Wallet wallet; protected void doGet(HttpServletRequest request, HttpServletResponse response) { + } protected void doPost(HttpServletRequest request, HttpServletResponse response) { @@ -28,16 +31,16 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); boolean visible = Util.getVisiblePost(contract); - WithdrawBalanceV2Contract.Builder build = WithdrawBalanceV2Contract.newBuilder(); + WithdrawExpireUnfreezeContract.Builder build = WithdrawExpireUnfreezeContract.newBuilder(); JsonFormat.merge(contract, build, visible); Transaction tx = wallet - .createTransactionCapsule(build.build(), ContractType.WithdrawBalanceV2Contract) + .createTransactionCapsule(build.build(), ContractType.WithdrawExpireUnfreezeContract) .getInstance(); - JSONObject jsonObject = JSONObject.parseObject(contract); + JSONObject jsonObject = JSON.parseObject(contract); tx = Util.setTransactionPermissionId(jsonObject, tx); response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { Util.processError(e, response); } } -} \ No newline at end of file +} diff --git a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java index f4118fbef90..87708196143 100644 --- a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java @@ -169,7 +169,7 @@ public void testFreezeBalanceForBandwidth() { Assert.assertEquals(owner.getBalance(), initBalance - frozenBalance - TRANSFER_FEE); - Assert.assertEquals(owner.getFrozenBalanceV2(), frozenBalance); + Assert.assertEquals(owner.getFrozenV2BalanceForBandwidth(), frozenBalance); Assert.assertEquals(frozenBalance, owner.getTronPower()); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java index 3633d1cba08..f174dbb782f 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java @@ -168,7 +168,7 @@ public void testUnfreezeBalanceForBandwidth() { accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); long unfreezeBalance = frozenBalance - 100; - Assert.assertEquals(accountCapsule.getFrozenBalanceV2(), frozenBalance); + Assert.assertEquals(accountCapsule.getFrozenV2BalanceForBandwidth(), frozenBalance); Assert.assertEquals(accountCapsule.getTronPower(), frozenBalance); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -187,7 +187,7 @@ public void testUnfreezeBalanceForBandwidth() { .get(ByteArray.fromHexString(OWNER_ADDRESS)); //Assert.assertEquals(owner.getBalance(), initBalance + frozenBalance); - Assert.assertEquals(owner.getFrozenBalanceV2(), 100); + Assert.assertEquals(owner.getFrozenV2BalanceForBandwidth(), 100); Assert.assertEquals(owner.getTronPower(), 100L); long totalNetWeightAfter = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); diff --git a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java new file mode 100644 index 00000000000..83d4dcbe7cc --- /dev/null +++ b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java @@ -0,0 +1,275 @@ +package org.tron.core.actuator; + +import static junit.framework.TestCase.fail; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import java.io.File; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.args.Witness; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.capsule.WitnessCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.exception.BalanceInsufficientException; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.protos.Protocol.Account.UnFreezeV2; +import org.tron.protos.Protocol.AccountType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.AssetIssueContractOuterClass; +import org.tron.protos.contract.BalanceContract.WithdrawExpireUnfreezeContract; + +@Slf4j +public class WithdrawExpireUnfreezeActuatorTest { + + private static final String dbPath = "output_withdraw_expire_unfreeze_test"; + private static final String OWNER_ADDRESS; + private static final String OWNER_ADDRESS_INVALID = "aaaa"; + private static final String OWNER_ACCOUNT_INVALID; + private static final long initBalance = 10_000_000_000L; + private static final long allowance = 32_000_000L; + private static Manager dbManager; + private static TronApplicationContext context; + + static { + Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + OWNER_ACCOUNT_INVALID = + Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; + } + + /** + * Init data. + */ + @BeforeClass + public static void init() { + dbManager = context.getBean(Manager.class); + } + + /** + * Release resources. + */ + @AfterClass + public static void destroy() { + Args.clearParam(); + context.destroy(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.info("Release resources failure."); + } + } + + /** + * create temp Capsule test need. + */ + @Before + public void createAccountCapsule() { + AccountCapsule ownerCapsule = new AccountCapsule(ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), AccountType.Normal, + initBalance); + UnFreezeV2 unFreezeV2_1 = UnFreezeV2.newBuilder().setType(BANDWIDTH) + .setUnfreezeAmount(16_000_000L).setUnfreezeExpireTime(1).build(); + UnFreezeV2 unFreezeV2_2 = UnFreezeV2.newBuilder().setType(ENERGY) + .setUnfreezeAmount(16_000_000L).setUnfreezeExpireTime(1).build(); + UnFreezeV2 unFreezeV2_3 = UnFreezeV2.newBuilder().setType(ENERGY) + .setUnfreezeAmount(0).setUnfreezeExpireTime(Long.MAX_VALUE).build(); + ownerCapsule.addUnfrozenV2(unFreezeV2_1); + ownerCapsule.addUnfrozenV2(unFreezeV2_2); + ownerCapsule.addUnfrozenV2(unFreezeV2_3); + dbManager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); + } + + private Any getContract(String ownerAddress) { + return Any.pack(WithdrawExpireUnfreezeContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))).build()); + } + + @Test + public void testWithdrawExpireUnfreeze() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + byte[] address = ByteArray.fromHexString(OWNER_ADDRESS); + + AccountCapsule accountCapsule = dbManager.getAccountStore().get(address); + Assert.assertEquals(accountCapsule.getLatestWithdrawTime(), 0); + + WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address), 100, + "http://baidu.com/"); + dbManager.getWitnessStore().put(address, witnessCapsule); + + WithdrawExpireUnfreezeActuator actuator = new WithdrawExpireUnfreezeActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContract(OWNER_ADDRESS)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); + AccountCapsule owner = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + List unfrozenV2List = owner.getInstance().getUnfrozenV2List(); + Assert.assertEquals(1, unfrozenV2List.size()); + Assert.assertEquals(Long.MAX_VALUE, unfrozenV2List.get(0).getUnfreezeExpireTime()); + Assert.assertEquals(initBalance + 32_000_000L, owner.getBalance()); + Assert.assertEquals(0, owner.getAllowance()); + Assert.assertNotEquals(0, owner.getLatestWithdrawTime()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + + @Test + public void invalidOwnerAddress() { + WithdrawExpireUnfreezeActuator actuator = new WithdrawExpireUnfreezeActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContract(OWNER_ADDRESS_INVALID)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + + Assert.assertEquals("Invalid address", e.getMessage()); + + } catch (ContractExeException e) { + Assert.assertTrue(e instanceof ContractExeException); + } + + } + + @Test + public void invalidOwnerAccount() { + WithdrawExpireUnfreezeActuator actuator = new WithdrawExpireUnfreezeActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContract(OWNER_ACCOUNT_INVALID)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Account[" + OWNER_ACCOUNT_INVALID + "] not exists", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void isGR() { + Witness w = Args.getInstance().getGenesisBlock().getWitnesses().get(0); + byte[] address = w.getAddress(); + AccountCapsule grCapsule = new AccountCapsule(ByteString.copyFromUtf8("gr"), + ByteString.copyFrom(address), AccountType.Normal, initBalance); + dbManager.getAccountStore().put(grCapsule.createDbKey(), grCapsule); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + try { + dbManager.getMortgageService() + .adjustAllowance(dbManager.getAccountStore(), address, allowance); + } catch (BalanceInsufficientException e) { + fail("BalanceInsufficientException"); + } + AccountCapsule accountCapsule = dbManager.getAccountStore().get(address); + Assert.assertEquals(accountCapsule.getAllowance(), allowance); + + WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address), 100, + "http://google.com/"); + + dbManager.getAccountStore().put(address, accountCapsule); + dbManager.getWitnessStore().put(address, witnessCapsule); + + WithdrawExpireUnfreezeActuator actuator = new WithdrawExpireUnfreezeActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContract(ByteArray.toHexString(address))); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + Assert.assertTrue(dbManager.getWitnessStore().has(address)); + + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + + } catch (ContractValidateException e) { + String readableOwnerAddress = StringUtil.createReadableString(address); + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Account[" + readableOwnerAddress + + "] is a guard representative and is not allowed to withdraw Balance", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void commonErrorCheck() { + + WithdrawExpireUnfreezeActuator actuator = new WithdrawExpireUnfreezeActuator(); + ActuatorTest actuatorTest = new ActuatorTest(actuator, dbManager); + actuatorTest.noContract(); + + Any invalidContractTypes = Any.pack(AssetIssueContractOuterClass.AssetIssueContract.newBuilder() + .build()); + actuatorTest.setInvalidContract(invalidContractTypes); + actuatorTest.setInvalidContractTypeMsg("contract type error", + "contract type error, expected type [WithdrawExpireUnfreezeContract], real type["); + actuatorTest.invalidContractType(); + + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + byte[] address = ByteArray.fromHexString(OWNER_ADDRESS); + try { + dbManager.getMortgageService() + .adjustAllowance(dbManager.getAccountStore(), address, allowance); + } catch (BalanceInsufficientException e) { + fail("BalanceInsufficientException"); + } + AccountCapsule accountCapsule = dbManager.getAccountStore().get(address); + Assert.assertEquals(accountCapsule.getAllowance(), allowance); + Assert.assertEquals(accountCapsule.getLatestWithdrawTime(), 0); + + WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address), 100, + "http://google.com/"); + dbManager.getWitnessStore().put(address, witnessCapsule); + + actuatorTest.setContract(getContract(OWNER_ADDRESS)); + actuatorTest.nullTransationResult(); + + actuatorTest.setNullDBManagerMsg("No account store or dynamic store!"); + actuatorTest.nullDBManger(); + } + +} + diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index baa4a5fad78..b3ce3d56e51 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -271,6 +271,10 @@ service Wallet { //Use this function instead of WithdrawBalance. rpc WithdrawBalance2 (WithdrawBalanceContract) returns (TransactionExtention) { } + + rpc WithdrawExpireUnfreeze (WithdrawExpireUnfreezeContract) returns (TransactionExtention) { + } + //Please use UpdateAsset2 instead of this function. rpc UpdateAsset (UpdateAssetContract) returns (Transaction) { option (google.api.http) = { diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index ba0e7d1b414..194a0d95a74 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -361,7 +361,7 @@ message Transaction { MarketCancelOrderContract = 53; FreezeBalanceV2Contract = 54; UnfreezeBalanceV2Contract = 55; - WithdrawBalanceV2Contract = 56; + WithdrawExpireUnfreezeContract = 56; DelegateResourceContract = 57; UnDelegateResourceContract = 58; } diff --git a/protocol/src/main/protos/core/contract/balance_contract.proto b/protocol/src/main/protos/core/contract/balance_contract.proto index db54939a3d4..284e43a03e6 100644 --- a/protocol/src/main/protos/core/contract/balance_contract.proto +++ b/protocol/src/main/protos/core/contract/balance_contract.proto @@ -93,7 +93,7 @@ message UnfreezeBalanceV2Contract { ResourceCode resource = 3; } -message WithdrawBalanceV2Contract { +message WithdrawExpireUnfreezeContract { bytes owner_address = 1; } From 127d28218c799ae24024ddaeee8b9a728f3da434 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Thu, 22 Sep 2022 14:49:39 +0800 Subject: [PATCH 0329/1197] feat(freezeV2): add delegate resource 1. add delegate resource contract 2. add undelegate resource contract 3. add test cases for delegate and undelegate resource --- .../actuator/DelegateResourceActuator.java | 268 ++++++ .../actuator/UnDelegateResourceActuator.java | 299 +++++++ .../DelegatedResourceAccountIndexCapsule.java | 9 + .../capsule/DelegatedResourceCapsule.java | 9 + .../org/tron/core/db/BandwidthProcessor.java | 0 .../DelegateResourceActuatorTest.java | 485 ++++++++++ .../UnDelegateResourceActuatorTest.java | 836 ++++++++++++++++++ 7 files changed, 1906 insertions(+) create mode 100755 actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java create mode 100755 actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java rename {framework => chainbase}/src/main/java/org/tron/core/db/BandwidthProcessor.java (100%) create mode 100644 framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java create mode 100644 framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java new file mode 100755 index 00000000000..156581342ad --- /dev/null +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -0,0 +1,268 @@ +package org.tron.core.actuator; + +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; +import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; +import org.tron.core.capsule.DelegatedResourceCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.db.BandwidthProcessor; +import org.tron.core.db.EnergyProcessor; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.AccountStore; +import org.tron.core.store.DelegatedResourceAccountIndexStore; +import org.tron.core.store.DelegatedResourceStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.Protocol.AccountType; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.BalanceContract.DelegateResourceContract; + +@Slf4j(topic = "actuator") +public class DelegateResourceActuator extends AbstractActuator { + + public DelegateResourceActuator() { + super(ContractType.DelegateResourceContract, DelegateResourceContract.class); + } + + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + + long fee = calcFee(); + final DelegateResourceContract delegateResourceContract; + AccountStore accountStore = chainBaseManager.getAccountStore(); + try { + delegateResourceContract = any.unpack(DelegateResourceContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + + AccountCapsule ownerCapsule = accountStore + .get(delegateResourceContract.getOwnerAddress().toByteArray()); + + // TODO remove + // if (dynamicStore.supportAllowNewResourceModel() + // && accountCapsule.oldTronPowerIsNotInitialized()) { + // accountCapsule.initializeOldTronPower(); + // } + + long delegateBalance = delegateResourceContract.getBalance(); + byte[] ownerAddress = delegateResourceContract.getOwnerAddress().toByteArray(); + byte[] receiverAddress = delegateResourceContract.getReceiverAddress().toByteArray(); + + // delegate resource to receiver + switch (delegateResourceContract.getResource()) { + case BANDWIDTH: + delegateResource(ownerAddress, receiverAddress, true, + delegateBalance); + + ownerCapsule.addDelegatedFrozenBalanceForBandwidth(delegateBalance); + ownerCapsule.addFrozenBalanceForBandwidthV2(-delegateBalance); + break; + case ENERGY: + delegateResource(ownerAddress, receiverAddress, false, + delegateBalance); + + ownerCapsule.addDelegatedFrozenBalanceForEnergy(delegateBalance); + ownerCapsule.addFrozenBalanceForEnergyV2(-delegateBalance); + break; + default: + logger.debug("Resource Code Error."); + } + + accountStore.put(ownerCapsule.createDbKey(), ownerCapsule); + + ret.setStatus(fee, code.SUCESS); + + return true; + } + + + @Override + public boolean validate() throws ContractValidateException { + if (this.any == null) { + throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); + } + if (chainBaseManager == null) { + throw new ContractValidateException(ActuatorConstant.STORE_NOT_EXIST); + } + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + if (!any.is(DelegateResourceContract.class)) { + throw new ContractValidateException( + "contract type error,expected type [DelegateResourceContract],real type[" + + any.getClass() + "]"); + } + + if (!dynamicStore.supportDR()) { + throw new ContractValidateException("No support for resource delegate"); + } + + final DelegateResourceContract delegateResourceContract; + try { + delegateResourceContract = this.any.unpack(DelegateResourceContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + throw new ContractValidateException(e.getMessage()); + } + byte[] ownerAddress = delegateResourceContract.getOwnerAddress().toByteArray(); + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + + AccountCapsule ownerCapsule = accountStore.get(ownerAddress); + if (ownerCapsule == null) { + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + throw new ContractValidateException( + ActuatorConstant.ACCOUNT_EXCEPTION_STR + readableOwnerAddress + NOT_EXIST_STR); + } + + long delegateBalance = delegateResourceContract.getBalance(); + if (delegateBalance < TRX_PRECISION) { + throw new ContractValidateException("delegateBalance must be more than 1TRX"); + } + + switch (delegateResourceContract.getResource()) { + case BANDWIDTH: { + BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); + processor.updateUsage(ownerCapsule); + long netBalanceUsage = (long) (ownerCapsule.getNetUsage() + * ((double) (dynamicStore.getTotalNetLimit()) / dynamicStore.getTotalNetWeight())); + if (ownerCapsule.getFrozenV2BalanceForBandwidth() - netBalanceUsage < delegateBalance) { + throw new ContractValidateException("delegateBalance must be less than accountFreezeBandwidthBalance"); + } + } + break; + case ENERGY: { + EnergyProcessor processor = new EnergyProcessor(dynamicStore, accountStore); + processor.updateUsage(ownerCapsule); + long energyBalanceUsage = (long) (ownerCapsule.getEnergyUsage() + * ((double) (dynamicStore.getTotalEnergyCurrentLimit()) / dynamicStore.getTotalEnergyWeight())); + if (ownerCapsule.getFrozenV2BalanceForEnergy() - energyBalanceUsage < delegateBalance) { + throw new ContractValidateException("delegateBalance must be less than accountFreezeEnergyBalance"); + } + } + break; + default: + throw new ContractValidateException( + "ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]"); + } + + byte[] receiverAddress = delegateResourceContract.getReceiverAddress().toByteArray(); + + if (ArrayUtils.isEmpty(receiverAddress) || !DecodeUtil.addressValid(receiverAddress)) { + throw new ContractValidateException("Invalid receiverAddress"); + } + + + if (Arrays.equals(receiverAddress, ownerAddress)) { + throw new ContractValidateException( + "receiverAddress must not be the same as ownerAddress"); + } + + AccountCapsule receiverCapsule = accountStore.get(receiverAddress); + if (receiverCapsule == null) { + String readableOwnerAddress = StringUtil.createReadableString(receiverAddress); + throw new ContractValidateException( + ActuatorConstant.ACCOUNT_EXCEPTION_STR + + readableOwnerAddress + NOT_EXIST_STR); + } + + if (receiverCapsule.getType() == AccountType.Contract) { + throw new ContractValidateException( + "Do not allow delegate resources to contract addresses"); + } + + return true; + } + + @Override + public ByteString getOwnerAddress() throws InvalidProtocolBufferException { + return any.unpack(DelegateResourceContract.class).getOwnerAddress(); + } + + @Override + public long calcFee() { + return 0; + } + + private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boolean isBandwidth, + long balance) { + AccountStore accountStore = chainBaseManager.getAccountStore(); + DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore(); + DelegatedResourceAccountIndexStore delegatedResourceAccountIndexStore = chainBaseManager + .getDelegatedResourceAccountIndexStore(); + + //modify DelegatedResourceStore + byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress); + DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore + .get(key); + if (delegatedResourceCapsule == null) { + delegatedResourceCapsule = new DelegatedResourceCapsule( + ByteString.copyFrom(ownerAddress), + ByteString.copyFrom(receiverAddress)); + } + if (isBandwidth) { + delegatedResourceCapsule.addFrozenBalanceForBandwidth(balance, 0); + } else { + delegatedResourceCapsule.addFrozenBalanceForEnergy(balance, 0); + } + delegatedResourceStore.put(key, delegatedResourceCapsule); + + //modify DelegatedResourceAccountIndexStore owner + byte[] ownerKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(ownerAddress); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = delegatedResourceAccountIndexStore + .get(ownerKey); + if (ownerIndexCapsule == null) { + ownerIndexCapsule = new DelegatedResourceAccountIndexCapsule( + ByteString.copyFrom(ownerAddress)); + } + List toAccountsList = ownerIndexCapsule.getToAccountsList(); + if (!toAccountsList.contains(ByteString.copyFrom(receiverAddress))) { + ownerIndexCapsule.addToAccount(ByteString.copyFrom(receiverAddress)); + delegatedResourceAccountIndexStore.put(ownerKey, ownerIndexCapsule); + } + + //modify DelegatedResourceAccountIndexStore receiver + byte[] receiverKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiverAddress); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = delegatedResourceAccountIndexStore + .get(receiverKey); + if (receiverIndexCapsule == null) { + receiverIndexCapsule = new DelegatedResourceAccountIndexCapsule( + ByteString.copyFrom(receiverAddress)); + } + List fromAccountsList = receiverIndexCapsule + .getFromAccountsList(); + if (!fromAccountsList.contains(ByteString.copyFrom(ownerAddress))) { + receiverIndexCapsule.addFromAccount(ByteString.copyFrom(ownerAddress)); + delegatedResourceAccountIndexStore.put(receiverKey, receiverIndexCapsule); + } + + //modify AccountStore for receiver + AccountCapsule receiverCapsule = accountStore.get(receiverAddress); + if (isBandwidth) { + receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(balance); + } else { + receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(balance); + } + accountStore.put(receiverCapsule.createDbKey(), receiverCapsule); + } + +} diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java new file mode 100755 index 00000000000..4140f9cfb73 --- /dev/null +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -0,0 +1,299 @@ +package org.tron.core.actuator; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; +import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; +import org.tron.core.capsule.DelegatedResourceCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.db.BandwidthProcessor; +import org.tron.core.db.EnergyProcessor; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.AccountStore; +import org.tron.core.store.DelegatedResourceAccountIndexStore; +import org.tron.core.store.DelegatedResourceStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.BalanceContract.UnDelegateResourceContract; + +@Slf4j(topic = "actuator") +public class UnDelegateResourceActuator extends AbstractActuator { + + public UnDelegateResourceActuator() { + super(ContractType.UnDelegateResourceContract, UnDelegateResourceContract.class); + } + + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + + long fee = calcFee(); + final UnDelegateResourceContract unDelegateResourceContract; + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore(); + DelegatedResourceAccountIndexStore delegatedResourceAccountIndexStore = chainBaseManager + .getDelegatedResourceAccountIndexStore(); + try { + unDelegateResourceContract = any.unpack(UnDelegateResourceContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + + + final long unDelegateBalance = unDelegateResourceContract.getBalance(); + byte[] ownerAddress = unDelegateResourceContract.getOwnerAddress().toByteArray(); + byte[] receiverAddress = unDelegateResourceContract.getReceiverAddress().toByteArray(); + + AccountCapsule receiverCapsule = accountStore.get(receiverAddress); + + long transferUsage = 0; + // modify receiver Account + if (receiverCapsule != null) { + switch (unDelegateResourceContract.getResource()) { + case BANDWIDTH: + BandwidthProcessor bandwidthProcessor = new BandwidthProcessor(chainBaseManager); + bandwidthProcessor.updateUsage(receiverCapsule); + + if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() + < unDelegateBalance) { + // A TVM contract suicide, re-create will produce this situation + transferUsage = receiverCapsule.getNetUsage(); + + receiverCapsule.setAcquiredDelegatedFrozenBalanceForBandwidth(0); + } else { + // calculate usage + long unDelegateBandwidth = (long) (unDelegateBalance / TRX_PRECISION + * ((double) (dynamicStore.getTotalNetLimit()) / dynamicStore.getTotalNetWeight())); + transferUsage = (long) (receiverCapsule.getNetUsage() + * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForBandwidth())); + transferUsage = Math.min(unDelegateBandwidth, transferUsage); + + receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(-unDelegateBalance); + } + + long newNetUsage = receiverCapsule.getNetUsage() - transferUsage; + receiverCapsule.setNetUsage(newNetUsage); + break; + case ENERGY: + EnergyProcessor energyProcessor = new EnergyProcessor(dynamicStore, accountStore); + energyProcessor.updateUsage(receiverCapsule); + + if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() + < unDelegateBalance) { + // A TVM contract receiver, re-create will produce this situation + transferUsage = receiverCapsule.getEnergyUsage(); + receiverCapsule.setAcquiredDelegatedFrozenBalanceForEnergy(0); + } else { + long unDelegateEnergy = (long) (unDelegateBalance / TRX_PRECISION + * ((double) (dynamicStore.getTotalEnergyCurrentLimit()) / dynamicStore.getTotalEnergyWeight())); + transferUsage = (long) (receiverCapsule.getEnergyUsage() + * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForEnergy())); + transferUsage = Math.min(unDelegateEnergy, transferUsage); + + receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(-unDelegateBalance); + } + + long newEnergyUsage = receiverCapsule.getEnergyUsage() - transferUsage; + receiverCapsule.setEnergyUsage(newEnergyUsage); + break; + default: + //this should never happen + break; + } + accountStore.put(receiverCapsule.createDbKey(), receiverCapsule); + } + + // modify owner Account + AccountCapsule accountCapsule = accountStore.get(ownerAddress); + byte[] key = DelegatedResourceCapsule + .createDbKeyV2(unDelegateResourceContract.getOwnerAddress().toByteArray(), + unDelegateResourceContract.getReceiverAddress().toByteArray()); + DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore + .get(key); + switch (unDelegateResourceContract.getResource()) { + case BANDWIDTH: { + long delegateBalance = delegatedResourceCapsule.getFrozenBalanceForBandwidth(); + delegatedResourceCapsule.setFrozenBalanceForBandwidth(delegateBalance - unDelegateBalance, 0); + accountCapsule.addDelegatedFrozenBalanceForBandwidth(-unDelegateBalance); + accountCapsule.addFrozenBalanceForBandwidthV2(unDelegateBalance); + + long newNetUsage = accountCapsule.getNetUsage() + transferUsage; + accountCapsule.setNetUsage(newNetUsage); + accountCapsule.setLatestConsumeTime(chainBaseManager.getHeadSlot()); + } + break; + case ENERGY: { + long delegateBalance = delegatedResourceCapsule.getFrozenBalanceForEnergy(); + delegatedResourceCapsule.setFrozenBalanceForEnergy(delegateBalance - unDelegateBalance, 0); + accountCapsule.addDelegatedFrozenBalanceForEnergy(-unDelegateBalance); + accountCapsule.addFrozenBalanceForEnergyV2(unDelegateBalance); + + long newEnergyUsage = accountCapsule.getEnergyUsage() + transferUsage; + accountCapsule.setEnergyUsage(newEnergyUsage); + accountCapsule.setLatestConsumeTimeForEnergy(chainBaseManager.getHeadSlot()); + } + break; + default: + //this should never happen + break; + } + + if (delegatedResourceCapsule.getFrozenBalanceForBandwidth() == 0 + && delegatedResourceCapsule.getFrozenBalanceForEnergy() == 0) { + delegatedResourceStore.delete(key); + + //modify DelegatedResourceAccountIndexStore for owner + byte[] ownerKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(ownerAddress); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = delegatedResourceAccountIndexStore + .get(ownerKey); + if (ownerIndexCapsule != null) { + List toAccountsList = new ArrayList<>(ownerIndexCapsule + .getToAccountsList()); + toAccountsList.remove(ByteString.copyFrom(receiverAddress)); + ownerIndexCapsule.setAllToAccounts(toAccountsList); + delegatedResourceAccountIndexStore + .put(ownerKey, ownerIndexCapsule); + } + + //modify DelegatedResourceAccountIndexStore for receive + byte[] receiverKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiverAddress); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = delegatedResourceAccountIndexStore + .get(receiverKey); + if (receiverIndexCapsule != null) { + List fromAccountsList = new ArrayList<>(receiverIndexCapsule + .getFromAccountsList()); + fromAccountsList.remove(ByteString.copyFrom(ownerAddress)); + receiverIndexCapsule.setAllFromAccounts(fromAccountsList); + delegatedResourceAccountIndexStore + .put(receiverKey, receiverIndexCapsule); + } + + } else { + delegatedResourceStore.put(key, delegatedResourceCapsule); + } + + accountStore.put(ownerAddress, accountCapsule); + + ret.setStatus(fee, code.SUCESS); + + return true; + } + + @Override + public boolean validate() throws ContractValidateException { + if (this.any == null) { + throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); + } + if (chainBaseManager == null) { + throw new ContractValidateException(ActuatorConstant.STORE_NOT_EXIST); + } + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore(); + if (!dynamicStore.supportDR()) { + throw new ContractValidateException("No support for resource delegate"); + } + + if (!this.any.is(UnDelegateResourceContract.class)) { + throw new ContractValidateException( + "contract type error, expected type [UnDelegateResourceContract], real type[" + any + .getClass() + "]"); + } + final UnDelegateResourceContract unDelegateResourceContract; + try { + unDelegateResourceContract = this.any.unpack(UnDelegateResourceContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + throw new ContractValidateException(e.getMessage()); + } + + byte[] ownerAddress = unDelegateResourceContract.getOwnerAddress().toByteArray(); + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + AccountCapsule ownerCapsule = accountStore.get(ownerAddress); + if (ownerCapsule == null) { + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + throw new ContractValidateException( + ACCOUNT_EXCEPTION_STR + readableOwnerAddress + "] does not exist"); + } + + byte[] receiverAddress = unDelegateResourceContract.getReceiverAddress().toByteArray(); + if (ArrayUtils.isEmpty(receiverAddress) || !DecodeUtil.addressValid(receiverAddress)) { + throw new ContractValidateException("Invalid receiverAddress"); + } + if (Arrays.equals(receiverAddress, ownerAddress)) { + throw new ContractValidateException( + "receiverAddress must not be the same as ownerAddress"); + } + + // TVM contract suicide can result in no receiving account + // AccountCapsule receiverCapsule = accountStore.get(receiverAddress); + // if (receiverCapsule == null) { + // String readableReceiverAddress = StringUtil.createReadableString(receiverAddress); + // throw new ContractValidateException( + // "Receiver Account[" + readableReceiverAddress + "] does not exist"); + // } + + byte[] key = DelegatedResourceCapsule + .createDbKeyV2(unDelegateResourceContract.getOwnerAddress().toByteArray(), + unDelegateResourceContract.getReceiverAddress().toByteArray()); + DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore.get(key); + if (delegatedResourceCapsule == null) { + throw new ContractValidateException( + "delegated Resource does not exist"); + } + + long unDelegateBalance = unDelegateResourceContract.getBalance(); + switch (unDelegateResourceContract.getResource()) { + case BANDWIDTH: + if (delegatedResourceCapsule.getFrozenBalanceForBandwidth() < unDelegateBalance) { + throw new ContractValidateException("insufficient delegatedFrozenBalance(BANDWIDTH), request=" + + unDelegateBalance + ", balance=" + delegatedResourceCapsule.getFrozenBalanceForBandwidth()); + } + break; + case ENERGY: + if (delegatedResourceCapsule.getFrozenBalanceForEnergy() < unDelegateBalance) { + throw new ContractValidateException("insufficient delegateFrozenBalance(Energy), request=" + + unDelegateBalance + ", balance=" + delegatedResourceCapsule.getFrozenBalanceForEnergy()); + } + break; + default: + throw new ContractValidateException( + "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + } + + + return true; + } + + @Override + public ByteString getOwnerAddress() throws InvalidProtocolBufferException { + return any.unpack(UnDelegateResourceContract.class).getOwnerAddress(); + } + + @Override + public long calcFee() { + return 0; + } + +} diff --git a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java index 7c7a37fa609..2ff6495b2cf 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java @@ -98,6 +98,15 @@ public byte[] createDbKey() { return getAccount().toByteArray(); } + public static byte[] createDbKeyV2(byte[] account) { + byte[] v2Prefix = "v2_".getBytes(); + byte[] key = new byte[v2Prefix.length + account.length]; + System.arraycopy(v2Prefix, 0, key, 0, v2Prefix.length); + System.arraycopy(account, 0, key, v2Prefix.length, account.length); + return key; + } + + public String createReadableString() { return ByteArray.toHexString(getAccount().toByteArray()); } diff --git a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java index 0eb6dc8ec09..b33e47a2406 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java @@ -37,6 +37,15 @@ public static byte[] createDbKey(byte[] from, byte[] to) { return key; } + public static byte[] createDbKeyV2(byte[] from, byte[] to) { + byte[] v2Prefix = "v2_".getBytes(); + byte[] key = new byte[v2Prefix.length + from.length + to.length]; + System.arraycopy(v2Prefix, 0, key, 0, v2Prefix.length); + System.arraycopy(from, 0, key, v2Prefix.length, from.length); + System.arraycopy(to, 0, key, v2Prefix.length+from.length, to.length); + return key; + } + public ByteString getFrom() { return this.delegatedResource.getFrom(); } diff --git a/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java similarity index 100% rename from framework/src/main/java/org/tron/core/db/BandwidthProcessor.java rename to chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java diff --git a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java new file mode 100644 index 00000000000..ebe491454e4 --- /dev/null +++ b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java @@ -0,0 +1,485 @@ +package org.tron.core.actuator; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import java.io.File; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; +import org.tron.core.capsule.DelegatedResourceCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.protos.Protocol.AccountType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.AssetIssueContractOuterClass; +import org.tron.protos.contract.BalanceContract.DelegateResourceContract; +import org.tron.protos.contract.Common.ResourceCode; + +@Slf4j +public class DelegateResourceActuatorTest { + + private static final String dbPath = "output_delegate_resource_test"; + private static final String OWNER_ADDRESS; + private static final String RECEIVER_ADDRESS; + private static final String OWNER_ADDRESS_INVALID = "aaaa"; + private static final String OWNER_ACCOUNT_INVALID; + private static final long initBalance = 10_000_000_000L; + private static Manager dbManager; + private static TronApplicationContext context; + + static { + Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; + OWNER_ACCOUNT_INVALID = + Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; + } + + /** + * Init data. + */ + @BeforeClass + public static void init() { + dbManager = context.getBean(Manager.class); + } + + /** + * Release resources. + */ + @AfterClass + public static void destroy() { + Args.clearParam(); + context.destroy(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.info("Release resources failure."); + } + } + + /** + * create temp Capsule test need. + */ + @Before + public void createAccountCapsule() { + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + AccountCapsule ownerCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(owner), + AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + + AccountCapsule receiverCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(receiver), + AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); + + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + + // clear delegate + dbManager.getDelegatedResourceStore().delete(DelegatedResourceCapsule.createDbKeyV2( + owner, receiver)); + dbManager.getDelegatedResourceAccountIndexStore().delete( + DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner)); + dbManager.getDelegatedResourceAccountIndexStore().delete( + DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver)); + } + + public void freezeBandwidthForOwner() { + AccountCapsule ownerCapsule = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + ownerCapsule.addFrozenBalanceForBandwidthV2(initBalance); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + } + + public void freezeCpuForOwner() { + AccountCapsule ownerCapsule = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + ownerCapsule.addFrozenBalanceForEnergyV2(initBalance); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + } + + private Any getDelegateContractForBandwidth( + String ownerAddress, String receiveAddress, long unfreezeBalance) { + return Any.pack( + DelegateResourceContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiveAddress))) + .setBalance(unfreezeBalance) + .setResource(ResourceCode.BANDWIDTH) + .build()); + } + + private Any getDelegateContractForCpu( + String ownerAddress, String receiveAddress, long unfreezeBalance) { + return Any.pack( + DelegateResourceContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiveAddress))) + .setBalance(unfreezeBalance) + .setResource(ResourceCode.ENERGY) + .build()); + } + + private Any getDelegateContractForTronPower( + String ownerAddress, String receiveAddress, long unfreezeBalance) { + return Any.pack( + DelegateResourceContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiveAddress))) + .setBalance(unfreezeBalance) + .setResource(ResourceCode.TRON_POWER) + .build()); + } + + @Test + public void testDelegateResourceWithNoFreeze() { + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForBandwidth( + OWNER_ADDRESS, + RECEIVER_ADDRESS, + 1_000_000_000L)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertEquals("delegateBalance must be less than accountFreezeBandwidthBalance", + e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(); + } + + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, 1_000_000_000L)); + try { + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertEquals("delegateBalance must be less than accountFreezeEnergyBalance", + e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testDelegateResourceWithContractAddress() { + freezeBandwidthForOwner(); + AccountCapsule receiverCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), + AccountType.Contract, + initBalance); + dbManager.getAccountStore().put(ByteArray.fromHexString(RECEIVER_ADDRESS), receiverCapsule); + + + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, 1_000_000_000L)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertEquals("Do not allow delegate resources to contract addresses", e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testDelegateResourceToSelf() { + freezeBandwidthForOwner(); + + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForBandwidth(OWNER_ADDRESS, OWNER_ADDRESS, 1_000_000_000L)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertEquals("receiverAddress must not be the same as ownerAddress", e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testDelegateResourceForBandwidth() { + freezeBandwidthForOwner(); + long delegateBalance = 1_000_000_000L; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + long totalNetWeightBefore = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule ownerCapsule = + dbManager.getAccountStore().get(owner); + + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(initBalance - delegateBalance, + ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(initBalance, ownerCapsule.getTronPower()); + + AccountCapsule receiverCapsule = + dbManager.getAccountStore().get(receiver); + Assert.assertEquals(delegateBalance, + receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0L, receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0L, receiverCapsule.getTronPower()); + + DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule + .createDbKeyV2(ByteArray.fromHexString(OWNER_ADDRESS), + ByteArray.fromHexString(RECEIVER_ADDRESS))); + + Assert.assertEquals(delegateBalance, delegatedResourceCapsule.getFrozenBalanceForBandwidth()); + long totalNetWeightAfter = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); + Assert.assertEquals(totalNetWeightBefore, totalNetWeightAfter); + + //check DelegatedResourceAccountIndex + byte[] key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); + Assert.assertTrue(ownerIndexCapsule.getToAccountsList() + .contains(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)))); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiveCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, receiveCapsule.getToAccountsList().size()); + Assert.assertEquals(1, receiveCapsule.getFromAccountsList().size()); + Assert.assertTrue(receiveCapsule.getFromAccountsList() + .contains(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)))); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testDelegateResourceForCpu() { + freezeCpuForOwner(); + long delegateBalance = 1_000_000_000L; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + long totalEnergyWeightBefore = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); + AccountCapsule ownerCapsule = + dbManager.getAccountStore().get(owner); + + Assert.assertEquals(initBalance, ownerCapsule.getBalance()); + Assert.assertEquals(0L, ownerCapsule.getFrozenBalance()); + Assert.assertEquals(0L, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(initBalance, ownerCapsule.getTronPower()); + + AccountCapsule receiverCapsule = + dbManager.getAccountStore().get(receiver); + Assert.assertEquals(0L, receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, + receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0L, receiverCapsule.getTronPower()); + + DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule.createDbKeyV2(owner, receiver)); + + Assert.assertEquals(0L, delegatedResourceCapsule.getFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, delegatedResourceCapsule.getFrozenBalanceForEnergy()); + + long totalEnergyWeightAfter = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); + Assert.assertEquals(totalEnergyWeightBefore, totalEnergyWeightAfter); + + //check DelegatedResourceAccountIndex + byte[] key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert + .assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); + Assert.assertTrue(ownerIndexCapsule.getToAccountsList() + .contains(ByteString.copyFrom(receiver))); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert + .assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + Assert + .assertEquals(1, + receiverIndexCapsule.getFromAccountsList().size()); + Assert.assertTrue(receiverIndexCapsule.getFromAccountsList() + .contains(ByteString.copyFrom(owner))); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void delegateLessThanZero() { + long delegateBalance = -1_000_000_000L; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegateContractForBandwidth( + OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertEquals("delegateBalance must be more than 1TRX", e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void delegateTronPower() { + long delegateBalance = 1_000_000_000L; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegateContractForTronPower( + OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertEquals("ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]", + e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + + @Test + public void delegateMoreThanBalance() { + long delegateBalance = 11_000_000_000L; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegateContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertEquals("delegateBalance must be less than accountFreezeBandwidthBalance", + e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void invalidOwnerAddress() { + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegateContractForBandwidth( + OWNER_ADDRESS_INVALID, RECEIVER_ADDRESS, 1_000_000_000L)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.fail("cannot run here."); + + } catch (ContractValidateException e) { + Assert.assertEquals("Invalid address", e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void invalidOwnerAccount() { + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegateContractForBandwidth( + OWNER_ACCOUNT_INVALID, RECEIVER_ADDRESS, 1_000_000_000L)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertEquals("Account[" + OWNER_ACCOUNT_INVALID + "] not exists", + e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void commonErrorCheck() { + freezeBandwidthForOwner(); + DelegateResourceActuator actuator = new DelegateResourceActuator(); + ActuatorTest actuatorTest = new ActuatorTest(actuator, dbManager); + actuatorTest.noContract(); + + Any invalidContractTypes = Any.pack(AssetIssueContractOuterClass.AssetIssueContract.newBuilder() + .build()); + actuatorTest.setInvalidContract(invalidContractTypes); + actuatorTest.setInvalidContractTypeMsg("contract type error", + "contract type error,expected type [DelegateResourceContract],real type["); + actuatorTest.invalidContractType(); + + actuatorTest.setContract( + getDelegateContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, 1_000_000_000L)); + actuatorTest.nullTransationResult(); + + actuatorTest.setNullDBManagerMsg("No account store or dynamic store!"); + actuatorTest.nullDBManger(); + } +} diff --git a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java new file mode 100644 index 00000000000..0abe5df3356 --- /dev/null +++ b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java @@ -0,0 +1,836 @@ +package org.tron.core.actuator; + +import static junit.framework.TestCase.fail; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import java.io.File; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; +import org.tron.core.capsule.DelegatedResourceCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.protos.Protocol.AccountType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.AssetIssueContractOuterClass; +import org.tron.protos.contract.BalanceContract.UnDelegateResourceContract; +import org.tron.protos.contract.Common.ResourceCode; + +@Slf4j +public class UnDelegateResourceActuatorTest { + + private static final String dbPath = "output_undelegate_resource_test"; + private static final String OWNER_ADDRESS; + private static final String RECEIVER_ADDRESS; + private static final String OWNER_ADDRESS_INVALID = "aaaa"; + private static final String OWNER_ACCOUNT_INVALID; + private static final long initBalance = 10_000_000_000L; + private static final long delegateBalance = 1_000_000_000L; + private static Manager dbManager; + private static TronApplicationContext context; + + static { + Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; + OWNER_ACCOUNT_INVALID = + Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; + } + + /** + * Init data. + */ + @BeforeClass + public static void init() { + dbManager = context.getBean(Manager.class); + } + + /** + * Release resources. + */ + @AfterClass + public static void destroy() { + Args.clearParam(); + context.destroy(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.info("Release resources failure."); + } + } + + /** + * create temp Capsule test need. + */ + @Before + public void createAccountCapsule() { + AccountCapsule ownerCapsule = new AccountCapsule(ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); + + AccountCapsule receiverCapsule = new AccountCapsule(ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); + + // clear delegate + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + dbManager.getDelegatedResourceStore().delete(DelegatedResourceCapsule.createDbKeyV2( + owner, receiver)); + dbManager.getDelegatedResourceAccountIndexStore().delete( + DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner)); + dbManager.getDelegatedResourceAccountIndexStore().delete( + DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver)); + + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + } + + public void delegateBandwidthForOwner() { + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + ownerCapsule.addDelegatedFrozenBalanceForBandwidth(delegateBalance); + dbManager.getAccountStore().put(owner, ownerCapsule); + AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); + receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(delegateBalance); + dbManager.getAccountStore().put(receiver, receiverCapsule); + dbManager.getDynamicPropertiesStore().addTotalNetWeight(delegateBalance / TRX_PRECISION); + + DelegatedResourceCapsule delegatedResourceCapsule = new DelegatedResourceCapsule( + ByteString.copyFrom(owner), + ByteString.copyFrom(receiver)); + delegatedResourceCapsule.setFrozenBalanceForBandwidth(delegateBalance, 0); + dbManager.getDelegatedResourceStore().put( + DelegatedResourceCapsule.createDbKeyV2(owner, receiver), delegatedResourceCapsule); + + + byte[] ownerKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = + new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(owner)); + + List toAccountsList = delegatedResourceAccountIndexCapsule.getToAccountsList(); + if (!toAccountsList.contains(ByteString.copyFrom(receiver))) { + delegatedResourceAccountIndexCapsule.addToAccount(ByteString.copyFrom(receiver)); + } + dbManager.getDelegatedResourceAccountIndexStore() + .put(ownerKey, delegatedResourceAccountIndexCapsule); + + + byte[] receiverKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + delegatedResourceAccountIndexCapsule = new DelegatedResourceAccountIndexCapsule( + ByteString.copyFrom(receiver)); + + List fromAccountsList = delegatedResourceAccountIndexCapsule + .getFromAccountsList(); + if (!fromAccountsList.contains(ByteString.copyFrom(owner))) { + delegatedResourceAccountIndexCapsule.addFromAccount(ByteString.copyFrom(owner)); + } + dbManager.getDelegatedResourceAccountIndexStore() + .put(receiverKey, delegatedResourceAccountIndexCapsule); + } + + public void delegateCpuForOwner() { + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + ownerCapsule.addDelegatedFrozenBalanceForEnergy(delegateBalance); + dbManager.getAccountStore().put(owner, ownerCapsule); + AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); + receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(delegateBalance); + dbManager.getAccountStore().put(receiver, receiverCapsule); + dbManager.getDynamicPropertiesStore().addTotalEnergyWeight(delegateBalance / TRX_PRECISION); + + DelegatedResourceCapsule delegatedResourceCapsule = new DelegatedResourceCapsule( + ByteString.copyFrom(owner), + ByteString.copyFrom(receiver)); + delegatedResourceCapsule.setFrozenBalanceForEnergy(delegateBalance, 0); + dbManager.getDelegatedResourceStore().put( + DelegatedResourceCapsule.createDbKeyV2(owner, receiver), delegatedResourceCapsule); + + + byte[] ownerKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = + new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(owner)); + + List toAccountsList = delegatedResourceAccountIndexCapsule.getToAccountsList(); + if (!toAccountsList.contains(ByteString.copyFrom(receiver))) { + delegatedResourceAccountIndexCapsule.addToAccount(ByteString.copyFrom(receiver)); + } + dbManager.getDelegatedResourceAccountIndexStore() + .put(ownerKey, delegatedResourceAccountIndexCapsule); + + + byte[] receiverKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + delegatedResourceAccountIndexCapsule = new DelegatedResourceAccountIndexCapsule( + ByteString.copyFrom(receiver)); + + List fromAccountsList = delegatedResourceAccountIndexCapsule + .getFromAccountsList(); + if (!fromAccountsList.contains(ByteString.copyFrom(owner))) { + delegatedResourceAccountIndexCapsule.addFromAccount(ByteString.copyFrom(owner)); + } + dbManager.getDelegatedResourceAccountIndexStore() + .put(receiverKey, delegatedResourceAccountIndexCapsule); + } + + private Any getDelegatedContractForBandwidth( + String ownerAddress, String receiverAddress, long balance) { + return Any.pack(UnDelegateResourceContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiverAddress))) + .setBalance(balance).build()); + } + + private Any getDelegatedContractForCpu( + String ownerAddress, String receiverAddress, long balance) { + return Any.pack(UnDelegateResourceContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiverAddress))) + .setResource(ResourceCode.ENERGY) + .setBalance(balance).build()); + } + + // test start + @Test + public void testUnDelegateForBandwidth() { + delegateBandwidthForOwner(); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); + receiverCapsule.setNetUsage(1_000_000_000); + receiverCapsule.setLatestConsumeTime(dbManager.getChainBaseManager().getHeadSlot()); + dbManager.getAccountStore().put(receiver, receiverCapsule); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(delegateBalance, + receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); + Assert.assertEquals(0, ownerCapsule.getNetUsage()); + Assert.assertEquals(1_000_000_000, receiverCapsule.getNetUsage()); + + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + + // check owner + ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(1000000000, ownerCapsule.getNetUsage()); + Assert.assertEquals(dbManager.getChainBaseManager().getHeadSlot(), + ownerCapsule.getLatestConsumeTime()); + + // check receiver + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0, receiverCapsule.getNetUsage()); + + //check DelegatedResource + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + DelegatedResourceCapsule delegatedCapsule = dbManager.getDelegatedResourceStore().get(key); + Assert.assertNull(delegatedCapsule); + + //check DelegatedResourceAccountIndex + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(0, ownerIndexCapsule.getToAccountsList().size()); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + Assert.assertEquals(0, receiverIndexCapsule.getFromAccountsList().size()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testPartialUnDelegateForBandwidth() { + delegateBandwidthForOwner(); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); + receiverCapsule.setNetUsage(1_000_000_000); + receiverCapsule.setLatestConsumeTime(dbManager.getChainBaseManager().getHeadSlot()); + dbManager.getAccountStore().put(receiver, receiverCapsule); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance / 2)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(delegateBalance, + receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); + Assert.assertEquals(0, ownerCapsule.getNetUsage()); + Assert.assertEquals(1_000_000_000, receiverCapsule.getNetUsage()); + + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + + // check owner + ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(delegateBalance / 2, + ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance / 2, + ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(1000000000 / 2, ownerCapsule.getNetUsage()); + Assert.assertEquals(dbManager.getChainBaseManager().getHeadSlot(), + ownerCapsule.getLatestConsumeTime()); + + // check receiver + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(delegateBalance / 2, + receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(1000000000 / 2, receiverCapsule.getNetUsage()); + + //check DelegatedResource + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + DelegatedResourceCapsule delegatedResourceCapsule = + dbManager.getDelegatedResourceStore().get(key); + Assert.assertEquals(delegateBalance / 2, + delegatedResourceCapsule.getFrozenBalanceForBandwidth()); + + //check DelegatedResourceAccountIndex + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + Assert.assertEquals(1, receiverIndexCapsule.getFromAccountsList().size()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testUnDelegatedForBandwidthWithDeletedReceiver() { + delegateBandwidthForOwner(); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + dbManager.getAccountStore().delete(receiver); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + + // check owner + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(0, ownerCapsule.getNetUsage()); + + // check receiver + Assert.assertNull(dbManager.getAccountStore().get(receiver)); + + //check DelegatedResource + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + DelegatedResourceCapsule delegatedResourceCapsule = + dbManager.getDelegatedResourceStore().get(key); + Assert.assertNull(delegatedResourceCapsule); + + //check DelegatedResourceAccountIndex + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(0, ownerIndexCapsule.getToAccountsList().size()); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + Assert.assertEquals(0, receiverIndexCapsule.getFromAccountsList().size()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + + } + + @Test + public void testUnDelegatedForBandwidthWithRecreatedReceiver() { + delegateBandwidthForOwner(); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + dbManager.getAccountStore().delete(receiver); + + AccountCapsule receiverCapsule = new AccountCapsule(ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), AccountType.Normal, + initBalance); + receiverCapsule.setAcquiredDelegatedFrozenBalanceForBandwidth(10L); + dbManager.getAccountStore().put(receiver, receiverCapsule); + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(10, receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + + // check owner + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(0, ownerCapsule.getNetUsage()); + + // check receiver + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + + //check DelegatedResource + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + DelegatedResourceCapsule delegatedCapsule = dbManager.getDelegatedResourceStore().get(key); + Assert.assertNull(delegatedCapsule); + + //check DelegatedResourceAccountIndex + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(0, ownerIndexCapsule.getToAccountsList().size()); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + Assert.assertEquals(0, receiverIndexCapsule.getFromAccountsList().size()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + + } + + @Test + public void testUnDelegatedForCpu() { + delegateCpuForOwner(); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); + receiverCapsule.setEnergyUsage(1_000_000_000); + receiverCapsule.setLatestConsumeTimeForEnergy(dbManager.getChainBaseManager().getHeadSlot()); + dbManager.getAccountStore().put(receiver, receiverCapsule); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(delegateBalance, + receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForEnergy()); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); + Assert.assertEquals(0, ownerCapsule.getEnergyUsage()); + Assert.assertEquals(1_000_000_000, receiverCapsule.getEnergyUsage()); + + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + + // check owner + ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForEnergy()); + Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(1_000_000_000, ownerCapsule.getEnergyUsage()); + Assert.assertEquals(dbManager.getChainBaseManager().getHeadSlot(), + ownerCapsule.getLatestConsumeTimeForEnergy()); + + // check receiver + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0, receiverCapsule.getEnergyUsage()); + + //check DelegatedResource + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + DelegatedResourceCapsule delegatedCapsule = dbManager.getDelegatedResourceStore().get(key); + Assert.assertNull(delegatedCapsule); + + //check DelegatedResourceAccountIndex + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(0, ownerIndexCapsule.getToAccountsList().size()); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + Assert.assertEquals(0, receiverIndexCapsule.getFromAccountsList().size()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testPartialUnDelegatedForCpu() { + delegateCpuForOwner(); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); + receiverCapsule.setEnergyUsage(1_000_000_000); + receiverCapsule.setLatestConsumeTimeForEnergy(dbManager.getChainBaseManager().getHeadSlot()); + dbManager.getAccountStore().put(receiver, receiverCapsule); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance / 2)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(delegateBalance, + receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForEnergy()); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); + Assert.assertEquals(0, ownerCapsule.getEnergyUsage()); + Assert.assertEquals(1_000_000_000, receiverCapsule.getEnergyUsage()); + + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + + // check owner + ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(delegateBalance / 2, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(delegateBalance / 2, ownerCapsule.getFrozenV2BalanceForEnergy()); + Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(1_000_000_000 / 2, ownerCapsule.getEnergyUsage()); + Assert.assertEquals(dbManager.getChainBaseManager().getHeadSlot(), + ownerCapsule.getLatestConsumeTimeForEnergy()); + + // check receiver + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(delegateBalance / 2, + receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(1_000_000_000 / 2, receiverCapsule.getEnergyUsage()); + + //check DelegatedResource + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + DelegatedResourceCapsule delegatedCapsule = dbManager.getDelegatedResourceStore().get(key); + Assert.assertEquals(delegateBalance / 2, + delegatedCapsule.getFrozenBalanceForEnergy()); + + //check DelegatedResourceAccountIndex + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + Assert.assertEquals(1, receiverIndexCapsule.getFromAccountsList().size()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testUnDelegatedForCpuWithDeletedReceiver() { + delegateCpuForOwner(); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + dbManager.getAccountStore().delete(receiver); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + + // check owner + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForEnergy()); + Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(0, ownerCapsule.getEnergyUsage()); + + // check receiver + Assert.assertNull(dbManager.getAccountStore().get(receiver)); + + //check DelegatedResource + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + DelegatedResourceCapsule delegatedCapsule = dbManager.getDelegatedResourceStore().get(key); + Assert.assertNull(delegatedCapsule); + + //check DelegatedResourceAccountIndex + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(0, ownerIndexCapsule.getToAccountsList().size()); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + Assert.assertEquals(0, receiverIndexCapsule.getFromAccountsList().size()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + + } + + @Test + public void testUnDelegatedForCpuWithRecreatedReceiver() { + delegateCpuForOwner(); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + dbManager.getAccountStore().delete(receiver); + + AccountCapsule receiverCapsule = new AccountCapsule(ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), AccountType.Normal, + initBalance); + receiverCapsule.setAcquiredDelegatedFrozenBalanceForEnergy(10L); + dbManager.getAccountStore().put(receiver, receiverCapsule); + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(10, receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + + // check owner + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForEnergy()); + Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(0, ownerCapsule.getEnergyUsage()); + + // check receiver + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + + //check DelegatedResource + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + DelegatedResourceCapsule delegatedResourceCapsule = + dbManager.getDelegatedResourceStore().get(key); + Assert.assertNull(delegatedResourceCapsule); + + //check DelegatedResourceAccountIndex + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(0, ownerIndexCapsule.getToAccountsList().size()); + + key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(key); + Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + Assert.assertEquals(0, receiverIndexCapsule.getFromAccountsList().size()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + + } + + @Test + public void invalidOwnerAddress() { + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForBandwidth( + OWNER_ADDRESS_INVALID, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + + } catch (ContractValidateException e) { + Assert.assertEquals("Invalid address", e.getMessage()); + + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + + } + + @Test + public void invalidOwnerAccount() { + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegatedContractForBandwidth(OWNER_ACCOUNT_INVALID, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertEquals("Account[" + OWNER_ACCOUNT_INVALID + "] does not exist", + e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void noDelegateBalance() { + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertEquals("delegated Resource does not exist", e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + try { + actuator.validate(); + actuator.execute(ret); + Assert.fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertEquals("delegated Resource does not exist", e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void commonErrorCheck() { + delegateBandwidthForOwner(); + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + ActuatorTest actuatorTest = new ActuatorTest(actuator, dbManager); + actuatorTest.noContract(); + + Any invalidContractTypes = Any.pack(AssetIssueContractOuterClass.AssetIssueContract.newBuilder() + .build()); + actuatorTest.setInvalidContract(invalidContractTypes); + actuatorTest.setInvalidContractTypeMsg("contract type error", + "contract type error, expected type [UnDelegateResourceContract], real type["); + actuatorTest.invalidContractType(); + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + Assert.assertEquals(0, accountCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(delegateBalance, accountCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, accountCapsule.getTronPower()); + + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + + actuatorTest.setContract(getDelegatedContractForBandwidth( + OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + actuatorTest.nullTransationResult(); + + actuatorTest.setNullDBManagerMsg("No account store or dynamic store!"); + actuatorTest.nullDBManger(); + } +} + From 0a1be1b27902de45b6bbfa5e22e752b2a3c3f60c Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Thu, 22 Sep 2022 16:04:29 +0800 Subject: [PATCH 0330/1197] feat(freezeV2): add freezeV2 contract api --- .../tron/core/consensus/ProposalService.java | 17 +++++++-- .../org/tron/core/services/RpcApiService.java | 16 ++++++++ .../http/DelegateResourceServlet.java | 36 ++++++++++++++++++ .../services/http/FullNodeHttpApiService.java | 17 +++++++++ .../http/UnDelegateResourceServlet.java | 38 +++++++++++++++++++ protocol/src/main/protos/api/api.proto | 6 +++ 6 files changed, 127 insertions(+), 3 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/services/http/DelegateResourceServlet.java create mode 100644 framework/src/main/java/org/tron/core/services/http/UnDelegateResourceServlet.java diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 3bb2abddc38..661a1b6eaa5 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -5,7 +5,9 @@ import org.tron.core.capsule.ProposalCapsule; import org.tron.core.config.Parameter.ForkBlockVersionEnum; import org.tron.core.db.Manager; +import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.utils.ProposalUtil; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; /** * Notice: @@ -290,9 +292,18 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) } case UNFREEZE_DELAY_DAYS: { - manager.getDynamicPropertiesStore().saveUnfreezeDelayDays(entry.getValue()); - manager.getDynamicPropertiesStore().addSystemContractAndSetPermission(54); - manager.getDynamicPropertiesStore().addSystemContractAndSetPermission(55); + DynamicPropertiesStore dynamicStore = manager.getDynamicPropertiesStore(); + dynamicStore.saveUnfreezeDelayDays(entry.getValue()); + dynamicStore.addSystemContractAndSetPermission( + ContractType.FreezeBalanceV2Contract_VALUE); + dynamicStore.addSystemContractAndSetPermission( + ContractType.UnfreezeBalanceV2Contract_VALUE); + dynamicStore.addSystemContractAndSetPermission( + ContractType.WithdrawExpireUnfreezeContract_VALUE); + dynamicStore.addSystemContractAndSetPermission( + ContractType.DelegateResourceContract_VALUE); + dynamicStore.addSystemContractAndSetPermission( + ContractType.UnDelegateResourceContract_VALUE); break; } default: diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index c3528237b98..c535950cffa 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -146,8 +146,10 @@ import org.tron.protos.contract.BalanceContract.AccountBalanceRequest; import org.tron.protos.contract.BalanceContract.AccountBalanceResponse; import org.tron.protos.contract.BalanceContract.BlockBalanceTrace; +import org.tron.protos.contract.BalanceContract.DelegateResourceContract; import org.tron.protos.contract.BalanceContract.FreezeBalanceContract; import org.tron.protos.contract.BalanceContract.TransferContract; +import org.tron.protos.contract.BalanceContract.UnDelegateResourceContract; import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; import org.tron.protos.contract.BalanceContract.WithdrawBalanceContract; import org.tron.protos.contract.BalanceContract.WithdrawExpireUnfreezeContract; @@ -1543,6 +1545,20 @@ public void withdrawExpireUnfreeze(WithdrawExpireUnfreezeContract request, responseObserver); } + @Override + public void delegateResource(DelegateResourceContract request, + StreamObserver responseObserver) { + createTransactionExtention(request, ContractType.DelegateResourceContract, + responseObserver); + } + + @Override + public void unDelegateResource(UnDelegateResourceContract request, + StreamObserver responseObserver) { + createTransactionExtention(request, ContractType.UnDelegateResourceContract, + responseObserver); + } + @Override public void proposalCreate(ProposalCreateContract request, StreamObserver responseObserver) { diff --git a/framework/src/main/java/org/tron/core/services/http/DelegateResourceServlet.java b/framework/src/main/java/org/tron/core/services/http/DelegateResourceServlet.java new file mode 100644 index 00000000000..221cc34cf7c --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/DelegateResourceServlet.java @@ -0,0 +1,36 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.contract.BalanceContract.DelegateResourceContract; + +@Component +@Slf4j(topic = "API") +public class DelegateResourceServlet extends RateLimiterServlet { + + @Autowired + private Wallet wallet; + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + PostParams params = PostParams.getPostParams(request); + DelegateResourceContract.Builder build = DelegateResourceContract.newBuilder(); + JsonFormat.merge(params.getParams(), build, params.isVisible()); + Transaction tx = wallet + .createTransactionCapsule(build.build(), ContractType.DelegateResourceContract) + .getInstance(); + JSONObject jsonObject = JSONObject.parseObject(params.getParams()); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, params.isVisible())); + } catch (Exception e) { + Util.processError(e, response); + } + } +} diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index 26a5256fcc2..43a0d87661b 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -293,8 +293,17 @@ public class FullNodeHttpApiService implements Service { private GetBandwidthPricesServlet getBandwidthPricesServlet; @Autowired private GetBlockServlet getBlockServlet; + + @Autowired + private FreezeBalanceV2Servlet freezeBalanceV2Servlet; + @Autowired + private UnFreezeBalanceV2Servlet unFreezeBalanceV2Servlet; @Autowired private WithdrawExpireUnfreezeServlet withdrawExpireUnfreezeServlet; + @Autowired + private DelegateResourceServlet delegateResourceServlet; + @Autowired + private UnDelegateResourceServlet unDelegateResourceServlet; private static String getParamsFile(String fileName) { InputStream in = Thread.currentThread().getContextClassLoader() @@ -545,8 +554,16 @@ public void start() { "/wallet/getbandwidthprices"); context.addServlet(new ServletHolder(getBlockServlet), "/wallet/getblock"); + context.addServlet(new ServletHolder(freezeBalanceV2Servlet), + "/wallet/freezebalancev2"); + context.addServlet(new ServletHolder(unFreezeBalanceV2Servlet), + "/wallet/unfreezebalancev2"); context.addServlet(new ServletHolder(withdrawExpireUnfreezeServlet), "/wallet/withdrawExpireUnfreeze"); + context.addServlet(new ServletHolder(delegateResourceServlet), + "/wallet/delegateresource"); + context.addServlet(new ServletHolder(unDelegateResourceServlet), + "/wallet/undelegateresource"); int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { diff --git a/framework/src/main/java/org/tron/core/services/http/UnDelegateResourceServlet.java b/framework/src/main/java/org/tron/core/services/http/UnDelegateResourceServlet.java new file mode 100644 index 00000000000..cf9c2c95dcd --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/UnDelegateResourceServlet.java @@ -0,0 +1,38 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.contract.BalanceContract.UnDelegateResourceContract; + +@Component +@Slf4j(topic = "API") +public class UnDelegateResourceServlet extends RateLimiterServlet { + @Autowired + private Wallet wallet; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + PostParams params = PostParams.getPostParams(request); + UnDelegateResourceContract.Builder build = UnDelegateResourceContract.newBuilder(); + JsonFormat.merge(params.getParams(), build, params.isVisible()); + Transaction tx = wallet + .createTransactionCapsule(build.build(), ContractType.UnDelegateResourceContract) + .getInstance(); + JSONObject jsonObject = JSONObject.parseObject(params.getParams()); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, params.isVisible())); + } catch (Exception e) { + Util.processError(e, response); + } + } +} \ No newline at end of file diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index b3ce3d56e51..037f137c79e 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -275,6 +275,12 @@ service Wallet { rpc WithdrawExpireUnfreeze (WithdrawExpireUnfreezeContract) returns (TransactionExtention) { } + rpc DelegateResource (DelegateResourceContract) returns (TransactionExtention) { + } + + rpc UnDelegateResource (UnDelegateResourceContract) returns (TransactionExtention) { + } + //Please use UpdateAsset2 instead of this function. rpc UpdateAsset (UpdateAssetContract) returns (Transaction) { option (google.api.http) = { From ecf6d2505ba38a5c29371a92ccdd250619429e9a Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Thu, 22 Sep 2022 17:44:28 +0800 Subject: [PATCH 0331/1197] fix(freezeV2): fix resource usage bug --- .../actuator/DelegateResourceActuator.java | 32 ++++---- .../actuator/UnDelegateResourceActuator.java | 55 +++++++------- .../WithdrawExpireUnfreezeActuator.java | 39 ++++------ .../DelegateResourceActuatorTest.java | 75 ++++++++++++++++++- .../UnDelegateResourceActuatorTest.java | 28 ++++--- .../WithdrawExpireUnfreezeActuatorTest.java | 47 ------------ 6 files changed, 152 insertions(+), 124 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 156581342ad..152c4fb2a7a 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -57,12 +57,6 @@ public boolean execute(Object result) throws ContractExeException { AccountCapsule ownerCapsule = accountStore .get(delegateResourceContract.getOwnerAddress().toByteArray()); - // TODO remove - // if (dynamicStore.supportAllowNewResourceModel() - // && accountCapsule.oldTronPowerIsNotInitialized()) { - // accountCapsule.initializeOldTronPower(); - // } - long delegateBalance = delegateResourceContract.getBalance(); byte[] ownerAddress = delegateResourceContract.getOwnerAddress().toByteArray(); byte[] receiverAddress = delegateResourceContract.getReceiverAddress().toByteArray(); @@ -143,20 +137,30 @@ public boolean validate() throws ContractValidateException { case BANDWIDTH: { BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); processor.updateUsage(ownerCapsule); - long netBalanceUsage = (long) (ownerCapsule.getNetUsage() - * ((double) (dynamicStore.getTotalNetLimit()) / dynamicStore.getTotalNetWeight())); - if (ownerCapsule.getFrozenV2BalanceForBandwidth() - netBalanceUsage < delegateBalance) { - throw new ContractValidateException("delegateBalance must be less than accountFreezeBandwidthBalance"); + + //The unit is trx + long netTrxUsage = (long) (ownerCapsule.getNetUsage() + * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); + + if (ownerCapsule.getFrozenV2BalanceForBandwidth() - netTrxUsage * TRX_PRECISION + < delegateBalance) { + throw new ContractValidateException( + "delegateBalance must be less than available FreezeBandwidthV2 balance"); } } break; case ENERGY: { EnergyProcessor processor = new EnergyProcessor(dynamicStore, accountStore); processor.updateUsage(ownerCapsule); - long energyBalanceUsage = (long) (ownerCapsule.getEnergyUsage() - * ((double) (dynamicStore.getTotalEnergyCurrentLimit()) / dynamicStore.getTotalEnergyWeight())); - if (ownerCapsule.getFrozenV2BalanceForEnergy() - energyBalanceUsage < delegateBalance) { - throw new ContractValidateException("delegateBalance must be less than accountFreezeEnergyBalance"); + + //The unit is trx + long energyTrxUsage = (long) (ownerCapsule.getEnergyUsage() + * ((double) (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); + + if (ownerCapsule.getFrozenV2BalanceForEnergy() - energyTrxUsage * TRX_PRECISION + < delegateBalance) { + throw new ContractValidateException( + "delegateBalance must be less than available FreezeEnergyV2Balance balance"); } } break; diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index 4140f9cfb73..f18083f77d2 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -76,16 +76,14 @@ public boolean execute(Object result) throws ContractExeException { if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() < unDelegateBalance) { // A TVM contract suicide, re-create will produce this situation - transferUsage = receiverCapsule.getNetUsage(); - receiverCapsule.setAcquiredDelegatedFrozenBalanceForBandwidth(0); } else { // calculate usage - long unDelegateBandwidth = (long) (unDelegateBalance / TRX_PRECISION + long unDelegateMaxUsage = (long) (unDelegateBalance / TRX_PRECISION * ((double) (dynamicStore.getTotalNetLimit()) / dynamicStore.getTotalNetWeight())); transferUsage = (long) (receiverCapsule.getNetUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForBandwidth())); - transferUsage = Math.min(unDelegateBandwidth, transferUsage); + transferUsage = Math.min(unDelegateMaxUsage, transferUsage); receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(-unDelegateBalance); } @@ -100,14 +98,14 @@ public boolean execute(Object result) throws ContractExeException { if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() < unDelegateBalance) { // A TVM contract receiver, re-create will produce this situation - transferUsage = receiverCapsule.getEnergyUsage(); receiverCapsule.setAcquiredDelegatedFrozenBalanceForEnergy(0); } else { - long unDelegateEnergy = (long) (unDelegateBalance / TRX_PRECISION + // calculate usage + long unDelegateMaxUsage = (long) (unDelegateBalance / TRX_PRECISION * ((double) (dynamicStore.getTotalEnergyCurrentLimit()) / dynamicStore.getTotalEnergyWeight())); transferUsage = (long) (receiverCapsule.getEnergyUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForEnergy())); - transferUsage = Math.min(unDelegateEnergy, transferUsage); + transferUsage = Math.min(unDelegateMaxUsage, transferUsage); receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(-unDelegateBalance); } @@ -123,7 +121,7 @@ public boolean execute(Object result) throws ContractExeException { } // modify owner Account - AccountCapsule accountCapsule = accountStore.get(ownerAddress); + AccountCapsule ownerCapsule = accountStore.get(ownerAddress); byte[] key = DelegatedResourceCapsule .createDbKeyV2(unDelegateResourceContract.getOwnerAddress().toByteArray(), unDelegateResourceContract.getReceiverAddress().toByteArray()); @@ -131,25 +129,29 @@ public boolean execute(Object result) throws ContractExeException { .get(key); switch (unDelegateResourceContract.getResource()) { case BANDWIDTH: { - long delegateBalance = delegatedResourceCapsule.getFrozenBalanceForBandwidth(); - delegatedResourceCapsule.setFrozenBalanceForBandwidth(delegateBalance - unDelegateBalance, 0); - accountCapsule.addDelegatedFrozenBalanceForBandwidth(-unDelegateBalance); - accountCapsule.addFrozenBalanceForBandwidthV2(unDelegateBalance); - - long newNetUsage = accountCapsule.getNetUsage() + transferUsage; - accountCapsule.setNetUsage(newNetUsage); - accountCapsule.setLatestConsumeTime(chainBaseManager.getHeadSlot()); + delegatedResourceCapsule.addFrozenBalanceForBandwidth(-unDelegateBalance, 0); + + ownerCapsule.addDelegatedFrozenBalanceForBandwidth(-unDelegateBalance); + ownerCapsule.addFrozenBalanceForBandwidthV2(unDelegateBalance); + + BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); + processor.updateUsage(ownerCapsule); + long newNetUsage = ownerCapsule.getNetUsage() + transferUsage; + ownerCapsule.setNetUsage(newNetUsage); + ownerCapsule.setLatestConsumeTime(chainBaseManager.getHeadSlot()); } break; case ENERGY: { - long delegateBalance = delegatedResourceCapsule.getFrozenBalanceForEnergy(); - delegatedResourceCapsule.setFrozenBalanceForEnergy(delegateBalance - unDelegateBalance, 0); - accountCapsule.addDelegatedFrozenBalanceForEnergy(-unDelegateBalance); - accountCapsule.addFrozenBalanceForEnergyV2(unDelegateBalance); - - long newEnergyUsage = accountCapsule.getEnergyUsage() + transferUsage; - accountCapsule.setEnergyUsage(newEnergyUsage); - accountCapsule.setLatestConsumeTimeForEnergy(chainBaseManager.getHeadSlot()); + delegatedResourceCapsule.addFrozenBalanceForEnergy(-unDelegateBalance, 0); + + ownerCapsule.addDelegatedFrozenBalanceForEnergy(-unDelegateBalance); + ownerCapsule.addFrozenBalanceForEnergyV2(unDelegateBalance); + + EnergyProcessor processor = new EnergyProcessor(dynamicStore, accountStore); + processor.updateUsage(ownerCapsule); + long newEnergyUsage = ownerCapsule.getEnergyUsage() + transferUsage; + ownerCapsule.setEnergyUsage(newEnergyUsage); + ownerCapsule.setLatestConsumeTimeForEnergy(chainBaseManager.getHeadSlot()); } break; default: @@ -191,7 +193,7 @@ public boolean execute(Object result) throws ContractExeException { delegatedResourceStore.put(key, delegatedResourceCapsule); } - accountStore.put(ownerAddress, accountCapsule); + accountStore.put(ownerAddress, ownerCapsule); ret.setStatus(fee, code.SUCESS); @@ -264,6 +266,9 @@ public boolean validate() throws ContractValidateException { } long unDelegateBalance = unDelegateResourceContract.getBalance(); + if (unDelegateBalance < TRX_PRECISION) { + throw new ContractValidateException("unDelegateBalance must be more than 1TRX"); + } switch (unDelegateResourceContract.getResource()) { case BANDWIDTH: if (delegatedResourceCapsule.getFrozenBalanceForBandwidth() < unDelegateBalance) { diff --git a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java index 5ba0a32e2be..5d49701ef92 100755 --- a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java @@ -1,10 +1,15 @@ package org.tron.core.actuator; +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; + import com.google.common.math.LongMath; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; -import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; @@ -18,14 +23,6 @@ import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.BalanceContract.WithdrawExpireUnfreezeContract; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; - @Slf4j(topic = "actuator") public class WithdrawExpireUnfreezeActuator extends AbstractActuator { @@ -51,8 +48,8 @@ public boolean execute(Object result) throws ContractExeException { ret.setStatus(fee, code.FAILED); throw new ContractExeException(e.getMessage()); } - AccountCapsule accountCapsule = accountStore. - get(withdrawExpireUnfreezeContract.getOwnerAddress().toByteArray()); + AccountCapsule accountCapsule = accountStore.get( + withdrawExpireUnfreezeContract.getOwnerAddress().toByteArray()); long now = dynamicStore.getLatestBlockHeaderTimestamp(); List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); long totalWithdrawUnfreeze = getTotalWithdrawUnfreeze(unfrozenV2List, now); @@ -97,18 +94,10 @@ public boolean validate() throws ContractValidateException { AccountCapsule accountCapsule = accountStore.get(ownerAddress); String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); if (Objects.isNull(accountCapsule)) { - throw new ContractValidateException(ACCOUNT_EXCEPTION_STR + - readableOwnerAddress + NOT_EXIST_STR); + throw new ContractValidateException(ACCOUNT_EXCEPTION_STR + + readableOwnerAddress + NOT_EXIST_STR); } - boolean isGP = CommonParameter.getInstance() - .getGenesisBlock().getWitnesses().stream().anyMatch(witness -> - Arrays.equals(ownerAddress, witness.getAddress())); - if (isGP) { - throw new ContractValidateException( - ACCOUNT_EXCEPTION_STR + readableOwnerAddress - + "] is a guard representative and is not allowed to withdraw Balance"); - } long now = dynamicStore.getLatestBlockHeaderTimestamp(); List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); long totalWithdrawUnfreeze = getTotalWithdrawUnfreeze(unfrozenV2List, now); @@ -126,18 +115,18 @@ public boolean validate() throws ContractValidateException { private long getTotalWithdrawUnfreeze(List unfrozenV2List, long now) { return getTotalWithdrawList(unfrozenV2List, now).stream() - .mapToLong(UnFreezeV2::getUnfreezeAmount).sum(); + .mapToLong(UnFreezeV2::getUnfreezeAmount).sum(); } private List getTotalWithdrawList(List unfrozenV2List, long now) { return unfrozenV2List.stream().filter(unfrozenV2 -> (unfrozenV2.getUnfreezeAmount() > 0 - && unfrozenV2.getUnfreezeExpireTime() <= now)).collect(Collectors.toList()); + && unfrozenV2.getUnfreezeExpireTime() <= now)).collect(Collectors.toList()); } private List getRemainWithdrawList(List unfrozenV2List, long now) { return unfrozenV2List.stream() - .filter(unfrozenV2 -> unfrozenV2.getUnfreezeExpireTime() > now) - .collect(Collectors.toList()); + .filter(unfrozenV2 -> unfrozenV2.getUnfreezeExpireTime() > now) + .collect(Collectors.toList()); } @Override diff --git a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java index ebe491454e4..6bfd885dc46 100644 --- a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java @@ -1,5 +1,7 @@ package org.tron.core.actuator; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + import com.google.protobuf.Any; import com.google.protobuf.ByteString; import java.io.File; @@ -23,6 +25,7 @@ import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.DynamicPropertiesStore; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.AssetIssueContractOuterClass; @@ -110,6 +113,7 @@ public void freezeBandwidthForOwner() { AccountCapsule ownerCapsule = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); ownerCapsule.addFrozenBalanceForBandwidthV2(initBalance); + dbManager.getDynamicPropertiesStore().addTotalNetWeight(initBalance / TRX_PRECISION); dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); } @@ -117,6 +121,7 @@ public void freezeCpuForOwner() { AccountCapsule ownerCapsule = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); ownerCapsule.addFrozenBalanceForEnergyV2(initBalance); + dbManager.getDynamicPropertiesStore().addTotalEnergyWeight(initBalance / TRX_PRECISION); dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); } @@ -167,8 +172,9 @@ public void testDelegateResourceWithNoFreeze() { try { actuator.validate(); actuator.execute(ret); + Assert.fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertEquals("delegateBalance must be less than accountFreezeBandwidthBalance", + Assert.assertEquals("delegateBalance must be less than available FreezeBandwidthV2 balance", e.getMessage()); } catch (ContractExeException e) { Assert.fail(); @@ -179,14 +185,77 @@ public void testDelegateResourceWithNoFreeze() { try { actuator.validate(); actuator.execute(ret); + Assert.fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertEquals( + "delegateBalance must be less than available FreezeEnergyV2Balance balance", + e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testDelegateBandwidthWithUsage() { + freezeBandwidthForOwner(); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + DynamicPropertiesStore dynamicPropertiesStore = dbManager.getDynamicPropertiesStore(); + ownerCapsule.setNetUsage(dynamicPropertiesStore.getTotalNetLimit() / 4); + ownerCapsule.setLatestConsumeTime(dbManager.getChainBaseManager().getHeadSlot()); + dbManager.getAccountStore().put(owner, ownerCapsule); + + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, initBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertEquals("delegateBalance must be less than accountFreezeEnergyBalance", + Assert.assertEquals("delegateBalance must be less than available FreezeBandwidthV2 balance", e.getMessage()); } catch (ContractExeException e) { Assert.fail(e.getMessage()); } } + + @Test + public void testDelegateCpuWithUsage() { + freezeCpuForOwner(); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + DynamicPropertiesStore dynamicPropertiesStore = dbManager.getDynamicPropertiesStore(); + ownerCapsule.setEnergyUsage(dynamicPropertiesStore.getTotalEnergyCurrentLimit() / 4); + ownerCapsule.setLatestConsumeTimeForEnergy(dbManager.getChainBaseManager().getHeadSlot()); + dbManager.getAccountStore().put(owner, ownerCapsule); + + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, initBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.fail("cannot run here."); + } catch (ContractValidateException e) { + Assert.assertEquals( + "delegateBalance must be less than available FreezeEnergyV2Balance balance", + e.getMessage()); + } catch (ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test public void testDelegateResourceWithContractAddress() { freezeBandwidthForOwner(); @@ -414,7 +483,7 @@ public void delegateMoreThanBalance() { actuator.execute(ret); Assert.fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertEquals("delegateBalance must be less than accountFreezeBandwidthBalance", + Assert.assertEquals("delegateBalance must be less than available FreezeBandwidthV2 balance", e.getMessage()); } catch (ContractExeException e) { Assert.fail(e.getMessage()); diff --git a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java index 0abe5df3356..c235de57a3a 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java @@ -222,8 +222,13 @@ public void testUnDelegateForBandwidth() { AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); receiverCapsule.setNetUsage(1_000_000_000); - receiverCapsule.setLatestConsumeTime(dbManager.getChainBaseManager().getHeadSlot()); + long nowSlot = dbManager.getChainBaseManager().getHeadSlot(); + receiverCapsule.setLatestConsumeTime(nowSlot - 14400); dbManager.getAccountStore().put(receiver, receiverCapsule); + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + ownerCapsule.setNetUsage(1_000_000_000); + ownerCapsule.setLatestConsumeTime(nowSlot - 14400); + dbManager.getAccountStore().put(owner, ownerCapsule); UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( @@ -231,13 +236,13 @@ public void testUnDelegateForBandwidth() { TransactionResultCapsule ret = new TransactionResultCapsule(); try { - AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + ownerCapsule = dbManager.getAccountStore().get(owner); Assert.assertEquals(delegateBalance, receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForBandwidth()); Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); - Assert.assertEquals(0, ownerCapsule.getNetUsage()); + Assert.assertEquals(1_000_000_000, ownerCapsule.getNetUsage()); Assert.assertEquals(1_000_000_000, receiverCapsule.getNetUsage()); actuator.validate(); @@ -250,8 +255,7 @@ public void testUnDelegateForBandwidth() { Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForBandwidth()); Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); Assert.assertEquals(1000000000, ownerCapsule.getNetUsage()); - Assert.assertEquals(dbManager.getChainBaseManager().getHeadSlot(), - ownerCapsule.getLatestConsumeTime()); + Assert.assertEquals(nowSlot, ownerCapsule.getLatestConsumeTime()); // check receiver receiverCapsule = dbManager.getAccountStore().get(receiver); @@ -483,10 +487,15 @@ public void testUnDelegatedForCpu() { long now = System.currentTimeMillis(); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + long nowSlot = dbManager.getChainBaseManager().getHeadSlot(); AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); receiverCapsule.setEnergyUsage(1_000_000_000); - receiverCapsule.setLatestConsumeTimeForEnergy(dbManager.getChainBaseManager().getHeadSlot()); + receiverCapsule.setLatestConsumeTimeForEnergy(nowSlot - 14400); dbManager.getAccountStore().put(receiver, receiverCapsule); + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + ownerCapsule.setEnergyUsage(1_000_000_000); + ownerCapsule.setLatestConsumeTimeForEnergy(nowSlot - 14400); + dbManager.getAccountStore().put(owner, ownerCapsule); UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) @@ -494,13 +503,13 @@ public void testUnDelegatedForCpu() { TransactionResultCapsule ret = new TransactionResultCapsule(); try { - AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + ownerCapsule = dbManager.getAccountStore().get(owner); Assert.assertEquals(delegateBalance, receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForEnergy()); Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); - Assert.assertEquals(0, ownerCapsule.getEnergyUsage()); + Assert.assertEquals(1_000_000_000, ownerCapsule.getEnergyUsage()); Assert.assertEquals(1_000_000_000, receiverCapsule.getEnergyUsage()); actuator.validate(); @@ -513,8 +522,7 @@ public void testUnDelegatedForCpu() { Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForEnergy()); Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); Assert.assertEquals(1_000_000_000, ownerCapsule.getEnergyUsage()); - Assert.assertEquals(dbManager.getChainBaseManager().getHeadSlot(), - ownerCapsule.getLatestConsumeTimeForEnergy()); + Assert.assertEquals(nowSlot, ownerCapsule.getLatestConsumeTimeForEnergy()); // check receiver receiverCapsule = dbManager.getAccountStore().get(receiver); diff --git a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java index 83d4dcbe7cc..e9dc144b0d1 100644 --- a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java @@ -186,53 +186,6 @@ public void invalidOwnerAccount() { } } - @Test - public void isGR() { - Witness w = Args.getInstance().getGenesisBlock().getWitnesses().get(0); - byte[] address = w.getAddress(); - AccountCapsule grCapsule = new AccountCapsule(ByteString.copyFromUtf8("gr"), - ByteString.copyFrom(address), AccountType.Normal, initBalance); - dbManager.getAccountStore().put(grCapsule.createDbKey(), grCapsule); - long now = System.currentTimeMillis(); - dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); - - try { - dbManager.getMortgageService() - .adjustAllowance(dbManager.getAccountStore(), address, allowance); - } catch (BalanceInsufficientException e) { - fail("BalanceInsufficientException"); - } - AccountCapsule accountCapsule = dbManager.getAccountStore().get(address); - Assert.assertEquals(accountCapsule.getAllowance(), allowance); - - WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address), 100, - "http://google.com/"); - - dbManager.getAccountStore().put(address, accountCapsule); - dbManager.getWitnessStore().put(address, witnessCapsule); - - WithdrawExpireUnfreezeActuator actuator = new WithdrawExpireUnfreezeActuator(); - actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getContract(ByteArray.toHexString(address))); - - TransactionResultCapsule ret = new TransactionResultCapsule(); - Assert.assertTrue(dbManager.getWitnessStore().has(address)); - - try { - actuator.validate(); - actuator.execute(ret); - fail("cannot run here."); - - } catch (ContractValidateException e) { - String readableOwnerAddress = StringUtil.createReadableString(address); - Assert.assertTrue(e instanceof ContractValidateException); - Assert.assertEquals("Account[" + readableOwnerAddress - + "] is a guard representative and is not allowed to withdraw Balance", e.getMessage()); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); - } - } - @Test public void commonErrorCheck() { From 2806c75009af3ee2bb3f8e3e47954d8957829000 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Mon, 26 Sep 2022 17:38:00 +0800 Subject: [PATCH 0332/1197] feat(freezeV2): add api for freezing and delegation --- .../actuator/DelegateResourceActuator.java | 5 ++++ .../actuator/FreezeBalanceV2Actuator.java | 5 ++++ .../actuator/UnDelegateResourceActuator.java | 5 ++++ .../actuator/UnfreezeBalanceV2Actuator.java | 6 ++++ .../WithdrawExpireUnfreezeActuator.java | 6 ++++ .../services/http/FullNodeHttpApiService.java | 2 +- .../solidity/SolidityNodeHttpApiService.java | 28 +++++++++++++++++-- 7 files changed, 54 insertions(+), 3 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 152c4fb2a7a..46aeb77e40b 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -109,6 +109,11 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("No support for resource delegate"); } + if (dynamicStore.getUnfreezeDelayDays() == 0) { + throw new ContractValidateException("Not support Delegate resource transaction," + + " need to be opened by the committee"); + } + final DelegateResourceContract delegateResourceContract; try { delegateResourceContract = this.any.unpack(DelegateResourceContract.class); diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java index 743aaff6824..60981f00588 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java @@ -96,6 +96,11 @@ public boolean validate() throws ContractValidateException { .getClass() + "]"); } + if (dynamicStore.getUnfreezeDelayDays() == 0) { + throw new ContractValidateException("Not support FreezeV2 transaction," + + " need to be opened by the committee"); + } + final FreezeBalanceV2Contract freezeBalanceV2Contract; try { freezeBalanceV2Contract = this.any.unpack(FreezeBalanceV2Contract.class); diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index f18083f77d2..414b9e44dc1 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -215,6 +215,11 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("No support for resource delegate"); } + if (dynamicStore.getUnfreezeDelayDays() == 0) { + throw new ContractValidateException("Not support Delegate resource transaction," + + " need to be opened by the committee"); + } + if (!this.any.is(UnDelegateResourceContract.class)) { throw new ContractValidateException( "contract type error, expected type [UnDelegateResourceContract], real type[" + any diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java index 09c2b90e6ef..c4edbf6d957 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java @@ -108,6 +108,12 @@ public boolean validate() throws ContractValidateException { "contract type error, expected type [UnfreezeBalanceContract], real type[" + any .getClass() + "]"); } + + if (dynamicStore.getUnfreezeDelayDays() == 0) { + throw new ContractValidateException("Not support UnfreezeV2 transaction," + + " need to be opened by the committee"); + } + final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract; try { unfreezeBalanceV2Contract = this.any.unpack(UnfreezeBalanceV2Contract.class); diff --git a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java index 5d49701ef92..11b991585f6 100755 --- a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java @@ -80,6 +80,12 @@ public boolean validate() throws ContractValidateException { "contract type error, expected type [WithdrawExpireUnfreezeContract], real type[" + any .getClass() + "]"); } + + if (dynamicStore.getUnfreezeDelayDays() == 0) { + throw new ContractValidateException("Not support WithdrawExpireUnfreeze transaction," + + " need to be opened by the committee"); + } + final WithdrawExpireUnfreezeContract withdrawExpireUnfreezeContract; try { withdrawExpireUnfreezeContract = this.any.unpack(WithdrawExpireUnfreezeContract.class); diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index 43a0d87661b..2c2a4f8797c 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -559,7 +559,7 @@ public void start() { context.addServlet(new ServletHolder(unFreezeBalanceV2Servlet), "/wallet/unfreezebalancev2"); context.addServlet(new ServletHolder(withdrawExpireUnfreezeServlet), - "/wallet/withdrawExpireUnfreeze"); + "/wallet/withdrawexpireunfreeze"); context.addServlet(new ServletHolder(delegateResourceServlet), "/wallet/delegateresource"); context.addServlet(new ServletHolder(unDelegateResourceServlet), diff --git a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java index 7453c833c10..e4ad276782e 100644 --- a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java @@ -2,13 +2,11 @@ import java.util.EnumSet; import javax.servlet.DispatcherType; -import javax.servlet.Filter; import lombok.extern.slf4j.Slf4j; import org.eclipse.jetty.server.ConnectionLimit; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -16,6 +14,8 @@ import org.tron.common.parameter.CommonParameter; import org.tron.core.config.args.Args; import org.tron.core.services.filter.HttpApiAccessFilter; +import org.tron.core.services.http.DelegateResourceServlet; +import org.tron.core.services.http.FreezeBalanceV2Servlet; import org.tron.core.services.http.FullNodeHttpApiService; import org.tron.core.services.http.GetAccountByIdServlet; import org.tron.core.services.http.GetAccountServlet; @@ -55,6 +55,9 @@ import org.tron.core.services.http.ScanShieldedTRC20NotesByIvkServlet; import org.tron.core.services.http.ScanShieldedTRC20NotesByOvkServlet; import org.tron.core.services.http.TriggerConstantContractServlet; +import org.tron.core.services.http.UnDelegateResourceServlet; +import org.tron.core.services.http.UnFreezeBalanceV2Servlet; +import org.tron.core.services.http.WithdrawExpireUnfreezeServlet; @Component @@ -153,6 +156,17 @@ public class SolidityNodeHttpApiService implements Service { @Autowired private GetBlockServlet getBlockServlet; + @Autowired + private FreezeBalanceV2Servlet freezeBalanceV2Servlet; + @Autowired + private UnFreezeBalanceV2Servlet unFreezeBalanceV2Servlet; + @Autowired + private WithdrawExpireUnfreezeServlet withdrawExpireUnfreezeServlet; + @Autowired + private DelegateResourceServlet delegateResourceServlet; + @Autowired + private UnDelegateResourceServlet unDelegateResourceServlet; + @Override public void init() { } @@ -255,6 +269,16 @@ public void start() { context.addServlet(new ServletHolder(getRewardServlet), "/walletsolidity/getReward"); context.addServlet(new ServletHolder(getBurnTrxServlet), "/walletsolidity/getburntrx"); context.addServlet(new ServletHolder(getBlockServlet), "/walletsolidity/getblock"); + context.addServlet(new ServletHolder(freezeBalanceV2Servlet), + "/walletsolidity/freezebalancev2"); + context.addServlet(new ServletHolder(unFreezeBalanceV2Servlet), + "/walletsolidity/unfreezebalancev2"); + context.addServlet(new ServletHolder(withdrawExpireUnfreezeServlet), + "/walletsolidity/withdrawexpireunfreeze"); + context.addServlet(new ServletHolder(delegateResourceServlet), + "/walletsolidity/delegateresource"); + context.addServlet(new ServletHolder(unDelegateResourceServlet), + "/walletsolidity/undelegateresource"); // http access filter context.addFilter(new FilterHolder(httpApiAccessFilter), "/walletsolidity/*", EnumSet.allOf(DispatcherType.class)); From e94a08c525c3b358cad8005acbe826b44e712026 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Mon, 26 Sep 2022 18:37:12 +0800 Subject: [PATCH 0333/1197] feat(freezeV2): add the config param for unfreezeDelayDays --- common/src/main/java/org/tron/core/Constant.java | 1 + .../src/main/java/org/tron/core/config/args/Args.java | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index af96fbea859..130395d1f5e 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -285,6 +285,7 @@ public class Constant { public static final String COMMITTEE_ALLOW_TVM_FREEZE = "committee.allowTvmFreeze"; public static final String COMMITTEE_ALLOW_TVM_VOTE = "committee.allowTvmVote"; + public static final String COMMITTEE_UNFREEZE_DELAY_DAYS = "committee.unfreezeDelayDays"; public static final String COMMITTEE_ALLOW_TVM_LONDON = "committee.allowTvmLondon"; public static final String COMMITTEE_ALLOW_TVM_COMPATIBLE_EVM = "committee.allowTvmCompatibleEvm"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index b75664ed3c1..6e159052e38 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1034,6 +1034,16 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.blockCacheTimeout = config.getLong(Constant.BLOCK_CACHE_TIMEOUT); } + if (config.hasPath(Constant.COMMITTEE_UNFREEZE_DELAY_DAYS)) { + PARAMETER.unfreezeDelayDays = config.getLong(Constant.COMMITTEE_UNFREEZE_DELAY_DAYS); + if (PARAMETER.unfreezeDelayDays > 365) { + PARAMETER.unfreezeDelayDays = 365; + } + if (PARAMETER.unfreezeDelayDays < 0) { + PARAMETER.unfreezeDelayDays = 0; + } + } + logConfig(); } From 2a6ba76d241546657a200f3ca9db4c00806edaa8 Mon Sep 17 00:00:00 2001 From: chaozhu Date: Tue, 27 Sep 2022 18:16:57 -0700 Subject: [PATCH 0334/1197] fix(freezeV2): fix http request address params --- .../core/services/http/HttpSelfFormatFieldName.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java b/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java index 99fa55d9241..2526a9cfabe 100644 --- a/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java +++ b/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java @@ -142,6 +142,18 @@ public class HttpSelfFormatFieldName { AddressFieldNameMap.put("protocol.ShieldedTransferContract.transparent_to_address", 1); //UpdateBrokerageContract AddressFieldNameMap.put("protocol.UpdateBrokerageContract.owner_address", 1); + //FreezeBalanceV2Contract + AddressFieldNameMap.put("protocol.FreezeBalanceV2Contract.owner_address", 1); + //UnfreezeBalanceV2Contract + AddressFieldNameMap.put("protocol.UnfreezeBalanceV2Contract.owner_address", 1); + //WithdrawExpireUnfreezeContract + AddressFieldNameMap.put("protocol.WithdrawExpireUnfreezeContract.owner_address", 1); + //DelegateResourceContract + AddressFieldNameMap.put("protocol.DelegateResourceContract.owner_address", 1); + AddressFieldNameMap.put("protocol.DelegateResourceContract.receiver_address", 1); + //UnDelegateResourceContract + AddressFieldNameMap.put("protocol.UnDelegateResourceContract.owner_address", 1); + AddressFieldNameMap.put("protocol.UnDelegateResourceContract.receiver_address", 1); //***** Tron.proto ***** //AccountId From bdc6da4e0a1168322f64cb807dc87ddee85892a0 Mon Sep 17 00:00:00 2001 From: chaozhu Date: Thu, 29 Sep 2022 12:07:33 -0700 Subject: [PATCH 0335/1197] docs(proto): update Tron protobuf protocol document.md --- Tron protobuf protocol document.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Tron protobuf protocol document.md b/Tron protobuf protocol document.md index be9558a1d93..f6fa2219ce3 100644 --- a/Tron protobuf protocol document.md +++ b/Tron protobuf protocol document.md @@ -620,6 +620,13 @@ Transaction and transaction-related messages. ClearABIContract = 48; UpdateBrokerageContract = 49; ShieldedTransferContract = 51; + MarketSellAssetContract = 52; + MarketCancelOrderContract = 53; + FreezeBalanceV2Contract = 54; + UnfreezeBalanceV2Contract = 55; + WithdrawExpireUnfreezeContract = 56; + DelegateResourceContract = 57; + UnDelegateResourceContract = 58; } ContractType type = 1; google.protobuf.Any parameter = 2; @@ -873,6 +880,13 @@ Contract and contract-related messages. ClearABIContract = 48; UpdateBrokerageContract = 49; ShieldedTransferContract = 51; + MarketSellAssetContract = 52; + MarketCancelOrderContract = 53; + FreezeBalanceV2Contract = 54; + UnfreezeBalanceV2Contract = 55; + WithdrawExpireUnfreezeContract = 56; + DelegateResourceContract = 57; + UnDelegateResourceContract = 58; } ContractType type = 1; google.protobuf.Any parameter = 2; From 448dd73df21b6e00b802792886b900f6eec318fc Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Thu, 13 Oct 2022 17:54:43 +0800 Subject: [PATCH 0336/1197] feat(freezeV2): optimize usage merging --- .../actuator/DelegateResourceActuator.java | 24 ++++--- .../core/actuator/FreezeBalanceActuator.java | 2 +- .../actuator/FreezeBalanceV2Actuator.java | 2 +- .../actuator/UnDelegateResourceActuator.java | 30 +++++---- .../actuator/UnfreezeBalanceV2Actuator.java | 7 +- .../WithdrawExpireUnfreezeActuator.java | 3 +- .../org/tron/core/capsule/AccountCapsule.java | 37 +++++++++++ .../org/tron/core/db/BandwidthProcessor.java | 20 ++++-- .../org/tron/core/db/EnergyProcessor.java | 12 ++-- .../org/tron/core/db/ResourceProcessor.java | 64 +++++++++++++++++++ .../core/store/DynamicPropertiesStore.java | 4 ++ .../tron/common/runtime/vm/FreezeTest.java | 5 ++ .../DelegateResourceActuatorTest.java | 2 + .../actuator/FreezeBalanceV2ActuatorTest.java | 8 +-- .../UnDelegateResourceActuatorTest.java | 2 + .../UnfreezeBalanceV2ActuatorTest.java | 6 +- .../WithdrawExpireUnfreezeActuatorTest.java | 5 +- protocol/src/main/protos/core/Tron.proto | 3 + 18 files changed, 186 insertions(+), 50 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 46aeb77e40b..ec36c2c4b90 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -109,7 +109,7 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("No support for resource delegate"); } - if (dynamicStore.getUnfreezeDelayDays() == 0) { + if (!dynamicStore.supportUnfreezeDelay()) { throw new ContractValidateException("Not support Delegate resource transaction," + " need to be opened by the committee"); } @@ -143,11 +143,14 @@ public boolean validate() throws ContractValidateException { BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); processor.updateUsage(ownerCapsule); - //The unit is trx - long netTrxUsage = (long) (ownerCapsule.getNetUsage() - * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); + long netUsage = (long) (ownerCapsule.getNetUsage() * TRX_PRECISION * ((double) + (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); - if (ownerCapsule.getFrozenV2BalanceForBandwidth() - netTrxUsage * TRX_PRECISION + long ownerNetUsage = (long) (netUsage * ((double)(ownerCapsule + .getFrozenV2BalanceForBandwidth()) / + ownerCapsule.getAllFrozenBalanceForBandwidth())); + + if (ownerCapsule.getFrozenV2BalanceForBandwidth() - ownerNetUsage < delegateBalance) { throw new ContractValidateException( "delegateBalance must be less than available FreezeBandwidthV2 balance"); @@ -158,12 +161,13 @@ public boolean validate() throws ContractValidateException { EnergyProcessor processor = new EnergyProcessor(dynamicStore, accountStore); processor.updateUsage(ownerCapsule); - //The unit is trx - long energyTrxUsage = (long) (ownerCapsule.getEnergyUsage() - * ((double) (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); + long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) + (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); - if (ownerCapsule.getFrozenV2BalanceForEnergy() - energyTrxUsage * TRX_PRECISION - < delegateBalance) { + long ownerEnergyUsage = (long) (energyUsage * ((double)(ownerCapsule + .getFrozenV2BalanceForEnergy()) / ownerCapsule.getAllFrozenBalanceForEnergy())); + + if (ownerCapsule.getFrozenV2BalanceForEnergy() - ownerEnergyUsage < delegateBalance) { throw new ContractValidateException( "delegateBalance must be less than available FreezeEnergyV2Balance balance"); } diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java index e194999a25f..5d630d0f115 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java @@ -249,7 +249,7 @@ public boolean validate() throws ContractValidateException { } - if (dynamicStore.getUnfreezeDelayDays() > 0) { + if (dynamicStore.supportUnfreezeDelay()) { throw new ContractValidateException( "freeze v2 is open, old freeze is closed"); } diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java index 60981f00588..3d4a8c8fae7 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java @@ -96,7 +96,7 @@ public boolean validate() throws ContractValidateException { .getClass() + "]"); } - if (dynamicStore.getUnfreezeDelayDays() == 0) { + if (!dynamicStore.supportUnfreezeDelay()) { throw new ContractValidateException("Not support FreezeV2 transaction," + " need to be opened by the committee"); } diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index 414b9e44dc1..56ad722533a 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -2,6 +2,8 @@ import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; @@ -135,10 +137,13 @@ public boolean execute(Object result) throws ContractExeException { ownerCapsule.addFrozenBalanceForBandwidthV2(unDelegateBalance); BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); - processor.updateUsage(ownerCapsule); - long newNetUsage = ownerCapsule.getNetUsage() + transferUsage; - ownerCapsule.setNetUsage(newNetUsage); - ownerCapsule.setLatestConsumeTime(chainBaseManager.getHeadSlot()); + + long now = chainBaseManager.getHeadSlot(); + if (Objects.nonNull(receiverCapsule) && transferUsage > 0) { + ownerCapsule.setNetUsage(processor.unDelegateIncrease(ownerCapsule, receiverCapsule, + transferUsage, BANDWIDTH, now)); + ownerCapsule.setLatestConsumeTime(now); + } } break; case ENERGY: { @@ -148,10 +153,13 @@ public boolean execute(Object result) throws ContractExeException { ownerCapsule.addFrozenBalanceForEnergyV2(unDelegateBalance); EnergyProcessor processor = new EnergyProcessor(dynamicStore, accountStore); - processor.updateUsage(ownerCapsule); - long newEnergyUsage = ownerCapsule.getEnergyUsage() + transferUsage; - ownerCapsule.setEnergyUsage(newEnergyUsage); - ownerCapsule.setLatestConsumeTimeForEnergy(chainBaseManager.getHeadSlot()); + + long now = chainBaseManager.getHeadSlot(); + if (Objects.nonNull(receiverCapsule) && transferUsage > 0) { + ownerCapsule.setEnergyUsage(processor.unDelegateIncrease(ownerCapsule, receiverCapsule, + transferUsage, ENERGY, now)); + ownerCapsule.setLatestConsumeTimeForEnergy(now); + } } break; default: @@ -215,7 +223,7 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("No support for resource delegate"); } - if (dynamicStore.getUnfreezeDelayDays() == 0) { + if (!dynamicStore.supportUnfreezeDelay()) { throw new ContractValidateException("Not support Delegate resource transaction," + " need to be opened by the committee"); } @@ -271,8 +279,8 @@ public boolean validate() throws ContractValidateException { } long unDelegateBalance = unDelegateResourceContract.getBalance(); - if (unDelegateBalance < TRX_PRECISION) { - throw new ContractValidateException("unDelegateBalance must be more than 1TRX"); + if (unDelegateBalance <= 0) { + throw new ContractValidateException("unDelegateBalance must be more than 0 TRX"); } switch (unDelegateResourceContract.getResource()) { case BANDWIDTH: diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java index c4edbf6d957..2c50875d298 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java @@ -109,7 +109,7 @@ public boolean validate() throws ContractValidateException { .getClass() + "]"); } - if (dynamicStore.getUnfreezeDelayDays() == 0) { + if (!dynamicStore.supportUnfreezeDelay()) { throw new ContractValidateException("Not support UnfreezeV2 transaction," + " need to be opened by the committee"); } @@ -165,7 +165,7 @@ public boolean validate() throws ContractValidateException { if (!checkUnfreezeBalance(accountCapsule, unfreezeBalanceV2Contract, unfreezeBalanceV2Contract.getResource())) { throw new ContractValidateException( - "Invalid unfreeze_balance, freezing resource[" + unfreezeBalanceV2Contract.getResource() + "] is not enough" + "Invalid unfreeze_balance, [" + unfreezeBalanceV2Contract.getUnfreezeBalance() + "] is error" ); } @@ -219,7 +219,8 @@ public boolean checkUnfreezeBalance(AccountCapsule accountCapsule, } } - if (unfreezeBalanceV2Contract.getUnfreezeBalance() <= frozenAmount) { + if (unfreezeBalanceV2Contract.getUnfreezeBalance() > 0 + && unfreezeBalanceV2Contract.getUnfreezeBalance() <= frozenAmount) { checkOk = true; } diff --git a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java index 11b991585f6..606c18028d5 100755 --- a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java @@ -55,7 +55,6 @@ public boolean execute(Object result) throws ContractExeException { long totalWithdrawUnfreeze = getTotalWithdrawUnfreeze(unfrozenV2List, now); accountCapsule.setInstance(accountCapsule.getInstance().toBuilder() .setBalance(accountCapsule.getBalance() + totalWithdrawUnfreeze) - .setLatestWithdrawTime(now) .build()); List newUnFreezeList = getRemainWithdrawList(unfrozenV2List, now); accountCapsule.clearUnfrozenV2(); @@ -81,7 +80,7 @@ public boolean validate() throws ContractValidateException { .getClass() + "]"); } - if (dynamicStore.getUnfreezeDelayDays() == 0) { + if (!dynamicStore.supportUnfreezeDelay()) { throw new ContractValidateException("Not support WithdrawExpireUnfreeze transaction," + " need to be opened by the committee"); } diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index 919e7a411d8..684d582ade8 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -43,9 +43,12 @@ import java.util.Map; import java.util.Objects; +import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; +import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_MS; import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; +import static org.tron.protos.contract.Common.ResourceCode; @Slf4j(topic = "capsule") public class AccountCapsule implements ProtoCapsule, Comparable { @@ -969,6 +972,14 @@ public long getNetUsage() { return this.account.getNetUsage(); } + public long getUsage(ResourceCode resourceCode) { + if (resourceCode == BANDWIDTH) { + return this.account.getNetUsage(); + } else { + return this.account.getAccountResource().getEnergyUsage(); + } + } + public void setNetUsage(long netUsage) { this.account = this.account.toBuilder() .setNetUsage(netUsage).build(); @@ -1262,4 +1273,30 @@ public void clearUnfrozenV2() { this.account = this.account.toBuilder().clearUnfrozenV2().build(); } + public void setNewWindowSize(ResourceCode resourceCode, long newWindowSize) { + if (resourceCode == BANDWIDTH) { + this.account = this.account.toBuilder().setNetWindowSize(newWindowSize).build(); + } else { + this.account = this.account.toBuilder().setAccountResource(this.account.getAccountResource() + .toBuilder().setEnergyWindowSize(newWindowSize).build()).build(); + } + } + + public long getWindowSize(ResourceCode resourceCode) { + long windowSize; + if (resourceCode == BANDWIDTH) { + windowSize = this.account.getNetWindowSize(); + } else { + windowSize = this.account.getAccountResource().getEnergyWindowSize(); + } + return windowSize == 0 ? WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL : windowSize; + } + + public long getLastConsumeTime(ResourceCode resourceCode) { + if (resourceCode == BANDWIDTH) { + return this.account.getLatestConsumeTime(); + } else { + return this.account.getAccountResource().getLatestConsumeTimeForEnergy(); + } + } } diff --git a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java index 64405a69f69..c2aba118405 100644 --- a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -24,6 +24,8 @@ import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; import org.tron.protos.contract.BalanceContract.TransferContract; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; + @Slf4j(topic = "DB") public class BandwidthProcessor extends ResourceProcessor { @@ -43,7 +45,8 @@ public void updateUsage(AccountCapsule accountCapsule) { private void updateUsage(AccountCapsule accountCapsule, long now) { long oldNetUsage = accountCapsule.getNetUsage(); long latestConsumeTime = accountCapsule.getLatestConsumeTime(); - accountCapsule.setNetUsage(increase(oldNetUsage, 0, latestConsumeTime, now)); + accountCapsule.setNetUsage(increase(accountCapsule, BANDWIDTH, + oldNetUsage, 0, latestConsumeTime, now)); long oldFreeNetUsage = accountCapsule.getFreeNetUsage(); long latestConsumeFreeTime = accountCapsule.getLatestConsumeFreeTime(); accountCapsule.setFreeNetUsage(increase(oldFreeNetUsage, 0, latestConsumeFreeTime, now)); @@ -189,13 +192,14 @@ public boolean consumeBandwidthForCreateNewAccount(AccountCapsule accountCapsule long netUsage = accountCapsule.getNetUsage(); long latestConsumeTime = accountCapsule.getLatestConsumeTime(); long netLimit = calculateGlobalNetLimit(accountCapsule); - long newNetUsage = increase(netUsage, 0, latestConsumeTime, now); + long newNetUsage = increase(accountCapsule, BANDWIDTH, netUsage, 0, latestConsumeTime, now); long netCost = bytes * createNewAccountBandwidthRatio; if (netCost <= (netLimit - newNetUsage)) { latestConsumeTime = now; long latestOperationTime = chainBaseManager.getHeadBlockTimeStamp(); - newNetUsage = increase(newNetUsage, netCost, latestConsumeTime, now); + newNetUsage = increase(accountCapsule, BANDWIDTH, + newNetUsage, netCost, latestConsumeTime, now); accountCapsule.setLatestConsumeTime(latestConsumeTime); accountCapsule.setLatestOperationTime(latestOperationTime); accountCapsule.setNetUsage(newNetUsage); @@ -323,7 +327,8 @@ private boolean useAssetAccountNet(Contract contract, AccountCapsule accountCaps long latestConsumeTime = issuerAccountCapsule.getLatestConsumeTime(); long issuerNetLimit = calculateGlobalNetLimit(issuerAccountCapsule); - long newIssuerNetUsage = increase(issuerNetUsage, 0, latestConsumeTime, now); + long newIssuerNetUsage = increase(issuerAccountCapsule, BANDWIDTH, + issuerNetUsage, 0, latestConsumeTime, now); if (bytes > (issuerNetLimit - newIssuerNetUsage)) { logger.debug("The {} issuer's bandwidth is not enough." @@ -337,7 +342,8 @@ private boolean useAssetAccountNet(Contract contract, AccountCapsule accountCaps publicLatestFreeNetTime = now; long latestOperationTime = chainBaseManager.getHeadBlockTimeStamp(); - newIssuerNetUsage = increase(newIssuerNetUsage, bytes, latestConsumeTime, now); + newIssuerNetUsage = increase(issuerAccountCapsule, BANDWIDTH, + newIssuerNetUsage, bytes, latestConsumeTime, now); newFreeAssetNetUsage = increase(newFreeAssetNetUsage, bytes, latestAssetOperationTime, now); newPublicFreeAssetNetUsage = increase(newPublicFreeAssetNetUsage, bytes, @@ -402,7 +408,7 @@ private boolean useAccountNet(AccountCapsule accountCapsule, long bytes, long no long latestConsumeTime = accountCapsule.getLatestConsumeTime(); long netLimit = calculateGlobalNetLimit(accountCapsule); - long newNetUsage = increase(netUsage, 0, latestConsumeTime, now); + long newNetUsage = increase(accountCapsule, BANDWIDTH, netUsage, 0, latestConsumeTime, now); if (bytes > (netLimit - newNetUsage)) { logger.debug("Net usage is running out, now use free net usage." @@ -413,7 +419,7 @@ private boolean useAccountNet(AccountCapsule accountCapsule, long bytes, long no latestConsumeTime = now; long latestOperationTime = chainBaseManager.getHeadBlockTimeStamp(); - newNetUsage = increase(newNetUsage, bytes, latestConsumeTime, now); + newNetUsage = increase(accountCapsule, BANDWIDTH, newNetUsage, bytes, latestConsumeTime, now); accountCapsule.setNetUsage(newNetUsage); accountCapsule.setLatestOperationTime(latestOperationTime); accountCapsule.setLatestConsumeTime(latestConsumeTime); diff --git a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java index 4ebe6d603d9..fe36575c512 100644 --- a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java @@ -15,6 +15,8 @@ import org.tron.core.store.DynamicPropertiesStore; import org.tron.protos.Protocol.Account.AccountResource; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; + @Slf4j(topic = "DB") public class EnergyProcessor extends ResourceProcessor { @@ -41,7 +43,8 @@ private void updateUsage(AccountCapsule accountCapsule, long now) { long oldEnergyUsage = accountResource.getEnergyUsage(); long latestConsumeTime = accountResource.getLatestConsumeTimeForEnergy(); - accountCapsule.setEnergyUsage(increase(oldEnergyUsage, 0, latestConsumeTime, now)); + accountCapsule.setEnergyUsage(increase(accountCapsule, ENERGY, + oldEnergyUsage, 0, latestConsumeTime, now)); } public void updateTotalEnergyAverageUsage() { @@ -100,7 +103,7 @@ public boolean useEnergy(AccountCapsule accountCapsule, long energy, long now) { long latestConsumeTime = accountCapsule.getAccountResource().getLatestConsumeTimeForEnergy(); long energyLimit = calculateGlobalEnergyLimit(accountCapsule); - long newEnergyUsage = increase(energyUsage, 0, latestConsumeTime, now); + long newEnergyUsage = increase(accountCapsule, ENERGY, energyUsage, 0, latestConsumeTime, now); if (energy > (energyLimit - newEnergyUsage) && dynamicPropertiesStore.getAllowTvmFreeze() == 0) { @@ -109,7 +112,8 @@ public boolean useEnergy(AccountCapsule accountCapsule, long energy, long now) { latestConsumeTime = now; long latestOperationTime = dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); - newEnergyUsage = increase(newEnergyUsage, energy, latestConsumeTime, now); + newEnergyUsage = increase(accountCapsule, ENERGY, + newEnergyUsage, energy, latestConsumeTime, now); accountCapsule.setEnergyUsage(newEnergyUsage); accountCapsule.setLatestOperationTime(latestOperationTime); accountCapsule.setLatestConsumeTimeForEnergy(latestConsumeTime); @@ -145,7 +149,7 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { long latestConsumeTime = accountCapsule.getAccountResource().getLatestConsumeTimeForEnergy(); long energyLimit = calculateGlobalEnergyLimit(accountCapsule); - long newEnergyUsage = increase(energyUsage, 0, latestConsumeTime, now); + long newEnergyUsage = increase(accountCapsule, ENERGY, energyUsage, 0, latestConsumeTime, now); return max(energyLimit - newEnergyUsage, 0); // us } diff --git a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java index 09bac96e0ae..e9aa35f696e 100644 --- a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java @@ -13,6 +13,7 @@ import org.tron.core.exception.TooBigTransactionResultException; import org.tron.core.store.AccountStore; import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.contract.Common.ResourceCode; abstract class ResourceProcessor { @@ -59,6 +60,69 @@ protected long increase(long lastUsage, long usage, long lastTime, long now, lon return getUsage(averageLastUsage, windowSize); } + protected long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, + long lastUsage, long usage, long lastTime, long now) { + long oldWindowSize = accountCapsule.getWindowSize(resourceCode); + /* old logic */ + long averageLastUsage = divideCeil(lastUsage * this.precision, oldWindowSize); + long averageUsage = divideCeil(usage * this.precision, this.windowSize); + + if (lastTime != now) { + assert now > lastTime; + if (lastTime + oldWindowSize > now) { + long delta = now - lastTime; + double decay = (oldWindowSize - delta) / (double) oldWindowSize; + averageLastUsage = Math.round(averageLastUsage * decay); + } else { + averageLastUsage = 0; + } + } + /* new logic */ + long newUsage = getUsage(averageLastUsage, oldWindowSize) + + getUsage(averageUsage, this.windowSize); + if (dynamicPropertiesStore.supportUnfreezeDelay()) { + long remainUsage = getUsage(averageLastUsage, oldWindowSize); + if (remainUsage == 0) { + accountCapsule.setNewWindowSize(resourceCode, this.windowSize); + return newUsage; + } + long remainWindowSize = oldWindowSize - (now - lastTime); + long newWindowSize = (remainWindowSize * remainUsage + this.windowSize * usage) + / newUsage; + accountCapsule.setNewWindowSize(resourceCode, newWindowSize); + } + return newUsage; + } + + public long unDelegateIncrease(AccountCapsule owner, AccountCapsule receiver, + long transferUsage, ResourceCode resourceCode, long now) { + long lastOwnerTime = owner.getLastConsumeTime(resourceCode); + long lastReceiverTime = receiver.getLastConsumeTime(resourceCode); + long ownerWindowSize = owner.getWindowSize(resourceCode); + long receiverWindowSize = receiver.getWindowSize(resourceCode); + long ownerUsage = owner.getUsage(resourceCode); + // Update itself first + ownerUsage = increase(owner, resourceCode, ownerUsage, 0, lastOwnerTime, now); + + long remainOwnerWindowSize = ownerWindowSize - (now - lastOwnerTime); + long remainReceiverWindowSize = receiverWindowSize - (now - lastReceiverTime); + remainOwnerWindowSize = remainOwnerWindowSize < 0 ? 0 : remainOwnerWindowSize; + remainReceiverWindowSize = remainReceiverWindowSize < 0 ? 0 : remainReceiverWindowSize; + + long newOwnerUsage = ownerUsage + transferUsage; + // mean ownerUsage == 0 and transferUsage == 0 + if (newOwnerUsage == 0) { + owner.setNewWindowSize(resourceCode, this.windowSize); + return newOwnerUsage; + } + // calculate new windowSize + long newOwnerWindowSize = (ownerUsage * remainOwnerWindowSize + + transferUsage * remainReceiverWindowSize) + / newOwnerUsage; + owner.setNewWindowSize(resourceCode, newOwnerWindowSize); + return newOwnerUsage; + } + private long divideCeil(long numerator, long denominator) { return (numerator / denominator) + ((numerator % denominator) > 0 ? 1 : 0); } diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index f7fd022f311..3540cad8316 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -2546,6 +2546,10 @@ public long getUnfreezeDelayDays() { .orElseThrow(() -> new IllegalArgumentException("not found UNFREEZE_DELAY_DAYS")); } + public boolean supportUnfreezeDelay() { + return getUnfreezeDelayDays() > 0; + } + public void saveUnfreezeDelayDays(long value) { this.put(UNFREEZE_DELAY_DAYS, new BytesCapsule(ByteArray.fromLong(value))); } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java index 60e7a3ffa9c..ba5456080e7 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java @@ -4,6 +4,7 @@ import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import static org.tron.protos.Protocol.Transaction.Result.contractResult.REVERT; import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import com.google.protobuf.ByteString; import java.io.File; @@ -798,7 +799,9 @@ private TVMTestResult freezeForOther(byte[] callerAddr, if (oldReceiver != null) { newReceiver.setBalance(oldReceiver.getBalance()); oldReceiver.setEnergyUsage(0); + oldReceiver.setNewWindowSize(ENERGY, 28800); newReceiver.setEnergyUsage(0); + newReceiver.setNewWindowSize(ENERGY,28800); if (res == 0) { oldReceiver.setAcquiredDelegatedFrozenBalanceForBandwidth(0); newReceiver.setAcquiredDelegatedFrozenBalanceForBandwidth(0); @@ -912,7 +915,9 @@ private TVMTestResult unfreezeForOther(byte[] callerAddr, || acquiredBalance - newAcquiredBalance == delegatedFrozenBalance); newReceiver.setBalance(oldReceiver.getBalance()); newReceiver.setEnergyUsage(0); + newReceiver.setNewWindowSize(ENERGY,28800); oldReceiver.setEnergyUsage(0); + oldReceiver.setNewWindowSize(ENERGY,28800); if (res == 0) { oldReceiver.setAcquiredDelegatedFrozenBalanceForBandwidth(0); newReceiver.setAcquiredDelegatedFrozenBalanceForBandwidth(0); diff --git a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java index 6bfd885dc46..e76d979cd1f 100644 --- a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java @@ -59,6 +59,8 @@ public class DelegateResourceActuatorTest { @BeforeClass public static void init() { dbManager = context.getBean(Manager.class); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); } /** diff --git a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java index 87708196143..1296886637d 100644 --- a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java @@ -61,10 +61,8 @@ public class FreezeBalanceV2ActuatorTest { @BeforeClass public static void init() { dbManager = context.getBean(Manager.class); - // Args.setParam(new String[]{"--output-directory", dbPath}, - // "config-junit.conf"); - // dbManager = new Manager(); - // dbManager.init(); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); } /** @@ -369,6 +367,7 @@ public void testFreezeBalanceForEnergyWithoutOldTronPowerAfterNewResourceModel() long frozenBalance = 1_000_000_000L; FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); ChainBaseManager chainBaseManager = dbManager.getChainBaseManager(); + chainBaseManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); chainBaseManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); actuator.setChainBaseManager(chainBaseManager) .setAny(getContractForCpuV2(OWNER_ADDRESS, frozenBalance)); @@ -396,6 +395,7 @@ public void testFreezeBalanceForEnergyWithOldTronPowerAfterNewResourceModel() { long duration = 3; FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); ChainBaseManager chainBaseManager = dbManager.getChainBaseManager(); + chainBaseManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); chainBaseManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); actuator.setChainBaseManager(chainBaseManager) .setAny(getContractForCpuV2(OWNER_ADDRESS, frozenBalance)); diff --git a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java index c235de57a3a..8ac20aa5e66 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java @@ -61,6 +61,8 @@ public class UnDelegateResourceActuatorTest { @BeforeClass public static void init() { dbManager = context.getBean(Manager.class); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); } /** diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java index f174dbb782f..004a9476ff1 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java @@ -64,10 +64,8 @@ public class UnfreezeBalanceV2ActuatorTest { @BeforeClass public static void init() { dbManager = context.getBean(Manager.class); - // Args.setParam(new String[]{"--output-directory", dbPath}, - // "config-junit.conf"); - // dbManager = new Manager(); - // dbManager.init(); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); } /** diff --git a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java index e9dc144b0d1..455c8ba8a92 100644 --- a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java @@ -15,10 +15,8 @@ import org.junit.BeforeClass; import org.junit.Test; import org.tron.common.application.TronApplicationContext; -import org.tron.common.args.Witness; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; -import org.tron.common.utils.StringUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; @@ -62,6 +60,8 @@ public class WithdrawExpireUnfreezeActuatorTest { @BeforeClass public static void init() { dbManager = context.getBean(Manager.class); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); } /** @@ -133,7 +133,6 @@ public void testWithdrawExpireUnfreeze() { Assert.assertEquals(Long.MAX_VALUE, unfrozenV2List.get(0).getUnfreezeExpireTime()); Assert.assertEquals(initBalance + 32_000_000L, owner.getBalance()); Assert.assertEquals(0, owner.getAllowance()); - Assert.assertNotEquals(0, owner.getLatestWithdrawTime()); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 194a0d95a74..67427214477 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -192,6 +192,8 @@ message Account { // the identity of this account, case insensitive bytes account_id = 23; + int64 net_window_size = 24; + message AccountResource { // energy resource, get from frozen int64 energy_usage = 1; @@ -209,6 +211,7 @@ message Account { int64 storage_usage = 7; int64 latest_exchange_storage_time = 8; + int64 energy_window_size = 9; } AccountResource account_resource = 26; bytes codeHash = 30; From adc933c1c81156733258009bc5071314f31b2500 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Thu, 20 Oct 2022 15:05:37 +0800 Subject: [PATCH 0337/1197] feat(freezeV2): optimize PrecompiledContracts energy cost --- .../org/tron/core/vm/PrecompiledContracts.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 6d009cc94ef..419d94f5c0a 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -1875,7 +1875,7 @@ public static class AvailableUnfreezeV2Size extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { - return 100; + return 50; } @Override @@ -1895,7 +1895,7 @@ public static class UnfreezableBalanceV2 extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { - return 100; + return 50; } @Override @@ -1917,7 +1917,7 @@ public static class ExpireUnfreezeBalanceV2 extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { - return 100; + return 50; } @Override @@ -1949,7 +1949,7 @@ public static class DelegatableResource extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { - return 100; + return 50; } @Override @@ -1971,7 +1971,7 @@ public static class ResourceV2 extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { - return 100; + return 50; } @Override @@ -1999,7 +1999,7 @@ public static class CheckUnDelegateResource extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { - return 100; + return 50; } @Override @@ -2026,7 +2026,7 @@ public static class ResourceUsage extends PrecompiledContract { @Override public long getEnergyForData(byte[] data) { - return 100; + return 50; } @Override From 7a2e67d7b198f596c0a589ae12f266c7a2305b56 Mon Sep 17 00:00:00 2001 From: Liulei Date: Thu, 20 Oct 2022 16:17:55 +0800 Subject: [PATCH 0338/1197] feat(freezeV2): optimize freezeV2 test --- .../org/tron/core/vm/program/Program.java | 4 + .../tron/common/runtime/vm/FreezeV2Test.java | 235 +++++++++--------- 2 files changed, 128 insertions(+), 111 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index b9a3d13da17..721f299e17f 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -2030,6 +2030,8 @@ private Common.ResourceCode parseResourceCode(DataWord resourceType) { return Common.ResourceCode.BANDWIDTH; case 1: return Common.ResourceCode.ENERGY; + case 2: + return Common.ResourceCode.TRON_POWER; default: return Common.ResourceCode.UNRECOGNIZED; } @@ -2041,6 +2043,8 @@ private String convertResourceToString(DataWord resourceType) { return "Bandwidth"; case 1: return "Energy"; + case 2: + return "TronPower"; default: return "UnknownType"; } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java index 6c2a6af45e9..8e8d912929c 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -51,7 +51,7 @@ public class FreezeV2Test { private static final String FREEZE_V2_CODE = - "60806040526111a6806100136000396000f3fe608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b50600436106101245760003560e01c80633dcba6fc116100bc578063a1243ded1161008b578063a1243ded1461030f578063a465bb191461033f578063b335634e1461035d578063c1a98a371461038d578063c8115bb7146103bd57610124565b80633dcba6fc146102715780635f5437741461028f57806385510c71146102bf5780639eb506e2146102df57610124565b80632fe36be5116100f85780632fe36be5146101c35780633160a6fc146101df57806333e7645d1461020f578063350a02341461023f57610124565b8062a73f7b14610129578063089480871461015b57806308bee6c414610177578063236051ed14610193575b600080fd5b610143600480360381019061013e9190610c73565b6103ee565b60405161015293929190610cd5565b60405180910390f35b61017560048036038101906101709190610d55565b610470565b005b610191600480360381019061018c9190610da8565b6104dc565b005b6101ad60048036038101906101a89190610de8565b61052e565b6040516101ba9190610e28565b60405180910390f35b6101dd60048036038101906101d89190610da8565b6105a4565b005b6101f960048036038101906101f49190610e43565b6105f6565b6040516102069190610e28565b60405180910390f35b61022960048036038101906102249190610de8565b610669565b6040516102369190610e28565b60405180910390f35b61025960048036038101906102549190610d55565b6106df565b60405161026893929190610cd5565b60405180910390f35b610279610760565b6040516102869190610e28565b60405180910390f35b6102a960048036038101906102a49190610e70565b61079f565b6040516102b69190610e28565b60405180910390f35b6102c76107fb565b6040516102d693929190610cd5565b60405180910390f35b6102f960048036038101906102f49190610de8565b610918565b6040516103069190610e28565b60405180910390f35b61032960048036038101906103249190610de8565b61098e565b6040516103369190610e28565b60405180910390f35b610347610a04565b6040516103549190610e28565b60405180910390f35b61037760048036038101906103729190610e9d565b610a43565b6040516103849190610e28565b60405180910390f35b6103a760048036038101906103a29190610de8565b610abc565b6040516103b49190610e28565b60405180910390f35b6103d760048036038101906103d29190610e9d565b610b32565b6040516103e5929190610ef0565b60405180910390f35b60008060008573ffffffffffffffffffffffffffffffffffffffff16630100001190868660405161042193929190610f28565b606060405180830381855afa15801561043e573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906104619190610f74565b92509250925093509350939050565b8073ffffffffffffffffffffffffffffffffffffffff168383de15801561049b573d6000803e3d6000fd5b507f025526dfa15721b77133358f4ef9591e878434240705071b580f0f8f955153be8383836040516104cf93929190611026565b60405180910390a1505050565b8181da1580156104f0573d6000803e3d6000fd5b507fc20c50cd22b066cd9d0cbbe9adbdee2f66da283d9971f5ff840fb01af79d98088282604051610522929190610ef0565b60405180910390a15050565b60008273ffffffffffffffffffffffffffffffffffffffff166301000014908360405161055c92919061105d565b602060405180830381855afa158015610579573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061059c9190611086565b905092915050565b8181db1580156105b8573d6000803e3d6000fd5b507fa2339ebec95cc02eea0ca9e15e5b1b4dd568105de8c4e47d2c6b96b1969348e882826040516105ea929190610ef0565b60405180910390a15050565b60008173ffffffffffffffffffffffffffffffffffffffff16630100000c9060405161062291906110b3565b602060405180830381855afa15801561063f573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906106629190611086565b9050919050565b60008273ffffffffffffffffffffffffffffffffffffffff16630100000f908360405161069792919061105d565b602060405180830381855afa1580156106b4573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906106d79190611086565b905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff168686df15801561070f573d6000803e3d6000fd5b508093508194508295505050507f42fddce307cf00fa55a23fcc80c1d2ba08ddce9776bbced3d1657321ed2b7bbe86868660405161074f93929190611026565b60405180910390a193509350939050565b6000dc90507f6f00343c17c6cb3178a14fe2a1b401a5ebaede910e21ee237af268c641450153816040516107949190610e28565b60405180910390a190565b6000630100000e826040516107b49190610e28565b602060405180830381855afa1580156107d1573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906107f49190611086565b9050919050565b600080600080600160405181601f820153602081602083630100000b5afa610829576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff8316831461084a57600080fd5b50506000600260405181601f820153602081602083630100000b5afa610876576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff8316831461089757600080fd5b50506000600360405181601f820153602081602083630100000b5afa6108c3576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff831683146108e457600080fd5b50508267ffffffffffffffff1692508167ffffffffffffffff1691508067ffffffffffffffff169050925092509250909192565b60008273ffffffffffffffffffffffffffffffffffffffff166301000013908360405161094692919061105d565b602060405180830381855afa158015610963573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906109869190611086565b905092915050565b60008273ffffffffffffffffffffffffffffffffffffffff16630100000d90836040516109bc92919061105d565b602060405180830381855afa1580156109d9573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906109fc9190611086565b905092915050565b6000dd90507f6a5f656ed489ef1dec34a7317ceb95e7363440f72efdb653107e66982370f06181604051610a389190610e28565b60405180910390a190565b60008373ffffffffffffffffffffffffffffffffffffffff166301000010908484604051610a73939291906110ce565b602060405180830381855afa158015610a90573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610ab39190611086565b90509392505050565b60008273ffffffffffffffffffffffffffffffffffffffff1663010000159083604051610aea92919061105d565b602060405180830381855afa158015610b07573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610b2a9190611086565b905092915050565b6000808473ffffffffffffffffffffffffffffffffffffffff166301000012908585604051610b63939291906110ce565b6040805180830381855afa158015610b7f573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610ba29190611105565b91509150935093915050565b600080fd5b600074ffffffffffffffffffffffffffffffffffffffffff82169050919050565b610bdd81610bb3565b8114610be857600080fd5b50565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610c1682610beb565b9050919050565b600081359050610c2c81610bd4565b610c3581610c0b565b905092915050565b6000819050919050565b610c5081610c3d565b8114610c5b57600080fd5b50565b600081359050610c6d81610c47565b92915050565b600080600060608486031215610c8c57610c8b610bae565b5b6000610c9a86828701610c1d565b9350506020610cab86828701610c5e565b9250506040610cbc86828701610c5e565b9150509250925092565b610ccf81610c3d565b82525050565b6000606082019050610cea6000830186610cc6565b610cf76020830185610cc6565b610d046040830184610cc6565b949350505050565b610d1581610bb3565b8114610d2057600080fd5b50565b6000610d2e82610beb565b9050919050565b600081359050610d4481610d0c565b610d4d81610d23565b905092915050565b600080600060608486031215610d6e57610d6d610bae565b5b6000610d7c86828701610c5e565b9350506020610d8d86828701610c5e565b9250506040610d9e86828701610d35565b9150509250925092565b60008060408385031215610dbf57610dbe610bae565b5b6000610dcd85828601610c5e565b9250506020610dde85828601610c5e565b9150509250929050565b60008060408385031215610dff57610dfe610bae565b5b6000610e0d85828601610c1d565b9250506020610e1e85828601610c5e565b9150509250929050565b6000602082019050610e3d6000830184610cc6565b92915050565b600060208284031215610e5957610e58610bae565b5b6000610e6784828501610c1d565b91505092915050565b600060208284031215610e8657610e85610bae565b5b6000610e9484828501610c5e565b91505092915050565b600080600060608486031215610eb657610eb5610bae565b5b6000610ec486828701610c1d565b9350506020610ed586828701610c1d565b9250506040610ee686828701610c5e565b9150509250925092565b6000604082019050610f056000830185610cc6565b610f126020830184610cc6565b9392505050565b610f2281610c0b565b82525050565b6000606082019050610f3d6000830186610f19565b610f4a6020830185610cc6565b610f576040830184610cc6565b949350505050565b600081519050610f6e81610c47565b92915050565b600080600060608486031215610f8d57610f8c610bae565b5b6000610f9b86828701610f5f565b9350506020610fac86828701610f5f565b9250506040610fbd86828701610f5f565b9150509250925092565b6000819050919050565b6000610fec610fe7610fe284610beb565b610fc7565b610beb565b9050919050565b6000610ffe82610fd1565b9050919050565b600061101082610ff3565b9050919050565b61102081611005565b82525050565b600060608201905061103b6000830186610cc6565b6110486020830185610cc6565b6110556040830184611017565b949350505050565b60006040820190506110726000830185610f19565b61107f6020830184610cc6565b9392505050565b60006020828403121561109c5761109b610bae565b5b60006110aa84828501610f5f565b91505092915050565b60006020820190506110c86000830184610f19565b92915050565b60006060820190506110e36000830186610f19565b6110f06020830185610f19565b6110fd6040830184610cc6565b949350505050565b6000806040838503121561111c5761111b610bae565b5b600061112a85828601610f5f565b925050602061113b85828601610f5f565b915050925092905056fea26474726f6e58221220cd9e546d3bedc2f439b615ab724a0cb6f44e676c635038b29a20a7f3c712c64f64736f6c63782d302e382e31372d646576656c6f702e323032322e31302e31392b636f6d6d69742e34313134656332632e6d6f64005e"; + "6080604052610aa0806100136000396000f3fe608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b50600436106101255760003560e01c806385510c71116100bc578063c1a98a371161008b578063c1a98a371461021d578063c8115bb714610230578063df860ab314610258578063f0130dc91461026b578063f70eb4c51461027e57600080fd5b806385510c71146101cc5780639eb506e2146101ef578063a465bb1914610202578063b335634e1461020a57600080fd5b806333e7645d116100f857806333e7645d1461018b578063350a02341461019e5780633dcba6fc146101b157806358974547146101b957600080fd5b8063089480871461012a57806308bee6c41461013f578063236051ed146101525780632fe36be514610178575b600080fd5b61013d610138366004610881565b610291565b005b61013d61014d3660046108c4565b610302565b6101656101603660046108e6565b610355565b6040519081526020015b60405180910390f35b61013d6101863660046108c4565b6103be565b6101656101993660046108e6565b610409565b61013d6101ac366004610881565b61042f565b61013d610497565b6101656101c73660046108e6565b6104c4565b6101d46104ea565b6040805193845260208401929092529082015260600161016f565b6101656101fd3660046108e6565b6105f0565b610165610616565b61016561021836600461091b565b610657565b61016561022b3660046108e6565b6106c9565b61024361023e36600461091b565b6106ef565b6040805192835260208301919091520161016f565b6101d4610266366004610969565b610766565b6101656102793660046108e6565b6107e2565b61016561028c3660046109a7565b610808565b806001600160a01b03168383de1580156102af573d6000803e3d6000fd5b5060408051848152602081018490526001600160a01b038316918101919091527f025526dfa15721b77133358f4ef9591e878434240705071b580f0f8f955153be906060015b60405180910390a1505050565b8181da158015610316573d6000803e3d6000fd5b5060408051838152602081018390527fc20c50cd22b066cd9d0cbbe9adbdee2f66da283d9971f5ff840fb01af79d980891015b60405180910390a15050565b604080516001600160a01b038416815260208101839052600091630100001491015b602060405180830381855afa158015610394573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906103b791906109d4565b9392505050565b8181db1580156103d2573d6000803e3d6000fd5b5060408051838152602081018390527fa2339ebec95cc02eea0ca9e15e5b1b4dd568105de8c4e47d2c6b96b1969348e89101610349565b604080516001600160a01b038416815260208101839052600091630100000f9101610377565b806001600160a01b03168383df15801561044d573d6000803e3d6000fd5b5060408051848152602081018490526001600160a01b038316918101919091527f42fddce307cf00fa55a23fcc80c1d2ba08ddce9776bbced3d1657321ed2b7bbe906060016102f5565bdc506040517f2ba20738f2500f7585581bf668aa65ab6de7d1c1822de5737455214184f37ed590600090a1565b604080516001600160a01b038416815260208101839052600091630100000e9101610377565b600080600080600160405181601f820153602081602083630100000b5afa610518576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff8316831461053957600080fd5b50506000600260405181601f820153602081602083630100000b5afa610565576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff8316831461058657600080fd5b50506000600360405181601f820153602081602083630100000b5afa6105b2576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff831683146105d357600080fd5b505067ffffffffffffffff92831696918316955090911692509050565b604080516001600160a01b03841681526020810183905260009163010000139101610377565b6000dd90507f6a5f656ed489ef1dec34a7317ceb95e7363440f72efdb653107e66982370f0618160405161064c91815260200190565b60405180910390a190565b604080516001600160a01b03808616825284166020820152908101829052600090630100001090606001602060405180830381855afa15801561069e573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906106c191906109d4565b949350505050565b604080516001600160a01b03841681526020810183905260009163010000159101610377565b604080516001600160a01b0380861682528416602082015290810182905260009081906301000012906060016040805180830381855afa158015610737573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061075a91906109ed565b91509150935093915050565b604080516001600160a01b03851681526020810184905290810182905260009081908190630100001190606001606060405180830381855afa1580156107b0573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906107d39190610a11565b92509250925093509350939050565b604080516001600160a01b038416815260208101839052600091630100000d9101610377565b6040516001600160a01b0382168152600090630100000c90602001602060405180830381855afa158015610840573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061086391906109d4565b92915050565b6001600160a81b038116811461087e57600080fd5b50565b60008060006060848603121561089657600080fd5b833592506020840135915060408401356108af81610869565b9295919450506001600160a01b039091169150565b600080604083850312156108d757600080fd5b50508035926020909101359150565b600080604083850312156108f957600080fd5b823561090481610869565b6001600160a01b0316946020939093013593505050565b60008060006060848603121561093057600080fd5b833561093b81610869565b6001600160a01b03908116935060208501359061095782610869565b93969316945050506040919091013590565b60008060006060848603121561097e57600080fd5b833561098981610869565b6001600160a01b031695602085013595506040909401359392505050565b6000602082840312156109b957600080fd5b81356109c481610869565b6001600160a01b03169392505050565b6000602082840312156109e657600080fd5b5051919050565b60008060408385031215610a0057600080fd5b505080516020909101519092909150565b600080600060608486031215610a2657600080fd5b835192506020840151915060408401519050925092509256fea26474726f6e5822122060a7d93c8ee9065ccd63ad4b97b050e98fb1394a4d6c66c5223273f96fbe4ffd64736f6c63782d302e382e31372d646576656c6f702e323032322e31302e32302b636f6d6d69742e34313134656332632e6d6f64005e"; private static final long value = 100_000_000_000_000_000L; private static final long fee = 1_000_000_000; @@ -198,8 +198,8 @@ private TVMTestResult triggerUnDelegateResource( } @Test - public void testFreezeUnfreezeWithdrawAndCancel() throws Exception { - byte[] contract = deployContract("TestNewFreeze", FREEZE_V2_CODE); + public void testFreezeV2Operations() throws Exception { + byte[] contract = deployContract("TestFreezeV2", FREEZE_V2_CODE); long frozenBalance = 1_000_000; // trigger freezeBalanceV2(uint256,uint256) to get bandwidth @@ -209,6 +209,8 @@ public void testFreezeUnfreezeWithdrawAndCancel() throws Exception { freezeV2(owner, contract, frozenBalance, 1); // trigger freezeBalanceV2(uint256,uint256) to get tp + freezeV2WithException(owner, contract, frozenBalance, 2); + manager.getDynamicPropertiesStore().saveAllowNewResourceModel(1); freezeV2(owner, contract, frozenBalance, 2); // tests of freezeBalanceV2(uint256,uint256) with invalid args @@ -218,17 +220,11 @@ public void testFreezeUnfreezeWithdrawAndCancel() throws Exception { freezeV2WithException(owner, contract, frozenBalance - 1, 1); freezeV2WithException(owner, contract, value, 0); - // not time to unfreeze - unfreezeV2WithException(owner, contract, frozenBalance, 0); - unfreezeV2WithException(owner, contract, frozenBalance, 1); - unfreezeV2WithException(owner, contract, frozenBalance, 2); // invalid args unfreezeV2WithException(owner, contract, frozenBalance, 3); unfreezeV2WithException(owner, contract, -frozenBalance, 2); unfreezeV2WithException(owner, contract, 0, 2); - clearExpireTime(contract); - // unfreeze unfreezeV2(owner, contract, frozenBalance, 0); unfreezeV2(owner, contract, frozenBalance, 1); @@ -239,17 +235,17 @@ public void testFreezeUnfreezeWithdrawAndCancel() throws Exception { unfreezeV2WithException(owner, contract, frozenBalance, 2); // withdrawExpireUnfreeze - withdrawExpireUnfreezeWithException(owner, contract); - clearUnfreezeV2ExpireTime(contract, 0); - withdrawExpireUnfreeze(owner, contract, frozenBalance); - - withdrawExpireUnfreezeWithException(owner, contract); - clearUnfreezeV2ExpireTime(contract, 1); - withdrawExpireUnfreeze(owner, contract, frozenBalance); - - withdrawExpireUnfreezeWithException(owner, contract); - clearUnfreezeV2ExpireTime(contract, 2); - withdrawExpireUnfreeze(owner, contract, frozenBalance); +// withdrawExpireUnfreezeWithException(owner, contract); +// clearUnfreezeV2ExpireTime(contract, 0); +// withdrawExpireUnfreeze(owner, contract, frozenBalance); +// +// withdrawExpireUnfreezeWithException(owner, contract); +// clearUnfreezeV2ExpireTime(contract, 1); +// withdrawExpireUnfreeze(owner, contract, frozenBalance); +// +// withdrawExpireUnfreezeWithException(owner, contract); +// clearUnfreezeV2ExpireTime(contract, 2); +// withdrawExpireUnfreeze(owner, contract, frozenBalance); // cancelAllUnfreezeV2 // freezeV2(owner, contract, frozenBalance, 0); @@ -260,8 +256,8 @@ public void testFreezeUnfreezeWithdrawAndCancel() throws Exception { } @Test - public void testDelegateAndUnDelegateResource() throws Exception { - byte[] contract = deployContract("TestNewFreeze", FREEZE_V2_CODE); + public void testDelegateResourceOperations() throws Exception { + byte[] contract = deployContract("TestFreezeV2", FREEZE_V2_CODE); long frozenBalance = 1_000_000; // trigger freezeBalanceV2(uint256,uint256) to get bandwidth freezeV2(owner, contract, frozenBalance, 0); @@ -269,6 +265,13 @@ public void testDelegateAndUnDelegateResource() throws Exception { freezeV2(owner, contract, frozenBalance, 1); // trigger freezeBalanceV2(uint256,uint256) to get tp freezeV2(owner, contract, frozenBalance, 2); +// +// delegateResourceWithException(owner, contract, userA, frozenBalance, 0); +// rootRepository.createAccount(userA, Protocol.AccountType.Normal); +// rootRepository.commit(); +// delegateResourceWithException(owner, contract, userA, 0, 0); +// delegateResourceWithException(owner, contract, userA, frozenBalance * 2, 0); +// delegateResourceWithException(owner, contract, userA, frozenBalance, 3); } private TVMTestResult freezeV2( @@ -276,36 +279,44 @@ private TVMTestResult freezeV2( DynamicPropertiesStore dynamicStore = manager.getDynamicPropertiesStore(); long oldTotalNetWeight = dynamicStore.getTotalNetWeight(); long oldTotalEnergyWeight = dynamicStore.getTotalEnergyWeight(); + long oldTronPowerWeight = dynamicStore.getTotalTronPowerWeight(); AccountStore accountStore = manager.getAccountStore(); AccountCapsule oldOwner = accountStore.get(contractAddr); - TVMTestResult result = triggerFreeze(callerAddr, contractAddr, frozenBalance, res, - SUCCESS, - returnValue -> Assert.assertEquals(dynamicStore.getMinFrozenTime() * FROZEN_PERIOD, - new DataWord(returnValue).longValue() * 1000)); + TVMTestResult result = + triggerFreeze(callerAddr, contractAddr, frozenBalance, res, SUCCESS, null); AccountCapsule newOwner = accountStore.get(contractAddr); Assert.assertEquals(oldOwner.getBalance() - frozenBalance, newOwner.getBalance()); newOwner.setBalance(oldOwner.getBalance()); if (res == 0) { - Assert.assertEquals(1, newOwner.getFrozenCount()); - Assert.assertEquals(oldOwner.getFrozenBalance() + frozenBalance, newOwner.getFrozenBalance()); - Assert.assertEquals(oldTotalNetWeight + frozenBalance / TRX_PRECISION, - dynamicStore.getTotalNetWeight()); + Assert.assertEquals( + oldOwner.getFrozenV2BalanceForBandwidth() + frozenBalance, + newOwner.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals( + oldTotalNetWeight + frozenBalance / TRX_PRECISION, dynamicStore.getTotalNetWeight()); Assert.assertEquals(oldTotalEnergyWeight, dynamicStore.getTotalEnergyWeight()); - oldOwner.setFrozenForBandwidth(0, 0); - newOwner.setFrozenForBandwidth(0, 0); - } else { - Assert.assertEquals(oldOwner.getEnergyFrozenBalance() + frozenBalance, - newOwner.getEnergyFrozenBalance()); + Assert.assertEquals(oldTronPowerWeight, dynamicStore.getTotalTronPowerWeight()); + } else if (res == 1) { + Assert.assertEquals( + oldOwner.getFrozenV2BalanceForEnergy() + frozenBalance, + newOwner.getFrozenV2BalanceForEnergy()); Assert.assertEquals(oldTotalNetWeight, dynamicStore.getTotalNetWeight()); - Assert.assertEquals(oldTotalEnergyWeight + frozenBalance / TRX_PRECISION, + Assert.assertEquals(oldTronPowerWeight, dynamicStore.getTotalTronPowerWeight()); + Assert.assertEquals( + oldTotalEnergyWeight + frozenBalance / TRX_PRECISION, dynamicStore.getTotalEnergyWeight()); - oldOwner.setFrozenForEnergy(0, 0); - newOwner.setFrozenForEnergy(0, 0); + } else { + Assert.assertEquals( + oldOwner.getTronPowerFrozenV2Balance() + frozenBalance, + newOwner.getTronPowerFrozenV2Balance()); + Assert.assertEquals(oldTotalNetWeight, dynamicStore.getTotalNetWeight()); + Assert.assertEquals(oldTotalEnergyWeight, dynamicStore.getTotalEnergyWeight()); + Assert.assertEquals( + oldTronPowerWeight + frozenBalance / TRX_PRECISION, + dynamicStore.getTotalTronPowerWeight()); } - Assert.assertArrayEquals(oldOwner.getData(), newOwner.getData()); return result; } @@ -320,50 +331,48 @@ private TVMTestResult unfreezeV2WithException( return triggerUnfreeze(callerAddr, contractAddr, unfreezeBalance, res, REVERT, null); } - private void clearExpireTime(byte[] owner) { - AccountCapsule accountCapsule = manager.getAccountStore().get(owner); - long now = manager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); - accountCapsule.setFrozenForBandwidth(accountCapsule.getFrozenBalance(), now); - accountCapsule.setFrozenForEnergy(accountCapsule.getEnergyFrozenBalance(), now); - manager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); - } - private TVMTestResult unfreezeV2( byte[] callerAddr, byte[] contractAddr, long unfreezeBalance, long res) throws Exception { DynamicPropertiesStore dynamicStore = manager.getDynamicPropertiesStore(); long oldTotalNetWeight = dynamicStore.getTotalNetWeight(); long oldTotalEnergyWeight = dynamicStore.getTotalEnergyWeight(); + long oldTotalTronPowerWeight = dynamicStore.getTotalTronPowerWeight(); AccountStore accountStore = manager.getAccountStore(); AccountCapsule oldOwner = accountStore.get(contractAddr); - long frozenBalance = res == 0 ? oldOwner.getFrozenBalance() : oldOwner.getEnergyFrozenBalance(); + long frozenBalance; + if (res == 0) { + frozenBalance = oldOwner.getFrozenV2BalanceForBandwidth(); + } else if (res == 1) { + frozenBalance = oldOwner.getFrozenV2BalanceForEnergy(); + } else { + frozenBalance = oldOwner.getTronPowerFrozenV2Balance(); + } Assert.assertTrue(frozenBalance > 0); - TVMTestResult result = triggerUnfreeze(callerAddr, contractAddr, unfreezeBalance, res, SUCCESS, - returnValue -> - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001", - Hex.toHexString(returnValue))); + TVMTestResult result = + triggerUnfreeze(callerAddr, contractAddr, unfreezeBalance, res, SUCCESS, null); AccountCapsule newOwner = accountStore.get(contractAddr); - Assert.assertEquals(oldOwner.getBalance() + frozenBalance, newOwner.getBalance()); - oldOwner.setBalance(newOwner.getBalance()); if (res == 0) { - Assert.assertEquals(0, newOwner.getFrozenCount()); - Assert.assertEquals(0, newOwner.getFrozenBalance()); + Assert.assertEquals(0, newOwner.getFrozenV2BalanceForBandwidth()); Assert.assertEquals(oldTotalNetWeight - frozenBalance / TRX_PRECISION, dynamicStore.getTotalNetWeight()); Assert.assertEquals(oldTotalEnergyWeight, dynamicStore.getTotalEnergyWeight()); - oldOwner.setFrozenForBandwidth(0, 0); - newOwner.setFrozenForBandwidth(0, 0); - } else { - Assert.assertEquals(0, newOwner.getEnergyFrozenBalance()); + Assert.assertEquals(oldTotalTronPowerWeight, dynamicStore.getTotalTronPowerWeight()); + } else if (res == 1) { + Assert.assertEquals(0, newOwner.getFrozenV2BalanceForEnergy()); Assert.assertEquals(oldTotalNetWeight, dynamicStore.getTotalNetWeight()); + Assert.assertEquals(oldTotalTronPowerWeight, dynamicStore.getTotalTronPowerWeight()); Assert.assertEquals(oldTotalEnergyWeight - frozenBalance / TRX_PRECISION, dynamicStore.getTotalEnergyWeight()); - oldOwner.setFrozenForEnergy(0, 0); - newOwner.setFrozenForEnergy(0, 0); + } else { + Assert.assertEquals(0, newOwner.getTronPowerFrozenV2Balance()); + Assert.assertEquals(oldTotalEnergyWeight, dynamicStore.getTotalEnergyWeight()); + Assert.assertEquals(oldTotalNetWeight, dynamicStore.getTotalNetWeight()); + Assert.assertEquals(oldTotalTronPowerWeight - frozenBalance / TRX_PRECISION, + dynamicStore.getTotalTronPowerWeight()); } - Assert.assertArrayEquals(oldOwner.getData(), newOwner.getData()); return result; } @@ -430,53 +439,57 @@ private TVMTestResult cancelAllUnfreezeV2( return result; } -// private TVMTestResult delegateResource( -// byte[] callerAddr, byte[] contractAddr, long expectedWithdrawBalance) throws Exception { -// AccountStore accountStore = manager.getAccountStore(); -// AccountCapsule oldOwner = accountStore.get(contractAddr); -// long oldBalance = oldOwner.getBalance(); -// -// TVMTestResult result = triggerWithdrawExpireUnfreeze(callerAddr, contractAddr, SUCCESS, -// returnValue -> -// Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001", -// Hex.toHexString(returnValue))); -// -// AccountCapsule newOwner = accountStore.get(contractAddr); -// Assert.assertEquals(oldBalance + expectedWithdrawBalance, newOwner.getBalance()); -// oldOwner.setBalance(newOwner.getBalance()); -// Assert.assertArrayEquals(oldOwner.getData(), newOwner.getData()); -// -// return result; -// } -// -// private TVMTestResult delegateResourceWithException(byte[] callerAddr, byte[] contractAddr) -// throws Exception { -// return triggerDelegateResource(callerAddr, contractAddr, REVERT, null); -// } -// -// private TVMTestResult unDelegateResource( -// byte[] callerAddr, byte[] contractAddr, long expectedWithdrawBalance) throws Exception { -// AccountStore accountStore = manager.getAccountStore(); -// AccountCapsule oldOwner = accountStore.get(contractAddr); -// long oldBalance = oldOwner.getBalance(); -// -// TVMTestResult result = triggerWithdrawExpireUnfreeze(callerAddr, contractAddr, SUCCESS, -// returnValue -> -// Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001", -// Hex.toHexString(returnValue))); -// -// AccountCapsule newOwner = accountStore.get(contractAddr); -// Assert.assertEquals(oldBalance + expectedWithdrawBalance, newOwner.getBalance()); -// oldOwner.setBalance(newOwner.getBalance()); -// Assert.assertArrayEquals(oldOwner.getData(), newOwner.getData()); -// -// return result; -// } -// -// private TVMTestResult unDelegateResourceWithException(byte[] callerAddr, byte[] contractAddr) -// throws Exception { -// return triggerUnDelegateResource(callerAddr, contractAddr, REVERT, null); -// } + private TVMTestResult delegateResource( + byte[] callerAddr, byte[] contractAddr, byte[] receiverAddr, long amount, long res) + throws Exception { + AccountStore accountStore = manager.getAccountStore(); + AccountCapsule oldOwner = accountStore.get(contractAddr); + long oldBalance = oldOwner.getBalance(); + + TVMTestResult result = triggerWithdrawExpireUnfreeze(callerAddr, contractAddr, SUCCESS, + returnValue -> + Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001", + Hex.toHexString(returnValue))); + + AccountCapsule newOwner = accountStore.get(contractAddr); + oldOwner.setBalance(newOwner.getBalance()); + Assert.assertArrayEquals(oldOwner.getData(), newOwner.getData()); + + return result; + } + + private TVMTestResult delegateResourceWithException( + byte[] callerAddr, byte[] contractAddr, byte[] receiverAddr, long amount, long res) + throws Exception { + return triggerDelegateResource( + callerAddr, contractAddr, REVERT, null, receiverAddr, amount, res); + } + + private TVMTestResult unDelegateResource( + byte[] callerAddr, byte[] contractAddr, byte[] receiverAddr, long amount, long res) + throws Exception { + AccountStore accountStore = manager.getAccountStore(); + AccountCapsule oldOwner = accountStore.get(contractAddr); + long oldBalance = oldOwner.getBalance(); + + TVMTestResult result = triggerWithdrawExpireUnfreeze(callerAddr, contractAddr, SUCCESS, + returnValue -> + Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001", + Hex.toHexString(returnValue))); + + AccountCapsule newOwner = accountStore.get(contractAddr); + oldOwner.setBalance(newOwner.getBalance()); + Assert.assertArrayEquals(oldOwner.getData(), newOwner.getData()); + + return result; + } + + private TVMTestResult unDelegateResourceWithException( + byte[] callerAddr, byte[] contractAddr, byte[] receiverAddr, long amount, long res) + throws Exception { + return triggerUnDelegateResource( + callerAddr, contractAddr, REVERT, null, receiverAddr, amount, res); + } @After public void destroy() { @@ -490,4 +503,4 @@ public void destroy() { logger.error("Release resources failure."); } } -} +} \ No newline at end of file From 90fd6a7863390aa7a451767a758ca7ec73b022c8 Mon Sep 17 00:00:00 2001 From: Liulei Date: Thu, 20 Oct 2022 16:41:04 +0800 Subject: [PATCH 0339/1197] feat(freezeV2): optimize freezeV2 op code --- actuator/src/main/java/org/tron/core/vm/Op.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/Op.java b/actuator/src/main/java/org/tron/core/vm/Op.java index 50e95f19efe..557619f554b 100644 --- a/actuator/src/main/java/org/tron/core/vm/Op.java +++ b/actuator/src/main/java/org/tron/core/vm/Op.java @@ -238,10 +238,10 @@ public class Op { public static final int WITHDRAWREWARD = 0xd9; public static final int FREEZEBALANCEV2 = 0xda; public static final int UNFREEZEBALANCEV2 = 0xdb; - public static final int WITHDRAWEXPIREUNFREEZE = 0xdc; - public static final int DELEGATERESOURCE = 0xdd; - public static final int UNDELEGATERESOURCE = 0xde; - public static final int CANCELALLUNFREEZEV2 = 0xdf; + public static final int CANCELALLUNFREEZEV2 = 0xdc; + public static final int WITHDRAWEXPIREUNFREEZE = 0xdd; + public static final int DELEGATERESOURCE = 0xde; + public static final int UNDELEGATERESOURCE = 0xdf; // (0xf0) Create a new account with associated code public static final int CREATE = 0xf0; From f267f3f8cb9c119e3278c34461b1d01dafc32db3 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Thu, 20 Oct 2022 16:49:27 +0800 Subject: [PATCH 0340/1197] feat(freezeV2): optimize queryExpireUnfreezeBalanceV2 time params --- .../main/java/org/tron/core/vm/program/ContractState.java | 5 +++++ .../main/java/org/tron/core/vm/repository/Repository.java | 2 ++ .../java/org/tron/core/vm/repository/RepositoryImpl.java | 7 +++++-- .../src/main/java/org/tron/core/vm/utils/FreezeV2Util.java | 4 +++- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java index 5ead8fda7c8..b961dca86de 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java +++ b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java @@ -369,4 +369,9 @@ public long getHeadSlot() { return repository.getHeadSlot(); } + @Override + public long getSlotByTimestampMs(long timestamp) { + return repository.getSlotByTimestampMs(timestamp); + } + } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java index 410742c02fb..87b869a9330 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java @@ -138,4 +138,6 @@ public interface Repository { long getHeadSlot(); + long getSlotByTimestampMs(long timestamp); + } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 84ae48637d4..b35be0d4f15 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -796,8 +796,11 @@ public long calculateGlobalEnergyLimit(AccountCapsule accountCapsule) { } public long getHeadSlot() { - return (getDynamicPropertiesStore().getLatestBlockHeaderTimestamp() - - Long.parseLong(CommonParameter.getInstance() + return getSlotByTimestampMs(getDynamicPropertiesStore().getLatestBlockHeaderTimestamp()); + } + + public long getSlotByTimestampMs(long timestamp) { + return (timestamp - Long.parseLong(CommonParameter.getInstance() .getGenesisBlock().getTimestamp())) / BLOCK_PRODUCED_INTERVAL; } diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index 2da14360a78..031be7ba0e9 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -22,6 +22,8 @@ public static long queryExpireUnfreezeBalanceV2(byte[] address, long time, Repos return 0; } + // time should be transferred to slot. + long slot = repository.getSlotByTimestampMs(time); AccountCapsule accountCapsule = repository.getAccount(address); if (accountCapsule == null) { return 0; @@ -30,7 +32,7 @@ public static long queryExpireUnfreezeBalanceV2(byte[] address, long time, Repos List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); - return getTotalWithdrawUnfreeze(unfrozenV2List, time); + return getTotalWithdrawUnfreeze(unfrozenV2List, slot); } public static long queryUnfreezableBalanceV2(byte[] address, long type, Repository repository) { From 65d1f146126ef9054532eaaa3f8edcf3ef17f8f2 Mon Sep 17 00:00:00 2001 From: Liulei Date: Thu, 20 Oct 2022 18:49:00 +0800 Subject: [PATCH 0341/1197] feat(freezeV2): add freezeV2 unit test --- .../UnDelegateResourceProcessor.java | 6 +- .../tron/common/runtime/vm/FreezeV2Test.java | 157 ++++++++++++------ 2 files changed, 107 insertions(+), 56 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index 52650864e53..f9e4e64acb2 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -91,7 +91,7 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont } } - public Triple execute (UnDelegateResourceParam param, Repository repo) { + public Triple execute(UnDelegateResourceParam param, Repository repo) { byte[] ownerAddress = param.getOwnerAddress(); byte[] receiverAddress = param.getReceiverAddress(); long unDelegateBalance = param.getUnDelegateBalance(); @@ -99,7 +99,7 @@ public Triple execute (UnDelegateResourceParam param, Reposito AccountCapsule receiverCapsule = repo.getAccount(receiverAddress); DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); - Triple unDelegateResourceIndo = + Triple unDelegateResourceInfo = FreezeV2Util.checkUndelegateResource( receiverAddress, unDelegateBalance, param.getResourceType().getNumber(), repo); @@ -197,6 +197,6 @@ public Triple execute (UnDelegateResourceParam param, Reposito } repo.updateDelegatedResource(key, delegatedResourceCapsule); repo.updateAccount(ownerCapsule.createDbKey(), ownerCapsule); - return unDelegateResourceIndo; + return unDelegateResourceInfo; } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java index 8e8d912929c..1711af9896c 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -1,9 +1,9 @@ package org.tron.common.runtime.vm; -import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import static org.tron.protos.Protocol.Transaction.Result.contractResult.REVERT; import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import com.google.protobuf.ByteString; import java.io.File; @@ -11,7 +11,6 @@ import java.util.Arrays; import java.util.List; import java.util.function.Consumer; -import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; @@ -31,12 +30,14 @@ import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; import org.tron.core.db.TransactionTrace; import org.tron.core.store.AccountStore; +import org.tron.core.store.DelegatedResourceStore; import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.store.StoreFactory; import org.tron.core.vm.config.ConfigLoader; @@ -83,6 +84,9 @@ public void init() throws Exception { ConfigLoader.disable = true; manager.getDynamicPropertiesStore().saveAllowTvmFreeze(1); + manager.getDynamicPropertiesStore().saveUnfreezeDelayDays(30); + manager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + manager.getDynamicPropertiesStore().saveAllowDelegateResource(1); VMConfig.initVmHardFork(true); VMConfig.initAllowTvmTransferTrc10(1); VMConfig.initAllowTvmConstantinople(1); @@ -185,7 +189,7 @@ private TVMTestResult triggerDelegateResource( throws Exception { return triggerContract( callerAddr, contractAddr, fee, expectedResult, check, - "delegateResource(uint,uint,address)", amount, res, receiverAddr); + "delegateResource(uint256,uint256,address)", amount, res, StringUtil.encode58Check(receiverAddr)); } private TVMTestResult triggerUnDelegateResource( @@ -194,7 +198,7 @@ private TVMTestResult triggerUnDelegateResource( throws Exception { return triggerContract( callerAddr, contractAddr, fee, expectedResult, check, - "unDelegateResource(uint,uint,address)", amount, res, receiverAddr); + "unDelegateResource(uint256,uint256,address)", amount, res, StringUtil.encode58Check(receiverAddr)); } @Test @@ -209,8 +213,6 @@ public void testFreezeV2Operations() throws Exception { freezeV2(owner, contract, frozenBalance, 1); // trigger freezeBalanceV2(uint256,uint256) to get tp - freezeV2WithException(owner, contract, frozenBalance, 2); - manager.getDynamicPropertiesStore().saveAllowNewResourceModel(1); freezeV2(owner, contract, frozenBalance, 2); // tests of freezeBalanceV2(uint256,uint256) with invalid args @@ -235,17 +237,17 @@ public void testFreezeV2Operations() throws Exception { unfreezeV2WithException(owner, contract, frozenBalance, 2); // withdrawExpireUnfreeze -// withdrawExpireUnfreezeWithException(owner, contract); -// clearUnfreezeV2ExpireTime(contract, 0); -// withdrawExpireUnfreeze(owner, contract, frozenBalance); -// -// withdrawExpireUnfreezeWithException(owner, contract); -// clearUnfreezeV2ExpireTime(contract, 1); -// withdrawExpireUnfreeze(owner, contract, frozenBalance); -// -// withdrawExpireUnfreezeWithException(owner, contract); -// clearUnfreezeV2ExpireTime(contract, 2); -// withdrawExpireUnfreeze(owner, contract, frozenBalance); + withdrawExpireUnfreeze(owner, contract, 0); + clearUnfreezeV2ExpireTime(contract, 0); + withdrawExpireUnfreeze(owner, contract, frozenBalance); + + withdrawExpireUnfreeze(owner, contract, 0); + clearUnfreezeV2ExpireTime(contract, 1); + withdrawExpireUnfreeze(owner, contract, frozenBalance); + + withdrawExpireUnfreeze(owner, contract, 0); + clearUnfreezeV2ExpireTime(contract, 2); + withdrawExpireUnfreeze(owner, contract, frozenBalance); // cancelAllUnfreezeV2 // freezeV2(owner, contract, frozenBalance, 0); @@ -265,13 +267,31 @@ public void testDelegateResourceOperations() throws Exception { freezeV2(owner, contract, frozenBalance, 1); // trigger freezeBalanceV2(uint256,uint256) to get tp freezeV2(owner, contract, frozenBalance, 2); -// -// delegateResourceWithException(owner, contract, userA, frozenBalance, 0); -// rootRepository.createAccount(userA, Protocol.AccountType.Normal); -// rootRepository.commit(); -// delegateResourceWithException(owner, contract, userA, 0, 0); -// delegateResourceWithException(owner, contract, userA, frozenBalance * 2, 0); -// delegateResourceWithException(owner, contract, userA, frozenBalance, 3); + + delegateResourceWithException(owner, contract, userA, frozenBalance, 0); + rootRepository.createAccount(userA, Protocol.AccountType.Normal); + rootRepository.commit(); + delegateResourceWithException(owner, contract, userA, 0, 0); + delegateResourceWithException(owner, contract, userA, frozenBalance * 2, 0); + delegateResourceWithException(owner, contract, userA, frozenBalance, 2); + delegateResourceWithException(owner, contract, userA, frozenBalance, 3); + delegateResourceWithException(owner, contract, contract, frozenBalance, 0); + + delegateResource(owner, contract, userA, frozenBalance, 0); + delegateResource(owner, contract, userA, frozenBalance, 1); + + // unDelegate + unDelegateResourceWithException(owner, contract, userA, frozenBalance, 2); + unDelegateResourceWithException(owner, contract, userA, frozenBalance, 3); + rootRepository.createAccount(userB, Protocol.AccountType.Normal); + rootRepository.commit(); + unDelegateResourceWithException(owner, contract, userB, frozenBalance, 0); + unDelegateResourceWithException(owner, contract, contract, frozenBalance, 0); + delegateResourceWithException(owner, contract, userA, frozenBalance * 2, 0); + delegateResourceWithException(owner, contract, userA, 0, 0); + +// unDelegateResource(owner, contract, userA, frozenBalance, 0); +// unDelegateResource(owner, contract, userA, frozenBalance, 1); } private TVMTestResult freezeV2( @@ -399,24 +419,18 @@ private TVMTestResult withdrawExpireUnfreeze( AccountCapsule oldOwner = accountStore.get(contractAddr); long oldBalance = oldOwner.getBalance(); - TVMTestResult result = triggerWithdrawExpireUnfreeze(callerAddr, contractAddr, SUCCESS, - returnValue -> - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001", - Hex.toHexString(returnValue))); + TVMTestResult result = triggerWithdrawExpireUnfreeze(callerAddr, contractAddr, SUCCESS, null); AccountCapsule newOwner = accountStore.get(contractAddr); Assert.assertEquals(oldBalance + expectedWithdrawBalance, newOwner.getBalance()); oldOwner.setBalance(newOwner.getBalance()); + oldOwner.clearUnfrozenV2(); + newOwner.getUnfrozenV2List().forEach(oldOwner::addUnfrozenV2); Assert.assertArrayEquals(oldOwner.getData(), newOwner.getData()); return result; } - private TVMTestResult withdrawExpireUnfreezeWithException(byte[] callerAddr, byte[] contractAddr) - throws Exception { - return triggerWithdrawExpireUnfreeze(callerAddr, contractAddr, REVERT, null); - } - private TVMTestResult cancelAllUnfreezeV2( byte[] callerAddr, byte[] contractAddr, long expectedWithdrawBalance) throws Exception { AccountStore accountStore = manager.getAccountStore(); @@ -424,10 +438,7 @@ private TVMTestResult cancelAllUnfreezeV2( long oldBalance = oldOwner.getBalance(); long now = manager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); - TVMTestResult result = triggerCancelAllUnfreezeV2(callerAddr, contractAddr, SUCCESS, - returnValue -> - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001", - Hex.toHexString(returnValue))); + TVMTestResult result = triggerCancelAllUnfreezeV2(callerAddr, contractAddr, SUCCESS, null); AccountCapsule newOwner = accountStore.get(contractAddr); long unfreezeV2Amount = newOwner.getUnfreezingV2Count(now); @@ -444,16 +455,62 @@ private TVMTestResult delegateResource( throws Exception { AccountStore accountStore = manager.getAccountStore(); AccountCapsule oldOwner = accountStore.get(contractAddr); - long oldBalance = oldOwner.getBalance(); + AccountCapsule oldReceiver = accountStore.get(receiverAddr); + + DelegatedResourceStore delegatedResourceStore = manager.getDelegatedResourceStore(); + DelegatedResourceCapsule oldDelegatedResource = delegatedResourceStore.get( + DelegatedResourceCapsule.createDbKeyV2(contractAddr, receiverAddr)); + if (oldDelegatedResource == null) { + oldDelegatedResource = new DelegatedResourceCapsule( + ByteString.copyFrom(contractAddr), + ByteString.copyFrom(receiverAddr)); + } - TVMTestResult result = triggerWithdrawExpireUnfreeze(callerAddr, contractAddr, SUCCESS, - returnValue -> - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001", - Hex.toHexString(returnValue))); + TVMTestResult result = triggerDelegateResource( + callerAddr, contractAddr, SUCCESS, null, receiverAddr, amount, res); AccountCapsule newOwner = accountStore.get(contractAddr); - oldOwner.setBalance(newOwner.getBalance()); - Assert.assertArrayEquals(oldOwner.getData(), newOwner.getData()); + AccountCapsule newReceiver = accountStore.get(receiverAddr); + Assert.assertNotNull(newReceiver); + if (res == 0) { + Assert.assertEquals(oldOwner.getDelegatedFrozenBalanceForBandwidth() + amount, + newOwner.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(oldReceiver.getAcquiredDelegatedFrozenBalanceForBandwidth() + amount, + newReceiver.getAcquiredDelegatedFrozenBalanceForBandwidth()); + } else { + Assert.assertEquals(oldOwner.getDelegatedFrozenBalanceForEnergy() + amount, + newOwner.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(oldReceiver.getAcquiredDelegatedFrozenBalanceForEnergy() + amount, + newReceiver.getAcquiredDelegatedFrozenBalanceForEnergy()); + } + newReceiver.setBalance(oldReceiver.getBalance()); + oldReceiver.setEnergyUsage(0); + oldReceiver.setNewWindowSize(ENERGY, 28800); + newReceiver.setEnergyUsage(0); + newReceiver.setNewWindowSize(ENERGY,28800); + if (res == 0) { + oldReceiver.setAcquiredDelegatedFrozenBalanceForBandwidth(0); + newReceiver.setAcquiredDelegatedFrozenBalanceForBandwidth(0); + } else { + oldReceiver.setAcquiredDelegatedFrozenBalanceForEnergy(0); + newReceiver.setAcquiredDelegatedFrozenBalanceForEnergy(0); + } + Assert.assertArrayEquals(oldReceiver.getData(), newReceiver.getData()); + + DelegatedResourceCapsule newDelegatedResource = manager.getDelegatedResourceStore().get( + DelegatedResourceCapsule.createDbKeyV2(contractAddr, receiverAddr)); + Assert.assertNotNull(newDelegatedResource); + if (res == 0) { + Assert.assertEquals(amount + oldDelegatedResource.getFrozenBalanceForBandwidth(), + newDelegatedResource.getFrozenBalanceForBandwidth()); + Assert.assertEquals(oldDelegatedResource.getFrozenBalanceForEnergy(), + newDelegatedResource.getFrozenBalanceForEnergy()); + } else { + Assert.assertEquals(oldDelegatedResource.getFrozenBalanceForBandwidth(), + newDelegatedResource.getFrozenBalanceForBandwidth()); + Assert.assertEquals(amount + oldDelegatedResource.getFrozenBalanceForEnergy(), + newDelegatedResource.getFrozenBalanceForEnergy()); + } return result; } @@ -470,16 +527,10 @@ private TVMTestResult unDelegateResource( throws Exception { AccountStore accountStore = manager.getAccountStore(); AccountCapsule oldOwner = accountStore.get(contractAddr); - long oldBalance = oldOwner.getBalance(); - TVMTestResult result = triggerWithdrawExpireUnfreeze(callerAddr, contractAddr, SUCCESS, - returnValue -> - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001", - Hex.toHexString(returnValue))); - - AccountCapsule newOwner = accountStore.get(contractAddr); - oldOwner.setBalance(newOwner.getBalance()); - Assert.assertArrayEquals(oldOwner.getData(), newOwner.getData()); + TVMTestResult result = + triggerUnDelegateResource( + callerAddr, contractAddr, SUCCESS, null, receiverAddr, amount, res); return result; } From 459fe0f5f6a2aab05c69bc8d7b5643312d59864e Mon Sep 17 00:00:00 2001 From: Liulei Date: Thu, 20 Oct 2022 19:02:46 +0800 Subject: [PATCH 0342/1197] feat(freezeV2): optimize unDelegateResource processor --- .../main/java/org/tron/core/vm/OperationActions.java | 12 ++---------- .../nativecontract/UnDelegateResourceProcessor.java | 9 +-------- .../main/java/org/tron/core/vm/program/Program.java | 8 ++++---- 3 files changed, 7 insertions(+), 22 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index ecf3063007f..2d10676dc4d 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -847,16 +847,8 @@ public static void unDelegateResourceAction(Program program) { DataWord unDelegateBalance = program.stackPop(); DataWord receiverAddress = program.stackPop(); - Triple result = - program.unDelegateResource(receiverAddress, unDelegateBalance, resourceType); - if (Objects.isNull(result)) { - program.stackPush(DataWord.ZERO()); - } else { - program.stackPush(new DataWord(result.getLeft())); - program.stackPush(new DataWord(result.getMiddle())); - program.stackPush(new DataWord(result.getRight())); - program.stackPush(DataWord.ONE()); - } + boolean result = program.unDelegateResource(receiverAddress, unDelegateBalance, resourceType); + program.stackPush(result ? DataWord.ONE() : DataWord.ZERO()); program.step(); } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index f9e4e64acb2..e289fa2d745 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -7,7 +7,6 @@ import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; -import org.apache.commons.lang3.tuple.Triple; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.ChainBaseManager; @@ -19,7 +18,6 @@ import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.vm.nativecontract.param.UnDelegateResourceParam; import org.tron.core.vm.repository.Repository; -import org.tron.core.vm.utils.FreezeV2Util; @Slf4j(topic = "VMProcessor") public class UnDelegateResourceProcessor { @@ -91,7 +89,7 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont } } - public Triple execute(UnDelegateResourceParam param, Repository repo) { + public void execute(UnDelegateResourceParam param, Repository repo) { byte[] ownerAddress = param.getOwnerAddress(); byte[] receiverAddress = param.getReceiverAddress(); long unDelegateBalance = param.getUnDelegateBalance(); @@ -99,10 +97,6 @@ public Triple execute(UnDelegateResourceParam param, Repositor AccountCapsule receiverCapsule = repo.getAccount(receiverAddress); DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); - Triple unDelegateResourceInfo = - FreezeV2Util.checkUndelegateResource( - receiverAddress, unDelegateBalance, param.getResourceType().getNumber(), repo); - long transferUsage = 0; // modify receiver Account if (receiverCapsule != null) { @@ -197,6 +191,5 @@ public Triple execute(UnDelegateResourceParam param, Repositor } repo.updateDelegatedResource(key, delegatedResourceCapsule); repo.updateAccount(ownerCapsule.createDbKey(), ownerCapsule); - return unDelegateResourceInfo; } } diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 721f299e17f..30a59241da0 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -1990,7 +1990,7 @@ public boolean delegateResource( return false; } - public Triple unDelegateResource( + public boolean unDelegateResource( DataWord receiverAddress, DataWord unDelegateBalance, DataWord resourceType) { Repository repository = getContractState().newRepositoryChild(); byte[] owner = getContextAddress(); @@ -2010,9 +2010,9 @@ public Triple unDelegateResource( UnDelegateResourceProcessor processor = new UnDelegateResourceProcessor(); processor.validate(param, repository); - Triple result = processor.execute(param, repository); + processor.execute(param, repository); repository.commit(); - return result; + return true; } catch (ContractValidateException e) { logger.error("TVM unDelegateResource: validate failure. Reason: {}", e.getMessage()); } catch (ArithmeticException e) { @@ -2021,7 +2021,7 @@ public Triple unDelegateResource( if (internalTx != null) { internalTx.reject(); } - return null; + return false; } private Common.ResourceCode parseResourceCode(DataWord resourceType) { From 983e5e583308362b72039b951840b37d3103dcdf Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 20 Oct 2022 19:18:28 +0800 Subject: [PATCH 0343/1197] func(freezeV2): decrease energy cost for new instructions --- .../src/main/java/org/tron/core/vm/EnergyCost.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java index f60de7e8a62..1bfac91394f 100644 --- a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java +++ b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java @@ -36,12 +36,12 @@ public class EnergyCost { private static final long NEW_ACCT_CALL = 25000; private static final long UNFREEZE = 20000; private static final long FREEZE_EXPIRE_TIME = 50; - private static final long FREEZE_V2 = 20000; - private static final long UNFREEZE_V2 = 20000; - private static final long WITHDRAW_EXPIRE_UNFREEZE = 20000; - private static final long CANCEL_ALL_UNFREEZE_V2 = 20000; - private static final long DELEGATE_RESOURCE = 20000; - private static final long UN_DELEGATE_RESOURCE = 20000; + private static final long FREEZE_V2 = 10000; + private static final long UNFREEZE_V2 = 10000; + private static final long WITHDRAW_EXPIRE_UNFREEZE = 10000; + private static final long CANCEL_ALL_UNFREEZE_V2 = 10000; + private static final long DELEGATE_RESOURCE = 10000; + private static final long UN_DELEGATE_RESOURCE = 10000; private static final long VOTE_WITNESS = 30000; private static final long WITHDRAW_REWARD = 20000; private static final long CREATE = 32000; From 3b539bb99c90725090663c2af3e4668e250fa00e Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 20 Oct 2022 19:22:52 +0800 Subject: [PATCH 0344/1197] func(vote): support new resource model for vote in TVM --- .../org/tron/core/vm/PrecompiledContracts.java | 17 +++++++++++++---- .../vm/nativecontract/VoteWitnessProcessor.java | 11 ++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 419d94f5c0a..0078892c06c 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -65,7 +65,6 @@ import org.tron.core.vm.repository.Repository; import org.tron.core.vm.utils.FreezeV2Util; import org.tron.core.vm.utils.VoteRewardUtil; - import org.tron.protos.Protocol; import org.tron.protos.Protocol.Permission; @@ -1788,9 +1787,19 @@ public Pair execute(byte[] data) { byte[] address = new DataWord(data).toTronAddress(); AccountCapsule accountCapsule = this.getDeposit().getAccount(address); - long tronPower = accountCapsule != null - ? accountCapsule.getTronPower() / TRX_PRECISION : 0; - return Pair.of(true, longTo32Bytes(tronPower)); + long tronPower; + if (accountCapsule == null) { + tronPower = 0; + } else { + // fixme check if supportUnfreezeDelay needed + if (getDeposit().getDynamicPropertiesStore().supportUnfreezeDelay() + && getDeposit().getDynamicPropertiesStore().supportAllowNewResourceModel()) { + tronPower = accountCapsule.getAllTronPower(); + } else { + tronPower = accountCapsule.getTronPower(); + } + } + return Pair.of(true, longTo32Bytes(tronPower / TRX_PRECISION)); } } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/VoteWitnessProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/VoteWitnessProcessor.java index ddc28bc2a41..f499562ea39 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/VoteWitnessProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/VoteWitnessProcessor.java @@ -8,11 +8,9 @@ import com.google.common.math.LongMath; import com.google.protobuf.ByteString; - import java.util.HashMap; import java.util.Iterator; import java.util.Map; - import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; @@ -87,7 +85,14 @@ public void execute(VoteWitnessParam param, Repository repo) throws ContractExeE } } - long tronPower = accountCapsule.getTronPower(); + long tronPower; + // fixme check if supportUnfreezeDelay needed + if (repo.getDynamicPropertiesStore().supportUnfreezeDelay() + && repo.getDynamicPropertiesStore().supportAllowNewResourceModel()) { + tronPower = accountCapsule.getAllTronPower(); + } else { + tronPower = accountCapsule.getTronPower(); + } sum = LongMath.checkedMultiply(sum, TRX_PRECISION); if (sum > tronPower) { throw new ContractExeException( From 2e73bec82c1d48d460b91e492677205fa6a7c125 Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 20 Oct 2022 19:54:59 +0800 Subject: [PATCH 0345/1197] fix(energy): also record caller and deployer frozen energy if allowTvmFreezeV2 activated --- actuator/src/main/java/org/tron/core/actuator/VMActuator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 1846eb6da68..74e161fef31 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -539,7 +539,7 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi } long leftFrozenEnergy = rootRepository.getAccountLeftEnergyFromFreeze(account); - if (VMConfig.allowTvmFreeze()) { + if (VMConfig.allowTvmFreeze() || VMConfig.allowTvmFreezeV2()) { receipt.setCallerEnergyLeft(leftFrozenEnergy); } @@ -679,7 +679,7 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu long originEnergyLeft = 0; if (consumeUserResourcePercent < VMConstant.ONE_HUNDRED) { originEnergyLeft = rootRepository.getAccountLeftEnergyFromFreeze(creator); - if (VMConfig.allowTvmFreeze()) { + if (VMConfig.allowTvmFreeze() || VMConfig.allowTvmFreezeV2()) { receipt.setOriginEnergyLeft(originEnergyLeft); } } From d3eb24e01eeee01e914339aea9ec444fb7f760da Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 20 Oct 2022 20:40:49 +0800 Subject: [PATCH 0346/1197] fix(code): resolve some conflicts --- .../java/org/tron/core/vm/program/Program.java | 17 +++++++++++++---- .../org/tron/core/db/ResourceProcessor.java | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 30a59241da0..dd55fc525c0 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -22,7 +22,6 @@ import org.apache.commons.collections4.map.LRUMap; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.tuple.Pair; -import org.apache.commons.lang3.tuple.Triple; import org.bouncycastle.util.encoders.Hex; import org.tron.common.crypto.Hash; import org.tron.common.parameter.CommonParameter; @@ -525,9 +524,19 @@ private void transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit ownerCapsule.getFrozenV2List().stream() .filter(freezeV2 -> freezeV2.getAmount() > 0) .forEach( - freezeV2 -> - inheritorCapsule.addFrozenBalanceForResource( - freezeV2.getType(), freezeV2.getAmount())); + freezeV2 -> { + switch (freezeV2.getType()) { + case BANDWIDTH: + inheritorCapsule.addFrozenBalanceForBandwidthV2(freezeV2.getAmount()); + break; + case ENERGY: + inheritorCapsule.addFrozenBalanceForEnergyV2(freezeV2.getAmount()); + break; + case TRON_POWER: + inheritorCapsule.addFrozenForTronPowerV2(freezeV2.getAmount()); + break; + } + }); // merge usage BandwidthProcessor bandwidthProcessor = new BandwidthProcessor(ChainBaseManager.getInstance()); diff --git a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java index e9aa35f696e..eb0ab0eba7a 100644 --- a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java @@ -60,7 +60,7 @@ protected long increase(long lastUsage, long usage, long lastTime, long now, lon return getUsage(averageLastUsage, windowSize); } - protected long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, + public long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, long lastUsage, long usage, long lastTime, long now) { long oldWindowSize = accountCapsule.getWindowSize(resourceCode); /* old logic */ From 9fbcb6dadb8806299c8cdd748d8447ab0b37475c Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Thu, 20 Oct 2022 20:57:03 +0800 Subject: [PATCH 0347/1197] feat(freezeV2): optimize checkUndelegateResource calculate --- actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index 031be7ba0e9..bbf4ed5c96a 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -220,7 +220,7 @@ public static Triple checkUndelegateResource(byte[] address, l return Triple.of(0L, amount, usagePair.getRight()); } - long clean = amount * (resourceLimit - usagePair.getLeft()) / resourceLimit; + long clean = (long) (amount * ((double) (resourceLimit - usagePair.getLeft()) / resourceLimit)); return Triple.of(clean, amount - clean, usagePair.getRight()); } From 1a554e5844535dde4ba98fb3d65d907d3da82f0c Mon Sep 17 00:00:00 2001 From: Liulei Date: Thu, 20 Oct 2022 20:58:32 +0800 Subject: [PATCH 0348/1197] feat(freezeV2): add freezeV2 delegateResource test --- .../org/tron/core/vm/OperationActions.java | 2 - .../tron/common/runtime/vm/FreezeV2Test.java | 163 ++++++++++++++---- 2 files changed, 131 insertions(+), 34 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index 2d10676dc4d..db1bc9c8dbf 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -6,8 +6,6 @@ import java.math.BigInteger; import java.util.ArrayList; import java.util.List; -import java.util.Objects; -import org.apache.commons.lang3.tuple.Triple; import org.tron.common.runtime.vm.DataWord; import org.tron.common.runtime.vm.LogInfo; import org.tron.core.vm.config.VMConfig; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java index 1711af9896c..83797e1815a 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -60,8 +60,6 @@ public class FreezeV2Test { private static final byte[] userA = Commons.decode58Check(userAStr); private static final String userBStr = "27jzp7nVEkH4Hf3H1PHPp4VDY7DxTy5eydL"; private static final byte[] userB = Commons.decode58Check(userBStr); - private static final String userCStr = "27juXSbMvL6pb8VgmKRgW6ByCfw5RqZjUuo"; - private static final byte[] userC = Commons.decode58Check(userCStr); private static String dbPath; private static TronApplicationContext context; @@ -180,7 +178,7 @@ private TVMTestResult triggerCancelAllUnfreezeV2( byte[] callerAddr, byte[] contractAddr, contractResult expectedResult, Consumer check) throws Exception { return triggerContract( - callerAddr, contractAddr, fee, expectedResult, check, "cancelAllUnfreezeV2()"); + callerAddr, contractAddr, fee, expectedResult, check, "cancelAllUnfreezeBalanceV2()"); } private TVMTestResult triggerDelegateResource( @@ -250,48 +248,57 @@ public void testFreezeV2Operations() throws Exception { withdrawExpireUnfreeze(owner, contract, frozenBalance); // cancelAllUnfreezeV2 -// freezeV2(owner, contract, frozenBalance, 0); -// cancelAllUnfreezeV2(owner, contract, 0); -// clearUnfreezeV2ExpireTime(contract, 0); -// unfreezeV2(owner, contract, frozenBalance, 0); -// cancelAllUnfreezeV2(owner, contract, frozenBalance); + freezeV2(owner, contract, frozenBalance, 0); + cancelAllUnfreezeV2(owner, contract, 0); + unfreezeV2(owner, contract, frozenBalance, 0); + cancelAllUnfreezeV2(owner, contract, 0); + freezeV2(owner, contract, frozenBalance, 1); + unfreezeV2(owner, contract, frozenBalance, 1); + clearUnfreezeV2ExpireTime(contract, 1); + cancelAllUnfreezeV2(owner, contract, frozenBalance); } @Test public void testDelegateResourceOperations() throws Exception { byte[] contract = deployContract("TestFreezeV2", FREEZE_V2_CODE); - long frozenBalance = 1_000_000; + long resourceAmount = 1_000_000; // trigger freezeBalanceV2(uint256,uint256) to get bandwidth - freezeV2(owner, contract, frozenBalance, 0); + freezeV2(owner, contract, resourceAmount, 0); // trigger freezeBalanceV2(uint256,uint256) to get energy - freezeV2(owner, contract, frozenBalance, 1); + freezeV2(owner, contract, resourceAmount, 1); // trigger freezeBalanceV2(uint256,uint256) to get tp - freezeV2(owner, contract, frozenBalance, 2); + freezeV2(owner, contract, resourceAmount, 2); - delegateResourceWithException(owner, contract, userA, frozenBalance, 0); + delegateResourceWithException(owner, contract, userA, resourceAmount, 0); rootRepository.createAccount(userA, Protocol.AccountType.Normal); rootRepository.commit(); delegateResourceWithException(owner, contract, userA, 0, 0); - delegateResourceWithException(owner, contract, userA, frozenBalance * 2, 0); - delegateResourceWithException(owner, contract, userA, frozenBalance, 2); - delegateResourceWithException(owner, contract, userA, frozenBalance, 3); - delegateResourceWithException(owner, contract, contract, frozenBalance, 0); + delegateResourceWithException(owner, contract, userA, resourceAmount * 2, 0); + delegateResourceWithException(owner, contract, userA, resourceAmount, 2); + delegateResourceWithException(owner, contract, userA, resourceAmount, 3); + delegateResourceWithException(owner, contract, contract, resourceAmount, 0); - delegateResource(owner, contract, userA, frozenBalance, 0); - delegateResource(owner, contract, userA, frozenBalance, 1); + delegateResource(owner, contract, userA, resourceAmount, 0); + delegateResource(owner, contract, userA, resourceAmount, 1); // unDelegate - unDelegateResourceWithException(owner, contract, userA, frozenBalance, 2); - unDelegateResourceWithException(owner, contract, userA, frozenBalance, 3); + // invalid args + unDelegateResourceWithException(owner, contract, userA, resourceAmount, 2); + unDelegateResourceWithException(owner, contract, userA, resourceAmount, 3); rootRepository.createAccount(userB, Protocol.AccountType.Normal); rootRepository.commit(); - unDelegateResourceWithException(owner, contract, userB, frozenBalance, 0); - unDelegateResourceWithException(owner, contract, contract, frozenBalance, 0); - delegateResourceWithException(owner, contract, userA, frozenBalance * 2, 0); - delegateResourceWithException(owner, contract, userA, 0, 0); - -// unDelegateResource(owner, contract, userA, frozenBalance, 0); -// unDelegateResource(owner, contract, userA, frozenBalance, 1); + unDelegateResourceWithException(owner, contract, userB, resourceAmount, 0); + unDelegateResourceWithException(owner, contract, contract, resourceAmount, 0); + unDelegateResourceWithException(owner, contract, userA, resourceAmount * 2, 0); + unDelegateResourceWithException(owner, contract, userA, 0, 0); + unDelegateResourceWithException(owner, contract, userA, -resourceAmount, 0); + + unDelegateResource(owner, contract, userA, resourceAmount, 0); + unDelegateResource(owner, contract, userA, resourceAmount, 1); + + // no enough delegated resource + unDelegateResourceWithException(owner, contract, userA, resourceAmount, 0); + unDelegateResourceWithException(owner, contract, userA, resourceAmount, 1); } private TVMTestResult freezeV2( @@ -437,15 +444,23 @@ private TVMTestResult cancelAllUnfreezeV2( AccountCapsule oldOwner = accountStore.get(contractAddr); long oldBalance = oldOwner.getBalance(); long now = manager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); + long oldFrozenBalance = + oldOwner.getFrozenV2List().stream().mapToLong(Protocol.Account.FreezeV2::getAmount).sum(); + long oldUnfreezingBalance = + oldOwner.getUnfrozenV2List().stream() + .filter(unFreezeV2 -> unFreezeV2.getUnfreezeExpireTime() > now) + .mapToLong(Protocol.Account.UnFreezeV2::getUnfreezeAmount) + .sum(); TVMTestResult result = triggerCancelAllUnfreezeV2(callerAddr, contractAddr, SUCCESS, null); AccountCapsule newOwner = accountStore.get(contractAddr); - long unfreezeV2Amount = newOwner.getUnfreezingV2Count(now); - Assert.assertEquals(0, unfreezeV2Amount); + long newUnfreezeV2Amount = newOwner.getUnfreezingV2Count(now); + long newFrozenBalance = + newOwner.getFrozenV2List().stream().mapToLong(Protocol.Account.FreezeV2::getAmount).sum(); + Assert.assertEquals(0, newUnfreezeV2Amount); Assert.assertEquals(expectedWithdrawBalance, newOwner.getBalance() - oldBalance); - oldOwner.setBalance(newOwner.getBalance()); - Assert.assertArrayEquals(oldOwner.getData(), newOwner.getData()); + Assert.assertEquals(oldFrozenBalance + oldUnfreezingBalance, newFrozenBalance); return result; } @@ -527,10 +542,94 @@ private TVMTestResult unDelegateResource( throws Exception { AccountStore accountStore = manager.getAccountStore(); AccountCapsule oldOwner = accountStore.get(contractAddr); + AccountCapsule oldReceiver = accountStore.get(receiverAddr); + DynamicPropertiesStore dynamicStore = manager.getDynamicPropertiesStore(); + long acquiredBalance = 0; + long transferUsage = 0; + if (oldReceiver != null) { + acquiredBalance = res == 0 ? oldReceiver.getAcquiredDelegatedFrozenBalanceForBandwidth() : + oldReceiver.getAcquiredDelegatedFrozenBalanceForEnergy(); + + if (res == 0) { + long unDelegateMaxUsage = (long) (amount / TRX_PRECISION + * ((double) (dynamicStore.getTotalNetLimit()) / dynamicStore.getTotalNetWeight())); + transferUsage = (long) (oldReceiver.getNetUsage() + * ((double) (amount) / oldReceiver.getAllFrozenBalanceForBandwidth())); + transferUsage = Math.min(unDelegateMaxUsage, transferUsage); + } else { + long unDelegateMaxUsage = (long) (amount / TRX_PRECISION + * ((double) (dynamicStore.getTotalEnergyCurrentLimit()) + / dynamicStore.getTotalEnergyWeight())); + transferUsage = (long) (oldReceiver.getEnergyUsage() + * ((double) (amount) / oldReceiver.getAllFrozenBalanceForEnergy())); + transferUsage = Math.min(unDelegateMaxUsage, transferUsage); + } + } + + DelegatedResourceStore delegatedResourceStore = manager.getDelegatedResourceStore(); + DelegatedResourceCapsule oldDelegatedResource = delegatedResourceStore.get( + DelegatedResourceCapsule.createDbKeyV2(contractAddr, receiverAddr)); + Assert.assertNotNull(oldDelegatedResource); + long delegatedFrozenBalance = res == 0 ? oldDelegatedResource.getFrozenBalanceForBandwidth() : + oldDelegatedResource.getFrozenBalanceForEnergy(); + Assert.assertTrue(delegatedFrozenBalance > 0); + Assert.assertTrue(amount <= delegatedFrozenBalance); TVMTestResult result = triggerUnDelegateResource( callerAddr, contractAddr, SUCCESS, null, receiverAddr, amount, res); + // check owner account + AccountCapsule newOwner = accountStore.get(contractAddr); + newOwner.setBalance(oldOwner.getBalance()); + if (res == 0) { + Assert.assertEquals( + oldOwner.getDelegatedFrozenBalanceForBandwidth() - amount, + newOwner.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals( + oldOwner.getFrozenV2BalanceForBandwidth() + amount, + newOwner.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(oldOwner.getNetUsage() + transferUsage, newOwner.getNetUsage()); + } else { + Assert.assertEquals( + oldOwner.getDelegatedFrozenBalanceForEnergy() - amount, + newOwner.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals( + oldOwner.getFrozenV2BalanceForEnergy() + amount, newOwner.getFrozenV2BalanceForEnergy()); + Assert.assertEquals(oldOwner.getEnergyUsage() + transferUsage, newOwner.getEnergyUsage()); + } + + // check receiver account + AccountCapsule newReceiver = accountStore.get(receiverAddr); + if (oldReceiver != null) { + Assert.assertNotNull(newReceiver); + long newAcquiredBalance = + res == 0 + ? newReceiver.getAcquiredDelegatedFrozenBalanceForBandwidth() + : newReceiver.getAcquiredDelegatedFrozenBalanceForEnergy(); + Assert.assertTrue(newAcquiredBalance == 0 || acquiredBalance - newAcquiredBalance == amount); + if (res == 0) { + Assert.assertEquals(oldReceiver.getNetUsage() - transferUsage, newReceiver.getNetUsage()); + } else { + Assert.assertEquals( + oldReceiver.getEnergyUsage() + transferUsage, newReceiver.getEnergyUsage()); + } + } else { + Assert.assertNull(newReceiver); + } + + // check delegated resource store + DelegatedResourceCapsule newDelegatedResource = delegatedResourceStore.get( + DelegatedResourceCapsule.createDbKeyV2(contractAddr, receiverAddr)); + Assert.assertNotNull(newDelegatedResource); + if (res == 0) { + Assert.assertEquals(0, newDelegatedResource.getFrozenBalanceForBandwidth()); + Assert.assertEquals(oldDelegatedResource.getFrozenBalanceForEnergy(), + newDelegatedResource.getFrozenBalanceForEnergy()); + } else { + Assert.assertEquals(oldDelegatedResource.getFrozenBalanceForBandwidth(), + newDelegatedResource.getFrozenBalanceForBandwidth()); + Assert.assertEquals(0, newDelegatedResource.getFrozenBalanceForEnergy()); + } return result; } From b4e8e57c89aef5c05bd45735a666c28c5260f0b0 Mon Sep 17 00:00:00 2001 From: Liulei Date: Thu, 20 Oct 2022 21:22:44 +0800 Subject: [PATCH 0349/1197] feat(freezeV2): add freezeV2 delegateResource test --- actuator/src/main/java/org/tron/core/vm/OperationRegistry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index ea11556761c..a0f4f653f0d 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -616,7 +616,7 @@ public static void appendDelegateOperations(JumpTable table) { proposal)); table.set(new Operation( - Op.UNDELEGATERESOURCE, 3, 4, + Op.UNDELEGATERESOURCE, 3, 1, EnergyCost::getUnDelegateResourceCost, OperationActions::unDelegateResourceAction, proposal)); From e878f33b1d5b59883516e9c25c41ab3eb3821c22 Mon Sep 17 00:00:00 2001 From: Liulei Date: Thu, 20 Oct 2022 21:35:27 +0800 Subject: [PATCH 0350/1197] feat(freezeV2): optimize delegateResource cost --- actuator/src/main/java/org/tron/core/vm/EnergyCost.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java index 1bfac91394f..11022da52b1 100644 --- a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java +++ b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java @@ -294,12 +294,7 @@ public static long getCancelAllUnfreezeV2Cost(Program ignored) { return CANCEL_ALL_UNFREEZE_V2; } - public static long getDelegateResourceCost(Program program) { - Stack stack = program.getStack(); - DataWord receiverAddressWord = stack.get(stack.size() - 3); - if (isDeadAccount(program, receiverAddressWord)) { - return DELEGATE_RESOURCE + NEW_ACCT_CALL; - } + public static long getDelegateResourceCost(Program ignored) { return DELEGATE_RESOURCE; } From 17bfd7df8fac63cce4a224a1967efdd3ad2c6cb8 Mon Sep 17 00:00:00 2001 From: Liulei Date: Thu, 20 Oct 2022 22:13:12 +0800 Subject: [PATCH 0351/1197] feat(freezeV2): optimize freezeV2 freeze and delegate --- .../core/vm/nativecontract/DelegateResourceProcessor.java | 4 ++-- .../core/vm/nativecontract/UnfreezeBalanceV2Processor.java | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index fad2833b147..3d658374a13 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -55,7 +55,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra processor.updateUsage(ownerCapsule); long netUsage = (long) (ownerCapsule.getNetUsage() * TRX_PRECISION * ((double) - (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); + (repo.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); long ownerNetUsage = (long) (netUsage * ((double)(ownerCapsule .getFrozenV2BalanceForBandwidth()) / @@ -74,7 +74,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra processor.updateUsage(ownerCapsule); long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) - (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); + (repo.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); long ownerEnergyUsage = (long) (energyUsage * ((double)(ownerCapsule .getFrozenV2BalanceForEnergy()) / ownerCapsule.getAllFrozenBalanceForEnergy())); diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index 5a7283f7620..13fa94486cc 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -126,6 +126,11 @@ public void execute(UnfreezeBalanceV2Param param, Repository repo) { this.unfreezeExpire(accountCapsule, now); + if (repo.getDynamicPropertiesStore().supportAllowNewResourceModel() + && accountCapsule.oldTronPowerIsNotInitialized()) { + accountCapsule.initializeOldTronPower(); + } + this.updateAccountFrozenInfo(param.getResourceType(), accountCapsule, unfreezeBalance); long expireTime = this.calcUnfreezeExpireTime(now, repo); From 412aebdb14d9a25d34fd23e2aaadd9e8717332cc Mon Sep 17 00:00:00 2001 From: Liulei Date: Thu, 20 Oct 2022 22:44:50 +0800 Subject: [PATCH 0352/1197] feat(freezeV2): optimize freezeV2 unDelegate usage --- .../UnDelegateResourceProcessor.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index e289fa2d745..f232467b3fd 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -3,8 +3,12 @@ import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import java.util.Arrays; +import java.util.Objects; + import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.tron.common.utils.DecodeUtil; @@ -157,6 +161,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { // modify owner Account byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress); DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); + long now = repo.getHeadSlot(); switch (param.getResourceType()) { case BANDWIDTH: { delegatedResourceCapsule.addFrozenBalanceForBandwidth(-unDelegateBalance, 0); @@ -165,10 +170,11 @@ public void execute(UnDelegateResourceParam param, Repository repo) { ownerCapsule.addFrozenBalanceForBandwidthV2(unDelegateBalance); BandwidthProcessor processor = new BandwidthProcessor(ChainBaseManager.getInstance()); - processor.updateUsage(ownerCapsule); - long newNetUsage = ownerCapsule.getNetUsage() + transferUsage; - ownerCapsule.setNetUsage(newNetUsage); - ownerCapsule.setLatestConsumeTime(ChainBaseManager.getInstance().getHeadSlot()); + if (Objects.nonNull(receiverCapsule) && transferUsage > 0) { + ownerCapsule.setNetUsage(processor.unDelegateIncrease(ownerCapsule, receiverCapsule, + transferUsage, BANDWIDTH, now)); + ownerCapsule.setLatestConsumeTime(now); + } } break; case ENERGY: { @@ -179,10 +185,11 @@ public void execute(UnDelegateResourceParam param, Repository repo) { EnergyProcessor processor = new EnergyProcessor(dynamicStore, ChainBaseManager.getInstance().getAccountStore()); - processor.updateUsage(ownerCapsule); - long newEnergyUsage = ownerCapsule.getEnergyUsage() + transferUsage; - ownerCapsule.setEnergyUsage(newEnergyUsage); - ownerCapsule.setLatestConsumeTimeForEnergy(ChainBaseManager.getInstance().getHeadSlot()); + if (Objects.nonNull(receiverCapsule) && transferUsage > 0) { + ownerCapsule.setEnergyUsage(processor.unDelegateIncrease(ownerCapsule, receiverCapsule, + transferUsage, ENERGY, now)); + ownerCapsule.setLatestConsumeTimeForEnergy(now); + } } break; default: From ba8807480851e92736ddb5e92227504739855215 Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 20 Oct 2022 23:14:28 +0800 Subject: [PATCH 0353/1197] fix(code): use supportUnfreezeDelay method to check proposal --- .../src/main/java/org/tron/core/actuator/VMActuator.java | 8 ++++++-- .../main/java/org/tron/core/vm/config/ConfigLoader.java | 2 +- .../main/java/org/tron/core/capsule/ReceiptCapsule.java | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 74e161fef31..52fc915ec22 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -549,7 +549,9 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi long energyFromFeeLimit = feeLimit / sunPerEnergy; long newEnergyUsage = rootRepository.getAccountEnergyUsageFromFreeze(account); long now = rootRepository.getHeadSlot(); - receipt.setCallerEnergyUsage(newEnergyUsage); + if (VMConfig.allowTvmFreeze() || VMConfig.allowTvmFreezeV2()) { + receipt.setCallerEnergyUsage(newEnergyUsage); + } account.setEnergyUsage(newEnergyUsage + min(leftFrozenEnergy, energyFromFeeLimit)); account.setLatestConsumeTimeForEnergy(now); rootRepository.updateAccount(account.createDbKey(), account); @@ -700,7 +702,9 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu } } long newEnergyUsage = rootRepository.getAccountEnergyUsageFromFreeze(creator); - receipt.setOriginEnergyUsage(newEnergyUsage); + if (VMConfig.allowTvmFreeze() || VMConfig.allowTvmFreezeV2()) { + receipt.setOriginEnergyUsage(newEnergyUsage); + } long now = rootRepository.getHeadSlot(); creator.setLatestConsumeTimeForEnergy(now); creator.setEnergyUsage(creator.getEnergyUsage() + creatorEnergyLimit); diff --git a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java index b2fa1876940..7d06e5c9490 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java +++ b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java @@ -31,7 +31,7 @@ public static void load(StoreFactory storeFactory) { VMConfig.initAllowTvmCompatibleEvm(ds.getAllowTvmCompatibleEvm()); VMConfig.initAllowHigherLimitForMaxCpuTimeOfOneTx( ds.getAllowHigherLimitForMaxCpuTimeOfOneTx()); - VMConfig.initAllowTvmFreezeV2(ds.getUnfreezeDelayDays() > 0 ? 1 : 0); + VMConfig.initAllowTvmFreezeV2(ds.supportUnfreezeDelay() ? 1 : 0); } } } diff --git a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index b0debe0f80b..c1a666eccdf 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -186,7 +186,7 @@ private void payEnergyBill( long now) throws BalanceInsufficientException { long accountEnergyLeft; if (dynamicPropertiesStore.getAllowTvmFreeze() == 1 - || dynamicPropertiesStore.getUnfreezeDelayDays() > 0) { + || dynamicPropertiesStore.supportUnfreezeDelay()) { accountEnergyLeft = callerEnergyLeft; } else { accountEnergyLeft = energyProcessor.getAccountLeftEnergyFromFreeze(account); From 866498c0f8108bd6158b1da69872b3e4d071d960 Mon Sep 17 00:00:00 2001 From: Liulei Date: Thu, 20 Oct 2022 23:15:22 +0800 Subject: [PATCH 0354/1197] feat(freezeV2): optimize freezeV2 suicide --- .../main/java/org/tron/core/vm/program/Program.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index dd55fc525c0..9ff866557e8 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -440,8 +440,8 @@ public void suicide(DataWord obtainerAddress) { increaseNonce(); - addInternalTx(null, owner, obtainer, balance, null, "suicide", nonce, - getContractState().getAccount(owner).getAssetMapV2()); + InternalTransaction internalTx = addInternalTx(null, owner, obtainer, balance, null, + "suicide", nonce, getContractState().getAccount(owner).getAssetMapV2()); if (FastByteComparisons.compareTo(owner, 0, 20, obtainer, 0, 20) == 0) { // if owner == obtainer just zeroing account according to Yellow Paper @@ -479,7 +479,10 @@ public void suicide(DataWord obtainerAddress) { FastByteComparisons.isEqual(owner, obtainer) ? getContractState().getBlackHoleAddress() : obtainer; - transferFrozenV2BalanceToInheritor(owner, Inheritor, getContractState()); + long expireUnfrozenBalance = transferFrozenV2BalanceToInheritor(owner, Inheritor, getContractState()); + if (expireUnfrozenBalance > 0 && internalTx != null) { + internalTx.setValue(internalTx.getValue() + expireUnfrozenBalance); + } } getResult().addDeleteAccount(this.getContractAddress()); } @@ -515,7 +518,7 @@ private void transferDelegatedResourceToInheritor(byte[] ownerAddr, byte[] inher repo.addBalance(inheritorAddr, frozenBalanceForBandwidthOfOwner + frozenBalanceForEnergyOfOwner); } - private void transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inheritorAddr, Repository repo) { + private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inheritorAddr, Repository repo) { AccountCapsule ownerCapsule = repo.getAccount(ownerAddr); AccountCapsule inheritorCapsule = repo.getAccount(inheritorAddr); long now = repo.getHeadSlot(); @@ -578,6 +581,7 @@ private void transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit } repo.updateAccount(inheritorCapsule.createDbKey(), inheritorCapsule); + return expireUnfrozenBalance; } private void withdrawRewardAndCancelVote(byte[] owner, Repository repo) { From b17c57dcb8bba52b254743bbe0ac19e5c720e2fc Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Thu, 20 Oct 2022 23:39:12 +0800 Subject: [PATCH 0355/1197] feat(freezeV2): optimize queryExpireUnfreezeBalanceV2 time params --- .../src/main/java/org/tron/core/vm/utils/FreezeV2Util.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index bbf4ed5c96a..deb3ad22aac 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -22,8 +22,6 @@ public static long queryExpireUnfreezeBalanceV2(byte[] address, long time, Repos return 0; } - // time should be transferred to slot. - long slot = repository.getSlotByTimestampMs(time); AccountCapsule accountCapsule = repository.getAccount(address); if (accountCapsule == null) { return 0; @@ -32,7 +30,7 @@ public static long queryExpireUnfreezeBalanceV2(byte[] address, long time, Repos List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); - return getTotalWithdrawUnfreeze(unfrozenV2List, slot); + return getTotalWithdrawUnfreeze(unfrozenV2List, time); } public static long queryUnfreezableBalanceV2(byte[] address, long type, Repository repository) { From b0f6e04ad9a8b6c4d5660b05537e31d7f0fefe09 Mon Sep 17 00:00:00 2001 From: Liulei Date: Thu, 20 Oct 2022 23:40:12 +0800 Subject: [PATCH 0356/1197] feat(freezeV2): optimize freezeV2 withdrawExpireUnfreeze --- .../vm/nativecontract/UnfreezeBalanceV2Processor.java | 8 +++++--- .../main/java/org/tron/core/vm/program/Program.java | 10 +++++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index 13fa94486cc..99fec720fdd 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -117,14 +117,14 @@ private boolean checkExistFrozenBalance(AccountCapsule accountCapsule, Common.Re return checkOk; } - public void execute(UnfreezeBalanceV2Param param, Repository repo) { + public long execute(UnfreezeBalanceV2Param param, Repository repo) { byte[] ownerAddress = param.getOwnerAddress(); long unfreezeBalance = param.getUnfreezeBalance(); AccountCapsule accountCapsule = repo.getAccount(ownerAddress); long now = repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); - this.unfreezeExpire(accountCapsule, now); + long unfreezeExpireBalance = this.unfreezeExpire(accountCapsule, now); if (repo.getDynamicPropertiesStore().supportAllowNewResourceModel() && accountCapsule.oldTronPowerIsNotInitialized()) { @@ -145,9 +145,10 @@ public void execute(UnfreezeBalanceV2Param param, Repository repo) { } repo.updateAccount(accountCapsule.createDbKey(), accountCapsule); + return unfreezeExpireBalance; } - private void unfreezeExpire(AccountCapsule accountCapsule, long now) { + private long unfreezeExpire(AccountCapsule accountCapsule, long now) { long unfreezeBalance = 0L; List unFrozenV2List = Lists.newArrayList(); @@ -168,6 +169,7 @@ private void unfreezeExpire(AccountCapsule accountCapsule, long now) { .clearUnfrozenV2() .addAllUnfrozenV2(unFrozenV2List).build() ); + return unfreezeBalance; } private void updateAccountFrozenInfo( diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 9ff866557e8..b5d08d51d4e 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -578,6 +578,9 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit .sum(); if (expireUnfrozenBalance > 0) { inheritorCapsule.setBalance(inheritorCapsule.getBalance() + expireUnfrozenBalance); + increaseNonce(); + addInternalTx(null, ownerAddr, inheritorAddr, expireUnfrozenBalance, null, + "withdrawExpireUnfreeze", nonce, null); } repo.updateAccount(inheritorCapsule.createDbKey(), inheritorCapsule); @@ -1896,8 +1899,13 @@ public boolean unfreezeBalanceV2(DataWord unfreezeBalance, DataWord resourceType UnfreezeBalanceV2Processor processor = new UnfreezeBalanceV2Processor(); processor.validate(param, repository); - processor.execute(param, repository); + long unfreezeExpireBalance = processor.execute(param, repository); repository.commit(); + if (unfreezeExpireBalance > 0) { + increaseNonce(); + addInternalTx(null, owner, owner, unfreezeExpireBalance, null, + "withdrawExpireUnfreeze", nonce, null); + } return true; } catch (ContractValidateException e) { logger.error("TVM UnfreezeBalanceV2: validate failure. Reason: {}", e.getMessage()); From f47b4bb44585a038836a9ad64a22c43b9acb5d75 Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 20 Oct 2022 23:43:41 +0800 Subject: [PATCH 0357/1197] fix(suicide): wrong check condition for expire unfreeze --- actuator/src/main/java/org/tron/core/vm/program/Program.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index b5d08d51d4e..e4e161c9dfa 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -521,7 +521,7 @@ private void transferDelegatedResourceToInheritor(byte[] ownerAddr, byte[] inher private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inheritorAddr, Repository repo) { AccountCapsule ownerCapsule = repo.getAccount(ownerAddr); AccountCapsule inheritorCapsule = repo.getAccount(inheritorAddr); - long now = repo.getHeadSlot(); + long now = repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); // transfer frozen resource ownerCapsule.getFrozenV2List().stream() @@ -638,7 +638,7 @@ private boolean freezeV2Check(AccountCapsule accountCapsule) { if (!VMConfig.allowTvmFreezeV2()) { return true; } - long now = ChainBaseManager.getInstance().getHeadSlot(); + long now = getContractState().getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); boolean isDelegatedResourceEmpty = accountCapsule.getDelegatedFrozenBalanceForBandwidth() == 0 From a8f09a77c4586105eb90b112ac8d06a2e8e23c2e Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 21 Oct 2022 00:49:14 +0800 Subject: [PATCH 0358/1197] fix(code): wrap code for check style --- .../org/tron/core/actuator/VMActuator.java | 15 +-- .../tron/common/runtime/vm/FreezeV2Test.java | 77 ++++++++++++- .../runtime/vm/PrecompiledContractsTest.java | 104 ++++++++++++------ 3 files changed, 146 insertions(+), 50 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 52fc915ec22..c32f9135577 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -548,14 +548,12 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi long energyFromFeeLimit = feeLimit / sunPerEnergy; long newEnergyUsage = rootRepository.getAccountEnergyUsageFromFreeze(account); - long now = rootRepository.getHeadSlot(); if (VMConfig.allowTvmFreeze() || VMConfig.allowTvmFreezeV2()) { receipt.setCallerEnergyUsage(newEnergyUsage); + account.setEnergyUsage(newEnergyUsage + min(leftFrozenEnergy, energyFromFeeLimit)); + account.setLatestConsumeTimeForEnergy(rootRepository.getHeadSlot()); + rootRepository.updateAccount(account.createDbKey(), account); } - account.setEnergyUsage(newEnergyUsage + min(leftFrozenEnergy, energyFromFeeLimit)); - account.setLatestConsumeTimeForEnergy(now); - rootRepository.updateAccount(account.createDbKey(), account); - return min(availableEnergy, energyFromFeeLimit); } @@ -704,11 +702,10 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu long newEnergyUsage = rootRepository.getAccountEnergyUsageFromFreeze(creator); if (VMConfig.allowTvmFreeze() || VMConfig.allowTvmFreezeV2()) { receipt.setOriginEnergyUsage(newEnergyUsage); + creator.setEnergyUsage(creator.getEnergyUsage() + creatorEnergyLimit); + creator.setLatestConsumeTimeForEnergy(rootRepository.getHeadSlot()); + rootRepository.updateAccount(creator.createDbKey(), creator); } - long now = rootRepository.getHeadSlot(); - creator.setLatestConsumeTimeForEnergy(now); - creator.setEnergyUsage(creator.getEnergyUsage() + creatorEnergyLimit); - rootRepository.updateAccount(creator.createDbKey(), creator); return Math.addExact(callerEnergyLimit, creatorEnergyLimit); } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java index 83797e1815a..c49a5031a13 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -11,7 +11,6 @@ import java.util.Arrays; import java.util.List; import java.util.function.Consumer; - import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.junit.After; @@ -52,7 +51,72 @@ public class FreezeV2Test { private static final String FREEZE_V2_CODE = - "6080604052610aa0806100136000396000f3fe608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b50600436106101255760003560e01c806385510c71116100bc578063c1a98a371161008b578063c1a98a371461021d578063c8115bb714610230578063df860ab314610258578063f0130dc91461026b578063f70eb4c51461027e57600080fd5b806385510c71146101cc5780639eb506e2146101ef578063a465bb1914610202578063b335634e1461020a57600080fd5b806333e7645d116100f857806333e7645d1461018b578063350a02341461019e5780633dcba6fc146101b157806358974547146101b957600080fd5b8063089480871461012a57806308bee6c41461013f578063236051ed146101525780632fe36be514610178575b600080fd5b61013d610138366004610881565b610291565b005b61013d61014d3660046108c4565b610302565b6101656101603660046108e6565b610355565b6040519081526020015b60405180910390f35b61013d6101863660046108c4565b6103be565b6101656101993660046108e6565b610409565b61013d6101ac366004610881565b61042f565b61013d610497565b6101656101c73660046108e6565b6104c4565b6101d46104ea565b6040805193845260208401929092529082015260600161016f565b6101656101fd3660046108e6565b6105f0565b610165610616565b61016561021836600461091b565b610657565b61016561022b3660046108e6565b6106c9565b61024361023e36600461091b565b6106ef565b6040805192835260208301919091520161016f565b6101d4610266366004610969565b610766565b6101656102793660046108e6565b6107e2565b61016561028c3660046109a7565b610808565b806001600160a01b03168383de1580156102af573d6000803e3d6000fd5b5060408051848152602081018490526001600160a01b038316918101919091527f025526dfa15721b77133358f4ef9591e878434240705071b580f0f8f955153be906060015b60405180910390a1505050565b8181da158015610316573d6000803e3d6000fd5b5060408051838152602081018390527fc20c50cd22b066cd9d0cbbe9adbdee2f66da283d9971f5ff840fb01af79d980891015b60405180910390a15050565b604080516001600160a01b038416815260208101839052600091630100001491015b602060405180830381855afa158015610394573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906103b791906109d4565b9392505050565b8181db1580156103d2573d6000803e3d6000fd5b5060408051838152602081018390527fa2339ebec95cc02eea0ca9e15e5b1b4dd568105de8c4e47d2c6b96b1969348e89101610349565b604080516001600160a01b038416815260208101839052600091630100000f9101610377565b806001600160a01b03168383df15801561044d573d6000803e3d6000fd5b5060408051848152602081018490526001600160a01b038316918101919091527f42fddce307cf00fa55a23fcc80c1d2ba08ddce9776bbced3d1657321ed2b7bbe906060016102f5565bdc506040517f2ba20738f2500f7585581bf668aa65ab6de7d1c1822de5737455214184f37ed590600090a1565b604080516001600160a01b038416815260208101839052600091630100000e9101610377565b600080600080600160405181601f820153602081602083630100000b5afa610518576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff8316831461053957600080fd5b50506000600260405181601f820153602081602083630100000b5afa610565576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff8316831461058657600080fd5b50506000600360405181601f820153602081602083630100000b5afa6105b2576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff831683146105d357600080fd5b505067ffffffffffffffff92831696918316955090911692509050565b604080516001600160a01b03841681526020810183905260009163010000139101610377565b6000dd90507f6a5f656ed489ef1dec34a7317ceb95e7363440f72efdb653107e66982370f0618160405161064c91815260200190565b60405180910390a190565b604080516001600160a01b03808616825284166020820152908101829052600090630100001090606001602060405180830381855afa15801561069e573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906106c191906109d4565b949350505050565b604080516001600160a01b03841681526020810183905260009163010000159101610377565b604080516001600160a01b0380861682528416602082015290810182905260009081906301000012906060016040805180830381855afa158015610737573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061075a91906109ed565b91509150935093915050565b604080516001600160a01b03851681526020810184905290810182905260009081908190630100001190606001606060405180830381855afa1580156107b0573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906107d39190610a11565b92509250925093509350939050565b604080516001600160a01b038416815260208101839052600091630100000d9101610377565b6040516001600160a01b0382168152600090630100000c90602001602060405180830381855afa158015610840573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061086391906109d4565b92915050565b6001600160a81b038116811461087e57600080fd5b50565b60008060006060848603121561089657600080fd5b833592506020840135915060408401356108af81610869565b9295919450506001600160a01b039091169150565b600080604083850312156108d757600080fd5b50508035926020909101359150565b600080604083850312156108f957600080fd5b823561090481610869565b6001600160a01b0316946020939093013593505050565b60008060006060848603121561093057600080fd5b833561093b81610869565b6001600160a01b03908116935060208501359061095782610869565b93969316945050506040919091013590565b60008060006060848603121561097e57600080fd5b833561098981610869565b6001600160a01b031695602085013595506040909401359392505050565b6000602082840312156109b957600080fd5b81356109c481610869565b6001600160a01b03169392505050565b6000602082840312156109e657600080fd5b5051919050565b60008060408385031215610a0057600080fd5b505080516020909101519092909150565b600080600060608486031215610a2657600080fd5b835192506020840151915060408401519050925092509256fea26474726f6e5822122060a7d93c8ee9065ccd63ad4b97b050e98fb1394a4d6c66c5223273f96fbe4ffd64736f6c63782d302e382e31372d646576656c6f702e323032322e31302e32302b636f6d6d69742e34313134656332632e6d6f64005e"; + "6080604052610aa0806100136000396000f3fe608060405234801561001057600080fd5b50d3801561001d57" + + "600080fd5b50d2801561002a57600080fd5b50600436106101255760003560e01c806385510c71116100" + + "bc578063c1a98a371161008b578063c1a98a371461021d578063c8115bb714610230578063df860ab314" + + "610258578063f0130dc91461026b578063f70eb4c51461027e57600080fd5b806385510c71146101cc57" + + "80639eb506e2146101ef578063a465bb1914610202578063b335634e1461020a57600080fd5b806333e7" + + "645d116100f857806333e7645d1461018b578063350a02341461019e5780633dcba6fc146101b1578063" + + "58974547146101b957600080fd5b8063089480871461012a57806308bee6c41461013f578063236051ed" + + "146101525780632fe36be514610178575b600080fd5b61013d610138366004610881565b610291565b00" + + "5b61013d61014d3660046108c4565b610302565b6101656101603660046108e6565b610355565b604051" + + "9081526020015b60405180910390f35b61013d6101863660046108c4565b6103be565b61016561019936" + + "60046108e6565b610409565b61013d6101ac366004610881565b61042f565b61013d610497565b610165" + + "6101c73660046108e6565b6104c4565b6101d46104ea565b604080519384526020840192909252908201" + + "5260600161016f565b6101656101fd3660046108e6565b6105f0565b610165610616565b610165610218" + + "36600461091b565b610657565b61016561022b3660046108e6565b6106c9565b61024361023e36600461" + + "091b565b6106ef565b6040805192835260208301919091520161016f565b6101d4610266366004610969" + + "565b610766565b6101656102793660046108e6565b6107e2565b61016561028c3660046109a7565b6108" + + "08565b806001600160a01b03168383de1580156102af573d6000803e3d6000fd5b506040805184815260" + + "2081018490526001600160a01b038316918101919091527f025526dfa15721b77133358f4ef9591e8784" + + "34240705071b580f0f8f955153be906060015b60405180910390a1505050565b8181da15801561031657" + + "3d6000803e3d6000fd5b5060408051838152602081018390527fc20c50cd22b066cd9d0cbbe9adbdee2f" + + "66da283d9971f5ff840fb01af79d980891015b60405180910390a15050565b604080516001600160a01b" + + "038416815260208101839052600091630100001491015b602060405180830381855afa15801561039457" + + "3d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906103b791906109" + + "d4565b9392505050565b8181db1580156103d2573d6000803e3d6000fd5b506040805183815260208101" + + "8390527fa2339ebec95cc02eea0ca9e15e5b1b4dd568105de8c4e47d2c6b96b1969348e8910161034956" + + "5b604080516001600160a01b038416815260208101839052600091630100000f9101610377565b806001" + + "600160a01b03168383df15801561044d573d6000803e3d6000fd5b506040805184815260208101849052" + + "6001600160a01b038316918101919091527f42fddce307cf00fa55a23fcc80c1d2ba08ddce9776bbced3" + + "d1657321ed2b7bbe906060016102f5565bdc506040517f2ba20738f2500f7585581bf668aa65ab6de7d1" + + "c1822de5737455214184f37ed590600090a1565b604080516001600160a01b0384168152602081018390" + + "52600091630100000e9101610377565b600080600080600160405181601f820153602081602083630100" + + "000b5afa610518576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff8316" + + "831461053957600080fd5b50506000600260405181601f820153602081602083630100000b5afa610565" + + "576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff831683146105865760" + + "0080fd5b50506000600360405181601f820153602081602083630100000b5afa6105b2576040513d6000" + + "823e3d81fd5b602081016040528051925067ffffffffffffffff831683146105d357600080fd5b505067" + + "ffffffffffffffff92831696918316955090911692509050565b604080516001600160a01b0384168152" + + "6020810183905260009163010000139101610377565b6000dd90507f6a5f656ed489ef1dec34a7317ceb" + + "95e7363440f72efdb653107e66982370f0618160405161064c91815260200190565b60405180910390a1" + + "90565b604080516001600160a01b03808616825284166020820152908101829052600090630100001090" + + "606001602060405180830381855afa15801561069e573d6000803e3d6000fd5b5050506040513d601f19" + + "601f820116820180604052508101906106c191906109d4565b949350505050565b604080516001600160" + + "a01b03841681526020810183905260009163010000159101610377565b604080516001600160a01b0380" + + "861682528416602082015290810182905260009081906301000012906060016040805180830381855afa" + + "158015610737573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190" + + "61075a91906109ed565b91509150935093915050565b604080516001600160a01b038516815260208101" + + "84905290810182905260009081908190630100001190606001606060405180830381855afa1580156107" + + "b0573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906107d39190" + + "610a11565b92509250925093509350939050565b604080516001600160a01b0384168152602081018390" + + "52600091630100000d9101610377565b6040516001600160a01b0382168152600090630100000c906020" + + "01602060405180830381855afa158015610840573d6000803e3d6000fd5b5050506040513d601f19601f" + + "8201168201806040525081019061086391906109d4565b92915050565b6001600160a81b038116811461" + + "087e57600080fd5b50565b60008060006060848603121561089657600080fd5b83359250602084013591" + + "5060408401356108af81610869565b9295919450506001600160a01b039091169150565b600080604083" + + "850312156108d757600080fd5b50508035926020909101359150565b600080604083850312156108f957" + + "600080fd5b823561090481610869565b6001600160a01b0316946020939093013593505050565b600080" + + "60006060848603121561093057600080fd5b833561093b81610869565b6001600160a01b039081169350" + + "60208501359061095782610869565b93969316945050506040919091013590565b600080600060608486" + + "03121561097e57600080fd5b833561098981610869565b6001600160a01b031695602085013595506040" + + "909401359392505050565b6000602082840312156109b957600080fd5b81356109c481610869565b6001" + + "600160a01b03169392505050565b6000602082840312156109e657600080fd5b5051919050565b600080" + + "60408385031215610a0057600080fd5b505080516020909101519092909150565b600080600060608486" + + "031215610a2657600080fd5b835192506020840151915060408401519050925092509256fea26474726f" + + "6e5822122060a7d93c8ee9065ccd63ad4b97b050e98fb1394a4d6c66c5223273f96fbe4ffd64736f6c63" + + "782d302e382e31372d646576656c6f702e323032322e31302e32302b636f6d6d69742e34313134656332" + + "632e6d6f64005e"; private static final long value = 100_000_000_000_000_000L; private static final long fee = 1_000_000_000; @@ -185,9 +249,9 @@ private TVMTestResult triggerDelegateResource( byte[] callerAddr, byte[] contractAddr, contractResult expectedResult, Consumer check, byte[] receiverAddr, long amount, long res) throws Exception { - return triggerContract( - callerAddr, contractAddr, fee, expectedResult, check, - "delegateResource(uint256,uint256,address)", amount, res, StringUtil.encode58Check(receiverAddr)); + return triggerContract(callerAddr, contractAddr, fee, expectedResult, check, + "delegateResource(uint256,uint256,address)", + amount, res, StringUtil.encode58Check(receiverAddr)); } private TVMTestResult triggerUnDelegateResource( @@ -196,7 +260,8 @@ private TVMTestResult triggerUnDelegateResource( throws Exception { return triggerContract( callerAddr, contractAddr, fee, expectedResult, check, - "unDelegateResource(uint256,uint256,address)", amount, res, StringUtil.encode58Check(receiverAddr)); + "unDelegateResource(uint256,uint256,address)", + amount, res, StringUtil.encode58Check(receiverAddr)); } @Test diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index be8bb239b6d..6a01c745825 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -27,7 +27,11 @@ import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.actuator.FreezeBalanceActuator; -import org.tron.core.capsule.*; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.BytesCapsule; +import org.tron.core.capsule.ProposalCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; @@ -322,19 +326,30 @@ public void proposalTest() { public void tvmFreezeV2SwitchTest() { VMConfig.initAllowTvmFreezeV2(0L); - PrecompiledContract getChainParameterPcc = PrecompiledContracts.getContractForAddress(getChainParameterAddr); - PrecompiledContract availableUnfreezeV2SizePcc = PrecompiledContracts.getContractForAddress(availableUnfreezeV2SizeAddr); - PrecompiledContract unfreezableBalanceV2Pcc = PrecompiledContracts.getContractForAddress(unfreezableBalanceV2Addr); - PrecompiledContract expireUnfreezeBalanceV2Pcc = PrecompiledContracts.getContractForAddress(expireUnfreezeBalanceV2Addr); - - PrecompiledContract delegatableResourcePcc = PrecompiledContracts.getContractForAddress(delegatableResourceAddr); - PrecompiledContract resourceV2Pcc = PrecompiledContracts.getContractForAddress(resourceV2Addr); - PrecompiledContract checkUnDelegateResourcePcc = PrecompiledContracts.getContractForAddress(checkUnDelegateResourceAddr); - - PrecompiledContract resourceUsagePcc = PrecompiledContracts.getContractForAddress(resourceUsageAddr); - PrecompiledContract totalResourcePcc = PrecompiledContracts.getContractForAddress(totalResourceAddr); - PrecompiledContract totalDelegatedResourcePcc = PrecompiledContracts.getContractForAddress(totalDelegatedResourceAddr); - PrecompiledContract totalAcquiredResourcePcc = PrecompiledContracts.getContractForAddress(totalAcquiredResourceAddr); + PrecompiledContract getChainParameterPcc = + PrecompiledContracts.getContractForAddress(getChainParameterAddr); + PrecompiledContract availableUnfreezeV2SizePcc = + PrecompiledContracts.getContractForAddress(availableUnfreezeV2SizeAddr); + PrecompiledContract unfreezableBalanceV2Pcc = + PrecompiledContracts.getContractForAddress(unfreezableBalanceV2Addr); + PrecompiledContract expireUnfreezeBalanceV2Pcc = + PrecompiledContracts.getContractForAddress(expireUnfreezeBalanceV2Addr); + + PrecompiledContract delegatableResourcePcc = + PrecompiledContracts.getContractForAddress(delegatableResourceAddr); + PrecompiledContract resourceV2Pcc = + PrecompiledContracts.getContractForAddress(resourceV2Addr); + PrecompiledContract checkUnDelegateResourcePcc = + PrecompiledContracts.getContractForAddress(checkUnDelegateResourceAddr); + + PrecompiledContract resourceUsagePcc = + PrecompiledContracts.getContractForAddress(resourceUsageAddr); + PrecompiledContract totalResourcePcc = + PrecompiledContracts.getContractForAddress(totalResourceAddr); + PrecompiledContract totalDelegatedResourcePcc = + PrecompiledContracts.getContractForAddress(totalDelegatedResourceAddr); + PrecompiledContract totalAcquiredResourcePcc = + PrecompiledContracts.getContractForAddress(totalAcquiredResourceAddr); Assert.assertNull(getChainParameterPcc); Assert.assertNull(availableUnfreezeV2SizePcc); @@ -353,19 +368,30 @@ public void tvmFreezeV2SwitchTest() { // enable TvmFreezeV2. VMConfig.initAllowTvmFreezeV2(1L); - getChainParameterPcc = PrecompiledContracts.getContractForAddress(getChainParameterAddr); - availableUnfreezeV2SizePcc = PrecompiledContracts.getContractForAddress(availableUnfreezeV2SizeAddr); - unfreezableBalanceV2Pcc = PrecompiledContracts.getContractForAddress(unfreezableBalanceV2Addr); - expireUnfreezeBalanceV2Pcc = PrecompiledContracts.getContractForAddress(expireUnfreezeBalanceV2Addr); - - delegatableResourcePcc = PrecompiledContracts.getContractForAddress(delegatableResourceAddr); - resourceV2Pcc = PrecompiledContracts.getContractForAddress(resourceV2Addr); - checkUnDelegateResourcePcc = PrecompiledContracts.getContractForAddress(checkUnDelegateResourceAddr); - - resourceUsagePcc = PrecompiledContracts.getContractForAddress(resourceUsageAddr); - totalResourcePcc = PrecompiledContracts.getContractForAddress(totalResourceAddr); - totalDelegatedResourcePcc = PrecompiledContracts.getContractForAddress(totalDelegatedResourceAddr); - totalAcquiredResourcePcc = PrecompiledContracts.getContractForAddress(totalAcquiredResourceAddr); + getChainParameterPcc = + PrecompiledContracts.getContractForAddress(getChainParameterAddr); + availableUnfreezeV2SizePcc = + PrecompiledContracts.getContractForAddress(availableUnfreezeV2SizeAddr); + unfreezableBalanceV2Pcc = + PrecompiledContracts.getContractForAddress(unfreezableBalanceV2Addr); + expireUnfreezeBalanceV2Pcc = + PrecompiledContracts.getContractForAddress(expireUnfreezeBalanceV2Addr); + + delegatableResourcePcc = + PrecompiledContracts.getContractForAddress(delegatableResourceAddr); + resourceV2Pcc = + PrecompiledContracts.getContractForAddress(resourceV2Addr); + checkUnDelegateResourcePcc = + PrecompiledContracts.getContractForAddress(checkUnDelegateResourceAddr); + + resourceUsagePcc = + PrecompiledContracts.getContractForAddress(resourceUsageAddr); + totalResourcePcc = + PrecompiledContracts.getContractForAddress(totalResourceAddr); + totalDelegatedResourcePcc = + PrecompiledContracts.getContractForAddress(totalDelegatedResourceAddr); + totalAcquiredResourcePcc = + PrecompiledContracts.getContractForAddress(totalAcquiredResourceAddr); Assert.assertNotNull(getChainParameterPcc); Assert.assertNotNull(availableUnfreezeV2SizePcc); @@ -386,7 +412,8 @@ public void tvmFreezeV2SwitchTest() { public void getChainParameterTest() { VMConfig.initAllowTvmFreezeV2(1L); - PrecompiledContract getChainParameterPcc = createPrecompiledContract(getChainParameterAddr, OWNER_ADDRESS); + PrecompiledContract getChainParameterPcc = + createPrecompiledContract(getChainParameterAddr, OWNER_ADDRESS); Repository tempRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); getChainParameterPcc.setRepository(tempRepository); @@ -407,20 +434,26 @@ public void getChainParameterTest() { "0000000000000000000000000000000000000000000000000000000000FFFFFF"); long energyLimit = 9_000_000_000_000_000L; - tempRepository.getDynamicPropertiesStore().put(TOTAL_ENERGY_CURRENT_LIMIT, new BytesCapsule(ByteArray.fromLong(energyLimit))); - Pair totalEnergyCurrentLimitRes = getChainParameterPcc.execute(totalEnergyCurrentLimitId.getData()); + tempRepository.getDynamicPropertiesStore().put(TOTAL_ENERGY_CURRENT_LIMIT, + new BytesCapsule(ByteArray.fromLong(energyLimit))); + Pair totalEnergyCurrentLimitRes = + getChainParameterPcc.execute(totalEnergyCurrentLimitId.getData()); Assert.assertTrue(totalEnergyCurrentLimitRes.getLeft()); Assert.assertEquals(ByteArray.toLong(totalEnergyCurrentLimitRes.getRight()), energyLimit); long energyWeight = 1_000_000_000L; - tempRepository.getDynamicPropertiesStore().put(TOTAL_ENERGY_WEIGHT, new BytesCapsule(ByteArray.fromLong(energyWeight))); - Pair totalEnergyWeightRes = getChainParameterPcc.execute(totalEnergyWeightId.getData()); + tempRepository.getDynamicPropertiesStore().put(TOTAL_ENERGY_WEIGHT, + new BytesCapsule(ByteArray.fromLong(energyWeight))); + Pair totalEnergyWeightRes = + getChainParameterPcc.execute(totalEnergyWeightId.getData()); Assert.assertTrue(totalEnergyWeightRes.getLeft()); Assert.assertEquals(ByteArray.toLong(totalEnergyWeightRes.getRight()), energyWeight); long delayDays = 3L; - tempRepository.getDynamicPropertiesStore().put(UNFREEZE_DELAY_DAYS, new BytesCapsule(ByteArray.fromLong(delayDays))); - Pair delayDaysRes = getChainParameterPcc.execute(unfreezeDelayDaysId.getData()); + tempRepository.getDynamicPropertiesStore().put(UNFREEZE_DELAY_DAYS, + new BytesCapsule(ByteArray.fromLong(delayDays))); + Pair delayDaysRes = + getChainParameterPcc.execute(unfreezeDelayDaysId.getData()); Assert.assertTrue(delayDaysRes.getLeft()); Assert.assertEquals(ByteArray.toLong(delayDaysRes.getRight()), delayDays); @@ -435,7 +468,8 @@ public void getChainParameterTest() { public void expireUnfreezeBalanceV2Test() { VMConfig.initAllowTvmFreezeV2(1L); - PrecompiledContract expireUnfreezeBalanceV2Pcc = createPrecompiledContract(expireUnfreezeBalanceV2Addr, OWNER_ADDRESS); + PrecompiledContract expireUnfreezeBalanceV2Pcc = + createPrecompiledContract(expireUnfreezeBalanceV2Addr, OWNER_ADDRESS); } From 7e07e55ff985320d9604fa837fd916d096e15310 Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 21 Oct 2022 00:59:54 +0800 Subject: [PATCH 0359/1197] fix(energy): simplify proposal check --- .../src/main/java/org/tron/core/actuator/VMActuator.java | 8 ++++---- .../src/main/java/org/tron/core/db/TransactionTrace.java | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index c32f9135577..9b3600ce6a8 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -547,8 +547,8 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi long availableEnergy = Math.addExact(leftFrozenEnergy, energyFromBalance); long energyFromFeeLimit = feeLimit / sunPerEnergy; - long newEnergyUsage = rootRepository.getAccountEnergyUsageFromFreeze(account); - if (VMConfig.allowTvmFreeze() || VMConfig.allowTvmFreezeV2()) { + if (VMConfig.allowTvmFreezeV2()) { + long newEnergyUsage = rootRepository.getAccountEnergyUsageFromFreeze(account); receipt.setCallerEnergyUsage(newEnergyUsage); account.setEnergyUsage(newEnergyUsage + min(leftFrozenEnergy, energyFromFeeLimit)); account.setLatestConsumeTimeForEnergy(rootRepository.getHeadSlot()); @@ -699,8 +699,8 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu ); } } - long newEnergyUsage = rootRepository.getAccountEnergyUsageFromFreeze(creator); - if (VMConfig.allowTvmFreeze() || VMConfig.allowTvmFreezeV2()) { + if (VMConfig.allowTvmFreezeV2()) { + long newEnergyUsage = rootRepository.getAccountEnergyUsageFromFreeze(creator); receipt.setOriginEnergyUsage(newEnergyUsage); creator.setEnergyUsage(creator.getEnergyUsage() + creatorEnergyLimit); creator.setLatestConsumeTimeForEnergy(rootRepository.getHeadSlot()); diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java index edef044d4c0..26aed26d8df 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java @@ -7,7 +7,6 @@ import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; import org.springframework.util.StringUtils; import org.tron.common.runtime.InternalTransaction.TrxType; import org.tron.common.runtime.ProgramResult; @@ -246,8 +245,10 @@ public void pay() throws BalanceInsufficientException { // originAccount Percent = 30% AccountCapsule origin = accountStore.get(originAccount); AccountCapsule caller = accountStore.get(callerAccount); - origin.setEnergyUsage(receipt.getOriginEnergyUsage()); - caller.setEnergyUsage(receipt.getCallerEnergyUsage()); + if (dynamicPropertiesStore.supportUnfreezeDelay()) { + origin.setEnergyUsage(receipt.getOriginEnergyUsage()); + caller.setEnergyUsage(receipt.getCallerEnergyUsage()); + } receipt.payEnergyBill( dynamicPropertiesStore, accountStore, forkController, origin, From 9a61f8ec1b7b14e5a50133c7bc8773cfd6e640af Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 21 Oct 2022 01:35:39 +0800 Subject: [PATCH 0360/1197] fix(test): force deactivate freeze v2 proposal before testing --- .../src/test/java/org/tron/common/runtime/vm/FreezeTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java index ba5456080e7..ae655e6eb24 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java @@ -148,6 +148,7 @@ public void init() throws Exception { VMConfig.initAllowTvmSolidity059(1); VMConfig.initAllowTvmIstanbul(1); VMConfig.initAllowTvmFreeze(1); + VMConfig.initAllowTvmFreezeV2(0); } private byte[] deployContract(String contractName, String code) throws Exception { From 0ee833a14ae08cd077e32a050617e0095574a940 Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 21 Oct 2022 01:44:25 +0800 Subject: [PATCH 0361/1197] func(freezeV1): move disable logic into v1 action --- .../org/tron/core/vm/OperationActions.java | 22 +++++-------------- .../org/tron/core/vm/OperationRegistry.java | 11 ---------- 2 files changed, 6 insertions(+), 27 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index db1bc9c8dbf..9895b24910f 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -736,23 +736,13 @@ public static void freezeAction(Program program) { DataWord frozenBalance = program.stackPop(); DataWord receiverAddress = program.stackPop(); - boolean result = program.freeze(receiverAddress, frozenBalance, resourceType ); - program.stackPush(result ? DataWord.ONE() : DataWord.ZERO()); - program.step(); - } - - public static void disabledFreezeAction(Program program) { - // after allow vote, check static - if (VMConfig.allowTvmVote() && program.isStaticCall()) { - throw new Program.StaticCallModificationException(); + if (VMConfig.allowTvmFreezeV2()) { + // after v2 activated, we just push zero to stack and do nothing + program.stackPush(DataWord.ZERO()); + } else { + boolean result = program.freeze(receiverAddress, frozenBalance, resourceType ); + program.stackPush(result ? DataWord.ONE() : DataWord.ZERO()); } - // 0 as bandwidth, 1 as energy - DataWord ignoredResourceType = program.stackPop(); - DataWord ignoredFrozenBalance = program.stackPop(); - DataWord ignoredReceiverAddress = program.stackPop(); - - // here we just push zero to stack and do nothing - program.stackPush(DataWord.ZERO()); program.step(); } diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index a0f4f653f0d..3660ab5ae4c 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -59,9 +59,6 @@ public static JumpTable getTable() { if (VMConfig.allowHigherLimitForMaxCpuTimeOfOneTx()) { adjustMemOperations(table); } - if (VMConfig.allowTvmFreezeV2()) { - disableFreezeOperation(table); - } return table; } @@ -621,12 +618,4 @@ public static void appendDelegateOperations(JumpTable table) { OperationActions::unDelegateResourceAction, proposal)); } - - public static void disableFreezeOperation(JumpTable table) { - table.set(new Operation( - Op.FREEZE, 3, 1, - EnergyCost::getExtTierCost, - OperationActions::disabledFreezeAction, - VMConfig::allowTvmFreeze)); - } } From b40273b6d15163a949bffc3cf98a05cf05590d5b Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 21 Oct 2022 02:49:52 +0800 Subject: [PATCH 0362/1197] fix(code): resolve sonar issues --- .../src/main/java/org/tron/core/vm/ChainParameterEnum.java | 3 +-- actuator/src/main/java/org/tron/core/vm/program/Program.java | 4 ++-- .../main/java/org/tron/core/vm/repository/RepositoryImpl.java | 4 ---- .../java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java | 2 +- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/ChainParameterEnum.java b/actuator/src/main/java/org/tron/core/vm/ChainParameterEnum.java index 8fb6b5a9836..217747312bd 100644 --- a/actuator/src/main/java/org/tron/core/vm/ChainParameterEnum.java +++ b/actuator/src/main/java/org/tron/core/vm/ChainParameterEnum.java @@ -1,12 +1,11 @@ package org.tron.core.vm; import java.util.function.Function; - import org.tron.core.store.DynamicPropertiesStore; public enum ChainParameterEnum { - INVALID_PARAMETER_KEY(0, (any) -> 0L), + INVALID_PARAMETER_KEY(0, ignored -> 0L), TOTAL_ENERGY_CURRENT_LIMIT(1, DynamicPropertiesStore::getTotalEnergyCurrentLimit), diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index e4e161c9dfa..7b84877c5ab 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -580,7 +580,7 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit inheritorCapsule.setBalance(inheritorCapsule.getBalance() + expireUnfrozenBalance); increaseNonce(); addInternalTx(null, ownerAddr, inheritorAddr, expireUnfrozenBalance, null, - "withdrawExpireUnfreeze", nonce, null); + "withdrawExpireUnfreezeWhileSuiciding", nonce, null); } repo.updateAccount(inheritorCapsule.createDbKey(), inheritorCapsule); @@ -1904,7 +1904,7 @@ public boolean unfreezeBalanceV2(DataWord unfreezeBalance, DataWord resourceType if (unfreezeExpireBalance > 0) { increaseNonce(); addInternalTx(null, owner, owner, unfreezeExpireBalance, null, - "withdrawExpireUnfreeze", nonce, null); + "withdrawExpireUnfreezeWhileUnfreezing", nonce, null); } return true; } catch (ContractValidateException e) { diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index b35be0d4f15..9f0836a2d9e 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -746,10 +746,6 @@ public BlockCapsule getBlockByNum(long num) { } } - private long increase(long lastUsage, long usage, long lastTime, long now) { - return increase(lastUsage, usage, lastTime, now, windowSize); - } - // new recover method, use personal window size. private long recover(long lastUsage, long lastTime, long now, long personalWindowSize) { return increase(lastUsage, 0, lastTime, now, personalWindowSize); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 4da6fe4b1e2..2f982398906 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -778,7 +778,7 @@ public String getCall(CallArguments transactionCall, Object blockParamObj) ByteArray.fromHexString(transactionCall.getData())); } else { try { - ByteArray.hexToBigInteger(blockNumOrTag).longValue(); + long ignored = ByteArray.hexToBigInteger(blockNumOrTag).longValue(); } catch (Exception e) { throw new JsonRpcInvalidParamsException(BLOCK_NUM_ERROR); } From 400eb35abff8088ac658241768708c9e9618c149 Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 21 Oct 2022 03:50:10 +0800 Subject: [PATCH 0363/1197] fix(code): resolve sonar issues --- .../main/java/org/tron/core/vm/repository/RepositoryImpl.java | 2 -- .../java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 9f0836a2d9e..06f01431d19 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -70,8 +70,6 @@ public class RepositoryImpl implements Repository { private final long precision = Parameter.ChainConstant.PRECISION; - private final long windowSize = Parameter.ChainConstant.WINDOW_SIZE_MS - / BLOCK_PRODUCED_INTERVAL; private static final byte[] TOTAL_NET_WEIGHT = "TOTAL_NET_WEIGHT".getBytes(); private static final byte[] TOTAL_ENERGY_WEIGHT = "TOTAL_ENERGY_WEIGHT".getBytes(); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 2f982398906..3d44815d06e 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -778,7 +778,7 @@ public String getCall(CallArguments transactionCall, Object blockParamObj) ByteArray.fromHexString(transactionCall.getData())); } else { try { - long ignored = ByteArray.hexToBigInteger(blockNumOrTag).longValue(); + ByteArray.hexToBigInteger(blockNumOrTag); } catch (Exception e) { throw new JsonRpcInvalidParamsException(BLOCK_NUM_ERROR); } From 1f900f23aec2f688cdbf8cf9655adfa9abfac93b Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Fri, 21 Oct 2022 11:26:00 +0800 Subject: [PATCH 0364/1197] feat(freezeV2): add test for availableUnfreezeV2Size PrecompiledContract --- .../org/tron/core/vm/utils/FreezeV2Util.java | 2 +- .../runtime/vm/PrecompiledContractsTest.java | 40 ++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index deb3ad22aac..e640310737c 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -115,7 +115,7 @@ public static long queryAvailableUnfreezeV2Size(byte[] address, Repository repos return 0L; } - long now = repository.getHeadSlot(); + long now = repository.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); int unfreezingV2Count = accountCapsule.getUnfreezingV2Count(now); return Long.max(UnfreezeBalanceV2Actuator.getUNFREEZE_MAX_TIMES() - unfreezingV2Count, 0L); } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index 6a01c745825..1d7c83ba316 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -44,9 +44,11 @@ import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.repository.Repository; import org.tron.core.vm.repository.RepositoryImpl; +import org.tron.protos.Protocol; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Proposal.State; import org.tron.protos.contract.BalanceContract.FreezeBalanceContract; +import org.tron.protos.contract.Common; @Slf4j public class PrecompiledContractsTest { @@ -111,6 +113,7 @@ public class PrecompiledContractsTest { // withdraw private static final long initBalance = 10_000_000_000L; private static final long allowance = 32_000_000L; + private static final long latestTimestamp = 1_000_000L; private static TronApplicationContext context; private static Application appT; private static Manager dbManager; @@ -179,7 +182,7 @@ public void createCapsule() { .put(ownerAccountFirstCapsule.getAddress().toByteArray(), ownerAccountFirstCapsule); dbManager.getWitnessStore().put(witnessCapsule.getAddress().toByteArray(), witnessCapsule); - dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(1000000); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(latestTimestamp); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(10); dbManager.getDynamicPropertiesStore().saveNextMaintenanceTime(2000000); } @@ -464,6 +467,41 @@ public void getChainParameterTest() { } + @Test + public void availableUnfreezeV2SizeTest() { + VMConfig.initAllowTvmFreezeV2(1L); + + PrecompiledContract availableUnfreezeV2SizePcc = createPrecompiledContract(availableUnfreezeV2SizeAddr, OWNER_ADDRESS); + Repository tempRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + availableUnfreezeV2SizePcc.setRepository(tempRepository); + + byte[] data = new DataWord(ByteArray.fromHexString(OWNER_ADDRESS)).getData(); + byte[] address = ByteArray.fromHexString(OWNER_ADDRESS); + + Pair res = availableUnfreezeV2SizePcc.execute(data); + + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(32L, ByteArray.toLong(res.getRight())); + + AccountCapsule accountCapsule = tempRepository.getAccount(address); + accountCapsule.addUnfrozenV2List(Common.ResourceCode.BANDWIDTH, 1_000_000L, latestTimestamp + 86_400_000L); + accountCapsule.addUnfrozenV2List(Common.ResourceCode.ENERGY, 1_000_000L, latestTimestamp + 86_400_000L); + + tempRepository.putAccountValue(address, accountCapsule); + res = availableUnfreezeV2SizePcc.execute(data); + + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(30L, ByteArray.toLong(res.getRight())); + + // expired unfreeze action, available size keep the same. + accountCapsule.addUnfrozenV2List(Common.ResourceCode.ENERGY, 1_000_000L, latestTimestamp - 100_000L); + + tempRepository.putAccountValue(address, accountCapsule); + res = availableUnfreezeV2SizePcc.execute(data); + + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(30L, ByteArray.toLong(res.getRight())); + } @Test public void expireUnfreezeBalanceV2Test() { VMConfig.initAllowTvmFreezeV2(1L); From b791dd72a0cf45009477a155a3cf195580a72b10 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Fri, 21 Oct 2022 11:59:44 +0800 Subject: [PATCH 0365/1197] feat(freezeV2): optimize code format for check style --- .../common/runtime/vm/PrecompiledContractsTest.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index 1d7c83ba316..40caf975caa 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -471,7 +471,8 @@ public void getChainParameterTest() { public void availableUnfreezeV2SizeTest() { VMConfig.initAllowTvmFreezeV2(1L); - PrecompiledContract availableUnfreezeV2SizePcc = createPrecompiledContract(availableUnfreezeV2SizeAddr, OWNER_ADDRESS); + PrecompiledContract availableUnfreezeV2SizePcc = + createPrecompiledContract(availableUnfreezeV2SizeAddr, OWNER_ADDRESS); Repository tempRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); availableUnfreezeV2SizePcc.setRepository(tempRepository); @@ -484,8 +485,10 @@ public void availableUnfreezeV2SizeTest() { Assert.assertEquals(32L, ByteArray.toLong(res.getRight())); AccountCapsule accountCapsule = tempRepository.getAccount(address); - accountCapsule.addUnfrozenV2List(Common.ResourceCode.BANDWIDTH, 1_000_000L, latestTimestamp + 86_400_000L); - accountCapsule.addUnfrozenV2List(Common.ResourceCode.ENERGY, 1_000_000L, latestTimestamp + 86_400_000L); + accountCapsule.addUnfrozenV2List( + Common.ResourceCode.BANDWIDTH, 1_000_000L, latestTimestamp + 86_400_000L); + accountCapsule.addUnfrozenV2List( + Common.ResourceCode.ENERGY, 1_000_000L, latestTimestamp + 86_400_000L); tempRepository.putAccountValue(address, accountCapsule); res = availableUnfreezeV2SizePcc.execute(data); @@ -494,7 +497,8 @@ public void availableUnfreezeV2SizeTest() { Assert.assertEquals(30L, ByteArray.toLong(res.getRight())); // expired unfreeze action, available size keep the same. - accountCapsule.addUnfrozenV2List(Common.ResourceCode.ENERGY, 1_000_000L, latestTimestamp - 100_000L); + accountCapsule.addUnfrozenV2List( + Common.ResourceCode.ENERGY, 1_000_000L, latestTimestamp - 100_000L); tempRepository.putAccountValue(address, accountCapsule); res = availableUnfreezeV2SizePcc.execute(data); From 6d71f2e1c2c32fbb2247b39d60e322176398233a Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Fri, 21 Oct 2022 12:10:10 +0800 Subject: [PATCH 0366/1197] feat(freezeV2): optimize code format for check style --- .../org/tron/common/runtime/vm/PrecompiledContractsTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index 40caf975caa..7a2d5fae544 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -506,6 +506,7 @@ public void availableUnfreezeV2SizeTest() { Assert.assertTrue(res.getLeft()); Assert.assertEquals(30L, ByteArray.toLong(res.getRight())); } + @Test public void expireUnfreezeBalanceV2Test() { VMConfig.initAllowTvmFreezeV2(1L); From 2e3c01cd90fd1e82c6f6a23933aa3a0c805f73e5 Mon Sep 17 00:00:00 2001 From: Liulei Date: Fri, 21 Oct 2022 15:17:41 +0800 Subject: [PATCH 0367/1197] feat(freezeV2): add freezeV2 pcc test --- .../tron/common/runtime/vm/FreezeV2Test.java | 22 +++-- .../runtime/vm/PrecompiledContractsTest.java | 96 +++++++++++++++++++ 2 files changed, 111 insertions(+), 7 deletions(-) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java index c49a5031a13..9c06ef83d95 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -447,22 +447,30 @@ private TVMTestResult unfreezeV2( AccountCapsule newOwner = accountStore.get(contractAddr); if (res == 0) { - Assert.assertEquals(0, newOwner.getFrozenV2BalanceForBandwidth()); - Assert.assertEquals(oldTotalNetWeight - frozenBalance / TRX_PRECISION, - dynamicStore.getTotalNetWeight()); + Assert.assertEquals( + oldOwner.getFrozenV2BalanceForBandwidth() - unfreezeBalance, + newOwner.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals( + oldTotalNetWeight - unfreezeBalance / TRX_PRECISION, dynamicStore.getTotalNetWeight()); Assert.assertEquals(oldTotalEnergyWeight, dynamicStore.getTotalEnergyWeight()); Assert.assertEquals(oldTotalTronPowerWeight, dynamicStore.getTotalTronPowerWeight()); } else if (res == 1) { - Assert.assertEquals(0, newOwner.getFrozenV2BalanceForEnergy()); + Assert.assertEquals( + oldOwner.getFrozenV2BalanceForEnergy() - unfreezeBalance, + newOwner.getFrozenV2BalanceForEnergy()); Assert.assertEquals(oldTotalNetWeight, dynamicStore.getTotalNetWeight()); Assert.assertEquals(oldTotalTronPowerWeight, dynamicStore.getTotalTronPowerWeight()); - Assert.assertEquals(oldTotalEnergyWeight - frozenBalance / TRX_PRECISION, + Assert.assertEquals( + oldTotalEnergyWeight - unfreezeBalance / TRX_PRECISION, dynamicStore.getTotalEnergyWeight()); } else { - Assert.assertEquals(0, newOwner.getTronPowerFrozenV2Balance()); + Assert.assertEquals( + oldOwner.getTronPowerFrozenV2Balance() - unfreezeBalance, + newOwner.getTronPowerFrozenV2Balance()); Assert.assertEquals(oldTotalEnergyWeight, dynamicStore.getTotalEnergyWeight()); Assert.assertEquals(oldTotalNetWeight, dynamicStore.getTotalNetWeight()); - Assert.assertEquals(oldTotalTronPowerWeight - frozenBalance / TRX_PRECISION, + Assert.assertEquals( + oldTotalTronPowerWeight - unfreezeBalance / TRX_PRECISION, dynamicStore.getTotalTronPowerWeight()); } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index 7a2d5fae544..8034f40f12e 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -507,13 +507,109 @@ public void availableUnfreezeV2SizeTest() { Assert.assertEquals(30L, ByteArray.toLong(res.getRight())); } + @Test + public void unfreezableBalanceV2Test() { + VMConfig.initAllowTvmFreezeV2(1L); + + PrecompiledContract unfreezableBalanceV2Pcc = + createPrecompiledContract(unfreezableBalanceV2Addr, OWNER_ADDRESS); + Repository tempRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + unfreezableBalanceV2Pcc.setRepository(tempRepository); + + byte[] address = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] address32 = new DataWord(ByteArray.fromHexString(OWNER_ADDRESS)).getData(); + byte[] type = ByteUtil.longTo32Bytes(0); + byte[] data = ByteUtil.merge(address32, type); + + Pair res = unfreezableBalanceV2Pcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(0, ByteArray.toLong(res.getRight())); + + AccountCapsule accountCapsule = tempRepository.getAccount(address); + accountCapsule.addFrozenBalanceForBandwidthV2(1_000_000L); + tempRepository.putAccountValue(address, accountCapsule); + res = unfreezableBalanceV2Pcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(1_000_000L, ByteArray.toLong(res.getRight())); + + accountCapsule.addFrozenBalanceForBandwidthV2(1_000_000L); + tempRepository.putAccountValue(address, accountCapsule); + res = unfreezableBalanceV2Pcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(2_000_000L, ByteArray.toLong(res.getRight())); + + type = ByteUtil.longTo32Bytes(1); + data = ByteUtil.merge(address32, type); + accountCapsule.addFrozenBalanceForEnergyV2(1_000_000L); + tempRepository.putAccountValue(address, accountCapsule); + res = unfreezableBalanceV2Pcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(1_000_000L, ByteArray.toLong(res.getRight())); + + type = ByteUtil.longTo32Bytes(2); + data = ByteUtil.merge(address32, type); + accountCapsule.addFrozenForTronPowerV2(1_000_000L); + tempRepository.putAccountValue(address, accountCapsule); + res = unfreezableBalanceV2Pcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(1_000_000L, ByteArray.toLong(res.getRight())); + } + @Test public void expireUnfreezeBalanceV2Test() { VMConfig.initAllowTvmFreezeV2(1L); PrecompiledContract expireUnfreezeBalanceV2Pcc = createPrecompiledContract(expireUnfreezeBalanceV2Addr, OWNER_ADDRESS); + Repository tempRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + expireUnfreezeBalanceV2Pcc.setRepository(tempRepository); + long now = dbManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); + + byte[] address = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] address32 = new DataWord(ByteArray.fromHexString(OWNER_ADDRESS)).getData(); + byte[] time = ByteUtil.longTo32Bytes(now / 1000); + byte[] data = ByteUtil.merge(address32, time); + Pair res = expireUnfreezeBalanceV2Pcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(0, ByteArray.toLong(res.getRight())); + + AccountCapsule accountCapsule = tempRepository.getAccount(address); + Protocol.Account.UnFreezeV2 unFreezeV2 = + Protocol.Account.UnFreezeV2.newBuilder() + .setType(Common.ResourceCode.BANDWIDTH) + .setUnfreezeExpireTime(now) + .setUnfreezeAmount(1_000_000L) + .build(); + accountCapsule.addUnfrozenV2(unFreezeV2); + tempRepository.putAccountValue(address, accountCapsule); + res = expireUnfreezeBalanceV2Pcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(1_000_000L, ByteArray.toLong(res.getRight())); + + unFreezeV2 = + Protocol.Account.UnFreezeV2.newBuilder() + .setType(Common.ResourceCode.ENERGY) + .setUnfreezeExpireTime(now) + .setUnfreezeAmount(1_000_000L) + .build(); + accountCapsule.addUnfrozenV2(unFreezeV2); + tempRepository.putAccountValue(address, accountCapsule); + res = expireUnfreezeBalanceV2Pcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(2_000_000L, ByteArray.toLong(res.getRight())); + + unFreezeV2 = + Protocol.Account.UnFreezeV2.newBuilder() + .setType(Common.ResourceCode.TRON_POWER) + .setUnfreezeExpireTime(now + 1_000_000L) + .setUnfreezeAmount(1_000_000L) + .build(); + accountCapsule.addUnfrozenV2(unFreezeV2); + tempRepository.putAccountValue(address, accountCapsule); + res = expireUnfreezeBalanceV2Pcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(2_000_000L, ByteArray.toLong(res.getRight())); } @Test From 6924e09860f491cd08b8dcecf402ed722578854c Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Fri, 21 Oct 2022 17:17:06 +0800 Subject: [PATCH 0368/1197] feat(freezeV2): optimize calculation and add unit tests for freezeV2 precompiledContracts --- .../org/tron/core/vm/utils/FreezeV2Util.java | 4 +- .../runtime/vm/PrecompiledContractsTest.java | 178 ++++++++++++++++++ 2 files changed, 180 insertions(+), 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index e640310737c..583f96f347f 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -152,7 +152,7 @@ public static long queryDelegatableResource(byte[] address, long type, Repositor return 0L; } - return frozenV2Resource * (totalResource - usage) / totalResource; + return (long) (frozenV2Resource * ((double) (totalResource - usage) / totalResource)); } if (type == 1) { @@ -177,7 +177,7 @@ public static long queryDelegatableResource(byte[] address, long type, Repositor return 0L; } - return frozenV2Resource * (totalResource - usage) / totalResource; + return (long) (frozenV2Resource * ((double) (totalResource - usage) / totalResource)); } return 0L; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index 8034f40f12e..7e0d0368563 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -1,5 +1,6 @@ package org.tron.common.runtime.vm; +import static org.tron.common.utils.ByteUtil.stripLeadingZeroes; import static org.tron.core.db.TransactionTrace.convertToTronAddress; import com.google.protobuf.Any; @@ -7,6 +8,7 @@ import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; + import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; import org.bouncycastle.util.Arrays; @@ -42,8 +44,10 @@ import org.tron.core.vm.PrecompiledContracts; import org.tron.core.vm.PrecompiledContracts.PrecompiledContract; import org.tron.core.vm.config.VMConfig; +import org.tron.core.vm.repository.Key; import org.tron.core.vm.repository.Repository; import org.tron.core.vm.repository.RepositoryImpl; +import org.tron.core.vm.repository.Value; import org.tron.protos.Protocol; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Proposal.State; @@ -411,6 +415,87 @@ public void tvmFreezeV2SwitchTest() { Assert.assertNotNull(totalAcquiredResourcePcc); } + @Test + public void delegatableResourceTest() { + VMConfig.initAllowTvmFreezeV2(1L); + + PrecompiledContract delegatableResourcePcc = + createPrecompiledContract(delegatableResourceAddr, OWNER_ADDRESS); + Repository tempRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + delegatableResourcePcc.setRepository(tempRepository); + + byte[] owner = new DataWord(ByteArray.fromHexString(OWNER_ADDRESS)).getData(); + byte[] zero = DataWord.ZERO().getData(); + byte[] one = new DataWord(1).getData(); + byte[] address = ByteArray.fromHexString(OWNER_ADDRESS); + + Pair res = delegatableResourcePcc.execute(null); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(0L, ByteArray.toLong(res.getRight())); + + res = delegatableResourcePcc.execute(encodeMultiWord(one, zero)); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(0L, ByteArray.toLong(res.getRight())); + + res = delegatableResourcePcc.execute(encodeMultiWord(owner, owner)); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(0L, ByteArray.toLong(res.getRight())); + + AccountCapsule accountCapsule = tempRepository.getAccount(address); + accountCapsule.setAcquiredDelegatedFrozenBalanceForEnergy(10_000_000L); + accountCapsule.addFrozenBalanceForBandwidthV2(5_000_000L); + accountCapsule.addFrozenBalanceForEnergyV2(10_000_000L); + + tempRepository.putAccountValue(address, accountCapsule); + + res = delegatableResourcePcc.execute(encodeMultiWord(owner, zero)); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(5_000_000L, ByteArray.toLong(res.getRight())); + + res = delegatableResourcePcc.execute(encodeMultiWord(owner, one)); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(10_000_000L, ByteArray.toLong(res.getRight())); + + // with usage. + byte[] TOTAL_ENERGY_CURRENT_LIMIT = "TOTAL_ENERGY_CURRENT_LIMIT".getBytes(); + byte[] TOTAL_ENERGY_WEIGHT = "TOTAL_ENERGY_WEIGHT".getBytes(); + + long energyLimit = 1_000_000_000_000L; + tempRepository.getDynamicPropertiesStore().put(TOTAL_ENERGY_CURRENT_LIMIT, + new BytesCapsule(ByteArray.fromLong(energyLimit))); + + long energyWeight = 1_000_000L; // unit: trx +// tempRepository.getDynamicPropertiesStore().put(TOTAL_ENERGY_WEIGHT, +// new BytesCapsule(ByteArray.fromLong(energyWeight))); + tempRepository.saveTotalEnergyWeight(energyWeight); + + // used all energy, recovered 1/2, delegatable: 1/2 + accountCapsule.setEnergyUsage(20_000_000L); + + long currentSlot = latestTimestamp / 3_000; + accountCapsule.setLatestConsumeTimeForEnergy(0L); + accountCapsule.setNewWindowSize(Common.ResourceCode.ENERGY, currentSlot * 2); + tempRepository.putAccountValue(address, accountCapsule); + + res = delegatableResourcePcc.execute(encodeMultiWord(owner, one)); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(5_000_000L, ByteArray.toLong(res.getRight())); + + // all recovered. + accountCapsule.setNewWindowSize(Common.ResourceCode.ENERGY, currentSlot); + tempRepository.putAccountValue(address, accountCapsule); + res = delegatableResourcePcc.execute(encodeMultiWord(owner, one)); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(10_000_000L, ByteArray.toLong(res.getRight())); + + // all used. + accountCapsule.setLatestConsumeTimeForEnergy(currentSlot); + tempRepository.putAccountValue(address, accountCapsule); + res = delegatableResourcePcc.execute(encodeMultiWord(owner, one)); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(0L, ByteArray.toLong(res.getRight())); + } + @Test public void getChainParameterTest() { VMConfig.initAllowTvmFreezeV2(1L); @@ -553,6 +638,40 @@ public void unfreezableBalanceV2Test() { res = unfreezableBalanceV2Pcc.execute(data); Assert.assertTrue(res.getLeft()); Assert.assertEquals(1_000_000L, ByteArray.toLong(res.getRight())); + + // new test round + tempRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + unfreezableBalanceV2Pcc.setRepository(tempRepository); + + byte[] owner = new DataWord(ByteArray.fromHexString(OWNER_ADDRESS)).getData(); + byte[] zero = DataWord.ZERO().getData(); + byte[] one = new DataWord(1).getData(); + + Pair result = unfreezableBalanceV2Pcc.execute(null); + Assert.assertTrue(result.getLeft()); + Assert.assertEquals(0L, ByteArray.toLong(result.getRight())); + + result = unfreezableBalanceV2Pcc.execute(encodeMultiWord(one, zero)); + Assert.assertTrue(result.getLeft()); + Assert.assertEquals(0L, ByteArray.toLong(result.getRight())); + + result = unfreezableBalanceV2Pcc.execute(encodeMultiWord(owner, owner)); + Assert.assertTrue(result.getLeft()); + Assert.assertEquals(0L, ByteArray.toLong(result.getRight())); + + AccountCapsule capsule = tempRepository.getAccount(address); + capsule.addFrozenBalanceForBandwidthV2(5_000_000L); + capsule.addFrozenBalanceForEnergyV2(10_000_000L); + + tempRepository.putAccountValue(address, capsule); + + result = unfreezableBalanceV2Pcc.execute(encodeMultiWord(owner, zero)); + Assert.assertTrue(result.getLeft()); + Assert.assertEquals(5_000_000L, ByteArray.toLong(result.getRight())); + + result = unfreezableBalanceV2Pcc.execute(encodeMultiWord(owner, one)); + Assert.assertTrue(result.getLeft()); + Assert.assertEquals(10_000_000L, ByteArray.toLong(result.getRight())); } @Test @@ -610,6 +729,46 @@ public void expireUnfreezeBalanceV2Test() { res = expireUnfreezeBalanceV2Pcc.execute(data); Assert.assertTrue(res.getLeft()); Assert.assertEquals(2_000_000L, ByteArray.toLong(res.getRight())); + + // new test round + tempRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + expireUnfreezeBalanceV2Pcc.setRepository(tempRepository); + + byte[] owner = new DataWord(ByteArray.fromHexString(OWNER_ADDRESS)).getData(); + address = ByteArray.fromHexString(OWNER_ADDRESS); + + Pair result = expireUnfreezeBalanceV2Pcc.execute(null); + + Assert.assertTrue(result.getLeft()); + Assert.assertEquals(0L, ByteArray.toLong(result.getRight())); + + result = expireUnfreezeBalanceV2Pcc.execute( + encodeMultiWord(DataWord.ZERO().getData(), DataWord.ZERO().getData())); + Assert.assertTrue(result.getLeft()); + Assert.assertEquals(0L, ByteArray.toLong(result.getRight())); + + result = expireUnfreezeBalanceV2Pcc.execute( + encodeMultiWord(owner, new DataWord(latestTimestamp / 1_000L).getData())); + Assert.assertTrue(result.getLeft()); + Assert.assertEquals(0L, ByteArray.toLong(result.getRight())); + + accountCapsule = tempRepository.getAccount(address); + accountCapsule.addUnfrozenV2List( + Common.ResourceCode.BANDWIDTH, 1_000_000L, latestTimestamp); + accountCapsule.addUnfrozenV2List( + Common.ResourceCode.ENERGY, 1_000_000L, latestTimestamp + 86_400_000L); + + tempRepository.putAccountValue(address, accountCapsule); + + result = expireUnfreezeBalanceV2Pcc.execute( + encodeMultiWord(owner, new DataWord(latestTimestamp / 1_000L).getData())); + Assert.assertTrue(result.getLeft()); + Assert.assertEquals(1_000_000L, ByteArray.toLong(result.getRight())); + + result = expireUnfreezeBalanceV2Pcc.execute( + encodeMultiWord(owner, new DataWord((latestTimestamp + 86_400_000L) / 1_000L).getData())); + Assert.assertTrue(result.getLeft()); + Assert.assertEquals(2_000_000L, ByteArray.toLong(result.getRight())); } @Test @@ -636,4 +795,23 @@ public void convertFromTronBase58AddressNative() { new DataWord(Hex.decode(WITNESS_ADDRESS_BASE)).getData()); } + private static byte[] encodeMultiWord(byte[]... words) { + if (words == null) { + return null; + } + if (words.length == 1) { + return words[0]; + } + + byte[] res = new byte[words.length * 32]; + + for (int i = 0; i < words.length; i++) { + byte[] word = stripLeadingZeroes(words[i]); + + System.arraycopy(word, 0, res, 32 * (i + 1) - word.length, word.length); + } + + return res; + } + } From 7fd85439b3cf78e476a1fab08f1ca28d7379dc26 Mon Sep 17 00:00:00 2001 From: Liulei Date: Fri, 21 Oct 2022 17:21:04 +0800 Subject: [PATCH 0369/1197] feat(freezeV2): add freezeV2 pcc test --- .../runtime/vm/PrecompiledContractsTest.java | 202 +++++++++++++++++- 1 file changed, 198 insertions(+), 4 deletions(-) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index 7e0d0368563..bafa6c33c2e 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -24,6 +24,7 @@ import org.tron.common.runtime.ProgramResult; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; +import org.tron.common.utils.Commons; import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.core.Constant; @@ -31,6 +32,7 @@ import org.tron.core.actuator.FreezeBalanceActuator; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BytesCapsule; +import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.ProposalCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.WitnessCapsule; @@ -44,10 +46,8 @@ import org.tron.core.vm.PrecompiledContracts; import org.tron.core.vm.PrecompiledContracts.PrecompiledContract; import org.tron.core.vm.config.VMConfig; -import org.tron.core.vm.repository.Key; import org.tron.core.vm.repository.Repository; import org.tron.core.vm.repository.RepositoryImpl; -import org.tron.core.vm.repository.Value; import org.tron.protos.Protocol; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Proposal.State; @@ -602,7 +602,7 @@ public void unfreezableBalanceV2Test() { unfreezableBalanceV2Pcc.setRepository(tempRepository); byte[] address = ByteArray.fromHexString(OWNER_ADDRESS); - byte[] address32 = new DataWord(ByteArray.fromHexString(OWNER_ADDRESS)).getData(); + byte[] address32 = new DataWord(address).getData(); byte[] type = ByteUtil.longTo32Bytes(0); byte[] data = ByteUtil.merge(address32, type); @@ -685,7 +685,7 @@ public void expireUnfreezeBalanceV2Test() { long now = dbManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); byte[] address = ByteArray.fromHexString(OWNER_ADDRESS); - byte[] address32 = new DataWord(ByteArray.fromHexString(OWNER_ADDRESS)).getData(); + byte[] address32 = new DataWord(address).getData(); byte[] time = ByteUtil.longTo32Bytes(now / 1000); byte[] data = ByteUtil.merge(address32, time); @@ -771,6 +771,200 @@ public void expireUnfreezeBalanceV2Test() { Assert.assertEquals(2_000_000L, ByteArray.toLong(result.getRight())); } + @Test + public void resourceV2Test() { + VMConfig.initAllowTvmFreezeV2(1L); + + PrecompiledContract resourceV2Pcc = + createPrecompiledContract(resourceV2Addr, OWNER_ADDRESS); + Repository tempRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + resourceV2Pcc.setRepository(tempRepository); + + String targetStr = "27k66nycZATHzBasFT9782nTsYWqVtxdtAc"; + byte[] targetAddr = Commons.decode58Check(targetStr); + byte[] target = new DataWord(targetAddr).getData(); + String fromStr = "27jzp7nVEkH4Hf3H1PHPp4VDY7DxTy5eydL"; + byte[] fromAddr = Commons.decode58Check(fromStr); + byte[] from = new DataWord(fromAddr).getData(); + byte[] type = ByteUtil.longTo32Bytes(0); + byte[] data = ByteUtil.merge(target, from, type); + + Pair res = resourceV2Pcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(0, ByteArray.toLong(res.getRight())); + + AccountCapsule fromAccount = + tempRepository.createAccount(fromAddr, Protocol.AccountType.Normal); + fromAccount.addFrozenBalanceForBandwidthV2(1_000_000L); + tempRepository.putAccountValue(fromAddr, fromAccount); + data = ByteUtil.merge(from, from, type); + res = resourceV2Pcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(1_000_000L, ByteArray.toLong(res.getRight())); + + data = ByteUtil.merge(from, from, ByteUtil.longTo32Bytes(1)); + res = resourceV2Pcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(0, ByteArray.toLong(res.getRight())); + + AccountCapsule targetAccount = + tempRepository.createAccount(target, Protocol.AccountType.Normal); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(fromAddr, targetAddr); + DelegatedResourceCapsule delegatedResource = + new DelegatedResourceCapsule( + ByteString.copyFrom(fromAddr), ByteString.copyFrom(targetAddr)); + delegatedResource.setFrozenBalanceForBandwidth(1_000_000L, 0); + tempRepository.updateDelegatedResource(key, delegatedResource); + targetAccount.addAcquiredDelegatedFrozenBalanceForBandwidth(1_000_000L); + fromAccount.addDelegatedFrozenBalanceForBandwidth(1_000_000L); + tempRepository.putAccountValue(fromAddr, fromAccount); + tempRepository.putAccountValue(targetAddr, targetAccount); + data = ByteUtil.merge(target, from, type); + res = resourceV2Pcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(1_000_000L, ByteArray.toLong(res.getRight())); + + data = ByteUtil.merge(from, from, ByteUtil.longTo32Bytes(1)); + res = resourceV2Pcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(0, ByteArray.toLong(res.getRight())); + } + + @Test + public void totalResourceTest() { + VMConfig.initAllowTvmFreezeV2(1L); + + PrecompiledContract totalResourcePcc = + createPrecompiledContract(totalResourceAddr, OWNER_ADDRESS); + Repository tempRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + totalResourcePcc.setRepository(tempRepository); + + byte[] address = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] address32 = new DataWord(address).getData(); + byte[] type = ByteUtil.longTo32Bytes(0); + byte[] data = ByteUtil.merge(address32, type); + + Pair res = totalResourcePcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(0, ByteArray.toLong(res.getRight())); + + AccountCapsule accountCapsule = tempRepository.getAccount(address); + tempRepository.putAccountValue(address, accountCapsule); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(0, ByteArray.toLong(res.getRight())); + + accountCapsule = tempRepository.getAccount(address); + accountCapsule.addFrozenBalanceForBandwidthV2(1_000_000L); + tempRepository.putAccountValue(address, accountCapsule); + res = totalResourcePcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(1_000_000L, ByteArray.toLong(res.getRight())); + + accountCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(1_000_000L); + tempRepository.putAccountValue(address, accountCapsule); + res = totalResourcePcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(2_000_000L, ByteArray.toLong(res.getRight())); + + accountCapsule.addFrozenBalanceForEnergyV2(1_000_000L); + tempRepository.putAccountValue(address, accountCapsule); + type = ByteUtil.longTo32Bytes(1); + data = ByteUtil.merge(address32, type); + res = totalResourcePcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(1_000_000L, ByteArray.toLong(res.getRight())); + + res = totalResourcePcc.execute(ByteUtil.merge(address32, ByteUtil.longTo32Bytes(2))); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(0, ByteArray.toLong(res.getRight())); + } + + @Test + public void totalDelegatedResourceTest() { + VMConfig.initAllowTvmFreezeV2(1L); + + PrecompiledContract totalDelegatedResourcePcc = + createPrecompiledContract(totalDelegatedResourceAddr, OWNER_ADDRESS); + Repository tempRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + totalDelegatedResourcePcc.setRepository(tempRepository); + + byte[] address = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] address32 = new DataWord(address).getData(); + byte[] type = ByteUtil.longTo32Bytes(0); + byte[] data = ByteUtil.merge(address32, type); + + Pair res = totalDelegatedResourcePcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(0, ByteArray.toLong(res.getRight())); + + AccountCapsule accountCapsule = tempRepository.getAccount(address); + tempRepository.putAccountValue(address, accountCapsule); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(0, ByteArray.toLong(res.getRight())); + + accountCapsule = tempRepository.getAccount(address); + accountCapsule.addDelegatedFrozenBalanceForBandwidth(1_000_000L); + tempRepository.putAccountValue(address, accountCapsule); + res = totalDelegatedResourcePcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(1_000_000L, ByteArray.toLong(res.getRight())); + + accountCapsule.addDelegatedFrozenBalanceForEnergy(1_000_000L); + tempRepository.putAccountValue(address, accountCapsule); + type = ByteUtil.longTo32Bytes(1); + data = ByteUtil.merge(address32, type); + res = totalDelegatedResourcePcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(1_000_000L, ByteArray.toLong(res.getRight())); + + res = totalDelegatedResourcePcc.execute(ByteUtil.merge(address32, ByteUtil.longTo32Bytes(2))); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(0, ByteArray.toLong(res.getRight())); + } + + @Test + public void totalAcquiredResourceTest() { + VMConfig.initAllowTvmFreezeV2(1L); + + PrecompiledContract totalAcquiredResourcePcc = + createPrecompiledContract(totalAcquiredResourceAddr, OWNER_ADDRESS); + Repository tempRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + totalAcquiredResourcePcc.setRepository(tempRepository); + + byte[] address = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] address32 = new DataWord(address).getData(); + byte[] type = ByteUtil.longTo32Bytes(0); + byte[] data = ByteUtil.merge(address32, type); + + Pair res = totalAcquiredResourcePcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(0, ByteArray.toLong(res.getRight())); + + AccountCapsule accountCapsule = tempRepository.getAccount(address); + tempRepository.putAccountValue(address, accountCapsule); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(0, ByteArray.toLong(res.getRight())); + + accountCapsule = tempRepository.getAccount(address); + accountCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(1_000_000L); + tempRepository.putAccountValue(address, accountCapsule); + res = totalAcquiredResourcePcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(1_000_000L, ByteArray.toLong(res.getRight())); + + accountCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(1_000_000L); + tempRepository.putAccountValue(address, accountCapsule); + type = ByteUtil.longTo32Bytes(1); + data = ByteUtil.merge(address32, type); + res = totalAcquiredResourcePcc.execute(data); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(1_000_000L, ByteArray.toLong(res.getRight())); + + res = totalAcquiredResourcePcc.execute(ByteUtil.merge(address32, ByteUtil.longTo32Bytes(2))); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(0, ByteArray.toLong(res.getRight())); + } + @Test public void convertFromTronBytesAddressNativeTest() { } From 642d665cd3072bfd54b804c7eb2e2a556002d26c Mon Sep 17 00:00:00 2001 From: Liulei Date: Fri, 21 Oct 2022 18:04:21 +0800 Subject: [PATCH 0370/1197] feat(freezeV2): add freezeV2 pcc test --- .../UnfreezeBalanceV2Processor.java | 2 + .../runtime/vm/PrecompiledContractsTest.java | 46 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index 99fec720fdd..0f0cd6ad815 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -20,6 +20,7 @@ import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.vm.nativecontract.param.UnfreezeBalanceV2Param; import org.tron.core.vm.repository.Repository; +import org.tron.core.vm.utils.VoteRewardUtil; import org.tron.protos.Protocol; import org.tron.protos.contract.Common; @@ -123,6 +124,7 @@ public long execute(UnfreezeBalanceV2Param param, Repository repo) { AccountCapsule accountCapsule = repo.getAccount(ownerAddress); long now = repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); + VoteRewardUtil.withdrawReward(ownerAddress, repo); long unfreezeExpireBalance = this.unfreezeExpire(accountCapsule, now); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index bafa6c33c2e..a5b6263362c 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -830,6 +830,52 @@ public void resourceV2Test() { Assert.assertEquals(0, ByteArray.toLong(res.getRight())); } + @Test + public void resourceUsageTest() { + VMConfig.initAllowTvmFreezeV2(1L); + + PrecompiledContract resourceUsagePcc = + createPrecompiledContract(resourceUsageAddr, OWNER_ADDRESS); + Repository tempRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + resourceUsagePcc.setRepository(tempRepository); + + byte[] address = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] address32 = new DataWord(address).getData(); + byte[] type = ByteUtil.longTo32Bytes(0); + byte[] data = ByteUtil.merge(address32, type); + + Pair res = resourceUsagePcc.execute(data); + Assert.assertTrue(res.getLeft()); + byte[] usage = Arrays.copyOfRange(res.getRight(), 0, 32); + byte[] recoverDuration = Arrays.copyOfRange(res.getRight(), 32, 64); + Assert.assertEquals(0, ByteArray.toLong(usage)); + + // with usage. + byte[] TOTAL_ENERGY_CURRENT_LIMIT = "TOTAL_ENERGY_CURRENT_LIMIT".getBytes(); + + long energyLimit = 1_000_000_000_000L; + tempRepository.getDynamicPropertiesStore().put(TOTAL_ENERGY_CURRENT_LIMIT, + new BytesCapsule(ByteArray.fromLong(energyLimit))); + + long energyWeight = 1_000_000L; // unit: trx + tempRepository.saveTotalEnergyWeight(energyWeight); + + AccountCapsule accountCapsule = tempRepository.getAccount(address); + // used all energy, recovered 1/2, delegatable: 1/2 + accountCapsule.setEnergyUsage(20_000_000L); + + long currentSlot = latestTimestamp / 3_000; + accountCapsule.setLatestConsumeTimeForEnergy(0L); + accountCapsule.setNewWindowSize(Common.ResourceCode.ENERGY, currentSlot * 2); + tempRepository.putAccountValue(address, accountCapsule); + + type = ByteUtil.longTo32Bytes(1); + res = resourceUsagePcc.execute(encodeMultiWord(address32, type)); + Assert.assertTrue(res.getLeft()); + usage = Arrays.copyOfRange(res.getRight(), 0, 32); + Assert.assertEquals(10_000_000L, ByteArray.toLong(usage)); + } + @Test public void totalResourceTest() { VMConfig.initAllowTvmFreezeV2(1L); From 6d1c5a7039534579ad3bb441461c99350c807419 Mon Sep 17 00:00:00 2001 From: Liulei Date: Fri, 21 Oct 2022 18:36:27 +0800 Subject: [PATCH 0371/1197] feat(freezeV2): add freezeV2 pcc test --- .../runtime/vm/PrecompiledContractsTest.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index a5b6263362c..096b50b1b17 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -847,7 +847,6 @@ public void resourceUsageTest() { Pair res = resourceUsagePcc.execute(data); Assert.assertTrue(res.getLeft()); byte[] usage = Arrays.copyOfRange(res.getRight(), 0, 32); - byte[] recoverDuration = Arrays.copyOfRange(res.getRight(), 32, 64); Assert.assertEquals(0, ByteArray.toLong(usage)); // with usage. @@ -874,6 +873,22 @@ public void resourceUsageTest() { Assert.assertTrue(res.getLeft()); usage = Arrays.copyOfRange(res.getRight(), 0, 32); Assert.assertEquals(10_000_000L, ByteArray.toLong(usage)); + + accountCapsule.setNewWindowSize(Common.ResourceCode.ENERGY, currentSlot); + tempRepository.putAccountValue(address, accountCapsule); + res = resourceUsagePcc.execute(encodeMultiWord(address32, type)); + Assert.assertTrue(res.getLeft()); + usage = Arrays.copyOfRange(res.getRight(), 0, 32); + byte[] recoverDuration = Arrays.copyOfRange(res.getRight(), 32, 64); + Assert.assertEquals(0, ByteArray.toLong(usage)); + Assert.assertEquals(0, ByteArray.toLong(recoverDuration)); + + accountCapsule.setLatestConsumeTimeForEnergy(currentSlot); + tempRepository.putAccountValue(address, accountCapsule); + res = resourceUsagePcc.execute(encodeMultiWord(address32, type)); + Assert.assertTrue(res.getLeft()); + usage = Arrays.copyOfRange(res.getRight(), 0, 32); + Assert.assertEquals(20_000_000L, ByteArray.toLong(usage)); } @Test From 08b95f37368ae7fe07375b4371d859fbdec2f156 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Fri, 21 Oct 2022 18:43:34 +0800 Subject: [PATCH 0372/1197] feat(freezeV2): optimize getChainParameter precompiledContracts and add unit tests --- .../org/tron/core/vm/ChainParameterEnum.java | 20 ++- .../tron/core/vm/PrecompiledContracts.java | 20 ++- .../runtime/vm/PrecompiledContractsTest.java | 139 +++++++++++++++++- 3 files changed, 159 insertions(+), 20 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/ChainParameterEnum.java b/actuator/src/main/java/org/tron/core/vm/ChainParameterEnum.java index 217747312bd..0d9df91ef6c 100644 --- a/actuator/src/main/java/org/tron/core/vm/ChainParameterEnum.java +++ b/actuator/src/main/java/org/tron/core/vm/ChainParameterEnum.java @@ -1,25 +1,31 @@ package org.tron.core.vm; import java.util.function.Function; -import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.vm.repository.Repository; public enum ChainParameterEnum { INVALID_PARAMETER_KEY(0, ignored -> 0L), - TOTAL_ENERGY_CURRENT_LIMIT(1, DynamicPropertiesStore::getTotalEnergyCurrentLimit), + TOTAL_NET_LIMIT(1, repository -> repository.getDynamicPropertiesStore().getTotalNetLimit()), - TOTAL_ENERGY_WEIGHT(2, DynamicPropertiesStore::getTotalEnergyWeight), + TOTAL_NET_WEIGHT(2, Repository::getTotalNetWeight), - UNFREEZE_DELAY_DAYS(3, DynamicPropertiesStore::getUnfreezeDelayDays), + TOTAL_ENERGY_CURRENT_LIMIT(3, + repository -> repository.getDynamicPropertiesStore().getTotalEnergyCurrentLimit()), + + TOTAL_ENERGY_WEIGHT(4, Repository::getTotalEnergyWeight), + + UNFREEZE_DELAY_DAYS(5, + repository -> repository.getDynamicPropertiesStore().getUnfreezeDelayDays()), ; private final long code; - private final Function action; + private final Function action; - ChainParameterEnum(long code, Function action) { + ChainParameterEnum(long code, Function action) { this.code = code; this.action = action; } @@ -38,7 +44,7 @@ public long getCode() { return code; } - public Function getAction() { + public Function getAction() { return action; } } diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 0078892c06c..be415b9b4fa 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -1874,7 +1874,7 @@ public Pair execute(byte[] data) { long code = new DataWord(data).longValueSafe(); long res = ChainParameterEnum.fromCode(code).getAction().apply( - getDeposit().getDynamicPropertiesStore()); + getDeposit()); return Pair.of(true, longTo32Bytes(res)); } @@ -2014,7 +2014,8 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { if (data == null || data.length != 3 * WORD_SIZE) { - return Pair.of(true, encodeMultiRes(DataWord.ZERO().getData(), DataWord.ZERO().getData(), DataWord.ZERO().getData())); + return Pair.of(true, encodeMultiRes( + DataWord.ZERO().getData(), DataWord.ZERO().getData(), DataWord.ZERO().getData())); } DataWord[] words = DataWord.parseArray(data); @@ -2022,12 +2023,16 @@ public Pair execute(byte[] data) { long amount = words[1].longValueSafe(); long type = words[2].longValueSafe(); - Triple values = FreezeV2Util.checkUndelegateResource(target, amount, type, getDeposit()); - if (values == null || values.getLeft() == null || values.getMiddle() == null || values.getRight() == null) { - return Pair.of(true, encodeMultiRes(DataWord.ZERO().getData(), DataWord.ZERO().getData(), DataWord.ZERO().getData())); + Triple values = + FreezeV2Util.checkUndelegateResource(target, amount, type, getDeposit()); + if (values == null || values.getLeft() == null + || values.getMiddle() == null || values.getRight() == null) { + return Pair.of(true, encodeMultiRes( + DataWord.ZERO().getData(), DataWord.ZERO().getData(), DataWord.ZERO().getData())); } - return Pair.of(true, encodeMultiRes(longTo32Bytes(values.getLeft()), longTo32Bytes(values.getMiddle()), longTo32Bytes(values.getRight()))); + return Pair.of(true, encodeMultiRes(longTo32Bytes(values.getLeft()), + longTo32Bytes(values.getMiddle()), longTo32Bytes(values.getRight()))); } } @@ -2053,7 +2058,8 @@ public Pair execute(byte[] data) { return Pair.of(true, encodeRes(DataWord.ZERO().getData(), DataWord.ZERO().getData())); } - return Pair.of(true, encodeRes(longTo32Bytes(values.getLeft()), longTo32Bytes(values.getRight()))); + return Pair.of(true, encodeRes( + longTo32Bytes(values.getLeft()), longTo32Bytes(values.getRight()))); } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index 096b50b1b17..90852061f51 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -496,6 +496,113 @@ public void delegatableResourceTest() { Assert.assertEquals(0L, ByteArray.toLong(res.getRight())); } + @Test + public void checkUnDelegateResourceTest() { + VMConfig.initAllowTvmFreezeV2(1L); + + PrecompiledContract checkUnDelegateResourcePcc = + createPrecompiledContract(checkUnDelegateResourceAddr, OWNER_ADDRESS); + Repository tempRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + checkUnDelegateResourcePcc.setRepository(tempRepository); + + byte[] TOTAL_ENERGY_CURRENT_LIMIT = "TOTAL_ENERGY_CURRENT_LIMIT".getBytes(); + + long energyLimit = 1_000_000_000_000L; + tempRepository.getDynamicPropertiesStore().put(TOTAL_ENERGY_CURRENT_LIMIT, + new BytesCapsule(ByteArray.fromLong(energyLimit))); + + long energyWeight = 1_000_000L; // unit: trx +// tempRepository.getDynamicPropertiesStore().put(TOTAL_ENERGY_WEIGHT, +// new BytesCapsule(ByteArray.fromLong(energyWeight))); + tempRepository.saveTotalEnergyWeight(energyWeight); + + byte[] owner = new DataWord(ByteArray.fromHexString(OWNER_ADDRESS)).getData(); + byte[] zero = DataWord.ZERO().getData(); + byte[] one = new DataWord(1).getData(); + byte[] address = ByteArray.fromHexString(OWNER_ADDRESS); + + Pair res = checkUnDelegateResourcePcc.execute(null); + Assert.assertTrue(res.getLeft()); + Assert.assertArrayEquals(encodeMultiWord(zero, zero, zero), res.getRight()); + + res = checkUnDelegateResourcePcc.execute(encodeMultiWord(one, one, one)); + Assert.assertTrue(res.getLeft()); + Assert.assertArrayEquals(encodeMultiWord(zero, zero, zero), res.getRight()); + + res = checkUnDelegateResourcePcc.execute( + encodeMultiWord(owner, ByteArray.fromLong(1_000_000L), ByteArray.fromLong(10L))); + Assert.assertTrue(res.getLeft()); + Assert.assertArrayEquals(encodeMultiWord(zero, zero, zero), res.getRight()); + + long defaultWindowSizeMs = 86_400_000L; + long currentSlot = latestTimestamp / 3_000; + long defaultLeftTime = (defaultWindowSizeMs - currentSlot * 3_000) / 1_000; + + res = checkUnDelegateResourcePcc.execute( + encodeMultiWord(owner, ByteArray.fromLong(1_000_000L), one)); + Assert.assertTrue(res.getLeft()); + Assert.assertArrayEquals( + encodeMultiWord(zero, zero, ByteArray.fromLong(defaultLeftTime)), + res.getRight()); + + AccountCapsule accountCapsule = tempRepository.getAccount(address); + accountCapsule.setLatestConsumeTimeForEnergy(0L); + accountCapsule.setAcquiredDelegatedFrozenBalanceForEnergy(10_000_000L); + accountCapsule.addFrozenBalanceForEnergyV2(10_000_000L); + tempRepository.putAccountValue(address, accountCapsule); + + res = checkUnDelegateResourcePcc.execute( + encodeMultiWord(owner, ByteArray.fromLong(10_000_000L), one)); + Assert.assertTrue(res.getLeft()); + Assert.assertArrayEquals( + encodeMultiWord(ByteArray.fromLong(10_000_000L), zero, + ByteArray.fromLong(defaultLeftTime)), + res.getRight()); + + // with usage. + + // used all energy, recovered 1/2, + accountCapsule.setEnergyUsage(20_000_000L); + + accountCapsule.setNewWindowSize(Common.ResourceCode.ENERGY, currentSlot * 2); + tempRepository.putAccountValue(address, accountCapsule); + + res = checkUnDelegateResourcePcc.execute( + encodeMultiWord(owner, ByteArray.fromLong(10_000_000L), one)); + Assert.assertTrue(res.getLeft()); + Assert.assertArrayEquals( + encodeMultiWord( + ByteArray.fromLong(5_000_000L), + ByteArray.fromLong(5_000_000L), + ByteArray.fromLong(currentSlot * 3)), res.getRight()); + + // all recovered. + accountCapsule.setNewWindowSize(Common.ResourceCode.ENERGY, currentSlot); + tempRepository.putAccountValue(address, accountCapsule); + res = checkUnDelegateResourcePcc.execute( + encodeMultiWord(owner, ByteArray.fromLong(10_000_000L), one)); + Assert.assertTrue(res.getLeft()); + Assert.assertArrayEquals( + encodeMultiWord( + ByteArray.fromLong(10_000_000L), + ByteArray.fromLong(0L), + ByteArray.fromLong(0L)), res.getRight()); + + // all used. + accountCapsule.setLatestConsumeTimeForEnergy(currentSlot); + accountCapsule.setNewWindowSize(Common.ResourceCode.ENERGY, currentSlot * 2); + tempRepository.putAccountValue(address, accountCapsule); + res = checkUnDelegateResourcePcc.execute( + encodeMultiWord(owner, ByteArray.fromLong(10_000_000L), one)); + Assert.assertTrue(res.getLeft()); + Assert.assertArrayEquals( + encodeMultiWord( + ByteArray.fromLong(0L), + ByteArray.fromLong(10_000_000L), + ByteArray.fromLong(2 * currentSlot * 3)), res.getRight()); + } + + @Test public void getChainParameterTest() { VMConfig.initAllowTvmFreezeV2(1L); @@ -505,22 +612,43 @@ public void getChainParameterTest() { Repository tempRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); getChainParameterPcc.setRepository(tempRepository); + byte[] TOTAL_NET_LIMIT = "TOTAL_NET_LIMIT".getBytes(); byte[] TOTAL_ENERGY_CURRENT_LIMIT = "TOTAL_ENERGY_CURRENT_LIMIT".getBytes(); - byte[] TOTAL_ENERGY_WEIGHT = "TOTAL_ENERGY_WEIGHT".getBytes(); byte[] UNFREEZE_DELAY_DAYS = "UNFREEZE_DELAY_DAYS".getBytes(); - DataWord totalEnergyCurrentLimitId = new DataWord( + DataWord totalNetLimitId = new DataWord( "0000000000000000000000000000000000000000000000000000000000000001"); - DataWord totalEnergyWeightId = new DataWord( + DataWord totalNetWeightId = new DataWord( "0000000000000000000000000000000000000000000000000000000000000002"); - DataWord unfreezeDelayDaysId = new DataWord( + DataWord totalEnergyCurrentLimitId = new DataWord( "0000000000000000000000000000000000000000000000000000000000000003"); + DataWord totalEnergyWeightId = new DataWord( + "0000000000000000000000000000000000000000000000000000000000000004"); + + DataWord unfreezeDelayDaysId = new DataWord( + "0000000000000000000000000000000000000000000000000000000000000005"); + DataWord invalidId = new DataWord( "0000000000000000000000000000000000000000000000000000000000FFFFFF"); + long netLimit = 90_000_000_000_000_000L; + tempRepository.getDynamicPropertiesStore().put(TOTAL_NET_LIMIT, + new BytesCapsule(ByteArray.fromLong(netLimit))); + Pair totalNetLimitRes = + getChainParameterPcc.execute(totalNetLimitId.getData()); + Assert.assertTrue(totalNetLimitRes.getLeft()); + Assert.assertEquals(ByteArray.toLong(totalNetLimitRes.getRight()), netLimit); + + long netWeight = 10_000_000_000L; + tempRepository.saveTotalNetWeight(netWeight); + Pair totalNetWeightRes = + getChainParameterPcc.execute(totalNetWeightId.getData()); + Assert.assertTrue(totalNetWeightRes.getLeft()); + Assert.assertEquals(ByteArray.toLong(totalNetWeightRes.getRight()), netWeight); + long energyLimit = 9_000_000_000_000_000L; tempRepository.getDynamicPropertiesStore().put(TOTAL_ENERGY_CURRENT_LIMIT, new BytesCapsule(ByteArray.fromLong(energyLimit))); @@ -530,8 +658,7 @@ public void getChainParameterTest() { Assert.assertEquals(ByteArray.toLong(totalEnergyCurrentLimitRes.getRight()), energyLimit); long energyWeight = 1_000_000_000L; - tempRepository.getDynamicPropertiesStore().put(TOTAL_ENERGY_WEIGHT, - new BytesCapsule(ByteArray.fromLong(energyWeight))); + tempRepository.saveTotalEnergyWeight(energyWeight); Pair totalEnergyWeightRes = getChainParameterPcc.execute(totalEnergyWeightId.getData()); Assert.assertTrue(totalEnergyWeightRes.getLeft()); From 4d0c539d1dc53d159075b17502da00e196dd1ec3 Mon Sep 17 00:00:00 2001 From: Liulei Date: Fri, 21 Oct 2022 18:50:53 +0800 Subject: [PATCH 0373/1197] feat(freezeV2): optimize freezeV2 pcc test --- .../tron/common/runtime/vm/PrecompiledContractsTest.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index 90852061f51..a9c9fa6f1db 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -1,6 +1,7 @@ package org.tron.common.runtime.vm; import static org.tron.common.utils.ByteUtil.stripLeadingZeroes; +import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.db.TransactionTrace.convertToTronAddress; import com.google.protobuf.Any; @@ -999,14 +1000,17 @@ public void resourceUsageTest() { res = resourceUsagePcc.execute(encodeMultiWord(address32, type)); Assert.assertTrue(res.getLeft()); usage = Arrays.copyOfRange(res.getRight(), 0, 32); + byte[] recoverDuration = Arrays.copyOfRange(res.getRight(), 32, 64); Assert.assertEquals(10_000_000L, ByteArray.toLong(usage)); + Assert.assertEquals( + currentSlot * BLOCK_PRODUCED_INTERVAL / 1000, ByteArray.toLong(recoverDuration)); accountCapsule.setNewWindowSize(Common.ResourceCode.ENERGY, currentSlot); tempRepository.putAccountValue(address, accountCapsule); res = resourceUsagePcc.execute(encodeMultiWord(address32, type)); Assert.assertTrue(res.getLeft()); usage = Arrays.copyOfRange(res.getRight(), 0, 32); - byte[] recoverDuration = Arrays.copyOfRange(res.getRight(), 32, 64); + recoverDuration = Arrays.copyOfRange(res.getRight(), 32, 64); Assert.assertEquals(0, ByteArray.toLong(usage)); Assert.assertEquals(0, ByteArray.toLong(recoverDuration)); @@ -1015,7 +1019,10 @@ public void resourceUsageTest() { res = resourceUsagePcc.execute(encodeMultiWord(address32, type)); Assert.assertTrue(res.getLeft()); usage = Arrays.copyOfRange(res.getRight(), 0, 32); + recoverDuration = Arrays.copyOfRange(res.getRight(), 32, 64); Assert.assertEquals(20_000_000L, ByteArray.toLong(usage)); + Assert.assertEquals( + currentSlot * BLOCK_PRODUCED_INTERVAL / 1000, ByteArray.toLong(recoverDuration)); } @Test From a6b73cde20b52946f1846220713be4f212ba7787 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Sat, 22 Oct 2022 14:56:55 +0800 Subject: [PATCH 0374/1197] feat(freezeV2): optimize code format PrecompiledContractsTest for check --- .../org/tron/common/runtime/vm/PrecompiledContractsTest.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index a9c9fa6f1db..20b12db8fc1 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -466,8 +466,6 @@ public void delegatableResourceTest() { new BytesCapsule(ByteArray.fromLong(energyLimit))); long energyWeight = 1_000_000L; // unit: trx -// tempRepository.getDynamicPropertiesStore().put(TOTAL_ENERGY_WEIGHT, -// new BytesCapsule(ByteArray.fromLong(energyWeight))); tempRepository.saveTotalEnergyWeight(energyWeight); // used all energy, recovered 1/2, delegatable: 1/2 @@ -513,8 +511,6 @@ public void checkUnDelegateResourceTest() { new BytesCapsule(ByteArray.fromLong(energyLimit))); long energyWeight = 1_000_000L; // unit: trx -// tempRepository.getDynamicPropertiesStore().put(TOTAL_ENERGY_WEIGHT, -// new BytesCapsule(ByteArray.fromLong(energyWeight))); tempRepository.saveTotalEnergyWeight(energyWeight); byte[] owner = new DataWord(ByteArray.fromHexString(OWNER_ADDRESS)).getData(); From 2632362e1c50de8d57b2014d4f44d43eb474ca5b Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 24 Oct 2022 17:23:59 +0800 Subject: [PATCH 0375/1197] feat(freezeV2): optimize freezeV2 --- .../CancelAllUnfreezeV2Processor.java | 9 ++++---- .../UnfreezeBalanceV2Processor.java | 6 ++--- .../tron/core/vm/program/ContractState.java | 15 ++++++++++++ .../org/tron/core/vm/program/Program.java | 7 +++++- .../tron/core/vm/repository/Repository.java | 6 +++++ .../core/vm/repository/RepositoryImpl.java | 23 +++++++++++++++++++ 6 files changed, 58 insertions(+), 8 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java index f3f4a3163c6..777447f8e24 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java @@ -37,7 +37,7 @@ public void validate(CancelAllUnfreezeV2Param param, Repository repo) throws Con } } - public void execute(CancelAllUnfreezeV2Param param, Repository repo) throws ContractExeException { + public long execute(CancelAllUnfreezeV2Param param, Repository repo) throws ContractExeException { byte[] ownerAddress = param.getOwnerAddress(); AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); long now = repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); @@ -56,6 +56,7 @@ public void execute(CancelAllUnfreezeV2Param param, Repository repo) throws Cont ownerCapsule.clearUnfrozenV2(); repo.updateAccount(ownerCapsule.createDbKey(), ownerCapsule); + return withdrawExpireBalance; } public void updateFrozenInfoAndTotalResourceWeight( @@ -64,15 +65,15 @@ public void updateFrozenInfoAndTotalResourceWeight( switch (unFreezeV2.getType()) { case BANDWIDTH: accountCapsule.addFrozenBalanceForBandwidthV2(unFreezeV2.getUnfreezeAmount()); - dynamicStore.addTotalNetWeight(unFreezeV2.getUnfreezeAmount() / TRX_PRECISION); + repo.addTotalNetWeight(unFreezeV2.getUnfreezeAmount() / TRX_PRECISION); break; case ENERGY: accountCapsule.addFrozenBalanceForEnergyV2(unFreezeV2.getUnfreezeAmount()); - dynamicStore.addTotalEnergyWeight(unFreezeV2.getUnfreezeAmount() / TRX_PRECISION); + repo.addTotalEnergyWeight(unFreezeV2.getUnfreezeAmount() / TRX_PRECISION); break; case TRON_POWER: accountCapsule.addFrozenForTronPowerV2(unFreezeV2.getUnfreezeAmount()); - dynamicStore.addTotalTronPowerWeight(unFreezeV2.getUnfreezeAmount() / TRX_PRECISION); + repo.addTotalTronPowerWeight(unFreezeV2.getUnfreezeAmount() / TRX_PRECISION); break; default: // this should never happen diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index 0f0cd6ad815..e53623ac7cc 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -201,13 +201,13 @@ public void updateTotalResourceWeight(Common.ResourceCode freezeType, DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); switch (freezeType) { case BANDWIDTH: - dynamicStore.addTotalNetWeight(-unfreezeBalance / TRX_PRECISION); + repo.addTotalNetWeight(-unfreezeBalance / TRX_PRECISION); break; case ENERGY: - dynamicStore.addTotalEnergyWeight(-unfreezeBalance / TRX_PRECISION); + repo.addTotalEnergyWeight(-unfreezeBalance / TRX_PRECISION); break; case TRON_POWER: - dynamicStore.addTotalTronPowerWeight(-unfreezeBalance / TRX_PRECISION); + repo.addTotalTronPowerWeight(-unfreezeBalance / TRX_PRECISION); break; default: //this should never happen diff --git a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java index b961dca86de..1fa463c1fe4 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java +++ b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java @@ -344,6 +344,11 @@ public void addTotalEnergyWeight(long amount) { repository.addTotalEnergyWeight(amount); } + @Override + public void addTotalTronPowerWeight(long amount) { + repository.addTotalTronPowerWeight(amount); + } + @Override public void saveTotalNetWeight(long totalNetWeight) { repository.saveTotalNetWeight(totalNetWeight); @@ -354,6 +359,11 @@ public void saveTotalEnergyWeight(long totalEnergyWeight) { repository.saveTotalEnergyWeight(totalEnergyWeight); } + @Override + public void saveTotalTronPowerWeight(long totalTronPowerWeight) { + repository.saveTotalTronPowerWeight(totalTronPowerWeight); + } + @Override public long getTotalNetWeight() { return repository.getTotalNetWeight(); @@ -364,6 +374,11 @@ public long getTotalEnergyWeight() { return repository.getTotalEnergyWeight(); } + @Override + public long getTotalTronPowerWeight() { + return repository.getTotalTronPowerWeight(); + } + @Override public long getHeadSlot() { return repository.getHeadSlot(); diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 7b84877c5ab..2a02e20db2e 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -1963,8 +1963,13 @@ public boolean cancelAllUnfreezeV2Action() { CancelAllUnfreezeV2Processor processor = new CancelAllUnfreezeV2Processor(); processor.validate(param, repository); - processor.execute(param, repository); + long withdrawExpireBalance = processor.execute(param, repository); repository.commit(); + if (withdrawExpireBalance > 0) { + increaseNonce(); + addInternalTx(null, owner, owner, withdrawExpireBalance, null, + "withdrawExpireUnfreezeWhileCancelling", nonce, null); + } return true; } catch (ContractValidateException e) { logger.error("TVM cancelAllUnfreezeV2Action: validate failure. Reason: {}", e.getMessage()); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java index 87b869a9330..49b0356588e 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java @@ -128,14 +128,20 @@ public interface Repository { void addTotalEnergyWeight(long amount); + void addTotalTronPowerWeight(long amount); + void saveTotalNetWeight(long totalNetWeight); void saveTotalEnergyWeight(long totalEnergyWeight); + void saveTotalTronPowerWeight(long totalTronPowerWeight); + long getTotalNetWeight(); long getTotalEnergyWeight(); + long getTotalTronPowerWeight(); + long getHeadSlot(); long getSlotByTimestampMs(long timestamp); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 06f01431d19..2326e1f5a2e 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -72,6 +72,7 @@ public class RepositoryImpl implements Repository { private final long precision = Parameter.ChainConstant.PRECISION; private static final byte[] TOTAL_NET_WEIGHT = "TOTAL_NET_WEIGHT".getBytes(); private static final byte[] TOTAL_ENERGY_WEIGHT = "TOTAL_ENERGY_WEIGHT".getBytes(); + private static final byte[] TOTAL_TRON_POWER_WEIGHT = "TOTAL_TRON_POWER_WEIGHT".getBytes(); private StoreFactory storeFactory; @Getter @@ -936,6 +937,13 @@ public void addTotalEnergyWeight(long amount) { saveTotalEnergyWeight(totalEnergyWeight); } + @Override + public void addTotalTronPowerWeight(long amount) { + long totalTronPowerWeight = getTotalTronPowerWeight(); + totalTronPowerWeight += amount; + saveTotalEnergyWeight(totalTronPowerWeight); + } + @Override public void saveTotalNetWeight(long totalNetWeight) { updateDynamicProperty(TOTAL_NET_WEIGHT, @@ -948,6 +956,12 @@ public void saveTotalEnergyWeight(long totalEnergyWeight) { new BytesCapsule(ByteArray.fromLong(totalEnergyWeight))); } + @Override + public void saveTotalTronPowerWeight(long totalTronPowerWeight) { + updateDynamicProperty(TOTAL_TRON_POWER_WEIGHT, + new BytesCapsule(ByteArray.fromLong(totalTronPowerWeight))); + } + @Override public long getTotalNetWeight() { return Optional.ofNullable(getDynamicProperty(TOTAL_NET_WEIGHT)) @@ -966,4 +980,13 @@ public long getTotalEnergyWeight() { () -> new IllegalArgumentException("not found TOTAL_ENERGY_WEIGHT")); } + @Override + public long getTotalTronPowerWeight() { + return Optional.ofNullable(getDynamicProperty(TOTAL_TRON_POWER_WEIGHT)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException("not found TOTAL_TRON_POWER_WEIGHT")); + } + } From 84785e72b1560fb48a845ddd30123cefbb93c70d Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 24 Oct 2022 17:31:26 +0800 Subject: [PATCH 0376/1197] feat(freezeV2): optimize freezeV2 tp modify --- .../vm/nativecontract/CancelAllUnfreezeV2Processor.java | 1 - .../core/vm/nativecontract/FreezeBalanceV2Processor.java | 6 +++--- .../core/vm/nativecontract/UnfreezeBalanceV2Processor.java | 1 - 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java index 777447f8e24..f818a88b237 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java @@ -61,7 +61,6 @@ public long execute(CancelAllUnfreezeV2Param param, Repository repo) throws Cont public void updateFrozenInfoAndTotalResourceWeight( AccountCapsule accountCapsule, Protocol.Account.UnFreezeV2 unFreezeV2, Repository repo) { - DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); switch (unFreezeV2.getType()) { case BANDWIDTH: accountCapsule.addFrozenBalanceForBandwidthV2(unFreezeV2.getUnfreezeAmount()); diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java index 1337a428f27..6f4634555d4 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java @@ -75,15 +75,15 @@ public void execute(FreezeBalanceV2Param param, Repository repo) { switch (param.getResourceType()) { case BANDWIDTH: accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); - dynamicStore.addTotalNetWeight(frozenBalance / TRX_PRECISION); + repo.addTotalNetWeight(frozenBalance / TRX_PRECISION); break; case ENERGY: accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); - dynamicStore.addTotalEnergyWeight(frozenBalance / TRX_PRECISION); + repo.addTotalEnergyWeight(frozenBalance / TRX_PRECISION); break; case TRON_POWER: accountCapsule.addFrozenForTronPowerV2(frozenBalance); - dynamicStore.addTotalTronPowerWeight(frozenBalance / TRX_PRECISION); + repo.addTotalTronPowerWeight(frozenBalance / TRX_PRECISION); break; default: logger.debug("Resource Code Error."); diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index e53623ac7cc..2baa2428358 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -198,7 +198,6 @@ private long calcUnfreezeExpireTime(long now, Repository repo) { public void updateTotalResourceWeight(Common.ResourceCode freezeType, long unfreezeBalance, Repository repo) { - DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); switch (freezeType) { case BANDWIDTH: repo.addTotalNetWeight(-unfreezeBalance / TRX_PRECISION); From 7ae4ebe5b9daad4a2c72797160ba4e8765d67257 Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 24 Oct 2022 18:44:48 +0800 Subject: [PATCH 0377/1197] func(tvm,freezeV2): use V2 method to parse resource type --- .../org/tron/core/vm/program/Program.java | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 2a02e20db2e..bf3337f323f 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -1863,7 +1863,7 @@ public boolean freezeBalanceV2(DataWord frozenBalance, DataWord resourceType) { try { FreezeBalanceV2Param param = new FreezeBalanceV2Param(); param.setOwnerAddress(owner); - param.setResourceType(parseResourceCode(resourceType)); + param.setResourceType(parseResourceCodeV2(resourceType)); param.setFrozenBalance(frozenBalance.sValue().longValueExact()); FreezeBalanceV2Processor processor = new FreezeBalanceV2Processor(); @@ -1895,7 +1895,7 @@ public boolean unfreezeBalanceV2(DataWord unfreezeBalance, DataWord resourceType UnfreezeBalanceV2Param param = new UnfreezeBalanceV2Param(); param.setOwnerAddress(owner); param.setUnfreezeBalance(unfreezeBalance.sValue().longValueExact()); - param.setResourceType(parseResourceCode(resourceType)); + param.setResourceType(parseResourceCodeV2(resourceType)); UnfreezeBalanceV2Processor processor = new UnfreezeBalanceV2Processor(); processor.validate(param, repository); @@ -1972,9 +1972,9 @@ public boolean cancelAllUnfreezeV2Action() { } return true; } catch (ContractValidateException e) { - logger.error("TVM cancelAllUnfreezeV2Action: validate failure. Reason: {}", e.getMessage()); + logger.error("TVM CancelAllUnfreezeV2Action: validate failure. Reason: {}", e.getMessage()); } catch (ContractExeException e) { - logger.error("TVM cancelAllUnfreezeV2Action: execute failure. Reason: {}", e.getMessage()); + logger.error("TVM CancelAllUnfreezeV2Action: execute failure. Reason: {}", e.getMessage()); } if (internalTx != null) { internalTx.reject(); @@ -1998,7 +1998,7 @@ public boolean delegateResource( param.setOwnerAddress(owner); param.setReceiverAddress(receiver); param.setDelegateBalance(delegateBalance.sValue().longValueExact()); - param.setResourceType(parseResourceCode(resourceType)); + param.setResourceType(parseResourceCodeV2(resourceType)); DelegateResourceProcessor processor = new DelegateResourceProcessor(); processor.validate(param, repository); @@ -2006,9 +2006,9 @@ public boolean delegateResource( repository.commit(); return true; } catch (ContractValidateException e) { - logger.error("TVM delegateResource: validate failure. Reason: {}", e.getMessage()); + logger.error("TVM DelegateResource: validate failure. Reason: {}", e.getMessage()); } catch (ArithmeticException e) { - logger.error("TVM delegateResource: balance out of long range."); + logger.error("TVM DelegateResource: balance out of long range."); } if (internalTx != null) { internalTx.reject(); @@ -2032,7 +2032,7 @@ public boolean unDelegateResource( param.setOwnerAddress(owner); param.setReceiverAddress(receiver); param.setUnDelegateBalance(unDelegateBalance.sValue().longValueExact()); - param.setResourceType(parseResourceCode(resourceType)); + param.setResourceType(parseResourceCodeV2(resourceType)); UnDelegateResourceProcessor processor = new UnDelegateResourceProcessor(); processor.validate(param, repository); @@ -2040,9 +2040,9 @@ public boolean unDelegateResource( repository.commit(); return true; } catch (ContractValidateException e) { - logger.error("TVM unDelegateResource: validate failure. Reason: {}", e.getMessage()); + logger.error("TVM UnDelegateResource: validate failure. Reason: {}", e.getMessage()); } catch (ArithmeticException e) { - logger.error("TVM unDelegateResource: balance out of long range."); + logger.error("TVM UnDelegateResource: balance out of long range."); } if (internalTx != null) { internalTx.reject(); @@ -2056,13 +2056,30 @@ private Common.ResourceCode parseResourceCode(DataWord resourceType) { return Common.ResourceCode.BANDWIDTH; case 1: return Common.ResourceCode.ENERGY; - case 2: - return Common.ResourceCode.TRON_POWER; default: return Common.ResourceCode.UNRECOGNIZED; } } + private Common.ResourceCode parseResourceCodeV2(DataWord resourceType) { + try { + byte type = resourceType.sValue().byteValueExact(); + switch (type) { + case 0: + return Common.ResourceCode.BANDWIDTH; + case 1: + return Common.ResourceCode.ENERGY; + case 2: + return Common.ResourceCode.TRON_POWER; + default: + return Common.ResourceCode.UNRECOGNIZED; + } + } catch (ArithmeticException e) { + logger.error(""); + return Common.ResourceCode.UNRECOGNIZED; + } + } + private String convertResourceToString(DataWord resourceType) { switch (resourceType.intValue()) { case 0: From 55447dba5758f11d3173b709f1273924b26ec3a3 Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 24 Oct 2022 19:14:51 +0800 Subject: [PATCH 0378/1197] feat(freezeV2): optimize unfreezeV2 votes --- .../UnfreezeBalanceV2Processor.java | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index 2baa2428358..cf0e668f8af 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -18,6 +18,7 @@ import org.tron.core.capsule.VotesCapsule; import org.tron.core.exception.ContractValidateException; import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.nativecontract.param.UnfreezeBalanceV2Param; import org.tron.core.vm.repository.Repository; import org.tron.core.vm.utils.VoteRewardUtil; @@ -230,15 +231,28 @@ private void clearVotes( } } - if (needToClearVote) { - VotesCapsule votesCapsule = repo.getVotes(ownerAddress); - if (votesCapsule == null) { - votesCapsule = new VotesCapsule(ByteString.copyFrom(ownerAddress), - accountCapsule.getVotesList()); + if (needToClearVote && VMConfig.allowTvmVote() && !accountCapsule.getVotesList().isEmpty()) { + long usedTronPower = 0; + for (Protocol.Vote vote : accountCapsule.getVotesList()) { + usedTronPower += vote.getVoteCount(); + } + long ownedTronPower; + if (repo.getDynamicPropertiesStore().supportAllowNewResourceModel()) { + ownedTronPower = accountCapsule.getAllTronPower(); + } else { + ownedTronPower = accountCapsule.getTronPower(); + } + if (ownedTronPower < usedTronPower * TRX_PRECISION) { + VotesCapsule votesCapsule = repo.getVotes(ownerAddress); + accountCapsule = repo.getAccount(ownerAddress); + if (votesCapsule == null) { + votesCapsule = + new VotesCapsule(ByteString.copyFrom(ownerAddress), accountCapsule.getVotesList()); + } + accountCapsule.clearVotes(); + votesCapsule.clearNewVotes(); + repo.updateVotes(ownerAddress, votesCapsule); } - accountCapsule.clearVotes(); - votesCapsule.clearNewVotes(); - repo.updateVotes(ownerAddress, votesCapsule); } } } From 16b912d2e74be17a492bb4ddd37278978687dc04 Mon Sep 17 00:00:00 2001 From: Liulei Date: Tue, 25 Oct 2022 11:22:54 +0800 Subject: [PATCH 0379/1197] feat(freezeV2): optimize unfreezeV2 votes --- .../tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java | 1 - 1 file changed, 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index cf0e668f8af..219b54c0300 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -244,7 +244,6 @@ private void clearVotes( } if (ownedTronPower < usedTronPower * TRX_PRECISION) { VotesCapsule votesCapsule = repo.getVotes(ownerAddress); - accountCapsule = repo.getAccount(ownerAddress); if (votesCapsule == null) { votesCapsule = new VotesCapsule(ByteString.copyFrom(ownerAddress), accountCapsule.getVotesList()); From 6b92f6d2e09e54daac20c9bb351eb4873e39a4a1 Mon Sep 17 00:00:00 2001 From: Liulei Date: Tue, 25 Oct 2022 11:40:25 +0800 Subject: [PATCH 0380/1197] feat(freezeV2): optimize unfreezeV2 processor --- actuator/src/main/java/org/tron/core/vm/program/Program.java | 4 ++-- .../main/java/org/tron/core/vm/repository/RepositoryImpl.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index bf3337f323f..0e76916438d 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -1968,7 +1968,7 @@ public boolean cancelAllUnfreezeV2Action() { if (withdrawExpireBalance > 0) { increaseNonce(); addInternalTx(null, owner, owner, withdrawExpireBalance, null, - "withdrawExpireUnfreezeWhileCancelling", nonce, null); + "withdrawExpireUnfreezeWhileCanceling", nonce, null); } return true; } catch (ContractValidateException e) { @@ -2075,7 +2075,7 @@ private Common.ResourceCode parseResourceCodeV2(DataWord resourceType) { return Common.ResourceCode.UNRECOGNIZED; } } catch (ArithmeticException e) { - logger.error(""); + logger.error("TVM ParseResourceCodeV2: invalid resource code: {}", resourceType.sValue()); return Common.ResourceCode.UNRECOGNIZED; } } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 2326e1f5a2e..2816aaa8282 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -941,7 +941,7 @@ public void addTotalEnergyWeight(long amount) { public void addTotalTronPowerWeight(long amount) { long totalTronPowerWeight = getTotalTronPowerWeight(); totalTronPowerWeight += amount; - saveTotalEnergyWeight(totalTronPowerWeight); + saveTotalTronPowerWeight(totalTronPowerWeight); } @Override From 66ebc6b09a72527a17f841ae7cd97543f11cdbac Mon Sep 17 00:00:00 2001 From: Liulei Date: Tue, 25 Oct 2022 18:12:08 +0800 Subject: [PATCH 0381/1197] feat(freezeV2): optimize freezeV2 --- .../java/org/tron/core/vm/program/Program.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 0e76916438d..91abb9acd4f 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -521,7 +521,7 @@ private void transferDelegatedResourceToInheritor(byte[] ownerAddr, byte[] inher private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inheritorAddr, Repository repo) { AccountCapsule ownerCapsule = repo.getAccount(ownerAddr); AccountCapsule inheritorCapsule = repo.getAccount(inheritorAddr); - long now = repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); + long now = repo.getHeadSlot(); // transfer frozen resource ownerCapsule.getFrozenV2List().stream() @@ -569,11 +569,12 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit inheritorCapsule.setLatestConsumeTimeForEnergy(now); // withdraw expire unfrozen balance + long nowTimestamp = repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); long expireUnfrozenBalance = ownerCapsule.getUnfrozenV2List().stream() .filter( unFreezeV2 -> - unFreezeV2.getUnfreezeAmount() > 0 && unFreezeV2.getUnfreezeExpireTime() <= now) + unFreezeV2.getUnfreezeAmount() > 0 && unFreezeV2.getUnfreezeExpireTime() <= nowTimestamp) .mapToLong(Protocol.Account.UnFreezeV2::getUnfreezeAmount) .sum(); if (expireUnfrozenBalance > 0) { @@ -582,11 +583,21 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit addInternalTx(null, ownerAddr, inheritorAddr, expireUnfrozenBalance, null, "withdrawExpireUnfreezeWhileSuiciding", nonce, null); } - + clearOwnerFreezeV2(ownerCapsule); + repo.updateAccount(ownerCapsule.createDbKey(), ownerCapsule); repo.updateAccount(inheritorCapsule.createDbKey(), inheritorCapsule); return expireUnfrozenBalance; } + private void clearOwnerFreezeV2(AccountCapsule ownerCapsule) { + ownerCapsule.clearFrozenV2(); + ownerCapsule.setNetUsage(0); + ownerCapsule.setNewWindowSize(Common.ResourceCode.BANDWIDTH, 0); + ownerCapsule.setEnergyUsage(0); + ownerCapsule.setNewWindowSize(Common.ResourceCode.ENERGY, 0); + ownerCapsule.clearUnfrozenV2(); + } + private void withdrawRewardAndCancelVote(byte[] owner, Repository repo) { VoteRewardUtil.withdrawReward(owner, repo); From 9be79abcf52529f4b72c68bf6ed3551598fecd5a Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Tue, 25 Oct 2022 18:15:44 +0800 Subject: [PATCH 0382/1197] feat(freezeV2): optimize account usage calculation --- .../main/java/org/tron/core/vm/repository/RepositoryImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 2816aaa8282..0a44548ae87 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -202,7 +202,7 @@ public Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCap long totalEnergyLimit = getDynamicPropertiesStore().getTotalEnergyCurrentLimit(); long totalEnergyWeight = getTotalEnergyWeight(); - long balance = (long) ((double) newEnergyUsage * totalEnergyWeight / totalEnergyLimit) * TRX_PRECISION; + long balance = (long) ((double) newEnergyUsage * totalEnergyWeight / totalEnergyLimit * TRX_PRECISION); return Pair.of(balance, restoreSlots * BLOCK_PRODUCED_INTERVAL / 1_000); } @@ -225,7 +225,7 @@ public Pair getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsul long totalNetLimit = getDynamicPropertiesStore().getTotalNetLimit(); long totalNetWeight = getTotalNetWeight(); - long balance = (long) ((double) newNetUsage * totalNetWeight / totalNetLimit) * TRX_PRECISION; + long balance = (long) ((double) newNetUsage * totalNetWeight / totalNetLimit * TRX_PRECISION); return Pair.of(balance, restoreSlots * BLOCK_PRODUCED_INTERVAL / 1_000); } From 20b32622531a2deee0c570855b1732ac9fa4965c Mon Sep 17 00:00:00 2001 From: Liulei Date: Tue, 25 Oct 2022 18:22:09 +0800 Subject: [PATCH 0383/1197] feat(freezeV2): optimize freezeV2 --- .../src/main/java/org/tron/core/capsule/AccountCapsule.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index 684d582ade8..9606d7271d0 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -1273,6 +1273,10 @@ public void clearUnfrozenV2() { this.account = this.account.toBuilder().clearUnfrozenV2().build(); } + public void clearFrozenV2() { + this.account = this.account.toBuilder().clearFrozenV2().build(); + } + public void setNewWindowSize(ResourceCode resourceCode, long newWindowSize) { if (resourceCode == BANDWIDTH) { this.account = this.account.toBuilder().setNetWindowSize(newWindowSize).build(); From e78d596e3fc4b2773eb898f03f8238c91f35cb71 Mon Sep 17 00:00:00 2001 From: Liulei Date: Tue, 25 Oct 2022 19:09:40 +0800 Subject: [PATCH 0384/1197] feat(freezeV2): optimize freezeV2 --- .../java/org/tron/core/vm/program/Program.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 91abb9acd4f..06e63835503 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -544,12 +544,11 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit // merge usage BandwidthProcessor bandwidthProcessor = new BandwidthProcessor(ChainBaseManager.getInstance()); long newNetUsage = - bandwidthProcessor.increase( + bandwidthProcessor.unDelegateIncrease( inheritorCapsule, - Common.ResourceCode.BANDWIDTH, - inheritorCapsule.getNetUsage(), + ownerCapsule, ownerCapsule.getNetUsage(), - inheritorCapsule.getLatestConsumeTime(), + Common.ResourceCode.BANDWIDTH, now); inheritorCapsule.setNetUsage(newNetUsage); inheritorCapsule.setLatestConsumeTime(now); @@ -558,12 +557,11 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit new EnergyProcessor( repo.getDynamicPropertiesStore(), ChainBaseManager.getInstance().getAccountStore()); long newEnergyUsage = - energyProcessor.increase( + energyProcessor.unDelegateIncrease( inheritorCapsule, - Common.ResourceCode.ENERGY, - inheritorCapsule.getEnergyUsage(), + ownerCapsule, ownerCapsule.getEnergyUsage(), - inheritorCapsule.getLatestConsumeTimeForEnergy(), + Common.ResourceCode.ENERGY, now); inheritorCapsule.setEnergyUsage(newEnergyUsage); inheritorCapsule.setLatestConsumeTimeForEnergy(now); From 85f5d1001cf267088ba622c2129a2fdd092c4dcc Mon Sep 17 00:00:00 2001 From: Liulei Date: Tue, 25 Oct 2022 19:19:45 +0800 Subject: [PATCH 0385/1197] feat(freezeV2): optimize freezeV2 --- .../org/tron/core/vm/program/Program.java | 51 ++++++++++--------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 06e63835503..974596e3667 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -542,29 +542,34 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit }); // merge usage - BandwidthProcessor bandwidthProcessor = new BandwidthProcessor(ChainBaseManager.getInstance()); - long newNetUsage = - bandwidthProcessor.unDelegateIncrease( - inheritorCapsule, - ownerCapsule, - ownerCapsule.getNetUsage(), - Common.ResourceCode.BANDWIDTH, - now); - inheritorCapsule.setNetUsage(newNetUsage); - inheritorCapsule.setLatestConsumeTime(now); - - EnergyProcessor energyProcessor = - new EnergyProcessor( - repo.getDynamicPropertiesStore(), ChainBaseManager.getInstance().getAccountStore()); - long newEnergyUsage = - energyProcessor.unDelegateIncrease( - inheritorCapsule, - ownerCapsule, - ownerCapsule.getEnergyUsage(), - Common.ResourceCode.ENERGY, - now); - inheritorCapsule.setEnergyUsage(newEnergyUsage); - inheritorCapsule.setLatestConsumeTimeForEnergy(now); + if (ownerCapsule.getNetUsage() > 0) { + BandwidthProcessor bandwidthProcessor = + new BandwidthProcessor(ChainBaseManager.getInstance()); + long newNetUsage = + bandwidthProcessor.unDelegateIncrease( + inheritorCapsule, + ownerCapsule, + ownerCapsule.getNetUsage(), + Common.ResourceCode.BANDWIDTH, + now); + inheritorCapsule.setNetUsage(newNetUsage); + inheritorCapsule.setLatestConsumeTime(now); + } + + if (ownerCapsule.getEnergyUsage() > 0) { + EnergyProcessor energyProcessor = + new EnergyProcessor( + repo.getDynamicPropertiesStore(), ChainBaseManager.getInstance().getAccountStore()); + long newEnergyUsage = + energyProcessor.unDelegateIncrease( + inheritorCapsule, + ownerCapsule, + ownerCapsule.getEnergyUsage(), + Common.ResourceCode.ENERGY, + now); + inheritorCapsule.setEnergyUsage(newEnergyUsage); + inheritorCapsule.setLatestConsumeTimeForEnergy(now); + } // withdraw expire unfrozen balance long nowTimestamp = repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); From 453f055baf2ab990154aa4dd6b5a7ded389c9ece Mon Sep 17 00:00:00 2001 From: Liulei Date: Wed, 26 Oct 2022 18:11:36 +0800 Subject: [PATCH 0386/1197] feat(freezeV2): optimize freezeV2 usage --- .../nativecontract/UnDelegateResourceProcessor.java | 5 +++-- .../main/java/org/tron/core/vm/program/Program.java | 13 ++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index f232467b3fd..8502f4a1bc5 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -100,6 +100,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); AccountCapsule receiverCapsule = repo.getAccount(receiverAddress); DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); + long now = repo.getHeadSlot(); long transferUsage = 0; // modify receiver Account @@ -107,7 +108,6 @@ public void execute(UnDelegateResourceParam param, Repository repo) { switch (param.getResourceType()) { case BANDWIDTH: BandwidthProcessor bandwidthProcessor = new BandwidthProcessor(ChainBaseManager.getInstance()); - // todo update usage time? bandwidthProcessor.updateUsage(receiverCapsule); if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() @@ -127,6 +127,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { long newNetUsage = receiverCapsule.getNetUsage() - transferUsage; receiverCapsule.setNetUsage(newNetUsage); + receiverCapsule.setLatestConsumeTime(now); break; case ENERGY: EnergyProcessor energyProcessor = @@ -150,6 +151,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { long newEnergyUsage = receiverCapsule.getEnergyUsage() - transferUsage; receiverCapsule.setEnergyUsage(newEnergyUsage); + receiverCapsule.setLatestConsumeTimeForEnergy(now); break; default: //this should never happen @@ -161,7 +163,6 @@ public void execute(UnDelegateResourceParam param, Repository repo) { // modify owner Account byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress); DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); - long now = repo.getHeadSlot(); switch (param.getResourceType()) { case BANDWIDTH: { delegatedResourceCapsule.addFrozenBalanceForBandwidth(-unDelegateBalance, 0); diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 974596e3667..8eb04f28d3c 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -542,9 +542,10 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit }); // merge usage + BandwidthProcessor bandwidthProcessor = new BandwidthProcessor(ChainBaseManager.getInstance()); + bandwidthProcessor.updateUsage(ownerCapsule); + ownerCapsule.setLatestConsumeTime(now); if (ownerCapsule.getNetUsage() > 0) { - BandwidthProcessor bandwidthProcessor = - new BandwidthProcessor(ChainBaseManager.getInstance()); long newNetUsage = bandwidthProcessor.unDelegateIncrease( inheritorCapsule, @@ -556,10 +557,12 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit inheritorCapsule.setLatestConsumeTime(now); } + EnergyProcessor energyProcessor = + new EnergyProcessor( + repo.getDynamicPropertiesStore(), ChainBaseManager.getInstance().getAccountStore()); + energyProcessor.updateUsage(ownerCapsule); + ownerCapsule.setLatestConsumeTimeForEnergy(now); if (ownerCapsule.getEnergyUsage() > 0) { - EnergyProcessor energyProcessor = - new EnergyProcessor( - repo.getDynamicPropertiesStore(), ChainBaseManager.getInstance().getAccountStore()); long newEnergyUsage = energyProcessor.unDelegateIncrease( inheritorCapsule, From 840646de6339f635f6e96cdf3b66ce8404314ff5 Mon Sep 17 00:00:00 2001 From: Liulei Date: Thu, 27 Oct 2022 15:53:46 +0800 Subject: [PATCH 0387/1197] feat(freezeV2): optimize freezeV2 usage and windowsize --- .../org/tron/core/actuator/VMActuator.java | 35 ++++++++++++++----- .../tron/core/vm/program/ContractState.java | 5 ++- .../tron/core/vm/repository/Repository.java | 3 +- .../core/vm/repository/RepositoryImpl.java | 2 +- .../org/tron/core/capsule/ReceiptCapsule.java | 10 +++++- .../org/tron/core/db/EnergyProcessor.java | 3 +- .../org/tron/core/db/TransactionTrace.java | 3 ++ 7 files changed, 45 insertions(+), 16 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 9b3600ce6a8..178f96c3fa6 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -25,10 +25,12 @@ import org.tron.common.utils.StorageUtils; import org.tron.common.utils.StringUtil; import org.tron.common.utils.WalletUtil; +import org.tron.core.ChainBaseManager; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.ContractCapsule; import org.tron.core.capsule.ReceiptCapsule; +import org.tron.core.db.EnergyProcessor; import org.tron.core.db.TransactionContext; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; @@ -56,6 +58,7 @@ import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result.contractResult; +import org.tron.protos.contract.Common; import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; import org.tron.protos.contract.SmartContractOuterClass.SmartContract; import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; @@ -548,10 +551,18 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi long energyFromFeeLimit = feeLimit / sunPerEnergy; if (VMConfig.allowTvmFreezeV2()) { - long newEnergyUsage = rootRepository.getAccountEnergyUsageFromFreeze(account); - receipt.setCallerEnergyUsage(newEnergyUsage); - account.setEnergyUsage(newEnergyUsage + min(leftFrozenEnergy, energyFromFeeLimit)); - account.setLatestConsumeTimeForEnergy(rootRepository.getHeadSlot()); + long now = rootRepository.getHeadSlot(); + EnergyProcessor energyProcessor = + new EnergyProcessor( + rootRepository.getDynamicPropertiesStore(), + ChainBaseManager.getInstance().getAccountStore()); + energyProcessor.updateUsage(account); + account.setLatestConsumeTimeForEnergy(now); + receipt.setCallerEnergyUsage(account.getEnergyUsage()); + receipt.setCallerEnergyWindowSize(account.getWindowSize(Common.ResourceCode.ENERGY)); + account.setEnergyUsage( + energyProcessor.increase(account, Common.ResourceCode.ENERGY, + account.getEnergyUsage(), min(leftFrozenEnergy, energyFromFeeLimit), now, now)); rootRepository.updateAccount(account.createDbKey(), account); } return min(availableEnergy, energyFromFeeLimit); @@ -700,10 +711,18 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu } } if (VMConfig.allowTvmFreezeV2()) { - long newEnergyUsage = rootRepository.getAccountEnergyUsageFromFreeze(creator); - receipt.setOriginEnergyUsage(newEnergyUsage); - creator.setEnergyUsage(creator.getEnergyUsage() + creatorEnergyLimit); - creator.setLatestConsumeTimeForEnergy(rootRepository.getHeadSlot()); + long now = rootRepository.getHeadSlot(); + EnergyProcessor energyProcessor = + new EnergyProcessor( + rootRepository.getDynamicPropertiesStore(), + ChainBaseManager.getInstance().getAccountStore()); + energyProcessor.updateUsage(creator); + creator.setLatestConsumeTimeForEnergy(now); + receipt.setOriginEnergyUsage(creator.getEnergyUsage()); + receipt.setOriginEnergyWindowSize(creator.getWindowSize(Common.ResourceCode.ENERGY)); + creator.setEnergyUsage( + energyProcessor.increase(creator, Common.ResourceCode.ENERGY, + creator.getEnergyUsage(), creatorEnergyLimit, now, now)); rootRepository.updateAccount(creator.createDbKey(), creator); } return Math.addExact(callerEnergyLimit, creatorEnergyLimit); diff --git a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java index 1fa463c1fe4..4cbccc58686 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java +++ b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java @@ -21,7 +21,6 @@ import org.tron.core.vm.repository.Repository; import org.tron.core.vm.repository.Value; import org.tron.protos.Protocol.AccountType; -import org.tron.protos.contract.Common; public class ContractState implements Repository, ProgramListenerAware { @@ -225,8 +224,8 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { } @Override - public long getAccountEnergyUsageFromFreeze(AccountCapsule accountCapsule) { - return repository.getAccountEnergyUsageFromFreeze(accountCapsule); + public long getAccountEnergyUsage(AccountCapsule accountCapsule) { + return repository.getAccountEnergyUsage(accountCapsule); } @Override diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java index 49b0356588e..c5b92a63ba8 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java @@ -6,7 +6,6 @@ import org.tron.core.store.*; import org.tron.core.vm.program.Storage; import org.tron.protos.Protocol; -import org.tron.protos.contract.Common; public interface Repository { @@ -108,7 +107,7 @@ public interface Repository { long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule); - long getAccountEnergyUsageFromFreeze(AccountCapsule accountCapsule); + long getAccountEnergyUsage(AccountCapsule accountCapsule); Pair getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCapsule accountCapsule); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 0a44548ae87..bf758c9fd44 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -174,7 +174,7 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { } @Override - public long getAccountEnergyUsageFromFreeze(AccountCapsule accountCapsule) { + public long getAccountEnergyUsage(AccountCapsule accountCapsule) { long now = getHeadSlot(); long energyUsage = accountCapsule.getEnergyUsage(); long latestConsumeTime = accountCapsule.getAccountResource().getLatestConsumeTimeForEnergy(); diff --git a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index c1a666eccdf..2cb475012f3 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -40,6 +40,14 @@ public class ReceiptCapsule { @Setter private long callerEnergyUsage; + @Getter + @Setter + private long callerEnergyWindowSize; + + @Getter + @Setter + private long originEnergyWindowSize; + private Sha256Hash receiptAddress; public ReceiptCapsule(ResourceReceipt data, Sha256Hash receiptAddress) { @@ -165,7 +173,7 @@ private long getOriginUsage(DynamicPropertiesStore dynamicPropertiesStore, Accou long originEnergyLimit, EnergyProcessor energyProcessor, long originUsage) { - if (dynamicPropertiesStore.getAllowTvmFreeze() == 1) { + if (dynamicPropertiesStore.getAllowTvmFreeze() == 1 || dynamicPropertiesStore.supportUnfreezeDelay()) { return Math.min(originUsage, Math.min(originEnergyLeft, originEnergyLimit)); } diff --git a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java index fe36575c512..c8abcfc6159 100644 --- a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java @@ -106,7 +106,8 @@ public boolean useEnergy(AccountCapsule accountCapsule, long energy, long now) { long newEnergyUsage = increase(accountCapsule, ENERGY, energyUsage, 0, latestConsumeTime, now); if (energy > (energyLimit - newEnergyUsage) - && dynamicPropertiesStore.getAllowTvmFreeze() == 0) { + && dynamicPropertiesStore.getAllowTvmFreeze() == 0 + && !dynamicPropertiesStore.supportUnfreezeDelay()) { return false; } diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java index 26aed26d8df..2ab6219f0d5 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java @@ -37,6 +37,7 @@ import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result.contractResult; +import org.tron.protos.contract.Common; import org.tron.protos.contract.SmartContractOuterClass.SmartContract.ABI; import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; @@ -247,7 +248,9 @@ public void pay() throws BalanceInsufficientException { AccountCapsule caller = accountStore.get(callerAccount); if (dynamicPropertiesStore.supportUnfreezeDelay()) { origin.setEnergyUsage(receipt.getOriginEnergyUsage()); + origin.setNewWindowSize(Common.ResourceCode.ENERGY, receipt.getOriginEnergyWindowSize()); caller.setEnergyUsage(receipt.getCallerEnergyUsage()); + caller.setNewWindowSize(Common.ResourceCode.ENERGY, receipt.getCallerEnergyWindowSize()); } receipt.payEnergyBill( dynamicPropertiesStore, accountStore, forkController, From d6f40cd41f28f33f3da53516b454a5c32c1423a5 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Thu, 27 Oct 2022 18:46:26 +0800 Subject: [PATCH 0388/1197] feat(freezeV2): optimize origin and caller energy usage calculation --- .../org/tron/core/actuator/VMActuator.java | 2 ++ .../org/tron/core/capsule/ReceiptCapsule.java | 8 ++++++ .../org/tron/core/db/TransactionTrace.java | 27 ++++++++++++++++--- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 178f96c3fa6..2388768f0d5 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -563,6 +563,7 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi account.setEnergyUsage( energyProcessor.increase(account, Common.ResourceCode.ENERGY, account.getEnergyUsage(), min(leftFrozenEnergy, energyFromFeeLimit), now, now)); + receipt.setCallerEnergyMergedUsage(account.getEnergyUsage()); rootRepository.updateAccount(account.createDbKey(), account); } return min(availableEnergy, energyFromFeeLimit); @@ -723,6 +724,7 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu creator.setEnergyUsage( energyProcessor.increase(creator, Common.ResourceCode.ENERGY, creator.getEnergyUsage(), creatorEnergyLimit, now, now)); + receipt.setOriginEnergyMergedUsage(creator.getEnergyUsage()); rootRepository.updateAccount(creator.createDbKey(), creator); } return Math.addExact(callerEnergyLimit, creatorEnergyLimit); diff --git a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index 2cb475012f3..2b9d2395caa 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -40,6 +40,14 @@ public class ReceiptCapsule { @Setter private long callerEnergyUsage; + @Getter + @Setter + private long callerEnergyMergedUsage; + + @Getter + @Setter + private long originEnergyMergedUsage; + @Getter @Setter private long callerEnergyWindowSize; diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java index 2ab6219f0d5..c4ba7b97cc8 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java @@ -247,10 +247,29 @@ public void pay() throws BalanceInsufficientException { AccountCapsule origin = accountStore.get(originAccount); AccountCapsule caller = accountStore.get(callerAccount); if (dynamicPropertiesStore.supportUnfreezeDelay()) { - origin.setEnergyUsage(receipt.getOriginEnergyUsage()); - origin.setNewWindowSize(Common.ResourceCode.ENERGY, receipt.getOriginEnergyWindowSize()); - caller.setEnergyUsage(receipt.getCallerEnergyUsage()); - caller.setNewWindowSize(Common.ResourceCode.ENERGY, receipt.getCallerEnergyWindowSize()); + + long originPrevUsage = receipt.getOriginEnergyUsage() * receipt.getOriginEnergyWindowSize(); + long originRepayUsage = (receipt.getOriginEnergyMergedUsage() - origin.getEnergyUsage()) + * origin.getWindowSize(Common.ResourceCode.ENERGY); + + long originUsageAfterRepay = Long.max(0, + (originPrevUsage - originRepayUsage) / receipt.getOriginEnergyWindowSize()); + long originWindowSizeAfterRepay = + originUsageAfterRepay == 0 ? 0L : receipt.getOriginEnergyWindowSize(); + + origin.setEnergyUsage(originUsageAfterRepay); + origin.setNewWindowSize(Common.ResourceCode.ENERGY, originWindowSizeAfterRepay); + + long callerPrevUsage = receipt.getCallerEnergyUsage() * receipt.getCallerEnergyWindowSize(); + long callerRepayUsage = (receipt.getCallerEnergyMergedUsage() - caller.getEnergyUsage()) + * caller.getWindowSize(Common.ResourceCode.ENERGY); + + long callerUsageAfterRepay = Long.max(0, + (callerPrevUsage - callerRepayUsage) / receipt.getCallerEnergyWindowSize()); + long callerWindowSizeAfterRepay = + callerUsageAfterRepay == 0 ? 0L : receipt.getCallerEnergyWindowSize(); + caller.setEnergyUsage(callerUsageAfterRepay); + caller.setNewWindowSize(Common.ResourceCode.ENERGY, callerWindowSizeAfterRepay); } receipt.payEnergyBill( dynamicPropertiesStore, accountStore, forkController, From ce0269b417f1330a3e9b07255108167455fd7a27 Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 28 Oct 2022 11:12:44 +0800 Subject: [PATCH 0389/1197] chore(tvm,freezeV2): adjust delegate related logs --- .../src/main/java/org/tron/core/vm/OperationRegistry.java | 3 +-- .../src/main/java/org/tron/core/vm/program/Program.java | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index 3660ab5ae4c..0df5a6b126f 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -48,8 +48,7 @@ public static JumpTable newTronV12OperationSet() { } // Just for warming up class to avoid out_of_time - public static void init() { - } + public static void init() {} public static JumpTable getTable() { // always get the table which has the newest version diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 8eb04f28d3c..ef572e32f79 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -1989,9 +1989,9 @@ public boolean cancelAllUnfreezeV2Action() { } return true; } catch (ContractValidateException e) { - logger.error("TVM CancelAllUnfreezeV2Action: validate failure. Reason: {}", e.getMessage()); + logger.error("TVM CancelAllUnfreezeV2: validate failure. Reason: {}", e.getMessage()); } catch (ContractExeException e) { - logger.error("TVM CancelAllUnfreezeV2Action: execute failure. Reason: {}", e.getMessage()); + logger.error("TVM CancelAllUnfreezeV2: execute failure. Reason: {}", e.getMessage()); } if (internalTx != null) { internalTx.reject(); @@ -2008,7 +2008,7 @@ public boolean delegateResource( increaseNonce(); InternalTransaction internalTx = addInternalTx(null, owner, receiver, delegateBalance.longValue(), null, - "delegateResource" + convertResourceToString(resourceType), nonce, null); + "delegateResourceOf" + convertResourceToString(resourceType), nonce, null); try { DelegateResourceParam param = new DelegateResourceParam(); @@ -2042,7 +2042,7 @@ public boolean unDelegateResource( increaseNonce(); InternalTransaction internalTx = addInternalTx(null, owner, receiver, unDelegateBalance.longValue(), null, - "unDelegateResource" + convertResourceToString(resourceType), nonce, null); + "unDelegateResourceOf" + convertResourceToString(resourceType), nonce, null); try { UnDelegateResourceParam param = new UnDelegateResourceParam(); From 16738475e124d19bfffe2f98d077aac47986fba9 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Thu, 27 Oct 2022 18:06:29 +0800 Subject: [PATCH 0390/1197] fix(freezeV2): upgrade freezeV2 --- .../actuator/UnDelegateResourceActuator.java | 6 +++--- .../actuator/UnfreezeBalanceV2Actuator.java | 6 ++++-- .../WithdrawExpireUnfreezeActuator.java | 1 + .../core/capsule/TransactionResultCapsule.java | 9 +++++++++ .../core/capsule/utils/TransactionUtil.java | 5 +++-- .../org/tron/core/db/BandwidthProcessor.java | 17 +++++++++++++++++ .../java/org/tron/core/db/EnergyProcessor.java | 15 +++++++++++++++ .../core/services/jsonrpc/JsonRpcApiUtil.java | 8 ++++++++ .../org/tron/core/BandwidthProcessorTest.java | 15 +++++++++++++++ .../WithdrawExpireUnfreezeActuatorTest.java | 2 +- protocol/src/main/protos/core/Tron.proto | 2 ++ 11 files changed, 78 insertions(+), 8 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index 56ad722533a..b629b9fd4a0 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -81,7 +81,7 @@ public boolean execute(Object result) throws ContractExeException { receiverCapsule.setAcquiredDelegatedFrozenBalanceForBandwidth(0); } else { // calculate usage - long unDelegateMaxUsage = (long) (unDelegateBalance / TRX_PRECISION + long unDelegateMaxUsage = (long) ((double) unDelegateBalance / TRX_PRECISION * ((double) (dynamicStore.getTotalNetLimit()) / dynamicStore.getTotalNetWeight())); transferUsage = (long) (receiverCapsule.getNetUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForBandwidth())); @@ -103,7 +103,7 @@ public boolean execute(Object result) throws ContractExeException { receiverCapsule.setAcquiredDelegatedFrozenBalanceForEnergy(0); } else { // calculate usage - long unDelegateMaxUsage = (long) (unDelegateBalance / TRX_PRECISION + long unDelegateMaxUsage = (long) ((double) unDelegateBalance / TRX_PRECISION * ((double) (dynamicStore.getTotalEnergyCurrentLimit()) / dynamicStore.getTotalEnergyWeight())); transferUsage = (long) (receiverCapsule.getEnergyUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForEnergy())); @@ -224,7 +224,7 @@ public boolean validate() throws ContractValidateException { } if (!dynamicStore.supportUnfreezeDelay()) { - throw new ContractValidateException("Not support Delegate resource transaction," + throw new ContractValidateException("Not support unDelegate resource transaction," + " need to be opened by the committee"); } diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java index 43b61ad125b..5a11d42bf12 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java @@ -65,7 +65,7 @@ public boolean execute(Object result) throws ContractExeException { mortgageService.withdrawReward(ownerAddress); AccountCapsule accountCapsule = accountStore.get(ownerAddress); - this.unfreezeExpire(accountCapsule, now); + long unfreezeAmount = this.unfreezeExpire(accountCapsule, now); long unfreezeBalance = unfreezeBalanceV2Contract.getUnfreezeBalance(); if (dynamicStore.supportAllowNewResourceModel() @@ -91,6 +91,7 @@ public boolean execute(Object result) throws ContractExeException { accountStore.put(ownerAddress, accountCapsule); ret.setUnfreezeAmount(unfreezeBalance); + ret.setWithdrawExpireAmount(unfreezeAmount); ret.setStatus(fee, code.SUCESS); return true; } @@ -250,7 +251,7 @@ public void updateAccountFrozenInfo(Common.ResourceCode freezeType, AccountCapsu } } - public void unfreezeExpire(AccountCapsule accountCapsule, long now) { + public long unfreezeExpire(AccountCapsule accountCapsule, long now) { long unfreezeBalance = 0L; List unFrozenV2List = Lists.newArrayList(); @@ -271,6 +272,7 @@ public void unfreezeExpire(AccountCapsule accountCapsule, long now) { .clearUnfrozenV2() .addAllUnfrozenV2(unFrozenV2List).build() ); + return unfreezeBalance; } public void updateTotalResourceWeight(final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract, diff --git a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java index 606c18028d5..6532be5439c 100755 --- a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java @@ -60,6 +60,7 @@ public boolean execute(Object result) throws ContractExeException { accountCapsule.clearUnfrozenV2(); newUnFreezeList.forEach(accountCapsule::addUnfrozenV2); accountStore.put(accountCapsule.createDbKey(), accountCapsule); + ret.setWithdrawExpireAmount(totalWithdrawUnfreeze); ret.setStatus(fee, code.SUCESS); return true; } diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionResultCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionResultCapsule.java index f82ec427a0f..98bb23c4729 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionResultCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionResultCapsule.java @@ -80,6 +80,15 @@ public void setWithdrawAmount(long amount) { this.transactionResult = this.transactionResult.toBuilder().setWithdrawAmount(amount).build(); } + public long getWithdrawExpireAmount() { + return transactionResult.getWithdrawExpireAmount(); + } + + public void setWithdrawExpireAmount(long amount) { + this.transactionResult = this.transactionResult.toBuilder() + .setWithdrawExpireAmount(amount).build(); + } + public long getExchangeReceivedAmount() { return transactionResult.getExchangeReceivedAmount(); } diff --git a/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java b/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java index a2c3facd565..d1126b23674 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java +++ b/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java @@ -90,15 +90,16 @@ public static TransactionInfoCapsule buildTransactionInfoInstance(TransactionCap } ByteString contractResult = ByteString.copyFrom(programResult.getHReturn()); - ByteString ContractAddress = ByteString.copyFrom(programResult.getContractAddress()); + ByteString contractAddress = ByteString.copyFrom(programResult.getContractAddress()); builder.setFee(fee); builder.addContractResult(contractResult); - builder.setContractAddress(ContractAddress); + builder.setContractAddress(contractAddress); builder.setUnfreezeAmount(programResult.getRet().getUnfreezeAmount()); builder.setAssetIssueID(programResult.getRet().getAssetIssueID()); builder.setExchangeId(programResult.getRet().getExchangeId()); builder.setWithdrawAmount(programResult.getRet().getWithdrawAmount()); + builder.setWithdrawExpireAmount(programResult.getRet().getWithdrawExpireAmount()); builder.setExchangeReceivedAmount(programResult.getRet().getExchangeReceivedAmount()); builder.setExchangeInjectAnotherAmount(programResult.getRet().getExchangeInjectAnotherAmount()); builder.setExchangeWithdrawAnotherAmount( diff --git a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java index c2aba118405..af4ef152a3b 100644 --- a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -47,9 +47,11 @@ private void updateUsage(AccountCapsule accountCapsule, long now) { long latestConsumeTime = accountCapsule.getLatestConsumeTime(); accountCapsule.setNetUsage(increase(accountCapsule, BANDWIDTH, oldNetUsage, 0, latestConsumeTime, now)); + accountCapsule.setLatestConsumeTime(now); long oldFreeNetUsage = accountCapsule.getFreeNetUsage(); long latestConsumeFreeTime = accountCapsule.getLatestConsumeFreeTime(); accountCapsule.setFreeNetUsage(increase(oldFreeNetUsage, 0, latestConsumeFreeTime, now)); + accountCapsule.setLatestConsumeFreeTime(now); if (chainBaseManager.getDynamicPropertiesStore().getAllowSameTokenName() == 0) { Map assetMap = accountCapsule.getAssetMap(); @@ -58,6 +60,7 @@ private void updateUsage(AccountCapsule accountCapsule, long now) { long latestAssetOperationTime = accountCapsule.getLatestAssetOperationTime(assetName); accountCapsule.putFreeAssetNetUsage(assetName, increase(oldFreeAssetNetUsage, 0, latestAssetOperationTime, now)); + accountCapsule.putLatestAssetOperationTimeMap(assetName, now); }); } Map assetMapV2 = accountCapsule.getAssetMapV2(); @@ -73,6 +76,7 @@ private void updateUsage(AccountCapsule accountCapsule, long now) { long latestAssetOperationTime = accountCapsule.getLatestAssetOperationTimeV2(assetName); accountCapsule.putFreeAssetNetUsageV2(assetName, increase(oldFreeAssetNetUsage, 0, latestAssetOperationTime, now)); + accountCapsule.putLatestAssetOperationTimeMapV2(assetName, now); }); } @@ -390,6 +394,9 @@ private boolean useAssetAccountNet(Contract contract, AccountCapsule accountCaps public long calculateGlobalNetLimit(AccountCapsule accountCapsule) { long frozeBalance = accountCapsule.getAllFrozenBalanceForBandwidth(); + if (dynamicPropertiesStore.supportUnfreezeDelay()) { + return calculateGlobalNetLimitV2(frozeBalance); + } if (frozeBalance < TRX_PRECISION) { return 0; } @@ -402,6 +409,16 @@ public long calculateGlobalNetLimit(AccountCapsule accountCapsule) { return (long) (netWeight * ((double) totalNetLimit / totalNetWeight)); } + public long calculateGlobalNetLimitV2(long frozeBalance) { + double netWeight = (double) frozeBalance / TRX_PRECISION; + long totalNetLimit = dynamicPropertiesStore.getTotalNetLimit(); + long totalNetWeight = dynamicPropertiesStore.getTotalNetWeight(); + if (totalNetWeight == 0) { + return 0; + } + return (long) (netWeight * ((double) totalNetLimit / totalNetWeight)); + } + private boolean useAccountNet(AccountCapsule accountCapsule, long bytes, long now) { long netUsage = accountCapsule.getNetUsage(); diff --git a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java index fe36575c512..cf2e7cd6187 100644 --- a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java @@ -45,6 +45,7 @@ private void updateUsage(AccountCapsule accountCapsule, long now) { accountCapsule.setEnergyUsage(increase(accountCapsule, ENERGY, oldEnergyUsage, 0, latestConsumeTime, now)); + accountCapsule.setLatestConsumeTimeForEnergy(now); } public void updateTotalEnergyAverageUsage() { @@ -130,6 +131,9 @@ public boolean useEnergy(AccountCapsule accountCapsule, long energy, long now) { public long calculateGlobalEnergyLimit(AccountCapsule accountCapsule) { long frozeBalance = accountCapsule.getAllFrozenBalanceForEnergy(); + if (dynamicPropertiesStore.supportUnfreezeDelay()) { + return calculateGlobalEnergyLimitV2(frozeBalance); + } if (frozeBalance < TRX_PRECISION) { return 0; } @@ -143,6 +147,17 @@ public long calculateGlobalEnergyLimit(AccountCapsule accountCapsule) { return (long) (energyWeight * ((double) totalEnergyLimit / totalEnergyWeight)); } + public long calculateGlobalEnergyLimitV2(long frozeBalance) { + double energyWeight = (double) frozeBalance / TRX_PRECISION; + long totalEnergyLimit = dynamicPropertiesStore.getTotalEnergyCurrentLimit(); + long totalEnergyWeight = dynamicPropertiesStore.getTotalEnergyWeight(); + if (totalEnergyWeight == 0) { + return 0; + } + return (long) (energyWeight * ((double) totalEnergyLimit / totalEnergyWeight)); + } + + public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { long now = getHeadSlot(); long energyUsage = accountCapsule.getEnergyUsage(); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java index 94bd69290ae..565ce922572 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java @@ -198,6 +198,8 @@ public static long getTransactionAmount(Transaction.Contract contract, String ha switch (contract.getType()) { case UnfreezeBalanceContract: case WithdrawBalanceContract: + case WithdrawExpireUnfreezeContract: + case UnfreezeBalanceV2Contract: TransactionInfo transactionInfo = wallet .getTransactionInfoById(ByteString.copyFrom(ByteArray.fromHexString(hash))); amount = getAmountFromTransactionInfo(hash, contract.getType(), transactionInfo); @@ -272,6 +274,8 @@ public static long getTransactionAmount(Transaction.Contract contract, String ha break; case UnfreezeBalanceContract: case WithdrawBalanceContract: + case WithdrawExpireUnfreezeContract: + case UnfreezeBalanceV2Contract: amount = getAmountFromTransactionInfo(hash, contract.getType(), transactionInfo); break; case UnfreezeAssetContract: @@ -296,6 +300,7 @@ public static long getAmountFromTransactionInfo(String hash, ContractType contra switch (contractType) { case UnfreezeBalanceContract: + case UnfreezeBalanceV2Contract: amount = transactionInfo.getUnfreezeAmount(); break; case WithdrawBalanceContract: @@ -310,6 +315,9 @@ public static long getAmountFromTransactionInfo(String hash, ContractType contra case ExchangeTransactionContract: amount = transactionInfo.getExchangeReceivedAmount(); break; + case WithdrawExpireUnfreezeContract: + amount = transactionInfo.getWithdrawExpireAmount(); + break; default: break; } diff --git a/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java b/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java index db5e63b77a8..4d000d375b5 100755 --- a/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java +++ b/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java @@ -147,6 +147,8 @@ public void createCapsule() { AccountType.AssetIssue, chainBaseManager.getDynamicPropertiesStore().getAssetIssueFee()); + assetCapsule2.addAcquiredDelegatedFrozenBalanceForBandwidth(999999L); + chainBaseManager.getAccountStore().reset(); chainBaseManager.getAccountAssetStore().reset(); chainBaseManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); @@ -858,4 +860,17 @@ public void sameTokenNameCloseTransferToAccountNotExist() { chainBaseManager.getAccountStore().delete(ByteArray.fromHexString(TO_ADDRESS)); } } + + @Test + public void testCalculateGlobalNetLimit() { + chainBaseManager.getDynamicPropertiesStore().saveTotalNetWeight(6310L); + BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); + AccountCapsule accountCapsule = chainBaseManager.getAccountStore() + .get(ByteArray.fromHexString(ASSET_ADDRESS_V2)); + long netLimit = processor.calculateGlobalNetLimit(accountCapsule); + Assert.assertEquals(0, netLimit); + long netLimitV2 = processor + .calculateGlobalNetLimitV2(accountCapsule.getAllFrozenBalanceForBandwidth()); + Assert.assertTrue(netLimitV2 > 0); + } } diff --git a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java index 455c8ba8a92..4ea3d5c83ac 100644 --- a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java @@ -132,7 +132,7 @@ public void testWithdrawExpireUnfreeze() { Assert.assertEquals(1, unfrozenV2List.size()); Assert.assertEquals(Long.MAX_VALUE, unfrozenV2List.get(0).getUnfreezeExpireTime()); Assert.assertEquals(initBalance + 32_000_000L, owner.getBalance()); - Assert.assertEquals(0, owner.getAllowance()); + Assert.assertEquals(32_000_000L, ret.getWithdrawExpireAmount()); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 67427214477..632dcc157ce 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -414,6 +414,7 @@ message Transaction { bytes orderId = 25; repeated MarketOrderDetail orderDetails = 26; + int64 withdraw_expire_amount = 27; } message raw { @@ -473,6 +474,7 @@ message TransactionInfo { repeated MarketOrderDetail orderDetails = 26; int64 packingFee = 27; + int64 withdraw_Expire_amount = 28; } message TransactionRet { From 613cd1bec35ac2bbfc7f567f8945bdba0f80740a Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 28 Oct 2022 14:37:18 +0800 Subject: [PATCH 0391/1197] fix(tvm,freezeV2): do not set origin if caller == origin --- .../org/tron/core/capsule/ReceiptCapsule.java | 2 +- .../org/tron/core/db/TransactionTrace.java | 25 +++++++++++-------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index 2b9d2395caa..e86d1f627ab 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -160,7 +160,7 @@ public void payEnergyBill(DynamicPropertiesStore dynamicPropertiesStore, return; } - if ((!Objects.isNull(origin))&&caller.getAddress().equals(origin.getAddress())) { + if ((!Objects.isNull(origin)) && caller.getAddress().equals(origin.getAddress())) { payEnergyBill(dynamicPropertiesStore, accountStore, forkController, caller, receipt.getEnergyUsageTotal(), receipt.getResult(), energyProcessor, now); } else { diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java index c4ba7b97cc8..c5989756681 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java @@ -248,17 +248,20 @@ public void pay() throws BalanceInsufficientException { AccountCapsule caller = accountStore.get(callerAccount); if (dynamicPropertiesStore.supportUnfreezeDelay()) { - long originPrevUsage = receipt.getOriginEnergyUsage() * receipt.getOriginEnergyWindowSize(); - long originRepayUsage = (receipt.getOriginEnergyMergedUsage() - origin.getEnergyUsage()) - * origin.getWindowSize(Common.ResourceCode.ENERGY); - - long originUsageAfterRepay = Long.max(0, - (originPrevUsage - originRepayUsage) / receipt.getOriginEnergyWindowSize()); - long originWindowSizeAfterRepay = - originUsageAfterRepay == 0 ? 0L : receipt.getOriginEnergyWindowSize(); - - origin.setEnergyUsage(originUsageAfterRepay); - origin.setNewWindowSize(Common.ResourceCode.ENERGY, originWindowSizeAfterRepay); + // just fo caller is not origin, we set the related field for origin account + if (!caller.getAddress().equals(origin.getAddress())) { + long originPrevUsage = receipt.getOriginEnergyUsage() * receipt.getOriginEnergyWindowSize(); + long originRepayUsage = (receipt.getOriginEnergyMergedUsage() - origin.getEnergyUsage()) + * origin.getWindowSize(Common.ResourceCode.ENERGY); + + long originUsageAfterRepay = Long.max(0, + (originPrevUsage - originRepayUsage) / receipt.getOriginEnergyWindowSize()); + long originWindowSizeAfterRepay = + originUsageAfterRepay == 0 ? 0L : receipt.getOriginEnergyWindowSize(); + + origin.setEnergyUsage(originUsageAfterRepay); + origin.setNewWindowSize(Common.ResourceCode.ENERGY, originWindowSizeAfterRepay); + } long callerPrevUsage = receipt.getCallerEnergyUsage() * receipt.getCallerEnergyWindowSize(); long callerRepayUsage = (receipt.getCallerEnergyMergedUsage() - caller.getEnergyUsage()) From 8177eb3510147514137a828e21308bf8a11cf38e Mon Sep 17 00:00:00 2001 From: Liulei Date: Fri, 28 Oct 2022 14:40:20 +0800 Subject: [PATCH 0392/1197] feat(freezeV2): merge release --- .../core/vm/nativecontract/UnDelegateResourceProcessor.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index 8502f4a1bc5..af2d7fb9eb9 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -127,7 +127,6 @@ public void execute(UnDelegateResourceParam param, Repository repo) { long newNetUsage = receiverCapsule.getNetUsage() - transferUsage; receiverCapsule.setNetUsage(newNetUsage); - receiverCapsule.setLatestConsumeTime(now); break; case ENERGY: EnergyProcessor energyProcessor = @@ -151,7 +150,6 @@ public void execute(UnDelegateResourceParam param, Repository repo) { long newEnergyUsage = receiverCapsule.getEnergyUsage() - transferUsage; receiverCapsule.setEnergyUsage(newEnergyUsage); - receiverCapsule.setLatestConsumeTimeForEnergy(now); break; default: //this should never happen From 70d91c50fd211315762975d47d8bf1f94f734921 Mon Sep 17 00:00:00 2001 From: Liulei Date: Fri, 28 Oct 2022 14:40:20 +0800 Subject: [PATCH 0393/1197] feat(freezeV2): merge release --- .../vm/nativecontract/UnDelegateResourceProcessor.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index 8502f4a1bc5..f44c221634b 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -55,14 +55,6 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont "receiverAddress must not be the same as ownerAddress"); } - // TVM contract suicide can result in no receiving account -// AccountCapsule receiverCapsule = repo.getAccount(receiverAddress); -// if (receiverCapsule == null) { -// String readableReceiverAddress = StringUtil.createReadableString(receiverAddress); -// throw new ContractValidateException( -// "Receiver Account[" + readableReceiverAddress + "] does not exist"); -// } - byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress); DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); if (delegatedResourceCapsule == null) { @@ -127,7 +119,6 @@ public void execute(UnDelegateResourceParam param, Repository repo) { long newNetUsage = receiverCapsule.getNetUsage() - transferUsage; receiverCapsule.setNetUsage(newNetUsage); - receiverCapsule.setLatestConsumeTime(now); break; case ENERGY: EnergyProcessor energyProcessor = @@ -151,7 +142,6 @@ public void execute(UnDelegateResourceParam param, Repository repo) { long newEnergyUsage = receiverCapsule.getEnergyUsage() - transferUsage; receiverCapsule.setEnergyUsage(newEnergyUsage); - receiverCapsule.setLatestConsumeTimeForEnergy(now); break; default: //this should never happen From 897a24baa65bcdbd26a302f8dde5a6a35e477979 Mon Sep 17 00:00:00 2001 From: Liulei Date: Fri, 28 Oct 2022 14:51:02 +0800 Subject: [PATCH 0394/1197] feat(freezeV2): optimize undelegate usage precision --- .../vm/nativecontract/UnDelegateResourceProcessor.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index f44c221634b..9050771950d 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -108,8 +108,8 @@ public void execute(UnDelegateResourceParam param, Repository repo) { receiverCapsule.setAcquiredDelegatedFrozenBalanceForBandwidth(0); } else { // calculate usage - long unDelegateMaxUsage = (long) (unDelegateBalance / TRX_PRECISION - * ((double) (dynamicStore.getTotalNetLimit()) / repo.getTotalNetWeight())); + long unDelegateMaxUsage = (long) ((double) unDelegateBalance / TRX_PRECISION + * dynamicStore.getTotalNetLimit() / repo.getTotalNetWeight()); transferUsage = (long) (receiverCapsule.getNetUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForBandwidth())); transferUsage = Math.min(unDelegateMaxUsage, transferUsage); @@ -131,8 +131,8 @@ public void execute(UnDelegateResourceParam param, Repository repo) { receiverCapsule.setAcquiredDelegatedFrozenBalanceForEnergy(0); } else { // calculate usage - long unDelegateMaxUsage = (long) (unDelegateBalance / TRX_PRECISION - * ((double) (dynamicStore.getTotalEnergyCurrentLimit()) / repo.getTotalEnergyWeight())); + long unDelegateMaxUsage = (long) ((double) unDelegateBalance / TRX_PRECISION + * dynamicStore.getTotalEnergyCurrentLimit() / repo.getTotalEnergyWeight()); transferUsage = (long) (receiverCapsule.getEnergyUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForEnergy())); transferUsage = Math.min(unDelegateMaxUsage, transferUsage); From bb98ec7f6478ff073d70229825beca02a3cd8772 Mon Sep 17 00:00:00 2001 From: Liulei Date: Fri, 28 Oct 2022 16:07:09 +0800 Subject: [PATCH 0395/1197] feat(freezeV2): optimize vmactuator energy consume time --- actuator/src/main/java/org/tron/core/actuator/VMActuator.java | 2 -- actuator/src/main/java/org/tron/core/vm/program/Program.java | 2 -- 2 files changed, 4 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 2388768f0d5..e7e98b62e60 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -557,7 +557,6 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi rootRepository.getDynamicPropertiesStore(), ChainBaseManager.getInstance().getAccountStore()); energyProcessor.updateUsage(account); - account.setLatestConsumeTimeForEnergy(now); receipt.setCallerEnergyUsage(account.getEnergyUsage()); receipt.setCallerEnergyWindowSize(account.getWindowSize(Common.ResourceCode.ENERGY)); account.setEnergyUsage( @@ -718,7 +717,6 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu rootRepository.getDynamicPropertiesStore(), ChainBaseManager.getInstance().getAccountStore()); energyProcessor.updateUsage(creator); - creator.setLatestConsumeTimeForEnergy(now); receipt.setOriginEnergyUsage(creator.getEnergyUsage()); receipt.setOriginEnergyWindowSize(creator.getWindowSize(Common.ResourceCode.ENERGY)); creator.setEnergyUsage( diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index ef572e32f79..c0a7827fe81 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -544,7 +544,6 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit // merge usage BandwidthProcessor bandwidthProcessor = new BandwidthProcessor(ChainBaseManager.getInstance()); bandwidthProcessor.updateUsage(ownerCapsule); - ownerCapsule.setLatestConsumeTime(now); if (ownerCapsule.getNetUsage() > 0) { long newNetUsage = bandwidthProcessor.unDelegateIncrease( @@ -561,7 +560,6 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit new EnergyProcessor( repo.getDynamicPropertiesStore(), ChainBaseManager.getInstance().getAccountStore()); energyProcessor.updateUsage(ownerCapsule); - ownerCapsule.setLatestConsumeTimeForEnergy(now); if (ownerCapsule.getEnergyUsage() > 0) { long newEnergyUsage = energyProcessor.unDelegateIncrease( From 24f141b6aa2419770f1ba305b08d861c2d52d902 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Wed, 26 Oct 2022 16:04:13 +0800 Subject: [PATCH 0396/1197] feat(freezeV2): optimize unfreeze vote 1. clear all votes at once when new resource model start 2. If there is not enough power to vote, reduce the votes proportionally --- .../actuator/UnfreezeBalanceV2Actuator.java | 134 ++++++++++++------ .../UnfreezeBalanceV2ActuatorTest.java | 59 ++++---- 2 files changed, 121 insertions(+), 72 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java index 43b61ad125b..df139730e3c 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java @@ -1,8 +1,15 @@ package org.tron.core.actuator; +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + import com.google.common.collect.Lists; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; @@ -19,17 +26,10 @@ import org.tron.protos.Protocol; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.Protocol.Vote; import org.tron.protos.contract.BalanceContract.UnfreezeBalanceV2Contract; import org.tron.protos.contract.Common; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; - -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; - @Slf4j(topic = "actuator") public class UnfreezeBalanceV2Actuator extends AbstractActuator { @@ -81,7 +81,7 @@ public boolean execute(Object result) throws ContractExeException { accountCapsule.addUnfrozenV2List(freezeType, unfreezeBalance, expireTime); this.updateTotalResourceWeight(unfreezeBalanceV2Contract, unfreezeBalance); - this.clearVotes(accountCapsule,unfreezeBalanceV2Contract, ownerAddress); + this.updateVote(accountCapsule, unfreezeBalanceV2Contract, ownerAddress); if (dynamicStore.supportAllowNewResourceModel() && !accountCapsule.oldTronPowerIsInvalid()) { @@ -154,7 +154,7 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("no frozenBalance(TronPower)"); } } else { - throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); } break; default: @@ -167,7 +167,7 @@ public boolean validate() throws ContractValidateException { if (!checkUnfreezeBalance(accountCapsule, unfreezeBalanceV2Contract, unfreezeBalanceV2Contract.getResource())) { throw new ContractValidateException( - "Invalid unfreeze_balance, [" + unfreezeBalanceV2Contract.getUnfreezeBalance() + "] is error" + "Invalid unfreeze_balance, [" + unfreezeBalanceV2Contract.getUnfreezeBalance() + "] is error" ); } @@ -208,8 +208,8 @@ public boolean checkExistFreezedBalance(AccountCapsule accountCapsule, Common.Re } public boolean checkUnfreezeBalance(AccountCapsule accountCapsule, - final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract, - Common.ResourceCode freezeType) { + final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract, + Common.ResourceCode freezeType) { boolean checkOk = false; long frozenAmount = 0L; @@ -222,7 +222,7 @@ public boolean checkUnfreezeBalance(AccountCapsule accountCapsule, } if (unfreezeBalanceV2Contract.getUnfreezeBalance() > 0 - && unfreezeBalanceV2Contract.getUnfreezeBalance() <= frozenAmount) { + && unfreezeBalanceV2Contract.getUnfreezeBalance() <= frozenAmount) { checkOk = true; } @@ -240,10 +240,10 @@ public void updateAccountFrozenInfo(Common.ResourceCode freezeType, AccountCapsu List freezeV2List = accountCapsule.getFrozenV2List(); for (int i = 0; i < freezeV2List.size(); i++) { if (freezeV2List.get(i).getType().equals(freezeType)) { - Protocol.Account.FreezeV2 freezeV2 = Protocol.Account.FreezeV2.newBuilder() - .setAmount(freezeV2List.get(i).getAmount() - unfreezeBalance) - .setType(freezeV2List.get(i).getType()) - .build(); + Protocol.Account.FreezeV2 freezeV2 = Protocol.Account.FreezeV2.newBuilder() + .setAmount(freezeV2List.get(i).getAmount() - unfreezeBalance) + .setType(freezeV2List.get(i).getType()) + .build(); accountCapsule.updateFrozenV2List(i, freezeV2); break; } @@ -266,7 +266,7 @@ public void unfreezeExpire(AccountCapsule accountCapsule, long now) { } accountCapsule.setInstance( - accountCapsule.getInstance().toBuilder() + accountCapsule.getInstance().toBuilder() .setBalance(accountCapsule.getBalance() + unfreezeBalance) .clearUnfrozenV2() .addAllUnfrozenV2(unFrozenV2List).build() @@ -274,7 +274,7 @@ public void unfreezeExpire(AccountCapsule accountCapsule, long now) { } public void updateTotalResourceWeight(final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract, - long unfreezeBalance) { + long unfreezeBalance) { DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); switch (unfreezeBalanceV2Contract.getResource()) { case BANDWIDTH: @@ -292,38 +292,86 @@ public void updateTotalResourceWeight(final UnfreezeBalanceV2Contract unfreezeBa } } - private void clearVotes(AccountCapsule accountCapsule, + private void updateVote(AccountCapsule accountCapsule, final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract, byte[] ownerAddress) { DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); VotesStore votesStore = chainBaseManager.getVotesStore(); - boolean needToClearVote = true; - if (dynamicStore.supportAllowNewResourceModel() - && accountCapsule.oldTronPowerIsInvalid()) { - switch (unfreezeBalanceV2Contract.getResource()) { - case BANDWIDTH: - case ENERGY: - needToClearVote = false; - break; - default: - break; + if (accountCapsule.getVotesList().isEmpty()) { + return; + } + if (dynamicStore.supportAllowNewResourceModel()) { + if (accountCapsule.oldTronPowerIsInvalid()) { + switch (unfreezeBalanceV2Contract.getResource()) { + case BANDWIDTH: + case ENERGY: + // there is no need to change votes + return; + default: + break; + } + } else { + // clear all votes at once when new resource model start + VotesCapsule votesCapsule; + if (!votesStore.has(ownerAddress)) { + votesCapsule = new VotesCapsule( + unfreezeBalanceV2Contract.getOwnerAddress(), + accountCapsule.getVotesList() + ); + } else { + votesCapsule = votesStore.get(ownerAddress); + } + accountCapsule.clearVotes(); + votesCapsule.clearNewVotes(); + votesStore.put(ownerAddress, votesCapsule); + return; } } - if (needToClearVote) { - VotesCapsule votesCapsule; - if (!votesStore.has(ownerAddress)) { - votesCapsule = new VotesCapsule( - unfreezeBalanceV2Contract.getOwnerAddress(), - accountCapsule.getVotesList() - ); - } else { - votesCapsule = votesStore.get(ownerAddress); + long totalVote = 0; + for (Protocol.Vote vote : accountCapsule.getVotesList()) { + totalVote += vote.getVoteCount(); + } + long ownedTronPower; + if (dynamicStore.supportAllowNewResourceModel()) { + ownedTronPower = accountCapsule.getAllTronPower(); + } else { + ownedTronPower = accountCapsule.getTronPower(); + } + + // tron power is enough to total votes + if (ownedTronPower >= totalVote * TRX_PRECISION) { + return; + } + if (totalVote == 0) { + return; + } + + VotesCapsule votesCapsule; + if (!votesStore.has(ownerAddress)) { + votesCapsule = new VotesCapsule( + unfreezeBalanceV2Contract.getOwnerAddress(), + accountCapsule.getVotesList() + ); + } else { + votesCapsule = votesStore.get(ownerAddress); + } + + // Update Owner Voting + votesCapsule.clearNewVotes(); + for (Vote vote : accountCapsule.getVotesList()) { + long newVoteCount = (long) + ((double) vote.getVoteCount() / totalVote * ownedTronPower / TRX_PRECISION); + if (newVoteCount > 0) { + votesCapsule.addNewVotes(vote.getVoteAddress(), newVoteCount); } - accountCapsule.clearVotes(); - votesCapsule.clearNewVotes(); - votesStore.put(ownerAddress, votesCapsule); + } + votesStore.put(ownerAddress, votesCapsule); + + accountCapsule.clearVotes(); + for (Vote vote : votesCapsule.getNewVotes()) { + accountCapsule.addVotes(vote.getVoteAddress(), vote.getVoteCount()); } } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java index 004a9476ff1..07d7f3a6def 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java @@ -7,8 +7,6 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; import java.io.File; -import java.util.ArrayList; -import java.util.List; import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; import org.junit.Assert; @@ -318,57 +316,60 @@ public void noFrozenBalance() { } @Test - public void testClearVotes() { + public void testVotes() { byte[] ownerAddressBytes = ByteArray.fromHexString(OWNER_ADDRESS); - ByteString ownerAddress = ByteString.copyFrom(ownerAddressBytes); - long unfreezeBalance = frozenBalance; + long unfreezeBalance = frozenBalance / 2; long now = System.currentTimeMillis(); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); - + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(0); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddressBytes); accountCapsule.addFrozenBalanceForBandwidthV2(1_000_000_000L); - + accountCapsule.addVotes(ByteString.copyFrom(RECEIVER_ADDRESS.getBytes()), 500); + accountCapsule.addVotes(ByteString.copyFrom(OWNER_ACCOUNT_INVALID.getBytes()), 500); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); TransactionResultCapsule ret = new TransactionResultCapsule(); - dbManager.getVotesStore().reset(); - Assert.assertNull(dbManager.getVotesStore().get(ownerAddressBytes)); try { actuator.validate(); actuator.execute(ret); VotesCapsule votesCapsule = dbManager.getVotesStore().get(ownerAddressBytes); Assert.assertNotNull(votesCapsule); - Assert.assertEquals(0, votesCapsule.getNewVotes().size()); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + for (Vote vote : votesCapsule.getOldVotes()) { + Assert.assertEquals(vote.getVoteCount(), 500); + } + for (Vote vote : votesCapsule.getNewVotes()) { + Assert.assertEquals(vote.getVoteCount(), 250); + } + accountCapsule = dbManager.getAccountStore().get(ownerAddressBytes); + for (Vote vote : accountCapsule.getVotesList()) { + Assert.assertEquals(vote.getVoteCount(), 250); + } + } catch (ContractValidateException | ContractExeException e) { + Assert.fail("cannot run here."); } - // if had votes - List oldVotes = new ArrayList(); - VotesCapsule votesCapsule = new VotesCapsule( - ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), oldVotes); - votesCapsule.addNewVotes( - ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), 100); - dbManager.getVotesStore().put(ByteArray.fromHexString(OWNER_ADDRESS), votesCapsule); - accountCapsule.addFrozenBalanceForBandwidthV2(1_000_000_000L); - dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + // clear for new resource model + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance / 2)); try { actuator.validate(); actuator.execute(ret); - votesCapsule = dbManager.getVotesStore().get(ownerAddressBytes); + VotesCapsule votesCapsule = dbManager.getVotesStore().get(ownerAddressBytes); Assert.assertNotNull(votesCapsule); + for (Vote vote : votesCapsule.getOldVotes()) { + Assert.assertEquals(vote.getVoteCount(), 500); + } Assert.assertEquals(0, votesCapsule.getNewVotes().size()); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + accountCapsule = dbManager.getAccountStore().get(ownerAddressBytes); + Assert.assertEquals(0, accountCapsule.getVotesList().size()); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail("cannot run here."); } - } @Test From 1467ce7a8433b10534c13f34105b43d665e7d77a Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 31 Oct 2022 11:59:47 +0800 Subject: [PATCH 0397/1197] feat(freezeV2): optimize unfreezeV2 votes update --- .../UnfreezeBalanceV2Processor.java | 88 +++++++++++++------ 1 file changed, 62 insertions(+), 26 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index 219b54c0300..aca12cde11d 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -140,7 +140,7 @@ public long execute(UnfreezeBalanceV2Param param, Repository repo) { accountCapsule.addUnfrozenV2List(param.getResourceType(), unfreezeBalance, expireTime); this.updateTotalResourceWeight(param.getResourceType(), unfreezeBalance, repo); - this.clearVotes(accountCapsule, param.getResourceType(), ownerAddress, repo); + this.updateVote(accountCapsule, param.getResourceType(), ownerAddress, repo); if (repo.getDynamicPropertiesStore().supportAllowNewResourceModel() && !accountCapsule.oldTronPowerIsInvalid()) { @@ -215,34 +215,28 @@ public void updateTotalResourceWeight(Common.ResourceCode freezeType, } } - private void clearVotes( - AccountCapsule accountCapsule, Common.ResourceCode freezeType, byte[] ownerAddress, Repository repo) { + private void updateVote( + AccountCapsule accountCapsule, + Common.ResourceCode freezeType, + byte[] ownerAddress, + Repository repo) { + DynamicPropertiesStore dynamicStore = repo.getDynamicPropertiesStore(); - boolean needToClearVote = true; - if (repo.getDynamicPropertiesStore().supportAllowNewResourceModel() - && accountCapsule.oldTronPowerIsInvalid()) { - switch (freezeType) { - case BANDWIDTH: - case ENERGY: - needToClearVote = false; - break; - default: - break; - } + if (!VMConfig.allowTvmVote() || accountCapsule.getVotesList().isEmpty()) { + return; } - - if (needToClearVote && VMConfig.allowTvmVote() && !accountCapsule.getVotesList().isEmpty()) { - long usedTronPower = 0; - for (Protocol.Vote vote : accountCapsule.getVotesList()) { - usedTronPower += vote.getVoteCount(); - } - long ownedTronPower; - if (repo.getDynamicPropertiesStore().supportAllowNewResourceModel()) { - ownedTronPower = accountCapsule.getAllTronPower(); + if (dynamicStore.supportAllowNewResourceModel()) { + if (accountCapsule.oldTronPowerIsInvalid()) { + switch (freezeType) { + case BANDWIDTH: + case ENERGY: + // there is no need to change votes + return; + default: + break; + } } else { - ownedTronPower = accountCapsule.getTronPower(); - } - if (ownedTronPower < usedTronPower * TRX_PRECISION) { + // clear all votes at once when new resource model start VotesCapsule votesCapsule = repo.getVotes(ownerAddress); if (votesCapsule == null) { votesCapsule = @@ -251,7 +245,49 @@ private void clearVotes( accountCapsule.clearVotes(); votesCapsule.clearNewVotes(); repo.updateVotes(ownerAddress, votesCapsule); + return; + } + } + + long totalVote = 0; + for (Protocol.Vote vote : accountCapsule.getVotesList()) { + totalVote += vote.getVoteCount(); + } + if (totalVote == 0) { + return; + } + + long ownedTronPower; + if (dynamicStore.supportAllowNewResourceModel()) { + ownedTronPower = accountCapsule.getAllTronPower(); + } else { + ownedTronPower = accountCapsule.getTronPower(); + } + // tron power is enough to total votes + if (ownedTronPower >= totalVote * TRX_PRECISION) { + return; + } + + VotesCapsule votesCapsule = repo.getVotes(ownerAddress); + if (votesCapsule == null) { + votesCapsule = + new VotesCapsule(ByteString.copyFrom(ownerAddress), accountCapsule.getVotesList()); + } + + // Update Owner Voting + votesCapsule.clearNewVotes(); + for (Protocol.Vote vote : accountCapsule.getVotesList()) { + long newVoteCount = + (long) ((double) vote.getVoteCount() / totalVote * ownedTronPower / TRX_PRECISION); + if (newVoteCount > 0) { + votesCapsule.addNewVotes(vote.getVoteAddress(), newVoteCount); } } + repo.updateVotes(ownerAddress, votesCapsule); + + accountCapsule.clearVotes(); + for (Protocol.Vote vote : votesCapsule.getNewVotes()) { + accountCapsule.addVotes(vote.getVoteAddress(), vote.getVoteCount()); + } } } From 8ff83b0bb66d6d4661407d51df31605b9a6243ba Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Mon, 31 Oct 2022 14:24:06 +0800 Subject: [PATCH 0398/1197] fix(freezeV2): fix freezeV2 --- .../org/tron/core/actuator/UnDelegateResourceActuator.java | 2 ++ .../src/main/java/org/tron/core/db/BandwidthProcessor.java | 4 ---- chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index b629b9fd4a0..0ab410939ea 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -92,6 +92,7 @@ public boolean execute(Object result) throws ContractExeException { long newNetUsage = receiverCapsule.getNetUsage() - transferUsage; receiverCapsule.setNetUsage(newNetUsage); + receiverCapsule.setLatestConsumeTime(chainBaseManager.getHeadSlot()); break; case ENERGY: EnergyProcessor energyProcessor = new EnergyProcessor(dynamicStore, accountStore); @@ -114,6 +115,7 @@ public boolean execute(Object result) throws ContractExeException { long newEnergyUsage = receiverCapsule.getEnergyUsage() - transferUsage; receiverCapsule.setEnergyUsage(newEnergyUsage); + receiverCapsule.setLatestConsumeTimeForEnergy(chainBaseManager.getHeadSlot()); break; default: //this should never happen diff --git a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java index af4ef152a3b..c98b553ba3f 100644 --- a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -47,11 +47,9 @@ private void updateUsage(AccountCapsule accountCapsule, long now) { long latestConsumeTime = accountCapsule.getLatestConsumeTime(); accountCapsule.setNetUsage(increase(accountCapsule, BANDWIDTH, oldNetUsage, 0, latestConsumeTime, now)); - accountCapsule.setLatestConsumeTime(now); long oldFreeNetUsage = accountCapsule.getFreeNetUsage(); long latestConsumeFreeTime = accountCapsule.getLatestConsumeFreeTime(); accountCapsule.setFreeNetUsage(increase(oldFreeNetUsage, 0, latestConsumeFreeTime, now)); - accountCapsule.setLatestConsumeFreeTime(now); if (chainBaseManager.getDynamicPropertiesStore().getAllowSameTokenName() == 0) { Map assetMap = accountCapsule.getAssetMap(); @@ -60,7 +58,6 @@ private void updateUsage(AccountCapsule accountCapsule, long now) { long latestAssetOperationTime = accountCapsule.getLatestAssetOperationTime(assetName); accountCapsule.putFreeAssetNetUsage(assetName, increase(oldFreeAssetNetUsage, 0, latestAssetOperationTime, now)); - accountCapsule.putLatestAssetOperationTimeMap(assetName, now); }); } Map assetMapV2 = accountCapsule.getAssetMapV2(); @@ -76,7 +73,6 @@ private void updateUsage(AccountCapsule accountCapsule, long now) { long latestAssetOperationTime = accountCapsule.getLatestAssetOperationTimeV2(assetName); accountCapsule.putFreeAssetNetUsageV2(assetName, increase(oldFreeAssetNetUsage, 0, latestAssetOperationTime, now)); - accountCapsule.putLatestAssetOperationTimeMapV2(assetName, now); }); } diff --git a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java index 4cc999a6937..beca72fad63 100644 --- a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java @@ -45,7 +45,6 @@ private void updateUsage(AccountCapsule accountCapsule, long now) { accountCapsule.setEnergyUsage(increase(accountCapsule, ENERGY, oldEnergyUsage, 0, latestConsumeTime, now)); - accountCapsule.setLatestConsumeTimeForEnergy(now); } public void updateTotalEnergyAverageUsage() { From 4efc27238d8cfcd825f57a520a0aec009d7df0c4 Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 31 Oct 2022 15:16:09 +0800 Subject: [PATCH 0399/1197] feat(freezeV2): optimize add all votes --- .../nativecontract/UnfreezeBalanceV2Processor.java | 13 +++++++++---- .../java/org/tron/core/capsule/AccountCapsule.java | 3 +++ .../java/org/tron/core/capsule/VotesCapsule.java | 4 ++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index aca12cde11d..2f5ff1cd8e3 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -7,6 +7,7 @@ import com.google.common.collect.Lists; import com.google.protobuf.ByteString; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -275,19 +276,23 @@ private void updateVote( } // Update Owner Voting + List votesToAdd = new ArrayList<>(); votesCapsule.clearNewVotes(); for (Protocol.Vote vote : accountCapsule.getVotesList()) { long newVoteCount = (long) ((double) vote.getVoteCount() / totalVote * ownedTronPower / TRX_PRECISION); if (newVoteCount > 0) { - votesCapsule.addNewVotes(vote.getVoteAddress(), newVoteCount); + votesToAdd.add( + Protocol.Vote.newBuilder() + .setVoteAddress(vote.getVoteAddress()) + .setVoteCount(newVoteCount) + .build()); } } + votesCapsule.addAllNewVotes(votesToAdd); repo.updateVotes(ownerAddress, votesCapsule); accountCapsule.clearVotes(); - for (Protocol.Vote vote : votesCapsule.getNewVotes()) { - accountCapsule.addVotes(vote.getVoteAddress(), vote.getVoteCount()); - } + accountCapsule.addAllVotes(votesToAdd); } } diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index 9606d7271d0..c17da254cfc 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -493,6 +493,9 @@ public void addVotes(ByteString voteAddress, long voteAdd) { .addVotes(Vote.newBuilder().setVoteAddress(voteAddress).setVoteCount(voteAdd).build()) .build(); } + public void addAllVotes(List votesToAdd) { + this.account = this.account.toBuilder().addAllVotes(votesToAdd).build(); + } public void clearLatestAssetOperationTimeV2() { this.account = this.account.toBuilder() diff --git a/chainbase/src/main/java/org/tron/core/capsule/VotesCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/VotesCapsule.java index a3692d52627..6e92dff56d4 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/VotesCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/VotesCapsule.java @@ -84,6 +84,10 @@ public void addNewVotes(ByteString voteAddress, long voteCount) { .build(); } + public void addAllNewVotes(List votesToAdd) { + this.votes = this.votes.toBuilder().addAllNewVotes(votesToAdd).build(); + } + public void addOldVotes(ByteString voteAddress, long voteCount) { this.votes = this.votes.toBuilder() .addOldVotes(Vote.newBuilder().setVoteAddress(voteAddress).setVoteCount(voteCount).build()) From 07ddb25c55eabfad5d2de4aa5a42b52517bbc558 Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 31 Oct 2022 15:30:42 +0800 Subject: [PATCH 0400/1197] feat(freezeV2): set latest consume time --- actuator/src/main/java/org/tron/core/actuator/VMActuator.java | 2 ++ .../core/vm/nativecontract/UnDelegateResourceProcessor.java | 2 ++ actuator/src/main/java/org/tron/core/vm/program/Program.java | 2 ++ 3 files changed, 6 insertions(+) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index e7e98b62e60..2388768f0d5 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -557,6 +557,7 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi rootRepository.getDynamicPropertiesStore(), ChainBaseManager.getInstance().getAccountStore()); energyProcessor.updateUsage(account); + account.setLatestConsumeTimeForEnergy(now); receipt.setCallerEnergyUsage(account.getEnergyUsage()); receipt.setCallerEnergyWindowSize(account.getWindowSize(Common.ResourceCode.ENERGY)); account.setEnergyUsage( @@ -717,6 +718,7 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu rootRepository.getDynamicPropertiesStore(), ChainBaseManager.getInstance().getAccountStore()); energyProcessor.updateUsage(creator); + creator.setLatestConsumeTimeForEnergy(now); receipt.setOriginEnergyUsage(creator.getEnergyUsage()); receipt.setOriginEnergyWindowSize(creator.getWindowSize(Common.ResourceCode.ENERGY)); creator.setEnergyUsage( diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index 9050771950d..f4c1af6dc59 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -119,6 +119,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { long newNetUsage = receiverCapsule.getNetUsage() - transferUsage; receiverCapsule.setNetUsage(newNetUsage); + receiverCapsule.setLatestConsumeTime(now); break; case ENERGY: EnergyProcessor energyProcessor = @@ -142,6 +143,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { long newEnergyUsage = receiverCapsule.getEnergyUsage() - transferUsage; receiverCapsule.setEnergyUsage(newEnergyUsage); + receiverCapsule.setLatestConsumeTimeForEnergy(now); break; default: //this should never happen diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index c0a7827fe81..ef572e32f79 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -544,6 +544,7 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit // merge usage BandwidthProcessor bandwidthProcessor = new BandwidthProcessor(ChainBaseManager.getInstance()); bandwidthProcessor.updateUsage(ownerCapsule); + ownerCapsule.setLatestConsumeTime(now); if (ownerCapsule.getNetUsage() > 0) { long newNetUsage = bandwidthProcessor.unDelegateIncrease( @@ -560,6 +561,7 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit new EnergyProcessor( repo.getDynamicPropertiesStore(), ChainBaseManager.getInstance().getAccountStore()); energyProcessor.updateUsage(ownerCapsule); + ownerCapsule.setLatestConsumeTimeForEnergy(now); if (ownerCapsule.getEnergyUsage() > 0) { long newEnergyUsage = energyProcessor.unDelegateIncrease( From 431c547bad007744d7a8b6b6f2b368825cda564e Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 31 Oct 2022 15:40:02 +0800 Subject: [PATCH 0401/1197] feat(freezeV2): optimize code format --- .../tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java | 2 +- .../src/main/java/org/tron/core/capsule/AccountCapsule.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index 2f5ff1cd8e3..4fb02d7dac1 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -277,7 +277,6 @@ private void updateVote( // Update Owner Voting List votesToAdd = new ArrayList<>(); - votesCapsule.clearNewVotes(); for (Protocol.Vote vote : accountCapsule.getVotesList()) { long newVoteCount = (long) ((double) vote.getVoteCount() / totalVote * ownedTronPower / TRX_PRECISION); @@ -289,6 +288,7 @@ private void updateVote( .build()); } } + votesCapsule.clearNewVotes(); votesCapsule.addAllNewVotes(votesToAdd); repo.updateVotes(ownerAddress, votesCapsule); diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index c17da254cfc..f94a9ca1eea 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -493,6 +493,7 @@ public void addVotes(ByteString voteAddress, long voteAdd) { .addVotes(Vote.newBuilder().setVoteAddress(voteAddress).setVoteCount(voteAdd).build()) .build(); } + public void addAllVotes(List votesToAdd) { this.account = this.account.toBuilder().addAllVotes(votesToAdd).build(); } From 719f8b774e926da783c73759274c877854f76ff9 Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 31 Oct 2022 19:37:17 +0800 Subject: [PATCH 0402/1197] fix(tvm,freezeV2): do not set merged state for caller & deployer if tx is not success --- chainbase/src/main/java/org/tron/core/db/TransactionTrace.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java index c5989756681..bf00c70e4e5 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java @@ -246,7 +246,8 @@ public void pay() throws BalanceInsufficientException { // originAccount Percent = 30% AccountCapsule origin = accountStore.get(originAccount); AccountCapsule caller = accountStore.get(callerAccount); - if (dynamicPropertiesStore.supportUnfreezeDelay()) { + if (dynamicPropertiesStore.supportUnfreezeDelay() + && receipt.getReceipt().getResult().equals(contractResult.SUCCESS)) { // just fo caller is not origin, we set the related field for origin account if (!caller.getAddress().equals(origin.getAddress())) { From 23e27d9f05957411b8018e71f6856d98506709d0 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Tue, 1 Nov 2022 20:24:46 +0800 Subject: [PATCH 0403/1197] feat(memo-fee): add a proposal for memo fee 1. additional fee is charged when the transaction has memo information. --- .../org/tron/core/utils/ProposalUtil.java | 14 ++++++- .../org/tron/core/capsule/ReceiptCapsule.java | 3 ++ .../core/capsule/utils/TransactionUtil.java | 6 +-- .../core/store/DynamicPropertiesStore.java | 19 ++++++++++ .../common/parameter/CommonParameter.java | 4 ++ .../src/main/java/org/tron/core/Constant.java | 1 + .../src/main/java/org/tron/core/Wallet.java | 5 +++ .../java/org/tron/core/config/args/Args.java | 10 +++++ .../tron/core/consensus/ProposalService.java | 4 ++ .../main/java/org/tron/core/db/Manager.java | 37 +++++++++++++++++++ 10 files changed, 99 insertions(+), 4 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 0fc7adba674..c18130d4221 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -575,6 +575,17 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case MEMO_FEE: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_6)) { + throw new ContractValidateException( + "Bad chain parameter id [MEMO_FEE]"); + } + if (value < 1 || value > 1_000_000_000) { + throw new ContractValidateException( + "This value[MEMO_FEE] is only allowed to be in the range 1-1000_000_000"); + } + break; + } default: break; } @@ -639,7 +650,8 @@ public enum ProposalType { // current value, value range ALLOW_TVM_LONDON(63), // 0, 1 ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX(65), // 0, 1 ALLOW_ASSET_OPTIMIZATION(66), // 0, 1 - ALLOW_NEW_REWARD_ALGO(67); // 0, 1 + ALLOW_NEW_REWARD_ALGO(67), // 0, 1 + MEMO_FEE(68); // 0, [1, 1000_000_000] private long code; diff --git a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index 3124494c67e..30fd1f7ecd3 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -24,6 +24,9 @@ public class ReceiptCapsule { @Setter private long multiSignFee; + @Getter + @Setter + private long memoFee; /** * Available energy of contract deployer before executing transaction */ diff --git a/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java b/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java index a2c3facd565..fc164bb9e36 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java +++ b/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java @@ -72,9 +72,9 @@ public static TransactionInfoCapsule buildTransactionInfoInstance(TransactionCap } builder.setId(ByteString.copyFrom(trxCap.getTransactionId().getBytes())); ProgramResult programResult = trace.getRuntimeResult(); - long fee = - programResult.getRet().getFee() + traceReceipt.getEnergyFee() - + traceReceipt.getNetFee() + traceReceipt.getMultiSignFee(); + long fee = programResult.getRet().getFee() + traceReceipt.getEnergyFee() + + traceReceipt.getNetFee() + traceReceipt.getMultiSignFee() + + traceReceipt.getMemoFee(); boolean supportTransactionFeePool = trace.getTransactionContext().getStoreFactory() .getChainBaseManager().getDynamicPropertiesStore().supportTransactionFeePool(); diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index df37059f2ad..aa800266be5 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -187,6 +187,8 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX = "ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX".getBytes(); + private static final byte[] MEMO_FEE = "MEMO_FEE".getBytes(); + @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { super(dbName); @@ -857,6 +859,12 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { new BytesCapsule(ByteArray.fromLong(Long.MAX_VALUE))); } } + + try { + this.getMemoFee(); + } catch (IllegalArgumentException e) { + this.saveMemoFee(CommonParameter.getInstance().getMemoFee()); + } } public String intArrayToString(int[] a) { @@ -2528,6 +2536,17 @@ public long getAllowHigherLimitForMaxCpuTimeOfOneTx() { () -> new IllegalArgumentException(msg)); } + public long getMemoFee() { + return Optional.ofNullable(getUnchecked(MEMO_FEE)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow(() -> new IllegalArgumentException("not found MEMO_FEE")); + } + + public void saveMemoFee(long value) { + this.put(MEMO_FEE, new BytesCapsule(ByteArray.fromLong(value))); + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 26aa7d44834..0331628d53c 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -561,6 +561,10 @@ public class CommonParameter { @Setter public long allowNewRewardAlgorithm; + @Getter + @Setter + public long memoFee = 0L; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index af96fbea859..aa287b1d885 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -307,6 +307,7 @@ public class Constant { public static final String ALLOW_ACCOUNT_ASSET_OPTIMIZATION = "committee.allowAccountAssetOptimization"; public static final String ALLOW_ASSET_OPTIMIZATION = "committee.allowAssetOptimization"; + public static final String MEMO_FEE = "committee.memoFee"; public static final String LOCAL_HOST = "127.0.0.1"; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 33bd411c28f..7db0fd83c33 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1103,6 +1103,11 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().useNewRewardAlgorithm() ? 1 : 0) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getMemoFee") + .setValue(dbManager.getDynamicPropertiesStore().getMemoFee()) + .build()); + return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index b75664ed3c1..26a3250a369 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1034,6 +1034,16 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.blockCacheTimeout = config.getLong(Constant.BLOCK_CACHE_TIMEOUT); } + if (config.hasPath(Constant.MEMO_FEE)) { + PARAMETER.memoFee = config.getLong(Constant.MEMO_FEE); + if (PARAMETER.memoFee > 1_000_000_000) { + PARAMETER.memoFee = 1_000_000_000; + } + if (PARAMETER.memoFee < 0) { + PARAMETER.memoFee = 0; + } + } + logConfig(); } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 92472335d20..50aee112819 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -288,6 +288,10 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveNewRewardAlgorithmEffectiveCycle(); break; } + case MEMO_FEE: { + manager.getDynamicPropertiesStore().saveMemoFee(entry.getValue()); + break; + } default: find = false; break; diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 80be86403ba..fa75deafb3f 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -855,6 +855,42 @@ public void consumeMultiSignFee(TransactionCapsule trx, TransactionTrace trace) } } + public void consumeMemoFee(TransactionCapsule trx, TransactionTrace trace) + throws AccountResourceInsufficientException { + if (trx.getInstance().getRawData().getData().isEmpty()) { + // no memo + return; + } + + long fee = getDynamicPropertiesStore().getMemoFee(); + if (fee == 0) { + return; + } + + List contracts = trx.getInstance().getRawData().getContractList(); + for (Contract contract : contracts) { + byte[] address = TransactionCapsule.getOwner(contract); + AccountCapsule accountCapsule = getAccountStore().get(address); + try { + if (accountCapsule != null) { + adjustBalance(getAccountStore(), accountCapsule, -fee); + + if (getDynamicPropertiesStore().supportBlackHoleOptimization()) { + getDynamicPropertiesStore().burnTrx(fee); + } else { + adjustBalance(getAccountStore(), this.getAccountStore().getBlackhole(), +fee); + } + } + } catch (BalanceInsufficientException e) { + throw new AccountResourceInsufficientException( + String.format("account %s insufficient balance[%d] to memo fee", + StringUtil.encode58Check(address), fee)); + } + } + + trace.getReceipt().setMemoFee(fee); + } + public void consumeBandwidth(TransactionCapsule trx, TransactionTrace trace) throws ContractValidateException, AccountResourceInsufficientException, TooBigTransactionResultException { @@ -1338,6 +1374,7 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block consumeBandwidth(trxCap, trace); consumeMultiSignFee(trxCap, trace); + consumeMemoFee(trxCap, trace); trace.init(blockCap, eventPluginLoaded); trace.checkIsConstant(); From 8a3877b1e3bcb2cfb2d1cea5908b2596c399719b Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Wed, 2 Nov 2022 17:10:47 +0800 Subject: [PATCH 0404/1197] feat(memo-fee): add a interface of memo fee --- .../org/tron/core/utils/ProposalUtil.java | 4 +- .../core/store/DynamicPropertiesStore.java | 16 +++++++- .../src/main/java/org/tron/core/Wallet.java | 8 ++++ .../tron/core/consensus/ProposalService.java | 4 ++ .../services/http/FullNodeHttpApiService.java | 3 ++ .../http/GetMemoFeePricesServlet.java | 37 +++++++++++++++++++ 6 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/services/http/GetMemoFeePricesServlet.java diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index c18130d4221..8235daa9cdb 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -580,9 +580,9 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, throw new ContractValidateException( "Bad chain parameter id [MEMO_FEE]"); } - if (value < 1 || value > 1_000_000_000) { + if (value < 0 || value > 1_000_000_000) { throw new ContractValidateException( - "This value[MEMO_FEE] is only allowed to be in the range 1-1000_000_000"); + "This value[MEMO_FEE] is only allowed to be in the range 0-1000_000_000"); } break; } diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index aa800266be5..9f4c9444cbe 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -188,6 +188,7 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking "ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX".getBytes(); private static final byte[] MEMO_FEE = "MEMO_FEE".getBytes(); + private static final byte[] MEMO_FEE_HISTORY = "MEMO_FEE_HISTORY".getBytes(); @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { @@ -863,7 +864,9 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { try { this.getMemoFee(); } catch (IllegalArgumentException e) { - this.saveMemoFee(CommonParameter.getInstance().getMemoFee()); + long memoFee = CommonParameter.getInstance().getMemoFee(); + this.saveMemoFee(memoFee); + this.saveMemoFeeHistory("0:" + memoFee); } } @@ -2547,6 +2550,17 @@ public void saveMemoFee(long value) { this.put(MEMO_FEE, new BytesCapsule(ByteArray.fromLong(value))); } + public String getMemoFeeHistory() { + return Optional.ofNullable(getUnchecked(MEMO_FEE_HISTORY)) + .map(BytesCapsule::getData) + .map(ByteArray::toStr) + .orElseThrow(() -> new IllegalArgumentException("not found MEMO_FEE_HISTORY")); + } + + public void saveMemoFeeHistory(String value) { + this.put(MEMO_FEE_HISTORY, new BytesCapsule(ByteArray.fromString(value))); + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 7db0fd83c33..5f77a651ea0 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -4085,5 +4085,13 @@ public Block getBlock(GrpcAPI.BlockReq request) { return block.toBuilder().clearTransactions().build(); } + public String getMemoFeePrices() { + try { + return chainBaseManager.getDynamicPropertiesStore().getMemoFeeHistory(); + } catch (Exception e) { + logger.error("getMemoFeePrices failed, error is {}", e.getMessage()); + } + return null; + } } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 50aee112819..0d2ed945f42 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -290,6 +290,10 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) } case MEMO_FEE: { manager.getDynamicPropertiesStore().saveMemoFee(entry.getValue()); + // update memo fee history + manager.getDynamicPropertiesStore().saveMemoFeeHistory( + manager.getDynamicPropertiesStore().getMemoFeeHistory() + + "," + proposalCapsule.getExpirationTime() + ":" + entry.getValue()); break; } default: diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index 031bd38e50c..30c0b380551 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -293,6 +293,8 @@ public class FullNodeHttpApiService implements Service { private GetBandwidthPricesServlet getBandwidthPricesServlet; @Autowired private GetBlockServlet getBlockServlet; + @Autowired + private GetMemoFeePricesServlet getMemoFeePricesServlet; private static String getParamsFile(String fileName) { InputStream in = Thread.currentThread().getContextClassLoader() @@ -542,6 +544,7 @@ public void start() { context.addServlet(new ServletHolder(getBandwidthPricesServlet), "/wallet/getbandwidthprices"); context.addServlet(new ServletHolder(getBlockServlet), "/wallet/getblock"); + context.addServlet(new ServletHolder(getMemoFeePricesServlet), "/wallet/getmemofee"); int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { diff --git a/framework/src/main/java/org/tron/core/services/http/GetMemoFeePricesServlet.java b/framework/src/main/java/org/tron/core/services/http/GetMemoFeePricesServlet.java new file mode 100644 index 00000000000..8d5f46d8236 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/GetMemoFeePricesServlet.java @@ -0,0 +1,37 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; + + +@Component +@Slf4j(topic = "API") +public class GetMemoFeePricesServlet extends RateLimiterServlet { + + @Autowired + private Wallet wallet; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + try { + String reply = wallet.getMemoFeePrices(); + if (reply != null) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("prices", reply); + response.getWriter().println(jsonObject); + } else { + response.getWriter().println("{}"); + } + } catch (Exception e) { + Util.processError(e, response); + } + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + doGet(request, response); + } +} From 6ba974155929551bef3ad0af467b59804412a3bd Mon Sep 17 00:00:00 2001 From: chaozhu Date: Wed, 2 Nov 2022 11:37:58 -0700 Subject: [PATCH 0405/1197] feat(freezeV2): new stake, add 3 interfaces --- .../src/main/java/org/tron/core/Wallet.java | 55 ++++++++++- .../org/tron/core/services/RpcApiService.java | 92 ++++++++++++++++++- .../services/http/FullNodeHttpApiService.java | 13 +++ .../GetCanWithdrawUnfreezeAmountServlet.java | 61 ++++++++++++ ...elegatedResourceAccountIndexV2Servlet.java | 70 ++++++++++++++ .../http/GetDelegatedResourceV2Servlet.java | 61 ++++++++++++ .../http/HttpSelfFormatFieldName.java | 1 + .../solidity/SolidityNodeHttpApiService.java | 15 +++ ...thdrawUnfreezeAmountOnSolidityServlet.java | 30 ++++++ ...sourceAccountIndexV2OnSolidityServlet.java | 26 ++++++ ...tDelegatedResourceV2OnSolidityServlet.java | 29 ++++++ .../solidity/HttpApiOnSolidityService.java | 18 ++++ protocol/src/main/protos/api/api.proto | 27 ++++++ 13 files changed, 495 insertions(+), 3 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/services/http/GetCanWithdrawUnfreezeAmountServlet.java create mode 100644 framework/src/main/java/org/tron/core/services/http/GetDelegatedResourceAccountIndexV2Servlet.java create mode 100644 framework/src/main/java/org/tron/core/services/http/GetDelegatedResourceV2Servlet.java create mode 100644 framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetCanWithdrawUnfreezeAmountOnSolidityServlet.java create mode 100644 framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetDelegatedResourceAccountIndexV2OnSolidityServlet.java create mode 100644 framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetDelegatedResourceV2OnSolidityServlet.java diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index c53943a4b1f..064f02443af 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -183,6 +183,7 @@ import org.tron.core.store.AccountTraceStore; import org.tron.core.store.BalanceTraceStore; import org.tron.core.store.ContractStore; +import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.store.MarketOrderStore; import org.tron.core.store.MarketPairPriceToOrderStore; import org.tron.core.store.MarketPairToPriceStore; @@ -751,13 +752,65 @@ public DelegatedResourceList getDelegatedResource(ByteString fromAddress, ByteSt return builder.build(); } + public DelegatedResourceList getDelegatedResourceV2( + ByteString fromAddress, ByteString toAddress) { + DelegatedResourceList.Builder builder = DelegatedResourceList.newBuilder(); + byte[] dbKey = DelegatedResourceCapsule + .createDbKeyV2(fromAddress.toByteArray(), toAddress.toByteArray()); + DelegatedResourceCapsule delegatedResourceCapsule = chainBaseManager.getDelegatedResourceStore() + .get(dbKey); + if (delegatedResourceCapsule != null) { + builder.addDelegatedResource(delegatedResourceCapsule.getInstance()); + } + return builder.build(); + } + + public GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage getCanWithdrawUnfreezeAmount( + ByteString ownerAddress) { + GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage.Builder builder = + GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage.newBuilder(); + long canWithdrawUnfreezeAmount; + + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + AccountCapsule accountCapsule = accountStore.get(ownerAddress.toByteArray()); + if (accountCapsule == null) { + return builder.build(); + } + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + + List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); + canWithdrawUnfreezeAmount = unfrozenV2List + .stream() + .filter(unfrozenV2 -> + (unfrozenV2.getUnfreezeAmount() > 0 + && unfrozenV2.getUnfreezeExpireTime() <= now)) + .mapToLong(Account.UnFreezeV2::getUnfreezeAmount) + .sum(); + + + builder.setAmount(canWithdrawUnfreezeAmount); + return builder.build(); + } + public DelegatedResourceAccountIndex getDelegatedResourceAccountIndex(ByteString address) { DelegatedResourceAccountIndexCapsule accountIndexCapsule = chainBaseManager.getDelegatedResourceAccountIndexStore().get(address.toByteArray()); if (accountIndexCapsule != null) { return accountIndexCapsule.getInstance(); } else { - return null; + return DelegatedResourceAccountIndex.getDefaultInstance(); + } + } + + public DelegatedResourceAccountIndex getDelegatedResourceAccountIndexV2(ByteString address) { + byte[] dbKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(address.toByteArray()); + DelegatedResourceAccountIndexCapsule accountIndexCapsule = + chainBaseManager.getDelegatedResourceAccountIndexStore().get(dbKey); + if (accountIndexCapsule != null) { + return accountIndexCapsule.getInstance(); + } else { + return DelegatedResourceAccountIndex.getDefaultInstance(); } } diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index c535950cffa..d8976d36547 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -35,6 +35,7 @@ import org.tron.api.GrpcAPI.BlockListExtention; import org.tron.api.GrpcAPI.BlockReference; import org.tron.api.GrpcAPI.BytesMessage; +import org.tron.api.GrpcAPI.CanWithdrawUnfreezeAmountRequestMessage; import org.tron.api.GrpcAPI.DecryptNotes; import org.tron.api.GrpcAPI.DecryptNotesMarked; import org.tron.api.GrpcAPI.DecryptNotesTRC20; @@ -600,11 +601,54 @@ public void getDelegatedResource(DelegatedResourceMessage request, responseObserver.onCompleted(); } + @Override + public void getDelegatedResourceV2(DelegatedResourceMessage request, + StreamObserver responseObserver) { + try { + responseObserver.onNext(wallet.getDelegatedResourceV2( + request.getFromAddress(), request.getToAddress()) + ); + } catch (Exception e) { + responseObserver.onError(getRunTimeException(e)); + } + responseObserver.onCompleted(); + } + @Override public void getDelegatedResourceAccountIndex(BytesMessage request, StreamObserver responseObserver) { - responseObserver + try { + responseObserver .onNext(wallet.getDelegatedResourceAccountIndex(request.getValue())); + } catch (Exception e) { + responseObserver.onError(getRunTimeException(e)); + } + responseObserver.onCompleted(); + } + + @Override + public void getDelegatedResourceAccountIndexV2(BytesMessage request, + StreamObserver responseObserver) { + try { + responseObserver + .onNext(wallet.getDelegatedResourceAccountIndexV2(request.getValue())); + } catch (Exception e) { + responseObserver.onError(getRunTimeException(e)); + } + responseObserver.onCompleted(); + } + + @Override + public void getCanWithdrawUnfreezeAmount(CanWithdrawUnfreezeAmountRequestMessage request, + StreamObserver responseObserver) { + try { + responseObserver + .onNext(wallet.getCanWithdrawUnfreezeAmount( + request.getOwnerAddress()) + ); + } catch (Exception e) { + responseObserver.onError(getRunTimeException(e)); + } responseObserver.onCompleted(); } @@ -2016,10 +2060,54 @@ public void getDelegatedResource(DelegatedResourceMessage request, responseObserver.onCompleted(); } + @Override + public void getDelegatedResourceV2(DelegatedResourceMessage request, + StreamObserver responseObserver) { + try { + responseObserver.onNext(wallet.getDelegatedResourceV2( + request.getFromAddress(), request.getToAddress()) + ); + } catch (Exception e) { + responseObserver.onError(getRunTimeException(e)); + } + responseObserver.onCompleted(); + } + + @Override public void getDelegatedResourceAccountIndex(BytesMessage request, StreamObserver responseObserver) { - responseObserver + try { + responseObserver .onNext(wallet.getDelegatedResourceAccountIndex(request.getValue())); + } catch (Exception e) { + responseObserver.onError(getRunTimeException(e)); + } + responseObserver.onCompleted(); + } + + @Override + public void getDelegatedResourceAccountIndexV2(BytesMessage request, + StreamObserver responseObserver) { + try { + responseObserver + .onNext(wallet.getDelegatedResourceAccountIndexV2(request.getValue())); + } catch (Exception e) { + responseObserver.onError(getRunTimeException(e)); + } + responseObserver.onCompleted(); + } + + @Override + public void getCanWithdrawUnfreezeAmount(CanWithdrawUnfreezeAmountRequestMessage request, + StreamObserver responseObserver) { + try { + responseObserver + .onNext(wallet.getCanWithdrawUnfreezeAmount( + request.getOwnerAddress() + )); + } catch (Exception e) { + responseObserver.onError(getRunTimeException(e)); + } responseObserver.onCompleted(); } diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index 2c2a4f8797c..b2ebf1af7ad 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -182,8 +182,14 @@ public class FullNodeHttpApiService implements Service { @Autowired private GetDelegatedResourceAccountIndexServlet getDelegatedResourceAccountIndexServlet; @Autowired + private GetDelegatedResourceAccountIndexV2Servlet getDelegatedResourceAccountIndexV2Servlet; + @Autowired private GetDelegatedResourceServlet getDelegatedResourceServlet; @Autowired + private GetDelegatedResourceV2Servlet getDelegatedResourceV2Servlet; + @Autowired + private GetCanWithdrawUnfreezeAmountServlet getCanWithdrawUnfreezeAmountServlet; + @Autowired private SetAccountIdServlet setAccountServlet; @Autowired private GetAccountByIdServlet getAccountByIdServlet; @@ -462,9 +468,16 @@ public void start() { context.addServlet(new ServletHolder(updateEnergyLimitServlet), "/wallet/updateenergylimit"); context.addServlet(new ServletHolder(getDelegatedResourceServlet), "/wallet/getdelegatedresource"); + context.addServlet(new ServletHolder(getDelegatedResourceV2Servlet), + "/wallet/getdelegatedresourcev2"); + context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountServlet), + "/wallet/getcanwithdrawunfreezeamount"); context.addServlet( new ServletHolder(getDelegatedResourceAccountIndexServlet), "/wallet/getdelegatedresourceaccountindex"); + context.addServlet( + new ServletHolder(getDelegatedResourceAccountIndexV2Servlet), + "/wallet/getdelegatedresourceaccountindexv2"); context.addServlet(new ServletHolder(setAccountServlet), "/wallet/setaccountid"); context.addServlet(new ServletHolder(getAccountByIdServlet), "/wallet/getaccountbyid"); context diff --git a/framework/src/main/java/org/tron/core/services/http/GetCanWithdrawUnfreezeAmountServlet.java b/framework/src/main/java/org/tron/core/services/http/GetCanWithdrawUnfreezeAmountServlet.java new file mode 100644 index 00000000000..fd1547d3931 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/GetCanWithdrawUnfreezeAmountServlet.java @@ -0,0 +1,61 @@ +package org.tron.core.services.http; + +import com.google.protobuf.ByteString; +import java.io.IOException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.api.GrpcAPI; +import org.tron.common.utils.ByteArray; +import org.tron.core.Wallet; + +@Component +@Slf4j(topic = "API") +public class GetCanWithdrawUnfreezeAmountServlet extends RateLimiterServlet { + + @Autowired + private Wallet wallet; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + try { + boolean visible = Util.getVisible(request); + String ownerAddress = request.getParameter("owner_address"); + if (visible) { + ownerAddress = Util.getHexAddress(ownerAddress); + } + fillResponse(visible, + ByteString.copyFrom(ByteArray.fromHexString(ownerAddress)), + response); + } catch (Exception e) { + Util.processError(e, response); + } + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + PostParams params = PostParams.getPostParams(request); + GrpcAPI.CanWithdrawUnfreezeAmountRequestMessage.Builder build = + GrpcAPI.CanWithdrawUnfreezeAmountRequestMessage.newBuilder(); + JsonFormat.merge(params.getParams(), build, params.isVisible()); + fillResponse(params.isVisible(), + build.getOwnerAddress(), + response); + } catch (Exception e) { + Util.processError(e, response); + } + } + + private void fillResponse(boolean visible, + ByteString ownerAddress, + HttpServletResponse response) throws IOException { + GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage reply = + wallet.getCanWithdrawUnfreezeAmount(ownerAddress); + if (reply != null) { + response.getWriter().println(JsonFormat.printToString(reply, visible)); + } else { + response.getWriter().println("{}"); + } + } +} diff --git a/framework/src/main/java/org/tron/core/services/http/GetDelegatedResourceAccountIndexV2Servlet.java b/framework/src/main/java/org/tron/core/services/http/GetDelegatedResourceAccountIndexV2Servlet.java new file mode 100644 index 00000000000..3d5bff80941 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/GetDelegatedResourceAccountIndexV2Servlet.java @@ -0,0 +1,70 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import com.google.protobuf.ByteString; +import java.io.IOException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.api.GrpcAPI.BytesMessage; +import org.tron.common.utils.ByteArray; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.DelegatedResourceAccountIndex; + + +@Component +@Slf4j(topic = "API") +public class GetDelegatedResourceAccountIndexV2Servlet extends RateLimiterServlet { + + private static final String VALUE_FIELD_NAME = "value"; + + @Autowired + private Wallet wallet; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + try { + boolean visible = Util.getVisible(request); + String address = request.getParameter(VALUE_FIELD_NAME); + if (visible) { + address = Util.getHexAddress(address); + } + fillResponse(ByteString.copyFrom(ByteArray.fromHexString(address)), visible, response); + } catch (Exception e) { + Util.processError(e, response); + } + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + PostParams params = PostParams.getPostParams(request); + boolean visible = params.isVisible(); + String input = params.getParams(); + if (visible) { + JSONObject jsonObject = JSONObject.parseObject(input); + String value = jsonObject.getString(VALUE_FIELD_NAME); + jsonObject.put(VALUE_FIELD_NAME, Util.getHexAddress(value)); + input = jsonObject.toJSONString(); + } + + BytesMessage.Builder build = BytesMessage.newBuilder(); + JsonFormat.merge(input, build, visible); + + fillResponse(build.getValue(), visible, response); + } catch (Exception e) { + Util.processError(e, response); + } + } + + private void fillResponse(ByteString address, boolean visible, HttpServletResponse response) + throws IOException { + DelegatedResourceAccountIndex reply = + wallet.getDelegatedResourceAccountIndexV2(address); + if (reply != null) { + response.getWriter().println(JsonFormat.printToString(reply, visible)); + } else { + response.getWriter().println("{}"); + } + } +} diff --git a/framework/src/main/java/org/tron/core/services/http/GetDelegatedResourceV2Servlet.java b/framework/src/main/java/org/tron/core/services/http/GetDelegatedResourceV2Servlet.java new file mode 100644 index 00000000000..632bb4f8033 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/GetDelegatedResourceV2Servlet.java @@ -0,0 +1,61 @@ +package org.tron.core.services.http; + +import com.google.protobuf.ByteString; +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.api.GrpcAPI.DelegatedResourceList; +import org.tron.api.GrpcAPI.DelegatedResourceMessage; +import org.tron.common.utils.ByteArray; +import org.tron.core.Wallet; + + + +@Component +@Slf4j(topic = "API") +public class GetDelegatedResourceV2Servlet extends RateLimiterServlet { + + @Autowired + private Wallet wallet; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + try { + boolean visible = Util.getVisible(request); + String fromAddress = request.getParameter("fromAddress"); + String toAddress = request.getParameter("toAddress"); + if (visible) { + fromAddress = Util.getHexAddress(fromAddress); + toAddress = Util.getHexAddress(toAddress); + } + fillResponse(visible, ByteString.copyFrom(ByteArray.fromHexString(fromAddress)), + ByteString.copyFrom(ByteArray.fromHexString(toAddress)), response); + } catch (Exception e) { + Util.processError(e, response); + } + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + PostParams params = PostParams.getPostParams(request); + DelegatedResourceMessage.Builder build = DelegatedResourceMessage.newBuilder(); + JsonFormat.merge(params.getParams(), build, params.isVisible()); + fillResponse(params.isVisible(), build.getFromAddress(), build.getToAddress(), response); + } catch (Exception e) { + Util.processError(e, response); + } + } + + private void fillResponse(boolean visible, ByteString fromAddress, ByteString toAddress, + HttpServletResponse response) throws IOException { + DelegatedResourceList reply = wallet.getDelegatedResourceV2(fromAddress, toAddress); + if (reply != null) { + response.getWriter().println(JsonFormat.printToString(reply, visible)); + } else { + response.getWriter().println("{}"); + } + } +} diff --git a/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java b/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java index 2526a9cfabe..7e320806de7 100644 --- a/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java +++ b/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java @@ -154,6 +154,7 @@ public class HttpSelfFormatFieldName { //UnDelegateResourceContract AddressFieldNameMap.put("protocol.UnDelegateResourceContract.owner_address", 1); AddressFieldNameMap.put("protocol.UnDelegateResourceContract.receiver_address", 1); + AddressFieldNameMap.put("protocol.CanWithdrawUnfreezeAmountRequestMessage.owner_address", 1); //***** Tron.proto ***** //AccountId diff --git a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java index e4ad276782e..de7d8491018 100644 --- a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java @@ -30,8 +30,11 @@ import org.tron.core.services.http.GetBlockServlet; import org.tron.core.services.http.GetBrokerageServlet; import org.tron.core.services.http.GetBurnTrxServlet; +import org.tron.core.services.http.GetCanWithdrawUnfreezeAmountServlet; import org.tron.core.services.http.GetDelegatedResourceAccountIndexServlet; +import org.tron.core.services.http.GetDelegatedResourceAccountIndexV2Servlet; import org.tron.core.services.http.GetDelegatedResourceServlet; +import org.tron.core.services.http.GetDelegatedResourceV2Servlet; import org.tron.core.services.http.GetExchangeByIdServlet; import org.tron.core.services.http.GetMarketOrderByAccountServlet; import org.tron.core.services.http.GetMarketOrderByIdServlet; @@ -80,8 +83,14 @@ public class SolidityNodeHttpApiService implements Service { @Autowired private GetDelegatedResourceServlet getDelegatedResourceServlet; @Autowired + private GetDelegatedResourceV2Servlet getDelegatedResourceV2Servlet; + @Autowired + private GetCanWithdrawUnfreezeAmountServlet getCanWithdrawUnfreezeAmountServlet; + @Autowired private GetDelegatedResourceAccountIndexServlet getDelegatedResourceAccountIndexServlet; @Autowired + private GetDelegatedResourceAccountIndexV2Servlet getDelegatedResourceAccountIndexV2Servlet; + @Autowired private GetExchangeByIdServlet getExchangeByIdServlet; @Autowired private ListExchangesServlet listExchangesServlet; @@ -201,8 +210,14 @@ public void start() { context.addServlet(new ServletHolder(getBlockByNumServlet), "/walletsolidity/getblockbynum"); context.addServlet(new ServletHolder(getDelegatedResourceServlet), "/walletsolidity/getdelegatedresource"); + context.addServlet(new ServletHolder(getDelegatedResourceV2Servlet), + "/walletsolidity/getdelegatedresourcev2"); + context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountServlet), + "/walletsolidity/getcanwithdrawunfreezeamount"); context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexServlet), "/walletsolidity/getdelegatedresourceaccountindex"); + context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexV2Servlet), + "/walletsolidity/getdelegatedresourceaccountindexv2"); context .addServlet(new ServletHolder(getExchangeByIdServlet), "/walletsolidity/getexchangebyid"); diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetCanWithdrawUnfreezeAmountOnSolidityServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetCanWithdrawUnfreezeAmountOnSolidityServlet.java new file mode 100644 index 00000000000..3f0b487fbe6 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetCanWithdrawUnfreezeAmountOnSolidityServlet.java @@ -0,0 +1,30 @@ +package org.tron.core.services.interfaceOnSolidity.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; +import org.tron.core.services.http.GetCanWithdrawUnfreezeAmountServlet; +import org.tron.core.services.interfaceOnSolidity.WalletOnSolidity; + +@Component +@Slf4j(topic = "API") +public class GetCanWithdrawUnfreezeAmountOnSolidityServlet + extends GetCanWithdrawUnfreezeAmountServlet { + + @Autowired + private Wallet wallet; + + @Autowired + private WalletOnSolidity walletOnSolidity; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetDelegatedResourceAccountIndexV2OnSolidityServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetDelegatedResourceAccountIndexV2OnSolidityServlet.java new file mode 100644 index 00000000000..edfaaf56c8b --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetDelegatedResourceAccountIndexV2OnSolidityServlet.java @@ -0,0 +1,26 @@ +package org.tron.core.services.interfaceOnSolidity.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetDelegatedResourceAccountIndexV2Servlet; +import org.tron.core.services.interfaceOnSolidity.WalletOnSolidity; + +@Component +@Slf4j(topic = "API") +public class GetDelegatedResourceAccountIndexV2OnSolidityServlet extends + GetDelegatedResourceAccountIndexV2Servlet { + + @Autowired + private WalletOnSolidity walletOnSolidity; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetDelegatedResourceV2OnSolidityServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetDelegatedResourceV2OnSolidityServlet.java new file mode 100644 index 00000000000..f481def86ea --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetDelegatedResourceV2OnSolidityServlet.java @@ -0,0 +1,29 @@ +package org.tron.core.services.interfaceOnSolidity.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; +import org.tron.core.services.http.GetDelegatedResourceV2Servlet; +import org.tron.core.services.interfaceOnSolidity.WalletOnSolidity; + +@Component +@Slf4j(topic = "API") +public class GetDelegatedResourceV2OnSolidityServlet extends GetDelegatedResourceV2Servlet { + + @Autowired + private Wallet wallet; + + @Autowired + private WalletOnSolidity walletOnSolidity; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java index 8f6d293a28b..fc1f0c592dd 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java @@ -29,8 +29,11 @@ import org.tron.core.services.interfaceOnSolidity.http.GetBlockOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetBrokerageOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetBurnTrxOnSolidityServlet; +import org.tron.core.services.interfaceOnSolidity.http.GetCanWithdrawUnfreezeAmountOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetDelegatedResourceAccountIndexOnSolidityServlet; +import org.tron.core.services.interfaceOnSolidity.http.GetDelegatedResourceAccountIndexV2OnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetDelegatedResourceOnSolidityServlet; +import org.tron.core.services.interfaceOnSolidity.http.GetDelegatedResourceV2OnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetEnergyPricesOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetExchangeByIdOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetMarketOrderByAccountOnSolidityServlet; @@ -56,6 +59,7 @@ import org.tron.core.services.interfaceOnSolidity.http.ScanShieldedTRC20NotesByOvkOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.TriggerConstantContractOnSolidityServlet; + @Slf4j(topic = "API") public class HttpApiOnSolidityService implements Service { @@ -87,9 +91,17 @@ public class HttpApiOnSolidityService implements Service { @Autowired private GetDelegatedResourceOnSolidityServlet getDelegatedResourceOnSolidityServlet; @Autowired + private GetDelegatedResourceV2OnSolidityServlet getDelegatedResourceV2OnSolidityServlet; + @Autowired + private GetCanWithdrawUnfreezeAmountOnSolidityServlet + getCanWithdrawUnfreezeAmountOnSolidityServlet; + @Autowired private GetDelegatedResourceAccountIndexOnSolidityServlet getDelegatedResourceAccountIndexOnSolidityServlet; @Autowired + private GetDelegatedResourceAccountIndexV2OnSolidityServlet + getDelegatedResourceAccountIndexV2OnSolidityServlet; + @Autowired private GetExchangeByIdOnSolidityServlet getExchangeByIdOnSolidityServlet; @Autowired private ListExchangesOnSolidityServlet listExchangesOnSolidityServlet; @@ -198,8 +210,14 @@ public void start() { "/walletsolidity/getblockbynum"); context.addServlet(new ServletHolder(getDelegatedResourceOnSolidityServlet), "/walletsolidity/getdelegatedresource"); + context.addServlet(new ServletHolder(getDelegatedResourceV2OnSolidityServlet), + "/walletsolidity/getdelegatedresourcev2"); + context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountOnSolidityServlet), + "/walletsolidity/getcanwithdrawunfreezeamount"); context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexOnSolidityServlet), "/walletsolidity/getdelegatedresourceaccountindex"); + context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexV2OnSolidityServlet), + "/walletsolidity/getdelegatedresourceaccountindexv2"); context.addServlet(new ServletHolder(getExchangeByIdOnSolidityServlet), "/walletsolidity/getexchangebyid"); context.addServlet(new ServletHolder(listExchangesOnSolidityServlet), diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 037f137c79e..4d75f0e9326 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -497,9 +497,19 @@ service Wallet { rpc GetDelegatedResource (DelegatedResourceMessage) returns (DelegatedResourceList) { }; + rpc GetDelegatedResourceV2 (DelegatedResourceMessage) returns (DelegatedResourceList) { + }; + rpc GetDelegatedResourceAccountIndex (BytesMessage) returns (DelegatedResourceAccountIndex) { }; + rpc GetDelegatedResourceAccountIndexV2 (BytesMessage) returns (DelegatedResourceAccountIndex) { + }; + + rpc GetCanWithdrawUnfreezeAmount (CanWithdrawUnfreezeAmountRequestMessage) + returns (CanWithdrawUnfreezeAmountResponseMessage) { + } + rpc ListProposals (EmptyMessage) returns (ProposalList) { option (google.api.http) = { post: "/wallet/listproposals" @@ -901,9 +911,19 @@ service WalletSolidity { rpc GetDelegatedResource (DelegatedResourceMessage) returns (DelegatedResourceList) { }; + rpc GetDelegatedResourceV2 (DelegatedResourceMessage) returns (DelegatedResourceList) { + }; + rpc GetDelegatedResourceAccountIndex (BytesMessage) returns (DelegatedResourceAccountIndex) { }; + rpc GetDelegatedResourceAccountIndexV2 (BytesMessage) returns (DelegatedResourceAccountIndex) { + }; + + rpc GetCanWithdrawUnfreezeAmount (CanWithdrawUnfreezeAmountRequestMessage) + returns (CanWithdrawUnfreezeAmountResponseMessage) { + } + rpc GetExchangeById (BytesMessage) returns (Exchange) { }; @@ -1118,6 +1138,13 @@ message DelegatedResourceList { repeated DelegatedResource delegatedResource = 1; } +message CanWithdrawUnfreezeAmountRequestMessage { + bytes owner_address = 1; +} +message CanWithdrawUnfreezeAmountResponseMessage { + int64 amount = 1; +} + // Gossip node list message NodeList { repeated Node nodes = 1; From 5711a01c669ae1ce329120c61c2f916b0dcfde56 Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 3 Nov 2022 17:22:45 +0800 Subject: [PATCH 0406/1197] func(proposal): optimize proposal check --- .../core/actuator/ClearABIContractActuator.java | 16 +++++++--------- .../UpdateEnergyLimitContractActuator.java | 10 +++++----- .../src/main/java/org/tron/core/db/Manager.java | 5 ----- 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/ClearABIContractActuator.java b/actuator/src/main/java/org/tron/core/actuator/ClearABIContractActuator.java index 5e0b2367dc5..7ce96d3318c 100755 --- a/actuator/src/main/java/org/tron/core/actuator/ClearABIContractActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/ClearABIContractActuator.java @@ -1,5 +1,7 @@ package org.tron.core.actuator; +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; + import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import java.util.Arrays; @@ -16,13 +18,10 @@ import org.tron.core.store.AbiStore; import org.tron.core.store.AccountStore; import org.tron.core.store.ContractStore; -import org.tron.core.vm.config.VMConfig; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result.code; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract.ABI; import org.tron.protos.contract.SmartContractOuterClass.ClearABIContract; - -import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; +import org.tron.protos.contract.SmartContractOuterClass.SmartContract.ABI; @Slf4j(topic = "actuator") public class ClearABIContractActuator extends AbstractActuator { @@ -57,17 +56,16 @@ public boolean execute(Object result) throws ContractExeException { @Override public boolean validate() throws ContractValidateException { - if (!VMConfig.allowTvmConstantinople()) { - throw new ContractValidateException( - "contract type error,unexpected type [ClearABIContract]"); - } - if (this.any == null) { throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); } if (chainBaseManager == null) { throw new ContractValidateException("No account store or contract store!"); } + if (chainBaseManager.getDynamicPropertiesStore().getAllowTvmConstantinople() == 0) { + throw new ContractValidateException( + "contract type error,unexpected type [ClearABIContract]"); + } AccountStore accountStore = chainBaseManager.getAccountStore(); ContractStore contractStore = chainBaseManager.getContractStore(); if (!this.any.is(ClearABIContract.class)) { diff --git a/actuator/src/main/java/org/tron/core/actuator/UpdateEnergyLimitContractActuator.java b/actuator/src/main/java/org/tron/core/actuator/UpdateEnergyLimitContractActuator.java index 369b936a527..f6b67e02891 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UpdateEnergyLimitContractActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UpdateEnergyLimitContractActuator.java @@ -6,10 +6,10 @@ import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; -import org.tron.common.utils.StorageUtils; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.ContractCapsule; +import org.tron.core.capsule.ReceiptCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; @@ -58,16 +58,16 @@ public boolean execute(Object object) throws ContractExeException { @Override public boolean validate() throws ContractValidateException { - if (!StorageUtils.getEnergyLimitHardFork()) { - throw new ContractValidateException( - "contract type error, unexpected type [UpdateEnergyLimitContract]"); - } if (this.any == null) { throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); } if (chainBaseManager == null) { throw new ContractValidateException(ActuatorConstant.STORE_NOT_EXIST); } + if (!ReceiptCapsule.checkForEnergyLimit(chainBaseManager.getDynamicPropertiesStore())) { + throw new ContractValidateException( + "contract type error, unexpected type [UpdateEnergyLimitContract]"); + } AccountStore accountStore = chainBaseManager.getAccountStore(); ContractStore contractStore = chainBaseManager.getContractStore(); if (!this.any.is(UpdateEnergyLimitContract.class)) { diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index fa75deafb3f..a9d11133866 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -85,7 +85,6 @@ import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.capsule.BytesCapsule; -import org.tron.core.capsule.ReceiptCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.TransactionInfoCapsule; import org.tron.core.capsule.TransactionRetCapsule; @@ -155,7 +154,6 @@ import org.tron.core.store.WitnessScheduleStore; import org.tron.core.store.WitnessStore; import org.tron.core.utils.TransactionRegister; -import org.tron.core.vm.config.VMConfig; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Permission; import org.tron.protos.Protocol.Transaction; @@ -537,9 +535,6 @@ public void init() { //initActuatorCreator ActuatorCreator.init(); TransactionRegister.registerActuator(); - //initEnergyLimitHardFork - VMConfig.initVmHardFork(ReceiptCapsule.checkForEnergyLimit( - chainBaseManager.getDynamicPropertiesStore())); long exitHeight = CommonParameter.getInstance().getShutdownBlockHeight(); long exitCount = CommonParameter.getInstance().getShutdownBlockCount(); From b9b39b7c091d35e4d4f7696e7e56f3a9b7408164 Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 3 Nov 2022 20:15:15 +0800 Subject: [PATCH 0407/1197] fix(test): some related unit tests --- .../org/tron/core/actuator/ClearABIContractActuatorTest.java | 3 +-- .../core/actuator/UpdateEnergyLimitContractActuatorTest.java | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java index a5341c22c3c..de6a426f1ef 100644 --- a/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java @@ -26,7 +26,6 @@ import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; -import org.tron.core.vm.config.VMConfig; import org.tron.protos.Protocol; import org.tron.protos.contract.AssetIssueContractOuterClass; import org.tron.protos.contract.SmartContractOuterClass.ClearABIContract; @@ -68,8 +67,8 @@ public class ClearABIContractActuatorTest { */ @BeforeClass public static void init() { - VMConfig.initAllowTvmConstantinople(1); dbManager = context.getBean(Manager.class); + dbManager.getDynamicPropertiesStore().saveAllowTvmConstantinople(1); } /** diff --git a/framework/src/test/java/org/tron/core/actuator/UpdateEnergyLimitContractActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UpdateEnergyLimitContractActuatorTest.java index 7dfcbee8824..9a662e15834 100644 --- a/framework/src/test/java/org/tron/core/actuator/UpdateEnergyLimitContractActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UpdateEnergyLimitContractActuatorTest.java @@ -30,7 +30,6 @@ import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.TronException; -import org.tron.core.vm.config.VMConfig; import org.tron.protos.Protocol; import org.tron.protos.contract.AssetIssueContractOuterClass; import org.tron.protos.contract.SmartContractOuterClass.SmartContract; @@ -78,7 +77,7 @@ public static void init() { Arrays.fill(stats, (byte) 1); dbManager.getDynamicPropertiesStore() .statsByVersion(ForkBlockVersionConsts.ENERGY_LIMIT, stats); - VMConfig.initVmHardFork(true); + CommonParameter.getInstance().setBlockNumForEnergyLimit(0); } /** @@ -93,7 +92,6 @@ public static void destroy() { } else { logger.info("Release resources failure."); } - CommonParameter.setENERGY_LIMIT_HARD_FORK(false); } /** From 344d149dbaca1574a513338b5a662bc7b90b5d3b Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Thu, 3 Nov 2022 14:20:34 +0800 Subject: [PATCH 0408/1197] fix(mechanism): fix deflation or expansion problems --- .../org/tron/core/utils/ProposalUtil.java | 2 +- .../org/tron/core/db/EnergyProcessor.java | 8 +++-- .../core/store/DynamicPropertiesStore.java | 35 +++++++++++++++++++ .../common/parameter/CommonParameter.java | 4 +++ .../src/main/java/org/tron/core/Constant.java | 1 + .../src/main/java/org/tron/core/Wallet.java | 4 +-- .../java/org/tron/core/config/args/Args.java | 12 +++++++ .../tron/core/consensus/ProposalService.java | 1 + .../org/tron/core/db/BandwidthProcessor.java | 3 ++ 9 files changed, 64 insertions(+), 6 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 8235daa9cdb..bc1cd18d47a 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -565,7 +565,7 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, throw new ContractValidateException( "Bad chain parameter id [ALLOW_NEW_REWARD_ALGO]"); } - if (dynamicPropertiesStore.useNewRewardAlgorithm()) { + if (dynamicPropertiesStore.allowNewRewardEnable()) { throw new ContractValidateException( "New reward algorithm has been valid."); } diff --git a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java index 4ebe6d603d9..0ce7487e23f 100644 --- a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java @@ -133,9 +133,11 @@ public long calculateGlobalEnergyLimit(AccountCapsule accountCapsule) { long energyWeight = frozeBalance / TRX_PRECISION; long totalEnergyLimit = dynamicPropertiesStore.getTotalEnergyCurrentLimit(); long totalEnergyWeight = dynamicPropertiesStore.getTotalEnergyWeight(); - - assert totalEnergyWeight > 0; - + if (dynamicPropertiesStore.allowNewRewardEnable() && totalEnergyWeight <= 0) { + return 0; + } else { + assert totalEnergyWeight > 0; + } return (long) (energyWeight * ((double) totalEnergyLimit / totalEnergyWeight)); } diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 9f4c9444cbe..f649aa08302 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -187,6 +187,7 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX = "ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX".getBytes(); + private static final byte[] ALLOW_NEW_REWARD = "ALLOW_NEW_REWARD".getBytes(); private static final byte[] MEMO_FEE = "MEMO_FEE".getBytes(); private static final byte[] MEMO_FEE_HISTORY = "MEMO_FEE_HISTORY".getBytes(); @@ -861,6 +862,16 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { } } + try { + this.getAllowNewRewardEnable(); + } catch (IllegalArgumentException e) { + this.saveAllowNewRewardEnable(CommonParameter.getInstance().getAllowNewRewardEnable()); + if (CommonParameter.getInstance().getAllowNewRewardEnable() == 1) { + this.put(NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE, + new BytesCapsule(ByteArray.fromLong(getCurrentCycleNumber()))); + } + } + try { this.getMemoFee(); } catch (IllegalArgumentException e) { @@ -2145,6 +2156,9 @@ public void updateNextMaintenanceTime(long blockTime) { public void addTotalNetWeight(long amount) { long totalNetWeight = getTotalNetWeight(); totalNetWeight += amount; + if (allowNewRewardEnable()) { + totalNetWeight = Math.max(0, totalNetWeight); + } saveTotalNetWeight(totalNetWeight); } @@ -2152,6 +2166,9 @@ public void addTotalNetWeight(long amount) { public void addTotalEnergyWeight(long amount) { long totalEnergyWeight = getTotalEnergyWeight(); totalEnergyWeight += amount; + if (allowNewRewardEnable()) { + totalEnergyWeight = Math.max(0, totalEnergyWeight); + } saveTotalEnergyWeight(totalEnergyWeight); } @@ -2159,6 +2176,9 @@ public void addTotalEnergyWeight(long amount) { public void addTotalTronPowerWeight(long amount) { long totalWeight = getTotalTronPowerWeight(); totalWeight += amount; + if (allowNewRewardEnable()) { + totalWeight = Math.max(0, totalWeight); + } saveTotalTronPowerWeight(totalWeight); } @@ -2561,6 +2581,21 @@ public void saveMemoFeeHistory(String value) { this.put(MEMO_FEE_HISTORY, new BytesCapsule(ByteArray.fromString(value))); } + public long getAllowNewRewardEnable() { + return Optional.ofNullable(getUnchecked(ALLOW_NEW_REWARD)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow(() -> new IllegalArgumentException("not found AllowNewRewardEnable")); + } + + public void saveAllowNewRewardEnable(long newReward) { + this.put(ALLOW_NEW_REWARD, new BytesCapsule(ByteArray.fromLong(newReward))); + } + + public boolean allowNewRewardEnable() { + return getAllowNewRewardEnable() == 1; + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 0331628d53c..accf4766ea4 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -561,6 +561,10 @@ public class CommonParameter { @Setter public long allowNewRewardAlgorithm; + @Getter + @Setter + public long allowNewRewardEnable = 0L; + @Getter @Setter public long memoFee = 0L; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index aa287b1d885..83430e9254c 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -307,6 +307,7 @@ public class Constant { public static final String ALLOW_ACCOUNT_ASSET_OPTIMIZATION = "committee.allowAccountAssetOptimization"; public static final String ALLOW_ASSET_OPTIMIZATION = "committee.allowAssetOptimization"; + public static final String ALLOW_NEW_REWARD_ENABLE = "committee.allowNewRewardEnable"; public static final String MEMO_FEE = "committee.memoFee"; public static final String LOCAL_HOST = "127.0.0.1"; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 5f77a651ea0..6cb7e9b9d01 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1099,8 +1099,8 @@ public Protocol.ChainParameters getChainParameters() { .build()); builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() - .setKey("getNewRewardAlgorithm") - .setValue(dbManager.getDynamicPropertiesStore().useNewRewardAlgorithm() ? 1 : 0) + .setKey("getAllowNewRewardEnable") + .setValue(dbManager.getDynamicPropertiesStore().getAllowNewRewardEnable()) .build()); builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 26a3250a369..1625a4c684d 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -215,6 +215,8 @@ public static void clearParam() { PARAMETER.shutdownBlockCount = -1; PARAMETER.blockCacheTimeout = 60; PARAMETER.allowNewRewardAlgorithm = 0; + PARAMETER.allowNewRewardEnable = 0; + PARAMETER.memoFee = 0; } /** @@ -1034,6 +1036,16 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.blockCacheTimeout = config.getLong(Constant.BLOCK_CACHE_TIMEOUT); } + if (config.hasPath(Constant.ALLOW_NEW_REWARD_ENABLE)) { + PARAMETER.allowNewRewardEnable = config.getLong(Constant.ALLOW_NEW_REWARD_ENABLE); + if (PARAMETER.allowNewRewardEnable > 1) { + PARAMETER.allowNewRewardEnable = 1; + } + if (PARAMETER.allowNewRewardEnable < 0) { + PARAMETER.allowNewRewardEnable = 0; + } + } + if (config.hasPath(Constant.MEMO_FEE)) { PARAMETER.memoFee = config.getLong(Constant.MEMO_FEE); if (PARAMETER.memoFee > 1_000_000_000) { diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 0d2ed945f42..99b4e569d4e 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -286,6 +286,7 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) } case ALLOW_NEW_REWARD_ALGO: { manager.getDynamicPropertiesStore().saveNewRewardAlgorithmEffectiveCycle(); + manager.getDynamicPropertiesStore().saveAllowNewRewardEnable(entry.getValue()); break; } case MEMO_FEE: { diff --git a/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java b/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java index 64405a69f69..9f4a9a1e5ed 100644 --- a/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -390,6 +390,9 @@ public long calculateGlobalNetLimit(AccountCapsule accountCapsule) { long netWeight = frozeBalance / TRX_PRECISION; long totalNetLimit = chainBaseManager.getDynamicPropertiesStore().getTotalNetLimit(); long totalNetWeight = chainBaseManager.getDynamicPropertiesStore().getTotalNetWeight(); + if (dynamicPropertiesStore.allowNewRewardEnable() && totalNetWeight <= 0) { + return 0; + } if (totalNetWeight == 0) { return 0; } From aa08143db52f62530cb0235bc99330ce081f1fb8 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Mon, 7 Nov 2022 13:10:27 +0800 Subject: [PATCH 0409/1197] fix(mechanism): optimize deflation problems --- .../core/actuator/FreezeBalanceActuator.java | 65 +++++++++++++------ .../org/tron/core/utils/ProposalUtil.java | 2 +- .../capsule/DelegatedResourceCapsule.java | 9 +++ 3 files changed, 55 insertions(+), 21 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java index f026a8769e6..d3f7c7f2922 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java @@ -3,6 +3,10 @@ import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; +import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; @@ -72,44 +76,48 @@ public boolean execute(Object result) throws ContractExeException { byte[] ownerAddress = freezeBalanceContract.getOwnerAddress().toByteArray(); byte[] receiverAddress = freezeBalanceContract.getReceiverAddress().toByteArray(); + long increment; switch (freezeBalanceContract.getResource()) { case BANDWIDTH: if (!ArrayUtils.isEmpty(receiverAddress) && dynamicStore.supportDR()) { - delegateResource(ownerAddress, receiverAddress, true, - frozenBalance, expireTime); + increment = delegateResource(ownerAddress, receiverAddress, true, + frozenBalance, expireTime); accountCapsule.addDelegatedFrozenBalanceForBandwidth(frozenBalance); } else { + long oldNetWeight = accountCapsule.getFrozenBalance() / TRX_PRECISION; long newFrozenBalanceForBandwidth = frozenBalance + accountCapsule.getFrozenBalance(); accountCapsule.setFrozenForBandwidth(newFrozenBalanceForBandwidth, expireTime); + long newNetWeight = accountCapsule.getFrozenBalance() / TRX_PRECISION; + increment = newNetWeight - oldNetWeight; } - dynamicStore - .addTotalNetWeight(frozenBalance / TRX_PRECISION); + addTotalWeight(BANDWIDTH, dynamicStore, frozenBalance, increment); break; case ENERGY: if (!ArrayUtils.isEmpty(receiverAddress) && dynamicStore.supportDR()) { - delegateResource(ownerAddress, receiverAddress, false, - frozenBalance, expireTime); + increment = delegateResource(ownerAddress, receiverAddress, false, + frozenBalance, expireTime); accountCapsule.addDelegatedFrozenBalanceForEnergy(frozenBalance); } else { + long oldEnergyWeight = accountCapsule.getEnergyFrozenBalance() / TRX_PRECISION; long newFrozenBalanceForEnergy = - frozenBalance + accountCapsule.getAccountResource() - .getFrozenBalanceForEnergy() - .getFrozenBalance(); + frozenBalance + accountCapsule.getEnergyFrozenBalance(); accountCapsule.setFrozenForEnergy(newFrozenBalanceForEnergy, expireTime); + long newEnergyWeight = accountCapsule.getEnergyFrozenBalance() / TRX_PRECISION; + increment = newEnergyWeight - oldEnergyWeight; } - dynamicStore - .addTotalEnergyWeight(frozenBalance / TRX_PRECISION); + addTotalWeight(ENERGY, dynamicStore, frozenBalance, increment); break; case TRON_POWER: + long oldTPWeight = accountCapsule.getTronPowerFrozenBalance() / TRX_PRECISION; long newFrozenBalanceForTronPower = frozenBalance + accountCapsule.getTronPowerFrozenBalance(); accountCapsule.setFrozenForTronPower(newFrozenBalanceForTronPower, expireTime); - - dynamicStore - .addTotalTronPowerWeight(frozenBalance / TRX_PRECISION); + long newTPWeight = accountCapsule.getTronPowerFrozenBalance() / TRX_PRECISION; + increment = newTPWeight - oldTPWeight; + addTotalWeight(TRON_POWER, dynamicStore, frozenBalance, increment); break; default: logger.debug("Resource Code Error."); @@ -123,6 +131,23 @@ public boolean execute(Object result) throws ContractExeException { return true; } + private void addTotalWeight(ResourceCode resourceCode, DynamicPropertiesStore dynamicStore, + long frozenBalance, long increment) { + long weight = dynamicStore.allowNewRewardEnable() ? increment : frozenBalance / TRX_PRECISION; + switch (resourceCode) { + case BANDWIDTH: + dynamicStore.addTotalNetWeight(weight); + break; + case ENERGY: + dynamicStore.addTotalEnergyWeight(weight); + break; + case TRON_POWER: + dynamicStore.addTotalTronPowerWeight(weight); + break; + default: + logger.debug("Resource Code Error."); + } + } @Override public boolean validate() throws ContractValidateException { @@ -175,11 +200,6 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("frozenBalance must be less than accountBalance"); } -// long maxFrozenNumber = dbManager.getDynamicPropertiesStore().getMaxFrozenNumber(); -// if (accountCapsule.getFrozenCount() >= maxFrozenNumber) { -// throw new ContractValidateException("max frozen number is: " + maxFrozenNumber); -// } - long frozenDuration = freezeBalanceContract.getFrozenDuration(); long minFrozenTime = dynamicStore.getMinFrozenTime(); long maxFrozenTime = dynamicStore.getMaxFrozenTime(); @@ -262,7 +282,7 @@ public long calcFee() { return 0; } - private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boolean isBandwidth, + private long delegateResource(byte[] ownerAddress, byte[] receiverAddress, boolean isBandwidth, long balance, long expireTime) { AccountStore accountStore = chainBaseManager.getAccountStore(); DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore(); @@ -272,13 +292,16 @@ private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boole //modify DelegatedResourceStore DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore .get(key); + long oldWeight; if (delegatedResourceCapsule != null) { + oldWeight = delegatedResourceCapsule.getFrozenBalance(isBandwidth) / TRX_PRECISION; if (isBandwidth) { delegatedResourceCapsule.addFrozenBalanceForBandwidth(balance, expireTime); } else { delegatedResourceCapsule.addFrozenBalanceForEnergy(balance, expireTime); } } else { + oldWeight = 0; delegatedResourceCapsule = new DelegatedResourceCapsule( ByteString.copyFrom(ownerAddress), ByteString.copyFrom(receiverAddress)); @@ -289,6 +312,7 @@ private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boole } } + long newWeight = delegatedResourceCapsule.getFrozenBalance(isBandwidth) / TRX_PRECISION; delegatedResourceStore.put(key, delegatedResourceCapsule); //modify DelegatedResourceAccountIndexStore @@ -332,6 +356,7 @@ private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boole } accountStore.put(receiverCapsule.createDbKey(), receiverCapsule); + return newWeight - oldWeight; } } diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index bc1cd18d47a..dacd713bf6d 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -651,7 +651,7 @@ public enum ProposalType { // current value, value range ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX(65), // 0, 1 ALLOW_ASSET_OPTIMIZATION(66), // 0, 1 ALLOW_NEW_REWARD_ALGO(67), // 0, 1 - MEMO_FEE(68); // 0, [1, 1000_000_000] + MEMO_FEE(68); // 0, [0, 1000_000_000] private long code; diff --git a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java index 0eb6dc8ec09..c24c2e72edf 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java @@ -67,6 +67,15 @@ public long getFrozenBalanceForBandwidth() { return this.delegatedResource.getFrozenBalanceForBandwidth(); } + public long getFrozenBalance(boolean isBandwidth) { + if (isBandwidth) { + return getFrozenBalanceForBandwidth(); + } else { + return getFrozenBalanceForEnergy(); + } + + } + public void setFrozenBalanceForBandwidth(long Bandwidth, long expireTime) { this.delegatedResource = this.delegatedResource.toBuilder() .setFrozenBalanceForBandwidth(Bandwidth) From fb6ee30bfa17fb4ccac29917a3b101b1e8d1dc8b Mon Sep 17 00:00:00 2001 From: chaozhu Date: Tue, 8 Nov 2022 11:13:57 +0800 Subject: [PATCH 0410/1197] feat(freezeV2): new stake, add 1 interfaces --- .../src/main/java/org/tron/core/Wallet.java | 39 +++++++++++- .../org/tron/core/services/RpcApiService.java | 29 ++++++++- .../services/http/FullNodeHttpApiService.java | 4 ++ .../GetAvailableUnfreezeCountServlet.java | 63 +++++++++++++++++++ .../GetCanWithdrawUnfreezeAmountServlet.java | 6 +- .../http/HttpSelfFormatFieldName.java | 1 + .../solidity/SolidityNodeHttpApiService.java | 5 ++ ...ailableUnfreezeCountOnSolidityServlet.java | 29 +++++++++ .../solidity/HttpApiOnSolidityService.java | 5 ++ protocol/src/main/protos/api/api.proto | 16 +++++ 10 files changed, 191 insertions(+), 6 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/services/http/GetAvailableUnfreezeCountServlet.java create mode 100644 framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetAvailableUnfreezeCountOnSolidityServlet.java diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 064f02443af..ba8e8e9a8be 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -123,6 +123,7 @@ import org.tron.consensus.ConsensusDelegate; import org.tron.core.actuator.Actuator; import org.tron.core.actuator.ActuatorFactory; +import org.tron.core.actuator.UnfreezeBalanceV2Actuator; import org.tron.core.actuator.VMActuator; import org.tron.core.capsule.AbiCapsule; import org.tron.core.capsule.AccountCapsule; @@ -766,7 +767,7 @@ public DelegatedResourceList getDelegatedResourceV2( } public GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage getCanWithdrawUnfreezeAmount( - ByteString ownerAddress) { + ByteString ownerAddress, long timestamp) { GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage.Builder builder = GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage.newBuilder(); long canWithdrawUnfreezeAmount; @@ -777,14 +778,19 @@ public GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage getCanWithdrawUnfreezeAm if (accountCapsule == null) { return builder.build(); } - long now = dynamicStore.getLatestBlockHeaderTimestamp(); + + if (timestamp == 0) { + timestamp = dynamicStore.getLatestBlockHeaderTimestamp(); + } List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); + long finalTimestamp = timestamp; + canWithdrawUnfreezeAmount = unfrozenV2List .stream() .filter(unfrozenV2 -> (unfrozenV2.getUnfreezeAmount() > 0 - && unfrozenV2.getUnfreezeExpireTime() <= now)) + && unfrozenV2.getUnfreezeExpireTime() <= finalTimestamp)) .mapToLong(Account.UnFreezeV2::getUnfreezeAmount) .sum(); @@ -793,6 +799,33 @@ public GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage getCanWithdrawUnfreezeAm return builder.build(); } + public GrpcAPI.GetAvailableUnfreezeCountResponseMessage getAvailableUnfreezeCount( + ByteString ownerAddress) { + long getAvailableUnfreezeCount; + GrpcAPI.GetAvailableUnfreezeCountResponseMessage.Builder builder = + GrpcAPI.GetAvailableUnfreezeCountResponseMessage.newBuilder(); + + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + AccountCapsule accountCapsule = accountStore.get(ownerAddress.toByteArray()); + if (accountCapsule == null) { + return builder.build(); + } + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + + List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); + long getUsedUnfreezeCount = unfrozenV2List + .stream() + .filter(unfrozenV2 -> + (unfrozenV2.getUnfreezeAmount() > 0 + && unfrozenV2.getUnfreezeExpireTime() > now)) + .count(); + getAvailableUnfreezeCount = UnfreezeBalanceV2Actuator.getUNFREEZE_MAX_TIMES() + - getUsedUnfreezeCount; + builder.setCount(getAvailableUnfreezeCount); + return builder.build(); + } + public DelegatedResourceAccountIndex getDelegatedResourceAccountIndex(ByteString address) { DelegatedResourceAccountIndexCapsule accountIndexCapsule = chainBaseManager.getDelegatedResourceAccountIndexStore().get(address.toByteArray()); diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index d8976d36547..40f62440ebb 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -638,13 +638,25 @@ public void getDelegatedResourceAccountIndexV2(BytesMessage request, responseObserver.onCompleted(); } + @Override + public void getAvailableUnfreezeCount(GrpcAPI.GetAvailableUnfreezeCountRequestMessage request, + StreamObserver responseObserver) { + try { + responseObserver.onNext(wallet.getAvailableUnfreezeCount( + request.getOwnerAddress())); + } catch (Exception e) { + responseObserver.onError(getRunTimeException(e)); + } + responseObserver.onCompleted(); + } + @Override public void getCanWithdrawUnfreezeAmount(CanWithdrawUnfreezeAmountRequestMessage request, StreamObserver responseObserver) { try { responseObserver .onNext(wallet.getCanWithdrawUnfreezeAmount( - request.getOwnerAddress()) + request.getOwnerAddress(), request.getTimestamp()) ); } catch (Exception e) { responseObserver.onError(getRunTimeException(e)); @@ -2097,13 +2109,26 @@ public void getDelegatedResourceAccountIndexV2(BytesMessage request, responseObserver.onCompleted(); } + @Override + public void getAvailableUnfreezeCount(GrpcAPI.GetAvailableUnfreezeCountRequestMessage request, + StreamObserver responseObserver) { + try { + responseObserver.onNext(wallet.getAvailableUnfreezeCount( + request.getOwnerAddress())); + } catch (Exception e) { + responseObserver.onError(getRunTimeException(e)); + } + + responseObserver.onCompleted(); + } + @Override public void getCanWithdrawUnfreezeAmount(CanWithdrawUnfreezeAmountRequestMessage request, StreamObserver responseObserver) { try { responseObserver .onNext(wallet.getCanWithdrawUnfreezeAmount( - request.getOwnerAddress() + request.getOwnerAddress(), request.getTimestamp() )); } catch (Exception e) { responseObserver.onError(getRunTimeException(e)); diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index b2ebf1af7ad..f9c804629ac 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -188,6 +188,8 @@ public class FullNodeHttpApiService implements Service { @Autowired private GetDelegatedResourceV2Servlet getDelegatedResourceV2Servlet; @Autowired + private GetAvailableUnfreezeCountServlet getAvailableUnfreezeCountServlet; + @Autowired private GetCanWithdrawUnfreezeAmountServlet getCanWithdrawUnfreezeAmountServlet; @Autowired private SetAccountIdServlet setAccountServlet; @@ -470,6 +472,8 @@ public void start() { "/wallet/getdelegatedresource"); context.addServlet(new ServletHolder(getDelegatedResourceV2Servlet), "/wallet/getdelegatedresourcev2"); + context.addServlet(new ServletHolder(getAvailableUnfreezeCountServlet), + "/wallet/getavailableunfreezecount"); context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountServlet), "/wallet/getcanwithdrawunfreezeamount"); context.addServlet( diff --git a/framework/src/main/java/org/tron/core/services/http/GetAvailableUnfreezeCountServlet.java b/framework/src/main/java/org/tron/core/services/http/GetAvailableUnfreezeCountServlet.java new file mode 100644 index 00000000000..28fec9f3ee3 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/GetAvailableUnfreezeCountServlet.java @@ -0,0 +1,63 @@ +package org.tron.core.services.http; + +import com.google.protobuf.ByteString; +import java.io.IOException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.api.GrpcAPI; +import org.tron.common.utils.ByteArray; +import org.tron.core.Wallet; + +@Component +@Slf4j(topic = "API") +public class GetAvailableUnfreezeCountServlet extends RateLimiterServlet { + + @Autowired + private Wallet wallet; + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + try { + boolean visible = Util.getVisible(request); + String ownerAddress = request.getParameter("ownerAddress"); + if (visible) { + ownerAddress = Util.getHexAddress(ownerAddress); + } + fillResponse(visible, + ByteString.copyFrom(ByteArray.fromHexString(ownerAddress)), + response); + } catch (Exception e) { + Util.processError(e, response); + } + } + + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + PostParams params = PostParams.getPostParams(request); + GrpcAPI.GetAvailableUnfreezeCountRequestMessage.Builder build = + GrpcAPI.GetAvailableUnfreezeCountRequestMessage.newBuilder(); + JsonFormat.merge(params.getParams(), build, params.isVisible()); + fillResponse(params.isVisible(), + build.getOwnerAddress(), + response); + } catch (Exception e) { + Util.processError(e, response); + } + } + + private void fillResponse(boolean visible, + ByteString ownerAddress, + HttpServletResponse response) throws IOException { + GrpcAPI.GetAvailableUnfreezeCountResponseMessage reply = + wallet.getAvailableUnfreezeCount(ownerAddress); + if (reply != null) { + response.getWriter().println(JsonFormat.printToString(reply, visible)); + } else { + response.getWriter().println("{}"); + } + } +} diff --git a/framework/src/main/java/org/tron/core/services/http/GetCanWithdrawUnfreezeAmountServlet.java b/framework/src/main/java/org/tron/core/services/http/GetCanWithdrawUnfreezeAmountServlet.java index fd1547d3931..4c1bbaf4f99 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetCanWithdrawUnfreezeAmountServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetCanWithdrawUnfreezeAmountServlet.java @@ -22,11 +22,13 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { boolean visible = Util.getVisible(request); String ownerAddress = request.getParameter("owner_address"); + long timestamp = Long.valueOf(request.getParameter("timestamp")); if (visible) { ownerAddress = Util.getHexAddress(ownerAddress); } fillResponse(visible, ByteString.copyFrom(ByteArray.fromHexString(ownerAddress)), + timestamp, response); } catch (Exception e) { Util.processError(e, response); @@ -41,6 +43,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) JsonFormat.merge(params.getParams(), build, params.isVisible()); fillResponse(params.isVisible(), build.getOwnerAddress(), + build.getTimestamp(), response); } catch (Exception e) { Util.processError(e, response); @@ -49,9 +52,10 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) private void fillResponse(boolean visible, ByteString ownerAddress, + long timestamp, HttpServletResponse response) throws IOException { GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage reply = - wallet.getCanWithdrawUnfreezeAmount(ownerAddress); + wallet.getCanWithdrawUnfreezeAmount(ownerAddress, timestamp); if (reply != null) { response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { diff --git a/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java b/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java index 7e320806de7..eb776a7e1c0 100644 --- a/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java +++ b/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java @@ -154,6 +154,7 @@ public class HttpSelfFormatFieldName { //UnDelegateResourceContract AddressFieldNameMap.put("protocol.UnDelegateResourceContract.owner_address", 1); AddressFieldNameMap.put("protocol.UnDelegateResourceContract.receiver_address", 1); + AddressFieldNameMap.put("protocol.GetAvailableUnfreezeCountRequestMessage.owner_address", 1); AddressFieldNameMap.put("protocol.CanWithdrawUnfreezeAmountRequestMessage.owner_address", 1); //***** Tron.proto ***** diff --git a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java index de7d8491018..0830568ad54 100644 --- a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java @@ -23,6 +23,7 @@ import org.tron.core.services.http.GetAssetIssueByNameServlet; import org.tron.core.services.http.GetAssetIssueListByNameServlet; import org.tron.core.services.http.GetAssetIssueListServlet; +import org.tron.core.services.http.GetAvailableUnfreezeCountServlet; import org.tron.core.services.http.GetBlockByIdServlet; import org.tron.core.services.http.GetBlockByLatestNumServlet; import org.tron.core.services.http.GetBlockByLimitNextServlet; @@ -85,6 +86,8 @@ public class SolidityNodeHttpApiService implements Service { @Autowired private GetDelegatedResourceV2Servlet getDelegatedResourceV2Servlet; @Autowired + private GetAvailableUnfreezeCountServlet getAvailableUnfreezeCountServlet; + @Autowired private GetCanWithdrawUnfreezeAmountServlet getCanWithdrawUnfreezeAmountServlet; @Autowired private GetDelegatedResourceAccountIndexServlet getDelegatedResourceAccountIndexServlet; @@ -212,6 +215,8 @@ public void start() { "/walletsolidity/getdelegatedresource"); context.addServlet(new ServletHolder(getDelegatedResourceV2Servlet), "/walletsolidity/getdelegatedresourcev2"); + context.addServlet(new ServletHolder(getAvailableUnfreezeCountServlet), + "/walletsolidity/getavailableunfreezecount"); context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountServlet), "/walletsolidity/getcanwithdrawunfreezeamount"); context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexServlet), diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetAvailableUnfreezeCountOnSolidityServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetAvailableUnfreezeCountOnSolidityServlet.java new file mode 100644 index 00000000000..218164fffb0 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetAvailableUnfreezeCountOnSolidityServlet.java @@ -0,0 +1,29 @@ +package org.tron.core.services.interfaceOnSolidity.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; +import org.tron.core.services.http.GetAvailableUnfreezeCountServlet; +import org.tron.core.services.interfaceOnSolidity.WalletOnSolidity; + +@Component +@Slf4j(topic = "API") +public class GetAvailableUnfreezeCountOnSolidityServlet extends GetAvailableUnfreezeCountServlet { + + @Autowired + private Wallet wallet; + + @Autowired + private WalletOnSolidity walletOnSolidity; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java index fc1f0c592dd..89da15b8555 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java @@ -22,6 +22,7 @@ import org.tron.core.services.interfaceOnSolidity.http.GetAssetIssueByNameOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetAssetIssueListByNameOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetAssetIssueListOnSolidityServlet; +import org.tron.core.services.interfaceOnSolidity.http.GetAvailableUnfreezeCountOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetBlockByIdOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetBlockByLatestNumOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetBlockByLimitNextOnSolidityServlet; @@ -93,6 +94,8 @@ public class HttpApiOnSolidityService implements Service { @Autowired private GetDelegatedResourceV2OnSolidityServlet getDelegatedResourceV2OnSolidityServlet; @Autowired + private GetAvailableUnfreezeCountOnSolidityServlet getAvailableUnfreezeCountOnSolidityServlet; + @Autowired private GetCanWithdrawUnfreezeAmountOnSolidityServlet getCanWithdrawUnfreezeAmountOnSolidityServlet; @Autowired @@ -212,6 +215,8 @@ public void start() { "/walletsolidity/getdelegatedresource"); context.addServlet(new ServletHolder(getDelegatedResourceV2OnSolidityServlet), "/walletsolidity/getdelegatedresourcev2"); + context.addServlet(new ServletHolder(getAvailableUnfreezeCountOnSolidityServlet), + "/walletsolidity/getavailableunfreezecount"); context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountOnSolidityServlet), "/walletsolidity/getcanwithdrawunfreezeamount"); context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexOnSolidityServlet), diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 4d75f0e9326..d94da7cad80 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -506,6 +506,10 @@ service Wallet { rpc GetDelegatedResourceAccountIndexV2 (BytesMessage) returns (DelegatedResourceAccountIndex) { }; + rpc GetAvailableUnfreezeCount (GetAvailableUnfreezeCountRequestMessage) + returns (GetAvailableUnfreezeCountResponseMessage) { + }; + rpc GetCanWithdrawUnfreezeAmount (CanWithdrawUnfreezeAmountRequestMessage) returns (CanWithdrawUnfreezeAmountResponseMessage) { } @@ -920,6 +924,10 @@ service WalletSolidity { rpc GetDelegatedResourceAccountIndexV2 (BytesMessage) returns (DelegatedResourceAccountIndex) { }; + rpc GetAvailableUnfreezeCount (GetAvailableUnfreezeCountRequestMessage) + returns (GetAvailableUnfreezeCountResponseMessage) { + }; + rpc GetCanWithdrawUnfreezeAmount (CanWithdrawUnfreezeAmountRequestMessage) returns (CanWithdrawUnfreezeAmountResponseMessage) { } @@ -1138,8 +1146,16 @@ message DelegatedResourceList { repeated DelegatedResource delegatedResource = 1; } +message GetAvailableUnfreezeCountRequestMessage { + bytes owner_address = 1; +} +message GetAvailableUnfreezeCountResponseMessage { + int64 count = 1; +} + message CanWithdrawUnfreezeAmountRequestMessage { bytes owner_address = 1; + int64 timestamp = 2; } message CanWithdrawUnfreezeAmountResponseMessage { int64 amount = 1; From 3033ed304cbc3a64649d24713b0c565a5c977dc7 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Tue, 8 Nov 2022 15:12:25 +0800 Subject: [PATCH 0411/1197] fix(mechanism): optimize freezing precision query --- .../core/actuator/FreezeBalanceActuator.java | 11 +++++---- .../actuator/UnfreezeBalanceActuator.java | 23 +++++++++++++++---- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java index d3f7c7f2922..91dcc1a6edd 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java @@ -292,16 +292,13 @@ private long delegateResource(byte[] ownerAddress, byte[] receiverAddress, boole //modify DelegatedResourceStore DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore .get(key); - long oldWeight; if (delegatedResourceCapsule != null) { - oldWeight = delegatedResourceCapsule.getFrozenBalance(isBandwidth) / TRX_PRECISION; if (isBandwidth) { delegatedResourceCapsule.addFrozenBalanceForBandwidth(balance, expireTime); } else { delegatedResourceCapsule.addFrozenBalanceForEnergy(balance, expireTime); } } else { - oldWeight = 0; delegatedResourceCapsule = new DelegatedResourceCapsule( ByteString.copyFrom(ownerAddress), ByteString.copyFrom(receiverAddress)); @@ -312,7 +309,6 @@ private long delegateResource(byte[] ownerAddress, byte[] receiverAddress, boole } } - long newWeight = delegatedResourceCapsule.getFrozenBalance(isBandwidth) / TRX_PRECISION; delegatedResourceStore.put(key, delegatedResourceCapsule); //modify DelegatedResourceAccountIndexStore @@ -349,12 +345,17 @@ private long delegateResource(byte[] ownerAddress, byte[] receiverAddress, boole //modify AccountStore AccountCapsule receiverCapsule = accountStore.get(receiverAddress); + long oldWeight; + long newWeight; if (isBandwidth) { + oldWeight = receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() / TRX_PRECISION; receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(balance); + newWeight = receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() / TRX_PRECISION; } else { + oldWeight = receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() / TRX_PRECISION; receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(balance); + newWeight = receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() / TRX_PRECISION; } - accountStore.put(receiverCapsule.createDbKey(), receiverCapsule); return newWeight - oldWeight; } diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java index 93dcd61e044..1f4426fb7ed 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java @@ -83,6 +83,7 @@ public boolean execute(Object result) throws ContractExeException { byte[] receiverAddress = unfreezeBalanceContract.getReceiverAddress().toByteArray(); //If the receiver is not included in the contract, unfreeze frozen balance for this account. //otherwise,unfreeze delegated frozen balance provided this account. + long decrease = 0; if (!ArrayUtils.isEmpty(receiverAddress) && dynamicStore.supportDR()) { byte[] key = DelegatedResourceCapsule .createDbKey(unfreezeBalanceContract.getOwnerAddress().toByteArray(), @@ -107,25 +108,38 @@ public boolean execute(Object result) throws ContractExeException { } AccountCapsule receiverCapsule = accountStore.get(receiverAddress); + if (dynamicStore.getAllowTvmConstantinople() == 0 || (receiverCapsule != null && receiverCapsule.getType() != AccountType.Contract)) { switch (unfreezeBalanceContract.getResource()) { case BANDWIDTH: + long oldNetWeight = receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() / + TRX_PRECISION; if (dynamicStore.getAllowTvmSolidity059() == 1 && receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() < unfreezeBalance) { + oldNetWeight = unfreezeBalance / TRX_PRECISION; receiverCapsule.setAcquiredDelegatedFrozenBalanceForBandwidth(0); } else { receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(-unfreezeBalance); } + long newNetWeight = receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() / + TRX_PRECISION; + decrease = newNetWeight - oldNetWeight; break; case ENERGY: + long oldEnergyWeight = receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() / + TRX_PRECISION; if (dynamicStore.getAllowTvmSolidity059() == 1 && receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() < unfreezeBalance) { + oldEnergyWeight = unfreezeBalance / TRX_PRECISION; receiverCapsule.setAcquiredDelegatedFrozenBalanceForEnergy(0); } else { receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(-unfreezeBalance); } + long newEnergyWeight = receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() / + TRX_PRECISION; + decrease = newEnergyWeight - oldEnergyWeight; break; default: //this should never happen @@ -213,19 +227,20 @@ public boolean execute(Object result) throws ContractExeException { } } - + + long weight = dynamicStore.allowNewRewardEnable() ? decrease : -unfreezeBalance / TRX_PRECISION; switch (unfreezeBalanceContract.getResource()) { case BANDWIDTH: dynamicStore - .addTotalNetWeight(-unfreezeBalance / TRX_PRECISION); + .addTotalNetWeight(weight); break; case ENERGY: dynamicStore - .addTotalEnergyWeight(-unfreezeBalance / TRX_PRECISION); + .addTotalEnergyWeight(weight); break; case TRON_POWER: dynamicStore - .addTotalTronPowerWeight(-unfreezeBalance / TRX_PRECISION); + .addTotalTronPowerWeight(weight); break; default: //this should never happen From d63d9e1f4837c957038c55661455f129c7174688 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Thu, 10 Nov 2022 12:53:19 +0800 Subject: [PATCH 0412/1197] fix(mechanism): optimize total weight when unfreeze owner --- .../actuator/UnfreezeBalanceActuator.java | 15 +++- .../actuator/UnfreezeBalanceActuatorTest.java | 90 +++++++++++++++++++ 2 files changed, 102 insertions(+), 3 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java index 1f4426fb7ed..e384dbd865c 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java @@ -108,7 +108,7 @@ public boolean execute(Object result) throws ContractExeException { } AccountCapsule receiverCapsule = accountStore.get(receiverAddress); - + if (dynamicStore.getAllowTvmConstantinople() == 0 || (receiverCapsule != null && receiverCapsule.getType() != AccountType.Contract)) { switch (unfreezeBalanceContract.getResource()) { @@ -146,6 +146,8 @@ public boolean execute(Object result) throws ContractExeException { break; } accountStore.put(receiverCapsule.createDbKey(), receiverCapsule); + } else { + decrease = -unfreezeBalance / TRX_PRECISION; } accountCapsule.setBalance(oldBalance + unfreezeBalance); @@ -187,7 +189,7 @@ public boolean execute(Object result) throws ContractExeException { } else { switch (unfreezeBalanceContract.getResource()) { case BANDWIDTH: - + long oldNetWeight = accountCapsule.getFrozenBalance() / TRX_PRECISION; List frozenList = Lists.newArrayList(); frozenList.addAll(accountCapsule.getFrozenList()); Iterator iterator = frozenList.iterator(); @@ -203,9 +205,11 @@ public boolean execute(Object result) throws ContractExeException { accountCapsule.setInstance(accountCapsule.getInstance().toBuilder() .setBalance(oldBalance + unfreezeBalance) .clearFrozen().addAllFrozen(frozenList).build()); - + long newNetWeight = accountCapsule.getFrozenBalance() / TRX_PRECISION; + decrease = newNetWeight - oldNetWeight; break; case ENERGY: + long oldEnergyWeight = accountCapsule.getEnergyFrozenBalance() / TRX_PRECISION; unfreezeBalance = accountCapsule.getAccountResource().getFrozenBalanceForEnergy() .getFrozenBalance(); @@ -214,12 +218,17 @@ public boolean execute(Object result) throws ContractExeException { accountCapsule.setInstance(accountCapsule.getInstance().toBuilder() .setBalance(oldBalance + unfreezeBalance) .setAccountResource(newAccountResource).build()); + long newEnergyWeight = accountCapsule.getEnergyFrozenBalance() / TRX_PRECISION; + decrease = newEnergyWeight - oldEnergyWeight; break; case TRON_POWER: + long oldTPWeight = accountCapsule.getTronPowerFrozenBalance() / TRX_PRECISION; unfreezeBalance = accountCapsule.getTronPowerFrozenBalance(); accountCapsule.setInstance(accountCapsule.getInstance().toBuilder() .setBalance(oldBalance + unfreezeBalance) .clearTronPower().build()); + long newTPWeight = accountCapsule.getTronPowerFrozenBalance() / TRX_PRECISION; + decrease = newTPWeight - oldTPWeight; break; default: //this should never happen diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java index 9dd1b026d08..d5238c838fb 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java @@ -140,6 +140,7 @@ private Any getContract(String ownerAddress, ResourceCode resourceCode) { @Test public void testUnfreezeBalanceForBandwidth() { long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveAllowNewRewardEnable(0); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); AccountCapsule accountCapsule = dbManager.getAccountStore() @@ -178,10 +179,98 @@ public void testUnfreezeBalanceForBandwidth() { } } + @Test + public void testUnfreezeSelfAndOthersForBandwidth() { + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + dbManager.getDynamicPropertiesStore().saveAllowNewRewardEnable(1); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule owner = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + owner.setDelegatedFrozenBalanceForBandwidth(150_0000L); + owner.setFrozen(150_0000L, now); + dbManager.getDynamicPropertiesStore().saveTotalNetWeight(2L); + long beforeWeight = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); + Assert.assertEquals(2, beforeWeight); + + AccountCapsule receiver = dbManager.getAccountStore() + .get(ByteArray.fromHexString(RECEIVER_ADDRESS)); + receiver.setAcquiredDelegatedFrozenBalanceForBandwidth(150_0000L); + + dbManager.getAccountStore().put(owner.createDbKey(), owner); + dbManager.getAccountStore().put(receiver.createDbKey(), receiver); + + //init DelegatedResourceCapsule + DelegatedResourceCapsule delegatedResourceCapsule = new DelegatedResourceCapsule( + owner.getAddress(), receiver.getAddress()); + delegatedResourceCapsule.setFrozenBalanceForBandwidth(150_0000L, now - 100L); + dbManager.getDelegatedResourceStore().put(DelegatedResourceCapsule + .createDbKey(ByteArray.fromHexString(OWNER_ADDRESS), + ByteArray.fromHexString(RECEIVER_ADDRESS)), delegatedResourceCapsule); + + //init DelegatedResourceAccountIndex + { + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndex = + new DelegatedResourceAccountIndexCapsule( + owner.getAddress()); + delegatedResourceAccountIndex + .addToAccount(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); + dbManager.getDelegatedResourceAccountIndexStore() + .put(ByteArray.fromHexString(OWNER_ADDRESS), delegatedResourceAccountIndex); + } + + { + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndex = + new DelegatedResourceAccountIndexCapsule( + receiver.getAddress()); + delegatedResourceAccountIndex + .addFromAccount(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); + dbManager.getDelegatedResourceAccountIndexStore() + .put(ByteArray.fromHexString(RECEIVER_ADDRESS), delegatedResourceAccountIndex); + } + + + + UnfreezeBalanceActuator actuator1 = new UnfreezeBalanceActuator(); + actuator1.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidth(OWNER_ADDRESS)); + TransactionResultCapsule ret1 = new TransactionResultCapsule(); + try { + actuator1.validate(); + actuator1.execute(ret1); + long afterWeight1 = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); + Assert.assertEquals(1, afterWeight1); + Assert.assertEquals(ret1.getInstance().getRet(), code.SUCESS); + } catch (ContractValidateException e) { + logger.error("ContractValidateException", e); + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + UnfreezeBalanceActuator actuator = new UnfreezeBalanceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + long afterWeight = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); + Assert.assertEquals(0, afterWeight); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + dbManager.getDynamicPropertiesStore().saveAllowNewRewardEnable(0); + } @Test public void testUnfreezeBalanceForEnergy() { long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveAllowNewRewardEnable(0); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); AccountCapsule accountCapsule = dbManager.getAccountStore() @@ -304,6 +393,7 @@ public void testUnfreezeDelegatedBalanceForBandwidth() { } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } + } @Test From afee145c009e7ffbc624a1279339a3aa5da02fd4 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Thu, 10 Nov 2022 20:33:21 +0800 Subject: [PATCH 0413/1197] fix(mechanism): optimize name of proposal --- .../core/actuator/FreezeBalanceActuator.java | 2 +- .../actuator/UnfreezeBalanceActuator.java | 2 +- .../org/tron/core/utils/ProposalUtil.java | 12 +++++----- .../org/tron/core/db/EnergyProcessor.java | 2 +- .../core/store/DynamicPropertiesStore.java | 22 +++++++++---------- .../common/parameter/CommonParameter.java | 2 +- .../src/main/java/org/tron/core/Constant.java | 2 +- .../src/main/java/org/tron/core/Wallet.java | 4 ++-- .../java/org/tron/core/config/args/Args.java | 14 ++++++------ .../tron/core/consensus/ProposalService.java | 4 ++-- .../org/tron/core/db/BandwidthProcessor.java | 2 +- .../actuator/UnfreezeBalanceActuatorTest.java | 8 +++---- 12 files changed, 38 insertions(+), 38 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java index 91dcc1a6edd..a92491bd51e 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java @@ -133,7 +133,7 @@ public boolean execute(Object result) throws ContractExeException { private void addTotalWeight(ResourceCode resourceCode, DynamicPropertiesStore dynamicStore, long frozenBalance, long increment) { - long weight = dynamicStore.allowNewRewardEnable() ? increment : frozenBalance / TRX_PRECISION; + long weight = dynamicStore.allowNewReward() ? increment : frozenBalance / TRX_PRECISION; switch (resourceCode) { case BANDWIDTH: dynamicStore.addTotalNetWeight(weight); diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java index e384dbd865c..66cfb3f9ab4 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java @@ -237,7 +237,7 @@ public boolean execute(Object result) throws ContractExeException { } - long weight = dynamicStore.allowNewRewardEnable() ? decrease : -unfreezeBalance / TRX_PRECISION; + long weight = dynamicStore.allowNewReward() ? decrease : -unfreezeBalance / TRX_PRECISION; switch (unfreezeBalanceContract.getResource()) { case BANDWIDTH: dynamicStore diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index dacd713bf6d..e97709d8708 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -560,18 +560,18 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } - case ALLOW_NEW_REWARD_ALGO: { + case ALLOW_NEW_REWARD: { if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_6)) { throw new ContractValidateException( - "Bad chain parameter id [ALLOW_NEW_REWARD_ALGO]"); + "Bad chain parameter id [ALLOW_NEW_REWARD]"); } - if (dynamicPropertiesStore.allowNewRewardEnable()) { + if (dynamicPropertiesStore.allowNewReward()) { throw new ContractValidateException( - "New reward algorithm has been valid."); + "New reward has been valid."); } if (value != 1) { throw new ContractValidateException( - "This value[ALLOW_NEW_REWARD_ALGO] is only allowed to be 1"); + "This value[ALLOW_NEW_REWARD] is only allowed to be 1"); } break; } @@ -650,7 +650,7 @@ public enum ProposalType { // current value, value range ALLOW_TVM_LONDON(63), // 0, 1 ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX(65), // 0, 1 ALLOW_ASSET_OPTIMIZATION(66), // 0, 1 - ALLOW_NEW_REWARD_ALGO(67), // 0, 1 + ALLOW_NEW_REWARD(67), // 0, 1 MEMO_FEE(68); // 0, [0, 1000_000_000] private long code; diff --git a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java index 0ce7487e23f..5576896bc12 100644 --- a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java @@ -133,7 +133,7 @@ public long calculateGlobalEnergyLimit(AccountCapsule accountCapsule) { long energyWeight = frozeBalance / TRX_PRECISION; long totalEnergyLimit = dynamicPropertiesStore.getTotalEnergyCurrentLimit(); long totalEnergyWeight = dynamicPropertiesStore.getTotalEnergyWeight(); - if (dynamicPropertiesStore.allowNewRewardEnable() && totalEnergyWeight <= 0) { + if (dynamicPropertiesStore.allowNewReward() && totalEnergyWeight <= 0) { return 0; } else { assert totalEnergyWeight > 0; diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index f649aa08302..04e79e50a9f 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -863,10 +863,10 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { } try { - this.getAllowNewRewardEnable(); + this.getAllowNewReward(); } catch (IllegalArgumentException e) { - this.saveAllowNewRewardEnable(CommonParameter.getInstance().getAllowNewRewardEnable()); - if (CommonParameter.getInstance().getAllowNewRewardEnable() == 1) { + this.saveAllowNewReward(CommonParameter.getInstance().getAllowNewReward()); + if (CommonParameter.getInstance().getAllowNewReward() == 1) { this.put(NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE, new BytesCapsule(ByteArray.fromLong(getCurrentCycleNumber()))); } @@ -2156,7 +2156,7 @@ public void updateNextMaintenanceTime(long blockTime) { public void addTotalNetWeight(long amount) { long totalNetWeight = getTotalNetWeight(); totalNetWeight += amount; - if (allowNewRewardEnable()) { + if (allowNewReward()) { totalNetWeight = Math.max(0, totalNetWeight); } saveTotalNetWeight(totalNetWeight); @@ -2166,7 +2166,7 @@ public void addTotalNetWeight(long amount) { public void addTotalEnergyWeight(long amount) { long totalEnergyWeight = getTotalEnergyWeight(); totalEnergyWeight += amount; - if (allowNewRewardEnable()) { + if (allowNewReward()) { totalEnergyWeight = Math.max(0, totalEnergyWeight); } saveTotalEnergyWeight(totalEnergyWeight); @@ -2176,7 +2176,7 @@ public void addTotalEnergyWeight(long amount) { public void addTotalTronPowerWeight(long amount) { long totalWeight = getTotalTronPowerWeight(); totalWeight += amount; - if (allowNewRewardEnable()) { + if (allowNewReward()) { totalWeight = Math.max(0, totalWeight); } saveTotalTronPowerWeight(totalWeight); @@ -2581,19 +2581,19 @@ public void saveMemoFeeHistory(String value) { this.put(MEMO_FEE_HISTORY, new BytesCapsule(ByteArray.fromString(value))); } - public long getAllowNewRewardEnable() { + public long getAllowNewReward() { return Optional.ofNullable(getUnchecked(ALLOW_NEW_REWARD)) .map(BytesCapsule::getData) .map(ByteArray::toLong) - .orElseThrow(() -> new IllegalArgumentException("not found AllowNewRewardEnable")); + .orElseThrow(() -> new IllegalArgumentException("not found AllowNewReward")); } - public void saveAllowNewRewardEnable(long newReward) { + public void saveAllowNewReward(long newReward) { this.put(ALLOW_NEW_REWARD, new BytesCapsule(ByteArray.fromLong(newReward))); } - public boolean allowNewRewardEnable() { - return getAllowNewRewardEnable() == 1; + public boolean allowNewReward() { + return getAllowNewReward() == 1; } private static class DynamicResourceProperties { diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index accf4766ea4..20e11e0f6c1 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -563,7 +563,7 @@ public class CommonParameter { @Getter @Setter - public long allowNewRewardEnable = 0L; + public long allowNewReward = 0L; @Getter @Setter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 83430e9254c..01f9ab0a509 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -307,7 +307,7 @@ public class Constant { public static final String ALLOW_ACCOUNT_ASSET_OPTIMIZATION = "committee.allowAccountAssetOptimization"; public static final String ALLOW_ASSET_OPTIMIZATION = "committee.allowAssetOptimization"; - public static final String ALLOW_NEW_REWARD_ENABLE = "committee.allowNewRewardEnable"; + public static final String ALLOW_NEW_REWARD = "committee.allowNewReward"; public static final String MEMO_FEE = "committee.memoFee"; public static final String LOCAL_HOST = "127.0.0.1"; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 6cb7e9b9d01..1735aff84ae 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1099,8 +1099,8 @@ public Protocol.ChainParameters getChainParameters() { .build()); builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() - .setKey("getAllowNewRewardEnable") - .setValue(dbManager.getDynamicPropertiesStore().getAllowNewRewardEnable()) + .setKey("getAllowNewReward") + .setValue(dbManager.getDynamicPropertiesStore().getAllowNewReward()) .build()); builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 1625a4c684d..cb842c3ffc6 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -215,7 +215,7 @@ public static void clearParam() { PARAMETER.shutdownBlockCount = -1; PARAMETER.blockCacheTimeout = 60; PARAMETER.allowNewRewardAlgorithm = 0; - PARAMETER.allowNewRewardEnable = 0; + PARAMETER.allowNewReward = 0; PARAMETER.memoFee = 0; } @@ -1036,13 +1036,13 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.blockCacheTimeout = config.getLong(Constant.BLOCK_CACHE_TIMEOUT); } - if (config.hasPath(Constant.ALLOW_NEW_REWARD_ENABLE)) { - PARAMETER.allowNewRewardEnable = config.getLong(Constant.ALLOW_NEW_REWARD_ENABLE); - if (PARAMETER.allowNewRewardEnable > 1) { - PARAMETER.allowNewRewardEnable = 1; + if (config.hasPath(Constant.ALLOW_NEW_REWARD)) { + PARAMETER.allowNewReward = config.getLong(Constant.ALLOW_NEW_REWARD); + if (PARAMETER.allowNewReward > 1) { + PARAMETER.allowNewReward = 1; } - if (PARAMETER.allowNewRewardEnable < 0) { - PARAMETER.allowNewRewardEnable = 0; + if (PARAMETER.allowNewReward < 0) { + PARAMETER.allowNewReward = 0; } } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 99b4e569d4e..9d89316b8bb 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -284,9 +284,9 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().setAllowAssetOptimization(entry.getValue()); break; } - case ALLOW_NEW_REWARD_ALGO: { + case ALLOW_NEW_REWARD: { manager.getDynamicPropertiesStore().saveNewRewardAlgorithmEffectiveCycle(); - manager.getDynamicPropertiesStore().saveAllowNewRewardEnable(entry.getValue()); + manager.getDynamicPropertiesStore().saveAllowNewReward(entry.getValue()); break; } case MEMO_FEE: { diff --git a/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java b/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java index 9f4a9a1e5ed..c349c6bf148 100644 --- a/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/framework/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -390,7 +390,7 @@ public long calculateGlobalNetLimit(AccountCapsule accountCapsule) { long netWeight = frozeBalance / TRX_PRECISION; long totalNetLimit = chainBaseManager.getDynamicPropertiesStore().getTotalNetLimit(); long totalNetWeight = chainBaseManager.getDynamicPropertiesStore().getTotalNetWeight(); - if (dynamicPropertiesStore.allowNewRewardEnable() && totalNetWeight <= 0) { + if (dynamicPropertiesStore.allowNewReward() && totalNetWeight <= 0) { return 0; } if (totalNetWeight == 0) { diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java index d5238c838fb..de24f581c04 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java @@ -140,7 +140,7 @@ private Any getContract(String ownerAddress, ResourceCode resourceCode) { @Test public void testUnfreezeBalanceForBandwidth() { long now = System.currentTimeMillis(); - dbManager.getDynamicPropertiesStore().saveAllowNewRewardEnable(0); + dbManager.getDynamicPropertiesStore().saveAllowNewReward(0); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); AccountCapsule accountCapsule = dbManager.getAccountStore() @@ -182,7 +182,7 @@ public void testUnfreezeBalanceForBandwidth() { @Test public void testUnfreezeSelfAndOthersForBandwidth() { dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); - dbManager.getDynamicPropertiesStore().saveAllowNewRewardEnable(1); + dbManager.getDynamicPropertiesStore().saveAllowNewReward(1); long now = System.currentTimeMillis(); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); @@ -264,13 +264,13 @@ public void testUnfreezeSelfAndOthersForBandwidth() { } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } - dbManager.getDynamicPropertiesStore().saveAllowNewRewardEnable(0); + dbManager.getDynamicPropertiesStore().saveAllowNewReward(0); } @Test public void testUnfreezeBalanceForEnergy() { long now = System.currentTimeMillis(); - dbManager.getDynamicPropertiesStore().saveAllowNewRewardEnable(0); + dbManager.getDynamicPropertiesStore().saveAllowNewReward(0); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); AccountCapsule accountCapsule = dbManager.getAccountStore() From 342d242e72c9d4e5bcfd0f6c7a05e6d5f1024732 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Sat, 12 Nov 2022 19:41:08 +0800 Subject: [PATCH 0414/1197] feat(delegate): optimize delegate index storage --- .../core/actuator/FreezeBalanceActuator.java | 43 +++++---- .../actuator/UnfreezeBalanceActuator.java | 36 ++++---- .../org/tron/core/utils/ProposalUtil.java | 14 ++- .../DelegatedResourceAccountIndexCapsule.java | 9 ++ .../tron/core/db/TronStoreWithRevoking.java | 14 +++ .../DelegatedResourceAccountIndexStore.java | 89 +++++++++++++++++++ .../core/store/DynamicPropertiesStore.java | 26 ++++++ .../common/parameter/CommonParameter.java | 4 + .../src/main/java/org/tron/core/Constant.java | 1 + .../src/main/java/org/tron/core/Wallet.java | 7 +- .../java/org/tron/core/config/args/Args.java | 6 ++ .../tron/core/consensus/ProposalService.java | 4 + protocol/src/main/protos/core/Tron.proto | 1 + 13 files changed, 215 insertions(+), 39 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java index a92491bd51e..af36795035f 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java @@ -285,6 +285,7 @@ public long calcFee() { private long delegateResource(byte[] ownerAddress, byte[] receiverAddress, boolean isBandwidth, long balance, long expireTime) { AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicPropertiesStore = chainBaseManager.getDynamicPropertiesStore(); DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore(); DelegatedResourceAccountIndexStore delegatedResourceAccountIndexStore = chainBaseManager .getDelegatedResourceAccountIndexStore(); @@ -312,35 +313,39 @@ private long delegateResource(byte[] ownerAddress, byte[] receiverAddress, boole delegatedResourceStore.put(key, delegatedResourceCapsule); //modify DelegatedResourceAccountIndexStore - { - DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = delegatedResourceAccountIndexStore - .get(ownerAddress); - if (delegatedResourceAccountIndexCapsule == null) { - delegatedResourceAccountIndexCapsule = new DelegatedResourceAccountIndexCapsule( + if (!dynamicPropertiesStore.supportAllowDelegateOptimization()) { + + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = + delegatedResourceAccountIndexStore.get(ownerAddress); + if (ownerIndexCapsule == null) { + ownerIndexCapsule = new DelegatedResourceAccountIndexCapsule( ByteString.copyFrom(ownerAddress)); } - List toAccountsList = delegatedResourceAccountIndexCapsule.getToAccountsList(); + List toAccountsList = ownerIndexCapsule.getToAccountsList(); if (!toAccountsList.contains(ByteString.copyFrom(receiverAddress))) { - delegatedResourceAccountIndexCapsule.addToAccount(ByteString.copyFrom(receiverAddress)); + ownerIndexCapsule.addToAccount(ByteString.copyFrom(receiverAddress)); } - delegatedResourceAccountIndexStore - .put(ownerAddress, delegatedResourceAccountIndexCapsule); - } + delegatedResourceAccountIndexStore.put(ownerAddress, ownerIndexCapsule); - { - DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = delegatedResourceAccountIndexStore - .get(receiverAddress); - if (delegatedResourceAccountIndexCapsule == null) { - delegatedResourceAccountIndexCapsule = new DelegatedResourceAccountIndexCapsule( + DelegatedResourceAccountIndexCapsule receiverIndexCapsule + = delegatedResourceAccountIndexStore.get(receiverAddress); + if (receiverIndexCapsule == null) { + receiverIndexCapsule = new DelegatedResourceAccountIndexCapsule( ByteString.copyFrom(receiverAddress)); } - List fromAccountsList = delegatedResourceAccountIndexCapsule + List fromAccountsList = receiverIndexCapsule .getFromAccountsList(); if (!fromAccountsList.contains(ByteString.copyFrom(ownerAddress))) { - delegatedResourceAccountIndexCapsule.addFromAccount(ByteString.copyFrom(ownerAddress)); + receiverIndexCapsule.addFromAccount(ByteString.copyFrom(ownerAddress)); } - delegatedResourceAccountIndexStore - .put(receiverAddress, delegatedResourceAccountIndexCapsule); + delegatedResourceAccountIndexStore.put(receiverAddress, receiverIndexCapsule); + + } else { + // modify DelegatedResourceAccountIndexStore new + delegatedResourceAccountIndexStore.convert(ownerAddress); + delegatedResourceAccountIndexStore.convert(receiverAddress); + delegatedResourceAccountIndexStore.delegate(ownerAddress, receiverAddress, + dynamicPropertiesStore.getLatestBlockHeaderTimestamp()); } //modify AccountStore diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java index 66cfb3f9ab4..befcefd32d2 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java @@ -157,32 +157,32 @@ public boolean execute(Object result) throws ContractExeException { delegatedResourceStore.delete(key); //modify DelegatedResourceAccountIndexStore - { - DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = delegatedResourceAccountIndexStore - .get(ownerAddress); - if (delegatedResourceAccountIndexCapsule != null) { - List toAccountsList = new ArrayList<>(delegatedResourceAccountIndexCapsule + if (!dynamicStore.supportAllowDelegateOptimization()) { + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = + delegatedResourceAccountIndexStore.get(ownerAddress); + if (ownerIndexCapsule != null) { + List toAccountsList = new ArrayList<>(ownerIndexCapsule .getToAccountsList()); toAccountsList.remove(ByteString.copyFrom(receiverAddress)); - delegatedResourceAccountIndexCapsule.setAllToAccounts(toAccountsList); - delegatedResourceAccountIndexStore - .put(ownerAddress, delegatedResourceAccountIndexCapsule); + ownerIndexCapsule.setAllToAccounts(toAccountsList); + delegatedResourceAccountIndexStore.put(ownerAddress, ownerIndexCapsule); } - } - { - DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = delegatedResourceAccountIndexStore - .get(receiverAddress); - if (delegatedResourceAccountIndexCapsule != null) { - List fromAccountsList = new ArrayList<>(delegatedResourceAccountIndexCapsule + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = + delegatedResourceAccountIndexStore.get(receiverAddress); + if (receiverIndexCapsule != null) { + List fromAccountsList = new ArrayList<>(receiverIndexCapsule .getFromAccountsList()); fromAccountsList.remove(ByteString.copyFrom(ownerAddress)); - delegatedResourceAccountIndexCapsule.setAllFromAccounts(fromAccountsList); - delegatedResourceAccountIndexStore - .put(receiverAddress, delegatedResourceAccountIndexCapsule); + receiverIndexCapsule.setAllFromAccounts(fromAccountsList); + delegatedResourceAccountIndexStore.put(receiverAddress, receiverIndexCapsule); } + } else { + //modify DelegatedResourceAccountIndexStore new + delegatedResourceAccountIndexStore.convert(ownerAddress); + delegatedResourceAccountIndexStore.convert(receiverAddress); + delegatedResourceAccountIndexStore.unDelegate(ownerAddress, receiverAddress); } - } else { delegatedResourceStore.put(key, delegatedResourceCapsule); } diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index e97709d8708..9a7491ebe0b 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -586,6 +586,17 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case ALLOW_DELEGATE_OPTIMIZATION: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_6)) { + throw new ContractValidateException( + "Bad chain parameter id [ALLOW_DELEGATE_OPTIMIZATION]"); + } + if (value != 1) { + throw new ContractValidateException( + "This value[ALLOW_DELEGATE_OPTIMIZATION] is only allowed to be 1"); + } + break; + } default: break; } @@ -651,7 +662,8 @@ public enum ProposalType { // current value, value range ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX(65), // 0, 1 ALLOW_ASSET_OPTIMIZATION(66), // 0, 1 ALLOW_NEW_REWARD(67), // 0, 1 - MEMO_FEE(68); // 0, [0, 1000_000_000] + MEMO_FEE(68), // 0, [0, 1000_000_000] + ALLOW_DELEGATE_OPTIMIZATION(69); // 0, 1 private long code; diff --git a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java index 7c7a37fa609..9874c7de503 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java @@ -93,6 +93,15 @@ public void removeToAccount(ByteString toAccount) { } } + public void setTimestamp(long time) { + this.delegatedResourceAccountIndex = this.delegatedResourceAccountIndex.toBuilder() + .setTimestamp(time) + .build(); + } + + public long getTimestamp() { + return this.delegatedResourceAccountIndex.getTimestamp(); + } public byte[] createDbKey() { return getAccount().toByteArray(); diff --git a/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java b/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java index d1bbed934d5..be005a1da76 100644 --- a/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java +++ b/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java @@ -11,6 +11,7 @@ import java.util.Iterator; import java.util.Map; import java.util.Objects; +import java.util.stream.Collectors; import javax.annotation.PostConstruct; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -29,6 +30,7 @@ import org.tron.core.db2.common.IRevokingDB; import org.tron.core.db2.common.LevelDB; import org.tron.core.db2.common.RocksDB; +import org.tron.core.db2.common.WrappedByteArray; import org.tron.core.db2.core.Chainbase; import org.tron.core.db2.core.ITronChainBase; import org.tron.core.db2.core.RevokingDBWithCachingOldValue; @@ -234,4 +236,16 @@ public long size() { public void setCursor(Chainbase.Cursor cursor) { revokingDB.setCursor(cursor); } + + public Map prefixQuery(byte[] key) { + return revokingDB.prefixQuery(key).entrySet().stream().collect( + Collectors.toMap(Map.Entry::getKey, e -> { + try { + return of(e.getValue()); + } catch (BadItemException e1) { + throw new RuntimeException(e1); + } + } + )); + } } diff --git a/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java b/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java index b3eb5675873..73e8abb00a5 100644 --- a/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java @@ -1,5 +1,10 @@ package org.tron.core.store; +import com.google.protobuf.ByteString; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; import org.apache.commons.lang3.ArrayUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -11,6 +16,9 @@ public class DelegatedResourceAccountIndexStore extends TronStoreWithRevoking { + private static final byte[] fromPrefix = {0x01}; + private static final byte[] toPrefix = {0x02}; + @Autowired public DelegatedResourceAccountIndexStore(@Value("DelegatedResourceAccountIndex") String dbName) { super(dbName); @@ -23,4 +31,85 @@ public DelegatedResourceAccountIndexCapsule get(byte[] key) { return ArrayUtils.isEmpty(value) ? null : new DelegatedResourceAccountIndexCapsule(value); } + private byte[] createKey(byte[] prefix, byte[] address1, byte[] address2) { + byte[] key = new byte[prefix.length + address1.length + address2.length]; + System.arraycopy(prefix, 0, key, 0, prefix.length); + System.arraycopy(address1, 0, key, prefix.length, address1.length); + System.arraycopy(address2, 0, key, prefix.length + address1.length, address2.length); + return key; + } + + public void convert(byte[] address) { + DelegatedResourceAccountIndexCapsule indexCapsule = this.get(address); + if (indexCapsule == null) { + // convert complete or have no delegate + return; + } + // convert old data + List toList = indexCapsule.getToAccountsList(); + for (int i = 0; i < toList.size(); i++) { + // use index as the timestamp, just to keep index in order + this.delegate(address, toList.get(i).toByteArray(), i + 1L); + } + + List fromList = indexCapsule.getFromAccountsList(); + for (int i = 0; i < fromList.size(); i++) { + // use index as the timestamp, just to keep index in order + this.delegate(fromList.get(i).toByteArray(), address, i + 1L); + } + this.delete(address); + } + + public void delegate(byte[] from, byte[] to, long time) { + byte[] fromKey = createKey(fromPrefix, from, to); + DelegatedResourceAccountIndexCapsule toIndexCapsule = + new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(to)); + toIndexCapsule.setTimestamp(time); + this.put(fromKey, toIndexCapsule); + + byte[] toKey = createKey(toPrefix, to, from); + DelegatedResourceAccountIndexCapsule fromIndexCapsule = + new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(from)); + fromIndexCapsule.setTimestamp(time); + this.put(toKey, fromIndexCapsule); + } + + public void unDelegate(byte[] from, byte[] to) { + byte[] fromKey = createKey(fromPrefix, from, to); + this.delete(fromKey); + byte[] toKey = createKey(toPrefix, to, from); + this.delete(toKey); + } + + public DelegatedResourceAccountIndexCapsule getIndex(byte[] address) { + DelegatedResourceAccountIndexCapsule indexCapsule = get(address); + if (indexCapsule != null) { + return indexCapsule; + } + + DelegatedResourceAccountIndexCapsule tmpIndexCapsule = + new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(address)); + byte[] key = new byte[fromPrefix.length + address.length]; + + System.arraycopy(fromPrefix, 0, key, 0, fromPrefix.length); + System.arraycopy(address, 0, key, fromPrefix.length, address.length); + List tmpToList = + new ArrayList<>(this.prefixQuery(key).values()); + + tmpToList.sort(Comparator.comparing(DelegatedResourceAccountIndexCapsule::getTimestamp)); + List list = tmpToList.stream() + .map(DelegatedResourceAccountIndexCapsule::getAccount).collect(Collectors.toList()); + tmpIndexCapsule.setAllToAccounts(list); + + System.arraycopy(toPrefix, 0, key, 0, toPrefix.length); + System.arraycopy(address, 0, key, toPrefix.length, address.length); + List tmpFromList = + new ArrayList<>(this.prefixQuery(key).values()); + tmpFromList.sort(Comparator.comparing(DelegatedResourceAccountIndexCapsule::getTimestamp)); + list = tmpFromList.stream().map(DelegatedResourceAccountIndexCapsule::getAccount).collect( + Collectors.toList()); + tmpIndexCapsule.setAllFromAccounts(list); + return tmpIndexCapsule; + } + } \ No newline at end of file diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 04e79e50a9f..74f0e19df7c 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -190,6 +190,9 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_NEW_REWARD = "ALLOW_NEW_REWARD".getBytes(); private static final byte[] MEMO_FEE = "MEMO_FEE".getBytes(); private static final byte[] MEMO_FEE_HISTORY = "MEMO_FEE_HISTORY".getBytes(); + private static final byte[] ALLOW_DELEGATE_OPTIMIZATION = + "ALLOW_DELEGATE_OPTIMIZATION".getBytes(); + @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { @@ -879,6 +882,13 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { this.saveMemoFee(memoFee); this.saveMemoFeeHistory("0:" + memoFee); } + + try { + this.getAllowDelegateOptimization(); + } catch (IllegalArgumentException e) { + this.saveAllowDelegateOptimization( + CommonParameter.getInstance().getAllowDelegateOptimization()); + } } public String intArrayToString(int[] a) { @@ -2592,6 +2602,22 @@ public void saveAllowNewReward(long newReward) { this.put(ALLOW_NEW_REWARD, new BytesCapsule(ByteArray.fromLong(newReward))); } + public long getAllowDelegateOptimization() { + return Optional.ofNullable(getUnchecked(ALLOW_DELEGATE_OPTIMIZATION)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException("not found ALLOW_DELEGATE_OPTIMIZATION")); + } + + public boolean supportAllowDelegateOptimization() { + return getAllowDelegateOptimization() == 1L; + } + + public void saveAllowDelegateOptimization(long value) { + this.put(ALLOW_DELEGATE_OPTIMIZATION, new BytesCapsule(ByteArray.fromLong(value))); + } + public boolean allowNewReward() { return getAllowNewReward() == 1; } diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 20e11e0f6c1..f8feb3da925 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -569,6 +569,10 @@ public class CommonParameter { @Setter public long memoFee = 0L; + @Getter + @Setter + public long allowDelegateOptimization = 0L; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 01f9ab0a509..808be9daf16 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -309,6 +309,7 @@ public class Constant { public static final String ALLOW_ASSET_OPTIMIZATION = "committee.allowAssetOptimization"; public static final String ALLOW_NEW_REWARD = "committee.allowNewReward"; public static final String MEMO_FEE = "committee.memoFee"; + public static final String ALLOW_DELEGATE_OPTIMIZATION = "committee.allowDelegateOptimization"; public static final String LOCAL_HOST = "127.0.0.1"; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 1735aff84ae..323585f1b24 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -753,7 +753,7 @@ public DelegatedResourceList getDelegatedResource(ByteString fromAddress, ByteSt public DelegatedResourceAccountIndex getDelegatedResourceAccountIndex(ByteString address) { DelegatedResourceAccountIndexCapsule accountIndexCapsule = - chainBaseManager.getDelegatedResourceAccountIndexStore().get(address.toByteArray()); + chainBaseManager.getDelegatedResourceAccountIndexStore().getIndex(address.toByteArray()); if (accountIndexCapsule != null) { return accountIndexCapsule.getInstance(); } else { @@ -1108,6 +1108,11 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getMemoFee()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getAllowDelegateOptimization") + .setValue(dbManager.getDynamicPropertiesStore().getAllowDelegateOptimization()) + .build()); + return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index cb842c3ffc6..a64560573b3 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1056,6 +1056,12 @@ public static void setParam(final String[] args, final String confFileName) { } } + if (config.hasPath(Constant.ALLOW_DELEGATE_OPTIMIZATION)) { + PARAMETER.allowDelegateOptimization = config.getLong(Constant.ALLOW_DELEGATE_OPTIMIZATION); + PARAMETER.allowDelegateOptimization = Math.min(PARAMETER.allowDelegateOptimization, 1); + PARAMETER.allowDelegateOptimization = Math.max(PARAMETER.allowDelegateOptimization, 0); + } + logConfig(); } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 9d89316b8bb..061afe590ab 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -297,6 +297,10 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) + "," + proposalCapsule.getExpirationTime() + ":" + entry.getValue()); break; } + case ALLOW_DELEGATE_OPTIMIZATION: { + manager.getDynamicPropertiesStore().saveAllowDelegateOptimization(entry.getValue()); + break; + } default: find = false; break; diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 9d4af0a3151..ba27a70525f 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -619,6 +619,7 @@ message DelegatedResourceAccountIndex { bytes account = 1; repeated bytes fromAccounts = 2; repeated bytes toAccounts = 3; + int64 timestamp = 4; } message NodeInfo { From 5ac7f0c93152c305a574ea5263ecafcac762cfdf Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Mon, 14 Nov 2022 14:28:56 +0800 Subject: [PATCH 0415/1197] feat(delegate): add test for delegate optimization --- .../DelegatedResourceAccountIndexStore.java | 22 +++--- .../actuator/FreezeBalanceActuatorTest.java | 67 +++++++++++++++++++ 2 files changed, 78 insertions(+), 11 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java b/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java index 73e8abb00a5..e9b7be47792 100644 --- a/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java @@ -16,8 +16,8 @@ public class DelegatedResourceAccountIndexStore extends TronStoreWithRevoking { - private static final byte[] fromPrefix = {0x01}; - private static final byte[] toPrefix = {0x02}; + private static final byte[] FROM_PREFIX = {0x01}; + private static final byte[] TO_PREFIX = {0x02}; @Autowired public DelegatedResourceAccountIndexStore(@Value("DelegatedResourceAccountIndex") String dbName) { @@ -61,13 +61,13 @@ public void convert(byte[] address) { } public void delegate(byte[] from, byte[] to, long time) { - byte[] fromKey = createKey(fromPrefix, from, to); + byte[] fromKey = createKey(FROM_PREFIX, from, to); DelegatedResourceAccountIndexCapsule toIndexCapsule = new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(to)); toIndexCapsule.setTimestamp(time); this.put(fromKey, toIndexCapsule); - byte[] toKey = createKey(toPrefix, to, from); + byte[] toKey = createKey(TO_PREFIX, to, from); DelegatedResourceAccountIndexCapsule fromIndexCapsule = new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(from)); fromIndexCapsule.setTimestamp(time); @@ -75,9 +75,9 @@ public void delegate(byte[] from, byte[] to, long time) { } public void unDelegate(byte[] from, byte[] to) { - byte[] fromKey = createKey(fromPrefix, from, to); + byte[] fromKey = createKey(FROM_PREFIX, from, to); this.delete(fromKey); - byte[] toKey = createKey(toPrefix, to, from); + byte[] toKey = createKey(TO_PREFIX, to, from); this.delete(toKey); } @@ -89,10 +89,10 @@ public DelegatedResourceAccountIndexCapsule getIndex(byte[] address) { DelegatedResourceAccountIndexCapsule tmpIndexCapsule = new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(address)); - byte[] key = new byte[fromPrefix.length + address.length]; + byte[] key = new byte[FROM_PREFIX.length + address.length]; - System.arraycopy(fromPrefix, 0, key, 0, fromPrefix.length); - System.arraycopy(address, 0, key, fromPrefix.length, address.length); + System.arraycopy(FROM_PREFIX, 0, key, 0, FROM_PREFIX.length); + System.arraycopy(address, 0, key, FROM_PREFIX.length, address.length); List tmpToList = new ArrayList<>(this.prefixQuery(key).values()); @@ -101,8 +101,8 @@ public DelegatedResourceAccountIndexCapsule getIndex(byte[] address) { .map(DelegatedResourceAccountIndexCapsule::getAccount).collect(Collectors.toList()); tmpIndexCapsule.setAllToAccounts(list); - System.arraycopy(toPrefix, 0, key, 0, toPrefix.length); - System.arraycopy(address, 0, key, toPrefix.length, address.length); + System.arraycopy(TO_PREFIX, 0, key, 0, TO_PREFIX.length); + System.arraycopy(address, 0, key, TO_PREFIX.length, address.length); List tmpFromList = new ArrayList<>(this.prefixQuery(key).values()); tmpFromList.sort(Comparator.comparing(DelegatedResourceAccountIndexCapsule::getTimestamp)); diff --git a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java index b2e84d39095..3494ddb0624 100644 --- a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java @@ -6,6 +6,7 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; import java.io.File; +import java.util.List; import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; import org.junit.Assert; @@ -13,8 +14,10 @@ import org.junit.BeforeClass; import org.junit.Test; import org.tron.common.application.TronApplicationContext; +import org.tron.common.crypto.ECKey; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; +import org.tron.common.utils.Utils; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -313,6 +316,70 @@ public void testFreezeDelegatedBalanceForBandwidth() { } } + @Test + public void testMultiFreezeDelegatedBalanceForBandwidth() { + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + dbManager.getDynamicPropertiesStore().saveAllowDelegateOptimization(1L); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(10000L); + long frozenBalance = 1_000_000_000L; + long duration = 3; + final int RECEIVE_COUNT = 100; + String[] RECEIVE_ADDRESSES = new String[RECEIVE_COUNT + 1]; + + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = + new DelegatedResourceAccountIndexCapsule( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); + for (int i = 0; i < RECEIVE_COUNT + 1; i++) { + ECKey ecKey = new ECKey(Utils.getRandom()); + RECEIVE_ADDRESSES[i] = ByteArray.toHexString(ecKey.getAddress()); + if (i != RECEIVE_COUNT) { + ownerIndexCapsule.addToAccount(ByteString.copyFrom(ecKey.getAddress())); + } + } + dbManager.getDelegatedResourceAccountIndexStore().put( + ByteArray.fromHexString(OWNER_ADDRESS), ownerIndexCapsule); + AccountCapsule receiverCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVE_ADDRESSES[RECEIVE_COUNT])), + AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + FreezeBalanceActuator actuator = new FreezeBalanceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForBandwidth( + OWNER_ADDRESS, RECEIVE_ADDRESSES[RECEIVE_COUNT], frozenBalance, duration)); + try { + ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().getIndex(ByteArray.fromHexString(OWNER_ADDRESS)); + List beforeList = ownerIndexCapsule.getToAccountsList(); + actuator.validate(); + actuator.execute(ret); + + //check DelegatedResourceAccountIndex convert + ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + Assert.assertNull(ownerIndexCapsule); + + ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().getIndex(ByteArray.fromHexString(OWNER_ADDRESS)); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + List tmpList = ownerIndexCapsule.getToAccountsList(); + Assert.assertEquals(RECEIVE_COUNT + 1, ownerIndexCapsule.getToAccountsList().size()); + for (int i = 0; i < RECEIVE_COUNT; i++) { + Assert.assertEquals(beforeList.get(i), tmpList.get(i)); + } + Assert.assertEquals(RECEIVE_ADDRESSES[RECEIVE_COUNT], + ByteArray.toHexString(tmpList.get(RECEIVE_COUNT).toByteArray())); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail("con not reach here"); + } + dbManager.getDynamicPropertiesStore().saveAllowDelegateOptimization(0L); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(10000L); + } + @Test public void testFreezeDelegatedBalanceForCpuSameNameTokenActive() { dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); From da34af135bc185ae93758f2bfe178deb0efd5339 Mon Sep 17 00:00:00 2001 From: liukai Date: Mon, 14 Nov 2022 17:18:09 +0800 Subject: [PATCH 0416/1197] feat(CONTRIBUTING.md): update CONTRIBUTING.md 1. update image links 2. modify log level --- CONTRIBUTING.md | 4 ++-- framework/src/main/java/org/tron/core/Wallet.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c81587501f3..d8dc83ad51b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -103,12 +103,12 @@ If you want to contribute codes to java-tron, please follow the following steps: Submit a pull request (PR) from your repository to `tronprotocol/java-tron`. Please be sure to click on the link in the red box shown below. Select the base branch for tronprotocol and the compare branch for your personal fork repository. - ![](https://codimd.s3.shivering-isles.com/demo/uploads/e24435ab42e4287d9369a2136.png) + ![image](https://raw.githubusercontent.com/tronprotocol/documentation-en/master/images/javatron_pr.png) ## Code Review Guidelines -The only way to get code into java-tron is to send a pull request. Those pull requests need to be reviewed by someone. there a guide that explains our expectations around PRs for both authors and reviewers. +The only way to get code into java-tron is to send a pull request. Those pull requests need to be reviewed by someone. The following guide explains our expectations around PRs for both authors and reviewers. ### Terminology - The author of a pull request is the entity who wrote the diff and submitted it to GitHub. diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 1735aff84ae..3bac75edbfe 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -687,7 +687,7 @@ public long getTransactionCountByBlockNum(long blockNum) { Block block = chainBaseManager.getBlockByNum(blockNum).getInstance(); count = block.getTransactionsCount(); } catch (StoreException e) { - logger.error(e.getMessage()); + logger.warn(e.getMessage()); } return count; @@ -1414,7 +1414,7 @@ public Block getBlockById(ByteString blockId) { try { block = chainBaseManager.getBlockStore().get(blockId.toByteArray()).getInstance(); } catch (StoreException e) { - logger.error(e.getMessage()); + logger.warn(e.getMessage()); } return block; } From 4afd4c567edc836534b39ce8bb90e50a6c98033a Mon Sep 17 00:00:00 2001 From: chaozhu Date: Mon, 14 Nov 2022 17:23:08 +0800 Subject: [PATCH 0417/1197] feat(freezeV2): add query api to get delegate max resource size --- .../org/tron/core/utils/TransactionUtil.java | 50 +++++++++++++++ .../java/org/tron/core/config/Parameter.java | 1 + .../src/main/java/org/tron/core/Wallet.java | 63 +++++++++++++++++++ .../org/tron/core/services/RpcApiService.java | 25 ++++++++ .../services/http/FullNodeHttpApiService.java | 4 ++ .../http/GetCanDelegatedMaxSizeServlet.java | 63 +++++++++++++++++++ .../http/HttpSelfFormatFieldName.java | 1 + .../solidity/SolidityNodeHttpApiService.java | 5 ++ ...tCanDelegatedMaxSizeOnSolidityServlet.java | 29 +++++++++ .../solidity/HttpApiOnSolidityService.java | 5 ++ protocol/src/main/protos/api/api.proto | 14 +++++ 11 files changed, 260 insertions(+) create mode 100644 framework/src/main/java/org/tron/core/services/http/GetCanDelegatedMaxSizeServlet.java create mode 100644 framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetCanDelegatedMaxSizeOnSolidityServlet.java diff --git a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java index 5ca4f36ab12..d03ca513822 100644 --- a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java @@ -16,6 +16,8 @@ package org.tron.core.utils; import static org.tron.common.crypto.Hash.sha3omit12; +import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_COST_BASE_SIZE; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import com.google.common.base.CaseFormat; import com.google.common.primitives.Longs; @@ -37,6 +39,7 @@ import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.Sha256Hash; import org.tron.core.ChainBaseManager; +import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.exception.PermissionException; @@ -49,6 +52,8 @@ import org.tron.protos.Protocol.TransactionSign; import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.contract.BalanceContract.DelegateResourceContract; @Slf4j(topic = "capsule") @Component @@ -264,4 +269,49 @@ public TransactionSignWeight getTransactionSignWeight(Transaction trx) { return tswBuilder.build(); } + public static long consumeBandWidthSize( + final TransactionCapsule transactionCapsule, + ChainBaseManager chainBaseManager) { + long bytesSize; + + boolean supportVM = chainBaseManager.getDynamicPropertiesStore().supportVM(); + if (supportVM) { + bytesSize = transactionCapsule.getInstance().toBuilder().clearRet().build().getSerializedSize(); + } else { + bytesSize = transactionCapsule.getSerializedSize(); + } + + List contracts = transactionCapsule.getInstance().getRawData().getContractList(); + for (Transaction.Contract contract : contracts) { + if (contract.getType() == Contract.ContractType.ShieldedTransferContract) { + continue; + } + if (supportVM) { + bytesSize += Constant.MAX_RESULT_SIZE_IN_TX; + } + } + + return bytesSize; + } + + + public static long estimateConsumeBandWidthSize( + final AccountCapsule ownerCapsule, + ChainBaseManager chainBaseManager) { + DelegateResourceContract.Builder builder = DelegateResourceContract.newBuilder() + .setBalance(ownerCapsule.getFrozenV2BalanceForBandwidth()); + TransactionCapsule fakeTransactionCapsule = new TransactionCapsule(builder.build() + , ContractType.DelegateResourceContract); + long size1 = consumeBandWidthSize(fakeTransactionCapsule, chainBaseManager); + + DelegateResourceContract.Builder builder2 = DelegateResourceContract.newBuilder() + .setBalance(TRX_PRECISION); + TransactionCapsule fakeTransactionCapsule2 = new TransactionCapsule(builder2.build() + , ContractType.DelegateResourceContract); + long size2 = consumeBandWidthSize(fakeTransactionCapsule2, chainBaseManager); + long addSize = Math.max(size1 - size2, 0L); + + return DELEGATE_COST_BASE_SIZE + addSize; + } + } diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index 1a4f9cf3dd7..dcaf004af6d 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -70,6 +70,7 @@ public class ChainConstant { public static final int BLOCK_VERSION = 25; public static final long FROZEN_PERIOD = 86_400_000L; public static final long TRX_PRECISION = 1000_000L; + public static final long DELEGATE_COST_BASE_SIZE = 275L; } public class NodeConstant { diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index ba8e8e9a8be..ba04a0b2b8b 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -222,6 +222,7 @@ import org.tron.protos.contract.BalanceContract; import org.tron.protos.contract.BalanceContract.BlockBalanceTrace; import org.tron.protos.contract.BalanceContract.TransferContract; +import org.tron.protos.contract.Common; import org.tron.protos.contract.ShieldContract.IncrementalMerkleTree; import org.tron.protos.contract.ShieldContract.IncrementalMerkleVoucherInfo; import org.tron.protos.contract.ShieldContract.OutputPoint; @@ -799,6 +800,22 @@ public GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage getCanWithdrawUnfreezeAm return builder.build(); } + public GrpcAPI.CanDelegatedMaxSizeResponseMessage getCanDelegatedMaxSize( + ByteString ownerAddress, + int resourceType) { + long canDelegatedMaxSize = 0L; + GrpcAPI.CanDelegatedMaxSizeResponseMessage.Builder builder = + GrpcAPI.CanDelegatedMaxSizeResponseMessage.newBuilder(); + if (Common.ResourceCode.BANDWIDTH.getNumber() == resourceType) { + canDelegatedMaxSize = this.calcCanDelegatedBandWidthMaxSize(ownerAddress); + } else if (Common.ResourceCode.ENERGY.getNumber() == resourceType) { + canDelegatedMaxSize = this.calcCanDelegatedEnergyMaxSize(ownerAddress); + } + + builder.setMaxSize(canDelegatedMaxSize); + return builder.build(); + } + public GrpcAPI.GetAvailableUnfreezeCountResponseMessage getAvailableUnfreezeCount( ByteString ownerAddress) { long getAvailableUnfreezeCount; @@ -826,6 +843,52 @@ public GrpcAPI.GetAvailableUnfreezeCountResponseMessage getAvailableUnfreezeCoun return builder.build(); } + public long calcCanDelegatedBandWidthMaxSize( + ByteString ownerAddress) { + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + AccountCapsule ownerCapsule = accountStore.get(ownerAddress.toByteArray()); + if (ownerCapsule == null) { + return 0L; + } + + BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); + processor.updateUsage(ownerCapsule); + + long accountNetUsage = ownerCapsule.getNetUsage(); + accountNetUsage += org.tron.core.utils.TransactionUtil.estimateConsumeBandWidthSize( + ownerCapsule, chainBaseManager); + + long netUsage = (long) (accountNetUsage * TRX_PRECISION * ((double) + (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); + + long ownerNetUsage = (long) (netUsage * ((double)(ownerCapsule.getFrozenV2BalanceForBandwidth()) + / ownerCapsule.getAllFrozenBalanceForBandwidth())); + long remain = ownerCapsule.getFrozenV2BalanceForBandwidth() - ownerNetUsage; + return remain > 0 ? remain : 0; + } + + public long calcCanDelegatedEnergyMaxSize(ByteString ownerAddress) { + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + AccountCapsule ownerCapsule = accountStore.get(ownerAddress.toByteArray()); + if (ownerCapsule == null) { + return 0L; + } + + EnergyProcessor processor = new EnergyProcessor(dynamicStore, accountStore); + processor.updateUsage(ownerCapsule); + + long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) + (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); + + long ownerEnergyUsage = (long) (energyUsage * ((double)(ownerCapsule + .getFrozenV2BalanceForEnergy()) / ownerCapsule.getAllFrozenBalanceForEnergy())); + + long remain = ownerCapsule.getFrozenV2BalanceForEnergy() - ownerEnergyUsage; + return remain > 0 ? remain : 0; + } + public DelegatedResourceAccountIndex getDelegatedResourceAccountIndex(ByteString address) { DelegatedResourceAccountIndexCapsule accountIndexCapsule = chainBaseManager.getDelegatedResourceAccountIndexStore().get(address.toByteArray()); diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 40f62440ebb..f6becb17252 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -638,6 +638,18 @@ public void getDelegatedResourceAccountIndexV2(BytesMessage request, responseObserver.onCompleted(); } + @Override + public void getCanDelegatedMaxSize(GrpcAPI.CanDelegatedMaxSizeRequestMessage request, + StreamObserver responseObserver) { + try { + responseObserver.onNext(wallet.getCanDelegatedMaxSize( + request.getOwnerAddress(),request.getType())); + } catch (Exception e) { + responseObserver.onError(getRunTimeException(e)); + } + responseObserver.onCompleted(); + } + @Override public void getAvailableUnfreezeCount(GrpcAPI.GetAvailableUnfreezeCountRequestMessage request, StreamObserver responseObserver) { @@ -2109,6 +2121,19 @@ public void getDelegatedResourceAccountIndexV2(BytesMessage request, responseObserver.onCompleted(); } + @Override + public void getCanDelegatedMaxSize(GrpcAPI.CanDelegatedMaxSizeRequestMessage request, + StreamObserver responseObserver) { + try { + responseObserver.onNext(wallet.getCanDelegatedMaxSize( + request.getOwnerAddress(), request.getType())); + } catch (Exception e) { + responseObserver.onError(getRunTimeException(e)); + } + + responseObserver.onCompleted(); + } + @Override public void getAvailableUnfreezeCount(GrpcAPI.GetAvailableUnfreezeCountRequestMessage request, StreamObserver responseObserver) { diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index f9c804629ac..b4479eafdea 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -188,6 +188,8 @@ public class FullNodeHttpApiService implements Service { @Autowired private GetDelegatedResourceV2Servlet getDelegatedResourceV2Servlet; @Autowired + private GetCanDelegatedMaxSizeServlet getCanDelegatedMaxSizeServlet; + @Autowired private GetAvailableUnfreezeCountServlet getAvailableUnfreezeCountServlet; @Autowired private GetCanWithdrawUnfreezeAmountServlet getCanWithdrawUnfreezeAmountServlet; @@ -472,6 +474,8 @@ public void start() { "/wallet/getdelegatedresource"); context.addServlet(new ServletHolder(getDelegatedResourceV2Servlet), "/wallet/getdelegatedresourcev2"); + context.addServlet(new ServletHolder(getCanDelegatedMaxSizeServlet), + "/wallet/getcandelegatedmaxsize"); context.addServlet(new ServletHolder(getAvailableUnfreezeCountServlet), "/wallet/getavailableunfreezecount"); context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountServlet), diff --git a/framework/src/main/java/org/tron/core/services/http/GetCanDelegatedMaxSizeServlet.java b/framework/src/main/java/org/tron/core/services/http/GetCanDelegatedMaxSizeServlet.java new file mode 100644 index 00000000000..81dd52400b5 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/GetCanDelegatedMaxSizeServlet.java @@ -0,0 +1,63 @@ +package org.tron.core.services.http; + +import com.google.protobuf.ByteString; +import java.io.IOException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.api.GrpcAPI; +import org.tron.common.utils.ByteArray; +import org.tron.core.Wallet; + +@Component +@Slf4j(topic = "API") +public class GetCanDelegatedMaxSizeServlet extends RateLimiterServlet { + + @Autowired + private Wallet wallet; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + try { + boolean visible = Util.getVisible(request); + int type = Integer.parseInt(request.getParameter("type")); + String ownerAddress = request.getParameter("owner_address"); + if (visible) { + ownerAddress = Util.getHexAddress(ownerAddress); + } + fillResponse(visible, + ByteString.copyFrom(ByteArray.fromHexString(ownerAddress)), + type, response); + } catch (Exception e) { + Util.processError(e, response); + } + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + PostParams params = PostParams.getPostParams(request); + GrpcAPI.CanDelegatedMaxSizeRequestMessage.Builder build = + GrpcAPI.CanDelegatedMaxSizeRequestMessage.newBuilder(); + JsonFormat.merge(params.getParams(), build, params.isVisible()); + fillResponse(params.isVisible(), + build.getOwnerAddress(), + build.getType(), response); + } catch (Exception e) { + Util.processError(e, response); + } + } + + private void fillResponse(boolean visible, + ByteString ownerAddress, + int resourceType, + HttpServletResponse response) throws IOException { + GrpcAPI.CanDelegatedMaxSizeResponseMessage reply = + wallet.getCanDelegatedMaxSize(ownerAddress, resourceType); + if (reply != null) { + response.getWriter().println(JsonFormat.printToString(reply, visible)); + } else { + response.getWriter().println("{}"); + } + } +} diff --git a/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java b/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java index eb776a7e1c0..3d3f73468bd 100644 --- a/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java +++ b/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java @@ -154,6 +154,7 @@ public class HttpSelfFormatFieldName { //UnDelegateResourceContract AddressFieldNameMap.put("protocol.UnDelegateResourceContract.owner_address", 1); AddressFieldNameMap.put("protocol.UnDelegateResourceContract.receiver_address", 1); + AddressFieldNameMap.put("protocol.CanDelegatedMaxSizeRequestMessage.owner_address", 1); AddressFieldNameMap.put("protocol.GetAvailableUnfreezeCountRequestMessage.owner_address", 1); AddressFieldNameMap.put("protocol.CanWithdrawUnfreezeAmountRequestMessage.owner_address", 1); diff --git a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java index 0830568ad54..580969ac13a 100644 --- a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java @@ -31,6 +31,7 @@ import org.tron.core.services.http.GetBlockServlet; import org.tron.core.services.http.GetBrokerageServlet; import org.tron.core.services.http.GetBurnTrxServlet; +import org.tron.core.services.http.GetCanDelegatedMaxSizeServlet; import org.tron.core.services.http.GetCanWithdrawUnfreezeAmountServlet; import org.tron.core.services.http.GetDelegatedResourceAccountIndexServlet; import org.tron.core.services.http.GetDelegatedResourceAccountIndexV2Servlet; @@ -86,6 +87,8 @@ public class SolidityNodeHttpApiService implements Service { @Autowired private GetDelegatedResourceV2Servlet getDelegatedResourceV2Servlet; @Autowired + private GetCanDelegatedMaxSizeServlet getCanDelegatedMaxSizeServlet; + @Autowired private GetAvailableUnfreezeCountServlet getAvailableUnfreezeCountServlet; @Autowired private GetCanWithdrawUnfreezeAmountServlet getCanWithdrawUnfreezeAmountServlet; @@ -215,6 +218,8 @@ public void start() { "/walletsolidity/getdelegatedresource"); context.addServlet(new ServletHolder(getDelegatedResourceV2Servlet), "/walletsolidity/getdelegatedresourcev2"); + context.addServlet(new ServletHolder(getCanDelegatedMaxSizeServlet), + "/walletsolidity/getcandelegatedmaxsize"); context.addServlet(new ServletHolder(getAvailableUnfreezeCountServlet), "/walletsolidity/getavailableunfreezecount"); context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountServlet), diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetCanDelegatedMaxSizeOnSolidityServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetCanDelegatedMaxSizeOnSolidityServlet.java new file mode 100644 index 00000000000..f2a2fb394e4 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetCanDelegatedMaxSizeOnSolidityServlet.java @@ -0,0 +1,29 @@ +package org.tron.core.services.interfaceOnSolidity.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; +import org.tron.core.services.http.GetCanDelegatedMaxSizeServlet; +import org.tron.core.services.interfaceOnSolidity.WalletOnSolidity; + +@Component +@Slf4j(topic = "API") +public class GetCanDelegatedMaxSizeOnSolidityServlet extends GetCanDelegatedMaxSizeServlet { + + @Autowired + private Wallet wallet; + + @Autowired + private WalletOnSolidity walletOnSolidity; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java index 89da15b8555..3073947368a 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java @@ -30,6 +30,7 @@ import org.tron.core.services.interfaceOnSolidity.http.GetBlockOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetBrokerageOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetBurnTrxOnSolidityServlet; +import org.tron.core.services.interfaceOnSolidity.http.GetCanDelegatedMaxSizeOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetCanWithdrawUnfreezeAmountOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetDelegatedResourceAccountIndexOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetDelegatedResourceAccountIndexV2OnSolidityServlet; @@ -94,6 +95,8 @@ public class HttpApiOnSolidityService implements Service { @Autowired private GetDelegatedResourceV2OnSolidityServlet getDelegatedResourceV2OnSolidityServlet; @Autowired + private GetCanDelegatedMaxSizeOnSolidityServlet getCanDelegatedMaxSizeOnSolidityServlet; + @Autowired private GetAvailableUnfreezeCountOnSolidityServlet getAvailableUnfreezeCountOnSolidityServlet; @Autowired private GetCanWithdrawUnfreezeAmountOnSolidityServlet @@ -215,6 +218,8 @@ public void start() { "/walletsolidity/getdelegatedresource"); context.addServlet(new ServletHolder(getDelegatedResourceV2OnSolidityServlet), "/walletsolidity/getdelegatedresourcev2"); + context.addServlet(new ServletHolder(getCanDelegatedMaxSizeOnSolidityServlet), + "/walletsolidity/getcandelegatedmaxsize"); context.addServlet(new ServletHolder(getAvailableUnfreezeCountOnSolidityServlet), "/walletsolidity/getavailableunfreezecount"); context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountOnSolidityServlet), diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index d94da7cad80..e2aa75255ad 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -506,6 +506,9 @@ service Wallet { rpc GetDelegatedResourceAccountIndexV2 (BytesMessage) returns (DelegatedResourceAccountIndex) { }; + rpc GetCanDelegatedMaxSize (CanDelegatedMaxSizeRequestMessage) returns (CanDelegatedMaxSizeResponseMessage) { + }; + rpc GetAvailableUnfreezeCount (GetAvailableUnfreezeCountRequestMessage) returns (GetAvailableUnfreezeCountResponseMessage) { }; @@ -924,6 +927,9 @@ service WalletSolidity { rpc GetDelegatedResourceAccountIndexV2 (BytesMessage) returns (DelegatedResourceAccountIndex) { }; + rpc GetCanDelegatedMaxSize (CanDelegatedMaxSizeRequestMessage) returns (CanDelegatedMaxSizeResponseMessage) { + }; + rpc GetAvailableUnfreezeCount (GetAvailableUnfreezeCountRequestMessage) returns (GetAvailableUnfreezeCountResponseMessage) { }; @@ -1153,6 +1159,14 @@ message GetAvailableUnfreezeCountResponseMessage { int64 count = 1; } +message CanDelegatedMaxSizeRequestMessage { + int32 type = 1; + bytes owner_address = 2; +} +message CanDelegatedMaxSizeResponseMessage { + int64 max_size = 1; +} + message CanWithdrawUnfreezeAmountRequestMessage { bytes owner_address = 1; int64 timestamp = 2; From 27cc33babfe98e155d28b2b5e31153e1d6b1a0ae Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 27 Oct 2022 14:54:37 +0800 Subject: [PATCH 0418/1197] feat(net): tron system integrates libp2p module --- .gitignore | 1 - .../tron/common/overlay/message/Message.java | 4 + .../common/overlay/discover/node/Node.java | 135 -------- .../common/parameter/CommonParameter.java | 10 +- framework/build.gradle | 2 + .../common/application/ApplicationImpl.java | 9 +- .../application/TronApplicationContext.java | 12 +- .../org/tron/common/backup/BackupManager.java | 12 +- .../message}/KeepAliveMessage.java | 7 +- .../{net/udp => backup}/message/Message.java | 17 +- .../message/UdpMessageTypeEnum.java | 10 +- .../backup/{ => socket}/BackupServer.java | 12 +- .../socket}/EventHandler.java | 2 +- .../socket}/MessageHandler.java | 2 +- .../socket}/PacketDecoder.java | 4 +- .../handler => backup/socket}/UdpEvent.java | 4 +- .../client/DatabaseGrpcClient.java | 3 +- .../client/WalletGrpcClient.java | 2 +- .../discover/DiscoverMessageInspector.java | 86 ----- .../udp/message/discover/FindNodeMessage.java | 55 --- .../message/discover/NeighborsMessage.java | 77 ----- .../net/udp/message/discover/PingMessage.java | 69 ---- .../net/udp/message/discover/PongMessage.java | 55 --- .../common/overlay/client/PeerClient.java | 99 ------ .../overlay/discover/DiscoverListener.java | 48 --- .../overlay/discover/DiscoverServer.java | 143 -------- .../common/overlay/discover/DiscoverTask.java | 63 ---- .../overlay/discover/DiscoveryExecutor.java | 52 --- .../common/overlay/discover/RefreshTask.java | 37 --- .../common/overlay/discover/dht/Bucket.java | 158 --------- .../common/overlay/discover/dht/DHTUtils.java | 40 --- .../common/overlay/discover/dht/Peer.java | 98 ------ .../common/overlay/discover/node/DBNode.java | 14 - .../overlay/discover/node/DBNodeStats.java | 34 -- .../overlay/discover/node/NodeHandler.java | 305 ----------------- .../overlay/discover/node/NodeManager.java | 314 ------------------ .../node/statistics/NodeStatistics.java | 214 ------------ .../discover/node/statistics/Reputation.java | 48 --- .../discover/table/DistanceComparator.java | 47 --- .../discover/table/KademliaOptions.java | 34 -- .../overlay/discover/table/NodeBucket.java | 75 ----- .../overlay/discover/table/NodeEntry.java | 106 ------ .../overlay/discover/table/NodeTable.java | 131 -------- .../discover/table/TimeComparator.java | 41 --- .../common/overlay/message/MessageCodec.java | 65 ---- .../overlay/message/MessageFactory.java | 22 -- .../common/overlay/message/P2pMessage.java | 34 -- .../overlay/message/P2pMessageFactory.java | 67 ---- .../overlay/message/StaticMessages.java | 10 - .../tron/common/overlay/server/Channel.java | 279 ---------------- .../common/overlay/server/ChannelManager.java | 206 ------------ .../overlay/server/HandshakeHandler.java | 223 ------------- .../common/overlay/server/MessageQueue.java | 217 ------------ .../overlay/server/MessageRoundTrip.java | 39 --- .../common/overlay/server/P2pHandler.java | 103 ------ .../server/PeerConnectionCheckService.java | 65 ---- .../common/overlay/server/PeerServer.java | 84 ----- .../tron/common/overlay/server/SyncPool.java | 265 --------------- .../server/TronChannelInitializer.java | 62 ---- .../TrxProtobufVarint32FrameDecoder.java | 99 ------ .../overlay/server/WireTrafficStats.java | 95 ------ .../src/main/java/org/tron/core/Wallet.java | 30 +- .../java/org/tron/core/config/args/Args.java | 47 ++- .../tron/core/consensus/BlockHandleImpl.java | 2 +- .../org/tron/core/consensus/PbftBaseImpl.java | 17 +- .../tron/core/net/P2pEventHandlerImpl.java | 239 +++++++++++++ .../org/tron/core/net/TronNetDelegate.java | 16 +- .../org/tron/core/net/TronNetHandler.java | 43 --- .../org/tron/core/net/TronNetService.java | 211 +++++------- .../tron/core/net/message/BlocksMessage.java | 43 --- .../net/message/FetchBlockHeadersMessage.java | 17 - .../tron/core/net/message/ItemNotFound.java | 30 -- .../core/net/message/PbftMessageFactory.java | 11 +- .../message/TransactionInventoryMessage.java | 21 -- .../core/net/message/TronMessageFactory.java | 40 ++- .../net/message/{ => adv}/BlockMessage.java | 4 +- .../{ => adv}/FetchInvDataMessage.java | 3 +- .../message/{ => adv}/InventoryMessage.java | 4 +- .../message/{ => adv}/TransactionMessage.java | 4 +- .../{ => adv}/TransactionsMessage.java | 4 +- .../net/message/base}/DisconnectMessage.java | 14 +- .../net/message/handshake}/HelloMessage.java | 26 +- .../net/message/keepalive}/PingMessage.java | 9 +- .../net/message/keepalive}/PongMessage.java | 9 +- .../message/{ => pbft}/PbftCommitMessage.java | 4 +- .../{ => sync}/BlockInventoryMessage.java | 4 +- .../{ => sync}/ChainInventoryMessage.java | 4 +- .../{ => sync}/SyncBlockChainMessage.java | 3 +- .../net/messagehandler/BlockMsgHandler.java | 18 +- .../ChainInventoryMsgHandler.java | 13 +- .../FetchInvDataMsgHandler.java | 33 +- .../messagehandler/InventoryMsgHandler.java | 6 +- .../messagehandler/PbftDataSyncHandler.java | 2 +- .../PbftMsgHandler.java} | 49 +-- .../SyncBlockChainMsgHandler.java | 4 +- .../TransactionsMsgHandler.java | 6 +- .../tron/core/net/peer/PeerConnection.java | 155 +++++++-- .../org/tron/core/net/peer/PeerManager.java | 154 +++++++++ .../org/tron/core/net/peer/TronState.java | 7 + .../tron/core/net/service/RelayService.java | 63 ---- .../net/service/{ => adv}/AdvService.java | 22 +- .../{ => fetchblock}/FetchBlockService.java | 12 +- .../service/handshake/HandshakeService.java | 119 +++++++ .../service/keepalive/KeepAliveService.java | 66 ++++ .../core/net/service/nodepersist/DBNode.java | 24 ++ .../core/net/service/nodepersist/DBNodes.java | 13 + .../nodepersist/NodePersistService.java | 91 +++++ .../net/service/relay/RelayService.java} | 91 +++-- .../net/service}/statistics/MessageCount.java | 4 +- .../statistics/MessageStatistics.java | 70 +--- .../service/statistics/NodeStatistics.java | 54 +++ .../service/statistics/PeerStatistics.java | 5 + .../service/statistics/TronStatsManager.java | 83 +++++ .../net/service/{ => sync}/SyncService.java | 15 +- .../tron/core/services/NodeInfoService.java | 61 ++-- .../org/tron/core/services/RpcApiService.java | 26 +- .../main/java/org/tron/program/FullNode.java | 2 +- .../java/org/tron/program/SolidityNode.java | 13 +- .../discover/node/NodeHandlerTest.java | 100 ------ .../discover/node/NodeManagerTest.java | 226 ------------- .../discover/node/NodeStatisticsTest.java | 150 --------- .../node/statistics/ReputationTest.java | 33 -- .../overlay/discover/table/NodeEntryTest.java | 69 ---- .../overlay/discover/table/NodeTableTest.java | 206 ------------ .../discover/table/TimeComparatorTest.java | 21 -- .../org/tron/common/utils/JsonUtilTest.java | 38 ++- .../test/java/org/tron/core/net/BaseNet.java | 2 +- .../java/org/tron/core/net/BaseNetTest.java | 4 +- .../tron/core/net/DisconnectMessageTest.java | 2 - .../java/org/tron/core/net/MessageTest.java | 2 +- .../test/java/org/tron/core/net/TcpTest.java | 294 ---------------- .../test/java/org/tron/core/net/UdpTest.java | 127 ------- .../messagehandler/BlockMsgHandlerTest.java | 3 +- .../ChainInventoryMsgHandlerTest.java | 2 +- .../InventoryMsgHandlerTest.java | 28 +- .../SyncBlockChainMsgHandlerTest.java | 2 +- .../core/net/services/AdvServiceTest.java | 47 +-- .../core/net/services/RelayServiceTest.java | 18 +- .../org/tron/program/SolidityNodeTest.java | 2 +- 139 files changed, 1502 insertions(+), 6640 deletions(-) delete mode 100644 common/src/main/java/org/tron/common/overlay/discover/node/Node.java rename framework/src/main/java/org/tron/common/{net/udp/message/backup => backup/message}/KeepAliveMessage.java (77%) rename framework/src/main/java/org/tron/common/{net/udp => backup}/message/Message.java (72%) rename framework/src/main/java/org/tron/common/{net/udp => backup}/message/UdpMessageTypeEnum.java (78%) rename framework/src/main/java/org/tron/common/backup/{ => socket}/BackupServer.java (91%) rename framework/src/main/java/org/tron/common/{net/udp/handler => backup/socket}/EventHandler.java (71%) rename framework/src/main/java/org/tron/common/{net/udp/handler => backup/socket}/MessageHandler.java (98%) rename framework/src/main/java/org/tron/common/{net/udp/handler => backup/socket}/PacketDecoder.java (95%) rename framework/src/main/java/org/tron/common/{net/udp/handler => backup/socket}/UdpEvent.java (93%) rename framework/src/main/java/org/tron/common/{overlay => }/client/DatabaseGrpcClient.java (97%) rename framework/src/main/java/org/tron/common/{overlay => }/client/WalletGrpcClient.java (99%) delete mode 100644 framework/src/main/java/org/tron/common/net/udp/message/discover/DiscoverMessageInspector.java delete mode 100755 framework/src/main/java/org/tron/common/net/udp/message/discover/FindNodeMessage.java delete mode 100755 framework/src/main/java/org/tron/common/net/udp/message/discover/NeighborsMessage.java delete mode 100755 framework/src/main/java/org/tron/common/net/udp/message/discover/PingMessage.java delete mode 100755 framework/src/main/java/org/tron/common/net/udp/message/discover/PongMessage.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/client/PeerClient.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/DiscoverListener.java delete mode 100755 framework/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/DiscoverTask.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/DiscoveryExecutor.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/RefreshTask.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/dht/Bucket.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/dht/DHTUtils.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/dht/Peer.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/node/DBNode.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/node/DBNodeStats.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/node/statistics/NodeStatistics.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/node/statistics/Reputation.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/table/DistanceComparator.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/table/KademliaOptions.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/table/NodeBucket.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/table/NodeEntry.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/discover/table/TimeComparator.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/message/MessageCodec.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/message/MessageFactory.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/message/P2pMessage.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/message/P2pMessageFactory.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/message/StaticMessages.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/server/Channel.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/server/MessageRoundTrip.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/server/P2pHandler.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/server/PeerServer.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/server/SyncPool.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/server/TronChannelInitializer.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/server/TrxProtobufVarint32FrameDecoder.java delete mode 100644 framework/src/main/java/org/tron/common/overlay/server/WireTrafficStats.java create mode 100644 framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java delete mode 100644 framework/src/main/java/org/tron/core/net/TronNetHandler.java delete mode 100644 framework/src/main/java/org/tron/core/net/message/BlocksMessage.java delete mode 100644 framework/src/main/java/org/tron/core/net/message/FetchBlockHeadersMessage.java delete mode 100644 framework/src/main/java/org/tron/core/net/message/ItemNotFound.java delete mode 100644 framework/src/main/java/org/tron/core/net/message/TransactionInventoryMessage.java rename framework/src/main/java/org/tron/core/net/message/{ => adv}/BlockMessage.java (92%) rename framework/src/main/java/org/tron/core/net/message/{ => adv}/FetchInvDataMessage.java (88%) rename framework/src/main/java/org/tron/core/net/message/{ => adv}/InventoryMessage.java (94%) rename framework/src/main/java/org/tron/core/net/message/{ => adv}/TransactionMessage.java (91%) rename framework/src/main/java/org/tron/core/net/message/{ => adv}/TransactionsMessage.java (90%) rename framework/src/main/java/org/tron/{common/overlay/message => core/net/message/base}/DisconnectMessage.java (70%) rename framework/src/main/java/org/tron/{common/overlay/message => core/net/message/handshake}/HelloMessage.java (88%) rename framework/src/main/java/org/tron/{common/overlay/message => core/net/message/keepalive}/PingMessage.java (74%) rename framework/src/main/java/org/tron/{common/overlay/message => core/net/message/keepalive}/PongMessage.java (74%) rename framework/src/main/java/org/tron/core/net/message/{ => pbft}/PbftCommitMessage.java (86%) rename framework/src/main/java/org/tron/core/net/message/{ => sync}/BlockInventoryMessage.java (91%) rename framework/src/main/java/org/tron/core/net/message/{ => sync}/ChainInventoryMessage.java (94%) rename framework/src/main/java/org/tron/core/net/message/{ => sync}/SyncBlockChainMessage.java (92%) rename framework/src/main/java/org/tron/core/net/{PbftHandler.java => messagehandler/PbftMsgHandler.java} (56%) create mode 100644 framework/src/main/java/org/tron/core/net/peer/PeerManager.java create mode 100644 framework/src/main/java/org/tron/core/net/peer/TronState.java delete mode 100644 framework/src/main/java/org/tron/core/net/service/RelayService.java rename framework/src/main/java/org/tron/core/net/service/{ => adv}/AdvService.java (95%) rename framework/src/main/java/org/tron/core/net/service/{ => fetchblock}/FetchBlockService.java (94%) create mode 100644 framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java create mode 100644 framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java create mode 100644 framework/src/main/java/org/tron/core/net/service/nodepersist/DBNode.java create mode 100644 framework/src/main/java/org/tron/core/net/service/nodepersist/DBNodes.java create mode 100644 framework/src/main/java/org/tron/core/net/service/nodepersist/NodePersistService.java rename framework/src/main/java/org/tron/{common/overlay/server/FastForward.java => core/net/service/relay/RelayService.java} (67%) rename framework/src/main/java/org/tron/{common/overlay/discover/node => core/net/service}/statistics/MessageCount.java (93%) rename framework/src/main/java/org/tron/{common/overlay/discover/node => core/net/service}/statistics/MessageStatistics.java (78%) create mode 100644 framework/src/main/java/org/tron/core/net/service/statistics/NodeStatistics.java create mode 100644 framework/src/main/java/org/tron/core/net/service/statistics/PeerStatistics.java create mode 100644 framework/src/main/java/org/tron/core/net/service/statistics/TronStatsManager.java rename framework/src/main/java/org/tron/core/net/service/{ => sync}/SyncService.java (96%) delete mode 100644 framework/src/test/java/org/tron/common/overlay/discover/node/NodeHandlerTest.java delete mode 100644 framework/src/test/java/org/tron/common/overlay/discover/node/NodeManagerTest.java delete mode 100644 framework/src/test/java/org/tron/common/overlay/discover/node/NodeStatisticsTest.java delete mode 100644 framework/src/test/java/org/tron/common/overlay/discover/node/statistics/ReputationTest.java delete mode 100644 framework/src/test/java/org/tron/common/overlay/discover/table/NodeEntryTest.java delete mode 100644 framework/src/test/java/org/tron/common/overlay/discover/table/NodeTableTest.java delete mode 100644 framework/src/test/java/org/tron/common/overlay/discover/table/TimeComparatorTest.java delete mode 100644 framework/src/test/java/org/tron/core/net/TcpTest.java delete mode 100644 framework/src/test/java/org/tron/core/net/UdpTest.java diff --git a/.gitignore b/.gitignore index b980800f353..9b19aa5de68 100644 --- a/.gitignore +++ b/.gitignore @@ -31,7 +31,6 @@ shareddata.* # protobuf generated classes src/main/gen - src/main/java/org/tron/core/bftconsensus src/test/java/org/tron/consensus2 src/main/java/META-INF/ diff --git a/chainbase/src/main/java/org/tron/common/overlay/message/Message.java b/chainbase/src/main/java/org/tron/common/overlay/message/Message.java index a0269d0481f..84c3f695686 100644 --- a/chainbase/src/main/java/org/tron/common/overlay/message/Message.java +++ b/chainbase/src/main/java/org/tron/common/overlay/message/Message.java @@ -69,6 +69,10 @@ public ByteBuf getSendData() { return Unpooled.wrappedBuffer(ArrayUtils.add(this.getData(), 0, type)); } + public byte[] getSendBytes() { + return ArrayUtils.add(this.getData(), 0, type); + } + public Sha256Hash getMessageId() { return Sha256Hash.of(CommonParameter.getInstance().isECKeyCryptoEngine(), getData()); diff --git a/common/src/main/java/org/tron/common/overlay/discover/node/Node.java b/common/src/main/java/org/tron/common/overlay/discover/node/Node.java deleted file mode 100644 index 9115b9c9414..00000000000 --- a/common/src/main/java/org/tron/common/overlay/discover/node/Node.java +++ /dev/null @@ -1,135 +0,0 @@ -package org.tron.common.overlay.discover.node; - -import java.io.Serializable; -import java.util.Random; -import lombok.Getter; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; - -@Slf4j(topic = "discover") -public class Node implements Serializable { - - private static final long serialVersionUID = -4267600517925770636L; - - private byte[] id; - - private String host; - - private int port; - - @Getter - private int bindPort; - - @Setter - private int p2pVersion; - - private boolean isFakeNodeId = false; - - public Node(byte[] id, String host, int port) { - this.id = id; - this.host = host; - this.port = port; - this.isFakeNodeId = true; - } - - public Node(byte[] id, String host, int port, int bindPort) { - this.id = id; - this.host = host; - this.port = port; - this.bindPort = bindPort; - } - - public static Node instanceOf(String hostPort) { - try { - String[] sz = hostPort.split(":"); - int port = Integer.parseInt(sz[1]); - return new Node(Node.getNodeId(), sz[0], port); - } catch (Exception e) { - logger.error("Parse node failed, {}", hostPort); - throw e; - } - } - - public static byte[] getNodeId() { - int NODE_ID_LENGTH = 64; - Random gen = new Random(); - byte[] id = new byte[NODE_ID_LENGTH]; - gen.nextBytes(id); - return id; - } - - public boolean isConnectible(int argsP2PVersion) { - return port == bindPort && p2pVersion == argsP2PVersion; - } - - public String getHexId() { - return Hex.toHexString(id); - } - - public String getHexIdShort() { - return Utils.getIdShort(getHexId()); - } - - public boolean isDiscoveryNode() { - return isFakeNodeId; - } - - public byte[] getId() { - return id; - } - - public void setId(byte[] id) { - this.id = id; - } - - public String getHost() { - return host; - } - - public int getPort() { - return port; - } - - public void setPort(int port) { - this.port = port; - } - - public String getIdString() { - if (id == null) { - return null; - } - return new String(id); - } - - @Override - public String toString() { - return "Node{" + " host='" + host + '\'' + ", port=" + port - + ", id=" + ByteArray.toHexString(id) + '}'; - } - - @Override - public int hashCode() { - return this.toString().hashCode(); - } - - @Override - public boolean equals(Object o) { - if (o == null) { - return false; - } - - if (o == this) { - return true; - } - - if (o.getClass() == getClass()) { - return StringUtils.equals(getIdString(), ((Node) o).getIdString()); - } - - return false; - } -} diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index accf4766ea4..870c697473c 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -1,6 +1,9 @@ package org.tron.common.parameter; import com.beust.jcommander.Parameter; + +import java.net.InetAddress; +import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -11,7 +14,6 @@ import org.tron.common.config.DbBackupConfig; import org.tron.common.logsfilter.EventPluginConfig; import org.tron.common.logsfilter.FilterQuery; -import org.tron.common.overlay.discover.node.Node; import org.tron.common.setting.RocksDbSettings; import org.tron.core.Constant; import org.tron.core.config.args.Overlay; @@ -390,12 +392,12 @@ public class CommonParameter { public GenesisBlock genesisBlock; @Getter @Setter - public List activeNodes; + public List activeNodes; @Getter @Setter - public List passiveNodes; + public List passiveNodes; @Getter - public List fastForwardNodes; + public List fastForwardNodes; @Getter public int maxFastForwardNum; @Getter diff --git a/framework/build.gradle b/framework/build.gradle index 7df08a90eb9..9e1e57413ea 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -44,6 +44,8 @@ dependencies { testCompile group: 'org.testng', name: 'testng', version: '6.14.3' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.1.3' + compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' compile group: 'com.typesafe', name: 'config', version: '1.3.2' diff --git a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java index 1be119f1be3..235ece75835 100644 --- a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java +++ b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java @@ -12,6 +12,7 @@ import org.tron.core.metrics.MetricsUtil; import org.tron.core.net.TronNetService; import org.tron.program.FullNode; +import org.tron.program.SolidityNode; @Slf4j(topic = "app") @Component @@ -56,7 +57,9 @@ public void initServices(CommonParameter parameter) { * start up the app. */ public void startup() { - tronNetService.start(); + if (!Args.getInstance().isSolidityNode()) { + tronNetService.start(); + } consensusService.start(); MetricsUtil.init(); } @@ -64,7 +67,9 @@ public void startup() { @Override public void shutdown() { logger.info("******** start to shutdown ********"); - tronNetService.stop(); + if (!Args.getInstance().isSolidityNode()) { + tronNetService.close(); + } consensusService.stop(); synchronized (dbManager.getRevokingStore()) { dbManager.getSession().reset(); diff --git a/framework/src/main/java/org/tron/common/application/TronApplicationContext.java b/framework/src/main/java/org/tron/common/application/TronApplicationContext.java index 204b5dc5a68..7f0aea813a3 100644 --- a/framework/src/main/java/org/tron/common/application/TronApplicationContext.java +++ b/framework/src/main/java/org/tron/common/application/TronApplicationContext.java @@ -2,10 +2,8 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.tron.common.overlay.discover.DiscoverServer; -import org.tron.common.overlay.discover.node.NodeManager; -import org.tron.common.overlay.server.ChannelManager; import org.tron.core.db.Manager; +import org.tron.core.net.TronNetService; public class TronApplicationContext extends AnnotationConfigApplicationContext { @@ -31,12 +29,8 @@ public void destroy() { appT.shutdownServices(); appT.shutdown(); - DiscoverServer discoverServer = getBean(DiscoverServer.class); - discoverServer.close(); - ChannelManager channelManager = getBean(ChannelManager.class); - channelManager.close(); - NodeManager nodeManager = getBean(NodeManager.class); - nodeManager.close(); + TronNetService tronNetService = getBean(TronNetService.class); + tronNetService.close(); Manager dbManager = getBean(Manager.class); dbManager.stopRePushThread(); diff --git a/framework/src/main/java/org/tron/common/backup/BackupManager.java b/framework/src/main/java/org/tron/common/backup/BackupManager.java index 1d78dd234ad..ef304164f1a 100644 --- a/framework/src/main/java/org/tron/common/backup/BackupManager.java +++ b/framework/src/main/java/org/tron/common/backup/BackupManager.java @@ -3,7 +3,7 @@ import static org.tron.common.backup.BackupManager.BackupStatusEnum.INIT; import static org.tron.common.backup.BackupManager.BackupStatusEnum.MASTER; import static org.tron.common.backup.BackupManager.BackupStatusEnum.SLAVER; -import static org.tron.common.net.udp.message.UdpMessageTypeEnum.BACKUP_KEEP_ALIVE; +import static org.tron.common.backup.message.UdpMessageTypeEnum.BACKUP_KEEP_ALIVE; import io.netty.util.internal.ConcurrentSet; import java.net.InetAddress; @@ -14,11 +14,11 @@ import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import org.tron.common.net.udp.handler.EventHandler; -import org.tron.common.net.udp.handler.MessageHandler; -import org.tron.common.net.udp.handler.UdpEvent; -import org.tron.common.net.udp.message.Message; -import org.tron.common.net.udp.message.backup.KeepAliveMessage; +import org.tron.common.backup.message.KeepAliveMessage; +import org.tron.common.backup.message.Message; +import org.tron.common.backup.socket.EventHandler; +import org.tron.common.backup.socket.MessageHandler; +import org.tron.common.backup.socket.UdpEvent; import org.tron.common.parameter.CommonParameter; @Slf4j(topic = "backup") diff --git a/framework/src/main/java/org/tron/common/net/udp/message/backup/KeepAliveMessage.java b/framework/src/main/java/org/tron/common/backup/message/KeepAliveMessage.java similarity index 77% rename from framework/src/main/java/org/tron/common/net/udp/message/backup/KeepAliveMessage.java rename to framework/src/main/java/org/tron/common/backup/message/KeepAliveMessage.java index 7e3ed37684a..fca63451107 100644 --- a/framework/src/main/java/org/tron/common/net/udp/message/backup/KeepAliveMessage.java +++ b/framework/src/main/java/org/tron/common/backup/message/KeepAliveMessage.java @@ -1,9 +1,8 @@ -package org.tron.common.net.udp.message.backup; +package org.tron.common.backup.message; -import static org.tron.common.net.udp.message.UdpMessageTypeEnum.BACKUP_KEEP_ALIVE; +import static org.tron.common.backup.message.UdpMessageTypeEnum.BACKUP_KEEP_ALIVE; -import org.tron.common.net.udp.message.Message; -import org.tron.common.overlay.discover.node.Node; +import org.tron.p2p.discover.Node; import org.tron.protos.Discover; public class KeepAliveMessage extends Message { diff --git a/framework/src/main/java/org/tron/common/net/udp/message/Message.java b/framework/src/main/java/org/tron/common/backup/message/Message.java similarity index 72% rename from framework/src/main/java/org/tron/common/net/udp/message/Message.java rename to framework/src/main/java/org/tron/common/backup/message/Message.java index bda851f9a5f..8f09a452877 100644 --- a/framework/src/main/java/org/tron/common/net/udp/message/Message.java +++ b/framework/src/main/java/org/tron/common/backup/message/Message.java @@ -1,16 +1,11 @@ -package org.tron.common.net.udp.message; +package org.tron.common.backup.message; import org.apache.commons.lang3.ArrayUtils; -import org.tron.common.net.udp.message.backup.KeepAliveMessage; -import org.tron.common.net.udp.message.discover.FindNodeMessage; -import org.tron.common.net.udp.message.discover.NeighborsMessage; -import org.tron.common.net.udp.message.discover.PingMessage; -import org.tron.common.net.udp.message.discover.PongMessage; -import org.tron.common.overlay.discover.node.Node; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; import org.tron.core.exception.P2pException; +import org.tron.p2p.discover.Node; import org.tron.protos.Discover.Endpoint; public abstract class Message { @@ -33,14 +28,6 @@ public static Message parse(byte[] encode) throws Exception { byte type = encode[0]; byte[] data = ArrayUtils.subarray(encode, 1, encode.length); switch (UdpMessageTypeEnum.fromByte(type)) { - case DISCOVER_PING: - return new PingMessage(data); - case DISCOVER_PONG: - return new PongMessage(data); - case DISCOVER_FIND_NODE: - return new FindNodeMessage(data); - case DISCOVER_NEIGHBORS: - return new NeighborsMessage(data); case BACKUP_KEEP_ALIVE: return new KeepAliveMessage(data); default: diff --git a/framework/src/main/java/org/tron/common/net/udp/message/UdpMessageTypeEnum.java b/framework/src/main/java/org/tron/common/backup/message/UdpMessageTypeEnum.java similarity index 78% rename from framework/src/main/java/org/tron/common/net/udp/message/UdpMessageTypeEnum.java rename to framework/src/main/java/org/tron/common/backup/message/UdpMessageTypeEnum.java index 1af4aa882d5..d4a5a9dd64b 100644 --- a/framework/src/main/java/org/tron/common/net/udp/message/UdpMessageTypeEnum.java +++ b/framework/src/main/java/org/tron/common/backup/message/UdpMessageTypeEnum.java @@ -1,18 +1,10 @@ -package org.tron.common.net.udp.message; +package org.tron.common.backup.message; import java.util.HashMap; import java.util.Map; public enum UdpMessageTypeEnum { - DISCOVER_PING((byte) 0x01), - - DISCOVER_PONG((byte) 0x02), - - DISCOVER_FIND_NODE((byte) 0x03), - - DISCOVER_NEIGHBORS((byte) 0x04), - BACKUP_KEEP_ALIVE((byte) 0x05), UNKNOWN((byte) 0xFF); diff --git a/framework/src/main/java/org/tron/common/backup/BackupServer.java b/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java similarity index 91% rename from framework/src/main/java/org/tron/common/backup/BackupServer.java rename to framework/src/main/java/org/tron/common/backup/socket/BackupServer.java index f95191a295d..e3b1de31736 100644 --- a/framework/src/main/java/org/tron/common/backup/BackupServer.java +++ b/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java @@ -1,4 +1,4 @@ -package org.tron.common.backup; +package org.tron.common.backup.socket; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; @@ -11,10 +11,9 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.common.net.udp.handler.MessageHandler; -import org.tron.common.net.udp.handler.PacketDecoder; -import org.tron.common.overlay.server.WireTrafficStats; +import org.tron.common.backup.BackupManager; import org.tron.common.parameter.CommonParameter; +import org.tron.p2p.stats.TrafficStats; @Slf4j(topic = "backup") @Component @@ -30,9 +29,6 @@ public class BackupServer { private volatile boolean shutdown = false; - @Autowired - private WireTrafficStats stats; - @Autowired public BackupServer(final BackupManager backupManager) { this.backupManager = backupManager; @@ -61,7 +57,7 @@ private void start() throws Exception { @Override public void initChannel(NioDatagramChannel ch) throws Exception { - ch.pipeline().addLast(stats.udp); + ch.pipeline().addLast(TrafficStats.udp); ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender()); ch.pipeline().addLast(new ProtobufVarint32FrameDecoder()); ch.pipeline().addLast(new PacketDecoder()); diff --git a/framework/src/main/java/org/tron/common/net/udp/handler/EventHandler.java b/framework/src/main/java/org/tron/common/backup/socket/EventHandler.java similarity index 71% rename from framework/src/main/java/org/tron/common/net/udp/handler/EventHandler.java rename to framework/src/main/java/org/tron/common/backup/socket/EventHandler.java index db7ddae9d35..699d4cc0cba 100644 --- a/framework/src/main/java/org/tron/common/net/udp/handler/EventHandler.java +++ b/framework/src/main/java/org/tron/common/backup/socket/EventHandler.java @@ -1,4 +1,4 @@ -package org.tron.common.net.udp.handler; +package org.tron.common.backup.socket; public interface EventHandler { diff --git a/framework/src/main/java/org/tron/common/net/udp/handler/MessageHandler.java b/framework/src/main/java/org/tron/common/backup/socket/MessageHandler.java similarity index 98% rename from framework/src/main/java/org/tron/common/net/udp/handler/MessageHandler.java rename to framework/src/main/java/org/tron/common/backup/socket/MessageHandler.java index 656dd9fb667..81ad88c6547 100644 --- a/framework/src/main/java/org/tron/common/net/udp/handler/MessageHandler.java +++ b/framework/src/main/java/org/tron/common/backup/socket/MessageHandler.java @@ -16,7 +16,7 @@ * along with the ethereumJ library. If not, see . */ -package org.tron.common.net.udp.handler; +package org.tron.common.backup.socket; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; diff --git a/framework/src/main/java/org/tron/common/net/udp/handler/PacketDecoder.java b/framework/src/main/java/org/tron/common/backup/socket/PacketDecoder.java similarity index 95% rename from framework/src/main/java/org/tron/common/net/udp/handler/PacketDecoder.java rename to framework/src/main/java/org/tron/common/backup/socket/PacketDecoder.java index 4859dcd04f6..4a66bf3253b 100644 --- a/framework/src/main/java/org/tron/common/net/udp/handler/PacketDecoder.java +++ b/framework/src/main/java/org/tron/common/backup/socket/PacketDecoder.java @@ -16,7 +16,7 @@ * along with the ethereumJ library. If not, see . */ -package org.tron.common.net.udp.handler; +package org.tron.common.backup.socket; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; @@ -24,7 +24,7 @@ import io.netty.handler.codec.MessageToMessageDecoder; import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.tron.common.net.udp.message.Message; +import org.tron.common.backup.message.Message; @Slf4j(topic = "net") public class PacketDecoder extends MessageToMessageDecoder { diff --git a/framework/src/main/java/org/tron/common/net/udp/handler/UdpEvent.java b/framework/src/main/java/org/tron/common/backup/socket/UdpEvent.java similarity index 93% rename from framework/src/main/java/org/tron/common/net/udp/handler/UdpEvent.java rename to framework/src/main/java/org/tron/common/backup/socket/UdpEvent.java index 969dcd0e1c7..f9755d15781 100644 --- a/framework/src/main/java/org/tron/common/net/udp/handler/UdpEvent.java +++ b/framework/src/main/java/org/tron/common/backup/socket/UdpEvent.java @@ -16,10 +16,10 @@ * along with the ethereumJ library. If not, see . */ -package org.tron.common.net.udp.handler; +package org.tron.common.backup.socket; import java.net.InetSocketAddress; -import org.tron.common.net.udp.message.Message; +import org.tron.common.backup.message.Message; public class UdpEvent { diff --git a/framework/src/main/java/org/tron/common/overlay/client/DatabaseGrpcClient.java b/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java similarity index 97% rename from framework/src/main/java/org/tron/common/overlay/client/DatabaseGrpcClient.java rename to framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java index 7a2da659275..b83c7235900 100644 --- a/framework/src/main/java/org/tron/common/overlay/client/DatabaseGrpcClient.java +++ b/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java @@ -1,4 +1,4 @@ -package org.tron.common.overlay.client; +package org.tron.common.client; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; @@ -27,7 +27,6 @@ public DatabaseGrpcClient(String host) { databaseBlockingStub = DatabaseGrpc.newBlockingStub(channel); } - public Block getBlock(long blockNum) { if (blockNum < 0) { return databaseBlockingStub.getNowBlock(EmptyMessage.newBuilder().build()); diff --git a/framework/src/main/java/org/tron/common/overlay/client/WalletGrpcClient.java b/framework/src/main/java/org/tron/common/client/WalletGrpcClient.java similarity index 99% rename from framework/src/main/java/org/tron/common/overlay/client/WalletGrpcClient.java rename to framework/src/main/java/org/tron/common/client/WalletGrpcClient.java index 6bff4810eec..9d3b5797e20 100644 --- a/framework/src/main/java/org/tron/common/overlay/client/WalletGrpcClient.java +++ b/framework/src/main/java/org/tron/common/client/WalletGrpcClient.java @@ -1,4 +1,4 @@ -package org.tron.common.overlay.client; +package org.tron.common.client; import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; diff --git a/framework/src/main/java/org/tron/common/net/udp/message/discover/DiscoverMessageInspector.java b/framework/src/main/java/org/tron/common/net/udp/message/discover/DiscoverMessageInspector.java deleted file mode 100644 index 6c8afdd5625..00000000000 --- a/framework/src/main/java/org/tron/common/net/udp/message/discover/DiscoverMessageInspector.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.tron.common.net.udp.message.discover; - -import java.util.regex.Pattern; -import org.springframework.util.StringUtils; -import org.tron.common.net.udp.message.Message; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.overlay.discover.table.KademliaOptions; - -public class DiscoverMessageInspector { - - public static final Pattern PATTERN_IP = - Pattern.compile("^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\" - + ".(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\" - + ".(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\" - + ".(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$"); - - private static boolean isFound(String str, Pattern pattern) { - if (str == null || pattern == null) { - return false; - } - return pattern.matcher(str).find(); - } - - private static boolean validNode(Node node) { - if (node == null) { - return false; - } - if (!isFound(node.getHost(), PATTERN_IP) - || node.getId().length != KademliaOptions.NODE_ID_LEN) { - return false; - } - return true; - } - - private static boolean valid(PingMessage message) { - return validNode(message.getFrom()) && validNode(message.getTo()); - } - - private static boolean valid(PongMessage message) { - return validNode(message.getFrom()); - } - - private static boolean valid(FindNodeMessage message) { - return validNode(message.getFrom()) - && message.getTargetId().length == KademliaOptions.NODE_ID_LEN; - } - - private static boolean valid(NeighborsMessage message) { - if (!validNode(message.getFrom())) { - return false; - } - if (!StringUtils.isEmpty(message.getNodes())) { - if (message.getNodes().size() > KademliaOptions.BUCKET_SIZE) { - return false; - } - for (Node node : message.getNodes()) { - if (!validNode(node)) { - return false; - } - } - } - return true; - } - - public static boolean valid(Message message) { - boolean flag = false; - switch (message.getType()) { - case DISCOVER_PING: - flag = valid((PingMessage) message); - break; - case DISCOVER_PONG: - flag = valid((PongMessage) message); - break; - case DISCOVER_FIND_NODE: - flag = valid((FindNodeMessage) message); - break; - case DISCOVER_NEIGHBORS: - flag = valid((NeighborsMessage) message); - break; - default: - break; - } - return flag; - } - -} diff --git a/framework/src/main/java/org/tron/common/net/udp/message/discover/FindNodeMessage.java b/framework/src/main/java/org/tron/common/net/udp/message/discover/FindNodeMessage.java deleted file mode 100755 index 1507366a9c5..00000000000 --- a/framework/src/main/java/org/tron/common/net/udp/message/discover/FindNodeMessage.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.tron.common.net.udp.message.discover; - -import static org.tron.common.net.udp.message.UdpMessageTypeEnum.DISCOVER_FIND_NODE; - -import com.google.protobuf.ByteString; -import org.tron.common.net.udp.message.Message; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.utils.ByteArray; -import org.tron.protos.Discover; -import org.tron.protos.Discover.Endpoint; -import org.tron.protos.Discover.FindNeighbours; - -public class FindNodeMessage extends Message { - - private Discover.FindNeighbours findNeighbours; - - public FindNodeMessage(byte[] data) throws Exception { - super(DISCOVER_FIND_NODE, data); - this.findNeighbours = Discover.FindNeighbours.parseFrom(data); - } - - public FindNodeMessage(Node from, byte[] targetId) { - super(DISCOVER_FIND_NODE, null); - Endpoint fromEndpoint = Endpoint.newBuilder() - .setAddress(ByteString.copyFrom(ByteArray.fromString(from.getHost()))) - .setPort(from.getPort()) - .setNodeId(ByteString.copyFrom(from.getId())) - .build(); - this.findNeighbours = FindNeighbours.newBuilder() - .setFrom(fromEndpoint) - .setTargetId(ByteString.copyFrom(targetId)) - .setTimestamp(System.currentTimeMillis()) - .build(); - this.data = this.findNeighbours.toByteArray(); - } - - public byte[] getTargetId() { - return this.findNeighbours.getTargetId().toByteArray(); - } - - @Override - public long getTimestamp() { - return this.findNeighbours.getTimestamp(); - } - - @Override - public Node getFrom() { - return Message.getNode(findNeighbours.getFrom()); - } - - @Override - public String toString() { - return "[findNeighbours: " + findNeighbours; - } -} diff --git a/framework/src/main/java/org/tron/common/net/udp/message/discover/NeighborsMessage.java b/framework/src/main/java/org/tron/common/net/udp/message/discover/NeighborsMessage.java deleted file mode 100755 index 61f7bddd18e..00000000000 --- a/framework/src/main/java/org/tron/common/net/udp/message/discover/NeighborsMessage.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.tron.common.net.udp.message.discover; - -import static org.tron.common.net.udp.message.UdpMessageTypeEnum.DISCOVER_NEIGHBORS; - -import com.google.protobuf.ByteString; -import java.util.ArrayList; -import java.util.List; -import org.tron.common.net.udp.message.Message; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.utils.ByteArray; -import org.tron.protos.Discover; -import org.tron.protos.Discover.Endpoint; -import org.tron.protos.Discover.Neighbours; -import org.tron.protos.Discover.Neighbours.Builder; - -public class NeighborsMessage extends Message { - - private Discover.Neighbours neighbours; - - public NeighborsMessage(byte[] data) throws Exception { - super(DISCOVER_NEIGHBORS, data); - this.neighbours = Discover.Neighbours.parseFrom(data); - } - - public NeighborsMessage(Node from, List neighbours, long sequence) { - super(DISCOVER_NEIGHBORS, null); - Builder builder = Neighbours.newBuilder() - .setTimestamp(sequence); - - neighbours.forEach(neighbour -> { - Endpoint endpoint = Endpoint.newBuilder() - .setAddress(ByteString.copyFrom(ByteArray.fromString(neighbour.getHost()))) - .setPort(neighbour.getPort()) - .setNodeId(ByteString.copyFrom(neighbour.getId())) - .build(); - - builder.addNeighbours(endpoint); - }); - - Endpoint fromEndpoint = Endpoint.newBuilder() - .setAddress(ByteString.copyFrom(ByteArray.fromString(from.getHost()))) - .setPort(from.getPort()) - .setNodeId(ByteString.copyFrom(from.getId())) - .build(); - - builder.setFrom(fromEndpoint); - - this.neighbours = builder.build(); - - this.data = this.neighbours.toByteArray(); - } - - public List getNodes() { - List nodes = new ArrayList<>(); - neighbours.getNeighboursList().forEach(neighbour -> nodes.add( - new Node(neighbour.getNodeId().toByteArray(), - ByteArray.toStr(neighbour.getAddress().toByteArray()), - neighbour.getPort()))); - return nodes; - } - - @Override - public long getTimestamp() { - return this.neighbours.getTimestamp(); - } - - @Override - public Node getFrom() { - return Message.getNode(neighbours.getFrom()); - } - - @Override - public String toString() { - return "[neighbours: " + neighbours; - } - -} diff --git a/framework/src/main/java/org/tron/common/net/udp/message/discover/PingMessage.java b/framework/src/main/java/org/tron/common/net/udp/message/discover/PingMessage.java deleted file mode 100755 index e7510414163..00000000000 --- a/framework/src/main/java/org/tron/common/net/udp/message/discover/PingMessage.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.tron.common.net.udp.message.discover; - -import static org.tron.common.net.udp.message.UdpMessageTypeEnum.DISCOVER_PING; - -import com.google.protobuf.ByteString; -import org.tron.common.net.udp.message.Message; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.utils.ByteArray; -import org.tron.core.config.args.Args; -import org.tron.protos.Discover; -import org.tron.protos.Discover.Endpoint; - -public class PingMessage extends Message { - - private Discover.PingMessage pingMessage; - - public PingMessage(byte[] data) throws Exception { - super(DISCOVER_PING, data); - this.pingMessage = Discover.PingMessage.parseFrom(data); - } - - public PingMessage(Node from, Node to) { - super(DISCOVER_PING, null); - Endpoint fromEndpoint = Endpoint.newBuilder() - .setNodeId(ByteString.copyFrom(from.getId())) - .setPort(from.getPort()) - .setAddress(ByteString.copyFrom(ByteArray.fromString(from.getHost()))) - .build(); - Endpoint toEndpoint = Endpoint.newBuilder() - .setNodeId(ByteString.copyFrom(to.getId())) - .setPort(to.getPort()) - .setAddress(ByteString.copyFrom(ByteArray.fromString(to.getHost()))) - .build(); - this.pingMessage = Discover.PingMessage.newBuilder() - .setVersion(Args.getInstance().getNodeP2pVersion()) - .setFrom(fromEndpoint) - .setTo(toEndpoint) - .setTimestamp(System.currentTimeMillis()) - .build(); - this.data = this.pingMessage.toByteArray(); - } - - public int getVersion() { - return this.pingMessage.getVersion(); - } - - public Node getTo() { - Endpoint to = this.pingMessage.getTo(); - Node node = new Node(to.getNodeId().toByteArray(), - ByteArray.toStr(to.getAddress().toByteArray()), to.getPort()); - return node; - } - - @Override - public long getTimestamp() { - return this.pingMessage.getTimestamp(); - } - - @Override - public Node getFrom() { - return Message.getNode(pingMessage.getFrom()); - } - - @Override - public String toString() { - return "[pingMessage: " + pingMessage; - } - -} diff --git a/framework/src/main/java/org/tron/common/net/udp/message/discover/PongMessage.java b/framework/src/main/java/org/tron/common/net/udp/message/discover/PongMessage.java deleted file mode 100755 index 735434966ef..00000000000 --- a/framework/src/main/java/org/tron/common/net/udp/message/discover/PongMessage.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.tron.common.net.udp.message.discover; - -import static org.tron.common.net.udp.message.UdpMessageTypeEnum.DISCOVER_PONG; - -import com.google.protobuf.ByteString; -import org.tron.common.net.udp.message.Message; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.utils.ByteArray; -import org.tron.core.config.args.Args; -import org.tron.protos.Discover; -import org.tron.protos.Discover.Endpoint; - -public class PongMessage extends Message { - - private Discover.PongMessage pongMessage; - - public PongMessage(byte[] data) throws Exception { - super(DISCOVER_PONG, data); - this.pongMessage = Discover.PongMessage.parseFrom(data); - } - - public PongMessage(Node from) { - super(DISCOVER_PONG, null); - Endpoint toEndpoint = Endpoint.newBuilder() - .setAddress(ByteString.copyFrom(ByteArray.fromString(from.getHost()))) - .setPort(from.getPort()) - .setNodeId(ByteString.copyFrom(from.getId())) - .build(); - this.pongMessage = Discover.PongMessage.newBuilder() - .setFrom(toEndpoint) - .setEcho(Args.getInstance().getNodeP2pVersion()) - .setTimestamp(System.currentTimeMillis()) - .build(); - this.data = this.pongMessage.toByteArray(); - } - - public int getVersion() { - return this.pongMessage.getEcho(); - } - - @Override - public long getTimestamp() { - return this.pongMessage.getTimestamp(); - } - - @Override - public Node getFrom() { - return Message.getNode(pongMessage.getFrom()); - } - - @Override - public String toString() { - return "[pongMessage: " + pongMessage; - } -} diff --git a/framework/src/main/java/org/tron/common/overlay/client/PeerClient.java b/framework/src/main/java/org/tron/common/overlay/client/PeerClient.java deleted file mode 100644 index d6a8b224c84..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/client/PeerClient.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.tron.common.overlay.client; - -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelOption; -import io.netty.channel.DefaultMessageSizeEstimator; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.stereotype.Component; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.overlay.discover.node.NodeHandler; -import org.tron.common.overlay.server.TronChannelInitializer; -import org.tron.core.config.args.Args; -import org.tron.protos.Protocol.ReasonCode; - -@Slf4j(topic = "net") -@Component -public class PeerClient { - - @Autowired - private ApplicationContext ctx; - - private EventLoopGroup workerGroup; - - public PeerClient() { - workerGroup = new NioEventLoopGroup(0, new ThreadFactory() { - private AtomicInteger cnt = new AtomicInteger(0); - - @Override - public Thread newThread(Runnable r) { - return new Thread(r, "TronJClientWorker-" + cnt.getAndIncrement()); - } - }); - } - - public void connect(String host, int port, String remoteId) { - try { - ChannelFuture f = connectAsync(host, port, remoteId, false); - f.sync().channel().closeFuture().sync(); - } catch (Exception e) { - logger.warn("Can't connect to {}:{}, cause:{})", host, port, e.getMessage()); - } - } - - public void connectAsync(NodeHandler nodeHandler, boolean discoveryMode) { - Node node = nodeHandler.getNode(); - try { - connectAsync(node.getHost(), node.getPort(), node.getHexId(), discoveryMode) - .addListener((ChannelFutureListener) future -> { - if (!future.isSuccess()) { - logger.warn("Connect to {}:{} fail, cause:{}", node.getHost(), node.getPort(), - future.cause().getMessage()); - nodeHandler.getNodeStatistics().nodeDisconnectedLocal(ReasonCode.CONNECT_FAIL); - nodeHandler.getNodeStatistics().notifyDisconnect(); - future.channel().close(); - } - }); - } catch (Exception e) { - logger.warn("Connect to peer {} failed, reason: {}", - node.getHost(), e.getMessage()); - } - } - - private ChannelFuture connectAsync(String host, int port, String remoteId, - boolean discoveryMode) { - - logger.info("Connect peer {}:{}, remoteId:{}", host, port, remoteId); - - TronChannelInitializer tronChannelInitializer = ctx - .getBean(TronChannelInitializer.class, remoteId); - tronChannelInitializer.setPeerDiscoveryMode(discoveryMode); - - Bootstrap b = new Bootstrap(); - b.group(workerGroup); - b.channel(NioSocketChannel.class); - - b.option(ChannelOption.SO_KEEPALIVE, true); - b.option(ChannelOption.MESSAGE_SIZE_ESTIMATOR, DefaultMessageSizeEstimator.DEFAULT); - b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, Args.getInstance().getNodeConnectionTimeout()); - b.remoteAddress(host, port); - - b.handler(tronChannelInitializer); - - // Start the client. - return b.connect(); - } - - public void close() { - workerGroup.shutdownGracefully(); - workerGroup.terminationFuture().syncUninterruptibly(); - } -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/DiscoverListener.java b/framework/src/main/java/org/tron/common/overlay/discover/DiscoverListener.java deleted file mode 100644 index e5760dbc2c6..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/DiscoverListener.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.discover; - -import org.tron.common.overlay.discover.node.NodeHandler; -import org.tron.common.overlay.discover.node.NodeManager; - -/** - * Allows to handle discovered nodes state changes Created by Anton Nashatyrev on 21.07.2015. - */ -public interface DiscoverListener { - - /** - * Invoked whenever a new node appeared which meets criteria specified in the {@link - * NodeManager#addDiscoverListener} method - */ - void nodeAppeared(NodeHandler handler); - - /** - * Invoked whenever a node stops meeting criteria. - */ - void nodeDisappeared(NodeHandler handler); - - class Adapter implements DiscoverListener { - - public void nodeAppeared(NodeHandler handler) { - } - - public void nodeDisappeared(NodeHandler handler) { - } - } -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java b/framework/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java deleted file mode 100755 index ce8d577caf2..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.discover; - -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioDatagramChannel; -import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder; -import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.common.net.udp.handler.MessageHandler; -import org.tron.common.net.udp.handler.PacketDecoder; -import org.tron.common.overlay.discover.node.NodeManager; -import org.tron.common.overlay.server.WireTrafficStats; -import org.tron.common.parameter.CommonParameter; -import org.tron.core.config.args.Args; - -@Slf4j(topic = "discover") -@Component -public class DiscoverServer { - - @Autowired - private NodeManager nodeManager; - - @Autowired - private WireTrafficStats stats; - - private CommonParameter parameter = Args.getInstance(); - - private int port = parameter.getNodeListenPort(); - - private Channel channel; - - private DiscoveryExecutor discoveryExecutor; - - private volatile boolean shutdown = false; - - @Autowired - public DiscoverServer(final NodeManager nodeManager) { - this.nodeManager = nodeManager; - if (parameter.isNodeDiscoveryEnable() && !parameter.isFastForward() - && !parameter.isSolidityNode()) { - if (port == 0) { - logger.error("Discovery can't be started while listen port == 0"); - } else { - new Thread(() -> { - try { - start(); - } catch (Exception e) { - logger.error("Discovery server start failed", e); - } - }, "DiscoverServer").start(); - } - } - } - - public void start() throws Exception { - NioEventLoopGroup group = new NioEventLoopGroup(parameter.getUdpNettyWorkThreadNum()); - try { - discoveryExecutor = new DiscoveryExecutor(nodeManager); - discoveryExecutor.start(); - while (!shutdown) { - Bootstrap b = new Bootstrap(); - b.group(group) - .channel(NioDatagramChannel.class) - .handler(new ChannelInitializer() { - @Override - public void initChannel(NioDatagramChannel ch) - throws Exception { - ch.pipeline().addLast(stats.udp); - ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender()); - ch.pipeline().addLast(new ProtobufVarint32FrameDecoder()); - ch.pipeline().addLast(new PacketDecoder()); - MessageHandler messageHandler = new MessageHandler(ch, nodeManager); - nodeManager.setMessageSender(messageHandler); - ch.pipeline().addLast(messageHandler); - } - }); - - channel = b.bind(port).sync().channel(); - - logger.info("Discovery server started, bind port {}", port); - - channel.closeFuture().sync(); - if (shutdown) { - logger.info("Shutdown discovery server"); - break; - } - logger.warn("Restart discovery server after 5 sec pause..."); - Thread.sleep(5000); - } - } catch (InterruptedException e) { - logger.warn("Discover server interrupted"); - Thread.currentThread().interrupt(); - } catch (Exception e) { - logger.error("Start discovery server with port {} failed", port, e); - } finally { - group.shutdownGracefully().sync(); - } - } - - public void close() { - logger.info("Closing discovery server..."); - shutdown = true; - if (channel != null) { - try { - channel.close().await(10, TimeUnit.SECONDS); - } catch (Exception e) { - logger.error("Closing discovery server failed", e); - } - } - - if (discoveryExecutor != null) { - try { - discoveryExecutor.close(); - } catch (Exception e) { - logger.error("Closing discovery executor failed", e); - } - } - } - -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/DiscoverTask.java b/framework/src/main/java/org/tron/common/overlay/discover/DiscoverTask.java deleted file mode 100644 index 8f105b6ee89..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/DiscoverTask.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.tron.common.overlay.discover; - -import java.util.ArrayList; -import java.util.List; -import lombok.extern.slf4j.Slf4j; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.overlay.discover.node.NodeManager; -import org.tron.common.overlay.discover.table.KademliaOptions; - -@Slf4j(topic = "discover") -public class DiscoverTask implements Runnable { - - private NodeManager nodeManager; - - private byte[] nodeId; - - public DiscoverTask(NodeManager nodeManager) { - this.nodeManager = nodeManager; - this.nodeId = nodeManager.getPublicHomeNode().getId(); - } - - @Override - public void run() { - discover(nodeId, 0, new ArrayList<>()); - } - - public synchronized void discover(byte[] nodeId, int round, List prevTried) { - - try { - if (round == KademliaOptions.MAX_STEPS) { - return; - } - - List closest = nodeManager.getTable().getClosestNodes(nodeId); - List tried = new ArrayList<>(); - for (Node n : closest) { - if (!tried.contains(n) && !prevTried.contains(n)) { - try { - nodeManager.getNodeHandler(n).sendFindNode(nodeId); - tried.add(n); - wait(50); - } catch (Exception ex) { - logger.error("Unexpected Exception", ex); - } - } - if (tried.size() == KademliaOptions.ALPHA) { - break; - } - } - - if (tried.isEmpty()) { - return; - } - - tried.addAll(prevTried); - - discover(nodeId, round + 1, tried); - } catch (Exception ex) { - logger.error("{}", ex); - } - } - -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/DiscoveryExecutor.java b/framework/src/main/java/org/tron/common/overlay/discover/DiscoveryExecutor.java deleted file mode 100644 index c15a362f9de..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/DiscoveryExecutor.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.discover; - -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import org.tron.common.overlay.discover.node.NodeManager; -import org.tron.common.overlay.discover.table.KademliaOptions; - -public class DiscoveryExecutor { - - private ScheduledExecutorService discoverer = Executors.newSingleThreadScheduledExecutor(); - private ScheduledExecutorService refresher = Executors.newSingleThreadScheduledExecutor(); - - private NodeManager nodeManager; - - public DiscoveryExecutor(NodeManager nodeManager) { - this.nodeManager = nodeManager; - } - - public void start() { - discoverer.scheduleWithFixedDelay( - new DiscoverTask(nodeManager), - 1, KademliaOptions.DISCOVER_CYCLE, TimeUnit.SECONDS); - - refresher.scheduleWithFixedDelay( - new RefreshTask(nodeManager), - 1, KademliaOptions.BUCKET_REFRESH, TimeUnit.MILLISECONDS); - } - - public void close() { - discoverer.shutdownNow(); - refresher.shutdownNow(); - } -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/RefreshTask.java b/framework/src/main/java/org/tron/common/overlay/discover/RefreshTask.java deleted file mode 100644 index d090cd82dcc..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/RefreshTask.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.discover; - -import java.util.ArrayList; -import lombok.extern.slf4j.Slf4j; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.overlay.discover.node.NodeManager; - -@Slf4j(topic = "discover") -public class RefreshTask extends DiscoverTask { - - public RefreshTask(NodeManager nodeManager) { - super(nodeManager); - } - - @Override - public void run() { - discover(Node.getNodeId(), 0, new ArrayList<>()); - } -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/dht/Bucket.java b/framework/src/main/java/org/tron/common/overlay/discover/dht/Bucket.java deleted file mode 100644 index bc523b46d4d..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/dht/Bucket.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.discover.dht; - -import java.util.ArrayList; -import java.util.List; - -public class Bucket { - - public static final int MAX_KADEMLIA_K = 5; - - // if bit = 1 go left - private Bucket left; - - // if bit = 0 go right - private Bucket right; - - private String name; - - private List peers = new ArrayList<>(); - - - public Bucket(String name) { - this.name = name; - } - - - public void add(Peer peer) { - - if (peer == null) { - throw new Error("Not a leaf"); - } - - if (peers == null) { - - if (peer.nextBit(name) == 1) { - left.add(peer); - } else { - right.add(peer); - } - - return; - } - - peers.add(peer); - - if (peers.size() > MAX_KADEMLIA_K) { - splitBucket(); - } - } - - public void splitBucket() { - left = new Bucket(name + "1"); - right = new Bucket(name + "0"); - - for (Peer id : peers) { - if (id.nextBit(name) == 1) { - left.add(id); - } else { - right.add(id); - } - } - - this.peers = null; - } - - - public Bucket left() { - return left; - } - - public Bucket right() { - return right; - } - - - @Override - public String toString() { - - StringBuilder sb = new StringBuilder(); - - sb.append(name).append("\n"); - - if (peers == null) { - return sb.toString(); - } - - for (Peer id : peers) { - sb.append(id.toBinaryString()).append("\n"); - } - - return sb.toString(); - } - - - public void traverseTree(DoOnTree doOnTree) { - - if (left != null) { - left.traverseTree(doOnTree); - } - if (right != null) { - right.traverseTree(doOnTree); - } - - doOnTree.call(this); - } - - //tree operations - - public String getName() { - return name; - } - - public List getPeers() { - return peers; - } - - public interface DoOnTree { - - void call(Bucket bucket); - } - - public static class SaveLeaf implements DoOnTree { - - private List leafs = new ArrayList<>(); - - @Override - public void call(Bucket bucket) { - if (bucket.peers != null) { - leafs.add(bucket); - } - } - - public List getLeafs() { - return leafs; - } - - public void setLeafs(List leafs) { - this.leafs = leafs; - } - } -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/dht/DHTUtils.java b/framework/src/main/java/org/tron/common/overlay/discover/dht/DHTUtils.java deleted file mode 100644 index 77c5874ae4d..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/dht/DHTUtils.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.discover.dht; - -import java.util.List; - -public class DHTUtils { - - public static void printAllLeafs(Bucket root) { - Bucket.SaveLeaf saveLeaf = new Bucket.SaveLeaf(); - root.traverseTree(saveLeaf); - - for (Bucket bucket : saveLeaf.getLeafs()) { - System.out.println(bucket); - } - } - - public static List getAllLeafs(Bucket root) { - Bucket.SaveLeaf saveLeaf = new Bucket.SaveLeaf(); - root.traverseTree(saveLeaf); - - return saveLeaf.getLeafs(); - } -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/dht/Peer.java b/framework/src/main/java/org/tron/common/overlay/discover/dht/Peer.java deleted file mode 100644 index 41d2964aa61..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/dht/Peer.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.discover.dht; - -import java.math.BigInteger; -import org.bouncycastle.util.BigIntegers; -import org.bouncycastle.util.encoders.Hex; -import org.tron.common.utils.Utils; -import org.tron.core.Constant; - -public class Peer { - - private byte[] id; - private String host = Constant.LOCAL_HOST; - private int port = 0; - - public Peer(byte[] id, String host, int port) { - this.id = id; - this.host = host; - this.port = port; - } - - public Peer(byte[] ip) { - this.id = ip; - } - - public static byte[] randomPeerId() { - - byte[] peerIdBytes = new BigInteger(512, Utils.getRandom()).toByteArray(); - - final String peerId; - if (peerIdBytes.length > 64) { - peerId = Hex.toHexString(peerIdBytes, 1, 64); - } else { - peerId = Hex.toHexString(peerIdBytes); - } - - return Hex.decode(peerId); - } - - public byte nextBit(String startPattern) { - - if (this.toBinaryString().startsWith(startPattern + "1")) { - return 1; - } else { - return 0; - } - } - - public byte[] calcDistance(Peer toPeer) { - - BigInteger aaPeer = new BigInteger(getId()); - BigInteger bbPeer = new BigInteger(toPeer.getId()); - - BigInteger distance = aaPeer.xor(bbPeer); - return BigIntegers.asUnsignedByteArray(distance); - } - - public byte[] getId() { - return id; - } - - public void setId(byte[] id) { - this.id = id; - } - - @Override - public String toString() { - return String - .format("Peer {\n id=%s, \n host=%s, \n port=%d\n}", Hex.toHexString(id), host, port); - } - - public String toBinaryString() { - - BigInteger bi = new BigInteger(1, id); - String out = String.format("%512s", bi.toString(2)); - out = out.replace(' ', '0'); - - return out; - } - -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/node/DBNode.java b/framework/src/main/java/org/tron/common/overlay/discover/node/DBNode.java deleted file mode 100644 index 2a5af767ecd..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/node/DBNode.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.tron.common.overlay.discover.node; - -import java.util.ArrayList; -import java.util.List; -import lombok.Getter; -import lombok.Setter; - -public class DBNode { - - @Getter - @Setter - private List nodes = new ArrayList<>(); - -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/node/DBNodeStats.java b/framework/src/main/java/org/tron/common/overlay/discover/node/DBNodeStats.java deleted file mode 100644 index 52b2b6bdc9b..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/node/DBNodeStats.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.tron.common.overlay.discover.node; - -import lombok.Getter; -import lombok.Setter; - -public class DBNodeStats { - - @Getter - @Setter - private byte[] id; - - @Getter - @Setter - private String host; - - @Getter - @Setter - private int port; - - @Getter - @Setter - private int reputation; - - public DBNodeStats() { - } - - public DBNodeStats(byte[] id, String host, int port, int reputation) { - this.id = id; - this.host = host; - this.port = port; - this.reputation = reputation; - } - -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java b/framework/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java deleted file mode 100644 index 44e8761c29a..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.discover.node; - -import java.net.InetSocketAddress; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import lombok.Getter; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; -import org.tron.common.net.udp.handler.UdpEvent; -import org.tron.common.net.udp.message.Message; -import org.tron.common.net.udp.message.discover.FindNodeMessage; -import org.tron.common.net.udp.message.discover.NeighborsMessage; -import org.tron.common.net.udp.message.discover.PingMessage; -import org.tron.common.net.udp.message.discover.PongMessage; -import org.tron.common.overlay.discover.node.statistics.NodeStatistics; -import org.tron.common.prometheus.MetricKeys; -import org.tron.common.prometheus.Metrics; -import org.tron.core.config.args.Args; - -@Slf4j(topic = "discover") -public class NodeHandler { - - private static long pingTimeout = Args.getInstance().getNodeDiscoveryPingTimeout(); - private Node sourceNode; - private Node node; - private State state; - private NodeManager nodeManager; - private NodeStatistics nodeStatistics; - private NodeHandler replaceCandidate; - private InetSocketAddress inetSocketAddress; - private AtomicInteger pingTrials = new AtomicInteger(3); - private volatile boolean waitForPong = false; - private volatile boolean waitForNeighbors = false; - private volatile long pingSent; - @Getter - @Setter - private int reputation; - - - public NodeHandler(Node node, NodeManager nodeManager) { - this.node = node; - this.nodeManager = nodeManager; - this.inetSocketAddress = new InetSocketAddress(node.getHost(), node.getPort()); - this.nodeStatistics = new NodeStatistics(); - changeState(State.DISCOVERED); - } - - public InetSocketAddress getInetSocketAddress() { - return inetSocketAddress; - } - - public Node getSourceNode() { - return sourceNode; - } - - public void setSourceNode(Node sourceNode) { - this.sourceNode = sourceNode; - } - - public Node getNode() { - return node; - } - - public void setNode(Node node) { - this.node = node; - } - - public State getState() { - return state; - } - - public NodeStatistics getNodeStatistics() { - return nodeStatistics; - } - - private void challengeWith(NodeHandler replaceCandidate) { - this.replaceCandidate = replaceCandidate; - changeState(State.EVICTCANDIDATE); - } - - // Manages state transfers - public void changeState(State newState) { - State oldState = state; - if (newState == State.DISCOVERED) { - if (sourceNode != null && sourceNode.getPort() != node.getPort()) { - changeState(State.DEAD); - } else { - sendPing(); - } - } - if (!node.isDiscoveryNode()) { - if (newState == State.ALIVE) { - Node evictCandidate = nodeManager.getTable().addNode(this.node); - if (evictCandidate == null) { - newState = State.ACTIVE; - } else { - NodeHandler evictHandler = nodeManager.getNodeHandler(evictCandidate); - if (evictHandler.state != State.EVICTCANDIDATE) { - evictHandler.challengeWith(this); - } - } - } - if (newState == State.ACTIVE) { - if (oldState == State.ALIVE) { - // new node won the challenge - nodeManager.getTable().addNode(node); - } else if (oldState == State.EVICTCANDIDATE) { - // nothing to do here the node is already in the table - } else { - // wrong state transition - } - } - - if (newState == State.NONACTIVE) { - if (oldState == State.EVICTCANDIDATE) { - // lost the challenge - // Removing ourselves from the table - nodeManager.getTable().dropNode(node); - // Congratulate the winner - replaceCandidate.changeState(State.ACTIVE); - } else if (oldState == State.ALIVE) { - // ok the old node was better, nothing to do here - } else { - // wrong state transition - } - } - } - - if (newState == State.EVICTCANDIDATE) { - // trying to survive, sending ping and waiting for pong - sendPing(); - } - state = newState; - } - - public void handlePing(PingMessage msg) { - if (!nodeManager.getTable().getNode().equals(node)) { - sendPong(); - } - node.setP2pVersion(msg.getVersion()); - if (!node.isConnectible(Args.getInstance().getNodeP2pVersion())) { - changeState(State.NONACTIVE); - } else if (state.equals(State.NONACTIVE) || state.equals(State.DEAD)) { - changeState(State.DISCOVERED); - } - } - - public void handlePong(PongMessage msg) { - if (waitForPong) { - waitForPong = false; - getNodeStatistics().discoverMessageLatency.add(System.currentTimeMillis() - pingSent); - Metrics.histogramObserve(MetricKeys.Histogram.PING_PONG_LATENCY, - (System.currentTimeMillis() - pingSent) / Metrics.MILLISECONDS_PER_SECOND); - getNodeStatistics().lastPongReplyTime.set(System.currentTimeMillis()); - node.setId(msg.getFrom().getId()); - node.setP2pVersion(msg.getVersion()); - if (!node.isConnectible(Args.getInstance().getNodeP2pVersion())) { - changeState(State.NONACTIVE); - } else { - changeState(State.ALIVE); - } - } - } - - public void handleNeighbours(NeighborsMessage msg) { - if (!waitForNeighbors) { - logger.warn("Receive neighbors from {} without send find nodes", node.getHost()); - return; - } - waitForNeighbors = false; - for (Node n : msg.getNodes()) { - if (!nodeManager.getPublicHomeNode().getHexId().equals(n.getHexId())) { - nodeManager.getNodeHandler(n); - } - } - } - - public void handleFindNode(FindNodeMessage msg) { - List closest = nodeManager.getTable().getClosestNodes(msg.getTargetId()); - sendNeighbours(closest, msg.getTimestamp()); - } - - public void handleTimedOut() { - waitForPong = false; - if (pingTrials.getAndDecrement() > 0) { - sendPing(); - } else { - if (state == State.DISCOVERED) { - changeState(State.DEAD); - } else if (state == State.EVICTCANDIDATE) { - changeState(State.NONACTIVE); - } else { - // TODO just influence to reputation - } - } - } - - public void sendPing() { - PingMessage msg = new PingMessage(nodeManager.getPublicHomeNode(), getNode()); - waitForPong = true; - pingSent = System.currentTimeMillis(); - sendMessage(msg); - - if (nodeManager.getPongTimer().isShutdown()) { - return; - } - nodeManager.getPongTimer().schedule(() -> { - try { - if (waitForPong) { - waitForPong = false; - handleTimedOut(); - } - } catch (Exception e) { - logger.error("Unhandled exception in pong timer schedule", e); - } - }, pingTimeout, TimeUnit.MILLISECONDS); - } - - public void sendPong() { - Message pong = new PongMessage(nodeManager.getPublicHomeNode()); - sendMessage(pong); - } - - public void sendFindNode(byte[] target) { - waitForNeighbors = true; - FindNodeMessage msg = new FindNodeMessage(nodeManager.getPublicHomeNode(), target); - sendMessage(msg); - } - - public void sendNeighbours(List neighbours, long sequence) { - Message msg = new NeighborsMessage(nodeManager.getPublicHomeNode(), neighbours, sequence); - sendMessage(msg); - } - - private void sendMessage(Message msg) { - nodeManager.sendOutbound(new UdpEvent(msg, getInetSocketAddress())); - nodeStatistics.messageStatistics.addUdpOutMessage(msg.getType()); - } - - @Override - public String toString() { - return "NodeHandler[state: " + state + ", node: " + node.getHost() + ":" + node.getPort() + "]"; - } - - public enum State { - /** - * The new node was just discovered either by receiving it with Neighbours message or by - * receiving Ping from a new node In either case we are sending Ping and waiting for Pong If the - * Pong is received the node becomes {@link #ALIVE} If the Pong was timed out the node becomes - * {@link #DEAD} - */ - DISCOVERED, - /** - * The node didn't send the Pong message back withing acceptable timeout This is the final - * state - */ - DEAD, - /** - * The node responded with Pong and is now the candidate for inclusion to the table If the table - * has bucket space for this node it is added to table and becomes {@link #ACTIVE} If the table - * bucket is full this node is challenging with the old node from the bucket if it wins then old - * node is dropped, and this node is added and becomes {@link #ACTIVE} else this node becomes - * {@link #NONACTIVE} - */ - ALIVE, - /** - * The node is included in the table. It may become {@link #EVICTCANDIDATE} if a new node wants - * to become Active but the table bucket is full. - */ - ACTIVE, - /** - * This node is in the table but is currently challenging with a new Node candidate to survive - * in the table bucket If it wins then returns back to {@link #ACTIVE} state, else is evicted - * from the table and becomes {@link #NONACTIVE} - */ - EVICTCANDIDATE, - /** - * Veteran. It was Alive and even Active but is now retired due to loosing the challenge with - * another Node. For no this is the final state It's an option for future to return veterans - * back to the table - */ - NONACTIVE - } - -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java b/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java deleted file mode 100644 index e8f2870fe98..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/node/NodeManager.java +++ /dev/null @@ -1,314 +0,0 @@ -package org.tron.common.overlay.discover.node; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.function.Consumer; -import java.util.function.Predicate; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.common.net.udp.handler.EventHandler; -import org.tron.common.net.udp.handler.UdpEvent; -import org.tron.common.net.udp.message.Message; -import org.tron.common.net.udp.message.discover.DiscoverMessageInspector; -import org.tron.common.net.udp.message.discover.FindNodeMessage; -import org.tron.common.net.udp.message.discover.NeighborsMessage; -import org.tron.common.net.udp.message.discover.PingMessage; -import org.tron.common.net.udp.message.discover.PongMessage; -import org.tron.common.overlay.discover.node.NodeHandler.State; -import org.tron.common.overlay.discover.node.statistics.NodeStatistics; -import org.tron.common.overlay.discover.table.NodeTable; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.prometheus.MetricKeys; -import org.tron.common.prometheus.MetricLabels; -import org.tron.common.prometheus.Metrics; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.CollectionUtils; -import org.tron.common.utils.JsonUtil; -import org.tron.core.ChainBaseManager; -import org.tron.core.capsule.BytesCapsule; -import org.tron.core.config.args.Args; -import org.tron.core.metrics.MetricsKey; -import org.tron.core.metrics.MetricsUtil; - -@Slf4j(topic = "discover") -@Component -public class NodeManager implements EventHandler { - - private static final byte[] DB_KEY_PEERS = "peers".getBytes(); - private static final long DB_COMMIT_RATE = 1 * 60 * 1000L; - private static final int MAX_NODES = 2000; - private static final int MAX_NODES_WRITE_TO_DB = 30; - private static final int NODES_TRIM_THRESHOLD = 3000; - private CommonParameter commonParameter = Args.getInstance(); - private ChainBaseManager chainBaseManager; - private Consumer messageSender; - - private NodeTable table; - private Node homeNode; - private Map nodeHandlerMap = new ConcurrentHashMap<>(); - private List bootNodes = new ArrayList<>(); - - private volatile boolean discoveryEnabled; - - private volatile boolean inited = false; - - private Timer nodeManagerTasksTimer = new Timer("NodeManagerTasks"); - - private ScheduledExecutorService pongTimer; - - @Autowired - public NodeManager(ChainBaseManager chainBaseManager) { - this.chainBaseManager = chainBaseManager; - discoveryEnabled = commonParameter.isNodeDiscoveryEnable(); - - homeNode = new Node(Node.getNodeId(), commonParameter.getNodeExternalIp(), - commonParameter.getNodeListenPort()); - - for (String boot : commonParameter.getSeedNode().getIpList()) { - bootNodes.add(Node.instanceOf(boot)); - } - - logger.info("Home node is {}", homeNode); - - table = new NodeTable(homeNode); - - this.pongTimer = Executors.newSingleThreadScheduledExecutor(); - } - - public ScheduledExecutorService getPongTimer() { - return pongTimer; - } - - @Override - public void channelActivated() { - if (!inited) { - inited = true; - - if (commonParameter.isNodeDiscoveryPersist()) { - dbRead(); - nodeManagerTasksTimer.scheduleAtFixedRate(new TimerTask() { - @Override - public void run() { - dbWrite(); - } - }, DB_COMMIT_RATE, DB_COMMIT_RATE); - } - - for (Node node : bootNodes) { - getNodeHandler(node); - } - } - } - - public boolean isNodeAlive(NodeHandler nodeHandler) { - return nodeHandler.getState().equals(State.ALIVE) - || nodeHandler.getState().equals(State.ACTIVE) - || nodeHandler.getState().equals(State.EVICTCANDIDATE); - } - - private void dbRead() { - try { - byte[] nodeBytes = chainBaseManager.getCommonStore().get(DB_KEY_PEERS).getData(); - if (ByteArray.isEmpty(nodeBytes)) { - return; - } - DBNode dbNode = JsonUtil.json2Obj(new String(nodeBytes), DBNode.class); - logger.info("Reading node statistics from store: {} nodes", dbNode.getNodes().size()); - dbNode.getNodes().forEach(n -> { - Node node = new Node(n.getId(), n.getHost(), n.getPort()); - getNodeHandler(node).getNodeStatistics().setPersistedReputation(n.getReputation()); - }); - } catch (Exception e) { - logger.error("DB read node failed", e); - } - } - - private void dbWrite() { - try { - List batch = new ArrayList<>(); - DBNode dbNode = new DBNode(); - for (NodeHandler nodeHandler : nodeHandlerMap.values()) { - Node node = nodeHandler.getNode(); - if (node.isConnectible(Args.getInstance().getNodeP2pVersion())) { - DBNodeStats nodeStatic = new DBNodeStats(node.getId(), node.getHost(), - node.getPort(), nodeHandler.getNodeStatistics().getReputation()); - batch.add(nodeStatic); - } - } - int size = batch.size(); - batch.sort(Comparator.comparingInt(value -> -value.getReputation())); - if (batch.size() > MAX_NODES_WRITE_TO_DB) { - batch = batch.subList(0, MAX_NODES_WRITE_TO_DB); - } - - dbNode.setNodes(batch); - - logger.info("Write node statistics to store: m:{}/t:{}/{}/{} nodes", - nodeHandlerMap.size(), getTable().getAllNodes().size(), size, batch.size()); - - chainBaseManager.getCommonStore() - .put(DB_KEY_PEERS, new BytesCapsule(JsonUtil.obj2Json(dbNode).getBytes())); - } catch (Exception e) { - logger.error("DB write node failed", e); - } - } - - public void setMessageSender(Consumer messageSender) { - this.messageSender = messageSender; - } - - private String getKey(Node n) { - return getKey(new InetSocketAddress(n.getHost(), n.getPort())); - } - - private String getKey(InetSocketAddress address) { - InetAddress inetAddress = address.getAddress(); - return (inetAddress == null ? address.getHostString() : inetAddress.getHostAddress()) + ":" - + address.getPort(); - } - - public NodeHandler getNodeHandler(Node n) { - String key = getKey(n); - NodeHandler ret = nodeHandlerMap.get(key); - if (ret == null) { - trimTable(); - ret = new NodeHandler(n, this); - nodeHandlerMap.put(key, ret); - } else if (ret.getNode().isDiscoveryNode() && !n.isDiscoveryNode()) { - ret.setNode(n); - } - return ret; - } - - private void trimTable() { - if (nodeHandlerMap.size() > NODES_TRIM_THRESHOLD) { - nodeHandlerMap.values().forEach(handler -> { - if (!handler.getNode().isConnectible(Args.getInstance().getNodeP2pVersion())) { - nodeHandlerMap.values().remove(handler); - } - }); - } - if (nodeHandlerMap.size() > NODES_TRIM_THRESHOLD) { - List sorted = new ArrayList<>(nodeHandlerMap.values()); - sorted.sort(Comparator.comparingInt(o -> o.getNodeStatistics().getReputation())); - for (NodeHandler handler : sorted) { - nodeHandlerMap.values().remove(handler); - if (nodeHandlerMap.size() <= MAX_NODES) { - break; - } - } - } - } - - public boolean hasNodeHandler(Node n) { - return nodeHandlerMap.containsKey(getKey(n)); - } - - public NodeTable getTable() { - return table; - } - - public NodeStatistics getNodeStatistics(Node n) { - return getNodeHandler(n).getNodeStatistics(); - } - - @Override - public void handleEvent(UdpEvent udpEvent) { - Message m = udpEvent.getMessage(); - if (!DiscoverMessageInspector.valid(m)) { - return; - } - - InetSocketAddress sender = udpEvent.getAddress(); - - Node n = new Node(m.getFrom().getId(), sender.getHostString(), sender.getPort(), - m.getFrom().getPort()); - - NodeHandler nodeHandler = getNodeHandler(n); - nodeHandler.getNodeStatistics().messageStatistics.addUdpInMessage(m.getType()); - int length = udpEvent.getMessage().getData().length + 1; - MetricsUtil.meterMark(MetricsKey.NET_UDP_IN_TRAFFIC, length); - Metrics.histogramObserve(MetricKeys.Histogram.UDP_BYTES, length, - MetricLabels.Histogram.TRAFFIC_IN); - - switch (m.getType()) { - case DISCOVER_PING: - nodeHandler.handlePing((PingMessage) m); - break; - case DISCOVER_PONG: - nodeHandler.handlePong((PongMessage) m); - break; - case DISCOVER_FIND_NODE: - nodeHandler.handleFindNode((FindNodeMessage) m); - break; - case DISCOVER_NEIGHBORS: - nodeHandler.handleNeighbours((NeighborsMessage) m); - break; - default: - break; - } - } - - public void sendOutbound(UdpEvent udpEvent) { - if (discoveryEnabled && messageSender != null) { - messageSender.accept(udpEvent); - int length = udpEvent.getMessage().getSendData().length; - MetricsUtil.meterMark(MetricsKey.NET_UDP_OUT_TRAFFIC, length); - Metrics.histogramObserve(MetricKeys.Histogram.UDP_BYTES, length, - MetricLabels.Histogram.TRAFFIC_OUT); - - } - } - - public List getNodes(Predicate predicate, int limit) { - List filtered = new ArrayList<>(); - for (NodeHandler handler : nodeHandlerMap.values()) { - if (handler.getNode().isConnectible(Args.getInstance().getNodeP2pVersion()) - && predicate.test(handler)) { - handler.setReputation(handler.getNodeStatistics().getReputation()); - filtered.add(handler); - } - } - filtered.sort(Comparator.comparingInt(handler -> -handler.getReputation())); - return CollectionUtils.truncate(filtered, limit); - } - - public List dumpActiveNodes() { - List handlers = new ArrayList<>(); - for (NodeHandler handler : this.nodeHandlerMap.values()) { - if (isNodeAlive(handler)) { - handlers.add(handler); - } - } - return handlers; - } - - public Node getPublicHomeNode() { - return homeNode; - } - - // just for test - public void clearNodeHandlerMap() { - nodeHandlerMap.clear(); - } - - public void close() { - try { - nodeManagerTasksTimer.cancel(); - pongTimer.shutdownNow(); - } catch (Exception e) { - logger.error("Close nodeManagerTasksTimer or pongTimer failed", e); - } - } - -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/node/statistics/NodeStatistics.java b/framework/src/main/java/org/tron/common/overlay/discover/node/statistics/NodeStatistics.java deleted file mode 100644 index 82b18b2071c..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/node/statistics/NodeStatistics.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.discover.node.statistics; - -import java.util.concurrent.atomic.AtomicLong; -import lombok.Getter; -import org.tron.core.config.args.Args; -import org.tron.protos.Protocol.ReasonCode; - -public class NodeStatistics { - - public static final int REPUTATION_PREDEFINED = 100000; - public static final long TOO_MANY_PEERS_PENALIZE_TIMEOUT = 60 * 1000L; - private static final long CLEAR_CYCLE_TIME = 60 * 60 * 1000L; - public final MessageStatistics messageStatistics = new MessageStatistics(); - public final MessageCount p2pHandShake = new MessageCount(); - public final MessageCount tcpFlow = new MessageCount(); - public final SimpleStatter discoverMessageLatency; - public final SimpleStatter pingMessageLatency; - public final AtomicLong lastPongReplyTime = new AtomicLong(0L); // in milliseconds - private final long MIN_DATA_LENGTH = Args.getInstance().getReceiveTcpMinDataLength(); - private boolean isPredefined = false; - private int persistedReputation = 0; - @Getter - private int disconnectTimes = 0; - @Getter - private ReasonCode tronLastRemoteDisconnectReason = null; - @Getter - private ReasonCode tronLastLocalDisconnectReason = null; - private long lastDisconnectedTime = 0; - private long firstDisconnectedTime = 0; - private Reputation reputation; - - public NodeStatistics() { - discoverMessageLatency = new SimpleStatter(); - pingMessageLatency = new SimpleStatter(); - reputation = new Reputation(this); - } - - public int getReputation() { - int score = 0; - if (!isReputationPenalized()) { - score += persistedReputation / 5 + reputation.getScore(); - } - if (isPredefined) { - score += REPUTATION_PREDEFINED; - } - return score; - } - - public ReasonCode getDisconnectReason() { - if (tronLastLocalDisconnectReason != null) { - return tronLastLocalDisconnectReason; - } - if (tronLastRemoteDisconnectReason != null) { - return tronLastRemoteDisconnectReason; - } - return ReasonCode.UNKNOWN; - } - - public boolean isReputationPenalized() { - - if (wasDisconnected() && tronLastRemoteDisconnectReason == ReasonCode.TOO_MANY_PEERS - && System.currentTimeMillis() - lastDisconnectedTime < TOO_MANY_PEERS_PENALIZE_TIMEOUT) { - return true; - } - - if (wasDisconnected() && tronLastRemoteDisconnectReason == ReasonCode.DUPLICATE_PEER - && System.currentTimeMillis() - lastDisconnectedTime < TOO_MANY_PEERS_PENALIZE_TIMEOUT) { - return true; - } - - if (firstDisconnectedTime > 0 - && (System.currentTimeMillis() - firstDisconnectedTime) > CLEAR_CYCLE_TIME) { - tronLastLocalDisconnectReason = null; - tronLastRemoteDisconnectReason = null; - disconnectTimes = 0; - persistedReputation = 0; - firstDisconnectedTime = 0; - } - - if (tronLastLocalDisconnectReason == ReasonCode.INCOMPATIBLE_PROTOCOL - || tronLastRemoteDisconnectReason == ReasonCode.INCOMPATIBLE_PROTOCOL - || tronLastLocalDisconnectReason == ReasonCode.BAD_PROTOCOL - || tronLastRemoteDisconnectReason == ReasonCode.BAD_PROTOCOL - || tronLastLocalDisconnectReason == ReasonCode.BAD_BLOCK - || tronLastRemoteDisconnectReason == ReasonCode.BAD_BLOCK - || tronLastLocalDisconnectReason == ReasonCode.BAD_TX - || tronLastRemoteDisconnectReason == ReasonCode.BAD_TX - || tronLastLocalDisconnectReason == ReasonCode.FORKED - || tronLastRemoteDisconnectReason == ReasonCode.FORKED - || tronLastLocalDisconnectReason == ReasonCode.UNLINKABLE - || tronLastRemoteDisconnectReason == ReasonCode.UNLINKABLE - || tronLastLocalDisconnectReason == ReasonCode.INCOMPATIBLE_CHAIN - || tronLastRemoteDisconnectReason == ReasonCode.INCOMPATIBLE_CHAIN - || tronLastRemoteDisconnectReason == ReasonCode.SYNC_FAIL - || tronLastLocalDisconnectReason == ReasonCode.SYNC_FAIL - || tronLastRemoteDisconnectReason == ReasonCode.INCOMPATIBLE_VERSION - || tronLastLocalDisconnectReason == ReasonCode.INCOMPATIBLE_VERSION) { - persistedReputation = 0; - return true; - } - return false; - } - - public void nodeDisconnectedRemote(ReasonCode reason) { - lastDisconnectedTime = System.currentTimeMillis(); - tronLastRemoteDisconnectReason = reason; - } - - public void nodeDisconnectedLocal(ReasonCode reason) { - lastDisconnectedTime = System.currentTimeMillis(); - tronLastLocalDisconnectReason = reason; - } - - public void notifyDisconnect() { - lastDisconnectedTime = System.currentTimeMillis(); - if (firstDisconnectedTime <= 0) { - firstDisconnectedTime = lastDisconnectedTime; - } - if (tronLastLocalDisconnectReason == ReasonCode.RESET) { - return; - } - disconnectTimes++; - persistedReputation = persistedReputation / 2; - } - - public boolean wasDisconnected() { - return lastDisconnectedTime > 0; - } - - public boolean isPredefined() { - return isPredefined; - } - - public void setPredefined(boolean isPredefined) { - this.isPredefined = isPredefined; - } - - public void setPersistedReputation(int persistedReputation) { - this.persistedReputation = persistedReputation; - } - - @Override - public String toString() { - return "NodeStat[reput: " + getReputation() + "(" + persistedReputation + "), discover: " - + messageStatistics.discoverInPong + "/" + messageStatistics.discoverOutPing + " " - + messageStatistics.discoverOutPong + "/" + messageStatistics.discoverInPing + " " - + messageStatistics.discoverInNeighbours + "/" + messageStatistics.discoverOutFindNode - + " " - + messageStatistics.discoverOutNeighbours + "/" + messageStatistics.discoverInFindNode - + " " - + ((int) discoverMessageLatency.getAvg()) + "ms" - + ", p2p: " + p2pHandShake + "/" + messageStatistics.p2pInHello + "/" - + messageStatistics.p2pOutHello + " " - + ", tron: " + messageStatistics.tronInMessage + "/" + messageStatistics.tronOutMessage - + " " - + (wasDisconnected() ? "X " + disconnectTimes : "") - + (tronLastLocalDisconnectReason != null ? ("<=" + tronLastLocalDisconnectReason) : " ") - + (tronLastRemoteDisconnectReason != null ? ("=>" + tronLastRemoteDisconnectReason) : " ") - + ", tcp flow: " + tcpFlow.getTotalCount(); - } - - public boolean nodeIsHaveDataTransfer() { - return tcpFlow.getTotalCount() > MIN_DATA_LENGTH; - } - - public void resetTcpFlow() { - tcpFlow.reset(); - } - - public class SimpleStatter { - - private long sum; - @Getter - private long count; - @Getter - private long last; - @Getter - private long min; - @Getter - private long max; - - public void add(long value) { - last = value; - sum += value; - min = min == 0 ? value : Math.min(min, value); - max = Math.max(max, value); - count++; - } - - public long getAvg() { - return count == 0 ? 0 : sum / count; - } - - } - -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/node/statistics/Reputation.java b/framework/src/main/java/org/tron/common/overlay/discover/node/statistics/Reputation.java deleted file mode 100644 index 685407c11ed..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/node/statistics/Reputation.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.tron.common.overlay.discover.node.statistics; - -import static java.lang.Math.min; - -public class Reputation { - - private NodeStatistics nodeStatistics; - - public Reputation(NodeStatistics nodeStatistics) { - this.nodeStatistics = nodeStatistics; - - } - - public int getScore() { - return getNodeActiveScore() + getPacketLossRateScore() + getNetLatencyScore() - + getHandshakeScore() + getTcpFlowScore() + getDisconnectionScore(); - } - - private int getNodeActiveScore() { - long inPongTotalCount = nodeStatistics.messageStatistics.discoverInPong.getTotalCount(); - return inPongTotalCount == 0 ? 0 : 100; - } - - private int getPacketLossRateScore() { - MessageStatistics s = nodeStatistics.messageStatistics; - long in = s.discoverInPong.getTotalCount() + s.discoverInNeighbours.getTotalCount(); - long out = s.discoverOutPing.getTotalCount() + s.discoverOutFindNode.getTotalCount(); - return out == 0 ? 0 : 100 - min((int) ((1 - (double) in / out) * 200), 100); - } - - private int getNetLatencyScore() { - return (int) (nodeStatistics.discoverMessageLatency.getAvg() == 0 ? 0 - : min(1000 / nodeStatistics.discoverMessageLatency.getAvg(), 20)); - } - - private int getHandshakeScore() { - return nodeStatistics.p2pHandShake.getTotalCount() > 0 ? 20 : 0; - } - - private int getTcpFlowScore() { - return (int) min(nodeStatistics.tcpFlow.getTotalCount() / 10240, 20); - } - - private int getDisconnectionScore() { - return -10 * nodeStatistics.getDisconnectTimes(); - } - -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/table/DistanceComparator.java b/framework/src/main/java/org/tron/common/overlay/discover/table/DistanceComparator.java deleted file mode 100644 index 38e0ff4b6a3..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/table/DistanceComparator.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.discover.table; - -import java.util.Comparator; - -/** - * Created by kest on 5/26/15. - */ -public class DistanceComparator implements Comparator { - - private byte[] targetId; - - DistanceComparator(byte[] targetId) { - this.targetId = targetId; - } - - @Override - public int compare(NodeEntry e1, NodeEntry e2) { - int d1 = NodeEntry.distance(targetId, e1.getNode().getId()); - int d2 = NodeEntry.distance(targetId, e2.getNode().getId()); - - if (d1 > d2) { - return 1; - } else if (d1 < d2) { - return -1; - } else { - return 0; - } - } -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/table/KademliaOptions.java b/framework/src/main/java/org/tron/common/overlay/discover/table/KademliaOptions.java deleted file mode 100644 index c5c37dd646e..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/table/KademliaOptions.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.discover.table; - -/** - * Created by kest on 5/25/15. - */ -public class KademliaOptions { - - public static final int NODE_ID_LEN = 64; - public static final int BUCKET_SIZE = 16; - public static final int ALPHA = 3; - public static final int BINS = 256; - public static final int MAX_STEPS = 8; - - public static final long BUCKET_REFRESH = 7200; //bucket refreshing interval in millis - public static final long DISCOVER_CYCLE = 30; //discovery cycle interval in seconds -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/table/NodeBucket.java b/framework/src/main/java/org/tron/common/overlay/discover/table/NodeBucket.java deleted file mode 100644 index 5742310802a..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/table/NodeBucket.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.discover.table; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Created by kest on 5/25/15. - */ -public class NodeBucket { - - private final int depth; - private List nodes = new ArrayList<>(); - - NodeBucket(int depth) { - this.depth = depth; - } - - public int getDepth() { - return depth; - } - - public synchronized NodeEntry addNode(NodeEntry e) { - if (!nodes.contains(e)) { - if (nodes.size() >= KademliaOptions.BUCKET_SIZE) { - return getLastSeen(); - } else { - nodes.add(e); - } - } - - return null; - } - - private NodeEntry getLastSeen() { - List sorted = nodes; - Collections.sort(sorted, new TimeComparator()); - return sorted.get(0); - } - - public synchronized void dropNode(NodeEntry entry) { - for (NodeEntry e : nodes) { - if (e.getId().equals(entry.getId())) { - nodes.remove(e); - break; - } - } - } - - public int getNodesCount() { - return nodes.size(); - } - - public List getNodes() { - return nodes; - } -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/table/NodeEntry.java b/framework/src/main/java/org/tron/common/overlay/discover/table/NodeEntry.java deleted file mode 100644 index 4d83f58734d..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/table/NodeEntry.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.discover.table; - -import org.tron.common.overlay.discover.node.Node; - -public class NodeEntry { - private Node node; - private String entryId; - private int distance; - private long modified; - - public NodeEntry(byte[] ownerId, Node n) { - this.node = n; - entryId = n.getHost(); - distance = distance(ownerId, n.getId()); - touch(); - } - - public static int distance(byte[] ownerId, byte[] targetId) { - byte[] h1 = targetId; - byte[] h2 = ownerId; - - byte[] hash = new byte[Math.min(h1.length, h2.length)]; - - for (int i = 0; i < hash.length; i++) { - hash[i] = (byte) (h1[i] ^ h2[i]); - } - - int d = KademliaOptions.BINS; - - for (byte b : hash) { - if (b == 0) { - d -= 8; - } else { - int count = 0; - for (int i = 7; i >= 0; i--) { - boolean a = ((b & 0xff) & (1 << i)) == 0; - if (a) { - count++; - } else { - break; - } - } - - d -= count; - - break; - } - } - return d; - } - - public void touch() { - modified = System.currentTimeMillis(); - } - - public int getDistance() { - return distance; - } - - public String getId() { - return entryId; - } - - public Node getNode() { - return node; - } - - public long getModified() { - return modified; - } - - @Override - public boolean equals(Object o) { - boolean ret = false; - - if (o != null && this.getClass() == o.getClass()) { - NodeEntry e = (NodeEntry) o; - ret = this.getId().equals(e.getId()); - } - - return ret; - } - - @Override - public int hashCode() { - return this.entryId.hashCode(); - } -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java b/framework/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java deleted file mode 100644 index 3846dbaf94d..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.discover.table; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import lombok.extern.slf4j.Slf4j; -import org.tron.common.overlay.discover.node.Node; - -@Slf4j(topic = "discover") -public class NodeTable { - - private final Node node; // our node - private transient NodeBucket[] buckets; - private transient Map nodes; - - public NodeTable(Node n) { - this.node = n; - initialize(); - } - - public Node getNode() { - return node; - } - - public final void initialize() { - nodes = new HashMap<>(); - buckets = new NodeBucket[KademliaOptions.BINS]; - for (int i = 0; i < KademliaOptions.BINS; i++) { - buckets[i] = new NodeBucket(i); - } - } - - public synchronized Node addNode(Node n) { - if (n.getHost().equals(node.getHost())) { - return null; - } - - NodeEntry entry = nodes.get(n.getHost()); - if (entry != null) { - entry.touch(); - return null; - } - - NodeEntry e = new NodeEntry(node.getId(), n); - NodeEntry lastSeen = buckets[getBucketId(e)].addNode(e); - if (lastSeen != null) { - return lastSeen.getNode(); - } - nodes.put(n.getHost(), e); - return null; - } - - public synchronized void dropNode(Node n) { - NodeEntry entry = nodes.get(n.getHost()); - if (entry != null) { - nodes.remove(n.getHost()); - buckets[getBucketId(entry)].dropNode(entry); - } - } - - public synchronized boolean contains(Node n) { - return nodes.containsKey(n.getHost()); - } - - public synchronized void touchNode(Node n) { - NodeEntry entry = nodes.get(n.getHost()); - if (entry != null) { - entry.touch(); - } - } - - public int getBucketsCount() { - int i = 0; - for (NodeBucket b : buckets) { - if (b.getNodesCount() > 0) { - i++; - } - } - return i; - } - - public int getBucketId(NodeEntry e) { - int id = e.getDistance() - 1; - return id < 0 ? 0 : id; - } - - public synchronized int getNodesCount() { - return nodes.size(); - } - - public synchronized List getAllNodes() { - return new ArrayList<>(nodes.values()); - } - - public synchronized List getClosestNodes(byte[] targetId) { - List closestEntries = getAllNodes(); - List closestNodes = new ArrayList<>(); - Collections.sort(closestEntries, new DistanceComparator(targetId)); - if (closestEntries.size() > KademliaOptions.BUCKET_SIZE) { - closestEntries = closestEntries.subList(0, KademliaOptions.BUCKET_SIZE); - } - for (NodeEntry e : closestEntries) { - if (!e.getNode().isDiscoveryNode()) { - closestNodes.add(e.getNode()); - } - } - return closestNodes; - } - -} diff --git a/framework/src/main/java/org/tron/common/overlay/discover/table/TimeComparator.java b/framework/src/main/java/org/tron/common/overlay/discover/table/TimeComparator.java deleted file mode 100644 index 056d913e781..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/discover/table/TimeComparator.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.discover.table; - -import java.util.Comparator; - -/** - * Created by kest on 5/26/15. - */ -public class TimeComparator implements Comparator { - - @Override - public int compare(NodeEntry e1, NodeEntry e2) { - long t1 = e1.getModified(); - long t2 = e2.getModified(); - - if (t1 < t2) { - return 1; - } else if (t1 > t2) { - return -1; - } else { - return 0; - } - } -} diff --git a/framework/src/main/java/org/tron/common/overlay/message/MessageCodec.java b/framework/src/main/java/org/tron/common/overlay/message/MessageCodec.java deleted file mode 100644 index 30a2329131e..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/message/MessageCodec.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.tron.common.overlay.message; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.ByteToMessageDecoder; -import java.util.List; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; -import org.tron.common.overlay.server.Channel; -import org.tron.common.prometheus.MetricKeys; -import org.tron.common.prometheus.MetricLabels; -import org.tron.common.prometheus.Metrics; -import org.tron.core.exception.P2pException; -import org.tron.core.metrics.MetricsKey; -import org.tron.core.metrics.MetricsUtil; -import org.tron.core.net.message.MessageTypes; -import org.tron.core.net.message.PbftMessageFactory; -import org.tron.core.net.message.TronMessageFactory; - -@Component -@Scope("prototype") -public class MessageCodec extends ByteToMessageDecoder { - - private Channel channel; - private P2pMessageFactory p2pMessageFactory = new P2pMessageFactory(); - private TronMessageFactory tronMessageFactory = new TronMessageFactory(); - private PbftMessageFactory pbftMessageFactory = new PbftMessageFactory(); - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List out) - throws Exception { - int length = buffer.readableBytes(); - byte[] encoded = new byte[length]; - buffer.readBytes(encoded); - try { - Message msg = createMessage(encoded); - channel.getNodeStatistics().tcpFlow.add(length); - MetricsUtil.meterMark(MetricsKey.NET_TCP_IN_TRAFFIC, length); - Metrics.histogramObserve(MetricKeys.Histogram.TCP_BYTES, length, - MetricLabels.Histogram.TRAFFIC_IN); - out.add(msg); - } catch (Exception e) { - channel.processException(e); - } - } - - public void setChannel(Channel channel) { - this.channel = channel; - } - - private Message createMessage(byte[] encoded) throws Exception { - byte type = encoded[0]; - if (MessageTypes.inP2pRange(type)) { - return p2pMessageFactory.create(encoded); - } - if (MessageTypes.inTronRange(type)) { - return tronMessageFactory.create(encoded); - } - if (MessageTypes.inPbftRange(type)) { - return pbftMessageFactory.create(encoded); - } - throw new P2pException(P2pException.TypeEnum.NO_SUCH_MESSAGE, "type=" + encoded[0]); - } - -} \ No newline at end of file diff --git a/framework/src/main/java/org/tron/common/overlay/message/MessageFactory.java b/framework/src/main/java/org/tron/common/overlay/message/MessageFactory.java deleted file mode 100644 index 6aa41ba085f..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/message/MessageFactory.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * java-tron is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * java-tron is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.tron.common.overlay.message; - -public abstract class MessageFactory { - - protected abstract Message create(byte[] data) throws Exception; - -} diff --git a/framework/src/main/java/org/tron/common/overlay/message/P2pMessage.java b/framework/src/main/java/org/tron/common/overlay/message/P2pMessage.java deleted file mode 100644 index a7827733837..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/message/P2pMessage.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.message; - -public abstract class P2pMessage extends Message { - - public P2pMessage() { - } - - public P2pMessage(byte[] rawData) { - super(rawData); - } - - public P2pMessage(byte type, byte[] rawData) { - super(type, rawData); - } - -} diff --git a/framework/src/main/java/org/tron/common/overlay/message/P2pMessageFactory.java b/framework/src/main/java/org/tron/common/overlay/message/P2pMessageFactory.java deleted file mode 100644 index e403b349984..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/message/P2pMessageFactory.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.message; - -import org.apache.commons.lang3.ArrayUtils; -import org.tron.core.exception.P2pException; -import org.tron.core.exception.P2pException.TypeEnum; -import org.tron.core.net.message.MessageTypes; - -public class P2pMessageFactory extends MessageFactory { - - @Override - public P2pMessage create(byte[] data) throws Exception { - if (data.length <= 1) { - throw new P2pException(TypeEnum.MESSAGE_WITH_WRONG_LENGTH, - "messageType=" + (data.length == 1 ? data[0] : "unknown")); - } - try { - byte type = data[0]; - byte[] rawData = ArrayUtils.subarray(data, 1, data.length); - return create(type, rawData); - } catch (Exception e) { - if (e instanceof P2pException) { - throw e; - } else { - throw new P2pException(P2pException.TypeEnum.PARSE_MESSAGE_FAILED, - "type=" + data[0] + ", len=" + data.length); - } - } - } - - private P2pMessage create(byte type, byte[] rawData) throws Exception { - MessageTypes messageType = MessageTypes.fromByte(type); - if (messageType == null) { - throw new P2pException(P2pException.TypeEnum.NO_SUCH_MESSAGE, - "type=" + type + ", len=" + rawData.length); - } - switch (messageType) { - case P2P_HELLO: - return new HelloMessage(type, rawData); - case P2P_DISCONNECT: - return new DisconnectMessage(type, rawData); - case P2P_PING: - return new PingMessage(type, rawData); - case P2P_PONG: - return new PongMessage(type, rawData); - default: - throw new P2pException(P2pException.TypeEnum.NO_SUCH_MESSAGE, messageType.toString()); - } - } -} diff --git a/framework/src/main/java/org/tron/common/overlay/message/StaticMessages.java b/framework/src/main/java/org/tron/common/overlay/message/StaticMessages.java deleted file mode 100644 index 46904ad1d5d..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/message/StaticMessages.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.tron.common.overlay.message; - -import org.springframework.stereotype.Component; - -@Component -public class StaticMessages { - - public static final PingMessage PING_MESSAGE = new PingMessage(); - public static final PongMessage PONG_MESSAGE = new PongMessage(); -} diff --git a/framework/src/main/java/org/tron/common/overlay/server/Channel.java b/framework/src/main/java/org/tron/common/overlay/server/Channel.java deleted file mode 100644 index f67cd8ba43b..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/server/Channel.java +++ /dev/null @@ -1,279 +0,0 @@ -package org.tron.common.overlay.server; - -import com.google.common.base.Throwables; -import com.google.protobuf.ByteString; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPipeline; -import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; -import io.netty.handler.timeout.ReadTimeoutException; -import io.netty.handler.timeout.ReadTimeoutHandler; -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.util.concurrent.TimeUnit; - -import lombok.Getter; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.overlay.discover.node.NodeHandler; -import org.tron.common.overlay.discover.node.NodeManager; -import org.tron.common.overlay.discover.node.statistics.NodeStatistics; -import org.tron.common.overlay.message.DisconnectMessage; -import org.tron.common.overlay.message.HelloMessage; -import org.tron.common.overlay.message.MessageCodec; -import org.tron.common.overlay.message.StaticMessages; -import org.tron.core.db.ByteArrayWrapper; -import org.tron.core.exception.P2pException; -import org.tron.core.net.PbftHandler; -import org.tron.core.net.TronNetHandler; -import org.tron.protos.Protocol.ReasonCode; - -@Slf4j(topic = "net") -@Component -@Scope("prototype") -public class Channel { - - @Autowired - protected MessageQueue msgQueue; - protected NodeStatistics nodeStatistics; - @Autowired - private MessageCodec messageCodec; - @Autowired - private NodeManager nodeManager; - @Autowired - private StaticMessages staticMessages; - @Autowired - private WireTrafficStats stats; - @Autowired - private HandshakeHandler handshakeHandler; - @Autowired - private P2pHandler p2pHandler; - @Autowired - private TronNetHandler tronNetHandler; - @Autowired - private PbftHandler pbftHandler; - private ChannelManager channelManager; - private ChannelHandlerContext ctx; - private InetSocketAddress inetSocketAddress; - private Node node; - private long startTime; - @Getter - private TronState tronState = TronState.INIT; - private boolean isActive; - @Getter - @Setter - private ByteString address; - - private volatile boolean isDisconnect; - - @Getter - private volatile long disconnectTime; - - private boolean isTrustPeer; - - private boolean isFastForwardPeer; - - public void init(ChannelPipeline pipeline, String remoteId, boolean discoveryMode, - ChannelManager channelManager) { - - this.channelManager = channelManager; - - isActive = remoteId != null && !remoteId.isEmpty(); - - startTime = System.currentTimeMillis(); - - //TODO: use config here - pipeline.addLast("readTimeoutHandler", new ReadTimeoutHandler(60, TimeUnit.SECONDS)); - pipeline.addLast(stats.tcp); - pipeline.addLast("protoPender", new ProtobufVarint32LengthFieldPrepender()); - pipeline.addLast("lengthDecode", new TrxProtobufVarint32FrameDecoder(this)); - - //handshake first - pipeline.addLast("handshakeHandler", handshakeHandler); - - messageCodec.setChannel(this); - msgQueue.setChannel(this); - handshakeHandler.setChannel(this, remoteId); - p2pHandler.setChannel(this); - tronNetHandler.setChannel(this); - pbftHandler.setChannel(this); - - p2pHandler.setMsgQueue(msgQueue); - tronNetHandler.setMsgQueue(msgQueue); - pbftHandler.setMsgQueue(msgQueue); - } - - public void publicHandshakeFinished(ChannelHandlerContext ctx, HelloMessage msg) { - isTrustPeer = channelManager.getTrustNodes().getIfPresent(getInetAddress()) != null; - isFastForwardPeer = channelManager.getFastForwardNodes().containsKey(getInetAddress()); - ctx.pipeline().remove(handshakeHandler); - msgQueue.activate(ctx); - ctx.pipeline().addLast("messageCodec", messageCodec); - ctx.pipeline().addLast("p2p", p2pHandler); - ctx.pipeline().addLast("data", tronNetHandler); - ctx.pipeline().addLast("pbft", pbftHandler); - setStartTime(msg.getTimestamp()); - setTronState(TronState.HANDSHAKE_FINISHED); - getNodeStatistics().p2pHandShake.add(); - logger.info("Finish handshake with {}", ctx.channel().remoteAddress()); - } - - /** - * Set node and register it in NodeManager if it is not registered yet. - */ - public void initNode(byte[] nodeId, int remotePort) { - Node n = new Node(nodeId, inetSocketAddress.getHostString(), remotePort); - NodeHandler handler = nodeManager.getNodeHandler(n); - node = handler.getNode(); - nodeStatistics = handler.getNodeStatistics(); - handler.getNode().setId(nodeId); - } - - public void disconnect(ReasonCode reason) { - this.isDisconnect = true; - this.disconnectTime = System.currentTimeMillis(); - channelManager.processDisconnect(this, reason); - DisconnectMessage msg = new DisconnectMessage(reason); - logger.info("Send to {} online-time {}s, {}", - ctx.channel().remoteAddress(), - (System.currentTimeMillis() - startTime) / 1000, - msg); - getNodeStatistics().nodeDisconnectedLocal(reason); - ctx.writeAndFlush(msg.getSendData()).addListener(future -> close()); - } - - public void processException(Throwable throwable) { - Throwable baseThrowable = throwable; - try { - baseThrowable = Throwables.getRootCause(baseThrowable); - } catch (IllegalArgumentException e) { - baseThrowable = e.getCause(); - logger.warn("Loop in causal chain detected"); - } - SocketAddress address = ctx.channel().remoteAddress(); - if (throwable instanceof ReadTimeoutException - || throwable instanceof IOException) { - logger.warn("Close peer {}, reason: {}", address, throwable.getMessage()); - } else if (baseThrowable instanceof P2pException) { - logger.warn("Close peer {}, type: {}, info: {}", - address, ((P2pException) baseThrowable).getType(), baseThrowable.getMessage()); - } else { - logger.error("Close peer {}, exception caught", address, throwable); - } - close(); - } - - public void close() { - this.isDisconnect = true; - this.disconnectTime = System.currentTimeMillis(); - p2pHandler.close(); - msgQueue.close(); - ctx.close(); - } - - public Node getNode() { - return node; - } - - public byte[] getNodeId() { - return node == null ? null : node.getId(); - } - - public ByteArrayWrapper getNodeIdWrapper() { - return node == null ? null : new ByteArrayWrapper(node.getId()); - } - - public String getPeerId() { - return node == null ? "" : node.getHexId(); - } - - public void setChannelHandlerContext(ChannelHandlerContext ctx) { - this.ctx = ctx; - this.inetSocketAddress = ctx == null ? null : (InetSocketAddress) ctx.channel().remoteAddress(); - } - - public InetAddress getInetAddress() { - return ctx == null ? null : ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress(); - } - - public NodeStatistics getNodeStatistics() { - return nodeStatistics; - } - - public long getStartTime() { - return startTime; - } - - public void setStartTime(long startTime) { - this.startTime = startTime; - } - - public void setTronState(TronState tronState) { - this.tronState = tronState; - logger.info("Peer {} status change to {}", inetSocketAddress, tronState); - } - - public boolean isActive() { - return isActive; - } - - public boolean isDisconnect() { - return isDisconnect; - } - - public boolean isTrustPeer() { - return isTrustPeer; - } - - public boolean isFastForwardPeer() { - return isFastForwardPeer; - } - - @Override - public boolean equals(Object o) { - - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Channel channel = (Channel) o; - if (inetSocketAddress != null ? !inetSocketAddress.equals(channel.inetSocketAddress) - : channel.inetSocketAddress != null) { - return false; - } - if (node != null ? !node.equals(channel.node) : channel.node != null) { - return false; - } - return this == channel; - } - - @Override - public int hashCode() { - int result = inetSocketAddress != null ? inetSocketAddress.hashCode() : 0; - result = 31 * result + (node != null ? node.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return String.format("%s | %s", inetSocketAddress, getPeerId()); - } - - public enum TronState { - INIT, - HANDSHAKE_FINISHED, - START_TO_SYNC, - SYNCING, - SYNC_COMPLETED, - SYNC_FAILED - } - -} - diff --git a/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java b/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java deleted file mode 100644 index 68c5ee78d97..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/server/ChannelManager.java +++ /dev/null @@ -1,206 +0,0 @@ -package org.tron.common.overlay.server; - -import static org.tron.protos.Protocol.ReasonCode.DUPLICATE_PEER; -import static org.tron.protos.Protocol.ReasonCode.TOO_MANY_PEERS; -import static org.tron.protos.Protocol.ReasonCode.TOO_MANY_PEERS_WITH_SAME_IP; -import static org.tron.protos.Protocol.ReasonCode.UNKNOWN; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.Collection; -import java.util.Locale; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.common.overlay.client.PeerClient; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.prometheus.MetricKeys; -import org.tron.common.prometheus.Metrics; -import org.tron.core.config.args.Args; -import org.tron.core.db.ByteArrayWrapper; -import org.tron.core.metrics.MetricsKey; -import org.tron.core.metrics.MetricsUtil; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.ReasonCode; - -@Slf4j(topic = "net") -@Component -public class ChannelManager { - - private final Map activeChannels = new ConcurrentHashMap<>(); - @Autowired - private PeerServer peerServer; - @Autowired - private PeerClient peerClient; - @Autowired - private SyncPool syncPool; - @Autowired - private PeerConnectionCheckService peerConnectionCheckService; - @Autowired - private FastForward fastForward; - private CommonParameter parameter = CommonParameter.getInstance(); - private Cache badPeers = CacheBuilder.newBuilder().maximumSize(10000) - .expireAfterWrite(1, TimeUnit.HOURS).recordStats().build(); - - private Cache recentlyDisconnected = CacheBuilder.newBuilder() - .maximumSize(1000).expireAfterWrite(30, TimeUnit.SECONDS).recordStats().build(); - - @Getter - private Cache helloMessageCache = CacheBuilder.newBuilder() - .maximumSize(2000).expireAfterWrite(24, TimeUnit.HOURS).recordStats().build(); - - @Getter - private Cache trustNodes = CacheBuilder.newBuilder().maximumSize(100).build(); - - @Getter - private Map activeNodes = new ConcurrentHashMap(); - - @Getter - private Map fastForwardNodes = new ConcurrentHashMap(); - - private int maxConnections = parameter.getMaxConnections(); - - private int maxConnectionsWithSameIp = parameter.getMaxConnectionsWithSameIp(); - - public void init() { - if (this.parameter.getNodeListenPort() > 0 && !this.parameter.isSolidityNode()) { - new Thread(() -> peerServer.start(Args.getInstance().getNodeListenPort()), - "PeerServerThread").start(); - } - - InetAddress address; - for (Node node : parameter.getPassiveNodes()) { - address = new InetSocketAddress(node.getHost(), node.getPort()).getAddress(); - trustNodes.put(address, node); - } - - for (Node node : parameter.getActiveNodes()) { - address = new InetSocketAddress(node.getHost(), node.getPort()).getAddress(); - trustNodes.put(address, node); - activeNodes.put(address, node); - } - - for (Node node : parameter.getFastForwardNodes()) { - address = new InetSocketAddress(node.getHost(), node.getPort()).getAddress(); - trustNodes.put(address, node); - fastForwardNodes.put(address, node); - } - - logger.info("Node config, trust {}, active {}, forward {}", - trustNodes.size(), activeNodes.size(), fastForwardNodes.size()); - - peerConnectionCheckService.init(); - syncPool.init(); - fastForward.init(); - } - - public void processDisconnect(Channel channel, ReasonCode reason) { - InetAddress inetAddress = channel.getInetAddress(); - if (inetAddress == null) { - return; - } - switch (reason) { - case BAD_PROTOCOL: - case BAD_BLOCK: - case BAD_TX: - badPeers.put(channel.getInetAddress(), reason); - break; - default: - recentlyDisconnected.put(channel.getInetAddress(), reason); - break; - } - MetricsUtil.counterInc(MetricsKey.NET_DISCONNECTION_COUNT); - MetricsUtil.counterInc(MetricsKey.NET_DISCONNECTION_DETAIL + reason); - Metrics.counterInc(MetricKeys.Counter.P2P_DISCONNECT, 1, - reason.name().toLowerCase(Locale.ROOT)); - } - - public void notifyDisconnect(Channel channel) { - syncPool.onDisconnect(channel); - activeChannels.values().remove(channel); - if (channel != null) { - if (channel.getNodeStatistics() != null) { - channel.getNodeStatistics().notifyDisconnect(); - } - InetAddress inetAddress = channel.getInetAddress(); - if (inetAddress != null && recentlyDisconnected.getIfPresent(inetAddress) == null) { - recentlyDisconnected.put(channel.getInetAddress(), UNKNOWN); - } - } - } - - public synchronized boolean processPeer(Channel peer) { - - if (trustNodes.getIfPresent(peer.getInetAddress()) == null) { - if (recentlyDisconnected.getIfPresent(peer) != null) { - logger.info("Peer {} recently disconnected", peer.getInetAddress()); - return false; - } - - if (badPeers.getIfPresent(peer) != null) { - peer.disconnect(peer.getNodeStatistics().getDisconnectReason()); - return false; - } - - if (!peer.isActive() && activeChannels.size() >= maxConnections) { - peer.disconnect(TOO_MANY_PEERS); - return false; - } - - if (getConnectionNum(peer.getInetAddress()) >= maxConnectionsWithSameIp) { - peer.disconnect(TOO_MANY_PEERS_WITH_SAME_IP); - return false; - } - } - - Channel channel = activeChannels.get(peer.getNodeIdWrapper()); - if (channel != null) { - if (channel.getStartTime() > peer.getStartTime()) { - logger.info("Disconnect connection established later, {}", channel.getNode()); - channel.disconnect(DUPLICATE_PEER); - } else { - peer.disconnect(DUPLICATE_PEER); - return false; - } - } - activeChannels.put(peer.getNodeIdWrapper(), peer); - logger.info("Add active peer {}, total active peers: {}", peer, activeChannels.size()); - return true; - } - - public int getConnectionNum(InetAddress inetAddress) { - int cnt = 0; - for (Channel channel : activeChannels.values()) { - if (channel.getInetAddress().equals(inetAddress)) { - cnt++; - } - } - return cnt; - } - - public Collection getActivePeers() { - return activeChannels.values(); - } - - public Cache getRecentlyDisconnected() { - return this.recentlyDisconnected; - } - - public Cache getBadPeers() { - return this.badPeers; - } - - public void close() { - peerConnectionCheckService.close(); - syncPool.close(); - peerServer.close(); - peerClient.close(); - } -} diff --git a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java b/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java deleted file mode 100644 index b36c7f31b5d..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/server/HandshakeHandler.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.server; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.ByteToMessageDecoder; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.Arrays; -import java.util.List; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; -import org.tron.common.overlay.discover.node.NodeManager; -import org.tron.common.overlay.message.DisconnectMessage; -import org.tron.common.overlay.message.HelloMessage; -import org.tron.common.overlay.message.P2pMessage; -import org.tron.common.overlay.message.P2pMessageFactory; -import org.tron.common.prometheus.MetricKeys; -import org.tron.common.prometheus.MetricLabels; -import org.tron.common.prometheus.Metrics; -import org.tron.common.utils.ByteArray; -import org.tron.core.ChainBaseManager; -import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; -import org.tron.core.metrics.MetricsKey; -import org.tron.core.metrics.MetricsUtil; -import org.tron.core.net.peer.PeerConnection; -import org.tron.protos.Protocol.ReasonCode; - -@Slf4j(topic = "net") -@Component -@Scope("prototype") -public class HandshakeHandler extends ByteToMessageDecoder { - - private Channel channel; - - @Autowired - private NodeManager nodeManager; - - @Autowired - private ChannelManager channelManager; - - @Autowired - private Manager manager; - - @Autowired - private ChainBaseManager chainBaseManager; - - @Autowired - private FastForward fastForward; - - private byte[] remoteId; - - private P2pMessageFactory messageFactory = new P2pMessageFactory(); - - @Autowired - private SyncPool syncPool; - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - logger.info("Channel active, {}", ctx.channel().remoteAddress()); - channel.setChannelHandlerContext(ctx); - if (remoteId.length == 64) { - channel.initNode(remoteId, ((InetSocketAddress) ctx.channel().remoteAddress()).getPort()); - sendHelloMsg(ctx, System.currentTimeMillis()); - } - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List out) - throws Exception { - byte[] encoded = new byte[buffer.readableBytes()]; - buffer.readBytes(encoded); - P2pMessage msg = messageFactory.create(encoded); - - logger.info("Handshake receive from {}, {}", ctx.channel().remoteAddress(), msg); - - switch (msg.getType()) { - case P2P_HELLO: - handleHelloMsg(ctx, (HelloMessage) msg); - break; - case P2P_DISCONNECT: - if (channel.getNodeStatistics() != null) { - channel.getNodeStatistics() - .nodeDisconnectedRemote(((DisconnectMessage) msg).getReasonCode()); - } - channel.close(); - break; - default: - channel.close(); - break; - } - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - channel.processException(cause); - } - - public void setChannel(Channel channel, String remoteId) { - this.channel = channel; - this.remoteId = Hex.decode(remoteId); - } - - protected void sendHelloMsg(ChannelHandlerContext ctx, long time) { - HelloMessage message = new HelloMessage( - nodeManager.getPublicHomeNode(), time, chainBaseManager); - fastForward.fillHelloMessage(message, channel); - ((PeerConnection) channel).setHelloMessageSend(message); - ctx.writeAndFlush(message.getSendData()); - int length = message.getSendData().readableBytes(); - channel.getNodeStatistics().messageStatistics.addTcpOutMessage(message); - MetricsUtil.meterMark(MetricsKey.NET_TCP_OUT_TRAFFIC, length); - Metrics.histogramObserve(MetricKeys.Histogram.TCP_BYTES, length, - MetricLabels.Histogram.TRAFFIC_OUT); - - logger.info("Handshake send to {}, {} ", ctx.channel().remoteAddress(), message); - } - - private void handleHelloMsg(ChannelHandlerContext ctx, HelloMessage msg) { - channel.initNode(msg.getFrom().getId(), msg.getFrom().getPort()); - - if (!msg.valid()) { - logger.warn("Peer {} invalid hello message parameters, " - + "GenesisBlockId: {}, SolidBlockId: {}, HeadBlockId: {}", - ctx.channel().remoteAddress(), - ByteArray.toHexString(msg.getInstance().getGenesisBlockId().getHash().toByteArray()), - ByteArray.toHexString(msg.getInstance().getSolidBlockId().getHash().toByteArray()), - ByteArray.toHexString(msg.getInstance().getHeadBlockId().getHash().toByteArray())); - channel.disconnect(ReasonCode.UNEXPECTED_IDENTITY); - return; - } - - channel.setAddress(msg.getHelloMessage().getAddress()); - - if (!fastForward.checkHelloMessage(msg, channel)) { - channel.disconnect(ReasonCode.UNEXPECTED_IDENTITY); - return; - } - - InetAddress address = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress(); - if (remoteId.length != 64 - && channelManager.getTrustNodes().getIfPresent(address) == null - && !syncPool.isCanConnect()) { - channel.disconnect(ReasonCode.TOO_MANY_PEERS); - return; - } - - long headBlockNum = chainBaseManager.getHeadBlockNum(); - long lowestBlockNum = msg.getLowestBlockNum(); - if (lowestBlockNum > headBlockNum) { - logger.info("Peer {} miss block, lowestBlockNum:{}, headBlockNum:{}", - ctx.channel().remoteAddress(), lowestBlockNum, headBlockNum); - channel.disconnect(ReasonCode.LIGHT_NODE_SYNC_FAIL); - return; - } - - if (msg.getVersion() != Args.getInstance().getNodeP2pVersion()) { - logger.info("Peer {} different p2p version, peer->{}, me->{}", - ctx.channel().remoteAddress(), msg.getVersion(), Args.getInstance().getNodeP2pVersion()); - channel.disconnect(ReasonCode.INCOMPATIBLE_VERSION); - return; - } - - if (!Arrays - .equals(chainBaseManager.getGenesisBlockId().getBytes(), - msg.getGenesisBlockId().getBytes())) { - logger - .info("Peer {} different genesis block, peer->{}, me->{}", ctx.channel().remoteAddress(), - msg.getGenesisBlockId().getString(), - chainBaseManager.getGenesisBlockId().getString()); - channel.disconnect(ReasonCode.INCOMPATIBLE_CHAIN); - return; - } - - if (chainBaseManager.getSolidBlockId().getNum() >= msg.getSolidBlockId().getNum() - && !chainBaseManager.containBlockInMainChain(msg.getSolidBlockId())) { - logger.info("Peer {} different solid block, peer->{}, me->{}", ctx.channel().remoteAddress(), - msg.getSolidBlockId().getString(), chainBaseManager.getSolidBlockId().getString()); - channel.disconnect(ReasonCode.FORKED); - return; - } - - if (msg.getFrom().getHost().equals(address.getHostAddress())) { - channelManager.getHelloMessageCache().put(msg.getFrom().getHost(), msg.getHelloMessage()); - } - - ((PeerConnection) channel).setHelloMessageReceive(msg); - - channel.getNodeStatistics().messageStatistics.addTcpInMessage(msg); - - channel.publicHandshakeFinished(ctx, msg); - if (!channelManager.processPeer(channel)) { - return; - } - - if (remoteId.length != 64) { - sendHelloMsg(ctx, msg.getTimestamp()); - } - - syncPool.onConnect(channel); - } -} diff --git a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java b/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java deleted file mode 100644 index de59cb85736..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/server/MessageQueue.java +++ /dev/null @@ -1,217 +0,0 @@ -package org.tron.common.overlay.server; - -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import java.util.Queue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; -import org.tron.common.overlay.message.Message; -import org.tron.common.overlay.message.PingMessage; -import org.tron.common.overlay.message.PongMessage; -import org.tron.common.prometheus.MetricKeys; -import org.tron.common.prometheus.MetricLabels; -import org.tron.common.prometheus.Metrics; -import org.tron.consensus.pbft.message.PbftBaseMessage; -import org.tron.core.metrics.MetricsKey; -import org.tron.core.metrics.MetricsUtil; -import org.tron.core.net.message.InventoryMessage; -import org.tron.core.net.message.TransactionsMessage; -import org.tron.protos.Protocol.Inventory.InventoryType; -import org.tron.protos.Protocol.ReasonCode; - -@Slf4j(topic = "net") -@Component -@Scope("prototype") -public class MessageQueue { - - private static ScheduledExecutorService sendTimer = - Executors.newSingleThreadScheduledExecutor(r -> new Thread(r, "sendTimer")); - private volatile boolean sendMsgFlag = false; - private volatile long sendTime; - private volatile long sendPing; - private Thread sendMsgThread; - private Channel channel; - private ChannelHandlerContext ctx = null; - private Queue requestQueue = new ConcurrentLinkedQueue<>(); - private BlockingQueue msgQueue = new LinkedBlockingQueue<>(); - private ScheduledFuture sendTask; - - - public void activate(ChannelHandlerContext ctx) { - - this.ctx = ctx; - - sendMsgFlag = true; - - sendTask = sendTimer.scheduleAtFixedRate(() -> { - try { - if (sendMsgFlag) { - send(); - } - } catch (Exception e) { - logger.error("Unhandled exception", e); - } - }, 10, 10, TimeUnit.MILLISECONDS); - - sendMsgThread = new Thread(() -> { - while (sendMsgFlag) { - try { - if (msgQueue.isEmpty()) { - Thread.sleep(10); - continue; - } - Message msg = msgQueue.take(); - if (channel.isDisconnect()) { - logger.warn("Failed to send to {} as channel has closed, {}", - ctx.channel().remoteAddress(), msg); - msgQueue.clear(); - return; - } - ctx.writeAndFlush(msg.getSendData()).addListener((ChannelFutureListener) future -> { - if (!future.isSuccess() && !channel.isDisconnect()) { - logger.warn("Failed to send to {}, {} ", ctx.channel().remoteAddress(), msg); - } - }); - } catch (InterruptedException e) { - logger.warn("Send message server interrupted"); - Thread.currentThread().interrupt(); - } catch (Exception e) { - logger.error("Failed to send to {} ", ctx.channel().remoteAddress(), e); - } - } - }); - sendMsgThread.setName("sendMsgThread-" + ctx.channel().remoteAddress()); - sendMsgThread.start(); - } - - public void setChannel(Channel channel) { - this.channel = channel; - } - - public void fastSend(Message msg) { - if (channel.isDisconnect()) { - logger.warn("Fast send to {} failed as channel has closed, {} ", - ctx.channel().remoteAddress(), msg); - return; - } - logger.info("Fast send to {}, {} ", ctx.channel().remoteAddress(), msg); - ctx.writeAndFlush(msg.getSendData()).addListener((ChannelFutureListener) future -> { - if (!future.isSuccess() && !channel.isDisconnect()) { - logger.warn("Fast send to {} failed, {}", ctx.channel().remoteAddress(), msg); - } - }); - } - - public boolean sendMessage(Message msg) { - long now = System.currentTimeMillis(); - if (msg instanceof PingMessage) { - if (now - sendTime < 10_000 && now - sendPing < 60_000) { - return false; - } - sendPing = now; - } - if (needToLog(msg)) { - logger.info("Send to {}, {} ", ctx.channel().remoteAddress(), msg); - } - channel.getNodeStatistics().messageStatistics.addTcpOutMessage(msg); - int length = msg.getSendData().readableBytes(); - MetricsUtil.meterMark(MetricsKey.NET_TCP_OUT_TRAFFIC, length); - Metrics.histogramObserve(MetricKeys.Histogram.TCP_BYTES, length, - MetricLabels.Histogram.TRAFFIC_OUT); - - sendTime = System.currentTimeMillis(); - if (msg.getAnswerMessage() != null) { - requestQueue.add(new MessageRoundTrip(msg)); - } else { - msgQueue.offer(msg); - } - return true; - } - - public void receivedMessage(Message msg) { - if (needToLog(msg)) { - logger.info("Receive from {}, {}", ctx.channel().remoteAddress(), msg); - } - channel.getNodeStatistics().messageStatistics.addTcpInMessage(msg); - MessageRoundTrip rt = requestQueue.peek(); - if (rt != null && rt.getMsg().getAnswerMessage() == msg.getClass()) { - requestQueue.remove(); - if (rt.getMsg() instanceof PingMessage) { - channel.getNodeStatistics().pingMessageLatency - .add(System.currentTimeMillis() - rt.getTime()); - } - } - } - - public void close() { - sendMsgFlag = false; - if (sendTask != null && !sendTask.isCancelled()) { - sendTask.cancel(true); - sendTask = null; - } - if (sendMsgThread != null) { - try { - sendMsgThread.join(20); - sendMsgThread = null; - } catch (InterruptedException e) { - logger.warn("Send message join interrupted"); - Thread.currentThread().interrupt(); - } catch (Exception e) { - logger.warn("Join send thread failed, peer {}", ctx.channel().remoteAddress()); - } - } - } - - private boolean needToLog(Message msg) { - if (msg instanceof PingMessage - || msg instanceof PongMessage - || msg instanceof TransactionsMessage - || msg instanceof PbftBaseMessage) { - return false; - } - - if (msg instanceof InventoryMessage - && ((InventoryMessage) msg).getInventoryType().equals(InventoryType.TRX)) { - return false; - } - - return true; - } - - private void send() { - MessageRoundTrip rt = requestQueue.peek(); - if (!sendMsgFlag || rt == null) { - return; - } - if (rt.getRetryTimes() > 0 && !rt.hasToRetry()) { - return; - } - if (rt.getRetryTimes() > 0) { - channel.getNodeStatistics().nodeDisconnectedLocal(ReasonCode.PING_TIMEOUT); - logger.warn("Wait {} timeout. close channel {}", - rt.getMsg().getAnswerMessage(), ctx.channel().remoteAddress()); - channel.close(); - return; - } - - Message msg = rt.getMsg(); - - ctx.writeAndFlush(msg.getSendData()).addListener((ChannelFutureListener) future -> { - if (!future.isSuccess()) { - logger.warn("Fail send to {}, {}", ctx.channel().remoteAddress(), msg); - } - }); - - rt.incRetryTimes(); - rt.saveTime(); - } - -} diff --git a/framework/src/main/java/org/tron/common/overlay/server/MessageRoundTrip.java b/framework/src/main/java/org/tron/common/overlay/server/MessageRoundTrip.java deleted file mode 100644 index d14954c4bf9..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/server/MessageRoundTrip.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.tron.common.overlay.server; - -import org.tron.common.overlay.message.Message; - -public class MessageRoundTrip { - - private final Message msg; - private long time = 0; - private long retryTimes = 0; - - public MessageRoundTrip(Message msg) { - this.msg = msg; - saveTime(); - } - - public long getRetryTimes() { - return retryTimes; - } - - public void incRetryTimes() { - ++retryTimes; - } - - public void saveTime() { - time = System.currentTimeMillis(); - } - - public long getTime() { - return time; - } - - public boolean hasToRetry() { - return 20000 < System.currentTimeMillis() - time; - } - - public Message getMsg() { - return msg; - } -} diff --git a/framework/src/main/java/org/tron/common/overlay/server/P2pHandler.java b/framework/src/main/java/org/tron/common/overlay/server/P2pHandler.java deleted file mode 100644 index 3346506396d..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/server/P2pHandler.java +++ /dev/null @@ -1,103 +0,0 @@ -package org.tron.common.overlay.server; - -import static org.tron.common.overlay.message.StaticMessages.PING_MESSAGE; -import static org.tron.common.overlay.message.StaticMessages.PONG_MESSAGE; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; -import org.tron.common.overlay.discover.node.statistics.MessageStatistics; -import org.tron.common.overlay.message.DisconnectMessage; -import org.tron.common.overlay.message.P2pMessage; -import org.tron.protos.Protocol.ReasonCode; - -@Slf4j(topic = "net") -@Component -@Scope("prototype") -public class P2pHandler extends SimpleChannelInboundHandler { - - private static ScheduledExecutorService pingTimer = - Executors.newSingleThreadScheduledExecutor(r -> new Thread(r, "P2pPingTimer")); - - private MessageQueue msgQueue; - - private Channel channel; - - private ScheduledFuture pingTask; - - private volatile boolean hasPing = false; - - @Override - public void handlerAdded(ChannelHandlerContext ctx) { - pingTask = pingTimer.scheduleAtFixedRate(() -> { - if (!hasPing) { - hasPing = msgQueue.sendMessage(PING_MESSAGE); - } - }, 10, 10, TimeUnit.SECONDS); - } - - @Override - public void channelRead0(final ChannelHandlerContext ctx, P2pMessage msg) { - - msgQueue.receivedMessage(msg); - MessageStatistics messageStatistics = channel.getNodeStatistics().messageStatistics; - switch (msg.getType()) { - case P2P_PING: - int count = messageStatistics.p2pInPing.getCount(10); - if (count > 3) { - logger.warn("TCP attack found: {} with ping count({})", ctx.channel().remoteAddress(), - count); - channel.disconnect(ReasonCode.BAD_PROTOCOL); - return; - } - msgQueue.sendMessage(PONG_MESSAGE); - break; - case P2P_PONG: - if (messageStatistics.p2pInPong.getTotalCount() > messageStatistics.p2pOutPing - .getTotalCount()) { - logger.warn("TCP attack found: {} with ping count({}), pong count({})", - ctx.channel().remoteAddress(), - messageStatistics.p2pOutPing.getTotalCount(), - messageStatistics.p2pInPong.getTotalCount()); - channel.disconnect(ReasonCode.BAD_PROTOCOL); - return; - } - hasPing = false; - channel.getNodeStatistics().lastPongReplyTime.set(System.currentTimeMillis()); - break; - case P2P_DISCONNECT: - channel.getNodeStatistics() - .nodeDisconnectedRemote(((DisconnectMessage) msg).getReasonCode()); - channel.close(); - break; - default: - channel.close(); - break; - } - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - channel.processException(cause); - } - - public void setMsgQueue(MessageQueue msgQueue) { - this.msgQueue = msgQueue; - } - - public void setChannel(Channel channel) { - this.channel = channel; - } - - public void close() { - if (pingTask != null && !pingTask.isCancelled()) { - pingTask.cancel(false); - } - } -} \ No newline at end of file diff --git a/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java b/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java deleted file mode 100644 index e0d9d39b4a7..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/server/PeerConnectionCheckService.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.tron.common.overlay.server; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Random; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.tron.core.config.args.Args; -import org.tron.core.net.peer.PeerConnection; -import org.tron.protos.Protocol; - -@Slf4j(topic = "net") -@Service -public class PeerConnectionCheckService { - private int maxConnections = Args.getInstance().getMaxConnections(); - private boolean isFastForward = Args.getInstance().isFastForward(); - private boolean isOpenFullTcpDisconnect = Args.getInstance().isOpenFullTcpDisconnect(); - private ScheduledExecutorService poolLoopExecutor = Executors.newSingleThreadScheduledExecutor(); - - @Autowired - private SyncPool syncPool; - - public void init() { - if (isFastForward || !isOpenFullTcpDisconnect) { - return; - } - logger.info("Start peer connection check service"); - poolLoopExecutor.scheduleWithFixedDelay(() -> { - try { - check(); - } catch (Throwable t) { - logger.error("Exception in peer connection check", t); - } - }, 10, 30, TimeUnit.SECONDS); - } - - public void close() { - logger.info("Close peer connection check service"); - poolLoopExecutor.shutdown(); - } - - public void check() { - if (syncPool.getActivePeers().size() < maxConnections) { - return; - } - Collection peers = syncPool.getActivePeers().stream() - .filter(peer -> peer.isIdle()) - .filter(peer -> !peer.isTrustPeer()) - .filter(peer -> !peer.isActive()) - .collect(Collectors.toList()); - if (peers.size() == 0) { - return; - } - List list = new ArrayList(); - peers.forEach(p -> list.add(p)); - PeerConnection peer = list.get(new Random().nextInt(peers.size())); - peer.disconnect(Protocol.ReasonCode.RANDOM_ELIMINATION); - } -} diff --git a/framework/src/main/java/org/tron/common/overlay/server/PeerServer.java b/framework/src/main/java/org/tron/common/overlay/server/PeerServer.java deleted file mode 100644 index e00372e9a5d..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/server/PeerServer.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.tron.common.overlay.server; - -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.DefaultMessageSizeEstimator; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import io.netty.handler.logging.LoggingHandler; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.stereotype.Component; -import org.tron.common.parameter.CommonParameter; -import org.tron.core.config.args.Args; - -@Slf4j(topic = "net") -@Component -public class PeerServer { - - private CommonParameter parameter = CommonParameter.getInstance(); - - private ApplicationContext ctx; - - private boolean listening; - - private ChannelFuture channelFuture; - - @Autowired - public PeerServer(final Args args, final ApplicationContext ctx) { - this.ctx = ctx; - } - - public void start(int port) { - - EventLoopGroup bossGroup = new NioEventLoopGroup(1); - EventLoopGroup workerGroup = new NioEventLoopGroup(parameter.getTcpNettyWorkThreadNum()); - TronChannelInitializer tronChannelInitializer = ctx.getBean(TronChannelInitializer.class, ""); - - try { - ServerBootstrap b = new ServerBootstrap(); - - b.group(bossGroup, workerGroup); - b.channel(NioServerSocketChannel.class); - - b.option(ChannelOption.MESSAGE_SIZE_ESTIMATOR, DefaultMessageSizeEstimator.DEFAULT); - b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, this.parameter.getNodeConnectionTimeout()); - - b.handler(new LoggingHandler()); - b.childHandler(tronChannelInitializer); - - // Start the client. - logger.info("TCP listener started, bind port {}", port); - - channelFuture = b.bind(port).sync(); - - listening = true; - - // Wait until the connection is closed. - channelFuture.channel().closeFuture().sync(); - - logger.info("TCP listener closed"); - - } catch (Exception e) { - logger.error("Start TCP server failed", e); - } finally { - workerGroup.shutdownGracefully(); - bossGroup.shutdownGracefully(); - listening = false; - } - } - - public void close() { - if (listening && channelFuture != null && channelFuture.channel().isOpen()) { - try { - logger.info("Closing TCP server..."); - channelFuture.channel().close().sync(); - } catch (Exception e) { - logger.error("Closing TCP server failed", e); - } - } - } -} diff --git a/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java b/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java deleted file mode 100644 index e4b28494404..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/server/SyncPool.java +++ /dev/null @@ -1,265 +0,0 @@ -package org.tron.common.overlay.server; - -import com.codahale.metrics.Snapshot; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.collect.Lists; -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Predicate; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.stereotype.Component; -import org.tron.common.overlay.client.PeerClient; -import org.tron.common.overlay.discover.node.NodeHandler; -import org.tron.common.overlay.discover.node.NodeManager; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.prometheus.MetricKeys; -import org.tron.common.prometheus.MetricLabels; -import org.tron.common.prometheus.Metrics; -import org.tron.core.ChainBaseManager; -import org.tron.core.config.args.Args; -import org.tron.core.metrics.MetricsKey; -import org.tron.core.metrics.MetricsUtil; -import org.tron.core.net.peer.PeerConnection; -import org.tron.protos.Protocol; - -@Slf4j(topic = "net") -@Component -public class SyncPool { - private final List activePeers = Collections - .synchronizedList(new ArrayList<>()); - private Cache nodeHandlerCache = CacheBuilder.newBuilder() - .maximumSize(1000).expireAfterWrite(180, TimeUnit.SECONDS).recordStats().build(); - private final AtomicInteger passivePeersCount = new AtomicInteger(0); - private final AtomicInteger activePeersCount = new AtomicInteger(0); - - @Autowired - private NodeManager nodeManager; - - @Autowired - private ApplicationContext ctx; - - @Autowired - private ChainBaseManager chainBaseManager; - - private ChannelManager channelManager; - - private CommonParameter commonParameter = CommonParameter.getInstance(); - - private int maxConnectionsWithSameIp = commonParameter.getMaxConnectionsWithSameIp(); - - private ScheduledExecutorService poolLoopExecutor = Executors.newSingleThreadScheduledExecutor(); - - private ScheduledExecutorService logExecutor = Executors.newSingleThreadScheduledExecutor(); - - private PeerClient peerClient; - - private int disconnectTimeout = 60_000; - - private int maxConnections = Args.getInstance().getMaxConnections(); - private int minConnections = Args.getInstance().getMinConnections(); - private int minActiveConnections = Args.getInstance().getMinActiveConnections(); - - public void init() { - - channelManager = ctx.getBean(ChannelManager.class); - - peerClient = ctx.getBean(PeerClient.class); - - poolLoopExecutor.scheduleWithFixedDelay(() -> { - try { - check(); - fillUp(); - } catch (Throwable t) { - logger.error("Exception in sync worker", t); - } - }, 100, 3600, TimeUnit.MILLISECONDS); - - logExecutor.scheduleWithFixedDelay(() -> { - try { - logActivePeers(); - } catch (Throwable t) { - logger.error("Exception in sync worker", t); - } - }, 30, 10, TimeUnit.SECONDS); - } - - private void check() { - for (PeerConnection peer : new ArrayList<>(activePeers)) { - long now = System.currentTimeMillis(); - long disconnectTime = peer.getDisconnectTime(); - if (disconnectTime != 0 && now - disconnectTime > disconnectTimeout) { - logger.warn("Notify disconnect peer {}.", peer.getInetAddress()); - channelManager.notifyDisconnect(peer); - } - } - } - - private void fillUp() { - List connectNodes = new ArrayList<>(); - Set addressInUse = new HashSet<>(); - Set nodesInUse = new HashSet<>(); - channelManager.getActivePeers().forEach(channel -> { - nodesInUse.add(channel.getPeerId()); - addressInUse.add(channel.getInetAddress()); - }); - - channelManager.getActiveNodes().forEach((address, node) -> { - nodesInUse.add(node.getHexId()); - if (!addressInUse.contains(address)) { - connectNodes.add(nodeManager.getNodeHandler(node)); - } - }); - - int size = Math.max(minConnections - activePeers.size(), - minActiveConnections - activePeersCount.get()); - int lackSize = size - connectNodes.size(); - if (lackSize > 0) { - nodesInUse.add(nodeManager.getPublicHomeNode().getHexId()); - List newNodes = nodeManager.getNodes(new NodeSelector(nodesInUse), lackSize); - connectNodes.addAll(newNodes); - } - - connectNodes.forEach(n -> { - peerClient.connectAsync(n, false); - nodeHandlerCache.put(n, System.currentTimeMillis()); - }); - } - - synchronized void logActivePeers() { - String str = String.format("\n\n============ Peer stats: all %d, active %d, passive %d\n\n", - channelManager.getActivePeers().size(), activePeersCount.get(), passivePeersCount.get()); - metric(channelManager.getActivePeers().size(), MetricLabels.Gauge.PEERS_ALL); - metric(activePeersCount.get(), MetricLabels.Gauge.PEERS_ACTIVE); - metric(passivePeersCount.get(), MetricLabels.Gauge.PEERS_PASSIVE); - StringBuilder sb = new StringBuilder(str); - int valid = 0; - for (PeerConnection peer : new ArrayList<>(activePeers)) { - sb.append(peer.log()); - appendPeerLatencyLog(sb, peer); - sb.append("\n"); - if (!(peer.isNeedSyncFromUs() || peer.isNeedSyncFromPeer())) { - valid++; - } - } - metric(valid, MetricLabels.Gauge.PEERS_VALID); - logger.info(sb.toString()); - } - - private void metric(double amt, String peerType) { - Metrics.gaugeSet(MetricKeys.Gauge.PEERS, amt, peerType); - } - - private void appendPeerLatencyLog(StringBuilder builder, PeerConnection peer) { - Snapshot peerSnapshot = MetricsUtil.getHistogram(MetricsKey.NET_LATENCY_FETCH_BLOCK - + peer.getNode().getHost()).getSnapshot(); - builder.append(String.format( - "top99 : %f, top95 : %f, top75 : %f, max : %d, min : %d, mean : %f, median : %f", - peerSnapshot.get99thPercentile(), peerSnapshot.get95thPercentile(), - peerSnapshot.get75thPercentile(), peerSnapshot.getMax(), peerSnapshot.getMin(), - peerSnapshot.getMean(), peerSnapshot.getMedian())).append("\n"); - } - - public List getActivePeers() { - List peers = Lists.newArrayList(); - for (PeerConnection peer : new ArrayList<>(activePeers)) { - if (!peer.isDisconnect()) { - peers.add(peer); - } - } - return peers; - } - - public synchronized void onConnect(Channel peer) { - PeerConnection peerConnection = (PeerConnection) peer; - if (!activePeers.contains(peerConnection)) { - if (!peerConnection.isActive()) { - passivePeersCount.incrementAndGet(); - } else { - activePeersCount.incrementAndGet(); - } - activePeers.add(peerConnection); - activePeers - .sort(Comparator.comparingDouble( - c -> c.getNodeStatistics().pingMessageLatency.getAvg())); - peerConnection.onConnect(); - } - } - - public synchronized void onDisconnect(Channel peer) { - PeerConnection peerConnection = (PeerConnection) peer; - if (activePeers.contains(peerConnection)) { - if (!peerConnection.isActive()) { - passivePeersCount.decrementAndGet(); - } else { - activePeersCount.decrementAndGet(); - } - activePeers.remove(peerConnection); - peerConnection.onDisconnect(); - } - } - - public boolean isCanConnect() { - return passivePeersCount.get() < maxConnections - minActiveConnections; - } - - public void close() { - try { - activePeers.forEach(p -> { - if (!p.isDisconnect()) { - p.close(); - } - }); - poolLoopExecutor.shutdownNow(); - logExecutor.shutdownNow(); - } catch (Exception e) { - logger.error("Problems shutting down executor", e); - } - } - - public AtomicInteger getPassivePeersCount() { - return passivePeersCount; - } - - public AtomicInteger getActivePeersCount() { - return activePeersCount; - } - - class NodeSelector implements Predicate { - - private Set nodesInUse; - - public NodeSelector(Set nodesInUse) { - this.nodesInUse = nodesInUse; - } - - @Override - public boolean test(NodeHandler handler) { - long headNum = chainBaseManager.getHeadBlockNum(); - InetAddress inetAddress = handler.getInetSocketAddress().getAddress(); - Protocol.HelloMessage message = channelManager.getHelloMessageCache() - .getIfPresent(inetAddress.getHostAddress()); - return !((handler.getNode().getHost().equals(nodeManager.getPublicHomeNode().getHost()) - && handler.getNode().getPort() == nodeManager.getPublicHomeNode().getPort()) - || (channelManager.getRecentlyDisconnected().getIfPresent(inetAddress) != null) - || (channelManager.getBadPeers().getIfPresent(inetAddress) != null) - || (channelManager.getConnectionNum(inetAddress) >= maxConnectionsWithSameIp) - || (nodesInUse.contains(handler.getNode().getHexId())) - || (nodeHandlerCache.getIfPresent(handler) != null) - || (message != null && headNum < message.getLowestBlockNum())); - } - } - -} diff --git a/framework/src/main/java/org/tron/common/overlay/server/TronChannelInitializer.java b/framework/src/main/java/org/tron/common/overlay/server/TronChannelInitializer.java deleted file mode 100644 index f6732adadd5..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/server/TronChannelInitializer.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.tron.common.overlay.server; - -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOption; -import io.netty.channel.FixedRecvByteBufAllocator; -import io.netty.channel.socket.nio.NioSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; -import org.tron.core.net.peer.PeerConnection; - -@Slf4j(topic = "net") -@Component -@Scope("prototype") -public class TronChannelInitializer extends ChannelInitializer { - - @Autowired - private ApplicationContext ctx; - - @Autowired - private ChannelManager channelManager; - - private String remoteId; - - private boolean peerDiscoveryMode = false; - - public TronChannelInitializer(String remoteId) { - this.remoteId = remoteId; - } - - @Override - public void initChannel(NioSocketChannel ch) throws Exception { - try { - final Channel channel = ctx.getBean(PeerConnection.class); - - channel.init(ch.pipeline(), remoteId, peerDiscoveryMode, channelManager); - - // limit the size of receiving buffer to 1024 - ch.config().setRecvByteBufAllocator(new FixedRecvByteBufAllocator(256 * 1024)); - ch.config().setOption(ChannelOption.SO_RCVBUF, 256 * 1024); - ch.config().setOption(ChannelOption.SO_BACKLOG, 1024); - - // be aware of channel closing - ch.closeFuture().addListener((ChannelFutureListener) future -> { - logger.info("Close channel: {}", channel); - if (!peerDiscoveryMode) { - channelManager.notifyDisconnect(channel); - } - }); - - } catch (Exception e) { - logger.error("Unexpected error: ", e); - } - } - - public void setPeerDiscoveryMode(boolean peerDiscoveryMode) { - this.peerDiscoveryMode = peerDiscoveryMode; - } -} diff --git a/framework/src/main/java/org/tron/common/overlay/server/TrxProtobufVarint32FrameDecoder.java b/framework/src/main/java/org/tron/common/overlay/server/TrxProtobufVarint32FrameDecoder.java deleted file mode 100644 index b6696200aff..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/server/TrxProtobufVarint32FrameDecoder.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.tron.common.overlay.server; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.ByteToMessageDecoder; -import io.netty.handler.codec.CorruptedFrameException; -import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class TrxProtobufVarint32FrameDecoder extends ByteToMessageDecoder { - - private static final Logger logger = LoggerFactory - .getLogger(TrxProtobufVarint32FrameDecoder.class); - - private static final int maxMsgLength = 5 * 1024 * 1024;//5M - - private Channel channel; - - public TrxProtobufVarint32FrameDecoder(Channel channel) { - this.channel = channel; - } - - private static int readRawVarint32(ByteBuf buffer) { - if (!buffer.isReadable()) { - return 0; - } - buffer.markReaderIndex(); - byte tmp = buffer.readByte(); - if (tmp >= 0) { - return tmp; - } else { - int result = tmp & 127; - if (!buffer.isReadable()) { - buffer.resetReaderIndex(); - return 0; - } - if ((tmp = buffer.readByte()) >= 0) { - result |= tmp << 7; - } else { - result |= (tmp & 127) << 7; - if (!buffer.isReadable()) { - buffer.resetReaderIndex(); - return 0; - } - if ((tmp = buffer.readByte()) >= 0) { - result |= tmp << 14; - } else { - result |= (tmp & 127) << 14; - if (!buffer.isReadable()) { - buffer.resetReaderIndex(); - return 0; - } - if ((tmp = buffer.readByte()) >= 0) { - result |= tmp << 21; - } else { - result |= (tmp & 127) << 21; - if (!buffer.isReadable()) { - buffer.resetReaderIndex(); - return 0; - } - result |= (tmp = buffer.readByte()) << 28; - if (tmp < 0) { - throw new CorruptedFrameException("malformed varint."); - } - } - } - } - return result; - } - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { - in.markReaderIndex(); - int preIndex = in.readerIndex(); - int length = readRawVarint32(in); - if (length >= maxMsgLength) { - logger.warn("Recv a big msg, host : {}, msg length is : {}", ctx.channel().remoteAddress(), - length); - in.clear(); - channel.close(); - return; - } - if (preIndex == in.readerIndex()) { - return; - } - if (length < 0) { - throw new CorruptedFrameException("negative length: " + length); - } - - if (in.readableBytes() < length) { - in.resetReaderIndex(); - } else { - out.add(in.readRetainedSlice(length)); - } - } -} - diff --git a/framework/src/main/java/org/tron/common/overlay/server/WireTrafficStats.java b/framework/src/main/java/org/tron/common/overlay/server/WireTrafficStats.java deleted file mode 100644 index 757e302626c..00000000000 --- a/framework/src/main/java/org/tron/common/overlay/server/WireTrafficStats.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.overlay.server; - -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import io.netty.channel.socket.DatagramPacket; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import javax.annotation.PreDestroy; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -@Slf4j(topic = "net") -@Component -public class WireTrafficStats implements Runnable { - - public final TrafficStatHandler tcp = new TrafficStatHandler(); - public final TrafficStatHandler udp = new TrafficStatHandler(); - private ScheduledExecutorService executor; - - public WireTrafficStats() { - executor = Executors.newSingleThreadScheduledExecutor( - new ThreadFactoryBuilder().setNameFormat("WireTrafficStats-%d").build()); - executor.scheduleAtFixedRate(this, 10, 10, TimeUnit.SECONDS); - } - - @Override - public void run() { - } - - @PreDestroy - public void close() { - executor.shutdownNow(); - } - - @ChannelHandler.Sharable - static class TrafficStatHandler extends ChannelDuplexHandler { - - private AtomicLong outSize = new AtomicLong(); - private AtomicLong inSize = new AtomicLong(); - private AtomicLong outPackets = new AtomicLong(); - private AtomicLong inPackets = new AtomicLong(); - - public String stats() { - return ""; - } - - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - inPackets.incrementAndGet(); - if (msg instanceof ByteBuf) { - inSize.addAndGet(((ByteBuf) msg).readableBytes()); - } else if (msg instanceof DatagramPacket) { - inSize.addAndGet(((DatagramPacket) msg).content().readableBytes()); - } - super.channelRead(ctx, msg); - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) - throws Exception { - outPackets.incrementAndGet(); - if (msg instanceof ByteBuf) { - outSize.addAndGet(((ByteBuf) msg).readableBytes()); - } else if (msg instanceof DatagramPacket) { - outSize.addAndGet(((DatagramPacket) msg).content().readableBytes()); - } - super.write(ctx, msg, promise); - } - } -} diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 6cb7e9b9d01..3079f5764d4 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -102,8 +102,6 @@ import org.tron.common.crypto.Hash; import org.tron.common.crypto.SignInterface; import org.tron.common.crypto.SignUtils; -import org.tron.common.overlay.discover.node.NodeHandler; -import org.tron.common.overlay.discover.node.NodeManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.runtime.ProgramResult; import org.tron.common.runtime.vm.LogInfo; @@ -177,7 +175,7 @@ import org.tron.core.exception.ZksnarkException; import org.tron.core.net.TronNetDelegate; import org.tron.core.net.TronNetService; -import org.tron.core.net.message.TransactionMessage; +import org.tron.core.net.message.adv.TransactionMessage; import org.tron.core.store.AccountIdIndexStore; import org.tron.core.store.AccountStore; import org.tron.core.store.AccountTraceStore; @@ -266,8 +264,6 @@ public class Wallet { @Autowired private ChainBaseManager chainBaseManager; - @Autowired - private NodeManager nodeManager; private int minEffectiveConnection = Args.getInstance().getMinEffectiveConnection(); private boolean trxCacheEnable = Args.getInstance().isTrxCacheEnable(); public static final String CONTRACT_VALIDATE_EXCEPTION = "ContractValidateException: {}"; @@ -2426,26 +2422,14 @@ public TransactionInfoList getTransactionInfoByBlockNum(long blockNum) { } public NodeList listNodes() { - List handlerList = nodeManager.dumpActiveNodes(); - - Map nodeHandlerMap = new HashMap<>(); - for (NodeHandler handler : handlerList) { - String key = handler.getNode().getHexId() + handler.getNode().getHost(); - nodeHandlerMap.put(key, handler); - } - NodeList.Builder nodeListBuilder = NodeList.newBuilder(); - - nodeHandlerMap.entrySet().stream() - .forEach(v -> { - org.tron.common.overlay.discover.node.Node node = v.getValue() - .getNode(); - nodeListBuilder.addNodes(Node.newBuilder().setAddress( + TronNetService.getP2pService().getConnectableNodes().forEach(node -> { + nodeListBuilder.addNodes(Node.newBuilder().setAddress( Address.newBuilder() - .setHost(ByteString - .copyFrom(ByteArray.fromString(node.getHost()))) - .setPort(node.getPort()))); - }); + .setHost(ByteString + .copyFrom(ByteArray.fromString(node.getHost()))) + .setPort(node.getPort()))); + }); return nodeListBuilder.build(); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 1625a4c684d..c926fe29724 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -19,6 +19,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.net.InetAddress; +import java.net.InetSocketAddress; import java.net.Socket; import java.net.URL; import java.nio.file.Paths; @@ -56,7 +57,6 @@ import org.tron.common.logsfilter.TriggerConfig; import org.tron.common.logsfilter.trigger.ContractEventTrigger; import org.tron.common.logsfilter.trigger.ContractLogTrigger; -import org.tron.common.overlay.discover.node.Node; import org.tron.common.parameter.CommonParameter; import org.tron.common.parameter.RateLimiterInitialization; import org.tron.common.setting.RocksDbSettings; @@ -886,11 +886,11 @@ public static void setParam(final String[] args, final String confFileName) { .getInt(Constant.NODE_VALID_CONTRACT_PROTO_THREADS) : Runtime.getRuntime().availableProcessors(); - PARAMETER.activeNodes = getNodes(config, Constant.NODE_ACTIVE); + PARAMETER.activeNodes = getInetSocketAddress(config, Constant.NODE_ACTIVE); - PARAMETER.passiveNodes = getNodes(config, Constant.NODE_PASSIVE); + PARAMETER.passiveNodes = getInetAddress(config, Constant.NODE_PASSIVE); - PARAMETER.fastForwardNodes = getNodes(config, Constant.NODE_FAST_FORWARD); + PARAMETER.fastForwardNodes = getInetSocketAddress(config, Constant.NODE_FAST_FORWARD); PARAMETER.maxFastForwardNum = config.hasPath(Constant.NODE_MAX_FAST_FORWARD_NUM) ? config .getInt(Constant.NODE_MAX_FAST_FORWARD_NUM) : 3; @@ -1108,25 +1108,46 @@ private static RateLimiterInitialization getRateLimiterFromConfig( return initialization; } - private static List getNodes(final com.typesafe.config.Config config, String path) { + private static List getInetSocketAddress( + final com.typesafe.config.Config config, String path) { if (!config.hasPath(path)) { return Collections.emptyList(); } - List ret = new ArrayList<>(); + List ret = new ArrayList<>(); List list = config.getStringList(path); for (String configString : list) { - Node n = Node.instanceOf(configString); - if (!(PARAMETER.nodeDiscoveryBindIp.equals(n.getHost()) - || PARAMETER.nodeExternalIp.equals(n.getHost()) - || Constant.LOCAL_HOST.equals(n.getHost())) - || PARAMETER.nodeListenPort != n.getPort()) { - ret.add(n); + String[] sz = configString.split(":"); + String ip = sz[0]; + int port = Integer.parseInt(sz[1]); + if (!(PARAMETER.nodeDiscoveryBindIp.equals(ip) + || PARAMETER.nodeExternalIp.equals(ip) + || Constant.LOCAL_HOST.equals(ip)) + || PARAMETER.nodeListenPort != port) { + ret.add(new InetSocketAddress(ip, port)); } } return ret; } - private static EventPluginConfig getEventPluginConfig(final com.typesafe.config.Config config) { + private static List getInetAddress( + final com.typesafe.config.Config config, String path) { + if (!config.hasPath(path)) { + return Collections.emptyList(); + } + List ret = new ArrayList<>(); + List list = config.getStringList(path); + for (String configString : list) { + try { + ret.add(InetAddress.getByName(configString.split(":")[0])); + } catch (Exception e) { + logger.warn("Get inet address failed, {}", e.getMessage()); + } + } + return ret; + } + + private static EventPluginConfig getEventPluginConfig( + final com.typesafe.config.Config config) { EventPluginConfig eventPluginConfig = new EventPluginConfig(); boolean useNativeQueue = false; diff --git a/framework/src/main/java/org/tron/core/consensus/BlockHandleImpl.java b/framework/src/main/java/org/tron/core/consensus/BlockHandleImpl.java index fcfb801d1ce..b905b42381f 100644 --- a/framework/src/main/java/org/tron/core/consensus/BlockHandleImpl.java +++ b/framework/src/main/java/org/tron/core/consensus/BlockHandleImpl.java @@ -12,7 +12,7 @@ import org.tron.core.capsule.BlockCapsule; import org.tron.core.db.Manager; import org.tron.core.net.TronNetService; -import org.tron.core.net.message.BlockMessage; +import org.tron.core.net.message.adv.BlockMessage; @Slf4j(topic = "consensus") @Component diff --git a/framework/src/main/java/org/tron/core/consensus/PbftBaseImpl.java b/framework/src/main/java/org/tron/core/consensus/PbftBaseImpl.java index 07f7ea5d0e2..61538e966ed 100644 --- a/framework/src/main/java/org/tron/core/consensus/PbftBaseImpl.java +++ b/framework/src/main/java/org/tron/core/consensus/PbftBaseImpl.java @@ -1,32 +1,32 @@ package org.tron.core.consensus; +import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.common.overlay.server.SyncPool; import org.tron.consensus.base.PbftInterface; import org.tron.consensus.pbft.message.PbftBaseMessage; import org.tron.core.capsule.BlockCapsule; import org.tron.core.db.Manager; import org.tron.core.exception.BadItemException; import org.tron.core.exception.ItemNotFoundException; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.peer.PeerManager; @Component public class PbftBaseImpl implements PbftInterface { - @Autowired - private SyncPool syncPool; - @Autowired private Manager manager; @Override public boolean isSyncing() { - if (syncPool == null) { + List peers = PeerManager.getPeers(); + if (peers.isEmpty()) { return true; } AtomicBoolean result = new AtomicBoolean(false); - syncPool.getActivePeers().forEach(peerConnection -> { + peers.forEach(peerConnection -> { if (peerConnection.isNeedSyncFromPeer()) { result.set(true); return; @@ -37,10 +37,11 @@ public boolean isSyncing() { @Override public void forwardMessage(PbftBaseMessage message) { - if (syncPool == null) { + List peers = PeerManager.getPeers(); + if (peers.isEmpty()) { return; } - syncPool.getActivePeers().forEach(peerConnection -> { + peers.forEach(peerConnection -> { peerConnection.sendMessage(message); }); } diff --git a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java new file mode 100644 index 00000000000..6a50ccb0a2e --- /dev/null +++ b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java @@ -0,0 +1,239 @@ +package org.tron.core.net; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.Metrics; +import org.tron.consensus.pbft.message.PbftMessage; +import org.tron.core.exception.P2pException; +import org.tron.core.net.message.MessageTypes; +import org.tron.core.net.message.PbftMessageFactory; +import org.tron.core.net.message.TronMessage; +import org.tron.core.net.message.TronMessageFactory; +import org.tron.core.net.message.base.DisconnectMessage; +import org.tron.core.net.message.handshake.HelloMessage; +import org.tron.core.net.messagehandler.BlockMsgHandler; +import org.tron.core.net.messagehandler.ChainInventoryMsgHandler; +import org.tron.core.net.messagehandler.FetchInvDataMsgHandler; +import org.tron.core.net.messagehandler.InventoryMsgHandler; +import org.tron.core.net.messagehandler.PbftDataSyncHandler; +import org.tron.core.net.messagehandler.PbftMsgHandler; +import org.tron.core.net.messagehandler.SyncBlockChainMsgHandler; +import org.tron.core.net.messagehandler.TransactionsMsgHandler; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.peer.PeerManager; +import org.tron.core.net.service.handshake.HandshakeService; +import org.tron.core.net.service.keepalive.KeepAliveService; +import org.tron.p2p.P2pEventHandler; +import org.tron.p2p.connection.Channel; +import org.tron.protos.Protocol; + +@Slf4j(topic = "net") +@Component +public class P2pEventHandlerImpl extends P2pEventHandler { + + private static final String TAG = "~"; + private static final int DURATION_STEP = 50; + @Getter + private static AtomicInteger passivePeersCount = new AtomicInteger(0); + @Getter + private final AtomicInteger activePeersCount = new AtomicInteger(0); + + @Autowired + private ApplicationContext ctx; + + @Autowired + private SyncBlockChainMsgHandler syncBlockChainMsgHandler; + + @Autowired + private ChainInventoryMsgHandler chainInventoryMsgHandler; + + @Autowired + private InventoryMsgHandler inventoryMsgHandler; + + @Autowired + private FetchInvDataMsgHandler fetchInvDataMsgHandler; + + @Autowired + private BlockMsgHandler blockMsgHandler; + + @Autowired + private TransactionsMsgHandler transactionsMsgHandler; + + @Autowired + private PbftDataSyncHandler pbftDataSyncHandler; + + @Autowired + private HandshakeService handshakeService; + + @Autowired + private PbftMsgHandler pbftMsgHandler; + + @Autowired + private KeepAliveService keepAliveService; + + private byte MESSAGE_MAX_TYPE = 127; + + public P2pEventHandlerImpl() { + Set set = new HashSet<>(); + for (byte i = 0; i < MESSAGE_MAX_TYPE; i++) { + set.add(i); + } + messageTypes = set; + } + + @Override + public synchronized void onConnect(Channel channel) { + PeerConnection peerConnection = PeerManager.add(ctx, channel); + if (peerConnection != null) { + handshakeService.startHandshake(peerConnection); + } + } + + @Override + public synchronized void onDisconnect(Channel channel) { + PeerConnection peerConnection = PeerManager.remove(channel); + if (peerConnection != null) { + peerConnection.onDisconnect(); + } + } + + @Override + public void onMessage(Channel c, byte[] data) { + PeerConnection peerConnection = PeerManager.getPeerConnection(c); + if (peerConnection == null) { + logger.warn("Receive msg from unknown peer {}", c.getInetSocketAddress()); + return; + } + + if (MessageTypes.PBFT_MSG.asByte() == data[0]) { + PbftMessage message = null; + try { + message = (PbftMessage) PbftMessageFactory.create(data); + pbftMsgHandler.processMessage(peerConnection, message); + } catch (Exception e) { + logger.warn("PBFT Message from {} process failed, {}", + peerConnection.getInetSocketAddress(), message, e); + peerConnection.disconnect(Protocol.ReasonCode.BAD_PROTOCOL); + } + return; + } + + processMessage(peerConnection, data); + } + + private void processMessage(PeerConnection peer, byte[] data) { + long startTime = System.currentTimeMillis(); + TronMessage msg = null; + try { + msg = TronMessageFactory.create(data); + peer.getPeerStatistics().messageStatistics.addTcpInMessage(msg); + logger.info("Receive message from peer: {}, {}", + peer.getInetSocketAddress(), msg); + switch (msg.getType()) { + case P2P_PING: + case P2P_PONG: + keepAliveService.processMessage(peer, msg); + break; + case P2P_HELLO: + handshakeService.processHelloMessage(peer, (HelloMessage) msg); + break; + case P2P_DISCONNECT: + peer.getChannel().close(); + peer.getNodeStatistics() + .nodeDisconnectedRemote(((DisconnectMessage)msg).getReason()); + break; + case SYNC_BLOCK_CHAIN: + syncBlockChainMsgHandler.processMessage(peer, msg); + break; + case BLOCK_CHAIN_INVENTORY: + chainInventoryMsgHandler.processMessage(peer, msg); + break; + case INVENTORY: + inventoryMsgHandler.processMessage(peer, msg); + break; + case FETCH_INV_DATA: + fetchInvDataMsgHandler.processMessage(peer, msg); + break; + case BLOCK: + blockMsgHandler.processMessage(peer, msg); + break; + case TRXS: + transactionsMsgHandler.processMessage(peer, msg); + break; + case PBFT_COMMIT_MSG: + pbftDataSyncHandler.processMessage(peer, msg); + break; + default: + throw new P2pException(P2pException.TypeEnum.NO_SUCH_MESSAGE, msg.getType().toString()); + } + } catch (Exception e) { + processException(peer, msg, e); + } finally { + long costs = System.currentTimeMillis() - startTime; + if (costs > 50) { + logger.info("Message processing costs {} ms, peer: {}, type: {}, time tag: {}", + costs, peer.getInetSocketAddress(), msg.getType(), getTimeTag(costs)); + Metrics.histogramObserve(MetricKeys.Histogram.MESSAGE_PROCESS_LATENCY, + costs / Metrics.MILLISECONDS_PER_SECOND, msg.getType().name()); + } + } + } + + private void processException(PeerConnection peer, TronMessage msg, Exception ex) { + Protocol.ReasonCode code; + + if (ex instanceof P2pException) { + P2pException.TypeEnum type = ((P2pException) ex).getType(); + switch (type) { + case BAD_TRX: + code = Protocol.ReasonCode.BAD_TX; + break; + case BAD_BLOCK: + code = Protocol.ReasonCode.BAD_BLOCK; + break; + case NO_SUCH_MESSAGE: + case MESSAGE_WITH_WRONG_LENGTH: + case BAD_MESSAGE: + code = Protocol.ReasonCode.BAD_PROTOCOL; + break; + case SYNC_FAILED: + code = Protocol.ReasonCode.SYNC_FAIL; + break; + case UNLINK_BLOCK: + code = Protocol.ReasonCode.UNLINKABLE; + break; + case DB_ITEM_NOT_FOUND: + code = Protocol.ReasonCode.FETCH_FAIL; + break; + default: + code = Protocol.ReasonCode.UNKNOWN; + break; + } + logger.warn("Message from {} process failed, {} \n type: {}, detail: {}", + peer.getInetSocketAddress(), msg, type, ex.getMessage()); + } else { + code = Protocol.ReasonCode.UNKNOWN; + logger.warn("Message from {} process failed, {}", + peer.getInetSocketAddress(), msg, ex); + } + + peer.disconnect(code); + } + + private String getTimeTag(long duration) { + StringBuilder tag = new StringBuilder(TAG); + long tagCount = duration / DURATION_STEP; + for (; tagCount > 0; tagCount--) { + tag.append(TAG); + } + return tag.toString(); + } + +} diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index 7a0c361165e..eafa9ff3766 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -16,10 +16,8 @@ import org.bouncycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.common.backup.BackupServer; +import org.tron.common.backup.socket.BackupServer; import org.tron.common.overlay.message.Message; -import org.tron.common.overlay.server.ChannelManager; -import org.tron.common.overlay.server.SyncPool; import org.tron.common.prometheus.MetricKeys; import org.tron.common.prometheus.MetricLabels; import org.tron.common.prometheus.Metrics; @@ -55,9 +53,9 @@ import org.tron.core.exception.ValidateSignatureException; import org.tron.core.exception.ZksnarkException; import org.tron.core.metrics.MetricsService; -import org.tron.core.net.message.BlockMessage; import org.tron.core.net.message.MessageTypes; -import org.tron.core.net.message.TransactionMessage; +import org.tron.core.net.message.adv.BlockMessage; +import org.tron.core.net.message.adv.TransactionMessage; import org.tron.core.net.peer.PeerConnection; import org.tron.core.store.WitnessScheduleStore; import org.tron.protos.Protocol.Inventory.InventoryType; @@ -66,12 +64,6 @@ @Component public class TronNetDelegate { - @Autowired - private SyncPool syncPool; - - @Autowired - private ChannelManager channelManager; - @Autowired private Manager dbManager; @@ -123,7 +115,7 @@ public void init() { } public Collection getActivePeer() { - return syncPool.getActivePeers(); + return TronNetService.getPeers(); } public long getSyncBeginNumber() { diff --git a/framework/src/main/java/org/tron/core/net/TronNetHandler.java b/framework/src/main/java/org/tron/core/net/TronNetHandler.java deleted file mode 100644 index 32c687244af..00000000000 --- a/framework/src/main/java/org/tron/core/net/TronNetHandler.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.tron.core.net; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; -import org.tron.common.overlay.server.Channel; -import org.tron.common.overlay.server.MessageQueue; -import org.tron.core.net.message.TronMessage; -import org.tron.core.net.peer.PeerConnection; - -@Component -@Scope("prototype") -public class TronNetHandler extends SimpleChannelInboundHandler { - - protected PeerConnection peer; - - private MessageQueue msgQueue; - - @Autowired - private TronNetService tronNetService; - - @Override - public void channelRead0(final ChannelHandlerContext ctx, TronMessage msg) throws Exception { - msgQueue.receivedMessage(msg); - tronNetService.onMessage(peer, msg); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - peer.processException(cause); - } - - public void setMsgQueue(MessageQueue msgQueue) { - this.msgQueue = msgQueue; - } - - public void setChannel(Channel channel) { - this.peer = (PeerConnection) channel; - } - -} \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 82568d6a7c0..c46c4688071 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -1,37 +1,38 @@ package org.tron.core.net; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.List; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.common.overlay.message.Message; -import org.tron.common.overlay.server.ChannelManager; -import org.tron.common.prometheus.MetricKeys; -import org.tron.common.prometheus.Metrics; -import org.tron.core.exception.P2pException; -import org.tron.core.exception.P2pException.TypeEnum; -import org.tron.core.net.message.BlockMessage; -import org.tron.core.net.message.TransactionMessage; -import org.tron.core.net.message.TronMessage; -import org.tron.core.net.messagehandler.BlockMsgHandler; -import org.tron.core.net.messagehandler.ChainInventoryMsgHandler; -import org.tron.core.net.messagehandler.FetchInvDataMsgHandler; -import org.tron.core.net.messagehandler.InventoryMsgHandler; -import org.tron.core.net.messagehandler.PbftDataSyncHandler; -import org.tron.core.net.messagehandler.SyncBlockChainMsgHandler; +import org.tron.common.parameter.CommonParameter; +import org.tron.core.config.args.Args; +import org.tron.core.net.message.adv.TransactionMessage; import org.tron.core.net.messagehandler.TransactionsMsgHandler; import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.peer.PeerManager; import org.tron.core.net.peer.PeerStatusCheck; -import org.tron.core.net.service.AdvService; -import org.tron.core.net.service.FetchBlockService; -import org.tron.core.net.service.SyncService; -import org.tron.protos.Protocol.ReasonCode; +import org.tron.core.net.service.adv.AdvService; +import org.tron.core.net.service.fetchblock.FetchBlockService; +import org.tron.core.net.service.keepalive.KeepAliveService; +import org.tron.core.net.service.nodepersist.NodePersistService; +import org.tron.core.net.service.statistics.TronStatsManager; +import org.tron.core.net.service.sync.SyncService; +import org.tron.p2p.P2pConfig; +import org.tron.p2p.P2pService; @Slf4j(topic = "net") @Component public class TronNetService { - @Autowired - private ChannelManager channelManager; + @Getter + private static P2pConfig p2pConfig; + + @Getter + private static P2pService p2pService; @Autowired private AdvService advService; @@ -43,150 +44,92 @@ public class TronNetService { private PeerStatusCheck peerStatusCheck; @Autowired - private SyncBlockChainMsgHandler syncBlockChainMsgHandler; - - @Autowired - private ChainInventoryMsgHandler chainInventoryMsgHandler; + private TransactionsMsgHandler transactionsMsgHandler; @Autowired - private InventoryMsgHandler inventoryMsgHandler; - + private FetchBlockService fetchBlockService; @Autowired - private FetchInvDataMsgHandler fetchInvDataMsgHandler; + private KeepAliveService keepAliveService; - @Autowired - private BlockMsgHandler blockMsgHandler; + private CommonParameter parameter = Args.getInstance(); @Autowired - private TransactionsMsgHandler transactionsMsgHandler; + private P2pEventHandlerImpl p2pEventHandler; @Autowired - private PbftDataSyncHandler pbftDataSyncHandler; + private NodePersistService nodePersistService; @Autowired - private FetchBlockService fetchBlockService; - - private static final String TAG = "~"; - private static final int DURATION_STEP = 50; + private TronStatsManager tronStatsManager; public void start() { - channelManager.init(); - advService.init(); - syncService.init(); - peerStatusCheck.init(); - transactionsMsgHandler.init(); - fetchBlockService.init(); - logger.info("TronNetService start successfully"); + try { + p2pConfig = getConfig(); + p2pService = new P2pService(); + p2pService.start(p2pConfig); + p2pService.register(p2pEventHandler); + advService.init(); + syncService.init(); + peerStatusCheck.init(); + transactionsMsgHandler.init(); + fetchBlockService.init(); + keepAliveService.init(); + nodePersistService.init(); + tronStatsManager.init(); + PeerManager.init(); + logger.info("Net service start successfully"); + } catch (Exception e) { + logger.error("Net service start failed", e); + } } - public void stop() { - logger.info("TronNetService closed start"); - channelManager.close(); + public void close() { + PeerManager.close(); + tronStatsManager.close(); + nodePersistService.close(); + keepAliveService.close(); advService.close(); syncService.close(); peerStatusCheck.close(); transactionsMsgHandler.close(); fetchBlockService.close(); - logger.info("TronNetService closed successfully"); + p2pService.close(); + logger.info("Net service closed successfully"); } - public int fastBroadcastTransaction(TransactionMessage msg) { - return advService.fastBroadcastTransaction(msg); + public static List getPeers() { + return PeerManager.getPeers(); } public void broadcast(Message msg) { advService.broadcast(msg); } - protected void onMessage(PeerConnection peer, TronMessage msg) { - long startTime = System.currentTimeMillis(); - try { - switch (msg.getType()) { - case SYNC_BLOCK_CHAIN: - syncBlockChainMsgHandler.processMessage(peer, msg); - break; - case BLOCK_CHAIN_INVENTORY: - chainInventoryMsgHandler.processMessage(peer, msg); - break; - case INVENTORY: - inventoryMsgHandler.processMessage(peer, msg); - break; - case FETCH_INV_DATA: - fetchInvDataMsgHandler.processMessage(peer, msg); - break; - case BLOCK: - blockMsgHandler.processMessage(peer, msg); - break; - case TRXS: - transactionsMsgHandler.processMessage(peer, msg); - break; - case PBFT_COMMIT_MSG: - pbftDataSyncHandler.processMessage(peer, msg); - break; - default: - throw new P2pException(TypeEnum.NO_SUCH_MESSAGE, msg.getType().toString()); - } - } catch (Exception e) { - processException(peer, msg, e); - } finally { - long costs = System.currentTimeMillis() - startTime; - if (costs > DURATION_STEP) { - logger.info("Message processing costs {} ms, peer: {}, type: {}, time tag: {}", - costs, peer.getInetAddress(), msg.getType(), getTimeTag(costs)); - Metrics.histogramObserve(MetricKeys.Histogram.MESSAGE_PROCESS_LATENCY, - costs / Metrics.MILLISECONDS_PER_SECOND, msg.getType().name()); - } - } + public int fastBroadcastTransaction(TransactionMessage msg) { + return advService.fastBroadcastTransaction(msg); } - private void processException(PeerConnection peer, TronMessage msg, Exception ex) { - ReasonCode code; - - if (ex instanceof P2pException) { - TypeEnum type = ((P2pException) ex).getType(); - switch (type) { - case BAD_TRX: - code = ReasonCode.BAD_TX; - break; - case BAD_BLOCK: - code = ReasonCode.BAD_BLOCK; - break; - case NO_SUCH_MESSAGE: - case MESSAGE_WITH_WRONG_LENGTH: - case BAD_MESSAGE: - code = ReasonCode.BAD_PROTOCOL; - break; - case SYNC_FAILED: - code = ReasonCode.SYNC_FAIL; - break; - case UNLINK_BLOCK: - code = ReasonCode.UNLINKABLE; - break; - case DB_ITEM_NOT_FOUND: - code = ReasonCode.FETCH_FAIL; - break; - default: - code = ReasonCode.UNKNOWN; - break; - } - logger.warn("Message from {} process failed, {} \n type: {}, detail: {}", - peer.getInetAddress(), msg, type, ex.getMessage()); - } else { - code = ReasonCode.UNKNOWN; - logger.warn("Message from {} process failed, {}", - peer.getInetAddress(), msg, ex); + private P2pConfig getConfig() { + List seeds = new ArrayList<>(); + seeds.addAll(nodePersistService.dbRead()); + for (String s : parameter.getSeedNode().getIpList()) { + String[] sz = s.split(":"); + seeds.add(new InetSocketAddress(sz[0], Integer.parseInt(sz[1]))); } - peer.disconnect(code); - } - - private String getTimeTag(long duration) { - StringBuilder tag = new StringBuilder(TAG); - long tagCount = duration / DURATION_STEP; - for (; tagCount > 0; tagCount--) { - tag.append(TAG); - } - return tag.toString(); + P2pConfig config = new P2pConfig(); + config.setSeedNodes(seeds); + config.setActiveNodes(parameter.getActiveNodes()); + config.setTrustNodes(parameter.getPassiveNodes()); + config.getActiveNodes().forEach(n -> config.getTrustNodes().add(n.getAddress())); + config.setMaxConnections(parameter.getMaxConnections()); + config.setMinConnections(parameter.getMinConnections()); + config.setMaxConnectionsWithSameIp(parameter.getMaxConnectionsWithSameIp()); + config.setPort(parameter.getNodeListenPort()); + config.setVersion(parameter.getNodeP2pVersion()); + config.setDisconnectionPolicyEnable(parameter.isOpenFullTcpDisconnect()); + config.setDiscoverEnable(parameter.isNodeDiscoveryEnable()); + return config; } -} +} \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/net/message/BlocksMessage.java b/framework/src/main/java/org/tron/core/net/message/BlocksMessage.java deleted file mode 100644 index 8705ff12bb7..00000000000 --- a/framework/src/main/java/org/tron/core/net/message/BlocksMessage.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.tron.core.net.message; - -import java.util.List; -import org.apache.commons.collections4.CollectionUtils; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Items; - -public class BlocksMessage extends TronMessage { - - private List blocks; - - public BlocksMessage(byte[] data) throws Exception { - super(data); - this.type = MessageTypes.BLOCKS.asByte(); - Items items = Items.parseFrom(getCodedInputStream(data)); - if (items.getType() == Items.ItemType.BLOCK) { - blocks = items.getBlocksList(); - } - if (isFilter() && CollectionUtils.isNotEmpty(blocks)) { - compareBytes(data, items.toByteArray()); - for (Block block : blocks) { - TransactionCapsule.validContractProto(block.getTransactionsList()); - } - } - } - - public List getBlocks() { - return blocks; - } - - @Override - public String toString() { - return super.toString() + "size: " + (CollectionUtils.isNotEmpty(blocks) ? blocks - .size() : 0); - } - - @Override - public Class getAnswerMessage() { - return null; - } - -} diff --git a/framework/src/main/java/org/tron/core/net/message/FetchBlockHeadersMessage.java b/framework/src/main/java/org/tron/core/net/message/FetchBlockHeadersMessage.java deleted file mode 100644 index 0e6e3f396b2..00000000000 --- a/framework/src/main/java/org/tron/core/net/message/FetchBlockHeadersMessage.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.tron.core.net.message; - -import org.tron.protos.Protocol; - -public class FetchBlockHeadersMessage extends InventoryMessage { - - public FetchBlockHeadersMessage(byte[] packed) throws Exception { - super(packed); - this.type = MessageTypes.FETCH_BLOCK_HEADERS.asByte(); - } - - public FetchBlockHeadersMessage(Protocol.Inventory inv) { - super(inv); - this.type = MessageTypes.FETCH_BLOCK_HEADERS.asByte(); - } - -} \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/net/message/ItemNotFound.java b/framework/src/main/java/org/tron/core/net/message/ItemNotFound.java deleted file mode 100644 index b4694048db0..00000000000 --- a/framework/src/main/java/org/tron/core/net/message/ItemNotFound.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.tron.core.net.message; - -import org.tron.protos.Protocol; - -public class ItemNotFound extends TronMessage { - - private org.tron.protos.Protocol.Items notFound; - - /** - * means can not find this block or trx. - */ - public ItemNotFound() { - Protocol.Items.Builder itemsBuilder = Protocol.Items.newBuilder(); - itemsBuilder.setType(Protocol.Items.ItemType.ERR); - notFound = itemsBuilder.build(); - this.type = MessageTypes.ITEM_NOT_FOUND.asByte(); - this.data = notFound.toByteArray(); - } - - @Override - public String toString() { - return "item not found"; - } - - @Override - public Class getAnswerMessage() { - return null; - } - -} diff --git a/framework/src/main/java/org/tron/core/net/message/PbftMessageFactory.java b/framework/src/main/java/org/tron/core/net/message/PbftMessageFactory.java index b40e9b8fa30..ea6b25e6ab1 100644 --- a/framework/src/main/java/org/tron/core/net/message/PbftMessageFactory.java +++ b/framework/src/main/java/org/tron/core/net/message/PbftMessageFactory.java @@ -1,21 +1,16 @@ package org.tron.core.net.message; import org.apache.commons.lang3.ArrayUtils; -import org.tron.common.overlay.message.MessageFactory; import org.tron.consensus.pbft.message.PbftBaseMessage; import org.tron.consensus.pbft.message.PbftMessage; import org.tron.core.exception.P2pException; -/** - * msg factory. - */ -public class PbftMessageFactory extends MessageFactory { +public class PbftMessageFactory { private static String LEN = ", len="; private static String TYPE = "type="; - @Override - public PbftBaseMessage create(byte[] data) throws Exception { + public static PbftBaseMessage create(byte[] data) throws Exception { try { byte type = data[0]; byte[] rawData = ArrayUtils.subarray(data, 1, data.length); @@ -28,7 +23,7 @@ public PbftBaseMessage create(byte[] data) throws Exception { } } - private PbftBaseMessage create(byte type, byte[] packed) throws Exception { + private static PbftBaseMessage create(byte type, byte[] packed) throws Exception { MessageTypes receivedTypes = MessageTypes.fromByte(type); if (receivedTypes == null) { throw new P2pException(P2pException.TypeEnum.NO_SUCH_MESSAGE, diff --git a/framework/src/main/java/org/tron/core/net/message/TransactionInventoryMessage.java b/framework/src/main/java/org/tron/core/net/message/TransactionInventoryMessage.java deleted file mode 100644 index 44fea28c88f..00000000000 --- a/framework/src/main/java/org/tron/core/net/message/TransactionInventoryMessage.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.tron.core.net.message; - -import java.util.List; -import org.tron.common.utils.Sha256Hash; -import org.tron.protos.Protocol.Inventory; -import org.tron.protos.Protocol.Inventory.InventoryType; - -public class TransactionInventoryMessage extends InventoryMessage { - - public TransactionInventoryMessage(byte[] packed) throws Exception { - super(packed); - } - - public TransactionInventoryMessage(Inventory inv) { - super(inv); - } - - public TransactionInventoryMessage(List hashList) { - super(hashList, InventoryType.TRX); - } -} diff --git a/framework/src/main/java/org/tron/core/net/message/TronMessageFactory.java b/framework/src/main/java/org/tron/core/net/message/TronMessageFactory.java index a4e9089dce0..3cc1b35e506 100644 --- a/framework/src/main/java/org/tron/core/net/message/TronMessageFactory.java +++ b/framework/src/main/java/org/tron/core/net/message/TronMessageFactory.java @@ -1,20 +1,28 @@ package org.tron.core.net.message; import org.apache.commons.lang3.ArrayUtils; -import org.tron.common.overlay.message.MessageFactory; +import org.tron.consensus.pbft.message.PbftMessage; import org.tron.core.exception.P2pException; import org.tron.core.metrics.MetricsKey; import org.tron.core.metrics.MetricsUtil; +import org.tron.core.net.message.adv.BlockMessage; +import org.tron.core.net.message.adv.FetchInvDataMessage; +import org.tron.core.net.message.adv.InventoryMessage; +import org.tron.core.net.message.adv.TransactionMessage; +import org.tron.core.net.message.adv.TransactionsMessage; +import org.tron.core.net.message.base.DisconnectMessage; +import org.tron.core.net.message.handshake.HelloMessage; +import org.tron.core.net.message.keepalive.PingMessage; +import org.tron.core.net.message.keepalive.PongMessage; +import org.tron.core.net.message.pbft.PbftCommitMessage; +import org.tron.core.net.message.sync.ChainInventoryMessage; +import org.tron.core.net.message.sync.SyncBlockChainMessage; -/** - * msg factory. - */ -public class TronMessageFactory extends MessageFactory { +public class TronMessageFactory { private static final String DATA_LEN = ", len="; - @Override - public TronMessage create(byte[] data) throws Exception { + public static TronMessage create(byte[] data) throws Exception { boolean isException = false; try { byte type = data[0]; @@ -34,21 +42,27 @@ public TronMessage create(byte[] data) throws Exception { } } - private TronMessage create(byte type, byte[] packed) throws Exception { + private static TronMessage create(byte type, byte[] packed) throws Exception { MessageTypes receivedTypes = MessageTypes.fromByte(type); if (receivedTypes == null) { throw new P2pException(P2pException.TypeEnum.NO_SUCH_MESSAGE, "type=" + type + DATA_LEN + packed.length); } switch (receivedTypes) { + case P2P_HELLO: + return new HelloMessage(packed); + case P2P_DISCONNECT: + return new DisconnectMessage(packed); + case P2P_PING: + return new PingMessage(packed); + case P2P_PONG: + return new PongMessage(packed); case TRX: return new TransactionMessage(packed); case BLOCK: return new BlockMessage(packed); case TRXS: return new TransactionsMessage(packed); - case BLOCKS: - return new BlocksMessage(packed); case INVENTORY: return new InventoryMessage(packed); case FETCH_INV_DATA: @@ -57,12 +71,6 @@ private TronMessage create(byte type, byte[] packed) throws Exception { return new SyncBlockChainMessage(packed); case BLOCK_CHAIN_INVENTORY: return new ChainInventoryMessage(packed); - case ITEM_NOT_FOUND: - return new ItemNotFound(); - case FETCH_BLOCK_HEADERS: - return new FetchBlockHeadersMessage(packed); - case TRX_INVENTORY: - return new TransactionInventoryMessage(packed); case PBFT_COMMIT_MSG: return new PbftCommitMessage(packed); default: diff --git a/framework/src/main/java/org/tron/core/net/message/BlockMessage.java b/framework/src/main/java/org/tron/core/net/message/adv/BlockMessage.java similarity index 92% rename from framework/src/main/java/org/tron/core/net/message/BlockMessage.java rename to framework/src/main/java/org/tron/core/net/message/adv/BlockMessage.java index 1b4c42e8060..d5aad2cd5c4 100644 --- a/framework/src/main/java/org/tron/core/net/message/BlockMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/adv/BlockMessage.java @@ -1,10 +1,12 @@ -package org.tron.core.net.message; +package org.tron.core.net.message.adv; import org.tron.common.overlay.message.Message; import org.tron.common.utils.Sha256Hash; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.net.message.MessageTypes; +import org.tron.core.net.message.TronMessage; public class BlockMessage extends TronMessage { diff --git a/framework/src/main/java/org/tron/core/net/message/FetchInvDataMessage.java b/framework/src/main/java/org/tron/core/net/message/adv/FetchInvDataMessage.java similarity index 88% rename from framework/src/main/java/org/tron/core/net/message/FetchInvDataMessage.java rename to framework/src/main/java/org/tron/core/net/message/adv/FetchInvDataMessage.java index 16caf8795d3..0a22461edce 100644 --- a/framework/src/main/java/org/tron/core/net/message/FetchInvDataMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/adv/FetchInvDataMessage.java @@ -1,7 +1,8 @@ -package org.tron.core.net.message; +package org.tron.core.net.message.adv; import java.util.List; import org.tron.common.utils.Sha256Hash; +import org.tron.core.net.message.MessageTypes; import org.tron.protos.Protocol.Inventory; import org.tron.protos.Protocol.Inventory.InventoryType; diff --git a/framework/src/main/java/org/tron/core/net/message/InventoryMessage.java b/framework/src/main/java/org/tron/core/net/message/adv/InventoryMessage.java similarity index 94% rename from framework/src/main/java/org/tron/core/net/message/InventoryMessage.java rename to framework/src/main/java/org/tron/core/net/message/adv/InventoryMessage.java index 701270a6626..d0991a9dcd3 100644 --- a/framework/src/main/java/org/tron/core/net/message/InventoryMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/adv/InventoryMessage.java @@ -1,10 +1,12 @@ -package org.tron.core.net.message; +package org.tron.core.net.message.adv; import java.util.Deque; import java.util.LinkedList; import java.util.List; import java.util.stream.Collectors; import org.tron.common.utils.Sha256Hash; +import org.tron.core.net.message.MessageTypes; +import org.tron.core.net.message.TronMessage; import org.tron.protos.Protocol; import org.tron.protos.Protocol.Inventory; import org.tron.protos.Protocol.Inventory.InventoryType; diff --git a/framework/src/main/java/org/tron/core/net/message/TransactionMessage.java b/framework/src/main/java/org/tron/core/net/message/adv/TransactionMessage.java similarity index 91% rename from framework/src/main/java/org/tron/core/net/message/TransactionMessage.java rename to framework/src/main/java/org/tron/core/net/message/adv/TransactionMessage.java index eebbe0980b0..3ffd65e0386 100644 --- a/framework/src/main/java/org/tron/core/net/message/TransactionMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/adv/TransactionMessage.java @@ -1,8 +1,10 @@ -package org.tron.core.net.message; +package org.tron.core.net.message.adv; import org.tron.common.overlay.message.Message; import org.tron.common.utils.Sha256Hash; import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.net.message.MessageTypes; +import org.tron.core.net.message.TronMessage; import org.tron.protos.Protocol.Transaction; public class TransactionMessage extends TronMessage { diff --git a/framework/src/main/java/org/tron/core/net/message/TransactionsMessage.java b/framework/src/main/java/org/tron/core/net/message/adv/TransactionsMessage.java similarity index 90% rename from framework/src/main/java/org/tron/core/net/message/TransactionsMessage.java rename to framework/src/main/java/org/tron/core/net/message/adv/TransactionsMessage.java index 72110041e87..2193ac6b546 100644 --- a/framework/src/main/java/org/tron/core/net/message/TransactionsMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/adv/TransactionsMessage.java @@ -1,7 +1,9 @@ -package org.tron.core.net.message; +package org.tron.core.net.message.adv; import java.util.List; import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.net.message.MessageTypes; +import org.tron.core.net.message.TronMessage; import org.tron.protos.Protocol; import org.tron.protos.Protocol.Transaction; diff --git a/framework/src/main/java/org/tron/common/overlay/message/DisconnectMessage.java b/framework/src/main/java/org/tron/core/net/message/base/DisconnectMessage.java similarity index 70% rename from framework/src/main/java/org/tron/common/overlay/message/DisconnectMessage.java rename to framework/src/main/java/org/tron/core/net/message/base/DisconnectMessage.java index 576dd0ef2a0..c8d0d2485ff 100755 --- a/framework/src/main/java/org/tron/common/overlay/message/DisconnectMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/base/DisconnectMessage.java @@ -1,10 +1,11 @@ -package org.tron.common.overlay.message; +package org.tron.core.net.message.base; import org.tron.core.net.message.MessageTypes; +import org.tron.core.net.message.TronMessage; import org.tron.protos.Protocol; import org.tron.protos.Protocol.ReasonCode; -public class DisconnectMessage extends P2pMessage { +public class DisconnectMessage extends TronMessage { private Protocol.DisconnectMessage disconnectMessage; @@ -13,6 +14,11 @@ public DisconnectMessage(byte type, byte[] rawData) throws Exception { this.disconnectMessage = Protocol.DisconnectMessage.parseFrom(this.data); } + public DisconnectMessage(byte[] data) throws Exception { + super(MessageTypes.P2P_DISCONNECT.asByte(), data); + this.disconnectMessage = Protocol.DisconnectMessage.parseFrom(data); + } + public DisconnectMessage(ReasonCode reasonCode) { this.disconnectMessage = Protocol.DisconnectMessage .newBuilder() @@ -22,8 +28,8 @@ public DisconnectMessage(ReasonCode reasonCode) { this.data = this.disconnectMessage.toByteArray(); } - public int getReason() { - return this.disconnectMessage.getReason().getNumber(); + public ReasonCode getReason() { + return this.disconnectMessage.getReason(); } public ReasonCode getReasonCode() { diff --git a/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java b/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java similarity index 88% rename from framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java rename to framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java index 86c01725aed..01cf19b2a0b 100755 --- a/framework/src/main/java/org/tron/common/overlay/message/HelloMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java @@ -1,10 +1,7 @@ -package org.tron.common.overlay.message; +package org.tron.core.net.message.handshake; import com.google.protobuf.ByteString; -import io.netty.channel.ChannelHandlerContext; import lombok.Getter; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.overlay.server.HandshakeHandler; import org.tron.common.utils.ByteArray; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; @@ -12,11 +9,13 @@ import org.tron.core.config.args.Args; import org.tron.core.db.CommonStore; import org.tron.core.net.message.MessageTypes; +import org.tron.core.net.message.TronMessage; +import org.tron.p2p.discover.Node; import org.tron.protos.Discover.Endpoint; import org.tron.protos.Protocol; import org.tron.protos.Protocol.HelloMessage.Builder; -public class HelloMessage extends P2pMessage { +public class HelloMessage extends TronMessage { @Getter private Protocol.HelloMessage helloMessage; @@ -26,6 +25,11 @@ public HelloMessage(byte type, byte[] rawData) throws Exception { this.helloMessage = Protocol.HelloMessage.parseFrom(rawData); } + public HelloMessage(byte[] data) throws Exception { + super(MessageTypes.P2P_HELLO.asByte(), data); + this.helloMessage = Protocol.HelloMessage.parseFrom(data); + } + public HelloMessage(Node from, long timestamp, ChainBaseManager chainBaseManager) { Endpoint fromEndpoint = Endpoint.newBuilder() @@ -124,12 +128,12 @@ public Class getAnswerMessage() { @Override public String toString() { - return new StringBuilder().append(super.toString()).append(", ") - .append("from: ").append(getFrom()).append(", ") - .append("timestamp: ").append(getTimestamp()).append(", ") - .append("headBlockId: {").append(getHeadBlockId().getString()).append("}, ") - .append("nodeType: ").append(helloMessage.getNodeType()).append(", ") - .append("lowestBlockNum: ").append(helloMessage.getLowestBlockNum()) + return new StringBuilder().append(super.toString()) + .append("from: ").append(getFrom().getInetSocketAddress()).append("\n") + .append("timestamp: ").append(getTimestamp()).append("\n") + .append("headBlockId: ").append(getHeadBlockId().getString()).append("\n") + .append("nodeType: ").append(helloMessage.getNodeType()).append("\n") + .append("lowestBlockNum: ").append(helloMessage.getLowestBlockNum()).append("\n") .toString(); } diff --git a/framework/src/main/java/org/tron/common/overlay/message/PingMessage.java b/framework/src/main/java/org/tron/core/net/message/keepalive/PingMessage.java similarity index 74% rename from framework/src/main/java/org/tron/common/overlay/message/PingMessage.java rename to framework/src/main/java/org/tron/core/net/message/keepalive/PingMessage.java index dbdbe956c5a..209ece12ddd 100644 --- a/framework/src/main/java/org/tron/common/overlay/message/PingMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/keepalive/PingMessage.java @@ -1,9 +1,10 @@ -package org.tron.common.overlay.message; +package org.tron.core.net.message.keepalive; import org.bouncycastle.util.encoders.Hex; import org.tron.core.net.message.MessageTypes; +import org.tron.core.net.message.TronMessage; -public class PingMessage extends P2pMessage { +public class PingMessage extends TronMessage { private static final byte[] FIXED_PAYLOAD = Hex.decode("C0"); @@ -16,6 +17,10 @@ public PingMessage(byte type, byte[] rawData) { super(type, rawData); } + public PingMessage(byte[] data) { + super(MessageTypes.P2P_PING.asByte(), data); + } + @Override public byte[] getData() { return FIXED_PAYLOAD; diff --git a/framework/src/main/java/org/tron/common/overlay/message/PongMessage.java b/framework/src/main/java/org/tron/core/net/message/keepalive/PongMessage.java similarity index 74% rename from framework/src/main/java/org/tron/common/overlay/message/PongMessage.java rename to framework/src/main/java/org/tron/core/net/message/keepalive/PongMessage.java index c17755125b2..d585a8e46d3 100644 --- a/framework/src/main/java/org/tron/common/overlay/message/PongMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/keepalive/PongMessage.java @@ -1,9 +1,10 @@ -package org.tron.common.overlay.message; +package org.tron.core.net.message.keepalive; import org.bouncycastle.util.encoders.Hex; import org.tron.core.net.message.MessageTypes; +import org.tron.core.net.message.TronMessage; -public class PongMessage extends P2pMessage { +public class PongMessage extends TronMessage { private static final byte[] FIXED_PAYLOAD = Hex.decode("C0"); @@ -16,6 +17,10 @@ public PongMessage(byte type, byte[] rawData) { super(type, rawData); } + public PongMessage(byte[] data) { + super(MessageTypes.P2P_PONG.asByte(), data); + } + @Override public byte[] getData() { return FIXED_PAYLOAD; diff --git a/framework/src/main/java/org/tron/core/net/message/PbftCommitMessage.java b/framework/src/main/java/org/tron/core/net/message/pbft/PbftCommitMessage.java similarity index 86% rename from framework/src/main/java/org/tron/core/net/message/PbftCommitMessage.java rename to framework/src/main/java/org/tron/core/net/message/pbft/PbftCommitMessage.java index 720f577676e..bfa34367f88 100644 --- a/framework/src/main/java/org/tron/core/net/message/PbftCommitMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/pbft/PbftCommitMessage.java @@ -1,6 +1,8 @@ -package org.tron.core.net.message; +package org.tron.core.net.message.pbft; import org.tron.core.capsule.PbftSignCapsule; +import org.tron.core.net.message.MessageTypes; +import org.tron.core.net.message.TronMessage; import org.tron.protos.Protocol.PBFTCommitResult; public class PbftCommitMessage extends TronMessage { diff --git a/framework/src/main/java/org/tron/core/net/message/BlockInventoryMessage.java b/framework/src/main/java/org/tron/core/net/message/sync/BlockInventoryMessage.java similarity index 91% rename from framework/src/main/java/org/tron/core/net/message/BlockInventoryMessage.java rename to framework/src/main/java/org/tron/core/net/message/sync/BlockInventoryMessage.java index daeab8e678e..53a736dcb90 100644 --- a/framework/src/main/java/org/tron/core/net/message/BlockInventoryMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/sync/BlockInventoryMessage.java @@ -1,9 +1,11 @@ -package org.tron.core.net.message; +package org.tron.core.net.message.sync; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import org.tron.core.capsule.BlockCapsule.BlockId; +import org.tron.core.net.message.MessageTypes; +import org.tron.core.net.message.TronMessage; import org.tron.protos.Protocol; import org.tron.protos.Protocol.BlockInventory; diff --git a/framework/src/main/java/org/tron/core/net/message/ChainInventoryMessage.java b/framework/src/main/java/org/tron/core/net/message/sync/ChainInventoryMessage.java similarity index 94% rename from framework/src/main/java/org/tron/core/net/message/ChainInventoryMessage.java rename to framework/src/main/java/org/tron/core/net/message/sync/ChainInventoryMessage.java index b38961d2e51..4179544ebf7 100644 --- a/framework/src/main/java/org/tron/core/net/message/ChainInventoryMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/sync/ChainInventoryMessage.java @@ -1,4 +1,4 @@ -package org.tron.core.net.message; +package org.tron.core.net.message.sync; import java.util.ArrayList; import java.util.Deque; @@ -6,6 +6,8 @@ import java.util.List; import java.util.stream.Collectors; import org.tron.core.capsule.BlockCapsule.BlockId; +import org.tron.core.net.message.MessageTypes; +import org.tron.core.net.message.TronMessage; import org.tron.protos.Protocol; import org.tron.protos.Protocol.ChainInventory; diff --git a/framework/src/main/java/org/tron/core/net/message/SyncBlockChainMessage.java b/framework/src/main/java/org/tron/core/net/message/sync/SyncBlockChainMessage.java similarity index 92% rename from framework/src/main/java/org/tron/core/net/message/SyncBlockChainMessage.java rename to framework/src/main/java/org/tron/core/net/message/sync/SyncBlockChainMessage.java index 3163660ecb2..d2e46a5aa70 100644 --- a/framework/src/main/java/org/tron/core/net/message/SyncBlockChainMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/sync/SyncBlockChainMessage.java @@ -1,7 +1,8 @@ -package org.tron.core.net.message; +package org.tron.core.net.message.sync; import java.util.List; import org.tron.core.capsule.BlockCapsule.BlockId; +import org.tron.core.net.message.MessageTypes; import org.tron.protos.Protocol.BlockInventory.Type; public class SyncBlockChainMessage extends BlockInventoryMessage { diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java index 5d6d4eb7f75..115e97db50d 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java @@ -18,14 +18,14 @@ import org.tron.core.metrics.MetricsKey; import org.tron.core.metrics.MetricsUtil; import org.tron.core.net.TronNetDelegate; -import org.tron.core.net.message.BlockMessage; import org.tron.core.net.message.TronMessage; +import org.tron.core.net.message.adv.BlockMessage; import org.tron.core.net.peer.Item; import org.tron.core.net.peer.PeerConnection; -import org.tron.core.net.service.AdvService; -import org.tron.core.net.service.FetchBlockService; -import org.tron.core.net.service.RelayService; -import org.tron.core.net.service.SyncService; +import org.tron.core.net.service.adv.AdvService; +import org.tron.core.net.service.fetchblock.FetchBlockService; +import org.tron.core.net.service.relay.RelayService; +import org.tron.core.net.service.sync.SyncService; import org.tron.core.services.WitnessProductBlockService; import org.tron.protos.Protocol.Inventory.InventoryType; @@ -61,7 +61,7 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep BlockMessage blockMessage = (BlockMessage) msg; BlockId blockId = blockMessage.getBlockId(); - if (!fastForward && !peer.isFastForwardPeer()) { + if (!fastForward && !peer.isRelayPeer()) { check(peer, blockMessage); } @@ -71,13 +71,13 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep } else { Item item = new Item(blockId, InventoryType.BLOCK); long now = System.currentTimeMillis(); - if (peer.isFastForwardPeer()) { + if (peer.isRelayPeer()) { peer.getAdvInvSpread().put(item, now); } Long time = peer.getAdvInvRequest().remove(item); if (null != time) { MetricsUtil.histogramUpdateUnCheck(MetricsKey.NET_LATENCY_FETCH_BLOCK - + peer.getNode().getHost(), now - time); + + peer.getInetAddress(), now - time); Metrics.histogramObserve(MetricKeys.Histogram.BLOCK_FETCH_LATENCY, (now - time) / Metrics.MILLISECONDS_PER_SECOND); } @@ -91,7 +91,7 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep + "txs/process {}/{}ms, witness: {}", blockId.getNum(), interval, - peer.getInetAddress(), + peer.getInetSocketAddress(), time == null ? 0 : now - time, now - blockMessage.getBlockCapsule().getTimeStamp(), ((BlockMessage) msg).getBlockCapsule().getTransactions().size(), diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java index 81f0d2290a1..9b71f6f185a 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java @@ -6,22 +6,21 @@ import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; - import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.common.overlay.server.Channel; import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.config.Parameter.ChainConstant; import org.tron.core.config.Parameter.NetConstants; import org.tron.core.exception.P2pException; import org.tron.core.exception.P2pException.TypeEnum; import org.tron.core.net.TronNetDelegate; -import org.tron.core.net.message.ChainInventoryMessage; import org.tron.core.net.message.TronMessage; +import org.tron.core.net.message.sync.ChainInventoryMessage; import org.tron.core.net.peer.PeerConnection; -import org.tron.core.net.service.SyncService; +import org.tron.core.net.peer.TronState; +import org.tron.core.net.service.sync.SyncService; @Slf4j(topic = "net") @Component @@ -47,7 +46,7 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep Deque blockIdWeGet = new LinkedList<>(chainInventoryMessage.getBlockIds()); if (blockIdWeGet.size() == 1 && tronNetDelegate.containBlock(blockIdWeGet.peek())) { - peer.setTronState(Channel.TronState.SYNC_COMPLETED); + peer.setTronState(TronState.SYNC_COMPLETED); peer.setNeedSyncFromPeer(false); return; } @@ -74,11 +73,11 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep } if (blockId != null) { logger.info("Block {} from {} is processed", - blockId.getString(), peer.getNode().getHost()); + blockId.getString(), peer.getInetAddress()); } } catch (NoSuchElementException e) { logger.warn("Process ChainInventoryMessage failed, peer {}, isDisconnect:{}", - peer.getNode().getHost(), peer.isDisconnect()); + peer.getInetAddress(), peer.isDisconnect()); return; } } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java index c719674966d..6b5b68b1d11 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java @@ -1,7 +1,5 @@ package org.tron.core.net.messagehandler; -import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; - import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.collect.Lists; @@ -10,7 +8,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.common.overlay.discover.node.statistics.MessageCount; import org.tron.common.overlay.message.Message; import org.tron.common.utils.Sha256Hash; import org.tron.consensus.ConsensusDelegate; @@ -21,17 +18,17 @@ import org.tron.core.exception.P2pException; import org.tron.core.exception.P2pException.TypeEnum; import org.tron.core.net.TronNetDelegate; -import org.tron.core.net.message.BlockMessage; -import org.tron.core.net.message.FetchInvDataMessage; import org.tron.core.net.message.MessageTypes; -import org.tron.core.net.message.PbftCommitMessage; -import org.tron.core.net.message.TransactionMessage; -import org.tron.core.net.message.TransactionsMessage; import org.tron.core.net.message.TronMessage; +import org.tron.core.net.message.adv.BlockMessage; +import org.tron.core.net.message.adv.FetchInvDataMessage; +import org.tron.core.net.message.adv.TransactionMessage; +import org.tron.core.net.message.adv.TransactionsMessage; +import org.tron.core.net.message.pbft.PbftCommitMessage; import org.tron.core.net.peer.Item; import org.tron.core.net.peer.PeerConnection; -import org.tron.core.net.service.AdvService; -import org.tron.core.net.service.SyncService; +import org.tron.core.net.service.adv.AdvService; +import org.tron.core.net.service.sync.SyncService; import org.tron.protos.Protocol.Inventory.InventoryType; import org.tron.protos.Protocol.PBFTMessage.Raw; import org.tron.protos.Protocol.Transaction; @@ -139,8 +136,8 @@ private void check(PeerConnection peer, FetchInvDataMessage fetchInvDataMsg) thr throw new P2pException(TypeEnum.BAD_MESSAGE, "not spread inv: {}" + hash); } } - int fetchCount = peer.getNodeStatistics().messageStatistics.tronInTrxFetchInvDataElement - .getCount(10); + int fetchCount = peer.getPeerStatistics().messageStatistics.tronInTrxFetchInvDataElement + .getCount(10); int maxCount = advService.getTrxCount().getCount(60); if (fetchCount > maxCount) { logger.warn("Peer fetch too more transactions in 10 seconds, " @@ -155,17 +152,7 @@ private void check(PeerConnection peer, FetchInvDataMessage fetchInvDataMsg) thr break; } } - if (isAdv) { - MessageCount tronOutAdvBlock = peer.getNodeStatistics().messageStatistics.tronOutAdvBlock; - tronOutAdvBlock.add(fetchInvDataMsg.getHashList().size()); - int outBlockCountIn1min = tronOutAdvBlock.getCount(60); - int producedBlockIn2min = 120_000 / BLOCK_PRODUCED_INTERVAL; - if (outBlockCountIn1min > producedBlockIn2min) { - logger.warn("Peer fetch too more blocks in a minute, producedBlockIn2min: {}," - + " outBlockCountIn1min: {}, peer: {}", - producedBlockIn2min, outBlockCountIn1min, peer.getInetAddress()); - } - } else { + if (!isAdv) { if (!peer.isNeedSyncFromUs()) { throw new P2pException(TypeEnum.BAD_MESSAGE, "no need sync"); } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java index 96f022543f2..65fa09128db 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java @@ -6,11 +6,11 @@ import org.tron.common.utils.Sha256Hash; import org.tron.core.config.args.Args; import org.tron.core.net.TronNetDelegate; -import org.tron.core.net.message.InventoryMessage; import org.tron.core.net.message.TronMessage; +import org.tron.core.net.message.adv.InventoryMessage; import org.tron.core.net.peer.Item; import org.tron.core.net.peer.PeerConnection; -import org.tron.core.net.service.AdvService; +import org.tron.core.net.service.adv.AdvService; import org.tron.protos.Protocol.Inventory.InventoryType; @Slf4j(topic = "net") @@ -55,7 +55,7 @@ private boolean check(PeerConnection peer, InventoryMessage inventoryMessage) { } if (type.equals(InventoryType.TRX)) { - int count = peer.getNodeStatistics().messageStatistics.tronInTrxInventoryElement.getCount(10); + int count = peer.getPeerStatistics().messageStatistics.tronInTrxInventoryElement.getCount(10); if (count > maxCountIn10s) { logger.warn("Drop inv: {} size: {} from Peer {}, Inv count: {} is overload", type, size, peer.getInetAddress(), count); diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java index 5f107c9958d..238d131abe8 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java @@ -26,8 +26,8 @@ import org.tron.core.capsule.TransactionCapsule; import org.tron.core.db.PbftSignDataStore; import org.tron.core.exception.P2pException; -import org.tron.core.net.message.PbftCommitMessage; import org.tron.core.net.message.TronMessage; +import org.tron.core.net.message.pbft.PbftCommitMessage; import org.tron.core.net.peer.PeerConnection; import org.tron.protos.Protocol.PBFTMessage.DataType; import org.tron.protos.Protocol.PBFTMessage.Raw; diff --git a/framework/src/main/java/org/tron/core/net/PbftHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/PbftMsgHandler.java similarity index 56% rename from framework/src/main/java/org/tron/core/net/PbftHandler.java rename to framework/src/main/java/org/tron/core/net/messagehandler/PbftMsgHandler.java index 4120edce707..44eed8d1c2f 100644 --- a/framework/src/main/java/org/tron/core/net/PbftHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/PbftMsgHandler.java @@ -1,32 +1,22 @@ -package org.tron.core.net; +package org.tron.core.net.messagehandler; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.util.concurrent.Striped; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; -import org.tron.common.overlay.server.Channel; -import org.tron.common.overlay.server.MessageQueue; -import org.tron.common.overlay.server.SyncPool; import org.tron.consensus.base.Param; import org.tron.consensus.pbft.PbftManager; import org.tron.consensus.pbft.message.PbftBaseMessage; import org.tron.consensus.pbft.message.PbftMessage; import org.tron.core.exception.P2pException; +import org.tron.core.net.TronNetService; import org.tron.core.net.peer.PeerConnection; @Component -@Scope("prototype") -public class PbftHandler extends SimpleChannelInboundHandler { - - protected PeerConnection peer; - - private MessageQueue msgQueue; +public class PbftMsgHandler { private static final Striped striped = Striped.lazyWeakLock(1024); @@ -36,12 +26,7 @@ public class PbftHandler extends SimpleChannelInboundHandler { @Autowired private PbftManager pbftManager; - @Autowired - private SyncPool syncPool; - - @Override - public void channelRead0(final ChannelHandlerContext ctx, PbftMessage msg) throws Exception { - msgQueue.receivedMessage(msg); + public void processMessage(PeerConnection peer, PbftMessage msg) throws Exception { if (Param.getInstance().getPbftInterface().isSyncing()) { return; } @@ -57,7 +42,7 @@ public void channelRead0(final ChannelHandlerContext ctx, PbftMessage msg) throw throw new P2pException(P2pException.TypeEnum.BAD_MESSAGE, msg.toString()); } msgCache.put(key, true); - forwardMessage(msg); + forwardMessage(peer, msg); pbftManager.doAction(msg); } finally { lock.unlock(); @@ -65,27 +50,9 @@ public void channelRead0(final ChannelHandlerContext ctx, PbftMessage msg) throw } - public void forwardMessage(PbftBaseMessage message) { - if (syncPool == null) { - return; - } - syncPool.getActivePeers().stream().filter(peerConnection -> !peerConnection.equals(peer)) - .forEach(peerConnection -> { - peerConnection.sendMessage(message); - }); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - peer.processException(cause); - } - - public void setMsgQueue(MessageQueue msgQueue) { - this.msgQueue = msgQueue; - } - - public void setChannel(Channel channel) { - this.peer = (PeerConnection) channel; + public void forwardMessage(PeerConnection peer, PbftBaseMessage message) { + TronNetService.getPeers().stream().filter(peerConnection -> !peerConnection.equals(peer)) + .forEach(peerConnection -> peerConnection.sendMessage(message)); } private String buildKey(PbftBaseMessage msg) { diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java index d9fc767ac6c..37d46f6a8f3 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java @@ -11,9 +11,9 @@ import org.tron.core.exception.P2pException; import org.tron.core.exception.P2pException.TypeEnum; import org.tron.core.net.TronNetDelegate; -import org.tron.core.net.message.ChainInventoryMessage; -import org.tron.core.net.message.SyncBlockChainMessage; import org.tron.core.net.message.TronMessage; +import org.tron.core.net.message.sync.ChainInventoryMessage; +import org.tron.core.net.message.sync.SyncBlockChainMessage; import org.tron.core.net.peer.PeerConnection; import org.tron.protos.Protocol; diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java index 28cc68c2e44..df46c448e4d 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java @@ -15,12 +15,12 @@ import org.tron.core.exception.P2pException; import org.tron.core.exception.P2pException.TypeEnum; import org.tron.core.net.TronNetDelegate; -import org.tron.core.net.message.TransactionMessage; -import org.tron.core.net.message.TransactionsMessage; import org.tron.core.net.message.TronMessage; +import org.tron.core.net.message.adv.TransactionMessage; +import org.tron.core.net.message.adv.TransactionsMessage; import org.tron.core.net.peer.Item; import org.tron.core.net.peer.PeerConnection; -import org.tron.core.net.service.AdvService; +import org.tron.core.net.service.adv.AdvService; import org.tron.protos.Protocol.Inventory.InventoryType; import org.tron.protos.Protocol.ReasonCode; import org.tron.protos.Protocol.Transaction; diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index c23db4baa28..3c35e08dd0a 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -2,8 +2,12 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; +import com.google.protobuf.ByteString; +import java.net.InetAddress; +import java.net.InetSocketAddress; import java.util.Deque; import java.util.HashSet; +import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -15,22 +19,57 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; -import org.tron.common.overlay.message.HelloMessage; import org.tron.common.overlay.message.Message; -import org.tron.common.overlay.server.Channel; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.Metrics; import org.tron.common.utils.Pair; import org.tron.common.utils.Sha256Hash; +import org.tron.consensus.pbft.message.PbftBaseMessage; import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.config.Parameter.NetConstants; +import org.tron.core.metrics.MetricsKey; +import org.tron.core.metrics.MetricsUtil; import org.tron.core.net.TronNetDelegate; -import org.tron.core.net.service.AdvService; -import org.tron.core.net.service.SyncService; +import org.tron.core.net.message.adv.InventoryMessage; +import org.tron.core.net.message.adv.TransactionsMessage; +import org.tron.core.net.message.base.DisconnectMessage; +import org.tron.core.net.message.handshake.HelloMessage; +import org.tron.core.net.message.keepalive.PingMessage; +import org.tron.core.net.message.keepalive.PongMessage; +import org.tron.core.net.service.adv.AdvService; +import org.tron.core.net.service.statistics.NodeStatistics; +import org.tron.core.net.service.statistics.PeerStatistics; +import org.tron.core.net.service.statistics.TronStatsManager; +import org.tron.core.net.service.sync.SyncService; +import org.tron.p2p.connection.Channel; +import org.tron.protos.Protocol; @Slf4j(topic = "net") @Component @Scope("prototype") -public class PeerConnection extends Channel { +public class PeerConnection { + + @Getter + private PeerStatistics peerStatistics = new PeerStatistics(); + + @Getter + private NodeStatistics nodeStatistics; + + @Getter + private Channel channel; + + @Getter + @Setter + private boolean isRelayPeer; + + @Getter + @Setter + private ByteString address; + + @Getter + @Setter + private TronState tronState = TronState.INIT; @Autowired private TronNetDelegate tronNetDelegate; @@ -51,6 +90,8 @@ public class PeerConnection extends Channel { private int invCacheSize = 20_000; + private long BAD_PEER_BAN_TIME = 3600 * 1000; + @Setter @Getter private Cache advInvReceive = CacheBuilder.newBuilder().maximumSize(invCacheSize) @@ -100,6 +141,11 @@ public class PeerConnection extends Channel { @Getter private volatile boolean needSyncFromUs = true; + public void setChannel(Channel channel) { + this.channel = channel; + this.nodeStatistics = TronStatsManager.getNodeStatistics(channel.getInetAddress()); + } + public void setBlockBothHave(BlockId blockId) { this.blockBothHave = blockId; this.blockBothHaveUpdateTime = System.currentTimeMillis(); @@ -110,11 +156,11 @@ public boolean isIdle() { } public void sendMessage(Message message) { - msgQueue.sendMessage(message); - } - - public void fastSend(Message message) { - msgQueue.fastSend(message); + if (needToLog(message)) { + logger.info("Send peer {} message {}", channel.getInetSocketAddress(), message); + } + channel.send(message.getSendBytes()); + peerStatistics.messageStatistics.addTcpOutMessage(message); } public void onConnect() { @@ -149,9 +195,8 @@ public void onDisconnect() { public String log() { long now = System.currentTimeMillis(); return String.format( - "Peer %s [%8s]\n" - + "ping msg: count %d, max-average-min-last: %d %d %d %d\n" - + "connect time: %ds\n" + "Peer %s\n" + + "connect time: %ds [%sms]\n" + "last know block num: %s\n" + "needSyncFromPeer:%b\n" + "needSyncFromUs:%b\n" @@ -161,16 +206,9 @@ public String log() { + "remainNum:%d\n" + "syncChainRequested:%d\n" + "blockInProcess:%d\n", - getNode().getHost() + ":" + getNode().getPort(), - getNode().getHexIdShort(), - - getNodeStatistics().pingMessageLatency.getCount(), - getNodeStatistics().pingMessageLatency.getMax(), - getNodeStatistics().pingMessageLatency.getAvg(), - getNodeStatistics().pingMessageLatency.getMin(), - getNodeStatistics().pingMessageLatency.getLast(), - - (now - getStartTime()) / Constant.ONE_THOUSAND, + channel.getInetAddress(), + (now - channel.getStartTime()) / Constant.ONE_THOUSAND, + channel.getLatency(), fastForwardBlock != null ? fastForwardBlock.getNum() : blockBothHave.getNum(), isNeedSyncFromPeer(), isNeedSyncFromUs(), @@ -180,12 +218,79 @@ public String log() { remainNum, syncChainRequested == null ? 0 : (now - syncChainRequested.getValue()) / Constant.ONE_THOUSAND, - syncBlockInProcess.size()) - + nodeStatistics.toString() + "\n"; + syncBlockInProcess.size()); } public boolean isSyncFinish() { return !(needSyncFromPeer || needSyncFromUs); } + public void disconnect(Protocol.ReasonCode code) { + sendMessage(new DisconnectMessage(code)); + processDisconnect(code); + nodeStatistics.nodeDisconnectedLocal(code); + } + + public InetSocketAddress getInetSocketAddress() { + return channel.getInetSocketAddress(); + } + + public InetAddress getInetAddress() { + return channel.getInetAddress(); + } + + public boolean isDisconnect() { + return channel.isDisconnect(); + } + + private void processDisconnect(Protocol.ReasonCode reason) { + InetAddress inetAddress = channel.getInetAddress(); + if (inetAddress == null) { + return; + } + switch (reason) { + case BAD_PROTOCOL: + case BAD_BLOCK: + case BAD_TX: + channel.close(BAD_PEER_BAN_TIME); + break; + default: + channel.close(); + break; + } + MetricsUtil.counterInc(MetricsKey.NET_DISCONNECTION_COUNT); + MetricsUtil.counterInc(MetricsKey.NET_DISCONNECTION_DETAIL + reason); + Metrics.counterInc(MetricKeys.Counter.P2P_DISCONNECT, 1, + reason.name().toLowerCase(Locale.ROOT)); + } + + private boolean needToLog(Message msg) { + if (msg instanceof PingMessage + || msg instanceof PongMessage + || msg instanceof TransactionsMessage + || msg instanceof PbftBaseMessage) { + return false; + } + + if (msg instanceof InventoryMessage && ((InventoryMessage) msg) + .getInventoryType().equals(Protocol.Inventory.InventoryType.TRX)) { + return false; + } + + return true; + } + + @Override + public boolean equals(Object o) { + if (o == null || !(o instanceof PeerConnection)) { + return false; + } + return this.channel.equals(((PeerConnection) o).getChannel()); + } + + @Override + public int hashCode() { + return this.channel.hashCode(); + } + } diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java new file mode 100644 index 00000000000..dfcb0c0e599 --- /dev/null +++ b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java @@ -0,0 +1,154 @@ +package org.tron.core.net.peer; + +import com.google.common.collect.Lists; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationContext; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; +import org.tron.p2p.connection.Channel; + +@Slf4j(topic = "net") +public class PeerManager { + + private static List peers = Collections.synchronizedList(new ArrayList<>()); + @Getter + private static AtomicInteger passivePeersCount = new AtomicInteger(0); + @Getter + private static AtomicInteger activePeersCount = new AtomicInteger(0); + + private static ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + + private static long DISCONNECTION_TIME_OUT = 60_000; + + public static void init() { + executor.scheduleWithFixedDelay(() -> { + try { + check(); + logPeerStats(); + } catch (Throwable t) { + logger.error("Exception in peer manager", t); + } + }, 30, 10, TimeUnit.SECONDS); + } + + public static void close() { + try { + peers.forEach(p -> { + if (!p.isDisconnect()) { + p.getChannel().close(); + } + }); + executor.shutdownNow(); + } catch (Exception e) { + logger.error("Peer manager shutdown failed", e); + } + } + + public static synchronized PeerConnection add(ApplicationContext ctx, Channel channel) { + PeerConnection peerConnection = getPeerConnection(channel); + if (peerConnection != null) { + return null; + } + peerConnection = ctx.getBean(PeerConnection.class); + peerConnection.setChannel(channel); + peers.add(peerConnection); + if (channel.isActive()) { + activePeersCount.incrementAndGet(); + } else { + passivePeersCount.incrementAndGet(); + } + return peerConnection; + } + + public static synchronized PeerConnection remove(Channel channel) { + PeerConnection peerConnection = getPeerConnection(channel); + if (peerConnection == null) { + return null; + } + remove(peerConnection); + return peerConnection; + } + + private static void remove(PeerConnection peerConnection) { + peers.remove(peerConnection); + if (peerConnection.getChannel().isActive()) { + activePeersCount.decrementAndGet(); + } else { + passivePeersCount.decrementAndGet(); + } + } + + public static synchronized void sortPeers() { + peers.sort(Comparator.comparingDouble(c -> c.getChannel().getLatency())); + } + + public static PeerConnection getPeerConnection(Channel channel) { + for (PeerConnection peer : new ArrayList<>(peers)) { + if (peer.getChannel().equals(channel)) { + return peer; + } + } + return null; + } + + public static List getPeers() { + List peers = Lists.newArrayList(); + for (PeerConnection peer : new ArrayList<>(PeerManager.peers)) { + if (!peer.isDisconnect()) { + peers.add(peer); + } + } + return peers; + } + + private static void check() { + long now = System.currentTimeMillis(); + for (PeerConnection peer : new ArrayList<>(peers)) { + long disconnectTime = peer.getChannel().getDisconnectTime(); + if (disconnectTime != 0 && now - disconnectTime > DISCONNECTION_TIME_OUT) { + logger.warn("Notify disconnect peer {}.", peer.getInetSocketAddress()); + peers.remove(peer); + if (peer.getChannel().isActive()) { + activePeersCount.decrementAndGet(); + } else { + passivePeersCount.decrementAndGet(); + } + peer.onDisconnect(); + } + } + } + + private static synchronized void logPeerStats() { + String str = String.format("\n\n============ Peer stats: all %d, active %d, passive %d\n\n", + peers.size(), activePeersCount.get(), passivePeersCount.get()); + metric(peers.size(), MetricLabels.Gauge.PEERS_ALL); + metric(activePeersCount.get(), MetricLabels.Gauge.PEERS_ACTIVE); + metric(passivePeersCount.get(), MetricLabels.Gauge.PEERS_PASSIVE); + StringBuilder sb = new StringBuilder(str); + int valid = 0; + for (PeerConnection peer : new ArrayList<>(peers)) { + sb.append(peer.log()); + sb.append("\n"); + if (!(peer.isNeedSyncFromUs() || peer.isNeedSyncFromPeer())) { + valid++; + } + } + metric(valid, MetricLabels.Gauge.PEERS_VALID); + logger.info(sb.toString()); + } + + private static void metric(double amt, String peerType) { + Metrics.gaugeSet(MetricKeys.Gauge.PEERS, amt, peerType); + } + +} diff --git a/framework/src/main/java/org/tron/core/net/peer/TronState.java b/framework/src/main/java/org/tron/core/net/peer/TronState.java new file mode 100644 index 00000000000..34bd4a39288 --- /dev/null +++ b/framework/src/main/java/org/tron/core/net/peer/TronState.java @@ -0,0 +1,7 @@ +package org.tron.core.net.peer; + +public enum TronState { + INIT, + SYNCING, + SYNC_COMPLETED +} diff --git a/framework/src/main/java/org/tron/core/net/service/RelayService.java b/framework/src/main/java/org/tron/core/net/service/RelayService.java deleted file mode 100644 index b4abfc835ea..00000000000 --- a/framework/src/main/java/org/tron/core/net/service/RelayService.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.tron.core.net.service; - -import com.google.protobuf.ByteString; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.core.ChainBaseManager; -import org.tron.core.config.args.Args; -import org.tron.core.net.TronNetDelegate; -import org.tron.core.net.message.BlockMessage; -import org.tron.core.net.peer.Item; -import org.tron.core.net.peer.PeerConnection; -import org.tron.protos.Protocol; - -@Slf4j(topic = "net") -@Component -public class RelayService { - - @Autowired - private ChainBaseManager chainBaseManager; - - @Autowired - private TronNetDelegate tronNetDelegate; - - private int maxFastForwardNum = Args.getInstance().getMaxFastForwardNum(); - - private Set getNextWitnesses(ByteString key, Integer count) { - List list = chainBaseManager.getWitnessScheduleStore().getActiveWitnesses(); - int index = list.indexOf(key); - if (index < 0) { - return new HashSet<>(list); - } - Set set = new HashSet<>(); - for (; count > 0; count--) { - set.add(list.get(++index % list.size())); - } - return set; - } - - public void broadcast(BlockMessage msg) { - Set witnesses = getNextWitnesses( - msg.getBlockCapsule().getWitnessAddress(), maxFastForwardNum); - Item item = new Item(msg.getBlockId(), Protocol.Inventory.InventoryType.BLOCK); - List peers = tronNetDelegate.getActivePeer().stream() - .filter(peer -> !peer.isNeedSyncFromPeer() && !peer.isNeedSyncFromUs()) - .filter(peer -> peer.getAdvInvReceive().getIfPresent(item) == null - && peer.getAdvInvSpread().getIfPresent(item) == null) - .filter(peer -> peer.getAddress() != null && witnesses.contains(peer.getAddress())) - .collect(Collectors.toList()); - - peers.forEach(peer -> { - peer.fastSend(msg); - peer.getAdvInvSpread().put(item, System.currentTimeMillis()); - peer.setFastForwardBlock(msg.getBlockId()); - }); - } - -} - diff --git a/framework/src/main/java/org/tron/core/net/service/AdvService.java b/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java similarity index 95% rename from framework/src/main/java/org/tron/core/net/service/AdvService.java rename to framework/src/main/java/org/tron/core/net/service/adv/AdvService.java index b10e0542919..b6ea7a3445f 100644 --- a/framework/src/main/java/org/tron/core/net/service/AdvService.java +++ b/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java @@ -1,4 +1,4 @@ -package org.tron.core.net.service; +package org.tron.core.net.service.adv; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.NetConstants.MAX_TRX_FETCH_PER_PEER; @@ -19,23 +19,25 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; + import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.common.overlay.discover.node.statistics.MessageCount; import org.tron.common.overlay.message.Message; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.Time; import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.config.args.Args; import org.tron.core.net.TronNetDelegate; -import org.tron.core.net.message.BlockMessage; -import org.tron.core.net.message.FetchInvDataMessage; -import org.tron.core.net.message.InventoryMessage; -import org.tron.core.net.message.TransactionMessage; +import org.tron.core.net.message.adv.BlockMessage; +import org.tron.core.net.message.adv.FetchInvDataMessage; +import org.tron.core.net.message.adv.InventoryMessage; +import org.tron.core.net.message.adv.TransactionMessage; import org.tron.core.net.peer.Item; import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.service.fetchblock.FetchBlockService; +import org.tron.core.net.service.statistics.MessageCount; import org.tron.protos.Protocol.Inventory.InventoryType; @Slf4j(topic = "net") @@ -169,7 +171,7 @@ public int fastBroadcastTransaction(TransactionMessage msg) { && peer.getAdvInvSpread().getIfPresent(item) == null) { peersCount++; peer.getAdvInvSpread().put(item, Time.getCurrentMillis()); - peer.fastSend(inventoryMessage); + peer.sendMessage(inventoryMessage); } } if (peersCount == 0) { @@ -359,12 +361,12 @@ public int getSize(PeerConnection peer) { public void sendInv() { send.forEach((peer, ids) -> ids.forEach((key, value) -> { - if (peer.isFastForwardPeer() && key.equals(InventoryType.TRX)) { + if (peer.isRelayPeer() && key.equals(InventoryType.TRX)) { return; } if (key.equals(InventoryType.BLOCK)) { value.sort(Comparator.comparingLong(value1 -> new BlockId(value1).getNum())); - peer.fastSend(new InventoryMessage(value, key)); + peer.sendMessage(new InventoryMessage(value, key)); } else { peer.sendMessage(new InventoryMessage(value, key)); } @@ -375,7 +377,7 @@ void sendFetch() { send.forEach((peer, ids) -> ids.forEach((key, value) -> { if (key.equals(InventoryType.BLOCK)) { value.sort(Comparator.comparingLong(value1 -> new BlockId(value1).getNum())); - peer.fastSend(new FetchInvDataMessage(value, key)); + peer.sendMessage(new FetchInvDataMessage(value, key)); fetchBlockService.fetchBlock(value, peer); } else { peer.sendMessage(new FetchInvDataMessage(value, key)); diff --git a/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java b/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java similarity index 94% rename from framework/src/main/java/org/tron/core/net/service/FetchBlockService.java rename to framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java index ef541eb3559..f3699c3be2e 100644 --- a/framework/src/main/java/org/tron/core/net/service/FetchBlockService.java +++ b/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java @@ -1,4 +1,4 @@ -package org.tron.core.net.service; +package org.tron.core.net.service.fetchblock; import java.util.Collections; import java.util.Comparator; @@ -22,15 +22,11 @@ import org.tron.core.metrics.MetricsKey; import org.tron.core.metrics.MetricsUtil; import org.tron.core.net.TronNetDelegate; -import org.tron.core.net.message.FetchInvDataMessage; +import org.tron.core.net.message.adv.FetchInvDataMessage; import org.tron.core.net.peer.Item; import org.tron.core.net.peer.PeerConnection; import org.tron.protos.Protocol.Inventory.InventoryType; -/** - * @author kiven.miao - * @date 2022/3/17 3:50 下午 - */ @Slf4j(topic = "net") @Component public class FetchBlockService { @@ -123,7 +119,7 @@ private void fetchBlockProcess(FetchBlockInfo fetchBlock) { optionalPeerConnection.ifPresent(firstPeer -> { if (shouldFetchBlock(firstPeer, fetchBlock)) { firstPeer.getAdvInvRequest().put(item, System.currentTimeMillis()); - firstPeer.fastSend(new FetchInvDataMessage(Collections.singletonList(item.getHash()), + firstPeer.sendMessage(new FetchInvDataMessage(Collections.singletonList(item.getHash()), item.getType())); this.fetchBlockInfo = null; } @@ -152,7 +148,7 @@ private boolean shouldFetchBlock(PeerConnection newPeer, FetchBlockInfo fetchBlo private double getPeerTop75(PeerConnection peerConnection) { return MetricsUtil.getHistogram(MetricsKey.NET_LATENCY_FETCH_BLOCK - + peerConnection.getNode().getHost()).getSnapshot().get75thPercentile(); + + peerConnection.getInetAddress()).getSnapshot().get75thPercentile(); } private static class FetchBlockInfo { diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java new file mode 100644 index 00000000000..22ba096fb20 --- /dev/null +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -0,0 +1,119 @@ +package org.tron.core.net.service.handshake; + +import java.util.Arrays; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.utils.ByteArray; +import org.tron.core.ChainBaseManager; +import org.tron.core.config.args.Args; +import org.tron.core.net.TronNetService; +import org.tron.core.net.message.handshake.HelloMessage; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.peer.PeerManager; +import org.tron.core.net.service.relay.RelayService; +import org.tron.p2p.discover.Node; +import org.tron.protos.Protocol.ReasonCode; + +@Slf4j(topic = "net") +@Component +public class HandshakeService { + + @Autowired + private RelayService relayService; + + @Autowired + private ChainBaseManager chainBaseManager; + + public void startHandshake(PeerConnection peer) { + sendHelloMessage(peer, peer.getChannel().getStartTime()); + } + + public void processHelloMessage(PeerConnection peer, HelloMessage msg) { + if (peer.getHelloMessageReceive() != null) { + logger.warn("Peer {} receive dup hello message", peer.getInetSocketAddress()); + peer.disconnect(ReasonCode.BAD_PROTOCOL); + return; + } + + TronNetService.getP2pService().updateNodeId(peer.getChannel(), msg.getFrom().getHexId()); + if (peer.isDisconnect()) { + logger.info("Duplicate Peer {}", peer.getInetSocketAddress()); + peer.disconnect(ReasonCode.DUPLICATE_PEER); + return; + } + + if (!msg.valid()) { + logger.warn("Peer {} invalid hello message parameters, " + + "GenesisBlockId: {}, SolidBlockId: {}, HeadBlockId: {}", + peer.getInetSocketAddress(), + ByteArray.toHexString(msg.getInstance().getGenesisBlockId().getHash().toByteArray()), + ByteArray.toHexString(msg.getInstance().getSolidBlockId().getHash().toByteArray()), + ByteArray.toHexString(msg.getInstance().getHeadBlockId().getHash().toByteArray())); + peer.disconnect(ReasonCode.UNEXPECTED_IDENTITY); + return; + } + + peer.setAddress(msg.getHelloMessage().getAddress()); + + if (!relayService.checkHelloMessage(msg, peer.getChannel())) { + peer.disconnect(ReasonCode.UNEXPECTED_IDENTITY); + return; + } + + long headBlockNum = chainBaseManager.getHeadBlockNum(); + long lowestBlockNum = msg.getLowestBlockNum(); + if (lowestBlockNum > headBlockNum) { + logger.info("Peer {} miss block, lowestBlockNum:{}, headBlockNum:{}", + peer.getInetSocketAddress(), lowestBlockNum, headBlockNum); + peer.disconnect(ReasonCode.LIGHT_NODE_SYNC_FAIL); + return; + } + + if (msg.getVersion() != Args.getInstance().getNodeP2pVersion()) { + logger.info("Peer {} different p2p version, peer->{}, me->{}", + peer.getInetSocketAddress(), msg.getVersion(), + Args.getInstance().getNodeP2pVersion()); + peer.disconnect(ReasonCode.INCOMPATIBLE_VERSION); + return; + } + + if (!Arrays.equals(chainBaseManager.getGenesisBlockId().getBytes(), + msg.getGenesisBlockId().getBytes())) { + logger.info("Peer {} different genesis block, peer->{}, me->{}", + peer.getInetSocketAddress(), + msg.getGenesisBlockId().getString(), + chainBaseManager.getGenesisBlockId().getString()); + peer.disconnect(ReasonCode.INCOMPATIBLE_CHAIN); + return; + } + + if (chainBaseManager.getSolidBlockId().getNum() >= msg.getSolidBlockId().getNum() + && !chainBaseManager.containBlockInMainChain(msg.getSolidBlockId())) { + logger.info("Peer {} different solid block, peer->{}, me->{}", + peer.getInetSocketAddress(), + msg.getSolidBlockId().getString(), + chainBaseManager.getSolidBlockId().getString()); + peer.disconnect(ReasonCode.FORKED); + return; + } + + peer.setHelloMessageReceive(msg); + + peer.getChannel().updateLatency( + System.currentTimeMillis() - peer.getChannel().getStartTime()); + PeerManager.sortPeers(); + peer.onConnect(); + return; + } + + private void sendHelloMessage(PeerConnection peer, long time) { + Node node = new Node(TronNetService.getP2pConfig().getNodeID(), + TronNetService.getP2pConfig().getIp(), + TronNetService.getP2pConfig().getPort()); + HelloMessage message = new HelloMessage(node, time, ChainBaseManager.getChainBaseManager()); + peer.sendMessage(message); + peer.setHelloMessageSend(message); + } + +} diff --git a/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java b/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java new file mode 100644 index 00000000000..35c2843c046 --- /dev/null +++ b/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java @@ -0,0 +1,66 @@ +package org.tron.core.net.service.keepalive; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.tron.core.net.TronNetService; +import org.tron.core.net.message.MessageTypes; +import org.tron.core.net.message.TronMessage; +import org.tron.core.net.message.keepalive.PingMessage; +import org.tron.core.net.message.keepalive.PongMessage; +import org.tron.core.net.peer.PeerConnection; +import org.tron.protos.Protocol; + +@Slf4j(topic = "net") +@Component +public class KeepAliveService { + + private long KEEP_ALIVE_TIMEOUT = 10_000; + + private long PING_TIMEOUT = 20_000; + + public long PING_PERIOD = 60_000; + + private final ScheduledExecutorService executor = + Executors.newSingleThreadScheduledExecutor(r -> new Thread(r, "KeepAlive")); + + public void init() { + executor.scheduleWithFixedDelay(() -> { + try { + long now = System.currentTimeMillis(); + TronNetService.getPeers().forEach(p -> { + long pingSent = p.getChannel().pingSent; + long lastSendTime = p.getChannel().getLastSendTime(); + if (p.getChannel().waitForPong) { + if (now - pingSent > PING_TIMEOUT) { + p.disconnect(Protocol.ReasonCode.TIME_OUT); + } + } else { + if (now - lastSendTime > KEEP_ALIVE_TIMEOUT || now - pingSent > PING_PERIOD) { + p.sendMessage(new PingMessage()); + p.getChannel().waitForPong = true; + p.getChannel().pingSent = now; + } + } + }); + } catch (Throwable t) { + logger.error("Exception in keep alive task.", t); + } + }, 2, 2, TimeUnit.SECONDS); + } + + public void close() { + executor.shutdown(); + } + + public void processMessage(PeerConnection peer, TronMessage message) { + if (message.getType().equals(MessageTypes.P2P_PING)) { + peer.sendMessage(new PongMessage()); + } else { + peer.getChannel().updateLatency(System.currentTimeMillis() - peer.getChannel().pingSent); + peer.getChannel().waitForPong = false; + } + } +} diff --git a/framework/src/main/java/org/tron/core/net/service/nodepersist/DBNode.java b/framework/src/main/java/org/tron/core/net/service/nodepersist/DBNode.java new file mode 100644 index 00000000000..74b4902dd77 --- /dev/null +++ b/framework/src/main/java/org/tron/core/net/service/nodepersist/DBNode.java @@ -0,0 +1,24 @@ +package org.tron.core.net.service.nodepersist; + +import lombok.Getter; +import lombok.Setter; + +public class DBNode { + + @Getter + @Setter + private String host; + + @Getter + @Setter + private int port; + + public DBNode() { + } + + public DBNode(String host, int port) { + this.host = host; + this.port = port; + } + +} diff --git a/framework/src/main/java/org/tron/core/net/service/nodepersist/DBNodes.java b/framework/src/main/java/org/tron/core/net/service/nodepersist/DBNodes.java new file mode 100644 index 00000000000..f56616d81e7 --- /dev/null +++ b/framework/src/main/java/org/tron/core/net/service/nodepersist/DBNodes.java @@ -0,0 +1,13 @@ +package org.tron.core.net.service.nodepersist; + +import java.util.ArrayList; +import java.util.List; +import lombok.Getter; +import lombok.Setter; + +public class DBNodes { + + @Getter + @Setter + private List nodes = new ArrayList<>(); +} \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/net/service/nodepersist/NodePersistService.java b/framework/src/main/java/org/tron/core/net/service/nodepersist/NodePersistService.java new file mode 100644 index 00000000000..02ff1e7a1aa --- /dev/null +++ b/framework/src/main/java/org/tron/core/net/service/nodepersist/NodePersistService.java @@ -0,0 +1,91 @@ +package org.tron.core.net.service.nodepersist; + +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.JsonUtil; +import org.tron.core.ChainBaseManager; +import org.tron.core.capsule.BytesCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.net.TronNetService; +import org.tron.p2p.discover.Node; + +@Slf4j(topic = "net") +@Component +public class NodePersistService { + private static final byte[] DB_KEY_PEERS = "peers".getBytes(); + private static final long DB_COMMIT_RATE = 1 * 60 * 1000L; + private static final int MAX_NODES_WRITE_TO_DB = 30; + + private boolean isNodePersist = Args.getInstance().isNodeDiscoveryPersist(); + + private ChainBaseManager chainBaseManager = ChainBaseManager.getInstance(); + + private Timer nodePersistTaskTimer = new Timer("NodePersistTaskTimer"); + + public void init() { + if (isNodePersist) { + nodePersistTaskTimer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + dbWrite(); + } + }, DB_COMMIT_RATE, DB_COMMIT_RATE); + } + } + + public void close() { + try { + nodePersistTaskTimer.cancel(); + } catch (Exception e) { + logger.error("Close nodePersistTaskTimer failed", e); + } + } + + public List dbRead() { + List nodes = new ArrayList<>(); + try { + byte[] nodeBytes = chainBaseManager.getCommonStore().get(DB_KEY_PEERS).getData(); + if (ByteArray.isEmpty(nodeBytes)) { + return nodes; + } + DBNodes dbNodes = JsonUtil.json2Obj(new String(nodeBytes), DBNodes.class); + logger.info("Read node from store: {} nodes", dbNodes.getNodes().size()); + dbNodes.getNodes().forEach(n -> nodes.add(new InetSocketAddress(n.getHost(), n.getPort()))); + } catch (Exception e) { + logger.warn("DB read nodes failed, {}", e.getMessage()); + } + return nodes; + } + + private void dbWrite() { + try { + List batch = new ArrayList<>(); + List tableNodes = TronNetService.getP2pService().getTableNodes(); + tableNodes.sort(Comparator.comparingLong(value -> -value.getUpdateTime())); + for (Node n : tableNodes) { + batch.add(new DBNode(n.getHost(), n.getPort())); + } + + if (batch.size() > MAX_NODES_WRITE_TO_DB) { + batch = batch.subList(0, MAX_NODES_WRITE_TO_DB); + } + + DBNodes dbNodes = new DBNodes(); + dbNodes.setNodes(batch); + + logger.info("Write nodes to store: {}/{} nodes", batch.size(), tableNodes.size()); + + chainBaseManager.getCommonStore() + .put(DB_KEY_PEERS, new BytesCapsule(JsonUtil.obj2Json(dbNodes).getBytes())); + } catch (Exception e) { + logger.warn("DB write nodes failed, {}", e.getMessage()); + } + } +} diff --git a/framework/src/main/java/org/tron/common/overlay/server/FastForward.java b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java similarity index 67% rename from framework/src/main/java/org/tron/common/overlay/server/FastForward.java rename to framework/src/main/java/org/tron/core/net/service/relay/RelayService.java index bc19fa206d9..46f3b5c7374 100644 --- a/framework/src/main/java/org/tron/common/overlay/server/FastForward.java +++ b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java @@ -1,15 +1,16 @@ -package org.tron.common.overlay.server; +package org.tron.core.net.service.relay; import com.google.protobuf.ByteString; -import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.codec.binary.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; @@ -17,28 +18,40 @@ import org.tron.common.backup.BackupManager.BackupStatusEnum; import org.tron.common.crypto.SignInterface; import org.tron.common.crypto.SignUtils; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.overlay.message.HelloMessage; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; +import org.tron.core.ChainBaseManager; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.TronNetService; +import org.tron.core.net.message.adv.BlockMessage; +import org.tron.core.net.message.handshake.HelloMessage; +import org.tron.core.net.peer.Item; +import org.tron.core.net.peer.PeerConnection; import org.tron.core.store.WitnessScheduleStore; +import org.tron.p2p.P2pConfig; +import org.tron.p2p.connection.Channel; import org.tron.protos.Protocol; -import org.tron.protos.Protocol.ReasonCode; @Slf4j(topic = "net") @Component -public class FastForward { +public class RelayService { + + @Autowired + private ChainBaseManager chainBaseManager; + + @Autowired + private TronNetDelegate tronNetDelegate; @Autowired private ApplicationContext ctx; - private Manager manager; + private P2pConfig p2pConfig; - private ChannelManager channelManager; + private Manager manager; private WitnessScheduleStore witnessScheduleStore; @@ -47,15 +60,19 @@ public class FastForward { private ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); private CommonParameter parameter = Args.getInstance(); - private List fastForwardNodes = parameter.getFastForwardNodes(); + + private List fastForwardNodes = parameter.getFastForwardNodes(); + private ByteString witnessAddress = ByteString .copyFrom(Args.getLocalWitnesses().getWitnessAccountAddress(CommonParameter.getInstance() .isECKeyCryptoEngine())); + private int keySize = Args.getLocalWitnesses().getPrivateKeys().size(); + private int maxFastForwardNum = Args.getInstance().getMaxFastForwardNum(); + public void init() { manager = ctx.getBean(Manager.class); - channelManager = ctx.getBean(ChannelManager.class); witnessScheduleStore = ctx.getBean(WitnessScheduleStore.class); backupManager = ctx.getBean(BackupManager.class); @@ -82,8 +99,7 @@ public void init() { public void fillHelloMessage(HelloMessage message, Channel channel) { if (isActiveWitness()) { - fastForwardNodes.forEach(node -> { - InetAddress address = new InetSocketAddress(node.getHost(), node.getPort()).getAddress(); + fastForwardNodes.forEach(address -> { if (address.equals(channel.getInetAddress())) { SignInterface cryptoEngine = SignUtils .fromPrivate(ByteArray.fromHexString(Args.getLocalWitnesses().getPrivateKey()), @@ -135,7 +151,7 @@ public boolean checkHelloMessage(HelloMessage message, Channel channel) { flag = Arrays.equals(sigAddress, witnessPermissionAddress); } if (flag) { - channelManager.getTrustNodes().put(channel.getInetAddress(), channel.getNode()); + p2pConfig.getTrustNodes().add(channel.getInetAddress()); } return flag; } catch (Exception e) { @@ -153,21 +169,48 @@ private boolean isActiveWitness() { } private void connect() { - fastForwardNodes.forEach(node -> { - InetAddress address = new InetSocketAddress(node.getHost(), node.getPort()).getAddress(); - channelManager.getActiveNodes().put(address, node); - }); + fastForwardNodes.forEach(address -> p2pConfig.getActiveNodes().add(address)); } private void disconnect() { - fastForwardNodes.forEach(node -> { - InetAddress address = new InetSocketAddress(node.getHost(), node.getPort()).getAddress(); - channelManager.getActiveNodes().remove(address); - channelManager.getActivePeers().forEach(channel -> { - if (channel.getInetAddress().equals(address)) { - channel.disconnect(ReasonCode.RESET); + fastForwardNodes.forEach(address -> { + p2pConfig.getActiveNodes().remove(address); + TronNetService.getPeers().forEach(peer -> { + if (peer.getInetAddress().equals(address.getAddress())) { + peer.getChannel().close(); } }); }); } + + private Set getNextWitnesses(ByteString key, Integer count) { + List list = chainBaseManager.getWitnessScheduleStore().getActiveWitnesses(); + int index = list.indexOf(key); + if (index < 0) { + return new HashSet<>(list); + } + Set set = new HashSet<>(); + for (; count > 0; count--) { + set.add(list.get(++index % list.size())); + } + return set; + } + + public void broadcast(BlockMessage msg) { + Set witnesses = getNextWitnesses( + msg.getBlockCapsule().getWitnessAddress(), maxFastForwardNum); + Item item = new Item(msg.getBlockId(), Protocol.Inventory.InventoryType.BLOCK); + List peers = tronNetDelegate.getActivePeer().stream() + .filter(peer -> !peer.isNeedSyncFromPeer() && !peer.isNeedSyncFromUs()) + .filter(peer -> peer.getAdvInvReceive().getIfPresent(item) == null + && peer.getAdvInvSpread().getIfPresent(item) == null) + .filter(peer -> peer.getAddress() != null && witnesses.contains(peer.getAddress())) + .collect(Collectors.toList()); + + peers.forEach(peer -> { + peer.sendMessage(msg); + peer.getAdvInvSpread().put(item, System.currentTimeMillis()); + peer.setFastForwardBlock(msg.getBlockId()); + }); + } } diff --git a/framework/src/main/java/org/tron/common/overlay/discover/node/statistics/MessageCount.java b/framework/src/main/java/org/tron/core/net/service/statistics/MessageCount.java similarity index 93% rename from framework/src/main/java/org/tron/common/overlay/discover/node/statistics/MessageCount.java rename to framework/src/main/java/org/tron/core/net/service/statistics/MessageCount.java index 28f0acfbf9e..750f4c52286 100644 --- a/framework/src/main/java/org/tron/common/overlay/discover/node/statistics/MessageCount.java +++ b/framework/src/main/java/org/tron/core/net/service/statistics/MessageCount.java @@ -1,8 +1,8 @@ -package org.tron.common.overlay.discover.node.statistics; +package org.tron.core.net.service.statistics; import lombok.extern.slf4j.Slf4j; -@Slf4j(topic = "discover") +@Slf4j(topic = "net") public class MessageCount { private static int SIZE = 60; diff --git a/framework/src/main/java/org/tron/common/overlay/discover/node/statistics/MessageStatistics.java b/framework/src/main/java/org/tron/core/net/service/statistics/MessageStatistics.java similarity index 78% rename from framework/src/main/java/org/tron/common/overlay/discover/node/statistics/MessageStatistics.java rename to framework/src/main/java/org/tron/core/net/service/statistics/MessageStatistics.java index fa285929639..6ed67026ada 100644 --- a/framework/src/main/java/org/tron/common/overlay/discover/node/statistics/MessageStatistics.java +++ b/framework/src/main/java/org/tron/core/net/service/statistics/MessageStatistics.java @@ -1,27 +1,13 @@ -package org.tron.common.overlay.discover.node.statistics; +package org.tron.core.net.service.statistics; -import lombok.extern.slf4j.Slf4j; -import org.tron.common.net.udp.message.UdpMessageTypeEnum; import org.tron.common.overlay.message.Message; -import org.tron.core.net.message.FetchInvDataMessage; -import org.tron.core.net.message.InventoryMessage; import org.tron.core.net.message.MessageTypes; -import org.tron.core.net.message.TransactionsMessage; +import org.tron.core.net.message.adv.FetchInvDataMessage; +import org.tron.core.net.message.adv.InventoryMessage; +import org.tron.core.net.message.adv.TransactionsMessage; -@Slf4j public class MessageStatistics { - //udp discovery - public final MessageCount discoverInPing = new MessageCount(); - public final MessageCount discoverOutPing = new MessageCount(); - public final MessageCount discoverInPong = new MessageCount(); - public final MessageCount discoverOutPong = new MessageCount(); - public final MessageCount discoverInFindNode = new MessageCount(); - public final MessageCount discoverOutFindNode = new MessageCount(); - public final MessageCount discoverInNeighbours = new MessageCount(); - public final MessageCount discoverOutNeighbours = new MessageCount(); - - //tcp p2p public final MessageCount p2pInHello = new MessageCount(); public final MessageCount p2pOutHello = new MessageCount(); public final MessageCount p2pInPing = new MessageCount(); @@ -31,7 +17,6 @@ public class MessageStatistics { public final MessageCount p2pInDisconnect = new MessageCount(); public final MessageCount p2pOutDisconnect = new MessageCount(); - //tcp tron public final MessageCount tronInMessage = new MessageCount(); public final MessageCount tronOutMessage = new MessageCount(); @@ -69,14 +54,6 @@ public class MessageStatistics { public final MessageCount tronOutBlock = new MessageCount(); public final MessageCount tronOutAdvBlock = new MessageCount(); - public void addUdpInMessage(UdpMessageTypeEnum type) { - addUdpMessage(type, true); - } - - public void addUdpOutMessage(UdpMessageTypeEnum type) { - addUdpMessage(type, false); - } - public void addTcpInMessage(Message msg) { addTcpMessage(msg, true); } @@ -85,41 +62,6 @@ public void addTcpOutMessage(Message msg) { addTcpMessage(msg, false); } - private void addUdpMessage(UdpMessageTypeEnum type, boolean flag) { - switch (type) { - case DISCOVER_PING: - if (flag) { - discoverInPing.add(); - } else { - discoverOutPing.add(); - } - break; - case DISCOVER_PONG: - if (flag) { - discoverInPong.add(); - } else { - discoverOutPong.add(); - } - break; - case DISCOVER_FIND_NODE: - if (flag) { - discoverInFindNode.add(); - } else { - discoverOutFindNode.add(); - } - break; - case DISCOVER_NEIGHBORS: - if (flag) { - discoverInNeighbours.add(); - } else { - discoverOutNeighbours.add(); - } - break; - default: - break; - } - } - private void addTcpMessage(Message msg, boolean flag) { if (flag) { @@ -216,8 +158,8 @@ private void addTcpMessage(Message msg, boolean flag) { break; } } - - + + private void messageProcess(MessageTypes messageType, MessageCount inTrx, MessageCount inTrxEle, diff --git a/framework/src/main/java/org/tron/core/net/service/statistics/NodeStatistics.java b/framework/src/main/java/org/tron/core/net/service/statistics/NodeStatistics.java new file mode 100644 index 00000000000..1bfd7a41738 --- /dev/null +++ b/framework/src/main/java/org/tron/core/net/service/statistics/NodeStatistics.java @@ -0,0 +1,54 @@ +package org.tron.core.net.service.statistics; + +import lombok.Getter; +import org.tron.protos.Protocol; + +public class NodeStatistics { + @Getter + private Protocol.ReasonCode remoteDisconnectReason = null; + @Getter + private Protocol.ReasonCode localDisconnectReason = null; + @Getter + private int disconnectTimes = 0; + private long lastDisconnectedTime = 0; + private long firstDisconnectedTime = 0; + private long start = System.currentTimeMillis(); + + public Protocol.ReasonCode getDisconnectReason() { + if (localDisconnectReason != null) { + return localDisconnectReason; + } + if (remoteDisconnectReason != null) { + return remoteDisconnectReason; + } + return Protocol.ReasonCode.UNKNOWN; + } + + public void nodeDisconnectedRemote(Protocol.ReasonCode reason) { + remoteDisconnectReason = reason; + notifyDisconnect(); + } + + public void nodeDisconnectedLocal(Protocol.ReasonCode reason) { + localDisconnectReason = reason; + notifyDisconnect(); + } + + private void notifyDisconnect() { + lastDisconnectedTime = System.currentTimeMillis(); + if (firstDisconnectedTime == 0) { + firstDisconnectedTime = lastDisconnectedTime; + } + disconnectTimes++; + } + + @Override + public String toString() { + return new StringBuilder() + .append("time:").append(System.currentTimeMillis() - start) + .append(", disconnectTimes:").append(disconnectTimes) + .append(", localReason:").append(localDisconnectReason) + .append(", remoteReason:").append(remoteDisconnectReason).toString(); + } + +} diff --git a/framework/src/main/java/org/tron/core/net/service/statistics/PeerStatistics.java b/framework/src/main/java/org/tron/core/net/service/statistics/PeerStatistics.java new file mode 100644 index 00000000000..8a73d8f21f1 --- /dev/null +++ b/framework/src/main/java/org/tron/core/net/service/statistics/PeerStatistics.java @@ -0,0 +1,5 @@ +package org.tron.core.net.service.statistics; + +public class PeerStatistics { + public final MessageStatistics messageStatistics = new MessageStatistics(); +} diff --git a/framework/src/main/java/org/tron/core/net/service/statistics/TronStatsManager.java b/framework/src/main/java/org/tron/core/net/service/statistics/TronStatsManager.java new file mode 100644 index 00000000000..cf241102dbf --- /dev/null +++ b/framework/src/main/java/org/tron/core/net/service/statistics/TronStatsManager.java @@ -0,0 +1,83 @@ +package org.tron.core.net.service.statistics; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import java.net.InetAddress; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.MetricLabels; +import org.tron.common.prometheus.Metrics; +import org.tron.core.metrics.MetricsKey; +import org.tron.core.metrics.MetricsUtil; +import org.tron.core.net.TronNetService; +import org.tron.p2p.stats.P2pStats; + +@Slf4j(topic = "net") +@Component +public class TronStatsManager { + private static volatile long TCP_TRAFFIC_IN = 0; + private static volatile long TCP_TRAFFIC_OUT = 0; + private static volatile long UDP_TRAFFIC_IN = 0; + private static volatile long UDP_TRAFFIC_OUT = 0; + + private static Cache cache = CacheBuilder.newBuilder() + .maximumSize(3000).recordStats().build(); + + private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + + public static NodeStatistics getNodeStatistics(InetAddress inetAddress) { + NodeStatistics nodeStatistics = cache.getIfPresent(inetAddress); + if (nodeStatistics == null) { + nodeStatistics = new NodeStatistics(); + cache.put(inetAddress, nodeStatistics); + } + return nodeStatistics; + } + + public void init() { + executor.scheduleWithFixedDelay(() -> { + try { + work(); + } catch (Throwable t) { + logger.error("Exception in traffic stats worker, {}", t.getMessage()); + } + }, 1, 1, TimeUnit.SECONDS); + } + + public void close() { + try { + executor.shutdownNow(); + } catch (Exception e) { + logger.error("Exception in shutdown traffic stats worker, {}", e.getMessage()); + } + } + + private void work() { + P2pStats stats = TronNetService.getP2pService().getP2pStats(); + + MetricsUtil.meterMark(MetricsKey.NET_TCP_IN_TRAFFIC, + stats.getTcpInSize() - TCP_TRAFFIC_IN); + Metrics.histogramObserve(MetricKeys.Histogram.TCP_BYTES, + stats.getTcpInSize() - TCP_TRAFFIC_IN, + MetricLabels.Histogram.TRAFFIC_IN); + MetricsUtil.meterMark(MetricsKey.NET_TCP_OUT_TRAFFIC, + stats.getTcpOutSize() - TCP_TRAFFIC_OUT); + Metrics.histogramObserve(MetricKeys.Histogram.UDP_BYTES, + stats.getUdpInSize() - UDP_TRAFFIC_IN, + MetricLabels.Histogram.TRAFFIC_IN); + MetricsUtil.meterMark(MetricsKey.NET_UDP_OUT_TRAFFIC, + stats.getUdpOutSize() - UDP_TRAFFIC_OUT); + Metrics.histogramObserve(MetricKeys.Histogram.UDP_BYTES, + stats.getUdpOutSize() - UDP_TRAFFIC_OUT, + MetricLabels.Histogram.TRAFFIC_OUT); + + TCP_TRAFFIC_IN = stats.getTcpInSize(); + TCP_TRAFFIC_OUT = stats.getTcpOutSize(); + UDP_TRAFFIC_IN = stats.getUdpInSize(); + UDP_TRAFFIC_OUT = stats.getUdpOutSize(); + } +} diff --git a/framework/src/main/java/org/tron/core/net/service/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java similarity index 96% rename from framework/src/main/java/org/tron/core/net/service/SyncService.java rename to framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 79697d7459f..f9351199b3e 100644 --- a/framework/src/main/java/org/tron/core/net/service/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -1,4 +1,4 @@ -package org.tron.core.net.service; +package org.tron.core.net.service.sync; import static org.tron.core.config.Parameter.NetConstants.MAX_BLOCK_FETCH_PER_PEER; @@ -18,7 +18,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.common.overlay.server.Channel.TronState; import org.tron.common.utils.Pair; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.BlockCapsule.BlockId; @@ -27,11 +26,12 @@ import org.tron.core.exception.P2pException; import org.tron.core.exception.P2pException.TypeEnum; import org.tron.core.net.TronNetDelegate; -import org.tron.core.net.message.BlockMessage; -import org.tron.core.net.message.FetchInvDataMessage; -import org.tron.core.net.message.SyncBlockChainMessage; +import org.tron.core.net.message.adv.BlockMessage; +import org.tron.core.net.message.adv.FetchInvDataMessage; +import org.tron.core.net.message.sync.SyncBlockChainMessage; import org.tron.core.net.messagehandler.PbftDataSyncHandler; import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.peer.TronState; import org.tron.protos.Protocol.Inventory.InventoryType; import org.tron.protos.Protocol.ReasonCode; @@ -95,7 +95,7 @@ public void close() { public void startSync(PeerConnection peer) { if (peer.getTronState().equals(TronState.SYNCING)) { - logger.warn("Start sync failed, peer {} is in sync", peer.getNode().getHost()); + logger.warn("Start sync failed, peer {} is in sync", peer.getInetSocketAddress()); return; } peer.setTronState(TronState.SYNCING); @@ -109,7 +109,7 @@ public void startSync(PeerConnection peer) { public void syncNext(PeerConnection peer) { try { if (peer.getSyncChainRequested() != null) { - logger.warn("Peer {} is in sync", peer.getNode().getHost()); + logger.warn("Peer {} is in sync", peer.getInetSocketAddress()); return; } LinkedList chainSummary = getBlockChainSummary(peer); @@ -201,7 +201,6 @@ private LinkedList getBlockChainSummary(PeerConnection peer) throws P2p private void startFetchSyncBlock() { HashMap> send = new HashMap<>(); - tronNetDelegate.getActivePeer().stream() .filter(peer -> peer.isNeedSyncFromPeer() && peer.isIdle()) .forEach(peer -> { diff --git a/framework/src/main/java/org/tron/core/services/NodeInfoService.java b/framework/src/main/java/org/tron/core/services/NodeInfoService.java index 79aff5b8a71..c67f522f1bc 100644 --- a/framework/src/main/java/org/tron/core/services/NodeInfoService.java +++ b/framework/src/main/java/org/tron/core/services/NodeInfoService.java @@ -11,6 +11,8 @@ import java.util.Arrays; import java.util.List; import java.util.Map.Entry; + +import org.apache.commons.codec.binary.Hex; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ArrayUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -21,14 +23,20 @@ import org.tron.common.entity.NodeInfo.MachineInfo.DeadLockThreadInfo; import org.tron.common.entity.NodeInfo.MachineInfo.MemoryDescInfo; import org.tron.common.entity.PeerInfo; -import org.tron.common.overlay.discover.node.NodeManager; -import org.tron.common.overlay.server.SyncPool; import org.tron.common.parameter.CommonParameter; import org.tron.common.prometheus.MetricTime; import org.tron.core.ChainBaseManager; import org.tron.core.db.Manager; +import org.tron.core.net.P2pEventHandlerImpl; +import org.tron.core.net.TronNetService; import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.peer.PeerManager; +import org.tron.core.net.service.statistics.NodeStatistics; +import org.tron.core.net.service.statistics.PeerStatistics; import org.tron.core.services.WitnessProductBlockService.CheatWitnessInfo; +import org.tron.p2p.P2pConfig; +import org.tron.p2p.P2pService; +import org.tron.p2p.connection.Channel; import org.tron.program.Version; import org.tron.protos.Protocol.ReasonCode; @@ -42,12 +50,6 @@ public class NodeInfoService { .getOperatingSystemMXBean(); private CommonParameter parameter = CommonParameter.getInstance(); - @Autowired - private SyncPool syncPool; - - @Autowired - private NodeManager nodeManager; - @Autowired private Manager dbManager; @@ -124,48 +126,49 @@ private void setMachineInfo(NodeInfo nodeInfo) { } private void setConnectInfo(NodeInfo nodeInfo) { - nodeInfo.setCurrentConnectCount(syncPool.getActivePeers().size()); - nodeInfo.setActiveConnectCount(syncPool.getActivePeersCount().get()); - nodeInfo.setPassiveConnectCount(syncPool.getPassivePeersCount().get()); - long totalFlow = 0; + int activeCnt = PeerManager.getActivePeersCount().get(); + int passiveCnt = PeerManager.getPassivePeersCount().get(); + nodeInfo.setCurrentConnectCount(activeCnt + passiveCnt); + nodeInfo.setActiveConnectCount(activeCnt); + nodeInfo.setPassiveConnectCount(passiveCnt); List peerInfoList = new ArrayList<>(); - for (PeerConnection peerConnection : syncPool.getActivePeers()) { + for (PeerConnection peerConnection : PeerManager.getPeers()) { + Channel channel = peerConnection.getChannel(); + NodeStatistics nodeStatistics = peerConnection.getNodeStatistics(); + P2pService P2pService = TronNetService.getP2pService(); + P2pConfig p2pConfig = TronNetService.getP2pConfig(); PeerInfo peerInfo = new PeerInfo(); peerInfo.setHeadBlockWeBothHave(peerConnection.getBlockBothHave().getString()); - peerInfo.setActive(peerConnection.isActive()); - peerInfo.setAvgLatency(peerConnection.getNodeStatistics().pingMessageLatency.getAvg()); + peerInfo.setActive(peerConnection.getChannel().isActive()); + peerInfo.setAvgLatency(peerConnection.getChannel().getLatency()); peerInfo.setBlockInPorcSize(peerConnection.getSyncBlockInProcess().size()); - peerInfo.setConnectTime(peerConnection.getStartTime()); - peerInfo.setDisconnectTimes(peerConnection.getNodeStatistics().getDisconnectTimes()); + peerInfo.setConnectTime(channel.getStartTime()); + peerInfo.setDisconnectTimes(nodeStatistics.getDisconnectTimes()); //peerInfo.setHeadBlockTimeWeBothHave(peerConnection.getHeadBlockTimeWeBothHave()); - peerInfo.setHost(peerConnection.getNode().getHost()); - peerInfo.setInFlow(peerConnection.getNodeStatistics().tcpFlow.getTotalCount()); + peerInfo.setHost(channel.getInetAddress().toString()); peerInfo.setLastBlockUpdateTime(peerConnection.getBlockBothHaveUpdateTime()); peerInfo.setLastSyncBlock(peerConnection.getLastSyncBlockId() == null ? "" : peerConnection.getLastSyncBlockId().getString()); - ReasonCode reasonCode = peerConnection.getNodeStatistics() - .getTronLastLocalDisconnectReason(); + ReasonCode reasonCode = nodeStatistics.getLocalDisconnectReason(); peerInfo.setLocalDisconnectReason(reasonCode == null ? "" : reasonCode.toString()); - reasonCode = peerConnection.getNodeStatistics().getTronLastRemoteDisconnectReason(); + reasonCode = nodeStatistics.getRemoteDisconnectReason(); peerInfo.setRemoteDisconnectReason(reasonCode == null ? "" : reasonCode.toString()); peerInfo.setNeedSyncFromPeer(peerConnection.isNeedSyncFromPeer()); peerInfo.setNeedSyncFromUs(peerConnection.isNeedSyncFromUs()); - peerInfo.setNodeCount(nodeManager.getTable().getAllNodes().size()); - peerInfo.setNodeId(peerConnection.getNode().getHexId()); - peerInfo.setPort(peerConnection.getNode().getPort()); + int tableNodesSize = P2pService.getTableNodes().size(); + peerInfo.setNodeCount(tableNodesSize); + peerInfo.setNodeId(Hex.encodeHexString(p2pConfig.getNodeID())); + peerInfo.setPort(p2pConfig.getPort()); peerInfo.setRemainNum(peerConnection.getRemainNum()); - peerInfo.setScore(peerConnection.getNodeStatistics().getReputation()); peerInfo.setSyncBlockRequestedSize(peerConnection.getSyncBlockRequested().size()); peerInfo.setSyncFlag(peerConnection.isDisconnect()); peerInfo.setSyncToFetchSize(peerConnection.getSyncBlockToFetch().size()); peerInfo.setSyncToFetchSizePeekNum(peerConnection.getSyncBlockToFetch().size() > 0 ? peerConnection.getSyncBlockToFetch().peek().getNum() : -1); peerInfo.setUnFetchSynNum(peerConnection.getRemainNum()); - totalFlow += peerConnection.getNodeStatistics().tcpFlow.getTotalCount(); peerInfoList.add(peerInfo); } nodeInfo.setPeerList(peerInfoList); - nodeInfo.setTotalFlow(totalFlow); } private void setConfigNodeInfo(NodeInfo nodeInfo) { @@ -177,7 +180,7 @@ private void setConfigNodeInfo(NodeInfo nodeInfo) { configNodeInfo.setDiscoverEnable(parameter.isNodeDiscoveryEnable()); configNodeInfo.setActiveNodeSize(parameter.getActiveNodes().size()); configNodeInfo.setPassiveNodeSize(parameter.getPassiveNodes().size()); - configNodeInfo.setSendNodeSize(parameter.getSeedNodes().size()); + configNodeInfo.setSendNodeSize(parameter.getSeedNode().getIpList().size()); configNodeInfo.setMaxConnectCount(parameter.getMaxConnections()); configNodeInfo.setSameIpMaxConnectCount(parameter.getMaxConnectionsWithSameIp()); configNodeInfo.setBackupListenPort(parameter.getBackupPort()); diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index c964536aa33..487f7d7076c 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -88,8 +88,6 @@ import org.tron.common.application.Service; import org.tron.common.crypto.SignInterface; import org.tron.common.crypto.SignUtils; -import org.tron.common.overlay.discover.node.NodeHandler; -import org.tron.common.overlay.discover.node.NodeManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; @@ -111,6 +109,7 @@ import org.tron.core.exception.VMIllegalException; import org.tron.core.exception.ZksnarkException; import org.tron.core.metrics.MetricsApiService; +import org.tron.core.net.TronNetService; import org.tron.core.services.filter.LiteFnQueryGrpcInterceptor; import org.tron.core.services.ratelimiter.RateLimiterInterceptor; import org.tron.core.services.ratelimiter.RpcApiAccessInterceptor; @@ -188,8 +187,6 @@ public class RpcApiService implements Service { @Autowired private ChainBaseManager chainBaseManager; - @Autowired - private NodeManager nodeManager; @Autowired private Wallet wallet; @@ -1603,24 +1600,13 @@ public void getTransactionCountByBlockNum(NumberMessage request, @Override public void listNodes(EmptyMessage request, StreamObserver responseObserver) { - List handlerList = nodeManager.dumpActiveNodes(); - - Map nodeHandlerMap = new HashMap<>(); - for (NodeHandler handler : handlerList) { - String key = handler.getNode().getHexId() + handler.getNode().getHost(); - nodeHandlerMap.put(key, handler); - } - NodeList.Builder nodeListBuilder = NodeList.newBuilder(); - - nodeHandlerMap.entrySet().stream() - .forEach(v -> { - org.tron.common.overlay.discover.node.Node node = v.getValue().getNode(); - nodeListBuilder.addNodes(Node.newBuilder().setAddress( + TronNetService.getP2pService().getConnectableNodes().forEach(node -> { + nodeListBuilder.addNodes(Node.newBuilder().setAddress( Address.newBuilder() - .setHost(ByteString.copyFrom(ByteArray.fromString(node.getHost()))) - .setPort(node.getPort()))); - }); + .setHost(ByteString.copyFrom(ByteArray.fromString(node.getHost()))) + .setPort(node.getPort()))); + }); responseObserver.onNext(nodeListBuilder.build()); responseObserver.onCompleted(); } diff --git a/framework/src/main/java/org/tron/program/FullNode.java b/framework/src/main/java/org/tron/program/FullNode.java index 63c1edaaecf..a056609a665 100644 --- a/framework/src/main/java/org/tron/program/FullNode.java +++ b/framework/src/main/java/org/tron/program/FullNode.java @@ -15,6 +15,7 @@ import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; +import org.tron.core.net.P2pEventHandlerImpl; import org.tron.core.services.RpcApiService; import org.tron.core.services.http.FullNodeHttpApiService; import org.tron.core.services.interfaceJsonRpcOnPBFT.JsonRpcServiceOnPBFT; @@ -79,7 +80,6 @@ public static void main(String[] args) { TronApplicationContext context = new TronApplicationContext(beanFactory); context.register(DefaultConfig.class); - context.refresh(); Application appT = ApplicationFactory.create(context); shutdown(appT); diff --git a/framework/src/main/java/org/tron/program/SolidityNode.java b/framework/src/main/java/org/tron/program/SolidityNode.java index e0c1fcaa231..9884a14a62b 100644 --- a/framework/src/main/java/org/tron/program/SolidityNode.java +++ b/framework/src/main/java/org/tron/program/SolidityNode.java @@ -11,9 +11,7 @@ import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; -import org.tron.common.overlay.client.DatabaseGrpcClient; -import org.tron.common.overlay.discover.DiscoverServer; -import org.tron.common.overlay.discover.node.NodeManager; +import org.tron.common.client.DatabaseGrpcClient; import org.tron.common.parameter.CommonParameter; import org.tron.common.prometheus.Metrics; import org.tron.core.ChainBaseManager; @@ -22,7 +20,6 @@ import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; -import org.tron.core.net.TronNetService; import org.tron.core.services.RpcApiService; import org.tron.core.services.http.solidity.SolidityNodeHttpApiService; import org.tron.protos.Protocol.Block; @@ -97,14 +94,6 @@ public static void main(String[] args) { appT.startServices(); appT.startup(); - //Disable peer discovery for solidity node - DiscoverServer discoverServer = context.getBean(DiscoverServer.class); - discoverServer.close(); - NodeManager nodeManager = context.getBean(NodeManager.class); - nodeManager.close(); - TronNetService tronNetService = context.getBean(TronNetService.class); - tronNetService.stop(); - SolidityNode node = new SolidityNode(appT.getDbManager()); node.start(); diff --git a/framework/src/test/java/org/tron/common/overlay/discover/node/NodeHandlerTest.java b/framework/src/test/java/org/tron/common/overlay/discover/node/NodeHandlerTest.java deleted file mode 100644 index dfe24f8e644..00000000000 --- a/framework/src/test/java/org/tron/common/overlay/discover/node/NodeHandlerTest.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.tron.common.overlay.discover.node; - -import java.io.File; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; -import org.tron.core.ChainBaseManager; -import org.tron.core.Constant; -import org.tron.core.config.DefaultConfig; -import org.tron.core.config.args.Args; - - -public class NodeHandlerTest { - - private static final Logger logger = LoggerFactory.getLogger("Test"); - // private static Manager dbManager; - private static TronApplicationContext context; - // private Application appTest; - // private CommonParameter argsTest; - private static Node currNode; - private static Node oldNode; - private static Node replaceNode; - private static NodeHandler currHandler; - private static NodeHandler oldHandler; - private static NodeHandler replaceHandler; - private static NodeManager nodeManager; - private static String dbPath = "NodeHandlerTest"; - - static { - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - } - - /** - * init the application. - */ - @BeforeClass - public static void init() { - initNodes(); - } - - /** - * destroy the context. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - - /** - * init nodes. - */ - public static void initNodes() { - // dbManager = context.getBean(Manager.class); - nodeManager = new NodeManager(context.getBean(ChainBaseManager.class)); - String currNodeId = "74c11ffad1d59d7b1a56691a0b84a53f0791c92361357364f1d2537" - + "898407ef0249bbbf5a4ce8cff9e34e2fdf8bac883540e026d1e5d6ebf536414bdde81198e"; - String oldNodeId = "74c11ffad1d59d7b2c56691a0b84a53f0791c92361357364f1d2537898407e" - + "f0249bbbf5a4ce8cff9e34e2fdf8bac883540e026d1e5d6ebf536414bdde81198e"; - String replaceNodeId = "74c11ffad1d59d7b1a56691a0b84a53f0791c92361357364f1d2537" - + "837407ef0249bbbf5a4ce8cff9e34e2fdf8bac883540e026d1e5d6ebf536414bdde81198e"; - currNode = new Node(currNodeId.getBytes(), "47.95.206.44", 18885, 18888); - oldNode = new Node(oldNodeId.getBytes(), "36.95.165.44", 18885, 18888); - replaceNode = new Node(replaceNodeId.getBytes(), "47.29.177.44", 18885, 18888); - currHandler = new NodeHandler(currNode, nodeManager); - oldHandler = new NodeHandler(oldNode, nodeManager); - replaceHandler = new NodeHandler(replaceNode, nodeManager); - } - - @Test - public void stateNonActiveTest() throws Exception { - Class clazz = NodeHandler.class; - Constructor cn = clazz.getDeclaredConstructor(Node.class, NodeManager.class); - NodeHandler nh = cn.newInstance(oldNode, nodeManager); - Field declaredField = clazz.getDeclaredField("replaceCandidate"); - declaredField.setAccessible(true); - declaredField.set(nh, replaceHandler); - - nodeManager.getTable().addNode(oldNode); - nh.changeState(NodeHandler.State.EVICTCANDIDATE); - nh.changeState(NodeHandler.State.NONACTIVE); - replaceHandler.changeState(NodeHandler.State.ALIVE); - - Assert.assertFalse(nodeManager.getTable().contains(oldNode)); - Assert.assertTrue(nodeManager.getTable().contains(replaceNode)); - } -} diff --git a/framework/src/test/java/org/tron/common/overlay/discover/node/NodeManagerTest.java b/framework/src/test/java/org/tron/common/overlay/discover/node/NodeManagerTest.java deleted file mode 100644 index f5b870bacdf..00000000000 --- a/framework/src/test/java/org/tron/common/overlay/discover/node/NodeManagerTest.java +++ /dev/null @@ -1,226 +0,0 @@ -package org.tron.common.overlay.discover.node; - -import java.io.File; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.tron.common.application.Application; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.FileUtil; -import org.tron.core.ChainBaseManager; -import org.tron.core.Constant; -import org.tron.core.config.DefaultConfig; -import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; - - -public class NodeManagerTest { - - private static final Logger logger = LoggerFactory.getLogger("Test"); - private static Manager manager; - private static NodeManager nodeManager; - private static TronApplicationContext context; - private static CommonParameter argsTest; - private static Application appTest; - private static Class nodeManagerClazz; - private static String dbPath = "NodeManagerTest"; - - static { - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - } - - /** - * start the application. - */ - @BeforeClass - public static void init() { - // argsTest = Args.getInstance(); - // Args.setParam(new String[]{"--output-directory", dbPath}, - // Constant.TEST_CONF); - // context = new TronApplicationContext(DefaultConfig.class); - // appTest = ApplicationFactory.create(context); - // appTest.initServices(argsTest); - // appTest.startServices(); - // appTest.startup(); - try { - initManager(); - } catch (Exception e) { - logger.error("init failed {}", e.getMessage()); - } - } - - /** - * destroy the context. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - - /** - * init the managers. - */ - // @Before - public static void initManager() throws Exception { - nodeManagerClazz = NodeManager.class; - // Constructor handlerConstructor - // = nodeManagerClazz.getConstructor(ChainBaseManager.class); - manager = context.getBean(Manager.class); - // nodeManager = handlerConstructor.newInstance(context.getBean(ChainBaseManager.class)); - nodeManager = new NodeManager(context.getBean(ChainBaseManager.class)); - } - - @Test - public void isNodeAliveTest() { - Node node = new Node(new byte[64], "128.0.0.1", 18889, 18889); - nodeManager.getTable().addNode(node); - NodeHandler nodeHandler = new NodeHandler(node, nodeManager); - nodeHandler.changeState(NodeHandler.State.ACTIVE); - Assert.assertTrue(nodeManager.isNodeAlive(nodeHandler)); - nodeHandler.changeState(NodeHandler.State.ALIVE); - Assert.assertTrue(nodeManager.isNodeAlive(nodeHandler)); - nodeHandler.changeState(NodeHandler.State.EVICTCANDIDATE); - Assert.assertTrue(nodeManager.isNodeAlive(nodeHandler)); - } - - @Test - public void trimTableTest_removeByReputation() throws Exception { - //insert 3001 nodes(isConnectible = true) with threshold = 3000 - final int totalNodes = insertValues(3002); - Assert.assertEquals(calculateTrimNodes(totalNodes, 0), getHandlerMapSize()); - - clearNodeManager(); - } - - @Test - public void trimTableTest_removeNotConnectibleNodes() throws Exception { - final int totalNodes = insertValues(3000); - insertNotConnectibleNodes(); - Method method = nodeManagerClazz.getDeclaredMethod("trimTable"); - method.setAccessible(true); - method.invoke(nodeManager); - Assert.assertEquals(calculateTrimNodes(totalNodes, 2), getHandlerMapSize()); - - clearNodeManager(); - } - - private void clearNodeManager() { - nodeManager.clearNodeHandlerMap(); - } - - /** - * calculate nodes number after table trim. - * - * @param totalNodes total nodes inserted - * @param wrongNodes isConnectable = false - * @return nodes count after trimTable() - */ - public int calculateTrimNodes(int totalNodes, int wrongNodes) { - if (totalNodes + wrongNodes > 3000) { - if (totalNodes <= 3000) { - return totalNodes; - } else { - int result = 2000 + ((totalNodes + wrongNodes) % 2000 - 1001); - return result; - } - } - return totalNodes + wrongNodes; - } - - /** - * insert valid nodes in map. - * - * @param totalNodes total nodes to be inserted. - * @return total nodes inserted. - */ - public int insertValues(int totalNodes) throws Exception { - //put 3001 nodes in nodeHandlerMap - int ipPart3 = 1; - int ipPart4 = 1; - for (int i = 0; i < totalNodes; i++) { - StringBuilder stringBuilder = new StringBuilder("128.0."); - byte[] bytes = new byte[64]; - bytes[0] = (byte) (i + 1); - stringBuilder.append(ipPart3); - stringBuilder.append("."); - stringBuilder.append(ipPart4); - ipPart4++; - if (ipPart4 == 256) { - ipPart3++; - ipPart4 = 1; - } - Class nodeClazz = Node.class; - Constructor nodeConstructor - = nodeClazz.getConstructor(byte[].class, String.class, int.class, int.class); - Node node = nodeConstructor.newInstance(bytes, stringBuilder.toString(), 18889, 18889); - Field isConnectableField = nodeClazz.getDeclaredField("p2pVersion"); - isConnectableField.setAccessible(true); - isConnectableField.set(node, Args.getInstance().getNodeP2pVersion()); - nodeManager.getNodeHandler(node); - } - return totalNodes; - } - - /** - * insert nodes with illegal p2p version. - */ - public void insertNotConnectibleNodes() throws Exception { - Class nodeClazz = Node.class; - Constructor nodeConstructor - = nodeClazz.getConstructor(byte[].class, String.class, int.class, int.class); - Node wrongNode1 = nodeConstructor.newInstance(new byte[64], "128.0.0.1", 1111, 18889); - byte[] id = new byte[64]; - id[63] = 1; - Node wrongNode2 = nodeConstructor.newInstance(id, "128.0.0.2", 1111, 18889); - Field isConnectableField = nodeClazz.getDeclaredField("p2pVersion"); - isConnectableField.setAccessible(true); - isConnectableField.set(wrongNode1, 999); - isConnectableField.set(wrongNode2, 999); - nodeManager.getNodeHandler(wrongNode1); - nodeManager.getNodeHandler(wrongNode2); - } - - - /** - * get the size of nodeHandlerMap. - * - * @return NodeManager.nodeHandlerMap - */ - public int getHandlerMapSize() throws Exception { - Field mapField = nodeManagerClazz.getDeclaredField("nodeHandlerMap"); - mapField.setAccessible(true); - Map nodeHandlerMap = (ConcurrentHashMap) mapField.get(nodeManager); - return nodeHandlerMap.size(); - } - - @Test - public void dumpActiveNodesTest() { - Node node1 = new Node(new byte[64], "128.0.0.1", 18889, 18889); - Node node2 = new Node(new byte[64], "128.0.0.2", 18889, 18889); - Node node3 = new Node(new byte[64], "128.0.0.3", 18889, 18889); - NodeHandler nodeHandler1 = nodeManager.getNodeHandler(node1); - NodeHandler nodeHandler2 = nodeManager.getNodeHandler(node2); - NodeHandler nodeHandler3 = nodeManager.getNodeHandler(node3); - nodeHandler1.changeState(NodeHandler.State.ALIVE); - nodeHandler2.changeState(NodeHandler.State.ACTIVE); - nodeHandler3.changeState(NodeHandler.State.NONACTIVE); - int activeNodes = nodeManager.dumpActiveNodes().size(); - Assert.assertEquals(2, activeNodes); - } -} diff --git a/framework/src/test/java/org/tron/common/overlay/discover/node/NodeStatisticsTest.java b/framework/src/test/java/org/tron/common/overlay/discover/node/NodeStatisticsTest.java deleted file mode 100644 index 157c31e26a3..00000000000 --- a/framework/src/test/java/org/tron/common/overlay/discover/node/NodeStatisticsTest.java +++ /dev/null @@ -1,150 +0,0 @@ -package org.tron.common.overlay.discover.node; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.LinkedList; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.tron.common.net.udp.message.UdpMessageTypeEnum; -import org.tron.common.overlay.discover.node.statistics.MessageStatistics; -import org.tron.common.overlay.discover.node.statistics.NodeStatistics; -import org.tron.common.overlay.message.DisconnectMessage; -import org.tron.common.overlay.message.PongMessage; -import org.tron.common.utils.Sha256Hash; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.net.message.BlockMessage; -import org.tron.core.net.message.ChainInventoryMessage; -import org.tron.core.net.message.FetchInvDataMessage; -import org.tron.core.net.message.InventoryMessage; -import org.tron.core.net.message.MessageTypes; -import org.tron.core.net.message.SyncBlockChainMessage; -import org.tron.core.net.message.TransactionsMessage; -import org.tron.protos.Protocol; - -public class NodeStatisticsTest { - - private NodeStatistics nodeStatistics; - - @Before - public void init() { - this.nodeStatistics = new NodeStatistics(); - } - - @Test - public void testNode() throws NoSuchFieldException, IllegalAccessException { - Protocol.ReasonCode reasonCode = this.nodeStatistics.getDisconnectReason(); - Assert.assertEquals(Protocol.ReasonCode.UNKNOWN, reasonCode); - - boolean isReputationPenalized = this.nodeStatistics.isReputationPenalized(); - Assert.assertFalse(isReputationPenalized); - - this.nodeStatistics.setPredefined(true); - Assert.assertTrue(this.nodeStatistics.isPredefined()); - - this.nodeStatistics.setPersistedReputation(10000); - this.nodeStatistics.nodeDisconnectedRemote(Protocol.ReasonCode.INCOMPATIBLE_VERSION); - isReputationPenalized = this.nodeStatistics.isReputationPenalized(); - Assert.assertTrue(isReputationPenalized); - - Field field = this.nodeStatistics.getClass().getDeclaredField("firstDisconnectedTime"); - field.setAccessible(true); - field.set(this.nodeStatistics, System.currentTimeMillis() - 60 * 60 * 1000L - 1); - isReputationPenalized = this.nodeStatistics.isReputationPenalized(); - Assert.assertFalse(isReputationPenalized); - reasonCode = this.nodeStatistics.getDisconnectReason(); - Assert.assertEquals(Protocol.ReasonCode.UNKNOWN, reasonCode); - - String str = this.nodeStatistics.toString(); - //System.out.println(str); - Assert.assertNotNull(str); - - this.nodeStatistics.nodeIsHaveDataTransfer(); - this.nodeStatistics.resetTcpFlow(); - this.nodeStatistics.discoverMessageLatency.add(10); - this.nodeStatistics.discoverMessageLatency.add(20); - long avg = this.nodeStatistics.discoverMessageLatency.getAvg(); - Assert.assertEquals(15, avg); - - } - - @Test - public void testMessage() { - MessageStatistics statistics = this.nodeStatistics.messageStatistics; - statistics.addUdpInMessage(UdpMessageTypeEnum.DISCOVER_FIND_NODE); - statistics.addUdpOutMessage(UdpMessageTypeEnum.DISCOVER_NEIGHBORS); - statistics.addUdpInMessage(UdpMessageTypeEnum.DISCOVER_NEIGHBORS); - statistics.addUdpOutMessage(UdpMessageTypeEnum.DISCOVER_FIND_NODE); - Assert.assertEquals(1, statistics.discoverInFindNode.getTotalCount()); - long inFindNodeCount = statistics.discoverInFindNode.getTotalCount(); - long outNeighbours = statistics.discoverOutNeighbours.getTotalCount(); - Assert.assertEquals(inFindNodeCount, outNeighbours); - - PongMessage pongMessage = new PongMessage(MessageTypes.P2P_PONG.asByte(), Hex.decode("C0")); - pongMessage.getData(); - String pongStr = pongMessage.toString(); - Assert.assertNotNull(pongStr); - statistics.addTcpInMessage(pongMessage); - statistics.addTcpOutMessage(pongMessage); - Assert.assertEquals(1, statistics.p2pInPong.getTotalCount()); - - DisconnectMessage disconnectMessage = new DisconnectMessage(Protocol.ReasonCode.TOO_MANY_PEERS); - Assert.assertEquals(Protocol.ReasonCode.TOO_MANY_PEERS, disconnectMessage.getReasonCode()); - statistics.addTcpInMessage(disconnectMessage); - statistics.addTcpOutMessage(disconnectMessage); - Assert.assertEquals(1, statistics.p2pOutDisconnect.getTotalCount()); - - SyncBlockChainMessage syncBlockChainMessage = new SyncBlockChainMessage(new ArrayList<>()); - String syncBlockChainStr = syncBlockChainMessage.toString(); - Assert.assertNotNull(syncBlockChainStr); - statistics.addTcpInMessage(syncBlockChainMessage); - statistics.addTcpOutMessage(syncBlockChainMessage); - Assert.assertEquals(1, statistics.tronInSyncBlockChain.getTotalCount()); - - ChainInventoryMessage chainInventoryMessage = new ChainInventoryMessage(new ArrayList<>(), 0L); - String chainInventoryMessageStr = chainInventoryMessage.toString(); - Assert.assertNotNull(chainInventoryMessageStr); - statistics.addTcpInMessage(chainInventoryMessage); - statistics.addTcpOutMessage(chainInventoryMessage); - Assert.assertEquals(1, statistics.tronOutBlockChainInventory.getTotalCount()); - - InventoryMessage invMsgTrx = - new InventoryMessage(new ArrayList<>(), Protocol.Inventory.InventoryType.TRX); - String inventoryMessageStr = invMsgTrx.toString(); - Assert.assertNotNull(inventoryMessageStr); - statistics.addTcpInMessage(invMsgTrx); - statistics.addTcpOutMessage(invMsgTrx); - InventoryMessage invMsgBlock = - new InventoryMessage(new ArrayList<>(), Protocol.Inventory.InventoryType.BLOCK); - MessageTypes invType = invMsgBlock.getInvMessageType(); - Assert.assertEquals(MessageTypes.BLOCK, invType); - statistics.addTcpInMessage(invMsgBlock); - statistics.addTcpOutMessage(invMsgBlock); - Assert.assertEquals(1, statistics.tronInBlockInventory.getTotalCount()); - - FetchInvDataMessage fetchInvDataTrx = - new FetchInvDataMessage(new ArrayList<>(), Protocol.Inventory.InventoryType.TRX); - statistics.addTcpInMessage(fetchInvDataTrx); - statistics.addTcpOutMessage(fetchInvDataTrx); - FetchInvDataMessage fetchInvDataBlock = - new FetchInvDataMessage(new ArrayList<>(), Protocol.Inventory.InventoryType.BLOCK); - statistics.addTcpInMessage(fetchInvDataBlock); - statistics.addTcpOutMessage(fetchInvDataBlock); - Assert.assertEquals(1, statistics.tronInTrxFetchInvData.getTotalCount()); - - TransactionsMessage transactionsMessage = - new TransactionsMessage(new LinkedList<>()); - statistics.addTcpInMessage(transactionsMessage); - statistics.addTcpOutMessage(transactionsMessage); - Assert.assertEquals(1, statistics.tronInTrxs.getTotalCount()); - - BlockCapsule blockCapsule = new BlockCapsule(1, Sha256Hash.ZERO_HASH, - System.currentTimeMillis(), Sha256Hash.ZERO_HASH.getByteString()); - BlockMessage blockMessage = new BlockMessage(blockCapsule); - statistics.addTcpInMessage(blockMessage); - statistics.addTcpOutMessage(blockMessage); - long inBlockCount = statistics.tronInBlock.getTotalCount(); - Assert.assertEquals(1, inBlockCount); - } -} diff --git a/framework/src/test/java/org/tron/common/overlay/discover/node/statistics/ReputationTest.java b/framework/src/test/java/org/tron/common/overlay/discover/node/statistics/ReputationTest.java deleted file mode 100644 index cee5d1d76dd..00000000000 --- a/framework/src/test/java/org/tron/common/overlay/discover/node/statistics/ReputationTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.tron.common.overlay.discover.node.statistics; - -import org.junit.Assert; -import org.junit.Test; - -public class ReputationTest { - - NodeStatistics nodeStatistics = new NodeStatistics(); - Reputation reputation = new Reputation(nodeStatistics); - - @Test - public void testGetScore() { - Assert.assertEquals(0, reputation.getScore()); - - nodeStatistics.messageStatistics.discoverInPong.add(3); - Assert.assertEquals(100, reputation.getScore()); - - nodeStatistics.messageStatistics.discoverOutPing.add(3); - Assert.assertEquals(200, reputation.getScore()); - - nodeStatistics.messageStatistics.discoverOutPing.add(1); - Assert.assertEquals(150, reputation.getScore()); - - nodeStatistics.tcpFlow.add(10240 * 5); - Assert.assertEquals(155, reputation.getScore()); - - nodeStatistics.discoverMessageLatency.add(100); - Assert.assertEquals(165, reputation.getScore()); - - nodeStatistics.notifyDisconnect(); - Assert.assertEquals(155, reputation.getScore()); - } -} diff --git a/framework/src/test/java/org/tron/common/overlay/discover/table/NodeEntryTest.java b/framework/src/test/java/org/tron/common/overlay/discover/table/NodeEntryTest.java deleted file mode 100644 index f30b02d3953..00000000000 --- a/framework/src/test/java/org/tron/common/overlay/discover/table/NodeEntryTest.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.tron.common.overlay.discover.table; - -import org.junit.Assert; -import org.junit.Test; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.utils.ByteArray; - -public class NodeEntryTest { - - @Test - public void test() throws InterruptedException { - Node node1 = Node.instanceOf("127.0.0.1:10001"); - NodeEntry nodeEntry = new NodeEntry(Node.getNodeId(), node1); - - long lastModified = nodeEntry.getModified(); - Thread.sleep(1); - nodeEntry.touch(); - long nowModified = nodeEntry.getModified(); - Assert.assertNotEquals(lastModified, nowModified); - - Node node2 = Node.instanceOf("127.0.0.1:10002"); - NodeEntry nodeEntry2 = new NodeEntry(Node.getNodeId(), node2); - boolean isDif = nodeEntry.equals(nodeEntry2); - Assert.assertTrue(isDif); - } - - @Test - public void testDistance() { - byte[] randomId = Node.getNodeId(); - String hexRandomIdStr = ByteArray.toHexString(randomId); - Assert.assertEquals(128, hexRandomIdStr.length()); - - byte[] nodeId1 = ByteArray.fromHexString( - "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000"); - byte[] nodeId2 = ByteArray.fromHexString( - "a000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000"); - Assert.assertEquals(256, NodeEntry.distance(nodeId1, nodeId2)); - - byte[] nodeId3 = ByteArray.fromHexString( - "0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000000"); - Assert.assertEquals(1, NodeEntry.distance(nodeId1, nodeId3)); - - byte[] nodeId4 = ByteArray.fromHexString( - "0000000000000000000000000000000000000000000000000000000000000000" - + "8000000000000000000000000000000000000000000000000000000000000000"); - Assert.assertEquals(0, NodeEntry.distance(nodeId1, nodeId4)); // => 0 - - byte[] nodeId5 = ByteArray.fromHexString( - "0000000000000000000000000000000000000000000000000000000000000000" - + "4000000000000000000000000000000000000000000000000000000000000000"); - Assert.assertEquals(-1, NodeEntry.distance(nodeId1, nodeId5)); // => 0 - - byte[] nodeId6 = ByteArray.fromHexString( - "0000000000000000000000000000000000000000000000000000000000000000" - + "2000000000000000000000000000000000000000000000000000000000000000"); - Assert.assertEquals(-2, NodeEntry.distance(nodeId1, nodeId6)); // => 0 - - byte[] nodeId7 = ByteArray.fromHexString( - "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000001"); - Assert.assertEquals(-255, NodeEntry.distance(nodeId1, nodeId7)); // => 0 - - Assert.assertEquals(-256, NodeEntry.distance(nodeId1, nodeId1)); // => 0 - } - -} diff --git a/framework/src/test/java/org/tron/common/overlay/discover/table/NodeTableTest.java b/framework/src/test/java/org/tron/common/overlay/discover/table/NodeTableTest.java deleted file mode 100644 index ed43aea43a2..00000000000 --- a/framework/src/test/java/org/tron/common/overlay/discover/table/NodeTableTest.java +++ /dev/null @@ -1,206 +0,0 @@ -package org.tron.common.overlay.discover.table; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.Assert; -import org.tron.common.overlay.discover.node.Node; - - -public class NodeTableTest { - - private static final Logger logger = LoggerFactory.getLogger("Test"); - private Node homeNode; - private NodeTable nodeTable; - private String[] ips; - private List ids; - - @Test - public void test() { - Node node1 = Node.instanceOf("127.0.0.5:10002"); - - NodeTable table = new NodeTable(node1); - Node nodeTemp = table.getNode(); - Assert.assertEquals(10002, nodeTemp.getPort()); - Assert.assertEquals(0, table.getNodesCount()); - Assert.assertEquals(0, table.getBucketsCount()); - - Node node2 = Node.instanceOf("127.0.0.1:10003"); - Node node3 = Node.instanceOf("127.0.0.2:10004"); - table.addNode(node2); - table.addNode(node3); - int bucketsCount = table.getBucketsCount(); - int nodeCount = table.getNodesCount(); - Assert.assertEquals(2, nodeCount); - Assert.assertTrue(bucketsCount > 0); - - boolean isExist = table.contains(node2); - table.touchNode(node2); - Assert.assertTrue(isExist); - - byte[] targetId = Node.getNodeId(); - List nodeList = table.getClosestNodes(targetId); - Assert.assertTrue(nodeList.isEmpty()); - //Assert.assertTrue(true); - } - - /** - * init nodes for test. - */ - @Before - public void init() { - ids = new ArrayList(); - for (int i = 0; i < KademliaOptions.BUCKET_SIZE + 1; i++) { - byte[] id = new byte[64]; - id[0] = 17; - id[1] = 16; - if (i < 10) { - id[63] = (byte) i; - } else { - id[62] = 1; - id[63] = (byte) (i - 10); - } - ids.add(id); - } - - ips = new String[KademliaOptions.BUCKET_SIZE + 1]; - byte[] homeId = new byte[64]; - homeNode = new Node(homeId, "127.0.0.1", 18888, 18888); - nodeTable = new NodeTable(homeNode); - ips[0] = "127.0.0.2"; - ips[1] = "127.0.0.3"; - ips[2] = "127.0.0.4"; - ips[3] = "127.0.0.5"; - ips[4] = "127.0.0.6"; - ips[5] = "127.0.0.7"; - ips[6] = "127.0.0.8"; - ips[7] = "127.0.0.9"; - ips[8] = "127.0.0.10"; - ips[9] = "127.0.0.11"; - ips[10] = "127.0.0.12"; - ips[11] = "127.0.0.13"; - ips[12] = "127.0.0.14"; - ips[13] = "127.0.0.15"; - ips[14] = "127.0.0.16"; - ips[15] = "127.0.0.17"; - ips[16] = "127.0.0.18"; - } - - @Test - public void addNodeTest() { - Node node = new Node(ids.get(0), ips[0], 18888, 18888); - Assert.assertEquals(0, nodeTable.getNodesCount()); - nodeTable.addNode(node); - Assert.assertEquals(1, nodeTable.getNodesCount()); - Assert.assertTrue(nodeTable.contains(node)); - } - - @Test - public void addDupNodeTest() throws Exception { - Node node = new Node(ids.get(0), ips[0], 18888, 18888); - nodeTable.addNode(node); - long firstTouchTime = nodeTable.getAllNodes().get(0).getModified(); - TimeUnit.MILLISECONDS.sleep(20); - nodeTable.addNode(node); - long lastTouchTime = nodeTable.getAllNodes().get(0).getModified(); - Assert.assertTrue(lastTouchTime > firstTouchTime); - Assert.assertEquals(1, nodeTable.getNodesCount()); - } - - @Test - public void addNode_bucketFullTest() throws Exception { - for (int i = 0; i < KademliaOptions.BUCKET_SIZE; i++) { - TimeUnit.MILLISECONDS.sleep(10); - addNode(new Node(ids.get(i), ips[i], 18888, 18888)); - } - Node lastSeen = nodeTable.addNode(new Node(ids.get(16), ips[16], 18888, 18888)); - Assert.assertTrue(null != lastSeen); - Assert.assertEquals(ips[15], lastSeen.getHost()); - } - - public void addNode(Node n) { - nodeTable.addNode(n); - } - - @Test - public void dropNodeTest() { - Node node = new Node(ids.get(0), ips[0], 18888, 18888); - nodeTable.addNode(node); - Assert.assertTrue(nodeTable.contains(node)); - nodeTable.dropNode(node); - Assert.assertTrue(!nodeTable.contains(node)); - nodeTable.addNode(node); - nodeTable.dropNode(new Node(ids.get(1), ips[0], 10000, 10000)); - Assert.assertTrue(!nodeTable.contains(node)); - } - - @Test - public void getBucketsCountTest() { - Assert.assertEquals(0, nodeTable.getBucketsCount()); - Node node = new Node(ids.get(0), ips[0], 18888, 18888); - nodeTable.addNode(node); - Assert.assertEquals(1, nodeTable.getBucketsCount()); - } - - @Test - public void touchNodeTest() throws Exception { - Node node = new Node(ids.get(0), ips[0], 18888, 18888); - nodeTable.addNode(node); - long firstTouchTime = nodeTable.getAllNodes().get(0).getModified(); - TimeUnit.MILLISECONDS.sleep(10); - nodeTable.touchNode(node); - long lastTouchTime = nodeTable.getAllNodes().get(0).getModified(); - Assert.assertTrue(firstTouchTime < lastTouchTime); - } - - @Test - public void containsTest() { - Node node = new Node(ids.get(0), ips[0], 18888, 18888); - Assert.assertTrue(!nodeTable.contains(node)); - nodeTable.addNode(node); - Assert.assertTrue(nodeTable.contains(node)); - } - - @Test - public void getBuckIdTest() { - Node node = new Node(ids.get(0), ips[0], 18888, 18888); //id: 11100...000 - nodeTable.addNode(node); - NodeEntry nodeEntry = new NodeEntry(homeNode.getId(), node); - Assert.assertEquals(252, nodeTable.getBucketId(nodeEntry)); - } - - @Test - public void getClosestNodes_nodesMoreThanBucketCapacity() throws Exception { - byte[] bytes = new byte[64]; - bytes[0] = 15; - Node nearNode = new Node(bytes, "127.0.0.19", 18888, 18888); - bytes[0] = 70; - Node farNode = new Node(bytes, "127.0.0.20", 18888, 18888); - nodeTable.addNode(nearNode); - nodeTable.addNode(farNode); - for (int i = 0; i < KademliaOptions.BUCKET_SIZE - 1; i++) { - //To control totally 17 nodes, however closest's capacity is 16 - nodeTable.addNode(new Node(ids.get(i), ips[i], 18888, 18888)); - TimeUnit.MILLISECONDS.sleep(10); - } - Assert.assertTrue(nodeTable.getBucketsCount() > 1); - //3 buckets, nearnode's distance is 252, far's is 255, others' are 253 - List closest = nodeTable.getClosestNodes(homeNode.getId()); - Assert.assertTrue(closest.contains(nearNode)); - //the farest node should be excluded - } - - @Test - public void getClosestNodes_isDiscoverNode() { - Node node = new Node(ids.get(0), ips[0], 18888); - //This constructor builds a node with isFakeNodeId = true - nodeTable.addNode(node); - List closest = nodeTable.getClosestNodes(homeNode.getId()); - Assert.assertTrue(closest.isEmpty()); - } - -} diff --git a/framework/src/test/java/org/tron/common/overlay/discover/table/TimeComparatorTest.java b/framework/src/test/java/org/tron/common/overlay/discover/table/TimeComparatorTest.java deleted file mode 100644 index b1c3a82f50e..00000000000 --- a/framework/src/test/java/org/tron/common/overlay/discover/table/TimeComparatorTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.tron.common.overlay.discover.table; - -import org.junit.Assert; -import org.junit.Test; -import org.tron.common.overlay.discover.node.Node; - -public class TimeComparatorTest { - - @Test - public void test() throws InterruptedException { - Node node1 = Node.instanceOf("127.0.0.1:10001"); - NodeEntry ne1 = new NodeEntry(Node.getNodeId(), node1); - Thread.sleep(1); - Node node2 = Node.instanceOf("127.0.0.1:10002"); - NodeEntry ne2 = new NodeEntry(Node.getNodeId(), node2); - TimeComparator tc = new TimeComparator(); - int result = tc.compare(ne1, ne2); - Assert.assertEquals(1, result); - - } -} diff --git a/framework/src/test/java/org/tron/common/utils/JsonUtilTest.java b/framework/src/test/java/org/tron/common/utils/JsonUtilTest.java index ae006f21521..9a4efb722e3 100644 --- a/framework/src/test/java/org/tron/common/utils/JsonUtilTest.java +++ b/framework/src/test/java/org/tron/common/utils/JsonUtilTest.java @@ -1,31 +1,35 @@ package org.tron.common.utils; -import java.util.ArrayList; -import java.util.List; +import lombok.Data; import org.junit.Assert; import org.junit.Test; -import org.tron.common.overlay.discover.node.DBNode; -import org.tron.common.overlay.discover.node.DBNodeStats; -import org.tron.common.overlay.discover.node.Node; public class JsonUtilTest { + @Data + public static class A { + private String key; + private int value; + + public A() {} + + public A(String key, int value) { + this.key = key; + this.value = value; + } + } + @Test public void test() { - DBNode dbNode = new DBNode(); - DBNodeStats dbNodeStats = new DBNodeStats(Node.getNodeId(), "1.0.0.1", 1000, 100); - List nodes = new ArrayList(); - nodes.add(dbNodeStats); - dbNode.setNodes(nodes); - - String jsonString = JsonUtil.obj2Json(dbNode); + A a1 = new A(); + a1.setKey("abc"); + a1.setValue(100); - DBNode dbNode2 = JsonUtil.json2Obj(jsonString, DBNode.class); + String jsonString = JsonUtil.obj2Json(a1); - dbNodeStats = dbNode2.getNodes().get(0); + A a2 = JsonUtil.json2Obj(jsonString, A.class); - Assert.assertEquals(dbNodeStats.getHost(), "1.0.0.1"); - Assert.assertEquals(dbNodeStats.getPort(), 1000); - Assert.assertEquals(dbNodeStats.getReputation(), 100); + Assert.assertEquals(a2.getKey(), "abc"); + Assert.assertEquals(a2.getValue(), 100); } } diff --git a/framework/src/test/java/org/tron/core/net/BaseNet.java b/framework/src/test/java/org/tron/core/net/BaseNet.java index cfd71080e4a..bb7ca85ef7f 100644 --- a/framework/src/test/java/org/tron/core/net/BaseNet.java +++ b/framework/src/test/java/org/tron/core/net/BaseNet.java @@ -113,7 +113,7 @@ public void destroy() { Collection peerConnections = ReflectUtils .invokeMethod(tronNetDelegate, "getActivePeer"); for (PeerConnection peer : peerConnections) { - peer.close(); + peer.getChannel().close(); } context.destroy(); diff --git a/framework/src/test/java/org/tron/core/net/BaseNetTest.java b/framework/src/test/java/org/tron/core/net/BaseNetTest.java index fee2695a80a..fd0847c1f08 100644 --- a/framework/src/test/java/org/tron/core/net/BaseNetTest.java +++ b/framework/src/test/java/org/tron/core/net/BaseNetTest.java @@ -9,10 +9,8 @@ public class BaseNetTest extends BaseNet { @Test - public void test() throws Exception { + public void test() { new NodeInfoServiceTest(context).test(); - new UdpTest(context).test(); - new TcpTest(context).test(); new DelegationServiceTest(context).test(); } } diff --git a/framework/src/test/java/org/tron/core/net/DisconnectMessageTest.java b/framework/src/test/java/org/tron/core/net/DisconnectMessageTest.java index 0155e5e5356..8ba255ccf08 100644 --- a/framework/src/test/java/org/tron/core/net/DisconnectMessageTest.java +++ b/framework/src/test/java/org/tron/core/net/DisconnectMessageTest.java @@ -4,13 +4,11 @@ import org.tron.protos.Protocol.DisconnectMessageOrBuilder; public class DisconnectMessageTest extends com.google.protobuf.GeneratedMessageV3 implements - // @@protoc_insertion_point(message_implements:protocol.DisconnectMessage) DisconnectMessageOrBuilder { public static final int REASON_FIELD_NUMBER = 1; public static final int NAME_FIELD_NUMBER = 2; private static final long serialVersionUID = 0L; - // @@protoc_insertion_point(class_scope:protocol.DisconnectMessage) private static final DisconnectMessageTest DEFAULT_INSTANCE; private static final com.google.protobuf.Parser PARSER = new com.google.protobuf.AbstractParser() { diff --git a/framework/src/test/java/org/tron/core/net/MessageTest.java b/framework/src/test/java/org/tron/core/net/MessageTest.java index 6d344dd61bc..0400d16b669 100644 --- a/framework/src/test/java/org/tron/core/net/MessageTest.java +++ b/framework/src/test/java/org/tron/core/net/MessageTest.java @@ -2,9 +2,9 @@ import org.junit.Assert; import org.junit.Test; -import org.tron.common.overlay.message.DisconnectMessage; import org.tron.core.exception.P2pException; import org.tron.core.net.message.MessageTypes; +import org.tron.core.net.message.base.DisconnectMessage; import org.tron.protos.Protocol.ReasonCode; public class MessageTest { diff --git a/framework/src/test/java/org/tron/core/net/TcpTest.java b/framework/src/test/java/org/tron/core/net/TcpTest.java deleted file mode 100644 index 5884efffd91..00000000000 --- a/framework/src/test/java/org/tron/core/net/TcpTest.java +++ /dev/null @@ -1,294 +0,0 @@ -package org.tron.core.net; - -import static org.tron.core.net.message.MessageTypes.P2P_DISCONNECT; -import static org.tron.core.net.message.MessageTypes.P2P_HELLO; -import static org.tron.protos.Protocol.ReasonCode.DUPLICATE_PEER; -import static org.tron.protos.Protocol.ReasonCode.FORKED; -import static org.tron.protos.Protocol.ReasonCode.INCOMPATIBLE_CHAIN; -import static org.tron.protos.Protocol.ReasonCode.INCOMPATIBLE_VERSION; -import static org.tron.protos.Protocol.ReasonCode.LIGHT_NODE_SYNC_FAIL; - -import com.google.common.cache.CacheBuilder; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.ByteToMessageDecoder; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.ArrayUtils; -import org.junit.Assert; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.overlay.discover.node.NodeManager; -import org.tron.common.overlay.message.DisconnectMessage; -import org.tron.common.overlay.message.HelloMessage; -import org.tron.common.overlay.message.Message; -import org.tron.common.overlay.message.P2pMessage; -import org.tron.common.overlay.message.P2pMessageFactory; -import org.tron.common.overlay.server.ChannelManager; -import org.tron.common.overlay.server.SyncPool; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.ReflectUtils; -import org.tron.core.ChainBaseManager; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.BlockCapsule.BlockId; -import org.tron.core.capsule.BytesCapsule; -import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; -import org.tron.core.net.message.BlockMessage; -import org.tron.core.net.peer.PeerConnection; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Block; - -@Slf4j -public class TcpTest { - - Node node = Node.instanceOf("127.0.0.1:" + Args.getInstance().getNodeListenPort()); - private ChannelManager channelManager; - private Manager manager; - private ChainBaseManager chainBaseManager; - private SyncPool pool; - private TronNetDelegate tronNetDelegate; - private int tryTimes = 10; - private int sleepTime = 1000; - private boolean finish = false; - - public TcpTest(TronApplicationContext context) { - channelManager = context.getBean(ChannelManager.class); - manager = context.getBean(Manager.class); - chainBaseManager = context.getBean(ChainBaseManager.class); - pool = context.getBean(SyncPool.class); - tronNetDelegate = context.getBean(TronNetDelegate.class); - } - - public void normalTest() throws InterruptedException { - Channel channel = BaseNet.connect(new HandshakeHandler(TestType.normal)); - HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), chainBaseManager); - sendMessage(channel, message); - validResultCloseConnect(channel); - } - - public void errorGenesisBlockIdTest() throws InterruptedException { - Channel channel = BaseNet.connect(new HandshakeHandler(TestType.errorGenesisBlock)); - HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), chainBaseManager); - Protocol.HelloMessage.BlockId genesisBlockId = Protocol.HelloMessage.BlockId.newBuilder() - .setHash(new BlockId().getByteString()) - .setNumber(new BlockId().getNum()) - .build(); - message.setHelloMessage( - message.getHelloMessage().toBuilder().setGenesisBlockId(genesisBlockId).build()); - sendMessage(channel, message); - validResultCloseConnect(channel); - } - - public void errorVersionTest() throws InterruptedException { - Channel channel = BaseNet.connect(new HandshakeHandler(TestType.errorVersion)); - Args.getInstance().setNodeP2pVersion(1); - HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), chainBaseManager); - Args.getInstance().setNodeP2pVersion(2); - sendMessage(channel, message); - validResultCloseConnect(channel); - } - - public void errorSolidBlockIdTest() throws InterruptedException { - Channel channel = BaseNet.connect(new HandshakeHandler(TestType.errorSolid)); - HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), chainBaseManager); - Protocol.HelloMessage.BlockId sBlockId = Protocol.HelloMessage.BlockId.newBuilder() - .setHash(new BlockId().getByteString()) - .setNumber(new BlockId().getNum()) - .build(); - message.setHelloMessage( - message.getHelloMessage().toBuilder().setSolidBlockId(sBlockId).build()); - sendMessage(channel, message); - validResultCloseConnect(channel); - } - - public void repeatConnectTest() throws InterruptedException { - Channel channel = BaseNet.connect(new HandshakeHandler(TestType.normal)); - HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), chainBaseManager); - sendMessage(channel, message); - validResultUnCloseConnect(); - Channel repeatChannel = BaseNet.connect(new HandshakeHandler(TestType.repeatConnect)); - sendMessage(repeatChannel, message); - validResultCloseConnect(repeatChannel); - clearConnect(channel); - } - - public void unHandshakeTest() throws InterruptedException { - List beforeActivePeers = - ReflectUtils.getFieldValue(pool, "activePeers"); - int beforeSize = beforeActivePeers.size(); - Channel channel = BaseNet.connect(new HandshakeHandler(TestType.normal)); - BlockMessage message = new BlockMessage(new BlockCapsule(Block.getDefaultInstance())); - sendMessage(channel, message); - List afterActivePeers = - ReflectUtils.getFieldValue(pool, "activePeers"); - int afterSize = afterActivePeers.size(); - Assert.assertEquals(beforeSize, afterSize); - clearConnect(channel); - } - - public void errorMsgTest() throws InterruptedException { - Channel channel = BaseNet.connect(new HandshakeHandler(TestType.normal)); - HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), chainBaseManager); - sendMessage(channel, message); - validResultUnCloseConnect(); - List beforeActivePeers = - ReflectUtils.getFieldValue(pool, "activePeers"); - int beforeSize = beforeActivePeers.size(); - logger.info("beforeSize : {}", beforeSize); - channel.writeAndFlush( - Unpooled.wrappedBuffer(ArrayUtils.add("nihao".getBytes(), 0, (byte) 1))) - .addListener((ChannelFutureListener) future -> { - if (future.isSuccess()) { - logger.info("send msg success"); - } else { - logger.error("send msg fail", future.cause()); - } - }); - Thread.sleep(2000); - List afterActivePeers = - ReflectUtils.getFieldValue(pool, "activePeers"); - int afterSize = afterActivePeers.size(); - logger.info("afterSize : {}", afterSize); - Assert.assertEquals(beforeSize, afterSize + 1); - clearConnect(channel); - } - - public void errorLowestBlockNumTest() throws InterruptedException { - Channel channel = BaseNet.connect(new HandshakeHandler(TestType.errorLowestBlockNum)); - HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), chainBaseManager); - message.setHelloMessage( - message.getHelloMessage().toBuilder().setNodeType(1).setLowestBlockNum(100).build()); - sendMessage(channel, message); - validResultCloseConnect(channel); - } - - private void sendMessage(Channel channel, Message message) { - channel.writeAndFlush(message.getSendData()) - .addListener((ChannelFutureListener) future -> { - if (future.isSuccess()) { - logger.info("send msg success"); - } else { - logger.error("send msg fail", future.cause()); - } - }); - } - - private void validResultCloseConnect(Channel channel) throws InterruptedException { - int trys = 0; - while (!finish && ++trys < tryTimes) { - Thread.sleep(sleepTime); - } - Assert.assertEquals(finish, true); - finish = false; - channel.close(); - Thread.sleep(sleepTime); - Collection peerConnections = ReflectUtils - .invokeMethod(tronNetDelegate, "getActivePeer"); - for (PeerConnection peer : peerConnections) { - peer.close(); - } - ReflectUtils.setFieldValue(channelManager, "recentlyDisconnected", - CacheBuilder.newBuilder().maximumSize(1000) - .expireAfterWrite(30, TimeUnit.SECONDS).recordStats().build()); - } - - private void validResultUnCloseConnect() throws InterruptedException { - int n = 0; - while (!finish && ++n < tryTimes) { - Thread.sleep(sleepTime); - } - Assert.assertEquals(finish, true); - finish = false; - } - - private void clearConnect(Channel channel) throws InterruptedException { - channel.close(); - Thread.sleep(sleepTime); - Collection peerConnections = ReflectUtils - .invokeMethod(tronNetDelegate, "getActivePeer"); - for (PeerConnection peer : peerConnections) { - peer.close(); - } - ReflectUtils.setFieldValue(channelManager, "recentlyDisconnected", - CacheBuilder.newBuilder().maximumSize(1000) - .expireAfterWrite(30, TimeUnit.SECONDS).recordStats().build()); - } - - public void test() throws InterruptedException { - logger.info("begin normal test "); - normalTest(); - logger.info("begin errorGenesisBlockId test "); - errorGenesisBlockIdTest(); - logger.info("begin errorVersion test "); - errorVersionTest(); - logger.info("begin errorSolidBlockId test "); - errorSolidBlockIdTest(); - logger.info("begin repeatConnect test"); - repeatConnectTest(); - logger.info("begin unHandshake test"); - unHandshakeTest(); - logger.info("begin errorMsg test"); - errorLowestBlockNumTest(); - logger.info("begin errorLowestBlockNum test"); - errorMsgTest(); - } - - private enum TestType { - normal, errorGenesisBlock, errorVersion, errorSolid, - repeatConnect, errorLowestBlockNum - } - - private class HandshakeHandler extends ByteToMessageDecoder { - - private P2pMessageFactory messageFactory = new P2pMessageFactory(); - - private TestType testType; - - public HandshakeHandler(TestType testType) { - this.testType = testType; - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List out) - throws Exception { - byte[] encoded = new byte[buffer.readableBytes()]; - buffer.readBytes(encoded); - P2pMessage msg = messageFactory.create(encoded); - switch (testType) { - case normal: - Assert.assertEquals(msg.getType(), P2P_HELLO); - break; - case errorGenesisBlock: - Assert.assertEquals(msg.getType(), P2P_DISCONNECT); - Assert.assertEquals(((DisconnectMessage) msg).getReasonCode(), INCOMPATIBLE_CHAIN); - break; - case errorVersion: - Assert.assertEquals(msg.getType(), P2P_DISCONNECT); - Assert.assertEquals(((DisconnectMessage) msg).getReasonCode(), INCOMPATIBLE_VERSION); - break; - case errorSolid: - Assert.assertEquals(msg.getType(), P2P_DISCONNECT); - Assert.assertEquals(((DisconnectMessage) msg).getReasonCode(), FORKED); - break; - case repeatConnect: - Assert.assertEquals(msg.getType(), P2P_DISCONNECT); - Assert.assertEquals(((DisconnectMessage) msg).getReasonCode(), DUPLICATE_PEER); - break; - case errorLowestBlockNum: - Assert.assertEquals(msg.getType(), P2P_DISCONNECT); - Assert.assertEquals(((DisconnectMessage) msg).getReasonCode(), LIGHT_NODE_SYNC_FAIL); - break; - default: - break; - } - - finish = true; - } - } -} diff --git a/framework/src/test/java/org/tron/core/net/UdpTest.java b/framework/src/test/java/org/tron/core/net/UdpTest.java deleted file mode 100644 index 6d90e4e748a..00000000000 --- a/framework/src/test/java/org/tron/core/net/UdpTest.java +++ /dev/null @@ -1,127 +0,0 @@ -package org.tron.core.net; - -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.util.Arrays; -import java.util.List; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.collections.Lists; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.net.udp.message.Message; -import org.tron.common.net.udp.message.discover.FindNodeMessage; -import org.tron.common.net.udp.message.discover.NeighborsMessage; -import org.tron.common.net.udp.message.discover.PingMessage; -import org.tron.common.net.udp.message.discover.PongMessage; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.overlay.discover.node.NodeManager; -import org.tron.core.config.args.Args; - -@Slf4j -public class UdpTest { - - private NodeManager nodeManager; - private int port = Args.getInstance().getNodeListenPort(); - //private volatile boolean finishFlag = false; - //private long timeOut = 30_000; - - public UdpTest(TronApplicationContext context) { - nodeManager = context.getBean(NodeManager.class); - } - - public void test() throws Exception { - /* - Thread thread = new Thread(() -> { - try { - discover(); - } catch (Exception e) { - logger.info("Discover test failed.", e); - } - }); - thread.start(); - - long time = System.currentTimeMillis(); - while (!finishFlag && System.currentTimeMillis() - time < timeOut) { - Thread.sleep(1000); - } - if (!finishFlag) { - thread.interrupt(); - Assert.assertTrue(false); - } - */ - } - - public void discover() throws Exception { - - InetAddress server = InetAddress.getByName("127.0.0.1"); - - Node from = Node.instanceOf("127.0.0.1:10002"); - Node peer1 = Node.instanceOf("127.0.0.1:10003"); - Node peer2 = Node.instanceOf("127.0.0.1:10004"); - - Assert.assertTrue(!nodeManager.hasNodeHandler(peer1)); - Assert.assertTrue(!nodeManager.hasNodeHandler(peer2)); - Assert.assertTrue(nodeManager.getTable().getAllNodes().isEmpty()); - - PingMessage pingMessage = new PingMessage(from, nodeManager.getPublicHomeNode()); - DatagramPacket pingPacket = new DatagramPacket(pingMessage.getSendData(), - pingMessage.getSendData().length, server, port); - - FindNodeMessage findNodeMessage = new FindNodeMessage(from, Node.getNodeId()); - DatagramPacket findNodePacket = new DatagramPacket(findNodeMessage.getSendData(), - findNodeMessage.getSendData().length, server, port); - - DatagramSocket socket = new DatagramSocket(); - - // send ping msg - socket.send(pingPacket); - byte[] data = new byte[1024]; - DatagramPacket packet = new DatagramPacket(data, data.length); - - boolean pingFlag = false; - boolean pongFlag = false; - boolean findNodeFlag = false; - boolean neighborsFlag = false; - while (true) { - socket.receive(packet); - byte[] bytes = Arrays.copyOfRange(data, 0, packet.getLength()); - Message msg = Message.parse(bytes); - Assert.assertTrue( - Arrays.equals(msg.getFrom().getId(), nodeManager.getPublicHomeNode().getId())); - if (!pingFlag) { - pingFlag = true; - Assert.assertTrue(msg instanceof PingMessage); - Assert.assertTrue(Arrays.equals(((PingMessage) msg).getTo().getId(), from.getId())); - PongMessage pongMessage = new PongMessage(from); - DatagramPacket pongPacket = new DatagramPacket(pongMessage.getSendData(), - pongMessage.getSendData().length, server, port); - socket.send(pongPacket); - } else if (!pongFlag) { - pongFlag = true; - Assert.assertTrue(msg instanceof PongMessage); - } else if (!findNodeFlag) { - findNodeFlag = true; - Assert.assertTrue(msg instanceof FindNodeMessage); - List peers = Lists.newArrayList(peer1, peer2); - NeighborsMessage neighborsMessage = new NeighborsMessage(from, peers, msg.getTimestamp()); - DatagramPacket neighborsPacket = new DatagramPacket(neighborsMessage.getSendData(), - neighborsMessage.getSendData().length, server, port); - socket.send(neighborsPacket); - socket.send(findNodePacket); - } else if (!neighborsFlag) { - Assert.assertTrue(msg instanceof NeighborsMessage); - break; - } - } - - Assert.assertTrue(nodeManager.hasNodeHandler(peer1)); - Assert.assertTrue(nodeManager.hasNodeHandler(peer2)); - Assert.assertTrue(nodeManager.getTable().getAllNodes().size() == 1); - - socket.close(); - - //finishFlag = true; - } -} - diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java index f5edf091a13..5b2abfd0705 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java @@ -7,7 +7,6 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.testng.collections.Lists; import org.tron.common.application.TronApplicationContext; import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; @@ -16,7 +15,7 @@ import org.tron.core.config.Parameter; import org.tron.core.config.args.Args; import org.tron.core.exception.P2pException; -import org.tron.core.net.message.BlockMessage; +import org.tron.core.net.message.adv.BlockMessage; import org.tron.core.net.peer.Item; import org.tron.core.net.peer.PeerConnection; import org.tron.protos.Protocol.Inventory.InventoryType; diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandlerTest.java index ee99a7dde6f..95cb9d0597f 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandlerTest.java @@ -9,7 +9,7 @@ import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.config.Parameter.NetConstants; import org.tron.core.exception.P2pException; -import org.tron.core.net.message.ChainInventoryMessage; +import org.tron.core.net.message.sync.ChainInventoryMessage; import org.tron.core.net.peer.PeerConnection; public class ChainInventoryMsgHandlerTest { diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/InventoryMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/InventoryMsgHandlerTest.java index 23a44ac3444..97db6207b2a 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/InventoryMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/InventoryMsgHandlerTest.java @@ -1,20 +1,24 @@ package org.tron.core.net.messagehandler; +import java.lang.reflect.Field; +import java.net.InetAddress; +import java.net.InetSocketAddress; import java.util.ArrayList; import org.junit.Test; -import org.tron.core.net.message.InventoryMessage; +import org.tron.core.net.message.adv.InventoryMessage; import org.tron.core.net.peer.PeerConnection; +import org.tron.p2p.connection.Channel; import org.tron.protos.Protocol.Inventory.InventoryType; public class InventoryMsgHandlerTest { private InventoryMsgHandler handler = new InventoryMsgHandler(); - private PeerConnection peer = new PeerConnection(); @Test - public void testProcessMessage() { + public void testProcessMessage() throws Exception { InventoryMessage msg = new InventoryMessage(new ArrayList<>(), InventoryType.TRX); - + PeerConnection peer = new PeerConnection(); + peer.setChannel(getChannel("1.0.0.3", 1000)); peer.setNeedSyncFromPeer(true); peer.setNeedSyncFromUs(true); handler.processMessage(peer, msg); @@ -28,4 +32,20 @@ public void testProcessMessage() { handler.processMessage(peer, msg); } + + private Channel getChannel(String host, int port) throws Exception { + Channel channel = new Channel(); + InetSocketAddress inetSocketAddress = new InetSocketAddress(host, port); + + Field field = channel.getClass().getDeclaredField("inetSocketAddress"); + field.setAccessible(true); + field.set(channel, inetSocketAddress); + + InetAddress inetAddress = inetSocketAddress.getAddress(); + field = channel.getClass().getDeclaredField("inetAddress"); + field.setAccessible(true); + field.set(channel, inetAddress); + + return channel; + } } diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java index 9749c59d911..a0c37d246da 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java @@ -4,7 +4,7 @@ import org.junit.Assert; import org.junit.Test; import org.tron.core.exception.P2pException; -import org.tron.core.net.message.SyncBlockChainMessage; +import org.tron.core.net.message.sync.SyncBlockChainMessage; import org.tron.core.net.peer.PeerConnection; public class SyncBlockChainMsgHandlerTest { diff --git a/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java b/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java index d850ab66958..a6189346ae5 100644 --- a/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java @@ -9,7 +9,6 @@ import org.junit.Before; import org.junit.Test; import org.tron.common.application.TronApplicationContext; -import org.tron.common.overlay.server.SyncPool; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.FileUtil; import org.tron.common.utils.ReflectUtils; @@ -18,21 +17,22 @@ import org.tron.core.capsule.BlockCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.net.message.BlockMessage; -import org.tron.core.net.message.TransactionMessage; +import org.tron.core.net.P2pEventHandlerImpl; +import org.tron.core.net.message.adv.BlockMessage; +import org.tron.core.net.message.adv.TransactionMessage; import org.tron.core.net.peer.Item; import org.tron.core.net.peer.PeerConnection; -import org.tron.core.net.service.AdvService; +import org.tron.core.net.service.adv.AdvService; +import org.tron.p2p.P2pEventHandler; import org.tron.protos.Protocol; import org.tron.protos.Protocol.Inventory.InventoryType; -//@Ignore public class AdvServiceTest { protected TronApplicationContext context; private AdvService service; private PeerConnection peer; - private SyncPool syncPool; + private P2pEventHandlerImpl p2pEventHandler; private String dbPath = "output-adv-service-test"; /** @@ -52,7 +52,6 @@ public void init() { @After public void destroy() { Args.clearParam(); - context.destroy(); FileUtil.deleteDir(new File(dbPath)); } @@ -60,7 +59,6 @@ public void destroy() { public void test() { testAddInv(); testBroadcast(); - //testFastSend(); testTrxBroadcast(); } @@ -87,51 +85,22 @@ private void testBroadcast() { try { peer = context.getBean(PeerConnection.class); - syncPool = context.getBean(SyncPool.class); + p2pEventHandler = context.getBean(P2pEventHandlerImpl.class); List peers = Lists.newArrayList(); peers.add(peer); - ReflectUtils.setFieldValue(syncPool, "activePeers", peers); + ReflectUtils.setFieldValue(P2pEventHandler.class, "peers", peers); BlockCapsule blockCapsule = new BlockCapsule(1, Sha256Hash.ZERO_HASH, System.currentTimeMillis(), Sha256Hash.ZERO_HASH.getByteString()); BlockMessage msg = new BlockMessage(blockCapsule); service.broadcast(msg); Item item = new Item(blockCapsule.getBlockId(), InventoryType.BLOCK); Assert.assertNotNull(service.getMessage(item)); - - peer.close(); - syncPool.close(); } catch (NullPointerException e) { System.out.println(e); } } - /* - private void testFastSend() { - - try { - peer = context.getBean(PeerConnection.class); - syncPool = context.getBean(SyncPool.class); - - List peers = Lists.newArrayList(); - peers.add(peer); - ReflectUtils.setFieldValue(syncPool, "activePeers", peers); - BlockCapsule blockCapsule = new BlockCapsule(1, Sha256Hash.ZERO_HASH, - System.currentTimeMillis(), Sha256Hash.ZERO_HASH.getByteString()); - BlockMessage msg = new BlockMessage(blockCapsule); - service.fastForward(msg); - Item item = new Item(blockCapsule.getBlockId(), InventoryType.BLOCK); - //Assert.assertNull(service.getMessage(item)); - - peer.getAdvInvRequest().put(item, System.currentTimeMillis()); - service.onDisconnect(peer); - peer.close(); - syncPool.close(); - } catch (NullPointerException e) { - System.out.println(e); - } - } - */ private void testTrxBroadcast() { Protocol.Transaction trx = Protocol.Transaction.newBuilder().build(); diff --git a/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java b/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java index 69dffe7ab29..b4deb6aff4b 100644 --- a/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java @@ -2,21 +2,18 @@ import com.google.common.collect.Lists; import com.google.protobuf.ByteString; - import java.io.File; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Set; - import org.bouncycastle.util.encoders.Hex; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.tron.common.application.TronApplicationContext; -import org.tron.common.overlay.server.SyncPool; import org.tron.common.utils.FileUtil; import org.tron.common.utils.ReflectUtils; import org.tron.core.ChainBaseManager; @@ -25,10 +22,11 @@ import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.net.message.BlockMessage; +import org.tron.core.net.P2pEventHandlerImpl; +import org.tron.core.net.message.adv.BlockMessage; import org.tron.core.net.peer.Item; import org.tron.core.net.peer.PeerConnection; -import org.tron.core.net.service.RelayService; +import org.tron.core.net.service.relay.RelayService; import org.tron.protos.Protocol; public class RelayServiceTest { @@ -37,7 +35,7 @@ public class RelayServiceTest { private RelayService service; private ChainBaseManager chainBaseManager; private PeerConnection peer; - private SyncPool syncPool; + private P2pEventHandlerImpl p2pEventHandler; private String dbPath = "output-relay-service-test"; /** @@ -50,6 +48,7 @@ public void init() { context = new TronApplicationContext(DefaultConfig.class); service = context.getBean(RelayService.class); chainBaseManager = context.getBean(ChainBaseManager.class); + p2pEventHandler = context.getBean(P2pEventHandlerImpl.class); } @After @@ -108,11 +107,11 @@ private void testBroadcast() { peer.setAddress(getFromHexString("A0299F3DB80A24B20A254B89CE639D59132F157F13")); peer.setNeedSyncFromPeer(false); peer.setNeedSyncFromUs(false); - syncPool = context.getBean(SyncPool.class); + p2pEventHandler = context.getBean(P2pEventHandlerImpl.class); List peers = Lists.newArrayList(); peers.add(peer); - ReflectUtils.setFieldValue(syncPool, "activePeers", peers); + ReflectUtils.setFieldValue(p2pEventHandler, "activePeers", peers); BlockCapsule blockCapsule = new BlockCapsule(chainBaseManager.getHeadBlockNum() + 1, chainBaseManager.getHeadBlockId(), 0, getFromHexString("A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F")); @@ -121,8 +120,7 @@ private void testBroadcast() { Item item = new Item(blockCapsule.getBlockId(), Protocol.Inventory.InventoryType.BLOCK); Assert.assertEquals(1, peer.getAdvInvSpread().size()); Assert.assertNotNull(peer.getAdvInvSpread().getIfPresent(item)); - peer.close(); - syncPool.close(); + peer.getChannel().close(); } catch (NullPointerException e) { System.out.println(e); } diff --git a/framework/src/test/java/org/tron/program/SolidityNodeTest.java b/framework/src/test/java/org/tron/program/SolidityNodeTest.java index 307b44d0b9c..0bd2dccfe85 100755 --- a/framework/src/test/java/org/tron/program/SolidityNodeTest.java +++ b/framework/src/test/java/org/tron/program/SolidityNodeTest.java @@ -9,7 +9,7 @@ import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; -import org.tron.common.overlay.client.DatabaseGrpcClient; +import org.tron.common.client.DatabaseGrpcClient; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; From 27ca2453fe3a7fb2d0153fce65bcab2ae44c5f86 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 15 Nov 2022 15:36:00 +0800 Subject: [PATCH 0419/1197] feat(net): optimize p2p service shutdown logic --- .../src/main/java/org/tron/core/net/TronNetService.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index c46c4688071..5f8bbbe8ad2 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -32,7 +32,7 @@ public class TronNetService { private static P2pConfig p2pConfig; @Getter - private static P2pService p2pService; + private static P2pService p2pService = new P2pService(); @Autowired private AdvService advService; @@ -63,10 +63,12 @@ public class TronNetService { @Autowired private TronStatsManager tronStatsManager; + private volatile boolean init; + public void start() { try { + init = true; p2pConfig = getConfig(); - p2pService = new P2pService(); p2pService.start(p2pConfig); p2pService.register(p2pEventHandler); advService.init(); @@ -85,6 +87,9 @@ public void start() { } public void close() { + if (!init) { + return; + } PeerManager.close(); tronStatsManager.close(); nodePersistService.close(); From ce4f290eb505cf826e7771a401e73b1fb1f4eda8 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 15 Nov 2022 17:08:44 +0800 Subject: [PATCH 0420/1197] feat(net): update p2p version to v0.1.4 --- framework/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/build.gradle b/framework/build.gradle index 9e1e57413ea..bbbeaee8a63 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -44,10 +44,10 @@ dependencies { testCompile group: 'org.testng', name: 'testng', version: '6.14.3' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.1.3' - compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.1.4' + compile group: 'com.typesafe', name: 'config', version: '1.3.2' compile "com.cedarsoftware:java-util:1.8.0" From 68254125bcd33aa2783a56dff559d63138f40ba7 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 15 Nov 2022 18:35:43 +0800 Subject: [PATCH 0421/1197] feat(net): solve sonar problems --- .../java/org/tron/core/net/P2pEventHandlerImpl.java | 12 ++++++++---- .../main/java/org/tron/core/net/TronNetService.java | 5 ++++- .../java/org/tron/core/net/peer/PeerConnection.java | 4 ++-- .../core/net/service/handshake/HandshakeService.java | 1 - .../core/net/service/keepalive/KeepAliveService.java | 2 +- .../core/net/service/statistics/NodeStatistics.java | 12 ++++++------ .../net/service/statistics/TronStatsManager.java | 8 ++++---- 7 files changed, 25 insertions(+), 19 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java index 6a50ccb0a2e..d19134b62ae 100644 --- a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java +++ b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java @@ -131,12 +131,14 @@ public void onMessage(Channel c, byte[] data) { private void processMessage(PeerConnection peer, byte[] data) { long startTime = System.currentTimeMillis(); TronMessage msg = null; + MessageTypes type = null; try { msg = TronMessageFactory.create(data); + type = msg.getType(); peer.getPeerStatistics().messageStatistics.addTcpInMessage(msg); logger.info("Receive message from peer: {}, {}", peer.getInetSocketAddress(), msg); - switch (msg.getType()) { + switch (type) { case P2P_PING: case P2P_PONG: keepAliveService.processMessage(peer, msg); @@ -179,9 +181,11 @@ private void processMessage(PeerConnection peer, byte[] data) { long costs = System.currentTimeMillis() - startTime; if (costs > 50) { logger.info("Message processing costs {} ms, peer: {}, type: {}, time tag: {}", - costs, peer.getInetSocketAddress(), msg.getType(), getTimeTag(costs)); - Metrics.histogramObserve(MetricKeys.Histogram.MESSAGE_PROCESS_LATENCY, - costs / Metrics.MILLISECONDS_PER_SECOND, msg.getType().name()); + costs, peer.getInetSocketAddress(), type, getTimeTag(costs)); + if (type != null) { + Metrics.histogramObserve(MetricKeys.Histogram.MESSAGE_PROCESS_LATENCY, + costs / Metrics.MILLISECONDS_PER_SECOND, type.name()); + } } } } diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 5f8bbbe8ad2..8b930dafade 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -65,10 +65,13 @@ public class TronNetService { private volatile boolean init; + private static void setP2pConfig(P2pConfig config) { + TronNetService.p2pConfig = config; + } public void start() { try { init = true; - p2pConfig = getConfig(); + setP2pConfig(getConfig()); p2pService.start(p2pConfig); p2pService.register(p2pEventHandler); advService.init(); diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index 3c35e08dd0a..260b82747f4 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -90,7 +90,7 @@ public class PeerConnection { private int invCacheSize = 20_000; - private long BAD_PEER_BAN_TIME = 3600 * 1000; + private long BAD_PEER_BAN_TIME = 3_600_000; @Setter @Getter @@ -282,7 +282,7 @@ private boolean needToLog(Message msg) { @Override public boolean equals(Object o) { - if (o == null || !(o instanceof PeerConnection)) { + if (!(o instanceof PeerConnection)) { return false; } return this.channel.equals(((PeerConnection) o).getChannel()); diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java index 22ba096fb20..d0ece8734d6 100644 --- a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -104,7 +104,6 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { System.currentTimeMillis() - peer.getChannel().getStartTime()); PeerManager.sortPeers(); peer.onConnect(); - return; } private void sendHelloMessage(PeerConnection peer, long time) { diff --git a/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java b/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java index 35c2843c046..49ae692b6f1 100644 --- a/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java +++ b/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java @@ -21,7 +21,7 @@ public class KeepAliveService { private long PING_TIMEOUT = 20_000; - public long PING_PERIOD = 60_000; + private long PING_PERIOD = 60_000; private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(r -> new Thread(r, "KeepAlive")); diff --git a/framework/src/main/java/org/tron/core/net/service/statistics/NodeStatistics.java b/framework/src/main/java/org/tron/core/net/service/statistics/NodeStatistics.java index 1bfd7a41738..aef293d493c 100644 --- a/framework/src/main/java/org/tron/core/net/service/statistics/NodeStatistics.java +++ b/framework/src/main/java/org/tron/core/net/service/statistics/NodeStatistics.java @@ -10,8 +10,8 @@ public class NodeStatistics { private Protocol.ReasonCode localDisconnectReason = null; @Getter private int disconnectTimes = 0; - private long lastDisconnectedTime = 0; - private long firstDisconnectedTime = 0; +// private long lastDisconnectedTime = 0; +// private long firstDisconnectedTime = 0; private long start = System.currentTimeMillis(); public Protocol.ReasonCode getDisconnectReason() { @@ -35,10 +35,10 @@ public void nodeDisconnectedLocal(Protocol.ReasonCode reason) { } private void notifyDisconnect() { - lastDisconnectedTime = System.currentTimeMillis(); - if (firstDisconnectedTime == 0) { - firstDisconnectedTime = lastDisconnectedTime; - } +// lastDisconnectedTime = System.currentTimeMillis(); +// if (firstDisconnectedTime == 0) { +// firstDisconnectedTime = lastDisconnectedTime; +// } disconnectTimes++; } diff --git a/framework/src/main/java/org/tron/core/net/service/statistics/TronStatsManager.java b/framework/src/main/java/org/tron/core/net/service/statistics/TronStatsManager.java index cf241102dbf..da9b4b0f2d3 100644 --- a/framework/src/main/java/org/tron/core/net/service/statistics/TronStatsManager.java +++ b/framework/src/main/java/org/tron/core/net/service/statistics/TronStatsManager.java @@ -19,10 +19,10 @@ @Slf4j(topic = "net") @Component public class TronStatsManager { - private static volatile long TCP_TRAFFIC_IN = 0; - private static volatile long TCP_TRAFFIC_OUT = 0; - private static volatile long UDP_TRAFFIC_IN = 0; - private static volatile long UDP_TRAFFIC_OUT = 0; + private volatile long TCP_TRAFFIC_IN = 0; + private volatile long TCP_TRAFFIC_OUT = 0; + private volatile long UDP_TRAFFIC_IN = 0; + private volatile long UDP_TRAFFIC_OUT = 0; private static Cache cache = CacheBuilder.newBuilder() .maximumSize(3000).recordStats().build(); From 736a518d614bd5e1dc6a8477f406fb2d48ba1e8b Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 15 Nov 2022 18:51:39 +0800 Subject: [PATCH 0422/1197] feat(net): remove unused code --- .../src/main/java/org/tron/core/net/TronNetService.java | 1 + .../tron/core/net/service/statistics/NodeStatistics.java | 6 ------ 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 8b930dafade..e036dd062d1 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -68,6 +68,7 @@ public class TronNetService { private static void setP2pConfig(P2pConfig config) { TronNetService.p2pConfig = config; } + public void start() { try { init = true; diff --git a/framework/src/main/java/org/tron/core/net/service/statistics/NodeStatistics.java b/framework/src/main/java/org/tron/core/net/service/statistics/NodeStatistics.java index aef293d493c..116b9a5c7e5 100644 --- a/framework/src/main/java/org/tron/core/net/service/statistics/NodeStatistics.java +++ b/framework/src/main/java/org/tron/core/net/service/statistics/NodeStatistics.java @@ -10,8 +10,6 @@ public class NodeStatistics { private Protocol.ReasonCode localDisconnectReason = null; @Getter private int disconnectTimes = 0; -// private long lastDisconnectedTime = 0; -// private long firstDisconnectedTime = 0; private long start = System.currentTimeMillis(); public Protocol.ReasonCode getDisconnectReason() { @@ -35,10 +33,6 @@ public void nodeDisconnectedLocal(Protocol.ReasonCode reason) { } private void notifyDisconnect() { -// lastDisconnectedTime = System.currentTimeMillis(); -// if (firstDisconnectedTime == 0) { -// firstDisconnectedTime = lastDisconnectedTime; -// } disconnectTimes++; } From 4353450af09aaaa4b6d8141532de1c6325fe9f19 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 16 Nov 2022 15:29:45 +0800 Subject: [PATCH 0423/1197] modify the network parameter initialization value --- .../main/java/org/tron/core/config/args/Args.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index a773c467481..92441675e7d 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -123,9 +123,9 @@ public static void clearParam() { PARAMETER.nodeDiscoveryEnable = false; PARAMETER.nodeDiscoveryPersist = false; PARAMETER.nodeConnectionTimeout = 2000; - PARAMETER.activeNodes = Collections.emptyList(); - PARAMETER.passiveNodes = Collections.emptyList(); - PARAMETER.fastForwardNodes = Collections.emptyList(); + PARAMETER.activeNodes = new ArrayList<>(); + PARAMETER.passiveNodes = new ArrayList<>(); + PARAMETER.fastForwardNodes = new ArrayList<>(); PARAMETER.maxFastForwardNum = 3; PARAMETER.nodeChannelReadTimeout = 0; PARAMETER.maxConnections = 30; @@ -1116,10 +1116,10 @@ private static RateLimiterInitialization getRateLimiterFromConfig( private static List getInetSocketAddress( final com.typesafe.config.Config config, String path) { + List ret = new ArrayList<>(); if (!config.hasPath(path)) { - return Collections.emptyList(); + return ret; } - List ret = new ArrayList<>(); List list = config.getStringList(path); for (String configString : list) { String[] sz = configString.split(":"); @@ -1137,10 +1137,10 @@ private static List getInetSocketAddress( private static List getInetAddress( final com.typesafe.config.Config config, String path) { + List ret = new ArrayList<>(); if (!config.hasPath(path)) { - return Collections.emptyList(); + return ret; } - List ret = new ArrayList<>(); List list = config.getStringList(path); for (String configString : list) { try { From 84849b4e4b68f88734d25f0dc19c107e3018cbcd Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 16 Nov 2022 14:17:16 +0800 Subject: [PATCH 0424/1197] fix(freezeV2): sort frozenV2 list for getaccount interface --- .../org/tron/core/capsule/AccountCapsule.java | 69 ++++++++----------- .../src/main/java/org/tron/core/Wallet.java | 57 ++++++++------- 2 files changed, 59 insertions(+), 67 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index f94a9ca1eea..a1e40878173 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -15,7 +15,6 @@ package org.tron.core.capsule; -import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; @@ -333,24 +332,24 @@ public long getLatestOperationTime() { return this.account.getLatestOprationTime(); } - public void setLatestOperationTime(long latest_time) { - this.account = this.account.toBuilder().setLatestOprationTime(latest_time).build(); + public void setLatestOperationTime(long latestTime) { + this.account = this.account.toBuilder().setLatestOprationTime(latestTime).build(); } public long getLatestConsumeTime() { return this.account.getLatestConsumeTime(); } - public void setLatestConsumeTime(long latest_time) { - this.account = this.account.toBuilder().setLatestConsumeTime(latest_time).build(); + public void setLatestConsumeTime(long latestTime) { + this.account = this.account.toBuilder().setLatestConsumeTime(latestTime).build(); } public long getLatestConsumeFreeTime() { return this.account.getLatestConsumeFreeTime(); } - public void setLatestConsumeFreeTime(long latest_time) { - this.account = this.account.toBuilder().setLatestConsumeFreeTime(latest_time).build(); + public void setLatestConsumeFreeTime(long latestTime) { + this.account = this.account.toBuilder().setLatestConsumeFreeTime(latestTime).build(); } public void addDelegatedFrozenBalanceForBandwidth(long balance) { @@ -363,8 +362,7 @@ public long getAcquiredDelegatedFrozenBalanceForBandwidth() { } public void addFrozenBalanceForBandwidthV2(long balance) { - Common.ResourceCode type = Common.ResourceCode.BANDWIDTH; - this.addFrozenBalanceForResource(type, balance); + this.addFrozenBalanceForResource(BANDWIDTH, balance); } public void setAcquiredDelegatedFrozenBalanceForBandwidth(long balance) { @@ -452,8 +450,7 @@ public void addDelegatedFrozenBalanceForEnergy(long balance) { } public void addFrozenBalanceForEnergyV2(long balance) { - Common.ResourceCode type = Common.ResourceCode.ENERGY; - this.addFrozenBalanceForResource(type, balance); + this.addFrozenBalanceForResource(ENERGY, balance); } private void addFrozenBalanceForResource(Common.ResourceCode type, long balance) { @@ -461,7 +458,7 @@ private void addFrozenBalanceForResource(Common.ResourceCode type, long balance) for (int i = 0; i < this.account.getFrozenV2List().size(); i++) { if (this.account.getFrozenV2List().get(i).getType().equals(type)) { long newAmount = this.account.getFrozenV2(i).getAmount() + balance; - Account.FreezeV2 freezeV2 = Account.FreezeV2.newBuilder() + FreezeV2 freezeV2 = FreezeV2.newBuilder() .setType(type) .setAmount(newAmount) .build(); @@ -472,7 +469,7 @@ private void addFrozenBalanceForResource(Common.ResourceCode type, long balance) } if (!doUpdate) { - Account.FreezeV2 freezeV2 = Account.FreezeV2.newBuilder() + FreezeV2 freezeV2 = FreezeV2.newBuilder() .setType(type) .setAmount(balance) .build(); @@ -520,19 +517,14 @@ public void clearVotes() { * get votes. */ public List getVotesList() { - if (this.account.getVotesList() != null) { - return this.account.getVotesList(); - } else { - return Lists.newArrayList(); - } + return this.account.getVotesList(); } public long getTronPowerUsage() { - if (this.account.getVotesList() != null) { - return this.account.getVotesList().stream().mapToLong(Vote::getVoteCount).sum(); - } else { + if (getVotesList().isEmpty()) { return 0L; } + return this.account.getVotesList().stream().mapToLong(Vote::getVoteCount).sum(); } //tp:Tron_Power @@ -563,47 +555,42 @@ public long getAllTronPower() { - public List getFrozenV2List() { + public List getFrozenV2List() { return account.getFrozenV2List(); } - public List getUnfrozenV2List() { + public List getUnfrozenV2List() { return account.getUnfrozenV2List(); } - public void updateFrozenV2List(int i, Account.FreezeV2 frozenV2) { + public void updateFrozenV2List(int index, FreezeV2 frozenV2) { this.account = this.account.toBuilder() - .setFrozenV2(i, frozenV2) + .setFrozenV2(index, frozenV2) .build(); } - public void addFrozenV2List(Account.FreezeV2 frozenV2) { + public void addFrozenV2List(FreezeV2 frozenV2) { this.account = this.account.toBuilder().addFrozenV2(frozenV2).build(); } - public void addUnfrozenV2List(Common.ResourceCode type, long unfreezeAmount, long expireTime) { - - Account.UnFreezeV2 unFreezeV2 = Account.UnFreezeV2.newBuilder() + public void addUnfrozenV2List(ResourceCode type, long unfreezeAmount, long expireTime) { + UnFreezeV2 unFreezeV2 = UnFreezeV2.newBuilder() .setType(type) .setUnfreezeAmount(unfreezeAmount) .setUnfreezeExpireTime(expireTime) .build(); - this.account = this.account.toBuilder() - .addUnfrozenV2(unFreezeV2) - .build(); + this.account = this.account.toBuilder().addUnfrozenV2(unFreezeV2).build(); } public int getUnfreezingV2Count(long now) { int count = 0; - - List unFreezeV2List = account.getUnfrozenV2List(); - for (Account.UnFreezeV2 item : unFreezeV2List) { + List unFreezeV2List = account.getUnfrozenV2List(); + for (UnFreezeV2 item : unFreezeV2List) { if (item.getUnfreezeExpireTime() > now) { count++; } } - return count; } @@ -1063,8 +1050,7 @@ public void setFrozenForTronPower(long frozenBalance, long expireTime) { } public void addFrozenForTronPowerV2(long balance) { - Common.ResourceCode type = Common.ResourceCode.TRON_POWER; - this.addFrozenBalanceForResource(type, balance); + this.addFrozenBalanceForResource(TRON_POWER, balance); } public long getTronPowerFrozenBalance() { @@ -1096,10 +1082,10 @@ public long getLatestConsumeTimeForEnergy() { return this.account.getAccountResource().getLatestConsumeTimeForEnergy(); } - public void setLatestConsumeTimeForEnergy(long latest_time) { + public void setLatestConsumeTimeForEnergy(long latestTime) { this.account = this.account.toBuilder() .setAccountResource( - this.account.getAccountResource().toBuilder().setLatestConsumeTimeForEnergy(latest_time) + this.account.getAccountResource().toBuilder().setLatestConsumeTimeForEnergy(latestTime) .build()).build(); } @@ -1108,8 +1094,7 @@ public long getFreeNetUsage() { } public void setFreeNetUsage(long freeNetUsage) { - this.account = this.account.toBuilder() - .setFreeNetUsage(freeNetUsage).build(); + this.account = this.account.toBuilder().setFreeNetUsage(freeNetUsage).build(); } public boolean addAllFreeAssetNetUsageV2(Map map) { diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index ba04a0b2b8b..c1904f76cf7 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -28,6 +28,7 @@ import static org.tron.core.config.Parameter.DatabaseConstants.PROPOSAL_COUNT_LIMIT_MAX; import static org.tron.core.services.jsonrpc.JsonRpcApiUtil.parseEnergyFee; import static org.tron.core.services.jsonrpc.TronJsonRpcImpl.EARLIEST_STR; +import static org.tron.protos.contract.Common.ResourceCode; import com.google.common.collect.ContiguousSet; import com.google.common.collect.DiscreteDomain; @@ -204,6 +205,8 @@ import org.tron.core.zen.note.OutgoingPlaintext; import org.tron.protos.Protocol; import org.tron.protos.Protocol.Account; +import org.tron.protos.Protocol.Account.FreezeV2; +import org.tron.protos.Protocol.Account.UnFreezeV2; import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.DelegatedResourceAccountIndex; import org.tron.protos.Protocol.Exchange; @@ -271,8 +274,8 @@ public class Wallet { @Autowired private NodeManager nodeManager; - private int minEffectiveConnection = Args.getInstance().getMinEffectiveConnection(); - private boolean trxCacheEnable = Args.getInstance().isTrxCacheEnable(); + private int minEffectiveConnection = CommonParameter.getInstance().getMinEffectiveConnection(); + private boolean trxCacheEnable = CommonParameter.getInstance().isTrxCacheEnable(); public static final String CONTRACT_VALIDATE_EXCEPTION = "ContractValidateException: {}"; public static final String CONTRACT_VALIDATE_ERROR = "Contract validate error : "; @@ -281,7 +284,7 @@ public class Wallet { */ public Wallet() { this.cryptoEngine = SignUtils.getGeneratedRandomSign(Utils.getRandom(), - Args.getInstance().isECKeyCryptoEngine()); + CommonParameter.getInstance().isECKeyCryptoEngine()); } /** @@ -308,24 +311,6 @@ public static void setAddressPreFixByte(byte addressPreFixByte) { DecodeUtil.addressPreFixByte = addressPreFixByte; } - // public ShieldAddress generateShieldAddress() { - // ShieldAddress.Builder builder = ShieldAddress.newBuilder(); - // ShieldAddressGenerator shieldAddressGenerator = new ShieldAddressGenerator(); - // - // byte[] privateKey = shieldAddressGenerator.generatePrivateKey(); - // byte[] publicKey = shieldAddressGenerator.generatePublicKey(privateKey); - // - // byte[] privateKeyEnc = shieldAddressGenerator.generatePrivateKeyEnc(privateKey); - // byte[] publicKeyEnc = shieldAddressGenerator.generatePublicKeyEnc(privateKeyEnc); - // - // byte[] addPrivate = ByteUtil.merge(privateKey, privateKeyEnc); - // byte[] addPublic = ByteUtil.merge(publicKey, publicKeyEnc); - // - // builder.setPrivateAddress(ByteString.copyFrom(addPrivate)); - // builder.setPublicAddress(ByteString.copyFrom(addPublic)); - // return builder.build(); - // } - public byte[] getAddress() { return cryptoEngine.getAddress(); } @@ -352,10 +337,32 @@ public Account getAccount(Account account) { + BLOCK_PRODUCED_INTERVAL * accountCapsule.getLatestConsumeFreeTime()); accountCapsule.setLatestConsumeTimeForEnergy(genesisTimeStamp + BLOCK_PRODUCED_INTERVAL * accountCapsule.getLatestConsumeTimeForEnergy()); - + sortFrozenV2List(accountCapsule); return accountCapsule.getInstance(); } + private void sortFrozenV2List(AccountCapsule accountCapsule) { + List oldFreezeV2List = accountCapsule.getFrozenV2List(); + accountCapsule.clearFrozenV2(); + ResourceCode[] codes = ResourceCode.values(); + for (ResourceCode code : codes) { + if (ResourceCode.UNRECOGNIZED != code) { + accountCapsule.addFrozenV2List(FreezeV2.newBuilder() + .setType(code) + .setAmount(0) + .build()); + } + } + List newFreezeV2List = accountCapsule.getFrozenV2List(); + for (int i = 0; i < newFreezeV2List.size(); i++) { + FreezeV2 freezeV2 = newFreezeV2List.get(i); + ResourceCode code = freezeV2.getType(); + Optional optional = oldFreezeV2List + .stream().filter(o -> o.getType() == code).findFirst(); + accountCapsule.updateFrozenV2List(i, optional.orElse(freezeV2)); + } + } + public Account getAccountById(Account account) { AccountStore accountStore = chainBaseManager.getAccountStore(); AccountIdIndexStore accountIdIndexStore = chainBaseManager.getAccountIdIndexStore(); @@ -784,7 +791,7 @@ public GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage getCanWithdrawUnfreezeAm timestamp = dynamicStore.getLatestBlockHeaderTimestamp(); } - List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); + List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); long finalTimestamp = timestamp; canWithdrawUnfreezeAmount = unfrozenV2List @@ -792,7 +799,7 @@ public GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage getCanWithdrawUnfreezeAm .filter(unfrozenV2 -> (unfrozenV2.getUnfreezeAmount() > 0 && unfrozenV2.getUnfreezeExpireTime() <= finalTimestamp)) - .mapToLong(Account.UnFreezeV2::getUnfreezeAmount) + .mapToLong(UnFreezeV2::getUnfreezeAmount) .sum(); @@ -830,7 +837,7 @@ public GrpcAPI.GetAvailableUnfreezeCountResponseMessage getAvailableUnfreezeCoun } long now = dynamicStore.getLatestBlockHeaderTimestamp(); - List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); + List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); long getUsedUnfreezeCount = unfrozenV2List .stream() .filter(unfrozenV2 -> From 62e9c1aad4ccd766ecb30a12ca0dfb649785030e Mon Sep 17 00:00:00 2001 From: chaozhu Date: Thu, 17 Nov 2022 12:00:22 +0800 Subject: [PATCH 0425/1197] feat(freezeV2): Add bandwidth cost for delegating validation --- .../org/tron/core/actuator/DelegateResourceActuator.java | 8 +++++++- .../java/org/tron/core/capsule/TransactionCapsule.java | 4 ++++ framework/src/main/java/org/tron/core/Wallet.java | 3 ++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index ec36c2c4b90..7c20de7b97b 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -28,6 +28,7 @@ import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.BalanceContract.DelegateResourceContract; +import org.tron.core.utils.TransactionUtil; @Slf4j(topic = "actuator") public class DelegateResourceActuator extends AbstractActuator { @@ -143,7 +144,12 @@ public boolean validate() throws ContractValidateException { BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); processor.updateUsage(ownerCapsule); - long netUsage = (long) (ownerCapsule.getNetUsage() * TRX_PRECISION * ((double) + long accountNetUsage = ownerCapsule.getNetUsage(); + if (null != this.getTx() && this.getTx().isTransactionCreate()) { + accountNetUsage += TransactionUtil.estimateConsumeBandWidthSize(ownerCapsule, + chainBaseManager); + } + long netUsage = (long) (accountNetUsage * TRX_PRECISION * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); long ownerNetUsage = (long) (netUsage * ((double)(ownerCapsule diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java index f3c2af334cb..2478a7ea7d2 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -107,6 +107,10 @@ public class TransactionCapsule implements ProtoCapsule { private long order; private byte[] ownerAddress; + @Getter + @Setter + private boolean isTransactionCreate = false; + public byte[] getOwnerAddress() { if (this.ownerAddress == null) { this.ownerAddress = getOwner(this.transaction.getRawData().getContract(0)); diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index ba04a0b2b8b..222d26ce5fd 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -457,6 +457,7 @@ public TransactionCapsule createTransactionCapsuleWithoutValidate( public TransactionCapsule createTransactionCapsule(com.google.protobuf.Message message, ContractType contractType) throws ContractValidateException { TransactionCapsule trx = new TransactionCapsule(message, contractType); + trx.setTransactionCreate(true); if (contractType != ContractType.CreateSmartContract && contractType != ContractType.TriggerSmartContract) { List actList = ActuatorFactory.createActuator(trx, chainBaseManager); @@ -464,7 +465,7 @@ public TransactionCapsule createTransactionCapsule(com.google.protobuf.Message m act.validate(); } } - + trx.setTransactionCreate(false); if (contractType == ContractType.CreateSmartContract) { CreateSmartContract contract = ContractCapsule From 5ebad2a7eac3451aa945ac8864eed297c97fa4f7 Mon Sep 17 00:00:00 2001 From: liukai Date: Fri, 18 Nov 2022 11:51:51 +0800 Subject: [PATCH 0426/1197] feat(version): update Version 1. update to Version 4.6.0 --- framework/src/main/java/org/tron/program/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 4296f5daf1a..93ee7a52818 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -4,7 +4,7 @@ public class Version { public static final String VERSION_NAME = "GreatVoyage-v4.5.1-125-ga9809b5bb"; public static final String VERSION_CODE = "17071"; - private static final String VERSION = "4.5.2"; + private static final String VERSION = "4.6.0"; public static String getVersion() { return VERSION; From 429f433b268eea85fe5c39a0bf00e9a73aab6ee0 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Fri, 18 Nov 2022 15:50:44 +0800 Subject: [PATCH 0427/1197] fix(freezeV2): optimize stake2.0 code --- .../core/actuator/FreezeBalanceActuator.java | 8 +-- .../actuator/UnfreezeBalanceActuator.java | 12 ++--- .../actuator/UnfreezeBalanceV2Actuator.java | 53 +++++++++---------- .../org/tron/core/capsule/AccountCapsule.java | 19 +++---- .../capsule/DelegatedResourceCapsule.java | 16 +++--- .../org/tron/core/db/BandwidthProcessor.java | 4 +- .../org/tron/core/db/EnergyProcessor.java | 1 - .../org/tron/core/db/ResourceProcessor.java | 7 +-- .../src/main/java/org/tron/core/Wallet.java | 12 ++--- .../core/services/jsonrpc/JsonRpcApiUtil.java | 22 ++++++-- .../jsonrpc/types/TransactionResult.java | 4 +- .../UnfreezeBalanceV2ActuatorTest.java | 21 ++++---- protocol/src/main/protos/core/Tron.proto | 2 +- 13 files changed, 87 insertions(+), 94 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java index 5d630d0f115..03cb72d8306 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java @@ -175,11 +175,6 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("frozenBalance must be less than accountBalance"); } -// long maxFrozenNumber = dbManager.getDynamicPropertiesStore().getMaxFrozenNumber(); -// if (accountCapsule.getFrozenCount() >= maxFrozenNumber) { -// throw new ContractValidateException("max frozen number is: " + maxFrozenNumber); -// } - long frozenDuration = freezeBalanceContract.getFrozenDuration(); long minFrozenTime = dynamicStore.getMinFrozenTime(); long maxFrozenTime = dynamicStore.getMaxFrozenTime(); @@ -224,8 +219,7 @@ public boolean validate() throws ContractValidateException { //If the receiver is included in the contract, the receiver will receive the resource. if (!ArrayUtils.isEmpty(receiverAddress) && dynamicStore.supportDR()) { if (Arrays.equals(receiverAddress, ownerAddress)) { - throw new ContractValidateException( - "receiverAddress must not be the same as ownerAddress"); + throw new ContractValidateException("receiverAddress must not be the same as ownerAddress"); } if (!DecodeUtil.addressValid(receiverAddress)) { diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java index 93dcd61e044..41a01d5f238 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java @@ -38,6 +38,9 @@ @Slf4j(topic = "actuator") public class UnfreezeBalanceActuator extends AbstractActuator { + private static final String INVALID_RESOURCE_CODE = + "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"; + public UnfreezeBalanceActuator() { super(ContractType.UnfreezeBalanceContract, UnfreezeBalanceContract.class); } @@ -402,8 +405,7 @@ public boolean validate() throws ContractValidateException { } break; default: - throw new ContractValidateException( - "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + throw new ContractValidateException(INVALID_RESOURCE_CODE); } } else { @@ -440,8 +442,7 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("It's not time to unfreeze(TronPower)."); } } else { - throw new ContractValidateException( - "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + throw new ContractValidateException(INVALID_RESOURCE_CODE); } break; default: @@ -449,8 +450,7 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException( "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy、TRON_POWER]"); } else { - throw new ContractValidateException( - "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + throw new ContractValidateException(INVALID_RESOURCE_CODE); } } diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java index 416f861d2da..b43b614b8a6 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java @@ -3,6 +3,10 @@ import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; +import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; import com.google.common.collect.Lists; import com.google.protobuf.ByteString; @@ -24,11 +28,12 @@ import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.store.VotesStore; import org.tron.protos.Protocol; +import org.tron.protos.Protocol.Account.FreezeV2; +import org.tron.protos.Protocol.Account.UnFreezeV2; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.Protocol.Vote; import org.tron.protos.contract.BalanceContract.UnfreezeBalanceV2Contract; -import org.tron.protos.contract.Common; @Slf4j(topic = "actuator") public class UnfreezeBalanceV2Actuator extends AbstractActuator { @@ -73,7 +78,7 @@ public boolean execute(Object result) throws ContractExeException { accountCapsule.initializeOldTronPower(); } - Common.ResourceCode freezeType = unfreezeBalanceV2Contract.getResource(); + ResourceCode freezeType = unfreezeBalanceV2Contract.getResource(); this.updateAccountFrozenInfo(freezeType, accountCapsule, unfreezeBalance); @@ -140,18 +145,18 @@ public boolean validate() throws ContractValidateException { long now = dynamicStore.getLatestBlockHeaderTimestamp(); switch (unfreezeBalanceV2Contract.getResource()) { case BANDWIDTH: - if (!this.checkExistFreezedBalance(accountCapsule, Common.ResourceCode.BANDWIDTH)) { + if (!checkExistFrozenBalance(accountCapsule, BANDWIDTH)) { throw new ContractValidateException("no frozenBalance(BANDWIDTH)"); } break; case ENERGY: - if (!this.checkExistFreezedBalance(accountCapsule, Common.ResourceCode.ENERGY)) { + if (!checkExistFrozenBalance(accountCapsule, ENERGY)) { throw new ContractValidateException("no frozenBalance(Energy)"); } break; case TRON_POWER: if (dynamicStore.supportAllowNewResourceModel()) { - if (!this.checkExistFreezedBalance(accountCapsule, Common.ResourceCode.TRON_POWER)) { + if (!checkExistFrozenBalance(accountCapsule, TRON_POWER)) { throw new ContractValidateException("no frozenBalance(TronPower)"); } } else { @@ -190,32 +195,24 @@ public long calcFee() { return 0; } - public boolean checkExistFreezedBalance(AccountCapsule accountCapsule, Common.ResourceCode freezeType) { - boolean checkOk = false; - - long frozenAmount = 0; - List frozenV2List = accountCapsule.getFrozenV2List(); - for (Protocol.Account.FreezeV2 frozenV2 : frozenV2List) { - if (frozenV2.getType().equals(freezeType)) { - frozenAmount = frozenV2.getAmount(); - if (frozenAmount > 0) { - checkOk = true; - break; - } + public boolean checkExistFrozenBalance(AccountCapsule accountCapsule, ResourceCode freezeType) { + List frozenV2List = accountCapsule.getFrozenV2List(); + for (FreezeV2 frozenV2 : frozenV2List) { + if (frozenV2.getType().equals(freezeType) && frozenV2.getAmount() > 0) { + return true; } } - - return checkOk; + return false; } public boolean checkUnfreezeBalance(AccountCapsule accountCapsule, final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract, - Common.ResourceCode freezeType) { + ResourceCode freezeType) { boolean checkOk = false; long frozenAmount = 0L; - List freezeV2List = accountCapsule.getFrozenV2List(); - for (Protocol.Account.FreezeV2 freezeV2 : freezeV2List) { + List freezeV2List = accountCapsule.getFrozenV2List(); + for (FreezeV2 freezeV2 : freezeV2List) { if (freezeV2.getType().equals(freezeType)) { frozenAmount = freezeV2.getAmount(); break; @@ -237,11 +234,11 @@ public long calcUnfreezeExpireTime(long now) { return now + unfreezeDelayDays * FROZEN_PERIOD; } - public void updateAccountFrozenInfo(Common.ResourceCode freezeType, AccountCapsule accountCapsule, long unfreezeBalance) { - List freezeV2List = accountCapsule.getFrozenV2List(); + public void updateAccountFrozenInfo(ResourceCode freezeType, AccountCapsule accountCapsule, long unfreezeBalance) { + List freezeV2List = accountCapsule.getFrozenV2List(); for (int i = 0; i < freezeV2List.size(); i++) { if (freezeV2List.get(i).getType().equals(freezeType)) { - Protocol.Account.FreezeV2 freezeV2 = Protocol.Account.FreezeV2.newBuilder() + FreezeV2 freezeV2 = FreezeV2.newBuilder() .setAmount(freezeV2List.get(i).getAmount() - unfreezeBalance) .setType(freezeV2List.get(i).getType()) .build(); @@ -254,12 +251,12 @@ public void updateAccountFrozenInfo(Common.ResourceCode freezeType, AccountCapsu public long unfreezeExpire(AccountCapsule accountCapsule, long now) { long unfreezeBalance = 0L; - List unFrozenV2List = Lists.newArrayList(); + List unFrozenV2List = Lists.newArrayList(); unFrozenV2List.addAll(accountCapsule.getUnfrozenV2List()); - Iterator iterator = unFrozenV2List.iterator(); + Iterator iterator = unFrozenV2List.iterator(); while (iterator.hasNext()) { - Protocol.Account.UnFreezeV2 next = iterator.next(); + UnFreezeV2 next = iterator.next(); if (next.getUnfreezeExpireTime() <= now) { unfreezeBalance += next.getUnfreezeAmount(); iterator.remove(); diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index a1e40878173..d2ab55a7032 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -36,7 +36,6 @@ import org.tron.protos.Protocol.Vote; import org.tron.protos.contract.AccountContract.AccountCreateContract; import org.tron.protos.contract.AccountContract.AccountUpdateContract; -import org.tron.protos.contract.Common; import java.util.List; import java.util.Map; @@ -453,7 +452,7 @@ public void addFrozenBalanceForEnergyV2(long balance) { this.addFrozenBalanceForResource(ENERGY, balance); } - private void addFrozenBalanceForResource(Common.ResourceCode type, long balance) { + private void addFrozenBalanceForResource(ResourceCode type, long balance) { boolean doUpdate = false; for (int i = 0; i < this.account.getFrozenV2List().size(); i++) { if (this.account.getFrozenV2List().get(i).getType().equals(type)) { @@ -564,9 +563,10 @@ public List getUnfrozenV2List() { } public void updateFrozenV2List(int index, FreezeV2 frozenV2) { - this.account = this.account.toBuilder() - .setFrozenV2(index, frozenV2) - .build(); + if (Objects.isNull(frozenV2)) { + return; + } + this.account = this.account.toBuilder().setFrozenV2(index, frozenV2).build(); } public void addFrozenV2List(FreezeV2 frozenV2) { @@ -750,9 +750,8 @@ public boolean addAssetV2(byte[] key, long value) { return true; } - public boolean addAssetMapV2(Map assetMap) { + public void addAssetMapV2(Map assetMap) { this.account = this.account.toBuilder().putAllAssetV2(assetMap).build(); - return true; } public Long getAsset(DynamicPropertiesStore dynamicStore, String key) { @@ -799,9 +798,8 @@ public Map getAssetV2MapForTest() { /*************************** end asset ****************************************/ - public boolean addAllLatestAssetOperationTimeV2(Map map) { + public void addAllLatestAssetOperationTimeV2(Map map) { this.account = this.account.toBuilder().putAllLatestAssetOperationTimeV2(map).build(); - return true; } public Map getLatestAssetOperationTimeMap() { @@ -1097,9 +1095,8 @@ public void setFreeNetUsage(long freeNetUsage) { this.account = this.account.toBuilder().setFreeNetUsage(freeNetUsage).build(); } - public boolean addAllFreeAssetNetUsageV2(Map map) { + public void addAllFreeAssetNetUsageV2(Map map) { this.account = this.account.toBuilder().putAllFreeAssetNetUsageV2(map).build(); - return true; } public long getFreeAssetNetUsage(String assetName) { diff --git a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java index b33e47a2406..e731eb76c82 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java @@ -76,17 +76,17 @@ public long getFrozenBalanceForBandwidth() { return this.delegatedResource.getFrozenBalanceForBandwidth(); } - public void setFrozenBalanceForBandwidth(long Bandwidth, long expireTime) { + public void setFrozenBalanceForBandwidth(long bandwidth, long expireTime) { this.delegatedResource = this.delegatedResource.toBuilder() - .setFrozenBalanceForBandwidth(Bandwidth) + .setFrozenBalanceForBandwidth(bandwidth) .setExpireTimeForBandwidth(expireTime) .build(); } - public void addFrozenBalanceForBandwidth(long Bandwidth, long expireTime) { + public void addFrozenBalanceForBandwidth(long bandwidth, long expireTime) { this.delegatedResource = this.delegatedResource.toBuilder() .setFrozenBalanceForBandwidth(this.delegatedResource.getFrozenBalanceForBandwidth() - + Bandwidth) + + bandwidth) .setExpireTimeForBandwidth(expireTime) .build(); } @@ -99,9 +99,9 @@ public long getExpireTimeForEnergy() { return this.delegatedResource.getExpireTimeForEnergy(); } - public void setExpireTimeForBandwidth(long ExpireTime) { + public void setExpireTimeForBandwidth(long expireTime) { this.delegatedResource = this.delegatedResource.toBuilder() - .setExpireTimeForBandwidth(ExpireTime) + .setExpireTimeForBandwidth(expireTime) .build(); } @@ -113,9 +113,9 @@ public long getExpireTimeForEnergy(DynamicPropertiesStore dynamicPropertiesStore } } - public void setExpireTimeForEnergy(long ExpireTime) { + public void setExpireTimeForEnergy(long expireTime) { this.delegatedResource = this.delegatedResource.toBuilder() - .setExpireTimeForEnergy(ExpireTime) + .setExpireTimeForEnergy(expireTime) .build(); } diff --git a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java index c98b553ba3f..64d13a6e75a 100644 --- a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -36,7 +36,6 @@ public BandwidthProcessor(ChainBaseManager chainBaseManager) { this.chainBaseManager = chainBaseManager; } - @Override public void updateUsage(AccountCapsule accountCapsule) { long now = chainBaseManager.getHeadSlot(); updateUsage(accountCapsule, now); @@ -61,8 +60,7 @@ private void updateUsage(AccountCapsule accountCapsule, long now) { }); } Map assetMapV2 = accountCapsule.getAssetMapV2(); - Map map = new HashMap<>(); - map.putAll(assetMapV2); + Map map = new HashMap<>(assetMapV2); accountCapsule.getAllFreeAssetNetUsageV2().forEach((k, v) -> { if (!map.containsKey(k)) { map.put(k, 0L); diff --git a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java index beca72fad63..f302318e723 100644 --- a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java @@ -31,7 +31,6 @@ public static long getHeadSlot(DynamicPropertiesStore dynamicPropertiesStore) { / BLOCK_PRODUCED_INTERVAL; } - @Override public void updateUsage(AccountCapsule accountCapsule) { long now = getHeadSlot(); updateUsage(accountCapsule, now); diff --git a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java index eb0ab0eba7a..c3a0b56221a 100644 --- a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java @@ -33,8 +33,6 @@ public ResourceProcessor(DynamicPropertiesStore dynamicPropertiesStore, AdaptiveResourceLimitConstants.PERIODS_MS / BLOCK_PRODUCED_INTERVAL; } - abstract void updateUsage(AccountCapsule accountCapsule); - abstract void consume(TransactionCapsule trx, TransactionTrace trace) throws ContractValidateException, AccountResourceInsufficientException, TooBigTransactionResultException; @@ -63,12 +61,10 @@ protected long increase(long lastUsage, long usage, long lastTime, long now, lon public long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, long lastUsage, long usage, long lastTime, long now) { long oldWindowSize = accountCapsule.getWindowSize(resourceCode); - /* old logic */ long averageLastUsage = divideCeil(lastUsage * this.precision, oldWindowSize); long averageUsage = divideCeil(usage * this.precision, this.windowSize); if (lastTime != now) { - assert now > lastTime; if (lastTime + oldWindowSize > now) { long delta = now - lastTime; double decay = (oldWindowSize - delta) / (double) oldWindowSize; @@ -77,7 +73,7 @@ public long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, averageLastUsage = 0; } } - /* new logic */ + long newUsage = getUsage(averageLastUsage, oldWindowSize) + getUsage(averageUsage, this.windowSize); if (dynamicPropertiesStore.supportUnfreezeDelay()) { @@ -150,7 +146,6 @@ protected boolean consumeFeeForBandwidth(AccountCapsule accountCapsule, long fee } } - protected boolean consumeFeeForNewAccount(AccountCapsule accountCapsule, long fee) { try { long latestOperationTime = dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index d4bff49fea3..aa8143c57cb 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -344,13 +344,9 @@ public Account getAccount(Account account) { private void sortFrozenV2List(AccountCapsule accountCapsule) { List oldFreezeV2List = accountCapsule.getFrozenV2List(); accountCapsule.clearFrozenV2(); - ResourceCode[] codes = ResourceCode.values(); - for (ResourceCode code : codes) { + for (ResourceCode code : ResourceCode.values()) { if (ResourceCode.UNRECOGNIZED != code) { - accountCapsule.addFrozenV2List(FreezeV2.newBuilder() - .setType(code) - .setAmount(0) - .build()); + accountCapsule.addFrozenV2List(FreezeV2.newBuilder().setType(code).setAmount(0).build()); } } List newFreezeV2List = accountCapsule.getFrozenV2List(); @@ -359,7 +355,9 @@ private void sortFrozenV2List(AccountCapsule accountCapsule) { ResourceCode code = freezeV2.getType(); Optional optional = oldFreezeV2List .stream().filter(o -> o.getType() == code).findFirst(); - accountCapsule.updateFrozenV2List(i, optional.orElse(freezeV2)); + if (optional.isPresent()) { + accountCapsule.updateFrozenV2List(i, optional.get()); + } } } diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java index 565ce922572..a25bedc577d 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java @@ -35,8 +35,10 @@ import org.tron.protos.contract.AssetIssueContractOuterClass.ParticipateAssetIssueContract; import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; import org.tron.protos.contract.AssetIssueContractOuterClass.UnfreezeAssetContract; +import org.tron.protos.contract.BalanceContract.DelegateResourceContract; import org.tron.protos.contract.BalanceContract.FreezeBalanceContract; import org.tron.protos.contract.BalanceContract.TransferContract; +import org.tron.protos.contract.BalanceContract.UnDelegateResourceContract; import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; import org.tron.protos.contract.ExchangeContract.ExchangeInjectContract; import org.tron.protos.contract.ExchangeContract.ExchangeTransactionContract; @@ -114,7 +116,7 @@ public static byte[] getToAddress(Transaction transaction) { if (!toAddressList.isEmpty()) { return toAddressList.get(0).toByteArray(); } else { - return null; + return new byte[0]; } } @@ -158,6 +160,20 @@ public static List getTo(Transaction transaction) { list.add(receiverAddress); } break; + case DelegateResourceContract: + receiverAddress = contractParameter.unpack(DelegateResourceContract.class) + .getReceiverAddress(); + if (!receiverAddress.isEmpty()) { + list.add(receiverAddress); + } + break; + case UnDelegateResourceContract: + receiverAddress = contractParameter.unpack(UnDelegateResourceContract.class) + .getReceiverAddress(); + if (!receiverAddress.isEmpty()) { + list.add(receiverAddress); + } + break; case TriggerSmartContract: list.add(contractParameter.unpack(TriggerSmartContract.class).getContractAddress()); break; @@ -205,7 +221,7 @@ public static long getTransactionAmount(Transaction.Contract contract, String ha amount = getAmountFromTransactionInfo(hash, contract.getType(), transactionInfo); break; default: - amount = getTransactionAmount(contract, hash, 0, null, wallet); + amount = getTransactionAmount(contract, hash, null, wallet); break; } } catch (Exception e) { @@ -217,7 +233,7 @@ public static long getTransactionAmount(Transaction.Contract contract, String ha } public static long getTransactionAmount(Transaction.Contract contract, String hash, - long blockNum, TransactionInfo transactionInfo, Wallet wallet) { + TransactionInfo transactionInfo, Wallet wallet) { long amount = 0; try { Any contractParameter = contract.getParameter(); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java b/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java index 5dd46d71235..389c58505cd 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java @@ -137,8 +137,8 @@ public TransactionResult(BlockCapsule blockCapsule, int index, Protocol.Transact public TransactionResult(Transaction tx, Wallet wallet) { TransactionCapsule capsule = new TransactionCapsule(tx); - byte[] txid = capsule.getTransactionId().getBytes(); - hash = ByteArray.toJsonHex(txid); + byte[] txId = capsule.getTransactionId().getBytes(); + hash = ByteArray.toJsonHex(txId); nonce = ByteArray.toJsonHex(new byte[8]); // no value blockHash = "0x"; blockNumber = "0x"; diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java index 07d7f3a6def..d1aa0820c6e 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java @@ -43,7 +43,6 @@ public class UnfreezeBalanceV2ActuatorTest { private static final String OWNER_ACCOUNT_INVALID; private static final long initBalance = 10_000_000_000L; private static final long frozenBalance = 1_000_000_000L; - private static final long smallTatalResource = 100L; private static Manager dbManager; private static TronApplicationContext context; @@ -541,7 +540,7 @@ public void testUnfreezeBalanceForTronPowerWithOldTronPowerAfterNewResourceModel try { actuator.validate(); //Assert.fail(); - } catch (ContractValidateException e) { + } catch (Exception e) { Assert.assertTrue(e instanceof ContractValidateException); } } @@ -566,15 +565,15 @@ public void testUnfreezeBalanceCheckExistFreezedBalance() { actuator.setChainBaseManager(dbManager.getChainBaseManager()) .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); - boolean bret1 = actuator.checkExistFreezedBalance( + boolean bret1 = actuator.checkExistFrozenBalance( accountCapsule, ResourceCode.BANDWIDTH); - Assert.assertTrue(true == bret1); - boolean bret2 = actuator.checkExistFreezedBalance( + Assert.assertTrue(bret1); + boolean bret2 = actuator.checkExistFrozenBalance( accountCapsule, ResourceCode.ENERGY); - Assert.assertTrue(true == bret2); - boolean bret3 = actuator.checkExistFreezedBalance( + Assert.assertTrue(bret2); + boolean bret3 = actuator.checkExistFrozenBalance( accountCapsule, ResourceCode.TRON_POWER); - Assert.assertTrue(true == bret3); + Assert.assertTrue(bret3); } @@ -603,7 +602,7 @@ public void testUnfreezeBalanceCheckUnfreezeBalance() { boolean bret1 = actuator.checkUnfreezeBalance( accountCapsule, unfreezeBalanceV2Contract, ResourceCode.BANDWIDTH ); - Assert.assertTrue(true == bret1); + Assert.assertTrue(bret1); } @@ -633,7 +632,7 @@ public void testUnfreezeBalanceGetFreezeType() { ResourceCode freezeType = unfreezeBalanceV2Contract.getResource(); - Assert.assertTrue(ResourceCode.TRON_POWER.equals(freezeType)); + Assert.assertEquals(ResourceCode.TRON_POWER, freezeType); } @Test @@ -695,7 +694,7 @@ public void testUnfreezeBalanceUpdateAccountFrozenInfo() { ResourceCode.BANDWIDTH, accountCapsule, unfreezeBalance ); - Assert.assertTrue(accountCapsule.getAllFrozenBalanceForBandwidth() == 1); + Assert.assertEquals(1, accountCapsule.getAllFrozenBalanceForBandwidth()); } diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 632dcc157ce..38d94e8b63b 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -474,7 +474,7 @@ message TransactionInfo { repeated MarketOrderDetail orderDetails = 26; int64 packingFee = 27; - int64 withdraw_Expire_amount = 28; + int64 withdraw_expire_amount = 28; } message TransactionRet { From 9f9780d2345f99a3d5633e406540dc9d184bf315 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 21 Nov 2022 12:30:12 +0800 Subject: [PATCH 0428/1197] feat(net): optimize the logic of generating hello message --- .../org/tron/core/net/service/handshake/HandshakeService.java | 1 + .../main/java/org/tron/core/net/service/relay/RelayService.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java index d0ece8734d6..7b19c9dd3d5 100644 --- a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -111,6 +111,7 @@ private void sendHelloMessage(PeerConnection peer, long time) { TronNetService.getP2pConfig().getIp(), TronNetService.getP2pConfig().getPort()); HelloMessage message = new HelloMessage(node, time, ChainBaseManager.getChainBaseManager()); + relayService.fillHelloMessage(message, peer.getChannel()); peer.sendMessage(message); peer.setHelloMessageSend(message); } diff --git a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java index 46f3b5c7374..ec231809ea5 100644 --- a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java @@ -100,7 +100,7 @@ public void init() { public void fillHelloMessage(HelloMessage message, Channel channel) { if (isActiveWitness()) { fastForwardNodes.forEach(address -> { - if (address.equals(channel.getInetAddress())) { + if (address.getAddress().equals(channel.getInetAddress())) { SignInterface cryptoEngine = SignUtils .fromPrivate(ByteArray.fromHexString(Args.getLocalWitnesses().getPrivateKey()), Args.getInstance().isECKeyCryptoEngine()); From adfa2525b637f494d039c9c47e3bb6d10d00f510 Mon Sep 17 00:00:00 2001 From: liukai Date: Mon, 21 Nov 2022 16:36:05 +0800 Subject: [PATCH 0429/1197] update a new version. version name:GreatVoyage-v4.5.2-125-ga2906563d,version code:17198 --- framework/src/main/java/org/tron/program/Version.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 93ee7a52818..47e0426aa47 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,8 +2,8 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.5.1-125-ga9809b5bb"; - public static final String VERSION_CODE = "17071"; + public static final String VERSION_NAME = "GreatVoyage-v4.5.2-125-ga2906563d"; + public static final String VERSION_CODE = "17198"; private static final String VERSION = "4.6.0"; public static String getVersion() { From 4ad5f0ebb11cdf5bc034b93c7bef3e6ee5e27ad1 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 21 Nov 2022 20:12:52 +0800 Subject: [PATCH 0430/1197] feat(net): modify hello message toString function --- .../tron/core/net/P2pEventHandlerImpl.java | 2 +- .../net/message/handshake/HelloMessage.java | 22 ++++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java index d19134b62ae..6a164d774da 100644 --- a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java +++ b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java @@ -119,7 +119,7 @@ public void onMessage(Channel c, byte[] data) { pbftMsgHandler.processMessage(peerConnection, message); } catch (Exception e) { logger.warn("PBFT Message from {} process failed, {}", - peerConnection.getInetSocketAddress(), message, e); + peerConnection.getInetSocketAddress(), message, e.getMessage()); peerConnection.disconnect(Protocol.ReasonCode.BAD_PROTOCOL); } return; diff --git a/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java b/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java index 01cf19b2a0b..d4ed7282386 100755 --- a/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import lombok.Getter; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.StringUtil; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; @@ -128,13 +129,28 @@ public Class getAnswerMessage() { @Override public String toString() { - return new StringBuilder().append(super.toString()) + StringBuilder builder = new StringBuilder(); + + builder.append(super.toString()) .append("from: ").append(getFrom().getInetSocketAddress()).append("\n") .append("timestamp: ").append(getTimestamp()).append("\n") .append("headBlockId: ").append(getHeadBlockId().getString()).append("\n") .append("nodeType: ").append(helloMessage.getNodeType()).append("\n") - .append("lowestBlockNum: ").append(helloMessage.getLowestBlockNum()).append("\n") - .toString(); + .append("lowestBlockNum: ").append(helloMessage.getLowestBlockNum()).append("\n"); + + ByteString address = helloMessage.getAddress(); + if (address != null && !address.isEmpty()) { + builder.append("address:") + .append(StringUtil.encode58Check(address.toByteArray())).append("\n"); + } + + ByteString signature = helloMessage.getSignature(); + if (signature != null && !signature.isEmpty()) { + builder.append("signature:") + .append(signature.toByteArray().length).append("\n"); + } + + return builder.toString(); } public Protocol.HelloMessage getInstance() { From 8ebf5930f71510dbad00710dbe4aedac00d2347d Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 22 Nov 2022 11:10:52 +0800 Subject: [PATCH 0431/1197] feat(net): enable the message forwarding function --- .../src/main/java/org/tron/core/net/TronNetService.java | 6 ++++++ .../java/org/tron/core/net/service/relay/RelayService.java | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index e036dd062d1..3c9554d79fa 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -19,6 +19,7 @@ import org.tron.core.net.service.fetchblock.FetchBlockService; import org.tron.core.net.service.keepalive.KeepAliveService; import org.tron.core.net.service.nodepersist.NodePersistService; +import org.tron.core.net.service.relay.RelayService; import org.tron.core.net.service.statistics.TronStatsManager; import org.tron.core.net.service.sync.SyncService; import org.tron.p2p.P2pConfig; @@ -63,6 +64,9 @@ public class TronNetService { @Autowired private TronStatsManager tronStatsManager; + @Autowired + private RelayService relayService; + private volatile boolean init; private static void setP2pConfig(P2pConfig config) { @@ -84,6 +88,7 @@ public void start() { nodePersistService.init(); tronStatsManager.init(); PeerManager.init(); + relayService.init(); logger.info("Net service start successfully"); } catch (Exception e) { logger.error("Net service start failed", e); @@ -104,6 +109,7 @@ public void close() { transactionsMsgHandler.close(); fetchBlockService.close(); p2pService.close(); + relayService.close(); logger.info("Net service closed successfully"); } diff --git a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java index ec231809ea5..380f097361b 100644 --- a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java @@ -97,6 +97,10 @@ public void init() { }, 30, 100, TimeUnit.SECONDS); } + public void close() { + executorService.shutdown(); + } + public void fillHelloMessage(HelloMessage message, Channel channel) { if (isActiveWitness()) { fastForwardNodes.forEach(address -> { From d3d53d906a614541e7c5bd8adc00d1d218ed6f05 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 22 Nov 2022 11:51:33 +0800 Subject: [PATCH 0432/1197] fix(net): solve p2p configuration initialization problem --- .../main/java/org/tron/core/net/service/relay/RelayService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java index 380f097361b..7dc75ec89a0 100644 --- a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java @@ -49,7 +49,7 @@ public class RelayService { @Autowired private ApplicationContext ctx; - private P2pConfig p2pConfig; + private P2pConfig p2pConfig = TronNetService.getP2pConfig(); private Manager manager; From 7c8fc3b86d8455eed9ac8b3c188d816fc49e1d30 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 22 Nov 2022 12:22:18 +0800 Subject: [PATCH 0433/1197] fix(net): solve p2p configuration initialization problem --- .../org/tron/core/net/service/relay/RelayService.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java index 7dc75ec89a0..478f0714875 100644 --- a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java @@ -49,8 +49,6 @@ public class RelayService { @Autowired private ApplicationContext ctx; - private P2pConfig p2pConfig = TronNetService.getP2pConfig(); - private Manager manager; private WitnessScheduleStore witnessScheduleStore; @@ -155,7 +153,7 @@ public boolean checkHelloMessage(HelloMessage message, Channel channel) { flag = Arrays.equals(sigAddress, witnessPermissionAddress); } if (flag) { - p2pConfig.getTrustNodes().add(channel.getInetAddress()); + TronNetService.getP2pConfig().getTrustNodes().add(channel.getInetAddress()); } return flag; } catch (Exception e) { @@ -173,12 +171,13 @@ private boolean isActiveWitness() { } private void connect() { - fastForwardNodes.forEach(address -> p2pConfig.getActiveNodes().add(address)); + fastForwardNodes.forEach(address -> + TronNetService.getP2pConfig().getActiveNodes().add(address)); } private void disconnect() { fastForwardNodes.forEach(address -> { - p2pConfig.getActiveNodes().remove(address); + TronNetService.getP2pConfig().getActiveNodes().remove(address); TronNetService.getPeers().forEach(peer -> { if (peer.getInetAddress().equals(address.getAddress())) { peer.getChannel().close(); From 4d07ef958a7419557e1c8b8a25f2d5868629f854 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Wed, 16 Nov 2022 17:25:00 +0800 Subject: [PATCH 0434/1197] fix(git): fix build failure issue 1. Fix build fails before git repo initialization for projects. --- framework/build.gradle | 2 ++ .../src/main/java/org/tron/core/config/args/Args.java | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/framework/build.gradle b/framework/build.gradle index 7df08a90eb9..329f0e6d265 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -3,6 +3,8 @@ plugins { id "com.gorylenko.gradle-git-properties" version "2.4.1" } +gitProperties.failOnNoGitDirectory = false; + apply plugin: 'application' apply plugin: 'checkstyle' diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index a64560573b3..7311f94a80d 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -224,17 +224,23 @@ public static void clearParam() { */ private static void printVersion() { Properties properties = new Properties(); + boolean noGitProperties = true; try { InputStream in = Thread.currentThread() .getContextClassLoader().getResourceAsStream("git.properties"); - properties.load(in); + if (in != null) { + noGitProperties = false; + properties.load(in); + } } catch (IOException e) { logger.error(e.getMessage()); } JCommander.getConsole().println("OS : " + System.getProperty("os.name")); JCommander.getConsole().println("JVM : " + System.getProperty("java.vendor") + " " + System.getProperty("java.version") + " " + System.getProperty("os.arch")); - JCommander.getConsole().println("Git : " + properties.getProperty("git.commit.id")); + if (!noGitProperties) { + JCommander.getConsole().println("Git : " + properties.getProperty("git.commit.id")); + } JCommander.getConsole().println("Version : " + Version.getVersion()); JCommander.getConsole().println("Code : " + Version.VERSION_CODE); } From 0d398159b1ab130edb8fe1efda93f4c3fb807577 Mon Sep 17 00:00:00 2001 From: guoquanwu Date: Wed, 23 Nov 2022 11:55:44 +0800 Subject: [PATCH 0435/1197] fix(db): the operation of putting byte[0] should be reserved instead of deleting --- .../java/org/tron/tool/litefullnode/LiteFullNodeTool.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java index ad32214840e..206ce1d6df2 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java @@ -31,6 +31,7 @@ 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; @@ -232,6 +233,12 @@ private void recover(DBInterface db, String destDir, List destDbs) destDb.put(realKey, realValue); } else { destDb.delete(realKey); + byte op = value[0]; + if (Value.Operator.DELETE.getValue() == op) { + destDb.delete(realKey); + } else { + destDb.put(realKey, new byte[0]); + } } } } From aee866556f516c624aa00e0ee520f93f009939af Mon Sep 17 00:00:00 2001 From: guoquanwu Date: Wed, 23 Nov 2022 11:57:30 +0800 Subject: [PATCH 0436/1197] fix(db): the operation of putting byte[0] should be reserved instead of deleting --- .../main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java index 206ce1d6df2..bec69227c52 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java @@ -232,7 +232,6 @@ private void recover(DBInterface db, String destDir, List destDbs) if (realValue != null) { destDb.put(realKey, realValue); } else { - destDb.delete(realKey); byte op = value[0]; if (Value.Operator.DELETE.getValue() == op) { destDb.delete(realKey); From 217469db15023936d19c043ed3999049366830f9 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 1 Nov 2022 17:46:08 +0800 Subject: [PATCH 0437/1197] feat(block): improve performance for transaction packing 1. remove unused code 2. optimize cycle operation --- .../org/tron/core/capsule/BlockCapsule.java | 7 ++++ .../core/capsule/TransactionRetCapsule.java | 7 +++- .../main/java/org/tron/core/db/Manager.java | 39 ++++++++++--------- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java index 5979ae5bf83..4853de64116 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java @@ -143,6 +143,13 @@ public void addTransaction(TransactionCapsule pendingTrx) { getTransactions().add(pendingTrx); } + public void addAllTransactions(List pendingTrxs) { + List list = pendingTrxs.stream().map(TransactionCapsule::getInstance).collect( + Collectors.toList()); + this.block = this.block.toBuilder().addAllTransactions(list).build(); + getTransactions().addAll(pendingTrxs); + } + public List getTransactions() { return transactions; } diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionRetCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionRetCapsule.java index 499cbcb3b42..94188229d98 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionRetCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionRetCapsule.java @@ -1,6 +1,7 @@ package org.tron.core.capsule; import com.google.protobuf.InvalidProtocolBufferException; +import java.util.List; import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.tron.core.exception.BadItemException; @@ -29,7 +30,7 @@ public TransactionRetCapsule() { public TransactionRetCapsule(byte[] data) throws BadItemException { try { - this.transactionRet = transactionRet.parseFrom(data); + this.transactionRet = TransactionRet.parseFrom(data); } catch (InvalidProtocolBufferException e) { throw new BadItemException("TransactionInfoCapsule proto data parse exception"); } @@ -39,6 +40,10 @@ public void addTransactionInfo(TransactionInfo result) { this.transactionRet = this.transactionRet.toBuilder().addTransactioninfo(result).build(); } + public void addAllTransactionInfos(List results) { + this.transactionRet = this.transactionRet.toBuilder().addAllTransactioninfo(results).build(); + } + @Override public byte[] getData() { if (Objects.isNull(transactionRet)) { diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index a9d11133866..ebc1eb60a38 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1470,16 +1470,17 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { } } - TransactionRetCapsule transactionRetCapsule = new TransactionRetCapsule(blockCapsule); - Set accountSet = new HashSet<>(); AtomicInteger shieldedTransCounts = new AtomicInteger(0); + List toBePacked = new ArrayList<>(); + long currentSize = blockCapsule.getInstance().getSerializedSize(); + boolean isSort = Args.getInstance().isOpenTransactionSort(); while (pendingTransactions.size() > 0 || rePushTransactions.size() > 0) { boolean fromPending = false; TransactionCapsule trx; if (pendingTransactions.size() > 0) { trx = pendingTransactions.peek(); - if (Args.getInstance().isOpenTransactionSort()) { + if (isSort) { TransactionCapsule trxRepush = rePushTransactions.peek(); if (trxRepush == null || trx.getOrder() >= trxRepush.getOrder()) { fromPending = true; @@ -1516,13 +1517,14 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { } // check the block size - if ((blockCapsule.getInstance().getSerializedSize() + trx.getSerializedSize() + 3) + if ((currentSize + trx.getSerializedSize() + 3) > ChainConstant.BLOCK_SIZE) { postponedTrxCount++; - continue; + continue; // try pack more small trx } //shielded transaction - if (isShieldedTransaction(trx.getInstance()) + Transaction transaction = trx.getInstance(); + if (isShieldedTransaction(transaction) && shieldedTransCounts.incrementAndGet() > SHIELDED_TRANS_IN_BLOCK_COUNTS) { continue; } @@ -1532,7 +1534,7 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { if (accountSet.contains(ownerAddress)) { continue; } else { - if (isMultiSignTransaction(trx.getInstance())) { + if (isMultiSignTransaction(transaction)) { accountSet.add(ownerAddress); } } @@ -1542,27 +1544,25 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { // apply transaction try (ISession tmpSession = revokingStore.buildSession()) { accountStateCallBack.preExeTrans(); - TransactionInfo result = processTransaction(trx, blockCapsule); + processTransaction(trx, blockCapsule); accountStateCallBack.exeTransFinish(); tmpSession.merge(); - blockCapsule.addTransaction(trx); - if (Objects.nonNull(result)) { - transactionRetCapsule.addTransactionInfo(result); - } + toBePacked.add(trx); + currentSize += trx.getSerializedSize() + 2; // proto tag num is 1 , so tag size is 2 } catch (Exception e) { logger.error("Process trx {} failed when generating block {}, {}.", trx.getTransactionId(), blockCapsule.getNum(), e.getMessage()); } } - + blockCapsule.addAllTransactions(toBePacked); accountStateCallBack.executeGenerateFinish(); session.reset(); - logger.info("Generate block {} success, trxs: {}, pendingCount: {}, rePushCount: {}," - + " postponedCount: {}.", + logger.info("Generate block {} success, trxs:{}, pendingCount: {}, rePushCount: {}," + + " postponedCount: {}, blockSize: {} B", blockCapsule.getNum(), blockCapsule.getTransactions().size(), - pendingTransactions.size(), rePushTransactions.size(), postponedTrxCount); + pendingTransactions.size(), rePushTransactions.size(), postponedTrxCount, currentSize); blockCapsule.setMerkleRoot(); blockCapsule.sign(miner.getPrivateKey()); @@ -1654,8 +1654,10 @@ private void processBlock(BlockCapsule block, List txs) try { merkleContainer.resetCurrentMerkleTree(); accountStateCallBack.preExecute(block); + List results = new ArrayList<>(); + long num = block.getNum(); for (TransactionCapsule transactionCapsule : block.getTransactions()) { - transactionCapsule.setBlockNum(block.getNum()); + transactionCapsule.setBlockNum(num); if (block.generatedByMyself) { transactionCapsule.setVerified(true); } @@ -1663,9 +1665,10 @@ private void processBlock(BlockCapsule block, List txs) TransactionInfo result = processTransaction(transactionCapsule, block); accountStateCallBack.exeTransFinish(); if (Objects.nonNull(result)) { - transactionRetCapsule.addTransactionInfo(result); + results.add(result); } } + transactionRetCapsule.addAllTransactionInfos(results); accountStateCallBack.executePushFinish(); } finally { accountStateCallBack.exceptionFinish(); From 74ec8167e2195c4cfdaed32f149f7438825200d5 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 1 Nov 2022 17:49:22 +0800 Subject: [PATCH 0438/1197] feat(db): improve performance for db query 1. add cache for db --- .../java/org/tron/core/db2/common/DB.java | 2 +- .../tron/core/db2/core/AbstractSnapshot.java | 7 -- .../java/org/tron/core/db2/core/Snapshot.java | 2 - .../org/tron/core/db2/core/SnapshotImpl.java | 14 --- .../org/tron/core/db2/core/SnapshotRoot.java | 64 +++++++++++-- .../tron/core/service/MortgageService.java | 38 ++------ .../org/tron/core/store/WitnessStore.java | 40 +++++++++ .../org/tron/common/cache/CacheManager.java | 44 +++++++++ .../tron/common/cache/CacheStrategies.java | 70 +++++++++++++++ .../java/org/tron/common/cache/CacheType.java | 46 ++++++++++ .../java/org/tron/common/cache/TronCache.java | 64 +++++++++++++ .../common/prometheus/GuavaCacheExports.java | 89 +++++++++++++++++++ .../org/tron/common/prometheus/Metrics.java | 1 + .../tron/common/utils/DbOptionalsUtils.java | 14 +-- .../org/tron/core/config/args/Storage.java | 26 ++++++ .../org/tron/consensus/ConsensusDelegate.java | 4 + .../consensus/dpos/MaintenanceManager.java | 4 +- .../java/org/tron/core/config/args/Args.java | 1 + .../tron/core/config/args/StorageTest.java | 2 +- 19 files changed, 458 insertions(+), 74 deletions(-) create mode 100644 common/src/main/java/org/tron/common/cache/CacheManager.java create mode 100644 common/src/main/java/org/tron/common/cache/CacheStrategies.java create mode 100644 common/src/main/java/org/tron/common/cache/CacheType.java create mode 100644 common/src/main/java/org/tron/common/cache/TronCache.java create mode 100644 common/src/main/java/org/tron/common/prometheus/GuavaCacheExports.java diff --git a/chainbase/src/main/java/org/tron/core/db2/common/DB.java b/chainbase/src/main/java/org/tron/core/db2/common/DB.java index fed5e52bb04..eae529c5ca9 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/DB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/DB.java @@ -15,7 +15,7 @@ public interface DB extends Iterable>, Instance> void remove(K k); - Iterator iterator(); + Iterator> iterator(); void close(); diff --git a/chainbase/src/main/java/org/tron/core/db2/core/AbstractSnapshot.java b/chainbase/src/main/java/org/tron/core/db2/core/AbstractSnapshot.java index ba6c77d43a2..496a0fd09ac 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/AbstractSnapshot.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/AbstractSnapshot.java @@ -15,8 +15,6 @@ public abstract class AbstractSnapshot implements Snapshot { protected WeakReference next; - protected boolean isOptimized; - @Override public Snapshot advance() { return new SnapshotImpl(this); @@ -36,9 +34,4 @@ public void setNext(Snapshot next) { public String getDbName() { return db.getDbName(); } - - @Override - public boolean isOptimized(){ - return isOptimized; - } } diff --git a/chainbase/src/main/java/org/tron/core/db2/core/Snapshot.java b/chainbase/src/main/java/org/tron/core/db2/core/Snapshot.java index db59713f34d..e1ca149b207 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/Snapshot.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/Snapshot.java @@ -46,6 +46,4 @@ static boolean isImpl(Snapshot snapshot) { void updateSolidity(); String getDbName(); - - boolean isOptimized(); } diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotImpl.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotImpl.java index 83c55c238ea..ae8073f668b 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotImpl.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotImpl.java @@ -30,16 +30,6 @@ public class SnapshotImpl extends AbstractSnapshot { } previous = snapshot; snapshot.setNext(this); - // inherit - isOptimized = snapshot.isOptimized(); - // merge for DynamicPropertiesStore,about 100 keys - if (isOptimized) { - if (root == previous ){ - Streams.stream(root.iterator()).forEach( e -> put(e.getKey(),e.getValue())); - }else { - merge(previous); - } - } } @Override @@ -50,10 +40,6 @@ public byte[] get(byte[] key) { private byte[] get(Snapshot head, byte[] key) { Snapshot snapshot = head; Value value; - if (isOptimized) { - value = db.get(Key.of(key)); - return value == null ? null: value.getBytes(); - } while (Snapshot.isImpl(snapshot)) { if ((value = ((SnapshotImpl) snapshot).db.get(Key.of(key))) != null) { return value.getBytes(); diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java index 9afb5277b9c..709e2ae1b62 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java @@ -1,14 +1,18 @@ package org.tron.core.db2.core; -import ch.qos.logback.core.encoder.ByteArrayUtil; import com.google.common.collect.Maps; import com.google.common.collect.Streams; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; import lombok.Getter; +import org.tron.common.cache.CacheManager; +import org.tron.common.cache.CacheType; +import org.tron.common.cache.TronCache; +import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.core.ChainBaseManager; import org.tron.core.capsule.AccountCapsule; @@ -23,11 +27,17 @@ public class SnapshotRoot extends AbstractSnapshot { private Snapshot solidity; private boolean isAccountDB; + private TronCache cache; + private static final List CACHE_DBS = CommonParameter.getInstance() + .getStorage().getCacheDbs(); + public SnapshotRoot(DB db) { this.db = db; solidity = this; - isOptimized = "properties".equalsIgnoreCase(db.getDbName()); isAccountDB = "account".equalsIgnoreCase(db.getDbName()); + if (CACHE_DBS.contains(this.db.getDbName())) { + this.cache = CacheManager.allocate(CacheType.findByType(this.db.getDbName())); + } } private boolean needOptAsset() { @@ -37,11 +47,18 @@ private boolean needOptAsset() { @Override public byte[] get(byte[] key) { - return db.get(key); + WrappedByteArray cache = getCache(key); + if (cache != null) { + return cache.getBytes(); + } + byte[] value = db.get(key); + putCache(key, value); + return value; } @Override public void put(byte[] key, byte[] value) { + byte[] v = value; if (needOptAsset()) { if (ByteArray.isEmpty(value)) { remove(key); @@ -56,10 +73,10 @@ public void put(byte[] key, byte[] value) { } assetStore.putAccount(item.getInstance()); item.clearAsset(); - db.put(key, item.getData()); - } else { - db.put(key, value); + v = item.getData(); } + db.put(key, v); + putCache(key, v); } @Override @@ -68,6 +85,7 @@ public void remove(byte[] key) { ChainBaseManager.getInstance().getAccountAssetStore().deleteAccount(key); } db.remove(key); + putCache(key, null); } @Override @@ -81,6 +99,7 @@ public void merge(Snapshot from) { processAccount(batch); } else { ((Flusher) db).flush(batch); + putCache(batch); } } @@ -97,6 +116,7 @@ public void merge(List snapshots) { processAccount(batch); } else { ((Flusher) db).flush(batch); + putCache(batch); } } @@ -120,11 +140,37 @@ private void processAccount(Map batch) { } }); ((Flusher) db).flush(accounts); + putCache(accounts); if (assets.size() > 0) { assetStore.updateByBatch(AccountAssetStore.convert(assets)); } } + private boolean cached() { + return Objects.nonNull(this.cache); + } + + private void putCache(byte[] key, byte[] value) { + if (cached()) { + cache.put(WrappedByteArray.of(key), WrappedByteArray.of(value)); + } + } + + private void putCache(Map values) { + if (cached()) { + values.forEach(cache::put); + } + } + + private WrappedByteArray getCache(byte[] key) { + if (cached()) { + return cache.getIfPresent(WrappedByteArray.of(key)); + } + return null; + } + + // second cache + @Override public Snapshot retreat() { return this; @@ -142,11 +188,17 @@ public Iterator> iterator() { @Override public void close() { + if (cached()) { + CacheManager.release(cache); + } ((Flusher) db).close(); } @Override public void reset() { + if (cached()) { + CacheManager.release(cache); + } ((Flusher) db).reset(); } diff --git a/chainbase/src/main/java/org/tron/core/service/MortgageService.java b/chainbase/src/main/java/org/tron/core/service/MortgageService.java index 5dd99626930..e9b00a38201 100644 --- a/chainbase/src/main/java/org/tron/core/service/MortgageService.java +++ b/chainbase/src/main/java/org/tron/core/service/MortgageService.java @@ -1,14 +1,9 @@ package org.tron.core.service; import com.google.protobuf.ByteString; - import java.math.BigInteger; -import java.util.ArrayList; import java.util.Comparator; -import java.util.HashMap; import java.util.List; -import java.util.Map; - import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @@ -18,7 +13,6 @@ import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.Parameter.ChainConstant; import org.tron.core.exception.BalanceInsufficientException; import org.tron.core.store.AccountStore; import org.tron.core.store.DelegationStore; @@ -52,31 +46,17 @@ public void initStore(WitnessStore witnessStore, DelegationStore delegationStore } public void payStandbyWitness() { - List witnessCapsules = witnessStore.getAllWitnesses(); - Map witnessCapsuleMap = new HashMap<>(); - List witnessAddressList = new ArrayList<>(); - for (WitnessCapsule witnessCapsule : witnessCapsules) { - witnessAddressList.add(witnessCapsule.getAddress()); - witnessCapsuleMap.put(witnessCapsule.getAddress(), witnessCapsule); - } - witnessAddressList.sort(Comparator.comparingLong((ByteString b) -> witnessCapsuleMap.get(b).getVoteCount()) - .reversed().thenComparing(Comparator.comparingInt(ByteString::hashCode).reversed())); - if (witnessAddressList.size() > ChainConstant.WITNESS_STANDBY_LENGTH) { - witnessAddressList = witnessAddressList.subList(0, ChainConstant.WITNESS_STANDBY_LENGTH); + List witnessStandbys = witnessStore.getWitnessStandby(); + long voteSum = witnessStandbys.stream().mapToLong(WitnessCapsule::getVoteCount).sum(); + if (voteSum < 1) { + return; } - long voteSum = 0; long totalPay = dynamicPropertiesStore.getWitness127PayPerBlock(); - for (ByteString b : witnessAddressList) { - voteSum += witnessCapsuleMap.get(b).getVoteCount(); - } - - if (voteSum > 0) { - for (ByteString b : witnessAddressList) { - double eachVotePay = (double) totalPay / voteSum; - long pay = (long) (witnessCapsuleMap.get(b).getVoteCount() * eachVotePay); - logger.debug("Pay {} stand reward {}.", Hex.toHexString(b.toByteArray()), pay); - payReward(b.toByteArray(), pay); - } + double eachVotePay = (double) totalPay / voteSum; + for (WitnessCapsule w : witnessStandbys) { + long pay = (long) (w.getVoteCount() * eachVotePay); + payReward(w.getAddress().toByteArray(), pay); + logger.debug("Pay {} stand reward {}.", Hex.toHexString(w.getAddress().toByteArray()), pay); } } diff --git a/chainbase/src/main/java/org/tron/core/store/WitnessStore.java b/chainbase/src/main/java/org/tron/core/store/WitnessStore.java index 22324bca108..e01680cfc74 100644 --- a/chainbase/src/main/java/org/tron/core/store/WitnessStore.java +++ b/chainbase/src/main/java/org/tron/core/store/WitnessStore.java @@ -1,6 +1,8 @@ package org.tron.core.store; import com.google.common.collect.Streams; +import java.util.ArrayList; +import java.util.Comparator; import java.util.List; import java.util.Map.Entry; import java.util.stream.Collectors; @@ -9,16 +11,25 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import org.tron.common.cache.CacheManager; +import org.tron.common.cache.CacheStrategies; +import org.tron.common.cache.CacheType; +import org.tron.common.cache.TronCache; import org.tron.core.capsule.WitnessCapsule; +import org.tron.core.config.Parameter; import org.tron.core.db.TronStoreWithRevoking; @Slf4j(topic = "DB") @Component public class WitnessStore extends TronStoreWithRevoking { + // cache for 127 SR + private final TronCache> witnessStandbyCache; @Autowired protected WitnessStore(@Value("witness") String dbName) { super(dbName); + String strategy = String.format(CacheStrategies.PATTERNS, 1, 1, "30s", 1); + witnessStandbyCache = CacheManager.allocate(CacheType.witnessStandby, strategy); } /** @@ -35,4 +46,33 @@ public WitnessCapsule get(byte[] key) { byte[] value = revokingDB.getUnchecked(key); return ArrayUtils.isEmpty(value) ? null : new WitnessCapsule(value); } + + public List getWitnessStandby() { + List list = + witnessStandbyCache.getIfPresent(Parameter.ChainConstant.WITNESS_STANDBY_LENGTH); + if (list != null) { + return list; + } + return updateWitnessStandby(null); + } + + public List updateWitnessStandby(List all) { + List ret; + if (all == null) { + all = getAllWitnesses(); + } + all.sort(Comparator.comparingLong(WitnessCapsule::getVoteCount) + .reversed().thenComparing(Comparator.comparingInt( + (WitnessCapsule w) -> w.getAddress().hashCode()).reversed())); + if (all.size() > Parameter.ChainConstant.WITNESS_STANDBY_LENGTH) { + ret = new ArrayList<>(all.subList(0, Parameter.ChainConstant.WITNESS_STANDBY_LENGTH)); + } else { + ret = new ArrayList<>(all); + } + // trim voteCount = 0 + ret.removeIf(w -> w.getVoteCount() < 1); + witnessStandbyCache.put(Parameter.ChainConstant.WITNESS_STANDBY_LENGTH, ret); + return ret; + } + } diff --git a/common/src/main/java/org/tron/common/cache/CacheManager.java b/common/src/main/java/org/tron/common/cache/CacheManager.java new file mode 100644 index 00000000000..fa1fbff193b --- /dev/null +++ b/common/src/main/java/org/tron/common/cache/CacheManager.java @@ -0,0 +1,44 @@ +package org.tron.common.cache; + +import com.google.common.cache.CacheLoader; +import com.google.common.cache.CacheStats; +import com.google.common.collect.Maps; +import java.util.Map; +import java.util.stream.Collectors; +import org.tron.common.parameter.CommonParameter; + +public class CacheManager { + + private static final Map> CACHES = Maps.newConcurrentMap(); + + public static TronCache allocate(CacheType name) { + TronCache cache = new TronCache<>(name, CommonParameter.getInstance() + .getStorage().getCacheStrategy(name)); + CACHES.put(name, cache); + return cache; + } + + public static TronCache allocate(CacheType name, String strategy) { + TronCache cache = new TronCache<>(name, strategy); + CACHES.put(name, cache); + return cache; + } + + public static TronCache allocate(CacheType name, String strategy, + CacheLoader loader) { + TronCache cache = new TronCache<>(name, strategy, loader); + CACHES.put(name, cache); + return cache; + } + + + public static void release(TronCache cache) { + cache.invalidateAll(); + } + + public static Map stats() { + return CACHES.values().stream().collect(Collectors.toMap(c -> c.getName().toString(), + TronCache::stats)); + } + +} diff --git a/common/src/main/java/org/tron/common/cache/CacheStrategies.java b/common/src/main/java/org/tron/common/cache/CacheStrategies.java new file mode 100644 index 00000000000..b282ca1a687 --- /dev/null +++ b/common/src/main/java/org/tron/common/cache/CacheStrategies.java @@ -0,0 +1,70 @@ +package org.tron.common.cache; + +import static org.tron.common.cache.CacheType.abi; +import static org.tron.common.cache.CacheType.account; +import static org.tron.common.cache.CacheType.assetIssueV2; +import static org.tron.common.cache.CacheType.code; +import static org.tron.common.cache.CacheType.contract; +import static org.tron.common.cache.CacheType.delegatedResource; +import static org.tron.common.cache.CacheType.delegatedResourceAccountIndex; +import static org.tron.common.cache.CacheType.delegation; +import static org.tron.common.cache.CacheType.properties; +import static org.tron.common.cache.CacheType.recentBlock; +import static org.tron.common.cache.CacheType.storageRow; +import static org.tron.common.cache.CacheType.votes; +import static org.tron.common.cache.CacheType.witness; +import static org.tron.common.cache.CacheType.witnessSchedule; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class CacheStrategies { + + + public static final String PATTERNS = + "initialCapacity=%d,maximumSize=%d,expireAfterAccess=%s,concurrencyLevel=%d,recordStats"; + public static final List CACHE_BIG_DBS = Collections.singletonList(delegation); + private static final int CPUS = Runtime.getRuntime().availableProcessors(); + public static final String CACHE_STRATEGY_DEFAULT = + String.format(PATTERNS, 1000, 1000, "30s", CPUS); + private static final String CACHE_STRATEGY_SMALL_DEFAULT = + String.format(PATTERNS, 100, 100, "30s", CPUS); + private static final List CACHE_SMALL_DBS = Arrays.asList(recentBlock, witness, + witnessSchedule, delegatedResource, delegatedResourceAccountIndex, + votes, abi); + private static final String CACHE_STRATEGY_NORMAL_DEFAULT = + String.format(PATTERNS, 500, 500, "30s", CPUS); + private static final List CACHE_NORMAL_DBS = Arrays.asList(code, contract, + assetIssueV2, properties); + private static final String CACHE_STRATEGY_BIG_DEFAULT = + String.format(PATTERNS, 10000, 10000, "30s", CPUS); + private static final String CACHE_STRATEGY_HUGE_DEFAULT = + String.format(PATTERNS, 20000, 20000, "30s", CPUS); + private static final List CACHE_HUGE_DBS = Arrays.asList(storageRow, account); + + public static final List CACHE_DBS = Stream.of(CACHE_SMALL_DBS, CACHE_NORMAL_DBS, + CACHE_BIG_DBS, CACHE_HUGE_DBS).flatMap(Collection::stream).map(CacheType::toString) + .collect(Collectors.toList()); + + + public static String getCacheStrategy(CacheType dbName) { + String defaultStrategy = CACHE_STRATEGY_DEFAULT; + if (CACHE_SMALL_DBS.contains(dbName)) { + defaultStrategy = CACHE_STRATEGY_SMALL_DEFAULT; + } + if (CACHE_NORMAL_DBS.contains(dbName)) { + defaultStrategy = CACHE_STRATEGY_NORMAL_DEFAULT; + } + if (CACHE_BIG_DBS.contains(dbName)) { + defaultStrategy = CACHE_STRATEGY_BIG_DEFAULT; + } + if (CACHE_HUGE_DBS.contains(dbName)) { + defaultStrategy = CACHE_STRATEGY_HUGE_DEFAULT; + } + return defaultStrategy; + } +} diff --git a/common/src/main/java/org/tron/common/cache/CacheType.java b/common/src/main/java/org/tron/common/cache/CacheType.java new file mode 100644 index 00000000000..b9b28d0bd7c --- /dev/null +++ b/common/src/main/java/org/tron/common/cache/CacheType.java @@ -0,0 +1,46 @@ +package org.tron.common.cache; + +import java.util.Arrays; + +public enum CacheType { + // for 127 SR + witnessStandby("witnessStandby"), + // for leveldb or rocksdb cache + recentBlock("recent-block"), + witness("witness"), + witnessSchedule("witness_schedule"), + delegatedResource("DelegatedResource"), + delegatedResourceAccountIndex("DelegatedResourceAccountIndex"), + votes("votes"), + abi("abi"), + code("code"), + contract("contract"), + assetIssueV2("asset-issue-v2"), + properties("properties"), + delegation("delegation"), + storageRow("storage-row"), + account("account"); + // for leveldb or rocksdb cache + + public final String type; + + CacheType(String type) { + this.type = type; + } + + public static CacheType findByType(String type) { + return Arrays.stream(CacheType.values()).filter(c -> c.type.equals(type)).findFirst() + .orElseThrow(() -> new IllegalArgumentException(type)); + } + + @Override + public String toString() { + return type; + } + + + + + + +} diff --git a/common/src/main/java/org/tron/common/cache/TronCache.java b/common/src/main/java/org/tron/common/cache/TronCache.java new file mode 100644 index 00000000000..4faf73f864a --- /dev/null +++ b/common/src/main/java/org/tron/common/cache/TronCache.java @@ -0,0 +1,64 @@ +package org.tron.common.cache; + +import com.google.common.base.Objects; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.CacheStats; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import lombok.Getter; + +public class TronCache { + + @Getter + private final CacheType name; + private final Cache cache; + + TronCache(CacheType name, String strategy) { + this.name = name; + this.cache = CacheBuilder.from(strategy).build(); + } + + TronCache(CacheType name, String strategy, CacheLoader loader) { + this.name = name; + this.cache = CacheBuilder.from(strategy).build(loader); + } + + public void put(K k, V v) { + this.cache.put(k, v); + } + + public V getIfPresent(K k) { + return this.cache.getIfPresent(k); + } + + public V get(K k, Callable loader) throws ExecutionException { + return this.cache.get(k, loader); + } + + public CacheStats stats() { + return this.cache.stats(); + } + + public void invalidateAll() { + this.cache.invalidateAll(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + TronCache tronCache = (TronCache) o; + return Objects.equal(name, tronCache.name); + } + + @Override + public int hashCode() { + return Objects.hashCode(name); + } +} diff --git a/common/src/main/java/org/tron/common/prometheus/GuavaCacheExports.java b/common/src/main/java/org/tron/common/prometheus/GuavaCacheExports.java new file mode 100644 index 00000000000..e8e39d5b3ad --- /dev/null +++ b/common/src/main/java/org/tron/common/prometheus/GuavaCacheExports.java @@ -0,0 +1,89 @@ +package org.tron.common.prometheus; + +import static io.prometheus.client.SampleNameFilter.ALLOW_ALL; + +import io.prometheus.client.Collector; +import io.prometheus.client.GaugeMetricFamily; +import io.prometheus.client.Predicate; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.tron.common.cache.CacheManager; + +/** + * Exports metrics about for guava cache. + *

+ * Example usage: + *

+ * {@code
+ *   new GuavaCacheExports().register();
+ * }
+ * 
+ * Example metrics being exported: + *
+ *   tron:guava_cache_hit_rate{type="account"} 0.135679
+ *   tron:guava_cache_request{type="account"} 3000
+ * 
+ */ +public class GuavaCacheExports extends Collector { + + private static final String TRON_GUAVA_CACHE_HIT_RATE = "tron:guava_cache_hit_rate"; + private static final String TRON_GUAVA_CACHE_REQUEST = "tron:guava_cache_request"; + private static final String TRON_GUAVA_CACHE_EVICTION_COUNT = "tron:guava_cache_eviction_count"; + + + public GuavaCacheExports() { + } + + + void addHitRateMetrics(List sampleFamilies, Predicate nameFilter) { + if (nameFilter.test(TRON_GUAVA_CACHE_HIT_RATE)) { + GaugeMetricFamily hitRate = new GaugeMetricFamily( + TRON_GUAVA_CACHE_HIT_RATE, + "Hit rate of a guava cache.", + Collections.singletonList("type")); + CacheManager.stats().forEach((k, v) -> hitRate + .addMetric(Collections.singletonList(k), v.hitRate())); + sampleFamilies.add(hitRate); + } + } + + void addRequestMetrics(List sampleFamilies, Predicate nameFilter) { + if (nameFilter.test(TRON_GUAVA_CACHE_REQUEST)) { + GaugeMetricFamily request = new GaugeMetricFamily( + TRON_GUAVA_CACHE_REQUEST, + "Request of a guava cache.", + Collections.singletonList("type")); + CacheManager.stats().forEach((k, v) -> request + .addMetric(Collections.singletonList(k), v.requestCount())); + sampleFamilies.add(request); + } + } + + void addEvictionCountMetrics(List sampleFamilies, + Predicate nameFilter) { + if (nameFilter.test(TRON_GUAVA_CACHE_EVICTION_COUNT)) { + GaugeMetricFamily request = new GaugeMetricFamily( + TRON_GUAVA_CACHE_EVICTION_COUNT, + "Eviction count of a guava cache.", + Collections.singletonList("type")); + CacheManager.stats().forEach((k, v) -> request + .addMetric(Collections.singletonList(k), v.evictionCount())); + sampleFamilies.add(request); + } + } + + @Override + public List collect() { + return collect(null); + } + + @Override + public List collect(Predicate nameFilter) { + List mfs = new ArrayList<>(); + addHitRateMetrics(mfs, nameFilter == null ? ALLOW_ALL : nameFilter); + addRequestMetrics(mfs, nameFilter == null ? ALLOW_ALL : nameFilter); + addEvictionCountMetrics(mfs, nameFilter == null ? ALLOW_ALL : nameFilter); + return mfs; + } +} diff --git a/common/src/main/java/org/tron/common/prometheus/Metrics.java b/common/src/main/java/org/tron/common/prometheus/Metrics.java index fd13fa3fa5a..3f37cf331aa 100644 --- a/common/src/main/java/org/tron/common/prometheus/Metrics.java +++ b/common/src/main/java/org/tron/common/prometheus/Metrics.java @@ -27,6 +27,7 @@ public static synchronized void init() { try { DefaultExports.initialize(); new OperatingSystemExports().register(CollectorRegistry.defaultRegistry); + new GuavaCacheExports().register(CollectorRegistry.defaultRegistry); int port = CommonParameter.getInstance().getMetricsPrometheusPort(); new HTTPServer.Builder().withPort(port).build(); logger.info("prometheus exposed on port : {}", port); diff --git a/common/src/main/java/org/tron/common/utils/DbOptionalsUtils.java b/common/src/main/java/org/tron/common/utils/DbOptionalsUtils.java index 69965bf39ab..ac743ebc7b7 100644 --- a/common/src/main/java/org/tron/common/utils/DbOptionalsUtils.java +++ b/common/src/main/java/org/tron/common/utils/DbOptionalsUtils.java @@ -12,7 +12,6 @@ public class DbOptionalsUtils { public static final int DEFAULT_BLOCK_SIZE = 4 * 1024; public static final int DEFAULT_WRITE_BUFFER_SIZE = 16 * 1024 * 1024; public static final int DEFAULT_WRITE_BUFFER_SIZE_M = 64 * 1024 * 1024; - public static final int DEFAULT_WRITE_BUFFER_SIZE_L = 256 * 1024 * 1024; public static final long DEFAULT_CACHE_SIZE = 32 * 1024 * 1024L; public static final int DEFAULT_MAX_OPEN_FILES = 100; /** @@ -30,13 +29,10 @@ public class DbOptionalsUtils { */ public static final int DEFAULT_MAX_OPEN_FILES_L = 100; // Read a lot - public static final List DB_M = Arrays.asList( "code", "contract"); + public static final List DB_M = Arrays.asList("code", "contract"); // Read frequently public static final List DB_L = Arrays.asList("account", "delegation", "storage-row"); - // Write frequently - public static final List DB_WRITE_L = Arrays.asList("block", "account", - "transactionRetStore", "storage-row", "trans"); private DbOptionalsUtils() { throw new IllegalStateException("DbOptionalsUtils class"); @@ -80,10 +76,6 @@ public static Options newDefaultDbOptions(String name ,Options defaultOptions) { adjustDefaultDbOptionsForL(dbOptions); } - if (DB_WRITE_L.contains(name)) { - adjustDefaultDbOptionsForWriteL(dbOptions); - } - return dbOptions; } @@ -97,8 +89,4 @@ private static void adjustDefaultDbOptionsForL(Options defaultOptions) { defaultOptions.writeBufferSize(DEFAULT_WRITE_BUFFER_SIZE_M); } - private static void adjustDefaultDbOptionsForWriteL(Options defaultOptions) { - - defaultOptions.writeBufferSize(DEFAULT_WRITE_BUFFER_SIZE_L); - } } diff --git a/common/src/main/java/org/tron/core/config/args/Storage.java b/common/src/main/java/org/tron/core/config/args/Storage.java index 6d911f3b0ac..2394a108c6e 100644 --- a/common/src/main/java/org/tron/core/config/args/Storage.java +++ b/common/src/main/java/org/tron/core/config/args/Storage.java @@ -15,9 +15,11 @@ package org.tron.core.config.args; +import com.google.common.collect.Maps; import com.typesafe.config.Config; import com.typesafe.config.ConfigObject; import java.io.File; +import java.util.List; import java.util.Map; import java.util.stream.Collectors; import lombok.Getter; @@ -25,6 +27,8 @@ import org.apache.commons.lang3.StringUtils; import org.iq80.leveldb.CompressionType; import org.iq80.leveldb.Options; +import org.tron.common.cache.CacheStrategies; +import org.tron.common.cache.CacheType; import org.tron.common.utils.DbOptionalsUtils; import org.tron.common.utils.FileUtil; import org.tron.common.utils.Property; @@ -72,6 +76,8 @@ public class Storage { private static final String CHECKPOINT_VERSION_KEY = "storage.checkpoint.version"; private static final String CHECKPOINT_SYNC_KEY = "storage.checkpoint.sync"; + private static final String CACHE_STRATEGIES = "storage.cache.strategies"; + /** * Default values of directory */ @@ -139,6 +145,13 @@ public class Storage { @Setter private int estimatedBlockTransactions; + // second cache + private final Map cacheStrategies = Maps.newConcurrentMap(); + + @Getter + private final List cacheDbs = CacheStrategies.CACHE_DBS; + // second cache + /** * Key: dbName, Value: Property object of that database */ @@ -213,6 +226,19 @@ public static int getEstimatedTransactionsFromConfig(final Config config) { return estimatedTransactions; } + + public void setCacheStrategies(Config config) { + if (config.hasPath(CACHE_STRATEGIES)) { + config.getConfig(CACHE_STRATEGIES).resolve().entrySet().forEach(c -> + this.cacheStrategies.put(CacheType.valueOf(c.getKey()), + c.getValue().unwrapped().toString())); + } + } + + public String getCacheStrategy(CacheType dbName) { + return this.cacheStrategies.getOrDefault(dbName, CacheStrategies.getCacheStrategy(dbName)); + } + private Property createProperty(final ConfigObject conf) { Property property = new Property(); diff --git a/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java b/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java index 767463a6a5b..4a98c933bd1 100644 --- a/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java +++ b/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java @@ -108,6 +108,10 @@ public List getAllWitnesses() { return witnessStore.getAllWitnesses(); } + public List updateWitnessStandby(List all) { + return witnessStore.updateWitnessStandby(all); + } + public void saveStateFlag(int flag) { dynamicPropertiesStore.saveStateFlag(flag); } diff --git a/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java b/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java index 012169bdb87..fc6cdd55c15 100644 --- a/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java +++ b/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java @@ -151,11 +151,13 @@ public void doMaintenance() { if (dynamicPropertiesStore.allowChangeDelegation()) { long nextCycle = dynamicPropertiesStore.getCurrentCycleNumber() + 1; dynamicPropertiesStore.saveCurrentCycleNumber(nextCycle); - consensusDelegate.getAllWitnesses().forEach(witness -> { + List all = consensusDelegate.getAllWitnesses(); + all.forEach(witness -> { delegationStore.setBrokerage(nextCycle, witness.createDbKey(), delegationStore.getBrokerage(witness.createDbKey())); delegationStore.setWitnessVote(nextCycle, witness.createDbKey(), witness.getVoteCount()); }); + consensusDelegate.updateWitnessStandby(all); } } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 7311f94a80d..a0b428df59f 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -520,6 +520,7 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.storage.setDefaultDbOptions(config); PARAMETER.storage.setPropertyMapFromConfig(config); + PARAMETER.storage.setCacheStrategies(config); PARAMETER.seedNode = new SeedNode(); PARAMETER.seedNode.setIpList(Optional.ofNullable(PARAMETER.seedNodes) diff --git a/framework/src/test/java/org/tron/core/config/args/StorageTest.java b/framework/src/test/java/org/tron/core/config/args/StorageTest.java index a6d9d9e7f73..eb349a2d146 100644 --- a/framework/src/test/java/org/tron/core/config/args/StorageTest.java +++ b/framework/src/test/java/org/tron/core/config/args/StorageTest.java @@ -93,7 +93,7 @@ public void getOptions() { Assert.assertEquals(1000, options.maxOpenFiles()); options = StorageUtils.getOptionsByDbName("trans"); - Assert.assertEquals(256 * 1024 * 1024, options.writeBufferSize()); + Assert.assertEquals(16 * 1024 * 1024, options.writeBufferSize()); Assert.assertEquals(50, options.maxOpenFiles()); } From 5758b660b11cb7df2b605ad6f73ca07f3866b2fb Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 15 Nov 2022 14:53:58 +0800 Subject: [PATCH 0439/1197] feat(db): improve performance for getting transaction hash 1. add cache for transaction hash --- .../tron/core/capsule/TransactionCapsule.java | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java index f3c2af334cb..afba80333cd 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -106,6 +106,7 @@ public class TransactionCapsule implements ProtoCapsule { @Setter private long order; private byte[] ownerAddress; + private Sha256Hash id; public byte[] getOwnerAddress() { if (this.ownerAddress == null) { @@ -488,7 +489,7 @@ public void setReference(long blockNum, byte[] blockHash) { .setRefBlockHash(ByteString.copyFrom(ByteArray.subArray(blockHash, 8, 16))) .setRefBlockBytes(ByteString.copyFrom(ByteArray.subArray(refBlockNum, 6, 8))) .build(); - this.transaction = this.transaction.toBuilder().setRawData(rawData).build(); + setRawData(rawData); } public long getExpiration() { @@ -501,21 +502,21 @@ public long getExpiration() { public void setExpiration(long expiration) { Transaction.raw rawData = this.transaction.getRawData().toBuilder().setExpiration(expiration) .build(); - this.transaction = this.transaction.toBuilder().setRawData(rawData).build(); + setRawData(rawData); } public void setTimestamp() { Transaction.raw rawData = this.transaction.getRawData().toBuilder() .setTimestamp(System.currentTimeMillis()) .build(); - this.transaction = this.transaction.toBuilder().setRawData(rawData).build(); + setRawData(rawData); } public void setTimestamp(long timestamp) { Transaction.raw rawData = this.transaction.getRawData().toBuilder() .setTimestamp(timestamp) .build(); - this.transaction = this.transaction.toBuilder().setRawData(rawData).build(); + setRawData(rawData); } public long getTimestamp() { @@ -545,7 +546,7 @@ public void sign(byte[] privateKey) { SignInterface cryptoEngine = SignUtils .fromPrivate(privateKey, CommonParameter.getInstance().isECKeyCryptoEngine()); ByteString sig = ByteString.copyFrom(cryptoEngine.Base64toBytes(cryptoEngine - .signHash(getRawHash().getBytes()))); + .signHash(getTransactionId().getBytes()))); this.transaction = this.transaction.toBuilder().addSignature(sig).build(); } @@ -568,7 +569,8 @@ public void addSign(byte[] privateKey, AccountStore accountStore) .fromPrivate(privateKey, CommonParameter.getInstance().isECKeyCryptoEngine()); byte[] address = cryptoEngine.getAddress(); if (this.transaction.getSignatureCount() > 0) { - checkWeight(permission, this.transaction.getSignatureList(), this.getRawHash().getBytes(), + checkWeight(permission, this.transaction.getSignatureList(), + this.getTransactionId().getBytes(), approveList); if (approveList.contains(ByteString.copyFrom(address))) { throw new PermissionException(encode58Check(address) + " had signed!"); @@ -582,7 +584,7 @@ public void addSign(byte[] privateKey, AccountStore accountStore) + " but it is not contained of permission."); } ByteString sig = ByteString.copyFrom(cryptoEngine.Base64toBytes(cryptoEngine - .signHash(getRawHash().getBytes()))); + .signHash(getTransactionId().getBytes()))); this.transaction = this.transaction.toBuilder().addSignature(sig).build(); } @@ -614,7 +616,7 @@ public boolean validatePubSignature(AccountStore accountStore, throw new ValidateSignatureException("too many signatures"); } - byte[] hash = this.getRawHash().getBytes(); + byte[] hash = getTransactionId().getBytes(); try { if (!validateSignature(this.transaction, hash, accountStore, dynamicPropertiesStore)) { @@ -657,7 +659,16 @@ public boolean validateSignature(AccountStore accountStore, } public Sha256Hash getTransactionId() { - return getRawHash(); + if (this.id == null) { + this.id = getRawHash(); + } + return this.id; + } + + private void setRawData(Transaction.raw rawData) { + this.transaction = this.transaction.toBuilder().setRawData(rawData).build(); + // invalidate trxId + this.id = null; } @Override From 31bb4d4b70a24ebe21eabc4a10083a674b60504f Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Wed, 23 Nov 2022 20:03:12 +0800 Subject: [PATCH 0440/1197] fix(db): remove trans-cache from checkpoint --- .../java/org/tron/core/db2/core/SnapshotManager.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java index f41e1490d87..3fb3176d0e4 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java @@ -7,7 +7,6 @@ import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; - import java.io.File; import java.nio.file.Paths; import java.util.ArrayList; @@ -15,6 +14,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -24,7 +24,6 @@ import java.util.concurrent.locks.LockSupport; import java.util.stream.Collectors; import javax.annotation.PostConstruct; - import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @@ -375,6 +374,12 @@ private void createCheckpoint() { } String dbName = db.getDbName(); + + if (Objects.equals(dbName, "trans-cache")) { + // trans-cache is deprecated + continue; + } + Snapshot next = head.getRoot(); for (int i = 0; i < flushCount; ++i) { next = next.getNext(); From b3f5fa991343925a8cf62866ff95a84881cf123c Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Wed, 30 Nov 2022 17:01:10 +0800 Subject: [PATCH 0441/1197] fix(net): introduce a new libp2p dependency to fix the logging issue --- framework/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/build.gradle b/framework/build.gradle index bbbeaee8a63..2cb1a61e245 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -46,7 +46,7 @@ dependencies { compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.1.4' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.1.5' compile group: 'com.typesafe', name: 'config', version: '1.3.2' From 0821f2e7d858cf3048c9db4b6b7b47fc1f80f25f Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Wed, 23 Nov 2022 16:54:22 +0800 Subject: [PATCH 0442/1197] feat(freezeV2): optimize delegate index --- .../actuator/DelegateResourceActuator.java | 54 +++------ .../actuator/UnDelegateResourceActuator.java | 35 +----- .../DelegatedResourceAccountIndexCapsule.java | 9 -- .../capsule/DelegatedResourceCapsule.java | 10 +- .../DelegatedResourceAccountIndexStore.java | 57 +++++++--- .../tron/common/utils/DbOptionalsUtils.java | 2 +- .../src/main/java/org/tron/core/Wallet.java | 5 +- .../DelegateResourceActuatorTest.java | 17 +-- .../UnDelegateResourceActuatorTest.java | 105 ++++-------------- 9 files changed, 89 insertions(+), 205 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 7c20de7b97b..397c245fceb 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -6,14 +6,12 @@ import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import java.util.Arrays; -import java.util.List; import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; -import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.db.BandwidthProcessor; @@ -24,11 +22,11 @@ import org.tron.core.store.DelegatedResourceAccountIndexStore; import org.tron.core.store.DelegatedResourceStore; import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.utils.TransactionUtil; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.BalanceContract.DelegateResourceContract; -import org.tron.core.utils.TransactionUtil; @Slf4j(topic = "actuator") public class DelegateResourceActuator extends AbstractActuator { @@ -146,15 +144,15 @@ public boolean validate() throws ContractValidateException { long accountNetUsage = ownerCapsule.getNetUsage(); if (null != this.getTx() && this.getTx().isTransactionCreate()) { - accountNetUsage += TransactionUtil.estimateConsumeBandWidthSize(ownerCapsule, - chainBaseManager); + accountNetUsage += TransactionUtil.estimateConsumeBandWidthSize(ownerCapsule, + chainBaseManager); } long netUsage = (long) (accountNetUsage * TRX_PRECISION * ((double) - (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); + (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); - long ownerNetUsage = (long) (netUsage * ((double)(ownerCapsule - .getFrozenV2BalanceForBandwidth()) / - ownerCapsule.getAllFrozenBalanceForBandwidth())); + long ownerNetUsage = (long) (netUsage * ((double) (ownerCapsule + .getFrozenV2BalanceForBandwidth()) / + ownerCapsule.getAllFrozenBalanceForBandwidth())); if (ownerCapsule.getFrozenV2BalanceForBandwidth() - ownerNetUsage < delegateBalance) { @@ -168,10 +166,10 @@ public boolean validate() throws ContractValidateException { processor.updateUsage(ownerCapsule); long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) - (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); + (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); - long ownerEnergyUsage = (long) (energyUsage * ((double)(ownerCapsule - .getFrozenV2BalanceForEnergy()) / ownerCapsule.getAllFrozenBalanceForEnergy())); + long ownerEnergyUsage = (long) (energyUsage * ((double) (ownerCapsule + .getFrozenV2BalanceForEnergy()) / ownerCapsule.getAllFrozenBalanceForEnergy())); if (ownerCapsule.getFrozenV2BalanceForEnergy() - ownerEnergyUsage < delegateBalance) { throw new ContractValidateException( @@ -225,6 +223,7 @@ public long calcFee() { private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boolean isBandwidth, long balance) { AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicPropertiesStore = chainBaseManager.getDynamicPropertiesStore(); DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore(); DelegatedResourceAccountIndexStore delegatedResourceAccountIndexStore = chainBaseManager .getDelegatedResourceAccountIndexStore(); @@ -245,34 +244,9 @@ private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boole } delegatedResourceStore.put(key, delegatedResourceCapsule); - //modify DelegatedResourceAccountIndexStore owner - byte[] ownerKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(ownerAddress); - DelegatedResourceAccountIndexCapsule ownerIndexCapsule = delegatedResourceAccountIndexStore - .get(ownerKey); - if (ownerIndexCapsule == null) { - ownerIndexCapsule = new DelegatedResourceAccountIndexCapsule( - ByteString.copyFrom(ownerAddress)); - } - List toAccountsList = ownerIndexCapsule.getToAccountsList(); - if (!toAccountsList.contains(ByteString.copyFrom(receiverAddress))) { - ownerIndexCapsule.addToAccount(ByteString.copyFrom(receiverAddress)); - delegatedResourceAccountIndexStore.put(ownerKey, ownerIndexCapsule); - } - - //modify DelegatedResourceAccountIndexStore receiver - byte[] receiverKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiverAddress); - DelegatedResourceAccountIndexCapsule receiverIndexCapsule = delegatedResourceAccountIndexStore - .get(receiverKey); - if (receiverIndexCapsule == null) { - receiverIndexCapsule = new DelegatedResourceAccountIndexCapsule( - ByteString.copyFrom(receiverAddress)); - } - List fromAccountsList = receiverIndexCapsule - .getFromAccountsList(); - if (!fromAccountsList.contains(ByteString.copyFrom(ownerAddress))) { - receiverIndexCapsule.addFromAccount(ByteString.copyFrom(ownerAddress)); - delegatedResourceAccountIndexStore.put(receiverKey, receiverIndexCapsule); - } + //modify DelegatedResourceAccountIndexStore + delegatedResourceAccountIndexStore.delegateV2(ownerAddress, receiverAddress, + dynamicPropertiesStore.getLatestBlockHeaderTimestamp()); //modify AccountStore for receiver AccountCapsule receiverCapsule = accountStore.get(receiverAddress); diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index 0ab410939ea..76c1411d983 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -7,16 +7,13 @@ import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; -import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.db.BandwidthProcessor; @@ -143,7 +140,7 @@ public boolean execute(Object result) throws ContractExeException { long now = chainBaseManager.getHeadSlot(); if (Objects.nonNull(receiverCapsule) && transferUsage > 0) { ownerCapsule.setNetUsage(processor.unDelegateIncrease(ownerCapsule, receiverCapsule, - transferUsage, BANDWIDTH, now)); + transferUsage, BANDWIDTH, now)); ownerCapsule.setLatestConsumeTime(now); } } @@ -159,7 +156,7 @@ public boolean execute(Object result) throws ContractExeException { long now = chainBaseManager.getHeadSlot(); if (Objects.nonNull(receiverCapsule) && transferUsage > 0) { ownerCapsule.setEnergyUsage(processor.unDelegateIncrease(ownerCapsule, receiverCapsule, - transferUsage, ENERGY, now)); + transferUsage, ENERGY, now)); ownerCapsule.setLatestConsumeTimeForEnergy(now); } } @@ -173,32 +170,8 @@ public boolean execute(Object result) throws ContractExeException { && delegatedResourceCapsule.getFrozenBalanceForEnergy() == 0) { delegatedResourceStore.delete(key); - //modify DelegatedResourceAccountIndexStore for owner - byte[] ownerKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(ownerAddress); - DelegatedResourceAccountIndexCapsule ownerIndexCapsule = delegatedResourceAccountIndexStore - .get(ownerKey); - if (ownerIndexCapsule != null) { - List toAccountsList = new ArrayList<>(ownerIndexCapsule - .getToAccountsList()); - toAccountsList.remove(ByteString.copyFrom(receiverAddress)); - ownerIndexCapsule.setAllToAccounts(toAccountsList); - delegatedResourceAccountIndexStore - .put(ownerKey, ownerIndexCapsule); - } - - //modify DelegatedResourceAccountIndexStore for receive - byte[] receiverKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiverAddress); - DelegatedResourceAccountIndexCapsule receiverIndexCapsule = delegatedResourceAccountIndexStore - .get(receiverKey); - if (receiverIndexCapsule != null) { - List fromAccountsList = new ArrayList<>(receiverIndexCapsule - .getFromAccountsList()); - fromAccountsList.remove(ByteString.copyFrom(ownerAddress)); - receiverIndexCapsule.setAllFromAccounts(fromAccountsList); - delegatedResourceAccountIndexStore - .put(receiverKey, receiverIndexCapsule); - } - + //modify DelegatedResourceAccountIndexStore + delegatedResourceAccountIndexStore.unDelegateV2(ownerAddress, receiverAddress); } else { delegatedResourceStore.put(key, delegatedResourceCapsule); } diff --git a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java index 9628f193b5e..9874c7de503 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java @@ -107,15 +107,6 @@ public byte[] createDbKey() { return getAccount().toByteArray(); } - public static byte[] createDbKeyV2(byte[] account) { - byte[] v2Prefix = "v2_".getBytes(); - byte[] key = new byte[v2Prefix.length + account.length]; - System.arraycopy(v2Prefix, 0, key, 0, v2Prefix.length); - System.arraycopy(account, 0, key, v2Prefix.length, account.length); - return key; - } - - public String createReadableString() { return ByteArray.toHexString(getAccount().toByteArray()); } diff --git a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java index fbb398a4b44..31c8dc5fb29 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java @@ -9,6 +9,7 @@ @Slf4j(topic = "capsule") public class DelegatedResourceCapsule implements ProtoCapsule { + private static final byte[] V2_PREFIX = {0x01}; private DelegatedResource delegatedResource; public DelegatedResourceCapsule(final DelegatedResource delegatedResource) { @@ -38,11 +39,10 @@ public static byte[] createDbKey(byte[] from, byte[] to) { } public static byte[] createDbKeyV2(byte[] from, byte[] to) { - byte[] v2Prefix = "v2_".getBytes(); - byte[] key = new byte[v2Prefix.length + from.length + to.length]; - System.arraycopy(v2Prefix, 0, key, 0, v2Prefix.length); - System.arraycopy(from, 0, key, v2Prefix.length, from.length); - System.arraycopy(to, 0, key, v2Prefix.length+from.length, to.length); + byte[] key = new byte[V2_PREFIX.length + from.length + to.length]; + System.arraycopy(V2_PREFIX, 0, key, 0, V2_PREFIX.length); + System.arraycopy(from, 0, key, V2_PREFIX.length, from.length); + System.arraycopy(to, 0, key, V2_PREFIX.length + from.length, to.length); return key; } diff --git a/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java b/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java index e9b7be47792..435f71c9a64 100644 --- a/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java @@ -1,5 +1,6 @@ package org.tron.core.store; +import com.google.common.primitives.Bytes; import com.google.protobuf.ByteString; import java.util.ArrayList; import java.util.Comparator; @@ -19,6 +20,9 @@ public class DelegatedResourceAccountIndexStore extends private static final byte[] FROM_PREFIX = {0x01}; private static final byte[] TO_PREFIX = {0x02}; + private static final byte[] V2_FROM_PREFIX = {0x03}; + private static final byte[] V2_TO_PREFIX = {0x04}; + @Autowired public DelegatedResourceAccountIndexStore(@Value("DelegatedResourceAccountIndex") String dbName) { super(dbName); @@ -31,14 +35,6 @@ public DelegatedResourceAccountIndexCapsule get(byte[] key) { return ArrayUtils.isEmpty(value) ? null : new DelegatedResourceAccountIndexCapsule(value); } - private byte[] createKey(byte[] prefix, byte[] address1, byte[] address2) { - byte[] key = new byte[prefix.length + address1.length + address2.length]; - System.arraycopy(prefix, 0, key, 0, prefix.length); - System.arraycopy(address1, 0, key, prefix.length, address1.length); - System.arraycopy(address2, 0, key, prefix.length + address1.length, address2.length); - return key; - } - public void convert(byte[] address) { DelegatedResourceAccountIndexCapsule indexCapsule = this.get(address); if (indexCapsule == null) { @@ -61,13 +57,27 @@ public void convert(byte[] address) { } public void delegate(byte[] from, byte[] to, long time) { - byte[] fromKey = createKey(FROM_PREFIX, from, to); + byte[] fromKey = Bytes.concat(FROM_PREFIX, from, to); DelegatedResourceAccountIndexCapsule toIndexCapsule = new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(to)); toIndexCapsule.setTimestamp(time); this.put(fromKey, toIndexCapsule); - byte[] toKey = createKey(TO_PREFIX, to, from); + byte[] toKey = Bytes.concat(TO_PREFIX, to, from); + DelegatedResourceAccountIndexCapsule fromIndexCapsule = + new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(from)); + fromIndexCapsule.setTimestamp(time); + this.put(toKey, fromIndexCapsule); + } + + public void delegateV2(byte[] from, byte[] to, long time) { + byte[] fromKey = Bytes.concat(V2_FROM_PREFIX, from, to); + DelegatedResourceAccountIndexCapsule toIndexCapsule = + new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(to)); + toIndexCapsule.setTimestamp(time); + this.put(fromKey, toIndexCapsule); + + byte[] toKey = Bytes.concat(V2_TO_PREFIX, to, from); DelegatedResourceAccountIndexCapsule fromIndexCapsule = new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(from)); fromIndexCapsule.setTimestamp(time); @@ -75,9 +85,17 @@ public void delegate(byte[] from, byte[] to, long time) { } public void unDelegate(byte[] from, byte[] to) { - byte[] fromKey = createKey(FROM_PREFIX, from, to); + byte[] fromKey = Bytes.concat(FROM_PREFIX, from, to); this.delete(fromKey); - byte[] toKey = createKey(TO_PREFIX, to, from); + byte[] toKey = Bytes.concat(TO_PREFIX, to, from); + this.delete(toKey); + } + + + public void unDelegateV2(byte[] from, byte[] to) { + byte[] fromKey = Bytes.concat(V2_FROM_PREFIX, from, to); + this.delete(fromKey); + byte[] toKey = Bytes.concat(V2_TO_PREFIX, to, from); this.delete(toKey); } @@ -86,23 +104,26 @@ public DelegatedResourceAccountIndexCapsule getIndex(byte[] address) { if (indexCapsule != null) { return indexCapsule; } + return getWithPrefix(FROM_PREFIX, TO_PREFIX, address); + } + public DelegatedResourceAccountIndexCapsule getV2Index(byte[] address) { + return getWithPrefix(V2_FROM_PREFIX, V2_TO_PREFIX, address); + } + + private DelegatedResourceAccountIndexCapsule getWithPrefix(byte[] fromPrefix, byte[] toPrefix, byte[] address) { DelegatedResourceAccountIndexCapsule tmpIndexCapsule = new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(address)); - byte[] key = new byte[FROM_PREFIX.length + address.length]; - System.arraycopy(FROM_PREFIX, 0, key, 0, FROM_PREFIX.length); - System.arraycopy(address, 0, key, FROM_PREFIX.length, address.length); + byte[] key = Bytes.concat(fromPrefix, address); List tmpToList = new ArrayList<>(this.prefixQuery(key).values()); - tmpToList.sort(Comparator.comparing(DelegatedResourceAccountIndexCapsule::getTimestamp)); List list = tmpToList.stream() .map(DelegatedResourceAccountIndexCapsule::getAccount).collect(Collectors.toList()); tmpIndexCapsule.setAllToAccounts(list); - System.arraycopy(TO_PREFIX, 0, key, 0, TO_PREFIX.length); - System.arraycopy(address, 0, key, TO_PREFIX.length, address.length); + key = Bytes.concat(toPrefix, address); List tmpFromList = new ArrayList<>(this.prefixQuery(key).values()); tmpFromList.sort(Comparator.comparing(DelegatedResourceAccountIndexCapsule::getTimestamp)); diff --git a/common/src/main/java/org/tron/common/utils/DbOptionalsUtils.java b/common/src/main/java/org/tron/common/utils/DbOptionalsUtils.java index 69965bf39ab..44f11d5de81 100644 --- a/common/src/main/java/org/tron/common/utils/DbOptionalsUtils.java +++ b/common/src/main/java/org/tron/common/utils/DbOptionalsUtils.java @@ -35,7 +35,7 @@ public class DbOptionalsUtils { public static final List DB_L = Arrays.asList("account", "delegation", "storage-row"); // Write frequently - public static final List DB_WRITE_L = Arrays.asList("block", "account", + protected static final List DB_WRITE_L = Arrays.asList("block", "account", "transactionRetStore", "storage-row", "trans"); private DbOptionalsUtils() { diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index cae83378ab0..3534af906fe 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -906,9 +906,8 @@ public DelegatedResourceAccountIndex getDelegatedResourceAccountIndex(ByteString } public DelegatedResourceAccountIndex getDelegatedResourceAccountIndexV2(ByteString address) { - byte[] dbKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(address.toByteArray()); - DelegatedResourceAccountIndexCapsule accountIndexCapsule = - chainBaseManager.getDelegatedResourceAccountIndexStore().get(dbKey); + DelegatedResourceAccountIndexCapsule accountIndexCapsule = chainBaseManager + .getDelegatedResourceAccountIndexStore().getV2Index(address.toByteArray()); if (accountIndexCapsule != null) { return accountIndexCapsule.getInstance(); } else { diff --git a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java index e76d979cd1f..74b1edbfc37 100644 --- a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java @@ -105,10 +105,7 @@ public void createAccountCapsule() { // clear delegate dbManager.getDelegatedResourceStore().delete(DelegatedResourceCapsule.createDbKeyV2( owner, receiver)); - dbManager.getDelegatedResourceAccountIndexStore().delete( - DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner)); - dbManager.getDelegatedResourceAccountIndexStore().delete( - DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver)); + dbManager.getDelegatedResourceAccountIndexStore().unDelegateV2(owner, receiver); } public void freezeBandwidthForOwner() { @@ -345,17 +342,15 @@ public void testDelegateResourceForBandwidth() { Assert.assertEquals(totalNetWeightBefore, totalNetWeightAfter); //check DelegatedResourceAccountIndex - byte[] key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(owner); Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); Assert.assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); Assert.assertTrue(ownerIndexCapsule.getToAccountsList() .contains(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)))); - key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); DelegatedResourceAccountIndexCapsule receiveCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(receiver); Assert.assertEquals(0, receiveCapsule.getToAccountsList().size()); Assert.assertEquals(1, receiveCapsule.getFromAccountsList().size()); Assert.assertTrue(receiveCapsule.getFromAccountsList() @@ -408,18 +403,16 @@ public void testDelegateResourceForCpu() { Assert.assertEquals(totalEnergyWeightBefore, totalEnergyWeightAfter); //check DelegatedResourceAccountIndex - byte[] key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(owner); Assert .assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); Assert.assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); Assert.assertTrue(ownerIndexCapsule.getToAccountsList() .contains(ByteString.copyFrom(receiver))); - key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(receiver); Assert .assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); Assert diff --git a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java index 8ac20aa5e66..e403e82167f 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java @@ -6,7 +6,6 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; import java.io.File; -import java.util.List; import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; import org.junit.Assert; @@ -99,11 +98,7 @@ public void createAccountCapsule() { byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); dbManager.getDelegatedResourceStore().delete(DelegatedResourceCapsule.createDbKeyV2( owner, receiver)); - dbManager.getDelegatedResourceAccountIndexStore().delete( - DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner)); - dbManager.getDelegatedResourceAccountIndexStore().delete( - DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver)); - + dbManager.getDelegatedResourceAccountIndexStore().unDelegateV2(owner, receiver); dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); } @@ -125,30 +120,7 @@ public void delegateBandwidthForOwner() { dbManager.getDelegatedResourceStore().put( DelegatedResourceCapsule.createDbKeyV2(owner, receiver), delegatedResourceCapsule); - - byte[] ownerKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); - DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = - new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(owner)); - - List toAccountsList = delegatedResourceAccountIndexCapsule.getToAccountsList(); - if (!toAccountsList.contains(ByteString.copyFrom(receiver))) { - delegatedResourceAccountIndexCapsule.addToAccount(ByteString.copyFrom(receiver)); - } - dbManager.getDelegatedResourceAccountIndexStore() - .put(ownerKey, delegatedResourceAccountIndexCapsule); - - - byte[] receiverKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); - delegatedResourceAccountIndexCapsule = new DelegatedResourceAccountIndexCapsule( - ByteString.copyFrom(receiver)); - - List fromAccountsList = delegatedResourceAccountIndexCapsule - .getFromAccountsList(); - if (!fromAccountsList.contains(ByteString.copyFrom(owner))) { - delegatedResourceAccountIndexCapsule.addFromAccount(ByteString.copyFrom(owner)); - } - dbManager.getDelegatedResourceAccountIndexStore() - .put(receiverKey, delegatedResourceAccountIndexCapsule); + dbManager.getDelegatedResourceAccountIndexStore().delegateV2(owner, receiver, 1); } public void delegateCpuForOwner() { @@ -169,30 +141,7 @@ public void delegateCpuForOwner() { dbManager.getDelegatedResourceStore().put( DelegatedResourceCapsule.createDbKeyV2(owner, receiver), delegatedResourceCapsule); - - byte[] ownerKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); - DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = - new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(owner)); - - List toAccountsList = delegatedResourceAccountIndexCapsule.getToAccountsList(); - if (!toAccountsList.contains(ByteString.copyFrom(receiver))) { - delegatedResourceAccountIndexCapsule.addToAccount(ByteString.copyFrom(receiver)); - } - dbManager.getDelegatedResourceAccountIndexStore() - .put(ownerKey, delegatedResourceAccountIndexCapsule); - - - byte[] receiverKey = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); - delegatedResourceAccountIndexCapsule = new DelegatedResourceAccountIndexCapsule( - ByteString.copyFrom(receiver)); - - List fromAccountsList = delegatedResourceAccountIndexCapsule - .getFromAccountsList(); - if (!fromAccountsList.contains(ByteString.copyFrom(owner))) { - delegatedResourceAccountIndexCapsule.addFromAccount(ByteString.copyFrom(owner)); - } - dbManager.getDelegatedResourceAccountIndexStore() - .put(receiverKey, delegatedResourceAccountIndexCapsule); + dbManager.getDelegatedResourceAccountIndexStore().delegateV2(owner, receiver, 1); } private Any getDelegatedContractForBandwidth( @@ -270,15 +219,13 @@ public void testUnDelegateForBandwidth() { Assert.assertNull(delegatedCapsule); //check DelegatedResourceAccountIndex - key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(owner); Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); Assert.assertEquals(0, ownerIndexCapsule.getToAccountsList().size()); - key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(receiver); Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); Assert.assertEquals(0, receiverIndexCapsule.getFromAccountsList().size()); @@ -345,15 +292,13 @@ public void testPartialUnDelegateForBandwidth() { delegatedResourceCapsule.getFrozenBalanceForBandwidth()); //check DelegatedResourceAccountIndex - key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(owner); Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); Assert.assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); - key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(receiver); Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); Assert.assertEquals(1, receiverIndexCapsule.getFromAccountsList().size()); @@ -399,15 +344,13 @@ public void testUnDelegatedForBandwidthWithDeletedReceiver() { Assert.assertNull(delegatedResourceCapsule); //check DelegatedResourceAccountIndex - key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(owner); Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); Assert.assertEquals(0, ownerIndexCapsule.getToAccountsList().size()); - key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(receiver); Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); Assert.assertEquals(0, receiverIndexCapsule.getFromAccountsList().size()); @@ -462,15 +405,13 @@ public void testUnDelegatedForBandwidthWithRecreatedReceiver() { Assert.assertNull(delegatedCapsule); //check DelegatedResourceAccountIndex - key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(owner); Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); Assert.assertEquals(0, ownerIndexCapsule.getToAccountsList().size()); - key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(receiver); Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); Assert.assertEquals(0, receiverIndexCapsule.getFromAccountsList().size()); @@ -537,15 +478,13 @@ public void testUnDelegatedForCpu() { Assert.assertNull(delegatedCapsule); //check DelegatedResourceAccountIndex - key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(owner); Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); Assert.assertEquals(0, ownerIndexCapsule.getToAccountsList().size()); - key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(owner); Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); Assert.assertEquals(0, receiverIndexCapsule.getFromAccountsList().size()); @@ -609,15 +548,13 @@ public void testPartialUnDelegatedForCpu() { delegatedCapsule.getFrozenBalanceForEnergy()); //check DelegatedResourceAccountIndex - key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(owner); Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); Assert.assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); - key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(receiver); Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); Assert.assertEquals(1, receiverIndexCapsule.getFromAccountsList().size()); @@ -662,15 +599,13 @@ public void testUnDelegatedForCpuWithDeletedReceiver() { Assert.assertNull(delegatedCapsule); //check DelegatedResourceAccountIndex - key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(owner); Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); Assert.assertEquals(0, ownerIndexCapsule.getToAccountsList().size()); - key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(receiver); Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); Assert.assertEquals(0, receiverIndexCapsule.getFromAccountsList().size()); @@ -726,15 +661,13 @@ public void testUnDelegatedForCpuWithRecreatedReceiver() { Assert.assertNull(delegatedResourceCapsule); //check DelegatedResourceAccountIndex - key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(owner); DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(owner); Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); Assert.assertEquals(0, ownerIndexCapsule.getToAccountsList().size()); - key = DelegatedResourceAccountIndexCapsule.createDbKeyV2(receiver); DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager - .getDelegatedResourceAccountIndexStore().get(key); + .getDelegatedResourceAccountIndexStore().getV2Index(receiver); Assert.assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); Assert.assertEquals(0, receiverIndexCapsule.getFromAccountsList().size()); From 241f94762b7a9afd8e6e21576b86b6694e1eeb7c Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 23 Nov 2022 11:50:04 +0800 Subject: [PATCH 0443/1197] fix(freezeV2): fix deflation or expansion problems caused by precision --- .../actuator/DelegateResourceActuator.java | 4 +- .../actuator/FreezeBalanceV2Actuator.java | 16 ++- .../actuator/UnDelegateResourceActuator.java | 4 +- .../actuator/UnfreezeBalanceV2Actuator.java | 22 ++-- .../DelegateResourceProcessor.java | 4 +- .../UnDelegateResourceProcessor.java | 4 +- .../org/tron/core/capsule/AccountCapsule.java | 33 ++++++ .../tron/common/runtime/vm/FreezeV2Test.java | 16 +-- .../DelegateResourceActuatorTest.java | 33 +++--- .../UnDelegateResourceActuatorTest.java | 104 +++++++++--------- .../UnfreezeBalanceV2ActuatorTest.java | 38 +++---- protocol/src/main/protos/core/Tron.proto | 4 + 12 files changed, 163 insertions(+), 119 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 397c245fceb..5f8fae99771 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -66,14 +66,14 @@ public boolean execute(Object result) throws ContractExeException { delegateResource(ownerAddress, receiverAddress, true, delegateBalance); - ownerCapsule.addDelegatedFrozenBalanceForBandwidth(delegateBalance); + ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(delegateBalance); ownerCapsule.addFrozenBalanceForBandwidthV2(-delegateBalance); break; case ENERGY: delegateResource(ownerAddress, receiverAddress, false, delegateBalance); - ownerCapsule.addDelegatedFrozenBalanceForEnergy(delegateBalance); + ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(delegateBalance); ownerCapsule.addFrozenBalanceForEnergyV2(-delegateBalance); break; default: diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java index 3d4a8c8fae7..90b03e43e1a 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java @@ -14,10 +14,13 @@ import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.BalanceContract.FreezeBalanceV2Contract; + import java.util.Objects; import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; @Slf4j(topic = "actuator") public class FreezeBalanceV2Actuator extends AbstractActuator { @@ -56,16 +59,22 @@ public boolean execute(Object result) throws ContractExeException { switch (freezeBalanceV2Contract.getResource()) { case BANDWIDTH: + long oldNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); - dynamicStore.addTotalNetWeight(frozenBalance / TRX_PRECISION); + long newNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; + dynamicStore.addTotalNetWeight(newNetWeight - oldNetWeight); break; case ENERGY: + long oldEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); - dynamicStore.addTotalEnergyWeight(frozenBalance / TRX_PRECISION); + long newEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; + dynamicStore.addTotalEnergyWeight(newEnergyWeight - oldEnergyWeight); break; case TRON_POWER: + long oldTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; accountCapsule.addFrozenForTronPowerV2(frozenBalance); - dynamicStore.addTotalTronPowerWeight(frozenBalance / TRX_PRECISION); + long newTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; + dynamicStore.addTotalTronPowerWeight(newTPWeight - oldTPWeight); break; default: logger.debug("Resource Code Error."); @@ -79,7 +88,6 @@ public boolean execute(Object result) throws ContractExeException { return true; } - @Override public boolean validate() throws ContractValidateException { if (this.any == null) { diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index 76c1411d983..1bc2ad0b55b 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -132,7 +132,7 @@ public boolean execute(Object result) throws ContractExeException { case BANDWIDTH: { delegatedResourceCapsule.addFrozenBalanceForBandwidth(-unDelegateBalance, 0); - ownerCapsule.addDelegatedFrozenBalanceForBandwidth(-unDelegateBalance); + ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(-unDelegateBalance); ownerCapsule.addFrozenBalanceForBandwidthV2(unDelegateBalance); BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); @@ -148,7 +148,7 @@ public boolean execute(Object result) throws ContractExeException { case ENERGY: { delegatedResourceCapsule.addFrozenBalanceForEnergy(-unDelegateBalance, 0); - ownerCapsule.addDelegatedFrozenBalanceForEnergy(-unDelegateBalance); + ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(-unDelegateBalance); ownerCapsule.addFrozenBalanceForEnergyV2(unDelegateBalance); EnergyProcessor processor = new EnergyProcessor(dynamicStore, accountStore); diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java index b43b614b8a6..53bcadc8bf9 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java @@ -80,12 +80,10 @@ public boolean execute(Object result) throws ContractExeException { ResourceCode freezeType = unfreezeBalanceV2Contract.getResource(); - this.updateAccountFrozenInfo(freezeType, accountCapsule, unfreezeBalance); - long expireTime = this.calcUnfreezeExpireTime(now); accountCapsule.addUnfrozenV2List(freezeType, unfreezeBalance, expireTime); - this.updateTotalResourceWeight(unfreezeBalanceV2Contract, unfreezeBalance); + this.updateTotalResourceWeight(accountCapsule, unfreezeBalanceV2Contract, unfreezeBalance); this.updateVote(accountCapsule, unfreezeBalanceV2Contract, ownerAddress); if (dynamicStore.supportAllowNewResourceModel() @@ -272,18 +270,28 @@ public long unfreezeExpire(AccountCapsule accountCapsule, long now) { return unfreezeBalance; } - public void updateTotalResourceWeight(final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract, + public void updateTotalResourceWeight(AccountCapsule accountCapsule, + final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract, long unfreezeBalance) { DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); switch (unfreezeBalanceV2Contract.getResource()) { case BANDWIDTH: - dynamicStore.addTotalNetWeight(-unfreezeBalance / TRX_PRECISION); + long oldNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; + accountCapsule.addFrozenBalanceForBandwidthV2(-unfreezeBalance); + long newNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; + dynamicStore.addTotalNetWeight(newNetWeight - oldNetWeight); break; case ENERGY: - dynamicStore.addTotalEnergyWeight(-unfreezeBalance / TRX_PRECISION); + long oldEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; + accountCapsule.addFrozenBalanceForEnergyV2(-unfreezeBalance); + long newEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; + dynamicStore.addTotalEnergyWeight(newEnergyWeight - oldEnergyWeight); break; case TRON_POWER: - dynamicStore.addTotalTronPowerWeight(-unfreezeBalance / TRX_PRECISION); + long oldTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; + accountCapsule.addFrozenForTronPowerV2(-unfreezeBalance); + long newTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; + dynamicStore.addTotalTronPowerWeight(newTPWeight - oldTPWeight); break; default: //this should never happen diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index 3d658374a13..42203d503fa 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -124,14 +124,14 @@ public void execute(DelegateResourceParam param, Repository repo) { delegateResource(ownerAddress, receiverAddress, true, delegateBalance, repo); - ownerCapsule.addDelegatedFrozenBalanceForBandwidth(delegateBalance); + ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(delegateBalance); ownerCapsule.addFrozenBalanceForBandwidthV2(-delegateBalance); break; case ENERGY: delegateResource(ownerAddress, receiverAddress, false, delegateBalance, repo); - ownerCapsule.addDelegatedFrozenBalanceForEnergy(delegateBalance); + ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(delegateBalance); ownerCapsule.addFrozenBalanceForEnergyV2(-delegateBalance); break; default: diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index f4c1af6dc59..091608050bd 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -159,7 +159,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { case BANDWIDTH: { delegatedResourceCapsule.addFrozenBalanceForBandwidth(-unDelegateBalance, 0); - ownerCapsule.addDelegatedFrozenBalanceForBandwidth(-unDelegateBalance); + ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(-unDelegateBalance); ownerCapsule.addFrozenBalanceForBandwidthV2(unDelegateBalance); BandwidthProcessor processor = new BandwidthProcessor(ChainBaseManager.getInstance()); @@ -173,7 +173,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { case ENERGY: { delegatedResourceCapsule.addFrozenBalanceForEnergy(-unDelegateBalance, 0); - ownerCapsule.addDelegatedFrozenBalanceForEnergy(-unDelegateBalance); + ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(-unDelegateBalance); ownerCapsule.addFrozenBalanceForEnergyV2(unDelegateBalance); EnergyProcessor processor = diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index d2ab55a7032..7213ac39000 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -356,6 +356,11 @@ public void addDelegatedFrozenBalanceForBandwidth(long balance) { this.account.getDelegatedFrozenBalanceForBandwidth() + balance).build(); } + public void addDelegatedFrozenV2BalanceForBandwidth(long balance) { + this.account = this.account.toBuilder().setDelegatedFrozenV2BalanceForBandwidth( + this.account.getDelegatedFrozenV2BalanceForBandwidth() + balance).build(); + } + public long getAcquiredDelegatedFrozenBalanceForBandwidth() { return this.account.getAcquiredDelegatedFrozenBalanceForBandwidth(); } @@ -398,10 +403,18 @@ public long getDelegatedFrozenBalanceForEnergy() { return getAccountResource().getDelegatedFrozenBalanceForEnergy(); } + public long getDelegatedFrozenV2BalanceForEnergy() { + return getAccountResource().getDelegatedFrozenV2BalanceForEnergy(); + } + public long getDelegatedFrozenBalanceForBandwidth() { return this.account.getDelegatedFrozenBalanceForBandwidth(); } + public long getDelegatedFrozenV2BalanceForBandwidth() { + return this.account.getDelegatedFrozenV2BalanceForBandwidth(); + } + public void setDelegatedFrozenBalanceForBandwidth(long balance) { this.account = this.account.toBuilder() .setDelegatedFrozenBalanceForBandwidth(balance) @@ -448,6 +461,14 @@ public void addDelegatedFrozenBalanceForEnergy(long balance) { .build(); } + public void addDelegatedFrozenV2BalanceForEnergy(long balance) { + AccountResource newAccountResource = getAccountResource().toBuilder() + .setDelegatedFrozenV2BalanceForEnergy( + getAccountResource().getDelegatedFrozenV2BalanceForEnergy() + balance).build(); + + this.account = this.account.toBuilder().setAccountResource(newAccountResource).build(); + } + public void addFrozenBalanceForEnergyV2(long balance) { this.addFrozenBalanceForResource(ENERGY, balance); } @@ -536,8 +557,11 @@ public long getTronPower() { tp += account.getAccountResource().getFrozenBalanceForEnergy().getFrozenBalance(); tp += account.getDelegatedFrozenBalanceForBandwidth(); tp += account.getAccountResource().getDelegatedFrozenBalanceForEnergy(); + tp += getFrozenV2List().stream().filter(o -> o.getType() != TRON_POWER) .mapToLong(FreezeV2::getAmount).sum(); + tp += account.getDelegatedFrozenV2BalanceForBandwidth(); + tp += account.getAccountResource().getDelegatedFrozenV2BalanceForEnergy(); return tp; } @@ -1289,4 +1313,13 @@ public long getLastConsumeTime(ResourceCode resourceCode) { return this.account.getAccountResource().getLatestConsumeTimeForEnergy(); } } + + public long getFrozenV2BalanceWithDelegated(ResourceCode resourceCode) { + if (resourceCode == BANDWIDTH) { + return getFrozenV2BalanceForBandwidth() + getDelegatedFrozenV2BalanceForBandwidth(); + } else { + return getFrozenV2BalanceForEnergy() + getDelegatedFrozenV2BalanceForEnergy(); + } + } + } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java index 9c06ef83d95..ee57107a72e 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -561,13 +561,13 @@ private TVMTestResult delegateResource( AccountCapsule newReceiver = accountStore.get(receiverAddr); Assert.assertNotNull(newReceiver); if (res == 0) { - Assert.assertEquals(oldOwner.getDelegatedFrozenBalanceForBandwidth() + amount, - newOwner.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(oldOwner.getDelegatedFrozenV2BalanceForBandwidth() + amount, + newOwner.getDelegatedFrozenV2BalanceForBandwidth()); Assert.assertEquals(oldReceiver.getAcquiredDelegatedFrozenBalanceForBandwidth() + amount, newReceiver.getAcquiredDelegatedFrozenBalanceForBandwidth()); } else { - Assert.assertEquals(oldOwner.getDelegatedFrozenBalanceForEnergy() + amount, - newOwner.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(oldOwner.getDelegatedFrozenV2BalanceForEnergy() + amount, + newOwner.getDelegatedFrozenV2BalanceForEnergy()); Assert.assertEquals(oldReceiver.getAcquiredDelegatedFrozenBalanceForEnergy() + amount, newReceiver.getAcquiredDelegatedFrozenBalanceForEnergy()); } @@ -656,16 +656,16 @@ private TVMTestResult unDelegateResource( newOwner.setBalance(oldOwner.getBalance()); if (res == 0) { Assert.assertEquals( - oldOwner.getDelegatedFrozenBalanceForBandwidth() - amount, - newOwner.getDelegatedFrozenBalanceForBandwidth()); + oldOwner.getDelegatedFrozenV2BalanceForBandwidth() - amount, + newOwner.getDelegatedFrozenV2BalanceForBandwidth()); Assert.assertEquals( oldOwner.getFrozenV2BalanceForBandwidth() + amount, newOwner.getFrozenV2BalanceForBandwidth()); Assert.assertEquals(oldOwner.getNetUsage() + transferUsage, newOwner.getNetUsage()); } else { Assert.assertEquals( - oldOwner.getDelegatedFrozenBalanceForEnergy() - amount, - newOwner.getDelegatedFrozenBalanceForEnergy()); + oldOwner.getDelegatedFrozenV2BalanceForEnergy() - amount, + newOwner.getDelegatedFrozenV2BalanceForEnergy()); Assert.assertEquals( oldOwner.getFrozenV2BalanceForEnergy() + amount, newOwner.getFrozenV2BalanceForEnergy()); Assert.assertEquals(oldOwner.getEnergyUsage() + transferUsage, newOwner.getEnergyUsage()); diff --git a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java index 74b1edbfc37..7d21c0bdbe6 100644 --- a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java @@ -42,7 +42,7 @@ public class DelegateResourceActuatorTest { private static final String OWNER_ACCOUNT_INVALID; private static final long initBalance = 10_000_000_000L; private static Manager dbManager; - private static TronApplicationContext context; + private static final TronApplicationContext context; static { Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); @@ -135,23 +135,21 @@ private Any getDelegateContractForBandwidth( .build()); } - private Any getDelegateContractForCpu( - String ownerAddress, String receiveAddress, long unfreezeBalance) { + private Any getDelegateContractForCpu(long unfreezeBalance) { return Any.pack( DelegateResourceContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) - .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiveAddress))) + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))) .setBalance(unfreezeBalance) .setResource(ResourceCode.ENERGY) .build()); } - private Any getDelegateContractForTronPower( - String ownerAddress, String receiveAddress, long unfreezeBalance) { + private Any getDelegateContractForTronPower(long unfreezeBalance) { return Any.pack( DelegateResourceContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) - .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiveAddress))) + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))) .setBalance(unfreezeBalance) .setResource(ResourceCode.TRON_POWER) .build()); @@ -180,7 +178,7 @@ public void testDelegateResourceWithNoFreeze() { } actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getDelegateContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, 1_000_000_000L)); + getDelegateContractForCpu(1_000_000_000L)); try { actuator.validate(); actuator.execute(ret); @@ -238,7 +236,7 @@ public void testDelegateCpuWithUsage() { DelegateResourceActuator actuator = new DelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getDelegateContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, initBalance)); + getDelegateContractForCpu(initBalance)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -316,11 +314,11 @@ public void testDelegateResourceForBandwidth() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); - Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); Assert.assertEquals(initBalance - delegateBalance, ownerCapsule.getFrozenV2BalanceForBandwidth()); Assert.assertEquals(initBalance, ownerCapsule.getTronPower()); @@ -367,7 +365,7 @@ public void testDelegateResourceForCpu() { long delegateBalance = 1_000_000_000L; DelegateResourceActuator actuator = new DelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getDelegateContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + getDelegateContractForCpu(delegateBalance)); TransactionResultCapsule ret = new TransactionResultCapsule(); long totalEnergyWeightBefore = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); @@ -382,8 +380,8 @@ public void testDelegateResourceForCpu() { Assert.assertEquals(initBalance, ownerCapsule.getBalance()); Assert.assertEquals(0L, ownerCapsule.getFrozenBalance()); - Assert.assertEquals(0L, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); - Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0L, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForEnergy()); Assert.assertEquals(initBalance, ownerCapsule.getTronPower()); AccountCapsule receiverCapsule = @@ -450,8 +448,7 @@ public void delegateTronPower() { long delegateBalance = 1_000_000_000L; DelegateResourceActuator actuator = new DelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getDelegateContractForTronPower( - OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + .setAny(getDelegateContractForTronPower(delegateBalance)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { actuator.validate(); diff --git a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java index e403e82167f..9a11e12e101 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java @@ -43,7 +43,7 @@ public class UnDelegateResourceActuatorTest { private static final long initBalance = 10_000_000_000L; private static final long delegateBalance = 1_000_000_000L; private static Manager dbManager; - private static TronApplicationContext context; + private static final TronApplicationContext context; static { Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); @@ -106,7 +106,7 @@ public void delegateBandwidthForOwner() { byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); - ownerCapsule.addDelegatedFrozenBalanceForBandwidth(delegateBalance); + ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(delegateBalance); dbManager.getAccountStore().put(owner, ownerCapsule); AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(delegateBalance); @@ -127,7 +127,7 @@ public void delegateCpuForOwner() { byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); - ownerCapsule.addDelegatedFrozenBalanceForEnergy(delegateBalance); + ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(delegateBalance); dbManager.getAccountStore().put(owner, ownerCapsule); AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(delegateBalance); @@ -144,19 +144,17 @@ public void delegateCpuForOwner() { dbManager.getDelegatedResourceAccountIndexStore().delegateV2(owner, receiver, 1); } - private Any getDelegatedContractForBandwidth( - String ownerAddress, String receiverAddress, long balance) { + private Any getDelegatedContractForBandwidth(String ownerAddress, long balance) { return Any.pack(UnDelegateResourceContract.newBuilder() .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) - .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiverAddress))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))) .setBalance(balance).build()); } - private Any getDelegatedContractForCpu( - String ownerAddress, String receiverAddress, long balance) { + private Any getDelegatedContractForCpu(long balance) { return Any.pack(UnDelegateResourceContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) - .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiverAddress))) + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))) .setResource(ResourceCode.ENERGY) .setBalance(balance).build()); } @@ -183,14 +181,14 @@ public void testUnDelegateForBandwidth() { UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + getDelegatedContractForBandwidth(OWNER_ADDRESS, delegateBalance)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { ownerCapsule = dbManager.getAccountStore().get(owner); Assert.assertEquals(delegateBalance, receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); - Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForBandwidth()); Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); Assert.assertEquals(1_000_000_000, ownerCapsule.getNetUsage()); @@ -198,13 +196,13 @@ public void testUnDelegateForBandwidth() { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); // check owner ownerCapsule = dbManager.getAccountStore().get(owner); - Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForBandwidth()); - Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); Assert.assertEquals(1000000000, ownerCapsule.getNetUsage()); Assert.assertEquals(nowSlot, ownerCapsule.getLatestConsumeTime()); @@ -250,14 +248,14 @@ public void testPartialUnDelegateForBandwidth() { UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance / 2)); + getDelegatedContractForBandwidth(OWNER_ADDRESS, delegateBalance / 2)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); Assert.assertEquals(delegateBalance, receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); - Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForBandwidth()); Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); Assert.assertEquals(0, ownerCapsule.getNetUsage()); @@ -265,15 +263,15 @@ public void testPartialUnDelegateForBandwidth() { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); // check owner ownerCapsule = dbManager.getAccountStore().get(owner); Assert.assertEquals(delegateBalance / 2, - ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); Assert.assertEquals(delegateBalance / 2, ownerCapsule.getFrozenV2BalanceForBandwidth()); - Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); Assert.assertEquals(1000000000 / 2, ownerCapsule.getNetUsage()); Assert.assertEquals(dbManager.getChainBaseManager().getHeadSlot(), ownerCapsule.getLatestConsumeTime()); @@ -319,19 +317,19 @@ public void testUnDelegatedForBandwidthWithDeletedReceiver() { UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + getDelegatedContractForBandwidth(OWNER_ADDRESS, delegateBalance)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); // check owner AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); - Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForBandwidth()); - Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); Assert.assertEquals(0, ownerCapsule.getNetUsage()); // check receiver @@ -380,19 +378,19 @@ public void testUnDelegatedForBandwidthWithRecreatedReceiver() { UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + .setAny(getDelegatedContractForBandwidth(OWNER_ADDRESS, delegateBalance)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); // check owner AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); - Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForBandwidth()); - Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); Assert.assertEquals(0, ownerCapsule.getNetUsage()); // check receiver @@ -442,14 +440,14 @@ public void testUnDelegatedForCpu() { UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getDelegatedContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + .setAny(getDelegatedContractForCpu(delegateBalance)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { ownerCapsule = dbManager.getAccountStore().get(owner); Assert.assertEquals(delegateBalance, receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); - Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForEnergy()); Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForEnergy()); Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); Assert.assertEquals(1_000_000_000, ownerCapsule.getEnergyUsage()); @@ -457,13 +455,13 @@ public void testUnDelegatedForCpu() { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); // check owner ownerCapsule = dbManager.getAccountStore().get(owner); - Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenV2BalanceForEnergy()); Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForEnergy()); - Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); Assert.assertEquals(1_000_000_000, ownerCapsule.getEnergyUsage()); Assert.assertEquals(nowSlot, ownerCapsule.getLatestConsumeTimeForEnergy()); @@ -509,14 +507,14 @@ public void testPartialUnDelegatedForCpu() { UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getDelegatedContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance / 2)); + .setAny(getDelegatedContractForCpu(delegateBalance / 2)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); Assert.assertEquals(delegateBalance, receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); - Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForEnergy()); Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForEnergy()); Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); Assert.assertEquals(0, ownerCapsule.getEnergyUsage()); @@ -524,13 +522,13 @@ public void testPartialUnDelegatedForCpu() { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); // check owner ownerCapsule = dbManager.getAccountStore().get(owner); - Assert.assertEquals(delegateBalance / 2, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(delegateBalance / 2, ownerCapsule.getDelegatedFrozenV2BalanceForEnergy()); Assert.assertEquals(delegateBalance / 2, ownerCapsule.getFrozenV2BalanceForEnergy()); - Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); Assert.assertEquals(1_000_000_000 / 2, ownerCapsule.getEnergyUsage()); Assert.assertEquals(dbManager.getChainBaseManager().getHeadSlot(), ownerCapsule.getLatestConsumeTimeForEnergy()); @@ -575,19 +573,19 @@ public void testUnDelegatedForCpuWithDeletedReceiver() { UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getDelegatedContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + .setAny(getDelegatedContractForCpu(delegateBalance)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); // check owner AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); - Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenV2BalanceForEnergy()); Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForEnergy()); - Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); Assert.assertEquals(0, ownerCapsule.getEnergyUsage()); // check receiver @@ -635,19 +633,19 @@ public void testUnDelegatedForCpuWithRecreatedReceiver() { UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getDelegatedContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + .setAny(getDelegatedContractForCpu(delegateBalance)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); // check owner AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); - Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenV2BalanceForEnergy()); Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForEnergy()); - Assert.assertEquals(ownerCapsule.getTronPower(), delegateBalance); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); Assert.assertEquals(0, ownerCapsule.getEnergyUsage()); // check receiver @@ -681,8 +679,7 @@ public void testUnDelegatedForCpuWithRecreatedReceiver() { public void invalidOwnerAddress() { UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getDelegatedContractForBandwidth( - OWNER_ADDRESS_INVALID, RECEIVER_ADDRESS, delegateBalance)); + .setAny(getDelegatedContractForBandwidth(OWNER_ADDRESS_INVALID, delegateBalance)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { actuator.validate(); @@ -702,7 +699,7 @@ public void invalidOwnerAddress() { public void invalidOwnerAccount() { UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getDelegatedContractForBandwidth(OWNER_ACCOUNT_INVALID, RECEIVER_ADDRESS, delegateBalance)); + getDelegatedContractForBandwidth(OWNER_ACCOUNT_INVALID, delegateBalance)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { actuator.validate(); @@ -720,7 +717,7 @@ public void invalidOwnerAccount() { public void noDelegateBalance() { UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + .setAny(getDelegatedContractForBandwidth(OWNER_ADDRESS, delegateBalance)); TransactionResultCapsule ret = new TransactionResultCapsule(); try { @@ -734,7 +731,7 @@ public void noDelegateBalance() { } actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getDelegatedContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + .setAny(getDelegatedContractForCpu(delegateBalance)); try { actuator.validate(); actuator.execute(ret); @@ -763,13 +760,12 @@ public void commonErrorCheck() { AccountCapsule accountCapsule = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); Assert.assertEquals(0, accountCapsule.getFrozenV2BalanceForBandwidth()); - Assert.assertEquals(delegateBalance, accountCapsule.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(delegateBalance, accountCapsule.getDelegatedFrozenV2BalanceForBandwidth()); Assert.assertEquals(delegateBalance, accountCapsule.getTronPower()); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); - actuatorTest.setContract(getDelegatedContractForBandwidth( - OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + actuatorTest.setContract(getDelegatedContractForBandwidth(OWNER_ADDRESS, delegateBalance)); actuatorTest.nullTransationResult(); actuatorTest.setNullDBManagerMsg("No account store or dynamic store!"); diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java index d1aa0820c6e..6caa3727a0c 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java @@ -44,7 +44,7 @@ public class UnfreezeBalanceV2ActuatorTest { private static final long initBalance = 10_000_000_000L; private static final long frozenBalance = 1_000_000_000L; private static Manager dbManager; - private static TronApplicationContext context; + private static final TronApplicationContext context; static { Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); @@ -157,14 +157,15 @@ private Any getContractForTronPowerV2_001(String ownerAddress, long unfreezeBala public void testUnfreezeBalanceForBandwidth() { long now = System.currentTimeMillis(); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveTotalNetWeight(1000); AccountCapsule accountCapsule = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); long unfreezeBalance = frozenBalance - 100; - Assert.assertEquals(accountCapsule.getFrozenV2BalanceForBandwidth(), frozenBalance); - Assert.assertEquals(accountCapsule.getTronPower(), frozenBalance); + Assert.assertEquals(frozenBalance, accountCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(frozenBalance, accountCapsule.getTronPower()); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); @@ -177,21 +178,19 @@ public void testUnfreezeBalanceForBandwidth() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule owner = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); //Assert.assertEquals(owner.getBalance(), initBalance + frozenBalance); - Assert.assertEquals(owner.getFrozenV2BalanceForBandwidth(), 100); - Assert.assertEquals(owner.getTronPower(), 100L); + Assert.assertEquals(100, owner.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(100L, owner.getTronPower()); long totalNetWeightAfter = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); - Assert.assertEquals(totalNetWeightBefore, - totalNetWeightAfter + (frozenBalance - 100) / 1000_000L); + Assert.assertEquals(totalNetWeightBefore - 1000, totalNetWeightAfter); - } catch (ContractValidateException e) { + } catch (Exception e) { Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } } @@ -201,13 +200,14 @@ public void testUnfreezeBalanceForBandwidth() { public void testUnfreezeBalanceForEnergy() { long now = System.currentTimeMillis(); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveTotalNetWeight(1000); long unfreezeBalance = frozenBalance - 100; AccountCapsule accountCapsule = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); - Assert.assertEquals(accountCapsule.getAllFrozenBalanceForEnergy(), frozenBalance); - Assert.assertEquals(accountCapsule.getTronPower(), frozenBalance); + Assert.assertEquals(frozenBalance, accountCapsule.getAllFrozenBalanceForEnergy()); + Assert.assertEquals(frozenBalance, accountCapsule.getTronPower()); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); @@ -219,19 +219,17 @@ public void testUnfreezeBalanceForEnergy() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule owner = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); //Assert.assertEquals(owner.getBalance(), initBalance + frozenBalance); - Assert.assertEquals(owner.getAllFrozenBalanceForEnergy(), 100); - Assert.assertEquals(owner.getTronPower(), 100); + Assert.assertEquals(100, owner.getAllFrozenBalanceForEnergy()); + Assert.assertEquals(100, owner.getTronPower()); long totalEnergyWeightAfter = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); - Assert.assertEquals(totalEnergyWeightBefore, - totalEnergyWeightAfter + (frozenBalance - 100) / 1000_000L); - } catch (ContractValidateException e) { + Assert.assertEquals(totalEnergyWeightBefore - 1000, totalEnergyWeightAfter); + } catch (Exception e) { Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } } @@ -771,7 +769,7 @@ public void testAddTotalResourceWeight() { .setResource(ResourceCode.TRON_POWER) .build(); - actuator.updateTotalResourceWeight(unfreezeBalanceV2Contract, unfreezeBalance); + actuator.updateTotalResourceWeight(accountCapsule, unfreezeBalanceV2Contract, unfreezeBalance); Assert.assertEquals(total - unfreezeBalance / TRX_PRECISION, dbManager.getDynamicPropertiesStore().getTotalTronPowerWeight()); diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 780b5b71e84..3794370de52 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -212,6 +212,8 @@ message Account { int64 latest_exchange_storage_time = 8; int64 energy_window_size = 9; + + int64 delegated_frozenV2_balance_for_energy = 10; } AccountResource account_resource = 26; bytes codeHash = 30; @@ -230,6 +232,8 @@ message Account { } repeated FreezeV2 frozenV2 = 34; repeated UnFreezeV2 unfrozenV2 = 35; + + int64 delegated_frozenV2_balance_for_bandwidth = 36; } message Key { From e751a2661006232e8a29bca39bb541636bc8d8e6 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 23 Nov 2022 21:05:00 +0800 Subject: [PATCH 0444/1197] fix(freezeV2): deduct resource of old freezing first --- .../actuator/DelegateResourceActuator.java | 30 ++++++---- .../actuator/UnDelegateResourceActuator.java | 12 ++-- .../DelegateResourceProcessor.java | 30 ++++++---- .../UnDelegateResourceProcessor.java | 12 ++-- .../org/tron/core/capsule/AccountCapsule.java | 55 +++++++++++++++++-- .../src/main/java/org/tron/core/Wallet.java | 25 ++++++--- .../tron/common/runtime/vm/FreezeV2Test.java | 24 ++++---- .../DelegateResourceActuatorTest.java | 8 +-- .../UnDelegateResourceActuatorTest.java | 32 +++++------ protocol/src/main/protos/core/Tron.proto | 2 + 10 files changed, 150 insertions(+), 80 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 5f8fae99771..a107b92e163 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -150,14 +150,16 @@ public boolean validate() throws ContractValidateException { long netUsage = (long) (accountNetUsage * TRX_PRECISION * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); - long ownerNetUsage = (long) (netUsage * ((double) (ownerCapsule - .getFrozenV2BalanceForBandwidth()) / - ownerCapsule.getAllFrozenBalanceForBandwidth())); + long remainNetUsage = netUsage + - ownerCapsule.getFrozenBalance() + - ownerCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() + - ownerCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth(); - if (ownerCapsule.getFrozenV2BalanceForBandwidth() - ownerNetUsage - < delegateBalance) { + remainNetUsage = Math.max(0, remainNetUsage); + + if (ownerCapsule.getFrozenV2BalanceForBandwidth() - remainNetUsage < delegateBalance) { throw new ContractValidateException( - "delegateBalance must be less than available FreezeBandwidthV2 balance"); + "delegateBalance must be less than available FreezeBandwidthV2 balance"); } } break; @@ -168,12 +170,16 @@ public boolean validate() throws ContractValidateException { long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); - long ownerEnergyUsage = (long) (energyUsage * ((double) (ownerCapsule - .getFrozenV2BalanceForEnergy()) / ownerCapsule.getAllFrozenBalanceForEnergy())); + long remainEnergyUsage = energyUsage + - ownerCapsule.getEnergyFrozenBalance() + - ownerCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() + - ownerCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy(); + + remainEnergyUsage = Math.max(0, remainEnergyUsage); - if (ownerCapsule.getFrozenV2BalanceForEnergy() - ownerEnergyUsage < delegateBalance) { + if (ownerCapsule.getFrozenV2BalanceForEnergy() - remainEnergyUsage < delegateBalance) { throw new ContractValidateException( - "delegateBalance must be less than available FreezeEnergyV2Balance balance"); + "delegateBalance must be less than available FreezeEnergyV2Balance balance"); } } break; @@ -251,9 +257,9 @@ private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boole //modify AccountStore for receiver AccountCapsule receiverCapsule = accountStore.get(receiverAddress); if (isBandwidth) { - receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(balance); + receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForBandwidth(balance); } else { - receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(balance); + receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForEnergy(balance); } accountStore.put(receiverCapsule.createDbKey(), receiverCapsule); } diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index 1bc2ad0b55b..85fd0120395 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -72,10 +72,10 @@ public boolean execute(Object result) throws ContractExeException { BandwidthProcessor bandwidthProcessor = new BandwidthProcessor(chainBaseManager); bandwidthProcessor.updateUsage(receiverCapsule); - if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() + if (receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth() < unDelegateBalance) { // A TVM contract suicide, re-create will produce this situation - receiverCapsule.setAcquiredDelegatedFrozenBalanceForBandwidth(0); + receiverCapsule.setAcquiredDelegatedFrozenV2BalanceForBandwidth(0); } else { // calculate usage long unDelegateMaxUsage = (long) ((double) unDelegateBalance / TRX_PRECISION @@ -84,7 +84,7 @@ public boolean execute(Object result) throws ContractExeException { * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForBandwidth())); transferUsage = Math.min(unDelegateMaxUsage, transferUsage); - receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(-unDelegateBalance); + receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForBandwidth(-unDelegateBalance); } long newNetUsage = receiverCapsule.getNetUsage() - transferUsage; @@ -95,10 +95,10 @@ public boolean execute(Object result) throws ContractExeException { EnergyProcessor energyProcessor = new EnergyProcessor(dynamicStore, accountStore); energyProcessor.updateUsage(receiverCapsule); - if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() + if (receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy() < unDelegateBalance) { // A TVM contract receiver, re-create will produce this situation - receiverCapsule.setAcquiredDelegatedFrozenBalanceForEnergy(0); + receiverCapsule.setAcquiredDelegatedFrozenV2BalanceForEnergy(0); } else { // calculate usage long unDelegateMaxUsage = (long) ((double) unDelegateBalance / TRX_PRECISION @@ -107,7 +107,7 @@ public boolean execute(Object result) throws ContractExeException { * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForEnergy())); transferUsage = Math.min(unDelegateMaxUsage, transferUsage); - receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(-unDelegateBalance); + receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForEnergy(-unDelegateBalance); } long newEnergyUsage = receiverCapsule.getEnergyUsage() - transferUsage; diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index 42203d503fa..55ec640d34e 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -57,14 +57,16 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra long netUsage = (long) (ownerCapsule.getNetUsage() * TRX_PRECISION * ((double) (repo.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); - long ownerNetUsage = (long) (netUsage * ((double)(ownerCapsule - .getFrozenV2BalanceForBandwidth()) / - ownerCapsule.getAllFrozenBalanceForBandwidth())); + long remainNetUsage = netUsage + - ownerCapsule.getFrozenBalance() + - ownerCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() + - ownerCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth(); - if (ownerCapsule.getFrozenV2BalanceForBandwidth() - ownerNetUsage - < delegateBalance) { + remainNetUsage = Math.max(0, remainNetUsage); + + if (ownerCapsule.getFrozenV2BalanceForBandwidth() - remainNetUsage < delegateBalance) { throw new ContractValidateException( - "delegateBalance must be less than available FreezeBandwidthV2 balance"); + "delegateBalance must be less than available FreezeBandwidthV2 balance"); } } break; @@ -76,12 +78,16 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) (repo.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); - long ownerEnergyUsage = (long) (energyUsage * ((double)(ownerCapsule - .getFrozenV2BalanceForEnergy()) / ownerCapsule.getAllFrozenBalanceForEnergy())); + long remainEnergyUsage = energyUsage + - ownerCapsule.getEnergyFrozenBalance() + - ownerCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() + - ownerCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy(); + + remainEnergyUsage = Math.max(0, remainEnergyUsage); - if (ownerCapsule.getFrozenV2BalanceForEnergy() - ownerEnergyUsage < delegateBalance) { + if (ownerCapsule.getFrozenV2BalanceForEnergy() - remainEnergyUsage < delegateBalance) { throw new ContractValidateException( - "delegateBalance must be less than available FreezeEnergyV2Balance balance"); + "delegateBalance must be less than available FreezeEnergyV2Balance balance"); } } break; @@ -164,9 +170,9 @@ private void delegateResource( //update Account for receiver AccountCapsule receiverCapsule = repo.getAccount(receiverAddress); if (isBandwidth) { - receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(delegateBalance); + receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForBandwidth(delegateBalance); } else { - receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(delegateBalance); + receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForEnergy(delegateBalance); } repo.updateDelegatedResource(key, delegatedResourceCapsule); repo.updateAccount(receiverCapsule.createDbKey(), receiverCapsule); diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index 091608050bd..8a98cf26ee5 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -102,10 +102,10 @@ public void execute(UnDelegateResourceParam param, Repository repo) { BandwidthProcessor bandwidthProcessor = new BandwidthProcessor(ChainBaseManager.getInstance()); bandwidthProcessor.updateUsage(receiverCapsule); - if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() + if (receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth() < unDelegateBalance) { // A TVM contract suicide, re-create will produce this situation - receiverCapsule.setAcquiredDelegatedFrozenBalanceForBandwidth(0); + receiverCapsule.setAcquiredDelegatedFrozenV2BalanceForBandwidth(0); } else { // calculate usage long unDelegateMaxUsage = (long) ((double) unDelegateBalance / TRX_PRECISION @@ -114,7 +114,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForBandwidth())); transferUsage = Math.min(unDelegateMaxUsage, transferUsage); - receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(-unDelegateBalance); + receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForBandwidth(-unDelegateBalance); } long newNetUsage = receiverCapsule.getNetUsage() - transferUsage; @@ -126,10 +126,10 @@ public void execute(UnDelegateResourceParam param, Repository repo) { new EnergyProcessor(dynamicStore, ChainBaseManager.getInstance().getAccountStore()); energyProcessor.updateUsage(receiverCapsule); - if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() + if (receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy() < unDelegateBalance) { // A TVM contract receiver, re-create will produce this situation - receiverCapsule.setAcquiredDelegatedFrozenBalanceForEnergy(0); + receiverCapsule.setAcquiredDelegatedFrozenV2BalanceForEnergy(0); } else { // calculate usage long unDelegateMaxUsage = (long) ((double) unDelegateBalance / TRX_PRECISION @@ -138,7 +138,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForEnergy())); transferUsage = Math.min(unDelegateMaxUsage, transferUsage); - receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(-unDelegateBalance); + receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForEnergy(-unDelegateBalance); } long newEnergyUsage = receiverCapsule.getEnergyUsage() - transferUsage; diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index 7213ac39000..a3b31e8baa4 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -365,6 +365,10 @@ public long getAcquiredDelegatedFrozenBalanceForBandwidth() { return this.account.getAcquiredDelegatedFrozenBalanceForBandwidth(); } + public long getAcquiredDelegatedFrozenV2BalanceForBandwidth() { + return this.account.getAcquiredDelegatedFrozenV2BalanceForBandwidth(); + } + public void addFrozenBalanceForBandwidthV2(long balance) { this.addFrozenBalanceForResource(BANDWIDTH, balance); } @@ -374,22 +378,42 @@ public void setAcquiredDelegatedFrozenBalanceForBandwidth(long balance) { .build(); } + public void setAcquiredDelegatedFrozenV2BalanceForBandwidth(long balance) { + this.account = this.account.toBuilder().setAcquiredDelegatedFrozenV2BalanceForBandwidth(balance) + .build(); + } + public void addAcquiredDelegatedFrozenBalanceForBandwidth(long balance) { this.account = this.account.toBuilder().setAcquiredDelegatedFrozenBalanceForBandwidth( this.account.getAcquiredDelegatedFrozenBalanceForBandwidth() + balance) .build(); } + public void addAcquiredDelegatedFrozenV2BalanceForBandwidth(long balance) { + this.account = this.account.toBuilder().setAcquiredDelegatedFrozenV2BalanceForBandwidth( + this.account.getAcquiredDelegatedFrozenV2BalanceForBandwidth() + balance).build(); + } + public void safeAddAcquiredDelegatedFrozenBalanceForBandwidth(long balance) { this.account = this.account.toBuilder().setAcquiredDelegatedFrozenBalanceForBandwidth( Math.max(0, this.account.getAcquiredDelegatedFrozenBalanceForBandwidth() + balance)) .build(); } + public void safeAddAcquiredDelegatedFrozenV2BalanceForBandwidth(long balance) { + this.account = this.account.toBuilder().setAcquiredDelegatedFrozenV2BalanceForBandwidth( + Math.max(0, this.account.getAcquiredDelegatedFrozenV2BalanceForBandwidth() + balance)) + .build(); + } + public long getAcquiredDelegatedFrozenBalanceForEnergy() { return getAccountResource().getAcquiredDelegatedFrozenBalanceForEnergy(); } + public long getAcquiredDelegatedFrozenV2BalanceForEnergy() { + return getAccountResource().getAcquiredDelegatedFrozenV2BalanceForEnergy(); + } + public void setAcquiredDelegatedFrozenBalanceForEnergy(long balance) { AccountResource newAccountResource = getAccountResource().toBuilder() .setAcquiredDelegatedFrozenBalanceForEnergy(balance).build(); @@ -399,6 +423,12 @@ public void setAcquiredDelegatedFrozenBalanceForEnergy(long balance) { .build(); } + public void setAcquiredDelegatedFrozenV2BalanceForEnergy(long balance) { + AccountResource newAccountResource = getAccountResource().toBuilder() + .setAcquiredDelegatedFrozenV2BalanceForEnergy(balance).build(); + this.account = this.account.toBuilder().setAccountResource(newAccountResource).build(); + } + public long getDelegatedFrozenBalanceForEnergy() { return getAccountResource().getDelegatedFrozenBalanceForEnergy(); } @@ -440,6 +470,13 @@ public void addAcquiredDelegatedFrozenBalanceForEnergy(long balance) { .build(); } + public void addAcquiredDelegatedFrozenV2BalanceForEnergy(long balance) { + AccountResource newAccountResource = getAccountResource().toBuilder() + .setAcquiredDelegatedFrozenV2BalanceForEnergy(getAccountResource() + .getAcquiredDelegatedFrozenV2BalanceForEnergy() + balance).build(); + this.account = this.account.toBuilder().setAccountResource(newAccountResource).build(); + } + public void safeAddAcquiredDelegatedFrozenBalanceForEnergy(long balance) { AccountResource newAccountResource = getAccountResource().toBuilder() .setAcquiredDelegatedFrozenBalanceForEnergy( @@ -451,6 +488,13 @@ public void safeAddAcquiredDelegatedFrozenBalanceForEnergy(long balance) { .build(); } + public void safeAddAcquiredDelegatedFrozenV2BalanceForEnergy(long balance) { + AccountResource newAccountResource = getAccountResource().toBuilder() + .setAcquiredDelegatedFrozenV2BalanceForEnergy(Math.max(0, getAccountResource() + .getAcquiredDelegatedFrozenV2BalanceForEnergy() + balance)).build(); + this.account = this.account.toBuilder().setAccountResource(newAccountResource).build(); + } + public void addDelegatedFrozenBalanceForEnergy(long balance) { AccountResource newAccountResource = getAccountResource().toBuilder() .setDelegatedFrozenBalanceForEnergy( @@ -877,7 +921,7 @@ public long getFrozenV2BalanceForBandwidth() { public long getAllFrozenBalanceForBandwidth() { return getFrozenBalance() + getAcquiredDelegatedFrozenBalanceForBandwidth() - + getFrozenV2BalanceForBandwidth(); + + getFrozenV2BalanceForBandwidth() + getAcquiredDelegatedFrozenV2BalanceForBandwidth(); } public int getFrozenSupplyCount() { @@ -1097,7 +1141,7 @@ public void setEnergyUsage(long energyUsage) { public long getAllFrozenBalanceForEnergy() { return getEnergyFrozenBalance() + getAcquiredDelegatedFrozenBalanceForEnergy() - + getFrozenV2BalanceForEnergy(); + + getFrozenV2BalanceForEnergy() + getAcquiredDelegatedFrozenV2BalanceForEnergy(); } public long getLatestConsumeTimeForEnergy() { @@ -1255,9 +1299,12 @@ public void updateAccountType(AccountType accountType) { public void clearDelegatedResource() { Builder builder = account.toBuilder(); AccountResource newAccountResource = getAccountResource().toBuilder() - .setAcquiredDelegatedFrozenBalanceForEnergy(0L).build(); + .setAcquiredDelegatedFrozenBalanceForEnergy(0L) + .setAcquiredDelegatedFrozenV2BalanceForEnergy(0L) + .build(); builder.setAccountResource(newAccountResource); - builder.setAcquiredDelegatedFrozenBalanceForBandwidth(0L); + builder.setAcquiredDelegatedFrozenBalanceForBandwidth(0L) + .setAcquiredDelegatedFrozenV2BalanceForBandwidth(0L); this.account = builder.build(); } diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 3534af906fe..ec90b1976d9 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -868,10 +868,15 @@ public long calcCanDelegatedBandWidthMaxSize( long netUsage = (long) (accountNetUsage * TRX_PRECISION * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); - long ownerNetUsage = (long) (netUsage * ((double)(ownerCapsule.getFrozenV2BalanceForBandwidth()) - / ownerCapsule.getAllFrozenBalanceForBandwidth())); - long remain = ownerCapsule.getFrozenV2BalanceForBandwidth() - ownerNetUsage; - return remain > 0 ? remain : 0; + long remainNetUsage = netUsage + - ownerCapsule.getFrozenBalance() + - ownerCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() + - ownerCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth(); + + remainNetUsage = Math.max(0, remainNetUsage); + + long maxSize = ownerCapsule.getFrozenV2BalanceForBandwidth() - remainNetUsage; + return Math.max(0, maxSize); } public long calcCanDelegatedEnergyMaxSize(ByteString ownerAddress) { @@ -888,11 +893,15 @@ public long calcCanDelegatedEnergyMaxSize(ByteString ownerAddress) { long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); - long ownerEnergyUsage = (long) (energyUsage * ((double)(ownerCapsule - .getFrozenV2BalanceForEnergy()) / ownerCapsule.getAllFrozenBalanceForEnergy())); + long remainEnergyUsage = energyUsage + - ownerCapsule.getEnergyFrozenBalance() + - ownerCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() + - ownerCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy(); + + remainEnergyUsage = Math.max(0, remainEnergyUsage); - long remain = ownerCapsule.getFrozenV2BalanceForEnergy() - ownerEnergyUsage; - return remain > 0 ? remain : 0; + long maxSize = ownerCapsule.getFrozenV2BalanceForEnergy() - remainEnergyUsage; + return Math.max(0, maxSize); } public DelegatedResourceAccountIndex getDelegatedResourceAccountIndex(ByteString address) { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java index ee57107a72e..efb963cc42b 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -563,13 +563,13 @@ private TVMTestResult delegateResource( if (res == 0) { Assert.assertEquals(oldOwner.getDelegatedFrozenV2BalanceForBandwidth() + amount, newOwner.getDelegatedFrozenV2BalanceForBandwidth()); - Assert.assertEquals(oldReceiver.getAcquiredDelegatedFrozenBalanceForBandwidth() + amount, - newReceiver.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(oldReceiver.getAcquiredDelegatedFrozenV2BalanceForBandwidth() + amount, + newReceiver.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); } else { Assert.assertEquals(oldOwner.getDelegatedFrozenV2BalanceForEnergy() + amount, newOwner.getDelegatedFrozenV2BalanceForEnergy()); - Assert.assertEquals(oldReceiver.getAcquiredDelegatedFrozenBalanceForEnergy() + amount, - newReceiver.getAcquiredDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(oldReceiver.getAcquiredDelegatedFrozenV2BalanceForEnergy() + amount, + newReceiver.getAcquiredDelegatedFrozenV2BalanceForEnergy()); } newReceiver.setBalance(oldReceiver.getBalance()); oldReceiver.setEnergyUsage(0); @@ -577,11 +577,11 @@ private TVMTestResult delegateResource( newReceiver.setEnergyUsage(0); newReceiver.setNewWindowSize(ENERGY,28800); if (res == 0) { - oldReceiver.setAcquiredDelegatedFrozenBalanceForBandwidth(0); - newReceiver.setAcquiredDelegatedFrozenBalanceForBandwidth(0); + oldReceiver.setAcquiredDelegatedFrozenV2BalanceForBandwidth(0); + newReceiver.setAcquiredDelegatedFrozenV2BalanceForBandwidth(0); } else { - oldReceiver.setAcquiredDelegatedFrozenBalanceForEnergy(0); - newReceiver.setAcquiredDelegatedFrozenBalanceForEnergy(0); + oldReceiver.setAcquiredDelegatedFrozenV2BalanceForEnergy(0); + newReceiver.setAcquiredDelegatedFrozenV2BalanceForEnergy(0); } Assert.assertArrayEquals(oldReceiver.getData(), newReceiver.getData()); @@ -620,8 +620,8 @@ private TVMTestResult unDelegateResource( long acquiredBalance = 0; long transferUsage = 0; if (oldReceiver != null) { - acquiredBalance = res == 0 ? oldReceiver.getAcquiredDelegatedFrozenBalanceForBandwidth() : - oldReceiver.getAcquiredDelegatedFrozenBalanceForEnergy(); + acquiredBalance = res == 0 ? oldReceiver.getAcquiredDelegatedFrozenV2BalanceForBandwidth() : + oldReceiver.getAcquiredDelegatedFrozenV2BalanceForEnergy(); if (res == 0) { long unDelegateMaxUsage = (long) (amount / TRX_PRECISION @@ -677,8 +677,8 @@ private TVMTestResult unDelegateResource( Assert.assertNotNull(newReceiver); long newAcquiredBalance = res == 0 - ? newReceiver.getAcquiredDelegatedFrozenBalanceForBandwidth() - : newReceiver.getAcquiredDelegatedFrozenBalanceForEnergy(); + ? newReceiver.getAcquiredDelegatedFrozenV2BalanceForBandwidth() + : newReceiver.getAcquiredDelegatedFrozenV2BalanceForEnergy(); Assert.assertTrue(newAcquiredBalance == 0 || acquiredBalance - newAcquiredBalance == amount); if (res == 0) { Assert.assertEquals(oldReceiver.getNetUsage() - transferUsage, newReceiver.getNetUsage()); diff --git a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java index 7d21c0bdbe6..f757d95f1cd 100644 --- a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java @@ -326,8 +326,8 @@ public void testDelegateResourceForBandwidth() { AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); Assert.assertEquals(delegateBalance, - receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); - Assert.assertEquals(0L, receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(0L, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy()); Assert.assertEquals(0L, receiverCapsule.getTronPower()); DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore() @@ -386,9 +386,9 @@ public void testDelegateResourceForCpu() { AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); - Assert.assertEquals(0L, receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0L, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); Assert.assertEquals(delegateBalance, - receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy()); Assert.assertEquals(0L, receiverCapsule.getTronPower()); DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore() diff --git a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java index 9a11e12e101..c9184c6dafe 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java @@ -109,7 +109,7 @@ public void delegateBandwidthForOwner() { ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(delegateBalance); dbManager.getAccountStore().put(owner, ownerCapsule); AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); - receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(delegateBalance); + receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForBandwidth(delegateBalance); dbManager.getAccountStore().put(receiver, receiverCapsule); dbManager.getDynamicPropertiesStore().addTotalNetWeight(delegateBalance / TRX_PRECISION); @@ -130,7 +130,7 @@ public void delegateCpuForOwner() { ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(delegateBalance); dbManager.getAccountStore().put(owner, ownerCapsule); AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); - receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(delegateBalance); + receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForEnergy(delegateBalance); dbManager.getAccountStore().put(receiver, receiverCapsule); dbManager.getDynamicPropertiesStore().addTotalEnergyWeight(delegateBalance / TRX_PRECISION); @@ -187,7 +187,7 @@ public void testUnDelegateForBandwidth() { try { ownerCapsule = dbManager.getAccountStore().get(owner); Assert.assertEquals(delegateBalance, - receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForBandwidth()); Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); @@ -208,7 +208,7 @@ public void testUnDelegateForBandwidth() { // check receiver receiverCapsule = dbManager.getAccountStore().get(receiver); - Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); Assert.assertEquals(0, receiverCapsule.getNetUsage()); //check DelegatedResource @@ -254,7 +254,7 @@ public void testPartialUnDelegateForBandwidth() { try { AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); Assert.assertEquals(delegateBalance, - receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForBandwidth()); Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); @@ -279,7 +279,7 @@ public void testPartialUnDelegateForBandwidth() { // check receiver receiverCapsule = dbManager.getAccountStore().get(receiver); Assert.assertEquals(delegateBalance / 2, - receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); Assert.assertEquals(1000000000 / 2, receiverCapsule.getNetUsage()); //check DelegatedResource @@ -371,10 +371,10 @@ public void testUnDelegatedForBandwidthWithRecreatedReceiver() { AccountCapsule receiverCapsule = new AccountCapsule(ByteString.copyFromUtf8("receiver"), ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), AccountType.Normal, initBalance); - receiverCapsule.setAcquiredDelegatedFrozenBalanceForBandwidth(10L); + receiverCapsule.setAcquiredDelegatedFrozenV2BalanceForBandwidth(10L); dbManager.getAccountStore().put(receiver, receiverCapsule); receiverCapsule = dbManager.getAccountStore().get(receiver); - Assert.assertEquals(10, receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(10, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) @@ -395,7 +395,7 @@ public void testUnDelegatedForBandwidthWithRecreatedReceiver() { // check receiver receiverCapsule = dbManager.getAccountStore().get(receiver); - Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); //check DelegatedResource byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); @@ -446,7 +446,7 @@ public void testUnDelegatedForCpu() { try { ownerCapsule = dbManager.getAccountStore().get(owner); Assert.assertEquals(delegateBalance, - receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy()); Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForEnergy()); Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForEnergy()); Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); @@ -467,7 +467,7 @@ public void testUnDelegatedForCpu() { // check receiver receiverCapsule = dbManager.getAccountStore().get(receiver); - Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy()); Assert.assertEquals(0, receiverCapsule.getEnergyUsage()); //check DelegatedResource @@ -513,7 +513,7 @@ public void testPartialUnDelegatedForCpu() { try { AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); Assert.assertEquals(delegateBalance, - receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy()); Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForEnergy()); Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForEnergy()); Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); @@ -536,7 +536,7 @@ public void testPartialUnDelegatedForCpu() { // check receiver receiverCapsule = dbManager.getAccountStore().get(receiver); Assert.assertEquals(delegateBalance / 2, - receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy()); Assert.assertEquals(1_000_000_000 / 2, receiverCapsule.getEnergyUsage()); //check DelegatedResource @@ -626,10 +626,10 @@ public void testUnDelegatedForCpuWithRecreatedReceiver() { AccountCapsule receiverCapsule = new AccountCapsule(ByteString.copyFromUtf8("receiver"), ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), AccountType.Normal, initBalance); - receiverCapsule.setAcquiredDelegatedFrozenBalanceForEnergy(10L); + receiverCapsule.setAcquiredDelegatedFrozenV2BalanceForEnergy(10L); dbManager.getAccountStore().put(receiver, receiverCapsule); receiverCapsule = dbManager.getAccountStore().get(receiver); - Assert.assertEquals(10, receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(10, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy()); UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) @@ -650,7 +650,7 @@ public void testUnDelegatedForCpuWithRecreatedReceiver() { // check receiver receiverCapsule = dbManager.getAccountStore().get(receiver); - Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy()); //check DelegatedResource byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 3794370de52..ed3cd8b4698 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -214,6 +214,7 @@ message Account { int64 energy_window_size = 9; int64 delegated_frozenV2_balance_for_energy = 10; + int64 acquired_delegated_frozenV2_balance_for_energy = 11; } AccountResource account_resource = 26; bytes codeHash = 30; @@ -234,6 +235,7 @@ message Account { repeated UnFreezeV2 unfrozenV2 = 35; int64 delegated_frozenV2_balance_for_bandwidth = 36; + int64 acquired_delegated_frozenV2_balance_for_bandwidth = 37; } message Key { From ab59a133e7ba501af075c87283612fbd314a9bf0 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Tue, 15 Nov 2022 15:05:23 +0800 Subject: [PATCH 0445/1197] feat(freezeV2): add a lock option for delegate --- .../actuator/DelegateResourceActuator.java | 32 +++++--- .../actuator/UnDelegateResourceActuator.java | 82 +++++++++++++------ .../capsule/DelegatedResourceCapsule.java | 15 ++-- .../core/store/DelegatedResourceStore.java | 39 +++++++++ .../java/org/tron/core/config/Parameter.java | 1 + .../core/contract/balance_contract.proto | 1 + 6 files changed, 128 insertions(+), 42 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index a107b92e163..148f7782666 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -1,6 +1,7 @@ package org.tron.core.actuator; import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; +import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import com.google.protobuf.ByteString; @@ -57,6 +58,7 @@ public boolean execute(Object result) throws ContractExeException { .get(delegateResourceContract.getOwnerAddress().toByteArray()); long delegateBalance = delegateResourceContract.getBalance(); + boolean lock = delegateResourceContract.getLock(); byte[] ownerAddress = delegateResourceContract.getOwnerAddress().toByteArray(); byte[] receiverAddress = delegateResourceContract.getReceiverAddress().toByteArray(); @@ -64,14 +66,14 @@ public boolean execute(Object result) throws ContractExeException { switch (delegateResourceContract.getResource()) { case BANDWIDTH: delegateResource(ownerAddress, receiverAddress, true, - delegateBalance); + delegateBalance, lock); ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(delegateBalance); ownerCapsule.addFrozenBalanceForBandwidthV2(-delegateBalance); break; case ENERGY: delegateResource(ownerAddress, receiverAddress, false, - delegateBalance); + delegateBalance, lock); ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(delegateBalance); ownerCapsule.addFrozenBalanceForEnergyV2(-delegateBalance); @@ -227,26 +229,36 @@ public long calcFee() { } private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boolean isBandwidth, - long balance) { + long balance, boolean lock) { AccountStore accountStore = chainBaseManager.getAccountStore(); DynamicPropertiesStore dynamicPropertiesStore = chainBaseManager.getDynamicPropertiesStore(); DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore(); DelegatedResourceAccountIndexStore delegatedResourceAccountIndexStore = chainBaseManager .getDelegatedResourceAccountIndexStore(); + // 1. unlock the expired delegate resource + long now = chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); + delegatedResourceStore.unLockExpireResource(ownerAddress, receiverAddress, now); + //modify DelegatedResourceStore - byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress); - DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore - .get(key); + byte[] key; + long expireTime = 0; + if (lock) { + expireTime = now + DELEGATE_PERIOD; + key = DelegatedResourceCapsule.createLockDbKeyV2(ownerAddress, receiverAddress); + } else { + key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress); + } + DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore.get(key); if (delegatedResourceCapsule == null) { - delegatedResourceCapsule = new DelegatedResourceCapsule( - ByteString.copyFrom(ownerAddress), + delegatedResourceCapsule = new DelegatedResourceCapsule(ByteString.copyFrom(ownerAddress), ByteString.copyFrom(receiverAddress)); } + if (isBandwidth) { - delegatedResourceCapsule.addFrozenBalanceForBandwidth(balance, 0); + delegatedResourceCapsule.addFrozenBalanceForBandwidth(balance, expireTime); } else { - delegatedResourceCapsule.addFrozenBalanceForEnergy(balance, 0); + delegatedResourceCapsule.addFrozenBalanceForEnergy(balance, expireTime); } delegatedResourceStore.put(key, delegatedResourceCapsule); diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index 85fd0120395..40c970123d4 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -121,16 +121,20 @@ public boolean execute(Object result) throws ContractExeException { accountStore.put(receiverCapsule.createDbKey(), receiverCapsule); } + // transfer lock delegate to unlock + delegatedResourceStore.unLockExpireResource(ownerAddress, receiverAddress, + dynamicStore.getLatestBlockHeaderTimestamp()); + + byte[] unlockKey = DelegatedResourceCapsule + .createDbKeyV2(ownerAddress, receiverAddress); + DelegatedResourceCapsule unlockResource = delegatedResourceStore + .get(unlockKey); + // modify owner Account AccountCapsule ownerCapsule = accountStore.get(ownerAddress); - byte[] key = DelegatedResourceCapsule - .createDbKeyV2(unDelegateResourceContract.getOwnerAddress().toByteArray(), - unDelegateResourceContract.getReceiverAddress().toByteArray()); - DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore - .get(key); switch (unDelegateResourceContract.getResource()) { case BANDWIDTH: { - delegatedResourceCapsule.addFrozenBalanceForBandwidth(-unDelegateBalance, 0); + unlockResource.addFrozenBalanceForBandwidth(-unDelegateBalance, 0); ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(-unDelegateBalance); ownerCapsule.addFrozenBalanceForBandwidthV2(unDelegateBalance); @@ -146,7 +150,7 @@ public boolean execute(Object result) throws ContractExeException { } break; case ENERGY: { - delegatedResourceCapsule.addFrozenBalanceForEnergy(-unDelegateBalance, 0); + unlockResource.addFrozenBalanceForEnergy(-unDelegateBalance, 0); ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(-unDelegateBalance); ownerCapsule.addFrozenBalanceForEnergyV2(unDelegateBalance); @@ -166,14 +170,21 @@ public boolean execute(Object result) throws ContractExeException { break; } - if (delegatedResourceCapsule.getFrozenBalanceForBandwidth() == 0 - && delegatedResourceCapsule.getFrozenBalanceForEnergy() == 0) { - delegatedResourceStore.delete(key); + if (unlockResource.getFrozenBalanceForBandwidth() == 0 + && unlockResource.getFrozenBalanceForEnergy() == 0) { + delegatedResourceStore.delete(unlockKey); + unlockResource = null; + } else { + delegatedResourceStore.put(unlockKey, unlockResource); + } + byte[] lockKey = DelegatedResourceCapsule + .createLockDbKeyV2(ownerAddress, receiverAddress); + DelegatedResourceCapsule lockResource = delegatedResourceStore + .get(lockKey); + if (lockResource == null && unlockResource == null) { //modify DelegatedResourceAccountIndexStore delegatedResourceAccountIndexStore.unDelegateV2(ownerAddress, receiverAddress); - } else { - delegatedResourceStore.put(key, delegatedResourceCapsule); } accountStore.put(ownerAddress, ownerCapsule); @@ -244,11 +255,12 @@ public boolean validate() throws ContractValidateException { // "Receiver Account[" + readableReceiverAddress + "] does not exist"); // } - byte[] key = DelegatedResourceCapsule - .createDbKeyV2(unDelegateResourceContract.getOwnerAddress().toByteArray(), - unDelegateResourceContract.getReceiverAddress().toByteArray()); + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress); DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore.get(key); - if (delegatedResourceCapsule == null) { + byte[] lockKey = DelegatedResourceCapsule.createLockDbKeyV2(ownerAddress, receiverAddress); + DelegatedResourceCapsule lockResourceCapsule = delegatedResourceStore.get(lockKey); + if (delegatedResourceCapsule == null && lockResourceCapsule == null) { throw new ContractValidateException( "delegated Resource does not exist"); } @@ -258,24 +270,42 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("unDelegateBalance must be more than 0 TRX"); } switch (unDelegateResourceContract.getResource()) { - case BANDWIDTH: - if (delegatedResourceCapsule.getFrozenBalanceForBandwidth() < unDelegateBalance) { - throw new ContractValidateException("insufficient delegatedFrozenBalance(BANDWIDTH), request=" - + unDelegateBalance + ", balance=" + delegatedResourceCapsule.getFrozenBalanceForBandwidth()); + case BANDWIDTH: { + long delegateBalance = 0; + if (delegatedResourceCapsule != null) { + delegateBalance += delegatedResourceCapsule.getFrozenBalanceForBandwidth(); } - break; - case ENERGY: - if (delegatedResourceCapsule.getFrozenBalanceForEnergy() < unDelegateBalance) { + if (lockResourceCapsule != null + && lockResourceCapsule.getExpireTimeForBandwidth() < now) { + delegateBalance += lockResourceCapsule.getFrozenBalanceForBandwidth(); + } + if (delegateBalance < unDelegateBalance) { + throw new ContractValidateException( + "insufficient delegatedFrozenBalance(BANDWIDTH), request=" + + unDelegateBalance + ", unlock_balance=" + delegateBalance); + } + } + break; + case ENERGY: { + long delegateBalance = 0; + if (delegatedResourceCapsule != null) { + delegateBalance += delegatedResourceCapsule.getFrozenBalanceForEnergy(); + } + if (lockResourceCapsule != null + && lockResourceCapsule.getExpireTimeForEnergy() < now) { + delegateBalance += lockResourceCapsule.getFrozenBalanceForEnergy(); + } + if (delegateBalance < unDelegateBalance) { throw new ContractValidateException("insufficient delegateFrozenBalance(Energy), request=" - + unDelegateBalance + ", balance=" + delegatedResourceCapsule.getFrozenBalanceForEnergy()); + + unDelegateBalance + ", unlock_balance=" + delegateBalance); } - break; + } + break; default: throw new ContractValidateException( "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); } - return true; } diff --git a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java index 31c8dc5fb29..bf69bb494cb 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java @@ -1,5 +1,6 @@ package org.tron.core.capsule; +import com.google.common.primitives.Bytes; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import lombok.extern.slf4j.Slf4j; @@ -9,7 +10,9 @@ @Slf4j(topic = "capsule") public class DelegatedResourceCapsule implements ProtoCapsule { - private static final byte[] V2_PREFIX = {0x01}; + public static final byte[] V2_PREFIX = new byte[]{0x01}; + public static final byte[] V2_LOCK_PREFIX = new byte[]{0x02}; + private DelegatedResource delegatedResource; public DelegatedResourceCapsule(final DelegatedResource delegatedResource) { @@ -39,11 +42,11 @@ public static byte[] createDbKey(byte[] from, byte[] to) { } public static byte[] createDbKeyV2(byte[] from, byte[] to) { - byte[] key = new byte[V2_PREFIX.length + from.length + to.length]; - System.arraycopy(V2_PREFIX, 0, key, 0, V2_PREFIX.length); - System.arraycopy(from, 0, key, V2_PREFIX.length, from.length); - System.arraycopy(to, 0, key, V2_PREFIX.length + from.length, to.length); - return key; + return Bytes.concat(V2_PREFIX, from, to); + } + + public static byte[] createLockDbKeyV2(byte[] from, byte[] to) { + return Bytes.concat(V2_LOCK_PREFIX, from, to); } public ByteString getFrom() { diff --git a/chainbase/src/main/java/org/tron/core/store/DelegatedResourceStore.java b/chainbase/src/main/java/org/tron/core/store/DelegatedResourceStore.java index 725c2d005ce..1618b2708d7 100644 --- a/chainbase/src/main/java/org/tron/core/store/DelegatedResourceStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DelegatedResourceStore.java @@ -1,5 +1,6 @@ package org.tron.core.store; +import com.google.protobuf.ByteString; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; @@ -33,4 +34,42 @@ public List getByFrom(byte[] key) { .collect(Collectors.toList()); } + public void unLockExpireResource(byte[] from, byte[] to, long now) { + byte[] lockKey = DelegatedResourceCapsule + .createLockDbKeyV2(from, to); + DelegatedResourceCapsule lockResource = get(lockKey); + if (lockResource == null) { + return; + } + if (lockResource.getExpireTimeForEnergy() >= now + && lockResource.getExpireTimeForBandwidth() >= now) { + return; + } + + byte[] unlockKey = DelegatedResourceCapsule + .createDbKeyV2(from, to); + DelegatedResourceCapsule unlockResource = get(unlockKey); + if (unlockResource == null) { + unlockResource = new DelegatedResourceCapsule(ByteString.copyFrom(from), + ByteString.copyFrom(to)); + } + if (lockResource.getExpireTimeForEnergy() < now) { + unlockResource.addFrozenBalanceForEnergy( + lockResource.getFrozenBalanceForEnergy(), 0); + lockResource.setFrozenBalanceForEnergy(0, 0); + } + if (lockResource.getExpireTimeForBandwidth() < now) { + unlockResource.addFrozenBalanceForBandwidth( + lockResource.getFrozenBalanceForBandwidth(), 0); + lockResource.setFrozenBalanceForBandwidth(0, 0); + } + if (lockResource.getFrozenBalanceForBandwidth() == 0 + && lockResource.getFrozenBalanceForEnergy() == 0) { + delete(lockKey); + } else { + put(lockKey, lockResource); + } + put(unlockKey, unlockResource); + } + } \ No newline at end of file diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index dcaf004af6d..6faf666af8b 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -69,6 +69,7 @@ public class ChainConstant { public static final int MAX_FROZEN_NUMBER = 1; public static final int BLOCK_VERSION = 25; public static final long FROZEN_PERIOD = 86_400_000L; + public static final long DELEGATE_PERIOD = 3 * 86_400_000L; public static final long TRX_PRECISION = 1000_000L; public static final long DELEGATE_COST_BASE_SIZE = 275L; } diff --git a/protocol/src/main/protos/core/contract/balance_contract.proto b/protocol/src/main/protos/core/contract/balance_contract.proto index 284e43a03e6..90a2dfaa48d 100644 --- a/protocol/src/main/protos/core/contract/balance_contract.proto +++ b/protocol/src/main/protos/core/contract/balance_contract.proto @@ -102,6 +102,7 @@ message DelegateResourceContract { ResourceCode resource = 2; int64 balance = 3; bytes receiver_address = 4; + bool lock = 5; } message UnDelegateResourceContract { From 0b5dec1e72531ee9cca5810293f1a390419a0dfe Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Thu, 1 Dec 2022 20:48:29 +0800 Subject: [PATCH 0446/1197] fix(freezeV2): add unit test for locked delegate --- .../DelegateResourceActuatorTest.java | 81 ++++++- .../UnDelegateResourceActuatorTest.java | 226 +++++++++++++++++- 2 files changed, 294 insertions(+), 13 deletions(-) diff --git a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java index f757d95f1cd..8a82c2211da 100644 --- a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java @@ -124,14 +124,20 @@ public void freezeCpuForOwner() { dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); } - private Any getDelegateContractForBandwidth( - String ownerAddress, String receiveAddress, long unfreezeBalance) { - return Any.pack( - DelegateResourceContract.newBuilder() + private Any getDelegateContractForBandwidth(String ownerAddress, String receiveAddress, + long unfreezeBalance) { + return getLockedDelegateContractForBandwidth(ownerAddress, receiveAddress, + unfreezeBalance, false); + } + + private Any getLockedDelegateContractForBandwidth(String ownerAddress, String receiveAddress, + long unfreezeBalance, boolean lock) { + return Any.pack(DelegateResourceContract.newBuilder() .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiveAddress))) .setBalance(unfreezeBalance) .setResource(ResourceCode.BANDWIDTH) + .setLock(lock) .build()); } @@ -359,6 +365,73 @@ public void testDelegateResourceForBandwidth() { } } + @Test + public void testLockedDelegateResourceForBandwidth() { + freezeBandwidthForOwner(); + long delegateBalance = 1_000_000_000L; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getLockedDelegateContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, + delegateBalance, true)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + long totalNetWeightBefore = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); + AccountCapsule ownerCapsule = + dbManager.getAccountStore().get(owner); + + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(initBalance - delegateBalance, + ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(initBalance, ownerCapsule.getTronPower()); + + AccountCapsule receiverCapsule = + dbManager.getAccountStore().get(receiver); + Assert.assertEquals(delegateBalance, + receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(0L, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy()); + Assert.assertEquals(0L, receiverCapsule.getTronPower()); + + DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule + .createDbKeyV2(ByteArray.fromHexString(OWNER_ADDRESS), + ByteArray.fromHexString(RECEIVER_ADDRESS))); + DelegatedResourceCapsule lockedResourceCapsule = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule + .createLockDbKeyV2(ByteArray.fromHexString(OWNER_ADDRESS), + ByteArray.fromHexString(RECEIVER_ADDRESS))); + Assert.assertNull(delegatedResourceCapsule); + Assert.assertNotNull(lockedResourceCapsule); + Assert.assertNotEquals(0, lockedResourceCapsule.getExpireTimeForBandwidth()); + Assert.assertEquals(delegateBalance, lockedResourceCapsule.getFrozenBalanceForBandwidth()); + long totalNetWeightAfter = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); + Assert.assertEquals(totalNetWeightBefore, totalNetWeightAfter); + + //check DelegatedResourceAccountIndex + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().getV2Index(owner); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + Assert.assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); + Assert.assertTrue(ownerIndexCapsule.getToAccountsList() + .contains(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)))); + + DelegatedResourceAccountIndexCapsule receiveCapsule = dbManager + .getDelegatedResourceAccountIndexStore().getV2Index(receiver); + Assert.assertEquals(0, receiveCapsule.getToAccountsList().size()); + Assert.assertEquals(1, receiveCapsule.getFromAccountsList().size()); + Assert.assertTrue(receiveCapsule.getFromAccountsList() + .contains(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)))); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + @Test public void testDelegateResourceForCpu() { freezeCpuForOwner(); diff --git a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java index c9184c6dafe..5d2d04c0269 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java @@ -1,6 +1,7 @@ package org.tron.core.actuator; import static junit.framework.TestCase.fail; +import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import com.google.protobuf.Any; @@ -35,7 +36,7 @@ @Slf4j public class UnDelegateResourceActuatorTest { - private static final String dbPath = "output_undelegate_resource_test"; + private static final String dbPath = "output_unDelegate_resource_test"; private static final String OWNER_ADDRESS; private static final String RECEIVER_ADDRESS; private static final String OWNER_ADDRESS_INVALID = "aaaa"; @@ -98,6 +99,8 @@ public void createAccountCapsule() { byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); dbManager.getDelegatedResourceStore().delete(DelegatedResourceCapsule.createDbKeyV2( owner, receiver)); + dbManager.getDelegatedResourceStore().delete(DelegatedResourceCapsule.createLockDbKeyV2( + owner, receiver)); dbManager.getDelegatedResourceAccountIndexStore().unDelegateV2(owner, receiver); dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); } @@ -123,6 +126,27 @@ public void delegateBandwidthForOwner() { dbManager.getDelegatedResourceAccountIndexStore().delegateV2(owner, receiver, 1); } + public void delegateLockedBandwidthForOwner(long period) { + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(delegateBalance); + dbManager.getAccountStore().put(owner, ownerCapsule); + AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); + receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForBandwidth(delegateBalance); + dbManager.getAccountStore().put(receiver, receiverCapsule); + dbManager.getDynamicPropertiesStore().addTotalNetWeight(delegateBalance / TRX_PRECISION); + + DelegatedResourceCapsule delegatedResourceCapsule = new DelegatedResourceCapsule( + ByteString.copyFrom(owner), + ByteString.copyFrom(receiver)); + delegatedResourceCapsule.setFrozenBalanceForBandwidth(delegateBalance, period); + dbManager.getDelegatedResourceStore().put( + DelegatedResourceCapsule.createLockDbKeyV2(owner, receiver), delegatedResourceCapsule); + + dbManager.getDelegatedResourceAccountIndexStore().delegateV2(owner, receiver, 1); + } + public void delegateCpuForOwner() { byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); @@ -232,6 +256,196 @@ public void testUnDelegateForBandwidth() { } } + @Test + public void testLockedUnDelegateForBandwidth() { + delegateLockedBandwidthForOwner(DELEGATE_PERIOD); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); + receiverCapsule.setNetUsage(1_000_000_000); + long nowSlot = dbManager.getChainBaseManager().getHeadSlot(); + receiverCapsule.setLatestConsumeTime(nowSlot - 14400); + dbManager.getAccountStore().put(receiver, receiverCapsule); + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + ownerCapsule.setNetUsage(1_000_000_000); + ownerCapsule.setLatestConsumeTime(nowSlot - 14400); + dbManager.getAccountStore().put(owner, ownerCapsule); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegatedContractForBandwidth(OWNER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(delegateBalance, + receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); + Assert.assertEquals(1_000_000_000, ownerCapsule.getNetUsage()); + Assert.assertEquals(1_000_000_000, receiverCapsule.getNetUsage()); + DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule.createDbKeyV2(owner, receiver)); + DelegatedResourceCapsule lockedResourceCapsule = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule.createLockDbKeyV2(owner, receiver)); + + Assert.assertNull(delegatedResourceCapsule); + Assert.assertNotNull(lockedResourceCapsule); + + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); + + // check + DelegatedResourceCapsule delegatedResourceCapsule1 = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule.createDbKeyV2(owner, receiver)); + DelegatedResourceCapsule lockedResourceCapsule1 = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule.createLockDbKeyV2(owner, receiver)); + Assert.assertNull(delegatedResourceCapsule1); + Assert.assertNull(lockedResourceCapsule1); + // check owner + ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(0, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); + Assert.assertEquals(1000000000, ownerCapsule.getNetUsage()); + Assert.assertEquals(nowSlot, ownerCapsule.getLatestConsumeTime()); + + // check receiver + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(0, receiverCapsule.getNetUsage()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testLockedAndUnlockUnDelegateForBandwidth() { + delegateLockedBandwidthForOwner(Long.MAX_VALUE); + delegateBandwidthForOwner(); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); + receiverCapsule.setNetUsage(1_000_000_000); + long nowSlot = dbManager.getChainBaseManager().getHeadSlot(); + receiverCapsule.setLatestConsumeTime(nowSlot - 14400); + dbManager.getAccountStore().put(receiver, receiverCapsule); + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + ownerCapsule.setNetUsage(1_000_000_000); + ownerCapsule.setLatestConsumeTime(nowSlot - 14400); + dbManager.getAccountStore().put(owner, ownerCapsule); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegatedContractForBandwidth(OWNER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(2 * delegateBalance, + receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(2 * delegateBalance, + ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(2 * delegateBalance, ownerCapsule.getTronPower()); + Assert.assertEquals(1_000_000_000, ownerCapsule.getNetUsage()); + Assert.assertEquals(1_000_000_000, receiverCapsule.getNetUsage()); + DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule.createDbKeyV2(owner, receiver)); + DelegatedResourceCapsule lockedResourceCapsule = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule.createLockDbKeyV2(owner, receiver)); + Assert.assertNotNull(delegatedResourceCapsule); + Assert.assertNotNull(lockedResourceCapsule); + + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); + + // check DelegatedResource + DelegatedResourceCapsule delegatedResourceCapsule1 = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule.createDbKeyV2(owner, receiver)); + DelegatedResourceCapsule lockedResourceCapsule1 = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule.createLockDbKeyV2(owner, receiver)); + Assert.assertNull(delegatedResourceCapsule1); + Assert.assertNotNull(lockedResourceCapsule1); + // check owner + ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(1000000000, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(2 * delegateBalance, ownerCapsule.getTronPower()); + Assert.assertEquals(750000000, ownerCapsule.getNetUsage()); + Assert.assertEquals(nowSlot, ownerCapsule.getLatestConsumeTime()); + + // check receiver + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(1000000000, + receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(250000000, receiverCapsule.getNetUsage()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testLockedUnDelegateBalanceForBandwidthInsufficient() { + delegateLockedBandwidthForOwner(Long.MAX_VALUE); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); + receiverCapsule.setNetUsage(1_000_000_000); + long nowSlot = dbManager.getChainBaseManager().getHeadSlot(); + receiverCapsule.setLatestConsumeTime(nowSlot - 14400); + dbManager.getAccountStore().put(receiver, receiverCapsule); + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + ownerCapsule.setNetUsage(1_000_000_000); + ownerCapsule.setLatestConsumeTime(nowSlot - 14400); + dbManager.getAccountStore().put(owner, ownerCapsule); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegatedContractForBandwidth(OWNER_ADDRESS, delegateBalance)); + + try { + ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(delegateBalance, + receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getTronPower()); + Assert.assertEquals(1_000_000_000, ownerCapsule.getNetUsage()); + Assert.assertEquals(1_000_000_000, receiverCapsule.getNetUsage()); + DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule.createDbKeyV2(owner, receiver)); + DelegatedResourceCapsule lockedResourceCapsule = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule.createLockDbKeyV2(owner, receiver)); + Assert.assertNull(delegatedResourceCapsule); + Assert.assertNotNull(lockedResourceCapsule); + + actuator.validate(); + Assert.fail(); + } catch (Exception e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("insufficient delegatedFrozenBalance(BANDWIDTH), " + + "request=1000000000, unlock_balance=0", e.getMessage()); + } + } + @Test public void testPartialUnDelegateForBandwidth() { delegateBandwidthForOwner(); @@ -718,28 +932,22 @@ public void noDelegateBalance() { UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) .setAny(getDelegatedContractForBandwidth(OWNER_ADDRESS, delegateBalance)); - TransactionResultCapsule ret = new TransactionResultCapsule(); try { actuator.validate(); - actuator.execute(ret); Assert.fail("cannot run here."); } catch (ContractValidateException e) { Assert.assertEquals("delegated Resource does not exist", e.getMessage()); - } catch (ContractExeException e) { - Assert.fail(e.getMessage()); } actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getDelegatedContractForCpu(delegateBalance)); + .setAny(getDelegatedContractForCpu(delegateBalance)); + try { actuator.validate(); - actuator.execute(ret); Assert.fail("cannot run here."); } catch (ContractValidateException e) { Assert.assertEquals("delegated Resource does not exist", e.getMessage()); - } catch (ContractExeException e) { - Assert.fail(e.getMessage()); } } From f172156f92045a9425938c8be28c5817b7b7e7c1 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 5 Dec 2022 14:24:52 +0800 Subject: [PATCH 0447/1197] docs(readme): remove useless tips for node runtime env --- README.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/README.md b/README.md index f128ca37dae..d0ee5fc1f15 100644 --- a/README.md +++ b/README.md @@ -177,11 +177,3 @@ Thank you for considering to help out with the source code! If you'd like to con # License java-tron is released under the [LGPLv3 license](https://github.com/tronprotocol/java-tron/blob/master/LICENSE). - - - -The minimum hardware requirements are `CPU with 8 cores`,`16GB RAM` and `1TB free storage space` to sync the Mainnet, the recommended hardware requirements: -* CPU with 16+ cores(32+ cores for a super representative) -* 32+ GB RAM(64+ GB for a super representative) -* High Performance SSD with at least 1.5TB free space -* 100+ MB/s download Internet service From a0edb2eca738cebcb90655584b91988c57864095 Mon Sep 17 00:00:00 2001 From: liukai Date: Tue, 6 Dec 2022 19:29:08 +0800 Subject: [PATCH 0448/1197] feat(gradle): update dependency --- build.gradle | 6 +++--- chainbase/build.gradle | 1 - common/build.gradle | 2 +- framework/build.gradle | 5 ++--- protocol/build.gradle | 7 ++++++- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index de4fb03e532..44c419ed199 100644 --- a/build.gradle +++ b/build.gradle @@ -44,11 +44,11 @@ subprojects { testAnnotationProcessor 'org.projectlombok:lombok:1.18.12' compile group: 'com.google.guava', name: 'guava', version: '24.1-jre' compile "com.google.code.findbugs:jsr305:3.0.0" - compile group: 'org.springframework', name: 'spring-context', version: '4.2.4.RELEASE' - compile group: 'org.springframework', name: 'spring-tx', version: '4.2.4.RELEASE' + compile group: 'org.springframework', name: 'spring-context', version: '5.3.18' + compile group: 'org.springframework', name: 'spring-tx', version: '5.3.18' compile "org.apache.commons:commons-lang3:3.4" compile group: 'org.apache.commons', name: 'commons-math', version: '2.2' - compile "org.apache.commons:commons-collections4:4.0" + compile "org.apache.commons:commons-collections4:4.1" compile group: 'joda-time', name: 'joda-time', version: '2.3' } diff --git a/chainbase/build.gradle b/chainbase/build.gradle index 499ef014b32..758a59aa23c 100644 --- a/chainbase/build.gradle +++ b/chainbase/build.gradle @@ -40,7 +40,6 @@ dependencies { compile group: 'org.rocksdb', name: 'rocksdbjni', version: '5.15.10' compile group: 'com.typesafe', name: 'config', version: '1.3.2' compile 'com.github.tronprotocol:zksnark-java-sdk:master-SNAPSHOT' - compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.10.3' compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.8.5' compile project(":protocol") compile project(":common") diff --git a/common/build.gradle b/common/build.gradle index 713e0a213e3..fc17f99cd84 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -37,7 +37,7 @@ repositories { dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' - compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.10.3' + compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.13.4.1' compile "com.cedarsoftware:java-util:1.8.0" compile group: 'org.apache.httpcomponents', name: 'httpasyncclient', version: '4.1.1' compile group: 'commons-codec', name: 'commons-codec', version: '1.11' diff --git a/framework/build.gradle b/framework/build.gradle index 329f0e6d265..4bfe0a5bbbe 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -60,7 +60,6 @@ dependencies { compile group: 'com.google.inject', name: 'guice', version: '4.1.0' - compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.10.3' compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.8.5' compile group: 'io.dropwizard.metrics', name: 'metrics-core', version: '3.1.2' @@ -72,8 +71,8 @@ dependencies { compile group: 'com.google.api.grpc', name: 'googleapis-common-protos', version: '0.0.3' // http - compile 'org.eclipse.jetty:jetty-server:9.4.11.v20180605' - compile 'org.eclipse.jetty:jetty-servlet:9.4.11.v20180605' + compile 'org.eclipse.jetty:jetty-server:9.4.49.v20220914' + compile 'org.eclipse.jetty:jetty-servlet:9.4.49.v20220914' compile 'com.alibaba:fastjson:1.2.83' compile group: 'org.apache.httpcomponents', name: 'httpasyncclient', version: '4.1.1' // end http diff --git a/protocol/build.gradle b/protocol/build.gradle index acdb7f15187..b3d83ee0149 100644 --- a/protocol/build.gradle +++ b/protocol/build.gradle @@ -1,12 +1,14 @@ apply plugin: 'com.google.protobuf' -def protobufVersion = "3.19.2" +def protobufVersion = "3.20.3" def grpcVersion = "1.14.0" dependencies { compile group: 'com.google.protobuf', name: 'protobuf-java', version: protobufVersion compile group: 'com.google.protobuf', name: 'protobuf-java-util', version: protobufVersion + compile group: 'com.google.code.gson', name: 'gson', version: '2.9.0' + compile group: 'net.jcip', name: 'jcip-annotations', version: '1.0' // checkstyleConfig "com.puppycrawl.tools:checkstyle:${versions.checkstyle}" @@ -17,6 +19,9 @@ dependencies { // end google grpc compile group: 'com.google.api.grpc', name: 'googleapis-common-protos', version: '0.0.3' + compile group: 'io.netty', name: 'netty-codec-http', version: '4.1.78.Final' + compile group: 'io.netty', name: 'netty-handler', version: '4.1.78.Final' + compile group: 'io.netty', name: 'netty-codec-http2', version: '4.1.78.Final' } tasks.matching { it instanceof Test }.all { From 1ab528ff1f72ac63bd0375a17d809f9f81758465 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 7 Dec 2022 15:22:07 +0800 Subject: [PATCH 0449/1197] fix(freezeV2): optimize reviewed code --- .../actuator/DelegateResourceActuator.java | 4 +- .../actuator/UnDelegateResourceActuator.java | 7 ++-- .../WithdrawExpireUnfreezeActuator.java | 2 +- .../org/tron/core/utils/ProposalUtil.java | 2 +- .../DelegateResourceProcessor.java | 4 +- .../UnDelegateResourceProcessor.java | 2 +- .../WithdrawExpireUnfreezeProcessor.java | 2 +- .../org/tron/core/vm/program/Program.java | 2 +- .../org/tron/core/capsule/AccountCapsule.java | 8 ++++ .../org/tron/core/db/BandwidthProcessor.java | 9 +++-- .../org/tron/core/db/ResourceProcessor.java | 11 ++---- .../java/org/tron/core/config/Parameter.java | 3 +- .../WithdrawExpireUnfreezeActuatorTest.java | 39 ++++++++----------- 13 files changed, 50 insertions(+), 45 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 148f7782666..efeebf58d35 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -142,7 +142,7 @@ public boolean validate() throws ContractValidateException { switch (delegateResourceContract.getResource()) { case BANDWIDTH: { BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); - processor.updateUsage(ownerCapsule); + processor.updateUsageForDelegated(ownerCapsule); long accountNetUsage = ownerCapsule.getNetUsage(); if (null != this.getTx() && this.getTx().isTransactionCreate()) { @@ -181,7 +181,7 @@ public boolean validate() throws ContractValidateException { if (ownerCapsule.getFrozenV2BalanceForEnergy() - remainEnergyUsage < delegateBalance) { throw new ContractValidateException( - "delegateBalance must be less than available FreezeEnergyV2Balance balance"); + "delegateBalance must be less than available FreezeEnergyV2 balance"); } } break; diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index 40c970123d4..d522b3c3ca9 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -67,10 +67,11 @@ public boolean execute(Object result) throws ContractExeException { long transferUsage = 0; // modify receiver Account if (receiverCapsule != null) { + long now = chainBaseManager.getHeadSlot(); switch (unDelegateResourceContract.getResource()) { case BANDWIDTH: BandwidthProcessor bandwidthProcessor = new BandwidthProcessor(chainBaseManager); - bandwidthProcessor.updateUsage(receiverCapsule); + bandwidthProcessor.updateUsageForDelegated(receiverCapsule); if (receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth() < unDelegateBalance) { @@ -89,7 +90,7 @@ public boolean execute(Object result) throws ContractExeException { long newNetUsage = receiverCapsule.getNetUsage() - transferUsage; receiverCapsule.setNetUsage(newNetUsage); - receiverCapsule.setLatestConsumeTime(chainBaseManager.getHeadSlot()); + receiverCapsule.setLatestConsumeTime(now); break; case ENERGY: EnergyProcessor energyProcessor = new EnergyProcessor(dynamicStore, accountStore); @@ -112,7 +113,7 @@ public boolean execute(Object result) throws ContractExeException { long newEnergyUsage = receiverCapsule.getEnergyUsage() - transferUsage; receiverCapsule.setEnergyUsage(newEnergyUsage); - receiverCapsule.setLatestConsumeTimeForEnergy(chainBaseManager.getHeadSlot()); + receiverCapsule.setLatestConsumeTimeForEnergy(now); break; default: //this should never happen diff --git a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java index 6532be5439c..0c547d2b5a3 100755 --- a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java @@ -58,7 +58,7 @@ public boolean execute(Object result) throws ContractExeException { .build()); List newUnFreezeList = getRemainWithdrawList(unfrozenV2List, now); accountCapsule.clearUnfrozenV2(); - newUnFreezeList.forEach(accountCapsule::addUnfrozenV2); + accountCapsule.addAllUnfrozenV2(newUnFreezeList); accountStore.put(accountCapsule.createDbKey(), accountCapsule); ret.setWithdrawExpireAmount(totalWithdrawUnfreeze); ret.setStatus(fee, code.SUCESS); diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index ca5691d25ee..f8e28296782 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -598,7 +598,7 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, break; } case UNFREEZE_DELAY_DAYS: { - if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_6)) { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7)) { throw new ContractValidateException( "Bad chain parameter id [UNFREEZE_DELAY_DAYS]"); } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index 55ec640d34e..0c9d0418cab 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -52,7 +52,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra switch (param.getResourceType()) { case BANDWIDTH: { BandwidthProcessor processor = new BandwidthProcessor(ChainBaseManager.getInstance()); - processor.updateUsage(ownerCapsule); + processor.updateUsageForDelegated(ownerCapsule); long netUsage = (long) (ownerCapsule.getNetUsage() * TRX_PRECISION * ((double) (repo.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); @@ -87,7 +87,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra if (ownerCapsule.getFrozenV2BalanceForEnergy() - remainEnergyUsage < delegateBalance) { throw new ContractValidateException( - "delegateBalance must be less than available FreezeEnergyV2Balance balance"); + "delegateBalance must be less than available FreezeEnergyV2 balance"); } } break; diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index 8a98cf26ee5..13ac8f6f2ee 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -100,7 +100,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { switch (param.getResourceType()) { case BANDWIDTH: BandwidthProcessor bandwidthProcessor = new BandwidthProcessor(ChainBaseManager.getInstance()); - bandwidthProcessor.updateUsage(receiverCapsule); + bandwidthProcessor.updateUsageForDelegated(receiverCapsule); if (receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth() < unDelegateBalance) { diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java index 7b8e5398862..da08a002677 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java @@ -79,7 +79,7 @@ public long execute(WithdrawExpireUnfreezeParam param, Repository repo) throws C .build()); List newUnFreezeList = getRemainWithdrawList(unfrozenV2List, now); ownerCapsule.clearUnfrozenV2(); - newUnFreezeList.forEach(ownerCapsule::addUnfrozenV2); + ownerCapsule.addAllUnfrozenV2(newUnFreezeList); repo.updateAccount(ownerCapsule.createDbKey(), ownerCapsule); return totalWithdrawUnfreeze; } diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index ef572e32f79..7a800a0b412 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -543,7 +543,7 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit // merge usage BandwidthProcessor bandwidthProcessor = new BandwidthProcessor(ChainBaseManager.getInstance()); - bandwidthProcessor.updateUsage(ownerCapsule); + bandwidthProcessor.updateUsageForDelegated(ownerCapsule); ownerCapsule.setLatestConsumeTime(now); if (ownerCapsule.getNetUsage() > 0) { long newNetUsage = diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index a3b31e8baa4..e91a0cad5b2 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -19,6 +19,7 @@ import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; import org.tron.common.utils.ByteArray; import org.tron.core.capsule.utils.AssetUtil; import org.tron.core.store.AssetIssueStore; @@ -1326,6 +1327,13 @@ public void addUnfrozenV2(UnFreezeV2 unfrozenV2) { this.account = this.account.toBuilder().addUnfrozenV2(unfrozenV2).build(); } + public void addAllUnfrozenV2(List unFreezeV2List) { + if (CollectionUtils.isEmpty(unFreezeV2List)) { + return; + } + this.account = this.account.toBuilder().addAllUnfrozenV2(unFreezeV2List).build(); + } + public void clearUnfrozenV2() { this.account = this.account.toBuilder().clearUnfrozenV2().build(); } diff --git a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java index d9cb61825e9..5a89bd13ffe 100644 --- a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -36,12 +36,15 @@ public BandwidthProcessor(ChainBaseManager chainBaseManager) { this.chainBaseManager = chainBaseManager; } - public void updateUsage(AccountCapsule accountCapsule) { + public void updateUsageForDelegated(AccountCapsule ac) { long now = chainBaseManager.getHeadSlot(); - updateUsage(accountCapsule, now); + long oldNetUsage = ac.getNetUsage(); + long latestConsumeTime = ac.getLatestConsumeTime(); + ac.setNetUsage(increase(ac, BANDWIDTH, oldNetUsage, 0, latestConsumeTime, now)); } - private void updateUsage(AccountCapsule accountCapsule, long now) { + public void updateUsage(AccountCapsule accountCapsule) { + long now = chainBaseManager.getHeadSlot(); long oldNetUsage = accountCapsule.getNetUsage(); long latestConsumeTime = accountCapsule.getLatestConsumeTime(); accountCapsule.setNetUsage(increase(accountCapsule, BANDWIDTH, diff --git a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java index c3a0b56221a..3702a433af5 100644 --- a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java @@ -23,7 +23,7 @@ abstract class ResourceProcessor { protected long windowSize; protected long averageWindowSize; - public ResourceProcessor(DynamicPropertiesStore dynamicPropertiesStore, + protected ResourceProcessor(DynamicPropertiesStore dynamicPropertiesStore, AccountStore accountStore) { this.dynamicPropertiesStore = dynamicPropertiesStore; this.accountStore = accountStore; @@ -90,18 +90,15 @@ public long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, return newUsage; } - public long unDelegateIncrease(AccountCapsule owner, AccountCapsule receiver, + public long unDelegateIncrease(AccountCapsule owner, final AccountCapsule receiver, long transferUsage, ResourceCode resourceCode, long now) { long lastOwnerTime = owner.getLastConsumeTime(resourceCode); - long lastReceiverTime = receiver.getLastConsumeTime(resourceCode); - long ownerWindowSize = owner.getWindowSize(resourceCode); - long receiverWindowSize = receiver.getWindowSize(resourceCode); long ownerUsage = owner.getUsage(resourceCode); // Update itself first ownerUsage = increase(owner, resourceCode, ownerUsage, 0, lastOwnerTime, now); - long remainOwnerWindowSize = ownerWindowSize - (now - lastOwnerTime); - long remainReceiverWindowSize = receiverWindowSize - (now - lastReceiverTime); + long remainOwnerWindowSize = owner.getWindowSize(resourceCode); + long remainReceiverWindowSize = receiver.getWindowSize(resourceCode); remainOwnerWindowSize = remainOwnerWindowSize < 0 ? 0 : remainOwnerWindowSize; remainReceiverWindowSize = remainReceiverWindowSize < 0 ? 0 : remainReceiverWindowSize; diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index 6faf666af8b..24fef8f84f6 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -19,7 +19,8 @@ public enum ForkBlockVersionEnum { VERSION_4_3(22, 1596780000000L, 80), VERSION_4_4(23, 1596780000000L, 80), VERSION_4_5(24, 1596780000000L, 80), - VERSION_4_6(25, 1596780000000L, 80); + VERSION_4_6(25, 1596780000000L, 80), + VERSION_4_7(26, 1596780000000L, 80); @Getter private int value; diff --git a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java index 4ea3d5c83ac..d3ec771b5fa 100644 --- a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java @@ -1,6 +1,7 @@ package org.tron.core.actuator; import static junit.framework.TestCase.fail; +import static org.junit.Assert.assertEquals; import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; import static org.tron.protos.contract.Common.ResourceCode.ENERGY; @@ -39,12 +40,12 @@ public class WithdrawExpireUnfreezeActuatorTest { private static final String dbPath = "output_withdraw_expire_unfreeze_test"; private static final String OWNER_ADDRESS; - private static final String OWNER_ADDRESS_INVALID = "aaaa"; + private static final String OWNER_ADDRESS_INVALID = "abc"; private static final String OWNER_ACCOUNT_INVALID; private static final long initBalance = 10_000_000_000L; private static final long allowance = 32_000_000L; private static Manager dbManager; - private static TronApplicationContext context; + private static final TronApplicationContext context; static { Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); @@ -110,7 +111,7 @@ public void testWithdrawExpireUnfreeze() { byte[] address = ByteArray.fromHexString(OWNER_ADDRESS); AccountCapsule accountCapsule = dbManager.getAccountStore().get(address); - Assert.assertEquals(accountCapsule.getLatestWithdrawTime(), 0); + assertEquals(0, accountCapsule.getLatestWithdrawTime()); WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address), 100, "http://baidu.com/"); @@ -125,18 +126,16 @@ public void testWithdrawExpireUnfreeze() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); + assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule owner = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); List unfrozenV2List = owner.getInstance().getUnfrozenV2List(); - Assert.assertEquals(1, unfrozenV2List.size()); - Assert.assertEquals(Long.MAX_VALUE, unfrozenV2List.get(0).getUnfreezeExpireTime()); - Assert.assertEquals(initBalance + 32_000_000L, owner.getBalance()); - Assert.assertEquals(32_000_000L, ret.getWithdrawExpireAmount()); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + assertEquals(1, unfrozenV2List.size()); + assertEquals(Long.MAX_VALUE, unfrozenV2List.get(0).getUnfreezeExpireTime()); + assertEquals(initBalance + 32_000_000L, owner.getBalance()); + assertEquals(32_000_000L, ret.getWithdrawExpireAmount()); + } catch (ContractValidateException | ContractExeException e) { + fail(); } } @@ -155,12 +154,9 @@ public void invalidOwnerAddress() { fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); - - Assert.assertEquals("Invalid address", e.getMessage()); - + assertEquals("Invalid address", e.getMessage()); } catch (ContractExeException e) { - Assert.assertTrue(e instanceof ContractExeException); + Assert.fail(e.getMessage()); } } @@ -178,10 +174,9 @@ public void invalidOwnerAccount() { actuator.execute(ret); fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); - Assert.assertEquals("Account[" + OWNER_ACCOUNT_INVALID + "] not exists", e.getMessage()); + assertEquals("Account[" + OWNER_ACCOUNT_INVALID + "] not exists", e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } } @@ -209,8 +204,8 @@ public void commonErrorCheck() { fail("BalanceInsufficientException"); } AccountCapsule accountCapsule = dbManager.getAccountStore().get(address); - Assert.assertEquals(accountCapsule.getAllowance(), allowance); - Assert.assertEquals(accountCapsule.getLatestWithdrawTime(), 0); + assertEquals(allowance, accountCapsule.getAllowance()); + assertEquals(0, accountCapsule.getLatestWithdrawTime()); WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address), 100, "http://google.com/"); From 4f6c1c28a3b1a7ea091d8cf643fefb01410c6d88 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Wed, 7 Dec 2022 18:28:42 +0800 Subject: [PATCH 0450/1197] feat(freezeV2): optimize delegate resource storage --- .../actuator/DelegateResourceActuator.java | 20 ++++++++--------- .../actuator/UnDelegateResourceActuator.java | 20 ++++++++--------- .../DelegateResourceProcessor.java | 2 +- .../UnDelegateResourceProcessor.java | 4 ++-- .../org/tron/core/vm/utils/FreezeV2Util.java | 2 +- .../capsule/DelegatedResourceCapsule.java | 9 ++++---- .../core/store/DelegatedResourceStore.java | 4 ++-- .../src/main/java/org/tron/core/Wallet.java | 17 +++++++++----- .../tron/common/runtime/vm/FreezeV2Test.java | 8 +++---- .../runtime/vm/PrecompiledContractsTest.java | 2 +- .../DelegateResourceActuatorTest.java | 8 ++++--- .../UnDelegateResourceActuatorTest.java | 22 +++++++++---------- 12 files changed, 62 insertions(+), 56 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 148f7782666..68004997b58 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -153,15 +153,15 @@ public boolean validate() throws ContractValidateException { (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); long remainNetUsage = netUsage - - ownerCapsule.getFrozenBalance() - - ownerCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() - - ownerCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth(); + - ownerCapsule.getFrozenBalance() + - ownerCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() + - ownerCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth(); remainNetUsage = Math.max(0, remainNetUsage); if (ownerCapsule.getFrozenV2BalanceForBandwidth() - remainNetUsage < delegateBalance) { throw new ContractValidateException( - "delegateBalance must be less than available FreezeBandwidthV2 balance"); + "delegateBalance must be less than available FreezeBandwidthV2 balance"); } } break; @@ -173,15 +173,15 @@ public boolean validate() throws ContractValidateException { (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); long remainEnergyUsage = energyUsage - - ownerCapsule.getEnergyFrozenBalance() - - ownerCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() - - ownerCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy(); + - ownerCapsule.getEnergyFrozenBalance() + - ownerCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() + - ownerCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy(); remainEnergyUsage = Math.max(0, remainEnergyUsage); if (ownerCapsule.getFrozenV2BalanceForEnergy() - remainEnergyUsage < delegateBalance) { throw new ContractValidateException( - "delegateBalance must be less than available FreezeEnergyV2Balance balance"); + "delegateBalance must be less than available FreezeEnergyV2Balance balance"); } } break; @@ -245,10 +245,8 @@ private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boole long expireTime = 0; if (lock) { expireTime = now + DELEGATE_PERIOD; - key = DelegatedResourceCapsule.createLockDbKeyV2(ownerAddress, receiverAddress); - } else { - key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress); } + key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, lock); DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore.get(key); if (delegatedResourceCapsule == null) { delegatedResourceCapsule = new DelegatedResourceCapsule(ByteString.copyFrom(ownerAddress), diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index 40c970123d4..670903eabf5 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -126,7 +126,7 @@ public boolean execute(Object result) throws ContractExeException { dynamicStore.getLatestBlockHeaderTimestamp()); byte[] unlockKey = DelegatedResourceCapsule - .createDbKeyV2(ownerAddress, receiverAddress); + .createDbKeyV2(ownerAddress, receiverAddress, false); DelegatedResourceCapsule unlockResource = delegatedResourceStore .get(unlockKey); @@ -179,7 +179,7 @@ public boolean execute(Object result) throws ContractExeException { } byte[] lockKey = DelegatedResourceCapsule - .createLockDbKeyV2(ownerAddress, receiverAddress); + .createDbKeyV2(ownerAddress, receiverAddress, true); DelegatedResourceCapsule lockResource = delegatedResourceStore .get(lockKey); if (lockResource == null && unlockResource == null) { @@ -256,11 +256,11 @@ public boolean validate() throws ContractValidateException { // } long now = dynamicStore.getLatestBlockHeaderTimestamp(); - byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress); - DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore.get(key); - byte[] lockKey = DelegatedResourceCapsule.createLockDbKeyV2(ownerAddress, receiverAddress); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, false); + DelegatedResourceCapsule unlockResourceCapsule = delegatedResourceStore.get(key); + byte[] lockKey = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, true); DelegatedResourceCapsule lockResourceCapsule = delegatedResourceStore.get(lockKey); - if (delegatedResourceCapsule == null && lockResourceCapsule == null) { + if (unlockResourceCapsule == null && lockResourceCapsule == null) { throw new ContractValidateException( "delegated Resource does not exist"); } @@ -272,8 +272,8 @@ public boolean validate() throws ContractValidateException { switch (unDelegateResourceContract.getResource()) { case BANDWIDTH: { long delegateBalance = 0; - if (delegatedResourceCapsule != null) { - delegateBalance += delegatedResourceCapsule.getFrozenBalanceForBandwidth(); + if (unlockResourceCapsule != null) { + delegateBalance += unlockResourceCapsule.getFrozenBalanceForBandwidth(); } if (lockResourceCapsule != null && lockResourceCapsule.getExpireTimeForBandwidth() < now) { @@ -288,8 +288,8 @@ public boolean validate() throws ContractValidateException { break; case ENERGY: { long delegateBalance = 0; - if (delegatedResourceCapsule != null) { - delegateBalance += delegatedResourceCapsule.getFrozenBalanceForEnergy(); + if (unlockResourceCapsule != null) { + delegateBalance += unlockResourceCapsule.getFrozenBalanceForEnergy(); } if (lockResourceCapsule != null && lockResourceCapsule.getExpireTimeForEnergy() < now) { diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index 55ec640d34e..65f62900a79 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -154,7 +154,7 @@ private void delegateResource( long delegateBalance, Repository repo) { //modify DelegatedResourceStore - byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, false); DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); if (delegatedResourceCapsule == null) { delegatedResourceCapsule = new DelegatedResourceCapsule( diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index 8a98cf26ee5..670f332213e 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -55,7 +55,7 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont "receiverAddress must not be the same as ownerAddress"); } - byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, false); DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); if (delegatedResourceCapsule == null) { throw new ContractValidateException( @@ -153,7 +153,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { } // modify owner Account - byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, false); DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); switch (param.getResourceType()) { case BANDWIDTH: { diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index 583f96f347f..8d904a139de 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -67,7 +67,7 @@ public static long queryResourceV2(byte[] from, byte[] to, long type, Repository return 0; } - byte[] key = DelegatedResourceCapsule.createDbKeyV2(from, to); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(from, to, false); DelegatedResourceCapsule delegatedResource = repository.getDelegatedResource(key); if (delegatedResource == null) { return 0; diff --git a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java index bf69bb494cb..1b631796feb 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java @@ -41,14 +41,13 @@ public static byte[] createDbKey(byte[] from, byte[] to) { return key; } - public static byte[] createDbKeyV2(byte[] from, byte[] to) { + public static byte[] createDbKeyV2(byte[] from, byte[] to, boolean lock) { + if (lock) { + return Bytes.concat(V2_LOCK_PREFIX, from, to); + } return Bytes.concat(V2_PREFIX, from, to); } - public static byte[] createLockDbKeyV2(byte[] from, byte[] to) { - return Bytes.concat(V2_LOCK_PREFIX, from, to); - } - public ByteString getFrom() { return this.delegatedResource.getFrom(); } diff --git a/chainbase/src/main/java/org/tron/core/store/DelegatedResourceStore.java b/chainbase/src/main/java/org/tron/core/store/DelegatedResourceStore.java index 1618b2708d7..48bc51892f6 100644 --- a/chainbase/src/main/java/org/tron/core/store/DelegatedResourceStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DelegatedResourceStore.java @@ -36,7 +36,7 @@ public List getByFrom(byte[] key) { public void unLockExpireResource(byte[] from, byte[] to, long now) { byte[] lockKey = DelegatedResourceCapsule - .createLockDbKeyV2(from, to); + .createDbKeyV2(from, to, true); DelegatedResourceCapsule lockResource = get(lockKey); if (lockResource == null) { return; @@ -47,7 +47,7 @@ public void unLockExpireResource(byte[] from, byte[] to, long now) { } byte[] unlockKey = DelegatedResourceCapsule - .createDbKeyV2(from, to); + .createDbKeyV2(from, to, false); DelegatedResourceCapsule unlockResource = get(unlockKey); if (unlockResource == null) { unlockResource = new DelegatedResourceCapsule(ByteString.copyFrom(from), diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index ec90b1976d9..4bd683fbaac 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -764,11 +764,18 @@ public DelegatedResourceList getDelegatedResourceV2( ByteString fromAddress, ByteString toAddress) { DelegatedResourceList.Builder builder = DelegatedResourceList.newBuilder(); byte[] dbKey = DelegatedResourceCapsule - .createDbKeyV2(fromAddress.toByteArray(), toAddress.toByteArray()); - DelegatedResourceCapsule delegatedResourceCapsule = chainBaseManager.getDelegatedResourceStore() - .get(dbKey); - if (delegatedResourceCapsule != null) { - builder.addDelegatedResource(delegatedResourceCapsule.getInstance()); + .createDbKeyV2(fromAddress.toByteArray(), toAddress.toByteArray(), false); + DelegatedResourceCapsule unlockResource = chainBaseManager.getDelegatedResourceStore() + .get(dbKey); + if (unlockResource != null) { + builder.addDelegatedResource(unlockResource.getInstance()); + } + dbKey = DelegatedResourceCapsule + .createDbKeyV2(fromAddress.toByteArray(), toAddress.toByteArray(), true); + DelegatedResourceCapsule lockResource = chainBaseManager.getDelegatedResourceStore() + .get(dbKey); + if (lockResource != null) { + builder.addDelegatedResource(lockResource.getInstance()); } return builder.build(); } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java index efb963cc42b..21fd4a445af 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -547,7 +547,7 @@ private TVMTestResult delegateResource( DelegatedResourceStore delegatedResourceStore = manager.getDelegatedResourceStore(); DelegatedResourceCapsule oldDelegatedResource = delegatedResourceStore.get( - DelegatedResourceCapsule.createDbKeyV2(contractAddr, receiverAddr)); + DelegatedResourceCapsule.createDbKeyV2(contractAddr, receiverAddr, false)); if (oldDelegatedResource == null) { oldDelegatedResource = new DelegatedResourceCapsule( ByteString.copyFrom(contractAddr), @@ -586,7 +586,7 @@ private TVMTestResult delegateResource( Assert.assertArrayEquals(oldReceiver.getData(), newReceiver.getData()); DelegatedResourceCapsule newDelegatedResource = manager.getDelegatedResourceStore().get( - DelegatedResourceCapsule.createDbKeyV2(contractAddr, receiverAddr)); + DelegatedResourceCapsule.createDbKeyV2(contractAddr, receiverAddr, false)); Assert.assertNotNull(newDelegatedResource); if (res == 0) { Assert.assertEquals(amount + oldDelegatedResource.getFrozenBalanceForBandwidth(), @@ -641,7 +641,7 @@ private TVMTestResult unDelegateResource( DelegatedResourceStore delegatedResourceStore = manager.getDelegatedResourceStore(); DelegatedResourceCapsule oldDelegatedResource = delegatedResourceStore.get( - DelegatedResourceCapsule.createDbKeyV2(contractAddr, receiverAddr)); + DelegatedResourceCapsule.createDbKeyV2(contractAddr, receiverAddr, false)); Assert.assertNotNull(oldDelegatedResource); long delegatedFrozenBalance = res == 0 ? oldDelegatedResource.getFrozenBalanceForBandwidth() : oldDelegatedResource.getFrozenBalanceForEnergy(); @@ -692,7 +692,7 @@ private TVMTestResult unDelegateResource( // check delegated resource store DelegatedResourceCapsule newDelegatedResource = delegatedResourceStore.get( - DelegatedResourceCapsule.createDbKeyV2(contractAddr, receiverAddr)); + DelegatedResourceCapsule.createDbKeyV2(contractAddr, receiverAddr, false)); Assert.assertNotNull(newDelegatedResource); if (res == 0) { Assert.assertEquals(0, newDelegatedResource.getFrozenBalanceForBandwidth()); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index 20b12db8fc1..e0a3577baae 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -933,7 +933,7 @@ public void resourceV2Test() { AccountCapsule targetAccount = tempRepository.createAccount(target, Protocol.AccountType.Normal); - byte[] key = DelegatedResourceCapsule.createDbKeyV2(fromAddr, targetAddr); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(fromAddr, targetAddr, false); DelegatedResourceCapsule delegatedResource = new DelegatedResourceCapsule( ByteString.copyFrom(fromAddr), ByteString.copyFrom(targetAddr)); diff --git a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java index f757d95f1cd..8781e0e7f1a 100644 --- a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java @@ -104,7 +104,9 @@ public void createAccountCapsule() { // clear delegate dbManager.getDelegatedResourceStore().delete(DelegatedResourceCapsule.createDbKeyV2( - owner, receiver)); + owner, receiver, false)); + dbManager.getDelegatedResourceStore().delete(DelegatedResourceCapsule.createDbKeyV2( + owner, receiver, true)); dbManager.getDelegatedResourceAccountIndexStore().unDelegateV2(owner, receiver); } @@ -333,7 +335,7 @@ public void testDelegateResourceForBandwidth() { DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore() .get(DelegatedResourceCapsule .createDbKeyV2(ByteArray.fromHexString(OWNER_ADDRESS), - ByteArray.fromHexString(RECEIVER_ADDRESS))); + ByteArray.fromHexString(RECEIVER_ADDRESS), false)); Assert.assertEquals(delegateBalance, delegatedResourceCapsule.getFrozenBalanceForBandwidth()); long totalNetWeightAfter = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); @@ -392,7 +394,7 @@ public void testDelegateResourceForCpu() { Assert.assertEquals(0L, receiverCapsule.getTronPower()); DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore() - .get(DelegatedResourceCapsule.createDbKeyV2(owner, receiver)); + .get(DelegatedResourceCapsule.createDbKeyV2(owner, receiver, false)); Assert.assertEquals(0L, delegatedResourceCapsule.getFrozenBalanceForBandwidth()); Assert.assertEquals(delegateBalance, delegatedResourceCapsule.getFrozenBalanceForEnergy()); diff --git a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java index c9184c6dafe..d7585e662a2 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java @@ -97,7 +97,7 @@ public void createAccountCapsule() { byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); dbManager.getDelegatedResourceStore().delete(DelegatedResourceCapsule.createDbKeyV2( - owner, receiver)); + owner, receiver, false)); dbManager.getDelegatedResourceAccountIndexStore().unDelegateV2(owner, receiver); dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); } @@ -118,7 +118,7 @@ public void delegateBandwidthForOwner() { ByteString.copyFrom(receiver)); delegatedResourceCapsule.setFrozenBalanceForBandwidth(delegateBalance, 0); dbManager.getDelegatedResourceStore().put( - DelegatedResourceCapsule.createDbKeyV2(owner, receiver), delegatedResourceCapsule); + DelegatedResourceCapsule.createDbKeyV2(owner, receiver, false), delegatedResourceCapsule); dbManager.getDelegatedResourceAccountIndexStore().delegateV2(owner, receiver, 1); } @@ -139,7 +139,7 @@ public void delegateCpuForOwner() { ByteString.copyFrom(receiver)); delegatedResourceCapsule.setFrozenBalanceForEnergy(delegateBalance, 0); dbManager.getDelegatedResourceStore().put( - DelegatedResourceCapsule.createDbKeyV2(owner, receiver), delegatedResourceCapsule); + DelegatedResourceCapsule.createDbKeyV2(owner, receiver, false), delegatedResourceCapsule); dbManager.getDelegatedResourceAccountIndexStore().delegateV2(owner, receiver, 1); } @@ -212,7 +212,7 @@ public void testUnDelegateForBandwidth() { Assert.assertEquals(0, receiverCapsule.getNetUsage()); //check DelegatedResource - byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver, false); DelegatedResourceCapsule delegatedCapsule = dbManager.getDelegatedResourceStore().get(key); Assert.assertNull(delegatedCapsule); @@ -283,7 +283,7 @@ public void testPartialUnDelegateForBandwidth() { Assert.assertEquals(1000000000 / 2, receiverCapsule.getNetUsage()); //check DelegatedResource - byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver, false); DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore().get(key); Assert.assertEquals(delegateBalance / 2, @@ -336,7 +336,7 @@ public void testUnDelegatedForBandwidthWithDeletedReceiver() { Assert.assertNull(dbManager.getAccountStore().get(receiver)); //check DelegatedResource - byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver, false); DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore().get(key); Assert.assertNull(delegatedResourceCapsule); @@ -398,7 +398,7 @@ public void testUnDelegatedForBandwidthWithRecreatedReceiver() { Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); //check DelegatedResource - byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver, false); DelegatedResourceCapsule delegatedCapsule = dbManager.getDelegatedResourceStore().get(key); Assert.assertNull(delegatedCapsule); @@ -471,7 +471,7 @@ public void testUnDelegatedForCpu() { Assert.assertEquals(0, receiverCapsule.getEnergyUsage()); //check DelegatedResource - byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver, false); DelegatedResourceCapsule delegatedCapsule = dbManager.getDelegatedResourceStore().get(key); Assert.assertNull(delegatedCapsule); @@ -540,7 +540,7 @@ public void testPartialUnDelegatedForCpu() { Assert.assertEquals(1_000_000_000 / 2, receiverCapsule.getEnergyUsage()); //check DelegatedResource - byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver, false); DelegatedResourceCapsule delegatedCapsule = dbManager.getDelegatedResourceStore().get(key); Assert.assertEquals(delegateBalance / 2, delegatedCapsule.getFrozenBalanceForEnergy()); @@ -592,7 +592,7 @@ public void testUnDelegatedForCpuWithDeletedReceiver() { Assert.assertNull(dbManager.getAccountStore().get(receiver)); //check DelegatedResource - byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver, false); DelegatedResourceCapsule delegatedCapsule = dbManager.getDelegatedResourceStore().get(key); Assert.assertNull(delegatedCapsule); @@ -653,7 +653,7 @@ public void testUnDelegatedForCpuWithRecreatedReceiver() { Assert.assertEquals(0, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy()); //check DelegatedResource - byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(owner, receiver, false); DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore().get(key); Assert.assertNull(delegatedResourceCapsule); From 4159b3a7c70fef5b2fe91ea34ff9704e869fe05a Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 23 Nov 2022 13:42:31 +0800 Subject: [PATCH 0451/1197] feat(toolkit): add db conversion and data splitting extensions 1. convert leveldb to rocksdb 2. split lite full node data 3. optimize gradle build --- framework/build.gradle | 30 +- .../java/org/tron/core/config/args/Args.java | 2 +- .../org/tron/tool/litefullnode/DbTool.java | 2 +- .../tool/litefullnode/LiteFullNodeTool.java | 12 + .../java/org/tron/tool/litefullnode/Util.java | 2 +- plugins/README.md | 115 +++ plugins/build.gradle | 27 +- .../org/tron/plugins/ArchiveManifest.java | 1 - .../src/main/java/org/tron/plugins/Db.java | 43 +- .../main/java/org/tron/plugins/DbArchive.java | 58 +- .../main/java/org/tron/plugins/DbConvert.java | 360 +++++++++ .../main/java/org/tron/plugins/DbLite.java | 740 ++++++++++++++++++ .../main/java/org/tron/plugins/DbMove.java | 66 +- .../MarketOrderPriceComparatorForLevelDB.java | 28 + .../MarketOrderPriceComparatorForRockDB.java | 38 + .../org/tron/plugins/utils/ByteArray.java | 101 +++ .../org/tron/plugins/utils/CryptoUitls.java | 6 + .../java/org/tron/plugins/utils/DBUtils.java | 153 ++++ .../org/tron/plugins/utils/FileUtils.java | 189 +++++ .../org/tron/plugins/utils/MarketUtils.java | 148 ++++ .../org/tron/plugins/utils/Sha256Hash.java | 202 +++++ .../tron/plugins/utils/db/DBInterface.java | 21 + .../org/tron/plugins/utils/db/DBIterator.java | 59 ++ .../org/tron/plugins/utils/db/DbTool.java | 187 +++++ .../tron/plugins/utils/db/LevelDBImpl.java | 46 ++ .../plugins/utils/db/LevelDBIterator.java | 58 ++ .../tron/plugins/utils/db/RockDBIterator.java | 77 ++ .../tron/plugins/utils/db/RocksDBImpl.java | 64 ++ plugins/src/main/resources/logback.xml | 7 +- .../java/org/tron/plugins/DbConvertTest.java | 110 +++ .../java/org/tron/plugins/DbMoveTest.java | 38 +- 31 files changed, 2813 insertions(+), 177 deletions(-) create mode 100644 plugins/README.md create mode 100644 plugins/src/main/java/org/tron/plugins/DbConvert.java create mode 100644 plugins/src/main/java/org/tron/plugins/DbLite.java create mode 100644 plugins/src/main/java/org/tron/plugins/comparator/MarketOrderPriceComparatorForLevelDB.java create mode 100644 plugins/src/main/java/org/tron/plugins/comparator/MarketOrderPriceComparatorForRockDB.java create mode 100644 plugins/src/main/java/org/tron/plugins/utils/ByteArray.java create mode 100644 plugins/src/main/java/org/tron/plugins/utils/CryptoUitls.java create mode 100644 plugins/src/main/java/org/tron/plugins/utils/DBUtils.java create mode 100644 plugins/src/main/java/org/tron/plugins/utils/FileUtils.java create mode 100644 plugins/src/main/java/org/tron/plugins/utils/MarketUtils.java create mode 100644 plugins/src/main/java/org/tron/plugins/utils/Sha256Hash.java create mode 100644 plugins/src/main/java/org/tron/plugins/utils/db/DBInterface.java create mode 100644 plugins/src/main/java/org/tron/plugins/utils/db/DBIterator.java create mode 100644 plugins/src/main/java/org/tron/plugins/utils/db/DbTool.java create mode 100644 plugins/src/main/java/org/tron/plugins/utils/db/LevelDBImpl.java create mode 100644 plugins/src/main/java/org/tron/plugins/utils/db/LevelDBIterator.java create mode 100644 plugins/src/main/java/org/tron/plugins/utils/db/RockDBIterator.java create mode 100644 plugins/src/main/java/org/tron/plugins/utils/db/RocksDBImpl.java create mode 100644 plugins/src/test/java/org/tron/plugins/DbConvertTest.java diff --git a/framework/build.gradle b/framework/build.gradle index 329f0e6d265..66acc047c80 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -267,14 +267,34 @@ 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 { - archives(binaryRelease('buildSolidityNodeJar', 'SolidityNode', 'org.tron.program.SolidityNode'), - binaryRelease('buildFullNodeJar', 'FullNode', 'org.tron.program.FullNode'), - binaryRelease('buildKeystoreFactoryJar', 'KeystoreFactory', 'org.tron.program.KeystoreFactory'), - binaryRelease('buildDBConvertJar', 'DBConvert', 'org.tron.program.DBConvert'), - binaryRelease('buildLiteFullNodeToolJar', 'LiteFullNodeTool', 'org.tron.tool.litefullnode.LiteFullNodeTool')) + archives(binaryRelease('buildFullNodeJar', 'FullNode', 'org.tron.program.FullNode')) } + if (!skipAll) { + if (!skipSolidity) { + artifacts { + archives(binaryRelease('buildSolidityNodeJar', 'SolidityNode', 'org.tron.program.SolidityNode'))} + } + if (!skipKeystore) { + artifacts { + archives(binaryRelease('buildKeystoreFactoryJar', 'KeystoreFactory', 'org.tron.program.KeystoreFactory'))} + } + if (!skipConvert) { + artifacts { + archives(binaryRelease('buildDBConvertJar', 'DBConvert', 'org.tron.program.DBConvert'))} + } + if (!skipLite) { + artifacts { + archives(binaryRelease('buildLiteFullNodeToolJar', 'LiteFullNodeTool', 'org.tron.tool.litefullnode.LiteFullNodeTool'))} + } + } + } task copyToParent(type: Copy) { diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index a0b428df59f..4386f592ea2 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1437,7 +1437,7 @@ public static boolean checkIsLiteFullNode() { PARAMETER.storage.getDbDirectory(), Constant.INFO_FILE_NAME).toString(); if (FileUtil.isExists(infoFile)) { String value = PropUtil.readProperty(infoFile, Constant.SPLIT_BLOCK_NUM); - return !"".equals(value) && Long.parseLong(value) > 0; + return !"".equals(value) && Long.parseLong(value) > 1; } return false; } diff --git a/framework/src/main/java/org/tron/tool/litefullnode/DbTool.java b/framework/src/main/java/org/tron/tool/litefullnode/DbTool.java index 49d4fac8384..5f43361eddf 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/DbTool.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/DbTool.java @@ -27,7 +27,7 @@ public class DbTool { private static final String KEY_ENGINE = "ENGINE"; - private static final String ENGINE_FILE = "engine.properties"; + public static final String ENGINE_FILE = "engine.properties"; private static final String FILE_SEPARATOR = File.separator; private static final String ROCKSDB = "ROCKSDB"; diff --git a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java index bec69227c52..bc72388e156 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java @@ -14,6 +14,7 @@ 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; @@ -331,6 +332,17 @@ private void fillSnapshotBlockAndTransDb(String sourceDir, String snapshotDir) DBInterface destCommonDb = DbTool.getDB(snapshotDir, COMMON_DB_NAME); destCommonDb.put(DB_KEY_NODE_TYPE, ByteArray.fromInt(Constant.NODE_TYPE_LIGHT_NODE)); destCommonDb.put(DB_KEY_LOWEST_BLOCK_NUM, ByteArray.fromLong(startIndex)); + // 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 { diff --git a/framework/src/main/java/org/tron/tool/litefullnode/Util.java b/framework/src/main/java/org/tron/tool/litefullnode/Util.java index 227ce5c5de4..0e4898b8031 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/Util.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/Util.java @@ -43,7 +43,7 @@ public static void copyDatabases(Path src, Path dest, List subDirs) }); } - private static void copy(Path source, Path dest) { + public static void copy(Path source, Path dest) { try { // create hard link when file is .sst if (source.toString().endsWith(".sst")) { diff --git a/plugins/README.md b/plugins/README.md new file mode 100644 index 00000000000..ff1fea4d17b --- /dev/null +++ b/plugins/README.md @@ -0,0 +1,115 @@ +# Toolkit Manual + +This package contains a set of tools for Tron, the following is the documentation for each tool. + +## DB Archive + +DB archive provides the ability to reformat the manifest according to the current `database`, +parameters are compatible with previous `ArchiveManifest`. + +Parameter explanation: + +- `-b | --batch-size`: [int] specify the batch manifest size,default:80000. +- `-d | --database-directory`: [string] specify the database directory to be processed,default:output-directory/database. +- `-m | --manifest-size`: [int] specify the minimum required manifest file size ,unit:M,default:0. +- `-h | --help`: provide the help info + +Demo: + +```shell script +# full command + java -jar Toolkit.jar db archive [-h] [-b=] [-d=] [-m=] +# examples + java -jar Toolkit.jar db archive #1. use default settings + java -jar Toolkit.jar db archive -d /tmp/db/database #2. Specify the database directory as /tmp/db/database + java -jar Toolkit.jar db archive -b 64000 #3. Specify the batch size to 64000 when optimizing Manifest + java -jar Toolkit.jar db archive -m 128 #4. Specify optimization only when Manifest exceeds 128M +``` + + +## DB Convert + +DB convert provides a helper which can convert LevelDB data to RocksDB data, parameters are compatible with previous `DBConvert`. + +Parameter explanation: + +- ``: Input path for leveldb. Default: output-directory/database +- ``: Output path for rocksdb. Default: output-directory-dst/database +- `--safe`: In safe mode, read data from leveldb then put rocksdb, it's a very time-consuming procedure. If not, just change engine.properties from leveldb to rocksdb,rocksdb + is compatible with leveldb for current version.This may not be the case in the future.Default: false +- `-h | --help`: provide the help info + +Demo: + +```shell script +# full command + java -jar Toolkit.jar db convert [-h] [--safe] +# examples + java -jar Toolkit.jar db convert output-directory/database /tmp/databse +``` + + +## DB Lite + +DB Lite provides lite database, parameters are compatible with previous `LiteFullNodeTool`. + +Parameter explanation: + +- `-o | --operate`: [split,merge]. Default: split. +- `-t | --type`: only used with operate=split: [snapshot,history]. Default: snapshot. +- `-fn | --fn-data-path`: the database path to be split or merged. +- `-ds | --dataset-path`: when operation is `split`,`dataset-path` is the path that store the `snapshot` or `history`,when + operation is `split`,`dataset-path` is the `history` data path. +- `-h | --help`: provide the help info + +Demo: + +```shell script +# full command + java -jar Toolkit.jar db lite [-h] -ds= -fn= [-o=] [-t=] +# examples + #split and get a snapshot dataset + java -jar Toolkit.jar db lite -o split -t snapshot --fn-data-path output-directory/database --dataset-path /tmp + #split and get a history dataset + java -jar Toolkit.jar db lite -o split -t history --fn-data-path output-directory/database --dataset-path /tmp + #merge history dataset and snapshot dataset + java -jar Toolkit.jar db lite -o split -t history --fn-data-path /tmp/snapshot --dataset-path /tmp/history +``` + +## DB Move + +DB Move provides a helper to move some dbs to pre-set new path. For example move `block`, `transactionRetStore` or `transactionHistoryStore` to HDD,reduce storage expenses + +Parameter explanation: + +- `-c | --config`: config file. Default: config.conf. +- `-d | --database-directory`: database directory path. Default: output-directory. +- `-h | --help`: provide the help info + +Demo: + +Take the example of moving `block` and `trans` + +```conf +storage { + ...... + properties = [ + { + name = "block", + path = "/data1/tron", + }, + { + name = "trans", + path = "/data1/tron", + } + ] + ...... +} +``` + +```shell script +# full command + java -jar Toolkit.jar db mv [-h] [-c=] [-d=] +# examples + java -jar Toolkit.jar db mv -c main_net_config.conf -d /data/tron/output-directory +``` \ No newline at end of file diff --git a/plugins/build.gradle b/plugins/build.gradle index f6815e606b3..7dff7295869 100644 --- a/plugins/build.gradle +++ b/plugins/build.gradle @@ -33,10 +33,11 @@ dependencies { compile group: 'info.picocli', name: 'picocli', version: '4.6.3' compile group: 'com.typesafe', name: 'config', version: '1.3.2' compile group: 'me.tongfei', name: 'progressbar', version: '0.9.3' - - - compile 'com.github.halibobo1205.leveldb-java:leveldb:v0.12.5' - compile 'com.github.halibobo1205.leveldb-java:leveldb-api:v0.12.5' + compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' + compile group: 'org.rocksdb', name: 'rocksdbjni', version: '5.15.10' + compile 'com.halibobor:leveldbjni-all:1.18.2' + compile 'com.halibobor:leveldb:1.18.2' + compile project(":protocol") } check.dependsOn 'lint' @@ -104,6 +105,11 @@ def binaryRelease(taskName, jarName, mainClass) { } } + // exclude these files for bouncycastle + exclude "META-INF/*.SF" + exclude "META-INF/*.DSA" + exclude "META-INF/*.RSA" + manifest { attributes "Main-Class": "${mainClass}" } @@ -132,11 +138,18 @@ createScript(project, 'org.tron.plugins.ArchiveManifest', 'ArchiveManifest') createScript(project, 'org.tron.plugins.Toolkit', 'Toolkit') def releaseBinary = hasProperty('binaryRelease') ? getProperty('binaryRelease') : 'true' +def skipArchive = hasProperty('skipArchive') ? true : false +def skipAll = hasProperty('skipAll') ? true : false if (releaseBinary == 'true') { artifacts { - archives( - binaryRelease('buildArchiveManifestJar', 'ArchiveManifest', 'org.tron.plugins.ArchiveManifest'), - binaryRelease('buildToolkitJar', 'Toolkit', 'org.tron.plugins.Toolkit')) + archives(binaryRelease('buildToolkitJar', 'Toolkit', 'org.tron.plugins.Toolkit')) + } + if (!skipAll) { + if (!skipArchive) { + artifacts { + archives(binaryRelease('buildArchiveManifestJar', 'ArchiveManifest', 'org.tron.plugins.ArchiveManifest')) + } + } } } diff --git a/plugins/src/main/java/org/tron/plugins/ArchiveManifest.java b/plugins/src/main/java/org/tron/plugins/ArchiveManifest.java index 793404ddc2c..4d54df6d299 100644 --- a/plugins/src/main/java/org/tron/plugins/ArchiveManifest.java +++ b/plugins/src/main/java/org/tron/plugins/ArchiveManifest.java @@ -82,7 +82,6 @@ public static org.iq80.leveldb.Options newDefaultLevelDbOptions() { dbOptions.maxOpenFiles(1000); dbOptions.maxBatchSize(64_000); dbOptions.maxManifestSize(128); - dbOptions.fast(false); return dbOptions; } diff --git a/plugins/src/main/java/org/tron/plugins/Db.java b/plugins/src/main/java/org/tron/plugins/Db.java index 702f505b147..e7296a2cbc5 100644 --- a/plugins/src/main/java/org/tron/plugins/Db.java +++ b/plugins/src/main/java/org/tron/plugins/Db.java @@ -1,47 +1,18 @@ package org.tron.plugins; -import com.typesafe.config.Config; -import com.typesafe.config.ConfigFactory; -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; import picocli.CommandLine; @CommandLine.Command(name = "db", mixinStandardHelpOptions = true, version = "db command 1.0", description = "An rich command set that provides high-level operations for dbs.", - subcommands = {CommandLine.HelpCommand.class, DbMove.class, DbArchive.class}, - commandListHeading = "%nCommands:%n%nThe most commonly used git commands are:%n" + subcommands = {CommandLine.HelpCommand.class, + DbMove.class, + DbArchive.class, + DbConvert.class, + DbLite.class + }, + commandListHeading = "%nCommands:%n%nThe most commonly used db commands are:%n" ) public class Db { - - static class ConfigConverter implements CommandLine.ITypeConverter { - ConfigConverter() { - } - - public Config convert(String value) throws IOException { - File file = Paths.get(value).toFile(); - if (file.exists() && file.isFile()) { - return ConfigFactory.parseFile(Paths.get(value).toFile()); - } else { - throw new IOException("DB config [" + value + "] not exist!"); - } - } - } - - static class PathConverter implements CommandLine.ITypeConverter { - PathConverter() { - } - - public Path convert(String value) throws IOException { - File file = Paths.get(value).toFile(); - if (file.exists() && file.isDirectory()) { - return file.toPath(); - } else { - throw new IOException("DB path [" + value + "] not exist!"); - } - } - } } diff --git a/plugins/src/main/java/org/tron/plugins/DbArchive.java b/plugins/src/main/java/org/tron/plugins/DbArchive.java index 2339fc9590b..e3032731ede 100644 --- a/plugins/src/main/java/org/tron/plugins/DbArchive.java +++ b/plugins/src/main/java/org/tron/plugins/DbArchive.java @@ -3,25 +3,14 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static org.iq80.leveldb.impl.Iq80DBFactory.factory; -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; -import java.util.Properties; import java.util.concurrent.Callable; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; @@ -30,11 +19,12 @@ import org.iq80.leveldb.DB; import org.iq80.leveldb.Options; import org.iq80.leveldb.impl.Filename; +import org.tron.plugins.utils.FileUtils; import picocli.CommandLine; import picocli.CommandLine.Option; @Slf4j(topic = "archive") -@CommandLine.Command(name = "archive", description = "a helper to rewrite leveldb manifest.") +@CommandLine.Command(name = "archive", description = "A helper to rewrite leveldb manifest.") public class DbArchive implements Callable { @CommandLine.Spec @@ -55,7 +45,7 @@ public class DbArchive implements Callable { description = "manifest min size(M) to archive. Default: ${DEFAULT-VALUE}") private int maxManifestSize; - @Option(names = {"-h", "--help"}, help = true) + @Option(names = {"-h", "--help"}) private boolean help; @@ -189,7 +179,7 @@ public void doArchive() { } try { if (checkManifest(levelDbFile.toString())) { - if (!checkEngine()) { + if (!FileUtils.isLevelDBEngine(srcDbPath)) { logger.info("Db {},not leveldb, ignored.", this.name); return; } @@ -203,46 +193,6 @@ public void doArchive() { throw new RuntimeException("Db " + this.name + " archive failed.", e); } } - - public boolean checkEngine() { - String dir = this.srcDbPath.toString(); - String enginePath = dir + File.separator + "engine.properties"; - if (!new File(enginePath).exists() && !writeProperty(enginePath, KEY_ENGINE, LEVELDB)) { - return false; - } - String engine = readProperty(enginePath, KEY_ENGINE); - return LEVELDB.equals(engine); - } - - public static String readProperty(String file, String key) { - try (FileInputStream fileInputStream = new FileInputStream(file); - InputStream inputStream = new BufferedInputStream(fileInputStream)) { - Properties prop = new Properties(); - prop.load(inputStream); - return new String(prop.getProperty(key, "").getBytes(StandardCharsets.ISO_8859_1), - UTF_8); - } catch (Exception e) { - logger.error("readProperty", e); - return ""; - } - } - - public static boolean writeProperty(String file, String key, String value) { - try (OutputStream out = new FileOutputStream(file); - FileInputStream fis = new FileInputStream(file); - BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out, UTF_8))) { - BufferedReader bf = new BufferedReader(new InputStreamReader(fis, UTF_8)); - Properties properties = new Properties(); - properties.load(bf); - properties.setProperty(key, value); - properties.store(bw, "Generated by the application. PLEASE DO NOT EDIT! "); - } catch (Exception e) { - logger.warn("writeProperty", e); - return false; - } - return true; - } - } } \ No newline at end of file diff --git a/plugins/src/main/java/org/tron/plugins/DbConvert.java b/plugins/src/main/java/org/tron/plugins/DbConvert.java new file mode 100644 index 00000000000..a75b235bbcf --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/DbConvert.java @@ -0,0 +1,360 @@ +package org.tron.plugins; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import me.tongfei.progressbar.ProgressBar; +import org.fusesource.leveldbjni.JniDBFactory; +import org.iq80.leveldb.DB; +import org.iq80.leveldb.DBIterator; +import org.rocksdb.RocksDB; +import org.rocksdb.RocksDBException; +import org.rocksdb.RocksIterator; +import org.rocksdb.Status; +import org.tron.plugins.utils.DBUtils; +import org.tron.plugins.utils.FileUtils; +import picocli.CommandLine; + + +@Slf4j(topic = "convert") +@CommandLine.Command(name = "convert", + description = "Covert leveldb to rocksdb.", + exitCodeListHeading = "Exit Codes:%n", + exitCodeList = { + "0:Successful", + "n:Internal error: exception occurred,please check toolkit.log"}) +public class DbConvert implements Callable { + + static { + RocksDB.loadLibrary(); + } + + private static final int BATCH = 256; + + @CommandLine.Spec + CommandLine.Model.CommandSpec spec; + @CommandLine.Parameters(index = "0", defaultValue = "output-directory/database", + description = " Input path for leveldb. Default: ${DEFAULT-VALUE}") + private File src; + @CommandLine.Parameters(index = "1", defaultValue = "output-directory-dst/database", + description = "Output path for rocksdb. Default: ${DEFAULT-VALUE}") + private File dest; + + @CommandLine.Option(names = {"--safe"}, + description = "In safe mode, read data from leveldb then put rocksdb." + + "If not, just change engine.properties from leveldb to rocksdb," + + "rocksdb is compatible with leveldb for current version." + + "This may not be the case in the future." + + "Default: ${DEFAULT-VALUE}") + private boolean safe; + + @CommandLine.Option(names = {"-h", "--help"}) + private boolean help; + + + @Override + public Integer call() throws Exception { + if (help) { + spec.commandLine().usage(System.out); + return 0; + } + if (!src.exists()) { + logger.info(" {} does not exist.", src); + spec.commandLine().getErr().println(spec.commandLine().getColorScheme() + .errorText(String.format("%s does not exist.", src))); + return 404; + } + List files = Arrays.stream(Objects.requireNonNull(src.listFiles())) + .filter(File::isDirectory) + .filter(e -> !DBUtils.CHECKPOINT_DB_V2.equals(e.getName())) + .collect(Collectors.toList()); + + // add checkpoint v2 convert + File cpV2Dir = new File(Paths.get(src.toString(), DBUtils.CHECKPOINT_DB_V2).toString()); + List cpList = new ArrayList<>(); + if (cpV2Dir.exists()) { + cpList = Arrays.stream(Objects.requireNonNull(cpV2Dir.listFiles())) + .filter(File::isDirectory) + .collect(Collectors.toList()); + } + + if (files.isEmpty()) { + logger.info("{} does not contain any database.", src); + spec.commandLine().getOut().format("%s does not contain any database.", src).println(); + return 0; + } + final long time = System.currentTimeMillis(); + List services = new ArrayList<>(); + files.forEach(f -> services.add( + new DbConverter(src.getPath(), dest.getPath(), f.getName(), safe))); + cpList.forEach(f -> services.add( + new DbConverter( + Paths.get(src.getPath(), DBUtils.CHECKPOINT_DB_V2).toString(), + Paths.get(dest.getPath(), DBUtils.CHECKPOINT_DB_V2).toString(), + f.getName(), safe))); + List fails = ProgressBar.wrap(services.stream(), "convert task").parallel().map( + dbConverter -> { + try { + return dbConverter.doConvert() ? null : dbConverter.name(); + } catch (Exception e) { + logger.error("{}", e); + spec.commandLine().getErr().println(spec.commandLine().getColorScheme() + .errorText(e.getMessage())); + return dbConverter.name(); + } + }).filter(Objects::nonNull).collect(Collectors.toList()); + long during = (System.currentTimeMillis() - time) / 1000; + spec.commandLine().getOut().format("convert db done, fails: %s, take %d s.", + fails, during).println(); + logger.info("database convert use {} seconds total, fails: {}.", during, fails); + return fails.size(); + } + + interface Converter { + + boolean doConvert() throws Exception; + + String name(); + } + + static class DbConverter implements Converter { + private final String srcDir; + private final String dstDir; + private final String dbName; + private final Path srcDbPath; + private final Path dstDbPath; + + private long srcDbKeyCount = 0L; + private long dstDbKeyCount = 0L; + private long srcDbKeySum = 0L; + private long dstDbKeySum = 0L; + private long srcDbValueSum = 0L; + private long dstDbValueSum = 0L; + + private boolean safe; + + public DbConverter(String srcDir, String dstDir, String name, boolean safe) { + this.srcDir = srcDir; + this.dstDir = dstDir; + this.dbName = name; + this.srcDbPath = Paths.get(this.srcDir, name); + this.dstDbPath = Paths.get(this.dstDir, name); + this.safe = safe; + } + + @Override + public boolean doConvert() throws Exception { + + if (checkDone(this.dstDbPath.toString())) { + logger.info(" {} is done, skip it.", this.dbName); + return true; + } + + File levelDbFile = srcDbPath.toFile(); + if (!levelDbFile.exists()) { + logger.info(" {} does not exist.", srcDbPath); + return true; + } + if (!FileUtils.isLevelDBEngine(srcDbPath)) { + logger.info("Db {},not leveldb, ignored.", this.dbName); + return true; + } + long startTime = System.currentTimeMillis(); + if (this.dstDbPath.toFile().exists()) { + logger.info(" {} begin to clear exist database directory", this.dbName); + FileUtils.deleteDir(this.dstDbPath.toFile()); + logger.info(" {} clear exist database directory done.", this.dbName); + } + + FileUtils.createDirIfNotExists(dstDir); + + logger.info("Convert database {} start", this.dbName); + if (safe) { + convertLevelToRocks(); + compact(); + } else { + FileUtils.copyDir(Paths.get(srcDir), Paths.get(dstDir), dbName); + } + boolean result = check() && createEngine(dstDbPath.toString()); + long etime = System.currentTimeMillis(); + + if (result) { + if (safe) { + logger.info("Convert database {} successful end with {} key-value {} minutes", + this.dbName, this.srcDbKeyCount, (etime - startTime) / 1000.0 / 60); + } else { + logger.info("Convert database {} successful end {} minutes", + this.dbName, (etime - startTime) / 1000.0 / 60); + } + + } else { + logger.info("Convert database {} failure", this.dbName); + if (this.dstDbPath.toFile().exists()) { + logger.info(" {} begin to clear exist database directory", this.dbName); + FileUtils.deleteDir(this.dstDbPath.toFile()); + logger.info(" {} clear exist database directory done.", this.dbName); + } + } + return result; + } + + @Override + public String name() { + return dbName; + } + + private void batchInsert(RocksDB rocks, List keys, List values) + throws Exception { + try (org.rocksdb.WriteBatch batch = new org.rocksdb.WriteBatch()) { + for (int i = 0; i < keys.size(); i++) { + byte[] k = keys.get(i); + byte[] v = values.get(i); + batch.put(k, v); + } + write(rocks, batch); + } + keys.clear(); + values.clear(); + } + + /** + * https://github.com/facebook/rocksdb/issues/6625. + * + * @param rocks db + * @param batch write batch + * @throws Exception RocksDBException + */ + private void write(RocksDB rocks, org.rocksdb.WriteBatch batch) throws Exception { + try { + rocks.write(new org.rocksdb.WriteOptions(), batch); + } catch (RocksDBException e) { + // retry + if (maybeRetry(e)) { + TimeUnit.MILLISECONDS.sleep(1); + write(rocks, batch); + } else { + throw e; + } + } + } + + private boolean maybeRetry(RocksDBException e) { + boolean retry = false; + if (e.getStatus() != null) { + retry = e.getStatus().getCode() == Status.Code.TryAgain + || e.getStatus().getCode() == Status.Code.Busy + || e.getStatus().getCode() == Status.Code.Incomplete; + } + return retry || (e.getMessage() != null && ("Write stall".equalsIgnoreCase(e.getMessage()) + || ("Incomplete").equalsIgnoreCase(e.getMessage()))); + } + + /** + * https://github.com/facebook/rocksdb/wiki/RocksDB-FAQ . + * What's the fastest way to load data into RocksDB? + * + * @return if ok + */ + public void convertLevelToRocks() throws Exception { + List keys = new ArrayList<>(BATCH); + List values = new ArrayList<>(BATCH); + JniDBFactory.pushMemoryPool(1024 * 1024); + try ( + DB level = DBUtils.newLevelDb(srcDbPath); + RocksDB rocks = DBUtils.newRocksDbForBulkLoad(dstDbPath); + DBIterator levelIterator = level.iterator( + new org.iq80.leveldb.ReadOptions().fillCache(false))) { + + levelIterator.seekToFirst(); + + while (levelIterator.hasNext()) { + Map.Entry entry = levelIterator.next(); + byte[] key = entry.getKey(); + byte[] value = entry.getValue(); + srcDbKeyCount++; + srcDbKeySum = byteArrayToIntWithOne(srcDbKeySum, key); + srcDbValueSum = byteArrayToIntWithOne(srcDbValueSum, value); + keys.add(key); + values.add(value); + if (keys.size() >= BATCH) { + batchInsert(rocks, keys, values); + } + } + // clear + if (!keys.isEmpty()) { + batchInsert(rocks, keys, values); + } + } finally { + JniDBFactory.popMemoryPool(); + } + } + + private void compact() throws RocksDBException { + if (DBUtils.MARKET_PAIR_PRICE_TO_ORDER.equalsIgnoreCase(this.dbName)) { + return; + } + try (RocksDB rocks = DBUtils.newRocksDb(this.dstDbPath)) { + logger.info("compact database {} start", this.dbName); + rocks.compactRange(); + logger.info("compact database {} end", this.dbName); + } + } + + private boolean check() throws RocksDBException { + if (!safe) { + return true; + } + try ( + RocksDB rocks = DBUtils.newRocksDbReadOnly(this.dstDbPath); + org.rocksdb.ReadOptions r = new org.rocksdb.ReadOptions().setFillCache(false); + RocksIterator rocksIterator = rocks.newIterator(r)) { + + // check + logger.info("check database {} start", this.dbName); + for (rocksIterator.seekToFirst(); rocksIterator.isValid(); rocksIterator.next()) { + byte[] key = rocksIterator.key(); + byte[] value = rocksIterator.value(); + dstDbKeyCount++; + dstDbKeySum = byteArrayToIntWithOne(dstDbKeySum, key); + dstDbValueSum = byteArrayToIntWithOne(dstDbValueSum, value); + } + logger.info("Check database {} end,dstDbKeyCount {}, dstDbKeySum {}, dstDbValueSum {}," + + "srcDbKeyCount {}, srcDbKeySum {}, srcDbValueSum {}", + dbName, dstDbKeyCount, dstDbKeySum, dstDbValueSum, + srcDbKeyCount, srcDbKeySum, srcDbValueSum); + return dstDbKeyCount == srcDbKeyCount && dstDbKeySum == srcDbKeySum + && dstDbValueSum == srcDbValueSum; + } + } + } + + private static boolean createEngine(String dir) { + String enginePath = dir + File.separator + DBUtils.FILE_ENGINE; + if (!FileUtils.createFileIfNotExists(enginePath)) { + return false; + } + return FileUtils.writeProperty(enginePath, DBUtils.KEY_ENGINE, DBUtils.ROCKSDB); + } + + private static boolean checkDone(String dir) { + String enginePath = dir + File.separator + DBUtils.FILE_ENGINE; + return FileUtils.isExists(enginePath); + } + + private static long byteArrayToIntWithOne(long sum, byte[] b) { + for (byte oneByte : b) { + sum += oneByte; + } + return sum; + } + +} diff --git a/plugins/src/main/java/org/tron/plugins/DbLite.java b/plugins/src/main/java/org/tron/plugins/DbLite.java new file mode 100644 index 00000000000..51b588bf9b5 --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/DbLite.java @@ -0,0 +1,740 @@ +package org.tron.plugins; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Lists; +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.concurrent.Callable; +import java.util.stream.Collectors; +import java.util.stream.LongStream; +import lombok.extern.slf4j.Slf4j; +import me.tongfei.progressbar.ProgressBar; +import org.rocksdb.RocksDBException; +import org.tron.plugins.utils.ByteArray; +import org.tron.plugins.utils.DBUtils; +import org.tron.plugins.utils.FileUtils; +import org.tron.plugins.utils.db.DBInterface; +import org.tron.plugins.utils.db.DBIterator; +import org.tron.plugins.utils.db.DbTool; +import org.tron.protos.Protocol; +import picocli.CommandLine; + +@Slf4j(topic = "lite") +@CommandLine.Command(name = "lite", + description = "Split lite data for java-tron.", + exitCodeListHeading = "Exit Codes:%n", + exitCodeList = { + "0:Successful", + "1:Internal error: exception occurred,please check toolkit.log"}) +public class DbLite implements Callable { + + private static final byte[] DB_KEY_LOWEST_BLOCK_NUM = "lowest_block_num".getBytes(); + private static final byte[] DB_KEY_NODE_TYPE = "node_type".getBytes(); + + 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 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 COMMON_DB_NAME = "common"; + 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 TRANS_CACHE_DB_NAME = "trans-cache"; + + private static final List archiveDbs = Arrays.asList( + BLOCK_DB_NAME, + BLOCK_INDEX_DB_NAME, + TRANS_DB_NAME, + TRANSACTION_RET_DB_NAME, + TRANSACTION_HISTORY_DB_NAME); + + enum Operate { split, merge } + + enum Type { snapshot, history } + + @CommandLine.Spec + CommandLine.Model.CommandSpec spec; + + @CommandLine.Option( + names = {"--operate", "-o"}, + defaultValue = "split", + description = "operate: [ ${COMPLETION-CANDIDATES} ]. Default: ${DEFAULT-VALUE}", + order = 1) + private Operate operate; + + @CommandLine.Option( + names = {"--type", "-t"}, + defaultValue = "snapshot", + description = "only used with operate=split: [ ${COMPLETION-CANDIDATES} ]." + + " Default: ${DEFAULT-VALUE}", + order = 2) + private Type type; + + @CommandLine.Option( + names = {"--fn-data-path", "-fn"}, + required = true, + description = "the database path to be split or merged.", + order = 3) + private String fnDataPath; + + @CommandLine.Option( + names = {"--dataset-path", "-ds"}, + required = true, + description = "when operation is `split`," + + "`dataset-path` is the path that store the `snapshot` or `history`," + + "when operation is `split`," + + "`dataset-path` is the `history` data path.", + order = 4) + private String datasetPath; + + @CommandLine.Option( + names = {"--help", "-h"}, + order = 5) + private boolean help; + + + @Override + public Integer call() { + if (help) { + spec.commandLine().usage(System.out); + return 0; + } + try { + switch (this.operate) { + case split: + if (Type.snapshot == this.type) { + generateSnapshot(fnDataPath, datasetPath); + } else if (Type.history == type) { + generateHistory(fnDataPath, datasetPath); + } + break; + case merge: + completeHistoryData(datasetPath, fnDataPath); + break; + default: + } + return 0; + } catch (Exception e) { + logger.error("{}", e); + spec.commandLine().getErr().println(spec.commandLine().getColorScheme() + .errorText(e.getMessage())); + spec.commandLine().usage(System.out); + return 1; + } finally { + DbTool.close(); + } + } + + /** + * 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."); + spec.commandLine().getOut().println("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); + // save min block to info + generateInfoProperties(Paths.get(snapshotDir, INFO_FILE_NAME).toString(), + getSecondBlock(snapshotDir)); + } catch (IOException | RocksDBException e) { + logger.error("Create snapshot failed, {}.", e.getMessage()); + spec.commandLine().getErr().println(spec.commandLine().getColorScheme() + .stackTraceText(e)); + return; + } + long during = (System.currentTimeMillis() - start) / 1000; + logger.info("Create snapshot finished, take {} s.", during); + spec.commandLine().getOut().format("Create snapshot finished, take %d s.", during).println(); + } + + /** + * 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."); + spec.commandLine().getOut().println("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); + // save max block to info + generateInfoProperties(Paths.get(historyDir, INFO_FILE_NAME).toString(), + getLatestBlockHeaderNum(sourceDir)); + } catch (IOException | RocksDBException e) { + logger.error("Create history failed, {}.", e.getMessage()); + spec.commandLine().getErr().println(spec.commandLine().getColorScheme() + .stackTraceText(e)); + return; + } + long during = (System.currentTimeMillis() - start) / 1000; + logger.info("Create history finished, take {} s.", during); + spec.commandLine().getOut().format("Create history finished, take %d s.", during).println(); + } + + /** + * Merge the history dataset into database. + * + * @param historyDir the path that stores the history dataset + * + * @param liteDir lite fullnode database path + */ + public void completeHistoryData(String historyDir, String liteDir) { + logger.info("Start merge history to lite node."); + spec.commandLine().getOut().println("Start merge history to lite node."); + long start = System.currentTimeMillis(); + 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 blockNumInfo = checkAndGetBlockNumInfo(historyDir, liteDir); + // 2. move archive dbs to bak + backupArchiveDbs(liteDir); + // 3. copy history data to liteDir + copyHistory2Database(historyDir, liteDir); + // 4. delete the extra block data in history data + trimExtraHistory(liteDir, blockNumInfo); + // 5. merge bak to database + mergeBak2Database(liteDir, blockNumInfo); + // 6. delete bak dir + deleteBackupArchiveDbs(liteDir); + // 7. delete snapshot flag + deleteSnapshotFlag(liteDir); + } catch (IOException | RocksDBException e) { + logger.error("Merge history data to database failed, {}.", e.getMessage()); + spec.commandLine().getErr().println(spec.commandLine().getColorScheme() + .stackTraceText(e)); + return; + } + long during = (System.currentTimeMillis() - start) / 1000; + logger.info("Merge history finished, take {} s.", during); + spec.commandLine().getOut().format("Merge history finished, take %d s.", during).println(); + } + + 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."); + spec.commandLine().getOut().println("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)); + } + FileUtils.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."); + spec.commandLine().getOut().println("Begin to merge checkpoint to dataset."); + try { + List cpList = getCheckpointV2List(sourceDir); + if (cpList.size() > 0) { + for (String cp : cpList) { + DBInterface checkpointDb = DbTool.getDB( + sourceDir + "/" + DBUtils.CHECKPOINT_DB_V2, cp); + recover(checkpointDb, destDir, destDbs); + } + } else if (Paths.get(sourceDir, CHECKPOINT_DB).toFile().exists()) { + 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 = DBUtils.simpleDecode(key); + // skip trans-cache db + if (TRANS_CACHE_DB_NAME.equalsIgnoreCase(dbName)) { + continue; + } + 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 (DBUtils.Operator.DELETE.getValue() == op) { + destDb.delete(realKey); + } else { + destDb.put(realKey, new byte[0]); + } + } + } + } + } + } + + private void generateInfoProperties(String propertyfile, long num) + throws IOException, RocksDBException { + logger.info("Create {} for dataset.", INFO_FILE_NAME); + spec.commandLine().getOut().format("Create %s for dataset.", INFO_FILE_NAME).println(); + if (!FileUtils.createFileIfNotExists(propertyfile)) { + throw new RuntimeException("Create properties file failed."); + } + if (!FileUtils.writeProperty(propertyfile, DBUtils.SPLIT_BLOCK_NUM, Long.toString(num))) { + 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; + if (cpList.size() > 0) { + String lastestCp = cpList.get(cpList.size() - 1); + checkpointDb = DbTool.getDB( + databaseDir + "/" + DBUtils.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); + spec.commandLine().getOut().format( + "Begin to fill %d block, genesis block and trans to snapshot.", RECENT_BLKS).println(); + DBInterface sourceBlockIndexDb = DbTool.getDB(sourceDir, BLOCK_INDEX_DB_NAME); + DBInterface sourceBlockDb = DbTool.getDB(sourceDir, BLOCK_DB_NAME); + // init snapshot db ,keep engine same as source + DBInterface destBlockDb = DbTool.getDB(sourceDir, snapshotDir, BLOCK_DB_NAME); + DBInterface destBlockIndexDb = DbTool.getDB(sourceDir, snapshotDir, BLOCK_INDEX_DB_NAME); + DBInterface destTransDb = DbTool.getDB(sourceDir, 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 + ProgressBar.wrap(LongStream.rangeClosed(startIndex, latestBlockNum), "fillBlockAndTrans") + .forEach(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; + Protocol.Block.parseFrom(block).getTransactionsList().stream().map( + tc -> DBUtils.getTransactionId(tc).getBytes()) + .map(bytes -> Maps.immutableEntry(bytes, Longs.toByteArray(finalBlockNum))) + .forEach(e -> destTransDb.put(e.getKey(), e.getValue())); + } catch (IOException | RocksDBException e) { + throw new RuntimeException(e.getMessage()); + } + }); + + DBInterface destCommonDb = DbTool.getDB(snapshotDir, COMMON_DB_NAME); + destCommonDb.put(DB_KEY_NODE_TYPE, ByteArray.fromInt(DBUtils.NODE_TYPE_LIGHT_NODE)); + destCommonDb.put(DB_KEY_LOWEST_BLOCK_NUM, ByteArray.fromLong(startIndex)); + // 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, DBUtils.FILE_ENGINE); + if (ori.toFile().exists()) { + FileUtils.copy(ori, Paths.get(dest, dbName, DBUtils.FILE_ENGINE)); + } + } + } + + 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 liteDir) + throws IOException, RocksDBException { + logger.info("Check the compatibility of this history."); + spec.commandLine().getOut().println("Check the compatibility of this history."); + String snapshotInfo = Paths.get(liteDir, INFO_FILE_NAME).toString(); + String historyInfo = Paths.get(historyDir, INFO_FILE_NAME).toString(); + if (!FileUtils.isExists(snapshotInfo)) { + throw new FileNotFoundException( + "Snapshot property file is not found. maybe this is a complete fullnode?"); + } + if (!FileUtils.isExists(historyInfo)) { + throw new FileNotFoundException("history property file is not found."); + } + // min block for snapshot + long snapshotMinNum = getSecondBlock(liteDir); + // max block for snapshot + long snapshotMaxNum = getLatestBlockHeaderNum(liteDir); + // max block for history + long historyMaxNum = Long.parseLong(FileUtils.readProperty(historyInfo, DBUtils + .SPLIT_BLOCK_NUM)); + if (historyMaxNum < snapshotMinNum) { + throw new RuntimeException( + String.format( + "History max block is lower than snapshot min number, history: %d, snapshot: %d", + historyMaxNum, snapshotMinNum)); + } + // check genesis block is equal + if (!Arrays.equals(getGenesisBlockHash(liteDir), getGenesisBlockHash(historyDir))) { + throw new RuntimeException(String.format( + "Genesis block hash is not equal, history: %s, database: %s", + Arrays.toString(getGenesisBlockHash(historyDir)), + Arrays.toString(getGenesisBlockHash(liteDir)))); + } + return new BlockNumInfo(snapshotMinNum, historyMaxNum, snapshotMaxNum); + } + + private void backupArchiveDbs(String databaseDir) throws IOException { + Path bakDir = Paths.get(databaseDir, BACKUP_DIR_PREFIX + START_TIME); + logger.info("Backup the archive dbs to {}.", bakDir); + spec.commandLine().getOut().format("Backup the archive dbs to %s.", bakDir).println(); + if (!FileUtils.createDirIfNotExists(bakDir.toString())) { + throw new RuntimeException(String.format("create bak dir %s failed", bakDir)); + } + FileUtils.copyDatabases(Paths.get(databaseDir), bakDir, archiveDbs); + archiveDbs.forEach(db -> FileUtils.deleteDir(new File(databaseDir, db))); + } + + private void copyHistory2Database(String historyDir, String databaseDir) throws IOException { + logger.info("Begin to copy history to database."); + spec.commandLine().getOut().println("Begin to copy history to database."); + FileUtils.copyDatabases(Paths.get(historyDir), Paths.get(databaseDir), archiveDbs); + } + + private void trimExtraHistory(String liteDir, BlockNumInfo blockNumInfo) + throws IOException, RocksDBException { + long start = blockNumInfo.getSnapshotMaxNum() + 1; + long end = blockNumInfo.getHistoryMaxNum(); + if (start > end) { + logger.info("Ignore trimming the history data, from {} to {}.", start, end); + spec.commandLine().getOut() + .format("Ignore trimming the history data, from %d to %d.", start, end).println(); + return; + } + logger.info("Begin to trim the history data, from {} to {}.", start, end); + spec.commandLine().getOut() + .format("Begin to trim the history data, from %d to %d.", start, end).println(); + DBInterface blockIndexDb = DbTool.getDB(liteDir, BLOCK_INDEX_DB_NAME); + DBInterface blockDb = DbTool.getDB(liteDir, BLOCK_DB_NAME); + DBInterface transDb = DbTool.getDB(liteDir, TRANS_DB_NAME); + DBInterface tranRetDb = DbTool.getDB(liteDir, TRANSACTION_RET_DB_NAME); + + + ProgressBar.wrap(LongStream.rangeClosed(start, end) + .boxed() + .sorted((a, b) -> Long.compare(b, a)), "trimHistory").forEach(n -> { + try { + byte[] blockIdHash = blockIndexDb.get(ByteArray.fromLong(n)); + Protocol.Block block = Protocol.Block.parseFrom(blockDb.get(blockIdHash)); + // delete transactions + for (Protocol.Transaction e : block.getTransactionsList()) { + transDb.delete(DBUtils.getTransactionId(e).getBytes()); + } + // delete transaction result + tranRetDb.delete(ByteArray.fromLong(n)); + // delete block + blockDb.delete(blockIdHash); + // delete block index + blockIndexDb.delete(ByteArray.fromLong(n)); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } + + private void mergeBak2Database(String liteDir, BlockNumInfo blockNumInfo) throws + IOException, RocksDBException { + long start = blockNumInfo.getHistoryMaxNum() + 1; + long end = blockNumInfo.getSnapshotMaxNum(); + + if (start > end) { + logger.info("Ignore merging the bak data, start {} end {}.", start, end); + spec.commandLine().getOut() + .format("Ignore merging the bak data, start %d end %d.", start, end).println(); + return; + } + + + Path bakDir = Paths.get(liteDir, BACKUP_DIR_PREFIX + START_TIME); + logger.info("Begin to merge {} to database, start {} end {}.", bakDir, start, end); + spec.commandLine().getOut() + .format("Begin to merge %s to database, start %d end %d.", bakDir, start, end).println(); + byte[] head = ByteArray.fromLong(start); + // use seek to skip + archiveDbs.stream().parallel().forEach(dbName -> { + try { + DBInterface bakDb = DbTool.getDB(bakDir.toString(), dbName); + DBInterface destDb = DbTool.getDB(liteDir, dbName); + try (DBIterator iterator = bakDb.iterator()) { + if (TRANS_DB_NAME.equals(dbName) || TRANSACTION_HISTORY_DB_NAME.equals(dbName)) { + iterator.seekToFirst(); + } else { + iterator.seek(head); + } + ProgressBar.wrap(iterator, dbName) + .forEachRemaining(e -> destDb.put(e.getKey(), e.getValue())); + } + } catch (IOException | RocksDBException e) { + throw new RuntimeException(e); + } + }); + } + + 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); + spec.commandLine().getOut().format("Delete the info file from %s.", databaseDir).println(); + Files.delete(Paths.get(databaseDir, INFO_FILE_NAME)); + if (!isLite(databaseDir)) { + DBInterface destCommonDb = DbTool.getDB(databaseDir, COMMON_DB_NAME); + destCommonDb.delete(DB_KEY_NODE_TYPE); + destCommonDb.delete(DB_KEY_LOWEST_BLOCK_NUM); + logger.info("Deleted {} and {} from {} to identify this node is a real fullnode.", + "node_type", "lowest_block_num", COMMON_DB_NAME); + spec.commandLine().getOut().format( + "Deleted %s and %s from %s to identify this node is a real fullnode.", + "node_type", "lowest_block_num", COMMON_DB_NAME).println(); + } + + } + + private void deleteBackupArchiveDbs(String liteDir) throws IOException, RocksDBException { + + Path bakDir = Paths.get(liteDir, BACKUP_DIR_PREFIX + START_TIME); + logger.info("Begin to delete bak dir {}.", bakDir); + spec.commandLine().getOut().format("Begin to delete bak dir %s.", bakDir).println(); + if (FileUtils.deleteDir(bakDir.toFile())) { + logger.info("End to delete bak dir {}.", bakDir); + spec.commandLine().getOut().format("End to delete bak dir %s.", bakDir).println(); + } else { + logger.info("Fail to delete bak dir {}, please remove manually.", bakDir); + spec.commandLine().getOut().format("Fail to delete bak dir %s, please remove manually.", + bakDir).println(); + } + } + + 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, DBUtils.CHECKPOINT_DB_V2).toString()); + if (file.exists() && file.isDirectory() && file.list() != null) { + return Arrays.stream(Objects.requireNonNull(file.list())).sorted() + .collect(Collectors.toList()); + } + return Lists.newArrayList(); + } + + static class BlockNumInfo { + private final long snapshotMinNum; + private final long snapshotMaxNum; + private final long historyMaxNum; + + public BlockNumInfo(long snapshotMinNum, long historyMaxNum, long snapshotMaxNum) { + this.snapshotMinNum = snapshotMinNum; + this.historyMaxNum = historyMaxNum; + this.snapshotMaxNum = snapshotMaxNum; + } + + public long getSnapshotMinNum() { + return snapshotMinNum; + } + + public long getHistoryMaxNum() { + return historyMaxNum; + } + + public long getSnapshotMaxNum() { + return snapshotMaxNum; + } + } +} + + + diff --git a/plugins/src/main/java/org/tron/plugins/DbMove.java b/plugins/src/main/java/org/tron/plugins/DbMove.java index 77c3dca26f8..a5619d2d7ed 100644 --- a/plugins/src/main/java/org/tron/plugins/DbMove.java +++ b/plugins/src/main/java/org/tron/plugins/DbMove.java @@ -15,12 +15,15 @@ import java.util.Set; import java.util.concurrent.Callable; import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; import me.tongfei.progressbar.ProgressBar; +import org.tron.plugins.utils.FileUtils; import picocli.CommandLine; import picocli.CommandLine.Command; +@Slf4j(topic = "move") @Command(name = "mv", aliases = "move", - description = "mv db to pre-set new path . For example HDD,reduce storage expenses.") + description = "Move db to pre-set new path . For example HDD,reduce storage expenses.") public class DbMove implements Callable { private static final String PROPERTIES_CONFIG_KEY = "storage.properties"; @@ -35,24 +38,24 @@ public class DbMove implements Callable { @CommandLine.Option(names = {"-d", "--database-directory"}, defaultValue = "output-directory", - converter = Db.PathConverter.class, + converter = PathConverter.class, description = "database directory path. Default: ${DEFAULT-VALUE}") static Path database; @CommandLine.Option(names = {"-c", "--config"}, defaultValue = "config.conf", converter = ConfigConverter.class, - order = Integer.MAX_VALUE, description = " config file. Default: ${DEFAULT-VALUE}") Config config; - @CommandLine.Option(names = {"-h", "--help"}, help = true, description = "display a help message") - boolean help; + @CommandLine.Option(names = {"-h", "--help"}) + static boolean help; @Override public Integer call() throws Exception { if (help) { spec.commandLine().usage(System.out); + help = false; return 0; } @@ -129,7 +132,7 @@ private void run(Property p) { } }); try { - if (deleteDir(p.original.toFile())) { + if (FileUtils.deleteDir(p.original.toFile())) { Files.createSymbolicLink(p.original, p.destination); } } catch (IOException | UnsupportedOperationException x) { @@ -144,20 +147,6 @@ private void printNotExist() { spec.commandLine().getErr().println(NOT_FIND); } - /** - * delete directory. - */ - public static boolean deleteDir(File dir) { - if (dir.isDirectory()) { - String[] children = dir.list(); - if (children != null) { - for (String child : children) { - deleteDir(new File(dir, child)); - } - } - } - return dir.delete(); - } static class Property { @@ -174,7 +163,7 @@ public Property(String name, Path original, Path destination) throws IOException if (this.original.toFile().isFile()) { throw new IOException(this.original + " is a file!"); } - if (isSymbolicLink(original.toFile())) { + if (FileUtils.isSymbolicLink(original.toFile())) { throw new IOException(original + " is symbolicLink!"); } this.destination = destination.toFile().getCanonicalFile().toPath(); @@ -185,21 +174,6 @@ public Property(String name, Path original, Path destination) throws IOException throw new IOException("destination and original can not be same:[" + this.original + "]!"); } } - - public boolean isSymbolicLink(File file) throws IOException { - if (file == null) { - throw new NullPointerException("File must not be null"); - } - - File canon; - if (file.getParent() == null) { - canon = file; - } else { - File canonDir = file.getParentFile().getCanonicalFile(); - canon = new File(canonDir, file.getName()); - } - return !canon.getCanonicalFile().equals(canon.getAbsoluteFile()); - } } static class ConfigConverter implements CommandLine.ITypeConverter { @@ -210,6 +184,9 @@ static class ConfigConverter implements CommandLine.ITypeConverter { } public Config convert(String value) throws Exception { + if (help) { + return null; + } File file = Paths.get(value).toFile(); if (file.exists() && file.isFile()) { Config config = ConfigFactory.parseFile(Paths.get(value).toFile()); @@ -248,4 +225,21 @@ public Config convert(String value) throws Exception { } } } + + static class PathConverter implements CommandLine.ITypeConverter { + PathConverter() { + } + + public Path convert(String value) throws IOException { + if (help) { + return null; + } + File file = Paths.get(value).toFile(); + if (file.exists() && file.isDirectory()) { + return file.toPath(); + } else { + throw new IOException("DB path [" + value + "] not exist!"); + } + } + } } diff --git a/plugins/src/main/java/org/tron/plugins/comparator/MarketOrderPriceComparatorForLevelDB.java b/plugins/src/main/java/org/tron/plugins/comparator/MarketOrderPriceComparatorForLevelDB.java new file mode 100644 index 00000000000..0879f770e1f --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/comparator/MarketOrderPriceComparatorForLevelDB.java @@ -0,0 +1,28 @@ +package org.tron.plugins.comparator; + +import org.iq80.leveldb.DBComparator; +import org.tron.plugins.utils.MarketUtils; + +public class MarketOrderPriceComparatorForLevelDB implements DBComparator { + + @Override + public String name() { + return "MarketOrderPriceComparator"; + } + + @Override + public byte[] findShortestSeparator(byte[] start, byte[] limit) { + return new byte[0]; + } + + @Override + public byte[] findShortSuccessor(byte[] key) { + return new byte[0]; + } + + @Override + public int compare(byte[] o1, byte[] o2) { + return MarketUtils.comparePriceKey(o1, o2); + } + +} \ No newline at end of file diff --git a/plugins/src/main/java/org/tron/plugins/comparator/MarketOrderPriceComparatorForRockDB.java b/plugins/src/main/java/org/tron/plugins/comparator/MarketOrderPriceComparatorForRockDB.java new file mode 100644 index 00000000000..cd718bdd2d7 --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/comparator/MarketOrderPriceComparatorForRockDB.java @@ -0,0 +1,38 @@ +package org.tron.plugins.comparator; + +import org.rocksdb.ComparatorOptions; +import org.rocksdb.DirectSlice; +import org.rocksdb.util.DirectBytewiseComparator; +import org.tron.plugins.utils.MarketUtils; + +public class MarketOrderPriceComparatorForRockDB extends DirectBytewiseComparator { + + public MarketOrderPriceComparatorForRockDB(final ComparatorOptions copt) { + super(copt); + } + + @Override + public String name() { + return "MarketOrderPriceComparator"; + } + + @Override + public int compare(final DirectSlice a, final DirectSlice b) { + return MarketUtils.comparePriceKey(convertDataToBytes(a), convertDataToBytes(b)); + } + + /** + * DirectSlice.data().array will throw UnsupportedOperationException. + * */ + public byte[] convertDataToBytes(DirectSlice directSlice) { + int capacity = directSlice.data().capacity(); + byte[] bytes = new byte[capacity]; + + for (int i = 0; i < capacity; i++) { + bytes[i] = directSlice.get(i); + } + + return bytes; + } + +} \ No newline at end of file diff --git a/plugins/src/main/java/org/tron/plugins/utils/ByteArray.java b/plugins/src/main/java/org/tron/plugins/utils/ByteArray.java new file mode 100644 index 00000000000..3422c36ca9d --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/utils/ByteArray.java @@ -0,0 +1,101 @@ +package org.tron.plugins.utils; + +import com.google.common.primitives.Ints; +import com.google.common.primitives.Longs; +import java.math.BigInteger; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; + +public class ByteArray { + + public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; + public static final byte[] ZERO_BYTE_ARRAY = new byte[]{0}; + public static final int WORD_SIZE = 32; + + /** + * get bytes data from string data. + */ + public static byte[] fromString(String s) { + return StringUtils.isBlank(s) ? null : s.getBytes(); + } + + /** + * get string data from bytes data. + */ + public static String toStr(byte[] b) { + return ArrayUtils.isEmpty(b) ? null : new String(b); + } + + public static byte[] fromLong(long val) { + return Longs.toByteArray(val); + } + + /** + * get long data from bytes data. + */ + public static long toLong(byte[] b) { + return ArrayUtils.isEmpty(b) ? 0 : new BigInteger(1, b).longValue(); + } + + public static byte[] fromInt(int val) { + return Ints.toByteArray(val); + } + + /** + * get int data from bytes data. + */ + public static int toInt(byte[] b) { + return ArrayUtils.isEmpty(b) ? 0 : new BigInteger(1, b).intValue(); + } + + public static int compareUnsigned(byte[] a, byte[] b) { + if (a == b) { + return 0; + } + if (a == null) { + return -1; + } + if (b == null) { + return 1; + } + int minLen = Math.min(a.length, b.length); + for (int i = 0; i < minLen; ++i) { + int aVal = a[i] & 0xFF; + int bVal = b[i] & 0xFF; + if (aVal < bVal) { + return -1; + } + if (aVal > bVal) { + return 1; + } + } + if (a.length < b.length) { + return -1; + } + if (a.length > b.length) { + return 1; + } + return 0; + } + + public static String toHexString(byte[] data) { + return data == null ? "" : Hex.toHexString(data); + } + + /** + * get bytes data from hex string data. + */ + public static byte[] fromHexString(String data) { + if (data == null) { + return EMPTY_BYTE_ARRAY; + } + if (data.startsWith("0x")) { + data = data.substring(2); + } + if (data.length() % 2 != 0) { + data = "0" + data; + } + return Hex.decode(data); + } +} diff --git a/plugins/src/main/java/org/tron/plugins/utils/CryptoUitls.java b/plugins/src/main/java/org/tron/plugins/utils/CryptoUitls.java new file mode 100644 index 00000000000..6d3e4ccb548 --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/utils/CryptoUitls.java @@ -0,0 +1,6 @@ +package org.tron.plugins.utils; + +public class CryptoUitls { + + public static final String ECKey_ENGINE = "ECKey"; +} diff --git a/plugins/src/main/java/org/tron/plugins/utils/DBUtils.java b/plugins/src/main/java/org/tron/plugins/utils/DBUtils.java new file mode 100644 index 00000000000..19547e2b5a5 --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/utils/DBUtils.java @@ -0,0 +1,153 @@ +package org.tron.plugins.utils; + +import static org.fusesource.leveldbjni.JniDBFactory.factory; + +import com.google.common.primitives.Ints; +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Arrays; +import lombok.Getter; +import org.iq80.leveldb.CompressionType; +import org.iq80.leveldb.DB; +import org.rocksdb.BlockBasedTableConfig; +import org.rocksdb.BloomFilter; +import org.rocksdb.ComparatorOptions; +import org.rocksdb.Options; +import org.rocksdb.RocksDB; +import org.rocksdb.RocksDBException; +import org.tron.plugins.comparator.MarketOrderPriceComparatorForLevelDB; +import org.tron.plugins.comparator.MarketOrderPriceComparatorForRockDB; +import org.tron.protos.Protocol; + +public class DBUtils { + + + public enum Operator { + CREATE((byte) 0), + MODIFY((byte) 1), + DELETE((byte) 2), + PUT((byte) 3); + + @Getter + private byte value; + + Operator(byte value) { + this.value = value; + } + + static Operator valueOf(byte b) { + switch (b) { + case 0: + return Operator.CREATE; + case 1: + return Operator.MODIFY; + case 2: + return Operator.DELETE; + case 3: + return Operator.PUT; + default: + return null; + } + } + } + + public static final String SPLIT_BLOCK_NUM = "split_block_num"; + public static final String MARKET_PAIR_PRICE_TO_ORDER = "market_pair_price_to_order"; + public static final String CHECKPOINT_DB_V2 = "checkpoint"; + public static final String TMP = "tmp"; + + public static final int NODE_TYPE_LIGHT_NODE = 1; + + public static final String KEY_ENGINE = "ENGINE"; + public static final String FILE_ENGINE = "engine.properties"; + public static final String LEVELDB = "LEVELDB"; + public static final String ROCKSDB = "ROCKSDB"; + + public static DB newLevelDb(Path db) throws IOException { + File file = db.toFile(); + org.iq80.leveldb.Options dbOptions = newDefaultLevelDbOptions(); + if (MARKET_PAIR_PRICE_TO_ORDER.equalsIgnoreCase(file.getName())) { + dbOptions.comparator(new MarketOrderPriceComparatorForLevelDB()); + } + return factory.open(file, dbOptions); + } + + public static org.iq80.leveldb.Options newDefaultLevelDbOptions() { + org.iq80.leveldb.Options dbOptions = new org.iq80.leveldb.Options(); + dbOptions.createIfMissing(true); + dbOptions.paranoidChecks(true); + dbOptions.verifyChecksums(true); + dbOptions.compressionType(CompressionType.SNAPPY); + dbOptions.blockSize(4 * 1024); + dbOptions.writeBufferSize(10 * 1024 * 1024); + dbOptions.cacheSize(10 * 1024 * 1024L); + dbOptions.maxOpenFiles(1000); + return dbOptions; + } + + private static Options newDefaultRocksDbOptions(boolean forBulkLoad) { + Options options = new Options(); + options.setCreateIfMissing(true); + options.setIncreaseParallelism(1); + options.setNumLevels(7); + options.setMaxOpenFiles(5000); + 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); + final BlockBasedTableConfig tableCfg; + options.setTableFormatConfig(tableCfg = new BlockBasedTableConfig()); + tableCfg.setBlockSize(64 * 1024); + tableCfg.setBlockCacheSize(32 * 1024 * 1024); + tableCfg.setCacheIndexAndFilterBlocks(true); + tableCfg.setPinL0FilterAndIndexBlocksInCache(true); + tableCfg.setFilter(new BloomFilter(10, false)); + if (forBulkLoad) { + options.prepareForBulkLoad(); + } + return options; + } + + public static RocksDB newRocksDb(Path db) throws RocksDBException { + try (Options options = newDefaultRocksDbOptions(false)) { + if (MARKET_PAIR_PRICE_TO_ORDER.equalsIgnoreCase(db.getFileName().toString())) { + options.setComparator(new MarketOrderPriceComparatorForRockDB(new ComparatorOptions())); + } + return RocksDB.open(options, db.toString()); + } + } + + public static RocksDB newRocksDbForBulkLoad(Path db) throws RocksDBException { + try (Options options = newDefaultRocksDbOptions(true)) { + if (MARKET_PAIR_PRICE_TO_ORDER.equalsIgnoreCase(db.getFileName().toString())) { + options.setComparator(new MarketOrderPriceComparatorForRockDB(new ComparatorOptions())); + } + return RocksDB.open(options, db.toString()); + } + } + + + public static RocksDB newRocksDbReadOnly(Path db) throws RocksDBException { + try (Options options = newDefaultRocksDbOptions(false)) { + if (MARKET_PAIR_PRICE_TO_ORDER.equalsIgnoreCase(db.getFileName().toString())) { + options.setComparator(new MarketOrderPriceComparatorForRockDB(new ComparatorOptions())); + } + return RocksDB.openReadOnly(options, db.toString()); + } + } + + public static String simpleDecode(byte[] bytes) { + byte[] lengthBytes = Arrays.copyOf(bytes, 4); + int length = Ints.fromByteArray(lengthBytes); + byte[] value = Arrays.copyOfRange(bytes, 4, 4 + length); + return new String(value); + } + + public static Sha256Hash getTransactionId(Protocol.Transaction transaction) { + return Sha256Hash.of(true, + transaction.getRawData().toByteArray()); + } +} diff --git a/plugins/src/main/java/org/tron/plugins/utils/FileUtils.java b/plugins/src/main/java/org/tron/plugins/utils/FileUtils.java new file mode 100644 index 00000000000..b07b4469dc3 --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/utils/FileUtils.java @@ -0,0 +1,189 @@ +package org.tron.plugins.utils; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; +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 java.util.Properties; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class FileUtils { + + public static boolean isLevelDBEngine(Path path) { + String dir = path.toString(); + String enginePath = dir + File.separator + "engine.properties"; + if (!new File(enginePath).exists() + && !writeProperty(enginePath, DBUtils.KEY_ENGINE, DBUtils.LEVELDB)) { + return false; + } + String engine = readProperty(enginePath, DBUtils.KEY_ENGINE); + return DBUtils.LEVELDB.equals(engine); + } + + public static String readProperty(String file, String key) { + try (FileInputStream fileInputStream = new FileInputStream(file); + InputStream inputStream = new BufferedInputStream(fileInputStream)) { + Properties prop = new Properties(); + prop.load(inputStream); + return new String(prop.getProperty(key, "").getBytes(StandardCharsets.ISO_8859_1), + StandardCharsets.UTF_8); + } catch (Exception e) { + logger.error("readProperty", e); + return ""; + } + } + + public static boolean writeProperty(String file, String key, String value) { + try (OutputStream o = new FileOutputStream(file); + FileInputStream f = new FileInputStream(file); + BufferedWriter w = new BufferedWriter(new OutputStreamWriter(o, StandardCharsets.UTF_8)); + BufferedReader r = new BufferedReader(new InputStreamReader(f, StandardCharsets.UTF_8)) + ) { + Properties properties = new Properties(); + properties.load(r); + properties.setProperty(key, value); + properties.store(w, "Generated by the application. PLEASE DO NOT EDIT! "); + } catch (Exception e) { + logger.warn("writeProperty", e); + return false; + } + return true; + } + + + /** + * delete directory. + */ + public static boolean deleteDir(File dir) { + if (dir.isDirectory()) { + String[] children = dir.list(); + for (int i = 0; i < children.length; i++) { + boolean success = deleteDir(new File(dir, children[i])); + if (!success) { + return false; + } + } + } + return dir.delete(); + } + + public static boolean createFileIfNotExists(String filepath) { + File file = new File(filepath); + if (!file.exists()) { + try { + file.createNewFile(); + } catch (Exception e) { + return false; + } + } + return true; + } + + public static boolean createDirIfNotExists(String dirPath) { + File dir = new File(dirPath); + if (!dir.exists()) { + return dir.mkdirs(); + } + return true; + } + + public static boolean isExists(String path) { + File file = new File(path); + return file.exists(); + } + + public static boolean isSymbolicLink(File file) throws IOException { + if (file == null) { + throw new NullPointerException("File must not be null"); + } + + File canon; + if (file.getParent() == null) { + canon = file; + } else { + File canonDir = file.getParentFile().getCanonicalFile(); + canon = new File(canonDir, file.getName()); + } + return !canon.getCanonicalFile().equals(canon.getAbsoluteFile()); + } + + /** + * 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 (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 copyDir(Path src, Path dest, String dir) { + if (isExists(Paths.get(src.toString(), dir).toString())) { + try { + if (createDirIfNotExists(Paths.get(dest.toString(), dir).toString())) { + Files.walk(Paths.get(src.toString(), dir), FileVisitOption.FOLLOW_LINKS) + .forEach(source -> copy(source, dest.resolve(src.relativize(source)))); + } else { + throw new IOException(String.format("dest %s create fail ", + Paths.get(dest.toString(), dir))); + } + } catch (IOException e) { + logger.error("copy dir 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 { + java.nio.file.Files.createLink(dest, source); + } catch (FileSystemException e) { + java.nio.file.Files.copy(source, dest, StandardCopyOption.REPLACE_EXISTING); + } + } else { + java.nio.file.Files.copy(source, dest, StandardCopyOption.REPLACE_EXISTING); + } + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } +} diff --git a/plugins/src/main/java/org/tron/plugins/utils/MarketUtils.java b/plugins/src/main/java/org/tron/plugins/utils/MarketUtils.java new file mode 100644 index 00000000000..a36fc8ad57c --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/utils/MarketUtils.java @@ -0,0 +1,148 @@ +package org.tron.plugins.utils; + +import java.math.BigInteger; +import org.tron.plugins.utils.ByteArray; + +public class MarketUtils { + + public static final int TOKEN_ID_LENGTH = ByteArray + .fromString(Long.toString(Long.MAX_VALUE)).length; // 19 + + + + /** + * In order to avoid the difference between the data of same key stored and fetched by hashMap and + * levelDB, when creating the price key, we will find the GCD (Greatest Common Divisor) of + * sellTokenQuantity and buyTokenQuantity. + */ + public static byte[] createPairPriceKey(byte[] sellTokenId, byte[] buyTokenId, + long sellTokenQuantity, long buyTokenQuantity) { + + byte[] sellTokenQuantityBytes; + byte[] buyTokenQuantityBytes; + + // cal the GCD + long gcd = findGCD(sellTokenQuantity, buyTokenQuantity); + if (gcd == 0) { + sellTokenQuantityBytes = ByteArray.fromLong(sellTokenQuantity); + buyTokenQuantityBytes = ByteArray.fromLong(buyTokenQuantity); + } else { + sellTokenQuantityBytes = ByteArray.fromLong(sellTokenQuantity / gcd); + buyTokenQuantityBytes = ByteArray.fromLong(buyTokenQuantity / gcd); + } + + return doCreatePairPriceKey(sellTokenId, buyTokenId, + sellTokenQuantityBytes, buyTokenQuantityBytes); + } + + public static long findGCD(long number1, long number2) { + if (number1 == 0 || number2 == 0) { + return 0; + } + return calGCD(number1, number2); + } + + private static long calGCD(long number1, long number2) { + if (number2 == 0) { + return number1; + } + return calGCD(number2, number1 % number2); + } + + + private static byte[] doCreatePairPriceKey(byte[] sellTokenId, byte[] buyTokenId, + byte[] sellTokenQuantity, byte[] buyTokenQuantity) { + byte[] result = new byte[TOKEN_ID_LENGTH + TOKEN_ID_LENGTH + + sellTokenQuantity.length + buyTokenQuantity.length]; + + System.arraycopy(sellTokenId, 0, result, 0, sellTokenId.length); + System.arraycopy(buyTokenId, 0, result, TOKEN_ID_LENGTH, buyTokenId.length); + System.arraycopy(sellTokenQuantity, 0, result, + TOKEN_ID_LENGTH + TOKEN_ID_LENGTH, + sellTokenQuantity.length); + System.arraycopy(buyTokenQuantity, 0, result, + TOKEN_ID_LENGTH + TOKEN_ID_LENGTH + buyTokenQuantity.length, + buyTokenQuantity.length); + + return result; + } + + + public static int comparePriceKey(byte[] o1, byte[] o2) { + //compare pair + byte[] pair1 = new byte[TOKEN_ID_LENGTH * 2]; + byte[] pair2 = new byte[TOKEN_ID_LENGTH * 2]; + + System.arraycopy(o1, 0, pair1, 0, TOKEN_ID_LENGTH * 2); + System.arraycopy(o2, 0, pair2, 0, TOKEN_ID_LENGTH * 2); + + int pairResult = ByteArray.compareUnsigned(pair1, pair2); + if (pairResult != 0) { + return pairResult; + } + + //compare price + byte[] getSellTokenQuantity1 = new byte[8]; + byte[] getBuyTokenQuantity1 = new byte[8]; + + byte[] getSellTokenQuantity2 = new byte[8]; + byte[] getBuyTokenQuantity2 = new byte[8]; + + int longByteNum = 8; + + System.arraycopy(o1, TOKEN_ID_LENGTH + TOKEN_ID_LENGTH, + getSellTokenQuantity1, 0, longByteNum); + System.arraycopy(o1, TOKEN_ID_LENGTH + TOKEN_ID_LENGTH + longByteNum, + getBuyTokenQuantity1, 0, longByteNum); + + System.arraycopy(o2, TOKEN_ID_LENGTH + TOKEN_ID_LENGTH, + getSellTokenQuantity2, 0, longByteNum); + System.arraycopy(o2, TOKEN_ID_LENGTH + TOKEN_ID_LENGTH + longByteNum, + getBuyTokenQuantity2, 0, longByteNum); + + long sellTokenQuantity1 = ByteArray.toLong(getSellTokenQuantity1); + long buyTokenQuantity1 = ByteArray.toLong(getBuyTokenQuantity1); + long sellTokenQuantity2 = ByteArray.toLong(getSellTokenQuantity2); + long buyTokenQuantity2 = ByteArray.toLong(getBuyTokenQuantity2); + + if ((sellTokenQuantity1 == 0 || buyTokenQuantity1 == 0) + && (sellTokenQuantity2 == 0 || buyTokenQuantity2 == 0)) { + return 0; + } + + if (sellTokenQuantity1 == 0 || buyTokenQuantity1 == 0) { + return -1; + } + + if (sellTokenQuantity2 == 0 || buyTokenQuantity2 == 0) { + return 1; + } + + return comparePrice(sellTokenQuantity1, buyTokenQuantity1, + sellTokenQuantity2, buyTokenQuantity2); + + } + + /** + * Note: the params should be the same token pair, or you should change the order. + * All the quantity should be bigger than 0. + * */ + public static int comparePrice(long price1SellQuantity, long price1BuyQuantity, + long price2SellQuantity, long price2BuyQuantity) { + try { + return Long.compare(Math.multiplyExact(price1BuyQuantity, price2SellQuantity), + Math.multiplyExact(price2BuyQuantity, price1SellQuantity)); + + } catch (ArithmeticException ex) { + // do nothing here, because we will use BigInteger to compute again + } + + BigInteger price1BuyQuantityBI = BigInteger.valueOf(price1BuyQuantity); + BigInteger price1SellQuantityBI = BigInteger.valueOf(price1SellQuantity); + BigInteger price2BuyQuantityBI = BigInteger.valueOf(price2BuyQuantity); + BigInteger price2SellQuantityBI = BigInteger.valueOf(price2SellQuantity); + + return price1BuyQuantityBI.multiply(price2SellQuantityBI) + .compareTo(price2BuyQuantityBI.multiply(price1SellQuantityBI)); + } +} diff --git a/plugins/src/main/java/org/tron/plugins/utils/Sha256Hash.java b/plugins/src/main/java/org/tron/plugins/utils/Sha256Hash.java new file mode 100644 index 00000000000..5fe80601b66 --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/utils/Sha256Hash.java @@ -0,0 +1,202 @@ +package org.tron.plugins.utils; + +/* + * Copyright 2011 Google Inc. + * Copyright 2014 Andreas Schildbach + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.common.io.ByteStreams; +import com.google.common.primitives.Ints; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.Serializable; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import org.bouncycastle.crypto.digests.SM3Digest; + + +/** + * A Sha256Hash just wraps a byte[] so that equals and hashcode work correctly, allowing it to be + * used as keys in a map. It also checks that the length is correct and provides a bit more type + * safety. + */ +public class Sha256Hash implements Serializable, Comparable { + + public static final int LENGTH = 32; // bytes + + private final byte[] bytes; + + /** + * Use {@link #wrap(byte[])} instead. + */ + @Deprecated + public Sha256Hash(byte[] rawHashBytes) { + checkArgument(rawHashBytes.length == LENGTH); + this.bytes = rawHashBytes; + } + + /** + * Creates a new instance that wraps the given hash value. + * + * @param rawHashBytes the raw hash bytes to wrap + * @return a new instance + * @throws IllegalArgumentException if the given array length is not exactly 32 + */ + @SuppressWarnings("deprecation") // the constructor will be made private in the future + public static Sha256Hash wrap(byte[] rawHashBytes) { + return new Sha256Hash(rawHashBytes); + } + + + /** + * Creates a new instance containing the calculated (one-time) hash of the given bytes. + * + * @param contents the bytes on which the hash value is calculated + * @return a new instance containing the calculated (one-time) hash + */ + public static Sha256Hash of(boolean isSha256, byte[] contents) { + return wrap(hash(isSha256, contents)); + } + + /** + * Creates a new instance containing the calculated (one-time) hash of the given file's contents. + * The file contents are read fully into memory, so this method should only be used with small + * files. + * + * @param file the file on which the hash value is calculated + * @return a new instance containing the calculated (one-time) hash + * @throws IOException if an error occurs while reading the file + */ + public static Sha256Hash of(boolean isSha256, File file) throws IOException { + + try (FileInputStream in = new FileInputStream(file)) { + return of(isSha256, ByteStreams.toByteArray(in)); + } + } + + + /** + * Returns a new SHA-256 MessageDigest instance. This is a convenience method which wraps the + * checked exception that can never occur with a RuntimeException. + * + * @return a new SHA-256 MessageDigest instance + */ + public static MessageDigest newDigest() { + try { + return MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); // Can't happen. + } + } + + /** + * Returns a new SM3 MessageDigest instance. This is a convenience method which wraps the checked + * exception that can never occur with a RuntimeException. + * + * @return a new SM3 MessageDigest instance + */ + public static SM3Digest newSM3Digest() { + return new SM3Digest(); + } + + /** + * Calculates the SHA-256 hash of the given bytes. + * + * @param input the bytes to hash + * @return the hash (in big-endian order) + */ + public static byte[] hash(boolean isSha256, byte[] input) { + return hash(isSha256, input, 0, input.length); + } + + /** + * Calculates the SHA-256 hash of the given byte range. + * + * @param input the array containing the bytes to hash + * @param offset the offset within the array of the bytes to hash + * @param length the number of bytes to hash + * @return the hash (in big-endian order) + */ + public static byte[] hash(boolean isSha256, byte[] input, int offset, int length) { + if (isSha256) { + MessageDigest digest = newDigest(); + digest.update(input, offset, length); + return digest.digest(); + } else { + SM3Digest digest = newSM3Digest(); + digest.update(input, offset, length); + byte[] eHash = new byte[digest.getDigestSize()]; + digest.doFinal(eHash, 0); + return eHash; + } + + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Sha256Hash)) { + return false; + } + return Arrays.equals(bytes, ((Sha256Hash) o).bytes); + } + + @Override + public String toString() { + return ByteArray.toHexString(bytes); + } + + /** + * Returns the last four bytes of the wrapped hash. This should be unique enough to be a suitable + * hash code even for blocks, where the goal is to try and get the first bytes to be zeros (i.e. + * the value as a big integer lower than the target value). + */ + @Override + public int hashCode() { + // Use the last 4 bytes, not the first 4 which are often zeros in Bitcoin. + return Ints + .fromBytes(bytes[LENGTH - 4], bytes[LENGTH - 3], bytes[LENGTH - 2], bytes[LENGTH - 1]); + } + + /** + * Returns the internal byte array, without defensively copying. Therefore do NOT modify the + * returned array. + */ + public byte[] getBytes() { + return bytes; + } + + + @Override + public int compareTo(final Sha256Hash other) { + for (int i = LENGTH - 1; i >= 0; i--) { + final int thisByte = this.bytes[i] & 0xff; + final int otherByte = other.bytes[i] & 0xff; + if (thisByte > otherByte) { + return 1; + } + if (thisByte < otherByte) { + return -1; + } + } + return 0; + } +} diff --git a/plugins/src/main/java/org/tron/plugins/utils/db/DBInterface.java b/plugins/src/main/java/org/tron/plugins/utils/db/DBInterface.java new file mode 100644 index 00000000000..b0f7c58c587 --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/utils/db/DBInterface.java @@ -0,0 +1,21 @@ +package org.tron.plugins.utils.db; + +import java.io.Closeable; +import java.io.IOException; + + +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/plugins/src/main/java/org/tron/plugins/utils/db/DBIterator.java b/plugins/src/main/java/org/tron/plugins/utils/db/DBIterator.java new file mode 100644 index 00000000000..b5cbd705331 --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/utils/db/DBIterator.java @@ -0,0 +1,59 @@ +package org.tron.plugins.utils.db; + +import java.io.Closeable; +import java.util.Iterator; +import java.util.Map; + +public interface DBIterator extends Iterator>, Closeable { + + /** + * An iterator is either positioned at a key/value pair, or + * not valid. This method returns true iff the iterator is valid. + * + * @return an iterator is either positioned at a key/value pair + */ + boolean valid(); + + /** + * Position at the first key in the source that is at or past target. + * The iterator is valid() after this call iff the source contains + * an entry that comes at or past target. + * + * @param key target + */ + void seek(byte[] key); + + /** + * Position at the first key in the source. The iterator is valid() + * after this call iff the source is not empty. + */ + void seekToFirst(); + + /** + * Position at the last key in the source. The iterator is + * valid() after this call iff the source is not empty. + */ + void seekToLast(); + + boolean hasNext(); + + /** + * The underlying storage for + * the returned slice is valid only until the next modification of + * the iterator. + * REQUIRES: valid() + * + * @return the key for the current entry + */ + byte[] getKey(); + + /** + * The underlying storage for + * the returned slice is valid only until the next modification of + * the iterator. + * REQUIRES: valid() + * + * @return the value for the current entry + */ + byte[] getValue(); +} diff --git a/plugins/src/main/java/org/tron/plugins/utils/db/DbTool.java b/plugins/src/main/java/org/tron/plugins/utils/db/DbTool.java new file mode 100644 index 00000000000..6e8df4c59fb --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/utils/db/DbTool.java @@ -0,0 +1,187 @@ +package org.tron.plugins.utils.db; + +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.rocksdb.RocksDBException; +import org.tron.plugins.utils.DBUtils; +import org.tron.plugins.utils.FileUtils; + + +@Slf4j(topic = "tool") +public class DbTool { + + private static final String KEY_ENGINE = "ENGINE"; + private static final String ENGINE_FILE = "engine.properties"; + private static final String FILE_SEPARATOR = File.separator; + private static final String ROCKSDB = "ROCKSDB"; + + private static final Map dbMap = Maps.newConcurrentMap(); + + 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 leveldb error + * @throws RocksDBException rocksdb error + */ + public static DBInterface getDB(String sourceDir, String dbName) + throws IOException, RocksDBException { + DbType type = getDbType(sourceDir, dbName); + return getDB(sourceDir, dbName, type); + } + + /** + * Get the DB object according to the specified path, keep engine same with source. + * + * @param sourceDir read engine + * @param destDir to be open parent path + * @param dbName database name + * + * @return db object + * + * @throws IOException leveldb error + * @throws RocksDBException rocksdb error + */ + public static DBInterface getDB(String sourceDir, String destDir, String dbName) + throws IOException, RocksDBException { + DbType type = getDbType(sourceDir, dbName); + return getDB(destDir, dbName, type); + } + + /** + * Get the DB object according to the specified path and engine. + * + * @param sourceDir to be open parent path + * @param dbName database name + * @param type engine + * @return db object + * @throws IOException leveldb error + * @throws RocksDBException rocksdb error + */ + public static DBInterface getDB(String sourceDir, String dbName, DbType type) + throws IOException, RocksDBException { + Path path = Paths.get(sourceDir, dbName); + if (dbMap.containsKey(path.toString())) { + return dbMap.get(path.toString()); + } + 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; + } + + /** + * Get the DB object according to the specified path, + * not managed by dbMap. + * + * @param sourceDir the parent path of db + * @param dbName db dir name + * + * @return db object + * + * @throws IOException leveldb error + * @throws RocksDBException rocksdb error + */ + public static DBInterface getDB(Path sourceDir, String dbName) + throws IOException, RocksDBException { + Path path = Paths.get(sourceDir.toString(), dbName); + DbType type = getDbType(sourceDir.toString(), dbName); + switch (type) { + case LevelDB: + return openLevelDb(path); + case RocksDB: + return openRocksDb(path); + default: + throw new IllegalStateException("Unexpected value: " + type); + } + } + + /** + * 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 = FileUtils.readProperty(engineFile, KEY_ENGINE); + if (engine.equalsIgnoreCase(ROCKSDB)) { + return DbType.RocksDB; + } else { + return DbType.LevelDB; + } + } + + private static LevelDBImpl openLevelDb(Path db) throws IOException { + return new LevelDBImpl(DBUtils.newLevelDb(db)); + } + + private static RocksDBImpl openRocksDb(Path db) throws RocksDBException { + return new RocksDBImpl(DBUtils.newRocksDb(db)); + } + + +} diff --git a/plugins/src/main/java/org/tron/plugins/utils/db/LevelDBImpl.java b/plugins/src/main/java/org/tron/plugins/utils/db/LevelDBImpl.java new file mode 100644 index 00000000000..3a89e77af40 --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/utils/db/LevelDBImpl.java @@ -0,0 +1,46 @@ +package org.tron.plugins.utils.db; + +import com.google.common.collect.Streams; +import java.io.IOException; +import org.iq80.leveldb.DB; +import org.iq80.leveldb.ReadOptions; + + +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(new ReadOptions().fillCache(false))); + } + + @Override + public long size() { + return Streams.stream(leveldb.iterator()).count(); + } + + @Override + public void close() throws IOException { + leveldb.close(); + } +} diff --git a/plugins/src/main/java/org/tron/plugins/utils/db/LevelDBIterator.java b/plugins/src/main/java/org/tron/plugins/utils/db/LevelDBIterator.java new file mode 100644 index 00000000000..b5f0028dd6f --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/utils/db/LevelDBIterator.java @@ -0,0 +1,58 @@ +package org.tron.plugins.utils.db; + +import java.io.IOException; +import java.util.Map; + +public class LevelDBIterator implements DBIterator { + + private final org.iq80.leveldb.DBIterator iterator; + + public LevelDBIterator(org.iq80.leveldb.DBIterator iterator) { + this.iterator = iterator; + } + + @Override + public boolean valid() { + return iterator.hasNext(); + } + + @Override + public void seek(byte[] key) { + iterator.seek(key); + } + + @Override + public void seekToFirst() { + iterator.seekToFirst(); + } + + @Override + public void seekToLast() { + iterator.seekToLast(); + } + + @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 Map.Entry next() { + return iterator.next(); + } + + @Override + public void close() throws IOException { + iterator.close(); + } +} diff --git a/plugins/src/main/java/org/tron/plugins/utils/db/RockDBIterator.java b/plugins/src/main/java/org/tron/plugins/utils/db/RockDBIterator.java new file mode 100644 index 00000000000..d3e17d9173f --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/utils/db/RockDBIterator.java @@ -0,0 +1,77 @@ +package org.tron.plugins.utils.db; + +import java.io.IOException; +import java.util.Map; +import org.rocksdb.RocksIterator; + +public class RockDBIterator implements DBIterator { + + private final RocksIterator iterator; + + public RockDBIterator(RocksIterator iterator) { + this.iterator = iterator; + } + + @Override + public boolean valid() { + return iterator.isValid(); + } + + @Override + public void seek(byte[] key) { + iterator.seek(key); + } + + @Override + public void seekToFirst() { + iterator.seekToFirst(); + } + + @Override + public void seekToLast() { + iterator.seekToLast(); + } + + @Override + public boolean hasNext() { + return iterator.isValid(); + } + + @Override + public byte[] getKey() { + return iterator.key(); + } + + @Override + public byte[] getValue() { + return iterator.value(); + } + + @Override + public Map.Entry next() { + byte[] key = iterator.key(); + byte[] value = iterator.value(); + iterator.next(); + return new Map.Entry() { + @Override + public byte[] getKey() { + return key; + } + + @Override + public byte[] getValue() { + return value; + } + + @Override + public byte[] setValue(byte[] value) { + throw new UnsupportedOperationException(); + } + }; + } + + @Override + public void close() throws IOException { + iterator.close(); + } +} diff --git a/plugins/src/main/java/org/tron/plugins/utils/db/RocksDBImpl.java b/plugins/src/main/java/org/tron/plugins/utils/db/RocksDBImpl.java new file mode 100644 index 00000000000..88b25b0413f --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/utils/db/RocksDBImpl.java @@ -0,0 +1,64 @@ +package org.tron.plugins.utils.db; + +import java.io.IOException; +import org.rocksdb.RocksDBException; +import org.rocksdb.RocksIterator; + +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( + new org.rocksdb.ReadOptions().setFillCache(false))); + } + + @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/plugins/src/main/resources/logback.xml b/plugins/src/main/resources/logback.xml index 5e632f0d424..6c415042e38 100644 --- a/plugins/src/main/resources/logback.xml +++ b/plugins/src/main/resources/logback.xml @@ -16,11 +16,11 @@ - ./logs/archive.log + ./logs/toolkit.log - ./logs/archive-%d{yyyy-MM-dd}.%i.log.gz + ./logs/toolkit-%d{yyyy-MM-dd}.%i.log.gz 500MB 10 @@ -49,6 +49,9 @@ + + + diff --git a/plugins/src/test/java/org/tron/plugins/DbConvertTest.java b/plugins/src/test/java/org/tron/plugins/DbConvertTest.java new file mode 100644 index 00000000000..91996815c01 --- /dev/null +++ b/plugins/src/test/java/org/tron/plugins/DbConvertTest.java @@ -0,0 +1,110 @@ +package org.tron.plugins; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.UUID; +import org.iq80.leveldb.DB; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.tron.plugins.utils.ByteArray; +import org.tron.plugins.utils.DBUtils; +import org.tron.plugins.utils.FileUtils; +import org.tron.plugins.utils.MarketUtils; +import picocli.CommandLine; + +public class DbConvertTest { + + + private static final String INPUT_DIRECTORY = "output-directory/convert-database/"; + private static final String OUTPUT_DIRECTORY = "output-directory/convert-database-dest/"; + private static final String ACCOUNT = "account"; + private static final String MARKET = DBUtils.MARKET_PAIR_PRICE_TO_ORDER; + CommandLine cli = new CommandLine(new Toolkit()); + + + @BeforeClass + public static void init() throws IOException { + if (new File(INPUT_DIRECTORY).mkdirs()) { + initDB(new File(INPUT_DIRECTORY,ACCOUNT)); + initDB(new File(INPUT_DIRECTORY,MARKET)); + } + } + + private static void initDB(File file) throws IOException { + try (DB db = DBUtils.newLevelDb(file.toPath())) { + if (MARKET.equalsIgnoreCase(file.getName())) { + byte[] sellTokenID1 = ByteArray.fromString("100"); + byte[] buyTokenID1 = ByteArray.fromString("200"); + byte[] pairPriceKey1 = MarketUtils.createPairPriceKey( + sellTokenID1, + buyTokenID1, + 1000L, + 2001L + ); + byte[] pairPriceKey2 = MarketUtils.createPairPriceKey( + sellTokenID1, + buyTokenID1, + 1000L, + 2002L + ); + byte[] pairPriceKey3 = MarketUtils.createPairPriceKey( + sellTokenID1, + buyTokenID1, + 1000L, + 2003L + ); + + + //Use out-of-order insertion,key in store should be 1,2,3 + db.put(pairPriceKey1, "1".getBytes(StandardCharsets.UTF_8)); + db.put(pairPriceKey2, "2".getBytes(StandardCharsets.UTF_8)); + db.put(pairPriceKey3, "3".getBytes(StandardCharsets.UTF_8)); + } else { + for (int i = 0; i < 100; i++) { + byte[] bytes = UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8); + db.put(bytes, bytes); + } + } + } + } + + @AfterClass + public static void destroy() { + FileUtils.deleteDir(new File(INPUT_DIRECTORY)); + FileUtils.deleteDir(new File(OUTPUT_DIRECTORY)); + } + + @Test + public void testRun() { + String[] args = new String[] { "db", "convert", INPUT_DIRECTORY, OUTPUT_DIRECTORY }; + Assert.assertEquals(0, cli.execute(args)); + } + + @Test + public void testHelp() { + String[] args = new String[] {"db", "convert", "-h"}; + CommandLine cli = new CommandLine(new Toolkit()); + Assert.assertEquals(0, cli.execute(args)); + } + + @Test + public void testNotExist() { + String[] args = new String[] {"db", "convert", + OUTPUT_DIRECTORY + File.separator + UUID.randomUUID(), + OUTPUT_DIRECTORY}; + Assert.assertEquals(404, cli.execute(args)); + } + + @Test + public void testEmpty() { + File file = new File(OUTPUT_DIRECTORY + File.separator + UUID.randomUUID()); + file.mkdirs(); + file.deleteOnExit(); + String[] args = new String[] {"db", "convert", file.toString(), OUTPUT_DIRECTORY}; + Assert.assertEquals(0, cli.execute(args)); + } + +} diff --git a/plugins/src/test/java/org/tron/plugins/DbMoveTest.java b/plugins/src/test/java/org/tron/plugins/DbMoveTest.java index 6bbac663c2c..c1bc6b470fc 100644 --- a/plugins/src/test/java/org/tron/plugins/DbMoveTest.java +++ b/plugins/src/test/java/org/tron/plugins/DbMoveTest.java @@ -2,25 +2,17 @@ import static org.iq80.leveldb.impl.Iq80DBFactory.factory; -import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; import java.net.URL; -import java.nio.charset.StandardCharsets; import java.nio.file.Paths; -import java.util.Properties; import java.util.UUID; import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.tron.plugins.utils.FileUtils; import picocli.CommandLine; @Slf4j @@ -41,15 +33,15 @@ public class DbMoveTest { public static void init() throws IOException { File file = new File(OUTPUT_DIRECTORY_DATABASE, ACCOUNT); factory.open(file, ArchiveManifest.newDefaultLevelDbOptions()).close(); - writeProperty(file + File.separator + ENGINE_FILE, ENGINE, LEVELDB); + FileUtils.writeProperty(file + File.separator + ENGINE_FILE, ENGINE, LEVELDB); file = new File(OUTPUT_DIRECTORY_DATABASE, MARKET); factory.open(file, ArchiveManifest.newDefaultLevelDbOptions()).close(); - writeProperty(file + File.separator + ENGINE_FILE, ENGINE, LEVELDB); + FileUtils.writeProperty(file + File.separator + ENGINE_FILE, ENGINE, LEVELDB); file = new File(OUTPUT_DIRECTORY_DATABASE, TRANS); factory.open(file, ArchiveManifest.newDefaultLevelDbOptions()).close(); - writeProperty(file + File.separator + ENGINE_FILE, ENGINE, LEVELDB); + FileUtils.writeProperty(file + File.separator + ENGINE_FILE, ENGINE, LEVELDB); } @@ -58,26 +50,6 @@ public static void destroy() { deleteDir(new File(OUTPUT_DIRECTORY)); } - private static void writeProperty(String filename, String key, String value) throws IOException { - File file = new File(filename); - if (!file.exists()) { - file.createNewFile(); - } - - try (FileInputStream fis = new FileInputStream(file); - OutputStream out = new FileOutputStream(file); - BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out, - StandardCharsets.UTF_8))) { - BufferedReader bf = new BufferedReader(new InputStreamReader(fis, StandardCharsets.UTF_8)); - Properties properties = new Properties(); - properties.load(bf); - properties.setProperty(key, value); - properties.store(bw, "Generated by the application. PLEASE DO NOT EDIT! "); - } catch (Exception e) { - logger.warn("{}", e); - } - } - /** * delete directory. */ @@ -122,7 +94,7 @@ public void testDuplicate() { @Test public void testHelp() { - String[] args = new String[] {}; + String[] args = new String[] {"db", "mv", "-h"}; CommandLine cli = new CommandLine(new Toolkit()); Assert.assertEquals(0, cli.execute(args)); } From 4f9a7e9826020203e6345691f09352f6577d3934 Mon Sep 17 00:00:00 2001 From: morgan Date: Wed, 9 Nov 2022 14:32:16 +0800 Subject: [PATCH 0452/1197] feat(db): print db internal log 1.print db internal log --- .../common/storage/leveldb/LevelDbDataSourceImpl.java | 10 +++++++--- .../common/storage/rocksdb/RocksDbDataSourceImpl.java | 10 ++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java index 054648eb467..16fd2b88a5e 100644 --- a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java @@ -44,10 +44,12 @@ import org.iq80.leveldb.CompressionType; import org.iq80.leveldb.DB; import org.iq80.leveldb.DBIterator; +import org.iq80.leveldb.Logger; import org.iq80.leveldb.Options; import org.iq80.leveldb.ReadOptions; import org.iq80.leveldb.WriteBatch; import org.iq80.leveldb.WriteOptions; +import org.slf4j.LoggerFactory; import org.tron.common.parameter.CommonParameter; import org.tron.common.storage.WriteOptionsWrapper; import org.tron.common.storage.metric.DbStat; @@ -71,6 +73,7 @@ public class LevelDbDataSourceImpl extends DbStat implements DbSourceInter Date: Mon, 17 Oct 2022 15:55:44 +0800 Subject: [PATCH 0453/1197] refactor(db): remove useless revokingDB 1.remove useless revokingDB --- .../tron/core/db/AbstractRevokingStore.java | 477 ------------------ .../java/org/tron/core/db/RevokingStore.java | 25 - .../tron/core/db/TronStoreWithRevoking.java | 67 +-- .../org/tron/core/db2/common/TxCacheDB.java | 37 +- .../core/RevokingDBWithCachingOldValue.java | 186 ------- .../common/parameter/CommonParameter.java | 2 - .../org/tron/core/config/args/Storage.java | 11 - .../org/tron/core/config/DefaultConfig.java | 32 +- .../java/org/tron/core/config/args/Args.java | 10 - .../core/db/backup/NeedBeanCondition.java | 5 +- .../tron/core/services/NodeInfoService.java | 2 +- .../main/java/org/tron/program/FullNode.java | 53 +- .../src/main/resources/config-localtest.conf | 3 +- framework/src/main/resources/config.conf | 7 +- ...riceToOrderStoreWithCacheOldValueTest.java | 188 ------- .../db2/RevokingDbWithCacheOldValueTest.java | 279 ---------- .../src/test/resources/config-localtest.conf | 3 +- .../test/resources/config-test-dbbackup.conf | 1 - .../resources/config-test-storagetest.conf | 1 - framework/src/test/resources/config-test.conf | 1 - .../src/test/resources/config-duplicate.conf | 1 - plugins/src/test/resources/config.conf | 1 - 22 files changed, 74 insertions(+), 1318 deletions(-) delete mode 100644 chainbase/src/main/java/org/tron/core/db/AbstractRevokingStore.java delete mode 100644 chainbase/src/main/java/org/tron/core/db/RevokingStore.java delete mode 100644 chainbase/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingOldValue.java delete mode 100644 framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreWithCacheOldValueTest.java delete mode 100644 framework/src/test/java/org/tron/core/db2/RevokingDbWithCacheOldValueTest.java diff --git a/chainbase/src/main/java/org/tron/core/db/AbstractRevokingStore.java b/chainbase/src/main/java/org/tron/core/db/AbstractRevokingStore.java deleted file mode 100644 index 725456ce39e..00000000000 --- a/chainbase/src/main/java/org/tron/core/db/AbstractRevokingStore.java +++ /dev/null @@ -1,477 +0,0 @@ -package org.tron.core.db; - -import static org.tron.core.db2.core.SnapshotManager.simpleDecode; - -import com.google.common.collect.Maps; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Deque; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; -import lombok.AllArgsConstructor; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.ToString; -import lombok.extern.slf4j.Slf4j; -import org.iq80.leveldb.Options; -import org.iq80.leveldb.WriteOptions; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.storage.WriteOptionsWrapper; -import org.tron.common.storage.leveldb.LevelDbDataSourceImpl; -import org.tron.common.utils.FileUtil; -import org.tron.common.utils.StorageUtils; -import org.tron.common.utils.Utils; -import org.tron.core.db.common.SourceInter; -import org.tron.core.db2.ISession; -import org.tron.core.db2.common.IRevokingDB; -import org.tron.core.db2.core.Chainbase; -import org.tron.core.db2.core.RevokingDBWithCachingOldValue; -import org.tron.core.exception.RevokingStoreIllegalStateException; - -@Slf4j(topic = "DB") -@Getter // only for unit test -public abstract class AbstractRevokingStore implements RevokingDatabase { - - private static final int DEFAULT_STACK_MAX_SIZE = 256; - private static String ACTIVE_DIALOG_POSITIVE = "activeDialog has to be greater than 0"; - private Deque stack = new LinkedList<>(); - private boolean disabled = true; - private int activeDialog = 0; - private AtomicInteger maxSize = new AtomicInteger(DEFAULT_STACK_MAX_SIZE); - private WriteOptionsWrapper writeOptionsWrapper = WriteOptionsWrapper.getInstance() - .sync(CommonParameter.getInstance().getStorage().isDbSync()); - private List dbs = new ArrayList<>(); - - @Override - public ISession buildSession() { - return buildSession(false); - } - - @Override - public synchronized ISession buildSession(boolean forceEnable) { - if (disabled && !forceEnable) { - return new Dialog(this); - } - - boolean disableOnExit = disabled && forceEnable; - if (forceEnable) { - disabled = false; - } - - while (stack.size() > maxSize.get()) { - stack.poll(); - } - - stack.add(new RevokingState()); - ++activeDialog; - return new Dialog(this, disableOnExit); - } - - @Override - public void setCursor(Chainbase.Cursor cursor) { - - } - - @Override - public void setCursor(Chainbase.Cursor cursor, long offset) { - - } - - @Override - public synchronized void check() { - LevelDbDataSourceImpl check = - new LevelDbDataSourceImpl(StorageUtils.getOutputDirectoryByDbName("tmp"), "tmp", - new Options(), - new WriteOptions()); - check.initDB(); - - if (!check.allKeys().isEmpty()) { - Map dbMap = dbs.stream() - .map(db -> Maps.immutableEntry(db.getDBName(), db)) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - for (Map.Entry e : check) { - byte[] key = e.getKey(); - byte[] value = e.getValue(); - String db = simpleDecode(key); - if (dbMap.get(db) == null) { - continue; - } - byte[] realKey = Arrays.copyOfRange(key, db.getBytes().length + 4, key.length); - - byte[] realValue = value.length == 1 ? null : Arrays.copyOfRange(value, 1, value.length); - if (realValue != null) { - dbMap.get(db).putData(realKey, realValue); - } else { - dbMap.get(db).deleteData(realKey); - } - } - } - - check.closeDB(); - FileUtil.recursiveDelete(check.getDbPath().toString()); - } - - @Override - public void add(IRevokingDB revokingDB) { - dbs.add(((RevokingDBWithCachingOldValue) revokingDB).getDbSource()); - } - - public synchronized void onCreate(RevokingTuple tuple, byte[] value) { - if (disabled) { - return; - } - - addIfEmpty(); - RevokingState state = stack.peekLast(); - state.newIds.add(tuple); - } - - public synchronized void onModify(RevokingTuple tuple, byte[] value) { - if (disabled) { - return; - } - - addIfEmpty(); - RevokingState state = stack.peekLast(); - if (state.newIds.contains(tuple) || state.oldValues.containsKey(tuple)) { - return; - } - - state.oldValues.put(tuple, Utils.clone(value)); - } - - public synchronized void onRemove(RevokingTuple tuple, byte[] value) { - if (disabled) { - return; - } - - addIfEmpty(); - RevokingState state = stack.peekLast(); - if (state.newIds.contains(tuple)) { - state.newIds.remove(tuple); - return; - } - - if (state.oldValues.containsKey(tuple)) { - state.removed.put(tuple, state.oldValues.get(tuple)); - state.oldValues.remove(tuple); - return; - } - - if (state.removed.containsKey(tuple)) { - return; - } - - state.removed.put(tuple, Utils.clone(value)); - } - - @Override - public synchronized void merge() { - if (activeDialog <= 0) { - throw new RevokingStoreIllegalStateException(ACTIVE_DIALOG_POSITIVE); - } - - if (activeDialog == 1 && stack.size() == 1) { - stack.pollLast(); - --activeDialog; - return; - } - - if (stack.size() < 2) { - return; - } - - RevokingState state = stack.peekLast(); - @SuppressWarnings("unchecked") - List list = (List) stack; - RevokingState prevState = list.get(stack.size() - 2); - - state.oldValues.entrySet().stream() - .filter(e -> !prevState.newIds.contains(e.getKey())) - .filter(e -> !prevState.oldValues.containsKey(e.getKey())) - .forEach(e -> prevState.oldValues.put(e.getKey(), e.getValue())); - - prevState.newIds.addAll(state.newIds); - - state.removed.entrySet().stream() - .filter(e -> { - boolean has = prevState.newIds.contains(e.getKey()); - if (has) { - prevState.newIds.remove(e.getKey()); - } - - return !has; - }) - .filter(e -> { - boolean has = prevState.oldValues.containsKey(e.getKey()); - if (has) { - prevState.removed.put(e.getKey(), prevState.oldValues.get(e.getKey())); - prevState.oldValues.remove(e.getKey()); - } - - return !has; - }) - .forEach(e -> prevState.removed.put(e.getKey(), e.getValue())); - - stack.pollLast(); - --activeDialog; - } - - @Override - public synchronized void revoke() { - if (disabled) { - return; - } - - if (activeDialog <= 0) { - throw new RevokingStoreIllegalStateException(ACTIVE_DIALOG_POSITIVE); - } - - disabled = true; - - try { - RevokingState state = stack.peekLast(); - if (Objects.isNull(state)) { - return; - } - - state.oldValues.forEach((k, v) -> k.database.putData(k.key, v)); - state.newIds.forEach(e -> e.database.deleteData(e.key)); - state.removed.forEach((k, v) -> k.database.putData(k.key, v)); - stack.pollLast(); - } finally { - disabled = false; - } - --activeDialog; - } - - @Override - public synchronized void commit() { - if (activeDialog <= 0) { - throw new RevokingStoreIllegalStateException(ACTIVE_DIALOG_POSITIVE); - } - - --activeDialog; - } - - @Override - public synchronized void pop() { - prune(writeOptionsWrapper); - } - - @Override - public synchronized void fastPop() { - prune(WriteOptionsWrapper.getInstance()); - } - - private synchronized void prune(WriteOptionsWrapper optionsWrapper) { - if (activeDialog != 0) { - throw new RevokingStoreIllegalStateException("activeDialog has to be equal 0"); - } - - if (stack.isEmpty()) { - throw new RevokingStoreIllegalStateException("stack is empty"); - } - - disabled = true; - - try { - RevokingState state = stack.peekLast(); - state.oldValues.forEach((k, v) -> k.database.putData(k.key, v)); - state.newIds.forEach(e -> e.database.deleteData(e.key)); - state.removed.forEach((k, v) -> k.database.putData(k.key, v)); - stack.pollLast(); - } finally { - disabled = false; - } - } - - @Override - public synchronized void enable() { - disabled = false; - } - - @Override - public synchronized void disable() { - disabled = true; - } - - private void addIfEmpty() { - if (stack.isEmpty()) { - stack.add(new RevokingState()); - } - } - - @Override - public synchronized int size() { - return stack.size(); - } - - public int getMaxSize() { - return maxSize.get(); - } - - @Override - public void setMaxSize(int maxSize) { - this.maxSize.set(maxSize); - } - - @Override - public void setMaxFlushCount(int maxFlushCount) { - } - - public synchronized void shutdown() { - System.err.println("******** begin to pop revokingDb ********"); - System.err.println("******** before revokingDb size:" + size()); - try { - disable(); - while (true) { - try { - commit(); - } catch (RevokingStoreIllegalStateException e) { - break; - } - if (activeDialog <= 0) { - break; - } - } - - while (true) { - try { - pop(); - } catch (RevokingStoreIllegalStateException e) { - break; - } - if (activeDialog != 0) { - break; - } - if (stack.isEmpty()) { - break; - } - } - } catch (Exception e) { - System.err.println("******** failed to pop revokingStore. " + e); - } finally { - System.err.println("******** after revokingStore size:" + stack.size()); - System.err.println("******** after revokingStore contains:" + stack); - System.err.println("******** end to pop revokingStore ********"); - } - } - - @Slf4j(topic = "DB") - @Getter // only for unit test - public static class Dialog implements ISession { - - private RevokingDatabase revokingDatabase; - private boolean applyRevoking = true; - private boolean disableOnExit = false; - - public Dialog(Dialog dialog) { - this.revokingDatabase = dialog.revokingDatabase; - this.applyRevoking = dialog.applyRevoking; - dialog.applyRevoking = false; - } - - public Dialog(RevokingDatabase revokingDatabase) { - this(revokingDatabase, false); - } - - public Dialog(RevokingDatabase revokingDatabase, boolean disableOnExit) { - this.revokingDatabase = revokingDatabase; - this.disableOnExit = disableOnExit; - } - - @Override - public void commit() { - applyRevoking = false; - revokingDatabase.commit(); - } - - @Override - public void revoke() { - if (applyRevoking) { - revokingDatabase.revoke(); - } - - applyRevoking = false; - } - - @Override - public void merge() { - if (applyRevoking) { - revokingDatabase.merge(); - } - - applyRevoking = false; - } - - void copy(Dialog dialog) { - if (this.equals(dialog)) { - return; - } - - if (applyRevoking) { - revokingDatabase.revoke(); - } - applyRevoking = dialog.applyRevoking; - dialog.applyRevoking = false; - } - - @Override - public void destroy() { - try { - if (applyRevoking) { - revokingDatabase.revoke(); - } - } catch (Exception e) { - logger.error("revoke database error.", e); - } - if (disableOnExit) { - revokingDatabase.disable(); - } - } - - @Override - public void close() { - try { - if (applyRevoking) { - revokingDatabase.revoke(); - } - } catch (Exception e) { - logger.error("revoke database error.", e); - throw new RevokingStoreIllegalStateException(e); - } - if (disableOnExit) { - revokingDatabase.disable(); - } - } - } - - @ToString - @Getter // only for unit test - static class RevokingState { - - private Map oldValues = new HashMap<>(); - private Set newIds = new HashSet<>(); - private Map removed = new HashMap<>(); - } - - @AllArgsConstructor - @EqualsAndHashCode - @Getter - @ToString - public static class RevokingTuple { - - private SourceInter database; - private byte[] key; - } - -} diff --git a/chainbase/src/main/java/org/tron/core/db/RevokingStore.java b/chainbase/src/main/java/org/tron/core/db/RevokingStore.java deleted file mode 100644 index 7b641cf6bc3..00000000000 --- a/chainbase/src/main/java/org/tron/core/db/RevokingStore.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.tron.core.db; - -public class RevokingStore extends AbstractRevokingStore { - - public RevokingStore() { - } - - public static RevokingStore getInstance() { - return RevokingEnum.INSTANCE.getInstance(); - } - - private enum RevokingEnum { - INSTANCE; - - private RevokingStore instance; - - RevokingEnum() { - instance = new RevokingStore(); - } - - private RevokingStore getInstance() { - return instance; - } - } -} diff --git a/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java b/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java index be005a1da76..2dcd370a656 100644 --- a/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java +++ b/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java @@ -15,7 +15,6 @@ import javax.annotation.PostConstruct; import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import org.iq80.leveldb.Options; import org.iq80.leveldb.WriteOptions; import org.rocksdb.DirectComparator; import org.springframework.beans.factory.annotation.Autowired; @@ -33,7 +32,6 @@ import org.tron.core.db2.common.WrappedByteArray; import org.tron.core.db2.core.Chainbase; import org.tron.core.db2.core.ITronChainBase; -import org.tron.core.db2.core.RevokingDBWithCachingOldValue; import org.tron.core.db2.core.SnapshotRoot; import org.tron.core.exception.BadItemException; import org.tron.core.exception.ItemNotFoundException; @@ -56,35 +54,26 @@ public abstract class TronStoreWithRevoking implements I private DB db; protected TronStoreWithRevoking(String dbName) { - int dbVersion = CommonParameter.getInstance().getStorage().getDbVersion(); String dbEngine = CommonParameter.getInstance().getStorage().getDbEngine(); - if (dbVersion == 1) { - this.revokingDB = new RevokingDBWithCachingOldValue(dbName, - getOptionsByDbNameForLevelDB(dbName)); - } else if (dbVersion == 2) { - if ("LEVELDB".equals(dbEngine.toUpperCase())) { - this.db = new LevelDB( - new LevelDbDataSourceImpl(StorageUtils.getOutputDirectoryByDbName(dbName), - dbName, - getOptionsByDbNameForLevelDB(dbName), - new WriteOptions().sync(CommonParameter.getInstance() - .getStorage().isDbSync()))); - } else if ("ROCKSDB".equals(dbEngine.toUpperCase())) { - String parentPath = Paths - .get(StorageUtils.getOutputDirectoryByDbName(dbName), CommonParameter - .getInstance().getStorage().getDbDirectory()).toString(); - this.db = new RocksDB( - new RocksDbDataSourceImpl(parentPath, - dbName, CommonParameter.getInstance() - .getRocksDBCustomSettings(), getDirectComparator())); - } else { - throw new RuntimeException(String.format("db engine %s is error", dbEngine)); - } - this.revokingDB = new Chainbase(new SnapshotRoot(this.db)); - + if ("LEVELDB".equals(dbEngine.toUpperCase())) { + this.db = new LevelDB( + new LevelDbDataSourceImpl(StorageUtils.getOutputDirectoryByDbName(dbName), + dbName, + getOptionsByDbNameForLevelDB(dbName), + new WriteOptions().sync(CommonParameter.getInstance() + .getStorage().isDbSync()))); + } else if ("ROCKSDB".equals(dbEngine.toUpperCase())) { + String parentPath = Paths + .get(StorageUtils.getOutputDirectoryByDbName(dbName), CommonParameter + .getInstance().getStorage().getDbDirectory()).toString(); + this.db = new RocksDB( + new RocksDbDataSourceImpl(parentPath, + dbName, CommonParameter.getInstance() + .getRocksDBCustomSettings(), getDirectComparator())); } else { - throw new RuntimeException(String.format("db version %d is error", dbVersion)); + throw new RuntimeException(String.format("db engine %s is error", dbEngine)); } + this.revokingDB = new Chainbase(new SnapshotRoot(this.db)); } protected org.iq80.leveldb.Options getOptionsByDbNameForLevelDB(String dbName) { @@ -96,26 +85,8 @@ protected DirectComparator getDirectComparator() { } protected TronStoreWithRevoking(DB db) { - int dbVersion = CommonParameter.getInstance().getStorage().getDbVersion(); - if (dbVersion == 2) { - this.db = db; - this.revokingDB = new Chainbase(new SnapshotRoot(db)); - } else { - throw new RuntimeException(String.format("db version is only 2, actual: %d", dbVersion)); - } - } - - // only for test - protected TronStoreWithRevoking(String dbName, RevokingDatabase revokingDatabase) { - this.revokingDB = new RevokingDBWithCachingOldValue(dbName, - (AbstractRevokingStore) revokingDatabase); - } - - // only for test - protected TronStoreWithRevoking(String dbName, Options options, - RevokingDatabase revokingDatabase) { - this.revokingDB = new RevokingDBWithCachingOldValue(dbName, options, - (AbstractRevokingStore) revokingDatabase); + this.db = db; + this.revokingDB = new Chainbase(new SnapshotRoot(db)); } @Override diff --git a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java index f574520b222..63e020ea1d6 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java @@ -62,29 +62,24 @@ public TxCacheDB(String name, RecentTransactionStore recentTransactionStore) { this.TRANSACTION_COUNT = CommonParameter.getInstance().getStorage().getEstimatedBlockTransactions(); this.recentTransactionStore = recentTransactionStore; - int dbVersion = CommonParameter.getInstance().getStorage().getDbVersion(); String dbEngine = CommonParameter.getInstance().getStorage().getDbEngine(); - if (dbVersion == 2) { - if ("LEVELDB".equals(dbEngine.toUpperCase())) { - this.persistentStore = new LevelDB( - new LevelDbDataSourceImpl(StorageUtils.getOutputDirectoryByDbName(name), - name, StorageUtils.getOptionsByDbName(name), - new WriteOptions().sync(CommonParameter.getInstance() - .getStorage().isDbSync()))); - } else if ("ROCKSDB".equals(dbEngine.toUpperCase())) { - String parentPath = Paths - .get(StorageUtils.getOutputDirectoryByDbName(name), CommonParameter - .getInstance().getStorage().getDbDirectory()).toString(); - - this.persistentStore = new RocksDB( - new RocksDbDataSourceImpl(parentPath, - name, CommonParameter.getInstance() - .getRocksDBCustomSettings())); - } else { - throw new RuntimeException(String.format("db type: %s is not supported", dbEngine)); - } + if ("LEVELDB".equals(dbEngine.toUpperCase())) { + this.persistentStore = new LevelDB( + new LevelDbDataSourceImpl(StorageUtils.getOutputDirectoryByDbName(name), + name, StorageUtils.getOptionsByDbName(name), + new WriteOptions().sync(CommonParameter.getInstance() + .getStorage().isDbSync()))); + } else if ("ROCKSDB".equals(dbEngine.toUpperCase())) { + String parentPath = Paths + .get(StorageUtils.getOutputDirectoryByDbName(name), CommonParameter + .getInstance().getStorage().getDbDirectory()).toString(); + + this.persistentStore = new RocksDB( + new RocksDbDataSourceImpl(parentPath, + name, CommonParameter.getInstance() + .getRocksDBCustomSettings())); } else { - throw new RuntimeException(String.format("db version: %d is not supported", dbVersion)); + throw new RuntimeException(String.format("db type: %s is not supported", dbEngine)); } this.bloomFilters[0] = BloomFilter.create(Funnels.byteArrayFunnel(), MAX_BLOCK_SIZE * TRANSACTION_COUNT); diff --git a/chainbase/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingOldValue.java b/chainbase/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingOldValue.java deleted file mode 100644 index ce6fdec9a07..00000000000 --- a/chainbase/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingOldValue.java +++ /dev/null @@ -1,186 +0,0 @@ -package org.tron.core.db2.core; - -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.ArrayUtils; -import org.iq80.leveldb.Options; -import org.iq80.leveldb.WriteOptions; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.storage.leveldb.LevelDbDataSourceImpl; -import org.tron.common.utils.StorageUtils; -import org.tron.core.db.AbstractRevokingStore; -import org.tron.core.db.RevokingStore; -import org.tron.core.db2.common.IRevokingDB; -import org.tron.core.db2.common.WrappedByteArray; -import org.tron.core.db2.core.Chainbase.Cursor; -import org.tron.core.exception.ItemNotFoundException; - -@Slf4j -public class RevokingDBWithCachingOldValue implements IRevokingDB { - - private AbstractRevokingStore revokingDatabase; - @Getter - private LevelDbDataSourceImpl dbSource; - - public RevokingDBWithCachingOldValue(String dbName) { - this(dbName, RevokingStore.getInstance()); - } - - // add for user defined option, ex: comparator - public RevokingDBWithCachingOldValue(String dbName, Options options) { - this(dbName, options, RevokingStore.getInstance()); - } - - // set public only for unit test - public RevokingDBWithCachingOldValue(String dbName, AbstractRevokingStore revokingDatabase) { - dbSource = new LevelDbDataSourceImpl(StorageUtils.getOutputDirectoryByDbName(dbName), - dbName, - StorageUtils.getOptionsByDbName(dbName), - new WriteOptions().sync(CommonParameter.getInstance().getStorage().isDbSync())); - dbSource.initDB(); - this.revokingDatabase = revokingDatabase; - } - - public RevokingDBWithCachingOldValue(String dbName, Options options, - AbstractRevokingStore revokingDatabase) { - dbSource = new LevelDbDataSourceImpl(StorageUtils.getOutputDirectoryByDbName(dbName), - dbName, - options, - new WriteOptions().sync(CommonParameter.getInstance().getStorage().isDbSync())); - dbSource.initDB(); - this.revokingDatabase = revokingDatabase; - } - - @Override - public void put(byte[] key, byte[] newValue) { - if (Objects.isNull(key) || Objects.isNull(newValue)) { - return; - } - byte[] value = dbSource.getData(key); - if (ArrayUtils.isNotEmpty(value)) { - onModify(key, value); - } - - dbSource.putData(key, newValue); - - if (ArrayUtils.isEmpty(value)) { - onCreate(key); - } - } - - @Override - public void delete(byte[] key) { - onDelete(key); - dbSource.deleteData(key); - } - - @Override - public boolean has(byte[] key) { - return dbSource.getData(key) != null; - } - - @Override - public byte[] get(byte[] key) throws ItemNotFoundException { - byte[] value = dbSource.getData(key); - if (ArrayUtils.isEmpty(value)) { - throw new ItemNotFoundException(); - } - return value; - } - - @Override - public byte[] getFromRoot(byte[] key) throws ItemNotFoundException { - return get(key); - } - - @Override - public byte[] getUnchecked(byte[] key) { - try { - return get(key); - } catch (ItemNotFoundException e) { - return null; - } - } - - @Override - public void close() { - dbSource.closeDB(); - } - - @Override - public void reset() { - dbSource.resetDb(); - } - - @Override - public void setCursor(Chainbase.Cursor cursor) { - } - - @Override - public void setCursor(Chainbase.Cursor cursor, long offset) { - } - - /** - * This should be never called - */ - @Override - public Chainbase.Cursor getCursor() { - logger.error("RevokingDBWithCachingOldValue getCursor is called, this should not be happened"); - return Cursor.HEAD; - } - - /** - * This should be called just after an object is created - */ - private void onCreate(byte[] key) { - revokingDatabase.onCreate(new AbstractRevokingStore.RevokingTuple(dbSource, key), null); - } - - /** - * This should be called just before an object is modified - */ - private void onModify(byte[] key, byte[] value) { - revokingDatabase.onModify(new AbstractRevokingStore.RevokingTuple(dbSource, key), value); - } - - /** - * This should be called just before an object is removed. - */ - private void onDelete(byte[] key) { - byte[] value; - if (Objects.nonNull(value = dbSource.getData(key))) { - revokingDatabase.onRemove(new AbstractRevokingStore.RevokingTuple(dbSource, key), value); - } - } - - @Override - public Iterator> iterator() { - return dbSource.iterator(); - } - - @Override - public Set getlatestValues(long limit) { - return dbSource.getlatestValues(limit); - } - - @Override - public Set getValuesNext(byte[] key, long limit) { - return dbSource.getValuesNext(key, limit); - } - - @Override - public List getKeysNext(byte[] key, long limit) { - return dbSource.getKeysNext(key, limit); - } - - @Override - public Map prefixQuery(byte[] key) { - return dbSource.prefixQuery(key); - } - -} diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index f8feb3da925..cc138af70d9 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -91,8 +91,6 @@ public class CommonParameter { public String password; @Parameter(names = {"--storage-db-directory"}, description = "Storage db directory") public String storageDbDirectory = ""; - @Parameter(names = {"--storage-db-version"}, description = "Storage db version.(1 or 2)") - public String storageDbVersion = ""; @Parameter(names = { "--storage-db-engine"}, description = "Storage db engine.(leveldb or rocksdb)") public String storageDbEngine = ""; diff --git a/common/src/main/java/org/tron/core/config/args/Storage.java b/common/src/main/java/org/tron/core/config/args/Storage.java index 2394a108c6e..66af3b18ce1 100644 --- a/common/src/main/java/org/tron/core/config/args/Storage.java +++ b/common/src/main/java/org/tron/core/config/args/Storage.java @@ -46,7 +46,6 @@ public class Storage { * Keys (names) of database config */ private static final String DB_DIRECTORY_CONFIG_KEY = "storage.db.directory"; - private static final String DB_VERSION_CONFIG_KEY = "storage.db.version"; private static final String DB_ENGINE_CONFIG_KEY = "storage.db.engine"; private static final String DB_SYNC_CONFIG_KEY = "storage.db.sync"; private static final String INDEX_DIRECTORY_CONFIG_KEY = "storage.index.directory"; @@ -81,7 +80,6 @@ public class Storage { /** * Default values of directory */ - private static final int DEFAULT_DB_VERSION = 2; private static final String DEFAULT_DB_ENGINE = "LEVELDB"; private static final boolean DEFAULT_DB_SYNC = false; private static final boolean DEFAULT_EVENT_SUBSCRIBE_CONTRACT_PARSE = true; @@ -100,10 +98,6 @@ public class Storage { @Setter private String dbDirectory; - @Getter - @Setter - private int dbVersion; - @Getter @Setter private String dbEngine; @@ -158,11 +152,6 @@ public class Storage { @Getter private Map propertyMap; - public static int getDbVersionFromConfig(final Config config) { - return config.hasPath(DB_VERSION_CONFIG_KEY) - ? config.getInt(DB_VERSION_CONFIG_KEY) : DEFAULT_DB_VERSION; - } - public static String getDbEngineFromConfig(final Config config) { return config.hasPath(DB_ENGINE_CONFIG_KEY) ? config.getString(DB_ENGINE_CONFIG_KEY) : DEFAULT_DB_ENGINE; diff --git a/framework/src/main/java/org/tron/core/config/DefaultConfig.java b/framework/src/main/java/org/tron/core/config/DefaultConfig.java index 7779ce55624..6c6a0e2c566 100755 --- a/framework/src/main/java/org/tron/core/config/DefaultConfig.java +++ b/framework/src/main/java/org/tron/core/config/DefaultConfig.java @@ -13,7 +13,6 @@ import org.tron.core.config.args.Args; import org.tron.core.db.RecentTransactionStore; import org.tron.core.db.RevokingDatabase; -import org.tron.core.db.RevokingStore; import org.tron.core.db.TransactionCache; import org.tron.core.db.backup.BackupRocksDBAspect; import org.tron.core.db.backup.NeedBeanCondition; @@ -45,18 +44,9 @@ public DefaultConfig() { @Bean public RevokingDatabase revokingDatabase() { - int dbVersion = Args.getInstance().getStorage().getDbVersion(); - RevokingDatabase revokingDatabase; try { - if (dbVersion == 1) { - revokingDatabase = RevokingStore.getInstance(); - } else if (dbVersion == 2) { - revokingDatabase = new SnapshotManager( - StorageUtils.getOutputDirectoryByDbName("block")); - } else { - throw new RuntimeException("db version is error."); - } - return revokingDatabase; + return new SnapshotManager( + StorageUtils.getOutputDirectoryByDbName("block")); } finally { logger.info("key-value data source created."); } @@ -66,8 +56,7 @@ public RevokingDatabase revokingDatabase() { @Bean public RpcApiServiceOnSolidity getRpcApiServiceOnSolidity() { boolean isSolidityNode = Args.getInstance().isSolidityNode(); - int dbVersion = Args.getInstance().getStorage().getDbVersion(); - if (!isSolidityNode && dbVersion == 2) { + if (!isSolidityNode) { return new RpcApiServiceOnSolidity(); } @@ -77,8 +66,7 @@ public RpcApiServiceOnSolidity getRpcApiServiceOnSolidity() { @Bean public HttpApiOnSolidityService getHttpApiOnSolidityService() { boolean isSolidityNode = Args.getInstance().isSolidityNode(); - int dbVersion = Args.getInstance().getStorage().getDbVersion(); - if (!isSolidityNode && dbVersion == 2) { + if (!isSolidityNode) { return new HttpApiOnSolidityService(); } @@ -88,8 +76,7 @@ public HttpApiOnSolidityService getHttpApiOnSolidityService() { @Bean public RpcApiServiceOnPBFT getRpcApiServiceOnPBFT() { boolean isSolidityNode = Args.getInstance().isSolidityNode(); - int dbVersion = Args.getInstance().getStorage().getDbVersion(); - if (!isSolidityNode && dbVersion == 2) { + if (!isSolidityNode) { return new RpcApiServiceOnPBFT(); } @@ -99,8 +86,7 @@ public RpcApiServiceOnPBFT getRpcApiServiceOnPBFT() { @Bean public HttpApiOnPBFTService getHttpApiOnPBFTService() { boolean isSolidityNode = Args.getInstance().isSolidityNode(); - int dbVersion = Args.getInstance().getStorage().getDbVersion(); - if (!isSolidityNode && dbVersion == 2) { + if (!isSolidityNode) { return new HttpApiOnPBFTService(); } @@ -109,11 +95,7 @@ public HttpApiOnPBFTService getHttpApiOnPBFTService() { @Bean public TransactionCache transactionCache() { - int dbVersion = Args.getInstance().getStorage().getDbVersion(); - if (dbVersion == 2) { - return new TransactionCache("trans-cache", appCtx.getBean(RecentTransactionStore.class)); - } - return null; + return new TransactionCache("trans-cache", appCtx.getBean(RecentTransactionStore.class)); } @Bean diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index a0b428df59f..3ce31b1d894 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -468,20 +468,11 @@ public static void setParam(final String[] args, final String confFileName) { } PARAMETER.storage = new Storage(); - PARAMETER.storage.setDbVersion(Optional.ofNullable(PARAMETER.storageDbVersion) - .filter(StringUtils::isNotEmpty) - .map(Integer::valueOf) - .orElse(Storage.getDbVersionFromConfig(config))); PARAMETER.storage.setDbEngine(Optional.ofNullable(PARAMETER.storageDbEngine) .filter(StringUtils::isNotEmpty) .orElse(Storage.getDbEngineFromConfig(config))); - if (Constant.ROCKSDB.equalsIgnoreCase(PARAMETER.storage.getDbEngine()) - && PARAMETER.storage.getDbVersion() == 1) { - throw new RuntimeException("db.version = 1 is not supported by ROCKSDB engine."); - } - PARAMETER.storage.setDbSync(Optional.ofNullable(PARAMETER.storageDbSynchronous) .filter(StringUtils::isNotEmpty) .map(Boolean::valueOf) @@ -1414,7 +1405,6 @@ public static void logConfig() { logger.info("Code version : {}", Version.getVersion()); logger.info("Version code: {}", Version.VERSION_CODE); logger.info("************************ DB config *************************"); - logger.info("DB version : {}", parameter.getStorage().getDbVersion()); logger.info("DB engine : {}", parameter.getStorage().getDbEngine()); logger.info("***************************************************************"); logger.info("************************ shutDown config *************************"); diff --git a/framework/src/main/java/org/tron/core/db/backup/NeedBeanCondition.java b/framework/src/main/java/org/tron/core/db/backup/NeedBeanCondition.java index 64da8d2acc4..e5230cb4ba8 100644 --- a/framework/src/main/java/org/tron/core/db/backup/NeedBeanCondition.java +++ b/framework/src/main/java/org/tron/core/db/backup/NeedBeanCondition.java @@ -9,8 +9,7 @@ public class NeedBeanCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - return (Args.getInstance().getStorage().getDbVersion() == 2 && "ROCKSDB" - .equals(Args.getInstance().getStorage().getDbEngine().toUpperCase())) && Args.getInstance() - .getDbBackupConfig().isEnable() && !Args.getInstance().isWitness(); + return ("ROCKSDB".equals(Args.getInstance().getStorage().getDbEngine().toUpperCase())) + && Args.getInstance().getDbBackupConfig().isEnable() && !Args.getInstance().isWitness(); } } \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/services/NodeInfoService.java b/framework/src/main/java/org/tron/core/services/NodeInfoService.java index 79aff5b8a71..062633af6ab 100644 --- a/framework/src/main/java/org/tron/core/services/NodeInfoService.java +++ b/framework/src/main/java/org/tron/core/services/NodeInfoService.java @@ -183,7 +183,7 @@ private void setConfigNodeInfo(NodeInfo nodeInfo) { configNodeInfo.setBackupListenPort(parameter.getBackupPort()); configNodeInfo.setBackupMemberSize(parameter.getBackupMembers().size()); configNodeInfo.setBackupPriority(parameter.getBackupPriority()); - configNodeInfo.setDbVersion(parameter.getStorage().getDbVersion()); + configNodeInfo.setDbVersion(2); configNodeInfo.setMinParticipationRate(parameter.getMinParticipationRate()); configNodeInfo.setSupportConstant(parameter.isSupportConstant()); configNodeInfo.setMinTimeRatio(parameter.getMinTimeRatio()); diff --git a/framework/src/main/java/org/tron/program/FullNode.java b/framework/src/main/java/org/tron/program/FullNode.java index 63c1edaaecf..6f2aedc44cd 100644 --- a/framework/src/main/java/org/tron/program/FullNode.java +++ b/framework/src/main/java/org/tron/program/FullNode.java @@ -28,7 +28,6 @@ @Slf4j(topic = "app") public class FullNode { - public static final int dbVersion = 2; public static volatile boolean shutDownSign = false; @@ -103,38 +102,34 @@ public static void main(String[] args) { // full node and solidity node fuse together // provide solidity rpc and http server on the full node. - if (CommonParameter.getInstance().getStorage().getDbVersion() == dbVersion) { - RpcApiServiceOnSolidity rpcApiServiceOnSolidity = context - .getBean(RpcApiServiceOnSolidity.class); - appT.addService(rpcApiServiceOnSolidity); - HttpApiOnSolidityService httpApiOnSolidityService = context - .getBean(HttpApiOnSolidityService.class); - if (CommonParameter.getInstance().solidityNodeHttpEnable) { - appT.addService(httpApiOnSolidityService); - } + RpcApiServiceOnSolidity rpcApiServiceOnSolidity = context + .getBean(RpcApiServiceOnSolidity.class); + appT.addService(rpcApiServiceOnSolidity); + HttpApiOnSolidityService httpApiOnSolidityService = context + .getBean(HttpApiOnSolidityService.class); + if (CommonParameter.getInstance().solidityNodeHttpEnable) { + appT.addService(httpApiOnSolidityService); + } - // JSON-RPC on solidity - if (CommonParameter.getInstance().jsonRpcHttpSolidityNodeEnable) { - JsonRpcServiceOnSolidity jsonRpcServiceOnSolidity = context - .getBean(JsonRpcServiceOnSolidity.class); - appT.addService(jsonRpcServiceOnSolidity); - } + // JSON-RPC on solidity + if (CommonParameter.getInstance().jsonRpcHttpSolidityNodeEnable) { + JsonRpcServiceOnSolidity jsonRpcServiceOnSolidity = context + .getBean(JsonRpcServiceOnSolidity.class); + appT.addService(jsonRpcServiceOnSolidity); } // PBFT API (HTTP and GRPC) - if (CommonParameter.getInstance().getStorage().getDbVersion() == dbVersion) { - RpcApiServiceOnPBFT rpcApiServiceOnPBFT = context - .getBean(RpcApiServiceOnPBFT.class); - appT.addService(rpcApiServiceOnPBFT); - HttpApiOnPBFTService httpApiOnPBFTService = context - .getBean(HttpApiOnPBFTService.class); - appT.addService(httpApiOnPBFTService); - - // JSON-RPC on PBFT - if (CommonParameter.getInstance().jsonRpcHttpPBFTNodeEnable) { - JsonRpcServiceOnPBFT jsonRpcServiceOnPBFT = context.getBean(JsonRpcServiceOnPBFT.class); - appT.addService(jsonRpcServiceOnPBFT); - } + RpcApiServiceOnPBFT rpcApiServiceOnPBFT = context + .getBean(RpcApiServiceOnPBFT.class); + appT.addService(rpcApiServiceOnPBFT); + HttpApiOnPBFTService httpApiOnPBFTService = context + .getBean(HttpApiOnPBFTService.class); + appT.addService(httpApiOnPBFTService); + + // JSON-RPC on PBFT + if (CommonParameter.getInstance().jsonRpcHttpPBFTNodeEnable) { + JsonRpcServiceOnPBFT jsonRpcServiceOnPBFT = context.getBean(JsonRpcServiceOnPBFT.class); + appT.addService(jsonRpcServiceOnPBFT); } appT.initServices(parameter); diff --git a/framework/src/main/resources/config-localtest.conf b/framework/src/main/resources/config-localtest.conf index 15488c53743..45254446001 100644 --- a/framework/src/main/resources/config-localtest.conf +++ b/framework/src/main/resources/config-localtest.conf @@ -5,7 +5,6 @@ net { storage { # Directory for storing persistent data - db.version = 2, db.directory = "database", index.directory = "index", @@ -127,7 +126,7 @@ node { rpc { port = 50051 - # This configuration takes effect only if db.version = 2,default value is 50061 + # default value is 50061 # solidityPort = 50061 # Number of gRPC thread, default availableProcessors / 2 diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 6a06f4ed0fe..6235167cb57 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -5,7 +5,6 @@ net { storage { # Directory for storing persistent data - db.version = 2, db.engine = "LEVELDB", db.sync = false, db.directory = "database", @@ -65,7 +64,7 @@ storage { needToUpdateAsset = true - //dbsettings is needed when using rocksdb as the storage implement (db.version=2 and db.engine="ROCKSDB"). + //dbsettings is needed when using rocksdb as the storage implement (db.engine="ROCKSDB"). //we'd strongly recommend that do not modify it unless you know every item's meaning clearly. dbSettings = { levelNumber = 7 @@ -78,8 +77,8 @@ storage { targetFileSizeMultiplier = 1 } - //backup settings when using rocks db as the storage implement (db.version=2 and db.engine="ROCKSDB"). - //if you want to use the backup plugin, please confirm set the db.version=2 and db.engine="ROCKSDB" above. + //backup settings when using rocks db as the storage implement (db.engine="ROCKSDB"). + //if you want to use the backup plugin, please confirm set the db.engine="ROCKSDB" above. backup = { enable = false // indicate whether enable the backup plugin propPath = "prop.properties" // record which bak directory is valid diff --git a/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreWithCacheOldValueTest.java b/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreWithCacheOldValueTest.java deleted file mode 100644 index 4e8f5ffe866..00000000000 --- a/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreWithCacheOldValueTest.java +++ /dev/null @@ -1,188 +0,0 @@ -package org.tron.core.db; - -import java.io.File; -import java.util.List; -import lombok.extern.slf4j.Slf4j; -import org.iq80.leveldb.Options; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.FileUtil; -import org.tron.common.utils.MarketOrderPriceComparatorForLevelDB; -import org.tron.common.utils.StorageUtils; -import org.tron.core.Constant; -import org.tron.core.capsule.MarketOrderIdListCapsule; -import org.tron.core.capsule.utils.MarketUtils; -import org.tron.core.config.DefaultConfig; -import org.tron.core.config.args.Args; -import org.tron.core.exception.BadItemException; -import org.tron.core.exception.ItemNotFoundException; - -@Slf4j -public class MarketPairPriceToOrderStoreWithCacheOldValueTest { - - private AbstractRevokingStore revokingDatabase; - private TronApplicationContext context; - - @Before - public void init() { - Args.setParam(new String[]{"-d", "output_market_revokingStore_test"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - ApplicationFactory.create(context); - revokingDatabase = new TestRevokingTronDatabase(); - revokingDatabase.enable(); - } - - @After - public void removeDb() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File("output_market_revokingStore_test")); - } - - /** - * Almost the same as testPriceSeqWithSamePair, except using the RevokingDBWithCachingOldValue. - * We add this test in order to test db.version=1. - * */ - @Test - public synchronized void testGetKeysNext() { - revokingDatabase.getStack().clear(); - String dbName = "testrevokingtronstore-testGetKeysNext"; - Options options = StorageUtils.getOptionsByDbName(dbName); - options.comparator(new MarketOrderPriceComparatorForLevelDB()); - TestRevokingTronStore tronDatabase = new TestRevokingTronStore(dbName, options, - revokingDatabase); - - // put order: 2 1 3 0 - // lexicographical order: 0 < 3 < 1 = 2 - // key order: 0 < 1 = 2 < 3 - byte[] sellTokenID1 = ByteArray.fromString("100"); - byte[] buyTokenID1 = ByteArray.fromString("200"); - byte[] pairPriceKey0 = MarketUtils.createPairPriceKey( - sellTokenID1, - buyTokenID1, - 0L, - 0L - ); - byte[] pairPriceKey1 = MarketUtils.createPairPriceKey( - sellTokenID1, - buyTokenID1, - 10L, - 21L - ); - byte[] pairPriceKey2 = MarketUtils.createPairPriceKey( - sellTokenID1, - buyTokenID1, - 30L, - 63L - ); - byte[] pairPriceKey3 = MarketUtils.createPairPriceKey( - sellTokenID1, - buyTokenID1, - 1L, - 4L - ); - - // lexicographical order: 0 < 3 < 1 = 2 - Assert.assertTrue(ByteUtil.compare(pairPriceKey0, pairPriceKey3) < 0); - Assert.assertTrue(ByteUtil.compare(pairPriceKey3, pairPriceKey1) < 0); - Assert.assertEquals(0, ByteUtil.compare(pairPriceKey1, pairPriceKey2)); - - MarketOrderIdListCapsule capsule0 = new MarketOrderIdListCapsule(ByteArray.fromLong(0), - ByteArray.fromLong(0)); - MarketOrderIdListCapsule capsule1 = new MarketOrderIdListCapsule(ByteArray.fromLong(1), - ByteArray.fromLong(1)); - MarketOrderIdListCapsule capsule2 = new MarketOrderIdListCapsule(ByteArray.fromLong(2), - ByteArray.fromLong(2)); - MarketOrderIdListCapsule capsule3 = new MarketOrderIdListCapsule(ByteArray.fromLong(3), - ByteArray.fromLong(3)); - - // put: 2 1 0 3 - Assert.assertFalse(tronDatabase.has(pairPriceKey2)); - tronDatabase.put(pairPriceKey2, capsule2); - - try { - Assert - .assertArrayEquals(capsule2.getData(), - tronDatabase.get(pairPriceKey2).getData()); - } catch (ItemNotFoundException | BadItemException e) { - Assert.fail(); - } - - // pairPriceKey1 and pairPriceKey2 has the same value, - // After put pairPriceKey2, pairPriceKey2 will be replaced by pairPriceKey1, both key and value. - // But you can still get(pairPriceKey2) return pairPriceKey1's value - Assert.assertTrue(tronDatabase.has(pairPriceKey1)); - tronDatabase.put(pairPriceKey1, capsule1); - Assert.assertEquals(1, tronDatabase.size()); - - try { - Assert - .assertArrayEquals(capsule1.getData(), - tronDatabase.get(pairPriceKey1).getData()); - Assert - .assertArrayEquals(capsule1.getData(), - tronDatabase.get(pairPriceKey2).getData()); - } catch (ItemNotFoundException | BadItemException e) { - Assert.fail(); - } - - Assert.assertFalse(tronDatabase.has(pairPriceKey0)); - if (!tronDatabase.has(pairPriceKey0)) { - tronDatabase.put(pairPriceKey0, capsule0); - } - - Assert.assertEquals(2, tronDatabase.size()); - - Assert.assertFalse(tronDatabase.has(pairPriceKey3)); - if (!tronDatabase.has(pairPriceKey3)) { - tronDatabase.put(pairPriceKey3, capsule3); - } - - Assert.assertEquals(3, tronDatabase.size()); - - // get pairPriceKey1, will get pairPriceKey2's value capsule2 - try { - Assert - .assertArrayEquals(capsule0.getData(), - tronDatabase.get(pairPriceKey0).getData()); - Assert - .assertArrayEquals(capsule1.getData(), - tronDatabase.get(pairPriceKey1).getData()); - Assert - .assertArrayEquals(capsule1.getData(), - tronDatabase.get(pairPriceKey2).getData()); - Assert - .assertArrayEquals(capsule3.getData(), - tronDatabase.get(pairPriceKey3).getData()); - } catch (ItemNotFoundException | BadItemException e) { - Assert.fail(); - } - - List keyList = tronDatabase.getRevokingDB().getKeysNext(pairPriceKey0, 2 + 1); - Assert.assertArrayEquals(pairPriceKey0, keyList.get(0)); - Assert.assertArrayEquals(pairPriceKey1, keyList.get(1)); - Assert.assertArrayEquals(pairPriceKey3, keyList.get(2)); - - - tronDatabase.close(); - } - - private static class TestRevokingTronStore extends - TronStoreWithRevoking { - - private TestRevokingTronStore(String dbName, Options options, - RevokingDatabase revokingDatabase) { - super(dbName, options, revokingDatabase); - } - } - - private static class TestRevokingTronDatabase extends AbstractRevokingStore { - - } -} diff --git a/framework/src/test/java/org/tron/core/db2/RevokingDbWithCacheOldValueTest.java b/framework/src/test/java/org/tron/core/db2/RevokingDbWithCacheOldValueTest.java deleted file mode 100644 index f7a4d58fd97..00000000000 --- a/framework/src/test/java/org/tron/core/db2/RevokingDbWithCacheOldValueTest.java +++ /dev/null @@ -1,279 +0,0 @@ -package org.tron.core.db2; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.ArrayUtils; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; -import org.tron.core.Constant; -import org.tron.core.config.DefaultConfig; -import org.tron.core.config.args.Args; -import org.tron.core.db.AbstractRevokingStore; -import org.tron.core.db.RevokingDatabase; -import org.tron.core.db.TronStoreWithRevoking; -import org.tron.core.db2.SnapshotRootTest.ProtoCapsuleTest; -import org.tron.core.exception.RevokingStoreIllegalStateException; - -@Slf4j -public class RevokingDbWithCacheOldValueTest { - - private AbstractRevokingStore revokingDatabase; - private TronApplicationContext context; - private Application appT; - - @Before - public void init() { - Args.setParam(new String[]{"-d", "output_revokingStore_test"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - appT = ApplicationFactory.create(context); - revokingDatabase = new TestRevokingTronDatabase(); - revokingDatabase.enable(); - } - - @After - public void removeDb() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File("output_revokingStore_test")); - } - - @Test - public synchronized void testReset() { - revokingDatabase.getStack().clear(); - TestRevokingTronStore tronDatabase = new TestRevokingTronStore( - "testrevokingtronstore-testReset", revokingDatabase); - ProtoCapsuleTest testProtoCapsule = new ProtoCapsuleTest(("reset").getBytes()); - try (ISession tmpSession = revokingDatabase.buildSession()) { - tronDatabase.put(testProtoCapsule.getData(), testProtoCapsule); - tmpSession.commit(); - } - Assert.assertTrue(tronDatabase.has(testProtoCapsule.getData())); - tronDatabase.reset(); - Assert.assertFalse(tronDatabase.has(testProtoCapsule.getData())); - tronDatabase.reset(); - } - - @Test - public synchronized void testPop() throws RevokingStoreIllegalStateException { - revokingDatabase.getStack().clear(); - TestRevokingTronStore tronDatabase = new TestRevokingTronStore( - "testrevokingtronstore-testPop", revokingDatabase); - - for (int i = 1; i < 11; i++) { - ProtoCapsuleTest testProtoCapsule = new ProtoCapsuleTest(("pop" + i).getBytes()); - try (ISession tmpSession = revokingDatabase.buildSession()) { - tronDatabase.put(testProtoCapsule.getData(), testProtoCapsule); - Assert.assertEquals(1, revokingDatabase.getActiveDialog()); - tmpSession.commit(); - Assert.assertEquals(i, revokingDatabase.getStack().size()); - Assert.assertEquals(0, revokingDatabase.getActiveDialog()); - } - } - - for (int i = 1; i < 11; i++) { - revokingDatabase.pop(); - Assert.assertEquals(10 - i, revokingDatabase.getStack().size()); - } - - tronDatabase.close(); - - Assert.assertEquals(0, revokingDatabase.getStack().size()); - } - - @Test - public synchronized void testUndo() throws RevokingStoreIllegalStateException { - revokingDatabase.getStack().clear(); - TestRevokingTronStore tronDatabase = new TestRevokingTronStore( - "testrevokingtronstore-testUndo", revokingDatabase); - - ISession dialog = revokingDatabase.buildSession(); - for (int i = 0; i < 10; i++) { - ProtoCapsuleTest testProtoCapsule = new ProtoCapsuleTest(("undo" + i).getBytes()); - try (ISession tmpSession = revokingDatabase.buildSession()) { - tronDatabase.put(testProtoCapsule.getData(), testProtoCapsule); - Assert.assertEquals(2, revokingDatabase.getStack().size()); - tmpSession.merge(); - Assert.assertEquals(1, revokingDatabase.getStack().size()); - } - } - - Assert.assertEquals(1, revokingDatabase.getStack().size()); - - dialog.destroy(); - Assert.assertTrue(revokingDatabase.getStack().isEmpty()); - Assert.assertEquals(0, revokingDatabase.getActiveDialog()); - - dialog = revokingDatabase.buildSession(); - revokingDatabase.disable(); - ProtoCapsuleTest testProtoCapsule = new ProtoCapsuleTest("del".getBytes()); - tronDatabase.put(testProtoCapsule.getData(), testProtoCapsule); - revokingDatabase.enable(); - - try (ISession tmpSession = revokingDatabase.buildSession()) { - tronDatabase.put(testProtoCapsule.getData(), new ProtoCapsuleTest("del2".getBytes())); - tmpSession.merge(); - } - - try (ISession tmpSession = revokingDatabase.buildSession()) { - tronDatabase.put(testProtoCapsule.getData(), new ProtoCapsuleTest("del22".getBytes())); - tmpSession.merge(); - } - - try (ISession tmpSession = revokingDatabase.buildSession()) { - tronDatabase.put(testProtoCapsule.getData(), new ProtoCapsuleTest("del222".getBytes())); - tmpSession.merge(); - } - - try (ISession tmpSession = revokingDatabase.buildSession()) { - tronDatabase.delete(testProtoCapsule.getData()); - tmpSession.merge(); - } - - dialog.destroy(); - - logger.info( - "**********testProtoCapsule:" + tronDatabase.getUnchecked(testProtoCapsule.getData()) - .toString()); - Assert.assertArrayEquals("del".getBytes(), - tronDatabase.getUnchecked(testProtoCapsule.getData()).getData()); - Assert.assertEquals(testProtoCapsule, tronDatabase.getUnchecked(testProtoCapsule.getData())); - - tronDatabase.close(); - } - - @Test - public synchronized void testGetlatestValues() { - revokingDatabase.getStack().clear(); - TestRevokingTronStore tronDatabase = new TestRevokingTronStore( - "testrevokingtronstore-testGetlatestValues", revokingDatabase); - - for (int i = 0; i < 10; i++) { - ProtoCapsuleTest testProtoCapsule = new ProtoCapsuleTest(("getLastestValues" + i).getBytes()); - try (ISession tmpSession = revokingDatabase.buildSession()) { - tronDatabase.put(testProtoCapsule.getData(), testProtoCapsule); - tmpSession.commit(); - } - } - Set result = tronDatabase.getRevokingDB().getlatestValues(5).stream() - .map(ProtoCapsuleTest::new) - .collect(Collectors.toSet()); - - for (int i = 9; i >= 5; i--) { - Assert.assertTrue(result.contains(new ProtoCapsuleTest(("getLastestValues" + i).getBytes()))); - } - tronDatabase.close(); - } - - @Test - public synchronized void testGetValuesNext() { - revokingDatabase.getStack().clear(); - TestRevokingTronStore tronDatabase = new TestRevokingTronStore( - "testrevokingtronstore-testGetValuesNext", revokingDatabase); - - for (int i = 0; i < 10; i++) { - ProtoCapsuleTest testProtoCapsule = new ProtoCapsuleTest(("getValuesNext" + i).getBytes()); - try (ISession tmpSession = revokingDatabase.buildSession()) { - tronDatabase.put(testProtoCapsule.getData(), testProtoCapsule); - tmpSession.commit(); - } - } - Set result = - tronDatabase.getRevokingDB().getValuesNext( - new ProtoCapsuleTest("getValuesNext2".getBytes()).getData(), 3) - .stream() - .map(ProtoCapsuleTest::new) - .collect(Collectors.toSet()); - - for (int i = 2; i < 5; i++) { - Assert.assertTrue(result.contains(new ProtoCapsuleTest(("getValuesNext" + i).getBytes()))); - } - tronDatabase.close(); - } - - @Test - public synchronized void testGetKeysNext() { - revokingDatabase.getStack().clear(); - TestRevokingTronStore tronDatabase = new TestRevokingTronStore( - "testrevokingtronstore-testGetKeysNext", revokingDatabase); - - String protoCapsuleStr = "getKeysNext"; - for (int i = 0; i < 10; i++) { - ProtoCapsuleTest testProtoCapsule = new ProtoCapsuleTest((protoCapsuleStr + i).getBytes()); - try (ISession tmpSession = revokingDatabase.buildSession()) { - tronDatabase.put(testProtoCapsule.getData(), testProtoCapsule); - tmpSession.commit(); - } - } - - int start = 2; - List result = - tronDatabase.getRevokingDB().getKeysNext( - new ProtoCapsuleTest((protoCapsuleStr + start).getBytes()).getData(), 3); - - for (int i = start; i < 5; i++) { - Assert.assertArrayEquals(new ProtoCapsuleTest((protoCapsuleStr + i).getBytes()).getData(), - result.get(i - 2)); - } - tronDatabase.close(); - } - - @Test - public void shutdown() throws RevokingStoreIllegalStateException { - revokingDatabase.getStack().clear(); - TestRevokingTronStore tronDatabase = new TestRevokingTronStore( - "testrevokingtronstore-shutdown", revokingDatabase); - - List capsules = new ArrayList<>(); - for (int i = 1; i < 11; i++) { - revokingDatabase.buildSession(); - ProtoCapsuleTest testProtoCapsule = new ProtoCapsuleTest(("test" + i).getBytes()); - capsules.add(testProtoCapsule); - tronDatabase.put(testProtoCapsule.getData(), testProtoCapsule); - Assert.assertEquals(revokingDatabase.getActiveDialog(), i); - Assert.assertEquals(revokingDatabase.getStack().size(), i); - } - - for (ProtoCapsuleTest capsule : capsules) { - logger.info(new String(capsule.getData())); - Assert.assertEquals(capsule, tronDatabase.getUnchecked(capsule.getData())); - } - - revokingDatabase.shutdown(); - - for (ProtoCapsuleTest capsule : capsules) { - logger.info(tronDatabase.getUnchecked(capsule.getData()).toString()); - Assert.assertEquals(null, tronDatabase.getUnchecked(capsule.getData()).getData()); - } - - Assert.assertEquals(0, revokingDatabase.getStack().size()); - tronDatabase.close(); - - } - - private static class TestRevokingTronStore extends TronStoreWithRevoking { - - protected TestRevokingTronStore(String dbName, RevokingDatabase revokingDatabase) { - super(dbName, revokingDatabase); - } - - @Override - public ProtoCapsuleTest get(byte[] key) { - byte[] value = this.revokingDB.getUnchecked(key); - return ArrayUtils.isEmpty(value) ? null : new ProtoCapsuleTest(value); - } - } - - private static class TestRevokingTronDatabase extends AbstractRevokingStore { - - } -} diff --git a/framework/src/test/resources/config-localtest.conf b/framework/src/test/resources/config-localtest.conf index 280e06b4af2..c6ecaf28173 100644 --- a/framework/src/test/resources/config-localtest.conf +++ b/framework/src/test/resources/config-localtest.conf @@ -5,7 +5,6 @@ net { storage { # Directory for storing persistent data - db.version = 2, db.engine ="LEVELDB", db.directory = "database", index.directory = "index", @@ -124,7 +123,7 @@ node { rpc { port = 50051 - # This configuration takes effect only if db.version = 2,default value is 50061 + # default value is 50061 # solidityPort = 50061 # Number of gRPC thread, default availableProcessors / 2 diff --git a/framework/src/test/resources/config-test-dbbackup.conf b/framework/src/test/resources/config-test-dbbackup.conf index 02c1aae36c2..bb64a87ef69 100644 --- a/framework/src/test/resources/config-test-dbbackup.conf +++ b/framework/src/test/resources/config-test-dbbackup.conf @@ -5,7 +5,6 @@ net { storage { # Directory for storing persistent data - db.version = 2, db.engine = "ROCKSDB", db.directory = "database", index.directory = "index", diff --git a/framework/src/test/resources/config-test-storagetest.conf b/framework/src/test/resources/config-test-storagetest.conf index ef8bfe906fa..87e3eabea2d 100644 --- a/framework/src/test/resources/config-test-storagetest.conf +++ b/framework/src/test/resources/config-test-storagetest.conf @@ -7,7 +7,6 @@ net { storage { # Directory for storing persistent data - db.version = 2, db.engine = "LEVELDB" db.directory = "database", index.directory = "index", diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index 886438cac57..8facbc2fb9a 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -7,7 +7,6 @@ net { storage { # Directory for storing persistent data - db.version = 2, db.engine = "LEVELDB" db.directory = "database", index.directory = "index", diff --git a/plugins/src/test/resources/config-duplicate.conf b/plugins/src/test/resources/config-duplicate.conf index 758312ad05e..f2eb7fbf357 100644 --- a/plugins/src/test/resources/config-duplicate.conf +++ b/plugins/src/test/resources/config-duplicate.conf @@ -1,7 +1,6 @@ storage { # Directory for storing persistent data - db.version = 2, db.engine = "LEVELDB", db.sync = false, db.directory = "database", diff --git a/plugins/src/test/resources/config.conf b/plugins/src/test/resources/config.conf index be16d44c420..2bfca7dbdd7 100644 --- a/plugins/src/test/resources/config.conf +++ b/plugins/src/test/resources/config.conf @@ -1,7 +1,6 @@ storage { # Directory for storing persistent data - db.version = 2, db.engine = "LEVELDB", db.sync = false, db.directory = "database", From e1d4cfd1667fb9de7e2fbec4fd1d6b4b4787cbdb Mon Sep 17 00:00:00 2001 From: "morgan.peng" Date: Thu, 20 Oct 2022 10:50:54 +0800 Subject: [PATCH 0454/1197] refactor(db): optimize db lock 1.optimize the scope of db lock --- .../leveldb/LevelDbDataSourceImpl.java | 2 +- .../rocksdb/RocksDbDataSourceImpl.java | 179 ++++++++++-------- 2 files changed, 97 insertions(+), 84 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java index 054648eb467..cc978efb225 100644 --- a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java @@ -65,7 +65,7 @@ public class LevelDbDataSourceImpl extends DbStat implements DbSourceInter allKeys() throws RuntimeException { - if (quitIfNotAlive()) { - return null; - } resetDbLock.readLock().lock(); - Set result = Sets.newHashSet(); - try (final RocksIterator iter = getRocksIterator()) { - for (iter.seekToFirst(); iter.isValid(); iter.next()) { - result.add(iter.key()); + try { + if (quitIfNotAlive()) { + return null; + } + Set result = Sets.newHashSet(); + try (final RocksIterator iter = getRocksIterator()) { + for (iter.seekToFirst(); iter.isValid(); iter.next()) { + result.add(iter.key()); + } + return result; } - return result; } finally { resetDbLock.readLock().unlock(); } @@ -272,11 +274,11 @@ public void initDB(RocksDbSettings settings) { @Override public void putData(byte[] key, byte[] value) { - if (quitIfNotAlive()) { - return; - } resetDbLock.readLock().lock(); try { + if (quitIfNotAlive()) { + return; + } database.put(key, value); } catch (RocksDBException e) { throw new RuntimeException(dataBaseName, e); @@ -287,11 +289,11 @@ public void putData(byte[] key, byte[] value) { @Override public byte[] getData(byte[] key) { - if (quitIfNotAlive()) { - return null; - } resetDbLock.readLock().lock(); try { + if (quitIfNotAlive()) { + return null; + } return database.get(key); } catch (RocksDBException e) { throw new RuntimeException(dataBaseName, e); @@ -302,11 +304,11 @@ public byte[] getData(byte[] key) { @Override public void deleteData(byte[] key) { - if (quitIfNotAlive()) { - return; - } resetDbLock.readLock().lock(); try { + if (quitIfNotAlive()) { + return; + } database.delete(key); } catch (RocksDBException e) { throw new RuntimeException(dataBaseName, e); @@ -360,11 +362,11 @@ private void updateByBatchInner(Map rows, WriteOptions options) @Override public void updateByBatch(Map rows, WriteOptionsWrapper optionsWrapper) { - if (quitIfNotAlive()) { - return; - } resetDbLock.readLock().lock(); try { + if (quitIfNotAlive()) { + return; + } updateByBatchInner(rows, optionsWrapper.rocks); } catch (Exception e) { try { @@ -379,11 +381,11 @@ public void updateByBatch(Map rows, WriteOptionsWrapper optionsW @Override public void updateByBatch(Map rows) { - if (quitIfNotAlive()) { - return; - } resetDbLock.readLock().lock(); try { + if (quitIfNotAlive()) { + return; + } updateByBatchInner(rows); } catch (Exception e) { try { @@ -397,40 +399,45 @@ public void updateByBatch(Map rows) { } public List getKeysNext(byte[] key, long limit) { - if (quitIfNotAlive()) { - return new ArrayList<>(); - } - if (limit <= 0) { - return new ArrayList<>(); - } resetDbLock.readLock().lock(); - try (RocksIterator iter = getRocksIterator()) { - List result = new ArrayList<>(); - long i = 0; - for (iter.seek(key); iter.isValid() && i < limit; iter.next(), i++) { - result.add(iter.key()); + try { + if (quitIfNotAlive()) { + return new ArrayList<>(); + } + if (limit <= 0) { + return new ArrayList<>(); + } + + try (RocksIterator iter = getRocksIterator()) { + List result = new ArrayList<>(); + long i = 0; + for (iter.seek(key); iter.isValid() && i < limit; iter.next(), i++) { + result.add(iter.key()); + } + return result; } - return result; } finally { resetDbLock.readLock().unlock(); } } public Map getNext(byte[] key, long limit) { - if (quitIfNotAlive()) { - return null; - } - if (limit <= 0) { - return Collections.emptyMap(); - } resetDbLock.readLock().lock(); - try (RocksIterator iter = getRocksIterator()) { - Map result = new HashMap<>(); - long i = 0; - for (iter.seek(key); iter.isValid() && i < limit; iter.next(), i++) { - result.put(iter.key(), iter.value()); + try { + if (quitIfNotAlive()) { + return null; + } + if (limit <= 0) { + return Collections.emptyMap(); + } + try (RocksIterator iter = getRocksIterator()) { + Map result = new HashMap<>(); + long i = 0; + for (iter.seek(key); iter.isValid() && i < limit; iter.next(), i++) { + result.put(iter.key(), iter.value()); + } + return result; } - return result; } finally { resetDbLock.readLock().unlock(); } @@ -438,40 +445,44 @@ public Map getNext(byte[] key, long limit) { @Override public Map prefixQuery(byte[] key) { - if (quitIfNotAlive()) { - return null; - } resetDbLock.readLock().lock(); - try (RocksIterator iterator = getRocksIterator()) { - Map result = new HashMap<>(); - for (iterator.seek(key); iterator.isValid(); iterator.next()) { - if (Bytes.indexOf(iterator.key(), key) == 0) { - result.put(WrappedByteArray.of(iterator.key()), iterator.value()); - } else { - return result; + try { + if (quitIfNotAlive()) { + return null; + } + try (RocksIterator iterator = getRocksIterator()) { + Map result = new HashMap<>(); + for (iterator.seek(key); iterator.isValid(); iterator.next()) { + if (Bytes.indexOf(iterator.key(), key) == 0) { + result.put(WrappedByteArray.of(iterator.key()), iterator.value()); + } else { + return result; + } } + return result; } - return result; } finally { resetDbLock.readLock().unlock(); } } public Set getlatestValues(long limit) { - if (quitIfNotAlive()) { - return null; - } - if (limit <= 0) { - return Sets.newHashSet(); - } resetDbLock.readLock().lock(); - try (RocksIterator iter = getRocksIterator()) { - Set result = Sets.newHashSet(); - long i = 0; - for (iter.seekToLast(); iter.isValid() && i < limit; iter.prev(), i++) { - result.add(iter.value()); + try { + if (quitIfNotAlive()) { + return null; + } + if (limit <= 0) { + return Sets.newHashSet(); + } + try (RocksIterator iter = getRocksIterator()) { + Set result = Sets.newHashSet(); + long i = 0; + for (iter.seekToLast(); iter.isValid() && i < limit; iter.prev(), i++) { + result.add(iter.value()); + } + return result; } - return result; } finally { resetDbLock.readLock().unlock(); } @@ -479,20 +490,22 @@ public Set getlatestValues(long limit) { public Set getValuesNext(byte[] key, long limit) { - if (quitIfNotAlive()) { - return null; - } - if (limit <= 0) { - return Sets.newHashSet(); - } resetDbLock.readLock().lock(); - try (RocksIterator iter = getRocksIterator()) { - Set result = Sets.newHashSet(); - long i = 0; - for (iter.seek(key); iter.isValid() && i < limit; iter.next(), i++) { - result.add(iter.value()); + try { + if (quitIfNotAlive()) { + return null; + } + if (limit <= 0) { + return Sets.newHashSet(); + } + try (RocksIterator iter = getRocksIterator()) { + Set result = Sets.newHashSet(); + long i = 0; + for (iter.seek(key); iter.isValid() && i < limit; iter.next(), i++) { + result.add(iter.value()); + } + return result; } - return result; } finally { resetDbLock.readLock().unlock(); } From bff517ddeefff79573ea4874e493ecb98d8b512b Mon Sep 17 00:00:00 2001 From: penghuan Date: Wed, 2 Nov 2022 21:16:26 +0800 Subject: [PATCH 0455/1197] feat(db): make snapshot flush speed configurable 1.make snapshot flush speed configurable --- .../org/tron/core/config/args/Storage.java | 20 +++++++++++++++++++ .../java/org/tron/core/config/args/Args.java | 2 ++ .../main/java/org/tron/core/db/Manager.java | 5 ++++- .../java/org/tron/core/db/ManagerTest.java | 1 + framework/src/test/resources/config-test.conf | 1 + 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/tron/core/config/args/Storage.java b/common/src/main/java/org/tron/core/config/args/Storage.java index 2394a108c6e..dbf371de109 100644 --- a/common/src/main/java/org/tron/core/config/args/Storage.java +++ b/common/src/main/java/org/tron/core/config/args/Storage.java @@ -54,6 +54,7 @@ public class Storage { private static final String TRANSACTIONHISTORY_SWITCH_CONFIG_KEY = "storage.transHistory.switch"; private static final String ESTIMATED_TRANSACTIONS_CONFIG_KEY = "storage.txCache.estimatedTransactions"; + private static final String SNAPSHOT_MAX_FLUSH_COUNT_CONFIG_KEY = "storage.snapshot.maxFlushCount"; private static final String PROPERTIES_CONFIG_KEY = "storage.properties"; private static final String PROPERTIES_CONFIG_DB_KEY = "storage"; private static final String PROPERTIES_CONFIG_DEFAULT_KEY = "default"; @@ -91,6 +92,7 @@ public class Storage { private static final int DEFAULT_CHECKPOINT_VERSION = 1; private static final boolean DEFAULT_CHECKPOINT_SYNC = true; private static final int DEFAULT_ESTIMATED_TRANSACTIONS = 1000; + private static final int DEFAULT_SNAPSHOT_MAX_FLUSH_COUNT = 500; private Config storage; /** @@ -112,6 +114,10 @@ public class Storage { @Setter private boolean dbSync; + @Getter + @Setter + private int maxFlushCount; + /** * Index storage directory: /path/to/{indexDirectory} */ @@ -173,6 +179,20 @@ public static Boolean getDbVersionSyncFromConfig(final Config config) { ? config.getBoolean(DB_SYNC_CONFIG_KEY) : DEFAULT_DB_SYNC; } + public static int getSnapshotMaxFlushCountFromConfig(final Config config) { + if (!config.hasPath(SNAPSHOT_MAX_FLUSH_COUNT_CONFIG_KEY)) { + return DEFAULT_SNAPSHOT_MAX_FLUSH_COUNT; + } + int maxFlushCountConfig = config.getInt(SNAPSHOT_MAX_FLUSH_COUNT_CONFIG_KEY); + if (maxFlushCountConfig <= 0) { + throw new IllegalArgumentException("MaxFlushCount value can not be negative or zero!"); + } + if (maxFlushCountConfig > 500) { + throw new IllegalArgumentException("MaxFlushCount value must not exceed 500!"); + } + return maxFlushCountConfig; + } + public static Boolean getContractParseSwitchFromConfig(final Config config) { return config.hasPath(EVENT_SUBSCRIBE_CONTRACT_PARSE) ? config.getBoolean(EVENT_SUBSCRIBE_CONTRACT_PARSE) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 1d9980d0370..4bd37be7581 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -517,6 +517,7 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.storage.setEstimatedBlockTransactions( Storage.getEstimatedTransactionsFromConfig(config)); + PARAMETER.storage.setMaxFlushCount(Storage.getSnapshotMaxFlushCountFromConfig(config)); PARAMETER.storage.setDefaultDbOptions(config); PARAMETER.storage.setPropertyMapFromConfig(config); @@ -1437,6 +1438,7 @@ public static void logConfig() { logger.info("************************ DB config *************************"); logger.info("DB version : {}", parameter.getStorage().getDbVersion()); logger.info("DB engine : {}", parameter.getStorage().getDbEngine()); + logger.info("Snapshot max flush count: {}", parameter.getStorage().getMaxFlushCount()); logger.info("***************************************************************"); logger.info("************************ shutDown config *************************"); logger.info("ShutDown blockTime : {}", parameter.getShutdownBlockTime()); diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index ebc1eb60a38..060a2db5de2 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -239,6 +239,8 @@ public class Manager { @Getter private volatile long latestSolidityNumShutDown; + @Getter + private int maxFlushCount; @Getter private final ThreadLocal blockedTimer = new ThreadLocal<>(); @@ -550,6 +552,7 @@ public void init() { } // init latestSolidityNumShutDown = CommonParameter.getInstance().getShutdownBlockHeight(); + maxFlushCount = CommonParameter.getInstance().getStorage().getMaxFlushCount(); } /** @@ -958,7 +961,7 @@ private void applyBlock(BlockCapsule block, List txs) updateFork(block); if (System.currentTimeMillis() - block.getTimeStamp() >= 60_000) { - revokingStore.setMaxFlushCount(SnapshotManager.DEFAULT_MAX_FLUSH_COUNT); + revokingStore.setMaxFlushCount(maxFlushCount); if (Args.getInstance().getShutdownBlockTime() != null && Args.getInstance().getShutdownBlockTime().getNextValidTimeAfter( new Date(block.getTimeStamp() - SnapshotManager.DEFAULT_MAX_FLUSH_COUNT * 1000 * 3)) diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index 3812c2335c5..e7319d0ed0b 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -118,6 +118,7 @@ public void init() { blockCapsule2.setMerkleRoot(); blockCapsule2.sign( ByteArray.fromHexString(Args.getLocalWitnesses().getPrivateKey())); + Assert.assertTrue(dbManager.getMaxFlushCount() == 200); } @After diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index 886438cac57..f06b7971d74 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -62,6 +62,7 @@ storage { ] needToUpdateAsset = false + snapshot.maxFlushCount = 200 } From 7f925a06540dcc4fa0a9885ddb0a83b3c506e32f Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 12 Dec 2022 21:46:14 +0800 Subject: [PATCH 0456/1197] docs(toolkit): optimize readme --- plugins/README.md | 73 ++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/plugins/README.md b/plugins/README.md index ff1fea4d17b..584619af395 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -1,29 +1,28 @@ # Toolkit Manual -This package contains a set of tools for Tron, the following is the documentation for each tool. +This package contains a set of tools for TRON, the followings are the documentation for each tool. ## DB Archive -DB archive provides the ability to reformat the manifest according to the current `database`, -parameters are compatible with previous `ArchiveManifest`. +DB archive provides the ability to reformat the manifest according to the current `database`, parameters are compatible with the previous `ArchiveManifest`. -Parameter explanation: +### Available parameters: -- `-b | --batch-size`: [int] specify the batch manifest size,default:80000. -- `-d | --database-directory`: [string] specify the database directory to be processed,default:output-directory/database. -- `-m | --manifest-size`: [int] specify the minimum required manifest file size ,unit:M,default:0. -- `-h | --help`: provide the help info +- `-b | --batch-size`: Specify the batch manifest size, default: 80000. +- `-d | --database-directory`: Specify the database directory to be processed, default: output-directory/database. +- `-m | --manifest-size`: Specify the minimum required manifest file size, unit: M, default: 0. +- `-h | --help`: Provide the help info. -Demo: +### Examples: ```shell script # full command java -jar Toolkit.jar db archive [-h] [-b=] [-d=] [-m=] # examples java -jar Toolkit.jar db archive #1. use default settings - java -jar Toolkit.jar db archive -d /tmp/db/database #2. Specify the database directory as /tmp/db/database - java -jar Toolkit.jar db archive -b 64000 #3. Specify the batch size to 64000 when optimizing Manifest - java -jar Toolkit.jar db archive -m 128 #4. Specify optimization only when Manifest exceeds 128M + java -jar Toolkit.jar db archive -d /tmp/db/database #2. specify the database directory as /tmp/db/database + java -jar Toolkit.jar db archive -b 64000 #3. specify the batch size to 64000 when optimizing manifest + java -jar Toolkit.jar db archive -m 128 #4. specify optimization only when Manifest exceeds 128M ``` @@ -31,38 +30,38 @@ Demo: DB convert provides a helper which can convert LevelDB data to RocksDB data, parameters are compatible with previous `DBConvert`. -Parameter explanation: +### Available parameters: -- ``: Input path for leveldb. Default: output-directory/database -- ``: Output path for rocksdb. Default: output-directory-dst/database -- `--safe`: In safe mode, read data from leveldb then put rocksdb, it's a very time-consuming procedure. If not, just change engine.properties from leveldb to rocksdb,rocksdb - is compatible with leveldb for current version.This may not be the case in the future.Default: false -- `-h | --help`: provide the help info +- ``: Input path for leveldb, default: output-directory/database. +- ``: Output path for rocksdb, default: output-directory-dst/database. +- `--safe`: In safe mode, read data from leveldb then put into rocksdb, it's a very time-consuming procedure. If not, just change engine.properties from leveldb to rocksdb, rocksdb + is compatible with leveldb for the current version. This may not be the case in the future, default: false. +- `-h | --help`: Provide the help info. -Demo: +### Examples: ```shell script # full command java -jar Toolkit.jar db convert [-h] [--safe] # examples - java -jar Toolkit.jar db convert output-directory/database /tmp/databse + java -jar Toolkit.jar db convert output-directory/database /tmp/database ``` ## DB Lite -DB Lite provides lite database, parameters are compatible with previous `LiteFullNodeTool`. +DB lite provides lite database, parameters are compatible with previous `LiteFullNodeTool`. -Parameter explanation: +### Available parameters: -- `-o | --operate`: [split,merge]. Default: split. -- `-t | --type`: only used with operate=split: [snapshot,history]. Default: snapshot. -- `-fn | --fn-data-path`: the database path to be split or merged. -- `-ds | --dataset-path`: when operation is `split`,`dataset-path` is the path that store the `snapshot` or `history`,when - operation is `split`,`dataset-path` is the `history` data path. -- `-h | --help`: provide the help info +- `-o | --operate`: [split,merge], default: split. +- `-t | --type`: Only used with operate=split: [snapshot,history], default: snapshot. +- `-fn | --fn-data-path`: The database path to be split or merged. +- `-ds | --dataset-path`: When operation is `split`,`dataset-path` is the path that store the `snapshot` or `history`, when + operation is `split`, `dataset-path` is the `history` data path. +- `-h | --help`: Provide the help info. -Demo: +### Examples: ```shell script # full command @@ -78,17 +77,20 @@ Demo: ## DB Move -DB Move provides a helper to move some dbs to pre-set new path. For example move `block`, `transactionRetStore` or `transactionHistoryStore` to HDD,reduce storage expenses +DB move provides a helper to move some dbs to a pre-set new path. For example move `block`, `transactionRetStore` or `transactionHistoryStore` to HDD for reducing storage expenses. -Parameter explanation: +### Available parameters: - `-c | --config`: config file. Default: config.conf. - `-d | --database-directory`: database directory path. Default: output-directory. - `-h | --help`: provide the help info -Demo: +### Examples: + +Take the example of moving `block` and `trans`. -Take the example of moving `block` and `trans` + +Set path for `block` and `trans`. ```conf storage { @@ -106,10 +108,11 @@ storage { ...... } ``` - +Execute move command. ```shell script # full command java -jar Toolkit.jar db mv [-h] [-c=] [-d=] # examples java -jar Toolkit.jar db mv -c main_net_config.conf -d /data/tron/output-directory -``` \ No newline at end of file +``` + From 7628510faa3c9c79a5084b339a6d857bc15e79f4 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 13 Dec 2022 10:39:27 +0800 Subject: [PATCH 0457/1197] fix(test): relieve JVM heap stress 1. release thread when spring bean is destroyed 2. reduce the bloom filter initial size for trans-cache when running test 3. set enough memory in the project's gradle.properties --- .../java/org/tron/core/db2/core/SnapshotManager.java | 12 ++++++++++++ .../org/tron/consensus/pbft/PbftMessageHandle.java | 12 ++++++++++++ .../main/java/org/tron/core/net/TronNetDelegate.java | 12 ++++++++++++ framework/src/test/resources/config-test.conf | 4 ++++ gradle.properties | 2 ++ 5 files changed, 42 insertions(+) create mode 100644 gradle.properties diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java index 3fb3176d0e4..ab953fae932 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java @@ -24,6 +24,7 @@ import java.util.concurrent.locks.LockSupport; import java.util.stream.Collectors; import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @@ -116,6 +117,17 @@ public void init() { exitThread.start(); } + @PreDestroy + public void close() { + try { + exitThread.interrupt(); + // help GC + exitThread = null; + } catch (Exception e) { + logger.warn("exitThread interrupt error", e); + } + } + public static String simpleDecode(byte[] bytes) { byte[] lengthBytes = Arrays.copyOf(bytes, 4); int length = Ints.fromByteArray(lengthBytes); diff --git a/consensus/src/main/java/org/tron/consensus/pbft/PbftMessageHandle.java b/consensus/src/main/java/org/tron/consensus/pbft/PbftMessageHandle.java index 978f7aa127a..f2ef7b43ef0 100644 --- a/consensus/src/main/java/org/tron/consensus/pbft/PbftMessageHandle.java +++ b/consensus/src/main/java/org/tron/consensus/pbft/PbftMessageHandle.java @@ -19,6 +19,7 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -79,6 +80,17 @@ public void init() { start(); } + @PreDestroy + public void close() { + try { + timer.cancel(); + // help GC + timer = null; + } catch (Exception e) { + logger.warn("pbft-timer cancel error", e); + } + } + public List getSrMinerList() { return Param.getInstance().getMiners().stream() .filter(miner -> chainBaseManager.getWitnesses().contains(miner.getWitnessAddress())) diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index eafa9ff3766..a531a0d50af 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -10,6 +10,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @@ -114,6 +115,17 @@ public void init() { hitThread.start(); } + @PreDestroy + public void close() { + try { + hitThread.interrupt(); + // help GC + hitThread = null; + } catch (Exception e) { + logger.warn("hitThread interrupt error", e); + } + } + public Collection getActivePeer() { return TronNetService.getPeers(); } diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index 886438cac57..7a72a99bfba 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -63,6 +63,10 @@ storage { needToUpdateAsset = false + # the estimated number of block transactions (default 1000, min 100, max 10000). + # so the total number of cached transactions is 65536 * txCache.estimatedTransactions + txCache.estimatedTransactions = 50 + } node.discovery = { diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000000..031a8cddc89 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.parallel=true +org.gradle.jvmargs=-Xms1g From de45d6ce8a73d865a3a6db90b6c6d07048388058 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Wed, 14 Dec 2022 12:00:16 +0800 Subject: [PATCH 0458/1197] feat(version): change the block version --- common/src/main/java/org/tron/core/config/Parameter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index 24fef8f84f6..16517f4664b 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -21,6 +21,7 @@ public enum ForkBlockVersionEnum { VERSION_4_5(24, 1596780000000L, 80), VERSION_4_6(25, 1596780000000L, 80), VERSION_4_7(26, 1596780000000L, 80); + // if add a version, modify BLOCK_VERSION simultaneously @Getter private int value; @@ -68,7 +69,7 @@ public class ChainConstant { public static final int SINGLE_REPEAT = 1; public static final int BLOCK_FILLED_SLOTS_NUMBER = 128; public static final int MAX_FROZEN_NUMBER = 1; - public static final int BLOCK_VERSION = 25; + public static final int BLOCK_VERSION = 26; public static final long FROZEN_PERIOD = 86_400_000L; public static final long DELEGATE_PERIOD = 3 * 86_400_000L; public static final long TRX_PRECISION = 1000_000L; From 2613092d51209afd923e817891b89f3f09934493 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 15 Dec 2022 15:46:31 +0800 Subject: [PATCH 0459/1197] feat(net): turn off log printing of transaction message --- .../main/java/org/tron/core/net/P2pEventHandlerImpl.java | 6 ++++-- .../main/java/org/tron/core/net/peer/PeerConnection.java | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java index 6a164d774da..2da01fe929f 100644 --- a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java +++ b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java @@ -136,8 +136,10 @@ private void processMessage(PeerConnection peer, byte[] data) { msg = TronMessageFactory.create(data); type = msg.getType(); peer.getPeerStatistics().messageStatistics.addTcpInMessage(msg); - logger.info("Receive message from peer: {}, {}", - peer.getInetSocketAddress(), msg); + if (PeerConnection.needToLog(msg)) { + logger.info("Receive message from peer: {}, {}", + peer.getInetSocketAddress(), msg); + } switch (type) { case P2P_PING: case P2P_PONG: diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index 260b82747f4..a433ad43bd8 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -264,7 +264,7 @@ private void processDisconnect(Protocol.ReasonCode reason) { reason.name().toLowerCase(Locale.ROOT)); } - private boolean needToLog(Message msg) { + public static boolean needToLog(Message msg) { if (msg instanceof PingMessage || msg instanceof PongMessage || msg instanceof TransactionsMessage From 22f8a7e9f46379d9f050700b7c7fc73b691643a8 Mon Sep 17 00:00:00 2001 From: morgan Date: Fri, 16 Dec 2022 19:28:16 +0800 Subject: [PATCH 0460/1197] feat(db): optimize the default snapshot flush speed 1. optimize the default snapshot flush speed --- .../src/main/java/org/tron/core/db2/core/SnapshotManager.java | 1 - common/src/main/java/org/tron/core/config/args/Storage.java | 2 +- framework/src/main/java/org/tron/core/db/Manager.java | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java index ab953fae932..fe59a2737dd 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java @@ -49,7 +49,6 @@ @Slf4j(topic = "DB") public class SnapshotManager implements RevokingDatabase { - public static final int DEFAULT_MAX_FLUSH_COUNT = 500; public static final int DEFAULT_MIN_FLUSH_COUNT = 1; private static final int DEFAULT_STACK_MAX_SIZE = 256; private static final long ONE_MINUTE_MILLS = 60*1000L; diff --git a/common/src/main/java/org/tron/core/config/args/Storage.java b/common/src/main/java/org/tron/core/config/args/Storage.java index ce4cc6865d3..778d4d0141c 100644 --- a/common/src/main/java/org/tron/core/config/args/Storage.java +++ b/common/src/main/java/org/tron/core/config/args/Storage.java @@ -90,7 +90,7 @@ public class Storage { private static final int DEFAULT_CHECKPOINT_VERSION = 1; private static final boolean DEFAULT_CHECKPOINT_SYNC = true; private static final int DEFAULT_ESTIMATED_TRANSACTIONS = 1000; - private static final int DEFAULT_SNAPSHOT_MAX_FLUSH_COUNT = 500; + private static final int DEFAULT_SNAPSHOT_MAX_FLUSH_COUNT = 1; private Config storage; /** diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 060a2db5de2..27c5cc30fe9 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -964,12 +964,12 @@ private void applyBlock(BlockCapsule block, List txs) revokingStore.setMaxFlushCount(maxFlushCount); if (Args.getInstance().getShutdownBlockTime() != null && Args.getInstance().getShutdownBlockTime().getNextValidTimeAfter( - new Date(block.getTimeStamp() - SnapshotManager.DEFAULT_MAX_FLUSH_COUNT * 1000 * 3)) + new Date(block.getTimeStamp() - maxFlushCount * 1000 * 3)) .compareTo(new Date(block.getTimeStamp())) <= 0) { revokingStore.setMaxFlushCount(SnapshotManager.DEFAULT_MIN_FLUSH_COUNT); } if (latestSolidityNumShutDown > 0 && latestSolidityNumShutDown - block.getNum() - <= SnapshotManager.DEFAULT_MAX_FLUSH_COUNT) { + <= maxFlushCount) { revokingStore.setMaxFlushCount(SnapshotManager.DEFAULT_MIN_FLUSH_COUNT); } } else { From 1cb32fc263f9f1c9f9486e7956b282051d24f157 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 15 Dec 2022 21:15:24 +0800 Subject: [PATCH 0461/1197] feat(toolkit): add db copy --- plugins/README.md | 19 +++ .../src/main/java/org/tron/plugins/Db.java | 3 +- .../main/java/org/tron/plugins/DbCopy.java | 160 ++++++++++++++++++ .../main/java/org/tron/plugins/DbLite.java | 3 +- 4 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 plugins/src/main/java/org/tron/plugins/DbCopy.java diff --git a/plugins/README.md b/plugins/README.md index 584619af395..e2458b7e9a6 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -47,6 +47,25 @@ DB convert provides a helper which can convert LevelDB data to RocksDB data, par java -jar Toolkit.jar db convert output-directory/database /tmp/database ``` +## DB Copy + +DB copy provides a helper which can copy LevelDB or RocksDB data quickly on the same file systems by creating hard links. + +### Available parameters: + +- ``: Source path for database. Default: output-directory/database +- ``: Output path for database. Default: output-directory-cp/database +- `-h | --help`: provide the help info + +### Examples: + +```shell script +# full command + java -jar Toolkit.jar db cp [-h] +# examples + java -jar Toolkit.jar db cp output-directory/database /tmp/databse +``` + ## DB Lite diff --git a/plugins/src/main/java/org/tron/plugins/Db.java b/plugins/src/main/java/org/tron/plugins/Db.java index e7296a2cbc5..c67c838a3d6 100644 --- a/plugins/src/main/java/org/tron/plugins/Db.java +++ b/plugins/src/main/java/org/tron/plugins/Db.java @@ -10,7 +10,8 @@ DbMove.class, DbArchive.class, DbConvert.class, - DbLite.class + DbLite.class, + DbCopy.class }, commandListHeading = "%nCommands:%n%nThe most commonly used db commands are:%n" ) diff --git a/plugins/src/main/java/org/tron/plugins/DbCopy.java b/plugins/src/main/java/org/tron/plugins/DbCopy.java new file mode 100644 index 00000000000..7558d764cd4 --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/DbCopy.java @@ -0,0 +1,160 @@ +package org.tron.plugins; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.Callable; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import me.tongfei.progressbar.ProgressBar; +import org.tron.plugins.utils.DBUtils; +import org.tron.plugins.utils.FileUtils; +import picocli.CommandLine; + + +@Slf4j(topic = "copy") +@CommandLine.Command(name = "cp", aliases = "copy", + description = "Quick copy leveldb or rocksdb data.", + exitCodeListHeading = "Exit Codes:%n", + exitCodeList = { + "0:Successful", + "n:Internal error: exception occurred,please check toolkit.log"}) +public class DbCopy implements Callable { + + + @CommandLine.Spec + CommandLine.Model.CommandSpec spec; + @CommandLine.Parameters(index = "0", defaultValue = "output-directory/database", + description = "Input path. Default: ${DEFAULT-VALUE}") + private File src; + @CommandLine.Parameters(index = "1", defaultValue = "output-directory-cp/database", + description = "Output path. Default: ${DEFAULT-VALUE}") + private File dest; + + @CommandLine.Option(names = {"-h", "--help"}) + private boolean help; + + + @Override + public Integer call() throws Exception { + if (help) { + spec.commandLine().usage(System.out); + return 0; + } + if (dest.exists()) { + logger.info(" {} exist, please delete it first.", dest); + spec.commandLine().getErr().println(spec.commandLine().getColorScheme() + .errorText(String.format("%s exist, please delete it first.", dest))); + return 402; + } + if (!src.exists()) { + logger.info(" {} does not exist.", src); + spec.commandLine().getErr().println(spec.commandLine().getColorScheme() + .errorText(String.format("%s does not exist.", src))); + return 404; + } + + if (!src.isDirectory()) { + logger.info(" {} is not a directory.", src); + spec.commandLine().getErr().println(spec.commandLine().getColorScheme() + .errorText(String.format("%s is not a directory.", src))); + return 403; + } + + List files = Arrays.stream(Objects.requireNonNull(src.listFiles())) + .filter(File::isDirectory) + .filter(e -> !DBUtils.CHECKPOINT_DB_V2.equals(e.getName())) + .collect(Collectors.toList()); + + // add checkpoint v2 convert + File cpV2Dir = new File(Paths.get(src.toString(), DBUtils.CHECKPOINT_DB_V2).toString()); + List cpList = new ArrayList<>(); + if (cpV2Dir.exists()) { + cpList = Arrays.stream(Objects.requireNonNull(cpV2Dir.listFiles())) + .filter(File::isDirectory) + .collect(Collectors.toList()); + } + + if (files.isEmpty()) { + logger.info("{} does not contain any database.", src); + spec.commandLine().getOut().format("%s does not contain any database.", src).println(); + return 0; + } + final long time = System.currentTimeMillis(); + List services = new ArrayList<>(); + files.forEach(f -> services.add( + new DbCopier(src.getPath(), dest.getPath(), f.getName()))); + cpList.forEach(f -> services.add( + new DbCopier( + Paths.get(src.getPath(), DBUtils.CHECKPOINT_DB_V2).toString(), + Paths.get(dest.getPath(), DBUtils.CHECKPOINT_DB_V2).toString(), + f.getName()))); + List fails = ProgressBar.wrap(services.stream(), "copy task").parallel().map( + dbCopier -> { + try { + return dbCopier.doCopy() ? null : dbCopier.name(); + } catch (Exception e) { + logger.error("{}", e); + spec.commandLine().getErr().println(spec.commandLine().getColorScheme() + .errorText(e.getMessage())); + return dbCopier.name(); + } + }).filter(Objects::nonNull).collect(Collectors.toList()); + // copy info.properties if lite need + Arrays.stream(Objects.requireNonNull(src.listFiles())) + .filter(File::isFile).forEach(f -> FileUtils.copy(Paths.get(src.toString(), f.getName()), + Paths.get(dest.toString(), f.getName()))); + long during = (System.currentTimeMillis() - time) / 1000; + spec.commandLine().getOut().format("copy db done, fails: %s, take %d s.", + fails, during).println(); + logger.info("database copy use {} seconds total, fails: {}.", during, fails); + return fails.size(); + } + + interface Copier { + + boolean doCopy(); + + String name(); + } + + static class DbCopier implements Copier { + private final String srcDir; + private final String dstDir; + private final String dbName; + private final Path srcDbPath; + private final Path dstDbPath; + + public DbCopier(String srcDir, String dstDir, String name) { + this.srcDir = srcDir; + this.dstDir = dstDir; + this.dbName = name; + this.srcDbPath = Paths.get(this.srcDir, name); + this.dstDbPath = Paths.get(this.dstDir, name); + } + + @Override + public boolean doCopy() { + File srcDb = srcDbPath.toFile(); + if (!srcDb.exists()) { + logger.info(" {} does not exist.", srcDb); + return true; + } + FileUtils.createDirIfNotExists(dstDir); + logger.info("Copy database {} start", this.dbName); + FileUtils.copyDir(Paths.get(srcDir), Paths.get(dstDir), dbName); + logger.info("Copy database {} end", this.dbName); + return true; + } + + @Override + public String name() { + return dbName; + } + } + +} diff --git a/plugins/src/main/java/org/tron/plugins/DbLite.java b/plugins/src/main/java/org/tron/plugins/DbLite.java index 51b588bf9b5..c4ea5872a51 100644 --- a/plugins/src/main/java/org/tron/plugins/DbLite.java +++ b/plugins/src/main/java/org/tron/plugins/DbLite.java @@ -591,8 +591,7 @@ private void mergeBak2Database(String liteDir, BlockNumInfo blockNumInfo) throws } else { iterator.seek(head); } - ProgressBar.wrap(iterator, dbName) - .forEachRemaining(e -> destDb.put(e.getKey(), e.getValue())); + iterator.forEachRemaining(e -> destDb.put(e.getKey(), e.getValue())); } } catch (IOException | RocksDBException e) { throw new RuntimeException(e); From 5ac8f53dd42b64bbe45b086e525dcf3aa8e73315 Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 19 Dec 2022 10:51:28 +0800 Subject: [PATCH 0462/1197] fix(tvm,stakeV2): origin can not exist because of create* opcode and suicide --- chainbase/src/main/java/org/tron/core/db/TransactionTrace.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java index bf00c70e4e5..c879d477ad8 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java @@ -250,7 +250,7 @@ public void pay() throws BalanceInsufficientException { && receipt.getReceipt().getResult().equals(contractResult.SUCCESS)) { // just fo caller is not origin, we set the related field for origin account - if (!caller.getAddress().equals(origin.getAddress())) { + if (origin != null && !caller.getAddress().equals(origin.getAddress())) { long originPrevUsage = receipt.getOriginEnergyUsage() * receipt.getOriginEnergyWindowSize(); long originRepayUsage = (receipt.getOriginEnergyMergedUsage() - origin.getEnergyUsage()) * origin.getWindowSize(Common.ResourceCode.ENERGY); From 8274b7b817bf8b6263f0d957cc640a5404eb3ef9 Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 19 Dec 2022 16:27:12 +0800 Subject: [PATCH 0463/1197] OTW --- .../org/tron/core/vm/OperationActions.java | 16 +++++---- .../DelegateResourceProcessor.java | 33 ++++++++++------- .../param/DelegateResourceParam.java | 10 ++++++ .../org/tron/core/vm/program/Program.java | 36 ++++++++++--------- 4 files changed, 59 insertions(+), 36 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index 9895b24910f..1166696e05c 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -1,17 +1,18 @@ package org.tron.core.vm; -import static org.tron.common.crypto.Hash.sha3; -import static org.tron.common.utils.ByteUtil.EMPTY_BYTE_ARRAY; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; import org.tron.common.runtime.vm.DataWord; import org.tron.common.runtime.vm.LogInfo; import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.program.Program; import org.tron.core.vm.program.Stack; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +import static org.tron.common.crypto.Hash.sha3; +import static org.tron.common.utils.ByteUtil.EMPTY_BYTE_ARRAY; + public class OperationActions { private static final BigInteger _32_ = BigInteger.valueOf(32); @@ -821,8 +822,9 @@ public static void delegateResourceAction(Program program) { DataWord resourceType = program.stackPop(); DataWord delegateBalance = program.stackPop(); DataWord receiverAddress = program.stackPop(); + DataWord lock = program.stackPop(); - boolean result = program.delegateResource(receiverAddress, delegateBalance, resourceType); + boolean result = program.delegateResource(receiverAddress, delegateBalance, resourceType, lock); program.stackPush(result ? DataWord.ONE() : DataWord.ZERO()); program.step(); } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index 3e06ba3a9c4..ff62969fe67 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -1,11 +1,6 @@ package org.tron.core.vm.nativecontract; -import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; -import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; - import com.google.protobuf.ByteString; -import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.tron.common.utils.DecodeUtil; @@ -22,6 +17,13 @@ import org.tron.core.vm.repository.Repository; import org.tron.protos.Protocol; +import java.util.Arrays; + +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + @Slf4j(topic = "VMProcessor") public class DelegateResourceProcessor { @@ -71,8 +73,8 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra } break; case ENERGY: { - EnergyProcessor processor = - new EnergyProcessor(dynamicStore, ChainBaseManager.getInstance().getAccountStore()); + EnergyProcessor processor = + new EnergyProcessor(dynamicStore, ChainBaseManager.getInstance().getAccountStore()); processor.updateUsage(ownerCapsule); long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) @@ -123,19 +125,20 @@ public void execute(DelegateResourceParam param, Repository repo) { AccountCapsule ownerCapsule = repo.getAccount(param.getOwnerAddress()); long delegateBalance = param.getDelegateBalance(); byte[] receiverAddress = param.getReceiverAddress(); + boolean lock = param.isLock(); // delegate resource to receiver switch (param.getResourceType()) { case BANDWIDTH: delegateResource(ownerAddress, receiverAddress, true, - delegateBalance, repo); + delegateBalance, repo, lock); ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(delegateBalance); ownerCapsule.addFrozenBalanceForBandwidthV2(-delegateBalance); break; case ENERGY: delegateResource(ownerAddress, receiverAddress, false, - delegateBalance, repo); + delegateBalance, repo, lock); ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(delegateBalance); ownerCapsule.addFrozenBalanceForEnergyV2(-delegateBalance); @@ -152,7 +155,8 @@ private void delegateResource( byte[] receiverAddress, boolean isBandwidth, long delegateBalance, - Repository repo) { + Repository repo, + boolean lock) { //modify DelegatedResourceStore byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, false); DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); @@ -161,10 +165,15 @@ private void delegateResource( ByteString.copyFrom(ownerAddress), ByteString.copyFrom(receiverAddress)); } + long expireTime = 0; + if (lock) { + expireTime = + repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp() + DELEGATE_PERIOD; + } if (isBandwidth) { - delegatedResourceCapsule.addFrozenBalanceForBandwidth(delegateBalance, 0); + delegatedResourceCapsule.addFrozenBalanceForBandwidth(delegateBalance, expireTime); } else { - delegatedResourceCapsule.addFrozenBalanceForEnergy(delegateBalance, 0); + delegatedResourceCapsule.addFrozenBalanceForEnergy(delegateBalance, expireTime); } //update Account for receiver diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/DelegateResourceParam.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/DelegateResourceParam.java index f7d897800b5..2f25239ebb2 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/DelegateResourceParam.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/DelegateResourceParam.java @@ -12,6 +12,8 @@ public class DelegateResourceParam { private Common.ResourceCode resourceType; + private boolean lock; + public byte[] getOwnerAddress() { return ownerAddress; } @@ -43,4 +45,12 @@ public Common.ResourceCode getResourceType() { public void setResourceType(Common.ResourceCode resourceType) { this.resourceType = resourceType; } + + public boolean isLock() { + return lock; + } + + public void setLock(boolean lock) { + this.lock = lock; + } } diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 7a800a0b412..967a2877225 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -1,22 +1,6 @@ package org.tron.core.vm.program; -import static java.lang.StrictMath.min; -import static java.lang.String.format; -import static org.apache.commons.lang3.ArrayUtils.EMPTY_BYTE_ARRAY; -import static org.apache.commons.lang3.ArrayUtils.getLength; -import static org.apache.commons.lang3.ArrayUtils.isEmpty; -import static org.apache.commons.lang3.ArrayUtils.isNotEmpty; -import static org.apache.commons.lang3.ArrayUtils.nullToEmpty; -import static org.tron.common.utils.ByteUtil.stripLeadingZeroes; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; - import com.google.protobuf.ByteString; -import java.math.BigInteger; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.map.LRUMap; @@ -92,6 +76,23 @@ import org.tron.protos.contract.SmartContractOuterClass.SmartContract; import org.tron.protos.contract.SmartContractOuterClass.SmartContract.Builder; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import static java.lang.StrictMath.min; +import static java.lang.String.format; +import static org.apache.commons.lang3.ArrayUtils.EMPTY_BYTE_ARRAY; +import static org.apache.commons.lang3.ArrayUtils.getLength; +import static org.apache.commons.lang3.ArrayUtils.isEmpty; +import static org.apache.commons.lang3.ArrayUtils.isNotEmpty; +import static org.apache.commons.lang3.ArrayUtils.nullToEmpty; +import static org.tron.common.utils.ByteUtil.stripLeadingZeroes; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + @Slf4j(topic = "VM") public class Program { @@ -2000,7 +2001,7 @@ public boolean cancelAllUnfreezeV2Action() { } public boolean delegateResource( - DataWord receiverAddress, DataWord delegateBalance, DataWord resourceType) { + DataWord receiverAddress, DataWord delegateBalance, DataWord resourceType, DataWord lock) { Repository repository = getContractState().newRepositoryChild(); byte[] owner = getContextAddress(); byte[] receiver = receiverAddress.toTronAddress(); @@ -2016,6 +2017,7 @@ public boolean delegateResource( param.setReceiverAddress(receiver); param.setDelegateBalance(delegateBalance.sValue().longValueExact()); param.setResourceType(parseResourceCodeV2(resourceType)); + param.setLock(lock.sValue().longValueExact() != 0); DelegateResourceProcessor processor = new DelegateResourceProcessor(); processor.validate(param, repository); From f3f0ae1742e1248f475e0c3d0c531d4c366e11a7 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 19 Dec 2022 16:42:30 +0800 Subject: [PATCH 0464/1197] fix(db): fix exceptional for auto-stop 1. Fix the scenario to trigger auto-stop when blockHeight and blockCount are set, and blockHeight < head. --- framework/src/main/java/org/tron/core/db/Manager.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 27c5cc30fe9..722bc9b981a 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -541,6 +541,13 @@ public void init() { long exitHeight = CommonParameter.getInstance().getShutdownBlockHeight(); long exitCount = CommonParameter.getInstance().getShutdownBlockCount(); + if (exitHeight > 0 && exitHeight < headNum) { + logger.info("ShutDownBlockHeight {} is less than headNum {}, reset it to -1.", + exitHeight, headNum); + CommonParameter.getInstance().setShutdownBlockHeight(-1); + exitHeight = -1; + } + if (exitCount > 0 && (exitHeight < 0 || exitHeight > headNum + exitCount)) { CommonParameter.getInstance().setShutdownBlockHeight(headNum + exitCount); } From d4ff6c254709a6235275c670072a4275d1b13ee0 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 19 Dec 2022 17:43:09 +0800 Subject: [PATCH 0465/1197] feat(net): optimize network module close logic --- .../src/main/java/org/tron/core/net/P2pEventHandlerImpl.java | 4 ++-- .../src/main/java/org/tron/core/net/peer/PeerConnection.java | 2 +- .../src/main/java/org/tron/core/net/peer/PeerManager.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java index 2da01fe929f..35ecd9e7144 100644 --- a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java +++ b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java @@ -137,8 +137,8 @@ private void processMessage(PeerConnection peer, byte[] data) { type = msg.getType(); peer.getPeerStatistics().messageStatistics.addTcpInMessage(msg); if (PeerConnection.needToLog(msg)) { - logger.info("Receive message from peer: {}, {}", - peer.getInetSocketAddress(), msg); + logger.info("Receive message from peer: {}, {}", + peer.getInetSocketAddress(), msg); } switch (type) { case P2P_PING: diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index a433ad43bd8..ae9f3169d6e 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -206,7 +206,7 @@ public String log() { + "remainNum:%d\n" + "syncChainRequested:%d\n" + "blockInProcess:%d\n", - channel.getInetAddress(), + channel.getInetSocketAddress(), (now - channel.getStartTime()) / Constant.ONE_THOUSAND, channel.getLatency(), fastForwardBlock != null ? fastForwardBlock.getNum() : blockBothHave.getNum(), diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java index dfcb0c0e599..8a402438c86 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java @@ -43,11 +43,11 @@ public static void init() { public static void close() { try { - peers.forEach(p -> { + for (PeerConnection p : new ArrayList<>(peers)) { if (!p.isDisconnect()) { p.getChannel().close(); } - }); + } executor.shutdownNow(); } catch (Exception e) { logger.error("Peer manager shutdown failed", e); From 4014bf4d5c887b6299c830567e415ad4d30f92d1 Mon Sep 17 00:00:00 2001 From: Liulei Date: Tue, 20 Dec 2022 18:32:09 +0800 Subject: [PATCH 0466/1197] feat(freezeV2): merge stake 2.0 new features --- .../actuator/DelegateResourceActuator.java | 122 ++++----- .../actuator/FreezeBalanceV2Actuator.java | 118 ++++----- .../actuator/UnDelegateResourceActuator.java | 245 +++++++++--------- .../actuator/UnfreezeBalanceV2Actuator.java | 171 ++++++------ .../WithdrawExpireUnfreezeActuator.java | 81 +++--- .../org/tron/core/vm/OperationActions.java | 2 +- .../DelegateResourceProcessor.java | 26 +- .../FreezeBalanceV2Processor.java | 22 +- .../UnDelegateResourceProcessor.java | 92 +++++-- .../UnfreezeBalanceV2Processor.java | 69 +++-- .../tron/core/vm/program/ContractState.java | 20 ++ .../tron/core/vm/repository/Repository.java | 7 + .../core/vm/repository/RepositoryImpl.java | 92 +++++++ .../DelegatedResourceAccountIndexStore.java | 4 + 14 files changed, 630 insertions(+), 441 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index f91c147e3ee..891c6505eda 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -1,13 +1,7 @@ package org.tron.core.actuator; -import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; -import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; - import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; -import java.util.Arrays; -import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.tron.common.utils.DecodeUtil; @@ -29,6 +23,13 @@ import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.BalanceContract.DelegateResourceContract; +import java.util.Arrays; +import java.util.Objects; + +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; +import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + @Slf4j(topic = "actuator") public class DelegateResourceActuator extends AbstractActuator { @@ -36,60 +37,6 @@ public DelegateResourceActuator() { super(ContractType.DelegateResourceContract, DelegateResourceContract.class); } - @Override - public boolean execute(Object result) throws ContractExeException { - TransactionResultCapsule ret = (TransactionResultCapsule) result; - if (Objects.isNull(ret)) { - throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); - } - - long fee = calcFee(); - final DelegateResourceContract delegateResourceContract; - AccountStore accountStore = chainBaseManager.getAccountStore(); - try { - delegateResourceContract = any.unpack(DelegateResourceContract.class); - } catch (InvalidProtocolBufferException e) { - logger.debug(e.getMessage(), e); - ret.setStatus(fee, code.FAILED); - throw new ContractExeException(e.getMessage()); - } - - AccountCapsule ownerCapsule = accountStore - .get(delegateResourceContract.getOwnerAddress().toByteArray()); - - long delegateBalance = delegateResourceContract.getBalance(); - boolean lock = delegateResourceContract.getLock(); - byte[] ownerAddress = delegateResourceContract.getOwnerAddress().toByteArray(); - byte[] receiverAddress = delegateResourceContract.getReceiverAddress().toByteArray(); - - // delegate resource to receiver - switch (delegateResourceContract.getResource()) { - case BANDWIDTH: - delegateResource(ownerAddress, receiverAddress, true, - delegateBalance, lock); - - ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(delegateBalance); - ownerCapsule.addFrozenBalanceForBandwidthV2(-delegateBalance); - break; - case ENERGY: - delegateResource(ownerAddress, receiverAddress, false, - delegateBalance, lock); - - ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(delegateBalance); - ownerCapsule.addFrozenBalanceForEnergyV2(-delegateBalance); - break; - default: - logger.debug("Resource Code Error."); - } - - accountStore.put(ownerCapsule.createDbKey(), ownerCapsule); - - ret.setStatus(fee, code.SUCESS); - - return true; - } - - @Override public boolean validate() throws ContractValidateException { if (this.any == null) { @@ -181,7 +128,7 @@ public boolean validate() throws ContractValidateException { if (ownerCapsule.getFrozenV2BalanceForEnergy() - remainEnergyUsage < delegateBalance) { throw new ContractValidateException( - "delegateBalance must be less than available FreezeEnergyV2 balance"); + "delegateBalance must be less than available FreezeEnergyV2 balance"); } } break; @@ -218,6 +165,59 @@ public boolean validate() throws ContractValidateException { return true; } + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + + long fee = calcFee(); + final DelegateResourceContract delegateResourceContract; + AccountStore accountStore = chainBaseManager.getAccountStore(); + try { + delegateResourceContract = any.unpack(DelegateResourceContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + + AccountCapsule ownerCapsule = accountStore + .get(delegateResourceContract.getOwnerAddress().toByteArray()); + + long delegateBalance = delegateResourceContract.getBalance(); + boolean lock = delegateResourceContract.getLock(); + byte[] ownerAddress = delegateResourceContract.getOwnerAddress().toByteArray(); + byte[] receiverAddress = delegateResourceContract.getReceiverAddress().toByteArray(); + + // delegate resource to receiver + switch (delegateResourceContract.getResource()) { + case BANDWIDTH: + delegateResource(ownerAddress, receiverAddress, true, + delegateBalance, lock); + + ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(delegateBalance); + ownerCapsule.addFrozenBalanceForBandwidthV2(-delegateBalance); + break; + case ENERGY: + delegateResource(ownerAddress, receiverAddress, false, + delegateBalance, lock); + + ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(delegateBalance); + ownerCapsule.addFrozenBalanceForEnergyV2(-delegateBalance); + break; + default: + logger.debug("Resource Code Error."); + } + + accountStore.put(ownerCapsule.createDbKey(), ownerCapsule); + + ret.setStatus(fee, code.SUCESS); + + return true; + } + @Override public ByteString getOwnerAddress() throws InvalidProtocolBufferException { return any.unpack(DelegateResourceContract.class).getOwnerAddress(); diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java index 90b03e43e1a..cde31e6ebf5 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java @@ -29,65 +29,6 @@ public FreezeBalanceV2Actuator() { super(ContractType.FreezeBalanceV2Contract, FreezeBalanceV2Contract.class); } - @Override - public boolean execute(Object result) throws ContractExeException { - TransactionResultCapsule ret = (TransactionResultCapsule) result; - if (Objects.isNull(ret)) { - throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); - } - - long fee = calcFee(); - final FreezeBalanceV2Contract freezeBalanceV2Contract; - AccountStore accountStore = chainBaseManager.getAccountStore(); - DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); - try { - freezeBalanceV2Contract = any.unpack(FreezeBalanceV2Contract.class); - } catch (InvalidProtocolBufferException e) { - logger.debug(e.getMessage(), e); - ret.setStatus(fee, code.FAILED); - throw new ContractExeException(e.getMessage()); - } - AccountCapsule accountCapsule = accountStore.get(freezeBalanceV2Contract.getOwnerAddress().toByteArray()); - - if (dynamicStore.supportAllowNewResourceModel() - && accountCapsule.oldTronPowerIsNotInitialized()) { - accountCapsule.initializeOldTronPower(); - } - - long newBalance = accountCapsule.getBalance() - freezeBalanceV2Contract.getFrozenBalance(); - long frozenBalance = freezeBalanceV2Contract.getFrozenBalance(); - - switch (freezeBalanceV2Contract.getResource()) { - case BANDWIDTH: - long oldNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; - accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); - long newNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; - dynamicStore.addTotalNetWeight(newNetWeight - oldNetWeight); - break; - case ENERGY: - long oldEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; - accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); - long newEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; - dynamicStore.addTotalEnergyWeight(newEnergyWeight - oldEnergyWeight); - break; - case TRON_POWER: - long oldTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; - accountCapsule.addFrozenForTronPowerV2(frozenBalance); - long newTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; - dynamicStore.addTotalTronPowerWeight(newTPWeight - oldTPWeight); - break; - default: - logger.debug("Resource Code Error."); - } - - accountCapsule.setBalance(newBalance); - accountStore.put(accountCapsule.createDbKey(), accountCapsule); - - ret.setStatus(fee, code.SUCESS); - - return true; - } - @Override public boolean validate() throws ContractValidateException { if (this.any == null) { @@ -163,6 +104,65 @@ public boolean validate() throws ContractValidateException { return true; } + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + + long fee = calcFee(); + final FreezeBalanceV2Contract freezeBalanceV2Contract; + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + try { + freezeBalanceV2Contract = any.unpack(FreezeBalanceV2Contract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + AccountCapsule accountCapsule = accountStore.get(freezeBalanceV2Contract.getOwnerAddress().toByteArray()); + + if (dynamicStore.supportAllowNewResourceModel() + && accountCapsule.oldTronPowerIsNotInitialized()) { + accountCapsule.initializeOldTronPower(); + } + + long newBalance = accountCapsule.getBalance() - freezeBalanceV2Contract.getFrozenBalance(); + long frozenBalance = freezeBalanceV2Contract.getFrozenBalance(); + + switch (freezeBalanceV2Contract.getResource()) { + case BANDWIDTH: + long oldNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + long newNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; + dynamicStore.addTotalNetWeight(newNetWeight - oldNetWeight); + break; + case ENERGY: + long oldEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; + accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); + long newEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; + dynamicStore.addTotalEnergyWeight(newEnergyWeight - oldEnergyWeight); + break; + case TRON_POWER: + long oldTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; + accountCapsule.addFrozenForTronPowerV2(frozenBalance); + long newTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; + dynamicStore.addTotalTronPowerWeight(newTPWeight - oldTPWeight); + break; + default: + logger.debug("Resource Code Error."); + } + + accountCapsule.setBalance(newBalance); + accountStore.put(accountCapsule.createDbKey(), accountCapsule); + + ret.setStatus(fee, code.SUCESS); + + return true; + } + @Override public ByteString getOwnerAddress() throws InvalidProtocolBufferException { return any.unpack(FreezeBalanceV2Contract.class).getOwnerAddress(); diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index a99d462b61c..2f8149efc6f 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -1,14 +1,7 @@ package org.tron.core.actuator; -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; -import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; -import static org.tron.protos.contract.Common.ResourceCode.ENERGY; - import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; -import java.util.Arrays; -import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.tron.common.utils.DecodeUtil; @@ -28,6 +21,14 @@ import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.BalanceContract.UnDelegateResourceContract; +import java.util.Arrays; +import java.util.Objects; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; + @Slf4j(topic = "actuator") public class UnDelegateResourceActuator extends AbstractActuator { @@ -35,6 +36,121 @@ public UnDelegateResourceActuator() { super(ContractType.UnDelegateResourceContract, UnDelegateResourceContract.class); } + @Override + public boolean validate() throws ContractValidateException { + if (this.any == null) { + throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); + } + if (chainBaseManager == null) { + throw new ContractValidateException(ActuatorConstant.STORE_NOT_EXIST); + } + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore(); + if (!dynamicStore.supportDR()) { + throw new ContractValidateException("No support for resource delegate"); + } + + if (!dynamicStore.supportUnfreezeDelay()) { + throw new ContractValidateException("Not support unDelegate resource transaction," + + " need to be opened by the committee"); + } + + if (!this.any.is(UnDelegateResourceContract.class)) { + throw new ContractValidateException( + "contract type error, expected type [UnDelegateResourceContract], real type[" + any + .getClass() + "]"); + } + final UnDelegateResourceContract unDelegateResourceContract; + try { + unDelegateResourceContract = this.any.unpack(UnDelegateResourceContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + throw new ContractValidateException(e.getMessage()); + } + + byte[] ownerAddress = unDelegateResourceContract.getOwnerAddress().toByteArray(); + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + AccountCapsule ownerCapsule = accountStore.get(ownerAddress); + if (ownerCapsule == null) { + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + throw new ContractValidateException( + ACCOUNT_EXCEPTION_STR + readableOwnerAddress + "] does not exist"); + } + + byte[] receiverAddress = unDelegateResourceContract.getReceiverAddress().toByteArray(); + if (ArrayUtils.isEmpty(receiverAddress) || !DecodeUtil.addressValid(receiverAddress)) { + throw new ContractValidateException("Invalid receiverAddress"); + } + if (Arrays.equals(receiverAddress, ownerAddress)) { + throw new ContractValidateException( + "receiverAddress must not be the same as ownerAddress"); + } + + // TVM contract suicide can result in no receiving account + // AccountCapsule receiverCapsule = accountStore.get(receiverAddress); + // if (receiverCapsule == null) { + // String readableReceiverAddress = StringUtil.createReadableString(receiverAddress); + // throw new ContractValidateException( + // "Receiver Account[" + readableReceiverAddress + "] does not exist"); + // } + + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, false); + DelegatedResourceCapsule unlockResourceCapsule = delegatedResourceStore.get(key); + byte[] lockKey = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, true); + DelegatedResourceCapsule lockResourceCapsule = delegatedResourceStore.get(lockKey); + if (unlockResourceCapsule == null && lockResourceCapsule == null) { + throw new ContractValidateException( + "delegated Resource does not exist"); + } + + long unDelegateBalance = unDelegateResourceContract.getBalance(); + if (unDelegateBalance <= 0) { + throw new ContractValidateException("unDelegateBalance must be more than 0 TRX"); + } + switch (unDelegateResourceContract.getResource()) { + case BANDWIDTH: { + long delegateBalance = 0; + if (unlockResourceCapsule != null) { + delegateBalance += unlockResourceCapsule.getFrozenBalanceForBandwidth(); + } + if (lockResourceCapsule != null + && lockResourceCapsule.getExpireTimeForBandwidth() < now) { + delegateBalance += lockResourceCapsule.getFrozenBalanceForBandwidth(); + } + if (delegateBalance < unDelegateBalance) { + throw new ContractValidateException( + "insufficient delegatedFrozenBalance(BANDWIDTH), request=" + + unDelegateBalance + ", unlock_balance=" + delegateBalance); + } + } + break; + case ENERGY: { + long delegateBalance = 0; + if (unlockResourceCapsule != null) { + delegateBalance += unlockResourceCapsule.getFrozenBalanceForEnergy(); + } + if (lockResourceCapsule != null + && lockResourceCapsule.getExpireTimeForEnergy() < now) { + delegateBalance += lockResourceCapsule.getFrozenBalanceForEnergy(); + } + if (delegateBalance < unDelegateBalance) { + throw new ContractValidateException("insufficient delegateFrozenBalance(Energy), request=" + + unDelegateBalance + ", unlock_balance=" + delegateBalance); + } + } + break; + default: + throw new ContractValidateException( + "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + } + + return true; + } + @Override public boolean execute(Object result) throws ContractExeException { TransactionResultCapsule ret = (TransactionResultCapsule) result; @@ -195,121 +311,6 @@ public boolean execute(Object result) throws ContractExeException { return true; } - @Override - public boolean validate() throws ContractValidateException { - if (this.any == null) { - throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); - } - if (chainBaseManager == null) { - throw new ContractValidateException(ActuatorConstant.STORE_NOT_EXIST); - } - AccountStore accountStore = chainBaseManager.getAccountStore(); - DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); - DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore(); - if (!dynamicStore.supportDR()) { - throw new ContractValidateException("No support for resource delegate"); - } - - if (!dynamicStore.supportUnfreezeDelay()) { - throw new ContractValidateException("Not support unDelegate resource transaction," - + " need to be opened by the committee"); - } - - if (!this.any.is(UnDelegateResourceContract.class)) { - throw new ContractValidateException( - "contract type error, expected type [UnDelegateResourceContract], real type[" + any - .getClass() + "]"); - } - final UnDelegateResourceContract unDelegateResourceContract; - try { - unDelegateResourceContract = this.any.unpack(UnDelegateResourceContract.class); - } catch (InvalidProtocolBufferException e) { - logger.debug(e.getMessage(), e); - throw new ContractValidateException(e.getMessage()); - } - - byte[] ownerAddress = unDelegateResourceContract.getOwnerAddress().toByteArray(); - if (!DecodeUtil.addressValid(ownerAddress)) { - throw new ContractValidateException("Invalid address"); - } - AccountCapsule ownerCapsule = accountStore.get(ownerAddress); - if (ownerCapsule == null) { - String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); - throw new ContractValidateException( - ACCOUNT_EXCEPTION_STR + readableOwnerAddress + "] does not exist"); - } - - byte[] receiverAddress = unDelegateResourceContract.getReceiverAddress().toByteArray(); - if (ArrayUtils.isEmpty(receiverAddress) || !DecodeUtil.addressValid(receiverAddress)) { - throw new ContractValidateException("Invalid receiverAddress"); - } - if (Arrays.equals(receiverAddress, ownerAddress)) { - throw new ContractValidateException( - "receiverAddress must not be the same as ownerAddress"); - } - - // TVM contract suicide can result in no receiving account - // AccountCapsule receiverCapsule = accountStore.get(receiverAddress); - // if (receiverCapsule == null) { - // String readableReceiverAddress = StringUtil.createReadableString(receiverAddress); - // throw new ContractValidateException( - // "Receiver Account[" + readableReceiverAddress + "] does not exist"); - // } - - long now = dynamicStore.getLatestBlockHeaderTimestamp(); - byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, false); - DelegatedResourceCapsule unlockResourceCapsule = delegatedResourceStore.get(key); - byte[] lockKey = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, true); - DelegatedResourceCapsule lockResourceCapsule = delegatedResourceStore.get(lockKey); - if (unlockResourceCapsule == null && lockResourceCapsule == null) { - throw new ContractValidateException( - "delegated Resource does not exist"); - } - - long unDelegateBalance = unDelegateResourceContract.getBalance(); - if (unDelegateBalance <= 0) { - throw new ContractValidateException("unDelegateBalance must be more than 0 TRX"); - } - switch (unDelegateResourceContract.getResource()) { - case BANDWIDTH: { - long delegateBalance = 0; - if (unlockResourceCapsule != null) { - delegateBalance += unlockResourceCapsule.getFrozenBalanceForBandwidth(); - } - if (lockResourceCapsule != null - && lockResourceCapsule.getExpireTimeForBandwidth() < now) { - delegateBalance += lockResourceCapsule.getFrozenBalanceForBandwidth(); - } - if (delegateBalance < unDelegateBalance) { - throw new ContractValidateException( - "insufficient delegatedFrozenBalance(BANDWIDTH), request=" - + unDelegateBalance + ", unlock_balance=" + delegateBalance); - } - } - break; - case ENERGY: { - long delegateBalance = 0; - if (unlockResourceCapsule != null) { - delegateBalance += unlockResourceCapsule.getFrozenBalanceForEnergy(); - } - if (lockResourceCapsule != null - && lockResourceCapsule.getExpireTimeForEnergy() < now) { - delegateBalance += lockResourceCapsule.getFrozenBalanceForEnergy(); - } - if (delegateBalance < unDelegateBalance) { - throw new ContractValidateException("insufficient delegateFrozenBalance(Energy), request=" - + unDelegateBalance + ", unlock_balance=" + delegateBalance); - } - } - break; - default: - throw new ContractValidateException( - "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); - } - - return true; - } - @Override public ByteString getOwnerAddress() throws InvalidProtocolBufferException { return any.unpack(UnDelegateResourceContract.class).getOwnerAddress(); diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java index 53bcadc8bf9..fdceac098d2 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java @@ -1,19 +1,8 @@ package org.tron.core.actuator; -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; -import static org.tron.protos.contract.Common.ResourceCode; -import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; -import static org.tron.protos.contract.Common.ResourceCode.ENERGY; -import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; - import com.google.common.collect.Lists; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; @@ -35,6 +24,18 @@ import org.tron.protos.Protocol.Vote; import org.tron.protos.contract.BalanceContract.UnfreezeBalanceV2Contract; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; +import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; + @Slf4j(topic = "actuator") public class UnfreezeBalanceV2Actuator extends AbstractActuator { @@ -45,60 +46,6 @@ public UnfreezeBalanceV2Actuator() { super(ContractType.UnfreezeBalanceV2Contract, UnfreezeBalanceV2Contract.class); } - @Override - public boolean execute(Object result) throws ContractExeException { - TransactionResultCapsule ret = (TransactionResultCapsule) result; - if (Objects.isNull(ret)) { - throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); - } - - long fee = calcFee(); - final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract; - AccountStore accountStore = chainBaseManager.getAccountStore(); - DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); - MortgageService mortgageService = chainBaseManager.getMortgageService(); - try { - unfreezeBalanceV2Contract = any.unpack(UnfreezeBalanceV2Contract.class); - } catch (InvalidProtocolBufferException e) { - logger.debug(e.getMessage(), e); - ret.setStatus(fee, code.FAILED); - throw new ContractExeException(e.getMessage()); - } - byte[] ownerAddress = unfreezeBalanceV2Contract.getOwnerAddress().toByteArray(); - long now = dynamicStore.getLatestBlockHeaderTimestamp(); - - mortgageService.withdrawReward(ownerAddress); - - AccountCapsule accountCapsule = accountStore.get(ownerAddress); - long unfreezeAmount = this.unfreezeExpire(accountCapsule, now); - long unfreezeBalance = unfreezeBalanceV2Contract.getUnfreezeBalance(); - - if (dynamicStore.supportAllowNewResourceModel() - && accountCapsule.oldTronPowerIsNotInitialized()) { - accountCapsule.initializeOldTronPower(); - } - - ResourceCode freezeType = unfreezeBalanceV2Contract.getResource(); - - long expireTime = this.calcUnfreezeExpireTime(now); - accountCapsule.addUnfrozenV2List(freezeType, unfreezeBalance, expireTime); - - this.updateTotalResourceWeight(accountCapsule, unfreezeBalanceV2Contract, unfreezeBalance); - this.updateVote(accountCapsule, unfreezeBalanceV2Contract, ownerAddress); - - if (dynamicStore.supportAllowNewResourceModel() - && !accountCapsule.oldTronPowerIsInvalid()) { - accountCapsule.invalidateOldTronPower(); - } - - accountStore.put(ownerAddress, accountCapsule); - - ret.setUnfreezeAmount(unfreezeBalance); - ret.setWithdrawExpireAmount(unfreezeAmount); - ret.setStatus(fee, code.SUCESS); - return true; - } - @Override public boolean validate() throws ContractValidateException { if (this.any == null) { @@ -183,26 +130,6 @@ public boolean validate() throws ContractValidateException { return true; } - @Override - public ByteString getOwnerAddress() throws InvalidProtocolBufferException { - return any.unpack(UnfreezeBalanceV2Contract.class).getOwnerAddress(); - } - - @Override - public long calcFee() { - return 0; - } - - public boolean checkExistFrozenBalance(AccountCapsule accountCapsule, ResourceCode freezeType) { - List frozenV2List = accountCapsule.getFrozenV2List(); - for (FreezeV2 frozenV2 : frozenV2List) { - if (frozenV2.getType().equals(freezeType) && frozenV2.getAmount() > 0) { - return true; - } - } - return false; - } - public boolean checkUnfreezeBalance(AccountCapsule accountCapsule, final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract, ResourceCode freezeType) { @@ -225,6 +152,80 @@ public boolean checkUnfreezeBalance(AccountCapsule accountCapsule, return checkOk; } + public boolean checkExistFrozenBalance(AccountCapsule accountCapsule, ResourceCode freezeType) { + List frozenV2List = accountCapsule.getFrozenV2List(); + for (FreezeV2 frozenV2 : frozenV2List) { + if (frozenV2.getType().equals(freezeType) && frozenV2.getAmount() > 0) { + return true; + } + } + return false; + } + + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + + long fee = calcFee(); + final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract; + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + MortgageService mortgageService = chainBaseManager.getMortgageService(); + try { + unfreezeBalanceV2Contract = any.unpack(UnfreezeBalanceV2Contract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + byte[] ownerAddress = unfreezeBalanceV2Contract.getOwnerAddress().toByteArray(); + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + + mortgageService.withdrawReward(ownerAddress); + + AccountCapsule accountCapsule = accountStore.get(ownerAddress); + long unfreezeAmount = this.unfreezeExpire(accountCapsule, now); + long unfreezeBalance = unfreezeBalanceV2Contract.getUnfreezeBalance(); + + if (dynamicStore.supportAllowNewResourceModel() + && accountCapsule.oldTronPowerIsNotInitialized()) { + accountCapsule.initializeOldTronPower(); + } + + ResourceCode freezeType = unfreezeBalanceV2Contract.getResource(); + + long expireTime = this.calcUnfreezeExpireTime(now); + accountCapsule.addUnfrozenV2List(freezeType, unfreezeBalance, expireTime); + + this.updateTotalResourceWeight(accountCapsule, unfreezeBalanceV2Contract, unfreezeBalance); + this.updateVote(accountCapsule, unfreezeBalanceV2Contract, ownerAddress); + + if (dynamicStore.supportAllowNewResourceModel() + && !accountCapsule.oldTronPowerIsInvalid()) { + accountCapsule.invalidateOldTronPower(); + } + + accountStore.put(ownerAddress, accountCapsule); + + ret.setUnfreezeAmount(unfreezeBalance); + ret.setWithdrawExpireAmount(unfreezeAmount); + ret.setStatus(fee, code.SUCESS); + return true; + } + + @Override + public ByteString getOwnerAddress() throws InvalidProtocolBufferException { + return any.unpack(UnfreezeBalanceV2Contract.class).getOwnerAddress(); + } + + @Override + public long calcFee() { + return 0; + } + public long calcUnfreezeExpireTime(long now) { DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); long unfreezeDelayDays = dynamicStore.getUnfreezeDelayDays(); diff --git a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java index 0c547d2b5a3..decabdb7192 100755 --- a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java @@ -1,14 +1,8 @@ package org.tron.core.actuator; -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; - import com.google.common.math.LongMath; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; @@ -23,6 +17,13 @@ import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.BalanceContract.WithdrawExpireUnfreezeContract; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; + @Slf4j(topic = "actuator") public class WithdrawExpireUnfreezeActuator extends AbstractActuator { @@ -31,40 +32,6 @@ public WithdrawExpireUnfreezeActuator() { super(ContractType.WithdrawExpireUnfreezeContract, WithdrawExpireUnfreezeContract.class); } - @Override - public boolean execute(Object result) throws ContractExeException { - TransactionResultCapsule ret = (TransactionResultCapsule) result; - if (Objects.isNull(ret)) { - throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); - } - long fee = calcFee(); - AccountStore accountStore = chainBaseManager.getAccountStore(); - DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); - final WithdrawExpireUnfreezeContract withdrawExpireUnfreezeContract; - try { - withdrawExpireUnfreezeContract = any.unpack(WithdrawExpireUnfreezeContract.class); - } catch (InvalidProtocolBufferException e) { - logger.debug(e.getMessage(), e); - ret.setStatus(fee, code.FAILED); - throw new ContractExeException(e.getMessage()); - } - AccountCapsule accountCapsule = accountStore.get( - withdrawExpireUnfreezeContract.getOwnerAddress().toByteArray()); - long now = dynamicStore.getLatestBlockHeaderTimestamp(); - List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); - long totalWithdrawUnfreeze = getTotalWithdrawUnfreeze(unfrozenV2List, now); - accountCapsule.setInstance(accountCapsule.getInstance().toBuilder() - .setBalance(accountCapsule.getBalance() + totalWithdrawUnfreeze) - .build()); - List newUnFreezeList = getRemainWithdrawList(unfrozenV2List, now); - accountCapsule.clearUnfrozenV2(); - accountCapsule.addAllUnfrozenV2(newUnFreezeList); - accountStore.put(accountCapsule.createDbKey(), accountCapsule); - ret.setWithdrawExpireAmount(totalWithdrawUnfreeze); - ret.setStatus(fee, code.SUCESS); - return true; - } - @Override public boolean validate() throws ContractValidateException { if (Objects.isNull(this.any)) { @@ -129,6 +96,40 @@ private List getTotalWithdrawList(List unfrozenV2List, l && unfrozenV2.getUnfreezeExpireTime() <= now)).collect(Collectors.toList()); } + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + long fee = calcFee(); + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + final WithdrawExpireUnfreezeContract withdrawExpireUnfreezeContract; + try { + withdrawExpireUnfreezeContract = any.unpack(WithdrawExpireUnfreezeContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + AccountCapsule accountCapsule = accountStore.get( + withdrawExpireUnfreezeContract.getOwnerAddress().toByteArray()); + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); + long totalWithdrawUnfreeze = getTotalWithdrawUnfreeze(unfrozenV2List, now); + accountCapsule.setInstance(accountCapsule.getInstance().toBuilder() + .setBalance(accountCapsule.getBalance() + totalWithdrawUnfreeze) + .build()); + List newUnFreezeList = getRemainWithdrawList(unfrozenV2List, now); + accountCapsule.clearUnfrozenV2(); + accountCapsule.addAllUnfrozenV2(newUnFreezeList); + accountStore.put(accountCapsule.createDbKey(), accountCapsule); + ret.setWithdrawExpireAmount(totalWithdrawUnfreeze); + ret.setStatus(fee, code.SUCESS); + return true; + } + private List getRemainWithdrawList(List unfrozenV2List, long now) { return unfrozenV2List.stream() .filter(unfrozenV2 -> unfrozenV2.getUnfreezeExpireTime() > now) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index 1166696e05c..793bc925903 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -819,10 +819,10 @@ public static void delegateResourceAction(Program program) { if (program.isStaticCall()) { throw new Program.StaticCallModificationException(); } + DataWord lock = program.stackPop(); DataWord resourceType = program.stackPop(); DataWord delegateBalance = program.stackPop(); DataWord receiverAddress = program.stackPop(); - DataWord lock = program.stackPop(); boolean result = program.delegateResource(receiverAddress, delegateBalance, resourceType, lock); program.stackPush(result ? DataWord.ONE() : DataWord.ZERO()); diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index ff62969fe67..03912abfc18 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -1,5 +1,6 @@ package org.tron.core.vm.nativecontract; +import com.google.common.primitives.Bytes; import com.google.protobuf.ByteString; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; @@ -8,10 +9,12 @@ import org.tron.core.ChainBaseManager; import org.tron.core.actuator.ActuatorConstant; import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.db.BandwidthProcessor; import org.tron.core.db.EnergyProcessor; import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.DelegatedResourceAccountIndexStore; import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.vm.nativecontract.param.DelegateResourceParam; import org.tron.core.vm.repository.Repository; @@ -157,8 +160,12 @@ private void delegateResource( long delegateBalance, Repository repo, boolean lock) { - //modify DelegatedResourceStore - byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, false); + // unlock the expired delegate resource + long now = repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); + repo.unlockExpireResource(ownerAddress, receiverAddress, now); + + //modify DelegatedResource + byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, lock); DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); if (delegatedResourceCapsule == null) { delegatedResourceCapsule = new DelegatedResourceCapsule( @@ -176,6 +183,21 @@ private void delegateResource( delegatedResourceCapsule.addFrozenBalanceForEnergy(delegateBalance, expireTime); } + //modify DelegatedResourceAccountIndex + byte[] fromKey = Bytes.concat( + DelegatedResourceAccountIndexStore.getV2_FROM_PREFIX(), ownerAddress, receiverAddress); + DelegatedResourceAccountIndexCapsule toIndexCapsule = + new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(receiverAddress)); + toIndexCapsule.setTimestamp(now); + repo.updateDelegatedResourceAccountIndex(fromKey, toIndexCapsule); + + byte[] toKey = Bytes.concat( + DelegatedResourceAccountIndexStore.getV2_TO_PREFIX(), receiverAddress, ownerAddress); + DelegatedResourceAccountIndexCapsule fromIndexCapsule = + new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(ownerAddress)); + fromIndexCapsule.setTimestamp(now); + repo.updateDelegatedResourceAccountIndex(toKey, fromIndexCapsule); + //update Account for receiver AccountCapsule receiverCapsule = repo.getAccount(receiverAddress); if (isBandwidth) { diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java index 6f4634555d4..2ab9fc451c2 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java @@ -1,9 +1,5 @@ package org.tron.core.vm.nativecontract; -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; - import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; @@ -13,6 +9,12 @@ import org.tron.core.vm.nativecontract.param.FreezeBalanceV2Param; import org.tron.core.vm.repository.Repository; +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; + @Slf4j(topic = "VMProcessor") public class FreezeBalanceV2Processor { @@ -74,16 +76,22 @@ public void execute(FreezeBalanceV2Param param, Repository repo) { } switch (param.getResourceType()) { case BANDWIDTH: + long oldNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); - repo.addTotalNetWeight(frozenBalance / TRX_PRECISION); + long newNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; + repo.addTotalNetWeight(newNetWeight - oldNetWeight); break; case ENERGY: + long oldEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); - repo.addTotalEnergyWeight(frozenBalance / TRX_PRECISION); + long newEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; + repo.addTotalEnergyWeight(newEnergyWeight - oldEnergyWeight); break; case TRON_POWER: + long oldTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; accountCapsule.addFrozenForTronPowerV2(frozenBalance); - repo.addTotalTronPowerWeight(frozenBalance / TRX_PRECISION); + long newTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; + repo.addTotalTronPowerWeight(newTPWeight - oldTPWeight); break; default: logger.debug("Resource Code Error."); diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index 9658f18ce67..b74d541a901 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -1,14 +1,6 @@ package org.tron.core.vm.nativecontract; -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; -import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; -import static org.tron.protos.contract.Common.ResourceCode.ENERGY; - -import java.util.Arrays; -import java.util.Objects; - +import com.google.common.primitives.Bytes; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.tron.common.utils.DecodeUtil; @@ -19,10 +11,20 @@ import org.tron.core.db.BandwidthProcessor; import org.tron.core.db.EnergyProcessor; import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.DelegatedResourceAccountIndexStore; import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.vm.nativecontract.param.UnDelegateResourceParam; import org.tron.core.vm.repository.Repository; +import java.util.Arrays; +import java.util.Objects; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; + @Slf4j(topic = "VMProcessor") public class UnDelegateResourceProcessor { @@ -55,9 +57,12 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont "receiverAddress must not be the same as ownerAddress"); } + long now = dynamicStore.getLatestBlockHeaderTimestamp(); byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, false); - DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); - if (delegatedResourceCapsule == null) { + DelegatedResourceCapsule unlockResourceCapsule = repo.getDelegatedResource(key); + byte[] lockKey = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, true); + DelegatedResourceCapsule lockResourceCapsule = repo.getDelegatedResource(lockKey); + if (unlockResourceCapsule == null && lockResourceCapsule == null) { throw new ContractValidateException( "delegated Resource does not exist"); } @@ -67,18 +72,37 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont throw new ContractValidateException("unDelegateBalance must be more than 0 TRX"); } switch (param.getResourceType()) { - case BANDWIDTH: - if (delegatedResourceCapsule.getFrozenBalanceForBandwidth() < unDelegateBalance) { - throw new ContractValidateException("insufficient delegatedFrozenBalance(BANDWIDTH), request=" - + unDelegateBalance + ", balance=" + delegatedResourceCapsule.getFrozenBalanceForBandwidth()); + case BANDWIDTH: { + long delegateBalance = 0; + if (unlockResourceCapsule != null) { + delegateBalance += unlockResourceCapsule.getFrozenBalanceForBandwidth(); } - break; - case ENERGY: - if (delegatedResourceCapsule.getFrozenBalanceForEnergy() < unDelegateBalance) { + if (lockResourceCapsule != null + && lockResourceCapsule.getExpireTimeForBandwidth() < now) { + delegateBalance += lockResourceCapsule.getFrozenBalanceForBandwidth(); + } + if (delegateBalance < unDelegateBalance) { + throw new ContractValidateException( + "insufficient delegatedFrozenBalance(BANDWIDTH), request=" + + unDelegateBalance + ", unlock_balance=" + delegateBalance); + } + } + break; + case ENERGY: { + long delegateBalance = 0; + if (unlockResourceCapsule != null) { + delegateBalance += unlockResourceCapsule.getFrozenBalanceForEnergy(); + } + if (lockResourceCapsule != null + && lockResourceCapsule.getExpireTimeForEnergy() < now) { + delegateBalance += lockResourceCapsule.getFrozenBalanceForEnergy(); + } + if (delegateBalance < unDelegateBalance) { throw new ContractValidateException("insufficient delegateFrozenBalance(ENERGY), request=" - + unDelegateBalance + ", balance=" + delegatedResourceCapsule.getFrozenBalanceForEnergy()); + + unDelegateBalance + ", unlock_balance=" + delegateBalance); } - break; + } + break; default: throw new ContractValidateException( "ResourceCode error.valid ResourceCode[BANDWIDTH、ENERGY]"); @@ -152,12 +176,16 @@ public void execute(UnDelegateResourceParam param, Repository repo) { repo.updateAccount(receiverCapsule.createDbKey(), receiverCapsule); } + // transfer lock delegate to unlock + repo.unlockExpireResource( + ownerAddress, receiverAddress, dynamicStore.getLatestBlockHeaderTimestamp()); + // modify owner Account byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, false); - DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); + DelegatedResourceCapsule unlockResource = repo.getDelegatedResource(key); switch (param.getResourceType()) { case BANDWIDTH: { - delegatedResourceCapsule.addFrozenBalanceForBandwidth(-unDelegateBalance, 0); + unlockResource.addFrozenBalanceForBandwidth(-unDelegateBalance, 0); ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(-unDelegateBalance); ownerCapsule.addFrozenBalanceForBandwidthV2(unDelegateBalance); @@ -171,7 +199,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { } break; case ENERGY: { - delegatedResourceCapsule.addFrozenBalanceForEnergy(-unDelegateBalance, 0); + unlockResource.addFrozenBalanceForEnergy(-unDelegateBalance, 0); ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(-unDelegateBalance); ownerCapsule.addFrozenBalanceForEnergyV2(unDelegateBalance); @@ -189,7 +217,23 @@ public void execute(UnDelegateResourceParam param, Repository repo) { //this should never happen break; } - repo.updateDelegatedResource(key, delegatedResourceCapsule); + + byte[] lockKey = DelegatedResourceCapsule + .createDbKeyV2(ownerAddress, receiverAddress, true); + DelegatedResourceCapsule lockResource = repo.getDelegatedResource(lockKey); + if (lockResource == null + && unlockResource.getFrozenBalanceForBandwidth() == 0 + && unlockResource.getFrozenBalanceForEnergy() == 0) { + //modify DelegatedResourceAccountIndex + byte[] fromKey = Bytes.concat( + DelegatedResourceAccountIndexStore.getV2_FROM_PREFIX(), ownerAddress, receiverAddress); + repo.updateDelegatedResourceAccountIndex(fromKey, null); + byte[] toKey = Bytes.concat( + DelegatedResourceAccountIndexStore.getV2_TO_PREFIX(), receiverAddress, ownerAddress); + repo.updateDelegatedResourceAccountIndex(toKey, null); + } + + repo.updateDelegatedResource(key, unlockResource); repo.updateAccount(ownerCapsule.createDbKey(), ownerCapsule); } } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index 4fb02d7dac1..d8f259385e3 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -1,16 +1,7 @@ package org.tron.core.vm.nativecontract; -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; -import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; - import com.google.common.collect.Lists; import com.google.protobuf.ByteString; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; @@ -26,6 +17,17 @@ import org.tron.protos.Protocol; import org.tron.protos.contract.Common; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; + @Slf4j(topic = "VMProcessor") public class UnfreezeBalanceV2Processor { @@ -105,19 +107,13 @@ private boolean checkUnfreezeBalance( } private boolean checkExistFrozenBalance(AccountCapsule accountCapsule, Common.ResourceCode freezeType) { - boolean checkOk = false; - long frozenBalance; List frozenV2List = accountCapsule.getFrozenV2List(); for (Protocol.Account.FreezeV2 frozenV2 : frozenV2List) { - if (frozenV2.getType().equals(freezeType)) { - frozenBalance = frozenV2.getAmount(); - if (frozenBalance > 0) { - checkOk = true; - break; - } + if (frozenV2.getType().equals(freezeType) && frozenV2.getAmount() > 0) { + return true; } } - return checkOk; + return false; } public long execute(UnfreezeBalanceV2Param param, Repository repo) { @@ -135,12 +131,10 @@ public long execute(UnfreezeBalanceV2Param param, Repository repo) { accountCapsule.initializeOldTronPower(); } - this.updateAccountFrozenInfo(param.getResourceType(), accountCapsule, unfreezeBalance); - long expireTime = this.calcUnfreezeExpireTime(now, repo); accountCapsule.addUnfrozenV2List(param.getResourceType(), unfreezeBalance, expireTime); - this.updateTotalResourceWeight(param.getResourceType(), unfreezeBalance, repo); + this.updateTotalResourceWeight(accountCapsule, param.getResourceType(), unfreezeBalance, repo); this.updateVote(accountCapsule, param.getResourceType(), ownerAddress, repo); if (repo.getDynamicPropertiesStore().supportAllowNewResourceModel() @@ -176,39 +170,34 @@ private long unfreezeExpire(AccountCapsule accountCapsule, long now) { return unfreezeBalance; } - private void updateAccountFrozenInfo( - Common.ResourceCode freezeType, AccountCapsule accountCapsule, long unfreezeBalance) { - List freezeV2List = accountCapsule.getFrozenV2List(); - for (int i = 0; i < freezeV2List.size(); i++) { - if (freezeV2List.get(i).getType().equals(freezeType)) { - Protocol.Account.FreezeV2 freezeV2 = Protocol.Account.FreezeV2.newBuilder() - .setAmount(freezeV2List.get(i).getAmount() - unfreezeBalance) - .setType(freezeV2List.get(i).getType()) - .build(); - accountCapsule.updateFrozenV2List(i, freezeV2); - break; - } - } - } - private long calcUnfreezeExpireTime(long now, Repository repo) { long unfreezeDelayDays = repo.getDynamicPropertiesStore().getUnfreezeDelayDays(); return now + unfreezeDelayDays * FROZEN_PERIOD; } - public void updateTotalResourceWeight(Common.ResourceCode freezeType, + public void updateTotalResourceWeight(AccountCapsule accountCapsule, + Common.ResourceCode freezeType, long unfreezeBalance, Repository repo) { switch (freezeType) { case BANDWIDTH: - repo.addTotalNetWeight(-unfreezeBalance / TRX_PRECISION); + long oldNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; + accountCapsule.addFrozenBalanceForBandwidthV2(-unfreezeBalance); + long newNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; + repo.addTotalNetWeight(newNetWeight - oldNetWeight); break; case ENERGY: - repo.addTotalEnergyWeight(-unfreezeBalance / TRX_PRECISION); + long oldEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; + accountCapsule.addFrozenBalanceForEnergyV2(-unfreezeBalance); + long newEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; + repo.addTotalEnergyWeight(newEnergyWeight - oldEnergyWeight); break; case TRON_POWER: - repo.addTotalTronPowerWeight(-unfreezeBalance / TRX_PRECISION); + long oldTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; + accountCapsule.addFrozenForTronPowerV2(-unfreezeBalance); + long newTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; + repo.addTotalTronPowerWeight(newTPWeight - oldTPWeight); break; default: //this should never happen diff --git a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java index 4cbccc58686..93a5ba7c535 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java +++ b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java @@ -7,6 +7,7 @@ import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.BytesCapsule; import org.tron.core.capsule.ContractCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.VotesCapsule; import org.tron.core.capsule.WitnessCapsule; @@ -208,6 +209,11 @@ public void putDelegation(Key key, Value value) { repository.putDelegation(key, value); } + @Override + public void putDelegatedResourceAccountIndex(Key key, Value value) { + repository.putDelegatedResourceAccountIndex(key, value); + } + @Override public long addTokenBalance(byte[] address, byte[] tokenId, long value) { return repository.addTokenBalance(address, tokenId, value); @@ -288,6 +294,11 @@ public BytesCapsule getDelegation(Key key) { return repository.getDelegation(key); } + @Override + public DelegatedResourceAccountIndexCapsule getDelegatedResourceAccountIndex(byte[] key) { + return repository.getDelegatedResourceAccountIndex(key); + } + @Override public void updateDynamicProperty(byte[] word, BytesCapsule bytesCapsule) { repository.updateDynamicProperty(word, bytesCapsule); @@ -323,6 +334,11 @@ public void updateDelegation(byte[] word, BytesCapsule bytesCapsule) { repository.updateDelegation(word, bytesCapsule); } + @Override + public void updateDelegatedResourceAccountIndex(byte[] word, DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule) { + repository.updateDelegatedResourceAccountIndex(word, delegatedResourceAccountIndexCapsule); + } + @Override public void putDynamicProperty(Key key, Value value) { repository.putDynamicProperty(key, value); @@ -388,4 +404,8 @@ public long getSlotByTimestampMs(long timestamp) { return repository.getSlotByTimestampMs(timestamp); } + @Override + public void unlockExpireResource(byte[] from, byte[] to, long now) { + repository.unlockExpireResource(from, to, now); + } } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java index c5b92a63ba8..529cfa06be1 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java @@ -39,6 +39,8 @@ public interface Repository { BytesCapsule getDelegation(Key key); + DelegatedResourceAccountIndexCapsule getDelegatedResourceAccountIndex(byte[] key); + void deleteContract(byte[] address); void createContract(byte[] address, ContractCapsule contractCapsule); @@ -63,6 +65,8 @@ public interface Repository { void updateDelegation(byte[] word, BytesCapsule bytesCapsule); + void updateDelegatedResourceAccountIndex(byte[] word, DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule); + void saveCode(byte[] address, byte[] code); byte[] getCode(byte[] address); @@ -101,6 +105,8 @@ public interface Repository { void putDelegation(Key key, Value value); + void putDelegatedResourceAccountIndex(Key key, Value value); + long addTokenBalance(byte[] address, byte[] tokenId, long value); long getTokenBalance(byte[] address, byte[] tokenId); @@ -145,4 +151,5 @@ public interface Repository { long getSlotByTimestampMs(long timestamp); + void unlockExpireResource(byte[] from, byte[] to, long now); } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index bf758c9fd44..a91faaa9895 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -30,6 +30,7 @@ import org.tron.core.capsule.BytesCapsule; import org.tron.core.capsule.CodeCapsule; import org.tron.core.capsule.ContractCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.VotesCapsule; import org.tron.core.capsule.WitnessCapsule; @@ -47,6 +48,7 @@ import org.tron.core.store.AssetIssueV2Store; import org.tron.core.store.CodeStore; import org.tron.core.store.ContractStore; +import org.tron.core.store.DelegatedResourceAccountIndexStore; import org.tron.core.store.DelegatedResourceStore; import org.tron.core.store.DelegationStore; import org.tron.core.store.DynamicPropertiesStore; @@ -62,6 +64,7 @@ import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.DelegatedResource; import org.tron.protos.Protocol.Votes; +import org.tron.protos.Protocol.DelegatedResourceAccountIndex; import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; import org.tron.protos.contract.Common; import org.tron.protos.contract.SmartContractOuterClass.SmartContract; @@ -105,6 +108,8 @@ public class RepositoryImpl implements Repository { private VotesStore votesStore; @Getter private DelegationStore delegationStore; + @Getter + private DelegatedResourceAccountIndexStore delegatedResourceAccountIndexStore; private Repository parent = null; @@ -118,6 +123,7 @@ public class RepositoryImpl implements Repository { private final HashMap> delegatedResourceCache = new HashMap<>(); private final HashMap> votesCache = new HashMap<>(); private final HashMap> delegationCache = new HashMap<>(); + private final HashMap> delegatedResourceAccountIndexCache = new HashMap<>(); public static void removeLruCache(byte[] address) { } @@ -149,6 +155,7 @@ protected void init(StoreFactory storeFactory, RepositoryImpl parent) { delegatedResourceStore = manager.getDelegatedResourceStore(); votesStore = manager.getVotesStore(); delegationStore = manager.getDelegationStore(); + delegatedResourceAccountIndexStore = manager.getDelegatedResourceAccountIndexStore(); } this.parent = parent; } @@ -405,6 +412,28 @@ public BytesCapsule getDelegation(Key key) { return bytesCapsule; } + @Override + public DelegatedResourceAccountIndexCapsule getDelegatedResourceAccountIndex(byte[] key) { + Key cacheKey = new Key(key); + if (delegatedResourceAccountIndexCache.containsKey(cacheKey)) { + return new DelegatedResourceAccountIndexCapsule( + delegatedResourceAccountIndexCache.get(cacheKey).getValue()); + } + + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule; + if (parent != null) { + delegatedResourceAccountIndexCapsule = parent.getDelegatedResourceAccountIndex(key); + } else { + delegatedResourceAccountIndexCapsule = getDelegatedResourceAccountIndexStore().get(key); + } + + if (delegatedResourceAccountIndexCapsule != null) { + delegatedResourceAccountIndexCache.put( + cacheKey, Value.create(delegatedResourceAccountIndexCapsule)); + } + return delegatedResourceAccountIndexCapsule; + } + @Override public void deleteContract(byte[] address) { @@ -495,6 +524,13 @@ public void updateDelegation(byte[] word, BytesCapsule bytesCapsule) { Value.create(bytesCapsule.getData(), Type.DIRTY)); } + @Override + public void updateDelegatedResourceAccountIndex( + byte[] word, DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule) { + delegatedResourceAccountIndexCache.put( + Key.create(word), Value.create(delegatedResourceAccountIndexCapsule, Type.DIRTY)); + } + @Override public void saveCode(byte[] address, byte[] code) { codeCache.put(Key.create(address), Value.create(code, Type.CREATE)); @@ -637,6 +673,7 @@ public void commit() { commitDelegatedResourceCache(repository); commitVotesCache(repository); commitDelegationCache(repository); + commitDelegatedResourceAccountIndexCache(repository); } @Override @@ -685,6 +722,11 @@ public void putDelegation(Key key, Value value) { delegationCache.put(key, value); } + @Override + public void putDelegatedResourceAccountIndex(Key key, Value value) { + delegatedResourceAccountIndexCache.put(key, value); + } + @Override public long addTokenBalance(byte[] address, byte[] tokenId, long value) { byte[] tokenIdWithoutLeadingZero = ByteUtil.stripLeadingZeroes(tokenId); @@ -800,6 +842,39 @@ public long getSlotByTimestampMs(long timestamp) { / BLOCK_PRODUCED_INTERVAL; } + @Override + public void unlockExpireResource(byte[] from, byte[] to, long now) { + byte[] lockKey = DelegatedResourceCapsule.createDbKeyV2(from, to, true); + DelegatedResourceCapsule lockResource = getDelegatedResource(lockKey); + if (lockResource == null) { + return; + } + if (lockResource.getExpireTimeForEnergy() >= now + && lockResource.getExpireTimeForBandwidth() >= now) { + return; + } + + byte[] unlockKey = DelegatedResourceCapsule.createDbKeyV2(from, to, false); + DelegatedResourceCapsule unlockResource = getDelegatedResource(unlockKey); + if (unlockResource == null) { + unlockResource = new DelegatedResourceCapsule(ByteString.copyFrom(from), + ByteString.copyFrom(to)); + } + if (lockResource.getExpireTimeForEnergy() < now) { + unlockResource.addFrozenBalanceForEnergy( + lockResource.getFrozenBalanceForEnergy(), 0); + lockResource.setFrozenBalanceForEnergy(0, 0); + } + if (lockResource.getExpireTimeForBandwidth() < now) { + unlockResource.addFrozenBalanceForBandwidth( + lockResource.getFrozenBalanceForBandwidth(), 0); + lockResource.setFrozenBalanceForBandwidth(0, 0); + } + + updateDelegatedResource(lockKey, lockResource); + updateDelegatedResource(unlockKey, unlockResource); + } + private void commitAccountCache(Repository deposit) { accountCache.forEach((key, value) -> { if (value.getType().isCreate() || value.getType().isDirty()) { @@ -901,6 +976,23 @@ private void commitDelegationCache(Repository deposit) { }); } + private void commitDelegatedResourceAccountIndexCache(Repository deposit) { + delegatedResourceAccountIndexCache.forEach(((key, value) -> { + if (value.getType().isDirty() || value.getType().isCreate()) { + if (deposit != null) { + deposit.putDelegatedResourceAccountIndex(key, value); + } else { + if (value.getValue() == null) { + getDelegatedResourceAccountIndexStore().delete(key.getData()); + } else { + getDelegatedResourceAccountIndexStore().put(key.getData(), + new DelegatedResourceAccountIndexCapsule(value.getValue())); + } + } + } + })); + } + /** * Get the block id from the number. */ diff --git a/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java b/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java index 435f71c9a64..2afa2cf6917 100644 --- a/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java @@ -6,6 +6,8 @@ import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; + +import lombok.Getter; import org.apache.commons.lang3.ArrayUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -20,7 +22,9 @@ public class DelegatedResourceAccountIndexStore extends private static final byte[] FROM_PREFIX = {0x01}; private static final byte[] TO_PREFIX = {0x02}; + @Getter private static final byte[] V2_FROM_PREFIX = {0x03}; + @Getter private static final byte[] V2_TO_PREFIX = {0x04}; @Autowired From 846864c6d389dd023f1390b760748bfcb398c4a0 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 20 Dec 2022 19:25:09 +0800 Subject: [PATCH 0467/1197] feat(db): optimize the auto-stop logic 1. print an error and exit when the parameter is illegal 2. print an error and exit when more than one parameter is set --- .../main/java/org/tron/core/db/Manager.java | 85 ++++++++++++++----- .../org/tron/core/net/TronNetDelegate.java | 5 +- .../services/stop/BlockHeightStopTest.java | 2 - .../services/stop/BlockSyncCountStopTest.java | 2 - .../core/services/stop/BlockTimeStopTest.java | 4 - .../services/stop/ConditionallyStopTest.java | 2 +- 6 files changed, 67 insertions(+), 33 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 722bc9b981a..41f948836b9 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -42,6 +42,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.bouncycastle.util.encoders.Hex; +import org.quartz.CronExpression; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.api.GrpcAPI.TransactionInfoList; @@ -537,28 +538,14 @@ public void init() { //initActuatorCreator ActuatorCreator.init(); TransactionRegister.registerActuator(); - - long exitHeight = CommonParameter.getInstance().getShutdownBlockHeight(); - long exitCount = CommonParameter.getInstance().getShutdownBlockCount(); - - if (exitHeight > 0 && exitHeight < headNum) { - logger.info("ShutDownBlockHeight {} is less than headNum {}, reset it to -1.", - exitHeight, headNum); - CommonParameter.getInstance().setShutdownBlockHeight(-1); - exitHeight = -1; - } - - if (exitCount > 0 && (exitHeight < 0 || exitHeight > headNum + exitCount)) { - CommonParameter.getInstance().setShutdownBlockHeight(headNum + exitCount); + // init auto-stop + try { + initAutoStop(); + } catch (IllegalArgumentException e) { + logger.error("Auto-stop params error: {}", e.getMessage()); + System.exit(1); } - if (CommonParameter.getInstance().getShutdownBlockHeight() < headNum) { - logger.info("ShutDownBlockHeight {} is less than headNum {}, ignored.", - CommonParameter.getInstance().getShutdownBlockHeight(), headNum); - CommonParameter.getInstance().setShutdownBlockHeight(-1); - } - // init - latestSolidityNumShutDown = CommonParameter.getInstance().getShutdownBlockHeight(); maxFlushCount = CommonParameter.getInstance().getStorage().getMaxFlushCount(); } @@ -684,6 +671,62 @@ private void initWitness() { }); } + /** + * init auto-stop, check params + */ + private void initAutoStop() { + final long headNum = chainBaseManager.getHeadBlockNum(); + final long headTime = chainBaseManager.getHeadBlockTimeStamp(); + final long exitHeight = CommonParameter.getInstance().getShutdownBlockHeight(); + final long exitCount = CommonParameter.getInstance().getShutdownBlockCount(); + final CronExpression blockTime = Args.getInstance().getShutdownBlockTime(); + + if (exitHeight > 0 && exitHeight < headNum) { + throw new IllegalArgumentException( + String.format("shutDownBlockHeight %d is less than headNum %d", exitHeight, headNum)); + } + + if (exitCount == 0) { + throw new IllegalArgumentException( + String.format("shutDownBlockCount %d is less than 1", exitCount)); + } + + if (blockTime != null && blockTime.getNextValidTimeAfter(new Date(headTime)) == null) { + throw new IllegalArgumentException( + String.format("shutDownBlockTime %s is illegal", blockTime)); + } + + if (exitHeight > 0 && exitCount > 0) { + throw new IllegalArgumentException( + String.format("shutDownBlockHeight %d and shutDownBlockCount %d set both", + exitHeight, exitCount)); + } + + if (exitHeight > 0 && blockTime != null) { + throw new IllegalArgumentException( + String.format("shutDownBlockHeight %d and shutDownBlockTime %s set both", + exitHeight, blockTime)); + } + + if (exitCount > 0 && blockTime != null) { + throw new IllegalArgumentException( + String.format("shutDownBlockCount %d and shutDownBlockTime %s set both", + exitCount, blockTime)); + } + + if (exitHeight == headNum) { + logger.info("Auto-stop hit: shutDownBlockHeight: {}, currentHeaderNum: {}, exit now", + exitHeight, headNum); + System.exit(0); + } + + if (exitCount > 0) { + CommonParameter.getInstance().setShutdownBlockHeight(headNum + exitCount); + } + // init + latestSolidityNumShutDown = CommonParameter.getInstance().getShutdownBlockHeight(); + } + public AccountStore getAccountStore() { return chainBaseManager.getAccountStore(); } @@ -971,7 +1014,7 @@ private void applyBlock(BlockCapsule block, List txs) revokingStore.setMaxFlushCount(maxFlushCount); if (Args.getInstance().getShutdownBlockTime() != null && Args.getInstance().getShutdownBlockTime().getNextValidTimeAfter( - new Date(block.getTimeStamp() - maxFlushCount * 1000 * 3)) + new Date(block.getTimeStamp() - maxFlushCount * 1000 * 3L)) .compareTo(new Date(block.getTimeStamp())) <= 0) { revokingStore.setMaxFlushCount(SnapshotManager.DEFAULT_MIN_FLUSH_COUNT); } diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index a531a0d50af..05dde7a9701 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -94,9 +94,8 @@ public class TronNetDelegate { private Thread hitThread; - // for Test @Setter - private volatile boolean test = false; + private volatile boolean exit = true; private Cache freshBlockId = CacheBuilder.newBuilder() .maximumSize(blockIdCacheSize).expireAfterWrite(1, TimeUnit.HOURS) @@ -107,7 +106,7 @@ public void init() { hitThread = new Thread(() -> { LockSupport.park(); // to Guarantee Some other thread invokes unpark with the current thread as the target - if (hitDown && !test) { + if (hitDown && exit) { System.exit(0); } }); diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java index 43eb4f5ba4e..a05cc64aad4 100644 --- a/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java @@ -11,8 +11,6 @@ public class BlockHeightStopTest extends ConditionallyStopTest { protected void initParameter(CommonParameter parameter) { parameter.setShutdownBlockHeight(height); - // will ignore - parameter.setShutdownBlockCount(128); } @Override diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java index cd5010fabc9..f974a8a4272 100644 --- a/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java @@ -11,8 +11,6 @@ public class BlockSyncCountStopTest extends ConditionallyStopTest { protected void initParameter(CommonParameter parameter) { parameter.setShutdownBlockCount(sync); - // will ignore - parameter.setShutdownBlockHeight(1024); } @Override diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java index 9dd34a577d6..2d3fde1afdb 100644 --- a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java @@ -28,10 +28,6 @@ public class BlockTimeStopTest extends ConditionallyStopTest { protected void initParameter(CommonParameter parameter) { parameter.setShutdownBlockTime(cronExpression); - // will ignore - parameter.setShutdownBlockHeight(48); - // will ignore - parameter.setShutdownBlockCount(32); } @Override diff --git a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java index 88f2d1c04e0..d012587849b 100644 --- a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java @@ -81,7 +81,7 @@ public void init() throws Exception { consensusService.start(); chainManager = dbManager.getChainBaseManager(); tronNetDelegate = context.getBean(TronNetDelegate.class); - tronNetDelegate.setTest(true); + tronNetDelegate.setExit(false); currentHeader = dbManager.getDynamicPropertiesStore() .getLatestBlockHeaderNumberFromDB(); } From 5ddaa454296411d567c713a0c861bf06d2c20970 Mon Sep 17 00:00:00 2001 From: Liulei Date: Tue, 20 Dec 2022 18:32:09 +0800 Subject: [PATCH 0468/1197] feat(freezeV2): merge stake 2.0 new features --- .../org/tron/core/vm/OperationActions.java | 2 +- .../DelegateResourceProcessor.java | 26 +++++- .../FreezeBalanceV2Processor.java | 22 +++-- .../UnDelegateResourceProcessor.java | 92 ++++++++++++++----- .../UnfreezeBalanceV2Processor.java | 69 ++++++-------- .../tron/core/vm/program/ContractState.java | 20 ++++ .../tron/core/vm/repository/Repository.java | 7 ++ .../core/vm/repository/RepositoryImpl.java | 92 +++++++++++++++++++ .../DelegatedResourceAccountIndexStore.java | 4 + 9 files changed, 260 insertions(+), 74 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index 1166696e05c..793bc925903 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -819,10 +819,10 @@ public static void delegateResourceAction(Program program) { if (program.isStaticCall()) { throw new Program.StaticCallModificationException(); } + DataWord lock = program.stackPop(); DataWord resourceType = program.stackPop(); DataWord delegateBalance = program.stackPop(); DataWord receiverAddress = program.stackPop(); - DataWord lock = program.stackPop(); boolean result = program.delegateResource(receiverAddress, delegateBalance, resourceType, lock); program.stackPush(result ? DataWord.ONE() : DataWord.ZERO()); diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index ff62969fe67..03912abfc18 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -1,5 +1,6 @@ package org.tron.core.vm.nativecontract; +import com.google.common.primitives.Bytes; import com.google.protobuf.ByteString; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; @@ -8,10 +9,12 @@ import org.tron.core.ChainBaseManager; import org.tron.core.actuator.ActuatorConstant; import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.db.BandwidthProcessor; import org.tron.core.db.EnergyProcessor; import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.DelegatedResourceAccountIndexStore; import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.vm.nativecontract.param.DelegateResourceParam; import org.tron.core.vm.repository.Repository; @@ -157,8 +160,12 @@ private void delegateResource( long delegateBalance, Repository repo, boolean lock) { - //modify DelegatedResourceStore - byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, false); + // unlock the expired delegate resource + long now = repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); + repo.unlockExpireResource(ownerAddress, receiverAddress, now); + + //modify DelegatedResource + byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, lock); DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); if (delegatedResourceCapsule == null) { delegatedResourceCapsule = new DelegatedResourceCapsule( @@ -176,6 +183,21 @@ private void delegateResource( delegatedResourceCapsule.addFrozenBalanceForEnergy(delegateBalance, expireTime); } + //modify DelegatedResourceAccountIndex + byte[] fromKey = Bytes.concat( + DelegatedResourceAccountIndexStore.getV2_FROM_PREFIX(), ownerAddress, receiverAddress); + DelegatedResourceAccountIndexCapsule toIndexCapsule = + new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(receiverAddress)); + toIndexCapsule.setTimestamp(now); + repo.updateDelegatedResourceAccountIndex(fromKey, toIndexCapsule); + + byte[] toKey = Bytes.concat( + DelegatedResourceAccountIndexStore.getV2_TO_PREFIX(), receiverAddress, ownerAddress); + DelegatedResourceAccountIndexCapsule fromIndexCapsule = + new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(ownerAddress)); + fromIndexCapsule.setTimestamp(now); + repo.updateDelegatedResourceAccountIndex(toKey, fromIndexCapsule); + //update Account for receiver AccountCapsule receiverCapsule = repo.getAccount(receiverAddress); if (isBandwidth) { diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java index 6f4634555d4..2ab9fc451c2 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java @@ -1,9 +1,5 @@ package org.tron.core.vm.nativecontract; -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; - import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; @@ -13,6 +9,12 @@ import org.tron.core.vm.nativecontract.param.FreezeBalanceV2Param; import org.tron.core.vm.repository.Repository; +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; + @Slf4j(topic = "VMProcessor") public class FreezeBalanceV2Processor { @@ -74,16 +76,22 @@ public void execute(FreezeBalanceV2Param param, Repository repo) { } switch (param.getResourceType()) { case BANDWIDTH: + long oldNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); - repo.addTotalNetWeight(frozenBalance / TRX_PRECISION); + long newNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; + repo.addTotalNetWeight(newNetWeight - oldNetWeight); break; case ENERGY: + long oldEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); - repo.addTotalEnergyWeight(frozenBalance / TRX_PRECISION); + long newEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; + repo.addTotalEnergyWeight(newEnergyWeight - oldEnergyWeight); break; case TRON_POWER: + long oldTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; accountCapsule.addFrozenForTronPowerV2(frozenBalance); - repo.addTotalTronPowerWeight(frozenBalance / TRX_PRECISION); + long newTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; + repo.addTotalTronPowerWeight(newTPWeight - oldTPWeight); break; default: logger.debug("Resource Code Error."); diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index 9658f18ce67..b74d541a901 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -1,14 +1,6 @@ package org.tron.core.vm.nativecontract; -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; -import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; -import static org.tron.protos.contract.Common.ResourceCode.ENERGY; - -import java.util.Arrays; -import java.util.Objects; - +import com.google.common.primitives.Bytes; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.tron.common.utils.DecodeUtil; @@ -19,10 +11,20 @@ import org.tron.core.db.BandwidthProcessor; import org.tron.core.db.EnergyProcessor; import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.DelegatedResourceAccountIndexStore; import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.vm.nativecontract.param.UnDelegateResourceParam; import org.tron.core.vm.repository.Repository; +import java.util.Arrays; +import java.util.Objects; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; + @Slf4j(topic = "VMProcessor") public class UnDelegateResourceProcessor { @@ -55,9 +57,12 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont "receiverAddress must not be the same as ownerAddress"); } + long now = dynamicStore.getLatestBlockHeaderTimestamp(); byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, false); - DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); - if (delegatedResourceCapsule == null) { + DelegatedResourceCapsule unlockResourceCapsule = repo.getDelegatedResource(key); + byte[] lockKey = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, true); + DelegatedResourceCapsule lockResourceCapsule = repo.getDelegatedResource(lockKey); + if (unlockResourceCapsule == null && lockResourceCapsule == null) { throw new ContractValidateException( "delegated Resource does not exist"); } @@ -67,18 +72,37 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont throw new ContractValidateException("unDelegateBalance must be more than 0 TRX"); } switch (param.getResourceType()) { - case BANDWIDTH: - if (delegatedResourceCapsule.getFrozenBalanceForBandwidth() < unDelegateBalance) { - throw new ContractValidateException("insufficient delegatedFrozenBalance(BANDWIDTH), request=" - + unDelegateBalance + ", balance=" + delegatedResourceCapsule.getFrozenBalanceForBandwidth()); + case BANDWIDTH: { + long delegateBalance = 0; + if (unlockResourceCapsule != null) { + delegateBalance += unlockResourceCapsule.getFrozenBalanceForBandwidth(); } - break; - case ENERGY: - if (delegatedResourceCapsule.getFrozenBalanceForEnergy() < unDelegateBalance) { + if (lockResourceCapsule != null + && lockResourceCapsule.getExpireTimeForBandwidth() < now) { + delegateBalance += lockResourceCapsule.getFrozenBalanceForBandwidth(); + } + if (delegateBalance < unDelegateBalance) { + throw new ContractValidateException( + "insufficient delegatedFrozenBalance(BANDWIDTH), request=" + + unDelegateBalance + ", unlock_balance=" + delegateBalance); + } + } + break; + case ENERGY: { + long delegateBalance = 0; + if (unlockResourceCapsule != null) { + delegateBalance += unlockResourceCapsule.getFrozenBalanceForEnergy(); + } + if (lockResourceCapsule != null + && lockResourceCapsule.getExpireTimeForEnergy() < now) { + delegateBalance += lockResourceCapsule.getFrozenBalanceForEnergy(); + } + if (delegateBalance < unDelegateBalance) { throw new ContractValidateException("insufficient delegateFrozenBalance(ENERGY), request=" - + unDelegateBalance + ", balance=" + delegatedResourceCapsule.getFrozenBalanceForEnergy()); + + unDelegateBalance + ", unlock_balance=" + delegateBalance); } - break; + } + break; default: throw new ContractValidateException( "ResourceCode error.valid ResourceCode[BANDWIDTH、ENERGY]"); @@ -152,12 +176,16 @@ public void execute(UnDelegateResourceParam param, Repository repo) { repo.updateAccount(receiverCapsule.createDbKey(), receiverCapsule); } + // transfer lock delegate to unlock + repo.unlockExpireResource( + ownerAddress, receiverAddress, dynamicStore.getLatestBlockHeaderTimestamp()); + // modify owner Account byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, false); - DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); + DelegatedResourceCapsule unlockResource = repo.getDelegatedResource(key); switch (param.getResourceType()) { case BANDWIDTH: { - delegatedResourceCapsule.addFrozenBalanceForBandwidth(-unDelegateBalance, 0); + unlockResource.addFrozenBalanceForBandwidth(-unDelegateBalance, 0); ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(-unDelegateBalance); ownerCapsule.addFrozenBalanceForBandwidthV2(unDelegateBalance); @@ -171,7 +199,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { } break; case ENERGY: { - delegatedResourceCapsule.addFrozenBalanceForEnergy(-unDelegateBalance, 0); + unlockResource.addFrozenBalanceForEnergy(-unDelegateBalance, 0); ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(-unDelegateBalance); ownerCapsule.addFrozenBalanceForEnergyV2(unDelegateBalance); @@ -189,7 +217,23 @@ public void execute(UnDelegateResourceParam param, Repository repo) { //this should never happen break; } - repo.updateDelegatedResource(key, delegatedResourceCapsule); + + byte[] lockKey = DelegatedResourceCapsule + .createDbKeyV2(ownerAddress, receiverAddress, true); + DelegatedResourceCapsule lockResource = repo.getDelegatedResource(lockKey); + if (lockResource == null + && unlockResource.getFrozenBalanceForBandwidth() == 0 + && unlockResource.getFrozenBalanceForEnergy() == 0) { + //modify DelegatedResourceAccountIndex + byte[] fromKey = Bytes.concat( + DelegatedResourceAccountIndexStore.getV2_FROM_PREFIX(), ownerAddress, receiverAddress); + repo.updateDelegatedResourceAccountIndex(fromKey, null); + byte[] toKey = Bytes.concat( + DelegatedResourceAccountIndexStore.getV2_TO_PREFIX(), receiverAddress, ownerAddress); + repo.updateDelegatedResourceAccountIndex(toKey, null); + } + + repo.updateDelegatedResource(key, unlockResource); repo.updateAccount(ownerCapsule.createDbKey(), ownerCapsule); } } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index 4fb02d7dac1..d8f259385e3 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -1,16 +1,7 @@ package org.tron.core.vm.nativecontract; -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; -import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; - import com.google.common.collect.Lists; import com.google.protobuf.ByteString; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; @@ -26,6 +17,17 @@ import org.tron.protos.Protocol; import org.tron.protos.contract.Common; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; + @Slf4j(topic = "VMProcessor") public class UnfreezeBalanceV2Processor { @@ -105,19 +107,13 @@ private boolean checkUnfreezeBalance( } private boolean checkExistFrozenBalance(AccountCapsule accountCapsule, Common.ResourceCode freezeType) { - boolean checkOk = false; - long frozenBalance; List frozenV2List = accountCapsule.getFrozenV2List(); for (Protocol.Account.FreezeV2 frozenV2 : frozenV2List) { - if (frozenV2.getType().equals(freezeType)) { - frozenBalance = frozenV2.getAmount(); - if (frozenBalance > 0) { - checkOk = true; - break; - } + if (frozenV2.getType().equals(freezeType) && frozenV2.getAmount() > 0) { + return true; } } - return checkOk; + return false; } public long execute(UnfreezeBalanceV2Param param, Repository repo) { @@ -135,12 +131,10 @@ public long execute(UnfreezeBalanceV2Param param, Repository repo) { accountCapsule.initializeOldTronPower(); } - this.updateAccountFrozenInfo(param.getResourceType(), accountCapsule, unfreezeBalance); - long expireTime = this.calcUnfreezeExpireTime(now, repo); accountCapsule.addUnfrozenV2List(param.getResourceType(), unfreezeBalance, expireTime); - this.updateTotalResourceWeight(param.getResourceType(), unfreezeBalance, repo); + this.updateTotalResourceWeight(accountCapsule, param.getResourceType(), unfreezeBalance, repo); this.updateVote(accountCapsule, param.getResourceType(), ownerAddress, repo); if (repo.getDynamicPropertiesStore().supportAllowNewResourceModel() @@ -176,39 +170,34 @@ private long unfreezeExpire(AccountCapsule accountCapsule, long now) { return unfreezeBalance; } - private void updateAccountFrozenInfo( - Common.ResourceCode freezeType, AccountCapsule accountCapsule, long unfreezeBalance) { - List freezeV2List = accountCapsule.getFrozenV2List(); - for (int i = 0; i < freezeV2List.size(); i++) { - if (freezeV2List.get(i).getType().equals(freezeType)) { - Protocol.Account.FreezeV2 freezeV2 = Protocol.Account.FreezeV2.newBuilder() - .setAmount(freezeV2List.get(i).getAmount() - unfreezeBalance) - .setType(freezeV2List.get(i).getType()) - .build(); - accountCapsule.updateFrozenV2List(i, freezeV2); - break; - } - } - } - private long calcUnfreezeExpireTime(long now, Repository repo) { long unfreezeDelayDays = repo.getDynamicPropertiesStore().getUnfreezeDelayDays(); return now + unfreezeDelayDays * FROZEN_PERIOD; } - public void updateTotalResourceWeight(Common.ResourceCode freezeType, + public void updateTotalResourceWeight(AccountCapsule accountCapsule, + Common.ResourceCode freezeType, long unfreezeBalance, Repository repo) { switch (freezeType) { case BANDWIDTH: - repo.addTotalNetWeight(-unfreezeBalance / TRX_PRECISION); + long oldNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; + accountCapsule.addFrozenBalanceForBandwidthV2(-unfreezeBalance); + long newNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; + repo.addTotalNetWeight(newNetWeight - oldNetWeight); break; case ENERGY: - repo.addTotalEnergyWeight(-unfreezeBalance / TRX_PRECISION); + long oldEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; + accountCapsule.addFrozenBalanceForEnergyV2(-unfreezeBalance); + long newEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; + repo.addTotalEnergyWeight(newEnergyWeight - oldEnergyWeight); break; case TRON_POWER: - repo.addTotalTronPowerWeight(-unfreezeBalance / TRX_PRECISION); + long oldTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; + accountCapsule.addFrozenForTronPowerV2(-unfreezeBalance); + long newTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; + repo.addTotalTronPowerWeight(newTPWeight - oldTPWeight); break; default: //this should never happen diff --git a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java index 4cbccc58686..93a5ba7c535 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java +++ b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java @@ -7,6 +7,7 @@ import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.BytesCapsule; import org.tron.core.capsule.ContractCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.VotesCapsule; import org.tron.core.capsule.WitnessCapsule; @@ -208,6 +209,11 @@ public void putDelegation(Key key, Value value) { repository.putDelegation(key, value); } + @Override + public void putDelegatedResourceAccountIndex(Key key, Value value) { + repository.putDelegatedResourceAccountIndex(key, value); + } + @Override public long addTokenBalance(byte[] address, byte[] tokenId, long value) { return repository.addTokenBalance(address, tokenId, value); @@ -288,6 +294,11 @@ public BytesCapsule getDelegation(Key key) { return repository.getDelegation(key); } + @Override + public DelegatedResourceAccountIndexCapsule getDelegatedResourceAccountIndex(byte[] key) { + return repository.getDelegatedResourceAccountIndex(key); + } + @Override public void updateDynamicProperty(byte[] word, BytesCapsule bytesCapsule) { repository.updateDynamicProperty(word, bytesCapsule); @@ -323,6 +334,11 @@ public void updateDelegation(byte[] word, BytesCapsule bytesCapsule) { repository.updateDelegation(word, bytesCapsule); } + @Override + public void updateDelegatedResourceAccountIndex(byte[] word, DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule) { + repository.updateDelegatedResourceAccountIndex(word, delegatedResourceAccountIndexCapsule); + } + @Override public void putDynamicProperty(Key key, Value value) { repository.putDynamicProperty(key, value); @@ -388,4 +404,8 @@ public long getSlotByTimestampMs(long timestamp) { return repository.getSlotByTimestampMs(timestamp); } + @Override + public void unlockExpireResource(byte[] from, byte[] to, long now) { + repository.unlockExpireResource(from, to, now); + } } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java index c5b92a63ba8..529cfa06be1 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java @@ -39,6 +39,8 @@ public interface Repository { BytesCapsule getDelegation(Key key); + DelegatedResourceAccountIndexCapsule getDelegatedResourceAccountIndex(byte[] key); + void deleteContract(byte[] address); void createContract(byte[] address, ContractCapsule contractCapsule); @@ -63,6 +65,8 @@ public interface Repository { void updateDelegation(byte[] word, BytesCapsule bytesCapsule); + void updateDelegatedResourceAccountIndex(byte[] word, DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule); + void saveCode(byte[] address, byte[] code); byte[] getCode(byte[] address); @@ -101,6 +105,8 @@ public interface Repository { void putDelegation(Key key, Value value); + void putDelegatedResourceAccountIndex(Key key, Value value); + long addTokenBalance(byte[] address, byte[] tokenId, long value); long getTokenBalance(byte[] address, byte[] tokenId); @@ -145,4 +151,5 @@ public interface Repository { long getSlotByTimestampMs(long timestamp); + void unlockExpireResource(byte[] from, byte[] to, long now); } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index bf758c9fd44..a91faaa9895 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -30,6 +30,7 @@ import org.tron.core.capsule.BytesCapsule; import org.tron.core.capsule.CodeCapsule; import org.tron.core.capsule.ContractCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.VotesCapsule; import org.tron.core.capsule.WitnessCapsule; @@ -47,6 +48,7 @@ import org.tron.core.store.AssetIssueV2Store; import org.tron.core.store.CodeStore; import org.tron.core.store.ContractStore; +import org.tron.core.store.DelegatedResourceAccountIndexStore; import org.tron.core.store.DelegatedResourceStore; import org.tron.core.store.DelegationStore; import org.tron.core.store.DynamicPropertiesStore; @@ -62,6 +64,7 @@ import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.DelegatedResource; import org.tron.protos.Protocol.Votes; +import org.tron.protos.Protocol.DelegatedResourceAccountIndex; import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; import org.tron.protos.contract.Common; import org.tron.protos.contract.SmartContractOuterClass.SmartContract; @@ -105,6 +108,8 @@ public class RepositoryImpl implements Repository { private VotesStore votesStore; @Getter private DelegationStore delegationStore; + @Getter + private DelegatedResourceAccountIndexStore delegatedResourceAccountIndexStore; private Repository parent = null; @@ -118,6 +123,7 @@ public class RepositoryImpl implements Repository { private final HashMap> delegatedResourceCache = new HashMap<>(); private final HashMap> votesCache = new HashMap<>(); private final HashMap> delegationCache = new HashMap<>(); + private final HashMap> delegatedResourceAccountIndexCache = new HashMap<>(); public static void removeLruCache(byte[] address) { } @@ -149,6 +155,7 @@ protected void init(StoreFactory storeFactory, RepositoryImpl parent) { delegatedResourceStore = manager.getDelegatedResourceStore(); votesStore = manager.getVotesStore(); delegationStore = manager.getDelegationStore(); + delegatedResourceAccountIndexStore = manager.getDelegatedResourceAccountIndexStore(); } this.parent = parent; } @@ -405,6 +412,28 @@ public BytesCapsule getDelegation(Key key) { return bytesCapsule; } + @Override + public DelegatedResourceAccountIndexCapsule getDelegatedResourceAccountIndex(byte[] key) { + Key cacheKey = new Key(key); + if (delegatedResourceAccountIndexCache.containsKey(cacheKey)) { + return new DelegatedResourceAccountIndexCapsule( + delegatedResourceAccountIndexCache.get(cacheKey).getValue()); + } + + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule; + if (parent != null) { + delegatedResourceAccountIndexCapsule = parent.getDelegatedResourceAccountIndex(key); + } else { + delegatedResourceAccountIndexCapsule = getDelegatedResourceAccountIndexStore().get(key); + } + + if (delegatedResourceAccountIndexCapsule != null) { + delegatedResourceAccountIndexCache.put( + cacheKey, Value.create(delegatedResourceAccountIndexCapsule)); + } + return delegatedResourceAccountIndexCapsule; + } + @Override public void deleteContract(byte[] address) { @@ -495,6 +524,13 @@ public void updateDelegation(byte[] word, BytesCapsule bytesCapsule) { Value.create(bytesCapsule.getData(), Type.DIRTY)); } + @Override + public void updateDelegatedResourceAccountIndex( + byte[] word, DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule) { + delegatedResourceAccountIndexCache.put( + Key.create(word), Value.create(delegatedResourceAccountIndexCapsule, Type.DIRTY)); + } + @Override public void saveCode(byte[] address, byte[] code) { codeCache.put(Key.create(address), Value.create(code, Type.CREATE)); @@ -637,6 +673,7 @@ public void commit() { commitDelegatedResourceCache(repository); commitVotesCache(repository); commitDelegationCache(repository); + commitDelegatedResourceAccountIndexCache(repository); } @Override @@ -685,6 +722,11 @@ public void putDelegation(Key key, Value value) { delegationCache.put(key, value); } + @Override + public void putDelegatedResourceAccountIndex(Key key, Value value) { + delegatedResourceAccountIndexCache.put(key, value); + } + @Override public long addTokenBalance(byte[] address, byte[] tokenId, long value) { byte[] tokenIdWithoutLeadingZero = ByteUtil.stripLeadingZeroes(tokenId); @@ -800,6 +842,39 @@ public long getSlotByTimestampMs(long timestamp) { / BLOCK_PRODUCED_INTERVAL; } + @Override + public void unlockExpireResource(byte[] from, byte[] to, long now) { + byte[] lockKey = DelegatedResourceCapsule.createDbKeyV2(from, to, true); + DelegatedResourceCapsule lockResource = getDelegatedResource(lockKey); + if (lockResource == null) { + return; + } + if (lockResource.getExpireTimeForEnergy() >= now + && lockResource.getExpireTimeForBandwidth() >= now) { + return; + } + + byte[] unlockKey = DelegatedResourceCapsule.createDbKeyV2(from, to, false); + DelegatedResourceCapsule unlockResource = getDelegatedResource(unlockKey); + if (unlockResource == null) { + unlockResource = new DelegatedResourceCapsule(ByteString.copyFrom(from), + ByteString.copyFrom(to)); + } + if (lockResource.getExpireTimeForEnergy() < now) { + unlockResource.addFrozenBalanceForEnergy( + lockResource.getFrozenBalanceForEnergy(), 0); + lockResource.setFrozenBalanceForEnergy(0, 0); + } + if (lockResource.getExpireTimeForBandwidth() < now) { + unlockResource.addFrozenBalanceForBandwidth( + lockResource.getFrozenBalanceForBandwidth(), 0); + lockResource.setFrozenBalanceForBandwidth(0, 0); + } + + updateDelegatedResource(lockKey, lockResource); + updateDelegatedResource(unlockKey, unlockResource); + } + private void commitAccountCache(Repository deposit) { accountCache.forEach((key, value) -> { if (value.getType().isCreate() || value.getType().isDirty()) { @@ -901,6 +976,23 @@ private void commitDelegationCache(Repository deposit) { }); } + private void commitDelegatedResourceAccountIndexCache(Repository deposit) { + delegatedResourceAccountIndexCache.forEach(((key, value) -> { + if (value.getType().isDirty() || value.getType().isCreate()) { + if (deposit != null) { + deposit.putDelegatedResourceAccountIndex(key, value); + } else { + if (value.getValue() == null) { + getDelegatedResourceAccountIndexStore().delete(key.getData()); + } else { + getDelegatedResourceAccountIndexStore().put(key.getData(), + new DelegatedResourceAccountIndexCapsule(value.getValue())); + } + } + } + })); + } + /** * Get the block id from the number. */ diff --git a/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java b/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java index 435f71c9a64..2afa2cf6917 100644 --- a/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java @@ -6,6 +6,8 @@ import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; + +import lombok.Getter; import org.apache.commons.lang3.ArrayUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -20,7 +22,9 @@ public class DelegatedResourceAccountIndexStore extends private static final byte[] FROM_PREFIX = {0x01}; private static final byte[] TO_PREFIX = {0x02}; + @Getter private static final byte[] V2_FROM_PREFIX = {0x03}; + @Getter private static final byte[] V2_TO_PREFIX = {0x04}; @Autowired From 8befb76b19e74474c5bcce862e475c62489be7cb Mon Sep 17 00:00:00 2001 From: Liulei Date: Wed, 21 Dec 2022 11:13:40 +0800 Subject: [PATCH 0469/1197] feat(freezeV2): merge stake 2.0 new features --- .../actuator/DelegateResourceActuator.java | 122 ++++----- .../actuator/FreezeBalanceV2Actuator.java | 118 ++++----- .../actuator/UnDelegateResourceActuator.java | 245 +++++++++--------- .../actuator/UnfreezeBalanceV2Actuator.java | 171 ++++++------ .../WithdrawExpireUnfreezeActuator.java | 81 +++--- 5 files changed, 367 insertions(+), 370 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 891c6505eda..f91c147e3ee 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -1,7 +1,13 @@ package org.tron.core.actuator; +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; +import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; +import java.util.Arrays; +import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.tron.common.utils.DecodeUtil; @@ -23,13 +29,6 @@ import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.BalanceContract.DelegateResourceContract; -import java.util.Arrays; -import java.util.Objects; - -import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; -import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; - @Slf4j(topic = "actuator") public class DelegateResourceActuator extends AbstractActuator { @@ -37,6 +36,60 @@ public DelegateResourceActuator() { super(ContractType.DelegateResourceContract, DelegateResourceContract.class); } + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + + long fee = calcFee(); + final DelegateResourceContract delegateResourceContract; + AccountStore accountStore = chainBaseManager.getAccountStore(); + try { + delegateResourceContract = any.unpack(DelegateResourceContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + + AccountCapsule ownerCapsule = accountStore + .get(delegateResourceContract.getOwnerAddress().toByteArray()); + + long delegateBalance = delegateResourceContract.getBalance(); + boolean lock = delegateResourceContract.getLock(); + byte[] ownerAddress = delegateResourceContract.getOwnerAddress().toByteArray(); + byte[] receiverAddress = delegateResourceContract.getReceiverAddress().toByteArray(); + + // delegate resource to receiver + switch (delegateResourceContract.getResource()) { + case BANDWIDTH: + delegateResource(ownerAddress, receiverAddress, true, + delegateBalance, lock); + + ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(delegateBalance); + ownerCapsule.addFrozenBalanceForBandwidthV2(-delegateBalance); + break; + case ENERGY: + delegateResource(ownerAddress, receiverAddress, false, + delegateBalance, lock); + + ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(delegateBalance); + ownerCapsule.addFrozenBalanceForEnergyV2(-delegateBalance); + break; + default: + logger.debug("Resource Code Error."); + } + + accountStore.put(ownerCapsule.createDbKey(), ownerCapsule); + + ret.setStatus(fee, code.SUCESS); + + return true; + } + + @Override public boolean validate() throws ContractValidateException { if (this.any == null) { @@ -128,7 +181,7 @@ public boolean validate() throws ContractValidateException { if (ownerCapsule.getFrozenV2BalanceForEnergy() - remainEnergyUsage < delegateBalance) { throw new ContractValidateException( - "delegateBalance must be less than available FreezeEnergyV2 balance"); + "delegateBalance must be less than available FreezeEnergyV2 balance"); } } break; @@ -165,59 +218,6 @@ public boolean validate() throws ContractValidateException { return true; } - @Override - public boolean execute(Object result) throws ContractExeException { - TransactionResultCapsule ret = (TransactionResultCapsule) result; - if (Objects.isNull(ret)) { - throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); - } - - long fee = calcFee(); - final DelegateResourceContract delegateResourceContract; - AccountStore accountStore = chainBaseManager.getAccountStore(); - try { - delegateResourceContract = any.unpack(DelegateResourceContract.class); - } catch (InvalidProtocolBufferException e) { - logger.debug(e.getMessage(), e); - ret.setStatus(fee, code.FAILED); - throw new ContractExeException(e.getMessage()); - } - - AccountCapsule ownerCapsule = accountStore - .get(delegateResourceContract.getOwnerAddress().toByteArray()); - - long delegateBalance = delegateResourceContract.getBalance(); - boolean lock = delegateResourceContract.getLock(); - byte[] ownerAddress = delegateResourceContract.getOwnerAddress().toByteArray(); - byte[] receiverAddress = delegateResourceContract.getReceiverAddress().toByteArray(); - - // delegate resource to receiver - switch (delegateResourceContract.getResource()) { - case BANDWIDTH: - delegateResource(ownerAddress, receiverAddress, true, - delegateBalance, lock); - - ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(delegateBalance); - ownerCapsule.addFrozenBalanceForBandwidthV2(-delegateBalance); - break; - case ENERGY: - delegateResource(ownerAddress, receiverAddress, false, - delegateBalance, lock); - - ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(delegateBalance); - ownerCapsule.addFrozenBalanceForEnergyV2(-delegateBalance); - break; - default: - logger.debug("Resource Code Error."); - } - - accountStore.put(ownerCapsule.createDbKey(), ownerCapsule); - - ret.setStatus(fee, code.SUCESS); - - return true; - } - @Override public ByteString getOwnerAddress() throws InvalidProtocolBufferException { return any.unpack(DelegateResourceContract.class).getOwnerAddress(); diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java index cde31e6ebf5..90b03e43e1a 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java @@ -29,6 +29,65 @@ public FreezeBalanceV2Actuator() { super(ContractType.FreezeBalanceV2Contract, FreezeBalanceV2Contract.class); } + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + + long fee = calcFee(); + final FreezeBalanceV2Contract freezeBalanceV2Contract; + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + try { + freezeBalanceV2Contract = any.unpack(FreezeBalanceV2Contract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + AccountCapsule accountCapsule = accountStore.get(freezeBalanceV2Contract.getOwnerAddress().toByteArray()); + + if (dynamicStore.supportAllowNewResourceModel() + && accountCapsule.oldTronPowerIsNotInitialized()) { + accountCapsule.initializeOldTronPower(); + } + + long newBalance = accountCapsule.getBalance() - freezeBalanceV2Contract.getFrozenBalance(); + long frozenBalance = freezeBalanceV2Contract.getFrozenBalance(); + + switch (freezeBalanceV2Contract.getResource()) { + case BANDWIDTH: + long oldNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + long newNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; + dynamicStore.addTotalNetWeight(newNetWeight - oldNetWeight); + break; + case ENERGY: + long oldEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; + accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); + long newEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; + dynamicStore.addTotalEnergyWeight(newEnergyWeight - oldEnergyWeight); + break; + case TRON_POWER: + long oldTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; + accountCapsule.addFrozenForTronPowerV2(frozenBalance); + long newTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; + dynamicStore.addTotalTronPowerWeight(newTPWeight - oldTPWeight); + break; + default: + logger.debug("Resource Code Error."); + } + + accountCapsule.setBalance(newBalance); + accountStore.put(accountCapsule.createDbKey(), accountCapsule); + + ret.setStatus(fee, code.SUCESS); + + return true; + } + @Override public boolean validate() throws ContractValidateException { if (this.any == null) { @@ -104,65 +163,6 @@ public boolean validate() throws ContractValidateException { return true; } - @Override - public boolean execute(Object result) throws ContractExeException { - TransactionResultCapsule ret = (TransactionResultCapsule) result; - if (Objects.isNull(ret)) { - throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); - } - - long fee = calcFee(); - final FreezeBalanceV2Contract freezeBalanceV2Contract; - AccountStore accountStore = chainBaseManager.getAccountStore(); - DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); - try { - freezeBalanceV2Contract = any.unpack(FreezeBalanceV2Contract.class); - } catch (InvalidProtocolBufferException e) { - logger.debug(e.getMessage(), e); - ret.setStatus(fee, code.FAILED); - throw new ContractExeException(e.getMessage()); - } - AccountCapsule accountCapsule = accountStore.get(freezeBalanceV2Contract.getOwnerAddress().toByteArray()); - - if (dynamicStore.supportAllowNewResourceModel() - && accountCapsule.oldTronPowerIsNotInitialized()) { - accountCapsule.initializeOldTronPower(); - } - - long newBalance = accountCapsule.getBalance() - freezeBalanceV2Contract.getFrozenBalance(); - long frozenBalance = freezeBalanceV2Contract.getFrozenBalance(); - - switch (freezeBalanceV2Contract.getResource()) { - case BANDWIDTH: - long oldNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; - accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); - long newNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; - dynamicStore.addTotalNetWeight(newNetWeight - oldNetWeight); - break; - case ENERGY: - long oldEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; - accountCapsule.addFrozenBalanceForEnergyV2(frozenBalance); - long newEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; - dynamicStore.addTotalEnergyWeight(newEnergyWeight - oldEnergyWeight); - break; - case TRON_POWER: - long oldTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; - accountCapsule.addFrozenForTronPowerV2(frozenBalance); - long newTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; - dynamicStore.addTotalTronPowerWeight(newTPWeight - oldTPWeight); - break; - default: - logger.debug("Resource Code Error."); - } - - accountCapsule.setBalance(newBalance); - accountStore.put(accountCapsule.createDbKey(), accountCapsule); - - ret.setStatus(fee, code.SUCESS); - - return true; - } - @Override public ByteString getOwnerAddress() throws InvalidProtocolBufferException { return any.unpack(FreezeBalanceV2Contract.class).getOwnerAddress(); diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index 2f8149efc6f..a99d462b61c 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -1,7 +1,14 @@ package org.tron.core.actuator; +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; + import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; +import java.util.Arrays; +import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.tron.common.utils.DecodeUtil; @@ -21,14 +28,6 @@ import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.BalanceContract.UnDelegateResourceContract; -import java.util.Arrays; -import java.util.Objects; - -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; -import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; -import static org.tron.protos.contract.Common.ResourceCode.ENERGY; - @Slf4j(topic = "actuator") public class UnDelegateResourceActuator extends AbstractActuator { @@ -36,121 +35,6 @@ public UnDelegateResourceActuator() { super(ContractType.UnDelegateResourceContract, UnDelegateResourceContract.class); } - @Override - public boolean validate() throws ContractValidateException { - if (this.any == null) { - throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); - } - if (chainBaseManager == null) { - throw new ContractValidateException(ActuatorConstant.STORE_NOT_EXIST); - } - AccountStore accountStore = chainBaseManager.getAccountStore(); - DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); - DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore(); - if (!dynamicStore.supportDR()) { - throw new ContractValidateException("No support for resource delegate"); - } - - if (!dynamicStore.supportUnfreezeDelay()) { - throw new ContractValidateException("Not support unDelegate resource transaction," - + " need to be opened by the committee"); - } - - if (!this.any.is(UnDelegateResourceContract.class)) { - throw new ContractValidateException( - "contract type error, expected type [UnDelegateResourceContract], real type[" + any - .getClass() + "]"); - } - final UnDelegateResourceContract unDelegateResourceContract; - try { - unDelegateResourceContract = this.any.unpack(UnDelegateResourceContract.class); - } catch (InvalidProtocolBufferException e) { - logger.debug(e.getMessage(), e); - throw new ContractValidateException(e.getMessage()); - } - - byte[] ownerAddress = unDelegateResourceContract.getOwnerAddress().toByteArray(); - if (!DecodeUtil.addressValid(ownerAddress)) { - throw new ContractValidateException("Invalid address"); - } - AccountCapsule ownerCapsule = accountStore.get(ownerAddress); - if (ownerCapsule == null) { - String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); - throw new ContractValidateException( - ACCOUNT_EXCEPTION_STR + readableOwnerAddress + "] does not exist"); - } - - byte[] receiverAddress = unDelegateResourceContract.getReceiverAddress().toByteArray(); - if (ArrayUtils.isEmpty(receiverAddress) || !DecodeUtil.addressValid(receiverAddress)) { - throw new ContractValidateException("Invalid receiverAddress"); - } - if (Arrays.equals(receiverAddress, ownerAddress)) { - throw new ContractValidateException( - "receiverAddress must not be the same as ownerAddress"); - } - - // TVM contract suicide can result in no receiving account - // AccountCapsule receiverCapsule = accountStore.get(receiverAddress); - // if (receiverCapsule == null) { - // String readableReceiverAddress = StringUtil.createReadableString(receiverAddress); - // throw new ContractValidateException( - // "Receiver Account[" + readableReceiverAddress + "] does not exist"); - // } - - long now = dynamicStore.getLatestBlockHeaderTimestamp(); - byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, false); - DelegatedResourceCapsule unlockResourceCapsule = delegatedResourceStore.get(key); - byte[] lockKey = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, true); - DelegatedResourceCapsule lockResourceCapsule = delegatedResourceStore.get(lockKey); - if (unlockResourceCapsule == null && lockResourceCapsule == null) { - throw new ContractValidateException( - "delegated Resource does not exist"); - } - - long unDelegateBalance = unDelegateResourceContract.getBalance(); - if (unDelegateBalance <= 0) { - throw new ContractValidateException("unDelegateBalance must be more than 0 TRX"); - } - switch (unDelegateResourceContract.getResource()) { - case BANDWIDTH: { - long delegateBalance = 0; - if (unlockResourceCapsule != null) { - delegateBalance += unlockResourceCapsule.getFrozenBalanceForBandwidth(); - } - if (lockResourceCapsule != null - && lockResourceCapsule.getExpireTimeForBandwidth() < now) { - delegateBalance += lockResourceCapsule.getFrozenBalanceForBandwidth(); - } - if (delegateBalance < unDelegateBalance) { - throw new ContractValidateException( - "insufficient delegatedFrozenBalance(BANDWIDTH), request=" - + unDelegateBalance + ", unlock_balance=" + delegateBalance); - } - } - break; - case ENERGY: { - long delegateBalance = 0; - if (unlockResourceCapsule != null) { - delegateBalance += unlockResourceCapsule.getFrozenBalanceForEnergy(); - } - if (lockResourceCapsule != null - && lockResourceCapsule.getExpireTimeForEnergy() < now) { - delegateBalance += lockResourceCapsule.getFrozenBalanceForEnergy(); - } - if (delegateBalance < unDelegateBalance) { - throw new ContractValidateException("insufficient delegateFrozenBalance(Energy), request=" - + unDelegateBalance + ", unlock_balance=" + delegateBalance); - } - } - break; - default: - throw new ContractValidateException( - "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); - } - - return true; - } - @Override public boolean execute(Object result) throws ContractExeException { TransactionResultCapsule ret = (TransactionResultCapsule) result; @@ -311,6 +195,121 @@ public boolean execute(Object result) throws ContractExeException { return true; } + @Override + public boolean validate() throws ContractValidateException { + if (this.any == null) { + throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); + } + if (chainBaseManager == null) { + throw new ContractValidateException(ActuatorConstant.STORE_NOT_EXIST); + } + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore(); + if (!dynamicStore.supportDR()) { + throw new ContractValidateException("No support for resource delegate"); + } + + if (!dynamicStore.supportUnfreezeDelay()) { + throw new ContractValidateException("Not support unDelegate resource transaction," + + " need to be opened by the committee"); + } + + if (!this.any.is(UnDelegateResourceContract.class)) { + throw new ContractValidateException( + "contract type error, expected type [UnDelegateResourceContract], real type[" + any + .getClass() + "]"); + } + final UnDelegateResourceContract unDelegateResourceContract; + try { + unDelegateResourceContract = this.any.unpack(UnDelegateResourceContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + throw new ContractValidateException(e.getMessage()); + } + + byte[] ownerAddress = unDelegateResourceContract.getOwnerAddress().toByteArray(); + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + AccountCapsule ownerCapsule = accountStore.get(ownerAddress); + if (ownerCapsule == null) { + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + throw new ContractValidateException( + ACCOUNT_EXCEPTION_STR + readableOwnerAddress + "] does not exist"); + } + + byte[] receiverAddress = unDelegateResourceContract.getReceiverAddress().toByteArray(); + if (ArrayUtils.isEmpty(receiverAddress) || !DecodeUtil.addressValid(receiverAddress)) { + throw new ContractValidateException("Invalid receiverAddress"); + } + if (Arrays.equals(receiverAddress, ownerAddress)) { + throw new ContractValidateException( + "receiverAddress must not be the same as ownerAddress"); + } + + // TVM contract suicide can result in no receiving account + // AccountCapsule receiverCapsule = accountStore.get(receiverAddress); + // if (receiverCapsule == null) { + // String readableReceiverAddress = StringUtil.createReadableString(receiverAddress); + // throw new ContractValidateException( + // "Receiver Account[" + readableReceiverAddress + "] does not exist"); + // } + + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, false); + DelegatedResourceCapsule unlockResourceCapsule = delegatedResourceStore.get(key); + byte[] lockKey = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, true); + DelegatedResourceCapsule lockResourceCapsule = delegatedResourceStore.get(lockKey); + if (unlockResourceCapsule == null && lockResourceCapsule == null) { + throw new ContractValidateException( + "delegated Resource does not exist"); + } + + long unDelegateBalance = unDelegateResourceContract.getBalance(); + if (unDelegateBalance <= 0) { + throw new ContractValidateException("unDelegateBalance must be more than 0 TRX"); + } + switch (unDelegateResourceContract.getResource()) { + case BANDWIDTH: { + long delegateBalance = 0; + if (unlockResourceCapsule != null) { + delegateBalance += unlockResourceCapsule.getFrozenBalanceForBandwidth(); + } + if (lockResourceCapsule != null + && lockResourceCapsule.getExpireTimeForBandwidth() < now) { + delegateBalance += lockResourceCapsule.getFrozenBalanceForBandwidth(); + } + if (delegateBalance < unDelegateBalance) { + throw new ContractValidateException( + "insufficient delegatedFrozenBalance(BANDWIDTH), request=" + + unDelegateBalance + ", unlock_balance=" + delegateBalance); + } + } + break; + case ENERGY: { + long delegateBalance = 0; + if (unlockResourceCapsule != null) { + delegateBalance += unlockResourceCapsule.getFrozenBalanceForEnergy(); + } + if (lockResourceCapsule != null + && lockResourceCapsule.getExpireTimeForEnergy() < now) { + delegateBalance += lockResourceCapsule.getFrozenBalanceForEnergy(); + } + if (delegateBalance < unDelegateBalance) { + throw new ContractValidateException("insufficient delegateFrozenBalance(Energy), request=" + + unDelegateBalance + ", unlock_balance=" + delegateBalance); + } + } + break; + default: + throw new ContractValidateException( + "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + } + + return true; + } + @Override public ByteString getOwnerAddress() throws InvalidProtocolBufferException { return any.unpack(UnDelegateResourceContract.class).getOwnerAddress(); diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java index fdceac098d2..53bcadc8bf9 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java @@ -1,8 +1,19 @@ package org.tron.core.actuator; +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; +import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; + import com.google.common.collect.Lists; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; @@ -24,18 +35,6 @@ import org.tron.protos.Protocol.Vote; import org.tron.protos.contract.BalanceContract.UnfreezeBalanceV2Contract; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; - -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; -import static org.tron.protos.contract.Common.ResourceCode; -import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; -import static org.tron.protos.contract.Common.ResourceCode.ENERGY; -import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; - @Slf4j(topic = "actuator") public class UnfreezeBalanceV2Actuator extends AbstractActuator { @@ -46,6 +45,60 @@ public UnfreezeBalanceV2Actuator() { super(ContractType.UnfreezeBalanceV2Contract, UnfreezeBalanceV2Contract.class); } + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + + long fee = calcFee(); + final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract; + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + MortgageService mortgageService = chainBaseManager.getMortgageService(); + try { + unfreezeBalanceV2Contract = any.unpack(UnfreezeBalanceV2Contract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + byte[] ownerAddress = unfreezeBalanceV2Contract.getOwnerAddress().toByteArray(); + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + + mortgageService.withdrawReward(ownerAddress); + + AccountCapsule accountCapsule = accountStore.get(ownerAddress); + long unfreezeAmount = this.unfreezeExpire(accountCapsule, now); + long unfreezeBalance = unfreezeBalanceV2Contract.getUnfreezeBalance(); + + if (dynamicStore.supportAllowNewResourceModel() + && accountCapsule.oldTronPowerIsNotInitialized()) { + accountCapsule.initializeOldTronPower(); + } + + ResourceCode freezeType = unfreezeBalanceV2Contract.getResource(); + + long expireTime = this.calcUnfreezeExpireTime(now); + accountCapsule.addUnfrozenV2List(freezeType, unfreezeBalance, expireTime); + + this.updateTotalResourceWeight(accountCapsule, unfreezeBalanceV2Contract, unfreezeBalance); + this.updateVote(accountCapsule, unfreezeBalanceV2Contract, ownerAddress); + + if (dynamicStore.supportAllowNewResourceModel() + && !accountCapsule.oldTronPowerIsInvalid()) { + accountCapsule.invalidateOldTronPower(); + } + + accountStore.put(ownerAddress, accountCapsule); + + ret.setUnfreezeAmount(unfreezeBalance); + ret.setWithdrawExpireAmount(unfreezeAmount); + ret.setStatus(fee, code.SUCESS); + return true; + } + @Override public boolean validate() throws ContractValidateException { if (this.any == null) { @@ -130,6 +183,26 @@ public boolean validate() throws ContractValidateException { return true; } + @Override + public ByteString getOwnerAddress() throws InvalidProtocolBufferException { + return any.unpack(UnfreezeBalanceV2Contract.class).getOwnerAddress(); + } + + @Override + public long calcFee() { + return 0; + } + + public boolean checkExistFrozenBalance(AccountCapsule accountCapsule, ResourceCode freezeType) { + List frozenV2List = accountCapsule.getFrozenV2List(); + for (FreezeV2 frozenV2 : frozenV2List) { + if (frozenV2.getType().equals(freezeType) && frozenV2.getAmount() > 0) { + return true; + } + } + return false; + } + public boolean checkUnfreezeBalance(AccountCapsule accountCapsule, final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract, ResourceCode freezeType) { @@ -152,80 +225,6 @@ public boolean checkUnfreezeBalance(AccountCapsule accountCapsule, return checkOk; } - public boolean checkExistFrozenBalance(AccountCapsule accountCapsule, ResourceCode freezeType) { - List frozenV2List = accountCapsule.getFrozenV2List(); - for (FreezeV2 frozenV2 : frozenV2List) { - if (frozenV2.getType().equals(freezeType) && frozenV2.getAmount() > 0) { - return true; - } - } - return false; - } - - @Override - public boolean execute(Object result) throws ContractExeException { - TransactionResultCapsule ret = (TransactionResultCapsule) result; - if (Objects.isNull(ret)) { - throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); - } - - long fee = calcFee(); - final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract; - AccountStore accountStore = chainBaseManager.getAccountStore(); - DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); - MortgageService mortgageService = chainBaseManager.getMortgageService(); - try { - unfreezeBalanceV2Contract = any.unpack(UnfreezeBalanceV2Contract.class); - } catch (InvalidProtocolBufferException e) { - logger.debug(e.getMessage(), e); - ret.setStatus(fee, code.FAILED); - throw new ContractExeException(e.getMessage()); - } - byte[] ownerAddress = unfreezeBalanceV2Contract.getOwnerAddress().toByteArray(); - long now = dynamicStore.getLatestBlockHeaderTimestamp(); - - mortgageService.withdrawReward(ownerAddress); - - AccountCapsule accountCapsule = accountStore.get(ownerAddress); - long unfreezeAmount = this.unfreezeExpire(accountCapsule, now); - long unfreezeBalance = unfreezeBalanceV2Contract.getUnfreezeBalance(); - - if (dynamicStore.supportAllowNewResourceModel() - && accountCapsule.oldTronPowerIsNotInitialized()) { - accountCapsule.initializeOldTronPower(); - } - - ResourceCode freezeType = unfreezeBalanceV2Contract.getResource(); - - long expireTime = this.calcUnfreezeExpireTime(now); - accountCapsule.addUnfrozenV2List(freezeType, unfreezeBalance, expireTime); - - this.updateTotalResourceWeight(accountCapsule, unfreezeBalanceV2Contract, unfreezeBalance); - this.updateVote(accountCapsule, unfreezeBalanceV2Contract, ownerAddress); - - if (dynamicStore.supportAllowNewResourceModel() - && !accountCapsule.oldTronPowerIsInvalid()) { - accountCapsule.invalidateOldTronPower(); - } - - accountStore.put(ownerAddress, accountCapsule); - - ret.setUnfreezeAmount(unfreezeBalance); - ret.setWithdrawExpireAmount(unfreezeAmount); - ret.setStatus(fee, code.SUCESS); - return true; - } - - @Override - public ByteString getOwnerAddress() throws InvalidProtocolBufferException { - return any.unpack(UnfreezeBalanceV2Contract.class).getOwnerAddress(); - } - - @Override - public long calcFee() { - return 0; - } - public long calcUnfreezeExpireTime(long now) { DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); long unfreezeDelayDays = dynamicStore.getUnfreezeDelayDays(); diff --git a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java index decabdb7192..0c547d2b5a3 100755 --- a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java @@ -1,8 +1,14 @@ package org.tron.core.actuator; +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; + import com.google.common.math.LongMath; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; @@ -17,13 +23,6 @@ import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.BalanceContract.WithdrawExpireUnfreezeContract; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; - @Slf4j(topic = "actuator") public class WithdrawExpireUnfreezeActuator extends AbstractActuator { @@ -32,6 +31,40 @@ public WithdrawExpireUnfreezeActuator() { super(ContractType.WithdrawExpireUnfreezeContract, WithdrawExpireUnfreezeContract.class); } + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + long fee = calcFee(); + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + final WithdrawExpireUnfreezeContract withdrawExpireUnfreezeContract; + try { + withdrawExpireUnfreezeContract = any.unpack(WithdrawExpireUnfreezeContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + AccountCapsule accountCapsule = accountStore.get( + withdrawExpireUnfreezeContract.getOwnerAddress().toByteArray()); + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); + long totalWithdrawUnfreeze = getTotalWithdrawUnfreeze(unfrozenV2List, now); + accountCapsule.setInstance(accountCapsule.getInstance().toBuilder() + .setBalance(accountCapsule.getBalance() + totalWithdrawUnfreeze) + .build()); + List newUnFreezeList = getRemainWithdrawList(unfrozenV2List, now); + accountCapsule.clearUnfrozenV2(); + accountCapsule.addAllUnfrozenV2(newUnFreezeList); + accountStore.put(accountCapsule.createDbKey(), accountCapsule); + ret.setWithdrawExpireAmount(totalWithdrawUnfreeze); + ret.setStatus(fee, code.SUCESS); + return true; + } + @Override public boolean validate() throws ContractValidateException { if (Objects.isNull(this.any)) { @@ -96,40 +129,6 @@ private List getTotalWithdrawList(List unfrozenV2List, l && unfrozenV2.getUnfreezeExpireTime() <= now)).collect(Collectors.toList()); } - @Override - public boolean execute(Object result) throws ContractExeException { - TransactionResultCapsule ret = (TransactionResultCapsule) result; - if (Objects.isNull(ret)) { - throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); - } - long fee = calcFee(); - AccountStore accountStore = chainBaseManager.getAccountStore(); - DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); - final WithdrawExpireUnfreezeContract withdrawExpireUnfreezeContract; - try { - withdrawExpireUnfreezeContract = any.unpack(WithdrawExpireUnfreezeContract.class); - } catch (InvalidProtocolBufferException e) { - logger.debug(e.getMessage(), e); - ret.setStatus(fee, code.FAILED); - throw new ContractExeException(e.getMessage()); - } - AccountCapsule accountCapsule = accountStore.get( - withdrawExpireUnfreezeContract.getOwnerAddress().toByteArray()); - long now = dynamicStore.getLatestBlockHeaderTimestamp(); - List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); - long totalWithdrawUnfreeze = getTotalWithdrawUnfreeze(unfrozenV2List, now); - accountCapsule.setInstance(accountCapsule.getInstance().toBuilder() - .setBalance(accountCapsule.getBalance() + totalWithdrawUnfreeze) - .build()); - List newUnFreezeList = getRemainWithdrawList(unfrozenV2List, now); - accountCapsule.clearUnfrozenV2(); - accountCapsule.addAllUnfrozenV2(newUnFreezeList); - accountStore.put(accountCapsule.createDbKey(), accountCapsule); - ret.setWithdrawExpireAmount(totalWithdrawUnfreeze); - ret.setStatus(fee, code.SUCESS); - return true; - } - private List getRemainWithdrawList(List unfrozenV2List, long now) { return unfrozenV2List.stream() .filter(unfrozenV2 -> unfrozenV2.getUnfreezeExpireTime() > now) From 9ad5bfd79c7316f83e4d45c7107ea18034188997 Mon Sep 17 00:00:00 2001 From: Liulei Date: Wed, 21 Dec 2022 15:04:04 +0800 Subject: [PATCH 0470/1197] feat(freezeV2): merge stake 2.0 new features --- .../org/tron/core/vm/OperationActions.java | 16 ++-- .../DelegateResourceProcessor.java | 38 +++------ .../UnDelegateResourceProcessor.java | 79 +++++++------------ .../param/DelegateResourceParam.java | 10 --- .../tron/core/vm/program/ContractState.java | 4 - .../org/tron/core/vm/program/Program.java | 36 ++++----- .../tron/core/vm/repository/Repository.java | 1 - .../core/vm/repository/RepositoryImpl.java | 49 +++--------- 8 files changed, 74 insertions(+), 159 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index 793bc925903..9895b24910f 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -1,18 +1,17 @@ package org.tron.core.vm; +import static org.tron.common.crypto.Hash.sha3; +import static org.tron.common.utils.ByteUtil.EMPTY_BYTE_ARRAY; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; import org.tron.common.runtime.vm.DataWord; import org.tron.common.runtime.vm.LogInfo; import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.program.Program; import org.tron.core.vm.program.Stack; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; - -import static org.tron.common.crypto.Hash.sha3; -import static org.tron.common.utils.ByteUtil.EMPTY_BYTE_ARRAY; - public class OperationActions { private static final BigInteger _32_ = BigInteger.valueOf(32); @@ -819,12 +818,11 @@ public static void delegateResourceAction(Program program) { if (program.isStaticCall()) { throw new Program.StaticCallModificationException(); } - DataWord lock = program.stackPop(); DataWord resourceType = program.stackPop(); DataWord delegateBalance = program.stackPop(); DataWord receiverAddress = program.stackPop(); - boolean result = program.delegateResource(receiverAddress, delegateBalance, resourceType, lock); + boolean result = program.delegateResource(receiverAddress, delegateBalance, resourceType); program.stackPush(result ? DataWord.ONE() : DataWord.ZERO()); program.step(); } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index 03912abfc18..66ea919d713 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -1,7 +1,12 @@ package org.tron.core.vm.nativecontract; +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + import com.google.common.primitives.Bytes; import com.google.protobuf.ByteString; +import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.tron.common.utils.DecodeUtil; @@ -20,13 +25,6 @@ import org.tron.core.vm.repository.Repository; import org.tron.protos.Protocol; -import java.util.Arrays; - -import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; -import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; -import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; - @Slf4j(topic = "VMProcessor") public class DelegateResourceProcessor { @@ -128,20 +126,19 @@ public void execute(DelegateResourceParam param, Repository repo) { AccountCapsule ownerCapsule = repo.getAccount(param.getOwnerAddress()); long delegateBalance = param.getDelegateBalance(); byte[] receiverAddress = param.getReceiverAddress(); - boolean lock = param.isLock(); // delegate resource to receiver switch (param.getResourceType()) { case BANDWIDTH: delegateResource(ownerAddress, receiverAddress, true, - delegateBalance, repo, lock); + delegateBalance, repo); ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(delegateBalance); ownerCapsule.addFrozenBalanceForBandwidthV2(-delegateBalance); break; case ENERGY: delegateResource(ownerAddress, receiverAddress, false, - delegateBalance, repo, lock); + delegateBalance, repo); ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(delegateBalance); ownerCapsule.addFrozenBalanceForEnergyV2(-delegateBalance); @@ -158,32 +155,23 @@ private void delegateResource( byte[] receiverAddress, boolean isBandwidth, long delegateBalance, - Repository repo, - boolean lock) { - // unlock the expired delegate resource - long now = repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); - repo.unlockExpireResource(ownerAddress, receiverAddress, now); - - //modify DelegatedResource - byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, lock); + Repository repo) { + //modify DelegatedResourceStore + byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, false); DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); if (delegatedResourceCapsule == null) { delegatedResourceCapsule = new DelegatedResourceCapsule( ByteString.copyFrom(ownerAddress), ByteString.copyFrom(receiverAddress)); } - long expireTime = 0; - if (lock) { - expireTime = - repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp() + DELEGATE_PERIOD; - } if (isBandwidth) { - delegatedResourceCapsule.addFrozenBalanceForBandwidth(delegateBalance, expireTime); + delegatedResourceCapsule.addFrozenBalanceForBandwidth(delegateBalance, 0); } else { - delegatedResourceCapsule.addFrozenBalanceForEnergy(delegateBalance, expireTime); + delegatedResourceCapsule.addFrozenBalanceForEnergy(delegateBalance, 0); } //modify DelegatedResourceAccountIndex + long now = repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); byte[] fromKey = Bytes.concat( DelegatedResourceAccountIndexStore.getV2_FROM_PREFIX(), ownerAddress, receiverAddress); DelegatedResourceAccountIndexCapsule toIndexCapsule = diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index b74d541a901..6bf0638570c 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -7,6 +7,7 @@ import org.tron.common.utils.StringUtil; import org.tron.core.ChainBaseManager; import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.db.BandwidthProcessor; import org.tron.core.db.EnergyProcessor; @@ -15,6 +16,7 @@ import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.vm.nativecontract.param.UnDelegateResourceParam; import org.tron.core.vm.repository.Repository; +import org.tron.protos.Protocol; import java.util.Arrays; import java.util.Objects; @@ -57,12 +59,9 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont "receiverAddress must not be the same as ownerAddress"); } - long now = dynamicStore.getLatestBlockHeaderTimestamp(); byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, false); - DelegatedResourceCapsule unlockResourceCapsule = repo.getDelegatedResource(key); - byte[] lockKey = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, true); - DelegatedResourceCapsule lockResourceCapsule = repo.getDelegatedResource(lockKey); - if (unlockResourceCapsule == null && lockResourceCapsule == null) { + DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); + if (delegatedResourceCapsule == null) { throw new ContractValidateException( "delegated Resource does not exist"); } @@ -72,37 +71,18 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont throw new ContractValidateException("unDelegateBalance must be more than 0 TRX"); } switch (param.getResourceType()) { - case BANDWIDTH: { - long delegateBalance = 0; - if (unlockResourceCapsule != null) { - delegateBalance += unlockResourceCapsule.getFrozenBalanceForBandwidth(); - } - if (lockResourceCapsule != null - && lockResourceCapsule.getExpireTimeForBandwidth() < now) { - delegateBalance += lockResourceCapsule.getFrozenBalanceForBandwidth(); - } - if (delegateBalance < unDelegateBalance) { - throw new ContractValidateException( - "insufficient delegatedFrozenBalance(BANDWIDTH), request=" - + unDelegateBalance + ", unlock_balance=" + delegateBalance); - } - } - break; - case ENERGY: { - long delegateBalance = 0; - if (unlockResourceCapsule != null) { - delegateBalance += unlockResourceCapsule.getFrozenBalanceForEnergy(); + case BANDWIDTH: + if (delegatedResourceCapsule.getFrozenBalanceForBandwidth() < unDelegateBalance) { + throw new ContractValidateException("insufficient delegatedFrozenBalance(BANDWIDTH), request=" + + unDelegateBalance + ", balance=" + delegatedResourceCapsule.getFrozenBalanceForBandwidth()); } - if (lockResourceCapsule != null - && lockResourceCapsule.getExpireTimeForEnergy() < now) { - delegateBalance += lockResourceCapsule.getFrozenBalanceForEnergy(); - } - if (delegateBalance < unDelegateBalance) { + break; + case ENERGY: + if (delegatedResourceCapsule.getFrozenBalanceForEnergy() < unDelegateBalance) { throw new ContractValidateException("insufficient delegateFrozenBalance(ENERGY), request=" - + unDelegateBalance + ", unlock_balance=" + delegateBalance); + + unDelegateBalance + ", balance=" + delegatedResourceCapsule.getFrozenBalanceForEnergy()); } - } - break; + break; default: throw new ContractValidateException( "ResourceCode error.valid ResourceCode[BANDWIDTH、ENERGY]"); @@ -176,16 +156,12 @@ public void execute(UnDelegateResourceParam param, Repository repo) { repo.updateAccount(receiverCapsule.createDbKey(), receiverCapsule); } - // transfer lock delegate to unlock - repo.unlockExpireResource( - ownerAddress, receiverAddress, dynamicStore.getLatestBlockHeaderTimestamp()); - // modify owner Account byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, false); - DelegatedResourceCapsule unlockResource = repo.getDelegatedResource(key); + DelegatedResourceCapsule delegatedResourceCapsule = repo.getDelegatedResource(key); switch (param.getResourceType()) { case BANDWIDTH: { - unlockResource.addFrozenBalanceForBandwidth(-unDelegateBalance, 0); + delegatedResourceCapsule.addFrozenBalanceForBandwidth(-unDelegateBalance, 0); ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(-unDelegateBalance); ownerCapsule.addFrozenBalanceForBandwidthV2(unDelegateBalance); @@ -199,7 +175,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { } break; case ENERGY: { - unlockResource.addFrozenBalanceForEnergy(-unDelegateBalance, 0); + delegatedResourceCapsule.addFrozenBalanceForEnergy(-unDelegateBalance, 0); ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(-unDelegateBalance); ownerCapsule.addFrozenBalanceForEnergyV2(unDelegateBalance); @@ -218,22 +194,23 @@ public void execute(UnDelegateResourceParam param, Repository repo) { break; } - byte[] lockKey = DelegatedResourceCapsule - .createDbKeyV2(ownerAddress, receiverAddress, true); - DelegatedResourceCapsule lockResource = repo.getDelegatedResource(lockKey); - if (lockResource == null - && unlockResource.getFrozenBalanceForBandwidth() == 0 - && unlockResource.getFrozenBalanceForEnergy() == 0) { + if (delegatedResourceCapsule.getFrozenBalanceForBandwidth() == 0 + && delegatedResourceCapsule.getFrozenBalanceForEnergy() == 0) { //modify DelegatedResourceAccountIndex byte[] fromKey = Bytes.concat( DelegatedResourceAccountIndexStore.getV2_FROM_PREFIX(), ownerAddress, receiverAddress); - repo.updateDelegatedResourceAccountIndex(fromKey, null); - byte[] toKey = Bytes.concat( - DelegatedResourceAccountIndexStore.getV2_TO_PREFIX(), receiverAddress, ownerAddress); - repo.updateDelegatedResourceAccountIndex(toKey, null); + repo.updateDelegatedResourceAccountIndex( + fromKey, + new DelegatedResourceAccountIndexCapsule((Protocol.DelegatedResourceAccountIndex) null)); + byte[] toKey = + Bytes.concat( + DelegatedResourceAccountIndexStore.getV2_TO_PREFIX(), receiverAddress, ownerAddress); + repo.updateDelegatedResourceAccountIndex( + toKey, + new DelegatedResourceAccountIndexCapsule((Protocol.DelegatedResourceAccountIndex) null)); } - repo.updateDelegatedResource(key, unlockResource); + repo.updateDelegatedResource(key, delegatedResourceCapsule); repo.updateAccount(ownerCapsule.createDbKey(), ownerCapsule); } } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/DelegateResourceParam.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/DelegateResourceParam.java index 2f25239ebb2..f7d897800b5 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/param/DelegateResourceParam.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/param/DelegateResourceParam.java @@ -12,8 +12,6 @@ public class DelegateResourceParam { private Common.ResourceCode resourceType; - private boolean lock; - public byte[] getOwnerAddress() { return ownerAddress; } @@ -45,12 +43,4 @@ public Common.ResourceCode getResourceType() { public void setResourceType(Common.ResourceCode resourceType) { this.resourceType = resourceType; } - - public boolean isLock() { - return lock; - } - - public void setLock(boolean lock) { - this.lock = lock; - } } diff --git a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java index 93a5ba7c535..7d4a6cff971 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java +++ b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java @@ -404,8 +404,4 @@ public long getSlotByTimestampMs(long timestamp) { return repository.getSlotByTimestampMs(timestamp); } - @Override - public void unlockExpireResource(byte[] from, byte[] to, long now) { - repository.unlockExpireResource(from, to, now); - } } diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 967a2877225..7a800a0b412 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -1,6 +1,22 @@ package org.tron.core.vm.program; +import static java.lang.StrictMath.min; +import static java.lang.String.format; +import static org.apache.commons.lang3.ArrayUtils.EMPTY_BYTE_ARRAY; +import static org.apache.commons.lang3.ArrayUtils.getLength; +import static org.apache.commons.lang3.ArrayUtils.isEmpty; +import static org.apache.commons.lang3.ArrayUtils.isNotEmpty; +import static org.apache.commons.lang3.ArrayUtils.nullToEmpty; +import static org.tron.common.utils.ByteUtil.stripLeadingZeroes; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + import com.google.protobuf.ByteString; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.map.LRUMap; @@ -76,23 +92,6 @@ import org.tron.protos.contract.SmartContractOuterClass.SmartContract; import org.tron.protos.contract.SmartContractOuterClass.SmartContract.Builder; -import java.math.BigInteger; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.stream.Collectors; - -import static java.lang.StrictMath.min; -import static java.lang.String.format; -import static org.apache.commons.lang3.ArrayUtils.EMPTY_BYTE_ARRAY; -import static org.apache.commons.lang3.ArrayUtils.getLength; -import static org.apache.commons.lang3.ArrayUtils.isEmpty; -import static org.apache.commons.lang3.ArrayUtils.isNotEmpty; -import static org.apache.commons.lang3.ArrayUtils.nullToEmpty; -import static org.tron.common.utils.ByteUtil.stripLeadingZeroes; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; - @Slf4j(topic = "VM") public class Program { @@ -2001,7 +2000,7 @@ public boolean cancelAllUnfreezeV2Action() { } public boolean delegateResource( - DataWord receiverAddress, DataWord delegateBalance, DataWord resourceType, DataWord lock) { + DataWord receiverAddress, DataWord delegateBalance, DataWord resourceType) { Repository repository = getContractState().newRepositoryChild(); byte[] owner = getContextAddress(); byte[] receiver = receiverAddress.toTronAddress(); @@ -2017,7 +2016,6 @@ public boolean delegateResource( param.setReceiverAddress(receiver); param.setDelegateBalance(delegateBalance.sValue().longValueExact()); param.setResourceType(parseResourceCodeV2(resourceType)); - param.setLock(lock.sValue().longValueExact() != 0); DelegateResourceProcessor processor = new DelegateResourceProcessor(); processor.validate(param, repository); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java index 529cfa06be1..7b8d2ced4af 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java @@ -151,5 +151,4 @@ public interface Repository { long getSlotByTimestampMs(long timestamp); - void unlockExpireResource(byte[] from, byte[] to, long now); } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index a91faaa9895..f77c229b249 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -842,39 +842,6 @@ public long getSlotByTimestampMs(long timestamp) { / BLOCK_PRODUCED_INTERVAL; } - @Override - public void unlockExpireResource(byte[] from, byte[] to, long now) { - byte[] lockKey = DelegatedResourceCapsule.createDbKeyV2(from, to, true); - DelegatedResourceCapsule lockResource = getDelegatedResource(lockKey); - if (lockResource == null) { - return; - } - if (lockResource.getExpireTimeForEnergy() >= now - && lockResource.getExpireTimeForBandwidth() >= now) { - return; - } - - byte[] unlockKey = DelegatedResourceCapsule.createDbKeyV2(from, to, false); - DelegatedResourceCapsule unlockResource = getDelegatedResource(unlockKey); - if (unlockResource == null) { - unlockResource = new DelegatedResourceCapsule(ByteString.copyFrom(from), - ByteString.copyFrom(to)); - } - if (lockResource.getExpireTimeForEnergy() < now) { - unlockResource.addFrozenBalanceForEnergy( - lockResource.getFrozenBalanceForEnergy(), 0); - lockResource.setFrozenBalanceForEnergy(0, 0); - } - if (lockResource.getExpireTimeForBandwidth() < now) { - unlockResource.addFrozenBalanceForBandwidth( - lockResource.getFrozenBalanceForBandwidth(), 0); - lockResource.setFrozenBalanceForBandwidth(0, 0); - } - - updateDelegatedResource(lockKey, lockResource); - updateDelegatedResource(unlockKey, unlockResource); - } - private void commitAccountCache(Repository deposit) { accountCache.forEach((key, value) -> { if (value.getType().isCreate() || value.getType().isDirty()) { @@ -978,16 +945,18 @@ private void commitDelegationCache(Repository deposit) { private void commitDelegatedResourceAccountIndexCache(Repository deposit) { delegatedResourceAccountIndexCache.forEach(((key, value) -> { - if (value.getType().isDirty() || value.getType().isCreate()) { + if (value.getValue() == null) { if (deposit != null) { deposit.putDelegatedResourceAccountIndex(key, value); } else { - if (value.getValue() == null) { - getDelegatedResourceAccountIndexStore().delete(key.getData()); - } else { - getDelegatedResourceAccountIndexStore().put(key.getData(), - new DelegatedResourceAccountIndexCapsule(value.getValue())); - } + getDelegatedResourceAccountIndexStore().delete(key.getData()); + } + } else if (value.getType().isDirty() || value.getType().isCreate()) { + if (deposit != null) { + deposit.putDelegatedResourceAccountIndex(key, value); + } else { + getDelegatedResourceAccountIndexStore().put(key.getData(), + new DelegatedResourceAccountIndexCapsule(value.getValue())); } } })); From f99e9a6fe08996b35e062023f329f91e4ec353a0 Mon Sep 17 00:00:00 2001 From: Liulei Date: Wed, 21 Dec 2022 15:17:22 +0800 Subject: [PATCH 0471/1197] feat(freezeV2): delegate resource account index cache --- .../UnDelegateResourceProcessor.java | 12 ++++-------- .../tron/core/vm/repository/RepositoryImpl.java | 16 +++++++--------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index 6bf0638570c..f4c18af85e5 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -16,7 +16,6 @@ import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.vm.nativecontract.param.UnDelegateResourceParam; import org.tron.core.vm.repository.Repository; -import org.tron.protos.Protocol; import java.util.Arrays; import java.util.Objects; @@ -200,14 +199,11 @@ public void execute(UnDelegateResourceParam param, Repository repo) { byte[] fromKey = Bytes.concat( DelegatedResourceAccountIndexStore.getV2_FROM_PREFIX(), ownerAddress, receiverAddress); repo.updateDelegatedResourceAccountIndex( - fromKey, - new DelegatedResourceAccountIndexCapsule((Protocol.DelegatedResourceAccountIndex) null)); - byte[] toKey = - Bytes.concat( - DelegatedResourceAccountIndexStore.getV2_TO_PREFIX(), receiverAddress, ownerAddress); + fromKey, new DelegatedResourceAccountIndexCapsule(new byte[0])); + byte[] toKey = Bytes.concat( + DelegatedResourceAccountIndexStore.getV2_TO_PREFIX(), receiverAddress, ownerAddress); repo.updateDelegatedResourceAccountIndex( - toKey, - new DelegatedResourceAccountIndexCapsule((Protocol.DelegatedResourceAccountIndex) null)); + toKey, new DelegatedResourceAccountIndexCapsule(new byte[0])); } repo.updateDelegatedResource(key, delegatedResourceCapsule); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index f77c229b249..fe27d6599d4 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -945,18 +945,16 @@ private void commitDelegationCache(Repository deposit) { private void commitDelegatedResourceAccountIndexCache(Repository deposit) { delegatedResourceAccountIndexCache.forEach(((key, value) -> { - if (value.getValue() == null) { - if (deposit != null) { - deposit.putDelegatedResourceAccountIndex(key, value); - } else { - getDelegatedResourceAccountIndexStore().delete(key.getData()); - } - } else if (value.getType().isDirty() || value.getType().isCreate()) { + if (value.getType().isDirty() || value.getType().isCreate()) { if (deposit != null) { deposit.putDelegatedResourceAccountIndex(key, value); } else { - getDelegatedResourceAccountIndexStore().put(key.getData(), - new DelegatedResourceAccountIndexCapsule(value.getValue())); + if (ByteUtil.isNullOrZeroArray(value.getValue().toByteArray())) { + getDelegatedResourceAccountIndexStore().delete(key.getData()); + } else { + getDelegatedResourceAccountIndexStore().put(key.getData(), + new DelegatedResourceAccountIndexCapsule(value.getValue())); + } } } })); From 56242e92e25759f5dd8375a36799a37b49dd1e11 Mon Sep 17 00:00:00 2001 From: Liulei Date: Wed, 21 Dec 2022 16:02:38 +0800 Subject: [PATCH 0472/1197] feat(freezeV2): add tests --- .../org/tron/core/vm/program/Program.java | 4 +- .../tron/common/runtime/vm/FreezeV2Test.java | 461 +++++++++++++++--- 2 files changed, 397 insertions(+), 68 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 7a800a0b412..0f141dce840 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -658,8 +658,8 @@ private boolean freezeV2Check(AccountCapsule accountCapsule) { long now = getContractState().getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); boolean isDelegatedResourceEmpty = - accountCapsule.getDelegatedFrozenBalanceForBandwidth() == 0 - && accountCapsule.getDelegatedFrozenBalanceForEnergy() == 0; + accountCapsule.getDelegatedFrozenV2BalanceForBandwidth() == 0 + && accountCapsule.getDelegatedFrozenV2BalanceForEnergy() == 0; boolean isUnFrozenV2ListEmpty = CollectionUtils.isEmpty( accountCapsule.getUnfrozenV2List().stream() diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java index 21fd4a445af..69529bbd3f0 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -1,8 +1,11 @@ package org.tron.common.runtime.vm; +import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_MS; import static org.tron.protos.Protocol.Transaction.Result.contractResult.REVERT; import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import com.google.protobuf.ByteString; @@ -23,16 +26,22 @@ import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.Commons; +import org.tron.common.utils.FastByteComparisons; import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.common.utils.WalletUtil; +import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.Wallet; +import org.tron.core.actuator.UnfreezeBalanceV2Actuator; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.capsule.VotesCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; +import org.tron.core.db.BandwidthProcessor; +import org.tron.core.db.EnergyProcessor; import org.tron.core.db.Manager; import org.tron.core.db.TransactionTrace; import org.tron.core.store.AccountStore; @@ -45,78 +54,98 @@ import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol; import org.tron.protos.Protocol.Transaction.Result.contractResult; +import org.tron.protos.contract.Common; import stest.tron.wallet.common.client.utils.AbiUtil; @Slf4j public class FreezeV2Test { private static final String FREEZE_V2_CODE = - "6080604052610aa0806100136000396000f3fe608060405234801561001057600080fd5b50d3801561001d57" - + "600080fd5b50d2801561002a57600080fd5b50600436106101255760003560e01c806385510c71116100" - + "bc578063c1a98a371161008b578063c1a98a371461021d578063c8115bb714610230578063df860ab314" - + "610258578063f0130dc91461026b578063f70eb4c51461027e57600080fd5b806385510c71146101cc57" - + "80639eb506e2146101ef578063a465bb1914610202578063b335634e1461020a57600080fd5b806333e7" - + "645d116100f857806333e7645d1461018b578063350a02341461019e5780633dcba6fc146101b1578063" - + "58974547146101b957600080fd5b8063089480871461012a57806308bee6c41461013f578063236051ed" - + "146101525780632fe36be514610178575b600080fd5b61013d610138366004610881565b610291565b00" - + "5b61013d61014d3660046108c4565b610302565b6101656101603660046108e6565b610355565b604051" - + "9081526020015b60405180910390f35b61013d6101863660046108c4565b6103be565b61016561019936" - + "60046108e6565b610409565b61013d6101ac366004610881565b61042f565b61013d610497565b610165" - + "6101c73660046108e6565b6104c4565b6101d46104ea565b604080519384526020840192909252908201" - + "5260600161016f565b6101656101fd3660046108e6565b6105f0565b610165610616565b610165610218" - + "36600461091b565b610657565b61016561022b3660046108e6565b6106c9565b61024361023e36600461" - + "091b565b6106ef565b6040805192835260208301919091520161016f565b6101d4610266366004610969" - + "565b610766565b6101656102793660046108e6565b6107e2565b61016561028c3660046109a7565b6108" - + "08565b806001600160a01b03168383de1580156102af573d6000803e3d6000fd5b506040805184815260" - + "2081018490526001600160a01b038316918101919091527f025526dfa15721b77133358f4ef9591e8784" - + "34240705071b580f0f8f955153be906060015b60405180910390a1505050565b8181da15801561031657" - + "3d6000803e3d6000fd5b5060408051838152602081018390527fc20c50cd22b066cd9d0cbbe9adbdee2f" - + "66da283d9971f5ff840fb01af79d980891015b60405180910390a15050565b604080516001600160a01b" - + "038416815260208101839052600091630100001491015b602060405180830381855afa15801561039457" - + "3d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906103b791906109" - + "d4565b9392505050565b8181db1580156103d2573d6000803e3d6000fd5b506040805183815260208101" - + "8390527fa2339ebec95cc02eea0ca9e15e5b1b4dd568105de8c4e47d2c6b96b1969348e8910161034956" - + "5b604080516001600160a01b038416815260208101839052600091630100000f9101610377565b806001" - + "600160a01b03168383df15801561044d573d6000803e3d6000fd5b506040805184815260208101849052" - + "6001600160a01b038316918101919091527f42fddce307cf00fa55a23fcc80c1d2ba08ddce9776bbced3" - + "d1657321ed2b7bbe906060016102f5565bdc506040517f2ba20738f2500f7585581bf668aa65ab6de7d1" - + "c1822de5737455214184f37ed590600090a1565b604080516001600160a01b0384168152602081018390" - + "52600091630100000e9101610377565b600080600080600160405181601f820153602081602083630100" - + "000b5afa610518576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff8316" - + "831461053957600080fd5b50506000600260405181601f820153602081602083630100000b5afa610565" - + "576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff831683146105865760" - + "0080fd5b50506000600360405181601f820153602081602083630100000b5afa6105b2576040513d6000" - + "823e3d81fd5b602081016040528051925067ffffffffffffffff831683146105d357600080fd5b505067" - + "ffffffffffffffff92831696918316955090911692509050565b604080516001600160a01b0384168152" - + "6020810183905260009163010000139101610377565b6000dd90507f6a5f656ed489ef1dec34a7317ceb" - + "95e7363440f72efdb653107e66982370f0618160405161064c91815260200190565b60405180910390a1" - + "90565b604080516001600160a01b03808616825284166020820152908101829052600090630100001090" - + "606001602060405180830381855afa15801561069e573d6000803e3d6000fd5b5050506040513d601f19" - + "601f820116820180604052508101906106c191906109d4565b949350505050565b604080516001600160" - + "a01b03841681526020810183905260009163010000159101610377565b604080516001600160a01b0380" - + "861682528416602082015290810182905260009081906301000012906060016040805180830381855afa" - + "158015610737573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190" - + "61075a91906109ed565b91509150935093915050565b604080516001600160a01b038516815260208101" - + "84905290810182905260009081908190630100001190606001606060405180830381855afa1580156107" - + "b0573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906107d39190" - + "610a11565b92509250925093509350939050565b604080516001600160a01b0384168152602081018390" - + "52600091630100000d9101610377565b6040516001600160a01b0382168152600090630100000c906020" - + "01602060405180830381855afa158015610840573d6000803e3d6000fd5b5050506040513d601f19601f" - + "8201168201806040525081019061086391906109d4565b92915050565b6001600160a81b038116811461" - + "087e57600080fd5b50565b60008060006060848603121561089657600080fd5b83359250602084013591" - + "5060408401356108af81610869565b9295919450506001600160a01b039091169150565b600080604083" - + "850312156108d757600080fd5b50508035926020909101359150565b600080604083850312156108f957" - + "600080fd5b823561090481610869565b6001600160a01b0316946020939093013593505050565b600080" - + "60006060848603121561093057600080fd5b833561093b81610869565b6001600160a01b039081169350" - + "60208501359061095782610869565b93969316945050506040919091013590565b600080600060608486" - + "03121561097e57600080fd5b833561098981610869565b6001600160a01b031695602085013595506040" - + "909401359392505050565b6000602082840312156109b957600080fd5b81356109c481610869565b6001" - + "600160a01b03169392505050565b6000602082840312156109e657600080fd5b5051919050565b600080" - + "60408385031215610a0057600080fd5b505080516020909101519092909150565b600080600060608486" - + "031215610a2657600080fd5b835192506020840151915060408401519050925092509256fea26474726f" - + "6e5822122060a7d93c8ee9065ccd63ad4b97b050e98fb1394a4d6c66c5223273f96fbe4ffd64736f6c63" - + "782d302e382e31372d646576656c6f702e323032322e31302e32302b636f6d6d69742e34313134656332" - + "632e6d6f64005e"; + "6080604052610e85806100136000396000f3fe60806040526004361061010d5760003560e01c80635897454711" + + "610095578063b335634e11610064578063b335634e14610457578063c1a98a3714610491578063df860ab314" + + "6104cb578063f0130dc914610525578063f70eb4c51461055f57600080fd5b8063589745471461035d578063" + + "85510c71146103975780639eb506e2146103ee578063a465bb191461042857600080fd5b8063236051ed1161" + + "00dc578063236051ed146102235780632fe36be51461026b57806333e7645d146102a5578063350a02341461" + + "02f45780633dcba6fc1461032e57600080fd5b8063089480871461011957806308bee6c4146101555780630a" + + "2dd8521461018f578063212743c9146101e957600080fd5b3661011457005b600080fd5b3480156101255760" + + "0080fd5b50d3801561013257600080fd5b50d2801561013f57600080fd5b5061015361014e366004610c9156" + + "5b610599565b005b34801561016157600080fd5b50d3801561016e57600080fd5b50d2801561017b57600080" + + "fd5b5061015361018a366004610cd4565b61060a565b34801561019b57600080fd5b50d380156101a8576000" + + "80fd5b50d280156101b557600080fd5b506101c96101c4366004610cf6565b61065d565b6040805193845260" + + "20840192909252908201526060015b60405180910390f35b3480156101f557600080fd5b50d3801561020257" + + "600080fd5b50d2801561020f57600080fd5b5061015361021e366004610d2b565b6106d5565b34801561022f" + + "57600080fd5b50d3801561023c57600080fd5b50d2801561024957600080fd5b5061025d610258366004610c" + + "f6565b6106e1565b6040519081526020016101e0565b34801561027757600080fd5b50d38015610284576000" + + "80fd5b50d2801561029157600080fd5b506101536102a0366004610cd4565b61074a565b3480156102b15760" + + "0080fd5b50d380156102be57600080fd5b50d280156102cb57600080fd5b506102df6102da366004610cf656" + + "5b610795565b604080519283526020830191909152016101e0565b34801561030057600080fd5b50d3801561" + + "030d57600080fd5b50d2801561031a57600080fd5b50610153610329366004610c91565b610802565b348015" + + "61033a57600080fd5b50d3801561034757600080fd5b50d2801561035457600080fd5b5061015361086a565b" + + "34801561036957600080fd5b50d3801561037657600080fd5b50d2801561038357600080fd5b5061025d6103" + + "92366004610cf6565b610897565b3480156103a357600080fd5b50d380156103b057600080fd5b50d2801561" + + "03bd57600080fd5b506103c66108bd565b604080519586526020860194909452928401919091526060830152" + + "608082015260a0016101e0565b3480156103fa57600080fd5b50d3801561040757600080fd5b50d280156104" + + "1457600080fd5b5061025d610423366004610cf6565b610a69565b34801561043457600080fd5b50d3801561" + + "044157600080fd5b50d2801561044e57600080fd5b5061025d610a8f565b34801561046357600080fd5b50d3" + + "801561047057600080fd5b50d2801561047d57600080fd5b5061025d61048c366004610d58565b610ad0565b" + + "34801561049d57600080fd5b50d380156104aa57600080fd5b50d280156104b757600080fd5b5061025d6104" + + "c6366004610cf6565b610b42565b3480156104d757600080fd5b50d380156104e457600080fd5b50d2801561" + + "04f157600080fd5b50610505610500366004610da6565b610b68565b60408051948552602085019390935291" + + "83015260608201526080016101e0565b34801561053157600080fd5b50d3801561053e57600080fd5b50d280" + + "1561054b57600080fd5b5061025d61055a366004610cf6565b610bf2565b34801561056b57600080fd5b50d3" + + "801561057857600080fd5b50d2801561058557600080fd5b5061025d610594366004610d2b565b610c18565b" + + "806001600160a01b03168383de1580156105b7573d6000803e3d6000fd5b5060408051848152602081018490" + + "526001600160a01b038316918101919091527fe0dda9e5664a3dcfa0628dc0392b74a4b2c63ba4887270f855" + + "7c1ed7deef3c82906060015b60405180910390a1505050565b8181da15801561061e573d6000803e3d6000fd" + + "5b5060408051838152602081018390527fc20c50cd22b066cd9d0cbbe9adbdee2f66da283d9971f5ff840fb0" + + "1af79d980891015b60405180910390a15050565b604080516001600160a01b03841681526020810183905260" + + "00918291829182918291630100001291016040805180830381855afa1580156106a2573d6000803e3d6000fd" + + "5b5050506040513d601f19601f820116820180604052508101906106c59190610de4565b9098909750439650" + + "945050505050565b806001600160a01b0316ff5b604080516001600160a01b03841681526020810183905260" + + "0091630100001491015b602060405180830381855afa158015610720573d6000803e3d6000fd5b5050506040" + + "513d601f19601f820116820180604052508101906107439190610e08565b9392505050565b8181db15801561" + + "075e573d6000803e3d6000fd5b5060408051838152602081018390527fa2339ebec95cc02eea0ca9e15e5b1b" + + "4dd568105de8c4e47d2c6b96b1969348e89101610651565b604080516001600160a01b038416815260208101" + + "8390526000918291630100000f9101602060405180830381855afa1580156107d5573d6000803e3d6000fd5b" + + "5050506040513d601f19601f820116820180604052508101906107f89190610e08565b944394509250505056" + + "5b806001600160a01b03168383df158015610820573d6000803e3d6000fd5b50604080518481526020810184" + + "90526001600160a01b038316918101919091527fd087798e9716d31cc0ef7780cb451270a6e4b447359da1b9" + + "f169996c3a942801906060016105fd565bdc506040517f2ba20738f2500f7585581bf668aa65ab6de7d1c182" + + "2de5737455214184f37ed590600090a1565b604080516001600160a01b038416815260208101839052600091" + + "630100000e9101610703565b600080600080600080600160405181601f820153602081602083630100000b5a" + + "fa6108ee576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff8316831461090f" + + "57600080fd5b50506000600260405181601f820153602081602083630100000b5afa61093b576040513d6000" + + "823e3d81fd5b602081016040528051925067ffffffffffffffff8316831461095c57600080fd5b5050600060" + + "0360405181601f820153602081602083630100000b5afa610988576040513d6000823e3d81fd5b6020810160" + + "40528051925067ffffffffffffffff831683146109a957600080fd5b50506000600460405181601f82015360" + + "2081602083630100000b5afa6109d5576040513d6000823e3d81fd5b602081016040528051925067ffffffff" + + "ffffffff831683146109f657600080fd5b50506000600560405181601f820153602081602083630100000b5a" + + "fa610a22576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff83168314610a43" + + "57600080fd5b505067ffffffffffffffff9485169a938516995091841697508316955090911692509050565b" + + "604080516001600160a01b03841681526020810183905260009163010000139101610703565b6000dd90507f" + + "6a5f656ed489ef1dec34a7317ceb95e7363440f72efdb653107e66982370f06181604051610ac59181526020" + + "0190565b60405180910390a190565b604080516001600160a01b038086168252841660208201529081018290" + + "52600090630100001090606001602060405180830381855afa158015610b17573d6000803e3d6000fd5b5050" + + "506040513d601f19601f82011682018060405250810190610b3a9190610e08565b949350505050565b604080" + + "516001600160a01b03841681526020810183905260009163010000159101610703565b604080516001600160" + + "a01b038516815260208101849052908101829052600090819081908190819081908190630100001190606001" + + "606060405180830381855afa158015610bba573d6000803e3d6000fd5b5050506040513d601f19601f820116" + + "82018060405250810190610bdd9190610e21565b919c909b509099504398509650505050505050565b604080" + + "516001600160a01b038416815260208101839052600091630100000d9101610703565b6040516001600160a0" + + "1b0382168152600090630100000c90602001602060405180830381855afa158015610c50573d6000803e3d60" + + "00fd5b5050506040513d601f19601f82011682018060405250810190610c739190610e08565b92915050565b" + + "6001600160a81b0381168114610c8e57600080fd5b50565b600080600060608486031215610ca657600080fd" + + "5b83359250602084013591506040840135610cbf81610c79565b9295919450506001600160a01b0390911691" + + "50565b60008060408385031215610ce757600080fd5b50508035926020909101359150565b60008060408385" + + "031215610d0957600080fd5b8235610d1481610c79565b6001600160a01b0316946020939093013593505050" + + "565b600060208284031215610d3d57600080fd5b8135610d4881610c79565b6001600160a01b031693925050" + + "50565b600080600060608486031215610d6d57600080fd5b8335610d7881610c79565b6001600160a01b0390" + + "81169350602085013590610d9482610c79565b93969316945050506040919091013590565b60008060006060" + + "8486031215610dbb57600080fd5b8335610dc681610c79565b6001600160a01b031695602085013595506040" + + "909401359392505050565b60008060408385031215610df757600080fd5b5050805160209091015190929091" + + "50565b600060208284031215610e1a57600080fd5b5051919050565b600080600060608486031215610e3657" + + "600080fd5b835192506020840151915060408401519050925092509256fea26474726f6e582212206da319ce" + + "ceb62dd2226a1f18adea5269deb830ff85c48e54bc8a6ed8822d8a3a64736f6c63430008110033"; private static final long value = 100_000_000_000_000_000L; private static final long fee = 1_000_000_000; @@ -124,6 +153,8 @@ public class FreezeV2Test { private static final byte[] userA = Commons.decode58Check(userAStr); private static final String userBStr = "27jzp7nVEkH4Hf3H1PHPp4VDY7DxTy5eydL"; private static final byte[] userB = Commons.decode58Check(userBStr); + private static final String userCStr = "27juXSbMvL6pb8VgmKRgW6ByCfw5RqZjUuo"; + private static final byte[] userC = Commons.decode58Check(userCStr); private static String dbPath; private static TronApplicationContext context; @@ -155,6 +186,7 @@ public void init() throws Exception { VMConfig.initAllowTvmSolidity059(1); VMConfig.initAllowTvmIstanbul(1); VMConfig.initAllowTvmFreezeV2(1); + VMConfig.initAllowTvmVote(1); } private byte[] deployContract(String contractName, String code) throws Exception { @@ -264,6 +296,15 @@ private TVMTestResult triggerUnDelegateResource( amount, res, StringUtil.encode58Check(receiverAddr)); } + private TVMTestResult triggerSuicide( + byte[] callerAddr, byte[] contractAddr, contractResult expectedResult, + Consumer check, byte[] inheritorAddress) + throws Exception { + return triggerContract( + callerAddr, contractAddr, fee, expectedResult, check, + "killme(address)", StringUtil.encode58Check(inheritorAddress)); + } + @Test public void testFreezeV2Operations() throws Exception { byte[] contract = deployContract("TestFreezeV2", FREEZE_V2_CODE); @@ -289,6 +330,22 @@ public void testFreezeV2Operations() throws Exception { unfreezeV2WithException(owner, contract, frozenBalance, 3); unfreezeV2WithException(owner, contract, -frozenBalance, 2); unfreezeV2WithException(owner, contract, 0, 2); + unfreezeV2WithException(owner, contract, frozenBalance + 100, 2); + // full unfreeze list exception + AccountCapsule ownerCapsule = manager.getAccountStore().get(contract); + long now = manager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); + int unfreezingCount = ownerCapsule.getUnfreezingV2Count(now); + List unFreezeV2List = + new ArrayList<>(ownerCapsule.getUnfrozenV2List()); + for (; unfreezingCount < UnfreezeBalanceV2Actuator.getUNFREEZE_MAX_TIMES(); unfreezingCount++) { + ownerCapsule.addUnfrozenV2List(BANDWIDTH, 1, now + 30000); + } + manager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); + unfreezeV2WithException(owner, contract, frozenBalance, 2); + ownerCapsule = manager.getAccountStore().get(contract); + ownerCapsule.clearUnfrozenV2(); + unFreezeV2List.forEach(ownerCapsule::addUnfrozenV2); + manager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); // unfreeze unfreezeV2(owner, contract, frozenBalance, 0); @@ -339,17 +396,23 @@ public void testDelegateResourceOperations() throws Exception { rootRepository.commit(); delegateResourceWithException(owner, contract, userA, 0, 0); delegateResourceWithException(owner, contract, userA, resourceAmount * 2, 0); + delegateResourceWithException(owner, contract, userA, resourceAmount - 100, 0); delegateResourceWithException(owner, contract, userA, resourceAmount, 2); delegateResourceWithException(owner, contract, userA, resourceAmount, 3); delegateResourceWithException(owner, contract, contract, resourceAmount, 0); + rootRepository.createAccount(userC, Protocol.AccountType.Contract); + rootRepository.commit(); + delegateResourceWithException(owner, contract, userC, resourceAmount, 0); delegateResource(owner, contract, userA, resourceAmount, 0); + delegateResourceWithException(owner, contract, userA, resourceAmount, 0); delegateResource(owner, contract, userA, resourceAmount, 1); // unDelegate // invalid args unDelegateResourceWithException(owner, contract, userA, resourceAmount, 2); unDelegateResourceWithException(owner, contract, userA, resourceAmount, 3); + unDelegateResourceWithException(owner, contract, userB, resourceAmount, 0); rootRepository.createAccount(userB, Protocol.AccountType.Normal); rootRepository.commit(); unDelegateResourceWithException(owner, contract, userB, resourceAmount, 0); @@ -358,7 +421,9 @@ public void testDelegateResourceOperations() throws Exception { unDelegateResourceWithException(owner, contract, userA, 0, 0); unDelegateResourceWithException(owner, contract, userA, -resourceAmount, 0); + manager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(System.currentTimeMillis()); unDelegateResource(owner, contract, userA, resourceAmount, 0); + unDelegateResourceWithException(owner, contract, userA, resourceAmount, 0); unDelegateResource(owner, contract, userA, resourceAmount, 1); // no enough delegated resource @@ -366,6 +431,160 @@ public void testDelegateResourceOperations() throws Exception { unDelegateResourceWithException(owner, contract, userA, resourceAmount, 1); } + @Test + public void testUnfreezeVotes() throws Exception { + byte[] contract = deployContract("TestFreezeV2", FREEZE_V2_CODE); + long frozenBalance = 1_000_000_000L; + + // trigger freezeBalanceV2(uint256,uint256) to get tp + freezeV2(owner, contract, frozenBalance, 2); + + // vote + AccountCapsule accountCapsule = manager.getAccountStore().get(contract); + VotesCapsule votesCapsule = + new VotesCapsule(ByteString.copyFrom(contract), accountCapsule.getVotesList()); + accountCapsule.addVotes(ByteString.copyFrom(userA), 500); + votesCapsule.addNewVotes(ByteString.copyFrom(userA), 500); + accountCapsule.addVotes(ByteString.copyFrom(userB), 500); + votesCapsule.addNewVotes(ByteString.copyFrom(userB), 500); + manager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + manager.getVotesStore().put(votesCapsule.createDbKey(), votesCapsule); + + // unfreeze half tp + unfreezeV2(owner, contract, frozenBalance / 2, 2); + accountCapsule = manager.getAccountStore().get(contract); + for (Protocol.Vote vote : accountCapsule.getVotesList()) { + Assert.assertEquals(250, vote.getVoteCount()); + } + + votesCapsule = manager.getVotesStore().get(contract); + Assert.assertNotNull(votesCapsule); + for (Protocol.Vote vote : votesCapsule.getOldVotes()) { + Assert.assertEquals(500, vote.getVoteCount()); + } + for (Protocol.Vote vote : votesCapsule.getNewVotes()) { + Assert.assertEquals(250, vote.getVoteCount()); + } + // unfreeze all tp + unfreezeV2(owner, contract, frozenBalance / 2, 2); + accountCapsule = manager.getAccountStore().get(contract); + Assert.assertEquals(0, accountCapsule.getVotesList().size()); + Assert.assertEquals(-1, accountCapsule.getInstance().getOldTronPower()); + } + + @Test + public void testUnfreezeWithOldTronPower() throws Exception { + byte[] contract = deployContract("TestFreezeV2", FREEZE_V2_CODE); + long frozenBalance = 1_000_000_000L; + long now = System.currentTimeMillis(); + manager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + // trigger freezeBalanceV2(uint256,uint256) to get energy + freezeV2(owner, contract, frozenBalance, 1); + AccountCapsule ownerCapsule = manager.getAccountStore().get(contract); + ownerCapsule.setOldTronPower(frozenBalance); + ownerCapsule.addVotes(ByteString.copyFrom(userA), 100L); + Assert.assertEquals(frozenBalance, ownerCapsule.getAllFrozenBalanceForEnergy()); + manager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); + + // unfreeze all balance + unfreezeV2(owner, contract, frozenBalance, 1); + ownerCapsule = manager.getAccountStore().get(contract); + Assert.assertEquals(0, ownerCapsule.getVotesList().size()); + Assert.assertEquals(-1, ownerCapsule.getInstance().getOldTronPower()); + } + + @Test + public void testUnfreezeWithoutOldTronPower() throws Exception { + byte[] contract = deployContract("TestFreezeV2", FREEZE_V2_CODE); + long frozenBalance = 1_000_000_000L; + long now = System.currentTimeMillis(); + manager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + // trigger freezeBalanceV2(uint256,uint256) to get energy + freezeV2(owner, contract, frozenBalance, 1); + AccountCapsule ownerCapsule = manager.getAccountStore().get(contract); + ownerCapsule.setOldTronPower(-1L); + ownerCapsule.addVotes(ByteString.copyFrom(userA), 100L); + Assert.assertEquals(frozenBalance, ownerCapsule.getAllFrozenBalanceForEnergy()); + manager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); + + // unfreeze all balance + unfreezeV2(owner, contract, frozenBalance, 1); + ownerCapsule = manager.getAccountStore().get(contract); + Assert.assertEquals(1, ownerCapsule.getVotesList().size()); + Assert.assertEquals(-1, ownerCapsule.getInstance().getOldTronPower()); + } + + @Test + public void testUnfreezeTronPowerWithOldTronPower() throws Exception { + byte[] contract = deployContract("TestFreezeV2", FREEZE_V2_CODE); + long frozenBalance = 1_000_000_000L; + long now = System.currentTimeMillis(); + manager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + // trigger freezeBalanceV2(uint256,uint256) to get energy + freezeV2(owner, contract, frozenBalance, 1); + // trigger freezeBalanceV2(uint256,uint256) to get tp + freezeV2(owner, contract, frozenBalance, 2); + AccountCapsule ownerCapsule = manager.getAccountStore().get(contract); + ownerCapsule.setOldTronPower(-1L); + ownerCapsule.addVotes(ByteString.copyFrom(userA), 100L); + Assert.assertEquals(frozenBalance, ownerCapsule.getAllFrozenBalanceForEnergy()); + manager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); + + // unfreeze + unfreezeV2(owner, contract, frozenBalance, 2); + ownerCapsule = manager.getAccountStore().get(contract); + Assert.assertEquals(0, ownerCapsule.getVotesList().size()); + Assert.assertEquals(-1, ownerCapsule.getInstance().getOldTronPower()); + } + + @Test + public void testSuicideToOtherAccount() throws Exception { + byte[] contract = deployContract("TestFreezeV2", FREEZE_V2_CODE); + long frozenBalance = 1_000_000_000L; + long now = System.currentTimeMillis(); + manager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + // trigger freezeBalanceV2(uint256,uint256) to get energy + freezeV2(owner, contract, frozenBalance, 1); + freezeV2(owner, contract, frozenBalance, 2); + rootRepository.createAccount(userA, Protocol.AccountType.Normal); + rootRepository.createAccount(userB, Protocol.AccountType.Normal); + rootRepository.commit(); + + // not empty delegate resource exception + delegateResource(owner, contract, userA, frozenBalance / 2, 1); + suicideWithException(owner, contract, userB); + unDelegateResource(owner, contract, userA, frozenBalance / 2, 1); + // not empty unfreezing list exception + unfreezeV2(owner, contract, frozenBalance / 2, 1); + suicideWithException(owner, contract, userB); + cancelAllUnfreezeV2(owner, contract, 0); + + AccountCapsule contractCapsule = manager.getAccountStore().get(contract); + contractCapsule.setLatestConsumeTimeForEnergy(ChainBaseManager.getInstance().getHeadSlot()); + contractCapsule.setNewWindowSize(ENERGY, WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL); + contractCapsule.setEnergyUsage(frozenBalance); + manager.getAccountStore().put(contract, contractCapsule); + manager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now + 30000); + suicide(owner, contract, userB); + } + + @Test + public void testSuicideToBlackHole() throws Exception { + byte[] contract = deployContract("TestFreezeV2", FREEZE_V2_CODE); + long frozenBalance = 1_000_000_000L; + long now = System.currentTimeMillis(); + manager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + // trigger freezeBalanceV2(uint256,uint256) to get energy + freezeV2(owner, contract, frozenBalance, 1); + + suicide(owner, contract, contract); + } + private TVMTestResult freezeV2( byte[] callerAddr, byte[] contractAddr, long frozenBalance, long res) throws Exception { DynamicPropertiesStore dynamicStore = manager.getDynamicPropertiesStore(); @@ -682,9 +901,13 @@ private TVMTestResult unDelegateResource( Assert.assertTrue(newAcquiredBalance == 0 || acquiredBalance - newAcquiredBalance == amount); if (res == 0) { Assert.assertEquals(oldReceiver.getNetUsage() - transferUsage, newReceiver.getNetUsage()); + Assert.assertEquals( + ChainBaseManager.getInstance().getHeadSlot(), newReceiver.getLastConsumeTime(BANDWIDTH)); } else { Assert.assertEquals( oldReceiver.getEnergyUsage() + transferUsage, newReceiver.getEnergyUsage()); + Assert.assertEquals( + ChainBaseManager.getInstance().getHeadSlot(), newReceiver.getLastConsumeTime(ENERGY)); } } else { Assert.assertNull(newReceiver); @@ -714,6 +937,112 @@ private TVMTestResult unDelegateResourceWithException( callerAddr, contractAddr, REVERT, null, receiverAddr, amount, res); } + private TVMTestResult suicide(byte[] callerAddr, byte[] contractAddr, byte[] inheritorAddr) + throws Exception { + if (FastByteComparisons.isEqual(contractAddr, inheritorAddr)) { + inheritorAddr = manager.getAccountStore().getBlackholeAddress(); + } + DynamicPropertiesStore dynamicStore = manager.getDynamicPropertiesStore(); + long oldTotalNetWeight = dynamicStore.getTotalNetWeight(); + long oldTotalEnergyWeight = dynamicStore.getTotalEnergyWeight(); + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + + AccountStore accountStore = manager.getAccountStore(); + AccountCapsule oldContract = accountStore.get(contractAddr); + AccountCapsule oldInheritor = accountStore.get(inheritorAddr); + long oldBalanceOfInheritor = 0; + long oldInheritorFrozenBalance = 0; + long oldInheritorBandwidthUsage = 0; + long oldInheritorEnergyUsage = 0; + if (oldInheritor != null) { + oldBalanceOfInheritor = oldInheritor.getBalance(); + oldInheritorFrozenBalance = oldInheritor.getFrozenBalance(); + oldInheritorBandwidthUsage = oldInheritor.getUsage(BANDWIDTH); + oldInheritorEnergyUsage = oldInheritor.getUsage(ENERGY); + } + BandwidthProcessor bandwidthProcessor = new BandwidthProcessor(ChainBaseManager.getInstance()); + bandwidthProcessor.updateUsage(oldContract); + oldContract.setLatestConsumeTime(now); + EnergyProcessor energyProcessor = + new EnergyProcessor( + manager.getDynamicPropertiesStore(), ChainBaseManager.getInstance().getAccountStore()); + energyProcessor.updateUsage(oldContract); + oldContract.setLatestConsumeTimeForEnergy(now); + + TVMTestResult result = triggerSuicide(callerAddr, contractAddr, SUCCESS, null, inheritorAddr); + + Assert.assertNull(accountStore.get(contractAddr)); + AccountCapsule newInheritor = accountStore.get(inheritorAddr); + Assert.assertNotNull(newInheritor); + long expectedIncreasingBalance = + oldContract.getBalance() + + oldContract.getUnfrozenV2List().stream() + .filter(unFreezeV2 -> unFreezeV2.getUnfreezeExpireTime() <= now) + .mapToLong(Protocol.Account.UnFreezeV2::getUnfreezeAmount) + .sum(); + if (FastByteComparisons.isEqual( + inheritorAddr, manager.getAccountStore().getBlackholeAddress())) { + Assert.assertEquals( + expectedIncreasingBalance, + newInheritor.getBalance() - oldBalanceOfInheritor - result.getReceipt().getEnergyFee()); + } else { + Assert.assertEquals( + expectedIncreasingBalance, newInheritor.getBalance() - oldBalanceOfInheritor); + } + + Assert.assertEquals(0, oldContract.getDelegatedFrozenBalanceForBandwidth()); + Assert.assertEquals(0, oldContract.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals( + oldContract.getFrozenBalance(), + newInheritor.getFrozenBalance() - oldInheritorFrozenBalance); + if (oldInheritor != null) { + if (oldContract.getNetUsage() > 0) { + long expectedNewNetUsage = + bandwidthProcessor.unDelegateIncrease( + oldInheritor, + oldContract, + oldContract.getNetUsage(), + Common.ResourceCode.BANDWIDTH, + now); + Assert.assertEquals( + expectedNewNetUsage, newInheritor.getNetUsage() - oldInheritorBandwidthUsage); + Assert.assertEquals( + ChainBaseManager.getInstance().getHeadSlot(), newInheritor.getLatestConsumeTime()); + } + if (oldContract.getEnergyUsage() > 0) { + long expectedNewEnergyUsage = + energyProcessor.unDelegateIncrease( + oldInheritor, + oldContract, + oldContract.getEnergyUsage(), + Common.ResourceCode.ENERGY, + now); + Assert.assertEquals( + expectedNewEnergyUsage, newInheritor.getEnergyUsage() - oldInheritorEnergyUsage); + Assert.assertEquals( + ChainBaseManager.getInstance().getHeadSlot(), + newInheritor.getLatestConsumeTimeForEnergy()); + } + } + + long newTotalNetWeight = dynamicStore.getTotalNetWeight(); + long newTotalEnergyWeight = dynamicStore.getTotalEnergyWeight(); + Assert.assertEquals( + oldContract.getFrozenBalance(), (oldTotalNetWeight - newTotalNetWeight) * TRX_PRECISION); + Assert.assertEquals( + oldContract.getEnergyFrozenBalance(), + (oldTotalEnergyWeight - newTotalEnergyWeight) * TRX_PRECISION); + + return result; + } + + private TVMTestResult suicideWithException( + byte[] callerAddr, byte[] contractAddr, byte[] inheritorAddr) + throws Exception { + return triggerSuicide( + callerAddr, contractAddr, REVERT, null, inheritorAddr); + } + @After public void destroy() { ConfigLoader.disable = false; From 716ab5394e7a1b86504e2806978186ec5570716c Mon Sep 17 00:00:00 2001 From: Asuka Date: Wed, 21 Dec 2022 17:03:10 +0800 Subject: [PATCH 0473/1197] func(proposal,chainid): optimize the return value of chainid --- .../org/tron/core/utils/ProposalUtil.java | 14 +++++++++- .../org/tron/core/vm/config/ConfigLoader.java | 2 ++ .../org/tron/core/vm/config/VMConfig.java | 10 +++++++ .../org/tron/core/vm/program/Program.java | 2 +- .../core/store/DynamicPropertiesStore.java | 26 ++++++++++++++++++- .../common/parameter/CommonParameter.java | 5 +++- .../src/main/java/org/tron/core/Constant.java | 2 ++ .../src/main/java/org/tron/core/Wallet.java | 5 ++++ .../java/org/tron/core/config/args/Args.java | 4 +++ .../tron/core/consensus/ProposalService.java | 5 ++++ 10 files changed, 71 insertions(+), 4 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index f8e28296782..a0154470bc5 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -608,6 +608,17 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7)) { + throw new ContractValidateException( + "Bad chain parameter id [ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID]"); + } + if (value != 1) { + throw new ContractValidateException( + "This value[ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID] is only allowed to be 1"); + } + break; + } default: break; @@ -676,7 +687,8 @@ public enum ProposalType { // current value, value range ALLOW_NEW_REWARD(67), // 0, 1 MEMO_FEE(68), // 0, [0, 1000_000_000] ALLOW_DELEGATE_OPTIMIZATION(69), - UNFREEZE_DELAY_DAYS(70); // 0, [1, 365] + UNFREEZE_DELAY_DAYS(70), // 0, [1, 365] + ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID(71); // 0, 1 private long code; diff --git a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java index 7d06e5c9490..8dbb4457d4d 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java +++ b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java @@ -32,6 +32,8 @@ public static void load(StoreFactory storeFactory) { VMConfig.initAllowHigherLimitForMaxCpuTimeOfOneTx( ds.getAllowHigherLimitForMaxCpuTimeOfOneTx()); VMConfig.initAllowTvmFreezeV2(ds.supportUnfreezeDelay() ? 1 : 0); + VMConfig.initAllowOptimizedReturnValueOfChainId( + ds.getAllowOptimizedReturnValueOfChainId()); } } } diff --git a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java index cd94409878d..38fa1ca17f6 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java +++ b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java @@ -37,6 +37,8 @@ public class VMConfig { private static boolean ALLOW_TVM_FREEZE_V2 = false; + private static boolean ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID = false; + private VMConfig() { } @@ -100,6 +102,10 @@ public static void initAllowTvmFreezeV2(long allow) { ALLOW_TVM_FREEZE_V2 = allow == 1; } + public static void initAllowOptimizedReturnValueOfChainId(long allow) { + ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID = allow == 1; + } + public static boolean getEnergyLimitHardFork() { return CommonParameter.ENERGY_LIMIT_HARD_FORK; } @@ -151,4 +157,8 @@ public static boolean allowHigherLimitForMaxCpuTimeOfOneTx() { public static boolean allowTvmFreezeV2() { return ALLOW_TVM_FREEZE_V2; } + + public static boolean allowOptimizedReturnValueOfChainId() { + return ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID; + } } diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 7a800a0b412..d90dbf197c0 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -1256,7 +1256,7 @@ public DataWord getCallerAddress() { public DataWord getChainId() { byte[] chainId = getContractState().getBlockByNum(0).getBlockId().getBytes(); - if (VMConfig.allowTvmCompatibleEvm()) { + if (VMConfig.allowTvmCompatibleEvm() || VMConfig.allowOptimizedReturnValueOfChainId()) { chainId = Arrays.copyOfRange(chainId, chainId.length - 4, chainId.length); } return new DataWord(chainId).clone(); diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index b417a3b283f..3770d0ab22e 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -193,9 +193,11 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_DELEGATE_OPTIMIZATION = "ALLOW_DELEGATE_OPTIMIZATION".getBytes(); - private static final byte[] UNFREEZE_DELAY_DAYS = "UNFREEZE_DELAY_DAYS".getBytes(); + private static final byte[] ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID = + "ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID".getBytes(); + @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { super(dbName); @@ -899,6 +901,14 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { CommonParameter.getInstance().getUnfreezeDelayDays() ); } + + try { + this.getAllowOptimizedReturnValueOfChainId(); + } catch (IllegalArgumentException e) { + this.saveAllowOptimizedReturnValueOfChainId( + CommonParameter.getInstance().getAllowOptimizedReturnValueOfChainId() + ); + } } public String intArrayToString(int[] a) { @@ -2647,6 +2657,20 @@ public void saveUnfreezeDelayDays(long value) { this.put(UNFREEZE_DELAY_DAYS, new BytesCapsule(ByteArray.fromLong(value))); } + public void saveAllowOptimizedReturnValueOfChainId(long value) { + this.put(ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID, + new BytesCapsule(ByteArray.fromLong(value))); + } + + public long getAllowOptimizedReturnValueOfChainId() { + String msg = "not found ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID"; + return Optional.ofNullable(getUnchecked(ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException(msg)); + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index e2308b58b86..e2737e964d9 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -1,7 +1,6 @@ package org.tron.common.parameter; import com.beust.jcommander.Parameter; - import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.ArrayList; @@ -577,6 +576,10 @@ public class CommonParameter { @Setter public long unfreezeDelayDays = 0L; + @Getter + @Setter + public long allowOptimizedReturnValueOfChainId = 0L; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index f91d04074ad..e71b7a7e870 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -292,6 +292,8 @@ public class Constant { public static final String COMMITTEE_ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX = "committee.allowHigherLimitForMaxCpuTimeOfOneTx"; public static final String COMMITTEE_ALLOW_NEW_REWARD_ALGORITHM = "committee.allowNewRewardAlgorithm"; + public static final String COMMITTEE_ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID = + "committee.allowOptimizedReturnValueOfChainId"; public static final String METRICS_STORAGE_ENABLE = "node.metrics.storageEnable"; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index b79bd3510e7..02a7562aeb6 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1284,6 +1284,11 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getUnfreezeDelayDays()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getAllowOptimizedReturnValueOfChainId") + .setValue(dbManager.getDynamicPropertiesStore().getAllowOptimizedReturnValueOfChainId()) + .build()); + return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index d88d3a95852..8347dfbf241 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -952,6 +952,10 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.COMMITTEE_ALLOW_NEW_REWARD_ALGORITHM) ? config .getInt(Constant.COMMITTEE_ALLOW_NEW_REWARD_ALGORITHM) : 0; + PARAMETER.allowOptimizedReturnValueOfChainId = + config.hasPath(Constant.COMMITTEE_ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID) ? config + .getInt(Constant.COMMITTEE_ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID) : 0; + initBackupProperty(config); if (Constant.ROCKSDB.equalsIgnoreCase(CommonParameter .getInstance().getStorage().getDbEngine())) { diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 9b5c6dfb975..c35549e8749 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -318,6 +318,11 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveAllowDelegateOptimization(entry.getValue()); break; } + case ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID: { + manager.getDynamicPropertiesStore() + .saveAllowOptimizedReturnValueOfChainId(entry.getValue()); + break; + } default: find = false; break; From a2d57d94045291853eb037b7a94bebe9adf1deb2 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Fri, 23 Dec 2022 18:19:15 +0800 Subject: [PATCH 0474/1197] feat(freezeV2): remove unfreeze amount from transaction detail --- .../java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java | 1 - 1 file changed, 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java index 53bcadc8bf9..45b05ec8bec 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java @@ -93,7 +93,6 @@ public boolean execute(Object result) throws ContractExeException { accountStore.put(ownerAddress, accountCapsule); - ret.setUnfreezeAmount(unfreezeBalance); ret.setWithdrawExpireAmount(unfreezeAmount); ret.setStatus(fee, code.SUCESS); return true; From 072586632edf1ae63f34e1819578396082f80624 Mon Sep 17 00:00:00 2001 From: Asuka Date: Sun, 25 Dec 2022 16:29:33 +0800 Subject: [PATCH 0475/1197] func(inter-tx): add a new switch config to indicate if save featured internal tx --- .../core/capsule/utils/TransactionUtil.java | 14 +++++- .../common/parameter/CommonParameter.java | 45 ++++++++++--------- .../src/main/java/org/tron/core/Constant.java | 2 + .../java/org/tron/core/config/args/Args.java | 4 ++ framework/src/main/resources/config.conf | 3 ++ 5 files changed, 46 insertions(+), 22 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java b/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java index d31b5009401..2d438229ee6 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java +++ b/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java @@ -124,8 +124,18 @@ public static TransactionInfoCapsule buildTransactionInfoInstance(TransactionCap builder.setReceipt(traceReceipt.getReceipt()); if (CommonParameter.getInstance().isSaveInternalTx()) { - programResult.getInternalTransactions().forEach(it -> - builder.addInternalTransactions(buildInternalTransaction(it))); + if (CommonParameter.getInstance().isSaveFeaturedInternalTx()) { + programResult.getInternalTransactions().forEach(it -> + builder.addInternalTransactions(buildInternalTransaction(it))); + } else { + programResult.getInternalTransactions().stream() + .filter(it -> + "call".equals(it.getNote()) + || "create".equals(it.getNote()) + || "suicide".equals(it.getNote())) + .forEach(it -> + builder.addInternalTransactions(buildInternalTransaction(it))); + } } return new TransactionInfoCapsule(builder.build()); diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index e2308b58b86..cd7ea7965e6 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -1,7 +1,6 @@ package org.tron.common.parameter; import com.beust.jcommander.Parameter; - import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.ArrayList; @@ -45,42 +44,53 @@ public class CommonParameter { public boolean witness = false; @Getter @Setter - @Parameter(names = {"--support-constant"}, description = "Support constant calling for TVM. " + - "(defalut: false)") + @Parameter(names = {"--support-constant"}, description = "Support constant calling for TVM. " + + "(defalut: false)") public boolean supportConstant = false; @Getter @Setter - @Parameter(names = {"--max-energy-limit-for-constant"}, description = "Max energy limit for " + - "constant calling. (default: 100,000,000)") + @Parameter(names = {"--max-energy-limit-for-constant"}, description = "Max energy limit for " + + "constant calling. (default: 100,000,000)") public long maxEnergyLimitForConstant = 100_000_000L; @Getter @Setter - @Parameter(names = {"--lru-cache-size"}, description = "Max LRU size for caching bytecode and " + - "result of JUMPDEST analysis. (default: 500)") + @Parameter(names = {"--lru-cache-size"}, description = "Max LRU size for caching bytecode and " + + "result of JUMPDEST analysis. (default: 500)") public int lruCacheSize = 500; @Getter @Setter - @Parameter(names = {"--debug"}, description = "Switch for TVM debug mode. In debug model, TVM " + - "will not check for timeout. (default: false)") + @Parameter(names = {"--debug"}, description = "Switch for TVM debug mode. In debug model, TVM " + + "will not check for timeout. (default: false)") public boolean debug = false; @Getter @Setter - @Parameter(names = {"--min-time-ratio"}, description = "Maximum CPU tolerance when executing " + - "non-timeout transactions while synchronizing blocks. (default: 5.0)") + @Parameter(names = {"--min-time-ratio"}, description = "Maximum CPU tolerance when executing " + + "non-timeout transactions while synchronizing blocks. (default: 5.0)") public double minTimeRatio = 0.0; @Getter @Setter - @Parameter(names = {"--max-time-ratio"}, description = "Maximum CPU tolerance when executing " + - "timeout transactions while synchronizing blocks. (default: 0.0)") + @Parameter(names = {"--max-time-ratio"}, description = "Maximum CPU tolerance when executing " + + "timeout transactions while synchronizing blocks. (default: 0.0)") public double maxTimeRatio = calcMaxTimeRatio(); @Getter @Setter + @Parameter(names = {"--save-internaltx"}, description = "Save internal transactions generated " + + "during TVM execution, such as create, call and suicide. (default: false)") + public boolean saveInternalTx; + @Getter + @Setter + @Parameter(names = {"--save-featured-internaltx"}, description = "Save featured internal " + + "transactions generated during TVM execution, such as freeze, vote and so on. " + + "(default: false)") + public boolean saveFeaturedInternalTx; + @Getter + @Setter @Parameter(names = {"--long-running-time"}) public int longRunningTime = 10; @Getter @Setter - @Parameter(names = {"--max-connect-number"}, description = "Http server max connect number " + - "(default:50)") + @Parameter(names = {"--max-connect-number"}, description = "Http server max connect number " + + "(default:50)") public int maxHttpConnectNumber = 50; @Getter @Parameter(description = "--seed-nodes") @@ -170,11 +180,6 @@ public class CommonParameter { public long nodeP2pPingInterval; @Getter @Setter - @Parameter(names = {"--save-internaltx"}, description = "Save internal transactions generated " + - "during TVM execution, such as create, call, suicide and so on. (default: false)") - public boolean saveInternalTx; - @Getter - @Setter public int nodeP2pVersion; @Getter @Setter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index f91d04074ad..e4725f413e5 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -192,6 +192,8 @@ public class Constant { public static final String VM_SAVE_INTERNAL_TX = "vm.saveInternalTx"; + public static final String VM_SAVE_FEATURED_INTERNAL_TX = "vm.saveFeaturedInternalTx"; + // public static final String COMMITTEE_ALLOW_SHIELDED_TRANSACTION = "committee.allowShieldedTransaction"; public static final String COMMITTEE_ALLOW_SHIELDED_TRC20_TRANSACTION = "committee" diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index d88d3a95852..72b526ad57b 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -829,6 +829,10 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.VM_SAVE_INTERNAL_TX) && config.getBoolean(Constant.VM_SAVE_INTERNAL_TX); + PARAMETER.saveFeaturedInternalTx = + config.hasPath(Constant.VM_SAVE_FEATURED_INTERNAL_TX) + && config.getBoolean(Constant.VM_SAVE_FEATURED_INTERNAL_TX); + // PARAMETER.allowShieldedTransaction = // config.hasPath(Constant.COMMITTEE_ALLOW_SHIELDED_TRANSACTION) ? config // .getInt(Constant.COMMITTEE_ALLOW_SHIELDED_TRANSACTION) : 0; diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 6235167cb57..7c8a9ec0913 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -566,6 +566,9 @@ vm = { maxTimeRatio = 5.0 saveInternalTx = false + # Indicates whether the node stores featured internal transactions, such as freeze, vote and so on + # saveFeaturedInternalTx = true + # In rare cases, transactions that will be within the specified maximum execution time (default 10(ms)) are re-executed and packaged # longRunningTime = 10 } From 3ec907b608ad89dfbe5f6a245d754b7f656f01b8 Mon Sep 17 00:00:00 2001 From: chaozhu Date: Tue, 20 Dec 2022 16:50:06 +0800 Subject: [PATCH 0476/1197] add stake2.0 new interfaces to rpc api on solidity --- .../src/main/java/org/tron/core/Wallet.java | 3 + .../interfaceOnPBFT/RpcApiServiceOnPBFT.java | 55 ++++++++++++++++++- ...etAvailableUnfreezeCountOnPBFTServlet.java | 25 +++++++++ .../GetCanDelegatedMaxSizeOnPBFTServlet.java | 25 +++++++++ ...anWithdrawUnfreezeAmountOnPBFTServlet.java | 26 +++++++++ ...edResourceAccountIndexV2OnPBFTServlet.java | 26 +++++++++ .../GetDelegatedResourceV2OnPBFTServlet.java | 25 +++++++++ .../http/PBFT/HttpApiOnPBFTService.java | 28 ++++++++++ .../RpcApiServiceOnSolidity.java | 45 ++++++++++++++- 9 files changed, 256 insertions(+), 2 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetAvailableUnfreezeCountOnPBFTServlet.java create mode 100644 framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetCanDelegatedMaxSizeOnPBFTServlet.java create mode 100644 framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetCanWithdrawUnfreezeAmountOnPBFTServlet.java create mode 100644 framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetDelegatedResourceAccountIndexV2OnPBFTServlet.java create mode 100644 framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetDelegatedResourceV2OnPBFTServlet.java diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index b79bd3510e7..af00fb7b389 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -821,6 +821,9 @@ public GrpcAPI.CanDelegatedMaxSizeResponseMessage getCanDelegatedMaxSize( canDelegatedMaxSize = this.calcCanDelegatedEnergyMaxSize(ownerAddress); } + if (canDelegatedMaxSize < TRX_PRECISION) { + canDelegatedMaxSize = 0L; + } builder.setMaxSize(canDelegatedMaxSize); return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java index 286613b14b9..281714bc083 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java @@ -16,11 +16,17 @@ import org.tron.api.GrpcAPI.BlockExtention; import org.tron.api.GrpcAPI.BlockReference; import org.tron.api.GrpcAPI.BytesMessage; +import org.tron.api.GrpcAPI.CanDelegatedMaxSizeRequestMessage; +import org.tron.api.GrpcAPI.CanDelegatedMaxSizeResponseMessage; +import org.tron.api.GrpcAPI.CanWithdrawUnfreezeAmountRequestMessage; +import org.tron.api.GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage; import org.tron.api.GrpcAPI.DecryptNotesTRC20; import org.tron.api.GrpcAPI.DelegatedResourceList; import org.tron.api.GrpcAPI.DelegatedResourceMessage; import org.tron.api.GrpcAPI.EmptyMessage; import org.tron.api.GrpcAPI.ExchangeList; +import org.tron.api.GrpcAPI.GetAvailableUnfreezeCountRequestMessage; +import org.tron.api.GrpcAPI.GetAvailableUnfreezeCountResponseMessage; import org.tron.api.GrpcAPI.IvkDecryptTRC20Parameters; import org.tron.api.GrpcAPI.NfTRC20Parameters; import org.tron.api.GrpcAPI.NoteParameters; @@ -44,6 +50,7 @@ import org.tron.core.services.ratelimiter.RpcApiAccessInterceptor; import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.Block; +import org.tron.protos.Protocol.DelegatedResourceAccountIndex; import org.tron.protos.Protocol.DynamicProperties; import org.tron.protos.Protocol.Exchange; import org.tron.protos.Protocol.MarketOrder; @@ -58,6 +65,7 @@ import org.tron.protos.contract.ShieldContract.OutputPointInfo; import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; + @Slf4j(topic = "API") public class RpcApiServiceOnPBFT implements Service { @@ -298,15 +306,60 @@ public void getDelegatedResource(DelegatedResourceMessage request, ); } + @Override + public void getDelegatedResourceV2(DelegatedResourceMessage request, + StreamObserver responseObserver) { + walletOnPBFT.futureGet( + () -> rpcApiService.getWalletSolidityApi() + .getDelegatedResourceV2(request, responseObserver) + ); + } + @Override public void getDelegatedResourceAccountIndex(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { walletOnPBFT.futureGet( () -> rpcApiService.getWalletSolidityApi() .getDelegatedResourceAccountIndex(request, responseObserver) ); } + @Override + public void getDelegatedResourceAccountIndexV2(BytesMessage request, + StreamObserver responseObserver) { + walletOnPBFT.futureGet( + () -> rpcApiService.getWalletSolidityApi() + .getDelegatedResourceAccountIndexV2(request, responseObserver) + ); + } + + @Override + public void getCanDelegatedMaxSize(CanDelegatedMaxSizeRequestMessage request, + StreamObserver responseObserver) { + walletOnPBFT.futureGet( + () -> rpcApiService.getWalletSolidityApi() + .getCanDelegatedMaxSize(request, responseObserver) + ); + } + + @Override + public void getAvailableUnfreezeCount(GetAvailableUnfreezeCountRequestMessage request, + StreamObserver responseObserver) { + walletOnPBFT.futureGet( + () -> rpcApiService.getWalletSolidityApi() + .getAvailableUnfreezeCount(request, responseObserver) + ); + } + + @Override + public void getCanWithdrawUnfreezeAmount(CanWithdrawUnfreezeAmountRequestMessage request, + StreamObserver responseObserver) { + walletOnPBFT.futureGet( + () -> rpcApiService.getWalletSolidityApi() + .getCanWithdrawUnfreezeAmount(request, responseObserver) + ); + } + @Override public void getTransactionCountByBlockNum(NumberMessage request, StreamObserver responseObserver) { diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetAvailableUnfreezeCountOnPBFTServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetAvailableUnfreezeCountOnPBFTServlet.java new file mode 100644 index 00000000000..bb393f92efc --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetAvailableUnfreezeCountOnPBFTServlet.java @@ -0,0 +1,25 @@ +package org.tron.core.services.interfaceOnPBFT.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetAvailableUnfreezeCountServlet; +import org.tron.core.services.interfaceOnPBFT.WalletOnPBFT; + +@Component +@Slf4j(topic = "API") +public class GetAvailableUnfreezeCountOnPBFTServlet extends GetAvailableUnfreezeCountServlet { + + @Autowired + private WalletOnPBFT walletOnPBFT; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetCanDelegatedMaxSizeOnPBFTServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetCanDelegatedMaxSizeOnPBFTServlet.java new file mode 100644 index 00000000000..8b3b47462e8 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetCanDelegatedMaxSizeOnPBFTServlet.java @@ -0,0 +1,25 @@ +package org.tron.core.services.interfaceOnPBFT.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetCanDelegatedMaxSizeServlet; +import org.tron.core.services.interfaceOnPBFT.WalletOnPBFT; + +@Component +@Slf4j(topic = "API") +public class GetCanDelegatedMaxSizeOnPBFTServlet extends GetCanDelegatedMaxSizeServlet { + + @Autowired + private WalletOnPBFT walletOnPBFT; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetCanWithdrawUnfreezeAmountOnPBFTServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetCanWithdrawUnfreezeAmountOnPBFTServlet.java new file mode 100644 index 00000000000..c8b20c4eef7 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetCanWithdrawUnfreezeAmountOnPBFTServlet.java @@ -0,0 +1,26 @@ +package org.tron.core.services.interfaceOnPBFT.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetCanWithdrawUnfreezeAmountServlet; +import org.tron.core.services.interfaceOnPBFT.WalletOnPBFT; + +@Component +@Slf4j(topic = "API") +public class GetCanWithdrawUnfreezeAmountOnPBFTServlet + extends GetCanWithdrawUnfreezeAmountServlet { + + @Autowired + private WalletOnPBFT walletOnPBFT; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetDelegatedResourceAccountIndexV2OnPBFTServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetDelegatedResourceAccountIndexV2OnPBFTServlet.java new file mode 100644 index 00000000000..07541905300 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetDelegatedResourceAccountIndexV2OnPBFTServlet.java @@ -0,0 +1,26 @@ +package org.tron.core.services.interfaceOnPBFT.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetDelegatedResourceAccountIndexV2Servlet; +import org.tron.core.services.interfaceOnPBFT.WalletOnPBFT; + +@Component +@Slf4j(topic = "API") +public class GetDelegatedResourceAccountIndexV2OnPBFTServlet extends + GetDelegatedResourceAccountIndexV2Servlet { + + @Autowired + private WalletOnPBFT walletOnPBFT; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetDelegatedResourceV2OnPBFTServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetDelegatedResourceV2OnPBFTServlet.java new file mode 100644 index 00000000000..6429c90eec5 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetDelegatedResourceV2OnPBFTServlet.java @@ -0,0 +1,25 @@ +package org.tron.core.services.interfaceOnPBFT.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetDelegatedResourceV2Servlet; +import org.tron.core.services.interfaceOnPBFT.WalletOnPBFT; + +@Component +@Slf4j(topic = "API") +public class GetDelegatedResourceV2OnPBFTServlet extends GetDelegatedResourceV2Servlet { + + @Autowired + private WalletOnPBFT walletOnPBFT; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java index 13b356deba1..a6e560e78be 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java @@ -20,14 +20,19 @@ import org.tron.core.services.interfaceOnPBFT.http.GetAssetIssueByNameOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetAssetIssueListByNameOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetAssetIssueListOnPBFTServlet; +import org.tron.core.services.interfaceOnPBFT.http.GetAvailableUnfreezeCountOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetBlockByIdOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetBlockByLatestNumOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetBlockByLimitNextOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetBlockByNumOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetBrokerageOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetBurnTrxOnPBFTServlet; +import org.tron.core.services.interfaceOnPBFT.http.GetCanDelegatedMaxSizeOnPBFTServlet; +import org.tron.core.services.interfaceOnPBFT.http.GetCanWithdrawUnfreezeAmountOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetDelegatedResourceAccountIndexOnPBFTServlet; +import org.tron.core.services.interfaceOnPBFT.http.GetDelegatedResourceAccountIndexV2OnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetDelegatedResourceOnPBFTServlet; +import org.tron.core.services.interfaceOnPBFT.http.GetDelegatedResourceV2OnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetEnergyPricesOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetExchangeByIdOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetMarketOrderByAccountOnPBFTServlet; @@ -154,6 +159,18 @@ public class HttpApiOnPBFTService implements Service { @Autowired private GetBlockOnPBFTServlet getBlockOnPBFTServlet; + @Autowired + private GetAvailableUnfreezeCountOnPBFTServlet getAvailableUnfreezeCountOnPBFTServlet; + @Autowired + private GetCanDelegatedMaxSizeOnPBFTServlet getCanDelegatedMaxSizeOnPBFTServlet; + @Autowired + private GetCanWithdrawUnfreezeAmountOnPBFTServlet getCanWithdrawUnfreezeAmountOnPBFTServlet; + @Autowired + private GetDelegatedResourceAccountIndexV2OnPBFTServlet + getDelegatedResourceAccountIndexV2OnPBFTServlet; + @Autowired + private GetDelegatedResourceV2OnPBFTServlet getDelegatedResourceV2OnPBFTServlet; + @Override public void init() { @@ -243,6 +260,17 @@ public void start() { context.addServlet(new ServletHolder(getBlockOnPBFTServlet), "/getblock"); + context.addServlet(new ServletHolder(getAvailableUnfreezeCountOnPBFTServlet), + "/getavailableunfreezecount"); + context.addServlet(new ServletHolder(getCanDelegatedMaxSizeOnPBFTServlet), + "/getcandelegatedmaxsize"); + context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountOnPBFTServlet), + "/getcanwithdrawunfreezeamount"); + context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexV2OnPBFTServlet), + "/getdelegatedresourceaccountindexv2"); + context.addServlet(new ServletHolder(getDelegatedResourceV2OnPBFTServlet), + "/getdelegatedresourcev2"); + int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { server.addBean(new ConnectionLimit(maxHttpConnectNumber, server)); diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java index 4d9d0361d23..2fc4b88de9b 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java @@ -17,10 +17,16 @@ import org.tron.api.GrpcAPI.BlockExtention; import org.tron.api.GrpcAPI.BlockReference; import org.tron.api.GrpcAPI.BytesMessage; +import org.tron.api.GrpcAPI.CanDelegatedMaxSizeRequestMessage; +import org.tron.api.GrpcAPI.CanDelegatedMaxSizeResponseMessage; +import org.tron.api.GrpcAPI.CanWithdrawUnfreezeAmountRequestMessage; +import org.tron.api.GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage; import org.tron.api.GrpcAPI.DelegatedResourceList; import org.tron.api.GrpcAPI.DelegatedResourceMessage; import org.tron.api.GrpcAPI.EmptyMessage; import org.tron.api.GrpcAPI.ExchangeList; +import org.tron.api.GrpcAPI.GetAvailableUnfreezeCountRequestMessage; +import org.tron.api.GrpcAPI.GetAvailableUnfreezeCountResponseMessage; import org.tron.api.GrpcAPI.NoteParameters; import org.tron.api.GrpcAPI.NumberMessage; import org.tron.api.GrpcAPI.PaginatedMessage; @@ -46,6 +52,7 @@ import org.tron.core.services.ratelimiter.RpcApiAccessInterceptor; import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.Block; +import org.tron.protos.Protocol.DelegatedResourceAccountIndex; import org.tron.protos.Protocol.DynamicProperties; import org.tron.protos.Protocol.Exchange; import org.tron.protos.Protocol.MarketOrder; @@ -60,6 +67,7 @@ import org.tron.protos.contract.ShieldContract.OutputPointInfo; import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; + @Slf4j(topic = "API") public class RpcApiServiceOnSolidity implements Service { @@ -305,13 +313,48 @@ public void getDelegatedResource(DelegatedResourceMessage request, .getDelegatedResource(request, responseObserver)); } + @Override + public void getDelegatedResourceV2(DelegatedResourceMessage request, + StreamObserver responseObserver) { + walletOnSolidity.futureGet(() -> rpcApiService.getWalletSolidityApi() + .getDelegatedResourceV2(request, responseObserver)); + } + @Override public void getDelegatedResourceAccountIndex(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { walletOnSolidity.futureGet(() -> rpcApiService.getWalletSolidityApi() .getDelegatedResourceAccountIndex(request, responseObserver)); } + @Override + public void getDelegatedResourceAccountIndexV2(BytesMessage request, + StreamObserver responseObserver) { + walletOnSolidity.futureGet(() -> rpcApiService.getWalletSolidityApi() + .getDelegatedResourceAccountIndexV2(request, responseObserver)); + } + + @Override + public void getCanDelegatedMaxSize(CanDelegatedMaxSizeRequestMessage request, + StreamObserver responseObserver) { + walletOnSolidity.futureGet(() -> rpcApiService.getWalletSolidityApi() + .getCanDelegatedMaxSize(request, responseObserver)); + } + + @Override + public void getAvailableUnfreezeCount(GetAvailableUnfreezeCountRequestMessage request, + StreamObserver responseObserver) { + walletOnSolidity.futureGet(() -> rpcApiService.getWalletSolidityApi() + .getAvailableUnfreezeCount(request, responseObserver)); + } + + @Override + public void getCanWithdrawUnfreezeAmount(CanWithdrawUnfreezeAmountRequestMessage request, + StreamObserver responseObserver) { + walletOnSolidity.futureGet(() -> rpcApiService.getWalletSolidityApi() + .getCanWithdrawUnfreezeAmount(request, responseObserver)); + } + @Override public void getTransactionCountByBlockNum(NumberMessage request, StreamObserver responseObserver) { From 1c1ccf039835bf52986d368284ec355019aa4a7a Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 26 Dec 2022 15:26:07 +0800 Subject: [PATCH 0477/1197] style: fix check style --- .../tron/core/net/P2pEventHandlerImpl.java | 3 +- .../tron/common/runtime/vm/FreezeV2Test.java | 185 +++++++++--------- 2 files changed, 96 insertions(+), 92 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java index 2da01fe929f..94f8191323b 100644 --- a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java +++ b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java @@ -137,8 +137,7 @@ private void processMessage(PeerConnection peer, byte[] data) { type = msg.getType(); peer.getPeerStatistics().messageStatistics.addTcpInMessage(msg); if (PeerConnection.needToLog(msg)) { - logger.info("Receive message from peer: {}, {}", - peer.getInetSocketAddress(), msg); + logger.info("Receive message from peer: {}, {}", peer.getInetSocketAddress(), msg); } switch (type) { case P2P_PING: diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java index 69529bbd3f0..b35b9870783 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -60,92 +60,92 @@ @Slf4j public class FreezeV2Test { - private static final String FREEZE_V2_CODE = - "6080604052610e85806100136000396000f3fe60806040526004361061010d5760003560e01c80635897454711" - + "610095578063b335634e11610064578063b335634e14610457578063c1a98a3714610491578063df860ab314" - + "6104cb578063f0130dc914610525578063f70eb4c51461055f57600080fd5b8063589745471461035d578063" - + "85510c71146103975780639eb506e2146103ee578063a465bb191461042857600080fd5b8063236051ed1161" - + "00dc578063236051ed146102235780632fe36be51461026b57806333e7645d146102a5578063350a02341461" - + "02f45780633dcba6fc1461032e57600080fd5b8063089480871461011957806308bee6c4146101555780630a" - + "2dd8521461018f578063212743c9146101e957600080fd5b3661011457005b600080fd5b3480156101255760" - + "0080fd5b50d3801561013257600080fd5b50d2801561013f57600080fd5b5061015361014e366004610c9156" - + "5b610599565b005b34801561016157600080fd5b50d3801561016e57600080fd5b50d2801561017b57600080" - + "fd5b5061015361018a366004610cd4565b61060a565b34801561019b57600080fd5b50d380156101a8576000" - + "80fd5b50d280156101b557600080fd5b506101c96101c4366004610cf6565b61065d565b6040805193845260" - + "20840192909252908201526060015b60405180910390f35b3480156101f557600080fd5b50d3801561020257" - + "600080fd5b50d2801561020f57600080fd5b5061015361021e366004610d2b565b6106d5565b34801561022f" - + "57600080fd5b50d3801561023c57600080fd5b50d2801561024957600080fd5b5061025d610258366004610c" - + "f6565b6106e1565b6040519081526020016101e0565b34801561027757600080fd5b50d38015610284576000" - + "80fd5b50d2801561029157600080fd5b506101536102a0366004610cd4565b61074a565b3480156102b15760" - + "0080fd5b50d380156102be57600080fd5b50d280156102cb57600080fd5b506102df6102da366004610cf656" - + "5b610795565b604080519283526020830191909152016101e0565b34801561030057600080fd5b50d3801561" - + "030d57600080fd5b50d2801561031a57600080fd5b50610153610329366004610c91565b610802565b348015" - + "61033a57600080fd5b50d3801561034757600080fd5b50d2801561035457600080fd5b5061015361086a565b" - + "34801561036957600080fd5b50d3801561037657600080fd5b50d2801561038357600080fd5b5061025d6103" - + "92366004610cf6565b610897565b3480156103a357600080fd5b50d380156103b057600080fd5b50d2801561" - + "03bd57600080fd5b506103c66108bd565b604080519586526020860194909452928401919091526060830152" - + "608082015260a0016101e0565b3480156103fa57600080fd5b50d3801561040757600080fd5b50d280156104" - + "1457600080fd5b5061025d610423366004610cf6565b610a69565b34801561043457600080fd5b50d3801561" - + "044157600080fd5b50d2801561044e57600080fd5b5061025d610a8f565b34801561046357600080fd5b50d3" - + "801561047057600080fd5b50d2801561047d57600080fd5b5061025d61048c366004610d58565b610ad0565b" - + "34801561049d57600080fd5b50d380156104aa57600080fd5b50d280156104b757600080fd5b5061025d6104" - + "c6366004610cf6565b610b42565b3480156104d757600080fd5b50d380156104e457600080fd5b50d2801561" - + "04f157600080fd5b50610505610500366004610da6565b610b68565b60408051948552602085019390935291" - + "83015260608201526080016101e0565b34801561053157600080fd5b50d3801561053e57600080fd5b50d280" - + "1561054b57600080fd5b5061025d61055a366004610cf6565b610bf2565b34801561056b57600080fd5b50d3" - + "801561057857600080fd5b50d2801561058557600080fd5b5061025d610594366004610d2b565b610c18565b" - + "806001600160a01b03168383de1580156105b7573d6000803e3d6000fd5b5060408051848152602081018490" - + "526001600160a01b038316918101919091527fe0dda9e5664a3dcfa0628dc0392b74a4b2c63ba4887270f855" - + "7c1ed7deef3c82906060015b60405180910390a1505050565b8181da15801561061e573d6000803e3d6000fd" - + "5b5060408051838152602081018390527fc20c50cd22b066cd9d0cbbe9adbdee2f66da283d9971f5ff840fb0" - + "1af79d980891015b60405180910390a15050565b604080516001600160a01b03841681526020810183905260" - + "00918291829182918291630100001291016040805180830381855afa1580156106a2573d6000803e3d6000fd" - + "5b5050506040513d601f19601f820116820180604052508101906106c59190610de4565b9098909750439650" - + "945050505050565b806001600160a01b0316ff5b604080516001600160a01b03841681526020810183905260" - + "0091630100001491015b602060405180830381855afa158015610720573d6000803e3d6000fd5b5050506040" - + "513d601f19601f820116820180604052508101906107439190610e08565b9392505050565b8181db15801561" - + "075e573d6000803e3d6000fd5b5060408051838152602081018390527fa2339ebec95cc02eea0ca9e15e5b1b" - + "4dd568105de8c4e47d2c6b96b1969348e89101610651565b604080516001600160a01b038416815260208101" - + "8390526000918291630100000f9101602060405180830381855afa1580156107d5573d6000803e3d6000fd5b" - + "5050506040513d601f19601f820116820180604052508101906107f89190610e08565b944394509250505056" - + "5b806001600160a01b03168383df158015610820573d6000803e3d6000fd5b50604080518481526020810184" - + "90526001600160a01b038316918101919091527fd087798e9716d31cc0ef7780cb451270a6e4b447359da1b9" - + "f169996c3a942801906060016105fd565bdc506040517f2ba20738f2500f7585581bf668aa65ab6de7d1c182" - + "2de5737455214184f37ed590600090a1565b604080516001600160a01b038416815260208101839052600091" - + "630100000e9101610703565b600080600080600080600160405181601f820153602081602083630100000b5a" - + "fa6108ee576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff8316831461090f" - + "57600080fd5b50506000600260405181601f820153602081602083630100000b5afa61093b576040513d6000" - + "823e3d81fd5b602081016040528051925067ffffffffffffffff8316831461095c57600080fd5b5050600060" - + "0360405181601f820153602081602083630100000b5afa610988576040513d6000823e3d81fd5b6020810160" - + "40528051925067ffffffffffffffff831683146109a957600080fd5b50506000600460405181601f82015360" - + "2081602083630100000b5afa6109d5576040513d6000823e3d81fd5b602081016040528051925067ffffffff" - + "ffffffff831683146109f657600080fd5b50506000600560405181601f820153602081602083630100000b5a" - + "fa610a22576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff83168314610a43" - + "57600080fd5b505067ffffffffffffffff9485169a938516995091841697508316955090911692509050565b" - + "604080516001600160a01b03841681526020810183905260009163010000139101610703565b6000dd90507f" - + "6a5f656ed489ef1dec34a7317ceb95e7363440f72efdb653107e66982370f06181604051610ac59181526020" - + "0190565b60405180910390a190565b604080516001600160a01b038086168252841660208201529081018290" - + "52600090630100001090606001602060405180830381855afa158015610b17573d6000803e3d6000fd5b5050" - + "506040513d601f19601f82011682018060405250810190610b3a9190610e08565b949350505050565b604080" - + "516001600160a01b03841681526020810183905260009163010000159101610703565b604080516001600160" - + "a01b038516815260208101849052908101829052600090819081908190819081908190630100001190606001" - + "606060405180830381855afa158015610bba573d6000803e3d6000fd5b5050506040513d601f19601f820116" - + "82018060405250810190610bdd9190610e21565b919c909b509099504398509650505050505050565b604080" - + "516001600160a01b038416815260208101839052600091630100000d9101610703565b6040516001600160a0" - + "1b0382168152600090630100000c90602001602060405180830381855afa158015610c50573d6000803e3d60" - + "00fd5b5050506040513d601f19601f82011682018060405250810190610c739190610e08565b92915050565b" - + "6001600160a81b0381168114610c8e57600080fd5b50565b600080600060608486031215610ca657600080fd" - + "5b83359250602084013591506040840135610cbf81610c79565b9295919450506001600160a01b0390911691" - + "50565b60008060408385031215610ce757600080fd5b50508035926020909101359150565b60008060408385" - + "031215610d0957600080fd5b8235610d1481610c79565b6001600160a01b0316946020939093013593505050" - + "565b600060208284031215610d3d57600080fd5b8135610d4881610c79565b6001600160a01b031693925050" - + "50565b600080600060608486031215610d6d57600080fd5b8335610d7881610c79565b6001600160a01b0390" - + "81169350602085013590610d9482610c79565b93969316945050506040919091013590565b60008060006060" - + "8486031215610dbb57600080fd5b8335610dc681610c79565b6001600160a01b031695602085013595506040" - + "909401359392505050565b60008060408385031215610df757600080fd5b5050805160209091015190929091" - + "50565b600060208284031215610e1a57600080fd5b5051919050565b600080600060608486031215610e3657" - + "600080fd5b835192506020840151915060408401519050925092509256fea26474726f6e582212206da319ce" - + "ceb62dd2226a1f18adea5269deb830ff85c48e54bc8a6ed8822d8a3a64736f6c63430008110033"; + private static final String FREEZE_V2_CODE = "60" + + "80604052610e85806100136000396000f3fe60806040526004361061010d5760003560e01c80635897454711" + + "610095578063b335634e11610064578063b335634e14610457578063c1a98a3714610491578063df860ab314" + + "6104cb578063f0130dc914610525578063f70eb4c51461055f57600080fd5b8063589745471461035d578063" + + "85510c71146103975780639eb506e2146103ee578063a465bb191461042857600080fd5b8063236051ed1161" + + "00dc578063236051ed146102235780632fe36be51461026b57806333e7645d146102a5578063350a02341461" + + "02f45780633dcba6fc1461032e57600080fd5b8063089480871461011957806308bee6c4146101555780630a" + + "2dd8521461018f578063212743c9146101e957600080fd5b3661011457005b600080fd5b3480156101255760" + + "0080fd5b50d3801561013257600080fd5b50d2801561013f57600080fd5b5061015361014e366004610c9156" + + "5b610599565b005b34801561016157600080fd5b50d3801561016e57600080fd5b50d2801561017b57600080" + + "fd5b5061015361018a366004610cd4565b61060a565b34801561019b57600080fd5b50d380156101a8576000" + + "80fd5b50d280156101b557600080fd5b506101c96101c4366004610cf6565b61065d565b6040805193845260" + + "20840192909252908201526060015b60405180910390f35b3480156101f557600080fd5b50d3801561020257" + + "600080fd5b50d2801561020f57600080fd5b5061015361021e366004610d2b565b6106d5565b34801561022f" + + "57600080fd5b50d3801561023c57600080fd5b50d2801561024957600080fd5b5061025d610258366004610c" + + "f6565b6106e1565b6040519081526020016101e0565b34801561027757600080fd5b50d38015610284576000" + + "80fd5b50d2801561029157600080fd5b506101536102a0366004610cd4565b61074a565b3480156102b15760" + + "0080fd5b50d380156102be57600080fd5b50d280156102cb57600080fd5b506102df6102da366004610cf656" + + "5b610795565b604080519283526020830191909152016101e0565b34801561030057600080fd5b50d3801561" + + "030d57600080fd5b50d2801561031a57600080fd5b50610153610329366004610c91565b610802565b348015" + + "61033a57600080fd5b50d3801561034757600080fd5b50d2801561035457600080fd5b5061015361086a565b" + + "34801561036957600080fd5b50d3801561037657600080fd5b50d2801561038357600080fd5b5061025d6103" + + "92366004610cf6565b610897565b3480156103a357600080fd5b50d380156103b057600080fd5b50d2801561" + + "03bd57600080fd5b506103c66108bd565b604080519586526020860194909452928401919091526060830152" + + "608082015260a0016101e0565b3480156103fa57600080fd5b50d3801561040757600080fd5b50d280156104" + + "1457600080fd5b5061025d610423366004610cf6565b610a69565b34801561043457600080fd5b50d3801561" + + "044157600080fd5b50d2801561044e57600080fd5b5061025d610a8f565b34801561046357600080fd5b50d3" + + "801561047057600080fd5b50d2801561047d57600080fd5b5061025d61048c366004610d58565b610ad0565b" + + "34801561049d57600080fd5b50d380156104aa57600080fd5b50d280156104b757600080fd5b5061025d6104" + + "c6366004610cf6565b610b42565b3480156104d757600080fd5b50d380156104e457600080fd5b50d2801561" + + "04f157600080fd5b50610505610500366004610da6565b610b68565b60408051948552602085019390935291" + + "83015260608201526080016101e0565b34801561053157600080fd5b50d3801561053e57600080fd5b50d280" + + "1561054b57600080fd5b5061025d61055a366004610cf6565b610bf2565b34801561056b57600080fd5b50d3" + + "801561057857600080fd5b50d2801561058557600080fd5b5061025d610594366004610d2b565b610c18565b" + + "806001600160a01b03168383de1580156105b7573d6000803e3d6000fd5b5060408051848152602081018490" + + "526001600160a01b038316918101919091527fe0dda9e5664a3dcfa0628dc0392b74a4b2c63ba4887270f855" + + "7c1ed7deef3c82906060015b60405180910390a1505050565b8181da15801561061e573d6000803e3d6000fd" + + "5b5060408051838152602081018390527fc20c50cd22b066cd9d0cbbe9adbdee2f66da283d9971f5ff840fb0" + + "1af79d980891015b60405180910390a15050565b604080516001600160a01b03841681526020810183905260" + + "00918291829182918291630100001291016040805180830381855afa1580156106a2573d6000803e3d6000fd" + + "5b5050506040513d601f19601f820116820180604052508101906106c59190610de4565b9098909750439650" + + "945050505050565b806001600160a01b0316ff5b604080516001600160a01b03841681526020810183905260" + + "0091630100001491015b602060405180830381855afa158015610720573d6000803e3d6000fd5b5050506040" + + "513d601f19601f820116820180604052508101906107439190610e08565b9392505050565b8181db15801561" + + "075e573d6000803e3d6000fd5b5060408051838152602081018390527fa2339ebec95cc02eea0ca9e15e5b1b" + + "4dd568105de8c4e47d2c6b96b1969348e89101610651565b604080516001600160a01b038416815260208101" + + "8390526000918291630100000f9101602060405180830381855afa1580156107d5573d6000803e3d6000fd5b" + + "5050506040513d601f19601f820116820180604052508101906107f89190610e08565b944394509250505056" + + "5b806001600160a01b03168383df158015610820573d6000803e3d6000fd5b50604080518481526020810184" + + "90526001600160a01b038316918101919091527fd087798e9716d31cc0ef7780cb451270a6e4b447359da1b9" + + "f169996c3a942801906060016105fd565bdc506040517f2ba20738f2500f7585581bf668aa65ab6de7d1c182" + + "2de5737455214184f37ed590600090a1565b604080516001600160a01b038416815260208101839052600091" + + "630100000e9101610703565b600080600080600080600160405181601f820153602081602083630100000b5a" + + "fa6108ee576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff8316831461090f" + + "57600080fd5b50506000600260405181601f820153602081602083630100000b5afa61093b576040513d6000" + + "823e3d81fd5b602081016040528051925067ffffffffffffffff8316831461095c57600080fd5b5050600060" + + "0360405181601f820153602081602083630100000b5afa610988576040513d6000823e3d81fd5b6020810160" + + "40528051925067ffffffffffffffff831683146109a957600080fd5b50506000600460405181601f82015360" + + "2081602083630100000b5afa6109d5576040513d6000823e3d81fd5b602081016040528051925067ffffffff" + + "ffffffff831683146109f657600080fd5b50506000600560405181601f820153602081602083630100000b5a" + + "fa610a22576040513d6000823e3d81fd5b602081016040528051925067ffffffffffffffff83168314610a43" + + "57600080fd5b505067ffffffffffffffff9485169a938516995091841697508316955090911692509050565b" + + "604080516001600160a01b03841681526020810183905260009163010000139101610703565b6000dd90507f" + + "6a5f656ed489ef1dec34a7317ceb95e7363440f72efdb653107e66982370f06181604051610ac59181526020" + + "0190565b60405180910390a190565b604080516001600160a01b038086168252841660208201529081018290" + + "52600090630100001090606001602060405180830381855afa158015610b17573d6000803e3d6000fd5b5050" + + "506040513d601f19601f82011682018060405250810190610b3a9190610e08565b949350505050565b604080" + + "516001600160a01b03841681526020810183905260009163010000159101610703565b604080516001600160" + + "a01b038516815260208101849052908101829052600090819081908190819081908190630100001190606001" + + "606060405180830381855afa158015610bba573d6000803e3d6000fd5b5050506040513d601f19601f820116" + + "82018060405250810190610bdd9190610e21565b919c909b509099504398509650505050505050565b604080" + + "516001600160a01b038416815260208101839052600091630100000d9101610703565b6040516001600160a0" + + "1b0382168152600090630100000c90602001602060405180830381855afa158015610c50573d6000803e3d60" + + "00fd5b5050506040513d601f19601f82011682018060405250810190610c739190610e08565b92915050565b" + + "6001600160a81b0381168114610c8e57600080fd5b50565b600080600060608486031215610ca657600080fd" + + "5b83359250602084013591506040840135610cbf81610c79565b9295919450506001600160a01b0390911691" + + "50565b60008060408385031215610ce757600080fd5b50508035926020909101359150565b60008060408385" + + "031215610d0957600080fd5b8235610d1481610c79565b6001600160a01b0316946020939093013593505050" + + "565b600060208284031215610d3d57600080fd5b8135610d4881610c79565b6001600160a01b031693925050" + + "50565b600080600060608486031215610d6d57600080fd5b8335610d7881610c79565b6001600160a01b0390" + + "81169350602085013590610d9482610c79565b93969316945050506040919091013590565b60008060006060" + + "8486031215610dbb57600080fd5b8335610dc681610c79565b6001600160a01b031695602085013595506040" + + "909401359392505050565b60008060408385031215610df757600080fd5b5050805160209091015190929091" + + "50565b600060208284031215610e1a57600080fd5b5051919050565b600080600060608486031215610e3657" + + "600080fd5b835192506020840151915060408401519050925092509256fea26474726f6e582212206da319ce" + + "ceb62dd2226a1f18adea5269deb830ff85c48e54bc8a6ed8822d8a3a64736f6c63430008110033"; private static final long value = 100_000_000_000_000_000L; private static final long fee = 1_000_000_000; @@ -900,14 +900,19 @@ private TVMTestResult unDelegateResource( : newReceiver.getAcquiredDelegatedFrozenV2BalanceForEnergy(); Assert.assertTrue(newAcquiredBalance == 0 || acquiredBalance - newAcquiredBalance == amount); if (res == 0) { - Assert.assertEquals(oldReceiver.getNetUsage() - transferUsage, newReceiver.getNetUsage()); Assert.assertEquals( - ChainBaseManager.getInstance().getHeadSlot(), newReceiver.getLastConsumeTime(BANDWIDTH)); + oldReceiver.getNetUsage() - transferUsage, + newReceiver.getNetUsage()); + Assert.assertEquals( + ChainBaseManager.getInstance().getHeadSlot(), + newReceiver.getLastConsumeTime(BANDWIDTH)); } else { Assert.assertEquals( - oldReceiver.getEnergyUsage() + transferUsage, newReceiver.getEnergyUsage()); + oldReceiver.getEnergyUsage() + transferUsage, + newReceiver.getEnergyUsage()); Assert.assertEquals( - ChainBaseManager.getInstance().getHeadSlot(), newReceiver.getLastConsumeTime(ENERGY)); + ChainBaseManager.getInstance().getHeadSlot(), + newReceiver.getLastConsumeTime(ENERGY)); } } else { Assert.assertNull(newReceiver); From 94f84264e8e3bc6648ad63921dd1979a7b4ab3b0 Mon Sep 17 00:00:00 2001 From: liukai Date: Mon, 26 Dec 2022 18:29:19 +0800 Subject: [PATCH 0478/1197] feat(docker): update Dockerfile 1. update the version of the base image referenced by the dockerfile --- docker/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index f19208f1816..2732f5a55ed 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM tronprotocol/centos7 +FROM tronprotocol/centos7:0.2 ENV TMP_DIR="/tron-build" ENV JDK_TAR="jdk-8u202-linux-x64.tar.gz" @@ -24,7 +24,7 @@ RUN set -o errexit -o nounset \ && git checkout master \ && ./gradlew build -x test \ && cd build/distributions \ - && unzip -o java-tron-1.0.0.zip \ + && 7za x -y java-tron-1.0.0.zip \ && mv java-tron-1.0.0 $BASE_DIR \ && rm -rf $TMP_DIR \ && rm -rf ~/.gradle \ From 5d9b2fb1a023197ba9e67a9ed6912bc901ccb90e Mon Sep 17 00:00:00 2001 From: Liulei Date: Tue, 27 Dec 2022 14:58:08 +0800 Subject: [PATCH 0479/1197] feat(freezeV2): fix freezeV2 precompiled contracts --- .../org/tron/core/vm/PrecompiledContracts.java | 16 ++++++++++++---- .../org/tron/common/runtime/vm/FreezeV2Test.java | 4 ++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index be415b9b4fa..942e6ba656d 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -2120,9 +2120,13 @@ public Pair execute(byte[] data) { long delegatedResource = 0; if (type == 0) { - delegatedResource = accountCapsule.getDelegatedFrozenBalanceForBandwidth(); + delegatedResource = + accountCapsule.getDelegatedFrozenBalanceForBandwidth() + + accountCapsule.getDelegatedFrozenV2BalanceForBandwidth(); } else if (type == 1) { - delegatedResource = accountCapsule.getDelegatedFrozenBalanceForEnergy(); + delegatedResource = + accountCapsule.getDelegatedFrozenBalanceForEnergy() + + accountCapsule.getDelegatedFrozenV2BalanceForEnergy(); } return Pair.of(true, longTo32Bytes(delegatedResource)); @@ -2153,9 +2157,13 @@ public Pair execute(byte[] data) { long acquiredResource = 0; if (type == 0) { - acquiredResource = accountCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth(); + acquiredResource = + accountCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() + + accountCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth(); } else if (type == 1) { - acquiredResource = accountCapsule.getAcquiredDelegatedFrozenBalanceForEnergy(); + acquiredResource = + accountCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() + + accountCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy(); } return Pair.of(true, longTo32Bytes(acquiredResource)); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java index b35b9870783..441aee15676 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -995,8 +995,8 @@ private TVMTestResult suicide(byte[] callerAddr, byte[] contractAddr, byte[] inh expectedIncreasingBalance, newInheritor.getBalance() - oldBalanceOfInheritor); } - Assert.assertEquals(0, oldContract.getDelegatedFrozenBalanceForBandwidth()); - Assert.assertEquals(0, oldContract.getDelegatedFrozenBalanceForEnergy()); + Assert.assertEquals(0, oldContract.getDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(0, oldContract.getDelegatedFrozenV2BalanceForEnergy()); Assert.assertEquals( oldContract.getFrozenBalance(), newInheritor.getFrozenBalance() - oldInheritorFrozenBalance); From c1b6783ec724a7c757b20a71ab653b235398aabc Mon Sep 17 00:00:00 2001 From: chaozhu Date: Tue, 27 Dec 2022 18:17:19 +0800 Subject: [PATCH 0480/1197] feat(freezeV2): add lock size in estimateConsumeBandWidthSize function --- actuator/src/main/java/org/tron/core/utils/TransactionUtil.java | 1 + 1 file changed, 1 insertion(+) diff --git a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java index d03ca513822..496af641cde 100644 --- a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java @@ -299,6 +299,7 @@ public static long estimateConsumeBandWidthSize( final AccountCapsule ownerCapsule, ChainBaseManager chainBaseManager) { DelegateResourceContract.Builder builder = DelegateResourceContract.newBuilder() + .setLock(true) .setBalance(ownerCapsule.getFrozenV2BalanceForBandwidth()); TransactionCapsule fakeTransactionCapsule = new TransactionCapsule(builder.build() , ContractType.DelegateResourceContract); From 86efac014c4c44d1a6626f375965164f4d35db56 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Wed, 7 Dec 2022 09:45:01 +0800 Subject: [PATCH 0481/1197] feat(DynamicEnergy): add proposals and parameters --- .../org/tron/core/utils/ProposalUtil.java | 33 +++++- .../core/store/DynamicPropertiesStore.java | 106 +++++++++++++++++- .../common/parameter/CommonParameter.java | 20 ++++ .../src/main/java/org/tron/core/Constant.java | 10 ++ .../src/main/java/org/tron/core/Wallet.java | 25 +++++ .../java/org/tron/core/config/args/Args.java | 37 ++++++ .../tron/core/consensus/ProposalService.java | 20 ++++ 7 files changed, 249 insertions(+), 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index a0154470bc5..35635510227 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -620,6 +620,32 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, break; } + case ALLOW_DYNAMIC_ENERGY: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7)) { + throw new ContractValidateException( + "Bad chain parameter id [UNFREEZE_DELAY_DAYS]"); + } + if (value < 0 || value > 1) { + throw new ContractValidateException( + "This value[ALLOW_DYNAMIC_ENERGY] is only allowed to be in the range 0-1" + ); + } + break; + } + case DYNAMIC_ENERGY_THRESHOLD: + case DYNAMIC_ENERGY_INCREASE_FACTOR: + case DYNAMIC_ENERGY_MAX_FACTOR: + case DYNAMIC_ENERGY_TRIGGER_BASE: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7)) { + throw new ContractValidateException( + "Bad chain parameter id [UNFREEZE_DELAY_DAYS]"); + } + + if (value < 0 || value > LONG_VALUE) { + throw new ContractValidateException(LONG_VALUE_ERROR); + } + break; + } default: break; } @@ -688,7 +714,12 @@ public enum ProposalType { // current value, value range MEMO_FEE(68), // 0, [0, 1000_000_000] ALLOW_DELEGATE_OPTIMIZATION(69), UNFREEZE_DELAY_DAYS(70), // 0, [1, 365] - ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID(71); // 0, 1 + ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID(71), // 0, 1 + ALLOW_DYNAMIC_ENERGY(72), // 0, 1 + DYNAMIC_ENERGY_THRESHOLD(73), // 0, [0, LONG] + DYNAMIC_ENERGY_INCREASE_FACTOR(74), // 0, [0, 1_000_000_000_000] + DYNAMIC_ENERGY_MAX_FACTOR(75), // 0, [0, 1_000_000_000_000] + DYNAMIC_ENERGY_TRIGGER_BASE(76); // 0, [0, 100_000_000] private long code; diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 3770d0ab22e..5554035122d 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -192,6 +192,16 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] MEMO_FEE_HISTORY = "MEMO_FEE_HISTORY".getBytes(); private static final byte[] ALLOW_DELEGATE_OPTIMIZATION = "ALLOW_DELEGATE_OPTIMIZATION".getBytes(); + private static final byte[] ALLOW_DYNAMIC_ENERGY = + "ALLOW_DYNAMIC_ENERGY".getBytes(); + private static final byte[] DYNAMIC_ENERGY_THRESHOLD = + "DYNAMIC_ENERGY_THRESHOLD".getBytes(); + private static final byte[] DYNAMIC_ENERGY_INCREASE_FACTOR = + "DYNAMIC_ENERGY_INCREASE_FACTOR".getBytes(); + private static final byte[] DYNAMIC_ENERGY_MAX_FACTOR = + "DYNAMIC_ENERGY_MAX_FACTOR".getBytes(); + private static final byte[] DYNAMIC_ENERGY_TRIGGER_BASE = + "DYNAMIC_ENERGY_TRIGGER_BASE".getBytes(); private static final byte[] UNFREEZE_DELAY_DAYS = "UNFREEZE_DELAY_DAYS".getBytes(); @@ -898,7 +908,7 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { this.getUnfreezeDelayDays(); } catch (IllegalArgumentException e) { this.saveUnfreezeDelayDays( - CommonParameter.getInstance().getUnfreezeDelayDays() + CommonParameter.getInstance().getUnfreezeDelayDays() ); } @@ -909,6 +919,36 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { CommonParameter.getInstance().getAllowOptimizedReturnValueOfChainId() ); } + + try { + this.getAllowDynamicEnergy(); + } catch (IllegalArgumentException e) { + this.saveAllowDynamicEnergy(CommonParameter.getInstance().getAllowDynamicEnergy()); + } + + try { + this.getDynamicEnergyThreshold(); + } catch (IllegalArgumentException e) { + this.saveDynamicEnergyThreshold(CommonParameter.getInstance().getDynamicEnergyThreshold()); + } + + try { + this.getDynamicEnergyIncreaseFactor(); + } catch (IllegalArgumentException e) { + this.saveDynamicEnergyIncreaseFactor(CommonParameter.getInstance().getDynamicEnergyIncreaseFactor()); + } + + try { + this.getDynamicEnergyMaxFactor(); + } catch (IllegalArgumentException e) { + this.saveDynamicEnergyMaxFactor(CommonParameter.getInstance().getDynamicEnergyMaxFactor()); + } + + try { + this.getDynamicEnergyTriggerBase(); + } catch (IllegalArgumentException e) { + this.saveDynamicEnergyTriggerBase(CommonParameter.getInstance().getDynamicEnergyTriggerBase()); + } } public String intArrayToString(int[] a) { @@ -2638,6 +2678,70 @@ public void saveAllowDelegateOptimization(long value) { this.put(ALLOW_DELEGATE_OPTIMIZATION, new BytesCapsule(ByteArray.fromLong(value))); } + public long getAllowDynamicEnergy() { + return Optional.ofNullable(getUnchecked(ALLOW_DYNAMIC_ENERGY)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException("not found ALLOW_DYNAMIC_ENERGY")); + } + + public boolean supportAllowDynamicEnergy() { + return getAllowDynamicEnergy() == 1L; + } + + public void saveAllowDynamicEnergy(long value) { + this.put(ALLOW_DYNAMIC_ENERGY, new BytesCapsule(ByteArray.fromLong(value))); + } + + public long getDynamicEnergyThreshold() { + return Optional.ofNullable(getUnchecked(DYNAMIC_ENERGY_THRESHOLD)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException("not found DYNAMIC_ENERGY_THRESHOLD")); + } + + public void saveDynamicEnergyThreshold(long value) { + this.put(DYNAMIC_ENERGY_THRESHOLD, new BytesCapsule(ByteArray.fromLong(value))); + } + + public long getDynamicEnergyIncreaseFactor() { + return Optional.ofNullable(getUnchecked(DYNAMIC_ENERGY_INCREASE_FACTOR)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException("not found DYNAMIC_ENERGY_INCREASE_FACTOR")); + } + + public void saveDynamicEnergyIncreaseFactor(long value) { + this.put(DYNAMIC_ENERGY_INCREASE_FACTOR, new BytesCapsule(ByteArray.fromLong(value))); + } + + public long getDynamicEnergyMaxFactor() { + return Optional.ofNullable(getUnchecked(DYNAMIC_ENERGY_MAX_FACTOR)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException("not found DYNAMIC_ENERGY_MAX_FACTOR")); + } + + public void saveDynamicEnergyMaxFactor(long value) { + this.put(DYNAMIC_ENERGY_MAX_FACTOR, new BytesCapsule(ByteArray.fromLong(value))); + } + + public long getDynamicEnergyTriggerBase() { + return Optional.ofNullable(getUnchecked(DYNAMIC_ENERGY_TRIGGER_BASE)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException("not found DYNAMIC_ENERGY_TRIGGER_BASE")); + } + + public void saveDynamicEnergyTriggerBase(long value) { + this.put(DYNAMIC_ENERGY_TRIGGER_BASE, new BytesCapsule(ByteArray.fromLong(value))); + } + public boolean allowNewReward() { return getAllowNewReward() == 1; } diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index e2737e964d9..6476e9d5634 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -580,6 +580,26 @@ public class CommonParameter { @Setter public long allowOptimizedReturnValueOfChainId = 0L; + @Getter + @Setter + public long allowDynamicEnergy = 0L; + + @Getter + @Setter + public long dynamicEnergyThreshold = 0L; + + @Getter + @Setter + public long dynamicEnergyIncreaseFactor = 0L; + + @Getter + @Setter + public long dynamicEnergyMaxFactor = 0L; + + @Getter + @Setter + public long dynamicEnergyTriggerBase = 0L; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index e71b7a7e870..ca2b6c997f5 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -314,6 +314,16 @@ public class Constant { public static final String MEMO_FEE = "committee.memoFee"; public static final String ALLOW_DELEGATE_OPTIMIZATION = "committee.allowDelegateOptimization"; + public static final String ALLOW_DYNAMIC_ENERGY = "committee.allowDynamicEnergy"; + + public static final String DYNAMIC_ENERGY_THRESHOLD = "committee.dynamicEnergyThreshold"; + + public static final String DYNAMIC_ENERGY_INCREASE_FACTOR = "committee.dynamicEnergyIncreaseFactor"; + + public static final String DYNAMIC_ENERGY_MAX_FACTOR = "committee.dynamicEnergyMaxFactor"; + + public static final String DYNAMIC_ENERGY_TRIGGER_BASE = "committee.dynamicEnergyTriggerBase"; + public static final String LOCAL_HOST = "127.0.0.1"; public static final String NODE_SHUTDOWN_BLOCK_TIME = "node.shutdown.BlockTime"; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 21c7bfa4441..e2c08fe9a6b 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1292,6 +1292,31 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getAllowOptimizedReturnValueOfChainId()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getAllowDynamicEnergy") + .setValue(dbManager.getDynamicPropertiesStore().getAllowDynamicEnergy()) + .build()); + + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getDynamicEnergyThreshold") + .setValue(dbManager.getDynamicPropertiesStore().getDynamicEnergyThreshold()) + .build()); + + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getDynamicEnergyIncreaseFactor") + .setValue(dbManager.getDynamicPropertiesStore().getDynamicEnergyIncreaseFactor()) + .build()); + + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getDynamicEnergyMaxFactor") + .setValue(dbManager.getDynamicPropertiesStore().getDynamicEnergyMaxFactor()) + .build()); + + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getDynamicEnergyTriggerBase") + .setValue(dbManager.getDynamicPropertiesStore().getDynamicEnergyTriggerBase()) + .build()); + return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 8347dfbf241..bc170edd817 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -72,6 +72,7 @@ import org.tron.core.config.Parameter.NodeConstant; import org.tron.core.exception.CipherException; import org.tron.core.store.AccountStore; +import org.tron.core.utils.ProposalUtil; import org.tron.keystore.Credentials; import org.tron.keystore.WalletUtils; import org.tron.program.Version; @@ -1075,6 +1076,42 @@ public static void setParam(final String[] args, final String confFileName) { } } + if (config.hasPath(Constant.ALLOW_DYNAMIC_ENERGY)) { + PARAMETER.allowDynamicEnergy = config.getLong(Constant.ALLOW_DYNAMIC_ENERGY); + PARAMETER.allowDynamicEnergy = Math.min(PARAMETER.allowDynamicEnergy, 1); + PARAMETER.allowDynamicEnergy = Math.max(PARAMETER.allowDynamicEnergy, 0); + } + + if (config.hasPath(Constant.DYNAMIC_ENERGY_THRESHOLD)) { + PARAMETER.dynamicEnergyThreshold = config.getLong(Constant.DYNAMIC_ENERGY_THRESHOLD); + PARAMETER.dynamicEnergyThreshold = Math.min(PARAMETER.dynamicEnergyThreshold, 100_000_000_000_000_000L); + PARAMETER.dynamicEnergyThreshold = Math.max(PARAMETER.dynamicEnergyThreshold, 0); + } + + if (config.hasPath(Constant.DYNAMIC_ENERGY_INCREASE_FACTOR)) { + PARAMETER.dynamicEnergyIncreaseFactor = config.getLong(Constant.DYNAMIC_ENERGY_INCREASE_FACTOR); + PARAMETER.dynamicEnergyIncreaseFactor = + Math.min(PARAMETER.dynamicEnergyIncreaseFactor, 100_000_000_000_000_000L); + PARAMETER.dynamicEnergyIncreaseFactor = + Math.max(PARAMETER.dynamicEnergyIncreaseFactor, 0); + } + + if (config.hasPath(Constant.DYNAMIC_ENERGY_MAX_FACTOR)) { + PARAMETER.dynamicEnergyMaxFactor = config.getLong(Constant.DYNAMIC_ENERGY_MAX_FACTOR); + PARAMETER.dynamicEnergyMaxFactor = + Math.min(PARAMETER.dynamicEnergyMaxFactor, 100_000_000_000_000_000L); + PARAMETER.dynamicEnergyMaxFactor = + Math.max(PARAMETER.dynamicEnergyMaxFactor, 0); + } + + if (config.hasPath(Constant.DYNAMIC_ENERGY_TRIGGER_BASE)) { + PARAMETER.dynamicEnergyTriggerBase = config.getLong(Constant.DYNAMIC_ENERGY_TRIGGER_BASE); + PARAMETER.dynamicEnergyTriggerBase = + Math.min(PARAMETER.dynamicEnergyTriggerBase, 100_000_000_000_000_000L); + PARAMETER.dynamicEnergyTriggerBase = + Math.max(PARAMETER.dynamicEnergyTriggerBase, 0); + } + logConfig(); } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index c35549e8749..cbe01247c6f 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -323,6 +323,26 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) .saveAllowOptimizedReturnValueOfChainId(entry.getValue()); break; } + case ALLOW_DYNAMIC_ENERGY: { + manager.getDynamicPropertiesStore().saveAllowDynamicEnergy(entry.getValue()); + break; + } + case DYNAMIC_ENERGY_THRESHOLD: { + manager.getDynamicPropertiesStore().saveDynamicEnergyThreshold(entry.getValue()); + break; + } + case DYNAMIC_ENERGY_INCREASE_FACTOR: { + manager.getDynamicPropertiesStore().saveDynamicEnergyIncreaseFactor(entry.getValue()); + break; + } + case DYNAMIC_ENERGY_MAX_FACTOR: { + manager.getDynamicPropertiesStore().saveDynamicEnergyMaxFactor(entry.getValue()); + break; + } + case DYNAMIC_ENERGY_TRIGGER_BASE: { + manager.getDynamicPropertiesStore().saveDynamicEnergyTriggerBase(entry.getValue()); + break; + } default: find = false; break; From 2c899faf81aaa18f30f49f8d3963686020712b5a Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Tue, 20 Dec 2022 16:57:08 +0800 Subject: [PATCH 0482/1197] feat(DynamicEnergy): add calculations for DynamicEnergy --- .../org/tron/core/actuator/VMActuator.java | 33 +++++++ .../src/main/java/org/tron/core/vm/VM.java | 41 +++++++- .../tron/core/capsule/ContractCapsule.java | 94 +++++++++++++++++++ .../src/main/java/org/tron/core/Constant.java | 5 +- .../protos/core/contract/smart_contract.proto | 4 + 5 files changed, 175 insertions(+), 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 2388768f0d5..ac1b13a02b1 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -4,6 +4,7 @@ import static java.lang.Math.min; import static org.apache.commons.lang3.ArrayUtils.getLength; import static org.apache.commons.lang3.ArrayUtils.isNotEmpty; +import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; import com.google.protobuf.ByteString; import java.math.BigInteger; @@ -50,8 +51,11 @@ import org.tron.core.vm.program.ProgramPrecompile; import org.tron.core.vm.program.invoke.ProgramInvoke; import org.tron.core.vm.program.invoke.ProgramInvokeFactory; +import org.tron.core.vm.repository.Key; import org.tron.core.vm.repository.Repository; import org.tron.core.vm.repository.RepositoryImpl; +import org.tron.core.vm.repository.Type; +import org.tron.core.vm.repository.Value; import org.tron.core.vm.utils.MUtil; import org.tron.protos.Protocol; import org.tron.protos.Protocol.Block; @@ -177,6 +181,35 @@ public void execute(Object object) throws ContractExeException { throw e; } + if (rootRepository.getDynamicPropertiesStore().supportAllowDynamicEnergy()) { + // only add trigger_energy_base when type is call. + if (this.trx.getRawData().getContract(0).getType() + == ContractType.TriggerSmartContract) { + + ContractCapsule deployedContract = + rootRepository.getContract(program.getContextAddress()); + if (deployedContract != null) { + + if (deployedContract.catchUpToCycle( + rootRepository.getDynamicPropertiesStore().getCurrentCycleNumber(), + rootRepository.getDynamicPropertiesStore().getDynamicEnergyThreshold(), + rootRepository.getDynamicPropertiesStore().getDynamicEnergyIncreaseFactor(), + rootRepository.getDynamicPropertiesStore().getDynamicEnergyMaxFactor())) { + rootRepository.putContract( + Key.create(program.getContextAddress()), + Value.create(deployedContract, Type.DIRTY)); + } + + if (deployedContract.getEnergyFactor() > DYNAMIC_ENERGY_FACTOR_DECIMAL) { + program.spendEnergy( + rootRepository.getDynamicPropertiesStore().getDynamicEnergyTriggerBase() + * deployedContract.getEnergyFactor() / DYNAMIC_ENERGY_FACTOR_DECIMAL, + "DYNAMIC_ENERGY_TRIGGER_BASE"); + } + } + } + } + VM.play(program, OperationRegistry.getTable()); result = program.getResult(); diff --git a/actuator/src/main/java/org/tron/core/vm/VM.java b/actuator/src/main/java/org/tron/core/vm/VM.java index 410e7bad311..12f0841519b 100644 --- a/actuator/src/main/java/org/tron/core/vm/VM.java +++ b/actuator/src/main/java/org/tron/core/vm/VM.java @@ -1,19 +1,47 @@ package org.tron.core.vm; +import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; + import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.springframework.util.StringUtils; +import org.tron.core.capsule.ContractCapsule; import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.program.Program; import org.tron.core.vm.program.Program.JVMStackOverFlowException; import org.tron.core.vm.program.Program.OutOfTimeException; import org.tron.core.vm.program.Program.TransferException; +import org.tron.core.vm.repository.Key; +import org.tron.core.vm.repository.Type; +import org.tron.core.vm.repository.Value; @Slf4j(topic = "VM") public class VM { public static void play(Program program, JumpTable jumpTable) { try { + ContractCapsule contextContract = null; + long factor = DYNAMIC_ENERGY_FACTOR_DECIMAL; + + boolean allowDynamicEnergy = + program.getContractState().getDynamicPropertiesStore().supportAllowDynamicEnergy(); + + if (allowDynamicEnergy) { + contextContract = program.getContractState().getContract(program.getContextAddress()); + + if (contextContract.catchUpToCycle( + program.getContractState().getDynamicPropertiesStore().getCurrentCycleNumber(), + program.getContractState().getDynamicPropertiesStore().getDynamicEnergyThreshold(), + program.getContractState().getDynamicPropertiesStore().getDynamicEnergyIncreaseFactor(), + program.getContractState().getDynamicPropertiesStore().getDynamicEnergyMaxFactor())) { + program.getContractState().putContract( + Key.create(program.getContextAddress()), + Value.create(contextContract, Type.DIRTY)); + } + + factor = contextContract.getEnergyFactor(); + } + while (!program.isStopped()) { if (VMConfig.vmTrace()) { program.saveOpTrace(); @@ -32,7 +60,18 @@ public static void play(Program program, JumpTable jumpTable) { String opName = Op.getNameOf(op.getOpcode()); /* spend energy before execution */ - program.spendEnergy(op.getEnergyCost(program), opName); + long energy = op.getEnergyCost(program); + if (allowDynamicEnergy) { + contextContract.addEnergyUsage(energy); + program.getContractState().putContract( + Key.create(program.getContextAddress()), + Value.create(contextContract, Type.DIRTY)); + + if (factor != DYNAMIC_ENERGY_FACTOR_DECIMAL) { + energy = energy * factor / DYNAMIC_ENERGY_FACTOR_DECIMAL; + } + } + program.spendEnergy(energy, opName); /* check if cpu time out */ program.checkCPUTimeLimit(opName); diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java index 2204b6446a3..6e6fda3191f 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java @@ -17,6 +17,7 @@ import static java.lang.Math.max; import static java.lang.Math.min; +import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; import com.google.protobuf.Any; import com.google.protobuf.ByteString; @@ -133,4 +134,97 @@ public byte[] getTrxHash() { public int getContractVersion() { return this.smartContract.getVersion(); } + + public long getEnergyUsage() { + return this.smartContract.getEnergyUsage(); + } + + public void setEnergyUsage(long value) { + this.smartContract = this.smartContract.toBuilder().setEnergyUsage(value).build(); + } + + public void addEnergyUsage(long toAdd) { + setEnergyUsage(getEnergyUsage() + toAdd); + } + + public long getEnergyFactor() { + return this.smartContract.getEnergyFactor(); + } + + public void setEnergyFactor(long value) { + this.smartContract = this.smartContract.toBuilder().setEnergyFactor(value).build(); + } + + public long getUpdateCycle() { + return this.smartContract.getUpdateCycle(); + } + + public void setUpdateCycle(long value) { + this.smartContract = this.smartContract.toBuilder().setUpdateCycle(value).build(); + } + + public void addUpdateCycle(long toAdd) { + setUpdateCycle(getUpdateCycle() + toAdd); + } + + public boolean catchUpToCycle(long newCycle, long threshold, long increaseFactor, long maxFactor) { + long lastCycle = getUpdateCycle(); + if (lastCycle >= newCycle) { + return false; + } + + if (lastCycle == 0L || newCycle - lastCycle >= 10) { + this.smartContract = this.smartContract.toBuilder() + .setUpdateCycle(newCycle) + .setEnergyUsage(0L) + .setEnergyFactor(DYNAMIC_ENERGY_FACTOR_DECIMAL) + .build(); + return true; + } + + // increase first + if (getEnergyUsage() >= threshold) { + lastCycle += 1; + this.smartContract = this.smartContract.toBuilder() + .setUpdateCycle(lastCycle) + .setEnergyUsage(0L) + .setEnergyFactor(Math.min( + maxFactor, + getEnergyFactor() * increaseFactor / DYNAMIC_ENERGY_FACTOR_DECIMAL)) + .build(); + } + + // decrease + long cycleCount = newCycle - lastCycle; + if (cycleCount <= 0) { + return true; + } + + // no need to decrease + if (getEnergyFactor() <= DYNAMIC_ENERGY_FACTOR_DECIMAL) { + this.smartContract = this.smartContract.toBuilder() + .setUpdateCycle(newCycle) + .setEnergyUsage(0L) + .setEnergyFactor(DYNAMIC_ENERGY_FACTOR_DECIMAL) + .build(); + return true; + } + + double decreaseFactor = 1 - ((double) increaseFactor / DYNAMIC_ENERGY_FACTOR_DECIMAL - 1) / 4; + if (cycleCount > 1) { + decreaseFactor = Math.pow( + decreaseFactor, + cycleCount); + } + + this.smartContract = this.smartContract.toBuilder() + .setUpdateCycle(newCycle) + .setEnergyUsage(0L) + .setEnergyFactor(Math.max( + DYNAMIC_ENERGY_FACTOR_DECIMAL, + (long) (getEnergyFactor() * decreaseFactor))) + .build(); + + return true; + } } diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index ca2b6c997f5..469794d2a43 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -318,10 +318,13 @@ public class Constant { public static final String DYNAMIC_ENERGY_THRESHOLD = "committee.dynamicEnergyThreshold"; - public static final String DYNAMIC_ENERGY_INCREASE_FACTOR = "committee.dynamicEnergyIncreaseFactor"; + public static final String DYNAMIC_ENERGY_INCREASE_FACTOR + = "committee.dynamicEnergyIncreaseFactor"; public static final String DYNAMIC_ENERGY_MAX_FACTOR = "committee.dynamicEnergyMaxFactor"; + public static final long DYNAMIC_ENERGY_FACTOR_DECIMAL = 100L; + public static final String DYNAMIC_ENERGY_TRIGGER_BASE = "committee.dynamicEnergyTriggerBase"; public static final String LOCAL_HOST = "127.0.0.1"; diff --git a/protocol/src/main/protos/core/contract/smart_contract.proto b/protocol/src/main/protos/core/contract/smart_contract.proto index ffbf399c38e..a6fba7b696a 100644 --- a/protocol/src/main/protos/core/contract/smart_contract.proto +++ b/protocol/src/main/protos/core/contract/smart_contract.proto @@ -56,6 +56,10 @@ message SmartContract { bytes code_hash = 9; bytes trx_hash = 10; int32 version = 11; + + int64 energy_usage = 12; + int64 energy_factor = 13; + int64 update_cycle = 14; } message CreateSmartContract { From 17d11eef2943404d537476eae353490496b8f239 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Tue, 20 Dec 2022 18:18:55 +0800 Subject: [PATCH 0483/1197] feat(DynamicEnergy): add test for DynamicEnergy cycle updates --- .../core/capsule/ContractCapsuleTest.java | 162 ++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/capsule/ContractCapsuleTest.java diff --git a/framework/src/test/java/org/tron/core/capsule/ContractCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/ContractCapsuleTest.java new file mode 100644 index 00000000000..b009d9dcffe --- /dev/null +++ b/framework/src/test/java/org/tron/core/capsule/ContractCapsuleTest.java @@ -0,0 +1,162 @@ +package org.tron.core.capsule; + +import org.junit.Assert; +import org.junit.Test; +import org.tron.protos.contract.SmartContractOuterClass; + +public class ContractCapsuleTest { + + @Test + public void testCatchUpCycle() { + ContractCapsule capsule = new ContractCapsule( + SmartContractOuterClass.SmartContract.newBuilder() + .setEnergyUsage(1_000_000L) + .setEnergyFactor(150L) + .setUpdateCycle(1000L) + .build()); + + Assert.assertFalse(capsule.catchUpToCycle(1000L, 2_000_000L, 120, 200)); + Assert.assertEquals(1000L, capsule.getUpdateCycle()); + Assert.assertEquals(1_000_000L, capsule.getEnergyUsage()); + Assert.assertEquals(150L, capsule.getEnergyFactor()); + + Assert.assertTrue(capsule.catchUpToCycle(1010L, 1_000_000L, 110, 200)); + Assert.assertEquals(1010L, capsule.getUpdateCycle()); + Assert.assertEquals(0L, capsule.getEnergyUsage()); + Assert.assertEquals(100L, capsule.getEnergyFactor()); + + capsule = new ContractCapsule( + SmartContractOuterClass.SmartContract.newBuilder() + .setEnergyUsage(1_000_000L) + .setEnergyFactor(150L) + .setUpdateCycle(1000L) + .build()); + + Assert.assertTrue(capsule.catchUpToCycle(1009L, 1_000_000L, 110, 200)); + Assert.assertEquals(1009L, capsule.getUpdateCycle()); + Assert.assertEquals(0L, capsule.getEnergyUsage()); + Assert.assertEquals(134L, capsule.getEnergyFactor()); + + capsule = new ContractCapsule( + SmartContractOuterClass.SmartContract.newBuilder() + .setEnergyUsage(1_000_000L) + .setEnergyFactor(150L) + .setUpdateCycle(1000L) + .build()); + + Assert.assertTrue(capsule.catchUpToCycle(1001L, 2_000_000L, 120, 200)); + Assert.assertEquals(1001L, capsule.getUpdateCycle()); + Assert.assertEquals(0L, capsule.getEnergyUsage()); + Assert.assertEquals(142L, capsule.getEnergyFactor()); + + capsule = new ContractCapsule( + SmartContractOuterClass.SmartContract.newBuilder() + .setEnergyUsage(1_000_000L) + .setEnergyFactor(150L) + .setUpdateCycle(1000L) + .build()); + + Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 120, 200)); + Assert.assertEquals(1001L, capsule.getUpdateCycle()); + Assert.assertEquals(0L, capsule.getEnergyUsage()); + Assert.assertEquals(180L, capsule.getEnergyFactor()); + + capsule = new ContractCapsule( + SmartContractOuterClass.SmartContract.newBuilder() + .setEnergyUsage(1_000_000L) + .setEnergyFactor(150L) + .setUpdateCycle(1000L) + .build()); + + Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 150, 200)); + Assert.assertEquals(1001L, capsule.getUpdateCycle()); + Assert.assertEquals(0L, capsule.getEnergyUsage()); + Assert.assertEquals(200L, capsule.getEnergyFactor()); + + capsule = new ContractCapsule( + SmartContractOuterClass.SmartContract.newBuilder() + .setEnergyUsage(1_000_000L) + .setEnergyFactor(150L) + .setUpdateCycle(1000L) + .build()); + + Assert.assertTrue(capsule.catchUpToCycle(1002L, 1_000_000L, 150, 200)); + Assert.assertEquals(1002L, capsule.getUpdateCycle()); + Assert.assertEquals(0L, capsule.getEnergyUsage()); + Assert.assertEquals(175L, capsule.getEnergyFactor()); + + capsule = new ContractCapsule( + SmartContractOuterClass.SmartContract.newBuilder() + .setEnergyUsage(1_000_000L) + .setEnergyFactor(150L) + .setUpdateCycle(1000L) + .build()); + + Assert.assertTrue(capsule.catchUpToCycle(1003L, 1_000_000L, 150, 200)); + Assert.assertEquals(1003L, capsule.getUpdateCycle()); + Assert.assertEquals(0L, capsule.getEnergyUsage()); + Assert.assertEquals(153L, capsule.getEnergyFactor()); + + capsule = new ContractCapsule( + SmartContractOuterClass.SmartContract.newBuilder() + .setEnergyUsage(1_000_000L) + .setEnergyFactor(150L) + .setUpdateCycle(1000L) + .build()); + + Assert.assertTrue(capsule.catchUpToCycle(1004L, 1_000_000L, 150, 200)); + Assert.assertEquals(1004L, capsule.getUpdateCycle()); + Assert.assertEquals(0L, capsule.getEnergyUsage()); + Assert.assertEquals(133L, capsule.getEnergyFactor()); + + capsule = new ContractCapsule( + SmartContractOuterClass.SmartContract.newBuilder() + .setEnergyUsage(1_000_000L) + .setEnergyFactor(150L) + .setUpdateCycle(1000L) + .build()); + + Assert.assertTrue(capsule.catchUpToCycle(1005L, 1_000_000L, 150, 200)); + Assert.assertEquals(1005L, capsule.getUpdateCycle()); + Assert.assertEquals(0L, capsule.getEnergyUsage()); + Assert.assertEquals(117L, capsule.getEnergyFactor()); + + capsule = new ContractCapsule( + SmartContractOuterClass.SmartContract.newBuilder() + .setEnergyUsage(1_000_000L) + .setEnergyFactor(150L) + .setUpdateCycle(1000L) + .build()); + + Assert.assertTrue(capsule.catchUpToCycle(1005L, 1_000_000L, 150, 200)); + Assert.assertEquals(1005L, capsule.getUpdateCycle()); + Assert.assertEquals(0L, capsule.getEnergyUsage()); + Assert.assertEquals(117L, capsule.getEnergyFactor()); + + capsule = new ContractCapsule( + SmartContractOuterClass.SmartContract.newBuilder() + .setEnergyUsage(1_000_000L) + .setEnergyFactor(150L) + .setUpdateCycle(1000L) + .build()); + + Assert.assertTrue(capsule.catchUpToCycle(1006L, 1_000_000L, 150, 200)); + Assert.assertEquals(1006L, capsule.getUpdateCycle()); + Assert.assertEquals(0L, capsule.getEnergyUsage()); + Assert.assertEquals(102L, capsule.getEnergyFactor()); + + capsule = new ContractCapsule( + SmartContractOuterClass.SmartContract.newBuilder() + .setEnergyUsage(1_000_000L) + .setEnergyFactor(150L) + .setUpdateCycle(1000L) + .build()); + + Assert.assertTrue(capsule.catchUpToCycle(1007L, 1_000_000L, 150, 200)); + Assert.assertEquals(1007L, capsule.getUpdateCycle()); + Assert.assertEquals(0L, capsule.getEnergyUsage()); + Assert.assertEquals(100L, capsule.getEnergyFactor()); + + } + +} From d22df333e8c62385a742c159f968445799dad1c8 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Wed, 21 Dec 2022 23:49:48 +0800 Subject: [PATCH 0484/1197] feat(DynamicEnergy): optimize ContractState storage --- .../org/tron/core/actuator/VMActuator.java | 25 ++-- .../src/main/java/org/tron/core/vm/VM.java | 36 ++--- .../tron/core/vm/program/ContractState.java | 15 ++ .../tron/core/vm/repository/Repository.java | 6 + .../core/vm/repository/RepositoryImpl.java | 53 +++++++ .../java/org/tron/core/ChainBaseManager.java | 5 + .../tron/core/capsule/ContractCapsule.java | 93 ------------- .../core/capsule/ContractStateCapsule.java | 131 ++++++++++++++++++ .../tron/core/store/ContractStateStore.java | 35 +++++ .../src/main/java/org/tron/core/Constant.java | 2 + ...est.java => ContractStateCapsuleTest.java} | 50 +++---- .../protos/core/contract/smart_contract.proto | 8 +- 12 files changed, 308 insertions(+), 151 deletions(-) create mode 100644 chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java create mode 100644 chainbase/src/main/java/org/tron/core/store/ContractStateStore.java rename framework/src/test/java/org/tron/core/capsule/{ContractCapsuleTest.java => ContractStateCapsuleTest.java} (80%) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index ac1b13a02b1..1b85bc7ede0 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -30,6 +30,7 @@ import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.ContractCapsule; +import org.tron.core.capsule.ContractStateCapsule; import org.tron.core.capsule.ReceiptCapsule; import org.tron.core.db.EnergyProcessor; import org.tron.core.db.TransactionContext; @@ -51,11 +52,8 @@ import org.tron.core.vm.program.ProgramPrecompile; import org.tron.core.vm.program.invoke.ProgramInvoke; import org.tron.core.vm.program.invoke.ProgramInvokeFactory; -import org.tron.core.vm.repository.Key; import org.tron.core.vm.repository.Repository; import org.tron.core.vm.repository.RepositoryImpl; -import org.tron.core.vm.repository.Type; -import org.tron.core.vm.repository.Value; import org.tron.core.vm.utils.MUtil; import org.tron.protos.Protocol; import org.tron.protos.Protocol.Block; @@ -183,27 +181,26 @@ public void execute(Object object) throws ContractExeException { if (rootRepository.getDynamicPropertiesStore().supportAllowDynamicEnergy()) { // only add trigger_energy_base when type is call. - if (this.trx.getRawData().getContract(0).getType() - == ContractType.TriggerSmartContract) { + if (TrxType.TRX_CONTRACT_CREATION_TYPE == trxType) { - ContractCapsule deployedContract = - rootRepository.getContract(program.getContextAddress()); - if (deployedContract != null) { + ContractStateCapsule contractStateCapsule = + rootRepository.getContractState(program.getContextAddress()); + if (contractStateCapsule != null) { - if (deployedContract.catchUpToCycle( + if (contractStateCapsule.catchUpToCycle( rootRepository.getDynamicPropertiesStore().getCurrentCycleNumber(), rootRepository.getDynamicPropertiesStore().getDynamicEnergyThreshold(), rootRepository.getDynamicPropertiesStore().getDynamicEnergyIncreaseFactor(), rootRepository.getDynamicPropertiesStore().getDynamicEnergyMaxFactor())) { - rootRepository.putContract( - Key.create(program.getContextAddress()), - Value.create(deployedContract, Type.DIRTY)); + rootRepository.updateContractState( + program.getContextAddress(), + contractStateCapsule); } - if (deployedContract.getEnergyFactor() > DYNAMIC_ENERGY_FACTOR_DECIMAL) { + if (contractStateCapsule.getEnergyFactor() > DYNAMIC_ENERGY_FACTOR_DECIMAL) { program.spendEnergy( rootRepository.getDynamicPropertiesStore().getDynamicEnergyTriggerBase() - * deployedContract.getEnergyFactor() / DYNAMIC_ENERGY_FACTOR_DECIMAL, + * contractStateCapsule.getEnergyFactor() / DYNAMIC_ENERGY_FACTOR_DECIMAL, "DYNAMIC_ENERGY_TRIGGER_BASE"); } } diff --git a/actuator/src/main/java/org/tron/core/vm/VM.java b/actuator/src/main/java/org/tron/core/vm/VM.java index 12f0841519b..21827b716cc 100644 --- a/actuator/src/main/java/org/tron/core/vm/VM.java +++ b/actuator/src/main/java/org/tron/core/vm/VM.java @@ -5,41 +5,39 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.springframework.util.StringUtils; -import org.tron.core.capsule.ContractCapsule; +import org.tron.core.capsule.ContractStateCapsule; import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.program.Program; import org.tron.core.vm.program.Program.JVMStackOverFlowException; import org.tron.core.vm.program.Program.OutOfTimeException; import org.tron.core.vm.program.Program.TransferException; -import org.tron.core.vm.repository.Key; -import org.tron.core.vm.repository.Type; -import org.tron.core.vm.repository.Value; @Slf4j(topic = "VM") public class VM { public static void play(Program program, JumpTable jumpTable) { try { - ContractCapsule contextContract = null; + ContractStateCapsule contextContractState = null; long factor = DYNAMIC_ENERGY_FACTOR_DECIMAL; + long energyUsage = 0L; boolean allowDynamicEnergy = program.getContractState().getDynamicPropertiesStore().supportAllowDynamicEnergy(); if (allowDynamicEnergy) { - contextContract = program.getContractState().getContract(program.getContextAddress()); + contextContractState = program.getContractState().getContractState(program.getContextAddress()); - if (contextContract.catchUpToCycle( + if (contextContractState.catchUpToCycle( program.getContractState().getDynamicPropertiesStore().getCurrentCycleNumber(), program.getContractState().getDynamicPropertiesStore().getDynamicEnergyThreshold(), program.getContractState().getDynamicPropertiesStore().getDynamicEnergyIncreaseFactor(), program.getContractState().getDynamicPropertiesStore().getDynamicEnergyMaxFactor())) { - program.getContractState().putContract( - Key.create(program.getContextAddress()), - Value.create(contextContract, Type.DIRTY)); + + program.getContractState().updateContractState( + program.getContextAddress(), contextContractState); } - factor = contextContract.getEnergyFactor(); + factor = contextContractState.getEnergyFactor(); } while (!program.isStopped()) { @@ -62,12 +60,9 @@ public static void play(Program program, JumpTable jumpTable) { /* spend energy before execution */ long energy = op.getEnergyCost(program); if (allowDynamicEnergy) { - contextContract.addEnergyUsage(energy); - program.getContractState().putContract( - Key.create(program.getContextAddress()), - Value.create(contextContract, Type.DIRTY)); + energyUsage += energy; - if (factor != DYNAMIC_ENERGY_FACTOR_DECIMAL) { + if (factor > DYNAMIC_ENERGY_FACTOR_DECIMAL) { energy = energy * factor / DYNAMIC_ENERGY_FACTOR_DECIMAL; } } @@ -92,6 +87,15 @@ public static void play(Program program, JumpTable jumpTable) { program.fullTrace(); } } + + if (allowDynamicEnergy) { + contextContractState = program.getContractState().getContractState(program.getContextAddress()); + contextContractState.addEnergyUsage(energyUsage); + program.getContractState().updateContractState( + program.getContextAddress(), + contextContractState); + } + } catch (JVMStackOverFlowException | OutOfTimeException e) { throw e; } catch (RuntimeException e) { diff --git a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java index 4cbccc58686..157f102168d 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java +++ b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java @@ -7,6 +7,7 @@ import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.BytesCapsule; import org.tron.core.capsule.ContractCapsule; +import org.tron.core.capsule.ContractStateCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.VotesCapsule; import org.tron.core.capsule.WitnessCapsule; @@ -104,11 +105,21 @@ public ContractCapsule getContract(byte[] codeHash) { return repository.getContract(codeHash); } + @Override + public ContractStateCapsule getContractState(byte[] address) { + return repository.getContractState(address); + } + @Override public void updateContract(byte[] address, ContractCapsule contractCapsule) { repository.updateContract(address, contractCapsule); } + @Override + public void updateContractState(byte[] address, ContractStateCapsule contractStateCapsule) { + repository.updateContractState(address, contractStateCapsule); + } + @Override public void updateAccount(byte[] address, AccountCapsule accountCapsule) { repository.updateAccount(address, accountCapsule); @@ -182,6 +193,10 @@ public void putContract(Key key, Value value) { repository.putContract(key, value); } + @Override + public void putContractState(Key key, Value value) { + repository.putContractState(key, value); + } public void putStorage(Key key, Storage cache) { repository.putStorage(key, cache); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java index c5b92a63ba8..39c8506d781 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java @@ -45,8 +45,12 @@ public interface Repository { ContractCapsule getContract(byte[] address); + ContractStateCapsule getContractState(byte[] address); + void updateContract(byte[] address, ContractCapsule contractCapsule); + void updateContractState(byte[] address, ContractStateCapsule contractStateCapsule); + void updateAccount(byte[] address, AccountCapsule accountCapsule); void updateDynamicProperty(byte[] word, BytesCapsule bytesCapsule); @@ -89,6 +93,8 @@ public interface Repository { void putContract(Key key, Value value); + void putContractState(Key key, Value value); + void putStorage(Key key, Storage cache); void putAccountValue(byte[] address, AccountCapsule accountCapsule); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index bf758c9fd44..ac884d9d0e5 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -30,6 +30,7 @@ import org.tron.core.capsule.BytesCapsule; import org.tron.core.capsule.CodeCapsule; import org.tron.core.capsule.ContractCapsule; +import org.tron.core.capsule.ContractStateCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.VotesCapsule; import org.tron.core.capsule.WitnessCapsule; @@ -46,6 +47,7 @@ import org.tron.core.store.AssetIssueStore; import org.tron.core.store.AssetIssueV2Store; import org.tron.core.store.CodeStore; +import org.tron.core.store.ContractStateStore; import org.tron.core.store.ContractStore; import org.tron.core.store.DelegatedResourceStore; import org.tron.core.store.DelegationStore; @@ -64,6 +66,7 @@ import org.tron.protos.Protocol.Votes; import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; import org.tron.protos.contract.Common; +import org.tron.protos.contract.SmartContractOuterClass.ContractState; import org.tron.protos.contract.SmartContractOuterClass.SmartContract; @Slf4j(topic = "Repository") @@ -90,6 +93,8 @@ public class RepositoryImpl implements Repository { @Getter private ContractStore contractStore; @Getter + private ContractStateStore contractStateStore; + @Getter private StorageRowStore storageRowStore; @Getter private BlockStore blockStore; @@ -111,6 +116,8 @@ public class RepositoryImpl implements Repository { private final HashMap> accountCache = new HashMap<>(); private final HashMap> codeCache = new HashMap<>(); private final HashMap> contractCache = new HashMap<>(); + private final HashMap> contractStateCache + = new HashMap<>(); private final HashMap storageCache = new HashMap<>(); private final HashMap> assetIssueCache = new HashMap<>(); @@ -139,6 +146,7 @@ protected void init(StoreFactory storeFactory, RepositoryImpl parent) { abiStore = manager.getAbiStore(); codeStore = manager.getCodeStore(); contractStore = manager.getContractStore(); + contractStateStore = manager.getContractStateStore(); assetIssueStore = manager.getAssetIssueStore(); assetIssueV2Store = manager.getAssetIssueV2Store(); storageRowStore = manager.getStorageRowStore(); @@ -439,12 +447,38 @@ public ContractCapsule getContract(byte[] address) { return contractCapsule; } + @Override + public ContractStateCapsule getContractState(byte[] address) { + Key key = Key.create(address); + if (contractStateCache.containsKey(key)) { + return new ContractStateCapsule(contractStateCache.get(key).getValue()); + } + + ContractStateCapsule contractStateCapsule; + if (parent != null) { + contractStateCapsule = parent.getContractState(address); + } else { + contractStateCapsule = getContractStateStore().get(address); + } + + if (contractStateCapsule != null) { + contractStateCache.put(key, Value.create(contractStateCapsule)); + } + return contractStateCapsule; + } + @Override public void updateContract(byte[] address, ContractCapsule contractCapsule) { contractCache.put(Key.create(address), Value.create(contractCapsule, Type.DIRTY)); } + @Override + public void updateContractState(byte[] address, ContractStateCapsule contractStateCapsule) { + contractStateCache.put(Key.create(address), + Value.create(contractStateCapsule, Type.DIRTY)); + } + @Override public void updateAccount(byte[] address, AccountCapsule accountCapsule) { accountCache.put(Key.create(address), @@ -632,6 +666,7 @@ public void commit() { commitAccountCache(repository); commitCodeCache(repository); commitContractCache(repository); + commitContractStateCache(repository); commitStorageCache(repository); commitDynamicCache(repository); commitDelegatedResourceCache(repository); @@ -654,6 +689,11 @@ public void putContract(Key key, Value value) { contractCache.put(key, value); } + @Override + public void putContractState(Key key, Value value) { + contractStateCache.put(key, value); + } + @Override public void putStorage(Key key, Storage cache) { storageCache.put(key, cache); @@ -840,6 +880,19 @@ private void commitContractCache(Repository deposit) { })); } + private void commitContractStateCache(Repository deposit) { + contractStateCache.forEach(((key, value) -> { + if (value.getType().isDirty() || value.getType().isCreate()) { + if (deposit != null) { + deposit.putContractState(key, value); + } else { + ContractStateCapsule contractStateCapsule = new ContractStateCapsule(value.getValue()); + getContractStateStore().put(key.getData(), contractStateCapsule); + } + } + })); + } + private void commitStorageCache(Repository deposit) { storageCache.forEach((Key address, Storage storage) -> { if (deposit != null) { diff --git a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java index a2f3cd67b8e..d824d36734f 100644 --- a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java +++ b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java @@ -43,6 +43,7 @@ import org.tron.core.store.AssetIssueV2Store; import org.tron.core.store.BalanceTraceStore; import org.tron.core.store.CodeStore; +import org.tron.core.store.ContractStateStore; import org.tron.core.store.ContractStore; import org.tron.core.store.DelegatedResourceAccountIndexStore; import org.tron.core.store.DelegatedResourceStore; @@ -143,6 +144,9 @@ public class ChainBaseManager { private ContractStore contractStore; @Autowired @Getter + private ContractStateStore contractStateStore; + @Autowired + @Getter private DelegatedResourceStore delegatedResourceStore; @Autowired @Getter @@ -260,6 +264,7 @@ public void closeAllStore() { closeOneStore(abiStore); closeOneStore(codeStore); closeOneStore(contractStore); + closeOneStore(contractStateStore); closeOneStore(storageRowStore); closeOneStore(exchangeStore); closeOneStore(proposalStore); diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java index 6e6fda3191f..cb6292ed290 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java @@ -17,7 +17,6 @@ import static java.lang.Math.max; import static java.lang.Math.min; -import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; import com.google.protobuf.Any; import com.google.protobuf.ByteString; @@ -135,96 +134,4 @@ public int getContractVersion() { return this.smartContract.getVersion(); } - public long getEnergyUsage() { - return this.smartContract.getEnergyUsage(); - } - - public void setEnergyUsage(long value) { - this.smartContract = this.smartContract.toBuilder().setEnergyUsage(value).build(); - } - - public void addEnergyUsage(long toAdd) { - setEnergyUsage(getEnergyUsage() + toAdd); - } - - public long getEnergyFactor() { - return this.smartContract.getEnergyFactor(); - } - - public void setEnergyFactor(long value) { - this.smartContract = this.smartContract.toBuilder().setEnergyFactor(value).build(); - } - - public long getUpdateCycle() { - return this.smartContract.getUpdateCycle(); - } - - public void setUpdateCycle(long value) { - this.smartContract = this.smartContract.toBuilder().setUpdateCycle(value).build(); - } - - public void addUpdateCycle(long toAdd) { - setUpdateCycle(getUpdateCycle() + toAdd); - } - - public boolean catchUpToCycle(long newCycle, long threshold, long increaseFactor, long maxFactor) { - long lastCycle = getUpdateCycle(); - if (lastCycle >= newCycle) { - return false; - } - - if (lastCycle == 0L || newCycle - lastCycle >= 10) { - this.smartContract = this.smartContract.toBuilder() - .setUpdateCycle(newCycle) - .setEnergyUsage(0L) - .setEnergyFactor(DYNAMIC_ENERGY_FACTOR_DECIMAL) - .build(); - return true; - } - - // increase first - if (getEnergyUsage() >= threshold) { - lastCycle += 1; - this.smartContract = this.smartContract.toBuilder() - .setUpdateCycle(lastCycle) - .setEnergyUsage(0L) - .setEnergyFactor(Math.min( - maxFactor, - getEnergyFactor() * increaseFactor / DYNAMIC_ENERGY_FACTOR_DECIMAL)) - .build(); - } - - // decrease - long cycleCount = newCycle - lastCycle; - if (cycleCount <= 0) { - return true; - } - - // no need to decrease - if (getEnergyFactor() <= DYNAMIC_ENERGY_FACTOR_DECIMAL) { - this.smartContract = this.smartContract.toBuilder() - .setUpdateCycle(newCycle) - .setEnergyUsage(0L) - .setEnergyFactor(DYNAMIC_ENERGY_FACTOR_DECIMAL) - .build(); - return true; - } - - double decreaseFactor = 1 - ((double) increaseFactor / DYNAMIC_ENERGY_FACTOR_DECIMAL - 1) / 4; - if (cycleCount > 1) { - decreaseFactor = Math.pow( - decreaseFactor, - cycleCount); - } - - this.smartContract = this.smartContract.toBuilder() - .setUpdateCycle(newCycle) - .setEnergyUsage(0L) - .setEnergyFactor(Math.max( - DYNAMIC_ENERGY_FACTOR_DECIMAL, - (long) (getEnergyFactor() * decreaseFactor))) - .build(); - - return true; - } } diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java new file mode 100644 index 00000000000..7c7f212d79d --- /dev/null +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java @@ -0,0 +1,131 @@ +package org.tron.core.capsule; + +import static org.tron.core.Constant.DYNAMIC_ENERGY_DECREASE_DIVISION; +import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; + +import com.google.protobuf.InvalidProtocolBufferException; +import lombok.extern.slf4j.Slf4j; +import org.tron.protos.contract.SmartContractOuterClass; +import org.tron.protos.contract.SmartContractOuterClass.ContractState; + +@Slf4j(topic = "capsule") +public class ContractStateCapsule implements ProtoCapsule { + + private ContractState contractState; + + public ContractStateCapsule(ContractState contractState) { + this.contractState = contractState; + } + + public ContractStateCapsule(byte[] data) { + try { + this.contractState = SmartContractOuterClass.ContractState.parseFrom(data); + } catch (InvalidProtocolBufferException e) { + // logger.debug(e.getMessage()); + } + } + + @Override + public byte[] getData() { + return this.contractState.toByteArray(); + } + + @Override + public ContractState getInstance() { + return this.contractState; + } + + public long getEnergyUsage() { + return this.contractState.getEnergyUsage(); + } + + public void setEnergyUsage(long value) { + this.contractState = this.contractState.toBuilder().setEnergyUsage(value).build(); + } + + public void addEnergyUsage(long toAdd) { + setEnergyUsage(getEnergyUsage() + toAdd); + } + + public long getEnergyFactor() { + return this.contractState.getEnergyFactor(); + } + + public void setEnergyFactor(long value) { + this.contractState = this.contractState.toBuilder().setEnergyFactor(value).build(); + } + + public long getUpdateCycle() { + return this.contractState.getUpdateCycle(); + } + + public void setUpdateCycle(long value) { + this.contractState = this.contractState.toBuilder().setUpdateCycle(value).build(); + } + + public void addUpdateCycle(long toAdd) { + setUpdateCycle(getUpdateCycle() + toAdd); + } + + public boolean catchUpToCycle(long newCycle, long threshold, long increaseFactor, long maxFactor) { + long lastCycle = getUpdateCycle(); + if (lastCycle == newCycle) { + return false; + } + + if (lastCycle > newCycle || lastCycle == 0L || newCycle - lastCycle >= 10) { + this.contractState = this.contractState.toBuilder() + .setUpdateCycle(newCycle) + .setEnergyUsage(0L) + .setEnergyFactor(DYNAMIC_ENERGY_FACTOR_DECIMAL) + .build(); + return true; + } + + // increase first + if (getEnergyUsage() >= threshold) { + lastCycle += 1; + this.contractState = this.contractState.toBuilder() + .setUpdateCycle(lastCycle) + .setEnergyUsage(0L) + .setEnergyFactor(Math.min( + maxFactor, + getEnergyFactor() * increaseFactor / DYNAMIC_ENERGY_FACTOR_DECIMAL)) + .build(); + } + + // decrease + long cycleCount = newCycle - lastCycle; + if (cycleCount <= 0) { + return true; + } + + // no need to decrease + if (getEnergyFactor() <= DYNAMIC_ENERGY_FACTOR_DECIMAL) { + this.contractState = this.contractState.toBuilder() + .setUpdateCycle(newCycle) + .setEnergyUsage(0L) + .setEnergyFactor(DYNAMIC_ENERGY_FACTOR_DECIMAL) + .build(); + return true; + } + + double decreaseFactor = 1 - ((double) increaseFactor / DYNAMIC_ENERGY_FACTOR_DECIMAL - 1) + / DYNAMIC_ENERGY_DECREASE_DIVISION; + if (cycleCount > 1) { + decreaseFactor = Math.pow( + decreaseFactor, + cycleCount); + } + + this.contractState = this.contractState.toBuilder() + .setUpdateCycle(newCycle) + .setEnergyUsage(0L) + .setEnergyFactor(Math.max( + DYNAMIC_ENERGY_FACTOR_DECIMAL, + (long) (getEnergyFactor() * decreaseFactor))) + .build(); + + return true; + } +} diff --git a/chainbase/src/main/java/org/tron/core/store/ContractStateStore.java b/chainbase/src/main/java/org/tron/core/store/ContractStateStore.java new file mode 100644 index 00000000000..99fcad02cbf --- /dev/null +++ b/chainbase/src/main/java/org/tron/core/store/ContractStateStore.java @@ -0,0 +1,35 @@ +package org.tron.core.store; + +import java.util.Objects; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.tron.core.capsule.ContractStateCapsule; +import org.tron.core.db.TronStoreWithRevoking; + +@Slf4j(topic = "DB") +@Component +public class ContractStateStore extends TronStoreWithRevoking { + + @Autowired + private ContractStateStore(@Value("contractState") String dbName) { + super(dbName); + } + + @Override + public ContractStateCapsule get(byte[] key) { + return getUnchecked(key); + } + + @Override + public void put(byte[] key, ContractStateCapsule item) { + if (Objects.isNull(key) || Objects.isNull(item)) { + return; + } + + revokingDB.put(key, item.getData()); + } + +} diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 469794d2a43..2cb04da963f 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -325,6 +325,8 @@ public class Constant { public static final long DYNAMIC_ENERGY_FACTOR_DECIMAL = 100L; + public static final int DYNAMIC_ENERGY_DECREASE_DIVISION = 4; + public static final String DYNAMIC_ENERGY_TRIGGER_BASE = "committee.dynamicEnergyTriggerBase"; public static final String LOCAL_HOST = "127.0.0.1"; diff --git a/framework/src/test/java/org/tron/core/capsule/ContractCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java similarity index 80% rename from framework/src/test/java/org/tron/core/capsule/ContractCapsuleTest.java rename to framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java index b009d9dcffe..f4fb616878f 100644 --- a/framework/src/test/java/org/tron/core/capsule/ContractCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java @@ -4,12 +4,12 @@ import org.junit.Test; import org.tron.protos.contract.SmartContractOuterClass; -public class ContractCapsuleTest { +public class ContractStateCapsuleTest { @Test public void testCatchUpCycle() { - ContractCapsule capsule = new ContractCapsule( - SmartContractOuterClass.SmartContract.newBuilder() + ContractStateCapsule capsule = new ContractStateCapsule( + SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) .setEnergyFactor(150L) .setUpdateCycle(1000L) @@ -25,8 +25,8 @@ public void testCatchUpCycle() { Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(100L, capsule.getEnergyFactor()); - capsule = new ContractCapsule( - SmartContractOuterClass.SmartContract.newBuilder() + capsule = new ContractStateCapsule( + SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) .setEnergyFactor(150L) .setUpdateCycle(1000L) @@ -37,8 +37,8 @@ public void testCatchUpCycle() { Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(134L, capsule.getEnergyFactor()); - capsule = new ContractCapsule( - SmartContractOuterClass.SmartContract.newBuilder() + capsule = new ContractStateCapsule( + SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) .setEnergyFactor(150L) .setUpdateCycle(1000L) @@ -49,8 +49,8 @@ public void testCatchUpCycle() { Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(142L, capsule.getEnergyFactor()); - capsule = new ContractCapsule( - SmartContractOuterClass.SmartContract.newBuilder() + capsule = new ContractStateCapsule( + SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) .setEnergyFactor(150L) .setUpdateCycle(1000L) @@ -61,8 +61,8 @@ public void testCatchUpCycle() { Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(180L, capsule.getEnergyFactor()); - capsule = new ContractCapsule( - SmartContractOuterClass.SmartContract.newBuilder() + capsule = new ContractStateCapsule( + SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) .setEnergyFactor(150L) .setUpdateCycle(1000L) @@ -73,8 +73,8 @@ public void testCatchUpCycle() { Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(200L, capsule.getEnergyFactor()); - capsule = new ContractCapsule( - SmartContractOuterClass.SmartContract.newBuilder() + capsule = new ContractStateCapsule( + SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) .setEnergyFactor(150L) .setUpdateCycle(1000L) @@ -85,8 +85,8 @@ public void testCatchUpCycle() { Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(175L, capsule.getEnergyFactor()); - capsule = new ContractCapsule( - SmartContractOuterClass.SmartContract.newBuilder() + capsule = new ContractStateCapsule( + SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) .setEnergyFactor(150L) .setUpdateCycle(1000L) @@ -97,8 +97,8 @@ public void testCatchUpCycle() { Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(153L, capsule.getEnergyFactor()); - capsule = new ContractCapsule( - SmartContractOuterClass.SmartContract.newBuilder() + capsule = new ContractStateCapsule( + SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) .setEnergyFactor(150L) .setUpdateCycle(1000L) @@ -109,8 +109,8 @@ public void testCatchUpCycle() { Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(133L, capsule.getEnergyFactor()); - capsule = new ContractCapsule( - SmartContractOuterClass.SmartContract.newBuilder() + capsule = new ContractStateCapsule( + SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) .setEnergyFactor(150L) .setUpdateCycle(1000L) @@ -121,8 +121,8 @@ public void testCatchUpCycle() { Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(117L, capsule.getEnergyFactor()); - capsule = new ContractCapsule( - SmartContractOuterClass.SmartContract.newBuilder() + capsule = new ContractStateCapsule( + SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) .setEnergyFactor(150L) .setUpdateCycle(1000L) @@ -133,8 +133,8 @@ public void testCatchUpCycle() { Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(117L, capsule.getEnergyFactor()); - capsule = new ContractCapsule( - SmartContractOuterClass.SmartContract.newBuilder() + capsule = new ContractStateCapsule( + SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) .setEnergyFactor(150L) .setUpdateCycle(1000L) @@ -145,8 +145,8 @@ public void testCatchUpCycle() { Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(102L, capsule.getEnergyFactor()); - capsule = new ContractCapsule( - SmartContractOuterClass.SmartContract.newBuilder() + capsule = new ContractStateCapsule( + SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) .setEnergyFactor(150L) .setUpdateCycle(1000L) diff --git a/protocol/src/main/protos/core/contract/smart_contract.proto b/protocol/src/main/protos/core/contract/smart_contract.proto index a6fba7b696a..c127b2f0e70 100644 --- a/protocol/src/main/protos/core/contract/smart_contract.proto +++ b/protocol/src/main/protos/core/contract/smart_contract.proto @@ -56,10 +56,12 @@ message SmartContract { bytes code_hash = 9; bytes trx_hash = 10; int32 version = 11; +} - int64 energy_usage = 12; - int64 energy_factor = 13; - int64 update_cycle = 14; +message ContractState { + int64 energy_usage = 1; + int64 energy_factor = 2; + int64 update_cycle = 3; } message CreateSmartContract { From 6a43e1027dd64dddc75f007510d9f370fa2b48a4 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Thu, 22 Dec 2022 11:56:37 +0800 Subject: [PATCH 0485/1197] feat(DynamicEnergy): optimize Program contextContractState update and proposal parameter range --- .../org/tron/core/actuator/VMActuator.java | 27 +++------- .../org/tron/core/utils/ProposalUtil.java | 51 ++++++++++++++++--- .../src/main/java/org/tron/core/vm/VM.java | 22 +------- .../org/tron/core/vm/program/Program.java | 46 +++++++++++++++++ .../core/capsule/ContractStateCapsule.java | 11 ++-- .../common/parameter/CommonParameter.java | 6 ++- .../src/main/java/org/tron/core/Constant.java | 4 ++ .../java/org/tron/core/config/args/Args.java | 5 +- 8 files changed, 115 insertions(+), 57 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 1b85bc7ede0..7cca3acab3a 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -182,27 +182,12 @@ public void execute(Object object) throws ContractExeException { if (rootRepository.getDynamicPropertiesStore().supportAllowDynamicEnergy()) { // only add trigger_energy_base when type is call. if (TrxType.TRX_CONTRACT_CREATION_TYPE == trxType) { - - ContractStateCapsule contractStateCapsule = - rootRepository.getContractState(program.getContextAddress()); - if (contractStateCapsule != null) { - - if (contractStateCapsule.catchUpToCycle( - rootRepository.getDynamicPropertiesStore().getCurrentCycleNumber(), - rootRepository.getDynamicPropertiesStore().getDynamicEnergyThreshold(), - rootRepository.getDynamicPropertiesStore().getDynamicEnergyIncreaseFactor(), - rootRepository.getDynamicPropertiesStore().getDynamicEnergyMaxFactor())) { - rootRepository.updateContractState( - program.getContextAddress(), - contractStateCapsule); - } - - if (contractStateCapsule.getEnergyFactor() > DYNAMIC_ENERGY_FACTOR_DECIMAL) { - program.spendEnergy( - rootRepository.getDynamicPropertiesStore().getDynamicEnergyTriggerBase() - * contractStateCapsule.getEnergyFactor() / DYNAMIC_ENERGY_FACTOR_DECIMAL, - "DYNAMIC_ENERGY_TRIGGER_BASE"); - } + long energyFactor = program.updateContextContractCycle(); + if (energyFactor > DYNAMIC_ENERGY_FACTOR_DECIMAL) { + program.spendEnergy( + rootRepository.getDynamicPropertiesStore().getDynamicEnergyTriggerBase() + * energyFactor / DYNAMIC_ENERGY_FACTOR_DECIMAL, + "DYNAMIC_ENERGY_TRIGGER_BASE"); } } } diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 35635510227..efb78cac015 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -6,6 +6,9 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.store.DynamicPropertiesStore; +import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; +import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_RANGE; + public class ProposalUtil { protected static final long LONG_VALUE = 100_000_000_000_000_000L; @@ -623,7 +626,7 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, case ALLOW_DYNAMIC_ENERGY: { if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7)) { throw new ContractValidateException( - "Bad chain parameter id [UNFREEZE_DELAY_DAYS]"); + "Bad chain parameter id [ALLOW_DYNAMIC_ENERGY]"); } if (value < 0 || value > 1) { throw new ContractValidateException( @@ -632,9 +635,43 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } - case DYNAMIC_ENERGY_THRESHOLD: - case DYNAMIC_ENERGY_INCREASE_FACTOR: - case DYNAMIC_ENERGY_MAX_FACTOR: + case DYNAMIC_ENERGY_THRESHOLD: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7)) { + throw new ContractValidateException( + "Bad chain parameter id [DYNAMIC_ENERGY_THRESHOLD]"); + } + + if (value < 0 || value > LONG_VALUE) { + throw new ContractValidateException(LONG_VALUE_ERROR); + } + break; + } + case DYNAMIC_ENERGY_INCREASE_FACTOR: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7)) { + throw new ContractValidateException( + "Bad chain parameter id [DYNAMIC_ENERGY_INCREASE_FACTOR]"); + } + + if (value < DYNAMIC_ENERGY_FACTOR_DECIMAL || value > DYNAMIC_ENERGY_FACTOR_RANGE) { + throw new ContractValidateException( + "This value[DYNAMIC_ENERGY_INCREASE_FACTOR] is only allowed to be in the range 100-10000" + ); + } + break; + } + case DYNAMIC_ENERGY_MAX_FACTOR: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7)) { + throw new ContractValidateException( + "Bad chain parameter id [DYNAMIC_ENERGY_MAX_FACTOR]"); + } + + if (value < DYNAMIC_ENERGY_FACTOR_DECIMAL || value > DYNAMIC_ENERGY_FACTOR_RANGE) { + throw new ContractValidateException( + "This value[DYNAMIC_ENERGY_MAX_FACTOR] is only allowed to be in the range 100-10000" + ); + } + break; + } case DYNAMIC_ENERGY_TRIGGER_BASE: { if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7)) { throw new ContractValidateException( @@ -717,9 +754,9 @@ public enum ProposalType { // current value, value range ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID(71), // 0, 1 ALLOW_DYNAMIC_ENERGY(72), // 0, 1 DYNAMIC_ENERGY_THRESHOLD(73), // 0, [0, LONG] - DYNAMIC_ENERGY_INCREASE_FACTOR(74), // 0, [0, 1_000_000_000_000] - DYNAMIC_ENERGY_MAX_FACTOR(75), // 0, [0, 1_000_000_000_000] - DYNAMIC_ENERGY_TRIGGER_BASE(76); // 0, [0, 100_000_000] + DYNAMIC_ENERGY_INCREASE_FACTOR(74), // 0, [100, 10_000] + DYNAMIC_ENERGY_MAX_FACTOR(75), // 0, [100, 10_000] + DYNAMIC_ENERGY_TRIGGER_BASE(76); // 0, [0, LONG] private long code; diff --git a/actuator/src/main/java/org/tron/core/vm/VM.java b/actuator/src/main/java/org/tron/core/vm/VM.java index 21827b716cc..50b3f428f63 100644 --- a/actuator/src/main/java/org/tron/core/vm/VM.java +++ b/actuator/src/main/java/org/tron/core/vm/VM.java @@ -5,7 +5,6 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.springframework.util.StringUtils; -import org.tron.core.capsule.ContractStateCapsule; import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.program.Program; import org.tron.core.vm.program.Program.JVMStackOverFlowException; @@ -17,7 +16,6 @@ public class VM { public static void play(Program program, JumpTable jumpTable) { try { - ContractStateCapsule contextContractState = null; long factor = DYNAMIC_ENERGY_FACTOR_DECIMAL; long energyUsage = 0L; @@ -25,19 +23,7 @@ public static void play(Program program, JumpTable jumpTable) { program.getContractState().getDynamicPropertiesStore().supportAllowDynamicEnergy(); if (allowDynamicEnergy) { - contextContractState = program.getContractState().getContractState(program.getContextAddress()); - - if (contextContractState.catchUpToCycle( - program.getContractState().getDynamicPropertiesStore().getCurrentCycleNumber(), - program.getContractState().getDynamicPropertiesStore().getDynamicEnergyThreshold(), - program.getContractState().getDynamicPropertiesStore().getDynamicEnergyIncreaseFactor(), - program.getContractState().getDynamicPropertiesStore().getDynamicEnergyMaxFactor())) { - - program.getContractState().updateContractState( - program.getContextAddress(), contextContractState); - } - - factor = contextContractState.getEnergyFactor(); + factor = program.updateContextContractCycle(); } while (!program.isStopped()) { @@ -89,11 +75,7 @@ public static void play(Program program, JumpTable jumpTable) { } if (allowDynamicEnergy) { - contextContractState = program.getContractState().getContractState(program.getContextAddress()); - contextContractState.addEnergyUsage(energyUsage); - program.getContractState().updateContractState( - program.getContextAddress(), - contextContractState); + program.addContextContractUsage(energyUsage); } } catch (JVMStackOverFlowException | OutOfTimeException e) { diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index d90dbf197c0..c0f9ace1d5b 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -8,6 +8,7 @@ import static org.apache.commons.lang3.ArrayUtils.isNotEmpty; import static org.apache.commons.lang3.ArrayUtils.nullToEmpty; import static org.tron.common.utils.ByteUtil.stripLeadingZeroes; +import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import com.google.protobuf.ByteString; @@ -37,6 +38,7 @@ import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.ContractCapsule; +import org.tron.core.capsule.ContractStateCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.VotesCapsule; import org.tron.core.capsule.WitnessCapsule; @@ -89,6 +91,7 @@ import org.tron.protos.Protocol; import org.tron.protos.Protocol.AccountType; import org.tron.protos.contract.Common; +import org.tron.protos.contract.SmartContractOuterClass; import org.tron.protos.contract.SmartContractOuterClass.SmartContract; import org.tron.protos.contract.SmartContractOuterClass.SmartContract.Builder; @@ -2201,6 +2204,49 @@ public long withdrawReward() { return 0; } + public long updateContextContractCycle() { + ContractStateCapsule contractStateCapsule = + contractState.getContractState(getContextAddress()); + + if (contractStateCapsule == null) { + contractStateCapsule = new ContractStateCapsule( + SmartContractOuterClass.ContractState.newBuilder() + .setUpdateCycle(contractState.getDynamicPropertiesStore().getCurrentCycleNumber()) + .setEnergyUsage(0L) + .setEnergyFactor(DYNAMIC_ENERGY_FACTOR_DECIMAL) + .build()); + contractState.updateContractState(getContextAddress(), contractStateCapsule); + } else { + if (contractStateCapsule.catchUpToCycle( + contractState.getDynamicPropertiesStore().getCurrentCycleNumber(), + contractState.getDynamicPropertiesStore().getDynamicEnergyThreshold(), + contractState.getDynamicPropertiesStore().getDynamicEnergyIncreaseFactor(), + contractState.getDynamicPropertiesStore().getDynamicEnergyMaxFactor())) { + contractState.updateContractState( + getContextAddress(), + contractStateCapsule); + } + } + return contractStateCapsule.getEnergyFactor(); + } + + public void addContextContractUsage(long value) { + ContractStateCapsule contractStateCapsule = + contractState.getContractState(getContextAddress()); + + if (contractStateCapsule == null) { + contractStateCapsule = new ContractStateCapsule( + SmartContractOuterClass.ContractState.newBuilder() + .setUpdateCycle(contractState.getDynamicPropertiesStore().getCurrentCycleNumber()) + .setEnergyUsage(0L) + .setEnergyFactor(DYNAMIC_ENERGY_FACTOR_DECIMAL) + .build()); + } + + contractStateCapsule.addEnergyUsage(value); + contractState.updateContractState(getContextAddress(), contractStateCapsule); + } + /** * Denotes problem when executing Ethereum bytecode. From blockchain and peer perspective this is * quite normal situation and doesn't mean exceptional situation in terms of the program diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java index 7c7f212d79d..3737b8873e9 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java @@ -1,13 +1,12 @@ package org.tron.core.capsule; -import static org.tron.core.Constant.DYNAMIC_ENERGY_DECREASE_DIVISION; -import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; - import com.google.protobuf.InvalidProtocolBufferException; import lombok.extern.slf4j.Slf4j; import org.tron.protos.contract.SmartContractOuterClass; import org.tron.protos.contract.SmartContractOuterClass.ContractState; +import static org.tron.core.Constant.*; + @Slf4j(topic = "capsule") public class ContractStateCapsule implements ProtoCapsule { @@ -67,13 +66,15 @@ public void addUpdateCycle(long toAdd) { setUpdateCycle(getUpdateCycle() + toAdd); } - public boolean catchUpToCycle(long newCycle, long threshold, long increaseFactor, long maxFactor) { + public boolean catchUpToCycle( + long newCycle, long threshold, long increaseFactor, long maxFactor) { long lastCycle = getUpdateCycle(); if (lastCycle == newCycle) { return false; } - if (lastCycle > newCycle || lastCycle == 0L || newCycle - lastCycle >= 10) { + if (lastCycle > newCycle || lastCycle == 0L + || newCycle - lastCycle >= DYNAMIC_ENERGY_DECREASE_MAX_CYCLE) { this.contractState = this.contractState.toBuilder() .setUpdateCycle(newCycle) .setEnergyUsage(0L) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 6476e9d5634..8a4cacdc21b 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -19,6 +19,8 @@ import org.tron.core.config.args.SeedNode; import org.tron.core.config.args.Storage; +import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; + public class CommonParameter { public static final String IGNORE_WRONG_WITNESS_ADDRESS_FORMAT = @@ -590,11 +592,11 @@ public class CommonParameter { @Getter @Setter - public long dynamicEnergyIncreaseFactor = 0L; + public long dynamicEnergyIncreaseFactor = DYNAMIC_ENERGY_FACTOR_DECIMAL; @Getter @Setter - public long dynamicEnergyMaxFactor = 0L; + public long dynamicEnergyMaxFactor = DYNAMIC_ENERGY_FACTOR_DECIMAL; @Getter @Setter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 2cb04da963f..65625876094 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -325,8 +325,12 @@ public class Constant { public static final long DYNAMIC_ENERGY_FACTOR_DECIMAL = 100L; + public static final long DYNAMIC_ENERGY_FACTOR_RANGE = 10_000L; + public static final int DYNAMIC_ENERGY_DECREASE_DIVISION = 4; + public static final int DYNAMIC_ENERGY_DECREASE_MAX_CYCLE = 10; + public static final String DYNAMIC_ENERGY_TRIGGER_BASE = "committee.dynamicEnergyTriggerBase"; public static final String LOCAL_HOST = "127.0.0.1"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index bc170edd817..cd038fb9024 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -3,6 +3,7 @@ import static java.lang.Math.max; import static java.lang.System.exit; import static org.tron.core.Constant.ADD_PRE_FIX_BYTE_MAINNET; +import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_RANGE; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCE_TIMEOUT_PERCENT; import static org.tron.core.config.Parameter.ChainConstant.MAX_ACTIVE_WITNESS_NUM; @@ -1091,7 +1092,7 @@ public static void setParam(final String[] args, final String confFileName) { if (config.hasPath(Constant.DYNAMIC_ENERGY_INCREASE_FACTOR)) { PARAMETER.dynamicEnergyIncreaseFactor = config.getLong(Constant.DYNAMIC_ENERGY_INCREASE_FACTOR); PARAMETER.dynamicEnergyIncreaseFactor = - Math.min(PARAMETER.dynamicEnergyIncreaseFactor, 100_000_000_000_000_000L); + Math.min(PARAMETER.dynamicEnergyIncreaseFactor, DYNAMIC_ENERGY_FACTOR_RANGE); PARAMETER.dynamicEnergyIncreaseFactor = Math.max(PARAMETER.dynamicEnergyIncreaseFactor, 0); } @@ -1099,7 +1100,7 @@ public static void setParam(final String[] args, final String confFileName) { if (config.hasPath(Constant.DYNAMIC_ENERGY_MAX_FACTOR)) { PARAMETER.dynamicEnergyMaxFactor = config.getLong(Constant.DYNAMIC_ENERGY_MAX_FACTOR); PARAMETER.dynamicEnergyMaxFactor = - Math.min(PARAMETER.dynamicEnergyMaxFactor, 100_000_000_000_000_000L); + Math.min(PARAMETER.dynamicEnergyMaxFactor, DYNAMIC_ENERGY_FACTOR_RANGE); PARAMETER.dynamicEnergyMaxFactor = Math.max(PARAMETER.dynamicEnergyMaxFactor, 0); } From 5a0696eba4babfbf8ff94d5543f1283c2d7356ea Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Thu, 22 Dec 2022 16:15:14 +0800 Subject: [PATCH 0486/1197] feat(DynamicEnergy): optimize proposal parameters and energy calculation --- .../java/org/tron/core/actuator/VMActuator.java | 3 +-- .../java/org/tron/core/utils/ProposalUtil.java | 5 +++-- actuator/src/main/java/org/tron/core/vm/VM.java | 16 +++++++++++++--- .../java/org/tron/core/vm/program/Program.java | 2 +- .../tron/core/capsule/ContractStateCapsule.java | 6 ++++-- common/src/main/java/org/tron/core/Constant.java | 2 ++ 6 files changed, 24 insertions(+), 10 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 7cca3acab3a..03b6f57a366 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -30,7 +30,6 @@ import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.ContractCapsule; -import org.tron.core.capsule.ContractStateCapsule; import org.tron.core.capsule.ReceiptCapsule; import org.tron.core.db.EnergyProcessor; import org.tron.core.db.TransactionContext; @@ -182,7 +181,7 @@ public void execute(Object object) throws ContractExeException { if (rootRepository.getDynamicPropertiesStore().supportAllowDynamicEnergy()) { // only add trigger_energy_base when type is call. if (TrxType.TRX_CONTRACT_CREATION_TYPE == trxType) { - long energyFactor = program.updateContextContractCycle(); + long energyFactor = program.updateContextContractFactor(); if (energyFactor > DYNAMIC_ENERGY_FACTOR_DECIMAL) { program.spendEnergy( rootRepository.getDynamicPropertiesStore().getDynamicEnergyTriggerBase() diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index efb78cac015..da01c1febc4 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -654,7 +654,8 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, if (value < DYNAMIC_ENERGY_FACTOR_DECIMAL || value > DYNAMIC_ENERGY_FACTOR_RANGE) { throw new ContractValidateException( - "This value[DYNAMIC_ENERGY_INCREASE_FACTOR] is only allowed to be in the range 100-10000" + "This value[DYNAMIC_ENERGY_INCREASE_FACTOR] " + + "is only allowed to be in the range 100-10000" ); } break; @@ -675,7 +676,7 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, case DYNAMIC_ENERGY_TRIGGER_BASE: { if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7)) { throw new ContractValidateException( - "Bad chain parameter id [UNFREEZE_DELAY_DAYS]"); + "Bad chain parameter id [DYNAMIC_ENERGY_TRIGGER_BASE]"); } if (value < 0 || value > LONG_VALUE) { diff --git a/actuator/src/main/java/org/tron/core/vm/VM.java b/actuator/src/main/java/org/tron/core/vm/VM.java index 50b3f428f63..de7378847c6 100644 --- a/actuator/src/main/java/org/tron/core/vm/VM.java +++ b/actuator/src/main/java/org/tron/core/vm/VM.java @@ -2,6 +2,7 @@ import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; +import com.google.common.collect.ImmutableSet; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.springframework.util.StringUtils; @@ -14,6 +15,9 @@ @Slf4j(topic = "VM") public class VM { + private static final ImmutableSet CALL_OPS = ImmutableSet.of(Op.CALL, Op.STATICCALL, + Op.DELEGATECALL, Op.CALLCODE, Op.CALLTOKEN); + public static void play(Program program, JumpTable jumpTable) { try { long factor = DYNAMIC_ENERGY_FACTOR_DECIMAL; @@ -23,7 +27,7 @@ public static void play(Program program, JumpTable jumpTable) { program.getContractState().getDynamicPropertiesStore().supportAllowDynamicEnergy(); if (allowDynamicEnergy) { - factor = program.updateContextContractCycle(); + factor = program.updateContextContractFactor(); } while (!program.isStopped()) { @@ -46,10 +50,16 @@ public static void play(Program program, JumpTable jumpTable) { /* spend energy before execution */ long energy = op.getEnergyCost(program); if (allowDynamicEnergy) { - energyUsage += energy; + long actualEnergy = energy; + // CALL Ops have special calculation on energy. + if (CALL_OPS.contains(op)) { + actualEnergy = energy - program.getAdjustedCallEnergy().longValueSafe(); + } + energyUsage += actualEnergy; if (factor > DYNAMIC_ENERGY_FACTOR_DECIMAL) { - energy = energy * factor / DYNAMIC_ENERGY_FACTOR_DECIMAL; + energy = energy - actualEnergy + + actualEnergy * factor / DYNAMIC_ENERGY_FACTOR_DECIMAL; } } program.spendEnergy(energy, opName); diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index c0f9ace1d5b..08e2ff692d9 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -2204,7 +2204,7 @@ public long withdrawReward() { return 0; } - public long updateContextContractCycle() { + public long updateContextContractFactor() { ContractStateCapsule contractStateCapsule = contractState.getContractState(getContextAddress()); diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java index 3737b8873e9..be30c4dbf37 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java @@ -111,8 +111,10 @@ public boolean catchUpToCycle( return true; } - double decreaseFactor = 1 - ((double) increaseFactor / DYNAMIC_ENERGY_FACTOR_DECIMAL - 1) - / DYNAMIC_ENERGY_DECREASE_DIVISION; + double decreaseFactor = Math.max( + DYNAMIC_ENERY_DECREASE_FACTOR_MAX, + 1 - ((double) increaseFactor / DYNAMIC_ENERGY_FACTOR_DECIMAL - 1) + / DYNAMIC_ENERGY_DECREASE_DIVISION); if (cycleCount > 1) { decreaseFactor = Math.pow( decreaseFactor, diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 65625876094..080694fbcbc 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -329,6 +329,8 @@ public class Constant { public static final int DYNAMIC_ENERGY_DECREASE_DIVISION = 4; + public static final double DYNAMIC_ENERY_DECREASE_FACTOR_MAX = 0.5; + public static final int DYNAMIC_ENERGY_DECREASE_MAX_CYCLE = 10; public static final String DYNAMIC_ENERGY_TRIGGER_BASE = "committee.dynamicEnergyTriggerBase"; From 01c25f33e3a9a6a5bc20f61e9e8dd119358412d1 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Fri, 23 Dec 2022 15:30:05 +0800 Subject: [PATCH 0487/1197] feat(DynamicEnergy): optimize for review comments --- .../main/java/org/tron/core/actuator/VMActuator.java | 2 +- .../main/java/org/tron/core/utils/ProposalUtil.java | 6 +++--- .../org/tron/core/capsule/ContractStateCapsule.java | 9 ++++++--- .../java/org/tron/core/store/ContractStateStore.java | 2 +- .../org/tron/common/parameter/CommonParameter.java | 4 ++-- common/src/main/java/org/tron/core/Constant.java | 2 +- .../src/main/java/org/tron/core/config/args/Args.java | 11 +++++++---- 7 files changed, 21 insertions(+), 15 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 03b6f57a366..5c1ca2822ed 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -180,7 +180,7 @@ public void execute(Object object) throws ContractExeException { if (rootRepository.getDynamicPropertiesStore().supportAllowDynamicEnergy()) { // only add trigger_energy_base when type is call. - if (TrxType.TRX_CONTRACT_CREATION_TYPE == trxType) { + if (TrxType.TRX_CONTRACT_CALL_TYPE == trxType) { long energyFactor = program.updateContextContractFactor(); if (energyFactor > DYNAMIC_ENERGY_FACTOR_DECIMAL) { program.spendEnergy( diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index da01c1febc4..132cd68c988 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -1,14 +1,14 @@ package org.tron.core.utils; +import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; +import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_RANGE; + import org.tron.common.utils.ForkController; import org.tron.core.config.Parameter.ForkBlockVersionConsts; import org.tron.core.config.Parameter.ForkBlockVersionEnum; import org.tron.core.exception.ContractValidateException; import org.tron.core.store.DynamicPropertiesStore; -import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; -import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_RANGE; - public class ProposalUtil { protected static final long LONG_VALUE = 100_000_000_000_000_000L; diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java index be30c4dbf37..304de60843d 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java @@ -1,12 +1,15 @@ package org.tron.core.capsule; +import static org.tron.core.Constant.DYNAMIC_ENERGY_DECREASE_DIVISION; +import static org.tron.core.Constant.DYNAMIC_ENERGY_DECREASE_MAX_CYCLE; +import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; +import static org.tron.core.Constant.DYNAMIC_ENERY_DECREASE_FACTOR_MIN; + import com.google.protobuf.InvalidProtocolBufferException; import lombok.extern.slf4j.Slf4j; import org.tron.protos.contract.SmartContractOuterClass; import org.tron.protos.contract.SmartContractOuterClass.ContractState; -import static org.tron.core.Constant.*; - @Slf4j(topic = "capsule") public class ContractStateCapsule implements ProtoCapsule { @@ -112,7 +115,7 @@ public boolean catchUpToCycle( } double decreaseFactor = Math.max( - DYNAMIC_ENERY_DECREASE_FACTOR_MAX, + DYNAMIC_ENERY_DECREASE_FACTOR_MIN, 1 - ((double) increaseFactor / DYNAMIC_ENERGY_FACTOR_DECIMAL - 1) / DYNAMIC_ENERGY_DECREASE_DIVISION); if (cycleCount > 1) { diff --git a/chainbase/src/main/java/org/tron/core/store/ContractStateStore.java b/chainbase/src/main/java/org/tron/core/store/ContractStateStore.java index 99fcad02cbf..19dfb11cdcd 100644 --- a/chainbase/src/main/java/org/tron/core/store/ContractStateStore.java +++ b/chainbase/src/main/java/org/tron/core/store/ContractStateStore.java @@ -14,7 +14,7 @@ public class ContractStateStore extends TronStoreWithRevoking { @Autowired - private ContractStateStore(@Value("contractState") String dbName) { + private ContractStateStore(@Value("contract-state") String dbName) { super(dbName); } diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 8a4cacdc21b..19ece03170f 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -1,5 +1,7 @@ package org.tron.common.parameter; +import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; + import com.beust.jcommander.Parameter; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -19,8 +21,6 @@ import org.tron.core.config.args.SeedNode; import org.tron.core.config.args.Storage; -import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; - public class CommonParameter { public static final String IGNORE_WRONG_WITNESS_ADDRESS_FORMAT = diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 080694fbcbc..097a558d16f 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -329,7 +329,7 @@ public class Constant { public static final int DYNAMIC_ENERGY_DECREASE_DIVISION = 4; - public static final double DYNAMIC_ENERY_DECREASE_FACTOR_MAX = 0.5; + public static final double DYNAMIC_ENERY_DECREASE_FACTOR_MIN = 0.5; public static final int DYNAMIC_ENERGY_DECREASE_MAX_CYCLE = 10; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index cd038fb9024..0f3227321ce 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -3,6 +3,7 @@ import static java.lang.Math.max; import static java.lang.System.exit; import static org.tron.core.Constant.ADD_PRE_FIX_BYTE_MAINNET; +import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_RANGE; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCE_TIMEOUT_PERCENT; import static org.tron.core.config.Parameter.ChainConstant.MAX_ACTIVE_WITNESS_NUM; @@ -1085,16 +1086,18 @@ public static void setParam(final String[] args, final String confFileName) { if (config.hasPath(Constant.DYNAMIC_ENERGY_THRESHOLD)) { PARAMETER.dynamicEnergyThreshold = config.getLong(Constant.DYNAMIC_ENERGY_THRESHOLD); - PARAMETER.dynamicEnergyThreshold = Math.min(PARAMETER.dynamicEnergyThreshold, 100_000_000_000_000_000L); + PARAMETER.dynamicEnergyThreshold + = Math.min(PARAMETER.dynamicEnergyThreshold, 100_000_000_000_000_000L); PARAMETER.dynamicEnergyThreshold = Math.max(PARAMETER.dynamicEnergyThreshold, 0); } if (config.hasPath(Constant.DYNAMIC_ENERGY_INCREASE_FACTOR)) { - PARAMETER.dynamicEnergyIncreaseFactor = config.getLong(Constant.DYNAMIC_ENERGY_INCREASE_FACTOR); + PARAMETER.dynamicEnergyIncreaseFactor + = config.getLong(Constant.DYNAMIC_ENERGY_INCREASE_FACTOR); PARAMETER.dynamicEnergyIncreaseFactor = Math.min(PARAMETER.dynamicEnergyIncreaseFactor, DYNAMIC_ENERGY_FACTOR_RANGE); PARAMETER.dynamicEnergyIncreaseFactor = - Math.max(PARAMETER.dynamicEnergyIncreaseFactor, 0); + Math.max(PARAMETER.dynamicEnergyIncreaseFactor, DYNAMIC_ENERGY_FACTOR_DECIMAL); } if (config.hasPath(Constant.DYNAMIC_ENERGY_MAX_FACTOR)) { @@ -1102,7 +1105,7 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.dynamicEnergyMaxFactor = Math.min(PARAMETER.dynamicEnergyMaxFactor, DYNAMIC_ENERGY_FACTOR_RANGE); PARAMETER.dynamicEnergyMaxFactor = - Math.max(PARAMETER.dynamicEnergyMaxFactor, 0); + Math.max(PARAMETER.dynamicEnergyMaxFactor, DYNAMIC_ENERGY_FACTOR_DECIMAL); } if (config.hasPath(Constant.DYNAMIC_ENERGY_TRIGGER_BASE)) { From 4145e5801c254a9b584bf75e3a092732ae8f59d2 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Fri, 23 Dec 2022 17:28:14 +0800 Subject: [PATCH 0488/1197] feat(DynamicEnergy): add API for Dynamic Energy and optimize ContractStateCapsule --- .../org/tron/core/vm/program/Program.java | 12 +-- .../core/capsule/ContractStateCapsule.java | 8 ++ .../src/main/java/org/tron/core/Wallet.java | 29 +++++++ .../org/tron/core/services/RpcApiService.java | 9 +++ .../services/http/FullNodeHttpApiService.java | 3 + .../http/GetContractStateServlet.java | 77 +++++++++++++++++++ protocol/src/main/protos/api/api.proto | 3 + 7 files changed, 131 insertions(+), 10 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/services/http/GetContractStateServlet.java diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 08e2ff692d9..a38d0145728 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -2210,11 +2210,7 @@ public long updateContextContractFactor() { if (contractStateCapsule == null) { contractStateCapsule = new ContractStateCapsule( - SmartContractOuterClass.ContractState.newBuilder() - .setUpdateCycle(contractState.getDynamicPropertiesStore().getCurrentCycleNumber()) - .setEnergyUsage(0L) - .setEnergyFactor(DYNAMIC_ENERGY_FACTOR_DECIMAL) - .build()); + contractState.getDynamicPropertiesStore().getCurrentCycleNumber()); contractState.updateContractState(getContextAddress(), contractStateCapsule); } else { if (contractStateCapsule.catchUpToCycle( @@ -2236,11 +2232,7 @@ public void addContextContractUsage(long value) { if (contractStateCapsule == null) { contractStateCapsule = new ContractStateCapsule( - SmartContractOuterClass.ContractState.newBuilder() - .setUpdateCycle(contractState.getDynamicPropertiesStore().getCurrentCycleNumber()) - .setEnergyUsage(0L) - .setEnergyFactor(DYNAMIC_ENERGY_FACTOR_DECIMAL) - .build()); + contractState.getDynamicPropertiesStore().getCurrentCycleNumber()); } contractStateCapsule.addEnergyUsage(value); diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java index 304de60843d..125da304f8d 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java @@ -27,6 +27,14 @@ public ContractStateCapsule(byte[] data) { } } + public ContractStateCapsule(long currentCycle) { + this.contractState = ContractState.newBuilder() + .setUpdateCycle(currentCycle) + .setEnergyFactor(DYNAMIC_ENERGY_FACTOR_DECIMAL) + .setEnergyUsage(0L) + .build(); + } + @Override public byte[] getData() { return this.contractState.toByteArray(); diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index e2c08fe9a6b..81166fd2aa5 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -133,6 +133,7 @@ import org.tron.core.capsule.BytesCapsule; import org.tron.core.capsule.CodeCapsule; import org.tron.core.capsule.ContractCapsule; +import org.tron.core.capsule.ContractStateCapsule; import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.ExchangeCapsule; @@ -231,6 +232,7 @@ import org.tron.protos.contract.ShieldContract.PedersenHash; import org.tron.protos.contract.ShieldContract.ReceiveDescription; import org.tron.protos.contract.ShieldContract.ShieldedTransferContract; +import org.tron.protos.contract.SmartContractOuterClass.ContractState; import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; import org.tron.protos.contract.SmartContractOuterClass.SmartContract; import org.tron.protos.contract.SmartContractOuterClass.SmartContractDataWrapper; @@ -2949,6 +2951,33 @@ public SmartContract getContract(GrpcAPI.BytesMessage bytesMessage) { return null; } + public ContractState getContractState(GrpcAPI.BytesMessage bytesMessage) { + byte[] address = bytesMessage.getValue().toByteArray(); + + ContractCapsule contractCapsule = chainBaseManager.getContractStore().get(address); + if (contractCapsule == null) { + logger.error( + "Get contract state failed, the contract does not exist!"); + return null; + } + + ContractStateCapsule contractStateCapsule + = chainBaseManager.getContractStateStore().get(address); + if (Objects.nonNull(contractStateCapsule)) { + contractStateCapsule.catchUpToCycle( + chainBaseManager.getDynamicPropertiesStore().getCurrentCycleNumber(), + chainBaseManager.getDynamicPropertiesStore().getDynamicEnergyThreshold(), + chainBaseManager.getDynamicPropertiesStore().getDynamicEnergyIncreaseFactor(), + chainBaseManager.getDynamicPropertiesStore().getDynamicEnergyMaxFactor() + ); + return contractStateCapsule.getInstance(); + } + + return new ContractStateCapsule( + chainBaseManager.getDynamicPropertiesStore().getCurrentCycleNumber()) + .getInstance(); + } + /** * Add a wrapper for smart contract. Current additional information including runtime code for a * smart contract. diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 0b2bc6a8f33..ba43420e13f 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -165,6 +165,7 @@ import org.tron.protos.contract.ShieldContract.IncrementalMerkleVoucherInfo; import org.tron.protos.contract.ShieldContract.OutputPointInfo; import org.tron.protos.contract.SmartContractOuterClass.ClearABIContract; +import org.tron.protos.contract.SmartContractOuterClass.ContractState; import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; import org.tron.protos.contract.SmartContractOuterClass.SmartContract; import org.tron.protos.contract.SmartContractOuterClass.SmartContractDataWrapper; @@ -2040,6 +2041,14 @@ public void getContract(BytesMessage request, responseObserver.onCompleted(); } + @Override + public void getContractState(BytesMessage request, + StreamObserver responseObserver) { + ContractState contractState = wallet.getContractState(request); + responseObserver.onNext(contractState); + responseObserver.onCompleted(); + } + @Override public void getContractInfo(BytesMessage request, StreamObserver responseObserver) { diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index c2b201cb787..af485e78386 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -138,6 +138,8 @@ public class FullNodeHttpApiService implements Service { @Autowired private GetContractInfoServlet getContractInfoServlet; @Autowired + private GetContractStateServlet getContractStateServlet; + @Autowired private ClearABIServlet clearABIServlet; @Autowired private ProposalCreateServlet proposalCreateServlet; @@ -444,6 +446,7 @@ public void start() { "/wallet/triggerconstantcontract"); context.addServlet(new ServletHolder(getContractServlet), "/wallet/getcontract"); context.addServlet(new ServletHolder(getContractInfoServlet), "/wallet/getcontractinfo"); + context.addServlet(new ServletHolder(getContractStateServlet), "/wallet/getcontractstate"); context.addServlet(new ServletHolder(clearABIServlet), "/wallet/clearabi"); context.addServlet(new ServletHolder(proposalCreateServlet), "/wallet/proposalcreate"); context.addServlet(new ServletHolder(proposalApproveServlet), "/wallet/proposalapprove"); diff --git a/framework/src/main/java/org/tron/core/services/http/GetContractStateServlet.java b/framework/src/main/java/org/tron/core/services/http/GetContractStateServlet.java new file mode 100644 index 00000000000..46eb3d7d4ca --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/GetContractStateServlet.java @@ -0,0 +1,77 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.api.GrpcAPI; +import org.tron.core.Wallet; +import org.tron.protos.contract.SmartContractOuterClass; + +@Component +@Slf4j(topic = "API") +public class GetContractStateServlet extends RateLimiterServlet { + + @Autowired + private Wallet wallet; + + private static final String VALUE = "value"; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + try { + boolean visible = Util.getVisible(request); + String input = request.getParameter(VALUE); + if (visible) { + input = Util.getHexAddress(input); + } + + JSONObject jsonObject = new JSONObject(); + jsonObject.put(VALUE, input); + GrpcAPI.BytesMessage.Builder build = GrpcAPI.BytesMessage.newBuilder(); + JsonFormat.merge(jsonObject.toJSONString(), build, visible); + SmartContractOuterClass.ContractState contractState = wallet.getContractState(build.build()); + + if (contractState == null) { + response.getWriter().println("{}"); + } else { + JSONObject jsonContractState = JSONObject + .parseObject(JsonFormat.printToString(contractState, visible)); + response.getWriter().println(jsonContractState.toJSONString()); + } + } catch (Exception e) { + Util.processError(e, response); + } + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + PostParams params = PostParams.getPostParams(request); + String input = params.getParams(); + boolean visible = params.isVisible(); + if (visible) { + JSONObject jsonObject = JSONObject.parseObject(input); + String value = jsonObject.getString(VALUE); + jsonObject.put(VALUE, Util.getHexAddress(value)); + input = jsonObject.toJSONString(); + } + + GrpcAPI.BytesMessage.Builder build = GrpcAPI.BytesMessage.newBuilder(); + JsonFormat.merge(input, build, visible); + SmartContractOuterClass.ContractState contractState = wallet.getContractState(build.build()); + + if (contractState == null) { + response.getWriter().println("{}"); + } else { + JSONObject jsonContractState = JSONObject + .parseObject(JsonFormat.printToString(contractState, visible)); + response.getWriter().println(jsonContractState.toJSONString()); + } + } catch (Exception e) { + Util.processError(e, response); + } + } +} diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index e2aa75255ad..72131928cc6 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -471,6 +471,9 @@ service Wallet { rpc GetContract (BytesMessage) returns (SmartContract) { } + rpc GetContractState (BytesMessage) returns (ContractState) { + } + rpc GetContractInfo (BytesMessage) returns (SmartContractDataWrapper) { } From 17bce84c6d3227a5f88638ec3494103c29e7c7d2 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Fri, 23 Dec 2022 18:30:19 +0800 Subject: [PATCH 0489/1197] feat(DynamicEnergy): optimize Dynamic Energy ContractState API --- .../src/main/java/org/tron/core/Wallet.java | 45 ++++------- .../org/tron/core/services/RpcApiService.java | 9 --- .../services/http/FullNodeHttpApiService.java | 3 - .../http/GetContractStateServlet.java | 77 ------------------- protocol/src/main/protos/api/api.proto | 3 - .../protos/core/contract/smart_contract.proto | 1 + 6 files changed, 17 insertions(+), 121 deletions(-) delete mode 100644 framework/src/main/java/org/tron/core/services/http/GetContractStateServlet.java diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 81166fd2aa5..213883f551a 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -232,7 +232,6 @@ import org.tron.protos.contract.ShieldContract.PedersenHash; import org.tron.protos.contract.ShieldContract.ReceiveDescription; import org.tron.protos.contract.ShieldContract.ShieldedTransferContract; -import org.tron.protos.contract.SmartContractOuterClass.ContractState; import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; import org.tron.protos.contract.SmartContractOuterClass.SmartContract; import org.tron.protos.contract.SmartContractOuterClass.SmartContractDataWrapper; @@ -2951,33 +2950,6 @@ public SmartContract getContract(GrpcAPI.BytesMessage bytesMessage) { return null; } - public ContractState getContractState(GrpcAPI.BytesMessage bytesMessage) { - byte[] address = bytesMessage.getValue().toByteArray(); - - ContractCapsule contractCapsule = chainBaseManager.getContractStore().get(address); - if (contractCapsule == null) { - logger.error( - "Get contract state failed, the contract does not exist!"); - return null; - } - - ContractStateCapsule contractStateCapsule - = chainBaseManager.getContractStateStore().get(address); - if (Objects.nonNull(contractStateCapsule)) { - contractStateCapsule.catchUpToCycle( - chainBaseManager.getDynamicPropertiesStore().getCurrentCycleNumber(), - chainBaseManager.getDynamicPropertiesStore().getDynamicEnergyThreshold(), - chainBaseManager.getDynamicPropertiesStore().getDynamicEnergyIncreaseFactor(), - chainBaseManager.getDynamicPropertiesStore().getDynamicEnergyMaxFactor() - ); - return contractStateCapsule.getInstance(); - } - - return new ContractStateCapsule( - chainBaseManager.getDynamicPropertiesStore().getCurrentCycleNumber()) - .getInstance(); - } - /** * Add a wrapper for smart contract. Current additional information including runtime code for a * smart contract. @@ -3008,7 +2980,22 @@ public SmartContractDataWrapper getContractInfo(GrpcAPI.BytesMessage bytesMessag } else { contractCapsule.setRuntimecode(new byte[0]); } - return contractCapsule.generateWrapper(); + SmartContractDataWrapper wrapper = contractCapsule.generateWrapper(); + + ContractStateCapsule contractStateCapsule + = chainBaseManager.getContractStateStore().get(address); + if (Objects.nonNull(contractStateCapsule)) { + contractStateCapsule.catchUpToCycle( + chainBaseManager.getDynamicPropertiesStore().getCurrentCycleNumber(), + chainBaseManager.getDynamicPropertiesStore().getDynamicEnergyThreshold(), + chainBaseManager.getDynamicPropertiesStore().getDynamicEnergyIncreaseFactor(), + chainBaseManager.getDynamicPropertiesStore().getDynamicEnergyMaxFactor() + ); + } else { + contractStateCapsule = new ContractStateCapsule( + chainBaseManager.getDynamicPropertiesStore().getCurrentCycleNumber()); + } + return wrapper.toBuilder().setContractState(contractStateCapsule.getInstance()).build(); } return null; } diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index ba43420e13f..0b2bc6a8f33 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -165,7 +165,6 @@ import org.tron.protos.contract.ShieldContract.IncrementalMerkleVoucherInfo; import org.tron.protos.contract.ShieldContract.OutputPointInfo; import org.tron.protos.contract.SmartContractOuterClass.ClearABIContract; -import org.tron.protos.contract.SmartContractOuterClass.ContractState; import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; import org.tron.protos.contract.SmartContractOuterClass.SmartContract; import org.tron.protos.contract.SmartContractOuterClass.SmartContractDataWrapper; @@ -2041,14 +2040,6 @@ public void getContract(BytesMessage request, responseObserver.onCompleted(); } - @Override - public void getContractState(BytesMessage request, - StreamObserver responseObserver) { - ContractState contractState = wallet.getContractState(request); - responseObserver.onNext(contractState); - responseObserver.onCompleted(); - } - @Override public void getContractInfo(BytesMessage request, StreamObserver responseObserver) { diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index af485e78386..c2b201cb787 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -138,8 +138,6 @@ public class FullNodeHttpApiService implements Service { @Autowired private GetContractInfoServlet getContractInfoServlet; @Autowired - private GetContractStateServlet getContractStateServlet; - @Autowired private ClearABIServlet clearABIServlet; @Autowired private ProposalCreateServlet proposalCreateServlet; @@ -446,7 +444,6 @@ public void start() { "/wallet/triggerconstantcontract"); context.addServlet(new ServletHolder(getContractServlet), "/wallet/getcontract"); context.addServlet(new ServletHolder(getContractInfoServlet), "/wallet/getcontractinfo"); - context.addServlet(new ServletHolder(getContractStateServlet), "/wallet/getcontractstate"); context.addServlet(new ServletHolder(clearABIServlet), "/wallet/clearabi"); context.addServlet(new ServletHolder(proposalCreateServlet), "/wallet/proposalcreate"); context.addServlet(new ServletHolder(proposalApproveServlet), "/wallet/proposalapprove"); diff --git a/framework/src/main/java/org/tron/core/services/http/GetContractStateServlet.java b/framework/src/main/java/org/tron/core/services/http/GetContractStateServlet.java deleted file mode 100644 index 46eb3d7d4ca..00000000000 --- a/framework/src/main/java/org/tron/core/services/http/GetContractStateServlet.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.tron.core.services.http; - -import com.alibaba.fastjson.JSONObject; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI; -import org.tron.core.Wallet; -import org.tron.protos.contract.SmartContractOuterClass; - -@Component -@Slf4j(topic = "API") -public class GetContractStateServlet extends RateLimiterServlet { - - @Autowired - private Wallet wallet; - - private static final String VALUE = "value"; - - protected void doGet(HttpServletRequest request, HttpServletResponse response) { - try { - boolean visible = Util.getVisible(request); - String input = request.getParameter(VALUE); - if (visible) { - input = Util.getHexAddress(input); - } - - JSONObject jsonObject = new JSONObject(); - jsonObject.put(VALUE, input); - GrpcAPI.BytesMessage.Builder build = GrpcAPI.BytesMessage.newBuilder(); - JsonFormat.merge(jsonObject.toJSONString(), build, visible); - SmartContractOuterClass.ContractState contractState = wallet.getContractState(build.build()); - - if (contractState == null) { - response.getWriter().println("{}"); - } else { - JSONObject jsonContractState = JSONObject - .parseObject(JsonFormat.printToString(contractState, visible)); - response.getWriter().println(jsonContractState.toJSONString()); - } - } catch (Exception e) { - Util.processError(e, response); - } - } - - protected void doPost(HttpServletRequest request, HttpServletResponse response) { - try { - PostParams params = PostParams.getPostParams(request); - String input = params.getParams(); - boolean visible = params.isVisible(); - if (visible) { - JSONObject jsonObject = JSONObject.parseObject(input); - String value = jsonObject.getString(VALUE); - jsonObject.put(VALUE, Util.getHexAddress(value)); - input = jsonObject.toJSONString(); - } - - GrpcAPI.BytesMessage.Builder build = GrpcAPI.BytesMessage.newBuilder(); - JsonFormat.merge(input, build, visible); - SmartContractOuterClass.ContractState contractState = wallet.getContractState(build.build()); - - if (contractState == null) { - response.getWriter().println("{}"); - } else { - JSONObject jsonContractState = JSONObject - .parseObject(JsonFormat.printToString(contractState, visible)); - response.getWriter().println(jsonContractState.toJSONString()); - } - } catch (Exception e) { - Util.processError(e, response); - } - } -} diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 72131928cc6..e2aa75255ad 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -471,9 +471,6 @@ service Wallet { rpc GetContract (BytesMessage) returns (SmartContract) { } - rpc GetContractState (BytesMessage) returns (ContractState) { - } - rpc GetContractInfo (BytesMessage) returns (SmartContractDataWrapper) { } diff --git a/protocol/src/main/protos/core/contract/smart_contract.proto b/protocol/src/main/protos/core/contract/smart_contract.proto index c127b2f0e70..c913f7f7577 100644 --- a/protocol/src/main/protos/core/contract/smart_contract.proto +++ b/protocol/src/main/protos/core/contract/smart_contract.proto @@ -100,4 +100,5 @@ message UpdateEnergyLimitContract { message SmartContractDataWrapper { SmartContract smart_contract = 1; bytes runtimecode = 2; + ContractState contract_state = 3; } \ No newline at end of file From a6fd14baf31f0f6792d380b4e738175a57d5917b Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Sun, 25 Dec 2022 16:14:19 +0800 Subject: [PATCH 0490/1197] feat(estimateEnergy): add estimate energy API --- .../tron/core/capsule/TransactionCapsule.java | 11 ++ .../common/parameter/CommonParameter.java | 3 + .../src/main/java/org/tron/core/Constant.java | 2 + .../src/main/java/org/tron/core/Wallet.java | 41 +++++++ .../java/org/tron/core/config/args/Args.java | 5 +- .../org/tron/core/services/RpcApiService.java | 50 +++++++- .../services/http/EstimateEnergyServlet.java | 109 ++++++++++++++++++ .../services/http/FullNodeHttpApiService.java | 3 + .../org/tron/core/services/http/Util.java | 13 +++ .../solidity/SolidityNodeHttpApiService.java | 5 + .../services/jsonrpc/TronJsonRpcImpl.java | 61 ++++++++-- .../src/main/resources/config-localtest.conf | 8 ++ protocol/src/main/protos/api/api.proto | 8 ++ 13 files changed, 308 insertions(+), 11 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java index 3f359654767..d3b7772693f 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -527,6 +527,17 @@ public long getTimestamp() { return transaction.getRawData().getTimestamp(); } + public void setFeeLimit(long feeLimit) { + Transaction.raw rawData = this.transaction.getRawData().toBuilder() + .setFeeLimit(feeLimit) + .build(); + setRawData(rawData); + } + + public long getFeeLimit() { + return transaction.getRawData().getFeeLimit(); + } + @Deprecated public void createTransaction(com.google.protobuf.Message message, ContractType contractType) { Transaction.raw.Builder transactionBuilder = Transaction.raw.newBuilder().addContract( diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 19ece03170f..37803c03b83 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -290,6 +290,9 @@ public class CommonParameter { public boolean walletExtensionApi; @Getter @Setter + public boolean estimateEnergyApi; + @Getter + @Setter public int backupPriority; @Getter @Setter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 097a558d16f..b85c94a52c9 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -168,6 +168,8 @@ public class Constant { public static final String NODE_WALLET_EXTENSION_API = "node.walletExtensionApi"; + public static final String NODE_ESTIMATE_ENERGY_API = "node.estimateEnergyApi"; + public static final String NODE_RECEIVE_TCP_MIN_DATA_LENGTH = "node.receiveTcpMinDataLength"; public static final String NODE_IS_OPEN_FULL_TCP_DISCONNECT = "node.isOpenFullTcpDisconnect"; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 213883f551a..ef14707383f 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2846,6 +2846,47 @@ public Transaction triggerContract(TriggerSmartContract } } + public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, + TransactionCapsule trxCap, Builder builder, + Return.Builder retBuilder, GrpcAPI.EstimateEnergyMessage.Builder estimateBuilder) + throws ContractValidateException, ContractExeException, HeaderNotFound, VMIllegalException { + + long high = chainBaseManager.getDynamicPropertiesStore().getMaxFeeLimit(); + trxCap.setFeeLimit(high); + + Transaction transaction = triggerConstantContract( + triggerSmartContract, trxCap, builder, retBuilder); + + // If failed, return directly. + if (transaction.getRet(0).getRet().equals(code.FAILED)) { + estimateBuilder.setTransactionExtension(builder); + estimateBuilder.setEnergyRequired(builder.getEnergyUsed()); + return transaction; + } + + long low = getEnergyFee() * builder.getEnergyUsed(); + + while (low + 1 < high) { + // clean the prev exec data. + trxCap.resetResult(); + builder.clear(); + retBuilder.clear(); + + long mid = (high + low) / 2; + trxCap.setFeeLimit(mid); + triggerConstantContract(triggerSmartContract, trxCap, builder, retBuilder); + if (transaction.getRet(0).getRet().equals(code.FAILED)) { + low = mid; + } else { + high = mid; + } + } + estimateBuilder.setTransactionExtension(builder); + estimateBuilder.setEnergyRequired(high); + + return transaction; + } + public Transaction triggerConstantContract(TriggerSmartContract triggerSmartContract, TransactionCapsule trxCap, Builder builder, Return.Builder retBuilder) throws ContractValidateException, ContractExeException, HeaderNotFound, VMIllegalException { diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 0f3227321ce..d5295bfc759 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -74,7 +74,6 @@ import org.tron.core.config.Parameter.NodeConstant; import org.tron.core.exception.CipherException; import org.tron.core.store.AccountStore; -import org.tron.core.utils.ProposalUtil; import org.tron.keystore.Credentials; import org.tron.keystore.WalletUtils; import org.tron.program.Version; @@ -169,6 +168,7 @@ public static void clearParam() { PARAMETER.solidityNode = false; PARAMETER.trustNodeAddr = ""; PARAMETER.walletExtensionApi = false; + PARAMETER.estimateEnergyApi = false; PARAMETER.receiveTcpMinDataLength = 2048; PARAMETER.isOpenFullTcpDisconnect = false; PARAMETER.supportConstant = false; @@ -793,6 +793,9 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.walletExtensionApi = config.hasPath(Constant.NODE_WALLET_EXTENSION_API) && config.getBoolean(Constant.NODE_WALLET_EXTENSION_API); + PARAMETER.estimateEnergyApi = + config.hasPath(Constant.NODE_ESTIMATE_ENERGY_API) + && config.getBoolean(Constant.NODE_ESTIMATE_ENERGY_API); PARAMETER.receiveTcpMinDataLength = config.hasPath(Constant.NODE_RECEIVE_TCP_MIN_DATA_LENGTH) ? config.getLong(Constant.NODE_RECEIVE_TCP_MIN_DATA_LENGTH) : 2048; diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 0b2bc6a8f33..16a6f1b3cfa 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -11,9 +11,6 @@ import io.grpc.netty.NettyServerBuilder; import io.grpc.stub.StreamObserver; import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @@ -1980,6 +1977,53 @@ public void triggerContract(TriggerSmartContract request, callContract(request, responseObserver, false); } + @Override + public void estimateEnergy(TriggerSmartContract request, + StreamObserver responseObserver) { + TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); + Return.Builder retBuilder = Return.newBuilder(); + GrpcAPI.EstimateEnergyMessage.Builder estimateBuilder + = GrpcAPI.EstimateEnergyMessage.newBuilder(); + + if (!CommonParameter.getInstance().isEstimateEnergyApi()) { + responseObserver.onNext(null); + responseObserver.onCompleted(); + return; + } + + try { + TransactionCapsule trxCap = createTransactionCapsule(request, + ContractType.TriggerSmartContract); + Transaction trx = wallet.estimateEnergy( + request, trxCap, trxExtBuilder, retBuilder, estimateBuilder); + + trxExtBuilder.setTransaction(trx); + trxExtBuilder.setTxid(trxCap.getTransactionId().getByteString()); + retBuilder.setResult(true).setCode(response_code.SUCCESS); + trxExtBuilder.setResult(retBuilder); + } catch (ContractValidateException | VMIllegalException e) { + retBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) + .setMessage(ByteString.copyFromUtf8(Wallet + .CONTRACT_VALIDATE_ERROR + e.getMessage())); + trxExtBuilder.setResult(retBuilder); + logger.warn(CONTRACT_VALIDATE_EXCEPTION, e.getMessage()); + } catch (RuntimeException e) { + retBuilder.setResult(false).setCode(response_code.CONTRACT_EXE_ERROR) + .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); + trxExtBuilder.setResult(retBuilder); + logger.warn("When run constant call in VM, have Runtime Exception: " + e.getMessage()); + } catch (Exception e) { + retBuilder.setResult(false).setCode(response_code.OTHER_ERROR) + .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); + trxExtBuilder.setResult(retBuilder); + logger.warn("unknown exception caught: " + e.getMessage(), e); + } finally { + estimateBuilder.setTransactionExtension(trxExtBuilder); + responseObserver.onNext(estimateBuilder.build()); + responseObserver.onCompleted(); + } + } + @Override public void triggerConstantContract(TriggerSmartContract request, StreamObserver responseObserver) { diff --git a/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java b/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java new file mode 100644 index 00000000000..493d9928af3 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java @@ -0,0 +1,109 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import com.google.protobuf.ByteString; +import io.netty.util.internal.StringUtil; + +import java.io.IOException; +import java.security.InvalidParameterException; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.api.GrpcAPI; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.ByteArray; +import org.tron.core.Wallet; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.exception.ContractValidateException; +import org.tron.protos.Protocol; +import org.tron.protos.contract.SmartContractOuterClass; + +@Component +@Slf4j(topic = "API") +public class EstimateEnergyServlet extends RateLimiterServlet { + + private final String functionSelector = "function_selector"; + + @Autowired + private Wallet wallet; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + } + + protected void validateParameter(String contract) { + JSONObject jsonObject = JSONObject.parseObject(contract); + if (!jsonObject.containsKey("owner_address") + || StringUtil.isNullOrEmpty(jsonObject.getString("owner_address"))) { + throw new InvalidParameterException("owner_address isn't set."); + } + if (!jsonObject.containsKey("contract_address") + || StringUtil.isNullOrEmpty(jsonObject.getString("contract_address"))) { + throw new InvalidParameterException("contract_address isn't set."); + } + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws IOException { + + if (!CommonParameter.getInstance().isEstimateEnergyApi()) { + return; + } + + SmartContractOuterClass.TriggerSmartContract.Builder build = SmartContractOuterClass.TriggerSmartContract.newBuilder(); + GrpcAPI.TransactionExtention.Builder trxExtBuilder = GrpcAPI.TransactionExtention.newBuilder(); + GrpcAPI.EstimateEnergyMessage.Builder estimateEnergyBuilder = GrpcAPI.EstimateEnergyMessage.newBuilder(); + GrpcAPI.Return.Builder retBuilder = GrpcAPI.Return.newBuilder(); + boolean visible = false; + try { + String contract = request.getReader().lines() + .collect(Collectors.joining(System.lineSeparator())); + Util.checkBodySize(contract); + visible = Util.getVisiblePost(contract); + validateParameter(contract); + JsonFormat.merge(contract, build, visible); + JSONObject jsonObject = JSONObject.parseObject(contract); + + boolean isFunctionSelectorSet = jsonObject.containsKey(functionSelector) + && !StringUtil.isNullOrEmpty(jsonObject.getString(functionSelector)); + String data; + if (isFunctionSelectorSet) { + String selector = jsonObject.getString(functionSelector); + String parameter = jsonObject.getString("parameter"); + data = Util.parseMethod(selector, parameter); + build.setData(ByteString.copyFrom(ByteArray.fromHexString(data))); + } else { + build.setData(ByteString.copyFrom(new byte[0])); + } + TransactionCapsule trxCap = wallet.createTransactionCapsule(build.build(), + Protocol.Transaction.Contract.ContractType.TriggerSmartContract); + + Protocol.Transaction trx = wallet + .estimateEnergy(build.build(), trxCap, + trxExtBuilder, + retBuilder, estimateEnergyBuilder); + trx = Util.setTransactionPermissionId(jsonObject, trx); + trx = Util.setTransactionExtraData(jsonObject, trx, visible); + trxExtBuilder.setTransaction(trx); + retBuilder.setResult(true).setCode(GrpcAPI.Return.response_code.SUCCESS); + } catch (ContractValidateException e) { + retBuilder.setResult(false).setCode(GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR) + .setMessage(ByteString.copyFromUtf8(e.getMessage())); + } catch (Exception e) { + String errString = null; + if (e.getMessage() != null) { + errString = e.getMessage().replaceAll("[\"]", "\'"); + } + retBuilder.setResult(false).setCode(GrpcAPI.Return.response_code.OTHER_ERROR) + .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + errString)); + } + trxExtBuilder.setResult(retBuilder); + estimateEnergyBuilder.setTransactionExtension(trxExtBuilder); + response.getWriter().println( + Util.printEstimateEnergyMessage(estimateEnergyBuilder.build(), visible)); + } +} diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index c2b201cb787..43f00454fd3 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -134,6 +134,8 @@ public class FullNodeHttpApiService implements Service { @Autowired private TriggerConstantContractServlet triggerConstantContractServlet; @Autowired + private EstimateEnergyServlet estimateEnergyServlet; + @Autowired private GetContractServlet getContractServlet; @Autowired private GetContractInfoServlet getContractInfoServlet; @@ -442,6 +444,7 @@ public void start() { "/wallet/triggersmartcontract"); context.addServlet(new ServletHolder(triggerConstantContractServlet), "/wallet/triggerconstantcontract"); + context.addServlet(new ServletHolder(estimateEnergyServlet), "/wallet/estimateenergy"); context.addServlet(new ServletHolder(getContractServlet), "/wallet/getcontract"); context.addServlet(new ServletHolder(getContractInfoServlet), "/wallet/getcontractinfo"); context.addServlet(new ServletHolder(clearABIServlet), "/wallet/clearabi"); diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 2fef8ff1425..5c8c6e13be3 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -25,6 +25,7 @@ import org.apache.commons.lang3.StringUtils; import org.bouncycastle.util.encoders.Hex; import org.eclipse.jetty.util.StringUtil; +import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.BlockList; import org.tron.api.GrpcAPI.EasyTransferResponse; import org.tron.api.GrpcAPI.TransactionApprovedList; @@ -58,6 +59,7 @@ public class Util { public static final String PERMISSION_ID = "Permission_id"; public static final String VISIBLE = "visible"; public static final String TRANSACTION = "transaction"; + public static final String TRANSACTION_EXTENSION = "transactionExtension"; public static final String VALUE = "value"; public static final String CONTRACT_TYPE = "contractType"; public static final String EXTRA_DATA = "extra_data"; @@ -160,6 +162,17 @@ public static String printTransactionExtention(TransactionExtention transactionE return jsonObject.toJSONString(); } + public static String printEstimateEnergyMessage(GrpcAPI.EstimateEnergyMessage message, boolean selfType) { + String string = JsonFormat.printToString(message, selfType); + JSONObject jsonObject = JSONObject.parseObject(string); + + String extension = printTransactionExtention(message.getTransactionExtension(), selfType); + JSONObject extensionObject = JSONObject.parseObject(extension); + + jsonObject.put(TRANSACTION_EXTENSION, extensionObject); + return jsonObject.toJSONString(); + } + public static String printTransactionSignWeight(TransactionSignWeight transactionSignWeight, boolean selfType) { String string = JsonFormat.printToString(transactionSignWeight, selfType); diff --git a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java index 580969ac13a..9fc62f36fd2 100644 --- a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java @@ -15,6 +15,7 @@ import org.tron.core.config.args.Args; import org.tron.core.services.filter.HttpApiAccessFilter; import org.tron.core.services.http.DelegateResourceServlet; +import org.tron.core.services.http.EstimateEnergyServlet; import org.tron.core.services.http.FreezeBalanceV2Servlet; import org.tron.core.services.http.FullNodeHttpApiService; import org.tron.core.services.http.GetAccountByIdServlet; @@ -161,6 +162,8 @@ public class SolidityNodeHttpApiService implements Service { private GetRewardServlet getRewardServlet; @Autowired private TriggerConstantContractServlet triggerConstantContractServlet; + @Autowired + private EstimateEnergyServlet estimateEnergyServlet; @Autowired private GetTransactionInfoByBlockNumServlet getTransactionInfoByBlockNumServlet; @@ -287,6 +290,8 @@ public void start() { "/walletsolidity/gettransactioncountbyblocknum"); context.addServlet(new ServletHolder(triggerConstantContractServlet), "/walletsolidity/triggerconstantcontract"); + context.addServlet(new ServletHolder(estimateEnergyServlet), + "/walletsolidity/estimateenergy"); context.addServlet(new ServletHolder(getNodeInfoServlet), "/wallet/getnodeinfo"); context.addServlet(new ServletHolder(getNodeInfoServlet), "/walletsolidity/getnodeinfo"); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 3d44815d06e..8571e601cef 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -30,6 +30,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.bouncycastle.util.encoders.Hex; +import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.BytesMessage; import org.tron.api.GrpcAPI.Return; import org.tron.api.GrpcAPI.Return.response_code; @@ -38,6 +39,7 @@ import org.tron.common.logsfilter.ContractEventParser; import org.tron.common.logsfilter.capsule.BlockFilterCapsule; import org.tron.common.logsfilter.capsule.LogsFilterCapsule; +import org.tron.common.parameter.CommonParameter; import org.tron.common.runtime.vm.DataWord; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; @@ -390,6 +392,33 @@ private void callTriggerConstantContract(byte[] ownerAddressByte, byte[] contrac retBuilder.setResult(true).setCode(response_code.SUCCESS); } + private void estimateEnergy(byte[] ownerAddressByte, byte[] contractAddressByte, + long value, byte[] data, TransactionExtention.Builder trxExtBuilder, + Return.Builder retBuilder, GrpcAPI.EstimateEnergyMessage.Builder estimateBuilder) + throws ContractValidateException, ContractExeException, HeaderNotFound, VMIllegalException { + + TriggerSmartContract triggerContract = triggerCallContract( + ownerAddressByte, + contractAddressByte, + value, + data, + 0, + null + ); + + TransactionCapsule trxCap = wallet.createTransactionCapsule(triggerContract, + ContractType.TriggerSmartContract); + Transaction trx = + wallet.estimateEnergy(triggerContract, trxCap, trxExtBuilder, retBuilder, estimateBuilder); + + trxExtBuilder.setTransaction(trx); + trxExtBuilder.setTxid(trxCap.getTransactionId().getByteString()); + trxExtBuilder.setResult(retBuilder); + retBuilder.setResult(true).setCode(response_code.SUCCESS); + estimateBuilder.setTransactionExtension(trxExtBuilder); + } + + /** * @param data Hash of the method signature and encoded parameters. for example: * getMethodSign(methodName(uint256,uint256)) || data1 || data2 @@ -541,8 +570,12 @@ public String estimateGas(CallArguments args) throws JsonRpcInvalidRequestExcept return "0x0"; } + boolean supportEstimateEnergy = CommonParameter.getInstance().isEstimateEnergyApi(); + TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); + GrpcAPI.EstimateEnergyMessage.Builder estimateBuilder + = GrpcAPI.EstimateEnergyMessage.newBuilder(); try { byte[] contractAddress; @@ -553,13 +586,22 @@ public String estimateGas(CallArguments args) throws JsonRpcInvalidRequestExcept contractAddress = new byte[0]; } - callTriggerConstantContract(ownerAddress, - contractAddress, - args.parseValue(), - ByteArray.fromHexString(args.getData()), - trxExtBuilder, - retBuilder); - + if (supportEstimateEnergy) { + estimateEnergy(ownerAddress, + contractAddress, + args.parseValue(), + ByteArray.fromHexString(args.getData()), + trxExtBuilder, + retBuilder, + estimateBuilder); + } else { + callTriggerConstantContract(ownerAddress, + contractAddress, + args.parseValue(), + ByteArray.fromHexString(args.getData()), + trxExtBuilder, + retBuilder); + } } catch (ContractValidateException e) { String errString = "invalid contract"; @@ -590,6 +632,11 @@ public String estimateGas(CallArguments args) throws JsonRpcInvalidRequestExcept throw new JsonRpcInternalException(errMsg); } else { + + if (supportEstimateEnergy) { + return ByteArray.toJsonHex(estimateBuilder.getEnergyRequired()); + } + return ByteArray.toJsonHex(trxExtBuilder.getEnergyUsed()); } } diff --git a/framework/src/main/resources/config-localtest.conf b/framework/src/main/resources/config-localtest.conf index 45254446001..bfa9f311c08 100644 --- a/framework/src/main/resources/config-localtest.conf +++ b/framework/src/main/resources/config-localtest.conf @@ -83,6 +83,9 @@ node { # expose extension api to public or not walletExtensionApi = true + # expose estimate energy api to public or not + estimateEnergyApi = true + listen.port = 6666 connection.timeout = 2 @@ -286,6 +289,11 @@ committee = { allowTvmSolidity059 = 1 allowMarketTransaction = 1 allowTransactionFeePool = 1 + allowDynamicEnergy = 1 + dynamicEnergyThreshold = 100000 + dynamicEnergyIncreaseFactor = 120 + dynamicEnergyMaxFactor = 350 + dynamicEnergyTriggerBase = 5000 } log.level = { diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index e2aa75255ad..9947502e9ee 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -480,6 +480,9 @@ service Wallet { rpc TriggerConstantContract (TriggerSmartContract) returns (TransactionExtention) { } + rpc EstimateEnergy (TriggerSmartContract) returns (EstimateEnergyMessage) { + } + rpc ClearContractABI (ClearABIContract) returns (TransactionExtention) { } @@ -1310,6 +1313,11 @@ message TransactionExtention { repeated InternalTransaction internal_transactions = 7; } +message EstimateEnergyMessage { + TransactionExtention transactionExtension = 1; + int64 energy_required = 2; +} + message BlockExtention { repeated TransactionExtention transactions = 1; BlockHeader block_header = 2; From 3d41f131484d71f04872c7cc1edda5e8e71eb746 Mon Sep 17 00:00:00 2001 From: Asuka Date: Sun, 25 Dec 2022 16:50:22 +0800 Subject: [PATCH 0491/1197] feat(estimateEnergy): use fee limit in tx to calc energy limit for constant call --- .../java/org/tron/core/actuator/VMActuator.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 5c1ca2822ed..aadd1bde408 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -88,6 +88,8 @@ public class VMActuator implements Actuator2 { @Setter private boolean isConstantCall; + private long maxEnergyLimit; + @Setter private boolean enableEventListener; @@ -95,6 +97,7 @@ public class VMActuator implements Actuator2 { public VMActuator(boolean isConstantCall) { this.isConstantCall = isConstantCall; + this.maxEnergyLimit = CommonParameter.getInstance().maxEnergyLimitForConstant; } private static long getEnergyFee(long callerEnergyUsage, long callerEnergyFrozen, @@ -119,6 +122,12 @@ public void validate(Object object) throws ContractValidateException { // Warm up registry class OperationRegistry.init(); trx = context.getTrxCap().getInstance(); + // If tx`s fee limit is set, use it to calc max energy limit for constant call + if (isConstantCall && trx.getRawData().getFeeLimit() > 0) { + maxEnergyLimit = trx.getRawData().getFeeLimit() + / context.getStoreFactory().getChainBaseManager() + .getDynamicPropertiesStore().getEnergyFee(); + } blockCap = context.getBlockCap(); if ((VMConfig.allowTvmFreeze() || VMConfig.allowTvmFreezeV2()) && context.getTrxCap().getTrxTrace() != null) { @@ -370,7 +379,7 @@ private void create() // according to version if (isConstantCall) { - energyLimit = CommonParameter.getInstance().maxEnergyLimitForConstant; + energyLimit = maxEnergyLimit; } else { if (StorageUtils.getEnergyLimitHardFork()) { if (callValue < 0) { @@ -500,7 +509,7 @@ private void call() AccountCapsule caller = rootRepository.getAccount(callerAddress); long energyLimit; if (isConstantCall) { - energyLimit = CommonParameter.getInstance().maxEnergyLimitForConstant; + energyLimit = maxEnergyLimit; } else { AccountCapsule creator = rootRepository .getAccount(deployedContract.getInstance().getOriginAddress().toByteArray()); From f0f781fc990b35142277f57ae2f097b9ceb8e7cf Mon Sep 17 00:00:00 2001 From: Asuka Date: Sun, 25 Dec 2022 16:54:51 +0800 Subject: [PATCH 0492/1197] feat(estimateEnergy): restrict max energy limit to setting in config --- actuator/src/main/java/org/tron/core/actuator/VMActuator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index aadd1bde408..6a14f2176db 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -124,9 +124,9 @@ public void validate(Object object) throws ContractValidateException { trx = context.getTrxCap().getInstance(); // If tx`s fee limit is set, use it to calc max energy limit for constant call if (isConstantCall && trx.getRawData().getFeeLimit() > 0) { - maxEnergyLimit = trx.getRawData().getFeeLimit() + maxEnergyLimit = Math.min(maxEnergyLimit, trx.getRawData().getFeeLimit() / context.getStoreFactory().getChainBaseManager() - .getDynamicPropertiesStore().getEnergyFee(); + .getDynamicPropertiesStore().getEnergyFee()); } blockCap = context.getBlockCap(); if ((VMConfig.allowTvmFreeze() || VMConfig.allowTvmFreezeV2()) From d5aa3eda341aeb584bbe2cf10d23e0f5ad81d835 Mon Sep 17 00:00:00 2001 From: Asuka Date: Sun, 25 Dec 2022 17:41:58 +0800 Subject: [PATCH 0493/1197] feat(estimateEnergy): set real energy required, not fee limit --- framework/src/main/java/org/tron/core/Wallet.java | 7 +++++-- .../main/java/org/tron/core/services/RpcApiService.java | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index ef14707383f..74f13cb1750 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2851,7 +2851,8 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, Return.Builder retBuilder, GrpcAPI.EstimateEnergyMessage.Builder estimateBuilder) throws ContractValidateException, ContractExeException, HeaderNotFound, VMIllegalException { - long high = chainBaseManager.getDynamicPropertiesStore().getMaxFeeLimit(); + DynamicPropertiesStore dps = chainBaseManager.getDynamicPropertiesStore(); + long high = dps.getMaxFeeLimit(); trxCap.setFeeLimit(high); Transaction transaction = triggerConstantContract( @@ -2882,7 +2883,7 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, } } estimateBuilder.setTransactionExtension(builder); - estimateBuilder.setEnergyRequired(high); + estimateBuilder.setEnergyRequired((long) Math.ceil((double) high / dps.getEnergyFee())); return transaction; } @@ -2904,7 +2905,9 @@ public Transaction triggerConstantContract(TriggerSmartContract triggerSmartCont ); deployBuilder.setCallTokenValue(triggerSmartContract.getCallTokenValue()); deployBuilder.setTokenId(triggerSmartContract.getTokenId()); + long feeLimit = trxCap.getFeeLimit(); trxCap = createTransactionCapsule(deployBuilder.build(), ContractType.CreateSmartContract); + trxCap.setFeeLimit(feeLimit); } else { // call contract ContractStore contractStore = chainBaseManager.getContractStore(); byte[] contractAddress = triggerSmartContract.getContractAddress().toByteArray(); diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 16a6f1b3cfa..615a00561f7 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -2011,7 +2011,7 @@ public void estimateEnergy(TriggerSmartContract request, retBuilder.setResult(false).setCode(response_code.CONTRACT_EXE_ERROR) .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); trxExtBuilder.setResult(retBuilder); - logger.warn("When run constant call in VM, have Runtime Exception: " + e.getMessage()); + logger.warn("When run estimate energy in VM, have Runtime Exception: " + e.getMessage()); } catch (Exception e) { retBuilder.setResult(false).setCode(response_code.OTHER_ERROR) .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); From e4fac13b8ac8848de9b6450b9e429e613e63c44c Mon Sep 17 00:00:00 2001 From: Asuka Date: Sun, 25 Dec 2022 18:31:01 +0800 Subject: [PATCH 0494/1197] feat(estimateEnergy): add estimate energy for solidity service --- .../http/EstimateEnergyOnSolidityServlet.java | 33 +++++++++++++++++++ .../solidity/HttpApiOnSolidityService.java | 7 ++-- 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/EstimateEnergyOnSolidityServlet.java diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/EstimateEnergyOnSolidityServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/EstimateEnergyOnSolidityServlet.java new file mode 100644 index 00000000000..e9e403c776b --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/EstimateEnergyOnSolidityServlet.java @@ -0,0 +1,33 @@ +package org.tron.core.services.interfaceOnSolidity.http; + +import java.io.IOException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.EstimateEnergyServlet; +import org.tron.core.services.interfaceOnSolidity.WalletOnSolidity; + + +@Component +@Slf4j(topic = "API") +public class EstimateEnergyOnSolidityServlet extends EstimateEnergyServlet { + + @Autowired + private WalletOnSolidity walletOnSolidity; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> { + try { + super.doPost(request, response); + } catch (IOException e) { + logger.error("EstimateEnergyOnSolidityServlet Exception", e); + } + }); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java index 3073947368a..bddec04d6a6 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java @@ -2,13 +2,11 @@ import java.util.EnumSet; import javax.servlet.DispatcherType; -import javax.servlet.Filter; import lombok.extern.slf4j.Slf4j; import org.eclipse.jetty.server.ConnectionLimit; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.springframework.beans.factory.annotation.Autowired; import org.tron.common.application.Service; @@ -16,6 +14,7 @@ import org.tron.core.config.args.Args; import org.tron.core.services.filter.HttpApiAccessFilter; import org.tron.core.services.filter.LiteFnQueryHttpFilter; +import org.tron.core.services.interfaceOnSolidity.http.EstimateEnergyOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetAccountByIdOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetAccountOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetAssetIssueByIdOnSolidityServlet; @@ -154,6 +153,8 @@ public class HttpApiOnSolidityService implements Service { @Autowired private TriggerConstantContractOnSolidityServlet triggerConstantContractOnSolidityServlet; @Autowired + private EstimateEnergyOnSolidityServlet estimateEnergyOnSolidityServlet; + @Autowired private GetTransactionInfoByBlockNumOnSolidityServlet getTransactionInfoByBlockNumOnSolidityServlet; @Autowired @@ -258,6 +259,8 @@ public void start() { "/walletsolidity/isshieldedtrc20contractnotespent"); context.addServlet(new ServletHolder(triggerConstantContractOnSolidityServlet), "/walletsolidity/triggerconstantcontract"); + context.addServlet(new ServletHolder(estimateEnergyOnSolidityServlet), + "/walletsolidity/estimateenergy"); context.addServlet(new ServletHolder(getTransactionInfoByBlockNumOnSolidityServlet), "/walletsolidity/gettransactioninfobyblocknum"); context.addServlet(new ServletHolder(getMarketOrderByAccountOnSolidityServlet), From ca15e63bba75f7858d23806e70a919b8421c0b63 Mon Sep 17 00:00:00 2001 From: Asuka Date: Sun, 25 Dec 2022 19:58:14 +0800 Subject: [PATCH 0495/1197] feat(estimateEnergy): optimize the switch --- .../src/main/java/org/tron/core/Wallet.java | 44 ++++++++++++------- .../org/tron/core/services/RpcApiService.java | 13 ++---- .../services/http/EstimateEnergyServlet.java | 29 +++++------- .../http/TriggerConstantContractServlet.java | 9 +--- 4 files changed, 45 insertions(+), 50 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 74f13cb1750..00ab2a792a5 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2847,43 +2847,57 @@ public Transaction triggerContract(TriggerSmartContract } public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, - TransactionCapsule trxCap, Builder builder, - Return.Builder retBuilder, GrpcAPI.EstimateEnergyMessage.Builder estimateBuilder) + TransactionCapsule txCap, TransactionExtention.Builder txExtBuilder, + Return.Builder txRetBuilder, GrpcAPI.EstimateEnergyMessage.Builder estimateBuilder) throws ContractValidateException, ContractExeException, HeaderNotFound, VMIllegalException { + if (!Args.getInstance().estimateEnergyApi) { + throw new ContractValidateException("this node does not estimate energy"); + } + DynamicPropertiesStore dps = chainBaseManager.getDynamicPropertiesStore(); long high = dps.getMaxFeeLimit(); - trxCap.setFeeLimit(high); + txCap.setFeeLimit(high); Transaction transaction = triggerConstantContract( - triggerSmartContract, trxCap, builder, retBuilder); + triggerSmartContract, txCap, txExtBuilder, txRetBuilder); // If failed, return directly. if (transaction.getRet(0).getRet().equals(code.FAILED)) { - estimateBuilder.setTransactionExtension(builder); - estimateBuilder.setEnergyRequired(builder.getEnergyUsed()); + estimateBuilder.setTransactionExtension(txExtBuilder); return transaction; } - long low = getEnergyFee() * builder.getEnergyUsed(); + long low = dps.getEnergyFee() * txExtBuilder.getEnergyUsed(); - while (low + 1 < high) { + while (low + TRX_PRECISION < high) { // clean the prev exec data. - trxCap.resetResult(); - builder.clear(); - retBuilder.clear(); + txCap.resetResult(); + txExtBuilder.clear(); + txRetBuilder.clear(); long mid = (high + low) / 2; - trxCap.setFeeLimit(mid); - triggerConstantContract(triggerSmartContract, trxCap, builder, retBuilder); + txCap.setFeeLimit(mid); + triggerConstantContract(triggerSmartContract, txCap, txExtBuilder, txRetBuilder); if (transaction.getRet(0).getRet().equals(code.FAILED)) { low = mid; } else { high = mid; } } - estimateBuilder.setTransactionExtension(builder); - estimateBuilder.setEnergyRequired((long) Math.ceil((double) high / dps.getEnergyFee())); + + // Retry the binary search result + txCap.resetResult(); + txCap.setFeeLimit(high); + txExtBuilder.clear(); + txRetBuilder.clear(); + triggerConstantContract(triggerSmartContract, txCap, txExtBuilder, txRetBuilder); + + // Setting estimating result + estimateBuilder.setTransactionExtension(txExtBuilder); + if (transaction.getRet(0).getRet().equals(code.SUCESS)) { + estimateBuilder.setEnergyRequired((long) Math.ceil((double) high / dps.getEnergyFee())); + } return transaction; } diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 615a00561f7..da4cccd4757 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -45,6 +45,7 @@ import org.tron.api.GrpcAPI.EasyTransferMessage; import org.tron.api.GrpcAPI.EasyTransferResponse; import org.tron.api.GrpcAPI.EmptyMessage; +import org.tron.api.GrpcAPI.EstimateEnergyMessage; import org.tron.api.GrpcAPI.ExchangeList; import org.tron.api.GrpcAPI.ExpandedSpendingKeyMessage; import org.tron.api.GrpcAPI.IncomingViewingKeyDiversifierMessage; @@ -1979,17 +1980,11 @@ public void triggerContract(TriggerSmartContract request, @Override public void estimateEnergy(TriggerSmartContract request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); - GrpcAPI.EstimateEnergyMessage.Builder estimateBuilder - = GrpcAPI.EstimateEnergyMessage.newBuilder(); - - if (!CommonParameter.getInstance().isEstimateEnergyApi()) { - responseObserver.onNext(null); - responseObserver.onCompleted(); - return; - } + EstimateEnergyMessage.Builder estimateBuilder + = EstimateEnergyMessage.newBuilder(); try { TransactionCapsule trxCap = createTransactionCapsule(request, diff --git a/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java b/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java index 493d9928af3..3e20d92226c 100644 --- a/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java @@ -3,25 +3,23 @@ import com.alibaba.fastjson.JSONObject; import com.google.protobuf.ByteString; import io.netty.util.internal.StringUtil; - import java.io.IOException; import java.security.InvalidParameterException; import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - import lombok.extern.slf4j.Slf4j; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI; -import org.tron.common.parameter.CommonParameter; +import org.tron.api.GrpcAPI.EstimateEnergyMessage; +import org.tron.api.GrpcAPI.Return; +import org.tron.api.GrpcAPI.TransactionExtention; import org.tron.common.utils.ByteArray; import org.tron.core.Wallet; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol; -import org.tron.protos.contract.SmartContractOuterClass; +import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; @Component @Slf4j(topic = "API") @@ -49,15 +47,10 @@ protected void validateParameter(String contract) { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { - - if (!CommonParameter.getInstance().isEstimateEnergyApi()) { - return; - } - - SmartContractOuterClass.TriggerSmartContract.Builder build = SmartContractOuterClass.TriggerSmartContract.newBuilder(); - GrpcAPI.TransactionExtention.Builder trxExtBuilder = GrpcAPI.TransactionExtention.newBuilder(); - GrpcAPI.EstimateEnergyMessage.Builder estimateEnergyBuilder = GrpcAPI.EstimateEnergyMessage.newBuilder(); - GrpcAPI.Return.Builder retBuilder = GrpcAPI.Return.newBuilder(); + TriggerSmartContract.Builder build = TriggerSmartContract.newBuilder(); + TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); + EstimateEnergyMessage.Builder estimateEnergyBuilder = EstimateEnergyMessage.newBuilder(); + Return.Builder retBuilder = Return.newBuilder(); boolean visible = false; try { String contract = request.getReader().lines() @@ -89,16 +82,16 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) trx = Util.setTransactionPermissionId(jsonObject, trx); trx = Util.setTransactionExtraData(jsonObject, trx, visible); trxExtBuilder.setTransaction(trx); - retBuilder.setResult(true).setCode(GrpcAPI.Return.response_code.SUCCESS); + retBuilder.setResult(true).setCode(Return.response_code.SUCCESS); } catch (ContractValidateException e) { - retBuilder.setResult(false).setCode(GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR) + retBuilder.setResult(false).setCode(Return.response_code.CONTRACT_VALIDATE_ERROR) .setMessage(ByteString.copyFromUtf8(e.getMessage())); } catch (Exception e) { String errString = null; if (e.getMessage() != null) { errString = e.getMessage().replaceAll("[\"]", "\'"); } - retBuilder.setResult(false).setCode(GrpcAPI.Return.response_code.OTHER_ERROR) + retBuilder.setResult(false).setCode(Return.response_code.OTHER_ERROR) .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + errString)); } trxExtBuilder.setResult(retBuilder); diff --git a/framework/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java b/framework/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java index c038a3b39bb..4c4b6908a6e 100644 --- a/framework/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java @@ -73,18 +73,11 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) } else { build.setData(ByteString.copyFrom(new byte[0])); } - long feeLimit = Util.getJsonLongValue(jsonObject, "fee_limit"); - TransactionCapsule trxCap = wallet .createTransactionCapsule(build.build(), ContractType.TriggerSmartContract); - Transaction.Builder txBuilder = trxCap.getInstance().toBuilder(); - Transaction.raw.Builder rawBuilder = trxCap.getInstance().getRawData().toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - txBuilder.setRawData(rawBuilder); - Transaction trx = wallet - .triggerConstantContract(build.build(), new TransactionCapsule(txBuilder.build()), + .triggerConstantContract(build.build(),trxCap, trxExtBuilder, retBuilder); trx = Util.setTransactionPermissionId(jsonObject, trx); From 8364569f5158389dc24e04258656432240ff9f4f Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 26 Dec 2022 14:51:13 +0800 Subject: [PATCH 0496/1197] feat(DynamicEnergy): fix operations test --- .../program/invoke/ProgramInvokeMockImpl.java | 7 ++++- .../common/runtime/vm/OperationsTest.java | 30 ++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/invoke/ProgramInvokeMockImpl.java b/actuator/src/main/java/org/tron/core/vm/program/invoke/ProgramInvokeMockImpl.java index 8674608f22a..e22c5d06578 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/invoke/ProgramInvokeMockImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/program/invoke/ProgramInvokeMockImpl.java @@ -8,6 +8,7 @@ import org.tron.common.parameter.CommonParameter; import org.tron.common.runtime.vm.DataWord; import org.tron.core.capsule.ContractCapsule; +import org.tron.core.store.StoreFactory; import org.tron.core.vm.repository.Repository; import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol; @@ -45,7 +46,11 @@ public ProgramInvokeMockImpl() { } public ProgramInvokeMockImpl(byte[] op, byte[] opAddress) { - this.deposit = RepositoryImpl.createRoot(null); + this(null, op, opAddress); + } + + public ProgramInvokeMockImpl(StoreFactory storeFactory, byte[] op, byte[] opAddress) { + this.deposit = RepositoryImpl.createRoot(storeFactory); this.deposit.createAccount(opAddress, Protocol.AccountType.Normal); this.deposit.createAccount(opAddress, Protocol.AccountType.Contract); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java index 765a8b6222c..f9f586b87a6 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java @@ -2,6 +2,7 @@ import static org.junit.Assert.assertEquals; +import java.io.File; import java.util.List; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -12,15 +13,23 @@ import org.junit.Ignore; import org.junit.Test; import org.springframework.util.StringUtils; +import org.tron.common.application.TronApplicationContext; import org.tron.common.parameter.CommonParameter; import org.tron.common.runtime.InternalTransaction; +import org.tron.common.utils.FileUtil; +import org.tron.core.ChainBaseManager; +import org.tron.core.Constant; +import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.StoreFactory; import org.tron.core.vm.JumpTable; import org.tron.core.vm.Op; import org.tron.core.vm.Operation; import org.tron.core.vm.OperationRegistry; import org.tron.core.vm.VM; +import org.tron.core.vm.config.ConfigLoader; import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.program.Program; import org.tron.core.vm.program.invoke.ProgramInvokeMockImpl; @@ -32,9 +41,17 @@ public class OperationsTest { private ProgramInvokeMockImpl invoke; private Program program; private final JumpTable jumpTable = OperationRegistry.newTronV10OperationSet(); + private static ChainBaseManager chainBaseManager; + private static String dbPath; + private static TronApplicationContext context; @BeforeClass public static void init() { + dbPath = "output_" + OperationsTest.class.getName(); + Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + Manager manager = context.getBean(Manager.class); + chainBaseManager = manager.getChainBaseManager(); CommonParameter.getInstance().setDebug(true); VMConfig.initAllowTvmTransferTrc10(1); VMConfig.initAllowTvmConstantinople(1); @@ -46,7 +63,15 @@ public static void init() { @AfterClass public static void destroy() { + ConfigLoader.disable = false; + VMConfig.initVmHardFork(false); Args.clearParam(); + context.destroy(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.error("Release resources failure."); + } VMConfig.initAllowTvmTransferTrc10(0); VMConfig.initAllowTvmConstantinople(0); VMConfig.initAllowTvmSolidity059(0); @@ -92,9 +117,12 @@ public void testStackOverFlow() { @SneakyThrows private Program buildEmptyContext(byte[] ops) { + StoreFactory.init(); + StoreFactory storeFactory = StoreFactory.getInstance(); + storeFactory.setChainBaseManager(chainBaseManager); Program context = new Program( ops, ops, - new ProgramInvokeMockImpl(ops, ops), + new ProgramInvokeMockImpl(storeFactory, ops, ops), new InternalTransaction( Protocol.Transaction.getDefaultInstance(), InternalTransaction.TrxType.TRX_UNKNOWN_TYPE)); From e80cc2967a64bf0eff8e17701852d1b1f867004d Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 26 Dec 2022 16:06:58 +0800 Subject: [PATCH 0497/1197] style: fix check style --- framework/src/main/java/org/tron/core/services/http/Util.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 5c8c6e13be3..1a4b747ac5b 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -162,7 +162,8 @@ public static String printTransactionExtention(TransactionExtention transactionE return jsonObject.toJSONString(); } - public static String printEstimateEnergyMessage(GrpcAPI.EstimateEnergyMessage message, boolean selfType) { + public static String printEstimateEnergyMessage(GrpcAPI.EstimateEnergyMessage message, + boolean selfType) { String string = JsonFormat.printToString(message, selfType); JSONObject jsonObject = JSONObject.parseObject(string); From 2cc467a3d01d1859837dcf847c604f78fd4a4536 Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 26 Dec 2022 18:26:19 +0800 Subject: [PATCH 0498/1197] feat(DynamicEnergy): drop trigger_base parameter --- .../org/tron/core/actuator/VMActuator.java | 14 ------------- .../org/tron/core/utils/ProposalUtil.java | 14 +------------ .../core/store/DynamicPropertiesStore.java | 20 ------------------- .../common/parameter/CommonParameter.java | 4 ---- .../src/main/java/org/tron/core/Constant.java | 2 -- .../src/main/java/org/tron/core/Wallet.java | 5 ----- .../java/org/tron/core/config/args/Args.java | 8 -------- .../tron/core/consensus/ProposalService.java | 4 ---- 8 files changed, 1 insertion(+), 70 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 6a14f2176db..336af2e0181 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -4,7 +4,6 @@ import static java.lang.Math.min; import static org.apache.commons.lang3.ArrayUtils.getLength; import static org.apache.commons.lang3.ArrayUtils.isNotEmpty; -import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; import com.google.protobuf.ByteString; import java.math.BigInteger; @@ -187,19 +186,6 @@ public void execute(Object object) throws ContractExeException { throw e; } - if (rootRepository.getDynamicPropertiesStore().supportAllowDynamicEnergy()) { - // only add trigger_energy_base when type is call. - if (TrxType.TRX_CONTRACT_CALL_TYPE == trxType) { - long energyFactor = program.updateContextContractFactor(); - if (energyFactor > DYNAMIC_ENERGY_FACTOR_DECIMAL) { - program.spendEnergy( - rootRepository.getDynamicPropertiesStore().getDynamicEnergyTriggerBase() - * energyFactor / DYNAMIC_ENERGY_FACTOR_DECIMAL, - "DYNAMIC_ENERGY_TRIGGER_BASE"); - } - } - } - VM.play(program, OperationRegistry.getTable()); result = program.getResult(); diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 132cd68c988..f73a631e286 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -673,17 +673,6 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } - case DYNAMIC_ENERGY_TRIGGER_BASE: { - if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7)) { - throw new ContractValidateException( - "Bad chain parameter id [DYNAMIC_ENERGY_TRIGGER_BASE]"); - } - - if (value < 0 || value > LONG_VALUE) { - throw new ContractValidateException(LONG_VALUE_ERROR); - } - break; - } default: break; } @@ -756,8 +745,7 @@ public enum ProposalType { // current value, value range ALLOW_DYNAMIC_ENERGY(72), // 0, 1 DYNAMIC_ENERGY_THRESHOLD(73), // 0, [0, LONG] DYNAMIC_ENERGY_INCREASE_FACTOR(74), // 0, [100, 10_000] - DYNAMIC_ENERGY_MAX_FACTOR(75), // 0, [100, 10_000] - DYNAMIC_ENERGY_TRIGGER_BASE(76); // 0, [0, LONG] + DYNAMIC_ENERGY_MAX_FACTOR(75); // 0, [100, 10_000] private long code; diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 5554035122d..d2870b45e2b 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -200,8 +200,6 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking "DYNAMIC_ENERGY_INCREASE_FACTOR".getBytes(); private static final byte[] DYNAMIC_ENERGY_MAX_FACTOR = "DYNAMIC_ENERGY_MAX_FACTOR".getBytes(); - private static final byte[] DYNAMIC_ENERGY_TRIGGER_BASE = - "DYNAMIC_ENERGY_TRIGGER_BASE".getBytes(); private static final byte[] UNFREEZE_DELAY_DAYS = "UNFREEZE_DELAY_DAYS".getBytes(); @@ -943,12 +941,6 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { } catch (IllegalArgumentException e) { this.saveDynamicEnergyMaxFactor(CommonParameter.getInstance().getDynamicEnergyMaxFactor()); } - - try { - this.getDynamicEnergyTriggerBase(); - } catch (IllegalArgumentException e) { - this.saveDynamicEnergyTriggerBase(CommonParameter.getInstance().getDynamicEnergyTriggerBase()); - } } public String intArrayToString(int[] a) { @@ -2730,18 +2722,6 @@ public void saveDynamicEnergyMaxFactor(long value) { this.put(DYNAMIC_ENERGY_MAX_FACTOR, new BytesCapsule(ByteArray.fromLong(value))); } - public long getDynamicEnergyTriggerBase() { - return Optional.ofNullable(getUnchecked(DYNAMIC_ENERGY_TRIGGER_BASE)) - .map(BytesCapsule::getData) - .map(ByteArray::toLong) - .orElseThrow( - () -> new IllegalArgumentException("not found DYNAMIC_ENERGY_TRIGGER_BASE")); - } - - public void saveDynamicEnergyTriggerBase(long value) { - this.put(DYNAMIC_ENERGY_TRIGGER_BASE, new BytesCapsule(ByteArray.fromLong(value))); - } - public boolean allowNewReward() { return getAllowNewReward() == 1; } diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 37803c03b83..a90c1899535 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -601,10 +601,6 @@ public class CommonParameter { @Setter public long dynamicEnergyMaxFactor = DYNAMIC_ENERGY_FACTOR_DECIMAL; - @Getter - @Setter - public long dynamicEnergyTriggerBase = 0L; - private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index b85c94a52c9..dced537407a 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -335,8 +335,6 @@ public class Constant { public static final int DYNAMIC_ENERGY_DECREASE_MAX_CYCLE = 10; - public static final String DYNAMIC_ENERGY_TRIGGER_BASE = "committee.dynamicEnergyTriggerBase"; - public static final String LOCAL_HOST = "127.0.0.1"; public static final String NODE_SHUTDOWN_BLOCK_TIME = "node.shutdown.BlockTime"; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 00ab2a792a5..5b075b983de 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1313,11 +1313,6 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getDynamicEnergyMaxFactor()) .build()); - builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() - .setKey("getDynamicEnergyTriggerBase") - .setValue(dbManager.getDynamicPropertiesStore().getDynamicEnergyTriggerBase()) - .build()); - return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index d5295bfc759..49fd7eb09c1 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1111,14 +1111,6 @@ public static void setParam(final String[] args, final String confFileName) { Math.max(PARAMETER.dynamicEnergyMaxFactor, DYNAMIC_ENERGY_FACTOR_DECIMAL); } - if (config.hasPath(Constant.DYNAMIC_ENERGY_TRIGGER_BASE)) { - PARAMETER.dynamicEnergyTriggerBase = config.getLong(Constant.DYNAMIC_ENERGY_TRIGGER_BASE); - PARAMETER.dynamicEnergyTriggerBase = - Math.min(PARAMETER.dynamicEnergyTriggerBase, 100_000_000_000_000_000L); - PARAMETER.dynamicEnergyTriggerBase = - Math.max(PARAMETER.dynamicEnergyTriggerBase, 0); - } - logConfig(); } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index cbe01247c6f..fb4c24eee40 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -339,10 +339,6 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveDynamicEnergyMaxFactor(entry.getValue()); break; } - case DYNAMIC_ENERGY_TRIGGER_BASE: { - manager.getDynamicPropertiesStore().saveDynamicEnergyTriggerBase(entry.getValue()); - break; - } default: find = false; break; From 2c80b9d83ce1f6c182f93d2890d703c972d7b60b Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Mon, 26 Dec 2022 21:23:36 +0800 Subject: [PATCH 0499/1197] feat(DynamicEnergy): optimize program result add energy_origin and energy_penalty --- actuator/src/main/java/org/tron/core/vm/VM.java | 12 +++++++++--- .../main/java/org/tron/core/vm/program/Program.java | 10 ++++++++++ .../java/org/tron/common/runtime/ProgramResult.java | 13 +++++++++++++ framework/src/main/java/org/tron/core/Wallet.java | 2 ++ protocol/src/main/protos/api/api.proto | 2 ++ 5 files changed, 36 insertions(+), 3 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/VM.java b/actuator/src/main/java/org/tron/core/vm/VM.java index de7378847c6..e36f8bcbd31 100644 --- a/actuator/src/main/java/org/tron/core/vm/VM.java +++ b/actuator/src/main/java/org/tron/core/vm/VM.java @@ -58,11 +58,17 @@ public static void play(Program program, JumpTable jumpTable) { energyUsage += actualEnergy; if (factor > DYNAMIC_ENERGY_FACTOR_DECIMAL) { - energy = energy - actualEnergy - + actualEnergy * factor / DYNAMIC_ENERGY_FACTOR_DECIMAL; + long penalty = + actualEnergy * factor / DYNAMIC_ENERGY_FACTOR_DECIMAL - actualEnergy; + program.spendEnergyWithPenalty(energy, penalty, opName); + } else { + program.spendEnergy(energy, opName); } + + } else { + program.spendEnergy(energy, opName); } - program.spendEnergy(energy, opName); + /* check if cpu time out */ program.checkCPUTimeLimit(opName); diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index a38d0145728..f5ca691382d 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -1108,6 +1108,16 @@ public void spendEnergy(long energyValue, String opName) { getResult().spendEnergy(energyValue); } + public void spendEnergyWithPenalty(long origin, long penalty, String opName) { + if (getEnergylimitLeftLong() < origin + penalty) { + throw new OutOfEnergyException( + "Not enough energy for '%s' operation executing: curInvokeEnergyLimit[%d]," + + " curOpEnergy[%d], penaltyEnergy[%d], usedEnergy[%d]", + opName, invoke.getEnergyLimit(), origin, penalty, getResult().getEnergyUsed()); + } + getResult().spendEnergyWithPenalty(origin, penalty); + } + public void checkCPUTimeLimit(String opName) { if (CommonParameter.getInstance().isDebug()) { diff --git a/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java b/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java index 112b7f921af..adc450dabb2 100644 --- a/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java +++ b/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java @@ -25,6 +25,12 @@ public class ProgramResult { private long energyUsed = 0; //private long futureRefund = 0; + @Getter + private long energyPenalty = 0; + + @Getter + private long energyOrigin = 0; + private byte[] hReturn = EMPTY_BYTE_ARRAY; private byte[] contractAddress = EMPTY_BYTE_ARRAY; private RuntimeException exception; @@ -62,6 +68,13 @@ public static ProgramResult createEmpty() { public void spendEnergy(long energy) { energyUsed += energy; + energyOrigin += energy; + } + + public void spendEnergyWithPenalty(long origin, long penalty) { + energyOrigin += origin; + energyPenalty += penalty; + energyUsed += origin + penalty; } public void setRevert() { diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 5b075b983de..d5453a70cc8 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2960,6 +2960,8 @@ public Transaction callConstantContract(TransactionCapsule trxCap, TransactionResultCapsule ret = new TransactionResultCapsule(); builder.setEnergyUsed(result.getEnergyUsed()); + builder.setEnergyOrigin(result.getEnergyOrigin()); + builder.setEnergyPenalty(result.getEnergyPenalty()); builder.addConstantResult(ByteString.copyFrom(result.getHReturn())); result.getLogInfoList().forEach(logInfo -> builder.addLogs(LogInfo.buildLog(logInfo))); diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 9947502e9ee..e59d8f2efb0 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -1311,6 +1311,8 @@ message TransactionExtention { int64 energy_used = 5; repeated TransactionInfo.Log logs = 6; repeated InternalTransaction internal_transactions = 7; + int64 energy_origin = 8; + int64 energy_penalty = 9; } message EstimateEnergyMessage { From 92892a7625bf99cd2b9156e76521d0a8785b004d Mon Sep 17 00:00:00 2001 From: Asuka Date: Tue, 27 Dec 2022 11:49:52 +0800 Subject: [PATCH 0500/1197] feat(DynamicEnergy): change factor decimal and limit it up to 100% --- .../org/tron/core/utils/ProposalUtil.java | 10 +-- .../src/main/java/org/tron/core/vm/VM.java | 5 +- .../org/tron/core/vm/program/Program.java | 7 +- .../core/capsule/ContractStateCapsule.java | 85 +++++++++---------- .../src/main/java/org/tron/core/Constant.java | 6 +- 5 files changed, 52 insertions(+), 61 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index f73a631e286..30c73eb626f 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -1,6 +1,5 @@ package org.tron.core.utils; -import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_RANGE; import org.tron.common.utils.ForkController; @@ -652,10 +651,10 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, "Bad chain parameter id [DYNAMIC_ENERGY_INCREASE_FACTOR]"); } - if (value < DYNAMIC_ENERGY_FACTOR_DECIMAL || value > DYNAMIC_ENERGY_FACTOR_RANGE) { + if (value < 0 || value > DYNAMIC_ENERGY_FACTOR_RANGE) { throw new ContractValidateException( "This value[DYNAMIC_ENERGY_INCREASE_FACTOR] " - + "is only allowed to be in the range 100-10000" + + "is only allowed to be in the range 0-10000" ); } break; @@ -666,9 +665,10 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, "Bad chain parameter id [DYNAMIC_ENERGY_MAX_FACTOR]"); } - if (value < DYNAMIC_ENERGY_FACTOR_DECIMAL || value > DYNAMIC_ENERGY_FACTOR_RANGE) { + if (value < 0 || value > DYNAMIC_ENERGY_FACTOR_RANGE) { throw new ContractValidateException( - "This value[DYNAMIC_ENERGY_MAX_FACTOR] is only allowed to be in the range 100-10000" + "This value[DYNAMIC_ENERGY_MAX_FACTOR] " + + "is only allowed to be in the range 0-10000" ); } break; diff --git a/actuator/src/main/java/org/tron/core/vm/VM.java b/actuator/src/main/java/org/tron/core/vm/VM.java index e36f8bcbd31..6fda100a62b 100644 --- a/actuator/src/main/java/org/tron/core/vm/VM.java +++ b/actuator/src/main/java/org/tron/core/vm/VM.java @@ -3,6 +3,7 @@ import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; import com.google.common.collect.ImmutableSet; +import java.util.Set; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.springframework.util.StringUtils; @@ -15,7 +16,7 @@ @Slf4j(topic = "VM") public class VM { - private static final ImmutableSet CALL_OPS = ImmutableSet.of(Op.CALL, Op.STATICCALL, + private static final Set CALL_OPS = ImmutableSet.of(Op.CALL, Op.STATICCALL, Op.DELEGATECALL, Op.CALLCODE, Op.CALLTOKEN); public static void play(Program program, JumpTable jumpTable) { @@ -52,7 +53,7 @@ public static void play(Program program, JumpTable jumpTable) { if (allowDynamicEnergy) { long actualEnergy = energy; // CALL Ops have special calculation on energy. - if (CALL_OPS.contains(op)) { + if (CALL_OPS.contains(op.getOpcode())) { actualEnergy = energy - program.getAdjustedCallEnergy().longValueSafe(); } energyUsage += actualEnergy; diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index f5ca691382d..c9de3cfe4af 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -8,7 +8,6 @@ import static org.apache.commons.lang3.ArrayUtils.isNotEmpty; import static org.apache.commons.lang3.ArrayUtils.nullToEmpty; import static org.tron.common.utils.ByteUtil.stripLeadingZeroes; -import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import com.google.protobuf.ByteString; @@ -91,7 +90,6 @@ import org.tron.protos.Protocol; import org.tron.protos.Protocol.AccountType; import org.tron.protos.contract.Common; -import org.tron.protos.contract.SmartContractOuterClass; import org.tron.protos.contract.SmartContractOuterClass.SmartContract; import org.tron.protos.contract.SmartContractOuterClass.SmartContract.Builder; @@ -2224,10 +2222,7 @@ public long updateContextContractFactor() { contractState.updateContractState(getContextAddress(), contractStateCapsule); } else { if (contractStateCapsule.catchUpToCycle( - contractState.getDynamicPropertiesStore().getCurrentCycleNumber(), - contractState.getDynamicPropertiesStore().getDynamicEnergyThreshold(), - contractState.getDynamicPropertiesStore().getDynamicEnergyIncreaseFactor(), - contractState.getDynamicPropertiesStore().getDynamicEnergyMaxFactor())) { + contractState.getDynamicPropertiesStore())) { contractState.updateContractState( getContextAddress(), contractStateCapsule); diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java index 125da304f8d..6babc2d619f 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java @@ -1,12 +1,11 @@ package org.tron.core.capsule; import static org.tron.core.Constant.DYNAMIC_ENERGY_DECREASE_DIVISION; -import static org.tron.core.Constant.DYNAMIC_ENERGY_DECREASE_MAX_CYCLE; import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; -import static org.tron.core.Constant.DYNAMIC_ENERY_DECREASE_FACTOR_MIN; import com.google.protobuf.InvalidProtocolBufferException; import lombok.extern.slf4j.Slf4j; +import org.tron.core.store.DynamicPropertiesStore; import org.tron.protos.contract.SmartContractOuterClass; import org.tron.protos.contract.SmartContractOuterClass.ContractState; @@ -28,11 +27,7 @@ public ContractStateCapsule(byte[] data) { } public ContractStateCapsule(long currentCycle) { - this.contractState = ContractState.newBuilder() - .setUpdateCycle(currentCycle) - .setEnergyFactor(DYNAMIC_ENERGY_FACTOR_DECIMAL) - .setEnergyUsage(0L) - .build(); + reset(currentCycle); } @Override @@ -77,69 +72,73 @@ public void addUpdateCycle(long toAdd) { setUpdateCycle(getUpdateCycle() + toAdd); } + public boolean catchUpToCycle(DynamicPropertiesStore dps) { + return catchUpToCycle( + dps.getCurrentCycleNumber(), + dps.getDynamicEnergyThreshold(), + dps.getDynamicEnergyIncreaseFactor(), + dps.getDynamicEnergyMaxFactor() + ); + } + public boolean catchUpToCycle( - long newCycle, long threshold, long increaseFactor, long maxFactor) { + long newCycle, long threshold, long increaseFactor, long maxFactor + ) { long lastCycle = getUpdateCycle(); + + // Updated within this cycle if (lastCycle == newCycle) { return false; } - if (lastCycle > newCycle || lastCycle == 0L - || newCycle - lastCycle >= DYNAMIC_ENERGY_DECREASE_MAX_CYCLE) { - this.contractState = this.contractState.toBuilder() - .setUpdateCycle(newCycle) - .setEnergyUsage(0L) - .setEnergyFactor(DYNAMIC_ENERGY_FACTOR_DECIMAL) - .build(); + // Guard judge and uninitialized state + if (lastCycle > newCycle || lastCycle == 0L) { + reset(newCycle); return true; } - // increase first + final long decimal = DYNAMIC_ENERGY_FACTOR_DECIMAL; + + // Increase the last cycle if (getEnergyUsage() >= threshold) { lastCycle += 1; - this.contractState = this.contractState.toBuilder() + this.contractState = ContractState.newBuilder() .setUpdateCycle(lastCycle) - .setEnergyUsage(0L) .setEnergyFactor(Math.min( maxFactor, - getEnergyFactor() * increaseFactor / DYNAMIC_ENERGY_FACTOR_DECIMAL)) + getEnergyFactor() * (decimal + increaseFactor) / decimal)) .build(); } - // decrease + // No need to decrease long cycleCount = newCycle - lastCycle; if (cycleCount <= 0) { return true; } - // no need to decrease - if (getEnergyFactor() <= DYNAMIC_ENERGY_FACTOR_DECIMAL) { - this.contractState = this.contractState.toBuilder() - .setUpdateCycle(newCycle) - .setEnergyUsage(0L) - .setEnergyFactor(DYNAMIC_ENERGY_FACTOR_DECIMAL) - .build(); - return true; - } - - double decreaseFactor = Math.max( - DYNAMIC_ENERY_DECREASE_FACTOR_MIN, - 1 - ((double) increaseFactor / DYNAMIC_ENERGY_FACTOR_DECIMAL - 1) - / DYNAMIC_ENERGY_DECREASE_DIVISION); - if (cycleCount > 1) { - decreaseFactor = Math.pow( - decreaseFactor, - cycleCount); - } + // Calc the decrease percent (decrease factor [75% ~ 100%]) + double decreaseFactor = 1 - (double) increaseFactor / decimal + / DYNAMIC_ENERGY_DECREASE_DIVISION; + double decreasePercent = Math.pow(decreaseFactor, cycleCount); - this.contractState = this.contractState.toBuilder() + // Decrease to this cycle + // (If long time no tx and factor is 100%, + // we just calc it again and result factor is still 100%. + // That means we merge this special case to normal cases) + this.contractState = ContractState.newBuilder() .setUpdateCycle(newCycle) - .setEnergyUsage(0L) .setEnergyFactor(Math.max( - DYNAMIC_ENERGY_FACTOR_DECIMAL, - (long) (getEnergyFactor() * decreaseFactor))) + decimal, + (long) (getEnergyFactor() * decreasePercent))) .build(); return true; } + + public void reset(long latestCycle) { + this.contractState = ContractState.newBuilder() + .setUpdateCycle(latestCycle) + .setEnergyFactor(DYNAMIC_ENERGY_FACTOR_DECIMAL) + .build(); + } } diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index dced537407a..1ae965c87f9 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -325,16 +325,12 @@ public class Constant { public static final String DYNAMIC_ENERGY_MAX_FACTOR = "committee.dynamicEnergyMaxFactor"; - public static final long DYNAMIC_ENERGY_FACTOR_DECIMAL = 100L; + public static final long DYNAMIC_ENERGY_FACTOR_DECIMAL = 10_000L; public static final long DYNAMIC_ENERGY_FACTOR_RANGE = 10_000L; public static final int DYNAMIC_ENERGY_DECREASE_DIVISION = 4; - public static final double DYNAMIC_ENERY_DECREASE_FACTOR_MIN = 0.5; - - public static final int DYNAMIC_ENERGY_DECREASE_MAX_CYCLE = 10; - public static final String LOCAL_HOST = "127.0.0.1"; public static final String NODE_SHUTDOWN_BLOCK_TIME = "node.shutdown.BlockTime"; From 0d76f952bb94462db4fc048e62459c34d49fbe2c Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Tue, 27 Dec 2022 11:32:01 +0800 Subject: [PATCH 0501/1197] feat(DynamicEnergy): optimize estimate energy response --- framework/src/main/java/org/tron/core/Wallet.java | 4 ++-- .../main/java/org/tron/core/services/RpcApiService.java | 2 +- .../tron/core/services/http/EstimateEnergyServlet.java | 2 +- .../src/main/java/org/tron/core/services/http/Util.java | 9 +-------- .../org/tron/core/services/jsonrpc/TronJsonRpcImpl.java | 2 +- protocol/src/main/protos/api/api.proto | 2 +- 6 files changed, 7 insertions(+), 14 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index d5453a70cc8..00dfb699990 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2859,7 +2859,7 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, // If failed, return directly. if (transaction.getRet(0).getRet().equals(code.FAILED)) { - estimateBuilder.setTransactionExtension(txExtBuilder); + estimateBuilder.setResult(txRetBuilder); return transaction; } @@ -2889,7 +2889,7 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, triggerConstantContract(triggerSmartContract, txCap, txExtBuilder, txRetBuilder); // Setting estimating result - estimateBuilder.setTransactionExtension(txExtBuilder); + estimateBuilder.setResult(txRetBuilder); if (transaction.getRet(0).getRet().equals(code.SUCESS)) { estimateBuilder.setEnergyRequired((long) Math.ceil((double) high / dps.getEnergyFee())); } diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index da4cccd4757..6ffb449f412 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -2013,7 +2013,7 @@ public void estimateEnergy(TriggerSmartContract request, trxExtBuilder.setResult(retBuilder); logger.warn("unknown exception caught: " + e.getMessage(), e); } finally { - estimateBuilder.setTransactionExtension(trxExtBuilder); + estimateBuilder.setResult(retBuilder); responseObserver.onNext(estimateBuilder.build()); responseObserver.onCompleted(); } diff --git a/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java b/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java index 3e20d92226c..5dcf869af12 100644 --- a/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java @@ -95,7 +95,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + errString)); } trxExtBuilder.setResult(retBuilder); - estimateEnergyBuilder.setTransactionExtension(trxExtBuilder); + estimateEnergyBuilder.setResult(retBuilder); response.getWriter().println( Util.printEstimateEnergyMessage(estimateEnergyBuilder.build(), visible)); } diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 1a4b747ac5b..6c8ce0b832c 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -164,14 +164,7 @@ public static String printTransactionExtention(TransactionExtention transactionE public static String printEstimateEnergyMessage(GrpcAPI.EstimateEnergyMessage message, boolean selfType) { - String string = JsonFormat.printToString(message, selfType); - JSONObject jsonObject = JSONObject.parseObject(string); - - String extension = printTransactionExtention(message.getTransactionExtension(), selfType); - JSONObject extensionObject = JSONObject.parseObject(extension); - - jsonObject.put(TRANSACTION_EXTENSION, extensionObject); - return jsonObject.toJSONString(); + return JsonFormat.printToString(message, selfType); } public static String printTransactionSignWeight(TransactionSignWeight transactionSignWeight, diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 8571e601cef..48d36f9df07 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -415,7 +415,7 @@ private void estimateEnergy(byte[] ownerAddressByte, byte[] contractAddressByte, trxExtBuilder.setTxid(trxCap.getTransactionId().getByteString()); trxExtBuilder.setResult(retBuilder); retBuilder.setResult(true).setCode(response_code.SUCCESS); - estimateBuilder.setTransactionExtension(trxExtBuilder); + estimateBuilder.setResult(retBuilder); } diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index e59d8f2efb0..81bbf42e51e 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -1316,7 +1316,7 @@ message TransactionExtention { } message EstimateEnergyMessage { - TransactionExtention transactionExtension = 1; + Return result = 1; int64 energy_required = 2; } From cd77191ecc6b1f1e5f78a08b0b611e4022eefdf1 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Tue, 27 Dec 2022 12:15:56 +0800 Subject: [PATCH 0502/1197] feat(DynamicEnergy): optimize dynamic energy penalty in receipts --- .../java/org/tron/common/runtime/ProgramResult.java | 11 +++++++---- .../java/org/tron/core/capsule/ReceiptCapsule.java | 8 ++++++++ .../main/java/org/tron/core/db/TransactionTrace.java | 8 ++++++++ framework/src/main/java/org/tron/core/Wallet.java | 3 +-- protocol/src/main/protos/api/api.proto | 3 +-- protocol/src/main/protos/core/Tron.proto | 1 + 6 files changed, 26 insertions(+), 8 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java b/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java index adc450dabb2..5c6c0d12294 100644 --- a/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java +++ b/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java @@ -16,7 +16,6 @@ import org.tron.common.logsfilter.trigger.ContractTrigger; import org.tron.common.runtime.vm.DataWord; import org.tron.common.runtime.vm.LogInfo; -import org.tron.common.utils.ByteArraySet; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.protos.Protocol.Transaction.Result.contractResult; @@ -29,7 +28,7 @@ public class ProgramResult { private long energyPenalty = 0; @Getter - private long energyOrigin = 0; + private long energyPenaltyTotal = 0; private byte[] hReturn = EMPTY_BYTE_ARRAY; private byte[] contractAddress = EMPTY_BYTE_ARRAY; @@ -68,12 +67,11 @@ public static ProgramResult createEmpty() { public void spendEnergy(long energy) { energyUsed += energy; - energyOrigin += energy; } public void spendEnergyWithPenalty(long origin, long penalty) { - energyOrigin += origin; energyPenalty += penalty; + energyPenaltyTotal += penalty; energyUsed += origin + penalty; } @@ -89,6 +87,10 @@ public void refundEnergy(long energy) { energyUsed -= energy; } + public void addTotalPenalty(long penalty) { + energyPenaltyTotal += penalty; + } + public byte[] getContractAddress() { return Arrays.copyOf(contractAddress, contractAddress.length); } @@ -243,6 +245,7 @@ public void merge(ProgramResult another) { if (another.getException() == null && !another.isRevert()) { addDeleteAccounts(another.getDeleteAccounts()); addLogInfos(another.getLogInfoList()); + addTotalPenalty(another.getEnergyPenaltyTotal()); //addFutureRefund(another.getFutureRefund()); //addTouchAccounts(another.getTouchedAccounts()); } diff --git a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index 5b362fae120..852196fb455 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -129,6 +129,14 @@ public void setEnergyUsageTotal(long energyUsage) { this.receipt = this.receipt.toBuilder().setEnergyUsageTotal(energyUsage).build(); } + public long getEnergyPenaltyTotal() { + return this.receipt.getEnergyPenaltyTotal(); + } + + public void setEnergyPenaltyTotal(long penalty) { + this.receipt = this.receipt.toBuilder().setEnergyPenaltyTotal(penalty).build(); + } + public long getNetUsage() { return this.receipt.getNetUsage(); } diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java index bf00c70e4e5..3301a57133b 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java @@ -158,6 +158,13 @@ public void setBill(long energyUsage) { receipt.setEnergyUsageTotal(energyUsage); } + public void setPenalty(long energyPenalty) { + if (energyPenalty < 0) { + energyPenalty = 0L; + } + receipt.setEnergyPenaltyTotal(energyPenalty); + } + //set net bill public void setNetBill(long netUsage, long netFee) { receipt.setNetUsage(netUsage); @@ -179,6 +186,7 @@ public void exec() /* VM execute */ runtime.execute(transactionContext); setBill(transactionContext.getProgramResult().getEnergyUsed()); + setPenalty(transactionContext.getProgramResult().getEnergyPenaltyTotal()); // if (TrxType.TRX_PRECOMPILED_TYPE != trxType) { // if (contractResult.OUT_OF_TIME diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 00dfb699990..23fb41bc82a 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2960,8 +2960,7 @@ public Transaction callConstantContract(TransactionCapsule trxCap, TransactionResultCapsule ret = new TransactionResultCapsule(); builder.setEnergyUsed(result.getEnergyUsed()); - builder.setEnergyOrigin(result.getEnergyOrigin()); - builder.setEnergyPenalty(result.getEnergyPenalty()); + builder.setEnergyPenalty(result.getEnergyPenaltyTotal()); builder.addConstantResult(ByteString.copyFrom(result.getHReturn())); result.getLogInfoList().forEach(logInfo -> builder.addLogs(LogInfo.buildLog(logInfo))); diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 81bbf42e51e..394cc3adf56 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -1311,8 +1311,7 @@ message TransactionExtention { int64 energy_used = 5; repeated TransactionInfo.Log logs = 6; repeated InternalTransaction internal_transactions = 7; - int64 energy_origin = 8; - int64 energy_penalty = 9; + int64 energy_penalty = 8; } message EstimateEnergyMessage { diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index ed3cd8b4698..e6aac408f95 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -321,6 +321,7 @@ message ResourceReceipt { int64 net_usage = 5; int64 net_fee = 6; Transaction.Result.contractResult result = 7; + int64 energy_penalty_total = 8; } message MarketOrderDetail { From 849517e661365d551680be10aabc2c48a5a706a1 Mon Sep 17 00:00:00 2001 From: Asuka Date: Tue, 27 Dec 2022 15:10:34 +0800 Subject: [PATCH 0503/1197] fix(unit-test): catch up method test --- .../core/capsule/ContractStateCapsule.java | 2 +- .../capsule/ContractStateCapsuleTest.java | 82 ++++++++----------- 2 files changed, 36 insertions(+), 48 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java index 6babc2d619f..1c490b66f59 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java @@ -105,7 +105,7 @@ public boolean catchUpToCycle( this.contractState = ContractState.newBuilder() .setUpdateCycle(lastCycle) .setEnergyFactor(Math.min( - maxFactor, + decimal + maxFactor, getEnergyFactor() * (decimal + increaseFactor) / decimal)) .build(); } diff --git a/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java index f4fb616878f..6035905cb96 100644 --- a/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java @@ -11,151 +11,139 @@ public void testCatchUpCycle() { ContractStateCapsule capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(150L) + .setEnergyFactor(15_000L) .setUpdateCycle(1000L) .build()); - Assert.assertFalse(capsule.catchUpToCycle(1000L, 2_000_000L, 120, 200)); + Assert.assertFalse(capsule.catchUpToCycle(1000L, 2_000_000L, 2_000L, 10_00L)); Assert.assertEquals(1000L, capsule.getUpdateCycle()); Assert.assertEquals(1_000_000L, capsule.getEnergyUsage()); - Assert.assertEquals(150L, capsule.getEnergyFactor()); + Assert.assertEquals(15_000L, capsule.getEnergyFactor()); - Assert.assertTrue(capsule.catchUpToCycle(1010L, 1_000_000L, 110, 200)); + Assert.assertTrue(capsule.catchUpToCycle(1010L, 1_000_000L, 1_000L, 10_000L)); Assert.assertEquals(1010L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(100L, capsule.getEnergyFactor()); + Assert.assertEquals(13_137L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(150L) + .setEnergyFactor(15_000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1009L, 1_000_000L, 110, 200)); - Assert.assertEquals(1009L, capsule.getUpdateCycle()); - Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(134L, capsule.getEnergyFactor()); - - capsule = new ContractStateCapsule( - SmartContractOuterClass.ContractState.newBuilder() - .setEnergyUsage(1_000_000L) - .setEnergyFactor(150L) - .setUpdateCycle(1000L) - .build()); - - Assert.assertTrue(capsule.catchUpToCycle(1001L, 2_000_000L, 120, 200)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 2_000_000L, 2_000L, 10_000L)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(142L, capsule.getEnergyFactor()); + Assert.assertEquals(14_250L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(150L) + .setEnergyFactor(15_000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 120, 200)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 2_000L, 10_000L)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(180L, capsule.getEnergyFactor()); + Assert.assertEquals(18_000L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(150L) + .setEnergyFactor(15_000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 150, 200)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 5_000L, 10_000L)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(200L, capsule.getEnergyFactor()); + Assert.assertEquals(20_000L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(150L) + .setEnergyFactor(15_000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1002L, 1_000_000L, 150, 200)); + Assert.assertTrue(capsule.catchUpToCycle(1002L, 1_000_000L, 5_000L, 10_000L)); Assert.assertEquals(1002L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(175L, capsule.getEnergyFactor()); + Assert.assertEquals(17_500L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(150L) + .setEnergyFactor(15_000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1003L, 1_000_000L, 150, 200)); + Assert.assertTrue(capsule.catchUpToCycle(1003L, 1_000_000L, 5_000L, 10_000L)); Assert.assertEquals(1003L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(153L, capsule.getEnergyFactor()); + Assert.assertEquals(15_312L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(150L) + .setEnergyFactor(15_000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1004L, 1_000_000L, 150, 200)); + Assert.assertTrue(capsule.catchUpToCycle(1004L, 1_000_000L, 5_000L, 10_000L)); Assert.assertEquals(1004L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(133L, capsule.getEnergyFactor()); + Assert.assertEquals(13_398L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(150L) + .setEnergyFactor(15_000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1005L, 1_000_000L, 150, 200)); + Assert.assertTrue(capsule.catchUpToCycle(1005L, 1_000_000L, 5_000L, 10_000L)); Assert.assertEquals(1005L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(117L, capsule.getEnergyFactor()); + Assert.assertEquals(11_723L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(150L) + .setEnergyFactor(15_000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1005L, 1_000_000L, 150, 200)); + Assert.assertTrue(capsule.catchUpToCycle(1005L, 1_000_000L, 5_000L, 10_000L)); Assert.assertEquals(1005L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(117L, capsule.getEnergyFactor()); + Assert.assertEquals(11_723L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(150L) + .setEnergyFactor(15_000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1006L, 1_000_000L, 150, 200)); + Assert.assertTrue(capsule.catchUpToCycle(1006L, 1_000_000L, 5_000L, 10_000L)); Assert.assertEquals(1006L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(102L, capsule.getEnergyFactor()); + Assert.assertEquals(10_258L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(150L) + .setEnergyFactor(15_000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1007L, 1_000_000L, 150, 200)); + Assert.assertTrue(capsule.catchUpToCycle(1007L, 1_000_000L, 5_000L, 10_000L)); Assert.assertEquals(1007L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(100L, capsule.getEnergyFactor()); + Assert.assertEquals(10_000L, capsule.getEnergyFactor()); } From 64fc6ede3d4a8817377d3729182b5db8fc1e703c Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Tue, 27 Dec 2022 16:50:36 +0800 Subject: [PATCH 0504/1197] feat(DynamicEnergy): optimize call energy penalty logic --- .../java/org/tron/core/vm/EnergyCost.java | 11 +++++++++ .../src/main/java/org/tron/core/vm/VM.java | 24 ++++++++++++------- .../org/tron/core/vm/program/Program.java | 24 +++++++++++++++---- .../tron/common/runtime/ProgramResult.java | 4 ++-- 4 files changed, 47 insertions(+), 16 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java index 11022da52b1..b74680bf732 100644 --- a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java +++ b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java @@ -5,6 +5,8 @@ import org.tron.core.vm.program.Program; import org.tron.core.vm.program.Stack; +import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; + public class EnergyCost { private static final long ZERO_TIER = 0; @@ -418,6 +420,15 @@ public static long getCalculateCallCost(Stack stack, Program program, energyCost += calcMemEnergy(oldMemSize, in.max(out), 0, op); + if (program.supportDynamicEnergy()) { + long factor = program.getContextContractFactor(); + if (factor > DYNAMIC_ENERGY_FACTOR_DECIMAL) { + long penalty = energyCost * factor / DYNAMIC_ENERGY_FACTOR_DECIMAL - energyCost; + program.setCallPenaltyEnergy(penalty); + energyCost += penalty; + } + } + if (energyCost > program.getEnergyLimitLeft().longValueSafe()) { throw new Program.OutOfEnergyException( "Not enough energy for '%s' operation executing: opEnergy[%d], programEnergy[%d]", diff --git a/actuator/src/main/java/org/tron/core/vm/VM.java b/actuator/src/main/java/org/tron/core/vm/VM.java index 6fda100a62b..02373bed90d 100644 --- a/actuator/src/main/java/org/tron/core/vm/VM.java +++ b/actuator/src/main/java/org/tron/core/vm/VM.java @@ -51,16 +51,22 @@ public static void play(Program program, JumpTable jumpTable) { /* spend energy before execution */ long energy = op.getEnergyCost(program); if (allowDynamicEnergy) { - long actualEnergy = energy; - // CALL Ops have special calculation on energy. - if (CALL_OPS.contains(op.getOpcode())) { - actualEnergy = energy - program.getAdjustedCallEnergy().longValueSafe(); - } - energyUsage += actualEnergy; - if (factor > DYNAMIC_ENERGY_FACTOR_DECIMAL) { - long penalty = - actualEnergy * factor / DYNAMIC_ENERGY_FACTOR_DECIMAL - actualEnergy; + long actualEnergy = energy; + long penalty; + + // CALL Ops have special calculation on energy. + if (CALL_OPS.contains(op.getOpcode())) { + actualEnergy = energy + - program.getAdjustedCallEnergy().longValueSafe() + - program.getCallPenaltyEnergy(); + penalty = program.getCallPenaltyEnergy(); + } else { + penalty = energy * factor / DYNAMIC_ENERGY_FACTOR_DECIMAL - energy; + energy += penalty; + } + + energyUsage += actualEnergy; program.spendEnergyWithPenalty(energy, penalty, opName); } else { program.spendEnergy(energy, opName); diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index c9de3cfe4af..d04fe083f99 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -17,6 +17,9 @@ import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; + +import lombok.Getter; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.map.LRUMap; @@ -130,6 +133,12 @@ public class Program { private ProgramPrecompile programPrecompile; private int contractVersion; private DataWord adjustedCallEnergy; + @Getter + @Setter + private long contextContractFactor; + @Getter + @Setter + private long callPenaltyEnergy; public Program(byte[] ops, byte[] codeAddress, ProgramInvoke programInvoke, InternalTransaction internalTransaction) { @@ -422,6 +431,10 @@ public void allocateMemory(int offset, int size) { memory.extend(offset, size); } + public boolean supportDynamicEnergy() { + return contractState.getDynamicPropertiesStore().supportAllowDynamicEnergy(); + } + public void suicide(DataWord obtainerAddress) { byte[] owner = getContextAddress(); @@ -1106,14 +1119,14 @@ public void spendEnergy(long energyValue, String opName) { getResult().spendEnergy(energyValue); } - public void spendEnergyWithPenalty(long origin, long penalty, String opName) { - if (getEnergylimitLeftLong() < origin + penalty) { + public void spendEnergyWithPenalty(long total, long penalty, String opName) { + if (getEnergylimitLeftLong() < total) { throw new OutOfEnergyException( "Not enough energy for '%s' operation executing: curInvokeEnergyLimit[%d]," + " curOpEnergy[%d], penaltyEnergy[%d], usedEnergy[%d]", - opName, invoke.getEnergyLimit(), origin, penalty, getResult().getEnergyUsed()); + opName, invoke.getEnergyLimit(), total - penalty, penalty, getResult().getEnergyUsed()); } - getResult().spendEnergyWithPenalty(origin, penalty); + getResult().spendEnergyWithPenalty(total, penalty); } public void checkCPUTimeLimit(String opName) { @@ -2228,7 +2241,8 @@ public long updateContextContractFactor() { contractStateCapsule); } } - return contractStateCapsule.getEnergyFactor(); + contextContractFactor = contractStateCapsule.getEnergyFactor(); + return contextContractFactor; } public void addContextContractUsage(long value) { diff --git a/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java b/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java index 5c6c0d12294..4410b828823 100644 --- a/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java +++ b/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java @@ -69,10 +69,10 @@ public void spendEnergy(long energy) { energyUsed += energy; } - public void spendEnergyWithPenalty(long origin, long penalty) { + public void spendEnergyWithPenalty(long total, long penalty) { energyPenalty += penalty; energyPenaltyTotal += penalty; - energyUsed += origin + penalty; + energyUsed += total; } public void setRevert() { From aee24119e1b680511be4652bf34f686b76b92341 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Tue, 27 Dec 2022 17:19:19 +0800 Subject: [PATCH 0505/1197] feat(DynamicEnergy): optimize penalty calculation and Program result --- actuator/src/main/java/org/tron/core/vm/EnergyCost.java | 3 +++ actuator/src/main/java/org/tron/core/vm/VM.java | 3 +++ .../src/main/java/org/tron/common/runtime/ProgramResult.java | 4 ---- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java index b74680bf732..5e54cef0226 100644 --- a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java +++ b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java @@ -424,6 +424,9 @@ public static long getCalculateCallCost(Stack stack, Program program, long factor = program.getContextContractFactor(); if (factor > DYNAMIC_ENERGY_FACTOR_DECIMAL) { long penalty = energyCost * factor / DYNAMIC_ENERGY_FACTOR_DECIMAL - energyCost; + if (penalty < 0) { + penalty = 0; + } program.setCallPenaltyEnergy(penalty); energyCost += penalty; } diff --git a/actuator/src/main/java/org/tron/core/vm/VM.java b/actuator/src/main/java/org/tron/core/vm/VM.java index 02373bed90d..cbe94141e9d 100644 --- a/actuator/src/main/java/org/tron/core/vm/VM.java +++ b/actuator/src/main/java/org/tron/core/vm/VM.java @@ -63,6 +63,9 @@ public static void play(Program program, JumpTable jumpTable) { penalty = program.getCallPenaltyEnergy(); } else { penalty = energy * factor / DYNAMIC_ENERGY_FACTOR_DECIMAL - energy; + if (penalty < 0) { + penalty = 0; + } energy += penalty; } diff --git a/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java b/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java index 4410b828823..221ac89dd0b 100644 --- a/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java +++ b/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java @@ -24,9 +24,6 @@ public class ProgramResult { private long energyUsed = 0; //private long futureRefund = 0; - @Getter - private long energyPenalty = 0; - @Getter private long energyPenaltyTotal = 0; @@ -70,7 +67,6 @@ public void spendEnergy(long energy) { } public void spendEnergyWithPenalty(long total, long penalty) { - energyPenalty += penalty; energyPenaltyTotal += penalty; energyUsed += total; } From 6577ddf6880d02a00ccda3cd35588408cdadbf69 Mon Sep 17 00:00:00 2001 From: Asuka Date: Tue, 27 Dec 2022 18:20:11 +0800 Subject: [PATCH 0506/1197] feat(DynamicEnergy): change the meanings of max factor and energy factor --- .../org/tron/core/utils/ProposalUtil.java | 17 +++-- .../org/tron/core/vm/program/Program.java | 17 ++--- .../core/capsule/ContractStateCapsule.java | 14 ++-- .../src/main/java/org/tron/core/Constant.java | 4 +- .../java/org/tron/core/config/args/Args.java | 15 ++-- .../capsule/ContractStateCapsuleTest.java | 70 +++++++++---------- 6 files changed, 69 insertions(+), 68 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 30c73eb626f..18586c56a8c 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -1,6 +1,7 @@ package org.tron.core.utils; -import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_RANGE; +import static org.tron.core.Constant.DYNAMIC_ENERGY_INCREASE_FACTOR_RANGE; +import static org.tron.core.Constant.DYNAMIC_ENERGY_MAX_FACTOR_RANGE; import org.tron.common.utils.ForkController; import org.tron.core.config.Parameter.ForkBlockVersionConsts; @@ -651,10 +652,11 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, "Bad chain parameter id [DYNAMIC_ENERGY_INCREASE_FACTOR]"); } - if (value < 0 || value > DYNAMIC_ENERGY_FACTOR_RANGE) { + if (value < 0 || value > DYNAMIC_ENERGY_INCREASE_FACTOR_RANGE) { throw new ContractValidateException( "This value[DYNAMIC_ENERGY_INCREASE_FACTOR] " - + "is only allowed to be in the range 0-10000" + + "is only allowed to be in the range 0-" + + DYNAMIC_ENERGY_INCREASE_FACTOR_RANGE ); } break; @@ -665,10 +667,11 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, "Bad chain parameter id [DYNAMIC_ENERGY_MAX_FACTOR]"); } - if (value < 0 || value > DYNAMIC_ENERGY_FACTOR_RANGE) { + if (value < 0 || value > DYNAMIC_ENERGY_MAX_FACTOR_RANGE) { throw new ContractValidateException( "This value[DYNAMIC_ENERGY_MAX_FACTOR] " - + "is only allowed to be in the range 0-10000" + + "is only allowed to be in the range 0-" + + DYNAMIC_ENERGY_MAX_FACTOR_RANGE ); } break; @@ -744,8 +747,8 @@ public enum ProposalType { // current value, value range ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID(71), // 0, 1 ALLOW_DYNAMIC_ENERGY(72), // 0, 1 DYNAMIC_ENERGY_THRESHOLD(73), // 0, [0, LONG] - DYNAMIC_ENERGY_INCREASE_FACTOR(74), // 0, [100, 10_000] - DYNAMIC_ENERGY_MAX_FACTOR(75); // 0, [100, 10_000] + DYNAMIC_ENERGY_INCREASE_FACTOR(74), // 0, [0, 10_000] + DYNAMIC_ENERGY_MAX_FACTOR(75); // 0, [0, 100_000] private long code; diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index d04fe083f99..d1daa031891 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -37,6 +37,7 @@ import org.tron.common.utils.Utils; import org.tron.common.utils.WalletUtil; import org.tron.core.ChainBaseManager; +import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.ContractCapsule; @@ -2234,14 +2235,13 @@ public long updateContextContractFactor() { contractState.getDynamicPropertiesStore().getCurrentCycleNumber()); contractState.updateContractState(getContextAddress(), contractStateCapsule); } else { - if (contractStateCapsule.catchUpToCycle( - contractState.getDynamicPropertiesStore())) { - contractState.updateContractState( - getContextAddress(), - contractStateCapsule); + if (contractStateCapsule.catchUpToCycle(contractState.getDynamicPropertiesStore())) { + contractState.updateContractState(getContextAddress(), contractStateCapsule + ); } } - contextContractFactor = contractStateCapsule.getEnergyFactor(); + contextContractFactor = contractStateCapsule.getEnergyFactor() + + Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; return contextContractFactor; } @@ -2249,11 +2249,6 @@ public void addContextContractUsage(long value) { ContractStateCapsule contractStateCapsule = contractState.getContractState(getContextAddress()); - if (contractStateCapsule == null) { - contractStateCapsule = new ContractStateCapsule( - contractState.getDynamicPropertiesStore().getCurrentCycleNumber()); - } - contractStateCapsule.addEnergyUsage(value); contractState.updateContractState(getContextAddress(), contractStateCapsule); } diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java index 1c490b66f59..abaf53a9335 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java @@ -102,11 +102,12 @@ public boolean catchUpToCycle( // Increase the last cycle if (getEnergyUsage() >= threshold) { lastCycle += 1; + double increasePercent = 1 + (double) increaseFactor / decimal; this.contractState = ContractState.newBuilder() .setUpdateCycle(lastCycle) .setEnergyFactor(Math.min( - decimal + maxFactor, - getEnergyFactor() * (decimal + increaseFactor) / decimal)) + maxFactor, + (long) ((getEnergyFactor() + decimal) * increasePercent) - decimal)) .build(); } @@ -117,9 +118,8 @@ public boolean catchUpToCycle( } // Calc the decrease percent (decrease factor [75% ~ 100%]) - double decreaseFactor = 1 - (double) increaseFactor / decimal - / DYNAMIC_ENERGY_DECREASE_DIVISION; - double decreasePercent = Math.pow(decreaseFactor, cycleCount); + long decreaseFactor = increaseFactor / DYNAMIC_ENERGY_DECREASE_DIVISION; + double decreasePercent = Math.pow(1 - (double) decreaseFactor / decimal, cycleCount); // Decrease to this cycle // (If long time no tx and factor is 100%, @@ -128,8 +128,8 @@ public boolean catchUpToCycle( this.contractState = ContractState.newBuilder() .setUpdateCycle(newCycle) .setEnergyFactor(Math.max( - decimal, - (long) (getEnergyFactor() * decreasePercent))) + 0, + (long) ((getEnergyFactor() + decimal) * decreasePercent) - decimal)) .build(); return true; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 1ae965c87f9..33490ce86a1 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -327,7 +327,9 @@ public class Constant { public static final long DYNAMIC_ENERGY_FACTOR_DECIMAL = 10_000L; - public static final long DYNAMIC_ENERGY_FACTOR_RANGE = 10_000L; + public static final long DYNAMIC_ENERGY_INCREASE_FACTOR_RANGE = 10_000L; + + public static final long DYNAMIC_ENERGY_MAX_FACTOR_RANGE = 100_000L; public static final int DYNAMIC_ENERGY_DECREASE_DIVISION = 4; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 49fd7eb09c1..2491385bb09 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -3,8 +3,8 @@ import static java.lang.Math.max; import static java.lang.System.exit; import static org.tron.core.Constant.ADD_PRE_FIX_BYTE_MAINNET; -import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; -import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_RANGE; +import static org.tron.core.Constant.DYNAMIC_ENERGY_INCREASE_FACTOR_RANGE; +import static org.tron.core.Constant.DYNAMIC_ENERGY_MAX_FACTOR_RANGE; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCE_TIMEOUT_PERCENT; import static org.tron.core.config.Parameter.ChainConstant.MAX_ACTIVE_WITNESS_NUM; @@ -1098,17 +1098,18 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.dynamicEnergyIncreaseFactor = config.getLong(Constant.DYNAMIC_ENERGY_INCREASE_FACTOR); PARAMETER.dynamicEnergyIncreaseFactor = - Math.min(PARAMETER.dynamicEnergyIncreaseFactor, DYNAMIC_ENERGY_FACTOR_RANGE); + Math.min(PARAMETER.dynamicEnergyIncreaseFactor, DYNAMIC_ENERGY_INCREASE_FACTOR_RANGE); PARAMETER.dynamicEnergyIncreaseFactor = - Math.max(PARAMETER.dynamicEnergyIncreaseFactor, DYNAMIC_ENERGY_FACTOR_DECIMAL); + Math.max(PARAMETER.dynamicEnergyIncreaseFactor, 0); } if (config.hasPath(Constant.DYNAMIC_ENERGY_MAX_FACTOR)) { - PARAMETER.dynamicEnergyMaxFactor = config.getLong(Constant.DYNAMIC_ENERGY_MAX_FACTOR); + PARAMETER.dynamicEnergyMaxFactor + = config.getLong(Constant.DYNAMIC_ENERGY_MAX_FACTOR); PARAMETER.dynamicEnergyMaxFactor = - Math.min(PARAMETER.dynamicEnergyMaxFactor, DYNAMIC_ENERGY_FACTOR_RANGE); + Math.min(PARAMETER.dynamicEnergyMaxFactor, DYNAMIC_ENERGY_MAX_FACTOR_RANGE); PARAMETER.dynamicEnergyMaxFactor = - Math.max(PARAMETER.dynamicEnergyMaxFactor, DYNAMIC_ENERGY_FACTOR_DECIMAL); + Math.max(PARAMETER.dynamicEnergyMaxFactor, 0); } logConfig(); diff --git a/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java index 6035905cb96..661fae2bdbf 100644 --- a/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java @@ -11,139 +11,139 @@ public void testCatchUpCycle() { ContractStateCapsule capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(15_000L) + .setEnergyFactor(5000L) .setUpdateCycle(1000L) .build()); - Assert.assertFalse(capsule.catchUpToCycle(1000L, 2_000_000L, 2_000L, 10_00L)); + Assert.assertFalse(capsule.catchUpToCycle(1000L, 2_000_000L, 2000L, 10_00L)); Assert.assertEquals(1000L, capsule.getUpdateCycle()); Assert.assertEquals(1_000_000L, capsule.getEnergyUsage()); - Assert.assertEquals(15_000L, capsule.getEnergyFactor()); + Assert.assertEquals(5000L, capsule.getEnergyFactor()); - Assert.assertTrue(capsule.catchUpToCycle(1010L, 1_000_000L, 1_000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1010L, 1_000_000L, 1000L, 10_000L)); Assert.assertEquals(1010L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(13_137L, capsule.getEnergyFactor()); + Assert.assertEquals(3137L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(15_000L) + .setEnergyFactor(5000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1001L, 2_000_000L, 2_000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 2_000_000L, 2000L, 10_000L)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(14_250L, capsule.getEnergyFactor()); + Assert.assertEquals(4250L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(15_000L) + .setEnergyFactor(5000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 2_000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 2000L, 10_000L)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(18_000L, capsule.getEnergyFactor()); + Assert.assertEquals(8000L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(15_000L) + .setEnergyFactor(5000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 5_000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 5000L, 10_000L)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(20_000L, capsule.getEnergyFactor()); + Assert.assertEquals(10_000L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(15_000L) + .setEnergyFactor(5000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1002L, 1_000_000L, 5_000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1002L, 1_000_000L, 5000L, 10_000L)); Assert.assertEquals(1002L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(17_500L, capsule.getEnergyFactor()); + Assert.assertEquals(7500L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(15_000L) + .setEnergyFactor(5000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1003L, 1_000_000L, 5_000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1003L, 1_000_000L, 5000L, 10_000L)); Assert.assertEquals(1003L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(15_312L, capsule.getEnergyFactor()); + Assert.assertEquals(5312L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(15_000L) + .setEnergyFactor(5000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1004L, 1_000_000L, 5_000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1004L, 1_000_000L, 5000L, 10_000L)); Assert.assertEquals(1004L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(13_398L, capsule.getEnergyFactor()); + Assert.assertEquals(3398L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(15_000L) + .setEnergyFactor(5000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1005L, 1_000_000L, 5_000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1005L, 1_000_000L, 5000L, 10_000L)); Assert.assertEquals(1005L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(11_723L, capsule.getEnergyFactor()); + Assert.assertEquals(1723L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(15_000L) + .setEnergyFactor(5000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1005L, 1_000_000L, 5_000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1005L, 1_000_000L, 5000L, 10_000L)); Assert.assertEquals(1005L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(11_723L, capsule.getEnergyFactor()); + Assert.assertEquals(1723L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(15_000L) + .setEnergyFactor(5000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1006L, 1_000_000L, 5_000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1006L, 1_000_000L, 5000L, 10_000L)); Assert.assertEquals(1006L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(10_258L, capsule.getEnergyFactor()); + Assert.assertEquals(258L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( SmartContractOuterClass.ContractState.newBuilder() .setEnergyUsage(1_000_000L) - .setEnergyFactor(15_000L) + .setEnergyFactor(5000L) .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1007L, 1_000_000L, 5_000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1007L, 1_000_000L, 5000L, 10_000L)); Assert.assertEquals(1007L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); - Assert.assertEquals(10_000L, capsule.getEnergyFactor()); + Assert.assertEquals(0L, capsule.getEnergyFactor()); } From fa63529b1b623e0be0ef43576a2a71e1178b59c4 Mon Sep 17 00:00:00 2001 From: Asuka Date: Tue, 27 Dec 2022 18:32:19 +0800 Subject: [PATCH 0507/1197] feat(DynamicEnergy): rename decimal to precision factor --- .../org/tron/core/capsule/ContractStateCapsule.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java index abaf53a9335..32953066c9d 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java @@ -97,17 +97,17 @@ public boolean catchUpToCycle( return true; } - final long decimal = DYNAMIC_ENERGY_FACTOR_DECIMAL; + final long precisionFactor = DYNAMIC_ENERGY_FACTOR_DECIMAL; // Increase the last cycle if (getEnergyUsage() >= threshold) { lastCycle += 1; - double increasePercent = 1 + (double) increaseFactor / decimal; + double increasePercent = 1 + (double) increaseFactor / precisionFactor; this.contractState = ContractState.newBuilder() .setUpdateCycle(lastCycle) .setEnergyFactor(Math.min( maxFactor, - (long) ((getEnergyFactor() + decimal) * increasePercent) - decimal)) + (long) ((getEnergyFactor() + precisionFactor) * increasePercent) - precisionFactor)) .build(); } @@ -119,7 +119,7 @@ public boolean catchUpToCycle( // Calc the decrease percent (decrease factor [75% ~ 100%]) long decreaseFactor = increaseFactor / DYNAMIC_ENERGY_DECREASE_DIVISION; - double decreasePercent = Math.pow(1 - (double) decreaseFactor / decimal, cycleCount); + double decreasePercent = Math.pow(1 - (double) decreaseFactor / precisionFactor, cycleCount); // Decrease to this cycle // (If long time no tx and factor is 100%, @@ -129,7 +129,7 @@ public boolean catchUpToCycle( .setUpdateCycle(newCycle) .setEnergyFactor(Math.max( 0, - (long) ((getEnergyFactor() + decimal) * decreasePercent) - decimal)) + (long) ((getEnergyFactor() + precisionFactor) * decreasePercent) - precisionFactor)) .build(); return true; From c5e2b741010842650f8deca03175b6e7c7dfbe43 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Tue, 27 Dec 2022 18:54:01 +0800 Subject: [PATCH 0508/1197] feat(DynamicEnergy): optimize estimate energy parameter path --- .../org/tron/common/parameter/CommonParameter.java | 2 +- common/src/main/java/org/tron/core/Constant.java | 3 +-- framework/src/main/java/org/tron/core/Wallet.java | 2 +- .../main/java/org/tron/core/config/args/Args.java | 8 ++++---- .../tron/core/services/jsonrpc/TronJsonRpcImpl.java | 2 +- framework/src/main/resources/config-localtest.conf | 13 ++++++------- 6 files changed, 14 insertions(+), 16 deletions(-) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index a90c1899535..46bf976907a 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -290,7 +290,7 @@ public class CommonParameter { public boolean walletExtensionApi; @Getter @Setter - public boolean estimateEnergyApi; + public boolean estimateEnergy; @Getter @Setter public int backupPriority; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 33490ce86a1..449ec3c11c4 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -68,6 +68,7 @@ public class Constant { public static final String VM_MIN_TIME_RATIO = "vm.minTimeRatio"; public static final String VM_MAX_TIME_RATIO = "vm.maxTimeRatio"; public static final String VM_LONG_RUNNING_TIME = "vm.longRunningTime"; + public static final String VM_ESTIMATE_ENERGY = "vm.estimateEnergy"; public static final String ROCKSDB = "ROCKSDB"; @@ -168,8 +169,6 @@ public class Constant { public static final String NODE_WALLET_EXTENSION_API = "node.walletExtensionApi"; - public static final String NODE_ESTIMATE_ENERGY_API = "node.estimateEnergyApi"; - public static final String NODE_RECEIVE_TCP_MIN_DATA_LENGTH = "node.receiveTcpMinDataLength"; public static final String NODE_IS_OPEN_FULL_TCP_DISCONNECT = "node.isOpenFullTcpDisconnect"; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 23fb41bc82a..e622766b4de 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2846,7 +2846,7 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, Return.Builder txRetBuilder, GrpcAPI.EstimateEnergyMessage.Builder estimateBuilder) throws ContractValidateException, ContractExeException, HeaderNotFound, VMIllegalException { - if (!Args.getInstance().estimateEnergyApi) { + if (!Args.getInstance().estimateEnergy) { throw new ContractValidateException("this node does not estimate energy"); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 2491385bb09..ada87763ba3 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -168,7 +168,7 @@ public static void clearParam() { PARAMETER.solidityNode = false; PARAMETER.trustNodeAddr = ""; PARAMETER.walletExtensionApi = false; - PARAMETER.estimateEnergyApi = false; + PARAMETER.estimateEnergy = false; PARAMETER.receiveTcpMinDataLength = 2048; PARAMETER.isOpenFullTcpDisconnect = false; PARAMETER.supportConstant = false; @@ -793,9 +793,9 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.walletExtensionApi = config.hasPath(Constant.NODE_WALLET_EXTENSION_API) && config.getBoolean(Constant.NODE_WALLET_EXTENSION_API); - PARAMETER.estimateEnergyApi = - config.hasPath(Constant.NODE_ESTIMATE_ENERGY_API) - && config.getBoolean(Constant.NODE_ESTIMATE_ENERGY_API); + PARAMETER.estimateEnergy = + config.hasPath(Constant.VM_ESTIMATE_ENERGY) + && config.getBoolean(Constant.VM_ESTIMATE_ENERGY); PARAMETER.receiveTcpMinDataLength = config.hasPath(Constant.NODE_RECEIVE_TCP_MIN_DATA_LENGTH) ? config.getLong(Constant.NODE_RECEIVE_TCP_MIN_DATA_LENGTH) : 2048; diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 48d36f9df07..0ff6f853857 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -570,7 +570,7 @@ public String estimateGas(CallArguments args) throws JsonRpcInvalidRequestExcept return "0x0"; } - boolean supportEstimateEnergy = CommonParameter.getInstance().isEstimateEnergyApi(); + boolean supportEstimateEnergy = CommonParameter.getInstance().isEstimateEnergy(); TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); diff --git a/framework/src/main/resources/config-localtest.conf b/framework/src/main/resources/config-localtest.conf index bfa9f311c08..2f749f25ef0 100644 --- a/framework/src/main/resources/config-localtest.conf +++ b/framework/src/main/resources/config-localtest.conf @@ -83,9 +83,6 @@ node { # expose extension api to public or not walletExtensionApi = true - # expose estimate energy api to public or not - estimateEnergyApi = true - listen.port = 6666 connection.timeout = 2 @@ -269,7 +266,8 @@ localwitness = [ block = { needSyncCheck = false - maintenanceTimeInterval = 21600000 +# maintenanceTimeInterval = 21600000 + maintenanceTimeInterval = 120000 proposalExpireTime = 259200000 // 3 day: 259200000(ms) } @@ -278,6 +276,8 @@ vm = { supportConstant = true minTimeRatio = 0.0 maxTimeRatio = 5.0 + # expose estimate energy api to public or not + estimateEnergy = true } committee = { @@ -291,9 +291,8 @@ committee = { allowTransactionFeePool = 1 allowDynamicEnergy = 1 dynamicEnergyThreshold = 100000 - dynamicEnergyIncreaseFactor = 120 - dynamicEnergyMaxFactor = 350 - dynamicEnergyTriggerBase = 5000 + dynamicEnergyIncreaseFactor = 2000 + dynamicEnergyMaxFactor = 25000 } log.level = { From b7e29c8196cac19725d16f68b9ed273321e4ae9c Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Tue, 27 Dec 2022 19:43:30 +0800 Subject: [PATCH 0509/1197] feat(DynamicEnergy): fix energy usage not added bug --- .../src/main/java/org/tron/core/vm/VM.java | 1 + .../src/main/resources/config-localtest.conf | 33 ++++++++++++++----- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/VM.java b/actuator/src/main/java/org/tron/core/vm/VM.java index cbe94141e9d..2eb505a72a5 100644 --- a/actuator/src/main/java/org/tron/core/vm/VM.java +++ b/actuator/src/main/java/org/tron/core/vm/VM.java @@ -72,6 +72,7 @@ public static void play(Program program, JumpTable jumpTable) { energyUsage += actualEnergy; program.spendEnergyWithPenalty(energy, penalty, opName); } else { + energyUsage += energy; program.spendEnergy(energy, opName); } diff --git a/framework/src/main/resources/config-localtest.conf b/framework/src/main/resources/config-localtest.conf index 2f749f25ef0..d8bf2047880 100644 --- a/framework/src/main/resources/config-localtest.conf +++ b/framework/src/main/resources/config-localtest.conf @@ -281,14 +281,31 @@ vm = { } committee = { - allowCreationOfContracts = 1 //mainnet:0 (reset by committee),test:1 - allowMultiSign = 1 //mainnet:0 (reset by committee),test:1 - allowSameTokenName = 1 - allowTvmTransferTrc10 = 1 - allowTvmConstantinople = 1 - allowTvmSolidity059 = 1 - allowMarketTransaction = 1 - allowTransactionFeePool = 1 + allowCreationOfContracts = 1 + allowDelegateResource = 1 + allowSameTokenName = 1 + allowTvmTransferTrc10 = 1 + allowMultiSign = 1 + #allowProtoFilterNum = 1 + #allowAccountStateRoot = 1 + allowTvmConstantinople = 1 + allowShieldedTransaction = 1 + allowTvmSolidity059 = 1 + changedDelegation = 1 + #forbidTransferToContract = 1 + #allowPBFT = 1 + allowShieldedTRC20Transaction = 1 + allowTvmIstanbul = 1 + #allowMarketTransaction = 1 + #allowTransactionFeePool = 1 + allowOptimizeBlackHole = 1 + allowBlackHoleOptimization = 1 + #allowTvmFreeze = 1 + #allowTvmCompatibleEvm = 1 + allowTvmLondon = 1 + allowHigherLimitForMaxCpuTimeOfOneTx = 1 + allowAssetOptimization = 1 + unfreezeDelayDays = 1 allowDynamicEnergy = 1 dynamicEnergyThreshold = 100000 dynamicEnergyIncreaseFactor = 2000 From 732317179bbf3ea7daaa395d17cfca33d0f9fd05 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Tue, 27 Dec 2022 19:52:39 +0800 Subject: [PATCH 0510/1197] feat(DynamicEnergy): optimize reset contract state factor --- .../main/java/org/tron/core/capsule/ContractStateCapsule.java | 1 - 1 file changed, 1 deletion(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java index 32953066c9d..d3d8b8b4447 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java @@ -138,7 +138,6 @@ public boolean catchUpToCycle( public void reset(long latestCycle) { this.contractState = ContractState.newBuilder() .setUpdateCycle(latestCycle) - .setEnergyFactor(DYNAMIC_ENERGY_FACTOR_DECIMAL) .build(); } } From f92cb38882eb7a7e9a851d121b4150284d678496 Mon Sep 17 00:00:00 2001 From: Liulei Date: Tue, 27 Dec 2022 21:09:10 +0800 Subject: [PATCH 0511/1197] feat(freezeV2): optimize total delegated resource --- .../org/tron/core/vm/PrecompiledContracts.java | 16 ++++------------ .../org/tron/core/capsule/AccountCapsule.java | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 942e6ba656d..dcd9ba1a2a3 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -2120,13 +2120,9 @@ public Pair execute(byte[] data) { long delegatedResource = 0; if (type == 0) { - delegatedResource = - accountCapsule.getDelegatedFrozenBalanceForBandwidth() - + accountCapsule.getDelegatedFrozenV2BalanceForBandwidth(); + delegatedResource = accountCapsule.getTotalDelegatedFrozenBalanceForBandwidth(); } else if (type == 1) { - delegatedResource = - accountCapsule.getDelegatedFrozenBalanceForEnergy() - + accountCapsule.getDelegatedFrozenV2BalanceForEnergy(); + delegatedResource = accountCapsule.getTotalDelegatedFrozenBalanceForEnergy(); } return Pair.of(true, longTo32Bytes(delegatedResource)); @@ -2157,13 +2153,9 @@ public Pair execute(byte[] data) { long acquiredResource = 0; if (type == 0) { - acquiredResource = - accountCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() - + accountCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth(); + acquiredResource = accountCapsule.getTotalAcquiredDelegatedFrozenBalanceForBandwidth(); } else if (type == 1) { - acquiredResource = - accountCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() - + accountCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy(); + acquiredResource = accountCapsule.getTotalAcquiredDelegatedFrozenBalanceForEnergy(); } return Pair.of(true, longTo32Bytes(acquiredResource)); diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index e91a0cad5b2..48593f5d36c 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -370,6 +370,10 @@ public long getAcquiredDelegatedFrozenV2BalanceForBandwidth() { return this.account.getAcquiredDelegatedFrozenV2BalanceForBandwidth(); } + public long getTotalAcquiredDelegatedFrozenBalanceForBandwidth() { + return getAcquiredDelegatedFrozenBalanceForBandwidth() + getAcquiredDelegatedFrozenV2BalanceForBandwidth(); + } + public void addFrozenBalanceForBandwidthV2(long balance) { this.addFrozenBalanceForResource(BANDWIDTH, balance); } @@ -415,6 +419,10 @@ public long getAcquiredDelegatedFrozenV2BalanceForEnergy() { return getAccountResource().getAcquiredDelegatedFrozenV2BalanceForEnergy(); } + public long getTotalAcquiredDelegatedFrozenBalanceForEnergy() { + return getAcquiredDelegatedFrozenBalanceForEnergy() + getAcquiredDelegatedFrozenV2BalanceForEnergy(); + } + public void setAcquiredDelegatedFrozenBalanceForEnergy(long balance) { AccountResource newAccountResource = getAccountResource().toBuilder() .setAcquiredDelegatedFrozenBalanceForEnergy(balance).build(); @@ -438,6 +446,10 @@ public long getDelegatedFrozenV2BalanceForEnergy() { return getAccountResource().getDelegatedFrozenV2BalanceForEnergy(); } + public long getTotalDelegatedFrozenBalanceForEnergy() { + return getDelegatedFrozenBalanceForEnergy() + getDelegatedFrozenV2BalanceForEnergy(); + } + public long getDelegatedFrozenBalanceForBandwidth() { return this.account.getDelegatedFrozenBalanceForBandwidth(); } @@ -446,6 +458,10 @@ public long getDelegatedFrozenV2BalanceForBandwidth() { return this.account.getDelegatedFrozenV2BalanceForBandwidth(); } + public long getTotalDelegatedFrozenBalanceForBandwidth() { + return getDelegatedFrozenBalanceForBandwidth() + getDelegatedFrozenV2BalanceForBandwidth(); + } + public void setDelegatedFrozenBalanceForBandwidth(long balance) { this.account = this.account.toBuilder() .setDelegatedFrozenBalanceForBandwidth(balance) From 54bc129150f911fa1e115d2383a5e69a73e1b06a Mon Sep 17 00:00:00 2001 From: Asuka Date: Wed, 28 Dec 2022 11:04:38 +0800 Subject: [PATCH 0512/1197] style(json-rpc): optimize code --- .../tron/core/services/jsonrpc/TronJsonRpcImpl.java | 12 ++++++------ framework/src/main/resources/config-localtest.conf | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 0ff6f853857..36efc20be8a 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -30,8 +30,8 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.bouncycastle.util.encoders.Hex; -import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.BytesMessage; +import org.tron.api.GrpcAPI.EstimateEnergyMessage; import org.tron.api.GrpcAPI.Return; import org.tron.api.GrpcAPI.Return.response_code; import org.tron.api.GrpcAPI.TransactionExtention; @@ -394,7 +394,7 @@ private void callTriggerConstantContract(byte[] ownerAddressByte, byte[] contrac private void estimateEnergy(byte[] ownerAddressByte, byte[] contractAddressByte, long value, byte[] data, TransactionExtention.Builder trxExtBuilder, - Return.Builder retBuilder, GrpcAPI.EstimateEnergyMessage.Builder estimateBuilder) + Return.Builder retBuilder, EstimateEnergyMessage.Builder estimateBuilder) throws ContractValidateException, ContractExeException, HeaderNotFound, VMIllegalException { TriggerSmartContract triggerContract = triggerCallContract( @@ -418,7 +418,6 @@ private void estimateEnergy(byte[] ownerAddressByte, byte[] contractAddressByte, estimateBuilder.setResult(retBuilder); } - /** * @param data Hash of the method signature and encoded parameters. for example: * getMethodSign(methodName(uint256,uint256)) || data1 || data2 @@ -574,8 +573,8 @@ public String estimateGas(CallArguments args) throws JsonRpcInvalidRequestExcept TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); - GrpcAPI.EstimateEnergyMessage.Builder estimateBuilder - = GrpcAPI.EstimateEnergyMessage.newBuilder(); + EstimateEnergyMessage.Builder estimateBuilder + = EstimateEnergyMessage.newBuilder(); try { byte[] contractAddress; @@ -635,9 +634,10 @@ public String estimateGas(CallArguments args) throws JsonRpcInvalidRequestExcept if (supportEstimateEnergy) { return ByteArray.toJsonHex(estimateBuilder.getEnergyRequired()); + } else { + return ByteArray.toJsonHex(trxExtBuilder.getEnergyUsed()); } - return ByteArray.toJsonHex(trxExtBuilder.getEnergyUsed()); } } diff --git a/framework/src/main/resources/config-localtest.conf b/framework/src/main/resources/config-localtest.conf index d8bf2047880..cd23882fa46 100644 --- a/framework/src/main/resources/config-localtest.conf +++ b/framework/src/main/resources/config-localtest.conf @@ -306,10 +306,10 @@ committee = { allowHigherLimitForMaxCpuTimeOfOneTx = 1 allowAssetOptimization = 1 unfreezeDelayDays = 1 - allowDynamicEnergy = 1 - dynamicEnergyThreshold = 100000 - dynamicEnergyIncreaseFactor = 2000 - dynamicEnergyMaxFactor = 25000 + allowDynamicEnergy = 1 + dynamicEnergyThreshold = 100000 + dynamicEnergyIncreaseFactor = 2000 + dynamicEnergyMaxFactor = 25000 } log.level = { From 3d3ffec43d7b974eed9bfb0fbf91acb39fc0b229 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Wed, 28 Dec 2022 11:39:32 +0800 Subject: [PATCH 0513/1197] feat(DynamicEnergy): revert config-localtest changes --- .../src/main/resources/config-localtest.conf | 42 ++++--------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/framework/src/main/resources/config-localtest.conf b/framework/src/main/resources/config-localtest.conf index cd23882fa46..45254446001 100644 --- a/framework/src/main/resources/config-localtest.conf +++ b/framework/src/main/resources/config-localtest.conf @@ -266,8 +266,7 @@ localwitness = [ block = { needSyncCheck = false -# maintenanceTimeInterval = 21600000 - maintenanceTimeInterval = 120000 + maintenanceTimeInterval = 21600000 proposalExpireTime = 259200000 // 3 day: 259200000(ms) } @@ -276,40 +275,17 @@ vm = { supportConstant = true minTimeRatio = 0.0 maxTimeRatio = 5.0 - # expose estimate energy api to public or not - estimateEnergy = true } committee = { - allowCreationOfContracts = 1 - allowDelegateResource = 1 - allowSameTokenName = 1 - allowTvmTransferTrc10 = 1 - allowMultiSign = 1 - #allowProtoFilterNum = 1 - #allowAccountStateRoot = 1 - allowTvmConstantinople = 1 - allowShieldedTransaction = 1 - allowTvmSolidity059 = 1 - changedDelegation = 1 - #forbidTransferToContract = 1 - #allowPBFT = 1 - allowShieldedTRC20Transaction = 1 - allowTvmIstanbul = 1 - #allowMarketTransaction = 1 - #allowTransactionFeePool = 1 - allowOptimizeBlackHole = 1 - allowBlackHoleOptimization = 1 - #allowTvmFreeze = 1 - #allowTvmCompatibleEvm = 1 - allowTvmLondon = 1 - allowHigherLimitForMaxCpuTimeOfOneTx = 1 - allowAssetOptimization = 1 - unfreezeDelayDays = 1 - allowDynamicEnergy = 1 - dynamicEnergyThreshold = 100000 - dynamicEnergyIncreaseFactor = 2000 - dynamicEnergyMaxFactor = 25000 + allowCreationOfContracts = 1 //mainnet:0 (reset by committee),test:1 + allowMultiSign = 1 //mainnet:0 (reset by committee),test:1 + allowSameTokenName = 1 + allowTvmTransferTrc10 = 1 + allowTvmConstantinople = 1 + allowTvmSolidity059 = 1 + allowMarketTransaction = 1 + allowTransactionFeePool = 1 } log.level = { From ec6f6c7ba1bf46c86d14407d15bcf50e4335db18 Mon Sep 17 00:00:00 2001 From: Asuka Date: Wed, 28 Dec 2022 13:42:05 +0800 Subject: [PATCH 0514/1197] style(rpc): fix code smell --- .../main/java/org/tron/core/services/RpcApiService.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 6ffb449f412..7757a05e62c 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -180,6 +180,7 @@ public class RpcApiService implements Service { public static final String CONTRACT_VALIDATE_EXCEPTION = "ContractValidateException: {}"; private static final String EXCEPTION_CAUGHT = "exception caught"; + private static final String UNKNOWN_EXCEPTION_CAUGHT = "unknown exception caught: "; private static final long BLOCK_LIMIT_NUM = 100; private static final long TRANSACTION_LIMIT_NUM = 1000; private int port = Args.getInstance().getRpcPort(); @@ -316,7 +317,7 @@ private void callContract(TriggerSmartContract request, retBuilder.setResult(false).setCode(response_code.OTHER_ERROR) .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); trxExtBuilder.setResult(retBuilder); - logger.warn("unknown exception caught: " + e.getMessage(), e); + logger.warn(UNKNOWN_EXCEPTION_CAUGHT + e.getMessage(), e); } finally { responseObserver.onNext(trxExtBuilder.build()); responseObserver.onCompleted(); @@ -2011,7 +2012,7 @@ public void estimateEnergy(TriggerSmartContract request, retBuilder.setResult(false).setCode(response_code.OTHER_ERROR) .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); trxExtBuilder.setResult(retBuilder); - logger.warn("unknown exception caught: " + e.getMessage(), e); + logger.warn(UNKNOWN_EXCEPTION_CAUGHT + e.getMessage(), e); } finally { estimateBuilder.setResult(retBuilder); responseObserver.onNext(estimateBuilder.build()); @@ -2058,7 +2059,7 @@ private void callContract(TriggerSmartContract request, retBuilder.setResult(false).setCode(response_code.OTHER_ERROR) .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); trxExtBuilder.setResult(retBuilder); - logger.warn("unknown exception caught: " + e.getMessage(), e); + logger.warn(UNKNOWN_EXCEPTION_CAUGHT + e.getMessage(), e); } finally { responseObserver.onNext(trxExtBuilder.build()); responseObserver.onCompleted(); From a053aadf67379c77ee76fae119a71a353c4ecdbd Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 27 Dec 2022 13:47:00 +0800 Subject: [PATCH 0515/1197] feat(*): update jar repository 1. remove jcenter and jitpack package repository --- actuator/build.gradle | 1 - build.gradle | 10 +++++----- chainbase/build.gradle | 2 +- consensus/build.gradle | 1 - framework/build.gradle | 3 +-- plugins/build.gradle | 4 ++-- 6 files changed, 9 insertions(+), 12 deletions(-) diff --git a/actuator/build.gradle b/actuator/build.gradle index 34bfc018500..3db2e55b3de 100644 --- a/actuator/build.gradle +++ b/actuator/build.gradle @@ -20,7 +20,6 @@ dependencies { compile "org.slf4j:jcl-over-slf4j:$slf4jVersion" compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' - compile 'com.github.tronprotocol:zksnark-java-sdk:master-SNAPSHOT' compile group: 'commons-codec', name: 'commons-codec', version: '1.11' compile 'org.reflections:reflections:0.9.11' } diff --git a/build.gradle b/build.gradle index 44c419ed199..8ff739a1e4c 100644 --- a/build.gradle +++ b/build.gradle @@ -17,12 +17,13 @@ subprojects { buildscript { repositories { mavenCentral() - jcenter() - maven { url 'https://jitpack.io/' } + maven { + url "https://plugins.gradle.org/m2/" + } } dependencies { - classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.12' - classpath 'com.github.jengelman.gradle.plugins:shadow:5.2.0' + classpath 'com.google.protobuf:protobuf-gradle-plugin:0.9.1' + classpath "gradle.plugin.com.github.johnrengelman:shadow:7.1.2" } } @@ -30,7 +31,6 @@ subprojects { mavenLocal() mavenCentral() maven { url 'https://repo.spring.io/plugins-release' } - maven { url 'https://jitpack.io/' } } dependencies { diff --git a/chainbase/build.gradle b/chainbase/build.gradle index 758a59aa23c..cac7efc6fa5 100644 --- a/chainbase/build.gradle +++ b/chainbase/build.gradle @@ -39,7 +39,7 @@ dependencies { compile "org.fusesource.jansi:jansi:$jansiVersion" compile group: 'org.rocksdb', name: 'rocksdbjni', version: '5.15.10' compile group: 'com.typesafe', name: 'config', version: '1.3.2' - compile 'com.github.tronprotocol:zksnark-java-sdk:master-SNAPSHOT' + compile 'io.github.tronprotocol:zksnark-java-sdk:1.0.0' compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.8.5' compile project(":protocol") compile project(":common") diff --git a/consensus/build.gradle b/consensus/build.gradle index 0b04d12dac4..c2393064d46 100644 --- a/consensus/build.gradle +++ b/consensus/build.gradle @@ -16,7 +16,6 @@ dependencies { testImplementation "org.testng:testng:$testNgVersion" compile "org.slf4j:jcl-over-slf4j:$slf4jVersion" compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' - compile 'com.github.tronprotocol:zksnark-java-sdk:master-SNAPSHOT' compile group: 'commons-codec', name: 'commons-codec', version: '1.11' } diff --git a/framework/build.gradle b/framework/build.gradle index bba8e2196df..6be5edf9002 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -48,7 +48,7 @@ dependencies { compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.1.5' + compile group: 'io.github.tronprotocol', name: 'libp2p', version: '0.1.1' compile group: 'com.typesafe', name: 'config', version: '1.3.2' @@ -89,7 +89,6 @@ dependencies { compile group: 'org.pf4j', name: 'pf4j', version: '2.5.0' compile group: 'org.zeromq', name: 'jeromq', version: '0.5.0' - compile 'com.github.tronprotocol:zksnark-java-sdk:master-SNAPSHOT' compile project(":chainbase") compile project(":protocol") compile project(":actuator") diff --git a/plugins/build.gradle b/plugins/build.gradle index 7dff7295869..22e37737731 100644 --- a/plugins/build.gradle +++ b/plugins/build.gradle @@ -35,8 +35,8 @@ dependencies { compile group: 'me.tongfei', name: 'progressbar', version: '0.9.3' compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' compile group: 'org.rocksdb', name: 'rocksdbjni', version: '5.15.10' - compile 'com.halibobor:leveldbjni-all:1.18.2' - compile 'com.halibobor:leveldb:1.18.2' + compile 'io.github.tronprotocol:leveldbjni-all:1.18.2' + compile 'io.github.tronprotocol:leveldb:1.18.2' compile project(":protocol") } From 8585044c561940ac1e7729da1a5995e8687d63ba Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Wed, 28 Dec 2022 16:57:32 +0800 Subject: [PATCH 0516/1197] feat(DynamicEnergy): optimize ContractState threshold compare logic --- .../core/capsule/ContractStateCapsule.java | 3 +- .../capsule/ContractStateCapsuleTest.java | 30 +++++++++++++------ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java index d3d8b8b4447..fc5fffb0151 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java @@ -100,7 +100,8 @@ public boolean catchUpToCycle( final long precisionFactor = DYNAMIC_ENERGY_FACTOR_DECIMAL; // Increase the last cycle - if (getEnergyUsage() >= threshold) { + // fix the threshold = 0 caused incompatible + if (getEnergyUsage() > threshold) { lastCycle += 1; double increasePercent = 1 + (double) increaseFactor / precisionFactor; this.contractState = ContractState.newBuilder() diff --git a/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java index 661fae2bdbf..90f74074a9b 100644 --- a/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java @@ -20,7 +20,7 @@ public void testCatchUpCycle() { Assert.assertEquals(1_000_000L, capsule.getEnergyUsage()); Assert.assertEquals(5000L, capsule.getEnergyFactor()); - Assert.assertTrue(capsule.catchUpToCycle(1010L, 1_000_000L, 1000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1010L, 900_000L, 1000L, 10_000L)); Assert.assertEquals(1010L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(3137L, capsule.getEnergyFactor()); @@ -47,6 +47,18 @@ public void testCatchUpCycle() { Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 2000L, 10_000L)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); + Assert.assertEquals(4250L, capsule.getEnergyFactor()); + + capsule = new ContractStateCapsule( + SmartContractOuterClass.ContractState.newBuilder() + .setEnergyUsage(1_000_000L) + .setEnergyFactor(5000L) + .setUpdateCycle(1000L) + .build()); + + Assert.assertTrue(capsule.catchUpToCycle(1001L, 900_000L, 2000L, 10_000L)); + Assert.assertEquals(1001L, capsule.getUpdateCycle()); + Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(8000L, capsule.getEnergyFactor()); capsule = new ContractStateCapsule( @@ -56,7 +68,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 5000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 900_000L, 5000L, 10_000L)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(10_000L, capsule.getEnergyFactor()); @@ -68,7 +80,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1002L, 1_000_000L, 5000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1002L, 900_000L, 5000L, 10_000L)); Assert.assertEquals(1002L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(7500L, capsule.getEnergyFactor()); @@ -80,7 +92,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1003L, 1_000_000L, 5000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1003L, 900_000L, 5000L, 10_000L)); Assert.assertEquals(1003L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(5312L, capsule.getEnergyFactor()); @@ -92,7 +104,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1004L, 1_000_000L, 5000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1004L, 900_000L, 5000L, 10_000L)); Assert.assertEquals(1004L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(3398L, capsule.getEnergyFactor()); @@ -104,7 +116,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1005L, 1_000_000L, 5000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1005L, 900_000L, 5000L, 10_000L)); Assert.assertEquals(1005L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(1723L, capsule.getEnergyFactor()); @@ -116,7 +128,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1005L, 1_000_000L, 5000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1005L, 900_000L, 5000L, 10_000L)); Assert.assertEquals(1005L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(1723L, capsule.getEnergyFactor()); @@ -128,7 +140,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1006L, 1_000_000L, 5000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1006L, 900_000L, 5000L, 10_000L)); Assert.assertEquals(1006L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(258L, capsule.getEnergyFactor()); @@ -140,7 +152,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1007L, 1_000_000L, 5000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1007L, 900_000L, 5000L, 10_000L)); Assert.assertEquals(1007L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(0L, capsule.getEnergyFactor()); From f349988f924f046a95063137410a74260a339abe Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Wed, 28 Dec 2022 17:10:27 +0800 Subject: [PATCH 0517/1197] feat(DynamicEnergy): add estimate energy api on PBFT --- .../http/EstimateEnergyOnPBFTServlet.java | 33 +++++++++++++++++++ .../http/PBFT/HttpApiOnPBFTService.java | 5 ++- 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/EstimateEnergyOnPBFTServlet.java diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/EstimateEnergyOnPBFTServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/EstimateEnergyOnPBFTServlet.java new file mode 100644 index 00000000000..825e2bf79e8 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/EstimateEnergyOnPBFTServlet.java @@ -0,0 +1,33 @@ +package org.tron.core.services.interfaceOnPBFT.http; + +import java.io.IOException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.EstimateEnergyServlet; +import org.tron.core.services.interfaceOnPBFT.WalletOnPBFT; + +@Component +@Slf4j(topic = "API") +public class EstimateEnergyOnPBFTServlet extends EstimateEnergyServlet { + + @Autowired + private WalletOnPBFT walletOnPBFT; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> { + try { + super.doPost(request, response); + } catch (IOException e) { + logger.error("EstimateEnergyOnPBFTServlet Exception", e); + } + }); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java index a6e560e78be..33da1414bbe 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java @@ -14,6 +14,7 @@ import org.tron.core.config.args.Args; import org.tron.core.services.filter.HttpApiAccessFilter; import org.tron.core.services.filter.LiteFnQueryHttpFilter; +import org.tron.core.services.interfaceOnPBFT.http.EstimateEnergyOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetAccountByIdOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetAccountOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetAssetIssueByIdOnPBFTServlet; @@ -127,7 +128,8 @@ public class HttpApiOnPBFTService implements Service { private GetRewardOnPBFTServlet getRewardServlet; @Autowired private TriggerConstantContractOnPBFTServlet triggerConstantContractOnPBFTServlet; - + @Autowired + private EstimateEnergyOnPBFTServlet estimateEnergyOnPBFTServlet; @Autowired private LiteFnQueryHttpFilter liteFnQueryHttpFilter; @Autowired @@ -223,6 +225,7 @@ public void start() { context.addServlet(new ServletHolder(isSpendOnPBFTServlet), "/isspend"); context.addServlet(new ServletHolder(triggerConstantContractOnPBFTServlet), "/triggerconstantcontract"); + context.addServlet(new ServletHolder(estimateEnergyOnPBFTServlet), "/estimateenergy"); // only for PBFTNode context.addServlet(new ServletHolder(getTransactionByIdOnPBFTServlet), "/gettransactionbyid"); From be2ce70e03ed8a3c027dbc79f9d2a0e5db28b8c8 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Wed, 28 Dec 2022 18:49:17 +0800 Subject: [PATCH 0518/1197] feat(DynamicEnergy): optimize VMConfig add DynamicEnergy committee params --- .../java/org/tron/core/vm/EnergyCost.java | 3 +- .../src/main/java/org/tron/core/vm/VM.java | 9 ++--- .../org/tron/core/vm/config/ConfigLoader.java | 4 ++ .../org/tron/core/vm/config/VMConfig.java | 40 +++++++++++++++++++ .../org/tron/core/vm/program/Program.java | 10 ++--- .../common/parameter/CommonParameter.java | 4 +- .../src/main/java/org/tron/core/Wallet.java | 7 +--- 7 files changed, 57 insertions(+), 20 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java index 5e54cef0226..3b62b2f549a 100644 --- a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java +++ b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java @@ -2,6 +2,7 @@ import java.math.BigInteger; import org.tron.common.runtime.vm.DataWord; +import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.program.Program; import org.tron.core.vm.program.Stack; @@ -420,7 +421,7 @@ public static long getCalculateCallCost(Stack stack, Program program, energyCost += calcMemEnergy(oldMemSize, in.max(out), 0, op); - if (program.supportDynamicEnergy()) { + if (VMConfig.allowDynamicEnergy()) { long factor = program.getContextContractFactor(); if (factor > DYNAMIC_ENERGY_FACTOR_DECIMAL) { long penalty = energyCost * factor / DYNAMIC_ENERGY_FACTOR_DECIMAL - energyCost; diff --git a/actuator/src/main/java/org/tron/core/vm/VM.java b/actuator/src/main/java/org/tron/core/vm/VM.java index 2eb505a72a5..37834752da3 100644 --- a/actuator/src/main/java/org/tron/core/vm/VM.java +++ b/actuator/src/main/java/org/tron/core/vm/VM.java @@ -24,10 +24,7 @@ public static void play(Program program, JumpTable jumpTable) { long factor = DYNAMIC_ENERGY_FACTOR_DECIMAL; long energyUsage = 0L; - boolean allowDynamicEnergy = - program.getContractState().getDynamicPropertiesStore().supportAllowDynamicEnergy(); - - if (allowDynamicEnergy) { + if (VMConfig.allowDynamicEnergy()) { factor = program.updateContextContractFactor(); } @@ -50,7 +47,7 @@ public static void play(Program program, JumpTable jumpTable) { String opName = Op.getNameOf(op.getOpcode()); /* spend energy before execution */ long energy = op.getEnergyCost(program); - if (allowDynamicEnergy) { + if (VMConfig.allowDynamicEnergy()) { if (factor > DYNAMIC_ENERGY_FACTOR_DECIMAL) { long actualEnergy = energy; long penalty; @@ -101,7 +98,7 @@ public static void play(Program program, JumpTable jumpTable) { } } - if (allowDynamicEnergy) { + if (VMConfig.allowDynamicEnergy()) { program.addContextContractUsage(energyUsage); } diff --git a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java index 8dbb4457d4d..8c597bc50bf 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java +++ b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java @@ -34,6 +34,10 @@ public static void load(StoreFactory storeFactory) { VMConfig.initAllowTvmFreezeV2(ds.supportUnfreezeDelay() ? 1 : 0); VMConfig.initAllowOptimizedReturnValueOfChainId( ds.getAllowOptimizedReturnValueOfChainId()); + VMConfig.initAllowDynamicEnergy(ds.getAllowDynamicEnergy()); + VMConfig.initDynamicEnergyThreshold(ds.getDynamicEnergyThreshold()); + VMConfig.initDynamicEnergyIncreaseFactor(ds.getDynamicEnergyIncreaseFactor()); + VMConfig.initDynamicEnergyMaxFactor(ds.getDynamicEnergyMaxFactor()); } } } diff --git a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java index 38fa1ca17f6..004fb5ffb8f 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java +++ b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java @@ -39,6 +39,14 @@ public class VMConfig { private static boolean ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID = false; + private static boolean ALLOW_DYNAMIC_ENERGY = false; + + private static long DYNAMIC_ENERGY_THRESHOLD = 0L; + + private static long DYNAMIC_ENERGY_INCREASE_FACTOR = 0L; + + private static long DYNAMIC_ENERGY_MAX_FACTOR = 0L; + private VMConfig() { } @@ -106,6 +114,22 @@ public static void initAllowOptimizedReturnValueOfChainId(long allow) { ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID = allow == 1; } + public static void initAllowDynamicEnergy(long allow) { + ALLOW_DYNAMIC_ENERGY = allow == 1; + } + + public static void initDynamicEnergyThreshold(long threshold) { + DYNAMIC_ENERGY_THRESHOLD = threshold; + } + + public static void initDynamicEnergyIncreaseFactor(long increaseFactor) { + DYNAMIC_ENERGY_INCREASE_FACTOR = increaseFactor; + } + + public static void initDynamicEnergyMaxFactor(long maxFactor) { + DYNAMIC_ENERGY_MAX_FACTOR = maxFactor; + } + public static boolean getEnergyLimitHardFork() { return CommonParameter.ENERGY_LIMIT_HARD_FORK; } @@ -161,4 +185,20 @@ public static boolean allowTvmFreezeV2() { public static boolean allowOptimizedReturnValueOfChainId() { return ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID; } + + public static boolean allowDynamicEnergy() { + return ALLOW_DYNAMIC_ENERGY; + } + + public static long getDynamicEnergyThreshold() { + return DYNAMIC_ENERGY_THRESHOLD; + } + + public static long getDynamicEnergyIncreaseFactor() { + return DYNAMIC_ENERGY_INCREASE_FACTOR; + } + + public static long getDynamicEnergyMaxFactor() { + return DYNAMIC_ENERGY_MAX_FACTOR; + } } diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index e27e94991db..382ee895d44 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -432,10 +432,6 @@ public void allocateMemory(int offset, int size) { memory.extend(offset, size); } - public boolean supportDynamicEnergy() { - return contractState.getDynamicPropertiesStore().supportAllowDynamicEnergy(); - } - public void suicide(DataWord obtainerAddress) { byte[] owner = getContextAddress(); @@ -2235,7 +2231,11 @@ public long updateContextContractFactor() { contractState.getDynamicPropertiesStore().getCurrentCycleNumber()); contractState.updateContractState(getContextAddress(), contractStateCapsule); } else { - if (contractStateCapsule.catchUpToCycle(contractState.getDynamicPropertiesStore())) { + if (contractStateCapsule.catchUpToCycle( + contractState.getDynamicPropertiesStore().getCurrentCycleNumber(), + VMConfig.getDynamicEnergyThreshold(), + VMConfig.getDynamicEnergyIncreaseFactor(), + VMConfig.getDynamicEnergyMaxFactor())) { contractState.updateContractState(getContextAddress(), contractStateCapsule ); } diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 1990a3d3659..87c5a644668 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -601,11 +601,11 @@ public class CommonParameter { @Getter @Setter - public long dynamicEnergyIncreaseFactor = DYNAMIC_ENERGY_FACTOR_DECIMAL; + public long dynamicEnergyIncreaseFactor = 0L; @Getter @Setter - public long dynamicEnergyMaxFactor = DYNAMIC_ENERGY_FACTOR_DECIMAL; + public long dynamicEnergyMaxFactor = 0L; private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index e622766b4de..9cd30fed0c0 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -3039,12 +3039,7 @@ public SmartContractDataWrapper getContractInfo(GrpcAPI.BytesMessage bytesMessag ContractStateCapsule contractStateCapsule = chainBaseManager.getContractStateStore().get(address); if (Objects.nonNull(contractStateCapsule)) { - contractStateCapsule.catchUpToCycle( - chainBaseManager.getDynamicPropertiesStore().getCurrentCycleNumber(), - chainBaseManager.getDynamicPropertiesStore().getDynamicEnergyThreshold(), - chainBaseManager.getDynamicPropertiesStore().getDynamicEnergyIncreaseFactor(), - chainBaseManager.getDynamicPropertiesStore().getDynamicEnergyMaxFactor() - ); + contractStateCapsule.catchUpToCycle(chainBaseManager.getDynamicPropertiesStore()); } else { contractStateCapsule = new ContractStateCapsule( chainBaseManager.getDynamicPropertiesStore().getCurrentCycleNumber()); From c005095b9bea0e313069e904459968054aac05dc Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 28 Dec 2022 17:17:11 +0800 Subject: [PATCH 0519/1197] fix(freezeV2): refine resource usage recovery logic --- .../org/tron/core/db/BandwidthProcessor.java | 50 +++++++++---------- .../org/tron/core/db/EnergyProcessor.java | 17 ++++--- .../org/tron/core/db/ResourceProcessor.java | 6 +++ 3 files changed, 40 insertions(+), 33 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java index 5a89bd13ffe..759e46cd016 100644 --- a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -193,15 +193,16 @@ public boolean consumeBandwidthForCreateNewAccount(AccountCapsule accountCapsule long netUsage = accountCapsule.getNetUsage(); long latestConsumeTime = accountCapsule.getLatestConsumeTime(); long netLimit = calculateGlobalNetLimit(accountCapsule); - long newNetUsage = increase(accountCapsule, BANDWIDTH, netUsage, 0, latestConsumeTime, now); + // only participate in the calculation as a temporary variable, without disk flushing + long recoveryNetUsage = recovery(accountCapsule, BANDWIDTH, netUsage, latestConsumeTime, now); long netCost = bytes * createNewAccountBandwidthRatio; - if (netCost <= (netLimit - newNetUsage)) { - latestConsumeTime = now; + if (netCost <= (netLimit - recoveryNetUsage)) { long latestOperationTime = chainBaseManager.getHeadBlockTimeStamp(); - newNetUsage = increase(accountCapsule, BANDWIDTH, - newNetUsage, netCost, latestConsumeTime, now); - accountCapsule.setLatestConsumeTime(latestConsumeTime); + // Participate in calculation and flush disk persistence + long newNetUsage = increase(accountCapsule, BANDWIDTH, + netUsage, netCost, latestConsumeTime, now); + accountCapsule.setLatestConsumeTime(now); accountCapsule.setLatestOperationTime(latestOperationTime); accountCapsule.setNetUsage(newNetUsage); @@ -327,31 +328,30 @@ private boolean useAssetAccountNet(Contract contract, AccountCapsule accountCaps long issuerNetUsage = issuerAccountCapsule.getNetUsage(); long latestConsumeTime = issuerAccountCapsule.getLatestConsumeTime(); long issuerNetLimit = calculateGlobalNetLimit(issuerAccountCapsule); + // only participate in the calculation as a temporary variable, without disk flushing + long recoveryIssuerNetUsage = recovery(issuerAccountCapsule, BANDWIDTH, issuerNetUsage, + latestConsumeTime, now); - long newIssuerNetUsage = increase(issuerAccountCapsule, BANDWIDTH, - issuerNetUsage, 0, latestConsumeTime, now); - - if (bytes > (issuerNetLimit - newIssuerNetUsage)) { + if (bytes > (issuerNetLimit - recoveryIssuerNetUsage)) { logger.debug("The {} issuer's bandwidth is not enough." - + " Bytes: {}, issuerNetLimit: {}, newIssuerNetUsage:{}.", - tokenID, bytes, issuerNetLimit, newIssuerNetUsage); + + " Bytes: {}, issuerNetLimit: {}, recoveryIssuerNetUsage:{}.", + tokenID, bytes, issuerNetLimit, recoveryIssuerNetUsage); return false; } - latestConsumeTime = now; latestAssetOperationTime = now; publicLatestFreeNetTime = now; long latestOperationTime = chainBaseManager.getHeadBlockTimeStamp(); - - newIssuerNetUsage = increase(issuerAccountCapsule, BANDWIDTH, - newIssuerNetUsage, bytes, latestConsumeTime, now); + // Participate in calculation and flush disk persistence + long newIssuerNetUsage = increase(issuerAccountCapsule, BANDWIDTH, + issuerNetUsage, bytes, latestConsumeTime, now); newFreeAssetNetUsage = increase(newFreeAssetNetUsage, bytes, latestAssetOperationTime, now); newPublicFreeAssetNetUsage = increase(newPublicFreeAssetNetUsage, bytes, publicLatestFreeNetTime, now); issuerAccountCapsule.setNetUsage(newIssuerNetUsage); - issuerAccountCapsule.setLatestConsumeTime(latestConsumeTime); + issuerAccountCapsule.setLatestConsumeTime(now); assetIssueCapsule.setPublicFreeAssetNetUsage(newPublicFreeAssetNetUsage); assetIssueCapsule.setPublicLatestFreeNetTime(publicLatestFreeNetTime); @@ -424,22 +424,22 @@ private boolean useAccountNet(AccountCapsule accountCapsule, long bytes, long no long netUsage = accountCapsule.getNetUsage(); long latestConsumeTime = accountCapsule.getLatestConsumeTime(); long netLimit = calculateGlobalNetLimit(accountCapsule); + // only participate in the calculation as a temporary variable, without disk flushing + long recoveryNetUsage = recovery(accountCapsule, BANDWIDTH, netUsage, latestConsumeTime, now); - long newNetUsage = increase(accountCapsule, BANDWIDTH, netUsage, 0, latestConsumeTime, now); - - if (bytes > (netLimit - newNetUsage)) { + if (bytes > (netLimit - recoveryNetUsage)) { logger.debug("Net usage is running out, now use free net usage." - + " Bytes: {}, netLimit: {}, newNetUsage: {}.", - bytes, netLimit, newNetUsage); + + " Bytes: {}, netLimit: {}, recoveryNetUsage: {}.", + bytes, netLimit, recoveryNetUsage); return false; } - latestConsumeTime = now; long latestOperationTime = chainBaseManager.getHeadBlockTimeStamp(); - newNetUsage = increase(accountCapsule, BANDWIDTH, newNetUsage, bytes, latestConsumeTime, now); + // Participate in calculation and flush disk persistence + long newNetUsage = increase(accountCapsule, BANDWIDTH, netUsage, bytes, latestConsumeTime, now); accountCapsule.setNetUsage(newNetUsage); accountCapsule.setLatestOperationTime(latestOperationTime); - accountCapsule.setLatestConsumeTime(latestConsumeTime); + accountCapsule.setLatestConsumeTime(now); chainBaseManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); return true; diff --git a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java index 362cb9e9392..286d307ef16 100644 --- a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java @@ -101,22 +101,23 @@ public boolean useEnergy(AccountCapsule accountCapsule, long energy, long now) { long energyUsage = accountCapsule.getEnergyUsage(); long latestConsumeTime = accountCapsule.getAccountResource().getLatestConsumeTimeForEnergy(); long energyLimit = calculateGlobalEnergyLimit(accountCapsule); + // only participate in the calculation as a temporary variable, without disk flushing + long recoveryEnergyUsage = recovery(accountCapsule, ENERGY, energyUsage, + latestConsumeTime, now); - long newEnergyUsage = increase(accountCapsule, ENERGY, energyUsage, 0, latestConsumeTime, now); - - if (energy > (energyLimit - newEnergyUsage) + if (energy > (energyLimit - recoveryEnergyUsage) && dynamicPropertiesStore.getAllowTvmFreeze() == 0 && !dynamicPropertiesStore.supportUnfreezeDelay()) { return false; } - latestConsumeTime = now; long latestOperationTime = dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); - newEnergyUsage = increase(accountCapsule, ENERGY, - newEnergyUsage, energy, latestConsumeTime, now); + // Participate in calculation and flush disk persistence + long newEnergyUsage = increase(accountCapsule, ENERGY, energyUsage, energy, + latestConsumeTime, now); accountCapsule.setEnergyUsage(newEnergyUsage); accountCapsule.setLatestOperationTime(latestOperationTime); - accountCapsule.setLatestConsumeTimeForEnergy(latestConsumeTime); + accountCapsule.setLatestConsumeTimeForEnergy(now); accountStore.put(accountCapsule.createDbKey(), accountCapsule); @@ -165,7 +166,7 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { long latestConsumeTime = accountCapsule.getAccountResource().getLatestConsumeTimeForEnergy(); long energyLimit = calculateGlobalEnergyLimit(accountCapsule); - long newEnergyUsage = increase(accountCapsule, ENERGY, energyUsage, 0, latestConsumeTime, now); + long newEnergyUsage = recovery(accountCapsule, ENERGY, energyUsage, latestConsumeTime, now); return max(energyLimit - newEnergyUsage, 0); // us } diff --git a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java index 3702a433af5..49656cfe1d4 100644 --- a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java @@ -58,6 +58,12 @@ protected long increase(long lastUsage, long usage, long lastTime, long now, lon return getUsage(averageLastUsage, windowSize); } + public long recovery(AccountCapsule accountCapsule, ResourceCode resourceCode, + long lastUsage, long lastTime, long now) { + long oldWindowSize = accountCapsule.getWindowSize(resourceCode); + return increase(lastUsage, 0, lastTime, now, oldWindowSize); + } + public long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, long lastUsage, long usage, long lastTime, long now) { long oldWindowSize = accountCapsule.getWindowSize(resourceCode); From fd76410cb60e1f70a71f038047c3d24f0dac1d48 Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 29 Dec 2022 11:41:38 +0800 Subject: [PATCH 0520/1197] style(receipt): fix check style --- .../java/org/tron/core/capsule/ContractStateCapsule.java | 6 ++++-- .../src/main/java/org/tron/core/capsule/ReceiptCapsule.java | 3 ++- .../src/main/java/org/tron/core/db/ResourceProcessor.java | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java index fc5fffb0151..8633534280b 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java @@ -119,8 +119,10 @@ public boolean catchUpToCycle( } // Calc the decrease percent (decrease factor [75% ~ 100%]) - long decreaseFactor = increaseFactor / DYNAMIC_ENERGY_DECREASE_DIVISION; - double decreasePercent = Math.pow(1 - (double) decreaseFactor / precisionFactor, cycleCount); + double decreasePercent = Math.pow( + 1 - (double) increaseFactor / DYNAMIC_ENERGY_DECREASE_DIVISION / precisionFactor, + cycleCount + ); // Decrease to this cycle // (If long time no tx and factor is 100%, diff --git a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index 852196fb455..4b041c22f1d 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -192,7 +192,8 @@ private long getOriginUsage(DynamicPropertiesStore dynamicPropertiesStore, Accou long originEnergyLimit, EnergyProcessor energyProcessor, long originUsage) { - if (dynamicPropertiesStore.getAllowTvmFreeze() == 1 || dynamicPropertiesStore.supportUnfreezeDelay()) { + if (dynamicPropertiesStore.getAllowTvmFreeze() == 1 + || dynamicPropertiesStore.supportUnfreezeDelay()) { return Math.min(originUsage, Math.min(originEnergyLeft, originEnergyLimit)); } diff --git a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java index 3702a433af5..0e0fbdecbf2 100644 --- a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java @@ -74,8 +74,8 @@ public long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, } } - long newUsage = getUsage(averageLastUsage, oldWindowSize) + - getUsage(averageUsage, this.windowSize); + long newUsage = getUsage(averageLastUsage, oldWindowSize) + + getUsage(averageUsage, this.windowSize); if (dynamicPropertiesStore.supportUnfreezeDelay()) { long remainUsage = getUsage(averageLastUsage, oldWindowSize); if (remainUsage == 0) { From 72b075fbfcc1df9187464b3df479d13b55048d4f Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Thu, 29 Dec 2022 12:25:48 +0800 Subject: [PATCH 0521/1197] feat(DynamicEnergy): optimize the return result of estimate energy --- framework/src/main/java/org/tron/core/Wallet.java | 3 +++ .../java/org/tron/core/services/RpcApiService.java | 11 +---------- .../core/services/http/EstimateEnergyServlet.java | 11 ++--------- 3 files changed, 6 insertions(+), 19 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 9cd30fed0c0..35a95b2df2c 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2859,6 +2859,7 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, // If failed, return directly. if (transaction.getRet(0).getRet().equals(code.FAILED)) { + txRetBuilder.setCode(response_code.CONTRACT_EXE_ERROR); estimateBuilder.setResult(txRetBuilder); return transaction; } @@ -2891,6 +2892,8 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, // Setting estimating result estimateBuilder.setResult(txRetBuilder); if (transaction.getRet(0).getRet().equals(code.SUCESS)) { + txRetBuilder.setResult(true); + txRetBuilder.setCode(response_code.SUCCESS); estimateBuilder.setEnergyRequired((long) Math.ceil((double) high / dps.getEnergyFee())); } diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 7757a05e62c..2458e76f800 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -1990,28 +1990,19 @@ public void estimateEnergy(TriggerSmartContract request, try { TransactionCapsule trxCap = createTransactionCapsule(request, ContractType.TriggerSmartContract); - Transaction trx = wallet.estimateEnergy( - request, trxCap, trxExtBuilder, retBuilder, estimateBuilder); - - trxExtBuilder.setTransaction(trx); - trxExtBuilder.setTxid(trxCap.getTransactionId().getByteString()); - retBuilder.setResult(true).setCode(response_code.SUCCESS); - trxExtBuilder.setResult(retBuilder); + wallet.estimateEnergy(request, trxCap, trxExtBuilder, retBuilder, estimateBuilder); } catch (ContractValidateException | VMIllegalException e) { retBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) .setMessage(ByteString.copyFromUtf8(Wallet .CONTRACT_VALIDATE_ERROR + e.getMessage())); - trxExtBuilder.setResult(retBuilder); logger.warn(CONTRACT_VALIDATE_EXCEPTION, e.getMessage()); } catch (RuntimeException e) { retBuilder.setResult(false).setCode(response_code.CONTRACT_EXE_ERROR) .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); - trxExtBuilder.setResult(retBuilder); logger.warn("When run estimate energy in VM, have Runtime Exception: " + e.getMessage()); } catch (Exception e) { retBuilder.setResult(false).setCode(response_code.OTHER_ERROR) .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); - trxExtBuilder.setResult(retBuilder); logger.warn(UNKNOWN_EXCEPTION_CAUGHT + e.getMessage(), e); } finally { estimateBuilder.setResult(retBuilder); diff --git a/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java b/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java index 5dcf869af12..6b82199bd0e 100644 --- a/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java @@ -75,14 +75,8 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) TransactionCapsule trxCap = wallet.createTransactionCapsule(build.build(), Protocol.Transaction.Contract.ContractType.TriggerSmartContract); - Protocol.Transaction trx = wallet - .estimateEnergy(build.build(), trxCap, - trxExtBuilder, - retBuilder, estimateEnergyBuilder); - trx = Util.setTransactionPermissionId(jsonObject, trx); - trx = Util.setTransactionExtraData(jsonObject, trx, visible); - trxExtBuilder.setTransaction(trx); - retBuilder.setResult(true).setCode(Return.response_code.SUCCESS); + wallet.estimateEnergy(build.build(), trxCap, + trxExtBuilder, retBuilder, estimateEnergyBuilder); } catch (ContractValidateException e) { retBuilder.setResult(false).setCode(Return.response_code.CONTRACT_VALIDATE_ERROR) .setMessage(ByteString.copyFromUtf8(e.getMessage())); @@ -94,7 +88,6 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) retBuilder.setResult(false).setCode(Return.response_code.OTHER_ERROR) .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + errString)); } - trxExtBuilder.setResult(retBuilder); estimateEnergyBuilder.setResult(retBuilder); response.getWriter().println( Util.printEstimateEnergyMessage(estimateEnergyBuilder.build(), visible)); From 60e004eb9b3e7f28fa0b9219eaacda3abde8d8bb Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Fri, 30 Dec 2022 15:09:08 +0800 Subject: [PATCH 0522/1197] feat(tvm_stake2.0): optimize delegatableResource calculate logic --- .../org/tron/core/vm/utils/FreezeV2Util.java | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index 8d904a139de..c74995fd685 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -12,6 +12,8 @@ import org.tron.core.vm.repository.Repository; import org.tron.protos.Protocol; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + public class FreezeV2Util { private FreezeV2Util() { @@ -146,13 +148,13 @@ public static long queryDelegatableResource(byte[] address, long type, Repositor return frozenV2Resource; } - // total resource - long totalResource = accountCapsule.getAllFrozenBalanceForBandwidth(); - if (totalResource <= usage) { - return 0L; - } + long remainNetUsage = usage + - accountCapsule.getFrozenBalance() + - accountCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() + - accountCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth(); - return (long) (frozenV2Resource * ((double) (totalResource - usage) / totalResource)); + remainNetUsage = Math.max(0, remainNetUsage); + return Math.max(0L, frozenV2Resource - remainNetUsage); } if (type == 1) { @@ -171,13 +173,13 @@ public static long queryDelegatableResource(byte[] address, long type, Repositor return frozenV2Resource; } - // total resource - long totalResource = accountCapsule.getAllFrozenBalanceForEnergy(); - if (totalResource <= usage) { - return 0L; - } + long remainEnergyUsage = usage + - accountCapsule.getEnergyFrozenBalance() + - accountCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() + - accountCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy(); - return (long) (frozenV2Resource * ((double) (totalResource - usage) / totalResource)); + remainEnergyUsage = Math.max(0, remainEnergyUsage); + return Math.max(0L, frozenV2Resource - remainEnergyUsage); } return 0L; From 3bdf9dcb5b9e4d0cb1d10f338b98260e1b85747b Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Fri, 30 Dec 2022 16:12:32 +0800 Subject: [PATCH 0523/1197] feat(tvm_stake2.0): fix the test cases for precompiled contract delegatable resource --- .../runtime/vm/PrecompiledContractsTest.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index e0a3577baae..492f9540df2 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -473,13 +473,27 @@ public void delegatableResourceTest() { long currentSlot = latestTimestamp / 3_000; accountCapsule.setLatestConsumeTimeForEnergy(0L); - accountCapsule.setNewWindowSize(Common.ResourceCode.ENERGY, currentSlot * 2); + + // recovered 1/4, usage_left: 15_000_000 + // use delegated first, 10_000_000 + // then, 5_000_000 is delegatable. + accountCapsule.setNewWindowSize(Common.ResourceCode.ENERGY, currentSlot * 4); tempRepository.putAccountValue(address, accountCapsule); res = delegatableResourcePcc.execute(encodeMultiWord(owner, one)); Assert.assertTrue(res.getLeft()); Assert.assertEquals(5_000_000L, ByteArray.toLong(res.getRight())); + // recovered 1/2, usage_left 10_000_000 + // use delegated first, 10_000_000 + // then all the FrozenBalanceForEnergyV2 is delegatable + accountCapsule.setNewWindowSize(Common.ResourceCode.ENERGY, currentSlot * 2); + tempRepository.putAccountValue(address, accountCapsule); + + res = delegatableResourcePcc.execute(encodeMultiWord(owner, one)); + Assert.assertTrue(res.getLeft()); + Assert.assertEquals(10_000_000L, ByteArray.toLong(res.getRight())); + // all recovered. accountCapsule.setNewWindowSize(Common.ResourceCode.ENERGY, currentSlot); tempRepository.putAccountValue(address, accountCapsule); From 7c48dd73ccb22879e7477d6c9474834c75f0178b Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 30 Dec 2022 18:11:43 +0800 Subject: [PATCH 0524/1197] chore(receipt): add some comments --- .../org/tron/core/actuator/VMActuator.java | 2 + .../org/tron/core/capsule/ReceiptCapsule.java | 47 +++++++++++------- .../org/tron/core/db/TransactionTrace.java | 48 +++++++++++-------- 3 files changed, 58 insertions(+), 39 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 2388768f0d5..b4b5b8d6c61 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -564,6 +564,7 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi energyProcessor.increase(account, Common.ResourceCode.ENERGY, account.getEnergyUsage(), min(leftFrozenEnergy, energyFromFeeLimit), now, now)); receipt.setCallerEnergyMergedUsage(account.getEnergyUsage()); + receipt.setCallerEnergyMergedWindowSize(account.getWindowSize(Common.ResourceCode.ENERGY)); rootRepository.updateAccount(account.createDbKey(), account); } return min(availableEnergy, energyFromFeeLimit); @@ -725,6 +726,7 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu energyProcessor.increase(creator, Common.ResourceCode.ENERGY, creator.getEnergyUsage(), creatorEnergyLimit, now, now)); receipt.setOriginEnergyMergedUsage(creator.getEnergyUsage()); + receipt.setOriginEnergyMergedWindowSize(creator.getWindowSize(Common.ResourceCode.ENERGY)); rootRepository.updateAccount(creator.createDbKey(), creator); } return Math.addExact(callerEnergyLimit, creatorEnergyLimit); diff --git a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index 5b362fae120..5d1c3058475 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -1,8 +1,7 @@ package org.tron.core.capsule; import java.util.Objects; -import lombok.Getter; -import lombok.Setter; +import lombok.Data; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.Commons; import org.tron.common.utils.ForkController; @@ -17,48 +16,60 @@ import org.tron.protos.Protocol.ResourceReceipt; import org.tron.protos.Protocol.Transaction.Result.contractResult; +@Data public class ReceiptCapsule { private ResourceReceipt receipt; - @Getter - @Setter + private long multiSignFee; - @Getter - @Setter private long memoFee; + /** * Available energy of contract deployer before executing transaction */ - @Setter private long originEnergyLeft; /** * Available energy of caller before executing transaction */ - @Setter private long callerEnergyLeft; - @Getter - @Setter + /** + * Energy usage of caller before merging frozen energy + */ private long callerEnergyUsage; - @Getter - @Setter + /** + * Energy usage of caller after merging frozen energy + */ private long callerEnergyMergedUsage; - @Getter - @Setter + /** + * Energy usage of origin after merging frozen energy + */ private long originEnergyMergedUsage; - @Getter - @Setter + /** + * Window size of caller before merging frozen energy + */ private long callerEnergyWindowSize; - @Getter - @Setter + /** + * Window size of caller after merging frozen energy + */ + private long callerEnergyMergedWindowSize; + + /** + * Window size of origin before merging frozen energy + */ private long originEnergyWindowSize; + /** + * Window size of origin after merging frozen energy + */ + private long originEnergyMergedWindowSize; + private Sha256Hash receiptAddress; public ReceiptCapsule(ResourceReceipt data, Sha256Hash receiptAddress) { diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java index c879d477ad8..d4527d6186c 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java @@ -251,29 +251,18 @@ public void pay() throws BalanceInsufficientException { // just fo caller is not origin, we set the related field for origin account if (origin != null && !caller.getAddress().equals(origin.getAddress())) { - long originPrevUsage = receipt.getOriginEnergyUsage() * receipt.getOriginEnergyWindowSize(); - long originRepayUsage = (receipt.getOriginEnergyMergedUsage() - origin.getEnergyUsage()) - * origin.getWindowSize(Common.ResourceCode.ENERGY); - - long originUsageAfterRepay = Long.max(0, - (originPrevUsage - originRepayUsage) / receipt.getOriginEnergyWindowSize()); - long originWindowSizeAfterRepay = - originUsageAfterRepay == 0 ? 0L : receipt.getOriginEnergyWindowSize(); - - origin.setEnergyUsage(originUsageAfterRepay); - origin.setNewWindowSize(Common.ResourceCode.ENERGY, originWindowSizeAfterRepay); + resetAccountUsage(origin, + receipt.getOriginEnergyUsage(), + receipt.getOriginEnergyWindowSize(), + receipt.getOriginEnergyMergedUsage(), + receipt.getOriginEnergyMergedWindowSize()); } - long callerPrevUsage = receipt.getCallerEnergyUsage() * receipt.getCallerEnergyWindowSize(); - long callerRepayUsage = (receipt.getCallerEnergyMergedUsage() - caller.getEnergyUsage()) - * caller.getWindowSize(Common.ResourceCode.ENERGY); - - long callerUsageAfterRepay = Long.max(0, - (callerPrevUsage - callerRepayUsage) / receipt.getCallerEnergyWindowSize()); - long callerWindowSizeAfterRepay = - callerUsageAfterRepay == 0 ? 0L : receipt.getCallerEnergyWindowSize(); - caller.setEnergyUsage(callerUsageAfterRepay); - caller.setNewWindowSize(Common.ResourceCode.ENERGY, callerWindowSizeAfterRepay); + resetAccountUsage(caller, + receipt.getCallerEnergyUsage(), + receipt.getCallerEnergyWindowSize(), + receipt.getCallerEnergyMergedUsage(), + receipt.getCallerEnergyMergedWindowSize()); } receipt.payEnergyBill( dynamicPropertiesStore, accountStore, forkController, @@ -284,6 +273,23 @@ public void pay() throws BalanceInsufficientException { EnergyProcessor.getHeadSlot(dynamicPropertiesStore)); } + private void resetAccountUsage(AccountCapsule accountCap, + long usage, long size, long mergedUsage, long mergedSize) { + long currentSize = accountCap.getWindowSize(Common.ResourceCode.ENERGY); + long currentUsage = accountCap.getEnergyUsage(); + // Drop the pre consumed frozen energy + long newArea = currentUsage * currentSize + - (mergedUsage * mergedSize - usage * size); + // If area merging happened during suicide, use the current window size + long newSize = mergedSize == currentSize ? size : currentSize; + // Calc new usage by fixed x-axes + long newUsage = Long.max(0, newArea / newSize); + // Reset account usage and window size + accountCap.setEnergyUsage(newUsage); + accountCap.setNewWindowSize(Common.ResourceCode.ENERGY, + newUsage == 0 ? 0L : newSize); + } + public boolean checkNeedRetry() { if (!needVM()) { return false; From 660ab2bb2490e194644d9d2c2ef0e5ab1a41c446 Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 30 Dec 2022 18:52:49 +0800 Subject: [PATCH 0525/1197] style(receipt): fix code smell --- .../org/tron/core/capsule/ReceiptCapsule.java | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index 5d1c3058475..7653573bf7e 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -1,7 +1,8 @@ package org.tron.core.capsule; import java.util.Objects; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.Commons; import org.tron.common.utils.ForkController; @@ -16,58 +17,77 @@ import org.tron.protos.Protocol.ResourceReceipt; import org.tron.protos.Protocol.Transaction.Result.contractResult; -@Data public class ReceiptCapsule { private ResourceReceipt receipt; + @Getter + @Setter private long multiSignFee; + @Getter + @Setter private long memoFee; /** * Available energy of contract deployer before executing transaction */ + @Setter private long originEnergyLeft; /** * Available energy of caller before executing transaction */ + @Setter private long callerEnergyLeft; /** * Energy usage of caller before merging frozen energy */ + @Getter + @Setter private long callerEnergyUsage; /** * Energy usage of caller after merging frozen energy */ + @Getter + @Setter private long callerEnergyMergedUsage; /** * Energy usage of origin after merging frozen energy */ + @Getter + @Setter private long originEnergyMergedUsage; /** * Window size of caller before merging frozen energy */ + @Getter + @Setter private long callerEnergyWindowSize; /** * Window size of caller after merging frozen energy */ + @Getter + @Setter private long callerEnergyMergedWindowSize; /** * Window size of origin before merging frozen energy */ + @Getter + @Setter private long originEnergyWindowSize; /** * Window size of origin after merging frozen energy */ + @Getter + @Setter private long originEnergyMergedWindowSize; private Sha256Hash receiptAddress; From 02e882726e4f91729274e0af87fd676fef7c6a41 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Mon, 2 Jan 2023 16:07:02 +0800 Subject: [PATCH 0526/1197] feat(DynamicEnergy): optimize call energy usage calculation and estimate function --- actuator/src/main/java/org/tron/core/vm/VM.java | 15 +++++++++------ framework/src/main/java/org/tron/core/Wallet.java | 5 +++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/VM.java b/actuator/src/main/java/org/tron/core/vm/VM.java index 37834752da3..2150df04c64 100644 --- a/actuator/src/main/java/org/tron/core/vm/VM.java +++ b/actuator/src/main/java/org/tron/core/vm/VM.java @@ -48,15 +48,20 @@ public static void play(Program program, JumpTable jumpTable) { /* spend energy before execution */ long energy = op.getEnergyCost(program); if (VMConfig.allowDynamicEnergy()) { + long actualEnergy = energy; + // CALL Ops have special calculation on energy. + if (CALL_OPS.contains(op.getOpcode())) { + actualEnergy = energy + - program.getAdjustedCallEnergy().longValueSafe() + - program.getCallPenaltyEnergy(); + } + energyUsage += actualEnergy; + if (factor > DYNAMIC_ENERGY_FACTOR_DECIMAL) { - long actualEnergy = energy; long penalty; // CALL Ops have special calculation on energy. if (CALL_OPS.contains(op.getOpcode())) { - actualEnergy = energy - - program.getAdjustedCallEnergy().longValueSafe() - - program.getCallPenaltyEnergy(); penalty = program.getCallPenaltyEnergy(); } else { penalty = energy * factor / DYNAMIC_ENERGY_FACTOR_DECIMAL - energy; @@ -66,10 +71,8 @@ public static void play(Program program, JumpTable jumpTable) { energy += penalty; } - energyUsage += actualEnergy; program.spendEnergyWithPenalty(energy, penalty, opName); } else { - energyUsage += energy; program.spendEnergy(energy, opName); } diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 35a95b2df2c..88f7fd890ef 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2874,7 +2874,8 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, long mid = (high + low) / 2; txCap.setFeeLimit(mid); - triggerConstantContract(triggerSmartContract, txCap, txExtBuilder, txRetBuilder); + transaction = triggerConstantContract( + triggerSmartContract, txCap, txExtBuilder, txRetBuilder); if (transaction.getRet(0).getRet().equals(code.FAILED)) { low = mid; } else { @@ -2887,7 +2888,7 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, txCap.setFeeLimit(high); txExtBuilder.clear(); txRetBuilder.clear(); - triggerConstantContract(triggerSmartContract, txCap, txExtBuilder, txRetBuilder); + transaction = triggerConstantContract(triggerSmartContract, txCap, txExtBuilder, txRetBuilder); // Setting estimating result estimateBuilder.setResult(txRetBuilder); From 5a0bcad6a1075e07c34c2d881a8e48fca7099994 Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 2 Jan 2023 16:48:12 +0800 Subject: [PATCH 0527/1197] feat(DynamicEnergy): add proposal dependency --- actuator/src/main/java/org/tron/core/utils/ProposalUtil.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 18586c56a8c..5597f985291 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -633,6 +633,11 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, "This value[ALLOW_DYNAMIC_ENERGY] is only allowed to be in the range 0-1" ); } + if (value == 1 && dynamicPropertiesStore.getChangeDelegation() == 0) { + throw new ContractValidateException( + "[ALLOW_CHANGE_DELEGATION] proposal must be approved " + + "before [ALLOW_DYNAMIC_ENERGY] can be opened"); + } break; } case DYNAMIC_ENERGY_THRESHOLD: { From 783b058d6ef0bf1cc79036c20ec94fadba941000 Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 2 Jan 2023 17:08:50 +0800 Subject: [PATCH 0528/1197] feat(tvm): optimize total weight --- .../CancelAllUnfreezeV2Processor.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java index f818a88b237..888071a177b 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java @@ -4,6 +4,8 @@ import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import java.util.Objects; import lombok.extern.slf4j.Slf4j; @@ -12,7 +14,6 @@ import org.tron.core.capsule.AccountCapsule; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; -import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.vm.nativecontract.param.CancelAllUnfreezeV2Param; import org.tron.core.vm.repository.Repository; import org.tron.protos.Protocol; @@ -63,16 +64,22 @@ public void updateFrozenInfoAndTotalResourceWeight( AccountCapsule accountCapsule, Protocol.Account.UnFreezeV2 unFreezeV2, Repository repo) { switch (unFreezeV2.getType()) { case BANDWIDTH: + long oldNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; accountCapsule.addFrozenBalanceForBandwidthV2(unFreezeV2.getUnfreezeAmount()); - repo.addTotalNetWeight(unFreezeV2.getUnfreezeAmount() / TRX_PRECISION); + long newNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; + repo.addTotalNetWeight(newNetWeight - oldNetWeight); break; case ENERGY: + long oldEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; accountCapsule.addFrozenBalanceForEnergyV2(unFreezeV2.getUnfreezeAmount()); - repo.addTotalEnergyWeight(unFreezeV2.getUnfreezeAmount() / TRX_PRECISION); + long newEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; + repo.addTotalEnergyWeight(newEnergyWeight - oldEnergyWeight); break; case TRON_POWER: + long oldTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; accountCapsule.addFrozenForTronPowerV2(unFreezeV2.getUnfreezeAmount()); - repo.addTotalTronPowerWeight(unFreezeV2.getUnfreezeAmount() / TRX_PRECISION); + long newTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; + repo.addTotalTronPowerWeight(newTPWeight - oldTPWeight); break; default: // this should never happen From cacf53d3c4b9df38d5c9858bdcacef6b489628d3 Mon Sep 17 00:00:00 2001 From: Asuka Date: Tue, 3 Jan 2023 11:44:59 +0800 Subject: [PATCH 0529/1197] chore(prompt): add missing word for estimate energy switch --- framework/src/main/java/org/tron/core/Wallet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 88f7fd890ef..aded985d5b8 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2847,7 +2847,7 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, throws ContractValidateException, ContractExeException, HeaderNotFound, VMIllegalException { if (!Args.getInstance().estimateEnergy) { - throw new ContractValidateException("this node does not estimate energy"); + throw new ContractValidateException("this node does not support estimate energy"); } DynamicPropertiesStore dps = chainBaseManager.getDynamicPropertiesStore(); From 1a001d739116df58b50fcfb2039d9cdf7b98e164 Mon Sep 17 00:00:00 2001 From: Asuka Date: Tue, 3 Jan 2023 12:11:35 +0800 Subject: [PATCH 0530/1197] chore(prompt): optimize the tip when estimate is on & constant is off --- framework/src/main/java/org/tron/core/Wallet.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index aded985d5b8..fce6cad55cf 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2850,6 +2850,11 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, throw new ContractValidateException("this node does not support estimate energy"); } + if (!Args.getInstance().supportConstant) { + throw new ContractValidateException("this node does not support constant, " + + "so estimate energy cannot work"); + } + DynamicPropertiesStore dps = chainBaseManager.getDynamicPropertiesStore(); long high = dps.getMaxFeeLimit(); txCap.setFeeLimit(high); From 918d3dd06a936e5b2cc270f4c83b98833236e897 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Tue, 3 Jan 2023 12:19:56 +0800 Subject: [PATCH 0531/1197] feat(DynamicEnergy): add solidity and pbft estimateEnergy grpc api --- .../org/tron/core/vm/utils/FreezeV2Util.java | 21 ++++++++++-- .../org/tron/core/services/RpcApiService.java | 32 +++++++++++++++++++ .../interfaceOnPBFT/RpcApiServiceOnPBFT.java | 9 ++++++ .../RpcApiServiceOnSolidity.java | 7 ++++ protocol/src/main/protos/api/api.proto | 3 ++ 5 files changed, 69 insertions(+), 3 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index 8d904a139de..eb96c3b9310 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -68,19 +68,34 @@ public static long queryResourceV2(byte[] from, byte[] to, long type, Repository } byte[] key = DelegatedResourceCapsule.createDbKeyV2(from, to, false); + byte[] lockKey = DelegatedResourceCapsule.createDbKeyV2(from, to, true); DelegatedResourceCapsule delegatedResource = repository.getDelegatedResource(key); - if (delegatedResource == null) { + DelegatedResourceCapsule lockDelegateResource = repository.getDelegatedResource(lockKey); + if (delegatedResource == null && lockDelegateResource == null) { return 0; } + long amount = 0; // BANDWIDTH if (type == 0) { - return delegatedResource.getFrozenBalanceForBandwidth(); + if (delegatedResource != null) { + amount += delegatedResource.getFrozenBalanceForBandwidth(); + } + if (lockDelegateResource != null) { + amount += lockDelegateResource.getFrozenBalanceForBandwidth(); + } + return amount; } // ENERGY if (type == 1) { - return delegatedResource.getFrozenBalanceForEnergy(); + if (delegatedResource != null) { + amount += delegatedResource.getFrozenBalanceForEnergy(); + } + if (lockDelegateResource != null) { + amount += lockDelegateResource.getFrozenBalanceForEnergy(); + } + return amount; } return 0; diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 2458e76f800..a6e1c5181ad 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -964,6 +964,38 @@ public void triggerConstantContract(TriggerSmartContract request, callContract(request, responseObserver, true); } + @Override + public void estimateEnergy(TriggerSmartContract request, + StreamObserver responseObserver) { + TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); + Return.Builder retBuilder = Return.newBuilder(); + EstimateEnergyMessage.Builder estimateBuilder + = EstimateEnergyMessage.newBuilder(); + + try { + TransactionCapsule trxCap = createTransactionCapsule(request, + ContractType.TriggerSmartContract); + wallet.estimateEnergy(request, trxCap, trxExtBuilder, retBuilder, estimateBuilder); + } catch (ContractValidateException | VMIllegalException e) { + retBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) + .setMessage(ByteString.copyFromUtf8(Wallet + .CONTRACT_VALIDATE_ERROR + e.getMessage())); + logger.warn(CONTRACT_VALIDATE_EXCEPTION, e.getMessage()); + } catch (RuntimeException e) { + retBuilder.setResult(false).setCode(response_code.CONTRACT_EXE_ERROR) + .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); + logger.warn("When run estimate energy in VM, have Runtime Exception: " + e.getMessage()); + } catch (Exception e) { + retBuilder.setResult(false).setCode(response_code.OTHER_ERROR) + .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); + logger.warn(UNKNOWN_EXCEPTION_CAUGHT + e.getMessage(), e); + } finally { + estimateBuilder.setResult(retBuilder); + responseObserver.onNext(estimateBuilder.build()); + responseObserver.onCompleted(); + } + } + @Override public void getTransactionInfoByBlockNum(NumberMessage request, StreamObserver responseObserver) { diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java index 281714bc083..7232ba01ce5 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java @@ -405,6 +405,15 @@ public void triggerConstantContract(TriggerSmartContract request, ); } + @Override + public void estimateEnergy(TriggerSmartContract request, + StreamObserver responseObserver) { + walletOnPBFT.futureGet( + () -> rpcApiService.getWalletSolidityApi() + .estimateEnergy(request, responseObserver) + ); + } + @Override public void generateAddress(EmptyMessage request, diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java index 2fc4b88de9b..254c5227929 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java @@ -391,6 +391,13 @@ public void triggerConstantContract(TriggerSmartContract request, .triggerConstantContract(request, responseObserver)); } + @Override + public void estimateEnergy(TriggerSmartContract request, + StreamObserver responseObserver) { + walletOnSolidity.futureGet(() -> rpcApiService.getWalletSolidityApi() + .estimateEnergy(request, responseObserver)); + } + @Override public void generateAddress(EmptyMessage request, diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 394cc3adf56..48cd64acc5b 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -1012,6 +1012,9 @@ service WalletSolidity { rpc TriggerConstantContract (TriggerSmartContract) returns (TransactionExtention) { } + rpc EstimateEnergy (TriggerSmartContract) returns (EstimateEnergyMessage) { + } + rpc GetTransactionInfoByBlockNum (NumberMessage) returns (TransactionInfoList) { } From 6026e44f5cbbd938734bb0700869c267cd4f5765 Mon Sep 17 00:00:00 2001 From: Marcus Date: Tue, 3 Jan 2023 13:38:24 +0800 Subject: [PATCH 0532/1197] add integrity check --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d0ee5fc1f15..038abe6406f 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,11 @@ Thank you for considering to help out with the source code! If you'd like to con * [Wallet-cli](https://github.com/tronprotocol/wallet-cli) TRON network wallet using command line. * [TIP](https://github.com/tronprotocol/tips) TRON Improvement Proposal (TIP) describes standards for the TRON network. * [TP](https://github.com/tronprotocol/tips/tree/master/tp) TRON Protocol (TP) describes standards already implemented in TRON network but not published as a TIP. - +# Integrity Check +* After January 3, 2023, releases are signed the gpg key: + ``` + pub: 1254 F859 D2B1 BD9F 66E7 107D F859 BCB4 4A28 290B + uid: build@tron.network + ``` # License java-tron is released under the [LGPLv3 license](https://github.com/tronprotocol/java-tron/blob/master/LICENSE). From 82987949b0dc90357e35ced209875126f49ddab3 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Tue, 3 Jan 2023 16:25:42 +0800 Subject: [PATCH 0533/1197] feat(DynamicEnergy): optimize program result penalty merge --- .../src/main/java/org/tron/common/runtime/ProgramResult.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java b/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java index 221ac89dd0b..04228d1316a 100644 --- a/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java +++ b/chainbase/src/main/java/org/tron/common/runtime/ProgramResult.java @@ -238,10 +238,10 @@ public void reset() { public void merge(ProgramResult another) { addInternalTransactions(another.getInternalTransactions()); + addTotalPenalty(another.getEnergyPenaltyTotal()); if (another.getException() == null && !another.isRevert()) { addDeleteAccounts(another.getDeleteAccounts()); addLogInfos(another.getLogInfoList()); - addTotalPenalty(another.getEnergyPenaltyTotal()); //addFutureRefund(another.getFutureRefund()); //addTouchAccounts(another.getTouchedAccounts()); } From ceb3aef15365b1ac0c9a3007e04487a45fccd2d5 Mon Sep 17 00:00:00 2001 From: Asuka Date: Tue, 3 Jan 2023 17:17:46 +0800 Subject: [PATCH 0534/1197] chore(comment): remove fix me cause we have confirmed it needed --- .../src/main/java/org/tron/core/vm/PrecompiledContracts.java | 1 - .../org/tron/core/vm/nativecontract/VoteWitnessProcessor.java | 1 - 2 files changed, 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index dcd9ba1a2a3..66d2095f999 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -1791,7 +1791,6 @@ public Pair execute(byte[] data) { if (accountCapsule == null) { tronPower = 0; } else { - // fixme check if supportUnfreezeDelay needed if (getDeposit().getDynamicPropertiesStore().supportUnfreezeDelay() && getDeposit().getDynamicPropertiesStore().supportAllowNewResourceModel()) { tronPower = accountCapsule.getAllTronPower(); diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/VoteWitnessProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/VoteWitnessProcessor.java index f499562ea39..8e17ffe8b13 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/VoteWitnessProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/VoteWitnessProcessor.java @@ -86,7 +86,6 @@ public void execute(VoteWitnessParam param, Repository repo) throws ContractExeE } long tronPower; - // fixme check if supportUnfreezeDelay needed if (repo.getDynamicPropertiesStore().supportUnfreezeDelay() && repo.getDynamicPropertiesStore().supportAllowNewResourceModel()) { tronPower = accountCapsule.getAllTronPower(); From 0dfe97dd8c0daa2bba40fb068b0b34b1edd6f524 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 3 Jan 2023 18:12:16 +0800 Subject: [PATCH 0535/1197] feat(net):optimize peer connect log --- .../main/java/org/tron/core/net/peer/PeerConnection.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index ae9f3169d6e..9893b3e4db8 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -194,6 +194,8 @@ public void onDisconnect() { public String log() { long now = System.currentTimeMillis(); + BlockId syncBlockId = syncBlockToFetch.peek(); + Pair, Long> requested = syncChainRequested; return String.format( "Peer %s\n" + "connect time: %ds [%sms]\n" @@ -213,10 +215,10 @@ public String log() { isNeedSyncFromPeer(), isNeedSyncFromUs(), syncBlockToFetch.size(), - !syncBlockToFetch.isEmpty() ? syncBlockToFetch.peek().getNum() : -1, + syncBlockId != null ? syncBlockId.getNum() : -1, syncBlockRequested.size(), remainNum, - syncChainRequested == null ? 0 : (now - syncChainRequested.getValue()) + requested == null ? 0 : (now - requested.getValue()) / Constant.ONE_THOUSAND, syncBlockInProcess.size()); } From 8fbc7ef0182e57e5d0b215ea66b442a8e47cdbe0 Mon Sep 17 00:00:00 2001 From: Asuka Date: Tue, 3 Jan 2023 21:58:57 +0800 Subject: [PATCH 0536/1197] feat(stake2.0): withdraw reward first --- .../UnfreezeBalanceV2Processor.java | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index d8f259385e3..f4d5c407373 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -1,7 +1,17 @@ package org.tron.core.vm.nativecontract; +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; + import com.google.common.collect.Lists; import com.google.protobuf.ByteString; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; @@ -17,17 +27,6 @@ import org.tron.protos.Protocol; import org.tron.protos.contract.Common; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; -import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; -import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; -import static org.tron.protos.contract.Common.ResourceCode.ENERGY; - @Slf4j(topic = "VMProcessor") public class UnfreezeBalanceV2Processor { @@ -119,10 +118,10 @@ private boolean checkExistFrozenBalance(AccountCapsule accountCapsule, Common.Re public long execute(UnfreezeBalanceV2Param param, Repository repo) { byte[] ownerAddress = param.getOwnerAddress(); long unfreezeBalance = param.getUnfreezeBalance(); + VoteRewardUtil.withdrawReward(ownerAddress, repo); AccountCapsule accountCapsule = repo.getAccount(ownerAddress); long now = repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); - VoteRewardUtil.withdrawReward(ownerAddress, repo); long unfreezeExpireBalance = this.unfreezeExpire(accountCapsule, now); From 79c5e578d4f0e22e8d8d861d3ed1a2438c960803 Mon Sep 17 00:00:00 2001 From: "morgan.peng" Date: Wed, 21 Dec 2022 15:11:59 +0800 Subject: [PATCH 0537/1197] feat(db): optimize internal db log print 1. optimize internal db log print --- .../leveldb/LevelDbDataSourceImpl.java | 45 ++------ .../rocksdb/RocksDbDataSourceImpl.java | 2 +- .../common/log/layout/MultiLayoutPattern.java | 106 ++++++++++++++++++ framework/src/main/resources/logback.xml | 13 ++- 4 files changed, 125 insertions(+), 41 deletions(-) create mode 100644 common/src/main/java/org/tron/common/log/layout/MultiLayoutPattern.java diff --git a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java index a198217a000..54df4946297 100644 --- a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java @@ -73,7 +73,13 @@ public class LevelDbDataSourceImpl extends DbStat implements DbSourceInter> stream() { return StreamSupport.stream(spliterator(), false); } - public Stream> parallelStream() { - return StreamSupport.stream(spliterator(), true); - } - @Override public LevelDbDataSourceImpl newInstance() { return new LevelDbDataSourceImpl(StorageUtils.getOutputDirectoryByDbName(dataBaseName), diff --git a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java index 74b1ecc0a05..a561ed1fa11 100644 --- a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java @@ -236,7 +236,7 @@ public void initDB(RocksDbSettings settings) { options.setLogger(new Logger(options) { @Override protected void log(InfoLogLevel infoLogLevel, String logMsg) { - rocksDbLogger.info(logMsg); + rocksDbLogger.info("{} {}", dataBaseName, logMsg); } }); diff --git a/common/src/main/java/org/tron/common/log/layout/MultiLayoutPattern.java b/common/src/main/java/org/tron/common/log/layout/MultiLayoutPattern.java new file mode 100644 index 00000000000..9fde78c1a7b --- /dev/null +++ b/common/src/main/java/org/tron/common/log/layout/MultiLayoutPattern.java @@ -0,0 +1,106 @@ +package org.tron.common.log.layout; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.encoder.PatternLayoutEncoder; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.Layout; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MultiLayoutPattern extends PatternLayoutEncoder { + private List rules = new ArrayList<>(); + private Map> layoutMap = new HashMap<>(); + + public void addRule(Rule rule) { + this.rules.add(rule); + rule.start(context); + } + + public byte[] encode(ILoggingEvent event) { + Layout layout = getLayout(event.getLoggerName()); + String txt = layout.doLayout(event); + return convertToBytes(txt); + } + + private byte[] convertToBytes(String s) { + Charset charset = getCharset(); + if (charset == null) { + return s.getBytes(); + } else { + return s.getBytes(charset); + } + } + + private Layout getLayout(final String name) { + if (name == null) { + throw new IllegalArgumentException("name cannot be null"); + } + if (Logger.ROOT_LOGGER_NAME.equalsIgnoreCase(name)) { + return this.getLayout(); + } + if (layoutMap.containsKey(name)) { + return layoutMap.get(name); + } + Layout layout = getLayout(); + for (Rule rule : rules) { + if (rule.logger.equals(name)) { + layout = rule.getPatternLayoutEncoder().getLayout(); + break; + } + } + layoutMap.put(name, layout); + return layout; + } + + @Override + public void start() { + super.start(); + } + + public static class Rule { + private String logger; + private String pattern; + private PatternLayoutEncoder patternLayoutEncoder; + private boolean outputPatternAsHeader = false; + + public String getLogger() { + return logger; + } + + public void setLogger(String logger) { + this.logger = logger; + } + + public String getPattern() { + return pattern; + } + + public void setPattern(String pattern) { + this.pattern = pattern; + } + + public boolean isOutputPatternAsHeader() { + return outputPatternAsHeader; + } + + public void setOutputPatternAsHeader(boolean outputPatternAsHeader) { + this.outputPatternAsHeader = outputPatternAsHeader; + } + + public PatternLayoutEncoder getPatternLayoutEncoder() { + return patternLayoutEncoder; + } + + public void start(Context context) { + patternLayoutEncoder = new PatternLayoutEncoder(); + patternLayoutEncoder.setPattern(pattern); + patternLayoutEncoder.setContext(context); + patternLayoutEncoder.setOutputPatternAsHeader(outputPatternAsHeader); + patternLayoutEncoder.start(); + } + } +} \ No newline at end of file diff --git a/framework/src/main/resources/logback.xml b/framework/src/main/resources/logback.xml index 5f180be405b..136d6342f9f 100644 --- a/framework/src/main/resources/logback.xml +++ b/framework/src/main/resources/logback.xml @@ -26,8 +26,16 @@ 7 50GB - + %d{HH:mm:ss.SSS} %-5level [%t] [%c{1}]\(%F:%L\) %m%n + + LEVELDB + %d{HH:mm:ss.SSS} %m%n + + + ROCKSDB + %d{HH:mm:ss.SSS} %m%n + TRACE @@ -69,7 +77,8 @@ - + + From fb8b872a15f802885b9106577b2a531e40b4059a Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 4 Jan 2023 12:13:44 +0800 Subject: [PATCH 0538/1197] fix(freezeV2): optimize the accuracy of usage --- .../src/main/java/org/tron/core/db/ResourceProcessor.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java index 1442780f33a..7603a25313a 100644 --- a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java @@ -80,8 +80,7 @@ public long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, } } - long newUsage = getUsage(averageLastUsage, oldWindowSize) - + getUsage(averageUsage, this.windowSize); + long newUsage = getUsage(averageLastUsage, oldWindowSize, averageUsage, this.windowSize); if (dynamicPropertiesStore.supportUnfreezeDelay()) { long remainUsage = getUsage(averageLastUsage, oldWindowSize); if (remainUsage == 0) { @@ -130,6 +129,10 @@ private long getUsage(long usage, long windowSize) { return usage * windowSize / precision; } + private long getUsage(long oldUsage, long oldWindowSize, long newUsage, long newWindowSize) { + return (oldUsage * oldWindowSize + newUsage * newWindowSize) / precision; + } + protected boolean consumeFeeForBandwidth(AccountCapsule accountCapsule, long fee) { try { long latestOperationTime = dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); From e5d86e6579ab6c3d254c69c88fc6d98913756a0c Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 4 Jan 2023 15:09:54 +0800 Subject: [PATCH 0539/1197] docs(readme): update hardware requirements --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d0ee5fc1f15..d489cb3aeb8 100644 --- a/README.md +++ b/README.md @@ -81,17 +81,17 @@ $ ./gradlew clean build -x test # Running java-tron Running java-tron requires `Oracle JDK 1.8` to be installed, other JDK versions are not supported yet. Make sure you operate on `Linux` and `MacOS` operating systems. -Get the mainnet configurate file: [main_net_config.conf](https://github.com/tronprotocol/tron-deployment/blob/master/main_net_config.conf), other network configuration files can be find [here](https://github.com/tronprotocol/tron-deployment). +Get the mainnet configuration file: [main_net_config.conf](https://github.com/tronprotocol/tron-deployment/blob/master/main_net_config.conf), other network configuration files can be find [here](https://github.com/tronprotocol/tron-deployment). ## Hardware Requirements Minimum: * CPU with 8 cores * 16GB RAM -* 1TB free storage space to sync the Mainnet +* 2TB free storage space to sync the Mainnet Recommended: * CPU with 16+ cores(32+ cores for a super representative) * 32GB+ RAM(64GB+ for a super representative) -* High Performance SSD with at least 1.5TB free space +* High Performance SSD with at least 2.5TB free space * 100+ MB/s download Internet service From 3eaa998690a3f1a24fb85c682170f84982558178 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 4 Jan 2023 14:16:26 +0800 Subject: [PATCH 0540/1197] fix(block): fix block size estimation during block production --- .../org/tron/core/capsule/BlockCapsule.java | 4 + .../tron/core/capsule/TransactionCapsule.java | 13 ++ .../main/java/org/tron/core/db/Manager.java | 15 +- .../java/org/tron/core/db/SerializedTest.java | 129 ++++++++++++++++++ 4 files changed, 154 insertions(+), 7 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/db/SerializedTest.java diff --git a/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java index 4853de64116..8baafcb5dd5 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java @@ -284,6 +284,10 @@ public Block getInstance() { return this.block; } + public long getSerializedSize() { + return this.block.getSerializedSize(); + } + public Sha256Hash getParentHash() { return Sha256Hash.wrap(this.block.getBlockHeader().getRawData().getParentHash()); } diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java index d3b7772693f..1d043ef112b 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -23,6 +23,7 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; import com.google.protobuf.CodedInputStream; +import com.google.protobuf.CodedOutputStream; import com.google.protobuf.GeneratedMessageV3; import com.google.protobuf.Internal; import com.google.protobuf.InvalidProtocolBufferException; @@ -695,6 +696,18 @@ public long getSerializedSize() { return this.transaction.getSerializedSize(); } + /** + * Compute the number of bytes that would be needed to encode an embedded message field, including + * tag. + * message Block { + * repeated Transaction transactions = 1; + * BlockHeader block_header = 2; + * } + */ + public long computeTrxSizeForBlockMessage() { + return CodedOutputStream.computeMessageSize(1, this.transaction); + } + public long getResultSerializedSize() { long size = 0; for (Result result : this.transaction.getRetList()) { diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 41f948836b9..b43387ec4f6 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1570,7 +1570,8 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { } // check the block size - if ((currentSize + trx.getSerializedSize() + 3) + long trxPackSize = trx.computeTrxSizeForBlockMessage(); + if ((currentSize + trxPackSize) > ChainConstant.BLOCK_SIZE) { postponedTrxCount++; continue; // try pack more small trx @@ -1601,7 +1602,7 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { accountStateCallBack.exeTransFinish(); tmpSession.merge(); toBePacked.add(trx); - currentSize += trx.getSerializedSize() + 2; // proto tag num is 1 , so tag size is 2 + currentSize += trxPackSize; } catch (Exception e) { logger.error("Process trx {} failed when generating block {}, {}.", trx.getTransactionId(), blockCapsule.getNum(), e.getMessage()); @@ -1612,17 +1613,17 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { session.reset(); - logger.info("Generate block {} success, trxs:{}, pendingCount: {}, rePushCount: {}," - + " postponedCount: {}, blockSize: {} B", - blockCapsule.getNum(), blockCapsule.getTransactions().size(), - pendingTransactions.size(), rePushTransactions.size(), postponedTrxCount, currentSize); - blockCapsule.setMerkleRoot(); blockCapsule.sign(miner.getPrivateKey()); BlockCapsule capsule = new BlockCapsule(blockCapsule.getInstance()); capsule.generatedByMyself = true; Metrics.histogramObserve(timer); + logger.info("Generate block {} success, trxs:{}, pendingCount: {}, rePushCount: {}," + + " postponedCount: {}, blockSize: {} B", + capsule.getNum(), capsule.getTransactions().size(), + pendingTransactions.size(), rePushTransactions.size(), postponedTrxCount, + capsule.getSerializedSize()); return capsule; } diff --git a/framework/src/test/java/org/tron/core/db/SerializedTest.java b/framework/src/test/java/org/tron/core/db/SerializedTest.java new file mode 100644 index 00000000000..221ca5e1139 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/SerializedTest.java @@ -0,0 +1,129 @@ +package org.tron.core.db; + +import com.google.protobuf.ByteString; +import com.google.protobuf.CodedOutputStream; +import com.google.protobuf.InvalidProtocolBufferException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import org.junit.Assert; +import org.junit.Test; +import org.tron.common.utils.ByteArray; +import org.tron.protos.Protocol; + +public class SerializedTest { + + + @Test + public void SerializedSize() throws InvalidProtocolBufferException { + // block header raw + Protocol.BlockHeader.raw.Builder blockHeaderRawBuild = Protocol.BlockHeader.raw.newBuilder(); + Protocol.BlockHeader.raw blockHeaderRaw = blockHeaderRawBuild + .setNumber(47377682) + .setParentHash(ByteString.copyFrom(ByteArray.fromHexString( + "0000000002d2ed11cac713f84349dde3c1a4af38b8480fdb72c6c41a315abf25"))) + .setTimestamp(1672734363000L) + .setVersion(26) + .setWitnessAddress(ByteString.copyFrom(ByteArray.fromHexString( + "41af619f8ce75a9e95a19e851bebe63e89fcb1826e"))) + .setTxTrieRoot(ByteString.copyFrom(ByteArray.fromHexString( + "8b006c280022d325a1eb6a64f0b9ca6ce9e23bcc380fb07d58be397219f935b3"))) + .build(); + + // block header + Protocol.BlockHeader.Builder blockHeaderBuild = Protocol.BlockHeader.newBuilder(); + Protocol.BlockHeader blockHeader = blockHeaderBuild.setRawData(blockHeaderRaw) + .setWitnessSignature(ByteString.copyFrom(ByteArray.fromHexString( + "aae20ba4216a2797fd4ece92e9b0748a30bf547a58c03ba8e1b9c818ea8f24b12afd4da" + + "d6f6d246428d641d695d204d5749af93340da90d0f52b0436dd1853ae00"))) + .build(); + + // block + Protocol.Block.Builder blockBuild = Protocol.Block.newBuilder(); + + blockBuild.setBlockHeader(blockHeader).build(); + long current = blockBuild.build().getSerializedSize(); + + byte[] data = new byte[512 * 1_0240]; + + for (int i = 0; i < 512 * 1_0240; i++) { + data[i] = (byte) i; + } + Protocol.Transaction large = Protocol.Transaction.newBuilder().setRawData( + Protocol.Transaction.raw.newBuilder().setData( + ByteString.copyFrom(data)).build()).build(); + Protocol.Transaction t = Protocol.Transaction.parseFrom(ByteString.copyFrom( + ByteArray.fromHexString( + "0aab010a080000018576b86dec220d3136373237333430373633393640ecdbe1b5d7305222544e66" + + "584555517359584355507641474e7448476b716d636e797050783947566e6a5a65080112610a" + + "2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572" + + "436f6e747261637412300a1541f08012b4881c320eb40b80f1228731898824e09d121541878e" + + "5427dec577ec5cb0bbcc6056837cb1926f2d1801124135eda8606f37f9d80625533832830853" + + "8b413ba3594a53d810deb3c657aa567e6e3fc52854737dc68f40d69e0e78e67df8edc508de43" + + "38c56d5acafb2797eec6002a021801"))); + Protocol.Transaction small = Protocol.Transaction.newBuilder().setRawData( + Protocol.Transaction.raw.newBuilder().setData( + ByteString.copyFrom("1".getBytes(StandardCharsets.UTF_8))).build()).build(); + + + Protocol.Transaction min = Protocol.Transaction.getDefaultInstance(); + int c = 300; + List l = new ArrayList<>(); + l.add(large); + l.add(t); + l.add(small); + l.add(min); + Random r = new Random(); + for (int i = 0; i < c; i++) { + Protocol.Transaction transaction = l.get(r.nextInt(l.size())); + current += CodedOutputStream.computeMessageSize(1, transaction); + blockBuild.addTransactions(transaction); + } + long aft = blockBuild.build().getSerializedSize(); + Assert.assertEquals(aft, current); + + Protocol.Account.Builder account = Protocol.Account.newBuilder(); + long base = account.build().getSerializedSize(); + Protocol.Vote vote = Protocol.Vote.newBuilder().setVoteAddress(ByteString.copyFrom("1".getBytes( + StandardCharsets.UTF_8))).build(); + account.addVotes(vote); + long v1 = vote.getSerializedSize(); + long a1 = account.build().getSerializedSize(); + Assert.assertEquals(a1 - base, + CodedOutputStream.computeTagSize(5) + + CodedOutputStream.computeInt64SizeNoTag(v1) + v1); + Protocol.Vote vote2 = Protocol.Vote.newBuilder().setVoteAddress( + ByteString.copyFrom("2".getBytes(StandardCharsets.UTF_8))).build(); + account.addVotes(vote2); + long v2 = vote2.getSerializedSize(); + long a2 = account.build().getSerializedSize(); + Assert.assertEquals(a2 - a1, + CodedOutputStream.computeTagSize(5) + + CodedOutputStream.computeInt64SizeNoTag(v2) + v2); + Protocol.Account.Frozen frozen = Protocol.Account.Frozen.newBuilder() + .setFrozenBalance(1).build(); + long currentSize = a2; + long cc = 0; + for (int i = 0; i < 1000; i++) { + if ((currentSize += CodedOutputStream.computeMessageSize(7, frozen)) > 1600) { + break; + } + account.addFrozen(frozen); + cc = i + 1; + } + + long a3 = account.build().getSerializedSize(); + Assert.assertEquals((a3 - a2) / cc, + CodedOutputStream.computeTagSize(7) + + CodedOutputStream.computeInt64SizeNoTag(frozen.getSerializedSize()) + + frozen.getSerializedSize()); + + Protocol.Permission p = Protocol.Permission.newBuilder().build(); + long p1 = p.getSerializedSize(); + account.addActivePermission(p); + long a4 = account.build().getSerializedSize(); + Assert.assertEquals(a4 - a3, CodedOutputStream.computeTagSize(33) + + CodedOutputStream.computeInt64SizeNoTag(p1) + p1); + } +} From edda4b2abb193f42790e5499a5ba7d11ee5521db Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Wed, 4 Jan 2023 20:21:56 +0800 Subject: [PATCH 0541/1197] feat(EstimateEnergy): optimize estimate search algorithm and add retry --- .../common/parameter/CommonParameter.java | 3 + .../src/main/java/org/tron/core/Constant.java | 2 + .../src/main/java/org/tron/core/Wallet.java | 73 +++++++++++++++++-- .../java/org/tron/core/config/args/Args.java | 3 + 4 files changed, 73 insertions(+), 8 deletions(-) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 87c5a644668..571ab968671 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -299,6 +299,9 @@ public class CommonParameter { public boolean estimateEnergy; @Getter @Setter + public int estimateEnergyMaxRetry; + @Getter + @Setter public int backupPriority; @Getter @Setter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 32595de0e5b..408782752f2 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -70,6 +70,8 @@ public class Constant { public static final String VM_LONG_RUNNING_TIME = "vm.longRunningTime"; public static final String VM_ESTIMATE_ENERGY = "vm.estimateEnergy"; + public static final String VM_ESTIMATE_ENERGY_MAX_RETRY = "vm.estimateEnergyMaxRetry"; + public static final String ROCKSDB = "ROCKSDB"; public static final String GENESIS_BLOCK = "genesis.block"; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index fce6cad55cf..02eb617b0f5 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -189,6 +189,7 @@ import org.tron.core.store.MarketPairPriceToOrderStore; import org.tron.core.store.MarketPairToPriceStore; import org.tron.core.store.StoreFactory; +import org.tron.core.vm.program.Program; import org.tron.core.zen.ShieldedTRC20ParametersBuilder; import org.tron.core.zen.ShieldedTRC20ParametersBuilder.ShieldedTRC20ParametersType; import org.tron.core.zen.ZenTransactionBuilder; @@ -2854,13 +2855,29 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, throw new ContractValidateException("this node does not support constant, " + "so estimate energy cannot work"); } + int retry = Args.getInstance().estimateEnergyMaxRetry; DynamicPropertiesStore dps = chainBaseManager.getDynamicPropertiesStore(); long high = dps.getMaxFeeLimit(); txCap.setFeeLimit(high); - Transaction transaction = triggerConstantContract( - triggerSmartContract, txCap, txExtBuilder, txRetBuilder); + Transaction transaction; + + while (true) { + try { + txCap.resetResult(); + txExtBuilder.clear(); + txRetBuilder.clear(); + transaction = triggerConstantContract( + triggerSmartContract, txCap, txExtBuilder, txRetBuilder); + break; + } catch (Program.OutOfTimeException e) { + retry--; + if (retry < 0) { + throw e; + } + } + } // If failed, return directly. if (transaction.getRet(0).getRet().equals(code.FAILED)) { @@ -2871,20 +2888,60 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, long low = dps.getEnergyFee() * txExtBuilder.getEnergyUsed(); + long twoTimes = low * 2; + if (twoTimes < high) { + txCap.setFeeLimit(twoTimes); + while (true) { + try { + txCap.resetResult(); + txExtBuilder.clear(); + txRetBuilder.clear(); + transaction = triggerConstantContract( + triggerSmartContract, txCap, txExtBuilder, txRetBuilder); + + if (transaction.getRet(0).getRet().equals(code.SUCESS)) { + high = twoTimes; + } + + break; + } catch (Program.OutOfTimeException e) { + retry--; + if (retry < 0) { + throw e; + } + } + } + } + while (low + TRX_PRECISION < high) { // clean the prev exec data. txCap.resetResult(); txExtBuilder.clear(); txRetBuilder.clear(); - long mid = (high + low) / 2; - txCap.setFeeLimit(mid); - transaction = triggerConstantContract( - triggerSmartContract, txCap, txExtBuilder, txRetBuilder); + long quarter = low + (high - low) / 4; + txCap.setFeeLimit(quarter); + + while (true) { + try { + txCap.resetResult(); + txExtBuilder.clear(); + txRetBuilder.clear(); + transaction = triggerConstantContract( + triggerSmartContract, txCap, txExtBuilder, txRetBuilder); + break; + } catch (Program.OutOfTimeException e) { + retry--; + if (retry < 0) { + throw e; + } + } + } + if (transaction.getRet(0).getRet().equals(code.FAILED)) { - low = mid; + low = quarter; } else { - high = mid; + high = quarter; } } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index ef300a77bc3..e5ba213b144 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -169,6 +169,7 @@ public static void clearParam() { PARAMETER.trustNodeAddr = ""; PARAMETER.walletExtensionApi = false; PARAMETER.estimateEnergy = false; + PARAMETER.estimateEnergyMaxRetry = 3; PARAMETER.receiveTcpMinDataLength = 2048; PARAMETER.isOpenFullTcpDisconnect = false; PARAMETER.supportConstant = false; @@ -796,6 +797,8 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.estimateEnergy = config.hasPath(Constant.VM_ESTIMATE_ENERGY) && config.getBoolean(Constant.VM_ESTIMATE_ENERGY); + PARAMETER.estimateEnergyMaxRetry = config.hasPath(Constant.VM_ESTIMATE_ENERGY_MAX_RETRY) + ? config.getInt(Constant.VM_ESTIMATE_ENERGY_MAX_RETRY) : 3; PARAMETER.receiveTcpMinDataLength = config.hasPath(Constant.NODE_RECEIVE_TCP_MIN_DATA_LENGTH) ? config.getLong(Constant.NODE_RECEIVE_TCP_MIN_DATA_LENGTH) : 2048; From d10caae3844f0af158011603992e845a5911c7f6 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Thu, 5 Jan 2023 11:41:29 +0800 Subject: [PATCH 0542/1197] feat(EstimateEnergy): optimize estimate energy search --- framework/src/main/java/org/tron/core/Wallet.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 02eb617b0f5..6a4bb49818b 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2899,7 +2899,9 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, transaction = triggerConstantContract( triggerSmartContract, txCap, txExtBuilder, txRetBuilder); - if (transaction.getRet(0).getRet().equals(code.SUCESS)) { + if (transaction.getRet(0).getRet().equals(code.FAILED)) { + low = twoTimes; + } else { high = twoTimes; } From 59aadbdccbb8f430e56a34c70f310dfb6db15542 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Thu, 5 Jan 2023 14:30:19 +0800 Subject: [PATCH 0543/1197] feat(EstimateEnergy): optimize the estimate energy search and add restrict parameters range --- framework/src/main/java/org/tron/core/Wallet.java | 8 ++++---- .../src/main/java/org/tron/core/config/args/Args.java | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 6a4bb49818b..666729e812d 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2921,8 +2921,8 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, txExtBuilder.clear(); txRetBuilder.clear(); - long quarter = low + (high - low) / 4; - txCap.setFeeLimit(quarter); + long mid = (low + high) / 2; + txCap.setFeeLimit(mid); while (true) { try { @@ -2941,9 +2941,9 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, } if (transaction.getRet(0).getRet().equals(code.FAILED)) { - low = quarter; + low = mid; } else { - high = quarter; + high = mid; } } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index e5ba213b144..f27ff3c2385 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -799,6 +799,12 @@ public static void setParam(final String[] args, final String confFileName) { && config.getBoolean(Constant.VM_ESTIMATE_ENERGY); PARAMETER.estimateEnergyMaxRetry = config.hasPath(Constant.VM_ESTIMATE_ENERGY_MAX_RETRY) ? config.getInt(Constant.VM_ESTIMATE_ENERGY_MAX_RETRY) : 3; + if (PARAMETER.estimateEnergyMaxRetry < 0) { + PARAMETER.estimateEnergyMaxRetry = 0; + } + if (PARAMETER.estimateEnergyMaxRetry > 10) { + PARAMETER.estimateEnergyMaxRetry = 10; + } PARAMETER.receiveTcpMinDataLength = config.hasPath(Constant.NODE_RECEIVE_TCP_MIN_DATA_LENGTH) ? config.getLong(Constant.NODE_RECEIVE_TCP_MIN_DATA_LENGTH) : 2048; From abedf533c69bb666e88ef522f0cf7cbebbc831b4 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Thu, 5 Jan 2023 14:39:44 +0800 Subject: [PATCH 0544/1197] feat(EstimateEnergy): refactor estimate energy function --- .../src/main/java/org/tron/core/Wallet.java | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 666729e812d..0f384810c60 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2865,10 +2865,7 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, while (true) { try { - txCap.resetResult(); - txExtBuilder.clear(); - txRetBuilder.clear(); - transaction = triggerConstantContract( + transaction = cleanContextAndTriggerConstantContract( triggerSmartContract, txCap, txExtBuilder, txRetBuilder); break; } catch (Program.OutOfTimeException e) { @@ -2893,10 +2890,7 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, txCap.setFeeLimit(twoTimes); while (true) { try { - txCap.resetResult(); - txExtBuilder.clear(); - txRetBuilder.clear(); - transaction = triggerConstantContract( + transaction = cleanContextAndTriggerConstantContract( triggerSmartContract, txCap, txExtBuilder, txRetBuilder); if (transaction.getRet(0).getRet().equals(code.FAILED)) { @@ -2926,10 +2920,7 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, while (true) { try { - txCap.resetResult(); - txExtBuilder.clear(); - txRetBuilder.clear(); - transaction = triggerConstantContract( + transaction = cleanContextAndTriggerConstantContract( triggerSmartContract, txCap, txExtBuilder, txRetBuilder); break; } catch (Program.OutOfTimeException e) { @@ -2948,12 +2939,9 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, } // Retry the binary search result - txCap.resetResult(); txCap.setFeeLimit(high); - txExtBuilder.clear(); - txRetBuilder.clear(); - transaction = triggerConstantContract(triggerSmartContract, txCap, txExtBuilder, txRetBuilder); - + transaction = cleanContextAndTriggerConstantContract( + triggerSmartContract, txCap, txExtBuilder, txRetBuilder); // Setting estimating result estimateBuilder.setResult(txRetBuilder); if (transaction.getRet(0).getRet().equals(code.SUCESS)) { @@ -2965,6 +2953,19 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, return transaction; } + private Transaction cleanContextAndTriggerConstantContract( + TriggerSmartContract triggerSmartContract, TransactionCapsule txCap, + Builder txExtBuilder, Return.Builder txRetBuilder) + throws ContractValidateException, ContractExeException, HeaderNotFound, VMIllegalException { + Transaction transaction; + txCap.resetResult(); + txExtBuilder.clear(); + txRetBuilder.clear(); + transaction = triggerConstantContract( + triggerSmartContract, txCap, txExtBuilder, txRetBuilder); + return transaction; + } + public Transaction triggerConstantContract(TriggerSmartContract triggerSmartContract, TransactionCapsule trxCap, Builder builder, Return.Builder retBuilder) throws ContractValidateException, ContractExeException, HeaderNotFound, VMIllegalException { From 86bebba8279956934ccc0c26cc5417a860204b68 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Thu, 5 Jan 2023 14:52:29 +0800 Subject: [PATCH 0545/1197] feat(EstimateEnergy): refactor estimate energy function --- .../src/main/java/org/tron/core/Wallet.java | 20 ++++++------------- .../services/jsonrpc/TronJsonRpcImpl.java | 7 +------ framework/src/main/resources/config.conf | 8 +++++++- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 0f384810c60..bcefbb9b2f1 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2859,14 +2859,13 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, DynamicPropertiesStore dps = chainBaseManager.getDynamicPropertiesStore(); long high = dps.getMaxFeeLimit(); - txCap.setFeeLimit(high); Transaction transaction; while (true) { try { transaction = cleanContextAndTriggerConstantContract( - triggerSmartContract, txCap, txExtBuilder, txRetBuilder); + triggerSmartContract, txCap, txExtBuilder, txRetBuilder, high); break; } catch (Program.OutOfTimeException e) { retry--; @@ -2887,11 +2886,10 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, long twoTimes = low * 2; if (twoTimes < high) { - txCap.setFeeLimit(twoTimes); while (true) { try { transaction = cleanContextAndTriggerConstantContract( - triggerSmartContract, txCap, txExtBuilder, txRetBuilder); + triggerSmartContract, txCap, txExtBuilder, txRetBuilder, twoTimes); if (transaction.getRet(0).getRet().equals(code.FAILED)) { low = twoTimes; @@ -2910,18 +2908,12 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, } while (low + TRX_PRECISION < high) { - // clean the prev exec data. - txCap.resetResult(); - txExtBuilder.clear(); - txRetBuilder.clear(); - long mid = (low + high) / 2; - txCap.setFeeLimit(mid); while (true) { try { transaction = cleanContextAndTriggerConstantContract( - triggerSmartContract, txCap, txExtBuilder, txRetBuilder); + triggerSmartContract, txCap, txExtBuilder, txRetBuilder, mid); break; } catch (Program.OutOfTimeException e) { retry--; @@ -2939,9 +2931,8 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, } // Retry the binary search result - txCap.setFeeLimit(high); transaction = cleanContextAndTriggerConstantContract( - triggerSmartContract, txCap, txExtBuilder, txRetBuilder); + triggerSmartContract, txCap, txExtBuilder, txRetBuilder, high); // Setting estimating result estimateBuilder.setResult(txRetBuilder); if (transaction.getRet(0).getRet().equals(code.SUCESS)) { @@ -2955,9 +2946,10 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, private Transaction cleanContextAndTriggerConstantContract( TriggerSmartContract triggerSmartContract, TransactionCapsule txCap, - Builder txExtBuilder, Return.Builder txRetBuilder) + Builder txExtBuilder, Return.Builder txRetBuilder, long feeLimit) throws ContractValidateException, ContractExeException, HeaderNotFound, VMIllegalException { Transaction transaction; + txCap.setFeeLimit(feeLimit); txCap.resetResult(); txExtBuilder.clear(); txRetBuilder.clear(); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 36efc20be8a..b1071564d57 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -408,12 +408,7 @@ private void estimateEnergy(byte[] ownerAddressByte, byte[] contractAddressByte, TransactionCapsule trxCap = wallet.createTransactionCapsule(triggerContract, ContractType.TriggerSmartContract); - Transaction trx = - wallet.estimateEnergy(triggerContract, trxCap, trxExtBuilder, retBuilder, estimateBuilder); - - trxExtBuilder.setTransaction(trx); - trxExtBuilder.setTxid(trxCap.getTransactionId().getByteString()); - trxExtBuilder.setResult(retBuilder); + wallet.estimateEnergy(triggerContract, trxCap, trxExtBuilder, retBuilder, estimateBuilder); retBuilder.setResult(true).setCode(response_code.SUCCESS); estimateBuilder.setResult(retBuilder); } diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 7c8a9ec0913..47635540017 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -567,10 +567,16 @@ vm = { saveInternalTx = false # Indicates whether the node stores featured internal transactions, such as freeze, vote and so on - # saveFeaturedInternalTx = true + # saveFeaturedInternalTx = false # In rare cases, transactions that will be within the specified maximum execution time (default 10(ms)) are re-executed and packaged # longRunningTime = 10 + + # Indicates whether the node support estimate energy API. + # estimateEnergy = false + + # Indicates the max retry time for executing transaction in estimating energy. + # estimateEnergyMaxRetry = 3 } committee = { From c4667da13b3b70019747e663efd52cd260804ac9 Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 5 Jan 2023 18:04:00 +0800 Subject: [PATCH 0546/1197] fix(suicide): reset old tron power when suicide --- actuator/src/main/java/org/tron/core/vm/program/Program.java | 1 + 1 file changed, 1 insertion(+) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index fac78690263..aca38c5f17d 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -617,6 +617,7 @@ private void withdrawRewardAndCancelVote(byte[] owner, Repository repo) { votesCapsule.clearNewVotes(); } ownerCapsule.clearVotes(); + ownerCapsule.setOldTronPower(0); repo.updateVotes(owner, votesCapsule); } try { From 370a86b44163d2541287d94c7c8be0d5f700ab07 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Fri, 6 Jan 2023 14:29:06 +0800 Subject: [PATCH 0547/1197] fix(resource): fix resource usage issue --- .../org/tron/core/db/BandwidthProcessor.java | 75 +++++++++++++------ .../org/tron/core/db/EnergyProcessor.java | 24 ++++-- 2 files changed, 70 insertions(+), 29 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java index 759e46cd016..f13002f2dfa 100644 --- a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -193,15 +193,24 @@ public boolean consumeBandwidthForCreateNewAccount(AccountCapsule accountCapsule long netUsage = accountCapsule.getNetUsage(); long latestConsumeTime = accountCapsule.getLatestConsumeTime(); long netLimit = calculateGlobalNetLimit(accountCapsule); - // only participate in the calculation as a temporary variable, without disk flushing - long recoveryNetUsage = recovery(accountCapsule, BANDWIDTH, netUsage, latestConsumeTime, now); + long newNetUsage; + if (!dynamicPropertiesStore.supportUnfreezeDelay()) { + newNetUsage = increase(netUsage, 0, latestConsumeTime, now); + } else { + // only participate in the calculation as a temporary variable, without disk flushing + newNetUsage = recovery(accountCapsule, BANDWIDTH, netUsage, latestConsumeTime, now); + } long netCost = bytes * createNewAccountBandwidthRatio; - if (netCost <= (netLimit - recoveryNetUsage)) { + if (netCost <= (netLimit - newNetUsage)) { long latestOperationTime = chainBaseManager.getHeadBlockTimeStamp(); - // Participate in calculation and flush disk persistence - long newNetUsage = increase(accountCapsule, BANDWIDTH, - netUsage, netCost, latestConsumeTime, now); + if (!dynamicPropertiesStore.supportUnfreezeDelay()) { + newNetUsage = increase(newNetUsage, netCost, now, now); + } else { + // Participate in calculation and flush disk persistence + newNetUsage = increase(accountCapsule, BANDWIDTH, + netUsage, netCost, latestConsumeTime, now); + } accountCapsule.setLatestConsumeTime(now); accountCapsule.setLatestOperationTime(latestOperationTime); accountCapsule.setNetUsage(newNetUsage); @@ -328,23 +337,33 @@ private boolean useAssetAccountNet(Contract contract, AccountCapsule accountCaps long issuerNetUsage = issuerAccountCapsule.getNetUsage(); long latestConsumeTime = issuerAccountCapsule.getLatestConsumeTime(); long issuerNetLimit = calculateGlobalNetLimit(issuerAccountCapsule); - // only participate in the calculation as a temporary variable, without disk flushing - long recoveryIssuerNetUsage = recovery(issuerAccountCapsule, BANDWIDTH, issuerNetUsage, - latestConsumeTime, now); + long newIssuerNetUsage; + if (!dynamicPropertiesStore.supportUnfreezeDelay()) { + newIssuerNetUsage = increase(issuerNetUsage, 0, latestConsumeTime, now); + } else { + // only participate in the calculation as a temporary variable, without disk flushing + newIssuerNetUsage = recovery(issuerAccountCapsule, BANDWIDTH, issuerNetUsage, + latestConsumeTime, now); + } - if (bytes > (issuerNetLimit - recoveryIssuerNetUsage)) { + if (bytes > (issuerNetLimit - newIssuerNetUsage)) { logger.debug("The {} issuer's bandwidth is not enough." - + " Bytes: {}, issuerNetLimit: {}, recoveryIssuerNetUsage:{}.", - tokenID, bytes, issuerNetLimit, recoveryIssuerNetUsage); + + " Bytes: {}, issuerNetLimit: {}, newIssuerNetUsage:{}.", + tokenID, bytes, issuerNetLimit, newIssuerNetUsage); return false; } latestAssetOperationTime = now; publicLatestFreeNetTime = now; long latestOperationTime = chainBaseManager.getHeadBlockTimeStamp(); - // Participate in calculation and flush disk persistence - long newIssuerNetUsage = increase(issuerAccountCapsule, BANDWIDTH, - issuerNetUsage, bytes, latestConsumeTime, now); + if (!dynamicPropertiesStore.supportUnfreezeDelay()) { + newIssuerNetUsage = increase(newIssuerNetUsage, bytes, now, now); + } else { + // Participate in calculation and flush disk persistence + newIssuerNetUsage = increase(issuerAccountCapsule, BANDWIDTH, + issuerNetUsage, bytes, latestConsumeTime, now); + } + newFreeAssetNetUsage = increase(newFreeAssetNetUsage, bytes, latestAssetOperationTime, now); newPublicFreeAssetNetUsage = increase(newPublicFreeAssetNetUsage, bytes, @@ -424,19 +443,31 @@ private boolean useAccountNet(AccountCapsule accountCapsule, long bytes, long no long netUsage = accountCapsule.getNetUsage(); long latestConsumeTime = accountCapsule.getLatestConsumeTime(); long netLimit = calculateGlobalNetLimit(accountCapsule); - // only participate in the calculation as a temporary variable, without disk flushing - long recoveryNetUsage = recovery(accountCapsule, BANDWIDTH, netUsage, latestConsumeTime, now); - if (bytes > (netLimit - recoveryNetUsage)) { + long newNetUsage; + if (!dynamicPropertiesStore.supportUnfreezeDelay()) { + newNetUsage = increase(netUsage, 0, latestConsumeTime, now); + } else { + // only participate in the calculation as a temporary variable, without disk flushing + newNetUsage = recovery(accountCapsule, BANDWIDTH, netUsage, latestConsumeTime, now); + } + + + if (bytes > (netLimit - newNetUsage)) { logger.debug("Net usage is running out, now use free net usage." - + " Bytes: {}, netLimit: {}, recoveryNetUsage: {}.", - bytes, netLimit, recoveryNetUsage); + + " Bytes: {}, netLimit: {}, newNetUsage: {}.", + bytes, netLimit, newNetUsage); return false; } long latestOperationTime = chainBaseManager.getHeadBlockTimeStamp(); - // Participate in calculation and flush disk persistence - long newNetUsage = increase(accountCapsule, BANDWIDTH, netUsage, bytes, latestConsumeTime, now); + if (!dynamicPropertiesStore.supportUnfreezeDelay()) { + newNetUsage = increase(newNetUsage, bytes, now, now); + } else { + // Participate in calculation and flush disk persistence + newNetUsage = increase(accountCapsule, BANDWIDTH, netUsage, bytes, latestConsumeTime, now); + } + accountCapsule.setNetUsage(newNetUsage); accountCapsule.setLatestOperationTime(latestOperationTime); accountCapsule.setLatestConsumeTime(now); diff --git a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java index 286d307ef16..5cd0f796374 100644 --- a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java @@ -101,20 +101,30 @@ public boolean useEnergy(AccountCapsule accountCapsule, long energy, long now) { long energyUsage = accountCapsule.getEnergyUsage(); long latestConsumeTime = accountCapsule.getAccountResource().getLatestConsumeTimeForEnergy(); long energyLimit = calculateGlobalEnergyLimit(accountCapsule); - // only participate in the calculation as a temporary variable, without disk flushing - long recoveryEnergyUsage = recovery(accountCapsule, ENERGY, energyUsage, - latestConsumeTime, now); + long newEnergyUsage; + if (!dynamicPropertiesStore.supportUnfreezeDelay()) { + newEnergyUsage = increase(energyUsage, 0, latestConsumeTime, now); + } else { + // only participate in the calculation as a temporary variable, without disk flushing + newEnergyUsage = recovery(accountCapsule, ENERGY, energyUsage, + latestConsumeTime, now); + } - if (energy > (energyLimit - recoveryEnergyUsage) + if (energy > (energyLimit - newEnergyUsage) && dynamicPropertiesStore.getAllowTvmFreeze() == 0 && !dynamicPropertiesStore.supportUnfreezeDelay()) { return false; } long latestOperationTime = dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); - // Participate in calculation and flush disk persistence - long newEnergyUsage = increase(accountCapsule, ENERGY, energyUsage, energy, - latestConsumeTime, now); + if (!dynamicPropertiesStore.supportUnfreezeDelay()) { + newEnergyUsage = increase(newEnergyUsage, energy, now, now); + } else { + // Participate in calculation and flush disk persistence + newEnergyUsage = increase(accountCapsule, ENERGY, energyUsage, energy, + latestConsumeTime, now); + } + accountCapsule.setEnergyUsage(newEnergyUsage); accountCapsule.setLatestOperationTime(latestOperationTime); accountCapsule.setLatestConsumeTimeForEnergy(now); From 35cc42f4dd85aa110d990d6ad6cbb43b7f38d779 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Sat, 7 Jan 2023 12:02:49 +0800 Subject: [PATCH 0548/1197] fix(DynamicEnergy): fix eth_estimateGas index out of range --- .../org/tron/core/services/jsonrpc/TronJsonRpcImpl.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index b1071564d57..453710b931b 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -408,7 +408,11 @@ private void estimateEnergy(byte[] ownerAddressByte, byte[] contractAddressByte, TransactionCapsule trxCap = wallet.createTransactionCapsule(triggerContract, ContractType.TriggerSmartContract); - wallet.estimateEnergy(triggerContract, trxCap, trxExtBuilder, retBuilder, estimateBuilder); + Transaction trx = + wallet.estimateEnergy(triggerContract, trxCap, trxExtBuilder, retBuilder, estimateBuilder); + trxExtBuilder.setTransaction(trx); + trxExtBuilder.setTxid(trxCap.getTransactionId().getByteString()); + trxExtBuilder.setResult(retBuilder); retBuilder.setResult(true).setCode(response_code.SUCCESS); estimateBuilder.setResult(retBuilder); } From 5a50ee6f2c6d3f87c67ff269d87e2a6d99ceb0b8 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 10 Jan 2023 11:30:46 +0800 Subject: [PATCH 0549/1197] feat(net): modify the default value of server ip --- framework/src/main/java/org/tron/core/net/TronNetService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 3c9554d79fa..8f9481ec20e 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -145,6 +145,9 @@ private P2pConfig getConfig() { config.setVersion(parameter.getNodeP2pVersion()); config.setDisconnectionPolicyEnable(parameter.isOpenFullTcpDisconnect()); config.setDiscoverEnable(parameter.isNodeDiscoveryEnable()); + if (config.getIp() == null) { + config.setIp(parameter.getNodeExternalIp()); + } return config; } } \ No newline at end of file From 7c745c90d2800e6f74df540333f9d8e6e5bd7f21 Mon Sep 17 00:00:00 2001 From: forfreeday Date: Thu, 12 Jan 2023 15:57:02 +0800 Subject: [PATCH 0550/1197] feat(shell): update start.sh 1. update start logic --- start.sh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/start.sh b/start.sh index fac6284bcc7..2e174e80747 100644 --- a/start.sh +++ b/start.sh @@ -597,7 +597,6 @@ if [[ $QUICK_START == true ]]; then restart fi fi - exit fi if [[ $UPGRADE == true ]]; then @@ -614,13 +613,11 @@ if [[ $DOWNLOAD == true ]]; then fi fi -if [[ $ALL_OPT_LENGTH -eq 0 ]]; then +if [[ $ALL_OPT_LENGTH -eq 0 || $ALL_OPT_LENGTH -gt 0 ]]; then restart - exit fi if [[ $RUN == true ]]; then restart - exit fi From 3ae525c381a79cc4bc95cac7dfc63c5f4d9be6a3 Mon Sep 17 00:00:00 2001 From: forfreeday Date: Thu, 12 Jan 2023 15:57:42 +0800 Subject: [PATCH 0551/1197] feat(shell): update start.sh 1. update start logic --- start.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/start.sh b/start.sh index 2e174e80747..63cf5ed50e5 100644 --- a/start.sh +++ b/start.sh @@ -541,14 +541,12 @@ while [ -n "$1" ]; do --run) if [[ $ALL_OPT_LENGTH -eq 1 ]]; then restart - exit fi RUN=true shift 1 ;; --stop) stopService - exit ;; FullNode) RUN=true From 0d941a98efc6eda060a52983840e74f659db62ae Mon Sep 17 00:00:00 2001 From: forfreeday Date: Thu, 12 Jan 2023 18:49:00 +0800 Subject: [PATCH 0552/1197] feat(shell): update start.sh 1. update download ArchiveManifest.jar --- start.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/start.sh b/start.sh index 63cf5ed50e5..6c579a97478 100644 --- a/start.sh +++ b/start.sh @@ -383,7 +383,8 @@ rebuildManifest() { $JAVACMD -jar $ARCHIVE_JAR -d $REBUILD_DIR -m $REBUILD_MANIFEST_SIZE -b $REBUILD_BATCH_SIZE else echo 'info: download the rebuild manifest plugin from the github' - download $RELEASE_URL/download/GreatVoyage-v4.3.0/$ARCHIVE_JAR $ARCHIVE_JAR + local latest=$(`echo getLatestReleaseVersion`) + download $RELEASE_URL/download/GreatVoyage-v"$latest"/$ARCHIVE_JAR $ARCHIVE_JAR if [[ $download == 0 ]]; then echo 'info: download success, rebuild manifest' $JAVACMD -jar $ARCHIVE_JAR $REBUILD_DIR -m $REBUILD_MANIFEST_SIZE -b $REBUILD_BATCH_SIZE From 0cc1731e922bb02305d8575c4f9cde8eebd68b4b Mon Sep 17 00:00:00 2001 From: wubin01 Date: Fri, 13 Jan 2023 14:43:31 +0800 Subject: [PATCH 0553/1197] feat(net): optimize network connection parameters --- .../java/org/tron/core/net/TronNetService.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 8f9481ec20e..fc4a3e8eee2 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -1,5 +1,6 @@ package org.tron.core.net; +import io.netty.util.internal.StringUtil; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; @@ -138,14 +139,25 @@ private P2pConfig getConfig() { config.setActiveNodes(parameter.getActiveNodes()); config.setTrustNodes(parameter.getPassiveNodes()); config.getActiveNodes().forEach(n -> config.getTrustNodes().add(n.getAddress())); - config.setMaxConnections(parameter.getMaxConnections()); - config.setMinConnections(parameter.getMinConnections()); + int maxConnections = parameter.getMaxConnections(); + int minConnections = parameter.getMinConnections(); + int minActiveConnections = parameter.getMinActiveConnections(); + if (minConnections > maxConnections) { + minConnections = maxConnections; + } + if (minActiveConnections > minConnections) { + minActiveConnections = minConnections; + } + config.setMaxConnections(maxConnections); + config.setMinConnections(minConnections); + config.setMinActiveConnections(minActiveConnections); + config.setMaxConnectionsWithSameIp(parameter.getMaxConnectionsWithSameIp()); config.setPort(parameter.getNodeListenPort()); config.setVersion(parameter.getNodeP2pVersion()); config.setDisconnectionPolicyEnable(parameter.isOpenFullTcpDisconnect()); config.setDiscoverEnable(parameter.isNodeDiscoveryEnable()); - if (config.getIp() == null) { + if (StringUtil.isNullOrEmpty(config.getIp())) { config.setIp(parameter.getNodeExternalIp()); } return config; From 8889bbfb43f36a58ab66383889694b8961a57f04 Mon Sep 17 00:00:00 2001 From: forfreeday Date: Sat, 14 Jan 2023 15:17:56 +0800 Subject: [PATCH 0554/1197] feat(Version): update version 4.7.0 1. update version 4.7.0 --- framework/src/main/java/org/tron/program/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 47e0426aa47..e44555bff65 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -4,7 +4,7 @@ public class Version { public static final String VERSION_NAME = "GreatVoyage-v4.5.2-125-ga2906563d"; public static final String VERSION_CODE = "17198"; - private static final String VERSION = "4.6.0"; + private static final String VERSION = "4.7.0"; public static String getVersion() { return VERSION; From 10da864fac3e80ce780324c2c47eb98d4e595679 Mon Sep 17 00:00:00 2001 From: forfreeday Date: Mon, 16 Jan 2023 12:01:43 +0800 Subject: [PATCH 0555/1197] update a new version. version name:GreatVoyage-v4.6.0-385-g4445a420c,version code:17585 --- framework/src/main/java/org/tron/program/Version.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 47e0426aa47..f48fe70d882 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,9 +2,9 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.5.2-125-ga2906563d"; - public static final String VERSION_CODE = "17198"; - private static final String VERSION = "4.6.0"; + public static final String VERSION_NAME = "GreatVoyage-v4.6.0-385-g4445a420c"; + public static final String VERSION_CODE = "17585"; + private static final String VERSION = "4.7.0"; public static String getVersion() { return VERSION; From 4a57bf04548c51c6cb80887f2c75d360f1dede95 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Mon, 16 Jan 2023 18:12:29 +0800 Subject: [PATCH 0556/1197] feat(version): add a unit test for BLOCK_VERSION --- .../org/tron/core/actuator/utils/ProposalUtilTest.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java index 1ad57367fdd..ed19516a608 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java @@ -18,6 +18,7 @@ import org.tron.common.utils.ForkController; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; +import org.tron.core.config.Parameter; import org.tron.core.config.Parameter.ForkBlockVersionEnum; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; @@ -357,4 +358,13 @@ public void validateCheck() { e.getMessage()); } } + + @Test + public void blockVersionCheck() { + for (ForkBlockVersionEnum forkVersion : ForkBlockVersionEnum.values()) { + if (forkVersion.getValue() > Parameter.ChainConstant.BLOCK_VERSION) { + Assert.fail("ForkBlockVersion must be less than BLOCK_VERSION"); + } + } + } } From 2878a710c3b108c80162c81156cd9246ebb94fe6 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 18 Jan 2023 19:34:54 +0800 Subject: [PATCH 0557/1197] fix(netty): netty revert --- protocol/build.gradle | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/protocol/build.gradle b/protocol/build.gradle index b3d83ee0149..acdb7f15187 100644 --- a/protocol/build.gradle +++ b/protocol/build.gradle @@ -1,14 +1,12 @@ apply plugin: 'com.google.protobuf' -def protobufVersion = "3.20.3" +def protobufVersion = "3.19.2" def grpcVersion = "1.14.0" dependencies { compile group: 'com.google.protobuf', name: 'protobuf-java', version: protobufVersion compile group: 'com.google.protobuf', name: 'protobuf-java-util', version: protobufVersion - compile group: 'com.google.code.gson', name: 'gson', version: '2.9.0' - compile group: 'net.jcip', name: 'jcip-annotations', version: '1.0' // checkstyleConfig "com.puppycrawl.tools:checkstyle:${versions.checkstyle}" @@ -19,9 +17,6 @@ dependencies { // end google grpc compile group: 'com.google.api.grpc', name: 'googleapis-common-protos', version: '0.0.3' - compile group: 'io.netty', name: 'netty-codec-http', version: '4.1.78.Final' - compile group: 'io.netty', name: 'netty-handler', version: '4.1.78.Final' - compile group: 'io.netty', name: 'netty-codec-http2', version: '4.1.78.Final' } tasks.matching { it instanceof Test }.all { From 36b5caa7cbacf912c86e2425509905b53a564fd5 Mon Sep 17 00:00:00 2001 From: zer0init1 <66873187+zer0init1@users.noreply.github.com> Date: Wed, 18 Jan 2023 19:08:33 +0200 Subject: [PATCH 0558/1197] Update docker.md Up in "Push" word on command sh docker.sh --log | grep 'PushBlock' --- docker/docker.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/docker.md b/docker/docker.md index a187f04631b..79aa6b08e2d 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -62,7 +62,7 @@ Or use the `-c` parameter to specify your own configuration file, which will not If you want to see the logs of the java-tron service, please use the `--log` parameter ```shell -$ sh docker.sh --log | grep 'pushBlock' +$ sh docker.sh --log | grep 'PushBlock' ``` ### Stop the service From 29ea4659ce75da639cf5600c509f42974e502b55 Mon Sep 17 00:00:00 2001 From: forfreeday Date: Thu, 19 Jan 2023 11:46:57 +0800 Subject: [PATCH 0559/1197] feature(version): update VERSION --- framework/src/main/java/org/tron/program/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index f48fe70d882..a94db0c8fa1 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -4,7 +4,7 @@ public class Version { public static final String VERSION_NAME = "GreatVoyage-v4.6.0-385-g4445a420c"; public static final String VERSION_CODE = "17585"; - private static final String VERSION = "4.7.0"; + private static final String VERSION = "4.7.0.1"; public static String getVersion() { return VERSION; From 5b357e729a5ce78449fb3d4ef456a67e43821563 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 19 Jan 2023 16:36:18 +0800 Subject: [PATCH 0560/1197] feat(net): update libp2p version --- framework/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/build.gradle b/framework/build.gradle index 6be5edf9002..93757755446 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -48,7 +48,7 @@ dependencies { compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' - compile group: 'io.github.tronprotocol', name: 'libp2p', version: '0.1.1' + compile group: 'io.github.tronprotocol', name: 'libp2p', version: '0.1.2' compile group: 'com.typesafe', name: 'config', version: '1.3.2' From ec11e2c366da85caac4e54ca0e0f4ad750b1c611 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Fri, 20 Jan 2023 11:20:05 +0800 Subject: [PATCH 0561/1197] update a new version. version name:GreatVoyage-v4.7.0-9-g9326a08dd9,version code:17596 --- framework/src/main/java/org/tron/program/Version.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index a94db0c8fa1..e1109bcc5b7 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,8 +2,8 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.6.0-385-g4445a420c"; - public static final String VERSION_CODE = "17585"; + public static final String VERSION_NAME = "GreatVoyage-v4.7.0-9-g9326a08dd9"; + public static final String VERSION_CODE = "17596"; private static final String VERSION = "4.7.0.1"; public static String getVersion() { From 40cd55a45e550e43b0cd08753e96c041d369188e Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 30 Jan 2023 14:28:50 +0800 Subject: [PATCH 0562/1197] feat(net): set relay node flag --- .../main/java/org/tron/core/net/peer/PeerConnection.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index 9893b3e4db8..5626c072864 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -7,6 +7,7 @@ import java.net.InetSocketAddress; import java.util.Deque; import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; @@ -28,6 +29,7 @@ import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.config.Parameter.NetConstants; +import org.tron.core.config.args.Args; import org.tron.core.metrics.MetricsKey; import org.tron.core.metrics.MetricsUtil; import org.tron.core.net.TronNetDelegate; @@ -50,6 +52,8 @@ @Scope("prototype") public class PeerConnection { + private static List relayNodes = Args.getInstance().getFastForwardNodes(); + @Getter private PeerStatistics peerStatistics = new PeerStatistics(); @@ -61,7 +65,7 @@ public class PeerConnection { @Getter @Setter - private boolean isRelayPeer; + private volatile boolean isRelayPeer; @Getter @Setter @@ -143,6 +147,9 @@ public class PeerConnection { public void setChannel(Channel channel) { this.channel = channel; + if (relayNodes.contains(channel.getInetSocketAddress())) { + this.isRelayPeer = true; + } this.nodeStatistics = TronStatsManager.getNodeStatistics(channel.getInetAddress()); } From 6e4889f0e9dab926acdb3be96e1b34d7be57a940 Mon Sep 17 00:00:00 2001 From: chaozhu Date: Mon, 30 Jan 2023 12:01:53 +0800 Subject: [PATCH 0563/1197] feat(freezeV2): add test cases for wallet api --- .../test/java/org/tron/core/WalletTest.java | 347 ++++++++++++++++++ 1 file changed, 347 insertions(+) diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 1b35a78bf82..dd275cc6e09 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -18,10 +18,14 @@ package org.tron.core; +import static junit.framework.TestCase.fail; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import static stest.tron.wallet.common.client.utils.PublicMethed.decode58Check; import com.google.protobuf.Any; @@ -34,6 +38,7 @@ import org.joda.time.DateTime; import org.junit.AfterClass; import org.junit.Assert; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; @@ -47,16 +52,26 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; import org.tron.common.utils.Utils; +import org.tron.core.actuator.DelegateResourceActuator; +import org.tron.core.actuator.FreezeBalanceActuator; +import org.tron.core.actuator.UnfreezeBalanceV2Actuator; +import org.tron.core.actuator.WithdrawExpireUnfreezeActuator; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; +import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.ExchangeCapsule; import org.tron.core.capsule.ProposalCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.TransactionInfoCapsule; +import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.utils.ProposalUtil.ProposalType; import org.tron.core.utils.TransactionUtil; @@ -72,7 +87,9 @@ import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.TransactionInfo; import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; +import org.tron.protos.contract.BalanceContract; import org.tron.protos.contract.BalanceContract.TransferContract; +import org.tron.protos.contract.Common; @Slf4j @@ -124,18 +141,61 @@ public class WalletTest { private static Transaction transaction6; private static AssetIssueCapsule Asset1; + private static Manager dbManager; + private static final String OWNER_ADDRESS; + private static final String RECEIVER_ADDRESS; + private static final long initBalance = 43_200_000_000L; + static { Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; } @BeforeClass public static void init() { wallet = context.getBean(Wallet.class); chainBaseManager = context.getBean(ChainBaseManager.class); + dbManager = context.getBean(Manager.class); initTransaction(); initBlock(); chainBaseManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(5); + chainBaseManager.getDelegatedResourceStore().reset(); + } + + @Before + public void createAccountCapsule() { + AccountCapsule ownerCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + + AccountCapsule receiverCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), + AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); + + byte[] dbKey = DelegatedResourceCapsule.createDbKey( + ByteArray.fromHexString(OWNER_ADDRESS), + ByteArray.fromHexString(RECEIVER_ADDRESS)); + byte[] dbKeyV2 = DelegatedResourceCapsule.createDbKeyV2( + ByteArray.fromHexString(OWNER_ADDRESS), + ByteArray.fromHexString(RECEIVER_ADDRESS), + false); + chainBaseManager.getDelegatedResourceStore().delete(dbKey); + chainBaseManager.getDelegatedResourceStore().delete(dbKeyV2); + chainBaseManager.getDelegatedResourceAccountIndexStore() + .delete(ByteArray.fromHexString(OWNER_ADDRESS)); + + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(0L); } /** @@ -552,5 +612,292 @@ public void testChainParameters() { System.out.printf(builder.build().toString()); } + + @Test + public void testGetDelegatedResource() { + long frozenBalance = 1_000_000_000L; + long duration = 3; + FreezeBalanceActuator actuator = new FreezeBalanceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegatedContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, frozenBalance, duration)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + + GrpcAPI.DelegatedResourceList delegatedResourceList = wallet.getDelegatedResource( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); + + Assert.assertEquals(1L, delegatedResourceList.getDelegatedResourceCount()); + Assert.assertEquals(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + delegatedResourceList.getDelegatedResource(0).getFrom()); + Assert.assertEquals(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), + delegatedResourceList.getDelegatedResource(0).getTo()); + Assert.assertEquals(frozenBalance, + delegatedResourceList.getDelegatedResource(0).getFrozenBalanceForEnergy()); + Assert.assertEquals(0L, + delegatedResourceList.getDelegatedResource(0).getFrozenBalanceForBandwidth()); + Assert.assertEquals(0L, + delegatedResourceList.getDelegatedResource(0).getExpireTimeForBandwidth()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } catch (Exception e) { + Assert.assertEquals(false, true); + } + } + + + @Test + public void testGetDelegatedResourceAccountIndex() { + long frozenBalance = 1_000_000_000L; + long duration = 3; + FreezeBalanceActuator actuator = new FreezeBalanceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegatedContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS, frozenBalance, duration)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + + Protocol.DelegatedResourceAccountIndex delegatedResourceAccountIndex = + wallet.getDelegatedResourceAccountIndex( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); + + Assert.assertEquals(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + delegatedResourceAccountIndex.getAccount()); + Assert.assertEquals(1L, delegatedResourceAccountIndex.getToAccountsCount()); + Assert.assertEquals(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), + delegatedResourceAccountIndex.getToAccounts(0)); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + private Any getDelegatedContractForCpu(String ownerAddress, String receiverAddress, + long frozenBalance, + long duration) { + return Any.pack( + BalanceContract.FreezeBalanceContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiverAddress))) + .setFrozenBalance(frozenBalance) + .setFrozenDuration(duration) + .setResource(Common.ResourceCode.ENERGY) + .build()); + } + + private void freezeBandwidthForOwner() { + AccountCapsule ownerCapsule = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + ownerCapsule.addFrozenBalanceForBandwidthV2(initBalance); + ownerCapsule.setNetUsage(0L); + ownerCapsule.setEnergyUsage(0L); + dbManager.getDynamicPropertiesStore().saveTotalNetWeight(0L); + dbManager.getDynamicPropertiesStore().saveTotalEnergyWeight(0L); + dbManager.getDynamicPropertiesStore().addTotalNetWeight(initBalance / TRX_PRECISION); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + } + + private void freezeCpuForOwner() { + AccountCapsule ownerCapsule = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + ownerCapsule.addFrozenBalanceForEnergyV2(initBalance); + ownerCapsule.setNetUsage(0L); + ownerCapsule.setEnergyUsage(0L); + dbManager.getDynamicPropertiesStore().saveTotalNetWeight(0L); + dbManager.getDynamicPropertiesStore().saveTotalEnergyWeight(0L); + dbManager.getDynamicPropertiesStore().addTotalEnergyWeight(initBalance / TRX_PRECISION); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + } + + private Any getDelegateContractForBandwidth(String ownerAddress, String receiveAddress, + long unfreezeBalance) { + return getLockedDelegateContractForBandwidth(ownerAddress, receiveAddress, + unfreezeBalance, false); + } + + private Any getLockedDelegateContractForBandwidth(String ownerAddress, String receiveAddress, + long unfreezeBalance, boolean lock) { + return Any.pack(BalanceContract.DelegateResourceContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiveAddress))) + .setBalance(unfreezeBalance) + .setResource(Common.ResourceCode.BANDWIDTH) + .setLock(lock) + .build()); + } + + @Test + public void testGetDelegatedResourceV2() { + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + freezeBandwidthForOwner(); + + long delegateBalance = 1_000_000_000L; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(Transaction.Result.code.SUCESS, ret.getInstance().getRet()); + + GrpcAPI.DelegatedResourceList delegatedResourceList = wallet.getDelegatedResourceV2( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); + + Assert.assertEquals(1L, delegatedResourceList.getDelegatedResourceCount()); + Assert.assertEquals(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + delegatedResourceList.getDelegatedResource(0).getFrom()); + Assert.assertEquals(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), + delegatedResourceList.getDelegatedResource(0).getTo()); + Assert.assertEquals(delegateBalance, + delegatedResourceList.getDelegatedResource(0).getFrozenBalanceForBandwidth()); + Assert.assertEquals(0L, + delegatedResourceList.getDelegatedResource(0).getExpireTimeForBandwidth()); + Assert.assertEquals(0L, + delegatedResourceList.getDelegatedResource(0).getFrozenBalanceForEnergy()); + Assert.assertEquals(0L, + delegatedResourceList.getDelegatedResource(0).getExpireTimeForEnergy()); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testGetDelegatedResourceAccountIndexV2() { + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + freezeBandwidthForOwner(); + + long delegateBalance = 1_000_000_000L; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(Transaction.Result.code.SUCESS, ret.getInstance().getRet()); + + Protocol.DelegatedResourceAccountIndex delegatedResourceAccountIndex = + wallet.getDelegatedResourceAccountIndexV2( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); + + Assert.assertEquals(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + delegatedResourceAccountIndex.getAccount()); + Assert.assertEquals(1L, delegatedResourceAccountIndex.getToAccountsCount()); + Assert.assertEquals(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), + delegatedResourceAccountIndex.getToAccounts(0)); + + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testGetCanDelegatedMaxSizeBandWidth() { + freezeBandwidthForOwner(); + + GrpcAPI.CanDelegatedMaxSizeResponseMessage message = wallet.getCanDelegatedMaxSize( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + Common.ResourceCode.BANDWIDTH.getNumber()); + Assert.assertEquals(initBalance - 280L, message.getMaxSize()); + + } + + @Test + public void testGetCanDelegatedMaxSizeEnergy() { + freezeCpuForOwner(); + + GrpcAPI.CanDelegatedMaxSizeResponseMessage message = wallet.getCanDelegatedMaxSize( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + Common.ResourceCode.ENERGY.getNumber()); + Assert.assertEquals(initBalance, message.getMaxSize()); + + } + + private Any getContractForBandwidthV2(String ownerAddress, long unfreezeBalance) { + return Any.pack( + BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress( + ByteString.copyFrom(ByteArray.fromHexString(ownerAddress)) + ) + .setUnfreezeBalance(unfreezeBalance) + .setResource(Common.ResourceCode.BANDWIDTH) + .build() + ); + } + + @Test + public void testGetAvailableUnfreezeCount() { + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + + long frozenBalance = 43_200_000_00L; + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + dbManager.getDynamicPropertiesStore().saveTotalNetWeight(1000); + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + long unfreezeBalance = frozenBalance - 100; + + Assert.assertEquals(frozenBalance, accountCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(frozenBalance, accountCapsule.getTronPower()); + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + + UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(Transaction.Result.code.SUCESS, ret.getInstance().getRet()); + + GrpcAPI.GetAvailableUnfreezeCountResponseMessage message = + wallet.getAvailableUnfreezeCount( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); + Assert.assertEquals(31, message.getCount()); + } catch (Exception e) { + Assert.fail(e.getMessage()); + } + } + + + @Test + public void testGetCanWithdrawUnfreezeAmount() { + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + byte[] address = ByteArray.fromHexString(OWNER_ADDRESS); + + AccountCapsule accountCapsule = dbManager.getAccountStore().get(address); + Protocol.Account.UnFreezeV2 unFreezeV2_1 = Protocol.Account.UnFreezeV2.newBuilder() + .setType(BANDWIDTH).setUnfreezeAmount(16_000_000L).setUnfreezeExpireTime(1).build(); + Protocol.Account.UnFreezeV2 unFreezeV2_2 = Protocol.Account.UnFreezeV2.newBuilder() + .setType(ENERGY).setUnfreezeAmount(16_000_000L).setUnfreezeExpireTime(1).build(); + Protocol.Account.UnFreezeV2 unFreezeV2_3 = Protocol.Account.UnFreezeV2.newBuilder() + .setType(ENERGY).setUnfreezeAmount(0).setUnfreezeExpireTime(Long.MAX_VALUE).build(); + accountCapsule.addUnfrozenV2(unFreezeV2_1); + accountCapsule.addUnfrozenV2(unFreezeV2_2); + accountCapsule.addUnfrozenV2(unFreezeV2_3); + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + + GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage message = + wallet.getCanWithdrawUnfreezeAmount( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + System.currentTimeMillis()); + Assert.assertEquals(16_000_000L * 2, message.getAmount()); + } + } From ef7c388198d3b889a8f4815a27ed35b478d62a7a Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 31 Jan 2023 12:22:22 +0800 Subject: [PATCH 0564/1197] feat(net): optimize network log --- .../main/java/org/tron/core/net/P2pEventHandlerImpl.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java index 94f8191323b..f6a01b1cf95 100644 --- a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java +++ b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java @@ -221,8 +221,13 @@ private void processException(PeerConnection peer, TronMessage msg, Exception ex code = Protocol.ReasonCode.UNKNOWN; break; } - logger.warn("Message from {} process failed, {} \n type: {}, detail: {}", - peer.getInetSocketAddress(), msg, type, ex.getMessage()); + if (type.equals(P2pException.TypeEnum.BAD_MESSAGE)) { + logger.error("Message from {} process failed, {} \n type: {}", + peer.getInetSocketAddress(), msg, type, ex); + } else { + logger.warn("Message from {} process failed, {} \n type: {}, detail: {}", + peer.getInetSocketAddress(), msg, type, ex.getMessage()); + } } else { code = Protocol.ReasonCode.UNKNOWN; logger.warn("Message from {} process failed, {}", From aad6911860b974301dd229c2f7fb5a007f7697bd Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 31 Jan 2023 17:37:12 +0800 Subject: [PATCH 0565/1197] feat(rpc): upgrade grpc --- docs/implement-a-customized-actuator-en.md | 2 +- docs/implement-a-customized-actuator-zh.md | 2 +- .../tron/common/client/DatabaseGrpcClient.java | 4 ++-- .../org/tron/common/client/WalletGrpcClient.java | 4 ++-- .../tron/core/CreateCommonTransactionTest.java | 2 +- .../core/services/DelegationServiceTest.java | 2 +- .../tron/core/services/NodeInfoServiceTest.java | 2 +- .../filter/LiteFnQueryGrpcInterceptorTest.java | 4 ++-- .../org/tron/program/LiteFullNodeToolTest.java | 2 +- .../tron/wallet/account/BrokerageTest001.java | 8 ++++---- .../wallet/account/WalletTestAccount001.java | 4 ++-- .../wallet/account/WalletTestAccount003.java | 2 +- .../wallet/account/WalletTestAccount004.java | 4 ++-- .../wallet/account/WalletTestAccount005.java | 4 ++-- .../wallet/account/WalletTestAccount006.java | 2 +- .../wallet/account/WalletTestAccount007.java | 2 +- .../wallet/account/WalletTestAccount009.java | 2 +- .../wallet/account/WalletTestAccount011.java | 4 ++-- .../tron/wallet/block/WalletTestBlock003.java | 4 ++-- .../tron/wallet/block/WalletTestBlock004.java | 2 +- .../tron/wallet/block/WalletTestBlock005.java | 2 +- .../tron/wallet/block/WalletTestBlock006.java | 4 ++-- .../wallet/committee/WalletTestCommittee001.java | 4 ++-- .../wallet/committee/WalletTestCommittee002.java | 4 ++-- .../wallet/committee/WalletTestCommittee003.java | 4 ++-- .../wallet/committee/WalletTestCommittee004.java | 4 ++-- .../tron/wallet/common/client/GrpcClient.java | 6 +++--- .../common/client/utils/DailyBuildReport.java | 2 +- .../wallet/common/client/utils/JsonRpcBase.java | 2 +- .../common/client/utils/ShieldWrapper.java | 2 +- .../wallet/common/client/utils/ZenTrc20Base.java | 2 +- .../contract/linkage/ContractLinkage002.java | 4 ++-- .../contract/linkage/ContractLinkage003.java | 4 ++-- .../contract/linkage/ContractLinkage004.java | 4 ++-- .../contract/linkage/ContractLinkage007.java | 4 ++-- .../contract/scenario/ContractScenario001.java | 4 ++-- .../contract/scenario/ContractScenario003.java | 4 ++-- .../contract/scenario/ContractScenario004.java | 2 +- .../contract/scenario/ContractScenario005.java | 2 +- .../contract/scenario/ContractScenario006.java | 2 +- .../contract/scenario/ContractScenario007.java | 2 +- .../contract/scenario/ContractScenario008.java | 2 +- .../contract/scenario/ContractScenario009.java | 2 +- .../contract/scenario/ContractScenario010.java | 2 +- .../contract/scenario/ContractScenario012.java | 2 +- .../contract/scenario/ContractScenario013.java | 2 +- .../contract/scenario/ContractScenario014.java | 6 +++--- .../contract/scenario/ContractScenario015.java | 6 +++--- .../contract/scenario/ContractScenario016.java | 4 ++-- .../dailybuild/account/GetAccountBalance001.java | 2 +- .../dailybuild/account/TransactionFee001.java | 6 +++--- .../dailybuild/account/WalletTestAccount012.java | 2 +- .../dailybuild/assetissue/WalletExchange001.java | 6 +++--- .../assetissue/WalletTestAssetIssue001.java | 2 +- .../assetissue/WalletTestAssetIssue002.java | 2 +- .../assetissue/WalletTestAssetIssue003.java | 2 +- .../assetissue/WalletTestAssetIssue004.java | 2 +- .../assetissue/WalletTestAssetIssue005.java | 4 ++-- .../assetissue/WalletTestAssetIssue006.java | 4 ++-- .../assetissue/WalletTestAssetIssue007.java | 2 +- .../assetissue/WalletTestAssetIssue008.java | 4 ++-- .../assetissue/WalletTestAssetIssue009.java | 4 ++-- .../assetissue/WalletTestAssetIssue010.java | 2 +- .../assetissue/WalletTestAssetIssue011.java | 2 +- .../assetissue/WalletTestAssetIssue012.java | 2 +- .../assetissue/WalletTestAssetIssue013.java | 2 +- .../assetissue/WalletTestAssetIssue014.java | 2 +- .../assetissue/WalletTestAssetIssue015.java | 2 +- .../assetissue/WalletTestAssetIssue016.java | 8 ++++---- .../assetissue/WalletTestAssetIssue020.java | 8 ++++---- .../WalletTestAssetIssue017.java | 4 ++-- .../WalletTestAssetIssue018.java | 2 +- .../WalletTestAssetIssue019.java | 2 +- .../assetissue/grammar/ContractGrammar001.java | 4 ++-- .../assetissue/grammar/ContractGrammar002.java | 4 ++-- .../assetissue/grammar/ContractGrammar003.java | 4 ++-- .../assetissue/grammar/ContractGrammar004.java | 4 ++-- .../assetmarket/MarketSellAsset001.java | 4 ++-- .../assetmarket/MarketSellAsset002.java | 2 +- .../assetmarket/MarketSellAsset003.java | 2 +- .../assetmarket/MarketSellAsset004.java | 2 +- .../assetmarket/MarketSellAsset005.java | 2 +- .../assetmarket/MarketSellAsset006.java | 6 +++--- .../wallet/dailybuild/eventquery/EventLog2.java | 2 +- .../dailybuild/eventquery/EventQuery001.java | 2 +- .../dailybuild/eventquery/EventQuery002.java | 2 +- .../dailybuild/eventquery/EventQuery003.java | 4 ++-- .../dailybuild/eventquery/EventQuery004.java | 4 ++-- .../dailybuild/exceptionfee/AssertException.java | 6 +++--- .../dailybuild/http/HttpTestMutiSign001.java | 2 +- .../ContractInternalTransaction001.java | 4 ++-- .../ContractInternalTransaction002.java | 4 ++-- .../ContractInternalTransaction003.java | 4 ++-- .../wallet/dailybuild/jsonrpc/Accounts001.java | 2 +- .../wallet/dailybuild/jsonrpc/Accounts002.java | 2 +- .../dailybuild/jsonrpc/BuildTransaction001.java | 2 +- .../wallet/dailybuild/jsonrpc/GetBlock001.java | 2 +- .../dailybuild/manual/ContractLinkage001.java | 4 ++-- .../dailybuild/manual/ContractLinkage005.java | 4 ++-- .../dailybuild/manual/ContractLinkage006.java | 4 ++-- .../dailybuild/manual/ContractScenario002.java | 10 +++++----- .../dailybuild/manual/ContractScenario011.java | 4 ++-- .../dailybuild/manual/ContractScenario014.java | 2 +- .../dailybuild/manual/ContractScenario015.java | 2 +- .../dailybuild/manual/ContractTrc1155.java | 2 +- .../manual/ContractUnknownException.java | 2 +- ...GetTransactionInfoByBlockNumFromSolidity.java | 4 ++-- .../wallet/dailybuild/manual/RateLimite001.java | 6 +++--- .../dailybuild/manual/RequireException.java | 6 +++--- .../dailybuild/manual/WalletTestAccount002.java | 4 ++-- .../dailybuild/manual/WalletTestAccount010.java | 2 +- .../dailybuild/manual/WalletTestAccount012.java | 4 ++-- .../dailybuild/manual/WalletTestAccount013.java | 8 ++++---- .../dailybuild/manual/WalletTestAccount014.java | 6 +++--- .../dailybuild/manual/WalletTestAccount015.java | 8 ++++---- .../dailybuild/manual/WalletTestBlock001.java | 4 ++-- .../dailybuild/manual/WalletTestBlock002.java | 8 ++++---- .../dailybuild/manual/WalletTestMutiSign002.java | 4 ++-- .../dailybuild/manual/WalletTestNode001.java | 4 ++-- .../dailybuild/manual/WalletTestTransfer002.java | 4 ++-- .../dailybuild/manual/WalletTestTransfer005.java | 4 ++-- .../dailybuild/manual/WalletTestTransfer006.java | 4 ++-- .../dailybuild/manual/WalletTestWitness003.java | 2 +- .../wallet/dailybuild/multisign/MultiSign01.java | 2 +- .../wallet/dailybuild/multisign/MultiSign02.java | 2 +- .../wallet/dailybuild/multisign/MultiSign03.java | 2 +- .../wallet/dailybuild/multisign/MultiSign04.java | 2 +- .../wallet/dailybuild/multisign/MultiSign05.java | 2 +- .../wallet/dailybuild/multisign/MultiSign06.java | 2 +- .../wallet/dailybuild/multisign/MultiSign07.java | 2 +- .../wallet/dailybuild/multisign/MultiSign08.java | 2 +- .../wallet/dailybuild/multisign/MultiSign09.java | 2 +- .../wallet/dailybuild/multisign/MultiSign10.java | 2 +- .../wallet/dailybuild/multisign/MultiSign11.java | 2 +- .../wallet/dailybuild/multisign/MultiSign12.java | 2 +- .../wallet/dailybuild/multisign/MultiSign13.java | 2 +- .../wallet/dailybuild/multisign/MultiSign14.java | 2 +- .../wallet/dailybuild/multisign/MultiSign15.java | 2 +- .../wallet/dailybuild/multisign/MultiSign16.java | 2 +- .../wallet/dailybuild/multisign/MultiSign17.java | 2 +- .../wallet/dailybuild/multisign/MultiSign18.java | 2 +- .../wallet/dailybuild/multisign/MultiSign19.java | 2 +- .../wallet/dailybuild/multisign/MultiSign20.java | 2 +- .../wallet/dailybuild/multisign/MultiSign21.java | 2 +- .../wallet/dailybuild/multisign/MultiSign22.java | 2 +- .../wallet/dailybuild/multisign/MultiSign23.java | 2 +- .../wallet/dailybuild/multisign/MultiSign24.java | 2 +- .../wallet/dailybuild/multisign/MultiSign26.java | 2 +- .../wallet/dailybuild/multisign/MultiSign27.java | 2 +- .../wallet/dailybuild/multisign/MultiSign28.java | 2 +- .../wallet/dailybuild/multisign/MultiSign29.java | 2 +- .../wallet/dailybuild/multisign/MultiSign30.java | 2 +- .../wallet/dailybuild/multisign/MultiSign31.java | 2 +- .../wallet/dailybuild/multisign/MultiSign33.java | 2 +- .../wallet/dailybuild/multisign/MultiSign34.java | 2 +- .../wallet/dailybuild/multisign/MultiSign35.java | 2 +- .../wallet/dailybuild/multisign/MultiSign36.java | 2 +- .../wallet/dailybuild/multisign/MultiSign37.java | 2 +- .../MutiSignAccountPermissionUpdateTest.java | 2 +- .../MutiSignAccountPermissionUpdateTest002.java | 2 +- .../operationupdate/MutiSignAccountTest.java | 2 +- .../operationupdate/MutiSignAccountTest002.java | 2 +- .../operationupdate/MutiSignAssetTest.java | 2 +- .../operationupdate/MutiSignAssetTest002.java | 2 +- .../MutiSignClearContractAbiTest.java | 4 ++-- .../MutiSignExchangeContractTest.java | 4 ++-- .../MutiSignExchangeContractTest002.java | 4 ++-- .../operationupdate/MutiSignMarketAssetTest.java | 2 +- .../operationupdate/MutiSignProposalTest.java | 4 ++-- .../operationupdate/MutiSignProposalTest002.java | 4 ++-- .../MutiSignSmartContractTest.java | 4 ++-- .../MutiSignSmartContractTest002.java | 4 ++-- .../MutiSignUpdataBrokerageTest.java | 4 ++-- .../ContractOriginEnergyLimit001.java | 4 ++-- .../ContractOriginEnergyLimit004.java | 4 ++-- .../transaction/TransactionPendingQuery001.java | 6 +++--- .../dailybuild/trctoken/ContractTrcToken001.java | 2 +- .../dailybuild/trctoken/ContractTrcToken002.java | 2 +- .../dailybuild/trctoken/ContractTrcToken003.java | 2 +- .../dailybuild/trctoken/ContractTrcToken005.java | 2 +- .../dailybuild/trctoken/ContractTrcToken011.java | 4 ++-- .../dailybuild/trctoken/ContractTrcToken012.java | 2 +- .../dailybuild/trctoken/ContractTrcToken014.java | 2 +- .../dailybuild/trctoken/ContractTrcToken018.java | 2 +- .../dailybuild/trctoken/ContractTrcToken023.java | 2 +- .../dailybuild/trctoken/ContractTrcToken026.java | 2 +- .../dailybuild/trctoken/ContractTrcToken027.java | 2 +- .../dailybuild/trctoken/ContractTrcToken028.java | 2 +- .../dailybuild/trctoken/ContractTrcToken029.java | 2 +- .../dailybuild/trctoken/ContractTrcToken030.java | 2 +- .../dailybuild/trctoken/ContractTrcToken031.java | 2 +- .../dailybuild/trctoken/ContractTrcToken034.java | 2 +- .../dailybuild/trctoken/ContractTrcToken035.java | 2 +- .../dailybuild/trctoken/ContractTrcToken036.java | 2 +- .../dailybuild/trctoken/ContractTrcToken037.java | 2 +- .../dailybuild/trctoken/ContractTrcToken038.java | 2 +- .../dailybuild/trctoken/ContractTrcToken039.java | 2 +- .../dailybuild/trctoken/ContractTrcToken041.java | 2 +- .../dailybuild/trctoken/ContractTrcToken043.java | 2 +- .../dailybuild/trctoken/ContractTrcToken048.java | 2 +- .../dailybuild/trctoken/ContractTrcToken049.java | 2 +- .../dailybuild/trctoken/ContractTrcToken050.java | 2 +- .../dailybuild/trctoken/ContractTrcToken051.java | 2 +- .../dailybuild/trctoken/ContractTrcToken052.java | 2 +- .../dailybuild/trctoken/ContractTrcToken054.java | 2 +- .../dailybuild/trctoken/ContractTrcToken055.java | 2 +- .../dailybuild/trctoken/ContractTrcToken060.java | 2 +- .../dailybuild/trctoken/ContractTrcToken061.java | 2 +- .../dailybuild/trctoken/ContractTrcToken064.java | 2 +- .../dailybuild/trctoken/ContractTrcToken066.java | 2 +- .../dailybuild/trctoken/ContractTrcToken067.java | 2 +- .../dailybuild/trctoken/ContractTrcToken073.java | 2 +- .../dailybuild/trctoken/ContractTrcToken075.java | 2 +- .../dailybuild/trctoken/ContractTrcToken076.java | 2 +- .../dailybuild/trctoken/ContractTrcToken077.java | 2 +- .../dailybuild/trctoken/ContractTrcToken078.java | 2 +- .../dailybuild/trctoken/ContractTrcToken079.java | 2 +- .../dailybuild/trctoken/ContractTrcToken080.java | 2 +- .../dailybuild/trctoken/ContractTrcToken081.java | 2 +- .../AddressStrictCheck001.java | 4 ++-- .../AddressStrictCheck002.java | 4 ++-- .../batchValidateSignContract001.java | 4 ++-- .../batchValidateSignContract002.java | 4 ++-- .../batchValidateSignContract003.java | 4 ++-- .../batchValidateSignContract004.java | 4 ++-- .../batchValidateSignContract005.java | 4 ++-- .../batchValidateSignContract006.java | 4 ++-- .../batchValidateSignContract007.java | 4 ++-- .../batchValidateSignContract008.java | 4 ++-- .../batchValidateSignContract009.java | 4 ++-- .../batchValidateSignContract010.java | 4 ++-- .../batchValidateSignContract011.java | 4 ++-- .../batchValidateSignContract012.java | 4 ++-- .../tvmnewcommand/clearabi/ClearAbi001.java | 6 +++--- .../tvmnewcommand/clearabi/ClearAbi002.java | 6 +++--- .../tvmnewcommand/clearabi/ClearAbi003.java | 6 +++--- .../tvmnewcommand/clearabi/ClearAbi004.java | 6 +++--- .../tvmnewcommand/clearabi/ClearAbi005.java | 6 +++--- .../tvmnewcommand/clearabi/ClearAbi006.java | 6 +++--- .../tvmnewcommand/clearabi/ClearAbi007.java | 6 +++--- .../tvmnewcommand/clearabi/ClearAbi008.java | 6 +++--- .../tvmnewcommand/clearabi/NoAbi009.java | 6 +++--- .../tvmnewcommand/create2/Create2Test001.java | 2 +- .../tvmnewcommand/create2/Create2Test002.java | 2 +- .../tvmnewcommand/create2/Create2Test003.java | 2 +- .../tvmnewcommand/create2/Create2Test004.java | 2 +- .../tvmnewcommand/create2/Create2Test005.java | 2 +- .../tvmnewcommand/create2/Create2Test006.java | 2 +- .../tvmnewcommand/create2/Create2Test007.java | 2 +- .../tvmnewcommand/create2/Create2Test008.java | 2 +- .../tvmnewcommand/create2/Create2Test009.java | 2 +- .../tvmnewcommand/create2/Create2Test010.java | 2 +- .../tvmnewcommand/create2/Create2Test011.java | 2 +- .../tvmnewcommand/create2/Create2Test012.java | 2 +- .../tvmnewcommand/create2/Create2Test013.java | 2 +- .../tvmnewcommand/create2/Create2Test014.java | 2 +- .../tvmnewcommand/create2/Create2Test015.java | 2 +- .../tvmnewcommand/create2/Create2Test016.java | 2 +- .../tvmnewcommand/create2/Create2Test017.java | 2 +- .../tvmnewcommand/create2/Create2Test018.java | 2 +- .../tvmnewcommand/create2/Create2Test019.java | 6 +++--- .../tvmnewcommand/create2/Create2Test020.java | 6 +++--- .../tvmnewcommand/create2/Create2Test021.java | 6 +++--- .../tvmnewcommand/create2/Create2Test023.java | 2 +- .../tvmnewcommand/create2/Create2Test024.java | 2 +- .../tvmnewcommand/create2/Create2Test025.java | 2 +- .../extCodeHash/ExtCodeHashTest001.java | 2 +- .../extCodeHash/ExtCodeHashTest002.java | 2 +- .../extCodeHash/ExtCodeHashTest003.java | 2 +- .../extCodeHash/ExtCodeHashTest004.java | 2 +- .../extCodeHash/ExtCodeHashTest005.java | 2 +- .../extCodeHash/ExtCodeHashTest006.java | 2 +- .../extCodeHash/ExtCodeHashTest007.java | 2 +- .../extCodeHash/ExtCodeHashTest008.java | 2 +- .../extCodeHash/ExtCodeHashTest009.java | 2 +- .../extCodeHash/ExtCodeHashTest010.java | 2 +- .../extCodeHash/ExtCodeHashTest011.java | 2 +- .../isContract/isContractCommand001.java | 4 ++-- .../isContract/isContractCommand002.java | 4 ++-- .../isContract/isContractCommand003.java | 4 ++-- .../tvmnewcommand/istanbul/AltbnTest001.java | 2 +- .../istanbul/ChainidAndSelfBalance001.java | 2 +- .../istanbul/Create2IstanbulTest001.java | 2 +- .../tvmnewcommand/newGrammar/AbiEncodeTest.java | 2 +- .../tvmnewcommand/newGrammar/AbstractTest.java | 2 +- .../tvmnewcommand/newGrammar/AddressChange.java | 6 +++--- .../newGrammar/AssignToExternalTest.java | 2 +- .../tvmnewcommand/newGrammar/BlockhashTest.java | 2 +- .../newGrammar/CallValueGasPureTest.java | 2 +- .../tvmnewcommand/newGrammar/CallvalueTest.java | 2 +- .../newGrammar/ConstantCallStorage001.java | 6 +++--- .../newGrammar/ConstantCallStorage002.java | 6 +++--- .../newGrammar/ConstantCallStorage0425.java | 2 +- .../tvmnewcommand/newGrammar/EthGrammer.java | 2 +- .../tvmnewcommand/newGrammar/EthGrammer02.java | 2 +- .../tvmnewcommand/newGrammar/FixbugTest086.java | 2 +- .../newGrammar/FunctionArray2Storage086.java | 2 +- .../tvmnewcommand/newGrammar/LengthTest.java | 2 +- .../tvmnewcommand/newGrammar/MappingFixTest.java | 2 +- .../newGrammar/MappingPopingTest.java | 2 +- .../newGrammar/NegativeArrayTest.java | 2 +- .../newGrammar/NewFeatureForSolc068.java | 2 +- .../newGrammar/NewFeatureForSolc076.java | 2 +- .../newGrammar/NewFeatureForSolc080.java | 2 +- .../newGrammar/NewFeatureForSolc0811.java | 2 +- .../newGrammar/NewFeatureForSolc086.java | 2 +- .../newGrammar/NewFeatureForSolidity062.java | 2 +- .../tvmnewcommand/newGrammar/Opcode.java | 2 +- .../newGrammar/OverridePrivateFunction.java | 2 +- .../newGrammar/OverrideTest001.java | 2 +- .../tvmnewcommand/newGrammar/PayableTest.java | 2 +- .../tvmnewcommand/newGrammar/SelectorTest.java | 2 +- .../newGrammar/SlotAndOffsetNewGrammer.java | 2 +- .../newGrammar/StringSplitTest.java | 2 +- .../tvmnewcommand/newGrammar/TvmVote.java | 2 +- .../tvmnewcommand/newGrammar/VirtualTest001.java | 2 +- .../tvmnewcommand/newGrammar/assemblyTest.java | 2 +- .../tvmnewcommand/newGrammar/calldataTest.java | 2 +- .../newGrammar/constructorDefaultsTest.java | 2 +- .../newGrammar/enumAndStructTest.java | 2 +- .../newGrammar/fallbackOldVersion.java | 6 +++--- .../newGrammar/fallbackReceive.java | 6 +++--- .../newGrammar/mappingGetterTest.java | 2 +- .../newGrammar/stateVariableShadowing.java | 6 +++--- .../tvmnewcommand/newGrammar/typeNameTest.java | 2 +- .../shiftcommand/ShiftCommand001.java | 6 +++--- .../shiftcommand/ShiftCommand002.java | 6 +++--- .../shiftcommand/ShiftCommand003.java | 6 +++--- .../shiftcommand/ShiftCommand004.java | 6 +++--- .../shiftcommand/ShiftCommand005.java | 6 +++--- .../shiftcommand/ShiftCommand006.java | 6 +++--- .../transferfailed/ContractTestSendCoin001.java | 2 +- .../transferfailed/TestResourceReceiver.java | 6 +++--- .../transferfailed/TransferFailed001.java | 6 +++--- .../transferfailed/TransferFailed002.java | 6 +++--- .../transferfailed/TransferFailed003.java | 6 +++--- .../transferfailed/TransferFailed004.java | 6 +++--- .../transferfailed/TransferFailed005.java | 4 ++-- .../transferfailed/TransferFailed006.java | 4 ++-- .../transferfailed/TransferFailed007.java | 4 ++-- .../transferfailed/TransferFailed008.java | 6 +++--- .../triggerconstant/TriggerConstant001.java | 8 ++++---- .../triggerconstant/TriggerConstant002.java | 6 +++--- .../triggerconstant/TriggerConstant003.java | 6 +++--- .../triggerconstant/TriggerConstant004.java | 6 +++--- .../triggerconstant/TriggerConstant005.java | 6 +++--- .../triggerconstant/TriggerConstant006.java | 6 +++--- .../triggerconstant/TriggerConstant007.java | 6 +++--- .../triggerconstant/TriggerConstant008.java | 6 +++--- .../triggerconstant/TriggerConstant009.java | 6 +++--- .../triggerconstant/TriggerConstant010.java | 6 +++--- .../triggerconstant/TriggerConstant011.java | 6 +++--- .../triggerconstant/TriggerConstant012.java | 6 +++--- .../triggerconstant/TriggerConstant013.java | 10 +++++----- .../triggerconstant/TriggerConstant014.java | 8 ++++---- .../triggerconstant/TriggerConstant015.java | 6 +++--- .../triggerconstant/TriggerConstant016.java | 6 +++--- .../triggerconstant/TriggerConstant017.java | 6 +++--- .../triggerconstant/TriggerConstant018.java | 6 +++--- .../triggerconstant/TriggerConstant019.java | 6 +++--- .../triggerconstant/TriggerConstant020.java | 6 +++--- .../triggerconstant/TriggerConstant021.java | 6 +++--- .../triggerconstant/TriggerConstant022.java | 6 +++--- .../triggerconstant/TriggerConstant023.java | 6 +++--- .../triggerconstant/TriggerConstant024.java | 6 +++--- .../triggerconstant/TriggerConstant025.java | 6 +++--- .../triggerconstant/TriggerConstant026.java | 6 +++--- .../triggerconstant/TriggerConstant027.java | 6 +++--- .../tvmnewcommand/tryCatch/tryCatchTest001.java | 2 +- .../tvmnewcommand/tryCatch/tryCatchTest002.java | 2 +- .../tvmFreeze/FreezeContractTest001.java | 2 +- .../tvmFreeze/FreezeContractTest002.java | 2 +- .../tvmFreeze/FreezeSuicideTest001.java | 2 +- .../tvmassetissue/TvmAssetIssue001.java | 2 +- .../tvmassetissue/TvmAssetIssue002.java | 2 +- .../tvmassetissue/TvmAssetIssue003.java | 2 +- .../tvmassetissue/TvmAssetIssue004.java | 2 +- .../tvmassetissue/TvmAssetIssue005.java | 2 +- .../tvmstake/ContractRewardTest001.java | 2 +- .../tvmstake/IsSrCandidateTest001.java | 2 +- .../tvmstake/StackSuicideTest001.java | 2 +- .../tvmstake/StakeSuicideTest002.java | 2 +- .../tvmstake/StakeSuicideTest003.java | 2 +- .../tvmstake/StakeSuicideTest004.java | 2 +- .../tvmstake/StakeSuicideTest005.java | 2 +- .../tvmnewcommand/tvmstake/StakeTest001.java | 2 +- .../tvmnewcommand/tvmstake/UnStakeTest001.java | 2 +- .../TestValidatemultisign001.java | 2 +- .../TestValidatemultisign002.java | 2 +- .../TestValidatemultisign003.java | 2 +- .../zenProofCommand/VerifyBurnProof001.java | 2 +- .../zenProofCommand/VerifyMintProof001.java | 2 +- .../zenProofCommand/pedersenHash001.java | 4 ++-- .../zenProofCommand/pedersenHash002.java | 2 +- .../zenProofCommand/verifyTransferProof001.java | 4 ++-- .../zentoken/WalletTestZenToken001.java | 4 ++-- .../zentoken/WalletTestZenToken002.java | 8 ++++---- .../zentoken/WalletTestZenToken003.java | 2 +- .../zentoken/WalletTestZenToken004.java | 2 +- .../zentoken/WalletTestZenToken005.java | 2 +- .../zentoken/WalletTestZenToken006.java | 2 +- .../zentoken/WalletTestZenToken007.java | 6 +++--- .../zentoken/WalletTestZenToken008.java | 6 +++--- .../zentoken/WalletTestZenToken009.java | 2 +- .../zentoken/WalletTestZenToken010.java | 6 +++--- .../zentoken/WalletTestZenToken011.java | 6 +++--- .../zentrc20token/ShieldTrc20Token001.java | 2 +- .../zentrc20token/ShieldTrc20Token002.java | 4 ++-- .../zentrc20token/ShieldTrc20Token003.java | 4 ++-- .../zentrc20token/ShieldTrc20Token004.java | 4 ++-- .../zentrc20token/ShieldTrc20Token005.java | 4 ++-- .../zentrc20token/ShieldTrc20Token006.java | 6 +++--- .../tron/wallet/fulltest/AttackSendcoin.java | 4 ++-- .../stest/tron/wallet/fulltest/ContinueVote.java | 4 ++-- .../stest/tron/wallet/fulltest/Creatasset.java | 4 ++-- .../tron/wallet/fulltest/FreezeAndSendcoin.java | 4 ++-- .../stest/tron/wallet/fulltest/Fuzzytest.java | 6 +++--- .../wallet/fulltest/ParticipateAssetIssue.java | 4 ++-- .../wallet/fulltest/SuperWitnessAllowance.java | 2 +- .../tron/wallet/fulltest/TransferAssetIssue.java | 4 ++-- .../stest/tron/wallet/fulltest/TronDice.java | 2 +- .../stest/tron/wallet/fulltest/TvmContract.java | 2 +- .../wallet/mutisign/WalletTestMutiSign001.java | 2 +- .../wallet/mutisign/WalletTestMutiSign003.java | 2 +- .../wallet/mutisign/WalletTestMutiSign004.java | 4 ++-- .../wallet/mutisign/WalletTestMutiSign005.java | 4 ++-- .../newaddinterface2/CreateAccount2Test.java | 2 +- .../newaddinterface2/CreateAssetIssue2Test.java | 2 +- .../newaddinterface2/CreateTransaction2Test.java | 4 ++-- .../CreateaAndUpdateWitness2Test.java | 2 +- .../newaddinterface2/FreezeBalance2Test.java | 4 ++-- .../GetBlockByLatestNum2Test.java | 2 +- .../newaddinterface2/GetBlockByLimitNext2.java | 2 +- .../newaddinterface2/GetBlockByNum2Test.java | 4 ++-- .../newaddinterface2/GetNowBlock2Test.java | 4 ++-- .../GetTransactionsFromThis2Test.java | 4 ++-- .../newaddinterface2/GetTransactionsToThis2.java | 4 ++-- .../ParticipateAssetIssue2Test.java | 2 +- .../newaddinterface2/TransferAsset2Test.java | 2 +- .../newaddinterface2/UnfreezeAsset2Test.java | 2 +- .../newaddinterface2/UpdateAccount2Test.java | 2 +- .../newaddinterface2/UpdateAsset2Test.java | 2 +- .../VoteWitnessAccount2Test.java | 4 ++-- .../newaddinterface2/WithdrawBalance2Test.java | 4 ++-- .../wallet/onlinestress/ContractEvent001.java | 4 ++-- .../tron/wallet/onlinestress/CycleMultiSign.java | 6 +++--- .../onlinestress/DelayTransactionStress.java | 2 +- .../onlinestress/ExtCodeHashStressTest.java | 2 +- .../onlinestress/MainNetTransferSendOrAsset.java | 2 +- .../MainNetVoteOrFreezeOrCreate.java | 2 +- .../MultiValiSignPerformanceTest.java | 4 ++-- .../tron/wallet/onlinestress/MutiSignStress.java | 2 +- .../tron/wallet/onlinestress/ScanBlockTools.java | 8 ++++---- .../wallet/onlinestress/ShieldTrc10Stress.java | 4 ++-- .../wallet/onlinestress/ShieldTrc20Stress.java | 16 ++++++++-------- .../onlinestress/SupportTronlinkAutoTest.java | 2 +- .../wallet/onlinestress/TestApproveProposal.java | 4 ++-- .../onlinestress/TestExchangeTransaction.java | 2 +- .../onlinestress/TestMapBigLongAndNumbers.java | 2 +- .../wallet/onlinestress/TestMutiSignStress.java | 2 +- .../wallet/onlinestress/TestNetErc721Cat.java | 2 +- .../tron/wallet/onlinestress/TestNetFomo3D.java | 2 +- .../wallet/onlinestress/TestStorageAndCpu.java | 4 ++-- .../TestTransferTokenInContract.java | 4 ++-- .../onlinestress/WalletTestZenTokenStress.java | 6 +++--- .../tron/wallet/other/deployMainGateway.java | 2 +- .../tron/wallet/other/deploySideGateway.java | 2 +- .../wallet/transfer/WalletTestTransfer001.java | 4 ++-- .../wallet/transfer/WalletTestTransfer003.java | 6 +++--- .../wallet/transfer/WalletTestTransfer004.java | 4 ++-- .../wallet/transfer/WalletTestTransfer007.java | 8 ++++---- .../MutisignOperationerGodicTest.java | 4 ++-- .../wallet/witness/WalletTestWitness001.java | 4 ++-- .../wallet/witness/WalletTestWitness002.java | 4 ++-- protocol/build.gradle | 10 +++++----- 475 files changed, 788 insertions(+), 788 deletions(-) diff --git a/docs/implement-a-customized-actuator-en.md b/docs/implement-a-customized-actuator-en.md index b6f9124b64f..7152a4a67e4 100644 --- a/docs/implement-a-customized-actuator-en.md +++ b/docs/implement-a-customized-actuator-en.md @@ -234,7 +234,7 @@ public class SumActuatorTest { appTest.startServices(); appTest.startup(); channelFull = ManagedChannelBuilder.forTarget(serviceNode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/docs/implement-a-customized-actuator-zh.md b/docs/implement-a-customized-actuator-zh.md index a248aa5c18b..3c60584c599 100644 --- a/docs/implement-a-customized-actuator-zh.md +++ b/docs/implement-a-customized-actuator-zh.md @@ -236,7 +236,7 @@ public class SumActuatorTest { appTest.startServices(); appTest.startup(); channelFull = ManagedChannelBuilder.forTarget(serviceNode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java b/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java index b83c7235900..f3650bfd2be 100644 --- a/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java +++ b/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java @@ -15,14 +15,14 @@ public class DatabaseGrpcClient { public DatabaseGrpcClient(String host, int port) { channel = ManagedChannelBuilder.forAddress(host, port) - .usePlaintext(true) + .usePlaintext() .build(); databaseBlockingStub = DatabaseGrpc.newBlockingStub(channel); } public DatabaseGrpcClient(String host) { channel = ManagedChannelBuilder.forTarget(host) - .usePlaintext(true) + .usePlaintext() .build(); databaseBlockingStub = DatabaseGrpc.newBlockingStub(channel); } diff --git a/framework/src/main/java/org/tron/common/client/WalletGrpcClient.java b/framework/src/main/java/org/tron/common/client/WalletGrpcClient.java index 9d3b5797e20..d28df0e7c77 100644 --- a/framework/src/main/java/org/tron/common/client/WalletGrpcClient.java +++ b/framework/src/main/java/org/tron/common/client/WalletGrpcClient.java @@ -29,14 +29,14 @@ public class WalletGrpcClient { public WalletGrpcClient(String host, int port) { channel = ManagedChannelBuilder.forAddress(host, port) - .usePlaintext(true) + .usePlaintext() .build(); walletBlockingStub = WalletGrpc.newBlockingStub(channel); } public WalletGrpcClient(String host) { channel = ManagedChannelBuilder.forTarget(host) - .usePlaintext(true) + .usePlaintext() .build(); walletBlockingStub = WalletGrpc.newBlockingStub(channel); } diff --git a/framework/src/test/java/org/tron/core/CreateCommonTransactionTest.java b/framework/src/test/java/org/tron/core/CreateCommonTransactionTest.java index e787fe16e96..b75f6ba16ff 100644 --- a/framework/src/test/java/org/tron/core/CreateCommonTransactionTest.java +++ b/framework/src/test/java/org/tron/core/CreateCommonTransactionTest.java @@ -23,7 +23,7 @@ public class CreateCommonTransactionTest { */ public static void testCreateUpdateBrokerageContract() { WalletBlockingStub walletStub = WalletGrpc - .newBlockingStub(ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build()); + .newBlockingStub(ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build()); UpdateBrokerageContract.Builder updateBrokerageContract = UpdateBrokerageContract.newBuilder(); updateBrokerageContract.setOwnerAddress( ByteString.copyFrom(decodeFromBase58Check("TN3zfjYUmMFK3ZsHSsrdJoNRtGkQmZLBLz"))) diff --git a/framework/src/test/java/org/tron/core/services/DelegationServiceTest.java b/framework/src/test/java/org/tron/core/services/DelegationServiceTest.java index dc99cb8f4af..f0ad0d7c77f 100644 --- a/framework/src/test/java/org/tron/core/services/DelegationServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/DelegationServiceTest.java @@ -33,7 +33,7 @@ public DelegationServiceTest(TronApplicationContext context) { public static void testGrpc() { WalletBlockingStub walletStub = WalletGrpc .newBlockingStub(ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build()); BytesMessage.Builder builder = BytesMessage.newBuilder(); builder.setValue(ByteString.copyFromUtf8("TLTDZBcPoJ8tZ6TTEeEqEvwYFk2wgotSfD")); diff --git a/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java b/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java index 6a8e211a1ed..8f2b9645672 100644 --- a/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java @@ -44,7 +44,7 @@ public void test() { public void testGrpc() { WalletBlockingStub walletStub = WalletGrpc .newBlockingStub(ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build()); logger.info("getNodeInfo: {}", walletStub.getNodeInfo(EmptyMessage.getDefaultInstance())); } diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java index 472096cf24b..e65c686d5b5 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java @@ -59,10 +59,10 @@ public void init() { String pBFTNode = String.format("%s:%d", Args.getInstance().getNodeDiscoveryBindIp(), Args.getInstance().getRpcOnPBFTPort()); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); channelpBFT = ManagedChannelBuilder.forTarget(pBFTNode) - .usePlaintext(true) + .usePlaintext() .build(); context = new TronApplicationContext(DefaultConfig.class); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java index 4549b2cde4d..64f64f88099 100644 --- a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java +++ b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java @@ -64,7 +64,7 @@ public void startApp() { String fullnode = String.format("%s:%d", "127.0.0.1", Args.getInstance().getRpcPort()); ManagedChannel channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/account/BrokerageTest001.java b/framework/src/test/java/stest/tron/wallet/account/BrokerageTest001.java index 636c2d361df..fdaf67406b3 100644 --- a/framework/src/test/java/stest/tron/wallet/account/BrokerageTest001.java +++ b/framework/src/test/java/stest/tron/wallet/account/BrokerageTest001.java @@ -53,22 +53,22 @@ public class BrokerageTest001 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelSoliInFull = ManagedChannelBuilder.forTarget(soliInFullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSoliInFull = WalletSolidityGrpc.newBlockingStub(channelSoliInFull); channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount001.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount001.java index 003518663d3..365f200e1bd 100644 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount001.java +++ b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount001.java @@ -50,12 +50,12 @@ public class WalletTestAccount001 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount003.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount003.java index b2206b426f7..b602265d26a 100644 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount003.java +++ b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount003.java @@ -103,7 +103,7 @@ public static String getRandomStr(int length) { public void beforeClass() { PublicMethed.printAddress(lowBalTest); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount004.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount004.java index 80d84a96fa3..cc2ebd9a961 100644 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount004.java +++ b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount004.java @@ -68,12 +68,12 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext(true) + .usePlaintext() .build(); searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount005.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount005.java index da675842482..ddafcb3714f 100644 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount005.java +++ b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount005.java @@ -68,12 +68,12 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext(true) + .usePlaintext() .build(); searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount006.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount006.java index d231ac80c60..539d53b3761 100644 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount006.java +++ b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount006.java @@ -58,7 +58,7 @@ public void beforeClass() { PublicMethed.printAddress(account006Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount007.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount007.java index 33a20804976..926c24310d7 100644 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount007.java +++ b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount007.java @@ -59,7 +59,7 @@ public void beforeClass() { logger.info(account007Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount009.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount009.java index d60c9171507..5814f539df8 100644 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount009.java +++ b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount009.java @@ -59,7 +59,7 @@ public void beforeClass() { PublicMethed.printAddress(account009Key); PublicMethed.printAddress(account009SecondKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount011.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount011.java index d50783f72c1..6b79970de10 100644 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount011.java +++ b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount011.java @@ -47,12 +47,12 @@ public class WalletTestAccount011 { public void beforeClass() { PublicMethed.printAddress(account011Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock003.java b/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock003.java index c226cef843f..dc6a60bb430 100644 --- a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock003.java +++ b/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock003.java @@ -52,12 +52,12 @@ public static String loadPubKey() { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock004.java b/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock004.java index 2a21a4bdc6d..67ae17f0303 100644 --- a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock004.java +++ b/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock004.java @@ -50,7 +50,7 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock005.java b/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock005.java index 4179fd4748a..14c3674cb76 100644 --- a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock005.java +++ b/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock005.java @@ -50,7 +50,7 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock006.java b/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock006.java index 4fb4103a537..09175895c37 100644 --- a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock006.java +++ b/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock006.java @@ -39,12 +39,12 @@ public class WalletTestBlock006 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee001.java b/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee001.java index 3116598bc08..b74448b0dff 100644 --- a/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee001.java +++ b/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee001.java @@ -70,12 +70,12 @@ public class WalletTestCommittee001 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee002.java b/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee002.java index 4abd87f3937..6ac3e112e9a 100644 --- a/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee002.java +++ b/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee002.java @@ -66,12 +66,12 @@ public class WalletTestCommittee002 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); } diff --git a/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee003.java b/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee003.java index 12b098f95fa..c9f3c3d7221 100644 --- a/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee003.java +++ b/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee003.java @@ -69,12 +69,12 @@ public class WalletTestCommittee003 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee004.java b/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee004.java index 6112ab62c7c..a5a02187b2c 100644 --- a/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee004.java +++ b/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee004.java @@ -73,12 +73,12 @@ public class WalletTestCommittee004 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/common/client/GrpcClient.java b/framework/src/test/java/stest/tron/wallet/common/client/GrpcClient.java index 11482d4af83..c6186ca1f3a 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/GrpcClient.java +++ b/framework/src/test/java/stest/tron/wallet/common/client/GrpcClient.java @@ -46,7 +46,7 @@ public class GrpcClient { // public GrpcClient(String host, int port) { // channel = ManagedChannelBuilder.forAddress(host, port) - // .usePlaintext(true) + // .usePlaintext() // .build(); // blockingStub = WalletGrpc.newBlockingStub(channel); // } @@ -58,13 +58,13 @@ public class GrpcClient { public GrpcClient(String fullnode, String soliditynode) { if (!(fullnode.isEmpty())) { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } if (!(soliditynode.isEmpty())) { channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); blockingStubExtension = WalletExtensionGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/DailyBuildReport.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/DailyBuildReport.java index ec4b061d1b7..67dfe7c18be 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/DailyBuildReport.java +++ b/framework/src/test/java/stest/tron/wallet/common/client/utils/DailyBuildReport.java @@ -119,7 +119,7 @@ public void onFinish(ITestContext testContext) { */ public List> calculateAfterDailyBuild() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); endBlockNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/JsonRpcBase.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/JsonRpcBase.java index eec885184d4..203d6204933 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/JsonRpcBase.java +++ b/framework/src/test/java/stest/tron/wallet/common/client/utils/JsonRpcBase.java @@ -113,7 +113,7 @@ public class JsonRpcBase { @BeforeSuite(enabled = true, description = "Deploy json rpc test case resource") public void deployJsonRpcUseResource() throws Exception { Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); Assert.assertTrue( PublicMethed.sendcoin( diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldWrapper.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldWrapper.java index 52290587fc7..3c89b794ed3 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldWrapper.java +++ b/framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldWrapper.java @@ -57,7 +57,7 @@ public class ShieldWrapper { private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") .get(0); private ManagedChannel channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); private WalletGrpc.WalletBlockingStub blockingStubFull = WalletGrpc.newBlockingStub(channelFull); private Thread thread; diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/ZenTrc20Base.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/ZenTrc20Base.java index ac77484cc2f..21d03f2c26b 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/ZenTrc20Base.java +++ b/framework/src/test/java/stest/tron/wallet/common/client/utils/ZenTrc20Base.java @@ -90,7 +90,7 @@ public class ZenTrc20Base { @BeforeSuite(enabled = true, description = "Deploy shield trc20 depend contract") public void deployShieldTrc20DependContract() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage002.java b/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage002.java index a4db9515248..f4e1b335649 100644 --- a/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage002.java +++ b/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage002.java @@ -61,11 +61,11 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(linkage002Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage003.java b/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage003.java index 1b4d8ad3c65..190867bba00 100644 --- a/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage003.java +++ b/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage003.java @@ -54,11 +54,11 @@ public class ContractLinkage003 { public void beforeClass() { PublicMethed.printAddress(linkage002Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage004.java b/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage004.java index 5cc614e08bc..159411040d4 100644 --- a/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage004.java +++ b/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage004.java @@ -77,11 +77,11 @@ public class ContractLinkage004 { public void beforeClass() { PublicMethed.printAddress(linkage004Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage007.java b/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage007.java index 7fabf396aaf..3b9867466db 100644 --- a/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage007.java +++ b/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage007.java @@ -57,11 +57,11 @@ public class ContractLinkage007 { public void beforeClass() { PublicMethed.printAddress(linkage007Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario001.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario001.java index 04d305fd384..4f2945ad443 100644 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario001.java +++ b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario001.java @@ -53,11 +53,11 @@ public class ContractScenario001 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario003.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario003.java index ae22985e8eb..9a04c761c9b 100644 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario003.java +++ b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario003.java @@ -51,13 +51,13 @@ public class ContractScenario003 { public void beforeClass() { PublicMethed.printAddress(contract003Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); logger.info(Long.toString(PublicMethed.queryAccount(contract003Key, blockingStubFull) .getBalance())); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario004.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario004.java index 050f4a13a1d..ac3286b339e 100644 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario004.java +++ b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario004.java @@ -49,7 +49,7 @@ public class ContractScenario004 { public void beforeClass() { PublicMethed.printAddress(contract004Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario005.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario005.java index 69821298387..6787c22ca83 100644 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario005.java +++ b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario005.java @@ -51,7 +51,7 @@ public class ContractScenario005 { public void beforeClass() { PublicMethed.printAddress(contract005Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario006.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario006.java index 78071cc7611..6938c5c875d 100644 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario006.java +++ b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario006.java @@ -51,7 +51,7 @@ public class ContractScenario006 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario007.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario007.java index 5b85d9e441c..630bcbffeba 100644 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario007.java +++ b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario007.java @@ -48,7 +48,7 @@ public class ContractScenario007 { public void beforeClass() { PublicMethed.printAddress(contract007Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario008.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario008.java index 6fb52760440..4575d7545bb 100644 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario008.java +++ b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario008.java @@ -47,7 +47,7 @@ public class ContractScenario008 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario009.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario009.java index 4b902d5b404..170a64c1ecd 100644 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario009.java +++ b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario009.java @@ -50,7 +50,7 @@ public class ContractScenario009 { public void beforeClass() { PublicMethed.printAddress(contract009Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario010.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario010.java index 58bbc6869bb..3eeeaeb5cc5 100644 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario010.java +++ b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario010.java @@ -47,7 +47,7 @@ public class ContractScenario010 { public void beforeClass() { PublicMethed.printAddress(contract009Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario012.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario012.java index caa9bb1b3b3..50c45589b33 100644 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario012.java +++ b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario012.java @@ -62,7 +62,7 @@ public void beforeClass() { PublicMethed.printAddress(contract012Key); PublicMethed.printAddress(receiverKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario013.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario013.java index d6adab1e7f8..11025ede0ce 100644 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario013.java +++ b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario013.java @@ -51,7 +51,7 @@ public class ContractScenario013 { public void beforeClass() { PublicMethed.printAddress(contract013Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario014.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario014.java index 90733f6989e..4dcb217815d 100644 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario014.java +++ b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario014.java @@ -64,16 +64,16 @@ public class ContractScenario014 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario015.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario015.java index 2ef1504c833..345ea9dc67f 100644 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario015.java +++ b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario015.java @@ -60,16 +60,16 @@ public class ContractScenario015 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario016.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario016.java index d5784b78778..3ee8e164328 100644 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario016.java +++ b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario016.java @@ -62,11 +62,11 @@ public class ContractScenario016 { public void beforeClass() { PublicMethed.printAddress(testKeyForGrammarAddress); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/account/GetAccountBalance001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/account/GetAccountBalance001.java index 6cbcc9b016f..01cb4d3c738 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/account/GetAccountBalance001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/account/GetAccountBalance001.java @@ -56,7 +56,7 @@ public class GetAccountBalance001 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/account/TransactionFee001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/account/TransactionFee001.java index 24843f19716..89894e8666c 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/account/TransactionFee001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/account/TransactionFee001.java @@ -101,16 +101,16 @@ public class TransactionFee001 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/account/WalletTestAccount012.java b/framework/src/test/java/stest/tron/wallet/dailybuild/account/WalletTestAccount012.java index c85fdca800b..3dd38dbd80a 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/account/WalletTestAccount012.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/account/WalletTestAccount012.java @@ -51,7 +51,7 @@ public class WalletTestAccount012 { public void beforeClass() { PublicMethed.printAddress(frozenKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletExchange001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletExchange001.java index 03a20ac4aa5..233c8a64947 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletExchange001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletExchange001.java @@ -78,17 +78,17 @@ public class WalletExchange001 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue001.java index e11c73c11f8..d384793d2d4 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue001.java @@ -68,7 +68,7 @@ public static String loadPubKey() { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue002.java index 5dc6e50fd69..be0cc3de7d3 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue002.java @@ -63,7 +63,7 @@ public static String loadPubKey() { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue003.java index d27ab4ab55c..60969accc18 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue003.java @@ -85,7 +85,7 @@ public static String loadPubKey() { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue004.java index 2b05a13861a..773e066ece8 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue004.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue004.java @@ -72,7 +72,7 @@ public static String loadPubKey() { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue005.java index 8b7fa37c5c6..742d5a52ca1 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue005.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue005.java @@ -70,12 +70,12 @@ public static String loadPubKey() { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue006.java index 181dac3eddb..97ffdb472c5 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue006.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue006.java @@ -139,12 +139,12 @@ public void testExceptionGetAssetIssueListByTimestamp() { @BeforeClass(enabled = false) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue007.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue007.java index aaac0b4ff29..df91b54f8dd 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue007.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue007.java @@ -66,7 +66,7 @@ public void beforeClass() { PublicMethed.printAddress(testKeyForAssetIssue007); PublicMethed.printAddress(participateAssetCreateKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue008.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue008.java index 97ff64d5ca6..258e0168094 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue008.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue008.java @@ -75,12 +75,12 @@ public static String loadPubKey() { public void beforeClass() { logger.info(ByteArray.toHexString(ecKey.getPrivKeyBytes())); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue009.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue009.java index 924698b417b..9d27d2781a5 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue009.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue009.java @@ -90,12 +90,12 @@ public void testGetAssetIssueByAccountOrNameFromSolidity() { @BeforeClass(enabled = false) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue010.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue010.java index f60dfa834eb..d367411244c 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue010.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue010.java @@ -86,7 +86,7 @@ public static String loadPubKey() { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue011.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue011.java index c44485f98f9..cac82c366ec 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue011.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue011.java @@ -62,7 +62,7 @@ public void beforeClass() { PublicMethed.printAddress(transferAssetCreateKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue012.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue012.java index 8ad9b6cbe40..9e265d0ee33 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue012.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue012.java @@ -63,7 +63,7 @@ public void beforeClass() { logger.info(transferAssetCreateKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue013.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue013.java index 58795fda9e7..ca0ce33895c 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue013.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue013.java @@ -60,7 +60,7 @@ public class WalletTestAssetIssue013 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue014.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue014.java index 71d1ae22b47..4af6e9a1c72 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue014.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue014.java @@ -62,7 +62,7 @@ public void beforeClass() { logger.info(transferAssetCreateKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue015.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue015.java index 97dd589f858..3541d7fd191 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue015.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue015.java @@ -67,7 +67,7 @@ public void beforeClass() { logger.info(testKeyForNewAddress); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue016.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue016.java index d9e6df172e2..17838c49434 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue016.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue016.java @@ -76,22 +76,22 @@ public class WalletTestAssetIssue016 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelSoliInFull = ManagedChannelBuilder.forTarget(soliInFullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSoliInFull = WalletSolidityGrpc.newBlockingStub(channelSoliInFull); channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue020.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue020.java index a9a47bc5b4e..c4c4af4bfce 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue020.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue020.java @@ -71,22 +71,22 @@ public class WalletTestAssetIssue020 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelSoliInFull = ManagedChannelBuilder.forTarget(soliInFullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSoliInFull = WalletSolidityGrpc.newBlockingStub(channelSoliInFull); channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue017.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue017.java index e7391a1968f..f46f741ac60 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue017.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue017.java @@ -149,12 +149,12 @@ public static Protocol.Transaction signTransaction(ECKey ecKey, public void beforeClass() { logger.info(testKeyForAssetIssue017); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue018.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue018.java index deb877b2444..f21ce45a756 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue018.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue018.java @@ -71,7 +71,7 @@ public class WalletTestAssetIssue018 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.printAddress(assetAccount1Key); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue019.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue019.java index b320b428025..80e8f990e1e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue019.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue019.java @@ -53,7 +53,7 @@ public class WalletTestAssetIssue019 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar001.java index 56401c66b5f..fb47cae025e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar001.java @@ -61,11 +61,11 @@ public class ContractGrammar001 { public void beforeClass() { PublicMethed.printAddress(testKeyForGrammarAddress); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar002.java index 83c9f8e0129..3dc3eb5884d 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar002.java @@ -57,11 +57,11 @@ public class ContractGrammar002 { public void beforeClass() { PublicMethed.printAddress(testKeyForGrammarAddress2); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar003.java index b3aafd25e88..c2aa82cf48f 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar003.java @@ -59,11 +59,11 @@ public class ContractGrammar003 { public void beforeClass() { PublicMethed.printAddress(testKeyForGrammarAddress3); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar004.java index ceae3fad717..02717194a3c 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar004.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar004.java @@ -68,9 +68,9 @@ public class ContractGrammar004 { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(testKeyForGrammarAddress); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset001.java index 59baee113a2..03aafbaa558 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset001.java @@ -64,10 +64,10 @@ public class MarketSellAsset001 { /** constructor. */ @BeforeClass public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelSolidity = ManagedChannelBuilder.forTarget(solidityNode).usePlaintext(true).build(); + channelSolidity = ManagedChannelBuilder.forTarget(solidityNode).usePlaintext().build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); PublicMethed.printAddress(testKey001); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset002.java index d145a540f20..15cee662117 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset002.java @@ -64,7 +64,7 @@ public class MarketSellAsset002 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset003.java index fb7e2898dd2..16dd38a5cee 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset003.java @@ -56,7 +56,7 @@ public class MarketSellAsset003 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset004.java index 2a911540df4..fae498c2a1f 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset004.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset004.java @@ -55,7 +55,7 @@ public class MarketSellAsset004 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset005.java index 951c404c6f0..e0cbb6caee6 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset005.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset005.java @@ -59,7 +59,7 @@ public class MarketSellAsset005 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset006.java index 830795dfded..8499963ccd2 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset006.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset006.java @@ -79,17 +79,17 @@ public class MarketSellAsset006 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); PublicMethed.printAddress(testKey001); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventLog2.java b/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventLog2.java index 124a8d4405f..77362ed8284 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventLog2.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventLog2.java @@ -57,7 +57,7 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery001.java index 79075b8dccd..9e4832bcea9 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery001.java @@ -45,7 +45,7 @@ public class EventQuery001 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery002.java index 8eed6a93ae5..889b5f37cd1 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery002.java @@ -54,7 +54,7 @@ public class EventQuery002 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery003.java index 20cb549cf1b..21046bdde8d 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery003.java @@ -60,12 +60,12 @@ public class EventQuery003 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery004.java index f4181489708..a261f1bcf47 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery004.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery004.java @@ -58,12 +58,12 @@ public class EventQuery004 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/exceptionfee/AssertException.java b/framework/src/test/java/stest/tron/wallet/dailybuild/exceptionfee/AssertException.java index 2ca3c357777..25d2c6afb68 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/exceptionfee/AssertException.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/exceptionfee/AssertException.java @@ -62,16 +62,16 @@ public class AssertException { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMutiSign001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMutiSign001.java index 09ba3d8c737..fe3c2a832d9 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMutiSign001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMutiSign001.java @@ -76,7 +76,7 @@ public class HttpTestMutiSign001 { @BeforeClass public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction001.java index 4bb08861889..be2e605ae71 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction001.java @@ -61,11 +61,11 @@ public class ContractInternalTransaction001 { public void beforeClass() { PublicMethed.printAddress(testKeyForinternalTxsAddress); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction002.java index 0794f29dfa0..8f52fc059ea 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction002.java @@ -60,11 +60,11 @@ public class ContractInternalTransaction002 { public void beforeClass() { PublicMethed.printAddress(testKeyForinternalTxsAddress); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction003.java index 1c7a94d3002..56408c239d6 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction003.java @@ -62,11 +62,11 @@ public class ContractInternalTransaction003 { public void beforeClass() { PublicMethed.printAddress(testKeyForinternalTxsAddress); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts001.java index 174f6d1d8d2..fd22c9bb213 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts001.java @@ -52,7 +52,7 @@ public class Accounts001 extends JsonRpcBase { /** constructor. */ @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts002.java index e4d2407bdb4..303c3f060dc 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts002.java @@ -54,7 +54,7 @@ public class Accounts002 extends JsonRpcBase { /** constructor. */ @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/BuildTransaction001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/BuildTransaction001.java index 0521f094147..d7f68a5f3eb 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/BuildTransaction001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/BuildTransaction001.java @@ -44,7 +44,7 @@ public class BuildTransaction001 extends JsonRpcBase { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/GetBlock001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/GetBlock001.java index ee30990dd65..2614d7e8681 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/GetBlock001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/GetBlock001.java @@ -30,7 +30,7 @@ public class GetBlock001 extends JsonRpcBase { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage001.java index 7dc75caa32f..c1ae1bd3f8e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage001.java @@ -54,11 +54,11 @@ public class ContractLinkage001 { public void beforeClass() { PublicMethed.printAddress(linkage001Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage005.java index 691ce5dadab..2dd70c55335 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage005.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage005.java @@ -69,11 +69,11 @@ public class ContractLinkage005 { public void beforeClass() { PublicMethed.printAddress(linkage005Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage006.java index 74fde7b7fc6..ab70dfed487 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage006.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage006.java @@ -64,11 +64,11 @@ public class ContractLinkage006 { public void beforeClass() { PublicMethed.printAddress(linkage006Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario002.java index fe16f92575c..b642e7487d0 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario002.java @@ -67,27 +67,27 @@ public class ContractScenario002 { public void beforeClass() { PublicMethed.printAddress(contract002Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelSoliInFull = ManagedChannelBuilder.forTarget(soliInFullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSoliInFull = WalletSolidityGrpc.newBlockingStub(channelSoliInFull); channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario011.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario011.java index c0630d1e6eb..cb1ba01dbba 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario011.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario011.java @@ -68,7 +68,7 @@ public void beforeClass() { PublicMethed.printAddress(deployKey); PublicMethed.printAddress(triggerKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); Assert.assertTrue(PublicMethed.sendcoin(deployAddress, 50000000000L, fromAddress, @@ -80,7 +80,7 @@ public void beforeClass() { PublicMethed.waitProduceNextBlock(blockingStubFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario014.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario014.java index 7e11bc176dd..119b1800412 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario014.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario014.java @@ -58,7 +58,7 @@ public class ContractScenario014 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario015.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario015.java index e937f957b67..531b4a85a41 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario015.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario015.java @@ -55,7 +55,7 @@ public class ContractScenario015 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractTrc1155.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractTrc1155.java index d6786d6695a..5800459911b 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractTrc1155.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractTrc1155.java @@ -55,7 +55,7 @@ public class ContractTrc1155 { @BeforeSuite public void beforeSuite() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractUnknownException.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractUnknownException.java index 17fa1ef3f4a..e6d10e00fa9 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractUnknownException.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractUnknownException.java @@ -65,7 +65,7 @@ public class ContractUnknownException { public void beforeClass() { PublicMethed.printAddress(testKeyForGrammarAddress); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/GetTransactionInfoByBlockNumFromSolidity.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/GetTransactionInfoByBlockNumFromSolidity.java index 459d96c5cec..3fa52bb619f 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/GetTransactionInfoByBlockNumFromSolidity.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/GetTransactionInfoByBlockNumFromSolidity.java @@ -26,9 +26,9 @@ public class GetTransactionInfoByBlockNumFromSolidity { @Test(enabled = true, description = "test getTransactionInfoByBlockNumFromSolidity") public void test01GetTransactionInfoByBlockNumFromSolidity() { - channelFull = ManagedChannelBuilder.forTarget(fullNode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullNode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelSolidity = ManagedChannelBuilder.forTarget(solidityNode).usePlaintext(true).build(); + channelSolidity = ManagedChannelBuilder.forTarget(solidityNode).usePlaintext().build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); Protocol.Block solidityCurrentBlock = diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/RateLimite001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/RateLimite001.java index 7070ab0db33..2036dc78ebb 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/RateLimite001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/RateLimite001.java @@ -42,15 +42,15 @@ public class RateLimite001 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelRealSolidity = ManagedChannelBuilder.forTarget(realSoliditynode) - .usePlaintext(true) + .usePlaintext() .build(); realBlockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelRealSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/RequireException.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/RequireException.java index ce5ec3bfaf3..2d06f119e39 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/RequireException.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/RequireException.java @@ -60,16 +60,16 @@ public class RequireException { public void beforeClass() { PublicMethed.printAddress(testKeyForAssetIssue016); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount002.java index cdf1adfd022..d77bcf889c9 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount002.java @@ -76,12 +76,12 @@ public void TestGetAllAccount(){ @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext(true) + .usePlaintext() .build(); searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount010.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount010.java index c9437546cda..af151e8cf56 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount010.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount010.java @@ -55,7 +55,7 @@ public void beforeClass() { PublicMethed.printAddress(account010Key); PublicMethed.printAddress(account010SecondKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount012.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount012.java index f4aa3b2d523..3a3a72c3ce1 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount012.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount012.java @@ -75,10 +75,10 @@ public void beforeClass() { PublicMethed.printAddress(testKey002); PublicMethed.printAddress(testKey003); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount013.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount013.java index e6d94b64fed..09c5849e97e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount013.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount013.java @@ -78,22 +78,22 @@ public class WalletTestAccount013 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelSoliInFull = ManagedChannelBuilder.forTarget(soliInFullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSoliInFull = WalletSolidityGrpc.newBlockingStub(channelSoliInFull); channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount014.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount014.java index 2dbf04b380b..fbeb31307cb 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount014.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount014.java @@ -57,17 +57,17 @@ public class WalletTestAccount014 { public void beforeClass() { PublicMethed.printAddress(testKey002); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelSoliInFull = ManagedChannelBuilder.forTarget(soliInFullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSoliInFull = WalletSolidityGrpc.newBlockingStub(channelSoliInFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount015.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount015.java index 640f6f202ad..5d93cfa9bc1 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount015.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount015.java @@ -60,22 +60,22 @@ public class WalletTestAccount015 { public void beforeClass() { PublicMethed.printAddress(testKey002); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelSoliInFull = ManagedChannelBuilder.forTarget(soliInFullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSoliInFull = WalletSolidityGrpc.newBlockingStub(channelSoliInFull); channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestBlock001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestBlock001.java index e38dc2065eb..a2515b390ba 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestBlock001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestBlock001.java @@ -53,12 +53,12 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestBlock002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestBlock002.java index 3517f4696cd..86e9d5bd382 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestBlock002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestBlock002.java @@ -61,22 +61,22 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelSoliInFull = ManagedChannelBuilder.forTarget(soliInFullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSoliInFull = WalletSolidityGrpc.newBlockingStub(channelSoliInFull); channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestMutiSign002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestMutiSign002.java index 7b69b3b11b6..a2dc1ee6bf0 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestMutiSign002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestMutiSign002.java @@ -85,12 +85,12 @@ public class WalletTestMutiSign002 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestNode001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestNode001.java index e9496dc9a7d..8fe5bf28f15 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestNode001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestNode001.java @@ -39,11 +39,11 @@ public class WalletTestNode001 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer002.java index 06760b8f94d..a7cfc9d0f8a 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer002.java @@ -64,12 +64,12 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); blockingStubExtension = WalletExtensionGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer005.java index 39c8ad9daef..f6465143cc5 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer005.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer005.java @@ -68,12 +68,12 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); blockingStubExtension = WalletExtensionGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer006.java index 4223cdafca6..ec741fd0889 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer006.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer006.java @@ -68,12 +68,12 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); blockingStubExtension = WalletExtensionGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestWitness003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestWitness003.java index f76efdfd6ed..4c287b78df9 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestWitness003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestWitness003.java @@ -90,7 +90,7 @@ public void beforeClass() { logger.info(Base58.encode58Check(PublicMethed.getFinalAddress(lowBalTest))); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign01.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign01.java index eb9f64b1073..2c1edea5b06 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign01.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign01.java @@ -75,7 +75,7 @@ public class MultiSign01 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign02.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign02.java index b732a0e1619..63623df347b 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign02.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign02.java @@ -79,7 +79,7 @@ public class MultiSign02 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign03.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign03.java index cb0817fb70b..ec70ac4b8a4 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign03.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign03.java @@ -75,7 +75,7 @@ public class MultiSign03 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign04.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign04.java index abb64dc6274..ca7a80ab15e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign04.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign04.java @@ -79,7 +79,7 @@ public class MultiSign04 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign05.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign05.java index b4c639089cc..5f60c562b21 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign05.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign05.java @@ -78,7 +78,7 @@ public class MultiSign05 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign06.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign06.java index f5c58d5b7b0..6ef136a70e9 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign06.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign06.java @@ -79,7 +79,7 @@ public class MultiSign06 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign07.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign07.java index 41745b6047b..65b2b586337 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign07.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign07.java @@ -77,7 +77,7 @@ public class MultiSign07 { @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign08.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign08.java index e23d5d7d6ca..070e1fd46ae 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign08.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign08.java @@ -78,7 +78,7 @@ public class MultiSign08 { @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign09.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign09.java index 44463b368c7..6814116b3ba 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign09.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign09.java @@ -78,7 +78,7 @@ public class MultiSign09 { @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign10.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign10.java index 31ce7e37c8f..69fafd0c8d1 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign10.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign10.java @@ -78,7 +78,7 @@ public class MultiSign10 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign11.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign11.java index 2c0a4aa4696..cb8a6a8ee10 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign11.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign11.java @@ -79,7 +79,7 @@ public class MultiSign11 { @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign12.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign12.java index 2f7ba226b32..3225ab8210f 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign12.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign12.java @@ -78,7 +78,7 @@ public class MultiSign12 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign13.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign13.java index 2dd2a2c8d67..1b915b7ae77 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign13.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign13.java @@ -79,7 +79,7 @@ public class MultiSign13 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign14.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign14.java index 25fadd1e082..1de83a9b1fd 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign14.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign14.java @@ -81,7 +81,7 @@ public class MultiSign14 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign15.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign15.java index a0e7124bd69..9138d4ba71e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign15.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign15.java @@ -79,7 +79,7 @@ public class MultiSign15 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign16.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign16.java index 8504f12df7b..15be0aff99c 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign16.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign16.java @@ -80,7 +80,7 @@ public class MultiSign16 { @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign17.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign17.java index 735933714fc..132c75282ec 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign17.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign17.java @@ -80,7 +80,7 @@ public class MultiSign17 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign18.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign18.java index 809f7d484ec..67cb3f0d217 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign18.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign18.java @@ -79,7 +79,7 @@ public class MultiSign18 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign19.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign19.java index a2a61d4d5b2..b92a85b421c 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign19.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign19.java @@ -74,7 +74,7 @@ public class MultiSign19 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign20.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign20.java index e6cc4123bc0..416ad33e8ca 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign20.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign20.java @@ -79,7 +79,7 @@ public class MultiSign20 { @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign21.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign21.java index eafca020b4a..5fbd6edf69c 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign21.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign21.java @@ -79,7 +79,7 @@ public class MultiSign21 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign22.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign22.java index f56eef85291..3d2823ced04 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign22.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign22.java @@ -70,7 +70,7 @@ public class MultiSign22 { @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign23.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign23.java index c2ec7fb39a3..732fc3838a1 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign23.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign23.java @@ -83,7 +83,7 @@ public class MultiSign23 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign24.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign24.java index a96d5e165b1..d3e823953fa 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign24.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign24.java @@ -79,7 +79,7 @@ public class MultiSign24 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign26.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign26.java index bdcd997afe8..9ae775126c5 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign26.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign26.java @@ -81,7 +81,7 @@ public class MultiSign26 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign27.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign27.java index 5d25db9e159..04fde1798dc 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign27.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign27.java @@ -73,7 +73,7 @@ public class MultiSign27 { @BeforeClass public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign28.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign28.java index dda33e99e0c..837488dff2a 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign28.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign28.java @@ -69,7 +69,7 @@ public class MultiSign28 { @BeforeClass public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign29.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign29.java index ec67d890388..254e166a4a7 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign29.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign29.java @@ -70,7 +70,7 @@ public class MultiSign29 { @BeforeClass public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign30.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign30.java index 854c2b7c986..8c3f522d109 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign30.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign30.java @@ -71,7 +71,7 @@ public class MultiSign30 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign31.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign31.java index 7aa7403c631..89c7ad0845c 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign31.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign31.java @@ -80,7 +80,7 @@ public class MultiSign31 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign33.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign33.java index 29c8c216d69..3c01db480ad 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign33.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign33.java @@ -66,7 +66,7 @@ public class MultiSign33 { @BeforeClass public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign34.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign34.java index 5205a5b4265..649cf12e4e7 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign34.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign34.java @@ -71,7 +71,7 @@ public class MultiSign34 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign35.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign35.java index 68808226df9..19db32ab69c 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign35.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign35.java @@ -74,7 +74,7 @@ public class MultiSign35 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign36.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign36.java index 1fb3bca6992..008194c81e6 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign36.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign36.java @@ -79,7 +79,7 @@ public class MultiSign36 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign37.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign37.java index 2f6ebf69130..f9d810ec589 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign37.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign37.java @@ -82,7 +82,7 @@ public class MultiSign37 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountPermissionUpdateTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountPermissionUpdateTest.java index c179d5b9821..244f75ab280 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountPermissionUpdateTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountPermissionUpdateTest.java @@ -74,7 +74,7 @@ public class MutiSignAccountPermissionUpdateTest { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountPermissionUpdateTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountPermissionUpdateTest002.java index 68513fd3a58..bfd91578a42 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountPermissionUpdateTest002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountPermissionUpdateTest002.java @@ -74,7 +74,7 @@ public class MutiSignAccountPermissionUpdateTest002 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountTest.java index a2d7790bf9d..6431929b8a9 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountTest.java @@ -83,7 +83,7 @@ public static byte[] randomBytes(int length) { public void beforeClass() { //operations = "77ff1fc0037e0100000000000000000000000000000000000000000000000000"; channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountTest002.java index ec26f326285..3d6c6e83d46 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountTest002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountTest002.java @@ -82,7 +82,7 @@ public static byte[] randomBytes(int length) { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAssetTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAssetTest.java index 8b62df24b37..0b7aaf59c98 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAssetTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAssetTest.java @@ -75,7 +75,7 @@ public class MutiSignAssetTest { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAssetTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAssetTest002.java index 2f829e1fcb7..cead81819fb 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAssetTest002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAssetTest002.java @@ -75,7 +75,7 @@ public class MutiSignAssetTest002 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignClearContractAbiTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignClearContractAbiTest.java index cce4a0c4660..fd873fc0bb3 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignClearContractAbiTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignClearContractAbiTest.java @@ -77,10 +77,10 @@ public class MutiSignClearContractAbiTest { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignExchangeContractTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignExchangeContractTest.java index f8cf2b07a3d..291d28352e4 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignExchangeContractTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignExchangeContractTest.java @@ -86,12 +86,12 @@ public class MutiSignExchangeContractTest { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignExchangeContractTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignExchangeContractTest002.java index 5edc03924e3..0a04c46a1ca 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignExchangeContractTest002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignExchangeContractTest002.java @@ -86,12 +86,12 @@ public class MutiSignExchangeContractTest002 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignMarketAssetTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignMarketAssetTest.java index 13be09fc9b9..da1c25cb649 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignMarketAssetTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignMarketAssetTest.java @@ -57,7 +57,7 @@ public class MutiSignMarketAssetTest { @BeforeClass public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); Assert.assertTrue(PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignProposalTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignProposalTest.java index 73d5c0071f6..68308bda11a 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignProposalTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignProposalTest.java @@ -68,12 +68,12 @@ public class MutiSignProposalTest { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignProposalTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignProposalTest002.java index 6724fe22d97..8c8a9b14975 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignProposalTest002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignProposalTest002.java @@ -68,12 +68,12 @@ public class MutiSignProposalTest002 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignSmartContractTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignSmartContractTest.java index 2b1c4943504..522bc66ceb0 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignSmartContractTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignSmartContractTest.java @@ -76,10 +76,10 @@ public class MutiSignSmartContractTest { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignSmartContractTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignSmartContractTest002.java index 655518c4ab9..4d1f891925a 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignSmartContractTest002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignSmartContractTest002.java @@ -76,10 +76,10 @@ public class MutiSignSmartContractTest002 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignUpdataBrokerageTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignUpdataBrokerageTest.java index 0958518d43d..bd8f2c87827 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignUpdataBrokerageTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignUpdataBrokerageTest.java @@ -63,10 +63,10 @@ public class MutiSignUpdataBrokerageTest { @BeforeClass public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode).usePlaintext(true).build(); + channelSolidity = ManagedChannelBuilder.forTarget(soliditynode).usePlaintext().build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit001.java index a2190cc24ac..4ac013f8e52 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit001.java @@ -53,11 +53,11 @@ public class ContractOriginEnergyLimit001 { public void beforeClass() { PublicMethed.printAddress(testKeyForGrammarAddress3); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit004.java index c2ca4ff01a0..496c4097a6d 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit004.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit004.java @@ -58,11 +58,11 @@ public class ContractOriginEnergyLimit004 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/transaction/TransactionPendingQuery001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/transaction/TransactionPendingQuery001.java index a0ec6441b33..a815f840fc4 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/transaction/TransactionPendingQuery001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/transaction/TransactionPendingQuery001.java @@ -61,17 +61,17 @@ public class TransactionPendingQuery001 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken001.java index 66ffddb0633..18b28eeb8e2 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken001.java @@ -60,7 +60,7 @@ public class ContractTrcToken001 { @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.printAddress(dev001Key); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken002.java index 83d4448645f..81055f9435d 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken002.java @@ -65,7 +65,7 @@ public class ContractTrcToken002 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken003.java index 4bc3cdab8cb..64147ba7f44 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken003.java @@ -63,7 +63,7 @@ public class ContractTrcToken003 { @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.printAddress(dev001Key); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken005.java index cff6e0ddcae..f4513bfdfef 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken005.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken005.java @@ -66,7 +66,7 @@ public class ContractTrcToken005 { @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.printAddress(dev001Key); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken011.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken011.java index f39b96cdf00..98f92a36572 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken011.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken011.java @@ -74,11 +74,11 @@ public class ContractTrcToken011 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken012.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken012.java index 14ad0553a11..51924b918b8 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken012.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken012.java @@ -65,7 +65,7 @@ public class ContractTrcToken012 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken014.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken014.java index 1134d4bae4c..e87790c6c96 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken014.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken014.java @@ -69,7 +69,7 @@ public class ContractTrcToken014 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken018.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken018.java index 07f96d21425..f795162f2a2 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken018.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken018.java @@ -73,7 +73,7 @@ public class ContractTrcToken018 { @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.printAddress(dev001Key); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken023.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken023.java index c78a088dd3c..05508808114 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken023.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken023.java @@ -71,7 +71,7 @@ private static int randomInt(int minInt, int maxInt) { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.printAddress(dev001Key); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken026.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken026.java index cc6251d9720..0747a38f68b 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken026.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken026.java @@ -69,7 +69,7 @@ private static int randomInt(int minInt, int maxInt) { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken027.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken027.java index 63fc4690a95..cc372212f3b 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken027.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken027.java @@ -73,7 +73,7 @@ private static int randomInt(int minInt, int maxInt) { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken028.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken028.java index 06ddba41e0e..20ec1e96c18 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken028.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken028.java @@ -67,7 +67,7 @@ private static int randomInt(int minInt, int maxInt) { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken029.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken029.java index 5dc1e876212..9d719619b84 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken029.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken029.java @@ -63,7 +63,7 @@ public class ContractTrcToken029 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken030.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken030.java index c35993a0207..0562ab5a840 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken030.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken030.java @@ -62,7 +62,7 @@ public class ContractTrcToken030 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken031.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken031.java index 4622e1f4897..598bf4faac3 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken031.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken031.java @@ -66,7 +66,7 @@ public class ContractTrcToken031 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken034.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken034.java index f9e5ed01772..b58777a69f9 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken034.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken034.java @@ -63,7 +63,7 @@ public class ContractTrcToken034 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 4048000000L, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken035.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken035.java index e3568c6873c..73ec82928cf 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken035.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken035.java @@ -64,7 +64,7 @@ public class ContractTrcToken035 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken036.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken036.java index 400e51cae3a..8d020a433fe 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken036.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken036.java @@ -65,7 +65,7 @@ public class ContractTrcToken036 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken037.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken037.java index 14c395b2f2f..caa2d493bed 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken037.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken037.java @@ -63,7 +63,7 @@ public class ContractTrcToken037 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken038.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken038.java index af4cc453903..63d88c71765 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken038.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken038.java @@ -63,7 +63,7 @@ public class ContractTrcToken038 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken039.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken039.java index 9f18bb1afb7..85a910193ba 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken039.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken039.java @@ -65,7 +65,7 @@ public class ContractTrcToken039 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken041.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken041.java index 9281c03d8cc..541811f51c3 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken041.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken041.java @@ -68,7 +68,7 @@ private static int randomInt(int minInt, int maxInt) { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken043.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken043.java index c07017f0ce5..2af2e6a386b 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken043.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken043.java @@ -73,7 +73,7 @@ public class ContractTrcToken043 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken048.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken048.java index ef74ef6e0c3..f340114a45c 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken048.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken048.java @@ -63,7 +63,7 @@ public class ContractTrcToken048 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken049.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken049.java index 0ee8fe250c5..bb901e48016 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken049.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken049.java @@ -69,7 +69,7 @@ private static int randomInt(int minInt, int maxInt) { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken050.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken050.java index f428d2932a7..67becbcaafc 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken050.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken050.java @@ -64,7 +64,7 @@ public class ContractTrcToken050 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken051.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken051.java index 5abad4b440d..bbfbccefe49 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken051.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken051.java @@ -64,7 +64,7 @@ public class ContractTrcToken051 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken052.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken052.java index b0b5efc8f20..5f76a458d4f 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken052.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken052.java @@ -63,7 +63,7 @@ public class ContractTrcToken052 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken054.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken054.java index 9ad9496fae4..7d03fc94753 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken054.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken054.java @@ -65,7 +65,7 @@ public class ContractTrcToken054 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken055.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken055.java index 36ce5677f1d..5d48630e192 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken055.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken055.java @@ -65,7 +65,7 @@ public class ContractTrcToken055 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken060.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken060.java index 4884706c2bf..088178a880c 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken060.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken060.java @@ -60,7 +60,7 @@ public class ContractTrcToken060 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken061.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken061.java index c13556767f7..6c78226dab7 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken061.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken061.java @@ -61,7 +61,7 @@ public class ContractTrcToken061 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken064.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken064.java index a7bce360148..58426f66f2b 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken064.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken064.java @@ -69,7 +69,7 @@ public class ContractTrcToken064 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken066.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken066.java index 5fef9eca4ac..68836cc079b 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken066.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken066.java @@ -67,7 +67,7 @@ public class ContractTrcToken066 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken067.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken067.java index 67d9f896944..fa6931be987 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken067.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken067.java @@ -67,7 +67,7 @@ public class ContractTrcToken067 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken073.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken073.java index 1d8024559e7..1db7cd8ee4d 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken073.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken073.java @@ -60,7 +60,7 @@ public class ContractTrcToken073 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken075.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken075.java index 849f752489d..3f959f772b5 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken075.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken075.java @@ -62,7 +62,7 @@ public class ContractTrcToken075 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken076.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken076.java index 51f7fc1b2db..23092b86f7a 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken076.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken076.java @@ -54,7 +54,7 @@ public class ContractTrcToken076 { public void beforeClass() { PublicMethed.printAddress(testKeyForGrammarAddress); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); logger.info(Long.toString(PublicMethed.queryAccount(testNetAccountKey, blockingStubFull) diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken077.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken077.java index f5cfcdab3b6..e9eb6d3e1f1 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken077.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken077.java @@ -54,7 +54,7 @@ public class ContractTrcToken077 { public void beforeClass() { PublicMethed.printAddress(testKeyForGrammarAddress); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); logger.info(Long.toString(PublicMethed.queryAccount(testNetAccountKey, blockingStubFull) diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken078.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken078.java index 84ace997b17..f872d6a0a9b 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken078.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken078.java @@ -74,7 +74,7 @@ public static String byte2HexStr(byte[] b, int offset, int length) { public void beforeClass() { PublicMethed.printAddress(testKeyForinternalTxsAddress); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken079.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken079.java index 46c5948b69b..f7a6d452e46 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken079.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken079.java @@ -66,7 +66,7 @@ public class ContractTrcToken079 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken080.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken080.java index c77fd323690..9c980ebdc66 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken080.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken080.java @@ -61,7 +61,7 @@ public class ContractTrcToken080 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken081.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken081.java index 8312b886b10..f2324b3cea2 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken081.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken081.java @@ -59,7 +59,7 @@ public class ContractTrcToken081 { @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.printAddress(dev001Key); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/addressStrictCheck/AddressStrictCheck001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/addressStrictCheck/AddressStrictCheck001.java index 814c9e38bd2..597b8541ac4 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/addressStrictCheck/AddressStrictCheck001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/addressStrictCheck/AddressStrictCheck001.java @@ -60,11 +60,11 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/addressStrictCheck/AddressStrictCheck002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/addressStrictCheck/AddressStrictCheck002.java index e64b30b47f1..13fd24c62dc 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/addressStrictCheck/AddressStrictCheck002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/addressStrictCheck/AddressStrictCheck002.java @@ -60,11 +60,11 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract001.java index f1b846be342..239a11c10a2 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract001.java @@ -62,9 +62,9 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); txid = PublicMethed .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract002.java index c0bb3e908a4..2900554f345 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract002.java @@ -63,9 +63,9 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); txid = PublicMethed .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract003.java index 4c1d12e6569..4f2b62354f1 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract003.java @@ -63,9 +63,9 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); txid = PublicMethed .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract004.java index f1a3eafa181..ca1da710088 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract004.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract004.java @@ -66,9 +66,9 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); txid = PublicMethed .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract005.java index 5277eb725f4..3575ecd3751 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract005.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract005.java @@ -64,9 +64,9 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); txid = PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract006.java index bbc541830c7..f64d71de7c1 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract006.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract006.java @@ -67,9 +67,9 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); txid = PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract007.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract007.java index b252c7170f6..5a2a6f2b383 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract007.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract007.java @@ -64,9 +64,9 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract008.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract008.java index 9f9b8b30512..7181272948a 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract008.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract008.java @@ -56,9 +56,9 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); txid = PublicMethed .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract009.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract009.java index fb9a8325914..0ed65c032a4 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract009.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract009.java @@ -60,9 +60,9 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); txid = PublicMethed .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract010.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract010.java index 663be1160c7..58ee1e4ef9c 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract010.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract010.java @@ -61,9 +61,9 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); txid = PublicMethed .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract011.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract011.java index 1697784e7e3..8286211defb 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract011.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract011.java @@ -64,9 +64,9 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); txid = PublicMethed .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract012.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract012.java index c35abd39f78..c8a92174265 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract012.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract012.java @@ -65,9 +65,9 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); txid = PublicMethed .sendcoinGetTransactionId(contractExcAddress, 10000000000L, testNetAccountAddress, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi001.java index aeb7f5d6e85..8ae62939860 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi001.java @@ -65,16 +65,16 @@ public class ClearAbi001 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi002.java index b949713f0ab..4b8c50b980e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi002.java @@ -60,16 +60,16 @@ public class ClearAbi002 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi003.java index 3daf89fc406..b6553e1e755 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi003.java @@ -60,16 +60,16 @@ public class ClearAbi003 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi004.java index efa7f20f6d8..4e2a940bef1 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi004.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi004.java @@ -57,16 +57,16 @@ public class ClearAbi004 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi005.java index 0af7a1bf2f1..149d512c336 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi005.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi005.java @@ -64,16 +64,16 @@ public class ClearAbi005 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi006.java index 25e85fe9e73..19e52757f07 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi006.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi006.java @@ -60,16 +60,16 @@ public class ClearAbi006 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi007.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi007.java index 02bf0babc42..5ee23abd611 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi007.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi007.java @@ -60,16 +60,16 @@ public class ClearAbi007 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi008.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi008.java index c12802bab0a..76d9b04804d 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi008.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi008.java @@ -60,16 +60,16 @@ public class ClearAbi008 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/NoAbi009.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/NoAbi009.java index fc6e57905ae..328e00b19f0 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/NoAbi009.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/NoAbi009.java @@ -69,16 +69,16 @@ public class NoAbi009 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test001.java index ce88b68644b..8e64dcde4e3 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test001.java @@ -62,7 +62,7 @@ public class Create2Test001 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test002.java index a708e96c3aa..e891e2847c3 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test002.java @@ -61,7 +61,7 @@ public class Create2Test002 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test003.java index bc536e7caf4..f381432548c 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test003.java @@ -60,7 +60,7 @@ public class Create2Test003 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test004.java index 17e87b7d289..40b6e6bf769 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test004.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test004.java @@ -64,7 +64,7 @@ public class Create2Test004 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test005.java index 9ec661328e6..cfc817ce2f3 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test005.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test005.java @@ -61,7 +61,7 @@ public class Create2Test005 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test006.java index fdd0504c242..20d316e34ac 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test006.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test006.java @@ -61,7 +61,7 @@ public class Create2Test006 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test007.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test007.java index 135a76a7560..1f25e90dc13 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test007.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test007.java @@ -61,7 +61,7 @@ public class Create2Test007 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test008.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test008.java index b278ff2ccac..ed382c537e8 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test008.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test008.java @@ -61,7 +61,7 @@ public class Create2Test008 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test009.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test009.java index fc3132c2d72..2d041d41ff2 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test009.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test009.java @@ -61,7 +61,7 @@ public class Create2Test009 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test010.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test010.java index cd32b9c983d..a5df4271070 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test010.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test010.java @@ -58,7 +58,7 @@ public class Create2Test010 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test011.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test011.java index 93a149c6298..3d8aa9a3cb6 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test011.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test011.java @@ -61,7 +61,7 @@ public class Create2Test011 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test012.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test012.java index f4a906c3af3..c77da670bd3 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test012.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test012.java @@ -62,7 +62,7 @@ public class Create2Test012 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test013.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test013.java index d1b1ebba816..9e4b13a896e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test013.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test013.java @@ -63,7 +63,7 @@ public class Create2Test013 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test014.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test014.java index 127eac0aad9..d276eab67ab 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test014.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test014.java @@ -64,7 +64,7 @@ public class Create2Test014 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test015.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test015.java index c61b9befe1b..890704c3d93 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test015.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test015.java @@ -62,7 +62,7 @@ public class Create2Test015 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test016.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test016.java index 055f55a982f..2934a55d909 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test016.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test016.java @@ -62,7 +62,7 @@ public class Create2Test016 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test017.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test017.java index 6346c900d21..337ec84b1a6 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test017.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test017.java @@ -61,7 +61,7 @@ public class Create2Test017 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test018.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test018.java index 858d167c80d..33608b3ad85 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test018.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test018.java @@ -62,7 +62,7 @@ public class Create2Test018 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test019.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test019.java index d903550be89..bd77817c636 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test019.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test019.java @@ -66,16 +66,16 @@ public class Create2Test019 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test020.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test020.java index 5329174e028..9ec6ad9f1d9 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test020.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test020.java @@ -62,16 +62,16 @@ public class Create2Test020 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test021.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test021.java index fafbd5244fe..847a6f6577e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test021.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test021.java @@ -74,16 +74,16 @@ public void beforeClass() { PublicMethed.printAddress(contractExcKey); PublicMethed.printAddress(resourceOnwerKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test023.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test023.java index b390698eb60..9ebc0295c32 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test023.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test023.java @@ -59,7 +59,7 @@ public class Create2Test023 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test024.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test024.java index 8c42a4362ec..f406a294e7b 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test024.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test024.java @@ -60,7 +60,7 @@ public class Create2Test024 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test025.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test025.java index be459a86a81..ca0a9a2d9c7 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test025.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test025.java @@ -60,7 +60,7 @@ public class Create2Test025 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest001.java index ecc505fa210..e6da831111f 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest001.java @@ -70,7 +70,7 @@ public class ExtCodeHashTest001 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest002.java index 9fbe6334872..933e9c4b7d6 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest002.java @@ -64,7 +64,7 @@ public class ExtCodeHashTest002 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest003.java index e6f29b2eaf0..1d036eae6f7 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest003.java @@ -68,7 +68,7 @@ public class ExtCodeHashTest003 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest004.java index 8e64990fe57..4b68380ff9e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest004.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest004.java @@ -67,7 +67,7 @@ public class ExtCodeHashTest004 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest005.java index 060b9b8e999..0f95573a1ea 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest005.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest005.java @@ -68,7 +68,7 @@ public class ExtCodeHashTest005 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest006.java index a0723bbe817..e68bb5907ae 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest006.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest006.java @@ -66,7 +66,7 @@ public class ExtCodeHashTest006 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest007.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest007.java index ddf712a08e8..31751de1346 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest007.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest007.java @@ -66,7 +66,7 @@ public class ExtCodeHashTest007 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest008.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest008.java index 87ac6cddfd3..5e2f90ce186 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest008.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest008.java @@ -64,7 +64,7 @@ public class ExtCodeHashTest008 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest009.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest009.java index 71b3b7b9274..e3f97cdf25a 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest009.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest009.java @@ -64,7 +64,7 @@ public class ExtCodeHashTest009 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest010.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest010.java index a9271034372..fa52442915a 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest010.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest010.java @@ -63,7 +63,7 @@ public class ExtCodeHashTest010 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest011.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest011.java index 20b5267d13f..1efc05049af 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest011.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest011.java @@ -65,7 +65,7 @@ public class ExtCodeHashTest011 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand001.java index 736fa1b5202..2c9bba20ccb 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand001.java @@ -62,9 +62,9 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand002.java index 327092c74e8..f1c588d6889 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand002.java @@ -64,11 +64,11 @@ public void beforeClass() { PublicMethed.printAddress(contractExcKey); PublicMethed.printAddress(selfdestructContractKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand003.java index ee33144338f..0f492396a92 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand003.java @@ -63,11 +63,11 @@ public void beforeClass() { PublicMethed.printAddress(contractExcKey); PublicMethed.printAddress(selfdestructContractKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/AltbnTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/AltbnTest001.java index 355c8cd30af..4324d68104d 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/AltbnTest001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/AltbnTest001.java @@ -50,7 +50,7 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/ChainidAndSelfBalance001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/ChainidAndSelfBalance001.java index f9770923984..ef638ec0f58 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/ChainidAndSelfBalance001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/ChainidAndSelfBalance001.java @@ -48,7 +48,7 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/Create2IstanbulTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/Create2IstanbulTest001.java index 9f6d87cf3af..89799615d99 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/Create2IstanbulTest001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/Create2IstanbulTest001.java @@ -47,7 +47,7 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AbiEncodeTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AbiEncodeTest.java index 6b8b21a29c5..8ff57cca43a 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AbiEncodeTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AbiEncodeTest.java @@ -54,7 +54,7 @@ public class AbiEncodeTest { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AbstractTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AbstractTest.java index 63aaa9ae313..e0f163a6362 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AbstractTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AbstractTest.java @@ -39,7 +39,7 @@ public class AbstractTest { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AddressChange.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AddressChange.java index d537f06ebd6..60f7f27a19e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AddressChange.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AddressChange.java @@ -61,16 +61,16 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AssignToExternalTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AssignToExternalTest.java index 990d8f44c59..9ec27a7d473 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AssignToExternalTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AssignToExternalTest.java @@ -53,7 +53,7 @@ public class AssignToExternalTest { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/BlockhashTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/BlockhashTest.java index febc9cbe63c..c4d47afd163 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/BlockhashTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/BlockhashTest.java @@ -48,7 +48,7 @@ public class BlockhashTest { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/CallValueGasPureTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/CallValueGasPureTest.java index 52f1eb6b80a..df5befec7d8 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/CallValueGasPureTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/CallValueGasPureTest.java @@ -55,7 +55,7 @@ public class CallValueGasPureTest { @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.printAddress(testKey001); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/CallvalueTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/CallvalueTest.java index 296f8a36b44..bb139eccc16 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/CallvalueTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/CallvalueTest.java @@ -54,7 +54,7 @@ public class CallvalueTest { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage001.java index bd6ad18c451..4d49194477c 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage001.java @@ -62,16 +62,16 @@ public class ConstantCallStorage001 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage002.java index 6e838b17bb4..fff67eb8a0d 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage002.java @@ -62,16 +62,16 @@ public class ConstantCallStorage002 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage0425.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage0425.java index 44e1fe2635f..b36b257d678 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage0425.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage0425.java @@ -56,7 +56,7 @@ public class ConstantCallStorage0425 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/EthGrammer.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/EthGrammer.java index 5633f0ff936..887d94dc351 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/EthGrammer.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/EthGrammer.java @@ -64,7 +64,7 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/EthGrammer02.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/EthGrammer02.java index 10b47c7793f..97ea2d08963 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/EthGrammer02.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/EthGrammer02.java @@ -59,7 +59,7 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/FixbugTest086.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/FixbugTest086.java index cd31d1f6826..268f3bdd4d9 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/FixbugTest086.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/FixbugTest086.java @@ -57,7 +57,7 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/FunctionArray2Storage086.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/FunctionArray2Storage086.java index 9977fc94cc8..b5527f9cf32 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/FunctionArray2Storage086.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/FunctionArray2Storage086.java @@ -57,7 +57,7 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/LengthTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/LengthTest.java index 2f7950ed5d9..8c1a685113e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/LengthTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/LengthTest.java @@ -52,7 +52,7 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/MappingFixTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/MappingFixTest.java index 4527a8d63bf..849a08020ab 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/MappingFixTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/MappingFixTest.java @@ -58,7 +58,7 @@ public class MappingFixTest { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/MappingPopingTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/MappingPopingTest.java index 6d80a266d5e..13fcc4f09e3 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/MappingPopingTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/MappingPopingTest.java @@ -53,7 +53,7 @@ public class MappingPopingTest { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NegativeArrayTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NegativeArrayTest.java index 13e676401ea..891e9303f3f 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NegativeArrayTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NegativeArrayTest.java @@ -55,7 +55,7 @@ public class NegativeArrayTest { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc068.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc068.java index 527dfcfdd9f..8a2c8059221 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc068.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc068.java @@ -58,7 +58,7 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc076.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc076.java index 3e55337e60c..5348521896c 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc076.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc076.java @@ -57,7 +57,7 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc080.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc080.java index 39820c4f24c..0fab29bcb22 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc080.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc080.java @@ -57,7 +57,7 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc0811.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc0811.java index 375323c0d66..4b2c475566d 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc0811.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc0811.java @@ -56,7 +56,7 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc086.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc086.java index 30544ef8e64..6947cfbe03a 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc086.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc086.java @@ -58,7 +58,7 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolidity062.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolidity062.java index addf73f5112..0212ac308f7 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolidity062.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolidity062.java @@ -60,7 +60,7 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/Opcode.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/Opcode.java index 65515d6db51..95292006f7c 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/Opcode.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/Opcode.java @@ -58,7 +58,7 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/OverridePrivateFunction.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/OverridePrivateFunction.java index 14473535bb8..ec42f439078 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/OverridePrivateFunction.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/OverridePrivateFunction.java @@ -53,7 +53,7 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/OverrideTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/OverrideTest001.java index 8219070fd5c..298311113e8 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/OverrideTest001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/OverrideTest001.java @@ -53,7 +53,7 @@ public class OverrideTest001 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/PayableTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/PayableTest.java index 65785e99283..d343542d350 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/PayableTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/PayableTest.java @@ -53,7 +53,7 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/SelectorTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/SelectorTest.java index d969f7a707e..ed322d8970c 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/SelectorTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/SelectorTest.java @@ -49,7 +49,7 @@ public class SelectorTest { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/SlotAndOffsetNewGrammer.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/SlotAndOffsetNewGrammer.java index b38ec456fca..94ef107b365 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/SlotAndOffsetNewGrammer.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/SlotAndOffsetNewGrammer.java @@ -51,7 +51,7 @@ public class SlotAndOffsetNewGrammer { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/StringSplitTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/StringSplitTest.java index 765fa4c3c99..0938f4d165e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/StringSplitTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/StringSplitTest.java @@ -49,7 +49,7 @@ public class StringSplitTest { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/TvmVote.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/TvmVote.java index 9d450b0392f..b6d80521c87 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/TvmVote.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/TvmVote.java @@ -64,7 +64,7 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/VirtualTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/VirtualTest001.java index c23787ffc5a..6657c66035e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/VirtualTest001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/VirtualTest001.java @@ -52,7 +52,7 @@ public class VirtualTest001 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/assemblyTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/assemblyTest.java index c462d208263..601c23ecd7c 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/assemblyTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/assemblyTest.java @@ -48,7 +48,7 @@ public class assemblyTest { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/calldataTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/calldataTest.java index d11e2338ddc..dc0d0359f9f 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/calldataTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/calldataTest.java @@ -54,7 +54,7 @@ public class calldataTest { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/constructorDefaultsTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/constructorDefaultsTest.java index 093e4a38324..7c6a906b5ff 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/constructorDefaultsTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/constructorDefaultsTest.java @@ -48,7 +48,7 @@ public class constructorDefaultsTest { public void beforeClass() { PublicMethed.printAddress(dev001Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/enumAndStructTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/enumAndStructTest.java index 4230379af5a..ddffd357881 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/enumAndStructTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/enumAndStructTest.java @@ -51,7 +51,7 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); String filePath = "src/test/resources/soliditycode/enumAndStruct.sol"; diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/fallbackOldVersion.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/fallbackOldVersion.java index bfa8ebf1561..aa5839b9b86 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/fallbackOldVersion.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/fallbackOldVersion.java @@ -61,16 +61,16 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/fallbackReceive.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/fallbackReceive.java index 63bd60a0d1c..517d9f1aa18 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/fallbackReceive.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/fallbackReceive.java @@ -69,16 +69,16 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/mappingGetterTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/mappingGetterTest.java index c1bb682a801..07e4eefa4c9 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/mappingGetterTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/mappingGetterTest.java @@ -54,7 +54,7 @@ public class mappingGetterTest { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/stateVariableShadowing.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/stateVariableShadowing.java index 82ff090f2e2..a5b78970469 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/stateVariableShadowing.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/stateVariableShadowing.java @@ -63,16 +63,16 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); PublicMethed.waitProduceNextBlock(blockingStubFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/typeNameTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/typeNameTest.java index 57aca964fad..4d3b3162448 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/typeNameTest.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/typeNameTest.java @@ -55,7 +55,7 @@ public class typeNameTest { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand001.java index 11ebe1e45ea..5c917469f58 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand001.java @@ -59,16 +59,16 @@ public class ShiftCommand001 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand002.java index 03e15dce8ce..51ba064d336 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand002.java @@ -58,12 +58,12 @@ public class ShiftCommand002 { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode).usePlaintext(true).build(); + channelSolidity = ManagedChannelBuilder.forTarget(soliditynode).usePlaintext().build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand003.java index 66da905e03e..b974a52c3ce 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand003.java @@ -61,16 +61,16 @@ public class ShiftCommand003 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand004.java index b382ae75a56..9c5f7148b67 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand004.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand004.java @@ -61,16 +61,16 @@ public class ShiftCommand004 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand005.java index 8030a54490f..880b435e321 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand005.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand005.java @@ -61,16 +61,16 @@ public class ShiftCommand005 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand006.java index 1991fc5a52f..beece0ef5d6 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand006.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand006.java @@ -61,16 +61,16 @@ public class ShiftCommand006 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/ContractTestSendCoin001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/ContractTestSendCoin001.java index a0b1f62289f..ede5fa69460 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/ContractTestSendCoin001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/ContractTestSendCoin001.java @@ -74,7 +74,7 @@ public class ContractTestSendCoin001 { @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.printAddress(dev001Key); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TestResourceReceiver.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TestResourceReceiver.java index 518e49aad24..4be2a319dc4 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TestResourceReceiver.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TestResourceReceiver.java @@ -61,16 +61,16 @@ public class TestResourceReceiver { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed001.java index cd62ed8edb6..e82fb89464a 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed001.java @@ -66,16 +66,16 @@ public class TransferFailed001 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed002.java index f3691a62b15..599e4b4c835 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed002.java @@ -61,12 +61,12 @@ public class TransferFailed002 { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode).usePlaintext(true).build(); + channelSolidity = ManagedChannelBuilder.forTarget(soliditynode).usePlaintext().build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed003.java index 5aa9255e54a..4f4194e0b3e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed003.java @@ -71,16 +71,16 @@ public class TransferFailed003 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed004.java index 9c9fea1af32..cd8cea864e6 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed004.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed004.java @@ -80,16 +80,16 @@ public class TransferFailed004 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed005.java index 5971122a9c8..63c589482bb 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed005.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed005.java @@ -56,9 +56,9 @@ public class TransferFailed005 { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(accountExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); { diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed006.java index c75f2b312af..1dbcf672b96 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed006.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed006.java @@ -55,11 +55,11 @@ public class TransferFailed006 { public void beforeClass() { PublicMethed.printAddress(accountExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed007.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed007.java index 886bc8683ee..652922245c9 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed007.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed007.java @@ -54,11 +54,11 @@ public class TransferFailed007 { public void beforeClass() { PublicMethed.printAddress(accountExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed008.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed008.java index 1d118bedd8b..02446c6f04b 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed008.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed008.java @@ -76,16 +76,16 @@ public class TransferFailed008 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant001.java index 38e2a13e64d..7b2a9da9e35 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant001.java @@ -64,16 +64,16 @@ public class TriggerConstant001 { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode).usePlaintext(true).build(); + channelSolidity = ManagedChannelBuilder.forTarget(soliditynode).usePlaintext().build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelRealSolidity = - ManagedChannelBuilder.forTarget(realSoliditynode).usePlaintext(true).build(); + ManagedChannelBuilder.forTarget(realSoliditynode).usePlaintext().build(); blockingStubRealSolidity = WalletSolidityGrpc.newBlockingStub(channelRealSolidity); { diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant002.java index cbfbef42dbe..fdd17a35ccf 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant002.java @@ -61,16 +61,16 @@ public class TriggerConstant002 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant003.java index e83946ff234..bf8fc22f827 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant003.java @@ -61,16 +61,16 @@ public class TriggerConstant003 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant004.java index 6caa243b2c0..53ac6dcf445 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant004.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant004.java @@ -61,16 +61,16 @@ public class TriggerConstant004 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant005.java index 82c1f52102d..677cc740345 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant005.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant005.java @@ -60,12 +60,12 @@ public class TriggerConstant005 { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode).usePlaintext(true).build(); + channelSolidity = ManagedChannelBuilder.forTarget(soliditynode).usePlaintext().build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant006.java index 38fa2431758..208be0ee96d 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant006.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant006.java @@ -61,16 +61,16 @@ public class TriggerConstant006 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant007.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant007.java index b2d4e06f49c..b91bdb8ec8b 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant007.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant007.java @@ -61,16 +61,16 @@ public class TriggerConstant007 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant008.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant008.java index 252924f21fd..908997a168f 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant008.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant008.java @@ -61,16 +61,16 @@ public class TriggerConstant008 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant009.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant009.java index 979e5d18ec7..a1a4bc82863 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant009.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant009.java @@ -59,16 +59,16 @@ public class TriggerConstant009 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant010.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant010.java index 9e945289276..2d461689d23 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant010.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant010.java @@ -59,16 +59,16 @@ public class TriggerConstant010 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant011.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant011.java index 23909e8bbf4..d54d607d404 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant011.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant011.java @@ -60,16 +60,16 @@ public class TriggerConstant011 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant012.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant012.java index 96a6e807ef2..978ab515113 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant012.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant012.java @@ -60,16 +60,16 @@ public class TriggerConstant012 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant013.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant013.java index fd4e6144d80..187623f508b 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant013.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant013.java @@ -74,24 +74,24 @@ public class TriggerConstant013 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelRealSolidity = ManagedChannelBuilder.forTarget(realSoliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubRealSolidity = WalletSolidityGrpc.newBlockingStub(channelRealSolidity); channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant014.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant014.java index 3e27bc60807..90ae8ecd158 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant014.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant014.java @@ -68,14 +68,14 @@ public class TriggerConstant014 { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode).usePlaintext(true).build(); + channelSolidity = ManagedChannelBuilder.forTarget(soliditynode).usePlaintext().build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - channelRealSolidity = ManagedChannelBuilder.forTarget(realSoliditynode).usePlaintext(true) + channelRealSolidity = ManagedChannelBuilder.forTarget(realSoliditynode).usePlaintext() .build(); blockingStubRealSolidity = WalletSolidityGrpc.newBlockingStub(channelRealSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant015.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant015.java index 5444b9408ac..fa1c5715f45 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant015.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant015.java @@ -64,16 +64,16 @@ public class TriggerConstant015 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant016.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant016.java index 33fb1210db6..77181e1af98 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant016.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant016.java @@ -63,16 +63,16 @@ public class TriggerConstant016 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant017.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant017.java index 8928e729b87..6e60d9280f2 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant017.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant017.java @@ -63,16 +63,16 @@ public class TriggerConstant017 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant018.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant018.java index 614a0ffb4fb..5cd429fccca 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant018.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant018.java @@ -61,16 +61,16 @@ public class TriggerConstant018 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant019.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant019.java index 05bdeffe04f..48e0ada0559 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant019.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant019.java @@ -60,16 +60,16 @@ public class TriggerConstant019 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant020.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant020.java index 4846cc1a1e4..0d6c7fae2fe 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant020.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant020.java @@ -60,16 +60,16 @@ public class TriggerConstant020 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant021.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant021.java index a33931489e7..dd64fd02a91 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant021.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant021.java @@ -59,16 +59,16 @@ public class TriggerConstant021 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant022.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant022.java index 1a2e0fbb35d..a0296a8afda 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant022.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant022.java @@ -61,16 +61,16 @@ public class TriggerConstant022 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant023.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant023.java index 6ec25f0e2dc..35d5d014434 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant023.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant023.java @@ -61,16 +61,16 @@ public class TriggerConstant023 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant024.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant024.java index 4fc3a7470d6..7d1f63e933d 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant024.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant024.java @@ -62,16 +62,16 @@ public class TriggerConstant024 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant025.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant025.java index b2198f98698..15da8c6e904 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant025.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant025.java @@ -62,16 +62,16 @@ public class TriggerConstant025 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant026.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant026.java index 551d094b77e..89c346f920f 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant026.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant026.java @@ -63,16 +63,16 @@ public class TriggerConstant026 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant027.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant027.java index a548b370d42..54a39d526d2 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant027.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant027.java @@ -63,16 +63,16 @@ public class TriggerConstant027 { public void beforeClass() { PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tryCatch/tryCatchTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tryCatch/tryCatchTest001.java index bd3e67c2c4c..5e715cc10f6 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tryCatch/tryCatchTest001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tryCatch/tryCatchTest001.java @@ -54,7 +54,7 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tryCatch/tryCatchTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tryCatch/tryCatchTest002.java index c55ba174d4f..debe21b95d1 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tryCatch/tryCatchTest002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tryCatch/tryCatchTest002.java @@ -52,7 +52,7 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeContractTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeContractTest001.java index 5556d5d0112..3dcbc9504c8 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeContractTest001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeContractTest001.java @@ -74,7 +74,7 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); Assert.assertTrue(PublicMethed.sendcoin(testAddress001,2000_000000L, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeContractTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeContractTest002.java index bb79702f0f0..bc0d8aca23b 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeContractTest002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeContractTest002.java @@ -64,7 +64,7 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); Assert.assertTrue(PublicMethed.sendcoin(testAddress001,2000_000000L, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeSuicideTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeSuicideTest001.java index e2b14c4277e..865aea5fe57 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeSuicideTest001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeSuicideTest001.java @@ -68,7 +68,7 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); Assert.assertTrue(PublicMethed.sendcoin(testAddress001,2000_000000L, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue001.java index 207406b58ca..4de382f52af 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue001.java @@ -64,7 +64,7 @@ public class TvmAssetIssue001 { */ @BeforeClass(enabled = false) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.printAddress(dev001Key); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue002.java index 2b7e693fa91..5997bd84075 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue002.java @@ -64,7 +64,7 @@ public class TvmAssetIssue002 { */ @BeforeClass(enabled = false) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.printAddress(dev001Key); PublicMethed.printAddress(dev002Key); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue003.java index 60ca55d3666..88885f1fd15 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue003.java @@ -64,7 +64,7 @@ public class TvmAssetIssue003 { */ @BeforeClass(enabled = false) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.printAddress(dev001Key); PublicMethed.printAddress(dev002Key); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue004.java index 9bf181a4c48..43f99347ee6 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue004.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue004.java @@ -63,7 +63,7 @@ public class TvmAssetIssue004 { */ @BeforeClass(enabled = false) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.printAddress(dev001Key); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue005.java index ba61000f6a6..4eb87691228 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue005.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue005.java @@ -68,7 +68,7 @@ public class TvmAssetIssue005 { */ @BeforeClass(enabled = false) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.printAddress(dev001Key); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/ContractRewardTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/ContractRewardTest001.java index 2dbc0b54cf9..ee08016ebb0 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/ContractRewardTest001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/ContractRewardTest001.java @@ -50,7 +50,7 @@ public void beforeSuite() { Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/IsSrCandidateTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/IsSrCandidateTest001.java index c1a3d68992e..39837c2fe70 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/IsSrCandidateTest001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/IsSrCandidateTest001.java @@ -50,7 +50,7 @@ public void beforeSuite() { @BeforeClass(enabled = false) public void beforeClass() { PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StackSuicideTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StackSuicideTest001.java index f1a43ad8e49..5758439a9da 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StackSuicideTest001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StackSuicideTest001.java @@ -57,7 +57,7 @@ public void beforeSuite() { @BeforeClass(enabled = false) public void beforeClass() { PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest002.java index 2856b2d436c..3aa1f7c9793 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest002.java @@ -52,7 +52,7 @@ public void beforeSuite() { @BeforeClass(enabled = false) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); String filePath = "src/test/resources/soliditycode/stackSuicide001.sol"; diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest003.java index 6393aece552..212e686b0ec 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest003.java @@ -54,7 +54,7 @@ public void beforeSuite() { @BeforeClass(enabled = false) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.sendcoin(testAddress001,10000000,testFoundationAddress, testFoundationKey,blockingStubFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest004.java index 69bcbcff619..93d69f3b17b 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest004.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest004.java @@ -70,7 +70,7 @@ public void beforeSuite() { public void beforeClass() { System.out.println(testKey001); PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest005.java index b324672d6ab..3dc87def0e5 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest005.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest005.java @@ -65,7 +65,7 @@ public void beforeSuite() { public void beforeClass() { System.out.println(testKey001); PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeTest001.java index 4b9102fc901..b51208bd8e9 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeTest001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeTest001.java @@ -61,7 +61,7 @@ public void beforeSuite() { @BeforeClass(enabled = false) public void beforeClass() { PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/UnStakeTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/UnStakeTest001.java index be418169c53..c738b9ad3d7 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/UnStakeTest001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/UnStakeTest001.java @@ -65,7 +65,7 @@ public void beforeSuite() { @BeforeClass(enabled = false) public void beforeClass() { PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign001.java index 32d378c4d83..831679cb4de 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign001.java @@ -80,7 +80,7 @@ public class TestValidatemultisign001 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign002.java index 8898e687459..c4350af2c07 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign002.java @@ -86,7 +86,7 @@ public class TestValidatemultisign002 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign003.java index 840c86c0102..a1adf048b8a 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign003.java @@ -72,7 +72,7 @@ public class TestValidatemultisign003 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/VerifyBurnProof001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/VerifyBurnProof001.java index 548ebf5330b..3acb6f21b44 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/VerifyBurnProof001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/VerifyBurnProof001.java @@ -49,7 +49,7 @@ public class VerifyBurnProof001 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/VerifyMintProof001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/VerifyMintProof001.java index a0c0df953e2..2ef5bb671db 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/VerifyMintProof001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/VerifyMintProof001.java @@ -49,7 +49,7 @@ public class VerifyMintProof001 { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/pedersenHash001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/pedersenHash001.java index 9ea86709e2e..62f53d03455 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/pedersenHash001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/pedersenHash001.java @@ -58,9 +58,9 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); txid = PublicMethed .sendcoinGetTransactionId(contractExcAddress, 10000000000L, testNetAccountAddress, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/pedersenHash002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/pedersenHash002.java index 26f29e5f69d..3d82e7a05b8 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/pedersenHash002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/pedersenHash002.java @@ -94,7 +94,7 @@ public void deployShieldTrc20DependContract() { Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); PublicMethed.printAddress(contractExcKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/verifyTransferProof001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/verifyTransferProof001.java index 82c01e7316a..ac93beef5a1 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/verifyTransferProof001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/verifyTransferProof001.java @@ -54,9 +54,9 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); txid = PublicMethed .sendcoinGetTransactionId(contractExcAddress, 10000000000L, testNetAccountAddress, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken001.java index 4e5a7908092..3e5bd578f5d 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken001.java @@ -66,7 +66,7 @@ public class WalletTestZenToken001 { public void beforeSuite() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); @@ -100,7 +100,7 @@ public void beforeClass() { PublicMethed.printAddress(foundationZenTokenKey); PublicMethed.printAddress(zenTokenOwnerKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken002.java index 6b761422c5b..4e3851fbb59 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken002.java @@ -91,22 +91,22 @@ public class WalletTestZenToken002 { public void beforeClass() { PublicMethed.printAddress(foundationZenTokenKey); PublicMethed.printAddress(zenTokenOwnerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true) + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelSolidity1 = ManagedChannelBuilder.forTarget(soliditynode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity1 = WalletSolidityGrpc.newBlockingStub(channelSolidity1); channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken003.java index 4480df80b5d..1cabccaa80d 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken003.java @@ -77,7 +77,7 @@ public void beforeClass() { PublicMethed.printAddress(foundationZenTokenKey); PublicMethed.printAddress(zenTokenOwnerKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken004.java index 6284508261e..51cea166ab1 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken004.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken004.java @@ -71,7 +71,7 @@ public void beforeClass() { PublicMethed.printAddress(foundationZenTokenKey); PublicMethed.printAddress(zenTokenOwnerKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); Args.setFullNodeAllowShieldedTransaction(true); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken005.java index 23398284924..802d49e9485 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken005.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken005.java @@ -67,7 +67,7 @@ public void beforeClass() { PublicMethed.printAddress(foundationZenTokenKey); PublicMethed.printAddress(zenTokenOwnerKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken006.java index 7b01959b2cb..774adda8ed6 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken006.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken006.java @@ -69,7 +69,7 @@ public void beforeClass() { PublicMethed.printAddress(foundationZenTokenKey); PublicMethed.printAddress(zenTokenOwnerKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken007.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken007.java index f43924eedcc..b8271b859b5 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken007.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken007.java @@ -128,17 +128,17 @@ public void beforeClass() { PublicMethed.printAddress(zenTokenOwnerKey2); PublicMethed.printAddress(zenTokenOwnerKey3); PublicMethed.printAddress(zenTokenOwnerKey4); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true) + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelSolidity1 = ManagedChannelBuilder.forTarget(soliditynode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity1 = WalletSolidityGrpc.newBlockingStub(channelSolidity1); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken008.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken008.java index 59abb2ec9f4..fc5cc247661 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken008.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken008.java @@ -82,17 +82,17 @@ public class WalletTestZenToken008 { public void beforeClass() { PublicMethed.printAddress(foundationZenTokenKey); PublicMethed.printAddress(zenTokenOwnerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true) + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelSolidity1 = ManagedChannelBuilder.forTarget(soliditynode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity1 = WalletSolidityGrpc.newBlockingStub(channelSolidity1); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken009.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken009.java index af1d45fb2e4..8ad9525c200 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken009.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken009.java @@ -89,7 +89,7 @@ public void beforeClass() { PublicMethed.printAddress(foundationZenTokenKey); PublicMethed.printAddress(zenTokenOwnerKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); long needCoin = updateAccountPermissionFee * 1 + multiSignFee * 3; diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken010.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken010.java index d1c162f770c..d629a43e6b6 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken010.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken010.java @@ -87,17 +87,17 @@ public class WalletTestZenToken010 { public void beforeClass() { PublicMethed.printAddress(foundationZenTokenKey); PublicMethed.printAddress(zenTokenOwnerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true) + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelSolidity1 = ManagedChannelBuilder.forTarget(soliditynode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity1 = WalletSolidityGrpc.newBlockingStub(channelSolidity1); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken011.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken011.java index 9287e92c0b7..591ad4d603e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken011.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken011.java @@ -88,17 +88,17 @@ public class WalletTestZenToken011 { public void beforeClass() { PublicMethed.printAddress(foundationZenTokenKey); PublicMethed.printAddress(zenTokenOwnerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true) + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelSolidity1 = ManagedChannelBuilder.forTarget(soliditynode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity1 = WalletSolidityGrpc.newBlockingStub(channelSolidity1); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token001.java index ee61c9996c9..2bc145c23c6 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token001.java @@ -30,7 +30,7 @@ public class ShieldTrc20Token001 extends ZenTrc20Base { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token002.java index f118553d496..b5c03c164ed 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token002.java @@ -42,12 +42,12 @@ public class ShieldTrc20Token002 extends ZenTrc20Base { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); publicFromAmount = getRandomAmount(); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token003.java index 81ee7e32b8f..6eb8ff23790 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token003.java @@ -44,12 +44,12 @@ public class ShieldTrc20Token003 extends ZenTrc20Base { @BeforeClass(enabled = true) public void beforeClass() throws Exception { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); publicFromAmount = getRandomAmount(); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token004.java index bad605d1cc9..cfbe9e562df 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token004.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token004.java @@ -55,12 +55,12 @@ public class ShieldTrc20Token004 extends ZenTrc20Base { @BeforeClass(enabled = true) public void beforeClass() throws Exception { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); publicFromAmount = getRandomAmount(); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token005.java index dcd9feeb8ee..fb5768ca316 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token005.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token005.java @@ -55,12 +55,12 @@ public class ShieldTrc20Token005 extends ZenTrc20Base { @BeforeClass(enabled = true) public void beforeClass() throws Exception { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); publicFromAmount = getRandomAmount(); diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token006.java index 079e46de22d..98137f506c3 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token006.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token006.java @@ -53,17 +53,17 @@ public class ShieldTrc20Token006 extends ZenTrc20Base { @BeforeClass(enabled = true) public void beforeClass() throws Exception { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/AttackSendcoin.java b/framework/src/test/java/stest/tron/wallet/fulltest/AttackSendcoin.java index b0343368d1b..7a4fe984bc4 100644 --- a/framework/src/test/java/stest/tron/wallet/fulltest/AttackSendcoin.java +++ b/framework/src/test/java/stest/tron/wallet/fulltest/AttackSendcoin.java @@ -156,7 +156,7 @@ public static Boolean freezeBalance(byte[] addRess, long freezeBalance, long fre @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); final Account fromInfo = PublicMethed.queryAccount(testKey002, blockingStubFull); @@ -189,7 +189,7 @@ public void freezeAndSendcoin() throws InterruptedException { fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") .get(randNum); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/ContinueVote.java b/framework/src/test/java/stest/tron/wallet/fulltest/ContinueVote.java index 5d60cee81f3..64d2b3a68eb 100644 --- a/framework/src/test/java/stest/tron/wallet/fulltest/ContinueVote.java +++ b/framework/src/test/java/stest/tron/wallet/fulltest/ContinueVote.java @@ -77,12 +77,12 @@ public void beforeClass() { WalletClient.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); logger.info("Pre fix byte ===== " + WalletClient.getAddressPreFixByte()); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext(true) + .usePlaintext() .build(); searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/Creatasset.java b/framework/src/test/java/stest/tron/wallet/fulltest/Creatasset.java index b9a2b68ea9f..a6fe9beee3d 100644 --- a/framework/src/test/java/stest/tron/wallet/fulltest/Creatasset.java +++ b/framework/src/test/java/stest/tron/wallet/fulltest/Creatasset.java @@ -70,7 +70,7 @@ public void beforeClass() { logger.info(testKeyForAssetIssue016); logger.info(transferAssetCreateKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } @@ -104,7 +104,7 @@ public void createAssetissue() throws InterruptedException { fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") .get(randNum); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/FreezeAndSendcoin.java b/framework/src/test/java/stest/tron/wallet/fulltest/FreezeAndSendcoin.java index c9c43d1e02c..203127fb3b4 100644 --- a/framework/src/test/java/stest/tron/wallet/fulltest/FreezeAndSendcoin.java +++ b/framework/src/test/java/stest/tron/wallet/fulltest/FreezeAndSendcoin.java @@ -135,7 +135,7 @@ public void beforeClass() { logger.info(testKeyForFreeze); logger.info(transferAssetCreateKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } @@ -164,7 +164,7 @@ public void freezeAndSendcoin() throws InterruptedException { fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") .get(randNum); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/Fuzzytest.java b/framework/src/test/java/stest/tron/wallet/fulltest/Fuzzytest.java index 0a4ed47dbb1..3179f5973ae 100644 --- a/framework/src/test/java/stest/tron/wallet/fulltest/Fuzzytest.java +++ b/framework/src/test/java/stest/tron/wallet/fulltest/Fuzzytest.java @@ -148,12 +148,12 @@ public static Protocol.Transaction signTransaction(ECKey ecKey, @BeforeClass(enabled = false) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); blockingStubExtension = WalletExtensionGrpc.newBlockingStub(channelSolidity); @@ -191,7 +191,7 @@ public void tooManyChannelFull() { ManagedChannel channelFull = null; WalletGrpc.WalletBlockingStub blockingStubFull = null; channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); GrpcAPI.NodeList nodeList = blockingStubFull diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/ParticipateAssetIssue.java b/framework/src/test/java/stest/tron/wallet/fulltest/ParticipateAssetIssue.java index e42128f5cae..53642957ea7 100644 --- a/framework/src/test/java/stest/tron/wallet/fulltest/ParticipateAssetIssue.java +++ b/framework/src/test/java/stest/tron/wallet/fulltest/ParticipateAssetIssue.java @@ -174,7 +174,7 @@ public void beforeClass() { logger.info(testKeyForCreate); logger.info(testKeyForParticipate); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); //Send coin to 2 account. @@ -228,7 +228,7 @@ public void testParticipateAssetIssue() throws InterruptedException { fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") .get(randNum); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/SuperWitnessAllowance.java b/framework/src/test/java/stest/tron/wallet/fulltest/SuperWitnessAllowance.java index 34b753c0229..7bcf1458376 100644 --- a/framework/src/test/java/stest/tron/wallet/fulltest/SuperWitnessAllowance.java +++ b/framework/src/test/java/stest/tron/wallet/fulltest/SuperWitnessAllowance.java @@ -87,7 +87,7 @@ public void beforeClass() { logger.info(Base58.encode58Check(PublicMethed.getFinalAddress(lowBalTest))); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/TransferAssetIssue.java b/framework/src/test/java/stest/tron/wallet/fulltest/TransferAssetIssue.java index a9b0a6fe02d..94a79770877 100644 --- a/framework/src/test/java/stest/tron/wallet/fulltest/TransferAssetIssue.java +++ b/framework/src/test/java/stest/tron/wallet/fulltest/TransferAssetIssue.java @@ -181,7 +181,7 @@ public void beforeClass() { logger.info(testKeyForCreate); logger.info(testKeyForParticipate); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); //Send coin to 2 account. @@ -235,7 +235,7 @@ public void transferAssetIssue() throws InterruptedException { fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") .get(randNum); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/TronDice.java b/framework/src/test/java/stest/tron/wallet/fulltest/TronDice.java index e2ad7c3cf61..2a30633de27 100644 --- a/framework/src/test/java/stest/tron/wallet/fulltest/TronDice.java +++ b/framework/src/test/java/stest/tron/wallet/fulltest/TronDice.java @@ -50,7 +50,7 @@ public class TronDice { public void beforeClass() { PublicMethed.printAddress(contract008Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); PublicMethed.printAddress(testKey002); diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/TvmContract.java b/framework/src/test/java/stest/tron/wallet/fulltest/TvmContract.java index 295376ed8e8..40025f12f85 100644 --- a/framework/src/test/java/stest/tron/wallet/fulltest/TvmContract.java +++ b/framework/src/test/java/stest/tron/wallet/fulltest/TvmContract.java @@ -45,7 +45,7 @@ public class TvmContract { public void beforeClass() { PublicMethed.printAddress(contract008Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); Assert.assertTrue(PublicMethed.sendcoin(contract008Address, 500000000L, fromAddress, diff --git a/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign001.java b/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign001.java index 139ca70fab5..99c641e9f72 100644 --- a/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign001.java +++ b/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign001.java @@ -70,7 +70,7 @@ public class WalletTestMutiSign001 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign003.java b/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign003.java index 7774d336613..d8e5f66cd13 100644 --- a/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign003.java +++ b/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign003.java @@ -67,7 +67,7 @@ public class WalletTestMutiSign003 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign004.java b/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign004.java index cbec5d977cb..721622bf303 100644 --- a/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign004.java +++ b/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign004.java @@ -75,10 +75,10 @@ public class WalletTestMutiSign004 { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); diff --git a/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign005.java b/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign005.java index 3271a36428c..4ccbe67b8d8 100644 --- a/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign005.java +++ b/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign005.java @@ -66,12 +66,12 @@ public class WalletTestMutiSign005 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateAccount2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateAccount2Test.java index fe735b21119..162b13c820f 100644 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateAccount2Test.java +++ b/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateAccount2Test.java @@ -56,7 +56,7 @@ public class CreateAccount2Test { public void beforeClass() { logger.info(account007Key); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); Assert.assertTrue(PublicMethed.sendcoin(account007Address, 10000000, diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateAssetIssue2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateAssetIssue2Test.java index a33ab4abe7b..c885377dc5c 100644 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateAssetIssue2Test.java +++ b/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateAssetIssue2Test.java @@ -74,7 +74,7 @@ public static String loadPubKey() { public void beforeClass() { logger.info(ByteArray.toHexString(ecKey.getPrivKeyBytes())); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateTransaction2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateTransaction2Test.java index bc3622f01ba..19d5cc2111a 100644 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateTransaction2Test.java +++ b/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateTransaction2Test.java @@ -76,12 +76,12 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext(true) + .usePlaintext() .build(); searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateaAndUpdateWitness2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateaAndUpdateWitness2Test.java index 19bba10b51f..fd8454599b9 100644 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateaAndUpdateWitness2Test.java +++ b/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateaAndUpdateWitness2Test.java @@ -79,7 +79,7 @@ public void beforeClass() { logger.info(Base58.encode58Check(PublicMethed.getFinalAddress(lowBalTest))); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/FreezeBalance2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/FreezeBalance2Test.java index 1253cdc8e0d..0618fe08d3d 100644 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/FreezeBalance2Test.java +++ b/framework/src/test/java/stest/tron/wallet/newaddinterface2/FreezeBalance2Test.java @@ -66,12 +66,12 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext(true) + .usePlaintext() .build(); searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByLatestNum2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByLatestNum2Test.java index 3667882e0c9..fbd8a29c3db 100644 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByLatestNum2Test.java +++ b/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByLatestNum2Test.java @@ -46,7 +46,7 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByLimitNext2.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByLimitNext2.java index 6ff1a358c89..3fd4fb3fa95 100644 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByLimitNext2.java +++ b/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByLimitNext2.java @@ -46,7 +46,7 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByNum2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByNum2Test.java index e71b2c041e1..01408f655b9 100644 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByNum2Test.java +++ b/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByNum2Test.java @@ -50,12 +50,12 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetNowBlock2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetNowBlock2Test.java index e1e66fc1ae2..b20b8331d4d 100644 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetNowBlock2Test.java +++ b/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetNowBlock2Test.java @@ -52,12 +52,12 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetTransactionsFromThis2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetTransactionsFromThis2Test.java index b3774396a1a..88fa0f01960 100644 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetTransactionsFromThis2Test.java +++ b/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetTransactionsFromThis2Test.java @@ -68,12 +68,12 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); blockingStubExtension = WalletExtensionGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetTransactionsToThis2.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetTransactionsToThis2.java index 399ca531578..29f53fb070e 100644 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetTransactionsToThis2.java +++ b/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetTransactionsToThis2.java @@ -76,12 +76,12 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); blockingStubExtension = WalletExtensionGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/ParticipateAssetIssue2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/ParticipateAssetIssue2Test.java index dea87ebc8ef..765c70ea7ee 100644 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/ParticipateAssetIssue2Test.java +++ b/framework/src/test/java/stest/tron/wallet/newaddinterface2/ParticipateAssetIssue2Test.java @@ -75,7 +75,7 @@ public static String loadPubKey() { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/TransferAsset2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/TransferAsset2Test.java index 0e1b80e1557..533c05dd002 100644 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/TransferAsset2Test.java +++ b/framework/src/test/java/stest/tron/wallet/newaddinterface2/TransferAsset2Test.java @@ -72,7 +72,7 @@ public static String loadPubKey() { public void beforeClass() { logger.info(ByteArray.toHexString(ecKey.getPrivKeyBytes())); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/UnfreezeAsset2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/UnfreezeAsset2Test.java index 2be9b42c6a1..7bc23cef344 100644 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/UnfreezeAsset2Test.java +++ b/framework/src/test/java/stest/tron/wallet/newaddinterface2/UnfreezeAsset2Test.java @@ -96,7 +96,7 @@ public static String loadPubKey() { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/UpdateAccount2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/UpdateAccount2Test.java index cae5235ebd0..82b395c24f2 100644 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/UpdateAccount2Test.java +++ b/framework/src/test/java/stest/tron/wallet/newaddinterface2/UpdateAccount2Test.java @@ -92,7 +92,7 @@ public static String loadPubKey() { public void beforeClass() { PublicMethed.printAddress(lowBalTest); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/UpdateAsset2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/UpdateAsset2Test.java index d394c879416..5725ba6e625 100644 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/UpdateAsset2Test.java +++ b/framework/src/test/java/stest/tron/wallet/newaddinterface2/UpdateAsset2Test.java @@ -80,7 +80,7 @@ public static String loadPubKey() { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/VoteWitnessAccount2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/VoteWitnessAccount2Test.java index 4219adfeb37..725b4055782 100644 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/VoteWitnessAccount2Test.java +++ b/framework/src/test/java/stest/tron/wallet/newaddinterface2/VoteWitnessAccount2Test.java @@ -70,12 +70,12 @@ public void beforeClass() { WalletClient.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); logger.info("Pre fix byte ===== " + WalletClient.getAddressPreFixByte()); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext(true) + .usePlaintext() .build(); searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/WithdrawBalance2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/WithdrawBalance2Test.java index 6c31c38c336..4442fd448fe 100644 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/WithdrawBalance2Test.java +++ b/framework/src/test/java/stest/tron/wallet/newaddinterface2/WithdrawBalance2Test.java @@ -67,12 +67,12 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext(true) + .usePlaintext() .build(); searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/ContractEvent001.java b/framework/src/test/java/stest/tron/wallet/onlinestress/ContractEvent001.java index 837e4c72aa8..9ff98b87be2 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/ContractEvent001.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/ContractEvent001.java @@ -87,9 +87,9 @@ public class ContractEvent001 extends JsonRpcBase { /** constructor. */ @BeforeClass(enabled = true) public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build(); + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext(true).build(); + channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/CycleMultiSign.java b/framework/src/test/java/stest/tron/wallet/onlinestress/CycleMultiSign.java index 6da00b39793..9f0b2983f68 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/CycleMultiSign.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/CycleMultiSign.java @@ -76,17 +76,17 @@ public class CycleMultiSign { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext(true) + .usePlaintext() .build(); searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/DelayTransactionStress.java b/framework/src/test/java/stest/tron/wallet/onlinestress/DelayTransactionStress.java index 967067b46a6..9f34dc8c249 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/DelayTransactionStress.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/DelayTransactionStress.java @@ -67,7 +67,7 @@ public class DelayTransactionStress { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/ExtCodeHashStressTest.java b/framework/src/test/java/stest/tron/wallet/onlinestress/ExtCodeHashStressTest.java index 8c4dab36742..ee29bda3644 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/ExtCodeHashStressTest.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/ExtCodeHashStressTest.java @@ -76,7 +76,7 @@ public class ExtCodeHashStressTest { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/MainNetTransferSendOrAsset.java b/framework/src/test/java/stest/tron/wallet/onlinestress/MainNetTransferSendOrAsset.java index b0f90198084..912abb2fe08 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/MainNetTransferSendOrAsset.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/MainNetTransferSendOrAsset.java @@ -67,7 +67,7 @@ public class MainNetTransferSendOrAsset { @BeforeClass(enabled = false) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); Account fromAccount = PublicMethed.queryAccount(testKey001, blockingStubFull); diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/MainNetVoteOrFreezeOrCreate.java b/framework/src/test/java/stest/tron/wallet/onlinestress/MainNetVoteOrFreezeOrCreate.java index 93abe8957b9..5d8e86e707d 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/MainNetVoteOrFreezeOrCreate.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/MainNetVoteOrFreezeOrCreate.java @@ -140,7 +140,7 @@ public static Boolean freezeBalance(byte[] addRess, long freezeBalance, long fre @BeforeClass(enabled = false) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); startTime = System.currentTimeMillis(); diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/MultiValiSignPerformanceTest.java b/framework/src/test/java/stest/tron/wallet/onlinestress/MultiValiSignPerformanceTest.java index 58c07f830f8..1d983e7d8ab 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/MultiValiSignPerformanceTest.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/MultiValiSignPerformanceTest.java @@ -73,11 +73,11 @@ public void beforeSuite() { public void beforeClass() { PublicMethed.printAddress(contractDepKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/MutiSignStress.java b/framework/src/test/java/stest/tron/wallet/onlinestress/MutiSignStress.java index 31516dc18d8..27ae66e5142 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/MutiSignStress.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/MutiSignStress.java @@ -58,7 +58,7 @@ public class MutiSignStress { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/ScanBlockTools.java b/framework/src/test/java/stest/tron/wallet/onlinestress/ScanBlockTools.java index a04dbc86262..73375d897b0 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/ScanBlockTools.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/ScanBlockTools.java @@ -101,10 +101,10 @@ public void beforeClass() { PublicMethed.printAddress(testKey002); PublicMethed.printAddress(testKey003); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); @@ -474,7 +474,7 @@ public void test06ScanMainNetMostActiveAccounts() throws Exception { ManagedChannel channelFull = null; WalletGrpc.WalletBlockingStub blockingStubFull = null; channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); NumberMessage.Builder builder = NumberMessage.newBuilder(); @@ -577,7 +577,7 @@ public void test07ScanAndCalculateTotalValueOrCallValue() throws Exception { ManagedChannel channelFull = null; WalletGrpc.WalletBlockingStub blockingStubFull = null; channelFull = ManagedChannelBuilder.forTarget("47.252.19.181:50051") - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/ShieldTrc10Stress.java b/framework/src/test/java/stest/tron/wallet/onlinestress/ShieldTrc10Stress.java index 92118d87fcc..bb89f4da195 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/ShieldTrc10Stress.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/ShieldTrc10Stress.java @@ -73,7 +73,7 @@ public void beforeClass() { PublicMethed.printAddress(foundationZenTokenKey); PublicMethed.printAddress(zenTokenOwnerKey); ManagedChannel channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); WalletGrpc.WalletBlockingStub blockingStubFull = WalletGrpc.newBlockingStub(channelFull); @@ -101,7 +101,7 @@ public void beforeClass() { @Test(enabled = true, threadPoolSize = 100, invocationCount = 100) public void test1Shield2TwoShieldTransaction() { ManagedChannel channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); WalletGrpc.WalletBlockingStub blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/ShieldTrc20Stress.java b/framework/src/test/java/stest/tron/wallet/onlinestress/ShieldTrc20Stress.java index e50f30b869a..4886502a48b 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/ShieldTrc20Stress.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/ShieldTrc20Stress.java @@ -59,11 +59,11 @@ public class ShieldTrc20Stress extends ZenTrc20Base { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); @@ -81,14 +81,14 @@ public void test01ScanAndCreateThenTrigger() throws Exception { ManagedChannel channelFull = null; WalletGrpc.WalletBlockingStub blockingStubFull = null; channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); ManagedChannel channelFull1 = null; WalletGrpc.WalletBlockingStub blockingStubFull1 = null; channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); @@ -192,14 +192,14 @@ public void test02FirstScanCreateParameterThenCreateTrigger() throws Exception { ManagedChannel channelFull = null; WalletGrpc.WalletBlockingStub blockingStubFull = null; channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); ManagedChannel channelFull1 = null; WalletGrpc.WalletBlockingStub blockingStubFull1 = null; channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); @@ -405,14 +405,14 @@ public void test03BurnStress() throws Exception { ManagedChannel channelFull = null; WalletGrpc.WalletBlockingStub blockingStubFull = null; channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); ManagedChannel channelFull1 = null; WalletGrpc.WalletBlockingStub blockingStubFull1 = null; channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/SupportTronlinkAutoTest.java b/framework/src/test/java/stest/tron/wallet/onlinestress/SupportTronlinkAutoTest.java index 4b7ede49ab8..65e17d4e8a4 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/SupportTronlinkAutoTest.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/SupportTronlinkAutoTest.java @@ -61,7 +61,7 @@ public class SupportTronlinkAutoTest { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/TestApproveProposal.java b/framework/src/test/java/stest/tron/wallet/onlinestress/TestApproveProposal.java index f4a97d2ba33..015242b1f94 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/TestApproveProposal.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/TestApproveProposal.java @@ -72,12 +72,12 @@ public class TestApproveProposal { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/TestExchangeTransaction.java b/framework/src/test/java/stest/tron/wallet/onlinestress/TestExchangeTransaction.java index db0de1d5b47..5fdfd7f3c73 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/TestExchangeTransaction.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/TestExchangeTransaction.java @@ -59,7 +59,7 @@ public class TestExchangeTransaction { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/TestMapBigLongAndNumbers.java b/framework/src/test/java/stest/tron/wallet/onlinestress/TestMapBigLongAndNumbers.java index efee959ba63..9864ff100ea 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/TestMapBigLongAndNumbers.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/TestMapBigLongAndNumbers.java @@ -63,7 +63,7 @@ public class TestMapBigLongAndNumbers { public void beforeClass() { PublicMethed.printAddress(triggerKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/TestMutiSignStress.java b/framework/src/test/java/stest/tron/wallet/onlinestress/TestMutiSignStress.java index 7f0382b2681..7995f85a993 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/TestMutiSignStress.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/TestMutiSignStress.java @@ -46,7 +46,7 @@ public class TestMutiSignStress { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/TestNetErc721Cat.java b/framework/src/test/java/stest/tron/wallet/onlinestress/TestNetErc721Cat.java index 8af17ca172f..600cbbfad9a 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/TestNetErc721Cat.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/TestNetErc721Cat.java @@ -65,7 +65,7 @@ public void beforeClass() { PublicMethed.printAddress(deployKey); PublicMethed.printAddress(triggerKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); Assert.assertTrue(PublicMethed.sendcoin(deployAddress, 50000000000L, fromAddress, diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/TestNetFomo3D.java b/framework/src/test/java/stest/tron/wallet/onlinestress/TestNetFomo3D.java index 9c84ac0bf96..b87ddd99558 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/TestNetFomo3D.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/TestNetFomo3D.java @@ -51,7 +51,7 @@ public class TestNetFomo3D { public void beforeClass() { PublicMethed.printAddress(testNetAccountKey); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); logger.info(Long.toString(PublicMethed.queryAccount(testNetAccountKey, blockingStubFull) diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/TestStorageAndCpu.java b/framework/src/test/java/stest/tron/wallet/onlinestress/TestStorageAndCpu.java index 458daa381b4..6123461efe3 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/TestStorageAndCpu.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/TestStorageAndCpu.java @@ -68,10 +68,10 @@ public void beforeClass() { PublicMethed.printAddress(testKey002); PublicMethed.printAddress(testKey003); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/TestTransferTokenInContract.java b/framework/src/test/java/stest/tron/wallet/onlinestress/TestTransferTokenInContract.java index 628b2843d8f..7a50f64f922 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/TestTransferTokenInContract.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/TestTransferTokenInContract.java @@ -65,12 +65,12 @@ private static int randomInt(int minInt, int maxInt) { public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); } diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/WalletTestZenTokenStress.java b/framework/src/test/java/stest/tron/wallet/onlinestress/WalletTestZenTokenStress.java index 68924eb6d56..b585bb91036 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/WalletTestZenTokenStress.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/WalletTestZenTokenStress.java @@ -103,17 +103,17 @@ public class WalletTestZenTokenStress { public void beforeClass() { PublicMethed.printAddress(foundationZenTokenKey); PublicMethed.printAddress(zenTokenOwnerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true) + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); channelSolidity1 = ManagedChannelBuilder.forTarget(soliditynode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity1 = WalletSolidityGrpc.newBlockingStub(channelSolidity1); diff --git a/framework/src/test/java/stest/tron/wallet/other/deployMainGateway.java b/framework/src/test/java/stest/tron/wallet/other/deployMainGateway.java index 2a81c673f23..2eb4df97095 100644 --- a/framework/src/test/java/stest/tron/wallet/other/deployMainGateway.java +++ b/framework/src/test/java/stest/tron/wallet/other/deployMainGateway.java @@ -55,7 +55,7 @@ public class deployMainGateway { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/other/deploySideGateway.java b/framework/src/test/java/stest/tron/wallet/other/deploySideGateway.java index 90b3266b149..326441d0d97 100644 --- a/framework/src/test/java/stest/tron/wallet/other/deploySideGateway.java +++ b/framework/src/test/java/stest/tron/wallet/other/deploySideGateway.java @@ -57,7 +57,7 @@ public class deploySideGateway { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer001.java b/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer001.java index e8b3d3acfe5..1ff26d3398e 100644 --- a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer001.java +++ b/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer001.java @@ -70,12 +70,12 @@ public static String loadPubKey() { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext(true) + .usePlaintext() .build(); searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer003.java b/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer003.java index 3c6435ee193..faf3ded16d7 100644 --- a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer003.java +++ b/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer003.java @@ -133,17 +133,17 @@ public static Protocol.Transaction sendcoin(byte[] to, long amount, byte[] owner public void beforeClass() { logger.info(testKeyForSendCoin); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); blockingStubExtension = WalletExtensionGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer004.java b/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer004.java index 181328d0f0f..8056f3e9941 100644 --- a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer004.java +++ b/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer004.java @@ -207,12 +207,12 @@ public void testExceptionTimeToGetGetTransactionsByTimestamp() { @BeforeClass public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true) + channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); blockingStubExtension = WalletExtensionGrpc.newBlockingStub(channelSolidity); diff --git a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer007.java b/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer007.java index 3619db66a17..09c63c85fbf 100644 --- a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer007.java +++ b/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer007.java @@ -62,22 +62,22 @@ public class WalletTestTransfer007 { @BeforeClass public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext(true) + .usePlaintext() .build(); searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); /* channelSolidityInFullnode = ManagedChannelBuilder.forTarget(solidityInFullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidityInFullnode = WalletSolidityGrpc.newBlockingStub(channelSolidityInFullnode); */ diff --git a/framework/src/test/java/stest/tron/wallet/updateCompatibility/MutisignOperationerGodicTest.java b/framework/src/test/java/stest/tron/wallet/updateCompatibility/MutisignOperationerGodicTest.java index 72ee459aae1..4909f84c4a6 100644 --- a/framework/src/test/java/stest/tron/wallet/updateCompatibility/MutisignOperationerGodicTest.java +++ b/framework/src/test/java/stest/tron/wallet/updateCompatibility/MutisignOperationerGodicTest.java @@ -98,7 +98,7 @@ public class MutisignOperationerGodicTest { @BeforeSuite public void beforeSuite() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); @@ -130,7 +130,7 @@ public void beforeSuite() { @BeforeClass(enabled = true) public void beforeClass() { channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); Assert.assertTrue(PublicMethed.sendcoin(mutisignAccountAddress, 1000_000_000_000L, fromAddress, diff --git a/framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness001.java b/framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness001.java index 322cdf9e3be..550f31235db 100644 --- a/framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness001.java +++ b/framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness001.java @@ -74,12 +74,12 @@ public void beforeClass() { WalletClient.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); logger.info("Pre fix byte ===== " + WalletClient.getAddressPreFixByte()); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext(true) + .usePlaintext() .build(); searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); } diff --git a/framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness002.java b/framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness002.java index 876f7b64b58..fd71379b2e5 100644 --- a/framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness002.java +++ b/framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness002.java @@ -63,12 +63,12 @@ public static String loadPubKey() { public void beforeClass() { WalletClient.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext(true) + .usePlaintext() .build(); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); } diff --git a/protocol/build.gradle b/protocol/build.gradle index acdb7f15187..e8e47de3297 100644 --- a/protocol/build.gradle +++ b/protocol/build.gradle @@ -1,8 +1,8 @@ apply plugin: 'com.google.protobuf' -def protobufVersion = "3.19.2" - -def grpcVersion = "1.14.0" +def grpcVersion = '1.52.1' // CURRENT_GRPC_VERSION +def protobufVersion = '3.21.12' +def protocVersion = protobufVersion dependencies { compile group: 'com.google.protobuf', name: 'protobuf-java', version: protobufVersion @@ -39,12 +39,12 @@ sourceSets { protobuf { generatedFilesBaseDir = "$projectDir/src/" protoc { - artifact = "com.google.protobuf:protoc:3.5.1-1" + artifact = "com.google.protobuf:protoc:${protocVersion}" } plugins { grpc { - artifact = 'io.grpc:protoc-gen-grpc-java:1.9.0' + artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" } } generateProtoTasks { From ad69dd87b02fc234ac0259896051ed32785166b6 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Tue, 31 Jan 2023 14:18:48 +0800 Subject: [PATCH 0566/1197] feat(test): add some interface tests --- .../test/java/org/tron/core/WalletTest.java | 67 ++++++++++++++++--- 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index dd275cc6e09..7fba210816d 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -18,7 +18,6 @@ package org.tron.core; -import static junit.framework.TestCase.fail; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -26,14 +25,11 @@ import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; import static org.tron.protos.contract.Common.ResourceCode.ENERGY; -import static stest.tron.wallet.common.client.utils.PublicMethed.decode58Check; import com.google.protobuf.Any; import com.google.protobuf.ByteString; import java.io.File; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; import lombok.extern.slf4j.Slf4j; import org.joda.time.DateTime; import org.junit.AfterClass; @@ -55,23 +51,21 @@ import org.tron.core.actuator.DelegateResourceActuator; import org.tron.core.actuator.FreezeBalanceActuator; import org.tron.core.actuator.UnfreezeBalanceV2Actuator; -import org.tron.core.actuator.WithdrawExpireUnfreezeActuator; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.ExchangeCapsule; import org.tron.core.capsule.ProposalCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.TransactionInfoCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; +import org.tron.core.exception.NonUniqueObjectException; import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.utils.ProposalUtil.ProposalType; import org.tron.core.utils.TransactionUtil; @@ -873,7 +867,6 @@ public void testGetAvailableUnfreezeCount() { } } - @Test public void testGetCanWithdrawUnfreezeAmount() { long now = System.currentTimeMillis(); @@ -899,5 +892,63 @@ public void testGetCanWithdrawUnfreezeAmount() { Assert.assertEquals(16_000_000L * 2, message.getAmount()); } + @Test + public void testGetMemoFeePrices() { + String memeFeeList = wallet.getMemoFeePrices(); + Assert.assertEquals("0:0", memeFeeList); + } + + @Test + public void testGetChainParameters() { + Protocol.ChainParameters params = wallet.getChainParameters(); + //getTotalEnergyAverageUsage & getTotalEnergyCurrentLimit have not ProposalType. + Assert.assertEquals(ProposalType.values().length + 2, params.getChainParameterCount()); + } + + @Test + public void testGetAccountById() { + AccountCapsule ownerCapsule = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + ownerCapsule.setAccountId(ByteString.copyFromUtf8("1001").toByteArray()); + chainBaseManager.getAccountIdIndexStore().put(ownerCapsule); + Protocol.Account account = wallet.getAccountById( + Protocol.Account.newBuilder().setAccountId(ByteString.copyFromUtf8("1001")).build()); + Assert.assertEquals(ownerCapsule.getAddress(),account.getAddress()); + } + + @Test + public void testGetAccountResource() { + GrpcAPI.AccountResourceMessage accountResource = + wallet.getAccountResource(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); + Assert.assertEquals( + chainBaseManager.getDynamicPropertiesStore().getFreeNetLimit(), + accountResource.getFreeNetLimit()); + Assert.assertEquals(0, accountResource.getFreeNetUsed()); + } + + @Test + public void testGetAssetIssueByName() { + String assetName = "My_asset"; + String id = "10001"; + AssetIssueCapsule assetCapsule = new AssetIssueCapsule(ByteArray.fromHexString(OWNER_ADDRESS), + id,assetName,"abbr", 1_000_000_000_000L,6); + chainBaseManager.getAssetIssueStore().put(assetCapsule.createDbKey(), assetCapsule); + chainBaseManager.getAssetIssueV2Store().put(assetCapsule.createDbV2Key(), assetCapsule); + try { + AssetIssueContract assetIssue = + wallet.getAssetIssueByName(ByteString.copyFromUtf8(assetName)); + Assert.assertEquals(ByteString.copyFromUtf8(assetName),assetIssue.getName()); + Assert.assertEquals(id,assetIssue.getId()); + chainBaseManager.getDynamicPropertiesStore().saveAllowSameTokenName(1); + assetIssue = wallet.getAssetIssueByName(ByteString.copyFromUtf8(assetName)); + Assert.assertEquals(ByteString.copyFromUtf8(assetName),assetIssue.getName()); + Assert.assertEquals(id,assetIssue.getId()); + } catch (NonUniqueObjectException e) { + Assert.fail(e.getMessage()); + } + chainBaseManager.getAssetIssueStore().delete(assetCapsule.createDbKey()); + chainBaseManager.getAssetIssueV2Store().delete(assetCapsule.createDbV2Key()); + chainBaseManager.getDynamicPropertiesStore().saveAllowSameTokenName(0); + } } From c3994e0e1ea6155964f61c1db792205711442ab0 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Wed, 1 Feb 2023 15:19:38 +0800 Subject: [PATCH 0567/1197] feat(test): add test for Wallet.estimateEnergy --- .../test/java/org/tron/core/WalletTest.java | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 7fba210816d..36f955cd655 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -30,6 +30,8 @@ import com.google.protobuf.ByteString; import java.io.File; import java.util.Arrays; + +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.joda.time.DateTime; import org.junit.AfterClass; @@ -54,6 +56,9 @@ import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.BytesCapsule; +import org.tron.core.capsule.CodeCapsule; +import org.tron.core.capsule.ContractCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.ExchangeCapsule; import org.tron.core.capsule.ProposalCapsule; @@ -69,6 +74,7 @@ import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.utils.ProposalUtil.ProposalType; import org.tron.core.utils.TransactionUtil; +import org.tron.core.vm.program.Program; import org.tron.protos.Protocol; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Block; @@ -84,6 +90,7 @@ import org.tron.protos.contract.BalanceContract; import org.tron.protos.contract.BalanceContract.TransferContract; import org.tron.protos.contract.Common; +import org.tron.protos.contract.SmartContractOuterClass; @Slf4j @@ -950,5 +957,92 @@ public void testGetAssetIssueByName() { chainBaseManager.getAssetIssueV2Store().delete(assetCapsule.createDbV2Key()); chainBaseManager.getDynamicPropertiesStore().saveAllowSameTokenName(0); } + + @Test + @SneakyThrows + public void testEstimateEnergy() { + dbManager.getDynamicPropertiesStore().put("ALLOW_TVM_TRANSFER_TRC10".getBytes(), + new BytesCapsule(ByteArray.fromHexString("0x01"))); + String contractAddress = "0x1A622D84ed49f01045f5f1a5AfcEb9c57e9cC3ca"; + + SmartContractOuterClass.SmartContract smartContract = + SmartContractOuterClass.SmartContract.newBuilder().build(); + ContractCapsule capsule = new ContractCapsule(smartContract); + dbManager.getContractStore().put(ByteArray.fromHexString(contractAddress), capsule); + + String codeString = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b50600436106100495760003560e01c806385bb7d69146100555761004a565b5b610052610073565b50005b61005d610073565b60405161006a91906100b9565b60405180910390f35b600080600090505b60028110156100a657808261009091906100d4565b915060018161009f91906100d4565b905061007b565b5090565b6100b38161012a565b82525050565b60006020820190506100ce60008301846100aa565b92915050565b60006100df8261012a565b91506100ea8361012a565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561011f5761011e610134565b5b828201905092915050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea26474726f6e58221220f3d0198323c67293b97323c101e294e6d2cac7fb29555292675277e11c275a4b64736f6c63430008060033"; + CodeCapsule codeCapsule = new CodeCapsule(ByteArray.fromHexString(codeString)); + dbManager.getCodeStore().put(ByteArray.fromHexString(contractAddress), codeCapsule); + + SmartContractOuterClass.TriggerSmartContract contract = + SmartContractOuterClass.TriggerSmartContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setContractAddress(ByteString.copyFrom( + ByteArray.fromHexString( + contractAddress))) + .build(); + TransactionCapsule trxCap = wallet.createTransactionCapsule(contract, ContractType.TriggerSmartContract); + + GrpcAPI.TransactionExtention.Builder trxExtBuilder = GrpcAPI.TransactionExtention.newBuilder(); + GrpcAPI.Return.Builder retBuilder = GrpcAPI.Return.newBuilder(); + GrpcAPI.EstimateEnergyMessage.Builder estimateBuilder + = GrpcAPI.EstimateEnergyMessage.newBuilder(); + + try { + wallet.estimateEnergy( + contract, trxCap, trxExtBuilder, retBuilder, estimateBuilder); + Assert.fail(); + } catch (ContractValidateException exception) { + assertEquals("this node does not support estimate energy", exception.getMessage()); + } + + Args.getInstance().setEstimateEnergy(true); + + wallet.estimateEnergy( + contract, trxCap, trxExtBuilder, retBuilder, estimateBuilder); + GrpcAPI.EstimateEnergyMessage message = estimateBuilder.build(); + Assert.assertTrue(message.getEnergyRequired() > 0); + } + + @Test + @SneakyThrows + public void testEstimateEnergyOutOfTime() { + dbManager.getDynamicPropertiesStore().put("ALLOW_TVM_TRANSFER_TRC10".getBytes(), + new BytesCapsule(ByteArray.fromHexString("0x01"))); + + String contractAddress = "0x1A622D84ed49f01045f5f1a5AfcEb9c57e9cC3ca"; + + SmartContractOuterClass.SmartContract smartContract = + SmartContractOuterClass.SmartContract.newBuilder().build(); + ContractCapsule capsule = new ContractCapsule(smartContract); + dbManager.getContractStore().put(ByteArray.fromHexString(contractAddress), capsule); + + String codeString = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b50600436106100495760003560e01c806385bb7d69146100555761004a565b5b610052610073565b50005b61005d610073565b60405161006a91906100ae565b60405180910390f35b600080600090505b64e8d4a5100081101561009b57808261009491906100c9565b915061007b565b5090565b6100a88161011f565b82525050565b60006020820190506100c3600083018461009f565b92915050565b60006100d48261011f565b91506100df8361011f565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561011457610113610129565b5b828201905092915050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea26474726f6e58221220a7e1a6e6d17684029015a0b593b63440f77e7eb8abd4297a3063e59f28086bf464736f6c63430008060033"; + CodeCapsule codeCapsule = new CodeCapsule(ByteArray.fromHexString(codeString)); + dbManager.getCodeStore().put(ByteArray.fromHexString(contractAddress), codeCapsule); + + SmartContractOuterClass.TriggerSmartContract contract = + SmartContractOuterClass.TriggerSmartContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setContractAddress(ByteString.copyFrom( + ByteArray.fromHexString( + contractAddress))) + .build(); + TransactionCapsule trxCap = wallet.createTransactionCapsule(contract, ContractType.TriggerSmartContract); + + GrpcAPI.TransactionExtention.Builder trxExtBuilder = GrpcAPI.TransactionExtention.newBuilder(); + GrpcAPI.Return.Builder retBuilder = GrpcAPI.Return.newBuilder(); + GrpcAPI.EstimateEnergyMessage.Builder estimateBuilder + = GrpcAPI.EstimateEnergyMessage.newBuilder(); + + Args.getInstance().setEstimateEnergy(true); + + try { + wallet.estimateEnergy( + contract, trxCap, trxExtBuilder, retBuilder, estimateBuilder); + Assert.fail("EstimateEnergy should throw exception!"); + } catch (Program.OutOfTimeException ignored) { + } + } } From 7956c48d6f03d825e2acc4dec44e8147de7ae4e7 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Wed, 1 Feb 2023 15:47:51 +0800 Subject: [PATCH 0568/1197] feat(test): restrict the test env for estimate energy --- framework/src/test/java/org/tron/core/WalletTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 36f955cd655..64e7f6c578e 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -988,6 +988,7 @@ public void testEstimateEnergy() { GrpcAPI.EstimateEnergyMessage.Builder estimateBuilder = GrpcAPI.EstimateEnergyMessage.newBuilder(); + Args.getInstance().setEstimateEnergy(false); try { wallet.estimateEnergy( contract, trxCap, trxExtBuilder, retBuilder, estimateBuilder); From ff4ee64cd06e61b4043310c9cf65fb6da701ca77 Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Wed, 1 Feb 2023 16:40:23 +0800 Subject: [PATCH 0569/1197] feat(test): fix checkstyle bugs --- .../test/java/org/tron/core/WalletTest.java | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 64e7f6c578e..e360d551665 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -970,7 +970,16 @@ public void testEstimateEnergy() { ContractCapsule capsule = new ContractCapsule(smartContract); dbManager.getContractStore().put(ByteArray.fromHexString(contractAddress), capsule); - String codeString = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b50600436106100495760003560e01c806385bb7d69146100555761004a565b5b610052610073565b50005b61005d610073565b60405161006a91906100b9565b60405180910390f35b600080600090505b60028110156100a657808261009091906100d4565b915060018161009f91906100d4565b905061007b565b5090565b6100b38161012a565b82525050565b60006020820190506100ce60008301846100aa565b92915050565b60006100df8261012a565b91506100ea8361012a565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561011f5761011e610134565b5b828201905092915050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea26474726f6e58221220f3d0198323c67293b97323c101e294e6d2cac7fb29555292675277e11c275a4b64736f6c63430008060033"; + String codeString = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d28015" + + "61002a57600080fd5b50600436106100495760003560e01c806385bb7d69146100555761004a565b5b61" + + "0052610073565b50005b61005d610073565b60405161006a91906100b9565b60405180910390f35b6000" + + "80600090505b60028110156100a657808261009091906100d4565b915060018161009f91906100d4565b" + + "905061007b565b5090565b6100b38161012a565b82525050565b60006020820190506100ce6000830184" + + "6100aa565b92915050565b60006100df8261012a565b91506100ea8361012a565b9250827fffffffffff" + + "ffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561011f5761011e61013456" + + "5b5b828201905092915050565b6000819050919050565b7f4e487b710000000000000000000000000000" + + "0000000000000000000000000000600052601160045260246000fdfea26474726f6e58221220f3d01983" + + "23c67293b97323c101e294e6d2cac7fb29555292675277e11c275a4b64736f6c63430008060033"; CodeCapsule codeCapsule = new CodeCapsule(ByteArray.fromHexString(codeString)); dbManager.getCodeStore().put(ByteArray.fromHexString(contractAddress), codeCapsule); @@ -981,7 +990,8 @@ public void testEstimateEnergy() { ByteArray.fromHexString( contractAddress))) .build(); - TransactionCapsule trxCap = wallet.createTransactionCapsule(contract, ContractType.TriggerSmartContract); + TransactionCapsule trxCap = wallet.createTransactionCapsule(contract, + ContractType.TriggerSmartContract); GrpcAPI.TransactionExtention.Builder trxExtBuilder = GrpcAPI.TransactionExtention.newBuilder(); GrpcAPI.Return.Builder retBuilder = GrpcAPI.Return.newBuilder(); @@ -1018,7 +1028,16 @@ public void testEstimateEnergyOutOfTime() { ContractCapsule capsule = new ContractCapsule(smartContract); dbManager.getContractStore().put(ByteArray.fromHexString(contractAddress), capsule); - String codeString = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b50600436106100495760003560e01c806385bb7d69146100555761004a565b5b610052610073565b50005b61005d610073565b60405161006a91906100ae565b60405180910390f35b600080600090505b64e8d4a5100081101561009b57808261009491906100c9565b915061007b565b5090565b6100a88161011f565b82525050565b60006020820190506100c3600083018461009f565b92915050565b60006100d48261011f565b91506100df8361011f565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561011457610113610129565b5b828201905092915050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea26474726f6e58221220a7e1a6e6d17684029015a0b593b63440f77e7eb8abd4297a3063e59f28086bf464736f6c63430008060033"; + String codeString = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d28015" + + "61002a57600080fd5b50600436106100495760003560e01c806385bb7d69146100555761004a565b5b61" + + "0052610073565b50005b61005d610073565b60405161006a91906100ae565b60405180910390f35b6000" + + "80600090505b64e8d4a5100081101561009b57808261009491906100c9565b915061007b565b5090565b" + + "6100a88161011f565b82525050565b60006020820190506100c3600083018461009f565b92915050565b" + + "60006100d48261011f565b91506100df8361011f565b9250827fffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff0382111561011457610113610129565b5b828201905092915050" + + "565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000" + + "000000600052601160045260246000fdfea26474726f6e58221220a7e1a6e6d17684029015a0b593b634" + + "40f77e7eb8abd4297a3063e59f28086bf464736f6c63430008060033"; CodeCapsule codeCapsule = new CodeCapsule(ByteArray.fromHexString(codeString)); dbManager.getCodeStore().put(ByteArray.fromHexString(contractAddress), codeCapsule); @@ -1029,7 +1048,8 @@ public void testEstimateEnergyOutOfTime() { ByteArray.fromHexString( contractAddress))) .build(); - TransactionCapsule trxCap = wallet.createTransactionCapsule(contract, ContractType.TriggerSmartContract); + TransactionCapsule trxCap = wallet.createTransactionCapsule(contract, + ContractType.TriggerSmartContract); GrpcAPI.TransactionExtention.Builder trxExtBuilder = GrpcAPI.TransactionExtention.newBuilder(); GrpcAPI.Return.Builder retBuilder = GrpcAPI.Return.newBuilder(); @@ -1043,6 +1063,7 @@ public void testEstimateEnergyOutOfTime() { contract, trxCap, trxExtBuilder, retBuilder, estimateBuilder); Assert.fail("EstimateEnergy should throw exception!"); } catch (Program.OutOfTimeException ignored) { + Assert.assertTrue(true); } } } From 3b9b79024eaa20451cdf4b96572b6369e493fc6a Mon Sep 17 00:00:00 2001 From: "daniel.cao" Date: Wed, 1 Feb 2023 17:15:09 +0800 Subject: [PATCH 0570/1197] feat(test): fix checkstyle checks --- .../test/java/org/tron/core/WalletTest.java | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index e360d551665..41afd1b0c8e 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -970,16 +970,16 @@ public void testEstimateEnergy() { ContractCapsule capsule = new ContractCapsule(smartContract); dbManager.getContractStore().put(ByteArray.fromHexString(contractAddress), capsule); - String codeString = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d28015" + - "61002a57600080fd5b50600436106100495760003560e01c806385bb7d69146100555761004a565b5b61" + - "0052610073565b50005b61005d610073565b60405161006a91906100b9565b60405180910390f35b6000" + - "80600090505b60028110156100a657808261009091906100d4565b915060018161009f91906100d4565b" + - "905061007b565b5090565b6100b38161012a565b82525050565b60006020820190506100ce6000830184" + - "6100aa565b92915050565b60006100df8261012a565b91506100ea8361012a565b9250827fffffffffff" + - "ffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561011f5761011e61013456" + - "5b5b828201905092915050565b6000819050919050565b7f4e487b710000000000000000000000000000" + - "0000000000000000000000000000600052601160045260246000fdfea26474726f6e58221220f3d01983" + - "23c67293b97323c101e294e6d2cac7fb29555292675277e11c275a4b64736f6c63430008060033"; + String codeString = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d28015" + + "61002a57600080fd5b50600436106100495760003560e01c806385bb7d69146100555761004a565b5b61" + + "0052610073565b50005b61005d610073565b60405161006a91906100b9565b60405180910390f35b6000" + + "80600090505b60028110156100a657808261009091906100d4565b915060018161009f91906100d4565b" + + "905061007b565b5090565b6100b38161012a565b82525050565b60006020820190506100ce6000830184" + + "6100aa565b92915050565b60006100df8261012a565b91506100ea8361012a565b9250827fffffffffff" + + "ffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561011f5761011e61013456" + + "5b5b828201905092915050565b6000819050919050565b7f4e487b710000000000000000000000000000" + + "0000000000000000000000000000600052601160045260246000fdfea26474726f6e58221220f3d01983" + + "23c67293b97323c101e294e6d2cac7fb29555292675277e11c275a4b64736f6c63430008060033"; CodeCapsule codeCapsule = new CodeCapsule(ByteArray.fromHexString(codeString)); dbManager.getCodeStore().put(ByteArray.fromHexString(contractAddress), codeCapsule); @@ -1028,16 +1028,16 @@ public void testEstimateEnergyOutOfTime() { ContractCapsule capsule = new ContractCapsule(smartContract); dbManager.getContractStore().put(ByteArray.fromHexString(contractAddress), capsule); - String codeString = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d28015" + - "61002a57600080fd5b50600436106100495760003560e01c806385bb7d69146100555761004a565b5b61" + - "0052610073565b50005b61005d610073565b60405161006a91906100ae565b60405180910390f35b6000" + - "80600090505b64e8d4a5100081101561009b57808261009491906100c9565b915061007b565b5090565b" + - "6100a88161011f565b82525050565b60006020820190506100c3600083018461009f565b92915050565b" + - "60006100d48261011f565b91506100df8361011f565b9250827fffffffffffffffffffffffffffffffff" + - "ffffffffffffffffffffffffffffffff0382111561011457610113610129565b5b828201905092915050" + - "565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000" + - "000000600052601160045260246000fdfea26474726f6e58221220a7e1a6e6d17684029015a0b593b634" + - "40f77e7eb8abd4297a3063e59f28086bf464736f6c63430008060033"; + String codeString = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d28015" + + "61002a57600080fd5b50600436106100495760003560e01c806385bb7d69146100555761004a565b5b61" + + "0052610073565b50005b61005d610073565b60405161006a91906100ae565b60405180910390f35b6000" + + "80600090505b64e8d4a5100081101561009b57808261009491906100c9565b915061007b565b5090565b" + + "6100a88161011f565b82525050565b60006020820190506100c3600083018461009f565b92915050565b" + + "60006100d48261011f565b91506100df8361011f565b9250827fffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff0382111561011457610113610129565b5b828201905092915050" + + "565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000" + + "000000600052601160045260246000fdfea26474726f6e58221220a7e1a6e6d17684029015a0b593b634" + + "40f77e7eb8abd4297a3063e59f28086bf464736f6c63430008060033"; CodeCapsule codeCapsule = new CodeCapsule(ByteArray.fromHexString(codeString)); dbManager.getCodeStore().put(ByteArray.fromHexString(contractAddress), codeCapsule); From 0b0597702ee8846ebf0a5a8c515892e75b9ab822 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Tue, 17 Jan 2023 12:29:20 +0800 Subject: [PATCH 0571/1197] fix(unitTest): optimize unit test --- framework/build.gradle | 2 + .../test/java/org/tron/common/BaseTest.java | 85 +++++++++++ .../org/tron/core/BandwidthProcessorTest.java | 43 +----- .../java/org/tron/core/BlockCapsuleTest.java | 23 --- .../java/org/tron/core/BlockUtilTest.java | 2 - .../core/CreateCommonTransactionTest.java | 4 +- .../org/tron/core/EnergyProcessorTest.java | 39 +----- .../tron/core/ShieldedTRC20BuilderTest.java | 55 ++------ .../java/org/tron/core/StorageMarketTest.java | 50 +------ .../test/java/org/tron/core/WalletTest.java | 132 +++++++----------- .../AccountPermissionUpdateActuatorTest.java | 46 +----- .../core/actuator/ActuatorConstantTest.java | 34 +---- .../core/actuator/AssetIssueActuatorTest.java | 40 +----- .../ClearABIContractActuatorTest.java | 40 +----- .../actuator/CreateAccountActuatorTest.java | 41 +----- .../DelegateResourceActuatorTest.java | 42 +----- .../actuator/ExchangeCreateActuatorTest.java | 44 +----- .../actuator/ExchangeInjectActuatorTest.java | 41 +----- .../ExchangeTransactionActuatorTest.java | 41 +----- .../ExchangeWithdrawActuatorTest.java | 41 +----- .../actuator/FreezeBalanceActuatorTest.java | 41 +----- .../actuator/FreezeBalanceV2ActuatorTest.java | 44 +----- .../MarketCancelOrderActuatorTest.java | 42 +----- .../actuator/MarketSellAssetActuatorTest.java | 42 +----- .../ParticipateAssetIssueActuatorTest.java | 47 +------ .../actuator/ProposalApproveActuatorTest.java | 38 +---- .../actuator/ProposalCreateActuatorTest.java | 41 +----- .../actuator/ProposalDeleteActuatorTest.java | 38 +---- .../actuator/SetAccountIdActuatorTest.java | 37 +---- .../ShieldedTransferActuatorTest.java | 43 ++---- .../core/actuator/TransferActuatorTest.java | 41 +----- .../actuator/TransferAssetActuatorTest.java | 40 +----- .../UnDelegateResourceActuatorTest.java | 42 +----- .../actuator/UnfreezeAssetActuatorTest.java | 38 +---- .../actuator/UnfreezeBalanceActuatorTest.java | 42 +----- .../UnfreezeBalanceV2ActuatorTest.java | 42 +----- .../actuator/UpdateAccountActuatorTest.java | 37 +---- .../actuator/UpdateAssetActuatorTest.java | 41 +----- .../actuator/UpdateBrokerageActuatorTest.java | 41 +----- ...UpdateEnergyLimitContractActuatorTest.java | 39 +----- .../UpdateSettingContractActuatorTest.java | 37 +---- .../actuator/VoteWitnessActuatorTest.java | 49 ++----- .../actuator/WithdrawBalanceActuatorTest.java | 41 +----- .../WithdrawExpireUnfreezeActuatorTest.java | 42 +----- .../actuator/WitnessCreateActuatorTest.java | 39 +----- .../actuator/WitnessUpdateActuatorTest.java | 37 +---- .../tron/core/db/AccountIdIndexStoreTest.java | 30 ++-- .../tron/core/db/AccountIndexStoreTest.java | 30 ++-- .../org/tron/core/db/AccountStoreTest.java | 54 +++---- .../java/org/tron/core/db/BlockGenerate.java | 1 + .../java/org/tron/core/db/BlockStoreTest.java | 27 +--- .../org/tron/core/db/CommonStoreTest.java | 29 +--- .../core/db/EnergyPriceHistoryLoaderTest.java | 40 +----- .../org/tron/core/db/KhaosDatabaseTest.java | 24 +--- .../db/MarketPairPriceToOrderStoreTest.java | 34 +---- .../org/tron/core/db/NullifierStoreTest.java | 33 ++--- .../tron/core/db/TransactionHistoryTest.java | 35 ++--- .../tron/core/db/TransactionRetStoreTest.java | 44 +++--- .../tron/core/db/TransactionStoreTest.java | 35 ++--- .../tron/core/db/TransactionTraceTest.java | 69 +-------- .../java/org/tron/core/db/TxCacheDBTest.java | 30 +--- .../java/org/tron/core/db/VotesStoreTest.java | 29 +--- .../org/tron/core/db/WitnessStoreTest.java | 30 +--- 63 files changed, 463 insertions(+), 2017 deletions(-) create mode 100644 framework/src/test/java/org/tron/common/BaseTest.java delete mode 100644 framework/src/test/java/org/tron/core/BlockCapsuleTest.java diff --git a/framework/build.gradle b/framework/build.gradle index 93757755446..e7b6d5ab5fa 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -88,6 +88,8 @@ dependencies { compile "io.vavr:vavr:0.9.2" compile group: 'org.pf4j', name: 'pf4j', version: '2.5.0' + testImplementation group: 'org.springframework', name: 'spring-test', version: '5.2.0.RELEASE' + compile group: 'org.zeromq', name: 'jeromq', version: '0.5.0' compile project(":chainbase") compile project(":protocol") diff --git a/framework/src/test/java/org/tron/common/BaseTest.java b/framework/src/test/java/org/tron/common/BaseTest.java new file mode 100644 index 00000000000..f7d453013b4 --- /dev/null +++ b/framework/src/test/java/org/tron/common/BaseTest.java @@ -0,0 +1,85 @@ +package org.tron.common; + +import com.google.protobuf.ByteString; +import java.io.File; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.runner.RunWith; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.tron.common.crypto.ECKey; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.Sha256Hash; +import org.tron.consensus.base.Param; +import org.tron.core.ChainBaseManager; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.protos.Protocol; + +@Slf4j +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = {DefaultConfig.class}) +@DirtiesContext +public abstract class BaseTest { + + protected static String dbPath; + + @Resource + protected Manager dbManager; + @Resource + protected ChainBaseManager chainBaseManager; + + @AfterClass + public static void destroy() { + Args.clearParam(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.info("Release resources failure."); + } + } + + public Protocol.Block getSignedBlock(ByteString witness, long time, byte[] privateKey) { + long blockTime = System.currentTimeMillis() / 3000 * 3000; + if (time != 0) { + blockTime = time; + } else { + if (chainBaseManager.getHeadBlockId().getNum() != 0) { + blockTime = chainBaseManager.getHeadBlockTimeStamp() + 3000; + } + } + Param param = Param.getInstance(); + Param.Miner miner = param.new Miner(privateKey, witness, witness); + BlockCapsule blockCapsule = dbManager + .generateBlock(miner, time, System.currentTimeMillis() + 1000); + Protocol.Block block = blockCapsule.getInstance(); + + Protocol.BlockHeader.raw raw = block.getBlockHeader().getRawData().toBuilder() + .setParentHash(ByteString + .copyFrom(chainBaseManager.getDynamicPropertiesStore() + .getLatestBlockHeaderHash().getBytes())) + .setNumber(chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() + 1) + .setTimestamp(blockTime) + .setWitnessAddress(witness) + .build(); + + ECKey ecKey = ECKey.fromPrivate(privateKey); + assert ecKey != null; + ECKey.ECDSASignature signature = ecKey.sign(Sha256Hash.of(CommonParameter + .getInstance().isECKeyCryptoEngine(), raw.toByteArray()).getBytes()); + ByteString sign = ByteString.copyFrom(signature.toByteArray()); + + Protocol.BlockHeader blockHeader = block.getBlockHeader().toBuilder() + .setRawData(raw) + .setWitnessSignature(sign) + .build(); + + return block.toBuilder().setBlockHeader(blockHeader).build(); + } + +} diff --git a/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java b/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java index 4d000d375b5..69501c4e393 100755 --- a/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java +++ b/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java @@ -2,26 +2,20 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; import org.joda.time.DateTime; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.RuntimeImpl; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.db.BandwidthProcessor; -import org.tron.core.db.Manager; import org.tron.core.db.TransactionTrace; import org.tron.core.exception.AccountResourceInsufficientException; import org.tron.core.exception.ContractValidateException; @@ -34,9 +28,8 @@ import org.tron.protos.contract.BalanceContract.TransferContract; @Slf4j -public class BandwidthProcessorTest { +public class BandwidthProcessorTest extends BaseTest { - private static final String dbPath = "output_bandwidth_test"; private static final String ASSET_NAME; private static final String ASSET_NAME_V2; private static final String OWNER_ADDRESS; @@ -49,16 +42,13 @@ public class BandwidthProcessorTest { private static final int VOTE_SCORE = 2; private static final String DESCRIPTION = "TRX"; private static final String URL = "https://tron.network/"; - private static Manager dbManager; - private static ChainBaseManager chainBaseManager; - private static TronApplicationContext context; - private static long START_TIME; - private static long END_TIME; + private static final long START_TIME; + private static final long END_TIME; static { + dbPath = "output_bandwidth_processor_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); ASSET_NAME = "test_token"; ASSET_NAME_V2 = "2"; OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; @@ -69,29 +59,6 @@ public class BandwidthProcessorTest { END_TIME = DateTime.now().getMillis(); } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - chainBaseManager = context.getBean(ChainBaseManager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/BlockCapsuleTest.java b/framework/src/test/java/org/tron/core/BlockCapsuleTest.java deleted file mode 100644 index ad129c6d471..00000000000 --- a/framework/src/test/java/org/tron/core/BlockCapsuleTest.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * java-tron is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * java-tron is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.tron.core; - -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public class BlockCapsuleTest { - -} diff --git a/framework/src/test/java/org/tron/core/BlockUtilTest.java b/framework/src/test/java/org/tron/core/BlockUtilTest.java index 25e998d7a70..b122c3082f7 100644 --- a/framework/src/test/java/org/tron/core/BlockUtilTest.java +++ b/framework/src/test/java/org/tron/core/BlockUtilTest.java @@ -69,9 +69,7 @@ public void testBlockUtil() { .fromHexString(blockCapsule2.getBlockId().toString()))) )).build()); - Assert.assertEquals(false, BlockUtil.isParentOf(blockCapsule1, blockCapsule2)); Assert.assertFalse(BlockUtil.isParentOf(blockCapsule1, blockCapsule2)); - Assert.assertEquals(true, BlockUtil.isParentOf(blockCapsule2, blockCapsule3)); Assert.assertTrue(BlockUtil.isParentOf(blockCapsule2, blockCapsule3)); } } diff --git a/framework/src/test/java/org/tron/core/CreateCommonTransactionTest.java b/framework/src/test/java/org/tron/core/CreateCommonTransactionTest.java index e787fe16e96..542373a1234 100644 --- a/framework/src/test/java/org/tron/core/CreateCommonTransactionTest.java +++ b/framework/src/test/java/org/tron/core/CreateCommonTransactionTest.java @@ -16,14 +16,14 @@ public class CreateCommonTransactionTest { - private static String fullnode = "127.0.0.1:50051"; + private static final String FULL_NODE = "127.0.0.1:50051"; /** * for example create UpdateBrokerageContract */ public static void testCreateUpdateBrokerageContract() { WalletBlockingStub walletStub = WalletGrpc - .newBlockingStub(ManagedChannelBuilder.forTarget(fullnode).usePlaintext(true).build()); + .newBlockingStub(ManagedChannelBuilder.forTarget(FULL_NODE).usePlaintext(true).build()); UpdateBrokerageContract.Builder updateBrokerageContract = UpdateBrokerageContract.newBuilder(); updateBrokerageContract.setOwnerAddress( ByteString.copyFrom(decodeFromBase58Check("TN3zfjYUmMFK3ZsHSsrdJoNRtGkQmZLBLz"))) diff --git a/framework/src/test/java/org/tron/core/EnergyProcessorTest.java b/framework/src/test/java/org/tron/core/EnergyProcessorTest.java index b66b79ba07f..f4311930bb2 100755 --- a/framework/src/test/java/org/tron/core/EnergyProcessorTest.java +++ b/framework/src/test/java/org/tron/core/EnergyProcessorTest.java @@ -1,69 +1,36 @@ package org.tron.core; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.capsule.AccountCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.Parameter.AdaptiveResourceLimitConstants; import org.tron.core.config.Parameter.ChainConstant; import org.tron.core.config.args.Args; import org.tron.core.db.EnergyProcessor; -import org.tron.core.db.Manager; import org.tron.protos.Protocol.AccountType; import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; @Slf4j -public class EnergyProcessorTest { +public class EnergyProcessorTest extends BaseTest { - private static final String dbPath = "EnergyProcessorTest"; private static final String ASSET_NAME; private static final String CONTRACT_PROVIDER_ADDRESS; private static final String USER_ADDRESS; - private static Manager dbManager; - private static ChainBaseManager chainBaseManager; - private static TronApplicationContext context; static { + dbPath = "energy_processor_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); ASSET_NAME = "test_token"; CONTRACT_PROVIDER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; USER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - chainBaseManager = context.getBean(ChainBaseManager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java b/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java index ba407b42e0b..5468e90c924 100644 --- a/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java +++ b/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java @@ -3,21 +3,18 @@ import static org.tron.core.zksnark.LibrustzcashTest.librustzcashInitZksnarkParams; import com.google.protobuf.ByteString; -import java.io.File; import java.math.BigInteger; import java.util.Arrays; import java.util.List; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.tuple.Pair; import org.bouncycastle.util.encoders.Hex; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.BytesMessage; import org.tron.api.GrpcAPI.PrivateShieldedTRC20Parameters; @@ -25,20 +22,16 @@ import org.tron.api.GrpcAPI.ShieldedTRC20Parameters; import org.tron.api.GrpcAPI.ShieldedTRC20TriggerContractParameters; import org.tron.api.GrpcAPI.SpendAuthSigParameters; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.FileUtil; import org.tron.common.zksnark.IncrementalMerkleTreeContainer; import org.tron.common.zksnark.IncrementalMerkleVoucherContainer; import org.tron.common.zksnark.JLibrustzcash; import org.tron.common.zksnark.LibrustzcashParam; import org.tron.core.capsule.IncrementalMerkleTreeCapsule; import org.tron.core.capsule.PedersenHashCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.BlockGenerate; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ZksnarkException; @@ -59,14 +52,10 @@ import stest.tron.wallet.common.client.WalletClient; @Slf4j -public class ShieldedTRC20BuilderTest extends BlockGenerate { - - private static String dbPath = "output_Shielded_TRC20_Api_test"; - private static AnnotationConfigApplicationContext context; - private static Manager dbManager; - private static Wallet wallet; - private String privateKey = "650950B193DDDDB35B6E48912DD28F7AB0E7140C1BFDEFD493348F02295BD812"; - private String pubAddress = "TFsrP7YcSSRwHzLPwaCnXyTKagHs8rXKNJ"; +public class ShieldedTRC20BuilderTest extends BaseTest { + @Resource + private Wallet wallet; + private final String priKey = "650950B193DDDDB35B6E48912DD28F7AB0E7140C1BFDEFD493348F02295BD812"; private static final String SHIELDED_CONTRACT_ADDRESS_STR = "TGAmX5AqVUoXCf8MoHxbuhQPmhGfWTnEgA"; private static final byte[] SHIELDED_CONTRACT_ADDRESS; private static final byte[] DEFAULT_OVK; @@ -74,8 +63,8 @@ public class ShieldedTRC20BuilderTest extends BlockGenerate { private static final byte[] PUBLIC_TO_ADDRESS; static { + dbPath = "output_Shielded_TRC20_Api_test"; Args.setParam(new String[]{"--output-directory", dbPath}, "config-test-mainnet.conf"); - context = new TronApplicationContext(DefaultConfig.class); SHIELDED_CONTRACT_ADDRESS = WalletClient.decodeFromBase58Check(SHIELDED_CONTRACT_ADDRESS_STR); DEFAULT_OVK = ByteArray .fromHexString("030c8c2bc59fb3eb8afb047a8ea4b028743d23e7d38c6fa30908358431e2314d"); @@ -87,25 +76,6 @@ public class ShieldedTRC20BuilderTest extends BlockGenerate { VerifyTransferProof transferContract = new VerifyTransferProof(); VerifyBurnProof burnContract = new VerifyBurnProof(); - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - wallet = context.getBean(Wallet.class); - dbManager.getDynamicPropertiesStore().saveAllowShieldedTRC20Transaction(1); - dbManager.getDynamicPropertiesStore().saveAllowShieldedTransaction(1); - } - - @AfterClass - public static void removeDb() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - @Before public void before() { } @@ -121,7 +91,7 @@ public void createShieldedContractParametersForMint() for (int countNum = 0; countNum < totalCountNum; countNum++) { GrpcAPI.PrivateShieldedTRC20Parameters mintPrivateParam1 = mintParams( - privateKey, value, SHIELDED_CONTRACT_ADDRESS_STR, null); + priKey, value, SHIELDED_CONTRACT_ADDRESS_STR, null); GrpcAPI.ShieldedTRC20Parameters trc20MintParams = wallet .createShieldedContractParameters(mintPrivateParam1); @@ -159,7 +129,7 @@ public void createShieldedContractParametersForTransfer1to1() IncrementalMerkleTreeContainer tree = new IncrementalMerkleTreeContainer( new IncrementalMerkleTreeCapsule()); for (int countNum = 0; countNum < totalCountNum; countNum++) { - SpendingKey senderSk = SpendingKey.decode(privateKey); + SpendingKey senderSk = SpendingKey.decode(priKey); FullViewingKey senderFvk = senderSk.fullViewingKey(); IncomingViewingKey senderIvk = senderFvk.inViewingKey(); byte[] rcm1 = new byte[32]; @@ -2203,6 +2173,7 @@ public void createShieldedContractParametersWithoutAskForBurn1to2() @Test public void getTriggerInputForForMint() throws Exception { librustzcashInitZksnarkParams(); + String pubAddress = "TFsrP7YcSSRwHzLPwaCnXyTKagHs8rXKNJ"; byte[] callerAddress = WalletClient.decodeFromBase58Check(pubAddress); SpendingKey sk = SpendingKey.random(); ExpandedSpendingKey expsk = sk.expandedSpendingKey(); @@ -2273,7 +2244,7 @@ public void testScanShieldedTRC20NotesByIvk() throws Exception { int statNum = 1; int endNum = 100; librustzcashInitZksnarkParams(); - SpendingKey sk = SpendingKey.decode(privateKey); + SpendingKey sk = SpendingKey.decode(priKey); FullViewingKey fvk = sk.fullViewingKey(); byte[] ivk = fvk.inViewingKey().value; @@ -2289,7 +2260,7 @@ public void testScanShieldedTRC20NotesByIvk() throws Exception { public void testscanShieldedTRC20NotesByOvk() throws Exception { int statNum = 9200; int endNum = 9240; - SpendingKey sk = SpendingKey.decode(privateKey); + SpendingKey sk = SpendingKey.decode(priKey); FullViewingKey fvk = sk.fullViewingKey(); GrpcAPI.DecryptNotesTRC20 scannedNotes = wallet.scanShieldedTRC20NotesByOvk( @@ -2305,7 +2276,7 @@ public void isShieldedTRC20ContractNoteSpent() throws Exception { int statNum = 9200; int endNum = 9240; librustzcashInitZksnarkParams(); - SpendingKey sk = SpendingKey.decode(privateKey); + SpendingKey sk = SpendingKey.decode(priKey); FullViewingKey fvk = sk.fullViewingKey(); byte[] ivk = fvk.inViewingKey().value; diff --git a/framework/src/test/java/org/tron/core/StorageMarketTest.java b/framework/src/test/java/org/tron/core/StorageMarketTest.java index 039f919c9f4..1c471032861 100644 --- a/framework/src/test/java/org/tron/core/StorageMarketTest.java +++ b/framework/src/test/java/org/tron/core/StorageMarketTest.java @@ -4,70 +4,29 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.capsule.AccountCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.db.StorageMarket; import org.tron.protos.Protocol.AccountType; import org.tron.protos.contract.StorageContract.BuyStorageContract; @Slf4j -public class StorageMarketTest { +public class StorageMarketTest extends BaseTest { - private static final String dbPath = "output_storage_market_test"; private static final String OWNER_ADDRESS; - private static final String OWNER_ADDRESS_INVALID = "aaaa"; - private static final String OWNER_ACCOUNT_INVALID; private static final long initBalance = 10_000_000_000_000_000L; - private static Manager dbManager; private static StorageMarket storageMarket; - private static TronApplicationContext context; static { + dbPath = "output_storage_market_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; - OWNER_ACCOUNT_INVALID = - Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; - } - - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - storageMarket = new StorageMarket(dbManager.getAccountStore(), - dbManager.getDynamicPropertiesStore()); - // Args.setParam(new String[]{"--output-directory", dbPath}, - // "config-junit.conf"); - // dbManager = new Manager(); - // dbManager.init(); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } /** @@ -75,6 +34,9 @@ public static void destroy() { */ @Before public void createAccountCapsule() { + storageMarket = new StorageMarket(dbManager.getAccountStore(), + dbManager.getDynamicPropertiesStore()); + AccountCapsule ownerCapsule = new AccountCapsule( ByteString.copyFromUtf8("owner"), diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 41afd1b0c8e..b353f665823 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -20,7 +20,7 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; @@ -28,16 +28,13 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import java.util.Arrays; - +import javax.annotation.Resource; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.joda.time.DateTime; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import org.tron.api.GrpcAPI; @@ -45,10 +42,9 @@ import org.tron.api.GrpcAPI.BlockList; import org.tron.api.GrpcAPI.ExchangeList; import org.tron.api.GrpcAPI.ProposalList; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.crypto.ECKey; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.Utils; import org.tron.core.actuator.DelegateResourceActuator; import org.tron.core.actuator.FreezeBalanceActuator; @@ -65,9 +61,7 @@ import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.TransactionInfoCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.NonUniqueObjectException; @@ -76,7 +70,6 @@ import org.tron.core.utils.TransactionUtil; import org.tron.core.vm.program.Program; import org.tron.protos.Protocol; -import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.BlockHeader; import org.tron.protos.Protocol.BlockHeader.raw; @@ -94,21 +87,18 @@ @Slf4j -public class WalletTest { +public class WalletTest extends BaseTest { public static final String ACCOUNT_ADDRESS_ONE = "121212a9cf"; public static final String ACCOUNT_ADDRESS_TWO = "232323a9cf"; public static final String ACCOUNT_ADDRESS_THREE = "343434a9cf"; public static final String ACCOUNT_ADDRESS_FOUR = "454545a9cf"; public static final String ACCOUNT_ADDRESS_FIVE = "565656a9cf"; - public static final String ACCOUNT_ADDRESS_SIX = "12344349cf"; public static final long BLOCK_NUM_ONE = 1; public static final long BLOCK_NUM_TWO = 2; public static final long BLOCK_NUM_THREE = 3; public static final long BLOCK_NUM_FOUR = 4; public static final long BLOCK_NUM_FIVE = 5; - public static final long CYCLE_NUM_ONE = 1; - public static final long CYCLE_NUM_TWO = 2; public static final long BLOCK_TIMESTAMP_ONE = DateTime.now().minusDays(4).getMillis(); public static final long BLOCK_TIMESTAMP_TWO = DateTime.now().minusDays(3).getMillis(); public static final long BLOCK_TIMESTAMP_THREE = DateTime.now().minusDays(2).getMillis(); @@ -119,16 +109,13 @@ public class WalletTest { public static final long BLOCK_WITNESS_THREE = 14; public static final long BLOCK_WITNESS_FOUR = 15; public static final long BLOCK_WITNESS_FIVE = 16; - //private static DeferredTransaction deferredTransaction; public static final long TRANSACTION_TIMESTAMP_ONE = DateTime.now().minusDays(4).getMillis(); public static final long TRANSACTION_TIMESTAMP_TWO = DateTime.now().minusDays(3).getMillis(); public static final long TRANSACTION_TIMESTAMP_THREE = DateTime.now().minusDays(2).getMillis(); public static final long TRANSACTION_TIMESTAMP_FOUR = DateTime.now().minusDays(1).getMillis(); public static final long TRANSACTION_TIMESTAMP_FIVE = DateTime.now().getMillis(); - private static TronApplicationContext context; - private static Wallet wallet; - private static ChainBaseManager chainBaseManager; - private static String dbPath = "output_wallet_test"; + @Resource + private Wallet wallet; private static Block block1; private static Block block2; private static Block block3; @@ -139,70 +126,32 @@ public class WalletTest { private static Transaction transaction3; private static Transaction transaction4; private static Transaction transaction5; - private static Transaction transaction6; private static AssetIssueCapsule Asset1; - private static Manager dbManager; private static final String OWNER_ADDRESS; private static final String RECEIVER_ADDRESS; private static final long initBalance = 43_200_000_000L; static { + dbPath = "output_wallet_test"; Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; } - @BeforeClass - public static void init() { - wallet = context.getBean(Wallet.class); - chainBaseManager = context.getBean(ChainBaseManager.class); - dbManager = context.getBean(Manager.class); + @Before + public void before() { initTransaction(); initBlock(); + initAccountCapsule(); chainBaseManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(5); chainBaseManager.getDelegatedResourceStore().reset(); } - @Before - public void createAccountCapsule() { - AccountCapsule ownerCapsule = - new AccountCapsule( - ByteString.copyFromUtf8("owner"), - ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), - AccountType.Normal, - initBalance); - dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); - - AccountCapsule receiverCapsule = - new AccountCapsule( - ByteString.copyFromUtf8("receiver"), - ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), - AccountType.Normal, - initBalance); - dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); - - byte[] dbKey = DelegatedResourceCapsule.createDbKey( - ByteArray.fromHexString(OWNER_ADDRESS), - ByteArray.fromHexString(RECEIVER_ADDRESS)); - byte[] dbKeyV2 = DelegatedResourceCapsule.createDbKeyV2( - ByteArray.fromHexString(OWNER_ADDRESS), - ByteArray.fromHexString(RECEIVER_ADDRESS), - false); - chainBaseManager.getDelegatedResourceStore().delete(dbKey); - chainBaseManager.getDelegatedResourceStore().delete(dbKeyV2); - chainBaseManager.getDelegatedResourceAccountIndexStore() - .delete(ByteArray.fromHexString(OWNER_ADDRESS)); - - dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); - dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(0L); - } - /** * initTransaction. */ - private static void initTransaction() { + private void initTransaction() { transaction1 = getBuildTransaction( getBuildTransferContract(ACCOUNT_ADDRESS_ONE, ACCOUNT_ADDRESS_TWO), TRANSACTION_TIMESTAMP_ONE, BLOCK_NUM_ONE); @@ -227,20 +176,48 @@ private static void initTransaction() { getBuildTransferContract(ACCOUNT_ADDRESS_FIVE, ACCOUNT_ADDRESS_ONE), TRANSACTION_TIMESTAMP_FIVE, BLOCK_NUM_FIVE); addTransactionToStore(transaction5); + } - transaction6 = getBuildTransaction( - getBuildTransferContract(ACCOUNT_ADDRESS_ONE, ACCOUNT_ADDRESS_SIX), - TRANSACTION_TIMESTAMP_FIVE, BLOCK_NUM_FIVE); - addTransactionToStore(transaction5); + private void initAccountCapsule() { + AccountCapsule ownerCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + Protocol.AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + + AccountCapsule receiverCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), + Protocol.AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); + + byte[] dbKey = DelegatedResourceCapsule.createDbKey( + ByteArray.fromHexString(OWNER_ADDRESS), + ByteArray.fromHexString(RECEIVER_ADDRESS)); + byte[] dbKeyV2 = DelegatedResourceCapsule.createDbKeyV2( + ByteArray.fromHexString(OWNER_ADDRESS), + ByteArray.fromHexString(RECEIVER_ADDRESS), + false); + chainBaseManager.getDelegatedResourceStore().delete(dbKey); + chainBaseManager.getDelegatedResourceStore().delete(dbKeyV2); + chainBaseManager.getDelegatedResourceAccountIndexStore() + .delete(ByteArray.fromHexString(OWNER_ADDRESS)); + + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(0L); } - private static void addTransactionToStore(Transaction transaction) { + private void addTransactionToStore(Transaction transaction) { TransactionCapsule transactionCapsule = new TransactionCapsule(transaction); chainBaseManager.getTransactionStore() .put(transactionCapsule.getTransactionId().getBytes(), transactionCapsule); } - private static void addTransactionInfoToStore(Transaction transaction) { + private void addTransactionInfoToStore(Transaction transaction) { TransactionInfoCapsule transactionInfo = new TransactionInfoCapsule(); byte[] trxId = transaction.getRawData().toByteArray(); transactionInfo.setId(trxId); @@ -268,7 +245,7 @@ private static TransferContract getBuildTransferContract(String ownerAddress, St /** * initBlock. */ - private static void initBlock() { + private void initBlock() { block1 = getBuildBlock(BLOCK_TIMESTAMP_ONE, BLOCK_NUM_ONE, BLOCK_WITNESS_ONE, ACCOUNT_ADDRESS_ONE, transaction1, transaction2); @@ -296,7 +273,7 @@ private static void initBlock() { addTransactionInfoToStore(transaction5); } - private static void addBlockToStore(Block block) { + private void addBlockToStore(Block block) { BlockCapsule blockCapsule = new BlockCapsule(block); chainBaseManager.getBlockStore().put(blockCapsule.getBlockId().getBytes(), blockCapsule); } @@ -311,14 +288,14 @@ private static Block getBuildBlock(long timestamp, long num, long witnessId, } - private static void buildAssetIssue() { + private void buildAssetIssue() { AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); builder.setName(ByteString.copyFromUtf8("Asset1")); Asset1 = new AssetIssueCapsule(builder.build()); chainBaseManager.getAssetIssueStore().put(Asset1.createDbKey(), Asset1); } - private static void buildProposal() { + private void buildProposal() { Proposal.Builder builder = Proposal.newBuilder(); builder.setProposalId(1L).setProposerAddress(ByteString.copyFromUtf8("Address1")); ProposalCapsule proposalCapsule = new ProposalCapsule(builder.build()); @@ -330,7 +307,7 @@ private static void buildProposal() { chainBaseManager.getDynamicPropertiesStore().saveLatestProposalNum(2L); } - private static void buildExchange() { + private void buildExchange() { Exchange.Builder builder = Exchange.newBuilder(); builder.setExchangeId(1L).setCreatorAddress(ByteString.copyFromUtf8("Address1")); ExchangeCapsule ExchangeCapsule = new ExchangeCapsule(builder.build()); @@ -344,13 +321,6 @@ private static void buildExchange() { } - @AfterClass - public static void removeDb() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } - @Test public void testWallet() { Wallet wallet1 = new Wallet(); @@ -359,7 +329,7 @@ public void testWallet() { .getAddress())); logger.info("wallet2 address = {}", ByteArray.toHexString(wallet2 .getAddress())); - assertFalse(wallet1.getAddress().equals(wallet2.getAddress())); + assertNotEquals(wallet1.getAddress(), wallet2.getAddress()); } @Test diff --git a/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java index ab0847ff072..2b98557e957 100644 --- a/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java @@ -4,27 +4,19 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import java.util.ArrayList; import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol.AccountType; @@ -37,9 +29,8 @@ import org.tron.protos.contract.AccountContract.AccountPermissionUpdateContract; @Slf4j -public class AccountPermissionUpdateActuatorTest { +public class AccountPermissionUpdateActuatorTest extends BaseTest { - private static final String dbPath = "output_transfer_test"; private static final String OWNER_ADDRESS; private static final String WITNESS_ADDRESS; private static final String KEY_ADDRESS; @@ -58,14 +49,10 @@ public class AccountPermissionUpdateActuatorTest { private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String OWNER_ADDRESS_NOACCOUNT; private static final String KEY_ADDRESS_INVALID = "bbbb"; - public static Application AppT; - private static Manager dbManager; - private static TronApplicationContext context; static { + dbPath = "output_account_permission_update_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - AppT = ApplicationFactory.create(context); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; WITNESS_ADDRESS = Wallet.getAddressPreFixString() + "8CFC572CC20CA18B636BDD93B4FB15EA84CC2B4E"; KEY_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; @@ -98,35 +85,14 @@ public class AccountPermissionUpdateActuatorTest { .setWeight(KEY_WEIGHT).build(); } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - dbManager.getDynamicPropertiesStore().saveAllowMultiSign(1); - dbManager.getDynamicPropertiesStore().saveTotalSignNum(5); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ @Before public void createCapsule() { + dbManager.getDynamicPropertiesStore().saveAllowMultiSign(1); + dbManager.getDynamicPropertiesStore().saveTotalSignNum(5); + AccountCapsule ownerCapsule = new AccountCapsule( ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), ByteString.copyFromUtf8("owner"), AccountType.Normal); diff --git a/framework/src/test/java/org/tron/core/actuator/ActuatorConstantTest.java b/framework/src/test/java/org/tron/core/actuator/ActuatorConstantTest.java index fe17d7ae7c4..3ad6aa1d6dd 100644 --- a/framework/src/test/java/org/tron/core/actuator/ActuatorConstantTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ActuatorConstantTest.java @@ -1,59 +1,33 @@ package org.tron.core.actuator; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; +import org.tron.common.BaseTest; import org.tron.core.Constant; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; @Slf4j(topic = "actuator") -public class ActuatorConstantTest { - - private static final String dbPath = "output_actuatorConstant_test"; - public static Application AppT; - private static TronApplicationContext context; +public class ActuatorConstantTest extends BaseTest { /** * Init . */ @BeforeClass public static void init() { + dbPath = "output_actuatorConstant_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - AppT = ApplicationFactory.create(context); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } @Test - public void variablecheck() { + public void variableCheck() { ActuatorConstant actuator = new ActuatorConstant(); Assert.assertEquals("Account[", actuator.ACCOUNT_EXCEPTION_STR); Assert.assertEquals("Witness[", actuator.WITNESS_EXCEPTION_STR); Assert.assertEquals("Proposal[", actuator.PROPOSAL_EXCEPTION_STR); Assert.assertEquals("] not exists", actuator.NOT_EXIST_STR); - Assert.assertTrue(actuator instanceof ActuatorConstant); } } diff --git a/framework/src/test/java/org/tron/core/actuator/AssetIssueActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/AssetIssueActuatorTest.java index 1fc858f0804..17cf0e2286c 100755 --- a/framework/src/test/java/org/tron/core/actuator/AssetIssueActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/AssetIssueActuatorTest.java @@ -4,31 +4,24 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import lombok.extern.slf4j.Slf4j; import org.junit.After; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; -import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.Parameter.ForkBlockVersionConsts; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol.AccountType; @@ -38,9 +31,8 @@ import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract.FrozenSupply; @Slf4j -public class AssetIssueActuatorTest { +public class AssetIssueActuatorTest extends BaseTest { - private static final String dbPath = "output_assetIssue_test"; private static final String OWNER_ADDRESS; private static final String OWNER_ADDRESS_SECOND; private static final String NAME = "trx-my"; @@ -50,44 +42,18 @@ public class AssetIssueActuatorTest { private static final String DESCRIPTION = "myCoin"; private static final String URL = "tron-my.com"; private static final String ASSET_NAME_SECOND = "asset_name2"; - private static TronApplicationContext context; - private static Manager dbManager; - private static ChainBaseManager chainBaseManager; private static long now = 0; private static long startTime = 0; private static long endTime = 0; static { + dbPath = "output_assetIssue_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; OWNER_ADDRESS_SECOND = Wallet .getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - chainBaseManager = context.getBean(ChainBaseManager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java index de6a426f1ef..fb26aca1979 100644 --- a/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java @@ -5,25 +5,19 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.ContractCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol; @@ -32,11 +26,9 @@ import org.tron.protos.contract.SmartContractOuterClass.SmartContract; import org.tron.protos.contract.SmartContractOuterClass.SmartContract.ABI; - @Slf4j -public class ClearABIContractActuatorTest { +public class ClearABIContractActuatorTest extends BaseTest { - private static final String dbPath = "output_clearabicontract_test"; private static final String OWNER_ADDRESS; private static final String OWNER_ADDRESS_ACCOUNT_NAME = "test_account"; private static final String SECOND_ACCOUNT_ADDRESS; @@ -49,12 +41,10 @@ public class ClearABIContractActuatorTest { "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\"" + ":\"constructor\"}]"); private static final ABI TARGET_ABI = ABI.getDefaultInstance(); - private static TronApplicationContext context; - private static Manager dbManager; static { + dbPath = "output_clearabicontract_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_NOTEXIST = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; @@ -62,34 +52,12 @@ public class ClearABIContractActuatorTest { Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d427122222"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - dbManager.getDynamicPropertiesStore().saveAllowTvmConstantinople(1); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ @Before public void createCapsule() { + dbManager.getDynamicPropertiesStore().saveAllowTvmConstantinople(1); // address in accountStore and the owner of contract AccountCapsule accountCapsule = new AccountCapsule( diff --git a/framework/src/test/java/org/tron/core/actuator/CreateAccountActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/CreateAccountActuatorTest.java index 11c8f7754fc..11f68c0b8bb 100755 --- a/framework/src/test/java/org/tron/core/actuator/CreateAccountActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/CreateAccountActuatorTest.java @@ -4,24 +4,18 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol.AccountType; @@ -30,19 +24,16 @@ import org.tron.protos.contract.AssetIssueContractOuterClass; @Slf4j -public class CreateAccountActuatorTest { +public class CreateAccountActuatorTest extends BaseTest { - private static final String dbPath = "output_CreateAccount_test"; private static final String OWNER_ADDRESS_FIRST; private static final String ACCOUNT_NAME_SECOND = "ownerS"; private static final String OWNER_ADDRESS_SECOND; private static final String INVALID_ACCOUNT_ADDRESS; - private static TronApplicationContext context; - private static Manager dbManager; static { + dbPath = "output_CreateAccount_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = @@ -50,32 +41,6 @@ public class CreateAccountActuatorTest { INVALID_ACCOUNT_ADDRESS = Wallet.getAddressPreFixString() + "12344500882809695a8a687866"; } - /** - * 548794500882809695a8a687866e76d4271a1abc Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - // Args.setParam(new String[]{"--output-directory", dbPath}, - // "config-junit.conf"); - // dbManager = new Manager(); - // dbManager.init(); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java index df7d7436f6a..afbe6895bb9 100644 --- a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java @@ -4,25 +4,19 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.store.DynamicPropertiesStore; @@ -33,55 +27,31 @@ import org.tron.protos.contract.Common.ResourceCode; @Slf4j -public class DelegateResourceActuatorTest { +public class DelegateResourceActuatorTest extends BaseTest { - private static final String dbPath = "output_delegate_resource_test"; private static final String OWNER_ADDRESS; private static final String RECEIVER_ADDRESS; private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String OWNER_ACCOUNT_INVALID; private static final long initBalance = 10_000_000_000L; - private static Manager dbManager; - private static final TronApplicationContext context; static { + dbPath = "output_delegate_resource_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; OWNER_ACCOUNT_INVALID = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); - dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ @Before public void createAccountCapsule() { + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); AccountCapsule ownerCapsule = diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java index 51f658bcbb4..f37016845d4 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java @@ -4,27 +4,21 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import java.util.Arrays; import java.util.Map; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.ExchangeCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ItemNotFoundException; @@ -36,53 +30,24 @@ @Slf4j -public class ExchangeCreateActuatorTest { +public class ExchangeCreateActuatorTest extends BaseTest { - private static final String dbPath = "output_ExchangeCreate_test"; private static final String ACCOUNT_NAME_FIRST = "ownerF"; private static final String OWNER_ADDRESS_FIRST; private static final String ACCOUNT_NAME_SECOND = "ownerS"; private static final String OWNER_ADDRESS_SECOND; - private static final String URL = "https://tron.network/"; private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String OWNER_ADDRESS_NOACCOUNT; - private static final String OWNER_ADDRESS_BALANCENOTSUFFIENT; - private static TronApplicationContext context; - private static Manager dbManager; static { + dbPath = "output_ExchangeCreate_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; OWNER_ADDRESS_NOACCOUNT = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1aed"; - OWNER_ADDRESS_BALANCENOTSUFFIENT = - Wallet.getAddressPreFixString() + "548794500882809695a8a687866e06d4271a1ced"; - } - - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } /** @@ -446,8 +411,7 @@ public void sameTokenNameOpenSuccessExchangeCreate() { Assert.assertEquals(id, exchangeCapsuleV2.getID()); Assert.assertEquals(1000000, exchangeCapsuleV2.getCreateTime()); - Assert - .assertTrue(Arrays.equals(firstTokenId.getBytes(), exchangeCapsuleV2.getFirstTokenId())); + Assert.assertArrayEquals(firstTokenId.getBytes(), exchangeCapsuleV2.getFirstTokenId()); Assert.assertEquals(firstTokenId, ByteArray.toStr(exchangeCapsuleV2.getFirstTokenId())); Assert.assertEquals(firstTokenBalance, exchangeCapsuleV2.getFirstTokenBalance()); Assert.assertEquals(secondTokenId, ByteArray.toStr(exchangeCapsuleV2.getSecondTokenId())); diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java index 28d699a26e0..49a80fd3253 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java @@ -5,27 +5,21 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import java.util.Arrays; import java.util.Map; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.ExchangeCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ItemNotFoundException; @@ -37,53 +31,24 @@ @Slf4j -public class ExchangeInjectActuatorTest { +public class ExchangeInjectActuatorTest extends BaseTest { - private static final String dbPath = "output_ExchangeInject_test"; private static final String ACCOUNT_NAME_FIRST = "ownerF"; private static final String OWNER_ADDRESS_FIRST; private static final String ACCOUNT_NAME_SECOND = "ownerS"; private static final String OWNER_ADDRESS_SECOND; - private static final String URL = "https://tron.network/"; private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String OWNER_ADDRESS_NOACCOUNT; - private static final String OWNER_ADDRESS_BALANCENOTSUFFIENT; - private static TronApplicationContext context; - private static Manager dbManager; static { + dbPath = "output_ExchangeInject_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; OWNER_ADDRESS_NOACCOUNT = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1aed"; - OWNER_ADDRESS_BALANCENOTSUFFIENT = - Wallet.getAddressPreFixString() + "548794500882809695a8a687866e06d4271a1ced"; - } - - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } /** diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java index c3381da72df..dad6b24e03e 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java @@ -5,28 +5,22 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import java.util.Arrays; import java.util.Map; import junit.framework.TestCase; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.ExchangeCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ItemNotFoundException; @@ -38,53 +32,24 @@ @Slf4j -public class ExchangeTransactionActuatorTest { +public class ExchangeTransactionActuatorTest extends BaseTest { - private static final String dbPath = "output_ExchangeTransaction_test"; private static final String ACCOUNT_NAME_FIRST = "ownerF"; private static final String OWNER_ADDRESS_FIRST; private static final String ACCOUNT_NAME_SECOND = "ownerS"; private static final String OWNER_ADDRESS_SECOND; - private static final String URL = "https://tron.network/"; private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String OWNER_ADDRESS_NOACCOUNT; - private static final String OWNER_ADDRESS_BALANCENOTSUFFIENT; - private static TronApplicationContext context; - private static Manager dbManager; static { + dbPath = "output_ExchangeTransaction_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; OWNER_ADDRESS_NOACCOUNT = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1aed"; - OWNER_ADDRESS_BALANCENOTSUFFIENT = - Wallet.getAddressPreFixString() + "548794500882809695a8a687866e06d4271a1ced"; - } - - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } /** diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java index 78b0c18294a..ad08b49c9ee 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java @@ -5,28 +5,22 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import java.util.Arrays; import java.util.Map; import junit.framework.TestCase; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.ExchangeCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ItemNotFoundException; @@ -38,53 +32,24 @@ @Slf4j -public class ExchangeWithdrawActuatorTest { +public class ExchangeWithdrawActuatorTest extends BaseTest { - private static final String dbPath = "output_ExchangeWithdraw_test"; private static final String ACCOUNT_NAME_FIRST = "ownerF"; private static final String OWNER_ADDRESS_FIRST; private static final String ACCOUNT_NAME_SECOND = "ownerS"; private static final String OWNER_ADDRESS_SECOND; - private static final String URL = "https://tron.network/"; private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String OWNER_ADDRESS_NOACCOUNT; - private static final String OWNER_ADDRESS_BALANCENOTSUFFIENT; - private static TronApplicationContext context; - private static Manager dbManager; static { + dbPath = "output_ExchangeWithdraw_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; OWNER_ADDRESS_NOACCOUNT = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1aed"; - OWNER_ADDRESS_BALANCENOTSUFFIENT = - Wallet.getAddressPreFixString() + "548794500882809695a8a687866e06d4271a1ced"; - } - - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } /** diff --git a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java index 3494ddb0624..abcaf538e93 100644 --- a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java @@ -5,18 +5,14 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.crypto.ECKey; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.Utils; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; @@ -25,10 +21,8 @@ import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.Parameter.ChainConstant; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol.AccountType; @@ -38,52 +32,23 @@ import org.tron.protos.contract.Common.ResourceCode; @Slf4j -public class FreezeBalanceActuatorTest { +public class FreezeBalanceActuatorTest extends BaseTest { - private static final String dbPath = "output_freeze_balance_test"; private static final String OWNER_ADDRESS; private static final String RECEIVER_ADDRESS; private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String OWNER_ACCOUNT_INVALID; private static final long initBalance = 10_000_000_000L; - private static Manager dbManager; - private static TronApplicationContext context; static { + dbPath = "output_freeze_balance_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; OWNER_ACCOUNT_INVALID = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - // Args.setParam(new String[]{"--output-directory", dbPath}, - // "config-junit.conf"); - // dbManager = new Manager(); - // dbManager.init(); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java index 1296886637d..082338df753 100644 --- a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java @@ -5,25 +5,19 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.Parameter.ChainConstant; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol.AccountType; @@ -32,58 +26,32 @@ import org.tron.protos.contract.BalanceContract; import org.tron.protos.contract.Common.ResourceCode; - - @Slf4j -public class FreezeBalanceV2ActuatorTest { +public class FreezeBalanceV2ActuatorTest extends BaseTest { - private static final String dbPath = "output_freeze_balance_test"; private static final String OWNER_ADDRESS; private static final String RECEIVER_ADDRESS; private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String OWNER_ACCOUNT_INVALID; private static final long initBalance = 10_000_000_000L; - private static Manager dbManager; - private static TronApplicationContext context; static { + dbPath = "output_freeze_balance_v2_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; OWNER_ACCOUNT_INVALID = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); - dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ @Before public void createAccountCapsule() { + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + AccountCapsule ownerCapsule = new AccountCapsule( ByteString.copyFromUtf8("owner"), diff --git a/framework/src/test/java/org/tron/core/actuator/MarketCancelOrderActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/MarketCancelOrderActuatorTest.java index ec6404b47a1..a9daf0871b1 100644 --- a/framework/src/test/java/org/tron/core/actuator/MarketCancelOrderActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/MarketCancelOrderActuatorTest.java @@ -4,17 +4,13 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -25,9 +21,7 @@ import org.tron.core.capsule.MarketOrderIdListCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.utils.MarketUtils; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ItemNotFoundException; @@ -46,9 +40,8 @@ @Slf4j -public class MarketCancelOrderActuatorTest { +public class MarketCancelOrderActuatorTest extends BaseTest { - private static final String dbPath = "output_MarketCancelOrder_test"; private static final String ACCOUNT_NAME_FIRST = "ownerF"; private static final String OWNER_ADDRESS_FIRST; private static final String ACCOUNT_NAME_SECOND = "ownerS"; @@ -58,12 +51,10 @@ public class MarketCancelOrderActuatorTest { private static final String TOKEN_ID_ONE = String.valueOf(1L); private static final String TOKEN_ID_TWO = String.valueOf(2L); private static final String TRX = "_"; - private static TronApplicationContext context; - private static Manager dbManager; static { + dbPath = "output_MarketCancelOrder_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = @@ -73,37 +64,16 @@ public class MarketCancelOrderActuatorTest { } /** - * Init data. + * create temp Capsule test need. */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); + @Before + public void initTest() { dbManager.getDynamicPropertiesStore().saveAllowMarketTransaction(1L); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(1000000); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(10); dbManager.getDynamicPropertiesStore().saveNextMaintenanceTime(2000000); dbManager.getDynamicPropertiesStore().saveAllowSameTokenName(1); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** - * create temp Capsule test need. - */ - @Before - public void initTest() { byte[] ownerAddressFirstBytes = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); byte[] ownerAddressSecondBytes = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); diff --git a/framework/src/test/java/org/tron/core/actuator/MarketSellAssetActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/MarketSellAssetActuatorTest.java index cf654af891d..587a6b5aacd 100644 --- a/framework/src/test/java/org/tron/core/actuator/MarketSellAssetActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/MarketSellAssetActuatorTest.java @@ -4,18 +4,14 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import java.util.List; import lombok.extern.slf4j.Slf4j; import org.junit.After; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -26,9 +22,7 @@ import org.tron.core.capsule.MarketOrderIdListCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.utils.MarketUtils; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ItemNotFoundException; @@ -46,9 +40,8 @@ @Slf4j -public class MarketSellAssetActuatorTest { +public class MarketSellAssetActuatorTest extends BaseTest { - private static final String dbPath = "output_MarketSellAsset_test"; private static final String ACCOUNT_NAME_FIRST = "ownerF"; private static final String OWNER_ADDRESS_FIRST; private static final String ACCOUNT_NAME_SECOND = "ownerS"; @@ -58,12 +51,10 @@ public class MarketSellAssetActuatorTest { private static final String TOKEN_ID_ONE = String.valueOf(1L); private static final String TOKEN_ID_TWO = String.valueOf(2L); private static final String TRX = "_"; - private static TronApplicationContext context; - private static Manager dbManager; static { + dbPath = "output_MarketSellAsset_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = @@ -73,37 +64,16 @@ public class MarketSellAssetActuatorTest { } /** - * Init data. + * create temp Capsule test need. */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); + @Before + public void initTest() { dbManager.getDynamicPropertiesStore().saveAllowMarketTransaction(1L); dbManager.getDynamicPropertiesStore().saveAllowSameTokenName(1); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(1000000); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(10); dbManager.getDynamicPropertiesStore().saveNextMaintenanceTime(2000000); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** - * create temp Capsule test need. - */ - @Before - public void initTest() { byte[] ownerAddressFirstBytes = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); byte[] ownerAddressSecondBytes = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); diff --git a/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java index 168725f9634..0bcfbc8820f 100755 --- a/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java @@ -2,27 +2,18 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import org.joda.time.DateTime; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; -import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol.AccountType; @@ -31,10 +22,8 @@ import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; import org.tron.protos.contract.AssetIssueContractOuterClass.ParticipateAssetIssueContract; -public class ParticipateAssetIssueActuatorTest { +public class ParticipateAssetIssueActuatorTest extends BaseTest { - private static final Logger logger = LoggerFactory.getLogger("Test"); - private static final String dbPath = "output_participateAsset_test"; private static final String OWNER_ADDRESS; private static final String TO_ADDRESS; private static final String TO_ADDRESS_2; @@ -49,14 +38,11 @@ public class ParticipateAssetIssueActuatorTest { private static final int VOTE_SCORE = 2; private static final String DESCRIPTION = "TRX"; private static final String URL = "https://tron.network/"; - private static Manager dbManager; - private static ChainBaseManager chainBaseManager; - private static TronApplicationContext context; private static long AMOUNT = TOTAL_SUPPLY - (1000L) / TRX_NUM * NUM; static { + dbPath = "output_participateAsset_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1234"; TO_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; TO_ADDRESS_2 = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e048892"; @@ -64,36 +50,13 @@ public class ParticipateAssetIssueActuatorTest { NOT_EXIT_ADDRESS = Wallet.getAddressPreFixString() + "B56446E617E924805E4D6CA021D341FEF6E2013B"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - chainBaseManager = context.getBean(ChainBaseManager.class); - - chainBaseManager.getDynamicPropertiesStore().saveTokenIdNum(1000000); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ @Before public void createCapsule() { + chainBaseManager.getDynamicPropertiesStore().saveTokenIdNum(1000000); + AccountCapsule ownerCapsule = new AccountCapsule( ByteString.copyFromUtf8("owner"), diff --git a/framework/src/test/java/org/tron/core/actuator/ProposalApproveActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ProposalApproveActuatorTest.java index 5ca4d7abfcf..484c6666941 100644 --- a/framework/src/test/java/org/tron/core/actuator/ProposalApproveActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ProposalApproveActuatorTest.java @@ -4,17 +4,13 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import java.util.HashMap; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -22,9 +18,7 @@ import org.tron.core.capsule.ProposalCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ItemNotFoundException; @@ -35,10 +29,8 @@ import org.tron.protos.contract.ProposalContract; @Slf4j +public class ProposalApproveActuatorTest extends BaseTest { -public class ProposalApproveActuatorTest { - - private static final String dbPath = "output_ProposalApprove_test"; private static final String ACCOUNT_NAME_FIRST = "ownerF"; private static final String OWNER_ADDRESS_FIRST; private static final String ACCOUNT_NAME_SECOND = "ownerS"; @@ -46,12 +38,10 @@ public class ProposalApproveActuatorTest { private static final String URL = "https://tron.network/"; private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String OWNER_ADDRESS_NOACCOUNT; - private static TronApplicationContext context; - private static Manager dbManager; static { + dbPath = "output_ProposalApprove_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = @@ -60,28 +50,6 @@ public class ProposalApproveActuatorTest { Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1aed"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/actuator/ProposalCreateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ProposalCreateActuatorTest.java index 56bf9504730..1e95911884c 100644 --- a/framework/src/test/java/org/tron/core/actuator/ProposalCreateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ProposalCreateActuatorTest.java @@ -4,26 +4,20 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import java.util.HashMap; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.ProposalCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ItemNotFoundException; @@ -33,10 +27,8 @@ import org.tron.protos.contract.ProposalContract.ProposalCreateContract; @Slf4j +public class ProposalCreateActuatorTest extends BaseTest { -public class ProposalCreateActuatorTest { - - private static final String dbPath = "output_ProposalCreate_test"; private static final String ACCOUNT_NAME_FIRST = "ownerF"; private static final String OWNER_ADDRESS_FIRST; private static final String ACCOUNT_NAME_SECOND = "ownerS"; @@ -44,43 +36,16 @@ public class ProposalCreateActuatorTest { private static final String URL = "https://tron.network/"; private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String OWNER_ADDRESS_NOACCOUNT; - private static final String OWNER_ADDRESS_BALANCENOTSUFFIENT; - private static TronApplicationContext context; - private static Manager dbManager; static { + dbPath = "output_ProposalCreate_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; OWNER_ADDRESS_NOACCOUNT = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1aed"; - OWNER_ADDRESS_BALANCENOTSUFFIENT = - Wallet.getAddressPreFixString() + "548794500882809695a8a687866e06d4271a1ced"; - } - - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } /** diff --git a/framework/src/test/java/org/tron/core/actuator/ProposalDeleteActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ProposalDeleteActuatorTest.java index e8d7829f90c..63e5758a907 100644 --- a/framework/src/test/java/org/tron/core/actuator/ProposalDeleteActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ProposalDeleteActuatorTest.java @@ -4,17 +4,13 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import java.util.HashMap; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -22,9 +18,7 @@ import org.tron.core.capsule.ProposalCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ItemNotFoundException; @@ -35,10 +29,8 @@ import org.tron.protos.contract.ProposalContract; @Slf4j +public class ProposalDeleteActuatorTest extends BaseTest { -public class ProposalDeleteActuatorTest { - - private static final String dbPath = "output_ProposalApprove_test"; private static final String ACCOUNT_NAME_FIRST = "ownerF"; private static final String OWNER_ADDRESS_FIRST; private static final String ACCOUNT_NAME_SECOND = "ownerS"; @@ -46,12 +38,10 @@ public class ProposalDeleteActuatorTest { private static final String URL = "https://tron.network/"; private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String OWNER_ADDRESS_NOACCOUNT; - private static TronApplicationContext context; - private static Manager dbManager; static { + dbPath = "output_ProposalDelete_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = @@ -60,28 +50,6 @@ public class ProposalDeleteActuatorTest { Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1aed"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/actuator/SetAccountIdActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/SetAccountIdActuatorTest.java index 018ae6401bc..0b4311ca46f 100644 --- a/framework/src/test/java/org/tron/core/actuator/SetAccountIdActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/SetAccountIdActuatorTest.java @@ -2,23 +2,17 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol.AccountType; @@ -27,46 +21,21 @@ import org.tron.protos.contract.AssetIssueContractOuterClass; @Slf4j -public class SetAccountIdActuatorTest { +public class SetAccountIdActuatorTest extends BaseTest { - private static final String dbPath = "output_setaccountid_test"; private static final String ACCOUNT_NAME = "ownertest"; private static final String ACCOUNT_NAME_1 = "ownertest1"; private static final String OWNER_ADDRESS; private static final String OWNER_ADDRESS_1; private static final String OWNER_ADDRESS_INVALID = "aaaa"; - private static TronApplicationContext context; - private static Manager dbManager; static { + dbPath = "output_setaccountid_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; OWNER_ADDRESS_1 = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java index 3042a745d94..88748e48dcd 100755 --- a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java @@ -1,16 +1,14 @@ package org.tron.core.actuator; import com.google.protobuf.ByteString; -import java.io.File; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.zksnark.IncrementalMerkleTreeContainer; import org.tron.common.zksnark.IncrementalMerkleVoucherContainer; import org.tron.core.Constant; @@ -22,9 +20,7 @@ import org.tron.core.capsule.PedersenHashCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.PermissionException; import org.tron.core.exception.ValidateSignatureException; @@ -47,14 +43,12 @@ import org.tron.protos.contract.ShieldContract.ShieldedTransferContract; @Slf4j -public class ShieldedTransferActuatorTest { +public class ShieldedTransferActuatorTest extends BaseTest { - private static final String dbPath = "output_shield_transfer_test"; private static final String PUBLIC_ADDRESS_ONE; private static final String ADDRESS_ONE_PRIVATE_KEY; private static final String PUBLIC_ADDRESS_TWO; private static final String ADDRESS_TWO_PRIVATE_KEY; - private static final String PUBLIC_ADDRESS_OFF_LINE; private static final long AMOUNT = 100000000L; private static final long OWNER_BALANCE = 9999999000000L; private static final long TO_BALANCE = 100001000000L; @@ -69,22 +63,20 @@ public class ShieldedTransferActuatorTest { private static final int VOTE_SCORE = 2; private static final String DESCRIPTION = "TRX"; private static final String URL = "https://tron.network/"; - private static Wallet wallet; - private static Manager dbManager; - private static TronApplicationContext context; - private static TransactionUtil transactionUtil; + @Resource + private Wallet wallet; + @Resource + private TransactionUtil transactionUtil; static { + dbPath = "output_shield_transfer_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); PUBLIC_ADDRESS_ONE = Wallet.getAddressPreFixString() + "a7d8a35b260395c14aa456297662092ba3b76fc0"; ADDRESS_ONE_PRIVATE_KEY = "7f7f701e94d4f1dd60ee5205e7ea8ee31121427210417b608a6b2e96433549a7"; PUBLIC_ADDRESS_TWO = Wallet.getAddressPreFixString() + "8ba2aaae540c642e44e3bed5522c63bbc21fff92"; ADDRESS_TWO_PRIVATE_KEY = "e4e0edd6bff7b353dfc69a590721e902e6915c5e3e87d36dcb567a9716304720"; - PUBLIC_ADDRESS_OFF_LINE = - Wallet.getAddressPreFixString() + "7bcb781f4743afaacf9f9528f3ea903b3782339f"; DEFAULT_OVK = ByteArray.fromHexString( "030c8c2bc59fb3eb8afb047a8ea4b028743d23e7d38c6fa30908358431e2314d"); } @@ -95,27 +87,10 @@ public class ShieldedTransferActuatorTest { @BeforeClass public static void init() throws ZksnarkException { Args.setFullNodeAllowShieldedTransaction(true); - wallet = context.getBean(Wallet.class); - transactionUtil = context.getBean(TransactionUtil.class); - dbManager = context.getBean(Manager.class); librustzcashInitZksnarkParams(); } - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - - private static void librustzcashInitZksnarkParams() throws ZksnarkException { + private static void librustzcashInitZksnarkParams() { FullNodeHttpApiService.librustzcashInitZksnarkParams(); } diff --git a/framework/src/test/java/org/tron/core/actuator/TransferActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/TransferActuatorTest.java index c8f55768910..05aea41e7c7 100644 --- a/framework/src/test/java/org/tron/core/actuator/TransferActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/TransferActuatorTest.java @@ -5,26 +5,20 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import java.util.Date; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.BalanceInsufficientException; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; @@ -38,9 +32,8 @@ import org.tron.protos.contract.BalanceContract.TransferContract; @Slf4j -public class TransferActuatorTest { +public class TransferActuatorTest extends BaseTest { - private static final String dbPath = "output_transfer_test"; private static final String OWNER_ADDRESS; private static final String TO_ADDRESS; private static final long AMOUNT = 100; @@ -51,12 +44,10 @@ public class TransferActuatorTest { private static final String OWNER_ACCOUNT_INVALID; private static final String OWNER_NO_BALANCE; private static final String To_ACCOUNT_INVALID; - private static Manager dbManager; - private static TronApplicationContext context; static { + dbPath = "output_transfer_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; TO_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ACCOUNT_INVALID = @@ -66,32 +57,6 @@ public class TransferActuatorTest { Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3422"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - // Args.setParam(new String[]{"--output-directory", dbPath}, - // "config-junit.conf"); - // dbManager = new Manager(); - // dbManager.init(); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/actuator/TransferAssetActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/TransferAssetActuatorTest.java index 440cbc3a4a7..07bb8415068 100755 --- a/framework/src/test/java/org/tron/core/actuator/TransferAssetActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/TransferAssetActuatorTest.java @@ -20,28 +20,20 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; - -import java.io.File; - import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.BalanceInsufficientException; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; @@ -57,9 +49,8 @@ import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; @Slf4j -public class TransferAssetActuatorTest { +public class TransferAssetActuatorTest extends BaseTest { - private static final String dbPath = "output_transferasset_test"; private static final String ASSET_NAME = "trx"; private static final String OWNER_ADDRESS; private static final String TO_ADDRESS; @@ -79,13 +70,10 @@ public class TransferAssetActuatorTest { private static final int VOTE_SCORE = 2; private static final String DESCRIPTION = "TRX"; private static final String URL = "https://tron.network/"; - private static TronApplicationContext context; - private static Manager dbManager; - private static Any contract; static { + dbPath = "output_transferasset_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; TO_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a146a"; NOT_EXIT_ADDRESS = Wallet.getAddressPreFixString() + "B56446E617E924805E4D6CA021D341FEF6E2013B"; @@ -95,28 +83,6 @@ public class TransferAssetActuatorTest { Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049010"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java index f57c82935e2..e825364be39 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java @@ -6,25 +6,19 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol.AccountType; @@ -34,56 +28,32 @@ import org.tron.protos.contract.Common.ResourceCode; @Slf4j -public class UnDelegateResourceActuatorTest { +public class UnDelegateResourceActuatorTest extends BaseTest { - private static final String dbPath = "output_unDelegate_resource_test"; private static final String OWNER_ADDRESS; private static final String RECEIVER_ADDRESS; private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String OWNER_ACCOUNT_INVALID; private static final long initBalance = 10_000_000_000L; private static final long delegateBalance = 1_000_000_000L; - private static Manager dbManager; - private static final TronApplicationContext context; static { + dbPath = "output_unDelegate_resource_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; OWNER_ACCOUNT_INVALID = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); - dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ @Before public void createAccountCapsule() { + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + AccountCapsule ownerCapsule = new AccountCapsule(ByteString.copyFromUtf8("owner"), ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), AccountType.Normal, initBalance); diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeAssetActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeAssetActuatorTest.java index 70437a890df..0a624faf113 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeAssetActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeAssetActuatorTest.java @@ -2,25 +2,19 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol.Account; @@ -32,49 +26,23 @@ import org.tron.protos.contract.AssetIssueContractOuterClass.UnfreezeAssetContract; @Slf4j -public class UnfreezeAssetActuatorTest { +public class UnfreezeAssetActuatorTest extends BaseTest { - private static final String dbPath = "output_unfreeze_asset_test"; private static final String OWNER_ADDRESS; private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String OWNER_ACCOUNT_INVALID; private static final long initBalance = 10_000_000_000L; private static final long frozenBalance = 1_000_000_000L; private static final String assetName = "testCoin"; - private static final String assetID = "123456"; - private static Manager dbManager; - private static TronApplicationContext context; static { + dbPath = "output_unfreeze_asset_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; OWNER_ACCOUNT_INVALID = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java index de24f581c04..3f9b999228c 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java @@ -4,18 +4,14 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import java.util.ArrayList; import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; @@ -23,9 +19,7 @@ import org.tron.core.capsule.DelegatedResourceCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.VotesCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol.AccountType; @@ -36,54 +30,24 @@ import org.tron.protos.contract.Common.ResourceCode; @Slf4j -public class UnfreezeBalanceActuatorTest { +public class UnfreezeBalanceActuatorTest extends BaseTest { - private static final String dbPath = "output_unfreeze_balance_test"; private static final String OWNER_ADDRESS; private static final String RECEIVER_ADDRESS; private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String OWNER_ACCOUNT_INVALID; private static final long initBalance = 10_000_000_000L; private static final long frozenBalance = 1_000_000_000L; - private static final long smallTatalResource = 100L; - private static Manager dbManager; - private static TronApplicationContext context; static { + dbPath = "output_unfreeze_balance_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; OWNER_ACCOUNT_INVALID = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - // Args.setParam(new String[]{"--output-directory", dbPath}, - // "config-junit.conf"); - // dbManager = new Manager(); - // dbManager.init(); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java index 6caa3727a0c..14a6de98606 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java @@ -6,24 +6,18 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.VotesCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol.AccountType; @@ -34,56 +28,32 @@ import org.tron.protos.contract.Common.ResourceCode; @Slf4j -public class UnfreezeBalanceV2ActuatorTest { +public class UnfreezeBalanceV2ActuatorTest extends BaseTest { - private static final String dbPath = "output_unfreeze_balance_test"; private static final String OWNER_ADDRESS; private static final String RECEIVER_ADDRESS; private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String OWNER_ACCOUNT_INVALID; private static final long initBalance = 10_000_000_000L; private static final long frozenBalance = 1_000_000_000L; - private static Manager dbManager; - private static final TronApplicationContext context; static { + dbPath = "output_unfreeze_balance_v2_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; OWNER_ACCOUNT_INVALID = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); - dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ @Before public void createAccountCapsule() { + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + AccountCapsule ownerCapsule = new AccountCapsule(ByteString.copyFromUtf8("owner"), ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), AccountType.Normal, initBalance); diff --git a/framework/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java index 315a045128a..acbb9fb4d0b 100755 --- a/framework/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java @@ -4,23 +4,17 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol.AccountType; @@ -29,46 +23,21 @@ import org.tron.protos.contract.AssetIssueContractOuterClass; @Slf4j -public class UpdateAccountActuatorTest { +public class UpdateAccountActuatorTest extends BaseTest { - private static final String dbPath = "output_updateaccount_test"; private static final String ACCOUNT_NAME = "ownerTest"; private static final String ACCOUNT_NAME_1 = "ownerTest1"; private static final String OWNER_ADDRESS; private static final String OWNER_ADDRESS_1; private static final String OWNER_ADDRESS_INVALID = "aaaa"; - private static TronApplicationContext context; - private static Manager dbManager; static { + dbPath = "output_updateaccount_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; OWNER_ADDRESS_1 = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/actuator/UpdateAssetActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UpdateAssetActuatorTest.java index 6bd57c85361..b7583bc335b 100644 --- a/framework/src/test/java/org/tron/core/actuator/UpdateAssetActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UpdateAssetActuatorTest.java @@ -4,28 +4,20 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import java.util.Date; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol; @@ -34,9 +26,8 @@ import org.tron.protos.contract.AssetIssueContractOuterClass.UpdateAssetContract; @Slf4j -public class UpdateAssetActuatorTest { +public class UpdateAssetActuatorTest extends BaseTest { - private static final String dbPath = "output_updateAsset_test"; private static final String OWNER_ADDRESS; private static final String OWNER_ADDRESS_ACCOUNT_NAME = "test_account"; private static final String SECOND_ACCOUNT_ADDRESS; @@ -46,14 +37,10 @@ public class UpdateAssetActuatorTest { private static final long TOTAL_SUPPLY = 10000L; private static final String DESCRIPTION = "myCoin"; private static final String URL = "tron-my.com"; - private static TronApplicationContext context; - private static Application AppT; - private static Manager dbManager; static { + dbPath = "output_updateAsset_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - AppT = ApplicationFactory.create(context); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_NOTEXIST = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; @@ -61,28 +48,6 @@ public class UpdateAssetActuatorTest { Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d427122222"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/actuator/UpdateBrokerageActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UpdateBrokerageActuatorTest.java index e2ce611c56b..034415e0ef1 100644 --- a/framework/src/test/java/org/tron/core/actuator/UpdateBrokerageActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UpdateBrokerageActuatorTest.java @@ -4,25 +4,19 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.store.DelegationStore; @@ -32,19 +26,16 @@ import org.tron.protos.contract.StorageContract.UpdateBrokerageContract; @Slf4j(topic = "actuator") -public class UpdateBrokerageActuatorTest { +public class UpdateBrokerageActuatorTest extends BaseTest { - private static final String dbPath = "output_updatebrokerageactuator_test"; private static final String OWNER_ADDRESS; private static final String OWNER_ADDRESS_NOTEXIST; private static final String OWNER_ADDRESS_INVALID; private static final int BROKEN_AGE = 10; - private static TronApplicationContext context; - private static Manager dbManager; static { + dbPath = "output_updatebrokerageactuator_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_NOTEXIST = Wallet.getAddressPreFixString() + "1234b9367799eaa3197fecb144eb71de1e049123"; @@ -52,34 +43,10 @@ public class UpdateBrokerageActuatorTest { Wallet.getAddressPreFixString() + "354394500882809695a8a687866e7"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - - dbManager = context.getBean(Manager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - - @Before /** * set witness store, account store, dynamic store */ + @Before public void initDB() { // allow dynamic store dbManager.getDynamicPropertiesStore().saveChangeDelegation(1); diff --git a/framework/src/test/java/org/tron/core/actuator/UpdateEnergyLimitContractActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UpdateEnergyLimitContractActuatorTest.java index 9a662e15834..3703dc74e87 100644 --- a/framework/src/test/java/org/tron/core/actuator/UpdateEnergyLimitContractActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UpdateEnergyLimitContractActuatorTest.java @@ -5,28 +5,23 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; -import java.io.File; import java.util.Arrays; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.ContractCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.Parameter.ForkBlockVersionConsts; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.TronException; @@ -37,10 +32,8 @@ @Slf4j -//@Ignore -public class UpdateEnergyLimitContractActuatorTest { +public class UpdateEnergyLimitContractActuatorTest extends BaseTest { - private static final String dbPath = "output_updateEnergyLimitContractActuator_test"; private static final String OWNER_ADDRESS_ACCOUNT_NAME = "test_account"; private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String SMART_CONTRACT_NAME = "smart_contarct"; @@ -49,15 +42,13 @@ public class UpdateEnergyLimitContractActuatorTest { private static final long SOURCE_ENERGY_LIMIT = 10L; private static final long TARGET_ENERGY_LIMIT = 30L; private static final long INVALID_ENERGY_LIMIT = -200L; - private static TronApplicationContext context; - private static Manager dbManager; private static String OWNER_ADDRESS; private static String SECOND_ACCOUNT_ADDRESS; private static String OWNER_ADDRESS_NOTEXIST; static { + dbPath = "output_updateEnergyLimitContractActuator_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); } /** @@ -65,40 +56,24 @@ public class UpdateEnergyLimitContractActuatorTest { */ @BeforeClass public static void init() { - dbManager = context.getBean(Manager.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; SECOND_ACCOUNT_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d427122222"; OWNER_ADDRESS_NOTEXIST = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; - - byte[] stats = new byte[27]; - Arrays.fill(stats, (byte) 1); - dbManager.getDynamicPropertiesStore() - .statsByVersion(ForkBlockVersionConsts.ENERGY_LIMIT, stats); CommonParameter.getInstance().setBlockNumForEnergyLimit(0); } - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ @Before public void createCapsule() { + byte[] stats = new byte[27]; + Arrays.fill(stats, (byte) 1); + dbManager.getDynamicPropertiesStore() + .statsByVersion(ForkBlockVersionConsts.ENERGY_LIMIT, stats); // address in accountStore and the owner of contract AccountCapsule accountCapsule = new AccountCapsule( diff --git a/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java index 1113b4b1689..0445f893983 100644 --- a/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java @@ -4,25 +4,19 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.ContractCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol; @@ -32,9 +26,8 @@ @Slf4j -public class UpdateSettingContractActuatorTest { +public class UpdateSettingContractActuatorTest extends BaseTest { - private static final String dbPath = "output_updatesettingcontract_test"; private static final String OWNER_ADDRESS; private static final String OWNER_ADDRESS_ACCOUNT_NAME = "test_account"; private static final String SECOND_ACCOUNT_ADDRESS; @@ -46,12 +39,10 @@ public class UpdateSettingContractActuatorTest { private static final long SOURCE_PERCENT = 10L; private static final long TARGET_PERCENT = 30L; private static final long INVALID_PERCENT = 200L; - private static TronApplicationContext context; - private static Manager dbManager; static { + dbPath = "output_updatesettingcontract_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_NOTEXIST = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; @@ -59,28 +50,6 @@ public class UpdateSettingContractActuatorTest { Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d427122222"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/actuator/VoteWitnessActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/VoteWitnessActuatorTest.java index ef075f02168..26e4e7364b9 100644 --- a/framework/src/test/java/org/tron/core/actuator/VoteWitnessActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/VoteWitnessActuatorTest.java @@ -4,16 +4,13 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.consensus.dpos.MaintenanceManager; import org.tron.core.Constant; @@ -22,10 +19,8 @@ import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.consensus.ConsensusService; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol.AccountType; @@ -37,9 +32,8 @@ import org.tron.protos.contract.WitnessContract.VoteWitnessContract.Vote; @Slf4j -public class VoteWitnessActuatorTest { +public class VoteWitnessActuatorTest extends BaseTest { - private static final String dbPath = "output_VoteWitness_test"; private static final String ACCOUNT_NAME = "account"; private static final String OWNER_ADDRESS; private static final String WITNESS_NAME = "witness"; @@ -49,14 +43,14 @@ public class VoteWitnessActuatorTest { private static final String WITNESS_ADDRESS_NOACCOUNT; private static final String OWNER_ADDRESS_NOACCOUNT; private static final String OWNER_ADDRESS_BALANCENOTSUFFICIENT; - private static TronApplicationContext context; - private static Manager dbManager; - private static MaintenanceManager maintenanceManager; - private static ConsensusService consensusService; + @Resource + private MaintenanceManager maintenanceManager; + @Resource + private ConsensusService consensusService; static { + dbPath = "output_VoteWitness_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; WITNESS_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; WITNESS_ADDRESS_NOACCOUNT = @@ -67,36 +61,13 @@ public class VoteWitnessActuatorTest { Wallet.getAddressPreFixString() + "548794500882809695a8a687866e06d4271a1ced"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - maintenanceManager = context.getBean(MaintenanceManager.class); - consensusService = context.getBean(ConsensusService.class); - consensusService.start(); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ @Before public void createCapsule() { + consensusService.start(); + WitnessCapsule ownerCapsule = new WitnessCapsule( StringUtil.hexString2ByteString(WITNESS_ADDRESS), diff --git a/framework/src/test/java/org/tron/core/actuator/WithdrawBalanceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/WithdrawBalanceActuatorTest.java index ef979d8acb9..7010b10657a 100644 --- a/framework/src/test/java/org/tron/core/actuator/WithdrawBalanceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/WithdrawBalanceActuatorTest.java @@ -4,26 +4,20 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.args.Witness; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.BalanceInsufficientException; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; @@ -33,51 +27,22 @@ import org.tron.protos.contract.BalanceContract.WithdrawBalanceContract; @Slf4j -public class WithdrawBalanceActuatorTest { +public class WithdrawBalanceActuatorTest extends BaseTest { - private static final String dbPath = "output_withdraw_balance_test"; private static final String OWNER_ADDRESS; private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String OWNER_ACCOUNT_INVALID; private static final long initBalance = 10_000_000_000L; private static final long allowance = 32_000_000L; - private static Manager dbManager; - private static TronApplicationContext context; static { + dbPath = "output_withdraw_balance_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; OWNER_ACCOUNT_INVALID = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - // Args.setParam(new String[]{"--output-directory", dbPath}, - // "config-junit.conf"); - // dbManager = new Manager(); - // dbManager.init(); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java index d3ec771b5fa..1544e546854 100644 --- a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java @@ -7,25 +7,19 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.BalanceInsufficientException; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; @@ -36,54 +30,30 @@ import org.tron.protos.contract.BalanceContract.WithdrawExpireUnfreezeContract; @Slf4j -public class WithdrawExpireUnfreezeActuatorTest { +public class WithdrawExpireUnfreezeActuatorTest extends BaseTest { - private static final String dbPath = "output_withdraw_expire_unfreeze_test"; private static final String OWNER_ADDRESS; private static final String OWNER_ADDRESS_INVALID = "abc"; private static final String OWNER_ACCOUNT_INVALID; private static final long initBalance = 10_000_000_000L; private static final long allowance = 32_000_000L; - private static Manager dbManager; - private static final TronApplicationContext context; static { + dbPath = "output_withdraw_expire_unfreeze_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; OWNER_ACCOUNT_INVALID = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); - dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ @Before public void createAccountCapsule() { + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); + AccountCapsule ownerCapsule = new AccountCapsule(ByteString.copyFromUtf8("owner"), ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), AccountType.Normal, initBalance); diff --git a/framework/src/test/java/org/tron/core/actuator/WitnessCreateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/WitnessCreateActuatorTest.java index 2c85ae00deb..721d88af2b6 100644 --- a/framework/src/test/java/org/tron/core/actuator/WitnessCreateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/WitnessCreateActuatorTest.java @@ -4,24 +4,18 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol.AccountType; @@ -30,10 +24,8 @@ import org.tron.protos.contract.WitnessContract.WitnessCreateContract; @Slf4j +public class WitnessCreateActuatorTest extends BaseTest { -public class WitnessCreateActuatorTest { - - private static final String dbPath = "output_WitnessCreate_test"; private static final String ACCOUNT_NAME_FIRST = "ownerF"; private static final String OWNER_ADDRESS_FIRST; private static final String ACCOUNT_NAME_SECOND = "ownerS"; @@ -42,12 +34,10 @@ public class WitnessCreateActuatorTest { private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String OWNER_ADDRESS_NOACCOUNT; private static final String OWNER_ADDRESS_BALANCENOTSUFFIENT; - private static TronApplicationContext context; - private static Manager dbManager; static { + dbPath = "output_WitnessCreate_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = @@ -58,29 +48,6 @@ public class WitnessCreateActuatorTest { Wallet.getAddressPreFixString() + "548794500882809695a8a687866e06d4271a1ced"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/actuator/WitnessUpdateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/WitnessUpdateActuatorTest.java index bad820cc7bb..31ac6a3cf88 100644 --- a/framework/src/test/java/org/tron/core/actuator/WitnessUpdateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/WitnessUpdateActuatorTest.java @@ -4,24 +4,18 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Protocol; @@ -30,9 +24,8 @@ import org.tron.protos.contract.WitnessContract.WitnessUpdateContract; @Slf4j -public class WitnessUpdateActuatorTest { +public class WitnessUpdateActuatorTest extends BaseTest { - private static final String dbPath = "output_WitnessUpdate_test"; private static final String OWNER_ADDRESS; private static final String OWNER_ADDRESS_ACCOUNT_NAME = "test_account"; private static final String OWNER_ADDRESS_NOT_WITNESS; @@ -41,12 +34,10 @@ public class WitnessUpdateActuatorTest { private static final String URL = "https://tron.network/"; private static final String NewURL = "https://tron.org/"; private static final String OWNER_ADDRESS_INVALID = "aaaa"; - private static TronApplicationContext context; - private static Manager dbManager; static { + dbPath = "output_WitnessUpdate_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_NOTEXIST = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; @@ -54,28 +45,6 @@ public class WitnessUpdateActuatorTest { Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d427122222"; } - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/db/AccountIdIndexStoreTest.java b/framework/src/test/java/org/tron/core/db/AccountIdIndexStoreTest.java index 6e50f3dfca7..fa31b2fd451 100644 --- a/framework/src/test/java/org/tron/core/db/AccountIdIndexStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/AccountIdIndexStoreTest.java @@ -1,23 +1,21 @@ package org.tron.core.db; import com.google.protobuf.ByteString; -import java.io.File; import java.util.Random; -import org.junit.AfterClass; +import javax.annotation.Resource; import org.junit.Assert; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; +import org.tron.common.BaseTest; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.store.AccountIdIndexStore; import org.tron.protos.Protocol.AccountType; -public class AccountIdIndexStoreTest { +public class AccountIdIndexStoreTest extends BaseTest { private static final byte[] ACCOUNT_ADDRESS_ONE = randomBytes(16); private static final byte[] ACCOUNT_ADDRESS_TWO = randomBytes(16); @@ -28,30 +26,21 @@ public class AccountIdIndexStoreTest { private static final byte[] ACCOUNT_NAME_THREE = randomBytes(6); private static final byte[] ACCOUNT_NAME_FOUR = randomBytes(6); private static final byte[] ACCOUNT_NAME_FIVE = randomBytes(6); - private static String dbPath = "output_AccountIndexStore_test"; - private static TronApplicationContext context; - private static AccountIdIndexStore accountIdIndexStore; + @Resource + private AccountIdIndexStore accountIdIndexStore; private static AccountCapsule accountCapsule1; private static AccountCapsule accountCapsule2; private static AccountCapsule accountCapsule3; private static AccountCapsule accountCapsule4; static { + dbPath = "output_AccountIndexStore_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } @BeforeClass public static void init() { - accountIdIndexStore = context.getBean(AccountIdIndexStore.class); accountCapsule1 = new AccountCapsule(ByteString.copyFrom(ACCOUNT_ADDRESS_ONE), ByteString.copyFrom(ACCOUNT_NAME_ONE), AccountType.Normal); accountCapsule1.setAccountId(ByteString.copyFrom(ACCOUNT_NAME_ONE).toByteArray()); @@ -64,6 +53,11 @@ public static void init() { accountCapsule4 = new AccountCapsule(ByteString.copyFrom(ACCOUNT_ADDRESS_FOUR), ByteString.copyFrom(ACCOUNT_NAME_FOUR), AccountType.Normal); accountCapsule4.setAccountId(ByteString.copyFrom(ACCOUNT_NAME_FOUR).toByteArray()); + + } + + @Before + public void before() { accountIdIndexStore.put(accountCapsule1); accountIdIndexStore.put(accountCapsule2); accountIdIndexStore.put(accountCapsule3); diff --git a/framework/src/test/java/org/tron/core/db/AccountIndexStoreTest.java b/framework/src/test/java/org/tron/core/db/AccountIndexStoreTest.java index fd0474f4dee..0b449addc41 100755 --- a/framework/src/test/java/org/tron/core/db/AccountIndexStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/AccountIndexStoreTest.java @@ -1,32 +1,29 @@ package org.tron.core.db; import com.google.protobuf.ByteString; -import java.io.File; -import org.junit.AfterClass; +import javax.annotation.Resource; import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.store.AccountIndexStore; import org.tron.protos.Protocol.AccountType; -public class AccountIndexStoreTest { +public class AccountIndexStoreTest extends BaseTest { - private static String dbPath = "output_AccountIndexStore_test"; private static String dbDirectory = "db_AccountIndexStore_test"; private static String indexDirectory = "index_AccountIndexStore_test"; - private static TronApplicationContext context; - private static AccountIndexStore accountIndexStore; + @Resource + private AccountIndexStore accountIndexStore; private static byte[] address = TransactionStoreTest.randomBytes(32); private static byte[] accountName = TransactionStoreTest.randomBytes(32); static { + dbPath = "output_AccountIndexStore_test"; Args.setParam( new String[]{ "--output-directory", dbPath, @@ -35,19 +32,10 @@ public class AccountIndexStoreTest { }, Constant.TEST_CONF ); - context = new TronApplicationContext(DefaultConfig.class); } - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } - - @BeforeClass - public static void init() { - accountIndexStore = context.getBean(AccountIndexStore.class); + @Before + public void init() { AccountCapsule accountCapsule = new AccountCapsule(ByteString.copyFrom(address), ByteString.copyFrom(accountName), AccountType.forNumber(1)); diff --git a/framework/src/test/java/org/tron/core/db/AccountStoreTest.java b/framework/src/test/java/org/tron/core/db/AccountStoreTest.java index 44efc7f1e97..6c02b038f8e 100755 --- a/framework/src/test/java/org/tron/core/db/AccountStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/AccountStoreTest.java @@ -3,46 +3,39 @@ import static org.junit.Assert.assertEquals; import com.google.protobuf.ByteString; -import java.io.File; import java.util.HashMap; import java.util.Map; - -import org.junit.AfterClass; +import javax.annotation.Resource; import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; -import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.db2.ISession; -import org.tron.core.store.AccountAssetStore; import org.tron.core.store.AccountStore; import org.tron.core.store.AssetIssueStore; import org.tron.core.store.DynamicPropertiesStore; import org.tron.protos.Protocol.AccountType; -public class AccountStoreTest { +public class AccountStoreTest extends BaseTest { private static final byte[] data = TransactionStoreTest.randomBytes(32); - private static String dbPath = "output_AccountStore_test"; private static String dbDirectory = "db_AccountStore_test"; private static String indexDirectory = "index_AccountStore_test"; - private static TronApplicationContext context; - private static AccountStore accountStore; - private static AccountAssetStore accountAssetStore; - private static Manager manager; - private static DynamicPropertiesStore dynamicPropertiesStore; - private static AssetIssueStore assetIssueStore; - private static ChainBaseManager chainBaseManager; + @Resource + private AccountStore accountStore; + @Resource + private DynamicPropertiesStore dynamicPropertiesStore; + @Resource + private AssetIssueStore assetIssueStore; private static byte[] address = TransactionStoreTest.randomBytes(32); private static byte[] accountName = TransactionStoreTest.randomBytes(32); static { + dbPath = "output_AccountStore_test"; Args.setParam( new String[]{ "--output-directory", dbPath, @@ -51,23 +44,10 @@ public class AccountStoreTest { }, Constant.TEST_CONF ); - context = new TronApplicationContext(DefaultConfig.class); - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } - @BeforeClass - public static void init() { - accountStore = context.getBean(AccountStore.class); - accountAssetStore = context.getBean(AccountAssetStore.class); - dynamicPropertiesStore = context.getBean(DynamicPropertiesStore.class); - manager = context.getBean(Manager.class); - chainBaseManager = context.getBean(ChainBaseManager.class); + @Before + public void init() { assetIssueStore = chainBaseManager.getAssetIssueStore(); dynamicPropertiesStore.saveAllowBlackHoleOptimization(1); AccountCapsule accountCapsule = new AccountCapsule(ByteString.copyFrom(address), @@ -149,7 +129,7 @@ public void assetTest() { assertEquals(100, (long)assets.get("200")); accountCapsule.clearAsset(); - try (ISession tmpSession = manager.getRevokingStore().buildSession()) { + try (ISession tmpSession = dbManager.getRevokingStore().buildSession()) { accountCapsule.addAssetAmountV2("100".getBytes(), 1, dynamicPropertiesStore, assetIssueStore); accountCapsule.reduceAssetAmountV2("200".getBytes(), 1, @@ -160,11 +140,11 @@ public void assetTest() { assertEquals(101, accountCapsule.getAssetV2("100")); assertEquals(99, accountCapsule.getAssetV2("200")); - try (ISession tmpSession = manager.getRevokingStore().buildSession()) { + try (ISession tmpSession = dbManager.getRevokingStore().buildSession()) { tmpSession.commit(); } - try (ISession tmpSession = manager.getRevokingStore().buildSession()) { + try (ISession tmpSession = dbManager.getRevokingStore().buildSession()) { accountCapsule.reduceAssetAmountV2("200".getBytes(), 89, dynamicPropertiesStore, assetIssueStore); accountCapsule.addAssetAmountV2("300".getBytes(), 10, @@ -178,7 +158,7 @@ public void assetTest() { assertEquals(10, (long)assets.get("200")); assertEquals(10, (long)assets.get("300")); - try (ISession tmpSession = manager.getRevokingStore().buildSession()) { + try (ISession tmpSession = dbManager.getRevokingStore().buildSession()) { accountCapsule.reduceAssetAmountV2("100".getBytes(), 91, dynamicPropertiesStore, assetIssueStore); accountCapsule.addAssetAmountV2("200".getBytes(), 0, diff --git a/framework/src/test/java/org/tron/core/db/BlockGenerate.java b/framework/src/test/java/org/tron/core/db/BlockGenerate.java index d7a2d21e408..197dd562485 100644 --- a/framework/src/test/java/org/tron/core/db/BlockGenerate.java +++ b/framework/src/test/java/org/tron/core/db/BlockGenerate.java @@ -1,6 +1,7 @@ package org.tron.core.db; import com.google.protobuf.ByteString; +import org.tron.common.BaseTest; import org.tron.common.crypto.ECKey; import org.tron.common.crypto.ECKey.ECDSASignature; import org.tron.common.parameter.CommonParameter; 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 0a5df8bf9bd..cdf8dbcc29c 100644 --- a/framework/src/test/java/org/tron/core/db/BlockStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/BlockStoreTest.java @@ -1,40 +1,19 @@ package org.tron.core.db; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.After; -import org.junit.Before; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; +import org.tron.common.BaseTest; import org.tron.core.Constant; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; @Slf4j -public class BlockStoreTest { +public class BlockStoreTest extends BaseTest { - private static final String dbPath = "output-blockStore-test"; - private static TronApplicationContext context; static { + dbPath = "output-blockStore-test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - } - - BlockStore blockStore; - - @Before - public void init() { - blockStore = context.getBean(BlockStore.class); - } - - @After - public void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } @Test diff --git a/framework/src/test/java/org/tron/core/db/CommonStoreTest.java b/framework/src/test/java/org/tron/core/db/CommonStoreTest.java index 9304be0665e..a745379ee94 100644 --- a/framework/src/test/java/org/tron/core/db/CommonStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/CommonStoreTest.java @@ -1,43 +1,26 @@ package org.tron.core.db; -import java.io.File; -import org.junit.AfterClass; +import javax.annotation.Resource; import org.junit.Assert; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; +import org.tron.common.BaseTest; import org.tron.core.Constant; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -public class CommonStoreTest { - private static String dbPath = "output_CommonStore_test"; +public class CommonStoreTest extends BaseTest { private static String dbDirectory = "db_CommonStore_test"; private static String indexDirectory = "index_CommonStore_test"; - private static TronApplicationContext context; - private static CommonStore commonStore; + @Resource + private CommonStore commonStore; static { + dbPath = "output_CommonStore_test"; Args.setParam(new String[] { "--output-directory", dbPath, "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory}, Constant.TEST_CONF ); - context = new TronApplicationContext(DefaultConfig.class); - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } - - @BeforeClass - public static void init() { - commonStore = context.getBean(CommonStore.class); } @Test diff --git a/framework/src/test/java/org/tron/core/db/EnergyPriceHistoryLoaderTest.java b/framework/src/test/java/org/tron/core/db/EnergyPriceHistoryLoaderTest.java index 13107480bf5..4e7efdd43f1 100644 --- a/framework/src/test/java/org/tron/core/db/EnergyPriceHistoryLoaderTest.java +++ b/framework/src/test/java/org/tron/core/db/EnergyPriceHistoryLoaderTest.java @@ -8,20 +8,14 @@ import static org.tron.core.utils.ProposalUtil.ProposalType.TRANSACTION_FEE; import static org.tron.core.utils.ProposalUtil.ProposalType.WITNESS_127_PAY_PER_BLOCK; -import java.io.File; import java.util.HashMap; import java.util.Map; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; -import org.tron.core.ChainBaseManager; +import org.tron.common.BaseTest; import org.tron.core.Constant; import org.tron.core.capsule.ProposalCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.db.api.EnergyPriceHistoryLoader; import org.tron.core.store.ProposalStore; @@ -30,10 +24,8 @@ @Slf4j -public class EnergyPriceHistoryLoaderTest { +public class EnergyPriceHistoryLoaderTest extends BaseTest { - private static ChainBaseManager chainBaseManager; - private static TronApplicationContext context; private static String dbPath = "output-EnergyPriceHistoryLoaderTest-test"; private static long t1 = 1542607200000L; private static long price1 = 20; @@ -46,23 +38,6 @@ public class EnergyPriceHistoryLoaderTest { static { Args.setParam(new String[] {"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - } - - @BeforeClass - public static void init() { - chainBaseManager = context.getBean(ChainBaseManager.class); - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } public void initDB() { @@ -102,7 +77,7 @@ public void initDB() { initProposal(parameters, 1572609600000L, State.CANCELED); } - private static void initProposal(long code, long timestamp, long price, State state) { + private void initProposal(long code, long timestamp, long price, State state) { long id = chainBaseManager.getDynamicPropertiesStore().getLatestProposalNum() + 1; Proposal proposal = Proposal.newBuilder().putParameters(code, price) @@ -116,7 +91,7 @@ private static void initProposal(long code, long timestamp, long price, State st chainBaseManager.getDynamicPropertiesStore().saveLatestProposalNum(id); } - private static void initProposal(Map parameters, long timestamp, State state) { + private void initProposal(Map parameters, long timestamp, State state) { long id = chainBaseManager.getDynamicPropertiesStore().getLatestProposalNum() + 1; Proposal proposal = Proposal.newBuilder().putAllParameters(parameters) @@ -132,9 +107,6 @@ private static void initProposal(Map parameters, long timestamp, Sta @Test public void testLoader() { - if (chainBaseManager == null) { - init(); - } EnergyPriceHistoryLoader loader = new EnergyPriceHistoryLoader(chainBaseManager); initDB(); @@ -154,10 +126,6 @@ public void testLoader() { @Test public void testProposalEmpty() { - if (chainBaseManager == null) { - init(); - } - // clean DB firstly ProposalStore proposalStore = chainBaseManager.getProposalStore(); proposalStore.forEach( diff --git a/framework/src/test/java/org/tron/core/db/KhaosDatabaseTest.java b/framework/src/test/java/org/tron/core/db/KhaosDatabaseTest.java index 031bb47eba2..87a38927be1 100644 --- a/framework/src/test/java/org/tron/core/db/KhaosDatabaseTest.java +++ b/framework/src/test/java/org/tron/core/db/KhaosDatabaseTest.java @@ -1,25 +1,22 @@ package org.tron.core.db; import com.google.protobuf.ByteString; -import java.io.File; import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.util.List; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.testng.collections.Lists; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.Pair; import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.exception.BadNumberBlockException; import org.tron.core.exception.NonCommonBlockException; @@ -29,28 +26,19 @@ import org.tron.protos.Protocol.BlockHeader.raw; @Slf4j -public class KhaosDatabaseTest { +public class KhaosDatabaseTest extends BaseTest { - private static final String dbPath = "output-khaosDatabase-test"; - private static KhaosDatabase khaosDatabase; - private static TronApplicationContext context; + @Resource + private KhaosDatabase khaosDatabase; static { + dbPath = "output-khaosDatabase-test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); } @BeforeClass public static void init() { Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - khaosDatabase = context.getBean(KhaosDatabase.class); - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } @Test diff --git a/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreTest.java b/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreTest.java index a264b33ee98..f90b5712c56 100755 --- a/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreTest.java @@ -1,22 +1,17 @@ package org.tron.core.db; -import java.io.File; import java.util.List; import lombok.extern.slf4j.Slf4j; import org.junit.After; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.FileUtil; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.MarketOrderIdListCapsule; import org.tron.core.capsule.utils.MarketUtils; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.exception.ItemNotFoundException; import org.tron.core.store.MarketPairPriceToOrderStore; @@ -25,34 +20,11 @@ import org.tron.protos.Protocol.MarketPrice; @Slf4j -public class MarketPairPriceToOrderStoreTest { - - private static final String dbPath = "output-MarketPairPriceToOrderStore-test"; - private static TronApplicationContext context; - private static Manager dbManager; +public class MarketPairPriceToOrderStoreTest extends BaseTest { static { + dbPath = "output-MarketPairPriceToOrderStore-test"; Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - } - - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } @After diff --git a/framework/src/test/java/org/tron/core/db/NullifierStoreTest.java b/framework/src/test/java/org/tron/core/db/NullifierStoreTest.java index 58de5f0747f..5ed2f967a15 100644 --- a/framework/src/test/java/org/tron/core/db/NullifierStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/NullifierStoreTest.java @@ -1,57 +1,48 @@ package org.tron.core.db; -import java.io.File; import java.util.Random; -import org.junit.AfterClass; +import javax.annotation.Resource; import org.junit.Assert; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.tron.common.BaseTest; import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.BytesCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.store.NullifierStore; -public class NullifierStoreTest { +public class NullifierStoreTest extends BaseTest { private static final byte[] NULLIFIER_ONE = randomBytes(32); private static final byte[] NULLIFIER_TWO = randomBytes(32); private static final byte[] TRX_TWO = randomBytes(32); private static final byte[] TRX_TWO_NEW = randomBytes(32); - public static Application AppT; - private static NullifierStore nullifierStore; - private static String dbPath = "output_NullifierStore_test"; - private static TronApplicationContext context; + @Resource + public Application AppT; + @Resource + private NullifierStore nullifierStore; private static BytesCapsule nullifier1; private static BytesCapsule nullifier2; private static BytesCapsule nullifier2New; static { + dbPath = "output_NullifierStore_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - AppT = ApplicationFactory.create(context); - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } @BeforeClass public static void init() { - nullifierStore = context.getBean(NullifierStore.class); nullifier1 = new BytesCapsule(NULLIFIER_ONE); nullifier2 = new BytesCapsule(TRX_TWO); nullifier2New = new BytesCapsule(TRX_TWO_NEW); + } + @Before + public void before() { nullifierStore.put(nullifier1); nullifierStore.put(NULLIFIER_TWO, nullifier2); } 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 c7439d84d82..812f19922ca 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionHistoryTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionHistoryTest.java @@ -1,30 +1,30 @@ package org.tron.core.db; -import java.io.File; -import org.junit.AfterClass; +import javax.annotation.Resource; import org.junit.Assert; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.capsule.TransactionInfoCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.exception.BadItemException; import org.tron.core.store.TransactionHistoryStore; -public class TransactionHistoryTest { +public class TransactionHistoryTest extends BaseTest { private static final byte[] transactionId = TransactionStoreTest.randomBytes(32); - private static String dbPath = "output_TransactionHistoryStore_test"; private static String dbDirectory = "db_TransactionHistoryStore_test"; private static String indexDirectory = "index_TransactionHistoryStore_test"; - private static TronApplicationContext context; - private static TransactionHistoryStore transactionHistoryStore; + @Resource + private TransactionHistoryStore transactionHistoryStore; + + private static TransactionInfoCapsule transactionInfoCapsule; static { + dbPath = "output_TransactionHistoryStore_test"; Args.setParam( new String[]{ "--output-directory", dbPath, @@ -33,25 +33,20 @@ public class TransactionHistoryTest { }, Constant.TEST_CONF ); - context = new TronApplicationContext(DefaultConfig.class); - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } @BeforeClass public static void init() { - transactionHistoryStore = context.getBean(TransactionHistoryStore.class); - TransactionInfoCapsule transactionInfoCapsule = new TransactionInfoCapsule(); - + transactionInfoCapsule = new TransactionInfoCapsule(); transactionInfoCapsule.setId(transactionId); transactionInfoCapsule.setFee(1000L); transactionInfoCapsule.setBlockNumber(100L); transactionInfoCapsule.setBlockTimeStamp(200L); + + } + + @Before + public void before() { transactionHistoryStore.put(transactionId, transactionInfoCapsule); } diff --git a/framework/src/test/java/org/tron/core/db/TransactionRetStoreTest.java b/framework/src/test/java/org/tron/core/db/TransactionRetStoreTest.java index c4a629b12bc..04478f2c261 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionRetStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionRetStoreTest.java @@ -1,52 +1,44 @@ package org.tron.core.db; -import java.io.File; -import org.junit.AfterClass; +import javax.annotation.Resource; import org.junit.Assert; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.TransactionInfoCapsule; import org.tron.core.capsule.TransactionRetCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.exception.BadItemException; import org.tron.core.store.TransactionRetStore; import org.tron.protos.Protocol.Transaction; -public class TransactionRetStoreTest { +public class TransactionRetStoreTest extends BaseTest { private static final byte[] transactionId = TransactionStoreTest.randomBytes(32); private static final byte[] blockNum = ByteArray.fromLong(1); - private static String dbPath = "output_TransactionRetStore_test"; private static String dbDirectory = "db_TransactionRetStore_test"; private static String indexDirectory = "index_TransactionRetStore_test"; - private static TronApplicationContext context; - private static TransactionRetStore transactionRetStore; + @Resource + private TransactionRetStore transactionRetStore; private static Transaction transaction; - private static TransactionStore transactionStore; + @Resource + private TransactionStore transactionStore; + + private static TransactionCapsule transactionCapsule; + private static TransactionRetCapsule transactionRetCapsule; static { + dbPath = "output_TransactionRetStore_test"; Args.setParam(new String[]{"--output-directory", dbPath, "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } @BeforeClass public static void init() { - transactionRetStore = context.getBean(TransactionRetStore.class); - transactionStore = context.getBean(TransactionStore.class); TransactionInfoCapsule transactionInfoCapsule = new TransactionInfoCapsule(); transactionInfoCapsule.setId(transactionId); @@ -54,12 +46,18 @@ public static void init() { transactionInfoCapsule.setBlockNumber(100L); transactionInfoCapsule.setBlockTimeStamp(200L); - TransactionRetCapsule transactionRetCapsule = new TransactionRetCapsule(); + transactionRetCapsule = new TransactionRetCapsule(); transactionRetCapsule.addTransactionInfo(transactionInfoCapsule.getInstance()); - transactionRetStore.put(blockNum, transactionRetCapsule); + transaction = Transaction.newBuilder().build(); - TransactionCapsule transactionCapsule = new TransactionCapsule(transaction); + transactionCapsule = new TransactionCapsule(transaction); transactionCapsule.setBlockNum(1); + + } + + @Before + public void before() { + transactionRetStore.put(blockNum, transactionRetCapsule); transactionStore.put(transactionId, transactionCapsule); } diff --git a/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java b/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java index 7993ee5b19c..471a994d4dd 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java @@ -1,26 +1,21 @@ package org.tron.core.db; import com.google.protobuf.ByteString; -import java.io.File; import java.util.Random; -import org.junit.AfterClass; +import javax.annotation.Resource; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.tron.common.BaseTest; import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; import org.tron.common.crypto.ECKey; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.Sha256Hash; -import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.exception.BadItemException; import org.tron.core.exception.ItemNotFoundException; @@ -32,7 +27,7 @@ import org.tron.protos.contract.WitnessContract.VoteWitnessContract.Vote; import org.tron.protos.contract.WitnessContract.WitnessCreateContract; -public class TransactionStoreTest { +public class TransactionStoreTest extends BaseTest { private static final byte[] key1 = TransactionStoreTest.randomBytes(21); private static final byte[] key2 = TransactionStoreTest.randomBytes(21); @@ -45,35 +40,21 @@ public class TransactionStoreTest { private static final long AMOUNT = 100; private static final String WITNESS_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; - private static String dbPath = "output_TransactionStore_test"; private static String dbDirectory = "db_TransactionStore_test"; private static String indexDirectory = "index_TransactionStore_test"; - private static TransactionStore transactionStore; - private static TronApplicationContext context; - private static Application AppT; - private static ChainBaseManager chainBaseManager; + @Resource + private TransactionStore transactionStore; + @Resource + private Application AppT; /** * Init data. */ @BeforeClass public static void init() { + dbPath = "output_TransactionStore_test"; Args.setParam(new String[]{"--output-directory", dbPath, "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory, "-w"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - AppT = ApplicationFactory.create(context); - chainBaseManager = context.getBean(ChainBaseManager.class); - transactionStore = chainBaseManager.getTransactionStore(); - } - - /** - * release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } /** diff --git a/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java b/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java index cb47bce4df6..d37b3d3d3a9 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java @@ -18,22 +18,17 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; -import java.io.File; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.RuntimeImpl; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Commons; -import org.tron.common.utils.FileUtil; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.ContractCapsule; import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.exception.BalanceInsufficientException; import org.tron.core.exception.ContractExeException; @@ -53,58 +48,18 @@ import org.tron.protos.contract.SmartContractOuterClass.SmartContract; import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; -public class TransactionTraceTest { +public class TransactionTraceTest extends BaseTest { public static final long totalBalance = 1000_0000_000_000L; - private static String dbPath = "output_TransactionTrace_test"; private static String dbDirectory = "db_TransactionTrace_test"; private static String indexDirectory = "index_TransactionTrace_test"; - private static AnnotationConfigApplicationContext context; - private static Manager dbManager; private static ByteString ownerAddress = ByteString.copyFrom(ByteArray.fromInt(1)); private static ByteString contractAddress = ByteString.copyFrom(ByteArray.fromInt(2)); - - /* - * DeployContract tracetestContract [{"constant":false,"inputs":[{"name":"accountId","type": - * "uint256"}],"name":"getVoters","outputs":[{"name":"","type":"uint256"}],"payable":false," - * stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type" - * :"uint256"}],"name":"voters","outputs":[{"name":"","type":"uint256"}],"payable":false, - * "stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"vote","type" - * :"uint256"}],"name":"addVoters","outputs":[],"payable":false,"stateMutability":"nonpayable", - * "type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type": - * "constructor"}] 608060405234801561001057600080fd5b5060015b620186a081101561003857600081815260 - * 2081905260409020819055600a01610014565b5061010b806100486000396000f300608060405260043610605257 - * 63ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166386b646f281 - * 146057578063da58c7d914607e578063eb91a5ff146093575b600080fd5b348015606257600080fd5b50606c6004 - * 3560aa565b60408051918252519081900360200190f35b348015608957600080fd5b50606c60043560bc565b3480 - * 15609e57600080fd5b5060a860043560ce565b005b60009081526020819052604090205490565b60006020819052 - * 908152604090205481565b6000818152602081905260409020555600a165627a7a72305820f9935f89890e51bcf3 - * ea98fa4841c91ac5957a197d99eeb7879a775b30ee9a2d0029 1000000000 100 - * */ - /* - * DeployContract tracetestContract [{"constant":false,"inputs":[{"name":"accountId","type": - * "uint256"}],"name":"getVoters","outputs":[{"name":"","type":"uint256"}],"payable":false, - * "stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"", - * "type":"uint256"}],"name":"voters","outputs":[{"name":"","type":"uint256"}],"payable":false, - * "stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"vote","type" - * :"uint256"}],"name":"addVoters","outputs":[],"payable":false,"stateMutability":"nonpayable", - * "type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type": - * "constructor"}] 608060405234801561001057600080fd5b5060015b620186a08110156100385760008181526020 - * 81905260409020819055600a01610014565b5061010b806100486000396000f30060806040526004361060525763ff - * ffffff7c010000000000000000000000000000000000000000000000000000000060003504166386b646f281146057 - * 578063da58c7d914607e578063eb91a5ff146093575b600080fd5b348015606257600080fd5b50606c60043560aa56 - * 5b60408051918252519081900360200190f35b348015608957600080fd5b50606c60043560bc565b348015609e576 - * 00080fd5b5060a860043560ce565b005b60009081526020819052604090205490565b6000602081905290815260409 - * 0205481565b6000818152602081905260409020555600a165627a7a72305820f9935f89890e51bcf3ea98fa4841c91 - * ac5957a197d99eeb7879a775b30ee9a2d0029 1000000000 40 - * */ private static String OwnerAddress = "TCWHANtDDdkZCTo2T2peyEq3Eg9c2XB7ut"; private static String TriggerOwnerAddress = "TCSgeWapPJhCqgWRxXCKb6jJ5AgNWSGjPA"; - /* - * triggercontract TPMBUANrTwwQAPwShn7ZZjTJz1f3F8jknj addVoters(uint256) 113 false 1000000000 0 - * */ static { + dbPath = "output_TransactionTrace_test"; Args.setParam( new String[]{ "--output-directory", dbPath, @@ -115,15 +70,13 @@ public class TransactionTraceTest { }, "config-test-mainnet.conf" ); - context = new TronApplicationContext(DefaultConfig.class); } /** * Init data. */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); + @Before + public void init() { //init energy dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(1526647838000L); dbManager.getDynamicPropertiesStore().saveTotalEnergyWeight(100_000L); @@ -132,16 +85,6 @@ public static void init() { } - /** - * destroy clear data of testing. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } - @Test public void testUseFee() throws InvalidProtocolBufferException, VMIllegalException, BalanceInsufficientException, diff --git a/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java b/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java index 7d9bbcd5ad2..8b1724248a0 100644 --- a/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java +++ b/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java @@ -1,26 +1,20 @@ package org.tron.core.db; -import java.io.File; -import org.junit.AfterClass; +import javax.annotation.Resource; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.tron.common.BaseTest; import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.capsule.BytesCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.keystore.Wallet; -public class TxCacheDBTest { - private static final String dbPath = "output_TransactionCache_test"; - - private static TronApplicationContext context; - private static Manager dbManager; +public class TxCacheDBTest extends BaseTest { + @Resource + private Application appT; /** * Init data. @@ -29,21 +23,9 @@ public class TxCacheDBTest { public static void init() { String dbDirectory = "db_TransactionCache_test"; String indexDirectory = "index_TransactionCache_test"; + dbPath = "output_TransactionCache_test"; Args.setParam(new String[]{"--output-directory", dbPath, "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory, "-w"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - Application appT = ApplicationFactory.create(context); - dbManager = context.getBean(Manager.class); - } - - /** - * release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } @Test diff --git a/framework/src/test/java/org/tron/core/db/VotesStoreTest.java b/framework/src/test/java/org/tron/core/db/VotesStoreTest.java index 55b0a4882e3..9e5cd7c0098 100755 --- a/framework/src/test/java/org/tron/core/db/VotesStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/VotesStoreTest.java @@ -1,47 +1,30 @@ package org.tron.core.db; import com.google.protobuf.ByteString; -import java.io.File; import java.util.ArrayList; import java.util.List; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; +import org.tron.common.BaseTest; import org.tron.core.Constant; import org.tron.core.capsule.VotesCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.store.VotesStore; import org.tron.protos.Protocol.Vote; @Slf4j -public class VotesStoreTest { +public class VotesStoreTest extends BaseTest { - private static final String dbPath = "output-votesStore-test"; - private static TronApplicationContext context; static { + dbPath = "output-votesStore-test"; Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); } - VotesStore votesStore; - - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } - - @Before - public void initDb() { - this.votesStore = context.getBean(VotesStore.class); - } + @Resource + private VotesStore votesStore; @Test public void putAndGetVotes() { diff --git a/framework/src/test/java/org/tron/core/db/WitnessStoreTest.java b/framework/src/test/java/org/tron/core/db/WitnessStoreTest.java index 5ae37650b6a..fd91e7da72a 100755 --- a/framework/src/test/java/org/tron/core/db/WitnessStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/WitnessStoreTest.java @@ -1,44 +1,26 @@ package org.tron.core.db; import com.google.protobuf.ByteString; -import java.io.File; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; +import org.tron.common.BaseTest; import org.tron.core.Constant; import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.store.WitnessStore; @Slf4j -public class WitnessStoreTest { - - private static final String dbPath = "output-witnessStore-test"; - private static TronApplicationContext context; +public class WitnessStoreTest extends BaseTest { static { + dbPath = "output-witnessStore-test"; Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); } - WitnessStore witnessStore; - - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } - - @Before - public void initDb() { - this.witnessStore = context.getBean(WitnessStore.class); - } + @Resource + private WitnessStore witnessStore; @Test public void putAndGetWitness() { From 39d2690990480770deed11b853051a64b0a41b50 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Sat, 28 Jan 2023 18:48:14 +0800 Subject: [PATCH 0572/1197] fix(unitTest): replace context with spring test config --- .../tron/core/db2/core/SnapshotManager.java | 2 + .../test/java/org/tron/common/BaseTest.java | 5 +- .../tron/common/runtime/InheritanceTest.java | 46 +----- .../InternalTransactionComplexTest.java | 42 +---- .../common/runtime/ProgramResultTest.java | 64 +++----- .../tron/common/runtime/RuntimeImplTest.java | 83 +++------- .../runtime/RuntimeTransferComplexTest.java | 59 +------ .../vm/BandWidthRuntimeOutOfTimeTest.java | 49 ++---- ...andWidthRuntimeOutOfTimeWithCheckTest.java | 51 ++---- .../runtime/vm/BandWidthRuntimeTest.java | 61 +++---- .../vm/BandWidthRuntimeWithCheckTest.java | 74 +++------ .../tron/common/runtime/vm/BatchSendTest.java | 69 ++------ .../tron/common/runtime/vm/ChargeTest.java | 98 +++-------- .../runtime/vm/EnergyWhenAssertStyleTest.java | 94 +++-------- .../vm/EnergyWhenRequireStyleTest.java | 111 ++++--------- .../vm/EnergyWhenSendAndTransferTest.java | 59 ++----- .../vm/EnergyWhenTimeoutStyleTest.java | 48 ++---- .../common/runtime/vm/OperationsTest.java | 46 ++---- .../runtime/vm/PrecompiledContractsTest.java | 53 +----- .../PrecompiledContractsVerifyProofTest.java | 37 +---- .../common/runtime/vm/RepositoryTest.java | 67 +++----- .../common/runtime/vm/TimeBenchmarkTest.java | 46 ++---- .../runtime/vm/TransferToAccountTest.java | 45 +---- .../common/runtime/vm/TransferTokenTest.java | 40 +---- .../vm/ValidateMultiSignContractTest.java | 43 ++--- .../test/java/org/tron/core/WalletTest.java | 6 +- .../actuator/VoteWitnessActuatorTest.java | 13 +- .../core/actuator/utils/ProposalUtilTest.java | 143 +++++++--------- .../actuator/utils/TransactionUtilTest.java | 104 +++++------- .../actuator/utils/ZenChainParamsTest.java | 80 +++------ .../tron/core/capsule/AccountCapsuleTest.java | 60 +++---- .../core/capsule/ExchangeCapsuleTest.java | 53 +----- .../core/capsule/TransactionCapsuleTest.java | 39 +---- .../core/capsule/utils/AssetUtilTest.java | 31 +--- .../capsule/utils/ExchangeProcessorTest.java | 38 +---- .../core/db/EnergyPriceHistoryLoaderTest.java | 2 +- .../core/db/api/AssetUpdateHelperTest.java | 42 ++--- .../tron/core/db/backup/BackupDbUtilTest.java | 79 +++------ .../core/jsonrpc/BuildTransactionTest.java | 38 +---- .../tron/core/jsonrpc/JsonrpcServiceTest.java | 45 ++--- .../core/jsonrpc/SectionBloomStoreTest.java | 32 +--- .../tron/core/jsonrpc/WalletCursorTest.java | 43 ++--- .../prometheus/PrometheusApiServiceTest.java | 82 +++------- .../messagehandler/BlockMsgHandlerTest.java | 37 ++--- .../core/net/services/AdvServiceTest.java | 37 +---- .../core/net/services/RelayServiceTest.java | 41 ++--- .../java/org/tron/core/pbft/PbftApiTest.java | 49 ++---- .../core/services/ProposalServiceTest.java | 55 +++---- .../filter/HttpApiAccessFilterTest.java | 75 +++------ .../LiteFnQueryGrpcInterceptorTest.java | 8 +- .../filter/LiteFnQueryHttpFilterTest.java | 68 +++----- .../filter/RpcApiAccessInterceptorTest.java | 8 +- .../org/tron/core/services/http/UtilTest.java | 33 +--- .../core/witness/ProposalControllerTest.java | 48 ++---- .../core/witness/WitnessControllerTest.java | 38 +---- .../tron/core/zksnark/LibrustzcashTest.java | 154 ++++++++---------- .../core/zksnark/MerkleContainerTest.java | 50 ++---- .../org/tron/core/zksnark/MerkleTreeTest.java | 40 +---- .../tron/core/zksnark/NoteEncDecryTest.java | 38 +---- .../tron/core/zksnark/SendCoinShieldTest.java | 49 ++---- .../core/zksnark/ShieldedReceiveTest.java | 63 ++----- .../tron/program/AccountVoteWitnessTest.java | 45 +---- .../tron/program/LiteFullNodeToolTest.java | 33 ++-- .../org/tron/program/SolidityNodeTest.java | 4 - 64 files changed, 913 insertions(+), 2382 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java index fe59a2737dd..97210e9ae07 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java @@ -16,6 +16,7 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; @@ -122,6 +123,7 @@ public void close() { exitThread.interrupt(); // help GC exitThread = null; + flushServices.values().forEach(ExecutorService::shutdown); } catch (Exception e) { logger.warn("exitThread interrupt error", e); } diff --git a/framework/src/test/java/org/tron/common/BaseTest.java b/framework/src/test/java/org/tron/common/BaseTest.java index f7d453013b4..1826dddea64 100644 --- a/framework/src/test/java/org/tron/common/BaseTest.java +++ b/framework/src/test/java/org/tron/common/BaseTest.java @@ -4,6 +4,7 @@ import java.io.File; import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.junit.AfterClass; import org.junit.runner.RunWith; import org.springframework.test.annotation.DirtiesContext; @@ -28,7 +29,6 @@ public abstract class BaseTest { protected static String dbPath; - @Resource protected Manager dbManager; @Resource @@ -37,7 +37,7 @@ public abstract class BaseTest { @AfterClass public static void destroy() { Args.clearParam(); - if (FileUtil.deleteDir(new File(dbPath))) { + if (StringUtils.isNotEmpty(dbPath) && FileUtil.deleteDir(new File(dbPath))) { logger.info("Release resources successful."); } else { logger.info("Release resources failure."); @@ -81,5 +81,4 @@ public Protocol.Block getSignedBlock(ByteString witness, long time, byte[] priva return block.toBuilder().setBlockHeader(blockHeader).build(); } - } diff --git a/framework/src/test/java/org/tron/common/runtime/InheritanceTest.java b/framework/src/test/java/org/tron/common/runtime/InheritanceTest.java index f5101af19af..c3d00ecf2c4 100644 --- a/framework/src/test/java/org/tron/common/runtime/InheritanceTest.java +++ b/framework/src/test/java/org/tron/common/runtime/InheritanceTest.java @@ -1,21 +1,14 @@ package org.tron.common.runtime; -import java.io.File; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.AfterClass; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; import org.testng.Assert; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; +import org.tron.common.BaseTest; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; @@ -25,54 +18,31 @@ import org.tron.protos.Protocol.AccountType; @Slf4j -public class InheritanceTest { +public class InheritanceTest extends BaseTest { - private static final String dbPath = "output_InheritanceTest"; private static final String OWNER_ADDRESS; - private static Runtime runtime; - private static Manager dbManager; - private static TronApplicationContext context; - private static Application appT; - private static RepositoryImpl repository; + private RepositoryImpl repository; static { + dbPath = "output_InheritanceTest"; Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - appT = ApplicationFactory.create(context); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; } /** * Init data. */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); + @Before + public void init() { repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); repository.addBalance(Hex.decode(OWNER_ADDRESS), 100000000); } - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * pragma solidity ^0.4.19; - * * contract foo { uint256 public id=10; function getNumber() returns (uint256){return 100;} * function getName() returns (string){ return "foo"; } } - * * contract bar is foo { function getName() returns (string) { return "bar"; } function getId() * returns(uint256){return id;} } */ @@ -119,7 +89,7 @@ public void inheritanceTest() /* ========================== CALL getName() return child value ============================= */ byte[] triggerData1 = TvmTestUtils.parseAbi("getName()", ""); - runtime = TvmTestUtils + Runtime runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(callerAddress, contractAddress, triggerData1, 0, 1000000, repository, null); diff --git a/framework/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java b/framework/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java index 22fb44bfacf..ca05cb8d3ac 100644 --- a/framework/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java +++ b/framework/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java @@ -1,22 +1,15 @@ package org.tron.common.runtime; -import java.io.File; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.AfterClass; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; import org.testng.Assert; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.vm.DataWord; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; @@ -26,55 +19,33 @@ import org.tron.protos.Protocol.AccountType; @Slf4j -public class InternalTransactionComplexTest { +public class InternalTransactionComplexTest extends BaseTest { - private static final String dbPath = "output_InternalTransactionComplexTest"; private static final String OWNER_ADDRESS; private static Runtime runtime; - private static Manager dbManager; - private static TronApplicationContext context; - private static Application appT; private static RepositoryImpl repository; static { + dbPath = "output_InternalTransactionComplexTest"; Args.setParam(new String[]{"--output-directory", dbPath, "--debug", "--support-constant"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - appT = ApplicationFactory.create(context); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; } /** * Init data. */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); + @Before + public void init() { repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); repository.addBalance(Hex.decode(OWNER_ADDRESS), 100000000); } - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * pragma solidity 0.4.24; - * * // this is to test wither the TVM is returning vars from one contract calling another // * contract's functions. - * * contract callerContract { // lets set up our instance of the new contract calledContract * CALLED_INSTANCE; // lets set the contract instance address in the constructor * constructor(address _addr) public { CALLED_INSTANCE = calledContract(_addr); } // lets create a @@ -85,7 +56,6 @@ public static void destroy() { * in to temp vars (bool _bool, uint256 _uint, bytes32 _bytes32) = CALLED_INSTANCE.testReturns(); * // lets write those temp vars to state testCallbackReturns_.someBool = _bool; * testCallbackReturns_.someUint = _uint; testCallbackReturns_.someBytes32 = _bytes32; } } - * * contract calledContract { function testReturns() external pure returns(bool, uint256, bytes32) * { return(true, 314159, 0x123456); } } */ diff --git a/framework/src/test/java/org/tron/common/runtime/ProgramResultTest.java b/framework/src/test/java/org/tron/common/runtime/ProgramResultTest.java index 8fa590eb4d8..be54826cf5b 100644 --- a/framework/src/test/java/org/tron/common/runtime/ProgramResultTest.java +++ b/framework/src/test/java/org/tron/common/runtime/ProgramResultTest.java @@ -3,29 +3,23 @@ import static org.tron.core.capsule.utils.TransactionUtil.buildTransactionInfoInstance; import static org.tron.core.utils.TransactionUtil.generateContractAddress; -import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.AfterClass; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; import org.testng.Assert; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.vm.DataWord; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.TransactionInfoCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.db.TransactionTrace; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; @@ -41,22 +35,17 @@ @Slf4j -public class ProgramResultTest { +public class ProgramResultTest extends BaseTest { - private static final String dbPath = "output_InternalTransactionComplexTest"; private static final String OWNER_ADDRESS; private static final String TRANSFER_TO; private static Runtime runtime; - private static Manager dbManager; - private static TronApplicationContext context; - private static Application appT; private static RepositoryImpl repository; static { + dbPath = "output_InternalTransactionComplexTest"; Args.setParam(new String[]{"--output-directory", dbPath, "--debug", "--support-constant"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - appT = ApplicationFactory.create(context); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; TRANSFER_TO = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; } @@ -64,9 +53,8 @@ public class ProgramResultTest { /** * Init data. */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); + @Before + public void init() { repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); repository.addBalance(Hex.decode(OWNER_ADDRESS), 100000000); @@ -75,20 +63,6 @@ public static void init() { repository.commit(); } - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * pragma solidity ^0.4.8; contract B{ address public calledAddress; constructor (address d) * payable{calledAddress = d;} function setB() payable returns(address,address){ calledContract c1 @@ -127,8 +101,8 @@ public void uniqueInternalTransactionHashTest() internalTransaction -> hashList.add(Hex.toHexString(internalTransaction.getHash()))); // No dup List dupHash = hashList.stream() - .collect(Collectors.toMap(e -> e, e -> 1, (a, b) -> a + b)).entrySet().stream() - .filter(entry -> entry.getValue() > 1).map(entry -> entry.getKey()) + .collect(Collectors.toMap(e -> e, e -> 1, Integer::sum)).entrySet().stream() + .filter(entry -> entry.getValue() > 1).map(Map.Entry::getKey) .collect(Collectors.toList()); Assert.assertEquals(dupHash.size(), 0); } @@ -307,27 +281,27 @@ public void successAndFailResultTest() new DataWord(internalTransactionsList.get(0).getTransferToAddress()).getLast20Bytes(), new DataWord(bContract).getLast20Bytes()); Assert.assertEquals(internalTransactionsList.get(0).getNote(), "create"); - Assert.assertEquals(internalTransactionsList.get(0).isRejected(), false); + Assert.assertFalse(internalTransactionsList.get(0).isRejected()); Assert.assertEquals(internalTransactionsList.get(1).getValue(), 5); Assert.assertEquals(internalTransactionsList.get(1).getSender(), aContract); Assert.assertEquals( new DataWord(internalTransactionsList.get(1).getTransferToAddress()).getLast20Bytes(), new DataWord(bContract).getLast20Bytes()); Assert.assertEquals(internalTransactionsList.get(1).getNote(), "call"); - Assert.assertEquals(internalTransactionsList.get(1).isRejected(), false); + Assert.assertFalse(internalTransactionsList.get(1).isRejected()); Assert.assertEquals(internalTransactionsList.get(2).getValue(), 0); Assert.assertEquals(internalTransactionsList.get(2).getSender(), aContract); Assert.assertEquals( new DataWord(internalTransactionsList.get(2).getTransferToAddress()).getLast20Bytes(), new DataWord(bContract).getLast20Bytes()); Assert.assertEquals(internalTransactionsList.get(2).getNote(), "call"); - Assert.assertEquals(internalTransactionsList.get(2).isRejected(), false); + Assert.assertFalse(internalTransactionsList.get(2).isRejected()); Assert.assertEquals(internalTransactionsList.get(3).getValue(), 1); Assert.assertEquals(new DataWord(internalTransactionsList.get(3).getSender()).getLast20Bytes(), new DataWord(bContract).getLast20Bytes()); Assert.assertEquals(internalTransactionsList.get(3).getTransferToAddress(), cContract); Assert.assertEquals(internalTransactionsList.get(3).getNote(), "call"); - Assert.assertEquals(internalTransactionsList.get(3).isRejected(), false); + Assert.assertFalse(internalTransactionsList.get(3).isRejected()); checkTransactionInfo(traceSuccess, trx1, null, internalTransactionsList); // ======================================= Test Fail ======================================= @@ -352,28 +326,28 @@ public void successAndFailResultTest() new DataWord(internalTransactionsListFail.get(0).getTransferToAddress()).getLast20Bytes(), new DataWord(bContract2).getLast20Bytes()); Assert.assertEquals(internalTransactionsListFail.get(0).getNote(), "create"); - Assert.assertEquals(internalTransactionsListFail.get(0).isRejected(), true); + Assert.assertTrue(internalTransactionsListFail.get(0).isRejected()); Assert.assertEquals(internalTransactionsListFail.get(1).getValue(), 5); Assert.assertEquals(internalTransactionsListFail.get(1).getSender(), aContract); Assert.assertEquals( new DataWord(internalTransactionsListFail.get(1).getTransferToAddress()).getLast20Bytes(), new DataWord(bContract2).getLast20Bytes()); Assert.assertEquals(internalTransactionsListFail.get(1).getNote(), "call"); - Assert.assertEquals(internalTransactionsListFail.get(1).isRejected(), true); + Assert.assertTrue(internalTransactionsListFail.get(1).isRejected()); Assert.assertEquals(internalTransactionsListFail.get(2).getValue(), 0); Assert.assertEquals(internalTransactionsListFail.get(2).getSender(), aContract); Assert.assertEquals( new DataWord(internalTransactionsListFail.get(2).getTransferToAddress()).getLast20Bytes(), new DataWord(bContract2).getLast20Bytes()); Assert.assertEquals(internalTransactionsListFail.get(2).getNote(), "call"); - Assert.assertEquals(internalTransactionsListFail.get(2).isRejected(), true); + Assert.assertTrue(internalTransactionsListFail.get(2).isRejected()); Assert.assertEquals(internalTransactionsListFail.get(3).getValue(), 1); Assert.assertEquals( new DataWord(internalTransactionsListFail.get(3).getSender()).getLast20Bytes(), new DataWord(bContract2).getLast20Bytes()); Assert.assertEquals(internalTransactionsListFail.get(3).getTransferToAddress(), cContract); Assert.assertEquals(internalTransactionsListFail.get(3).getNote(), "call"); - Assert.assertEquals(internalTransactionsListFail.get(3).isRejected(), true); + Assert.assertTrue(internalTransactionsListFail.get(3).isRejected()); checkTransactionInfo(traceFailed, trx2, null, internalTransactionsListFail); } @@ -520,14 +494,14 @@ public void suicideResultTest() .getInternalTransactions(); Assert .assertEquals(dbManager.getAccountStore().get(Hex.decode(TRANSFER_TO)).getBalance(), 1000); - Assert.assertEquals(dbManager.getAccountStore().get(suicideContract), null); + Assert.assertNull(dbManager.getAccountStore().get(suicideContract)); Assert.assertEquals(internalTransactionsList.get(0).getValue(), 1000); Assert.assertEquals(new DataWord(internalTransactionsList.get(0).getSender()).getLast20Bytes(), new DataWord(suicideContract).getLast20Bytes()); Assert.assertEquals(internalTransactionsList.get(0).getTransferToAddress(), Hex.decode(TRANSFER_TO)); Assert.assertEquals(internalTransactionsList.get(0).getNote(), "suicide"); - Assert.assertEquals(internalTransactionsList.get(0).isRejected(), false); + Assert.assertFalse(internalTransactionsList.get(0).isRejected()); checkTransactionInfo(trace, trx, null, internalTransactionsList); } diff --git a/framework/src/test/java/org/tron/common/runtime/RuntimeImplTest.java b/framework/src/test/java/org/tron/common/runtime/RuntimeImplTest.java index cd23edbcb5e..04b08d3a58d 100644 --- a/framework/src/test/java/org/tron/common/runtime/RuntimeImplTest.java +++ b/framework/src/test/java/org/tron/common/runtime/RuntimeImplTest.java @@ -3,26 +3,19 @@ import static org.tron.common.runtime.TvmTestUtils.generateDeploySmartContractAndGetTransaction; import static org.tron.common.runtime.TvmTestUtils.generateTriggerSmartContractAndGetTransaction; -import java.io.File; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.After; import org.junit.Before; import org.junit.Test; import org.testng.Assert; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; +import org.tron.common.BaseTest; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.actuator.VMActuator; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.ContractCapsule; import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.db.TransactionContext; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; @@ -38,31 +31,28 @@ @Slf4j -public class RuntimeImplTest { +public class RuntimeImplTest extends BaseTest { - private Manager dbManager; - private TronApplicationContext context; private Repository repository; - private String dbPath = "output_RuntimeImplTest"; - private Application AppT; - private byte[] callerAddress; - private long callerTotalBalance = 4_000_000_000L; - private byte[] creatorAddress; - private long creatorTotalBalance = 3_000_000_000L; + private static final byte[] callerAddress; + private final long callerTotalBalance = 4_000_000_000L; + private static final byte[] creatorAddress; + private final long creatorTotalBalance = 3_000_000_000L; - /** - * Init data. - */ - @Before - public void init() { + static { + dbPath = "output_RuntimeImplTest"; Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - AppT = ApplicationFactory.create(context); callerAddress = Hex .decode(Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"); creatorAddress = Hex .decode(Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abd"); - dbManager = context.getBean(Manager.class); + } + + /** + * Init data. + */ + @Before + public void init() { dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(1526647838000L); dbManager.getDynamicPropertiesStore().saveTotalEnergyWeight(5_000_000_000L); // unit is trx repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); @@ -117,11 +107,10 @@ public void getCreatorEnergyLimit2Test() throws ContractValidateException, Contr + "060018201915060aa565b505050565b600080600091505b8282101560e1576001905060018201915060cc56" + "5b5050505600a165627a7a72305820267cf0ebf31051a92ff62bed7490045b8063be9f1e1a22d07dce25765" + "4c8c17b0029"; - String libraryAddressPair = null; Transaction trx = generateDeploySmartContractAndGetTransaction(contractName, creatorAddress, ABI, - code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair); + code, value, feeLimit, consumeUserResourcePercent, null); RuntimeImpl runtimeImpl = new RuntimeImpl(); runtimeImpl.execute( @@ -167,7 +156,6 @@ public void getCreatorEnergyLimit2Test() throws ContractValidateException, Contr expectEnergyLimit4); feeLimit = 3_000_000_000L; - value = 10L; long expectEnergyLimit5 = 20_009_999L; Assert.assertEquals( ((VMActuator) runtimeImpl.getActuator2()) @@ -175,7 +163,6 @@ public void getCreatorEnergyLimit2Test() throws ContractValidateException, Contr expectEnergyLimit5); feeLimit = 3_000L; - value = 10L; long expectEnergyLimit6 = 30L; Assert.assertEquals( ((VMActuator) runtimeImpl.getActuator2()) @@ -207,11 +194,10 @@ public void getCallerAndCreatorEnergyLimit2With0PercentTest() + "060018201915060aa565b505050565b600080600091505b8282101560e1576001905060018201915060cc56" + "5b5050505600a165627a7a72305820267cf0ebf31051a92ff62bed7490045b8063be9f1e1a22d07dce25765" + "4c8c17b0029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractWithCreatorEnergyLimitAndReturnTvmTestResult(contractName, creatorAddress, ABI, code, value, - feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null, + feeLimit, consumeUserResourcePercent, null, dbManager, null, creatorEnergyLimit); byte[] contractAddress = result.getContractAddress(); @@ -229,8 +215,6 @@ public void getCallerAndCreatorEnergyLimit2With0PercentTest() AccountCapsule callerAccount = repository.getAccount(callerAddress); TriggerSmartContract contract = ContractCapsule.getTriggerContractFromTransaction(trx); - feeLimit = 1_000_000_000L; - value = 0L; long expectEnergyLimit1 = 10_000_000L; Assert.assertEquals( ((VMActuator) runtimeImpl.getActuator2()) @@ -245,8 +229,6 @@ public void getCallerAndCreatorEnergyLimit2With0PercentTest() repository.putAccountValue(creatorAddress, creatorAccount); repository.commit(); - feeLimit = 1_000_000_000L; - value = 0L; long expectEnergyLimit2 = 10_005_000L; Assert.assertEquals( ((VMActuator) runtimeImpl.getActuator2()) @@ -277,8 +259,6 @@ public void getCallerAndCreatorEnergyLimit2With0PercentTest() repository.putAccountValue(callerAddress, callerAccount); repository.commit(); - value = 10L; - feeLimit = 5_000_000_000L; long expectEnergyLimit5 = 30_014_999L; Assert.assertEquals( ((VMActuator) runtimeImpl.getActuator2()) @@ -311,11 +291,10 @@ public void getCallerAndCreatorEnergyLimit2With40PercentTest() + "5060018201915060aa565b505050565b600080600091505b8282101560e1576001905060018201915060cc5" + "65b5050505600a165627a7a72305820267cf0ebf31051a92ff62bed7490045b8063be9f1e1a22d07dce2576" + "54c8c17b0029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractWithCreatorEnergyLimitAndReturnTvmTestResult(contractName, creatorAddress, ABI, code, value, - feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null, + feeLimit, consumeUserResourcePercent, null, dbManager, null, creatorEnergyLimit); byte[] contractAddress = result.getContractAddress(); @@ -333,8 +312,6 @@ public void getCallerAndCreatorEnergyLimit2With40PercentTest() AccountCapsule callerAccount = repository.getAccount(callerAddress); TriggerSmartContract contract = ContractCapsule.getTriggerContractFromTransaction(trx); - feeLimit = 1_000_000_000L; - value = 0L; long expectEnergyLimit1 = 10_000_000L; Assert.assertEquals( ((VMActuator) runtimeImpl.getActuator2()) @@ -349,8 +326,6 @@ public void getCallerAndCreatorEnergyLimit2With40PercentTest() repository.putAccountValue(creatorAddress, creatorAccount); repository.commit(); - feeLimit = 1_000_000_000L; - value = 0L; long expectEnergyLimit2 = 10_005_000L; Assert.assertEquals( ((VMActuator) runtimeImpl.getActuator2()) @@ -391,11 +366,10 @@ public void getCallerAndCreatorEnergyLimit2With100PercentTest() + "060018201915060aa565b505050565b600080600091505b8282101560e1576001905060018201915060cc56" + "5b5050505600a165627a7a72305820267cf0ebf31051a92ff62bed7490045b8063be9f1e1a22d07dce25765" + "4c8c17b0029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractWithCreatorEnergyLimitAndReturnTvmTestResult(contractName, creatorAddress, ABI, code, value, - feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null, + feeLimit, consumeUserResourcePercent, null, dbManager, null, creatorEnergyLimit); byte[] contractAddress = result.getContractAddress(); @@ -413,8 +387,6 @@ public void getCallerAndCreatorEnergyLimit2With100PercentTest() AccountCapsule callerAccount = repository.getAccount(callerAddress); TriggerSmartContract contract = ContractCapsule.getTriggerContractFromTransaction(trx); - feeLimit = 1_000_000_000L; - value = 0L; long expectEnergyLimit1 = 10_000_000L; Assert.assertEquals( ((VMActuator) runtimeImpl.getActuator2()) @@ -429,8 +401,6 @@ public void getCallerAndCreatorEnergyLimit2With100PercentTest() repository.putAccountValue(creatorAddress, creatorAccount); repository.commit(); - feeLimit = 1_000_000_000L; - value = 0L; long expectEnergyLimit2 = 10_000_000L; Assert.assertEquals( ((VMActuator) runtimeImpl.getActuator2()) @@ -445,21 +415,6 @@ public void getCallerAndCreatorEnergyLimit2With100PercentTest() .getTotalEnergyLimitWithFixRatio(creatorAccount, callerAccount, contract, feeLimit, value), expectEnergyLimit3); - - } - - /** - * Release resources. - */ - @After - public void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } } diff --git a/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java b/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java index e983ce12647..ef85569e0e6 100644 --- a/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java +++ b/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java @@ -2,23 +2,16 @@ import static org.tron.core.db.TransactionTrace.convertToTronAddress; -import java.io.File; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.AfterClass; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; import org.testng.Assert; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; +import org.tron.common.BaseTest; import org.tron.common.utils.WalletUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; @@ -30,21 +23,16 @@ import stest.tron.wallet.common.client.utils.DataWord; @Slf4j -public class RuntimeTransferComplexTest { +public class RuntimeTransferComplexTest extends BaseTest { - private static final String dbPath = "output_RuntimeTransferComplexTest"; private static final String OWNER_ADDRESS; private static final String TRANSFER_TO; private static Runtime runtime; - private static Manager dbManager; - private static TronApplicationContext context; - private static Application appT; private static RepositoryImpl repository; static { + dbPath = "output_RuntimeTransferComplexTest"; Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - appT = ApplicationFactory.create(context); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; TRANSFER_TO = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; } @@ -52,9 +40,8 @@ public class RuntimeTransferComplexTest { /** * Init data. */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); + @Before + public void init() { repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); repository.addBalance(Hex.decode(OWNER_ADDRESS), 1000000000); @@ -63,20 +50,6 @@ public static void init() { repository.commit(); } - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * Test constructor Transfer pragma solidity ^0.4.16; contract transferWhenDeploy { constructor () * payable{} } @@ -132,7 +105,7 @@ public void TransferTrxToContractAccountFailIfNotPayable() consumeUserResourcePercent, null); byte[] contractAddress = WalletUtil.generateContractAddress(trx); runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, repository, null); - Assert.assertNotNull(runtime.getRuntimeError().contains("REVERT")); + Assert.assertTrue(runtime.getRuntimeError().contains("REVERT")); Assert.assertNull(dbManager.getAccountStore().get(contractAddress)); recoverDeposit(); } @@ -194,34 +167,25 @@ public void TransferTrxToContractAccountWhenTriggerAContract() * payable { CALLED_INSTANCE = calledContract(_addr); } // expect calledContract -5, toAddress +5 * function testCallTransferToInCalledContract(address toAddress) { * CALLED_INSTANCE.transferTo(toAddress); } - * * // expect calledContract -0, toAddress +0 function testRevertForCall(address toAddress){ * CALLED_INSTANCE.transferTo(toAddress); revert(); } function testExceptionForCall(address * toAddress){ CALLED_INSTANCE.transferTo(toAddress); assert(1==2); } // expect c +100 -5, * toAddress +0 function testTransferToInCreatedContract(address toAddress) payable * returns(address){ createdContract c = (new createdContract).value(100)(); * c.transferTo(toAddress); return address(c); } - * * // expect c +100 -5, toAddress not exist function testRevertForCreate(address toAddress) * payable returns(address){ createdContract c = (new createdContract).value(100)(); * c.transferTo(toAddress); revert(); return address(c); } - * * // expect c +100 -5, toAddress not exist function testExceptionForCreate(address toAddress) * payable returns(address){ createdContract c = (new createdContract).value(100)(); * c.transferTo(toAddress); assert(1==2); return address(c); } - * * function getBalance() public view returns(uint256){ return this.balance; } } - * * contract calledContract { constructor() payable {} function transferTo(address toAddress) * payable{ toAddress.transfer(5); } - * * function getBalance() public view returns(uint256){ return this.balance; } - * * } - * * contract createdContract { constructor() payable {} function transferTo(address toAddress){ * toAddress.transfer(5); } - * * function getBalance() public view returns(uint256){ return this.balance; } } */ @@ -352,8 +316,6 @@ public void TransferCallValueTestWhenUsingCallAndCreate() .generateTriggerSmartContractAndGetTransaction(msgSenderAddress, callerAddress, triggerData6, triggerCallValue, feeLimit); runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction6, repository, null); - byte[] createdAddress3 = convertToTronAddress( - new DataWord(runtime.getResult().getHReturn()).getLast20Bytes()); Assert.assertTrue(Hex.toHexString(new DataWord(createdAddress2).getLast20Bytes()) .equalsIgnoreCase("0000000000000000000000000000000000000000")); Assert.assertTrue(runtime.getRuntimeError().contains("Invalid operation code: opCode[fe];")); @@ -394,10 +356,9 @@ private byte[] deployCalledContract() long feeLimit = 100000000; long consumeUserResourcePercent = 0; - byte[] contractAddress = TvmTestUtils + return TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, null, repository, null); - return contractAddress; } private byte[] deployCallerContract(byte[] calledAddress) @@ -475,14 +436,12 @@ private byte[] deployCallerContract(byte[] calledAddress) long value = 1000; long feeLimit = 100000000; long consumeUserResourcePercent = 0; - byte[] contractAddress = TvmTestUtils + return TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, callerAddress, callerABI, callerCode, value, feeLimit, consumeUserResourcePercent, null, repository, null); - return contractAddress; } private void recoverDeposit() { - dbManager = context.getBean(Manager.class); repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java index f8a4f1ef0bb..9bfaebc0edf 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java @@ -17,24 +17,18 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.RuntimeImpl; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.Commons; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.db.TransactionTrace; import org.tron.core.exception.AccountResourceInsufficientException; import org.tron.core.exception.ContractExeException; @@ -53,32 +47,26 @@ /** * pragma solidity ^0.4.2; - * * contract Fibonacci { - * * event Notify(uint input, uint result); - * * function fibonacci(uint number) constant returns(uint result) { if (number == 0) { return 0; } * else if (number == 1) { return 1; } else { uint256 first = 0; uint256 second = 1; uint256 ret = * 0; for(uint256 i = 2; i <= number; i++) { ret = first + second; first = second; second = ret; } * return ret; } } - * * function fibonacciNotify(uint number) returns(uint result) { result = fibonacci(number); * Notify(number, result); } } */ -public class BandWidthRuntimeOutOfTimeTest { +public class BandWidthRuntimeOutOfTimeTest extends BaseTest { public static final long totalBalance = 1000_0000_000_000L; - private static String dbPath = "output_BandWidthRuntimeOutOfTimeTest_test"; - private static String dbDirectory = "db_BandWidthRuntimeOutOfTimeTest_test"; - private static String indexDirectory = "index_BandWidthRuntimeOutOfTimeTest_test"; - private static AnnotationConfigApplicationContext context; - private static Manager dbManager; + private static final String dbDirectory = "db_BandWidthRuntimeOutOfTimeTest_test"; + private static final String indexDirectory = "index_BandWidthRuntimeOutOfTimeTest_test"; - private static String OwnerAddress = "TCWHANtDDdkZCTo2T2peyEq3Eg9c2XB7ut"; - private static String TriggerOwnerAddress = "TCSgeWapPJhCqgWRxXCKb6jJ5AgNWSGjPA"; + private static final String OwnerAddress = "TCWHANtDDdkZCTo2T2peyEq3Eg9c2XB7ut"; + private static final String TriggerOwnerAddress = "TCSgeWapPJhCqgWRxXCKb6jJ5AgNWSGjPA"; static { + dbPath = "output_BandWidthRuntimeOutOfTimeTest_test"; Args.setParam( new String[]{ "--output-directory", dbPath, @@ -89,17 +77,13 @@ public class BandWidthRuntimeOutOfTimeTest { }, "config-test-mainnet.conf" ); - context = new TronApplicationContext(DefaultConfig.class); } - private String trx2ContractAddress = "TPMBUANrTwwQAPwShn7ZZjTJz1f3F8jknj"; - /** * Init data. */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); + @Before + public void init() { //init energy dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(1526647828000L); dbManager.getDynamicPropertiesStore().saveTotalEnergyWeight(10_000_000L); @@ -125,16 +109,6 @@ public static void init() { .saveLatestBlockHeaderTimestamp(System.currentTimeMillis() / 1000); } - /** - * destroy clear data of testing. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } - @Test public void testSuccess() { try { @@ -216,8 +190,7 @@ private byte[] createContract() TransactionTrace trace = new TransactionTrace(trxCap, StoreFactory.getInstance(), new RuntimeImpl()); dbManager.consumeBandwidth(trxCap, trace); - BlockCapsule blockCapsule = null; - trace.init(blockCapsule); + trace.init(null); trace.exec(); trace.finalization(); owner = dbManager.getAccountStore() diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java index 68fa9e12fa7..b39f4e56391 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java @@ -17,24 +17,18 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.RuntimeImpl; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.Commons; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.db.TransactionTrace; import org.tron.core.exception.AccountResourceInsufficientException; import org.tron.core.exception.ContractExeException; @@ -55,32 +49,25 @@ /** * pragma solidity ^0.4.2; - * * contract Fibonacci { - * * event Notify(uint input, uint result); - * * function fibonacci(uint number) constant returns(uint result) { if (number == 0) { return 0; } * else if (number == 1) { return 1; } else { uint256 first = 0; uint256 second = 1; uint256 ret = * 0; for(uint256 i = 2; i <= number; i++) { ret = first + second; first = second; second = ret; } * return ret; } } - * * function fibonacciNotify(uint number) returns(uint result) { result = fibonacci(number); * Notify(number, result); } } */ -public class BandWidthRuntimeOutOfTimeWithCheckTest { +public class BandWidthRuntimeOutOfTimeWithCheckTest extends BaseTest { public static final long totalBalance = 1000_0000_000_000L; - private static String dbPath = "output_BandWidthRuntimeOutOfTimeTest_test"; - private static String dbDirectory = "db_BandWidthRuntimeOutOfTimeTest_test"; - private static String indexDirectory = "index_BandWidthRuntimeOutOfTimeTest_test"; - private static AnnotationConfigApplicationContext context; - private static Manager dbManager; - - private static String OwnerAddress = "TCWHANtDDdkZCTo2T2peyEq3Eg9c2XB7ut"; - private static String TriggerOwnerAddress = "TCSgeWapPJhCqgWRxXCKb6jJ5AgNWSGjPA"; + private static final String dbDirectory = "db_BandWidthRuntimeOutOfTimeTest_test"; + private static final String indexDirectory = "index_BandWidthRuntimeOutOfTimeTest_test"; + private static final String OwnerAddress = "TCWHANtDDdkZCTo2T2peyEq3Eg9c2XB7ut"; + private static final String TriggerOwnerAddress = "TCSgeWapPJhCqgWRxXCKb6jJ5AgNWSGjPA"; static { + dbPath = "output_BandWidthRuntimeOutOfTimeTest_test"; Args.setParam( new String[]{ "--output-directory", dbPath, @@ -91,17 +78,13 @@ public class BandWidthRuntimeOutOfTimeWithCheckTest { }, "config-test-mainnet.conf" ); - context = new TronApplicationContext(DefaultConfig.class); } - private String trx2ContractAddress = "TPMBUANrTwwQAPwShn7ZZjTJz1f3F8jknj"; - /** * Init data. */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); + @Before + public void init() { //init energy dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(1526647837000L); dbManager.getDynamicPropertiesStore().saveTotalEnergyWeight(10_000_000L); @@ -127,16 +110,6 @@ public static void init() { .saveLatestBlockHeaderTimestamp(System.currentTimeMillis() / 1000); } - /** - * destroy clear data of testing. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } - @Test public void testSuccess() { try { @@ -172,9 +145,7 @@ public void testSuccess() { Assert.assertEquals(990000000, balance); Assert.assertEquals(9950000 * Constant.SUN_PER_ENERGY, balance + energy * Constant.SUN_PER_ENERGY); - } catch (TronException e) { - Assert.assertNotNull(e); - } catch (ReceiptCheckErrException e) { + } catch (TronException | ReceiptCheckErrException e) { Assert.assertNotNull(e); } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java index 5e6663e8cfe..9309bc398bc 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java @@ -17,26 +17,19 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.RuntimeImpl; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.Commons; -import org.tron.common.utils.FileUtil; -import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.ReceiptCapsule; import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.db.TransactionTrace; import org.tron.core.exception.AccountResourceInsufficientException; import org.tron.core.exception.ContractExeException; @@ -53,21 +46,18 @@ import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; -public class BandWidthRuntimeTest { +public class BandWidthRuntimeTest extends BaseTest { public static final long totalBalance = 1000_0000_000_000L; - private static String dbPath = "output_BandWidthRuntimeTest_test"; - private static String dbDirectory = "db_BandWidthRuntimeTest_test"; - private static String indexDirectory = "index_BandWidthRuntimeTest_test"; - private static AnnotationConfigApplicationContext context; - private static Manager dbManager; - private static ChainBaseManager chainBaseManager; - - private static String OwnerAddress = "TCWHANtDDdkZCTo2T2peyEq3Eg9c2XB7ut"; - private static String TriggerOwnerAddress = "TCSgeWapPJhCqgWRxXCKb6jJ5AgNWSGjPA"; - private static String TriggerOwnerTwoAddress = "TPMBUANrTwwQAPwShn7ZZjTJz1f3F8jknj"; + private static final String dbDirectory = "db_BandWidthRuntimeTest_test"; + private static final String indexDirectory = "index_BandWidthRuntimeTest_test"; + private static final String OwnerAddress = "TCWHANtDDdkZCTo2T2peyEq3Eg9c2XB7ut"; + private static final String TriggerOwnerAddress = "TCSgeWapPJhCqgWRxXCKb6jJ5AgNWSGjPA"; + private static final String TriggerOwnerTwoAddress = "TPMBUANrTwwQAPwShn7ZZjTJz1f3F8jknj"; + private static boolean init; static { + dbPath = "output_BandWidthRuntimeTest_test"; Args.setParam( new String[]{ "--output-directory", dbPath, @@ -77,16 +67,16 @@ public class BandWidthRuntimeTest { }, "config-test-mainnet.conf" ); - context = new TronApplicationContext(DefaultConfig.class); } /** * Init data. */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - chainBaseManager = context.getBean(ChainBaseManager.class); + @Before + public void init() { + if (init) { + return; + } //init energy dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(1526547838000L); dbManager.getDynamicPropertiesStore().saveTotalEnergyWeight(10_000_000L); @@ -122,25 +112,13 @@ public static void init() { dbManager.getDynamicPropertiesStore() .saveLatestBlockHeaderTimestamp(System.currentTimeMillis() / 1000); - } - - /** - * destroy clear data of testing. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); + init = true; } @Test public void testSuccess() { try { byte[] contractAddress = createContract(); - AccountCapsule triggerOwner = dbManager.getAccountStore() - .get(Commons.decodeFromBase58Check(TriggerOwnerAddress)); - long energy = triggerOwner.getEnergyUsage(); TriggerSmartContract triggerContract = TvmTestUtils.createTriggerContract(contractAddress, "setCoin(uint256)", "3", false, 0, Commons.decodeFromBase58Check(TriggerOwnerAddress)); @@ -151,15 +129,14 @@ public void testSuccess() { TransactionTrace trace = new TransactionTrace(trxCap, StoreFactory.getInstance(), new RuntimeImpl()); dbManager.consumeBandwidth(trxCap, trace); - BlockCapsule blockCapsule = null; - trace.init(blockCapsule); + trace.init(null); trace.exec(); trace.finalization(); - triggerOwner = dbManager.getAccountStore() + AccountCapsule triggerOwner = dbManager.getAccountStore() .get(Commons.decodeFromBase58Check(TriggerOwnerAddress)); - energy = triggerOwner.getEnergyUsage(); + long energy = triggerOwner.getEnergyUsage(); long balance = triggerOwner.getBalance(); Assert.assertEquals(45706, trace.getReceipt().getEnergyUsageTotal()); Assert.assertEquals(45706, energy); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java index 37e21b086ea..1f1efe6cc6b 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java @@ -17,26 +17,18 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.RuntimeImpl; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.Commons; -import org.tron.common.utils.FileUtil; -import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; -import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.ReceiptCapsule; import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.db.TransactionTrace; import org.tron.core.exception.AccountResourceInsufficientException; import org.tron.core.exception.ContractExeException; @@ -57,34 +49,28 @@ /** * pragma solidity ^0.4.2; - * * contract Fibonacci { - * * event Notify(uint input, uint result); - * * function fibonacci(uint number) constant returns(uint result) { if (number == 0) { return 0; } * else if (number == 1) { return 1; } else { uint256 first = 0; uint256 second = 1; uint256 ret = * 0; for(uint256 i = 2; i <= number; i++) { ret = first + second; first = second; second = ret; } * return ret; } } - * * function fibonacciNotify(uint number) returns(uint result) { result = fibonacci(number); * Notify(number, result); } } */ -public class BandWidthRuntimeWithCheckTest { +public class BandWidthRuntimeWithCheckTest extends BaseTest { public static final long totalBalance = 1000_0000_000_000L; - private static String dbPath = "output_BandWidthRuntimeTest_test"; - private static String dbDirectory = "db_BandWidthRuntimeTest_test"; - private static String indexDirectory = "index_BandWidthRuntimeTest_test"; - private static AnnotationConfigApplicationContext context; - private static Manager dbManager; - private static ChainBaseManager chainBaseManager; + private static final String dbDirectory = "db_BandWidthRuntimeTest_test"; + private static final String indexDirectory = "index_BandWidthRuntimeTest_test"; + private static final String OwnerAddress = "TCWHANtDDdkZCTo2T2peyEq3Eg9c2XB7ut"; + private static final String TriggerOwnerAddress = "TCSgeWapPJhCqgWRxXCKb6jJ5AgNWSGjPA"; + private static final String TriggerOwnerTwoAddress = "TPMBUANrTwwQAPwShn7ZZjTJz1f3F8jknj"; - private static String OwnerAddress = "TCWHANtDDdkZCTo2T2peyEq3Eg9c2XB7ut"; - private static String TriggerOwnerAddress = "TCSgeWapPJhCqgWRxXCKb6jJ5AgNWSGjPA"; - private static String TriggerOwnerTwoAddress = "TPMBUANrTwwQAPwShn7ZZjTJz1f3F8jknj"; + private static boolean init; static { + dbPath = "output_BandWidthRuntimeTest_test"; Args.setParam( new String[]{ "--output-directory", dbPath, @@ -94,17 +80,16 @@ public class BandWidthRuntimeWithCheckTest { }, "config-test-mainnet.conf" ); - context = new TronApplicationContext(DefaultConfig.class); } /** * Init data. */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - chainBaseManager = context.getBean(ChainBaseManager.class); - + @Before + public void init() { + if (init) { + return; + } //init energy dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(1526647838000L); dbManager.getDynamicPropertiesStore().saveTotalEnergyWeight(10_000_000L); @@ -134,17 +119,7 @@ public static void init() { accountCapsule3.setFrozenForEnergy(10_000_000L, 0L); dbManager.getAccountStore() .put(Commons.decodeFromBase58Check(TriggerOwnerTwoAddress), accountCapsule3); - - } - - /** - * destroy clear data of testing. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); + init = true; } @Test @@ -165,9 +140,8 @@ public void testSuccess() { TransactionTrace trace = new TransactionTrace(trxCap, StoreFactory.getInstance(), new RuntimeImpl()); dbManager.consumeBandwidth(trxCap, trace); - BlockCapsule blockCapsule = null; - trace.init(blockCapsule); + trace.init(null); trace.exec(); trace.finalization(); @@ -180,9 +154,7 @@ public void testSuccess() { Assert.assertEquals(57466800, balance); Assert.assertEquals(624668 * Constant.SUN_PER_ENERGY, balance + energy * Constant.SUN_PER_ENERGY); - } catch (TronException e) { - Assert.assertNotNull(e); - } catch (ReceiptCheckErrException e) { + } catch (TronException | ReceiptCheckErrException e) { Assert.assertNotNull(e); } @@ -204,8 +176,7 @@ public void testSuccessNoBandWidth() { new RuntimeImpl()); dbManager.consumeBandwidth(trxCap, trace); long bandWidth = trxCap.getSerializedSize() + Constant.MAX_RESULT_SIZE_IN_TX; - BlockCapsule blockCapsule = null; - trace.init(blockCapsule); + trace.init(null); trace.exec(); trace.finalization(); trace.check(); @@ -220,9 +191,7 @@ public void testSuccessNoBandWidth() { Assert.assertEquals(0, receipt.getEnergyFee()); Assert.assertEquals(totalBalance, balance); - } catch (TronException e) { - Assert.assertNotNull(e); - } catch (ReceiptCheckErrException e) { + } catch (TronException | ReceiptCheckErrException e) { Assert.assertNotNull(e); } } @@ -270,9 +239,8 @@ private byte[] createContract() TransactionTrace trace = new TransactionTrace(trxCap, StoreFactory.getInstance(), new RuntimeImpl()); dbManager.consumeBandwidth(trxCap, trace); - BlockCapsule blockCapsule = null; - trace.init(blockCapsule); + trace.init(null); trace.exec(); trace.finalization(); trace.check(); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java index 200df06f084..88067be30e9 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java @@ -1,30 +1,24 @@ package org.tron.common.runtime.vm; import com.google.protobuf.ByteString; -import java.io.File; import java.util.ArrayList; import java.util.List; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.AfterClass; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.crypto.ECKey; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.common.utils.Utils; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; @@ -36,37 +30,20 @@ import stest.tron.wallet.common.client.utils.AbiUtil; @Slf4j -public class BatchSendTest { +public class BatchSendTest extends BaseTest { - private static final String dbPath = "output_BatchSendTest"; private static final String OWNER_ADDRESS; private static final String TRANSFER_TO; - private static final long TOTAL_SUPPLY = 1000_000_000L; - private static final int TRX_NUM = 10; - private static final int NUM = 1; - private static final long START_TIME = 1; - private static final long END_TIME = 2; - private static final int VOTE_SCORE = 2; - private static final String DESCRIPTION = "TRX"; - private static final String URL = "https://tron.network/"; private static Runtime runtime; - private static Manager dbManager; - private static TronApplicationContext context; - private static Application appT; private static RepositoryImpl repository; - private static AccountCapsule ownerCapsule; + private static final AccountCapsule ownerCapsule; static { + dbPath = "output_BatchSendTest"; Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - appT = ApplicationFactory.create(context); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; TRANSFER_TO = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; - dbManager = context.getBean(Manager.class); - repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); - repository.createAccount(Hex.decode(TRANSFER_TO), AccountType.Normal); - repository.addBalance(Hex.decode(TRANSFER_TO), 10); - repository.commit(); + ownerCapsule = new AccountCapsule( ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), @@ -74,40 +51,31 @@ public class BatchSendTest { AccountType.AssetIssue); ownerCapsule.setBalance(1000_1000_1000L); + + + } + + @Before + public void before() { + repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + repository.createAccount(Hex.decode(TRANSFER_TO), AccountType.Normal); + repository.addBalance(Hex.decode(TRANSFER_TO), 10); + repository.commit(); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); dbManager.getDynamicPropertiesStore().saveAllowSameTokenName(1); dbManager.getDynamicPropertiesStore().saveAllowMultiSign(1); dbManager.getDynamicPropertiesStore().saveAllowTvmTransferTrc10(1); dbManager.getDynamicPropertiesStore().saveAllowTvmConstantinople(1); dbManager.getDynamicPropertiesStore().saveAllowTvmSolidity059(1); - - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } /** * pragma solidity ^0.5.4; - * * contract TestBatchSendTo { constructor() public payable{} - * * function depositIn() public payable{} - * - * * function batchSendTo (address payable to1 ,address payable to2 ,address payable to3, uint256 * m1,uint256 m2,uint256 m3) public { to1.send(m1 ); to2.send(m2 ); to3.send(m3 ); } - * * } */ @Test @@ -181,10 +149,9 @@ private byte[] deployTransferContract() long tokenValue = 0; long tokenId = 0; - byte[] contractAddress = TvmTestUtils + return TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, null, tokenValue, tokenId, repository, null); - return contractAddress; } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/ChargeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/ChargeTest.java index 91378fdcb64..600b81750da 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/ChargeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/ChargeTest.java @@ -1,24 +1,16 @@ package org.tron.common.runtime.vm; -import java.io.File; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.testng.Assert; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; @@ -28,28 +20,24 @@ import org.tron.protos.Protocol.AccountType; @Slf4j +public class ChargeTest extends BaseTest { -public class ChargeTest { - - private Manager dbManager; - private TronApplicationContext context; private RepositoryImpl repository; - private String dbPath = "output_ChargeTest"; - private String OWNER_ADDRESS; - private Application AppT; + private static String OWNER_ADDRESS; private long totalBalance = 100_000_000_000_000L; + static { + dbPath = "output_ChargeTest"; + Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; + } + /** * Init data. */ @Before public void init() { - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - AppT = ApplicationFactory.create(context); - OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; - dbManager = context.getBean(Manager.class); repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); repository.addBalance(Hex.decode(OWNER_ADDRESS), totalBalance); @@ -88,11 +76,10 @@ public void testOverflow() + "3901905600608060405260358060116000396000f3006080604052600080fd00a165627a7a723058201738d" + "6aa899dc00d4e99de944eb74d30a9ba1fcae37b99dc6299d95e992ca8b40029a165627a7a72305820683901" + "37ba70dfc460810603eba8500b050ed3cd01e66f55ec07d387ec1cd2750029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 51293; // 200 * code.length() + 93 Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -108,7 +95,7 @@ public void testOverflow() long expectEnergyUsageTotal2 = feeLimit / 100; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), false); + Assert.assertFalse(result.getRuntime().getResult().isRevert()); Assert .assertTrue(result.getRuntime().getResult().getException() instanceof ArithmeticException); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), @@ -154,11 +141,10 @@ public void testNegative() + "5600608060405260358060116000396000f3006080604052600080fd00a165627a7a72305820ef54aac72ef" + "ff56dbe894e7218d009a87368bb70338bb385db5d3dec9927bc2c0029a165627a7a723058201620679ac2ae" + "640d0a6c26e9cb4523e98eb0de8fff26975c5bb4c7fda1c98d720029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 68111; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -174,7 +160,7 @@ public void testNegative() long expectEnergyUsageTotal2 = feeLimit / 100; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), false); + Assert.assertFalse(result.getRuntime().getResult().isRevert()); Assert .assertTrue(result.getRuntime().getResult().getException() instanceof ArithmeticException); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), @@ -189,7 +175,7 @@ public void testNegative() long expectEnergyUsageTotal3 = feeLimit / 100; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal3); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), false); + Assert.assertFalse(result.getRuntime().getResult().isRevert()); Assert .assertTrue(result.getRuntime().getResult().getException() instanceof ArithmeticException); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance @@ -197,27 +183,6 @@ public void testNegative() } - @Test - @Ignore - public void testFallback() - throws ContractExeException, ContractValidateException, ReceiptCheckErrException { - // done in EnergyWhenSendAndTransferTest.java - - } - - // contract TestCallDepth { - // - // function CallstackExploit(int256 counter) external { - // if (counter > 0) { - // this.CallstackExploit.gas(msg.gas - 2000)(counter - 1); - // } else {} - // } - // - // function Call(int256 counter) { - // this.CallstackExploit(counter); - // } - // } - @Test public void testCallDepth() throws ContractExeException, ContractValidateException, @@ -243,11 +208,10 @@ public void testCallDepth() + "152602001915050600060405180830381600087803b15801561012d57600080fd5b505af115801561014157" + "3d6000803e3d6000fd5b50505050505600a165627a7a72305820510367f4437b1af16931cacc744eb6f3102" + "d72f0c369aa795a4dc49a7f90a3e90029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 74517; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -265,8 +229,8 @@ public void testCallDepth() long expectEnergyUsageTotal2 = 27743; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), true); - Assert.assertEquals(result.getRuntime().getResult().getException(), null); + Assert.assertTrue(result.getRuntime().getResult().isRevert()); + Assert.assertNull(result.getRuntime().getResult().getException()); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - (expectEnergyUsageTotal + expectEnergyUsageTotal2) * 100); @@ -360,11 +324,10 @@ public void testCallDepthAndWidth() + "8e9050565b50505600a165627a7a72305820a9e7e1401001d6c131ebf4727fbcedede08d16416dc0447cef60" + "e0b9516c6a260029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 286450; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -382,8 +345,8 @@ public void testCallDepthAndWidth() long expectEnergyUsageTotal2 = 243698; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), false); - Assert.assertEquals(result.getRuntime().getResult().getException(), null); + Assert.assertFalse(result.getRuntime().getResult().isRevert()); + Assert.assertNull(result.getRuntime().getResult().getException()); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - (expectEnergyUsageTotal + expectEnergyUsageTotal2) * 100); @@ -428,11 +391,9 @@ public void testCreateDepthAndWidth() + "029a165627a7a7230582071d51c39c93b0aba5baeacea0b2bd5ca5342d028bb834046eca92975a3517a4c0" + "029"; - String libraryAddressPair = null; - TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 201839; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -450,24 +411,11 @@ public void testCreateDepthAndWidth() long expectEnergyUsageTotal2 = 4481164; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), false); - Assert.assertEquals(result.getRuntime().getResult().getException(), null); + Assert.assertFalse(result.getRuntime().getResult().isRevert()); + Assert.assertNull(result.getRuntime().getResult().getException()); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - (expectEnergyUsageTotal + expectEnergyUsageTotal2) * 100); } - /** - * Release resources. - */ - @After - public void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java index 5fa63096b9f..aec3f2322a6 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java @@ -1,24 +1,16 @@ package org.tron.common.runtime.vm; -import java.io.File; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.testng.Assert; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; @@ -33,15 +25,17 @@ @Slf4j -public class EnergyWhenAssertStyleTest { +public class EnergyWhenAssertStyleTest extends BaseTest { - private Manager dbManager; - private TronApplicationContext context; private RepositoryImpl repository; - private String dbPath = "output_EnergyWhenAssertStyleTest"; - private String OWNER_ADDRESS; - private Application AppT; + private static String OWNER_ADDRESS; private long totalBalance = 30_000_000_000_000L; + + static { + dbPath = "output_EnergyWhenAssertStyleTest"; + Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; + } /** @@ -49,11 +43,6 @@ public class EnergyWhenAssertStyleTest { */ @Before public void init() { - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - AppT = ApplicationFactory.create(context); - OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; - dbManager = context.getBean(Manager.class); repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); repository.addBalance(Hex.decode(OWNER_ADDRESS), totalBalance); @@ -104,11 +93,10 @@ public void outOfIndexTest() + "25261016082019092526060916020820161014080388339019050509050600a81600a815181101515608c57" + "fe5b60209081029091010152505600a165627a7a723058201aaf6626083e32afa834a13d3365784c509d10f" + "57ce1024f88c697cf0718795e0029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 39487; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -123,7 +111,7 @@ public void outOfIndexTest() long expectEnergyUsageTotal2 = feeLimit / 100; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), false); + Assert.assertFalse(result.getRuntime().getResult().isRevert()); Assert.assertTrue( result.getRuntime().getResult().getException() instanceof IllegalOperationException); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), @@ -159,11 +147,10 @@ public void bytesNTest() + "1e76e10781146043575b600080fd5b348015604e57600080fd5b5060556057565b005b72012345000000000" + "00000000000000000000000601460008282fe00a165627a7a72305820a1c7c81d642cc0aa11c43d63614a5b" + "3c018e4af84700af4bfde5f2efb18b55130029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 31875; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -178,7 +165,7 @@ public void bytesNTest() long expectEnergyUsageTotal2 = feeLimit / 100; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), false); + Assert.assertFalse(result.getRuntime().getResult().isRevert()); Assert.assertTrue( result.getRuntime().getResult().getException() instanceof IllegalOperationException); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), @@ -212,11 +199,10 @@ public void divZeroTest() + "03e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663" + "b87d948d81146043575b600080fd5b348015604e57600080fd5b5060556057565b005b60008080600afe00a" + "165627a7a7230582084ed35f2e244d6721bb5f5fcaf53d237ea050b3de84d5cc7fee74584fd2ff31f0029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 27875; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -231,7 +217,7 @@ public void divZeroTest() long expectEnergyUsageTotal2 = feeLimit / 100; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), false); + Assert.assertFalse(result.getRuntime().getResult().isRevert()); Assert.assertTrue( result.getRuntime().getResult().getException() instanceof IllegalOperationException); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), @@ -267,11 +253,10 @@ public void shiftByNegativeTest() + "e88e362a81146043575b600080fd5b348015604e57600080fd5b5060556057565b005b60091960008161040" + "0fe00a165627a7a7230582086c99cfe65e26909bb0fb3a2bdaf2385ad8dfff72680adab954063a4fe1d549b" + "0029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 28475; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -286,7 +271,7 @@ public void shiftByNegativeTest() long expectEnergyUsageTotal2 = feeLimit / 100; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), false); + Assert.assertFalse(result.getRuntime().getResult().isRevert()); Assert.assertTrue( result.getRuntime().getResult().getException() instanceof IllegalOperationException); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), @@ -322,11 +307,10 @@ public void enumTypeTest() + "03e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663" + "5a43cddc81146043575b600080fd5b348015604e57600080fd5b5060556057565b005b6000600afe00a1656" + "27a7a72305820b24a4d459b753723d300f56c408c6120d5ef0c7ddb166d66ccf4277a76ad83ed0029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 27475; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -341,7 +325,7 @@ public void enumTypeTest() long expectEnergyUsageTotal2 = feeLimit / 100; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), false); + Assert.assertFalse(result.getRuntime().getResult().isRevert()); Assert.assertTrue( result.getRuntime().getResult().getException() instanceof IllegalOperationException); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), @@ -376,11 +360,10 @@ public void functionPointerTest() + "e9ad8ee781146043575b600080fd5b348015604e57600080fd5b5060556057565b005b606a606660018263f" + "fffffff16565b5050565bfe00a165627a7a723058201c8982fa288ec7aad86b1d1992ecc5d08c4b22e4fe03" + "7981f91aff8bcbd900680029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 30475; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -395,7 +378,7 @@ public void functionPointerTest() long expectEnergyUsageTotal2 = feeLimit / 100; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), false); + Assert.assertFalse(result.getRuntime().getResult().isRevert()); Assert.assertTrue( result.getRuntime().getResult().getException() instanceof IllegalOperationException); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), @@ -429,11 +412,10 @@ public void assertTest() + "03e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663" + "2b813bc081146043575b600080fd5b348015604e57600080fd5b5060556057565b005bfe00a165627a7a723" + "058208ce7511bd3a946a22baaba2b4521cbf29d2481ad52887c5567e422cd89726eda0029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 26675; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -448,7 +430,7 @@ public void assertTest() long expectEnergyUsageTotal2 = feeLimit / 100; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), false); + Assert.assertFalse(result.getRuntime().getResult().isRevert()); Assert.assertTrue( result.getRuntime().getResult().getException() instanceof IllegalOperationException); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), @@ -497,11 +479,10 @@ public void systemPrecompileTest() + "fffffff868116825260208201869052825193169381830193909290918290030181855af491505015156101" + "2957600080fd5b50505600a165627a7a723058206090aa7a8ac0e45fac642652417495e81dad6f1592343bf" + "f8cfe97f61cf74e880029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 89214; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -520,7 +501,7 @@ public void systemPrecompileTest() long expectEnergyUsageTotal2 = feeLimit / 100; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), false); + Assert.assertFalse(result.getRuntime().getResult().isRevert()); Assert.assertTrue( result.getRuntime().getResult().getException() instanceof PrecompiledContractException); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), @@ -557,11 +538,10 @@ public void outOfMemTest() + "b82821015609957604080516230040080825263060080208201909252906020820163060080008038833901" + "9050506001909201919050605f565b5050505600a165627a7a723058209e5d294a7bf5133b304bc6851c749" + "cd5e1f4748230405755e6bd2e31549ae1d00029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 40487; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -576,32 +556,12 @@ public void outOfMemTest() long expectEnergyUsageTotal2 = feeLimit / 100; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), false); + Assert.assertFalse(result.getRuntime().getResult().isRevert()); Assert .assertTrue(result.getRuntime().getResult().getException() instanceof OutOfMemoryException); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - (expectEnergyUsageTotal + expectEnergyUsageTotal2) * 100); } - @Test - @Ignore - public void overflowTest() - throws ContractExeException, ReceiptCheckErrException, ContractValidateException { - // done in ChargeTest - } - - /** - * Release resources. - */ - @After - public void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java index 5ce9729393f..2356a649e82 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java @@ -1,24 +1,16 @@ package org.tron.common.runtime.vm; -import java.io.File; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.testng.Assert; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; @@ -29,16 +21,17 @@ import org.tron.protos.Protocol.AccountType; @Slf4j +public class EnergyWhenRequireStyleTest extends BaseTest { -public class EnergyWhenRequireStyleTest { - - private Manager dbManager; - private TronApplicationContext context; private RepositoryImpl repository; - private String dbPath = "output_EnergyWhenRequireStyleTest"; - private String OWNER_ADDRESS; - private Application AppT; + private static final String OWNER_ADDRESS; private long totalBalance = 30_000_000_000_000L; + + static { + dbPath = "output_EnergyWhenRequireStyleTest"; + Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; + } /** @@ -46,11 +39,6 @@ public class EnergyWhenRequireStyleTest { */ @Before public void init() { - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - AppT = ApplicationFactory.create(context); - OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; - dbManager = context.getBean(Manager.class); repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); repository.addBalance(Hex.decode(OWNER_ADDRESS), totalBalance); @@ -100,11 +88,10 @@ public void throwTest() + "03e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663" + "50bff6bf81146043575b600080fd5b348015604e57600080fd5b506055603e565b0000a165627a7a7230582" + "0f51282c5910e3ff1b5f2e9509f3cf23c7035027aae1947ab46e5a9252fb061eb0029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 26275; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -120,8 +107,8 @@ public void throwTest() long expectEnergyUsageTotal2 = 124; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), true); - Assert.assertTrue(result.getRuntime().getResult().getException() == null); + Assert.assertTrue(result.getRuntime().getResult().isRevert()); + Assert.assertNull(result.getRuntime().getResult().getException()); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - (expectEnergyUsageTotal + expectEnergyUsageTotal2) * 100); @@ -153,11 +140,10 @@ public void requireTest() + "03e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663" + "357815c481146043575b600080fd5b348015604e57600080fd5b506055603e565b0000a165627a7a7230582" + "054141931bcc37d4f266815f02d2fb113f5af20825cbce45d3b0f2fe90ac0145d0029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 26275; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -173,8 +159,8 @@ public void requireTest() long expectEnergyUsageTotal2 = 124; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), true); - Assert.assertTrue(result.getRuntime().getResult().getException() == null); + Assert.assertTrue(result.getRuntime().getResult().isRevert()); + Assert.assertNull(result.getRuntime().getResult().getException()); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - (expectEnergyUsageTotal + expectEnergyUsageTotal2) * 100); @@ -217,11 +203,10 @@ public void thisFunctionViaMessageCallTest() + "000000000000000028152600401600060405180830381600088803b15801560db57600080fd5b5087f11580" + "1560ee573d6000803e3d6000fd5b50505050505600a165627a7a7230582087d830c44fb566498789b212e3d" + "0374f7a7589a2efdda11b3a4c03051b57891a0029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 57905; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -237,8 +222,8 @@ public void thisFunctionViaMessageCallTest() long expectEnergyUsageTotal2 = 5339; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), true); - Assert.assertTrue(result.getRuntime().getResult().getException() == null); + Assert.assertTrue(result.getRuntime().getResult().isRevert()); + Assert.assertNull(result.getRuntime().getResult().getException()); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - (expectEnergyUsageTotal + expectEnergyUsageTotal2) * 100); @@ -294,11 +279,10 @@ public void thatFunctionViaMessageCallTest() + "0006000350416632b813bc081146043575b600080fd5b348015604e57600080fd5b5060556057565b005bfe" + "00a165627a7a72305820c02c76575c2a0ada80c3f6db47f885cece6c254d1e7c79eb6ddc1c1d4e70ebae002" + "9a165627a7a72305820cf879e62f738b44636adf61bd4b2fb38c10f027d2a4484d58baf44a06dc97bd90029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 97341; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -314,8 +298,8 @@ public void thatFunctionViaMessageCallTest() long expectEnergyUsageTotal2 = 64125; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), true); - Assert.assertTrue(result.getRuntime().getResult().getException() == null); + Assert.assertTrue(result.getRuntime().getResult().isRevert()); + Assert.assertNull(result.getRuntime().getResult().getException()); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - (expectEnergyUsageTotal + expectEnergyUsageTotal2) * 100); @@ -356,11 +340,10 @@ public void newContractTest1() + "10066610087565b604051809103906000f080158015610082573d6000803e3d6000fd5b505050565b604051" + "6013806100978339019056006080604052348015600f57600080fd5b50fe00a165627a7a72305820685ff8f" + "74890f671deb4d3881a4b72ab0daac2ab0d36112e1ebdf98a43ac4d940029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 42687; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -377,7 +360,7 @@ public void newContractTest1() long expectEnergyUsageTotal2 = feeLimit / 100; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); // todo: revert should be true!! see later - Assert.assertEquals(result.getRuntime().getResult().isRevert(), false); + Assert.assertFalse(result.getRuntime().getResult().isRevert()); Assert .assertTrue(result.getRuntime().getResult().getException() instanceof OutOfEnergyException); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), @@ -433,22 +416,21 @@ public void receiveTrxWithoutPayableTest() + "4052348015600f57600080fd5b500000a165627a7a72305820a82006ee5ac783bcea7085501eaed33360b31" + "20278f1f39e611afedc9f4a693b0029a165627a7a72305820a50d9536f182fb6aefc737fdc3a675630e75a0" + "8de88deb6b1bee6d4b6dff04730029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 42; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), true); - Assert.assertTrue(result.getRuntime().getResult().getException() == null); + Assert.assertTrue(result.getRuntime().getResult().isRevert()); + Assert.assertNull(result.getRuntime().getResult().getException()); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - expectEnergyUsageTotal * 100); result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, 0, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); byte[] contractAddress = result.getContractAddress(); long expectEnergyUsageTotal2 = 100341; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); @@ -462,21 +444,13 @@ public void receiveTrxWithoutPayableTest() long expectEnergyUsageTotal3 = 51833; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal3); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), true); - Assert.assertTrue(result.getRuntime().getResult().getException() == null); + Assert.assertTrue(result.getRuntime().getResult().isRevert()); + Assert.assertNull(result.getRuntime().getResult().getException()); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - (expectEnergyUsageTotal + expectEnergyUsageTotal2 + expectEnergyUsageTotal3) * 100); } - @Test - @Ignore - public void transferTest() - throws ContractExeException, ReceiptCheckErrException, ContractValidateException { - // done in EnergyWhenSendAndTransferTest - - } - // pragma solidity ^0.4.16; // // contract TestRevertContract { @@ -512,11 +486,10 @@ public void revertTest() + "6312065fe08114604d578063a26388bb146071575b600080fd5b348015605857600080fd5b50605f6085565" + "b60408051918252519081900360200190f35b348015607c57600080fd5b5060836048565b005b3031905600" + "a165627a7a7230582059cab3a7a5851a7852c728ec8729456a04dc022674976f3f26bfd51491dbf1080029"; - String libraryAddressPair = null; TVMTestResult result = TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); long expectEnergyUsageTotal = 36481; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal); @@ -532,31 +505,11 @@ public void revertTest() long expectEnergyUsageTotal2 = 146; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), true); - Assert.assertTrue(result.getRuntime().getResult().getException() == null); + Assert.assertTrue(result.getRuntime().getResult().isRevert()); + Assert.assertNull(result.getRuntime().getResult().getException()); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - (expectEnergyUsageTotal + expectEnergyUsageTotal2) * 100); } - @Test - @Ignore - public void reach64CallDepth() { - // done in ChargeTest - } - - /** - * Release resources. - */ - @After - public void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java index b834f953eb4..40af27612df 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java @@ -1,23 +1,16 @@ package org.tron.common.runtime.vm; -import java.io.File; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.After; import org.junit.Before; import org.junit.Test; import org.testng.Assert; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; @@ -27,26 +20,23 @@ import org.tron.protos.Protocol.AccountType; @Slf4j -public class EnergyWhenSendAndTransferTest { +public class EnergyWhenSendAndTransferTest extends BaseTest { - private Manager dbManager; - private TronApplicationContext context; private RepositoryImpl repository; - private String dbPath = "output_EnergyWhenSendAndTransferTest"; - private String OWNER_ADDRESS; - private Application AppT; + private static final String OWNER_ADDRESS; private long totalBalance = 30_000_000_000_000L; + static { + dbPath = "output_EnergyWhenSendAndTransferTest"; + Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; + } + /** * Init data. */ @Before public void init() { - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - AppT = ApplicationFactory.create(context); - OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; - dbManager = context.getBean(Manager.class); repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); repository.addBalance(Hex.decode(OWNER_ADDRESS), totalBalance); @@ -124,7 +114,7 @@ public void callValueTest() long expectEnergyUsageTotal3 = 9459; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal3); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), true); + Assert.assertTrue(result.getRuntime().getResult().isRevert()); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - value - (expectEnergyUsageTotal + expectEnergyUsageTotal2 + expectEnergyUsageTotal3) * 100); } @@ -189,8 +179,8 @@ public void sendTest() long expectEnergyUsageTotal2 = 7025; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().getException(), null); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), false); + Assert.assertNull(result.getRuntime().getResult().getException()); + Assert.assertFalse(result.getRuntime().getResult().isRevert()); Assert.assertEquals(repository.getAccount(contractAddress).getBalance(), value); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - value - (expectEnergyUsageTotal + expectEnergyUsageTotal2) * 100); @@ -224,8 +214,8 @@ public void transferTest() long expectEnergyUsageTotal2 = 7030; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().getException(), null); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), true); + Assert.assertNull(result.getRuntime().getResult().getException()); + Assert.assertTrue(result.getRuntime().getResult().isRevert()); Assert.assertEquals(repository.getAccount(contractAddress).getBalance(), value); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - value - (expectEnergyUsageTotal + expectEnergyUsageTotal2) * 100); @@ -260,11 +250,10 @@ public TVMTestResult deployCallValueTestContract(long value, long feeLimit, + "b602a90565b6000805b600a81101560945760008181526020819052604090208190556001016074565b5090" + "5600a165627a7a723058205ded543feb546472be4e116e713a2d46b8dafc823ca31256e67a1be92a6752730" + "029"; - String libraryAddressPair = null; return TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); } public TVMTestResult deploySendAndTransferTestContract(long value, long feeLimit, @@ -294,25 +283,9 @@ public TVMTestResult deploySendAndTransferTestContract(long value, long feeLimit + "2600160008181526020527fada5013122d395ba3c54772283fb069b10426056ef8ca54750cb9bb552a59e7d" + "550000a165627a7a7230582029b27c10c1568d590fa66bc0b7d42537a314c78d028f59a188fa411f7fc15c4" + "f0029"; - String libraryAddressPair = null; return TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, - consumeUserResourcePercent, libraryAddressPair, dbManager, null); + consumeUserResourcePercent, null, dbManager, null); } - - /** - * Release resources. - */ - @After - public void destroy() { - context.destroy(); - Args.clearParam(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.warn("Release resources failure."); - } - } - } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java index 73b51c803f8..c2dc1d524ad 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java @@ -1,23 +1,16 @@ package org.tron.common.runtime.vm; -import java.io.File; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.After; import org.junit.Before; import org.junit.Test; import org.testng.Assert; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; @@ -29,28 +22,24 @@ import org.tron.protos.Protocol.AccountType; @Slf4j -public class EnergyWhenTimeoutStyleTest { +public class EnergyWhenTimeoutStyleTest extends BaseTest { - private Manager dbManager; - private TronApplicationContext context; private RepositoryImpl repository; - private String dbPath = "output_CPUTimeTest"; - private String OWNER_ADDRESS; - private Application AppT; + private static final String OWNER_ADDRESS; private long totalBalance = 30_000_000_000_000L; + static { + dbPath = "output_CPUTimeTest"; + Args.setParam(new String[]{"--output-directory", dbPath}, + Constant.TEST_CONF); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; + } /** * Init data. */ @Before public void init() { - Args.setParam(new String[]{"--output-directory", dbPath}, - Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - AppT = ApplicationFactory.create(context); - OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; - dbManager = context.getBean(Manager.class); repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); repository.addBalance(Hex.decode(OWNER_ADDRESS), totalBalance); @@ -109,7 +98,6 @@ public void endlessLoopTest() /* =================================== CALL setVote(uint256) =============================== */ String params = "0000000000000000000000000000000000000000000000000000000000000003"; byte[] triggerData = TvmTestUtils.parseAbi("setVote(uint256)", params); - boolean haveException = false; result = TvmTestUtils .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, value, feeLimit, dbManager, null); @@ -144,27 +132,11 @@ public TVMTestResult deployEndlessLoopContract(long value, long feeLimit, + "60011560cb576001600080828254019250508190555060b1565b505600a165627a7a72305820290a38c9bbaf" + "ccaf6c7f752ab56d229e354da767efb72715ee9fdb653b9f4b6c0029"; - String libraryAddressPair = null; return TvmTestUtils .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, - feeLimit, consumeUserResourcePercent, libraryAddressPair, + feeLimit, consumeUserResourcePercent, null, dbManager, null); } - - /** - * Release resources. - */ - @After - public void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java index f9f586b87a6..ab34c29fefd 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java @@ -13,15 +13,12 @@ import org.junit.Ignore; import org.junit.Test; import org.springframework.util.StringUtils; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.parameter.CommonParameter; import org.tron.common.runtime.InternalTransaction; import org.tron.common.utils.FileUtil; -import org.tron.core.ChainBaseManager; import org.tron.core.Constant; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractValidateException; import org.tron.core.store.StoreFactory; import org.tron.core.vm.JumpTable; @@ -36,22 +33,16 @@ import org.tron.protos.Protocol; @Slf4j -public class OperationsTest { +public class OperationsTest extends BaseTest { private ProgramInvokeMockImpl invoke; private Program program; private final JumpTable jumpTable = OperationRegistry.newTronV10OperationSet(); - private static ChainBaseManager chainBaseManager; - private static String dbPath; - private static TronApplicationContext context; @BeforeClass public static void init() { - dbPath = "output_" + OperationsTest.class.getName(); + dbPath = "output_operations_test"; Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - Manager manager = context.getBean(Manager.class); - chainBaseManager = manager.getChainBaseManager(); CommonParameter.getInstance().setDebug(true); VMConfig.initAllowTvmTransferTrc10(1); VMConfig.initAllowTvmConstantinople(1); @@ -66,12 +57,7 @@ public static void destroy() { ConfigLoader.disable = false; VMConfig.initVmHardFork(false); Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.error("Release resources failure."); - } + FileUtil.deleteDir(new File(dbPath)); VMConfig.initAllowTvmTransferTrc10(0); VMConfig.initAllowTvmConstantinople(0); VMConfig.initAllowTvmSolidity059(0); @@ -196,7 +182,7 @@ public void testArithmeticOperations() throws ContractValidateException { // test MULMOD op = new byte[]{0x60, 0x02, 0x60, 0x01, 0x60, 0x01, 0x09}; - program = new Program(op, op, invoke, interTrx);; + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(17, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x01), program.getStack().pop()); @@ -254,7 +240,7 @@ public void testLogicAndComparisonOperations() throws ContractValidateException // test EQ = 0X14 op = new byte[]{0x60, 0x01, 0x60, 0x02, 0X14}; - program = new Program(op, op, invoke, interTrx);; + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x00), program.getStack().pop()); @@ -275,7 +261,7 @@ public void testLogicAndComparisonOperations() throws ContractValidateException // test OR = 0x17 op = new byte[]{0x60, 0x01, 0x60, 0x02, 0x17}; - program = new Program(op, op, invoke, interTrx);; + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x03), program.getStack().pop()); @@ -303,7 +289,7 @@ public void testLogicAndComparisonOperations() throws ContractValidateException // test SHL = 0x1b op = new byte[]{0x60, 0x01, 0x60, 0x01, 0x1b}; - program = new Program(op, op, invoke, interTrx);; + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed()); Assert.assertEquals(new DataWord(0x02), program.getStack().pop()); @@ -342,7 +328,7 @@ public void testCryptographicAndEnvironmentalOperations() throws ContractValidat // test ADDRESS = 0x30 op = new byte[]{0x30}; - program = new Program(op, op, invoke, interTrx);; + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(2, program.getResult().getEnergyUsed()); Assert.assertArrayEquals(invoke.getContractAddress().getLast20Bytes(), @@ -520,7 +506,7 @@ public void testMemoryStorageAndFlowOperations() throws ContractValidateExceptio // MSTORE8 = 0x53 op = new byte[]{0x60, 0x01, 0x60, 0x01, 0x53}; - program = new Program(op, op, invoke, interTrx);; + program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(9, program.getResult().getEnergyUsed(), 41); Assert.assertEquals(32, program.getMemSize()); @@ -897,10 +883,10 @@ private void testOperations(Program program) { } catch (Program.JVMStackOverFlowException | Program.OutOfTimeException e) { throw e; } catch (RuntimeException e) { - if (StringUtils.isEmpty(e.getMessage())) { - program.setRuntimeFailure(new RuntimeException("Unknown Exception")); - } else { + if (StringUtils.hasLength(e.getMessage())) { program.setRuntimeFailure(e); + } else { + program.setRuntimeFailure(new RuntimeException("Unknown Exception")); } } catch (StackOverflowError soe) { logger.info("\n !!! StackOverflowError: update your java run command with -Xss !!!\n", soe); @@ -937,10 +923,10 @@ private void testSingleOperation(Program program) { } catch (Program.JVMStackOverFlowException | Program.OutOfTimeException e) { throw e; } catch (RuntimeException e) { - if (StringUtils.isEmpty(e.getMessage())) { - program.setRuntimeFailure(new RuntimeException("Unknown Exception")); - } else { + if (StringUtils.hasLength(e.getMessage())) { program.setRuntimeFailure(e); + } else { + program.setRuntimeFailure(new RuntimeException("Unknown Exception")); } } catch (StackOverflowError soe) { logger.info("\n !!! StackOverflowError: update your java run command with -Xss !!!\n", soe); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index 492f9540df2..b4365f02338 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -6,27 +6,20 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; - import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.encoders.Hex; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.ProgramResult; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; import org.tron.common.utils.Commons; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -37,9 +30,7 @@ import org.tron.core.capsule.ProposalCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ItemNotFoundException; @@ -56,21 +47,17 @@ import org.tron.protos.contract.Common; @Slf4j -public class PrecompiledContractsTest { +public class PrecompiledContractsTest extends BaseTest { // common private static final DataWord voteContractAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000000010001"); - private static final DataWord withdrawBalanceAddr = new DataWord( - "0000000000000000000000000000000000000000000000000000000000010004"); private static final DataWord proposalApproveAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000000010005"); private static final DataWord proposalCreateAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000000010006"); private static final DataWord proposalDeleteAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000000010007"); - private static final DataWord convertFromTronBytesAddressAddr = new DataWord( - "0000000000000000000000000000000000000000000000000000000000010008"); private static final DataWord convertFromTronBase58AddressAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000000010009"); @@ -108,7 +95,6 @@ public class PrecompiledContractsTest { private static final DataWord totalAcquiredResourceAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000001000015"); - private static final String dbPath = "output_PrecompiledContracts_test"; private static final String ACCOUNT_NAME = "account"; private static final String OWNER_ADDRESS; private static final String WITNESS_NAME = "witness"; @@ -117,44 +103,16 @@ public class PrecompiledContractsTest { private static final String URL = "https://tron.network/"; // withdraw private static final long initBalance = 10_000_000_000L; - private static final long allowance = 32_000_000L; private static final long latestTimestamp = 1_000_000L; - private static TronApplicationContext context; - private static Application appT; - private static Manager dbManager; static { + dbPath = "output_PrecompiledContracts_test"; Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - appT = ApplicationFactory.create(context); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; WITNESS_ADDRESS = Wallet.getAddressPreFixString() + WITNESS_ADDRESS_BASE; } - - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ @@ -459,7 +417,6 @@ public void delegatableResourceTest() { // with usage. byte[] TOTAL_ENERGY_CURRENT_LIMIT = "TOTAL_ENERGY_CURRENT_LIMIT".getBytes(); - byte[] TOTAL_ENERGY_WEIGHT = "TOTAL_ENERGY_WEIGHT".getBytes(); long energyLimit = 1_000_000_000_000L; tempRepository.getDynamicPropertiesStore().put(TOTAL_ENERGY_CURRENT_LIMIT, @@ -1170,10 +1127,6 @@ public void totalAcquiredResourceTest() { Assert.assertEquals(0, ByteArray.toLong(res.getRight())); } - @Test - public void convertFromTronBytesAddressNativeTest() { - } - //@Test public void convertFromTronBase58AddressNative() { // 27WnTihwXsqCqpiNedWvtKCZHsLjDt4Hfmf TestNet address diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java index 8be1ebf88df..1053b759fe9 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java @@ -1,30 +1,24 @@ package org.tron.common.runtime.vm; import com.google.protobuf.ByteString; -import java.io.File; import java.math.BigInteger; import java.util.Arrays; import java.util.List; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.BeforeClass; import org.junit.Test; import org.tron.api.GrpcAPI.ShieldedTRC20Parameters; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.FileUtil; import org.tron.common.zksnark.IncrementalMerkleTreeContainer; import org.tron.common.zksnark.IncrementalMerkleVoucherContainer; import org.tron.common.zksnark.JLibrustzcash; import org.tron.common.zksnark.LibrustzcashParam; import org.tron.core.capsule.IncrementalMerkleTreeCapsule; import org.tron.core.capsule.PedersenHashCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ZksnarkException; import org.tron.core.services.http.FullNodeHttpApiService; import org.tron.core.vm.PrecompiledContracts.MerkleHash; @@ -45,20 +39,17 @@ import stest.tron.wallet.common.client.WalletClient; @Slf4j -public class PrecompiledContractsVerifyProofTest { +public class PrecompiledContractsVerifyProofTest extends BaseTest { - private static final String dbPath = "output_PrecompiledContracts_VerifyProof_test"; private static final String SHIELDED_CONTRACT_ADDRESS_STR = "TGAmX5AqVUoXCf8MoHxbuhQPmhGfWTnEgA"; private static final byte[] SHIELDED_CONTRACT_ADDRESS; private static final String PUBLIC_TO_ADDRESS_STR = "TBaBXpRAeBhs75TZT751LwyhrcR25XeUot"; private static final byte[] PUBLIC_TO_ADDRESS; private static final byte[] DEFAULT_OVK; - private static TronApplicationContext context; - private static Manager dbManager; static { + dbPath = "output_PrecompiledContracts_VerifyProof_test"; Args.setParam(new String[]{"--output-directory", dbPath}, "config-test.conf"); - context = new TronApplicationContext(DefaultConfig.class); DEFAULT_OVK = ByteArray .fromHexString("030c8c2bc59fb3eb8afb047a8ea4b028743d23e7d38c6fa30908358431e2314d"); SHIELDED_CONTRACT_ADDRESS = WalletClient.decodeFromBase58Check(SHIELDED_CONTRACT_ADDRESS_STR); @@ -71,28 +62,6 @@ public class PrecompiledContractsVerifyProofTest { VerifyBurnProof burnContract = new VerifyBurnProof(); MerkleHash merkleHash = new MerkleHash(); - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - @Test public void verifyMintProofCorrect() throws ZksnarkException { int totalCountNum = 2; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/RepositoryTest.java b/framework/src/test/java/org/tron/common/runtime/vm/RepositoryTest.java index 6323ef4aa40..390b1396337 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/RepositoryTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/RepositoryTest.java @@ -1,27 +1,22 @@ package org.tron.common.runtime.vm; -import java.io.File; import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.testng.Assert; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.parameter.CommonParameter; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.WalletUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.Parameter.ForkBlockVersionConsts; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; @@ -33,20 +28,19 @@ import org.tron.protos.Protocol.Transaction; @Slf4j -public class RepositoryTest { +public class RepositoryTest extends BaseTest { - private Manager manager; - private TronApplicationContext context; - private String dbPath = "output_DepostitTest"; - private String OWNER_ADDRESS; + private static final String OWNER_ADDRESS; private Repository rootRepository; + + static { + dbPath = "output_DepostitTest"; + Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; + } @Before public void init() { - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; - manager = context.getBean(Manager.class); rootRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); rootRepository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); rootRepository.addBalance(Hex.decode(OWNER_ADDRESS), 30000000000000L); @@ -102,9 +96,9 @@ public void loopCallTest() VMIllegalException, ContractValidateException { byte[] stats = new byte[27]; Arrays.fill(stats, (byte) 1); - this.manager.getDynamicPropertiesStore() + this.dbManager.getDynamicPropertiesStore() .statsByVersion(ForkBlockVersionConsts.ENERGY_LIMIT, stats); - this.manager.getDynamicPropertiesStore() + this.dbManager.getDynamicPropertiesStore() .saveLatestBlockHeaderNumber(CommonParameter.getInstance() .getBlockNumForEnergyLimit() + 1); @@ -206,7 +200,7 @@ public void loopCallTest() .parseAbi("callBcallARevert(address,uint256,uint256)", params1); TVMTestResult result = TvmTestUtils .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), - aAddress, triggerData, 0, fee, manager, null); + aAddress, triggerData, 0, fee, dbManager, null); Assert.assertNull(result.getRuntime().getRuntimeError()); // check result @@ -216,10 +210,10 @@ public void loopCallTest() TVMTestResult checkN1 = TvmTestUtils .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), - aAddress, checkN1Data, 0, fee, manager, null); + aAddress, checkN1Data, 0, fee, dbManager, null); TVMTestResult checkN2 = TvmTestUtils .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), - aAddress, checkN2Data, 0, fee, manager, null); + aAddress, checkN2Data, 0, fee, dbManager, null); System.out.println(Hex.toHexString(checkN1.getRuntime().getResult().getHReturn())); System.out.println(Hex.toHexString(checkN2.getRuntime().getResult().getHReturn())); @@ -238,14 +232,14 @@ public void loopCallTest() triggerData = TvmTestUtils.parseAbi("callBcallA(address,uint256,uint256)", params2); result = TvmTestUtils .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), - aAddress, triggerData, 0, fee, manager, null); + aAddress, triggerData, 0, fee, dbManager, null); Assert.assertNull(result.getRuntime().getRuntimeError()); checkN1 = TvmTestUtils .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), - aAddress, checkN1Data, 0, fee, manager, null); + aAddress, checkN1Data, 0, fee, dbManager, null); checkN2 = TvmTestUtils .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), - aAddress, checkN2Data, 0, fee, manager, null); + aAddress, checkN2Data, 0, fee, dbManager, null); System.out.println(Hex.toHexString(checkN1.getRuntime().getResult().getHReturn())); System.out.println(Hex.toHexString(checkN2.getRuntime().getResult().getHReturn())); Assert.assertEquals(checkN1.getRuntime().getResult().getHReturn(), @@ -262,7 +256,7 @@ public void loopCallTestOldVersion() VMIllegalException, ContractValidateException { byte[] stats = new byte[27]; Arrays.fill(stats, (byte) 0); - this.manager.getDynamicPropertiesStore() + this.dbManager.getDynamicPropertiesStore() .statsByVersion(ForkBlockVersionConsts.ENERGY_LIMIT, stats); String contractA = "A"; @@ -360,7 +354,7 @@ public void loopCallTestOldVersion() .parseAbi("callBcallARevert(address,uint256,uint256)", params1); TVMTestResult result = TvmTestUtils .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), - aAddress, triggerData, 0, fee, manager, null); + aAddress, triggerData, 0, fee, dbManager, null); Assert.assertNull(result.getRuntime().getRuntimeError()); // check result @@ -370,10 +364,10 @@ public void loopCallTestOldVersion() TVMTestResult checkN1 = TvmTestUtils .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), - aAddress, checkN1Data, 0, fee, manager, null); + aAddress, checkN1Data, 0, fee, dbManager, null); TVMTestResult checkN2 = TvmTestUtils .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), - aAddress, checkN2Data, 0, fee, manager, null); + aAddress, checkN2Data, 0, fee, dbManager, null); System.out.println(Hex.toHexString(checkN1.getRuntime().getResult().getHReturn())); System.out.println(Hex.toHexString(checkN2.getRuntime().getResult().getHReturn())); @@ -392,14 +386,14 @@ public void loopCallTestOldVersion() triggerData = TvmTestUtils.parseAbi("callBcallA(address,uint256,uint256)", params2); result = TvmTestUtils .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), - aAddress, triggerData, 0, fee, manager, null); + aAddress, triggerData, 0, fee, dbManager, null); Assert.assertNull(result.getRuntime().getRuntimeError()); checkN1 = TvmTestUtils .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), - aAddress, checkN1Data, 0, fee, manager, null); + aAddress, checkN1Data, 0, fee, dbManager, null); checkN2 = TvmTestUtils .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), - aAddress, checkN2Data, 0, fee, manager, null); + aAddress, checkN2Data, 0, fee, dbManager, null); System.out.println(Hex.toHexString(checkN1.getRuntime().getResult().getHReturn())); System.out.println(Hex.toHexString(checkN2.getRuntime().getResult().getHReturn())); Assert.assertEquals(checkN1.getRuntime().getResult().getHReturn(), @@ -409,17 +403,4 @@ public void loopCallTestOldVersion() new DataWord(1000).getData()); CommonParameter.setENERGY_LIMIT_HARD_FORK(false); } - - - @After - public void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.error("Release resources failure."); - } - } - } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java b/framework/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java index c5ac42e93ce..2c04b302c49 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java @@ -1,24 +1,17 @@ package org.tron.common.runtime.vm; -import java.io.File; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.testng.Assert; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; @@ -29,27 +22,24 @@ @Slf4j @Ignore -public class TimeBenchmarkTest { +public class TimeBenchmarkTest extends BaseTest { - private Manager dbManager; - private TronApplicationContext context; private RepositoryImpl repository; - private String dbPath = "output_TimeBenchmarkTest"; - private String OWNER_ADDRESS; - private Application AppT; + private static final String OWNER_ADDRESS; private long totalBalance = 30_000_000_000_000L; + static { + dbPath = "output_TimeBenchmarkTest"; + Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; + } + /** * Init data. */ @Before public void init() { - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - AppT = ApplicationFactory.create(context); - OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; - dbManager = context.getBean(Manager.class); repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); repository.createAccount(Hex.decode(OWNER_ADDRESS), AccountType.Normal); repository.addBalance(Hex.decode(OWNER_ADDRESS), totalBalance); @@ -137,23 +127,9 @@ public void timeBenchmark() long expectEnergyUsageTotal2 = 110; Assert.assertEquals(result.getReceipt().getEnergyUsageTotal(), expectEnergyUsageTotal2); - Assert.assertEquals(result.getRuntime().getResult().isRevert(), true); - Assert.assertTrue(result.getRuntime().getResult().getException() == null); + Assert.assertTrue(result.getRuntime().getResult().isRevert()); + Assert.assertNull(result.getRuntime().getResult().getException()); Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - (expectEnergyUsageTotal + expectEnergyUsageTotal2) * 100); } - - /** - * Release resources. - */ - @After - public void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java b/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java index aa6fccecc7a..cd79e00eb29 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java @@ -1,24 +1,19 @@ package org.tron.common.runtime.vm; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.AfterClass; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.crypto.ECKey; import org.tron.common.runtime.ProgramResult; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.common.utils.Utils; -import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.actuator.VMActuator; @@ -26,9 +21,7 @@ import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.db.TransactionContext; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; @@ -43,9 +36,8 @@ import stest.tron.wallet.common.client.utils.AbiUtil; @Slf4j -public class TransferToAccountTest { +public class TransferToAccountTest extends BaseTest { - private static final String dbPath = "output_TransferToAccountTest"; private static final String OWNER_ADDRESS; private static final String TRANSFER_TO; private static final long TOTAL_SUPPLY = 1000_000_000L; @@ -57,21 +49,18 @@ public class TransferToAccountTest { private static final String DESCRIPTION = "TRX"; private static final String URL = "https://tron.network/"; private static Runtime runtime; - private static Manager dbManager; - private static ChainBaseManager chainBaseManager; - private static TronApplicationContext context; - private static Application appT; private static RepositoryImpl repository; private static AccountCapsule ownerCapsule; static { + dbPath = "output_TransferToAccountTest"; Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - appT = ApplicationFactory.create(context); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; TRANSFER_TO = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; - dbManager = context.getBean(Manager.class); - chainBaseManager = context.getBean(ChainBaseManager.class); + } + + @Before + public void before() { repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); repository.createAccount(Hex.decode(TRANSFER_TO), AccountType.Normal); repository.addBalance(Hex.decode(TRANSFER_TO), 10); @@ -85,20 +74,6 @@ public class TransferToAccountTest { ownerCapsule.setBalance(1000_1000_1000L); } - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - private long createAsset(String tokenName) { chainBaseManager.getDynamicPropertiesStore().saveAllowSameTokenName(1); chainBaseManager.getDynamicPropertiesStore().saveAllowTvmTransferTrc10(1); @@ -250,7 +225,6 @@ public void TransferTokenTest() // 9.Test transferToken Big Amount selectorStr = "transferTokenTo(address,trcToken,uint256)"; - ecKey = new ECKey(Utils.getRandom()); String params = "000000000000000000000000548794500882809695a8a687866e76d4271a1abc" + Hex.toHexString(new DataWord(id).getData()) + "0000000000000000000000000000000011111111111111111111111111111111"; @@ -318,10 +292,9 @@ private byte[] deployTransferContract(long id) long tokenValue = 100; long tokenId = id; - byte[] contractAddress = TvmTestUtils + return TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, null, tokenValue, tokenId, repository, null); - return contractAddress; } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java b/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java index 754c03118a5..bc9a60a9704 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java @@ -1,26 +1,20 @@ package org.tron.common.runtime.vm; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.AfterClass; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; @@ -32,9 +26,8 @@ import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; @Slf4j -public class TransferTokenTest { +public class TransferTokenTest extends BaseTest { - private static final String dbPath = "output_TransferTokenTest"; private static final String OWNER_ADDRESS; private static final String TRANSFER_TO; private static final long TOTAL_SUPPLY = 1000_000_000L; @@ -46,20 +39,19 @@ public class TransferTokenTest { private static final String DESCRIPTION = "TRX"; private static final String URL = "https://tron.network/"; private static Runtime runtime; - private static Manager dbManager; - private static TronApplicationContext context; - private static Application appT; private static RepositoryImpl repository; private static AccountCapsule ownerCapsule; static { + dbPath = "output_TransferTokenTest"; Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - appT = ApplicationFactory.create(context); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; TRANSFER_TO = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; - dbManager = context.getBean(Manager.class); + } + + @Before + public void before() { repository = RepositoryImpl.createRoot(StoreFactory.getInstance()); repository.createAccount(Hex.decode(TRANSFER_TO), AccountType.Normal); repository.addBalance(Hex.decode(TRANSFER_TO), 10); @@ -73,20 +65,6 @@ public class TransferTokenTest { ownerCapsule.setBalance(1000_1000_1000L); } - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - private long createAsset(String tokenName) { dbManager.getDynamicPropertiesStore().saveAllowSameTokenName(1); dbManager.getDynamicPropertiesStore().saveAllowTvmTransferTrc10(1); @@ -116,13 +94,11 @@ private long createAsset(String tokenName) { /** * pragma solidity ^0.4.24; - * * contract tokenTest{ constructor() public payable{} // positive case function * TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ * toAddress.transferToken(amount,id); } function suicide(address toAddress) payable public{ * selfdestruct(toAddress); } function get(trcToken trc) public payable returns(uint256){ return * address(this).tokenBalance(trc); } } - * * 1. deploy 2. trigger and internal transaction 3. suicide (all token) */ @Test diff --git a/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java b/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java index 4ce516cd11f..1ee561aa97d 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java @@ -1,32 +1,27 @@ package org.tron.common.runtime.vm; import com.google.protobuf.ByteString; -import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; import org.bouncycastle.util.encoders.Hex; -import org.junit.AfterClass; +import org.junit.Before; import org.junit.Test; import org.testng.Assert; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.crypto.ECKey; import org.tron.common.crypto.Hash; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.StringUtil; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.store.StoreFactory; import org.tron.core.vm.PrecompiledContracts.ValidateMultiSign; import org.tron.core.vm.repository.Repository; @@ -35,41 +30,24 @@ import stest.tron.wallet.common.client.utils.AbiUtil; @Slf4j -public class ValidateMultiSignContractTest { +public class ValidateMultiSignContractTest extends BaseTest { - private static final String dbPath = "output_ValidateMultiSignContract_test"; private static final String METHOD_SIGN = "validatemultisign(address,uint256,bytes32,bytes[])"; private static final byte[] longData; - private static TronApplicationContext context; - private static Application appT; - private static Manager dbManager; static { + dbPath = "output_ValidateMultiSignContract_test"; Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - appT = ApplicationFactory.create(context); - dbManager = context.getBean(Manager.class); - dbManager.getDynamicPropertiesStore().saveAllowMultiSign(1); - dbManager.getDynamicPropertiesStore().saveTotalSignNum(5); - longData = new byte[1000000]; Arrays.fill(longData, (byte) 2); } ValidateMultiSign contract = new ValidateMultiSign(); - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } + @Before + public void before() { + dbManager.getDynamicPropertiesStore().saveAllowMultiSign(1); + dbManager.getDynamicPropertiesStore().saveTotalSignNum(5); } @Test @@ -116,7 +94,8 @@ public void testDifferentCase() { .build(); toAccount - .updatePermissions(toAccount.getPermissionById(0), null, Arrays.asList(activePermission)); + .updatePermissions(toAccount.getPermissionById(0), null, + Collections.singletonList(activePermission)); dbManager.getAccountStore().put(key.getAddress(), toAccount); //generate data diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index b353f665823..34b585b1252 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -346,7 +346,6 @@ public void testGetAddress() { @Test public void testGetEcKey() { ECKey ecKey = new ECKey(Utils.getRandom()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); Wallet wallet1 = new Wallet(ecKey); logger.info("ecKey address = {}", ByteArray.toHexString(ecKey .getAddress())); @@ -477,8 +476,7 @@ public void getBlockByLatestNum() { public void getPaginatedAssetIssueList() { buildAssetIssue(); AssetIssueList assetList1 = wallet.getAssetIssueList(0, 100); - Assert.assertTrue("get Asset1", - assetList1.getAssetIssue(0).getName().equals(Asset1.getName())); + assertEquals("get Asset1", assetList1.getAssetIssue(0).getName(), Asset1.getName()); try { assetList1.getAssetIssue(1); } catch (Exception e) { @@ -581,7 +579,7 @@ public void testChainParameters() { }); - System.out.printf(builder.build().toString()); + System.out.print(builder.build()); } @Test diff --git a/framework/src/test/java/org/tron/core/actuator/VoteWitnessActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/VoteWitnessActuatorTest.java index 26e4e7364b9..cedd147dbaa 100644 --- a/framework/src/test/java/org/tron/core/actuator/VoteWitnessActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/VoteWitnessActuatorTest.java @@ -48,6 +48,8 @@ public class VoteWitnessActuatorTest extends BaseTest { @Resource private ConsensusService consensusService; + private static boolean consensusStart; + static { dbPath = "output_VoteWitness_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); @@ -66,8 +68,6 @@ public class VoteWitnessActuatorTest extends BaseTest { */ @Before public void createCapsule() { - consensusService.start(); - WitnessCapsule ownerCapsule = new WitnessCapsule( StringUtil.hexString2ByteString(WITNESS_ADDRESS), @@ -91,6 +91,12 @@ public void createCapsule() { dbManager.getAccountStore() .put(ownerAccountFirstCapsule.getAddress().toByteArray(), ownerAccountFirstCapsule); dbManager.getWitnessStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + + if (consensusStart) { + return; + } + consensusService.start(); + consensusStart = true; } private Any getContract(String address, String voteaddress, Long value) { @@ -174,7 +180,6 @@ public void InvalidAddress() { actuator.execute(ret); fail("Invalid address"); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Invalid address", e.getMessage()); maintenanceManager.doMaintenance(); WitnessCapsule witnessCapsule = dbManager.getWitnessStore() @@ -271,7 +276,7 @@ public void invalideVoteAddress() { try { actuator.validate(); actuator.execute(ret); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals(0, dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)).getVotesList().size()); diff --git a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java index ed19516a608..f70884aa88c 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java @@ -1,82 +1,55 @@ package org.tron.core.actuator.utils; import com.google.protobuf.ByteString; -import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.ForkController; import org.tron.core.Constant; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.Parameter; import org.tron.core.config.Parameter.ForkBlockVersionEnum; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractValidateException; import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.utils.ProposalUtil; import org.tron.core.utils.ProposalUtil.ProposalType; @Slf4j(topic = "actuator") -public class ProposalUtilTest { +public class ProposalUtilTest extends BaseTest { - private static final String dbPath = "output_ProposalUtil_test"; private static final long LONG_VALUE = 100_000_000_000_000_000L; private static final String LONG_VALUE_ERROR = "Bad chain parameter value, valid range is [0," + LONG_VALUE + "]"; - public static Application AppT; - private static TronApplicationContext context; - private static Manager dbManager; /** * Init . */ @BeforeClass public static void init() { + dbPath = "output_ProposalUtil_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - dbManager = context.getBean(Manager.class); - AppT = ApplicationFactory.create(context); } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - + @Test public void validProposalTypeCheck() throws ContractValidateException { - Assert.assertEquals(false, ProposalType.contain(4000)); - Assert.assertEquals(false, ProposalType.contain(-1)); - Assert.assertEquals(true, ProposalType.contain(2)); + Assert.assertFalse(ProposalType.contain(4000)); + Assert.assertFalse(ProposalType.contain(-1)); + Assert.assertTrue(ProposalType.contain(2)); - Assert.assertEquals(null, ProposalType.getEnumOrNull(-2)); + Assert.assertNull(ProposalType.getEnumOrNull(-2)); Assert.assertEquals(ProposalType.ALLOW_TVM_SOLIDITY_059, ProposalType.getEnumOrNull(32)); long code = -1; try { ProposalType.getEnum(code); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals("Does not support code : " + code, e.getMessage()); } @@ -88,128 +61,126 @@ public void validProposalTypeCheck() throws ContractValidateException { @Test public void validateCheck() { - ProposalUtil actuatorUtil = new ProposalUtil(); DynamicPropertiesStore dynamicPropertiesStore = null; ForkController forkUtils = ForkController.instance(); long invalidValue = -1; try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.ACCOUNT_UPGRADE_COST.getCode(), invalidValue); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals(LONG_VALUE_ERROR, e.getMessage()); } try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.ACCOUNT_UPGRADE_COST.getCode(), LONG_VALUE + 1); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals(LONG_VALUE_ERROR, e.getMessage()); } try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.CREATE_ACCOUNT_FEE.getCode(), invalidValue); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals(LONG_VALUE_ERROR, e.getMessage()); } try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.CREATE_ACCOUNT_FEE.getCode(), LONG_VALUE + 1); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals(LONG_VALUE_ERROR, e.getMessage()); } try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.ASSET_ISSUE_FEE.getCode(), invalidValue); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals(LONG_VALUE_ERROR, e.getMessage()); } try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.ASSET_ISSUE_FEE.getCode(), LONG_VALUE + 1); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals(LONG_VALUE_ERROR, e.getMessage()); } try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.WITNESS_PAY_PER_BLOCK.getCode(), invalidValue); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals(LONG_VALUE_ERROR, e.getMessage()); } try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.WITNESS_PAY_PER_BLOCK.getCode(), LONG_VALUE + 1); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals(LONG_VALUE_ERROR, e.getMessage()); } try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.WITNESS_STANDBY_ALLOWANCE.getCode(), invalidValue); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals(LONG_VALUE_ERROR, e.getMessage()); } try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.WITNESS_STANDBY_ALLOWANCE.getCode(), LONG_VALUE + 1); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals(LONG_VALUE_ERROR, e.getMessage()); } try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.CREATE_NEW_ACCOUNT_FEE_IN_SYSTEM_CONTRACT.getCode(), invalidValue); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals(LONG_VALUE_ERROR, e.getMessage()); } try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.CREATE_NEW_ACCOUNT_FEE_IN_SYSTEM_CONTRACT.getCode(), LONG_VALUE + 1); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals(LONG_VALUE_ERROR, e.getMessage()); } try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.CREATE_NEW_ACCOUNT_BANDWIDTH_RATE.getCode(), invalidValue); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals(LONG_VALUE_ERROR, e.getMessage()); } try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.CREATE_NEW_ACCOUNT_BANDWIDTH_RATE.getCode(), LONG_VALUE + 1); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals(LONG_VALUE_ERROR, e.getMessage()); } - long value = 32; try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.MAINTENANCE_TIME_INTERVAL.getCode(), 3 * 27 * 1000 - 1); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals( "Bad chain parameter value, valid range is [3 * 27 * 1000,24 * 3600 * 1000]", @@ -217,9 +188,9 @@ public void validateCheck() { } try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.MAINTENANCE_TIME_INTERVAL.getCode(), 24 * 3600 * 1000 + 1); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals( "Bad chain parameter value, valid range is [3 * 27 * 1000,24 * 3600 * 1000]", @@ -227,9 +198,9 @@ public void validateCheck() { } try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.ALLOW_CREATION_OF_CONTRACTS.getCode(), 2); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals( "This value[ALLOW_CREATION_OF_CONTRACTS] is only allowed to be 1", @@ -239,9 +210,9 @@ public void validateCheck() { dynamicPropertiesStore = dbManager.getDynamicPropertiesStore(); dynamicPropertiesStore.saveRemoveThePowerOfTheGr(1); try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.REMOVE_THE_POWER_OF_THE_GR.getCode(), 2); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals( "This value[REMOVE_THE_POWER_OF_THE_GR] is only allowed to be 1", @@ -250,9 +221,9 @@ public void validateCheck() { dynamicPropertiesStore.saveRemoveThePowerOfTheGr(-1); try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.REMOVE_THE_POWER_OF_THE_GR.getCode(), 1); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals( "This proposal has been executed before and is only allowed to be executed once", @@ -260,27 +231,27 @@ public void validateCheck() { } try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.MAX_CPU_TIME_OF_ONE_TX.getCode(), 9); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals( "Bad chain parameter value, valid range is [10,100]", e.getMessage()); } try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.MAX_CPU_TIME_OF_ONE_TX.getCode(), 101); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals( "Bad chain parameter value, valid range is [10,100]", e.getMessage()); } try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.ALLOW_DELEGATE_RESOURCE.getCode(), 2); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals( "This value[ALLOW_DELEGATE_RESOURCE] is only allowed to be 1", e.getMessage()); @@ -288,9 +259,9 @@ public void validateCheck() { dynamicPropertiesStore.saveAllowSameTokenName(1); try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.ALLOW_TVM_TRANSFER_TRC10.getCode(), 2); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals( "This value[ALLOW_TVM_TRANSFER_TRC10] is only allowed to be 1", e.getMessage()); @@ -298,9 +269,9 @@ public void validateCheck() { dynamicPropertiesStore.saveAllowSameTokenName(0); try { - actuatorUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, ProposalType.ALLOW_TVM_TRANSFER_TRC10.getCode(), 1); - Assert.assertTrue(false); + Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals("[ALLOW_SAME_TOKEN_NAME] proposal must be approved " + "before [ALLOW_TVM_TRANSFER_TRC10] can be proposed", e.getMessage()); diff --git a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java index a46bf546821..ad8846743e5 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java @@ -1,147 +1,117 @@ package org.tron.core.actuator.utils; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.tron.core.capsule.utils.TransactionUtil.isNumber; -import java.io.File; -import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; -import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; +import org.tron.common.BaseTest; import org.tron.core.Constant; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.utils.TransactionUtil; @Slf4j(topic = "capsule") -public class TransactionUtilTest { - - private static final String dbPath = "output_transactionUtil_test"; - public static Application AppT; - private static TronApplicationContext context; +public class TransactionUtilTest extends BaseTest { /** * Init . */ @BeforeClass public static void init() { + dbPath = "output_transactionUtil_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - AppT = ApplicationFactory.create(context); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } @Test - public void validAccountNameCheck() throws UnsupportedEncodingException { - TransactionUtil actuatorUtil = new TransactionUtil(); + public void validAccountNameCheck() { String account = ""; - Assert.assertEquals(true, actuatorUtil.validAccountName(account.getBytes("utf-8"))); + assertTrue(TransactionUtil.validAccountName(account.getBytes(StandardCharsets.UTF_8))); for (int i = 0; i < 200; i++) { account += (char) ('a' + (i % 26)); } - Assert.assertEquals(true, actuatorUtil.validAccountName(account.getBytes("utf-8"))); + assertTrue(TransactionUtil.validAccountName(account.getBytes(StandardCharsets.UTF_8))); account += 'z'; - Assert.assertEquals(false, actuatorUtil.validAccountName(account.getBytes("utf-8"))); + assertFalse(TransactionUtil.validAccountName(account.getBytes(StandardCharsets.UTF_8))); } @Test - public void validAccountIdCheck() throws UnsupportedEncodingException { - TransactionUtil actuatorUtil = new TransactionUtil(); + public void validAccountIdCheck() { String accountId = ""; - Assert.assertEquals(false, actuatorUtil.validAccountId(accountId.getBytes("utf-8"))); + assertFalse(TransactionUtil.validAccountId(accountId.getBytes(StandardCharsets.UTF_8))); for (int i = 0; i < 7; i++) { accountId += (char) ('a' + (i % 26)); } - Assert.assertEquals(false, actuatorUtil.validAccountId(accountId.getBytes("utf-8"))); + assertFalse(TransactionUtil.validAccountId(accountId.getBytes(StandardCharsets.UTF_8))); for (int i = 0; i < 26; i++) { accountId += (char) ('a' + (i % 26)); } - Assert.assertEquals(false, actuatorUtil.validAccountId(accountId.getBytes("utf-8"))); + assertFalse(TransactionUtil.validAccountId(accountId.getBytes(StandardCharsets.UTF_8))); accountId = "ab cdefghij"; - Assert.assertEquals(false, actuatorUtil.validAccountId(accountId.getBytes("utf-8"))); - accountId = Character.toString((char) 128) + "abcdefjijk" + Character.toString((char) 129); - Assert.assertEquals(false, actuatorUtil.validAccountId(accountId.getBytes("utf-8"))); + assertFalse(TransactionUtil.validAccountId(accountId.getBytes(StandardCharsets.UTF_8))); + accountId = (char) 128 + "abcdefjijk" + (char) 129; + assertFalse(TransactionUtil.validAccountId(accountId.getBytes(StandardCharsets.UTF_8))); accountId = ""; for (int i = 0; i < 30; i++) { accountId += (char) ('a' + (i % 26)); } - Assert.assertEquals(true, actuatorUtil.validAccountId(accountId.getBytes("utf-8"))); + assertTrue(TransactionUtil.validAccountId(accountId.getBytes(StandardCharsets.UTF_8))); } @Test - public void validAssetNameCheck() throws UnsupportedEncodingException { - TransactionUtil actuatorUtil = new TransactionUtil(); + public void validAssetNameCheck() { String assetName = ""; - Assert.assertEquals(false, actuatorUtil.validAssetName(assetName.getBytes("utf-8"))); + assertFalse(TransactionUtil.validAssetName(assetName.getBytes(StandardCharsets.UTF_8))); for (int i = 0; i < 33; i++) { assetName += (char) ('a' + (i % 26)); } - Assert.assertEquals(false, actuatorUtil.validAssetName(assetName.getBytes("utf-8"))); + assertFalse(TransactionUtil.validAssetName(assetName.getBytes(StandardCharsets.UTF_8))); assetName = "ab cdefghij"; - Assert.assertEquals(false, actuatorUtil.validAssetName(assetName.getBytes("utf-8"))); - assetName = Character.toString((char) 128) + "abcdefjijk" + Character.toString((char) 129); - Assert.assertEquals(false, actuatorUtil.validAssetName(assetName.getBytes("utf-8"))); + assertFalse(TransactionUtil.validAssetName(assetName.getBytes(StandardCharsets.UTF_8))); + assetName = (char) 128 + "abcdefjijk" + (char) 129; + assertFalse(TransactionUtil.validAssetName(assetName.getBytes(StandardCharsets.UTF_8))); assetName = ""; for (int i = 0; i < 20; i++) { assetName += (char) ('a' + (i % 26)); } - Assert.assertEquals(true, actuatorUtil.validAssetName(assetName.getBytes("utf-8"))); + assertTrue(TransactionUtil.validAssetName(assetName.getBytes(StandardCharsets.UTF_8))); } @Test - public void validTokenAbbrNameCheck() throws UnsupportedEncodingException { - - TransactionUtil actuatorUtil = new TransactionUtil(); + public void validTokenAbbrNameCheck() { String abbrName = ""; - Assert.assertEquals(false, actuatorUtil.validTokenAbbrName(abbrName.getBytes("utf-8"))); + assertFalse(TransactionUtil.validTokenAbbrName(abbrName.getBytes(StandardCharsets.UTF_8))); for (int i = 0; i < 6; i++) { abbrName += (char) ('a' + (i % 26)); } - Assert.assertEquals(false, actuatorUtil.validTokenAbbrName(abbrName.getBytes("utf-8"))); + assertFalse(TransactionUtil.validTokenAbbrName(abbrName.getBytes(StandardCharsets.UTF_8))); abbrName = "a bd"; - Assert.assertEquals(false, actuatorUtil.validTokenAbbrName(abbrName.getBytes("utf-8"))); - abbrName = "a" + Character.toString((char) 129) + 'f'; - Assert.assertEquals(false, actuatorUtil.validTokenAbbrName(abbrName.getBytes("utf-8"))); + assertFalse(TransactionUtil.validTokenAbbrName(abbrName.getBytes(StandardCharsets.UTF_8))); + abbrName = "a" + (char) 129 + 'f'; + assertFalse(TransactionUtil.validTokenAbbrName(abbrName.getBytes(StandardCharsets.UTF_8))); abbrName = ""; for (int i = 0; i < 5; i++) { abbrName += (char) ('a' + (i % 26)); } - Assert.assertEquals(true, actuatorUtil.validTokenAbbrName(abbrName.getBytes("utf-8"))); + assertTrue(TransactionUtil.validTokenAbbrName(abbrName.getBytes(StandardCharsets.UTF_8))); } @Test - public void isNumberCheck() throws UnsupportedEncodingException { - TransactionUtil actuatorUtil = new TransactionUtil(); + public void isNumberCheck() { String number = ""; - Assert.assertEquals(false, isNumber(number.getBytes("utf-8"))); + assertFalse(isNumber(number.getBytes(StandardCharsets.UTF_8))); number = "123df34"; - Assert.assertEquals(false, isNumber(number.getBytes("utf-8"))); + assertFalse(isNumber(number.getBytes(StandardCharsets.UTF_8))); number = "013"; - Assert.assertEquals(false, isNumber(number.getBytes("utf-8"))); + assertFalse(isNumber(number.getBytes(StandardCharsets.UTF_8))); number = "24"; - Assert.assertEquals(true, isNumber(number.getBytes("utf-8"))); + assertTrue(isNumber(number.getBytes(StandardCharsets.UTF_8))); } } diff --git a/framework/src/test/java/org/tron/core/actuator/utils/ZenChainParamsTest.java b/framework/src/test/java/org/tron/core/actuator/utils/ZenChainParamsTest.java index 3fd3a352a48..952aab1a91d 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/ZenChainParamsTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/ZenChainParamsTest.java @@ -1,74 +1,38 @@ package org.tron.core.actuator.utils; -import java.io.File; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; -import org.tron.core.Constant; -import org.tron.core.config.DefaultConfig; -import org.tron.core.config.args.Args; import org.tron.core.utils.ZenChainParams; @Slf4j(topic = "capsule") public class ZenChainParamsTest { - private static final String dbPath = "output_zenchainparams_test"; - public static Application AppT; - private static TronApplicationContext context; - - /** - * Init . - */ - @BeforeClass - public static void init() { - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - AppT = ApplicationFactory.create(context); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - @Test public void variableCheck() { - ZenChainParams actuatorUtils = new ZenChainParams(); - Assert.assertEquals(16, actuatorUtils.NOTEENCRYPTION_AUTH_BYTES); - Assert.assertEquals(1, actuatorUtils.ZC_NOTEPLAINTEXT_LEADING); - Assert.assertEquals(8, actuatorUtils.ZC_V_SIZE); - Assert.assertEquals(32, actuatorUtils.ZC_R_SIZE); - Assert.assertEquals(512, actuatorUtils.ZC_MEMO_SIZE); - Assert.assertEquals(11, actuatorUtils.ZC_DIVERSIFIER_SIZE); - Assert.assertEquals(32, actuatorUtils.ZC_JUBJUB_POINT_SIZE); - Assert.assertEquals(32, actuatorUtils.ZC_JUBJUB_SCALAR_SIZE); + ZenChainParams zenChainParams = new ZenChainParams(); + assertNotNull(zenChainParams); + assertEquals(16, ZenChainParams.NOTEENCRYPTION_AUTH_BYTES); + assertEquals(1, ZenChainParams.ZC_NOTEPLAINTEXT_LEADING); + assertEquals(8, ZenChainParams.ZC_V_SIZE); + assertEquals(32, ZenChainParams.ZC_R_SIZE); + assertEquals(512, ZenChainParams.ZC_MEMO_SIZE); + assertEquals(11, ZenChainParams.ZC_DIVERSIFIER_SIZE); + assertEquals(32, ZenChainParams.ZC_JUBJUB_POINT_SIZE); + assertEquals(32, ZenChainParams.ZC_JUBJUB_SCALAR_SIZE); int ZC_ENCPLAINTEXT_SIZE = - actuatorUtils.ZC_NOTEPLAINTEXT_LEADING + actuatorUtils.ZC_DIVERSIFIER_SIZE - + actuatorUtils.ZC_V_SIZE + actuatorUtils.ZC_R_SIZE + actuatorUtils.ZC_MEMO_SIZE; - Assert.assertEquals(ZC_ENCPLAINTEXT_SIZE, actuatorUtils.ZC_ENCPLAINTEXT_SIZE); - int ZC_ENCCIPHERTEXT_SIZE = (actuatorUtils.ZC_ENCPLAINTEXT_SIZE - + actuatorUtils.NOTEENCRYPTION_AUTH_BYTES); - Assert.assertEquals(ZC_ENCCIPHERTEXT_SIZE, actuatorUtils.ZC_ENCCIPHERTEXT_SIZE); - int ZC_OUTCIPHERTEXT_SIZE = (actuatorUtils.ZC_OUTPLAINTEXT_SIZE - + actuatorUtils.NOTEENCRYPTION_AUTH_BYTES); - Assert.assertEquals(ZC_OUTCIPHERTEXT_SIZE, actuatorUtils.ZC_OUTCIPHERTEXT_SIZE); - Assert.assertTrue(actuatorUtils instanceof ZenChainParams); + ZenChainParams.ZC_NOTEPLAINTEXT_LEADING + ZenChainParams.ZC_DIVERSIFIER_SIZE + + ZenChainParams.ZC_V_SIZE + ZenChainParams.ZC_R_SIZE + ZenChainParams.ZC_MEMO_SIZE; + assertEquals(ZenChainParams.ZC_ENCPLAINTEXT_SIZE, ZC_ENCPLAINTEXT_SIZE); + int ZC_ENCCIPHERTEXT_SIZE = (ZenChainParams.ZC_ENCPLAINTEXT_SIZE + + ZenChainParams.NOTEENCRYPTION_AUTH_BYTES); + assertEquals(ZenChainParams.ZC_ENCCIPHERTEXT_SIZE, ZC_ENCCIPHERTEXT_SIZE); + int ZC_OUTCIPHERTEXT_SIZE = (ZenChainParams.ZC_OUTPLAINTEXT_SIZE + + ZenChainParams.NOTEENCRYPTION_AUTH_BYTES); + assertEquals(ZenChainParams.ZC_OUTCIPHERTEXT_SIZE, ZC_OUTCIPHERTEXT_SIZE); } } diff --git a/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java index 6c97848cd70..65aab3e9e7a 100644 --- a/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java @@ -1,34 +1,25 @@ package org.tron.core.capsule; import com.google.protobuf.ByteString; -import java.io.File; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Random; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Key; import org.tron.protos.Protocol.Permission; import org.tron.protos.Protocol.Vote; import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -public class AccountCapsuleTest { +public class AccountCapsuleTest extends BaseTest { - private static final String dbPath = "output_accountCapsule_test"; - private static final Manager dbManager; - private static final TronApplicationContext context; private static final String OWNER_ADDRESS; private static final String ASSET_NAME = "trx"; private static final long TOTAL_SUPPLY = 10000L; @@ -45,10 +36,8 @@ public class AccountCapsuleTest { static AccountCapsule accountCapsule; static { + dbPath = "output_accountCapsule_test"; Args.setParam(new String[]{"-d", dbPath, "-w"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - dbManager = context.getBean(Manager.class); - OWNER_ADDRESS = Wallet.getAddressPreFixString() + "a06a17a49648a8ad32055c06f60fa14ae46df91234"; } @@ -64,13 +53,6 @@ public static void init() { accountCapsuleTest.setBalance(1111L); } - @AfterClass - public static void removeDb() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } - public static byte[] randomBytes(int length) { //generate the random number byte[] result = new byte[length]; @@ -129,9 +111,8 @@ public void AssetAmountTest() { Assert.assertEquals(nameAdd, entry.getKey()); Assert.assertEquals(amountAdd - amountReduce, entry.getValue().longValue()); } - String key = nameAdd; long value = 11L; - boolean addAsssetBoolean = accountCapsuleTest.addAsset(key.getBytes(), value); + boolean addAsssetBoolean = accountCapsuleTest.addAsset(nameAdd.getBytes(), value); Assert.assertFalse(addAsssetBoolean); String keyName = "TokenTest"; @@ -193,9 +174,9 @@ public void sameTokenNameCloseAssertAmountV2test() { dbManager.getAccountStore().put(accountCapsule.getAddress().toByteArray(), accountCapsule); accountCapsule.addAssetV2(ByteArray.fromString(String.valueOf(id)), 1000L); - Assert.assertEquals(accountCapsule.getAssetMapForTest().get(ASSET_NAME).longValue(), 1000L); - Assert.assertEquals(accountCapsule.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), - 1000L); + Assert.assertEquals(1000L, accountCapsule.getAssetMapForTest().get(ASSET_NAME).longValue()); + Assert.assertEquals(1000L, + accountCapsule.getAssetV2MapForTest().get(String.valueOf(id)).longValue()); //assetBalanceEnoughV2 Assert.assertTrue(accountCapsule.assetBalanceEnoughV2(ByteArray.fromString(ASSET_NAME), @@ -217,10 +198,11 @@ public void sameTokenNameCloseAssertAmountV2test() { Assert.assertTrue(accountCapsule.addAssetAmountV2(ByteArray.fromString(ASSET_NAME), 500, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore())); // 1000-999 +500 - Assert.assertEquals(accountCapsule.getAssetMapForTest().get(ASSET_NAME).longValue(), 501L); + Assert.assertEquals(501L, accountCapsule.getAssetMapForTest().get(ASSET_NAME).longValue()); Assert.assertTrue(accountCapsule.addAssetAmountV2(ByteArray.fromString("abc"), 500, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore())); - Assert.assertEquals(accountCapsule.getAssetMapForTest().get("abc").longValue(), 500L); + Assert.assertEquals(500L, + accountCapsule.getAssetMapForTest().get("abc").longValue()); } /** @@ -274,8 +256,8 @@ public void sameTokenNameOpenAssertAmountV2test() { 10000); accountCapsule.addAssetV2(ByteArray.fromString(String.valueOf(id)), 1000L); dbManager.getAccountStore().put(accountCapsule.getAddress().toByteArray(), accountCapsule); - Assert.assertEquals(accountCapsule.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), - 1000L); + Assert.assertEquals(1000L, + accountCapsule.getAssetV2MapForTest().get(String.valueOf(id)).longValue()); //assetBalanceEnoughV2 Assert.assertTrue(accountCapsule.assetBalanceEnoughV2(ByteArray.fromString(String.valueOf(id)), @@ -300,14 +282,14 @@ public void sameTokenNameOpenAssertAmountV2test() { Assert.assertTrue(accountCapsule.addAssetAmountV2(ByteArray.fromString(String.valueOf(id)), 500, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore())); // 1000-999 +500 - Assert.assertEquals(accountCapsule.getAssetV2MapForTest().get(String.valueOf(id)).longValue(), - 501L); + Assert.assertEquals(501L, + accountCapsule.getAssetV2MapForTest().get(String.valueOf(id)).longValue()); //abc Assert.assertTrue(accountCapsule.addAssetAmountV2(ByteArray.fromString(String.valueOf(id + 1)), 500, dbManager.getDynamicPropertiesStore(), dbManager.getAssetIssueStore())); Assert - .assertEquals(accountCapsule.getAssetV2MapForTest().get(String.valueOf(id + 1)).longValue(), - 500L); + .assertEquals(500L, + accountCapsule.getAssetV2MapForTest().get(String.valueOf(id + 1)).longValue()); } @Test @@ -319,9 +301,8 @@ public void witnessPermissionTest() { AccountType.Normal, 10000); - Assert.assertTrue( - Arrays.equals(ByteArray.fromHexString(OWNER_ADDRESS), - accountCapsule.getWitnessPermissionAddress())); + Assert.assertArrayEquals(ByteArray.fromHexString(OWNER_ADDRESS), + accountCapsule.getWitnessPermissionAddress()); String witnessPermissionAddress = Wallet.getAddressPreFixString() + "cc6a17a49648a8ad32055c06f60fa14ae46df912cc"; @@ -330,8 +311,7 @@ public void witnessPermissionTest() { .setAddress(ByteString.copyFrom(ByteArray.fromHexString(witnessPermissionAddress))) .build()).build()).build()); - Assert.assertTrue( - Arrays.equals(ByteArray.fromHexString(witnessPermissionAddress), - accountCapsule.getWitnessPermissionAddress())); + Assert.assertArrayEquals(ByteArray.fromHexString(witnessPermissionAddress), + accountCapsule.getWitnessPermissionAddress()); } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/capsule/ExchangeCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/ExchangeCapsuleTest.java index d1a86f273db..48479287eab 100644 --- a/framework/src/test/java/org/tron/core/capsule/ExchangeCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/ExchangeCapsuleTest.java @@ -1,69 +1,22 @@ package org.tron.core.capsule; import com.google.protobuf.ByteString; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; -import org.tron.core.ChainBaseManager; import org.tron.core.Constant; -import org.tron.core.Wallet; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; -import org.tron.core.db.StorageMarket; import org.tron.core.exception.ItemNotFoundException; @Slf4j -public class ExchangeCapsuleTest { - - private static final String dbPath = "output_exchange_capsule_test_test"; - private static final String OWNER_ADDRESS; - private static final String OWNER_ADDRESS_INVALID = "aaaa"; - private static final String OWNER_ACCOUNT_INVALID; - private static final long initBalance = 10_000_000_000_000_000L; - private static Manager dbManager; - private static ChainBaseManager chainBaseManager; - private static StorageMarket storageMarket; - private static TronApplicationContext context; +public class ExchangeCapsuleTest extends BaseTest { static { + dbPath = "output_exchange_capsule_test_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; - OWNER_ACCOUNT_INVALID = - Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; - } - - /** - * Init data. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - chainBaseManager = context.getBean(ChainBaseManager.class); - storageMarket = new StorageMarket(chainBaseManager.getAccountStore(), - chainBaseManager.getDynamicPropertiesStore()); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } /** diff --git a/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java index ed0a3bda670..c9d593daf66 100644 --- a/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java @@ -1,38 +1,26 @@ package org.tron.core.capsule; import com.google.protobuf.ByteString; -import java.io.File; -import java.util.Objects; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.testng.Assert; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; +import org.tron.common.BaseTest; import org.tron.common.utils.StringUtil; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Result; import org.tron.protos.Protocol.Transaction.Result.contractResult; @Slf4j -public class TransactionCapsuleTest { +public class TransactionCapsuleTest extends BaseTest { - private static Manager dbManager; - private static TronApplicationContext context; - private static Application AppT; - private static String dbPath = "output_transactioncapsule_test"; private static String OWNER_ADDRESS; - private static String OWNER_KEY = + /*private static String OWNER_KEY = "bfa67cb3dc6609b3a0c98e717d66f38ed1a159b5b3421678dfab85961c40de2f"; private static String TO_ADDRESS; private static String OWNER_ACCOUNT_NOT_Exist; @@ -54,16 +42,14 @@ public class TransactionCapsuleTest { private static String KEY_ADDRESS_23; private static String KEY_ADDRESS_31; private static String KEY_ADDRESS_32; - private static String KEY_ADDRESS_33; + private static String KEY_ADDRESS_33;*/ @BeforeClass public static void init() { + dbPath = "output_transactioncapsule_test"; Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - AppT = ApplicationFactory.create(context); - dbManager = context.getBean(Manager.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "03702350064AD5C1A8AA6B4D74B051199CFF8EA7"; - TO_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; + /*TO_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ACCOUNT_NOT_Exist = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; KEY_ADDRESS_11 = Wallet.getAddressPreFixString() + "19E7E376E7C213B7E7E7E46CC70A5DD086DAFF2A"; @@ -76,16 +62,7 @@ public static void init() { KEY_ADDRESS_31 = Wallet.getAddressPreFixString() + "77952CE83CA3CAD9F7ADCFABEDA85BD2F1F52008"; KEY_ADDRESS_32 = Wallet.getAddressPreFixString() + "94622CC2A5B64A58C25A129D48A2BEEC4B65B779"; - KEY_ADDRESS_33 = Wallet.getAddressPreFixString() + "5CBDD86A2FA8DC4BDDD8A8F69DBA48572EEC07FB"; - } - - @AfterClass - public static void removeDb() { - Args.clearParam(); - AppT.shutdownServices(); - AppT.shutdown(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); + KEY_ADDRESS_33 = Wallet.getAddressPreFixString() + "5CBDD86A2FA8DC4BDDD8A8F69DBA48572EEC07FB";*/ } /** @@ -1086,6 +1063,6 @@ public void trxCapsuleClearTest() { Assert.assertEquals(trxCap.getInstance().getRetCount(), 0); trxCap.setResultCode(contractResult); Assert.assertEquals(trxCap.getInstance() - .getRet(0).getContractRet(), contractResult.OUT_OF_TIME); + .getRet(0).getContractRet(), Result.contractResult.OUT_OF_TIME); } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java b/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java index b07061dc696..8d56c1a5f21 100644 --- a/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java +++ b/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java @@ -2,49 +2,30 @@ import com.google.common.collect.Lists; import com.google.protobuf.ByteString; -import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Random; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Test; import org.tron.api.GrpcAPI.AssetIssueList; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; -import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.db.BandwidthProcessor; -import org.tron.core.db.Manager; -import org.tron.core.store.AccountAssetStore; import org.tron.protos.Protocol; import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; @Slf4j -public class AssetUtilTest { +public class AssetUtilTest extends BaseTest { - private static String dbPath = "output_AssetUtil_test"; - private static Manager dbManager; - private static TronApplicationContext context; - private static ChainBaseManager chainBaseManager; static { + dbPath = "output_AssetUtil_test"; Args.setParam(new String[] {"-d", dbPath, "-w"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - dbManager = context.getBean(Manager.class); - chainBaseManager = context.getBean(ChainBaseManager.class); - } - - @AfterClass - public static void removeDb() { - Args.clearParam(); - FileUtil.deleteDir(new File(dbPath)); } public static byte[] randomBytes(int length) { @@ -54,14 +35,12 @@ public static byte[] randomBytes(int length) { return result; } - private static AccountCapsule createAccount2() { - AccountAssetStore accountAssetStore = dbManager.getAccountAssetStore(); + private AccountCapsule createAccount2() { com.google.protobuf.ByteString accountName = com.google.protobuf.ByteString.copyFrom(randomBytes(16)); com.google.protobuf.ByteString address = ByteString.copyFrom(randomBytes(32)); Protocol.AccountType accountType = Protocol.AccountType.forNumber(1); - AccountCapsule accountCapsule = new AccountCapsule(accountName, address, accountType); - return accountCapsule; + return new AccountCapsule(accountName, address, accountType); } @Test diff --git a/framework/src/test/java/org/tron/core/capsule/utils/ExchangeProcessorTest.java b/framework/src/test/java/org/tron/core/capsule/utils/ExchangeProcessorTest.java index 50d01e2b982..3d30dabf031 100644 --- a/framework/src/test/java/org/tron/core/capsule/utils/ExchangeProcessorTest.java +++ b/framework/src/test/java/org/tron/core/capsule/utils/ExchangeProcessorTest.java @@ -1,36 +1,22 @@ package org.tron.core.capsule.utils; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; +import org.tron.common.BaseTest; import org.tron.core.Constant; -import org.tron.core.Wallet; import org.tron.core.capsule.ExchangeProcessor; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; @Slf4j -public class ExchangeProcessorTest { +public class ExchangeProcessorTest extends BaseTest { - private static final String dbPath = "output_buy_exchange_processor_test"; - private static final String OWNER_ADDRESS; - private static final String OWNER_ADDRESS_INVALID = "aaaa"; - private static final String OWNER_ACCOUNT_INVALID; - private static final long initBalance = 10_000_000_000_000_000L; private static ExchangeProcessor processor; - private static TronApplicationContext context; static { + dbPath = "output_buy_exchange_processor_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; - OWNER_ACCOUNT_INVALID = - Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; } /** @@ -40,24 +26,6 @@ public class ExchangeProcessorTest { public static void init() { long supply = 1_000_000_000_000_000_000L; processor = new ExchangeProcessor(supply); - // Args.setParam(new String[]{"--output-directory", dbPath}, - // "config-junit.conf"); - // dbManager = new Manager(); - // dbManager.init(); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } @Test diff --git a/framework/src/test/java/org/tron/core/db/EnergyPriceHistoryLoaderTest.java b/framework/src/test/java/org/tron/core/db/EnergyPriceHistoryLoaderTest.java index 4e7efdd43f1..ca115bed2bd 100644 --- a/framework/src/test/java/org/tron/core/db/EnergyPriceHistoryLoaderTest.java +++ b/framework/src/test/java/org/tron/core/db/EnergyPriceHistoryLoaderTest.java @@ -26,7 +26,6 @@ @Slf4j public class EnergyPriceHistoryLoaderTest extends BaseTest { - private static String dbPath = "output-EnergyPriceHistoryLoaderTest-test"; private static long t1 = 1542607200000L; private static long price1 = 20; private static long t3 = 1544724000000L; @@ -37,6 +36,7 @@ public class EnergyPriceHistoryLoaderTest extends BaseTest { private static long price5 = 140L; static { + dbPath = "output-EnergyPriceHistoryLoaderTest-test"; Args.setParam(new String[] {"--output-directory", dbPath}, Constant.TEST_CONF); } diff --git a/framework/src/test/java/org/tron/core/db/api/AssetUpdateHelperTest.java b/framework/src/test/java/org/tron/core/db/api/AssetUpdateHelperTest.java index 34ce5d7d6ec..035a34ac414 100644 --- a/framework/src/test/java/org/tron/core/db/api/AssetUpdateHelperTest.java +++ b/framework/src/test/java/org/tron/core/db/api/AssetUpdateHelperTest.java @@ -3,50 +3,36 @@ import static org.tron.core.config.Parameter.ChainSymbol.TRX_SYMBOL_BYTES; import com.google.protobuf.ByteString; -import java.io.File; -import org.junit.AfterClass; +import java.util.Objects; import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.Sha256Hash; -import org.tron.core.ChainBaseManager; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.ExchangeCapsule; import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.Exchange; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -public class AssetUpdateHelperTest { +public class AssetUpdateHelperTest extends BaseTest { - private static ChainBaseManager chainBaseManager; - private static TronApplicationContext context; - private static String dbPath = "output_AssetUpdateHelperTest_test"; - private static Application AppT; - - private static ByteString assetName = ByteString.copyFrom("assetIssueName".getBytes()); + private static final ByteString assetName = ByteString.copyFrom("assetIssueName".getBytes()); static { + dbPath = "output_AssetUpdateHelperTest_test"; Args.setParam(new String[]{"-d", dbPath, "-w"}, "config-test-index.conf"); Args.getInstance().setSolidityNode(true); - context = new TronApplicationContext(DefaultConfig.class); - AppT = ApplicationFactory.create(context); } - @BeforeClass - public static void init() { - - chainBaseManager = context.getBean(ChainBaseManager.class); + @Before + public void init() { AssetIssueContract contract = AssetIssueContract.newBuilder().setName(assetName).setNum(12581).setPrecision(5).build(); @@ -86,13 +72,6 @@ public static void init() { accountCapsule); } - @AfterClass - public static void removeDb() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } - @Test public void test() { @@ -112,7 +91,7 @@ public void test() { Assert.assertEquals(5L, assetIssueCapsule.getPrecision()); AssetIssueCapsule assetIssueCapsule2 = - chainBaseManager.getAssetIssueV2Store().get(ByteArray.fromString(String.valueOf(idNum))); + chainBaseManager.getAssetIssueV2Store().get(ByteArray.fromString(idNum)); Assert.assertEquals(idNum, assetIssueCapsule2.getId()); Assert.assertEquals(assetName, assetIssueCapsule2.getName()); @@ -139,7 +118,8 @@ public void test() { chainBaseManager.getAccountStore().get(ByteArray.fromHexString("121212abc")); Assert.assertEquals( - ByteString.copyFrom(ByteArray.fromString("1000001")), accountCapsule.getAssetIssuedID()); + ByteString.copyFrom(Objects.requireNonNull(ByteArray.fromString("1000001"))), + accountCapsule.getAssetIssuedID()); Assert.assertEquals(1, accountCapsule.getAssetV2MapForTest().size()); diff --git a/framework/src/test/java/org/tron/core/db/backup/BackupDbUtilTest.java b/framework/src/test/java/org/tron/core/db/backup/BackupDbUtilTest.java index f63fafe060e..4ddbd88d338 100644 --- a/framework/src/test/java/org/tron/core/db/backup/BackupDbUtilTest.java +++ b/framework/src/test/java/org/tron/core/db/backup/BackupDbUtilTest.java @@ -1,51 +1,41 @@ package org.tron.core.db.backup; import java.io.File; -import java.util.List; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.rocksdb.RocksDB; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.FileUtil; import org.tron.common.utils.PropUtil; import org.tron.consensus.dpos.DposSlot; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.consensus.ConsensusService; -import org.tron.core.db.Manager; import org.tron.core.db.ManagerForTest; -import org.tron.core.db2.core.Chainbase; -import org.tron.core.db2.core.SnapshotManager; @Slf4j -public class BackupDbUtilTest { +public class BackupDbUtilTest extends BaseTest { static { RocksDB.loadLibrary(); } - public TronApplicationContext context; - public Application AppT = null; - public BackupDbUtil dbBackupUtil; - public Manager dbManager; + @Resource public ConsensusService consensusService; + @Resource public DposSlot dposSlot; public ManagerForTest mngForTest; - public String dbPath = "output-BackupDbUtilTest"; String propPath; String bak1Path; String bak2Path; int frequency; - @Before - public void before() { + static { + dbPath = "output-BackupDbUtilTest"; Args.setParam( new String[]{ "--output-directory", dbPath, @@ -54,16 +44,12 @@ public void before() { }, "config-test-dbbackup.conf" ); + } - context = new TronApplicationContext(DefaultConfig.class); - AppT = ApplicationFactory.create(context); - dbManager = context.getBean(Manager.class); - dposSlot = context.getBean(DposSlot.class); - consensusService = context.getBean(ConsensusService.class); - dbBackupUtil = context.getBean(BackupDbUtil.class); + @Before + public void before() { consensusService.start(); mngForTest = new ManagerForTest(dbManager, dposSlot); - //prepare prop.properties propPath = dbPath + File.separator + "test_prop.properties"; bak1Path = dbPath + File.separator + "bak1/database"; @@ -75,49 +61,30 @@ public void before() { FileUtil.createFileIfNotExists(propPath); } - @After - public void after() { - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - @Test public void testDoBackup() { - PropUtil.writeProperty(propPath, BackupDbUtil.getDB_BACKUP_STATE(), - String.valueOf("11")); + PropUtil.writeProperty(propPath, BackupDbUtil.getDB_BACKUP_STATE(), "11"); mngForTest.pushNTestBlock(50); - List alist = ((SnapshotManager) dbBackupUtil.getDb()).getDbs(); - Assert.assertTrue(dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() == 50); - Assert.assertTrue("22".equals( - PropUtil.readProperty(propPath, BackupDbUtil.getDB_BACKUP_STATE()))); + Assert.assertEquals(50, dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber()); + Assert.assertEquals("22", PropUtil.readProperty(propPath, BackupDbUtil.getDB_BACKUP_STATE())); mngForTest.pushNTestBlock(50); - Assert.assertTrue(dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() == 100); - Assert.assertTrue("11".equals( - PropUtil.readProperty(propPath, BackupDbUtil.getDB_BACKUP_STATE()))); + Assert.assertEquals(100, dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber()); + Assert.assertEquals("11", PropUtil.readProperty(propPath, BackupDbUtil.getDB_BACKUP_STATE())); mngForTest.pushNTestBlock(50); - Assert.assertTrue(dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() == 150); - Assert.assertTrue("22".equals( - PropUtil.readProperty(propPath, BackupDbUtil.getDB_BACKUP_STATE()))); + Assert.assertEquals(150, dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber()); + Assert.assertEquals("22", PropUtil.readProperty(propPath, BackupDbUtil.getDB_BACKUP_STATE())); - PropUtil.writeProperty(propPath, BackupDbUtil.getDB_BACKUP_STATE(), - String.valueOf("1")); + PropUtil.writeProperty(propPath, BackupDbUtil.getDB_BACKUP_STATE(), "1"); mngForTest.pushNTestBlock(50); - Assert.assertTrue(dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() == 200); - Assert.assertTrue("11".equals( - PropUtil.readProperty(propPath, BackupDbUtil.getDB_BACKUP_STATE()))); + Assert.assertEquals(200, dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber()); + Assert.assertEquals("11", PropUtil.readProperty(propPath, BackupDbUtil.getDB_BACKUP_STATE())); - PropUtil.writeProperty(propPath, BackupDbUtil.getDB_BACKUP_STATE(), - String.valueOf("2")); + PropUtil.writeProperty(propPath, BackupDbUtil.getDB_BACKUP_STATE(), "2"); mngForTest.pushNTestBlock(50); - Assert.assertTrue(dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() == 250); - Assert.assertTrue("22".equals( - PropUtil.readProperty(propPath, BackupDbUtil.getDB_BACKUP_STATE()))); + Assert.assertEquals(250, dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber()); + Assert.assertEquals("22", PropUtil.readProperty(propPath, BackupDbUtil.getDB_BACKUP_STATE())); } } diff --git a/framework/src/test/java/org/tron/core/jsonrpc/BuildTransactionTest.java b/framework/src/test/java/org/tron/core/jsonrpc/BuildTransactionTest.java index bbc49835bd5..55d7c106458 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/BuildTransactionTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/BuildTransactionTest.java @@ -1,31 +1,26 @@ package org.tron.core.jsonrpc; import com.google.protobuf.ByteString; -import java.io.File; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.ContractCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.services.jsonrpc.types.BuildArguments; import org.tron.protos.Protocol; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.contract.SmartContractOuterClass.SmartContract; @Slf4j -public class BuildTransactionTest { +public class BuildTransactionTest extends BaseTest { - private static String dbPath = "output_build_transaction_test"; private static final String OWNER_ADDRESS; private static final String OWNER_ADDRESS_ACCOUNT_NAME = "first"; @@ -33,24 +28,20 @@ public class BuildTransactionTest { private static final String CONTRACT_ADDRESS; private static final long SOURCE_PERCENT = 10L; - private static TronApplicationContext context; - private static Manager dbManager; - private static Wallet wallet; + @Resource + private Wallet wallet; static { + dbPath = "output_build_transaction_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; CONTRACT_ADDRESS = Wallet.getAddressPreFixString() + "f859b5c93f789f4bcffbe7cc95a71e28e5e6a5bd"; } - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - wallet = context.getBean(Wallet.class); - + @Before + public void init() { AccountCapsule accountCapsule = new AccountCapsule( ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), @@ -76,17 +67,6 @@ public static void init() { new ContractCapsule(builder.build())); } - @AfterClass - public static void removeDb() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - @Test public void testTransferContract() { BuildArguments buildArguments = new BuildArguments(); diff --git a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java index 143f257d85a..2b2d6f8b277 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java @@ -1,25 +1,21 @@ package org.tron.core.jsonrpc; import com.google.protobuf.ByteString; -import java.io.File; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.services.NodeInfoService; import org.tron.core.services.jsonrpc.TronJsonRpcImpl; import org.tron.core.services.jsonrpc.types.BlockResult; @@ -30,33 +26,29 @@ @Slf4j -public class JsonrpcServiceTest { - private static String dbPath = "output_jsonrpc_service_test"; +public class JsonrpcServiceTest extends BaseTest { private static final String OWNER_ADDRESS; private static final String OWNER_ADDRESS_ACCOUNT_NAME = "first"; private static TronJsonRpcImpl tronJsonRpc; - private static TronApplicationContext context; - private static NodeInfoService nodeInfoService; + @Resource + private NodeInfoService nodeInfoService; private static BlockCapsule blockCapsule; private static TransactionCapsule transactionCapsule1; - private static TransactionCapsule transactionCapsule2; + @Resource + private Wallet wallet; static { + dbPath = "output_jsonrpc_service_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; - nodeInfoService = context.getBean("nodeInfoService", NodeInfoService.class); } - @BeforeClass - public static void init() { - Manager dbManager = context.getBean(Manager.class); - Wallet wallet = context.getBean(Wallet.class); - + @Before + public void init() { AccountCapsule accountCapsule = new AccountCapsule( ByteString.copyFromUtf8(OWNER_ADDRESS_ACCOUNT_NAME), @@ -89,8 +81,8 @@ public static void init() { transactionCapsule1 = new TransactionCapsule(transferContract1, ContractType.TransferContract); transactionCapsule1.setBlockNum(blockCapsule.getNum()); - transactionCapsule2 = - new TransactionCapsule(transferContract2, ContractType.TransferContract); + TransactionCapsule transactionCapsule2 = new TransactionCapsule(transferContract2, + ContractType.TransferContract); transactionCapsule2.setBlockNum(2L); blockCapsule.addTransaction(transactionCapsule1); @@ -107,17 +99,6 @@ public static void init() { tronJsonRpc = new TronJsonRpcImpl(nodeInfoService, wallet, dbManager); } - @AfterClass - public static void removeDb() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - @Test public void testWeb3Sha3() { String result = ""; diff --git a/framework/src/test/java/org/tron/core/jsonrpc/SectionBloomStoreTest.java b/framework/src/test/java/org/tron/core/jsonrpc/SectionBloomStoreTest.java index 4fa40e42807..fd2b7a66d31 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/SectionBloomStoreTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/SectionBloomStoreTest.java @@ -1,23 +1,19 @@ package org.tron.core.jsonrpc; -import java.io.File; import java.util.ArrayList; import java.util.BitSet; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import org.junit.AfterClass; -import org.junit.BeforeClass; +import javax.annotation.Resource; import org.junit.Test; import org.testng.Assert; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.runtime.vm.DataWord; import org.tron.common.runtime.vm.LogInfo; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.capsule.TransactionRetCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.exception.EventBloomException; import org.tron.core.services.jsonrpc.TronJsonRpc.FilterRequest; @@ -27,28 +23,14 @@ import org.tron.protos.Protocol.TransactionInfo; import org.tron.protos.Protocol.TransactionInfo.Log; -public class SectionBloomStoreTest { +public class SectionBloomStoreTest extends BaseTest { - private static final String dbPath = "output-sectionBloomStore-test"; - static SectionBloomStore sectionBloomStore; - private static TronApplicationContext context; + @Resource + SectionBloomStore sectionBloomStore; static { - Args.setParam(new String[] {"--output-directory", dbPath}, - Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - } - - @BeforeClass - public static void init() { - sectionBloomStore = context.getBean(SectionBloomStore.class); - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); + dbPath = "output-sectionBloomStore-test"; + Args.setParam(new String[] {"--output-directory", dbPath}, Constant.TEST_CONF); } @Test diff --git a/framework/src/test/java/org/tron/core/jsonrpc/WalletCursorTest.java b/framework/src/test/java/org/tron/core/jsonrpc/WalletCursorTest.java index 778860b8879..158f924c446 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/WalletCursorTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/WalletCursorTest.java @@ -1,21 +1,17 @@ package org.tron.core.jsonrpc; import com.google.protobuf.ByteString; -import java.io.File; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.db2.core.Chainbase.Cursor; import org.tron.core.services.NodeInfoService; import org.tron.core.services.jsonrpc.TronJsonRpcImpl; @@ -24,30 +20,24 @@ import org.tron.protos.Protocol; @Slf4j -public class WalletCursorTest { - private static String dbPath = "output_wallet_cursor_test"; +public class WalletCursorTest extends BaseTest { private static final String OWNER_ADDRESS; private static final String OWNER_ADDRESS_ACCOUNT_NAME = "first"; - - private static TronApplicationContext context; - private static Manager dbManager; - private static Wallet wallet; - private static NodeInfoService nodeInfoService; + @Resource + private Wallet wallet; + @Resource + private NodeInfoService nodeInfoService; static { + dbPath = "output_wallet_cursor_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; - nodeInfoService = context.getBean("nodeInfoService", NodeInfoService.class); } - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - wallet = context.getBean(Wallet.class); - + @Before + public void init() { AccountCapsule accountCapsule = new AccountCapsule( ByteString.copyFromUtf8(OWNER_ADDRESS_ACCOUNT_NAME), @@ -57,17 +47,6 @@ public static void init() { dbManager.getAccountStore().put(accountCapsule.getAddress().toByteArray(), accountCapsule); } - @AfterClass - public static void removeDb() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - @Test public void testSource() { TronJsonRpcImpl tronJsonRpc = new TronJsonRpcImpl(nodeInfoService, wallet, dbManager); diff --git a/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java b/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java index dadc688e5bd..86fa45a3e59 100644 --- a/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java +++ b/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java @@ -3,7 +3,6 @@ import com.google.common.collect.Maps; import com.google.protobuf.ByteString; import io.prometheus.client.CollectorRegistry; -import java.io.File; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; @@ -12,54 +11,54 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import java.util.stream.IntStream; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.crypto.ECKey; import org.tron.common.parameter.CommonParameter; import org.tron.common.prometheus.MetricLabels; import org.tron.common.prometheus.Metrics; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.Utils; import org.tron.consensus.dpos.DposSlot; -import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.consensus.ConsensusService; -import org.tron.core.db.BlockGenerate; -import org.tron.core.db.Manager; import org.tron.core.net.TronNetDelegate; import org.tron.protos.Protocol; @Slf4j(topic = "metric") -public class PrometheusApiServiceTest extends BlockGenerate { - - - static ChainBaseManager chainManager; +public class PrometheusApiServiceTest extends BaseTest { static LocalDateTime localDateTime = LocalDateTime.now(); - private static DposSlot dposSlot; + @Resource + private DposSlot dposSlot; final int blocks = 512; private final String key = "f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62"; private final byte[] privateKey = ByteArray.fromHexString(key); - private final AtomicInteger port = new AtomicInteger(0); + private static final AtomicInteger port = new AtomicInteger(0); private final long time = ZonedDateTime.of(localDateTime, ZoneId.systemDefault()).toInstant().toEpochMilli(); - protected String dbPath; - protected String dbEngine; - protected Manager dbManager; + @Resource private TronNetDelegate tronNetDelegate; - private TronApplicationContext context; + @Resource + private ConsensusService consensusService; + + static { + dbPath = "output-prometheus-metric"; + Args.setParam(new String[] {"-d", dbPath, "-w"}, Constant.TEST_CONF); + Args.getInstance().setNodeListenPort(10000 + port.incrementAndGet()); + initParameter(Args.getInstance()); + Metrics.init(); + } - protected void initParameter(CommonParameter parameter) { + protected static void initParameter(CommonParameter parameter) { parameter.setMetricsPrometheusEnable(true); } @@ -83,47 +82,20 @@ protected void check() throws Exception { Assert.assertNull(errorLogs); } - protected void initDb() { - dbPath = "output-prometheus-metric"; - dbEngine = "LEVELDB"; - } - @Before public void init() throws Exception { - - initDb(); - FileUtil.deleteDir(new File(dbPath)); logger.info("Full node running."); - Args.setParam(new String[] {"-d", dbPath, "-w"}, Constant.TEST_CONF); - Args.getInstance().setNodeListenPort(10000 + port.incrementAndGet()); - initParameter(Args.getInstance()); - Metrics.init(); - context = new TronApplicationContext(DefaultConfig.class); - - dbManager = context.getBean(Manager.class); - setManager(dbManager); - dposSlot = context.getBean(DposSlot.class); - ConsensusService consensusService = context.getBean(ConsensusService.class); consensusService.start(); - chainManager = dbManager.getChainBaseManager(); - tronNetDelegate = context.getBean(TronNetDelegate.class); - } - - @After - public void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } private void generateBlock(Map witnessAndAccount) throws Exception { BlockCapsule block = createTestBlockCapsule( - chainManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp() + 3000, - chainManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() + 1, - chainManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(), + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp() + 3000, + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() + 1, + chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(), witnessAndAccount); tronNetDelegate.processBlock(block, false); @@ -136,8 +108,8 @@ public void testMetric() throws Exception { Assert.assertNotNull(ecKey); byte[] address = ecKey.getAddress(); WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address)); - chainManager.getWitnessScheduleStore().saveActiveWitnesses(new ArrayList<>()); - chainManager.addWitness(ByteString.copyFrom(address)); + chainBaseManager.getWitnessScheduleStore().saveActiveWitnesses(new ArrayList<>()); + chainBaseManager.addWitness(ByteString.copyFrom(address)); Protocol.Block block = getSignedBlock(witnessCapsule.getAddress(), time, privateKey); @@ -152,7 +124,7 @@ public void testMetric() throws Exception { } private Map addTestWitnessAndAccount() { - chainManager.getWitnesses().clear(); + chainBaseManager.getWitnesses().clear(); return IntStream.range(0, 2) .mapToObj( i -> { @@ -161,12 +133,12 @@ private Map addTestWitnessAndAccount() { ByteString address = ByteString.copyFrom(ecKey.getAddress()); WitnessCapsule witnessCapsule = new WitnessCapsule(address); - chainManager.getWitnessStore().put(address.toByteArray(), witnessCapsule); - chainManager.addWitness(address); + chainBaseManager.getWitnessStore().put(address.toByteArray(), witnessCapsule); + chainBaseManager.addWitness(address); AccountCapsule accountCapsule = new AccountCapsule(Protocol.Account.newBuilder().setAddress(address).build()); - chainManager.getAccountStore().put(address.toByteArray(), accountCapsule); + chainBaseManager.getAccountStore().put(address.toByteArray(), accountCapsule); return Maps.immutableEntry(address, privateKey); }) diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java index 5b2abfd0705..b8b00e30523 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java @@ -1,17 +1,17 @@ package org.tron.core.net.messagehandler; +import static org.junit.Assert.assertEquals; + import com.google.common.collect.ImmutableList; import com.google.protobuf.ByteString; import java.util.List; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; +import javax.annotation.Resource; +import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +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.DefaultConfig; import org.tron.core.config.Parameter; import org.tron.core.config.args.Args; import org.tron.core.exception.P2pException; @@ -21,22 +21,21 @@ import org.tron.protos.Protocol.Inventory.InventoryType; import org.tron.protos.Protocol.Transaction; -public class BlockMsgHandlerTest { +public class BlockMsgHandlerTest extends BaseTest { - protected TronApplicationContext context; + @Resource private BlockMsgHandler handler; + @Resource private PeerConnection peer; /** * init context. */ - @Before - public void init() { - Args.setParam(new String[]{"--output-directory", "output-directory", "--debug"}, + @BeforeClass + public static void init() { + dbPath = "output_blockmsghandler_test"; + Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - handler = context.getBean(BlockMsgHandler.class); - peer = context.getBean(PeerConnection.class); } @Test @@ -49,7 +48,7 @@ public void testProcessMessage() { msg = new BlockMessage(blockCapsule); handler.processMessage(peer, msg); } catch (P2pException e) { - Assert.assertTrue(e.getMessage().equals("no request")); + assertEquals("no request", e.getMessage()); } try { @@ -69,7 +68,7 @@ public void testProcessMessage() { handler.processMessage(peer, msg); } catch (P2pException e) { //System.out.println(e); - Assert.assertTrue(e.getMessage().equals("block size over limit")); + assertEquals("block size over limit", e.getMessage()); } try { @@ -81,7 +80,7 @@ public void testProcessMessage() { handler.processMessage(peer, msg); } catch (P2pException e) { //System.out.println(e); - Assert.assertTrue(e.getMessage().equals("block time error")); + assertEquals("block time error", e.getMessage()); } try { @@ -106,10 +105,4 @@ public void testProcessMessage() { System.out.println(e); } } - - @After - public void destroy() { - Args.clearParam(); - context.destroy(); - } } diff --git a/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java b/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java index a6189346ae5..86e7f662b38 100644 --- a/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java @@ -1,23 +1,18 @@ package org.tron.core.net.services; import com.google.common.collect.Lists; - -import java.io.File; import java.util.List; -import org.junit.After; +import javax.annotation.Resource; import org.junit.Assert; -import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.ReflectUtils; import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.net.P2pEventHandlerImpl; import org.tron.core.net.message.adv.BlockMessage; import org.tron.core.net.message.adv.TransactionMessage; import org.tron.core.net.peer.Item; @@ -27,32 +22,21 @@ import org.tron.protos.Protocol; import org.tron.protos.Protocol.Inventory.InventoryType; -public class AdvServiceTest { +public class AdvServiceTest extends BaseTest { - protected TronApplicationContext context; + @Resource private AdvService service; + @Resource private PeerConnection peer; - private P2pEventHandlerImpl p2pEventHandler; - private String dbPath = "output-adv-service-test"; /** * init context. */ - @Before - public void init() { + @BeforeClass + public static void init() { + dbPath = "output-adv-service-test"; Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - service = context.getBean(AdvService.class); - } - - /** - * destroy. - */ - @After - public void destroy() { - Args.clearParam(); - FileUtil.deleteDir(new File(dbPath)); } @Test @@ -84,9 +68,6 @@ private void testAddInv() { private void testBroadcast() { try { - peer = context.getBean(PeerConnection.class); - p2pEventHandler = context.getBean(P2pEventHandlerImpl.class); - List peers = Lists.newArrayList(); peers.add(peer); ReflectUtils.setFieldValue(P2pEventHandler.class, "peers", peers); diff --git a/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java b/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java index b4deb6aff4b..a5b676d0144 100644 --- a/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java @@ -2,25 +2,22 @@ import com.google.common.collect.Lists; import com.google.protobuf.ByteString; -import java.io.File; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Set; +import javax.annotation.Resource; import org.bouncycastle.util.encoders.Hex; -import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; +import org.tron.common.BaseTest; import org.tron.common.utils.ReflectUtils; -import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.net.P2pEventHandlerImpl; import org.tron.core.net.message.adv.BlockMessage; @@ -29,33 +26,23 @@ import org.tron.core.net.service.relay.RelayService; import org.tron.protos.Protocol; -public class RelayServiceTest { +public class RelayServiceTest extends BaseTest { - protected TronApplicationContext context; + @Resource private RelayService service; - private ChainBaseManager chainBaseManager; + @Resource private PeerConnection peer; + @Resource private P2pEventHandlerImpl p2pEventHandler; - private String dbPath = "output-relay-service-test"; /** * init context. */ - @Before - public void init() { + @BeforeClass + public static void init() { + dbPath = "output-relay-service-test"; Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - service = context.getBean(RelayService.class); - chainBaseManager = context.getBean(ChainBaseManager.class); - p2pEventHandler = context.getBean(P2pEventHandlerImpl.class); - } - - @After - public void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } @Test @@ -83,31 +70,29 @@ public void testGetNextWitnesses() throws Exception { method.setAccessible(true); Set s1 = (Set) method.invoke( service, getFromHexString("A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F"), 3); - Assert.assertEquals(s1.size(), 3); + Assert.assertEquals(3, s1.size()); assertContains(s1, "A0299F3DB80A24B20A254B89CE639D59132F157F13"); assertContains(s1, "A0807337F180B62A77576377C1D0C9C24DF5C0DD62"); assertContains(s1, "A05430A3F089154E9E182DDD6FE136A62321AF22A7"); Set s2 = (Set) method.invoke( service, getFromHexString("A0FAB5FBF6AFB681E4E37E9D33BDDB7E923D6132E5"), 3); - Assert.assertEquals(s2.size(), 3); + Assert.assertEquals(3, s2.size()); assertContains(s2, "A014EEBE4D30A6ACB505C8B00B218BDC4733433C68"); assertContains(s2, "A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F"); assertContains(s2, "A0299F3DB80A24B20A254B89CE639D59132F157F13"); Set s3 = (Set) method.invoke( service, getFromHexString("A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F"), 1); - Assert.assertEquals(s3.size(), 1); + Assert.assertEquals(1, s3.size()); assertContains(s3, "A0299F3DB80A24B20A254B89CE639D59132F157F13"); } private void testBroadcast() { try { - peer = context.getBean(PeerConnection.class); peer.setAddress(getFromHexString("A0299F3DB80A24B20A254B89CE639D59132F157F13")); peer.setNeedSyncFromPeer(false); peer.setNeedSyncFromUs(false); - p2pEventHandler = context.getBean(P2pEventHandlerImpl.class); List peers = Lists.newArrayList(); peers.add(peer); diff --git a/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java b/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java index 16c1205a818..61ce5ec3625 100755 --- a/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java +++ b/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java @@ -3,60 +3,44 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.google.protobuf.ByteString; -import java.io.File; import java.io.IOException; +import java.util.Objects; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; -import org.junit.After; import org.junit.Assert; -import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.crypto.ECKey; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.Utils; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.BlockGenerate; import org.tron.core.db.CommonDataBase; -import org.tron.core.db.Manager; import org.tron.core.db2.ISession; -import org.tron.core.exception.HeaderNotFound; import org.tron.core.services.interfaceOnPBFT.http.PBFT.HttpApiOnPBFTService; import org.tron.core.store.DynamicPropertiesStore; @Slf4j -public class PbftApiTest extends BlockGenerate { +public class PbftApiTest extends BaseTest { + @Resource + private HttpApiOnPBFTService httpApiOnPBFTService; - private static Manager dbManager; - private static TronApplicationContext context; - private static String dbPath = "output_pbftAPI_test"; - - @Before - public void init() { + @BeforeClass + public static void init() { + dbPath = "output_pbftAPI_test"; Args.setParam(new String[]{"-d", dbPath, "-w"}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - dbManager = context.getBean(Manager.class); - setManager(dbManager); - } - - @After - public void removeDb() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } @Test - public void pbftapi() throws IOException, InterruptedException, HeaderNotFound { + public void pbftapi() throws IOException { ChainBaseManager chainBaseManager = dbManager.getChainBaseManager(); DynamicPropertiesStore dynamicPropertiesStore = chainBaseManager.getDynamicPropertiesStore(); CommonDataBase commonDataBase = chainBaseManager.getCommonDataBase(); @@ -75,17 +59,18 @@ public void pbftapi() throws IOException, InterruptedException, HeaderNotFound { Assert.assertTrue(dynamicPropertiesStore.getLatestBlockHeaderNumber() >= 10); commonDataBase.saveLatestPbftBlockNum(6); - HttpApiOnPBFTService httpApiOnPBFTService = context.getBean(HttpApiOnPBFTService.class); httpApiOnPBFTService.start(); - CloseableHttpResponse response = null; + CloseableHttpResponse response; try (CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpGet httpGet = new HttpGet("http://127.0.0.1:8092/walletpbft/getnowblock"); response = httpClient.execute(httpGet); String responseString = EntityUtils.toString(response.getEntity()); JSONObject jsonObject = JSON.parseObject(responseString); - long num = jsonObject.getJSONObject("block_header").getJSONObject("raw_data") - .getLongValue("number"); - Assert.assertEquals(commonDataBase.getLatestPbftBlockNum(), num); + if (Objects.nonNull(jsonObject)) { + long num = jsonObject.getJSONObject("block_header").getJSONObject("raw_data") + .getLongValue("number"); + Assert.assertEquals(commonDataBase.getLatestPbftBlockNum(), num); + } response.close(); } httpApiOnPBFTService.stop(); diff --git a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java index 7978d98a9fe..59c4691f50b 100644 --- a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java @@ -4,38 +4,35 @@ import static org.tron.core.utils.ProposalUtil.ProposalType.TRANSACTION_FEE; import static org.tron.core.utils.ProposalUtil.ProposalType.WITNESS_127_PAY_PER_BLOCK; -import java.io.File; import java.util.HashSet; import java.util.Set; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; +import org.tron.common.BaseTest; import org.tron.core.Constant; import org.tron.core.capsule.ProposalCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.consensus.ProposalService; -import org.tron.core.db.Manager; import org.tron.core.utils.ProposalUtil.ProposalType; import org.tron.protos.Protocol.Proposal; @Slf4j -public class ProposalServiceTest { +public class ProposalServiceTest extends BaseTest { - private static TronApplicationContext context; - private static Manager manager; - private static String dbPath = "output_proposal_test"; @BeforeClass public static void init() { + dbPath = "output_proposal_test"; Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - manager = context.getBean(Manager.class); - manager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(5); + + } + + @Before + public void before() { + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(5); } @Test @@ -47,12 +44,12 @@ public void test() { Proposal proposal = Proposal.newBuilder().putParameters(1, 1).build(); ProposalCapsule proposalCapsule = new ProposalCapsule(proposal); - boolean result = ProposalService.process(manager, proposalCapsule); + boolean result = ProposalService.process(dbManager, proposalCapsule); Assert.assertTrue(result); // proposal = Proposal.newBuilder().putParameters(1000, 1).build(); proposalCapsule = new ProposalCapsule(proposal); - result = ProposalService.process(manager, proposalCapsule); + result = ProposalService.process(dbManager, proposalCapsule); Assert.assertFalse(result); // for (ProposalType proposalType : ProposalType.values()) { @@ -62,57 +59,47 @@ public void test() { proposal = Proposal.newBuilder().putParameters(proposalType.getCode(), 1).build(); } proposalCapsule = new ProposalCapsule(proposal); - result = ProposalService.process(manager, proposalCapsule); + result = ProposalService.process(dbManager, proposalCapsule); Assert.assertTrue(result); } } @Test public void testUpdateEnergyFee() { - String preHistory = manager.getDynamicPropertiesStore().getEnergyPriceHistory(); + String preHistory = dbManager.getDynamicPropertiesStore().getEnergyPriceHistory(); long newPrice = 500; Proposal proposal = Proposal.newBuilder().putParameters(ENERGY_FEE.getCode(), newPrice).build(); ProposalCapsule proposalCapsule = new ProposalCapsule(proposal); - boolean result = ProposalService.process(manager, proposalCapsule); + boolean result = ProposalService.process(dbManager, proposalCapsule); Assert.assertTrue(result); - long currentPrice = manager.getDynamicPropertiesStore().getEnergyFee(); + long currentPrice = dbManager.getDynamicPropertiesStore().getEnergyFee(); Assert.assertEquals(currentPrice, newPrice); - String currentHistory = manager.getDynamicPropertiesStore().getEnergyPriceHistory(); + String currentHistory = dbManager.getDynamicPropertiesStore().getEnergyPriceHistory(); Assert.assertEquals(preHistory + "," + proposalCapsule.getExpirationTime() + ":" + newPrice, currentHistory); } @Test public void testUpdateTransactionFee() { - String preHistory = manager.getDynamicPropertiesStore().getBandwidthPriceHistory(); + String preHistory = dbManager.getDynamicPropertiesStore().getBandwidthPriceHistory(); long newPrice = 1500; Proposal proposal = Proposal.newBuilder().putParameters(TRANSACTION_FEE.getCode(), newPrice).build(); ProposalCapsule proposalCapsule = new ProposalCapsule(proposal); proposalCapsule.setExpirationTime(1627279200000L); - boolean result = ProposalService.process(manager, proposalCapsule); + boolean result = ProposalService.process(dbManager, proposalCapsule); Assert.assertTrue(result); - long currentPrice = manager.getDynamicPropertiesStore().getTransactionFee(); + long currentPrice = dbManager.getDynamicPropertiesStore().getTransactionFee(); Assert.assertEquals(currentPrice, newPrice); String expResult = preHistory + "," + proposalCapsule.getExpirationTime() + ":" + newPrice; - String currentHistory = manager.getDynamicPropertiesStore().getBandwidthPriceHistory(); + String currentHistory = dbManager.getDynamicPropertiesStore().getBandwidthPriceHistory(); Assert.assertEquals(expResult, currentHistory); } - @AfterClass - public static void removeDb() { - Args.clearParam(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java b/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java index 4a288b4402c..cbb6c739c9b 100644 --- a/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java @@ -1,60 +1,51 @@ package org.tron.core.services.filter; import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import javax.annotation.Resource; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.tron.common.BaseTest; import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.services.http.FullNodeHttpApiService; import org.tron.core.services.interfaceOnPBFT.http.PBFT.HttpApiOnPBFTService; import org.tron.core.services.interfaceOnSolidity.http.solidity.HttpApiOnSolidityService; -public class HttpApiAccessFilterTest { +public class HttpApiAccessFilterTest extends BaseTest { - private static final Logger logger = LoggerFactory.getLogger("Test"); + @Resource + private Application appTest; + @Resource + private FullNodeHttpApiService httpApiService; + @Resource + private HttpApiOnSolidityService httpApiOnSolidityService; + @Resource + private HttpApiOnPBFTService httpApiOnPBFTService; + private static final CloseableHttpClient httpClient = HttpClients.createDefault(); - private static TronApplicationContext context; - private static Application appTest; - private static CloseableHttpClient httpClient = HttpClients.createDefault(); - private static String dbPath = "output_http_api_access_filter_test"; + static { + dbPath = "output_http_api_access_filter_test"; + Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + Args.getInstance().setFullNodeAllowShieldedTransactionArgs(false); + } /** * init dependencies. */ - @BeforeClass - public static void init() { - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - Args.getInstance().setFullNodeAllowShieldedTransactionArgs(false); - context = new TronApplicationContext(DefaultConfig.class); - appTest = ApplicationFactory.create(context); - - FullNodeHttpApiService httpApiService = context - .getBean(FullNodeHttpApiService.class); - HttpApiOnSolidityService httpApiOnSolidityService = context - .getBean(HttpApiOnSolidityService.class); - HttpApiOnPBFTService httpApiOnPBFTService = context - .getBean(HttpApiOnPBFTService.class); - + @Before + public void init() { appTest.addService(httpApiService); appTest.addService(httpApiOnSolidityService); appTest.addService(httpApiOnPBFTService); @@ -63,22 +54,6 @@ public static void init() { appTest.startup(); } - /** - * destroy the context. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - appTest.shutdownServices(); - appTest.shutdown(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - @Test public void testHttpFilter() { List disabledApiList = new ArrayList<>(); @@ -113,7 +88,7 @@ public void testHttpFilter() { response); Args.getInstance().setDisabledApiList(emptyList); - int statusCode = getReuqestCode(url); + int statusCode = getRequestCode(url); Assert.assertEquals(HttpStatus.SC_OK, statusCode); } } @@ -122,12 +97,12 @@ public void testHttpFilter() { private String sendGetRequest(String url) { HttpGet request = new HttpGet(url); request.setHeader("User-Agent", "Java client"); - HttpResponse response = null; + HttpResponse response; try { response = httpClient.execute(request); BufferedReader rd = new BufferedReader( new InputStreamReader(response.getEntity().getContent())); - StringBuffer result = new StringBuffer(); + StringBuilder result = new StringBuilder(); String line; while ((line = rd.readLine()) != null) { result.append(line); @@ -139,10 +114,10 @@ private String sendGetRequest(String url) { return null; } - private int getReuqestCode(String url) { + private int getRequestCode(String url) { HttpGet request = new HttpGet(url); request.setHeader("User-Agent", "Java client"); - HttpResponse response = null; + HttpResponse response; try { response = httpClient.execute(request); diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java index 472096cf24b..243a76108c9 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java @@ -4,14 +4,13 @@ import io.grpc.ManagedChannelBuilder; import io.grpc.StatusRuntimeException; import java.io.File; +import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.tron.api.DatabaseGrpc; import org.tron.api.GrpcAPI; import org.tron.api.WalletGrpc; @@ -27,10 +26,9 @@ import org.tron.core.services.interfaceOnPBFT.RpcApiServiceOnPBFT; import org.tron.core.services.interfaceOnSolidity.RpcApiServiceOnSolidity; +@Slf4j public class LiteFnQueryGrpcInterceptorTest { - private static final Logger logger = LoggerFactory.getLogger("Test"); - private TronApplicationContext context; private ManagedChannel channelFull = null; private ManagedChannel channelpBFT = null; @@ -43,7 +41,7 @@ public class LiteFnQueryGrpcInterceptorTest { private RpcApiServiceOnPBFT rpcApiServiceOnPBFT; private Application appTest; - private String dbPath = "output_grpc_filter_test"; + private String dbPath = "output_grpc_interceptor_test"; @Rule public ExpectedException thrown = ExpectedException.none(); diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java index d1d294475c9..370c780a192 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java @@ -1,62 +1,54 @@ package org.tron.core.services.filter; import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.util.Set; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; -import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.tron.common.BaseTest; import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.services.http.FullNodeHttpApiService; import org.tron.core.services.interfaceOnPBFT.http.PBFT.HttpApiOnPBFTService; import org.tron.core.services.interfaceOnSolidity.http.solidity.HttpApiOnSolidityService; -public class LiteFnQueryHttpFilterTest { +@Slf4j +public class LiteFnQueryHttpFilterTest extends BaseTest { - private static final Logger logger = LoggerFactory.getLogger("Test"); - - private TronApplicationContext context; - private String ip = "127.0.0.1"; + private final String ip = "127.0.0.1"; private int fullHttpPort; + @Resource private Application appTest; - private CloseableHttpClient httpClient = HttpClients.createDefault(); + @Resource + private FullNodeHttpApiService httpApiService; + @Resource + private HttpApiOnSolidityService httpApiOnSolidityService; + @Resource + private HttpApiOnPBFTService httpApiOnPBFTService; + private final CloseableHttpClient httpClient = HttpClients.createDefault(); - private String dbPath = "output_grpc_filter_test"; + static { + dbPath = "output_http_filter_test"; + Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + Args.getInstance().setFullNodeAllowShieldedTransactionArgs(false); + } /** * init dependencies. */ @Before public void init() { - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - Args.getInstance().setFullNodeAllowShieldedTransactionArgs(false); - context = new TronApplicationContext(DefaultConfig.class); - appTest = ApplicationFactory.create(context); - FullNodeHttpApiService httpApiService = context - .getBean(FullNodeHttpApiService.class); - HttpApiOnSolidityService httpApiOnSolidityService = context - .getBean(HttpApiOnSolidityService.class); - HttpApiOnPBFTService httpApiOnPBFTService = context - .getBean(HttpApiOnPBFTService.class); appTest.addService(httpApiService); appTest.addService(httpApiOnSolidityService); appTest.addService(httpApiOnPBFTService); @@ -65,22 +57,6 @@ public void init() { appTest.startup(); } - /** - * destroy the context. - */ - @After - public void destroy() { - Args.clearParam(); - appTest.shutdownServices(); - appTest.shutdown(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - @Test public void testHttpFilter() { Set urlPathSets = LiteFnQueryHttpFilter.getFilterPaths(); @@ -120,12 +96,12 @@ public void testHttpFilter() { private String sendGetRequest(String url) { HttpGet request = new HttpGet(url); request.setHeader("User-Agent", "Java client"); - HttpResponse response = null; + HttpResponse response; try { response = httpClient.execute(request); BufferedReader rd = new BufferedReader( new InputStreamReader(response.getEntity().getContent())); - StringBuffer result = new StringBuffer(); + StringBuilder result = new StringBuilder(); String line; while ((line = rd.readLine()) != null) { result.append(line); @@ -145,7 +121,7 @@ private String sendPostRequest(String url, String body) throws IOException { HttpResponse response = httpClient.execute(request); BufferedReader rd = new BufferedReader( new InputStreamReader(response.getEntity().getContent())); - StringBuffer result = new StringBuffer(); + StringBuilder result = new StringBuilder(); String line; while ((line = rd.readLine()) != null) { result.append(line); diff --git a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java index c3ef7265f65..f31e96d42dd 100644 --- a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java @@ -7,14 +7,13 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.tron.api.GrpcAPI; import org.tron.api.WalletGrpc; import org.tron.api.WalletSolidityGrpc; @@ -29,10 +28,9 @@ import org.tron.core.services.interfaceOnPBFT.RpcApiServiceOnPBFT; import org.tron.core.services.interfaceOnSolidity.RpcApiServiceOnSolidity; +@Slf4j public class RpcApiAccessInterceptorTest { - private static final Logger logger = LoggerFactory.getLogger("Test"); - private static TronApplicationContext context; private static WalletGrpc.WalletBlockingStub blockingStubFull = null; @@ -40,7 +38,7 @@ public class RpcApiAccessInterceptorTest { private static WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPBFT = null; private static Application appTest; - private static String dbPath = "output_rpc_api_access_filter_test"; + private static String dbPath = "output_rpc_api_access_interceptor_test"; @Rule public ExpectedException thrown = ExpectedException.none(); diff --git a/framework/src/test/java/org/tron/core/services/http/UtilTest.java b/framework/src/test/java/org/tron/core/services/http/UtilTest.java index fed314ba44e..1f698796ba7 100644 --- a/framework/src/test/java/org/tron/core/services/http/UtilTest.java +++ b/framework/src/test/java/org/tron/core/services/http/UtilTest.java @@ -1,44 +1,27 @@ package org.tron.core.services.http; -import java.io.File; -import org.junit.AfterClass; +import javax.annotation.Resource; import org.junit.Assert; -import org.junit.BeforeClass; import org.junit.Test; import org.tron.api.GrpcAPI.TransactionApprovedList; import org.tron.api.GrpcAPI.TransactionSignWeight; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; +import org.tron.common.BaseTest; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.utils.TransactionUtil; import org.tron.protos.Protocol.Transaction; -public class UtilTest { +public class UtilTest extends BaseTest { - private static Wallet wallet; - private static String dbPath = "output_util_test"; - private static TronApplicationContext context; - private static TransactionUtil transactionUtil; + @Resource + private Wallet wallet; + @Resource + private TransactionUtil transactionUtil; static { + dbPath = "output_util_test"; Args.setParam(new String[] {"-d", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - } - - @BeforeClass - public static void init() { - wallet = context.getBean(Wallet.class); - transactionUtil = context.getBean(TransactionUtil.class); - } - - @AfterClass - public static void removeDb() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } @Test diff --git a/framework/src/test/java/org/tron/core/witness/ProposalControllerTest.java b/framework/src/test/java/org/tron/core/witness/ProposalControllerTest.java index 56e115aa325..cb502008bfc 100644 --- a/framework/src/test/java/org/tron/core/witness/ProposalControllerTest.java +++ b/framework/src/test/java/org/tron/core/witness/ProposalControllerTest.java @@ -1,57 +1,46 @@ package org.tron.core.witness; import com.google.protobuf.ByteString; -import java.io.File; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.junit.AfterClass; +import javax.annotation.Resource; import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; import org.testng.collections.Lists; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.ProposalCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.consensus.ConsensusService; import org.tron.core.consensus.ProposalController; -import org.tron.core.db.Manager; import org.tron.core.store.DynamicPropertiesStore; import org.tron.protos.Protocol.Proposal; import org.tron.protos.Protocol.Proposal.State; -public class ProposalControllerTest { +public class ProposalControllerTest extends BaseTest { - private static Manager dbManager; - private static ConsensusService consensusService; - private static TronApplicationContext context; - private static String dbPath = "output_proposal_controller_test"; + @Resource + private ConsensusService consensusService; private static ProposalController proposalController; + private static boolean init; static { + dbPath = "output_proposal_controller_test"; Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); } - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - consensusService = context.getBean(ConsensusService.class); + @Before + public void init() { + if (init) { + return; + } consensusService.start(); - proposalController = ProposalController - .createInstance(dbManager); - } - - @AfterClass - public static void removeDb() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); + proposalController = ProposalController.createInstance(dbManager); + init = true; } @Test @@ -199,7 +188,7 @@ public void testHasMostApprovals() { proposalCapsule.addApproval(ByteString.copyFrom(new byte[]{(byte) i})); } - Assert.assertEquals(true, proposalCapsule.hasMostApprovals(activeWitnesses)); + Assert.assertTrue(proposalCapsule.hasMostApprovals(activeWitnesses)); proposalCapsule.clearApproval(); for (int i = 1; i < 18; i++) { @@ -214,10 +203,7 @@ public void testHasMostApprovals() { for (int i = 0; i < 3; i++) { proposalCapsule.addApproval(ByteString.copyFrom(new byte[]{(byte) i})); } - Assert.assertEquals(true, proposalCapsule.hasMostApprovals(activeWitnesses)); - - + Assert.assertTrue(proposalCapsule.hasMostApprovals(activeWitnesses)); } - } diff --git a/framework/src/test/java/org/tron/core/witness/WitnessControllerTest.java b/framework/src/test/java/org/tron/core/witness/WitnessControllerTest.java index 665b5049bfc..dcca6e4bc65 100644 --- a/framework/src/test/java/org/tron/core/witness/WitnessControllerTest.java +++ b/framework/src/test/java/org/tron/core/witness/WitnessControllerTest.java @@ -3,51 +3,25 @@ import static org.junit.Assert.assertEquals; import com.google.protobuf.ByteString; -import java.io.File; import java.util.ArrayList; import java.util.List; -import org.junit.AfterClass; -import org.junit.BeforeClass; +import javax.annotation.Resource; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.consensus.dpos.DposSlot; -import org.tron.core.ChainBaseManager; import org.tron.core.Constant; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; -public class WitnessControllerTest { +public class WitnessControllerTest extends BaseTest { - private static Manager dbManager = new Manager(); - private static DposSlot dposSlot; - private static ChainBaseManager chainBaseManager; + @Resource + private DposSlot dposSlot; - private static TronApplicationContext context; - private static String dbPath = "output_witness_controller_test"; static { + dbPath = "output_witness_controller_test"; Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - } - - ByteString blank = ByteString.copyFrom(new byte[1]); - - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - chainBaseManager = context.getBean(ChainBaseManager.class); - - dposSlot = context.getBean(DposSlot.class); - } - - @AfterClass - public static void removeDb() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } @Test diff --git a/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java b/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java index 2556b1b3005..55223bccb0c 100644 --- a/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java @@ -1,5 +1,9 @@ package org.tron.core.zksnark; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; import static org.tron.common.zksnark.JLibrustzcash.librustzcashCheckDiversifier; import static org.tron.common.zksnark.JLibrustzcash.librustzcashComputeCm; import static org.tron.common.zksnark.JLibrustzcash.librustzcashIvkToPkd; @@ -11,23 +15,20 @@ import static org.tron.common.zksnark.JLibsodium.CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES; import com.google.protobuf.ByteString; -import java.io.File; +import java.util.Arrays; import java.util.Optional; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; import java.util.stream.LongStream; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; -import org.junit.Assert; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.FileUtil; import org.tron.common.zksnark.IncrementalMerkleTreeContainer; import org.tron.common.zksnark.IncrementalMerkleVoucherContainer; import org.tron.common.zksnark.JLibrustzcash; @@ -46,7 +47,6 @@ import org.tron.core.capsule.IncrementalMerkleTreeCapsule; import org.tron.core.capsule.PedersenHashCapsule; import org.tron.core.capsule.SpendDescriptionCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.exception.BadItemException; import org.tron.core.exception.ZksnarkException; @@ -65,15 +65,15 @@ import org.tron.protos.contract.ShieldContract.PedersenHash; @Slf4j -public class LibrustzcashTest { +public class LibrustzcashTest extends BaseTest { + private static final String dbDirectory = "db_Librustzcash_test"; + private static final String indexDirectory = "index_Librustzcash_test"; + @Resource + private Wallet wallet; - private static String dbPath = "output_Librustzcash_test"; - private static String dbDirectory = "db_Librustzcash_test"; - private static String indexDirectory = "index_Librustzcash_test"; - private static AnnotationConfigApplicationContext context; - private static Wallet wallet; - - static { + @BeforeClass + public static void init() { + dbPath = "output_Librustzcash_test"; Args.setParam( new String[]{ "--output-directory", dbPath, @@ -84,23 +84,9 @@ public class LibrustzcashTest { }, "config-test-mainnet.conf" ); - - context = new TronApplicationContext(DefaultConfig.class); - } - - @BeforeClass - public static void init() { - wallet = context.getBean(Wallet.class); Args.setFullNodeAllowShieldedTransaction(true); } - @AfterClass - public static void removeDb() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } - private static int randomInt(int minInt, int maxInt) { return (int) Math.round(Math.random() * (maxInt - minInt) + minInt); } @@ -117,21 +103,19 @@ public static void test(byte[] K, byte[] ovk, byte[] cv, byte[] cm, byte[] epk) byte[] personalization = new byte[16]; byte[] aa = "Zcash_Derive_ock".getBytes(); System.arraycopy(aa, 0, personalization, 0, aa.length); - Assert.assertTrue( - JLibsodium.cryptoGenerichashBlack2bSaltPersonal( - new Black2bSaltPersonalParams(K, 32, block, 128, null, 0, // No key. - null, // No salt. - personalization)) == 0); + assertEquals(0, JLibsodium.cryptoGenerichashBlack2bSaltPersonal( + new Black2bSaltPersonalParams(K, 32, block, 128, null, 0, // No key. + null, // No salt. + personalization))); byte[] cipher_nonce = new byte[CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES]; - Assert.assertTrue(JLibsodium + assertNotEquals(0, JLibsodium .cryptoAeadChacha20poly1305IetfDecrypt(new Chacha20poly1305IetfDecryptParams( new byte[1024], null, null, new byte[1024], 1024, - null, 0, cipher_nonce, K)) != 0); + null, 0, cipher_nonce, K))); } public static void librustzcashInitZksnarkParams() { - FullNodeHttpApiService.librustzcashInitZksnarkParams(); } @@ -148,8 +132,6 @@ public void testLibsodium() throws ZksnarkException { @Test public void testZcashParam() throws ZksnarkException { byte[] d = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - //byte[] d ={}; - //byte[] pkD = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; byte[] ivk = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; @@ -161,7 +143,7 @@ public void testZcashParam() throws ZksnarkException { (byte) 0xb4, 0x7d, 0x0e}; byte[] cm = new byte[32]; boolean check_d = librustzcashCheckDiversifier(d); - Assert.assertTrue(check_d); + assertTrue(check_d); //Most significant five bits of ivk must be 0. ivk[31] = (byte) 0x07; @@ -173,10 +155,10 @@ public void testZcashParam() throws ZksnarkException { System.out.printf("\n"); } } - Assert.assertTrue(check_pkd); + assertTrue(check_pkd); boolean res = librustzcashComputeCm(new ComputeCmParams(d, pkD, value, r, cm)); - Assert.assertFalse(res); + assertFalse(res); //check range of alpha byte[] ask = {(byte) 0xb7, 0x2c, (byte) 0xf7, (byte) 0xd6, 0x5e, 0x0e, (byte) 0x97, (byte) 0xd0, @@ -196,14 +178,14 @@ public void testZcashParam() throws ZksnarkException { boolean boolSigRes = librustzcashSaplingSpendSig( new SpendSigParams(ask, alpha, sighash, sigRes)); - Assert.assertFalse(boolSigRes); + assertFalse(boolSigRes); byte[] nsk = {(byte) 0xb6, 0x2c, (byte) 0xf7, (byte) 0xd6, 0x5e, 0x0e, (byte) 0x97, (byte) 0xd0, (byte) 0x82, 0x10, (byte) 0xc8, (byte) 0xcc, (byte) 0x93, 0x20, 0x68, (byte) 0xa6, 0x00, 0x3b, 0x34, 0x01, 0x01, 0x3b, 0x67, 0x06, (byte) 0xa9, (byte) 0xaf, 0x33, 0x65, (byte) 0xea, (byte) 0xb4, 0x7d, 0x0e}; - byte[] nk = new byte[32]; + byte[] nk; nk = librustzcashNskToNk(nsk); for (int j = 0; j < 32; j++) { @@ -217,7 +199,7 @@ public void testZcashParam() throws ZksnarkException { byte[] resbindSig = new byte[64]; boolean boolBindSig = librustzcashSaplingBindingSig( new BindingSigParams(ctx, value, sighash, resbindSig)); - Assert.assertFalse(boolBindSig); + assertFalse(boolBindSig); JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); } @@ -284,15 +266,14 @@ public long benchmarkCreateSpend() throws ZksnarkException { zkproof)); JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); - Assert.assertTrue(ret); - long time = (System.currentTimeMillis() - start); - System.out.println("--- time is: " + time + ", result is " + ret); + assertTrue(ret); return time; } - // @Test + @Ignore + @Test public void calBenchmarkSpendConcurrent() throws Exception { librustzcashInitZksnarkParams(); System.out.println("--- load ok ---"); @@ -307,24 +288,17 @@ public void calBenchmarkSpendConcurrent() throws Exception { ExecutorService generatePool = Executors.newFixedThreadPool( availableProcessors, - new ThreadFactory() { - @Override - public Thread newThread(Runnable r) { - return new Thread(r, "generate-transaction"); - } - }); + r -> new Thread(r, "generate-transaction")); long startGenerate = System.currentTimeMillis(); - LongStream.range(0L, count).forEach(l -> { - generatePool.execute(() -> { - try { - benchmarkCreateSpend(); - } catch (Exception ex) { - ex.printStackTrace(); - logger.error("", ex); - } - }); - }); + LongStream.range(0L, count).forEach(l -> generatePool.execute(() -> { + try { + benchmarkCreateSpend(); + } catch (Exception ex) { + ex.printStackTrace(); + logger.error("", ex); + } + })); countDownLatch.await(); @@ -466,7 +440,7 @@ public long benchmarkCreateSaplingOutput() throws BadItemException, ZksnarkExcep JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); - Assert.assertTrue(result); + assertTrue(result); long endTime = System.currentTimeMillis(); long time = endTime - startTime; @@ -526,7 +500,7 @@ public void checkVerifyOutErr() throws ZksnarkException { JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); - Assert.assertFalse(result); + assertFalse(result); } @Test @@ -550,19 +524,20 @@ public void testGenerateNote() throws Exception { try { Optional op = incomingViewingKey.address(diversifierT); // PaymentAddress op = spendingKey.defaultAddress(); - - Note note = new Note(op.get(), 100); - note.setRcm(ByteArray - .fromHexString( - "bf4b2042e3e8c4a0b390e407a79a0b46e36eff4f7bb54b2349dbb0046ee21e02")); - - byte[] cm = note.cm(); - if (cm != null) { - success++; - } else { - fail++; + if (op.isPresent()) { + Note note = new Note(op.get(), 100); + note.setRcm(ByteArray + .fromHexString( + "bf4b2042e3e8c4a0b390e407a79a0b46e36eff4f7bb54b2349dbb0046ee21e02")); + + byte[] cm = note.cm(); + if (cm != null) { + success++; + } else { + fail++; + } + System.out.println("note is " + Arrays.toString(cm)); } - System.out.println("note is " + note.cm()); } catch (ZksnarkException e) { System.out.println("failed: " + e.getMessage()); fail++; @@ -573,7 +548,7 @@ public void testGenerateNote() throws Exception { System.out.println("success is: " + success); System.out.println("fail is: " + fail); - Assert.assertEquals(0, fail); + assertEquals(0, fail); } @Test @@ -615,7 +590,7 @@ public void testGenerateNoteWithDefault() throws Exception { System.out.println("success is: " + success); System.out.println("fail is: " + fail); - Assert.assertEquals(0, fail); + assertEquals(0, fail); } @Test @@ -635,13 +610,14 @@ public void testGenerateNoteWithConstant() throws Exception { try { Optional op = incomingViewingKey.address(diversifierT); // PaymentAddress op = spendingKey.defaultAddress(); + if (op.isPresent()) { + Note note = new Note(op.get(), randomInt(100, 100000)); + note.setRcm(ByteArray + .fromHexString("bf4b2042e3e8c4a0b390e407a79a0b46e36eff4f7bb54b2349dbb0046ee21e02")); - Note note = new Note(op.get(), randomInt(100, 100000)); - note.setRcm(ByteArray - .fromHexString("bf4b2042e3e8c4a0b390e407a79a0b46e36eff4f7bb54b2349dbb0046ee21e02")); - - byte[] cm = note.cm(); - System.out.println("note is " + note.cm()); + byte[] cm = note.cm(); + System.out.println("note is " + Arrays.toString(cm)); + } } catch (ZksnarkException e) { System.out.println("failed: " + e.getMessage()); } @@ -659,7 +635,7 @@ public void testPedersenHash() throws Exception { byte[] res = new byte[32]; JLibrustzcash.librustzcashMerkleHash(new MerkleHashParams(25, a, b, res)); - Assert.assertEquals("61a50a5540b4944da27cbd9b3d6ec39234ba229d2c461f4d719bc136573bf45b", + assertEquals("61a50a5540b4944da27cbd9b3d6ec39234ba229d2c461f4d719bc136573bf45b", ByteArray.toHexString(res)); } } diff --git a/framework/src/test/java/org/tron/core/zksnark/MerkleContainerTest.java b/framework/src/test/java/org/tron/core/zksnark/MerkleContainerTest.java index 60c5dd43eac..678eb137df0 100644 --- a/framework/src/test/java/org/tron/core/zksnark/MerkleContainerTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/MerkleContainerTest.java @@ -2,19 +2,14 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; -import java.io.File; -import java.util.Arrays; -import org.junit.AfterClass; +import javax.annotation.Resource; import org.junit.Assert; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.Sha256Hash; import org.tron.common.zksnark.IncrementalMerkleVoucherContainer; -import org.tron.common.zksnark.MerkleContainer; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.BlockCapsule; @@ -23,9 +18,7 @@ import org.tron.core.capsule.IncrementalMerkleVoucherCapsule; import org.tron.core.capsule.PedersenHashCapsule; import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ZksnarkException; import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.Transaction; @@ -37,38 +30,29 @@ import org.tron.protos.contract.ShieldContract.ReceiveDescription; import org.tron.protos.contract.ShieldContract.ShieldedTransferContract; -public class MerkleContainerTest { +public class MerkleContainerTest extends BaseTest { - private static Manager dbManager = new Manager(); - private static TronApplicationContext context; - private static String dbPath = "MerkleContainerTest"; - private static MerkleContainer merkleContainer; + @Resource + private Wallet wallet; + // private static MerkleContainer merkleContainer; static { + dbPath = "MerkleContainerTest"; Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); } - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); + /*@Before + public void init() { merkleContainer = MerkleContainer .createInstance(dbManager.getMerkleTreeStore(), dbManager.getChainBaseManager() .getMerkleTreeIndexStore()); - } - - @AfterClass - public static void removeDb() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } + }*/ - @Test + /*@Test public void test() { //add - /*IncrementalMerkleTreeContainer tree = new IncrementalMerkleTreeContainer( + IncrementalMerkleTreeContainer tree = new IncrementalMerkleTreeContainer( new IncrementalMerkleTreeCapsule()); String s1 = "2ec45f5ae2d1bc7a80df02abfb2814a1239f956c6fb3ac0e112c008ba2c1ab91"; PedersenHashCapsule compressCapsule1 = new PedersenHashCapsule(); @@ -164,9 +148,9 @@ public void test() { .putMerkleVoucherIntoStore(witness.getMerkleVoucherKey(), witness.getVoucherCapsule()); IncrementalMerkleTreeContainer bestMerkleRoot = merkleContainer.getBestMerkle(); - Assert.assertEquals(1, bestMerkleRoot.size());*/ + Assert.assertEquals(1, bestMerkleRoot.size()); - } + }*/ private Transaction createTransaction(String strCm1, String strCm2) { ByteString cm1 = ByteString.copyFrom(ByteArray.fromHexString(strCm1)); @@ -182,9 +166,8 @@ private Transaction createTransaction(String strCm1, String strCm2) { Transaction.Contract.newBuilder().setType(ContractType.ShieldedTransferContract) .setParameter( Any.pack(contract)).build()); - Transaction transaction = Transaction.newBuilder().setRawData(transactionBuilder.build()) + return Transaction.newBuilder().setRawData(transactionBuilder.build()) .build(); - return transaction; } private void initMerkleTreeWitnessInfo() throws ZksnarkException { @@ -361,7 +344,6 @@ public void getMerkleTreeWitnessInfoTest() throws Exception { OutputPointInfo outputPointInfo = OutputPointInfo.newBuilder().addOutPoints(outputPoint1) .addOutPoints(outputPoint2).setBlockNum(number).build(); // Args.getInstance().setAllowShieldedTransaction(1); - Wallet wallet = context.getBean(Wallet.class); IncrementalMerkleVoucherInfo merkleTreeWitnessInfo = wallet .getMerkleTreeVoucherInfo(outputPointInfo); @@ -426,7 +408,7 @@ public void append() throws ZksnarkException { byte[] roota = witnessa.root().getContent().toByteArray(); byte[] rootb = witnessb.root().getContent().toByteArray(); - Assert.assertTrue(Arrays.equals(roota, rootb)); + Assert.assertArrayEquals(roota, rootb); } } diff --git a/framework/src/test/java/org/tron/core/zksnark/MerkleTreeTest.java b/framework/src/test/java/org/tron/core/zksnark/MerkleTreeTest.java index 155d5aee11a..512b2f99228 100644 --- a/framework/src/test/java/org/tron/core/zksnark/MerkleTreeTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/MerkleTreeTest.java @@ -6,40 +6,31 @@ import com.google.protobuf.ByteString; import java.io.File; import java.util.List; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.testng.collections.Lists; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.FileUtil; import org.tron.common.zksnark.IncrementalMerkleTreeContainer; import org.tron.common.zksnark.IncrementalMerkleTreeContainer.EmptyMerkleRoots; import org.tron.common.zksnark.IncrementalMerkleVoucherContainer; import org.tron.common.zksnark.MerklePath; -import org.tron.core.Wallet; import org.tron.core.capsule.IncrementalMerkleTreeCapsule; import org.tron.core.capsule.IncrementalMerkleVoucherCapsule; import org.tron.core.capsule.PedersenHashCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.protos.contract.ShieldContract.PedersenHash; -public class MerkleTreeTest { +public class MerkleTreeTest extends BaseTest { public static final long totalBalance = 1000_0000_000_000L; - private static String dbPath = "output_ShieldedTransaction_test"; - private static String dbDirectory = "db_ShieldedTransaction_test"; - private static String indexDirectory = "index_ShieldedTransaction_test"; - private static AnnotationConfigApplicationContext context; - private static Manager dbManager; - private static Wallet wallet; + private static final String dbDirectory = "db_ShieldedTransaction_test"; + private static final String indexDirectory = "index_ShieldedTransaction_test"; static { + dbPath = "output_ShieldedTransaction_test"; Args.setParam( new String[]{ "--output-directory", dbPath, @@ -50,40 +41,27 @@ public class MerkleTreeTest { }, "config-test-mainnet.conf" ); - context = new TronApplicationContext(DefaultConfig.class); } /** * Init data. */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - wallet = context.getBean(Wallet.class); + @Before + public void init() { //init energy dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(1526647838000L); dbManager.getDynamicPropertiesStore().saveTotalEnergyWeight(100_000L); - dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(0); } - @AfterClass - public static void removeDb() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } - private JSONArray readFile(String fileName) throws Exception { String file1 = SendCoinShieldTest.class.getClassLoader() .getResource("json" + File.separator + fileName).getFile(); List readLines = Files.readLines(new File(file1), Charsets.UTF_8); - JSONArray array = JSONArray + return JSONArray .parseArray(readLines.stream().reduce((s, s2) -> s + s2).get()); - - return array; } private String PedersenHash2String(PedersenHash hash) { diff --git a/framework/src/test/java/org/tron/core/zksnark/NoteEncDecryTest.java b/framework/src/test/java/org/tron/core/zksnark/NoteEncDecryTest.java index f77a85b5bc1..1fc31c293e8 100644 --- a/framework/src/test/java/org/tron/core/zksnark/NoteEncDecryTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/NoteEncDecryTest.java @@ -1,22 +1,17 @@ package org.tron.core.zksnark; import com.google.protobuf.ByteString; -import java.io.File; import java.util.Optional; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Wallet; import org.tron.core.capsule.AssetIssueCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ZksnarkException; import org.tron.core.zen.note.Note; import org.tron.core.zen.note.NoteEncryption.Encryption; @@ -25,7 +20,7 @@ import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; @Slf4j -public class NoteEncDecryTest { +public class NoteEncDecryTest extends BaseTest { private static final String dbPath = "note_encdec_test"; private static final String FROM_ADDRESS; @@ -41,13 +36,11 @@ public class NoteEncDecryTest { private static final int VOTE_SCORE = 2; private static final String DESCRIPTION = "TRX"; private static final String URL = "https://tron.network/"; - private static Manager dbManager; - private static TronApplicationContext context; - private static Wallet wallet; + @Resource + private Wallet wallet; static { Args.setParam(new String[]{"--output-directory", dbPath}, "config-localtest.conf"); - context = new TronApplicationContext(DefaultConfig.class); FROM_ADDRESS = Wallet.getAddressPreFixString() + "a7d8a35b260395c14aa456297662092ba3b76fc0"; ADDRESS_ONE_PRIVATE_KEY = "7f7f701e94d4f1dd60ee5205e7ea8ee31121427210417b608a6b2e96433549a7"; } @@ -55,30 +48,13 @@ public class NoteEncDecryTest { /** * Init data. */ - @BeforeClass - public static void init() { - wallet = context.getBean(Wallet.class); - dbManager = context.getBean(Manager.class); + @Before + public void init() { //give a big value for pool, avoid for dbManager.getDynamicPropertiesStore().saveTotalShieldedPoolValue(10_000_000_000L); // Args.getInstance().setAllowShieldedTransaction(1); } - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - /** * create temp Capsule test need. */ diff --git a/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java b/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java index 1eb5becffb6..cbc657e02c9 100644 --- a/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java @@ -11,19 +11,16 @@ import java.util.Arrays; import java.util.List; import java.util.Optional; -import org.junit.AfterClass; +import javax.annotation.Resource; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.testng.collections.Lists; import org.tron.api.GrpcAPI; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.Sha256Hash; import org.tron.common.zksnark.IncrementalMerkleTreeContainer; import org.tron.common.zksnark.IncrementalMerkleTreeContainer.EmptyMerkleRoots; @@ -50,9 +47,7 @@ import org.tron.core.capsule.SpendDescriptionCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.TransactionResultCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.AccountResourceInsufficientException; import org.tron.core.exception.BadItemException; import org.tron.core.exception.ContractExeException; @@ -90,7 +85,7 @@ import org.tron.protos.contract.ShieldContract.ShieldedTransferContract; import org.tron.protos.contract.ShieldContract.SpendDescription; -public class SendCoinShieldTest { +public class SendCoinShieldTest extends BaseTest { public static final long totalBalance = 1000_0000_000_000L; private static final byte[] DEFAULT_OVK; @@ -105,16 +100,15 @@ public class SendCoinShieldTest { private static final int VOTE_SCORE = 2; private static final String DESCRIPTION = "TRX"; private static final String URL = "https://tron.network/"; - private static String dbPath = "output_ShieldedTransaction_test"; - private static String dbDirectory = "db_ShieldedTransaction_test"; - private static String indexDirectory = "index_ShieldedTransaction_test"; - private static AnnotationConfigApplicationContext context; - private static Manager dbManager; - private static Wallet wallet; + @Resource + private Wallet wallet; + + private static boolean init; static { + dbPath = "output_ShieldedTransaction_test"; Args.setParam(new String[]{"--output-directory", dbPath}, "config-test-mainnet.conf"); - context = new TronApplicationContext(DefaultConfig.class); + Args.getInstance().setZenTokenId(String.valueOf(tokenId)); PUBLIC_ADDRESS_ONE = Wallet.getAddressPreFixString() + "a7d8a35b260395c14aa456297662092ba3b76fc0"; DEFAULT_OVK = ByteArray @@ -124,29 +118,16 @@ public class SendCoinShieldTest { /** * Init data. */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - wallet = context.getBean(Wallet.class); + @Before + public void init() { + if (init) { + return; + } //init energy dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(1526647838000L); dbManager.getDynamicPropertiesStore().saveTotalEnergyWeight(100_000L); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(0); - } - @AfterClass - public static void removeDb() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } - - /** - * create temp Capsule test need. - */ - @Before - public void createCapsule() { - Args.getInstance().setZenTokenId(String.valueOf(tokenId)); dbManager.getDynamicPropertiesStore().saveAllowSameTokenName(1); dbManager.getDynamicPropertiesStore().saveTokenIdNum(tokenId); @@ -159,6 +140,8 @@ public void createCapsule() { .setUrl(ByteString.copyFrom(ByteArray.fromString(URL))).build(); AssetIssueCapsule assetIssueCapsule = new AssetIssueCapsule(assetIssueContract); dbManager.getAssetIssueV2Store().put(assetIssueCapsule.createDbV2Key(), assetIssueCapsule); + + init = true; } private void addZeroValueOutputNote(ZenTransactionBuilder builder) throws ZksnarkException { diff --git a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java index d3cbdb71e95..d549d306cb1 100755 --- a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java @@ -4,29 +4,26 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; -import java.io.File; import java.security.SignatureException; import java.util.List; import java.util.Optional; +import javax.annotation.Resource; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; import org.tron.api.GrpcAPI.BytesMessage; import org.tron.api.GrpcAPI.DecryptNotes; import org.tron.api.GrpcAPI.ReceiveNote; import org.tron.api.GrpcAPI.SpendAuthSigParameters; import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.crypto.ECKey; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.Sha256Hash; import org.tron.common.zksnark.IncrementalMerkleTreeContainer; import org.tron.common.zksnark.IncrementalMerkleVoucherContainer; @@ -37,7 +34,6 @@ import org.tron.common.zksnark.LibrustzcashParam.IvkToPkdParams; import org.tron.common.zksnark.LibrustzcashParam.OutputProofParams; import org.tron.common.zksnark.LibrustzcashParam.SpendSigParams; -import org.tron.core.ChainBaseManager; import org.tron.core.Wallet; import org.tron.core.actuator.Actuator; import org.tron.core.actuator.ActuatorCreator; @@ -52,11 +48,8 @@ import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.consensus.ConsensusService; -import org.tron.core.db.BlockGenerate; -import org.tron.core.db.Manager; import org.tron.core.exception.AccountResourceInsufficientException; import org.tron.core.exception.BadItemException; import org.tron.core.exception.ContractExeException; @@ -104,9 +97,8 @@ import org.tron.protos.contract.ShieldContract.SpendDescription; @Slf4j -public class ShieldedReceiveTest extends BlockGenerate { +public class ShieldedReceiveTest extends BaseTest { - private static final String dbPath = "receive_description_test"; private static final String FROM_ADDRESS; private static final String ADDRESS_ONE_PRIVATE_KEY; private static final long OWNER_BALANCE = 100_000_000; @@ -120,16 +112,18 @@ public class ShieldedReceiveTest extends BlockGenerate { private static final int VOTE_SCORE = 2; private static final String DESCRIPTION = "TRX"; private static final String URL = "https://tron.network/"; - private static Manager dbManager; - private static ChainBaseManager chainBaseManager; - private static ConsensusService consensusService; - private static TronApplicationContext context; - private static Wallet wallet; - private static TransactionUtil transactionUtil; + @Resource + private ConsensusService consensusService; + @Resource + private Wallet wallet; + @Resource + private TransactionUtil transactionUtil; + + private static boolean init; static { + dbPath = "receive_description_test"; Args.setParam(new String[]{"--output-directory", dbPath}, "config-localtest.conf"); - context = new TronApplicationContext(DefaultConfig.class); FROM_ADDRESS = Wallet.getAddressPreFixString() + "a7d8a35b260395c14aa456297662092ba3b76fc0"; ADDRESS_ONE_PRIVATE_KEY = "7f7f701e94d4f1dd60ee5205e7ea8ee31121427210417b608a6b2e96433549a7"; } @@ -137,35 +131,14 @@ public class ShieldedReceiveTest extends BlockGenerate { /** * Init data. */ - @BeforeClass - public static void init() { - FileUtil.deleteDir(new File(dbPath)); - - wallet = context.getBean(Wallet.class); - transactionUtil = context.getBean(TransactionUtil.class); - dbManager = context.getBean(Manager.class); - chainBaseManager = context.getBean(ChainBaseManager.class); - setManager(dbManager); - consensusService = context.getBean(ConsensusService.class); + @Before + public void init() { + if (init) { + return; + } consensusService.start(); - //give a big value for pool, avoid for chainBaseManager.getDynamicPropertiesStore().saveTotalShieldedPoolValue(10_000_000_000L); - // Args.getInstance().setAllowShieldedTransaction(1); - } - - /** - * Release resources. - */ - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } + init = true; } private static void librustzcashInitZksnarkParams() { diff --git a/framework/src/test/java/org/tron/program/AccountVoteWitnessTest.java b/framework/src/test/java/org/tron/program/AccountVoteWitnessTest.java index f87b0f81730..9f61d91a938 100755 --- a/framework/src/test/java/org/tron/program/AccountVoteWitnessTest.java +++ b/framework/src/test/java/org/tron/program/AccountVoteWitnessTest.java @@ -4,59 +4,26 @@ import com.google.protobuf.ByteString; import java.io.File; import java.util.List; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.consensus.dpos.MaintenanceManager; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.protos.Protocol.AccountType; @Slf4j -public class AccountVoteWitnessTest { +public class AccountVoteWitnessTest extends BaseTest { - private static TronApplicationContext context; - - private static Manager dbManager; - private static MaintenanceManager maintenanceManager; - private static String dbPath = "output_witness_test"; + @Resource + private MaintenanceManager maintenanceManager; static { + dbPath = "output_witness_test"; Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - } - - /** - * init db. - */ - @BeforeClass - public static void init() { - dbManager = context.getBean(Manager.class); - maintenanceManager = context.getBean(MaintenanceManager.class); - // Args.setParam(new String[]{}, Constant.TEST_CONF); - // dbManager = new Manager(); - // dbManager.init(); - } - - /** - * remo db when after test. - */ - @AfterClass - public static void removeDb() { - Args.clearParam(); - context.destroy(); - File dbFolder = new File(dbPath); - if (deleteFolder(dbFolder)) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } private static Boolean deleteFolder(File index) { diff --git a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java index 4549b2cde4d..ed268ec882a 100644 --- a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java +++ b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java @@ -1,19 +1,15 @@ package org.tron.program; -import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.io.File; -import java.math.BigInteger; import java.nio.file.Paths; +import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.tron.api.GrpcAPI; import org.tron.api.WalletGrpc; import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; @@ -23,30 +19,23 @@ import org.tron.common.utils.FileUtil; import org.tron.common.utils.PublicMethod; import org.tron.common.utils.Utils; -import org.tron.core.Wallet; 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.protos.Protocol; -import org.tron.protos.contract.BalanceContract; import org.tron.tool.litefullnode.LiteFullNodeTool; -import stest.tron.wallet.common.client.utils.TransactionUtils; +@Slf4j public class LiteFullNodeToolTest { - private static final Logger logger = LoggerFactory.getLogger("Test"); - private TronApplicationContext context; private WalletGrpc.WalletBlockingStub blockingStubFull = null; private Application appTest; - private String databaseDir; @Rule public ExpectedException thrown = ExpectedException.none(); - private static final String DB_PATH = "output_lite_fn"; /** @@ -61,16 +50,16 @@ public void startApp() { appTest.startServices(); appTest.startup(); - String fullnode = String.format("%s:%d", "127.0.0.1", + String fullNode = String.format("%s:%d", "127.0.0.1", Args.getInstance().getRpcPort()); - ManagedChannel channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext(true) + ManagedChannel channelFull = ManagedChannelBuilder.forTarget(fullNode) + .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } /** - * Delete the database when exit. + * Delete the database when exited. */ public static void destroy(String dbPath) { File f = new File(dbPath); @@ -84,7 +73,7 @@ public static void destroy(String dbPath) { } /** - * shutdown the fullnode. + * shutdown the fullNode. */ public void shutdown() { appTest.shutdownServices(); @@ -142,7 +131,7 @@ private void testTools(String dbType, int checkpointVersion) { Args.getInstance().getStorage().setDbEngine(dbType); Args.getInstance().getStorage().setCheckpointVersion(checkpointVersion); LiteFullNodeTool.setRecentBlks(3); - // start fullnode + // start fullNode startApp(); // produce transactions for 18 seconds generateSomeTransactions(18); @@ -152,7 +141,7 @@ private void testTools(String dbType, int checkpointVersion) { FileUtil.deleteDir(Paths.get(DB_PATH, databaseDir, "trans-cache").toFile()); // generate snapshot LiteFullNodeTool.main(argsForSnapshot); - // start fullnode + // start fullNode startApp(); // produce transactions for 6 seconds generateSomeTransactions(6); @@ -165,14 +154,14 @@ private void testTools(String dbType, int checkpointVersion) { if (!database.renameTo(new File(Paths.get(DB_PATH, databaseDir + "_bak").toString()))) { throw new RuntimeException( String.format("rename %s to %s failed", database.getPath(), - Paths.get(DB_PATH, databaseDir).toString())); + Paths.get(DB_PATH, databaseDir))); } // change snapshot to the new database File snapshot = new File(Paths.get(DB_PATH, "snapshot").toString()); if (!snapshot.renameTo(new File(Paths.get(DB_PATH, databaseDir).toString()))) { throw new RuntimeException( String.format("rename snapshot to %s failed", - Paths.get(DB_PATH, databaseDir).toString())); + Paths.get(DB_PATH, databaseDir))); } // start and validate the snapshot startApp(); diff --git a/framework/src/test/java/org/tron/program/SolidityNodeTest.java b/framework/src/test/java/org/tron/program/SolidityNodeTest.java index 0bd2dccfe85..b9989f9c002 100755 --- a/framework/src/test/java/org/tron/program/SolidityNodeTest.java +++ b/framework/src/test/java/org/tron/program/SolidityNodeTest.java @@ -6,8 +6,6 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.client.DatabaseGrpcClient; import org.tron.core.Constant; @@ -23,14 +21,12 @@ public class SolidityNodeTest { private static TronApplicationContext context; private static RpcApiService rpcApiService; - private static Application appT; private static String dbPath = "output_witness_test"; static { Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); Args.getInstance().setSolidityNode(true); - appT = ApplicationFactory.create(context); rpcApiService = context.getBean(RpcApiService.class); } From 06bd0107953d7c77304d43c0b2366de6c8ad13ad Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Thu, 2 Feb 2023 15:05:50 +0800 Subject: [PATCH 0573/1197] fix(unitTest): shutdown thread pools and timers --- framework/src/main/java/org/tron/core/db/Manager.java | 1 + .../tron/core/net/messagehandler/TransactionsMsgHandler.java | 1 + .../tron/core/net/service/nodepersist/NodePersistService.java | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index b43387ec4f6..feac88a9a1f 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1907,6 +1907,7 @@ public NullifierStore getNullifierStore() { public void closeAllStore() { logger.info("******** Begin to close db. ********"); chainBaseManager.closeAllStore(); + validateSignService.shutdown(); logger.info("******** End to close db. ********"); } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java index df46c448e4d..5f8b3fcef16 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java @@ -53,6 +53,7 @@ public void init() { } public void close() { + trxHandlePool.shutdown(); smartContractExecutor.shutdown(); } diff --git a/framework/src/main/java/org/tron/core/net/service/nodepersist/NodePersistService.java b/framework/src/main/java/org/tron/core/net/service/nodepersist/NodePersistService.java index 02ff1e7a1aa..e2e5bc4dc08 100644 --- a/framework/src/main/java/org/tron/core/net/service/nodepersist/NodePersistService.java +++ b/framework/src/main/java/org/tron/core/net/service/nodepersist/NodePersistService.java @@ -27,9 +27,10 @@ public class NodePersistService { private ChainBaseManager chainBaseManager = ChainBaseManager.getInstance(); - private Timer nodePersistTaskTimer = new Timer("NodePersistTaskTimer"); + private Timer nodePersistTaskTimer; public void init() { + nodePersistTaskTimer = new Timer("NodePersistTaskTimer"); if (isNodePersist) { nodePersistTaskTimer.scheduleAtFixedRate(new TimerTask() { @Override From 3664fff3837c1cb651e1793f7f33f876ef767468 Mon Sep 17 00:00:00 2001 From: zhang0125 Date: Thu, 2 Feb 2023 15:07:13 +0800 Subject: [PATCH 0574/1197] fix(unitTest): ignore LiteFullNodeToolTest --- .../tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java | 4 ++-- .../src/test/java/org/tron/program/LiteFullNodeToolTest.java | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java index 1f1efe6cc6b..d1f19fc4d2a 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java @@ -61,8 +61,8 @@ public class BandWidthRuntimeWithCheckTest extends BaseTest { public static final long totalBalance = 1000_0000_000_000L; - private static final String dbDirectory = "db_BandWidthRuntimeTest_test"; - private static final String indexDirectory = "index_BandWidthRuntimeTest_test"; + private static final String dbDirectory = "db_BandWidthRuntimeWithCheckTest_test"; + private static final String indexDirectory = "index_BandWidthRuntimeWithCheckTest_test"; private static final String OwnerAddress = "TCWHANtDDdkZCTo2T2peyEq3Eg9c2XB7ut"; private static final String TriggerOwnerAddress = "TCSgeWapPJhCqgWRxXCKb6jJ5AgNWSGjPA"; private static final String TriggerOwnerTwoAddress = "TPMBUANrTwwQAPwShn7ZZjTJz1f3F8jknj"; diff --git a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java index ed268ec882a..d0a3d153d7d 100644 --- a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java +++ b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java @@ -7,6 +7,7 @@ import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -25,6 +26,7 @@ import org.tron.core.services.interfaceOnSolidity.RpcApiServiceOnSolidity; import org.tron.tool.litefullnode.LiteFullNodeTool; +@Ignore @Slf4j public class LiteFullNodeToolTest { From 628678450fddb66f919ffde04e1ed9942b2a6e53 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 9 Feb 2023 18:21:03 +0800 Subject: [PATCH 0575/1197] feat(net): optimize network logs --- .../org/tron/core/net/messagehandler/BlockMsgHandler.java | 6 ++++++ .../main/java/org/tron/core/net/peer/PeerStatusCheck.java | 6 ++++++ .../tron/core/net/service/keepalive/KeepAliveService.java | 1 + 3 files changed, 13 insertions(+) diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java index 115e97db50d..6613ebfc581 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java @@ -104,14 +104,20 @@ private void check(PeerConnection peer, BlockMessage msg) throws P2pException { Item item = new Item(msg.getBlockId(), InventoryType.BLOCK); if (!peer.getSyncBlockRequested().containsKey(msg.getBlockId()) && !peer.getAdvInvRequest() .containsKey(item)) { + logger.error("Receive bad block {} from peer {}, with no request", + msg.getBlockId(), peer.getInetSocketAddress()); throw new P2pException(TypeEnum.BAD_MESSAGE, "no request"); } BlockCapsule blockCapsule = msg.getBlockCapsule(); if (blockCapsule.getInstance().getSerializedSize() > maxBlockSize) { + logger.error("Receive bad block {} from peer {}, block size over limit", + msg.getBlockId(), peer.getInetSocketAddress()); throw new P2pException(TypeEnum.BAD_MESSAGE, "block size over limit"); } long gap = blockCapsule.getTimeStamp() - System.currentTimeMillis(); if (gap >= BLOCK_PRODUCED_INTERVAL) { + logger.error("Receive bad block {} from peer {}, block time error", + msg.getBlockId(), peer.getInetSocketAddress()); throw new P2pException(TypeEnum.BAD_MESSAGE, "block time error"); } } diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java b/framework/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java index 993d9e94781..84cf59b9bd7 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java @@ -53,11 +53,17 @@ public void statusCheck() { if (!isDisconnected) { isDisconnected = peer.getAdvInvRequest().values().stream() .anyMatch(time -> time < now - NetConstants.ADV_TIME_OUT); + if (isDisconnected) { + logger.warn("Peer {} get avd message timeout", peer.getInetAddress()); + } } if (!isDisconnected) { isDisconnected = peer.getSyncBlockRequested().values().stream() .anyMatch(time -> time < now - NetConstants.SYNC_TIME_OUT); + if (isDisconnected) { + logger.warn("Peer {} get sync message timeout", peer.getInetAddress()); + } } if (isDisconnected) { diff --git a/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java b/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java index 49ae692b6f1..07ab20c3954 100644 --- a/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java +++ b/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java @@ -35,6 +35,7 @@ public void init() { long lastSendTime = p.getChannel().getLastSendTime(); if (p.getChannel().waitForPong) { if (now - pingSent > PING_TIMEOUT) { + logger.warn("Peer {} receive pong timeout", p.getInetSocketAddress()); p.disconnect(Protocol.ReasonCode.TIME_OUT); } } else { From e1ef12711f74f1c1aa6fb1e333d836fc99d50591 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 9 Feb 2023 18:55:23 +0800 Subject: [PATCH 0576/1197] feat(net): solve the unit test problem --- .../core/net/messagehandler/BlockMsgHandlerTest.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java index 5b2abfd0705..ff6203ee870 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java @@ -2,6 +2,8 @@ import com.google.common.collect.ImmutableList; import com.google.protobuf.ByteString; +import java.lang.reflect.Field; +import java.net.InetSocketAddress; import java.util.List; import org.junit.After; import org.junit.Assert; @@ -18,6 +20,7 @@ import org.tron.core.net.message.adv.BlockMessage; import org.tron.core.net.peer.Item; import org.tron.core.net.peer.PeerConnection; +import org.tron.p2p.connection.Channel; import org.tron.protos.Protocol.Inventory.InventoryType; import org.tron.protos.Protocol.Transaction; @@ -31,12 +34,18 @@ public class BlockMsgHandlerTest { * init context. */ @Before - public void init() { + public void init() throws Exception { Args.setParam(new String[]{"--output-directory", "output-directory", "--debug"}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); handler = context.getBean(BlockMsgHandler.class); peer = context.getBean(PeerConnection.class); + Channel c1 = new Channel(); + InetSocketAddress a1 = new InetSocketAddress("100.1.1.1", 100); + Field field = c1.getClass().getDeclaredField("inetAddress"); + field.setAccessible(true); + field.set(c1, a1.getAddress()); + peer.setChannel(c1); } @Test From 057f3f0defde05868584202c92ed22e8facac889 Mon Sep 17 00:00:00 2001 From: guoquanwu Date: Wed, 8 Feb 2023 16:25:16 +0800 Subject: [PATCH 0577/1197] feat(event): skip log warning when solidity block number is 0 --- framework/src/main/java/org/tron/core/db/Manager.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index b43387ec4f6..d47b32cbf74 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -2082,7 +2082,8 @@ private void processTransactionTrigger(BlockCapsule newBlock) { List transactionCapsuleList = newBlock.getTransactions(); // need to set eth compatible data from transactionInfoList - if (EventPluginLoader.getInstance().isTransactionLogTriggerEthCompatible()) { + if (EventPluginLoader.getInstance().isTransactionLogTriggerEthCompatible() + && newBlock.getNum() != 0) { TransactionInfoList transactionInfoList = TransactionInfoList.newBuilder().build(); TransactionInfoList.Builder transactionInfoListBuilder = TransactionInfoList.newBuilder(); @@ -2119,7 +2120,8 @@ private void processTransactionTrigger(BlockCapsule newBlock) { cumulativeLogCount += transactionInfo.getLogCount(); } } else { - logger.error("PostBlockTrigger blockNum = {} has no transactions or {}.", newBlock.getNum(), + logger.error("PostBlockTrigger blockNum = {} has no transactions or {}.", + newBlock.getNum(), "the sizes of transactionInfoList and transactionCapsuleList are not equal"); for (TransactionCapsule e : newBlock.getTransactions()) { postTransactionTrigger(e, newBlock); From d513fd203cc72bda22d6eff87e7571ef2a74c68b Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 13 Feb 2023 15:37:18 +0800 Subject: [PATCH 0578/1197] support libp2p v0.2 --- build.gradle | 2 + common/build.gradle | 2 + .../common/parameter/CommonParameter.java | 8 ++ .../src/main/java/org/tron/core/Constant.java | 13 +++ framework/build.gradle | 2 +- .../tron/common/backup/message/Message.java | 3 +- .../src/main/java/org/tron/core/Wallet.java | 9 +- .../java/org/tron/core/config/args/Args.java | 87 +++++++++++++++++++ .../org/tron/core/net/TronNetService.java | 8 +- .../net/message/handshake/HelloMessage.java | 29 +++++-- .../tron/core/net/peer/PeerConnection.java | 2 +- .../org/tron/core/net/peer/PeerManager.java | 2 +- .../service/handshake/HandshakeService.java | 7 +- .../service/keepalive/KeepAliveService.java | 2 +- .../nodepersist/NodePersistService.java | 3 +- .../tron/core/services/NodeInfoService.java | 2 +- .../org/tron/core/services/RpcApiService.java | 7 +- framework/src/main/resources/logback.xml | 2 +- protocol/src/main/protos/core/Discover.proto | 1 + 19 files changed, 165 insertions(+), 26 deletions(-) diff --git a/build.gradle b/build.gradle index 8ff739a1e4c..39313270417 100644 --- a/build.gradle +++ b/build.gradle @@ -17,6 +17,7 @@ subprojects { buildscript { repositories { mavenCentral() + maven { url 'https://jitpack.io/' } maven { url "https://plugins.gradle.org/m2/" } @@ -29,6 +30,7 @@ subprojects { repositories { mavenLocal() + maven { url 'https://jitpack.io/' } mavenCentral() maven { url 'https://repo.spring.io/plugins-release' } } diff --git a/common/build.gradle b/common/build.gradle index fc17f99cd84..99610cc0f20 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,6 +53,8 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' + //compile group: 'io.github.tronprotocol', name: 'libp2p', version: '0.1.2' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.1.6' compile project(":protocol") } diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 571ab968671..876add633c7 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -20,6 +20,7 @@ import org.tron.core.config.args.Overlay; import org.tron.core.config.args.SeedNode; import org.tron.core.config.args.Storage; +import org.tron.p2p.dns.update.PublishConfig; public class CommonParameter { @@ -186,6 +187,13 @@ public class CommonParameter { @Getter @Setter public String p2pNodeId; + @Getter + @Setter + public List dnsTreeUrls; + @Getter + @Setter + public PublishConfig dnsPublishConfig; + //If you are running a solidity node for java tron, this flag is set to true @Getter @Setter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 408782752f2..51e5a553bde 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -103,6 +103,19 @@ public class Constant { public static final String NODE_P2P_PING_INTERVAL = "node.p2p.pingInterval"; public static final String NODE_P2P_VERSION = "node.p2p.version"; + + public static final String NODE_DNS_TREE_URLS = "node.dns.treeUrls"; + public static final String NODE_DNS_PUBLISH = "node.dns.publish"; + public static final String NODE_DNS_DOMAIN = "node.dns.dnsDomain"; + public static final String NODE_DNS_PRIVATE = "node.dns.dnsPrivate"; + public static final String NODE_DNS_KNOWN_URLS = "node.dns.knownUrls"; + public static final String NODE_DNS_SERVER_TYPE = "node.dns.serverType"; + public static final String NODE_DNS_ACCESS_KEY_ID = "node.dns.accessKeyId"; + public static final String NODE_DNS_ACCESS_KEY_SECRET = "node.dns.accessKeySecret"; + public static final String NODE_DNS_ALIYUN_ENDPOINT = "node.dns.aliyunDnsEndpoint"; + public static final String NODE_DNS_AWS_REGION = "node.dns.awsRegion"; + public static final String NODE_DNS_AWS_HOST_ZONE_ID = "node.dns.awsHostZoneId"; + public static final String NODE_RPC_PORT = "node.rpc.port"; public static final String NODE_RPC_SOLIDITY_PORT = "node.rpc.solidityPort"; public static final String NODE_RPC_PBFT_PORT = "node.rpc.PBFTPort"; diff --git a/framework/build.gradle b/framework/build.gradle index 93757755446..676088868be 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -48,7 +48,7 @@ dependencies { compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' - compile group: 'io.github.tronprotocol', name: 'libp2p', version: '0.1.2' + compile group: 'software.amazon.awssdk', name: 'regions', version: '2.18.41' compile group: 'com.typesafe', name: 'config', version: '1.3.2' diff --git a/framework/src/main/java/org/tron/common/backup/message/Message.java b/framework/src/main/java/org/tron/common/backup/message/Message.java index 8f09a452877..cd1a2669427 100644 --- a/framework/src/main/java/org/tron/common/backup/message/Message.java +++ b/framework/src/main/java/org/tron/common/backup/message/Message.java @@ -20,7 +20,8 @@ public Message(UdpMessageTypeEnum type, byte[] data) { public static Node getNode(Endpoint endpoint) { Node node = new Node(endpoint.getNodeId().toByteArray(), - ByteArray.toStr(endpoint.getAddress().toByteArray()), endpoint.getPort()); + ByteArray.toStr(endpoint.getAddress().toByteArray()), + ByteArray.toStr(endpoint.getAddressIpv6().toByteArray()), endpoint.getPort()); return node; } diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index bcefbb9b2f1..197a8a4a904 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2635,10 +2635,11 @@ public NodeList listNodes() { NodeList.Builder nodeListBuilder = NodeList.newBuilder(); TronNetService.getP2pService().getConnectableNodes().forEach(node -> { nodeListBuilder.addNodes(Node.newBuilder().setAddress( - Address.newBuilder() - .setHost(ByteString - .copyFrom(ByteArray.fromString(node.getHost()))) - .setPort(node.getPort()))); + Address.newBuilder() + .setHost(ByteString + .copyFrom(ByteArray.fromString( + node.getPreferInetSocketAddress().getAddress().getHostAddress()))) + .setPort(node.getPort()))); }); return nodeListBuilder.build(); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index f27ff3c2385..d0ca057c7e0 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -76,8 +76,12 @@ import org.tron.core.store.AccountStore; import org.tron.keystore.Credentials; import org.tron.keystore.WalletUtils; +import org.tron.p2p.dns.update.DnsType; +import org.tron.p2p.dns.update.PublishConfig; import org.tron.program.Version; +import software.amazon.awssdk.regions.Region; + @Slf4j(topic = "app") @NoArgsConstructor @Component @@ -142,6 +146,8 @@ public static void clearParam() { PARAMETER.nodeDiscoveryPingTimeout = 15000; PARAMETER.nodeP2pPingInterval = 0L; PARAMETER.nodeP2pVersion = 0; + PARAMETER.dnsTreeUrls = new ArrayList<>(); + PARAMETER.dnsPublishConfig = null; PARAMETER.rpcPort = 0; PARAMETER.rpcOnSolidityPort = 0; PARAMETER.rpcOnPBFTPort = 0; @@ -637,6 +643,11 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.NODE_P2P_VERSION) ? config.getInt(Constant.NODE_P2P_VERSION) : 0; + PARAMETER.dnsTreeUrls = config.hasPath(Constant.NODE_DNS_TREE_URLS) ? config.getStringList( + Constant.NODE_DNS_TREE_URLS) : new ArrayList<>(); + + PARAMETER.dnsPublishConfig = loadDnsPublishConfig(config); + PARAMETER.rpcPort = config.hasPath(Constant.NODE_RPC_PORT) ? config.getInt(Constant.NODE_RPC_PORT) : 50051; @@ -1274,6 +1285,82 @@ private static EventPluginConfig getEventPluginConfig( return eventPluginConfig; } + public static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Config config) { + PublishConfig publishConfig = new PublishConfig(); + if (config.hasPath(Constant.NODE_DNS_PUBLISH)) { + publishConfig.setDnsPublishEnable(config.getBoolean(Constant.NODE_DNS_PUBLISH)); + } + + if (publishConfig.isDnsPublishEnable()) { + if (config.hasPath(Constant.NODE_DNS_DOMAIN)) { + publishConfig.setDnsDomain(config.getString(Constant.NODE_DNS_DOMAIN)); + } else { + logger.error("Check {}, must not be null", Constant.NODE_DNS_DOMAIN); + return null; + } + + if (config.hasPath(Constant.NODE_DNS_PRIVATE)) { + publishConfig.setDnsPrivate(config.getString(Constant.NODE_DNS_PRIVATE)); + } else { + logger.error("Check {}, must not be null", Constant.NODE_DNS_PRIVATE); + return null; + } + + if (config.hasPath(Constant.NODE_DNS_KNOWN_URLS)) { + publishConfig.setKnownTreeUrls(config.getStringList(Constant.NODE_DNS_KNOWN_URLS)); + } + + if (config.hasPath(Constant.NODE_DNS_SERVER_TYPE)) { + String serverType = config.getString(Constant.NODE_DNS_SERVER_TYPE); + if (!serverType.equalsIgnoreCase("aws") && !serverType.equalsIgnoreCase("aliyun")) { + logger.error("Check {}, must be aws or aliyun", Constant.NODE_DNS_SERVER_TYPE); + return null; + } + if (serverType.equalsIgnoreCase("aws")) { + publishConfig.setDnsType(DnsType.AwsRoute53); + } else { + publishConfig.setDnsType(DnsType.AliYun); + } + } else { + logger.error("Check {}, must not be null", Constant.NODE_DNS_SERVER_TYPE); + return null; + } + + if (config.hasPath(Constant.NODE_DNS_ACCESS_KEY_ID)) { + publishConfig.setAccessKeyId(config.getString(Constant.NODE_DNS_ACCESS_KEY_ID)); + } else { + logger.error("Check {}, must not be null", Constant.NODE_DNS_ACCESS_KEY_ID); + return null; + } + if (config.hasPath(Constant.NODE_DNS_ACCESS_KEY_SECRET)) { + publishConfig.setAccessKeySecret(config.getString(Constant.NODE_DNS_ACCESS_KEY_SECRET)); + } else { + logger.error("Check {}, must not be null", Constant.NODE_DNS_ACCESS_KEY_SECRET); + return null; + } + + if (publishConfig.getDnsType() == DnsType.AwsRoute53) { + if (!config.hasPath(Constant.NODE_DNS_AWS_REGION)) { + logger.error("Check {}, must not be null", Constant.NODE_DNS_AWS_REGION); + return null; + } else { + publishConfig.setAwsRegion(Region.of(config.getString(Constant.NODE_DNS_AWS_REGION))); + } + if (config.hasPath(Constant.NODE_DNS_AWS_HOST_ZONE_ID)) { + publishConfig.setAwsHostZoneId(config.getString(Constant.NODE_DNS_AWS_HOST_ZONE_ID)); + } + } else { + if (!config.hasPath(Constant.NODE_DNS_ALIYUN_ENDPOINT)) { + logger.error("Check {}, must not be null", Constant.NODE_DNS_ALIYUN_ENDPOINT); + return null; + } else { + publishConfig.setAliDnsEndpoint(config.getString(Constant.NODE_DNS_ALIYUN_ENDPOINT)); + } + } + } + return publishConfig; + } + private static TriggerConfig createTriggerConfig(ConfigObject triggerObject) { if (Objects.isNull(triggerObject)) { return null; diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index fc4a3e8eee2..7b33736f5fa 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -4,6 +4,7 @@ import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -139,6 +140,7 @@ private P2pConfig getConfig() { config.setActiveNodes(parameter.getActiveNodes()); config.setTrustNodes(parameter.getPassiveNodes()); config.getActiveNodes().forEach(n -> config.getTrustNodes().add(n.getAddress())); + parameter.getFastForwardNodes().forEach(f -> config.getTrustNodes().add(f.getAddress())); int maxConnections = parameter.getMaxConnections(); int minConnections = parameter.getMinConnections(); int minActiveConnections = parameter.getMinActiveConnections(); @@ -154,12 +156,16 @@ private P2pConfig getConfig() { config.setMaxConnectionsWithSameIp(parameter.getMaxConnectionsWithSameIp()); config.setPort(parameter.getNodeListenPort()); - config.setVersion(parameter.getNodeP2pVersion()); + config.setNetworkId(parameter.getNodeP2pVersion()); config.setDisconnectionPolicyEnable(parameter.isOpenFullTcpDisconnect()); config.setDiscoverEnable(parameter.isNodeDiscoveryEnable()); if (StringUtil.isNullOrEmpty(config.getIp())) { config.setIp(parameter.getNodeExternalIp()); } + config.setTreeUrls(parameter.getDnsTreeUrls()); + if (Objects.nonNull(parameter.getDnsPublishConfig())) { + config.setPublishConfig(parameter.getDnsPublishConfig()); + } return config; } } \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java b/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java index d4ed7282386..dfef5d6b9f6 100755 --- a/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java @@ -2,6 +2,7 @@ import com.google.protobuf.ByteString; import lombok.Getter; +import org.apache.commons.lang3.StringUtils; import org.tron.common.utils.ByteArray; import org.tron.common.utils.StringUtil; import org.tron.core.ChainBaseManager; @@ -33,11 +34,7 @@ public HelloMessage(byte[] data) throws Exception { public HelloMessage(Node from, long timestamp, ChainBaseManager chainBaseManager) { - Endpoint fromEndpoint = Endpoint.newBuilder() - .setNodeId(ByteString.copyFrom(from.getId())) - .setPort(from.getPort()) - .setAddress(ByteString.copyFrom(ByteArray.fromString(from.getHost()))) - .build(); + Endpoint fromEndpoint = getEndpointFromNode(from); BlockCapsule.BlockId gid = chainBaseManager.getGenesisBlockId(); Protocol.HelloMessage.BlockId gBlockId = Protocol.HelloMessage.BlockId.newBuilder() @@ -104,7 +101,8 @@ public long getTimestamp() { public Node getFrom() { Endpoint from = this.helloMessage.getFrom(); return new Node(from.getNodeId().toByteArray(), - ByteArray.toStr(from.getAddress().toByteArray()), from.getPort()); + ByteArray.toStr(from.getAddress().toByteArray()), + ByteArray.toStr(from.getAddressIpv6().toByteArray()), from.getPort()); } public BlockCapsule.BlockId getGenesisBlockId() { @@ -132,7 +130,7 @@ public String toString() { StringBuilder builder = new StringBuilder(); builder.append(super.toString()) - .append("from: ").append(getFrom().getInetSocketAddress()).append("\n") + .append("from: ").append(getFrom().getPreferInetSocketAddress()).append("\n") .append("timestamp: ").append(getTimestamp()).append("\n") .append("headBlockId: ").append(getHeadBlockId().getString()).append("\n") .append("nodeType: ").append(helloMessage.getNodeType()).append("\n") @@ -175,4 +173,21 @@ public boolean valid() { return true; } + + public static Endpoint getEndpointFromNode(Node node) { + Endpoint.Builder builder = Endpoint.newBuilder() + .setPort(node.getPort()); + if (node.getId() != null) { + builder.setNodeId(ByteString.copyFrom(node.getId())); + } + if (StringUtils.isNotEmpty(node.getHostV4())) { + builder.setAddress( + ByteString.copyFrom(org.tron.p2p.utils.ByteArray.fromString(node.getHostV4()))); + } + if (StringUtils.isNotEmpty(node.getHostV6())) { + builder.setAddressIpv6( + ByteString.copyFrom(org.tron.p2p.utils.ByteArray.fromString(node.getHostV6()))); + } + return builder.build(); + } } diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index 5626c072864..d15725ebf3f 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -217,7 +217,7 @@ public String log() { + "blockInProcess:%d\n", channel.getInetSocketAddress(), (now - channel.getStartTime()) / Constant.ONE_THOUSAND, - channel.getLatency(), + channel.getAvgLatency(), fastForwardBlock != null ? fastForwardBlock.getNum() : blockBothHave.getNum(), isNeedSyncFromPeer(), isNeedSyncFromUs(), diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java index 8a402438c86..6817720dff5 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java @@ -89,7 +89,7 @@ private static void remove(PeerConnection peerConnection) { } public static synchronized void sortPeers() { - peers.sort(Comparator.comparingDouble(c -> c.getChannel().getLatency())); + peers.sort(Comparator.comparingDouble(c -> c.getChannel().getAvgLatency())); } public static PeerConnection getPeerConnection(Channel channel) { diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java index 7b19c9dd3d5..6c9e53c3a98 100644 --- a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -100,7 +100,7 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { peer.setHelloMessageReceive(msg); - peer.getChannel().updateLatency( + peer.getChannel().updateAvgLatency( System.currentTimeMillis() - peer.getChannel().getStartTime()); PeerManager.sortPeers(); peer.onConnect(); @@ -108,8 +108,9 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { private void sendHelloMessage(PeerConnection peer, long time) { Node node = new Node(TronNetService.getP2pConfig().getNodeID(), - TronNetService.getP2pConfig().getIp(), - TronNetService.getP2pConfig().getPort()); + TronNetService.getP2pConfig().getIp(), + TronNetService.getP2pConfig().getIpv6(), + TronNetService.getP2pConfig().getPort()); HelloMessage message = new HelloMessage(node, time, ChainBaseManager.getChainBaseManager()); relayService.fillHelloMessage(message, peer.getChannel()); peer.sendMessage(message); diff --git a/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java b/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java index 49ae692b6f1..50b7be9dcbf 100644 --- a/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java +++ b/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java @@ -59,7 +59,7 @@ public void processMessage(PeerConnection peer, TronMessage message) { if (message.getType().equals(MessageTypes.P2P_PING)) { peer.sendMessage(new PongMessage()); } else { - peer.getChannel().updateLatency(System.currentTimeMillis() - peer.getChannel().pingSent); + peer.getChannel().updateAvgLatency(System.currentTimeMillis() - peer.getChannel().pingSent); peer.getChannel().waitForPong = false; } } diff --git a/framework/src/main/java/org/tron/core/net/service/nodepersist/NodePersistService.java b/framework/src/main/java/org/tron/core/net/service/nodepersist/NodePersistService.java index 02ff1e7a1aa..8d07df0d7a4 100644 --- a/framework/src/main/java/org/tron/core/net/service/nodepersist/NodePersistService.java +++ b/framework/src/main/java/org/tron/core/net/service/nodepersist/NodePersistService.java @@ -70,7 +70,8 @@ private void dbWrite() { List tableNodes = TronNetService.getP2pService().getTableNodes(); tableNodes.sort(Comparator.comparingLong(value -> -value.getUpdateTime())); for (Node n : tableNodes) { - batch.add(new DBNode(n.getHost(), n.getPort())); + batch.add( + new DBNode(n.getPreferInetSocketAddress().getAddress().getHostAddress(), n.getPort())); } if (batch.size() > MAX_NODES_WRITE_TO_DB) { diff --git a/framework/src/main/java/org/tron/core/services/NodeInfoService.java b/framework/src/main/java/org/tron/core/services/NodeInfoService.java index cd73a010258..b08f0107760 100644 --- a/framework/src/main/java/org/tron/core/services/NodeInfoService.java +++ b/framework/src/main/java/org/tron/core/services/NodeInfoService.java @@ -140,7 +140,7 @@ private void setConnectInfo(NodeInfo nodeInfo) { PeerInfo peerInfo = new PeerInfo(); peerInfo.setHeadBlockWeBothHave(peerConnection.getBlockBothHave().getString()); peerInfo.setActive(peerConnection.getChannel().isActive()); - peerInfo.setAvgLatency(peerConnection.getChannel().getLatency()); + peerInfo.setAvgLatency(peerConnection.getChannel().getAvgLatency()); peerInfo.setBlockInPorcSize(peerConnection.getSyncBlockInProcess().size()); peerInfo.setConnectTime(channel.getStartTime()); peerInfo.setDisconnectTimes(nodeStatistics.getDisconnectTimes()); diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index a6e1c5181ad..e16f5ff9565 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -1739,9 +1739,10 @@ public void listNodes(EmptyMessage request, StreamObserver responseObs NodeList.Builder nodeListBuilder = NodeList.newBuilder(); TronNetService.getP2pService().getConnectableNodes().forEach(node -> { nodeListBuilder.addNodes(Node.newBuilder().setAddress( - Address.newBuilder() - .setHost(ByteString.copyFrom(ByteArray.fromString(node.getHost()))) - .setPort(node.getPort()))); + Address.newBuilder() + .setHost(ByteString.copyFrom(ByteArray.fromString( + node.getPreferInetSocketAddress().getAddress().getHostAddress()))) + .setPort(node.getPort()))); }); responseObserver.onNext(nodeListBuilder.build()); responseObserver.onCompleted(); diff --git a/framework/src/main/resources/logback.xml b/framework/src/main/resources/logback.xml index 136d6342f9f..c97c9f8d3b4 100644 --- a/framework/src/main/resources/logback.xml +++ b/framework/src/main/resources/logback.xml @@ -66,7 +66,7 @@ - + diff --git a/protocol/src/main/protos/core/Discover.proto b/protocol/src/main/protos/core/Discover.proto index 4cc0d83b02a..fadb819e92d 100644 --- a/protocol/src/main/protos/core/Discover.proto +++ b/protocol/src/main/protos/core/Discover.proto @@ -11,6 +11,7 @@ message Endpoint { bytes address = 1; int32 port = 2; bytes nodeId = 3; + bytes addressIpv6 = 4; } message PingMessage { From e693d8ab5f30d24b11d9c606d99ac085814766b0 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 8 Feb 2023 16:26:46 +0800 Subject: [PATCH 0579/1197] feat(log): separate database logs --- .../common/log/layout/MultiLayoutPattern.java | 106 ------------------ framework/src/main/resources/logback.xml | 35 ++++-- 2 files changed, 24 insertions(+), 117 deletions(-) delete mode 100644 common/src/main/java/org/tron/common/log/layout/MultiLayoutPattern.java diff --git a/common/src/main/java/org/tron/common/log/layout/MultiLayoutPattern.java b/common/src/main/java/org/tron/common/log/layout/MultiLayoutPattern.java deleted file mode 100644 index 9fde78c1a7b..00000000000 --- a/common/src/main/java/org/tron/common/log/layout/MultiLayoutPattern.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.tron.common.log.layout; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.encoder.PatternLayoutEncoder; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.Context; -import ch.qos.logback.core.Layout; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class MultiLayoutPattern extends PatternLayoutEncoder { - private List rules = new ArrayList<>(); - private Map> layoutMap = new HashMap<>(); - - public void addRule(Rule rule) { - this.rules.add(rule); - rule.start(context); - } - - public byte[] encode(ILoggingEvent event) { - Layout layout = getLayout(event.getLoggerName()); - String txt = layout.doLayout(event); - return convertToBytes(txt); - } - - private byte[] convertToBytes(String s) { - Charset charset = getCharset(); - if (charset == null) { - return s.getBytes(); - } else { - return s.getBytes(charset); - } - } - - private Layout getLayout(final String name) { - if (name == null) { - throw new IllegalArgumentException("name cannot be null"); - } - if (Logger.ROOT_LOGGER_NAME.equalsIgnoreCase(name)) { - return this.getLayout(); - } - if (layoutMap.containsKey(name)) { - return layoutMap.get(name); - } - Layout layout = getLayout(); - for (Rule rule : rules) { - if (rule.logger.equals(name)) { - layout = rule.getPatternLayoutEncoder().getLayout(); - break; - } - } - layoutMap.put(name, layout); - return layout; - } - - @Override - public void start() { - super.start(); - } - - public static class Rule { - private String logger; - private String pattern; - private PatternLayoutEncoder patternLayoutEncoder; - private boolean outputPatternAsHeader = false; - - public String getLogger() { - return logger; - } - - public void setLogger(String logger) { - this.logger = logger; - } - - public String getPattern() { - return pattern; - } - - public void setPattern(String pattern) { - this.pattern = pattern; - } - - public boolean isOutputPatternAsHeader() { - return outputPatternAsHeader; - } - - public void setOutputPatternAsHeader(boolean outputPatternAsHeader) { - this.outputPatternAsHeader = outputPatternAsHeader; - } - - public PatternLayoutEncoder getPatternLayoutEncoder() { - return patternLayoutEncoder; - } - - public void start(Context context) { - patternLayoutEncoder = new PatternLayoutEncoder(); - patternLayoutEncoder.setPattern(pattern); - patternLayoutEncoder.setContext(context); - patternLayoutEncoder.setOutputPatternAsHeader(outputPatternAsHeader); - patternLayoutEncoder.start(); - } - } -} \ No newline at end of file diff --git a/framework/src/main/resources/logback.xml b/framework/src/main/resources/logback.xml index 136d6342f9f..39c7f463172 100644 --- a/framework/src/main/resources/logback.xml +++ b/framework/src/main/resources/logback.xml @@ -26,16 +26,25 @@ 7 50GB - + %d{HH:mm:ss.SSS} %-5level [%t] [%c{1}]\(%F:%L\) %m%n - - LEVELDB - %d{HH:mm:ss.SSS} %m%n - - - ROCKSDB - %d{HH:mm:ss.SSS} %m%n - + + + TRACE + + + + + ./logs/db/db.log + + ./logs/db/db-%d{yyyy-MM-dd}.%i.log.gz + 500MB + 7 + 50GB + + + %d{HH:mm:ss.SSS} %m%n + UTF-8 TRACE @@ -77,8 +86,12 @@ - - + + + + + + From e236398df8b6be9ebae459e6cdd7e5758fdbf6da Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 13 Feb 2023 18:28:00 +0800 Subject: [PATCH 0580/1197] remove ping in KeepAliveService because it exist in libp2p --- .../service/keepalive/KeepAliveService.java | 41 ------------------- 1 file changed, 41 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java b/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java index 50b7be9dcbf..0387dd88c8e 100644 --- a/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java +++ b/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java @@ -1,66 +1,25 @@ package org.tron.core.net.service.keepalive; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import org.tron.core.net.TronNetService; import org.tron.core.net.message.MessageTypes; import org.tron.core.net.message.TronMessage; -import org.tron.core.net.message.keepalive.PingMessage; import org.tron.core.net.message.keepalive.PongMessage; import org.tron.core.net.peer.PeerConnection; -import org.tron.protos.Protocol; @Slf4j(topic = "net") @Component public class KeepAliveService { - private long KEEP_ALIVE_TIMEOUT = 10_000; - - private long PING_TIMEOUT = 20_000; - - private long PING_PERIOD = 60_000; - - private final ScheduledExecutorService executor = - Executors.newSingleThreadScheduledExecutor(r -> new Thread(r, "KeepAlive")); - public void init() { - executor.scheduleWithFixedDelay(() -> { - try { - long now = System.currentTimeMillis(); - TronNetService.getPeers().forEach(p -> { - long pingSent = p.getChannel().pingSent; - long lastSendTime = p.getChannel().getLastSendTime(); - if (p.getChannel().waitForPong) { - if (now - pingSent > PING_TIMEOUT) { - p.disconnect(Protocol.ReasonCode.TIME_OUT); - } - } else { - if (now - lastSendTime > KEEP_ALIVE_TIMEOUT || now - pingSent > PING_PERIOD) { - p.sendMessage(new PingMessage()); - p.getChannel().waitForPong = true; - p.getChannel().pingSent = now; - } - } - }); - } catch (Throwable t) { - logger.error("Exception in keep alive task.", t); - } - }, 2, 2, TimeUnit.SECONDS); } public void close() { - executor.shutdown(); } public void processMessage(PeerConnection peer, TronMessage message) { if (message.getType().equals(MessageTypes.P2P_PING)) { peer.sendMessage(new PongMessage()); - } else { - peer.getChannel().updateAvgLatency(System.currentTimeMillis() - peer.getChannel().pingSent); - peer.getChannel().waitForPong = false; } } } From ed38d78d2b6897a90f2c1fc906fc227853b5cc10 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 8 Feb 2023 18:11:00 +0800 Subject: [PATCH 0581/1197] feat(db): optimize the judgement of node type --- .../java/org/tron/core/ChainBaseManager.java | 32 +++++++++++ .../org/tron/core/db/BlockIndexStore.java | 22 +++++++- .../java/org/tron/core/db/CommonStore.java | 32 ----------- .../common/parameter/CommonParameter.java | 6 +- .../java/org/tron/core/config/args/Args.java | 16 ------ .../main/java/org/tron/core/db/Manager.java | 7 ++- .../net/message/handshake/HelloMessage.java | 16 +----- .../filter/LiteFnQueryGrpcInterceptor.java | 12 ++-- .../filter/LiteFnQueryHttpFilter.java | 11 ++-- .../tool/litefullnode/LiteFullNodeTool.java | 16 ------ .../org/tron/core/db/CommonStoreTest.java | 56 ------------------- .../LiteFnQueryGrpcInterceptorTest.java | 9 ++- .../filter/LiteFnQueryHttpFilterTest.java | 12 ++-- .../main/java/org/tron/plugins/DbLite.java | 19 ------- 14 files changed, 88 insertions(+), 178 deletions(-) delete mode 100644 framework/src/test/java/org/tron/core/db/CommonStoreTest.java diff --git a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java index d824d36734f..c9ced891ee6 100644 --- a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java +++ b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java @@ -4,6 +4,7 @@ import com.google.protobuf.ByteString; import java.util.List; +import javax.annotation.PostConstruct; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @@ -236,6 +237,14 @@ public class ChainBaseManager { @Autowired private DbStatService dbStatService; + @Getter + @Setter + private NodeType nodeType; + + @Getter + @Setter + private long lowestBlockNum = -1; // except num = 0. + public void closeOneStore(ITronChainBase database) { logger.info("******** Begin to close {}. ********", database.getName()); try { @@ -414,5 +423,28 @@ public static synchronized void init(ChainBaseManager manager) { AssetUtil.setAccountAssetStore(manager.getAccountAssetStore()); AssetUtil.setDynamicPropertiesStore(manager.getDynamicPropertiesStore()); } + + @PostConstruct + private void init() { + this.lowestBlockNum = this.blockIndexStore.getLimitNumber(1, 1).stream() + .map(BlockId::getNum).findFirst().orElse(0L); + this.nodeType = getLowestBlockNum() > 1 ? NodeType.LITE : NodeType.FULL; + } + + public boolean isLiteNode() { + return getNodeType() == NodeType.LITE; + } + + public enum NodeType { + FULL(0), + LITE(1); + + @Getter + private final int type; + + NodeType(int type) { + this.type = type; + } + } } diff --git a/chainbase/src/main/java/org/tron/core/db/BlockIndexStore.java b/chainbase/src/main/java/org/tron/core/db/BlockIndexStore.java index 50402002f88..5722d3506af 100644 --- a/chainbase/src/main/java/org/tron/core/db/BlockIndexStore.java +++ b/chainbase/src/main/java/org/tron/core/db/BlockIndexStore.java @@ -1,6 +1,10 @@ package org.tron.core.db; -import java.util.Arrays; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Set; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -12,6 +16,7 @@ import org.tron.core.exception.ItemNotFoundException; @Component +@Slf4j(topic = "DB") public class BlockIndexStore extends TronStoreWithRevoking { @@ -44,4 +49,17 @@ public BytesCapsule get(byte[] key) } return new BytesCapsule(value); } -} \ No newline at end of file + + public List getLimitNumber(long startNumber, long limit) { + return pack(revokingDB.getValuesNext(ByteArray.fromLong(startNumber), limit)); + } + + private List pack(Set values) { + List blocks = new ArrayList<>(); + for (byte[] bytes : values) { + blocks.add(new BlockId(Sha256Hash.wrap(bytes))); + } + blocks.sort(Comparator.comparing(BlockId::getNum)); + return blocks; + } +} diff --git a/chainbase/src/main/java/org/tron/core/db/CommonStore.java b/chainbase/src/main/java/org/tron/core/db/CommonStore.java index a22406f5f90..acc137bdb2a 100644 --- a/chainbase/src/main/java/org/tron/core/db/CommonStore.java +++ b/chainbase/src/main/java/org/tron/core/db/CommonStore.java @@ -3,16 +3,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; -import org.tron.common.utils.ByteArray; -import org.tron.core.Constant; import org.tron.core.capsule.BytesCapsule; @Component public class CommonStore extends TronDatabase { - private static final byte[] DB_KEY_LOWEST_BLOCK_NUM = "lowest_block_num".getBytes(); - private static final byte[] DB_KEY_NODE_TYPE = "node_type".getBytes(); - @Autowired public CommonStore(ApplicationContext ctx) { super("common"); @@ -37,31 +32,4 @@ public BytesCapsule get(byte[] key) { public boolean has(byte[] key) { return dbSource.getData(key) != null; } - - public int getNodeType() { - int nodeType = 0; - byte[] bytes = get(DB_KEY_NODE_TYPE).getData(); - if (bytes != null) { - nodeType = ByteArray.toInt(bytes); - } - return nodeType; - } - - public void setNodeType(int nodeType) { - put(DB_KEY_NODE_TYPE, new BytesCapsule(ByteArray.fromInt(nodeType))); - } - - public long getLowestBlockNum() { - long lowestBlockNum = 0; - byte[] bytes = get(DB_KEY_LOWEST_BLOCK_NUM).getData(); - if (bytes != null) { - lowestBlockNum = ByteArray.toLong(bytes); - } - return lowestBlockNum; - } - - public void setLowestBlockNum(long lowestBlockNum) { - put(DB_KEY_LOWEST_BLOCK_NUM, new BytesCapsule(ByteArray.fromLong(lowestBlockNum))); - } - } diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 571ab968671..ab04ca3e7a4 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -8,6 +8,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; + +import com.google.common.annotations.VisibleForTesting; import lombok.Getter; import lombok.Setter; import org.quartz.CronExpression; @@ -526,10 +528,6 @@ public class CommonParameter { @Setter public boolean openHistoryQueryWhenLiteFN = false; - @Getter - @Setter - public boolean isLiteFullNode = false; - @Getter @Setter @Parameter(names = {"--history-balance-lookup"}) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index f27ff3c2385..905b2c6cf9e 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1006,9 +1006,6 @@ public static void setParam(final String[] args, final String confFileName) { .getBoolean(Constant.METRICS_PROMETHEUS_ENABLE); PARAMETER.metricsPrometheusPort = config.hasPath(Constant.METRICS_PROMETHEUS_PORT) ? config .getInt(Constant.METRICS_PROMETHEUS_PORT) : 9527; - - // lite fullnode params - PARAMETER.setLiteFullNode(checkIsLiteFullNode()); PARAMETER.setOpenHistoryQueryWhenLiteFN( config.hasPath(Constant.NODE_OPEN_HISTORY_QUERY_WHEN_LITEFN) && config.getBoolean(Constant.NODE_OPEN_HISTORY_QUERY_WHEN_LITEFN)); @@ -1506,19 +1503,6 @@ public static void setFullNodeAllowShieldedTransaction(boolean fullNodeAllowShie PARAMETER.fullNodeAllowShieldedTransactionArgs = fullNodeAllowShieldedTransaction; } - /** - * set isLiteFullNode=true when this node is a lite fullnode. - */ - public static boolean checkIsLiteFullNode() { - String infoFile = Paths.get(PARAMETER.outputDirectory, - PARAMETER.storage.getDbDirectory(), Constant.INFO_FILE_NAME).toString(); - if (FileUtil.isExists(infoFile)) { - String value = PropUtil.readProperty(infoFile, Constant.SPLIT_BLOCK_NUM); - return !"".equals(value) && Long.parseLong(value) > 1; - } - return false; - } - private static void witnessAddressCheck(Config config) { if (config.hasPath(Constant.LOCAL_WITNESS_ACCOUNT_ADDRESS)) { byte[] bytes = Commons diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index b43387ec4f6..6ce1e80661c 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -511,8 +511,11 @@ public void init() { long headNum = chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber(); logger.info("Current headNum is: {}.", headNum); - int nodeType = chainBaseManager.getCommonStore().getNodeType(); - logger.info("Node type is: {}.", Constant.NODE_TYPE_LIGHT_NODE == nodeType ? "lite" : "full"); + boolean isLite = chainBaseManager.isLiteNode(); + logger.info("Node type is: {}.", isLite ? "lite" : "full"); + if (isLite) { + logger.info("Lite node lowestNum: {}", chainBaseManager.getLowestBlockNum()); + } revokingStore.enable(); validateSignService = Executors .newFixedThreadPool(Args.getInstance().getValidateSignThreadNum()); diff --git a/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java b/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java index d4ed7282386..0c06c332bd0 100755 --- a/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java @@ -5,10 +5,8 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.StringUtil; import org.tron.core.ChainBaseManager; -import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; import org.tron.core.config.args.Args; -import org.tron.core.db.CommonStore; import org.tron.core.net.message.MessageTypes; import org.tron.core.net.message.TronMessage; import org.tron.p2p.discover.Node; @@ -56,24 +54,16 @@ public HelloMessage(Node from, long timestamp, ChainBaseManager chainBaseManager .setHash(hid.getByteString()) .setNumber(hid.getNum()) .build(); - - CommonStore commonStore = chainBaseManager.getCommonStore(); - long lowestBlockNum = 0; - int nodeType = commonStore.getNodeType(); - if (nodeType == Constant.NODE_TYPE_LIGHT_NODE) { - lowestBlockNum = commonStore.getLowestBlockNum(); - } - Builder builder = Protocol.HelloMessage.newBuilder(); - builder.setFrom(fromEndpoint); builder.setVersion(Args.getInstance().getNodeP2pVersion()); builder.setTimestamp(timestamp); builder.setGenesisBlockId(gBlockId); builder.setSolidBlockId(sBlockId); builder.setHeadBlockId(hBlockId); - builder.setNodeType(nodeType); - builder.setLowestBlockNum(lowestBlockNum); + builder.setNodeType(chainBaseManager.getNodeType().getType()); + builder.setLowestBlockNum(chainBaseManager.isLiteNode() + ? chainBaseManager.getLowestBlockNum() : 0); this.helloMessage = builder.build(); this.type = MessageTypes.P2P_HELLO.asByte(); diff --git a/framework/src/main/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptor.java b/framework/src/main/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptor.java index cd5645f32c2..82819d163f3 100644 --- a/framework/src/main/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptor.java +++ b/framework/src/main/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptor.java @@ -8,12 +8,16 @@ import io.grpc.ServerInterceptor; import io.grpc.Status; import java.util.Set; + +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.common.parameter.CommonParameter; +import org.tron.core.ChainBaseManager; @Component public class LiteFnQueryGrpcInterceptor implements ServerInterceptor { - + @Autowired + private ChainBaseManager chainBaseManager; private static final Set filterMethods = Sets.newHashSet(); // for test @@ -75,13 +79,9 @@ public static Set getFilterMethods() { @Override public ServerCall.Listener interceptCall(ServerCall call, Metadata headers, ServerCallHandler next) { - boolean shouldBeFiltered = false; - if (CommonParameter.getInstance().isLiteFullNode + if (chainBaseManager.isLiteNode() && !CommonParameter.getInstance().openHistoryQueryWhenLiteFN && filterMethods.contains(call.getMethodDescriptor().getFullMethodName())) { - shouldBeFiltered = true; - } - if (shouldBeFiltered) { call.close(Status.UNAVAILABLE .withDescription("this API is closed because this node is a lite fullnode"), headers); return new ServerCall.Listener() {}; diff --git a/framework/src/main/java/org/tron/core/services/filter/LiteFnQueryHttpFilter.java b/framework/src/main/java/org/tron/core/services/filter/LiteFnQueryHttpFilter.java index b7afdbb4258..a8ab947066c 100644 --- a/framework/src/main/java/org/tron/core/services/filter/LiteFnQueryHttpFilter.java +++ b/framework/src/main/java/org/tron/core/services/filter/LiteFnQueryHttpFilter.java @@ -11,13 +11,18 @@ import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.common.parameter.CommonParameter; +import org.tron.core.ChainBaseManager; @Component @Slf4j(topic = "API") public class LiteFnQueryHttpFilter implements Filter { + @Autowired + private ChainBaseManager chainBaseManager; + private static Set filterPaths = Sets.newHashSet(); // for test @@ -106,13 +111,9 @@ public void init(FilterConfig filterConfig) throws ServletException { public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { String requestPath = ((HttpServletRequest) servletRequest).getRequestURI(); - boolean shouldBeFiltered = false; - if (CommonParameter.getInstance().isLiteFullNode + if (chainBaseManager.isLiteNode() && !CommonParameter.getInstance().openHistoryQueryWhenLiteFN && filterPaths.contains(requestPath)) { - shouldBeFiltered = true; - } - if (shouldBeFiltered) { servletResponse.setContentType("application/json; charset=utf-8"); servletResponse.getWriter().write("this API is closed because this node is a lite fullnode"); } else { diff --git a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java index bc72388e156..f2535c7caa5 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java @@ -41,9 +41,6 @@ @Slf4j(topic = "tool") public class LiteFullNodeTool { - private static final byte[] DB_KEY_LOWEST_BLOCK_NUM = "lowest_block_num".getBytes(); - private static final byte[] DB_KEY_NODE_TYPE = "node_type".getBytes(); - private static final long START_TIME = System.currentTimeMillis() / 1000; private static long RECENT_BLKS = 65536; @@ -57,7 +54,6 @@ public class LiteFullNodeTool { 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 COMMON_DB_NAME = "common"; 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"; @@ -328,10 +324,6 @@ private void fillSnapshotBlockAndTransDb(String sourceDir, String snapshotDir) throw new RuntimeException(e.getMessage()); } } - - DBInterface destCommonDb = DbTool.getDB(snapshotDir, COMMON_DB_NAME); - destCommonDb.put(DB_KEY_NODE_TYPE, ByteArray.fromInt(Constant.NODE_TYPE_LIGHT_NODE)); - destCommonDb.put(DB_KEY_LOWEST_BLOCK_NUM, ByteArray.fromLong(startIndex)); // 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); } @@ -487,14 +479,6 @@ private static boolean isEmptyBytes(byte[] b) { private void deleteSnapshotFlag(String databaseDir) throws IOException, RocksDBException { logger.info("Delete the info file from {}.", databaseDir); Files.delete(Paths.get(databaseDir, INFO_FILE_NAME)); - if (!isLite(databaseDir)) { - DBInterface destCommonDb = DbTool.getDB(databaseDir, COMMON_DB_NAME); - destCommonDb.delete(DB_KEY_NODE_TYPE); - destCommonDb.delete(DB_KEY_LOWEST_BLOCK_NUM); - logger.info("Deleted {} and {} from {} to identify this node is a real fullnode.", - "node_type", "lowest_block_num", COMMON_DB_NAME); - } - } private void hasEnoughBlock(String sourceDir) throws RocksDBException, IOException { diff --git a/framework/src/test/java/org/tron/core/db/CommonStoreTest.java b/framework/src/test/java/org/tron/core/db/CommonStoreTest.java deleted file mode 100644 index 9304be0665e..00000000000 --- a/framework/src/test/java/org/tron/core/db/CommonStoreTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.tron.core.db; - -import java.io.File; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; -import org.tron.core.Constant; -import org.tron.core.config.DefaultConfig; -import org.tron.core.config.args.Args; - -public class CommonStoreTest { - private static String dbPath = "output_CommonStore_test"; - private static String dbDirectory = "db_CommonStore_test"; - private static String indexDirectory = "index_CommonStore_test"; - private static TronApplicationContext context; - private static CommonStore commonStore; - - static { - Args.setParam(new String[] { - "--output-directory", dbPath, - "--storage-db-directory", dbDirectory, - "--storage-index-directory", indexDirectory}, - Constant.TEST_CONF - ); - context = new TronApplicationContext(DefaultConfig.class); - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } - - @BeforeClass - public static void init() { - commonStore = context.getBean(CommonStore.class); - } - - @Test - public void nodeTypeTest() { - Assert.assertEquals(0, commonStore.getNodeType()); - commonStore.setNodeType(1); - Assert.assertEquals(1, commonStore.getNodeType()); - } - - @Test - public void lowestBlockNumTest() { - Assert.assertEquals(0, commonStore.getLowestBlockNum()); - commonStore.setLowestBlockNum(100); - Assert.assertEquals(100, commonStore.getLowestBlockNum()); - } -} diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java index 472096cf24b..5e5d7d807ae 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java @@ -20,6 +20,7 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.utils.FileUtil; +import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; @@ -42,6 +43,7 @@ public class LiteFnQueryGrpcInterceptorTest { private RpcApiServiceOnSolidity rpcApiServiceOnSolidity; private RpcApiServiceOnPBFT rpcApiServiceOnPBFT; private Application appTest; + private ChainBaseManager chainBaseManager; private String dbPath = "output_grpc_filter_test"; @@ -73,6 +75,7 @@ public void init() { rpcApiService = context.getBean(RpcApiService.class); rpcApiServiceOnSolidity = context.getBean(RpcApiServiceOnSolidity.class); rpcApiServiceOnPBFT = context.getBean(RpcApiServiceOnPBFT.class); + chainBaseManager = context.getBean(ChainBaseManager.class); appTest = ApplicationFactory.create(context); appTest.addService(rpcApiService); appTest.addService(rpcApiServiceOnSolidity); @@ -101,7 +104,7 @@ public void destroy() { @Test public void testGrpcApiThrowStatusRuntimeException() { final GrpcAPI.NumberMessage message = GrpcAPI.NumberMessage.newBuilder().setNum(0).build(); - Args.getInstance().setLiteFullNode(true); + chainBaseManager.setNodeType(ChainBaseManager.NodeType.LITE); thrown.expect(StatusRuntimeException.class); thrown.expectMessage("UNAVAILABLE: this API is closed because this node is a lite fullnode"); blockingStubFull.getBlockByNum(message); @@ -110,7 +113,7 @@ public void testGrpcApiThrowStatusRuntimeException() { @Test public void testpBFTGrpcApiThrowStatusRuntimeException() { final GrpcAPI.NumberMessage message = GrpcAPI.NumberMessage.newBuilder().setNum(0).build(); - Args.getInstance().setLiteFullNode(true); + chainBaseManager.setNodeType(ChainBaseManager.NodeType.LITE); thrown.expect(StatusRuntimeException.class); thrown.expectMessage("UNAVAILABLE: this API is closed because this node is a lite fullnode"); blockingStubpBFT.getBlockByNum(message); @@ -119,7 +122,7 @@ public void testpBFTGrpcApiThrowStatusRuntimeException() { @Test public void testGrpcInterceptor() { GrpcAPI.NumberMessage message = GrpcAPI.NumberMessage.newBuilder().setNum(0).build(); - Args.getInstance().setLiteFullNode(false); + chainBaseManager.setNodeType(ChainBaseManager.NodeType.FULL); Assert.assertNotNull(blockingStubFull.getBlockByNum(message)); } } diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java index d1d294475c9..b63ebc9caed 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java @@ -23,6 +23,7 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.utils.FileUtil; +import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; @@ -40,7 +41,9 @@ public class LiteFnQueryHttpFilterTest { private Application appTest; private CloseableHttpClient httpClient = HttpClients.createDefault(); - private String dbPath = "output_grpc_filter_test"; + private String dbPath = "output_http_filter_test"; + + private ChainBaseManager chainBaseManager; /** * init dependencies. @@ -57,6 +60,7 @@ public void init() { .getBean(HttpApiOnSolidityService.class); HttpApiOnPBFTService httpApiOnPBFTService = context .getBean(HttpApiOnPBFTService.class); + chainBaseManager = context.getBean(ChainBaseManager.class); appTest.addService(httpApiService); appTest.addService(httpApiOnSolidityService); appTest.addService(httpApiOnPBFTService); @@ -94,21 +98,21 @@ public void testHttpFilter() { } String url = String.format("http://%s:%d%s", ip, fullHttpPort, urlPath); // test lite fullnode with history query closed - Args.getInstance().setLiteFullNode(true); + chainBaseManager.setNodeType(ChainBaseManager.NodeType.LITE); Args.getInstance().setOpenHistoryQueryWhenLiteFN(false); String response = sendGetRequest(url); Assert.assertEquals("this API is closed because this node is a lite fullnode", response); // test lite fullnode with history query opened - Args.getInstance().setLiteFullNode(false); + chainBaseManager.setNodeType(ChainBaseManager.NodeType.FULL); Args.getInstance().setOpenHistoryQueryWhenLiteFN(true); response = sendGetRequest(url); Assert.assertNotEquals("this API is closed because this node is a lite fullnode", response); // test normal fullnode - Args.getInstance().setLiteFullNode(false); + chainBaseManager.setNodeType(ChainBaseManager.NodeType.FULL); Args.getInstance().setOpenHistoryQueryWhenLiteFN(true); response = sendGetRequest(url); Assert.assertNotEquals("this API is closed because this node is a lite fullnode", diff --git a/plugins/src/main/java/org/tron/plugins/DbLite.java b/plugins/src/main/java/org/tron/plugins/DbLite.java index c4ea5872a51..ef7e73ec6d6 100644 --- a/plugins/src/main/java/org/tron/plugins/DbLite.java +++ b/plugins/src/main/java/org/tron/plugins/DbLite.java @@ -41,9 +41,6 @@ "1:Internal error: exception occurred,please check toolkit.log"}) public class DbLite implements Callable { - private static final byte[] DB_KEY_LOWEST_BLOCK_NUM = "lowest_block_num".getBytes(); - private static final byte[] DB_KEY_NODE_TYPE = "node_type".getBytes(); - private static final long START_TIME = System.currentTimeMillis() / 1000; private static long RECENT_BLKS = 65536; @@ -56,7 +53,6 @@ public class DbLite implements Callable { 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 COMMON_DB_NAME = "common"; 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"; @@ -432,10 +428,6 @@ private void fillSnapshotBlockAndTransDb(String sourceDir, String snapshotDir) throw new RuntimeException(e.getMessage()); } }); - - DBInterface destCommonDb = DbTool.getDB(snapshotDir, COMMON_DB_NAME); - destCommonDb.put(DB_KEY_NODE_TYPE, ByteArray.fromInt(DBUtils.NODE_TYPE_LIGHT_NODE)); - destCommonDb.put(DB_KEY_LOWEST_BLOCK_NUM, ByteArray.fromLong(startIndex)); // 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); } @@ -636,17 +628,6 @@ private void deleteSnapshotFlag(String databaseDir) throws IOException, RocksDBE logger.info("Delete the info file from {}.", databaseDir); spec.commandLine().getOut().format("Delete the info file from %s.", databaseDir).println(); Files.delete(Paths.get(databaseDir, INFO_FILE_NAME)); - if (!isLite(databaseDir)) { - DBInterface destCommonDb = DbTool.getDB(databaseDir, COMMON_DB_NAME); - destCommonDb.delete(DB_KEY_NODE_TYPE); - destCommonDb.delete(DB_KEY_LOWEST_BLOCK_NUM); - logger.info("Deleted {} and {} from {} to identify this node is a real fullnode.", - "node_type", "lowest_block_num", COMMON_DB_NAME); - spec.commandLine().getOut().format( - "Deleted %s and %s from %s to identify this node is a real fullnode.", - "node_type", "lowest_block_num", COMMON_DB_NAME).println(); - } - } private void deleteBackupArchiveDbs(String liteDir) throws IOException, RocksDBException { From 38f6eb000037db46b57438de99dad134e1909543 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 14 Feb 2023 16:24:14 +0800 Subject: [PATCH 0582/1197] use libp2p test-v0.2.0; don't add fastForwardNode to activeNodes if already exist; if ipv4 and ipv6 not exist, use local ipv4 --- common/build.gradle | 2 +- .../src/main/java/org/tron/core/net/TronNetService.java | 2 +- .../org/tron/core/net/service/relay/RelayService.java | 8 +++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/common/build.gradle b/common/build.gradle index 99610cc0f20..21212d42e19 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -54,7 +54,7 @@ dependencies { compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' //compile group: 'io.github.tronprotocol', name: 'libp2p', version: '0.1.2' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.1.6' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.0' compile project(":protocol") } diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 7b33736f5fa..0e3fc21efb6 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -159,7 +159,7 @@ private P2pConfig getConfig() { config.setNetworkId(parameter.getNodeP2pVersion()); config.setDisconnectionPolicyEnable(parameter.isOpenFullTcpDisconnect()); config.setDiscoverEnable(parameter.isNodeDiscoveryEnable()); - if (StringUtil.isNullOrEmpty(config.getIp())) { + if (StringUtil.isNullOrEmpty(config.getIp()) && StringUtil.isNullOrEmpty(config.getIpv6())) { config.setIp(parameter.getNodeExternalIp()); } config.setTreeUrls(parameter.getDnsTreeUrls()); diff --git a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java index 478f0714875..665255a6594 100644 --- a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java @@ -32,7 +32,6 @@ import org.tron.core.net.peer.Item; import org.tron.core.net.peer.PeerConnection; import org.tron.core.store.WitnessScheduleStore; -import org.tron.p2p.P2pConfig; import org.tron.p2p.connection.Channel; import org.tron.protos.Protocol; @@ -171,8 +170,11 @@ private boolean isActiveWitness() { } private void connect() { - fastForwardNodes.forEach(address -> - TronNetService.getP2pConfig().getActiveNodes().add(address)); + for (InetSocketAddress fastForwardNode : fastForwardNodes) { + if (!TronNetService.getP2pConfig().getActiveNodes().contains(fastForwardNode)) { + TronNetService.getP2pConfig().getActiveNodes().add(fastForwardNode); + } + } } private void disconnect() { From 80e700fe7b0f57468b86d34a9fc761ac85d1e012 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 8 Feb 2023 11:55:33 +0800 Subject: [PATCH 0583/1197] fix(test): add some test cases of utils --- .../java/org/tron/core/capsule/utils/RLP.java | 6 +- .../vm/BandWidthRuntimeOutOfTimeTest.java | 2 +- ...andWidthRuntimeOutOfTimeWithCheckTest.java | 2 +- .../runtime/vm/BandWidthRuntimeTest.java | 8 +- .../vm/BandWidthRuntimeWithCheckTest.java | 2 +- .../PrecompiledContractsVerifyProofTest.java | 374 ++++++++++-------- .../java/org/tron/core/tire/TrieTest.java | 2 +- .../tron/program/LiteFullNodeToolTest.java | 5 - .../org/tron/program/SolidityNodeTest.java | 2 +- .../java/org/tron/program/SupplementTest.java | 137 +++++++ 10 files changed, 352 insertions(+), 188 deletions(-) create mode 100644 framework/src/test/java/org/tron/program/SupplementTest.java diff --git a/framework/src/main/java/org/tron/core/capsule/utils/RLP.java b/framework/src/main/java/org/tron/core/capsule/utils/RLP.java index 54e7d044346..60a84cfd3d3 100644 --- a/framework/src/main/java/org/tron/core/capsule/utils/RLP.java +++ b/framework/src/main/java/org/tron/core/capsule/utils/RLP.java @@ -204,7 +204,7 @@ public static long decodeLong(byte[] data, int index) { return value; } - private static String decodeStringItem(byte[] data, int index) { + public static String decodeStringItem(byte[] data, int index) { final byte[] valueBytes = decodeItemBytes(data, index); @@ -229,12 +229,12 @@ public static BigInteger decodeBigInteger(byte[] data, int index) { } } - private static byte[] decodeByteArray(byte[] data, int index) { + public static byte[] decodeByteArray(byte[] data, int index) { return decodeItemBytes(data, index); } - private static int nextItemLength(byte[] data, int index) { + public static int nextItemLength(byte[] data, int index) { if (index >= data.length) { return -1; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java index 9bfaebc0edf..f2cd7ae28ce 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java @@ -66,7 +66,7 @@ public class BandWidthRuntimeOutOfTimeTest extends BaseTest { private static final String TriggerOwnerAddress = "TCSgeWapPJhCqgWRxXCKb6jJ5AgNWSGjPA"; static { - dbPath = "output_BandWidthRuntimeOutOfTimeTest_test"; + dbPath = "output_bandwidth_runtime_out_of_time_test"; Args.setParam( new String[]{ "--output-directory", dbPath, diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java index b39f4e56391..0b9cdc9018a 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java @@ -67,7 +67,7 @@ public class BandWidthRuntimeOutOfTimeWithCheckTest extends BaseTest { private static final String TriggerOwnerAddress = "TCSgeWapPJhCqgWRxXCKb6jJ5AgNWSGjPA"; static { - dbPath = "output_BandWidthRuntimeOutOfTimeTest_test"; + dbPath = "output_bandwidth_runtime_out_of_time_with_check_test"; Args.setParam( new String[]{ "--output-directory", dbPath, diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java index 9309bc398bc..20e8e11535a 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java @@ -19,6 +19,7 @@ import com.google.protobuf.ByteString; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.tron.common.BaseTest; import org.tron.common.runtime.RuntimeImpl; @@ -56,8 +57,9 @@ public class BandWidthRuntimeTest extends BaseTest { private static final String TriggerOwnerTwoAddress = "TPMBUANrTwwQAPwShn7ZZjTJz1f3F8jknj"; private static boolean init; - static { - dbPath = "output_BandWidthRuntimeTest_test"; + @BeforeClass + public static void init() { + dbPath = "output_bandwidth_runtime_test"; Args.setParam( new String[]{ "--output-directory", dbPath, @@ -73,7 +75,7 @@ public class BandWidthRuntimeTest extends BaseTest { * Init data. */ @Before - public void init() { + public void before() { if (init) { return; } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java index d1f19fc4d2a..0e7f79eb42f 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java @@ -70,7 +70,7 @@ public class BandWidthRuntimeWithCheckTest extends BaseTest { private static boolean init; static { - dbPath = "output_BandWidthRuntimeTest_test"; + dbPath = "output_bandwidth_runtime_with_check_test"; Args.setParam( new String[]{ "--output-directory", dbPath, diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java index 1053b759fe9..4779c90205d 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java @@ -1,5 +1,7 @@ package org.tron.common.runtime.vm; +import static org.junit.Assert.assertNotNull; + import com.google.protobuf.ByteString; import java.math.BigInteger; import java.util.Arrays; @@ -7,6 +9,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; import org.junit.Assert; +import org.junit.BeforeClass; import org.junit.Test; import org.tron.api.GrpcAPI.ShieldedTRC20Parameters; import org.tron.common.BaseTest; @@ -42,12 +45,18 @@ public class PrecompiledContractsVerifyProofTest extends BaseTest { private static final String SHIELDED_CONTRACT_ADDRESS_STR = "TGAmX5AqVUoXCf8MoHxbuhQPmhGfWTnEgA"; - private static final byte[] SHIELDED_CONTRACT_ADDRESS; + private static byte[] SHIELDED_CONTRACT_ADDRESS; private static final String PUBLIC_TO_ADDRESS_STR = "TBaBXpRAeBhs75TZT751LwyhrcR25XeUot"; - private static final byte[] PUBLIC_TO_ADDRESS; - private static final byte[] DEFAULT_OVK; + private static byte[] PUBLIC_TO_ADDRESS; + private static byte[] DEFAULT_OVK; - static { + VerifyMintProof mintContract = new VerifyMintProof(); + VerifyTransferProof transferContract = new VerifyTransferProof(); + VerifyBurnProof burnContract = new VerifyBurnProof(); + MerkleHash merkleHash = new MerkleHash(); + + @BeforeClass + public static void init() { dbPath = "output_PrecompiledContracts_VerifyProof_test"; Args.setParam(new String[]{"--output-directory", dbPath}, "config-test.conf"); DEFAULT_OVK = ByteArray @@ -57,11 +66,6 @@ public class PrecompiledContractsVerifyProofTest extends BaseTest { FullNodeHttpApiService.librustzcashInitZksnarkParams(); } - VerifyMintProof mintContract = new VerifyMintProof(); - VerifyTransferProof transferContract = new VerifyTransferProof(); - VerifyBurnProof burnContract = new VerifyBurnProof(); - MerkleHash merkleHash = new MerkleHash(); - @Test public void verifyMintProofCorrect() throws ZksnarkException { int totalCountNum = 2; @@ -79,7 +83,8 @@ public void verifyMintProofCorrect() throws ZksnarkException { SpendingKey recvSk = SpendingKey.random(); FullViewingKey fullViewingKey = recvSk.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()).get(); + PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()) + .orElse(null); builder.addOutput(DEFAULT_OVK, paymentAddress, value, new byte[512]); ShieldedTRC20Parameters params = builder.build(false); @@ -121,9 +126,10 @@ public void verifyTransferProofCorrect() throws ZksnarkException { JLibrustzcash.librustzcashSaplingGenerateR(rcm1); byte[] rcm2 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm2); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); + assertNotNull(senderPaymentAddress2); { //for mint1 ShieldedTRC20ParametersBuilder mintBuilder1 = new ShieldedTRC20ParametersBuilder(); mintBuilder1.setTransparentFromAmount(BigInteger.valueOf(30)); @@ -211,14 +217,16 @@ public void verifyTransferProofCorrect() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 40, new byte[512]); //receiveNote2 SpendingKey receiveSk2 = SpendingKey.random(); FullViewingKey receiveFvk2 = receiveSk2.fullViewingKey(); IncomingViewingKey receiveIvk2 = receiveFvk2.inViewingKey(); - PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress2, 60, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -277,8 +285,8 @@ public void verifyTransfer1v1ProofCorrect() throws ZksnarkException { IncomingViewingKey senderIvk = senderFvk.inViewingKey(); byte[] rcm1 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm1); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); { //for mint1 ShieldedTRC20ParametersBuilder mintBuilder1 = new ShieldedTRC20ParametersBuilder(); mintBuilder1.setTransparentFromAmount(BigInteger.valueOf(100)); @@ -327,7 +335,8 @@ public void verifyTransfer1v1ProofCorrect() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 100, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -382,8 +391,8 @@ public void verifyBurnWithCmCorrect() throws ZksnarkException { IncomingViewingKey senderIvk = senderFvk.inViewingKey(); byte[] rcm1 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm1); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); { //for mint1 ShieldedTRC20ParametersBuilder mintBuilder1 = new ShieldedTRC20ParametersBuilder(); mintBuilder1.setTransparentFromAmount(BigInteger.valueOf(100)); @@ -433,7 +442,8 @@ public void verifyBurnWithCmCorrect() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 50, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -488,8 +498,8 @@ public void verifyTransfer1v2ProofCorrect() throws ZksnarkException { IncomingViewingKey senderIvk = senderFvk.inViewingKey(); byte[] rcm1 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm1); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); { //for mint1 ShieldedTRC20ParametersBuilder mintBuilder1 = new ShieldedTRC20ParametersBuilder(); mintBuilder1.setTransparentFromAmount(BigInteger.valueOf(100)); @@ -538,14 +548,16 @@ public void verifyTransfer1v2ProofCorrect() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 40, new byte[512]); //receiveNote2 SpendingKey receiveSk2 = SpendingKey.random(); FullViewingKey receiveFvk2 = receiveSk2.fullViewingKey(); IncomingViewingKey receiveIvk2 = receiveFvk2.inViewingKey(); - PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress2, 60, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -606,9 +618,10 @@ public void verifyTransfer2v1ProofCorrect() throws ZksnarkException { JLibrustzcash.librustzcashSaplingGenerateR(rcm1); byte[] rcm2 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm2); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); + assertNotNull(senderPaymentAddress2); { //for mint1 ShieldedTRC20ParametersBuilder mintBuilder1 = new ShieldedTRC20ParametersBuilder(); mintBuilder1.setTransparentFromAmount(BigInteger.valueOf(30)); @@ -696,7 +709,8 @@ public void verifyTransfer2v1ProofCorrect() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 100, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -749,12 +763,11 @@ public void verifyBurnProofCorrect() throws ZksnarkException { SpendingKey senderSk = SpendingKey.random(); ExpandedSpendingKey senderExpsk = senderSk.expandedSpendingKey(); FullViewingKey senderFvk = senderSk.fullViewingKey(); - byte[] senderOvk = senderFvk.getOvk(); IncomingViewingKey senderIvk = senderFvk.inViewingKey(); byte[] rcm = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm); - PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress); { //for mint ShieldedTRC20ParametersBuilder mintBuilder = new ShieldedTRC20ParametersBuilder(); mintBuilder.setTransparentFromAmount(BigInteger.valueOf(value)); @@ -830,7 +843,8 @@ public void merkleHashCorrectTest() throws ZksnarkException { IncomingViewingKey ivk = fvk.inViewingKey(); byte[] rcm = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm); - PaymentAddress paymentAddress = ivk.address(DiversifierT.random()).get(); + PaymentAddress paymentAddress = ivk.address(DiversifierT.random()).orElse(null); + assertNotNull(paymentAddress); Note note = new Note(paymentAddress.getD(), paymentAddress.getPkD(), randomLong(), rcm, new byte[512]); byte[] node = note.cm(); @@ -867,8 +881,8 @@ public void verifyBurnWithCmWrong() throws ZksnarkException { IncomingViewingKey senderIvk = senderFvk.inViewingKey(); byte[] rcm1 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm1); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); { //for mint1 ShieldedTRC20ParametersBuilder mintBuilder1 = new ShieldedTRC20ParametersBuilder(); mintBuilder1.setTransparentFromAmount(BigInteger.valueOf(100)); @@ -918,7 +932,7 @@ public void verifyBurnWithCmWrong() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 50, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -988,7 +1002,7 @@ public void verifyMintWrongDataLength() throws ZksnarkException { SpendingKey recvSk = SpendingKey.random(); FullViewingKey fullViewingKey = recvSk.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()).get(); + PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()).orElse(null); builder.addOutput(DEFAULT_OVK, paymentAddress, value, new byte[512]); ShieldedTRC20Parameters params = builder.build(false); @@ -1014,9 +1028,10 @@ public void verifyTransferWrongDataLength() throws ZksnarkException { JLibrustzcash.librustzcashSaplingGenerateR(rcm1); byte[] rcm2 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm2); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); + assertNotNull(senderPaymentAddress2); ShieldedTRC20ParametersBuilder builder = new ShieldedTRC20ParametersBuilder(); builder.setShieldedTRC20ParametersType(ShieldedTRC20ParametersType.TRANSFER); builder.setShieldedTRC20Address(SHIELDED_CONTRACT_ADDRESS); @@ -1051,14 +1066,14 @@ public void verifyTransferWrongDataLength() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 40, new byte[512]); //receiveNote2 SpendingKey receiveSk2 = SpendingKey.random(); FullViewingKey receiveFvk2 = receiveSk2.fullViewingKey(); IncomingViewingKey receiveIvk2 = receiveFvk2.inViewingKey(); - PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).orElse(null); builder.addOutput(senderOvk, receivePaymentAddress2, 60, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -1079,8 +1094,8 @@ public void verifyBurnWrongDataLength() throws ZksnarkException { IncomingViewingKey senderIvk = senderFvk.inViewingKey(); byte[] rcm = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm); - PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress); ShieldedTRC20ParametersBuilder builder = new ShieldedTRC20ParametersBuilder(); builder.setShieldedTRC20ParametersType(ShieldedTRC20ParametersType.BURN); builder.setShieldedTRC20Address(SHIELDED_CONTRACT_ADDRESS); @@ -1124,7 +1139,8 @@ public void verifyMintWrongLeafcount() throws ZksnarkException { SpendingKey recvSk = SpendingKey.random(); FullViewingKey fullViewingKey = recvSk.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()).get(); + PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()) + .orElse(null); builder.addOutput(DEFAULT_OVK, paymentAddress, value, new byte[512]); ShieldedTRC20Parameters params = builder.build(false); @@ -1150,9 +1166,10 @@ public void verifyTransferWrongLeafcount() throws ZksnarkException { JLibrustzcash.librustzcashSaplingGenerateR(rcm1); byte[] rcm2 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm2); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); + assertNotNull(senderPaymentAddress2); for (long leafCount : leafCountList) { ShieldedTRC20ParametersBuilder builder = new ShieldedTRC20ParametersBuilder(); builder.setShieldedTRC20ParametersType(ShieldedTRC20ParametersType.TRANSFER); @@ -1187,14 +1204,14 @@ public void verifyTransferWrongLeafcount() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 40, new byte[512]); //receiveNote2 SpendingKey receiveSk2 = SpendingKey.random(); FullViewingKey receiveFvk2 = receiveSk2.fullViewingKey(); IncomingViewingKey receiveIvk2 = receiveFvk2.inViewingKey(); - PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).orElse(null); builder.addOutput(senderOvk, receivePaymentAddress2, 60, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -1218,8 +1235,8 @@ public void verifyTransferDuplicateNf() throws ZksnarkException { IncomingViewingKey senderIvk = senderFvk.inViewingKey(); byte[] rcm = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm); - PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress); ShieldedTRC20ParametersBuilder builder = new ShieldedTRC20ParametersBuilder(); builder.setShieldedTRC20ParametersType(ShieldedTRC20ParametersType.TRANSFER); builder.setShieldedTRC20Address(SHIELDED_CONTRACT_ADDRESS); @@ -1244,14 +1261,14 @@ public void verifyTransferDuplicateNf() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 40, new byte[512]); //receiveNote2 SpendingKey receiveSk2 = SpendingKey.random(); FullViewingKey receiveFvk2 = receiveSk2.fullViewingKey(); IncomingViewingKey receiveIvk2 = receiveFvk2.inViewingKey(); - PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).orElse(null); builder.addOutput(senderOvk, receivePaymentAddress2, 60, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -1276,9 +1293,10 @@ public void verifyTransferDuplicateReceiveNotes() throws ZksnarkException { JLibrustzcash.librustzcashSaplingGenerateR(rcm1); byte[] rcm2 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm2); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); + assertNotNull(senderPaymentAddress2); ShieldedTRC20ParametersBuilder builder = new ShieldedTRC20ParametersBuilder(); builder.setShieldedTRC20ParametersType(ShieldedTRC20ParametersType.TRANSFER); builder.setShieldedTRC20Address(SHIELDED_CONTRACT_ADDRESS); @@ -1313,7 +1331,8 @@ public void verifyTransferDuplicateReceiveNotes() throws ZksnarkException { SpendingKey receiveSk = SpendingKey.random(); FullViewingKey receiveFvk = receiveSk.fullViewingKey(); IncomingViewingKey receiveIvk = receiveFvk.inViewingKey(); - PaymentAddress receivePaymentAddress = receiveIvk.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress = receiveIvk.address(new DiversifierT()).orElse(null); + assertNotNull(receivePaymentAddress); byte[] r = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(r); builder.addOutput(senderOvk, receivePaymentAddress.getD(), receivePaymentAddress.getPkD(), @@ -1345,7 +1364,8 @@ public void verifyMintWrongValue() throws ZksnarkException { SpendingKey recvSk = SpendingKey.random(); FullViewingKey fullViewingKey = recvSk.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()).get(); + PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()) + .orElse(null); builder.addOutput(DEFAULT_OVK, paymentAddress, 50, new byte[512]); ShieldedTRC20Parameters params = builder.build(false); @@ -1363,12 +1383,11 @@ public void verifyBurnWrongValue() throws ZksnarkException { SpendingKey senderSk = SpendingKey.random(); ExpandedSpendingKey senderExpsk = senderSk.expandedSpendingKey(); FullViewingKey senderFvk = senderSk.fullViewingKey(); - byte[] senderOvk = senderFvk.getOvk(); IncomingViewingKey senderIvk = senderFvk.inViewingKey(); byte[] rcm = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm); - PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress); ShieldedTRC20ParametersBuilder builder = new ShieldedTRC20ParametersBuilder(); builder.setShieldedTRC20ParametersType(ShieldedTRC20ParametersType.BURN); builder.setShieldedTRC20Address(SHIELDED_CONTRACT_ADDRESS); @@ -1412,7 +1431,8 @@ public void verifyMintProofWrongCM() throws ZksnarkException { SpendingKey recvSk = SpendingKey.random(); FullViewingKey fullViewingKey = recvSk.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()).get(); + PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()) + .orElse(null); builder.addOutput(DEFAULT_OVK, paymentAddress, value, new byte[512]); ShieldedTRC20Parameters params = builder.build(false); @@ -1442,7 +1462,8 @@ public void verifyMintProofWrongCV() throws ZksnarkException { SpendingKey recvSk = SpendingKey.random(); FullViewingKey fullViewingKey = recvSk.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()).get(); + PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()) + .orElse(null); builder.addOutput(DEFAULT_OVK, paymentAddress, value, new byte[512]); ShieldedTRC20Parameters params = builder.build(false); @@ -1471,7 +1492,8 @@ public void verifyMintProofWrongEpk() throws ZksnarkException { SpendingKey recvSk = SpendingKey.random(); FullViewingKey fullViewingKey = recvSk.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()).get(); + PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()) + .orElse(null); builder.addOutput(DEFAULT_OVK, paymentAddress, value, new byte[512]); ShieldedTRC20Parameters params = builder.build(false); @@ -1500,7 +1522,8 @@ public void verifyMintProofWrongProof() throws ZksnarkException { SpendingKey recvSk = SpendingKey.random(); FullViewingKey fullViewingKey = recvSk.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()).get(); + PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()) + .orElse(null); builder.addOutput(DEFAULT_OVK, paymentAddress, value, new byte[512]); ShieldedTRC20Parameters params = builder.build(false); @@ -1529,7 +1552,8 @@ public void verifyMintProofWrongBindingSignature() throws ZksnarkException { SpendingKey recvSk = SpendingKey.random(); FullViewingKey fullViewingKey = recvSk.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()).get(); + PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()) + .orElse(null); builder.addOutput(DEFAULT_OVK, paymentAddress, value, new byte[512]); ShieldedTRC20Parameters params = builder.build(false); @@ -1558,7 +1582,8 @@ public void verifyMintProofWrongHash() throws ZksnarkException { SpendingKey recvSk = SpendingKey.random(); FullViewingKey fullViewingKey = recvSk.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()).get(); + PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()) + .orElse(null); builder.addOutput(DEFAULT_OVK, paymentAddress, value, new byte[512]); ShieldedTRC20Parameters params = builder.build(false); @@ -1588,9 +1613,10 @@ public void verifyTransferProofWrongNf() throws ZksnarkException { JLibrustzcash.librustzcashSaplingGenerateR(rcm1); byte[] rcm2 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm2); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); + assertNotNull(senderPaymentAddress2); { //for mint1 ShieldedTRC20ParametersBuilder mintBuilder1 = new ShieldedTRC20ParametersBuilder(); mintBuilder1.setTransparentFromAmount(BigInteger.valueOf(30)); @@ -1676,14 +1702,16 @@ public void verifyTransferProofWrongNf() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 40, new byte[512]); //receiveNote2 SpendingKey receiveSk2 = SpendingKey.random(); FullViewingKey receiveFvk2 = receiveSk2.fullViewingKey(); IncomingViewingKey receiveIvk2 = receiveFvk2.inViewingKey(); - PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress2, 60, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -1714,9 +1742,10 @@ public void verifyTransferProofWrongRoot() throws ZksnarkException { JLibrustzcash.librustzcashSaplingGenerateR(rcm1); byte[] rcm2 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm2); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); + assertNotNull(senderPaymentAddress2); { //for mint1 ShieldedTRC20ParametersBuilder mintBuilder1 = new ShieldedTRC20ParametersBuilder(); mintBuilder1.setTransparentFromAmount(BigInteger.valueOf(30)); @@ -1802,14 +1831,16 @@ public void verifyTransferProofWrongRoot() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 40, new byte[512]); //receiveNote2 SpendingKey receiveSk2 = SpendingKey.random(); FullViewingKey receiveFvk2 = receiveSk2.fullViewingKey(); IncomingViewingKey receiveIvk2 = receiveFvk2.inViewingKey(); - PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress2, 60, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -1841,9 +1872,10 @@ public void verifyTransferProofWrongSpendCV() throws ZksnarkException { JLibrustzcash.librustzcashSaplingGenerateR(rcm1); byte[] rcm2 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm2); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); + assertNotNull(senderPaymentAddress2); { //for mint1 ShieldedTRC20ParametersBuilder mintBuilder1 = new ShieldedTRC20ParametersBuilder(); mintBuilder1.setTransparentFromAmount(BigInteger.valueOf(30)); @@ -1929,14 +1961,16 @@ public void verifyTransferProofWrongSpendCV() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 40, new byte[512]); //receiveNote2 SpendingKey receiveSk2 = SpendingKey.random(); FullViewingKey receiveFvk2 = receiveSk2.fullViewingKey(); IncomingViewingKey receiveIvk2 = receiveFvk2.inViewingKey(); - PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress2, 60, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -1967,9 +2001,10 @@ public void verifyTransferProofWrongRk() throws ZksnarkException { JLibrustzcash.librustzcashSaplingGenerateR(rcm1); byte[] rcm2 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm2); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); + assertNotNull(senderPaymentAddress2); { //for mint1 ShieldedTRC20ParametersBuilder mintBuilder1 = new ShieldedTRC20ParametersBuilder(); mintBuilder1.setTransparentFromAmount(BigInteger.valueOf(30)); @@ -2055,14 +2090,16 @@ public void verifyTransferProofWrongRk() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 40, new byte[512]); //receiveNote2 SpendingKey receiveSk2 = SpendingKey.random(); FullViewingKey receiveFvk2 = receiveSk2.fullViewingKey(); IncomingViewingKey receiveIvk2 = receiveFvk2.inViewingKey(); - PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress2, 60, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -2093,9 +2130,10 @@ public void verifyTransferProofWrongSpendProof() throws ZksnarkException { JLibrustzcash.librustzcashSaplingGenerateR(rcm1); byte[] rcm2 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm2); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); + assertNotNull(senderPaymentAddress2); { //for mint1 ShieldedTRC20ParametersBuilder mintBuilder1 = new ShieldedTRC20ParametersBuilder(); mintBuilder1.setTransparentFromAmount(BigInteger.valueOf(30)); @@ -2181,14 +2219,16 @@ public void verifyTransferProofWrongSpendProof() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 40, new byte[512]); //receiveNote2 SpendingKey receiveSk2 = SpendingKey.random(); FullViewingKey receiveFvk2 = receiveSk2.fullViewingKey(); IncomingViewingKey receiveIvk2 = receiveFvk2.inViewingKey(); - PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress2, 60, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -2219,9 +2259,10 @@ public void verifyTransferProofWrongCm() throws ZksnarkException { JLibrustzcash.librustzcashSaplingGenerateR(rcm1); byte[] rcm2 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm2); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); + assertNotNull(senderPaymentAddress2); { //for mint1 ShieldedTRC20ParametersBuilder mintBuilder1 = new ShieldedTRC20ParametersBuilder(); mintBuilder1.setTransparentFromAmount(BigInteger.valueOf(30)); @@ -2307,14 +2348,16 @@ public void verifyTransferProofWrongCm() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 40, new byte[512]); //receiveNote2 SpendingKey receiveSk2 = SpendingKey.random(); FullViewingKey receiveFvk2 = receiveSk2.fullViewingKey(); IncomingViewingKey receiveIvk2 = receiveFvk2.inViewingKey(); - PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress2, 60, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -2345,9 +2388,10 @@ public void verifyTransferProofWrongReceiveCV() throws ZksnarkException { JLibrustzcash.librustzcashSaplingGenerateR(rcm1); byte[] rcm2 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm2); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); + assertNotNull(senderPaymentAddress2); { //for mint1 ShieldedTRC20ParametersBuilder mintBuilder1 = new ShieldedTRC20ParametersBuilder(); mintBuilder1.setTransparentFromAmount(BigInteger.valueOf(30)); @@ -2433,14 +2477,16 @@ public void verifyTransferProofWrongReceiveCV() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 40, new byte[512]); //receiveNote2 SpendingKey receiveSk2 = SpendingKey.random(); FullViewingKey receiveFvk2 = receiveSk2.fullViewingKey(); IncomingViewingKey receiveIvk2 = receiveFvk2.inViewingKey(); - PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress2, 60, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -2471,9 +2517,10 @@ public void verifyTransferProofWrongEpk() throws ZksnarkException { JLibrustzcash.librustzcashSaplingGenerateR(rcm1); byte[] rcm2 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm2); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); + assertNotNull(senderPaymentAddress2); { //for mint1 ShieldedTRC20ParametersBuilder mintBuilder1 = new ShieldedTRC20ParametersBuilder(); mintBuilder1.setTransparentFromAmount(BigInteger.valueOf(30)); @@ -2559,14 +2606,16 @@ public void verifyTransferProofWrongEpk() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 40, new byte[512]); //receiveNote2 SpendingKey receiveSk2 = SpendingKey.random(); FullViewingKey receiveFvk2 = receiveSk2.fullViewingKey(); IncomingViewingKey receiveIvk2 = receiveFvk2.inViewingKey(); - PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress2, 60, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -2597,9 +2646,10 @@ public void verifyTransferProofWrongReceiveProof() throws ZksnarkException { JLibrustzcash.librustzcashSaplingGenerateR(rcm1); byte[] rcm2 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm2); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); + assertNotNull(senderPaymentAddress2); { //for mint1 ShieldedTRC20ParametersBuilder mintBuilder1 = new ShieldedTRC20ParametersBuilder(); mintBuilder1.setTransparentFromAmount(BigInteger.valueOf(30)); @@ -2685,14 +2735,16 @@ public void verifyTransferProofWrongReceiveProof() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 40, new byte[512]); //receiveNote2 SpendingKey receiveSk2 = SpendingKey.random(); FullViewingKey receiveFvk2 = receiveSk2.fullViewingKey(); IncomingViewingKey receiveIvk2 = receiveFvk2.inViewingKey(); - PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress2, 60, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -2723,9 +2775,10 @@ public void verifyTransferProofWrongBindingSignature() throws ZksnarkException { JLibrustzcash.librustzcashSaplingGenerateR(rcm1); byte[] rcm2 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm2); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); + assertNotNull(senderPaymentAddress2); { //for mint1 ShieldedTRC20ParametersBuilder mintBuilder1 = new ShieldedTRC20ParametersBuilder(); mintBuilder1.setTransparentFromAmount(BigInteger.valueOf(30)); @@ -2811,14 +2864,16 @@ public void verifyTransferProofWrongBindingSignature() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 40, new byte[512]); //receiveNote2 SpendingKey receiveSk2 = SpendingKey.random(); FullViewingKey receiveFvk2 = receiveSk2.fullViewingKey(); IncomingViewingKey receiveIvk2 = receiveFvk2.inViewingKey(); - PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress2, 60, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -2849,9 +2904,10 @@ public void verifyTransferProofWrongHash() throws ZksnarkException { JLibrustzcash.librustzcashSaplingGenerateR(rcm1); byte[] rcm2 = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm2); - PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).get(); - PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress1 = senderIvk.address(DiversifierT.random()).orElse(null); + PaymentAddress senderPaymentAddress2 = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress1); + assertNotNull(senderPaymentAddress2); { //for mint1 ShieldedTRC20ParametersBuilder mintBuilder1 = new ShieldedTRC20ParametersBuilder(); mintBuilder1.setTransparentFromAmount(BigInteger.valueOf(30)); @@ -2937,14 +2993,16 @@ public void verifyTransferProofWrongHash() throws ZksnarkException { SpendingKey receiveSk1 = SpendingKey.random(); FullViewingKey receiveFvk1 = receiveSk1.fullViewingKey(); IncomingViewingKey receiveIvk1 = receiveFvk1.inViewingKey(); - PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress1 = receiveIvk1.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress1, 40, new byte[512]); //receiveNote2 SpendingKey receiveSk2 = SpendingKey.random(); FullViewingKey receiveFvk2 = receiveSk2.fullViewingKey(); IncomingViewingKey receiveIvk2 = receiveFvk2.inViewingKey(); - PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()).get(); + PaymentAddress receivePaymentAddress2 = receiveIvk2.address(new DiversifierT()) + .orElse(null); builder.addOutput(senderOvk, receivePaymentAddress2, 60, new byte[512]); ShieldedTRC20Parameters params = builder.build(true); @@ -2970,12 +3028,11 @@ public void verifyBurnWrongNF() throws ZksnarkException { SpendingKey senderSk = SpendingKey.random(); ExpandedSpendingKey senderExpsk = senderSk.expandedSpendingKey(); FullViewingKey senderFvk = senderSk.fullViewingKey(); - byte[] senderOvk = senderFvk.getOvk(); IncomingViewingKey senderIvk = senderFvk.inViewingKey(); byte[] rcm = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm); - PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress); { //for mint ShieldedTRC20ParametersBuilder mintBuilder = new ShieldedTRC20ParametersBuilder(); mintBuilder.setTransparentFromAmount(BigInteger.valueOf(value)); @@ -3041,12 +3098,11 @@ public void verifyBurnWrongRoot() throws ZksnarkException { SpendingKey senderSk = SpendingKey.random(); ExpandedSpendingKey senderExpsk = senderSk.expandedSpendingKey(); FullViewingKey senderFvk = senderSk.fullViewingKey(); - byte[] senderOvk = senderFvk.getOvk(); IncomingViewingKey senderIvk = senderFvk.inViewingKey(); byte[] rcm = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm); - PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress); { //for mint ShieldedTRC20ParametersBuilder mintBuilder = new ShieldedTRC20ParametersBuilder(); mintBuilder.setTransparentFromAmount(BigInteger.valueOf(value)); @@ -3113,12 +3169,11 @@ public void verifyBurnWrongCV() throws ZksnarkException { SpendingKey senderSk = SpendingKey.random(); ExpandedSpendingKey senderExpsk = senderSk.expandedSpendingKey(); FullViewingKey senderFvk = senderSk.fullViewingKey(); - byte[] senderOvk = senderFvk.getOvk(); IncomingViewingKey senderIvk = senderFvk.inViewingKey(); byte[] rcm = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm); - PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress); { //for mint ShieldedTRC20ParametersBuilder mintBuilder = new ShieldedTRC20ParametersBuilder(); mintBuilder.setTransparentFromAmount(BigInteger.valueOf(value)); @@ -3184,12 +3239,11 @@ public void verifyBurnWrongRk() throws ZksnarkException { SpendingKey senderSk = SpendingKey.random(); ExpandedSpendingKey senderExpsk = senderSk.expandedSpendingKey(); FullViewingKey senderFvk = senderSk.fullViewingKey(); - byte[] senderOvk = senderFvk.getOvk(); IncomingViewingKey senderIvk = senderFvk.inViewingKey(); byte[] rcm = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm); - PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress); { //for mint ShieldedTRC20ParametersBuilder mintBuilder = new ShieldedTRC20ParametersBuilder(); mintBuilder.setTransparentFromAmount(BigInteger.valueOf(value)); @@ -3255,12 +3309,11 @@ public void verifyBurnWrongProof() throws ZksnarkException { SpendingKey senderSk = SpendingKey.random(); ExpandedSpendingKey senderExpsk = senderSk.expandedSpendingKey(); FullViewingKey senderFvk = senderSk.fullViewingKey(); - byte[] senderOvk = senderFvk.getOvk(); IncomingViewingKey senderIvk = senderFvk.inViewingKey(); byte[] rcm = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm); - PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress); { //for mint ShieldedTRC20ParametersBuilder mintBuilder = new ShieldedTRC20ParametersBuilder(); mintBuilder.setTransparentFromAmount(BigInteger.valueOf(value)); @@ -3326,12 +3379,11 @@ public void verifyBurnWrongAuthoritySingature() throws ZksnarkException { SpendingKey senderSk = SpendingKey.random(); ExpandedSpendingKey senderExpsk = senderSk.expandedSpendingKey(); FullViewingKey senderFvk = senderSk.fullViewingKey(); - byte[] senderOvk = senderFvk.getOvk(); IncomingViewingKey senderIvk = senderFvk.inViewingKey(); byte[] rcm = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm); - PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress); { //for mint ShieldedTRC20ParametersBuilder mintBuilder = new ShieldedTRC20ParametersBuilder(); mintBuilder.setTransparentFromAmount(BigInteger.valueOf(value)); @@ -3397,12 +3449,11 @@ public void verifyBurnWrongBindingSingature() throws ZksnarkException { SpendingKey senderSk = SpendingKey.random(); ExpandedSpendingKey senderExpsk = senderSk.expandedSpendingKey(); FullViewingKey senderFvk = senderSk.fullViewingKey(); - byte[] senderOvk = senderFvk.getOvk(); IncomingViewingKey senderIvk = senderFvk.inViewingKey(); byte[] rcm = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm); - PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress); { //for mint ShieldedTRC20ParametersBuilder mintBuilder = new ShieldedTRC20ParametersBuilder(); mintBuilder.setTransparentFromAmount(BigInteger.valueOf(value)); @@ -3468,12 +3519,11 @@ public void verifyBurnWrongHash() throws ZksnarkException { SpendingKey senderSk = SpendingKey.random(); ExpandedSpendingKey senderExpsk = senderSk.expandedSpendingKey(); FullViewingKey senderFvk = senderSk.fullViewingKey(); - byte[] senderOvk = senderFvk.getOvk(); IncomingViewingKey senderIvk = senderFvk.inViewingKey(); byte[] rcm = new byte[32]; JLibrustzcash.librustzcashSaplingGenerateR(rcm); - PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).get(); - + PaymentAddress senderPaymentAddress = senderIvk.address(DiversifierT.random()).orElse(null); + assertNotNull(senderPaymentAddress); { //for mint ShieldedTRC20ParametersBuilder mintBuilder = new ShieldedTRC20ParametersBuilder(); mintBuilder.setTransparentFromAmount(BigInteger.valueOf(value)); @@ -3529,21 +3579,19 @@ public void verifyBurnWrongHash() throws ZksnarkException { private Pair verifyTransfer(byte[] input) { transferContract.getEnergyForData(input); transferContract.setVmShouldEndInUs(System.nanoTime() / 1000 + 50 * 1000); - Pair ret = transferContract.execute(input); - return ret; + return transferContract.execute(input); } private IncrementalMerkleVoucherContainer addSimpleMerkleVoucherContainer( IncrementalMerkleTreeContainer tree, byte[][] cm) throws ZksnarkException { - for (int i = 0; i < cm.length; i++) { + for (byte[] bytes : cm) { PedersenHashCapsule compressCapsule = new PedersenHashCapsule(); - compressCapsule.setContent(ByteString.copyFrom(cm[i])); + compressCapsule.setContent(ByteString.copyFrom(bytes)); ShieldContract.PedersenHash a = compressCapsule.getInstance(); tree.append(a); } - IncrementalMerkleVoucherContainer voucher = tree.toVoucher(); - return voucher; + return tree.toVoucher(); } private byte[] decodePath(byte[] encodedPath) { @@ -3646,24 +3694,6 @@ private byte[] abiEncodeForMintWrongProof(ShieldedTRC20Parameters params, long v return mergedBytes; } - private byte[] abiEncodeForMintWrongBindingSignature(ShieldedTRC20Parameters params, long value, - byte[] frontier, long leafCount) { - byte[] mergedBytes; - ShieldContract.ReceiveDescription revDesc = params.getReceiveDescription(0); - mergedBytes = ByteUtil.merge( - revDesc.getNoteCommitment().toByteArray(), - revDesc.getValueCommitment().toByteArray(), - revDesc.getEpk().toByteArray(), - revDesc.getZkproof().toByteArray(), - Wallet.generateRandomBytes(64), - longTo32Bytes(value), - params.getMessageHash().toByteArray(), - frontier, - longTo32Bytes(leafCount) - ); - return mergedBytes; - } - private byte[] abiEncodeForMintWrongHash(ShieldedTRC20Parameters params, long value, byte[] frontier, long leafCount) { byte[] mergedBytes; @@ -4474,7 +4504,7 @@ private byte[] longTo32Bytes(long value) { } private long randomLong() { - return (long) Math.round(Math.random() * Long.MAX_VALUE / 2); + return Math.round(Math.random() * Long.MAX_VALUE / 2); } } diff --git a/framework/src/test/java/org/tron/core/tire/TrieTest.java b/framework/src/test/java/org/tron/core/tire/TrieTest.java index 103972b2e91..ba5c536c987 100644 --- a/framework/src/test/java/org/tron/core/tire/TrieTest.java +++ b/framework/src/test/java/org/tron/core/tire/TrieTest.java @@ -136,7 +136,7 @@ public void testOrder() { trie2.put(RLP.encodeInt(i), String.valueOf(i).getBytes()); } byte[] rootHash2 = trie2.getRootHash(); - Assert.assertTrue(java.util.Arrays.equals(rootHash1, rootHash2)); + Assert.assertArrayEquals(rootHash1, rootHash2); } private void assertTrue(byte[] key, TrieImpl trieCopy) { diff --git a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java index d0a3d153d7d..aa2400a2a25 100644 --- a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java +++ b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java @@ -8,9 +8,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Ignore; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.tron.api.WalletGrpc; import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; @@ -35,9 +33,6 @@ public class LiteFullNodeToolTest { private Application appTest; private String databaseDir; - @Rule - public ExpectedException thrown = ExpectedException.none(); - private static final String DB_PATH = "output_lite_fn"; /** diff --git a/framework/src/test/java/org/tron/program/SolidityNodeTest.java b/framework/src/test/java/org/tron/program/SolidityNodeTest.java index b9989f9c002..7cb3ac9823f 100755 --- a/framework/src/test/java/org/tron/program/SolidityNodeTest.java +++ b/framework/src/test/java/org/tron/program/SolidityNodeTest.java @@ -21,7 +21,7 @@ public class SolidityNodeTest { private static TronApplicationContext context; private static RpcApiService rpcApiService; - private static String dbPath = "output_witness_test"; + private static String dbPath = "output_sn_test"; static { Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); diff --git a/framework/src/test/java/org/tron/program/SupplementTest.java b/framework/src/test/java/org/tron/program/SupplementTest.java new file mode 100644 index 00000000000..5655ee4a098 --- /dev/null +++ b/framework/src/test/java/org/tron/program/SupplementTest.java @@ -0,0 +1,137 @@ +package org.tron.program; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.math.BigInteger; +import javax.annotation.Resource; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.tron.common.config.DbBackupConfig; +import org.tron.common.entity.PeerInfo; +import org.tron.common.utils.CompactEncoder; +import org.tron.common.utils.JsonUtil; +import org.tron.common.utils.Value; +import org.tron.core.Constant; +import org.tron.core.capsule.StorageRowCapsule; +import org.tron.core.capsule.utils.RLP; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.services.http.HttpSelfFormatFieldName; +import org.tron.core.store.StorageRowStore; +import org.tron.keystore.WalletUtils; + +@RunWith(SpringJUnit4ClassRunner.class) +@DirtiesContext +@ContextConfiguration(classes = {DefaultConfig.class}) +public class SupplementTest { + + private static final String dbPath = "output_coverage_test"; + + @Resource + private StorageRowStore storageRowStore; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @BeforeClass + public static void init() { + Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + } + + @Test + public void testGet() throws Exception { + StorageRowCapsule storageRowCapsule = storageRowStore.get(new byte[]{}); + assertNotNull(storageRowCapsule); + + DbBackupConfig dbBackupConfig = new DbBackupConfig(); + dbBackupConfig.initArgs(true, "propPath", "bak1path/", "bak2path/", 1); + + WalletUtils.generateFullNewWalletFile("123456", new File(dbPath)); + WalletUtils.generateLightNewWalletFile("123456", new File(dbPath)); + WalletUtils.getDefaultKeyDirectory(); + WalletUtils.getTestnetKeyDirectory(); + WalletUtils.getMainnetKeyDirectory(); + + Value value = new Value(new byte[]{1}); + value.asBytes(); + value = new Value(1); + value.asInt(); + value = new Value(100L); + value.asLong(); + value = new Value(new BigInteger("1000")); + value.asBigInt(); + value = new Value("1000"); + value.asString(); + value.isEmpty(); + value = new Value(new byte[]{1, 2, 3}); + value.isList(); + value.isReadableString(); + value.isHexString(); + value.isHashCode(); + value.isNull(); + value.length(); + assertNotNull(value.toString()); + value.countBranchNodes(); + + PeerInfo peerInfo = new PeerInfo(); + peerInfo.setAvgLatency(peerInfo.getAvgLatency()); + peerInfo.setBlockInPorcSize(peerInfo.getBlockInPorcSize()); + peerInfo.setConnectTime(peerInfo.getConnectTime()); + peerInfo.setDisconnectTimes(peerInfo.getDisconnectTimes()); + peerInfo.setHeadBlockTimeWeBothHave(peerInfo.getHeadBlockTimeWeBothHave()); + peerInfo.setHeadBlockWeBothHave(peerInfo.getHeadBlockWeBothHave()); + peerInfo.setHost(peerInfo.getHost()); + peerInfo.setInFlow(peerInfo.getInFlow()); + peerInfo.setLastBlockUpdateTime(peerInfo.getLastBlockUpdateTime()); + peerInfo.setLastSyncBlock(peerInfo.getLastSyncBlock()); + peerInfo.setLocalDisconnectReason(peerInfo.getLocalDisconnectReason()); + peerInfo.setNodeCount(peerInfo.getNodeCount()); + peerInfo.setNodeId(peerInfo.getNodeId()); + peerInfo.setRemainNum(peerInfo.getRemainNum()); + peerInfo.setRemoteDisconnectReason(peerInfo.getRemoteDisconnectReason()); + peerInfo.setScore(peerInfo.getScore()); + peerInfo.setPort(peerInfo.getPort()); + peerInfo.setSyncFlag(peerInfo.isSyncFlag()); + peerInfo.setNeedSyncFromPeer(peerInfo.isNeedSyncFromPeer()); + peerInfo.setNeedSyncFromUs(peerInfo.isNeedSyncFromUs()); + peerInfo.setSyncToFetchSize(peerInfo.getSyncToFetchSize()); + peerInfo.setSyncToFetchSizePeekNum(peerInfo.getSyncToFetchSizePeekNum()); + peerInfo.setSyncBlockRequestedSize(peerInfo.getSyncBlockRequestedSize()); + peerInfo.setUnFetchSynNum(peerInfo.getUnFetchSynNum()); + peerInfo.setActive(peerInfo.isActive()); + + assertNotNull(JsonUtil.json2Obj("{}", PeerInfo.class)); + assertNotNull(JsonUtil.obj2Json(peerInfo)); + + assertTrue(HttpSelfFormatFieldName.isAddressFormat( + "protocol.DelegatedResourceMessage.fromAddress")); + assertTrue(HttpSelfFormatFieldName.isNameStringFormat( + "protocol.MarketPriceList.buy_token_id")); + + CompactEncoder.packNibbles(new byte[] {1,2,3,4,5,6,7}); + assertFalse(CompactEncoder.hasTerminator(new byte[] {1,2,3,4,5,6,7})); + CompactEncoder.unpackToNibbles(new byte[] {1,2,3,4,5,6,7}); + CompactEncoder.binToNibblesNoTerminator(new byte[] {1,2,3,4,5,6,7}); + + assertNotNull(RLP.decodeIP4Bytes(new byte[] {1,2,3,4,5,6,7}, 0)); + RLP.decodeByteArray(new byte[] {1,2,3,4,5,6,7}, 0); + RLP.nextItemLength(new byte[] {1,2,3,4,5,6,7}, 0); + RLP.decodeStringItem(new byte[] {1,2,3,4,5,6,7}, 0); + RLP.decodeInt(new byte[] {1,2,3,4,5,6,7}, 0); + RLP.decode2OneItem(new byte[] {1,2,3,4,5,6,7}, 0); + RLP.decode2(new byte[] {1,2,3,4,5,6,7}, 1); + RLP.decode2(new byte[] {1,2,3,4,5,6,7}); + thrown.expect(ClassCastException.class); + RLP.unwrapList(new byte[] {1,2,3,4,5,6,7}); + } + +} From a3628fda8dbe64344823b8a84ab1e11025586e28 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 14 Feb 2023 17:30:45 +0800 Subject: [PATCH 0584/1197] fix(net):change the default IP of the node --- framework/src/main/java/org/tron/core/config/args/Args.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 905b2c6cf9e..8e6a7526362 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1351,8 +1351,8 @@ private static void bindIp(final com.typesafe.config.Config config) { PARAMETER.nodeDiscoveryBindIp = s.getLocalAddress().getHostAddress(); logger.info("UDP local bound to: {}", PARAMETER.nodeDiscoveryBindIp); } catch (IOException e) { - logger.warn("Can't get bind IP. Fall back to 0.0.0.0: " + e); - PARAMETER.nodeDiscoveryBindIp = "0.0.0.0"; + logger.warn("Can't get bind IP. Fall back to 127.0.0.1: " + e); + PARAMETER.nodeDiscoveryBindIp = "127.0.0.1"; } } } else { From ab07d2fe2b8d4c1392e625efc95d031c433f4b07 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 14 Feb 2023 18:05:48 +0800 Subject: [PATCH 0585/1197] fix(net):change the log level of bad message from warn to error --- .../main/java/org/tron/core/net/P2pEventHandlerImpl.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java index 94f8191323b..f6a01b1cf95 100644 --- a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java +++ b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java @@ -221,8 +221,13 @@ private void processException(PeerConnection peer, TronMessage msg, Exception ex code = Protocol.ReasonCode.UNKNOWN; break; } - logger.warn("Message from {} process failed, {} \n type: {}, detail: {}", - peer.getInetSocketAddress(), msg, type, ex.getMessage()); + if (type.equals(P2pException.TypeEnum.BAD_MESSAGE)) { + logger.error("Message from {} process failed, {} \n type: {}", + peer.getInetSocketAddress(), msg, type, ex); + } else { + logger.warn("Message from {} process failed, {} \n type: {}, detail: {}", + peer.getInetSocketAddress(), msg, type, ex.getMessage()); + } } else { code = Protocol.ReasonCode.UNKNOWN; logger.warn("Message from {} process failed, {}", From b41826f415b2326ad022048480b451b10e939a9b Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 14 Feb 2023 18:54:38 +0800 Subject: [PATCH 0586/1197] fix(net):fix the issue of fast forwarding service --- framework/src/main/java/org/tron/core/net/TronNetService.java | 1 + .../src/main/java/org/tron/core/net/peer/PeerConnection.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index fc4a3e8eee2..dcee7ecc7b2 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -139,6 +139,7 @@ private P2pConfig getConfig() { config.setActiveNodes(parameter.getActiveNodes()); config.setTrustNodes(parameter.getPassiveNodes()); config.getActiveNodes().forEach(n -> config.getTrustNodes().add(n.getAddress())); + parameter.getFastForwardNodes().forEach(f -> config.getTrustNodes().add(f.getAddress())); int maxConnections = parameter.getMaxConnections(); int minConnections = parameter.getMinConnections(); int minActiveConnections = parameter.getMinActiveConnections(); diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index 5626c072864..aafb0e30806 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -147,7 +147,7 @@ public class PeerConnection { public void setChannel(Channel channel) { this.channel = channel; - if (relayNodes.contains(channel.getInetSocketAddress())) { + if (relayNodes.stream().anyMatch(n -> n.getAddress().equals(channel.getInetAddress()))) { this.isRelayPeer = true; } this.nodeStatistics = TronStatsManager.getNodeStatistics(channel.getInetAddress()); From 9e086c756a40997a7cb52f679f14559b94a327c3 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 15 Feb 2023 11:54:12 +0800 Subject: [PATCH 0587/1197] add fastForwardNode to activeNodes only if not exist --- .../java/org/tron/core/net/service/relay/RelayService.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java index 478f0714875..686799bdf81 100644 --- a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java @@ -171,8 +171,11 @@ private boolean isActiveWitness() { } private void connect() { - fastForwardNodes.forEach(address -> - TronNetService.getP2pConfig().getActiveNodes().add(address)); + for (InetSocketAddress fastForwardNode : fastForwardNodes) { + if (!TronNetService.getP2pConfig().getActiveNodes().contains(fastForwardNode)) { + TronNetService.getP2pConfig().getActiveNodes().add(fastForwardNode); + } + } } private void disconnect() { From a5f9c6f6a8152e1fa784ded42d6d35677a4015c2 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 15 Feb 2023 12:21:30 +0800 Subject: [PATCH 0588/1197] fix(net): solve the problem of obtaining the same block during block synchronization --- .../tron/core/net/service/sync/SyncService.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index f9351199b3e..91d9bc96d78 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -50,7 +50,7 @@ public class SyncService { private Map blockJustReceived = new ConcurrentHashMap<>(); private long blockCacheTimeout = Args.getInstance().getBlockCacheTimeout(); - private Cache requestBlockIds = CacheBuilder.newBuilder().maximumSize(10_000) + private Cache requestBlockIds = CacheBuilder.newBuilder().maximumSize(10_000) .expireAfterWrite(blockCacheTimeout, TimeUnit.MINUTES).initialCapacity(10_000) .recordStats().build(); @@ -138,13 +138,16 @@ public void processBlock(PeerConnection peer, BlockMessage blockMessage) { public void onDisconnect(PeerConnection peer) { if (!peer.getSyncBlockRequested().isEmpty()) { - peer.getSyncBlockRequested().keySet().forEach(blockId -> invalid(blockId)); + peer.getSyncBlockRequested().keySet().forEach(blockId -> invalid(blockId, peer)); } } - private void invalid(BlockId blockId) { - requestBlockIds.invalidate(blockId); - fetchFlag = true; + private void invalid(BlockId blockId, PeerConnection peerConnection) { + PeerConnection p = requestBlockIds.getIfPresent(blockId); + if (peerConnection.equals(p)) { + requestBlockIds.invalidate(blockId); + fetchFlag = true; + } } private LinkedList getBlockChainSummary(PeerConnection peer) throws P2pException { @@ -209,7 +212,7 @@ private void startFetchSyncBlock() { } for (BlockId blockId : peer.getSyncBlockToFetch()) { if (requestBlockIds.getIfPresent(blockId) == null) { - requestBlockIds.put(blockId, System.currentTimeMillis()); + requestBlockIds.put(blockId, peer); peer.getSyncBlockRequested().put(blockId, System.currentTimeMillis()); send.get(peer).add(blockId); if (send.get(peer).size() >= MAX_BLOCK_FETCH_PER_PEER) { @@ -243,7 +246,7 @@ private synchronized void handleSyncBlock() { synchronized (tronNetDelegate.getBlockLock()) { if (peerConnection.isDisconnect()) { blockWaitToProcess.remove(msg); - invalid(msg.getBlockId()); + invalid(msg.getBlockId(), peerConnection); return; } final boolean[] isFound = {false}; From ced6fce5cec162672531160590b86094f290f229 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 15 Feb 2023 14:58:07 +0800 Subject: [PATCH 0589/1197] update PeerConnection --- .../src/main/java/org/tron/core/net/peer/PeerConnection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index d15725ebf3f..ba972ed7b7c 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -147,7 +147,7 @@ public class PeerConnection { public void setChannel(Channel channel) { this.channel = channel; - if (relayNodes.contains(channel.getInetSocketAddress())) { + if (relayNodes.stream().anyMatch(n -> n.getAddress().equals(channel.getInetAddress()))) { this.isRelayPeer = true; } this.nodeStatistics = TronStatsManager.getNodeStatistics(channel.getInetAddress()); From 5a70a07f45713936cc9370fcd6086a69f4db7e81 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 15 Feb 2023 16:07:42 +0800 Subject: [PATCH 0590/1197] fet(net): olve the problem of reporting 'no need sync' --- .../core/net/messagehandler/ChainInventoryMsgHandler.java | 3 +++ .../src/main/java/org/tron/core/net/peer/PeerConnection.java | 4 ++++ .../main/java/org/tron/core/net/service/sync/SyncService.java | 4 +++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java index 9b71f6f185a..7db1cd9e1ec 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java @@ -39,6 +39,8 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep check(peer, chainInventoryMessage); + peer.setFetchAble(false); + peer.setNeedSyncFromPeer(true); peer.setSyncChainRequested(null); @@ -85,6 +87,7 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep if ((chainInventoryMessage.getRemainNum() == 0 && !peer.getSyncBlockToFetch().isEmpty()) || (chainInventoryMessage.getRemainNum() != 0 && peer.getSyncBlockToFetch().size() > NetConstants.SYNC_FETCH_BATCH_NUM)) { + peer.setFetchAble(true); syncService.setFetchFlag(true); } else { syncService.syncNext(peer); diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index aafb0e30806..a13240fa8ff 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -67,6 +67,10 @@ public class PeerConnection { @Setter private volatile boolean isRelayPeer; + @Setter + @Getter + private volatile boolean fetchAble; + @Getter @Setter private ByteString address; diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 91d9bc96d78..733dd5e62c8 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -50,7 +50,8 @@ public class SyncService { private Map blockJustReceived = new ConcurrentHashMap<>(); private long blockCacheTimeout = Args.getInstance().getBlockCacheTimeout(); - private Cache requestBlockIds = CacheBuilder.newBuilder().maximumSize(10_000) + private Cache requestBlockIds = CacheBuilder.newBuilder() + .maximumSize(10_000) .expireAfterWrite(blockCacheTimeout, TimeUnit.MINUTES).initialCapacity(10_000) .recordStats().build(); @@ -206,6 +207,7 @@ private void startFetchSyncBlock() { HashMap> send = new HashMap<>(); tronNetDelegate.getActivePeer().stream() .filter(peer -> peer.isNeedSyncFromPeer() && peer.isIdle()) + .filter(peer -> peer.isFetchAble()) .forEach(peer -> { if (!send.containsKey(peer)) { send.put(peer, new LinkedList<>()); From d585cf3ff0ce9b2afb8bddfd57ff1e8893833aeb Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 15 Feb 2023 16:08:39 +0800 Subject: [PATCH 0591/1197] solve check style problem --- .../main/java/org/tron/core/net/service/sync/SyncService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 91d9bc96d78..10ce83eb198 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -50,7 +50,8 @@ public class SyncService { private Map blockJustReceived = new ConcurrentHashMap<>(); private long blockCacheTimeout = Args.getInstance().getBlockCacheTimeout(); - private Cache requestBlockIds = CacheBuilder.newBuilder().maximumSize(10_000) + private Cache requestBlockIds = CacheBuilder.newBuilder() + .maximumSize(10_000) .expireAfterWrite(blockCacheTimeout, TimeUnit.MINUTES).initialCapacity(10_000) .recordStats().build(); From 4413df5814d88dfc7444950f5ead6d7244aa9606 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 15 Feb 2023 17:36:16 +0800 Subject: [PATCH 0592/1197] support to read ipv6 address from config file --- .../java/org/tron/core/config/args/Args.java | 24 +++++++++++++++---- .../org/tron/core/net/TronNetService.java | 6 +++-- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 9678001d02b..f6ff13f01c4 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1186,21 +1186,24 @@ private static RateLimiterInitialization getRateLimiterFromConfig( } private static List getInetSocketAddress( - final com.typesafe.config.Config config, String path) { + final com.typesafe.config.Config config, String path) { List ret = new ArrayList<>(); if (!config.hasPath(path)) { return ret; } List list = config.getStringList(path); for (String configString : list) { - String[] sz = configString.split(":"); - String ip = sz[0]; - int port = Integer.parseInt(sz[1]); + InetSocketAddress inetSocketAddress = parseInetSocketAddress(configString); + if (inetSocketAddress == null) { + continue; + } + String ip = inetSocketAddress.getAddress().getHostAddress(); + int port = inetSocketAddress.getPort(); if (!(PARAMETER.nodeDiscoveryBindIp.equals(ip) || PARAMETER.nodeExternalIp.equals(ip) || Constant.LOCAL_HOST.equals(ip)) || PARAMETER.nodeListenPort != port) { - ret.add(new InetSocketAddress(ip, port)); + ret.add(inetSocketAddress); } } return ret; @@ -1612,5 +1615,16 @@ public String getOutputDirectory() { } return this.outputDirectory; } + + public static InetSocketAddress parseInetSocketAddress(String para) { + InetSocketAddress address = null; + int index = para.lastIndexOf(":"); + if (index > 0) { + String host = para.substring(0, index); + int port = Integer.parseInt(para.substring(index + 1)); + address = new InetSocketAddress(host, port); + } + return address; + } } diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 0e3fc21efb6..78de59a0619 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -131,8 +131,10 @@ private P2pConfig getConfig() { List seeds = new ArrayList<>(); seeds.addAll(nodePersistService.dbRead()); for (String s : parameter.getSeedNode().getIpList()) { - String[] sz = s.split(":"); - seeds.add(new InetSocketAddress(sz[0], Integer.parseInt(sz[1]))); + InetSocketAddress inetSocketAddress = Args.parseInetSocketAddress(s); + if (inetSocketAddress != null) { + seeds.add(inetSocketAddress); + } } P2pConfig config = new P2pConfig(); From 15b36cc71fb3ce6277489ec616499bfa0659c8c0 Mon Sep 17 00:00:00 2001 From: chaozhu Date: Wed, 15 Feb 2023 18:51:06 +0800 Subject: [PATCH 0593/1197] feat(stake2.0): optimize code, remove useless code --- .../solidity/SolidityNodeHttpApiService.java | 26 +------------------ 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java index 9fc62f36fd2..534bc504c82 100644 --- a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java @@ -14,9 +14,7 @@ import org.tron.common.parameter.CommonParameter; import org.tron.core.config.args.Args; import org.tron.core.services.filter.HttpApiAccessFilter; -import org.tron.core.services.http.DelegateResourceServlet; import org.tron.core.services.http.EstimateEnergyServlet; -import org.tron.core.services.http.FreezeBalanceV2Servlet; import org.tron.core.services.http.FullNodeHttpApiService; import org.tron.core.services.http.GetAccountByIdServlet; import org.tron.core.services.http.GetAccountServlet; @@ -61,9 +59,6 @@ import org.tron.core.services.http.ScanShieldedTRC20NotesByIvkServlet; import org.tron.core.services.http.ScanShieldedTRC20NotesByOvkServlet; import org.tron.core.services.http.TriggerConstantContractServlet; -import org.tron.core.services.http.UnDelegateResourceServlet; -import org.tron.core.services.http.UnFreezeBalanceV2Servlet; -import org.tron.core.services.http.WithdrawExpireUnfreezeServlet; @Component @@ -174,16 +169,6 @@ public class SolidityNodeHttpApiService implements Service { @Autowired private GetBlockServlet getBlockServlet; - @Autowired - private FreezeBalanceV2Servlet freezeBalanceV2Servlet; - @Autowired - private UnFreezeBalanceV2Servlet unFreezeBalanceV2Servlet; - @Autowired - private WithdrawExpireUnfreezeServlet withdrawExpireUnfreezeServlet; - @Autowired - private DelegateResourceServlet delegateResourceServlet; - @Autowired - private UnDelegateResourceServlet unDelegateResourceServlet; @Override public void init() { @@ -299,16 +284,7 @@ public void start() { context.addServlet(new ServletHolder(getRewardServlet), "/walletsolidity/getReward"); context.addServlet(new ServletHolder(getBurnTrxServlet), "/walletsolidity/getburntrx"); context.addServlet(new ServletHolder(getBlockServlet), "/walletsolidity/getblock"); - context.addServlet(new ServletHolder(freezeBalanceV2Servlet), - "/walletsolidity/freezebalancev2"); - context.addServlet(new ServletHolder(unFreezeBalanceV2Servlet), - "/walletsolidity/unfreezebalancev2"); - context.addServlet(new ServletHolder(withdrawExpireUnfreezeServlet), - "/walletsolidity/withdrawexpireunfreeze"); - context.addServlet(new ServletHolder(delegateResourceServlet), - "/walletsolidity/delegateresource"); - context.addServlet(new ServletHolder(unDelegateResourceServlet), - "/walletsolidity/undelegateresource"); + // http access filter context.addFilter(new FilterHolder(httpApiAccessFilter), "/walletsolidity/*", EnumSet.allOf(DispatcherType.class)); From c2b6b8062edecd25512df074820b8953f40d4f8a Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 15 Feb 2023 18:52:51 +0800 Subject: [PATCH 0594/1197] add some log --- .../src/main/java/org/tron/core/net/TronNetService.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 78de59a0619..f5e14c5e545 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -74,7 +74,7 @@ public class TronNetService { private static void setP2pConfig(P2pConfig config) { TronNetService.p2pConfig = config; } - + public void start() { try { init = true; @@ -136,7 +136,9 @@ private P2pConfig getConfig() { seeds.add(inetSocketAddress); } } - + for (InetSocketAddress inetSocketAddress : seeds) { + logger.debug("Seed InetSocketAddress: {}", inetSocketAddress); + } P2pConfig config = new P2pConfig(); config.setSeedNodes(seeds); config.setActiveNodes(parameter.getActiveNodes()); From a82003c212eea55aaa30dada189b60fd16bd19ae Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 15 Feb 2023 19:11:36 +0800 Subject: [PATCH 0595/1197] optimize chain inventory message processing logic --- .../tron/core/net/messagehandler/ChainInventoryMsgHandler.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java index 7db1cd9e1ec..d1ee974cc64 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java @@ -80,14 +80,15 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep } catch (NoSuchElementException e) { logger.warn("Process ChainInventoryMessage failed, peer {}, isDisconnect:{}", peer.getInetAddress(), peer.isDisconnect()); + peer.setFetchAble(true); return; } } + peer.setFetchAble(true); if ((chainInventoryMessage.getRemainNum() == 0 && !peer.getSyncBlockToFetch().isEmpty()) || (chainInventoryMessage.getRemainNum() != 0 && peer.getSyncBlockToFetch().size() > NetConstants.SYNC_FETCH_BATCH_NUM)) { - peer.setFetchAble(true); syncService.setFetchFlag(true); } else { syncService.syncNext(peer); From e3995bf6282068c8f0f3ffce66064a1f65ea8895 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 15 Feb 2023 20:16:11 +0800 Subject: [PATCH 0596/1197] add some log --- framework/src/main/java/org/tron/core/net/TronNetService.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index f5e14c5e545..40f101f5b5a 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -166,6 +166,8 @@ private P2pConfig getConfig() { if (StringUtil.isNullOrEmpty(config.getIp()) && StringUtil.isNullOrEmpty(config.getIpv6())) { config.setIp(parameter.getNodeExternalIp()); } + logger.debug("Local ipv4: {}", config.getIp()); + logger.debug("Local ipv6: {}", config.getIpv6()); config.setTreeUrls(parameter.getDnsTreeUrls()); if (Objects.nonNull(parameter.getDnsPublishConfig())) { config.setPublishConfig(parameter.getDnsPublishConfig()); From 6c51cfff5c1a90eb0a07ced889dc423e926cf617 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 16 Feb 2023 12:28:46 +0800 Subject: [PATCH 0597/1197] feat(log): add encoder to avoid any external usage --- .../common/log/layout/MultiLayoutPattern.java | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 common/src/main/java/org/tron/common/log/layout/MultiLayoutPattern.java diff --git a/common/src/main/java/org/tron/common/log/layout/MultiLayoutPattern.java b/common/src/main/java/org/tron/common/log/layout/MultiLayoutPattern.java new file mode 100644 index 00000000000..9fde78c1a7b --- /dev/null +++ b/common/src/main/java/org/tron/common/log/layout/MultiLayoutPattern.java @@ -0,0 +1,106 @@ +package org.tron.common.log.layout; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.encoder.PatternLayoutEncoder; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.Layout; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MultiLayoutPattern extends PatternLayoutEncoder { + private List rules = new ArrayList<>(); + private Map> layoutMap = new HashMap<>(); + + public void addRule(Rule rule) { + this.rules.add(rule); + rule.start(context); + } + + public byte[] encode(ILoggingEvent event) { + Layout layout = getLayout(event.getLoggerName()); + String txt = layout.doLayout(event); + return convertToBytes(txt); + } + + private byte[] convertToBytes(String s) { + Charset charset = getCharset(); + if (charset == null) { + return s.getBytes(); + } else { + return s.getBytes(charset); + } + } + + private Layout getLayout(final String name) { + if (name == null) { + throw new IllegalArgumentException("name cannot be null"); + } + if (Logger.ROOT_LOGGER_NAME.equalsIgnoreCase(name)) { + return this.getLayout(); + } + if (layoutMap.containsKey(name)) { + return layoutMap.get(name); + } + Layout layout = getLayout(); + for (Rule rule : rules) { + if (rule.logger.equals(name)) { + layout = rule.getPatternLayoutEncoder().getLayout(); + break; + } + } + layoutMap.put(name, layout); + return layout; + } + + @Override + public void start() { + super.start(); + } + + public static class Rule { + private String logger; + private String pattern; + private PatternLayoutEncoder patternLayoutEncoder; + private boolean outputPatternAsHeader = false; + + public String getLogger() { + return logger; + } + + public void setLogger(String logger) { + this.logger = logger; + } + + public String getPattern() { + return pattern; + } + + public void setPattern(String pattern) { + this.pattern = pattern; + } + + public boolean isOutputPatternAsHeader() { + return outputPatternAsHeader; + } + + public void setOutputPatternAsHeader(boolean outputPatternAsHeader) { + this.outputPatternAsHeader = outputPatternAsHeader; + } + + public PatternLayoutEncoder getPatternLayoutEncoder() { + return patternLayoutEncoder; + } + + public void start(Context context) { + patternLayoutEncoder = new PatternLayoutEncoder(); + patternLayoutEncoder.setPattern(pattern); + patternLayoutEncoder.setContext(context); + patternLayoutEncoder.setOutputPatternAsHeader(outputPatternAsHeader); + patternLayoutEncoder.start(); + } + } +} \ No newline at end of file From 760a3dd51f2f49dcccc185a3ee83f2978662bbf5 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 16 Feb 2023 12:32:29 +0800 Subject: [PATCH 0598/1197] feat(net):update libp2p to beta version --- build.gradle | 166 +++++++++++++++++++++-------------------- framework/build.gradle | 3 +- 2 files changed, 86 insertions(+), 83 deletions(-) diff --git a/build.gradle b/build.gradle index 8ff739a1e4c..82760ffd8cf 100644 --- a/build.gradle +++ b/build.gradle @@ -1,82 +1,84 @@ -allprojects { - version = "1.0.0" - apply plugin: "java" -} - -subprojects { - apply plugin: "java" - apply plugin: "jacoco" - apply plugin: "maven" - apply plugin: "maven-publish" - - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - - [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' - - buildscript { - repositories { - mavenCentral() - maven { - url "https://plugins.gradle.org/m2/" - } - } - dependencies { - classpath 'com.google.protobuf:protobuf-gradle-plugin:0.9.1' - classpath "gradle.plugin.com.github.johnrengelman:shadow:7.1.2" - } - } - - repositories { - mavenLocal() - mavenCentral() - maven { url 'https://repo.spring.io/plugins-release' } - } - - dependencies { - compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25' - compile group: 'org.slf4j', name: 'jcl-over-slf4j', version: '1.7.25' - compile "org.slf4j:jcl-over-slf4j:1.7.25" - compile group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.9' - compileOnly 'org.projectlombok:lombok:1.18.12' - annotationProcessor 'org.projectlombok:lombok:1.18.12' - testCompileOnly 'org.projectlombok:lombok:1.18.12' - testAnnotationProcessor 'org.projectlombok:lombok:1.18.12' - compile group: 'com.google.guava', name: 'guava', version: '24.1-jre' - compile "com.google.code.findbugs:jsr305:3.0.0" - compile group: 'org.springframework', name: 'spring-context', version: '5.3.18' - compile group: 'org.springframework', name: 'spring-tx', version: '5.3.18' - compile "org.apache.commons:commons-lang3:3.4" - compile group: 'org.apache.commons', name: 'commons-math', version: '2.2' - compile "org.apache.commons:commons-collections4:4.1" - compile group: 'joda-time', name: 'joda-time', version: '2.3' - - } - - task sourcesJar(type: Jar, dependsOn: classes) { - classifier = "sources" - from sourceSets.main.allSource - } - - - tasks.withType(AbstractArchiveTask) { - preserveFileTimestamps = false - reproducibleFileOrder = true - } - - configurations.all { - resolutionStrategy { - force group: 'com.google.guava', name: 'guava', version: '30.1-jre' - } - } -} - -task copyToParent(type: Copy) { - into "$buildDir/libs" - subprojects { - from tasks.withType(Jar) - } -} - -build.finalizedBy(copyToParent) - +allprojects { + version = "1.0.0" + apply plugin: "java" +} + +subprojects { + apply plugin: "java" + apply plugin: "jacoco" + apply plugin: "maven" + apply plugin: "maven-publish" + + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + + [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' + + buildscript { + repositories { + mavenCentral() + maven { url 'https://jitpack.io/' } + maven { + url "https://plugins.gradle.org/m2/" + } + } + dependencies { + classpath 'com.google.protobuf:protobuf-gradle-plugin:0.9.1' + classpath "gradle.plugin.com.github.johnrengelman:shadow:7.1.2" + } + } + + repositories { + mavenLocal() + mavenCentral() + maven { url 'https://repo.spring.io/plugins-release' } + maven { url 'https://jitpack.io/' } + } + + dependencies { + compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25' + compile group: 'org.slf4j', name: 'jcl-over-slf4j', version: '1.7.25' + compile "org.slf4j:jcl-over-slf4j:1.7.25" + compile group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.9' + compileOnly 'org.projectlombok:lombok:1.18.12' + annotationProcessor 'org.projectlombok:lombok:1.18.12' + testCompileOnly 'org.projectlombok:lombok:1.18.12' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.12' + compile group: 'com.google.guava', name: 'guava', version: '24.1-jre' + compile "com.google.code.findbugs:jsr305:3.0.0" + compile group: 'org.springframework', name: 'spring-context', version: '5.3.18' + compile group: 'org.springframework', name: 'spring-tx', version: '5.3.18' + compile "org.apache.commons:commons-lang3:3.4" + compile group: 'org.apache.commons', name: 'commons-math', version: '2.2' + compile "org.apache.commons:commons-collections4:4.1" + compile group: 'joda-time', name: 'joda-time', version: '2.3' + + } + + task sourcesJar(type: Jar, dependsOn: classes) { + classifier = "sources" + from sourceSets.main.allSource + } + + + tasks.withType(AbstractArchiveTask) { + preserveFileTimestamps = false + reproducibleFileOrder = true + } + + configurations.all { + resolutionStrategy { + force group: 'com.google.guava', name: 'guava', version: '30.1-jre' + } + } +} + +task copyToParent(type: Copy) { + into "$buildDir/libs" + subprojects { + from tasks.withType(Jar) + } +} + +build.finalizedBy(copyToParent) + diff --git a/framework/build.gradle b/framework/build.gradle index 93757755446..8d7489bd6ec 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -48,7 +48,8 @@ dependencies { compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' - compile group: 'io.github.tronprotocol', name: 'libp2p', version: '0.1.2' + //compile group: 'io.github.tronprotocol', name: 'libp2p', version: '0.1.2' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.1.7' compile group: 'com.typesafe', name: 'config', version: '1.3.2' From b2656495553af3eca926efb0f5e94361ef1b9b36 Mon Sep 17 00:00:00 2001 From: forfreeday Date: Mon, 20 Feb 2023 11:18:55 +0800 Subject: [PATCH 0599/1197] feat(version): update Version 1. update to version 4.7.1 --- framework/src/main/java/org/tron/program/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index e1109bcc5b7..4f435b1b0cb 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -4,7 +4,7 @@ public class Version { public static final String VERSION_NAME = "GreatVoyage-v4.7.0-9-g9326a08dd9"; public static final String VERSION_CODE = "17596"; - private static final String VERSION = "4.7.0.1"; + private static final String VERSION = "4.7.1"; public static String getVersion() { return VERSION; From 14e904769828febca4889e0cd71ad3b327ccc0fb Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 20 Feb 2023 12:05:12 +0800 Subject: [PATCH 0600/1197] feat(net): optimize the logic of obtaining block ID --- .../org/tron/core/net/service/sync/SyncService.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 733dd5e62c8..5b8ea730e99 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -117,7 +117,7 @@ public void syncNext(PeerConnection peer) { peer.setSyncChainRequested(new Pair<>(chainSummary, System.currentTimeMillis())); peer.sendMessage(new SyncBlockChainMessage(chainSummary)); } catch (Exception e) { - logger.warn("Peer {} sync failed, reason: {}", peer.getInetAddress(), e.getMessage()); + logger.error("Peer {} sync failed, reason: {}", peer.getInetAddress(), e); peer.disconnect(ReasonCode.SYNC_FAIL); } } @@ -191,7 +191,7 @@ private LinkedList getBlockChainSummary(PeerConnection peer) throws P2p while (low <= realHigh) { if (low <= highNoFork) { - summary.offer(tronNetDelegate.getBlockIdByNum(low)); + summary.offer(getBlockIdByNum(low)); } else if (low <= high) { summary.offer(forkList.get((int) (low - highNoFork - 1))); } else { @@ -203,6 +203,14 @@ private LinkedList getBlockChainSummary(PeerConnection peer) throws P2p return summary; } + private BlockId getBlockIdByNum(long num) throws P2pException { + BlockId head = tronNetDelegate.getHeadBlockId(); + if (num == head.getNum()) { + return head; + } + return tronNetDelegate.getBlockIdByNum(num); + } + private void startFetchSyncBlock() { HashMap> send = new HashMap<>(); tronNetDelegate.getActivePeer().stream() From 092d9ceee78b72584bc5838979e0eb3e7ace8768 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 20 Feb 2023 14:08:50 +0800 Subject: [PATCH 0601/1197] feat(log): use AsyncAppender for DB --- framework/src/main/resources/logback.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/main/resources/logback.xml b/framework/src/main/resources/logback.xml index 39c7f463172..8dcf9b6c66b 100644 --- a/framework/src/main/resources/logback.xml +++ b/framework/src/main/resources/logback.xml @@ -60,6 +60,7 @@ 100 true + From 88620185dbfe3717d12b47c191bd87dc333655a8 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 20 Feb 2023 14:24:30 +0800 Subject: [PATCH 0602/1197] feat(db): add sending timeout of zmq --- .../tron/common/logsfilter/nativequeue/NativeMessageQueue.java | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java b/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java index cf2fe6dce0a..a1e932bfaeb 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java +++ b/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java @@ -29,6 +29,7 @@ public static NativeMessageQueue getInstance() { public boolean start(int bindPort, int sendQueueLength) { context = new ZContext(); publisher = context.createSocket(SocketType.PUB); + publisher.setSendTimeOut(1000); if (Objects.isNull(publisher)) { return false; From 69deaae7b42376565c6fa7699a9cf4b94de5b8de Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 20 Feb 2023 15:18:18 +0800 Subject: [PATCH 0603/1197] fix(db): use constant ZMQ_SEND_TIME_OUT --- .../tron/common/logsfilter/nativequeue/NativeMessageQueue.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java b/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java index a1e932bfaeb..0a40bd18ecd 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java +++ b/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java @@ -11,6 +11,7 @@ public class NativeMessageQueue { private static final int DEFAULT_BIND_PORT = 5555; private static final int DEFAULT_QUEUE_LENGTH = 1000; + private static final int ZMQ_SEND_TIME_OUT = 1_000; private static NativeMessageQueue instance; private ZContext context = null; private ZMQ.Socket publisher = null; @@ -29,7 +30,7 @@ public static NativeMessageQueue getInstance() { public boolean start(int bindPort, int sendQueueLength) { context = new ZContext(); publisher = context.createSocket(SocketType.PUB); - publisher.setSendTimeOut(1000); + publisher.setSendTimeOut(ZMQ_SEND_TIME_OUT); if (Objects.isNull(publisher)) { return false; From 6b2a7f9dc54d3ccbb1a2b8701488f8c4f18910f3 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 20 Feb 2023 17:12:54 +0800 Subject: [PATCH 0604/1197] fix(net): optimize log of P2pEventHandlerImpl --- .../src/main/java/org/tron/core/net/P2pEventHandlerImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java index f6a01b1cf95..66774a216f2 100644 --- a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java +++ b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java @@ -222,10 +222,10 @@ private void processException(PeerConnection peer, TronMessage msg, Exception ex break; } if (type.equals(P2pException.TypeEnum.BAD_MESSAGE)) { - logger.error("Message from {} process failed, {} \n type: {}", + logger.error("Message from {} process failed, {} \n type: ({})", peer.getInetSocketAddress(), msg, type, ex); } else { - logger.warn("Message from {} process failed, {} \n type: {}, detail: {}", + logger.warn("Message from {} process failed, {} \n type: ({}), detail: {}", peer.getInetSocketAddress(), msg, type, ex.getMessage()); } } else { From 14c1c80bc08861d6ce4bff424f23472e43e26665 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 20 Feb 2023 17:41:27 +0800 Subject: [PATCH 0605/1197] fix(db): reorder setSendTimeOut function --- .../tron/common/logsfilter/nativequeue/NativeMessageQueue.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java b/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java index 0a40bd18ecd..e79a0973c1a 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java +++ b/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java @@ -30,12 +30,11 @@ public static NativeMessageQueue getInstance() { public boolean start(int bindPort, int sendQueueLength) { context = new ZContext(); publisher = context.createSocket(SocketType.PUB); - publisher.setSendTimeOut(ZMQ_SEND_TIME_OUT); if (Objects.isNull(publisher)) { return false; } - + publisher.setSendTimeOut(ZMQ_SEND_TIME_OUT); if (bindPort == 0 || bindPort < 0) { bindPort = DEFAULT_BIND_PORT; } From e860b0b2897bad093b2ea3661b72646502f7a86c Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 21 Feb 2023 12:30:05 +0800 Subject: [PATCH 0606/1197] fix(db): revert timeout of sending data to zmq --- .../tron/common/logsfilter/nativequeue/NativeMessageQueue.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java b/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java index e79a0973c1a..cf2fe6dce0a 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java +++ b/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java @@ -11,7 +11,6 @@ public class NativeMessageQueue { private static final int DEFAULT_BIND_PORT = 5555; private static final int DEFAULT_QUEUE_LENGTH = 1000; - private static final int ZMQ_SEND_TIME_OUT = 1_000; private static NativeMessageQueue instance; private ZContext context = null; private ZMQ.Socket publisher = null; @@ -34,7 +33,7 @@ public boolean start(int bindPort, int sendQueueLength) { if (Objects.isNull(publisher)) { return false; } - publisher.setSendTimeOut(ZMQ_SEND_TIME_OUT); + if (bindPort == 0 || bindPort < 0) { bindPort = DEFAULT_BIND_PORT; } From 53ddc27bbbdffc3fbb0fd2a03ed6cc98949b2c8a Mon Sep 17 00:00:00 2001 From: "morgan.peng" Date: Tue, 14 Feb 2023 19:15:36 +0800 Subject: [PATCH 0607/1197] feat(db): optimize the auto-stop logic 1. provide data query service when auto stop --- .../tron/common/parameter/CommonParameter.java | 5 +++++ .../tron/common/application/ApplicationImpl.java | 4 ++-- .../src/main/java/org/tron/core/Wallet.java | 16 +++++++++------- .../java/org/tron/core/config/args/Args.java | 1 + .../src/main/java/org/tron/core/db/Manager.java | 2 +- .../org/tron/core/services/RpcApiService.java | 9 +-------- .../org/tron/common/config/args/ArgsTest.java | 5 +++-- 7 files changed, 22 insertions(+), 20 deletions(-) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 571ab968671..8970a53dca2 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -403,6 +403,11 @@ public class CommonParameter { public GenesisBlock genesisBlock; @Getter @Setter + @Parameter(names = {"--p2p-disable"}, description = "Switch for p2p module initialization. " + + "(defalut: false)", arity = 1) + public boolean p2pDisable = false; + @Getter + @Setter public List activeNodes; @Getter @Setter diff --git a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java index 235ece75835..78395f63a78 100644 --- a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java +++ b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java @@ -57,7 +57,7 @@ public void initServices(CommonParameter parameter) { * start up the app. */ public void startup() { - if (!Args.getInstance().isSolidityNode()) { + if ((!Args.getInstance().isSolidityNode()) && (!Args.getInstance().isP2pDisable())) { tronNetService.start(); } consensusService.start(); @@ -67,7 +67,7 @@ public void startup() { @Override public void shutdown() { logger.info("******** start to shutdown ********"); - if (!Args.getInstance().isSolidityNode()) { + if (!Args.getInstance().isSolidityNode() && (!Args.getInstance().p2pDisable)) { tronNetService.close(); } consensusService.stop(); diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index bcefbb9b2f1..e89431dabcf 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2633,13 +2633,15 @@ public TransactionInfoList getTransactionInfoByBlockNum(long blockNum) { public NodeList listNodes() { NodeList.Builder nodeListBuilder = NodeList.newBuilder(); - TronNetService.getP2pService().getConnectableNodes().forEach(node -> { - nodeListBuilder.addNodes(Node.newBuilder().setAddress( - Address.newBuilder() - .setHost(ByteString - .copyFrom(ByteArray.fromString(node.getHost()))) - .setPort(node.getPort()))); - }); + if (!Args.getInstance().p2pDisable) { + TronNetService.getP2pService().getConnectableNodes().forEach(node -> { + nodeListBuilder.addNodes(Node.newBuilder().setAddress( + Address.newBuilder() + .setHost(ByteString + .copyFrom(ByteArray.fromString(node.getHost()))) + .setPort(node.getPort()))); + }); + } return nodeListBuilder.build(); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index f27ff3c2385..933d59f4f5c 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -221,6 +221,7 @@ public static void clearParam() { PARAMETER.allowNewRewardAlgorithm = 0; PARAMETER.allowNewReward = 0; PARAMETER.memoFee = 0; + PARAMETER.p2pDisable = false; } /** diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index b43387ec4f6..7a6520074a9 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -714,7 +714,7 @@ private void initAutoStop() { exitCount, blockTime)); } - if (exitHeight == headNum) { + if (exitHeight == headNum && (!Args.getInstance().isP2pDisable())) { logger.info("Auto-stop hit: shutDownBlockHeight: {}, currentHeaderNum: {}, exit now", exitHeight, headNum); System.exit(0); diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index a6e1c5181ad..a81be8f7728 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -1736,14 +1736,7 @@ public void getTransactionCountByBlockNum(NumberMessage request, @Override public void listNodes(EmptyMessage request, StreamObserver responseObserver) { - NodeList.Builder nodeListBuilder = NodeList.newBuilder(); - TronNetService.getP2pService().getConnectableNodes().forEach(node -> { - nodeListBuilder.addNodes(Node.newBuilder().setAddress( - Address.newBuilder() - .setHost(ByteString.copyFrom(ByteArray.fromString(node.getHost()))) - .setPort(node.getPort()))); - }); - responseObserver.onNext(nodeListBuilder.build()); + responseObserver.onNext(wallet.listNodes()); responseObserver.onCompleted(); } diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index 5b391f0d38d..6d698af10e6 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -13,8 +13,8 @@ public class ArgsTest { @Before public void init() { - Args.setParam(new String[]{"--output-directory", "output-directory", "--debug"}, - Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", "output-directory", "--p2p-disable", "true", + "--debug"}, Constant.TEST_CONF); } @After @@ -30,5 +30,6 @@ public void testConfig() { Assert.assertEquals(Args.getInstance().getNodeDiscoveryPingTimeout(), 15_000); Assert.assertEquals(Args.getInstance().getMaxFastForwardNum(), 3); Assert.assertEquals(Args.getInstance().getBlockCacheTimeout(), 60); + Assert.assertEquals(Args.getInstance().p2pDisable, true); } } \ No newline at end of file From 8fd659ff2c2d3df0b66e0637e9fbd49451402358 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 21 Feb 2023 12:08:11 +0800 Subject: [PATCH 0608/1197] feature(consensus): optimize signatures --- .../java/org/tron/common/utils/ForkController.java | 3 +++ .../java/org/tron/core/capsule/TransactionCapsule.java | 10 ++++++++++ .../src/main/java/org/tron/core/config/Parameter.java | 5 +++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/utils/ForkController.java b/chainbase/src/main/java/org/tron/common/utils/ForkController.java index db4d77fd809..89ffcbd111f 100644 --- a/chainbase/src/main/java/org/tron/common/utils/ForkController.java +++ b/chainbase/src/main/java/org/tron/common/utils/ForkController.java @@ -44,6 +44,9 @@ public boolean pass(ForkBlockVersionEnum forkBlockVersionEnum) { } public synchronized boolean pass(int version) { + if (manager == null) { + throw new IllegalStateException("not inited"); + } if (version > ForkBlockVersionEnum.VERSION_4_0.getValue()) { return passNew(version); } else { diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java index 1d043ef112b..1b6bf0722d4 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -46,9 +46,11 @@ import org.tron.common.overlay.message.Message; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.ForkController; import org.tron.common.utils.ReflectUtils; import org.tron.common.utils.Sha256Hash; import org.tron.core.actuator.TransactionFactory; +import org.tron.core.config.Parameter; import org.tron.core.db.TransactionContext; import org.tron.core.db.TransactionTrace; import org.tron.core.exception.BadItemException; @@ -213,6 +215,11 @@ public static long getWeight(Permission permission, byte[] address) { return 0; } + /** + * make sure ForkController.init(ChainBaseManager) is invoked before invoke this method. + * + * @see ForkController#init(org.tron.core.ChainBaseManager) + */ public static long checkWeight(Permission permission, List sigs, byte[] hash, List approveList) throws SignatureException, PermissionException, SignatureFormatException { @@ -237,6 +244,9 @@ public static long checkWeight(Permission permission, List sigs, byt ByteArray.toHexString(sig.toByteArray()) + " is signed by " + encode58Check(address) + " but it is not contained of permission."); } + if (ForkController.instance().pass(Parameter.ForkBlockVersionEnum.VERSION_4_7_1)) { + base64 = encode58Check(address); + } if (addMap.containsKey(base64)) { throw new PermissionException(encode58Check(address) + " has signed twice!"); } diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index 16517f4664b..7116e1e7141 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -20,7 +20,8 @@ public enum ForkBlockVersionEnum { VERSION_4_4(23, 1596780000000L, 80), VERSION_4_5(24, 1596780000000L, 80), VERSION_4_6(25, 1596780000000L, 80), - VERSION_4_7(26, 1596780000000L, 80); + VERSION_4_7(26, 1596780000000L, 80), + VERSION_4_7_1(27, 1596780000000L, 80); // if add a version, modify BLOCK_VERSION simultaneously @Getter @@ -69,7 +70,7 @@ public class ChainConstant { public static final int SINGLE_REPEAT = 1; public static final int BLOCK_FILLED_SLOTS_NUMBER = 128; public static final int MAX_FROZEN_NUMBER = 1; - public static final int BLOCK_VERSION = 26; + public static final int BLOCK_VERSION = 27; public static final long FROZEN_PERIOD = 86_400_000L; public static final long DELEGATE_PERIOD = 3 * 86_400_000L; public static final long TRX_PRECISION = 1000_000L; From acdb2e5210beb4106de3a3eb86f0325022d080be Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 21 Feb 2023 20:28:09 +0800 Subject: [PATCH 0609/1197] feat(net):update libp2p to latest version --- framework/build.gradle | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/framework/build.gradle b/framework/build.gradle index 8d7489bd6ec..f708733d4e2 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -48,8 +48,7 @@ dependencies { compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' - //compile group: 'io.github.tronprotocol', name: 'libp2p', version: '0.1.2' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.1.7' + compile group: 'io.github.tronprotocol', name: 'libp2p', version: '0.1.3' compile group: 'com.typesafe', name: 'config', version: '1.3.2' From e71b33b6210ae702d99c8c14d4746a8abdb8f32c Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 22 Feb 2023 12:24:48 +0800 Subject: [PATCH 0610/1197] feat(net): remove redundant logic after libp2p upgrade --- .../java/org/tron/core/net/TronNetService.java | 5 ----- .../net/service/handshake/HandshakeService.java | 15 --------------- .../net/service/keepalive/KeepAliveService.java | 6 ------ 3 files changed, 26 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 40f101f5b5a..5eea2e5a45f 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -52,9 +52,6 @@ public class TronNetService { @Autowired private FetchBlockService fetchBlockService; - @Autowired - private KeepAliveService keepAliveService; - private CommonParameter parameter = Args.getInstance(); @Autowired @@ -86,7 +83,6 @@ public void start() { peerStatusCheck.init(); transactionsMsgHandler.init(); fetchBlockService.init(); - keepAliveService.init(); nodePersistService.init(); tronStatsManager.init(); PeerManager.init(); @@ -104,7 +100,6 @@ public void close() { PeerManager.close(); tronStatsManager.close(); nodePersistService.close(); - keepAliveService.close(); advService.close(); syncService.close(); peerStatusCheck.close(); diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java index 6c9e53c3a98..04ef5d1d5c5 100644 --- a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -36,13 +36,6 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { return; } - TronNetService.getP2pService().updateNodeId(peer.getChannel(), msg.getFrom().getHexId()); - if (peer.isDisconnect()) { - logger.info("Duplicate Peer {}", peer.getInetSocketAddress()); - peer.disconnect(ReasonCode.DUPLICATE_PEER); - return; - } - if (!msg.valid()) { logger.warn("Peer {} invalid hello message parameters, " + "GenesisBlockId: {}, SolidBlockId: {}, HeadBlockId: {}", @@ -70,14 +63,6 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { return; } - if (msg.getVersion() != Args.getInstance().getNodeP2pVersion()) { - logger.info("Peer {} different p2p version, peer->{}, me->{}", - peer.getInetSocketAddress(), msg.getVersion(), - Args.getInstance().getNodeP2pVersion()); - peer.disconnect(ReasonCode.INCOMPATIBLE_VERSION); - return; - } - if (!Arrays.equals(chainBaseManager.getGenesisBlockId().getBytes(), msg.getGenesisBlockId().getBytes())) { logger.info("Peer {} different genesis block, peer->{}, me->{}", diff --git a/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java b/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java index 0387dd88c8e..cb5260a880c 100644 --- a/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java +++ b/framework/src/main/java/org/tron/core/net/service/keepalive/KeepAliveService.java @@ -11,12 +11,6 @@ @Component public class KeepAliveService { - public void init() { - } - - public void close() { - } - public void processMessage(PeerConnection peer, TronMessage message) { if (message.getType().equals(MessageTypes.P2P_PING)) { peer.sendMessage(new PongMessage()); From 5e203bdef232df8909eb2a692d8c66f0cdb251c8 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Wed, 22 Feb 2023 15:23:51 +0800 Subject: [PATCH 0611/1197] feat(net):update libp2p to v0.1.4 --- framework/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/build.gradle b/framework/build.gradle index f708733d4e2..4cd08614032 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -48,7 +48,7 @@ dependencies { compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' - compile group: 'io.github.tronprotocol', name: 'libp2p', version: '0.1.3' + compile group: 'io.github.tronprotocol', name: 'libp2p', version: '0.1.4' compile group: 'com.typesafe', name: 'config', version: '1.3.2' From cd4ff2ce189fe42fc56d24d1cd624deed1d2511f Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 22 Feb 2023 19:08:38 +0800 Subject: [PATCH 0612/1197] fix(net): use libp2p test-v0.2.1 --- common/build.gradle | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/common/build.gradle b/common/build.gradle index 21212d42e19..526b04d933e 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,8 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - //compile group: 'io.github.tronprotocol', name: 'libp2p', version: '0.1.2' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.0' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.1' compile project(":protocol") } From 2e4ed64391cf9e498226e838114555621883286a Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 22 Feb 2023 19:46:16 +0800 Subject: [PATCH 0613/1197] fix(api): add input check --- framework/src/main/java/org/tron/core/Wallet.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index bcefbb9b2f1..6d9b12608c5 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -913,6 +913,9 @@ public long calcCanDelegatedEnergyMaxSize(ByteString ownerAddress) { } public DelegatedResourceAccountIndex getDelegatedResourceAccountIndex(ByteString address) { + if (address == null || address.size() != DecodeUtil.ADDRESS_SIZE / 2) { + return DelegatedResourceAccountIndex.getDefaultInstance(); + } DelegatedResourceAccountIndexCapsule accountIndexCapsule = chainBaseManager.getDelegatedResourceAccountIndexStore().getIndex(address.toByteArray()); if (accountIndexCapsule != null) { @@ -923,6 +926,9 @@ public DelegatedResourceAccountIndex getDelegatedResourceAccountIndex(ByteString } public DelegatedResourceAccountIndex getDelegatedResourceAccountIndexV2(ByteString address) { + if (address == null || address.size() != DecodeUtil.ADDRESS_SIZE / 2) { + return DelegatedResourceAccountIndex.getDefaultInstance(); + } DelegatedResourceAccountIndexCapsule accountIndexCapsule = chainBaseManager .getDelegatedResourceAccountIndexStore().getV2Index(address.toByteArray()); if (accountIndexCapsule != null) { From 662959d9ec2fa2bf7a8c49fb3b54b052432819fd Mon Sep 17 00:00:00 2001 From: zhangheng Date: Fri, 24 Feb 2023 18:02:54 +0800 Subject: [PATCH 0614/1197] feature(tvm): optimize signatures --- .../main/java/org/tron/core/vm/PrecompiledContracts.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 66d2095f999..f17177a2192 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -52,12 +52,14 @@ import org.tron.common.utils.BIUtil; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; +import org.tron.common.utils.ForkController; import org.tron.common.utils.Sha256Hash; import org.tron.common.zksnark.JLibrustzcash; import org.tron.common.zksnark.LibrustzcashParam; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.WitnessCapsule; +import org.tron.core.config.Parameter; import org.tron.core.db.TransactionTrace; import org.tron.core.exception.ZksnarkException; import org.tron.core.vm.config.VMConfig; @@ -944,10 +946,14 @@ public Pair execute(byte[] rawData) { long totalWeight = 0L; List executedSignList = new ArrayList<>(); for (byte[] sign : signatures) { + byte[] recoveredAddr = recoverAddrBySign(sign, hash); + + if (ForkController.instance().pass(Parameter.ForkBlockVersionEnum.VERSION_4_7_1)) { + sign = recoveredAddr; + } if (ByteArray.matrixContains(executedSignList, sign)) { continue; } - byte[] recoveredAddr = recoverAddrBySign(sign, hash); long weight = TransactionCapsule.getWeight(permission, recoveredAddr); if (weight == 0) { //incorrect sign From 6d0fa0ee7cfc0e8e646b8e295e7f9d6303ded0e9 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Fri, 24 Feb 2023 18:44:23 +0800 Subject: [PATCH 0615/1197] feat(net): make the node detect function configurable --- .../java/org/tron/common/parameter/CommonParameter.java | 3 +++ common/src/main/java/org/tron/core/Constant.java | 2 ++ .../src/main/java/org/tron/core/config/args/Args.java | 8 ++++++++ .../src/main/java/org/tron/core/net/TronNetService.java | 1 + .../test/java/org/tron/common/config/args/ArgsTest.java | 1 + 5 files changed, 15 insertions(+) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 067abf000aa..c1eb8d0e489 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -330,6 +330,9 @@ public class CommonParameter { public boolean isOpenFullTcpDisconnect; @Getter @Setter + public boolean nodeDetectEnable; + @Getter + @Setter public int allowMultiSign; @Getter @Setter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 51e5a553bde..7da1f9fb537 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -188,6 +188,8 @@ public class Constant { public static final String NODE_IS_OPEN_FULL_TCP_DISCONNECT = "node.isOpenFullTcpDisconnect"; + public static final String NODE_DETECT_ENABLE = "node.nodeDetectEnable"; + public static final String NODE_MAX_TRANSACTION_PENDING_SIZE = "node.maxTransactionPendingSize"; public static final String NODE_PENDING_TRANSACTION_TIMEOUT = "node.pendingTransactionTimeout"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index f6ff13f01c4..e42c96281cf 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -178,6 +178,7 @@ public static void clearParam() { PARAMETER.estimateEnergyMaxRetry = 3; PARAMETER.receiveTcpMinDataLength = 2048; PARAMETER.isOpenFullTcpDisconnect = false; + PARAMETER.nodeDetectEnable = false; PARAMETER.supportConstant = false; PARAMETER.debug = false; PARAMETER.minTimeRatio = 0.0; @@ -819,8 +820,13 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.receiveTcpMinDataLength = config.hasPath(Constant.NODE_RECEIVE_TCP_MIN_DATA_LENGTH) ? config.getLong(Constant.NODE_RECEIVE_TCP_MIN_DATA_LENGTH) : 2048; + PARAMETER.isOpenFullTcpDisconnect = config.hasPath(Constant.NODE_IS_OPEN_FULL_TCP_DISCONNECT) && config.getBoolean(Constant.NODE_IS_OPEN_FULL_TCP_DISCONNECT); + + PARAMETER.nodeDetectEnable = config.hasPath(Constant.NODE_DETECT_ENABLE) + && config.getBoolean(Constant.NODE_DETECT_ENABLE); + PARAMETER.maxTransactionPendingSize = config.hasPath(Constant.NODE_MAX_TRANSACTION_PENDING_SIZE) ? config.getInt(Constant.NODE_MAX_TRANSACTION_PENDING_SIZE) : 2000; @@ -1569,6 +1575,8 @@ public static void logConfig() { logger.info("Max connection with same IP: {}", parameter.getMaxConnectionsWithSameIp()); logger.info("Solidity threads: {}", parameter.getSolidityThreads()); logger.info("Trx reference block: {}", parameter.getTrxReferenceBlock()); + logger.info("Open full tcp disconnect: {}", parameter.isOpenFullTcpDisconnect()); + logger.info("Node detect enable: {}", parameter.isNodeDetectEnable()); logger.info("************************ Backup config ************************"); logger.info("Backup priority: {}", parameter.getBackupPriority()); logger.info("Backup listen port: {}", parameter.getBackupPort()); diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 5eea2e5a45f..fe1347a8ebc 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -157,6 +157,7 @@ private P2pConfig getConfig() { config.setPort(parameter.getNodeListenPort()); config.setNetworkId(parameter.getNodeP2pVersion()); config.setDisconnectionPolicyEnable(parameter.isOpenFullTcpDisconnect()); + config.setNodeDetectEnable(parameter.isNodeDetectEnable()); config.setDiscoverEnable(parameter.isNodeDiscoveryEnable()); if (StringUtil.isNullOrEmpty(config.getIp()) && StringUtil.isNullOrEmpty(config.getIpv6())) { config.setIp(parameter.getNodeExternalIp()); diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index 5b391f0d38d..cbacb5f6246 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -30,5 +30,6 @@ public void testConfig() { Assert.assertEquals(Args.getInstance().getNodeDiscoveryPingTimeout(), 15_000); Assert.assertEquals(Args.getInstance().getMaxFastForwardNum(), 3); Assert.assertEquals(Args.getInstance().getBlockCacheTimeout(), 60); + Assert.assertEquals(Args.getInstance().isNodeDetectEnable(), false); } } \ No newline at end of file From 17bf1a45d3b8c37db498f7f8030019551e4664c6 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 24 Feb 2023 21:50:40 +0800 Subject: [PATCH 0616/1197] update libp2p version to test-v0.2.2 --- common/build.gradle | 2 +- framework/build.gradle | 2 -- framework/src/main/java/org/tron/core/config/args/Args.java | 4 +--- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/common/build.gradle b/common/build.gradle index 526b04d933e..58476ea8ae5 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.1' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.2' compile project(":protocol") } diff --git a/framework/build.gradle b/framework/build.gradle index 676088868be..f4f5134bf6e 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -48,8 +48,6 @@ dependencies { compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' - compile group: 'software.amazon.awssdk', name: 'regions', version: '2.18.41' - compile group: 'com.typesafe', name: 'config', version: '1.3.2' compile "com.cedarsoftware:java-util:1.8.0" diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index e42c96281cf..667686b8096 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -80,8 +80,6 @@ import org.tron.p2p.dns.update.PublishConfig; import org.tron.program.Version; -import software.amazon.awssdk.regions.Region; - @Slf4j(topic = "app") @NoArgsConstructor @Component @@ -1350,7 +1348,7 @@ public static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Confi logger.error("Check {}, must not be null", Constant.NODE_DNS_AWS_REGION); return null; } else { - publishConfig.setAwsRegion(Region.of(config.getString(Constant.NODE_DNS_AWS_REGION))); + publishConfig.setAwsRegion(config.getString(Constant.NODE_DNS_AWS_REGION)); } if (config.hasPath(Constant.NODE_DNS_AWS_HOST_ZONE_ID)) { publishConfig.setAwsHostZoneId(config.getString(Constant.NODE_DNS_AWS_HOST_ZONE_ID)); From f8bab83effa146940c48ac7acc89648f4c7f13d5 Mon Sep 17 00:00:00 2001 From: zhangheng Date: Fri, 24 Feb 2023 22:23:34 +0800 Subject: [PATCH 0617/1197] feature(tvm): optimize the check of cpu time --- .../tron/core/vm/PrecompiledContracts.java | 19 ++++++++++++------- .../java/org/tron/core/vm/utils/MUtil.java | 9 +++++++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index f17177a2192..9d4aef2bf36 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -52,20 +52,20 @@ import org.tron.common.utils.BIUtil; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.ForkController; import org.tron.common.utils.Sha256Hash; import org.tron.common.zksnark.JLibrustzcash; import org.tron.common.zksnark.LibrustzcashParam; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.Parameter; import org.tron.core.db.TransactionTrace; import org.tron.core.exception.ZksnarkException; import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.program.Program; +import org.tron.core.vm.program.Program.OutOfTimeException; import org.tron.core.vm.repository.Repository; import org.tron.core.vm.utils.FreezeV2Util; +import org.tron.core.vm.utils.MUtil; import org.tron.core.vm.utils.VoteRewardUtil; import org.tron.protos.Protocol; import org.tron.protos.Protocol.Permission; @@ -948,11 +948,12 @@ public Pair execute(byte[] rawData) { for (byte[] sign : signatures) { byte[] recoveredAddr = recoverAddrBySign(sign, hash); - if (ForkController.instance().pass(Parameter.ForkBlockVersionEnum.VERSION_4_7_1)) { - sign = recoveredAddr; - } - if (ByteArray.matrixContains(executedSignList, sign)) { - continue; + sign = merge(recoveredAddr, sign); + if (ByteArray.matrixContains(executedSignList, recoveredAddr)) { + if (ByteArray.matrixContains(executedSignList, sign)) { + continue; + } + MUtil.checkCPUTime(); } long weight = TransactionCapsule.getWeight(permission, recoveredAddr); if (weight == 0) { @@ -961,6 +962,7 @@ public Pair execute(byte[] rawData) { } totalWeight += weight; executedSignList.add(sign); + executedSignList.add(recoveredAddr); } if (totalWeight >= permission.getThreshold()) { @@ -968,6 +970,9 @@ public Pair execute(byte[] rawData) { } } } catch (Throwable t) { + if (t instanceof OutOfTimeException) { + throw t; + } logger.info("ValidateMultiSign error:{}", t.getMessage()); } } diff --git a/actuator/src/main/java/org/tron/core/vm/utils/MUtil.java b/actuator/src/main/java/org/tron/core/vm/utils/MUtil.java index 6d002c4db81..c94f28b3a2f 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/MUtil.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/MUtil.java @@ -1,8 +1,11 @@ package org.tron.core.vm.utils; +import org.tron.common.utils.ForkController; import org.tron.core.capsule.AccountCapsule; +import org.tron.core.config.Parameter; import org.tron.core.exception.ContractValidateException; import org.tron.core.vm.VMUtils; +import org.tron.core.vm.program.Program.OutOfTimeException; import org.tron.core.vm.repository.Repository; import org.tron.protos.Protocol; @@ -55,4 +58,10 @@ public static boolean isNullOrEmpty(String str) { public static boolean isNotNullOrEmpty(String str) { return !isNullOrEmpty(str); } + + public static void checkCPUTime() { + if (ForkController.instance().pass(Parameter.ForkBlockVersionEnum.VERSION_4_7_1)) { + throw new OutOfTimeException("CPU timeout for 0x0a executing"); + } + } } From 772eb45b84473605a55b2d91f49d87f733fb58f9 Mon Sep 17 00:00:00 2001 From: lvs007 Date: Mon, 27 Feb 2023 17:52:58 +0800 Subject: [PATCH 0618/1197] update a new version. version name:GreatVoyage-v4.7.0.1-75-g36fc5063e9,version code:17673 --- framework/src/main/java/org/tron/program/Version.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 4f435b1b0cb..88f87a68297 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,8 +2,8 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.7.0-9-g9326a08dd9"; - public static final String VERSION_CODE = "17596"; + public static final String VERSION_NAME = "GreatVoyage-v4.7.0.1-75-g36fc5063e9"; + public static final String VERSION_CODE = "17673"; private static final String VERSION = "4.7.1"; public static String getVersion() { From f7a2f47771c0158fd9cb6543f43803d00a6717f7 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 28 Feb 2023 16:14:26 +0800 Subject: [PATCH 0619/1197] feat(log): remove unused config 1. One and only one appender may be attached to AsyncAppender. --- framework/src/main/resources/logback.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/main/resources/logback.xml b/framework/src/main/resources/logback.xml index 8dcf9b6c66b..39c7f463172 100644 --- a/framework/src/main/resources/logback.xml +++ b/framework/src/main/resources/logback.xml @@ -60,7 +60,6 @@ 100 true - From 543fbb1ef9331fa6480986d5d20f9afdc7cbf9e0 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 28 Feb 2023 19:57:38 +0800 Subject: [PATCH 0620/1197] fix(net): fix the bug of missing data in mongo --- .../main/java/org/tron/core/db/Manager.java | 107 ++++++++++-------- 1 file changed, 59 insertions(+), 48 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index b43387ec4f6..9cceda9d462 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -241,6 +241,9 @@ public class Manager { @Getter private volatile long latestSolidityNumShutDown; @Getter + private long lastUsedSolidityNum = -1; + private boolean useSolidity = false; + @Getter private int maxFlushCount; @Getter @@ -525,12 +528,18 @@ public void init() { Thread triggerCapsuleProcessThread = new Thread(triggerCapsuleProcessLoop); triggerCapsuleProcessThread.setDaemon(true); triggerCapsuleProcessThread.start(); + if (eventPluginLoaded) { + useSolidity = EventPluginLoader.getInstance().isBlockLogTriggerSolidified() + | EventPluginLoader.getInstance().isTransactionLogTriggerEnable() + | EventPluginLoader.getInstance().isTransactionLogTriggerSolidified(); + } } // start json rpc filter process if (CommonParameter.getInstance().isJsonRpcFilterEnabled()) { Thread filterProcessThread = new Thread(filterProcessLoop); filterProcessThread.start(); + useSolidity |= CommonParameter.getInstance().isJsonRpcHttpSolidityNodeEnable(); } //initStoreFactory @@ -2027,17 +2036,11 @@ private void postSolidityFilter(final long oldSolidNum, final long latestSolidif return; } - BlockCapsule blockCapsule; - try { - blockCapsule = chainBaseManager.getBlockByNum(latestSolidifiedBlockNumber); - } catch (Exception e) { - logger.error("PostSolidityFilter getBlockByNum = {} except, {}.", - latestSolidifiedBlockNumber, e.getMessage()); - return; + List capsuleList = getCrossBlockCapsule(latestSolidifiedBlockNumber); + for (BlockCapsule blockCapsule : capsuleList) { + postBlockFilter(blockCapsule, true); + postLogsFilter(blockCapsule, true, false); } - - postBlockFilter(blockCapsule, true); - postLogsFilter(blockCapsule, true, false); } private void postSolidityTrigger(final long oldSolidNum, final long latestSolidifiedBlockNumber) { @@ -2054,28 +2057,27 @@ private void postSolidityTrigger(final long oldSolidNum, final long latestSolidi } if (eventPluginLoaded && EventPluginLoader.getInstance().isSolidityTriggerEnable()) { - SolidityTriggerCapsule solidityTriggerCapsule - = new SolidityTriggerCapsule(latestSolidifiedBlockNumber); - - BlockCapsule blockCapsule; - try { - blockCapsule = chainBaseManager.getBlockByNum(latestSolidifiedBlockNumber); + List capsuleList = getCrossBlockCapsule(latestSolidifiedBlockNumber); + for(BlockCapsule blockCapsule : capsuleList){ + SolidityTriggerCapsule solidityTriggerCapsule + = new SolidityTriggerCapsule(latestSolidifiedBlockNumber); solidityTriggerCapsule.setTimeStamp(blockCapsule.getTimeStamp()); - } catch (Exception e) { - logger.error("PostSolidityTrigger getBlockByNum = {} except, {}.", - latestSolidifiedBlockNumber, e.getMessage()); - } - boolean result = triggerCapsuleQueue.offer(solidityTriggerCapsule); - if (!result) { - logger.info("Too many trigger, lost solidified trigger, block number: {}.", - latestSolidifiedBlockNumber); + boolean result = triggerCapsuleQueue.offer(solidityTriggerCapsule); + if (!result) { + logger.info("Too many trigger, lost solidified trigger, block number: {}.", + latestSolidifiedBlockNumber); + } } } if (CommonParameter.getInstance().isJsonRpcHttpSolidityNodeEnable()) { postSolidityFilter(oldSolidNum, latestSolidifiedBlockNumber); } + + if (useSolidity) { + lastUsedSolidityNum = latestSolidifiedBlockNumber; + } } private void processTransactionTrigger(BlockCapsule newBlock) { @@ -2184,7 +2186,6 @@ private void postLogsFilter(final BlockCapsule blockCapsule, boolean solidified, } private void postBlockTrigger(final BlockCapsule blockCapsule) { - BlockCapsule newBlock = blockCapsule; // post block and logs for jsonrpc if (CommonParameter.getInstance().isJsonRpcHttpFullNodeEnable()) { @@ -2193,44 +2194,54 @@ private void postBlockTrigger(final BlockCapsule blockCapsule) { } // process block trigger + long solidityBlkNum = getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); if (eventPluginLoaded && EventPluginLoader.getInstance().isBlockLogTriggerEnable()) { + List capsuleList = new ArrayList<>(); if (EventPluginLoader.getInstance().isBlockLogTriggerSolidified()) { - long solidityBlkNum = getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); - try { - newBlock = chainBaseManager - .getBlockByNum(solidityBlkNum); - } catch (Exception e) { - logger.error("PostBlockTrigger getBlockByNum blkNum = {} except, error is {}.", - solidityBlkNum, e.getMessage()); - } + capsuleList = getCrossBlockCapsule(solidityBlkNum); + } else { + capsuleList.add(blockCapsule); } - BlockLogTriggerCapsule blockLogTriggerCapsule = new BlockLogTriggerCapsule(newBlock); - blockLogTriggerCapsule.setLatestSolidifiedBlockNumber(getDynamicPropertiesStore() - .getLatestSolidifiedBlockNum()); - if (!triggerCapsuleQueue.offer(blockLogTriggerCapsule)) { - logger.info("Too many triggers, block trigger lost: {}.", newBlock.getBlockId()); + for (BlockCapsule capsule : capsuleList) { + BlockLogTriggerCapsule blockLogTriggerCapsule = new BlockLogTriggerCapsule(capsule); + blockLogTriggerCapsule.setLatestSolidifiedBlockNumber(getDynamicPropertiesStore() + .getLatestSolidifiedBlockNum()); + if (!triggerCapsuleQueue.offer(blockLogTriggerCapsule)) { + logger.info("Too many triggers, block trigger lost: {}.", capsule.getBlockId()); + } } } // process transaction trigger if (eventPluginLoaded && EventPluginLoader.getInstance().isTransactionLogTriggerEnable()) { - // set newBlock + List capsuleList = new ArrayList<>(); if (EventPluginLoader.getInstance().isTransactionLogTriggerSolidified()) { - long solidityBlkNum = getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); - try { - newBlock = chainBaseManager.getBlockByNum(solidityBlkNum); - } catch (Exception e) { - logger.error("PostBlockTrigger getBlockByNum blkNum = {} except, error is {}.", - solidityBlkNum, e.getMessage()); - } + capsuleList = getCrossBlockCapsule(solidityBlkNum); } else { // need to reset block - newBlock = blockCapsule; + capsuleList.add(blockCapsule); } - processTransactionTrigger(newBlock); + for (BlockCapsule capsule : capsuleList) { + processTransactionTrigger(capsule); + } + } + } + + private List getCrossBlockCapsule(long solidityBlkNum) { + List capsuleList = new ArrayList<>(); + long start = lastUsedSolidityNum < 0 ? (solidityBlkNum - 1) : lastUsedSolidityNum; + for (long i = start + 1; i <= solidityBlkNum; i++) { + try { + BlockCapsule capsule = chainBaseManager.getBlockByNum(solidityBlkNum); + capsuleList.add(capsule); + } catch (Exception e) { + logger.error("GetCrossBlockCapsule getBlockByNum blkNum = {} except, error is {}.", + solidityBlkNum, e.getMessage()); + } } + return capsuleList; } // return energyUsageTotal of the current transaction From 50ceff55e74d61c12b957dc8f621028e3c823334 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 1 Mar 2023 11:09:55 +0800 Subject: [PATCH 0621/1197] fix(net): use blockNum instead of i --- framework/src/main/java/org/tron/core/db/Manager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 9cceda9d462..0acc2595e4d 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -2232,9 +2232,9 @@ private void postBlockTrigger(final BlockCapsule blockCapsule) { private List getCrossBlockCapsule(long solidityBlkNum) { List capsuleList = new ArrayList<>(); long start = lastUsedSolidityNum < 0 ? (solidityBlkNum - 1) : lastUsedSolidityNum; - for (long i = start + 1; i <= solidityBlkNum; i++) { + for (long blockNum = start + 1; blockNum <= solidityBlkNum; blockNum++) { try { - BlockCapsule capsule = chainBaseManager.getBlockByNum(solidityBlkNum); + BlockCapsule capsule = chainBaseManager.getBlockByNum(blockNum); capsuleList.add(capsule); } catch (Exception e) { logger.error("GetCrossBlockCapsule getBlockByNum blkNum = {} except, error is {}.", From 833eb0c80677efe94ab1da1edeeba5d383d53f93 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 1 Mar 2023 16:06:41 +0800 Subject: [PATCH 0622/1197] update libp2p from test-v0.2.2 to test-v0.2.3 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 58476ea8ae5..1217302c6ac 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.2' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.3' compile project(":protocol") } From b33c660eceb55a04c60e06145630a487d43f6a60 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 1 Mar 2023 18:26:50 +0800 Subject: [PATCH 0623/1197] fix(db): update postSolidityTrigger --- .../src/main/java/org/tron/core/db/Manager.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 4b04292d517..fde976b2c7f 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -2061,11 +2061,16 @@ private void postSolidityTrigger(final long oldSolidNum, final long latestSolidi if (eventPluginLoaded && EventPluginLoader.getInstance().isSolidityTriggerEnable()) { List capsuleList = getCrossBlockCapsule(latestSolidifiedBlockNumber); - for(BlockCapsule blockCapsule : capsuleList){ + long solidifiedTime = -1; + if (!capsuleList.isEmpty()) { + solidifiedTime = capsuleList.get(capsuleList.size() - 1).getTimeStamp(); + } + for (BlockCapsule blockCapsule : capsuleList) { SolidityTriggerCapsule solidityTriggerCapsule - = new SolidityTriggerCapsule(latestSolidifiedBlockNumber); - solidityTriggerCapsule.setTimeStamp(blockCapsule.getTimeStamp()); - + = new SolidityTriggerCapsule(blockCapsule.getNum());//unique key + if (solidifiedTime >= 0) { + solidityTriggerCapsule.setTimeStamp(solidifiedTime); + } boolean result = triggerCapsuleQueue.offer(solidityTriggerCapsule); if (!result) { logger.info("Too many trigger, lost solidified trigger, block number: {}.", From d24d6404220fd74434311a89ec43bd982c5695c5 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 1 Mar 2023 18:34:00 +0800 Subject: [PATCH 0624/1197] fix(db): update postSolidityTrigger --- framework/src/main/java/org/tron/core/db/Manager.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index fde976b2c7f..fdacb9d1b6b 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -2063,7 +2063,10 @@ private void postSolidityTrigger(final long oldSolidNum, final long latestSolidi List capsuleList = getCrossBlockCapsule(latestSolidifiedBlockNumber); long solidifiedTime = -1; if (!capsuleList.isEmpty()) { - solidifiedTime = capsuleList.get(capsuleList.size() - 1).getTimeStamp(); + BlockCapsule blockCapsule = capsuleList.get(capsuleList.size() - 1); + if (blockCapsule.getNum() == latestSolidifiedBlockNumber) { + solidifiedTime = blockCapsule.getTimeStamp(); + } } for (BlockCapsule blockCapsule : capsuleList) { SolidityTriggerCapsule solidityTriggerCapsule @@ -2074,7 +2077,7 @@ private void postSolidityTrigger(final long oldSolidNum, final long latestSolidi boolean result = triggerCapsuleQueue.offer(solidityTriggerCapsule); if (!result) { logger.info("Too many trigger, lost solidified trigger, block number: {}.", - latestSolidifiedBlockNumber); + blockCapsule.getNum()); } } } From 8c72efc04b9e2493f8ebf402e89b83862237e135 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 2 Mar 2023 20:14:11 +0800 Subject: [PATCH 0625/1197] fix(net): add paramater node.dns.staticNodes --- common/build.gradle | 2 +- .../src/main/java/org/tron/core/Constant.java | 1 + .../java/org/tron/core/config/args/Args.java | 35 ++++++++++------ .../test/java/org/tron/core/net/NodeTest.java | 40 +++++++++++++++++++ 4 files changed, 64 insertions(+), 14 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/net/NodeTest.java diff --git a/common/build.gradle b/common/build.gradle index 1217302c6ac..530515f065a 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.3' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.4' compile project(":protocol") } diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 7da1f9fb537..7c0f0c40ee2 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -109,6 +109,7 @@ public class Constant { public static final String NODE_DNS_DOMAIN = "node.dns.dnsDomain"; public static final String NODE_DNS_PRIVATE = "node.dns.dnsPrivate"; public static final String NODE_DNS_KNOWN_URLS = "node.dns.knownUrls"; + public static final String NODE_DNS_STATIC_NODES = "node.dns.staticNodes"; public static final String NODE_DNS_SERVER_TYPE = "node.dns.serverType"; public static final String NODE_DNS_ACCESS_KEY_ID = "node.dns.accessKeyId"; public static final String NODE_DNS_ACCESS_KEY_SECRET = "node.dns.accessKeySecret"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 667686b8096..58fd764b18f 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -24,7 +24,6 @@ import java.net.InetSocketAddress; import java.net.Socket; import java.net.URL; -import java.nio.file.Paths; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; @@ -64,9 +63,7 @@ import org.tron.common.setting.RocksDbSettings; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Commons; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.LocalWitnesses; -import org.tron.common.utils.PropUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.config.Configuration; @@ -1289,7 +1286,7 @@ private static EventPluginConfig getEventPluginConfig( return eventPluginConfig; } - public static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Config config) { + private static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Config config) { PublishConfig publishConfig = new PublishConfig(); if (config.hasPath(Constant.NODE_DNS_PUBLISH)) { publishConfig.setDnsPublishEnable(config.getBoolean(Constant.NODE_DNS_PUBLISH)); @@ -1299,14 +1296,14 @@ public static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Confi if (config.hasPath(Constant.NODE_DNS_DOMAIN)) { publishConfig.setDnsDomain(config.getString(Constant.NODE_DNS_DOMAIN)); } else { - logger.error("Check {}, must not be null", Constant.NODE_DNS_DOMAIN); + logEmptyError(Constant.NODE_DNS_DOMAIN); return null; } if (config.hasPath(Constant.NODE_DNS_PRIVATE)) { publishConfig.setDnsPrivate(config.getString(Constant.NODE_DNS_PRIVATE)); } else { - logger.error("Check {}, must not be null", Constant.NODE_DNS_PRIVATE); + logEmptyError(Constant.NODE_DNS_PRIVATE); return null; } @@ -1314,6 +1311,10 @@ public static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Confi publishConfig.setKnownTreeUrls(config.getStringList(Constant.NODE_DNS_KNOWN_URLS)); } + if (config.hasPath(Constant.NODE_DNS_STATIC_NODES)) { + publishConfig.setStaticNodes(getInetSocketAddress(config, Constant.NODE_DNS_STATIC_NODES)); + } + if (config.hasPath(Constant.NODE_DNS_SERVER_TYPE)) { String serverType = config.getString(Constant.NODE_DNS_SERVER_TYPE); if (!serverType.equalsIgnoreCase("aws") && !serverType.equalsIgnoreCase("aliyun")) { @@ -1326,26 +1327,26 @@ public static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Confi publishConfig.setDnsType(DnsType.AliYun); } } else { - logger.error("Check {}, must not be null", Constant.NODE_DNS_SERVER_TYPE); + logEmptyError(Constant.NODE_DNS_SERVER_TYPE); return null; } if (config.hasPath(Constant.NODE_DNS_ACCESS_KEY_ID)) { publishConfig.setAccessKeyId(config.getString(Constant.NODE_DNS_ACCESS_KEY_ID)); } else { - logger.error("Check {}, must not be null", Constant.NODE_DNS_ACCESS_KEY_ID); + logEmptyError(Constant.NODE_DNS_ACCESS_KEY_ID); return null; } if (config.hasPath(Constant.NODE_DNS_ACCESS_KEY_SECRET)) { publishConfig.setAccessKeySecret(config.getString(Constant.NODE_DNS_ACCESS_KEY_SECRET)); } else { - logger.error("Check {}, must not be null", Constant.NODE_DNS_ACCESS_KEY_SECRET); + logEmptyError(Constant.NODE_DNS_ACCESS_KEY_SECRET); return null; } if (publishConfig.getDnsType() == DnsType.AwsRoute53) { if (!config.hasPath(Constant.NODE_DNS_AWS_REGION)) { - logger.error("Check {}, must not be null", Constant.NODE_DNS_AWS_REGION); + logEmptyError(Constant.NODE_DNS_AWS_REGION); return null; } else { publishConfig.setAwsRegion(config.getString(Constant.NODE_DNS_AWS_REGION)); @@ -1355,7 +1356,7 @@ public static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Confi } } else { if (!config.hasPath(Constant.NODE_DNS_ALIYUN_ENDPOINT)) { - logger.error("Check {}, must not be null", Constant.NODE_DNS_ALIYUN_ENDPOINT); + logEmptyError(Constant.NODE_DNS_ALIYUN_ENDPOINT); return null; } else { publishConfig.setAliDnsEndpoint(config.getString(Constant.NODE_DNS_ALIYUN_ENDPOINT)); @@ -1365,6 +1366,10 @@ public static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Confi return publishConfig; } + private static void logEmptyError(String arg) { + logger.error("Check {}, must not be null", arg); + } + private static TriggerConfig createTriggerConfig(ConfigObject triggerObject) { if (Objects.isNull(triggerObject)) { return null; @@ -1627,8 +1632,12 @@ public static InetSocketAddress parseInetSocketAddress(String para) { int index = para.lastIndexOf(":"); if (index > 0) { String host = para.substring(0, index); - int port = Integer.parseInt(para.substring(index + 1)); - address = new InetSocketAddress(host, port); + try { + int port = Integer.parseInt(para.substring(index + 1)); + address = new InetSocketAddress(host, port); + } catch (RuntimeException e) { + logger.error("Invalid inetSocketAddress: {}", para); + } } return address; } diff --git a/framework/src/test/java/org/tron/core/net/NodeTest.java b/framework/src/test/java/org/tron/core/net/NodeTest.java new file mode 100644 index 00000000000..f97f147193b --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/NodeTest.java @@ -0,0 +1,40 @@ +package org.tron.core.net; + +import static org.tron.core.net.message.handshake.HelloMessage.getEndpointFromNode; + +import java.net.InetSocketAddress; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; +import org.tron.core.config.args.Args; +import org.tron.p2p.discover.Node; +import org.tron.protos.Discover.Endpoint; + +@Slf4j +public class NodeTest { + + @Test + public void testIpV4() { + InetSocketAddress address1 = Args.parseInetSocketAddress("192.168.0.1:18888"); + Assert.assertNotNull(address1); + InetSocketAddress address2 = Args.parseInetSocketAddress("192.168.0.1"); + Assert.assertNull(address2); + } + + @Test + public void testIpV6() { + InetSocketAddress address1 = Args.parseInetSocketAddress("fe80::216:3eff:fe0e:23bb:18888"); + Assert.assertNotNull(address1); + InetSocketAddress address2 = Args.parseInetSocketAddress("fe80::216:3eff:fe0e:23bb"); + Assert.assertNull(address2); + } + + @Test + public void testEndpointFromNode() { + Node node = new Node(null, null, null, 18888); + Endpoint endpoint = getEndpointFromNode(node); + Assert.assertTrue(endpoint.getNodeId().isEmpty()); + Assert.assertTrue(endpoint.getAddress().isEmpty()); + Assert.assertTrue(endpoint.getAddressIpv6().isEmpty()); + } +} From 7b0032597fb08994875b685eefc1bc6311214a7d Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 2 Mar 2023 20:40:35 +0800 Subject: [PATCH 0626/1197] style(net): fix checkstyle warning --- framework/src/main/java/org/tron/core/config/args/Args.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 58fd764b18f..7aa107cdc71 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1317,11 +1317,11 @@ private static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Conf if (config.hasPath(Constant.NODE_DNS_SERVER_TYPE)) { String serverType = config.getString(Constant.NODE_DNS_SERVER_TYPE); - if (!serverType.equalsIgnoreCase("aws") && !serverType.equalsIgnoreCase("aliyun")) { + if (!"aws".equalsIgnoreCase(serverType) && !"aliyun".equalsIgnoreCase(serverType)) { logger.error("Check {}, must be aws or aliyun", Constant.NODE_DNS_SERVER_TYPE); return null; } - if (serverType.equalsIgnoreCase("aws")) { + if ("aws".equalsIgnoreCase(serverType)) { publishConfig.setDnsType(DnsType.AwsRoute53); } else { publishConfig.setDnsType(DnsType.AliYun); From 2709f2a8ca992f85c3f36c4b227cc789213782ce Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 3 Mar 2023 16:25:22 +0800 Subject: [PATCH 0627/1197] fix(db): rename geContinuousBlockCapsule --- .../src/main/java/org/tron/core/db/Manager.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index fdacb9d1b6b..918eb0044b6 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -2039,7 +2039,7 @@ private void postSolidityFilter(final long oldSolidNum, final long latestSolidif return; } - List capsuleList = getCrossBlockCapsule(latestSolidifiedBlockNumber); + List capsuleList = geContinuousBlockCapsule(latestSolidifiedBlockNumber); for (BlockCapsule blockCapsule : capsuleList) { postBlockFilter(blockCapsule, true); postLogsFilter(blockCapsule, true, false); @@ -2060,7 +2060,7 @@ private void postSolidityTrigger(final long oldSolidNum, final long latestSolidi } if (eventPluginLoaded && EventPluginLoader.getInstance().isSolidityTriggerEnable()) { - List capsuleList = getCrossBlockCapsule(latestSolidifiedBlockNumber); + List capsuleList = geContinuousBlockCapsule(latestSolidifiedBlockNumber); long solidifiedTime = -1; if (!capsuleList.isEmpty()) { BlockCapsule blockCapsule = capsuleList.get(capsuleList.size() - 1); @@ -2211,15 +2211,14 @@ private void postBlockTrigger(final BlockCapsule blockCapsule) { if (eventPluginLoaded && EventPluginLoader.getInstance().isBlockLogTriggerEnable()) { List capsuleList = new ArrayList<>(); if (EventPluginLoader.getInstance().isBlockLogTriggerSolidified()) { - capsuleList = getCrossBlockCapsule(solidityBlkNum); + capsuleList = geContinuousBlockCapsule(solidityBlkNum); } else { capsuleList.add(blockCapsule); } for (BlockCapsule capsule : capsuleList) { BlockLogTriggerCapsule blockLogTriggerCapsule = new BlockLogTriggerCapsule(capsule); - blockLogTriggerCapsule.setLatestSolidifiedBlockNumber(getDynamicPropertiesStore() - .getLatestSolidifiedBlockNum()); + blockLogTriggerCapsule.setLatestSolidifiedBlockNumber(solidityBlkNum); if (!triggerCapsuleQueue.offer(blockLogTriggerCapsule)) { logger.info("Too many triggers, block trigger lost: {}.", capsule.getBlockId()); } @@ -2230,7 +2229,7 @@ private void postBlockTrigger(final BlockCapsule blockCapsule) { if (eventPluginLoaded && EventPluginLoader.getInstance().isTransactionLogTriggerEnable()) { List capsuleList = new ArrayList<>(); if (EventPluginLoader.getInstance().isTransactionLogTriggerSolidified()) { - capsuleList = getCrossBlockCapsule(solidityBlkNum); + capsuleList = geContinuousBlockCapsule(solidityBlkNum); } else { // need to reset block capsuleList.add(blockCapsule); @@ -2242,9 +2241,10 @@ private void postBlockTrigger(final BlockCapsule blockCapsule) { } } - private List getCrossBlockCapsule(long solidityBlkNum) { + private List geContinuousBlockCapsule(long solidityBlkNum) { List capsuleList = new ArrayList<>(); long start = lastUsedSolidityNum < 0 ? (solidityBlkNum - 1) : lastUsedSolidityNum; + logger.info("Continuous block start:{}, end:{}", start +1, solidityBlkNum); for (long blockNum = start + 1; blockNum <= solidityBlkNum; blockNum++) { try { BlockCapsule capsule = chainBaseManager.getBlockByNum(blockNum); From bec6bc23580d71a19790033cb67aab22554a159c Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 3 Mar 2023 16:31:01 +0800 Subject: [PATCH 0628/1197] fix(db): add some log in geContinuousBlockCapsule --- framework/src/main/java/org/tron/core/db/Manager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 918eb0044b6..13764016a75 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -2244,7 +2244,9 @@ private void postBlockTrigger(final BlockCapsule blockCapsule) { private List geContinuousBlockCapsule(long solidityBlkNum) { List capsuleList = new ArrayList<>(); long start = lastUsedSolidityNum < 0 ? (solidityBlkNum - 1) : lastUsedSolidityNum; - logger.info("Continuous block start:{}, end:{}", start +1, solidityBlkNum); + if (solidityBlkNum - start > 1) { + logger.info("Continuous block start:{}, end:{}", start + 1, solidityBlkNum); + } for (long blockNum = start + 1; blockNum <= solidityBlkNum; blockNum++) { try { BlockCapsule capsule = chainBaseManager.getBlockByNum(blockNum); From 2016860056d94ceae502cdc291ecb4f733102de3 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 6 Mar 2023 15:34:15 +0800 Subject: [PATCH 0629/1197] feat(net): recover handshake check logic --- .../net/service/handshake/HandshakeService.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java index 04ef5d1d5c5..6c9e53c3a98 100644 --- a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -36,6 +36,13 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { return; } + TronNetService.getP2pService().updateNodeId(peer.getChannel(), msg.getFrom().getHexId()); + if (peer.isDisconnect()) { + logger.info("Duplicate Peer {}", peer.getInetSocketAddress()); + peer.disconnect(ReasonCode.DUPLICATE_PEER); + return; + } + if (!msg.valid()) { logger.warn("Peer {} invalid hello message parameters, " + "GenesisBlockId: {}, SolidBlockId: {}, HeadBlockId: {}", @@ -63,6 +70,14 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { return; } + if (msg.getVersion() != Args.getInstance().getNodeP2pVersion()) { + logger.info("Peer {} different p2p version, peer->{}, me->{}", + peer.getInetSocketAddress(), msg.getVersion(), + Args.getInstance().getNodeP2pVersion()); + peer.disconnect(ReasonCode.INCOMPATIBLE_VERSION); + return; + } + if (!Arrays.equals(chainBaseManager.getGenesisBlockId().getBytes(), msg.getGenesisBlockId().getBytes())) { logger.info("Peer {} different genesis block, peer->{}, me->{}", From 5f66f93266b75513bf6ec050198bae37a5fe249e Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 6 Mar 2023 16:02:36 +0800 Subject: [PATCH 0630/1197] fix(net): update libp2p from test-v0.2.4 to test-v0.2.5 --- common/build.gradle | 2 +- .../tron/core/net/messagehandler/FetchInvDataMsgHandler.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/build.gradle b/common/build.gradle index 530515f065a..644cb2536f2 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.4' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.5' compile project(":protocol") } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java index 6b5b68b1d11..5e797c084b3 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java @@ -133,7 +133,7 @@ private void check(PeerConnection peer, FetchInvDataMessage fetchInvDataMsg) thr if (type == MessageTypes.TRX) { for (Sha256Hash hash : fetchInvDataMsg.getHashList()) { if (peer.getAdvInvSpread().getIfPresent(new Item(hash, InventoryType.TRX)) == null) { - throw new P2pException(TypeEnum.BAD_MESSAGE, "not spread inv: {}" + hash); + throw new P2pException(TypeEnum.BAD_MESSAGE, "not spread inv: " + hash); } } int fetchCount = peer.getPeerStatistics().messageStatistics.tronInTrxFetchInvDataElement From 0f82f22e0807706aed213ac1676d4dd718ab2cf8 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 6 Mar 2023 17:16:38 +0800 Subject: [PATCH 0631/1197] fix(net): update libp2p from test-v0.2.5 to test-v0.2.6 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 644cb2536f2..0c10faff4bd 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.5' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.6' compile project(":protocol") } From f39f279442e8952cce374ceb6667e73d674fb89c Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 6 Mar 2023 18:21:38 +0800 Subject: [PATCH 0632/1197] update libp2p from test-v0.2.6 to test-v0.2.7 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 0c10faff4bd..f119fb5c5ea 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.6' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.7' compile project(":protocol") } From 7b4c8f3d5a149b57d442a200f2b421dd15dee258 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 6 Mar 2023 19:40:14 +0800 Subject: [PATCH 0633/1197] update libp2p from test-v0.2.7 to test-v0.2.8 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index f119fb5c5ea..69ba3c4efbb 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.7' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.8' compile project(":protocol") } From a21d46d944ecfaeefa8f3a83c5fea42f1acde577 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 7 Mar 2023 16:46:08 +0800 Subject: [PATCH 0634/1197] add two parametres in dns section of config.conf --- common/build.gradle | 2 +- .../src/main/java/org/tron/core/Constant.java | 2 ++ .../java/org/tron/core/config/args/Args.java | 22 +++++++++++++++++-- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/common/build.gradle b/common/build.gradle index 69ba3c4efbb..1aa9aed7861 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.8' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.10' compile project(":protocol") } diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 7c0f0c40ee2..c8875c5fa56 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -107,6 +107,8 @@ public class Constant { public static final String NODE_DNS_TREE_URLS = "node.dns.treeUrls"; public static final String NODE_DNS_PUBLISH = "node.dns.publish"; public static final String NODE_DNS_DOMAIN = "node.dns.dnsDomain"; + public static final String NODE_DNS_CHANGE_THRESHOLD = "node.dns.changeThreshold"; + public static final String NODE_DNS_MAX_MERGE_SIZE = "node.dns.maxMergeSize"; public static final String NODE_DNS_PRIVATE = "node.dns.dnsPrivate"; public static final String NODE_DNS_KNOWN_URLS = "node.dns.knownUrls"; public static final String NODE_DNS_STATIC_NODES = "node.dns.staticNodes"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 7aa107cdc71..6cd5f04c524 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -820,7 +820,7 @@ public static void setParam(final String[] args, final String confFileName) { && config.getBoolean(Constant.NODE_IS_OPEN_FULL_TCP_DISCONNECT); PARAMETER.nodeDetectEnable = config.hasPath(Constant.NODE_DETECT_ENABLE) - && config.getBoolean(Constant.NODE_DETECT_ENABLE); + && config.getBoolean(Constant.NODE_DETECT_ENABLE); PARAMETER.maxTransactionPendingSize = config.hasPath(Constant.NODE_MAX_TRANSACTION_PENDING_SIZE) ? config.getInt(Constant.NODE_MAX_TRANSACTION_PENDING_SIZE) : 2000; @@ -872,7 +872,6 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.COMMITTEE_ALLOW_MARKET_TRANSACTION) ? config .getInt(Constant.COMMITTEE_ALLOW_MARKET_TRANSACTION) : 0; - PARAMETER.allowTransactionFeePool = config.hasPath(Constant.COMMITTEE_ALLOW_TRANSACTION_FEE_POOL) ? config .getInt(Constant.COMMITTEE_ALLOW_TRANSACTION_FEE_POOL) : 0; @@ -1300,6 +1299,25 @@ private static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Conf return null; } + if (config.hasPath(Constant.NODE_DNS_CHANGE_THRESHOLD)) { + double changeThreshold = config.getDouble(Constant.NODE_DNS_CHANGE_THRESHOLD); + if (changeThreshold > 0) { + publishConfig.setChangeThreshold(changeThreshold); + } else { + logger.error("Check {}, should be bigger than 0, default 0.1", + Constant.NODE_DNS_CHANGE_THRESHOLD); + } + } + + if (config.hasPath(Constant.NODE_DNS_MAX_MERGE_SIZE)) { + int maxMergeSize = config.getInt(Constant.NODE_DNS_MAX_MERGE_SIZE); + if (maxMergeSize >= 1 && maxMergeSize <= 5) { + publishConfig.setChangeThreshold(maxMergeSize); + } else { + logger.error("Check {}, should be [1~5], default 5", Constant.NODE_DNS_MAX_MERGE_SIZE); + } + } + if (config.hasPath(Constant.NODE_DNS_PRIVATE)) { publishConfig.setDnsPrivate(config.getString(Constant.NODE_DNS_PRIVATE)); } else { From 24f6c28d6b03157d8baec6e2b211ac34875fe261 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 8 Mar 2023 00:36:29 +0800 Subject: [PATCH 0635/1197] update libp2p from test-v0.2.10 to test-v0.2.11 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 1aa9aed7861..f2391f248e7 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.10' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.11' compile project(":protocol") } From bd8e07e15fb5803a22b8e91c2a3ab9bf87e59fce Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 8 Mar 2023 11:58:26 +0800 Subject: [PATCH 0636/1197] fix(net): don't filter address in static nodes --- .../java/org/tron/core/config/args/Args.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 6cd5f04c524..b2ec5b33dd1 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -915,11 +915,11 @@ public static void setParam(final String[] args, final String confFileName) { .getInt(Constant.NODE_VALID_CONTRACT_PROTO_THREADS) : Runtime.getRuntime().availableProcessors(); - PARAMETER.activeNodes = getInetSocketAddress(config, Constant.NODE_ACTIVE); + PARAMETER.activeNodes = getInetSocketAddress(config, Constant.NODE_ACTIVE, true); PARAMETER.passiveNodes = getInetAddress(config, Constant.NODE_PASSIVE); - PARAMETER.fastForwardNodes = getInetSocketAddress(config, Constant.NODE_FAST_FORWARD); + PARAMETER.fastForwardNodes = getInetSocketAddress(config, Constant.NODE_FAST_FORWARD, true); PARAMETER.maxFastForwardNum = config.hasPath(Constant.NODE_MAX_FAST_FORWARD_NUM) ? config .getInt(Constant.NODE_MAX_FAST_FORWARD_NUM) : 3; @@ -1186,7 +1186,7 @@ private static RateLimiterInitialization getRateLimiterFromConfig( } private static List getInetSocketAddress( - final com.typesafe.config.Config config, String path) { + final com.typesafe.config.Config config, String path, boolean filter) { List ret = new ArrayList<>(); if (!config.hasPath(path)) { return ret; @@ -1199,10 +1199,14 @@ private static List getInetSocketAddress( } String ip = inetSocketAddress.getAddress().getHostAddress(); int port = inetSocketAddress.getPort(); - if (!(PARAMETER.nodeDiscoveryBindIp.equals(ip) - || PARAMETER.nodeExternalIp.equals(ip) - || Constant.LOCAL_HOST.equals(ip)) - || PARAMETER.nodeListenPort != port) { + if (filter) { + if (!(PARAMETER.nodeDiscoveryBindIp.equals(ip) + || PARAMETER.nodeExternalIp.equals(ip) + || Constant.LOCAL_HOST.equals(ip)) + || PARAMETER.nodeListenPort != port) { + ret.add(inetSocketAddress); + } + } else { ret.add(inetSocketAddress); } } @@ -1330,7 +1334,8 @@ private static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Conf } if (config.hasPath(Constant.NODE_DNS_STATIC_NODES)) { - publishConfig.setStaticNodes(getInetSocketAddress(config, Constant.NODE_DNS_STATIC_NODES)); + publishConfig.setStaticNodes( + getInetSocketAddress(config, Constant.NODE_DNS_STATIC_NODES, false)); } if (config.hasPath(Constant.NODE_DNS_SERVER_TYPE)) { From 6a19a6f1a7970e5918d11211036aa2e2417726c3 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Thu, 2 Mar 2023 18:33:07 +0800 Subject: [PATCH 0637/1197] fix(gradle): clean up the sub-project build directory --- build.gradle | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build.gradle b/build.gradle index 82760ffd8cf..fb7479c281b 100644 --- a/build.gradle +++ b/build.gradle @@ -82,3 +82,11 @@ task copyToParent(type: Copy) { build.finalizedBy(copyToParent) +gradle.buildFinished { + if (project.hasProperty('cleanSubBuild')) { + subprojects { + buildDir.deleteDir() + } + } +} + From 36e9ee281d171982e1ae317249a491f95a039201 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 8 Mar 2023 19:24:54 +0800 Subject: [PATCH 0638/1197] fix(db): remove variable useSolidity --- .../main/java/org/tron/core/db/Manager.java | 42 +++++-------------- 1 file changed, 11 insertions(+), 31 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 13764016a75..3e665a924e4 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -242,7 +242,6 @@ public class Manager { private volatile long latestSolidityNumShutDown; @Getter private long lastUsedSolidityNum = -1; - private boolean useSolidity = false; @Getter private int maxFlushCount; @@ -531,18 +530,12 @@ public void init() { Thread triggerCapsuleProcessThread = new Thread(triggerCapsuleProcessLoop); triggerCapsuleProcessThread.setDaemon(true); triggerCapsuleProcessThread.start(); - if (eventPluginLoaded) { - useSolidity = EventPluginLoader.getInstance().isBlockLogTriggerSolidified() - | EventPluginLoader.getInstance().isTransactionLogTriggerEnable() - | EventPluginLoader.getInstance().isTransactionLogTriggerSolidified(); - } } // start json rpc filter process if (CommonParameter.getInstance().isJsonRpcFilterEnabled()) { Thread filterProcessThread = new Thread(filterProcessLoop); filterProcessThread.start(); - useSolidity |= CommonParameter.getInstance().isJsonRpcHttpSolidityNodeEnable(); } //initStoreFactory @@ -2039,7 +2032,7 @@ private void postSolidityFilter(final long oldSolidNum, final long latestSolidif return; } - List capsuleList = geContinuousBlockCapsule(latestSolidifiedBlockNumber); + List capsuleList = getContinuousBlockCapsule(latestSolidifiedBlockNumber); for (BlockCapsule blockCapsule : capsuleList) { postBlockFilter(blockCapsule, true); postLogsFilter(blockCapsule, true, false); @@ -2060,20 +2053,11 @@ private void postSolidityTrigger(final long oldSolidNum, final long latestSolidi } if (eventPluginLoaded && EventPluginLoader.getInstance().isSolidityTriggerEnable()) { - List capsuleList = geContinuousBlockCapsule(latestSolidifiedBlockNumber); - long solidifiedTime = -1; - if (!capsuleList.isEmpty()) { - BlockCapsule blockCapsule = capsuleList.get(capsuleList.size() - 1); - if (blockCapsule.getNum() == latestSolidifiedBlockNumber) { - solidifiedTime = blockCapsule.getTimeStamp(); - } - } + List capsuleList = getContinuousBlockCapsule(latestSolidifiedBlockNumber); for (BlockCapsule blockCapsule : capsuleList) { SolidityTriggerCapsule solidityTriggerCapsule = new SolidityTriggerCapsule(blockCapsule.getNum());//unique key - if (solidifiedTime >= 0) { - solidityTriggerCapsule.setTimeStamp(solidifiedTime); - } + solidityTriggerCapsule.setTimeStamp(blockCapsule.getTimeStamp()); boolean result = triggerCapsuleQueue.offer(solidityTriggerCapsule); if (!result) { logger.info("Too many trigger, lost solidified trigger, block number: {}.", @@ -2085,10 +2069,7 @@ private void postSolidityTrigger(final long oldSolidNum, final long latestSolidi if (CommonParameter.getInstance().isJsonRpcHttpSolidityNodeEnable()) { postSolidityFilter(oldSolidNum, latestSolidifiedBlockNumber); } - - if (useSolidity) { - lastUsedSolidityNum = latestSolidifiedBlockNumber; - } + lastUsedSolidityNum = latestSolidifiedBlockNumber; } private void processTransactionTrigger(BlockCapsule newBlock) { @@ -2199,7 +2180,6 @@ private void postLogsFilter(final BlockCapsule blockCapsule, boolean solidified, } private void postBlockTrigger(final BlockCapsule blockCapsule) { - // post block and logs for jsonrpc if (CommonParameter.getInstance().isJsonRpcHttpFullNodeEnable()) { postBlockFilter(blockCapsule, false); @@ -2211,7 +2191,7 @@ private void postBlockTrigger(final BlockCapsule blockCapsule) { if (eventPluginLoaded && EventPluginLoader.getInstance().isBlockLogTriggerEnable()) { List capsuleList = new ArrayList<>(); if (EventPluginLoader.getInstance().isBlockLogTriggerSolidified()) { - capsuleList = geContinuousBlockCapsule(solidityBlkNum); + capsuleList = getContinuousBlockCapsule(solidityBlkNum); } else { capsuleList.add(blockCapsule); } @@ -2229,7 +2209,7 @@ private void postBlockTrigger(final BlockCapsule blockCapsule) { if (eventPluginLoaded && EventPluginLoader.getInstance().isTransactionLogTriggerEnable()) { List capsuleList = new ArrayList<>(); if (EventPluginLoader.getInstance().isTransactionLogTriggerSolidified()) { - capsuleList = geContinuousBlockCapsule(solidityBlkNum); + capsuleList = getContinuousBlockCapsule(solidityBlkNum); } else { // need to reset block capsuleList.add(blockCapsule); @@ -2241,13 +2221,13 @@ private void postBlockTrigger(final BlockCapsule blockCapsule) { } } - private List geContinuousBlockCapsule(long solidityBlkNum) { + private List getContinuousBlockCapsule(long solidityBlkNum) { List capsuleList = new ArrayList<>(); - long start = lastUsedSolidityNum < 0 ? (solidityBlkNum - 1) : lastUsedSolidityNum; - if (solidityBlkNum - start > 1) { - logger.info("Continuous block start:{}, end:{}", start + 1, solidityBlkNum); + long start = lastUsedSolidityNum < 0 ? solidityBlkNum : (lastUsedSolidityNum + 1); + if (solidityBlkNum > start) { + logger.info("Continuous block start:{}, end:{}", start, solidityBlkNum); } - for (long blockNum = start + 1; blockNum <= solidityBlkNum; blockNum++) { + for (long blockNum = start; blockNum <= solidityBlkNum; blockNum++) { try { BlockCapsule capsule = chainBaseManager.getBlockByNum(blockNum); capsuleList.add(capsule); From daa656d595db1503e384b180be2bdcd89a6d9783 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 8 Mar 2023 19:28:01 +0800 Subject: [PATCH 0639/1197] fix(db): update log of getContinuousBlockCapsule --- framework/src/main/java/org/tron/core/db/Manager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 3e665a924e4..4e277e9c00b 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -2232,7 +2232,7 @@ private List getContinuousBlockCapsule(long solidityBlkNum) { BlockCapsule capsule = chainBaseManager.getBlockByNum(blockNum); capsuleList.add(capsule); } catch (Exception e) { - logger.error("GetCrossBlockCapsule getBlockByNum blkNum = {} except, error is {}.", + logger.error("GetContinuousBlockCapsule getBlockByNum blkNum = {} except, error is {}.", solidityBlkNum, e.getMessage()); } } From c104e6a63efd61f288457ecc8159a7cf4e300a5c Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 9 Mar 2023 16:15:02 +0800 Subject: [PATCH 0640/1197] update libp2p from test-v0.2.11 to test-v0.2.12 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index f2391f248e7..b31c841bb99 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.11' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.12' compile project(":protocol") } From 4bb4f248501974b78bd51b3563170d32c84354d2 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 9 Mar 2023 20:42:53 +0800 Subject: [PATCH 0641/1197] fix(db): add a config item: node.enableIpv6 --- common/build.gradle | 2 +- .../java/org/tron/common/parameter/CommonParameter.java | 3 +++ common/src/main/java/org/tron/core/Constant.java | 2 +- .../src/main/java/org/tron/core/config/args/Args.java | 4 ++++ .../src/main/java/org/tron/core/net/TronNetService.java | 9 ++++++--- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/common/build.gradle b/common/build.gradle index b31c841bb99..07f9483d8e6 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.12' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.13' compile project(":protocol") } diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index c1eb8d0e489..ad956895bc1 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -191,6 +191,9 @@ public class CommonParameter { public String p2pNodeId; @Getter @Setter + public boolean nodeEnableIpv6 = false; + @Getter + @Setter public List dnsTreeUrls; @Getter @Setter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index c8875c5fa56..ec921f1a858 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -103,7 +103,7 @@ public class Constant { public static final String NODE_P2P_PING_INTERVAL = "node.p2p.pingInterval"; public static final String NODE_P2P_VERSION = "node.p2p.version"; - + public static final String NODE_ENABLE_IPV6 = "node.enableIpv6"; public static final String NODE_DNS_TREE_URLS = "node.dns.treeUrls"; public static final String NODE_DNS_PUBLISH = "node.dns.publish"; public static final String NODE_DNS_DOMAIN = "node.dns.dnsDomain"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index b2ec5b33dd1..7a497bddfc9 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -141,6 +141,7 @@ public static void clearParam() { PARAMETER.nodeDiscoveryPingTimeout = 15000; PARAMETER.nodeP2pPingInterval = 0L; PARAMETER.nodeP2pVersion = 0; + PARAMETER.nodeEnableIpv6 = false; PARAMETER.dnsTreeUrls = new ArrayList<>(); PARAMETER.dnsPublishConfig = null; PARAMETER.rpcPort = 0; @@ -639,6 +640,9 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.NODE_P2P_VERSION) ? config.getInt(Constant.NODE_P2P_VERSION) : 0; + PARAMETER.nodeEnableIpv6 = + config.hasPath(Constant.NODE_ENABLE_IPV6) && config.getBoolean(Constant.NODE_ENABLE_IPV6); + PARAMETER.dnsTreeUrls = config.hasPath(Constant.NODE_DNS_TREE_URLS) ? config.getStringList( Constant.NODE_DNS_TREE_URLS) : new ArrayList<>(); diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index fe1347a8ebc..912b73bd273 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -159,11 +159,14 @@ private P2pConfig getConfig() { config.setDisconnectionPolicyEnable(parameter.isOpenFullTcpDisconnect()); config.setNodeDetectEnable(parameter.isNodeDetectEnable()); config.setDiscoverEnable(parameter.isNodeDiscoveryEnable()); - if (StringUtil.isNullOrEmpty(config.getIp()) && StringUtil.isNullOrEmpty(config.getIpv6())) { + if (StringUtil.isNullOrEmpty(config.getIp())) { config.setIp(parameter.getNodeExternalIp()); } - logger.debug("Local ipv4: {}", config.getIp()); - logger.debug("Local ipv6: {}", config.getIpv6()); + if (!parameter.nodeEnableIpv6) { + config.setIpv6(null); + } + logger.info("Local ipv4: {}", config.getIp()); + logger.info("Local ipv6: {}", config.getIpv6()); config.setTreeUrls(parameter.getDnsTreeUrls()); if (Objects.nonNull(parameter.getDnsPublishConfig())) { config.setPublishConfig(parameter.getDnsPublishConfig()); From 6f27050a7ea4d73049ba36053b3790a8a411193c Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 10 Mar 2023 11:01:58 +0800 Subject: [PATCH 0642/1197] remove local ipv6 from active nodes --- .../src/main/java/org/tron/core/config/args/Args.java | 2 +- .../src/main/java/org/tron/core/net/TronNetService.java | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 7a497bddfc9..308f1071619 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1320,7 +1320,7 @@ private static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Conf if (config.hasPath(Constant.NODE_DNS_MAX_MERGE_SIZE)) { int maxMergeSize = config.getInt(Constant.NODE_DNS_MAX_MERGE_SIZE); if (maxMergeSize >= 1 && maxMergeSize <= 5) { - publishConfig.setChangeThreshold(maxMergeSize); + publishConfig.setMaxMergeSize(maxMergeSize); } else { logger.error("Check {}, should be [1~5], default 5", Constant.NODE_DNS_MAX_MERGE_SIZE); } diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 912b73bd273..687c2595735 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -1,12 +1,12 @@ package org.tron.core.net; -import io.netty.util.internal.StringUtil; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; import java.util.Objects; import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.common.overlay.message.Message; @@ -19,7 +19,6 @@ import org.tron.core.net.peer.PeerStatusCheck; import org.tron.core.net.service.adv.AdvService; import org.tron.core.net.service.fetchblock.FetchBlockService; -import org.tron.core.net.service.keepalive.KeepAliveService; import org.tron.core.net.service.nodepersist.NodePersistService; import org.tron.core.net.service.relay.RelayService; import org.tron.core.net.service.statistics.TronStatsManager; @@ -159,9 +158,12 @@ private P2pConfig getConfig() { config.setDisconnectionPolicyEnable(parameter.isOpenFullTcpDisconnect()); config.setNodeDetectEnable(parameter.isNodeDetectEnable()); config.setDiscoverEnable(parameter.isNodeDiscoveryEnable()); - if (StringUtil.isNullOrEmpty(config.getIp())) { + if (StringUtils.isEmpty(config.getIp())) { config.setIp(parameter.getNodeExternalIp()); } + if (StringUtils.isNotEmpty(config.getIpv6())) { + config.getActiveNodes().remove(new InetSocketAddress(config.getIpv6(), config.getPort())); + } if (!parameter.nodeEnableIpv6) { config.setIpv6(null); } From b909e3bd99180c0e15d2f34b14403180df6189d8 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 13 Mar 2023 17:47:18 +0800 Subject: [PATCH 0643/1197] update libp2p from test-v0.2.13 to test-v0.2.14 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 07f9483d8e6..ad58e68ac31 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.13' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.14' compile project(":protocol") } From 53b6d6bd26446359123098da4bca77c3eb11ee72 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 13 Mar 2023 20:05:59 +0800 Subject: [PATCH 0644/1197] fix(net): set ip to null if node doesn't has ipv4 stack --- .../java/org/tron/core/net/TronNetService.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 687c2595735..2bcb42f6133 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -1,9 +1,11 @@ package org.tron.core.net; +import java.net.Inet4Address; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.Set; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -25,6 +27,7 @@ import org.tron.core.net.service.sync.SyncService; import org.tron.p2p.P2pConfig; import org.tron.p2p.P2pService; +import org.tron.p2p.utils.NetUtil; @Slf4j(topic = "net") @Component @@ -121,6 +124,17 @@ public int fastBroadcastTransaction(TransactionMessage msg) { return advService.fastBroadcastTransaction(msg); } + private boolean hasIpv4Stack() { + Set ipSet = NetUtil.getAllLocalAddress(); + for (String ip : ipSet) { + InetSocketAddress inetSocketAddress = new InetSocketAddress(ip, 10000); + if (inetSocketAddress.getAddress() instanceof Inet4Address) { + return true; + } + } + return false; + } + private P2pConfig getConfig() { List seeds = new ArrayList<>(); seeds.addAll(nodePersistService.dbRead()); @@ -158,7 +172,7 @@ private P2pConfig getConfig() { config.setDisconnectionPolicyEnable(parameter.isOpenFullTcpDisconnect()); config.setNodeDetectEnable(parameter.isNodeDetectEnable()); config.setDiscoverEnable(parameter.isNodeDiscoveryEnable()); - if (StringUtils.isEmpty(config.getIp())) { + if (StringUtils.isEmpty(config.getIp()) && hasIpv4Stack()) { config.setIp(parameter.getNodeExternalIp()); } if (StringUtils.isNotEmpty(config.getIpv6())) { From cebdb364b51fa408c2a8e330b90d6364826b7cc8 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 14 Mar 2023 12:53:54 +0800 Subject: [PATCH 0645/1197] fix(net): use [ipv6]:port instead of ipv6:port --- common/build.gradle | 2 +- .../java/org/tron/core/config/args/Args.java | 27 +++++-------------- .../org/tron/core/net/TronNetService.java | 14 +++++++--- .../test/java/org/tron/core/net/NodeTest.java | 16 ++++++----- 4 files changed, 27 insertions(+), 32 deletions(-) diff --git a/common/build.gradle b/common/build.gradle index ad58e68ac31..14a6f8fdc16 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.14' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.15' compile project(":protocol") } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 308f1071619..702ef3d5e0d 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -75,6 +75,7 @@ import org.tron.keystore.WalletUtils; import org.tron.p2p.dns.update.DnsType; import org.tron.p2p.dns.update.PublishConfig; +import org.tron.p2p.utils.NetUtil; import org.tron.program.Version; @Slf4j(topic = "app") @@ -1197,7 +1198,7 @@ private static List getInetSocketAddress( } List list = config.getStringList(path); for (String configString : list) { - InetSocketAddress inetSocketAddress = parseInetSocketAddress(configString); + InetSocketAddress inetSocketAddress = NetUtil.parseInetSocketAddress(configString); if (inetSocketAddress == null) { continue; } @@ -1218,17 +1219,16 @@ private static List getInetSocketAddress( } private static List getInetAddress( - final com.typesafe.config.Config config, String path) { + final com.typesafe.config.Config config, String path) { List ret = new ArrayList<>(); if (!config.hasPath(path)) { return ret; } List list = config.getStringList(path); for (String configString : list) { - try { - ret.add(InetAddress.getByName(configString.split(":")[0])); - } catch (Exception e) { - logger.warn("Get inet address failed, {}", e.getMessage()); + InetSocketAddress inetSocketAddress = NetUtil.parseInetSocketAddress(configString); + if (inetSocketAddress != null) { + ret.add(inetSocketAddress.getAddress()); } } return ret; @@ -1653,20 +1653,5 @@ public String getOutputDirectory() { } return this.outputDirectory; } - - public static InetSocketAddress parseInetSocketAddress(String para) { - InetSocketAddress address = null; - int index = para.lastIndexOf(":"); - if (index > 0) { - String host = para.substring(0, index); - try { - int port = Integer.parseInt(para.substring(index + 1)); - address = new InetSocketAddress(host, port); - } catch (RuntimeException e) { - logger.error("Invalid inetSocketAddress: {}", para); - } - } - return address; - } } diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 2bcb42f6133..d9bc96c5918 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -1,7 +1,9 @@ package org.tron.core.net; import java.net.Inet4Address; +import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -127,8 +129,14 @@ public int fastBroadcastTransaction(TransactionMessage msg) { private boolean hasIpv4Stack() { Set ipSet = NetUtil.getAllLocalAddress(); for (String ip : ipSet) { - InetSocketAddress inetSocketAddress = new InetSocketAddress(ip, 10000); - if (inetSocketAddress.getAddress() instanceof Inet4Address) { + InetAddress inetAddress; + try { + inetAddress = InetAddress.getByName(ip); + } catch (UnknownHostException e) { + logger.warn("Get inet address failed, {}", e.getMessage()); + continue; + } + if (inetAddress instanceof Inet4Address) { return true; } } @@ -139,7 +147,7 @@ private P2pConfig getConfig() { List seeds = new ArrayList<>(); seeds.addAll(nodePersistService.dbRead()); for (String s : parameter.getSeedNode().getIpList()) { - InetSocketAddress inetSocketAddress = Args.parseInetSocketAddress(s); + InetSocketAddress inetSocketAddress = NetUtil.parseInetSocketAddress(s); if (inetSocketAddress != null) { seeds.add(inetSocketAddress); } diff --git a/framework/src/test/java/org/tron/core/net/NodeTest.java b/framework/src/test/java/org/tron/core/net/NodeTest.java index f97f147193b..90f441c42bf 100644 --- a/framework/src/test/java/org/tron/core/net/NodeTest.java +++ b/framework/src/test/java/org/tron/core/net/NodeTest.java @@ -6,8 +6,8 @@ import lombok.extern.slf4j.Slf4j; import org.junit.Assert; import org.junit.Test; -import org.tron.core.config.args.Args; import org.tron.p2p.discover.Node; +import org.tron.p2p.utils.NetUtil; import org.tron.protos.Discover.Endpoint; @Slf4j @@ -15,18 +15,20 @@ public class NodeTest { @Test public void testIpV4() { - InetSocketAddress address1 = Args.parseInetSocketAddress("192.168.0.1:18888"); + InetSocketAddress address1 = NetUtil.parseInetSocketAddress("192.168.0.1:18888"); Assert.assertNotNull(address1); - InetSocketAddress address2 = Args.parseInetSocketAddress("192.168.0.1"); + InetSocketAddress address2 = NetUtil.parseInetSocketAddress("192.168.0.1"); Assert.assertNull(address2); } @Test public void testIpV6() { - InetSocketAddress address1 = Args.parseInetSocketAddress("fe80::216:3eff:fe0e:23bb:18888"); - Assert.assertNotNull(address1); - InetSocketAddress address2 = Args.parseInetSocketAddress("fe80::216:3eff:fe0e:23bb"); - Assert.assertNull(address2); + InetSocketAddress address1 = NetUtil.parseInetSocketAddress("fe80::216:3eff:fe0e:23bb:18888"); + Assert.assertNull(address1); + InetSocketAddress address2 = NetUtil.parseInetSocketAddress("[fe80::216:3eff:fe0e:23bb]:18888"); + Assert.assertNotNull(address2); + InetSocketAddress address3 = NetUtil.parseInetSocketAddress("fe80::216:3eff:fe0e:23bb"); + Assert.assertNull(address3); } @Test From fcf3366a47479d1f2fb530ce9123a9901cc5e875 Mon Sep 17 00:00:00 2001 From: guoquanwu Date: Mon, 13 Mar 2023 19:15:52 +0800 Subject: [PATCH 0646/1197] fix(json-rpc): fix address generation of contract which created by `create2` --- .../services/jsonrpc/TronJsonRpcImpl.java | 1 + .../tron/common/runtime/vm/Create2Test.java | 24 ++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 453710b931b..9b9dbbdfe70 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -496,6 +496,7 @@ public String getStorageAt(String address, String storageIdx, String blockNumOrT StorageRowStore store = manager.getStorageRowStore(); Storage storage = new Storage(addressByte, store); storage.setContractVersion(smartContract.getVersion()); + storage.generateAddrHash(smartContract.getTrxHash().toByteArray()); DataWord value = storage.getValue(new DataWord(ByteArray.fromHexString(storageIdx))); return ByteArray.toJsonHex(value == null ? new byte[32] : value.getData()); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java index 137bb180dc0..074b157f115 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java @@ -11,11 +11,16 @@ import org.testng.Assert; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; +import org.tron.common.utils.ByteArray; import org.tron.common.utils.WalletUtil; +import org.tron.core.Wallet; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; +import org.tron.core.exception.JsonRpcInvalidParamsException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; +import org.tron.core.services.NodeInfoService; +import org.tron.core.services.jsonrpc.TronJsonRpcImpl; import org.tron.protos.Protocol.Transaction; import stest.tron.wallet.common.client.utils.AbiUtil; import stest.tron.wallet.common.client.utils.DataWord; @@ -171,7 +176,8 @@ public void testCreate2() // trigger deployed contract String methodToTrigger = "plusOne()"; - for (int i = 1; i < 3; i++) { + long loop = 2; + for (int i = 1; i <= loop; i++) { hexInput = AbiUtil.parseMethod(methodToTrigger, Collections.emptyList()); result = TvmTestUtils .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), @@ -179,6 +185,22 @@ public void testCreate2() Assert.assertNull(result.getRuntime().getRuntimeError()); Assert.assertEquals(result.getRuntime().getResult().getHReturn(), new DataWord(i).getData()); } + testJsonRpc(actualContract, loop); + } + + private void testJsonRpc(byte[] actualContract, long loop) { + TronJsonRpcImpl tronJsonRpc; + NodeInfoService nodeInfoService; + nodeInfoService = context.getBean(NodeInfoService.class); + Wallet wallet = context.getBean(Wallet.class); + tronJsonRpc = new TronJsonRpcImpl(nodeInfoService, wallet, manager); + try { + String res = + tronJsonRpc.getStorageAt(ByteArray.toHexString(actualContract), "0", "latest"); + Assert.assertEquals(loop, ByteArray.jsonHexToLong(res)); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } } /* From 72fde485616b0f4c40e3b06c26abe98a5c25379b Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 14 Mar 2023 14:08:28 +0800 Subject: [PATCH 0647/1197] fix(net): update libp2p from test-v0.2.15 to test-v0.2.16 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 14a6f8fdc16..e229ef2119b 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.15' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.16' compile project(":protocol") } From 9b233e3a70b605b4b51aff44ca90ed00333a9052 Mon Sep 17 00:00:00 2001 From: Asuka Date: Tue, 14 Mar 2023 15:52:04 +0800 Subject: [PATCH 0648/1197] feat(interface): optimize TriggerSmartContract and TriggerConstantContract - support call_data parameter - support deploying contract for TriggerConstantContract --- .../http/TriggerConstantContractServlet.java | 38 +++++++++++-------- .../http/TriggerSmartContractServlet.java | 30 ++++++++------- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java b/framework/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java index 4c4b6908a6e..1baed135039 100644 --- a/framework/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java @@ -27,7 +27,11 @@ @Slf4j(topic = "API") public class TriggerConstantContractServlet extends RateLimiterServlet { - private final String functionSelector = "function_selector"; + private final String OWNER_ADDRESS = "owner_address"; + private final String CONTRACT_ADDRESS = "contract_address"; + private final String FUNCTION_SELECTOR = "function_selector"; + private final String FUNCTION_PARAMETER = "parameter"; + private final String CALL_DATA = "data"; @Autowired private Wallet wallet; @@ -37,13 +41,19 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { protected void validateParameter(String contract) { JSONObject jsonObject = JSONObject.parseObject(contract); - if (!jsonObject.containsKey("owner_address") - || StringUtil.isNullOrEmpty(jsonObject.getString("owner_address"))) { - throw new InvalidParameterException("owner_address isn't set."); + if (StringUtil.isNullOrEmpty(jsonObject.getString(OWNER_ADDRESS))) { + throw new InvalidParameterException(OWNER_ADDRESS + " isn't set."); } - if (!jsonObject.containsKey("contract_address") - || StringUtil.isNullOrEmpty(jsonObject.getString("contract_address"))) { - throw new InvalidParameterException("contract_address isn't set."); + if (StringUtil.isNullOrEmpty(jsonObject.getString(CONTRACT_ADDRESS))) { + if (StringUtil.isNullOrEmpty(jsonObject.getString(CALL_DATA))) { + throw new InvalidParameterException("At least one of " + + CONTRACT_ADDRESS + " and " + CALL_DATA + " must be set."); + } + } + if (!StringUtil.isNullOrEmpty(jsonObject.getString(FUNCTION_SELECTOR)) + && !StringUtil.isNullOrEmpty(jsonObject.getString(CALL_DATA))) { + throw new InvalidParameterException("Only one of " + + FUNCTION_SELECTOR + " and " + CALL_DATA + " can be set."); } } @@ -62,17 +72,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) JsonFormat.merge(contract, build, visible); JSONObject jsonObject = JSONObject.parseObject(contract); - boolean isFunctionSelectorSet = jsonObject.containsKey(functionSelector) - && !StringUtil.isNullOrEmpty(jsonObject.getString(functionSelector)); - String data; + boolean isFunctionSelectorSet = + !StringUtil.isNullOrEmpty(jsonObject.getString(FUNCTION_SELECTOR)); if (isFunctionSelectorSet) { - String selector = jsonObject.getString(functionSelector); - String parameter = jsonObject.getString("parameter"); - data = Util.parseMethod(selector, parameter); + String selector = jsonObject.getString(FUNCTION_SELECTOR); + String parameter = jsonObject.getString(FUNCTION_PARAMETER); + String data = Util.parseMethod(selector, parameter); build.setData(ByteString.copyFrom(ByteArray.fromHexString(data))); - } else { - build.setData(ByteString.copyFrom(new byte[0])); } + TransactionCapsule trxCap = wallet .createTransactionCapsule(build.build(), ContractType.TriggerSmartContract); diff --git a/framework/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java b/framework/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java index 345475cbec5..23481fff8e8 100644 --- a/framework/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java @@ -27,7 +27,11 @@ @Slf4j(topic = "API") public class TriggerSmartContractServlet extends RateLimiterServlet { - private final String functionSelector = "function_selector"; + private final String OWNER_ADDRESS = "owner_address"; + private final String CONTRACT_ADDRESS = "contract_address"; + private final String FUNCTION_SELECTOR = "function_selector"; + private final String FUNCTION_PARAMETER = "parameter"; + private final String CALL_DATA = "data"; @Autowired private Wallet wallet; @@ -37,14 +41,17 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { protected void validateParameter(String contract) { JSONObject jsonObject = JSONObject.parseObject(contract); - if (!jsonObject.containsKey("owner_address") - || StringUtil.isNullOrEmpty(jsonObject.getString("owner_address"))) { + if (StringUtil.isNullOrEmpty(jsonObject.getString(OWNER_ADDRESS))) { throw new InvalidParameterException("owner_address isn't set."); } - if (!jsonObject.containsKey("contract_address") - || StringUtil.isNullOrEmpty(jsonObject.getString("contract_address"))) { + if (StringUtil.isNullOrEmpty(jsonObject.getString(CONTRACT_ADDRESS))) { throw new InvalidParameterException("contract_address isn't set."); } + if (!StringUtil.isNullOrEmpty(jsonObject.getString(FUNCTION_SELECTOR)) + && !StringUtil.isNullOrEmpty(jsonObject.getString(CALL_DATA))) { + throw new InvalidParameterException("Only one of " + + FUNCTION_SELECTOR + " and " + CALL_DATA + " can be set."); + } } protected void doPost(HttpServletRequest request, HttpServletResponse response) @@ -62,16 +69,13 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) JsonFormat.merge(contract, build, visible); JSONObject jsonObject = JSONObject.parseObject(contract); - boolean isFunctionSelectorSet = jsonObject.containsKey(functionSelector) - && !StringUtil.isNullOrEmpty(jsonObject.getString(functionSelector)); - String data; + boolean isFunctionSelectorSet = + !StringUtil.isNullOrEmpty(jsonObject.getString(FUNCTION_SELECTOR)); if (isFunctionSelectorSet) { - String selector = jsonObject.getString(functionSelector); - String parameter = jsonObject.getString("parameter"); - data = Util.parseMethod(selector, parameter); + String selector = jsonObject.getString(FUNCTION_SELECTOR); + String parameter = jsonObject.getString(FUNCTION_PARAMETER); + String data = Util.parseMethod(selector, parameter); build.setData(ByteString.copyFrom(ByteArray.fromHexString(data))); - } else { - build.setData(ByteString.copyFrom(new byte[0])); } build.setCallTokenValue(Util.getJsonLongValue(jsonObject, "call_token_value")); From 46ea86631264e93881f8708d8b3a5a93abdf155a Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 14 Mar 2023 17:52:10 +0800 Subject: [PATCH 0649/1197] fix(net):update libp2p from test-v0.2.16 to test-v0.2.17 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index e229ef2119b..329676bf560 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.16' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.17' compile project(":protocol") } From 437ebb1e273a9d8f5f01b4664d942b02483ddcae Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 14 Mar 2023 19:34:48 +0800 Subject: [PATCH 0650/1197] fix(net): check seed ip's format in class Args --- .../org/tron/core/config/args/SeedNode.java | 3 ++- .../java/org/tron/core/config/args/Args.java | 26 ++++++++++++++----- .../org/tron/core/net/TronNetService.java | 9 +------ .../tron/core/services/NodeInfoService.java | 4 +-- .../org/tron/core/config/args/ArgsTest.java | 2 +- .../core/metrics/MetricsApiServiceTest.java | 2 +- .../test/java/org/tron/core/net/BaseNet.java | 2 +- 7 files changed, 27 insertions(+), 21 deletions(-) diff --git a/common/src/main/java/org/tron/core/config/args/SeedNode.java b/common/src/main/java/org/tron/core/config/args/SeedNode.java index 6597110074d..9420d969789 100644 --- a/common/src/main/java/org/tron/core/config/args/SeedNode.java +++ b/common/src/main/java/org/tron/core/config/args/SeedNode.java @@ -1,5 +1,6 @@ package org.tron.core.config.args; +import java.net.InetSocketAddress; import java.util.List; import lombok.Getter; import lombok.Setter; @@ -8,5 +9,5 @@ public class SeedNode { @Getter @Setter - private List ipList; + private List addressList; } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 702ef3d5e0d..5c887ec37d2 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -523,9 +523,7 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.storage.setCacheStrategies(config); PARAMETER.seedNode = new SeedNode(); - PARAMETER.seedNode.setIpList(Optional.ofNullable(PARAMETER.seedNodes) - .filter(seedNode -> 0 != seedNode.size()) - .orElse(config.getStringList(Constant.SEED_NODE_IP_LIST))); + PARAMETER.seedNode.setAddressList(loadSeeds(config)); if (config.hasPath(Constant.GENESIS_BLOCK)) { PARAMETER.genesisBlock = new GenesisBlock(); @@ -1202,9 +1200,9 @@ private static List getInetSocketAddress( if (inetSocketAddress == null) { continue; } - String ip = inetSocketAddress.getAddress().getHostAddress(); - int port = inetSocketAddress.getPort(); if (filter) { + String ip = inetSocketAddress.getAddress().getHostAddress(); + int port = inetSocketAddress.getPort(); if (!(PARAMETER.nodeDiscoveryBindIp.equals(ip) || PARAMETER.nodeExternalIp.equals(ip) || Constant.LOCAL_HOST.equals(ip)) @@ -1293,6 +1291,22 @@ private static EventPluginConfig getEventPluginConfig( return eventPluginConfig; } + private static List loadSeeds(final com.typesafe.config.Config config) { + List inetSocketAddressList = new ArrayList<>(); + if (PARAMETER.seedNodes != null && !PARAMETER.seedNodes.isEmpty()) { + for (String s : PARAMETER.seedNodes) { + InetSocketAddress inetSocketAddress = NetUtil.parseInetSocketAddress(s); + if (inetSocketAddress != null) { + inetSocketAddressList.add(inetSocketAddress); + } + } + } else { + inetSocketAddressList = getInetSocketAddress(config, Constant.SEED_NODE_IP_LIST, false); + } + + return inetSocketAddressList; + } + private static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Config config) { PublishConfig publishConfig = new PublishConfig(); if (config.hasPath(Constant.NODE_DNS_PUBLISH)) { @@ -1598,7 +1612,7 @@ public static void logConfig() { logger.info("Passive node size: {}", parameter.getPassiveNodes().size()); logger.info("FastForward node size: {}", parameter.getFastForwardNodes().size()); logger.info("FastForward node number: {}", parameter.getMaxFastForwardNum()); - logger.info("Seed node size: {}", parameter.getSeedNode().getIpList().size()); + logger.info("Seed node size: {}", parameter.getSeedNode().getAddressList().size()); logger.info("Max connection: {}", parameter.getMaxConnections()); logger.info("Min connection: {}", parameter.getMinConnections()); logger.info("Min active connection: {}", parameter.getMinActiveConnections()); diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index d9bc96c5918..f886b06bfab 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -4,7 +4,6 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; -import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Set; @@ -144,14 +143,8 @@ private boolean hasIpv4Stack() { } private P2pConfig getConfig() { - List seeds = new ArrayList<>(); + List seeds = parameter.getSeedNode().getAddressList(); seeds.addAll(nodePersistService.dbRead()); - for (String s : parameter.getSeedNode().getIpList()) { - InetSocketAddress inetSocketAddress = NetUtil.parseInetSocketAddress(s); - if (inetSocketAddress != null) { - seeds.add(inetSocketAddress); - } - } for (InetSocketAddress inetSocketAddress : seeds) { logger.debug("Seed InetSocketAddress: {}", inetSocketAddress); } diff --git a/framework/src/main/java/org/tron/core/services/NodeInfoService.java b/framework/src/main/java/org/tron/core/services/NodeInfoService.java index b08f0107760..ddf72c64410 100644 --- a/framework/src/main/java/org/tron/core/services/NodeInfoService.java +++ b/framework/src/main/java/org/tron/core/services/NodeInfoService.java @@ -27,12 +27,10 @@ import org.tron.common.prometheus.MetricTime; import org.tron.core.ChainBaseManager; import org.tron.core.db.Manager; -import org.tron.core.net.P2pEventHandlerImpl; import org.tron.core.net.TronNetService; import org.tron.core.net.peer.PeerConnection; import org.tron.core.net.peer.PeerManager; import org.tron.core.net.service.statistics.NodeStatistics; -import org.tron.core.net.service.statistics.PeerStatistics; import org.tron.core.services.WitnessProductBlockService.CheatWitnessInfo; import org.tron.p2p.P2pConfig; import org.tron.p2p.P2pService; @@ -180,7 +178,7 @@ private void setConfigNodeInfo(NodeInfo nodeInfo) { configNodeInfo.setDiscoverEnable(parameter.isNodeDiscoveryEnable()); configNodeInfo.setActiveNodeSize(parameter.getActiveNodes().size()); configNodeInfo.setPassiveNodeSize(parameter.getPassiveNodes().size()); - configNodeInfo.setSendNodeSize(parameter.getSeedNode().getIpList().size()); + configNodeInfo.setSendNodeSize(parameter.getSeedNode().getAddressList().size()); configNodeInfo.setMaxConnectCount(parameter.getMaxConnections()); configNodeInfo.setSameIpMaxConnectCount(parameter.getMaxConnectionsWithSameIp()); configNodeInfo.setBackupListenPort(parameter.getBackupPort()); diff --git a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java index 5768fc0b1d8..20d9e979fee 100644 --- a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java @@ -51,7 +51,7 @@ public void get() { Assert.assertEquals("database", parameter.getStorage().getDbDirectory()); - Assert.assertEquals(11, parameter.getSeedNode().getIpList().size()); + Assert.assertEquals(11, parameter.getSeedNode().getAddressList().size()); GenesisBlock genesisBlock = parameter.getGenesisBlock(); diff --git a/framework/src/test/java/org/tron/core/metrics/MetricsApiServiceTest.java b/framework/src/test/java/org/tron/core/metrics/MetricsApiServiceTest.java index dfe658080fc..714faea05d9 100644 --- a/framework/src/test/java/org/tron/core/metrics/MetricsApiServiceTest.java +++ b/framework/src/test/java/org/tron/core/metrics/MetricsApiServiceTest.java @@ -45,7 +45,7 @@ public void init() { ); CommonParameter parameter = Args.getInstance(); parameter.setNodeListenPort(port); - parameter.getSeedNode().getIpList().clear(); + parameter.getSeedNode().getAddressList().clear(); parameter.setNodeExternalIp("127.0.0.1"); context = new TronApplicationContext(DefaultConfig.class); appT = ApplicationFactory.create(context); diff --git a/framework/src/test/java/org/tron/core/net/BaseNet.java b/framework/src/test/java/org/tron/core/net/BaseNet.java index bb7ca85ef7f..ca42dc2a65e 100644 --- a/framework/src/test/java/org/tron/core/net/BaseNet.java +++ b/framework/src/test/java/org/tron/core/net/BaseNet.java @@ -89,7 +89,7 @@ public void run() { ); CommonParameter parameter = Args.getInstance(); parameter.setNodeListenPort(port); - parameter.getSeedNode().getIpList().clear(); + parameter.getSeedNode().getAddressList().clear(); parameter.setNodeExternalIp(Constant.LOCAL_HOST); context = new TronApplicationContext(DefaultConfig.class); appT = ApplicationFactory.create(context); From 50082a1eba1b6b7046d856fa452f0638e71f7e7b Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 16 Mar 2023 15:29:57 +0800 Subject: [PATCH 0651/1197] feat(net): add global rate limiter function --- .../common/parameter/CommonParameter.java | 6 ++++ .../src/main/java/org/tron/core/Constant.java | 4 +++ .../java/org/tron/core/config/args/Args.java | 10 ++++++ .../services/http/RateLimiterServlet.java | 7 +++- .../ratelimiter/GlobalRateLimiter.java | 35 +++++++++++++++++++ .../ratelimiter/RateLimiterInterceptor.java | 5 ++- .../org/tron/common/config/args/ArgsTest.java | 2 ++ 7 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/services/ratelimiter/GlobalRateLimiter.java diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index ab04ca3e7a4..0c05733fec1 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -398,6 +398,12 @@ public class CommonParameter { @Setter public RateLimiterInitialization rateLimiterInitialization; @Getter + @Setter + public int rateLimiterGlobalQps; + @Getter + @Setter + public int rateLimiterGlobalIpQps; + @Getter public DbBackupConfig dbBackupConfig; @Getter public RocksDbSettings rocksDBCustomSettings; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 408782752f2..cd0de4d478d 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -235,6 +235,10 @@ public class Constant { public static final String RATE_LIMITER = "rate.limiter"; + public static final String RATE_LIMITER_GLOBAL_QPS = "rate.limiter.global.qps"; + + public static final String RATE_LIMITER_GLOBAL_IP_QPS = "rate.limiter.global.ip.qps"; + public static final String COMMITTEE_CHANGED_DELEGATION = "committee.changedDelegation"; public static final String CRYPTO_ENGINE = "crypto.engine"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 8e6a7526362..3d2c2e8a66a 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -221,6 +221,8 @@ public static void clearParam() { PARAMETER.allowNewRewardAlgorithm = 0; PARAMETER.allowNewReward = 0; PARAMETER.memoFee = 0; + PARAMETER.rateLimiterGlobalQps = 3000; + PARAMETER.rateLimiterGlobalIpQps = 30; } /** @@ -927,6 +929,14 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.fullNodeAllowShieldedTransactionArgs = true; } + PARAMETER.rateLimiterGlobalQps = + config.hasPath(Constant.RATE_LIMITER_GLOBAL_QPS) ? config + .getInt(Constant.RATE_LIMITER_GLOBAL_QPS) : 3000; + + PARAMETER.rateLimiterGlobalIpQps = + config.hasPath(Constant.RATE_LIMITER_GLOBAL_IP_QPS) ? config + .getInt(Constant.RATE_LIMITER_GLOBAL_IP_QPS) : 30; + PARAMETER.rateLimiterInitialization = config.hasPath(Constant.RATE_LIMITER) ? getRateLimiterFromConfig(config) : new RateLimiterInitialization(); diff --git a/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java b/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java index 53eb1067fd3..eb8b7b86257 100644 --- a/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java @@ -16,6 +16,7 @@ import org.tron.common.prometheus.MetricLabels; import org.tron.common.prometheus.Metrics; import org.tron.core.config.args.Args; +import org.tron.core.services.ratelimiter.GlobalRateLimiter; import org.tron.core.services.ratelimiter.RateLimiterContainer; import org.tron.core.services.ratelimiter.RuntimeData; import org.tron.core.services.ratelimiter.adapter.DefaultBaseQqsAdapter; @@ -91,12 +92,16 @@ private void addRateContainer() { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + + RuntimeData runtimeData = new RuntimeData(req); + GlobalRateLimiter.acquire(runtimeData); + IRateLimiter rateLimiter = container.get(KEY_PREFIX_HTTP, getClass().getSimpleName()); boolean acquireResource = true; if (rateLimiter != null) { - acquireResource = rateLimiter.acquire(new RuntimeData(req)); + acquireResource = rateLimiter.acquire(runtimeData); } String url = Strings.isNullOrEmpty(req.getRequestURI()) ? MetricLabels.UNDEFINED : req.getRequestURI(); diff --git a/framework/src/main/java/org/tron/core/services/ratelimiter/GlobalRateLimiter.java b/framework/src/main/java/org/tron/core/services/ratelimiter/GlobalRateLimiter.java new file mode 100644 index 00000000000..a3b1638ac95 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/ratelimiter/GlobalRateLimiter.java @@ -0,0 +1,35 @@ +package org.tron.core.services.ratelimiter; + +import com.google.common.base.Strings; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.util.concurrent.RateLimiter; +import java.util.concurrent.TimeUnit; +import org.tron.core.config.args.Args; + +public class GlobalRateLimiter { + + private static double QPS = Args.getInstance().getRateLimiterGlobalQps(); + + private static double IP_QPS = Args.getInstance().getRateLimiterGlobalIpQps(); + + private static Cache cache = CacheBuilder.newBuilder() + .maximumSize(10000).expireAfterWrite(1, TimeUnit.HOURS).build(); + + private static RateLimiter rateLimiter = RateLimiter.create(QPS); + + public static void acquire(RuntimeData runtimeData) { + rateLimiter.acquire(); + String ip = runtimeData.getRemoteAddr(); + if (Strings.isNullOrEmpty(ip)) { + return; + } + RateLimiter r = cache.getIfPresent(ip); + if (r == null) { + r = RateLimiter.create(IP_QPS); + cache.put(ip, r); + } + r.acquire(); + } + +} diff --git a/framework/src/main/java/org/tron/core/services/ratelimiter/RateLimiterInterceptor.java b/framework/src/main/java/org/tron/core/services/ratelimiter/RateLimiterInterceptor.java index a74f89df517..d629ae05abd 100644 --- a/framework/src/main/java/org/tron/core/services/ratelimiter/RateLimiterInterceptor.java +++ b/framework/src/main/java/org/tron/core/services/ratelimiter/RateLimiterInterceptor.java @@ -107,10 +107,13 @@ public Listener interceptCall(ServerCall call, IRateLimiter rateLimiter = container .get(KEY_PREFIX_RPC, call.getMethodDescriptor().getFullMethodName()); + RuntimeData runtimeData = new RuntimeData(call); + GlobalRateLimiter.acquire(runtimeData); + boolean acquireResource = true; if (rateLimiter != null) { - acquireResource = rateLimiter.acquire(new RuntimeData(call)); + acquireResource = rateLimiter.acquire(runtimeData); } Listener listener = new ServerCall.Listener() { diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index 5b391f0d38d..feeb628e035 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -30,5 +30,7 @@ public void testConfig() { Assert.assertEquals(Args.getInstance().getNodeDiscoveryPingTimeout(), 15_000); Assert.assertEquals(Args.getInstance().getMaxFastForwardNum(), 3); Assert.assertEquals(Args.getInstance().getBlockCacheTimeout(), 60); + Assert.assertEquals(Args.getInstance().getRateLimiterGlobalQps(), 3000); + Assert.assertEquals(Args.getInstance().getRateLimiterGlobalIpQps(), 30); } } \ No newline at end of file From dac20fc92112f57d6d944c28ba905f23025efa59 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 16 Mar 2023 17:51:50 +0800 Subject: [PATCH 0652/1197] fix(net): add some test case --- .../java/org/tron/core/config/args/Args.java | 2 +- .../org/tron/core/net/TronNetService.java | 5 +- .../test/java/org/tron/core/net/NodeTest.java | 55 +++++++++++++++++-- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 5c887ec37d2..70a3174748e 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1307,7 +1307,7 @@ private static List loadSeeds(final com.typesafe.config.Confi return inetSocketAddressList; } - private static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Config config) { + public static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Config config) { PublishConfig publishConfig = new PublishConfig(); if (config.hasPath(Constant.NODE_DNS_PUBLISH)) { publishConfig.setDnsPublishEnable(config.getBoolean(Constant.NODE_DNS_PUBLISH)); diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index f886b06bfab..561c3cbae9e 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -125,8 +125,7 @@ public int fastBroadcastTransaction(TransactionMessage msg) { return advService.fastBroadcastTransaction(msg); } - private boolean hasIpv4Stack() { - Set ipSet = NetUtil.getAllLocalAddress(); + public static boolean hasIpv4Stack(Set ipSet) { for (String ip : ipSet) { InetAddress inetAddress; try { @@ -173,7 +172,7 @@ private P2pConfig getConfig() { config.setDisconnectionPolicyEnable(parameter.isOpenFullTcpDisconnect()); config.setNodeDetectEnable(parameter.isNodeDetectEnable()); config.setDiscoverEnable(parameter.isNodeDiscoveryEnable()); - if (StringUtils.isEmpty(config.getIp()) && hasIpv4Stack()) { + if (StringUtils.isEmpty(config.getIp()) && hasIpv4Stack(NetUtil.getAllLocalAddress())) { config.setIp(parameter.getNodeExternalIp()); } if (StringUtils.isNotEmpty(config.getIpv6())) { diff --git a/framework/src/test/java/org/tron/core/net/NodeTest.java b/framework/src/test/java/org/tron/core/net/NodeTest.java index 90f441c42bf..ac01a46dbc8 100644 --- a/framework/src/test/java/org/tron/core/net/NodeTest.java +++ b/framework/src/test/java/org/tron/core/net/NodeTest.java @@ -2,11 +2,20 @@ import static org.tron.core.net.message.handshake.HelloMessage.getEndpointFromNode; +import com.typesafe.config.Config; import java.net.InetSocketAddress; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; import org.junit.Test; +import org.tron.core.Constant; +import org.tron.core.config.Configuration; +import org.tron.core.config.args.Args; import org.tron.p2p.discover.Node; +import org.tron.p2p.dns.update.PublishConfig; import org.tron.p2p.utils.NetUtil; import org.tron.protos.Discover.Endpoint; @@ -17,18 +26,44 @@ public class NodeTest { public void testIpV4() { InetSocketAddress address1 = NetUtil.parseInetSocketAddress("192.168.0.1:18888"); Assert.assertNotNull(address1); - InetSocketAddress address2 = NetUtil.parseInetSocketAddress("192.168.0.1"); - Assert.assertNull(address2); + try { + NetUtil.parseInetSocketAddress("192.168.0.1"); + Assert.fail(); + } catch (RuntimeException e) { + Assert.assertTrue(true); + } } @Test public void testIpV6() { - InetSocketAddress address1 = NetUtil.parseInetSocketAddress("fe80::216:3eff:fe0e:23bb:18888"); - Assert.assertNull(address1); + try { + NetUtil.parseInetSocketAddress("fe80::216:3eff:fe0e:23bb:18888"); + Assert.fail(); + } catch (RuntimeException e) { + Assert.assertTrue(true); + } InetSocketAddress address2 = NetUtil.parseInetSocketAddress("[fe80::216:3eff:fe0e:23bb]:18888"); Assert.assertNotNull(address2); - InetSocketAddress address3 = NetUtil.parseInetSocketAddress("fe80::216:3eff:fe0e:23bb"); - Assert.assertNull(address3); + try { + NetUtil.parseInetSocketAddress("fe80::216:3eff:fe0e:23bb"); + Assert.fail(); + } catch (RuntimeException e) { + Assert.assertTrue(true); + } + } + + @Test + public void testIpStack() { + Set ipSet = new HashSet<>(Collections.singletonList("192.168.0.1")); + Assert.assertTrue(TronNetService.hasIpv4Stack(ipSet)); + ipSet = new HashSet<>(Collections.singletonList("127.0.0.1")); + Assert.assertTrue(TronNetService.hasIpv4Stack(ipSet)); + ipSet = new HashSet<>(Collections.singletonList("fe80:0:0:0:0:0:0:1")); + Assert.assertFalse(TronNetService.hasIpv4Stack(ipSet)); + ipSet = new HashSet<>(Arrays.asList("127.0.0.1", "fe80:0:0:0:0:0:0:1")); + Assert.assertTrue(TronNetService.hasIpv4Stack(ipSet)); + ipSet = new HashSet<>(Collections.emptyList()); + Assert.assertFalse(TronNetService.hasIpv4Stack(ipSet)); } @Test @@ -39,4 +74,12 @@ public void testEndpointFromNode() { Assert.assertTrue(endpoint.getAddress().isEmpty()); Assert.assertTrue(endpoint.getAddressIpv6().isEmpty()); } + + @Test + public void testPublishConfig() { + Config config = Configuration.getByFileName(Constant.TEST_CONF, Constant.TEST_CONF); + PublishConfig publishConfig = Args.loadDnsPublishConfig(config); + assert publishConfig != null; + Assert.assertFalse(publishConfig.isDnsPublishEnable()); + } } From 248496ec9005b3f05392e0fe2803901c36974e89 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 16 Mar 2023 18:09:05 +0800 Subject: [PATCH 0653/1197] feat(net): add EffectiveService to get effective connection --- common/build.gradle | 2 +- .../org/tron/core/net/TronNetService.java | 6 + .../service/effective/EffectiveService.java | 156 ++++++++++++++++++ .../service/handshake/HandshakeService.java | 21 +++ 4 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 framework/src/main/java/org/tron/core/net/service/effective/EffectiveService.java diff --git a/common/build.gradle b/common/build.gradle index 329676bf560..bd5b400ae38 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.17' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-callback-v1' compile project(":protocol") } diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index f886b06bfab..ec082ae38cf 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -21,6 +21,7 @@ import org.tron.core.net.peer.PeerManager; import org.tron.core.net.peer.PeerStatusCheck; import org.tron.core.net.service.adv.AdvService; +import org.tron.core.net.service.effective.EffectiveService; import org.tron.core.net.service.fetchblock.FetchBlockService; import org.tron.core.net.service.nodepersist.NodePersistService; import org.tron.core.net.service.relay.RelayService; @@ -69,6 +70,9 @@ public class TronNetService { @Autowired private RelayService relayService; + @Autowired + private EffectiveService effectiveService; + private volatile boolean init; private static void setP2pConfig(P2pConfig config) { @@ -90,6 +94,7 @@ public void start() { tronStatsManager.init(); PeerManager.init(); relayService.init(); + effectiveService.init(); logger.info("Net service start successfully"); } catch (Exception e) { logger.error("Net service start failed", e); @@ -110,6 +115,7 @@ public void close() { fetchBlockService.close(); p2pService.close(); relayService.close(); + effectiveService.close(); logger.info("Net service closed successfully"); } diff --git a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveService.java b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveService.java new file mode 100644 index 00000000000..78c33d7af21 --- /dev/null +++ b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveService.java @@ -0,0 +1,156 @@ +package org.tron.core.net.service.effective; + + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import io.netty.channel.ChannelFutureListener; +import java.net.InetSocketAddress; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.TronNetService; +import org.tron.core.net.peer.PeerConnection; +import org.tron.p2p.discover.Node; +import org.tron.p2p.utils.NetUtil; +import org.tron.protos.Protocol.ReasonCode; + +@Slf4j(topic = "net") +@Component +public class EffectiveService { + + @Autowired + private TronNetDelegate tronNetDelegate; + + private final Cache nodesCache = CacheBuilder.newBuilder() + .initialCapacity(100) + .maximumSize(1000) + .expireAfterWrite(10, TimeUnit.MINUTES).build(); + @Getter + private InetSocketAddress cur = null; + private final AtomicInteger tryCount = new AtomicInteger(0); + @Setter + private boolean found = false; + + private final ScheduledExecutorService executor = Executors + .newSingleThreadScheduledExecutor( + new ThreadFactoryBuilder().setNameFormat("effective-thread-%d").build()); + + public void init() { + executor.scheduleWithFixedDelay(() -> { + try { + findEffectiveNode(); + } catch (Exception e) { + logger.error("Check effective connection processing failed", e); + } + }, 1 * 60, 5, TimeUnit.SECONDS); + } + + public void close() { + try { + executor.shutdownNow(); + } catch (Exception e) { + logger.error("Exception in shutdown effective service worker, {}", e.getMessage()); + } + } + + public boolean isIsolateLand() { + int count = (int) tronNetDelegate.getActivePeer().stream() + .filter(PeerConnection::isNeedSyncFromUs) + .count(); + return count == tronNetDelegate.getActivePeer().size(); + } + + private synchronized void findEffectiveNode() throws InterruptedException { + if (!isIsolateLand()) { + resetCount(); + return; + } + if (found) { + Thread.sleep(10_000);//wait found node to sync + if (isIsolateLand()) { + found = false; + disconnect(); + } + return; + } + + //hashcode of PeerConnection = hashcode of InetSocketAddress + if (cur != null && tronNetDelegate.getActivePeer().contains(cur)) { + // we encounter no effective connection again, so we disconnect with last used node + disconnect(); + return; + } + + List tableNodes = TronNetService.getP2pService().getAllNodes(); + for (Node node : tableNodes) { + if (node.getId() == null) { + node.setId(NetUtil.getNodeId()); + } + } + + Optional chosenNode = tableNodes.stream() + .filter(node -> nodesCache.getIfPresent(node.getPreferInetSocketAddress()) == null) + .filter(node -> !TronNetService.getP2pConfig().getActiveNodes() + .contains(node.getPreferInetSocketAddress())) + .findFirst(); + if (!chosenNode.isPresent()) { + logger.warn("Failed to find effective node, have tried {} times", tryCount.get()); + resetCount(); + return; + } + + tryCount.incrementAndGet(); + nodesCache.put(chosenNode.get().getPreferInetSocketAddress(), true); + cur = new InetSocketAddress(chosenNode.get().getPreferInetSocketAddress().getAddress(), + chosenNode.get().getPreferInetSocketAddress().getPort()); + + logger.info("Try to get effective connection by using {} at times {}", cur, + tryCount.get()); + TronNetService.getP2pService().connect(chosenNode.get(), future -> { + if (future.isCancelled()) { + // Connection attempt cancelled by user + } else if (!future.isSuccess()) { + // You might get a NullPointerException here because the future might not be completed yet. + logger.warn("Connect to chosen peer {} fail, cause:{}", + chosenNode.get().getPreferInetSocketAddress(), future.cause().getMessage()); + future.channel().close(); + + findEffectiveNode(); + } else { + // Connection established successfully + future.channel().closeFuture().addListener((ChannelFutureListener) closeFuture -> { + logger.info("Close chosen channel:{}", chosenNode.get().getPreferInetSocketAddress()); + if (isIsolateLand()) { + findEffectiveNode(); + } + }); + } + }); + } + + public void resetCount() { + tryCount.set(0); + } + + public int getCount() { + return tryCount.get(); + } + + private void disconnect() { + tronNetDelegate.getActivePeer().forEach(p -> { + if (p.getInetSocketAddress().equals(cur)) { + p.disconnect(ReasonCode.UNKNOWN); + } + }); + } +} diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java index 6c9e53c3a98..e269ea67734 100644 --- a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -11,6 +11,7 @@ import org.tron.core.net.message.handshake.HelloMessage; import org.tron.core.net.peer.PeerConnection; import org.tron.core.net.peer.PeerManager; +import org.tron.core.net.service.effective.EffectiveService; import org.tron.core.net.service.relay.RelayService; import org.tron.p2p.discover.Node; import org.tron.protos.Protocol.ReasonCode; @@ -22,6 +23,9 @@ public class HandshakeService { @Autowired private RelayService relayService; + @Autowired + private EffectiveService effectiveService; + @Autowired private ChainBaseManager chainBaseManager; @@ -98,6 +102,23 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { return; } + if (peer.getInetSocketAddress().equals(effectiveService.getCur())) { + if (effectiveService.isIsolateLand() + && msg.getSolidBlockId().getNum() <= chainBaseManager.getSolidBlockId().getNum()) { + logger.info("Peer's solid block {} is below than we, peer->{}, me->{}", + peer.getInetSocketAddress(), + msg.getSolidBlockId().getNum(), + chainBaseManager.getSolidBlockId().getNum()); + peer.disconnect(ReasonCode.UNKNOWN); + return; + } else { + logger.info("Success to find effective node {} at times {}", + peer.getInetSocketAddress(), effectiveService.getCount()); + effectiveService.setFound(true); + effectiveService.resetCount(); + } + } + peer.setHelloMessageReceive(msg); peer.getChannel().updateAvgLatency( From 05e4232dbf09bec0e35ec564f69f8e2c37b17a9e Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 17 Mar 2023 13:09:29 +0800 Subject: [PATCH 0654/1197] fix(net): add ReasonCode BELOW_THAN_ME --- .../service/effective/EffectiveService.java | 33 +++++++++---------- .../service/handshake/HandshakeService.java | 2 +- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveService.java b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveService.java index 78c33d7af21..43686fa505f 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveService.java @@ -1,6 +1,5 @@ package org.tron.core.net.service.effective; - import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.util.concurrent.ThreadFactoryBuilder; @@ -36,8 +35,8 @@ public class EffectiveService { .maximumSize(1000) .expireAfterWrite(10, TimeUnit.MINUTES).build(); @Getter - private InetSocketAddress cur = null; - private final AtomicInteger tryCount = new AtomicInteger(0); + private InetSocketAddress cur; + private final AtomicInteger count = new AtomicInteger(0); @Setter private boolean found = false; @@ -64,10 +63,9 @@ public void close() { } public boolean isIsolateLand() { - int count = (int) tronNetDelegate.getActivePeer().stream() + return (int) tronNetDelegate.getActivePeer().stream() .filter(PeerConnection::isNeedSyncFromUs) - .count(); - return count == tronNetDelegate.getActivePeer().size(); + .count() == tronNetDelegate.getActivePeer().size(); } private synchronized void findEffectiveNode() throws InterruptedException { @@ -84,8 +82,8 @@ private synchronized void findEffectiveNode() throws InterruptedException { return; } - //hashcode of PeerConnection = hashcode of InetSocketAddress - if (cur != null && tronNetDelegate.getActivePeer().contains(cur)) { + if (cur != null && tronNetDelegate.getActivePeer().stream() + .anyMatch(p -> p.getInetSocketAddress().equals(cur))) { // we encounter no effective connection again, so we disconnect with last used node disconnect(); return; @@ -104,32 +102,31 @@ private synchronized void findEffectiveNode() throws InterruptedException { .contains(node.getPreferInetSocketAddress())) .findFirst(); if (!chosenNode.isPresent()) { - logger.warn("Failed to find effective node, have tried {} times", tryCount.get()); + logger.warn("Failed to find effective node, have tried {} times", count.get()); resetCount(); return; } - tryCount.incrementAndGet(); + count.incrementAndGet(); nodesCache.put(chosenNode.get().getPreferInetSocketAddress(), true); cur = new InetSocketAddress(chosenNode.get().getPreferInetSocketAddress().getAddress(), chosenNode.get().getPreferInetSocketAddress().getPort()); - logger.info("Try to get effective connection by using {} at times {}", cur, - tryCount.get()); + logger.info("Try to get effective connection by using {} at times {}", cur, count.get()); TronNetService.getP2pService().connect(chosenNode.get(), future -> { if (future.isCancelled()) { // Connection attempt cancelled by user + logger.warn("Channel {} has been cancelled by user", cur); } else if (!future.isSuccess()) { // You might get a NullPointerException here because the future might not be completed yet. - logger.warn("Connect to chosen peer {} fail, cause:{}", - chosenNode.get().getPreferInetSocketAddress(), future.cause().getMessage()); + logger.warn("Connect to chosen peer {} fail, cause:{}", cur, future.cause().getMessage()); future.channel().close(); findEffectiveNode(); } else { // Connection established successfully future.channel().closeFuture().addListener((ChannelFutureListener) closeFuture -> { - logger.info("Close chosen channel:{}", chosenNode.get().getPreferInetSocketAddress()); + logger.info("Close chosen channel:{}", cur); if (isIsolateLand()) { findEffectiveNode(); } @@ -139,17 +136,17 @@ private synchronized void findEffectiveNode() throws InterruptedException { } public void resetCount() { - tryCount.set(0); + count.set(0); } public int getCount() { - return tryCount.get(); + return count.get(); } private void disconnect() { tronNetDelegate.getActivePeer().forEach(p -> { if (p.getInetSocketAddress().equals(cur)) { - p.disconnect(ReasonCode.UNKNOWN); + p.disconnect(ReasonCode.BELOW_THAN_ME); } }); } diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java index e269ea67734..a3bc241f9a9 100644 --- a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -109,7 +109,7 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { peer.getInetSocketAddress(), msg.getSolidBlockId().getNum(), chainBaseManager.getSolidBlockId().getNum()); - peer.disconnect(ReasonCode.UNKNOWN); + peer.disconnect(ReasonCode.BELOW_THAN_ME); return; } else { logger.info("Success to find effective node {} at times {}", From 4e3814af23762a7887e2498aa2efadd9b70aa8f8 Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 17 Mar 2023 15:36:10 +0800 Subject: [PATCH 0655/1197] feat(interface): add block number and block hash to the result of call constant contract --- framework/src/main/java/org/tron/core/Wallet.java | 6 +++++- protocol/src/main/protos/api/api.proto | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 6d9b12608c5..d834d4ae661 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -3011,7 +3011,8 @@ public Transaction callConstantContract(TransactionCapsule trxCap, headBlock = blockCapsuleList.get(0).getInstance(); } - TransactionContext context = new TransactionContext(new BlockCapsule(headBlock), trxCap, + BlockCapsule headBlockCapsule = new BlockCapsule(headBlock); + TransactionContext context = new TransactionContext(headBlockCapsule, trxCap, StoreFactory.getInstance(), true, false); VMActuator vmActuator = new VMActuator(true); @@ -3028,6 +3029,9 @@ public Transaction callConstantContract(TransactionCapsule trxCap, TransactionResultCapsule ret = new TransactionResultCapsule(); builder.setEnergyUsed(result.getEnergyUsed()); builder.setEnergyPenalty(result.getEnergyPenaltyTotal()); + builder.setBlockNumber(headBlockCapsule.getNum()); + builder.setBlockHash(ByteString.copyFrom(headBlockCapsule.getBlockId().getBytes())); + builder.setEnergyPenalty(result.getEnergyPenaltyTotal()); builder.addConstantResult(ByteString.copyFrom(result.getHReturn())); result.getLogInfoList().forEach(logInfo -> builder.addLogs(LogInfo.buildLog(logInfo))); diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 48cd64acc5b..13dbeee4389 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -1315,6 +1315,8 @@ message TransactionExtention { repeated TransactionInfo.Log logs = 6; repeated InternalTransaction internal_transactions = 7; int64 energy_penalty = 8; + int64 block_number = 9; + bytes block_hash = 10; } message EstimateEnergyMessage { From ba8331bddf230d17cb90d066d2400fdae4a815b6 Mon Sep 17 00:00:00 2001 From: guoquanwu Date: Fri, 17 Mar 2023 13:15:41 +0800 Subject: [PATCH 0656/1197] fix(test): fix port unavaliable when running unit test --- .../org/tron/common/utils/PublicMethod.java | 10 +++ .../LiteFnQueryGrpcInterceptorTest.java | 16 ++++- .../filter/RpcApiAccessInterceptorTest.java | 4 ++ .../tron/program/LiteFullNodeToolTest.java | 65 ++++++++++--------- 4 files changed, 61 insertions(+), 34 deletions(-) diff --git a/framework/src/test/java/org/tron/common/utils/PublicMethod.java b/framework/src/test/java/org/tron/common/utils/PublicMethod.java index b61ea6c8c4d..3c945b47530 100644 --- a/framework/src/test/java/org/tron/common/utils/PublicMethod.java +++ b/framework/src/test/java/org/tron/common/utils/PublicMethod.java @@ -2,6 +2,8 @@ import com.google.protobuf.ByteString; import java.math.BigInteger; +import java.util.Random; + import org.tron.api.GrpcAPI; import org.tron.api.WalletGrpc; import org.tron.common.crypto.ECKey; @@ -102,4 +104,12 @@ public static GrpcAPI.Return broadcastTransaction( } return response; } + + public static int chooseRandomPort(int min, int max) { + return new Random().nextInt(max - min + 1) + min; + } + + public static int chooseRandomPort() { + return new Random().nextInt(65530 - 1024) + 1024; + } } diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java index 5e5d7d807ae..77eb9a00cab 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java @@ -4,6 +4,8 @@ import io.grpc.ManagedChannelBuilder; import io.grpc.StatusRuntimeException; import java.io.File; +import java.util.concurrent.TimeUnit; + import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -20,6 +22,7 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.utils.FileUtil; +import org.tron.common.utils.PublicMethod; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; @@ -38,7 +41,6 @@ public class LiteFnQueryGrpcInterceptorTest { private WalletGrpc.WalletBlockingStub blockingStubFull = null; private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubpBFT = null; - private DatabaseGrpc.DatabaseBlockingStub databaseBlockingStub = null; private RpcApiService rpcApiService; private RpcApiServiceOnSolidity rpcApiServiceOnSolidity; private RpcApiServiceOnPBFT rpcApiServiceOnPBFT; @@ -56,6 +58,9 @@ public class LiteFnQueryGrpcInterceptorTest { @Before public void init() { Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + Args.getInstance().setRpcPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setRpcOnSolidityPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setRpcOnPBFTPort(PublicMethod.chooseRandomPort()); String fullnode = String.format("%s:%d", Args.getInstance().getNodeDiscoveryBindIp(), Args.getInstance().getRpcPort()); String pBFTNode = String.format("%s:%d", Args.getInstance().getNodeDiscoveryBindIp(), @@ -71,7 +76,6 @@ public void init() { blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelFull); blockingStubpBFT = WalletSolidityGrpc.newBlockingStub(channelpBFT); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelFull); - databaseBlockingStub = DatabaseGrpc.newBlockingStub(channelFull); rpcApiService = context.getBean(RpcApiService.class); rpcApiServiceOnSolidity = context.getBean(RpcApiServiceOnSolidity.class); rpcApiServiceOnPBFT = context.getBean(RpcApiServiceOnPBFT.class); @@ -89,7 +93,13 @@ public void init() { * destroy the context. */ @After - public void destroy() { + public void destroy() throws InterruptedException { + if (channelFull != null) { + channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + if (channelpBFT != null) { + channelpBFT.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } Args.clearParam(); appTest.shutdownServices(); appTest.shutdown(); diff --git a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java index c3ef7265f65..5560d9b9397 100644 --- a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java @@ -22,6 +22,7 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.utils.FileUtil; +import org.tron.common.utils.PublicMethod; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; @@ -51,6 +52,9 @@ public class RpcApiAccessInterceptorTest { @BeforeClass public static void init() { Args.setParam(new String[] {"-d", dbPath}, Constant.TEST_CONF); + Args.getInstance().setRpcPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setRpcOnSolidityPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setRpcOnPBFTPort(PublicMethod.chooseRandomPort()); String fullNode = String.format("%s:%d", Args.getInstance().getNodeDiscoveryBindIp(), Args.getInstance().getRpcPort()); String solidityNode = String.format("%s:%d", Args.getInstance().getNodeDiscoveryBindIp(), diff --git a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java index 4549b2cde4d..2c91c2f8b9a 100644 --- a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java +++ b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java @@ -1,11 +1,11 @@ package org.tron.program; -import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.io.File; -import java.math.BigInteger; import java.nio.file.Paths; +import java.util.concurrent.TimeUnit; + import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -13,7 +13,6 @@ import org.junit.rules.ExpectedException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.tron.api.GrpcAPI; import org.tron.api.WalletGrpc; import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; @@ -23,15 +22,11 @@ import org.tron.common.utils.FileUtil; import org.tron.common.utils.PublicMethod; import org.tron.common.utils.Utils; -import org.tron.core.Wallet; 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.protos.Protocol; -import org.tron.protos.contract.BalanceContract; import org.tron.tool.litefullnode.LiteFullNodeTool; -import stest.tron.wallet.common.client.utils.TransactionUtils; public class LiteFullNodeToolTest { @@ -39,6 +34,7 @@ public class LiteFullNodeToolTest { private TronApplicationContext context; private WalletGrpc.WalletBlockingStub blockingStubFull = null; + private ManagedChannel channelFull; private Application appTest; private String databaseDir; @@ -47,7 +43,7 @@ public class LiteFullNodeToolTest { public ExpectedException thrown = ExpectedException.none(); - private static final String DB_PATH = "output_lite_fn"; + private static String dbPath = "output_lite_fn"; /** * init logic. @@ -63,7 +59,7 @@ public void startApp() { String fullnode = String.format("%s:%d", "127.0.0.1", Args.getInstance().getRpcPort()); - ManagedChannel channelFull = ManagedChannelBuilder.forTarget(fullnode) + channelFull = ManagedChannelBuilder.forTarget(fullnode) .usePlaintext(true) .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); @@ -86,18 +82,21 @@ public static void destroy(String dbPath) { /** * shutdown the fullnode. */ - public void shutdown() { + public void shutdown() throws InterruptedException { + if (channelFull != null) { + channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } appTest.shutdownServices(); appTest.shutdown(); context.destroy(); } - @Before public void init() { - destroy(DB_PATH); // delete if prev failed - Args.setParam(new String[]{"-d", DB_PATH, "-w"}, "config-localtest.conf"); + 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(); @@ -105,40 +104,44 @@ public void init() { @After public void clear() { - destroy(DB_PATH); + destroy(dbPath); Args.clearParam(); + dbPath = "output_lite_fn"; } @Test - public void testToolsWithLevelDB() { + public void testToolsWithLevelDB() throws InterruptedException { logger.info("testToolsWithLevelDB start"); testTools("LEVELDB", 1); } @Test - public void testToolsWithLevelDBV2() { + public void testToolsWithLevelDBV2() throws InterruptedException { logger.info("testToolsWithLevelDB start"); testTools("LEVELDB", 2); } @Test - public void testToolsWithRocksDB() { + public void testToolsWithRocksDB() throws InterruptedException { logger.info("testToolsWithRocksDB start"); testTools("ROCKSDB", 1); } - private void testTools(String dbType, int checkpointVersion) { + 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", - DB_PATH + File.separator + databaseDir, "--dataset-path", - DB_PATH}; + dbPath + File.separator + databaseDir, "--dataset-path", + dbPath}; final String[] argsForHistory = new String[]{"-o", "split", "-t", "history", "--fn-data-path", - DB_PATH + File.separator + databaseDir, "--dataset-path", - DB_PATH}; + dbPath + File.separator + databaseDir, "--dataset-path", + dbPath}; final String[] argsForMerge = - new String[]{"-o", "merge", "--fn-data-path", DB_PATH + File.separator + databaseDir, - "--dataset-path", DB_PATH + File.separator + "history"}; + 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); @@ -149,7 +152,7 @@ private void testTools(String dbType, int checkpointVersion) { // stop the node shutdown(); // delete tran-cache - FileUtil.deleteDir(Paths.get(DB_PATH, databaseDir, "trans-cache").toFile()); + FileUtil.deleteDir(Paths.get(dbPath, databaseDir, "trans-cache").toFile()); // generate snapshot LiteFullNodeTool.main(argsForSnapshot); // start fullnode @@ -161,18 +164,18 @@ private void testTools(String dbType, int checkpointVersion) { // generate history LiteFullNodeTool.main(argsForHistory); // backup original database to database_bak - File database = new File(Paths.get(DB_PATH, databaseDir).toString()); - if (!database.renameTo(new File(Paths.get(DB_PATH, databaseDir + "_bak").toString()))) { + 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(DB_PATH, databaseDir).toString())); + Paths.get(dbPath, databaseDir).toString())); } // change snapshot to the new database - File snapshot = new File(Paths.get(DB_PATH, "snapshot").toString()); - if (!snapshot.renameTo(new File(Paths.get(DB_PATH, databaseDir).toString()))) { + 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(DB_PATH, databaseDir).toString())); + Paths.get(dbPath, databaseDir).toString())); } // start and validate the snapshot startApp(); From 998d7fb03cadef03ed0336d382434d9746ca7b0e Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 17 Mar 2023 18:24:03 +0800 Subject: [PATCH 0657/1197] fix(interface): some conditions not suitable --- .../services/http/TriggerConstantContractServlet.java | 11 +++++------ .../services/http/TriggerSmartContractServlet.java | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java b/framework/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java index 1baed135039..fa3336df5eb 100644 --- a/framework/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java @@ -44,14 +44,13 @@ protected void validateParameter(String contract) { if (StringUtil.isNullOrEmpty(jsonObject.getString(OWNER_ADDRESS))) { throw new InvalidParameterException(OWNER_ADDRESS + " isn't set."); } - if (StringUtil.isNullOrEmpty(jsonObject.getString(CONTRACT_ADDRESS))) { - if (StringUtil.isNullOrEmpty(jsonObject.getString(CALL_DATA))) { - throw new InvalidParameterException("At least one of " - + CONTRACT_ADDRESS + " and " + CALL_DATA + " must be set."); - } + if (StringUtil.isNullOrEmpty(jsonObject.getString(CONTRACT_ADDRESS)) + && StringUtil.isNullOrEmpty(jsonObject.getString(CALL_DATA))) { + throw new InvalidParameterException("At least one of " + + CONTRACT_ADDRESS + " and " + CALL_DATA + " must be set."); } if (!StringUtil.isNullOrEmpty(jsonObject.getString(FUNCTION_SELECTOR)) - && !StringUtil.isNullOrEmpty(jsonObject.getString(CALL_DATA))) { + ^ StringUtil.isNullOrEmpty(jsonObject.getString(CALL_DATA))) { throw new InvalidParameterException("Only one of " + FUNCTION_SELECTOR + " and " + CALL_DATA + " can be set."); } diff --git a/framework/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java b/framework/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java index 23481fff8e8..5ce27e7cd0b 100644 --- a/framework/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java @@ -48,7 +48,7 @@ protected void validateParameter(String contract) { throw new InvalidParameterException("contract_address isn't set."); } if (!StringUtil.isNullOrEmpty(jsonObject.getString(FUNCTION_SELECTOR)) - && !StringUtil.isNullOrEmpty(jsonObject.getString(CALL_DATA))) { + ^ StringUtil.isNullOrEmpty(jsonObject.getString(CALL_DATA))) { throw new InvalidParameterException("Only one of " + FUNCTION_SELECTOR + " and " + CALL_DATA + " can be set."); } From 172010e2f117b772a55f32eb4d4f6bd712dd1d28 Mon Sep 17 00:00:00 2001 From: "morgan.peng" Date: Fri, 17 Mar 2023 19:42:28 +0800 Subject: [PATCH 0658/1197] feat(*): add wallet unit test 1. add wallet unit test --- .../test/java/org/tron/core/WalletTest.java | 12 ++++ .../org/tron/core/services/WalletApiTest.java | 60 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/services/WalletApiTest.java diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 41afd1b0c8e..36a34edc295 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -1066,5 +1066,17 @@ public void testEstimateEnergyOutOfTime() { Assert.assertTrue(true); } } + + @Test + public void testListNodes() { + try { + GrpcAPI.NodeList nodeList = wallet.listNodes(); + } catch (Exception e) { + Assert.assertTrue(e instanceof NullPointerException); + } + Args.getInstance().setP2pDisable(true); + GrpcAPI.NodeList nodeList = wallet.listNodes(); + Assert.assertTrue(nodeList.getNodesList().size() == 0); + } } diff --git a/framework/src/test/java/org/tron/core/services/WalletApiTest.java b/framework/src/test/java/org/tron/core/services/WalletApiTest.java new file mode 100644 index 00000000000..2138421daf8 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/WalletApiTest.java @@ -0,0 +1,60 @@ +package org.tron.core.services; + +import io.grpc.ManagedChannelBuilder; +import java.io.File; +import lombok.extern.slf4j.Slf4j; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.api.GrpcAPI.EmptyMessage; +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.utils.FileUtil; +import org.tron.core.Constant; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import stest.tron.wallet.common.client.Configuration; + +@Slf4j +public class WalletApiTest { + + private static TronApplicationContext context; + private static String dbPath = "output_wallet_api_test"; + private String fullnode = Configuration.getByPath("testng.conf") + .getStringList("fullnode.ip.list").get(0); + private RpcApiService rpcApiService; + private Application appT; + + @Before + public void init() { + Args.setParam(new String[]{ "-d", dbPath, "--p2p-disable", "true"}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + appT = ApplicationFactory.create(context); + rpcApiService = context.getBean(RpcApiService.class); + appT.addService(rpcApiService); + appT.initServices(Args.getInstance()); + appT.startServices(); + appT.startup(); + } + + @Test + public void listNodesTest() { + WalletGrpc.WalletBlockingStub walletStub = WalletGrpc + .newBlockingStub(ManagedChannelBuilder.forTarget(fullnode) + .usePlaintext(true) + .build()); + Assert.assertTrue(walletStub.listNodes(EmptyMessage.getDefaultInstance()) + .getNodesList().size() == 0); + } + + @After + public void destroy() { + Args.clearParam(); + context.destroy(); + FileUtil.deleteDir(new File(dbPath)); + } + +} From 9c98abfd04f3942ede88aa654cc375fd4edaf51b Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 20 Mar 2023 15:30:26 +0800 Subject: [PATCH 0659/1197] fix(net): merge 4.7.2 and update libp2p --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 329676bf560..6ce3c0bef41 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.17' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.19' compile project(":protocol") } From df2840e29f21a854061ff8622414b6e57a9abaf4 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 20 Mar 2023 17:30:56 +0800 Subject: [PATCH 0660/1197] feature(net): add config node.enableEffectiveCheck; add one ReasonCode --- .../common/parameter/CommonParameter.java | 6 +-- .../src/main/java/org/tron/core/Constant.java | 1 + .../java/org/tron/core/config/args/Args.java | 5 ++ .../org/tron/core/net/TronNetService.java | 8 ++-- ...ervice.java => EffectiveCheckService.java} | 47 +++++++++++-------- .../service/handshake/HandshakeService.java | 15 +++--- protocol/src/main/protos/core/Tron.proto | 1 + 7 files changed, 49 insertions(+), 34 deletions(-) rename framework/src/main/java/org/tron/core/net/service/effective/{EffectiveService.java => EffectiveCheckService.java} (81%) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index ad956895bc1..0ba57c2050c 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -1,7 +1,5 @@ package org.tron.common.parameter; -import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; - import com.beust.jcommander.Parameter; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -9,7 +7,6 @@ import java.util.List; import java.util.Set; -import com.google.common.annotations.VisibleForTesting; import lombok.Getter; import lombok.Setter; import org.quartz.CronExpression; @@ -143,6 +140,9 @@ public class CommonParameter { public boolean nodeDiscoveryPersist; @Getter @Setter + public boolean nodeEffectiveCheckEnable; + @Getter + @Setter public int nodeConnectionTimeout; @Getter @Setter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index ec921f1a858..efff664f38e 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -83,6 +83,7 @@ public class Constant { public static final String BLOCK_NEED_SYNC_CHECK = "block.needSyncCheck"; public static final String NODE_DISCOVERY_ENABLE = "node.discovery.enable"; public static final String NODE_DISCOVERY_PERSIST = "node.discovery.persist"; + public static final String NODE_ENABLE_EFFECTIVE_CHECK = "node.enableEffectiveCheck"; public static final String NODE_CONNECTION_TIMEOUT = "node.connection.timeout"; public static final String NODE_FETCH_BLOCK_TIMEOUT = "node.fetchBlock.timeout"; public static final String NODE_CHANNEL_READ_TIMEOUT = "node.channel.read.timeout"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 70a3174748e..29d33fec436 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -124,6 +124,7 @@ public static void clearParam() { PARAMETER.needSyncCheck = false; PARAMETER.nodeDiscoveryEnable = false; PARAMETER.nodeDiscoveryPersist = false; + PARAMETER.nodeEffectiveCheckEnable = true; PARAMETER.nodeConnectionTimeout = 2000; PARAMETER.activeNodes = new ArrayList<>(); PARAMETER.passiveNodes = new ArrayList<>(); @@ -554,6 +555,10 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.NODE_DISCOVERY_PERSIST) && config.getBoolean(Constant.NODE_DISCOVERY_PERSIST); + PARAMETER.nodeEffectiveCheckEnable = + config.hasPath(Constant.NODE_ENABLE_EFFECTIVE_CHECK) + && config.getBoolean(Constant.NODE_ENABLE_EFFECTIVE_CHECK); + PARAMETER.nodeConnectionTimeout = config.hasPath(Constant.NODE_CONNECTION_TIMEOUT) ? config.getInt(Constant.NODE_CONNECTION_TIMEOUT) * 1000 diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index d92b794296d..ebd0b1b4114 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -21,7 +21,7 @@ import org.tron.core.net.peer.PeerManager; import org.tron.core.net.peer.PeerStatusCheck; import org.tron.core.net.service.adv.AdvService; -import org.tron.core.net.service.effective.EffectiveService; +import org.tron.core.net.service.effective.EffectiveCheckService; import org.tron.core.net.service.fetchblock.FetchBlockService; import org.tron.core.net.service.nodepersist.NodePersistService; import org.tron.core.net.service.relay.RelayService; @@ -71,7 +71,7 @@ public class TronNetService { private RelayService relayService; @Autowired - private EffectiveService effectiveService; + private EffectiveCheckService effectiveCheckService; private volatile boolean init; @@ -94,7 +94,7 @@ public void start() { tronStatsManager.init(); PeerManager.init(); relayService.init(); - effectiveService.init(); + effectiveCheckService.init(); logger.info("Net service start successfully"); } catch (Exception e) { logger.error("Net service start failed", e); @@ -115,7 +115,7 @@ public void close() { fetchBlockService.close(); p2pService.close(); relayService.close(); - effectiveService.close(); + effectiveCheckService.close(); logger.info("Net service closed successfully"); } diff --git a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveService.java b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java similarity index 81% rename from framework/src/main/java/org/tron/core/net/service/effective/EffectiveService.java rename to framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java index 43686fa505f..c2d399bf1e5 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java @@ -16,6 +16,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.common.parameter.CommonParameter; import org.tron.core.net.TronNetDelegate; import org.tron.core.net.TronNetService; import org.tron.core.net.peer.PeerConnection; @@ -25,8 +26,11 @@ @Slf4j(topic = "net") @Component -public class EffectiveService { +public class EffectiveCheckService { + @Getter + private final boolean isEffectiveCheck = CommonParameter.getInstance() + .isNodeEffectiveCheckEnable(); @Autowired private TronNetDelegate tronNetDelegate; @@ -39,43 +43,46 @@ public class EffectiveService { private final AtomicInteger count = new AtomicInteger(0); @Setter private boolean found = false; + private ScheduledExecutorService executor = null; - private final ScheduledExecutorService executor = Executors - .newSingleThreadScheduledExecutor( + public void init() { + if (isEffectiveCheck) { + executor = Executors.newSingleThreadScheduledExecutor( new ThreadFactoryBuilder().setNameFormat("effective-thread-%d").build()); + executor.scheduleWithFixedDelay(() -> { + try { + findEffectiveNode(); + } catch (Exception e) { + logger.error("Check effective connection processing failed", e); + } + }, 1 * 60, 5, TimeUnit.SECONDS); + } + } - public void init() { - executor.scheduleWithFixedDelay(() -> { + public void close() { + if (executor != null) { try { - findEffectiveNode(); + executor.shutdown(); } catch (Exception e) { - logger.error("Check effective connection processing failed", e); + logger.error("Exception in shutdown effective service worker, {}", e.getMessage()); } - }, 1 * 60, 5, TimeUnit.SECONDS); - } - - public void close() { - try { - executor.shutdownNow(); - } catch (Exception e) { - logger.error("Exception in shutdown effective service worker, {}", e.getMessage()); } } - public boolean isIsolateLand() { + public boolean haveEffectiveConnection() { return (int) tronNetDelegate.getActivePeer().stream() .filter(PeerConnection::isNeedSyncFromUs) - .count() == tronNetDelegate.getActivePeer().size(); + .count() != tronNetDelegate.getActivePeer().size(); } private synchronized void findEffectiveNode() throws InterruptedException { - if (!isIsolateLand()) { + if (haveEffectiveConnection()) { resetCount(); return; } if (found) { Thread.sleep(10_000);//wait found node to sync - if (isIsolateLand()) { + if (!haveEffectiveConnection()) { found = false; disconnect(); } @@ -127,7 +134,7 @@ private synchronized void findEffectiveNode() throws InterruptedException { // Connection established successfully future.channel().closeFuture().addListener((ChannelFutureListener) closeFuture -> { logger.info("Close chosen channel:{}", cur); - if (isIsolateLand()) { + if (!haveEffectiveConnection()) { findEffectiveNode(); } }); diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java index a3bc241f9a9..64eefacbb72 100644 --- a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -11,7 +11,7 @@ import org.tron.core.net.message.handshake.HelloMessage; import org.tron.core.net.peer.PeerConnection; import org.tron.core.net.peer.PeerManager; -import org.tron.core.net.service.effective.EffectiveService; +import org.tron.core.net.service.effective.EffectiveCheckService; import org.tron.core.net.service.relay.RelayService; import org.tron.p2p.discover.Node; import org.tron.protos.Protocol.ReasonCode; @@ -24,7 +24,7 @@ public class HandshakeService { private RelayService relayService; @Autowired - private EffectiveService effectiveService; + private EffectiveCheckService effectiveCheckService; @Autowired private ChainBaseManager chainBaseManager; @@ -102,8 +102,9 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { return; } - if (peer.getInetSocketAddress().equals(effectiveService.getCur())) { - if (effectiveService.isIsolateLand() + if (effectiveCheckService.isEffectiveCheck() && + peer.getInetSocketAddress().equals(effectiveCheckService.getCur())) { + if (!effectiveCheckService.haveEffectiveConnection() && msg.getSolidBlockId().getNum() <= chainBaseManager.getSolidBlockId().getNum()) { logger.info("Peer's solid block {} is below than we, peer->{}, me->{}", peer.getInetSocketAddress(), @@ -113,9 +114,9 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { return; } else { logger.info("Success to find effective node {} at times {}", - peer.getInetSocketAddress(), effectiveService.getCount()); - effectiveService.setFound(true); - effectiveService.resetCount(); + peer.getInetSocketAddress(), effectiveCheckService.getCount()); + effectiveCheckService.setFound(true); + effectiveCheckService.resetCount(); } } diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index e6aac408f95..437f5bf85a2 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -600,6 +600,7 @@ enum ReasonCode { CONNECT_FAIL = 0x21; TOO_MANY_PEERS_WITH_SAME_IP = 0x22; LIGHT_NODE_SYNC_FAIL = 0x23; + BELOW_THAN_ME = 0X24; UNKNOWN = 0xFF; } From 429f2a0fc0febc384cdc306e1776cf43ee731d9d Mon Sep 17 00:00:00 2001 From: forfreeday Date: Mon, 20 Mar 2023 18:24:55 +0800 Subject: [PATCH 0661/1197] feature(shell): move shell to script directory --- DownloadLinks.sh | 21 --------------------- checkStyle.sh => script/checkStyle.sh | 0 codecov.sh => script/codecov.sh | 0 querySonar.sh => script/querySonar.sh | 0 sonar.sh => script/sonar.sh | 0 5 files changed, 21 deletions(-) delete mode 100644 DownloadLinks.sh rename checkStyle.sh => script/checkStyle.sh (100%) rename codecov.sh => script/codecov.sh (100%) rename querySonar.sh => script/querySonar.sh (100%) rename sonar.sh => script/sonar.sh (100%) diff --git a/DownloadLinks.sh b/DownloadLinks.sh deleted file mode 100644 index babc5a266f6..00000000000 --- a/DownloadLinks.sh +++ /dev/null @@ -1,21 +0,0 @@ -PassFlag=`curl -s http://47.95.206.44:50080/Daily_Build_Task_Report | grep "Failed: 0" | wc -c` - -if [ $PassFlag -eq 0 ]; then - echo "Daily Build Stest Fail" - echo "To view Daily Replay and Stress Test logs please visit website below on browsers" - echo "--- http://47.95.206.44:50080/latestReplayLog" - echo "--- http://47.95.206.44:50080/latestStressLog" - -else - echo "Daily Build Stest Pass" - echo "Build on `date +"%Y-%m-%d"` 3:00:00 (CST), UTC +8" - echo "Please visit following website to download java-tron.jar on browsers" - echo "--- http://47.95.206.44:50080/Daily_Build/jFava-tron.jar" - echo "To view Daily Replay and Stress Test logs please visit website below on browsers" - echo "--- http://47.95.206.44:50080/latestReplayLog" - echo "--- http://47.95.206.44:50080/latestStressLog" - echo "The following compressed package is provided for user to set up Fullnode. Please use Linux OS to Download" - echo "--- curl -# -O http://47.95.206.44:50080/Daily_Build/java-tron.tar.gz" - echo "To unzip file use the command below" - echo "--- tar -xzvf java-tron.tar.gz" -fi \ No newline at end of file diff --git a/checkStyle.sh b/script/checkStyle.sh similarity index 100% rename from checkStyle.sh rename to script/checkStyle.sh diff --git a/codecov.sh b/script/codecov.sh similarity index 100% rename from codecov.sh rename to script/codecov.sh diff --git a/querySonar.sh b/script/querySonar.sh similarity index 100% rename from querySonar.sh rename to script/querySonar.sh diff --git a/sonar.sh b/script/sonar.sh similarity index 100% rename from sonar.sh rename to script/sonar.sh From 5959a1bf76786aed364c5cf3828507c3cfdcd307 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 21 Mar 2023 16:40:41 +0800 Subject: [PATCH 0662/1197] feat(config):add support for dynamically loading configuration --- .../common/parameter/CommonParameter.java | 5 + .../src/main/java/org/tron/core/Constant.java | 2 + .../common/application/ApplicationImpl.java | 6 + .../java/org/tron/core/config/args/Args.java | 8 +- .../tron/core/config/args/DynamicArgs.java | 163 ++++++++++++++++++ .../org/tron/core/net/TronNetService.java | 4 +- 6 files changed, 184 insertions(+), 4 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/config/args/DynamicArgs.java diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index ab04ca3e7a4..ef1bff15d16 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -30,6 +30,7 @@ public class CommonParameter { public static CommonParameter PARAMETER = new CommonParameter(); @Setter public static boolean ENERGY_LIMIT_HARD_FORK = false; + @Getter @Parameter(names = {"-c", "--config"}, description = "Config file (default:config.conf)") public String shellConfFileName = ""; @Getter @@ -608,6 +609,10 @@ public class CommonParameter { @Setter public long dynamicEnergyMaxFactor = 0L; + @Getter + @Setter + public boolean dynamicConfigEnable; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 408782752f2..59d69bfecfd 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -343,4 +343,6 @@ public class Constant { public static final String NODE_SHUTDOWN_BLOCK_COUNT = "node.shutdown.BlockCount"; public static final String BLOCK_CACHE_TIMEOUT = "node.blockCacheTimeout"; + + public static final String DYNAMIC_CONFIG_ENABLE = "dynamicConfigEnable"; } diff --git a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java index 235ece75835..174dc92b25d 100644 --- a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java +++ b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java @@ -7,6 +7,7 @@ import org.tron.common.parameter.CommonParameter; import org.tron.core.ChainBaseManager; import org.tron.core.config.args.Args; +import org.tron.core.config.args.DynamicArgs; import org.tron.core.consensus.ConsensusService; import org.tron.core.db.Manager; import org.tron.core.metrics.MetricsUtil; @@ -32,6 +33,9 @@ public class ApplicationImpl implements Application { @Autowired private ConsensusService consensusService; + @Autowired + private DynamicArgs dynamicArgs; + @Override public void setOptions(Args args) { // not used @@ -62,6 +66,7 @@ public void startup() { } consensusService.start(); MetricsUtil.init(); + dynamicArgs.init(); } @Override @@ -80,6 +85,7 @@ public void shutdown() { dbManager.stopRePushTriggerThread(); EventPluginLoader.getInstance().stopPlugin(); dbManager.stopFilterProcessThread(); + dynamicArgs.close(); logger.info("******** end to shutdown ********"); FullNode.shutDownSign = true; } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 8e6a7526362..b9cfde485da 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -221,6 +221,7 @@ public static void clearParam() { PARAMETER.allowNewRewardAlgorithm = 0; PARAMETER.allowNewReward = 0; PARAMETER.memoFee = 0; + PARAMETER.dynamicConfigEnable = false; } /** @@ -1122,6 +1123,9 @@ public static void setParam(final String[] args, final String confFileName) { Math.max(PARAMETER.dynamicEnergyMaxFactor, 0); } + PARAMETER.dynamicConfigEnable = config.hasPath(Constant.DYNAMIC_CONFIG_ENABLE) + && config.getBoolean(Constant.DYNAMIC_CONFIG_ENABLE); + logConfig(); } @@ -1174,7 +1178,7 @@ private static RateLimiterInitialization getRateLimiterFromConfig( return initialization; } - private static List getInetSocketAddress( + public static List getInetSocketAddress( final com.typesafe.config.Config config, String path) { List ret = new ArrayList<>(); if (!config.hasPath(path)) { @@ -1195,7 +1199,7 @@ private static List getInetSocketAddress( return ret; } - private static List getInetAddress( + public static List getInetAddress( final com.typesafe.config.Config config, String path) { List ret = new ArrayList<>(); if (!config.hasPath(path)) { diff --git a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java new file mode 100644 index 00000000000..e441bc527a2 --- /dev/null +++ b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java @@ -0,0 +1,163 @@ +package org.tron.core.config.args; + +import static org.apache.commons.lang3.StringUtils.isNoneBlank; + +import com.typesafe.config.Config; +import java.io.File; +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.nio.file.StandardWatchEventKinds; +import java.nio.file.WatchEvent; +import java.nio.file.WatchKey; +import java.nio.file.WatchService; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.tron.common.parameter.CommonParameter; +import org.tron.core.Constant; +import org.tron.core.config.Configuration; +import org.tron.core.net.TronNetService; + + +@Slf4j(topic = "app") +@Component +public class DynamicArgs { + private final CommonParameter parameter = Args.getInstance(); + + private volatile boolean shutdown = false; + + public void init() { + if (parameter.isDynamicConfigEnable()) { + new Thread(this::start, "DynamicArgs").start(); + } + } + + public void start() { + WatchService watchService; + Path path; + String confFileName; + try { + logger.info("Start the dynamic loading configuration service"); + String confFile; + if (isNoneBlank(parameter.getShellConfFileName())) { + confFile = parameter.getShellConfFileName(); + } else { + confFile = Constant.TESTNET_CONF; + // + //logger.warn("Configuration path is required!"); + //return; + } + + File confDir = new File(confFile); + confFileName = confDir.getName(); + if (confFile.contains(File.separator)) { + path = FileSystems.getDefault().getPath(confDir.getPath()).getParent(); + } else { + File directory = new File(""); + path = FileSystems.getDefault().getPath(directory.getAbsolutePath()); + } + + logger.info("confDirString = {}", confDir); + watchService = FileSystems.getDefault().newWatchService(); + path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY); + logger.info("watch path : {}", path.toString()); + } catch (Exception e) { + logger.error("Exception caught when register the watch key", e.getCause()); + return; + } + + while (!shutdown) { + try { + WatchKey wk = watchService.take(); + long changeCount = 0; + for (WatchEvent event : wk.pollEvents()) { + final Path changed = (Path)event.context(); + if (changed.endsWith(confFileName)) { + reload(); + logger.info("Config was modify and we reload it"); + } + changeCount++; + } + logger.info("change count : {}", changeCount); + + boolean valid = wk.reset(); + if (!valid) { + path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY); + } + } catch (InterruptedException e) { + logger.warn(""); + break; + } catch (IOException e) { + break; + } + } + } + + public void reload() { + logger.info("reloading ... "); + Config config = Configuration.getByFileName(parameter.getShellConfFileName(), + Constant.TESTNET_CONF); + + updateActiveNodes(config); + + updateTrustNodes(config); + } + + private void updateActiveNodes(Config config) { + if (parameter.isWitness() || parameter.isFastForward()) { + return; + } + + List lastActiveNodes = parameter.getActiveNodes(); + List newActiveNodes = + Args.getInetSocketAddress(config, Constant.NODE_ACTIVE); + parameter.setActiveNodes(newActiveNodes); + parameter.getActiveNodes().forEach(n -> { + logger.info("active node : {}", n.toString()); + if (!lastActiveNodes.contains(n)) { + TronNetService.getP2pConfig().getActiveNodes().add(n); + if (!TronNetService.getP2pConfig().getTrustNodes().contains(n.getAddress())) { + TronNetService.getP2pConfig().getTrustNodes().add(n.getAddress()); + } + } + }); + + lastActiveNodes.forEach(ln -> { + if (!parameter.getActiveNodes().contains(ln)) { + TronNetService.getP2pConfig().getActiveNodes().remove(ln); + TronNetService.getP2pConfig().getTrustNodes().remove(ln.getAddress()); + } + }); + } + + private void updateTrustNodes(Config config) { + if (parameter.isWitness() || parameter.isFastForward()) { + return; + } + + List lastPassiveNodes = parameter.getPassiveNodes(); + List newPassiveNodes = Args.getInetAddress(config, Constant.NODE_PASSIVE); + parameter.setPassiveNodes(newPassiveNodes); + parameter.getPassiveNodes().forEach(n -> { + logger.info("passive node : {}", n.toString()); + if (!lastPassiveNodes.contains(n) + || !TronNetService.getP2pConfig().getTrustNodes().contains(n)) { + TronNetService.getP2pConfig().getTrustNodes().add(n); + } + }); + + lastPassiveNodes.forEach(ln -> { + if (!parameter.getPassiveNodes().contains(ln)) { + TronNetService.getP2pConfig().getTrustNodes().remove(ln); + } + }); + } + + public void close() { + logger.info("Closing watchService ..."); + shutdown = true; + } +} \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index dcee7ecc7b2..5e32d834d67 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -136,8 +136,8 @@ private P2pConfig getConfig() { P2pConfig config = new P2pConfig(); config.setSeedNodes(seeds); - config.setActiveNodes(parameter.getActiveNodes()); - config.setTrustNodes(parameter.getPassiveNodes()); + config.getActiveNodes().addAll(parameter.getActiveNodes()); + config.getTrustNodes().addAll(parameter.getPassiveNodes()); config.getActiveNodes().forEach(n -> config.getTrustNodes().add(n.getAddress())); parameter.getFastForwardNodes().forEach(f -> config.getTrustNodes().add(f.getAddress())); int maxConnections = parameter.getMaxConnections(); From db678c1279a82c854f924c27e0d4f2873c98d052 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 21 Mar 2023 17:01:04 +0800 Subject: [PATCH 0663/1197] fix(net): simplify EffectiveCheckService; set nodeEffectiveCheckEnable deafult to true --- .../java/org/tron/core/config/args/Args.java | 4 +- .../effective/EffectiveCheckService.java | 51 +++++++------------ .../service/handshake/HandshakeService.java | 8 ++- .../org/tron/common/config/args/ArgsTest.java | 1 + 4 files changed, 23 insertions(+), 41 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 29d33fec436..4d3c76deb97 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -556,8 +556,8 @@ public static void setParam(final String[] args, final String confFileName) { && config.getBoolean(Constant.NODE_DISCOVERY_PERSIST); PARAMETER.nodeEffectiveCheckEnable = - config.hasPath(Constant.NODE_ENABLE_EFFECTIVE_CHECK) - && config.getBoolean(Constant.NODE_ENABLE_EFFECTIVE_CHECK); + !config.hasPath(Constant.NODE_ENABLE_EFFECTIVE_CHECK) + || config.getBoolean(Constant.NODE_ENABLE_EFFECTIVE_CHECK); PARAMETER.nodeConnectionTimeout = config.hasPath(Constant.NODE_CONNECTION_TIMEOUT) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java index c2d399bf1e5..d00340a3ada 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java @@ -12,16 +12,14 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import lombok.Getter; -import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.common.parameter.CommonParameter; +import org.tron.core.config.args.Args; import org.tron.core.net.TronNetDelegate; import org.tron.core.net.TronNetService; import org.tron.core.net.peer.PeerConnection; import org.tron.p2p.discover.Node; -import org.tron.p2p.utils.NetUtil; import org.tron.protos.Protocol.ReasonCode; @Slf4j(topic = "net") @@ -29,8 +27,7 @@ public class EffectiveCheckService { @Getter - private final boolean isEffectiveCheck = CommonParameter.getInstance() - .isNodeEffectiveCheckEnable(); + private final boolean isEffectiveCheck = Args.getInstance().isNodeEffectiveCheckEnable(); @Autowired private TronNetDelegate tronNetDelegate; @@ -41,8 +38,6 @@ public class EffectiveCheckService { @Getter private InetSocketAddress cur; private final AtomicInteger count = new AtomicInteger(0); - @Setter - private boolean found = false; private ScheduledExecutorService executor = null; public void init() { @@ -55,7 +50,9 @@ public void init() { } catch (Exception e) { logger.error("Check effective connection processing failed", e); } - }, 1 * 60, 5, TimeUnit.SECONDS); + }, 60, 5, TimeUnit.SECONDS); + } else { + logger.warn("EffectiveCheckService is disabled"); } } @@ -69,23 +66,19 @@ public void close() { } } - public boolean haveEffectiveConnection() { + public boolean isIsolateLand() { return (int) tronNetDelegate.getActivePeer().stream() .filter(PeerConnection::isNeedSyncFromUs) - .count() != tronNetDelegate.getActivePeer().size(); + .count() == tronNetDelegate.getActivePeer().size(); } - private synchronized void findEffectiveNode() throws InterruptedException { - if (haveEffectiveConnection()) { - resetCount(); - return; - } - if (found) { - Thread.sleep(10_000);//wait found node to sync - if (!haveEffectiveConnection()) { - found = false; - disconnect(); + //try to find node which we can sync from + private synchronized void findEffectiveNode() { + if (!isIsolateLand()) { + if (count.get() > 0) { + logger.info("Success to verify effective node {}", cur); } + resetCount(); return; } @@ -97,11 +90,6 @@ private synchronized void findEffectiveNode() throws InterruptedException { } List tableNodes = TronNetService.getP2pService().getAllNodes(); - for (Node node : tableNodes) { - if (node.getId() == null) { - node.setId(NetUtil.getNodeId()); - } - } Optional chosenNode = tableNodes.stream() .filter(node -> nodesCache.getIfPresent(node.getPreferInetSocketAddress()) == null) @@ -109,8 +97,7 @@ private synchronized void findEffectiveNode() throws InterruptedException { .contains(node.getPreferInetSocketAddress())) .findFirst(); if (!chosenNode.isPresent()) { - logger.warn("Failed to find effective node, have tried {} times", count.get()); - resetCount(); + logger.warn("No available node to choose"); return; } @@ -119,7 +106,7 @@ private synchronized void findEffectiveNode() throws InterruptedException { cur = new InetSocketAddress(chosenNode.get().getPreferInetSocketAddress().getAddress(), chosenNode.get().getPreferInetSocketAddress().getPort()); - logger.info("Try to get effective connection by using {} at times {}", cur, count.get()); + logger.info("Try to get effective connection by using {} at seq {}", cur, count.get()); TronNetService.getP2pService().connect(chosenNode.get(), future -> { if (future.isCancelled()) { // Connection attempt cancelled by user @@ -134,7 +121,7 @@ private synchronized void findEffectiveNode() throws InterruptedException { // Connection established successfully future.channel().closeFuture().addListener((ChannelFutureListener) closeFuture -> { logger.info("Close chosen channel:{}", cur); - if (!haveEffectiveConnection()) { + if (isIsolateLand()) { findEffectiveNode(); } }); @@ -142,14 +129,10 @@ private synchronized void findEffectiveNode() throws InterruptedException { }); } - public void resetCount() { + private void resetCount() { count.set(0); } - public int getCount() { - return count.get(); - } - private void disconnect() { tronNetDelegate.getActivePeer().forEach(p -> { if (p.getInetSocketAddress().equals(cur)) { diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java index 64eefacbb72..0332e008c72 100644 --- a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -104,7 +104,7 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { if (effectiveCheckService.isEffectiveCheck() && peer.getInetSocketAddress().equals(effectiveCheckService.getCur())) { - if (!effectiveCheckService.haveEffectiveConnection() + if (effectiveCheckService.isIsolateLand() && msg.getSolidBlockId().getNum() <= chainBaseManager.getSolidBlockId().getNum()) { logger.info("Peer's solid block {} is below than we, peer->{}, me->{}", peer.getInetSocketAddress(), @@ -113,10 +113,8 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { peer.disconnect(ReasonCode.BELOW_THAN_ME); return; } else { - logger.info("Success to find effective node {} at times {}", - peer.getInetSocketAddress(), effectiveCheckService.getCount()); - effectiveCheckService.setFound(true); - effectiveCheckService.resetCount(); + logger.info("Success to find effective node {}", peer.getInetSocketAddress()); + peer.setNeedSyncFromUs(false); } } diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index cbacb5f6246..b523cbf82b2 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -31,5 +31,6 @@ public void testConfig() { Assert.assertEquals(Args.getInstance().getMaxFastForwardNum(), 3); Assert.assertEquals(Args.getInstance().getBlockCacheTimeout(), 60); Assert.assertEquals(Args.getInstance().isNodeDetectEnable(), false); + Assert.assertTrue(Args.getInstance().isNodeEffectiveCheckEnable()); } } \ No newline at end of file From 73b88097823b62e97b3d7623ab7128a2b6a54197 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 21 Mar 2023 17:01:58 +0800 Subject: [PATCH 0664/1197] fix(net): update libp2p to test-callback-v2 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index bd5b400ae38..84433da52d1 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-callback-v1' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-callback-v2' compile project(":protocol") } From 02d2e9f7b175ba5d4d6974d2d7e6f802ef348876 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 22 Mar 2023 12:20:00 +0800 Subject: [PATCH 0665/1197] feat(net): normalize http urls to prevent attacks --- .../java/org/tron/core/services/filter/HttpApiAccessFilter.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/framework/src/main/java/org/tron/core/services/filter/HttpApiAccessFilter.java b/framework/src/main/java/org/tron/core/services/filter/HttpApiAccessFilter.java index 35ebd9d6d6d..ae7ab75a473 100644 --- a/framework/src/main/java/org/tron/core/services/filter/HttpApiAccessFilter.java +++ b/framework/src/main/java/org/tron/core/services/filter/HttpApiAccessFilter.java @@ -1,6 +1,7 @@ package org.tron.core.services.filter; import com.alibaba.fastjson.JSONObject; +import java.net.URI; import java.util.List; import javax.servlet.Filter; import javax.servlet.FilterChain; @@ -58,6 +59,7 @@ private boolean isDisabled(String endpoint) { boolean disabled = false; try { + endpoint = URI.create(endpoint).normalize().toString(); List disabledApiList = CommonParameter.getInstance().getDisabledApiList(); if (!disabledApiList.isEmpty()) { disabled = disabledApiList.contains(endpoint.split("/")[2].toLowerCase()); From fdb17bcd72dc7ca20cac4d509fdab2d6ec5904f5 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 22 Mar 2023 15:20:08 +0800 Subject: [PATCH 0666/1197] fix(net): resolve the bug that Lack size is increasing by time --- common/build.gradle | 2 +- .../effective/EffectiveCheckService.java | 18 +++++++++++++++--- .../service/handshake/HandshakeService.java | 4 ++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/common/build.gradle b/common/build.gradle index 84433da52d1..bcbfb8b9249 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-callback-v2' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-callback-v3' compile project(":protocol") } diff --git a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java index d00340a3ada..7739e065487 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java @@ -39,6 +39,7 @@ public class EffectiveCheckService { private InetSocketAddress cur; private final AtomicInteger count = new AtomicInteger(0); private ScheduledExecutorService executor = null; + private boolean isRunning = false; public void init() { if (isEffectiveCheck) { @@ -50,7 +51,7 @@ public void init() { } catch (Exception e) { logger.error("Check effective connection processing failed", e); } - }, 60, 5, TimeUnit.SECONDS); + }, 60, 2, TimeUnit.SECONDS); } else { logger.warn("EffectiveCheckService is disabled"); } @@ -73,7 +74,7 @@ public boolean isIsolateLand() { } //try to find node which we can sync from - private synchronized void findEffectiveNode() { + private void findEffectiveNode() { if (!isIsolateLand()) { if (count.get() > 0) { logger.info("Success to verify effective node {}", cur); @@ -82,14 +83,21 @@ private synchronized void findEffectiveNode() { return; } + if (isRunning) { + logger.info("Thread is running"); + return; + } + isRunning = true; + if (cur != null && tronNetDelegate.getActivePeer().stream() .anyMatch(p -> p.getInetSocketAddress().equals(cur))) { // we encounter no effective connection again, so we disconnect with last used node disconnect(); + isRunning = false; return; } - List tableNodes = TronNetService.getP2pService().getAllNodes(); + List tableNodes = TronNetService.getP2pService().getConnectableNodes(); Optional chosenNode = tableNodes.stream() .filter(node -> nodesCache.getIfPresent(node.getPreferInetSocketAddress()) == null) @@ -110,17 +118,20 @@ private synchronized void findEffectiveNode() { TronNetService.getP2pService().connect(chosenNode.get(), future -> { if (future.isCancelled()) { // Connection attempt cancelled by user + isRunning = false; logger.warn("Channel {} has been cancelled by user", cur); } else if (!future.isSuccess()) { // You might get a NullPointerException here because the future might not be completed yet. logger.warn("Connect to chosen peer {} fail, cause:{}", cur, future.cause().getMessage()); future.channel().close(); + isRunning = false; findEffectiveNode(); } else { // Connection established successfully future.channel().closeFuture().addListener((ChannelFutureListener) closeFuture -> { logger.info("Close chosen channel:{}", cur); + isRunning = false; if (isIsolateLand()) { findEffectiveNode(); } @@ -134,6 +145,7 @@ private void resetCount() { } private void disconnect() { + logger.info("Disconnect with {}", cur); tronNetDelegate.getActivePeer().forEach(p -> { if (p.getInetSocketAddress().equals(cur)) { p.disconnect(ReasonCode.BELOW_THAN_ME); diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java index 0332e008c72..b81517e2adc 100644 --- a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -102,8 +102,8 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { return; } - if (effectiveCheckService.isEffectiveCheck() && - peer.getInetSocketAddress().equals(effectiveCheckService.getCur())) { + if (effectiveCheckService.isEffectiveCheck() && peer.getInetSocketAddress() + .equals(effectiveCheckService.getCur())) { if (effectiveCheckService.isIsolateLand() && msg.getSolidBlockId().getNum() <= chainBaseManager.getSolidBlockId().getNum()) { logger.info("Peer's solid block {} is below than we, peer->{}, me->{}", From 891c15aeb0291485a8cda6946a9966c8701c6033 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 22 Mar 2023 15:29:52 +0800 Subject: [PATCH 0667/1197] fix(net): optimize code --- .../tron/core/net/service/handshake/HandshakeService.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java index b81517e2adc..924c792d0c4 100644 --- a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -102,10 +102,9 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { return; } - if (effectiveCheckService.isEffectiveCheck() && peer.getInetSocketAddress() - .equals(effectiveCheckService.getCur())) { - if (effectiveCheckService.isIsolateLand() - && msg.getSolidBlockId().getNum() <= chainBaseManager.getSolidBlockId().getNum()) { + if (effectiveCheckService.isEffectiveCheck() && effectiveCheckService.isIsolateLand() + && peer.getInetSocketAddress().equals(effectiveCheckService.getCur())) { + if (msg.getSolidBlockId().getNum() <= chainBaseManager.getSolidBlockId().getNum()) { logger.info("Peer's solid block {} is below than we, peer->{}, me->{}", peer.getInetSocketAddress(), msg.getSolidBlockId().getNum(), From f7c93fa3f2829ee0192bbf8b4e7579b8e17f6222 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 22 Mar 2023 17:00:31 +0800 Subject: [PATCH 0668/1197] fix(net): optimize EffectiveCheckService --- .../tron/core/net/service/effective/EffectiveCheckService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java index 7739e065487..18e380f102a 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java @@ -98,7 +98,6 @@ private void findEffectiveNode() { } List tableNodes = TronNetService.getP2pService().getConnectableNodes(); - Optional chosenNode = tableNodes.stream() .filter(node -> nodesCache.getIfPresent(node.getPreferInetSocketAddress()) == null) .filter(node -> !TronNetService.getP2pConfig().getActiveNodes() @@ -106,6 +105,7 @@ private void findEffectiveNode() { .findFirst(); if (!chosenNode.isPresent()) { logger.warn("No available node to choose"); + isRunning = false; return; } From bfa2ffef5e743f6d0109dbac796fe8251ac0ec3d Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 23 Mar 2023 12:27:18 +0800 Subject: [PATCH 0669/1197] feat(net): add unit test for url checking --- .../filter/HttpApiAccessFilterTest.java | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java b/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java index 4a288b4402c..dcf56c18ae9 100644 --- a/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java @@ -4,7 +4,9 @@ import java.io.File; import java.io.IOException; import java.io.InputStreamReader; +import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import org.apache.http.HttpResponse; @@ -21,10 +23,13 @@ import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; +import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.FileUtil; +import org.tron.common.utils.ReflectUtils; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; +import org.tron.core.net.peer.PeerConnection; import org.tron.core.services.http.FullNodeHttpApiService; import org.tron.core.services.interfaceOnPBFT.http.PBFT.HttpApiOnPBFTService; import org.tron.core.services.interfaceOnSolidity.http.solidity.HttpApiOnSolidityService; @@ -37,6 +42,7 @@ public class HttpApiAccessFilterTest { private static Application appTest; private static CloseableHttpClient httpClient = HttpClients.createDefault(); private static String dbPath = "output_http_api_access_filter_test"; + private static HttpApiAccessFilter httpApiAccessFilter; /** * init dependencies. @@ -47,7 +53,7 @@ public static void init() { Args.getInstance().setFullNodeAllowShieldedTransactionArgs(false); context = new TronApplicationContext(DefaultConfig.class); appTest = ApplicationFactory.create(context); - + httpApiAccessFilter = context.getBean(HttpApiAccessFilter.class); FullNodeHttpApiService httpApiService = context .getBean(FullNodeHttpApiService.class); HttpApiOnSolidityService httpApiOnSolidityService = context @@ -153,4 +159,31 @@ private int getReuqestCode(String url) { return 0; } + + @Test + public void testIsDisabled() throws Exception { + List list = new ArrayList<>(); + list.add("getnowblock"); + CommonParameter.getInstance().setDisabledApiList(list); + Method privateMethod = httpApiAccessFilter.getClass() + .getDeclaredMethod("isDisabled", String.class); + privateMethod.setAccessible(true); + + String url = "/wallet/getnowblock"; + boolean f = (boolean) privateMethod.invoke(httpApiAccessFilter,url); + Assert.assertTrue(f); + + url = "/wallet/a/../b/../getnowblock"; + f = (boolean) privateMethod.invoke(httpApiAccessFilter,url); + Assert.assertTrue(f); + + url = "/wallet/a/b/../getnowblock"; + f = (boolean) privateMethod.invoke(httpApiAccessFilter,url); + Assert.assertTrue(!f); + + url = "/wallet/getblock"; + f = (boolean) privateMethod.invoke(httpApiAccessFilter,url); + Assert.assertTrue(!f); + } + } From d23fbb17e206618d7d45d7b2d9b6e5dcbfb05624 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 23 Mar 2023 16:36:22 +0800 Subject: [PATCH 0670/1197] fix(net): change node.effectiveCheckEnable default to false --- common/build.gradle | 2 +- common/src/main/java/org/tron/core/Constant.java | 2 +- .../src/main/java/org/tron/core/config/args/Args.java | 8 +++++--- .../net/service/effective/EffectiveCheckService.java | 9 +++++++-- .../test/java/org/tron/common/config/args/ArgsTest.java | 2 +- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/common/build.gradle b/common/build.gradle index bcbfb8b9249..a09a1ac9159 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-callback-v3' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-callback-v4' compile project(":protocol") } diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index efff664f38e..faa01540cda 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -83,7 +83,7 @@ public class Constant { public static final String BLOCK_NEED_SYNC_CHECK = "block.needSyncCheck"; public static final String NODE_DISCOVERY_ENABLE = "node.discovery.enable"; public static final String NODE_DISCOVERY_PERSIST = "node.discovery.persist"; - public static final String NODE_ENABLE_EFFECTIVE_CHECK = "node.enableEffectiveCheck"; + public static final String NODE_EFFECTIVE_CHECK_ENABLE = "node.effectiveCheckEnable"; public static final String NODE_CONNECTION_TIMEOUT = "node.connection.timeout"; public static final String NODE_FETCH_BLOCK_TIMEOUT = "node.fetchBlock.timeout"; public static final String NODE_CHANNEL_READ_TIMEOUT = "node.channel.read.timeout"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 4d3c76deb97..60c87f737ff 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -124,7 +124,7 @@ public static void clearParam() { PARAMETER.needSyncCheck = false; PARAMETER.nodeDiscoveryEnable = false; PARAMETER.nodeDiscoveryPersist = false; - PARAMETER.nodeEffectiveCheckEnable = true; + PARAMETER.nodeEffectiveCheckEnable = false; PARAMETER.nodeConnectionTimeout = 2000; PARAMETER.activeNodes = new ArrayList<>(); PARAMETER.passiveNodes = new ArrayList<>(); @@ -556,8 +556,8 @@ public static void setParam(final String[] args, final String confFileName) { && config.getBoolean(Constant.NODE_DISCOVERY_PERSIST); PARAMETER.nodeEffectiveCheckEnable = - !config.hasPath(Constant.NODE_ENABLE_EFFECTIVE_CHECK) - || config.getBoolean(Constant.NODE_ENABLE_EFFECTIVE_CHECK); + config.hasPath(Constant.NODE_EFFECTIVE_CHECK_ENABLE) + && config.getBoolean(Constant.NODE_EFFECTIVE_CHECK_ENABLE); PARAMETER.nodeConnectionTimeout = config.hasPath(Constant.NODE_CONNECTION_TIMEOUT) @@ -1612,6 +1612,7 @@ public static void logConfig() { logger.info("Bind IP: {}", parameter.getNodeDiscoveryBindIp()); logger.info("External IP: {}", parameter.getNodeExternalIp()); logger.info("Listen port: {}", parameter.getNodeListenPort()); + logger.info("Node ipv6 enable: {}", parameter.isNodeEnableIpv6()); logger.info("Discover enable: {}", parameter.isNodeDiscoveryEnable()); logger.info("Active node size: {}", parameter.getActiveNodes().size()); logger.info("Passive node size: {}", parameter.getPassiveNodes().size()); @@ -1626,6 +1627,7 @@ public static void logConfig() { logger.info("Trx reference block: {}", parameter.getTrxReferenceBlock()); logger.info("Open full tcp disconnect: {}", parameter.isOpenFullTcpDisconnect()); logger.info("Node detect enable: {}", parameter.isNodeDetectEnable()); + logger.info("Node effective check enable: {}", parameter.isNodeEffectiveCheckEnable()); logger.info("************************ Backup config ************************"); logger.info("Backup priority: {}", parameter.getBackupPriority()); logger.info("Backup listen port: {}", parameter.getBackupPort()); diff --git a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java index 18e380f102a..ab4a2bdbd7e 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java @@ -5,8 +5,10 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; import io.netty.channel.ChannelFutureListener; import java.net.InetSocketAddress; +import java.util.HashSet; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -33,7 +35,7 @@ public class EffectiveCheckService { private final Cache nodesCache = CacheBuilder.newBuilder() .initialCapacity(100) - .maximumSize(1000) + .maximumSize(10000) .expireAfterWrite(10, TimeUnit.MINUTES).build(); @Getter private InetSocketAddress cur; @@ -53,7 +55,7 @@ public void init() { } }, 60, 2, TimeUnit.SECONDS); } else { - logger.warn("EffectiveCheckService is disabled"); + logger.info("EffectiveCheckService is disabled"); } } @@ -98,8 +100,11 @@ private void findEffectiveNode() { } List tableNodes = TronNetService.getP2pService().getConnectableNodes(); + Set usedAddressSet = new HashSet<>(); + tronNetDelegate.getActivePeer().forEach(p -> usedAddressSet.add(p.getInetSocketAddress())); Optional chosenNode = tableNodes.stream() .filter(node -> nodesCache.getIfPresent(node.getPreferInetSocketAddress()) == null) + .filter(node -> !usedAddressSet.contains(node.getPreferInetSocketAddress())) .filter(node -> !TronNetService.getP2pConfig().getActiveNodes() .contains(node.getPreferInetSocketAddress())) .findFirst(); diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index b523cbf82b2..b72855539d2 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -31,6 +31,6 @@ public void testConfig() { Assert.assertEquals(Args.getInstance().getMaxFastForwardNum(), 3); Assert.assertEquals(Args.getInstance().getBlockCacheTimeout(), 60); Assert.assertEquals(Args.getInstance().isNodeDetectEnable(), false); - Assert.assertTrue(Args.getInstance().isNodeEffectiveCheckEnable()); + Assert.assertFalse(Args.getInstance().isNodeEffectiveCheckEnable()); } } \ No newline at end of file From 3799c16f3719fd70b451e636a353688051cdb194 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 23 Mar 2023 18:20:54 +0800 Subject: [PATCH 0671/1197] feat(config):optimize logs for dynamic loading configuration --- .../tron/core/config/args/DynamicArgs.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java index e441bc527a2..6e7aabe1119 100644 --- a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java +++ b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java @@ -46,12 +46,15 @@ public void start() { confFile = parameter.getShellConfFileName(); } else { confFile = Constant.TESTNET_CONF; - // //logger.warn("Configuration path is required!"); //return; } File confDir = new File(confFile); + if (!confDir.exists()) { + logger.warn("Configuration path is required! No such file {}", confFile); + return; + } confFileName = confDir.getName(); if (confFile.contains(File.separator)) { path = FileSystems.getDefault().getPath(confDir.getPath()).getParent(); @@ -60,10 +63,10 @@ public void start() { path = FileSystems.getDefault().getPath(directory.getAbsolutePath()); } - logger.info("confDirString = {}", confDir); + logger.debug("confDirString = {}", confDir); watchService = FileSystems.getDefault().newWatchService(); path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY); - logger.info("watch path : {}", path.toString()); + logger.debug("watch path : {}", path.toString()); } catch (Exception e) { logger.error("Exception caught when register the watch key", e.getCause()); return; @@ -77,27 +80,28 @@ public void start() { final Path changed = (Path)event.context(); if (changed.endsWith(confFileName)) { reload(); - logger.info("Config was modify and we reload it"); + logger.info("The configuration was modified and we reloaded it"); } changeCount++; } - logger.info("change count : {}", changeCount); + logger.debug("change count : {}", changeCount); boolean valid = wk.reset(); if (!valid) { path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY); } } catch (InterruptedException e) { - logger.warn(""); + logger.warn("WatchService was interrupted"); break; } catch (IOException e) { + logger.error("Exception caught when register the watch key", e.getCause()); break; } } } public void reload() { - logger.info("reloading ... "); + logger.debug("Reloading ... "); Config config = Configuration.getByFileName(parameter.getShellConfFileName(), Constant.TESTNET_CONF); @@ -116,7 +120,6 @@ private void updateActiveNodes(Config config) { Args.getInetSocketAddress(config, Constant.NODE_ACTIVE); parameter.setActiveNodes(newActiveNodes); parameter.getActiveNodes().forEach(n -> { - logger.info("active node : {}", n.toString()); if (!lastActiveNodes.contains(n)) { TronNetService.getP2pConfig().getActiveNodes().add(n); if (!TronNetService.getP2pConfig().getTrustNodes().contains(n.getAddress())) { @@ -131,6 +134,8 @@ private void updateActiveNodes(Config config) { TronNetService.getP2pConfig().getTrustNodes().remove(ln.getAddress()); } }); + logger.debug("p2p active nodes : {}", + TronNetService.getP2pConfig().getActiveNodes().toString()); } private void updateTrustNodes(Config config) { @@ -142,7 +147,6 @@ private void updateTrustNodes(Config config) { List newPassiveNodes = Args.getInetAddress(config, Constant.NODE_PASSIVE); parameter.setPassiveNodes(newPassiveNodes); parameter.getPassiveNodes().forEach(n -> { - logger.info("passive node : {}", n.toString()); if (!lastPassiveNodes.contains(n) || !TronNetService.getP2pConfig().getTrustNodes().contains(n)) { TronNetService.getP2pConfig().getTrustNodes().add(n); @@ -154,6 +158,7 @@ private void updateTrustNodes(Config config) { TronNetService.getP2pConfig().getTrustNodes().remove(ln); } }); + logger.debug("p2p trust nodes : {}", TronNetService.getP2pConfig().getTrustNodes().toString()); } public void close() { From ef6b5349f2489c151c1a78458e0a06609a658753 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Fri, 24 Mar 2023 14:28:42 +0800 Subject: [PATCH 0672/1197] feat(config):add dynamic loading configuration test case --- .../tron/core/config/args/DynamicArgs.java | 1 + .../core/config/args/DynamicArgsTest.java | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java diff --git a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java index 6e7aabe1119..9da606e680a 100644 --- a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java +++ b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java @@ -92,6 +92,7 @@ public void start() { } } catch (InterruptedException e) { logger.warn("WatchService was interrupted"); + Thread.currentThread().interrupt(); break; } catch (IOException e) { logger.error("Exception caught when register the watch key", e.getCause()); diff --git a/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java new file mode 100644 index 00000000000..c544a545e16 --- /dev/null +++ b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java @@ -0,0 +1,55 @@ +package org.tron.core.config.args; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.ReflectUtils; +import org.tron.core.Constant; +import org.tron.core.config.DefaultConfig; +import org.tron.core.net.TronNetService; +import org.tron.p2p.P2pConfig; + +import java.io.File; + +public class DynamicArgsTest { + protected TronApplicationContext context; + private DynamicArgs dynamicArgs; + private String dbPath = "output-dynamic-config-test"; + + @Before + public void init() { + Args.setParam(new String[]{"--output-directory", dbPath}, + Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + dynamicArgs = context.getBean(DynamicArgs.class); + + } + + @After + public void destroy() { + Args.clearParam(); + context.destroy(); + FileUtil.deleteDir(new File(dbPath)); + } + + @Test + public void get() { + CommonParameter parameter = Args.getInstance(); + Assert.assertFalse(parameter.isDynamicConfigEnable()); + + } + + @Test + public void start() { + dynamicArgs.start(); + TronNetService tronNetService = context.getBean(TronNetService.class); + ReflectUtils.setFieldValue(tronNetService, "p2pConfig", new P2pConfig()); + dynamicArgs.reload(); + dynamicArgs.close(); + Assert.assertTrue((boolean)ReflectUtils.getFieldObject(dynamicArgs, "shutdown")); + } +} From dd56bf0b4c5f2966c9b42b3991e6411e8ec0d814 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 24 Mar 2023 17:57:13 +0800 Subject: [PATCH 0673/1197] fix(net): use get,add to replace set list in P2pConfig --- .../src/main/java/org/tron/core/net/TronNetService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index ebd0b1b4114..718f0844fc2 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -154,9 +154,9 @@ private P2pConfig getConfig() { logger.debug("Seed InetSocketAddress: {}", inetSocketAddress); } P2pConfig config = new P2pConfig(); - config.setSeedNodes(seeds); - config.setActiveNodes(parameter.getActiveNodes()); - config.setTrustNodes(parameter.getPassiveNodes()); + config.getSeedNodes().addAll(seeds); + config.getActiveNodes().addAll(parameter.getActiveNodes()); + config.getTrustNodes().addAll(parameter.getPassiveNodes()); config.getActiveNodes().forEach(n -> config.getTrustNodes().add(n.getAddress())); parameter.getFastForwardNodes().forEach(f -> config.getTrustNodes().add(f.getAddress())); int maxConnections = parameter.getMaxConnections(); From 659d80a1c221645dc13b82c081508c25c933ec65 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Fri, 24 Mar 2023 18:29:13 +0800 Subject: [PATCH 0674/1197] fix(net):fix the problem of repeated fetch block in FetchBlockService --- .../main/java/org/tron/core/net/peer/PeerConnection.java | 8 ++++++++ .../java/org/tron/core/net/service/adv/AdvService.java | 5 +++-- .../core/net/service/fetchblock/FetchBlockService.java | 4 ++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index a13240fa8ff..ab379ec8b75 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -293,6 +293,14 @@ public static boolean needToLog(Message msg) { return true; } + public synchronized boolean checkAndPutAdvInvRequest(Item key, Long value) { + if (advInvRequest.containsKey(key)) { + return false; + } + advInvRequest.put(key, value); + return true; + } + @Override public boolean equals(Object o) { if (!(o instanceof PeerConnection)) { diff --git a/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java b/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java index b6ea7a3445f..03668d01837 100644 --- a/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java +++ b/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java @@ -281,8 +281,9 @@ private void consumerInvToFetch() { && invSender.getSize(peer) < MAX_TRX_FETCH_PER_PEER) .sorted(Comparator.comparingInt(peer -> invSender.getSize(peer))) .findFirst().ifPresent(peer -> { - invSender.add(item, peer); - peer.getAdvInvRequest().put(item, now); + if (peer.checkAndPutAdvInvRequest(item, now)) { + invSender.add(item, peer); + } invToFetch.remove(item); }); }); diff --git a/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java b/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java index f3699c3be2e..de20a17af0b 100644 --- a/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java +++ b/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java @@ -117,8 +117,8 @@ private void fetchBlockProcess(FetchBlockInfo fetchBlock) { if (optionalPeerConnection.isPresent()) { optionalPeerConnection.ifPresent(firstPeer -> { - if (shouldFetchBlock(firstPeer, fetchBlock)) { - firstPeer.getAdvInvRequest().put(item, System.currentTimeMillis()); + if (shouldFetchBlock(firstPeer, fetchBlock) + && firstPeer.checkAndPutAdvInvRequest(item, System.currentTimeMillis())) { firstPeer.sendMessage(new FetchInvDataMessage(Collections.singletonList(item.getHash()), item.getType())); this.fetchBlockInfo = null; From 52eaea6eb8df81edc92d46b6b91e8fd477d505a7 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 27 Mar 2023 12:15:25 +0800 Subject: [PATCH 0675/1197] feat(net): add global rate limiter test --- .../ratelimiter/GlobalRateLimiterTest.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/services/ratelimiter/GlobalRateLimiterTest.java diff --git a/framework/src/test/java/org/tron/core/services/ratelimiter/GlobalRateLimiterTest.java b/framework/src/test/java/org/tron/core/services/ratelimiter/GlobalRateLimiterTest.java new file mode 100644 index 00000000000..3187ed36792 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/ratelimiter/GlobalRateLimiterTest.java @@ -0,0 +1,22 @@ +package org.tron.core.services.ratelimiter; + +import java.lang.reflect.Field; +import org.junit.Assert; +import org.junit.Test; +import org.tron.core.Constant; +import org.tron.core.config.args.Args; + +public class GlobalRateLimiterTest { + + @Test + public void testAcquire() throws Exception { + String[] a = new String[0]; + Args.setParam(a, Constant.TESTNET_CONF); + RuntimeData runtimeData = new RuntimeData(null); + Field field = runtimeData.getClass().getDeclaredField("address"); + field.setAccessible(true); + field.set(runtimeData, "127.0.0.1"); + Assert.assertEquals(runtimeData.getRemoteAddr(), "127.0.0.1"); + GlobalRateLimiter.acquire(runtimeData); + } +} \ No newline at end of file From 7128fa9f1755ea73cd8598295a067653cc724c52 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 27 Mar 2023 14:44:07 +0800 Subject: [PATCH 0676/1197] fix(net): don't find new node if executor is closed --- .../src/main/java/org/tron/core/net/TronNetService.java | 2 +- .../core/net/service/effective/EffectiveCheckService.java | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 718f0844fc2..fab50cd500d 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -113,9 +113,9 @@ public void close() { peerStatusCheck.close(); transactionsMsgHandler.close(); fetchBlockService.close(); + effectiveCheckService.close(); p2pService.close(); relayService.close(); - effectiveCheckService.close(); logger.info("Net service closed successfully"); } diff --git a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java index ab4a2bdbd7e..e3bdc82c05c 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java @@ -5,6 +5,7 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; import io.netty.channel.ChannelFutureListener; import java.net.InetSocketAddress; +import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Optional; @@ -42,6 +43,7 @@ public class EffectiveCheckService { private final AtomicInteger count = new AtomicInteger(0); private ScheduledExecutorService executor = null; private boolean isRunning = false; + private boolean isClosed = false; public void init() { if (isEffectiveCheck) { @@ -60,6 +62,7 @@ public void init() { } public void close() { + isClosed = true; if (executor != null) { try { executor.shutdown(); @@ -77,6 +80,9 @@ public boolean isIsolateLand() { //try to find node which we can sync from private void findEffectiveNode() { + if (isClosed) { + return; + } if (!isIsolateLand()) { if (count.get() > 0) { logger.info("Success to verify effective node {}", cur); @@ -100,6 +106,7 @@ private void findEffectiveNode() { } List tableNodes = TronNetService.getP2pService().getConnectableNodes(); + tableNodes.sort(Comparator.comparingLong(node -> -node.getUpdateTime())); Set usedAddressSet = new HashSet<>(); tronNetDelegate.getActivePeer().forEach(p -> usedAddressSet.add(p.getInetSocketAddress())); Optional chosenNode = tableNodes.stream() From ae5dd9d5238229440d70aff9deca7924eb833796 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 27 Mar 2023 20:08:02 +0800 Subject: [PATCH 0677/1197] fix(net): remove isClosed, use executor to schedule --- .../effective/EffectiveCheckService.java | 40 +++++++++---------- .../service/handshake/HandshakeService.java | 4 +- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java index e3bdc82c05c..437e88a12bd 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java @@ -37,13 +37,12 @@ public class EffectiveCheckService { private final Cache nodesCache = CacheBuilder.newBuilder() .initialCapacity(100) .maximumSize(10000) - .expireAfterWrite(10, TimeUnit.MINUTES).build(); + .expireAfterWrite(20, TimeUnit.MINUTES).build(); @Getter private InetSocketAddress cur; private final AtomicInteger count = new AtomicInteger(0); private ScheduledExecutorService executor = null; private boolean isRunning = false; - private boolean isClosed = false; public void init() { if (isEffectiveCheck) { @@ -61,8 +60,15 @@ public void init() { } } + private void triggerNext() { + try { + executor.submit(this::findEffectiveNode); + } catch (Exception e) { + logger.warn("Submit effective service task failed, message:{}", e.getMessage()); + } + } + public void close() { - isClosed = true; if (executor != null) { try { executor.shutdown(); @@ -80,14 +86,11 @@ public boolean isIsolateLand() { //try to find node which we can sync from private void findEffectiveNode() { - if (isClosed) { - return; - } if (!isIsolateLand()) { if (count.get() > 0) { logger.info("Success to verify effective node {}", cur); + resetCount(); } - resetCount(); return; } @@ -100,8 +103,12 @@ private void findEffectiveNode() { if (cur != null && tronNetDelegate.getActivePeer().stream() .anyMatch(p -> p.getInetSocketAddress().equals(cur))) { // we encounter no effective connection again, so we disconnect with last used node - disconnect(); - isRunning = false; + logger.info("Disconnect with {}", cur); + tronNetDelegate.getActivePeer().forEach(p -> { + if (p.getInetSocketAddress().equals(cur)) { + p.disconnect(ReasonCode.BELOW_THAN_ME); + } + }); return; } @@ -130,22 +137,20 @@ private void findEffectiveNode() { TronNetService.getP2pService().connect(chosenNode.get(), future -> { if (future.isCancelled()) { // Connection attempt cancelled by user - isRunning = false; - logger.warn("Channel {} has been cancelled by user", cur); } else if (!future.isSuccess()) { // You might get a NullPointerException here because the future might not be completed yet. logger.warn("Connect to chosen peer {} fail, cause:{}", cur, future.cause().getMessage()); future.channel().close(); isRunning = false; - findEffectiveNode(); + triggerNext(); } else { // Connection established successfully future.channel().closeFuture().addListener((ChannelFutureListener) closeFuture -> { logger.info("Close chosen channel:{}", cur); isRunning = false; if (isIsolateLand()) { - findEffectiveNode(); + triggerNext(); } }); } @@ -155,13 +160,4 @@ private void findEffectiveNode() { private void resetCount() { count.set(0); } - - private void disconnect() { - logger.info("Disconnect with {}", cur); - tronNetDelegate.getActivePeer().forEach(p -> { - if (p.getInetSocketAddress().equals(cur)) { - p.disconnect(ReasonCode.BELOW_THAN_ME); - } - }); - } } diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java index 924c792d0c4..317a3f47a53 100644 --- a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -104,8 +104,8 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { if (effectiveCheckService.isEffectiveCheck() && effectiveCheckService.isIsolateLand() && peer.getInetSocketAddress().equals(effectiveCheckService.getCur())) { - if (msg.getSolidBlockId().getNum() <= chainBaseManager.getSolidBlockId().getNum()) { - logger.info("Peer's solid block {} is below than we, peer->{}, me->{}", + if (msg.getHeadBlockId().getNum() <= chainBaseManager.getHeadBlockId().getNum()) { + logger.info("Peer's head block {} is below than we, peer->{}, me->{}", peer.getInetSocketAddress(), msg.getSolidBlockId().getNum(), chainBaseManager.getSolidBlockId().getNum()); From b4171911874d26886a5802f5f0b9d291b960bd99 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 27 Mar 2023 21:20:31 +0800 Subject: [PATCH 0678/1197] fix(net): remove isRunnig --- .../effective/EffectiveCheckService.java | 42 ++++++++----------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java index 437e88a12bd..32854341c19 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java @@ -42,7 +42,6 @@ public class EffectiveCheckService { private InetSocketAddress cur; private final AtomicInteger count = new AtomicInteger(0); private ScheduledExecutorService executor = null; - private boolean isRunning = false; public void init() { if (isEffectiveCheck) { @@ -54,7 +53,7 @@ public void init() { } catch (Exception e) { logger.error("Check effective connection processing failed", e); } - }, 60, 2, TimeUnit.SECONDS); + }, 60 * 1000, 200, TimeUnit.MILLISECONDS); } else { logger.info("EffectiveCheckService is disabled"); } @@ -94,21 +93,19 @@ private void findEffectiveNode() { return; } - if (isRunning) { - logger.info("Thread is running"); - return; - } - isRunning = true; - - if (cur != null && tronNetDelegate.getActivePeer().stream() - .anyMatch(p -> p.getInetSocketAddress().equals(cur))) { - // we encounter no effective connection again, so we disconnect with last used node - logger.info("Disconnect with {}", cur); - tronNetDelegate.getActivePeer().forEach(p -> { - if (p.getInetSocketAddress().equals(cur)) { - p.disconnect(ReasonCode.BELOW_THAN_ME); - } - }); + if (cur != null) { + if (tronNetDelegate.getActivePeer().stream() + .anyMatch(p -> p.getInetSocketAddress().equals(cur))) { + // we encounter no effective connection again, so we disconnect with last used node + logger.info("Disconnect with {}", cur); + tronNetDelegate.getActivePeer().forEach(p -> { + if (p.getInetSocketAddress().equals(cur)) { + p.disconnect(ReasonCode.BELOW_THAN_ME); + } + }); + } else { + logger.info("Thread is running"); + } return; } @@ -124,7 +121,6 @@ private void findEffectiveNode() { .findFirst(); if (!chosenNode.isPresent()) { logger.warn("No available node to choose"); - isRunning = false; return; } @@ -137,21 +133,19 @@ private void findEffectiveNode() { TronNetService.getP2pService().connect(chosenNode.get(), future -> { if (future.isCancelled()) { // Connection attempt cancelled by user + cur = null; } else if (!future.isSuccess()) { // You might get a NullPointerException here because the future might not be completed yet. logger.warn("Connect to chosen peer {} fail, cause:{}", cur, future.cause().getMessage()); future.channel().close(); - - isRunning = false; + cur = null; triggerNext(); } else { // Connection established successfully future.channel().closeFuture().addListener((ChannelFutureListener) closeFuture -> { logger.info("Close chosen channel:{}", cur); - isRunning = false; - if (isIsolateLand()) { - triggerNext(); - } + cur = null; + triggerNext(); }); } }); From dc63ec19171a84db78c5a5ba08ae846b9fb9fdfd Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 28 Mar 2023 11:41:35 +0800 Subject: [PATCH 0679/1197] feat(net): modify global rate limiter default value --- .../src/main/java/org/tron/core/config/args/Args.java | 10 ++++++---- .../java/org/tron/common/config/args/ArgsTest.java | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index ea44ec36475..368012cfc3d 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -221,8 +221,8 @@ public static void clearParam() { PARAMETER.allowNewRewardAlgorithm = 0; PARAMETER.allowNewReward = 0; PARAMETER.memoFee = 0; - PARAMETER.rateLimiterGlobalQps = 3000; - PARAMETER.rateLimiterGlobalIpQps = 30; + PARAMETER.rateLimiterGlobalQps = 50000; + PARAMETER.rateLimiterGlobalIpQps = 10000; PARAMETER.p2pDisable = false; } @@ -932,11 +932,11 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.rateLimiterGlobalQps = config.hasPath(Constant.RATE_LIMITER_GLOBAL_QPS) ? config - .getInt(Constant.RATE_LIMITER_GLOBAL_QPS) : 3000; + .getInt(Constant.RATE_LIMITER_GLOBAL_QPS) : 50000; PARAMETER.rateLimiterGlobalIpQps = config.hasPath(Constant.RATE_LIMITER_GLOBAL_IP_QPS) ? config - .getInt(Constant.RATE_LIMITER_GLOBAL_IP_QPS) : 30; + .getInt(Constant.RATE_LIMITER_GLOBAL_IP_QPS) : 10000; PARAMETER.rateLimiterInitialization = config.hasPath(Constant.RATE_LIMITER) ? getRateLimiterFromConfig(config) @@ -1490,6 +1490,8 @@ public static void logConfig() { logger.info("Max connection with same IP: {}", parameter.getMaxConnectionsWithSameIp()); logger.info("Solidity threads: {}", parameter.getSolidityThreads()); logger.info("Trx reference block: {}", parameter.getTrxReferenceBlock()); + logger.info("Rate limiter global qps: {}", parameter.getRateLimiterGlobalQps()); + logger.info("Rate limiter global ip qps: {}", parameter.getRateLimiterGlobalIpQps()); logger.info("************************ Backup config ************************"); logger.info("Backup priority: {}", parameter.getBackupPriority()); logger.info("Backup listen port: {}", parameter.getBackupPort()); diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index 5b3f2c8eb78..8bb77ee36da 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -30,8 +30,8 @@ public void testConfig() { Assert.assertEquals(Args.getInstance().getNodeDiscoveryPingTimeout(), 15_000); Assert.assertEquals(Args.getInstance().getMaxFastForwardNum(), 3); Assert.assertEquals(Args.getInstance().getBlockCacheTimeout(), 60); - Assert.assertEquals(Args.getInstance().getRateLimiterGlobalQps(), 3000); - Assert.assertEquals(Args.getInstance().getRateLimiterGlobalIpQps(), 30); + Assert.assertEquals(Args.getInstance().getRateLimiterGlobalQps(), 50000); + Assert.assertEquals(Args.getInstance().getRateLimiterGlobalIpQps(), 10000); Assert.assertEquals(Args.getInstance().p2pDisable, true); } } \ No newline at end of file From 6959bd4590b9dae0dd59a521f853f2b448390e4e Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 28 Mar 2023 14:35:11 +0800 Subject: [PATCH 0680/1197] fix(net):optimize EffectiveCheckService --- .../org/tron/core/net/P2pEventHandlerImpl.java | 5 +++++ .../org/tron/core/net/peer/PeerConnection.java | 11 +++++++++++ .../service/effective/EffectiveCheckService.java | 14 ++++++++------ .../net/service/handshake/HandshakeService.java | 15 --------------- 4 files changed, 24 insertions(+), 21 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java index 66774a216f2..602b6c9f81c 100644 --- a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java +++ b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java @@ -28,6 +28,7 @@ import org.tron.core.net.messagehandler.TransactionsMsgHandler; import org.tron.core.net.peer.PeerConnection; import org.tron.core.net.peer.PeerManager; +import org.tron.core.net.service.effective.EffectiveCheckService; import org.tron.core.net.service.handshake.HandshakeService; import org.tron.core.net.service.keepalive.KeepAliveService; import org.tron.p2p.P2pEventHandler; @@ -78,6 +79,9 @@ public class P2pEventHandlerImpl extends P2pEventHandler { @Autowired private KeepAliveService keepAliveService; + @Autowired + private EffectiveCheckService effectiveCheckService; + private byte MESSAGE_MAX_TYPE = 127; public P2pEventHandlerImpl() { @@ -102,6 +106,7 @@ public synchronized void onDisconnect(Channel channel) { if (peerConnection != null) { peerConnection.onDisconnect(); } + effectiveCheckService.onDisconnect(channel.getInetSocketAddress()); } @Override diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index 7e417bd24f4..c6bdb413f68 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -40,12 +40,14 @@ import org.tron.core.net.message.keepalive.PingMessage; import org.tron.core.net.message.keepalive.PongMessage; import org.tron.core.net.service.adv.AdvService; +import org.tron.core.net.service.effective.EffectiveCheckService; import org.tron.core.net.service.statistics.NodeStatistics; import org.tron.core.net.service.statistics.PeerStatistics; import org.tron.core.net.service.statistics.TronStatsManager; import org.tron.core.net.service.sync.SyncService; import org.tron.p2p.connection.Channel; import org.tron.protos.Protocol; +import org.tron.protos.Protocol.ReasonCode; @Slf4j(topic = "net") @Component @@ -88,6 +90,9 @@ public class PeerConnection { @Autowired private AdvService advService; + @Autowired + private EffectiveCheckService effectiveCheckService; + @Setter @Getter private HelloMessage helloMessageReceive; @@ -182,6 +187,12 @@ public void onConnect() { needSyncFromUs = false; syncService.startSync(this); } else { + if (getInetSocketAddress().equals(effectiveCheckService.getCur())) { + logger.info("Peer's head block {} is below than we, peer->{}, me->{}", + getInetSocketAddress(), peerHeadBlockNum, headBlockNum); + disconnect(ReasonCode.BELOW_THAN_ME); + return; + } needSyncFromPeer = false; if (peerHeadBlockNum == headBlockNum) { needSyncFromUs = false; diff --git a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java index 32854341c19..ac8587c0b5b 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java @@ -3,7 +3,6 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import io.netty.channel.ChannelFutureListener; import java.net.InetSocketAddress; import java.util.Comparator; import java.util.HashSet; @@ -142,11 +141,6 @@ private void findEffectiveNode() { triggerNext(); } else { // Connection established successfully - future.channel().closeFuture().addListener((ChannelFutureListener) closeFuture -> { - logger.info("Close chosen channel:{}", cur); - cur = null; - triggerNext(); - }); } }); } @@ -154,4 +148,12 @@ private void findEffectiveNode() { private void resetCount() { count.set(0); } + + public void onDisconnect(InetSocketAddress inetSocketAddress) { + if (inetSocketAddress.equals(cur)) { + logger.warn("Close chosen peer: {}", cur); + cur = null; + triggerNext(); + } + } } diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java index 317a3f47a53..81feb590e4f 100644 --- a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -102,21 +102,6 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { return; } - if (effectiveCheckService.isEffectiveCheck() && effectiveCheckService.isIsolateLand() - && peer.getInetSocketAddress().equals(effectiveCheckService.getCur())) { - if (msg.getHeadBlockId().getNum() <= chainBaseManager.getHeadBlockId().getNum()) { - logger.info("Peer's head block {} is below than we, peer->{}, me->{}", - peer.getInetSocketAddress(), - msg.getSolidBlockId().getNum(), - chainBaseManager.getSolidBlockId().getNum()); - peer.disconnect(ReasonCode.BELOW_THAN_ME); - return; - } else { - logger.info("Success to find effective node {}", peer.getInetSocketAddress()); - peer.setNeedSyncFromUs(false); - } - } - peer.setHelloMessageReceive(msg); peer.getChannel().updateAvgLatency( From 66f1ea6d64890b20fc673595252abc7bdfcb6c84 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 28 Mar 2023 14:39:15 +0800 Subject: [PATCH 0681/1197] fix(net): delete changes in HandshakeService --- .../org/tron/core/net/service/handshake/HandshakeService.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java index 81feb590e4f..6c9e53c3a98 100644 --- a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -11,7 +11,6 @@ import org.tron.core.net.message.handshake.HelloMessage; import org.tron.core.net.peer.PeerConnection; import org.tron.core.net.peer.PeerManager; -import org.tron.core.net.service.effective.EffectiveCheckService; import org.tron.core.net.service.relay.RelayService; import org.tron.p2p.discover.Node; import org.tron.protos.Protocol.ReasonCode; @@ -23,9 +22,6 @@ public class HandshakeService { @Autowired private RelayService relayService; - @Autowired - private EffectiveCheckService effectiveCheckService; - @Autowired private ChainBaseManager chainBaseManager; From 8b23eb705ccf1e27a01190ce7708197656afe76f Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 28 Mar 2023 14:43:15 +0800 Subject: [PATCH 0682/1197] fix(net):optimize EffectiveCheckService --- .../tron/core/net/service/effective/EffectiveCheckService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java index ac8587c0b5b..057480905f2 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java @@ -52,7 +52,7 @@ public void init() { } catch (Exception e) { logger.error("Check effective connection processing failed", e); } - }, 60 * 1000, 200, TimeUnit.MILLISECONDS); + }, 60 , 5, TimeUnit.SECONDS); } else { logger.info("EffectiveCheckService is disabled"); } From ec5ac7069cea0b5837f77dc2d2a72afc5f62a6c8 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 28 Mar 2023 14:58:23 +0800 Subject: [PATCH 0683/1197] feat(config):change the method of getting configuration file changes --- .../tron/core/config/args/DynamicArgs.java | 161 ++++++------------ .../core/config/args/DynamicArgsTest.java | 19 ++- 2 files changed, 63 insertions(+), 117 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java index 9da606e680a..c0f08f61148 100644 --- a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java +++ b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java @@ -4,16 +4,13 @@ import com.typesafe.config.Config; import java.io.File; -import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; -import java.nio.file.FileSystems; -import java.nio.file.Path; -import java.nio.file.StandardWatchEventKinds; -import java.nio.file.WatchEvent; -import java.nio.file.WatchKey; -import java.nio.file.WatchService; import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.tron.common.parameter.CommonParameter; @@ -27,78 +24,54 @@ public class DynamicArgs { private final CommonParameter parameter = Args.getInstance(); - private volatile boolean shutdown = false; + private long lastModified = 0; + + private ScheduledExecutorService reloadExecutor = Executors.newSingleThreadScheduledExecutor(); public void init() { if (parameter.isDynamicConfigEnable()) { - new Thread(this::start, "DynamicArgs").start(); + File config = getConfigFile(); + if (config != null) { + lastModified = config.lastModified(); + } else { + return; + } + logger.info("Start the dynamic loading configuration service"); + reloadExecutor.scheduleWithFixedDelay(() -> { + try { + run(); + } catch (Exception e) { + logger.error("Exception caught when reloading configuration", e); + } + }, 100, 10, TimeUnit.SECONDS); } } - public void start() { - WatchService watchService; - Path path; - String confFileName; - try { - logger.info("Start the dynamic loading configuration service"); - String confFile; - if (isNoneBlank(parameter.getShellConfFileName())) { - confFile = parameter.getShellConfFileName(); - } else { - confFile = Constant.TESTNET_CONF; - //logger.warn("Configuration path is required!"); - //return; + public void run() { + File config = getConfigFile(); + if (config != null) { + long lastModifiedTime = config.lastModified(); + if (lastModifiedTime > lastModified) { + reload(); + lastModified = lastModifiedTime; } - - File confDir = new File(confFile); - if (!confDir.exists()) { - logger.warn("Configuration path is required! No such file {}", confFile); - return; - } - confFileName = confDir.getName(); - if (confFile.contains(File.separator)) { - path = FileSystems.getDefault().getPath(confDir.getPath()).getParent(); - } else { - File directory = new File(""); - path = FileSystems.getDefault().getPath(directory.getAbsolutePath()); - } - - logger.debug("confDirString = {}", confDir); - watchService = FileSystems.getDefault().newWatchService(); - path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY); - logger.debug("watch path : {}", path.toString()); - } catch (Exception e) { - logger.error("Exception caught when register the watch key", e.getCause()); - return; } + } - while (!shutdown) { - try { - WatchKey wk = watchService.take(); - long changeCount = 0; - for (WatchEvent event : wk.pollEvents()) { - final Path changed = (Path)event.context(); - if (changed.endsWith(confFileName)) { - reload(); - logger.info("The configuration was modified and we reloaded it"); - } - changeCount++; - } - logger.debug("change count : {}", changeCount); + private File getConfigFile() { + String confFilePath; + if (isNoneBlank(parameter.getShellConfFileName())) { + confFilePath = parameter.getShellConfFileName(); + } else { + confFilePath = Constant.TESTNET_CONF; + } - boolean valid = wk.reset(); - if (!valid) { - path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY); - } - } catch (InterruptedException e) { - logger.warn("WatchService was interrupted"); - Thread.currentThread().interrupt(); - break; - } catch (IOException e) { - logger.error("Exception caught when register the watch key", e.getCause()); - break; - } + File confFile = new File(confFilePath); + if (!confFile.exists()) { + logger.warn("Configuration path is required! No such file {}", confFile); + return null; } + return confFile; } public void reload() { @@ -112,58 +85,30 @@ public void reload() { } private void updateActiveNodes(Config config) { - if (parameter.isWitness() || parameter.isFastForward()) { - return; - } - - List lastActiveNodes = parameter.getActiveNodes(); List newActiveNodes = Args.getInetSocketAddress(config, Constant.NODE_ACTIVE); parameter.setActiveNodes(newActiveNodes); - parameter.getActiveNodes().forEach(n -> { - if (!lastActiveNodes.contains(n)) { - TronNetService.getP2pConfig().getActiveNodes().add(n); - if (!TronNetService.getP2pConfig().getTrustNodes().contains(n.getAddress())) { - TronNetService.getP2pConfig().getTrustNodes().add(n.getAddress()); - } - } - }); - - lastActiveNodes.forEach(ln -> { - if (!parameter.getActiveNodes().contains(ln)) { - TronNetService.getP2pConfig().getActiveNodes().remove(ln); - TronNetService.getP2pConfig().getTrustNodes().remove(ln.getAddress()); - } - }); + List activeNodes = TronNetService.getP2pConfig().getActiveNodes(); + activeNodes.clear(); + activeNodes.addAll(newActiveNodes); logger.debug("p2p active nodes : {}", TronNetService.getP2pConfig().getActiveNodes().toString()); } private void updateTrustNodes(Config config) { - if (parameter.isWitness() || parameter.isFastForward()) { - return; - } - - List lastPassiveNodes = parameter.getPassiveNodes(); List newPassiveNodes = Args.getInetAddress(config, Constant.NODE_PASSIVE); parameter.setPassiveNodes(newPassiveNodes); - parameter.getPassiveNodes().forEach(n -> { - if (!lastPassiveNodes.contains(n) - || !TronNetService.getP2pConfig().getTrustNodes().contains(n)) { - TronNetService.getP2pConfig().getTrustNodes().add(n); - } - }); - - lastPassiveNodes.forEach(ln -> { - if (!parameter.getPassiveNodes().contains(ln)) { - TronNetService.getP2pConfig().getTrustNodes().remove(ln); - } - }); - logger.debug("p2p trust nodes : {}", TronNetService.getP2pConfig().getTrustNodes().toString()); + List trustNodes = TronNetService.getP2pConfig().getTrustNodes(); + trustNodes.clear(); + trustNodes.addAll(newPassiveNodes); + parameter.getActiveNodes().forEach(n -> trustNodes.add(n.getAddress())); + parameter.getFastForwardNodes().forEach(f -> trustNodes.add(f.getAddress())); + logger.debug("p2p trust nodes : {}", + TronNetService.getP2pConfig().getTrustNodes().toString()); } public void close() { - logger.info("Closing watchService ..."); - shutdown = true; + logger.info("Closing the dynamic loading configuration service ..."); + reloadExecutor.shutdown(); } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java index c544a545e16..0dcb755894f 100644 --- a/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java @@ -1,5 +1,6 @@ package org.tron.core.config.args; +import java.io.File; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -10,10 +11,8 @@ import org.tron.common.utils.ReflectUtils; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; -import org.tron.core.net.TronNetService; -import org.tron.p2p.P2pConfig; - -import java.io.File; +//import org.tron.core.net.TronNetService; +//import org.tron.p2p.P2pConfig; public class DynamicArgsTest { protected TronApplicationContext context; @@ -45,11 +44,13 @@ public void get() { @Test public void start() { - dynamicArgs.start(); - TronNetService tronNetService = context.getBean(TronNetService.class); - ReflectUtils.setFieldValue(tronNetService, "p2pConfig", new P2pConfig()); - dynamicArgs.reload(); + dynamicArgs.init(); + Assert.assertEquals(0, (long) ReflectUtils.getFieldObject(dynamicArgs, "lastModified")); + + dynamicArgs.run(); +// TronNetService tronNetService = context.getBean(TronNetService.class); +// ReflectUtils.setFieldValue(tronNetService, "p2pConfig", new P2pConfig()); +// dynamicArgs.reload(); dynamicArgs.close(); - Assert.assertTrue((boolean)ReflectUtils.getFieldObject(dynamicArgs, "shutdown")); } } From 06b814e67ecd1b5943714074ee1136191089a8b9 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 29 Mar 2023 13:13:45 +0800 Subject: [PATCH 0684/1197] fix(net):don't start program if some dns patameter is empty --- .../java/org/tron/core/config/args/Args.java | 42 +++++++-------- .../test/java/org/tron/core/net/NodeTest.java | 6 ++- framework/src/test/resources/config-test.conf | 54 +++++++++++++++++++ 3 files changed, 79 insertions(+), 23 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index af4fca636ad..b39770980ea 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1315,11 +1315,11 @@ public static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Confi } if (publishConfig.isDnsPublishEnable()) { - if (config.hasPath(Constant.NODE_DNS_DOMAIN)) { + if (config.hasPath(Constant.NODE_DNS_DOMAIN) && StringUtils.isNotEmpty( + config.getString(Constant.NODE_DNS_DOMAIN))) { publishConfig.setDnsDomain(config.getString(Constant.NODE_DNS_DOMAIN)); } else { logEmptyError(Constant.NODE_DNS_DOMAIN); - return null; } if (config.hasPath(Constant.NODE_DNS_CHANGE_THRESHOLD)) { @@ -1341,11 +1341,11 @@ public static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Confi } } - if (config.hasPath(Constant.NODE_DNS_PRIVATE)) { + if (config.hasPath(Constant.NODE_DNS_PRIVATE) && StringUtils.isNotEmpty( + config.getString(Constant.NODE_DNS_PRIVATE))) { publishConfig.setDnsPrivate(config.getString(Constant.NODE_DNS_PRIVATE)); } else { logEmptyError(Constant.NODE_DNS_PRIVATE); - return null; } if (config.hasPath(Constant.NODE_DNS_KNOWN_URLS)) { @@ -1357,11 +1357,12 @@ public static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Confi getInetSocketAddress(config, Constant.NODE_DNS_STATIC_NODES, false)); } - if (config.hasPath(Constant.NODE_DNS_SERVER_TYPE)) { + if (config.hasPath(Constant.NODE_DNS_SERVER_TYPE) && StringUtils.isNotEmpty( + config.getString(Constant.NODE_DNS_SERVER_TYPE))) { String serverType = config.getString(Constant.NODE_DNS_SERVER_TYPE); if (!"aws".equalsIgnoreCase(serverType) && !"aliyun".equalsIgnoreCase(serverType)) { - logger.error("Check {}, must be aws or aliyun", Constant.NODE_DNS_SERVER_TYPE); - return null; + throw new IllegalArgumentException( + String.format("Check %s, must be aws or aliyun", Constant.NODE_DNS_SERVER_TYPE)); } if ("aws".equalsIgnoreCase(serverType)) { publishConfig.setDnsType(DnsType.AwsRoute53); @@ -1370,38 +1371,37 @@ public static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Confi } } else { logEmptyError(Constant.NODE_DNS_SERVER_TYPE); - return null; } - if (config.hasPath(Constant.NODE_DNS_ACCESS_KEY_ID)) { + if (config.hasPath(Constant.NODE_DNS_ACCESS_KEY_ID) && StringUtils.isNotEmpty( + config.getString(Constant.NODE_DNS_ACCESS_KEY_ID))) { publishConfig.setAccessKeyId(config.getString(Constant.NODE_DNS_ACCESS_KEY_ID)); } else { logEmptyError(Constant.NODE_DNS_ACCESS_KEY_ID); - return null; } - if (config.hasPath(Constant.NODE_DNS_ACCESS_KEY_SECRET)) { + if (config.hasPath(Constant.NODE_DNS_ACCESS_KEY_SECRET) && StringUtils.isNotEmpty( + config.getString(Constant.NODE_DNS_ACCESS_KEY_SECRET))) { publishConfig.setAccessKeySecret(config.getString(Constant.NODE_DNS_ACCESS_KEY_SECRET)); } else { logEmptyError(Constant.NODE_DNS_ACCESS_KEY_SECRET); - return null; } if (publishConfig.getDnsType() == DnsType.AwsRoute53) { - if (!config.hasPath(Constant.NODE_DNS_AWS_REGION)) { - logEmptyError(Constant.NODE_DNS_AWS_REGION); - return null; - } else { + if (config.hasPath(Constant.NODE_DNS_AWS_REGION) && StringUtils.isNotEmpty( + config.getString(Constant.NODE_DNS_AWS_REGION))) { publishConfig.setAwsRegion(config.getString(Constant.NODE_DNS_AWS_REGION)); + } else { + logEmptyError(Constant.NODE_DNS_AWS_REGION); } if (config.hasPath(Constant.NODE_DNS_AWS_HOST_ZONE_ID)) { publishConfig.setAwsHostZoneId(config.getString(Constant.NODE_DNS_AWS_HOST_ZONE_ID)); } } else { - if (!config.hasPath(Constant.NODE_DNS_ALIYUN_ENDPOINT)) { - logEmptyError(Constant.NODE_DNS_ALIYUN_ENDPOINT); - return null; - } else { + if (config.hasPath(Constant.NODE_DNS_ALIYUN_ENDPOINT) && StringUtils.isNotEmpty( + config.getString(Constant.NODE_DNS_ALIYUN_ENDPOINT))) { publishConfig.setAliDnsEndpoint(config.getString(Constant.NODE_DNS_ALIYUN_ENDPOINT)); + } else { + logEmptyError(Constant.NODE_DNS_ALIYUN_ENDPOINT); } } } @@ -1409,7 +1409,7 @@ public static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Confi } private static void logEmptyError(String arg) { - logger.error("Check {}, must not be null", arg); + throw new IllegalArgumentException(String.format("Check %s, must not be null or empty", arg)); } private static TriggerConfig createTriggerConfig(ConfigObject triggerObject) { diff --git a/framework/src/test/java/org/tron/core/net/NodeTest.java b/framework/src/test/java/org/tron/core/net/NodeTest.java index ac01a46dbc8..421b93f589a 100644 --- a/framework/src/test/java/org/tron/core/net/NodeTest.java +++ b/framework/src/test/java/org/tron/core/net/NodeTest.java @@ -15,6 +15,7 @@ import org.tron.core.config.Configuration; import org.tron.core.config.args.Args; import org.tron.p2p.discover.Node; +import org.tron.p2p.dns.update.DnsType; import org.tron.p2p.dns.update.PublishConfig; import org.tron.p2p.utils.NetUtil; import org.tron.protos.Discover.Endpoint; @@ -79,7 +80,8 @@ public void testEndpointFromNode() { public void testPublishConfig() { Config config = Configuration.getByFileName(Constant.TEST_CONF, Constant.TEST_CONF); PublishConfig publishConfig = Args.loadDnsPublishConfig(config); - assert publishConfig != null; - Assert.assertFalse(publishConfig.isDnsPublishEnable()); + Assert.assertTrue(publishConfig.isDnsPublishEnable()); + Assert.assertEquals(5, publishConfig.getMaxMergeSize()); + Assert.assertEquals(DnsType.AwsRoute53, publishConfig.getDnsType()); } } diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index 2cd108bf966..d61e0eead64 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -105,6 +105,60 @@ node { solidityPort = 8091 } + enableIpv6 = false + + dns { + # dns urls to get nodes, url format tree://{pubkey}@{domain}, default empty + treeUrls = [ + #"tree://APFGGTFOBVE2ZNAB3CSMNNX6RRK3ODIRLP2AA5U4YFAA6MSYZUYTQ@nodes1.example.org", + ] + + # enable or disable dns publish, default false + publish = true + + # dns domain to publish nodes, required if publish is true + dnsDomain = "nodes1.example.org" + + # dns private key used to publish, required if publish is true, hex string of length 64 + dnsPrivate = "b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291" + + # known dns urls to publish if publish is true, url format tree://{pubkey}@{domain}, default empty + knownUrls = [ + #"tree://APFGGTFOBVE2ZNAB3CSMNNX6RRK3ODIRLP2AA5U4YFAA6MSYZUYTQ@nodes2.example.org", + ] + + staticNodes = [ + # static nodes to published on dns + # Sample entries: + # "ip:port", + # "ip:port" + ] + + # merge several nodes into a leaf of tree, should be 1~5 + maxMergeSize = 5 + + # only nodes change percent is bigger then the threshold, we update data on dns + changeThreshold = 0.1 + + # dns server to publish, required if publish is true, only aws or aliyun is support + serverType = "aws" + + # access key id of aws or aliyun api, required if publish is true, string + accessKeyId = "your-key-id" + + # access key secret of aws or aliyun api, required if publish is true, string + accessKeySecret = "your-key-secret" + + # if publish is true and serverType is aliyun, it's endpoint of aws dns server, string + aliyunDnsEndpoint = "alidns.aliyuncs.com" + + # if publish is true and serverType is aws, it's region of aws api, such as "eu-south-1", string + awsRegion = "us-east-1" + + # if publish is true and server-type is aws, it's host zone id of aws's domain, string + awsHostZoneId = "your-host-zone-id" + } + rpc { port = 50051 From cf3dfd254b323931cb792d32fba9581ac9a5e2f9 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 29 Mar 2023 13:20:05 +0800 Subject: [PATCH 0685/1197] fix(net):revert log level of net to info --- framework/src/main/resources/logback.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/resources/logback.xml b/framework/src/main/resources/logback.xml index 62accd7f2c5..39c7f463172 100644 --- a/framework/src/main/resources/logback.xml +++ b/framework/src/main/resources/logback.xml @@ -75,7 +75,7 @@ - + From b1d52552ebc9f8b9ab18e69a9e060afcb41b5639 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 29 Mar 2023 14:48:03 +0800 Subject: [PATCH 0686/1197] fix(net): optimize EffectiveCheckService --- .../java/org/tron/core/config/args/Args.java | 11 ++------ .../org/tron/core/net/TronNetService.java | 4 +-- .../tron/core/net/peer/PeerConnection.java | 10 ------- .../effective/EffectiveCheckService.java | 26 +++++++++---------- .../service/handshake/HandshakeService.java | 13 ++++++++++ 5 files changed, 28 insertions(+), 36 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 60c87f737ff..a746e96c97e 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1202,9 +1202,6 @@ private static List getInetSocketAddress( List list = config.getStringList(path); for (String configString : list) { InetSocketAddress inetSocketAddress = NetUtil.parseInetSocketAddress(configString); - if (inetSocketAddress == null) { - continue; - } if (filter) { String ip = inetSocketAddress.getAddress().getHostAddress(); int port = inetSocketAddress.getPort(); @@ -1230,9 +1227,7 @@ private static List getInetAddress( List list = config.getStringList(path); for (String configString : list) { InetSocketAddress inetSocketAddress = NetUtil.parseInetSocketAddress(configString); - if (inetSocketAddress != null) { - ret.add(inetSocketAddress.getAddress()); - } + ret.add(inetSocketAddress.getAddress()); } return ret; } @@ -1301,9 +1296,7 @@ private static List loadSeeds(final com.typesafe.config.Confi if (PARAMETER.seedNodes != null && !PARAMETER.seedNodes.isEmpty()) { for (String s : PARAMETER.seedNodes) { InetSocketAddress inetSocketAddress = NetUtil.parseInetSocketAddress(s); - if (inetSocketAddress != null) { - inetSocketAddressList.add(inetSocketAddress); - } + inetSocketAddressList.add(inetSocketAddress); } } else { inetSocketAddressList = getInetSocketAddress(config, Constant.SEED_NODE_IP_LIST, false); diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index fab50cd500d..89767e31827 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -150,9 +150,7 @@ public static boolean hasIpv4Stack(Set ipSet) { private P2pConfig getConfig() { List seeds = parameter.getSeedNode().getAddressList(); seeds.addAll(nodePersistService.dbRead()); - for (InetSocketAddress inetSocketAddress : seeds) { - logger.debug("Seed InetSocketAddress: {}", inetSocketAddress); - } + logger.debug("Seed InetSocketAddress: {}", seeds); P2pConfig config = new P2pConfig(); config.getSeedNodes().addAll(seeds); config.getActiveNodes().addAll(parameter.getActiveNodes()); diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index c6bdb413f68..1bd1ce20595 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -47,7 +47,6 @@ import org.tron.core.net.service.sync.SyncService; import org.tron.p2p.connection.Channel; import org.tron.protos.Protocol; -import org.tron.protos.Protocol.ReasonCode; @Slf4j(topic = "net") @Component @@ -90,9 +89,6 @@ public class PeerConnection { @Autowired private AdvService advService; - @Autowired - private EffectiveCheckService effectiveCheckService; - @Setter @Getter private HelloMessage helloMessageReceive; @@ -187,12 +183,6 @@ public void onConnect() { needSyncFromUs = false; syncService.startSync(this); } else { - if (getInetSocketAddress().equals(effectiveCheckService.getCur())) { - logger.info("Peer's head block {} is below than we, peer->{}, me->{}", - getInetSocketAddress(), peerHeadBlockNum, headBlockNum); - disconnect(ReasonCode.BELOW_THAN_ME); - return; - } needSyncFromPeer = false; if (peerHeadBlockNum == headBlockNum) { needSyncFromUs = false; diff --git a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java index 057480905f2..b5792507d06 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java @@ -38,9 +38,10 @@ public class EffectiveCheckService { .maximumSize(10000) .expireAfterWrite(20, TimeUnit.MINUTES).build(); @Getter - private InetSocketAddress cur; + private volatile InetSocketAddress cur; private final AtomicInteger count = new AtomicInteger(0); private ScheduledExecutorService executor = null; + private long MAX_HANDSHAKE_TIME = 60_000; public void init() { if (isEffectiveCheck) { @@ -52,7 +53,7 @@ public void init() { } catch (Exception e) { logger.error("Check effective connection processing failed", e); } - }, 60 , 5, TimeUnit.SECONDS); + }, 60, 5, TimeUnit.SECONDS); } else { logger.info("EffectiveCheckService is disabled"); } @@ -93,18 +94,15 @@ private void findEffectiveNode() { } if (cur != null) { - if (tronNetDelegate.getActivePeer().stream() - .anyMatch(p -> p.getInetSocketAddress().equals(cur))) { - // we encounter no effective connection again, so we disconnect with last used node - logger.info("Disconnect with {}", cur); - tronNetDelegate.getActivePeer().forEach(p -> { - if (p.getInetSocketAddress().equals(cur)) { - p.disconnect(ReasonCode.BELOW_THAN_ME); - } - }); - } else { - logger.info("Thread is running"); - } + tronNetDelegate.getActivePeer().forEach(p -> { + if (p.getInetSocketAddress().equals(cur) + && System.currentTimeMillis() - p.getChannel().getStartTime() >= MAX_HANDSHAKE_TIME) { + // we encounter no effective connection again, so we disconnect with last used node + logger.info("Disconnect with {}", cur); + p.disconnect(ReasonCode.BELOW_THAN_ME); + } + }); + logger.info("Thread is running"); return; } diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java index 6c9e53c3a98..aa6567d1cda 100644 --- a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -11,6 +11,7 @@ import org.tron.core.net.message.handshake.HelloMessage; import org.tron.core.net.peer.PeerConnection; import org.tron.core.net.peer.PeerManager; +import org.tron.core.net.service.effective.EffectiveCheckService; import org.tron.core.net.service.relay.RelayService; import org.tron.p2p.discover.Node; import org.tron.protos.Protocol.ReasonCode; @@ -22,6 +23,9 @@ public class HandshakeService { @Autowired private RelayService relayService; + @Autowired + private EffectiveCheckService effectiveCheckService; + @Autowired private ChainBaseManager chainBaseManager; @@ -98,6 +102,15 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { return; } + if (msg.getHeadBlockId().getNum() < chainBaseManager.getHeadBlockId().getNum() + && peer.getInetSocketAddress().equals(effectiveCheckService.getCur())) { + logger.info("Peer's head block {} is below than we, peer->{}, me->{}", + peer.getInetSocketAddress(), msg.getHeadBlockId().getNum(), + chainBaseManager.getHeadBlockId().getNum()); + peer.disconnect(ReasonCode.BELOW_THAN_ME); + return; + } + peer.setHelloMessageReceive(msg); peer.getChannel().updateAvgLatency( From 2fd5fbef5a9428a037640a43e29cc179d218a844 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 29 Mar 2023 14:59:13 +0800 Subject: [PATCH 0687/1197] feat(net): optimize sync block chain message check logic --- .../SyncBlockChainMsgHandler.java | 13 ++++- .../messagehandler/BlockMsgHandlerTest.java | 10 +++- .../SyncBlockChainMsgHandlerTest.java | 57 ++++++++++++++++++- 3 files changed, 71 insertions(+), 9 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java index 37d46f6a8f3..9027034ccc7 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java @@ -29,7 +29,10 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep SyncBlockChainMessage syncBlockChainMessage = (SyncBlockChainMessage) msg; - check(peer, syncBlockChainMessage); + if (!check(peer, syncBlockChainMessage)) { + peer.disconnect(Protocol.ReasonCode.BAD_PROTOCOL); + return; + } long remainNum = 0; @@ -53,7 +56,7 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep peer.sendMessage(new ChainInventoryMessage(blockIds, remainNum)); } - private void check(PeerConnection peer, SyncBlockChainMessage msg) throws P2pException { + private boolean check(PeerConnection peer, SyncBlockChainMessage msg) throws P2pException { List blockIds = msg.getBlockIds(); if (CollectionUtils.isEmpty(blockIds)) { throw new P2pException(TypeEnum.BAD_MESSAGE, "SyncBlockChain blockIds is empty"); @@ -61,7 +64,9 @@ private void check(PeerConnection peer, SyncBlockChainMessage msg) throws P2pExc BlockId firstId = blockIds.get(0); if (!tronNetDelegate.containBlockInMainChain(firstId)) { - throw new P2pException(TypeEnum.BAD_MESSAGE, "No first block:" + firstId.getString()); + logger.warn("Sync message from peer {} without the first block: {}", + peer.getInetSocketAddress(), firstId.getString()); + return false; } long headNum = tronNetDelegate.getHeadBlockId().getNum(); @@ -76,6 +81,8 @@ private void check(PeerConnection peer, SyncBlockChainMessage msg) throws P2pExc throw new P2pException(TypeEnum.BAD_MESSAGE, "lastSyncNum:" + lastSyncBlockId.getNum() + " gt lastNum:" + lastNum); } + + return true; } private LinkedList getLostBlockIds(List blockIds) throws P2pException { diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java index ff6203ee870..d4d53da1748 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java @@ -2,6 +2,7 @@ import com.google.common.collect.ImmutableList; import com.google.protobuf.ByteString; +import java.io.File; import java.lang.reflect.Field; import java.net.InetSocketAddress; import java.util.List; @@ -10,6 +11,7 @@ import org.junit.Before; import org.junit.Test; import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.FileUtil; import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; @@ -26,23 +28,24 @@ public class BlockMsgHandlerTest { - protected TronApplicationContext context; + private TronApplicationContext context; private BlockMsgHandler handler; private PeerConnection peer; + private String dbPath = "output-block-message-handler-test"; /** * init context. */ @Before public void init() throws Exception { - Args.setParam(new String[]{"--output-directory", "output-directory", "--debug"}, + Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); handler = context.getBean(BlockMsgHandler.class); peer = context.getBean(PeerConnection.class); Channel c1 = new Channel(); InetSocketAddress a1 = new InetSocketAddress("100.1.1.1", 100); - Field field = c1.getClass().getDeclaredField("inetAddress"); + Field field = c1.getClass().getDeclaredField("inetAddress"); field.setAccessible(true); field.set(c1, a1.getAddress()); peer.setChannel(c1); @@ -120,5 +123,6 @@ public void testProcessMessage() { public void destroy() { Args.clearParam(); context.destroy(); + FileUtil.deleteDir(new File(dbPath)); } } diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java index a0c37d246da..2dbad09c655 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java @@ -1,24 +1,75 @@ package org.tron.core.net.messagehandler; +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.InetSocketAddress; import java.util.ArrayList; +import java.util.List; +import org.junit.After; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.FileUtil; +import org.tron.core.Constant; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; import org.tron.core.exception.P2pException; import org.tron.core.net.message.sync.SyncBlockChainMessage; import org.tron.core.net.peer.PeerConnection; +import org.tron.p2p.connection.Channel; public class SyncBlockChainMsgHandlerTest { - private SyncBlockChainMsgHandler handler = new SyncBlockChainMsgHandler(); - private PeerConnection peer = new PeerConnection(); + private TronApplicationContext context; + private SyncBlockChainMsgHandler handler; + private PeerConnection peer; + private String dbPath = "output-sync-chain-test"; + + @Before + public void init() throws Exception { + Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, + Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + handler = context.getBean(SyncBlockChainMsgHandler.class); + peer = context.getBean(PeerConnection.class); + Channel c1 = new Channel(); + InetSocketAddress a1 = new InetSocketAddress("100.1.1.1", 100); + Field field = c1.getClass().getDeclaredField("inetSocketAddress"); + field.setAccessible(true); + field.set(c1, a1); + + field = c1.getClass().getDeclaredField("inetAddress"); + field.setAccessible(true); + field.set(c1, a1.getAddress()); + + peer.setChannel(c1); + } @Test - public void testProcessMessage() { + public void testProcessMessage() throws Exception { try { handler.processMessage(peer, new SyncBlockChainMessage(new ArrayList<>())); } catch (P2pException e) { Assert.assertTrue(e.getMessage().equals("SyncBlockChain blockIds is empty")); } + + List blockIds = new ArrayList<>(); + blockIds.add(new BlockCapsule.BlockId()); + SyncBlockChainMessage message = new SyncBlockChainMessage(blockIds); + Method method = handler.getClass().getDeclaredMethod( + "check", PeerConnection.class, SyncBlockChainMessage.class); + method.setAccessible(true); + boolean f = (boolean)method.invoke(handler, peer, message); + Assert.assertTrue(!f); + } + + @After + public void destroy() { + Args.clearParam(); + FileUtil.deleteDir(new File(dbPath)); } } From 272a16a286c0090cac0665ba5086279ad1179cac Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 29 Mar 2023 16:20:37 +0800 Subject: [PATCH 0688/1197] fix(net): update libp2p to test-v0.2.20 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index a09a1ac9159..5c70edf0b65 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-callback-v4' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.20' compile project(":protocol") } From 83ed16c03b2ff1655c96204c882be14da27d99fe Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Wed, 29 Mar 2023 16:21:34 +0800 Subject: [PATCH 0689/1197] feat(config):add test case --- .../common/parameter/CommonParameter.java | 4 +++ .../src/main/java/org/tron/core/Constant.java | 3 ++- .../java/org/tron/core/config/args/Args.java | 10 +++++++ .../tron/core/config/args/DynamicArgs.java | 10 +++---- .../core/config/args/DynamicArgsTest.java | 27 ++++++++++++++----- framework/src/test/resources/config-test.conf | 4 ++- 6 files changed, 44 insertions(+), 14 deletions(-) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 9ff70a42a30..c878acd943e 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -618,6 +618,10 @@ public class CommonParameter { @Setter public boolean dynamicConfigEnable; + @Getter + @Setter + public long dynamicConfigCheckInterval; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 59d69bfecfd..7f572058218 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -344,5 +344,6 @@ public class Constant { public static final String BLOCK_CACHE_TIMEOUT = "node.blockCacheTimeout"; - public static final String DYNAMIC_CONFIG_ENABLE = "dynamicConfigEnable"; + public static final String DYNAMIC_CONFIG_ENABLE = "node.dynamicConfig.enable"; + public static final String DYNAMIC_CONFIG_CHECK_INTERVAL = "node.dynamicConfig.checkInterval"; } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 78be66c6576..e18984ed7f7 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -223,6 +223,7 @@ public static void clearParam() { PARAMETER.memoFee = 0; PARAMETER.p2pDisable = false; PARAMETER.dynamicConfigEnable = false; + PARAMETER.dynamicConfigCheckInterval = 600; } /** @@ -1126,6 +1127,15 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.dynamicConfigEnable = config.hasPath(Constant.DYNAMIC_CONFIG_ENABLE) && config.getBoolean(Constant.DYNAMIC_CONFIG_ENABLE); + if (config.hasPath(Constant.DYNAMIC_CONFIG_CHECK_INTERVAL)) { + PARAMETER.dynamicConfigCheckInterval + = config.getLong(Constant.DYNAMIC_CONFIG_CHECK_INTERVAL); + if (PARAMETER.dynamicConfigCheckInterval <= 0) { + PARAMETER.dynamicConfigCheckInterval = 600; + } + } else { + PARAMETER.dynamicConfigCheckInterval = 600; + } logConfig(); } diff --git a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java index c0f08f61148..4834bb6bdff 100644 --- a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java +++ b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java @@ -31,19 +31,19 @@ public class DynamicArgs { public void init() { if (parameter.isDynamicConfigEnable()) { File config = getConfigFile(); - if (config != null) { - lastModified = config.lastModified(); - } else { + if (config == null) { return; } + lastModified = config.lastModified(); logger.info("Start the dynamic loading configuration service"); + long checkInterval = parameter.getDynamicConfigCheckInterval(); reloadExecutor.scheduleWithFixedDelay(() -> { try { run(); } catch (Exception e) { logger.error("Exception caught when reloading configuration", e); } - }, 100, 10, TimeUnit.SECONDS); + }, 10, checkInterval, TimeUnit.SECONDS); } } @@ -108,7 +108,7 @@ private void updateTrustNodes(Config config) { } public void close() { - logger.info("Closing the dynamic loading configuration service ..."); + logger.info("Closing the dynamic loading configuration service"); reloadExecutor.shutdown(); } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java index 0dcb755894f..09f527fdd08 100644 --- a/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java @@ -11,8 +11,8 @@ import org.tron.common.utils.ReflectUtils; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; -//import org.tron.core.net.TronNetService; -//import org.tron.p2p.P2pConfig; +import org.tron.core.net.TronNetService; +import org.tron.p2p.P2pConfig; public class DynamicArgsTest { protected TronApplicationContext context; @@ -39,7 +39,7 @@ public void destroy() { public void get() { CommonParameter parameter = Args.getInstance(); Assert.assertFalse(parameter.isDynamicConfigEnable()); - + Assert.assertEquals(600, parameter.getDynamicConfigCheckInterval()); } @Test @@ -47,10 +47,23 @@ public void start() { dynamicArgs.init(); Assert.assertEquals(0, (long) ReflectUtils.getFieldObject(dynamicArgs, "lastModified")); - dynamicArgs.run(); -// TronNetService tronNetService = context.getBean(TronNetService.class); -// ReflectUtils.setFieldValue(tronNetService, "p2pConfig", new P2pConfig()); -// dynamicArgs.reload(); + TronNetService tronNetService = context.getBean(TronNetService.class); + ReflectUtils.setFieldValue(tronNetService, "p2pConfig", new P2pConfig()); + File config = new File(Constant.TESTNET_CONF); + if (!config.exists()) { + try { + config.createNewFile(); + } catch (Exception e) { + return; + } + dynamicArgs.run(); + try { + config.delete(); + } catch (Exception e) { + return; + } + } + dynamicArgs.close(); } } diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index 2cd108bf966..2dcb7daa34a 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -286,4 +286,6 @@ vm = { } committee = { allowCreationOfContracts = 1 //mainnet:0 (reset by committee),test:1 -} \ No newline at end of file +} + +node.dynamicConfig.checkInterval = 0 \ No newline at end of file From 1f61d7ff9f9d8fa850cfc6a3b27a96fccf3107b4 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 29 Mar 2023 16:23:25 +0800 Subject: [PATCH 0690/1197] fix(net): revert PeerConnection --- .../src/main/java/org/tron/core/net/peer/PeerConnection.java | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index 1bd1ce20595..7e417bd24f4 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -40,7 +40,6 @@ import org.tron.core.net.message.keepalive.PingMessage; import org.tron.core.net.message.keepalive.PongMessage; import org.tron.core.net.service.adv.AdvService; -import org.tron.core.net.service.effective.EffectiveCheckService; import org.tron.core.net.service.statistics.NodeStatistics; import org.tron.core.net.service.statistics.PeerStatistics; import org.tron.core.net.service.statistics.TronStatsManager; From d0adfa06be9f89480e7f059682ea10ccebe645c5 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Wed, 29 Mar 2023 16:30:58 +0800 Subject: [PATCH 0691/1197] feat(config):fix merge issue --- .../src/main/java/org/tron/core/config/args/DynamicArgs.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java index 4834bb6bdff..5e2725c8322 100644 --- a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java +++ b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java @@ -86,7 +86,7 @@ public void reload() { private void updateActiveNodes(Config config) { List newActiveNodes = - Args.getInetSocketAddress(config, Constant.NODE_ACTIVE); + Args.getInetSocketAddress(config, Constant.NODE_ACTIVE, true); parameter.setActiveNodes(newActiveNodes); List activeNodes = TronNetService.getP2pConfig().getActiveNodes(); activeNodes.clear(); From 88565009844905ad6c727ff2a0afa7408b53c28e Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Wed, 29 Mar 2023 17:53:18 +0800 Subject: [PATCH 0692/1197] feat(config):change libp2p version --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 6ce3c0bef41..5c70edf0b65 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.19' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.20' compile project(":protocol") } From a4aaa80ff4685c0fb9f947067894ae7e2a4158f7 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 29 Mar 2023 18:12:13 +0800 Subject: [PATCH 0693/1197] fix(net): add test case EffectiveCheckServiceTest --- .../effective/EffectiveCheckService.java | 9 ++-- .../services/EffectiveCheckServiceTest.java | 44 +++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java diff --git a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java index b5792507d06..44fdc56f938 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java @@ -14,6 +14,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import lombok.Getter; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -38,15 +39,15 @@ public class EffectiveCheckService { .maximumSize(10000) .expireAfterWrite(20, TimeUnit.MINUTES).build(); @Getter + @Setter private volatile InetSocketAddress cur; private final AtomicInteger count = new AtomicInteger(0); - private ScheduledExecutorService executor = null; + private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor( + new ThreadFactoryBuilder().setNameFormat("effective-thread-%d").build()); private long MAX_HANDSHAKE_TIME = 60_000; public void init() { if (isEffectiveCheck) { - executor = Executors.newSingleThreadScheduledExecutor( - new ThreadFactoryBuilder().setNameFormat("effective-thread-%d").build()); executor.scheduleWithFixedDelay(() -> { try { findEffectiveNode(); @@ -59,7 +60,7 @@ public void init() { } } - private void triggerNext() { + public void triggerNext() { try { executor.submit(this::findEffectiveNode); } catch (Exception e) { diff --git a/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java b/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java new file mode 100644 index 00000000000..315159cfea2 --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java @@ -0,0 +1,44 @@ +package org.tron.core.net.services; + +import java.io.File; +import java.net.InetSocketAddress; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.FileUtil; +import org.tron.core.Constant; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.net.service.effective.EffectiveCheckService; + +public class EffectiveCheckServiceTest { + + protected TronApplicationContext context; + private EffectiveCheckService service; + private String dbPath = "output-effective-service-test"; + + @Before + public void init() { + Args.setParam(new String[] {"--output-directory", dbPath, "--debug"}, + Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + service = context.getBean(EffectiveCheckService.class); + } + + @After + public void destroy() { + Args.clearParam(); + FileUtil.deleteDir(new File(dbPath)); + } + + @Test + public void testFind() { + service.triggerNext(); + Assert.assertNull(service.getCur()); + service.setCur(new InetSocketAddress("192.168.10.100", 12345)); + service.triggerNext(); + Assert.assertNotNull(service.getCur()); + } +} From 287aa7ae20cdbef07cd6b0406eafbb77039799d8 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 30 Mar 2023 01:04:45 +0800 Subject: [PATCH 0694/1197] fix(net): add test case for MessageStatistics --- .../service/statistics/MessageStatistics.java | 7 +- .../java/org/tron/core/net/MessageTest.java | 74 +++++++++++++++++++ 2 files changed, 78 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/statistics/MessageStatistics.java b/framework/src/main/java/org/tron/core/net/service/statistics/MessageStatistics.java index 6ed67026ada..787f6ef5de2 100644 --- a/framework/src/main/java/org/tron/core/net/service/statistics/MessageStatistics.java +++ b/framework/src/main/java/org/tron/core/net/service/statistics/MessageStatistics.java @@ -143,16 +143,17 @@ private void addTcpMessage(Message msg, boolean flag) { break; case TRX: if (flag) { - tronInMessage.add(); + tronInTrx.add(); } else { - tronOutMessage.add(); + tronOutTrx.add(); } break; case BLOCK: if (flag) { tronInBlock.add(); + } else { + tronOutBlock.add(); } - tronOutBlock.add(); break; default: break; diff --git a/framework/src/test/java/org/tron/core/net/MessageTest.java b/framework/src/test/java/org/tron/core/net/MessageTest.java index 0400d16b669..f9179868858 100644 --- a/framework/src/test/java/org/tron/core/net/MessageTest.java +++ b/framework/src/test/java/org/tron/core/net/MessageTest.java @@ -2,9 +2,11 @@ import org.junit.Assert; import org.junit.Test; +import org.tron.common.overlay.message.Message; import org.tron.core.exception.P2pException; import org.tron.core.net.message.MessageTypes; import org.tron.core.net.message.base.DisconnectMessage; +import org.tron.core.net.service.statistics.MessageStatistics; import org.tron.protos.Protocol.ReasonCode; public class MessageTest { @@ -35,4 +37,76 @@ public void test2() throws Exception { System.out.println("spend time : " + (endTime - startTime)); } + @Test + public void testMessageStatistics() { + MessageStatistics messageStatistics = new MessageStatistics(); + Message message1 = new Message(MessageTypes.P2P_HELLO.asByte(), null) { + @Override + public Class getAnswerMessage() { + return null; + } + }; + Message message2 = new Message(MessageTypes.P2P_PING.asByte(), null) { + @Override + public Class getAnswerMessage() { + return null; + } + }; + Message message3 = new Message(MessageTypes.P2P_PONG.asByte(), null) { + @Override + public Class getAnswerMessage() { + return null; + } + }; + Message message4 = new Message(MessageTypes.P2P_DISCONNECT.asByte(), null) { + @Override + public Class getAnswerMessage() { + return null; + } + }; + Message message5 = new Message(MessageTypes.SYNC_BLOCK_CHAIN.asByte(), null) { + @Override + public Class getAnswerMessage() { + return null; + } + }; + Message message6 = new Message(MessageTypes.BLOCK_CHAIN_INVENTORY.asByte(), null) { + @Override + public Class getAnswerMessage() { + return null; + } + }; + Message message7 = new Message(MessageTypes.TRX.asByte(), null) { + @Override + public Class getAnswerMessage() { + return null; + } + }; + Message message8 = new Message(MessageTypes.BLOCK.asByte(), null) { + @Override + public Class getAnswerMessage() { + return null; + } + }; + messageStatistics.addTcpInMessage(message1); + messageStatistics.addTcpOutMessage(message1); + messageStatistics.addTcpInMessage(message2); + messageStatistics.addTcpOutMessage(message2); + messageStatistics.addTcpInMessage(message3); + messageStatistics.addTcpOutMessage(message3); + messageStatistics.addTcpInMessage(message4); + messageStatistics.addTcpOutMessage(message4); + messageStatistics.addTcpInMessage(message5); + messageStatistics.addTcpOutMessage(message5); + messageStatistics.addTcpInMessage(message6); + messageStatistics.addTcpOutMessage(message6); + messageStatistics.addTcpInMessage(message7); + messageStatistics.addTcpOutMessage(message7); + messageStatistics.addTcpInMessage(message8); + messageStatistics.addTcpOutMessage(message8); + + Assert.assertEquals(8, messageStatistics.tronInMessage.getTotalCount()); + Assert.assertEquals(8, messageStatistics.tronOutMessage.getTotalCount()); + } + } From 74c8179ca154a8384f0154996bbe873622e6f188 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 30 Mar 2023 09:33:23 +0800 Subject: [PATCH 0695/1197] fix(net):add unit test for peer connection --- .../test/java/org/tron/core/net/services/AdvServiceTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java b/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java index a6189346ae5..556eec980ed 100644 --- a/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java @@ -85,6 +85,7 @@ private void testBroadcast() { try { peer = context.getBean(PeerConnection.class); + Assert.assertFalse(peer.isDisconnect()); p2pEventHandler = context.getBean(P2pEventHandlerImpl.class); List peers = Lists.newArrayList(); @@ -96,6 +97,9 @@ private void testBroadcast() { service.broadcast(msg); Item item = new Item(blockCapsule.getBlockId(), InventoryType.BLOCK); Assert.assertNotNull(service.getMessage(item)); + peer.checkAndPutAdvInvRequest(item, System.currentTimeMillis()); + boolean res = peer.checkAndPutAdvInvRequest(item, System.currentTimeMillis()); + Assert.assertFalse(res); } catch (NullPointerException e) { System.out.println(e); } From 1467908dc009b85601e694a466632dbbd819ef53 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 30 Mar 2023 10:11:12 +0800 Subject: [PATCH 0696/1197] feat(config):add unit test for DynamicArgs --- .../java/org/tron/core/config/args/DynamicArgs.java | 4 ++-- .../org/tron/core/config/args/DynamicArgsTest.java | 12 +++++++----- framework/src/test/resources/config-test.conf | 1 + 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java index 5e2725c8322..cbf167cb955 100644 --- a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java +++ b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java @@ -30,13 +30,13 @@ public class DynamicArgs { public void init() { if (parameter.isDynamicConfigEnable()) { + logger.info("Start the dynamic loading configuration service"); + long checkInterval = parameter.getDynamicConfigCheckInterval(); File config = getConfigFile(); if (config == null) { return; } lastModified = config.lastModified(); - logger.info("Start the dynamic loading configuration service"); - long checkInterval = parameter.getDynamicConfigCheckInterval(); reloadExecutor.scheduleWithFixedDelay(() -> { try { run(); diff --git a/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java index 09f527fdd08..2ca95239ad7 100644 --- a/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java @@ -36,14 +36,11 @@ public void destroy() { } @Test - public void get() { + public void start() { CommonParameter parameter = Args.getInstance(); - Assert.assertFalse(parameter.isDynamicConfigEnable()); + Assert.assertTrue(parameter.isDynamicConfigEnable()); Assert.assertEquals(600, parameter.getDynamicConfigCheckInterval()); - } - @Test - public void start() { dynamicArgs.init(); Assert.assertEquals(0, (long) ReflectUtils.getFieldObject(dynamicArgs, "lastModified")); @@ -63,6 +60,11 @@ public void start() { return; } } + try { + dynamicArgs.reload(); + } catch (Exception e) { + // no need to deal with + } dynamicArgs.close(); } diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index f800fb2486b..76e99c8d4a1 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -342,4 +342,5 @@ committee = { allowCreationOfContracts = 1 //mainnet:0 (reset by committee),test:1 } +node.dynamicConfig.enable = true node.dynamicConfig.checkInterval = 0 \ No newline at end of file From e0c8ba5e41fbbe7268d17024a0b4afcc5fbe7c2c Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 30 Mar 2023 10:15:01 +0800 Subject: [PATCH 0697/1197] feat(config):resolve code conflicts --- framework/src/main/java/org/tron/core/net/TronNetService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 95a3cc869c6..561c3cbae9e 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -149,8 +149,8 @@ private P2pConfig getConfig() { } P2pConfig config = new P2pConfig(); config.setSeedNodes(seeds); - config.getActiveNodes().addAll(parameter.getActiveNodes()); - config.getTrustNodes().addAll(parameter.getPassiveNodes()); + config.setActiveNodes(parameter.getActiveNodes()); + config.setTrustNodes(parameter.getPassiveNodes()); config.getActiveNodes().forEach(n -> config.getTrustNodes().add(n.getAddress())); parameter.getFastForwardNodes().forEach(f -> config.getTrustNodes().add(f.getAddress())); int maxConnections = parameter.getMaxConnections(); From c7cf0a8eda9ddc4cbd9bf0b96ad1e8eeb56468ce Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Thu, 30 Mar 2023 10:51:40 +0800 Subject: [PATCH 0698/1197] fix(freezeV2): optimize the query return of the interface --- framework/src/main/java/org/tron/core/Wallet.java | 11 +++++++++-- framework/src/test/java/org/tron/core/WalletTest.java | 11 ++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index ea47c2c686b..86429b65fe0 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -765,19 +765,26 @@ public DelegatedResourceList getDelegatedResourceV2( .createDbKeyV2(fromAddress.toByteArray(), toAddress.toByteArray(), false); DelegatedResourceCapsule unlockResource = chainBaseManager.getDelegatedResourceStore() .get(dbKey); - if (unlockResource != null) { + if (nonEmptyResource(unlockResource)) { builder.addDelegatedResource(unlockResource.getInstance()); } dbKey = DelegatedResourceCapsule .createDbKeyV2(fromAddress.toByteArray(), toAddress.toByteArray(), true); DelegatedResourceCapsule lockResource = chainBaseManager.getDelegatedResourceStore() .get(dbKey); - if (lockResource != null) { + if (nonEmptyResource(lockResource)) { builder.addDelegatedResource(lockResource.getInstance()); } return builder.build(); } + private boolean nonEmptyResource(DelegatedResourceCapsule resource) { + return Objects.nonNull(resource) && !(resource.getExpireTimeForBandwidth() == 0 + && resource.getExpireTimeForEnergy() == 0 + && resource.getFrozenBalanceForBandwidth() == 0 + && resource.getFrozenBalanceForEnergy() == 0); + } + public GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage getCanWithdrawUnfreezeAmount( ByteString ownerAddress, long timestamp) { GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage.Builder builder = diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 36a34edc295..1d8ae810dfd 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -728,7 +728,7 @@ private Any getLockedDelegateContractForBandwidth(String ownerAddress, String re .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiveAddress))) .setBalance(unfreezeBalance) - .setResource(Common.ResourceCode.BANDWIDTH) + .setResource(BANDWIDTH) .setLock(lock) .build()); } @@ -753,6 +753,11 @@ public void testGetDelegatedResourceV2() { ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); + Protocol.Account account = Protocol.Account.newBuilder() + .setAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))).build(); + wallet.getAccount(account); + wallet.getProposalList(); + wallet.getWitnessList(); Assert.assertEquals(1L, delegatedResourceList.getDelegatedResourceCount()); Assert.assertEquals(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), delegatedResourceList.getDelegatedResource(0).getFrom()); @@ -809,7 +814,7 @@ public void testGetCanDelegatedMaxSizeBandWidth() { GrpcAPI.CanDelegatedMaxSizeResponseMessage message = wallet.getCanDelegatedMaxSize( ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), - Common.ResourceCode.BANDWIDTH.getNumber()); + BANDWIDTH.getNumber()); Assert.assertEquals(initBalance - 280L, message.getMaxSize()); } @@ -832,7 +837,7 @@ private Any getContractForBandwidthV2(String ownerAddress, long unfreezeBalance) ByteString.copyFrom(ByteArray.fromHexString(ownerAddress)) ) .setUnfreezeBalance(unfreezeBalance) - .setResource(Common.ResourceCode.BANDWIDTH) + .setResource(BANDWIDTH) .build() ); } From c2dc4081b46fa6bc768d44b1536488db44a423c4 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 30 Mar 2023 12:02:39 +0800 Subject: [PATCH 0699/1197] feat(net): optimize processSyncBlock function logic --- .../main/java/org/tron/core/net/service/sync/SyncService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 5b8ea730e99..68f113afd9f 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -292,7 +292,7 @@ private void processSyncBlock(BlockCapsule block) { if (peer.getSyncBlockInProcess().remove(blockId)) { if (flag) { peer.setBlockBothHave(blockId); - if (peer.getSyncBlockToFetch().isEmpty()) { + if (peer.getSyncBlockToFetch().isEmpty() && !peer.isFetchAble()) { syncNext(peer); } } else { From 0ce3ad365ba400b2d61c7ca9a7a7b9257ab7b067 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 30 Mar 2023 13:10:21 +0800 Subject: [PATCH 0700/1197] fix(net): add test case for MessageTest --- .../java/org/tron/core/net/MessageTest.java | 19 +++++++++++++++++-- .../services/EffectiveCheckServiceTest.java | 18 +++++++++++++++--- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/framework/src/test/java/org/tron/core/net/MessageTest.java b/framework/src/test/java/org/tron/core/net/MessageTest.java index f9179868858..d27f37214c5 100644 --- a/framework/src/test/java/org/tron/core/net/MessageTest.java +++ b/framework/src/test/java/org/tron/core/net/MessageTest.java @@ -1,12 +1,17 @@ package org.tron.core.net; +import java.util.ArrayList; import org.junit.Assert; import org.junit.Test; import org.tron.common.overlay.message.Message; import org.tron.core.exception.P2pException; import org.tron.core.net.message.MessageTypes; +import org.tron.core.net.message.adv.FetchInvDataMessage; +import org.tron.core.net.message.adv.InventoryMessage; +import org.tron.core.net.message.adv.TransactionsMessage; import org.tron.core.net.message.base.DisconnectMessage; import org.tron.core.net.service.statistics.MessageStatistics; +import org.tron.protos.Protocol.Inventory.InventoryType; import org.tron.protos.Protocol.ReasonCode; public class MessageTest { @@ -88,6 +93,10 @@ public Class getAnswerMessage() { return null; } }; + InventoryMessage message9 = new InventoryMessage(new ArrayList<>(), InventoryType.TRX); + FetchInvDataMessage message10 = new FetchInvDataMessage(new ArrayList<>(), InventoryType.TRX); + TransactionsMessage message11 = new TransactionsMessage(new ArrayList<>()); + messageStatistics.addTcpInMessage(message1); messageStatistics.addTcpOutMessage(message1); messageStatistics.addTcpInMessage(message2); @@ -104,9 +113,15 @@ public Class getAnswerMessage() { messageStatistics.addTcpOutMessage(message7); messageStatistics.addTcpInMessage(message8); messageStatistics.addTcpOutMessage(message8); + messageStatistics.addTcpInMessage(message9); + messageStatistics.addTcpOutMessage(message9); + messageStatistics.addTcpInMessage(message10); + messageStatistics.addTcpOutMessage(message10); + messageStatistics.addTcpInMessage(message11); + messageStatistics.addTcpOutMessage(message11); - Assert.assertEquals(8, messageStatistics.tronInMessage.getTotalCount()); - Assert.assertEquals(8, messageStatistics.tronOutMessage.getTotalCount()); + Assert.assertEquals(11, messageStatistics.tronInMessage.getTotalCount()); + Assert.assertEquals(11, messageStatistics.tronOutMessage.getTotalCount()); } } diff --git a/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java b/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java index 315159cfea2..eb517df23a7 100644 --- a/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java @@ -8,10 +8,13 @@ import org.junit.Test; import org.tron.common.application.TronApplicationContext; import org.tron.common.utils.FileUtil; +import org.tron.common.utils.ReflectUtils; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; +import org.tron.core.net.TronNetService; import org.tron.core.net.service.effective.EffectiveCheckService; +import org.tron.p2p.P2pConfig; public class EffectiveCheckServiceTest { @@ -35,10 +38,19 @@ public void destroy() { @Test public void testFind() { + TronNetService tronNetService = context.getBean(TronNetService.class); + P2pConfig p2pConfig = new P2pConfig(); + p2pConfig.setIp("127.0.0.1"); + p2pConfig.setPort(34567); + ReflectUtils.setFieldValue(tronNetService, "p2pConfig", p2pConfig); + TronNetService.getP2pService().start(p2pConfig); + service.triggerNext(); Assert.assertNull(service.getCur()); - service.setCur(new InetSocketAddress("192.168.10.100", 12345)); - service.triggerNext(); - Assert.assertNotNull(service.getCur()); + + ReflectUtils.invokeMethod(service, "resetCount"); + InetSocketAddress cur = new InetSocketAddress("192.168.0.1", 34567); + service.setCur(cur); + service.onDisconnect(cur); } } From 7bf49f799a3ed4d01e2c76b63e47a5994e162da0 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 28 Mar 2023 16:55:31 +0800 Subject: [PATCH 0701/1197] feat(api): remove insecure API --- .../org/tron/core/utils/TransactionUtil.java | 16 - .../src/main/java/org/tron/core/Wallet.java | 12 - .../org/tron/core/services/RpcApiService.java | 205 ------------- .../http/AddTransactionSignServlet.java | 51 ---- .../services/http/CreateAddressServlet.java | 76 ----- .../EasyTransferAssetByPrivateServlet.java | 75 ----- .../http/EasyTransferAssetServlet.java | 101 ------- .../http/EasyTransferByPrivateServlet.java | 72 ----- .../services/http/EasyTransferServlet.java | 82 ----- .../services/http/FullNodeHttpApiService.java | 27 -- .../services/http/GenerateAddressServlet.java | 43 --- .../http/HttpSelfFormatFieldName.java | 14 - .../services/http/TransactionSignServlet.java | 47 --- .../org/tron/core/services/http/Util.java | 7 - .../interfaceOnPBFT/RpcApiServiceOnPBFT.java | 18 -- .../RpcApiServiceOnSolidity.java | 19 -- .../ShieldedTransferActuatorTest.java | 37 +-- .../core/zksnark/ShieldedReceiveTest.java | 11 +- .../wallet/account/WalletTestAccount011.java | 7 - .../common/client/utils/HttpMethed.java | 124 +------- .../common/client/utils/TransactionUtils.java | 31 +- .../http/HttpTestEasyAccount001.java | 281 ------------------ protocol/src/main/protos/api/api.proto | 114 ------- protocol/src/main/protos/core/Tron.proto | 5 - 24 files changed, 46 insertions(+), 1429 deletions(-) delete mode 100644 framework/src/main/java/org/tron/core/services/http/AddTransactionSignServlet.java delete mode 100644 framework/src/main/java/org/tron/core/services/http/CreateAddressServlet.java delete mode 100644 framework/src/main/java/org/tron/core/services/http/EasyTransferAssetByPrivateServlet.java delete mode 100644 framework/src/main/java/org/tron/core/services/http/EasyTransferAssetServlet.java delete mode 100644 framework/src/main/java/org/tron/core/services/http/EasyTransferByPrivateServlet.java delete mode 100644 framework/src/main/java/org/tron/core/services/http/EasyTransferServlet.java delete mode 100644 framework/src/main/java/org/tron/core/services/http/GenerateAddressServlet.java delete mode 100644 framework/src/main/java/org/tron/core/services/http/TransactionSignServlet.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestEasyAccount001.java diff --git a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java index 496af641cde..e5cffa49790 100644 --- a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java @@ -49,7 +49,6 @@ import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract; import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionSign; import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; import org.tron.protos.Protocol.Transaction.Contract.ContractType; @@ -184,21 +183,6 @@ public static String makeUpperCamelMethod(String originName) { .replace("_", ""); } - public static TransactionCapsule getTransactionSign(TransactionSign transactionSign) { - byte[] privateKey = transactionSign.getPrivateKey().toByteArray(); - TransactionCapsule trx = new TransactionCapsule(transactionSign.getTransaction()); - trx.sign(privateKey); - return trx; - } - - public TransactionCapsule addSign(TransactionSign transactionSign) - throws PermissionException, SignatureException, SignatureFormatException { - byte[] privateKey = transactionSign.getPrivateKey().toByteArray(); - TransactionCapsule trx = new TransactionCapsule(transactionSign.getTransaction()); - trx.addSign(privateKey, chainBaseManager.getAccountStore()); - return trx; - } - public TransactionSignWeight getTransactionSignWeight(Transaction trx) { TransactionSignWeight.Builder tswBuilder = TransactionSignWeight.newBuilder(); TransactionExtention.Builder trxExBuilder = TransactionExtention.newBuilder(); diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 86429b65fe0..8fd966384e3 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -648,18 +648,6 @@ public TransactionApprovedList getTransactionApprovedList(Transaction trx) { return tswBuilder.build(); } - public byte[] pass2Key(byte[] passPhrase) { - return Sha256Hash.hash(CommonParameter - .getInstance().isECKeyCryptoEngine(), passPhrase); - } - - public byte[] createAddress(byte[] passPhrase) { - byte[] privateKey = pass2Key(passPhrase); - SignInterface ecKey = SignUtils.fromPrivate(privateKey, - Args.getInstance().isECKeyCryptoEngine()); - return ecKey.getAddress(); - } - public Block getNowBlock() { List blockList = chainBaseManager.getBlockStore().getBlockByLatestNum(1); if (CollectionUtils.isEmpty(blockList)) { diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index a81be8f7728..1f767eeb237 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -16,15 +16,12 @@ import java.util.concurrent.TimeUnit; import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.codec.binary.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.api.DatabaseGrpc.DatabaseImplBase; import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.AccountNetMessage; import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.Address; -import org.tron.api.GrpcAPI.AddressPrKeyPairMessage; import org.tron.api.GrpcAPI.AssetIssueList; import org.tron.api.GrpcAPI.BlockExtention; import org.tron.api.GrpcAPI.BlockLimit; @@ -39,11 +36,6 @@ import org.tron.api.GrpcAPI.DelegatedResourceList; import org.tron.api.GrpcAPI.DelegatedResourceMessage; import org.tron.api.GrpcAPI.DiversifierMessage; -import org.tron.api.GrpcAPI.EasyTransferAssetByPrivateMessage; -import org.tron.api.GrpcAPI.EasyTransferAssetMessage; -import org.tron.api.GrpcAPI.EasyTransferByPrivateMessage; -import org.tron.api.GrpcAPI.EasyTransferMessage; -import org.tron.api.GrpcAPI.EasyTransferResponse; import org.tron.api.GrpcAPI.EmptyMessage; import org.tron.api.GrpcAPI.EstimateEnergyMessage; import org.tron.api.GrpcAPI.ExchangeList; @@ -52,7 +44,6 @@ import org.tron.api.GrpcAPI.IncomingViewingKeyMessage; import org.tron.api.GrpcAPI.IvkDecryptTRC20Parameters; import org.tron.api.GrpcAPI.NfTRC20Parameters; -import org.tron.api.GrpcAPI.Node; import org.tron.api.GrpcAPI.NodeList; import org.tron.api.GrpcAPI.NoteParameters; import org.tron.api.GrpcAPI.NumberMessage; @@ -85,13 +76,10 @@ import org.tron.api.WalletGrpc.WalletImplBase; import org.tron.api.WalletSolidityGrpc.WalletSolidityImplBase; import org.tron.common.application.Service; -import org.tron.common.crypto.SignInterface; -import org.tron.common.crypto.SignUtils; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; import org.tron.core.ChainBaseManager; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; @@ -108,7 +96,6 @@ import org.tron.core.exception.VMIllegalException; import org.tron.core.exception.ZksnarkException; import org.tron.core.metrics.MetricsApiService; -import org.tron.core.net.TronNetService; import org.tron.core.services.filter.LiteFnQueryGrpcInterceptor; import org.tron.core.services.ratelimiter.RateLimiterInterceptor; import org.tron.core.services.ratelimiter.RpcApiAccessInterceptor; @@ -130,7 +117,6 @@ import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.Protocol.TransactionSign; import org.tron.protos.contract.AccountContract.AccountCreateContract; import org.tron.protos.contract.AccountContract.AccountPermissionUpdateContract; import org.tron.protos.contract.AccountContract.AccountUpdateContract; @@ -726,12 +712,6 @@ public void getTransactionInfoById(BytesMessage request, responseObserver.onCompleted(); } - @Override - public void generateAddress(EmptyMessage request, - StreamObserver responseObserver) { - generateAddressCommon(request, responseObserver); - } - @Override public void getRewardInfo(BytesMessage request, StreamObserver responseObserver) { @@ -1145,55 +1125,6 @@ private void createTransactionExtention(Message request, ContractType contractTy responseObserver.onCompleted(); } - - @Override - public void getTransactionSign(TransactionSign req, - StreamObserver responseObserver) { - TransactionCapsule result = TransactionUtil.getTransactionSign(req); - responseObserver.onNext(result.getInstance()); - responseObserver.onCompleted(); - } - - @Override - public void getTransactionSign2(TransactionSign req, - StreamObserver responseObserver) { - TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); - Return.Builder retBuilder = Return.newBuilder(); - try { - TransactionCapsule trx = TransactionUtil.getTransactionSign(req); - trxExtBuilder.setTransaction(trx.getInstance()); - trxExtBuilder.setTxid(trx.getTransactionId().getByteString()); - retBuilder.setResult(true).setCode(response_code.SUCCESS); - } catch (Exception e) { - retBuilder.setResult(false).setCode(response_code.OTHER_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); - logger.info(EXCEPTION_CAUGHT + e.getMessage()); - } - trxExtBuilder.setResult(retBuilder); - responseObserver.onNext(trxExtBuilder.build()); - responseObserver.onCompleted(); - } - - @Override - public void addSign(TransactionSign req, - StreamObserver responseObserver) { - TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); - Return.Builder retBuilder = Return.newBuilder(); - try { - TransactionCapsule trx = transactionUtil.addSign(req); - trxExtBuilder.setTransaction(trx.getInstance()); - trxExtBuilder.setTxid(trx.getTransactionId().getByteString()); - retBuilder.setResult(true).setCode(response_code.SUCCESS); - } catch (Exception e) { - retBuilder.setResult(false).setCode(response_code.OTHER_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); - logger.info(EXCEPTION_CAUGHT + e.getMessage()); - } - trxExtBuilder.setResult(retBuilder); - responseObserver.onNext(trxExtBuilder.build()); - responseObserver.onCompleted(); - } - @Override public void getTransactionSignWeight(Transaction req, StreamObserver responseObserver) { @@ -1210,121 +1141,6 @@ public void getTransactionApprovedList(Transaction req, responseObserver.onCompleted(); } - @Override - public void createAddress(BytesMessage req, - StreamObserver responseObserver) { - byte[] address = wallet.createAddress(req.getValue().toByteArray()); - BytesMessage.Builder builder = BytesMessage.newBuilder(); - builder.setValue(ByteString.copyFrom(address)); - responseObserver.onNext(builder.build()); - responseObserver.onCompleted(); - } - - private EasyTransferResponse easyTransfer(byte[] privateKey, ByteString toAddress, - long amount) { - TransactionCapsule transactionCapsule; - GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); - EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); - try { - SignInterface cryptoEngine = SignUtils.fromPrivate(privateKey, Args.getInstance() - .isECKeyCryptoEngine()); - byte[] owner = cryptoEngine.getAddress(); - TransferContract.Builder builder = TransferContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setToAddress(toAddress); - builder.setAmount(amount); - transactionCapsule = createTransactionCapsule(builder.build(), - ContractType.TransferContract); - transactionCapsule.sign(privateKey); - GrpcAPI.Return result = wallet.broadcastTransaction(transactionCapsule.getInstance()); - responseBuild.setTransaction(transactionCapsule.getInstance()); - responseBuild.setTxid(transactionCapsule.getTransactionId().getByteString()); - responseBuild.setResult(result); - } catch (ContractValidateException e) { - returnBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - } catch (Exception e) { - returnBuilder.setResult(false).setCode(response_code.OTHER_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - } - - return responseBuild.build(); - } - - @Override - public void easyTransfer(EasyTransferMessage req, - StreamObserver responseObserver) { - byte[] privateKey = wallet.pass2Key(req.getPassPhrase().toByteArray()); - EasyTransferResponse response = easyTransfer(privateKey, req.getToAddress(), req.getAmount()); - responseObserver.onNext(response); - responseObserver.onCompleted(); - } - - @Override - public void easyTransferAsset(EasyTransferAssetMessage req, - StreamObserver responseObserver) { - byte[] privateKey = wallet.pass2Key(req.getPassPhrase().toByteArray()); - EasyTransferResponse response = easyTransferAsset(privateKey, req.getToAddress(), - req.getAssetId(), req.getAmount()); - responseObserver.onNext(response); - responseObserver.onCompleted(); - } - - private EasyTransferResponse easyTransferAsset(byte[] privateKey, ByteString toAddress, - String assetId, long amount) { - TransactionCapsule transactionCapsule; - GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); - EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); - try { - SignInterface cryptoEngine = SignUtils.fromPrivate(privateKey, - Args.getInstance().isECKeyCryptoEngine()); - byte[] owner = cryptoEngine.getAddress(); - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setToAddress(toAddress); - builder.setAssetName(ByteString.copyFrom(assetId.getBytes())); - builder.setAmount(amount); - transactionCapsule = createTransactionCapsule(builder.build(), - ContractType.TransferAssetContract); - transactionCapsule.sign(privateKey); - GrpcAPI.Return result = wallet.broadcastTransaction(transactionCapsule.getInstance()); - responseBuild.setTransaction(transactionCapsule.getInstance()); - responseBuild.setTxid(transactionCapsule.getTransactionId().getByteString()); - responseBuild.setResult(result); - } catch (ContractValidateException e) { - returnBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - } catch (Exception e) { - returnBuilder.setResult(false).setCode(response_code.OTHER_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - } - - return responseBuild.build(); - } - - @Override - public void easyTransferByPrivate(EasyTransferByPrivateMessage req, - StreamObserver responseObserver) { - byte[] privateKey = req.getPrivateKey().toByteArray(); - EasyTransferResponse response = easyTransfer(privateKey, req.getToAddress(), req.getAmount()); - responseObserver.onNext(response); - responseObserver.onCompleted(); - } - - @Override - public void easyTransferAssetByPrivate(EasyTransferAssetByPrivateMessage req, - StreamObserver responseObserver) { - byte[] privateKey = req.getPrivateKey().toByteArray(); - EasyTransferResponse response = easyTransferAsset(privateKey, req.getToAddress(), - req.getAssetId(), req.getAmount()); - responseObserver.onNext(response); - responseObserver.onCompleted(); - } - @Override public void broadcastTransaction(Transaction req, StreamObserver responseObserver) { @@ -2235,12 +2051,6 @@ public void getChainParameters(EmptyMessage request, responseObserver.onCompleted(); } - @Override - public void generateAddress(EmptyMessage request, - StreamObserver responseObserver) { - generateAddressCommon(request, responseObserver); - } - @Override public void getTransactionInfoById(BytesMessage request, StreamObserver responseObserver) { @@ -2899,21 +2709,6 @@ public void getStatsInfo(EmptyMessage request, } } - public void generateAddressCommon(EmptyMessage request, - StreamObserver responseObserver) { - SignInterface cryptoEngine = SignUtils.getGeneratedRandomSign(Utils.getRandom(), - Args.getInstance().isECKeyCryptoEngine()); - byte[] priKey = cryptoEngine.getPrivateKey(); - byte[] address = cryptoEngine.getAddress(); - String addressStr = StringUtil.encode58Check(address); - String priKeyStr = Hex.encodeHexString(priKey); - AddressPrKeyPairMessage.Builder builder = AddressPrKeyPairMessage.newBuilder(); - builder.setAddress(addressStr); - builder.setPrivateKey(priKeyStr); - responseObserver.onNext(builder.build()); - responseObserver.onCompleted(); - } - public void getRewardInfoCommon(BytesMessage request, StreamObserver responseObserver) { try { diff --git a/framework/src/main/java/org/tron/core/services/http/AddTransactionSignServlet.java b/framework/src/main/java/org/tron/core/services/http/AddTransactionSignServlet.java deleted file mode 100644 index f9fd1fa4936..00000000000 --- a/framework/src/main/java/org/tron/core/services/http/AddTransactionSignServlet.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.tron.core.services.http; - -import com.alibaba.fastjson.JSONObject; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.utils.TransactionUtil; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionSign; - - -@Component -@Slf4j(topic = "API") -public class AddTransactionSignServlet extends RateLimiterServlet { - - @Autowired - private TransactionUtil transactionUtil; - - protected void doGet(HttpServletRequest request, HttpServletResponse response) { - - } - - protected void doPost(HttpServletRequest request, HttpServletResponse response) { - try { - String contract = request.getReader().lines() - .collect(Collectors.joining(System.lineSeparator())); - Util.checkBodySize(contract); - JSONObject input = JSONObject.parseObject(contract); - boolean visible = Util.getVisibleOnlyForSign(input); - String strTransaction = input.getJSONObject("transaction").toJSONString(); - Transaction transaction = Util.packTransaction(strTransaction, visible); - JSONObject jsonTransaction = JSONObject.parseObject(JsonFormat.printToString(transaction, - visible)); - input.put("transaction", jsonTransaction); - TransactionSign.Builder build = TransactionSign.newBuilder(); - JsonFormat.merge(input.toJSONString(), build, visible); - TransactionCapsule reply = transactionUtil.addSign(build.build()); - if (reply != null) { - response.getWriter().println(Util.printCreateTransaction(reply.getInstance(), visible)); - } else { - response.getWriter().println("{}"); - } - } catch (Exception e) { - Util.processError(e, response); - } - } -} diff --git a/framework/src/main/java/org/tron/core/services/http/CreateAddressServlet.java b/framework/src/main/java/org/tron/core/services/http/CreateAddressServlet.java deleted file mode 100644 index 7e52abddf6a..00000000000 --- a/framework/src/main/java/org/tron/core/services/http/CreateAddressServlet.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.tron.core.services.http; - -import static org.tron.core.services.http.PostParams.S_VALUE; - -import com.alibaba.fastjson.JSONObject; -import com.google.protobuf.ByteString; -import java.io.IOException; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI.BytesMessage; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.StringUtil; -import org.tron.core.Wallet; - - -@Component -@Slf4j(topic = "API") -public class CreateAddressServlet extends RateLimiterServlet { - - @Autowired - private Wallet wallet; - - protected void doGet(HttpServletRequest request, HttpServletResponse response) { - try { - boolean visible = Util.getVisible(request); - String input = request.getParameter(S_VALUE); - if (visible) { - input = Util.getHexString(input); - } - JSONObject jsonObject = new JSONObject(); - jsonObject.put(S_VALUE, input); - BytesMessage.Builder build = BytesMessage.newBuilder(); - JsonFormat.merge(jsonObject.toJSONString(), build, visible); - fillResponse(build.getValue(), response); - } catch (Exception e) { - Util.processError(e, response); - } - } - - protected void doPost(HttpServletRequest request, HttpServletResponse response) { - try { - PostParams params = PostParams.getPostParams(request); - boolean visible = params.isVisible(); - String input = params.getParams(); - if (visible) { - input = covertStringToHex(input); - } - BytesMessage.Builder build = BytesMessage.newBuilder(); - JsonFormat.merge(input, build, visible); - fillResponse(build.getValue(), response); - } catch (Exception e) { - Util.processError(e, response); - } - } - - private String covertStringToHex(String input) { - JSONObject jsonObject = JSONObject.parseObject(input); - String value = jsonObject.getString(S_VALUE); - jsonObject.put(S_VALUE, Util.getHexString(value)); - return jsonObject.toJSONString(); - } - - private void fillResponse(ByteString value, HttpServletResponse response) throws IOException { - byte[] address = wallet.createAddress(value.toByteArray()); - String base58check = StringUtil.encode58Check(address); - String hexString = ByteArray.toHexString(address); - JSONObject jsonAddress = new JSONObject(); - jsonAddress.put("base58checkAddress", base58check); - jsonAddress.put(S_VALUE, hexString); - response.getWriter().println(jsonAddress.toJSONString()); - } -} diff --git a/framework/src/main/java/org/tron/core/services/http/EasyTransferAssetByPrivateServlet.java b/framework/src/main/java/org/tron/core/services/http/EasyTransferAssetByPrivateServlet.java deleted file mode 100644 index 2739df81387..00000000000 --- a/framework/src/main/java/org/tron/core/services/http/EasyTransferAssetByPrivateServlet.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.tron.core.services.http; - -import com.google.protobuf.ByteString; -import java.io.IOException; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.EasyTransferAssetByPrivateMessage; -import org.tron.api.GrpcAPI.EasyTransferResponse; -import org.tron.api.GrpcAPI.Return.response_code; -import org.tron.common.crypto.SignInterface; -import org.tron.common.crypto.SignUtils; -import org.tron.core.Wallet; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.args.Args; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; - - -@Component -@Slf4j -public class EasyTransferAssetByPrivateServlet extends RateLimiterServlet { - - @Autowired - private Wallet wallet; - - protected void doGet(HttpServletRequest request, HttpServletResponse response) { - - } - - protected void doPost(HttpServletRequest request, HttpServletResponse response) { - GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); - EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); - boolean visible = false; - try { - String input = request.getReader().lines() - .collect(Collectors.joining(System.lineSeparator())); - visible = Util.getVisiblePost(input); - EasyTransferAssetByPrivateMessage.Builder build = EasyTransferAssetByPrivateMessage - .newBuilder(); - JsonFormat.merge(input, build, visible); - byte[] privateKey = build.getPrivateKey().toByteArray(); - SignInterface ecKey = SignUtils.fromPrivate(privateKey, Args.getInstance() - .isECKeyCryptoEngine()); - byte[] owner = ecKey.getAddress(); - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setToAddress(build.getToAddress()); - builder.setAssetName(ByteString.copyFrom(build.getAssetId().getBytes())); - builder.setAmount(build.getAmount()); - - TransactionCapsule transactionCapsule; - transactionCapsule = wallet - .createTransactionCapsule(builder.build(), ContractType.TransferAssetContract); - transactionCapsule.sign(privateKey); - GrpcAPI.Return result = wallet.broadcastTransaction(transactionCapsule.getInstance()); - responseBuild.setTransaction(transactionCapsule.getInstance()); - responseBuild.setResult(result); - response.getWriter().println(Util.printEasyTransferResponse(responseBuild.build(), visible)); - } catch (Exception e) { - returnBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - try { - response.getWriter().println(JsonFormat.printToString(responseBuild.build(), visible)); - } catch (IOException ioe) { - logger.debug("IOException: {}", ioe.getMessage()); - } - } - } -} diff --git a/framework/src/main/java/org/tron/core/services/http/EasyTransferAssetServlet.java b/framework/src/main/java/org/tron/core/services/http/EasyTransferAssetServlet.java deleted file mode 100644 index b6939570bac..00000000000 --- a/framework/src/main/java/org/tron/core/services/http/EasyTransferAssetServlet.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.tron.core.services.http; - -import com.google.protobuf.ByteString; -import java.io.IOException; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.EasyTransferAssetMessage; -import org.tron.api.GrpcAPI.EasyTransferResponse; -import org.tron.api.GrpcAPI.Return.response_code; -import org.tron.common.crypto.SignInterface; -import org.tron.common.crypto.SignUtils; -import org.tron.core.Wallet; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.args.Args; -import org.tron.core.exception.ContractValidateException; -import org.tron.core.services.http.JsonFormat.ParseException; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; - - -@Component -@Slf4j -public class EasyTransferAssetServlet extends RateLimiterServlet { - - private static final String S_IOEXCEPTION = "IOException: {}"; - - @Autowired - private Wallet wallet; - - protected void doGet(HttpServletRequest request, HttpServletResponse response) { - - } - - protected void doPost(HttpServletRequest request, HttpServletResponse response) { - GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); - EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); - boolean visible = false; - try { - String input = request.getReader().lines() - .collect(Collectors.joining(System.lineSeparator())); - visible = Util.getVisiblePost(input); - EasyTransferAssetMessage.Builder build = EasyTransferAssetMessage.newBuilder(); - JsonFormat.merge(input, build, visible); - byte[] privateKey = wallet.pass2Key(build.getPassPhrase().toByteArray()); - SignInterface ecKey = SignUtils.fromPrivate(privateKey, Args.getInstance() - .isECKeyCryptoEngine()); - byte[] owner = ecKey.getAddress(); - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setToAddress(build.getToAddress()); - builder.setAssetName(ByteString.copyFrom(build.getAssetId().getBytes())); - builder.setAmount(build.getAmount()); - - TransactionCapsule transactionCapsule; - transactionCapsule = wallet - .createTransactionCapsule(builder.build(), ContractType.TransferAssetContract); - transactionCapsule.sign(privateKey); - GrpcAPI.Return result = wallet.broadcastTransaction(transactionCapsule.getInstance()); - responseBuild.setTransaction(transactionCapsule.getInstance()); - responseBuild.setResult(result); - response.getWriter().println(Util.printEasyTransferResponse(responseBuild.build(), visible)); - } catch (ParseException e) { - logger.debug("ParseException: {}", e.getMessage()); - returnBuilder.setResult(false).setCode(response_code.OTHER_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - try { - response.getWriter().println(JsonFormat.printToString(responseBuild.build(), visible)); - } catch (IOException ioe) { - logger.debug(S_IOEXCEPTION, ioe.getMessage()); - } - return; - } catch (IOException e) { - logger.debug(S_IOEXCEPTION, e.getMessage()); - returnBuilder.setResult(false).setCode(response_code.OTHER_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - try { - response.getWriter().println(JsonFormat.printToString(responseBuild.build(), visible)); - } catch (IOException ioe) { - logger.debug(S_IOEXCEPTION, ioe.getMessage()); - } - return; - } catch (ContractValidateException e) { - returnBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - try { - response.getWriter().println(JsonFormat.printToString(responseBuild.build(), visible)); - } catch (IOException ioe) { - logger.debug(S_IOEXCEPTION, ioe.getMessage()); - } - return; - } - } -} diff --git a/framework/src/main/java/org/tron/core/services/http/EasyTransferByPrivateServlet.java b/framework/src/main/java/org/tron/core/services/http/EasyTransferByPrivateServlet.java deleted file mode 100644 index aa6574dc66f..00000000000 --- a/framework/src/main/java/org/tron/core/services/http/EasyTransferByPrivateServlet.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.tron.core.services.http; - -import com.google.protobuf.ByteString; -import java.io.IOException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.EasyTransferByPrivateMessage; -import org.tron.api.GrpcAPI.EasyTransferResponse; -import org.tron.api.GrpcAPI.Return.response_code; -import org.tron.common.crypto.SignInterface; -import org.tron.common.crypto.SignUtils; -import org.tron.core.Wallet; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.args.Args; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.contract.BalanceContract.TransferContract; - - -@Component -@Slf4j(topic = "API") -public class EasyTransferByPrivateServlet extends RateLimiterServlet { - - @Autowired - private Wallet wallet; - - protected void doGet(HttpServletRequest request, HttpServletResponse response) { - - } - - protected void doPost(HttpServletRequest request, HttpServletResponse response) { - GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); - EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); - boolean visible = false; - try { - PostParams params = PostParams.getPostParams(request); - visible = params.isVisible(); - EasyTransferByPrivateMessage.Builder build = EasyTransferByPrivateMessage.newBuilder(); - JsonFormat.merge(params.getParams(), build, visible); - byte[] privateKey = build.getPrivateKey().toByteArray(); - SignInterface ecKey = SignUtils.fromPrivate(privateKey, Args.getInstance() - .isECKeyCryptoEngine()); - byte[] owner = ecKey.getAddress(); - TransferContract.Builder builder = TransferContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setToAddress(build.getToAddress()); - builder.setAmount(build.getAmount()); - - TransactionCapsule transactionCapsule; - transactionCapsule = wallet - .createTransactionCapsule(builder.build(), ContractType.TransferContract); - transactionCapsule.sign(privateKey); - GrpcAPI.Return result = wallet.broadcastTransaction(transactionCapsule.getInstance()); - responseBuild.setTransaction(transactionCapsule.getInstance()); - responseBuild.setResult(result); - response.getWriter().println(Util.printEasyTransferResponse(responseBuild.build(), visible)); - } catch (Exception e) { - returnBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - try { - response.getWriter().println(JsonFormat.printToString(responseBuild.build(), visible)); - } catch (IOException ioe) { - logger.debug("IOException: {}", ioe.getMessage()); - } - return; - } - } -} diff --git a/framework/src/main/java/org/tron/core/services/http/EasyTransferServlet.java b/framework/src/main/java/org/tron/core/services/http/EasyTransferServlet.java deleted file mode 100644 index 6c80153044e..00000000000 --- a/framework/src/main/java/org/tron/core/services/http/EasyTransferServlet.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.tron.core.services.http; - -import com.google.protobuf.ByteString; -import java.io.IOException; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.EasyTransferMessage; -import org.tron.api.GrpcAPI.EasyTransferResponse; -import org.tron.api.GrpcAPI.Return.response_code; -import org.tron.common.crypto.SignInterface; -import org.tron.common.crypto.SignUtils; -import org.tron.core.Wallet; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.args.Args; -import org.tron.core.exception.ContractValidateException; -import org.tron.core.services.http.JsonFormat.ParseException; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.contract.BalanceContract.TransferContract; - - -@Component -@Slf4j(topic = "API") -public class EasyTransferServlet extends RateLimiterServlet { - - @Autowired - private Wallet wallet; - - protected void doGet(HttpServletRequest request, HttpServletResponse response) { - - } - - protected void doPost(HttpServletRequest request, HttpServletResponse response) { - GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); - EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); - boolean visible = false; - try { - String input = request.getReader().lines() - .collect(Collectors.joining(System.lineSeparator())); - Util.checkBodySize(input); - visible = Util.getVisiblePost(input); - EasyTransferMessage.Builder build = EasyTransferMessage.newBuilder(); - JsonFormat.merge(input, build, visible); - byte[] privateKey = wallet.pass2Key(build.getPassPhrase().toByteArray()); - SignInterface ecKey = SignUtils.fromPrivate(privateKey, Args.getInstance() - .isECKeyCryptoEngine()); - byte[] owner = ecKey.getAddress(); - TransferContract.Builder builder = TransferContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setToAddress(build.getToAddress()); - builder.setAmount(build.getAmount()); - - TransactionCapsule transactionCapsule; - transactionCapsule = wallet - .createTransactionCapsule(builder.build(), ContractType.TransferContract); - transactionCapsule.sign(privateKey); - GrpcAPI.Return result = wallet.broadcastTransaction(transactionCapsule.getInstance()); - responseBuild.setTransaction(transactionCapsule.getInstance()); - responseBuild.setResult(result); - response.getWriter().println(Util.printEasyTransferResponse(responseBuild.build(), visible)); - } catch (ParseException e) { - logger.debug("ParseException: {}", e.getMessage()); - } catch (IOException e) { - logger.debug("IOException: {}", e.getMessage()); - } catch (ContractValidateException e) { - returnBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - try { - response.getWriter().println(JsonFormat.printToString(responseBuild.build(), visible)); - } catch (IOException ioe) { - logger.debug("IOException: {}", ioe.getMessage()); - } - } catch (Exception e) { - logger.debug("Exception: {}", e.getMessage()); - } - } -} diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index 43f00454fd3..030adc489ed 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -42,8 +42,6 @@ public class FullNodeHttpApiService implements Service { @Autowired private BroadcastServlet broadcastServlet; @Autowired - private TransactionSignServlet transactionSignServlet; - @Autowired private UpdateAccountServlet updateAccountServlet; @Autowired private VoteWitnessAccountServlet voteWitnessAccountServlet; @@ -114,18 +112,6 @@ public class FullNodeHttpApiService implements Service { @Autowired private GetNextMaintenanceTimeServlet getNextMaintenanceTimeServlet; @Autowired - private EasyTransferServlet easyTransferServlet; - @Autowired - private EasyTransferByPrivateServlet easyTransferByPrivateServlet; - @Autowired - private EasyTransferAssetServlet easyTransferAssetServlet; - @Autowired - private EasyTransferAssetByPrivateServlet easyTransferAssetByPrivateServlet; - @Autowired - private CreateAddressServlet createAddressServlet; - @Autowired - private GenerateAddressServlet generateAddressServlet; - @Autowired private ValidateAddressServlet validateAddressServlet; @Autowired private DeployContractServlet deployContractServlet; @@ -170,8 +156,6 @@ public class FullNodeHttpApiService implements Service { @Autowired private GetNodeInfoServlet getNodeInfoServlet; @Autowired - private AddTransactionSignServlet addTransactionSignServlet; - @Autowired private GetTransactionSignWeightServlet getTransactionSignWeightServlet; @Autowired private GetTransactionApprovedListServlet getTransactionApprovedListServlet; @@ -377,7 +361,6 @@ public void start() { context.addServlet(new ServletHolder(getAccountServlet), "/wallet/getaccount"); context.addServlet(new ServletHolder(transferServlet), "/wallet/createtransaction"); context.addServlet(new ServletHolder(broadcastServlet), "/wallet/broadcasttransaction"); - context.addServlet(new ServletHolder(transactionSignServlet), "/wallet/gettransactionsign"); context.addServlet(new ServletHolder(updateAccountServlet), "/wallet/updateaccount"); context.addServlet(new ServletHolder(voteWitnessAccountServlet), "/wallet/votewitnessaccount"); @@ -430,14 +413,6 @@ public void start() { context.addServlet(new ServletHolder(totalTransactionServlet), "/wallet/totaltransaction"); context.addServlet( new ServletHolder(getNextMaintenanceTimeServlet), "/wallet/getnextmaintenancetime"); - context.addServlet(new ServletHolder(createAddressServlet), "/wallet/createaddress"); - context.addServlet(new ServletHolder(easyTransferServlet), "/wallet/easytransfer"); - context.addServlet(new ServletHolder(easyTransferByPrivateServlet), - "/wallet/easytransferbyprivate"); - context.addServlet(new ServletHolder(easyTransferAssetServlet), "/wallet/easytransferasset"); - context.addServlet(new ServletHolder(easyTransferAssetByPrivateServlet), - "/wallet/easytransferassetbyprivate"); - context.addServlet(new ServletHolder(generateAddressServlet), "/wallet/generateaddress"); context.addServlet(new ServletHolder(validateAddressServlet), "/wallet/validateaddress"); context.addServlet(new ServletHolder(deployContractServlet), "/wallet/deploycontract"); context.addServlet(new ServletHolder(triggerSmartContractServlet), @@ -464,8 +439,6 @@ public void start() { "/wallet/getchainparameters"); context.addServlet(new ServletHolder(getAccountResourceServlet), "/wallet/getaccountresource"); - context.addServlet(new ServletHolder(addTransactionSignServlet), - "/wallet/addtransactionsign"); context.addServlet(new ServletHolder(getTransactionSignWeightServlet), "/wallet/getsignweight"); context.addServlet(new ServletHolder(getTransactionApprovedListServlet), diff --git a/framework/src/main/java/org/tron/core/services/http/GenerateAddressServlet.java b/framework/src/main/java/org/tron/core/services/http/GenerateAddressServlet.java deleted file mode 100644 index 1814b34c322..00000000000 --- a/framework/src/main/java/org/tron/core/services/http/GenerateAddressServlet.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.tron.core.services.http; - -import com.alibaba.fastjson.JSONObject; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.codec.binary.Hex; -import org.springframework.stereotype.Component; -import org.tron.common.crypto.SignInterface; -import org.tron.common.crypto.SignUtils; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; -import org.tron.core.config.args.Args; - - -@Component -@Slf4j(topic = "API") -public class GenerateAddressServlet extends RateLimiterServlet { - - protected void doGet(HttpServletRequest request, HttpServletResponse response) { - try { - SignInterface sign = SignUtils.getGeneratedRandomSign(Utils.getRandom(), - Args.getInstance().isECKeyCryptoEngine()); - byte[] priKey = sign.getPrivateKey(); - byte[] address = sign.getAddress(); - String priKeyStr = Hex.encodeHexString(priKey); - String base58check = StringUtil.encode58Check(address); - String hexString = ByteArray.toHexString(address); - JSONObject jsonAddress = new JSONObject(); - jsonAddress.put("address", base58check); - jsonAddress.put("hexAddress", hexString); - jsonAddress.put("privateKey", priKeyStr); - response.getWriter().println(jsonAddress.toJSONString()); - } catch (Exception e) { - Util.processError(e, response); - } - } - - protected void doPost(HttpServletRequest request, HttpServletResponse response) { - doGet(request, response); - } -} \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java b/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java index 3d3f73468bd..93b726bb0e5 100644 --- a/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java +++ b/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java @@ -13,14 +13,6 @@ public class HttpSelfFormatFieldName { //DelegatedResourceMessage AddressFieldNameMap.put("protocol.DelegatedResourceMessage.fromAddress", 1); AddressFieldNameMap.put("protocol.DelegatedResourceMessage.toAddress", 1); - //EasyTransferMessage - AddressFieldNameMap.put("protocol.EasyTransferMessage.toAddress", 1); - //EasyTransferAssetMessage - AddressFieldNameMap.put("protocol.EasyTransferAssetMessage.toAddress", 1); - //EasyTransferByPrivateMessage - AddressFieldNameMap.put("protocol.EasyTransferByPrivateMessage.toAddress", 1); - //EasyTransferAssetByPrivateMessage - AddressFieldNameMap.put("protocol.EasyTransferAssetByPrivateMessage.toAddress", 1); //TransactionSignWeight AddressFieldNameMap.put("protocol.TransactionSignWeight.approved_list", 1); //TransactionApprovedList @@ -140,8 +132,6 @@ public class HttpSelfFormatFieldName { //ShieldedTransferContract AddressFieldNameMap.put("protocol.ShieldedTransferContract.transparent_from_address", 1); AddressFieldNameMap.put("protocol.ShieldedTransferContract.transparent_to_address", 1); - //UpdateBrokerageContract - AddressFieldNameMap.put("protocol.UpdateBrokerageContract.owner_address", 1); //FreezeBalanceV2Contract AddressFieldNameMap.put("protocol.FreezeBalanceV2Contract.owner_address", 1); //UnfreezeBalanceV2Contract @@ -206,10 +196,6 @@ public class HttpSelfFormatFieldName { NameFieldNameMap.put("protocol.Return.message", 1); //Address NameFieldNameMap.put("protocol.Address.host", 1); - //EasyTransferMessage - NameFieldNameMap.put("protocol.EasyTransferMessage.passPhrase", 1); - //EasyTransferAssetMessage - NameFieldNameMap.put("protocol.EasyTransferAssetMessage.passPhrase", 1); //Note NameFieldNameMap.put("protocol.Note.memo", 1); diff --git a/framework/src/main/java/org/tron/core/services/http/TransactionSignServlet.java b/framework/src/main/java/org/tron/core/services/http/TransactionSignServlet.java deleted file mode 100644 index 86d1b07f457..00000000000 --- a/framework/src/main/java/org/tron/core/services/http/TransactionSignServlet.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.tron.core.services.http; - -import com.alibaba.fastjson.JSONObject; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.utils.TransactionUtil; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionSign; - - -@Component -@Slf4j(topic = "API") -public class TransactionSignServlet extends RateLimiterServlet { - - protected void doGet(HttpServletRequest request, HttpServletResponse response) { - - } - - protected void doPost(HttpServletRequest request, HttpServletResponse response) { - try { - String contract = request.getReader().lines() - .collect(Collectors.joining(System.lineSeparator())); - Util.checkBodySize(contract); - JSONObject input = JSONObject.parseObject(contract); - boolean visible = Util.getVisibleOnlyForSign(input); - String strTransaction = input.getJSONObject("transaction").toJSONString(); - Transaction transaction = Util.packTransaction(strTransaction, visible); - JSONObject jsonTransaction = JSONObject.parseObject(JsonFormat.printToString(transaction, - visible)); - input.put("transaction", jsonTransaction); - TransactionSign.Builder build = TransactionSign.newBuilder(); - JsonFormat.merge(input.toJSONString(), build, visible); - TransactionCapsule reply = TransactionUtil.getTransactionSign(build.build()); - if (reply != null) { - response.getWriter().println(Util.printCreateTransaction(reply.getInstance(), visible)); - } else { - response.getWriter().println("{}"); - } - } catch (Exception e) { - Util.processError(e, response); - } - } -} diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 6c8ce0b832c..28ec18b59ac 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -27,7 +27,6 @@ import org.eclipse.jetty.util.StringUtil; import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.BlockList; -import org.tron.api.GrpcAPI.EasyTransferResponse; import org.tron.api.GrpcAPI.TransactionApprovedList; import org.tron.api.GrpcAPI.TransactionExtention; import org.tron.api.GrpcAPI.TransactionIdList; @@ -129,12 +128,6 @@ public static JSONArray printTransactionListToJSON(List list return transactions; } - public static String printEasyTransferResponse(EasyTransferResponse response, boolean selfType) { - JSONObject jsonResponse = JSONObject.parseObject(JsonFormat.printToString(response, selfType)); - jsonResponse.put(TRANSACTION, printTransactionToJSON(response.getTransaction(), selfType)); - return jsonResponse.toJSONString(); - } - public static String printTransaction(Transaction transaction, boolean selfType) { return printTransactionToJSON(transaction, selfType).toJSONString(); } diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java index 7232ba01ce5..c003f9d3994 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java @@ -7,11 +7,9 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.codec.binary.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.tron.api.DatabaseGrpc.DatabaseImplBase; import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AddressPrKeyPairMessage; import org.tron.api.GrpcAPI.AssetIssueList; import org.tron.api.GrpcAPI.BlockExtention; import org.tron.api.GrpcAPI.BlockReference; @@ -414,22 +412,6 @@ public void estimateEnergy(TriggerSmartContract request, ); } - - @Override - public void generateAddress(EmptyMessage request, - StreamObserver responseObserver) { - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] priKey = ecKey.getPrivKeyBytes(); - byte[] address = ecKey.getAddress(); - String addressStr = StringUtil.encode58Check(address); - String priKeyStr = Hex.encodeHexString(priKey); - AddressPrKeyPairMessage.Builder builder = AddressPrKeyPairMessage.newBuilder(); - builder.setAddress(addressStr); - builder.setPrivateKey(priKeyStr); - responseObserver.onNext(builder.build()); - responseObserver.onCompleted(); - } - @Override public void getRewardInfo(BytesMessage request, StreamObserver responseObserver) { diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java index 254c5227929..3f4bfeda731 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java @@ -8,11 +8,9 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.codec.binary.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.tron.api.DatabaseGrpc.DatabaseImplBase; import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AddressPrKeyPairMessage; import org.tron.api.GrpcAPI.AssetIssueList; import org.tron.api.GrpcAPI.BlockExtention; import org.tron.api.GrpcAPI.BlockReference; @@ -398,23 +396,6 @@ public void estimateEnergy(TriggerSmartContract request, .estimateEnergy(request, responseObserver)); } - - @Override - public void generateAddress(EmptyMessage request, - StreamObserver responseObserver) { - SignInterface cryptoEngine = SignUtils - .getGeneratedRandomSign(Utils.getRandom(), Args.getInstance().isECKeyCryptoEngine()); - byte[] priKey = cryptoEngine.getPrivateKey(); - byte[] address = cryptoEngine.getAddress(); - String addressStr = StringUtil.encode58Check(address); - String priKeyStr = Hex.encodeHexString(priKey); - AddressPrKeyPairMessage.Builder builder = AddressPrKeyPairMessage.newBuilder(); - builder.setAddress(addressStr); - builder.setPrivateKey(priKeyStr); - responseObserver.onNext(builder.build()); - responseObserver.onCompleted(); - } - @Override public void getRewardInfo(BytesMessage request, StreamObserver responseObserver) { diff --git a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java index 3042a745d94..5bac3effbef 100755 --- a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java @@ -41,10 +41,10 @@ import org.tron.core.zen.note.Note; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction.Contract; -import org.tron.protos.Protocol.TransactionSign; import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; import org.tron.protos.contract.ShieldContract.PedersenHash; import org.tron.protos.contract.ShieldContract.ShieldedTransferContract; +import stest.tron.wallet.common.client.utils.TransactionUtils; @Slf4j public class ShieldedTransferActuatorTest { @@ -232,11 +232,8 @@ public void publicAddressToShieldedAddressSuccess() { TransactionCapsule transactionCap = getPublicToShieldedTransaction(); //Add public address sign - TransactionSign.Builder transactionSignBuild = TransactionSign.newBuilder(); - transactionSignBuild.setTransaction(transactionCap.getInstance()); - transactionSignBuild.setPrivateKey(ByteString.copyFrom( - ByteArray.fromHexString(ADDRESS_ONE_PRIVATE_KEY))); - transactionCap = transactionUtil.addSign(transactionSignBuild.build()); + transactionCap = TransactionUtils.addTransactionSign(transactionCap.getInstance(), + ADDRESS_ONE_PRIVATE_KEY, dbManager.getAccountStore()); Assert.assertTrue(dbManager.pushTransaction(transactionCap)); } catch (Exception e) { @@ -263,11 +260,8 @@ public void publicAddressToPublicAddressAndZereValueOutputSuccess() { TransactionCapsule transactionCap = builder.build(); //Add public address sign - TransactionSign.Builder transactionSignBuild = TransactionSign.newBuilder(); - transactionSignBuild.setTransaction(transactionCap.getInstance()); - transactionSignBuild.setPrivateKey(ByteString.copyFrom( - ByteArray.fromHexString(ADDRESS_ONE_PRIVATE_KEY))); - transactionCap = transactionUtil.addSign(transactionSignBuild.build()); + transactionCap = TransactionUtils.addTransactionSign(transactionCap.getInstance(), + ADDRESS_ONE_PRIVATE_KEY, dbManager.getAccountStore()); Assert.assertTrue(dbManager.pushTransaction(transactionCap)); } catch (Exception e) { @@ -286,11 +280,8 @@ public void publicAddressToShieldedAddressInvalidSign() { TransactionCapsule transactionCap = getPublicToShieldedTransaction(); //Add public address sign - TransactionSign.Builder transactionSignBuild = TransactionSign.newBuilder(); - transactionSignBuild.setTransaction(transactionCap.getInstance()); - transactionSignBuild.setPrivateKey(ByteString.copyFrom( - ByteArray.fromHexString(ADDRESS_TWO_PRIVATE_KEY))); - transactionUtil.addSign(transactionSignBuild.build()); + TransactionUtils.addTransactionSign(transactionCap.getInstance(), ADDRESS_TWO_PRIVATE_KEY, + dbManager.getAccountStore()); Assert.assertTrue(false); } catch (PermissionException e) { Assert.assertTrue(e instanceof PermissionException); @@ -429,11 +420,8 @@ public void publicAddressToShieldedAddressNotConsumeBandwidth() { try { TransactionCapsule transactionCap = getPublicToShieldedTransaction(); //Add public address sign - TransactionSign.Builder transactionSignBuild = TransactionSign.newBuilder(); - transactionSignBuild.setTransaction(transactionCap.getInstance()); - transactionSignBuild.setPrivateKey(ByteString.copyFrom( - ByteArray.fromHexString(ADDRESS_ONE_PRIVATE_KEY))); - transactionCap = transactionUtil.addSign(transactionSignBuild.build()); + transactionCap = TransactionUtils.addTransactionSign(transactionCap.getInstance(), + ADDRESS_ONE_PRIVATE_KEY, dbManager.getAccountStore()); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ByteArray.fromHexString(PUBLIC_ADDRESS_ONE)); @@ -1020,11 +1008,8 @@ public void publicToShieldAddressAndShieldToPublicAddressWithZoreValueSuccess() TransactionCapsule transactionCapOne = builderOne.build(); //Add public address sign - TransactionSign.Builder transactionSignBuild = TransactionSign.newBuilder(); - transactionSignBuild.setTransaction(transactionCapOne.getInstance()); - transactionSignBuild.setPrivateKey(ByteString.copyFrom( - ByteArray.fromHexString(ADDRESS_ONE_PRIVATE_KEY))); - transactionCapOne = transactionUtil.addSign(transactionSignBuild.build()); + transactionCapOne = TransactionUtils.addTransactionSign(transactionCapOne.getInstance(), + ADDRESS_ONE_PRIVATE_KEY, dbManager.getAccountStore()); Assert.assertTrue(dbManager.pushTransaction(transactionCapOne)); AccountCapsule accountCapsuleOne = diff --git a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java index d3cbdb71e95..71501d68a41 100755 --- a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java @@ -93,7 +93,6 @@ import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.Protocol.TransactionSign; import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; import org.tron.protos.contract.ShieldContract.IncrementalMerkleVoucherInfo; import org.tron.protos.contract.ShieldContract.OutputPoint; @@ -102,6 +101,7 @@ import org.tron.protos.contract.ShieldContract.ReceiveDescription; import org.tron.protos.contract.ShieldContract.ShieldedTransferContract; import org.tron.protos.contract.ShieldContract.SpendDescription; +import stest.tron.wallet.common.client.utils.TransactionUtils; @Slf4j public class ShieldedReceiveTest extends BlockGenerate { @@ -329,13 +329,8 @@ public void testBroadcastBeforeAllowZksnark() TransactionCapsule transactionCap = builder.build(); //Add public address sign - TransactionSign.Builder transactionSignBuild = TransactionSign.newBuilder(); - transactionSignBuild.setTransaction(transactionCap.getInstance()); - transactionSignBuild.setPrivateKey(ByteString.copyFrom( - ByteArray.fromHexString(ADDRESS_ONE_PRIVATE_KEY))); - - transactionCap = transactionUtil.addSign(transactionSignBuild.build()); - + transactionCap = TransactionUtils.addTransactionSign(transactionCap.getInstance(), + ADDRESS_ONE_PRIVATE_KEY, chainBaseManager.getAccountStore()); try { dbManager.pushTransaction(transactionCap); Assert.assertFalse(true); diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount011.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount011.java index d50783f72c1..8d829424643 100644 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount011.java +++ b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount011.java @@ -58,13 +58,6 @@ public void beforeClass() { } - @Test(enabled = true) - public void testgenerateAddress() { - EmptyMessage.Builder builder = EmptyMessage.newBuilder(); - blockingStubFull.generateAddress(builder.build()); - blockingStubSolidity.generateAddress(builder.build()); - } - /** * constructor. */ diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java index 8ef8fecbd8e..adb7c0e54a0 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java +++ b/framework/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java @@ -1174,12 +1174,8 @@ public static HttpResponse unFreezeBalance( public static String gettransactionsign( String httpNode, String transactionString, String privateKey) { try { - String requestUrl = "http://" + httpNode + "/wallet/gettransactionsign"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("transaction", transactionString); - userBaseObj2.addProperty("privateKey", privateKey); - response = createConnect(requestUrl, userBaseObj2); - transactionSignString = EntityUtils.toString(response.getEntity()); + transactionSignString = TransactionUtils.getTransactionSign(transactionString, privateKey, + false); } catch (Exception e) { e.printStackTrace(); httppost.releaseConnection(); @@ -2968,36 +2964,6 @@ public static HttpResponse updateEnergyLimit( return response; } - /** constructor. */ - public static HttpResponse createAddress(String httpNode, String value) { - try { - final String requestUrl = "http://" + httpNode + "/wallet/createaddress"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("value", str2hex(value)); - response = createConnect(requestUrl, userBaseObj2); - logger.info(userBaseObj2.toString()); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - /** constructor. */ - public static HttpResponse generateAddress(String httpNode) { - try { - final String requestUrl = "http://" + httpNode + "/wallet/generateaddress"; - JsonObject userBaseObj2 = new JsonObject(); - response = createConnect(requestUrl, userBaseObj2); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - /** constructor. */ public static HttpResponse getTransactionCountByBlocknum(String httpNode, long blocknum) { try { @@ -3029,92 +2995,6 @@ public static HttpResponse validateAddress(String httpNode, String address) { return response; } - /** constructor. */ - public static HttpResponse easyTransfer( - String httpNode, String value, byte[] toAddress, Long amount) { - try { - final String requestUrl = "http://" + httpNode + "/wallet/easytransfer"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("toAddress", ByteArray.toHexString(toAddress)); - userBaseObj2.addProperty("passPhrase", str2hex(value)); - userBaseObj2.addProperty("amount", amount); - response = createConnect(requestUrl, userBaseObj2); - logger.info(userBaseObj2.toString()); - transactionString = EntityUtils.toString(response.getEntity()); - logger.info(transactionString); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - /** constructor. */ - public static HttpResponse easyTransferByPrivate( - String httpNode, String privateKey, byte[] toAddress, Long amount) { - try { - final String requestUrl = "http://" + httpNode + "/wallet/easytransferbyprivate"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("privateKey", privateKey); - userBaseObj2.addProperty("toAddress", ByteArray.toHexString(toAddress)); - userBaseObj2.addProperty("amount", amount); - response = createConnect(requestUrl, userBaseObj2); - logger.info(userBaseObj2.toString()); - transactionString = EntityUtils.toString(response.getEntity()); - logger.info(transactionString); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - /** constructor. */ - public static HttpResponse easyTransferAsset( - String httpNode, String value, byte[] toAddress, Long amount, String assetId) { - try { - final String requestUrl = "http://" + httpNode + "/wallet/easytransferasset"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("toAddress", ByteArray.toHexString(toAddress)); - userBaseObj2.addProperty("passPhrase", str2hex(value)); - userBaseObj2.addProperty("amount", amount); - userBaseObj2.addProperty("assetId", assetId); - response = createConnect(requestUrl, userBaseObj2); - logger.info(userBaseObj2.toString()); - transactionString = EntityUtils.toString(response.getEntity()); - logger.info(transactionString); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - /** constructor. */ - public static HttpResponse easyTransferAssetByPrivate( - String httpNode, String privateKey, byte[] toAddress, Long amount, String assetId) { - try { - final String requestUrl = "http://" + httpNode + "/wallet/easytransferassetbyprivate"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("privateKey", privateKey); - userBaseObj2.addProperty("toAddress", ByteArray.toHexString(toAddress)); - userBaseObj2.addProperty("amount", amount); - userBaseObj2.addProperty("assetId", assetId); - response = createConnect(requestUrl, userBaseObj2); - logger.info(userBaseObj2.toString()); - transactionString = EntityUtils.toString(response.getEntity()); - logger.info(transactionString); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - /** constructor. */ public static HttpResponse getContractInfo(String httpNode, String contractAddress) { try { diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java index cc2af15ec7b..179af83e083 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java +++ b/framework/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java @@ -24,7 +24,13 @@ import org.tron.common.crypto.ECKey; import org.tron.common.crypto.ECKey.ECDSASignature; import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.exception.PermissionException; +import org.tron.core.exception.SignatureFormatException; +import org.tron.core.services.http.JsonFormat; +import org.tron.core.store.AccountStore; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract; import org.tron.protos.contract.AccountContract.AccountCreateContract; @@ -168,7 +174,6 @@ public static boolean validTransaction(Transaction signedTransaction) { */ public static Transaction sign(Transaction transaction, ECKey myKey) { - ByteString lockSript = ByteString.copyFrom(myKey.getAddress()); Transaction.Builder transactionBuilderSigned = transaction.toBuilder(); byte[] hash = Sha256Hash.hash(CommonParameter @@ -185,6 +190,30 @@ public static Transaction sign(Transaction transaction, ECKey myKey) { return transaction; } + public static String getTransactionSign(String transaction, String priKey, + boolean selfType) { + byte[] privateKey = ByteArray.fromHexString(priKey); + Transaction.Builder builder = Transaction.newBuilder(); + try { + JsonFormat.merge(transaction, builder, selfType); + TransactionCapsule trx = new TransactionCapsule(builder.build()); + trx.sign(privateKey); + return JsonFormat.printToString(trx.getInstance(), selfType); + } catch (JsonFormat.ParseException e) { + logger.error("{}", e); + } + return null; + } + + public static TransactionCapsule addTransactionSign(Transaction transaction, String priKey, + AccountStore accountStore) + throws PermissionException, SignatureException, SignatureFormatException { + byte[] privateKey = ByteArray.fromHexString(priKey); + TransactionCapsule trx = new TransactionCapsule(transaction); + trx.addSign(privateKey, accountStore); + return trx; + } + /** * constructor. */ diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestEasyAccount001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestEasyAccount001.java deleted file mode 100644 index a4d854547fd..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestEasyAccount001.java +++ /dev/null @@ -1,281 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Commons; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestEasyAccount001 { - - private static String assetIssueId; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf").getString("defaultParameter.assetUrl"); - long beforeEasyBalance = 0L; - long afterEasyBalance = 0L; - long beforeGenerateBalance = 0L; - long afterGenerateBalance = 0L; - long beforeEasyAsset = 0L; - long afterEasyAsset = 0L; - long beforeGenerateAsset = 0L; - long afterGenerateAsset = 0L; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] assetAddress = ecKey1.getAddress(); - String assetKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private JSONObject responseContent; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(0); - private long now = System.currentTimeMillis(); - private final long totalSupply = now; - private String userPassword = "ps_" + now; - private String assetName = "httpEasyAsset_" + now; - private String easyAddress = null; - private String generatePriKey = null; - private String generateAddress = null; - private String generateHexAddress = null; - - /** - * constructor. - */ - @Test(enabled = true, description = "Create address by http") - public void test01CreateAddress() { - logger.info(userPassword); - response = HttpMethed.createAddress(httpnode, userPassword); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - easyAddress = responseContent.get("base58checkAddress").toString(); - - //Send trx to easy account - response = HttpMethed - .sendCoin(httpnode, fromAddress, Commons.decodeFromBase58Check(easyAddress), 5000000L, - testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - beforeEasyBalance = HttpMethed.getBalance(httpnode, Commons.decodeFromBase58Check(easyAddress)); - logger.info("beforeEasyBalance: " + beforeEasyBalance); - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Generate address by http") - public void test02GenerateAddress() { - response = HttpMethed.generateAddress(httpnode); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - generateAddress = responseContent.get("address").toString(); - generateHexAddress = responseContent.get("hexAddress").toString(); - generatePriKey = responseContent.get("privateKey").toString(); - - //Send trx to easy account - response = HttpMethed - .sendCoin(httpnode, fromAddress, Commons.decodeFromBase58Check(generateAddress), 5000000L, - testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - beforeGenerateBalance = HttpMethed - .getBalance(httpnode, Commons.decodeFromBase58Check(generateAddress)); - logger.info("beforeGenerateBalance: " + beforeGenerateBalance); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "Validate address by http") - public void test03ValideteAddress() { - // Base58check format - response = HttpMethed.validateAddress(httpnode, generateAddress); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - // Hex string format - response = HttpMethed.validateAddress(httpnode, generateHexAddress); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "Easy transfer by http") - public void test04EasyTransfer() { - response = HttpMethed - .easyTransfer(httpnode, userPassword, Commons.decodeFromBase58Check(generateAddress), - 1000000L); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - HttpMethed.waitToProduceOneBlock(httpnode); - - //Send trx to easy account - afterEasyBalance = HttpMethed.getBalance(httpnode, Commons.decodeFromBase58Check(easyAddress)); - logger.info("afterEasyBalance: " + afterEasyBalance); - - afterGenerateBalance = HttpMethed - .getBalance(httpnode, Commons.decodeFromBase58Check(generateAddress)); - logger.info("afterGenerateBalance: " + afterGenerateBalance); - - Assert.assertEquals(beforeEasyBalance - afterEasyBalance, - afterGenerateBalance - beforeGenerateBalance); - beforeEasyBalance = afterEasyBalance; - beforeGenerateBalance = afterGenerateBalance; - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Easy transfer by privateKey by http") - public void test05EasyTransferByPrivateKey() { - response = HttpMethed - .easyTransferByPrivate(httpnode, generatePriKey, Commons.decodeFromBase58Check(easyAddress), - 1000000L); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - HttpMethed.waitToProduceOneBlock(httpnode); - - //Send trx to easy account - afterEasyBalance = HttpMethed.getBalance(httpnode, Commons.decodeFromBase58Check(easyAddress)); - logger.info("beforeEasyBalance: " + beforeEasyBalance); - logger.info("afterEasyBalance: " + afterEasyBalance); - - afterGenerateBalance = HttpMethed - .getBalance(httpnode, Commons.decodeFromBase58Check(generateAddress)); - logger.info("beforeGenerateBalance: " + beforeGenerateBalance); - logger.info("afterGenerateBalance: " + afterGenerateBalance); - - Assert.assertEquals(beforeGenerateBalance - afterGenerateBalance, - afterEasyBalance - beforeEasyBalance); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Create asset issue by http") - public void test06CreateAssetIssue() { - Long amount = 2048000000L; - response = HttpMethed.sendCoin(httpnode, fromAddress, assetAddress, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - //Create an asset issue - response = HttpMethed - .assetIssue(httpnode, assetAddress, assetName, assetName, totalSupply, 1, 1, - System.currentTimeMillis() + 5000, System.currentTimeMillis() + 50000000, 2, 3, - description, url, 1000L, 1000L, assetKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed.getAccount(httpnode, assetAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - assetIssueId = responseContent.getString("asset_issued_ID"); - logger.info(assetIssueId); - Assert.assertTrue(Integer.parseInt(assetIssueId) > 1000000); - - response = HttpMethed - .transferAsset(httpnode, assetAddress, Commons.decodeFromBase58Check(easyAddress), - assetIssueId, 100L, assetKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed.getAccount(httpnode, Commons.decodeFromBase58Check(easyAddress)); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - beforeEasyAsset = responseContent.getJSONArray("assetV2").getJSONObject(0) - .getLongValue("value"); - logger.info("beforeEasyAsset:" + beforeEasyAsset); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Easy transfer asset by http") - public void test07EasyTransferAsset() { - response = HttpMethed - .easyTransferAsset(httpnode, userPassword, Commons.decodeFromBase58Check(generateAddress), - 10L, assetIssueId); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed.getAccount(httpnode, Commons.decodeFromBase58Check(easyAddress)); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - afterEasyAsset = responseContent.getJSONArray("assetV2").getJSONObject(0).getLongValue("value"); - logger.info("afterEasyAsset:" + afterEasyAsset); - - response = HttpMethed.getAccount(httpnode, Commons.decodeFromBase58Check(generateAddress)); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - beforeGenerateAsset = responseContent.getJSONArray("assetV2").getJSONObject(0) - .getLongValue("value"); - logger.info("beforeGenerateAsset:" + beforeGenerateAsset); - Assert.assertEquals(beforeEasyAsset - afterEasyAsset, beforeGenerateAsset); - beforeEasyAsset = afterEasyAsset; - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Easy transfer asset by private key by http") - public void test08EasyTransferAssetByPrivateKey() { - response = HttpMethed.easyTransferAssetByPrivate(httpnode, generatePriKey, - Commons.decodeFromBase58Check(easyAddress), 5L, assetIssueId); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed.getAccount(httpnode, Commons.decodeFromBase58Check(easyAddress)); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - afterEasyAsset = responseContent.getJSONArray("assetV2").getJSONObject(0).getLongValue("value"); - logger.info("beforeEasyAsset:" + beforeEasyAsset); - logger.info("afterEasyAsset:" + afterEasyAsset); - - response = HttpMethed.getAccount(httpnode, Commons.decodeFromBase58Check(generateAddress)); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - afterGenerateAsset = responseContent.getJSONArray("assetV2").getJSONObject(0) - .getLongValue("value"); - logger.info("afterGenerateAsset:" + afterGenerateAsset); - Assert.assertEquals(beforeGenerateAsset - afterGenerateAsset, afterEasyAsset - beforeEasyAsset); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.freedResource(httpnode, Commons.decodeFromBase58Check(generateAddress), fromAddress, - generatePriKey); - HttpMethed.freedResource(httpnode, assetAddress, fromAddress, assetKey); - HttpMethed.disConnect(); - } - -} diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 48cd64acc5b..70297d0959b 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -624,68 +624,6 @@ service Wallet { } }; } - //Warning: do not invoke this interface provided by others. - //Please use GetTransactionSign2 instead of this function. - rpc GetTransactionSign (TransactionSign) returns (Transaction) { - option (google.api.http) = { - post: "/wallet/gettransactionsign" - body: "*" - additional_bindings { - get: "/wallet/gettransactionsign" - } - }; - }; - //Warning: do not invoke this interface provided by others. - //Use this function instead of GetTransactionSign. - rpc GetTransactionSign2 (TransactionSign) returns (TransactionExtention) { - }; - //Warning: do not invoke this interface provided by others. - rpc CreateAddress (BytesMessage) returns (BytesMessage) { - option (google.api.http) = { - post: "/wallet/createaddress" - body: "*" - additional_bindings { - get: "/wallet/createaddress" - } - }; - }; - //Warning: do not invoke this interface provided by others. - rpc EasyTransferAsset (EasyTransferAssetMessage) returns (EasyTransferResponse) { - }; - //Warning: do not invoke this interface provided by others. - rpc EasyTransferAssetByPrivate (EasyTransferAssetByPrivateMessage) returns (EasyTransferResponse) { - }; - //Warning: do not invoke this interface provided by others. - rpc EasyTransfer (EasyTransferMessage) returns (EasyTransferResponse) { - option (google.api.http) = { - post: "/wallet/easytransfer" - body: "*" - additional_bindings { - get: "/wallet/easytransfer" - } - }; - }; - //Warning: do not invoke this interface provided by others. - rpc EasyTransferByPrivate (EasyTransferByPrivateMessage) returns (EasyTransferResponse) { - option (google.api.http) = { - post: "/wallet/easytransferbyprivate" - body: "*" - additional_bindings { - get: "/wallet/easytransferbyprivate" - } - }; - }; - //Warning: do not invoke this interface provided by others. - rpc GenerateAddress (EmptyMessage) returns (AddressPrKeyPairMessage) { - - option (google.api.http) = { - post: "/wallet/generateaddress" - body: "*" - additional_bindings { - get: "/wallet/generateaddress" - } - }; - } rpc GetTransactionInfoById (BytesMessage) returns (TransactionInfo) { option (google.api.http) = { @@ -707,10 +645,6 @@ service Wallet { }; } - rpc AddSign (TransactionSign) returns (TransactionExtention) { - - } - rpc GetTransactionSignWeight (Transaction) returns (TransactionSignWeight) { } @@ -968,17 +902,6 @@ service WalletSolidity { }; } - //Warning: do not invoke this interface provided by others. - rpc GenerateAddress (EmptyMessage) returns (AddressPrKeyPairMessage) { - option (google.api.http) = { - post: "/walletsolidity/generateaddress" - body: "*" - additional_bindings { - get: "/walletsolidity/generateaddress" - } - }; - } - rpc GetMerkleTreeVoucherInfo (OutputPointInfo) returns (IncrementalMerkleVoucherInfo) { } @@ -1269,43 +1192,6 @@ message PaginatedMessage { int64 limit = 2; } -message EasyTransferMessage { - bytes passPhrase = 1; - bytes toAddress = 2; - int64 amount = 3; -} - -message EasyTransferAssetMessage { - bytes passPhrase = 1; - bytes toAddress = 2; - string assetId = 3; - int64 amount = 4; -} - -message EasyTransferByPrivateMessage { - bytes privateKey = 1; - bytes toAddress = 2; - int64 amount = 3; -} - -message EasyTransferAssetByPrivateMessage { - bytes privateKey = 1; - bytes toAddress = 2; - string assetId = 3; - int64 amount = 4; -} - -message EasyTransferResponse { - Transaction transaction = 1; - Return result = 2; - bytes txid = 3; //transaction id = sha256(transaction.rowdata) -} - -message AddressPrKeyPairMessage { - string address = 1; - string privateKey = 2; -} - message TransactionExtention { Transaction transaction = 1; bytes txid = 2; //transaction id = sha256(transaction.rowdata) diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 437f5bf85a2..e5145484f05 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -494,11 +494,6 @@ message Transactions { repeated Transaction transactions = 1; } -message TransactionSign { - Transaction transaction = 1; - bytes privateKey = 2; -} - message BlockHeader { message raw { int64 timestamp = 1; From 3f00ebdd0f0af107bbcee07044738012a8fe0eb8 Mon Sep 17 00:00:00 2001 From: vikingzzu Date: Fri, 31 Mar 2023 16:51:09 +0800 Subject: [PATCH 0702/1197] update fetchBlockTimeout to 500ms --- framework/src/main/java/org/tron/core/config/args/Args.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 80c87b91005..a44e79ae5aa 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -570,7 +570,7 @@ public static void setParam(final String[] args, final String confFileName) { : 2000; if (!config.hasPath(Constant.NODE_FETCH_BLOCK_TIMEOUT)) { - PARAMETER.fetchBlockTimeout = 200; + PARAMETER.fetchBlockTimeout = 500; } else if (config.getInt(Constant.NODE_FETCH_BLOCK_TIMEOUT) > 1000) { PARAMETER.fetchBlockTimeout = 1000; } else if (config.getInt(Constant.NODE_FETCH_BLOCK_TIMEOUT) < 100) { From 5c615f7c160162c92fd9b8d71d1594c9abc63cd4 Mon Sep 17 00:00:00 2001 From: Asuka Date: Sun, 2 Apr 2023 18:23:56 +0800 Subject: [PATCH 0703/1197] fix(interface): continue to estimate if runtime exception occurred while estimating --- .../java/org/tron/core/db/TransactionTrace.java | 2 +- .../src/main/java/org/tron/core/Wallet.java | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java index 84b22adf0d9..c239639f019 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java @@ -255,7 +255,7 @@ public void pay() throws BalanceInsufficientException { AccountCapsule origin = accountStore.get(originAccount); AccountCapsule caller = accountStore.get(callerAccount); if (dynamicPropertiesStore.supportUnfreezeDelay() - && receipt.getReceipt().getResult().equals(contractResult.SUCCESS)) { + && getRuntimeResult().getException() == null && !getRuntimeResult().isRevert()) { // just fo caller is not origin, we set the related field for origin account if (origin != null && !caller.getAddress().equals(origin.getAddress())) { diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index d834d4ae661..2d5503e9c39 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2842,7 +2842,7 @@ public Transaction triggerContract(TriggerSmartContract triggerSmartContract.getData().toByteArray()); if (isConstant(abi, selector)) { - return callConstantContract(trxCap, builder, retBuilder); + return callConstantContract(trxCap, builder, retBuilder, false); } else { return trxCap.getInstance(); } @@ -2960,13 +2960,19 @@ private Transaction cleanContextAndTriggerConstantContract( txExtBuilder.clear(); txRetBuilder.clear(); transaction = triggerConstantContract( - triggerSmartContract, txCap, txExtBuilder, txRetBuilder); + triggerSmartContract, txCap, txExtBuilder, txRetBuilder, true); return transaction; } public Transaction triggerConstantContract(TriggerSmartContract triggerSmartContract, TransactionCapsule trxCap, Builder builder, Return.Builder retBuilder) throws ContractValidateException, ContractExeException, HeaderNotFound, VMIllegalException { + return triggerConstantContract(triggerSmartContract, trxCap, builder, retBuilder, false); + } + + public Transaction triggerConstantContract(TriggerSmartContract triggerSmartContract, + TransactionCapsule trxCap, Builder builder, Return.Builder retBuilder, boolean isEstimating) + throws ContractValidateException, ContractExeException, HeaderNotFound, VMIllegalException { if (triggerSmartContract.getContractAddress().isEmpty()) { // deploy contract CreateSmartContract.Builder deployBuilder = CreateSmartContract.newBuilder(); @@ -2991,11 +2997,11 @@ public Transaction triggerConstantContract(TriggerSmartContract triggerSmartCont throw new ContractValidateException("Smart contract is not exist."); } } - return callConstantContract(trxCap, builder, retBuilder); + return callConstantContract(trxCap, builder, retBuilder, isEstimating); } public Transaction callConstantContract(TransactionCapsule trxCap, - Builder builder, Return.Builder retBuilder) + Builder builder, Return.Builder retBuilder, boolean isEstimating) throws ContractValidateException, ContractExeException, HeaderNotFound, VMIllegalException { if (!Args.getInstance().isSupportConstant()) { @@ -3020,7 +3026,7 @@ public Transaction callConstantContract(TransactionCapsule trxCap, vmActuator.execute(context); ProgramResult result = context.getProgramResult(); - if (result.getException() != null) { + if (!isEstimating && result.getException() != null) { RuntimeException e = result.getException(); logger.warn("Constant call has an error {}", e.getMessage()); throw e; From ad30d13976c38bc58076cd98dcd32ec3db4942d9 Mon Sep 17 00:00:00 2001 From: Asuka Date: Sun, 2 Apr 2023 19:38:18 +0800 Subject: [PATCH 0704/1197] fix(interface): throw out of time exception in any case --- framework/src/main/java/org/tron/core/Wallet.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 2d5503e9c39..c36437a806d 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -3026,7 +3026,8 @@ public Transaction callConstantContract(TransactionCapsule trxCap, vmActuator.execute(context); ProgramResult result = context.getProgramResult(); - if (!isEstimating && result.getException() != null) { + if (!isEstimating && result.getException() != null + || result.getException() instanceof Program.OutOfTimeException) { RuntimeException e = result.getException(); logger.warn("Constant call has an error {}", e.getMessage()); throw e; From 6956e371bf884a7e630c4e13bbd38063ff7bf73c Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 3 Apr 2023 11:49:08 +0800 Subject: [PATCH 0705/1197] func(interface): do the same modification for estimate energy --- .../services/http/EstimateEnergyServlet.java | 31 ++++-------------- .../http/TriggerConstantContractServlet.java | 32 +++---------------- .../http/TriggerSmartContractServlet.java | 28 +++++++--------- .../org/tron/core/services/http/Util.java | 32 +++++++++++++++++++ 4 files changed, 54 insertions(+), 69 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java b/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java index 6b82199bd0e..d88f7dd1af1 100644 --- a/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/EstimateEnergyServlet.java @@ -4,7 +4,6 @@ import com.google.protobuf.ByteString; import io.netty.util.internal.StringUtil; import java.io.IOException; -import java.security.InvalidParameterException; import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -25,26 +24,12 @@ @Slf4j(topic = "API") public class EstimateEnergyServlet extends RateLimiterServlet { - private final String functionSelector = "function_selector"; - @Autowired private Wallet wallet; protected void doGet(HttpServletRequest request, HttpServletResponse response) { } - protected void validateParameter(String contract) { - JSONObject jsonObject = JSONObject.parseObject(contract); - if (!jsonObject.containsKey("owner_address") - || StringUtil.isNullOrEmpty(jsonObject.getString("owner_address"))) { - throw new InvalidParameterException("owner_address isn't set."); - } - if (!jsonObject.containsKey("contract_address") - || StringUtil.isNullOrEmpty(jsonObject.getString("contract_address"))) { - throw new InvalidParameterException("contract_address isn't set."); - } - } - protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { TriggerSmartContract.Builder build = TriggerSmartContract.newBuilder(); @@ -57,21 +42,19 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); visible = Util.getVisiblePost(contract); - validateParameter(contract); + Util.validateParameter(contract); JsonFormat.merge(contract, build, visible); JSONObject jsonObject = JSONObject.parseObject(contract); - boolean isFunctionSelectorSet = jsonObject.containsKey(functionSelector) - && !StringUtil.isNullOrEmpty(jsonObject.getString(functionSelector)); - String data; + boolean isFunctionSelectorSet = + !StringUtil.isNullOrEmpty(jsonObject.getString(Util.FUNCTION_SELECTOR)); if (isFunctionSelectorSet) { - String selector = jsonObject.getString(functionSelector); - String parameter = jsonObject.getString("parameter"); - data = Util.parseMethod(selector, parameter); + String selector = jsonObject.getString(Util.FUNCTION_SELECTOR); + String parameter = jsonObject.getString(Util.FUNCTION_PARAMETER); + String data = Util.parseMethod(selector, parameter); build.setData(ByteString.copyFrom(ByteArray.fromHexString(data))); - } else { - build.setData(ByteString.copyFrom(new byte[0])); } + TransactionCapsule trxCap = wallet.createTransactionCapsule(build.build(), Protocol.Transaction.Contract.ContractType.TriggerSmartContract); diff --git a/framework/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java b/framework/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java index fa3336df5eb..8a46ee1ed74 100644 --- a/framework/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java @@ -4,7 +4,6 @@ import com.google.protobuf.ByteString; import io.netty.util.internal.StringUtil; import java.io.IOException; -import java.security.InvalidParameterException; import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -27,35 +26,12 @@ @Slf4j(topic = "API") public class TriggerConstantContractServlet extends RateLimiterServlet { - private final String OWNER_ADDRESS = "owner_address"; - private final String CONTRACT_ADDRESS = "contract_address"; - private final String FUNCTION_SELECTOR = "function_selector"; - private final String FUNCTION_PARAMETER = "parameter"; - private final String CALL_DATA = "data"; - @Autowired private Wallet wallet; protected void doGet(HttpServletRequest request, HttpServletResponse response) { } - protected void validateParameter(String contract) { - JSONObject jsonObject = JSONObject.parseObject(contract); - if (StringUtil.isNullOrEmpty(jsonObject.getString(OWNER_ADDRESS))) { - throw new InvalidParameterException(OWNER_ADDRESS + " isn't set."); - } - if (StringUtil.isNullOrEmpty(jsonObject.getString(CONTRACT_ADDRESS)) - && StringUtil.isNullOrEmpty(jsonObject.getString(CALL_DATA))) { - throw new InvalidParameterException("At least one of " - + CONTRACT_ADDRESS + " and " + CALL_DATA + " must be set."); - } - if (!StringUtil.isNullOrEmpty(jsonObject.getString(FUNCTION_SELECTOR)) - ^ StringUtil.isNullOrEmpty(jsonObject.getString(CALL_DATA))) { - throw new InvalidParameterException("Only one of " - + FUNCTION_SELECTOR + " and " + CALL_DATA + " can be set."); - } - } - protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { TriggerSmartContract.Builder build = TriggerSmartContract.newBuilder(); @@ -67,15 +43,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); visible = Util.getVisiblePost(contract); - validateParameter(contract); + Util.validateParameter(contract); JsonFormat.merge(contract, build, visible); JSONObject jsonObject = JSONObject.parseObject(contract); boolean isFunctionSelectorSet = - !StringUtil.isNullOrEmpty(jsonObject.getString(FUNCTION_SELECTOR)); + !StringUtil.isNullOrEmpty(jsonObject.getString(Util.FUNCTION_SELECTOR)); if (isFunctionSelectorSet) { - String selector = jsonObject.getString(FUNCTION_SELECTOR); - String parameter = jsonObject.getString(FUNCTION_PARAMETER); + String selector = jsonObject.getString(Util.FUNCTION_SELECTOR); + String parameter = jsonObject.getString(Util.FUNCTION_PARAMETER); String data = Util.parseMethod(selector, parameter); build.setData(ByteString.copyFrom(ByteArray.fromHexString(data))); } diff --git a/framework/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java b/framework/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java index 5ce27e7cd0b..d8f142edb46 100644 --- a/framework/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java @@ -27,30 +27,24 @@ @Slf4j(topic = "API") public class TriggerSmartContractServlet extends RateLimiterServlet { - private final String OWNER_ADDRESS = "owner_address"; - private final String CONTRACT_ADDRESS = "contract_address"; - private final String FUNCTION_SELECTOR = "function_selector"; - private final String FUNCTION_PARAMETER = "parameter"; - private final String CALL_DATA = "data"; - @Autowired private Wallet wallet; protected void doGet(HttpServletRequest request, HttpServletResponse response) { } - protected void validateParameter(String contract) { + private void validateParameter(String contract) { JSONObject jsonObject = JSONObject.parseObject(contract); - if (StringUtil.isNullOrEmpty(jsonObject.getString(OWNER_ADDRESS))) { - throw new InvalidParameterException("owner_address isn't set."); + if (StringUtil.isNullOrEmpty(jsonObject.getString(Util.OWNER_ADDRESS))) { + throw new InvalidParameterException(Util.OWNER_ADDRESS + " isn't set."); } - if (StringUtil.isNullOrEmpty(jsonObject.getString(CONTRACT_ADDRESS))) { - throw new InvalidParameterException("contract_address isn't set."); + if (StringUtil.isNullOrEmpty(jsonObject.getString(Util.CONTRACT_ADDRESS))) { + throw new InvalidParameterException(Util.CONTRACT_ADDRESS + " isn't set."); } - if (!StringUtil.isNullOrEmpty(jsonObject.getString(FUNCTION_SELECTOR)) - ^ StringUtil.isNullOrEmpty(jsonObject.getString(CALL_DATA))) { + if (!StringUtil.isNullOrEmpty(jsonObject.getString(Util.FUNCTION_SELECTOR)) + ^ StringUtil.isNullOrEmpty(jsonObject.getString(Util.CALL_DATA))) { throw new InvalidParameterException("Only one of " - + FUNCTION_SELECTOR + " and " + CALL_DATA + " can be set."); + + Util.FUNCTION_SELECTOR + " and " + Util.CALL_DATA + " can be set."); } } @@ -70,10 +64,10 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) JSONObject jsonObject = JSONObject.parseObject(contract); boolean isFunctionSelectorSet = - !StringUtil.isNullOrEmpty(jsonObject.getString(FUNCTION_SELECTOR)); + !StringUtil.isNullOrEmpty(jsonObject.getString(Util.FUNCTION_SELECTOR)); if (isFunctionSelectorSet) { - String selector = jsonObject.getString(FUNCTION_SELECTOR); - String parameter = jsonObject.getString(FUNCTION_PARAMETER); + String selector = jsonObject.getString(Util.FUNCTION_SELECTOR); + String parameter = jsonObject.getString(Util.FUNCTION_PARAMETER); String data = Util.parseMethod(selector, parameter); build.setData(ByteString.copyFrom(ByteArray.fromHexString(data))); } diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 6c8ce0b832c..2e91a5693fc 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -65,6 +65,13 @@ public class Util { public static final String EXTRA_DATA = "extra_data"; public static final String PARAMETER = "parameter"; + // Used for TVM http interfaces + public static final String OWNER_ADDRESS = "owner_address"; + public static final String CONTRACT_ADDRESS = "contract_address"; + public static final String FUNCTION_SELECTOR = "function_selector"; + public static final String FUNCTION_PARAMETER = "parameter"; + public static final String CALL_DATA = "data"; + public static String printTransactionFee(String transactionFee) { JSONObject jsonObject = new JSONObject(); JSONObject receipt = JSONObject.parseObject(transactionFee); @@ -543,4 +550,29 @@ public static List convertLogAddressToTronAddress(TransactionInfo transacti return newLogList; } + /** + * Validate parameters for trigger constant and estimate energy + * - Rule-1: owner address must be set + * - Rule-2: either contract address is set or call data is set + * - Rule-3: only one of function selector and call data can be set + * @param contract parameters in json format + * @throws InvalidParameterException if validation is not passed, this kind of exception is thrown + */ + public static void validateParameter(String contract) throws InvalidParameterException { + JSONObject jsonObject = JSONObject.parseObject(contract); + if (StringUtils.isEmpty(jsonObject.getString(OWNER_ADDRESS))) { + throw new InvalidParameterException(OWNER_ADDRESS + " isn't set."); + } + if (StringUtils.isEmpty(jsonObject.getString(CONTRACT_ADDRESS)) + && StringUtils.isEmpty(jsonObject.getString(CALL_DATA))) { + throw new InvalidParameterException("At least one of " + + CONTRACT_ADDRESS + " and " + CALL_DATA + " must be set."); + } + if (!StringUtils.isEmpty(jsonObject.getString(FUNCTION_SELECTOR)) + ^ StringUtils.isEmpty(jsonObject.getString(CALL_DATA))) { + throw new InvalidParameterException("Only one of " + + FUNCTION_SELECTOR + " and " + CALL_DATA + " can be set."); + } + } + } From 708271491cad976c7caf60f7fc246781db93bec0 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Mon, 3 Apr 2023 13:56:59 +0800 Subject: [PATCH 0706/1197] fix(net):fix the issue of block synchronization --- .../main/java/org/tron/core/net/service/sync/SyncService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 68f113afd9f..79cc4830e60 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -292,7 +292,7 @@ private void processSyncBlock(BlockCapsule block) { if (peer.getSyncBlockInProcess().remove(blockId)) { if (flag) { peer.setBlockBothHave(blockId); - if (peer.getSyncBlockToFetch().isEmpty() && !peer.isFetchAble()) { + if (peer.getSyncBlockToFetch().isEmpty() && peer.isFetchAble()) { syncNext(peer); } } else { From 5643063f8e5632b4bb521eddd95e84144a7a5b59 Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 3 Apr 2023 14:11:30 +0800 Subject: [PATCH 0707/1197] style(http,util): fix sonar check problem --- framework/src/main/java/org/tron/core/services/http/Util.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 2e91a5693fc..15c5bc97009 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -227,7 +227,7 @@ public static JSONObject printTransactionToJSON(Transaction transaction, boolean .parseObject(JsonFormat.printToString(deployContract, selfType)); byte[] ownerAddress = deployContract.getOwnerAddress().toByteArray(); byte[] contractAddress = generateContractAddress(transaction, ownerAddress); - jsonTransaction.put("contract_address", ByteArray.toHexString(contractAddress)); + jsonTransaction.put(CONTRACT_ADDRESS, ByteArray.toHexString(contractAddress)); break; default: Class clazz = TransactionFactory.getContract(contract.getType()); From a3afa12bb5e9c422c60c1c6809a01a7ab4db8958 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Mon, 3 Apr 2023 16:16:54 +0800 Subject: [PATCH 0708/1197] feat(net):add unit test for block synchronization --- .../core/net/services/SyncServiceTest.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java diff --git a/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java b/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java new file mode 100644 index 00000000000..dd8707d3dc6 --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java @@ -0,0 +1,74 @@ +package org.tron.core.net.services; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.ReflectUtils; +import org.tron.core.Constant; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.net.P2pEventHandlerImpl; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.peer.TronState; +import org.tron.core.net.service.sync.SyncService; +import org.tron.p2p.connection.Channel; + +import java.io.File; +import java.lang.reflect.Field; +import java.net.InetSocketAddress; + +public class SyncServiceTest { + protected TronApplicationContext context; + private SyncService service; + private PeerConnection peer; + private P2pEventHandlerImpl p2pEventHandler; + private String dbPath = "output-sync-service-test"; + + /** + * init context. + */ + @Before + public void init() { + Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, + Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + service = context.getBean(SyncService.class); + } + + /** + * destroy. + */ + @After + public void destroy() { + Args.clearParam(); + FileUtil.deleteDir(new File(dbPath)); + } + + @Test + public void test() { + try { + ReflectUtils.setFieldValue(service, "fetchFlag", true); + ReflectUtils.setFieldValue(service, "handleFlag", true); + service.init(); + Assert.assertTrue((boolean) ReflectUtils.getFieldObject(service, "fetchFlag")); + Assert.assertTrue((boolean) ReflectUtils.getFieldObject(service, "handleFlag")); + peer = context.getBean(PeerConnection.class); + Assert.assertNull(peer.getSyncChainRequested()); + Channel c1 = new Channel(); + InetSocketAddress a1 =new InetSocketAddress("127.0.0.1", 10001); + Field field = c1.getClass().getDeclaredField("inetSocketAddress"); + field.setAccessible(true); + field.set(c1, a1.getAddress()); + peer.setChannel(c1); + service.startSync(peer); + ReflectUtils.setFieldValue(peer, "tronState", TronState.SYNCING); + service.startSync(peer); + } catch (Exception e) { + // no need to deal with + } + service.close(); + } +} From 7c1bd7d8e78dd8019a817872344fd4594df4e86b Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Mon, 3 Apr 2023 16:49:03 +0800 Subject: [PATCH 0709/1197] fix(net):fix checkstyle issues --- .../java/org/tron/core/net/services/SyncServiceTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java b/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java index dd8707d3dc6..8493b1785be 100644 --- a/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java @@ -1,5 +1,8 @@ package org.tron.core.net.services; +import java.io.File; +import java.lang.reflect.Field; +import java.net.InetSocketAddress; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -16,9 +19,6 @@ import org.tron.core.net.service.sync.SyncService; import org.tron.p2p.connection.Channel; -import java.io.File; -import java.lang.reflect.Field; -import java.net.InetSocketAddress; public class SyncServiceTest { protected TronApplicationContext context; @@ -58,7 +58,7 @@ public void test() { peer = context.getBean(PeerConnection.class); Assert.assertNull(peer.getSyncChainRequested()); Channel c1 = new Channel(); - InetSocketAddress a1 =new InetSocketAddress("127.0.0.1", 10001); + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); Field field = c1.getClass().getDeclaredField("inetSocketAddress"); field.setAccessible(true); field.set(c1, a1.getAddress()); From 7af64889e3d0f9d1ed09de47466def4dafe415b6 Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 3 Apr 2023 17:17:29 +0800 Subject: [PATCH 0710/1197] func(http,util): remove rule-3 validation --- framework/src/main/java/org/tron/core/Wallet.java | 1 - .../src/main/java/org/tron/core/services/http/Util.java | 6 ------ 2 files changed, 7 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index c36437a806d..98b9c992f0d 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -3035,7 +3035,6 @@ public Transaction callConstantContract(TransactionCapsule trxCap, TransactionResultCapsule ret = new TransactionResultCapsule(); builder.setEnergyUsed(result.getEnergyUsed()); - builder.setEnergyPenalty(result.getEnergyPenaltyTotal()); builder.setBlockNumber(headBlockCapsule.getNum()); builder.setBlockHash(ByteString.copyFrom(headBlockCapsule.getBlockId().getBytes())); builder.setEnergyPenalty(result.getEnergyPenaltyTotal()); diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 15c5bc97009..5d97e944709 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -554,7 +554,6 @@ public static List convertLogAddressToTronAddress(TransactionInfo transacti * Validate parameters for trigger constant and estimate energy * - Rule-1: owner address must be set * - Rule-2: either contract address is set or call data is set - * - Rule-3: only one of function selector and call data can be set * @param contract parameters in json format * @throws InvalidParameterException if validation is not passed, this kind of exception is thrown */ @@ -568,11 +567,6 @@ public static void validateParameter(String contract) throws InvalidParameterExc throw new InvalidParameterException("At least one of " + CONTRACT_ADDRESS + " and " + CALL_DATA + " must be set."); } - if (!StringUtils.isEmpty(jsonObject.getString(FUNCTION_SELECTOR)) - ^ StringUtils.isEmpty(jsonObject.getString(CALL_DATA))) { - throw new InvalidParameterException("Only one of " - + FUNCTION_SELECTOR + " and " + CALL_DATA + " can be set."); - } } } From 131161e9504fa6aa9b7ead0c42fd39b6f05aba7e Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 3 Apr 2023 17:37:08 +0800 Subject: [PATCH 0711/1197] func(http,util): add new rule-3 validation --- .../src/main/java/org/tron/core/services/http/Util.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 5d97e944709..4bd1be3fb6f 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -554,6 +554,7 @@ public static List convertLogAddressToTronAddress(TransactionInfo transacti * Validate parameters for trigger constant and estimate energy * - Rule-1: owner address must be set * - Rule-2: either contract address is set or call data is set + * - Rule-3: if try to deploy, function selector and call data can not be both set * @param contract parameters in json format * @throws InvalidParameterException if validation is not passed, this kind of exception is thrown */ @@ -567,6 +568,12 @@ public static void validateParameter(String contract) throws InvalidParameterExc throw new InvalidParameterException("At least one of " + CONTRACT_ADDRESS + " and " + CALL_DATA + " must be set."); } + if (StringUtils.isEmpty(jsonObject.getString(CONTRACT_ADDRESS)) + && !StringUtils.isEmpty(jsonObject.getString(FUNCTION_SELECTOR)) + && !StringUtils.isEmpty(jsonObject.getString(CALL_DATA))) { + throw new InvalidParameterException("While trying to deploy, " + + FUNCTION_SELECTOR + " and " + CALL_DATA + " can not be both set."); + } } } From 495f7ac69bc32252c57da8610c09ccab4ecd42dc Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 3 Apr 2023 18:54:58 +0800 Subject: [PATCH 0712/1197] func(interface): drop rule-3 for trigger contract --- .../tron/core/services/http/TriggerSmartContractServlet.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java b/framework/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java index d8f142edb46..6577a9e5f24 100644 --- a/framework/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java @@ -41,11 +41,6 @@ private void validateParameter(String contract) { if (StringUtil.isNullOrEmpty(jsonObject.getString(Util.CONTRACT_ADDRESS))) { throw new InvalidParameterException(Util.CONTRACT_ADDRESS + " isn't set."); } - if (!StringUtil.isNullOrEmpty(jsonObject.getString(Util.FUNCTION_SELECTOR)) - ^ StringUtil.isNullOrEmpty(jsonObject.getString(Util.CALL_DATA))) { - throw new InvalidParameterException("Only one of " - + Util.FUNCTION_SELECTOR + " and " + Util.CALL_DATA + " can be set."); - } } protected void doPost(HttpServletRequest request, HttpServletResponse response) From 78b46c3ed411764f7f103ddb8d0e695ad360b38f Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 3 Apr 2023 19:29:25 +0800 Subject: [PATCH 0713/1197] log(vm): reduce exception log level of featured instructions from error to warn --- .../org/tron/core/vm/program/Program.java | 43 +++++++++---------- .../src/main/java/org/tron/core/Wallet.java | 6 +-- .../org/tron/core/services/RpcApiService.java | 4 +- 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 3a0aaf21f70..90a59f53a36 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -17,7 +17,6 @@ import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; - import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @@ -1815,9 +1814,9 @@ public boolean freeze(DataWord receiverAddress, DataWord frozenBalance, DataWord repository.commit(); return true; } catch (ContractValidateException e) { - logger.error("TVM Freeze: validate failure. Reason: {}", e.getMessage()); + logger.warn("TVM Freeze: validate failure. Reason: {}", e.getMessage()); } catch (ArithmeticException e) { - logger.error("TVM Freeze: frozenBalance out of long range."); + logger.warn("TVM Freeze: frozenBalance out of long range."); } if (internalTx != null) { internalTx.reject(); @@ -1848,7 +1847,7 @@ public boolean unfreeze(DataWord receiverAddress, DataWord resourceType) { } return true; } catch (ContractValidateException e) { - logger.error("TVM Unfreeze: validate failure. Reason: {}", e.getMessage()); + logger.warn("TVM Unfreeze: validate failure. Reason: {}", e.getMessage()); } if (internalTx != null) { internalTx.reject(); @@ -1911,9 +1910,9 @@ public boolean freezeBalanceV2(DataWord frozenBalance, DataWord resourceType) { repository.commit(); return true; } catch (ContractValidateException e) { - logger.error("TVM FreezeBalanceV2: validate failure. Reason: {}", e.getMessage()); + logger.warn("TVM FreezeBalanceV2: validate failure. Reason: {}", e.getMessage()); } catch (ArithmeticException e) { - logger.error("TVM FreezeBalanceV2: frozenBalance out of long range."); + logger.warn("TVM FreezeBalanceV2: frozenBalance out of long range."); } if (internalTx != null) { internalTx.reject(); @@ -1947,9 +1946,9 @@ public boolean unfreezeBalanceV2(DataWord unfreezeBalance, DataWord resourceType } return true; } catch (ContractValidateException e) { - logger.error("TVM UnfreezeBalanceV2: validate failure. Reason: {}", e.getMessage()); + logger.warn("TVM UnfreezeBalanceV2: validate failure. Reason: {}", e.getMessage()); } catch (ArithmeticException e) { - logger.error("TVM UnfreezeBalanceV2: balance out of long range."); + logger.warn("TVM UnfreezeBalanceV2: balance out of long range."); } if (internalTx != null) { internalTx.reject(); @@ -1978,9 +1977,9 @@ public long withdrawExpireUnfreeze() { } return expireUnfreezeBalance; } catch (ContractValidateException e) { - logger.error("TVM WithdrawExpireUnfreeze: validate failure. Reason: {}", e.getMessage()); + logger.warn("TVM WithdrawExpireUnfreeze: validate failure. Reason: {}", e.getMessage()); } catch (ContractExeException e) { - logger.error("TVM WithdrawExpireUnfreeze: execute failure. Reason: {}", e.getMessage()); + logger.warn("TVM WithdrawExpireUnfreeze: execute failure. Reason: {}", e.getMessage()); } if (internalTx != null) { internalTx.reject(); @@ -2011,9 +2010,9 @@ public boolean cancelAllUnfreezeV2Action() { } return true; } catch (ContractValidateException e) { - logger.error("TVM CancelAllUnfreezeV2: validate failure. Reason: {}", e.getMessage()); + logger.warn("TVM CancelAllUnfreezeV2: validate failure. Reason: {}", e.getMessage()); } catch (ContractExeException e) { - logger.error("TVM CancelAllUnfreezeV2: execute failure. Reason: {}", e.getMessage()); + logger.warn("TVM CancelAllUnfreezeV2: execute failure. Reason: {}", e.getMessage()); } if (internalTx != null) { internalTx.reject(); @@ -2045,9 +2044,9 @@ public boolean delegateResource( repository.commit(); return true; } catch (ContractValidateException e) { - logger.error("TVM DelegateResource: validate failure. Reason: {}", e.getMessage()); + logger.warn("TVM DelegateResource: validate failure. Reason: {}", e.getMessage()); } catch (ArithmeticException e) { - logger.error("TVM DelegateResource: balance out of long range."); + logger.warn("TVM DelegateResource: balance out of long range."); } if (internalTx != null) { internalTx.reject(); @@ -2079,9 +2078,9 @@ public boolean unDelegateResource( repository.commit(); return true; } catch (ContractValidateException e) { - logger.error("TVM UnDelegateResource: validate failure. Reason: {}", e.getMessage()); + logger.warn("TVM UnDelegateResource: validate failure. Reason: {}", e.getMessage()); } catch (ArithmeticException e) { - logger.error("TVM UnDelegateResource: balance out of long range."); + logger.warn("TVM UnDelegateResource: balance out of long range."); } if (internalTx != null) { internalTx.reject(); @@ -2114,7 +2113,7 @@ private Common.ResourceCode parseResourceCodeV2(DataWord resourceType) { return Common.ResourceCode.UNRECOGNIZED; } } catch (ArithmeticException e) { - logger.error("TVM ParseResourceCodeV2: invalid resource code: {}", resourceType.sValue()); + logger.warn("TVM ParseResourceCodeV2: invalid resource code: {}", resourceType.sValue()); return Common.ResourceCode.UNRECOGNIZED; } } @@ -2180,11 +2179,11 @@ public boolean voteWitness(int witnessArrayOffset, int witnessArrayLength, repository.commit(); return true; } catch (ContractValidateException e) { - logger.error("TVM VoteWitness: validate failure. Reason: {}", e.getMessage()); + logger.warn("TVM VoteWitness: validate failure. Reason: {}", e.getMessage()); } catch (ContractExeException e) { - logger.error("TVM VoteWitness: execute failure. Reason: {}", e.getMessage()); + logger.warn("TVM VoteWitness: execute failure. Reason: {}", e.getMessage()); } catch (ArithmeticException e) { - logger.error("TVM VoteWitness: int or long out of range. caused by: {}", e.getMessage()); + logger.warn("TVM VoteWitness: int or long out of range. caused by: {}", e.getMessage()); } if (internalTx != null) { internalTx.reject(); @@ -2213,9 +2212,9 @@ public long withdrawReward() { } return allowance; } catch (ContractValidateException e) { - logger.error("TVM WithdrawReward: validate failure. Reason: {}", e.getMessage()); + logger.warn("TVM WithdrawReward: validate failure. Reason: {}", e.getMessage()); } catch (ContractExeException e) { - logger.error("TVM WithdrawReward: execute failure. Reason: {}", e.getMessage()); + logger.warn("TVM WithdrawReward: execute failure. Reason: {}", e.getMessage()); } if (internalTx != null) { internalTx.reject(); diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 98b9c992f0d..adb6c26db5a 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -3029,7 +3029,7 @@ public Transaction callConstantContract(TransactionCapsule trxCap, if (!isEstimating && result.getException() != null || result.getException() instanceof Program.OutOfTimeException) { RuntimeException e = result.getException(); - logger.warn("Constant call has an error {}", e.getMessage()); + logger.warn("Constant call failed for reason: {}", e.getMessage()); throw e; } @@ -3866,7 +3866,7 @@ private boolean isShieldedTRC20NoteSpent(GrpcAPI.Note note, long pos, byte[] ak, retBuilder.setResult(false).setCode(response_code.CONTRACT_EXE_ERROR) .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); trxExtBuilder.setResult(retBuilder); - logger.warn("When run constant call in VM, have RuntimeException: " + e.getMessage()); + logger.warn("When run constant call in VM, failed for reason: " + e.getMessage()); } catch (Exception e) { retBuilder.setResult(false).setCode(response_code.OTHER_ERROR) .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); @@ -4130,7 +4130,7 @@ private byte[] getShieldedContractScalingFactor(byte[] contractAddress) retBuilder.setResult(false).setCode(response_code.CONTRACT_EXE_ERROR) .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); trxExtBuilder.setResult(retBuilder); - logger.warn("When run constant call in VM, have RuntimeException: " + e.getMessage()); + logger.warn("When run constant call in VM, failed for reason: " + e.getMessage()); } catch (Exception e) { retBuilder.setResult(false).setCode(response_code.OTHER_ERROR) .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index a6e1c5181ad..991124cc2ba 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -312,7 +312,7 @@ private void callContract(TriggerSmartContract request, retBuilder.setResult(false).setCode(response_code.CONTRACT_EXE_ERROR) .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); trxExtBuilder.setResult(retBuilder); - logger.warn("When run constant call in VM, have RuntimeException: " + e.getMessage()); + logger.warn("When run constant call in VM, failed for reason: " + e.getMessage()); } catch (Exception e) { retBuilder.setResult(false).setCode(response_code.OTHER_ERROR) .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); @@ -2077,7 +2077,7 @@ private void callContract(TriggerSmartContract request, retBuilder.setResult(false).setCode(response_code.CONTRACT_EXE_ERROR) .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); trxExtBuilder.setResult(retBuilder); - logger.warn("When run constant call in VM, have Runtime Exception: " + e.getMessage()); + logger.warn("When run constant call in VM, failed for reason: " + e.getMessage()); } catch (Exception e) { retBuilder.setResult(false).setCode(response_code.OTHER_ERROR) .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); From 77700b952c692a8ec944d23e9e51819de059651d Mon Sep 17 00:00:00 2001 From: Asuka Date: Tue, 4 Apr 2023 14:48:31 +0800 Subject: [PATCH 0714/1197] chore(vm): replace `ResourceCode error` with `Unknown ResourceCode` --- .../DelegateResourceProcessor.java | 2 +- .../FreezeBalanceProcessor.java | 2 +- .../FreezeBalanceV2Processor.java | 18 +++++++++--------- .../UnDelegateResourceProcessor.java | 19 +++++++++---------- .../UnfreezeBalanceProcessor.java | 8 ++++---- .../UnfreezeBalanceV2Processor.java | 6 +++--- 6 files changed, 27 insertions(+), 28 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index 66ea919d713..18eb543097b 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -96,7 +96,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra break; default: throw new ContractValidateException( - "ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]"); + "Unknown ResourceCode, valid ResourceCode[BANDWIDTH、ENERGY]"); } byte[] receiverAddress = param.getReceiverAddress(); diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceProcessor.java index 9a1af3c9cec..c5c8fa91344 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceProcessor.java @@ -48,7 +48,7 @@ public void validate(FreezeBalanceParam param, Repository repo) throws ContractV break; default: throw new ContractValidateException( - "ResourceCode error,valid ResourceCode[BANDWIDTH、ENERGY]"); + "Unknown ResourceCode, valid ResourceCode[BANDWIDTH、ENERGY]"); } // validate for delegating resource diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java index 2ab9fc451c2..b3dd258ae59 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java @@ -1,5 +1,11 @@ package org.tron.core.vm.nativecontract; +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; + import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; @@ -9,12 +15,6 @@ import org.tron.core.vm.nativecontract.param.FreezeBalanceV2Param; import org.tron.core.vm.repository.Repository; -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; -import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; -import static org.tron.protos.contract.Common.ResourceCode.ENERGY; - @Slf4j(topic = "VMProcessor") public class FreezeBalanceV2Processor { @@ -50,16 +50,16 @@ public void validate(FreezeBalanceV2Param param, Repository repo) throws Contrac case TRON_POWER: if (!repo.getDynamicPropertiesStore().supportAllowNewResourceModel()) { throw new ContractValidateException( - "ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]"); + "Unknown ResourceCode, valid ResourceCode[BANDWIDTH、ENERGY]"); } break; default: if (repo.getDynamicPropertiesStore().supportAllowNewResourceModel()) { throw new ContractValidateException( - "ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY、TRON_POWER]"); + "Unknown ResourceCode, valid ResourceCode[BANDWIDTH、ENERGY、TRON_POWER]"); } else { throw new ContractValidateException( - "ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]"); + "Unknown ResourceCode, valid ResourceCode[BANDWIDTH、ENERGY]"); } } } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index f4c18af85e5..d4cc2fcb8ce 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -1,6 +1,14 @@ package org.tron.core.vm.nativecontract; +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; + import com.google.common.primitives.Bytes; +import java.util.Arrays; +import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.tron.common.utils.DecodeUtil; @@ -17,15 +25,6 @@ import org.tron.core.vm.nativecontract.param.UnDelegateResourceParam; import org.tron.core.vm.repository.Repository; -import java.util.Arrays; -import java.util.Objects; - -import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; -import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; -import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; -import static org.tron.protos.contract.Common.ResourceCode.ENERGY; - @Slf4j(topic = "VMProcessor") public class UnDelegateResourceProcessor { @@ -84,7 +83,7 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont break; default: throw new ContractValidateException( - "ResourceCode error.valid ResourceCode[BANDWIDTH、ENERGY]"); + "Unknown ResourceCode, valid ResourceCode[BANDWIDTH、ENERGY]"); } } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceProcessor.java index 0eda888d3ca..211784d279b 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceProcessor.java @@ -65,8 +65,8 @@ public void validate(UnfreezeBalanceParam param, Repository repo) } break; default: - throw new ContractValidateException("ResourceCode error." - + "valid ResourceCode[BANDWIDTH、Energy]"); + throw new ContractValidateException("Unknown ResourceCode, " + + "valid ResourceCode[BANDWIDTH、ENERGY]"); } } else { switch (param.getResourceType()) { @@ -95,8 +95,8 @@ public void validate(UnfreezeBalanceParam param, Repository repo) } break; default: - throw new ContractValidateException("ResourceCode error." - + "valid ResourceCode[BANDWIDTH、Energy]"); + throw new ContractValidateException("Unknown ResourceCode, " + + "valid ResourceCode[BANDWIDTH、ENERGY]"); } } } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index f4d5c407373..56366bbdb0c 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -71,14 +71,14 @@ public void validate(UnfreezeBalanceV2Param param, Repository repo) throw new ContractValidateException("no frozenBalance(TRON_POWER)"); } } else { - throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、ENERGY]"); + throw new ContractValidateException("Unknown ResourceCode, valid ResourceCode[BANDWIDTH、ENERGY]"); } break; default: if (dynamicStore.supportAllowNewResourceModel()) { - throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、ENERGY、TRON_POWER]"); + throw new ContractValidateException("Unknown ResourceCode, valid ResourceCode[BANDWIDTH、ENERGY、TRON_POWER]"); } else { - throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、ENERGY]"); + throw new ContractValidateException("Unknown ResourceCode, valid ResourceCode[BANDWIDTH、ENERGY]"); } } From 26360b987c01f890bf532c56c45402afb0d1181c Mon Sep 17 00:00:00 2001 From: Asuka Date: Tue, 4 Apr 2023 19:00:23 +0800 Subject: [PATCH 0715/1197] test(interface): add http unit tests --- .../http/TriggerSmartContractServletTest.java | 105 ++++++++++++++++++ .../common/client/utils/HttpMethed.java | 11 +- 2 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java diff --git a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java new file mode 100644 index 00000000000..8e9b79dbb53 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java @@ -0,0 +1,105 @@ +package org.tron.core.services.http; + +import com.google.gson.JsonObject; +import java.io.File; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpResponse; +import org.bouncycastle.util.encoders.Hex; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.tron.common.application.Application; +import org.tron.common.application.ApplicationFactory; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.core.Constant; +import org.tron.core.capsule.ContractCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.store.StoreFactory; +import org.tron.core.vm.repository.Repository; +import org.tron.core.vm.repository.RepositoryImpl; +import org.tron.protos.Protocol; +import org.tron.protos.contract.SmartContractOuterClass; +import stest.tron.wallet.common.client.utils.HttpMethed; + +@Slf4j +public class TriggerSmartContractServletTest { + + private static String dbPath; + private static byte[] ownerAddr = Hex.decode("410000000000000000000000000000000000000000"); + private static byte[] contractAddr = Hex.decode("41000000000000000000000000000000000000dEaD"); + private static TronApplicationContext context; + + @BeforeClass + public static void init() throws Exception { + dbPath = "output_" + TriggerSmartContractServletTest.class.getName(); + Args.setParam( + new String[]{"--output-directory", dbPath, "--debug", "--witness"}, Constant.TEST_CONF); + Args.getInstance().needSyncCheck = false; + + // build app context + DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); + beanFactory.setAllowCircularReferences(false); + context = new TronApplicationContext(beanFactory); + context.register(DefaultConfig.class); + context.refresh(); + Application appT = ApplicationFactory.create(context); + + // register http service + FullNodeHttpApiService httpApiService = context.getBean(FullNodeHttpApiService.class); + appT.addService(httpApiService); + + // start services + appT.initServices(Args.getInstance()); + appT.startServices(); + appT.startup(); + + // create contract for testing + Repository rootRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); + rootRepository.createAccount(contractAddr, Protocol.AccountType.Contract); + rootRepository.createContract(contractAddr, new ContractCapsule( + SmartContractOuterClass.SmartContract.newBuilder().build())); + rootRepository.saveCode(contractAddr, Hex.decode( + "608060405260043610601c5760003560e01c8063f8a8fd6d146021575b600080fd5b60276029565b00" + + "5b3373ffffffffffffffffffffffffffffffffffffffff166108fc34908115029060405160006040518" + + "0830381858888f19350505050158015606e573d6000803e3d6000fd5b5056fea2646970667358221220" + + "45fe2c565cf16b27bb8cbafbe251a850a0bb5cd8806a186dbda12d57685ced6f64736f6c63430008120" + + "033")); + rootRepository.commit(); + } + + @AfterClass + public static void destroy() { + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.error("Release resources failure."); + } + } + + @Test + public void testNormalCall() throws Exception { + HttpMethed.waitToProduceOneBlock("127.0.0.1:8090"); + JsonObject parameter = new JsonObject(); + parameter.addProperty("owner_address", ByteArray.toHexString(ownerAddr)); + parameter.addProperty("contract_address", ByteArray.toHexString(contractAddr)); + parameter.addProperty("function_selector", "test()"); + invokeToLocal("triggersmartcontract", parameter); + invokeToLocal("triggerconstantcontract", parameter); + invokeToLocal("estimateenergy", parameter); + } + + public static HttpResponse invokeToLocal( + String method, JsonObject parameter) { + try { + final String requestUrl = "http://127.0.0.1:8090/wallet/" + method; + return HttpMethed.createConnect(requestUrl, parameter); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java index 8ef8fecbd8e..9aaa74938d8 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java +++ b/framework/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java @@ -8,14 +8,12 @@ import com.google.gson.JsonParser; import com.google.protobuf.ByteString; import io.netty.util.internal.StringUtil; - import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; - import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; @@ -2231,7 +2229,10 @@ public static void waitToProduceOneBlock(String httpNode) { responseContent = HttpMethed.parseResponseContent(response); responseContent = HttpMethed.parseStringContent(responseContent.get("block_header").toString()); responseContent = HttpMethed.parseStringContent(responseContent.get("raw_data").toString()); - Integer currentBlockNum = Integer.parseInt(responseContent.get("number").toString()); + Integer currentBlockNum = 0; + if (responseContent.containsKey("number")) { + currentBlockNum = Integer.parseInt(responseContent.get("number").toString()); + } Integer nextBlockNum = 0; Integer times = 0; while (nextBlockNum <= currentBlockNum + 1 && times++ <= 10) { @@ -2240,7 +2241,9 @@ public static void waitToProduceOneBlock(String httpNode) { responseContent = HttpMethed.parseStringContent(responseContent.get("block_header").toString()); responseContent = HttpMethed.parseStringContent(responseContent.get("raw_data").toString()); - nextBlockNum = Integer.parseInt(responseContent.get("number").toString()); + if (responseContent.containsKey("number")) { + nextBlockNum = Integer.parseInt(responseContent.get("number").toString()); + } try { Thread.sleep(1200); } catch (InterruptedException e) { From 4b12b178cef2188164257c0051d008e0a54f9796 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 6 Apr 2023 14:52:57 +0800 Subject: [PATCH 0716/1197] feat(net): update libp2p with latest grpc --- build.gradle | 12 +++++++++--- common/build.gradle | 6 +++++- .../org/tron/common/client/DatabaseGrpcClient.java | 4 ++-- .../org/tron/common/client/WalletGrpcClient.java | 4 ++-- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index 427ea071d57..490348dd559 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ subprojects { annotationProcessor 'org.projectlombok:lombok:1.18.12' testCompileOnly 'org.projectlombok:lombok:1.18.12' testAnnotationProcessor 'org.projectlombok:lombok:1.18.12' - compile group: 'com.google.guava', name: 'guava', version: '24.1-jre' + compile group: 'com.google.guava', name: 'guava', version: '30.1-jre' compile "com.google.code.findbugs:jsr305:3.0.0" compile group: 'org.springframework', name: 'spring-context', version: '5.3.18' compile group: 'org.springframework', name: 'spring-tx', version: '5.3.18' @@ -67,8 +67,14 @@ subprojects { } configurations.all { - resolutionStrategy { - force group: 'com.google.guava', name: 'guava', version: '30.1-jre' + resolutionStrategy.eachDependency { details -> + if (details.requested.group == 'com.google.guava' && details.requested.name == 'guava') { + details.useVersion "30.1-jre" + } + // TODO if update grpc remove + if(details.requested.group == 'io.netty') { + details.useVersion "4.1.27.Final" + } } } } diff --git a/common/build.gradle b/common/build.gradle index 5c70edf0b65..e81a2ceae85 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,11 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.20' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-grpc-v2-1',{ + exclude group: 'io.grpc', module: 'grpc-context' + exclude group: 'io.grpc', module: 'grpc-core' + exclude group: 'io.grpc', module: 'grpc-netty' + } compile project(":protocol") } diff --git a/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java b/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java index b83c7235900..f3650bfd2be 100644 --- a/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java +++ b/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java @@ -15,14 +15,14 @@ public class DatabaseGrpcClient { public DatabaseGrpcClient(String host, int port) { channel = ManagedChannelBuilder.forAddress(host, port) - .usePlaintext(true) + .usePlaintext() .build(); databaseBlockingStub = DatabaseGrpc.newBlockingStub(channel); } public DatabaseGrpcClient(String host) { channel = ManagedChannelBuilder.forTarget(host) - .usePlaintext(true) + .usePlaintext() .build(); databaseBlockingStub = DatabaseGrpc.newBlockingStub(channel); } diff --git a/framework/src/main/java/org/tron/common/client/WalletGrpcClient.java b/framework/src/main/java/org/tron/common/client/WalletGrpcClient.java index 9d3b5797e20..d28df0e7c77 100644 --- a/framework/src/main/java/org/tron/common/client/WalletGrpcClient.java +++ b/framework/src/main/java/org/tron/common/client/WalletGrpcClient.java @@ -29,14 +29,14 @@ public class WalletGrpcClient { public WalletGrpcClient(String host, int port) { channel = ManagedChannelBuilder.forAddress(host, port) - .usePlaintext(true) + .usePlaintext() .build(); walletBlockingStub = WalletGrpc.newBlockingStub(channel); } public WalletGrpcClient(String host) { channel = ManagedChannelBuilder.forTarget(host) - .usePlaintext(true) + .usePlaintext() .build(); walletBlockingStub = WalletGrpc.newBlockingStub(channel); } From cfd4fbd62bcf9b81545cf119d6f1a1137734cf04 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 6 Apr 2023 15:57:20 +0800 Subject: [PATCH 0717/1197] fix(net): update libp2p version --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index e81a2ceae85..2ffc1f82f16 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-grpc-v2-1',{ + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-grpc-v2-2',{ exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' From 42e0ab35e96620ab346a3bd052a43a88df1a45c6 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 6 Apr 2023 17:54:00 +0800 Subject: [PATCH 0718/1197] fix(net): update libp2p to test-v0.2.21 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 2ffc1f82f16..47d8a1302c7 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-grpc-v2-2',{ + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.21',{ exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' From 78130633f13997111ac7b95a595f2a959a9fcf12 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 7 Apr 2023 17:32:16 +0800 Subject: [PATCH 0719/1197] fix(net):revert DatabaseGrpcClient WalletGrpcClient --- .../main/java/org/tron/common/client/DatabaseGrpcClient.java | 4 ++-- .../main/java/org/tron/common/client/WalletGrpcClient.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java b/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java index f3650bfd2be..b83c7235900 100644 --- a/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java +++ b/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java @@ -15,14 +15,14 @@ public class DatabaseGrpcClient { public DatabaseGrpcClient(String host, int port) { channel = ManagedChannelBuilder.forAddress(host, port) - .usePlaintext() + .usePlaintext(true) .build(); databaseBlockingStub = DatabaseGrpc.newBlockingStub(channel); } public DatabaseGrpcClient(String host) { channel = ManagedChannelBuilder.forTarget(host) - .usePlaintext() + .usePlaintext(true) .build(); databaseBlockingStub = DatabaseGrpc.newBlockingStub(channel); } diff --git a/framework/src/main/java/org/tron/common/client/WalletGrpcClient.java b/framework/src/main/java/org/tron/common/client/WalletGrpcClient.java index d28df0e7c77..9d3b5797e20 100644 --- a/framework/src/main/java/org/tron/common/client/WalletGrpcClient.java +++ b/framework/src/main/java/org/tron/common/client/WalletGrpcClient.java @@ -29,14 +29,14 @@ public class WalletGrpcClient { public WalletGrpcClient(String host, int port) { channel = ManagedChannelBuilder.forAddress(host, port) - .usePlaintext() + .usePlaintext(true) .build(); walletBlockingStub = WalletGrpc.newBlockingStub(channel); } public WalletGrpcClient(String host) { channel = ManagedChannelBuilder.forTarget(host) - .usePlaintext() + .usePlaintext(true) .build(); walletBlockingStub = WalletGrpc.newBlockingStub(channel); } From 9c2208bfcfa1cef7e71189adbc8e3d15eb5c04d5 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 7 Apr 2023 19:24:48 +0800 Subject: [PATCH 0720/1197] fix(net): exclude com.google.protobuf from libp2p --- common/build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/build.gradle b/common/build.gradle index 47d8a1302c7..86f9b328184 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -57,6 +57,8 @@ dependencies { exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' + exclude group: 'com.google.protobuf', module: 'protobuf-java' + exclude group: 'com.google.protobuf', module: 'protobuf-java-util' } compile project(":protocol") } From 5fc0c7879933736951e4d6f1ff97288c30d83fd7 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 7 Apr 2023 20:16:45 +0800 Subject: [PATCH 0721/1197] fix(net): optimize build.gradle --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 490348dd559..a4d23e2184e 100644 --- a/build.gradle +++ b/build.gradle @@ -67,10 +67,10 @@ subprojects { } configurations.all { + resolutionStrategy { + force group: 'com.google.guava', name: 'guava', version: '30.1-jre' + } resolutionStrategy.eachDependency { details -> - if (details.requested.group == 'com.google.guava' && details.requested.name == 'guava') { - details.useVersion "30.1-jre" - } // TODO if update grpc remove if(details.requested.group == 'io.netty') { details.useVersion "4.1.27.Final" From 9fbc009c3320883d14085f6f7b2f34a4d692a817 Mon Sep 17 00:00:00 2001 From: Asuka Date: Sat, 8 Apr 2023 21:21:06 +0800 Subject: [PATCH 0722/1197] fix(receipt): reset origin energy usage to avoid the dirty record --- .../java/org/tron/core/capsule/ReceiptCapsule.java | 6 ++++++ .../org/tron/core/store/TransactionRetStore.java | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index eb6bcd48d84..2cef21e7617 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -192,6 +192,12 @@ public void payEnergyBill(DynamicPropertiesStore dynamicPropertiesStore, AccountCapsule caller, long percent, long originEnergyLimit, EnergyProcessor energyProcessor, long now) throws BalanceInsufficientException { + + // Reset origin energy usage here! Because after stake 2.0, this field are reused for + // recording pre-merge frozen energy for origin account. If total energy usage is zero, this + // field will be a dirty record. + this.setOriginEnergyUsage(0); + if (receipt.getEnergyUsageTotal() <= 0) { return; } diff --git a/chainbase/src/main/java/org/tron/core/store/TransactionRetStore.java b/chainbase/src/main/java/org/tron/core/store/TransactionRetStore.java index 249523de5a4..8de82c98cf9 100644 --- a/chainbase/src/main/java/org/tron/core/store/TransactionRetStore.java +++ b/chainbase/src/main/java/org/tron/core/store/TransactionRetStore.java @@ -14,6 +14,7 @@ import org.tron.core.db.TransactionStore; import org.tron.core.db.TronStoreWithRevoking; import org.tron.core.exception.BadItemException; +import org.tron.protos.Protocol; import org.tron.protos.Protocol.TransactionInfo; @Slf4j(topic = "DB") @@ -54,6 +55,17 @@ public TransactionInfoCapsule getTransactionInfo(byte[] key) throws BadItemExcep ByteString id = ByteString.copyFrom(key); for (TransactionInfo transactionResultInfo : result.getInstance().getTransactioninfoList()) { if (transactionResultInfo.getId().equals(id)) { + Protocol.ResourceReceipt receipt = transactionResultInfo.getReceipt(); + // If query a result with dirty origin usage in receipt, we just reset it. + if (receipt.getEnergyPenaltyTotal() == 0 && receipt.getOriginEnergyUsage() > 0) { + transactionResultInfo = + transactionResultInfo.toBuilder() + .setReceipt( + receipt.toBuilder() + .clearOriginEnergyUsage() + .build()) + .build(); + } return new TransactionInfoCapsule(transactionResultInfo); } } From 81d31dd97179541de129be9c82e02b83c0242639 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Sun, 9 Apr 2023 22:00:36 +0800 Subject: [PATCH 0723/1197] fix(net): try to remove shield in test case --- .../org/tron/core/services/filter/HttpApiAccessFilterTest.java | 2 +- .../tron/core/services/filter/LiteFnQueryHttpFilterTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java b/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java index dcf56c18ae9..63e215f87af 100644 --- a/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java @@ -50,7 +50,7 @@ public class HttpApiAccessFilterTest { @BeforeClass public static void init() { Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - Args.getInstance().setFullNodeAllowShieldedTransactionArgs(false); + //Args.getInstance().setFullNodeAllowShieldedTransactionArgs(false); context = new TronApplicationContext(DefaultConfig.class); appTest = ApplicationFactory.create(context); httpApiAccessFilter = context.getBean(HttpApiAccessFilter.class); diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java index b63ebc9caed..87e124725dc 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java @@ -51,7 +51,7 @@ public class LiteFnQueryHttpFilterTest { @Before public void init() { Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - Args.getInstance().setFullNodeAllowShieldedTransactionArgs(false); + //Args.getInstance().setFullNodeAllowShieldedTransactionArgs(false); context = new TronApplicationContext(DefaultConfig.class); appTest = ApplicationFactory.create(context); FullNodeHttpApiService httpApiService = context From 3e1298c7d9bef89afc2bc4e535be45eddd1003b5 Mon Sep 17 00:00:00 2001 From: guoquanwu Date: Fri, 7 Apr 2023 20:26:18 +0800 Subject: [PATCH 0724/1197] feature(test): use random port in unit test --- .../org/tron/common/utils/PublicMethod.java | 29 +++++++++++++++++-- .../filter/LiteFnQueryHttpFilterTest.java | 6 +++- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/framework/src/test/java/org/tron/common/utils/PublicMethod.java b/framework/src/test/java/org/tron/common/utils/PublicMethod.java index 3c945b47530..b6e8f661b2c 100644 --- a/framework/src/test/java/org/tron/common/utils/PublicMethod.java +++ b/framework/src/test/java/org/tron/common/utils/PublicMethod.java @@ -1,7 +1,11 @@ package org.tron.common.utils; import com.google.protobuf.ByteString; + +import java.io.IOException; import java.math.BigInteger; +import java.net.InetAddress; +import java.net.Socket; import java.util.Random; import org.tron.api.GrpcAPI; @@ -105,11 +109,30 @@ public static GrpcAPI.Return broadcastTransaction( return response; } + public static int chooseRandomPort() { + return chooseRandomPort(10240, 65000); + } + public static int chooseRandomPort(int min, int max) { - return new Random().nextInt(max - min + 1) + min; + int port = new Random().nextInt(max - min + 1) + min; + try { + while (!checkPortAvailable(port)) { + port = new Random().nextInt(max - min + 1) + min; + } + } catch (IOException e) { + return new Random().nextInt(max - min + 1) + min; + } + return port; } - public static int chooseRandomPort() { - return new Random().nextInt(65530 - 1024) + 1024; + private static boolean checkPortAvailable(int port) throws IOException { + InetAddress theAddress = InetAddress.getByName("127.0.0.1"); + try (Socket socket = new Socket(theAddress, port)) { + // only check + socket.getPort(); + } catch (IOException e) { + return true; + } + return false; } } diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java index b63ebc9caed..660cb521fc4 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java @@ -23,6 +23,7 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.utils.FileUtil; +import org.tron.common.utils.PublicMethod; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; @@ -50,8 +51,11 @@ public class LiteFnQueryHttpFilterTest { */ @Before public void init() { - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath, "--p2p-disable", "true"}, Constant.TEST_CONF); Args.getInstance().setFullNodeAllowShieldedTransactionArgs(false); + Args.getInstance().setFullNodeHttpPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setSolidityHttpPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setPBFTHttpPort(PublicMethod.chooseRandomPort()); context = new TronApplicationContext(DefaultConfig.class); appTest = ApplicationFactory.create(context); FullNodeHttpApiService httpApiService = context From e9a34f44fbe896a58d2e393b6ebc4ece75ddf2a2 Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 10 Apr 2023 11:29:04 +0800 Subject: [PATCH 0725/1197] fix(receipt): use the right energy total --- .../src/main/java/org/tron/core/store/TransactionRetStore.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainbase/src/main/java/org/tron/core/store/TransactionRetStore.java b/chainbase/src/main/java/org/tron/core/store/TransactionRetStore.java index 8de82c98cf9..a22e69e8692 100644 --- a/chainbase/src/main/java/org/tron/core/store/TransactionRetStore.java +++ b/chainbase/src/main/java/org/tron/core/store/TransactionRetStore.java @@ -57,7 +57,7 @@ public TransactionInfoCapsule getTransactionInfo(byte[] key) throws BadItemExcep if (transactionResultInfo.getId().equals(id)) { Protocol.ResourceReceipt receipt = transactionResultInfo.getReceipt(); // If query a result with dirty origin usage in receipt, we just reset it. - if (receipt.getEnergyPenaltyTotal() == 0 && receipt.getOriginEnergyUsage() > 0) { + if (receipt.getEnergyUsageTotal() == 0 && receipt.getOriginEnergyUsage() > 0) { transactionResultInfo = transactionResultInfo.toBuilder() .setReceipt( From da14f79143c4afa22952afad969e3350e1a23f8d Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 10 Apr 2023 14:36:34 +0800 Subject: [PATCH 0726/1197] feat(net): optimize the acquisition of the ip address of the GRPC interface --- .../java/org/tron/core/services/ratelimiter/RuntimeData.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/ratelimiter/RuntimeData.java b/framework/src/main/java/org/tron/core/services/ratelimiter/RuntimeData.java index 0f3c78b18d8..7cbadbc5435 100644 --- a/framework/src/main/java/org/tron/core/services/ratelimiter/RuntimeData.java +++ b/framework/src/main/java/org/tron/core/services/ratelimiter/RuntimeData.java @@ -2,6 +2,7 @@ import io.grpc.Grpc; import io.grpc.ServerCall; +import java.net.InetSocketAddress; import javax.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; @@ -16,7 +17,9 @@ public RuntimeData(Object o) { address = ((HttpServletRequest) o).getRemoteAddr(); } else if (o instanceof ServerCall) { try { - address = ((ServerCall) o).getAttributes().get(Grpc.TRANSPORT_ATTR_REMOTE_ADDR).toString(); + InetSocketAddress s = (InetSocketAddress) + ((ServerCall) o).getAttributes().get(Grpc.TRANSPORT_ATTR_REMOTE_ADDR); + address = s.getAddress().getHostAddress(); } catch (Exception npe) { logger.warn("the address get from the runtime data is a null value unexpected."); } From 150dd39abfcef3af5e0817d40fb406538eccb0ed Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 10 Apr 2023 16:59:54 +0800 Subject: [PATCH 0727/1197] fix(net): optimize NodeTest --- .../src/main/java/org/tron/core/config/args/Args.java | 6 +++++- framework/src/test/java/org/tron/core/net/NodeTest.java | 8 +++++++- .../java/org/tron/core/zksnark/SendCoinShieldTest.java | 2 ++ framework/src/test/resources/config-test.conf | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index a44e79ae5aa..19962fbac8e 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1335,7 +1335,12 @@ public static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Confi if (config.hasPath(Constant.NODE_DNS_PUBLISH)) { publishConfig.setDnsPublishEnable(config.getBoolean(Constant.NODE_DNS_PUBLISH)); } + loadDnsPublishParameters(config, publishConfig); + return publishConfig; + } + public static void loadDnsPublishParameters(final com.typesafe.config.Config config, + PublishConfig publishConfig) { if (publishConfig.isDnsPublishEnable()) { if (config.hasPath(Constant.NODE_DNS_DOMAIN) && StringUtils.isNotEmpty( config.getString(Constant.NODE_DNS_DOMAIN))) { @@ -1427,7 +1432,6 @@ public static PublishConfig loadDnsPublishConfig(final com.typesafe.config.Confi } } } - return publishConfig; } private static void logEmptyError(String arg) { diff --git a/framework/src/test/java/org/tron/core/net/NodeTest.java b/framework/src/test/java/org/tron/core/net/NodeTest.java index 421b93f589a..623c24d6040 100644 --- a/framework/src/test/java/org/tron/core/net/NodeTest.java +++ b/framework/src/test/java/org/tron/core/net/NodeTest.java @@ -79,7 +79,13 @@ public void testEndpointFromNode() { @Test public void testPublishConfig() { Config config = Configuration.getByFileName(Constant.TEST_CONF, Constant.TEST_CONF); - PublishConfig publishConfig = Args.loadDnsPublishConfig(config); + + PublishConfig publishConfig = new PublishConfig(); + Assert.assertFalse(publishConfig.isDnsPublishEnable()); + + publishConfig.setDnsPublishEnable(true); + Assert.assertTrue(publishConfig.isDnsPublishEnable()); + Args.loadDnsPublishParameters(config, publishConfig); Assert.assertTrue(publishConfig.isDnsPublishEnable()); Assert.assertEquals(5, publishConfig.getMaxMergeSize()); Assert.assertEquals(DnsType.AwsRoute53, publishConfig.getDnsType()); diff --git a/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java b/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java index 1eb5becffb6..96ff338d3ce 100644 --- a/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java @@ -126,6 +126,8 @@ public class SendCoinShieldTest { */ @BeforeClass public static void init() { + FileUtil.deleteDir(new File(dbPath)); + dbManager = context.getBean(Manager.class); wallet = context.getBean(Wallet.class); //init energy diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index 76e99c8d4a1..c9602ef977b 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -114,7 +114,7 @@ node { ] # enable or disable dns publish, default false - publish = true + publish = false # dns domain to publish nodes, required if publish is true dnsDomain = "nodes1.example.org" From 2e38098cae993154c7521b45394d43ca9069be56 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 10 Apr 2023 18:09:38 +0800 Subject: [PATCH 0728/1197] fix(net): optimize new test case --- framework/src/test/java/org/tron/core/net/NodeTest.java | 6 ++++++ .../core/net/services/EffectiveCheckServiceTest.java | 1 + .../java/org/tron/core/net/services/SyncServiceTest.java | 1 + .../services/http/TriggerSmartContractServletTest.java | 9 ++++----- .../core/services/ratelimiter/GlobalRateLimiterTest.java | 6 ++++++ 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/framework/src/test/java/org/tron/core/net/NodeTest.java b/framework/src/test/java/org/tron/core/net/NodeTest.java index 623c24d6040..5f0e2c38b2b 100644 --- a/framework/src/test/java/org/tron/core/net/NodeTest.java +++ b/framework/src/test/java/org/tron/core/net/NodeTest.java @@ -9,6 +9,7 @@ import java.util.HashSet; import java.util.Set; import lombok.extern.slf4j.Slf4j; +import org.junit.After; import org.junit.Assert; import org.junit.Test; import org.tron.core.Constant; @@ -90,4 +91,9 @@ public void testPublishConfig() { Assert.assertEquals(5, publishConfig.getMaxMergeSize()); Assert.assertEquals(DnsType.AwsRoute53, publishConfig.getDnsType()); } + + @After + public void destroy() { + Args.clearParam(); + } } diff --git a/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java b/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java index eb517df23a7..5f68be84251 100644 --- a/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java @@ -33,6 +33,7 @@ public void init() { @After public void destroy() { Args.clearParam(); + context.destroy(); FileUtil.deleteDir(new File(dbPath)); } diff --git a/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java b/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java index 8493b1785be..fd2bb5dd017 100644 --- a/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java @@ -44,6 +44,7 @@ public void init() { @After public void destroy() { Args.clearParam(); + context.destroy(); FileUtil.deleteDir(new File(dbPath)); } diff --git a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java index 8e9b79dbb53..1fdf884eab6 100644 --- a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java @@ -73,13 +73,12 @@ public static void init() throws Exception { @AfterClass public static void destroy() { - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.error("Release resources failure."); - } + Args.clearParam(); + context.destroy(); + FileUtil.deleteDir(new File(dbPath)); } + @Test public void testNormalCall() throws Exception { HttpMethed.waitToProduceOneBlock("127.0.0.1:8090"); diff --git a/framework/src/test/java/org/tron/core/services/ratelimiter/GlobalRateLimiterTest.java b/framework/src/test/java/org/tron/core/services/ratelimiter/GlobalRateLimiterTest.java index 3187ed36792..b2f4915df1e 100644 --- a/framework/src/test/java/org/tron/core/services/ratelimiter/GlobalRateLimiterTest.java +++ b/framework/src/test/java/org/tron/core/services/ratelimiter/GlobalRateLimiterTest.java @@ -1,6 +1,7 @@ package org.tron.core.services.ratelimiter; import java.lang.reflect.Field; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Test; import org.tron.core.Constant; @@ -19,4 +20,9 @@ public void testAcquire() throws Exception { Assert.assertEquals(runtimeData.getRemoteAddr(), "127.0.0.1"); GlobalRateLimiter.acquire(runtimeData); } + + @AfterClass + public static void destroy() { + Args.clearParam(); + } } \ No newline at end of file From 84b011663e3eeb52f3e87451146eb1a062237733 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Mon, 10 Apr 2023 18:11:53 +0800 Subject: [PATCH 0729/1197] fix(freezeV2): optimize the query return of the interface --- framework/src/main/java/org/tron/core/Wallet.java | 11 +++++++++-- framework/src/test/java/org/tron/core/WalletTest.java | 11 ++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 6d9b12608c5..d07e2e6c9bf 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -765,19 +765,26 @@ public DelegatedResourceList getDelegatedResourceV2( .createDbKeyV2(fromAddress.toByteArray(), toAddress.toByteArray(), false); DelegatedResourceCapsule unlockResource = chainBaseManager.getDelegatedResourceStore() .get(dbKey); - if (unlockResource != null) { + if (nonEmptyResource(unlockResource)) { builder.addDelegatedResource(unlockResource.getInstance()); } dbKey = DelegatedResourceCapsule .createDbKeyV2(fromAddress.toByteArray(), toAddress.toByteArray(), true); DelegatedResourceCapsule lockResource = chainBaseManager.getDelegatedResourceStore() .get(dbKey); - if (lockResource != null) { + if (nonEmptyResource(lockResource)) { builder.addDelegatedResource(lockResource.getInstance()); } return builder.build(); } + private boolean nonEmptyResource(DelegatedResourceCapsule resource) { + return Objects.nonNull(resource) && !(resource.getExpireTimeForBandwidth() == 0 + && resource.getExpireTimeForEnergy() == 0 + && resource.getFrozenBalanceForBandwidth() == 0 + && resource.getFrozenBalanceForEnergy() == 0); + } + public GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage getCanWithdrawUnfreezeAmount( ByteString ownerAddress, long timestamp) { GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage.Builder builder = diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 41afd1b0c8e..4c0545f3c78 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -728,7 +728,7 @@ private Any getLockedDelegateContractForBandwidth(String ownerAddress, String re .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiveAddress))) .setBalance(unfreezeBalance) - .setResource(Common.ResourceCode.BANDWIDTH) + .setResource(BANDWIDTH) .setLock(lock) .build()); } @@ -753,6 +753,11 @@ public void testGetDelegatedResourceV2() { ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); + Protocol.Account account = Protocol.Account.newBuilder() + .setAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))).build(); + wallet.getAccount(account); + wallet.getProposalList(); + wallet.getWitnessList(); Assert.assertEquals(1L, delegatedResourceList.getDelegatedResourceCount()); Assert.assertEquals(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), delegatedResourceList.getDelegatedResource(0).getFrom()); @@ -809,7 +814,7 @@ public void testGetCanDelegatedMaxSizeBandWidth() { GrpcAPI.CanDelegatedMaxSizeResponseMessage message = wallet.getCanDelegatedMaxSize( ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), - Common.ResourceCode.BANDWIDTH.getNumber()); + BANDWIDTH.getNumber()); Assert.assertEquals(initBalance - 280L, message.getMaxSize()); } @@ -832,7 +837,7 @@ private Any getContractForBandwidthV2(String ownerAddress, long unfreezeBalance) ByteString.copyFrom(ByteArray.fromHexString(ownerAddress)) ) .setUnfreezeBalance(unfreezeBalance) - .setResource(Common.ResourceCode.BANDWIDTH) + .setResource(BANDWIDTH) .build() ); } From 043fdbf217fe4540dfc9cefdb1f7bc9e4fdb6fdd Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 10 Apr 2023 20:25:21 +0800 Subject: [PATCH 0730/1197] opt(receipt): use program result to check transaction execution result --- chainbase/src/main/java/org/tron/core/db/TransactionTrace.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java index 84b22adf0d9..c239639f019 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java @@ -255,7 +255,7 @@ public void pay() throws BalanceInsufficientException { AccountCapsule origin = accountStore.get(originAccount); AccountCapsule caller = accountStore.get(callerAccount); if (dynamicPropertiesStore.supportUnfreezeDelay() - && receipt.getReceipt().getResult().equals(contractResult.SUCCESS)) { + && getRuntimeResult().getException() == null && !getRuntimeResult().isRevert()) { // just fo caller is not origin, we set the related field for origin account if (origin != null && !caller.getAddress().equals(origin.getAddress())) { From 36e9e10b4142ff9366c18c0de7960d446c2a1aa1 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 10 Apr 2023 17:09:45 +0800 Subject: [PATCH 0731/1197] refactor(log):downgrade certain log level in some files --- .../tron/core/capsule/TransactionCapsule.java | 4 ++-- .../src/main/java/org/tron/core/Wallet.java | 23 ++++++++++--------- .../main/java/org/tron/core/db/Manager.java | 2 +- .../org/tron/core/services/http/Util.java | 2 +- .../core/services/jsonrpc/JsonRpcApiUtil.java | 2 +- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java index 1b6bf0722d4..a33f445c15f 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -333,13 +333,13 @@ public static byte[] getOwner(Transaction.Contract contract) { Class clazz = TransactionFactory .getContract(contract.getType()); if (clazz == null) { - logger.error("not exist {}", contract.getType()); + logger.warn("not exist {}", contract.getType()); return new byte[0]; } GeneratedMessageV3 generatedMessageV3 = contractParameter.unpack(clazz); owner = ReflectUtils.getFieldValue(generatedMessageV3, OWNER_ADDRESS); if (owner == null) { - logger.error("not exist [{}] field,{}", OWNER_ADDRESS, clazz); + logger.warn("not exist [{}] field,{}", OWNER_ADDRESS, clazz); return new byte[0]; } break; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index f6b48e68509..02d1d1d2f9f 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -110,6 +110,7 @@ import org.tron.common.utils.ByteUtil; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.Sha256Hash; +import org.tron.common.utils.StringUtil; import org.tron.common.utils.Utils; import org.tron.common.utils.WalletUtil; import org.tron.common.zksnark.IncrementalMerkleTreeContainer; @@ -583,7 +584,7 @@ public GrpcAPI.Return broadcastTransaction(Transaction signedTransaction) { .setMessage(ByteString.copyFromUtf8("Transaction expired")) .build(); } catch (Exception e) { - logger.error(BROADCAST_TRANS_FAILED, txID, e.getMessage()); + logger.warn("Broadcast transaction {} failed", txID, e); return builder.setResult(false).setCode(response_code.OTHER_ERROR) .setMessage(ByteString.copyFromUtf8("Error: " + e.getMessage())) .build(); @@ -1708,7 +1709,7 @@ public Proposal getProposalById(ByteString proposalId) { proposalCapsule = chainBaseManager.getProposalStore() .get(proposalId.toByteArray()); } catch (StoreException e) { - logger.error(e.getMessage()); + logger.warn(e.getMessage()); } if (proposalCapsule != null) { return proposalCapsule.getInstance(); @@ -2626,7 +2627,7 @@ public TransactionInfoList getTransactionInfoByBlockNum(long blockNum) { } } } catch (BadItemException | ItemNotFoundException e) { - logger.error(e.getMessage()); + logger.warn(e.getMessage()); } return transactionInfoList.build(); @@ -2658,7 +2659,7 @@ public MarketOrder getMarketOrderById(ByteString orderId) { try { return marketOrderStore.get(orderId.toByteArray()).getInstance(); } catch (ItemNotFoundException e) { - logger.error("orderId = " + orderId.toString() + " not found"); + logger.warn("orderId = {} not found", orderId); throw new IllegalStateException("order not found in store"); } @@ -2694,7 +2695,7 @@ public MarketOrderList getMarketOrderByAccount(ByteString accountAddress) { marketOrderListBuilder .addOrders(orderCapsule.getInstance()); } catch (ItemNotFoundException e) { - logger.error("orderId = " + orderId.toString() + " not found"); + logger.warn("orderId = {} not found", orderId); throw new IllegalStateException("order not found in store"); } } @@ -3061,9 +3062,9 @@ public SmartContract getContract(GrpcAPI.BytesMessage bytesMessage) { byte[] address = bytesMessage.getValue().toByteArray(); AccountCapsule accountCapsule = chainBaseManager.getAccountStore().get(address); if (accountCapsule == null) { - logger.error( - "Get contract failed, the account does not exist or the account " - + "does not have a code hash!"); + logger.warn( + "Get contract failed, the account {} does not exist or the account " + + "does not have a code hash!", StringUtil.encode58Check(address)); return null; } @@ -3090,9 +3091,9 @@ public SmartContractDataWrapper getContractInfo(GrpcAPI.BytesMessage bytesMessag byte[] address = bytesMessage.getValue().toByteArray(); AccountCapsule accountCapsule = chainBaseManager.getAccountStore().get(address); if (accountCapsule == null) { - logger.error( - "Get contract failed, the account does not exist or the account does not have a code " - + "hash!"); + logger.warn( + "Get contract failed, the account {} does not exist or the account does not have a code " + + "hash!", StringUtil.encode58Check(address)); return null; } diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 8787c70aeb8..c323df397a8 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1609,7 +1609,7 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { toBePacked.add(trx); currentSize += trxPackSize; } catch (Exception e) { - logger.error("Process trx {} failed when generating block {}, {}.", trx.getTransactionId(), + logger.warn("Process trx {} failed when generating block {}, {}.", trx.getTransactionId(), blockCapsule.getNum(), e.getMessage()); } } diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 8ce5a647566..2cbf5d2e718 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -303,7 +303,7 @@ public static Transaction packTransaction(String strTransaction, boolean selfTyp } catch (JSONException e) { logger.debug("JSONException: {}", e.getMessage()); } catch (Exception e) { - logger.error("", e); + logger.warn("{}", contractType, e); } } rawData.put("contract", contracts); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java index a25bedc577d..00a33f21bff 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java @@ -338,7 +338,7 @@ public static long getAmountFromTransactionInfo(String hash, ContractType contra break; } } else { - logger.error("Can't find transaction {} ", hash); + logger.warn("Can't find transaction {} ", hash); } } catch (Exception e) { logger.warn("Exception happens when get amount from transactionInfo. Exception = [{}]", From 9a825ec23f0871ebf036677bac2ac5f3951736f4 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 12 Apr 2023 18:10:52 +0800 Subject: [PATCH 0732/1197] feat(net): optimize sync block processing logic --- .../core/exception/BadBlockException.java | 26 +++++++++++++++++++ .../org/tron/core/exception/P2pException.java | 2 ++ .../main/java/org/tron/core/db/Manager.java | 5 ++-- .../org/tron/core/net/TronNetDelegate.java | 12 ++++++--- .../core/net/service/sync/SyncService.java | 26 +++++++++++++++---- .../java/org/tron/core/db/ManagerTest.java | 2 ++ 6 files changed, 63 insertions(+), 10 deletions(-) diff --git a/common/src/main/java/org/tron/core/exception/BadBlockException.java b/common/src/main/java/org/tron/core/exception/BadBlockException.java index e3308819d22..224ffc253ee 100644 --- a/common/src/main/java/org/tron/core/exception/BadBlockException.java +++ b/common/src/main/java/org/tron/core/exception/BadBlockException.java @@ -2,6 +2,8 @@ public class BadBlockException extends TronException { + private TypeEnum type = TypeEnum.DEFAULT; + public BadBlockException() { super(); } @@ -9,4 +11,28 @@ public BadBlockException() { public BadBlockException(String message) { super(message); } + + public BadBlockException(TypeEnum type, String message) { + super(message); + this.type = type; + } + + public TypeEnum getType() { + return type; + } + + public enum TypeEnum { + CALC_MERKLE_ROOT_FAILED(1), + DEFAULT(100); + + private Integer value; + + TypeEnum(Integer value) { + this.value = value; + } + + public Integer getValue() { + return value; + } + } } diff --git a/common/src/main/java/org/tron/core/exception/P2pException.java b/common/src/main/java/org/tron/core/exception/P2pException.java index d566b833d59..33c4c4fbec7 100644 --- a/common/src/main/java/org/tron/core/exception/P2pException.java +++ b/common/src/main/java/org/tron/core/exception/P2pException.java @@ -50,6 +50,8 @@ public enum TypeEnum { TRX_EXE_FAILED(12, "trx exe failed"), DB_ITEM_NOT_FOUND(13, "DB item not found"), PROTOBUF_ERROR(14, "protobuf inconsistent"), + SIGN_ERROR(15, "sign error"), + CALC_MERKLE_ROOT_FAILED(16, "calc merkle root failed"), DEFAULT(100, "default exception"); diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index c323df397a8..b1127029b46 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1,6 +1,7 @@ package org.tron.core.db; import static org.tron.common.utils.Commons.adjustBalance; +import static org.tron.core.exception.BadBlockException.TypeEnum.CALC_MERKLE_ROOT_FAILED; import static org.tron.protos.Protocol.Transaction.Contract.ContractType.TransferContract; import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS; @@ -1213,8 +1214,8 @@ public void pushBlock(final BlockCapsule block) if (!block.calcMerkleRoot().equals(block.getMerkleRoot())) { logger.warn("Num: {}, the merkle root doesn't match, expect is {} , actual is {}.", block.getNum(), block.getMerkleRoot(), block.calcMerkleRoot()); - throw new BadBlockException(String.format("The merkle hash is not validated for %d", - block.getNum())); + throw new BadBlockException(CALC_MERKLE_ROOT_FAILED, + String.format("The merkle hash is not validated for %d", block.getNum())); } consensus.receiveBlock(block); } diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index 05dde7a9701..f840341c1b2 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -1,6 +1,7 @@ package org.tron.core.net; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; +import static org.tron.core.exception.BadBlockException.TypeEnum.CALC_MERKLE_ROOT_FAILED; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; @@ -282,7 +283,12 @@ public void processBlock(BlockCapsule block, boolean isSync) throws P2pException | EventBloomException e) { metricsService.failProcessBlock(block.getNum(), e.getMessage()); logger.error("Process block failed, {}, reason: {}", blockId.getString(), e.getMessage()); - throw new P2pException(TypeEnum.BAD_BLOCK, e); + if (e instanceof BadBlockException + && ((BadBlockException) e).getType().equals(CALC_MERKLE_ROOT_FAILED)) { + throw new P2pException(TypeEnum.CALC_MERKLE_ROOT_FAILED, e); + } else { + throw new P2pException(TypeEnum.BAD_BLOCK, e); + } } } } @@ -312,10 +318,10 @@ public void validSignature(BlockCapsule block) throws P2pException { try { if (!block.validateSignature(dbManager.getDynamicPropertiesStore(), dbManager.getAccountStore())) { - throw new P2pException(TypeEnum.BAD_BLOCK, "valid signature failed."); + throw new P2pException(TypeEnum.SIGN_ERROR, "valid signature failed."); } } catch (ValidateSignatureException e) { - throw new P2pException(TypeEnum.BAD_BLOCK, e); + throw new P2pException(TypeEnum.SIGN_ERROR, e); } } diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 79cc4830e60..2ba35723e06 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -1,6 +1,8 @@ package org.tron.core.net.service.sync; import static org.tron.core.config.Parameter.NetConstants.MAX_BLOCK_FETCH_PER_PEER; +import static org.tron.core.exception.P2pException.TypeEnum.CALC_MERKLE_ROOT_FAILED; +import static org.tron.core.exception.P2pException.TypeEnum.SIGN_ERROR; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; @@ -23,6 +25,7 @@ import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.config.Parameter.NetConstants; import org.tron.core.config.args.Args; +import org.tron.core.exception.BadBlockException; import org.tron.core.exception.P2pException; import org.tron.core.exception.P2pException.TypeEnum; import org.tron.core.net.TronNetDelegate; @@ -263,33 +266,46 @@ private synchronized void handleSyncBlock() { tronNetDelegate.getActivePeer().stream() .filter(peer -> msg.getBlockId().equals(peer.getSyncBlockToFetch().peek())) .forEach(peer -> { - peer.getSyncBlockToFetch().pop(); - peer.getSyncBlockInProcess().add(msg.getBlockId()); isFound[0] = true; }); if (isFound[0]) { blockWaitToProcess.remove(msg); isProcessed[0] = true; - processSyncBlock(msg.getBlockCapsule()); + processSyncBlock(msg.getBlockCapsule(), peerConnection); } } }); } } - private void processSyncBlock(BlockCapsule block) { + private void processSyncBlock(BlockCapsule block, PeerConnection peerConnection) { boolean flag = true; + boolean attackFlag = false; BlockId blockId = block.getBlockId(); try { tronNetDelegate.validSignature(block); tronNetDelegate.processBlock(block, true); pbftDataSyncHandler.processPBFTCommitData(block); + } catch (P2pException p2pException) { + logger.error("Process sync block {} failed, type: {}", + blockId.getString(), p2pException.getType()); + attackFlag = p2pException.getType().equals(SIGN_ERROR) + || p2pException.getType().equals(CALC_MERKLE_ROOT_FAILED); + flag = false; } catch (Exception e) { logger.error("Process sync block {} failed", blockId.getString(), e); flag = false; } + + if (attackFlag) { + invalid(blockId, peerConnection); + peerConnection.disconnect(ReasonCode.BAD_BLOCK); + return; + } + for (PeerConnection peer : tronNetDelegate.getActivePeer()) { - if (peer.getSyncBlockInProcess().remove(blockId)) { + if (blockId.equals(peer.getSyncBlockToFetch().peek())) { + peer.getSyncBlockToFetch().pop(); if (flag) { peer.setBlockBothHave(blockId); if (peer.getSyncBlockToFetch().isEmpty() && peer.isFetchAble()) { diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index e7319d0ed0b..8cec1fc9cb8 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -4,6 +4,7 @@ import static org.tron.common.utils.Commons.adjustBalance; import static org.tron.common.utils.Commons.adjustTotalShieldedPoolValue; import static org.tron.common.utils.Commons.getExchangeStoreFinal; +import static org.tron.core.exception.BadBlockException.TypeEnum.CALC_MERKLE_ROOT_FAILED; import com.google.common.collect.Maps; import com.google.protobuf.ByteString; @@ -392,6 +393,7 @@ public void pushBlockInvalidMerkelRoot() { Assert.assertTrue(false); } catch (BadBlockException e) { Assert.assertTrue(e instanceof BadBlockException); + Assert.assertTrue(e.getType().equals(CALC_MERKLE_ROOT_FAILED)); Assert.assertEquals("The merkle hash is not validated for " + blockCapsule2.getNum(), e.getMessage()); } catch (Exception e) { From aaa64f99ebd9cea87ce59e8e95296e3904c11ad6 Mon Sep 17 00:00:00 2001 From: Asuka Date: Wed, 12 Apr 2023 18:19:29 +0800 Subject: [PATCH 0733/1197] func(version): update version to 4.7.1.1 --- framework/src/main/java/org/tron/program/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 88f87a68297..4163c4ca5e9 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -4,7 +4,7 @@ public class Version { public static final String VERSION_NAME = "GreatVoyage-v4.7.0.1-75-g36fc5063e9"; public static final String VERSION_CODE = "17673"; - private static final String VERSION = "4.7.1"; + private static final String VERSION = "4.7.1.1"; public static String getVersion() { return VERSION; From 75fba7a1c242611415efbd2e112f262597470afd Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 13 Apr 2023 14:37:36 +0800 Subject: [PATCH 0734/1197] fix(net): stable test case; add parameters in config --- .../main/java/org/tron/core/net/TronNetService.java | 6 +++--- framework/src/main/resources/config.conf | 13 +++++++++++++ .../java/org/tron/common/config/args/ArgsTest.java | 6 ++++-- .../tron/core/actuator/utils/ProposalUtilTest.java | 4 ++++ .../src/test/java/org/tron/core/db/ManagerTest.java | 7 +++++++ .../test/java/org/tron/core/net/MessageTest.java | 5 +++++ .../net/services/EffectiveCheckServiceTest.java | 13 +++++++++++++ framework/src/test/resources/config-test.conf | 4 ++++ 8 files changed, 53 insertions(+), 5 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 89767e31827..dda3be886dc 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -82,7 +82,8 @@ private static void setP2pConfig(P2pConfig config) { public void start() { try { init = true; - setP2pConfig(getConfig()); + P2pConfig config = new P2pConfig(); + setP2pConfig(getConfig(config)); p2pService.start(p2pConfig); p2pService.register(p2pEventHandler); advService.init(); @@ -147,11 +148,10 @@ public static boolean hasIpv4Stack(Set ipSet) { return false; } - private P2pConfig getConfig() { + private P2pConfig getConfig(P2pConfig config) { List seeds = parameter.getSeedNode().getAddressList(); seeds.addAll(nodePersistService.dbRead()); logger.debug("Seed InetSocketAddress: {}", seeds); - P2pConfig config = new P2pConfig(); config.getSeedNodes().addAll(seeds); config.getActiveNodes().addAll(parameter.getActiveNodes()); config.getTrustNodes().addAll(parameter.getPassiveNodes()); diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 47635540017..67aa374eec3 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -202,6 +202,19 @@ node { solidityPort = 8091 } + # use your ipv6 address for node discovery and tcp connection, default false + enableIpv6 = false + + # if your node's highest block num is below than all your pees', try to acquire new connection. default false + effectiveCheckEnable = false + + dns { + # dns urls to get nodes, url format tree://{pubkey}@{domain}, default empty + treeUrls = [ + #"tree://APFGGTFOBVE2ZNAB3CSMNNX6RRK3ODIRLP2AA5U4YFAA6MSYZUYTQ@nodes1.example.org", + ] + } + rpc { port = 50051 #solidityPort = 50061 diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index 2c85397eb1b..aa58d8e0fc9 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -11,16 +11,18 @@ public class ArgsTest { + private static final String dbPath = "output_arg_test"; + @Before public void init() { - Args.setParam(new String[]{"--output-directory", "output-directory", "--p2p-disable", "true", + Args.setParam(new String[]{"--output-directory", dbPath, "--p2p-disable", "true", "--debug"}, Constant.TEST_CONF); } @After public void destroy() { Args.clearParam(); - FileUtil.deleteDir(new File("output-directory")); + FileUtil.deleteDir(new File(dbPath)); } @Test diff --git a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java index ed19516a608..4f409815f8b 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java @@ -357,6 +357,10 @@ public void validateCheck() { Assert.assertEquals("Bad chain parameter value, valid range is [0, 1_000_000_000_000L]", e.getMessage()); } + + forkUtils.getManager().getDynamicPropertiesStore() + .statsByVersion(ForkBlockVersionEnum.ENERGY_LIMIT.getValue(), stats); + forkUtils.reset(); } @Test diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index e7319d0ed0b..b7b29f49930 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -226,6 +226,13 @@ public void pushBlock() { } } + try { + chainManager.getBlockIdByNum(-1); + Assert.fail(); + } catch (ItemNotFoundException e) { + Assert.assertTrue(true); + } + Assert.assertTrue("hasBlocks is error", chainManager.hasBlocks()); } diff --git a/framework/src/test/java/org/tron/core/net/MessageTest.java b/framework/src/test/java/org/tron/core/net/MessageTest.java index d27f37214c5..5b81d18a599 100644 --- a/framework/src/test/java/org/tron/core/net/MessageTest.java +++ b/framework/src/test/java/org/tron/core/net/MessageTest.java @@ -107,6 +107,11 @@ public Class getAnswerMessage() { messageStatistics.addTcpOutMessage(message4); messageStatistics.addTcpInMessage(message5); messageStatistics.addTcpOutMessage(message5); + try { + Thread.sleep(2000);// so that gap > 1 in MessageCount.update method + } catch (InterruptedException e) { + //ignore + } messageStatistics.addTcpInMessage(message6); messageStatistics.addTcpOutMessage(message6); messageStatistics.addTcpInMessage(message7); diff --git a/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java b/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java index 5f68be84251..1c422047e10 100644 --- a/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java @@ -1,6 +1,7 @@ package org.tron.core.net.services; import java.io.File; +import java.lang.reflect.Method; import java.net.InetSocketAddress; import org.junit.After; import org.junit.Assert; @@ -37,6 +38,18 @@ public void destroy() { FileUtil.deleteDir(new File(dbPath)); } + @Test + public void testNoIpv4() throws Exception { + TronNetService tronNetService = context.getBean(TronNetService.class); + Method privateMethod = tronNetService.getClass() + .getDeclaredMethod("getConfig", P2pConfig.class); + privateMethod.setAccessible(true); + P2pConfig config = new P2pConfig(); + config.setIp(null); + P2pConfig newConfig = (P2pConfig) privateMethod.invoke(tronNetService, config); + Assert.assertNotNull(newConfig.getIp()); + } + @Test public void testFind() { TronNetService tronNetService = context.getBean(TronNetService.class); diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index c9602ef977b..bef8239fd86 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -105,8 +105,12 @@ node { solidityPort = 8091 } + # use your ipv6 address for node discovery and tcp connection, default false enableIpv6 = false + # if your node's highest block num is below than all your pees', try to acquire new connection + effectiveCheckEnable = false + dns { # dns urls to get nodes, url format tree://{pubkey}@{domain}, default empty treeUrls = [ From 73ae4895c8f4d9cb300e6125170e74ef3f10e34d Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 28 Mar 2023 16:55:31 +0800 Subject: [PATCH 0735/1197] feat(api): remove insecure API --- .../org/tron/core/utils/TransactionUtil.java | 16 - .../src/main/java/org/tron/core/Wallet.java | 12 - .../org/tron/core/services/RpcApiService.java | 202 ------------- .../http/AddTransactionSignServlet.java | 51 ---- .../services/http/CreateAddressServlet.java | 76 ----- .../EasyTransferAssetByPrivateServlet.java | 75 ----- .../http/EasyTransferAssetServlet.java | 101 ------- .../http/EasyTransferByPrivateServlet.java | 72 ----- .../services/http/EasyTransferServlet.java | 82 ----- .../services/http/FullNodeHttpApiService.java | 27 -- .../services/http/GenerateAddressServlet.java | 43 --- .../http/HttpSelfFormatFieldName.java | 14 - .../services/http/TransactionSignServlet.java | 47 --- .../org/tron/core/services/http/Util.java | 7 - .../interfaceOnPBFT/RpcApiServiceOnPBFT.java | 18 -- .../RpcApiServiceOnSolidity.java | 19 -- .../ShieldedTransferActuatorTest.java | 37 +-- .../core/zksnark/ShieldedReceiveTest.java | 11 +- .../wallet/account/WalletTestAccount011.java | 7 - .../common/client/utils/HttpMethed.java | 124 +------- .../common/client/utils/TransactionUtils.java | 31 +- .../http/HttpTestEasyAccount001.java | 281 ------------------ protocol/src/main/protos/api/api.proto | 114 ------- protocol/src/main/protos/core/Tron.proto | 5 - 24 files changed, 46 insertions(+), 1426 deletions(-) delete mode 100644 framework/src/main/java/org/tron/core/services/http/AddTransactionSignServlet.java delete mode 100644 framework/src/main/java/org/tron/core/services/http/CreateAddressServlet.java delete mode 100644 framework/src/main/java/org/tron/core/services/http/EasyTransferAssetByPrivateServlet.java delete mode 100644 framework/src/main/java/org/tron/core/services/http/EasyTransferAssetServlet.java delete mode 100644 framework/src/main/java/org/tron/core/services/http/EasyTransferByPrivateServlet.java delete mode 100644 framework/src/main/java/org/tron/core/services/http/EasyTransferServlet.java delete mode 100644 framework/src/main/java/org/tron/core/services/http/GenerateAddressServlet.java delete mode 100644 framework/src/main/java/org/tron/core/services/http/TransactionSignServlet.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestEasyAccount001.java diff --git a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java index 496af641cde..e5cffa49790 100644 --- a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java @@ -49,7 +49,6 @@ import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract; import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionSign; import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; import org.tron.protos.Protocol.Transaction.Contract.ContractType; @@ -184,21 +183,6 @@ public static String makeUpperCamelMethod(String originName) { .replace("_", ""); } - public static TransactionCapsule getTransactionSign(TransactionSign transactionSign) { - byte[] privateKey = transactionSign.getPrivateKey().toByteArray(); - TransactionCapsule trx = new TransactionCapsule(transactionSign.getTransaction()); - trx.sign(privateKey); - return trx; - } - - public TransactionCapsule addSign(TransactionSign transactionSign) - throws PermissionException, SignatureException, SignatureFormatException { - byte[] privateKey = transactionSign.getPrivateKey().toByteArray(); - TransactionCapsule trx = new TransactionCapsule(transactionSign.getTransaction()); - trx.addSign(privateKey, chainBaseManager.getAccountStore()); - return trx; - } - public TransactionSignWeight getTransactionSignWeight(Transaction trx) { TransactionSignWeight.Builder tswBuilder = TransactionSignWeight.newBuilder(); TransactionExtention.Builder trxExBuilder = TransactionExtention.newBuilder(); diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index d07e2e6c9bf..295cb7d5bc1 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -648,18 +648,6 @@ public TransactionApprovedList getTransactionApprovedList(Transaction trx) { return tswBuilder.build(); } - public byte[] pass2Key(byte[] passPhrase) { - return Sha256Hash.hash(CommonParameter - .getInstance().isECKeyCryptoEngine(), passPhrase); - } - - public byte[] createAddress(byte[] passPhrase) { - byte[] privateKey = pass2Key(passPhrase); - SignInterface ecKey = SignUtils.fromPrivate(privateKey, - Args.getInstance().isECKeyCryptoEngine()); - return ecKey.getAddress(); - } - public Block getNowBlock() { List blockList = chainBaseManager.getBlockStore().getBlockByLatestNum(1); if (CollectionUtils.isEmpty(blockList)) { diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index a6e1c5181ad..437714ab5bd 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -16,7 +16,6 @@ import java.util.concurrent.TimeUnit; import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.codec.binary.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.api.DatabaseGrpc.DatabaseImplBase; @@ -24,7 +23,6 @@ import org.tron.api.GrpcAPI.AccountNetMessage; import org.tron.api.GrpcAPI.AccountResourceMessage; import org.tron.api.GrpcAPI.Address; -import org.tron.api.GrpcAPI.AddressPrKeyPairMessage; import org.tron.api.GrpcAPI.AssetIssueList; import org.tron.api.GrpcAPI.BlockExtention; import org.tron.api.GrpcAPI.BlockLimit; @@ -39,11 +37,6 @@ import org.tron.api.GrpcAPI.DelegatedResourceList; import org.tron.api.GrpcAPI.DelegatedResourceMessage; import org.tron.api.GrpcAPI.DiversifierMessage; -import org.tron.api.GrpcAPI.EasyTransferAssetByPrivateMessage; -import org.tron.api.GrpcAPI.EasyTransferAssetMessage; -import org.tron.api.GrpcAPI.EasyTransferByPrivateMessage; -import org.tron.api.GrpcAPI.EasyTransferMessage; -import org.tron.api.GrpcAPI.EasyTransferResponse; import org.tron.api.GrpcAPI.EmptyMessage; import org.tron.api.GrpcAPI.EstimateEnergyMessage; import org.tron.api.GrpcAPI.ExchangeList; @@ -85,13 +78,10 @@ import org.tron.api.WalletGrpc.WalletImplBase; import org.tron.api.WalletSolidityGrpc.WalletSolidityImplBase; import org.tron.common.application.Service; -import org.tron.common.crypto.SignInterface; -import org.tron.common.crypto.SignUtils; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; import org.tron.core.ChainBaseManager; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; @@ -130,7 +120,6 @@ import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.Protocol.TransactionSign; import org.tron.protos.contract.AccountContract.AccountCreateContract; import org.tron.protos.contract.AccountContract.AccountPermissionUpdateContract; import org.tron.protos.contract.AccountContract.AccountUpdateContract; @@ -726,12 +715,6 @@ public void getTransactionInfoById(BytesMessage request, responseObserver.onCompleted(); } - @Override - public void generateAddress(EmptyMessage request, - StreamObserver responseObserver) { - generateAddressCommon(request, responseObserver); - } - @Override public void getRewardInfo(BytesMessage request, StreamObserver responseObserver) { @@ -1145,55 +1128,6 @@ private void createTransactionExtention(Message request, ContractType contractTy responseObserver.onCompleted(); } - - @Override - public void getTransactionSign(TransactionSign req, - StreamObserver responseObserver) { - TransactionCapsule result = TransactionUtil.getTransactionSign(req); - responseObserver.onNext(result.getInstance()); - responseObserver.onCompleted(); - } - - @Override - public void getTransactionSign2(TransactionSign req, - StreamObserver responseObserver) { - TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); - Return.Builder retBuilder = Return.newBuilder(); - try { - TransactionCapsule trx = TransactionUtil.getTransactionSign(req); - trxExtBuilder.setTransaction(trx.getInstance()); - trxExtBuilder.setTxid(trx.getTransactionId().getByteString()); - retBuilder.setResult(true).setCode(response_code.SUCCESS); - } catch (Exception e) { - retBuilder.setResult(false).setCode(response_code.OTHER_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); - logger.info(EXCEPTION_CAUGHT + e.getMessage()); - } - trxExtBuilder.setResult(retBuilder); - responseObserver.onNext(trxExtBuilder.build()); - responseObserver.onCompleted(); - } - - @Override - public void addSign(TransactionSign req, - StreamObserver responseObserver) { - TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); - Return.Builder retBuilder = Return.newBuilder(); - try { - TransactionCapsule trx = transactionUtil.addSign(req); - trxExtBuilder.setTransaction(trx.getInstance()); - trxExtBuilder.setTxid(trx.getTransactionId().getByteString()); - retBuilder.setResult(true).setCode(response_code.SUCCESS); - } catch (Exception e) { - retBuilder.setResult(false).setCode(response_code.OTHER_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); - logger.info(EXCEPTION_CAUGHT + e.getMessage()); - } - trxExtBuilder.setResult(retBuilder); - responseObserver.onNext(trxExtBuilder.build()); - responseObserver.onCompleted(); - } - @Override public void getTransactionSignWeight(Transaction req, StreamObserver responseObserver) { @@ -1210,121 +1144,6 @@ public void getTransactionApprovedList(Transaction req, responseObserver.onCompleted(); } - @Override - public void createAddress(BytesMessage req, - StreamObserver responseObserver) { - byte[] address = wallet.createAddress(req.getValue().toByteArray()); - BytesMessage.Builder builder = BytesMessage.newBuilder(); - builder.setValue(ByteString.copyFrom(address)); - responseObserver.onNext(builder.build()); - responseObserver.onCompleted(); - } - - private EasyTransferResponse easyTransfer(byte[] privateKey, ByteString toAddress, - long amount) { - TransactionCapsule transactionCapsule; - GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); - EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); - try { - SignInterface cryptoEngine = SignUtils.fromPrivate(privateKey, Args.getInstance() - .isECKeyCryptoEngine()); - byte[] owner = cryptoEngine.getAddress(); - TransferContract.Builder builder = TransferContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setToAddress(toAddress); - builder.setAmount(amount); - transactionCapsule = createTransactionCapsule(builder.build(), - ContractType.TransferContract); - transactionCapsule.sign(privateKey); - GrpcAPI.Return result = wallet.broadcastTransaction(transactionCapsule.getInstance()); - responseBuild.setTransaction(transactionCapsule.getInstance()); - responseBuild.setTxid(transactionCapsule.getTransactionId().getByteString()); - responseBuild.setResult(result); - } catch (ContractValidateException e) { - returnBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - } catch (Exception e) { - returnBuilder.setResult(false).setCode(response_code.OTHER_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - } - - return responseBuild.build(); - } - - @Override - public void easyTransfer(EasyTransferMessage req, - StreamObserver responseObserver) { - byte[] privateKey = wallet.pass2Key(req.getPassPhrase().toByteArray()); - EasyTransferResponse response = easyTransfer(privateKey, req.getToAddress(), req.getAmount()); - responseObserver.onNext(response); - responseObserver.onCompleted(); - } - - @Override - public void easyTransferAsset(EasyTransferAssetMessage req, - StreamObserver responseObserver) { - byte[] privateKey = wallet.pass2Key(req.getPassPhrase().toByteArray()); - EasyTransferResponse response = easyTransferAsset(privateKey, req.getToAddress(), - req.getAssetId(), req.getAmount()); - responseObserver.onNext(response); - responseObserver.onCompleted(); - } - - private EasyTransferResponse easyTransferAsset(byte[] privateKey, ByteString toAddress, - String assetId, long amount) { - TransactionCapsule transactionCapsule; - GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); - EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); - try { - SignInterface cryptoEngine = SignUtils.fromPrivate(privateKey, - Args.getInstance().isECKeyCryptoEngine()); - byte[] owner = cryptoEngine.getAddress(); - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setToAddress(toAddress); - builder.setAssetName(ByteString.copyFrom(assetId.getBytes())); - builder.setAmount(amount); - transactionCapsule = createTransactionCapsule(builder.build(), - ContractType.TransferAssetContract); - transactionCapsule.sign(privateKey); - GrpcAPI.Return result = wallet.broadcastTransaction(transactionCapsule.getInstance()); - responseBuild.setTransaction(transactionCapsule.getInstance()); - responseBuild.setTxid(transactionCapsule.getTransactionId().getByteString()); - responseBuild.setResult(result); - } catch (ContractValidateException e) { - returnBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - } catch (Exception e) { - returnBuilder.setResult(false).setCode(response_code.OTHER_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - } - - return responseBuild.build(); - } - - @Override - public void easyTransferByPrivate(EasyTransferByPrivateMessage req, - StreamObserver responseObserver) { - byte[] privateKey = req.getPrivateKey().toByteArray(); - EasyTransferResponse response = easyTransfer(privateKey, req.getToAddress(), req.getAmount()); - responseObserver.onNext(response); - responseObserver.onCompleted(); - } - - @Override - public void easyTransferAssetByPrivate(EasyTransferAssetByPrivateMessage req, - StreamObserver responseObserver) { - byte[] privateKey = req.getPrivateKey().toByteArray(); - EasyTransferResponse response = easyTransferAsset(privateKey, req.getToAddress(), - req.getAssetId(), req.getAmount()); - responseObserver.onNext(response); - responseObserver.onCompleted(); - } - @Override public void broadcastTransaction(Transaction req, StreamObserver responseObserver) { @@ -2242,12 +2061,6 @@ public void getChainParameters(EmptyMessage request, responseObserver.onCompleted(); } - @Override - public void generateAddress(EmptyMessage request, - StreamObserver responseObserver) { - generateAddressCommon(request, responseObserver); - } - @Override public void getTransactionInfoById(BytesMessage request, StreamObserver responseObserver) { @@ -2906,21 +2719,6 @@ public void getStatsInfo(EmptyMessage request, } } - public void generateAddressCommon(EmptyMessage request, - StreamObserver responseObserver) { - SignInterface cryptoEngine = SignUtils.getGeneratedRandomSign(Utils.getRandom(), - Args.getInstance().isECKeyCryptoEngine()); - byte[] priKey = cryptoEngine.getPrivateKey(); - byte[] address = cryptoEngine.getAddress(); - String addressStr = StringUtil.encode58Check(address); - String priKeyStr = Hex.encodeHexString(priKey); - AddressPrKeyPairMessage.Builder builder = AddressPrKeyPairMessage.newBuilder(); - builder.setAddress(addressStr); - builder.setPrivateKey(priKeyStr); - responseObserver.onNext(builder.build()); - responseObserver.onCompleted(); - } - public void getRewardInfoCommon(BytesMessage request, StreamObserver responseObserver) { try { diff --git a/framework/src/main/java/org/tron/core/services/http/AddTransactionSignServlet.java b/framework/src/main/java/org/tron/core/services/http/AddTransactionSignServlet.java deleted file mode 100644 index f9fd1fa4936..00000000000 --- a/framework/src/main/java/org/tron/core/services/http/AddTransactionSignServlet.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.tron.core.services.http; - -import com.alibaba.fastjson.JSONObject; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.utils.TransactionUtil; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionSign; - - -@Component -@Slf4j(topic = "API") -public class AddTransactionSignServlet extends RateLimiterServlet { - - @Autowired - private TransactionUtil transactionUtil; - - protected void doGet(HttpServletRequest request, HttpServletResponse response) { - - } - - protected void doPost(HttpServletRequest request, HttpServletResponse response) { - try { - String contract = request.getReader().lines() - .collect(Collectors.joining(System.lineSeparator())); - Util.checkBodySize(contract); - JSONObject input = JSONObject.parseObject(contract); - boolean visible = Util.getVisibleOnlyForSign(input); - String strTransaction = input.getJSONObject("transaction").toJSONString(); - Transaction transaction = Util.packTransaction(strTransaction, visible); - JSONObject jsonTransaction = JSONObject.parseObject(JsonFormat.printToString(transaction, - visible)); - input.put("transaction", jsonTransaction); - TransactionSign.Builder build = TransactionSign.newBuilder(); - JsonFormat.merge(input.toJSONString(), build, visible); - TransactionCapsule reply = transactionUtil.addSign(build.build()); - if (reply != null) { - response.getWriter().println(Util.printCreateTransaction(reply.getInstance(), visible)); - } else { - response.getWriter().println("{}"); - } - } catch (Exception e) { - Util.processError(e, response); - } - } -} diff --git a/framework/src/main/java/org/tron/core/services/http/CreateAddressServlet.java b/framework/src/main/java/org/tron/core/services/http/CreateAddressServlet.java deleted file mode 100644 index 7e52abddf6a..00000000000 --- a/framework/src/main/java/org/tron/core/services/http/CreateAddressServlet.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.tron.core.services.http; - -import static org.tron.core.services.http.PostParams.S_VALUE; - -import com.alibaba.fastjson.JSONObject; -import com.google.protobuf.ByteString; -import java.io.IOException; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI.BytesMessage; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.StringUtil; -import org.tron.core.Wallet; - - -@Component -@Slf4j(topic = "API") -public class CreateAddressServlet extends RateLimiterServlet { - - @Autowired - private Wallet wallet; - - protected void doGet(HttpServletRequest request, HttpServletResponse response) { - try { - boolean visible = Util.getVisible(request); - String input = request.getParameter(S_VALUE); - if (visible) { - input = Util.getHexString(input); - } - JSONObject jsonObject = new JSONObject(); - jsonObject.put(S_VALUE, input); - BytesMessage.Builder build = BytesMessage.newBuilder(); - JsonFormat.merge(jsonObject.toJSONString(), build, visible); - fillResponse(build.getValue(), response); - } catch (Exception e) { - Util.processError(e, response); - } - } - - protected void doPost(HttpServletRequest request, HttpServletResponse response) { - try { - PostParams params = PostParams.getPostParams(request); - boolean visible = params.isVisible(); - String input = params.getParams(); - if (visible) { - input = covertStringToHex(input); - } - BytesMessage.Builder build = BytesMessage.newBuilder(); - JsonFormat.merge(input, build, visible); - fillResponse(build.getValue(), response); - } catch (Exception e) { - Util.processError(e, response); - } - } - - private String covertStringToHex(String input) { - JSONObject jsonObject = JSONObject.parseObject(input); - String value = jsonObject.getString(S_VALUE); - jsonObject.put(S_VALUE, Util.getHexString(value)); - return jsonObject.toJSONString(); - } - - private void fillResponse(ByteString value, HttpServletResponse response) throws IOException { - byte[] address = wallet.createAddress(value.toByteArray()); - String base58check = StringUtil.encode58Check(address); - String hexString = ByteArray.toHexString(address); - JSONObject jsonAddress = new JSONObject(); - jsonAddress.put("base58checkAddress", base58check); - jsonAddress.put(S_VALUE, hexString); - response.getWriter().println(jsonAddress.toJSONString()); - } -} diff --git a/framework/src/main/java/org/tron/core/services/http/EasyTransferAssetByPrivateServlet.java b/framework/src/main/java/org/tron/core/services/http/EasyTransferAssetByPrivateServlet.java deleted file mode 100644 index 2739df81387..00000000000 --- a/framework/src/main/java/org/tron/core/services/http/EasyTransferAssetByPrivateServlet.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.tron.core.services.http; - -import com.google.protobuf.ByteString; -import java.io.IOException; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.EasyTransferAssetByPrivateMessage; -import org.tron.api.GrpcAPI.EasyTransferResponse; -import org.tron.api.GrpcAPI.Return.response_code; -import org.tron.common.crypto.SignInterface; -import org.tron.common.crypto.SignUtils; -import org.tron.core.Wallet; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.args.Args; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; - - -@Component -@Slf4j -public class EasyTransferAssetByPrivateServlet extends RateLimiterServlet { - - @Autowired - private Wallet wallet; - - protected void doGet(HttpServletRequest request, HttpServletResponse response) { - - } - - protected void doPost(HttpServletRequest request, HttpServletResponse response) { - GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); - EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); - boolean visible = false; - try { - String input = request.getReader().lines() - .collect(Collectors.joining(System.lineSeparator())); - visible = Util.getVisiblePost(input); - EasyTransferAssetByPrivateMessage.Builder build = EasyTransferAssetByPrivateMessage - .newBuilder(); - JsonFormat.merge(input, build, visible); - byte[] privateKey = build.getPrivateKey().toByteArray(); - SignInterface ecKey = SignUtils.fromPrivate(privateKey, Args.getInstance() - .isECKeyCryptoEngine()); - byte[] owner = ecKey.getAddress(); - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setToAddress(build.getToAddress()); - builder.setAssetName(ByteString.copyFrom(build.getAssetId().getBytes())); - builder.setAmount(build.getAmount()); - - TransactionCapsule transactionCapsule; - transactionCapsule = wallet - .createTransactionCapsule(builder.build(), ContractType.TransferAssetContract); - transactionCapsule.sign(privateKey); - GrpcAPI.Return result = wallet.broadcastTransaction(transactionCapsule.getInstance()); - responseBuild.setTransaction(transactionCapsule.getInstance()); - responseBuild.setResult(result); - response.getWriter().println(Util.printEasyTransferResponse(responseBuild.build(), visible)); - } catch (Exception e) { - returnBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - try { - response.getWriter().println(JsonFormat.printToString(responseBuild.build(), visible)); - } catch (IOException ioe) { - logger.debug("IOException: {}", ioe.getMessage()); - } - } - } -} diff --git a/framework/src/main/java/org/tron/core/services/http/EasyTransferAssetServlet.java b/framework/src/main/java/org/tron/core/services/http/EasyTransferAssetServlet.java deleted file mode 100644 index b6939570bac..00000000000 --- a/framework/src/main/java/org/tron/core/services/http/EasyTransferAssetServlet.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.tron.core.services.http; - -import com.google.protobuf.ByteString; -import java.io.IOException; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.EasyTransferAssetMessage; -import org.tron.api.GrpcAPI.EasyTransferResponse; -import org.tron.api.GrpcAPI.Return.response_code; -import org.tron.common.crypto.SignInterface; -import org.tron.common.crypto.SignUtils; -import org.tron.core.Wallet; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.args.Args; -import org.tron.core.exception.ContractValidateException; -import org.tron.core.services.http.JsonFormat.ParseException; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; - - -@Component -@Slf4j -public class EasyTransferAssetServlet extends RateLimiterServlet { - - private static final String S_IOEXCEPTION = "IOException: {}"; - - @Autowired - private Wallet wallet; - - protected void doGet(HttpServletRequest request, HttpServletResponse response) { - - } - - protected void doPost(HttpServletRequest request, HttpServletResponse response) { - GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); - EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); - boolean visible = false; - try { - String input = request.getReader().lines() - .collect(Collectors.joining(System.lineSeparator())); - visible = Util.getVisiblePost(input); - EasyTransferAssetMessage.Builder build = EasyTransferAssetMessage.newBuilder(); - JsonFormat.merge(input, build, visible); - byte[] privateKey = wallet.pass2Key(build.getPassPhrase().toByteArray()); - SignInterface ecKey = SignUtils.fromPrivate(privateKey, Args.getInstance() - .isECKeyCryptoEngine()); - byte[] owner = ecKey.getAddress(); - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setToAddress(build.getToAddress()); - builder.setAssetName(ByteString.copyFrom(build.getAssetId().getBytes())); - builder.setAmount(build.getAmount()); - - TransactionCapsule transactionCapsule; - transactionCapsule = wallet - .createTransactionCapsule(builder.build(), ContractType.TransferAssetContract); - transactionCapsule.sign(privateKey); - GrpcAPI.Return result = wallet.broadcastTransaction(transactionCapsule.getInstance()); - responseBuild.setTransaction(transactionCapsule.getInstance()); - responseBuild.setResult(result); - response.getWriter().println(Util.printEasyTransferResponse(responseBuild.build(), visible)); - } catch (ParseException e) { - logger.debug("ParseException: {}", e.getMessage()); - returnBuilder.setResult(false).setCode(response_code.OTHER_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - try { - response.getWriter().println(JsonFormat.printToString(responseBuild.build(), visible)); - } catch (IOException ioe) { - logger.debug(S_IOEXCEPTION, ioe.getMessage()); - } - return; - } catch (IOException e) { - logger.debug(S_IOEXCEPTION, e.getMessage()); - returnBuilder.setResult(false).setCode(response_code.OTHER_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - try { - response.getWriter().println(JsonFormat.printToString(responseBuild.build(), visible)); - } catch (IOException ioe) { - logger.debug(S_IOEXCEPTION, ioe.getMessage()); - } - return; - } catch (ContractValidateException e) { - returnBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - try { - response.getWriter().println(JsonFormat.printToString(responseBuild.build(), visible)); - } catch (IOException ioe) { - logger.debug(S_IOEXCEPTION, ioe.getMessage()); - } - return; - } - } -} diff --git a/framework/src/main/java/org/tron/core/services/http/EasyTransferByPrivateServlet.java b/framework/src/main/java/org/tron/core/services/http/EasyTransferByPrivateServlet.java deleted file mode 100644 index aa6574dc66f..00000000000 --- a/framework/src/main/java/org/tron/core/services/http/EasyTransferByPrivateServlet.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.tron.core.services.http; - -import com.google.protobuf.ByteString; -import java.io.IOException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.EasyTransferByPrivateMessage; -import org.tron.api.GrpcAPI.EasyTransferResponse; -import org.tron.api.GrpcAPI.Return.response_code; -import org.tron.common.crypto.SignInterface; -import org.tron.common.crypto.SignUtils; -import org.tron.core.Wallet; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.args.Args; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.contract.BalanceContract.TransferContract; - - -@Component -@Slf4j(topic = "API") -public class EasyTransferByPrivateServlet extends RateLimiterServlet { - - @Autowired - private Wallet wallet; - - protected void doGet(HttpServletRequest request, HttpServletResponse response) { - - } - - protected void doPost(HttpServletRequest request, HttpServletResponse response) { - GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); - EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); - boolean visible = false; - try { - PostParams params = PostParams.getPostParams(request); - visible = params.isVisible(); - EasyTransferByPrivateMessage.Builder build = EasyTransferByPrivateMessage.newBuilder(); - JsonFormat.merge(params.getParams(), build, visible); - byte[] privateKey = build.getPrivateKey().toByteArray(); - SignInterface ecKey = SignUtils.fromPrivate(privateKey, Args.getInstance() - .isECKeyCryptoEngine()); - byte[] owner = ecKey.getAddress(); - TransferContract.Builder builder = TransferContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setToAddress(build.getToAddress()); - builder.setAmount(build.getAmount()); - - TransactionCapsule transactionCapsule; - transactionCapsule = wallet - .createTransactionCapsule(builder.build(), ContractType.TransferContract); - transactionCapsule.sign(privateKey); - GrpcAPI.Return result = wallet.broadcastTransaction(transactionCapsule.getInstance()); - responseBuild.setTransaction(transactionCapsule.getInstance()); - responseBuild.setResult(result); - response.getWriter().println(Util.printEasyTransferResponse(responseBuild.build(), visible)); - } catch (Exception e) { - returnBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - try { - response.getWriter().println(JsonFormat.printToString(responseBuild.build(), visible)); - } catch (IOException ioe) { - logger.debug("IOException: {}", ioe.getMessage()); - } - return; - } - } -} diff --git a/framework/src/main/java/org/tron/core/services/http/EasyTransferServlet.java b/framework/src/main/java/org/tron/core/services/http/EasyTransferServlet.java deleted file mode 100644 index 6c80153044e..00000000000 --- a/framework/src/main/java/org/tron/core/services/http/EasyTransferServlet.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.tron.core.services.http; - -import com.google.protobuf.ByteString; -import java.io.IOException; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.EasyTransferMessage; -import org.tron.api.GrpcAPI.EasyTransferResponse; -import org.tron.api.GrpcAPI.Return.response_code; -import org.tron.common.crypto.SignInterface; -import org.tron.common.crypto.SignUtils; -import org.tron.core.Wallet; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.args.Args; -import org.tron.core.exception.ContractValidateException; -import org.tron.core.services.http.JsonFormat.ParseException; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.contract.BalanceContract.TransferContract; - - -@Component -@Slf4j(topic = "API") -public class EasyTransferServlet extends RateLimiterServlet { - - @Autowired - private Wallet wallet; - - protected void doGet(HttpServletRequest request, HttpServletResponse response) { - - } - - protected void doPost(HttpServletRequest request, HttpServletResponse response) { - GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); - EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); - boolean visible = false; - try { - String input = request.getReader().lines() - .collect(Collectors.joining(System.lineSeparator())); - Util.checkBodySize(input); - visible = Util.getVisiblePost(input); - EasyTransferMessage.Builder build = EasyTransferMessage.newBuilder(); - JsonFormat.merge(input, build, visible); - byte[] privateKey = wallet.pass2Key(build.getPassPhrase().toByteArray()); - SignInterface ecKey = SignUtils.fromPrivate(privateKey, Args.getInstance() - .isECKeyCryptoEngine()); - byte[] owner = ecKey.getAddress(); - TransferContract.Builder builder = TransferContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setToAddress(build.getToAddress()); - builder.setAmount(build.getAmount()); - - TransactionCapsule transactionCapsule; - transactionCapsule = wallet - .createTransactionCapsule(builder.build(), ContractType.TransferContract); - transactionCapsule.sign(privateKey); - GrpcAPI.Return result = wallet.broadcastTransaction(transactionCapsule.getInstance()); - responseBuild.setTransaction(transactionCapsule.getInstance()); - responseBuild.setResult(result); - response.getWriter().println(Util.printEasyTransferResponse(responseBuild.build(), visible)); - } catch (ParseException e) { - logger.debug("ParseException: {}", e.getMessage()); - } catch (IOException e) { - logger.debug("IOException: {}", e.getMessage()); - } catch (ContractValidateException e) { - returnBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getMessage())); - responseBuild.setResult(returnBuilder.build()); - try { - response.getWriter().println(JsonFormat.printToString(responseBuild.build(), visible)); - } catch (IOException ioe) { - logger.debug("IOException: {}", ioe.getMessage()); - } - } catch (Exception e) { - logger.debug("Exception: {}", e.getMessage()); - } - } -} diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index 43f00454fd3..030adc489ed 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -42,8 +42,6 @@ public class FullNodeHttpApiService implements Service { @Autowired private BroadcastServlet broadcastServlet; @Autowired - private TransactionSignServlet transactionSignServlet; - @Autowired private UpdateAccountServlet updateAccountServlet; @Autowired private VoteWitnessAccountServlet voteWitnessAccountServlet; @@ -114,18 +112,6 @@ public class FullNodeHttpApiService implements Service { @Autowired private GetNextMaintenanceTimeServlet getNextMaintenanceTimeServlet; @Autowired - private EasyTransferServlet easyTransferServlet; - @Autowired - private EasyTransferByPrivateServlet easyTransferByPrivateServlet; - @Autowired - private EasyTransferAssetServlet easyTransferAssetServlet; - @Autowired - private EasyTransferAssetByPrivateServlet easyTransferAssetByPrivateServlet; - @Autowired - private CreateAddressServlet createAddressServlet; - @Autowired - private GenerateAddressServlet generateAddressServlet; - @Autowired private ValidateAddressServlet validateAddressServlet; @Autowired private DeployContractServlet deployContractServlet; @@ -170,8 +156,6 @@ public class FullNodeHttpApiService implements Service { @Autowired private GetNodeInfoServlet getNodeInfoServlet; @Autowired - private AddTransactionSignServlet addTransactionSignServlet; - @Autowired private GetTransactionSignWeightServlet getTransactionSignWeightServlet; @Autowired private GetTransactionApprovedListServlet getTransactionApprovedListServlet; @@ -377,7 +361,6 @@ public void start() { context.addServlet(new ServletHolder(getAccountServlet), "/wallet/getaccount"); context.addServlet(new ServletHolder(transferServlet), "/wallet/createtransaction"); context.addServlet(new ServletHolder(broadcastServlet), "/wallet/broadcasttransaction"); - context.addServlet(new ServletHolder(transactionSignServlet), "/wallet/gettransactionsign"); context.addServlet(new ServletHolder(updateAccountServlet), "/wallet/updateaccount"); context.addServlet(new ServletHolder(voteWitnessAccountServlet), "/wallet/votewitnessaccount"); @@ -430,14 +413,6 @@ public void start() { context.addServlet(new ServletHolder(totalTransactionServlet), "/wallet/totaltransaction"); context.addServlet( new ServletHolder(getNextMaintenanceTimeServlet), "/wallet/getnextmaintenancetime"); - context.addServlet(new ServletHolder(createAddressServlet), "/wallet/createaddress"); - context.addServlet(new ServletHolder(easyTransferServlet), "/wallet/easytransfer"); - context.addServlet(new ServletHolder(easyTransferByPrivateServlet), - "/wallet/easytransferbyprivate"); - context.addServlet(new ServletHolder(easyTransferAssetServlet), "/wallet/easytransferasset"); - context.addServlet(new ServletHolder(easyTransferAssetByPrivateServlet), - "/wallet/easytransferassetbyprivate"); - context.addServlet(new ServletHolder(generateAddressServlet), "/wallet/generateaddress"); context.addServlet(new ServletHolder(validateAddressServlet), "/wallet/validateaddress"); context.addServlet(new ServletHolder(deployContractServlet), "/wallet/deploycontract"); context.addServlet(new ServletHolder(triggerSmartContractServlet), @@ -464,8 +439,6 @@ public void start() { "/wallet/getchainparameters"); context.addServlet(new ServletHolder(getAccountResourceServlet), "/wallet/getaccountresource"); - context.addServlet(new ServletHolder(addTransactionSignServlet), - "/wallet/addtransactionsign"); context.addServlet(new ServletHolder(getTransactionSignWeightServlet), "/wallet/getsignweight"); context.addServlet(new ServletHolder(getTransactionApprovedListServlet), diff --git a/framework/src/main/java/org/tron/core/services/http/GenerateAddressServlet.java b/framework/src/main/java/org/tron/core/services/http/GenerateAddressServlet.java deleted file mode 100644 index 1814b34c322..00000000000 --- a/framework/src/main/java/org/tron/core/services/http/GenerateAddressServlet.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.tron.core.services.http; - -import com.alibaba.fastjson.JSONObject; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.codec.binary.Hex; -import org.springframework.stereotype.Component; -import org.tron.common.crypto.SignInterface; -import org.tron.common.crypto.SignUtils; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; -import org.tron.core.config.args.Args; - - -@Component -@Slf4j(topic = "API") -public class GenerateAddressServlet extends RateLimiterServlet { - - protected void doGet(HttpServletRequest request, HttpServletResponse response) { - try { - SignInterface sign = SignUtils.getGeneratedRandomSign(Utils.getRandom(), - Args.getInstance().isECKeyCryptoEngine()); - byte[] priKey = sign.getPrivateKey(); - byte[] address = sign.getAddress(); - String priKeyStr = Hex.encodeHexString(priKey); - String base58check = StringUtil.encode58Check(address); - String hexString = ByteArray.toHexString(address); - JSONObject jsonAddress = new JSONObject(); - jsonAddress.put("address", base58check); - jsonAddress.put("hexAddress", hexString); - jsonAddress.put("privateKey", priKeyStr); - response.getWriter().println(jsonAddress.toJSONString()); - } catch (Exception e) { - Util.processError(e, response); - } - } - - protected void doPost(HttpServletRequest request, HttpServletResponse response) { - doGet(request, response); - } -} \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java b/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java index 3d3f73468bd..93b726bb0e5 100644 --- a/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java +++ b/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java @@ -13,14 +13,6 @@ public class HttpSelfFormatFieldName { //DelegatedResourceMessage AddressFieldNameMap.put("protocol.DelegatedResourceMessage.fromAddress", 1); AddressFieldNameMap.put("protocol.DelegatedResourceMessage.toAddress", 1); - //EasyTransferMessage - AddressFieldNameMap.put("protocol.EasyTransferMessage.toAddress", 1); - //EasyTransferAssetMessage - AddressFieldNameMap.put("protocol.EasyTransferAssetMessage.toAddress", 1); - //EasyTransferByPrivateMessage - AddressFieldNameMap.put("protocol.EasyTransferByPrivateMessage.toAddress", 1); - //EasyTransferAssetByPrivateMessage - AddressFieldNameMap.put("protocol.EasyTransferAssetByPrivateMessage.toAddress", 1); //TransactionSignWeight AddressFieldNameMap.put("protocol.TransactionSignWeight.approved_list", 1); //TransactionApprovedList @@ -140,8 +132,6 @@ public class HttpSelfFormatFieldName { //ShieldedTransferContract AddressFieldNameMap.put("protocol.ShieldedTransferContract.transparent_from_address", 1); AddressFieldNameMap.put("protocol.ShieldedTransferContract.transparent_to_address", 1); - //UpdateBrokerageContract - AddressFieldNameMap.put("protocol.UpdateBrokerageContract.owner_address", 1); //FreezeBalanceV2Contract AddressFieldNameMap.put("protocol.FreezeBalanceV2Contract.owner_address", 1); //UnfreezeBalanceV2Contract @@ -206,10 +196,6 @@ public class HttpSelfFormatFieldName { NameFieldNameMap.put("protocol.Return.message", 1); //Address NameFieldNameMap.put("protocol.Address.host", 1); - //EasyTransferMessage - NameFieldNameMap.put("protocol.EasyTransferMessage.passPhrase", 1); - //EasyTransferAssetMessage - NameFieldNameMap.put("protocol.EasyTransferAssetMessage.passPhrase", 1); //Note NameFieldNameMap.put("protocol.Note.memo", 1); diff --git a/framework/src/main/java/org/tron/core/services/http/TransactionSignServlet.java b/framework/src/main/java/org/tron/core/services/http/TransactionSignServlet.java deleted file mode 100644 index 86d1b07f457..00000000000 --- a/framework/src/main/java/org/tron/core/services/http/TransactionSignServlet.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.tron.core.services.http; - -import com.alibaba.fastjson.JSONObject; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.utils.TransactionUtil; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionSign; - - -@Component -@Slf4j(topic = "API") -public class TransactionSignServlet extends RateLimiterServlet { - - protected void doGet(HttpServletRequest request, HttpServletResponse response) { - - } - - protected void doPost(HttpServletRequest request, HttpServletResponse response) { - try { - String contract = request.getReader().lines() - .collect(Collectors.joining(System.lineSeparator())); - Util.checkBodySize(contract); - JSONObject input = JSONObject.parseObject(contract); - boolean visible = Util.getVisibleOnlyForSign(input); - String strTransaction = input.getJSONObject("transaction").toJSONString(); - Transaction transaction = Util.packTransaction(strTransaction, visible); - JSONObject jsonTransaction = JSONObject.parseObject(JsonFormat.printToString(transaction, - visible)); - input.put("transaction", jsonTransaction); - TransactionSign.Builder build = TransactionSign.newBuilder(); - JsonFormat.merge(input.toJSONString(), build, visible); - TransactionCapsule reply = TransactionUtil.getTransactionSign(build.build()); - if (reply != null) { - response.getWriter().println(Util.printCreateTransaction(reply.getInstance(), visible)); - } else { - response.getWriter().println("{}"); - } - } catch (Exception e) { - Util.processError(e, response); - } - } -} diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 6c8ce0b832c..28ec18b59ac 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -27,7 +27,6 @@ import org.eclipse.jetty.util.StringUtil; import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.BlockList; -import org.tron.api.GrpcAPI.EasyTransferResponse; import org.tron.api.GrpcAPI.TransactionApprovedList; import org.tron.api.GrpcAPI.TransactionExtention; import org.tron.api.GrpcAPI.TransactionIdList; @@ -129,12 +128,6 @@ public static JSONArray printTransactionListToJSON(List list return transactions; } - public static String printEasyTransferResponse(EasyTransferResponse response, boolean selfType) { - JSONObject jsonResponse = JSONObject.parseObject(JsonFormat.printToString(response, selfType)); - jsonResponse.put(TRANSACTION, printTransactionToJSON(response.getTransaction(), selfType)); - return jsonResponse.toJSONString(); - } - public static String printTransaction(Transaction transaction, boolean selfType) { return printTransactionToJSON(transaction, selfType).toJSONString(); } diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java index 7232ba01ce5..c003f9d3994 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java @@ -7,11 +7,9 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.codec.binary.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.tron.api.DatabaseGrpc.DatabaseImplBase; import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AddressPrKeyPairMessage; import org.tron.api.GrpcAPI.AssetIssueList; import org.tron.api.GrpcAPI.BlockExtention; import org.tron.api.GrpcAPI.BlockReference; @@ -414,22 +412,6 @@ public void estimateEnergy(TriggerSmartContract request, ); } - - @Override - public void generateAddress(EmptyMessage request, - StreamObserver responseObserver) { - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] priKey = ecKey.getPrivKeyBytes(); - byte[] address = ecKey.getAddress(); - String addressStr = StringUtil.encode58Check(address); - String priKeyStr = Hex.encodeHexString(priKey); - AddressPrKeyPairMessage.Builder builder = AddressPrKeyPairMessage.newBuilder(); - builder.setAddress(addressStr); - builder.setPrivateKey(priKeyStr); - responseObserver.onNext(builder.build()); - responseObserver.onCompleted(); - } - @Override public void getRewardInfo(BytesMessage request, StreamObserver responseObserver) { diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java index 254c5227929..3f4bfeda731 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java @@ -8,11 +8,9 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.codec.binary.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.tron.api.DatabaseGrpc.DatabaseImplBase; import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AddressPrKeyPairMessage; import org.tron.api.GrpcAPI.AssetIssueList; import org.tron.api.GrpcAPI.BlockExtention; import org.tron.api.GrpcAPI.BlockReference; @@ -398,23 +396,6 @@ public void estimateEnergy(TriggerSmartContract request, .estimateEnergy(request, responseObserver)); } - - @Override - public void generateAddress(EmptyMessage request, - StreamObserver responseObserver) { - SignInterface cryptoEngine = SignUtils - .getGeneratedRandomSign(Utils.getRandom(), Args.getInstance().isECKeyCryptoEngine()); - byte[] priKey = cryptoEngine.getPrivateKey(); - byte[] address = cryptoEngine.getAddress(); - String addressStr = StringUtil.encode58Check(address); - String priKeyStr = Hex.encodeHexString(priKey); - AddressPrKeyPairMessage.Builder builder = AddressPrKeyPairMessage.newBuilder(); - builder.setAddress(addressStr); - builder.setPrivateKey(priKeyStr); - responseObserver.onNext(builder.build()); - responseObserver.onCompleted(); - } - @Override public void getRewardInfo(BytesMessage request, StreamObserver responseObserver) { diff --git a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java index 3042a745d94..5bac3effbef 100755 --- a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java @@ -41,10 +41,10 @@ import org.tron.core.zen.note.Note; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction.Contract; -import org.tron.protos.Protocol.TransactionSign; import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; import org.tron.protos.contract.ShieldContract.PedersenHash; import org.tron.protos.contract.ShieldContract.ShieldedTransferContract; +import stest.tron.wallet.common.client.utils.TransactionUtils; @Slf4j public class ShieldedTransferActuatorTest { @@ -232,11 +232,8 @@ public void publicAddressToShieldedAddressSuccess() { TransactionCapsule transactionCap = getPublicToShieldedTransaction(); //Add public address sign - TransactionSign.Builder transactionSignBuild = TransactionSign.newBuilder(); - transactionSignBuild.setTransaction(transactionCap.getInstance()); - transactionSignBuild.setPrivateKey(ByteString.copyFrom( - ByteArray.fromHexString(ADDRESS_ONE_PRIVATE_KEY))); - transactionCap = transactionUtil.addSign(transactionSignBuild.build()); + transactionCap = TransactionUtils.addTransactionSign(transactionCap.getInstance(), + ADDRESS_ONE_PRIVATE_KEY, dbManager.getAccountStore()); Assert.assertTrue(dbManager.pushTransaction(transactionCap)); } catch (Exception e) { @@ -263,11 +260,8 @@ public void publicAddressToPublicAddressAndZereValueOutputSuccess() { TransactionCapsule transactionCap = builder.build(); //Add public address sign - TransactionSign.Builder transactionSignBuild = TransactionSign.newBuilder(); - transactionSignBuild.setTransaction(transactionCap.getInstance()); - transactionSignBuild.setPrivateKey(ByteString.copyFrom( - ByteArray.fromHexString(ADDRESS_ONE_PRIVATE_KEY))); - transactionCap = transactionUtil.addSign(transactionSignBuild.build()); + transactionCap = TransactionUtils.addTransactionSign(transactionCap.getInstance(), + ADDRESS_ONE_PRIVATE_KEY, dbManager.getAccountStore()); Assert.assertTrue(dbManager.pushTransaction(transactionCap)); } catch (Exception e) { @@ -286,11 +280,8 @@ public void publicAddressToShieldedAddressInvalidSign() { TransactionCapsule transactionCap = getPublicToShieldedTransaction(); //Add public address sign - TransactionSign.Builder transactionSignBuild = TransactionSign.newBuilder(); - transactionSignBuild.setTransaction(transactionCap.getInstance()); - transactionSignBuild.setPrivateKey(ByteString.copyFrom( - ByteArray.fromHexString(ADDRESS_TWO_PRIVATE_KEY))); - transactionUtil.addSign(transactionSignBuild.build()); + TransactionUtils.addTransactionSign(transactionCap.getInstance(), ADDRESS_TWO_PRIVATE_KEY, + dbManager.getAccountStore()); Assert.assertTrue(false); } catch (PermissionException e) { Assert.assertTrue(e instanceof PermissionException); @@ -429,11 +420,8 @@ public void publicAddressToShieldedAddressNotConsumeBandwidth() { try { TransactionCapsule transactionCap = getPublicToShieldedTransaction(); //Add public address sign - TransactionSign.Builder transactionSignBuild = TransactionSign.newBuilder(); - transactionSignBuild.setTransaction(transactionCap.getInstance()); - transactionSignBuild.setPrivateKey(ByteString.copyFrom( - ByteArray.fromHexString(ADDRESS_ONE_PRIVATE_KEY))); - transactionCap = transactionUtil.addSign(transactionSignBuild.build()); + transactionCap = TransactionUtils.addTransactionSign(transactionCap.getInstance(), + ADDRESS_ONE_PRIVATE_KEY, dbManager.getAccountStore()); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ByteArray.fromHexString(PUBLIC_ADDRESS_ONE)); @@ -1020,11 +1008,8 @@ public void publicToShieldAddressAndShieldToPublicAddressWithZoreValueSuccess() TransactionCapsule transactionCapOne = builderOne.build(); //Add public address sign - TransactionSign.Builder transactionSignBuild = TransactionSign.newBuilder(); - transactionSignBuild.setTransaction(transactionCapOne.getInstance()); - transactionSignBuild.setPrivateKey(ByteString.copyFrom( - ByteArray.fromHexString(ADDRESS_ONE_PRIVATE_KEY))); - transactionCapOne = transactionUtil.addSign(transactionSignBuild.build()); + transactionCapOne = TransactionUtils.addTransactionSign(transactionCapOne.getInstance(), + ADDRESS_ONE_PRIVATE_KEY, dbManager.getAccountStore()); Assert.assertTrue(dbManager.pushTransaction(transactionCapOne)); AccountCapsule accountCapsuleOne = diff --git a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java index d3cbdb71e95..71501d68a41 100755 --- a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java @@ -93,7 +93,6 @@ import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.Protocol.TransactionSign; import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; import org.tron.protos.contract.ShieldContract.IncrementalMerkleVoucherInfo; import org.tron.protos.contract.ShieldContract.OutputPoint; @@ -102,6 +101,7 @@ import org.tron.protos.contract.ShieldContract.ReceiveDescription; import org.tron.protos.contract.ShieldContract.ShieldedTransferContract; import org.tron.protos.contract.ShieldContract.SpendDescription; +import stest.tron.wallet.common.client.utils.TransactionUtils; @Slf4j public class ShieldedReceiveTest extends BlockGenerate { @@ -329,13 +329,8 @@ public void testBroadcastBeforeAllowZksnark() TransactionCapsule transactionCap = builder.build(); //Add public address sign - TransactionSign.Builder transactionSignBuild = TransactionSign.newBuilder(); - transactionSignBuild.setTransaction(transactionCap.getInstance()); - transactionSignBuild.setPrivateKey(ByteString.copyFrom( - ByteArray.fromHexString(ADDRESS_ONE_PRIVATE_KEY))); - - transactionCap = transactionUtil.addSign(transactionSignBuild.build()); - + transactionCap = TransactionUtils.addTransactionSign(transactionCap.getInstance(), + ADDRESS_ONE_PRIVATE_KEY, chainBaseManager.getAccountStore()); try { dbManager.pushTransaction(transactionCap); Assert.assertFalse(true); diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount011.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount011.java index d50783f72c1..8d829424643 100644 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount011.java +++ b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount011.java @@ -58,13 +58,6 @@ public void beforeClass() { } - @Test(enabled = true) - public void testgenerateAddress() { - EmptyMessage.Builder builder = EmptyMessage.newBuilder(); - blockingStubFull.generateAddress(builder.build()); - blockingStubSolidity.generateAddress(builder.build()); - } - /** * constructor. */ diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java index 8ef8fecbd8e..adb7c0e54a0 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java +++ b/framework/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java @@ -1174,12 +1174,8 @@ public static HttpResponse unFreezeBalance( public static String gettransactionsign( String httpNode, String transactionString, String privateKey) { try { - String requestUrl = "http://" + httpNode + "/wallet/gettransactionsign"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("transaction", transactionString); - userBaseObj2.addProperty("privateKey", privateKey); - response = createConnect(requestUrl, userBaseObj2); - transactionSignString = EntityUtils.toString(response.getEntity()); + transactionSignString = TransactionUtils.getTransactionSign(transactionString, privateKey, + false); } catch (Exception e) { e.printStackTrace(); httppost.releaseConnection(); @@ -2968,36 +2964,6 @@ public static HttpResponse updateEnergyLimit( return response; } - /** constructor. */ - public static HttpResponse createAddress(String httpNode, String value) { - try { - final String requestUrl = "http://" + httpNode + "/wallet/createaddress"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("value", str2hex(value)); - response = createConnect(requestUrl, userBaseObj2); - logger.info(userBaseObj2.toString()); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - /** constructor. */ - public static HttpResponse generateAddress(String httpNode) { - try { - final String requestUrl = "http://" + httpNode + "/wallet/generateaddress"; - JsonObject userBaseObj2 = new JsonObject(); - response = createConnect(requestUrl, userBaseObj2); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - /** constructor. */ public static HttpResponse getTransactionCountByBlocknum(String httpNode, long blocknum) { try { @@ -3029,92 +2995,6 @@ public static HttpResponse validateAddress(String httpNode, String address) { return response; } - /** constructor. */ - public static HttpResponse easyTransfer( - String httpNode, String value, byte[] toAddress, Long amount) { - try { - final String requestUrl = "http://" + httpNode + "/wallet/easytransfer"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("toAddress", ByteArray.toHexString(toAddress)); - userBaseObj2.addProperty("passPhrase", str2hex(value)); - userBaseObj2.addProperty("amount", amount); - response = createConnect(requestUrl, userBaseObj2); - logger.info(userBaseObj2.toString()); - transactionString = EntityUtils.toString(response.getEntity()); - logger.info(transactionString); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - /** constructor. */ - public static HttpResponse easyTransferByPrivate( - String httpNode, String privateKey, byte[] toAddress, Long amount) { - try { - final String requestUrl = "http://" + httpNode + "/wallet/easytransferbyprivate"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("privateKey", privateKey); - userBaseObj2.addProperty("toAddress", ByteArray.toHexString(toAddress)); - userBaseObj2.addProperty("amount", amount); - response = createConnect(requestUrl, userBaseObj2); - logger.info(userBaseObj2.toString()); - transactionString = EntityUtils.toString(response.getEntity()); - logger.info(transactionString); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - /** constructor. */ - public static HttpResponse easyTransferAsset( - String httpNode, String value, byte[] toAddress, Long amount, String assetId) { - try { - final String requestUrl = "http://" + httpNode + "/wallet/easytransferasset"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("toAddress", ByteArray.toHexString(toAddress)); - userBaseObj2.addProperty("passPhrase", str2hex(value)); - userBaseObj2.addProperty("amount", amount); - userBaseObj2.addProperty("assetId", assetId); - response = createConnect(requestUrl, userBaseObj2); - logger.info(userBaseObj2.toString()); - transactionString = EntityUtils.toString(response.getEntity()); - logger.info(transactionString); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - /** constructor. */ - public static HttpResponse easyTransferAssetByPrivate( - String httpNode, String privateKey, byte[] toAddress, Long amount, String assetId) { - try { - final String requestUrl = "http://" + httpNode + "/wallet/easytransferassetbyprivate"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("privateKey", privateKey); - userBaseObj2.addProperty("toAddress", ByteArray.toHexString(toAddress)); - userBaseObj2.addProperty("amount", amount); - userBaseObj2.addProperty("assetId", assetId); - response = createConnect(requestUrl, userBaseObj2); - logger.info(userBaseObj2.toString()); - transactionString = EntityUtils.toString(response.getEntity()); - logger.info(transactionString); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - /** constructor. */ public static HttpResponse getContractInfo(String httpNode, String contractAddress) { try { diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java index cc2af15ec7b..179af83e083 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java +++ b/framework/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java @@ -24,7 +24,13 @@ import org.tron.common.crypto.ECKey; import org.tron.common.crypto.ECKey.ECDSASignature; import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.exception.PermissionException; +import org.tron.core.exception.SignatureFormatException; +import org.tron.core.services.http.JsonFormat; +import org.tron.core.store.AccountStore; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract; import org.tron.protos.contract.AccountContract.AccountCreateContract; @@ -168,7 +174,6 @@ public static boolean validTransaction(Transaction signedTransaction) { */ public static Transaction sign(Transaction transaction, ECKey myKey) { - ByteString lockSript = ByteString.copyFrom(myKey.getAddress()); Transaction.Builder transactionBuilderSigned = transaction.toBuilder(); byte[] hash = Sha256Hash.hash(CommonParameter @@ -185,6 +190,30 @@ public static Transaction sign(Transaction transaction, ECKey myKey) { return transaction; } + public static String getTransactionSign(String transaction, String priKey, + boolean selfType) { + byte[] privateKey = ByteArray.fromHexString(priKey); + Transaction.Builder builder = Transaction.newBuilder(); + try { + JsonFormat.merge(transaction, builder, selfType); + TransactionCapsule trx = new TransactionCapsule(builder.build()); + trx.sign(privateKey); + return JsonFormat.printToString(trx.getInstance(), selfType); + } catch (JsonFormat.ParseException e) { + logger.error("{}", e); + } + return null; + } + + public static TransactionCapsule addTransactionSign(Transaction transaction, String priKey, + AccountStore accountStore) + throws PermissionException, SignatureException, SignatureFormatException { + byte[] privateKey = ByteArray.fromHexString(priKey); + TransactionCapsule trx = new TransactionCapsule(transaction); + trx.addSign(privateKey, accountStore); + return trx; + } + /** * constructor. */ diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestEasyAccount001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestEasyAccount001.java deleted file mode 100644 index a4d854547fd..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestEasyAccount001.java +++ /dev/null @@ -1,281 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Commons; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestEasyAccount001 { - - private static String assetIssueId; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf").getString("defaultParameter.assetUrl"); - long beforeEasyBalance = 0L; - long afterEasyBalance = 0L; - long beforeGenerateBalance = 0L; - long afterGenerateBalance = 0L; - long beforeEasyAsset = 0L; - long afterEasyAsset = 0L; - long beforeGenerateAsset = 0L; - long afterGenerateAsset = 0L; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] assetAddress = ecKey1.getAddress(); - String assetKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private JSONObject responseContent; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(0); - private long now = System.currentTimeMillis(); - private final long totalSupply = now; - private String userPassword = "ps_" + now; - private String assetName = "httpEasyAsset_" + now; - private String easyAddress = null; - private String generatePriKey = null; - private String generateAddress = null; - private String generateHexAddress = null; - - /** - * constructor. - */ - @Test(enabled = true, description = "Create address by http") - public void test01CreateAddress() { - logger.info(userPassword); - response = HttpMethed.createAddress(httpnode, userPassword); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - easyAddress = responseContent.get("base58checkAddress").toString(); - - //Send trx to easy account - response = HttpMethed - .sendCoin(httpnode, fromAddress, Commons.decodeFromBase58Check(easyAddress), 5000000L, - testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - beforeEasyBalance = HttpMethed.getBalance(httpnode, Commons.decodeFromBase58Check(easyAddress)); - logger.info("beforeEasyBalance: " + beforeEasyBalance); - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Generate address by http") - public void test02GenerateAddress() { - response = HttpMethed.generateAddress(httpnode); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - generateAddress = responseContent.get("address").toString(); - generateHexAddress = responseContent.get("hexAddress").toString(); - generatePriKey = responseContent.get("privateKey").toString(); - - //Send trx to easy account - response = HttpMethed - .sendCoin(httpnode, fromAddress, Commons.decodeFromBase58Check(generateAddress), 5000000L, - testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - beforeGenerateBalance = HttpMethed - .getBalance(httpnode, Commons.decodeFromBase58Check(generateAddress)); - logger.info("beforeGenerateBalance: " + beforeGenerateBalance); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "Validate address by http") - public void test03ValideteAddress() { - // Base58check format - response = HttpMethed.validateAddress(httpnode, generateAddress); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - // Hex string format - response = HttpMethed.validateAddress(httpnode, generateHexAddress); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "Easy transfer by http") - public void test04EasyTransfer() { - response = HttpMethed - .easyTransfer(httpnode, userPassword, Commons.decodeFromBase58Check(generateAddress), - 1000000L); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - HttpMethed.waitToProduceOneBlock(httpnode); - - //Send trx to easy account - afterEasyBalance = HttpMethed.getBalance(httpnode, Commons.decodeFromBase58Check(easyAddress)); - logger.info("afterEasyBalance: " + afterEasyBalance); - - afterGenerateBalance = HttpMethed - .getBalance(httpnode, Commons.decodeFromBase58Check(generateAddress)); - logger.info("afterGenerateBalance: " + afterGenerateBalance); - - Assert.assertEquals(beforeEasyBalance - afterEasyBalance, - afterGenerateBalance - beforeGenerateBalance); - beforeEasyBalance = afterEasyBalance; - beforeGenerateBalance = afterGenerateBalance; - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Easy transfer by privateKey by http") - public void test05EasyTransferByPrivateKey() { - response = HttpMethed - .easyTransferByPrivate(httpnode, generatePriKey, Commons.decodeFromBase58Check(easyAddress), - 1000000L); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - HttpMethed.waitToProduceOneBlock(httpnode); - - //Send trx to easy account - afterEasyBalance = HttpMethed.getBalance(httpnode, Commons.decodeFromBase58Check(easyAddress)); - logger.info("beforeEasyBalance: " + beforeEasyBalance); - logger.info("afterEasyBalance: " + afterEasyBalance); - - afterGenerateBalance = HttpMethed - .getBalance(httpnode, Commons.decodeFromBase58Check(generateAddress)); - logger.info("beforeGenerateBalance: " + beforeGenerateBalance); - logger.info("afterGenerateBalance: " + afterGenerateBalance); - - Assert.assertEquals(beforeGenerateBalance - afterGenerateBalance, - afterEasyBalance - beforeEasyBalance); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Create asset issue by http") - public void test06CreateAssetIssue() { - Long amount = 2048000000L; - response = HttpMethed.sendCoin(httpnode, fromAddress, assetAddress, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - //Create an asset issue - response = HttpMethed - .assetIssue(httpnode, assetAddress, assetName, assetName, totalSupply, 1, 1, - System.currentTimeMillis() + 5000, System.currentTimeMillis() + 50000000, 2, 3, - description, url, 1000L, 1000L, assetKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed.getAccount(httpnode, assetAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - assetIssueId = responseContent.getString("asset_issued_ID"); - logger.info(assetIssueId); - Assert.assertTrue(Integer.parseInt(assetIssueId) > 1000000); - - response = HttpMethed - .transferAsset(httpnode, assetAddress, Commons.decodeFromBase58Check(easyAddress), - assetIssueId, 100L, assetKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed.getAccount(httpnode, Commons.decodeFromBase58Check(easyAddress)); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - beforeEasyAsset = responseContent.getJSONArray("assetV2").getJSONObject(0) - .getLongValue("value"); - logger.info("beforeEasyAsset:" + beforeEasyAsset); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Easy transfer asset by http") - public void test07EasyTransferAsset() { - response = HttpMethed - .easyTransferAsset(httpnode, userPassword, Commons.decodeFromBase58Check(generateAddress), - 10L, assetIssueId); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed.getAccount(httpnode, Commons.decodeFromBase58Check(easyAddress)); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - afterEasyAsset = responseContent.getJSONArray("assetV2").getJSONObject(0).getLongValue("value"); - logger.info("afterEasyAsset:" + afterEasyAsset); - - response = HttpMethed.getAccount(httpnode, Commons.decodeFromBase58Check(generateAddress)); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - beforeGenerateAsset = responseContent.getJSONArray("assetV2").getJSONObject(0) - .getLongValue("value"); - logger.info("beforeGenerateAsset:" + beforeGenerateAsset); - Assert.assertEquals(beforeEasyAsset - afterEasyAsset, beforeGenerateAsset); - beforeEasyAsset = afterEasyAsset; - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Easy transfer asset by private key by http") - public void test08EasyTransferAssetByPrivateKey() { - response = HttpMethed.easyTransferAssetByPrivate(httpnode, generatePriKey, - Commons.decodeFromBase58Check(easyAddress), 5L, assetIssueId); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed.getAccount(httpnode, Commons.decodeFromBase58Check(easyAddress)); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - afterEasyAsset = responseContent.getJSONArray("assetV2").getJSONObject(0).getLongValue("value"); - logger.info("beforeEasyAsset:" + beforeEasyAsset); - logger.info("afterEasyAsset:" + afterEasyAsset); - - response = HttpMethed.getAccount(httpnode, Commons.decodeFromBase58Check(generateAddress)); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - afterGenerateAsset = responseContent.getJSONArray("assetV2").getJSONObject(0) - .getLongValue("value"); - logger.info("afterGenerateAsset:" + afterGenerateAsset); - Assert.assertEquals(beforeGenerateAsset - afterGenerateAsset, afterEasyAsset - beforeEasyAsset); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.freedResource(httpnode, Commons.decodeFromBase58Check(generateAddress), fromAddress, - generatePriKey); - HttpMethed.freedResource(httpnode, assetAddress, fromAddress, assetKey); - HttpMethed.disConnect(); - } - -} diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 48cd64acc5b..70297d0959b 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -624,68 +624,6 @@ service Wallet { } }; } - //Warning: do not invoke this interface provided by others. - //Please use GetTransactionSign2 instead of this function. - rpc GetTransactionSign (TransactionSign) returns (Transaction) { - option (google.api.http) = { - post: "/wallet/gettransactionsign" - body: "*" - additional_bindings { - get: "/wallet/gettransactionsign" - } - }; - }; - //Warning: do not invoke this interface provided by others. - //Use this function instead of GetTransactionSign. - rpc GetTransactionSign2 (TransactionSign) returns (TransactionExtention) { - }; - //Warning: do not invoke this interface provided by others. - rpc CreateAddress (BytesMessage) returns (BytesMessage) { - option (google.api.http) = { - post: "/wallet/createaddress" - body: "*" - additional_bindings { - get: "/wallet/createaddress" - } - }; - }; - //Warning: do not invoke this interface provided by others. - rpc EasyTransferAsset (EasyTransferAssetMessage) returns (EasyTransferResponse) { - }; - //Warning: do not invoke this interface provided by others. - rpc EasyTransferAssetByPrivate (EasyTransferAssetByPrivateMessage) returns (EasyTransferResponse) { - }; - //Warning: do not invoke this interface provided by others. - rpc EasyTransfer (EasyTransferMessage) returns (EasyTransferResponse) { - option (google.api.http) = { - post: "/wallet/easytransfer" - body: "*" - additional_bindings { - get: "/wallet/easytransfer" - } - }; - }; - //Warning: do not invoke this interface provided by others. - rpc EasyTransferByPrivate (EasyTransferByPrivateMessage) returns (EasyTransferResponse) { - option (google.api.http) = { - post: "/wallet/easytransferbyprivate" - body: "*" - additional_bindings { - get: "/wallet/easytransferbyprivate" - } - }; - }; - //Warning: do not invoke this interface provided by others. - rpc GenerateAddress (EmptyMessage) returns (AddressPrKeyPairMessage) { - - option (google.api.http) = { - post: "/wallet/generateaddress" - body: "*" - additional_bindings { - get: "/wallet/generateaddress" - } - }; - } rpc GetTransactionInfoById (BytesMessage) returns (TransactionInfo) { option (google.api.http) = { @@ -707,10 +645,6 @@ service Wallet { }; } - rpc AddSign (TransactionSign) returns (TransactionExtention) { - - } - rpc GetTransactionSignWeight (Transaction) returns (TransactionSignWeight) { } @@ -968,17 +902,6 @@ service WalletSolidity { }; } - //Warning: do not invoke this interface provided by others. - rpc GenerateAddress (EmptyMessage) returns (AddressPrKeyPairMessage) { - option (google.api.http) = { - post: "/walletsolidity/generateaddress" - body: "*" - additional_bindings { - get: "/walletsolidity/generateaddress" - } - }; - } - rpc GetMerkleTreeVoucherInfo (OutputPointInfo) returns (IncrementalMerkleVoucherInfo) { } @@ -1269,43 +1192,6 @@ message PaginatedMessage { int64 limit = 2; } -message EasyTransferMessage { - bytes passPhrase = 1; - bytes toAddress = 2; - int64 amount = 3; -} - -message EasyTransferAssetMessage { - bytes passPhrase = 1; - bytes toAddress = 2; - string assetId = 3; - int64 amount = 4; -} - -message EasyTransferByPrivateMessage { - bytes privateKey = 1; - bytes toAddress = 2; - int64 amount = 3; -} - -message EasyTransferAssetByPrivateMessage { - bytes privateKey = 1; - bytes toAddress = 2; - string assetId = 3; - int64 amount = 4; -} - -message EasyTransferResponse { - Transaction transaction = 1; - Return result = 2; - bytes txid = 3; //transaction id = sha256(transaction.rowdata) -} - -message AddressPrKeyPairMessage { - string address = 1; - string privateKey = 2; -} - message TransactionExtention { Transaction transaction = 1; bytes txid = 2; //transaction id = sha256(transaction.rowdata) diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index e6aac408f95..dafee3a6afd 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -494,11 +494,6 @@ message Transactions { repeated Transaction transactions = 1; } -message TransactionSign { - Transaction transaction = 1; - bytes privateKey = 2; -} - message BlockHeader { message raw { int64 timestamp = 1; From ab6a65e117049f5a23df0866471e3ddff0bf898b Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 13 Apr 2023 19:23:38 +0800 Subject: [PATCH 0736/1197] feat(net): optimize p2p exception type description --- .../src/main/java/org/tron/core/exception/P2pException.java | 4 ++-- .../src/main/java/org/tron/core/net/TronNetDelegate.java | 6 +++--- .../java/org/tron/core/net/service/sync/SyncService.java | 6 ++---- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/common/src/main/java/org/tron/core/exception/P2pException.java b/common/src/main/java/org/tron/core/exception/P2pException.java index 33c4c4fbec7..00d82e9fbf7 100644 --- a/common/src/main/java/org/tron/core/exception/P2pException.java +++ b/common/src/main/java/org/tron/core/exception/P2pException.java @@ -50,8 +50,8 @@ public enum TypeEnum { TRX_EXE_FAILED(12, "trx exe failed"), DB_ITEM_NOT_FOUND(13, "DB item not found"), PROTOBUF_ERROR(14, "protobuf inconsistent"), - SIGN_ERROR(15, "sign error"), - CALC_MERKLE_ROOT_FAILED(16, "calc merkle root failed"), + BLOCK_SIGN_ERROR(15, "block sign error"), + BLOCK_MERKLE_ERROR(16, "block merkle error"), DEFAULT(100, "default exception"); diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index f840341c1b2..3e7381a0504 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -285,7 +285,7 @@ public void processBlock(BlockCapsule block, boolean isSync) throws P2pException logger.error("Process block failed, {}, reason: {}", blockId.getString(), e.getMessage()); if (e instanceof BadBlockException && ((BadBlockException) e).getType().equals(CALC_MERKLE_ROOT_FAILED)) { - throw new P2pException(TypeEnum.CALC_MERKLE_ROOT_FAILED, e); + throw new P2pException(TypeEnum.BLOCK_MERKLE_ERROR, e); } else { throw new P2pException(TypeEnum.BAD_BLOCK, e); } @@ -318,10 +318,10 @@ public void validSignature(BlockCapsule block) throws P2pException { try { if (!block.validateSignature(dbManager.getDynamicPropertiesStore(), dbManager.getAccountStore())) { - throw new P2pException(TypeEnum.SIGN_ERROR, "valid signature failed."); + throw new P2pException(TypeEnum.BLOCK_SIGN_ERROR, "valid signature failed."); } } catch (ValidateSignatureException e) { - throw new P2pException(TypeEnum.SIGN_ERROR, e); + throw new P2pException(TypeEnum.BLOCK_SIGN_ERROR, e); } } diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 2ba35723e06..86b775df6f8 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -1,8 +1,6 @@ package org.tron.core.net.service.sync; import static org.tron.core.config.Parameter.NetConstants.MAX_BLOCK_FETCH_PER_PEER; -import static org.tron.core.exception.P2pException.TypeEnum.CALC_MERKLE_ROOT_FAILED; -import static org.tron.core.exception.P2pException.TypeEnum.SIGN_ERROR; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; @@ -289,8 +287,8 @@ private void processSyncBlock(BlockCapsule block, PeerConnection peerConnection) } catch (P2pException p2pException) { logger.error("Process sync block {} failed, type: {}", blockId.getString(), p2pException.getType()); - attackFlag = p2pException.getType().equals(SIGN_ERROR) - || p2pException.getType().equals(CALC_MERKLE_ROOT_FAILED); + attackFlag = p2pException.getType().equals(TypeEnum.BLOCK_SIGN_ERROR) + || p2pException.getType().equals(TypeEnum.BLOCK_MERKLE_ERROR); flag = false; } catch (Exception e) { logger.error("Process sync block {} failed", blockId.getString(), e); From 071a15bf69caebb59e42387ab0a144194b78c609 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 14 Apr 2023 12:15:52 +0800 Subject: [PATCH 0737/1197] fix(net):modify BaseNet --- .../main/java/org/tron/core/net/TronNetService.java | 10 +++++++--- framework/src/test/java/org/tron/core/net/BaseNet.java | 8 ++++---- .../core/net/services/EffectiveCheckServiceTest.java | 2 +- framework/src/test/resources/config-test.conf | 2 +- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index dda3be886dc..2e9345a6794 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -82,8 +82,7 @@ private static void setP2pConfig(P2pConfig config) { public void start() { try { init = true; - P2pConfig config = new P2pConfig(); - setP2pConfig(getConfig(config)); + setP2pConfig(getConfig()); p2pService.start(p2pConfig); p2pService.register(p2pEventHandler); advService.init(); @@ -148,7 +147,12 @@ public static boolean hasIpv4Stack(Set ipSet) { return false; } - private P2pConfig getConfig(P2pConfig config) { + private P2pConfig getConfig(){ + P2pConfig config = new P2pConfig(); + return updateConfig(config); + } + + private P2pConfig updateConfig(P2pConfig config) { List seeds = parameter.getSeedNode().getAddressList(); seeds.addAll(nodePersistService.dbRead()); logger.debug("Seed InetSocketAddress: {}", seeds); diff --git a/framework/src/test/java/org/tron/core/net/BaseNet.java b/framework/src/test/java/org/tron/core/net/BaseNet.java index ca42dc2a65e..64d4b128543 100644 --- a/framework/src/test/java/org/tron/core/net/BaseNet.java +++ b/framework/src/test/java/org/tron/core/net/BaseNet.java @@ -103,9 +103,9 @@ public void run() { } }); int tryTimes = 0; - while (++tryTimes < 100 && tronNetDelegate == null) { - Thread.sleep(3000); - } + do { + Thread.sleep(3000); //coverage consumerInvToSpread,consumerInvToFetch in AdvService.init + } while (++tryTimes < 100 && tronNetDelegate == null); } @After @@ -115,7 +115,7 @@ public void destroy() { for (PeerConnection peer : peerConnections) { peer.getChannel().close(); } - + Args.clearParam(); context.destroy(); FileUtil.deleteDir(new File(dbPath)); } diff --git a/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java b/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java index 1c422047e10..aa42e0fcb89 100644 --- a/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java @@ -42,7 +42,7 @@ public void destroy() { public void testNoIpv4() throws Exception { TronNetService tronNetService = context.getBean(TronNetService.class); Method privateMethod = tronNetService.getClass() - .getDeclaredMethod("getConfig", P2pConfig.class); + .getDeclaredMethod("updateConfig", P2pConfig.class); privateMethod.setAccessible(true); P2pConfig config = new P2pConfig(); config.setIp(null); diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index bef8239fd86..dea5d72961d 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -108,7 +108,7 @@ node { # use your ipv6 address for node discovery and tcp connection, default false enableIpv6 = false - # if your node's highest block num is below than all your pees', try to acquire new connection + # if your node's highest block num is below than all your pees', try to acquire new connection, default false effectiveCheckEnable = false dns { From 1b2024de69eeabc3545f4c4e63e21466c1616737 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 14 Apr 2023 12:17:34 +0800 Subject: [PATCH 0738/1197] fix(net):format code --- framework/src/main/java/org/tron/core/net/TronNetService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 2e9345a6794..87d878be8c9 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -147,7 +147,7 @@ public static boolean hasIpv4Stack(Set ipSet) { return false; } - private P2pConfig getConfig(){ + private P2pConfig getConfig() { P2pConfig config = new P2pConfig(); return updateConfig(config); } From fbcbd6ee98c26e04dcc5e9765e1cdbd6995954ca Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 14 Apr 2023 15:57:50 +0800 Subject: [PATCH 0739/1197] fix(net):optimize BaseNet --- .../test/java/org/tron/core/net/BaseNet.java | 76 ++++++++++--------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/framework/src/test/java/org/tron/core/net/BaseNet.java b/framework/src/test/java/org/tron/core/net/BaseNet.java index 64d4b128543..6af079a0197 100644 --- a/framework/src/test/java/org/tron/core/net/BaseNet.java +++ b/framework/src/test/java/org/tron/core/net/BaseNet.java @@ -19,8 +19,8 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; -import org.junit.After; -import org.junit.Before; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; @@ -34,20 +34,20 @@ import org.tron.core.services.RpcApiService; @Slf4j -public abstract class BaseNet { +public class BaseNet { private static String dbPath = "output-net"; private static String dbDirectory = "net-database"; private static String indexDirectory = "net-index"; private static int port = 10000; - protected TronApplicationContext context; + protected static TronApplicationContext context; - private RpcApiService rpcApiService; - private Application appT; - private TronNetDelegate tronNetDelegate; + private static RpcApiService rpcApiService; + private static Application appT; + private static TronNetDelegate tronNetDelegate; - private ExecutorService executorService = Executors.newFixedThreadPool(1); + private static ExecutorService executorService = Executors.newFixedThreadPool(1); public static Channel connect(ByteToMessageDecoder decoder) throws InterruptedException { NioEventLoopGroup group = new NioEventLoopGroup(1); @@ -73,34 +73,36 @@ protected void initChannel(Channel ch) throws Exception { return b.connect(Constant.LOCAL_HOST, port).sync().channel(); } - @Before - public void init() throws Exception { - executorService.execute(new Runnable() { - @Override - public void run() { - logger.info("Full node running."); - Args.setParam( - new String[]{ - "--output-directory", dbPath, - "--storage-db-directory", dbDirectory, - "--storage-index-directory", indexDirectory - }, - "config.conf" - ); - CommonParameter parameter = Args.getInstance(); - parameter.setNodeListenPort(port); - parameter.getSeedNode().getAddressList().clear(); - parameter.setNodeExternalIp(Constant.LOCAL_HOST); - context = new TronApplicationContext(DefaultConfig.class); - appT = ApplicationFactory.create(context); - rpcApiService = context.getBean(RpcApiService.class); - appT.addService(rpcApiService); - appT.initServices(parameter); - appT.startServices(); - appT.startup(); - tronNetDelegate = context.getBean(TronNetDelegate.class); - rpcApiService.blockUntilShutdown(); + @BeforeClass + public static void init() throws Exception { + executorService.execute(() -> { + logger.info("Full node running."); + Args.setParam( + new String[]{ + "--output-directory", dbPath, + "--storage-db-directory", dbDirectory, + "--storage-index-directory", indexDirectory + }, + "config.conf" + ); + CommonParameter parameter = Args.getInstance(); + parameter.setNodeListenPort(port); + parameter.getSeedNode().getAddressList().clear(); + parameter.setNodeExternalIp(Constant.LOCAL_HOST); + context = new TronApplicationContext(DefaultConfig.class); + appT = ApplicationFactory.create(context); + rpcApiService = context.getBean(RpcApiService.class); + appT.addService(rpcApiService); + appT.initServices(parameter); + appT.startServices(); + appT.startup(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + //ignore } + tronNetDelegate = context.getBean(TronNetDelegate.class); + rpcApiService.blockUntilShutdown(); }); int tryTimes = 0; do { @@ -108,8 +110,8 @@ public void run() { } while (++tryTimes < 100 && tronNetDelegate == null); } - @After - public void destroy() { + @AfterClass + public static void destroy() { Collection peerConnections = ReflectUtils .invokeMethod(tronNetDelegate, "getActivePeer"); for (PeerConnection peer : peerConnections) { From 27f2255596ef335890a67af153b990b57c29fcdb Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 14 Apr 2023 16:10:36 +0800 Subject: [PATCH 0740/1197] func(interface): remove the added field --- framework/src/main/java/org/tron/core/Wallet.java | 2 -- protocol/src/main/protos/api/api.proto | 2 -- 2 files changed, 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 02d1d1d2f9f..487d6aaa886 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -3034,8 +3034,6 @@ public Transaction callConstantContract(TransactionCapsule trxCap, TransactionResultCapsule ret = new TransactionResultCapsule(); builder.setEnergyUsed(result.getEnergyUsed()); - builder.setBlockNumber(headBlockCapsule.getNum()); - builder.setBlockHash(ByteString.copyFrom(headBlockCapsule.getBlockId().getBytes())); builder.setEnergyPenalty(result.getEnergyPenaltyTotal()); builder.addConstantResult(ByteString.copyFrom(result.getHReturn())); result.getLogInfoList().forEach(logInfo -> diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 57bd5a4e748..70297d0959b 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -1201,8 +1201,6 @@ message TransactionExtention { repeated TransactionInfo.Log logs = 6; repeated InternalTransaction internal_transactions = 7; int64 energy_penalty = 8; - int64 block_number = 9; - bytes block_hash = 10; } message EstimateEnergyMessage { From 403da93b5c07b2994bd4cfbd4b62cd07bd7f45b0 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 14 Apr 2023 19:25:30 +0800 Subject: [PATCH 0741/1197] fix(net):optimize BaseNet --- framework/src/test/java/org/tron/core/net/BaseNet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/test/java/org/tron/core/net/BaseNet.java b/framework/src/test/java/org/tron/core/net/BaseNet.java index 6af079a0197..805f8aa76a4 100644 --- a/framework/src/test/java/org/tron/core/net/BaseNet.java +++ b/framework/src/test/java/org/tron/core/net/BaseNet.java @@ -97,7 +97,7 @@ public static void init() throws Exception { appT.startServices(); appT.startup(); try { - Thread.sleep(1000); + Thread.sleep(2000); } catch (InterruptedException e) { //ignore } From 66a646e6fa2bc609ed6e319acabe022a07b4978d Mon Sep 17 00:00:00 2001 From: "morgan.peng" Date: Thu, 30 Mar 2023 20:13:39 +0800 Subject: [PATCH 0742/1197] feat(db): prune lite node data automatically Prune lite node data automatically --- .../common/storage/prune/ChainDataPruner.java | 149 +++++++++++++ .../java/org/tron/core/ChainBaseManager.java | 12 +- .../org/tron/core/db2/core/SnapshotRoot.java | 4 + .../src/main/java/org/tron/core/Constant.java | 4 + .../org/tron/core/config/args/Storage.java | 77 +++++++ .../java/org/tron/core/config/args/Args.java | 1 + .../main/java/org/tron/core/db/Manager.java | 4 + .../net/message/handshake/HelloMessage.java | 21 +- framework/src/main/resources/config.conf | 11 + .../storage/prune/ChainDataPrunerTest.java | 202 ++++++++++++++++++ framework/src/test/resources/config-test.conf | 11 + 11 files changed, 492 insertions(+), 4 deletions(-) create mode 100644 chainbase/src/main/java/org/tron/common/storage/prune/ChainDataPruner.java create mode 100644 framework/src/test/java/org/tron/common/storage/prune/ChainDataPrunerTest.java diff --git a/chainbase/src/main/java/org/tron/common/storage/prune/ChainDataPruner.java b/chainbase/src/main/java/org/tron/common/storage/prune/ChainDataPruner.java new file mode 100644 index 00000000000..ed6cc3c37d9 --- /dev/null +++ b/chainbase/src/main/java/org/tron/common/storage/prune/ChainDataPruner.java @@ -0,0 +1,149 @@ +package org.tron.common.storage.prune; + +import com.google.common.primitives.Longs; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import javax.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.Commons; +import org.tron.core.ChainBaseManager; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.db2.common.Flusher; +import org.tron.core.db2.common.Value; +import org.tron.core.db2.common.WrappedByteArray; +import org.tron.core.db2.core.SnapshotRoot; + +@Slf4j(topic = "db") +@Component +public class ChainDataPruner { + + private static final String BLOCK_INDEX_STORE_NAME = "block-index"; + private static final String BLOCK_STORE_NAME = "block"; + private static final String TRANSACTION_STORE_NAME = "trans"; + private static final String TRANSACTION_RET_STORE_NAME = "transactionRetStore"; + private static final Set PRUNE_DBS = new HashSet<>(Arrays.asList(BLOCK_INDEX_STORE_NAME + , BLOCK_STORE_NAME, TRANSACTION_STORE_NAME, TRANSACTION_RET_STORE_NAME)); + private long blocksToRetain = CommonParameter.getInstance().getStorage(). + getDbAutoPruneRetain(); + private long blocksBatchFlush = CommonParameter.getInstance().getStorage().getDbAutoPruneBatch(); + private static Map snapshotRootMap = new ConcurrentHashMap<>(); + + private ScheduledExecutorService pruneExecutor = null; + + @Autowired + private ChainBaseManager chainBaseManager; + + @PostConstruct + public void init() { + if ((!chainBaseManager.isLiteNode()) || + (!CommonParameter.getInstance().getStorage().isDbAutoPrune())) { + return; + } + pruneExecutor = Executors.newSingleThreadScheduledExecutor( + new ThreadFactoryBuilder().setNameFormat("db-prune-thread-%d").build()); + pruneExecutor.scheduleWithFixedDelay(() -> { + try { + if (!shouldBeginPrune()) { + return; + } + prune(); + } catch (InterruptedException e) { + logger.warn("Prune chain data thread interrupted!"); + Thread.currentThread().interrupt(); + } + }, 60, + CommonParameter.getInstance().getStorage().getDbAutoPruneFrequency(), TimeUnit.SECONDS); + } + + private boolean shouldBeginPrune() { + OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); + int currentHour = now.getHour(); + return currentHour >= 20 || currentHour < 2; + } + + public static void register(String dbName, SnapshotRoot snapshotRoot) { + if ((!CommonParameter.getInstance().getStorage().isDbAutoPrune()) + ||(!PRUNE_DBS.contains(dbName))) { + return; + } + snapshotRootMap.put(dbName, snapshotRoot); + } + + public void prune() throws InterruptedException { + long lowestBlockNumber = chainBaseManager.getBlockStore().getLimitNumber(1, 1). + stream().map(BlockCapsule::getNum).findFirst().get(); + long latestBlockNumber = chainBaseManager.getDynamicPropertiesStore(). + getLatestBlockHeaderNumberFromDB(); + if (latestBlockNumber - lowestBlockNumber + 1 > blocksToRetain) { + doPrune(lowestBlockNumber, latestBlockNumber); + } + } + + private void doPrune(long lowestBlockNumber, long latestBlockNumber) { + long toFetchCount = + Math.min((latestBlockNumber - lowestBlockNumber + 1 - blocksToRetain), blocksBatchFlush); + List blockCapsuleList = chainBaseManager.getBlockStore() + .getLimitNumber(lowestBlockNumber, toFetchCount); + Map blockIdBatch = new HashMap<>(); + Map blockNumBatch = new HashMap<>(); + Map transIdBatch = new HashMap<>(); + prepareWriteBatch(blockIdBatch, blockNumBatch, transIdBatch, blockCapsuleList); + flushDb(blockIdBatch, blockNumBatch, transIdBatch); + } + + private void flushDb(Map blockIdBatch, + Map blockNumBatch, + Map transIdBatch) { + SnapshotRoot transactionRoot = snapshotRootMap.get(TRANSACTION_STORE_NAME); + ((Flusher)transactionRoot.getDb()).flush(transIdBatch); + SnapshotRoot transactionRetRoot = snapshotRootMap.get(TRANSACTION_RET_STORE_NAME); + ((Flusher)transactionRetRoot.getDb()).flush(blockNumBatch); + SnapshotRoot blockIndexRoot = snapshotRootMap.get(BLOCK_INDEX_STORE_NAME); + ((Flusher)blockIndexRoot.getDb()).flush(blockNumBatch); + SnapshotRoot blockRoot = snapshotRootMap.get(BLOCK_STORE_NAME); + ((Flusher)blockRoot.getDb()).flush(blockIdBatch); + } + + private void prepareWriteBatch ( + Map blockIdBatch, + Map blockNumBatch, + Map transIdBatch, + List blockCapsuleList) { + for (BlockCapsule blockCapsule: blockCapsuleList) { + blockIdBatch.put(WrappedByteArray.of(blockCapsule.getBlockId().getBytes()), + WrappedByteArray.of(Value.of(Value.Operator.DELETE, null).getBytes())); + blockNumBatch.put(WrappedByteArray.of(Longs.toByteArray(blockCapsule.getNum())), + WrappedByteArray.of(Value.of(Value.Operator.DELETE, null).getBytes())); + blockCapsule.getTransactions().forEach(tx-> transIdBatch.put(WrappedByteArray.of(tx. + getTransactionId().getBytes()), WrappedByteArray.of(Value.of(Value.Operator.DELETE, + null).getBytes()))); + } + } + + public void shutdown() { + if (Objects.nonNull(pruneExecutor)) { + try { + pruneExecutor.shutdown(); + } catch (Exception e) { + logger.error("Chain pruner shutdown error: {}", e.getMessage()); + } + } + } + +} diff --git a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java index c9ced891ee6..9511735f22a 100644 --- a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java +++ b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java @@ -11,6 +11,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.common.parameter.CommonParameter; import org.tron.common.storage.metric.DbStatService; import org.tron.common.utils.ForkController; import org.tron.common.utils.Sha256Hash; @@ -241,8 +242,6 @@ public class ChainBaseManager { @Setter private NodeType nodeType; - @Getter - @Setter private long lowestBlockNum = -1; // except num = 0. public void closeOneStore(ITronChainBase database) { @@ -431,6 +430,15 @@ private void init() { this.nodeType = getLowestBlockNum() > 1 ? NodeType.LITE : NodeType.FULL; } + public long getLowestBlockNum(){ + if(isLiteNode() && CommonParameter.getInstance().getStorage().isDbAutoPrune()) { + return this.blockIndexStore.getLimitNumber(1, 1).stream() + .map(BlockId::getNum).findFirst().orElseThrow( + () -> new IllegalArgumentException("LowestBlockNum not found!")); + } + return lowestBlockNum; + } + public boolean isLiteNode() { return getNodeType() == NodeType.LITE; } diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java index 709e2ae1b62..66173ea45a1 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java @@ -2,17 +2,20 @@ import com.google.common.collect.Maps; import com.google.common.collect.Streams; +import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.stream.Collectors; import lombok.Getter; import org.tron.common.cache.CacheManager; import org.tron.common.cache.CacheType; import org.tron.common.cache.TronCache; import org.tron.common.parameter.CommonParameter; +import org.tron.common.storage.prune.ChainDataPruner; import org.tron.common.utils.ByteArray; import org.tron.core.ChainBaseManager; import org.tron.core.capsule.AccountCapsule; @@ -38,6 +41,7 @@ public SnapshotRoot(DB db) { if (CACHE_DBS.contains(this.db.getDbName())) { this.cache = CacheManager.allocate(CacheType.findByType(this.db.getDbName())); } + ChainDataPruner.register(this.db.getDbName(), this); } private boolean needOptAsset() { diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 2f08df3e931..9044af43ca4 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -1,5 +1,7 @@ package org.tron.core; +import org.tron.core.config.Parameter.ChainConstant; + public class Constant { //config for testnet, mainnet, beta @@ -39,6 +41,8 @@ public class Constant { public static final int ONE_HUNDRED = 100; public static final int ONE_THOUSAND = 1000; + public static final long ONE_DAY_BLOCKS_PREDICT = 24 * 60 * 60 * 1000 / ChainConstant.BLOCK_PRODUCED_INTERVAL; + public static final byte[] ZTRON_EXPANDSEED_PERSONALIZATION = {'Z', 't', 'r', 'o', 'n', '_', 'E', 'x', 'p', 'a', 'n', 'd', 'S', 'e', 'e', 'd'}; diff --git a/common/src/main/java/org/tron/core/config/args/Storage.java b/common/src/main/java/org/tron/core/config/args/Storage.java index 778d4d0141c..9f2182816f3 100644 --- a/common/src/main/java/org/tron/core/config/args/Storage.java +++ b/common/src/main/java/org/tron/core/config/args/Storage.java @@ -32,6 +32,7 @@ import org.tron.common.utils.DbOptionalsUtils; import org.tron.common.utils.FileUtil; import org.tron.common.utils.Property; +import org.tron.core.Constant; /** * Custom storage configurations @@ -54,6 +55,10 @@ public class Storage { private static final String ESTIMATED_TRANSACTIONS_CONFIG_KEY = "storage.txCache.estimatedTransactions"; private static final String SNAPSHOT_MAX_FLUSH_COUNT_CONFIG_KEY = "storage.snapshot.maxFlushCount"; + private static final String DB_AUTO_PRUNE_SWITCH_CONFIG_KEY = "storage.prune.enable"; + private static final String DB_AUTO_PRUNE_RETAIN_CONFIG_KEY = "storage.prune.retain"; + private static final String DB_AUTO_PRUNE_FREQUENCY_CONFIG_KEY = "storage.prune.frequency"; + private static final String DB_AUTO_PRUNE_BATCH_CONFIG_KEY = "storage.prune.batch"; private static final String PROPERTIES_CONFIG_KEY = "storage.properties"; private static final String PROPERTIES_CONFIG_DB_KEY = "storage"; private static final String PROPERTIES_CONFIG_DEFAULT_KEY = "default"; @@ -91,6 +96,11 @@ public class Storage { private static final boolean DEFAULT_CHECKPOINT_SYNC = true; private static final int DEFAULT_ESTIMATED_TRANSACTIONS = 1000; private static final int DEFAULT_SNAPSHOT_MAX_FLUSH_COUNT = 1; + private static final boolean DEFAULT_DB_AUTO_PRUNE_SWITCH = false; + private static final int DEFAULT_DB_AUTO_PRUNE_RETAIN = 864000; + private static final int DEFAULT_DB_AUTO_PRUNE_FREQUENCY = 3; + private static final int DEFAULT_DB_AUTO_PRUNE_BATCH = 50; + private Config storage; /** @@ -112,6 +122,22 @@ public class Storage { @Setter private int maxFlushCount; + @Getter + @Setter + private boolean dbAutoPrune; + + @Getter + @Setter + private int dbAutoPruneRetain; + + @Getter + @Setter + private int dbAutoPruneFrequency; + + @Getter + @Setter + private int dbAutoPruneBatch; + /** * Index storage directory: /path/to/{indexDirectory} */ @@ -182,6 +208,57 @@ public static int getSnapshotMaxFlushCountFromConfig(final Config config) { return maxFlushCountConfig; } + public void setDbAutoPruneInfo(final Config config) { + setDbAutoPrune(Storage.getDbAutoPruneSwitchFromConfig(config)); + setDbAutoPruneRetain(Storage.getDbAutoPruneRetainFromConfig(config)); + setDbAutoPruneFrequency( + Storage.getDbAutoPruneFrequencyFromConfig(config)); + setDbAutoPruneBatch(Storage.getDbAutoPruneBatchFromConfig(config)); + } + + public static boolean getDbAutoPruneSwitchFromConfig(final Config config) { + return config.hasPath(DB_AUTO_PRUNE_SWITCH_CONFIG_KEY) + ? config.getBoolean(DB_AUTO_PRUNE_SWITCH_CONFIG_KEY) : DEFAULT_DB_AUTO_PRUNE_SWITCH; + } + + public static int getDbAutoPruneRetainFromConfig(final Config config) { + if (!config.hasPath(DB_AUTO_PRUNE_RETAIN_CONFIG_KEY)) { + return DEFAULT_DB_AUTO_PRUNE_RETAIN; + } + int dbAutoPruneRetain = config.getInt(DB_AUTO_PRUNE_RETAIN_CONFIG_KEY); + if (dbAutoPruneRetain < 30 * Constant.ONE_DAY_BLOCKS_PREDICT) { + throw new IllegalArgumentException( + "[storage.prune.retain] value must not be less than 864000!"); + } + return dbAutoPruneRetain; + } + + public static int getDbAutoPruneFrequencyFromConfig(final Config config) { + if (!config.hasPath(DB_AUTO_PRUNE_FREQUENCY_CONFIG_KEY)) { + return DEFAULT_DB_AUTO_PRUNE_FREQUENCY; + } + int dbAutoPruneFrequency = config.getInt(DB_AUTO_PRUNE_FREQUENCY_CONFIG_KEY); + if (dbAutoPruneFrequency < 1) { + throw new IllegalArgumentException("[storage.prune.frequency] value must not be less than " + + "1!"); + } + return dbAutoPruneFrequency; + } + + public static int getDbAutoPruneBatchFromConfig(final Config config) { + if (!config.hasPath(DB_AUTO_PRUNE_BATCH_CONFIG_KEY)) { + return DEFAULT_DB_AUTO_PRUNE_BATCH; + } + int dbAutoPruneBatch = config.getInt(DB_AUTO_PRUNE_BATCH_CONFIG_KEY); + if (dbAutoPruneBatch < 1) { + throw new IllegalArgumentException("[storage.prune.batch] value must not be less than 1!"); + } + if (dbAutoPruneBatch > 50) { + throw new IllegalArgumentException("[storage.prune.batch] value must not be more than 50!"); + } + return dbAutoPruneBatch; + } + public static Boolean getContractParseSwitchFromConfig(final Config config) { return config.hasPath(EVENT_SUBSCRIBE_CONTRACT_PARSE) ? config.getBoolean(EVENT_SUBSCRIBE_CONTRACT_PARSE) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 858f0d42d86..ace342771a1 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -522,6 +522,7 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.storage.setEstimatedBlockTransactions( Storage.getEstimatedTransactionsFromConfig(config)); PARAMETER.storage.setMaxFlushCount(Storage.getSnapshotMaxFlushCountFromConfig(config)); + PARAMETER.storage.setDbAutoPruneInfo(config); PARAMETER.storage.setDefaultDbOptions(config); PARAMETER.storage.setPropertyMapFromConfig(config); diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 8787c70aeb8..ac91b66bfac 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -68,6 +68,7 @@ import org.tron.common.prometheus.MetricLabels; import org.tron.common.prometheus.Metrics; import org.tron.common.runtime.RuntimeImpl; +import org.tron.common.storage.prune.ChainDataPruner; import org.tron.common.utils.ByteArray; import org.tron.common.utils.JsonUtil; import org.tron.common.utils.Pair; @@ -224,6 +225,8 @@ public class Manager { @Autowired @Getter private ChainBaseManager chainBaseManager; + @Autowired + private ChainDataPruner chainDataPruner; // transactions cache private BlockingQueue pendingTransactions; @Getter @@ -1911,6 +1914,7 @@ public NullifierStore getNullifierStore() { public void closeAllStore() { logger.info("******** Begin to close db. ********"); + chainDataPruner.shutdown(); chainBaseManager.closeAllStore(); logger.info("******** End to close db. ********"); } diff --git a/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java b/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java index 9efb223fdb7..40d6ff7f51b 100755 --- a/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java @@ -3,9 +3,12 @@ import com.google.protobuf.ByteString; import lombok.Getter; import org.apache.commons.lang3.StringUtils; +import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Commons; import org.tron.common.utils.StringUtil; import org.tron.core.ChainBaseManager; +import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; import org.tron.core.config.args.Args; import org.tron.core.net.message.MessageTypes; @@ -59,14 +62,28 @@ public HelloMessage(Node from, long timestamp, ChainBaseManager chainBaseManager builder.setSolidBlockId(sBlockId); builder.setHeadBlockId(hBlockId); builder.setNodeType(chainBaseManager.getNodeType().getType()); - builder.setLowestBlockNum(chainBaseManager.isLiteNode() - ? chainBaseManager.getLowestBlockNum() : 0); + builder.setLowestBlockNum(calculateLowestBlockNum(chainBaseManager)); this.helloMessage = builder.build(); this.type = MessageTypes.P2P_HELLO.asByte(); this.data = this.helloMessage.toByteArray(); } + public long calculateLowestBlockNum(ChainBaseManager chainBaseManager) { + if (!chainBaseManager.isLiteNode()) { + return 0; + } + if (!CommonParameter.getInstance().getStorage().isDbAutoPrune()) { + return chainBaseManager.getLowestBlockNum(); + } + long lowestBlockNum = chainBaseManager.getLowestBlockNum(); + long latestBlockNum = chainBaseManager.getDynamicPropertiesStore() + .getLatestBlockHeaderNumberFromDB(); + long retainBlocksSafeIn2Days = CommonParameter.getInstance().getStorage() + .getDbAutoPruneRetain() - 2 * Constant.ONE_DAY_BLOCKS_PREDICT; + return Math.max(latestBlockNum - retainBlocksSafeIn2Days + 1, lowestBlockNum); + } + public void setHelloMessage(Protocol.HelloMessage helloMessage) { this.helloMessage = helloMessage; this.data = this.helloMessage.toByteArray(); diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 47635540017..2caec06aaeb 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -95,6 +95,17 @@ storage { # the estimated number of block transactions (default 1000, min 100, max 10000). # so the total number of cached transactions is 65536 * txCache.estimatedTransactions # txCache.estimatedTransactions = 1000 + + # prune = { + # prune enable switch + # enable = true + # retain number of blocks after prune + # retain = 864000 + # seconds between two prune operations + # frequency = 3 + # the number of blocks prune once + # batch = 50 + # } } node.discovery = { diff --git a/framework/src/test/java/org/tron/common/storage/prune/ChainDataPrunerTest.java b/framework/src/test/java/org/tron/common/storage/prune/ChainDataPrunerTest.java new file mode 100644 index 00000000000..7d7c9d8ae56 --- /dev/null +++ b/framework/src/test/java/org/tron/common/storage/prune/ChainDataPrunerTest.java @@ -0,0 +1,202 @@ +package org.tron.common.storage.prune; + +import com.google.common.primitives.Longs; +import com.google.protobuf.ByteString; +import java.io.File; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.crypto.ECKey; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.ReflectUtils; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.ChainBaseManager; +import org.tron.core.Constant; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.capsule.TransactionInfoCapsule; +import org.tron.core.capsule.TransactionRetCapsule; +import org.tron.core.capsule.utils.BlockUtil; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.consensus.ConsensusService; +import org.tron.core.db.BlockIndexStore; +import org.tron.core.db.BlockStore; +import org.tron.core.db.Manager; +import org.tron.core.db.TransactionStore; +import org.tron.core.db2.core.Chainbase; +import org.tron.core.exception.ItemNotFoundException; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.store.TransactionRetStore; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.contract.BalanceContract; + + + +@Slf4j +public class ChainDataPrunerTest { + + private static Manager dbManager; + private static ChainDataPruner chainDataPruner; + private static ChainBaseManager chainBaseManager; + private static ConsensusService consensusService; + private static TronApplicationContext context; + private static BlockCapsule blockCapsule1; + private static BlockCapsule blockCapsule2; + private static String dbPath = "output_pruner_test"; + private static AtomicInteger port = new AtomicInteger(0); + + @Before + public void init() { + Args.setParam(new String[] {"-d", dbPath, "-w"}, Constant.TEST_CONF); + Args.getInstance().setNodeListenPort(10000 + port.incrementAndGet()); + context = new TronApplicationContext(DefaultConfig.class); + + dbManager = context.getBean(Manager.class); + chainDataPruner = context.getBean(ChainDataPruner.class); + consensusService = context.getBean(ConsensusService.class); + consensusService.start(); + chainBaseManager = dbManager.getChainBaseManager(); + } + + @Test + public void initTest() { + chainDataPruner.init(); + Assert.assertNull(ReflectUtils.getFieldValue(chainDataPruner, "pruneExecutor")); + Assert.assertEquals(0, chainBaseManager.getLowestBlockNum()); + } + + + @Test + public void pruneTest() { + try { + blockCapsule1 = BlockUtil.newGenesisBlockCapsule(); + blockCapsule2 = + new BlockCapsule( + 2, + Sha256Hash.wrap(ByteString.copyFrom( + ByteArray.fromHexString( + blockCapsule1.getBlockId().toString()))), + 0, + ByteString.copyFrom( + ECKey.fromPrivate( + ByteArray.fromHexString( + Args.getLocalWitnesses().getPrivateKey())) + .getAddress())); + BlockCapsule blockCapsule3 = + new BlockCapsule( + 3, + Sha256Hash.wrap(ByteString.copyFrom( + ByteArray.fromHexString( + blockCapsule2.getBlockId().toString()))), + 0, + ByteString.copyFrom( + ECKey.fromPrivate( + ByteArray.fromHexString( + Args.getLocalWitnesses().getPrivateKey())) + .getAddress())); + BlockCapsule blockCapsule4 = + new BlockCapsule( + 4, + Sha256Hash.wrap(ByteString.copyFrom( + ByteArray.fromHexString( + blockCapsule3.getBlockId().toString()))), + 0, + ByteString.copyFrom( + ECKey.fromPrivate( + ByteArray.fromHexString( + Args.getLocalWitnesses().getPrivateKey())) + .getAddress())); + BlockCapsule blockCapsule5 = + new BlockCapsule( + 5, + Sha256Hash.wrap(ByteString.copyFrom( + ByteArray.fromHexString( + blockCapsule4.getBlockId().toString()))), + 0, + ByteString.copyFrom( + ECKey.fromPrivate( + ByteArray.fromHexString( + Args.getLocalWitnesses().getPrivateKey())) + .getAddress())); + final BlockStore blockStore = chainBaseManager.getBlockStore(); + final TransactionStore trxStore = chainBaseManager.getTransactionStore(); + final BlockIndexStore blockIndexStore = chainBaseManager.getBlockIndexStore(); + final TransactionRetStore transactionRetStore = chainBaseManager.getTransactionRetStore(); + final DynamicPropertiesStore dynamicPropertiesStore = + chainBaseManager.getDynamicPropertiesStore(); + // save in database with block number + BalanceContract.TransferContract tc = + BalanceContract.TransferContract.newBuilder() + .setAmount(10) + .setOwnerAddress(ByteString.copyFromUtf8("aaa")) + .setToAddress(ByteString.copyFromUtf8("bbb")) + .build(); + TransactionCapsule trx = new TransactionCapsule(tc, ContractType.TransferContract); + trx.setBlockNum(blockCapsule2.getNum()); + TransactionInfoCapsule transactionInfoCapsule = new TransactionInfoCapsule(); + transactionInfoCapsule.setId(trx.getTransactionId().getBytes()); + transactionInfoCapsule.setFee(1000L); + transactionInfoCapsule.setBlockNumber(blockCapsule2.getNum()); + transactionInfoCapsule.setBlockTimeStamp(200L); + TransactionRetCapsule transactionRetCapsule = new TransactionRetCapsule(); + transactionRetCapsule.addTransactionInfo(transactionInfoCapsule.getInstance()); + blockCapsule2.addTransaction(trx); + blockCapsule2.setMerkleRoot(); + blockCapsule2.sign( + ByteArray.fromHexString(Args.getLocalWitnesses().getPrivateKey())); + trxStore.put(trx.getTransactionId().getBytes(), trx); + blockStore.put(blockCapsule1.getBlockId().getBytes(), blockCapsule1); + blockStore.put(blockCapsule2.getBlockId().getBytes(), blockCapsule2); + blockStore.put(blockCapsule3.getBlockId().getBytes(), blockCapsule3); + blockStore.put(blockCapsule4.getBlockId().getBytes(), blockCapsule4); + blockStore.put(blockCapsule5.getBlockId().getBytes(), blockCapsule5); + blockIndexStore.put(blockCapsule1.getBlockId()); + blockIndexStore.put(blockCapsule2.getBlockId()); + blockIndexStore.put(blockCapsule3.getBlockId()); + blockIndexStore.put(blockCapsule4.getBlockId()); + blockIndexStore.put(blockCapsule5.getBlockId()); + transactionRetStore.put(Longs.toByteArray(blockCapsule2.getNum()), transactionRetCapsule); + dynamicPropertiesStore.saveLatestBlockHeaderNumber(5L); + ReflectUtils.setFieldValue(chainDataPruner,"blocksToRetain",3); + List blockBytes = chainBaseManager.getBlockStore().getLimitNumber(2, + 1).stream().map(blockCapsule -> blockCapsule.getBlockId().getBytes()).collect( + Collectors.toList()); + chainDataPruner.prune(); + Thread.sleep(1000); + Boolean notFoundBlock2 = Boolean.FALSE; + try { + chainBaseManager.getBlockStore() + .getFromRoot(blockBytes.get(0)); + } catch (ItemNotFoundException e) { + notFoundBlock2 = Boolean.TRUE; + } + Assert.assertTrue(chainBaseManager.getBlockStore() + .getFromRoot(blockCapsule1.getBlockId().getBytes()) != null); + Assert.assertTrue(notFoundBlock2); + Assert.assertTrue(chainBaseManager.getBlockStore() + .getFromRoot(blockCapsule3.getBlockId().getBytes()) != null); + Assert.assertTrue(chainBaseManager.getBlockStore() + .getFromRoot(blockCapsule4.getBlockId().getBytes()) != null); + Assert.assertTrue(chainBaseManager.getBlockStore() + .getFromRoot(blockCapsule5.getBlockId().getBytes()) != null); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @After + public void removeDb() { + Args.clearParam(); + context.destroy(); + FileUtil.deleteDir(new File(dbPath)); + } + +} diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index 76e99c8d4a1..7e42a1283b1 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -63,6 +63,17 @@ storage { needToUpdateAsset = false snapshot.maxFlushCount = 200 + prune = { + # prune enable switch + enable = true + # retain number of blocks after prune + retain = 864000 + # seconds between two prune operations + frequency = 3 + # the number of blocks prune once + batch = 50 + } + # the estimated number of block transactions (default 1000, min 100, max 10000). # so the total number of cached transactions is 65536 * txCache.estimatedTransactions txCache.estimatedTransactions = 50 From 582c9987e05e2c33db27baa6f790554a40cb3319 Mon Sep 17 00:00:00 2001 From: forfreeday Date: Mon, 17 Apr 2023 16:12:47 +0800 Subject: [PATCH 0743/1197] update a new version. version name:GreatVoyage-v4.7.1-11-ge5e347de7,version code:17686 --- framework/src/main/java/org/tron/program/Version.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 4163c4ca5e9..72028032c8e 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,8 +2,8 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.7.0.1-75-g36fc5063e9"; - public static final String VERSION_CODE = "17673"; + public static final String VERSION_NAME = "GreatVoyage-v4.7.1-11-ge5e347de7"; + public static final String VERSION_CODE = "17686"; private static final String VERSION = "4.7.1.1"; public static String getVersion() { From 0c3dc83bc3382f78a629a24ccc7bc5c463dc1d5e Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Mon, 17 Apr 2023 16:30:05 +0800 Subject: [PATCH 0744/1197] Revert "feat(db): prune lite node data automatically" --- .../common/storage/prune/ChainDataPruner.java | 149 ------------- .../java/org/tron/core/ChainBaseManager.java | 12 +- .../org/tron/core/db2/core/SnapshotRoot.java | 4 - .../src/main/java/org/tron/core/Constant.java | 4 - .../org/tron/core/config/args/Storage.java | 77 ------- .../java/org/tron/core/config/args/Args.java | 1 - .../main/java/org/tron/core/db/Manager.java | 4 - .../net/message/handshake/HelloMessage.java | 21 +- framework/src/main/resources/config.conf | 11 - .../storage/prune/ChainDataPrunerTest.java | 202 ------------------ framework/src/test/resources/config-test.conf | 11 - 11 files changed, 4 insertions(+), 492 deletions(-) delete mode 100644 chainbase/src/main/java/org/tron/common/storage/prune/ChainDataPruner.java delete mode 100644 framework/src/test/java/org/tron/common/storage/prune/ChainDataPrunerTest.java diff --git a/chainbase/src/main/java/org/tron/common/storage/prune/ChainDataPruner.java b/chainbase/src/main/java/org/tron/common/storage/prune/ChainDataPruner.java deleted file mode 100644 index ed6cc3c37d9..00000000000 --- a/chainbase/src/main/java/org/tron/common/storage/prune/ChainDataPruner.java +++ /dev/null @@ -1,149 +0,0 @@ -package org.tron.common.storage.prune; - -import com.google.common.primitives.Longs; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import java.time.OffsetDateTime; -import java.time.ZoneOffset; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import javax.annotation.PostConstruct; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.Commons; -import org.tron.core.ChainBaseManager; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.db2.common.Flusher; -import org.tron.core.db2.common.Value; -import org.tron.core.db2.common.WrappedByteArray; -import org.tron.core.db2.core.SnapshotRoot; - -@Slf4j(topic = "db") -@Component -public class ChainDataPruner { - - private static final String BLOCK_INDEX_STORE_NAME = "block-index"; - private static final String BLOCK_STORE_NAME = "block"; - private static final String TRANSACTION_STORE_NAME = "trans"; - private static final String TRANSACTION_RET_STORE_NAME = "transactionRetStore"; - private static final Set PRUNE_DBS = new HashSet<>(Arrays.asList(BLOCK_INDEX_STORE_NAME - , BLOCK_STORE_NAME, TRANSACTION_STORE_NAME, TRANSACTION_RET_STORE_NAME)); - private long blocksToRetain = CommonParameter.getInstance().getStorage(). - getDbAutoPruneRetain(); - private long blocksBatchFlush = CommonParameter.getInstance().getStorage().getDbAutoPruneBatch(); - private static Map snapshotRootMap = new ConcurrentHashMap<>(); - - private ScheduledExecutorService pruneExecutor = null; - - @Autowired - private ChainBaseManager chainBaseManager; - - @PostConstruct - public void init() { - if ((!chainBaseManager.isLiteNode()) || - (!CommonParameter.getInstance().getStorage().isDbAutoPrune())) { - return; - } - pruneExecutor = Executors.newSingleThreadScheduledExecutor( - new ThreadFactoryBuilder().setNameFormat("db-prune-thread-%d").build()); - pruneExecutor.scheduleWithFixedDelay(() -> { - try { - if (!shouldBeginPrune()) { - return; - } - prune(); - } catch (InterruptedException e) { - logger.warn("Prune chain data thread interrupted!"); - Thread.currentThread().interrupt(); - } - }, 60, - CommonParameter.getInstance().getStorage().getDbAutoPruneFrequency(), TimeUnit.SECONDS); - } - - private boolean shouldBeginPrune() { - OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); - int currentHour = now.getHour(); - return currentHour >= 20 || currentHour < 2; - } - - public static void register(String dbName, SnapshotRoot snapshotRoot) { - if ((!CommonParameter.getInstance().getStorage().isDbAutoPrune()) - ||(!PRUNE_DBS.contains(dbName))) { - return; - } - snapshotRootMap.put(dbName, snapshotRoot); - } - - public void prune() throws InterruptedException { - long lowestBlockNumber = chainBaseManager.getBlockStore().getLimitNumber(1, 1). - stream().map(BlockCapsule::getNum).findFirst().get(); - long latestBlockNumber = chainBaseManager.getDynamicPropertiesStore(). - getLatestBlockHeaderNumberFromDB(); - if (latestBlockNumber - lowestBlockNumber + 1 > blocksToRetain) { - doPrune(lowestBlockNumber, latestBlockNumber); - } - } - - private void doPrune(long lowestBlockNumber, long latestBlockNumber) { - long toFetchCount = - Math.min((latestBlockNumber - lowestBlockNumber + 1 - blocksToRetain), blocksBatchFlush); - List blockCapsuleList = chainBaseManager.getBlockStore() - .getLimitNumber(lowestBlockNumber, toFetchCount); - Map blockIdBatch = new HashMap<>(); - Map blockNumBatch = new HashMap<>(); - Map transIdBatch = new HashMap<>(); - prepareWriteBatch(blockIdBatch, blockNumBatch, transIdBatch, blockCapsuleList); - flushDb(blockIdBatch, blockNumBatch, transIdBatch); - } - - private void flushDb(Map blockIdBatch, - Map blockNumBatch, - Map transIdBatch) { - SnapshotRoot transactionRoot = snapshotRootMap.get(TRANSACTION_STORE_NAME); - ((Flusher)transactionRoot.getDb()).flush(transIdBatch); - SnapshotRoot transactionRetRoot = snapshotRootMap.get(TRANSACTION_RET_STORE_NAME); - ((Flusher)transactionRetRoot.getDb()).flush(blockNumBatch); - SnapshotRoot blockIndexRoot = snapshotRootMap.get(BLOCK_INDEX_STORE_NAME); - ((Flusher)blockIndexRoot.getDb()).flush(blockNumBatch); - SnapshotRoot blockRoot = snapshotRootMap.get(BLOCK_STORE_NAME); - ((Flusher)blockRoot.getDb()).flush(blockIdBatch); - } - - private void prepareWriteBatch ( - Map blockIdBatch, - Map blockNumBatch, - Map transIdBatch, - List blockCapsuleList) { - for (BlockCapsule blockCapsule: blockCapsuleList) { - blockIdBatch.put(WrappedByteArray.of(blockCapsule.getBlockId().getBytes()), - WrappedByteArray.of(Value.of(Value.Operator.DELETE, null).getBytes())); - blockNumBatch.put(WrappedByteArray.of(Longs.toByteArray(blockCapsule.getNum())), - WrappedByteArray.of(Value.of(Value.Operator.DELETE, null).getBytes())); - blockCapsule.getTransactions().forEach(tx-> transIdBatch.put(WrappedByteArray.of(tx. - getTransactionId().getBytes()), WrappedByteArray.of(Value.of(Value.Operator.DELETE, - null).getBytes()))); - } - } - - public void shutdown() { - if (Objects.nonNull(pruneExecutor)) { - try { - pruneExecutor.shutdown(); - } catch (Exception e) { - logger.error("Chain pruner shutdown error: {}", e.getMessage()); - } - } - } - -} diff --git a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java index 9511735f22a..c9ced891ee6 100644 --- a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java +++ b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java @@ -11,7 +11,6 @@ import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.common.parameter.CommonParameter; import org.tron.common.storage.metric.DbStatService; import org.tron.common.utils.ForkController; import org.tron.common.utils.Sha256Hash; @@ -242,6 +241,8 @@ public class ChainBaseManager { @Setter private NodeType nodeType; + @Getter + @Setter private long lowestBlockNum = -1; // except num = 0. public void closeOneStore(ITronChainBase database) { @@ -430,15 +431,6 @@ private void init() { this.nodeType = getLowestBlockNum() > 1 ? NodeType.LITE : NodeType.FULL; } - public long getLowestBlockNum(){ - if(isLiteNode() && CommonParameter.getInstance().getStorage().isDbAutoPrune()) { - return this.blockIndexStore.getLimitNumber(1, 1).stream() - .map(BlockId::getNum).findFirst().orElseThrow( - () -> new IllegalArgumentException("LowestBlockNum not found!")); - } - return lowestBlockNum; - } - public boolean isLiteNode() { return getNodeType() == NodeType.LITE; } diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java index 66173ea45a1..709e2ae1b62 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java @@ -2,20 +2,17 @@ import com.google.common.collect.Maps; import com.google.common.collect.Streams; -import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Set; import java.util.stream.Collectors; import lombok.Getter; import org.tron.common.cache.CacheManager; import org.tron.common.cache.CacheType; import org.tron.common.cache.TronCache; import org.tron.common.parameter.CommonParameter; -import org.tron.common.storage.prune.ChainDataPruner; import org.tron.common.utils.ByteArray; import org.tron.core.ChainBaseManager; import org.tron.core.capsule.AccountCapsule; @@ -41,7 +38,6 @@ public SnapshotRoot(DB db) { if (CACHE_DBS.contains(this.db.getDbName())) { this.cache = CacheManager.allocate(CacheType.findByType(this.db.getDbName())); } - ChainDataPruner.register(this.db.getDbName(), this); } private boolean needOptAsset() { diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 799f8bcd42b..bcbfecb7904 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -1,7 +1,5 @@ package org.tron.core; -import org.tron.core.config.Parameter.ChainConstant; - public class Constant { //config for testnet, mainnet, beta @@ -41,8 +39,6 @@ public class Constant { public static final int ONE_HUNDRED = 100; public static final int ONE_THOUSAND = 1000; - public static final long ONE_DAY_BLOCKS_PREDICT = 24 * 60 * 60 * 1000 / ChainConstant.BLOCK_PRODUCED_INTERVAL; - public static final byte[] ZTRON_EXPANDSEED_PERSONALIZATION = {'Z', 't', 'r', 'o', 'n', '_', 'E', 'x', 'p', 'a', 'n', 'd', 'S', 'e', 'e', 'd'}; diff --git a/common/src/main/java/org/tron/core/config/args/Storage.java b/common/src/main/java/org/tron/core/config/args/Storage.java index 9f2182816f3..778d4d0141c 100644 --- a/common/src/main/java/org/tron/core/config/args/Storage.java +++ b/common/src/main/java/org/tron/core/config/args/Storage.java @@ -32,7 +32,6 @@ import org.tron.common.utils.DbOptionalsUtils; import org.tron.common.utils.FileUtil; import org.tron.common.utils.Property; -import org.tron.core.Constant; /** * Custom storage configurations @@ -55,10 +54,6 @@ public class Storage { private static final String ESTIMATED_TRANSACTIONS_CONFIG_KEY = "storage.txCache.estimatedTransactions"; private static final String SNAPSHOT_MAX_FLUSH_COUNT_CONFIG_KEY = "storage.snapshot.maxFlushCount"; - private static final String DB_AUTO_PRUNE_SWITCH_CONFIG_KEY = "storage.prune.enable"; - private static final String DB_AUTO_PRUNE_RETAIN_CONFIG_KEY = "storage.prune.retain"; - private static final String DB_AUTO_PRUNE_FREQUENCY_CONFIG_KEY = "storage.prune.frequency"; - private static final String DB_AUTO_PRUNE_BATCH_CONFIG_KEY = "storage.prune.batch"; private static final String PROPERTIES_CONFIG_KEY = "storage.properties"; private static final String PROPERTIES_CONFIG_DB_KEY = "storage"; private static final String PROPERTIES_CONFIG_DEFAULT_KEY = "default"; @@ -96,11 +91,6 @@ public class Storage { private static final boolean DEFAULT_CHECKPOINT_SYNC = true; private static final int DEFAULT_ESTIMATED_TRANSACTIONS = 1000; private static final int DEFAULT_SNAPSHOT_MAX_FLUSH_COUNT = 1; - private static final boolean DEFAULT_DB_AUTO_PRUNE_SWITCH = false; - private static final int DEFAULT_DB_AUTO_PRUNE_RETAIN = 864000; - private static final int DEFAULT_DB_AUTO_PRUNE_FREQUENCY = 3; - private static final int DEFAULT_DB_AUTO_PRUNE_BATCH = 50; - private Config storage; /** @@ -122,22 +112,6 @@ public class Storage { @Setter private int maxFlushCount; - @Getter - @Setter - private boolean dbAutoPrune; - - @Getter - @Setter - private int dbAutoPruneRetain; - - @Getter - @Setter - private int dbAutoPruneFrequency; - - @Getter - @Setter - private int dbAutoPruneBatch; - /** * Index storage directory: /path/to/{indexDirectory} */ @@ -208,57 +182,6 @@ public static int getSnapshotMaxFlushCountFromConfig(final Config config) { return maxFlushCountConfig; } - public void setDbAutoPruneInfo(final Config config) { - setDbAutoPrune(Storage.getDbAutoPruneSwitchFromConfig(config)); - setDbAutoPruneRetain(Storage.getDbAutoPruneRetainFromConfig(config)); - setDbAutoPruneFrequency( - Storage.getDbAutoPruneFrequencyFromConfig(config)); - setDbAutoPruneBatch(Storage.getDbAutoPruneBatchFromConfig(config)); - } - - public static boolean getDbAutoPruneSwitchFromConfig(final Config config) { - return config.hasPath(DB_AUTO_PRUNE_SWITCH_CONFIG_KEY) - ? config.getBoolean(DB_AUTO_PRUNE_SWITCH_CONFIG_KEY) : DEFAULT_DB_AUTO_PRUNE_SWITCH; - } - - public static int getDbAutoPruneRetainFromConfig(final Config config) { - if (!config.hasPath(DB_AUTO_PRUNE_RETAIN_CONFIG_KEY)) { - return DEFAULT_DB_AUTO_PRUNE_RETAIN; - } - int dbAutoPruneRetain = config.getInt(DB_AUTO_PRUNE_RETAIN_CONFIG_KEY); - if (dbAutoPruneRetain < 30 * Constant.ONE_DAY_BLOCKS_PREDICT) { - throw new IllegalArgumentException( - "[storage.prune.retain] value must not be less than 864000!"); - } - return dbAutoPruneRetain; - } - - public static int getDbAutoPruneFrequencyFromConfig(final Config config) { - if (!config.hasPath(DB_AUTO_PRUNE_FREQUENCY_CONFIG_KEY)) { - return DEFAULT_DB_AUTO_PRUNE_FREQUENCY; - } - int dbAutoPruneFrequency = config.getInt(DB_AUTO_PRUNE_FREQUENCY_CONFIG_KEY); - if (dbAutoPruneFrequency < 1) { - throw new IllegalArgumentException("[storage.prune.frequency] value must not be less than " + - "1!"); - } - return dbAutoPruneFrequency; - } - - public static int getDbAutoPruneBatchFromConfig(final Config config) { - if (!config.hasPath(DB_AUTO_PRUNE_BATCH_CONFIG_KEY)) { - return DEFAULT_DB_AUTO_PRUNE_BATCH; - } - int dbAutoPruneBatch = config.getInt(DB_AUTO_PRUNE_BATCH_CONFIG_KEY); - if (dbAutoPruneBatch < 1) { - throw new IllegalArgumentException("[storage.prune.batch] value must not be less than 1!"); - } - if (dbAutoPruneBatch > 50) { - throw new IllegalArgumentException("[storage.prune.batch] value must not be more than 50!"); - } - return dbAutoPruneBatch; - } - public static Boolean getContractParseSwitchFromConfig(final Config config) { return config.hasPath(EVENT_SUBSCRIBE_CONTRACT_PARSE) ? config.getBoolean(EVENT_SUBSCRIBE_CONTRACT_PARSE) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index a24b872795a..19962fbac8e 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -523,7 +523,6 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.storage.setEstimatedBlockTransactions( Storage.getEstimatedTransactionsFromConfig(config)); PARAMETER.storage.setMaxFlushCount(Storage.getSnapshotMaxFlushCountFromConfig(config)); - PARAMETER.storage.setDbAutoPruneInfo(config); PARAMETER.storage.setDefaultDbOptions(config); PARAMETER.storage.setPropertyMapFromConfig(config); diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 3519ec528eb..b1127029b46 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -69,7 +69,6 @@ import org.tron.common.prometheus.MetricLabels; import org.tron.common.prometheus.Metrics; import org.tron.common.runtime.RuntimeImpl; -import org.tron.common.storage.prune.ChainDataPruner; import org.tron.common.utils.ByteArray; import org.tron.common.utils.JsonUtil; import org.tron.common.utils.Pair; @@ -226,8 +225,6 @@ public class Manager { @Autowired @Getter private ChainBaseManager chainBaseManager; - @Autowired - private ChainDataPruner chainDataPruner; // transactions cache private BlockingQueue pendingTransactions; @Getter @@ -1915,7 +1912,6 @@ public NullifierStore getNullifierStore() { public void closeAllStore() { logger.info("******** Begin to close db. ********"); - chainDataPruner.shutdown(); chainBaseManager.closeAllStore(); logger.info("******** End to close db. ********"); } diff --git a/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java b/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java index 40d6ff7f51b..9efb223fdb7 100755 --- a/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java @@ -3,12 +3,9 @@ import com.google.protobuf.ByteString; import lombok.Getter; import org.apache.commons.lang3.StringUtils; -import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Commons; import org.tron.common.utils.StringUtil; import org.tron.core.ChainBaseManager; -import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; import org.tron.core.config.args.Args; import org.tron.core.net.message.MessageTypes; @@ -62,28 +59,14 @@ public HelloMessage(Node from, long timestamp, ChainBaseManager chainBaseManager builder.setSolidBlockId(sBlockId); builder.setHeadBlockId(hBlockId); builder.setNodeType(chainBaseManager.getNodeType().getType()); - builder.setLowestBlockNum(calculateLowestBlockNum(chainBaseManager)); + builder.setLowestBlockNum(chainBaseManager.isLiteNode() + ? chainBaseManager.getLowestBlockNum() : 0); this.helloMessage = builder.build(); this.type = MessageTypes.P2P_HELLO.asByte(); this.data = this.helloMessage.toByteArray(); } - public long calculateLowestBlockNum(ChainBaseManager chainBaseManager) { - if (!chainBaseManager.isLiteNode()) { - return 0; - } - if (!CommonParameter.getInstance().getStorage().isDbAutoPrune()) { - return chainBaseManager.getLowestBlockNum(); - } - long lowestBlockNum = chainBaseManager.getLowestBlockNum(); - long latestBlockNum = chainBaseManager.getDynamicPropertiesStore() - .getLatestBlockHeaderNumberFromDB(); - long retainBlocksSafeIn2Days = CommonParameter.getInstance().getStorage() - .getDbAutoPruneRetain() - 2 * Constant.ONE_DAY_BLOCKS_PREDICT; - return Math.max(latestBlockNum - retainBlocksSafeIn2Days + 1, lowestBlockNum); - } - public void setHelloMessage(Protocol.HelloMessage helloMessage) { this.helloMessage = helloMessage; this.data = this.helloMessage.toByteArray(); diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 2caec06aaeb..47635540017 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -95,17 +95,6 @@ storage { # the estimated number of block transactions (default 1000, min 100, max 10000). # so the total number of cached transactions is 65536 * txCache.estimatedTransactions # txCache.estimatedTransactions = 1000 - - # prune = { - # prune enable switch - # enable = true - # retain number of blocks after prune - # retain = 864000 - # seconds between two prune operations - # frequency = 3 - # the number of blocks prune once - # batch = 50 - # } } node.discovery = { diff --git a/framework/src/test/java/org/tron/common/storage/prune/ChainDataPrunerTest.java b/framework/src/test/java/org/tron/common/storage/prune/ChainDataPrunerTest.java deleted file mode 100644 index 7d7c9d8ae56..00000000000 --- a/framework/src/test/java/org/tron/common/storage/prune/ChainDataPrunerTest.java +++ /dev/null @@ -1,202 +0,0 @@ -package org.tron.common.storage.prune; - -import com.google.common.primitives.Longs; -import com.google.protobuf.ByteString; -import java.io.File; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; -import lombok.extern.slf4j.Slf4j; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; -import org.tron.common.utils.ReflectUtils; -import org.tron.common.utils.Sha256Hash; -import org.tron.core.ChainBaseManager; -import org.tron.core.Constant; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.capsule.TransactionInfoCapsule; -import org.tron.core.capsule.TransactionRetCapsule; -import org.tron.core.capsule.utils.BlockUtil; -import org.tron.core.config.DefaultConfig; -import org.tron.core.config.args.Args; -import org.tron.core.consensus.ConsensusService; -import org.tron.core.db.BlockIndexStore; -import org.tron.core.db.BlockStore; -import org.tron.core.db.Manager; -import org.tron.core.db.TransactionStore; -import org.tron.core.db2.core.Chainbase; -import org.tron.core.exception.ItemNotFoundException; -import org.tron.core.store.DynamicPropertiesStore; -import org.tron.core.store.TransactionRetStore; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.contract.BalanceContract; - - - -@Slf4j -public class ChainDataPrunerTest { - - private static Manager dbManager; - private static ChainDataPruner chainDataPruner; - private static ChainBaseManager chainBaseManager; - private static ConsensusService consensusService; - private static TronApplicationContext context; - private static BlockCapsule blockCapsule1; - private static BlockCapsule blockCapsule2; - private static String dbPath = "output_pruner_test"; - private static AtomicInteger port = new AtomicInteger(0); - - @Before - public void init() { - Args.setParam(new String[] {"-d", dbPath, "-w"}, Constant.TEST_CONF); - Args.getInstance().setNodeListenPort(10000 + port.incrementAndGet()); - context = new TronApplicationContext(DefaultConfig.class); - - dbManager = context.getBean(Manager.class); - chainDataPruner = context.getBean(ChainDataPruner.class); - consensusService = context.getBean(ConsensusService.class); - consensusService.start(); - chainBaseManager = dbManager.getChainBaseManager(); - } - - @Test - public void initTest() { - chainDataPruner.init(); - Assert.assertNull(ReflectUtils.getFieldValue(chainDataPruner, "pruneExecutor")); - Assert.assertEquals(0, chainBaseManager.getLowestBlockNum()); - } - - - @Test - public void pruneTest() { - try { - blockCapsule1 = BlockUtil.newGenesisBlockCapsule(); - blockCapsule2 = - new BlockCapsule( - 2, - Sha256Hash.wrap(ByteString.copyFrom( - ByteArray.fromHexString( - blockCapsule1.getBlockId().toString()))), - 0, - ByteString.copyFrom( - ECKey.fromPrivate( - ByteArray.fromHexString( - Args.getLocalWitnesses().getPrivateKey())) - .getAddress())); - BlockCapsule blockCapsule3 = - new BlockCapsule( - 3, - Sha256Hash.wrap(ByteString.copyFrom( - ByteArray.fromHexString( - blockCapsule2.getBlockId().toString()))), - 0, - ByteString.copyFrom( - ECKey.fromPrivate( - ByteArray.fromHexString( - Args.getLocalWitnesses().getPrivateKey())) - .getAddress())); - BlockCapsule blockCapsule4 = - new BlockCapsule( - 4, - Sha256Hash.wrap(ByteString.copyFrom( - ByteArray.fromHexString( - blockCapsule3.getBlockId().toString()))), - 0, - ByteString.copyFrom( - ECKey.fromPrivate( - ByteArray.fromHexString( - Args.getLocalWitnesses().getPrivateKey())) - .getAddress())); - BlockCapsule blockCapsule5 = - new BlockCapsule( - 5, - Sha256Hash.wrap(ByteString.copyFrom( - ByteArray.fromHexString( - blockCapsule4.getBlockId().toString()))), - 0, - ByteString.copyFrom( - ECKey.fromPrivate( - ByteArray.fromHexString( - Args.getLocalWitnesses().getPrivateKey())) - .getAddress())); - final BlockStore blockStore = chainBaseManager.getBlockStore(); - final TransactionStore trxStore = chainBaseManager.getTransactionStore(); - final BlockIndexStore blockIndexStore = chainBaseManager.getBlockIndexStore(); - final TransactionRetStore transactionRetStore = chainBaseManager.getTransactionRetStore(); - final DynamicPropertiesStore dynamicPropertiesStore = - chainBaseManager.getDynamicPropertiesStore(); - // save in database with block number - BalanceContract.TransferContract tc = - BalanceContract.TransferContract.newBuilder() - .setAmount(10) - .setOwnerAddress(ByteString.copyFromUtf8("aaa")) - .setToAddress(ByteString.copyFromUtf8("bbb")) - .build(); - TransactionCapsule trx = new TransactionCapsule(tc, ContractType.TransferContract); - trx.setBlockNum(blockCapsule2.getNum()); - TransactionInfoCapsule transactionInfoCapsule = new TransactionInfoCapsule(); - transactionInfoCapsule.setId(trx.getTransactionId().getBytes()); - transactionInfoCapsule.setFee(1000L); - transactionInfoCapsule.setBlockNumber(blockCapsule2.getNum()); - transactionInfoCapsule.setBlockTimeStamp(200L); - TransactionRetCapsule transactionRetCapsule = new TransactionRetCapsule(); - transactionRetCapsule.addTransactionInfo(transactionInfoCapsule.getInstance()); - blockCapsule2.addTransaction(trx); - blockCapsule2.setMerkleRoot(); - blockCapsule2.sign( - ByteArray.fromHexString(Args.getLocalWitnesses().getPrivateKey())); - trxStore.put(trx.getTransactionId().getBytes(), trx); - blockStore.put(blockCapsule1.getBlockId().getBytes(), blockCapsule1); - blockStore.put(blockCapsule2.getBlockId().getBytes(), blockCapsule2); - blockStore.put(blockCapsule3.getBlockId().getBytes(), blockCapsule3); - blockStore.put(blockCapsule4.getBlockId().getBytes(), blockCapsule4); - blockStore.put(blockCapsule5.getBlockId().getBytes(), blockCapsule5); - blockIndexStore.put(blockCapsule1.getBlockId()); - blockIndexStore.put(blockCapsule2.getBlockId()); - blockIndexStore.put(blockCapsule3.getBlockId()); - blockIndexStore.put(blockCapsule4.getBlockId()); - blockIndexStore.put(blockCapsule5.getBlockId()); - transactionRetStore.put(Longs.toByteArray(blockCapsule2.getNum()), transactionRetCapsule); - dynamicPropertiesStore.saveLatestBlockHeaderNumber(5L); - ReflectUtils.setFieldValue(chainDataPruner,"blocksToRetain",3); - List blockBytes = chainBaseManager.getBlockStore().getLimitNumber(2, - 1).stream().map(blockCapsule -> blockCapsule.getBlockId().getBytes()).collect( - Collectors.toList()); - chainDataPruner.prune(); - Thread.sleep(1000); - Boolean notFoundBlock2 = Boolean.FALSE; - try { - chainBaseManager.getBlockStore() - .getFromRoot(blockBytes.get(0)); - } catch (ItemNotFoundException e) { - notFoundBlock2 = Boolean.TRUE; - } - Assert.assertTrue(chainBaseManager.getBlockStore() - .getFromRoot(blockCapsule1.getBlockId().getBytes()) != null); - Assert.assertTrue(notFoundBlock2); - Assert.assertTrue(chainBaseManager.getBlockStore() - .getFromRoot(blockCapsule3.getBlockId().getBytes()) != null); - Assert.assertTrue(chainBaseManager.getBlockStore() - .getFromRoot(blockCapsule4.getBlockId().getBytes()) != null); - Assert.assertTrue(chainBaseManager.getBlockStore() - .getFromRoot(blockCapsule5.getBlockId().getBytes()) != null); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @After - public void removeDb() { - Args.clearParam(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } - -} diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index ef5ba73e891..c9602ef977b 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -63,17 +63,6 @@ storage { needToUpdateAsset = false snapshot.maxFlushCount = 200 - prune = { - # prune enable switch - enable = true - # retain number of blocks after prune - retain = 864000 - # seconds between two prune operations - frequency = 3 - # the number of blocks prune once - batch = 50 - } - # the estimated number of block transactions (default 1000, min 100, max 10000). # so the total number of cached transactions is 65536 * txCache.estimatedTransactions txCache.estimatedTransactions = 50 From bc2c141c226d83cc1898bf3728d34bd8479a5cbd Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 18 Apr 2023 11:16:02 +0800 Subject: [PATCH 0745/1197] feat(backup): increase the unit test of the backup module --- .../tron/common/backup/BackupManagerTest.java | 90 +++++++++++++++++++ .../common/backup/KeepAliveMessageTest.java | 32 +++++++ .../common/backup/UdpMessageTypeEnumTest.java | 23 +++++ 3 files changed, 145 insertions(+) create mode 100644 framework/src/test/java/org/tron/common/backup/BackupManagerTest.java create mode 100644 framework/src/test/java/org/tron/common/backup/KeepAliveMessageTest.java create mode 100644 framework/src/test/java/org/tron/common/backup/UdpMessageTypeEnumTest.java diff --git a/framework/src/test/java/org/tron/common/backup/BackupManagerTest.java b/framework/src/test/java/org/tron/common/backup/BackupManagerTest.java new file mode 100644 index 00000000000..8a5ff4f4bc2 --- /dev/null +++ b/framework/src/test/java/org/tron/common/backup/BackupManagerTest.java @@ -0,0 +1,90 @@ +package org.tron.common.backup; + +import java.lang.reflect.Field; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ScheduledExecutorService; +import org.junit.Assert; +import org.junit.Test; +import org.tron.common.backup.message.KeepAliveMessage; +import org.tron.common.backup.socket.UdpEvent; +import org.tron.common.parameter.CommonParameter; +import org.tron.core.Constant; +import org.tron.core.config.args.Args; + +public class BackupManagerTest { + + @Test + public void test() throws Exception { + String[] a = new String[0]; + Args.setParam(a, Constant.TESTNET_CONF); + CommonParameter parameter = CommonParameter.getInstance(); + parameter.setBackupPriority(8); + List members = new ArrayList<>(); + members.add("127.0.0.2"); + parameter.setBackupMembers(members); + + BackupManager manager = new BackupManager(); + + Field field = manager.getClass().getDeclaredField("localIp"); + field.setAccessible(true); + field.set(manager, "127.0.0.1"); + + Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.MASTER); + + field = manager.getClass().getDeclaredField("executorService"); + field.setAccessible(true); + ScheduledExecutorService executorService = (ScheduledExecutorService) field.get(manager); + manager.init(); + executorService.shutdown(); + Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.INIT); + + /* ip not in the members */ + manager.setStatus(BackupManager.BackupStatusEnum.INIT); + KeepAliveMessage message = new KeepAliveMessage(false, 6); + InetSocketAddress address = new InetSocketAddress("127.0.0.3", 1000); + UdpEvent event = new UdpEvent(message, address); + manager.handleEvent(event); + Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.INIT); + + /* ip not the member */ + address = new InetSocketAddress("127.0.0.3", 1000); + message = new KeepAliveMessage(false, 6); + event = new UdpEvent(message, address); + manager.handleEvent(event); + Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.INIT); + + /* keepAliveMessage.getFlag() || peerPriority > priority */ + address = new InetSocketAddress("127.0.0.2", 1000); + message = new KeepAliveMessage(false, 6); + event = new UdpEvent(message, address); + manager.handleEvent(event); + Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.INIT); + + /* keepAliveMessage.getFlag() || peerPriority > priority */ + message = new KeepAliveMessage(false, 10); + event = new UdpEvent(message, address); + manager.handleEvent(event); + Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.SLAVER); + + /* keepAliveMessage.getFlag() || peerPriority > priority */ + manager.setStatus(BackupManager.BackupStatusEnum.INIT); + message = new KeepAliveMessage(true, 6); + event = new UdpEvent(message, address); + manager.handleEvent(event); + Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.SLAVER); + + manager.setStatus(BackupManager.BackupStatusEnum.MASTER); + message = new KeepAliveMessage(false, 10); + event = new UdpEvent(message, address); + manager.handleEvent(event); + Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.MASTER); + + message = new KeepAliveMessage(true, 10); + event = new UdpEvent(message, address); + manager.handleEvent(event); + Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.SLAVER); + + } +} diff --git a/framework/src/test/java/org/tron/common/backup/KeepAliveMessageTest.java b/framework/src/test/java/org/tron/common/backup/KeepAliveMessageTest.java new file mode 100644 index 00000000000..a93e044db03 --- /dev/null +++ b/framework/src/test/java/org/tron/common/backup/KeepAliveMessageTest.java @@ -0,0 +1,32 @@ +package org.tron.common.backup; + +import static org.tron.common.backup.message.UdpMessageTypeEnum.BACKUP_KEEP_ALIVE; + +import org.junit.Test; +import org.testng.Assert; +import org.tron.common.backup.message.KeepAliveMessage; +import org.tron.protos.Discover; + +public class KeepAliveMessageTest { + + @Test + public void test() throws Exception { + KeepAliveMessage m1 = new KeepAliveMessage(true, 10); + Assert.assertTrue(m1.getFlag()); + Assert.assertEquals(m1.getPriority(), 10); + Assert.assertEquals(m1.getType(), BACKUP_KEEP_ALIVE); + Assert.assertEquals(m1.getFrom(), null); + Assert.assertEquals(m1.getTimestamp(), 0); + Assert.assertEquals(m1.getData().length + 1, m1.getSendData().length); + + + Discover.BackupMessage backupMessage = Discover.BackupMessage.newBuilder() + .setFlag(true).setPriority(10).build(); + KeepAliveMessage m2 = new KeepAliveMessage(backupMessage.toByteArray()); + Assert.assertTrue(m2.getFlag()); + Assert.assertEquals(m2.getPriority(), 10); + Assert.assertEquals(m2.getType(), BACKUP_KEEP_ALIVE); + + Assert.assertEquals(m2.getMessageId().getBytes(), m1.getMessageId().getBytes()); + } +} diff --git a/framework/src/test/java/org/tron/common/backup/UdpMessageTypeEnumTest.java b/framework/src/test/java/org/tron/common/backup/UdpMessageTypeEnumTest.java new file mode 100644 index 00000000000..e3ded4a23e5 --- /dev/null +++ b/framework/src/test/java/org/tron/common/backup/UdpMessageTypeEnumTest.java @@ -0,0 +1,23 @@ +package org.tron.common.backup; + +import static org.tron.common.backup.message.UdpMessageTypeEnum.BACKUP_KEEP_ALIVE; +import static org.tron.common.backup.message.UdpMessageTypeEnum.UNKNOWN; + +import org.junit.Test; +import org.testng.Assert; +import org.tron.common.backup.message.UdpMessageTypeEnum; + +public class UdpMessageTypeEnumTest { + + @Test + public void test() { + UdpMessageTypeEnum type = UdpMessageTypeEnum.fromByte((byte) 5); + Assert.assertEquals(type.getType(), (byte) 0x05); + Assert.assertEquals(type, BACKUP_KEEP_ALIVE); + + + type = UdpMessageTypeEnum.fromByte((byte) 1); + Assert.assertEquals(type.getType(), (byte) 0xFF); + Assert.assertEquals(type, UNKNOWN); + } +} From 9d5d0e022d11fdb98910181fa8f1deeed435d214 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 18 Apr 2023 11:57:48 +0800 Subject: [PATCH 0746/1197] feat(net): optimize validSignature function --- .../main/java/org/tron/core/net/TronNetDelegate.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index 3e7381a0504..7ff02250eb5 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -315,14 +315,16 @@ public void pushTransaction(TransactionCapsule trx) throws P2pException { } public void validSignature(BlockCapsule block) throws P2pException { + boolean flag; try { - if (!block.validateSignature(dbManager.getDynamicPropertiesStore(), - dbManager.getAccountStore())) { - throw new P2pException(TypeEnum.BLOCK_SIGN_ERROR, "valid signature failed."); - } - } catch (ValidateSignatureException e) { + flag = block.validateSignature(dbManager.getDynamicPropertiesStore(), + dbManager.getAccountStore()); + } catch (Exception e) { throw new P2pException(TypeEnum.BLOCK_SIGN_ERROR, e); } + if (!flag) { + throw new P2pException(TypeEnum.BLOCK_SIGN_ERROR, "valid signature failed."); + } } public boolean validBlock(BlockCapsule block) throws P2pException { From 747757b0030ff341e2a8d70340780b70150ca995 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 18 Apr 2023 16:23:46 +0800 Subject: [PATCH 0747/1197] feat(net): optimize getBlockChainSummary logic --- framework/src/main/java/org/tron/core/db/Manager.java | 8 +++++--- .../src/main/java/org/tron/core/net/TronNetDelegate.java | 4 ++++ .../java/org/tron/core/net/service/sync/SyncService.java | 6 ++++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index b1127029b46..e7aadc7f4aa 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -193,7 +193,8 @@ public class Manager { @Getter @Setter private boolean isSyncMode; - + @Getter + private Object forkLock = new Object(); // map @Getter @Setter @@ -1269,8 +1270,9 @@ public void pushBlock(final BlockCapsule block) chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(), khaosDb.getHead(), khaosDb.getMiniStore().size(), khaosDb.getMiniUnlinkedStore().size()); - - switchFork(newBlock); + synchronized (forkLock) { + switchFork(newBlock); + } logger.info(SAVE_BLOCK, newBlock); logger.warn( diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index 7ff02250eb5..47e13de6109 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -349,4 +349,8 @@ public boolean allowPBFT() { return chainBaseManager.getDynamicPropertiesStore().allowPBFT(); } + public Object getForkLock() { + return dbManager.getForkLock(); + } + } diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 86b775df6f8..5f7ab11f6c9 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -23,7 +23,6 @@ import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.config.Parameter.NetConstants; import org.tron.core.config.args.Args; -import org.tron.core.exception.BadBlockException; import org.tron.core.exception.P2pException; import org.tron.core.exception.P2pException.TypeEnum; import org.tron.core.net.TronNetDelegate; @@ -114,7 +113,10 @@ public void syncNext(PeerConnection peer) { logger.warn("Peer {} is in sync", peer.getInetSocketAddress()); return; } - LinkedList chainSummary = getBlockChainSummary(peer); + LinkedList chainSummary; + synchronized (tronNetDelegate.getForkLock()) { + chainSummary = getBlockChainSummary(peer); + } peer.setSyncChainRequested(new Pair<>(chainSummary, System.currentTimeMillis())); peer.sendMessage(new SyncBlockChainMessage(chainSummary)); } catch (Exception e) { From 4e8152677f3ee5f03e0cafe55fafb663304f5483 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 18 Apr 2023 16:44:51 +0800 Subject: [PATCH 0748/1197] optimize test case --- .../common/logsfilter/EventParserTest.java | 3 +++ .../test/java/org/tron/core/WalletTest.java | 6 ++++++ .../java/org/tron/core/db/ManagerTest.java | 21 +++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/framework/src/test/java/org/tron/common/logsfilter/EventParserTest.java b/framework/src/test/java/org/tron/common/logsfilter/EventParserTest.java index a9b06c0e039..b5339156d9a 100644 --- a/framework/src/test/java/org/tron/common/logsfilter/EventParserTest.java +++ b/framework/src/test/java/org/tron/common/logsfilter/EventParserTest.java @@ -11,6 +11,7 @@ import org.tron.common.crypto.Hash; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.WalletUtil; import org.tron.core.Wallet; import org.tron.core.vm.LogInfoTriggerParser; import org.tron.protos.contract.SmartContractOuterClass.SmartContract.ABI; @@ -57,6 +58,8 @@ public synchronized void testEventParser() { + "000000000"; ABI abi = TvmTestUtils.jsonStr2Abi(abiStr); + Assert.assertFalse(WalletUtil.isConstant(abi, new byte[3])); + byte[] data = ByteArray.fromHexString(dataStr); List topicList = new LinkedList<>(); topicList.add(Hash.sha3(eventSign.getBytes())); diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 1d8ae810dfd..bfbbbbf8e48 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -755,6 +755,12 @@ public void testGetDelegatedResourceV2() { Protocol.Account account = Protocol.Account.newBuilder() .setAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))).build(); + + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addAssetV2("testv2".getBytes(), 1L); + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + wallet.getAccount(account); wallet.getProposalList(); wallet.getWitnessList(); diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index b7b29f49930..5c4f10dc738 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -938,4 +938,25 @@ private BlockCapsule createTestBlockCapsuleError(long time, blockCapsule.sign(ByteArray.fromHexString(addressToProvateKeys.get(witnessAddress))); return blockCapsule; } + + @Test + public void testExpireTransaction() { + TransferContract tc = + TransferContract.newBuilder() + .setAmount(10) + .setOwnerAddress(ByteString.copyFromUtf8("aaa")) + .setToAddress(ByteString.copyFromUtf8("bbb")) + .build(); + TransactionCapsule trx = new TransactionCapsule(tc, ContractType.TransferContract); + long latestBlockTime = dbManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); + trx.setExpiration(latestBlockTime - 100); + try { + dbManager.validateCommon(trx); + Assert.fail(); + } catch (TransactionExpirationException e) { + Assert.assertTrue(true); + } catch (TooBigTransactionException e) { + Assert.fail(); + } + } } From f2e064b5cdbb209b8aff4974e593c1d5a72ae922 Mon Sep 17 00:00:00 2001 From: "morgan.peng" Date: Fri, 10 Mar 2023 19:05:23 +0800 Subject: [PATCH 0749/1197] feat(db): check second cache config in unit tests 1. check second cache config in unit tests --- .../org/tron/core/db2/SnapshotRootTest.java | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/framework/src/test/java/org/tron/core/db2/SnapshotRootTest.java b/framework/src/test/java/org/tron/core/db2/SnapshotRootTest.java index f7985017285..a483be278ff 100644 --- a/framework/src/test/java/org/tron/core/db2/SnapshotRootTest.java +++ b/framework/src/test/java/org/tron/core/db2/SnapshotRootTest.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @@ -11,9 +13,12 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.springframework.util.CollectionUtils; +import org.testng.collections.Sets; import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; +import org.tron.common.cache.CacheStrategies; import org.tron.common.utils.FileUtil; import org.tron.common.utils.SessionOptional; import org.tron.core.Constant; @@ -24,6 +29,7 @@ import org.tron.core.db2.core.Snapshot; import org.tron.core.db2.core.SnapshotManager; import org.tron.core.db2.core.SnapshotRoot; +import org.tron.core.exception.ItemNotFoundException; public class SnapshotRootTest { @@ -31,6 +37,15 @@ public class SnapshotRootTest { private TronApplicationContext context; private Application appT; private SnapshotManager revokingDatabase; + private final Set noSecondCacheDBs = Sets.newHashSet(Arrays.asList("trans-cache", + "exchange-v2","nullifier","accountTrie","transactionRetStore","accountid-index", + "market_account","market_pair_to_price","recent-transaction","block-index","block", + "market_pair_price_to_order","proposal","tree-block-index","IncrementalMerkleTree", + "asset-issue","balance-trace","transactionHistoryStore","account-index","section-bloom", + "exchange","market_order","account-trace","contract-state","trans")); + private Set allDBNames; + private Set allRevokingDBNames; + @Before public void init() { @@ -113,6 +128,52 @@ public synchronized void testMergeList() { tronDatabase.close(); } + @Test + public void testSecondCacheCheck() + throws ItemNotFoundException { + revokingDatabase = context.getBean(SnapshotManager.class); + allRevokingDBNames = parseRevokingDBNames(context); + allDBNames = Arrays.stream(new File("output_revokingStore_test/database").list()) + .collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(allDBNames)) { + throw new ItemNotFoundException("No DBs found"); + } + allDBNames.removeAll(noSecondCacheDBs); + allDBNames.removeAll(CacheStrategies.CACHE_DBS); + allDBNames.retainAll(allRevokingDBNames); + org.junit.Assert.assertEquals(String.format("New added dbs %s " + + "shall consider to add second cache or add to noNeedCheckDBs!", + allDBNames.stream().collect(Collectors.joining(","))), allDBNames.size(), 0); + } + + @Test + public void testSecondCacheCheckAddDb() + throws ItemNotFoundException { + revokingDatabase = context.getBean(SnapshotManager.class); + allRevokingDBNames = parseRevokingDBNames(context); + allRevokingDBNames.add("secondCheckTestDB"); + FileUtil.createDirIfNotExists("output_revokingStore_test/database/secondCheckTestDB"); + allDBNames = Arrays.stream(new File("output_revokingStore_test/database").list()) + .collect(Collectors.toSet()); + FileUtil.deleteDir(new File("output_revokingStore_test/database/secondCheckTestDB")); + if (CollectionUtils.isEmpty(allDBNames)) { + throw new ItemNotFoundException("No DBs found"); + } + allDBNames.removeAll(noSecondCacheDBs); + allDBNames.removeAll(CacheStrategies.CACHE_DBS); + allDBNames.retainAll(allRevokingDBNames); + org.junit.Assert.assertTrue(String.format("New added dbs %s " + + "check second cache failed!", + allDBNames.stream().collect(Collectors.joining(","))), allDBNames.size() == 1); + } + + private Set parseRevokingDBNames(TronApplicationContext context) { + SnapshotManager snapshotManager = context.getBean(SnapshotManager.class); + return snapshotManager.getDbs().stream().map(chainbase -> + chainbase.getDbName()).collect(Collectors.toSet()); + } + + @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode From cd9e5347562b7369fa7d1a060b2160ee9b968e8b Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 19 Apr 2023 16:50:51 +0800 Subject: [PATCH 0750/1197] fix(net):descrease memory cost of test cases --- framework/build.gradle | 4 + .../vm/BandWidthRuntimeOutOfTimeTest.java | 2 + ...andWidthRuntimeOutOfTimeWithCheckTest.java | 2 + .../tron/core/db/TransactionExpireTest.java | 89 +++++++++++++++++++ 4 files changed, 97 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/db/TransactionExpireTest.java diff --git a/framework/build.gradle b/framework/build.gradle index f4f5134bf6e..85d01ed11b0 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -151,6 +151,10 @@ test { exclude 'org/tron/common/runtime/vm/WithdrawRewardTest.class' } maxHeapSize = "1024m" + doFirst { + forkEvery = 100 + jvmArgs "-XX:MetaspaceSize=128m","-XX:MaxMetaspaceSize=256m", "-XX:+UseG1GC" + } } task stest(type: Test) { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java index f8a4f1ef0bb..bb751d56941 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java @@ -133,6 +133,8 @@ public static void destroy() { Args.clearParam(); context.destroy(); FileUtil.deleteDir(new File(dbPath)); + FileUtil.deleteDir(new File(dbDirectory)); + FileUtil.deleteDir(new File(indexDirectory)); } @Test diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java index 68fa9e12fa7..5d015aa9356 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java @@ -135,6 +135,8 @@ public static void destroy() { Args.clearParam(); context.destroy(); FileUtil.deleteDir(new File(dbPath)); + FileUtil.deleteDir(new File(dbDirectory)); + FileUtil.deleteDir(new File(indexDirectory)); } @Test diff --git a/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java b/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java new file mode 100644 index 00000000000..26b1e7e7bc1 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java @@ -0,0 +1,89 @@ +package org.tron.core.db; + +import com.google.protobuf.ByteString; +import java.io.File; +import lombok.extern.slf4j.Slf4j; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.api.GrpcAPI; +import org.tron.api.GrpcAPI.Return.response_code; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.contract.BalanceContract.TransferContract; + +@Slf4j +public class TransactionExpireTest { + + private String dbPath = "output_expire_test"; + private TronApplicationContext context; + private Wallet wallet; + private Manager dbManager; + private BlockCapsule blockCapsule; + + @Before + public void init() { + Args.setParam(new String[] {"--output-directory", dbPath}, Constant.TEST_CONF); + CommonParameter.PARAMETER.setMinEffectiveConnection(0); + + context = new TronApplicationContext(DefaultConfig.class); + wallet = context.getBean(Wallet.class); + dbManager = context.getBean(Manager.class); + + blockCapsule = new BlockCapsule( + 1, + Sha256Hash.wrap(ByteString.copyFrom( + ByteArray.fromHexString( + "0304f784e4e7bae517bcab94c3e0c9214fb4ac7ff9d7d5a937d1f40031f87b81"))), + 1, + ByteString.copyFromUtf8("testAddress")); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(blockCapsule.getNum()); + dbManager.getDynamicPropertiesStore() + .saveLatestBlockHeaderTimestamp(blockCapsule.getTimeStamp()); + dbManager.updateRecentBlock(blockCapsule); + } + + @After + public void removeDb() { + Args.clearParam(); + context.destroy(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.info("Release resources failure."); + } + } + + @Test + public void testExpireTransaction() { + TransferContract transferContract = TransferContract.newBuilder() + .setAmount(1L) + .setOwnerAddress(ByteString.copyFrom(Args.getLocalWitnesses() + .getWitnessAccountAddress(CommonParameter.getInstance().isECKeyCryptoEngine()))) + .setToAddress(ByteString.copyFrom(ByteArray.fromHexString( + (Wallet.getAddressPreFixString() + "A389132D6639FBDA4FBC8B659264E6B7C90DB086")))) + .build(); + TransactionCapsule transactionCapsule = + new TransactionCapsule(transferContract, ContractType.TransferContract); + transactionCapsule.setReference(blockCapsule.getNum(), blockCapsule.getBlockId().getBytes()); + Assert.assertEquals(1, blockCapsule.getTimeStamp()); + + long blockTimeStamp = blockCapsule.getTimeStamp(); + transactionCapsule.setExpiration(blockTimeStamp - 1); + transactionCapsule.sign(ByteArray.fromHexString(Args.getLocalWitnesses().getPrivateKey())); + + GrpcAPI.Return result = wallet.broadcastTransaction(transactionCapsule.getInstance()); + Assert.assertEquals(response_code.TRANSACTION_EXPIRATION_ERROR, result.getCode()); + } +} From 45f0e016d7dcd66f34845aa93a6aa46e122dfa3e Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 20 Apr 2023 14:24:02 +0800 Subject: [PATCH 0751/1197] feat(version): update version --- framework/src/main/java/org/tron/program/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 88f87a68297..d3c9846d6e4 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -4,7 +4,7 @@ public class Version { public static final String VERSION_NAME = "GreatVoyage-v4.7.0.1-75-g36fc5063e9"; public static final String VERSION_CODE = "17673"; - private static final String VERSION = "4.7.1"; + private static final String VERSION = "4.7.2"; public static String getVersion() { return VERSION; From 73a7419c110c380b4b4f1a43ba2d280b98ac0538 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Thu, 20 Apr 2023 17:05:07 +0800 Subject: [PATCH 0752/1197] fix(test): optimize unit test --- .../common/client/DatabaseGrpcClient.java | 4 +- .../tron/common/client/WalletGrpcClient.java | 4 +- .../java/org/tron/program/SolidityNode.java | 17 +- .../services/http/BroadcastServletTest.java | 3 +- .../core/services/http/HttpServletTest.java | 531 +++++++++++++++ .../http/TriggerSmartContractServletTest.java | 10 +- ...GetTransactionByIdSolidityServletTest.java | 16 +- .../tron/core/zksnark/SendCoinShieldTest.java | 603 +++++++++--------- .../org/tron/program/SolidityNodeTest.java | 7 +- 9 files changed, 885 insertions(+), 310 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/services/http/HttpServletTest.java diff --git a/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java b/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java index b83c7235900..f3650bfd2be 100644 --- a/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java +++ b/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java @@ -15,14 +15,14 @@ public class DatabaseGrpcClient { public DatabaseGrpcClient(String host, int port) { channel = ManagedChannelBuilder.forAddress(host, port) - .usePlaintext(true) + .usePlaintext() .build(); databaseBlockingStub = DatabaseGrpc.newBlockingStub(channel); } public DatabaseGrpcClient(String host) { channel = ManagedChannelBuilder.forTarget(host) - .usePlaintext(true) + .usePlaintext() .build(); databaseBlockingStub = DatabaseGrpc.newBlockingStub(channel); } diff --git a/framework/src/main/java/org/tron/common/client/WalletGrpcClient.java b/framework/src/main/java/org/tron/common/client/WalletGrpcClient.java index 9d3b5797e20..d28df0e7c77 100644 --- a/framework/src/main/java/org/tron/common/client/WalletGrpcClient.java +++ b/framework/src/main/java/org/tron/common/client/WalletGrpcClient.java @@ -29,14 +29,14 @@ public class WalletGrpcClient { public WalletGrpcClient(String host, int port) { channel = ManagedChannelBuilder.forAddress(host, port) - .usePlaintext(true) + .usePlaintext() .build(); walletBlockingStub = WalletGrpc.newBlockingStub(channel); } public WalletGrpcClient(String host) { channel = ManagedChannelBuilder.forTarget(host) - .usePlaintext(true) + .usePlaintext() .build(); walletBlockingStub = WalletGrpc.newBlockingStub(channel); } diff --git a/framework/src/main/java/org/tron/program/SolidityNode.java b/framework/src/main/java/org/tron/program/SolidityNode.java index 9884a14a62b..0ca001da7bb 100644 --- a/framework/src/main/java/org/tron/program/SolidityNode.java +++ b/framework/src/main/java/org/tron/program/SolidityNode.java @@ -7,6 +7,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.BooleanUtils; import org.springframework.context.ApplicationContext; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; @@ -37,7 +38,7 @@ public class SolidityNode { private AtomicLong remoteBlockNum = new AtomicLong(); - private LinkedBlockingDeque blockQueue = new LinkedBlockingDeque(100); + private LinkedBlockingDeque blockQueue = new LinkedBlockingDeque<>(100); private int exceptionSleepTime = 1000; @@ -48,7 +49,7 @@ public SolidityNode(Manager dbManager) { this.chainBaseManager = dbManager.getChainBaseManager(); resolveCompatibilityIssueIfUsingFullNodeDatabase(); ID.set(chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum()); - databaseGrpcClient = new DatabaseGrpcClient(Args.getInstance().getTrustNodeAddr()); + databaseGrpcClient = new DatabaseGrpcClient(CommonParameter.getInstance().getTrustNodeAddr()); remoteBlockNum.set(getLastSolidityBlockNum()); } @@ -58,13 +59,13 @@ public SolidityNode(Manager dbManager) { public static void main(String[] args) { logger.info("Solidity node is running."); Args.setParam(args, Constant.TESTNET_CONF); - CommonParameter parameter = Args.getInstance(); + CommonParameter parameter = CommonParameter.getInstance(); logger.info("index switch is {}", BooleanUtils.toStringOnOff(BooleanUtils .toBoolean(parameter.getStorage().getIndexSwitch()))); - if (StringUtils.isEmpty(parameter.getTrustNodeAddr())) { + if (ObjectUtils.isEmpty(parameter.getTrustNodeAddr())) { logger.error("Trust node is not set."); return; } @@ -102,13 +103,13 @@ public static void main(String[] args) { private void start() { try { - new Thread(() -> getBlock()).start(); - new Thread(() -> processBlock()).start(); + new Thread(this::getBlock).start(); + new Thread(this::processBlock).start(); logger.info("Success to start solid node, ID: {}, remoteBlockNum: {}.", ID.get(), remoteBlockNum); } catch (Exception e) { - logger - .error("Failed to start solid node, address: {}.", Args.getInstance().getTrustNodeAddr()); + logger.error("Failed to start solid node, address: {}.", + CommonParameter.getInstance().getTrustNodeAddr()); System.exit(0); } } diff --git a/framework/src/test/java/org/tron/core/services/http/BroadcastServletTest.java b/framework/src/test/java/org/tron/core/services/http/BroadcastServletTest.java index 1d8f02910b3..24ec969c08b 100644 --- a/framework/src/test/java/org/tron/core/services/http/BroadcastServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/BroadcastServletTest.java @@ -81,7 +81,7 @@ public void tearDown() { } @Test - public void testDoPost() throws IOException { + public void doPostTest() throws IOException { URLStreamHandlerFactory urlStreamHandlerFactory = mock(URLStreamHandlerFactory.class); URL.setURLStreamHandlerFactory(urlStreamHandlerFactory); @@ -139,6 +139,7 @@ public void testDoPost() throws IOException { while ((line = in.readLine()) != null) { result.append(line).append("\n"); } + Assert.assertNotNull(result); in.close(); writer.flush(); FileInputStream fileInputStream = new FileInputStream("temp.txt"); diff --git a/framework/src/test/java/org/tron/core/services/http/HttpServletTest.java b/framework/src/test/java/org/tron/core/services/http/HttpServletTest.java new file mode 100644 index 00000000000..9775db0a954 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/HttpServletTest.java @@ -0,0 +1,531 @@ +package org.tron.core.services.http; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Before; +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; + +@Slf4j +public class HttpServletTest { + private AccountPermissionUpdateServlet accountPermissionUpdateServlet; + private BroadcastHexServlet broadcastHexServlet; + private BroadcastServlet broadcastServlet; + private ClearABIServlet clearABIServlet; + private CreateAccountServlet createAccountServlet; + private CreateAssetIssueServlet createAssetIssueServlet; + private CreateCommonTransactionServlet createCommonTransactionServlet; + private CreateShieldedContractParametersServlet createShieldedContractParametersServlet; + private CreateShieldedContractParametersWithoutAskServlet + createShieldedContractParametersWithoutAskServlet; + private CreateShieldedTransactionServlet createShieldedTransactionServlet; + private CreateShieldedTransactionWithoutSpendAuthSigServlet + createShieldedTransactionWithoutSpendAuthSigServlet; + private CreateShieldNullifierServlet createShieldNullifierServlet; + private CreateSpendAuthSigServlet createSpendAuthSigServlet; + private CreateWitnessServlet createWitnessServlet; + private DelegateResourceServlet delegateResourceServlet; + private DeployContractServlet deployContractServlet; + private EstimateEnergyServlet estimateEnergyServlet; + private ExchangeCreateServlet exchangeCreateServlet; + private ExchangeInjectServlet exchangeInjectServlet; + private ExchangeTransactionServlet exchangeTransactionServlet; + private ExchangeWithdrawServlet exchangeWithdrawServlet; + private FreezeBalanceServlet freezeBalanceServlet; + private FreezeBalanceV2Servlet freezeBalanceV2Servlet; + private GetAccountBalanceServlet getAccountBalanceServlet; + private GetAccountByIdServlet getAccountByIdServlet; + private GetAccountNetServlet getAccountNetServlet; + private GetAccountResourceServlet getAccountResourceServlet; + private GetAccountServlet getAccountServlet; + private GetAkFromAskServlet getAkFromAskServlet; + private GetAssetIssueByAccountServlet getAssetIssueByAccountServlet; + private GetAssetIssueByIdServlet getAssetIssueByIdServlet; + private GetAssetIssueByNameServlet getAssetIssueByNameServlet; + private GetAssetIssueListByNameServlet getAssetIssueListByNameServlet; + private GetAssetIssueListServlet getAssetIssueListServlet; + private GetAvailableUnfreezeCountServlet getAvailableUnfreezeCountServlet; + private GetBandwidthPricesServlet getBandwidthPricesServlet; + private GetBlockBalanceServlet getBlockBalanceServlet; + private GetBlockByIdServlet getBlockByIdServlet; + private GetBlockByLatestNumServlet getBlockByLatestNumServlet; + private GetBlockByLimitNextServlet getBlockByLimitNextServlet; + private GetBlockByNumServlet getBlockByNumServlet; + private GetBlockServlet getBlockServlet; + private GetBrokerageServlet getBrokerageServlet; + private GetBurnTrxServlet getBurnTrxServlet; + private GetCanDelegatedMaxSizeServlet getCanDelegatedMaxSizeServlet; + private GetCanWithdrawUnfreezeAmountServlet getCanWithdrawUnfreezeAmountServlet; + private GetChainParametersServlet getChainParametersServlet; + private GetContractInfoServlet getContractInfoServlet; + private GetContractServlet getContractServlet; + private GetDelegatedResourceAccountIndexServlet getDelegatedResourceAccountIndexServlet; + private GetDelegatedResourceAccountIndexV2Servlet getDelegatedResourceAccountIndexV2Servlet; + private GetDelegatedResourceServlet getDelegatedResourceServlet; + private GetDelegatedResourceV2Servlet getDelegatedResourceV2Servlet; + private GetDiversifierServlet getDiversifierServlet; + private GetEnergyPricesServlet getEnergyPricesServlet; + private GetExchangeByIdServlet getExchangeByIdServlet; + private GetExpandedSpendingKeyServlet getExpandedSpendingKeyServlet; + private GetIncomingViewingKeyServlet getIncomingViewingKeyServlet; + private GetMarketOrderByAccountServlet getMarketOrderByAccountServlet; + private GetMarketOrderByIdServlet getMarketOrderByIdServlet; + private GetMarketOrderListByPairServlet getMarketOrderListByPairServlet; + private GetMarketPairListServlet getMarketPairListServlet; + private GetMarketPriceByPairServlet getMarketPriceByPairServlet; + private GetMemoFeePricesServlet getMemoFeePricesServlet; + private GetMerkleTreeVoucherInfoServlet getMerkleTreeVoucherInfoServlet; + private GetNewShieldedAddressServlet getNewShieldedAddressServlet; + private GetNextMaintenanceTimeServlet getNextMaintenanceTimeServlet; + private GetNkFromNskServlet getNkFromNskServlet; + private GetNodeInfoServlet getNodeInfoServlet; + private GetNowBlockServlet getNowBlockServlet; + private GetPaginatedAssetIssueListServlet getPaginatedAssetIssueListServlet; + private GetPaginatedExchangeListServlet getPaginatedExchangeListServlet; + private GetPaginatedProposalListServlet getPaginatedProposalListServlet; + private GetPendingSizeServlet getPendingSizeServlet; + private GetProposalByIdServlet getProposalByIdServlet; + private GetRcmServlet getRcmServlet; + private GetRewardServlet getRewardServlet; + private GetShieldTransactionHashServlet getShieldTransactionHashServlet; + private GetSpendingKeyServlet getSpendingKeyServlet; + private GetTransactionApprovedListServlet getTransactionApprovedListServlet; + private GetTransactionByIdServlet getTransactionByIdServlet; + private GetTransactionCountByBlockNumServlet getTransactionCountByBlockNumServlet; + private GetTransactionFromPendingServlet getTransactionFromPendingServlet; + private GetTransactionInfoByBlockNumServlet getTransactionInfoByBlockNumServlet; + private GetTransactionInfoByIdServlet getTransactionInfoByIdServlet; + private GetTransactionListFromPendingServlet getTransactionListFromPendingServlet; + private GetTransactionReceiptByIdServlet getTransactionReceiptByIdServlet; + private GetTransactionSignWeightServlet getTransactionSignWeightServlet; + private GetTriggerInputForShieldedTRC20ContractServlet + getTriggerInputForShieldedTRC20ContractServlet; + private GetZenPaymentAddressServlet getZenPaymentAddressServlet; + private IsShieldedTRC20ContractNoteSpentServlet isShieldedTRC20ContractNoteSpentServlet; + private IsSpendServlet isSpendServlet; + private ListExchangesServlet listExchangesServlet; + private ListNodesServlet listNodesServlet; + private ListProposalsServlet listProposalsServlet; + private ListWitnessesServlet listWitnessesServlet; + private MarketCancelOrderServlet marketCancelOrderServlet; + private MarketSellAssetServlet marketSellAssetServlet; + private MetricsServlet metricsServlet; + private ParticipateAssetIssueServlet participateAssetIssueServlet; + private ProposalApproveServlet proposalApproveServlet; + private ProposalCreateServlet proposalCreateServlet; + private ProposalDeleteServlet proposalDeleteServlet; + private ScanAndMarkNoteByIvkServlet scanAndMarkNoteByIvkServlet; + private ScanNoteByIvkServlet scanNoteByIvkServlet; + private ScanNoteByOvkServlet scanNoteByOvkServlet; + private ScanShieldedTRC20NotesByIvkServlet scanShieldedTRC20NotesByIvkServlet; + private ScanShieldedTRC20NotesByOvkServlet scanShieldedTRC20NotesByOvkServlet; + private SetAccountIdServlet setAccountIdServlet; + private TotalTransactionServlet totalTransactionServlet; + private TransferAssetServlet transferAssetServlet; + private TransferServlet transferServlet; + private TriggerConstantContractServlet triggerConstantContractServlet; + private TriggerSmartContractServlet triggerSmartContractServlet; + private UnDelegateResourceServlet unDelegateResourceServlet; + private UnFreezeAssetServlet unFreezeAssetServlet; + private UnFreezeBalanceServlet unFreezeBalanceServlet; + private UnFreezeBalanceV2Servlet unFreezeBalanceV2Servlet; + private UpdateAccountServlet updateAccountServlet; + private UpdateAssetServlet updateAssetServlet; + private UpdateBrokerageServlet updateBrokerageServlet; + private UpdateEnergyLimitServlet updateEnergyLimitServlet; + private UpdateSettingServlet updateSettingServlet; + private UpdateWitnessServlet updateWitnessServlet; + private ValidateAddressServlet validateAddressServlet; + private VoteWitnessAccountServlet voteWitnessAccountServlet; + private WithdrawBalanceServlet withdrawBalanceServlet; + private WithdrawExpireUnfreezeServlet withdrawExpireUnfreezeServlet; + private MockHttpServletRequest request; + private MockHttpServletResponse response; + + @Before + public void setUp() { + accountPermissionUpdateServlet = new AccountPermissionUpdateServlet(); + broadcastHexServlet = new BroadcastHexServlet(); + broadcastServlet = new BroadcastServlet(); + clearABIServlet = new ClearABIServlet(); + createAccountServlet = new CreateAccountServlet(); + createAssetIssueServlet = new CreateAssetIssueServlet(); + createCommonTransactionServlet = new CreateCommonTransactionServlet(); + createShieldedContractParametersServlet = new CreateShieldedContractParametersServlet(); + createShieldedContractParametersWithoutAskServlet = + new CreateShieldedContractParametersWithoutAskServlet(); + createShieldedTransactionServlet = new CreateShieldedTransactionServlet(); + createShieldedTransactionWithoutSpendAuthSigServlet = + new CreateShieldedTransactionWithoutSpendAuthSigServlet(); + createShieldNullifierServlet = new CreateShieldNullifierServlet(); + createSpendAuthSigServlet = new CreateSpendAuthSigServlet(); + createWitnessServlet = new CreateWitnessServlet(); + delegateResourceServlet = new DelegateResourceServlet(); + deployContractServlet = new DeployContractServlet(); + estimateEnergyServlet = new EstimateEnergyServlet(); + exchangeCreateServlet = new ExchangeCreateServlet(); + exchangeInjectServlet = new ExchangeInjectServlet(); + exchangeTransactionServlet = new ExchangeTransactionServlet(); + exchangeWithdrawServlet = new ExchangeWithdrawServlet(); + freezeBalanceServlet = new FreezeBalanceServlet(); + freezeBalanceV2Servlet = new FreezeBalanceV2Servlet(); + getAccountBalanceServlet = new GetAccountBalanceServlet(); + getAccountByIdServlet = new GetAccountByIdServlet(); + getAccountNetServlet = new GetAccountNetServlet(); + getAccountResourceServlet = new GetAccountResourceServlet(); + getAccountServlet = new GetAccountServlet(); + getAkFromAskServlet = new GetAkFromAskServlet(); + getAssetIssueByAccountServlet = new GetAssetIssueByAccountServlet(); + getAssetIssueByIdServlet = new GetAssetIssueByIdServlet(); + getAssetIssueByNameServlet = new GetAssetIssueByNameServlet(); + getAssetIssueListByNameServlet = new GetAssetIssueListByNameServlet(); + getAssetIssueListServlet = new GetAssetIssueListServlet(); + getAvailableUnfreezeCountServlet = new GetAvailableUnfreezeCountServlet(); + getBandwidthPricesServlet = new GetBandwidthPricesServlet(); + getBlockBalanceServlet = new GetBlockBalanceServlet(); + getBlockByIdServlet = new GetBlockByIdServlet(); + getBlockByLatestNumServlet = new GetBlockByLatestNumServlet(); + getBlockByLimitNextServlet = new GetBlockByLimitNextServlet(); + getBlockByNumServlet = new GetBlockByNumServlet(); + getBlockServlet = new GetBlockServlet(); + getBrokerageServlet = new GetBrokerageServlet(); + getBurnTrxServlet = new GetBurnTrxServlet(); + getCanDelegatedMaxSizeServlet = new GetCanDelegatedMaxSizeServlet(); + getCanWithdrawUnfreezeAmountServlet = new GetCanWithdrawUnfreezeAmountServlet(); + getChainParametersServlet = new GetChainParametersServlet(); + getContractInfoServlet = new GetContractInfoServlet(); + getContractServlet = new GetContractServlet(); + getDelegatedResourceAccountIndexServlet = new GetDelegatedResourceAccountIndexServlet(); + getDelegatedResourceAccountIndexV2Servlet = new GetDelegatedResourceAccountIndexV2Servlet(); + getDelegatedResourceServlet = new GetDelegatedResourceServlet(); + getDelegatedResourceV2Servlet = new GetDelegatedResourceV2Servlet(); + getDiversifierServlet = new GetDiversifierServlet(); + getEnergyPricesServlet = new GetEnergyPricesServlet(); + getExchangeByIdServlet = new GetExchangeByIdServlet(); + getExpandedSpendingKeyServlet = new GetExpandedSpendingKeyServlet(); + getIncomingViewingKeyServlet = new GetIncomingViewingKeyServlet(); + getMarketOrderByAccountServlet = new GetMarketOrderByAccountServlet(); + getMarketOrderByIdServlet = new GetMarketOrderByIdServlet(); + getMarketOrderListByPairServlet = new GetMarketOrderListByPairServlet(); + getMarketPairListServlet = new GetMarketPairListServlet(); + getMarketPriceByPairServlet = new GetMarketPriceByPairServlet(); + getMemoFeePricesServlet = new GetMemoFeePricesServlet(); + getMerkleTreeVoucherInfoServlet = new GetMerkleTreeVoucherInfoServlet(); + getNewShieldedAddressServlet = new GetNewShieldedAddressServlet(); + getNextMaintenanceTimeServlet = new GetNextMaintenanceTimeServlet(); + getNkFromNskServlet = new GetNkFromNskServlet(); + getNodeInfoServlet = new GetNodeInfoServlet(); + getNowBlockServlet = new GetNowBlockServlet(); + getPaginatedAssetIssueListServlet = new GetPaginatedAssetIssueListServlet(); + getPaginatedExchangeListServlet = new GetPaginatedExchangeListServlet(); + getPaginatedProposalListServlet = new GetPaginatedProposalListServlet(); + getPendingSizeServlet = new GetPendingSizeServlet(); + getProposalByIdServlet = new GetProposalByIdServlet(); + getRcmServlet = new GetRcmServlet(); + getRewardServlet = new GetRewardServlet(); + getShieldTransactionHashServlet = new GetShieldTransactionHashServlet(); + getSpendingKeyServlet = new GetSpendingKeyServlet(); + getTransactionApprovedListServlet = new GetTransactionApprovedListServlet(); + getTransactionByIdServlet = new GetTransactionByIdServlet(); + getTransactionCountByBlockNumServlet = new GetTransactionCountByBlockNumServlet(); + getTransactionFromPendingServlet = new GetTransactionFromPendingServlet(); + getTransactionInfoByBlockNumServlet = new GetTransactionInfoByBlockNumServlet(); + getTransactionInfoByIdServlet = new GetTransactionInfoByIdServlet(); + getTransactionListFromPendingServlet = new GetTransactionListFromPendingServlet(); + getTransactionReceiptByIdServlet = new GetTransactionReceiptByIdServlet(); + getTransactionSignWeightServlet = new GetTransactionSignWeightServlet(); + getTriggerInputForShieldedTRC20ContractServlet = + new GetTriggerInputForShieldedTRC20ContractServlet(); + getZenPaymentAddressServlet = new GetZenPaymentAddressServlet(); + isShieldedTRC20ContractNoteSpentServlet = new IsShieldedTRC20ContractNoteSpentServlet(); + isSpendServlet = new IsSpendServlet(); + listExchangesServlet = new ListExchangesServlet(); + listNodesServlet = new ListNodesServlet(); + listProposalsServlet = new ListProposalsServlet(); + listWitnessesServlet = new ListWitnessesServlet(); + marketCancelOrderServlet = new MarketCancelOrderServlet(); + marketSellAssetServlet = new MarketSellAssetServlet(); + metricsServlet = new MetricsServlet(); + participateAssetIssueServlet = new ParticipateAssetIssueServlet(); + proposalApproveServlet = new ProposalApproveServlet(); + proposalCreateServlet = new ProposalCreateServlet(); + proposalDeleteServlet = new ProposalDeleteServlet(); + scanAndMarkNoteByIvkServlet = new ScanAndMarkNoteByIvkServlet(); + scanNoteByIvkServlet = new ScanNoteByIvkServlet(); + scanNoteByOvkServlet = new ScanNoteByOvkServlet(); + scanShieldedTRC20NotesByIvkServlet = new ScanShieldedTRC20NotesByIvkServlet(); + scanShieldedTRC20NotesByOvkServlet = new ScanShieldedTRC20NotesByOvkServlet(); + setAccountIdServlet = new SetAccountIdServlet(); + totalTransactionServlet = new TotalTransactionServlet(); + transferAssetServlet = new TransferAssetServlet(); + transferServlet = new TransferServlet(); + triggerConstantContractServlet = new TriggerConstantContractServlet(); + triggerSmartContractServlet = new TriggerSmartContractServlet(); + unDelegateResourceServlet = new UnDelegateResourceServlet(); + unFreezeAssetServlet = new UnFreezeAssetServlet(); + unFreezeBalanceServlet = new UnFreezeBalanceServlet(); + unFreezeBalanceV2Servlet = new UnFreezeBalanceV2Servlet(); + updateAccountServlet = new UpdateAccountServlet(); + updateAssetServlet = new UpdateAssetServlet(); + updateBrokerageServlet = new UpdateBrokerageServlet(); + updateEnergyLimitServlet = new UpdateEnergyLimitServlet(); + updateSettingServlet = new UpdateSettingServlet(); + updateWitnessServlet = new UpdateWitnessServlet(); + validateAddressServlet = new ValidateAddressServlet(); + voteWitnessAccountServlet = new VoteWitnessAccountServlet(); + withdrawBalanceServlet = new WithdrawBalanceServlet(); + withdrawExpireUnfreezeServlet = new WithdrawExpireUnfreezeServlet(); + request = new MockHttpServletRequest(); + request.setCharacterEncoding("UTF-8"); + response = new MockHttpServletResponse(); + } + + @Test + public void doGetTest() { + accountPermissionUpdateServlet.doGet(request, response); + clearABIServlet.doGet(request, response); + createAssetIssueServlet.doGet(request, response); + createShieldedContractParametersServlet.doGet(request, response); + createShieldedContractParametersWithoutAskServlet.doGet(request, response); + createShieldedTransactionServlet.doGet(request, response); + createShieldedTransactionWithoutSpendAuthSigServlet.doGet(request, response); + createShieldNullifierServlet.doGet(request, response); + createSpendAuthSigServlet.doGet(request, response); + createWitnessServlet.doGet(request, response); + deployContractServlet.doGet(request, response); + estimateEnergyServlet.doGet(request, response); + getAccountByIdServlet.doGet(request, response); + getAccountNetServlet.doGet(request, response); + getAccountResourceServlet.doGet(request, response); + getAccountServlet.doGet(request, response); + getAkFromAskServlet.doGet(request, response); + getAssetIssueByAccountServlet.doGet(request, response); + getAssetIssueByIdServlet.doGet(request, response); + getAssetIssueByNameServlet.doGet(request, response); + getAssetIssueListByNameServlet.doGet(request, response); + getAssetIssueListServlet.doGet(request, response); + getAvailableUnfreezeCountServlet.doGet(request, response); + getBandwidthPricesServlet.doGet(request, response); + getBlockByIdServlet.doGet(request, response); + getBlockByLatestNumServlet.doGet(request, response); + getBlockByLimitNextServlet.doGet(request, response); + getBlockByNumServlet.doGet(request, response); + getBlockServlet.doGet(request, response); + getBrokerageServlet.doGet(request, response); + getBurnTrxServlet.doGet(request, response); + getCanDelegatedMaxSizeServlet.doGet(request, response); + getCanWithdrawUnfreezeAmountServlet.doGet(request, response); + getChainParametersServlet.doGet(request, response); + getContractInfoServlet.doGet(request, response); + getContractServlet.doGet(request, response); + getDelegatedResourceAccountIndexServlet.doGet(request, response); + getDelegatedResourceAccountIndexV2Servlet.doGet(request, response); + getDelegatedResourceServlet.doGet(request, response); + getDelegatedResourceV2Servlet.doGet(request, response); + getDiversifierServlet.doGet(request, response); + getEnergyPricesServlet.doGet(request, response); + getExchangeByIdServlet.doGet(request, response); + getExpandedSpendingKeyServlet.doGet(request, response); + getIncomingViewingKeyServlet.doGet(request, response); + getMarketOrderByAccountServlet.doGet(request, response); + getMarketOrderByIdServlet.doGet(request, response); + getMarketOrderListByPairServlet.doGet(request, response); + getMarketPairListServlet.doGet(request, response); + getMarketPriceByPairServlet.doGet(request, response); + getMemoFeePricesServlet.doGet(request, response); + getMerkleTreeVoucherInfoServlet.doGet(request, response); + getNewShieldedAddressServlet.doGet(request, response); + getNextMaintenanceTimeServlet.doGet(request, response); + getNkFromNskServlet.doGet(request, response); + getNodeInfoServlet.doGet(request, response); + getNowBlockServlet.doGet(request, response); + getPaginatedAssetIssueListServlet.doGet(request, response); + getPaginatedExchangeListServlet.doGet(request, response); + getPaginatedProposalListServlet.doGet(request, response); + getPendingSizeServlet.doGet(request, response); + getProposalByIdServlet.doGet(request, response); + getRcmServlet.doGet(request, response); + getRewardServlet.doGet(request, response); + getShieldTransactionHashServlet.doGet(request, response); + getSpendingKeyServlet.doGet(request, response); + getTransactionApprovedListServlet.doGet(request, response); + getTransactionByIdServlet.doGet(request, response); + getTransactionCountByBlockNumServlet.doGet(request, response); + getTransactionFromPendingServlet.doGet(request, response); + getTransactionInfoByBlockNumServlet.doGet(request, response); + getTransactionInfoByIdServlet.doGet(request, response); + getTransactionListFromPendingServlet.doGet(request, response); + getTransactionReceiptByIdServlet.doGet(request, response); + getTransactionSignWeightServlet.doGet(request, response); + getTriggerInputForShieldedTRC20ContractServlet.doGet(request, response); + getZenPaymentAddressServlet.doGet(request, response); + isShieldedTRC20ContractNoteSpentServlet.doGet(request, response); + isSpendServlet.doGet(request, response); + listExchangesServlet.doGet(request, response); + listNodesServlet.doGet(request, response); + listProposalsServlet.doGet(request, response); + listWitnessesServlet.doGet(request, response); + marketCancelOrderServlet.doGet(request, response); + marketSellAssetServlet.doGet(request, response); + metricsServlet.doGet(request, response); + participateAssetIssueServlet.doGet(request, response); + proposalApproveServlet.doGet(request, response); + proposalCreateServlet.doGet(request, response); + proposalDeleteServlet.doGet(request, response); + scanAndMarkNoteByIvkServlet.doGet(request, response); + scanNoteByIvkServlet.doGet(request, response); + scanNoteByOvkServlet.doGet(request, response); + scanShieldedTRC20NotesByIvkServlet.doGet(request, response); + scanShieldedTRC20NotesByOvkServlet.doGet(request, response); + setAccountIdServlet.doGet(request, response); + totalTransactionServlet.doGet(request, response); + transferAssetServlet.doGet(request, response); + transferServlet.doGet(request, response); + triggerConstantContractServlet.doGet(request, response); + triggerSmartContractServlet.doGet(request, response); + unDelegateResourceServlet.doGet(request, response); + unFreezeAssetServlet.doGet(request, response); + unFreezeBalanceServlet.doGet(request, response); + unFreezeBalanceV2Servlet.doGet(request, response); + updateAccountServlet.doGet(request, response); + updateAssetServlet.doGet(request, response); + updateEnergyLimitServlet.doGet(request, response); + updateSettingServlet.doGet(request, response); + updateWitnessServlet.doGet(request, response); + validateAddressServlet.doGet(request, response); + voteWitnessAccountServlet.doGet(request, response); + withdrawBalanceServlet.doGet(request, response); + withdrawExpireUnfreezeServlet.doGet(request, response); + } + + + @Test + public void doPostTest() { + request.addParameter("owner_address", "TZ4UXDV5ZhNW7fb2AMSbgfAEZ7hWsnYS2g"); + accountPermissionUpdateServlet.doPost(request, response); + broadcastHexServlet.doPost(request, response); + broadcastServlet.doPost(request, response); + clearABIServlet.doPost(request, response); + createAccountServlet.doPost(request, response); + createAssetIssueServlet.doPost(request, response); + createCommonTransactionServlet.doPost(request, response); + createShieldedContractParametersServlet.doPost(request, response); + createShieldedContractParametersWithoutAskServlet.doPost(request, response); + createShieldedTransactionServlet.doPost(request, response); + createShieldedTransactionWithoutSpendAuthSigServlet.doPost(request, response); + createShieldNullifierServlet.doPost(request, response); + createSpendAuthSigServlet.doPost(request, response); + createWitnessServlet.doPost(request, response); + delegateResourceServlet.doPost(request, response); + deployContractServlet.doPost(request, response); + exchangeCreateServlet.doPost(request, response); + exchangeInjectServlet.doPost(request, response); + exchangeTransactionServlet.doPost(request, response); + exchangeWithdrawServlet.doPost(request, response); + freezeBalanceServlet.doPost(request, response); + freezeBalanceV2Servlet.doPost(request, response); + getAccountBalanceServlet.doPost(request, response); + getAccountByIdServlet.doPost(request, response); + getAccountNetServlet.doPost(request, response); + getAccountResourceServlet.doPost(request, response); + getAccountServlet.doPost(request, response); + getAkFromAskServlet.doPost(request, response); + getAssetIssueByAccountServlet.doPost(request, response); + getAssetIssueByIdServlet.doPost(request, response); + getAssetIssueByNameServlet.doPost(request, response); + getAssetIssueListByNameServlet.doPost(request, response); + getAssetIssueListServlet.doPost(request, response); + getAvailableUnfreezeCountServlet.doPost(request, response); + getBandwidthPricesServlet.doPost(request, response); + getBlockBalanceServlet.doPost(request, response); + getBlockByIdServlet.doPost(request, response); + getBlockByLatestNumServlet.doPost(request, response); + getBlockByLimitNextServlet.doPost(request, response); + getBlockByNumServlet.doPost(request, response); + getBlockServlet.doPost(request, response); + getBrokerageServlet.doPost(request, response); + getBurnTrxServlet.doPost(request, response); + getCanDelegatedMaxSizeServlet.doPost(request, response); + getCanWithdrawUnfreezeAmountServlet.doPost(request, response); + getChainParametersServlet.doPost(request, response); + getContractInfoServlet.doPost(request, response); + getContractServlet.doPost(request, response); + getDelegatedResourceAccountIndexServlet.doPost(request, response); + getDelegatedResourceAccountIndexV2Servlet.doPost(request, response); + getDelegatedResourceServlet.doPost(request, response); + getDelegatedResourceV2Servlet.doPost(request, response); + getDiversifierServlet.doPost(request, response); + getEnergyPricesServlet.doPost(request, response); + getExchangeByIdServlet.doPost(request, response); + getExpandedSpendingKeyServlet.doPost(request, response); + getIncomingViewingKeyServlet.doPost(request, response); + getMarketOrderByAccountServlet.doPost(request, response); + getMarketOrderByIdServlet.doPost(request, response); + getMarketOrderListByPairServlet.doPost(request, response); + getMarketPairListServlet.doPost(request, response); + getMarketPriceByPairServlet.doPost(request, response); + getMemoFeePricesServlet.doPost(request, response); + getMerkleTreeVoucherInfoServlet.doPost(request, response); + getNewShieldedAddressServlet.doPost(request, response); + getNextMaintenanceTimeServlet.doPost(request, response); + getNkFromNskServlet.doPost(request, response); + getNodeInfoServlet.doPost(request, response); + getNowBlockServlet.doPost(request, response); + getPaginatedAssetIssueListServlet.doPost(request, response); + getPaginatedExchangeListServlet.doPost(request, response); + getPaginatedProposalListServlet.doPost(request, response); + getPendingSizeServlet.doPost(request, response); + getProposalByIdServlet.doPost(request, response); + getRcmServlet.doPost(request, response); + getRewardServlet.doPost(request, response); + getShieldTransactionHashServlet.doPost(request, response); + getSpendingKeyServlet.doPost(request, response); + getTransactionApprovedListServlet.doPost(request, response); + getTransactionByIdServlet.doPost(request, response); + getTransactionCountByBlockNumServlet.doPost(request, response); + getTransactionFromPendingServlet.doPost(request, response); + getTransactionInfoByBlockNumServlet.doPost(request, response); + getTransactionInfoByIdServlet.doPost(request, response); + getTransactionListFromPendingServlet.doPost(request, response); + getTransactionReceiptByIdServlet.doPost(request, response); + getTransactionSignWeightServlet.doPost(request, response); + getTriggerInputForShieldedTRC20ContractServlet.doPost(request, response); + getZenPaymentAddressServlet.doPost(request, response); + isShieldedTRC20ContractNoteSpentServlet.doPost(request, response); + isSpendServlet.doPost(request, response); + listExchangesServlet.doPost(request, response); + listNodesServlet.doPost(request, response); + listProposalsServlet.doPost(request, response); + listWitnessesServlet.doPost(request, response); + marketCancelOrderServlet.doPost(request, response); + marketSellAssetServlet.doPost(request, response); + participateAssetIssueServlet.doPost(request, response); + proposalApproveServlet.doPost(request, response); + proposalCreateServlet.doPost(request, response); + proposalDeleteServlet.doPost(request, response); + scanAndMarkNoteByIvkServlet.doPost(request, response); + scanNoteByIvkServlet.doPost(request, response); + scanNoteByOvkServlet.doPost(request, response); + scanShieldedTRC20NotesByIvkServlet.doPost(request, response); + scanShieldedTRC20NotesByOvkServlet.doPost(request, response); + setAccountIdServlet.doPost(request, response); + totalTransactionServlet.doPost(request, response); + transferAssetServlet.doPost(request, response); + transferServlet.doPost(request, response); + unDelegateResourceServlet.doPost(request, response); + unFreezeAssetServlet.doPost(request, response); + unFreezeBalanceServlet.doPost(request, response); + unFreezeBalanceV2Servlet.doPost(request, response); + updateAccountServlet.doPost(request, response); + updateAssetServlet.doPost(request, response); + updateBrokerageServlet.doPost(request, response); + updateEnergyLimitServlet.doPost(request, response); + updateSettingServlet.doPost(request, response); + updateWitnessServlet.doPost(request, response); + validateAddressServlet.doPost(request, response); + voteWitnessAccountServlet.doPost(request, response); + withdrawBalanceServlet.doPost(request, response); + withdrawExpireUnfreezeServlet.doPost(request, response); + } + +} diff --git a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java index ec9a1f91efa..4ba762d3340 100644 --- a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java @@ -5,6 +5,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpResponse; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -80,9 +81,12 @@ public void testNormalCall() { parameter.addProperty("owner_address", ByteArray.toHexString(ownerAddr)); parameter.addProperty("contract_address", ByteArray.toHexString(contractAddr)); parameter.addProperty("function_selector", "test()"); - invokeToLocal("triggersmartcontract", parameter); - invokeToLocal("triggerconstantcontract", parameter); - invokeToLocal("estimateenergy", parameter); + HttpResponse triggersmartcontract1 = invokeToLocal("triggersmartcontract", parameter); + HttpResponse triggersmartcontract2 = invokeToLocal("triggerconstantcontract", parameter); + HttpResponse triggersmartcontract3 = invokeToLocal("estimateenergy", parameter); + Assert.assertNotNull(triggersmartcontract1); + Assert.assertNotNull(triggersmartcontract2); + Assert.assertNotNull(triggersmartcontract3); } public static HttpResponse invokeToLocal( diff --git a/framework/src/test/java/org/tron/core/services/http/solidity/GetTransactionByIdSolidityServletTest.java b/framework/src/test/java/org/tron/core/services/http/solidity/GetTransactionByIdSolidityServletTest.java index 64d44955536..06bc5f561c5 100644 --- a/framework/src/test/java/org/tron/core/services/http/solidity/GetTransactionByIdSolidityServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/solidity/GetTransactionByIdSolidityServletTest.java @@ -59,7 +59,7 @@ public static void init() { */ @Before - public void setUp() throws InterruptedException { + public void setUp() { getTransactionByIdSolidityServlet = new GetTransactionByIdSolidityServlet(); this.request = mock(HttpServletRequest.class); this.response = mock(HttpServletResponse.class); @@ -96,7 +96,7 @@ public void doPostTest() throws IOException { httpUrlConnection.setDoOutput(true); String postData = "{\"value\": \"309b6fa3d01353e46f57dd8a8f27611f98e392b50d035cef21" + "3f2c55225a8bd2\"}"; - httpUrlConnection.setRequestProperty("Content-Length", "" + postData.length()); + httpUrlConnection.setRequestProperty("Content-Length", String.valueOf(postData.length())); when(httpUrlConnection.getOutputStream()).thenReturn(outContent); OutputStreamWriter out = new OutputStreamWriter(httpUrlConnection.getOutputStream(), @@ -121,14 +121,15 @@ public void doPostTest() throws IOException { while ((line = in.readLine()) != null) { result.append(line).append("\n"); } + Assert.assertNotNull(result); in.close(); writer.flush(); FileInputStream fileInputStream = new FileInputStream("temp.txt"); InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); - StringBuffer sb = new StringBuffer(); - String text = null; + StringBuilder sb = new StringBuilder(); + String text; while ((text = bufferedReader.readLine()) != null) { sb.append(text); } @@ -150,7 +151,7 @@ public void doGetTest() throws IOException { httpUrlConnection.setDoOutput(true); String postData = "{\"value\": \"309b6fa3d01353e46f57dd8a8f27611f98e392b50d035cef21" + "3f2c55225a8bd2\"}"; - httpUrlConnection.setRequestProperty("Content-Length", "" + postData.length()); + httpUrlConnection.setRequestProperty("Content-Length", String.valueOf(postData.length())); when(httpUrlConnection.getOutputStream()).thenReturn(outContent); OutputStreamWriter out = new OutputStreamWriter(httpUrlConnection.getOutputStream(), @@ -175,14 +176,15 @@ public void doGetTest() throws IOException { while ((line = in.readLine()) != null) { result.append(line).append("\n"); } + Assert.assertNotNull(result); in.close(); writer.flush(); FileInputStream fileInputStream = new FileInputStream("temp.txt"); InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); - StringBuffer sb = new StringBuffer(); - String text = null; + StringBuilder sb = new StringBuilder(); + String text; while ((text = bufferedReader.readLine()) != null) { sb.append(text); } diff --git a/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java b/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java index cbc657e02c9..cd7a36ab7a4 100644 --- a/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java @@ -10,10 +10,13 @@ import java.io.File; import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.Optional; import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.testng.collections.Lists; import org.tron.api.GrpcAPI; @@ -85,6 +88,7 @@ import org.tron.protos.contract.ShieldContract.ShieldedTransferContract; import org.tron.protos.contract.ShieldContract.SpendDescription; +@Slf4j public class SendCoinShieldTest extends BaseTest { public static final long totalBalance = 1000_0000_000_000L; @@ -133,11 +137,12 @@ public void init() { AssetIssueContract assetIssueContract = AssetIssueContract.newBuilder() .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(PUBLIC_ADDRESS_ONE))) - .setName(ByteString.copyFrom(ByteArray.fromString(ASSET_NAME))) + .setName(ByteString.copyFrom(Objects.requireNonNull(ByteArray.fromString(ASSET_NAME)))) .setId(Long.toString(tokenId)).setTotalSupply(OWNER_BALANCE).setTrxNum(TRX_NUM).setNum(NUM) .setStartTime(START_TIME).setEndTime(END_TIME).setVoteScore(VOTE_SCORE) - .setDescription(ByteString.copyFrom(ByteArray.fromString(DESCRIPTION))) - .setUrl(ByteString.copyFrom(ByteArray.fromString(URL))).build(); + .setDescription(ByteString.copyFrom( + Objects.requireNonNull(ByteArray.fromString(DESCRIPTION)))) + .setUrl(ByteString.copyFrom(Objects.requireNonNull(ByteArray.fromString(URL)))).build(); AssetIssueCapsule assetIssueCapsule = new AssetIssueCapsule(assetIssueContract); dbManager.getAssetIssueV2Store().put(assetIssueCapsule.createDbV2Key(), assetIssueCapsule); @@ -148,8 +153,11 @@ private void addZeroValueOutputNote(ZenTransactionBuilder builder) throws Zksnar SpendingKey spendingKey = SpendingKey.random(); FullViewingKey fullViewingKey = spendingKey.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()).get(); - builder.addOutput(DEFAULT_OVK, paymentAddress, 0, "just for decode for ovk".getBytes()); + Optional optional = incomingViewingKey.address(DiversifierT.random()); + if (optional.isPresent()) { + PaymentAddress paymentAddress = optional.get(); + builder.addOutput(DEFAULT_OVK, paymentAddress, 0, "just for decode for ovk".getBytes()); + } } @Test @@ -163,7 +171,9 @@ public void testPathMock() throws ZksnarkException { List index = Lists.newArrayList(Arrays.asList(indexArray)); MerklePath path = new MerklePath(authenticationPath, index); byte[] encode = path.encode(); - System.out.print(ByteArray.toHexString(encode)); + String hexString = ByteArray.toHexString(encode); + System.out.print(hexString); + Assert.assertNotNull(hexString); } private PedersenHash String2PedersenHash(String str) { @@ -207,20 +217,21 @@ private IncrementalMerkleVoucherContainer createSimpleMerkleVoucherContainer(byt compressCapsule1.setContent(ByteString.copyFrom(cm)); PedersenHash a = compressCapsule1.getInstance(); tree.append(a); - IncrementalMerkleVoucherContainer voucher = tree.toVoucher(); - return voucher; + return tree.toVoucher(); } - private void librustzcashInitZksnarkParams() throws ZksnarkException { + private void librustzcashInitZksnarkParams() { FullNodeHttpApiService.librustzcashInitZksnarkParams(); } @Test - public void testStringRevert() throws Exception { + public void testStringRevert() { byte[] bytes = ByteArray .fromHexString("6c030e6d7460f91668cc842ceb78cdb54470469e78cd59cf903d3a6e1aa03e7c"); ByteUtil.reverse(bytes); - System.out.println("testStringRevert------" + ByteArray.toHexString(bytes)); + String hexString = ByteArray.toHexString(bytes); + System.out.println("testStringRevert------" + hexString); + Assert.assertNotNull(hexString); } @Test @@ -233,12 +244,9 @@ public void testGenerateSpendProof() throws Exception { DiversifierT diversifierT = new DiversifierT(); byte[] d; - while (true) { + do { d = org.tron.keystore.Wallet.generateRandomBytes(Constant.ZC_DIVERSIFIER_SIZE); - if (JLibrustzcash.librustzcashCheckDiversifier(d)) { - break; - } - } + } while (!JLibrustzcash.librustzcashCheckDiversifier(d)); diversifierT.setData(d); FullViewingKey fullViewingKey = expsk.fullViewingKey(); @@ -246,17 +254,19 @@ public void testGenerateSpendProof() throws Exception { IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); Optional op = incomingViewingKey.address(diversifierT); + if (op.isPresent()) { + Note note = new Note(op.get(), 100); + note.setRcm(ByteArray + .fromHexString("bf4b2042e3e8c4a0b390e407a79a0b46e36eff4f7bb54b2349dbb0046ee21e02")); - Note note = new Note(op.get(), 100); - note.setRcm(ByteArray - .fromHexString("bf4b2042e3e8c4a0b390e407a79a0b46e36eff4f7bb54b2349dbb0046ee21e02")); - - IncrementalMerkleVoucherContainer voucher = createComplexMerkleVoucherContainer(note.cm()); + IncrementalMerkleVoucherContainer voucher = createComplexMerkleVoucherContainer(note.cm()); - byte[] anchor = voucher.root().getContent().toByteArray(); - SpendDescriptionInfo spend = new SpendDescriptionInfo(expsk, note, anchor, voucher); - long ctx = JLibrustzcash.librustzcashSaplingProvingCtxInit(); - SpendDescriptionCapsule sdesc = builder.generateSpendProof(spend, ctx); + byte[] anchor = voucher.root().getContent().toByteArray(); + SpendDescriptionInfo spend = new SpendDescriptionInfo(expsk, note, anchor, voucher); + long ctx = JLibrustzcash.librustzcashSaplingProvingCtxInit(); + SpendDescriptionCapsule sdesc = builder.generateSpendProof(spend, ctx); + Assert.assertNotNull(sdesc); + } } @Test @@ -267,11 +277,15 @@ public void generateOutputProof() throws ZksnarkException { FullViewingKey fullViewingKey = spendingKey.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(new DiversifierT()).get(); - long ctx = JLibrustzcash.librustzcashSaplingProvingCtxInit(); - builder.addOutput(fullViewingKey.getOvk(), paymentAddress, 4000, new byte[512]); - builder.generateOutputProof(builder.getReceives().get(0), ctx); - JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); + Optional optional = incomingViewingKey.address(new DiversifierT()); + if (optional.isPresent()) { + PaymentAddress paymentAddress = optional.get(); + Assert.assertNotNull(paymentAddress); + long ctx = JLibrustzcash.librustzcashSaplingProvingCtxInit(); + builder.addOutput(fullViewingKey.getOvk(), paymentAddress, 4000, new byte[512]); + builder.generateOutputProof(builder.getReceives().get(0), ctx); + JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); + } } @Test @@ -281,24 +295,27 @@ public void verifyOutputProof() throws ZksnarkException { SpendingKey spendingKey = SpendingKey.random(); FullViewingKey fullViewingKey = spendingKey.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - - PaymentAddress paymentAddress = incomingViewingKey.address(new DiversifierT()).get(); - long ctx = JLibrustzcash.librustzcashSaplingProvingCtxInit(); - builder.addOutput(fullViewingKey.getOvk(), paymentAddress, 4000, new byte[512]); - ReceiveDescriptionCapsule capsule = builder - .generateOutputProof(builder.getReceives().get(0), ctx); - JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); - ReceiveDescription receiveDescription = capsule.getInstance(); - ctx = JLibrustzcash.librustzcashSaplingVerificationCtxInit(); - if (!JLibrustzcash.librustzcashSaplingCheckOutput( - new CheckOutputParams(ctx, receiveDescription.getValueCommitment().toByteArray(), - receiveDescription.getNoteCommitment().toByteArray(), - receiveDescription.getEpk().toByteArray(), - receiveDescription.getZkproof().toByteArray()))) { + Optional optional = incomingViewingKey.address(new DiversifierT()); + if (optional.isPresent()) { + PaymentAddress paymentAddress = optional.get(); + Assert.assertNotNull(paymentAddress); + long ctx = JLibrustzcash.librustzcashSaplingProvingCtxInit(); + builder.addOutput(fullViewingKey.getOvk(), paymentAddress, 4000, new byte[512]); + ReceiveDescriptionCapsule capsule = builder + .generateOutputProof(builder.getReceives().get(0), ctx); + JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); + ReceiveDescription receiveDescription = capsule.getInstance(); + ctx = JLibrustzcash.librustzcashSaplingVerificationCtxInit(); + if (!JLibrustzcash.librustzcashSaplingCheckOutput( + new CheckOutputParams(ctx, receiveDescription.getValueCommitment().toByteArray(), + receiveDescription.getNoteCommitment().toByteArray(), + receiveDescription.getEpk().toByteArray(), + receiveDescription.getZkproof().toByteArray()))) { + JLibrustzcash.librustzcashSaplingVerificationCtxFree(ctx); + throw new RuntimeException("librustzcashSaplingCheckOutput error"); + } JLibrustzcash.librustzcashSaplingVerificationCtxFree(ctx); - throw new RuntimeException("librustzcashSaplingCheckOutput error"); } - JLibrustzcash.librustzcashSaplingVerificationCtxFree(ctx); } @@ -312,49 +329,54 @@ public void testDecryptReceiveWithIvk() throws ZksnarkException { FullViewingKey fullViewingKey = spendingKey.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(new DiversifierT()).get(); + Optional optional = incomingViewingKey.address(new DiversifierT()); + if (optional.isPresent()) { + PaymentAddress paymentAddress = optional.get(); - long ctx = JLibrustzcash.librustzcashSaplingProvingCtxInit(); - byte[] memo = org.tron.keystore.Wallet.generateRandomBytes(512); - builder.addOutput(fullViewingKey.getOvk(), paymentAddress, 4000, memo); + long ctx = JLibrustzcash.librustzcashSaplingProvingCtxInit(); + byte[] memo = org.tron.keystore.Wallet.generateRandomBytes(512); + builder.addOutput(fullViewingKey.getOvk(), paymentAddress, 4000, memo); - ZenTransactionBuilder.ReceiveDescriptionInfo output = builder.getReceives().get(0); - ReceiveDescriptionCapsule receiveDescriptionCapsule = builder.generateOutputProof(output, ctx); - ReceiveDescription receiveDescription = receiveDescriptionCapsule.getInstance(); + ZenTransactionBuilder.ReceiveDescriptionInfo output = builder.getReceives().get(0); + ReceiveDescriptionCapsule receiveDescriptionCapsule = builder + .generateOutputProof(output, ctx); + ReceiveDescription receiveDescription = receiveDescriptionCapsule.getInstance(); - Optional ret1 = Note.decrypt(receiveDescription.getCEnc().toByteArray(),//ciphertext - fullViewingKey.inViewingKey().getValue(), receiveDescription.getEpk().toByteArray(),//epk - receiveDescription.getNoteCommitment().toByteArray() //cm - ); + Optional ret1 = Note.decrypt(receiveDescription.getCEnc().toByteArray(),//ciphertext + fullViewingKey.inViewingKey().getValue(), receiveDescription.getEpk().toByteArray(),//epk + receiveDescription.getNoteCommitment().toByteArray() //cm + ); - Assert.assertTrue(ret1.isPresent()); + Assert.assertTrue(ret1.isPresent()); - Note noteText = ret1.get(); - byte[] pkD = new byte[32]; - if (!JLibrustzcash.librustzcashIvkToPkd( - new IvkToPkdParams(incomingViewingKey.getValue(), noteText.getD().getData(), pkD))) { - JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); - return; - } + Note noteText = ret1.get(); + byte[] pkD = new byte[32]; + if (!JLibrustzcash.librustzcashIvkToPkd( + new IvkToPkdParams(incomingViewingKey.getValue(), noteText.getD().getData(), pkD))) { + JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); + return; + } - Assert.assertArrayEquals(paymentAddress.getPkD(), pkD); - Assert.assertEquals(noteText.getValue(), 4000); - Assert.assertArrayEquals(noteText.getMemo(), memo); + Assert.assertArrayEquals(paymentAddress.getPkD(), pkD); + Assert.assertEquals(4000, noteText.getValue()); + Assert.assertArrayEquals(noteText.getMemo(), memo); - String paymentAddressStr = KeyIo.encodePaymentAddress(new PaymentAddress(noteText.getD(), pkD)); + String paymentAddressStr = KeyIo.encodePaymentAddress( + new PaymentAddress(noteText.getD(), pkD)); - GrpcAPI.Note grpcAPINote = GrpcAPI.Note.newBuilder().setPaymentAddress(paymentAddressStr) - .setValue(noteText.getValue()).setRcm(ByteString.copyFrom(noteText.getRcm())) - .setMemo(ByteString.copyFrom(noteText.getMemo())).build(); + GrpcAPI.Note grpcAPINote = GrpcAPI.Note.newBuilder().setPaymentAddress(paymentAddressStr) + .setValue(noteText.getValue()).setRcm(ByteString.copyFrom(noteText.getRcm())) + .setMemo(ByteString.copyFrom(noteText.getMemo())).build(); - JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); + JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); + } } public String byte2intstring(byte[] input) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < input.length; i++) { - sb.append(String.valueOf((int) input[i]) + ", "); + sb.append(String.valueOf(input[i])).append(", "); if (i % 16 == 15) { sb.append("\n"); } @@ -391,48 +413,50 @@ public void testDecryptReceiveWithOvk() throws Exception { byte[] cmuOpt = note.cm(); Assert.assertNotNull(cmuOpt); - NotePlaintextEncryptionResult enc = note.encrypt(pkd).get(); - NoteEncryption encryptor = enc.getNoteEncryption(); - OutgoingPlaintext outgoingPlaintext = new OutgoingPlaintext(note.getPkD(), encryptor.getEsk()); - - // encrypt with ovk - Encryption.OutCiphertext outCiphertext = outgoingPlaintext - .encrypt(fullViewingKey.getOvk(), receiveDescription.getValueCommitment().toByteArray(), - receiveDescription.getNoteCommitment().toByteArray(), encryptor); - - // get pkD, esk from decryption of c_out with ovk - Optional ret2 = OutgoingPlaintext - .decrypt(outCiphertext, fullViewingKey.getOvk(), - receiveDescription.getValueCommitment().toByteArray(), - receiveDescription.getNoteCommitment().toByteArray(), encryptor.getEpk()); - - if (ret2.isPresent()) { - OutgoingPlaintext decryptedOutgoingPlaintext = ret2.get(); - Assert.assertArrayEquals(decryptedOutgoingPlaintext.getPkD(), outgoingPlaintext.getPkD()); - Assert.assertArrayEquals(decryptedOutgoingPlaintext.getEsk(), outgoingPlaintext.getEsk()); - - //decrypt c_enc with pkd、esk - Encryption.EncCiphertext ciphertext = new Encryption.EncCiphertext(); - ciphertext.setData(enc.getEncCiphertext()); - Optional foo = Note - .decrypt(ciphertext, encryptor.getEpk(), decryptedOutgoingPlaintext.getEsk(), - decryptedOutgoingPlaintext.getPkD(), cmuOpt); - - if (foo.isPresent()) { - Note bar = foo.get(); - //verify result - Assert.assertEquals(4000, bar.getValue()); - Assert.assertArrayEquals(memo, bar.getMemo()); + Optional optional = note.encrypt(pkd); + if (optional.isPresent()) { + NotePlaintextEncryptionResult enc = optional.get(); + NoteEncryption encryptor = enc.getNoteEncryption(); + OutgoingPlaintext outgoingPlaintext = new OutgoingPlaintext( + note.getPkD(), encryptor.getEsk()); + // encrypt with ovk + Encryption.OutCiphertext outCiphertext = outgoingPlaintext + .encrypt(fullViewingKey.getOvk(), receiveDescription.getValueCommitment().toByteArray(), + receiveDescription.getNoteCommitment().toByteArray(), encryptor); + + // get pkD, esk from decryption of c_out with ovk + Optional ret2 = OutgoingPlaintext + .decrypt(outCiphertext, fullViewingKey.getOvk(), + receiveDescription.getValueCommitment().toByteArray(), + receiveDescription.getNoteCommitment().toByteArray(), encryptor.getEpk()); + + if (ret2.isPresent()) { + OutgoingPlaintext decryptedOutgoingPlaintext = ret2.get(); + Assert.assertArrayEquals(decryptedOutgoingPlaintext.getPkD(), outgoingPlaintext.getPkD()); + Assert.assertArrayEquals(decryptedOutgoingPlaintext.getEsk(), outgoingPlaintext.getEsk()); + + //decrypt c_enc with pkd、esk + Encryption.EncCiphertext ciphertext = new Encryption.EncCiphertext(); + ciphertext.setData(enc.getEncCiphertext()); + Optional foo = Note + .decrypt(ciphertext, encryptor.getEpk(), decryptedOutgoingPlaintext.getEsk(), + decryptedOutgoingPlaintext.getPkD(), cmuOpt); + + if (foo.isPresent()) { + Note bar = foo.get(); + //verify result + Assert.assertEquals(4000, bar.getValue()); + Assert.assertArrayEquals(memo, bar.getMemo()); + } else { + JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); + Assert.fail(); + } } else { JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); - Assert.assertFalse(true); + Assert.fail(); } - } else { JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); - Assert.assertFalse(true); } - - JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); } @Test @@ -466,53 +490,55 @@ public void pushShieldedTransactionAndDecryptWithIvk() SpendingKey spendingKey = SpendingKey.random(); FullViewingKey fullViewingKey = spendingKey.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(new DiversifierT()).get(); - byte[] memo = org.tron.keystore.Wallet.generateRandomBytes(512); - builder - .addOutput(senderOvk, paymentAddress, 1000 * 1000000L - wallet.getShieldedTransactionFee(), - memo); - - TransactionCapsule transactionCap = builder.build(); + Optional optional = incomingViewingKey.address(new DiversifierT()); + if (optional.isPresent()) { + PaymentAddress paymentAddress = optional.get(); + byte[] memo = org.tron.keystore.Wallet.generateRandomBytes(512); + builder.addOutput(senderOvk, paymentAddress, + 1000 * 1000000L - wallet.getShieldedTransactionFee(), memo); - boolean ok = dbManager.pushTransaction(transactionCap); - Assert.assertTrue(ok); + TransactionCapsule transactionCap = builder.build(); - // add here - byte[] ivk = incomingViewingKey.getValue(); - Protocol.Transaction t = transactionCap.getInstance(); + boolean ok = dbManager.pushTransaction(transactionCap); + Assert.assertTrue(ok); - for (org.tron.protos.Protocol.Transaction.Contract c : t.getRawData().getContractList()) { - if (c.getType() != ContractType.ShieldedTransferContract) { - continue; - } - ShieldedTransferContract stContract = c.getParameter() - .unpack(ShieldedTransferContract.class); - ReceiveDescription receiveDescription = stContract.getReceiveDescription(0); + // add here + byte[] ivk = incomingViewingKey.getValue(); + Protocol.Transaction t = transactionCap.getInstance(); - Optional ret1 = Note.decrypt(receiveDescription.getCEnc().toByteArray(),//ciphertext - ivk, receiveDescription.getEpk().toByteArray(),//epk - receiveDescription.getNoteCommitment().toByteArray() //cm - ); - - if (ret1.isPresent()) { - Note noteText = ret1.get(); - byte[] pkD = new byte[32]; - if (!JLibrustzcash.librustzcashIvkToPkd( - new IvkToPkdParams(incomingViewingKey.getValue(), noteText.getD().getData(), pkD))) { - JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); - return; + for (org.tron.protos.Protocol.Transaction.Contract c : t.getRawData().getContractList()) { + if (c.getType() != ContractType.ShieldedTransferContract) { + continue; + } + ShieldedTransferContract stContract = c.getParameter() + .unpack(ShieldedTransferContract.class); + ReceiveDescription receiveDescription = stContract.getReceiveDescription(0); + + Optional ret1 = Note.decrypt(receiveDescription.getCEnc().toByteArray(),//ciphertext + ivk, receiveDescription.getEpk().toByteArray(),//epk + receiveDescription.getNoteCommitment().toByteArray() //cm + ); + + if (ret1.isPresent()) { + Note noteText = ret1.get(); + byte[] pkD = new byte[32]; + if (!JLibrustzcash.librustzcashIvkToPkd( + new IvkToPkdParams(incomingViewingKey.getValue(), noteText.getD().getData(), pkD))) { + JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); + return; + } + Assert.assertArrayEquals(paymentAddress.getPkD(), pkD); + Assert.assertEquals(1000 * 1000000L - wallet.getShieldedTransactionFee(), + noteText.getValue()); + Assert.assertArrayEquals(memo, noteText.getMemo()); + } else { + Assert.fail(); } - Assert.assertArrayEquals(paymentAddress.getPkD(), pkD); - Assert.assertEquals(1000 * 1000000L - wallet.getShieldedTransactionFee(), - noteText.getValue()); - Assert.assertArrayEquals(memo, noteText.getMemo()); - } else { - Assert.assertFalse(true); } + // end here + JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); + Assert.assertTrue(ok); } - // end here - JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); - Assert.assertTrue(ok); } @Test @@ -553,59 +579,61 @@ public void pushShieldedTransactionAndDecryptWithOvk() SpendingKey spendingKey = SpendingKey.random(); FullViewingKey fullViewingKey = spendingKey.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(new DiversifierT()).get(); - byte[] memo = org.tron.keystore.Wallet.generateRandomBytes(512); - builder - .addOutput(senderOvk, paymentAddress, 1000 * 1000000L - wallet.getShieldedTransactionFee(), - memo); - - TransactionCapsule transactionCap = builder.build(); - boolean ok = dbManager.pushTransaction(transactionCap); - Assert.assertTrue(ok); - - // add here - Protocol.Transaction t = transactionCap.getInstance(); - for (org.tron.protos.Protocol.Transaction.Contract c : t.getRawData().getContractList()) { - if (c.getType() != Protocol.Transaction.Contract.ContractType.ShieldedTransferContract) { - continue; - } - ShieldedTransferContract stContract = c.getParameter() - .unpack(ShieldedTransferContract.class); - ReceiveDescription receiveDescription = stContract.getReceiveDescription(0); - - //first try to decrypt cOut with ovk, get pkd、esk - Encryption.OutCiphertext cOut = new Encryption.OutCiphertext(); - cOut.setData(receiveDescription.getCOut().toByteArray()); - Optional notePlaintext = OutgoingPlaintext.decrypt(cOut,//ciphertext - senderOvk, receiveDescription.getValueCommitment().toByteArray(), //cv - receiveDescription.getNoteCommitment().toByteArray(), //cmu - receiveDescription.getEpk().toByteArray() //epk - ); + Optional optional = incomingViewingKey.address(new DiversifierT()); + if (optional.isPresent()) { + PaymentAddress paymentAddress = optional.get(); + byte[] memo = org.tron.keystore.Wallet.generateRandomBytes(512); + builder.addOutput(senderOvk, paymentAddress, + 1000 * 1000000L - wallet.getShieldedTransactionFee(), memo); - //then decrypt c_enc with pkd、esk, get decoded note == ciphertext - if (notePlaintext.isPresent()) { - OutgoingPlaintext decryptedOutgoingPlaintext = notePlaintext.get(); - - Encryption.EncCiphertext ciphertext = new Encryption.EncCiphertext(); - ciphertext.setData(receiveDescription.getCEnc().toByteArray()); - Optional foo = Note.decrypt(ciphertext, receiveDescription.getEpk().toByteArray(), - decryptedOutgoingPlaintext.getEsk(), decryptedOutgoingPlaintext.getPkD(), - receiveDescription.getNoteCommitment().toByteArray()); - - if (foo.isPresent()) { - Note bar = foo.get(); - //verify result - Assert.assertEquals(1000 * 1000000L - wallet.getShieldedTransactionFee(), bar.getValue()); - Assert.assertArrayEquals(memo, bar.getMemo()); - } else { - Assert.assertFalse(true); + TransactionCapsule transactionCap = builder.build(); + boolean ok = dbManager.pushTransaction(transactionCap); + Assert.assertTrue(ok); + + // add here + Protocol.Transaction t = transactionCap.getInstance(); + for (org.tron.protos.Protocol.Transaction.Contract c : t.getRawData().getContractList()) { + if (c.getType() != Protocol.Transaction.Contract.ContractType.ShieldedTransferContract) { + continue; + } + ShieldedTransferContract stContract = c.getParameter() + .unpack(ShieldedTransferContract.class); + ReceiveDescription receiveDescription = stContract.getReceiveDescription(0); + + //first try to decrypt cOut with ovk, get pkd、esk + Encryption.OutCiphertext cOut = new Encryption.OutCiphertext(); + cOut.setData(receiveDescription.getCOut().toByteArray()); + Optional notePlaintext = OutgoingPlaintext.decrypt(cOut,//ciphertext + senderOvk, receiveDescription.getValueCommitment().toByteArray(), //cv + receiveDescription.getNoteCommitment().toByteArray(), //cmu + receiveDescription.getEpk().toByteArray() //epk + ); + + //then decrypt c_enc with pkd、esk, get decoded note == ciphertext + if (notePlaintext.isPresent()) { + OutgoingPlaintext decryptedOutgoingPlaintext = notePlaintext.get(); + + Encryption.EncCiphertext ciphertext = new Encryption.EncCiphertext(); + ciphertext.setData(receiveDescription.getCEnc().toByteArray()); + Optional foo = Note.decrypt(ciphertext, receiveDescription.getEpk().toByteArray(), + decryptedOutgoingPlaintext.getEsk(), decryptedOutgoingPlaintext.getPkD(), + receiveDescription.getNoteCommitment().toByteArray()); + + if (foo.isPresent()) { + Note bar = foo.get(); + //verify result + Assert.assertEquals(1000 * 1000000L - wallet.getShieldedTransactionFee(), + bar.getValue()); + Assert.assertArrayEquals(memo, bar.getMemo()); + } else { + Assert.fail(); + } } } + // end here + JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); + Assert.assertTrue(ok); } - // end here - - JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); - Assert.assertTrue(ok); } private byte[] getHash() { @@ -613,6 +641,8 @@ private byte[] getHash() { .getInstance().isECKeyCryptoEngine(), "this is a test".getBytes()).getBytes(); } + @Ignore + @Test public void checkZksnark() throws BadItemException, ZksnarkException { librustzcashInitZksnarkParams(); long ctx = JLibrustzcash.librustzcashSaplingProvingCtxInit(); @@ -635,14 +665,17 @@ public void checkZksnark() throws BadItemException, ZksnarkException { SpendingKey spendingKey = SpendingKey.random(); FullViewingKey fullViewingKey = spendingKey.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()).get(); - builder.addOutput(fullViewingKey.getOvk(), paymentAddress, 4000 * 1000000L, new byte[512]); - TransactionCapsule transactionCap = builder.build(); - JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); - boolean ret = ZksnarkClient.getInstance().checkZksnarkProof(transactionCap.getInstance(), - getShieldTransactionHashIgnoreTypeException(transactionCap.getInstance()), - 10 * 1000000); - Assert.assertTrue(ret); + Optional optional = incomingViewingKey.address(DiversifierT.random()); + if (optional.isPresent()) { + PaymentAddress paymentAddress = optional.get(); + builder.addOutput(fullViewingKey.getOvk(), paymentAddress, 4000 * 1000000L, new byte[512]); + TransactionCapsule transactionCap = builder.build(); + JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); + boolean ret = ZksnarkClient.getInstance().checkZksnarkProof(transactionCap.getInstance(), + getShieldTransactionHashIgnoreTypeException(transactionCap.getInstance()), + 10 * 1000000); + Assert.assertTrue(ret); + } } @Test @@ -678,7 +711,7 @@ public void testVerifySpendProof() throws BadItemException, ZksnarkException { spendDescriptionCapsule.getRk().toByteArray(), spendDescriptionCapsule.getZkproof().toByteArray(), result, getHash())); JLibrustzcash.librustzcashSaplingVerificationCtxFree(verifyContext); - Assert.assertEquals(ok, true); + Assert.assertTrue(ok); } @Test @@ -700,16 +733,19 @@ public void saplingBindingSig() throws BadItemException, ZksnarkException { SpendingKey spendingKey = SpendingKey.random(); FullViewingKey fullViewingKey = spendingKey.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(new DiversifierT()).get(); - builder.addOutput(fullViewingKey.getOvk(), paymentAddress, 4000 * 1000000L, new byte[512]); - builder.generateOutputProof(builder.getReceives().get(0), ctx); - - // test create binding sig - byte[] bindingSig = new byte[64]; - boolean ret = JLibrustzcash.librustzcashSaplingBindingSig( - new BindingSigParams(ctx, builder.getValueBalance(), getHash(), bindingSig)); - JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); - Assert.assertTrue(ret); + Optional optional = incomingViewingKey.address(new DiversifierT()); + if (optional.isPresent()) { + PaymentAddress paymentAddress = optional.get(); + builder.addOutput(fullViewingKey.getOvk(), paymentAddress, 4000 * 1000000L, new byte[512]); + builder.generateOutputProof(builder.getReceives().get(0), ctx); + + // test create binding sig + byte[] bindingSig = new byte[64]; + boolean ret = JLibrustzcash.librustzcashSaplingBindingSig( + new BindingSigParams(ctx, builder.getValueBalance(), getHash(), bindingSig)); + JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); + Assert.assertTrue(ret); + } } @Test @@ -739,13 +775,16 @@ public void pushShieldedTransaction() SpendingKey spendingKey = SpendingKey.random(); FullViewingKey fullViewingKey = spendingKey.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(DiversifierT.random()).get(); - builder.addOutput(fullViewingKey.getOvk(), paymentAddress, - 4010 * 1000000L - wallet.getShieldedTransactionFee(), new byte[512]); - TransactionCapsule transactionCap = builder.build(); - boolean ok = dbManager.pushTransaction(transactionCap); - JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); - Assert.assertTrue(ok); + Optional optional = incomingViewingKey.address(DiversifierT.random()); + if (optional.isPresent()) { + PaymentAddress paymentAddress = optional.get(); + builder.addOutput(fullViewingKey.getOvk(), paymentAddress, + 4010 * 1000000L - wallet.getShieldedTransactionFee(), new byte[512]); + TransactionCapsule transactionCap = builder.build(); + boolean ok = dbManager.pushTransaction(transactionCap); + JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); + Assert.assertTrue(ok); + } } @Test @@ -768,46 +807,49 @@ public void finalCheck() throws BadItemException, ZksnarkException { SpendingKey spendingKey = SpendingKey.random(); FullViewingKey fullViewingKey = spendingKey.fullViewingKey(); IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(new DiversifierT()).get(); - builder.addOutput(fullViewingKey.getOvk(), paymentAddress, 4000 * 1000000L, new byte[512]); - ReceiveDescriptionCapsule receiveDescriptionCapsule = builder - .generateOutputProof(builder.getReceives().get(0), ctx); - - //create binding sig - byte[] bindingSig = new byte[64]; - boolean ret = JLibrustzcash.librustzcashSaplingBindingSig( - new BindingSigParams(ctx, builder.getValueBalance(), getHash(), bindingSig)); - JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); - Assert.assertTrue(ret); - // check spend - ctx = JLibrustzcash.librustzcashSaplingVerificationCtxInit(); - byte[] result = new byte[64]; - JLibrustzcash.librustzcashSaplingSpendSig( - new SpendSigParams(expsk.getAsk(), builder.getSpends().get(0).getAlpha(), getHash(), - result)); - - SpendDescription spendDescription = spendDescriptionCapsule.getInstance(); - boolean ok; - ok = JLibrustzcash.librustzcashSaplingCheckSpend( - new CheckSpendParams(ctx, spendDescription.getValueCommitment().toByteArray(), - spendDescription.getAnchor().toByteArray(), - spendDescription.getNullifier().toByteArray(), spendDescription.getRk().toByteArray(), - spendDescription.getZkproof().toByteArray(), result, getHash())); - Assert.assertTrue(ok); - - // check output - ReceiveDescription receiveDescription = receiveDescriptionCapsule.getInstance(); - ok = JLibrustzcash.librustzcashSaplingCheckOutput( - new CheckOutputParams(ctx, receiveDescription.getValueCommitment().toByteArray(), - receiveDescription.getNoteCommitment().toByteArray(), - receiveDescription.getEpk().toByteArray(), - receiveDescription.getZkproof().toByteArray())); - Assert.assertTrue(ok); - // final check - ok = JLibrustzcash.librustzcashSaplingFinalCheck( - new FinalCheckParams(ctx, builder.getValueBalance(), bindingSig, getHash())); - Assert.assertTrue(ok); - JLibrustzcash.librustzcashSaplingVerificationCtxFree(ctx); + Optional optional = incomingViewingKey.address(new DiversifierT()); + if (optional.isPresent()) { + PaymentAddress paymentAddress = optional.get(); + builder.addOutput(fullViewingKey.getOvk(), paymentAddress, 4000 * 1000000L, new byte[512]); + ReceiveDescriptionCapsule receiveDescriptionCapsule = builder + .generateOutputProof(builder.getReceives().get(0), ctx); + + //create binding sig + byte[] bindingSig = new byte[64]; + boolean ret = JLibrustzcash.librustzcashSaplingBindingSig( + new BindingSigParams(ctx, builder.getValueBalance(), getHash(), bindingSig)); + JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); + Assert.assertTrue(ret); + // check spend + ctx = JLibrustzcash.librustzcashSaplingVerificationCtxInit(); + byte[] result = new byte[64]; + JLibrustzcash.librustzcashSaplingSpendSig( + new SpendSigParams(expsk.getAsk(), builder.getSpends().get(0).getAlpha(), getHash(), + result)); + + SpendDescription spendDescription = spendDescriptionCapsule.getInstance(); + boolean ok; + ok = JLibrustzcash.librustzcashSaplingCheckSpend( + new CheckSpendParams(ctx, spendDescription.getValueCommitment().toByteArray(), + spendDescription.getAnchor().toByteArray(), + spendDescription.getNullifier().toByteArray(), spendDescription.getRk().toByteArray(), + spendDescription.getZkproof().toByteArray(), result, getHash())); + Assert.assertTrue(ok); + + // check output + ReceiveDescription receiveDescription = receiveDescriptionCapsule.getInstance(); + ok = JLibrustzcash.librustzcashSaplingCheckOutput( + new CheckOutputParams(ctx, receiveDescription.getValueCommitment().toByteArray(), + receiveDescription.getNoteCommitment().toByteArray(), + receiveDescription.getEpk().toByteArray(), + receiveDescription.getZkproof().toByteArray())); + Assert.assertTrue(ok); + // final check + ok = JLibrustzcash.librustzcashSaplingFinalCheck( + new FinalCheckParams(ctx, builder.getValueBalance(), bindingSig, getHash())); + Assert.assertTrue(ok); + JLibrustzcash.librustzcashSaplingVerificationCtxFree(ctx); + } } @Test @@ -830,11 +872,11 @@ public void testEmptyRoots() throws Exception { } private JSONArray readFile(String fileName) throws Exception { - String file1 = SendCoinShieldTest.class.getClassLoader() - .getResource("json" + File.separator + fileName).getFile(); + String file1 = Objects.requireNonNull(SendCoinShieldTest.class.getClassLoader() + .getResource("json" + File.separator + fileName)).getFile(); List readLines = Files.readLines(new File(file1), Charsets.UTF_8); - JSONArray array = JSONArray.parseArray(readLines.stream().reduce((s, s2) -> s + s2).get()); - return array; + Optional optional = readLines.stream().reduce((s, s2) -> s + s2); + return optional.map(JSONArray::parseArray).orElse(null); } @@ -847,9 +889,9 @@ public void testComputeCm() throws Exception { 9990000000L, ByteArray .fromHexString("08e3a2ff1101b628147125b786c757b483f1cf7c309f8a647055bfb1ca819c02"), result))) { - System.out.println(" error"); + Assert.fail(); } else { - System.out.println(" ok"); + Assert.assertTrue(true); } } @@ -880,12 +922,9 @@ public void getSpendingKey() throws Exception { DiversifierT diversifierT = new DiversifierT(); byte[] d; - while (true) { + do { d = org.tron.keystore.Wallet.generateRandomBytes(Constant.ZC_DIVERSIFIER_SIZE); - if (JLibrustzcash.librustzcashCheckDiversifier(d)) { - break; - } - } + } while (!JLibrustzcash.librustzcashCheckDiversifier(d)); diversifierT.setData(d); System.out.println("d is: " + ByteArray.toHexString(d)); @@ -1319,7 +1358,7 @@ public void TestCreateMultipleTxAtTheSameTime() throws Exception { executeTx(transactionCapsule); System.out.println("Success execute tx,num:" + transactionCapsule.getBlockNum()); } catch (Exception ex) { - System.out.println(ex); + logger.error("error", ex); } }); } @@ -1514,7 +1553,7 @@ public void TestGeneratesProofWithWrongRcm() throws Exception { builder.addSpend(expsk, note, anchor, voucher); SpendDescriptionCapsule spendDescriptionCapsule = builder .generateSpendProof(builder.getSpends().get(0), ctx); - + Assert.assertNotNull(spendDescriptionCapsule); } @Test @@ -1624,9 +1663,7 @@ private TransactionCapsule generateDefaultBuilder(ZenTransactionBuilder builder) String TO_ADDRESS = generateDefaultToAccount(); builder.setTransparentOutput(ByteArray.fromHexString(TO_ADDRESS), 1000 * 1000000L - wallet.getShieldedTransactionFee()); - - TransactionCapsule transactionCap = builder.build(); - return transactionCap; + return builder.build(); } @Test @@ -1753,7 +1790,6 @@ public SpendDescriptionCapsule generateSpendProof(SpendDescriptionInfo spend, lo throw e; } System.out.println("Done"); - return; } } } @@ -1790,7 +1826,6 @@ public SpendDescriptionCapsule generateSpendProof(SpendDescriptionInfo spend, lo throw e; } System.out.println("Done"); - return; } } } diff --git a/framework/src/test/java/org/tron/program/SolidityNodeTest.java b/framework/src/test/java/org/tron/program/SolidityNodeTest.java index 7cb3ac9823f..99d6a75adbe 100755 --- a/framework/src/test/java/org/tron/program/SolidityNodeTest.java +++ b/framework/src/test/java/org/tron/program/SolidityNodeTest.java @@ -75,11 +75,11 @@ public void testSolidityArgs() { @Test public void testSolidityGrpcCall() { DatabaseGrpcClient databaseGrpcClient = null; - String addr = Args.getInstance().getTrustNodeAddr(); + String address = Args.getInstance().getTrustNodeAddr(); try { - databaseGrpcClient = new DatabaseGrpcClient(addr); + databaseGrpcClient = new DatabaseGrpcClient(address); } catch (Exception e) { - logger.error("Failed to create database grpc client {}", addr); + logger.error("Failed to create database grpc client {}", address); } Assert.assertNotNull(databaseGrpcClient); @@ -89,6 +89,7 @@ public void testSolidityGrpcCall() { Block genesisBlock = databaseGrpcClient.getBlock(0); Assert.assertNotNull(genesisBlock); Assert.assertFalse(genesisBlock.getTransactionsList().isEmpty()); + databaseGrpcClient.shutdown(); } } From c6337adb68c5b7e8eb6353920909a21d4e9989ae Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 21 Apr 2023 14:57:15 +0800 Subject: [PATCH 0753/1197] func(vm): support ShangHai upgrade --- .../org/tron/core/utils/ProposalUtil.java | 14 +++++++++++- .../src/main/java/org/tron/core/vm/Op.java | 1 + .../org/tron/core/vm/OperationActions.java | 5 +++++ .../org/tron/core/vm/OperationRegistry.java | 20 ++++++++++++++++- .../org/tron/core/vm/config/ConfigLoader.java | 1 + .../org/tron/core/vm/config/VMConfig.java | 10 +++++++++ .../core/store/DynamicPropertiesStore.java | 22 +++++++++++++++++++ .../common/parameter/CommonParameter.java | 5 ++++- .../src/main/java/org/tron/core/Constant.java | 2 ++ .../java/org/tron/core/config/Parameter.java | 5 +++-- .../src/main/java/org/tron/core/Wallet.java | 5 +++++ .../java/org/tron/core/config/args/Args.java | 5 +++++ .../tron/core/consensus/ProposalService.java | 4 ++++ 13 files changed, 94 insertions(+), 5 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 5597f985291..9ab68cc1925 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -681,6 +681,17 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case ALLOW_TVM_SHANGHAI: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7_2)) { + throw new ContractValidateException( + "Bad chain parameter id [ALLOW_TVM_SHANGHAI]"); + } + if (value != 1) { + throw new ContractValidateException( + "This value[ALLOW_TVM_SHANGHAI] is only allowed to be 1"); + } + break; + } default: break; } @@ -753,7 +764,8 @@ public enum ProposalType { // current value, value range ALLOW_DYNAMIC_ENERGY(72), // 0, 1 DYNAMIC_ENERGY_THRESHOLD(73), // 0, [0, LONG] DYNAMIC_ENERGY_INCREASE_FACTOR(74), // 0, [0, 10_000] - DYNAMIC_ENERGY_MAX_FACTOR(75); // 0, [0, 100_000] + DYNAMIC_ENERGY_MAX_FACTOR(75), // 0, [0, 100_000] + ALLOW_TVM_SHANGHAI(76); // 0, 1 private long code; diff --git a/actuator/src/main/java/org/tron/core/vm/Op.java b/actuator/src/main/java/org/tron/core/vm/Op.java index 557619f554b..f6987c12942 100644 --- a/actuator/src/main/java/org/tron/core/vm/Op.java +++ b/actuator/src/main/java/org/tron/core/vm/Op.java @@ -148,6 +148,7 @@ public class Op { /* Push Operations */ // Place item on stack + public static final int PUSH0 = 0x5f; public static final int PUSH1 = 0x60; public static final int PUSH2 = 0x61; public static final int PUSH3 = 0x62; diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index 9895b24910f..5ed6ead075f 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -643,6 +643,11 @@ public static void jumpDestAction(Program program) { program.step(); } + public static void push0Action(Program program) { + program.stackPush(DataWord.ZERO()); + program.step(); + } + public static void pushAction(Program program) { int n = program.getCurrentOpIntValue() - Op.PUSH1 + 1; program.step(); diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index 0df5a6b126f..8aab51a1f31 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -11,6 +11,7 @@ public enum Version { TRON_V1_0, TRON_V1_1, TRON_V1_2, + TRON_V1_3, // add more // TRON_V2, // ETH @@ -22,6 +23,7 @@ public enum Version { tableMap.put(Version.TRON_V1_0, newTronV10OperationSet()); tableMap.put(Version.TRON_V1_1, newTronV11OperationSet()); tableMap.put(Version.TRON_V1_2, newTronV12OperationSet()); + tableMap.put(Version.TRON_V1_3, newTronV13OperationSet()); } public static JumpTable newTronV10OperationSet() { @@ -47,12 +49,18 @@ public static JumpTable newTronV12OperationSet() { return table; } + public static JumpTable newTronV13OperationSet() { + JumpTable table = newTronV12OperationSet(); + appendShangHaiOperations(table); + return table; + } + // Just for warming up class to avoid out_of_time public static void init() {} public static JumpTable getTable() { // always get the table which has the newest version - JumpTable table = tableMap.get(Version.TRON_V1_2); + JumpTable table = tableMap.get(Version.TRON_V1_3); // next make the corresponding changes, exclude activating opcode if (VMConfig.allowHigherLimitForMaxCpuTimeOfOneTx()) { @@ -617,4 +625,14 @@ public static void appendDelegateOperations(JumpTable table) { OperationActions::unDelegateResourceAction, proposal)); } + + public static void appendShangHaiOperations(JumpTable table) { + BooleanSupplier proposal = VMConfig::allowTvmShanghai; + + table.set(new Operation( + Op.PUSH0, 0, 0, + EnergyCost::getBaseTierCost, + OperationActions::push0Action, + proposal)); + } } diff --git a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java index 8c597bc50bf..463d8c8995a 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java +++ b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java @@ -38,6 +38,7 @@ public static void load(StoreFactory storeFactory) { VMConfig.initDynamicEnergyThreshold(ds.getDynamicEnergyThreshold()); VMConfig.initDynamicEnergyIncreaseFactor(ds.getDynamicEnergyIncreaseFactor()); VMConfig.initDynamicEnergyMaxFactor(ds.getDynamicEnergyMaxFactor()); + VMConfig.initAllowTvmShangHai(ds.getAllowTvmShangHai()); } } } diff --git a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java index 004fb5ffb8f..97202432598 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java +++ b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java @@ -47,6 +47,8 @@ public class VMConfig { private static long DYNAMIC_ENERGY_MAX_FACTOR = 0L; + private static boolean ALLOW_TVM_SHANGHAI = false; + private VMConfig() { } @@ -130,6 +132,10 @@ public static void initDynamicEnergyMaxFactor(long maxFactor) { DYNAMIC_ENERGY_MAX_FACTOR = maxFactor; } + public static void initAllowTvmShangHai(long allow) { + ALLOW_TVM_SHANGHAI = allow == 1; + } + public static boolean getEnergyLimitHardFork() { return CommonParameter.ENERGY_LIMIT_HARD_FORK; } @@ -201,4 +207,8 @@ public static long getDynamicEnergyIncreaseFactor() { public static long getDynamicEnergyMaxFactor() { return DYNAMIC_ENERGY_MAX_FACTOR; } + + public static boolean allowTvmShanghai() { + return ALLOW_TVM_SHANGHAI; + } } diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index d2870b45e2b..8e678ac7c23 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -206,6 +206,8 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID = "ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID".getBytes(); + private static final byte[] ALLOW_TVM_SHANGHAI = "ALLOW_TVM_SHANGHAI".getBytes(); + @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { super(dbName); @@ -941,6 +943,12 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { } catch (IllegalArgumentException e) { this.saveDynamicEnergyMaxFactor(CommonParameter.getInstance().getDynamicEnergyMaxFactor()); } + + try { + this.getAllowTvmShangHai(); + } catch (IllegalArgumentException e) { + this.saveAllowTvmShangHai(CommonParameter.getInstance().getAllowTvmShangHai()); + } } public String intArrayToString(int[] a) { @@ -2755,6 +2763,20 @@ public long getAllowOptimizedReturnValueOfChainId() { () -> new IllegalArgumentException(msg)); } + public void saveAllowTvmShangHai(long allowTvmShangHai) { + this.put(DynamicPropertiesStore.ALLOW_TVM_SHANGHAI, + new BytesCapsule(ByteArray.fromLong(allowTvmShangHai))); + } + + public long getAllowTvmShangHai() { + String msg = "not found ALLOW_TVM_SHANGHAI"; + return Optional.ofNullable(getUnchecked(ALLOW_TVM_SHANGHAI)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException(msg)); + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index caf74d61658..a69bb02fc07 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -6,7 +6,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; - import lombok.Getter; import lombok.Setter; import org.quartz.CronExpression; @@ -642,6 +641,10 @@ public class CommonParameter { @Setter public long dynamicConfigCheckInterval; + @Getter + @Setter + public long allowTvmShangHai; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index bcbfecb7904..c7f5ac86ad7 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -369,4 +369,6 @@ public class Constant { public static final String DYNAMIC_CONFIG_ENABLE = "node.dynamicConfig.enable"; public static final String DYNAMIC_CONFIG_CHECK_INTERVAL = "node.dynamicConfig.checkInterval"; + + public static final String COMMITTEE_ALLOW_TVM_SHANGHAI = "committee.allowTvmShangHai"; } diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index 7116e1e7141..5a170577b99 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -21,7 +21,8 @@ public enum ForkBlockVersionEnum { VERSION_4_5(24, 1596780000000L, 80), VERSION_4_6(25, 1596780000000L, 80), VERSION_4_7(26, 1596780000000L, 80), - VERSION_4_7_1(27, 1596780000000L, 80); + VERSION_4_7_1(27, 1596780000000L, 80), + VERSION_4_7_2(28, 1596780000000L, 80); // if add a version, modify BLOCK_VERSION simultaneously @Getter @@ -70,7 +71,7 @@ public class ChainConstant { public static final int SINGLE_REPEAT = 1; public static final int BLOCK_FILLED_SLOTS_NUMBER = 128; public static final int MAX_FROZEN_NUMBER = 1; - public static final int BLOCK_VERSION = 27; + public static final int BLOCK_VERSION = 28; public static final long FROZEN_PERIOD = 86_400_000L; public static final long DELEGATE_PERIOD = 3 * 86_400_000L; public static final long TRX_PRECISION = 1000_000L; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 487d6aaa886..9051bde8bba 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1316,6 +1316,11 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getDynamicEnergyMaxFactor()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getAllowTvmShangHai") + .setValue(dbManager.getDynamicPropertiesStore().getAllowTvmShangHai()) + .build()); + return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 19962fbac8e..5f25c9f6f22 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -231,6 +231,7 @@ public static void clearParam() { PARAMETER.p2pDisable = false; PARAMETER.dynamicConfigEnable = false; PARAMETER.dynamicConfigCheckInterval = 600; + PARAMETER.allowTvmShangHai = 0; } /** @@ -1166,6 +1167,10 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.dynamicConfigCheckInterval = 600; } + PARAMETER.allowTvmShangHai = + config.hasPath(Constant.COMMITTEE_ALLOW_TVM_SHANGHAI) ? config + .getInt(Constant.COMMITTEE_ALLOW_TVM_SHANGHAI) : 0; + logConfig(); } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index fb4c24eee40..4ca90eae640 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -339,6 +339,10 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveDynamicEnergyMaxFactor(entry.getValue()); break; } + case ALLOW_TVM_SHANGHAI: { + manager.getDynamicPropertiesStore().saveAllowTvmShangHai(entry.getValue()); + break; + } default: find = false; break; From 2d7186c2d121c5031c41d5e5e053d3ee0242251a Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 21 Apr 2023 18:35:27 +0800 Subject: [PATCH 0754/1197] func(proposal): optimize proposal initialization logic --- .../org/tron/core/store/DynamicPropertiesStore.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 8e678ac7c23..001282a0de8 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -943,12 +943,6 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { } catch (IllegalArgumentException e) { this.saveDynamicEnergyMaxFactor(CommonParameter.getInstance().getDynamicEnergyMaxFactor()); } - - try { - this.getAllowTvmShangHai(); - } catch (IllegalArgumentException e) { - this.saveAllowTvmShangHai(CommonParameter.getInstance().getAllowTvmShangHai()); - } } public String intArrayToString(int[] a) { @@ -2769,12 +2763,10 @@ public void saveAllowTvmShangHai(long allowTvmShangHai) { } public long getAllowTvmShangHai() { - String msg = "not found ALLOW_TVM_SHANGHAI"; return Optional.ofNullable(getUnchecked(ALLOW_TVM_SHANGHAI)) .map(BytesCapsule::getData) .map(ByteArray::toLong) - .orElseThrow( - () -> new IllegalArgumentException(msg)); + .orElse(CommonParameter.getInstance().getAllowTvmShangHai()); } private static class DynamicResourceProperties { From add119e2f3ac0f8530a4cfb3baea8507954b848b Mon Sep 17 00:00:00 2001 From: "morgan.peng" Date: Wed, 12 Apr 2023 19:59:00 +0800 Subject: [PATCH 0755/1197] feat(test): add unit test Add unit test --- .../tron/core/db/ByteArrayWrapperTest.java | 22 ++++ .../java/org/tron/core/db/ManagerTest.java | 83 +++++++++++++- .../filter/RpcApiAccessInterceptorTest.java | 102 ++++++++++++++++++ .../org/tron/keystore/CredentialsTest.java | 48 +++++++++ .../org/tron/keystore/WalletFileTest.java | 28 +++++ .../org/tron/program/SolidityNodeTest.java | 7 ++ 6 files changed, 289 insertions(+), 1 deletion(-) create mode 100644 framework/src/test/java/org/tron/core/db/ByteArrayWrapperTest.java create mode 100644 framework/src/test/java/org/tron/keystore/CredentialsTest.java create mode 100644 framework/src/test/java/org/tron/keystore/WalletFileTest.java diff --git a/framework/src/test/java/org/tron/core/db/ByteArrayWrapperTest.java b/framework/src/test/java/org/tron/core/db/ByteArrayWrapperTest.java new file mode 100644 index 00000000000..ef4a60ca1da --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/ByteArrayWrapperTest.java @@ -0,0 +1,22 @@ +package org.tron.core.db; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.testng.Assert; +import org.tron.common.utils.ByteArray; + +@Slf4j +public class ByteArrayWrapperTest { + + @Test + public void createByteArray() { + ByteArrayWrapper byteArrayWrapper1 = new ByteArrayWrapper(ByteArray.fromHexString("1")); + ByteArrayWrapper byteArrayWrapper2 = new ByteArrayWrapper(ByteArray.fromHexString("2")); + Assert.assertEquals(byteArrayWrapper1.compareTo(byteArrayWrapper2), -1); + Assert.assertFalse(byteArrayWrapper1.equals(byteArrayWrapper2)); + Assert.assertFalse(byteArrayWrapper1.getData().equals(byteArrayWrapper2.getData())); + Assert.assertTrue(byteArrayWrapper1.hashCode() != byteArrayWrapper2.hashCode()); + Assert.assertEquals(byteArrayWrapper1.toString().equals(byteArrayWrapper2.toString()),false); + } + +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index bed884cc427..916ea784939 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -12,6 +12,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -20,11 +21,14 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.testng.collections.Sets; import org.tron.common.application.TronApplicationContext; import org.tron.common.crypto.ECKey; +import org.tron.common.runtime.RuntimeImpl; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; import org.tron.common.utils.JsonUtil; +import org.tron.common.utils.ReflectUtils; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.StringUtil; import org.tron.common.utils.Utils; @@ -38,8 +42,12 @@ import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.DefaultConfig; +import org.tron.core.config.Parameter; import org.tron.core.config.args.Args; import org.tron.core.consensus.ConsensusService; +import org.tron.core.db.accountstate.AccountStateEntity; +import org.tron.core.db.accountstate.TrieService; +import org.tron.core.db.accountstate.storetrie.AccountStateStoreTrie; import org.tron.core.exception.AccountResourceInsufficientException; import org.tron.core.exception.BadBlockException; import org.tron.core.exception.BadItemException; @@ -67,6 +75,7 @@ import org.tron.core.store.ExchangeStore; import org.tron.core.store.ExchangeV2Store; import org.tron.core.store.IncrementalMerkleTreeStore; +import org.tron.core.store.StoreFactory; import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.Transaction; @@ -142,6 +151,17 @@ public void updateRecentTransaction() throws Exception { 0, ByteString.copyFrom(new byte[64])); b.addTransaction(trx); dbManager.updateRecentTransaction(b); + try { + dbManager.consumeBandwidth(trx, new TransactionTrace(trx, StoreFactory.getInstance(), + new RuntimeImpl())); + } catch (Exception e) { + Assert.assertTrue(e instanceof ContractValidateException); + } + dbManager.consumeMemoFee(trx, new TransactionTrace(trx, StoreFactory.getInstance(), + new RuntimeImpl())); + Assert.assertTrue(dbManager.getTxListFromPending().isEmpty()); + Assert.assertNull(dbManager.getTxFromPending(trx.getTransactionId().toString())); + Assert.assertEquals(0, dbManager.getPendingSize()); Assert.assertEquals(1, chainManager.getRecentTransactionStore().size()); byte[] key = ByteArray.subArray(ByteArray.fromLong(1), 6, 8); byte[] value = chainManager.getRecentTransactionStore().get(key).getData(); @@ -212,6 +232,9 @@ public void pushBlock() { } catch (Exception e) { Assert.assertTrue("pushBlock is error", false); } + TrieService trieService = context.getBean(TrieService.class); + Assert.assertTrue(trieService.getFullAccountStateRootHash().length > 0); + Assert.assertTrue(trieService.getSolidityAccountStateRootHash().length > 0); if (isUnlinked) { Assert.assertEquals("getBlockIdByNum is error", @@ -233,10 +256,50 @@ public void pushBlock() { } catch (ItemNotFoundException e) { Assert.assertTrue(true); } - + try { + dbManager.getBlockChainHashesOnFork(blockCapsule2.getBlockId()); + } catch (Exception e) { + Assert.assertTrue(e instanceof NonCommonBlockException); + } Assert.assertTrue("hasBlocks is error", chainManager.hasBlocks()); } + @Test + public void transactionTest() { + TransactionCapsule trans0 = new TransactionCapsule(Transaction.newBuilder() + .setRawData(Transaction.raw.newBuilder().setData(ByteString.copyFrom( + new byte[Parameter.ChainConstant.BLOCK_SIZE + Constant.ONE_THOUSAND]))).build(), + ContractType.ShieldedTransferContract); + ShieldContract.ShieldedTransferContract trx1 = ShieldContract.ShieldedTransferContract + .newBuilder() + .setFromAmount(10) + .setToAmount(10) + .build(); + TransactionCapsule trans = new TransactionCapsule(trx1, ContractType.ShieldedTransferContract); + try { + dbManager.pushTransaction(trans0); + dbManager.pushTransaction(trans); + } catch (Exception e) { + Assert.assertTrue(e instanceof TaposException); + } + dbManager.rePush(trans0); + ReflectUtils.invokeMethod(dbManager,"filterOwnerAddress", + new Class[]{trans.getClass(), Set.class},trans, Sets.newHashSet()); + Assert.assertNotNull(dbManager.getTxListFromPending()); + + try { + dbManager.validateTapos(trans); + } catch (Exception e) { + Assert.assertTrue(e instanceof TaposException); + } + try { + dbManager.pushVerifiedBlock(chainManager.getHead()); + dbManager.getBlockChainHashesOnFork(chainManager.getHeadBlockId()); + } catch (Exception e) { + Assert.assertTrue(e instanceof TaposException); + } + } + @Test public void GetterInstanceTest() { @@ -260,6 +323,24 @@ public void GetterInstanceTest() { } + @Test + public void entityTest() { + AccountStateStoreTrie trie = context.getBean(AccountStateStoreTrie.class); + Assert.assertNull(trie.getAccount("".getBytes())); + Assert.assertNull(trie.getAccount("".getBytes(), "".getBytes())); + Assert.assertNull(trie.getSolidityAccount("".getBytes())); + Assert.assertTrue(trie.isEmpty()); + AccountStateEntity entity = new AccountStateEntity(); + AccountStateEntity parsedEntity = AccountStateEntity.parse("".getBytes()); + Assert.assertTrue(parsedEntity != null); + Assert.assertTrue(parsedEntity.getAccount() != null); + Assert.assertTrue(org.tron.core.db.api.pojo.Account.of() != null); + Assert.assertTrue(org.tron.core.db.api.pojo.AssetIssue.of() != null); + Assert.assertTrue(org.tron.core.db.api.pojo.Block.of() != null); + Assert.assertTrue(org.tron.core.db.api.pojo.Transaction.of() != null); + + } + @Test public void getHeadTest() { try { diff --git a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java index dd6bd132f0e..edd15fc19de 100644 --- a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java @@ -3,10 +3,12 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import io.grpc.StatusRuntimeException; +import io.grpc.stub.ServerCallStreamObserver; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; import org.junit.Assert; @@ -119,6 +121,106 @@ public void testAccessDisabledFullNode() { blockingStubFull.getBlockByNum(message); } + @Test + public void testRpcApiService() { + RpcApiService rpcApiService = context.getBean(RpcApiService.class); + ServerCallStreamObserverTest serverCallStreamObserverTest = new ServerCallStreamObserverTest(); + rpcApiService.getBlockCommon(GrpcAPI.BlockReq.getDefaultInstance(), + serverCallStreamObserverTest); + Assert.assertTrue("Get block Common failed!", serverCallStreamObserverTest.isReady()); + serverCallStreamObserverTest.isCancelled(); + rpcApiService.getBrokerageInfoCommon(GrpcAPI.BytesMessage.newBuilder().build(), + serverCallStreamObserverTest); + Assert.assertTrue("Get brokerage info Common failed!", + serverCallStreamObserverTest.isReady()); + serverCallStreamObserverTest.isCancelled(); + rpcApiService.getBurnTrxCommon(GrpcAPI.EmptyMessage.newBuilder().build(), + serverCallStreamObserverTest); + Assert.assertTrue("Get burn trx common failed!", + serverCallStreamObserverTest.isReady()); + serverCallStreamObserverTest.isCancelled(); + rpcApiService.getPendingSizeCommon(GrpcAPI.EmptyMessage.getDefaultInstance(), + serverCallStreamObserverTest); + Assert.assertTrue("Get pending size common failed!", + serverCallStreamObserverTest.isReady()); + serverCallStreamObserverTest.isCancelled(); + rpcApiService.getRewardInfoCommon(GrpcAPI.BytesMessage.newBuilder().build(), + serverCallStreamObserverTest); + Assert.assertTrue("Get reward info common failed!", + serverCallStreamObserverTest.isReady()); + serverCallStreamObserverTest.isCancelled(); + rpcApiService.getTransactionCountByBlockNumCommon( + GrpcAPI.NumberMessage.newBuilder().getDefaultInstanceForType(), + serverCallStreamObserverTest); + Assert.assertTrue("Get transaction count by block num failed!", + serverCallStreamObserverTest.isReady()); + serverCallStreamObserverTest.isCancelled(); + rpcApiService.getTransactionFromPendingCommon(GrpcAPI.BytesMessage.newBuilder().build(), + serverCallStreamObserverTest); + Assert.assertTrue("Get transaction from pending failed!", + serverCallStreamObserverTest.isReady() == false); + serverCallStreamObserverTest.isCancelled(); + rpcApiService.getTransactionListFromPendingCommon(GrpcAPI.EmptyMessage.newBuilder() + .getDefaultInstanceForType(), serverCallStreamObserverTest); + Assert.assertTrue("Get transaction list from pending failed!", + serverCallStreamObserverTest.isReady()); + } + + + class ServerCallStreamObserverTest extends ServerCallStreamObserver { + + Object ret; + + @Override + public boolean isCancelled() { + ret = null; + return true; + } + + @Override + public void setOnCancelHandler(Runnable onCancelHandler) { + } + + @Override + public void setCompression(String compression) { + } + + @Override + public boolean isReady() { + return Objects.nonNull(ret); + } + + @Override + public void setOnReadyHandler(Runnable onReadyHandler) { + } + + @Override + public void disableAutoInboundFlowControl() { + } + + @Override + public void request(int count) { + } + + @Override + public void setMessageCompression(boolean enable) { + } + + @Override + public void onNext(Object value) { + ret = value; + } + + @Override + public void onError(Throwable t) { + } + + @Override + public void onCompleted() { + } + } + + @Test public void testAccessDisabledSolidityNode() { List disabledApiList = new ArrayList<>(); diff --git a/framework/src/test/java/org/tron/keystore/CredentialsTest.java b/framework/src/test/java/org/tron/keystore/CredentialsTest.java new file mode 100644 index 00000000000..3fe2ce02b63 --- /dev/null +++ b/framework/src/test/java/org/tron/keystore/CredentialsTest.java @@ -0,0 +1,48 @@ +package org.tron.keystore; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import junit.framework.TestCase; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.springframework.util.Assert; +import org.tron.common.crypto.SignUtils; +import org.tron.common.crypto.sm2.SM2; +import org.tron.common.utils.ByteUtil; + +@Slf4j +public class CredentialsTest extends TestCase { + + @Test + public void testCreate() throws NoSuchAlgorithmException { + Credentials credentials = Credentials.create(SignUtils.getGeneratedRandomSign( + SecureRandom.getInstance("NativePRNG"),true)); + Assert.hasText(credentials.getAddress(),"Credentials address create failed!"); + Assert.notNull(credentials.getSignInterface(), + "Credentials cryptoEngine create failed"); + } + + @Test + public void testCreateFromSM2() { + try { + Credentials.create(SM2.fromNodeId(ByteUtil.hexToBytes("fffffffffff" + + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + + "fffffffffffffffffffffffffffffffffffffff"))); + } catch (Exception e) { + Assert.isInstanceOf(IllegalArgumentException.class, e); + } + } + + @Test + public void testEquals() throws NoSuchAlgorithmException { + Credentials credentials1 = Credentials.create(SignUtils.getGeneratedRandomSign( + SecureRandom.getInstance("NativePRNG"),true)); + Credentials credentials2 = Credentials.create(SignUtils.getGeneratedRandomSign( + SecureRandom.getInstance("NativePRNG"),true)); + Assert.isTrue(!credentials1.equals(credentials2), + "Credentials instance should be not equal!"); + Assert.isTrue(!(credentials1.hashCode() == credentials2.hashCode()), + "Credentials instance hashcode should be not equal!"); + } + +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/keystore/WalletFileTest.java b/framework/src/test/java/org/tron/keystore/WalletFileTest.java new file mode 100644 index 00000000000..7d584b3d8e2 --- /dev/null +++ b/framework/src/test/java/org/tron/keystore/WalletFileTest.java @@ -0,0 +1,28 @@ +package org.tron.keystore; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import junit.framework.TestCase; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; +import org.tron.common.crypto.SignUtils; +import org.tron.core.exception.CipherException; + +@Slf4j +public class WalletFileTest extends TestCase { + + + @Test + public void testGetAddress() throws NoSuchAlgorithmException, CipherException { + WalletFile walletFile1 = Wallet.createStandard("", SignUtils.getGeneratedRandomSign( + SecureRandom.getInstance("NativePRNG"),true)); + WalletFile walletFile2 = Wallet.createStandard("", SignUtils.getGeneratedRandomSign( + SecureRandom.getInstance("NativePRNG"),true)); + Assert.assertTrue(!walletFile1.getAddress().equals(walletFile2.getAddress())); + Assert.assertTrue(!walletFile1.getCrypto().equals(walletFile2.getCrypto())); + Assert.assertTrue(!walletFile1.getId().equals(walletFile2.getId())); + Assert.assertTrue(walletFile1.getVersion() == walletFile2.getVersion()); + } + +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/program/SolidityNodeTest.java b/framework/src/test/java/org/tron/program/SolidityNodeTest.java index 99d6a75adbe..422ec5e6876 100755 --- a/framework/src/test/java/org/tron/program/SolidityNodeTest.java +++ b/framework/src/test/java/org/tron/program/SolidityNodeTest.java @@ -89,6 +89,13 @@ public void testSolidityGrpcCall() { Block genesisBlock = databaseGrpcClient.getBlock(0); Assert.assertNotNull(genesisBlock); Assert.assertFalse(genesisBlock.getTransactionsList().isEmpty()); + Block invalidBlock = databaseGrpcClient.getBlock(-1); + Assert.assertNotNull(invalidBlock); + try { + databaseGrpcClient = new DatabaseGrpcClient(address, -1); + } catch (Exception e) { + logger.error("Failed to create database grpc client {}", address); + } databaseGrpcClient.shutdown(); } From 519cbeb713f17e16e9c0420cc2b97c750f5f9feb Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 24 Apr 2023 16:40:41 +0800 Subject: [PATCH 0756/1197] test(vm): add unit test for push0 instruction --- .../common/runtime/vm/OperationsTest.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java index f9f586b87a6..8dd5e3341c2 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java @@ -24,6 +24,7 @@ import org.tron.core.db.Manager; import org.tron.core.exception.ContractValidateException; import org.tron.core.store.StoreFactory; +import org.tron.core.vm.EnergyCost; import org.tron.core.vm.JumpTable; import org.tron.core.vm.Op; import org.tron.core.vm.Operation; @@ -40,7 +41,7 @@ public class OperationsTest { private ProgramInvokeMockImpl invoke; private Program program; - private final JumpTable jumpTable = OperationRegistry.newTronV10OperationSet(); + private final JumpTable jumpTable = OperationRegistry.getTable(); private static ChainBaseManager chainBaseManager; private static String dbPath; private static TronApplicationContext context; @@ -862,6 +863,25 @@ public void testComplexOperations() throws ContractValidateException { } + @Test + public void testPush0() throws ContractValidateException { + VMConfig.initAllowTvmShangHai(1); + + invoke = new ProgramInvokeMockImpl(); + Protocol.Transaction trx = Protocol.Transaction.getDefaultInstance(); + InternalTransaction interTrx = + new InternalTransaction(trx, InternalTransaction.TrxType.TRX_UNKNOWN_TYPE); + + byte[] op = new byte[1]; + op[0] = Op.PUSH0; + program = new Program(op, op, invoke, interTrx); + testOperations(program); + Assert.assertEquals(EnergyCost.getBaseTierCost(null), program.getResult().getEnergyUsed()); + Assert.assertEquals(DataWord.ZERO(), program.getStack().pop()); + + VMConfig.initAllowTvmShangHai(0); + } + private void testOperations(Program program) { try { while (!program.isStopped()) { From 6e10cd3b440632b12d82e88acb1e69ce89fcec4b Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 25 Apr 2023 19:35:06 +0800 Subject: [PATCH 0757/1197] fix(net):update libp2p from test-v0.2.21 to test-v2.0.0 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 86f9b328184..d065d3cbf89 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.21',{ + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v2.0.0',{ exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' From aa30ec643ebe12c368391cf3ee9b65d9159f0a89 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 26 Apr 2023 11:56:59 +0800 Subject: [PATCH 0758/1197] feat(net): add unit test for SyncService --- .../core/net/services/SyncServiceTest.java | 134 +++++++++++++++++- 1 file changed, 130 insertions(+), 4 deletions(-) diff --git a/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java b/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java index fd2bb5dd017..6f5d21b028f 100644 --- a/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java @@ -1,41 +1,57 @@ package org.tron.core.net.services; +import static org.mockito.Mockito.mock; + +import com.google.common.cache.Cache; import java.io.File; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.net.InetSocketAddress; +import java.util.Map; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.context.ApplicationContext; import org.tron.common.application.TronApplicationContext; import org.tron.common.utils.FileUtil; import org.tron.common.utils.ReflectUtils; import org.tron.core.Constant; +import org.tron.core.capsule.BlockCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.net.P2pEventHandlerImpl; +import org.tron.core.net.message.adv.BlockMessage; import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.peer.PeerManager; import org.tron.core.net.peer.TronState; import org.tron.core.net.service.sync.SyncService; import org.tron.p2p.connection.Channel; - +import org.tron.protos.Protocol; public class SyncServiceTest { protected TronApplicationContext context; private SyncService service; private PeerConnection peer; private P2pEventHandlerImpl p2pEventHandler; + private ApplicationContext ctx; private String dbPath = "output-sync-service-test"; + public SyncServiceTest() { + } + /** * init context. */ @Before - public void init() { + public void init() throws Exception { Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, - Constant.TEST_CONF); + Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); service = context.getBean(SyncService.class); + p2pEventHandler = context.getBean(P2pEventHandlerImpl.class); + ctx = (ApplicationContext) ReflectUtils.getFieldObject(p2pEventHandler, "ctx"); } /** @@ -49,7 +65,7 @@ public void destroy() { } @Test - public void test() { + public void testStartSync() { try { ReflectUtils.setFieldValue(service, "fetchFlag", true); ReflectUtils.setFieldValue(service, "handleFlag", true); @@ -72,4 +88,114 @@ public void test() { } service.close(); } + + @Test + public void testProcessBlock() throws Exception { + peer = context.getBean(PeerConnection.class); + Assert.assertNull(peer.getSyncChainRequested()); + Channel c1 = new Channel(); + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); + Field field = c1.getClass().getDeclaredField("inetSocketAddress"); + field.setAccessible(true); + field.set(c1, a1.getAddress()); + peer.setChannel(c1); + service.processBlock(peer, + new BlockMessage(new BlockCapsule(Protocol.Block.newBuilder().build()))); + boolean fetchFlag = (boolean) ReflectUtils.getFieldObject(service, "fetchFlag"); + boolean handleFlag = (boolean) ReflectUtils.getFieldObject(service, "handleFlag"); + Assert.assertTrue(fetchFlag); + Assert.assertTrue(handleFlag); + } + + @Test + public void testOnDisconnect() throws Exception { + Cache requestBlockIds = + (Cache) ReflectUtils.getFieldObject(service, "requestBlockIds"); + peer = context.getBean(PeerConnection.class); + Assert.assertNull(peer.getSyncChainRequested()); + Channel c1 = new Channel(); + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); + Field field = c1.getClass().getDeclaredField("inetSocketAddress"); + field.setAccessible(true); + field.set(c1, a1.getAddress()); + peer.setChannel(c1); + BlockCapsule.BlockId blockId = new BlockCapsule.BlockId(); + requestBlockIds.put(blockId, peer); + peer.getSyncBlockToFetch().push(blockId); + service.onDisconnect(peer); + Assert.assertTrue(requestBlockIds.getIfPresent(blockId) == null); + } + + @Test + public void testStartFetchSyncBlock() throws Exception { + BlockCapsule.BlockId blockId = new BlockCapsule.BlockId(); + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); + + Method method = service.getClass().getDeclaredMethod("startFetchSyncBlock"); + method.setAccessible(true); + + Cache requestBlockIds = + (Cache) + ReflectUtils.getFieldObject(service, "requestBlockIds"); + + Channel c1 = mock(Channel.class); + Mockito.when(c1.getInetSocketAddress()).thenReturn(a1); + Mockito.when(c1.getInetAddress()).thenReturn(a1.getAddress()); + + PeerManager.add(ctx, c1); + peer = PeerManager.getPeers().get(0); + + method.invoke(service); + Assert.assertTrue(peer.getSyncBlockRequested().get(blockId) == null); + + peer.getSyncBlockToFetch().add(blockId); + method.invoke(service); + Assert.assertTrue(peer.getSyncBlockToFetch().size() == 1); + Assert.assertTrue(peer.getSyncBlockRequested().get(blockId) == null); + + peer.setFetchAble(true); + method.invoke(service); + Assert.assertTrue(peer.getSyncBlockToFetch().size() == 1); + Assert.assertTrue(peer.getSyncBlockRequested().get(blockId) != null); + Assert.assertTrue(requestBlockIds.getIfPresent(blockId) != null); + + peer.getSyncBlockRequested().remove(blockId); + method.invoke(service); + Assert.assertTrue(peer.getSyncBlockRequested().get(blockId) == null); + } + + @Test + public void testHandleSyncBlock() throws Exception { + Method method = service.getClass().getDeclaredMethod("handleSyncBlock"); + method.setAccessible(true); + + Map blockJustReceived = + (Map) + ReflectUtils.getFieldObject(service, "blockJustReceived"); + + BlockCapsule blockCapsule = new BlockCapsule(Protocol.Block.newBuilder().build()); + + BlockCapsule.BlockId blockId = blockCapsule.getBlockId(); + + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); + Channel c1 = mock(Channel.class); + Mockito.when(c1.getInetSocketAddress()).thenReturn(a1); + Mockito.when(c1.getInetAddress()).thenReturn(a1.getAddress()); + PeerManager.add(ctx, c1); + peer = PeerManager.getPeers().get(0); + + blockJustReceived.put(new BlockMessage(blockCapsule), peer); + + peer.getSyncBlockToFetch().add(blockId); + + Cache requestBlockIds = + (Cache) + ReflectUtils.getFieldObject(service, "requestBlockIds"); + + requestBlockIds.put(blockId, peer); + + method.invoke(service); + + Assert.assertTrue(requestBlockIds.getIfPresent(blockId) == null); + } } From 4a1b42d616b9813fe3c32617962fee20b7d78521 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 26 Apr 2023 15:11:32 +0800 Subject: [PATCH 0759/1197] feat(net): optimize SyncService unit test code --- .../core/net/services/SyncServiceTest.java | 49 ++++++++++++------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java b/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java index 6f5d21b028f..35fa6f4fd5c 100644 --- a/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java @@ -7,6 +7,8 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Collections; import java.util.Map; import org.junit.After; import org.junit.Assert; @@ -37,6 +39,8 @@ public class SyncServiceTest { private P2pEventHandlerImpl p2pEventHandler; private ApplicationContext ctx; private String dbPath = "output-sync-service-test"; + private InetSocketAddress inetSocketAddress = + new InetSocketAddress("127.0.0.2", 10001); public SyncServiceTest() { } @@ -74,14 +78,17 @@ public void testStartSync() { Assert.assertTrue((boolean) ReflectUtils.getFieldObject(service, "handleFlag")); peer = context.getBean(PeerConnection.class); Assert.assertNull(peer.getSyncChainRequested()); + Channel c1 = new Channel(); - InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); - Field field = c1.getClass().getDeclaredField("inetSocketAddress"); - field.setAccessible(true); - field.set(c1, a1.getAddress()); + ReflectUtils.setFieldValue(c1, "inetSocketAddress", inetSocketAddress); + ReflectUtils.setFieldValue(c1, "inetAddress", inetSocketAddress.getAddress()); + peer.setChannel(c1); + service.startSync(peer); + ReflectUtils.setFieldValue(peer, "tronState", TronState.SYNCING); + service.startSync(peer); } catch (Exception e) { // no need to deal with @@ -90,14 +97,12 @@ public void testStartSync() { } @Test - public void testProcessBlock() throws Exception { + public void testProcessBlock() { peer = context.getBean(PeerConnection.class); Assert.assertNull(peer.getSyncChainRequested()); Channel c1 = new Channel(); - InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); - Field field = c1.getClass().getDeclaredField("inetSocketAddress"); - field.setAccessible(true); - field.set(c1, a1.getAddress()); + ReflectUtils.setFieldValue(c1, "inetSocketAddress", inetSocketAddress); + ReflectUtils.setFieldValue(c1, "inetAddress", inetSocketAddress.getAddress()); peer.setChannel(c1); service.processBlock(peer, new BlockMessage(new BlockCapsule(Protocol.Block.newBuilder().build()))); @@ -108,28 +113,29 @@ public void testProcessBlock() throws Exception { } @Test - public void testOnDisconnect() throws Exception { + public void testOnDisconnect() { Cache requestBlockIds = (Cache) ReflectUtils.getFieldObject(service, "requestBlockIds"); peer = context.getBean(PeerConnection.class); Assert.assertNull(peer.getSyncChainRequested()); - Channel c1 = new Channel(); - InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); - Field field = c1.getClass().getDeclaredField("inetSocketAddress"); - field.setAccessible(true); - field.set(c1, a1.getAddress()); + Channel c1 = mock(Channel.class); + Mockito.when(c1.getInetSocketAddress()).thenReturn(inetSocketAddress); + Mockito.when(c1.getInetAddress()).thenReturn(inetSocketAddress.getAddress()); peer.setChannel(c1); BlockCapsule.BlockId blockId = new BlockCapsule.BlockId(); requestBlockIds.put(blockId, peer); - peer.getSyncBlockToFetch().push(blockId); + peer.getSyncBlockRequested().put(blockId, System.currentTimeMillis()); service.onDisconnect(peer); Assert.assertTrue(requestBlockIds.getIfPresent(blockId) == null); } @Test public void testStartFetchSyncBlock() throws Exception { + Field field = PeerManager.class.getDeclaredField("peers"); + field.setAccessible(true); + field.set(PeerManager.class, Collections.synchronizedList(new ArrayList<>())); + BlockCapsule.BlockId blockId = new BlockCapsule.BlockId(); - InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); Method method = service.getClass().getDeclaredMethod("startFetchSyncBlock"); method.setAccessible(true); @@ -139,8 +145,8 @@ public void testStartFetchSyncBlock() throws Exception { ReflectUtils.getFieldObject(service, "requestBlockIds"); Channel c1 = mock(Channel.class); - Mockito.when(c1.getInetSocketAddress()).thenReturn(a1); - Mockito.when(c1.getInetAddress()).thenReturn(a1.getAddress()); + Mockito.when(c1.getInetSocketAddress()).thenReturn(inetSocketAddress); + Mockito.when(c1.getInetAddress()).thenReturn(inetSocketAddress.getAddress()); PeerManager.add(ctx, c1); peer = PeerManager.getPeers().get(0); @@ -166,6 +172,11 @@ public void testStartFetchSyncBlock() throws Exception { @Test public void testHandleSyncBlock() throws Exception { + + Field field = PeerManager.class.getDeclaredField("peers"); + field.setAccessible(true); + field.set(PeerManager.class, Collections.synchronizedList(new ArrayList<>())); + Method method = service.getClass().getDeclaredMethod("handleSyncBlock"); method.setAccessible(true); From 41080209fd7c0ba79f8f82bb617c32e72ecfb138 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Fri, 5 May 2023 11:57:51 +0800 Subject: [PATCH 0760/1197] feat(net): optimize InventoryMessage processing logic --- .../common/parameter/CommonParameter.java | 3 +++ .../src/main/java/org/tron/core/Constant.java | 1 + .../java/org/tron/core/config/args/Args.java | 4 +++ .../tron/core/net/P2pEventHandlerImpl.java | 24 +++++++++++++++++ .../messagehandler/InventoryMsgHandler.java | 26 +++++-------------- .../org/tron/common/config/args/ArgsTest.java | 1 + 6 files changed, 39 insertions(+), 20 deletions(-) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index caf74d61658..0822bdddfe9 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -165,6 +165,9 @@ public class CommonParameter { public int maxConnectionsWithSameIp; @Getter @Setter + public int maxTps; + @Getter + @Setter public int minParticipationRate; @Getter @Setter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index bcbfecb7904..4ee1fb40d8e 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -93,6 +93,7 @@ public class Constant { public static final String NODE_MAX_ACTIVE_NODES = "node.maxActiveNodes"; public static final String NODE_MAX_ACTIVE_NODES_WITH_SAME_IP = "node.maxActiveNodesWithSameIp"; + public static final String NODE_MAX_TPS = "node.maxTps"; public static final String NODE_CONNECT_FACTOR = "node.connectFactor"; public static final String NODE_ACTIVE_CONNECT_FACTOR = "node.activeConnectFactor"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 19962fbac8e..87825114c92 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -135,6 +135,7 @@ public static void clearParam() { PARAMETER.minConnections = 8; PARAMETER.minActiveConnections = 3; PARAMETER.maxConnectionsWithSameIp = 2; + PARAMETER.maxTps = 1000; PARAMETER.minParticipationRate = 0; PARAMETER.nodeListenPort = 0; PARAMETER.nodeDiscoveryBindIp = ""; @@ -621,6 +622,9 @@ public static void setParam(final String[] args, final String confFileName) { .getInt(Constant.NODE_MAX_CONNECTIONS_WITH_SAME_IP) : 2; } + PARAMETER.maxTps = config.hasPath(Constant.NODE_MAX_TPS) + ? config.getInt(Constant.NODE_MAX_TPS) : 1000; + PARAMETER.minParticipationRate = config.hasPath(Constant.NODE_MIN_PARTICIPATION_RATE) ? config.getInt(Constant.NODE_MIN_PARTICIPATION_RATE) diff --git a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java index 602b6c9f81c..10f29ddb11c 100644 --- a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java +++ b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java @@ -1,5 +1,8 @@ package org.tron.core.net; +import static org.tron.core.net.message.MessageTypes.INVENTORY; +import static org.tron.core.net.message.MessageTypes.TRX; + import java.util.HashSet; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; @@ -11,11 +14,13 @@ import org.tron.common.prometheus.MetricKeys; import org.tron.common.prometheus.Metrics; import org.tron.consensus.pbft.message.PbftMessage; +import org.tron.core.config.args.Args; import org.tron.core.exception.P2pException; import org.tron.core.net.message.MessageTypes; import org.tron.core.net.message.PbftMessageFactory; import org.tron.core.net.message.TronMessage; import org.tron.core.net.message.TronMessageFactory; +import org.tron.core.net.message.adv.InventoryMessage; import org.tron.core.net.message.base.DisconnectMessage; import org.tron.core.net.message.handshake.HelloMessage; import org.tron.core.net.messagehandler.BlockMsgHandler; @@ -84,6 +89,8 @@ public class P2pEventHandlerImpl extends P2pEventHandler { private byte MESSAGE_MAX_TYPE = 127; + private int maxCountIn10s = Args.getInstance().getMaxTps() * 10; + public P2pEventHandlerImpl() { Set set = new HashSet<>(); for (byte i = 0; i < MESSAGE_MAX_TYPE; i++) { @@ -140,10 +147,27 @@ private void processMessage(PeerConnection peer, byte[] data) { try { msg = TronMessageFactory.create(data); type = msg.getType(); + + if (INVENTORY.equals(type)) { + InventoryMessage message = (InventoryMessage) msg; + Protocol.Inventory.InventoryType inventoryType = message.getInventoryType(); + int count = peer.getPeerStatistics().messageStatistics.tronInTrxInventoryElement + .getCount(10); + if (inventoryType.equals(Protocol.Inventory.InventoryType.TRX) && count > maxCountIn10s) { + logger.warn("Drop inventory from Peer {}, cur:{}, max:{}", + peer.getInetAddress(), count, maxCountIn10s); + if (Args.getInstance().isOpenPrintLog()) { + logger.warn("[overload]Drop tx list is: {}", ((InventoryMessage) msg).getHashList()); + } + return; + } + } + peer.getPeerStatistics().messageStatistics.addTcpInMessage(msg); if (PeerConnection.needToLog(msg)) { logger.info("Receive message from peer: {}, {}", peer.getInetSocketAddress(), msg); } + switch (type) { case P2P_PING: case P2P_PONG: diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java index 65fa09128db..02b04d73b32 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java @@ -26,8 +26,6 @@ public class InventoryMsgHandler implements TronMsgHandler { @Autowired private TransactionsMsgHandler transactionsMsgHandler; - private int maxCountIn10s = 10_000; - @Override public void processMessage(PeerConnection peer, TronMessage msg) { InventoryMessage inventoryMessage = (InventoryMessage) msg; @@ -54,25 +52,13 @@ private boolean check(PeerConnection peer, InventoryMessage inventoryMessage) { return false; } - if (type.equals(InventoryType.TRX)) { - int count = peer.getPeerStatistics().messageStatistics.tronInTrxInventoryElement.getCount(10); - if (count > maxCountIn10s) { - logger.warn("Drop inv: {} size: {} from Peer {}, Inv count: {} is overload", - type, size, peer.getInetAddress(), count); - if (Args.getInstance().isOpenPrintLog()) { - logger.warn("[overload]Drop tx list is: {}", inventoryMessage.getHashList()); - } - return false; - } - - if (transactionsMsgHandler.isBusy()) { - logger.warn("Drop inv: {} size: {} from Peer {}, transactionsMsgHandler is busy", - type, size, peer.getInetAddress()); - if (Args.getInstance().isOpenPrintLog()) { - logger.warn("[isBusy]Drop tx list is: {}", inventoryMessage.getHashList()); - } - return false; + if (type.equals(InventoryType.TRX) && transactionsMsgHandler.isBusy()) { + logger.warn("Drop inv: {} size: {} from Peer {}, transactionsMsgHandler is busy", + type, size, peer.getInetAddress()); + if (Args.getInstance().isOpenPrintLog()) { + logger.warn("[isBusy]Drop tx list is: {}", inventoryMessage.getHashList()); } + return false; } return true; diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index aa58d8e0fc9..c487125d3e3 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -37,5 +37,6 @@ public void testConfig() { Assert.assertEquals(Args.getInstance().getRateLimiterGlobalQps(), 50000); Assert.assertEquals(Args.getInstance().getRateLimiterGlobalIpQps(), 10000); Assert.assertEquals(Args.getInstance().p2pDisable, true); + Assert.assertEquals(Args.getInstance().getMaxTps(), 1000); } } \ No newline at end of file From 88798794742cbecd7dc21decd1daaa624ee22714 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Fri, 5 May 2023 12:10:39 +0800 Subject: [PATCH 0761/1197] feat(net):optimize sync service --- .../org/tron/common/parameter/CommonParameter.java | 3 +++ common/src/main/java/org/tron/core/Constant.java | 1 + .../src/main/java/org/tron/core/config/args/Args.java | 10 ++++++++++ .../net/messagehandler/ChainInventoryMsgHandler.java | 5 ++++- .../org/tron/core/net/service/sync/SyncService.java | 11 +++++++++-- 5 files changed, 27 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index caf74d61658..3036a72a87c 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -199,6 +199,9 @@ public class CommonParameter { @Getter @Setter public PublishConfig dnsPublishConfig; + @Getter + @Setter + public long syncFetchBatchNum; //If you are running a solidity node for java tron, this flag is set to true @Getter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index bcbfecb7904..b016be700fc 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -90,6 +90,7 @@ public class Constant { public static final String NODE_MAX_CONNECTIONS = "node.maxConnections"; public static final String NODE_MIN_CONNECTIONS = "node.minConnections"; public static final String NODE_MIN_ACTIVE_CONNECTIONS = "node.minActiveConnections"; + public static final String NODE_SYNC_FETCH_BATCH_NUM = "node.syncFetchBatchNum"; public static final String NODE_MAX_ACTIVE_NODES = "node.maxActiveNodes"; public static final String NODE_MAX_ACTIVE_NODES_WITH_SAME_IP = "node.maxActiveNodesWithSameIp"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 19962fbac8e..c16def9d934 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -146,6 +146,7 @@ public static void clearParam() { PARAMETER.nodeEnableIpv6 = false; PARAMETER.dnsTreeUrls = new ArrayList<>(); PARAMETER.dnsPublishConfig = null; + PARAMETER.syncFetchBatchNum = 1000; PARAMETER.rpcPort = 0; PARAMETER.rpcOnSolidityPort = 0; PARAMETER.rpcOnPBFTPort = 0; @@ -657,6 +658,15 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.dnsPublishConfig = loadDnsPublishConfig(config); + PARAMETER.syncFetchBatchNum = config.hasPath(Constant.NODE_SYNC_FETCH_BATCH_NUM) ? config + .getInt(Constant.NODE_SYNC_FETCH_BATCH_NUM) : 1000; + if (PARAMETER.syncFetchBatchNum > 2000) { + PARAMETER.syncFetchBatchNum = 2000; + } + if (PARAMETER.syncFetchBatchNum < 100) { + PARAMETER.syncFetchBatchNum = 100; + } + PARAMETER.rpcPort = config.hasPath(Constant.NODE_RPC_PORT) ? config.getInt(Constant.NODE_RPC_PORT) : 50051; diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java index d1ee974cc64..bd2e428418c 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java @@ -13,6 +13,7 @@ import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.config.Parameter.ChainConstant; import org.tron.core.config.Parameter.NetConstants; +import org.tron.core.config.args.Args; import org.tron.core.exception.P2pException; import org.tron.core.exception.P2pException.TypeEnum; import org.tron.core.net.TronNetDelegate; @@ -32,6 +33,8 @@ public class ChainInventoryMsgHandler implements TronMsgHandler { @Autowired private SyncService syncService; + private final long syncFetchBatchNum = Args.getInstance().getSyncFetchBatchNum(); + @Override public void processMessage(PeerConnection peer, TronMessage msg) throws P2pException { @@ -88,7 +91,7 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep peer.setFetchAble(true); if ((chainInventoryMessage.getRemainNum() == 0 && !peer.getSyncBlockToFetch().isEmpty()) || (chainInventoryMessage.getRemainNum() != 0 - && peer.getSyncBlockToFetch().size() > NetConstants.SYNC_FETCH_BATCH_NUM)) { + && peer.getSyncBlockToFetch().size() > syncFetchBatchNum)) { syncService.setFetchFlag(true); } else { syncService.syncNext(peer); diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 5f7ab11f6c9..12f317b88c5 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -21,7 +21,6 @@ import org.tron.common.utils.Pair; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.BlockCapsule.BlockId; -import org.tron.core.config.Parameter.NetConstants; import org.tron.core.config.args.Args; import org.tron.core.exception.P2pException; import org.tron.core.exception.P2pException.TypeEnum; @@ -65,6 +64,8 @@ public class SyncService { @Setter private volatile boolean fetchFlag = false; + private final long syncFetchBatchNum = Args.getInstance().getSyncFetchBatchNum(); + public void init() { fetchExecutor.scheduleWithFixedDelay(() -> { try { @@ -132,7 +133,7 @@ public void processBlock(PeerConnection peer, BlockMessage blockMessage) { handleFlag = true; if (peer.isIdle()) { if (peer.getRemainNum() > 0 - && peer.getSyncBlockToFetch().size() <= NetConstants.SYNC_FETCH_BATCH_NUM) { + && peer.getSyncBlockToFetch().size() <= syncFetchBatchNum) { syncNext(peer); } else { fetchFlag = true; @@ -250,10 +251,12 @@ private synchronized void handleSyncBlock() { } final boolean[] isProcessed = {true}; + final long[] solidNum = {0}; while (isProcessed[0]) { isProcessed[0] = false; + solidNum[0] = tronNetDelegate.getSolidBlockId().getNum(); blockWaitToProcess.forEach((msg, peerConnection) -> { synchronized (tronNetDelegate.getBlockLock()) { @@ -262,6 +265,10 @@ private synchronized void handleSyncBlock() { invalid(msg.getBlockId(), peerConnection); return; } + if (msg.getBlockId().getNum() <= solidNum[0]) { + blockWaitToProcess.remove(msg); + return; + } final boolean[] isFound = {false}; tronNetDelegate.getActivePeer().stream() .filter(peer -> msg.getBlockId().equals(peer.getSyncBlockToFetch().peek())) From 5cb0028fe593139cb6cb5df080bc7a7e5ecde184 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Fri, 5 May 2023 14:49:12 +0800 Subject: [PATCH 0762/1197] fix(test):fix unit test issue --- .../org/tron/core/net/services/SyncServiceTest.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java b/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java index 35fa6f4fd5c..4eebb7da12c 100644 --- a/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java @@ -183,11 +183,21 @@ public void testHandleSyncBlock() throws Exception { Map blockJustReceived = (Map) ReflectUtils.getFieldObject(service, "blockJustReceived"); + Protocol.BlockHeader.raw.Builder blockHeaderRawBuild = Protocol.BlockHeader.raw.newBuilder(); + Protocol.BlockHeader.raw blockHeaderRaw = blockHeaderRawBuild + .setNumber(100000) + .build(); - BlockCapsule blockCapsule = new BlockCapsule(Protocol.Block.newBuilder().build()); + // block header + Protocol.BlockHeader.Builder blockHeaderBuild = Protocol.BlockHeader.newBuilder(); + Protocol.BlockHeader blockHeader = blockHeaderBuild.setRawData(blockHeaderRaw).build(); + + BlockCapsule blockCapsule = new BlockCapsule(Protocol.Block.newBuilder() + .setBlockHeader(blockHeader).build()); BlockCapsule.BlockId blockId = blockCapsule.getBlockId(); + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); Channel c1 = mock(Channel.class); Mockito.when(c1.getInetSocketAddress()).thenReturn(a1); From 7a08ec0be9e4aef08182c5bf65c19ba8f6f92f3f Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Fri, 5 May 2023 16:49:44 +0800 Subject: [PATCH 0763/1197] feat(net):optimize sync service --- framework/src/main/java/org/tron/core/config/args/Args.java | 2 +- .../java/org/tron/core/net/service/sync/SyncService.java | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index c16def9d934..0eeb89197c0 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -659,7 +659,7 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.dnsPublishConfig = loadDnsPublishConfig(config); PARAMETER.syncFetchBatchNum = config.hasPath(Constant.NODE_SYNC_FETCH_BATCH_NUM) ? config - .getInt(Constant.NODE_SYNC_FETCH_BATCH_NUM) : 1000; + .getInt(Constant.NODE_SYNC_FETCH_BATCH_NUM) : 2000; if (PARAMETER.syncFetchBatchNum > 2000) { PARAMETER.syncFetchBatchNum = 2000; } diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 12f317b88c5..3ad59564e0c 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -251,12 +251,11 @@ private synchronized void handleSyncBlock() { } final boolean[] isProcessed = {true}; - final long[] solidNum = {0}; + long solidNum = tronNetDelegate.getSolidBlockId().getNum();; while (isProcessed[0]) { isProcessed[0] = false; - solidNum[0] = tronNetDelegate.getSolidBlockId().getNum(); blockWaitToProcess.forEach((msg, peerConnection) -> { synchronized (tronNetDelegate.getBlockLock()) { @@ -265,7 +264,7 @@ private synchronized void handleSyncBlock() { invalid(msg.getBlockId(), peerConnection); return; } - if (msg.getBlockId().getNum() <= solidNum[0]) { + if (msg.getBlockId().getNum() <= solidNum) { blockWaitToProcess.remove(msg); return; } From 1e3e3852c7d426b45122b5a6a80fe54198a38452 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Fri, 5 May 2023 17:26:08 +0800 Subject: [PATCH 0764/1197] feat(net):change the default value of syncFetchBatchNum --- framework/src/main/java/org/tron/core/config/args/Args.java | 2 +- .../main/java/org/tron/core/net/service/sync/SyncService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 0eeb89197c0..24762e856a1 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -146,7 +146,7 @@ public static void clearParam() { PARAMETER.nodeEnableIpv6 = false; PARAMETER.dnsTreeUrls = new ArrayList<>(); PARAMETER.dnsPublishConfig = null; - PARAMETER.syncFetchBatchNum = 1000; + PARAMETER.syncFetchBatchNum = 2000; PARAMETER.rpcPort = 0; PARAMETER.rpcOnSolidityPort = 0; PARAMETER.rpcOnPBFTPort = 0; diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 3ad59564e0c..9476b32fa46 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -251,7 +251,7 @@ private synchronized void handleSyncBlock() { } final boolean[] isProcessed = {true}; - long solidNum = tronNetDelegate.getSolidBlockId().getNum();; + long solidNum = tronNetDelegate.getSolidBlockId().getNum(); while (isProcessed[0]) { From 48254d9ec1761a78bb8c663dd653eb11a4773dc9 Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 8 May 2023 10:25:48 +0800 Subject: [PATCH 0765/1197] fix(vm): push0 instruction should push 1 operand on to the stack --- actuator/src/main/java/org/tron/core/vm/OperationRegistry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index 8aab51a1f31..e4b1e174702 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -630,7 +630,7 @@ public static void appendShangHaiOperations(JumpTable table) { BooleanSupplier proposal = VMConfig::allowTvmShanghai; table.set(new Operation( - Op.PUSH0, 0, 0, + Op.PUSH0, 0, 1, EnergyCost::getBaseTierCost, OperationActions::push0Action, proposal)); From c929ee348c76b48e0fd28325150e036dfc17baec Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 8 May 2023 11:35:13 +0800 Subject: [PATCH 0766/1197] feat(net): add unit test for P2pEventHandlerImpl --- .../tron/core/net/P2pEventHandlerImpl.java | 1 - .../core/net/P2pEventHandlerImplTest.java | 111 ++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 framework/src/test/java/org/tron/core/net/P2pEventHandlerImplTest.java diff --git a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java index 10f29ddb11c..10615b70ce3 100644 --- a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java +++ b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java @@ -1,7 +1,6 @@ package org.tron.core.net; import static org.tron.core.net.message.MessageTypes.INVENTORY; -import static org.tron.core.net.message.MessageTypes.TRX; import java.util.HashSet; import java.util.Set; diff --git a/framework/src/test/java/org/tron/core/net/P2pEventHandlerImplTest.java b/framework/src/test/java/org/tron/core/net/P2pEventHandlerImplTest.java new file mode 100644 index 00000000000..0008ec315d5 --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/P2pEventHandlerImplTest.java @@ -0,0 +1,111 @@ +package org.tron.core.net; + +import static org.mockito.Mockito.mock; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.Constant; +import org.tron.core.config.args.Args; +import org.tron.core.net.message.adv.InventoryMessage; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.service.statistics.PeerStatistics; +import org.tron.protos.Protocol; + +public class P2pEventHandlerImplTest { + + @Test + public void testProcessInventoryMessage() throws Exception { + String[] a = new String[0]; + Args.setParam(a, Constant.TESTNET_CONF); + CommonParameter parameter = CommonParameter.getInstance(); + parameter.setMaxTps(10); + + PeerStatistics peerStatistics = new PeerStatistics(); + + PeerConnection peer = mock(PeerConnection.class); + Mockito.when(peer.getPeerStatistics()).thenReturn(peerStatistics); + + P2pEventHandlerImpl p2pEventHandler = new P2pEventHandlerImpl(); + + Method method = p2pEventHandler.getClass() + .getDeclaredMethod("processMessage", PeerConnection.class, byte[].class); + method.setAccessible(true); + + int count = peer.getPeerStatistics().messageStatistics.tronInTrxInventoryElement + .getCount(10); + + Assert.assertEquals(0, count); + + List list = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + list.add(new Sha256Hash(i, new byte[32])); + } + + InventoryMessage msg = new InventoryMessage(list, Protocol.Inventory.InventoryType.TRX); + + method.invoke(p2pEventHandler, peer, msg.getSendBytes()); + + count = peer.getPeerStatistics().messageStatistics.tronInTrxInventoryElement.getCount(10); + + Assert.assertEquals(10, count); + + list.clear(); + for (int i = 0; i < 100; i++) { + list.add(new Sha256Hash(i, new byte[32])); + } + + msg = new InventoryMessage(list, Protocol.Inventory.InventoryType.TRX); + + method.invoke(p2pEventHandler, peer, msg.getSendBytes()); + + count = peer.getPeerStatistics().messageStatistics.tronInTrxInventoryElement.getCount(10); + + Assert.assertEquals(110, count); + + list.clear(); + for (int i = 0; i < 100; i++) { + list.add(new Sha256Hash(i, new byte[32])); + } + + msg = new InventoryMessage(list, Protocol.Inventory.InventoryType.TRX); + + method.invoke(p2pEventHandler, peer, msg.getSendBytes()); + + count = peer.getPeerStatistics().messageStatistics.tronInTrxInventoryElement.getCount(10); + + Assert.assertEquals(110, count); + + list.clear(); + for (int i = 0; i < 200; i++) { + list.add(new Sha256Hash(i, new byte[32])); + } + + msg = new InventoryMessage(list, Protocol.Inventory.InventoryType.BLOCK); + + method.invoke(p2pEventHandler, peer, msg.getSendBytes()); + + count = peer.getPeerStatistics().messageStatistics.tronInBlockInventoryElement.getCount(10); + + Assert.assertEquals(200, count); + + list.clear(); + for (int i = 0; i < 100; i++) { + list.add(new Sha256Hash(i, new byte[32])); + } + + msg = new InventoryMessage(list, Protocol.Inventory.InventoryType.BLOCK); + + method.invoke(p2pEventHandler, peer, msg.getSendBytes()); + + count = peer.getPeerStatistics().messageStatistics.tronInBlockInventoryElement.getCount(10); + + Assert.assertEquals(300, count); + + } +} From 1cd7c3e34aa4e50c7de3f699a267446d7b79e764 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 8 May 2023 15:10:07 +0800 Subject: [PATCH 0767/1197] feat(cofig): optimize rate.limiter configuration parsing --- .../java/org/tron/core/config/args/Args.java | 33 +++++++++---------- .../org/tron/common/config/args/ArgsTest.java | 8 +++-- framework/src/test/resources/config-test.conf | 10 ++++++ 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 8bd12bce061..79788332093 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -973,9 +973,7 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.RATE_LIMITER_GLOBAL_IP_QPS) ? config .getInt(Constant.RATE_LIMITER_GLOBAL_IP_QPS) : 10000; - PARAMETER.rateLimiterInitialization = - config.hasPath(Constant.RATE_LIMITER) ? getRateLimiterFromConfig(config) - : new RateLimiterInitialization(); + PARAMETER.rateLimiterInitialization = getRateLimiterFromConfig(config); PARAMETER.changedDelegation = config.hasPath(Constant.COMMITTEE_CHANGED_DELEGATION) ? config @@ -1214,21 +1212,22 @@ private static Account createAccount(final ConfigObject asset) { } private static RateLimiterInitialization getRateLimiterFromConfig( - final com.typesafe.config.Config config) { - + final com.typesafe.config.Config config) { RateLimiterInitialization initialization = new RateLimiterInitialization(); - ArrayList list1 = config - .getObjectList(Constant.RATE_LIMITER_HTTP).stream() - .map(RateLimiterInitialization::createHttpItem) - .collect(Collectors.toCollection(ArrayList::new)); - initialization.setHttpMap(list1); - - ArrayList list2 = config - .getObjectList(Constant.RATE_LIMITER_RPC).stream() - .map(RateLimiterInitialization::createRpcItem) - .collect(Collectors.toCollection(ArrayList::new)); - - initialization.setRpcMap(list2); + if (config.hasPath(Constant.RATE_LIMITER_HTTP)) { + ArrayList list1 = config + .getObjectList(Constant.RATE_LIMITER_HTTP).stream() + .map(RateLimiterInitialization::createHttpItem) + .collect(Collectors.toCollection(ArrayList::new)); + initialization.setHttpMap(list1); + } + if (config.hasPath(Constant.RATE_LIMITER_RPC)) { + ArrayList list2 = config + .getObjectList(Constant.RATE_LIMITER_RPC).stream() + .map(RateLimiterInitialization::createRpcItem) + .collect(Collectors.toCollection(ArrayList::new)); + initialization.setRpcMap(list2); + } return initialization; } diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index c487125d3e3..6b85c69867b 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -5,6 +5,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.tron.common.parameter.RateLimiterInitialization; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.config.args.Args; @@ -34,9 +35,12 @@ public void testConfig() { Assert.assertEquals(Args.getInstance().getBlockCacheTimeout(), 60); Assert.assertEquals(Args.getInstance().isNodeDetectEnable(), false); Assert.assertFalse(Args.getInstance().isNodeEffectiveCheckEnable()); - Assert.assertEquals(Args.getInstance().getRateLimiterGlobalQps(), 50000); - Assert.assertEquals(Args.getInstance().getRateLimiterGlobalIpQps(), 10000); + Assert.assertEquals(Args.getInstance().getRateLimiterGlobalQps(), 1000); + Assert.assertEquals(Args.getInstance().getRateLimiterGlobalIpQps(), 1000); Assert.assertEquals(Args.getInstance().p2pDisable, true); Assert.assertEquals(Args.getInstance().getMaxTps(), 1000); + RateLimiterInitialization rateLimiter = Args.getInstance().getRateLimiterInitialization(); + Assert.assertEquals(rateLimiter.getHttpMap().size(), 1); + Assert.assertEquals(rateLimiter.getRpcMap().size(), 0); } } \ No newline at end of file diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index dea5d72961d..2ace5fab538 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -346,5 +346,15 @@ committee = { allowCreationOfContracts = 1 //mainnet:0 (reset by committee),test:1 } +rate.limiter.global.qps = 1000 +rate.limiter.global.ip.qps = 1000 +rate.limiter.http = [ + { + component = "GetNowBlockServlet", + strategy = "GlobalPreemptibleAdapter", + paramString = "permit=1" + } +] + node.dynamicConfig.enable = true node.dynamicConfig.checkInterval = 0 \ No newline at end of file From 93ba0a1f2216067d955edb2f0114b52113d596cc Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 9 May 2023 11:42:21 +0800 Subject: [PATCH 0768/1197] test(net): add MessageHandlerTest --- .../service/handshake/HandshakeService.java | 10 ++ .../messagehandler/MessageHandlerTest.java | 144 ++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java index aa6567d1cda..e7f4f89826b 100644 --- a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -35,6 +35,7 @@ public void startHandshake(PeerConnection peer) { public void processHelloMessage(PeerConnection peer, HelloMessage msg) { if (peer.getHelloMessageReceive() != null) { + System.out.println("11111111111"); logger.warn("Peer {} receive dup hello message", peer.getInetSocketAddress()); peer.disconnect(ReasonCode.BAD_PROTOCOL); return; @@ -42,12 +43,14 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { TronNetService.getP2pService().updateNodeId(peer.getChannel(), msg.getFrom().getHexId()); if (peer.isDisconnect()) { + System.out.println("222222222"); logger.info("Duplicate Peer {}", peer.getInetSocketAddress()); peer.disconnect(ReasonCode.DUPLICATE_PEER); return; } if (!msg.valid()) { + System.out.println("333333333"); logger.warn("Peer {} invalid hello message parameters, " + "GenesisBlockId: {}, SolidBlockId: {}, HeadBlockId: {}", peer.getInetSocketAddress(), @@ -61,6 +64,7 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { peer.setAddress(msg.getHelloMessage().getAddress()); if (!relayService.checkHelloMessage(msg, peer.getChannel())) { + System.out.println("44444444444"); peer.disconnect(ReasonCode.UNEXPECTED_IDENTITY); return; } @@ -68,6 +72,7 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { long headBlockNum = chainBaseManager.getHeadBlockNum(); long lowestBlockNum = msg.getLowestBlockNum(); if (lowestBlockNum > headBlockNum) { + System.out.println("55555555555"); logger.info("Peer {} miss block, lowestBlockNum:{}, headBlockNum:{}", peer.getInetSocketAddress(), lowestBlockNum, headBlockNum); peer.disconnect(ReasonCode.LIGHT_NODE_SYNC_FAIL); @@ -75,6 +80,7 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { } if (msg.getVersion() != Args.getInstance().getNodeP2pVersion()) { + System.out.println("6666666666"); logger.info("Peer {} different p2p version, peer->{}, me->{}", peer.getInetSocketAddress(), msg.getVersion(), Args.getInstance().getNodeP2pVersion()); @@ -84,6 +90,7 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { if (!Arrays.equals(chainBaseManager.getGenesisBlockId().getBytes(), msg.getGenesisBlockId().getBytes())) { + System.out.println("7777777777"); logger.info("Peer {} different genesis block, peer->{}, me->{}", peer.getInetSocketAddress(), msg.getGenesisBlockId().getString(), @@ -94,6 +101,7 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { if (chainBaseManager.getSolidBlockId().getNum() >= msg.getSolidBlockId().getNum() && !chainBaseManager.containBlockInMainChain(msg.getSolidBlockId())) { + System.out.println("88888888888"); logger.info("Peer {} different solid block, peer->{}, me->{}", peer.getInetSocketAddress(), msg.getSolidBlockId().getString(), @@ -104,6 +112,7 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { if (msg.getHeadBlockId().getNum() < chainBaseManager.getHeadBlockId().getNum() && peer.getInetSocketAddress().equals(effectiveCheckService.getCur())) { + System.out.println("99999999999"); logger.info("Peer's head block {} is below than we, peer->{}, me->{}", peer.getInetSocketAddress(), msg.getHeadBlockId().getNum(), chainBaseManager.getHeadBlockId().getNum()); @@ -111,6 +120,7 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { return; } + System.out.println("000000000"); peer.setHelloMessageReceive(msg); peer.getChannel().updateAvgLatency( diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java new file mode 100644 index 00000000000..1a47cec008d --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java @@ -0,0 +1,144 @@ +package org.tron.core.net.messagehandler; + + +import static org.mockito.Mockito.mock; + +import com.google.protobuf.ByteString; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Collections; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.context.ApplicationContext; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.ReflectUtils; +import org.tron.common.utils.Sha256Hash; +import org.tron.consensus.pbft.message.PbftMessage; +import org.tron.core.ChainBaseManager; +import org.tron.core.Constant; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.net.P2pEventHandlerImpl; +import org.tron.core.net.TronNetService; +import org.tron.core.net.message.handshake.HelloMessage; +import org.tron.core.net.message.keepalive.PingMessage; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.peer.PeerManager; +import org.tron.p2p.P2pConfig; +import org.tron.p2p.base.Parameter; +import org.tron.p2p.connection.Channel; +import org.tron.p2p.discover.Node; +import org.tron.p2p.utils.NetUtil; +import org.tron.protos.Protocol; +import org.tron.protos.Protocol.ReasonCode; + +public class MessageHandlerTest { + + private static TronApplicationContext context; + private PeerConnection peer; + private static P2pEventHandlerImpl p2pEventHandler; + private static ApplicationContext ctx; + private static String dbPath = "output-message-handler-test"; + + + @BeforeClass + public static void init() throws Exception { + Args.setParam(new String[] {"--output-directory", dbPath, "--debug"}, + Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + p2pEventHandler = context.getBean(P2pEventHandlerImpl.class); + ctx = (ApplicationContext) ReflectUtils.getFieldObject(p2pEventHandler, "ctx"); + + TronNetService tronNetService = context.getBean(TronNetService.class); + Parameter.p2pConfig = new P2pConfig(); + ReflectUtils.setFieldValue(tronNetService, "p2pConfig", Parameter.p2pConfig); + } + + + @Before + public void clearPeers() throws NoSuchFieldException, IllegalAccessException { + Field field = PeerManager.class.getDeclaredField("peers"); + field.setAccessible(true); + field.set(PeerManager.class, Collections.synchronizedList(new ArrayList<>())); + } + + @Test + public void testPbft() { + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); + Channel c1 = mock(Channel.class); + Mockito.when(c1.getInetSocketAddress()).thenReturn(a1); + Mockito.when(c1.getInetAddress()).thenReturn(a1.getAddress()); + p2pEventHandler.onConnect(c1); + Assert.assertEquals(1, PeerManager.getPeers().size()); + Assert.assertFalse(c1.isDisconnect()); + + peer = PeerManager.getPeers().get(0); + BlockCapsule blockCapsule = new BlockCapsule(1, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), ByteString.EMPTY); + PbftMessage pbftMessage = PbftMessage.fullNodePrePrepareBlockMsg(blockCapsule, 0L); + p2pEventHandler.onMessage(peer.getChannel(), pbftMessage.getSendBytes()); + + InetSocketAddress a2 = new InetSocketAddress("127.0.0.1", 10002); + Channel c2 = mock(Channel.class); + Mockito.when(c2.getInetSocketAddress()).thenReturn(a2); + Mockito.when(c2.getInetAddress()).thenReturn(a2.getAddress()); + p2pEventHandler.onMessage(c2, pbftMessage.getSendBytes()); + + Assert.assertEquals(1, PeerManager.getPeers().size()); + } + + @Test + public void testPing() { + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); + Channel c1 = mock(Channel.class); + Mockito.when(c1.getInetSocketAddress()).thenReturn(a1); + Mockito.when(c1.getInetAddress()).thenReturn(a1.getAddress()); + PeerManager.add(ctx, c1); + + PingMessage pingMessage = new PingMessage(); + p2pEventHandler.onMessage(c1, pingMessage.getSendBytes()); + Assert.assertEquals(1, PeerManager.getPeers().size()); + } + + @Test + public void testHelloMessage() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); + Channel c1 = mock(Channel.class); + Mockito.when(c1.getInetSocketAddress()).thenReturn(a1); + Mockito.when(c1.getInetAddress()).thenReturn(a1.getAddress()); + PeerManager.add(ctx, c1); + + Method method = p2pEventHandler.getClass() + .getDeclaredMethod("onMessage", Channel.class, byte[].class); + method.setAccessible(true); + + //ok + peer = PeerManager.getPeers().get(0); + Node node = new Node(NetUtil.getNodeId(), + a1.getAddress().getHostAddress(), + null, + a1.getPort()); + HelloMessage helloMessage = new HelloMessage(node, System.currentTimeMillis(), + ChainBaseManager.getChainBaseManager()); + method.invoke(p2pEventHandler, c1, helloMessage.getSendBytes()); + + //dup hello message + peer.setHelloMessageReceive(helloMessage); + method.invoke(p2pEventHandler, c1, helloMessage.getSendBytes()); + + //dup peer + peer.setHelloMessageReceive(null); + Mockito.when(c1.isDisconnect()).thenReturn(true); + method.invoke(p2pEventHandler, c1, helloMessage.getSendBytes()); + +// Assert.assertEquals(1, PeerManager.getPeers().size()); + } +} From cf50c54e0a40f121f2d58490c9c9e2f3248611fd Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 9 May 2023 15:31:01 +0800 Subject: [PATCH 0769/1197] feat(db): change log --- .../messagehandler/MessageHandlerTest.java | 92 +++++++++++++++++-- 1 file changed, 82 insertions(+), 10 deletions(-) diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java index 1a47cec008d..56e7ea1afcd 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java @@ -2,6 +2,7 @@ import static org.mockito.Mockito.mock; +import static org.tron.core.net.message.handshake.HelloMessage.getEndpointFromNode; import com.google.protobuf.ByteString; import java.lang.reflect.Field; @@ -36,7 +37,9 @@ import org.tron.p2p.connection.Channel; import org.tron.p2p.discover.Node; import org.tron.p2p.utils.NetUtil; +import org.tron.protos.Discover.Endpoint; import org.tron.protos.Protocol; +import org.tron.protos.Protocol.HelloMessage.Builder; import org.tron.protos.Protocol.ReasonCode; public class MessageHandlerTest { @@ -63,10 +66,14 @@ public static void init() throws Exception { @Before - public void clearPeers() throws NoSuchFieldException, IllegalAccessException { - Field field = PeerManager.class.getDeclaredField("peers"); - field.setAccessible(true); - field.set(PeerManager.class, Collections.synchronizedList(new ArrayList<>())); + public void clearPeers() { + try { + Field field = PeerManager.class.getDeclaredField("peers"); + field.setAccessible(true); + field.set(PeerManager.class, Collections.synchronizedList(new ArrayList<>())); + } catch (NoSuchFieldException | IllegalAccessException e) { + //ignore + } } @Test @@ -115,30 +122,95 @@ public void testHelloMessage() Mockito.when(c1.getInetSocketAddress()).thenReturn(a1); Mockito.when(c1.getInetAddress()).thenReturn(a1.getAddress()); PeerManager.add(ctx, c1); + peer = PeerManager.getPeers().get(0); Method method = p2pEventHandler.getClass() - .getDeclaredMethod("onMessage", Channel.class, byte[].class); + .getDeclaredMethod("processMessage", PeerConnection.class, byte[].class); method.setAccessible(true); //ok - peer = PeerManager.getPeers().get(0); Node node = new Node(NetUtil.getNodeId(), a1.getAddress().getHostAddress(), null, a1.getPort()); HelloMessage helloMessage = new HelloMessage(node, System.currentTimeMillis(), ChainBaseManager.getChainBaseManager()); - method.invoke(p2pEventHandler, c1, helloMessage.getSendBytes()); + method.invoke(p2pEventHandler, peer, helloMessage.getSendBytes()); //dup hello message peer.setHelloMessageReceive(helloMessage); - method.invoke(p2pEventHandler, c1, helloMessage.getSendBytes()); + method.invoke(p2pEventHandler, peer, helloMessage.getSendBytes()); //dup peer peer.setHelloMessageReceive(null); Mockito.when(c1.isDisconnect()).thenReturn(true); - method.invoke(p2pEventHandler, c1, helloMessage.getSendBytes()); + method.invoke(p2pEventHandler, peer, helloMessage.getSendBytes()); + + //invalid hello message + try { + Protocol.HelloMessage.Builder builder = + getHelloMessageBuilder(node, System.currentTimeMillis(), + ChainBaseManager.getChainBaseManager()); + + BlockCapsule.BlockId hid = ChainBaseManager.getChainBaseManager().getHeadBlockId(); + Protocol.HelloMessage.BlockId hBlockId = Protocol.HelloMessage.BlockId.newBuilder() + .setHash(ByteString.copyFrom(new byte[0])) + .setNumber(hid.getNum()) + .build(); + builder.setHeadBlockId(hBlockId); + helloMessage = new HelloMessage(builder.build().toByteArray()); + Assert.assertTrue(!helloMessage.valid()); + } catch (Exception e) { + Assert.fail(); + } + + //relay check service check failed + Args.getInstance().fastForward = true; + clearPeers(); + try { + Protocol.HelloMessage.Builder builder = + getHelloMessageBuilder(node, System.currentTimeMillis(), + ChainBaseManager.getChainBaseManager()); + helloMessage = new HelloMessage(builder.build().toByteArray()); + method.invoke(p2pEventHandler, peer, helloMessage.getSendBytes()); + } catch (Exception e) { + Assert.fail(); + } + + } -// Assert.assertEquals(1, PeerManager.getPeers().size()); + private Protocol.HelloMessage.Builder getHelloMessageBuilder(Node from, long timestamp, + ChainBaseManager chainBaseManager) throws Exception { + Endpoint fromEndpoint = getEndpointFromNode(from); + + BlockCapsule.BlockId gid = chainBaseManager.getGenesisBlockId(); + Protocol.HelloMessage.BlockId gBlockId = Protocol.HelloMessage.BlockId.newBuilder() + .setHash(gid.getByteString()) + .setNumber(gid.getNum()) + .build(); + + BlockCapsule.BlockId sid = chainBaseManager.getSolidBlockId(); + Protocol.HelloMessage.BlockId sBlockId = Protocol.HelloMessage.BlockId.newBuilder() + .setHash(sid.getByteString()) + .setNumber(sid.getNum()) + .build(); + + BlockCapsule.BlockId hid = chainBaseManager.getHeadBlockId(); + Protocol.HelloMessage.BlockId hBlockId = Protocol.HelloMessage.BlockId.newBuilder() + .setHash(hid.getByteString()) + .setNumber(hid.getNum()) + .build(); + Builder builder = Protocol.HelloMessage.newBuilder(); + builder.setFrom(fromEndpoint); + builder.setVersion(Args.getInstance().getNodeP2pVersion()); + builder.setTimestamp(timestamp); + builder.setGenesisBlockId(gBlockId); + builder.setSolidBlockId(sBlockId); + builder.setHeadBlockId(hBlockId); + builder.setNodeType(chainBaseManager.getNodeType().getType()); + builder.setLowestBlockNum(chainBaseManager.isLiteNode() + ? chainBaseManager.getLowestBlockNum() : 0); + + return builder; } } From 446f8909df23ed00856d2e6fb2a4bd7da4bf6553 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 9 May 2023 18:54:27 +0800 Subject: [PATCH 0770/1197] feat(db): add HandShakeServiceTest --- .../messagehandler/MessageHandlerTest.java | 120 +------- .../net/services/HandShakeServiceTest.java | 265 ++++++++++++++++++ 2 files changed, 274 insertions(+), 111 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java index 56e7ea1afcd..e0752484642 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java @@ -2,15 +2,14 @@ import static org.mockito.Mockito.mock; -import static org.tron.core.net.message.handshake.HelloMessage.getEndpointFromNode; import com.google.protobuf.ByteString; +import java.io.File; import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Collections; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; @@ -18,29 +17,22 @@ import org.mockito.Mockito; import org.springframework.context.ApplicationContext; import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.FileUtil; import org.tron.common.utils.ReflectUtils; import org.tron.common.utils.Sha256Hash; import org.tron.consensus.pbft.message.PbftMessage; -import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.net.P2pEventHandlerImpl; import org.tron.core.net.TronNetService; -import org.tron.core.net.message.handshake.HelloMessage; import org.tron.core.net.message.keepalive.PingMessage; import org.tron.core.net.peer.PeerConnection; import org.tron.core.net.peer.PeerManager; import org.tron.p2p.P2pConfig; import org.tron.p2p.base.Parameter; import org.tron.p2p.connection.Channel; -import org.tron.p2p.discover.Node; -import org.tron.p2p.utils.NetUtil; -import org.tron.protos.Discover.Endpoint; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.HelloMessage.Builder; -import org.tron.protos.Protocol.ReasonCode; public class MessageHandlerTest { @@ -64,6 +56,12 @@ public static void init() throws Exception { ReflectUtils.setFieldValue(tronNetService, "p2pConfig", Parameter.p2pConfig); } + @AfterClass + public static void destroy() { + Args.clearParam(); + context.destroy(); + FileUtil.deleteDir(new File(dbPath)); + } @Before public void clearPeers() { @@ -113,104 +111,4 @@ public void testPing() { p2pEventHandler.onMessage(c1, pingMessage.getSendBytes()); Assert.assertEquals(1, PeerManager.getPeers().size()); } - - @Test - public void testHelloMessage() - throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); - Channel c1 = mock(Channel.class); - Mockito.when(c1.getInetSocketAddress()).thenReturn(a1); - Mockito.when(c1.getInetAddress()).thenReturn(a1.getAddress()); - PeerManager.add(ctx, c1); - peer = PeerManager.getPeers().get(0); - - Method method = p2pEventHandler.getClass() - .getDeclaredMethod("processMessage", PeerConnection.class, byte[].class); - method.setAccessible(true); - - //ok - Node node = new Node(NetUtil.getNodeId(), - a1.getAddress().getHostAddress(), - null, - a1.getPort()); - HelloMessage helloMessage = new HelloMessage(node, System.currentTimeMillis(), - ChainBaseManager.getChainBaseManager()); - method.invoke(p2pEventHandler, peer, helloMessage.getSendBytes()); - - //dup hello message - peer.setHelloMessageReceive(helloMessage); - method.invoke(p2pEventHandler, peer, helloMessage.getSendBytes()); - - //dup peer - peer.setHelloMessageReceive(null); - Mockito.when(c1.isDisconnect()).thenReturn(true); - method.invoke(p2pEventHandler, peer, helloMessage.getSendBytes()); - - //invalid hello message - try { - Protocol.HelloMessage.Builder builder = - getHelloMessageBuilder(node, System.currentTimeMillis(), - ChainBaseManager.getChainBaseManager()); - - BlockCapsule.BlockId hid = ChainBaseManager.getChainBaseManager().getHeadBlockId(); - Protocol.HelloMessage.BlockId hBlockId = Protocol.HelloMessage.BlockId.newBuilder() - .setHash(ByteString.copyFrom(new byte[0])) - .setNumber(hid.getNum()) - .build(); - builder.setHeadBlockId(hBlockId); - helloMessage = new HelloMessage(builder.build().toByteArray()); - Assert.assertTrue(!helloMessage.valid()); - } catch (Exception e) { - Assert.fail(); - } - - //relay check service check failed - Args.getInstance().fastForward = true; - clearPeers(); - try { - Protocol.HelloMessage.Builder builder = - getHelloMessageBuilder(node, System.currentTimeMillis(), - ChainBaseManager.getChainBaseManager()); - helloMessage = new HelloMessage(builder.build().toByteArray()); - method.invoke(p2pEventHandler, peer, helloMessage.getSendBytes()); - } catch (Exception e) { - Assert.fail(); - } - - } - - private Protocol.HelloMessage.Builder getHelloMessageBuilder(Node from, long timestamp, - ChainBaseManager chainBaseManager) throws Exception { - Endpoint fromEndpoint = getEndpointFromNode(from); - - BlockCapsule.BlockId gid = chainBaseManager.getGenesisBlockId(); - Protocol.HelloMessage.BlockId gBlockId = Protocol.HelloMessage.BlockId.newBuilder() - .setHash(gid.getByteString()) - .setNumber(gid.getNum()) - .build(); - - BlockCapsule.BlockId sid = chainBaseManager.getSolidBlockId(); - Protocol.HelloMessage.BlockId sBlockId = Protocol.HelloMessage.BlockId.newBuilder() - .setHash(sid.getByteString()) - .setNumber(sid.getNum()) - .build(); - - BlockCapsule.BlockId hid = chainBaseManager.getHeadBlockId(); - Protocol.HelloMessage.BlockId hBlockId = Protocol.HelloMessage.BlockId.newBuilder() - .setHash(hid.getByteString()) - .setNumber(hid.getNum()) - .build(); - Builder builder = Protocol.HelloMessage.newBuilder(); - builder.setFrom(fromEndpoint); - builder.setVersion(Args.getInstance().getNodeP2pVersion()); - builder.setTimestamp(timestamp); - builder.setGenesisBlockId(gBlockId); - builder.setSolidBlockId(sBlockId); - builder.setHeadBlockId(hBlockId); - builder.setNodeType(chainBaseManager.getNodeType().getType()); - builder.setLowestBlockNum(chainBaseManager.isLiteNode() - ? chainBaseManager.getLowestBlockNum() : 0); - - return builder; - } } diff --git a/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java b/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java new file mode 100644 index 00000000000..d28903965e7 --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java @@ -0,0 +1,265 @@ +package org.tron.core.net.services; + +import static org.mockito.Mockito.mock; +import static org.tron.core.net.message.handshake.HelloMessage.getEndpointFromNode; + +import com.google.protobuf.ByteString; +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Collections; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.context.ApplicationContext; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.ReflectUtils; +import org.tron.common.utils.Sha256Hash; +import org.tron.consensus.pbft.message.PbftMessage; +import org.tron.core.ChainBaseManager; +import org.tron.core.Constant; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.net.P2pEventHandlerImpl; +import org.tron.core.net.TronNetService; +import org.tron.core.net.message.handshake.HelloMessage; +import org.tron.core.net.message.keepalive.PingMessage; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.peer.PeerManager; +import org.tron.p2p.P2pConfig; +import org.tron.p2p.base.Parameter; +import org.tron.p2p.connection.Channel; +import org.tron.p2p.discover.Node; +import org.tron.p2p.utils.NetUtil; +import org.tron.protos.Discover.Endpoint; +import org.tron.protos.Protocol; +import org.tron.protos.Protocol.HelloMessage.Builder; + +public class HandShakeServiceTest { + + private static TronApplicationContext context; + private PeerConnection peer; + private static P2pEventHandlerImpl p2pEventHandler; + private static ApplicationContext ctx; + private static String dbPath = "output-message-handler-test"; + + + @BeforeClass + public static void init() throws Exception { + Args.setParam(new String[] {"--output-directory", dbPath, "--debug"}, + Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + p2pEventHandler = context.getBean(P2pEventHandlerImpl.class); + ctx = (ApplicationContext) ReflectUtils.getFieldObject(p2pEventHandler, "ctx"); + + TronNetService tronNetService = context.getBean(TronNetService.class); + Parameter.p2pConfig = new P2pConfig(); + ReflectUtils.setFieldValue(tronNetService, "p2pConfig", Parameter.p2pConfig); + } + + @AfterClass + public static void destroy() { + Args.clearParam(); + context.destroy(); + FileUtil.deleteDir(new File(dbPath)); + } + + @Before + public void clearPeers() { + try { + Field field = PeerManager.class.getDeclaredField("peers"); + field.setAccessible(true); + field.set(PeerManager.class, Collections.synchronizedList(new ArrayList<>())); + } catch (NoSuchFieldException | IllegalAccessException e) { + //ignore + } + } + + @Test + public void testOkHelloMessage() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); + Channel c1 = mock(Channel.class); + Mockito.when(c1.getInetSocketAddress()).thenReturn(a1); + Mockito.when(c1.getInetAddress()).thenReturn(a1.getAddress()); + PeerManager.add(ctx, c1); + peer = PeerManager.getPeers().get(0); + + Method method = p2pEventHandler.getClass() + .getDeclaredMethod("processMessage", PeerConnection.class, byte[].class); + method.setAccessible(true); + + //ok + Node node = new Node(NetUtil.getNodeId(), a1.getAddress().getHostAddress(), null, a1.getPort()); + HelloMessage helloMessage = new HelloMessage(node, System.currentTimeMillis(), + ChainBaseManager.getChainBaseManager()); + method.invoke(p2pEventHandler, peer, helloMessage.getSendBytes()); + + //dup hello message + peer.setHelloMessageReceive(helloMessage); + method.invoke(p2pEventHandler, peer, helloMessage.getSendBytes()); + + //dup peer + peer.setHelloMessageReceive(null); + Mockito.when(c1.isDisconnect()).thenReturn(true); + method.invoke(p2pEventHandler, peer, helloMessage.getSendBytes()); + } + + @Test + public void testInvalidHelloMessage() { + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); + Node node = new Node(NetUtil.getNodeId(), a1.getAddress().getHostAddress(), null, a1.getPort()); + Protocol.HelloMessage.Builder builder = + getHelloMessageBuilder(node, System.currentTimeMillis(), + ChainBaseManager.getChainBaseManager()); + //block hash is empty + try { + BlockCapsule.BlockId hid = ChainBaseManager.getChainBaseManager().getHeadBlockId(); + Protocol.HelloMessage.BlockId hBlockId = Protocol.HelloMessage.BlockId.newBuilder() + .setHash(ByteString.copyFrom(new byte[0])) + .setNumber(hid.getNum()) + .build(); + builder.setHeadBlockId(hBlockId); + HelloMessage helloMessage = new HelloMessage(builder.build().toByteArray()); + Assert.assertTrue(!helloMessage.valid()); + } catch (Exception e) { + Assert.fail(); + } + } + + @Test + public void testRelayHelloMessage() throws NoSuchMethodException { + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); + Channel c1 = mock(Channel.class); + Mockito.when(c1.getInetSocketAddress()).thenReturn(a1); + Mockito.when(c1.getInetAddress()).thenReturn(a1.getAddress()); + PeerManager.add(ctx, c1); + peer = PeerManager.getPeers().get(0); + + Method method = p2pEventHandler.getClass() + .getDeclaredMethod("processMessage", PeerConnection.class, byte[].class); + method.setAccessible(true); + + //address is empty + Args.getInstance().fastForward = true; + clearPeers(); + Node node2 = new Node(NetUtil.getNodeId(), a1.getAddress().getHostAddress(), null, 10002); + Protocol.HelloMessage.Builder builder = + getHelloMessageBuilder(node2, System.currentTimeMillis(), + ChainBaseManager.getChainBaseManager()); + + try { + HelloMessage helloMessage = new HelloMessage(builder.build().toByteArray()); + method.invoke(p2pEventHandler, peer, helloMessage.getSendBytes()); + } catch (Exception e) { + Assert.fail(); + } + Args.getInstance().fastForward = false; + } + + @Test + public void testLowAndGenesisBlockNum() throws NoSuchMethodException { + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); + Channel c1 = mock(Channel.class); + Mockito.when(c1.getInetSocketAddress()).thenReturn(a1); + Mockito.when(c1.getInetAddress()).thenReturn(a1.getAddress()); + PeerManager.add(ctx, c1); + peer = PeerManager.getPeers().get(0); + + Method method = p2pEventHandler.getClass() + .getDeclaredMethod("processMessage", PeerConnection.class, byte[].class); + method.setAccessible(true); + + Node node2 = new Node(NetUtil.getNodeId(), a1.getAddress().getHostAddress(), null, 10002); + + //lowestBlockNum > headBlockNum + Protocol.HelloMessage.Builder builder = + getHelloMessageBuilder(node2, System.currentTimeMillis(), + ChainBaseManager.getChainBaseManager()); + builder.setLowestBlockNum(ChainBaseManager.getChainBaseManager().getLowestBlockNum() + 1); + try { + HelloMessage helloMessage = new HelloMessage(builder.build().toByteArray()); + method.invoke(p2pEventHandler, peer, helloMessage.getSendBytes()); + } catch (Exception e) { + Assert.fail(); + } + + //genesisBlock is not equal + builder = getHelloMessageBuilder(node2, System.currentTimeMillis(), + ChainBaseManager.getChainBaseManager()); + BlockCapsule.BlockId gid = ChainBaseManager.getChainBaseManager().getGenesisBlockId(); + Protocol.HelloMessage.BlockId gBlockId = Protocol.HelloMessage.BlockId.newBuilder() + .setHash(gid.getByteString()) + .setNumber(gid.getNum() + 1) + .build(); + builder.setGenesisBlockId(gBlockId); + try { + HelloMessage helloMessage = new HelloMessage(builder.build().toByteArray()); + method.invoke(p2pEventHandler, peer, helloMessage.getSendBytes()); + } catch (Exception e) { + Assert.fail(); + } + + //solidityBlock is small than us, but not contained + builder = getHelloMessageBuilder(node2, System.currentTimeMillis(), + ChainBaseManager.getChainBaseManager()); + BlockCapsule.BlockId sid = ChainBaseManager.getChainBaseManager().getSolidBlockId(); + Protocol.HelloMessage.BlockId sBlockId = Protocol.HelloMessage.BlockId.newBuilder() + .setHash(ByteString.copyFrom( + ByteArray.fromHex("0304f784e4e7bae517bcab94c3e0c9214fb4ac7ff9d7d5a937d1f40031f87b81") + .getBytes())) + .setNumber(sid.getNum()) + .build(); + builder.setSolidBlockId(sBlockId); + try { + HelloMessage helloMessage = new HelloMessage(builder.build().toByteArray()); + method.invoke(p2pEventHandler, peer, helloMessage.getSendBytes()); + } catch (Exception e) { + Assert.fail(); + } + } + + private Protocol.HelloMessage.Builder getHelloMessageBuilder(Node from, long timestamp, + ChainBaseManager chainBaseManager) { + Endpoint fromEndpoint = getEndpointFromNode(from); + + BlockCapsule.BlockId gid = chainBaseManager.getGenesisBlockId(); + Protocol.HelloMessage.BlockId gBlockId = Protocol.HelloMessage.BlockId.newBuilder() + .setHash(gid.getByteString()) + .setNumber(gid.getNum()) + .build(); + + BlockCapsule.BlockId sid = chainBaseManager.getSolidBlockId(); + Protocol.HelloMessage.BlockId sBlockId = Protocol.HelloMessage.BlockId.newBuilder() + .setHash(sid.getByteString()) + .setNumber(sid.getNum()) + .build(); + + BlockCapsule.BlockId hid = chainBaseManager.getHeadBlockId(); + Protocol.HelloMessage.BlockId hBlockId = Protocol.HelloMessage.BlockId.newBuilder() + .setHash(hid.getByteString()) + .setNumber(hid.getNum()) + .build(); + Builder builder = Protocol.HelloMessage.newBuilder(); + builder.setFrom(fromEndpoint); + builder.setVersion(Args.getInstance().getNodeP2pVersion()); + builder.setTimestamp(timestamp); + builder.setGenesisBlockId(gBlockId); + builder.setSolidBlockId(sBlockId); + builder.setHeadBlockId(hBlockId); + builder.setNodeType(chainBaseManager.getNodeType().getType()); + builder.setLowestBlockNum(chainBaseManager.isLiteNode() + ? chainBaseManager.getLowestBlockNum() : 0); + + return builder; + } +} From 146c9f74c0ff44323b3e79e72c87c3e7aebfa257 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Wed, 10 May 2023 18:53:57 +0800 Subject: [PATCH 0771/1197] fix(pbft):optimize pbft logic --- .../org/tron/consensus/pbft/PbftManager.java | 4 +-- .../consensus/pbft/PbftMessageHandle.java | 32 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/consensus/src/main/java/org/tron/consensus/pbft/PbftManager.java b/consensus/src/main/java/org/tron/consensus/pbft/PbftManager.java index 8d12ecbd3f4..2f42524e03e 100644 --- a/consensus/src/main/java/org/tron/consensus/pbft/PbftManager.java +++ b/consensus/src/main/java/org/tron/consensus/pbft/PbftManager.java @@ -44,7 +44,7 @@ public void blockPrePrepare(BlockCapsule block, long epoch) { } if (!pbftMessageHandle.isSyncing()) { if (Param.getInstance().isEnable()) { - for (Miner miner : pbftMessageHandle.getSrMinerList()) { + for (Miner miner : pbftMessageHandle.getSrMinerList(epoch)) { doAction(PbftMessage.prePrepareBlockMsg(block, epoch, miner)); } } else { @@ -59,7 +59,7 @@ public void srPrePrepare(BlockCapsule block, List currentWitness, lo } if (!pbftMessageHandle.isSyncing()) { if (Param.getInstance().isEnable()) { - for (Miner miner : pbftMessageHandle.getSrMinerList()) { + for (Miner miner : pbftMessageHandle.getSrMinerList(epoch)) { doAction(PbftMessage.prePrepareSRLMsg(block, currentWitness, epoch, miner)); } } else { diff --git a/consensus/src/main/java/org/tron/consensus/pbft/PbftMessageHandle.java b/consensus/src/main/java/org/tron/consensus/pbft/PbftMessageHandle.java index f2ef7b43ef0..ea7b00802b2 100644 --- a/consensus/src/main/java/org/tron/consensus/pbft/PbftMessageHandle.java +++ b/consensus/src/main/java/org/tron/consensus/pbft/PbftMessageHandle.java @@ -91,9 +91,15 @@ public void close() { } } - public List getSrMinerList() { + public List getSrMinerList(long epoch) { + List compareList; + if (epoch > maintenanceManager.getBeforeMaintenanceTime()) { + compareList = maintenanceManager.getCurrentWitness(); + } else { + compareList = maintenanceManager.getBeforeWitness(); + } return Param.getInstance().getMiners().stream() - .filter(miner -> chainBaseManager.getWitnesses().contains(miner.getWitnessAddress())) + .filter(miner -> compareList.contains(miner.getWitnessAddress())) .collect(Collectors.toList()); } @@ -115,10 +121,11 @@ public void onPrePrepare(PbftMessage message) { // checkPrepareMsgCache(key); //Into the preparation phase, if not the sr node does not need to be prepared - if (!checkIsCanSendMsg(message)) { + long epoch = message.getPbftMessage().getRawData().getEpoch(); + if (!checkIsCanSendMsg(epoch)) { return; } - for (Miner miner : getSrMinerList()) { + for (Miner miner : getSrMinerList(epoch)) { PbftMessage paMessage = message.buildPrePareMessage(miner); forwardMessage(paMessage); try { @@ -153,7 +160,8 @@ public synchronized void onPrepare(PbftMessage message) { pareVoteMap.put(key, message); // checkCommitMsgCache(message.getNo()); - if (!checkIsCanSendMsg(message)) { + long epoch = message.getPbftMessage().getRawData().getEpoch(); + if (!checkIsCanSendMsg(epoch)) { return; } //The number of votes plus 1 @@ -162,7 +170,7 @@ public synchronized void onPrepare(PbftMessage message) { if (agCou >= Param.getInstance().getAgreeNodeCount()) { agreePare.remove(message.getDataKey()); //Entering the submission stage - for (Miner miner : getSrMinerList()) { + for (Miner miner : getSrMinerList(epoch)) { PbftMessage cmMessage = message.buildCommitMessage(miner); doneMsg.put(message.getNo(), cmMessage); forwardMessage(cmMessage); @@ -239,19 +247,11 @@ private void checkCommitMsgCache(String key) { } } - public boolean checkIsCanSendMsg(PbftMessage msg) { + public boolean checkIsCanSendMsg(long epoch) { if (!Param.getInstance().isEnable()) {//is witness return false; } - ByteString publicKey = Param.getInstance().getMiner().getPrivateKeyAddress(); - List compareList; - long epoch = msg.getPbftMessage().getRawData().getEpoch(); - if (epoch > maintenanceManager.getBeforeMaintenanceTime()) { - compareList = maintenanceManager.getCurrentWitness(); - } else { - compareList = maintenanceManager.getBeforeWitness(); - } - if (!compareList.contains(publicKey)) { + if (getSrMinerList(epoch).isEmpty()) { return false; } return !isSyncing(); From 441215697aafe391371263bcc4e91dbdd5aa20d3 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 11 May 2023 16:51:15 +0800 Subject: [PATCH 0772/1197] fix(net): check if there is contract in transaction before pushTransaction --- framework/src/main/java/org/tron/core/Wallet.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 9051bde8bba..a836b15d59d 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -122,6 +122,7 @@ import org.tron.common.zksnark.LibrustzcashParam.SpendSigParams; import org.tron.consensus.ConsensusDelegate; import org.tron.core.actuator.Actuator; +import org.tron.core.actuator.ActuatorConstant; import org.tron.core.actuator.ActuatorFactory; import org.tron.core.actuator.UnfreezeBalanceV2Actuator; import org.tron.core.actuator.VMActuator; @@ -534,6 +535,9 @@ public GrpcAPI.Return broadcastTransaction(Transaction signedTransaction) { if (chainBaseManager.getDynamicPropertiesStore().supportVM()) { trx.resetResult(); } + if (trx.getInstance().getRawData().getContractCount() == 0) { + throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); + } dbManager.pushTransaction(trx); int num = tronNetService.fastBroadcastTransaction(message); if (num == 0 && minEffectiveConnection != 0) { From 6528f7ff4e5ebda569419fe284bc2cb90db2b6e0 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 11 May 2023 17:47:36 +0800 Subject: [PATCH 0773/1197] test(net): modify HandShakeServiceTest --- .../core/net/service/handshake/HandshakeService.java | 10 ---------- .../tron/core/net/services/HandShakeServiceTest.java | 12 ++++++++---- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java index e7f4f89826b..aa6567d1cda 100644 --- a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -35,7 +35,6 @@ public void startHandshake(PeerConnection peer) { public void processHelloMessage(PeerConnection peer, HelloMessage msg) { if (peer.getHelloMessageReceive() != null) { - System.out.println("11111111111"); logger.warn("Peer {} receive dup hello message", peer.getInetSocketAddress()); peer.disconnect(ReasonCode.BAD_PROTOCOL); return; @@ -43,14 +42,12 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { TronNetService.getP2pService().updateNodeId(peer.getChannel(), msg.getFrom().getHexId()); if (peer.isDisconnect()) { - System.out.println("222222222"); logger.info("Duplicate Peer {}", peer.getInetSocketAddress()); peer.disconnect(ReasonCode.DUPLICATE_PEER); return; } if (!msg.valid()) { - System.out.println("333333333"); logger.warn("Peer {} invalid hello message parameters, " + "GenesisBlockId: {}, SolidBlockId: {}, HeadBlockId: {}", peer.getInetSocketAddress(), @@ -64,7 +61,6 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { peer.setAddress(msg.getHelloMessage().getAddress()); if (!relayService.checkHelloMessage(msg, peer.getChannel())) { - System.out.println("44444444444"); peer.disconnect(ReasonCode.UNEXPECTED_IDENTITY); return; } @@ -72,7 +68,6 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { long headBlockNum = chainBaseManager.getHeadBlockNum(); long lowestBlockNum = msg.getLowestBlockNum(); if (lowestBlockNum > headBlockNum) { - System.out.println("55555555555"); logger.info("Peer {} miss block, lowestBlockNum:{}, headBlockNum:{}", peer.getInetSocketAddress(), lowestBlockNum, headBlockNum); peer.disconnect(ReasonCode.LIGHT_NODE_SYNC_FAIL); @@ -80,7 +75,6 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { } if (msg.getVersion() != Args.getInstance().getNodeP2pVersion()) { - System.out.println("6666666666"); logger.info("Peer {} different p2p version, peer->{}, me->{}", peer.getInetSocketAddress(), msg.getVersion(), Args.getInstance().getNodeP2pVersion()); @@ -90,7 +84,6 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { if (!Arrays.equals(chainBaseManager.getGenesisBlockId().getBytes(), msg.getGenesisBlockId().getBytes())) { - System.out.println("7777777777"); logger.info("Peer {} different genesis block, peer->{}, me->{}", peer.getInetSocketAddress(), msg.getGenesisBlockId().getString(), @@ -101,7 +94,6 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { if (chainBaseManager.getSolidBlockId().getNum() >= msg.getSolidBlockId().getNum() && !chainBaseManager.containBlockInMainChain(msg.getSolidBlockId())) { - System.out.println("88888888888"); logger.info("Peer {} different solid block, peer->{}, me->{}", peer.getInetSocketAddress(), msg.getSolidBlockId().getString(), @@ -112,7 +104,6 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { if (msg.getHeadBlockId().getNum() < chainBaseManager.getHeadBlockId().getNum() && peer.getInetSocketAddress().equals(effectiveCheckService.getCur())) { - System.out.println("99999999999"); logger.info("Peer's head block {} is below than we, peer->{}, me->{}", peer.getInetSocketAddress(), msg.getHeadBlockId().getNum(), chainBaseManager.getHeadBlockId().getNum()); @@ -120,7 +111,6 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { return; } - System.out.println("000000000"); peer.setHelloMessageReceive(msg); peer.getChannel().updateAvgLatency( diff --git a/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java b/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java index d28903965e7..4f074b2c825 100644 --- a/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java @@ -11,6 +11,7 @@ import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Collections; +import java.util.Random; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; @@ -209,14 +210,17 @@ public void testLowAndGenesisBlockNum() throws NoSuchMethodException { Assert.fail(); } - //solidityBlock is small than us, but not contained + //solidityBlock <= us, but not contained builder = getHelloMessageBuilder(node2, System.currentTimeMillis(), ChainBaseManager.getChainBaseManager()); BlockCapsule.BlockId sid = ChainBaseManager.getChainBaseManager().getSolidBlockId(); + + Random gen = new Random(); + byte[] randomHash = new byte[Sha256Hash.LENGTH]; + gen.nextBytes(randomHash); + Protocol.HelloMessage.BlockId sBlockId = Protocol.HelloMessage.BlockId.newBuilder() - .setHash(ByteString.copyFrom( - ByteArray.fromHex("0304f784e4e7bae517bcab94c3e0c9214fb4ac7ff9d7d5a937d1f40031f87b81") - .getBytes())) + .setHash(ByteString.copyFrom(randomHash)) .setNumber(sid.getNum()) .build(); builder.setSolidBlockId(sBlockId); From 7b67006712c56b3cb295c64ba847d783079eed32 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 11 May 2023 18:38:45 +0800 Subject: [PATCH 0774/1197] test(db): optimize --- .../org/tron/core/net/messagehandler/MessageHandlerTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java index e0752484642..215b5f495ad 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java @@ -1,6 +1,5 @@ package org.tron.core.net.messagehandler; - import static org.mockito.Mockito.mock; import com.google.protobuf.ByteString; From 563f09ade16491c72303ed73eebd11559163fe30 Mon Sep 17 00:00:00 2001 From: guoquanwu Date: Thu, 18 May 2023 14:50:47 +0800 Subject: [PATCH 0775/1197] fix(db): skip expired checkpoints to avoid recovery from corrupted databases --- .../main/java/org/tron/core/db2/core/SnapshotManager.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java index 97210e9ae07..85d0f3c2dd0 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java @@ -471,9 +471,10 @@ private void pruneCheckpoint() { if (cpList.size() < 3) { return; } + long latestTimestamp = Long.parseLong(cpList.get(cpList.size()-1)); for (String cp: cpList.subList(0, cpList.size()-3)) { long timestamp = Long.parseLong(cp); - if (System.currentTimeMillis() - timestamp < ONE_MINUTE_MILLS*2) { + if (latestTimestamp - timestamp <= ONE_MINUTE_MILLS*2) { break; } String checkpointPath = Paths.get(StorageUtils.getOutputDirectoryByDbName(CHECKPOINT_V2_DIR), @@ -522,7 +523,12 @@ private void checkV2() { return; } + long latestTimestamp = Long.parseLong(cpList.get(cpList.size()-1)); for (String cp: cpList) { + long timestamp = Long.parseLong(cp); + if (latestTimestamp - timestamp > ONE_MINUTE_MILLS*2) { + continue; + } TronDatabase checkPointV2Store = getCheckpointDB(cp); recover(checkPointV2Store); checkPointV2Store.close(); From 8318708fa9107a9f064d27c4ef7b35d58a8c596e Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 18 Apr 2023 22:12:03 +0800 Subject: [PATCH 0776/1197] feat(db): remove auto-repair for leveldb --- .../leveldb/LevelDbDataSourceImpl.java | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java index 54df4946297..2292f974c4b 100644 --- a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java @@ -142,22 +142,11 @@ private void openDatabase(Options dbOptions) throws IOException { if (!Files.isSymbolicLink(dbPath.getParent())) { Files.createDirectories(dbPath.getParent()); } - try { - database = factory.open(dbPath.toFile(), dbOptions); - if (!this.getDBName().startsWith("checkpoint")) { - logger.info("DB {} open success with writeBufferSize {} M, cacheSize {} M, maxOpenFiles {}.", - this.getDBName(), dbOptions.writeBufferSize() / 1024 / 1024, - dbOptions.cacheSize() / 1024 / 1024, dbOptions.maxOpenFiles()); - } - } catch (IOException e) { - if (e.getMessage().contains("Corruption:")) { - logger.warn("DB {} corruption detected, try to repair it.", this.getDBName(), e); - factory.repair(dbPath.toFile(), dbOptions); - logger.warn("DB {} corruption detected, repair done.", this.getDBName()); - database = factory.open(dbPath.toFile(), dbOptions); - } else { - throw e; - } + database = factory.open(dbPath.toFile(), dbOptions); + if (!this.getDBName().startsWith("checkpoint")) { + logger.info("DB {} open success with writeBufferSize {} M, cacheSize {} M, maxOpenFiles {}.", + this.getDBName(), dbOptions.writeBufferSize() / 1024 / 1024, + dbOptions.cacheSize() / 1024 / 1024, dbOptions.maxOpenFiles()); } } From c8b9d1a2c03058f93e2014b30f3351a2ba9fe782 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 23 May 2023 17:49:35 +0800 Subject: [PATCH 0777/1197] fix(net):fix the issue of repeated request blocks --- .../org/tron/core/net/messagehandler/BlockMsgHandler.java | 1 + .../java/org/tron/core/net/service/sync/SyncService.java | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java index 6613ebfc581..9bb746346a6 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java @@ -67,6 +67,7 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep if (peer.getSyncBlockRequested().containsKey(blockId)) { peer.getSyncBlockRequested().remove(blockId); + peer.getSyncBlockInProcess().add(blockId); syncService.processBlock(peer, blockMessage); } else { Item item = new Item(blockId, InventoryType.BLOCK); diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 9476b32fa46..eef6c7efc88 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -225,7 +225,8 @@ private void startFetchSyncBlock() { send.put(peer, new LinkedList<>()); } for (BlockId blockId : peer.getSyncBlockToFetch()) { - if (requestBlockIds.getIfPresent(blockId) == null) { + if (requestBlockIds.getIfPresent(blockId) == null + && !peer.getSyncBlockInProcess().contains(blockId)) { requestBlockIds.put(blockId, peer); peer.getSyncBlockRequested().put(blockId, System.currentTimeMillis()); send.get(peer).add(blockId); @@ -266,6 +267,7 @@ private synchronized void handleSyncBlock() { } if (msg.getBlockId().getNum() <= solidNum) { blockWaitToProcess.remove(msg); + peerConnection.getSyncBlockInProcess().remove(msg.getBlockId()); return; } final boolean[] isFound = {false}; @@ -278,6 +280,7 @@ private synchronized void handleSyncBlock() { blockWaitToProcess.remove(msg); isProcessed[0] = true; processSyncBlock(msg.getBlockCapsule(), peerConnection); + peerConnection.getSyncBlockInProcess().remove(msg.getBlockId()); } } }); From 98fc6eb5313d83f5bd92cebc1eaba4a3767e2f39 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 24 May 2023 17:41:48 +0800 Subject: [PATCH 0778/1197] fix(net): update org.zeromq.jeromq from 0.5.0 to 0.5.3 --- framework/build.gradle | 2 +- .../tron/common/logsfilter/nativequeue/NativeMessageQueue.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/build.gradle b/framework/build.gradle index 6f6f861a6e9..299c5fe611a 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -88,7 +88,7 @@ dependencies { testImplementation group: 'org.springframework', name: 'spring-test', version: '5.2.0.RELEASE' - compile group: 'org.zeromq', name: 'jeromq', version: '0.5.0' + compile group: 'org.zeromq', name: 'jeromq', version: '0.5.3' compile project(":chainbase") compile project(":protocol") compile project(":actuator") diff --git a/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java b/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java index cf2fe6dce0a..c0a115620c2 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java +++ b/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java @@ -59,7 +59,7 @@ public void stop() { } public void publishTrigger(String data, String topic) { - if (Objects.isNull(publisher) || Objects.isNull(context.isClosed()) || context.isClosed()) { + if (Objects.isNull(publisher) || Objects.isNull(context) || context.isClosed()) { return; } From a5c19013e2b7f70792fae671285cbc63b35864b7 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 9 May 2023 16:17:46 +0800 Subject: [PATCH 0779/1197] feat(metric): add metric for json-rpc --- .../tron/common/prometheus/MetricKeys.java | 1 + .../common/prometheus/MetricsHistogram.java | 2 + .../core/services/jsonrpc/JsonRpcServlet.java | 9 +++ .../interceptor/MetricInterceptor.java | 42 ++++++++++++++ .../services/jsonrpc/types/BlockResult.java | 4 ++ .../tron/core/jsonrpc/JsonrpcServiceTest.java | 57 ++++++++++++++++++- 6 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 framework/src/main/java/org/tron/core/services/jsonrpc/interceptor/MetricInterceptor.java diff --git a/common/src/main/java/org/tron/common/prometheus/MetricKeys.java b/common/src/main/java/org/tron/common/prometheus/MetricKeys.java index 800c5cd3c62..87ab6fae0a3 100644 --- a/common/src/main/java/org/tron/common/prometheus/MetricKeys.java +++ b/common/src/main/java/org/tron/common/prometheus/MetricKeys.java @@ -44,6 +44,7 @@ private Gauge() { public static class Histogram { public static final String HTTP_SERVICE_LATENCY = "tron:http_service_latency_seconds"; public static final String GRPC_SERVICE_LATENCY = "tron:grpc_service_latency_seconds"; + public static final String JSONRPC_SERVICE_LATENCY = "tron:jsonrpc_service_latency_seconds"; public static final String MINER_LATENCY = "tron:miner_latency_seconds"; public static final String PING_PONG_LATENCY = "tron:ping_pong_latency_seconds"; public static final String VERIFY_SIGN_LATENCY = "tron:verify_sign_latency_seconds"; diff --git a/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java b/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java index 10cbf1d2979..556db10feb5 100644 --- a/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java +++ b/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java @@ -17,6 +17,8 @@ public class MetricsHistogram { "url"); init(MetricKeys.Histogram.GRPC_SERVICE_LATENCY, "Grpc Service latency.", "endpoint"); + init(MetricKeys.Histogram.JSONRPC_SERVICE_LATENCY, "JsonRpc Service latency.", + "method"); init(MetricKeys.Histogram.MINER_LATENCY, "miner latency.", "miner"); init(MetricKeys.Histogram.PING_PONG_LATENCY, "node ping pong latency."); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcServlet.java b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcServlet.java index b14c3e67e39..61d163a3e8a 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcServlet.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcServlet.java @@ -1,9 +1,11 @@ package org.tron.core.services.jsonrpc; import com.googlecode.jsonrpc4j.HttpStatusCodeProvider; +import com.googlecode.jsonrpc4j.JsonRpcInterceptor; import com.googlecode.jsonrpc4j.JsonRpcServer; import com.googlecode.jsonrpc4j.ProxyUtil; import java.io.IOException; +import java.util.Collections; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -11,6 +13,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.common.parameter.CommonParameter; import org.tron.core.Wallet; import org.tron.core.db.Manager; import org.tron.core.services.NodeInfoService; @@ -29,6 +32,9 @@ public class JsonRpcServlet extends RateLimiterServlet { @Autowired private Manager manager; + @Autowired + private JsonRpcInterceptor interceptor; + @Override public void init(ServletConfig config) throws ServletException { super.init(config); @@ -57,6 +63,9 @@ public Integer getJsonRpcCode(int httpStatusCode) { rpcServer.setHttpStatusCodeProvider(httpStatusCodeProvider); rpcServer.setShouldLogInvocationErrors(false); + if (CommonParameter.getInstance().isMetricsPrometheusEnable()) { + rpcServer.setInterceptorList(Collections.singletonList(interceptor)); + } } @Override diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/interceptor/MetricInterceptor.java b/framework/src/main/java/org/tron/core/services/jsonrpc/interceptor/MetricInterceptor.java new file mode 100644 index 00000000000..b4579fa461f --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/interceptor/MetricInterceptor.java @@ -0,0 +1,42 @@ +package org.tron.core.services.jsonrpc.interceptor; + +import com.fasterxml.jackson.databind.JsonNode; +import com.googlecode.jsonrpc4j.JsonRpcInterceptor; +import com.googlecode.jsonrpc4j.ProxyUtil; +import io.prometheus.client.Histogram; +import java.lang.reflect.Method; +import java.util.List; +import org.springframework.stereotype.Component; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.Metrics; + +@Component +public class MetricInterceptor implements JsonRpcInterceptor { + + private final ThreadLocal timer = new ThreadLocal<>(); + + @Override + public void preHandleJson(JsonNode json) { + + } + + @Override + public void preHandle(Object target, Method method, List params) { + timer.set(Metrics.histogramStartTimer(MetricKeys.Histogram.JSONRPC_SERVICE_LATENCY, + ProxyUtil.getMethodName(method))); + } + + @Override + public void postHandle(Object target, Method method, List params, JsonNode result) { + try { + Metrics.histogramObserve(timer.get()); + } finally { + timer.remove(); + } + } + + @Override + public void postHandleJson(JsonNode json) { + + } +} diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/types/BlockResult.java b/framework/src/main/java/org/tron/core/services/jsonrpc/types/BlockResult.java index 65d0dd56ca9..f5f8fb7fdef 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/types/BlockResult.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/types/BlockResult.java @@ -84,6 +84,10 @@ public class BlockResult { @Setter private String mixHash = ByteArray.toJsonHex(new byte[32]); + public BlockResult() { + + } + public BlockResult(Block block, boolean fullTx, Wallet wallet) { BlockCapsule blockCapsule = new BlockCapsule(block); diff --git a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java index 2b2d6f8b277..f3ad69d09a1 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java @@ -1,13 +1,25 @@ package org.tron.core.jsonrpc; +import com.alibaba.fastjson.JSON; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; import com.google.protobuf.ByteString; +import io.prometheus.client.CollectorRegistry; import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; import org.bouncycastle.util.encoders.Hex; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.tron.common.BaseTest; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.prometheus.Metrics; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; @@ -17,6 +29,7 @@ import org.tron.core.capsule.TransactionCapsule; import org.tron.core.config.args.Args; import org.tron.core.services.NodeInfoService; +import org.tron.core.services.jsonrpc.FullNodeJsonRpcHttpService; import org.tron.core.services.jsonrpc.TronJsonRpcImpl; import org.tron.core.services.jsonrpc.types.BlockResult; import org.tron.core.services.jsonrpc.types.TransactionResult; @@ -39,9 +52,15 @@ public class JsonrpcServiceTest extends BaseTest { @Resource private Wallet wallet; + @Resource + private FullNodeJsonRpcHttpService fullNodeJsonRpcHttpService; + static { dbPath = "output_jsonrpc_service_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + CommonParameter.getInstance().setJsonRpcHttpFullNodeEnable(true); + CommonParameter.getInstance().setMetricsPrometheusEnable(true); + Metrics.init(); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; @@ -235,4 +254,40 @@ public void testGetTransactionByHash() { transactionResult.getBlockNumber()); } -} \ No newline at end of file + @Test + public void testGetBlockByNumber2() { + fullNodeJsonRpcHttpService.start(); + JsonArray params = new JsonArray(); + params.add(ByteArray.toJsonHex(blockCapsule.getNum())); + params.add(false); + JsonObject requestBody = new JsonObject(); + requestBody.addProperty("jsonrpc", "2.0"); + requestBody.addProperty("method", "eth_getBlockByNumber"); + requestBody.add("params", params); + requestBody.addProperty("id", 1); + CloseableHttpResponse response; + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + HttpPost httpPost = new HttpPost("http://127.0.0.1:8545/jsonrpc"); + httpPost.addHeader("Content-Type", "application/json"); + httpPost.setEntity(new StringEntity(requestBody.toString())); + response = httpClient.execute(httpPost); + String resp = EntityUtils.toString(response.getEntity()); + BlockResult blockResult = JSON.parseObject(resp).getObject("result", BlockResult.class); + Assert.assertEquals(ByteArray.toJsonHex(blockCapsule.getNum()), + blockResult.getNumber()); + Assert.assertEquals(blockCapsule.getTransactions().size(), + blockResult.getTransactions().length); + Assert.assertEquals("0x0000000000000000", + blockResult.getNonce()); + response.close(); + Assert.assertEquals(1, CollectorRegistry.defaultRegistry.getSampleValue( + "tron:jsonrpc_service_latency_seconds_count", + new String[] {"method"}, new String[] {"eth_getBlockByNumber"}).intValue()); + } catch (Exception e) { + Assert.fail(e.getMessage()); + } finally { + fullNodeJsonRpcHttpService.stop(); + } + } + +} From 25df6605ab7e89f08678b6f974307b6247bb6717 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 25 May 2023 18:37:48 +0800 Subject: [PATCH 0780/1197] fix(hard_fork):optimize hard fork logic --- .../org/tron/common/utils/ForkController.java | 65 +++++++++++++++---- .../core/store/DynamicPropertiesStore.java | 14 ++++ .../common/parameter/CommonParameter.java | 3 + .../src/main/java/org/tron/core/Constant.java | 2 + .../java/org/tron/core/config/args/Args.java | 4 ++ .../main/java/org/tron/core/db/Manager.java | 10 ++- 6 files changed, 83 insertions(+), 15 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/utils/ForkController.java b/chainbase/src/main/java/org/tron/common/utils/ForkController.java index 89ffcbd111f..16f1f5aadf5 100644 --- a/chainbase/src/main/java/org/tron/common/utils/ForkController.java +++ b/chainbase/src/main/java/org/tron/common/utils/ForkController.java @@ -19,6 +19,7 @@ import org.tron.core.capsule.BlockCapsule; import org.tron.core.config.Parameter.ForkBlockVersionConsts; import org.tron.core.config.Parameter.ForkBlockVersionEnum; +import org.tron.core.store.DynamicPropertiesStore; @Slf4j(topic = "utils") public class ForkController { @@ -37,6 +38,12 @@ public class ForkController { public void init(ChainBaseManager manager) { this.manager = manager; + try { + checkLocalVersion(); + } catch (RuntimeException r) { + logger.warn("Exception caught, detail:{}", r.getMessage()); + System.exit(1); + } } public boolean pass(ForkBlockVersionEnum forkBlockVersionEnum) { @@ -87,7 +94,7 @@ private boolean passNew(int version) { } } return count >= Math - .ceil((double) versionEnum.getHardForkRate() * manager.getWitnesses().size() / 100); + .ceil((double) versionEnum.getHardForkRate() * stats.length / 100); } @@ -116,9 +123,9 @@ private boolean check(byte[] stats) { private void downgrade(int version, int slot) { for (ForkBlockVersionEnum versionEnum : ForkBlockVersionEnum.values()) { int versionValue = versionEnum.getValue(); - if (versionValue > version) { + if (versionValue > version && !pass(versionValue)) { byte[] stats = manager.getDynamicPropertiesStore().statsByVersion(versionValue); - if (!check(stats) && Objects.nonNull(stats)) { + if (Objects.nonNull(stats)) { stats[slot] = VERSION_DOWNGRADE; manager.getDynamicPropertiesStore().statsByVersion(versionValue, stats); } @@ -129,15 +136,13 @@ private void downgrade(int version, int slot) { private void upgrade(int version, int slotSize) { for (ForkBlockVersionEnum versionEnum : ForkBlockVersionEnum.values()) { int versionValue = versionEnum.getValue(); - if (versionValue < version) { + if (versionValue < version && !pass(versionValue)) { byte[] stats = manager.getDynamicPropertiesStore().statsByVersion(versionValue); - if (!check(stats)) { - if (stats == null || stats.length == 0) { - stats = new byte[slotSize]; - } - Arrays.fill(stats, VERSION_UPGRADE); - manager.getDynamicPropertiesStore().statsByVersion(versionValue, stats); + if (stats == null || stats.length == 0) { + stats = new byte[slotSize]; } + Arrays.fill(stats, VERSION_UPGRADE); + manager.getDynamicPropertiesStore().statsByVersion(versionValue, stats); } } } @@ -155,6 +160,10 @@ public synchronized void update(BlockCapsule blockCapsule) { return; } + if (manager.getDynamicPropertiesStore().getLatestVersion() >= version) { + return; + } + downgrade(version, slot); byte[] stats = manager.getDynamicPropertiesStore().statsByVersion(version); @@ -162,8 +171,9 @@ public synchronized void update(BlockCapsule blockCapsule) { stats = new byte[witnesses.size()]; } - if (check(stats)) { + if (pass(version)) { upgrade(version, stats.length); + manager.getDynamicPropertiesStore().saveLatestVersion(version); return; } @@ -185,11 +195,12 @@ public synchronized void update(BlockCapsule blockCapsule) { } public synchronized void reset() { + int size = manager.getWitnessScheduleStore().getActiveWitnesses().size(); for (ForkBlockVersionEnum versionEnum : ForkBlockVersionEnum.values()) { int versionValue = versionEnum.getValue(); byte[] stats = manager.getDynamicPropertiesStore().statsByVersion(versionValue); if (Objects.nonNull(stats) && !pass(versionValue)) { - Arrays.fill(stats, VERSION_DOWNGRADE); + stats = new byte[size]; manager.getDynamicPropertiesStore().statsByVersion(versionValue, stats); } } @@ -212,4 +223,34 @@ private ForkController getInstance() { return instance; } } + + public void checkLocalVersion() { + DynamicPropertiesStore store = manager.getDynamicPropertiesStore(); + int latestVersion = store.getLatestVersion(); + if (latestVersion == 0) { + for (ForkBlockVersionEnum version : ForkBlockVersionEnum.values()) { + int v = version.getValue(); + if (pass(v) && latestVersion < v) { + latestVersion = v; + } + } + store.saveLatestVersion(latestVersion); + return; + } + + if (!CommonParameter.getInstance().isVersionCheckEnable()) { + return; + } + + int systemVersion = 0; + for (ForkBlockVersionEnum version : ForkBlockVersionEnum.values()) { + if (version.getValue() > systemVersion) { + systemVersion = version.getValue(); + } + } + if (latestVersion > systemVersion) { + throw new RuntimeException("Version check failed, latestVersion:" + + latestVersion + ", systemVersion:" + systemVersion); + } + } } diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 001282a0de8..5e414108bb7 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -101,6 +101,7 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] STORAGE_EXCHANGE_TAX_RATE = "STORAGE_EXCHANGE_TAX_RATE".getBytes(); private static final String FORK_CONTROLLER = "FORK_CONTROLLER"; private static final String FORK_PREFIX = "FORK_VERSION_"; + private static final byte[] VERSION_NUMBER = "VERSION_NUMBER".getBytes(); //This value is only allowed to be 0, 1, -1 private static final byte[] REMOVE_THE_POWER_OF_THE_GR = "REMOVE_THE_POWER_OF_THE_GR".getBytes(); //This value is only allowed to be 0, 1, -1 @@ -2282,6 +2283,19 @@ public Boolean getForked(int version) { return value == null ? null : Boolean.valueOf(new String(value)); } + public void saveLatestVersion(int version) { + this.put(VERSION_NUMBER, new BytesCapsule(ByteArray.fromInt(version))); + } + + public int getLatestVersion() { + BytesCapsule data = getUnchecked(VERSION_NUMBER); + if (data == null) { + saveLatestVersion(0); + return 0; + } + return ByteArray.toInt(data.getData()); + } + /** * get allow protobuf number. */ diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index ef89e01925a..338ca38c602 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -395,6 +395,9 @@ public class CommonParameter { public boolean version; @Getter @Setter + public boolean versionCheckEnable; + @Getter + @Setter public String zenTokenId; @Getter @Setter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index dea5a2534b9..e15ace95ec2 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -372,5 +372,7 @@ public class Constant { public static final String DYNAMIC_CONFIG_ENABLE = "node.dynamicConfig.enable"; public static final String DYNAMIC_CONFIG_CHECK_INTERVAL = "node.dynamicConfig.checkInterval"; + public static final String NODE_VERSION_CHECK_ENABLE = "node.versionCheckEnable"; + public static final String COMMITTEE_ALLOW_TVM_SHANGHAI = "committee.allowTvmShangHai"; } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 50e4dacf6a9..71c4a50ea7a 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -233,6 +233,7 @@ public static void clearParam() { PARAMETER.p2pDisable = false; PARAMETER.dynamicConfigEnable = false; PARAMETER.dynamicConfigCheckInterval = 600; + PARAMETER.versionCheckEnable = true; PARAMETER.allowTvmShangHai = 0; } @@ -1179,6 +1180,9 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.dynamicConfigCheckInterval = 600; } + PARAMETER.versionCheckEnable = !config.hasPath(Constant.NODE_VERSION_CHECK_ENABLE) + || config.getBoolean(Constant.NODE_VERSION_CHECK_ENABLE); + PARAMETER.allowTvmShangHai = config.hasPath(Constant.COMMITTEE_ALLOW_TVM_SHANGHAI) ? config .getInt(Constant.COMMITTEE_ALLOW_TVM_SHANGHAI) : 0; diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 1929bae1d3d..a3f8fb8de03 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1746,16 +1746,20 @@ private void processBlock(BlockCapsule block, List txs) payReward(block); - if (chainBaseManager.getDynamicPropertiesStore().getNextMaintenanceTime() - <= block.getTimeStamp()) { + boolean flag = chainBaseManager.getDynamicPropertiesStore().getNextMaintenanceTime() + <= block.getTimeStamp(); + if (flag) { proposalController.processProposals(); - chainBaseManager.getForkController().reset(); } if (!consensus.applyBlock(block)) { throw new BadBlockException("consensus apply block failed"); } + if (flag) { + chainBaseManager.getForkController().reset(); + } + updateTransHashCache(block); updateRecentBlock(block); updateRecentTransaction(block); From b2f830fef7a53135a557cdaac97490555ba28567 Mon Sep 17 00:00:00 2001 From: forfreeday Date: Thu, 25 May 2023 13:57:56 +0800 Subject: [PATCH 0781/1197] feat(test): remove stest --- .../org/tron/common/config/args/ArgsTest.java | 4 +- .../runtime/RuntimeTransferComplexTest.java | 2 +- .../org/tron/common/runtime/TvmTestUtils.java | 11 +- .../runtime/vm/AllowTvmCompatibleEvmTest.java | 3 +- .../common/runtime/vm/AllowTvmLondonTest.java | 2 +- .../tron/common/runtime/vm/BatchSendTest.java | 2 +- .../vm/BatchValidateSignContractTest.java | 6 +- .../tron/common/runtime/vm/Create2Test.java | 4 +- .../common/runtime/vm/ExtCodeHashTest.java | 2 +- .../tron/common/runtime/vm/FreezeTest.java | 2 +- .../tron/common/runtime/vm/FreezeV2Test.java | 4 +- .../common/runtime/vm/IsContractTest.java | 2 +- .../common/runtime/vm/IsSRCandidateTest.java | 2 +- .../PrecompiledContractsVerifyProofTest.java | 3 +- .../common/runtime/vm/RewardBalanceTest.java | 2 +- .../runtime/vm/TransferFailedEnergyTest.java | 2 +- .../runtime/vm/TransferToAccountTest.java | 3 +- .../vm/ValidateMultiSignContractTest.java | 3 +- .../org/tron/common/runtime/vm/VoteTest.java | 4 +- .../org/tron/common/utils/PublicMethod.java | 157 +- .../common/utils}/client/Configuration.java | 7 +- .../tron/common/utils}/client/GrpcClient.java | 4 +- .../tron/common/utils}/client/Parameter.java | 4 +- .../common/utils}/client/WalletClient.java | 12 +- .../utils}/client/WitnessComparator.java | 4 +- .../common/utils}/client/utils/AbiUtil.java | 2 +- .../common/utils}/client/utils/Base58.java | 5 +- .../utils}/client/utils/ByteArrayWrapper.java | 3 +- .../common/utils}/client/utils/DataWord.java | 3 +- .../utils}/client/utils/HttpMethed.java | 115 +- .../utils}/client/utils/JSONObjectWarp.java | 22 +- .../utils}/client/utils/Sha256Sm3Hash.java | 13 +- .../client/utils/ShieldAddressInfo.java | 2 +- .../utils}/client/utils/ShieldNoteInfo.java | 3 +- .../utils}/client/utils/TransactionUtils.java | 2 +- .../core/CreateCommonTransactionTest.java | 2 +- .../tron/core/ShieldedTRC20BuilderTest.java | 4 +- .../ClearABIContractActuatorTest.java | 2 +- .../ShieldedTransferActuatorTest.java | 5 +- .../core/services/DelegationServiceTest.java | 2 +- .../core/services/NodeInfoServiceTest.java | 3 +- .../org/tron/core/services/WalletApiTest.java | 3 +- .../http/TriggerSmartContractServletTest.java | 4 +- .../core/zksnark/ShieldedReceiveTest.java | 2 +- .../tron/wallet/account/BrokerageTest001.java | 167 - .../wallet/account/WalletTestAccount001.java | 232 - .../wallet/account/WalletTestAccount003.java | 485 -- .../wallet/account/WalletTestAccount004.java | 338 - .../wallet/account/WalletTestAccount005.java | 267 - .../wallet/account/WalletTestAccount006.java | 186 - .../wallet/account/WalletTestAccount007.java | 126 - .../wallet/account/WalletTestAccount009.java | 122 - .../wallet/account/WalletTestAccount011.java | 76 - .../tron/wallet/block/WalletTestBlock003.java | 144 - .../tron/wallet/block/WalletTestBlock004.java | 203 - .../tron/wallet/block/WalletTestBlock005.java | 177 - .../tron/wallet/block/WalletTestBlock006.java | 111 - .../committee/WalletTestCommittee001.java | 131 - .../committee/WalletTestCommittee002.java | 365 - .../committee/WalletTestCommittee003.java | 166 - .../committee/WalletTestCommittee004.java | 219 - .../common/client/utils/CipherException.java | 19 - .../common/client/utils/DailyBuildReport.java | 167 - .../wallet/common/client/utils/FileUtil.java | 142 - .../common/client/utils/JsonRpcBase.java | 405 - .../common/client/utils/PublicMethed.java | 7091 ----------------- .../client/utils/PublicMethedForMutiSign.java | 5335 ------------- .../wallet/common/client/utils/Retry.java | 50 - .../common/client/utils/RetryListener.java | 20 - .../common/client/utils/Sha256Hash.java | 346 - .../common/client/utils/ShieldWrapper.java | 427 - .../client/utils/ShieldedAddressInfo.java | 122 - .../client/utils/ShieldedTRC20NoteInfo.java | 96 - .../common/client/utils/ZenTrc20Base.java | 1724 ---- .../wallet/common/client/utils/ZenUtils.java | 154 - .../contract/linkage/ContractLinkage002.java | 271 - .../contract/linkage/ContractLinkage003.java | 157 - .../contract/linkage/ContractLinkage004.java | 320 - .../contract/linkage/ContractLinkage007.java | 350 - .../scenario/ContractScenario001.java | 129 - .../scenario/ContractScenario003.java | 135 - .../scenario/ContractScenario004.java | 131 - .../scenario/ContractScenario005.java | 110 - .../scenario/ContractScenario006.java | 123 - .../scenario/ContractScenario007.java | 111 - .../scenario/ContractScenario008.java | 114 - .../scenario/ContractScenario009.java | 126 - .../scenario/ContractScenario010.java | 114 - .../scenario/ContractScenario012.java | 198 - .../scenario/ContractScenario013.java | 142 - .../scenario/ContractScenario014.java | 158 - .../scenario/ContractScenario015.java | 142 - .../scenario/ContractScenario016.java | 193 - .../account/GetAccountBalance001.java | 129 - .../dailybuild/account/TransactionFee001.java | 662 -- .../account/WalletTestAccount012.java | 204 - .../assetissue/WalletExchange001.java | 394 - .../assetissue/WalletTestAssetIssue001.java | 333 - .../assetissue/WalletTestAssetIssue002.java | 346 - .../assetissue/WalletTestAssetIssue003.java | 416 - .../assetissue/WalletTestAssetIssue004.java | 294 - .../assetissue/WalletTestAssetIssue005.java | 297 - .../assetissue/WalletTestAssetIssue006.java | 213 - .../assetissue/WalletTestAssetIssue007.java | 173 - .../assetissue/WalletTestAssetIssue008.java | 282 - .../assetissue/WalletTestAssetIssue009.java | 171 - .../assetissue/WalletTestAssetIssue010.java | 443 - .../assetissue/WalletTestAssetIssue011.java | 133 - .../assetissue/WalletTestAssetIssue012.java | 155 - .../assetissue/WalletTestAssetIssue013.java | 157 - .../assetissue/WalletTestAssetIssue014.java | 154 - .../assetissue/WalletTestAssetIssue015.java | 218 - .../assetissue/WalletTestAssetIssue016.java | 236 - .../assetissue/WalletTestAssetIssue020.java | 225 - .../WalletTestAssetIssue017.java | 347 - .../WalletTestAssetIssue018.java | 238 - .../WalletTestAssetIssue019.java | 171 - .../grammar/ContractGrammar001.java | 375 - .../grammar/ContractGrammar002.java | 335 - .../grammar/ContractGrammar003.java | 522 -- .../grammar/ContractGrammar004.java | 638 -- .../assetmarket/MarketSellAsset001.java | 316 - .../assetmarket/MarketSellAsset002.java | 374 - .../assetmarket/MarketSellAsset003.java | 155 - .../assetmarket/MarketSellAsset004.java | 113 - .../assetmarket/MarketSellAsset005.java | 160 - .../assetmarket/MarketSellAsset006.java | 288 - .../dailybuild/eventquery/EventLog2.java | 117 - .../dailybuild/eventquery/EventQuery001.java | 152 - .../dailybuild/eventquery/EventQuery002.java | 147 - .../dailybuild/eventquery/EventQuery003.java | 214 - .../dailybuild/eventquery/EventQuery004.java | 223 - .../exceptionfee/AssertException.java | 566 -- .../dailybuild/http/HttpRateLimite001.java | 132 - .../dailybuild/http/HttpTestAccount001.java | 107 - .../dailybuild/http/HttpTestAccount002.java | 335 - .../dailybuild/http/HttpTestAccount003.java | 230 - .../dailybuild/http/HttpTestAccount004.java | 115 - .../dailybuild/http/HttpTestAccount005.java | 62 - .../dailybuild/http/HttpTestAsset001.java | 311 - .../dailybuild/http/HttpTestBlock001.java | 383 - .../http/HttpTestClearAbiContract001.java | 185 - .../http/HttpTestConstantContract001.java | 119 - .../dailybuild/http/HttpTestExchange001.java | 314 - .../http/HttpTestGetAccountBalance001.java | 218 - .../dailybuild/http/HttpTestMarket001.java | 533 -- .../dailybuild/http/HttpTestMarket002.java | 534 -- .../http/HttpTestMortgageMechanism01.java | 214 - .../dailybuild/http/HttpTestMutiSign001.java | 224 - .../dailybuild/http/HttpTestProposal001.java | 144 - .../dailybuild/http/HttpTestSendCoin001.java | 164 - .../http/HttpTestSmartContract001.java | 373 - .../http/HttpTestTransactionPending001.java | 100 - .../dailybuild/http/HttpTestZenToken001.java | 382 - .../dailybuild/http/HttpTestZenToken002.java | 332 - .../dailybuild/http/HttpTestZenToken003.java | 308 - .../dailybuild/http/HttpTestZenToken004.java | 289 - .../dailybuild/http/HttpTestZenToken005.java | 174 - .../dailybuild/http/HttpTestZenToken006.java | 176 - .../ContractInternalTransaction001.java | 503 -- .../ContractInternalTransaction002.java | 580 -- .../ContractInternalTransaction003.java | 584 -- .../dailybuild/jsonrpc/Accounts001.java | 1225 --- .../dailybuild/jsonrpc/Accounts002.java | 1290 --- .../dailybuild/jsonrpc/Accounts003.java | 373 - .../dailybuild/jsonrpc/Accounts004.java | 388 - .../jsonrpc/BuildTransaction001.java | 121 - .../jsonrpc/EthSmartContract001.java | 80 - .../dailybuild/jsonrpc/GetBlock001.java | 69 - .../dailybuild/manual/ContractLinkage001.java | 343 - .../dailybuild/manual/ContractLinkage005.java | 345 - .../dailybuild/manual/ContractLinkage006.java | 331 - .../manual/ContractScenario002.java | 239 - .../manual/ContractScenario011.java | 511 -- .../manual/ContractScenario014.java | 231 - .../manual/ContractScenario015.java | 132 - .../dailybuild/manual/ContractTrc1155.java | 696 -- .../manual/ContractUnknownException.java | 343 - ...TransactionInfoByBlockNumFromSolidity.java | 53 - .../dailybuild/manual/RateLimite001.java | 176 - .../dailybuild/manual/RequireException.java | 791 -- .../manual/WalletTestAccount002.java | 163 - .../manual/WalletTestAccount010.java | 128 - .../manual/WalletTestAccount012.java | 188 - .../manual/WalletTestAccount013.java | 515 -- .../manual/WalletTestAccount014.java | 229 - .../manual/WalletTestAccount015.java | 171 - .../dailybuild/manual/WalletTestBlock001.java | 177 - .../dailybuild/manual/WalletTestBlock002.java | 381 - .../manual/WalletTestMutiSign002.java | 459 -- .../dailybuild/manual/WalletTestNode001.java | 106 - .../manual/WalletTestTransfer002.java | 208 - .../manual/WalletTestTransfer005.java | 227 - .../manual/WalletTestTransfer006.java | 229 - .../manual/WalletTestWitness003.java | 326 - .../dailybuild/multisign/MultiSign01.java | 894 --- .../dailybuild/multisign/MultiSign02.java | 719 -- .../dailybuild/multisign/MultiSign03.java | 541 -- .../dailybuild/multisign/MultiSign04.java | 550 -- .../dailybuild/multisign/MultiSign05.java | 746 -- .../dailybuild/multisign/MultiSign06.java | 689 -- .../dailybuild/multisign/MultiSign07.java | 662 -- .../dailybuild/multisign/MultiSign08.java | 623 -- .../dailybuild/multisign/MultiSign09.java | 489 -- .../dailybuild/multisign/MultiSign10.java | 651 -- .../dailybuild/multisign/MultiSign11.java | 1089 --- .../dailybuild/multisign/MultiSign12.java | 501 -- .../dailybuild/multisign/MultiSign13.java | 845 -- .../dailybuild/multisign/MultiSign14.java | 699 -- .../dailybuild/multisign/MultiSign15.java | 597 -- .../dailybuild/multisign/MultiSign16.java | 574 -- .../dailybuild/multisign/MultiSign17.java | 735 -- .../dailybuild/multisign/MultiSign18.java | 612 -- .../dailybuild/multisign/MultiSign19.java | 647 -- .../dailybuild/multisign/MultiSign20.java | 518 -- .../dailybuild/multisign/MultiSign21.java | 228 - .../dailybuild/multisign/MultiSign22.java | 682 -- .../dailybuild/multisign/MultiSign23.java | 1015 --- .../dailybuild/multisign/MultiSign24.java | 280 - .../dailybuild/multisign/MultiSign26.java | 780 -- .../dailybuild/multisign/MultiSign27.java | 604 -- .../dailybuild/multisign/MultiSign28.java | 1134 --- .../dailybuild/multisign/MultiSign29.java | 656 -- .../dailybuild/multisign/MultiSign30.java | 198 - .../dailybuild/multisign/MultiSign31.java | 681 -- .../dailybuild/multisign/MultiSign33.java | 168 - .../dailybuild/multisign/MultiSign34.java | 231 - .../dailybuild/multisign/MultiSign35.java | 299 - .../dailybuild/multisign/MultiSign36.java | 549 -- .../dailybuild/multisign/MultiSign37.java | 416 - .../MutiSignAccountPermissionUpdateTest.java | 192 - ...utiSignAccountPermissionUpdateTest002.java | 192 - .../operationupdate/MutiSignAccountTest.java | 227 - .../MutiSignAccountTest002.java | 217 - .../operationupdate/MutiSignAssetTest.java | 348 - .../operationupdate/MutiSignAssetTest002.java | 348 - .../MutiSignClearContractAbiTest.java | 311 - .../MutiSignExchangeContractTest.java | 414 - .../MutiSignExchangeContractTest002.java | 414 - .../MutiSignMarketAssetTest.java | 217 - .../operationupdate/MutiSignProposalTest.java | 170 - .../MutiSignProposalTest002.java | 169 - .../MutiSignSmartContractTest.java | 195 - .../MutiSignSmartContractTest002.java | 195 - .../MutiSignUpdataBrokerageTest.java | 163 - .../ContractOriginEnergyLimit001.java | 145 - .../ContractOriginEnergyLimit004.java | 378 - .../TransactionPendingQuery001.java | 138 - .../trctoken/ContractTrcToken001.java | 214 - .../trctoken/ContractTrcToken002.java | 285 - .../trctoken/ContractTrcToken003.java | 354 - .../trctoken/ContractTrcToken005.java | 422 - .../trctoken/ContractTrcToken011.java | 476 -- .../trctoken/ContractTrcToken012.java | 373 - .../trctoken/ContractTrcToken014.java | 544 -- .../trctoken/ContractTrcToken018.java | 286 - .../trctoken/ContractTrcToken023.java | 235 - .../trctoken/ContractTrcToken026.java | 514 -- .../trctoken/ContractTrcToken027.java | 490 -- .../trctoken/ContractTrcToken028.java | 189 - .../trctoken/ContractTrcToken029.java | 174 - .../trctoken/ContractTrcToken030.java | 187 - .../trctoken/ContractTrcToken031.java | 171 - .../trctoken/ContractTrcToken034.java | 195 - .../trctoken/ContractTrcToken035.java | 195 - .../trctoken/ContractTrcToken036.java | 527 -- .../trctoken/ContractTrcToken037.java | 205 - .../trctoken/ContractTrcToken038.java | 209 - .../trctoken/ContractTrcToken039.java | 345 - .../trctoken/ContractTrcToken041.java | 198 - .../trctoken/ContractTrcToken043.java | 466 -- .../trctoken/ContractTrcToken048.java | 193 - .../trctoken/ContractTrcToken049.java | 228 - .../trctoken/ContractTrcToken050.java | 203 - .../trctoken/ContractTrcToken051.java | 203 - .../trctoken/ContractTrcToken052.java | 207 - .../trctoken/ContractTrcToken054.java | 272 - .../trctoken/ContractTrcToken055.java | 277 - .../trctoken/ContractTrcToken060.java | 232 - .../trctoken/ContractTrcToken061.java | 218 - .../trctoken/ContractTrcToken064.java | 450 -- .../trctoken/ContractTrcToken066.java | 333 - .../trctoken/ContractTrcToken067.java | 339 - .../trctoken/ContractTrcToken073.java | 260 - .../trctoken/ContractTrcToken075.java | 268 - .../trctoken/ContractTrcToken076.java | 138 - .../trctoken/ContractTrcToken077.java | 184 - .../trctoken/ContractTrcToken078.java | 275 - .../trctoken/ContractTrcToken079.java | 220 - .../trctoken/ContractTrcToken080.java | 195 - .../trctoken/ContractTrcToken081.java | 239 - .../AddressStrictCheck001.java | 144 - .../AddressStrictCheck002.java | 142 - .../batchValidateSignContract001.java | 368 - .../batchValidateSignContract002.java | 675 -- .../batchValidateSignContract003.java | 302 - .../batchValidateSignContract004.java | 534 -- .../batchValidateSignContract005.java | 233 - .../batchValidateSignContract006.java | 426 - .../batchValidateSignContract007.java | 196 - .../batchValidateSignContract008.java | 146 - .../batchValidateSignContract009.java | 225 - .../batchValidateSignContract010.java | 358 - .../batchValidateSignContract011.java | 695 -- .../batchValidateSignContract012.java | 172 - .../tvmnewcommand/clearabi/ClearAbi001.java | 301 - .../tvmnewcommand/clearabi/ClearAbi002.java | 149 - .../tvmnewcommand/clearabi/ClearAbi003.java | 148 - .../tvmnewcommand/clearabi/ClearAbi004.java | 115 - .../tvmnewcommand/clearabi/ClearAbi005.java | 197 - .../tvmnewcommand/clearabi/ClearAbi006.java | 114 - .../tvmnewcommand/clearabi/ClearAbi007.java | 129 - .../tvmnewcommand/clearabi/ClearAbi008.java | 162 - .../tvmnewcommand/clearabi/NoAbi009.java | 356 - .../tvmnewcommand/create2/Create2Test001.java | 558 -- .../tvmnewcommand/create2/Create2Test002.java | 324 - .../tvmnewcommand/create2/Create2Test003.java | 489 -- .../tvmnewcommand/create2/Create2Test004.java | 470 -- .../tvmnewcommand/create2/Create2Test005.java | 358 - .../tvmnewcommand/create2/Create2Test006.java | 1014 --- .../tvmnewcommand/create2/Create2Test007.java | 358 - .../tvmnewcommand/create2/Create2Test008.java | 358 - .../tvmnewcommand/create2/Create2Test009.java | 365 - .../tvmnewcommand/create2/Create2Test010.java | 210 - .../tvmnewcommand/create2/Create2Test011.java | 369 - .../tvmnewcommand/create2/Create2Test012.java | 396 - .../tvmnewcommand/create2/Create2Test013.java | 436 - .../tvmnewcommand/create2/Create2Test014.java | 641 -- .../tvmnewcommand/create2/Create2Test015.java | 499 -- .../tvmnewcommand/create2/Create2Test016.java | 422 - .../tvmnewcommand/create2/Create2Test017.java | 405 - .../tvmnewcommand/create2/Create2Test018.java | 358 - .../tvmnewcommand/create2/Create2Test019.java | 297 - .../tvmnewcommand/create2/Create2Test020.java | 896 --- .../tvmnewcommand/create2/Create2Test021.java | 372 - .../tvmnewcommand/create2/Create2Test023.java | 282 - .../tvmnewcommand/create2/Create2Test024.java | 277 - .../tvmnewcommand/create2/Create2Test025.java | 263 - .../extCodeHash/ExtCodeHashTest001.java | 689 -- .../extCodeHash/ExtCodeHashTest002.java | 246 - .../extCodeHash/ExtCodeHashTest003.java | 336 - .../extCodeHash/ExtCodeHashTest004.java | 256 - .../extCodeHash/ExtCodeHashTest005.java | 713 -- .../extCodeHash/ExtCodeHashTest006.java | 185 - .../extCodeHash/ExtCodeHashTest007.java | 617 -- .../extCodeHash/ExtCodeHashTest008.java | 512 -- .../extCodeHash/ExtCodeHashTest009.java | 512 -- .../extCodeHash/ExtCodeHashTest010.java | 370 - .../extCodeHash/ExtCodeHashTest011.java | 369 - .../isContract/isContractCommand001.java | 340 - .../isContract/isContractCommand002.java | 190 - .../isContract/isContractCommand003.java | 252 - .../tvmnewcommand/istanbul/AltbnTest001.java | 161 - .../istanbul/ChainidAndSelfBalance001.java | 158 - .../istanbul/Create2IstanbulTest001.java | 105 - .../newGrammar/AbiEncodeTest.java | 269 - .../newGrammar/AbstractTest.java | 78 - .../newGrammar/AddressChange.java | 149 - .../newGrammar/AssignToExternalTest.java | 249 - .../newGrammar/BlockhashTest.java | 170 - .../newGrammar/CallValueGasPureTest.java | 136 - .../newGrammar/CallvalueTest.java | 205 - .../newGrammar/ConstantCallStorage001.java | 255 - .../newGrammar/ConstantCallStorage002.java | 421 - .../newGrammar/ConstantCallStorage0425.java | 462 -- .../tvmnewcommand/newGrammar/EthGrammer.java | 539 -- .../newGrammar/EthGrammer02.java | 556 -- .../newGrammar/FixbugTest086.java | 147 - .../newGrammar/FunctionArray2Storage086.java | 158 - .../tvmnewcommand/newGrammar/LengthTest.java | 285 - .../newGrammar/MappingFixTest.java | 186 - .../newGrammar/MappingPopingTest.java | 183 - .../newGrammar/NegativeArrayTest.java | 259 - .../newGrammar/NewFeatureForSolc068.java | 269 - .../newGrammar/NewFeatureForSolc076.java | 133 - .../newGrammar/NewFeatureForSolc080.java | 313 - .../newGrammar/NewFeatureForSolc0811.java | 240 - .../newGrammar/NewFeatureForSolc086.java | 305 - .../newGrammar/NewFeatureForSolidity062.java | 306 - .../tvmnewcommand/newGrammar/Opcode.java | 509 -- .../newGrammar/OverridePrivateFunction.java | 106 - .../newGrammar/OverrideTest001.java | 455 -- .../tvmnewcommand/newGrammar/PayableTest.java | 158 - .../newGrammar/SelectorTest.java | 104 - .../newGrammar/SlotAndOffsetNewGrammer.java | 153 - .../newGrammar/StringSplitTest.java | 167 - .../tvmnewcommand/newGrammar/TvmVote.java | 334 - .../newGrammar/VirtualTest001.java | 207 - .../newGrammar/assemblyTest.java | 118 - .../newGrammar/calldataTest.java | 155 - .../newGrammar/constructorDefaultsTest.java | 105 - .../newGrammar/enumAndStructTest.java | 89 - .../newGrammar/fallbackOldVersion.java | 156 - .../newGrammar/fallbackReceive.java | 376 - .../newGrammar/mappingGetterTest.java | 158 - .../newGrammar/stateVariableShadowing.java | 140 - .../newGrammar/typeNameTest.java | 174 - .../shiftcommand/ShiftCommand001.java | 253 - .../shiftcommand/ShiftCommand002.java | 265 - .../shiftcommand/ShiftCommand003.java | 332 - .../shiftcommand/ShiftCommand004.java | 1040 --- .../shiftcommand/ShiftCommand005.java | 1049 --- .../shiftcommand/ShiftCommand006.java | 1539 ---- .../ContractTestSendCoin001.java | 624 -- .../transferfailed/TestResourceReceiver.java | 189 - .../transferfailed/TransferFailed001.java | 920 --- .../transferfailed/TransferFailed002.java | 582 -- .../transferfailed/TransferFailed003.java | 817 -- .../transferfailed/TransferFailed004.java | 576 -- .../transferfailed/TransferFailed005.java | 493 -- .../transferfailed/TransferFailed006.java | 229 - .../transferfailed/TransferFailed007.java | 201 - .../transferfailed/TransferFailed008.java | 485 -- .../triggerconstant/TriggerConstant001.java | 1684 ---- .../triggerconstant/TriggerConstant002.java | 150 - .../triggerconstant/TriggerConstant003.java | 243 - .../triggerconstant/TriggerConstant004.java | 153 - .../triggerconstant/TriggerConstant005.java | 141 - .../triggerconstant/TriggerConstant006.java | 150 - .../triggerconstant/TriggerConstant007.java | 153 - .../triggerconstant/TriggerConstant008.java | 153 - .../triggerconstant/TriggerConstant009.java | 176 - .../triggerconstant/TriggerConstant010.java | 176 - .../triggerconstant/TriggerConstant011.java | 177 - .../triggerconstant/TriggerConstant012.java | 177 - .../triggerconstant/TriggerConstant013.java | 338 - .../triggerconstant/TriggerConstant014.java | 277 - .../triggerconstant/TriggerConstant015.java | 201 - .../triggerconstant/TriggerConstant016.java | 196 - .../triggerconstant/TriggerConstant017.java | 175 - .../triggerconstant/TriggerConstant018.java | 151 - .../triggerconstant/TriggerConstant019.java | 175 - .../triggerconstant/TriggerConstant020.java | 175 - .../triggerconstant/TriggerConstant021.java | 149 - .../triggerconstant/TriggerConstant022.java | 154 - .../triggerconstant/TriggerConstant023.java | 154 - .../triggerconstant/TriggerConstant024.java | 158 - .../triggerconstant/TriggerConstant025.java | 155 - .../triggerconstant/TriggerConstant026.java | 159 - .../triggerconstant/TriggerConstant027.java | 159 - .../tryCatch/tryCatchTest001.java | 254 - .../tryCatch/tryCatchTest002.java | 252 - .../tvmFreeze/FreezeContractTest001.java | 506 -- .../tvmFreeze/FreezeContractTest002.java | 271 - .../tvmFreeze/FreezeSuicideTest001.java | 290 - .../tvmassetissue/TvmAssetIssue001.java | 282 - .../tvmassetissue/TvmAssetIssue002.java | 744 -- .../tvmassetissue/TvmAssetIssue003.java | 864 -- .../tvmassetissue/TvmAssetIssue004.java | 205 - .../tvmassetissue/TvmAssetIssue005.java | 703 -- .../tvmstake/ContractRewardTest001.java | 233 - .../tvmstake/IsSrCandidateTest001.java | 118 - .../tvmstake/StackSuicideTest001.java | 247 - .../tvmstake/StakeSuicideTest002.java | 186 - .../tvmstake/StakeSuicideTest003.java | 196 - .../tvmstake/StakeSuicideTest004.java | 397 - .../tvmstake/StakeSuicideTest005.java | 204 - .../tvmnewcommand/tvmstake/StakeTest001.java | 312 - .../tvmstake/UnStakeTest001.java | 471 -- .../TestValidatemultisign001.java | 506 -- .../TestValidatemultisign002.java | 378 - .../TestValidatemultisign003.java | 242 - .../zenProofCommand/VerifyBurnProof001.java | 326 - .../zenProofCommand/VerifyMintProof001.java | 457 -- .../zenProofCommand/pedersenHash001.java | 166 - .../zenProofCommand/pedersenHash002.java | 476 -- .../verifyTransferProof001.java | 802 -- .../zentoken/WalletTestZenToken001.java | 262 - .../zentoken/WalletTestZenToken002.java | 403 - .../zentoken/WalletTestZenToken003.java | 474 -- .../zentoken/WalletTestZenToken004.java | 286 - .../zentoken/WalletTestZenToken005.java | 215 - .../zentoken/WalletTestZenToken006.java | 266 - .../zentoken/WalletTestZenToken007.java | 639 -- .../zentoken/WalletTestZenToken008.java | 214 - .../zentoken/WalletTestZenToken009.java | 222 - .../zentoken/WalletTestZenToken010.java | 260 - .../zentoken/WalletTestZenToken011.java | 144 - .../HttpShieldTrc20Token001.java | 206 - .../HttpShieldTrc20Token002.java | 200 - .../HttpShieldTrc20Token003.java | 289 - .../HttpShieldTrc20Token004.java | 376 - .../HttpShieldTrc20Token005.java | 197 - .../zentrc20token/ShieldTrc20Token001.java | 84 - .../zentrc20token/ShieldTrc20Token002.java | 132 - .../zentrc20token/ShieldTrc20Token003.java | 216 - .../zentrc20token/ShieldTrc20Token004.java | 307 - .../zentrc20token/ShieldTrc20Token005.java | 276 - .../zentrc20token/ShieldTrc20Token006.java | 525 -- .../tron/wallet/fulltest/AttackSendcoin.java | 439 - .../tron/wallet/fulltest/ContinueVote.java | 410 - .../tron/wallet/fulltest/Creatasset.java | 189 - .../wallet/fulltest/CreateAddressAndKey.java | 234 - .../wallet/fulltest/FreezeAndSendcoin.java | 321 - .../stest/tron/wallet/fulltest/Fuzzytest.java | 223 - .../fulltest/ParticipateAssetIssue.java | 341 - .../fulltest/SuperWitnessAllowance.java | 398 - .../wallet/fulltest/TransferAssetIssue.java | 371 - .../stest/tron/wallet/fulltest/TronDice.java | 138 - .../tron/wallet/fulltest/TvmContract.java | 150 - .../mutisign/WalletTestMutiSign001.java | 342 - .../mutisign/WalletTestMutiSign003.java | 200 - .../mutisign/WalletTestMutiSign004.java | 198 - .../mutisign/WalletTestMutiSign005.java | 167 - .../newaddinterface2/CreateAccount2Test.java | 120 - .../CreateAssetIssue2Test.java | 398 - .../CreateTransaction2Test.java | 352 - .../CreateaAndUpdateWitness2Test.java | 433 - .../newaddinterface2/FreezeBalance2Test.java | 478 -- .../GetBlockByLatestNum2Test.java | 178 - .../GetBlockByLimitNext2.java | 204 - .../newaddinterface2/GetBlockByNum2Test.java | 265 - .../newaddinterface2/GetNowBlock2Test.java | 177 - .../GetTransactionsFromThis2Test.java | 220 - .../GetTransactionsToThis2.java | 234 - .../ParticipateAssetIssue2Test.java | 358 - .../newaddinterface2/TransferAsset2Test.java | 402 - .../newaddinterface2/UnfreezeAsset2Test.java | 632 -- .../newaddinterface2/UpdateAccount2Test.java | 961 --- .../newaddinterface2/UpdateAsset2Test.java | 467 -- .../VoteWitnessAccount2Test.java | 585 -- .../WithdrawBalance2Test.java | 308 - .../wallet/onlinestress/ContractEvent001.java | 757 -- .../wallet/onlinestress/CycleMultiSign.java | 253 - .../onlinestress/DelayTransactionStress.java | 340 - .../onlinestress/ExtCodeHashStressTest.java | 619 -- .../wallet/onlinestress/HttpStressTest.java | 160 - .../MainNetTransferSendOrAsset.java | 153 - .../MainNetVoteOrFreezeOrCreate.java | 359 - .../MultiValiSignPerformanceTest.java | 336 - .../wallet/onlinestress/MutiSignStress.java | 143 - .../wallet/onlinestress/ScanBlockTools.java | 1100 --- .../onlinestress/ShieldTrc10Stress.java | 147 - .../onlinestress/ShieldTrc20Stress.java | 719 -- .../onlinestress/SupportTronlinkAutoTest.java | 374 - .../onlinestress/TestApproveProposal.java | 169 - .../onlinestress/TestExchangeTransaction.java | 176 - .../TestMapBigLongAndNumbers.java | 183 - .../onlinestress/TestMutiSignStress.java | 146 - .../wallet/onlinestress/TestNetErc721Cat.java | 389 - .../wallet/onlinestress/TestNetFomo3D.java | 207 - .../wallet/onlinestress/TestOperations.java | 43 - .../onlinestress/TestStorageAndCpu.java | 233 - .../TestTransferTokenInContract.java | 324 - .../wallet/onlinestress/TransactionCheck.java | 52 - .../WalletTestZenTokenStress.java | 268 - .../tron/wallet/other/deployMainGateway.java | 129 - .../tron/wallet/other/deploySideGateway.java | 122 - .../transfer/WalletTestTransfer001.java | 320 - .../transfer/WalletTestTransfer003.java | 389 - .../transfer/WalletTestTransfer004.java | 288 - .../transfer/WalletTestTransfer007.java | 149 - .../MutisignOperationerGodicTest.java | 504 -- .../wallet/witness/WalletTestWitness001.java | 399 - .../wallet/witness/WalletTestWitness002.java | 210 - 555 files changed, 253 insertions(+), 177099 deletions(-) rename framework/src/test/java/{stest/tron/wallet/common => org/tron/common/utils}/client/Configuration.java (90%) rename framework/src/test/java/{stest/tron/wallet/common => org/tron/common/utils}/client/GrpcClient.java (99%) rename framework/src/test/java/{stest/tron/wallet/common => org/tron/common/utils}/client/Parameter.java (89%) rename framework/src/test/java/{stest/tron/wallet/common => org/tron/common/utils}/client/WalletClient.java (99%) rename framework/src/test/java/{stest/tron/wallet/common => org/tron/common/utils}/client/WitnessComparator.java (85%) rename framework/src/test/java/{stest/tron/wallet/common => org/tron/common/utils}/client/utils/AbiUtil.java (99%) rename framework/src/test/java/{stest/tron/wallet/common => org/tron/common/utils}/client/utils/Base58.java (99%) rename framework/src/test/java/{stest/tron/wallet/common => org/tron/common/utils}/client/utils/ByteArrayWrapper.java (97%) rename framework/src/test/java/{stest/tron/wallet/common => org/tron/common/utils}/client/utils/DataWord.java (99%) rename framework/src/test/java/{stest/tron/wallet/common => org/tron/common/utils}/client/utils/HttpMethed.java (97%) rename framework/src/test/java/{stest/tron/wallet/common => org/tron/common/utils}/client/utils/JSONObjectWarp.java (77%) mode change 100755 => 100644 rename framework/src/test/java/{stest/tron/wallet/common => org/tron/common/utils}/client/utils/Sha256Sm3Hash.java (97%) rename framework/src/test/java/{stest/tron/wallet/common => org/tron/common/utils}/client/utils/ShieldAddressInfo.java (98%) rename framework/src/test/java/{stest/tron/wallet/common => org/tron/common/utils}/client/utils/ShieldNoteInfo.java (97%) rename framework/src/test/java/{stest/tron/wallet/common => org/tron/common/utils}/client/utils/TransactionUtils.java (99%) delete mode 100644 framework/src/test/java/stest/tron/wallet/account/BrokerageTest001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/account/WalletTestAccount001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/account/WalletTestAccount003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/account/WalletTestAccount004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/account/WalletTestAccount005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/account/WalletTestAccount006.java delete mode 100644 framework/src/test/java/stest/tron/wallet/account/WalletTestAccount007.java delete mode 100644 framework/src/test/java/stest/tron/wallet/account/WalletTestAccount009.java delete mode 100644 framework/src/test/java/stest/tron/wallet/account/WalletTestAccount011.java delete mode 100644 framework/src/test/java/stest/tron/wallet/block/WalletTestBlock003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/block/WalletTestBlock004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/block/WalletTestBlock005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/block/WalletTestBlock006.java delete mode 100644 framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/common/client/utils/CipherException.java delete mode 100644 framework/src/test/java/stest/tron/wallet/common/client/utils/DailyBuildReport.java delete mode 100644 framework/src/test/java/stest/tron/wallet/common/client/utils/FileUtil.java delete mode 100644 framework/src/test/java/stest/tron/wallet/common/client/utils/JsonRpcBase.java delete mode 100644 framework/src/test/java/stest/tron/wallet/common/client/utils/PublicMethed.java delete mode 100644 framework/src/test/java/stest/tron/wallet/common/client/utils/PublicMethedForMutiSign.java delete mode 100644 framework/src/test/java/stest/tron/wallet/common/client/utils/Retry.java delete mode 100644 framework/src/test/java/stest/tron/wallet/common/client/utils/RetryListener.java delete mode 100644 framework/src/test/java/stest/tron/wallet/common/client/utils/Sha256Hash.java delete mode 100644 framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldWrapper.java delete mode 100644 framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldedAddressInfo.java delete mode 100644 framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldedTRC20NoteInfo.java delete mode 100644 framework/src/test/java/stest/tron/wallet/common/client/utils/ZenTrc20Base.java delete mode 100644 framework/src/test/java/stest/tron/wallet/common/client/utils/ZenUtils.java delete mode 100644 framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage007.java delete mode 100644 framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario006.java delete mode 100644 framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario007.java delete mode 100644 framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario008.java delete mode 100644 framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario009.java delete mode 100644 framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario010.java delete mode 100644 framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario012.java delete mode 100644 framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario013.java delete mode 100644 framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario014.java delete mode 100644 framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario015.java delete mode 100644 framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario016.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/account/GetAccountBalance001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/account/TransactionFee001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/account/WalletTestAccount012.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletExchange001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue006.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue007.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue008.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue009.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue010.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue011.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue012.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue013.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue014.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue015.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue016.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue020.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue017.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue018.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue019.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset006.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventLog2.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/exceptionfee/AssertException.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpRateLimite001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAsset001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestBlock001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestClearAbiContract001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestConstantContract001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestExchange001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestGetAccountBalance001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMarket001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMarket002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMortgageMechanism01.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMutiSign001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestProposal001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestSendCoin001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestSmartContract001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestTransactionPending001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken006.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/BuildTransaction001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/EthSmartContract001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/GetBlock001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage006.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario011.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario014.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario015.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractTrc1155.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractUnknownException.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/GetTransactionInfoByBlockNumFromSolidity.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/RateLimite001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/RequireException.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount010.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount012.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount013.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount014.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount015.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestBlock001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestBlock002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestMutiSign002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestNode001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer006.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestWitness003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign01.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign02.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign03.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign04.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign05.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign06.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign07.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign08.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign09.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign10.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign11.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign12.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign13.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign14.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign15.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign16.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign17.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign18.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign19.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign20.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign21.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign22.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign23.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign24.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign26.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign27.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign28.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign29.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign30.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign31.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign33.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign34.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign35.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign36.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign37.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountPermissionUpdateTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountPermissionUpdateTest002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountTest002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAssetTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAssetTest002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignClearContractAbiTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignExchangeContractTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignExchangeContractTest002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignMarketAssetTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignProposalTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignProposalTest002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignSmartContractTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignSmartContractTest002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignUpdataBrokerageTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/transaction/TransactionPendingQuery001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken011.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken012.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken014.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken018.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken023.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken026.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken027.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken028.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken029.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken030.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken031.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken034.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken035.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken036.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken037.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken038.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken039.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken041.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken043.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken048.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken049.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken050.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken051.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken052.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken054.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken055.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken060.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken061.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken064.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken066.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken067.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken073.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken075.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken076.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken077.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken078.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken079.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken080.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken081.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/addressStrictCheck/AddressStrictCheck001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/addressStrictCheck/AddressStrictCheck002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract006.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract007.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract008.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract009.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract010.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract011.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract012.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi006.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi007.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi008.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/NoAbi009.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test006.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test007.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test008.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test009.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test010.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test011.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test012.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test013.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test014.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test015.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test016.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test017.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test018.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test019.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test020.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test021.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test023.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test024.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test025.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest006.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest007.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest008.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest009.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest010.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest011.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/AltbnTest001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/ChainidAndSelfBalance001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/Create2IstanbulTest001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AbiEncodeTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AbstractTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AddressChange.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AssignToExternalTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/BlockhashTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/CallValueGasPureTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/CallvalueTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage0425.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/EthGrammer.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/EthGrammer02.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/FixbugTest086.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/FunctionArray2Storage086.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/LengthTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/MappingFixTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/MappingPopingTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NegativeArrayTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc068.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc076.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc080.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc0811.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc086.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolidity062.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/Opcode.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/OverridePrivateFunction.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/OverrideTest001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/PayableTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/SelectorTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/SlotAndOffsetNewGrammer.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/StringSplitTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/TvmVote.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/VirtualTest001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/assemblyTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/calldataTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/constructorDefaultsTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/enumAndStructTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/fallbackOldVersion.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/fallbackReceive.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/mappingGetterTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/stateVariableShadowing.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/typeNameTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand006.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/ContractTestSendCoin001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TestResourceReceiver.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed006.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed007.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed008.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant006.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant007.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant008.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant009.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant010.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant011.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant012.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant013.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant014.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant015.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant016.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant017.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant018.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant019.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant020.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant021.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant022.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant023.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant024.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant025.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant026.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant027.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tryCatch/tryCatchTest001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tryCatch/tryCatchTest002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeContractTest001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeContractTest002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeSuicideTest001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/ContractRewardTest001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/IsSrCandidateTest001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StackSuicideTest001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeTest001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/UnStakeTest001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/VerifyBurnProof001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/VerifyMintProof001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/pedersenHash001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/pedersenHash002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/verifyTransferProof001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken006.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken007.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken008.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken009.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken010.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken011.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token002.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token006.java delete mode 100644 framework/src/test/java/stest/tron/wallet/fulltest/AttackSendcoin.java delete mode 100644 framework/src/test/java/stest/tron/wallet/fulltest/ContinueVote.java delete mode 100644 framework/src/test/java/stest/tron/wallet/fulltest/Creatasset.java delete mode 100644 framework/src/test/java/stest/tron/wallet/fulltest/CreateAddressAndKey.java delete mode 100644 framework/src/test/java/stest/tron/wallet/fulltest/FreezeAndSendcoin.java delete mode 100644 framework/src/test/java/stest/tron/wallet/fulltest/Fuzzytest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/fulltest/ParticipateAssetIssue.java delete mode 100644 framework/src/test/java/stest/tron/wallet/fulltest/SuperWitnessAllowance.java delete mode 100644 framework/src/test/java/stest/tron/wallet/fulltest/TransferAssetIssue.java delete mode 100644 framework/src/test/java/stest/tron/wallet/fulltest/TronDice.java delete mode 100644 framework/src/test/java/stest/tron/wallet/fulltest/TvmContract.java delete mode 100644 framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign005.java delete mode 100644 framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateAccount2Test.java delete mode 100644 framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateAssetIssue2Test.java delete mode 100644 framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateTransaction2Test.java delete mode 100644 framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateaAndUpdateWitness2Test.java delete mode 100644 framework/src/test/java/stest/tron/wallet/newaddinterface2/FreezeBalance2Test.java delete mode 100644 framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByLatestNum2Test.java delete mode 100644 framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByLimitNext2.java delete mode 100644 framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByNum2Test.java delete mode 100644 framework/src/test/java/stest/tron/wallet/newaddinterface2/GetNowBlock2Test.java delete mode 100644 framework/src/test/java/stest/tron/wallet/newaddinterface2/GetTransactionsFromThis2Test.java delete mode 100644 framework/src/test/java/stest/tron/wallet/newaddinterface2/GetTransactionsToThis2.java delete mode 100644 framework/src/test/java/stest/tron/wallet/newaddinterface2/ParticipateAssetIssue2Test.java delete mode 100644 framework/src/test/java/stest/tron/wallet/newaddinterface2/TransferAsset2Test.java delete mode 100644 framework/src/test/java/stest/tron/wallet/newaddinterface2/UnfreezeAsset2Test.java delete mode 100644 framework/src/test/java/stest/tron/wallet/newaddinterface2/UpdateAccount2Test.java delete mode 100644 framework/src/test/java/stest/tron/wallet/newaddinterface2/UpdateAsset2Test.java delete mode 100644 framework/src/test/java/stest/tron/wallet/newaddinterface2/VoteWitnessAccount2Test.java delete mode 100644 framework/src/test/java/stest/tron/wallet/newaddinterface2/WithdrawBalance2Test.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/ContractEvent001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/CycleMultiSign.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/DelayTransactionStress.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/ExtCodeHashStressTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/HttpStressTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/MainNetTransferSendOrAsset.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/MainNetVoteOrFreezeOrCreate.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/MultiValiSignPerformanceTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/MutiSignStress.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/ScanBlockTools.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/ShieldTrc10Stress.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/ShieldTrc20Stress.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/SupportTronlinkAutoTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/TestApproveProposal.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/TestExchangeTransaction.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/TestMapBigLongAndNumbers.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/TestMutiSignStress.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/TestNetErc721Cat.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/TestNetFomo3D.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/TestOperations.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/TestStorageAndCpu.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/TestTransferTokenInContract.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/TransactionCheck.java delete mode 100644 framework/src/test/java/stest/tron/wallet/onlinestress/WalletTestZenTokenStress.java delete mode 100644 framework/src/test/java/stest/tron/wallet/other/deployMainGateway.java delete mode 100644 framework/src/test/java/stest/tron/wallet/other/deploySideGateway.java delete mode 100644 framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer003.java delete mode 100644 framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer004.java delete mode 100644 framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer007.java delete mode 100644 framework/src/test/java/stest/tron/wallet/updateCompatibility/MutisignOperationerGodicTest.java delete mode 100644 framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness001.java delete mode 100644 framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness002.java diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index 6b85c69867b..7ad8069db06 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -10,6 +10,8 @@ import org.tron.core.Constant; import org.tron.core.config.args.Args; + + public class ArgsTest { private static final String dbPath = "output_arg_test"; @@ -43,4 +45,4 @@ public void testConfig() { Assert.assertEquals(rateLimiter.getHttpMap().size(), 1); Assert.assertEquals(rateLimiter.getRpcMap().size(), 0); } -} \ No newline at end of file +} diff --git a/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java b/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java index 868eb4caea8..b40b927c5ec 100644 --- a/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java +++ b/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java @@ -9,6 +9,7 @@ import org.testng.Assert; import org.tron.common.BaseTest; import org.tron.common.utils.WalletUtil; +import org.tron.common.utils.client.utils.DataWord; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.config.args.Args; @@ -20,7 +21,6 @@ import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.utils.DataWord; @Slf4j public class RuntimeTransferComplexTest extends BaseTest { diff --git a/framework/src/test/java/org/tron/common/runtime/TvmTestUtils.java b/framework/src/test/java/org/tron/common/runtime/TvmTestUtils.java index a90010f3043..5a9a77e108a 100644 --- a/framework/src/test/java/org/tron/common/runtime/TvmTestUtils.java +++ b/framework/src/test/java/org/tron/common/runtime/TvmTestUtils.java @@ -10,7 +10,11 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.tron.common.crypto.Hash; +import org.tron.common.utils.PublicMethod; import org.tron.common.utils.WalletUtil; +import org.tron.common.utils.client.Parameter.CommonConstant; +import org.tron.common.utils.client.WalletClient; +import org.tron.common.utils.client.utils.AbiUtil; import org.tron.core.Wallet; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.TransactionCapsule; @@ -23,15 +27,12 @@ import org.tron.core.store.StoreFactory; import org.tron.core.vm.repository.Repository; import org.tron.core.vm.repository.RepositoryImpl; + import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; import org.tron.protos.contract.SmartContractOuterClass.SmartContract; import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.AbiUtil; -import stest.tron.wallet.common.client.utils.PublicMethed; /** @@ -621,7 +622,7 @@ public static CreateSmartContract createSmartContract(byte[] owner, String contr String abiString, String code, long value, long consumeUserResourcePercent) { Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - SmartContract.ABI abi = PublicMethed.jsonStr2Abi(abiString); + SmartContract.ABI abi = jsonStr2Abi(abiString); if (abi == null) { return null; } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmCompatibleEvmTest.java b/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmCompatibleEvmTest.java index 0f3cae8476a..ffc3a44e730 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmCompatibleEvmTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmCompatibleEvmTest.java @@ -13,14 +13,15 @@ import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.WalletUtil; +import org.tron.common.utils.client.utils.AbiUtil; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; import org.tron.core.vm.config.ConfigLoader; import org.tron.core.vm.config.VMConfig; + import org.tron.protos.Protocol; -import stest.tron.wallet.common.client.utils.AbiUtil; @Slf4j public class AllowTvmCompatibleEvmTest extends VMTestBase { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmLondonTest.java b/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmLondonTest.java index 42725d1cbd7..864a583050b 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmLondonTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmLondonTest.java @@ -10,6 +10,7 @@ import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.WalletUtil; +import org.tron.common.utils.client.utils.AbiUtil; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; @@ -17,7 +18,6 @@ import org.tron.core.vm.config.ConfigLoader; import org.tron.core.vm.config.VMConfig; import org.tron.protos.Protocol; -import stest.tron.wallet.common.client.utils.AbiUtil; @Slf4j public class AllowTvmLondonTest extends VMTestBase { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java index 88067be30e9..a5c397e54c2 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java @@ -15,6 +15,7 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.StringUtil; import org.tron.common.utils.Utils; +import org.tron.common.utils.client.utils.AbiUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; @@ -27,7 +28,6 @@ import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.utils.AbiUtil; @Slf4j public class BatchSendTest extends BaseTest { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BatchValidateSignContractTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BatchValidateSignContractTest.java index f7226bb3b3d..524c40ee8fb 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BatchValidateSignContractTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BatchValidateSignContractTest.java @@ -6,16 +6,16 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; import org.bouncycastle.util.encoders.Hex; -import org.junit.Ignore; import org.junit.Test; import org.testng.Assert; import org.tron.common.crypto.ECKey; import org.tron.common.crypto.Hash; import org.tron.common.utils.StringUtil; +import org.tron.common.utils.client.utils.AbiUtil; import org.tron.core.db.TransactionTrace; import org.tron.core.vm.PrecompiledContracts; import org.tron.core.vm.PrecompiledContracts.BatchValidateSign; -import stest.tron.wallet.common.client.utils.AbiUtil; + @Slf4j public class BatchValidateSignContractTest { @@ -76,7 +76,7 @@ public void staticCallTest() { Assert.assertEquals(ret.getValue(), new byte[32]); System.gc(); // force triggering full gc to avoid timeout for next test } - + @Test public void correctionTest() { contract.setConstantCall(false); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java index 074b157f115..868e7b1c558 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java @@ -13,6 +13,8 @@ import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.ByteArray; import org.tron.common.utils.WalletUtil; +import org.tron.common.utils.client.utils.AbiUtil; +import org.tron.common.utils.client.utils.DataWord; import org.tron.core.Wallet; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; @@ -22,8 +24,6 @@ import org.tron.core.services.NodeInfoService; import org.tron.core.services.jsonrpc.TronJsonRpcImpl; import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.utils.AbiUtil; -import stest.tron.wallet.common.client.utils.DataWord; @Slf4j public class Create2Test extends VMTestBase { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/ExtCodeHashTest.java b/framework/src/test/java/org/tron/common/runtime/vm/ExtCodeHashTest.java index 8acc8ed494b..d8c8a23a8ee 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/ExtCodeHashTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/ExtCodeHashTest.java @@ -9,12 +9,12 @@ import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.WalletUtil; +import org.tron.common.utils.client.utils.AbiUtil; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.utils.AbiUtil; @Slf4j public class ExtCodeHashTest extends VMTestBase { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java index ae655e6eb24..600000e6535 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java @@ -26,6 +26,7 @@ import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.common.utils.WalletUtil; +import org.tron.common.utils.client.utils.AbiUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; @@ -46,7 +47,6 @@ import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol; import org.tron.protos.Protocol.Transaction.Result.contractResult; -import stest.tron.wallet.common.client.utils.AbiUtil; @Slf4j public class FreezeTest { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java index 441aee15676..78096564e48 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -30,6 +30,7 @@ import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.common.utils.WalletUtil; +import org.tron.common.utils.client.utils.AbiUtil; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -55,7 +56,6 @@ import org.tron.protos.Protocol; import org.tron.protos.Protocol.Transaction.Result.contractResult; import org.tron.protos.contract.Common; -import stest.tron.wallet.common.client.utils.AbiUtil; @Slf4j public class FreezeV2Test { @@ -1060,4 +1060,4 @@ public void destroy() { logger.error("Release resources failure."); } } -} \ No newline at end of file +} diff --git a/framework/src/test/java/org/tron/common/runtime/vm/IsContractTest.java b/framework/src/test/java/org/tron/common/runtime/vm/IsContractTest.java index d5d6a18b031..540a30a240f 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/IsContractTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/IsContractTest.java @@ -9,6 +9,7 @@ import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.StringUtil; import org.tron.common.utils.WalletUtil; +import org.tron.common.utils.client.utils.AbiUtil; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; @@ -16,7 +17,6 @@ import org.tron.core.vm.config.ConfigLoader; import org.tron.core.vm.config.VMConfig; import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.utils.AbiUtil; @Slf4j public class IsContractTest extends VMTestBase { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/IsSRCandidateTest.java b/framework/src/test/java/org/tron/common/runtime/vm/IsSRCandidateTest.java index e95eaf46189..3cec683ed63 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/IsSRCandidateTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/IsSRCandidateTest.java @@ -9,6 +9,7 @@ import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.StringUtil; import org.tron.common.utils.WalletUtil; +import org.tron.common.utils.client.utils.AbiUtil; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; @@ -22,7 +23,6 @@ import org.tron.core.vm.repository.Repository; import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.utils.AbiUtil; @Slf4j public class IsSRCandidateTest extends VMTestBase { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java index 4779c90205d..d97be9581b7 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java @@ -15,6 +15,8 @@ import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.client.WalletClient; import org.tron.common.zksnark.IncrementalMerkleTreeContainer; import org.tron.common.zksnark.IncrementalMerkleVoucherContainer; import org.tron.common.zksnark.JLibrustzcash; @@ -39,7 +41,6 @@ import org.tron.core.zen.note.Note; import org.tron.keystore.Wallet; import org.tron.protos.contract.ShieldContract; -import stest.tron.wallet.common.client.WalletClient; @Slf4j public class PrecompiledContractsVerifyProofTest extends BaseTest { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/RewardBalanceTest.java b/framework/src/test/java/org/tron/common/runtime/vm/RewardBalanceTest.java index 1711f8441e6..b9fa24712c9 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/RewardBalanceTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/RewardBalanceTest.java @@ -10,6 +10,7 @@ import org.tron.common.utils.Base58; import org.tron.common.utils.StringUtil; import org.tron.common.utils.WalletUtil; +import org.tron.common.utils.client.utils.AbiUtil; import org.tron.core.capsule.BlockCapsule; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; @@ -25,7 +26,6 @@ import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol; import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.utils.AbiUtil; @Slf4j public class RewardBalanceTest extends VMTestBase { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/TransferFailedEnergyTest.java b/framework/src/test/java/org/tron/common/runtime/vm/TransferFailedEnergyTest.java index 51d8e8dafae..8a3bbbbeede 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/TransferFailedEnergyTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/TransferFailedEnergyTest.java @@ -12,6 +12,7 @@ import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.WalletUtil; +import org.tron.common.utils.client.utils.AbiUtil; import org.tron.core.capsule.ReceiptCapsule; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; @@ -20,7 +21,6 @@ import org.tron.core.vm.config.ConfigLoader; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Result.contractResult; -import stest.tron.wallet.common.client.utils.AbiUtil; public class TransferFailedEnergyTest extends VMTestBase { /* diff --git a/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java b/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java index cd79e00eb29..13f01847c81 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java @@ -14,6 +14,8 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.StringUtil; import org.tron.common.utils.Utils; +import org.tron.common.utils.client.utils.AbiUtil; +import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.actuator.VMActuator; @@ -33,7 +35,6 @@ import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction; import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import stest.tron.wallet.common.client.utils.AbiUtil; @Slf4j public class TransferToAccountTest extends BaseTest { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java b/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java index 1ee561aa97d..e6ef013bd85 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java @@ -19,6 +19,7 @@ import org.tron.common.utils.ByteUtil; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.StringUtil; +import org.tron.common.utils.client.utils.AbiUtil; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; import org.tron.core.config.args.Args; @@ -27,7 +28,7 @@ import org.tron.core.vm.repository.Repository; import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol; -import stest.tron.wallet.common.client.utils.AbiUtil; + @Slf4j public class ValidateMultiSignContractTest extends BaseTest { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java b/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java index 9622c8a1b25..22a33993589 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java @@ -30,6 +30,8 @@ import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.common.utils.WalletUtil; +import org.tron.common.utils.client.utils.AbiUtil; +import org.tron.common.utils.client.utils.DataWord; import org.tron.consensus.dpos.MaintenanceManager; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -47,8 +49,6 @@ import org.tron.core.vm.repository.Repository; import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol; -import stest.tron.wallet.common.client.utils.AbiUtil; -import stest.tron.wallet.common.client.utils.DataWord; @Slf4j public class VoteTest { diff --git a/framework/src/test/java/org/tron/common/utils/PublicMethod.java b/framework/src/test/java/org/tron/common/utils/PublicMethod.java index b6e8f661b2c..1088ff25ba2 100644 --- a/framework/src/test/java/org/tron/common/utils/PublicMethod.java +++ b/framework/src/test/java/org/tron/common/utils/PublicMethod.java @@ -1,5 +1,8 @@ package org.tron.common.utils; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; import com.google.protobuf.ByteString; import java.io.IOException; @@ -8,16 +11,168 @@ import java.net.Socket; import java.util.Random; +import lombok.extern.slf4j.Slf4j; import org.tron.api.GrpcAPI; import org.tron.api.WalletGrpc; import org.tron.common.crypto.ECKey; +import org.tron.common.utils.client.utils.TransactionUtils; import org.tron.core.Wallet; import org.tron.protos.Protocol; import org.tron.protos.contract.BalanceContract; -import stest.tron.wallet.common.client.utils.TransactionUtils; +import org.tron.protos.contract.SmartContractOuterClass; +@Slf4j public class PublicMethod { + /** constructor. */ + public static SmartContractOuterClass.SmartContract.ABI jsonStr2Abi(String jsonStr) { + if (jsonStr == null) { + return null; + } + + JsonParser jsonParser = new JsonParser(); + JsonElement jsonElementRoot = jsonParser.parse(jsonStr); + JsonArray jsonRoot = jsonElementRoot.getAsJsonArray(); + SmartContractOuterClass.SmartContract.ABI.Builder abiBuilder = + SmartContractOuterClass.SmartContract.ABI.newBuilder(); + for (int index = 0; index < jsonRoot.size(); index++) { + JsonElement abiItem = jsonRoot.get(index); + boolean anonymous = + abiItem.getAsJsonObject().get("anonymous") != null + && abiItem.getAsJsonObject().get("anonymous").getAsBoolean(); + final boolean constant = + abiItem.getAsJsonObject().get("constant") != null + && abiItem.getAsJsonObject().get("constant").getAsBoolean(); + final String name = + abiItem.getAsJsonObject().get("name") != null + ? abiItem.getAsJsonObject().get("name").getAsString() + : null; + JsonArray inputs = + abiItem.getAsJsonObject().get("inputs") != null + ? abiItem.getAsJsonObject().get("inputs").getAsJsonArray() : null; + final JsonArray outputs = + abiItem.getAsJsonObject().get("outputs") != null + ? abiItem.getAsJsonObject().get("outputs").getAsJsonArray() : null; + String type = + abiItem.getAsJsonObject().get("type") != null + ? abiItem.getAsJsonObject().get("type").getAsString() : null; + final boolean payable = + abiItem.getAsJsonObject().get("payable") != null + && abiItem.getAsJsonObject().get("payable").getAsBoolean(); + final String stateMutability = + abiItem.getAsJsonObject().get("stateMutability") != null + ? abiItem.getAsJsonObject().get("stateMutability").getAsString() + : null; + if (type == null) { + logger.error("No type!"); + return null; + } + if (!type.equalsIgnoreCase("fallback") && null == inputs) { + logger.error("No inputs!"); + return null; + } + + SmartContractOuterClass.SmartContract.ABI.Entry.Builder entryBuilder = + SmartContractOuterClass.SmartContract.ABI.Entry.newBuilder(); + entryBuilder.setAnonymous(anonymous); + entryBuilder.setConstant(constant); + if (name != null) { + entryBuilder.setName(name); + } + + /* { inputs : optional } since fallback function not requires inputs*/ + if (inputs != null) { + for (int j = 0; j < inputs.size(); j++) { + JsonElement inputItem = inputs.get(j); + if (inputItem.getAsJsonObject().get("name") == null + || inputItem.getAsJsonObject().get("type") == null) { + logger.error("Input argument invalid due to no name or no type!"); + return null; + } + String inputName = inputItem.getAsJsonObject().get("name").getAsString(); + String inputType = inputItem.getAsJsonObject().get("type").getAsString(); + SmartContractOuterClass.SmartContract.ABI.Entry.Param.Builder paramBuilder + = SmartContractOuterClass.SmartContract.ABI.Entry.Param.newBuilder(); + JsonElement indexed = inputItem.getAsJsonObject().get("indexed"); + + paramBuilder.setIndexed((indexed != null) && indexed.getAsBoolean()); + paramBuilder.setName(inputName); + paramBuilder.setType(inputType); + entryBuilder.addInputs(paramBuilder.build()); + } + } + + /* { outputs : optional } */ + if (outputs != null) { + for (int k = 0; k < outputs.size(); k++) { + JsonElement outputItem = outputs.get(k); + if (outputItem.getAsJsonObject().get("name") == null + || outputItem.getAsJsonObject().get("type") == null) { + logger.error("Output argument invalid due to no name or no type!"); + return null; + } + String outputName = outputItem.getAsJsonObject().get("name").getAsString(); + String outputType = outputItem.getAsJsonObject().get("type").getAsString(); + SmartContractOuterClass.SmartContract.ABI.Entry.Param.Builder paramBuilder = + SmartContractOuterClass.SmartContract.ABI.Entry.Param.newBuilder(); + JsonElement indexed = outputItem.getAsJsonObject().get("indexed"); + + paramBuilder.setIndexed((indexed != null) && indexed.getAsBoolean()); + paramBuilder.setName(outputName); + paramBuilder.setType(outputType); + entryBuilder.addOutputs(paramBuilder.build()); + } + } + + entryBuilder.setType(getEntryType(type)); + entryBuilder.setPayable(payable); + if (stateMutability != null) { + entryBuilder.setStateMutability(getStateMutability(stateMutability)); + } + + abiBuilder.addEntrys(entryBuilder.build()); + } + + return abiBuilder.build(); + } + + /** constructor. */ + public static SmartContractOuterClass.SmartContract.ABI.Entry.EntryType + getEntryType(String type) { + switch (type) { + case "constructor": + return SmartContractOuterClass.SmartContract.ABI.Entry.EntryType.Constructor; + case "function": + return SmartContractOuterClass.SmartContract.ABI.Entry.EntryType.Function; + case "event": + return SmartContractOuterClass.SmartContract.ABI.Entry.EntryType.Event; + case "fallback": + return SmartContractOuterClass.SmartContract.ABI.Entry.EntryType.Fallback; + case "error": + return SmartContractOuterClass.SmartContract.ABI.Entry.EntryType.Error; + default: + return SmartContractOuterClass.SmartContract.ABI.Entry.EntryType.UNRECOGNIZED; + } + } + + + /** constructor. */ + public static SmartContractOuterClass.SmartContract.ABI.Entry.StateMutabilityType + getStateMutability(String stateMutability) { + switch (stateMutability) { + case "pure": + return SmartContractOuterClass.SmartContract.ABI.Entry.StateMutabilityType.Pure; + case "view": + return SmartContractOuterClass.SmartContract.ABI.Entry.StateMutabilityType.View; + case "nonpayable": + return SmartContractOuterClass.SmartContract.ABI.Entry.StateMutabilityType.Nonpayable; + case "payable": + return SmartContractOuterClass.SmartContract.ABI.Entry.StateMutabilityType.Payable; + default: + return SmartContractOuterClass.SmartContract.ABI.Entry.StateMutabilityType.UNRECOGNIZED; + } + } + /** * Convert to pub. * @param priKey private key diff --git a/framework/src/test/java/stest/tron/wallet/common/client/Configuration.java b/framework/src/test/java/org/tron/common/utils/client/Configuration.java similarity index 90% rename from framework/src/test/java/stest/tron/wallet/common/client/Configuration.java rename to framework/src/test/java/org/tron/common/utils/client/Configuration.java index 9d0cdd050c8..79dded303aa 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/Configuration.java +++ b/framework/src/test/java/org/tron/common/utils/client/Configuration.java @@ -1,6 +1,4 @@ -package stest.tron.wallet.common.client; - -import static org.apache.commons.lang3.StringUtils.isBlank; +package org.tron.common.utils.client; import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory; @@ -8,6 +6,7 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStreamReader; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,7 +21,7 @@ public class Configuration { */ public static Config getByPath(final String configurationPath) { - if (isBlank(configurationPath)) { + if (StringUtils.isBlank(configurationPath)) { throw new IllegalArgumentException("Configuration path is required!"); } diff --git a/framework/src/test/java/stest/tron/wallet/common/client/GrpcClient.java b/framework/src/test/java/org/tron/common/utils/client/GrpcClient.java similarity index 99% rename from framework/src/test/java/stest/tron/wallet/common/client/GrpcClient.java rename to framework/src/test/java/org/tron/common/utils/client/GrpcClient.java index c6186ca1f3a..139485e4e2b 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/GrpcClient.java +++ b/framework/src/test/java/org/tron/common/utils/client/GrpcClient.java @@ -1,10 +1,11 @@ -package stest.tron.wallet.common.client; +package org.tron.common.utils.client; import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.util.Optional; import java.util.concurrent.TimeUnit; + import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.AccountNetMessage; import org.tron.api.GrpcAPI.AccountPaginated; @@ -35,7 +36,6 @@ import org.tron.protos.contract.BalanceContract.WithdrawBalanceContract; import org.tron.protos.contract.WitnessContract; - public class GrpcClient { private ManagedChannel channelFull = null; diff --git a/framework/src/test/java/stest/tron/wallet/common/client/Parameter.java b/framework/src/test/java/org/tron/common/utils/client/Parameter.java similarity index 89% rename from framework/src/test/java/stest/tron/wallet/common/client/Parameter.java rename to framework/src/test/java/org/tron/common/utils/client/Parameter.java index 8fead433c2e..f0531c95165 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/Parameter.java +++ b/framework/src/test/java/org/tron/common/utils/client/Parameter.java @@ -1,4 +1,4 @@ -package stest.tron.wallet.common.client; +package org.tron.common.utils.client; public interface Parameter { @@ -11,4 +11,4 @@ interface CommonConstant { byte ADD_PRE_FIX_BYTE_MAINNET = (byte) 0x41; //41 + address byte ADD_PRE_FIX_BYTE_TESTNET = (byte) 0xa0; //a0 + address } -} \ No newline at end of file +} diff --git a/framework/src/test/java/stest/tron/wallet/common/client/WalletClient.java b/framework/src/test/java/org/tron/common/utils/client/WalletClient.java similarity index 99% rename from framework/src/test/java/stest/tron/wallet/common/client/WalletClient.java rename to framework/src/test/java/org/tron/common/utils/client/WalletClient.java index c4bd7ae29d3..37b67ffaa46 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/WalletClient.java +++ b/framework/src/test/java/org/tron/common/utils/client/WalletClient.java @@ -1,9 +1,10 @@ -package stest.tron.wallet.common.client; +package org.tron.common.utils.client; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import com.typesafe.config.Config; import com.typesafe.config.ConfigObject; + import java.io.IOException; import java.math.BigInteger; import java.util.ArrayList; @@ -12,6 +13,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; + import org.apache.commons.lang3.StringUtils; import org.bouncycastle.util.encoders.Hex; import org.slf4j.Logger; @@ -28,6 +30,9 @@ import org.tron.common.utils.FileUtil; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.Utils; +import org.tron.common.utils.client.Parameter.CommonConstant; +import org.tron.common.utils.client.utils.Base58; +import org.tron.common.utils.client.utils.TransactionUtils; import org.tron.core.exception.CancelException; import org.tron.core.exception.CipherException; import org.tron.protos.Protocol.Account; @@ -45,9 +50,6 @@ import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; import org.tron.protos.contract.BalanceContract.WithdrawBalanceContract; import org.tron.protos.contract.WitnessContract; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.TransactionUtils; public class WalletClient { @@ -246,7 +248,7 @@ public static Transaction createTransferAssetTransaction(byte[] to, byte[] asser public static Transaction participateAssetIssueTransaction(byte[] to, byte[] assertName, byte[] owner, long amount) { - AssetIssueContractOuterClass.ParticipateAssetIssueContract contract = + ParticipateAssetIssueContract contract = participateAssetIssueContract(to, assertName, owner, amount); return rpcCli.createParticipateAssetIssueTransaction(contract); } diff --git a/framework/src/test/java/stest/tron/wallet/common/client/WitnessComparator.java b/framework/src/test/java/org/tron/common/utils/client/WitnessComparator.java similarity index 85% rename from framework/src/test/java/stest/tron/wallet/common/client/WitnessComparator.java rename to framework/src/test/java/org/tron/common/utils/client/WitnessComparator.java index c032fce9eff..43e10441c51 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/WitnessComparator.java +++ b/framework/src/test/java/org/tron/common/utils/client/WitnessComparator.java @@ -1,4 +1,4 @@ -package stest.tron.wallet.common.client; +package org.tron.common.utils.client; import java.util.Comparator; import org.tron.protos.Protocol.Witness; @@ -8,4 +8,4 @@ class WitnessComparator implements Comparator { public int compare(Object o1, Object o2) { return Long.compare(((Witness) o2).getVoteCount(), ((Witness) o1).getVoteCount()); } -} \ No newline at end of file +} diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/AbiUtil.java b/framework/src/test/java/org/tron/common/utils/client/utils/AbiUtil.java similarity index 99% rename from framework/src/test/java/stest/tron/wallet/common/client/utils/AbiUtil.java rename to framework/src/test/java/org/tron/common/utils/client/utils/AbiUtil.java index 9eb2bf3a8c0..976490b8c80 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/AbiUtil.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/AbiUtil.java @@ -1,4 +1,4 @@ -package stest.tron.wallet.common.client.utils; +package org.tron.common.utils.client.utils; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/Base58.java b/framework/src/test/java/org/tron/common/utils/client/utils/Base58.java similarity index 99% rename from framework/src/test/java/stest/tron/wallet/common/client/utils/Base58.java rename to framework/src/test/java/org/tron/common/utils/client/utils/Base58.java index 6fd13777927..2106b191af9 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/Base58.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/Base58.java @@ -1,7 +1,8 @@ -package stest.tron.wallet.common.client.utils; +package org.tron.common.utils.client.utils; import java.io.UnsupportedEncodingException; import java.math.BigInteger; + import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.Commons; import org.tron.common.utils.Sha256Hash; @@ -240,4 +241,4 @@ public static byte[] decode58CheckForShield(String input) { } -} \ No newline at end of file +} diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/ByteArrayWrapper.java b/framework/src/test/java/org/tron/common/utils/client/utils/ByteArrayWrapper.java similarity index 97% rename from framework/src/test/java/stest/tron/wallet/common/client/utils/ByteArrayWrapper.java rename to framework/src/test/java/org/tron/common/utils/client/utils/ByteArrayWrapper.java index 7a41ed44b23..1775f28ac17 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/ByteArrayWrapper.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/ByteArrayWrapper.java @@ -1,4 +1,4 @@ -package stest.tron.wallet.common.client.utils; +package org.tron.common.utils.client.utils; /* * Copyright (c) [2016] [ ] * This file is part of the ethereumJ library. @@ -19,6 +19,7 @@ import java.io.Serializable; import java.util.Arrays; + import org.bouncycastle.util.encoders.Hex; import org.tron.common.utils.FastByteComparisons; diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/DataWord.java b/framework/src/test/java/org/tron/common/utils/client/utils/DataWord.java similarity index 99% rename from framework/src/test/java/stest/tron/wallet/common/client/utils/DataWord.java rename to framework/src/test/java/org/tron/common/utils/client/utils/DataWord.java index e44ac34e765..6c36f4d636a 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/DataWord.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/DataWord.java @@ -1,4 +1,4 @@ -package stest.tron.wallet.common.client.utils; +package org.tron.common.utils.client.utils; /* * Copyright (c) [2016] [ ] @@ -22,6 +22,7 @@ import com.fasterxml.jackson.annotation.JsonValue; import java.math.BigInteger; import java.nio.ByteBuffer; + import org.bouncycastle.util.Arrays; import org.bouncycastle.util.encoders.Hex; import org.tron.common.utils.ByteUtil; diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java b/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java similarity index 97% rename from framework/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java rename to framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java index 6dcb2035913..0d117dd4a45 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java @@ -1,4 +1,4 @@ -package stest.tron.wallet.common.client.utils; +package org.tron.common.utils.client.utils; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -6,15 +6,11 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import com.google.protobuf.ByteString; -import io.netty.util.internal.StringUtil; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; -import java.util.Optional; import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; @@ -30,8 +26,8 @@ import org.tron.api.GrpcAPI; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; -import org.tron.core.zen.address.DiversifierT; -import stest.tron.wallet.common.client.Configuration; +import org.tron.common.utils.PublicMethod; +import org.tron.common.utils.client.Configuration; @Slf4j public class HttpMethed { @@ -105,7 +101,7 @@ public static HttpResponse setAccountId( JsonObject userBaseObj2 = new JsonObject(); userBaseObj2.addProperty("account_id", accountId); userBaseObj2.addProperty( - "owner_address", Base58.encode58Check(PublicMethed.getFinalAddress(fromKey))); + "owner_address", Base58.encode58Check(PublicMethod.getFinalAddress(fromKey))); userBaseObj2.addProperty("visible", visable); response = createConnect(requestUrl, userBaseObj2); transactionString = EntityUtils.toString(response.getEntity()); @@ -3123,97 +3119,7 @@ public static HttpResponse clearABiGetTxid( return response; } - /** constructor. */ - public static Optional generateShieldAddress(String httpnode) { - ShieldAddressInfo addressInfo = new ShieldAddressInfo(); - String sk; - String d; - String ask; - String nsk; - String ovk; - String ak; - String nk; - String ivk; - String pkD; - try { - response = HttpMethed.getSpendingKey(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - sk = responseContent.getString("value"); - - response = HttpMethed.getDiversifier(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - d = responseContent.getString("d"); - - response = HttpMethed.getExpandedSpendingKey(httpnode, sk); - responseContent = HttpMethed.parseResponseContent(response); - ask = responseContent.getString("ask"); - nsk = responseContent.getString("nsk"); - ovk = responseContent.getString("ovk"); - - response = HttpMethed.getAkFromAsk(httpnode, ask); - responseContent = HttpMethed.parseResponseContent(response); - ak = responseContent.getString("value"); - - response = HttpMethed.getNkFromNsk(httpnode, nsk); - responseContent = HttpMethed.parseResponseContent(response); - nk = responseContent.getString("value"); - - response = HttpMethed.getIncomingViewingKey(httpnode, ak, nk); - responseContent = HttpMethed.parseResponseContent(response); - ivk = responseContent.getString("ivk"); - - response = HttpMethed.getZenPaymentAddress(httpnode, ivk, d); - responseContent = HttpMethed.parseResponseContent(response); - pkD = responseContent.getString("pkD"); - addressInfo.setSk(ByteArray.fromHexString(sk)); - addressInfo.setD(new DiversifierT(ByteArray.fromHexString(d))); - addressInfo.setIvk(ByteArray.fromHexString(ivk)); - addressInfo.setOvk(ByteArray.fromHexString(ovk)); - addressInfo.setPkD(ByteArray.fromHexString(pkD)); - logger.info("sk:" + sk); - - if (addressInfo.validateCheck()) { - return Optional.of(addressInfo); - } - } catch (Exception e) { - e.printStackTrace(); - } - - return Optional.empty(); - } - - /** constructor. */ - public static List addShieldOutputList( - String httpNode, - List shieldOutList, - String shieldToAddress, - String toAmountString, - String menoString) { - String shieldAddress = shieldToAddress; - String amountString = toAmountString; - if (menoString.equals("null")) { - menoString = ""; - } - long shieldAmount = 0; - if (!StringUtil.isNullOrEmpty(amountString)) { - shieldAmount = Long.valueOf(amountString); - } - - GrpcAPI.Note.Builder noteBuild = GrpcAPI.Note.newBuilder(); - noteBuild.setPaymentAddress(shieldAddress); - noteBuild.setPaymentAddress(shieldAddress); - noteBuild.setValue(shieldAmount); - - response = HttpMethed.getRcm(httpNode); - responseContent = HttpMethed.parseResponseContent(response); - String rcm = responseContent.getString("value"); - - noteBuild.setRcm(ByteString.copyFrom(rcm.getBytes())); - noteBuild.setMemo(ByteString.copyFrom(menoString.getBytes())); - shieldOutList.add(noteBuild.build()); - return shieldOutList; - } /** constructor. */ public static HttpResponse getSpendingKey(String httpNode) { @@ -3315,19 +3221,6 @@ public static HttpResponse getIncomingViewingKey(String httpNode, String ak, Str return response; } - /** constructor. */ - public static HttpResponse getNewShieldedAddress(String httpNode) { - try { - String requestUrl = "http://" + httpNode + "/wallet/getnewshieldedaddress"; - response = createConnect(requestUrl); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - /** constructor. */ public static HttpResponse getZenPaymentAddress(String httpNode, String ivk, String d) { try { diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/JSONObjectWarp.java b/framework/src/test/java/org/tron/common/utils/client/utils/JSONObjectWarp.java old mode 100755 new mode 100644 similarity index 77% rename from framework/src/test/java/stest/tron/wallet/common/client/utils/JSONObjectWarp.java rename to framework/src/test/java/org/tron/common/utils/client/utils/JSONObjectWarp.java index b482068f118..bab667dedf1 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/JSONObjectWarp.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/JSONObjectWarp.java @@ -1,11 +1,11 @@ -package stest.tron.wallet.common.client.utils; - -import com.alibaba.fastjson.JSONObject; - -public class JSONObjectWarp extends JSONObject { - - public JSONObjectWarp put(String key, Object value) { - super.put(key, value); - return this; - } -} +package org.tron.common.utils.client.utils; + +import com.alibaba.fastjson.JSONObject; + +public class JSONObjectWarp extends JSONObject { + + public JSONObjectWarp put(String key, Object value) { + super.put(key, value); + return this; + } +} diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/Sha256Sm3Hash.java b/framework/src/test/java/org/tron/common/utils/client/utils/Sha256Sm3Hash.java similarity index 97% rename from framework/src/test/java/stest/tron/wallet/common/client/utils/Sha256Sm3Hash.java rename to framework/src/test/java/org/tron/common/utils/client/utils/Sha256Sm3Hash.java index 478bd280440..fde88385794 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/Sha256Sm3Hash.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/Sha256Sm3Hash.java @@ -1,4 +1,4 @@ -package stest.tron.wallet.common.client.utils; +package org.tron.common.utils.client.utils; /* * Copyright 2011 Google Inc. @@ -16,9 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import static com.google.common.base.Preconditions.checkArgument; - +import com.google.common.base.Preconditions; import com.google.common.io.ByteStreams; import com.google.common.primitives.Ints; import com.google.common.primitives.Longs; @@ -31,6 +29,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; + import org.bouncycastle.crypto.digests.SM3Digest; import org.tron.common.utils.ByteArray; @@ -59,13 +58,13 @@ public class Sha256Sm3Hash implements Serializable, Comparable { public Sha256Sm3Hash(long num, byte[] hash) { byte[] rawHashBytes = this.generateBlockId(num, hash); - checkArgument(rawHashBytes.length == LENGTH); + Preconditions.checkArgument(rawHashBytes.length == LENGTH); this.bytes = rawHashBytes; } public Sha256Sm3Hash(long num, Sha256Sm3Hash hash) { byte[] rawHashBytes = this.generateBlockId(num, hash); - checkArgument(rawHashBytes.length == LENGTH); + Preconditions.checkArgument(rawHashBytes.length == LENGTH); this.bytes = rawHashBytes; } @@ -74,7 +73,7 @@ public Sha256Sm3Hash(long num, Sha256Sm3Hash hash) { */ @Deprecated public Sha256Sm3Hash(byte[] rawHashBytes) { - checkArgument(rawHashBytes.length == LENGTH); + Preconditions.checkArgument(rawHashBytes.length == LENGTH); this.bytes = rawHashBytes; } diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldAddressInfo.java b/framework/src/test/java/org/tron/common/utils/client/utils/ShieldAddressInfo.java similarity index 98% rename from framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldAddressInfo.java rename to framework/src/test/java/org/tron/common/utils/client/utils/ShieldAddressInfo.java index 35332287e93..5d0de50c0b8 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldAddressInfo.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/ShieldAddressInfo.java @@ -1,4 +1,4 @@ -package stest.tron.wallet.common.client.utils; +package org.tron.common.utils.client.utils; import java.util.Arrays; import java.util.Optional; diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldNoteInfo.java b/framework/src/test/java/org/tron/common/utils/client/utils/ShieldNoteInfo.java similarity index 97% rename from framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldNoteInfo.java rename to framework/src/test/java/org/tron/common/utils/client/utils/ShieldNoteInfo.java index 8691ac26abc..50fad817c56 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldNoteInfo.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/ShieldNoteInfo.java @@ -1,4 +1,4 @@ -package stest.tron.wallet.common.client.utils; +package org.tron.common.utils.client.utils; import lombok.AllArgsConstructor; import lombok.Getter; @@ -78,4 +78,3 @@ public boolean decode(final String data) { } } - diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java b/framework/src/test/java/org/tron/common/utils/client/utils/TransactionUtils.java similarity index 99% rename from framework/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java rename to framework/src/test/java/org/tron/common/utils/client/utils/TransactionUtils.java index 179af83e083..b6226d01aae 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/TransactionUtils.java @@ -1,4 +1,4 @@ -package stest.tron.wallet.common.client.utils; +package org.tron.common.utils.client.utils; /* * java-tron is free software: you can redistribute it and/or modify diff --git a/framework/src/test/java/org/tron/core/CreateCommonTransactionTest.java b/framework/src/test/java/org/tron/core/CreateCommonTransactionTest.java index 5b0c8dc02b4..4bcef1e148c 100644 --- a/framework/src/test/java/org/tron/core/CreateCommonTransactionTest.java +++ b/framework/src/test/java/org/tron/core/CreateCommonTransactionTest.java @@ -1,6 +1,6 @@ package org.tron.core; -import static stest.tron.wallet.common.client.WalletClient.decodeFromBase58Check; +import static org.tron.common.utils.client.WalletClient.decodeFromBase58Check; import com.google.protobuf.Any; import com.google.protobuf.ByteString; diff --git a/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java b/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java index 5468e90c924..6945c044194 100644 --- a/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java +++ b/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java @@ -25,6 +25,7 @@ import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; +import org.tron.common.utils.client.WalletClient; import org.tron.common.zksnark.IncrementalMerkleTreeContainer; import org.tron.common.zksnark.IncrementalMerkleVoucherContainer; import org.tron.common.zksnark.JLibrustzcash; @@ -49,7 +50,6 @@ import org.tron.core.zen.note.Note; import org.tron.protos.contract.ShieldContract; import org.tron.protos.contract.ShieldContract.SpendDescription; -import stest.tron.wallet.common.client.WalletClient; @Slf4j public class ShieldedTRC20BuilderTest extends BaseTest { @@ -102,7 +102,7 @@ public void createShieldedContractParametersForMint() Assert.assertEquals(1, result[31]); //update frontier and leafCount - + int slot = result[63]; if (slot == 0) { System.arraycopy(inputData, 0, frontier, 0, 32); diff --git a/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java index fb26aca1979..1f6571e8868 100644 --- a/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java @@ -1,7 +1,7 @@ package org.tron.core.actuator; import static junit.framework.TestCase.fail; -import static stest.tron.wallet.common.client.utils.PublicMethed.jsonStr2Abi; +import static org.tron.common.utils.PublicMethod.jsonStr2Abi; import com.google.protobuf.Any; import com.google.protobuf.ByteString; diff --git a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java index 8f0f7c5616f..a795cf14447 100755 --- a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java @@ -9,6 +9,7 @@ import org.junit.Test; import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.client.utils.TransactionUtils; import org.tron.common.zksnark.IncrementalMerkleTreeContainer; import org.tron.common.zksnark.IncrementalMerkleVoucherContainer; import org.tron.core.Constant; @@ -40,7 +41,6 @@ import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; import org.tron.protos.contract.ShieldContract.PedersenHash; import org.tron.protos.contract.ShieldContract.ShieldedTransferContract; -import stest.tron.wallet.common.client.utils.TransactionUtils; @Slf4j public class ShieldedTransferActuatorTest extends BaseTest { @@ -63,10 +63,9 @@ public class ShieldedTransferActuatorTest extends BaseTest { private static final int VOTE_SCORE = 2; private static final String DESCRIPTION = "TRX"; private static final String URL = "https://tron.network/"; + @Resource private Wallet wallet; - @Resource - private TransactionUtil transactionUtil; static { dbPath = "output_shield_transfer_test"; diff --git a/framework/src/test/java/org/tron/core/services/DelegationServiceTest.java b/framework/src/test/java/org/tron/core/services/DelegationServiceTest.java index f0ad0d7c77f..e2ea87a1d0f 100644 --- a/framework/src/test/java/org/tron/core/services/DelegationServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/DelegationServiceTest.java @@ -1,7 +1,7 @@ package org.tron.core.services; import static org.tron.common.utils.Commons.decodeFromBase58Check; -import static stest.tron.wallet.common.client.Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET; +import static org.tron.common.utils.client.Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET; import com.google.protobuf.ByteString; import io.grpc.ManagedChannelBuilder; diff --git a/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java b/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java index 8f2b9645672..d442a5826f7 100644 --- a/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java @@ -11,9 +11,10 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.entity.NodeInfo; import org.tron.common.utils.Sha256Hash; +import org.tron.common.utils.client.Configuration; import org.tron.core.capsule.BlockCapsule; import org.tron.program.Version; -import stest.tron.wallet.common.client.Configuration; + @Slf4j public class NodeInfoServiceTest { diff --git a/framework/src/test/java/org/tron/core/services/WalletApiTest.java b/framework/src/test/java/org/tron/core/services/WalletApiTest.java index c7964e6d854..3e8316666e6 100644 --- a/framework/src/test/java/org/tron/core/services/WalletApiTest.java +++ b/framework/src/test/java/org/tron/core/services/WalletApiTest.java @@ -13,10 +13,11 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.utils.FileUtil; +import org.tron.common.utils.client.Configuration; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import stest.tron.wallet.common.client.Configuration; + @Slf4j public class WalletApiTest { diff --git a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java index 4ba762d3340..8adae9b8c3d 100644 --- a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java @@ -13,6 +13,8 @@ import org.tron.common.BaseTest; import org.tron.common.application.Application; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.client.Configuration; +import org.tron.common.utils.client.utils.HttpMethed; import org.tron.core.Constant; import org.tron.core.capsule.ContractCapsule; import org.tron.core.config.args.Args; @@ -21,8 +23,6 @@ import org.tron.core.vm.repository.RepositoryImpl; import org.tron.protos.Protocol; import org.tron.protos.contract.SmartContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; @Slf4j public class TriggerSmartContractServletTest extends BaseTest { diff --git a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java index 0504f08274f..514a5dfab76 100755 --- a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java @@ -25,6 +25,7 @@ import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; +import org.tron.common.utils.client.utils.TransactionUtils; import org.tron.common.zksnark.IncrementalMerkleTreeContainer; import org.tron.common.zksnark.IncrementalMerkleVoucherContainer; import org.tron.common.zksnark.JLibrustzcash; @@ -94,7 +95,6 @@ import org.tron.protos.contract.ShieldContract.ReceiveDescription; import org.tron.protos.contract.ShieldContract.ShieldedTransferContract; import org.tron.protos.contract.ShieldContract.SpendDescription; -import stest.tron.wallet.common.client.utils.TransactionUtils; @Slf4j public class ShieldedReceiveTest extends BaseTest { diff --git a/framework/src/test/java/stest/tron/wallet/account/BrokerageTest001.java b/framework/src/test/java/stest/tron/wallet/account/BrokerageTest001.java deleted file mode 100644 index fdaf67406b3..00000000000 --- a/framework/src/test/java/stest/tron/wallet/account/BrokerageTest001.java +++ /dev/null @@ -1,167 +0,0 @@ -package stest.tron.wallet.account; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.BytesMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.protos.Protocol; -import org.tron.protos.contract.StorageContract.UpdateBrokerageContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class BrokerageTest001 { - - private String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private ManagedChannel channelSoliInFull = null; - private ManagedChannel channelPbft = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSoliInFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPbft = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String soliInFullnode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - private String soliInPbft = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(2); - - private String dev001Key = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private byte[] dev001Address = PublicMethed.getFinalAddress(dev001Key); - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelSoliInFull = ManagedChannelBuilder.forTarget(soliInFullnode) - .usePlaintext() - .build(); - blockingStubSoliInFull = WalletSolidityGrpc.newBlockingStub(channelSoliInFull); - - channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext() - .build(); - blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); - - PublicMethed.printAddress(dev001Key); - } - - @Test - public void updateBrokerageTest001() { - // witness updateBrokerage - Assert.assertTrue(updateBrokerage(witnessAddress001, 55, blockingStubFull)); - - Assert.assertTrue(updateBrokerage(witnessAddress001, 0, blockingStubFull)); - - Assert.assertTrue(updateBrokerage(witnessAddress001, 100, blockingStubFull)); - - Assert.assertFalse(updateBrokerage(witnessAddress001, -55, blockingStubFull)); - - // normal account updateBrokerage fail - Assert.assertFalse(updateBrokerage(dev001Address, 55, blockingStubFull)); - } - - @Test - public void getBrokerageTest001() { - BytesMessage bytesMessage = BytesMessage.newBuilder().setValue(ByteString - .copyFrom(witnessAddress001)) - .build(); - - Assert.assertEquals(20, blockingStubFull.getBrokerageInfo(bytesMessage).getNum()); - - // getBrokerageInfo from solidity node - Assert.assertEquals(20, blockingStubSolidity.getBrokerageInfo(bytesMessage).getNum()); - Assert.assertEquals(20, blockingStubSoliInFull.getBrokerageInfo(bytesMessage).getNum()); - Assert.assertEquals(20, blockingStubPbft.getBrokerageInfo(bytesMessage).getNum()); - } - - @Test - public void getRewardTest002() { - BytesMessage bytesMessage = BytesMessage.newBuilder().setValue(ByteString - .copyFrom(witnessAddress001)) - .build(); - Assert.assertTrue(blockingStubFull.getRewardInfo(bytesMessage) != null); - - // getRewardInfo from solidity node - Assert.assertTrue(blockingStubSolidity.getRewardInfo(bytesMessage) != null); - Assert.assertTrue(blockingStubPbft.getRewardInfo(bytesMessage) != null); - Assert.assertTrue(blockingStubSoliInFull.getRewardInfo(bytesMessage) != null); - } - - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelPbft != null) { - channelPbft.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSoliInFull != null) { - channelSoliInFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - - boolean updateBrokerage(byte[] owner, int brokerage, - WalletGrpc.WalletBlockingStub blockingStubFull) { - - UpdateBrokerageContract.Builder updateBrokerageContract = UpdateBrokerageContract.newBuilder(); - updateBrokerageContract.setOwnerAddress(ByteString.copyFrom(owner)).setBrokerage(brokerage); - TransactionExtention transactionExtention = blockingStubFull - .updateBrokerage(updateBrokerageContract.build()); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return false; - } - logger.info("transaction:" + transaction); - if (transactionExtention.getResult().getResult()) { - return true; - } - return true; - } - - public void getBrokerage() { - - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount001.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount001.java deleted file mode 100644 index 365f200e1bd..00000000000 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount001.java +++ /dev/null @@ -1,232 +0,0 @@ -package stest.tron.wallet.account; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class WalletTestAccount001 { - - private static final long now = System.currentTimeMillis(); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String invalidTestKey = - "592BB6C9BB255409A6A45EFD18E9A74FECDDCCE93A40D96B70FBE334E6361E36"; - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - /** - * constructor. - */ - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - - @Test - public void testqueryaccountfromfullnode() { - //Query success, get the right balance,bandwidth and the account name. - Account queryResult = queryAccount(testKey002, blockingStubFull); - /* Account queryResult = PublicMethed.queryAccountByAddress(fromAddress,blockingStubFull); - logger.info(ByteArray.toStr(queryResult.getAccountName().toByteArray())); - logger.info(Long.toString(queryResult.getBalance())); - logger.info(ByteArray.toStr(queryResult.getAddress().toByteArray()));*/ - Assert.assertTrue(queryResult.getBalance() > 0); - //Assert.assertTrue(queryResult.getBandwidth() >= 0); - Assert.assertTrue(queryResult.getAccountName().toByteArray().length > 0); - Assert.assertFalse(queryResult.getAddress().isEmpty()); - - //Query failed - Account invalidQueryResult = queryAccount(invalidTestKey, blockingStubFull); - Assert.assertTrue(invalidQueryResult.getAccountName().isEmpty()); - Assert.assertTrue(invalidQueryResult.getAddress().isEmpty()); - - //Improve coverage. - queryResult.hashCode(); - queryResult.getSerializedSize(); - queryResult.equals(queryResult); - queryResult.equals(invalidQueryResult); - } - - @Test - public void testqueryaccountfromsoliditynode() { - //Query success, get the right balance,bandwidth and the account name. - Account queryResult = solidityqueryAccount(testKey002, blockingStubSolidity); - Assert.assertTrue(queryResult.getBalance() > 0); - //Assert.assertTrue(queryResult.getBandwidth() >= 0); - Assert.assertTrue(queryResult.getAccountName().toByteArray().length > 0); - Assert.assertFalse(queryResult.getAddress().isEmpty()); - - //Query failed - Account invalidQueryResult = solidityqueryAccount(invalidTestKey, blockingStubSolidity); - Assert.assertTrue(invalidQueryResult.getAccountName().isEmpty()); - Assert.assertTrue(invalidQueryResult.getAddress().isEmpty()); - - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - logger.info(Integer.toString(ecKey.getAddress().length)); - - //PublicMethed.AddPreFix(); - logger.info(Integer.toString(ecKey.getAddress().length)); - System.out.println("address ====== " + ByteArray.toHexString(ecKey.getAddress())); - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - //return grpcQueryAccount(address,blockingStubFull); - } - - /** - * constructor. - */ - - public Account solidityqueryAccount(String priKey, - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) { - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - //byte[] address = PublicMethed.AddPreFix(ecKey.getAddress()); - return grpcQueryAccountSolidity(ecKey.getAddress(), blockingStubSolidity); - //return grpcQueryAccountSolidity(address,blockingStubSolidity); - } - - /** - * constructor. - */ - - public String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, - WalletGrpc.WalletBlockingStub blockingStubFull) { - //address = PublicMethed.AddPreFix(address); - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Account grpcQueryAccountSolidity(byte[] address, - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) { - //address = PublicMethed.AddPreFix(address); - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubSolidity.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount003.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount003.java deleted file mode 100644 index b602265d26a..00000000000 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount003.java +++ /dev/null @@ -1,485 +0,0 @@ -package stest.tron.wallet.account; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.contract.AssetIssueContractOuterClass; -import org.tron.protos.contract.BalanceContract; -import org.tron.protos.contract.WitnessContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -//import stest.tron.wallet.common.client.AccountComparator; - -@Slf4j -public class WalletTestAccount003 { - - private static final long now = System.currentTimeMillis(); - private static final String name = "testAssetIssue_" + Long.toString(now); - private static final long TotalSupply = now; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - String mostLongNamePlusOneChar = "1abcdeabcdefabcdefg1abcdefg10o0og1abcdefg10o0oabcd" - + "efabcdefg1abcdefg10o0og1abcdefg10o0oabcdefabcdefg1abcdefg10o0og1abcdefg10o0oab" - + "cdefabcdefg1abcdefg10o0og1abcdefg10o0ofabcdefg1abcdefg10o0og1abcdefg10o0o"; - - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - //get account - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] lowBalAddress = ecKey.getAddress(); - String lowBalTest = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] noBandwitchAddress = ecKey1.getAddress(); - String noBandwitch = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - /** - * constructor. - */ - - public static String getRandomStr(int length) { - String base = "abcdefghijklmnopqrstuvwxyz0123456789"; - int randomNum; - char randomChar; - Random random = new Random(); - StringBuffer str = new StringBuffer(); - - for (int i = 0; i < length; i++) { - randomNum = random.nextInt(base.length()); - randomChar = base.charAt(randomNum); - str.append(randomChar); - } - return str.toString(); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - PublicMethed.printAddress(lowBalTest); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test - public void test1CreateAccount() { - Account noCreateAccount = PublicMethed.queryAccount(lowBalTest, blockingStubFull); - while (noCreateAccount.getBalance() != 0) { - ecKey = new ECKey(Utils.getRandom()); - lowBalAddress = ecKey.getAddress(); - lowBalTest = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - noCreateAccount = PublicMethed.queryAccount(lowBalTest, blockingStubFull); - } - Assert.assertTrue(sendCoin(lowBalAddress, 1L, fromAddress, testKey002)); - noCreateAccount = PublicMethed.queryAccount(lowBalTest, blockingStubFull); - logger.info(Long.toString(noCreateAccount.getBalance())); - Assert.assertTrue(noCreateAccount.getBalance() == 1); - } - - @Test(enabled = true) - public void test2UpdateAccount() { - Assert.assertFalse(PublicMethed.updateAccount(lowBalAddress, - mostLongNamePlusOneChar.getBytes(), lowBalTest, blockingStubFull)); - Assert.assertFalse(PublicMethed.updateAccount(lowBalAddress, "".getBytes(), lowBalTest, - blockingStubFull)); - String mostLongName = getRandomStr(33); - Assert.assertTrue(PublicMethed.updateAccount(lowBalAddress, mostLongName.getBytes(), lowBalTest, - blockingStubFull)); - String firstUpdateName = getRandomStr(32); - Assert.assertFalse(PublicMethed.updateAccount(lowBalAddress, firstUpdateName.getBytes(), - lowBalTest, blockingStubFull)); - String secondUpdateName = getRandomStr(15); - Assert.assertFalse(PublicMethed.updateAccount(lowBalAddress, secondUpdateName.getBytes(), - lowBalTest, blockingStubFull)); - } - - @Test(enabled = true) - public void test3NoBalanceCreateAssetIssue() { - Account lowaccount = PublicMethed.queryAccount(lowBalTest, blockingStubFull); - if (lowaccount.getBalance() > 0) { - Assert.assertTrue(sendCoin(toAddress, lowaccount.getBalance(), lowBalAddress, lowBalTest)); - } - //Create AssetIssue failed when there is no enough balance. - Assert.assertFalse(PublicMethed.createAssetIssue(lowBalAddress, name, TotalSupply, 1, - 1, now + 100000000L, now + 10000000000L, 2, - description, url, 10000L, 10000L, 1L, - 1L, lowBalTest, blockingStubFull)); - logger.info("nobalancecreateassetissue"); - } - - @Test(enabled = true) - public void test4NoBalanceTransferTrx() { - //Send Coin failed when there is no enough balance. - Assert.assertFalse(sendCoin(toAddress, 100000000000000000L, lowBalAddress, lowBalTest)); - } - - @Test(enabled = true) - public void test5NoBalanceCreateWitness() { - //Apply to be super witness failed when no enough balance. - Assert.assertFalse(createWitness(lowBalAddress, fromAddress, lowBalTest)); - } - - @Test(enabled = true) - public void test6NoFreezeBalanceToUnfreezeBalance() { - //Unfreeze account failed when no freeze balance - Account noFreezeAccount = PublicMethed.queryAccount(lowBalTest, blockingStubFull); - if (noFreezeAccount.getFrozenCount() == 0) { - Assert.assertFalse(unFreezeBalance(lowBalAddress, lowBalTest)); - } else { - logger.info("This account has freeze balance, please test this case for manual"); - } - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean createWitness(byte[] owner, byte[] url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - WitnessContract.WitnessCreateContract.Builder builder = WitnessContract.WitnessCreateContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setUrl(ByteString.copyFrom(url)); - WitnessContract.WitnessCreateContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createWitness(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - return response.getResult(); - } - - /** - * constructor. - */ - - public Boolean sendCoin(byte[] to, long amount, byte[] owner, String priKey) { - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - BalanceContract.TransferContract.Builder builder = BalanceContract.TransferContract - .newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - BalanceContract.TransferContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createTransaction(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public Boolean createAssetIssue(byte[] address, String name, Long totalSupply, Integer trxNum, - Integer icoNum, Long startTime, Long endTime, - Integer voteScore, String description, String url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - try { - AssetIssueContractOuterClass.AssetIssueContract.Builder builder - = AssetIssueContractOuterClass.AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(TotalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - - Protocol.Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("Please check!!! transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info("Please check!!! response.getresult==false"); - return false; - } else { - logger.info(name); - return true; - } - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Protocol.Transaction signTransaction(ECKey ecKey, Protocol.Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - - public boolean unFreezeBalance(byte[] address, String priKey) { - //byte[] address = address; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - BalanceContract.UnfreezeBalanceContract.Builder builder - = BalanceContract.UnfreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess); - - BalanceContract.UnfreezeBalanceContract contract = builder.build(); - - Protocol.Transaction transaction = blockingStubFull.unfreezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public Boolean voteWitness(HashMap witness, byte[] address, String priKey) { - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - WitnessContract.VoteWitnessContract.Builder builder = WitnessContract.VoteWitnessContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - for (String addressBase58 : witness.keySet()) { - String value = witness.get(addressBase58); - long count = Long.parseLong(value); - WitnessContract.VoteWitnessContract.Vote.Builder voteBuilder - = WitnessContract.VoteWitnessContract.Vote.newBuilder(); - byte[] addRess = WalletClient.decodeFromBase58Check(addressBase58); - if (addRess == null) { - return false; - } - voteBuilder.setVoteAddress(ByteString.copyFrom(addRess)); - voteBuilder.setVoteCount(count); - builder.addVotes(voteBuilder.build()); - } - - WitnessContract.VoteWitnessContract contract = builder.build(); - - Protocol.Transaction transaction = blockingStubFull.voteWitnessAccount(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - logger.info("response.getresult() == false"); - return false; - } - return true; - } - - /** - * constructor. - */ - - public Boolean freezeBalance(byte[] addRess, long freezeBalance, long freezeDuration, - String priKey) { - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - BalanceContract.FreezeBalanceContract.Builder builder = BalanceContract.FreezeBalanceContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration); - - BalanceContract.FreezeBalanceContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - return false; - } - return true; - - - } - - class AccountComparator implements Comparator { - - public int compare(Object o1, Object o2) { - return Long.compare(((Account) o2).getBalance(), ((Account) o1).getBalance()); - } - } - -} - - - diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount004.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount004.java deleted file mode 100644 index cc2ebd9a961..00000000000 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount004.java +++ /dev/null @@ -1,338 +0,0 @@ -package stest.tron.wallet.account; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.BalanceContract.FreezeBalanceContract; -import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class WalletTestAccount004 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - private final String noFrozenBalanceTestKey = - "8CB4480194192F30907E14B52498F594BD046E21D7C4D8FE866563A6760AC891"; - - - private final byte[] noFrozenAddress = PublicMethed.getFinalAddress(noFrozenBalanceTestKey); - Long freezeAmount = 2000000L; - private ManagedChannel channelFull = null; - private ManagedChannel searchChannelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletGrpc.WalletBlockingStub searchBlockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String searchFullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext() - .build(); - searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); - - - } - - @Test(enabled = true) - public void testFreezeBalance() { - - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] account004AddressForFreeze = ecKey2.getAddress(); - String account004KeyForFreeze = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - Assert.assertTrue(PublicMethed.sendcoin(account004AddressForFreeze, 10000000, - fromAddress, testKey002, blockingStubFull)); - //Freeze failed when freeze amount is large than currently balance. - Assert.assertFalse(freezeBalance(account004AddressForFreeze, 9000000000000000000L, - 3L, account004KeyForFreeze)); - //Freeze failed when freeze amount less than 1Trx - Assert.assertFalse(freezeBalance(account004AddressForFreeze, 999999L, 3L, - account004KeyForFreeze)); - //Freeze failed when freeze duration isn't 3 days. - //Assert.assertFalse(freezeBalance(fromAddress, 1000000L, 2L, testKey002)); - //Unfreeze balance failed when 3 days hasn't come. - Assert.assertFalse(PublicMethed.unFreezeBalance(account004AddressForFreeze, - account004KeyForFreeze, 0, null, blockingStubFull)); - //Freeze failed when freeze amount is 0. - Assert.assertFalse(freezeBalance(account004AddressForFreeze, 0L, 3L, - account004KeyForFreeze)); - //Freeze failed when freeze amount is -1. - Assert.assertFalse(freezeBalance(account004AddressForFreeze, -1L, 3L, - account004KeyForFreeze)); - //Freeze failed when freeze duration is -1. - //Assert.assertFalse(freezeBalance(fromAddress, 1000000L, -1L, testKey002)); - //Freeze failed when freeze duration is 0. - //Assert.assertFalse(freezeBalance(fromAddress, 1000000L, 0L, testKey002)); - - } - - @Test(enabled = true) - public void testUnFreezeBalance() { - //Unfreeze failed when there is no freeze balance. - //Wait to be create account - - Assert.assertFalse(PublicMethed.unFreezeBalance(noFrozenAddress, noFrozenBalanceTestKey, 1, - null, blockingStubFull)); - logger.info("Test unfreezebalance"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] account004Address = ecKey1.getAddress(); - String account004Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert - .assertTrue(PublicMethed.sendcoin(account004Address, freezeAmount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalance(account004Address, freezeAmount, 0, - account004Key, blockingStubFull)); - Account account004; - account004 = PublicMethed.queryAccount(account004Address, blockingStubFull); - Assert.assertTrue(account004.getBalance() == 0); - Assert.assertTrue(PublicMethed.unFreezeBalance(account004Address, account004Key, 0, - null, blockingStubFull)); - account004 = PublicMethed.queryAccount(account004Address, blockingStubFull); - Assert.assertTrue(account004.getBalance() == freezeAmount); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(account004Address, freezeAmount, 0, - 1, account004Key, blockingStubFull)); - account004 = PublicMethed.queryAccount(account004Address, blockingStubFull); - Assert.assertTrue(account004.getBalance() == 0); - - Assert.assertFalse(PublicMethed.unFreezeBalance(account004Address, account004Key, 0, - null, blockingStubFull)); - Assert.assertTrue(PublicMethed.unFreezeBalance(account004Address, account004Key, 1, - null, blockingStubFull)); - account004 = PublicMethed.queryAccount(account004Address, blockingStubFull); - Assert.assertTrue(account004.getBalance() == freezeAmount); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (searchChannelFull != null) { - searchChannelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean freezeBalance(byte[] addRess, long freezeBalance, long freezeDuration, - String priKey) { - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Block currentBlock = blockingStubFull.getNowBlock(EmptyMessage.newBuilder().build()); - final Long beforeBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Account beforeFronzen = queryAccount(ecKey, blockingStubFull); - Long beforeFrozenBalance = 0L; - //Long beforeBandwidth = beforeFronzen.getBandwidth(); - if (beforeFronzen.getFrozenCount() != 0) { - beforeFrozenBalance = beforeFronzen.getFrozen(0).getFrozenBalance(); - //beforeBandwidth = beforeFronzen.getBandwidth(); - //logger.info(Long.toString(beforeFronzen.getBandwidth())); - logger.info(Long.toString(beforeFronzen.getFrozen(0).getFrozenBalance())); - } - - FreezeBalanceContract.Builder builder = FreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration); - - FreezeBalanceContract contract = builder.build(); - Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - return false; - } - - Long afterBlockNum = 0L; - Integer wait = 0; - PublicMethed.waitProduceNextBlock(searchBlockingStubFull); - /* while (afterBlockNum < beforeBlockNum + 1 && wait < 10) { - Block currentBlock1 = searchBlockingStubFull.getNowBlock(EmptyMessage.newBuilder().build()); - afterBlockNum = currentBlock1.getBlockHeader().getRawData().getNumber(); - wait++; - try { - Thread.sleep(2000); - logger.info("wait 2 second"); - } catch (InterruptedException e) { - e.printStackTrace(); - } - }*/ - - Account afterFronzen = queryAccount(ecKey, searchBlockingStubFull); - Long afterFrozenBalance = afterFronzen.getFrozen(0).getFrozenBalance(); - //Long afterBandwidth = afterFronzen.getBandwidth(); - //logger.info(Long.toString(afterFronzen.getBandwidth())); - logger.info(Long.toString(afterFronzen.getFrozen(0).getFrozenBalance())); - //logger.info(Integer.toString(search.getFrozenCount())); - logger.info( - "beforefronen" + beforeFrozenBalance.toString() + " afterfronzen" + afterFrozenBalance - .toString()); - Assert.assertTrue(afterFrozenBalance - beforeFrozenBalance == freezeBalance); - //Assert.assertTrue(afterBandwidth - beforeBandwidth == freezeBalance * frozen_duration); - return true; - - - } - - /** - * constructor. - */ - - public boolean unFreezeBalance(byte[] addRess, String priKey) { - byte[] address = addRess; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account search = queryAccount(ecKey, blockingStubFull); - - UnfreezeBalanceContract.Builder builder = UnfreezeBalanceContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess); - - UnfreezeBalanceContract contract = builder.build(); - - Transaction transaction = blockingStubFull.unfreezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount005.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount005.java deleted file mode 100644 index ddafcb3714f..00000000000 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount005.java +++ /dev/null @@ -1,267 +0,0 @@ -package stest.tron.wallet.account; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.BalanceContract; -import org.tron.protos.contract.WitnessContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class WalletTestAccount005 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - private final String notWitnessTestKey = - "8CB4480194192F30907E14B52498F594BD046E21D7C4D8FE866563A6760AC891"; - - private final byte[] notWitness = PublicMethed.getFinalAddress(notWitnessTestKey); - - private ManagedChannel channelFull = null; - private ManagedChannel searchChannelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletGrpc.WalletBlockingStub searchBlockingStubFull = null; - private String fullnode = - Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String searchFullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext() - .build(); - searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); - - - } - - @Test - public void testWithdrawBalance() { - //Withdraw failed when you are not witness - Assert.assertFalse(withdrawBalance(notWitness, notWitnessTestKey)); - //Due to it's hard to automation, withdraw balance success case is not automation, - // please test by manual - //Assert.assertTrue(WithdrawBalance(fromAddress,testKey002)); - //Withdraw failed when the latest time to withdraw within 1 day. - - if (withdrawBalance(fromAddress, testKey002)) { - Assert.assertFalse(withdrawBalance(fromAddress, testKey002)); - } else { - logger.info("This account has withdraw within 1 day, please confirm"); - } - - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (searchChannelFull != null) { - searchChannelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public boolean withdrawBalance(byte[] address, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - BalanceContract.WithdrawBalanceContract.Builder builder = - BalanceContract.WithdrawBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - builder.setOwnerAddress(byteAddreess); - BalanceContract.WithdrawBalanceContract contract = builder.build(); - - Transaction transaction = blockingStubFull.withdrawBalance(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return false; - } - logger.info("test withdraw" + priKey); - return true; - - } - - /** - * constructor. - */ - - public Boolean voteWitness(HashMap witness, byte[] address, String priKey) { - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account beforeVote = queryAccount(ecKey, blockingStubFull); - Long beforeVoteNum = 0L; - if (beforeVote.getVotesCount() != 0) { - beforeVoteNum = beforeVote.getVotes(0).getVoteCount(); - } - - WitnessContract.VoteWitnessContract.Builder builder = WitnessContract.VoteWitnessContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - for (String addressBase58 : witness.keySet()) { - String value = witness.get(addressBase58); - long count = Long.parseLong(value); - WitnessContract.VoteWitnessContract.Vote.Builder voteBuilder = - WitnessContract.VoteWitnessContract.Vote.newBuilder(); - byte[] addRess = WalletClient.decodeFromBase58Check(addressBase58); - if (addRess == null) { - continue; - } - voteBuilder.setVoteAddress(ByteString.copyFrom(address)); - voteBuilder.setVoteCount(count); - builder.addVotes(voteBuilder.build()); - } - - WitnessContract.VoteWitnessContract contract = builder.build(); - - Transaction transaction = blockingStubFull.voteWitnessAccount(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - return false; - } - Account afterVote = queryAccount(ecKey, searchBlockingStubFull); - //Long afterVoteNum = afterVote.getVotes(0).getVoteCount(); - for (String key : witness.keySet()) { - for (int j = 0; j < afterVote.getVotesCount(); j++) { - if (key.equals(afterVote.getVotes(j).getVoteAddress())) { - Long afterVoteNum = Long.parseLong(witness.get(key)); - Assert.assertTrue(afterVoteNum == afterVote.getVotes(j).getVoteCount()); - logger.info("test equal vote"); - } - } - } - return true; - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount006.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount006.java deleted file mode 100644 index 539d53b3761..00000000000 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount006.java +++ /dev/null @@ -1,186 +0,0 @@ -package stest.tron.wallet.account; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AccountNetMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAccount006 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static final long sendAmount = 20000000000L; - private static final long FREENETLIMIT = 5000L; - private static final long BASELINE = 4800L; - private static String name = "AssetIssue012_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - //get account - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] account006Address = ecKey.getAddress(); - String account006Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(account006Key); - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void test1GetAccountNet() { - ecKey = new ECKey(Utils.getRandom()); - account006Address = ecKey.getAddress(); - account006Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - //Sendcoin to this account - ByteString addressBS1 = ByteString.copyFrom(account006Address); - Account request1 = Account.newBuilder().setAddress(addressBS1).build(); - GrpcAPI.AssetIssueList assetIssueList1 = blockingStubFull - .getAssetIssueByAccount(request1); - Optional queryAssetByAccount = Optional.ofNullable(assetIssueList1); - Assert.assertTrue(PublicMethed.freezeBalance(fromAddress, 100000000, 3, testKey002, - blockingStubFull)); - Assert.assertTrue(PublicMethed - .sendcoin(account006Address, sendAmount, fromAddress, testKey002, blockingStubFull)); - - //Get new account net information. - ByteString addressBs = ByteString.copyFrom(account006Address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - AccountNetMessage accountNetMessage = blockingStubFull.getAccountNet(request); - logger.info(Long.toString(accountNetMessage.getNetLimit())); - logger.info(Long.toString(accountNetMessage.getNetUsed())); - logger.info(Long.toString(accountNetMessage.getFreeNetLimit())); - logger.info(Long.toString(accountNetMessage.getFreeNetUsed())); - logger.info(Long.toString(accountNetMessage.getTotalNetLimit())); - logger.info(Long.toString(accountNetMessage.getTotalNetWeight())); - Assert.assertTrue(accountNetMessage.getNetLimit() == 0); - Assert.assertTrue(accountNetMessage.getNetUsed() == 0); - Assert.assertTrue(accountNetMessage.getFreeNetLimit() == FREENETLIMIT); - Assert.assertTrue(accountNetMessage.getFreeNetUsed() == 0); - Assert.assertTrue(accountNetMessage.getTotalNetLimit() > 0); - Assert.assertTrue(accountNetMessage.getTotalNetWeight() > 0); - logger.info("testGetAccountNet"); - - } - - @Test(enabled = true) - public void test2UseFreeNet() { - - //Transfer some TRX to other to test free net cost. - Assert.assertTrue(PublicMethed.sendcoin(fromAddress, 1L, account006Address, - account006Key, blockingStubFull)); - ByteString addressBs = ByteString.copyFrom(account006Address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - AccountNetMessage accountNetMessage = blockingStubFull.getAccountNet(request); - //Every transaction may cost 200 net. - Assert.assertTrue(accountNetMessage.getFreeNetUsed() > 0 && accountNetMessage - .getFreeNetUsed() < 300); - logger.info("testUseFreeNet"); - } - - @Test(enabled = true) - public void test3UseMoneyToDoTransaction() { - Assert.assertTrue(PublicMethed.sendcoin(account006Address, 1000000L, fromAddress, - testKey002, blockingStubFull)); - ByteString addressBs = ByteString.copyFrom(account006Address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - AccountNetMessage accountNetMessage = blockingStubFull.getAccountNet(request); - //Use out the free net - Integer times = 0; - while (accountNetMessage.getFreeNetUsed() < BASELINE && times++ < 30) { - PublicMethed.sendcoin(fromAddress, 1L, account006Address, account006Key, - blockingStubFull); - accountNetMessage = blockingStubFull.getAccountNet(request); - } - - Account queryAccount = PublicMethed.queryAccount(account006Key, blockingStubFull); - Long beforeSendBalance = queryAccount.getBalance(); - Assert.assertTrue(PublicMethed.sendcoin(fromAddress, 1L, account006Address, account006Key, - blockingStubFull)); - queryAccount = PublicMethed.queryAccount(account006Key, blockingStubFull); - Long afterSendBalance = queryAccount.getBalance(); - //when the free net is not enough and no balance freeze, use money to do the transaction. - Assert.assertTrue(beforeSendBalance - afterSendBalance > 1); - logger.info("testUseMoneyToDoTransaction"); - } - - @Test(enabled = true) - public void test4UseNet() { - //Freeze balance to own net. - Assert.assertTrue(PublicMethed.freezeBalance(account006Address, 10000000L, - 3, account006Key, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(toAddress, 1L, account006Address, - account006Key, blockingStubFull)); - ByteString addressBs = ByteString.copyFrom(account006Address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - AccountNetMessage accountNetMessage = blockingStubFull.getAccountNet(request); - Assert.assertTrue(accountNetMessage.getNetLimit() > 0); - Assert.assertTrue(accountNetMessage.getNetUsed() > 150); - - Account queryAccount = PublicMethed.queryAccount(account006Key, blockingStubFull); - Long beforeSendBalance = queryAccount.getBalance(); - Assert.assertTrue(PublicMethed.sendcoin(fromAddress, 1L, account006Address, - account006Key, blockingStubFull)); - queryAccount = PublicMethed.queryAccount(account006Key, blockingStubFull); - Long afterSendBalance = queryAccount.getBalance(); - //when you freeze balance and has net,you didn't cost money. - logger.info("before is " + Long.toString(beforeSendBalance) + " and after is " - + Long.toString(afterSendBalance)); - Assert.assertTrue(beforeSendBalance - afterSendBalance == 1); - addressBs = ByteString.copyFrom(account006Address); - request = Account.newBuilder().setAddress(addressBs).build(); - accountNetMessage = blockingStubFull.getAccountNet(request); - //when you freeze balance and has net,you cost net. - logger.info(Long.toString(accountNetMessage.getNetUsed())); - Assert.assertTrue(accountNetMessage.getNetUsed() > 350); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount007.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount007.java deleted file mode 100644 index 926c24310d7..00000000000 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount007.java +++ /dev/null @@ -1,126 +0,0 @@ -package stest.tron.wallet.account; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountNetMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAccount007 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static final long sendAmount = 10000000000L; - private static final long FREENETLIMIT = 5000L; - private static final long BASELINE = 4800L; - private static String name = "AssetIssue012_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - //owner account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] account007Address = ecKey1.getAddress(); - String account007Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - //Wait to be create account - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] newAccountAddress = ecKey2.getAddress(); - String newAccountKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - logger.info(account007Key); - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - @Test(enabled = true) - public void testCreateAccount() { - Assert.assertTrue(PublicMethed.sendcoin(account007Address, 10000000, - fromAddress, testKey002, blockingStubFull)); - Account accountInfo = PublicMethed.queryAccount(account007Key, blockingStubFull); - final Long beforeBalance = accountInfo.getBalance(); - - AccountNetMessage accountNetInfo = PublicMethed.getAccountNet(account007Address, - blockingStubFull); - final Long beforeFreeNet = accountNetInfo.getFreeNetUsed(); - - Assert.assertTrue(PublicMethed.createAccount(account007Address, newAccountAddress, - account007Key, blockingStubFull)); - - accountInfo = PublicMethed.queryAccount(account007Key, blockingStubFull); - Long afterBalance = accountInfo.getBalance(); - - accountNetInfo = PublicMethed.getAccountNet(account007Address, - blockingStubFull); - Long afterFreeNet = accountNetInfo.getFreeNetUsed(); - - logger.info(Long.toString(beforeBalance)); - logger.info(Long.toString(afterBalance)); - - //When creator has no bandwidth, he can't use the free net. - Assert.assertTrue(afterFreeNet == beforeFreeNet); - - //When the creator has no bandwidth, create a new account should spend 0.1TRX. - Assert.assertTrue(beforeBalance - afterBalance == 100000); - } - - @Test(enabled = true) - public void testExceptionCreateAccount() { - //Try to create an exist account - Assert - .assertFalse(PublicMethed.createAccount(account007Address, account007Address, account007Key, - blockingStubFull)); - - //Try to create an invalid account - byte[] wrongAddress = "wrongAddress".getBytes(); - Assert.assertFalse(PublicMethed.createAccount(account007Address, wrongAddress, account007Key, - blockingStubFull)); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount009.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount009.java deleted file mode 100644 index 5814f539df8..00000000000 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount009.java +++ /dev/null @@ -1,122 +0,0 @@ -package stest.tron.wallet.account; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAccount009 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static final long sendAmount = 10000000000L; - private static final long FREENETLIMIT = 5000L; - private static final long BASELINE = 4800L; - private static String name = "AssetIssue012_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] account009Address = ecKey1.getAddress(); - String account009Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] account009SecondAddress = ecKey2.getAddress(); - String account009SecondKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] account009InvalidAddress = ecKey3.getAddress(); - String account009InvalidKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(account009Key); - PublicMethed.printAddress(account009SecondKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - @Test(enabled = true) - public void testGetEnergy() { - Assert.assertTrue(PublicMethed.sendcoin(account009Address, 10000000, - fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(account009SecondAddress, 10000000, - fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(account009InvalidAddress, 10000000, - fromAddress, testKey002, blockingStubFull)); - - Account account009Info = PublicMethed.queryAccount(account009Key, blockingStubFull); - logger.info(Long.toString( - account009Info.getAccountResource().getFrozenBalanceForEnergy().getExpireTime())); - Assert.assertTrue(account009Info.getAccountResource().getEnergyUsage() == 0); - Assert.assertTrue(account009Info.getAccountResource().getFrozenBalanceForEnergy() - .getExpireTime() == 0); - - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(account009Address, 1000000L, - 3, 1, account009Key, blockingStubFull)); - account009Info = PublicMethed.queryAccount(account009Key, blockingStubFull); - Assert.assertTrue(account009Info.getAccountResource().getEnergyUsage() == 0); - Assert.assertTrue(account009Info.getAccountResource().getFrozenBalanceForEnergy() - .getFrozenBalance() == 1000000L); - - AccountResourceMessage account009Resource = PublicMethed.getAccountResource(account009Address, - blockingStubFull); - Assert.assertTrue(account009Resource.getTotalEnergyLimit() >= 50000000000L); - Assert.assertTrue(account009Resource.getEnergyLimit() > 0); - Assert.assertTrue(account009Resource.getTotalEnergyWeight() >= 1); - } - - @Test(enabled = true) - public void testGetEnergyInvalid() { - //The resourceCode can only be 0 or 1 - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(account009InvalidAddress, - 1000000L, 3, 0, account009InvalidKey, blockingStubFull)); - Assert.assertFalse(PublicMethed.freezeBalanceGetEnergy(account009InvalidAddress, 1000000L, - 3, -1, account009InvalidKey, blockingStubFull)); - Assert.assertFalse(PublicMethed.freezeBalanceGetEnergy(account009InvalidAddress, 1000000L, - 3, 3, account009InvalidKey, blockingStubFull)); - - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount011.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount011.java deleted file mode 100644 index 263dfbaa773..00000000000 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount011.java +++ /dev/null @@ -1,76 +0,0 @@ -package stest.tron.wallet.account; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAccount011 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] account011Address = ecKey1.getAddress(); - String account011Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(account011Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - - } - - } -} diff --git a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock003.java b/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock003.java deleted file mode 100644 index dc6a60bb430..00000000000 --- a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock003.java +++ /dev/null @@ -1,144 +0,0 @@ -package stest.tron.wallet.block; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class WalletTestBlock003 { - - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true) - public void testGetNextMaintenanceTime() { - long now = System.currentTimeMillis(); - NumberMessage getNextMaintenanceTime = blockingStubFull - .getNextMaintenanceTime(GrpcAPI.EmptyMessage.newBuilder().build()); - logger.info(Long.toString(getNextMaintenanceTime.getNum())); - logger.info(Long.toString(now)); - Assert.assertTrue(getNextMaintenanceTime.getNum() > now); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock004.java b/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock004.java deleted file mode 100644 index 67ae17f0303..00000000000 --- a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock004.java +++ /dev/null @@ -1,203 +0,0 @@ -package stest.tron.wallet.block; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; - -//import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIConversion; - -//import stest.tron.wallet.common.client.AccountComparator; - -@Slf4j -public class WalletTestBlock004 { - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void testGetBlockByLimitNext() { - // - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Assert.assertFalse(currentBlockNum < 0); - while (currentBlockNum <= 5) { - logger.info("Now has very little block, Please wait"); - currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - } - - GrpcAPI.BlockLimit.Builder builder = GrpcAPI.BlockLimit.newBuilder(); - builder.setStartNum(2); - builder.setEndNum(4); - GrpcAPI.BlockList blockList = blockingStubFull.getBlockByLimitNext(builder.build()); - Optional getBlockByLimitNext = Optional.ofNullable(blockList); - Assert.assertTrue(getBlockByLimitNext.isPresent()); - Assert.assertTrue(getBlockByLimitNext.get().getBlockCount() == 2); - logger.info(Long.toString( - getBlockByLimitNext.get().getBlock(0).getBlockHeader().getRawData().getNumber())); - logger.info(Long.toString( - getBlockByLimitNext.get().getBlock(1).getBlockHeader().getRawData().getNumber())); - Assert.assertTrue( - getBlockByLimitNext.get().getBlock(0).getBlockHeader().getRawData().getNumber() < 4); - Assert.assertTrue( - getBlockByLimitNext.get().getBlock(1).getBlockHeader().getRawData().getNumber() < 4); - Assert.assertTrue(getBlockByLimitNext.get().getBlock(0).hasBlockHeader()); - Assert.assertTrue(getBlockByLimitNext.get().getBlock(1).hasBlockHeader()); - Assert.assertFalse( - getBlockByLimitNext.get().getBlock(0).getBlockHeader().getRawData().getParentHash() - .isEmpty()); - Assert.assertFalse( - getBlockByLimitNext.get().getBlock(1).getBlockHeader().getRawData().getParentHash() - .isEmpty()); - } - - @Test(enabled = true) - public void testGetBlockByExceptionLimitNext() { - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Assert.assertFalse(currentBlockNum < 0); - while (currentBlockNum <= 5) { - logger.info("Now has very little block, Please wait"); - currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - } - - //From -1 to 1 - GrpcAPI.BlockLimit.Builder builder = GrpcAPI.BlockLimit.newBuilder(); - builder.setStartNum(-1); - builder.setEndNum(1); - GrpcAPI.BlockList blockList = blockingStubFull.getBlockByLimitNext(builder.build()); - Optional getBlockByLimitNext = Optional.ofNullable(blockList); - Assert.assertTrue(getBlockByLimitNext.get().getBlockCount() == 0); - - //From 3 to 3 - builder = GrpcAPI.BlockLimit.newBuilder(); - builder.setStartNum(3); - builder.setEndNum(3); - blockList = blockingStubFull.getBlockByLimitNext(builder.build()); - getBlockByLimitNext = Optional.ofNullable(blockList); - Assert.assertTrue(getBlockByLimitNext.get().getBlockCount() == 0); - - //From 4 to 2 - builder = GrpcAPI.BlockLimit.newBuilder(); - builder.setStartNum(4); - builder.setEndNum(2); - blockList = blockingStubFull.getBlockByLimitNext(builder.build()); - getBlockByLimitNext = Optional.ofNullable(blockList); - Assert.assertTrue(getBlockByLimitNext.get().getBlockCount() == 0); - - //From 999999990 to 999999999 - builder = GrpcAPI.BlockLimit.newBuilder(); - builder.setStartNum(999999990); - builder.setEndNum(999999999); - blockList = blockingStubFull.getBlockByLimitNext(builder.build()); - getBlockByLimitNext = Optional.ofNullable(blockList); - Assert.assertTrue(getBlockByLimitNext.get().getBlockCount() == 0); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock005.java b/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock005.java deleted file mode 100644 index 14c3674cb76..00000000000 --- a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock005.java +++ /dev/null @@ -1,177 +0,0 @@ -package stest.tron.wallet.block; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; - -//import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIConversion; - -//import stest.tron.wallet.common.client.AccountComparator; - -@Slf4j -public class WalletTestBlock005 { - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void testGetBlockByLatestNum() { - // - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Assert.assertFalse(currentBlockNum < 0); - while (currentBlockNum <= 5) { - logger.info("Now the block num is " + Long.toString(currentBlockNum) + " Please wait"); - currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - } - - NumberMessage numberMessage = NumberMessage.newBuilder().setNum(3).build(); - GrpcAPI.BlockList blockList = blockingStubFull.getBlockByLatestNum(numberMessage); - Optional getBlockByLatestNum = Optional.ofNullable(blockList); - Assert.assertTrue(getBlockByLatestNum.isPresent()); - Assert.assertTrue(getBlockByLatestNum.get().getBlockCount() == 3); - Assert.assertTrue(getBlockByLatestNum.get().getBlock(0).hasBlockHeader()); - Assert.assertTrue( - getBlockByLatestNum.get().getBlock(1).getBlockHeader().getRawData().getNumber() > 0); - Assert.assertFalse( - getBlockByLatestNum.get().getBlock(2).getBlockHeader().getRawData().getParentHash() - .isEmpty()); - logger.info("TestGetBlockByLatestNum ok!!!"); - - } - - @Test(enabled = true) - public void testGetBlockByExceptionNum() { - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Assert.assertFalse(currentBlockNum < 0); - while (currentBlockNum <= 5) { - logger.info("Now the block num is " + Long.toString(currentBlockNum) + " Please wait"); - currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - } - NumberMessage numberMessage = NumberMessage.newBuilder().setNum(-1).build(); - GrpcAPI.BlockList blockList = blockingStubFull.getBlockByLatestNum(numberMessage); - Optional getBlockByLatestNum = Optional.ofNullable(blockList); - Assert.assertTrue(getBlockByLatestNum.get().getBlockCount() == 0); - - numberMessage = NumberMessage.newBuilder().setNum(0).build(); - blockList = blockingStubFull.getBlockByLatestNum(numberMessage); - getBlockByLatestNum = Optional.ofNullable(blockList); - Assert.assertTrue(getBlockByLatestNum.get().getBlockCount() == 0); - - numberMessage = NumberMessage.newBuilder().setNum(100).build(); - blockList = blockingStubFull.getBlockByLatestNum(numberMessage); - getBlockByLatestNum = Optional.ofNullable(blockList); - Assert.assertTrue(getBlockByLatestNum.get().getBlockCount() == 0); - - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock006.java b/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock006.java deleted file mode 100644 index 09175895c37..00000000000 --- a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock006.java +++ /dev/null @@ -1,111 +0,0 @@ -package stest.tron.wallet.block; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Block; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; - -@Slf4j -public class WalletTestBlock006 { - - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true) - public void testGetTransactionCountByBlockNumFromFullnode() { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(0); - Long transactionNumInBlock = 0L; - transactionNumInBlock = blockingStubFull.getTransactionCountByBlockNum(builder - .build()).getNum(); - Assert.assertTrue(transactionNumInBlock >= 1); - - builder.setNum(-10); - transactionNumInBlock = blockingStubFull.getTransactionCountByBlockNum(builder - .build()).getNum(); - Assert.assertTrue(transactionNumInBlock == -1); - - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - builder.setNum(currentBlockNum + 10000L); - transactionNumInBlock = blockingStubFull.getTransactionCountByBlockNum(builder - .build()).getNum(); - Assert.assertTrue(transactionNumInBlock == -1); - } - - @Test(enabled = true) - public void testGetTransactionCountByBlockNumFromSolidity() { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(0); - Long transactionNumInBlock = 0L; - transactionNumInBlock = blockingStubSolidity.getTransactionCountByBlockNum(builder - .build()).getNum(); - Assert.assertTrue(transactionNumInBlock >= 1); - - builder.setNum(-10); - transactionNumInBlock = blockingStubSolidity.getTransactionCountByBlockNum(builder - .build()).getNum(); - Assert.assertTrue(transactionNumInBlock == -1); - - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - builder.setNum(currentBlockNum + 10000L); - transactionNumInBlock = blockingStubSolidity.getTransactionCountByBlockNum(builder - .build()).getNum(); - Assert.assertTrue(transactionNumInBlock == -1); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee001.java b/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee001.java deleted file mode 100644 index b74448b0dff..00000000000 --- a/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee001.java +++ /dev/null @@ -1,131 +0,0 @@ -package stest.tron.wallet.committee; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.PaginatedMessage; -import org.tron.api.GrpcAPI.ProposalList; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class WalletTestCommittee001 { - - private static final long now = System.currentTimeMillis(); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - //Witness 47.93.9.236 - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - //Witness 47.93.33.201 - private final String witnessKey002 = Configuration.getByPath("testng.conf") - .getString("witness.key2"); - //Witness 123.56.10.6 - private final String witnessKey003 = Configuration.getByPath("testng.conf") - .getString("witness.key3"); - //Wtiness 39.107.80.135 - private final String witnessKey004 = Configuration.getByPath("testng.conf") - .getString("witness.key4"); - //Witness 47.93.184.2 - private final String witnessKey005 = Configuration.getByPath("testng.conf") - .getString("witness.key5"); - private final byte[] witness001Address = PublicMethed.getFinalAddress(witnessKey001); - private final byte[] witness002Address = PublicMethed.getFinalAddress(witnessKey002); - private final byte[] witness003Address = PublicMethed.getFinalAddress(witnessKey003); - private final byte[] witness004Address = PublicMethed.getFinalAddress(witnessKey004); - private final byte[] witness005Address = PublicMethed.getFinalAddress(witnessKey005); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - - @Test - public void testListProposals() { - //List proposals - ProposalList proposalList = blockingStubFull.listProposals(EmptyMessage.newBuilder().build()); - Optional listProposals = Optional.ofNullable(proposalList); - final Integer beforeProposalCount = listProposals.get().getProposalsCount(); - - //CreateProposal - final long now = System.currentTimeMillis(); - HashMap proposalMap = new HashMap(); - proposalMap.put(0L, 1000000L); - PublicMethed.createProposal(witness001Address, witnessKey001, proposalMap, blockingStubFull); - - //List proposals - proposalList = blockingStubFull.listProposals(EmptyMessage.newBuilder().build()); - listProposals = Optional.ofNullable(proposalList); - Integer afterProposalCount = listProposals.get().getProposalsCount(); - Assert.assertTrue(beforeProposalCount + 1 == afterProposalCount); - logger.info(Long.toString(listProposals.get().getProposals(0).getCreateTime())); - logger.info(Long.toString(now)); - //Assert.assertTrue(listProposals.get().getProposals(0).getCreateTime() >= now); - Assert.assertTrue(listProposals.get().getProposals(0).getParametersMap().equals(proposalMap)); - - //getProposalListPaginated - PaginatedMessage.Builder pageMessageBuilder = PaginatedMessage.newBuilder(); - pageMessageBuilder.setOffset(0); - pageMessageBuilder.setLimit(1); - ProposalList paginatedProposalList = blockingStubFull - .getPaginatedProposalList(pageMessageBuilder.build()); - Assert.assertTrue(paginatedProposalList.getProposalsCount() >= 1); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee002.java b/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee002.java deleted file mode 100644 index 6ac3e112e9a..00000000000 --- a/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee002.java +++ /dev/null @@ -1,365 +0,0 @@ -package stest.tron.wallet.committee; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class WalletTestCommittee002 { - - private static final long now = System.currentTimeMillis(); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - //Witness 47.93.9.236 - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - //Witness 47.93.33.201 - private final String witnessKey002 = Configuration.getByPath("testng.conf") - .getString("witness.key2"); - //Witness 123.56.10.6 - private final String witnessKey003 = Configuration.getByPath("testng.conf") - .getString("witness.key3"); - //Wtiness 39.107.80.135 - private final String witnessKey004 = Configuration.getByPath("testng.conf") - .getString("witness.key4"); - //Witness 47.93.184.2 - private final String witnessKey005 = Configuration.getByPath("testng.conf") - .getString("witness.key5"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - private final byte[] witness001Address = PublicMethed.getFinalAddress(witnessKey001); - private final byte[] witness002Address = PublicMethed.getFinalAddress(witnessKey002); - private final byte[] witness003Address = PublicMethed.getFinalAddress(witnessKey003); - private final byte[] witness004Address = PublicMethed.getFinalAddress(witnessKey004); - private final byte[] witness005Address = PublicMethed.getFinalAddress(witnessKey005); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - } - - - @Test(enabled = true) - public void testCreateProposalMaintenanceTimeInterval() { - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - Assert.assertTrue(PublicMethed.sendcoin(witness001Address, 10000000L, - toAddress, testKey003, blockingStubFull)); - - //0:MAINTENANCE_TIME_INTERVAL,[3*27s,24h] - //Minimum interval - HashMap proposalMap = new HashMap(); - proposalMap.put(0L, 81000L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Maximum interval - proposalMap.put(0L, 86400000L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Minimum -1 interval, create failed. - proposalMap.put(0L, 80000L); - Assert.assertFalse(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Maximum + 1 interval - proposalMap.put(0L, 86401000L); - Assert.assertFalse(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Non witness account - proposalMap.put(0L, 86400000L); - Assert.assertFalse(PublicMethed.createProposal(toAddress, testKey003, proposalMap, - blockingStubFull)); - } - - @Test(enabled = true) - public void testCreateProposalAccountUpgradeCost() { - //1:ACCOUNT_UPGRADE_COST,[0,100 000 000 000 000 000]//drop - //Minimum AccountUpgradeCost - HashMap proposalMap = new HashMap(); - proposalMap.put(1L, 0L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Maximum AccountUpgradeCost - proposalMap.put(1L, 100000000000000000L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Minimum - 1 AccountUpgradeCost - proposalMap.put(1L, -1L); - Assert.assertFalse(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Maximum + 1 AccountUpgradeCost - proposalMap.put(1L, 100000000000000001L); - Assert.assertFalse(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Non witness account - proposalMap.put(1L, 86400000L); - Assert.assertFalse(PublicMethed.createProposal(toAddress, testKey003, - proposalMap, blockingStubFull)); - } - - @Test(enabled = true) - public void testCreateProposalCreateAccountFee() { - //2:CREATE_ACCOUNT_FEE,[0,100 000 000 000 000 000]//drop - //Minimum CreateAccountFee - HashMap proposalMap = new HashMap(); - proposalMap.put(2L, 0L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Maximum CreateAccountFee - proposalMap.put(2L, 100000000000000000L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Minimum - 1 CreateAccountFee - proposalMap.put(2L, -1L); - Assert.assertFalse(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Maximum + 1 CreateAccountFee - proposalMap.put(2L, 100000000000000001L); - Assert.assertFalse(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Non witness account - proposalMap.put(2L, 86400000L); - Assert.assertFalse(PublicMethed.createProposal(toAddress, testKey003, - proposalMap, blockingStubFull)); - - } - - @Test(enabled = true) - public void testTransactionFee() { - //3:TRANSACTION_FEE,[0,100 000 000 000 000 000]//drop - //Minimum TransactionFee - HashMap proposalMap = new HashMap(); - proposalMap.put(3L, 0L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Maximum TransactionFee - proposalMap.put(3L, 100000000000000000L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Minimum - 1 TransactionFee - proposalMap.put(3L, -1L); - Assert.assertFalse(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Maximum + 1 TransactionFee - proposalMap.put(3L, 100000000000000001L); - Assert.assertFalse(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Non witness account - proposalMap.put(3L, 86400000L); - Assert.assertFalse(PublicMethed.createProposal(toAddress, testKey003, - proposalMap, blockingStubFull)); - - } - - @Test(enabled = true) - public void testAssetIssueFee() { - //4:ASSET_ISSUE_FEE,[0,100 000 000 000 000 000]//drop - //Minimum AssetIssueFee - HashMap proposalMap = new HashMap(); - proposalMap.put(4L, 0L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Duplicat proposals - proposalMap.put(4L, 0L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Maximum AssetIssueFee - proposalMap.put(4L, 100000000000000000L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Minimum - 1 AssetIssueFee - proposalMap.put(4L, -1L); - Assert.assertFalse(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Maximum + 1 AssetIssueFee - proposalMap.put(4L, 100000000000000001L); - Assert.assertFalse(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Non witness account - proposalMap.put(4L, 86400000L); - Assert.assertFalse(PublicMethed.createProposal(toAddress, testKey003, - proposalMap, blockingStubFull)); - - } - - @Test(enabled = true) - public void testWitnessPayPerBlock() { - //5:WITNESS_PAY_PER_BLOCK,[0,100 000 000 000 000 000]//drop - //Minimum WitnessPayPerBlock - HashMap proposalMap = new HashMap(); - proposalMap.put(5L, 0L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Maximum WitnessPayPerBlock - proposalMap.put(5L, 100000000000000000L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Minimum - 1 WitnessPayPerBlock - proposalMap.put(5L, -1L); - Assert.assertFalse(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Maximum + 1 WitnessPayPerBlock - proposalMap.put(5L, 100000000000000001L); - Assert.assertFalse(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Non witness account - proposalMap.put(5L, 86400000L); - Assert.assertFalse(PublicMethed.createProposal(toAddress, testKey003, - proposalMap, blockingStubFull)); - - } - - @Test(enabled = true) - public void testWitnessStandbyAllowance() { - //6:WITNESS_STANDBY_ALLOWANCE,[0,100 000 000 000 000 000]//drop - //Minimum WitnessStandbyAllowance - HashMap proposalMap = new HashMap(); - proposalMap.put(6L, 0L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Maximum WitnessStandbyAllowance - proposalMap.put(6L, 100000000000000000L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Minimum - 1 WitnessStandbyAllowance - proposalMap.put(6L, -1L); - Assert.assertFalse(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Maximum + 1 WitnessStandbyAllowance - proposalMap.put(6L, 100000000000000001L); - Assert.assertFalse(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Non witness account - proposalMap.put(6L, 86400000L); - Assert.assertFalse(PublicMethed.createProposal(toAddress, testKey003, - proposalMap, blockingStubFull)); - - } - - @Test(enabled = true) - public void testCreateNewAccountFeeInSystemControl() { - //7:CREATE_NEW_ACCOUNT_FEE_IN_SYSTEM_CONTRACT,0 or 1 - HashMap proposalMap = new HashMap(); - proposalMap.put(7L, 1L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Maximum WitnessStandbyAllowance - proposalMap.put(7L, 100000000000000000L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Minimum - 1 WitnessStandbyAllowance - proposalMap.put(6L, -1L); - Assert.assertFalse(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Maximum + 1 WitnessStandbyAllowance - proposalMap.put(6L, 100000000000000001L); - Assert.assertFalse(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //Non witness account - proposalMap.put(6L, 86400000L); - Assert.assertFalse(PublicMethed.createProposal(toAddress, testKey003, - proposalMap, blockingStubFull)); - - } - - - @Test(enabled = true) - public void testInvalidProposals() { - // The index isn't from 0-9 - HashMap proposalMap = new HashMap(); - proposalMap.put(10L, 60L); - Assert.assertFalse(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - //The index is -1 - proposalMap.put(-1L, 6L); - Assert.assertFalse(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee003.java b/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee003.java deleted file mode 100644 index c9f3c3d7221..00000000000 --- a/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee003.java +++ /dev/null @@ -1,166 +0,0 @@ -package stest.tron.wallet.committee; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.ProposalList; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class WalletTestCommittee003 { - - private static final long now = System.currentTimeMillis(); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - //Witness 47.93.33.201 - private final String witnessKey002 = Configuration.getByPath("testng.conf") - .getString("witness.key2"); - //Witness 123.56.10.6 - private final String witnessKey003 = Configuration.getByPath("testng.conf") - .getString("witness.key3"); - //Wtiness 39.107.80.135 - private final String witnessKey004 = Configuration.getByPath("testng.conf") - .getString("witness.key4"); - //Witness 47.93.184.2 - private final String witnessKey005 = Configuration.getByPath("testng.conf") - .getString("witness.key5"); - private final byte[] witness001Address = PublicMethed.getFinalAddress(witnessKey001); - //private final byte[] witness003Address = PublicMethed.getFinalAddress(witnessKey003); - //private final byte[] witness004Address = PublicMethed.getFinalAddress(witnessKey004); - //private final byte[] witness005Address = PublicMethed.getFinalAddress(witnessKey005); - private final byte[] witness002Address = PublicMethed.getFinalAddress(witnessKey002); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true) - public void testApproveProposal() { - PublicMethed.sendcoin(witness001Address, 1000000L, - toAddress, testKey003, blockingStubFull); - PublicMethed.sendcoin(witness002Address, 1000000L, - toAddress, testKey003, blockingStubFull); - - HashMap proposalMap = new HashMap(); - proposalMap.put(0L, 81000L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Get proposal list - ProposalList proposalList = blockingStubFull.listProposals(EmptyMessage.newBuilder().build()); - Optional listProposals = Optional.ofNullable(proposalList); - final Integer proposalId = listProposals.get().getProposalsCount(); - logger.info(Integer.toString(proposalId)); - - Assert.assertTrue(PublicMethed.approveProposal(witness002Address, witnessKey002, proposalId, - true, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Get proposal list after approve - proposalList = blockingStubFull.listProposals(EmptyMessage.newBuilder().build()); - listProposals = Optional.ofNullable(proposalList); - logger.info(Integer.toString(listProposals.get().getProposals(0).getApprovalsCount())); - Assert.assertTrue(listProposals.get().getProposals(0).getApprovalsCount() == 1); - //logger.info(Base58.encode58Check(witness002Address)); - //logger.info(Base58.encode58Check(listProposals.get().getProposals(0). - // getApprovalsList().get(0).toByteArray())); - Assert.assertTrue(Base58.encode58Check(witness002Address).equals(Base58.encode58Check( - listProposals.get().getProposals(0).getApprovalsList().get(0).toByteArray()))); - - //Failed to approve proposal when you already approval this proposal - Assert.assertFalse(PublicMethed.approveProposal(witness002Address, witnessKey002, proposalId, - true, blockingStubFull)); - - //Success to change the option from true to false. - Assert.assertTrue(PublicMethed.approveProposal(witness002Address, witnessKey002, proposalId, - false, blockingStubFull)); - proposalList = blockingStubFull.listProposals(EmptyMessage.newBuilder().build()); - listProposals = Optional.ofNullable(proposalList); - Assert.assertTrue(listProposals.get().getProposals(0).getApprovalsCount() == 0); - - //Failed to approvel proposal when you already approval this proposal - Assert.assertFalse(PublicMethed.approveProposal(witness002Address, witnessKey002, proposalId, - false, blockingStubFull)); - - //Non witness can't approval proposal - Assert.assertFalse(PublicMethed.approveProposal(toAddress, testKey003, proposalId, - true, blockingStubFull)); - - //Muti approval - Assert.assertTrue(PublicMethed.approveProposal(witness001Address, witnessKey001, proposalId, - true, blockingStubFull)); - Assert.assertTrue(PublicMethed.approveProposal(witness002Address, witnessKey002, proposalId, - true, blockingStubFull)); - //Assert.assertTrue(PublicMethed.approveProposal(witness003Address,witnessKey003,proposalId, - // true,blockingStubFull)); - //Assert.assertTrue(PublicMethed.approveProposal(witness004Address,witnessKey004,proposalId, - // true,blockingStubFull)); - //Assert.assertTrue(PublicMethed.approveProposal(witness005Address,witnessKey005,proposalId, - // true,blockingStubFull)); - proposalList = blockingStubFull.listProposals(EmptyMessage.newBuilder().build()); - listProposals = Optional.ofNullable(proposalList); - Assert.assertTrue(listProposals.get().getProposals(0).getApprovalsCount() == 2); - - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee004.java b/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee004.java deleted file mode 100644 index a5a02187b2c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee004.java +++ /dev/null @@ -1,219 +0,0 @@ -package stest.tron.wallet.committee; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.BytesMessage; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.ProposalList; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.utils.ByteArray; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.ChainParameters; -import org.tron.protos.Protocol.Proposal; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class WalletTestCommittee004 { - - private static final long now = System.currentTimeMillis(); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - //Witness 47.93.33.201 - private final String witnessKey002 = Configuration.getByPath("testng.conf") - .getString("witness.key2"); - //Witness 123.56.10.6 - private final String witnessKey003 = Configuration.getByPath("testng.conf") - .getString("witness.key3"); - //Wtiness 39.107.80.135 - private final String witnessKey004 = Configuration.getByPath("testng.conf") - .getString("witness.key4"); - //Witness 47.93.184.2 - private final String witnessKey005 = Configuration.getByPath("testng.conf") - .getString("witness.key5"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - private final byte[] witness001Address = PublicMethed.getFinalAddress(witnessKey001); - //private final byte[] witness003Address = PublicMethed.getFinalAddress(witnessKey003); - //private final byte[] witness004Address = PublicMethed.getFinalAddress(witnessKey004); - //private final byte[] witness005Address = PublicMethed.getFinalAddress(witnessKey005); - private final byte[] witness002Address = PublicMethed.getFinalAddress(witnessKey002); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true) - public void test1DeleteProposal() { - PublicMethed.sendcoin(witness001Address, 1000000L, - toAddress, testKey003, blockingStubFull); - PublicMethed.sendcoin(witness002Address, 1000000L, - toAddress, testKey003, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Create a proposal and approval it - HashMap proposalMap = new HashMap(); - proposalMap.put(1L, 99999L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - //Get proposal list - ProposalList proposalList = blockingStubFull.listProposals(EmptyMessage.newBuilder().build()); - Optional listProposals = Optional.ofNullable(proposalList); - final Integer proposalId = listProposals.get().getProposalsCount(); - Assert.assertTrue(PublicMethed.approveProposal(witness001Address, witnessKey001, - proposalId, true, blockingStubFull)); - logger.info(Integer.toString(listProposals.get().getProposals(0).getStateValue())); - //The state is "pending", state value == 0 - Assert.assertTrue(listProposals.get().getProposals(0).getStateValue() == 0); - - //When the proposal isn't created by you, you can't delete it. - Assert.assertFalse(PublicMethed.deleteProposal(witness002Address, witnessKey002, - proposalId, blockingStubFull)); - //Cancel the proposal - Assert.assertTrue(PublicMethed.deleteProposal(witness001Address, witnessKey001, - proposalId, blockingStubFull)); - //When the state is cancel, you can't delete it again. - Assert.assertFalse(PublicMethed.deleteProposal(witness001Address, witnessKey001, - proposalId, blockingStubFull)); - //You can't delete an invalid proposal - Assert.assertFalse(PublicMethed.deleteProposal(witness001Address, witnessKey001, - proposalId + 100, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - proposalList = blockingStubFull.listProposals(EmptyMessage.newBuilder().build()); - listProposals = Optional.ofNullable(proposalList); - logger.info(Integer.toString(listProposals.get().getProposals(0).getStateValue())); - //The state is "cancel", state value == 3 - Assert.assertTrue(listProposals.get().getProposals(0).getStateValue() == 3); - - //When the state is cancel, you can't approval proposal - Assert.assertFalse(PublicMethed.approveProposal(witness001Address, witnessKey001, - proposalId, true, blockingStubFull)); - Assert.assertFalse(PublicMethed.approveProposal(witness001Address, witnessKey001, - proposalId, false, blockingStubFull)); - } - - @Test(enabled = true) - public void test2GetProposal() { - //Create a proposal and approval it - HashMap proposalMap = new HashMap(); - proposalMap.put(1L, 999999999L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - //Get proposal list - ProposalList proposalList = blockingStubFull.listProposals(EmptyMessage.newBuilder().build()); - Optional listProposals = Optional.ofNullable(proposalList); - final Integer proposalId = listProposals.get().getProposalsCount(); - - BytesMessage request = BytesMessage.newBuilder().setValue(ByteString.copyFrom( - ByteArray.fromLong(Long.parseLong(proposalId.toString())))) - .build(); - Proposal proposal = blockingStubFull.getProposalById(request); - Optional getProposal = Optional.ofNullable(proposal); - - Assert.assertTrue(getProposal.isPresent()); - Assert.assertTrue(getProposal.get().getStateValue() == 0); - - //Invalid get proposal - final Integer wrongProposalId = proposalId + 99; - request = BytesMessage.newBuilder().setValue(ByteString.copyFrom( - ByteArray.fromLong(Long.parseLong(wrongProposalId.toString())))) - .build(); - proposal = blockingStubFull.getProposalById(request); - getProposal = Optional.ofNullable(proposal); - logger.info(Long.toString(getProposal.get().getCreateTime())); - Assert.assertTrue(getProposal.get().getCreateTime() == 0); - } - - @Test(enabled = false) - public void testGetChainParameters() { - //Set the default map - HashMap defaultCommitteeMap = new HashMap(); - defaultCommitteeMap.put("MAINTENANCE_TIME_INTERVAL", 300000L); - defaultCommitteeMap.put("ACCOUNT_UPGRADE_COST", 9999000000L); - defaultCommitteeMap.put("CREATE_ACCOUNT_FEE", 100000L); - defaultCommitteeMap.put("TRANSACTION_FEE", 10L); - defaultCommitteeMap.put("ASSET_ISSUE_FEE", 1024000000L); - defaultCommitteeMap.put("WITNESS_PAY_PER_BLOCK", 32000000L); - defaultCommitteeMap.put("WITNESS_STANDBY_ALLOWANCE", 115200000000L); - defaultCommitteeMap.put("CREATE_NEW_ACCOUNT_FEE_IN_SYSTEM_CONTRACT", 0L); - defaultCommitteeMap.put("CREATE_NEW_ACCOUNT_BANDWIDTH_RATE", 1L); - - ChainParameters chainParameters = blockingStubFull - .getChainParameters(EmptyMessage.newBuilder().build()); - Optional getChainParameters = Optional.ofNullable(chainParameters); - logger.info(Long.toString(getChainParameters.get().getChainParameterCount())); - for (Integer i = 0; i < getChainParameters.get().getChainParameterCount(); i++) { - logger.info(getChainParameters.get().getChainParameter(i).getKey()); - logger.info(Long.toString(getChainParameters.get().getChainParameter(i).getValue())); - } - Assert.assertTrue(getChainParameters.get().getChainParameterCount() >= 10); - Assert.assertTrue(getChainParameters.get() - .getChainParameter(1).getValue() == 9999000000L); - Assert.assertTrue(getChainParameters.get().getChainParameter(4) - .getValue() == 1024000000L); - Assert.assertTrue(getChainParameters.get().getChainParameter(7).getValue() == 0); - Assert.assertTrue(getChainParameters.get().getChainParameter(8).getValue() == 1); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/CipherException.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/CipherException.java deleted file mode 100644 index a0164c6bba6..00000000000 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/CipherException.java +++ /dev/null @@ -1,19 +0,0 @@ -package stest.tron.wallet.common.client.utils; - -/** - * Cipher exception wrapper. - */ -public class CipherException extends Exception { - - public CipherException(String message) { - super(message); - } - - public CipherException(Throwable cause) { - super(cause); - } - - public CipherException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/DailyBuildReport.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/DailyBuildReport.java deleted file mode 100644 index 67dfe7c18be..00000000000 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/DailyBuildReport.java +++ /dev/null @@ -1,167 +0,0 @@ -package stest.tron.wallet.common.client.utils; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import org.testng.ITestContext; -import org.testng.ITestResult; -import org.testng.TestListenerAdapter; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.protos.Protocol; -import stest.tron.wallet.common.client.Configuration; - -public class DailyBuildReport extends TestListenerAdapter { - - StringBuilder passedDescriptionList = new StringBuilder(""); - StringBuilder failedDescriptionList = new StringBuilder(""); - StringBuilder skippedDescriptionList = new StringBuilder(""); - private Integer passedNum = 0; - private Integer failedNum = 0; - private Integer skippedNum = 0; - private String reportPath; - public Map transactionType = new HashMap<>(); - public Long endBlockNum = 0L; - public static Long startBlockNum = 0L; - public Long totalTransactionNum = 0L; - public ManagedChannel channelFull = null; - public WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - - @Override - public void onStart(ITestContext context) { - reportPath = "Daily_Build_Report"; - StringBuilder sb = new StringBuilder("3.Stest report: "); - String res = sb.toString(); - try { - Files.write((Paths.get(reportPath)), res.getBytes("utf-8")); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void onTestSuccess(ITestResult result) { - passedDescriptionList.append(result.getMethod().getRealClass() + ": " - + result.getMethod().getDescription() + "\n"); - passedNum++; - } - - @Override - public void onTestFailure(ITestResult result) { - failedDescriptionList.append(result.getMethod().getRealClass() + ": " - + result.getMethod().getDescription() + "\n"); - failedNum++; - } - - @Override - public void onTestSkipped(ITestResult result) { - skippedDescriptionList.append(result.getMethod().getRealClass() + ": " - + result.getMethod().getDescription() + "\n"); - skippedNum++; - } - - - @Override - public void onFinish(ITestContext testContext) { - StringBuilder sb = new StringBuilder(); - sb.append("Total: " + (passedNum + failedNum + skippedNum) + ", " + "Passed: " + passedNum - + ", " + "Failed: " + failedNum + ", " + "Skipped: " + skippedNum + "\n"); - sb.append("------------------------------------------------------------------------------\n"); - List> list = calculateAfterDailyBuild(); - sb.append("Total transaction number:" + totalTransactionNum + "\n"); - sb.append("Transaction type list:" + "\n"); - for (Map.Entry entry : list) { - sb.append(entry.getKey()); - for (int i = entry.getKey().length(); i < 40; i++) { - sb.append(" "); - } - sb.append(" : " + entry.getValue() + "\n"); - - } - sb.append("------------------------------------------------------------------------------\n"); - sb.append("Passed list " + "\n"); - //sb.append("Passed case List: " + "\n"); - sb.append(passedDescriptionList.toString()); - sb.append("------------------------------------------------------------------------------\n"); - sb.append("Failed list: " + "\n"); - //sb.append("Failed case List: " + "\n"); - sb.append(failedDescriptionList.toString()); - sb.append("------------------------------------------------------------------------------\n"); - sb.append("Skipped list: " + "\n"); - //sb.append("Skipped case List: " + "\n"); - sb.append(skippedDescriptionList.toString()); - sb.append("----------------------------------------------------------------\n"); - - String res = sb.toString(); - try { - Files.write((Paths.get(reportPath)), res.getBytes("utf-8"), StandardOpenOption.APPEND); - } catch (IOException e) { - e.printStackTrace(); - } - - } - - /** - * calculate transaction num and transaction type After DailyBuild. - */ - public List> calculateAfterDailyBuild() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - endBlockNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - System.out.println("-----startnum :" + startBlockNum + "-----endnum:" + endBlockNum); - List listTrans; - List listContract; - Protocol.Block block; - int transNum; - int contractNum; - String contractType; - for (long i = startBlockNum; i < endBlockNum; i++) { - block = PublicMethed.getBlock(i, blockingStubFull); - listTrans = block.getTransactionsList(); - transNum = block.getTransactionsCount(); - totalTransactionNum += transNum; - for (int j = 0; j < transNum; j++) { - listContract = listTrans.get(j).getRawData().getContractList(); - contractNum = listContract.size(); - for (int k = 0; k < contractNum; k++) { - contractType = listContract.get(k).getType().toString(); - transactionType.put(contractType, transactionType.getOrDefault(contractType, 0) + 1); - } - } - } - try { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - - List> list = new ArrayList<>(transactionType.entrySet()); - Collections.sort(list, new Comparator>() { - @Override - public int compare(Map.Entry o1, Map.Entry o2) { - return (o2.getValue()).compareTo(o1.getValue()); - } - }); - return list; - } - -} - diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/FileUtil.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/FileUtil.java deleted file mode 100644 index 03268fa8b9e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/FileUtil.java +++ /dev/null @@ -1,142 +0,0 @@ -package stest.tron.wallet.common.client.utils; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.file.FileVisitResult; -import java.nio.file.FileVisitor; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.List; - -public class FileUtil { - - /** - * constructor. - */ - - public static List recursiveList(String path) throws IOException { - - final List files = new ArrayList<>(); - - Files.walkFileTree(Paths.get(path), new FileVisitor() { - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { - files.add(file.toString()); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFileFailed(Path file, IOException exc) { - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) { - return FileVisitResult.CONTINUE; - } - }); - - return files; - } - - /** - * constructor. - */ - - public static boolean recursiveDelete(String fileName) { - File file = new File(fileName); - if (file.exists()) { - //check if the file is a directory - if (file.isDirectory()) { - if ((file.list()).length > 0) { - for (String s : file.list()) { - //call deletion of file individually - recursiveDelete(fileName + System.getProperty("file.separator") + s); - } - } - } - - file.setWritable(true); - boolean result = file.delete(); - return result; - } else { - return false; - } - } - - /** - * constructor. - */ - - public static void saveData(String filePath, byte[] data) { - FileOutputStream fos = null; - try { - File file = new File(filePath); - file.createNewFile(); - fos = new FileOutputStream(file); - fos.write(data); - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (fos != null) { - try { - fos.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - } - - /** - * constructor. - */ - - public static byte[] readData(String filePath) { - FileInputStream fi = null; - try { - File file = new File(filePath); - long fileSize = file.length(); - if (fileSize > Integer.MAX_VALUE) { - System.out.println("file too big..."); - return null; - } - fi = new FileInputStream(file); - byte[] buffer = new byte[(int) fileSize]; - int offset = 0; - int numRead; - while (offset < buffer.length - && (numRead = fi.read(buffer, offset, buffer.length - offset)) >= 0) { - offset += numRead; - } - if (offset != buffer.length) { - return null; - } - return buffer; - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (fi != null) { - try { - fi.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - return null; - } -} diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/JsonRpcBase.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/JsonRpcBase.java deleted file mode 100644 index 203d6204933..00000000000 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/JsonRpcBase.java +++ /dev/null @@ -1,405 +0,0 @@ -package stest.tron.wallet.common.client.utils; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import io.grpc.Status; -import io.netty.util.internal.StringUtil; - -import java.math.BigInteger; -import java.util.HashMap; -import java.util.Optional; -// import java.util.*; - -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpPost; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.BytesMessage; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.GrpcAPI.ShieldedTRC20Parameters; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.Commons; -import org.tron.core.Wallet; -import org.tron.core.exception.ZksnarkException; -import org.tron.core.services.http.Util; -import org.tron.core.zen.address.DiversifierT; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.ShieldContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; - -@Slf4j -public class JsonRpcBase { - - public final String foundationAccountKey = - Configuration.getByPath("testng.conf").getString("foundationAccount.key1"); - public final byte[] foundationAccountAddress = PublicMethed.getFinalAddress(foundationAccountKey); - - public static final String jsonRpcOwnerKey = - Configuration.getByPath("testng.conf").getString("defaultParameter.jsonRpcOwnerKey"); - public static final byte[] jsonRpcOwnerAddress = PublicMethed.getFinalAddress(jsonRpcOwnerKey); - public static final String jsonRpcOwnerAddressString = - PublicMethed.getAddressString(jsonRpcOwnerKey); - public static String jsonRpcNode = - Configuration.getByPath("testng.conf").getStringList("jsonRpcNode.ip.list").get(0); - public static String jsonRpcNodeForSolidity = - Configuration.getByPath("testng.conf").getStringList("jsonRpcNode.ip.list").get(1); - public static String httpFullNode = - Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list").get(0); - public static String httpsolidityNode = - Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list").get(3); - public static String ethHttpsNode = - Configuration.getByPath("testng.conf").getStringList("ethHttpsNode.host.list").get(0); - - public ManagedChannel channelFull = null; - public WalletGrpc.WalletBlockingStub blockingStubFull = null; - public ManagedChannel channelSolidity = null; - public ManagedChannel channelPbft = null; - public static String data = null; - public String paramString = null; - public WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - public WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPbft = null; - public String fullnode = - Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list").get(0); - - public static long maxFeeLimit = - Configuration.getByPath("testng.conf").getLong("defaultParameter.maxFeeLimit"); - public static String trc20AddressByteString; - public static String trc20AddressHex; - public static String contractAddressFrom58; - public static String contractTrc20AddressFrom58; - public static String contractAddressFromHex; - public static ByteString shieldAddressByteString; - public static byte[] shieldAddressByte; - public static String shieldAddress; - public static String deployTrc20Txid; - public static String deployShieldTxid; - public static String mint = "mint(uint256,bytes32[9],bytes32[2],bytes32[21])"; - public static String transfer = - "transfer(bytes32[10][],bytes32[2][],bytes32[9][],bytes32[2],bytes32[21][])"; - public static String burn = - "burn(bytes32[10],bytes32[2],uint256,bytes32[2],address," - + "bytes32[3],bytes32[9][],bytes32[21][])"; - public Wallet wallet = new Wallet(); - static HttpResponse response; - static HttpPost httppost; - static JSONObject responseContent; - public static Integer scalingFactorLogarithm = 0; - public static Long totalSupply = 1000000000000L; - public static String name = "jsonrpc-test"; - public static String jsonRpcAssetId; - public static Integer blockNum; - public static Integer blockNumForTrc20; - public static String blockNumHex; - public static String blockId; - public static String txid; - public static String trc20Txid; - - /** constructor. */ - @BeforeSuite(enabled = true, description = "Deploy json rpc test case resource") - public void deployJsonRpcUseResource() throws Exception { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - Assert.assertTrue( - PublicMethed.sendcoin( - jsonRpcOwnerAddress, - 2048000000L, - foundationAccountAddress, - foundationAccountKey, - blockingStubFull)); - if (PublicMethed.queryAccount(jsonRpcOwnerAddress, blockingStubFull).getAssetV2Count() == 0L) { - Assert.assertTrue( - PublicMethed.sendcoin( - jsonRpcOwnerAddress, - 2048000000L, - foundationAccountAddress, - foundationAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // Create a new Asset Issue - Assert.assertTrue( - PublicMethed.createAssetIssue( - jsonRpcOwnerAddress, - name, - totalSupply, - 1, - 1, - System.currentTimeMillis() + 5000, - System.currentTimeMillis() + 1000000000, - 1, - "description", - "urlurlurl", - 2000L, - 2000L, - 1L, - 1L, - jsonRpcOwnerKey, - blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - response = HttpMethed.getAccount(httpFullNode, jsonRpcOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - jsonRpcAssetId = responseContent.getString("asset_issued_ID"); - - deployContract(); - triggerContract(); - deployTrc20Contract(); - } - - /** constructor. */ - public void deployContract() throws Exception { - final Long beforeTokenBalance = - PublicMethed.getAssetBalanceByAssetId( - ByteString.copyFromUtf8(jsonRpcAssetId), jsonRpcOwnerKey, blockingStubFull); - - JsonObject param = new JsonObject(); - param.addProperty("from", ByteArray.toHexString(jsonRpcOwnerAddress)); - param.addProperty("name", "transferTokenContract"); - param.addProperty("gas", "0x245498"); - String filePath = "./src/test/resources/soliditycode/contractTrcToken001.sol"; - String contractName = "tokenTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - System.out.println("CODE:" + code); - String abi = retMap.get("abI").toString(); - System.out.println("abi:" + abi); - - param.addProperty("abi", abi); - param.addProperty("data", code); - param.addProperty("consumeUserResourcePercent", 100); - param.addProperty("originEnergyLimit", 11111111111111L); - param.addProperty("value", "0x1f4"); - param.addProperty("tokenId", Long.valueOf(jsonRpcAssetId)); - param.addProperty("tokenValue", 1); - JsonArray params = new JsonArray(); - params.add(param); - JsonObject requestBody = getJsonRpcBody("buildTransaction", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String transactionString = responseContent.getJSONObject("result").getString("transaction"); - String transactionSignString = - HttpMethed.gettransactionsign(httpFullNode, transactionString, jsonRpcOwnerKey); - - responseContent = HttpMethed.parseStringContent(transactionString); - final String txid = responseContent.getString("txID"); - response = HttpMethed.broadcastTransaction(httpFullNode, transactionSignString); - org.junit.Assert.assertTrue(HttpMethed.verificationResult(response)); - - HttpMethed.waitToProduceOneBlock(httpFullNode); - Long afterTokenBalance = - PublicMethed.getAssetBalanceByAssetId( - ByteString.copyFromUtf8(jsonRpcAssetId), jsonRpcOwnerKey, blockingStubFull); - - org.junit.Assert.assertEquals(beforeTokenBalance - afterTokenBalance, 1L); - - response = HttpMethed.getTransactionById(httpFullNode, txid); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - org.junit.Assert.assertTrue(!responseContent.getString("contract_address").isEmpty()); - contractAddressFrom58 = responseContent.getString("contract_address"); - logger.info("contractAddressFrom58:" + contractAddressFrom58); - } - - /** constructor. */ - public void triggerContract() throws Exception { - final Long beforeTokenBalance = - PublicMethed.getAssetBalanceByAssetId( - ByteString.copyFromUtf8(jsonRpcAssetId), foundationAccountKey, blockingStubFull); - final Long beforeBalance = HttpMethed.getBalance(httpFullNode, jsonRpcOwnerAddress); - JsonObject param = new JsonObject(); - param.addProperty("from", "0x" + ByteArray.toHexString(jsonRpcOwnerAddress).substring(2)); - param.addProperty("to", "0x" + contractAddressFrom58); - - String addressParam = - "000000000000000000000000" - + ByteArray.toHexString(foundationAccountAddress).substring(2); // [0,3) - - String tokenIdParam = - "00000000000000000000000000000000000000000000000000000000000" - + Integer.toHexString(Integer.valueOf(jsonRpcAssetId)); - - String tokenValueParam = "0000000000000000000000000000000000000000000000000000000000000001"; - paramString = addressParam + tokenIdParam + tokenValueParam; - logger.info("paramString:" + paramString); - - String selector = "TransferTokenTo(address,trcToken,uint256)"; - // exit(1); - param.addProperty("data", "0x" + Util.parseMethod(selector, paramString)); - data = "0x" + Util.parseMethod(selector, paramString); - param.addProperty("gas", "0x245498"); - param.addProperty("value", "0x1389"); - param.addProperty("tokenId", Long.valueOf(jsonRpcAssetId)); - param.addProperty("tokenValue", 1); - JsonArray params = new JsonArray(); - params.add(param); - JsonObject requestBody = getJsonRpcBody("buildTransaction", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String transactionString = responseContent.getJSONObject("result").getString("transaction"); - logger.info("transactionString : " + transactionString); - String transactionSignString = - HttpMethed.gettransactionsign(httpFullNode, transactionString, jsonRpcOwnerKey); - logger.info("transactionSignString:" + transactionSignString); - responseContent = HttpMethed.parseStringContent(transactionString); - txid = responseContent.getString("txID"); - logger.info("triggerTxid:" + txid); - - response = HttpMethed.broadcastTransaction(httpFullNode, transactionSignString); - logger.info("response:" + response); - HttpMethed.verificationResult(response); - org.junit.Assert.assertTrue(HttpMethed.verificationResult(response)); - - HttpMethed.waitToProduceOneBlock(httpFullNode); - Long afterTokenBalance = - PublicMethed.getAssetBalanceByAssetId( - ByteString.copyFromUtf8(jsonRpcAssetId), foundationAccountKey, blockingStubFull); - Long afterBalance = HttpMethed.getBalance(httpFullNode, jsonRpcOwnerAddress); - - org.junit.Assert.assertEquals(beforeTokenBalance - afterTokenBalance, -1L); - org.junit.Assert.assertTrue(beforeBalance - afterBalance >= 5000); - - blockNum = - (int) (PublicMethed.getTransactionInfoById(txid, blockingStubFull).get().getBlockNumber()); - PublicMethed.waitProduceNextBlock(blockingStubFull); - response = HttpMethed.getBlockByNum(httpFullNode, blockNum); - org.junit.Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - blockId = responseContent.get("blockID").toString(); - } - - /** constructor. */ - public void deployTrc20Contract() throws InterruptedException { - String contractName = "shieldTrc20Token"; - - String abi = Configuration.getByPath("testng.conf").getString("abi.abi_shieldTrc20Token"); - String code = Configuration.getByPath("testng.conf").getString("code.code_shieldTrc20Token"); - String constructorStr = "constructor(uint256,string,string)"; - String data = totalSupply.toString() + "," + "\"TokenTRC20\"" + "," + "\"zen20\""; - logger.info("data:" + data); - deployTrc20Txid = - PublicMethed.deployContractWithConstantParame( - contractName, - abi, - code, - constructorStr, - data, - "", - maxFeeLimit, - 0L, - 100, - null, - jsonRpcOwnerKey, - jsonRpcOwnerAddress, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("deployTrc20Txid:" + deployTrc20Txid); - response = HttpMethed.getTransactionById(httpFullNode, deployTrc20Txid); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - org.junit.Assert.assertTrue(!responseContent.getString("contract_address").isEmpty()); - contractTrc20AddressFrom58 = responseContent.getString("contract_address"); - logger.info("contractTrc20AddressFrom58:" + contractTrc20AddressFrom58); - - // NewFilterId = createNewFilterId(); - - Optional infoById = - PublicMethed.getTransactionInfoById(deployTrc20Txid, blockingStubFull); - - trc20AddressHex = ByteArray.toHexString(infoById.get().getContractAddress().toByteArray()); - byte[] trc20Address = infoById.get().getContractAddress().toByteArray(); - - String selector = "transfer(address,uint256)"; - String addressParam = - "000000000000000000000000" - + ByteArray.toHexString(foundationAccountAddress).substring(2); // [0,3) - String transferValueParam = "0000000000000000000000000000000000000000000000000000000000000001"; - String paramString = addressParam + transferValueParam; - trc20Txid = - PublicMethed.triggerContract( - trc20Address, - selector, - paramString, - true, - 0, - maxFeeLimit, - "0", - 0, - jsonRpcOwnerAddress, - jsonRpcOwnerKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - blockNumForTrc20 = - (int) - (PublicMethed.getTransactionInfoById(trc20Txid, blockingStubFull) - .get() - .getBlockNumber()); - } - - /** constructor. */ - public static HttpResponse getEthHttps(String ethHttpsNode, JsonObject jsonRpcObject) { - try { - String requestUrl = "https://" + ethHttpsNode + "/v3/dfb752dd45204b8daae74249f4653584"; - response = HttpMethed.createConnect(requestUrl, jsonRpcObject); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - /** constructor. */ - public static HttpResponse getJsonRpc(String jsonRpcNode, JsonObject jsonRpcObject) { - try { - String requestUrl = "http://" + jsonRpcNode + "/jsonrpc"; - response = HttpMethed.createConnect(requestUrl, jsonRpcObject); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - /** constructor. */ - public static JsonObject getJsonRpcBody(String method) { - return getJsonRpcBody(method, new JsonArray(), 1); - } - - /** constructor. */ - public static JsonObject getJsonRpcBody(String method, JsonArray params) { - return getJsonRpcBody(method, params, 1); - } - - /** constructor. */ - public static JsonObject getJsonRpcBody(String method, JsonArray params, Integer id) { - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("jsonrpc", "2.0"); - jsonObject.addProperty("method", method); - jsonObject.add("params", params); - jsonObject.addProperty("id", id); - - return jsonObject; - } -} diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/PublicMethed.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/PublicMethed.java deleted file mode 100644 index e528c647545..00000000000 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/PublicMethed.java +++ /dev/null @@ -1,7091 +0,0 @@ -package stest.tron.wallet.common.client.utils; - -import static org.tron.common.crypto.Hash.sha3; -import static org.tron.common.crypto.Hash.sha3omit12; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.google.common.primitives.Longs; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.google.protobuf.Any; -import com.google.protobuf.ByteString; -import io.netty.util.internal.StringUtil; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.math.BigInteger; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.Assert; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AccountNetMessage; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.AssetIssueList; -import org.tron.api.GrpcAPI.BlockExtention; -import org.tron.api.GrpcAPI.BytesMessage; -import org.tron.api.GrpcAPI.DecryptNotes; -import org.tron.api.GrpcAPI.DecryptNotes.NoteTx; -import org.tron.api.GrpcAPI.DecryptNotesMarked; -import org.tron.api.GrpcAPI.DelegatedResourceList; -import org.tron.api.GrpcAPI.DelegatedResourceMessage; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.ExchangeList; -import org.tron.api.GrpcAPI.IvkDecryptAndMarkParameters; -import org.tron.api.GrpcAPI.IvkDecryptParameters; -import org.tron.api.GrpcAPI.NfParameters; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.GrpcAPI.NoteParameters; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.OvkDecryptParameters; -import org.tron.api.GrpcAPI.PrivateParameters; -import org.tron.api.GrpcAPI.PrivateParametersWithoutAsk; -import org.tron.api.GrpcAPI.ReceiveNote; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.GrpcAPI.Return.response_code; -import org.tron.api.GrpcAPI.SpendAuthSigParameters; -import org.tron.api.GrpcAPI.SpendNote; -import org.tron.api.GrpcAPI.SpendResult; -import org.tron.api.GrpcAPI.TransactionApprovedList; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.GrpcAPI.TransactionInfoList; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletGrpc.WalletBlockingStub; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.crypto.ECKey.ECDSASignature; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.Commons; -import org.tron.core.Wallet; -import org.tron.core.capsule.BlockCapsule.BlockId; -import org.tron.core.zen.address.DiversifierT; -import org.tron.core.zen.address.ExpandedSpendingKey; -import org.tron.core.zen.address.FullViewingKey; -import org.tron.core.zen.address.IncomingViewingKey; -import org.tron.core.zen.address.PaymentAddress; -import org.tron.core.zen.address.SpendingKey; -import org.tron.keystore.WalletFile; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.DelegatedResourceAccountIndex; -import org.tron.protos.Protocol.Exchange; -import org.tron.protos.Protocol.Key; -import org.tron.protos.Protocol.Permission; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.Protocol.Transaction.Result; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.AccountContract.AccountCreateContract; -import org.tron.protos.contract.AccountContract.AccountPermissionUpdateContract; -import org.tron.protos.contract.AccountContract.AccountUpdateContract; -import org.tron.protos.contract.AccountContract.SetAccountIdContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.ParticipateAssetIssueContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.UnfreezeAssetContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.UpdateAssetContract; -import org.tron.protos.contract.BalanceContract; -import org.tron.protos.contract.BalanceContract.FreezeBalanceContract; -import org.tron.protos.contract.BalanceContract.TransferContract; -import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; -import org.tron.protos.contract.ExchangeContract.ExchangeCreateContract; -import org.tron.protos.contract.ExchangeContract.ExchangeInjectContract; -import org.tron.protos.contract.ExchangeContract.ExchangeTransactionContract; -import org.tron.protos.contract.ExchangeContract.ExchangeWithdrawContract; -import org.tron.protos.contract.MarketContract; -import org.tron.protos.contract.ProposalContract.ProposalApproveContract; -import org.tron.protos.contract.ProposalContract.ProposalCreateContract; -import org.tron.protos.contract.ProposalContract.ProposalDeleteContract; -import org.tron.protos.contract.ShieldContract.IncrementalMerkleVoucherInfo; -import org.tron.protos.contract.ShieldContract.OutputPoint; -import org.tron.protos.contract.ShieldContract.OutputPointInfo; -import org.tron.protos.contract.ShieldContract.ShieldedTransferContract; -import org.tron.protos.contract.ShieldContract.SpendDescription; -import org.tron.protos.contract.SmartContractOuterClass.ClearABIContract; -import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; -import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract.Builder; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract.ABI; -import org.tron.protos.contract.SmartContractOuterClass.SmartContractDataWrapper; -import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; -import org.tron.protos.contract.SmartContractOuterClass.UpdateEnergyLimitContract; -import org.tron.protos.contract.SmartContractOuterClass.UpdateSettingContract; -import org.tron.protos.contract.StorageContract.BuyStorageContract; -import org.tron.protos.contract.StorageContract.SellStorageContract; -import org.tron.protos.contract.StorageContract.UpdateBrokerageContract; -import org.tron.protos.contract.WitnessContract.VoteWitnessContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; - -public class PublicMethed { - - // Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - private static final String FilePath = "Wallet"; - private static final Logger logger = LoggerFactory.getLogger("TestLogger"); - // private WalletGrpc.WalletBlockingStub blockingStubFull = null; - // private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - public static Map utxoMapNote = new ConcurrentHashMap(); - public static List spendUtxoList = new ArrayList<>(); - private static List walletFile = new ArrayList<>(); - private static ShieldWrapper shieldWrapper = new ShieldWrapper(); - Wallet wallet = new Wallet(); - public static volatile Integer witnessNum; - - /** constructor. */ - public static Integer getWitnessNum(WalletGrpc.WalletBlockingStub blockingStubFull) { - if (null == witnessNum) { - witnessNum = PublicMethed.listWitnesses(blockingStubFull).get().getWitnessesList().size(); - } - - return witnessNum; - } - - /** constructor. */ - public static String createAssetIssueGetTxid( - byte[] address, - String name, - String abbreviation, - Long totalSupply, - Integer trxNum, - Integer icoNum, - Long startTime, - Long endTime, - Integer voteScore, - String description, - String url, - Long freeAssetNetLimit, - Long publicFreeAssetNetLimit, - Long fronzenAmount, - Long frozenDay, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - try { - AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setAbbr(ByteString.copyFrom(abbreviation.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - builder.setFreeAssetNetLimit(freeAssetNetLimit); - builder.setPublicFreeAssetNetLimit(publicFreeAssetNetLimit); - AssetIssueContract.FrozenSupply.Builder frozenBuilder = - AssetIssueContract.FrozenSupply.newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - builder.addFrozenSupply(0, frozenBuilder); - - Protocol.Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return null; - } - transaction = signTransaction(ecKey, transaction); - - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - - return ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray())); - } catch (Exception ex) { - ex.printStackTrace(); - return null; - } - } - - /** constructor. */ - public static Boolean createAssetIssue( - byte[] address, - String name, - Long totalSupply, - Integer trxNum, - Integer icoNum, - Long startTime, - Long endTime, - Integer voteScore, - String description, - String url, - Long freeAssetNetLimit, - Long publicFreeAssetNetLimit, - Long fronzenAmount, - Long frozenDay, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - try { - AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - builder.setFreeAssetNetLimit(freeAssetNetLimit); - builder.setPublicFreeAssetNetLimit(publicFreeAssetNetLimit); - AssetIssueContract.FrozenSupply.Builder frozenBuilder = - AssetIssueContract.FrozenSupply.newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - builder.addFrozenSupply(0, frozenBuilder); - - Protocol.Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - - return response.getResult(); - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - /** constructor. */ - public static Boolean createAssetIssue( - byte[] address, - String name, - String abbreviation, - Long totalSupply, - Integer trxNum, - Integer icoNum, - Long startTime, - Long endTime, - Integer voteScore, - String description, - String url, - Long freeAssetNetLimit, - Long publicFreeAssetNetLimit, - Long fronzenAmount, - Long frozenDay, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - try { - AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setAbbr(ByteString.copyFrom(abbreviation.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - builder.setFreeAssetNetLimit(freeAssetNetLimit); - builder.setPublicFreeAssetNetLimit(publicFreeAssetNetLimit); - AssetIssueContract.FrozenSupply.Builder frozenBuilder = - AssetIssueContract.FrozenSupply.newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - builder.addFrozenSupply(0, frozenBuilder); - - Protocol.Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - - return response.getResult(); - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - /** constructor. */ - public static Boolean createAssetIssue( - byte[] address, - String name, - Long totalSupply, - Integer trxNum, - Integer icoNum, - int precision, - Long startTime, - Long endTime, - Integer voteScore, - String description, - String url, - Long freeAssetNetLimit, - Long publicFreeAssetNetLimit, - Long fronzenAmount, - Long frozenDay, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - try { - AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setPrecision(precision); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - builder.setFreeAssetNetLimit(freeAssetNetLimit); - builder.setPublicFreeAssetNetLimit(publicFreeAssetNetLimit); - AssetIssueContract.FrozenSupply.Builder frozenBuilder = - AssetIssueContract.FrozenSupply.newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - builder.addFrozenSupply(0, frozenBuilder); - - Protocol.Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - - return response.getResult(); - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - /** constructor. */ - public static Return createAssetIssue2( - byte[] address, - String name, - Long totalSupply, - Integer trxNum, - Integer icoNum, - Long startTime, - Long endTime, - Integer voteScore, - String description, - String url, - Long freeAssetNetLimit, - Long publicFreeAssetNetLimit, - Long fronzenAmount, - Long frozenDay, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - // Protocol.Account search = queryAccount(ecKey, blockingStubFull); - try { - AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - builder.setFreeAssetNetLimit(freeAssetNetLimit); - builder.setPublicFreeAssetNetLimit(publicFreeAssetNetLimit); - // builder.setPublicFreeAssetNetUsage(); - // builder.setPublicLatestFreeNetTime(); - AssetIssueContract.FrozenSupply.Builder frozenBuilder = - AssetIssueContract.FrozenSupply.newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - builder.addFrozenSupply(0, frozenBuilder); - - TransactionExtention transactionExtention = - blockingStubFull.createAssetIssue2(builder.build()); - - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(ecKey, transaction); - - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - if (response.getResult() == false) { - return response; - } else { - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - return ret; - } catch (Exception ex) { - ex.printStackTrace(); - // return false; - return Return.getDefaultInstance(); - } - } - - /** constructor. */ - public static Account queryAccountByAddress( - byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** constructor. */ - public static Account queryAccount( - byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** constructor. */ - public static Protocol.Account queryAccount( - String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - byte[] address; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); // 04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - /** constructor. */ - public static Account queryAccount( - byte[] address, WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** constructor. */ - public static Account getAccountById( - String accountId, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString bsAccountId = ByteString.copyFromUtf8(accountId); - Account request = Account.newBuilder().setAccountId(bsAccountId).build(); - return blockingStubFull.getAccountById(request); - } - - /** constructor. */ - public static Account getAccountByIdFromSolidity( - String accountId, WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString bsAccountId = ByteString.copyFromUtf8(accountId); - Account request = Account.newBuilder().setAccountId(bsAccountId).build(); - return blockingStubFull.getAccountById(request); - } - - /** constructor. */ - public static String loadPubKey() { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - /** constructor. */ - public static byte[] getAddress(ECKey ecKey) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - - return ecKey.getAddress(); - } - - /** constructor. */ - public static Protocol.Account grpcQueryAccount( - byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString addressBs = ByteString.copyFrom(address); - Protocol.Account request = Protocol.Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** constructor. */ - public static Protocol.Block getBlock( - long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - GrpcAPI.NumberMessage.Builder builder = GrpcAPI.NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - } - - /** constructor. */ - public static BlockExtention getBlock2(long blockNum, WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - GrpcAPI.NumberMessage.Builder builder = GrpcAPI.NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum2(builder.build()); - } - - /** constructor. */ - public static Protocol.Transaction signTransaction( - ECKey ecKey, Protocol.Transaction transaction) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - if (ecKey == null || ecKey.getPrivKey() == null) { - // logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - logger.info( - "Txid in sign is " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - return TransactionUtils.sign(transaction, ecKey); - } - - /** constructor. */ - public static Protocol.Transaction signTransactionForShield( - ECKey ecKey, Protocol.Transaction transaction) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - if (ecKey == null || ecKey.getPrivKey() == null) { - // logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - logger.info( - "Txid in sign is " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - return TransactionUtils.sign(transaction, ecKey); - } - - /** constructor. */ - public static boolean participateAssetIssue( - byte[] to, - byte[] assertName, - long amount, - byte[] from, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - ParticipateAssetIssueContract.Builder builder = ParticipateAssetIssueContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(from); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - ParticipateAssetIssueContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.participateAssetIssue(contract); - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - /** constructor. */ - public static Return participateAssetIssue2( - byte[] to, - byte[] assertName, - long amount, - byte[] from, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - ParticipateAssetIssueContract.Builder builder = ParticipateAssetIssueContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(from); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - ParticipateAssetIssueContract contract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.participateAssetIssue2(contract); - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - // Protocol.Transaction transaction = blockingStubFull.participateAssetIssue(contract); - - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - if (response.getResult() == false) { - return response; - } else { - return ret; - } - } - - /** constructor. */ - public static Boolean freezeBalance( - byte[] addRess, - long freezeBalance, - long freezeDuration, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - // String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - Protocol.Block currentBlock = - blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - final Long beforeBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Protocol.Account beforeFronzen = queryAccount(priKey, blockingStubFull); - Long beforeFrozenBalance = 0L; - // Long beforeBandwidth = beforeFronzen.getBandwidth(); - if (beforeFronzen.getFrozenCount() != 0) { - beforeFrozenBalance = beforeFronzen.getFrozen(0).getFrozenBalance(); - // beforeBandwidth = beforeFronzen.getBandwidth(); - // logger.info(Long.toString(beforeFronzen.getBandwidth())); - logger.info(Long.toString(beforeFronzen.getFrozen(0).getFrozenBalance())); - } - - FreezeBalanceContract.Builder builder = FreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder - .setOwnerAddress(byteAddreess) - .setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration); - - FreezeBalanceContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction = null"); - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - - return response.getResult(); - /* Long afterBlockNum = 0L; - - while (afterBlockNum < beforeBlockNum) { - Protocol.Block currentBlock1 = blockingStubFull.getNowBlock(GrpcAPI - .EmptyMessage.newBuilder().build()); - afterBlockNum = currentBlock1.getBlockHeader().getRawData().getNumber(); - } - - Protocol.Account afterFronzen = queryAccount(priKey, blockingStubFull); - Long afterFrozenBalance = afterFronzen.getFrozen(0).getFrozenBalance(); - logger.info(Long.toString(afterFronzen.getFrozen(0).getFrozenBalance())); - logger.info("beforefronen" + beforeFrozenBalance.toString() + " afterfronzen" - + afterFrozenBalance.toString()); - Assert.assertTrue(afterFrozenBalance - beforeFrozenBalance == freezeBalance);*/ - } - - /** constructor. */ - public static Return freezeBalance2( - byte[] addRess, - long freezeBalance, - long freezeDuration, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - // String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - Protocol.Block currentBlock = - blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - final Long beforeBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Protocol.Account beforeFronzen = queryAccount(priKey, blockingStubFull); - Long beforeFrozenBalance = 0L; - // Long beforeBandwidth = beforeFronzen.getBandwidth(); - if (beforeFronzen.getFrozenCount() != 0) { - beforeFrozenBalance = beforeFronzen.getFrozen(0).getFrozenBalance(); - // beforeBandwidth = beforeFronzen.getBandwidth(); - // logger.info(Long.toString(beforeFronzen.getBandwidth())); - logger.info(Long.toString(beforeFronzen.getFrozen(0).getFrozenBalance())); - } - - FreezeBalanceContract.Builder builder = FreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder - .setOwnerAddress(byteAddreess) - .setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration); - - FreezeBalanceContract contract = builder.build(); - - GrpcAPI.TransactionExtention transactionExtention = blockingStubFull.freezeBalance2(contract); - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - - if (response.getResult() == false) { - return response; - } - - Long afterBlockNum = 0L; - - while (afterBlockNum < beforeBlockNum) { - Protocol.Block currentBlock1 = - blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - afterBlockNum = currentBlock1.getBlockHeader().getRawData().getNumber(); - } - - Protocol.Account afterFronzen = queryAccount(priKey, blockingStubFull); - Long afterFrozenBalance = afterFronzen.getFrozen(0).getFrozenBalance(); - logger.info(Long.toString(afterFronzen.getFrozen(0).getFrozenBalance())); - logger.info( - "beforefronen" - + beforeFrozenBalance.toString() - + " afterfronzen" - + afterFrozenBalance.toString()); - Assert.assertTrue(afterFrozenBalance - beforeFrozenBalance == freezeBalance); - return ret; - } - - /** constructor. */ - public static Boolean unFreezeBalance( - byte[] address, - String priKey, - int resourceCode, - byte[] receiverAddress, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - UnfreezeBalanceContract.Builder builder = UnfreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - builder.setOwnerAddress(byteAddreess).setResourceValue(resourceCode); - if (receiverAddress != null) { - ByteString receiverAddressBytes = ByteString.copyFrom(receiverAddress); - builder.setReceiverAddress(receiverAddressBytes); - } - - UnfreezeBalanceContract contract = builder.build(); - Transaction transaction = blockingStubFull.unfreezeBalance(contract); - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - - return response.getResult(); - } - - /** constructor. */ - public static Boolean sendcoin( - byte[] to, - long amount, - byte[] owner, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - // String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - Integer times = 0; - while (times++ <= 2) { - - TransferContract.Builder builder = TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createTransaction(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction ==null"); - continue; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - return false; - } - - /** constructor. */ - public static String sendcoinGetTransactionHex( - byte[] to, - long amount, - byte[] owner, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - Integer times = 0; - TransferContract.Builder builder = TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createTransaction(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction ==null"); - return null; - } - transaction = signTransaction(ecKey, transaction); - logger.info( - "HEX transaction is : " - + "transaction hex string is " - + ByteArray.toHexString(transaction.toByteArray())); - return ByteArray.toHexString(transaction.toByteArray()); - } - - /** constructor. */ - public static Boolean cancelDeferredTransactionById( - String txid, byte[] owner, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - /*Contract.CancelDeferredTransactionContract.Builder builder = Contract - .CancelDeferredTransactionContract.newBuilder(); - builder.setTransactionId(ByteString.copyFrom(ByteArray.fromHexString(txid))); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - - Contract.CancelDeferredTransactionContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull - .createCancelDeferredTransactionContract(contract); - - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Cancel transaction before sign txid = " + ByteArray.toHexString( - transactionExtention.getTxid().toByteArray())); - - transaction = signTransaction(ecKey, transaction); - System.out.println( - "Cancel transaction txid = " + ByteArray.toHexString(transactionExtention - .getTxid().toByteArray())); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult();*/ - return null; - } - - - - /** constructor. */ - public static Boolean sendcoinDelayed( - byte[] to, - long amount, - long delaySeconds, - byte[] owner, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferContract.Builder builder = TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createTransaction(contract); - - // transaction = TransactionUtils.setDelaySeconds(transaction, delaySeconds); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction ==null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - logger.info( - "Txid is " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - - /** constructor. */ - public static String sendcoinDelayedGetTxid( - byte[] to, - long amount, - long delaySeconds, - byte[] owner, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferContract.Builder builder = TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createTransaction(contract); - - // transaction = TransactionUtils.setDelaySeconds(transaction, delaySeconds); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction ==null"); - return null; - } - transaction = signTransaction(ecKey, transaction); - logger.info( - "Txid is " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray())); - } - - - - - /** constructor. */ - public static Return sendcoin2( - byte[] to, - long amount, - byte[] owner, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - // Protocol.Account search = queryAccount(priKey, blockingStubFull); - - TransferContract.Builder builder = TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.createTransaction2(contract); - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - if (response.getResult() == false) { - // logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return response; - } - return ret; - } - - /** constructor. */ - public static String sendcoinGetTransactionId( - byte[] to, - long amount, - byte[] owner, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - // String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - // Protocol.Account search = queryAccount(priKey, blockingStubFull); - - TransferContract.Builder builder = TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createTransaction(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction ==null"); - return null; - } - // Test raw data - /* Protocol.Transaction.raw.Builder builder1 = transaction.getRawData().toBuilder(); - builder1.setData(ByteString.copyFromUtf8("12345678")); - Transaction.Builder builder2 = transaction.toBuilder(); - builder2.setRawData(builder1); - transaction = builder2.build();*/ - - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - if (response.getResult() == false) { - // logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return null; - } else { - return ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray())); - } - } - - /** constructor. */ - public static Optional getTransactionById( - String txId, WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubFull) { - ByteString bsTxid = ByteString.copyFrom(ByteArray.fromHexString(txId)); - BytesMessage request = BytesMessage.newBuilder().setValue(bsTxid).build(); - Transaction transaction = blockingStubFull.getTransactionById(request); - - return Optional.ofNullable(transaction); - } - - /** constructor. */ - public static Optional getTransactionById( - String txId, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString bsTxid = ByteString.copyFrom(ByteArray.fromHexString(txId)); - BytesMessage request = BytesMessage.newBuilder().setValue(bsTxid).build(); - Transaction transaction = blockingStubFull.getTransactionById(request); - return Optional.ofNullable(transaction); - } - - /** constructor. */ - public static Long getAssetBalanceByAssetId( - ByteString assetId, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - Account assetOwnerAccount = queryAccount(priKey, blockingStubFull); - Long assetOwnerAssetBalance = 0L; - for (String id : assetOwnerAccount.getAssetV2Map().keySet()) { - if (assetId.toStringUtf8().equalsIgnoreCase(id)) { - assetOwnerAssetBalance = assetOwnerAccount.getAssetV2Map().get(id); - } - } - logger.info("asset balance is " + assetOwnerAssetBalance); - return assetOwnerAssetBalance; - } - - /* - public static Optional getDeferredTransactionById(String txId, - WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString bsTxid = ByteString.copyFrom(ByteArray.fromHexString(txId)); - BytesMessage request = BytesMessage.newBuilder().setValue(bsTxid).build(); - DeferredTransaction transaction = blockingStubFull.getDeferredTransactionById(request); - if (Objects.isNull(transaction)) { - transaction = blockingStubFull.getDeferredTransactionById(request); - } - return Optional.ofNullable(transaction); - } - */ - - /** constructor. */ - public static Optional getTransactionByIdSolidity( - String txId, WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) { - ByteString bsTxid = ByteString.copyFrom(ByteArray.fromHexString(txId)); - BytesMessage request = BytesMessage.newBuilder().setValue(bsTxid).build(); - Transaction transaction = blockingStubSolidity.getTransactionById(request); - return Optional.ofNullable(transaction); - } - - /** constructor. */ - public static String printTransaction(Transaction transaction) { - String result = ""; - result += "hash: "; - result += "\n"; - result += - ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), transaction.toByteArray())); - result += "\n"; - result += "txid: "; - result += "\n"; - result += - ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray())); - result += "\n"; - - if (transaction.getRawData() != null) { - result += "raw_data: "; - result += "\n"; - result += "{"; - result += "\n"; - result += printTransactionRow(transaction.getRawData()); - result += "}"; - result += "\n"; - } - - return result; - } - - /** constructor. */ - public static long printTransactionRow(Transaction.raw raw) { - long timestamp = raw.getTimestamp(); - - return timestamp; - } - - /** constructor. */ - public static boolean updateAsset( - byte[] address, - byte[] description, - byte[] url, - long newLimit, - long newPublicLimit, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - UpdateAssetContract.Builder builder = UpdateAssetContract.newBuilder(); - ByteString basAddreess = ByteString.copyFrom(address); - builder.setDescription(ByteString.copyFrom(description)); - builder.setUrl(ByteString.copyFrom(url)); - builder.setNewLimit(newLimit); - builder.setNewPublicLimit(newPublicLimit); - builder.setOwnerAddress(basAddreess); - - UpdateAssetContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.updateAsset(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - /** constructor. */ - public static Return updateAsset2( - byte[] address, - byte[] description, - byte[] url, - long newLimit, - long newPublicLimit, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - UpdateAssetContract.Builder builder = UpdateAssetContract.newBuilder(); - ByteString basAddreess = ByteString.copyFrom(address); - builder.setDescription(ByteString.copyFrom(description)); - builder.setUrl(ByteString.copyFrom(url)); - builder.setNewLimit(newLimit); - builder.setNewPublicLimit(newPublicLimit); - builder.setOwnerAddress(basAddreess); - - UpdateAssetContract contract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.updateAsset2(contract); - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - if (response.getResult() == false) { - // logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return response; - } - return ret; - } - - /** constructor. */ - public static boolean transferAsset( - byte[] to, - byte[] assertName, - long amount, - byte[] address, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferAssetContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.transferAsset(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - if (transaction == null) { - logger.info("transaction == null"); - } else { - logger.info("transaction.getRawData().getContractCount() == 0"); - } - return false; - } - transaction = signTransaction(ecKey, transaction); - - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - /** constructor. */ - public static boolean updateAccount( - byte[] addressBytes, - byte[] accountNameBytes, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - AccountUpdateContract.Builder builder = AccountUpdateContract.newBuilder(); - ByteString basAddreess = ByteString.copyFrom(addressBytes); - ByteString bsAccountName = ByteString.copyFrom(accountNameBytes); - - builder.setAccountName(bsAccountName); - builder.setOwnerAddress(basAddreess); - - AccountUpdateContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.updateAccount(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("Please check!!! transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - /** constructor. */ - public static boolean waitSolidityNodeSynFullNodeData( - WalletGrpc.WalletBlockingStub blockingStubFull, - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Block solidityCurrentBlock = - blockingStubSolidity.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Integer wait = 0; - logger.info("Fullnode block num is " + currentBlock.getBlockHeader().getRawData().getNumber()); - - while (solidityCurrentBlock.getBlockHeader().getRawData().getNumber() - < currentBlock.getBlockHeader().getRawData().getNumber() + 1 - && wait - < ((getWitnessNum(blockingStubFull) >= 27) - ? 27 - : getWitnessNum(blockingStubFull) + 1)) { - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - logger.info( - "Soliditynode num is " + solidityCurrentBlock.getBlockHeader().getRawData().getNumber()); - solidityCurrentBlock = - blockingStubSolidity.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - if (wait == 24) { - logger.info("Didn't syn,skip to next case."); - return false; - } - wait++; - } - return true; - } - - /** constructor. */ - public static boolean waitProduceNextBlock(WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - final Long currentNum = currentBlock.getBlockHeader().getRawData().getNumber(); - - Block nextBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long nextNum = nextBlock.getBlockHeader().getRawData().getNumber(); - - Integer wait = 0; - logger.info("Block num is " + currentBlock.getBlockHeader().getRawData().getNumber()); - while (nextNum <= currentNum + 1 && wait <= 45) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - // logger.info("Wait to produce next block"); - nextBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - nextNum = nextBlock.getBlockHeader().getRawData().getNumber(); - if (wait == 45) { - logger.info("These 45 second didn't produce a block,please check."); - return false; - } - wait++; - } - logger.info("quit normally"); - return true; - } - - /** constructor. */ - public static AccountNetMessage getAccountNet( - byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccountNet(request); - } - - /* public static byte[] addPreFix(byte[] address) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - Config config = Configuration.getByPath("testng.conf"); - byte ADD_PRE_FIX_BYTE_MAINNET = (byte) 0x41; //41 + address - byte ADD_PRE_FIX_BYTE_TESTNET = (byte) 0xa0; //a0 + address - byte[] preFix = new byte[1]; - if (config.hasPath("net.type") && "mainnet".equalsIgnoreCase(config.getString("net.type"))) { - WalletClient.setAddressPreFixByte(ADD_PRE_FIX_BYTE_MAINNET); - preFix[0] = ADD_PRE_FIX_BYTE_MAINNET; - }else { - WalletClient.setAddressPreFixByte(ADD_PRE_FIX_BYTE_TESTNET); - preFix[0] = ADD_PRE_FIX_BYTE_TESTNET; - } - byte[] finalAddress = new byte[preFix.length+address.length]; - System.arraycopy(preFix, 0, finalAddress, 0, preFix.length); - System.arraycopy(address, 0, finalAddress, preFix.length, address.length); - return finalAddress; - - }*/ - - /** constructor. */ - public static byte[] getFinalAddress(String priKey) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - WalletClient walletClient; - walletClient = new WalletClient(priKey); - // walletClient.init(0); - return walletClient.getAddress(); - } - - /** constructor. */ - public static String createAccountGetTxid( - byte[] ownerAddress, - byte[] newAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - AccountCreateContract.Builder builder = AccountCreateContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setAccountAddress(ByteString.copyFrom(newAddress)); - AccountCreateContract contract = builder.build(); - Transaction transaction = blockingStubFull.createAccount(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - if (response.getResult() == false) { - return null; - } else { - // logger.info("brodacast succesfully"); - return ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray())); - } - } - - /** constructor. */ - public static boolean createAccount( - byte[] ownerAddress, - byte[] newAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - AccountCreateContract.Builder builder = AccountCreateContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setAccountAddress(ByteString.copyFrom(newAddress)); - AccountCreateContract contract = builder.build(); - Transaction transaction = blockingStubFull.createAccount(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - /** constructor. */ - public static Return createAccount2( - byte[] ownerAddress, - byte[] newAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - AccountCreateContract.Builder builder = AccountCreateContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setAccountAddress(ByteString.copyFrom(newAddress)); - AccountCreateContract contract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.createAccount2(contract); - - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - if (response.getResult() == false) { - // logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return response; - } - return ret; - } - - /** constructor. */ - public static boolean voteWitness( - byte[] ownerAddress, - String priKey, - HashMap witnessMap, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - VoteWitnessContract.Builder builder = VoteWitnessContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - for (byte[] address : witnessMap.keySet()) { - VoteWitnessContract.Vote.Builder voteBuilder = VoteWitnessContract.Vote.newBuilder(); - voteBuilder.setVoteAddress(ByteString.copyFrom(address)); - voteBuilder.setVoteCount(witnessMap.get(address)); - builder.addVotes(voteBuilder.build()); - } - - VoteWitnessContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.voteWitnessAccount2(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - - return response.getResult(); - } - - /** constructor. */ - public static boolean createProposal( - byte[] ownerAddress, - String priKey, - HashMap parametersMap, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - ProposalCreateContract.Builder builder = ProposalCreateContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.putAllParameters(parametersMap); - - ProposalCreateContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.proposalCreate(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - - return response.getResult(); - } - - /** constructor. */ - public static boolean approveProposal( - byte[] ownerAddress, - String priKey, - long id, - boolean isAddApproval, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - ProposalApproveContract.Builder builder = ProposalApproveContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setProposalId(id); - builder.setIsAddApproval(isAddApproval); - ProposalApproveContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.proposalApprove(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - /** constructor. */ - public static boolean deleteProposal( - byte[] ownerAddress, String priKey, long id, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - ProposalDeleteContract.Builder builder = ProposalDeleteContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setProposalId(id); - - ProposalDeleteContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.proposalDelete(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - /** constructor. */ - public static boolean printAddress(String key) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - logger.info(key); - logger.info(ByteArray.toHexString(getFinalAddress(key))); - logger.info(Base58.encode58Check(getFinalAddress(key))); - return true; - } - - /** constructor. */ - public static String getAddressString(String key) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - return Base58.encode58Check(getFinalAddress(key)); - } - - /** constructor. */ - public static ArrayList getAddressInfo(String key) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ArrayList accountList = new ArrayList(); - accountList.add(key); - accountList.add(ByteArray.toHexString(getFinalAddress(key))); - accountList.add(Base58.encode58Check(getFinalAddress(key))); - return accountList; - } - - /** constructor. */ - public static boolean setAccountId( - byte[] accountIdBytes, - byte[] ownerAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - SetAccountIdContract.Builder builder = SetAccountIdContract.newBuilder(); - ByteString bsAddress = ByteString.copyFrom(owner); - ByteString bsAccountId = ByteString.copyFrom(accountIdBytes); - builder.setAccountId(bsAccountId); - builder.setOwnerAddress(bsAddress); - SetAccountIdContract contract = builder.build(); - Transaction transaction = blockingStubFull.setAccountId(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - /** constructor. */ - public static Boolean freezeBalanceGetTronPower( - byte[] addRess, - long freezeBalance, - long freezeDuration, - int resourceCode, - ByteString receiverAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - return freezeBalanceForReceiver( - addRess, - freezeBalance, - freezeDuration, - resourceCode, - receiverAddress, - priKey, - blockingStubFull); - } - - /** constructor. */ - public static Boolean freezeBalanceGetEnergy( - byte[] addRess, - long freezeBalance, - long freezeDuration, - int resourceCode, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - FreezeBalanceContract.Builder builder = FreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder - .setOwnerAddress(byteAddreess) - .setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration) - .setResourceValue(resourceCode); - - FreezeBalanceContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction = null"); - return false; - } - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - /** constructor. */ - public static AccountResourceMessage getAccountResource( - byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccountResource(request); - } - - /** constructor. */ - public static boolean buyStorage( - long quantity, - byte[] address, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - BuyStorageContract.Builder builder = BuyStorageContract.newBuilder(); - ByteString byteAddress = ByteString.copyFrom(address); - builder.setOwnerAddress(byteAddress).setQuant(quantity); - BuyStorageContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.buyStorage(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - /** constructor. */ - public static boolean sellStorage( - long quantity, - byte[] address, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - SellStorageContract.Builder builder = SellStorageContract.newBuilder(); - ByteString byteAddress = ByteString.copyFrom(address); - builder.setOwnerAddress(byteAddress).setStorageBytes(quantity); - SellStorageContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.sellStorage(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - /** constructor. */ - public static byte[] deployContractFallbackReceive( - String contractName, - String abiString, - String code, - String data, - Long feeLimit, - long value, - long consumeUserResourcePercent, - long originEnergyLimit, - String tokenId, - long tokenValue, - String libraryAddress, - String priKey, - byte[] ownerAddress, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - SmartContract.ABI abi = jsonStr2Abi2(abiString); - if (abi == null) { - logger.error("abi is null"); - return null; - } - // byte[] codeBytes = Hex.decode(code); - SmartContract.Builder builder = SmartContract.newBuilder(); - builder.setName(contractName); - builder.setOriginAddress(ByteString.copyFrom(owner)); - builder.setAbi(abi); - builder.setConsumeUserResourcePercent(consumeUserResourcePercent); - builder.setOriginEnergyLimit(originEnergyLimit); - - if (value != 0) { - - builder.setCallValue(value); - } - - byte[] byteCode; - if (null != libraryAddress) { - byteCode = replaceLibraryAddress(code, libraryAddress); - } else { - byteCode = Hex.decode(code); - } - builder.setBytecode(ByteString.copyFrom(byteCode)); - - Builder contractBuilder = CreateSmartContract.newBuilder(); - contractBuilder.setOwnerAddress(ByteString.copyFrom(owner)); - contractBuilder.setCallTokenValue(tokenValue); - contractBuilder.setTokenId(Long.parseLong(tokenId)); - CreateSmartContract contractDeployContract = - contractBuilder.setNewContract(builder.build()).build(); - - TransactionExtention transactionExtention = - blockingStubFull.deployContract(contractDeployContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create trx failed!"); - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println( - "Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = - transactionExtention.getTransaction().getRawData().toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - - byte[] contractAddress = generateContractAddress(transactionExtention.getTransaction(), owner); - System.out.println( - "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - transaction = signTransaction(ecKey, transaction); - System.out.println( - "txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - contractAddress = generateContractAddress(transaction, owner); - System.out.println( - "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); - - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - if (response.getResult() == false) { - return null; - } else { - // logger.info("brodacast succesfully"); - return contractAddress; - } - } - - /** constructor. */ - public static byte[] deployContract( - String contractName, - String abiString, - String code, - String data, - Long feeLimit, - long value, - long consumeUserResourcePercent, - long originEnergyLimit, - String tokenId, - long tokenValue, - String libraryAddress, - String priKey, - byte[] ownerAddress, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - SmartContract.ABI abi = jsonStr2Abi(abiString); - if (abi == null) { - logger.error("abi is null"); - return null; - } - // byte[] codeBytes = Hex.decode(code); - SmartContract.Builder builder = SmartContract.newBuilder(); - builder.setName(contractName); - builder.setOriginAddress(ByteString.copyFrom(owner)); - builder.setAbi(abi); - builder.setConsumeUserResourcePercent(consumeUserResourcePercent); - builder.setOriginEnergyLimit(originEnergyLimit); - - if (value != 0) { - - builder.setCallValue(value); - } - - byte[] byteCode; - if (null != libraryAddress) { - byteCode = replaceLibraryAddress(code, libraryAddress); - } else { - byteCode = Hex.decode(code); - } - builder.setBytecode(ByteString.copyFrom(byteCode)); - - Builder contractBuilder = CreateSmartContract.newBuilder(); - contractBuilder.setOwnerAddress(ByteString.copyFrom(owner)); - contractBuilder.setCallTokenValue(tokenValue); - contractBuilder.setTokenId(Long.parseLong(tokenId)); - CreateSmartContract contractDeployContract = - contractBuilder.setNewContract(builder.build()).build(); - - TransactionExtention transactionExtention = - blockingStubFull.deployContract(contractDeployContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create trx failed!"); - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println( - "Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = - transactionExtention.getTransaction().getRawData().toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - - byte[] contractAddress = generateContractAddress(transactionExtention.getTransaction(), owner); - System.out.println( - "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - transaction = signTransaction(ecKey, transaction); - System.out.println( - "txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - contractAddress = generateContractAddress(transaction, owner); - System.out.println( - "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); - - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - if (response.getResult() == false) { - return null; - } else { - // logger.info("brodacast succesfully"); - return contractAddress; - } - } - - /** constructor. */ - public static byte[] deployContract( - String contractName, - String abiString, - String code, - String data, - Long feeLimit, - long value, - long consumeUserResourcePercent, - String libraryAddress, - String priKey, - byte[] ownerAddress, - WalletGrpc.WalletBlockingStub blockingStubFull) { - return deployContract( - contractName, - abiString, - code, - data, - feeLimit, - value, - consumeUserResourcePercent, - 1000L, - "0", - 0L, - libraryAddress, - priKey, - ownerAddress, - blockingStubFull); - } - - /** constructor. */ - public static byte[] deployContractFallback( - String contractName, - String abiString, - String code, - String data, - Long feeLimit, - long value, - long consumeUserResourcePercent, - String libraryAddress, - String priKey, - byte[] ownerAddress, - WalletGrpc.WalletBlockingStub blockingStubFull) { - return deployContractFallbackReceive( - contractName, - abiString, - code, - data, - feeLimit, - value, - consumeUserResourcePercent, - 1000L, - "0", - 0L, - libraryAddress, - priKey, - ownerAddress, - blockingStubFull); - } - - /** constructor. */ - public static byte[] deployContractForLibrary( - String contractName, - String abiString, - String code, - String data, - Long feeLimit, - long value, - long consumeUserResourcePercent, - String libraryAddress, - String priKey, - byte[] ownerAddress, - String compilerVersion, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - SmartContract.ABI abi = jsonStr2Abi(abiString); - if (abi == null) { - logger.error("abi is null"); - return null; - } - // byte[] codeBytes = Hex.decode(code); - SmartContract.Builder builder = SmartContract.newBuilder(); - builder.setName(contractName); - builder.setOriginAddress(ByteString.copyFrom(owner)); - builder.setAbi(abi); - builder.setConsumeUserResourcePercent(consumeUserResourcePercent); - builder.setOriginEnergyLimit(1000L); - - if (value != 0) { - - builder.setCallValue(value); - } - - byte[] byteCode; - if (null != libraryAddress) { - if (compilerVersion.equals("v5") || compilerVersion.equals("V5")) { - byteCode = replaceLibraryAddresscompilerVersion(code, libraryAddress, "v5"); - } else { - // old version - byteCode = replaceLibraryAddresscompilerVersion(code, libraryAddress, null); - } - - } else { - byteCode = Hex.decode(code); - } - builder.setBytecode(ByteString.copyFrom(byteCode)); - - Builder contractBuilder = CreateSmartContract.newBuilder(); - contractBuilder.setOwnerAddress(ByteString.copyFrom(owner)); - contractBuilder.setCallTokenValue(0); - contractBuilder.setTokenId(Long.parseLong("0")); - CreateSmartContract contractDeployContract = - contractBuilder.setNewContract(builder.build()).build(); - - TransactionExtention transactionExtention = - blockingStubFull.deployContract(contractDeployContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create trx failed!"); - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println( - "Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = - transactionExtention.getTransaction().getRawData().toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - - byte[] contractAddress = generateContractAddress(transactionExtention.getTransaction(), owner); - System.out.println( - "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - transaction = signTransaction(ecKey, transaction); - System.out.println( - "txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - contractAddress = generateContractAddress(transaction, owner); - System.out.println( - "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); - - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - if (response.getResult() == false) { - return null; - } else { - // logger.info("brodacast succesfully"); - return contractAddress; - } - } - - /** constructor. */ - public static String deployContractAndGetTransactionInfoById( - String contractName, - String abiString, - String code, - String data, - Long feeLimit, - long value, - long consumeUserResourcePercent, - String libraryAddress, - String priKey, - byte[] ownerAddress, - WalletGrpc.WalletBlockingStub blockingStubFull) { - return deployContractAndGetTransactionInfoById( - contractName, - abiString, - code, - data, - feeLimit, - value, - consumeUserResourcePercent, - 1000L, - "0", - 0L, - libraryAddress, - priKey, - ownerAddress, - blockingStubFull); - } - - /** constructor. */ - public static String deployContractAndGetTransactionInfoById( - String contractName, - String abiString, - String code, - String data, - Long feeLimit, - long value, - long consumeUserResourcePercent, - long originEnergyLimit, - String tokenId, - long tokenValue, - String libraryAddress, - String priKey, - byte[] ownerAddress, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - SmartContract.ABI abi = jsonStr2Abi(abiString); - if (abi == null) { - logger.error("abi is null"); - return null; - } - // byte[] codeBytes = Hex.decode(code); - SmartContract.Builder builder = SmartContract.newBuilder(); - builder.setName(contractName); - builder.setOriginAddress(ByteString.copyFrom(owner)); - builder.setAbi(abi); - builder.setConsumeUserResourcePercent(consumeUserResourcePercent); - builder.setOriginEnergyLimit(originEnergyLimit); - - if (value != 0) { - - builder.setCallValue(value); - } - - byte[] byteCode; - if (null != libraryAddress) { - byteCode = replaceLibraryAddress(code, libraryAddress); - } else { - byteCode = Hex.decode(code); - } - builder.setBytecode(ByteString.copyFrom(byteCode)); - - Builder contractBuilder = CreateSmartContract.newBuilder(); - contractBuilder.setOwnerAddress(ByteString.copyFrom(owner)); - contractBuilder.setCallTokenValue(tokenValue); - contractBuilder.setTokenId(Long.parseLong(tokenId)); - CreateSmartContract contractDeployContract = - contractBuilder.setNewContract(builder.build()).build(); - - TransactionExtention transactionExtention = - blockingStubFull.deployContract(contractDeployContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create trx failed!"); - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println( - "Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = - transactionExtention.getTransaction().getRawData().toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - transaction = signTransaction(ecKey, transaction); - System.out.println( - "txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - byte[] contractAddress = generateContractAddress(transaction, owner); - System.out.println( - "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - if (response.getResult() == false) { - return null; - } else { - // logger.info("brodacast succesfully"); - return ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray())); - } - } - - /** constructor. */ - public static SmartContract.ABI jsonStr2Abi(String jsonStr) { - if (jsonStr == null) { - return null; - } - - JsonParser jsonParser = new JsonParser(); - JsonElement jsonElementRoot = jsonParser.parse(jsonStr); - JsonArray jsonRoot = jsonElementRoot.getAsJsonArray(); - SmartContract.ABI.Builder abiBuilder = SmartContract.ABI.newBuilder(); - for (int index = 0; index < jsonRoot.size(); index++) { - JsonElement abiItem = jsonRoot.get(index); - boolean anonymous = - abiItem.getAsJsonObject().get("anonymous") != null - && abiItem.getAsJsonObject().get("anonymous").getAsBoolean(); - final boolean constant = - abiItem.getAsJsonObject().get("constant") != null - && abiItem.getAsJsonObject().get("constant").getAsBoolean(); - final String name = - abiItem.getAsJsonObject().get("name") != null - ? abiItem.getAsJsonObject().get("name").getAsString() - : null; - JsonArray inputs = - abiItem.getAsJsonObject().get("inputs") != null - ? abiItem.getAsJsonObject().get("inputs").getAsJsonArray() - : null; - final JsonArray outputs = - abiItem.getAsJsonObject().get("outputs") != null - ? abiItem.getAsJsonObject().get("outputs").getAsJsonArray() - : null; - String type = - abiItem.getAsJsonObject().get("type") != null - ? abiItem.getAsJsonObject().get("type").getAsString() - : null; - final boolean payable = - abiItem.getAsJsonObject().get("payable") != null - && abiItem.getAsJsonObject().get("payable").getAsBoolean(); - final String stateMutability = - abiItem.getAsJsonObject().get("stateMutability") != null - ? abiItem.getAsJsonObject().get("stateMutability").getAsString() - : null; - if (type == null) { - logger.error("No type!"); - return null; - } - if (!type.equalsIgnoreCase("fallback") && null == inputs) { - logger.error("No inputs!"); - return null; - } - - SmartContract.ABI.Entry.Builder entryBuilder = SmartContract.ABI.Entry.newBuilder(); - entryBuilder.setAnonymous(anonymous); - entryBuilder.setConstant(constant); - if (name != null) { - entryBuilder.setName(name); - } - - /* { inputs : optional } since fallback function not requires inputs*/ - if (inputs != null) { - for (int j = 0; j < inputs.size(); j++) { - JsonElement inputItem = inputs.get(j); - if (inputItem.getAsJsonObject().get("name") == null - || inputItem.getAsJsonObject().get("type") == null) { - logger.error("Input argument invalid due to no name or no type!"); - return null; - } - String inputName = inputItem.getAsJsonObject().get("name").getAsString(); - String inputType = inputItem.getAsJsonObject().get("type").getAsString(); - ABI.Entry.Param.Builder paramBuilder = SmartContract.ABI.Entry.Param.newBuilder(); - JsonElement indexed = inputItem.getAsJsonObject().get("indexed"); - - paramBuilder.setIndexed((indexed != null) && indexed.getAsBoolean()); - paramBuilder.setName(inputName); - paramBuilder.setType(inputType); - entryBuilder.addInputs(paramBuilder.build()); - } - } - - /* { outputs : optional } */ - if (outputs != null) { - for (int k = 0; k < outputs.size(); k++) { - JsonElement outputItem = outputs.get(k); - if (outputItem.getAsJsonObject().get("name") == null - || outputItem.getAsJsonObject().get("type") == null) { - logger.error("Output argument invalid due to no name or no type!"); - return null; - } - String outputName = outputItem.getAsJsonObject().get("name").getAsString(); - String outputType = outputItem.getAsJsonObject().get("type").getAsString(); - SmartContract.ABI.Entry.Param.Builder paramBuilder = - SmartContract.ABI.Entry.Param.newBuilder(); - JsonElement indexed = outputItem.getAsJsonObject().get("indexed"); - - paramBuilder.setIndexed((indexed != null) && indexed.getAsBoolean()); - paramBuilder.setName(outputName); - paramBuilder.setType(outputType); - entryBuilder.addOutputs(paramBuilder.build()); - } - } - - entryBuilder.setType(getEntryType(type)); - entryBuilder.setPayable(payable); - if (stateMutability != null) { - entryBuilder.setStateMutability(getStateMutability(stateMutability)); - } - - abiBuilder.addEntrys(entryBuilder.build()); - } - - return abiBuilder.build(); - } - - /** constructor. */ - public static SmartContract.ABI jsonStr2Abi2(String jsonStr) { - if (jsonStr == null) { - return null; - } - - JsonParser jsonParser = new JsonParser(); - JsonElement jsonElementRoot = jsonParser.parse(jsonStr); - JsonArray jsonRoot = jsonElementRoot.getAsJsonArray(); - SmartContract.ABI.Builder abiBuilder = SmartContract.ABI.newBuilder(); - for (int index = 0; index < jsonRoot.size(); index++) { - JsonElement abiItem = jsonRoot.get(index); - boolean anonymous = - abiItem.getAsJsonObject().get("anonymous") != null - && abiItem.getAsJsonObject().get("anonymous").getAsBoolean(); - final boolean constant = - abiItem.getAsJsonObject().get("constant") != null - && abiItem.getAsJsonObject().get("constant").getAsBoolean(); - final String name = - abiItem.getAsJsonObject().get("name") != null - ? abiItem.getAsJsonObject().get("name").getAsString() - : null; - JsonArray inputs = - abiItem.getAsJsonObject().get("inputs") != null - ? abiItem.getAsJsonObject().get("inputs").getAsJsonArray() - : null; - final JsonArray outputs = - abiItem.getAsJsonObject().get("outputs") != null - ? abiItem.getAsJsonObject().get("outputs").getAsJsonArray() - : null; - String type = - abiItem.getAsJsonObject().get("type") != null - ? abiItem.getAsJsonObject().get("type").getAsString() - : null; - final boolean payable = - abiItem.getAsJsonObject().get("payable") != null - && abiItem.getAsJsonObject().get("payable").getAsBoolean(); - final String stateMutability = - abiItem.getAsJsonObject().get("stateMutability") != null - ? abiItem.getAsJsonObject().get("stateMutability").getAsString() - : null; - if (type == null) { - logger.error("No type!"); - return null; - } - if (!type.equalsIgnoreCase("fallback") - && !type.equalsIgnoreCase("receive") - && null == inputs) { - logger.error("No inputs!"); - return null; - } - - SmartContract.ABI.Entry.Builder entryBuilder = SmartContract.ABI.Entry.newBuilder(); - entryBuilder.setAnonymous(anonymous); - entryBuilder.setConstant(constant); - if (name != null) { - entryBuilder.setName(name); - } - - /* { inputs : optional } since fallback function not requires inputs*/ - if (inputs != null) { - for (int j = 0; j < inputs.size(); j++) { - JsonElement inputItem = inputs.get(j); - if (inputItem.getAsJsonObject().get("name") == null - || inputItem.getAsJsonObject().get("type") == null) { - logger.error("Input argument invalid due to no name or no type!"); - return null; - } - String inputName = inputItem.getAsJsonObject().get("name").getAsString(); - String inputType = inputItem.getAsJsonObject().get("type").getAsString(); - ABI.Entry.Param.Builder paramBuilder = SmartContract.ABI.Entry.Param.newBuilder(); - JsonElement indexed = inputItem.getAsJsonObject().get("indexed"); - - paramBuilder.setIndexed((indexed != null) && indexed.getAsBoolean()); - paramBuilder.setName(inputName); - paramBuilder.setType(inputType); - entryBuilder.addInputs(paramBuilder.build()); - } - } - - /* { outputs : optional } */ - if (outputs != null) { - for (int k = 0; k < outputs.size(); k++) { - JsonElement outputItem = outputs.get(k); - if (outputItem.getAsJsonObject().get("name") == null - || outputItem.getAsJsonObject().get("type") == null) { - logger.error("Output argument invalid due to no name or no type!"); - return null; - } - String outputName = outputItem.getAsJsonObject().get("name").getAsString(); - String outputType = outputItem.getAsJsonObject().get("type").getAsString(); - SmartContract.ABI.Entry.Param.Builder paramBuilder = - SmartContract.ABI.Entry.Param.newBuilder(); - JsonElement indexed = outputItem.getAsJsonObject().get("indexed"); - - paramBuilder.setIndexed((indexed != null) && indexed.getAsBoolean()); - paramBuilder.setName(outputName); - paramBuilder.setType(outputType); - entryBuilder.addOutputs(paramBuilder.build()); - } - } - entryBuilder.setType(getEntryType2(type)); - - if (stateMutability != null) { - entryBuilder.setStateMutability(getStateMutability(stateMutability)); - } - - abiBuilder.addEntrys(entryBuilder.build()); - } - - return abiBuilder.build(); - } - - /** constructor. */ - public static SmartContract.ABI.Entry.EntryType getEntryType(String type) { - switch (type) { - case "constructor": - return SmartContract.ABI.Entry.EntryType.Constructor; - case "function": - return SmartContract.ABI.Entry.EntryType.Function; - case "event": - return SmartContract.ABI.Entry.EntryType.Event; - case "fallback": - return SmartContract.ABI.Entry.EntryType.Fallback; - case "error": - return SmartContract.ABI.Entry.EntryType.Error; - default: - return SmartContract.ABI.Entry.EntryType.UNRECOGNIZED; - } - } - - /** constructor. */ - public static SmartContract.ABI.Entry.EntryType getEntryType2(String type) { - switch (type) { - case "constructor": - return SmartContract.ABI.Entry.EntryType.Constructor; - case "function": - return SmartContract.ABI.Entry.EntryType.Function; - case "event": - return SmartContract.ABI.Entry.EntryType.Event; - case "fallback": - return SmartContract.ABI.Entry.EntryType.Fallback; - case "receive": - return SmartContract.ABI.Entry.EntryType.Receive; - default: - return SmartContract.ABI.Entry.EntryType.UNRECOGNIZED; - } - } - - /** constructor. */ - public static SmartContract.ABI.Entry.StateMutabilityType getStateMutability( - String stateMutability) { - switch (stateMutability) { - case "pure": - return SmartContract.ABI.Entry.StateMutabilityType.Pure; - case "view": - return SmartContract.ABI.Entry.StateMutabilityType.View; - case "nonpayable": - return SmartContract.ABI.Entry.StateMutabilityType.Nonpayable; - case "payable": - return SmartContract.ABI.Entry.StateMutabilityType.Payable; - default: - return SmartContract.ABI.Entry.StateMutabilityType.UNRECOGNIZED; - } - } - - /** constructor. */ - public static byte[] generateContractAddress(Transaction trx, byte[] owneraddress) { - - // get owner address - // this address should be as same as the onweraddress in trx, DONNOT modify it - byte[] ownerAddress = owneraddress; - - // get tx hash - byte[] txRawDataHash = - Sha256Hash.of( - CommonParameter.getInstance().isECKeyCryptoEngine(), trx.getRawData().toByteArray()) - .getBytes(); - - // combine - byte[] combined = new byte[txRawDataHash.length + ownerAddress.length]; - System.arraycopy(txRawDataHash, 0, combined, 0, txRawDataHash.length); - System.arraycopy(ownerAddress, 0, combined, txRawDataHash.length, ownerAddress.length); - - return sha3omit12(combined); - } - - /** constructor. */ - public static SmartContract getContract( - byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString byteString = ByteString.copyFrom(address); - BytesMessage bytesMessage = BytesMessage.newBuilder().setValue(byteString).build(); - logger.info("contract name is " + blockingStubFull.getContract(bytesMessage).getName()); - logger.info("contract address is " + WalletClient.encode58Check(address)); - return blockingStubFull.getContract(bytesMessage); - } - - /** constructor. */ - public static SmartContractDataWrapper getContractInfo( - byte[] address, WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString byteString = ByteString.copyFrom(address); - BytesMessage bytesMessage = BytesMessage.newBuilder().setValue(byteString).build(); - logger.info( - "contract name is " - + blockingStubFull.getContractInfo(bytesMessage).getSmartContract().getName()); - logger.info("contract address is " + WalletClient.encode58Check(address)); - return blockingStubFull.getContractInfo(bytesMessage); - } - - private static byte[] replaceLibraryAddress(String code, String libraryAddressPair) { - - String[] libraryAddressList = libraryAddressPair.split("[,]"); - - for (int i = 0; i < libraryAddressList.length; i++) { - String cur = libraryAddressList[i]; - - int lastPosition = cur.lastIndexOf(":"); - if (-1 == lastPosition) { - throw new RuntimeException("libraryAddress delimit by ':'"); - } - String libraryName = cur.substring(0, lastPosition); - String addr = cur.substring(lastPosition + 1); - String libraryAddressHex = - ByteArray.toHexString(Commons.decodeFromBase58Check(addr)).substring(2); - - String repeated = new String(new char[40 - libraryName.length() - 2]).replace("\0", "_"); - String beReplaced = "__" + libraryName + repeated; - Matcher m = Pattern.compile(beReplaced).matcher(code); - code = m.replaceAll(libraryAddressHex); - } - - return Hex.decode(code); - } - - - - private static byte[] replaceLibraryAddresscompilerVersion( - String code, String libraryAddressPair, String compilerVersion) { - - String[] libraryAddressList = libraryAddressPair.split("[,]"); - - for (int i = 0; i < libraryAddressList.length; i++) { - String cur = libraryAddressList[i]; - - int lastPosition = cur.lastIndexOf(":"); - if (-1 == lastPosition) { - throw new RuntimeException("libraryAddress delimit by ':'"); - } - String libraryName = cur.substring(0, lastPosition); - String addr = cur.substring(lastPosition + 1); - String libraryAddressHex; - libraryAddressHex = - (new String(Hex.encode(Commons.decodeFromBase58Check(addr)), StandardCharsets.US_ASCII)) - .substring(2); - - String beReplaced; - if (compilerVersion == null) { - // old version - String repeated = new String(new char[40 - libraryName.length() - 2]).replace("\0", "_"); - beReplaced = "__" + libraryName + repeated; - } else if (compilerVersion.equalsIgnoreCase("v5")) { - // 0.5.4 version - String libraryNameKeccak256 = - ByteArray.toHexString(sha3(ByteArray.fromString(libraryName))).substring(0, 34); - beReplaced = "__\\$" + libraryNameKeccak256 + "\\$__"; - } else { - throw new RuntimeException("unknown compiler version."); - } - - Matcher m = Pattern.compile(beReplaced).matcher(code); - code = m.replaceAll(libraryAddressHex); - } - - return Hex.decode(code); - } - - /** constructor. */ - public static boolean updateSetting( - byte[] contractAddress, - long consumeUserResourcePercent, - String priKey, - byte[] ownerAddress, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - UpdateSettingContract.Builder builder = UpdateSettingContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - builder.setConsumeUserResourcePercent(consumeUserResourcePercent); - - UpdateSettingContract updateSettingContract = builder.build(); - TransactionExtention transactionExtention = - blockingStubFull.updateSetting(updateSettingContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create trx failed!"); - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println( - "Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return false; - } - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - - /** 61 constructor. */ - public static Optional getTransactionInfoById( - String txId, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString bsTxid = ByteString.copyFrom(ByteArray.fromHexString(txId)); - BytesMessage request = BytesMessage.newBuilder().setValue(bsTxid).build(); - TransactionInfo transactionInfo; - transactionInfo = blockingStubFull.getTransactionInfoById(request); - return Optional.ofNullable(transactionInfo); - } - - /** 61 constructor. */ - public static Optional getTransactionInfoByIdFromSolidity( - String txId, WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubFull) { - ByteString bsTxid = ByteString.copyFrom(ByteArray.fromHexString(txId)); - BytesMessage request = BytesMessage.newBuilder().setValue(bsTxid).build(); - TransactionInfo transactionInfo; - transactionInfo = blockingStubFull.getTransactionInfoById(request); - return Optional.ofNullable(transactionInfo); - } - - /** constructor. */ - public static Optional getTransactionInfoByBlockNum( - long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - TransactionInfoList transactionInfoList; - transactionInfoList = blockingStubFull.getTransactionInfoByBlockNum(builder.build()); - return Optional.ofNullable(transactionInfoList); - } - - /** constructor. */ - public static Optional getTransactionInfoByBlockNumFromSolidity( - long blockNum, WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - TransactionInfoList transactionInfoList; - transactionInfoList = blockingStubSolidity.getTransactionInfoByBlockNum(builder.build()); - return Optional.ofNullable(transactionInfoList); - } - - /** constructor. */ - public static String triggerContract( - byte[] contractAddress, - String method, - String argsStr, - Boolean isHex, - long callValue, - long feeLimit, - byte[] ownerAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - return triggerContract( - contractAddress, - method, - argsStr, - isHex, - callValue, - feeLimit, - "0", - 0, - ownerAddress, - priKey, - blockingStubFull); - } - - /** constructor. */ - public static String triggerContract( - byte[] contractAddress, - String method, - String argsStr, - Boolean isHex, - long callValue, - long feeLimit, - String tokenId, - long tokenValue, - byte[] ownerAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - if (argsStr.equalsIgnoreCase("#")) { - logger.info("argsstr is #"); - argsStr = ""; - } - - byte[] owner = ownerAddress; - byte[] input = new byte[0]; - if (!method.equalsIgnoreCase("#")) { - input = Hex.decode(AbiUtil.parseMethod(method, argsStr, isHex)); - } - - TriggerSmartContract.Builder builder = TriggerSmartContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - builder.setData(ByteString.copyFrom(input)); - builder.setCallValue(callValue); - builder.setTokenId(Long.parseLong(tokenId)); - builder.setCallTokenValue(tokenValue); - TriggerSmartContract triggerContract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.triggerContract(triggerContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create call trx failed!"); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println( - "Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction.getRetCount() != 0 - && transactionExtention.getConstantResult(0) != null - && transactionExtention.getResult() != null) { - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = - transactionExtention.getTransaction().getRawData().toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - - transactionExtention = texBuilder.build(); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - transaction = signTransaction(ecKey, transaction); - System.out.println( - "trigger txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - if (response.getResult() == false) { - return null; - } else { - return ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray())); - } - } - - /** constructor. */ - public static String triggerContractBoth( - byte[] contractAddress, - String method, - String argsStr, - Boolean isHex, - long callValue, - long feeLimit, - byte[] ownerAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, - WalletGrpc.WalletBlockingStub blockingStubFull1) { - return triggerContractBoth( - contractAddress, - method, - argsStr, - isHex, - callValue, - feeLimit, - "0", - 0, - ownerAddress, - priKey, - blockingStubFull, - blockingStubFull1); - } - - /** constructor. */ - public static String triggerContractBoth( - byte[] contractAddress, - String method, - String argsStr, - Boolean isHex, - long callValue, - long feeLimit, - String tokenId, - long tokenValue, - byte[] ownerAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, - WalletGrpc.WalletBlockingStub blockingStubFull1) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - if (argsStr.equalsIgnoreCase("#")) { - logger.info("argsstr is #"); - argsStr = ""; - } - - byte[] owner = ownerAddress; - byte[] input = Hex.decode(AbiUtil.parseMethod(method, argsStr, isHex)); - - TriggerSmartContract.Builder builder = TriggerSmartContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - builder.setData(ByteString.copyFrom(input)); - builder.setCallValue(callValue); - builder.setTokenId(Long.parseLong(tokenId)); - builder.setCallTokenValue(tokenValue); - TriggerSmartContract triggerContract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.triggerContract(triggerContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create call trx failed!"); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println( - "Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction.getRetCount() != 0 - && transactionExtention.getConstantResult(0) != null - && transactionExtention.getResult() != null) { - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = - transactionExtention.getTransaction().getRawData().toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - transaction = signTransaction(ecKey, transaction); - System.out.println( - "trigger txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - GrpcAPI.Return response = - broadcastTransactionBoth(transaction, blockingStubFull, blockingStubFull1); - if (response.getResult() == false) { - return null; - } else { - return ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray())); - } - } - - /** constructor. */ - public static String triggerParamListContract( - byte[] contractAddress, - String method, - List params, - Boolean isHex, - long callValue, - long feeLimit, - String tokenId, - long tokenValue, - byte[] ownerAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - byte[] input = Hex.decode(AbiUtil.parseMethod(method, params)); - - TriggerSmartContract.Builder builder = TriggerSmartContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - builder.setData(ByteString.copyFrom(input)); - builder.setCallValue(callValue); - builder.setTokenId(Long.parseLong(tokenId)); - builder.setCallTokenValue(tokenValue); - TriggerSmartContract triggerContract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.triggerContract(triggerContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create call trx failed!"); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println( - "Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction.getRetCount() != 0 - && transactionExtention.getConstantResult(0) != null - && transactionExtention.getResult() != null) { - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = - transactionExtention.getTransaction().getRawData().toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - transaction = signTransaction(ecKey, transaction); - System.out.println( - "trigger txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - if (response.getResult() == false) { - return null; - } else { - return ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray())); - } - } - - /** constructor. */ - public static Boolean exchangeCreate( - byte[] firstTokenId, - long firstTokenBalance, - byte[] secondTokenId, - long secondTokenBalance, - byte[] ownerAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - - ExchangeCreateContract.Builder builder = ExchangeCreateContract.newBuilder(); - builder - .setOwnerAddress(ByteString.copyFrom(owner)) - .setFirstTokenId(ByteString.copyFrom(firstTokenId)) - .setFirstTokenBalance(firstTokenBalance) - .setSecondTokenId(ByteString.copyFrom(secondTokenId)) - .setSecondTokenBalance(secondTokenBalance); - ExchangeCreateContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.exchangeCreate(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(ecKey, transaction); - System.out.println( - "txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - - return response.getResult(); - } - - /** constructor. */ - public static Boolean injectExchange( - long exchangeId, - byte[] tokenId, - long quant, - byte[] ownerAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - - ExchangeInjectContract.Builder builder = ExchangeInjectContract.newBuilder(); - builder - .setOwnerAddress(ByteString.copyFrom(owner)) - .setExchangeId(exchangeId) - .setTokenId(ByteString.copyFrom(tokenId)) - .setQuant(quant); - ExchangeInjectContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.exchangeInject(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(ecKey, transaction); - System.out.println( - "txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - - return response.getResult(); - } - - public static Optional getExchangeList( - WalletGrpc.WalletBlockingStub blockingStubFull) { - ExchangeList exchangeList = blockingStubFull.listExchanges(EmptyMessage.newBuilder().build()); - return Optional.ofNullable(exchangeList); - } - - /** constructor. */ - public static Optional getExchangeList( - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) { - ExchangeList exchangeList = - blockingStubSolidity.listExchanges(EmptyMessage.newBuilder().build()); - return Optional.ofNullable(exchangeList); - } - - /** constructor. */ - public static Optional getExchange( - String id, WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) { - BytesMessage request = - BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromLong(Long.parseLong(id)))) - .build(); - Exchange exchange = blockingStubSolidity.getExchangeById(request); - return Optional.ofNullable(exchange); - } - - /** constructor. */ - public static Optional getExchange( - String id, WalletGrpc.WalletBlockingStub blockingStubFull) { - BytesMessage request = - BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromLong(Long.parseLong(id)))) - .build(); - Exchange exchange = blockingStubFull.getExchangeById(request); - return Optional.ofNullable(exchange); - } - - /** constructor. */ - public static boolean exchangeWithdraw( - long exchangeId, - byte[] tokenId, - long quant, - byte[] ownerAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - byte[] owner = ownerAddress; - - ExchangeWithdrawContract.Builder builder = ExchangeWithdrawContract.newBuilder(); - builder - .setOwnerAddress(ByteString.copyFrom(owner)) - .setExchangeId(exchangeId) - .setTokenId(ByteString.copyFrom(tokenId)) - .setQuant(quant); - ExchangeWithdrawContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.exchangeWithdraw(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(ecKey, transaction); - System.out.println( - "txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - /** constructor. */ - public static boolean exchangeTransaction( - long exchangeId, - byte[] tokenId, - long quant, - long expected, - byte[] ownerAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - byte[] owner = ownerAddress; - - ExchangeTransactionContract.Builder builder = ExchangeTransactionContract.newBuilder(); - builder - .setOwnerAddress(ByteString.copyFrom(owner)) - .setExchangeId(exchangeId) - .setTokenId(ByteString.copyFrom(tokenId)) - .setQuant(quant) - .setExpected(expected); - ExchangeTransactionContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.exchangeTransaction(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(ecKey, transaction); - System.out.println( - "txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - /** constructor. */ - public static String deployContractWithConstantParame( - String contractName, - String abiString, - String code, - String constructorStr, - String argsStr, - String data, - Long feeLimit, - long value, - long consumeUserResourcePercent, - String libraryAddress, - String priKey, - byte[] ownerAddress, - WalletGrpc.WalletBlockingStub blockingStubFull) { - return deployContractWithConstantParame( - contractName, - abiString, - code, - constructorStr, - argsStr, - data, - feeLimit, - value, - consumeUserResourcePercent, - 1000L, - "0", - 0L, - libraryAddress, - priKey, - ownerAddress, - blockingStubFull); - } - - /** constructor. */ - public static String deployContractWithConstantParame( - String contractName, - String abiString, - String code, - String constructorStr, - String argsStr, - String data, - Long feeLimit, - long value, - long consumeUserResourcePercent, - long originEnergyLimit, - String tokenId, - long tokenValue, - String libraryAddress, - String priKey, - byte[] ownerAddress, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - SmartContract.ABI abi = jsonStr2Abi(abiString); - if (abi == null) { - logger.error("abi is null"); - return null; - } - - code += Hex.toHexString(AbiUtil.encodeInput(constructorStr, argsStr)); - byte[] owner = ownerAddress; - SmartContract.Builder builder = SmartContract.newBuilder(); - builder.setName(contractName); - builder.setOriginAddress(ByteString.copyFrom(owner)); - builder.setAbi(abi); - builder.setConsumeUserResourcePercent(consumeUserResourcePercent); - builder.setOriginEnergyLimit(originEnergyLimit); - - if (value != 0) { - - builder.setCallValue(value); - } - - byte[] byteCode; - if (null != libraryAddress) { - byteCode = replaceLibraryAddress(code, libraryAddress); - } else { - byteCode = Hex.decode(code); - } - builder.setBytecode(ByteString.copyFrom(byteCode)); - - Builder contractBuilder = CreateSmartContract.newBuilder(); - contractBuilder.setOwnerAddress(ByteString.copyFrom(owner)); - contractBuilder.setCallTokenValue(tokenValue); - contractBuilder.setTokenId(Long.parseLong(tokenId)); - CreateSmartContract contractDeployContract = - contractBuilder.setNewContract(builder.build()).build(); - - TransactionExtention transactionExtention = - blockingStubFull.deployContract(contractDeployContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create trx failed!"); - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println( - "Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = - transactionExtention.getTransaction().getRawData().toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - transaction = signTransaction(ecKey, transaction); - System.out.println( - "txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - byte[] contractAddress = generateContractAddress(transaction, owner); - System.out.println( - "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - if (response.getResult() == false) { - return null; - } else { - // logger.info("brodacast succesfully"); - return ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray())); - } - } - - /** constructor. */ - public static Boolean freezeBalanceForReceiver( - byte[] addRess, - long freezeBalance, - long freezeDuration, - int resourceCode, - ByteString receiverAddressBytes, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - FreezeBalanceContract.Builder builder = FreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder - .setOwnerAddress(byteAddreess) - .setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration) - .setResourceValue(resourceCode); - if (receiverAddressBytes != null) { - builder.setReceiverAddress(receiverAddressBytes); - } - FreezeBalanceContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction = null"); - return false; - } - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - /** constructor. */ - public static Optional getDelegatedResource( - byte[] fromAddress, byte[] toAddress, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString fromAddressBs = ByteString.copyFrom(fromAddress); - ByteString toAddressBs = ByteString.copyFrom(toAddress); - - DelegatedResourceMessage request = - DelegatedResourceMessage.newBuilder() - .setFromAddress(fromAddressBs) - .setToAddress(toAddressBs) - .build(); - DelegatedResourceList delegatedResource = blockingStubFull.getDelegatedResource(request); - return Optional.ofNullable(delegatedResource); - } - - /** constructor. */ - public static Optional getDelegatedResourceFromSolidity( - byte[] fromAddress, - byte[] toAddress, - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString fromAddressBs = ByteString.copyFrom(fromAddress); - ByteString toAddressBs = ByteString.copyFrom(toAddress); - - DelegatedResourceMessage request = - DelegatedResourceMessage.newBuilder() - .setFromAddress(fromAddressBs) - .setToAddress(toAddressBs) - .build(); - DelegatedResourceList delegatedResource = blockingStubFull.getDelegatedResource(request); - return Optional.ofNullable(delegatedResource); - } - - /** constructor. */ - public static Optional getDelegatedResourceAccountIndex( - byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - - ByteString addressBs = ByteString.copyFrom(address); - - BytesMessage bytesMessage = BytesMessage.newBuilder().setValue(addressBs).build(); - - DelegatedResourceAccountIndex accountIndex = - blockingStubFull.getDelegatedResourceAccountIndex(bytesMessage); - return Optional.ofNullable(accountIndex); - } - - /** constructor. */ - public static Optional - getDelegatedResourceAccountIndexFromSolidity( - byte[] address, WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - - ByteString addressBs = ByteString.copyFrom(address); - - BytesMessage bytesMessage = BytesMessage.newBuilder().setValue(addressBs).build(); - - DelegatedResourceAccountIndex accountIndex = - blockingStubFull.getDelegatedResourceAccountIndex(bytesMessage); - return Optional.ofNullable(accountIndex); - } - - /** constructor. */ - public static AssetIssueContract getAssetIssueByName( - String assetName, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString assetNameBs = ByteString.copyFrom(assetName.getBytes()); - BytesMessage request = BytesMessage.newBuilder().setValue(assetNameBs).build(); - return blockingStubFull.getAssetIssueByName(request); - } - - /** constructor. */ - public static AssetIssueContract getAssetIssueByNameFromSolidity( - String assetName, WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString assetNameBs = ByteString.copyFrom(assetName.getBytes()); - BytesMessage request = BytesMessage.newBuilder().setValue(assetNameBs).build(); - return blockingStubFull.getAssetIssueByName(request); - } - - /** constructor. */ - public static Optional getAssetIssueListByName( - String assetName, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString assetNameBs = ByteString.copyFrom(assetName.getBytes()); - BytesMessage request = BytesMessage.newBuilder().setValue(assetNameBs).build(); - AssetIssueList assetIssueList = blockingStubFull.getAssetIssueListByName(request); - return Optional.ofNullable(assetIssueList); - } - - /** constructor. */ - public static Optional getAssetIssueListByNameFromSolidity( - String assetName, WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString assetNameBs = ByteString.copyFrom(assetName.getBytes()); - BytesMessage request = BytesMessage.newBuilder().setValue(assetNameBs).build(); - AssetIssueList assetIssueList = blockingStubFull.getAssetIssueListByName(request); - return Optional.ofNullable(assetIssueList); - } - - /** constructor. */ - public static Optional listAssetIssueFromSolidity( - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubFull) { - GrpcAPI.AssetIssueList assetIssueList = - blockingStubFull.getAssetIssueList(EmptyMessage.newBuilder().build()); - return Optional.ofNullable(assetIssueList); - } - - /** constructor. */ - public static Optional listAssetIssuepaginatedFromSolidity( - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubFull, Long offset, Long limit) { - GrpcAPI.PaginatedMessage.Builder pageMessageBuilder = GrpcAPI.PaginatedMessage.newBuilder(); - pageMessageBuilder.setOffset(offset); - pageMessageBuilder.setLimit(limit); - AssetIssueList assetIssueList = - blockingStubFull.getPaginatedAssetIssueList(pageMessageBuilder.build()); - return Optional.ofNullable(assetIssueList); - } - - /** constructor. */ - public static Optional listWitnesses( - WalletGrpc.WalletBlockingStub blockingStubFull) { - GrpcAPI.WitnessList witnessList = - blockingStubFull.listWitnesses(EmptyMessage.newBuilder().build()); - return Optional.ofNullable(witnessList); - } - - /** constructor. */ - public static Optional listWitnessesFromSolidity( - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubFull) { - GrpcAPI.WitnessList witnessList = - blockingStubFull.listWitnesses(EmptyMessage.newBuilder().build()); - return Optional.ofNullable(witnessList); - } - - /** constructor. */ - public static AssetIssueContract getAssetIssueById( - String assetId, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString assetIdBs = ByteString.copyFrom(assetId.getBytes()); - BytesMessage request = BytesMessage.newBuilder().setValue(assetIdBs).build(); - return blockingStubFull.getAssetIssueById(request); - } - - /** constructor. */ - public static AssetIssueContract getAssetIssueByIdFromSolidity( - String assetId, WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString assetIdBs = ByteString.copyFrom(assetId.getBytes()); - BytesMessage request = BytesMessage.newBuilder().setValue(assetIdBs).build(); - return blockingStubFull.getAssetIssueById(request); - } - - /** constructor. */ - public static Optional getAssetIssueByAccount( - byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - AssetIssueList assetIssueList = blockingStubFull.getAssetIssueByAccount(request); - return Optional.ofNullable(assetIssueList); - } - - private static Permission json2Permission(JSONObject json) { - Permission.Builder permissionBuilder = Permission.newBuilder(); - if (json.containsKey("type")) { - int type = json.getInteger("type"); - permissionBuilder.setTypeValue(type); - } - if (json.containsKey("permission_name")) { - String permissionName = json.getString("permission_name"); - permissionBuilder.setPermissionName(permissionName); - } - if (json.containsKey("threshold")) { - // long threshold = json.getLong("threshold"); - long threshold = Long.parseLong(json.getString("threshold")); - permissionBuilder.setThreshold(threshold); - } - if (json.containsKey("parent_id")) { - int parentId = json.getInteger("parent_id"); - permissionBuilder.setParentId(parentId); - } - if (json.containsKey("operations")) { - byte[] operations = ByteArray.fromHexString(json.getString("operations")); - permissionBuilder.setOperations(ByteString.copyFrom(operations)); - } - if (json.containsKey("keys")) { - JSONArray keys = json.getJSONArray("keys"); - List keyList = new ArrayList<>(); - for (int i = 0; i < keys.size(); i++) { - Key.Builder keyBuilder = Key.newBuilder(); - JSONObject key = keys.getJSONObject(i); - String address = key.getString("address"); - long weight = Long.parseLong(key.getString("weight")); - // long weight = key.getLong("weight"); - // keyBuilder.setAddress(ByteString.copyFrom(address.getBytes())); - keyBuilder.setAddress(ByteString.copyFrom(WalletClient.decodeFromBase58Check(address))); - keyBuilder.setWeight(weight); - keyList.add(keyBuilder.build()); - } - permissionBuilder.addAllKeys(keyList); - } - return permissionBuilder.build(); - } - - /** constructor. */ - public static boolean accountPermissionUpdate( - String permissionJson, - byte[] owner, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, - String[] priKeys) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - AccountPermissionUpdateContract.Builder builder = AccountPermissionUpdateContract.newBuilder(); - - JSONObject permissions = JSONObject.parseObject(permissionJson); - JSONObject ownerpermission = permissions.getJSONObject("owner_permission"); - JSONObject witnesspermission = permissions.getJSONObject("witness_permission"); - JSONArray activepermissions = permissions.getJSONArray("active_permissions"); - - if (ownerpermission != null) { - Permission ownerPermission = json2Permission(ownerpermission); - builder.setOwner(ownerPermission); - } - if (witnesspermission != null) { - Permission witnessPermission = json2Permission(witnesspermission); - builder.setWitness(witnessPermission); - } - if (activepermissions != null) { - List activePermissionList = new ArrayList<>(); - for (int j = 0; j < activepermissions.size(); j++) { - JSONObject permission = activepermissions.getJSONObject(j); - activePermissionList.add(json2Permission(permission)); - } - builder.addAllActives(activePermissionList); - } - builder.setOwnerAddress(ByteString.copyFrom(owner)); - - AccountPermissionUpdateContract contract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.accountPermissionUpdate(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - /** constructor. */ - public static long getFreezeBalanceCount( - byte[] accountAddress, - String ecKey, - Long targetEnergy, - WalletGrpc.WalletBlockingStub blockingStubFull) { - // Precision change as the entire network freezes - AccountResourceMessage resourceInfo = getAccountResource(accountAddress, blockingStubFull); - - Account info = queryAccount(accountAddress, blockingStubFull); - - Account getAccount = queryAccount(ecKey, blockingStubFull); - - long balance = info.getBalance(); - long frozenBalance = info.getAccountResource().getFrozenBalanceForEnergy().getFrozenBalance(); - long totalEnergyLimit = resourceInfo.getTotalEnergyLimit(); - long totalEnergyWeight = resourceInfo.getTotalEnergyWeight(); - long energyUsed = resourceInfo.getEnergyUsed(); - long energyLimit = resourceInfo.getEnergyLimit(); - - if (energyUsed > energyLimit) { - targetEnergy = energyUsed - energyLimit + targetEnergy; - } - - if (totalEnergyWeight == 0) { - return 1000_000L; - } - - // totalEnergyLimit / (totalEnergyWeight + needBalance) = needEnergy / needBalance - final BigInteger totalEnergyWeightBi = BigInteger.valueOf(totalEnergyWeight); - long needBalance = - totalEnergyWeightBi - .multiply(BigInteger.valueOf(1_000_000)) - .multiply(BigInteger.valueOf(targetEnergy)) - .divide(BigInteger.valueOf(totalEnergyLimit - targetEnergy)) - .longValue(); - - logger.info("getFreezeBalanceCount, needBalance: " + needBalance); - - if (needBalance < 1000000L) { - needBalance = 1000000L; - logger.info("getFreezeBalanceCount, needBalance less than 1 TRX, modify to: " + needBalance); - } - return needBalance; - } - - /** constructor. */ - public static Long getAssetIssueValue( - byte[] accountAddress, - ByteString assetIssueId, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Long assetIssueCount = 0L; - Account contractAccount = queryAccount(accountAddress, blockingStubFull); - Map createAssetIssueMap = contractAccount.getAssetV2Map(); - for (Map.Entry entry : createAssetIssueMap.entrySet()) { - if (assetIssueId.toStringUtf8().equals(entry.getKey())) { - assetIssueCount = entry.getValue(); - } - } - return assetIssueCount; - } - - /** constructor. */ - public static List getStrings(byte[] data) { - int index = 0; - List ret = new ArrayList<>(); - while (index < data.length) { - ret.add(byte2HexStr(data, index, 32)); - index += 32; - } - return ret; - } - - /** constructor. */ - public static String byte2HexStr(byte[] b, int offset, int length) { - StringBuilder ssBuilder = new StringBuilder(); - for (int n = offset; n < offset + length && n < b.length; n++) { - String stmp = Integer.toHexString(b[n] & 0xFF); - ssBuilder.append((stmp.length() == 1) ? "0" + stmp : stmp); - } - return ssBuilder.toString().toUpperCase().trim(); - } - - /** constructor. */ - public static Transaction addTransactionSign( - Transaction transaction, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - Transaction.Builder transactionBuilderSigned = transaction.toBuilder(); - byte[] hash = - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()); - - ECDSASignature signature = ecKey.sign(hash); - ByteString bsSign = ByteString.copyFrom(signature.toByteArray()); - transactionBuilderSigned.addSignature(bsSign); - transaction = transactionBuilderSigned.build(); - return transaction; - } - - /** constructor. */ - public static GrpcAPI.Return deployContractAndGetResponse( - String contractName, - String abiString, - String code, - String data, - Long feeLimit, - long value, - long consumeUserResourcePercent, - long originEnergyLimit, - String tokenId, - long tokenValue, - String libraryAddress, - String priKey, - byte[] ownerAddress, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - SmartContract.ABI abi = jsonStr2Abi(abiString); - if (abi == null) { - logger.error("abi is null"); - return null; - } - // byte[] codeBytes = Hex.decode(code); - SmartContract.Builder builder = SmartContract.newBuilder(); - builder.setName(contractName); - builder.setOriginAddress(ByteString.copyFrom(owner)); - builder.setAbi(abi); - builder.setConsumeUserResourcePercent(consumeUserResourcePercent); - builder.setOriginEnergyLimit(originEnergyLimit); - - if (value != 0) { - - builder.setCallValue(value); - } - - byte[] byteCode; - if (null != libraryAddress) { - byteCode = replaceLibraryAddress(code, libraryAddress); - } else { - byteCode = Hex.decode(code); - } - builder.setBytecode(ByteString.copyFrom(byteCode)); - - Builder contractBuilder = CreateSmartContract.newBuilder(); - contractBuilder.setOwnerAddress(ByteString.copyFrom(owner)); - contractBuilder.setCallTokenValue(tokenValue); - contractBuilder.setTokenId(Long.parseLong(tokenId)); - CreateSmartContract contractDeployContract = - contractBuilder.setNewContract(builder.build()).build(); - - TransactionExtention transactionExtention = - blockingStubFull.deployContract(contractDeployContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create trx failed!"); - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println( - "Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = - transactionExtention.getTransaction().getRawData().toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - transaction = signTransaction(ecKey, transaction); - System.out.println( - "txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - byte[] contractAddress = generateContractAddress(transaction, owner); - System.out.println( - "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - - return response; - } - - /** constructor. */ - public static GrpcAPI.Return triggerContractAndGetResponse( - byte[] contractAddress, - String method, - String argsStr, - Boolean isHex, - long callValue, - long feeLimit, - String tokenId, - long tokenValue, - byte[] ownerAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - if (argsStr.equalsIgnoreCase("#")) { - logger.info("argsstr is #"); - argsStr = ""; - } - - byte[] owner = ownerAddress; - byte[] input = Hex.decode(AbiUtil.parseMethod(method, argsStr, isHex)); - - TriggerSmartContract.Builder builder = TriggerSmartContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - builder.setData(ByteString.copyFrom(input)); - builder.setCallValue(callValue); - builder.setTokenId(Long.parseLong(tokenId)); - builder.setCallTokenValue(tokenValue); - TriggerSmartContract triggerContract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.triggerContract(triggerContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create call trx failed!"); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println( - "Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction.getRetCount() != 0 - && transactionExtention.getConstantResult(0) != null - && transactionExtention.getResult() != null) { - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = - transactionExtention.getTransaction().getRawData().toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - transaction = signTransaction(ecKey, transaction); - System.out.println( - "trigger txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response; - } - - /** constructor. */ - public static boolean updateEnergyLimit( - byte[] contractAddress, - long originEnergyLimit, - String priKey, - byte[] ownerAddress, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - UpdateEnergyLimitContract.Builder builder = UpdateEnergyLimitContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - builder.setOriginEnergyLimit(originEnergyLimit); - - UpdateEnergyLimitContract updateEnergyLimitContract = builder.build(); - TransactionExtention transactionExtention = - blockingStubFull.updateEnergyLimit(updateEnergyLimitContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create trx failed!"); - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println( - "Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return false; - } - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - /** constructor. */ - public static GrpcAPI.Return accountPermissionUpdateForResponse( - String permissionJson, - byte[] owner, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - AccountPermissionUpdateContract.Builder builder = AccountPermissionUpdateContract.newBuilder(); - - JSONObject permissions = JSONObject.parseObject(permissionJson); - JSONObject ownerpermission = permissions.getJSONObject("owner_permission"); - JSONObject witnesspermission = permissions.getJSONObject("witness_permission"); - JSONArray activepermissions = permissions.getJSONArray("active_permissions"); - - if (ownerpermission != null) { - Permission ownerPermission = json2Permission(ownerpermission); - builder.setOwner(ownerPermission); - } - if (witnesspermission != null) { - Permission witnessPermission = json2Permission(witnesspermission); - builder.setWitness(witnessPermission); - } - if (activepermissions != null) { - List activePermissionList = new ArrayList<>(); - for (int j = 0; j < activepermissions.size(); j++) { - JSONObject permission = activepermissions.getJSONObject(j); - activePermissionList.add(json2Permission(permission)); - } - builder.addAllActives(activePermissionList); - } - builder.setOwnerAddress(ByteString.copyFrom(owner)); - - AccountPermissionUpdateContract contract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.accountPermissionUpdate(contract); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return ret; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - - return response; - } - - public static TransactionApprovedList getTransactionApprovedList( - Transaction transaction, WalletGrpc.WalletBlockingStub blockingStubFull) { - return blockingStubFull.getTransactionApprovedList(transaction); - } - - /** constructor. */ - public static long getFreezeBalanceNetCount( - byte[] accountAddress, - String ecKey, - Long targetNet, - WalletGrpc.WalletBlockingStub blockingStubFull) { - // Precision change as the entire network freezes - AccountResourceMessage resourceInfo = getAccountResource(accountAddress, blockingStubFull); - - Account info = queryAccount(accountAddress, blockingStubFull); - - Account getAccount = queryAccount(ecKey, blockingStubFull); - - long balance = info.getBalance(); - long totalNetLimit = resourceInfo.getTotalNetLimit(); - long totalNetWeight = resourceInfo.getTotalNetWeight(); - long netUsed = resourceInfo.getNetUsed(); - long netLimit = resourceInfo.getNetLimit(); - - if (netUsed > netLimit) { - targetNet = netUsed - netLimit + targetNet; - } - - if (totalNetWeight == 0) { - return 1000_000L; - } - - // totalNetLimit / (totalNetWeight + needBalance) = needNet / needBalance - final BigInteger totalNetWeightBi = BigInteger.valueOf(totalNetWeight); - long needBalance = - totalNetWeightBi - .multiply(BigInteger.valueOf(1_000_000)) - .multiply(BigInteger.valueOf(targetNet)) - .divide(BigInteger.valueOf(totalNetLimit - targetNet)) - .longValue(); - - logger.info("getFreezeBalanceNetCount, needBalance: " + needBalance); - - if (needBalance < 1000000L) { - needBalance = 1000000L; - logger.info( - "getFreezeBalanceNetCount, needBalance less than 1 TRX, modify to: " + needBalance); - } - return needBalance; - } - - /** constructor. */ - public static GrpcAPI.Return broadcastTransaction( - Transaction transaction, WalletGrpc.WalletBlockingStub blockingStubFull) { - int i = 10; - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - while (!response.getResult() && response.getCode() == response_code.SERVER_BUSY && i > 0) { - try { - Thread.sleep(300); - } catch (InterruptedException e) { - e.printStackTrace(); - } - i--; - response = blockingStubFull.broadcastTransaction(transaction); - logger.info("repeate times = " + (10 - i)); - } - - if (response.getResult() == false) { - logger.info("Code = " + response.getCode()); - logger.info("Message = " + response.getMessage().toStringUtf8()); - } - return response; - } - - /** constructor. */ - public static GrpcAPI.Return broadcastTransactionBoth( - Transaction transaction, - WalletGrpc.WalletBlockingStub blockingStubFull, - WalletGrpc.WalletBlockingStub blockingStubFull1) { - int i = 10; - waitProduceNextBlock(blockingStubFull1); - GrpcAPI.Return response = blockingStubFull1.broadcastTransaction(transaction); - GrpcAPI.Return response1 = blockingStubFull.broadcastTransaction(transaction); - while (response.getResult() == false - && response.getCode() == response_code.SERVER_BUSY - && i > 0) { - try { - Thread.sleep(300); - } catch (InterruptedException e) { - e.printStackTrace(); - } - i--; - response = blockingStubFull.broadcastTransaction(transaction); - logger.info("repeate times = " + (10 - i)); - } - - if (response.getResult() == false) { - logger.info("Code = " + response.getCode()); - logger.info("Message = " + response.getMessage().toStringUtf8()); - } - return response; - } - - /** constructor. */ - public static String exec(String command) throws InterruptedException { - String returnString = ""; - Process pro = null; - Runtime runTime = Runtime.getRuntime(); - if (runTime == null) { - logger.error("Create runtime false!"); - } - try { - pro = runTime.exec(command); - BufferedReader input = new BufferedReader(new InputStreamReader(pro.getInputStream())); - PrintWriter output = new PrintWriter(new OutputStreamWriter(pro.getOutputStream())); - String line; - while ((line = input.readLine()) != null) { - returnString = returnString + line + "\n"; - } - input.close(); - output.close(); - pro.destroy(); - } catch (IOException ex) { - logger.error(null, ex); - } - return returnString; - } - - /** constructor. */ - public static HashMap getBycodeAbiNoOptimize( - String solFile, String contractName) { - final String compile = - Configuration.getByPath("testng.conf").getString("defaultParameter.solidityCompile"); - - String dirPath = solFile.substring(solFile.lastIndexOf("/"), solFile.lastIndexOf(".")); - String outputPath = "src/test/resources/soliditycode//output" + dirPath; - - File binFile = new File(outputPath + "/" + contractName + ".bin"); - File abiFile = new File(outputPath + "/" + contractName + ".abi"); - if (binFile.exists()) { - binFile.delete(); - } - if (abiFile.exists()) { - abiFile.delete(); - } - - HashMap retMap = new HashMap<>(); - String absolutePath = System.getProperty("user.dir"); - logger.debug("absolutePath: " + absolutePath); - logger.debug("solFile: " + solFile); - logger.debug("outputPath: " + outputPath); - String cmd = - compile - + " --bin --abi --overwrite " - + absolutePath - + "/" - + solFile - + " -o " - + absolutePath - + "/" - + outputPath; - logger.info("cmd: " + cmd); - - String byteCode = null; - String abI = null; - - // compile solidity file - try { - exec(cmd); - } catch (InterruptedException e) { - e.printStackTrace(); - } - // get byteCode and ABI - try { - byteCode = fileRead(outputPath + "/" + contractName + ".bin", false); - retMap.put("byteCode", byteCode); - logger.debug("byteCode: " + byteCode); - abI = fileRead(outputPath + "/" + contractName + ".abi", false); - retMap.put("abI", abI); - logger.debug("abI: " + abI); - } catch (Exception e) { - e.printStackTrace(); - } - return retMap; - } - - /** constructor. */ - public static HashMap getBycodeAbi(String solFile, String contractName) { - final String compile = - Configuration.getByPath("testng.conf").getString("defaultParameter.solidityCompile"); - - String dirPath = solFile.substring(solFile.lastIndexOf("/"), solFile.lastIndexOf(".")); - String outputPath = "src/test/resources/soliditycode//output" + dirPath; - - File binFile = new File(outputPath + "/" + contractName + ".bin"); - File abiFile = new File(outputPath + "/" + contractName + ".abi"); - if (binFile.exists()) { - binFile.delete(); - } - if (abiFile.exists()) { - abiFile.delete(); - } - - HashMap retMap = new HashMap<>(); - String absolutePath = System.getProperty("user.dir"); - logger.debug("absolutePath: " + absolutePath); - logger.debug("solFile: " + solFile); - logger.debug("outputPath: " + outputPath); - String cmd = - compile - + " --optimize --bin --abi --overwrite " - + absolutePath - + "/" - + solFile - + " -o " - + absolutePath - + "/" - + outputPath; - logger.info("cmd: " + cmd); - - String byteCode = null; - String abI = null; - - // compile solidity file - try { - exec(cmd); - } catch (InterruptedException e) { - e.printStackTrace(); - } - // get byteCode and ABI - try { - byteCode = fileRead(outputPath + "/" + contractName + ".bin", false); - retMap.put("byteCode", byteCode); - logger.debug("byteCode: " + byteCode); - abI = fileRead(outputPath + "/" + contractName + ".abi", false); - retMap.put("abI", abI); - logger.debug("abI: " + abI); - } catch (Exception e) { - e.printStackTrace(); - } - return retMap; - } - - /** constructor. */ - public static String fileRead(String filePath, boolean isLibrary) throws Exception { - File file = new File(filePath); - FileReader reader = new FileReader(file); - BufferedReader breader = new BufferedReader(reader); - StringBuilder sb = new StringBuilder(); - String s = ""; - if (!isLibrary) { - if ((s = breader.readLine()) != null) { - sb.append(s); - } - breader.close(); - } else { - String fistLine = breader.readLine(); - breader.readLine(); - if ((s = breader.readLine()) != null && !s.equals("")) { - s = s.substring(s.indexOf("-> ") + 3); - sb.append(s + ":"); - } else { - s = fistLine.substring(fistLine.indexOf("__") + 2, fistLine.lastIndexOf("__")); - sb.append(s + ":"); - } - breader.close(); - } - return sb.toString(); - } - - /** constructor. */ - public static HashMap getBycodeAbiForLibrary( - String solFile, String contractName) { - HashMap retMap = null; - String dirPath = solFile.substring(solFile.lastIndexOf("/"), solFile.lastIndexOf(".")); - String outputPath = "src/test/resources/soliditycode/output" + dirPath; - try { - retMap = PublicMethed.getBycodeAbi(solFile, contractName); - String library = fileRead(outputPath + "/" + contractName + ".bin", true); - retMap.put("library", library); - logger.debug("library: " + library); - } catch (Exception e) { - e.printStackTrace(); - } - - return retMap; - } - - /** constructor. */ - public static String triggerConstantContract( - byte[] contractAddress, - String method, - String argsStr, - Boolean isHex, - long callValue, - long feeLimit, - String tokenId, - long tokenValue, - byte[] ownerAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - if (argsStr.equalsIgnoreCase("#")) { - logger.info("argsstr is #"); - argsStr = ""; - } - - byte[] owner = ownerAddress; - byte[] input = Hex.decode(AbiUtil.parseMethod(method, argsStr, isHex)); - - TriggerSmartContract.Builder builder = TriggerSmartContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - builder.setData(ByteString.copyFrom(input)); - builder.setCallValue(callValue); - builder.setTokenId(Long.parseLong(tokenId)); - builder.setCallTokenValue(tokenValue); - TriggerSmartContract triggerContract = builder.build(); - - TransactionExtention transactionExtention = - blockingStubFull.triggerConstantContract(triggerContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create call trx failed!"); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println( - "Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction.getRetCount() != 0 - && transactionExtention.getConstantResult(0) != null - && transactionExtention.getResult() != null) { - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = - transactionExtention.getTransaction().getRawData().toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - transaction = signTransaction(ecKey, transaction); - System.out.println( - "trigger txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - if (response.getResult() == false) { - return null; - } else { - return ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray())); - } - } - - /** constructor. */ - public static TransactionExtention triggerConstantContractForExtentionOnSolidity( - byte[] contractAddress, - String method, - String argsStr, - Boolean isHex, - long callValue, - long feeLimit, - String tokenId, - long tokenValue, - byte[] ownerAddress, - String priKey, - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - if (argsStr.equalsIgnoreCase("#")) { - logger.info("argsstr is #"); - argsStr = ""; - } - - byte[] owner = ownerAddress; - byte[] input = Hex.decode(AbiUtil.parseMethod(method, argsStr, isHex)); - - TriggerSmartContract.Builder builder = TriggerSmartContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - builder.setData(ByteString.copyFrom(input)); - builder.setCallValue(callValue); - builder.setTokenId(Long.parseLong(tokenId)); - builder.setCallTokenValue(tokenValue); - TriggerSmartContract triggerContract = builder.build(); - - TransactionExtention transactionExtention = - blockingStubSolidity.triggerConstantContract(triggerContract); - return transactionExtention; - } - - /** constructor. */ - public static String clearContractAbi( - byte[] contractAddress, - byte[] ownerAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - - ClearABIContract.Builder builder = ClearABIContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - - ClearABIContract clearAbiContract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.clearContractABI(clearAbiContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create call trx failed!"); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println( - "Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction.getRetCount() != 0 - && transactionExtention.getConstantResult(0) != null - && transactionExtention.getResult() != null) { - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = - transactionExtention.getTransaction().getRawData().toBuilder(); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - transaction = signTransaction(ecKey, transaction); - System.out.println( - "trigger txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - if (response.getResult() == false) { - return null; - } else { - return ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray())); - } - } - - /** constructor. */ - public static TransactionExtention clearContractAbiForExtention( - byte[] contractAddress, - byte[] ownerAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - - ClearABIContract.Builder builder = ClearABIContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - - ClearABIContract clearAbiContract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.clearContractABI(clearAbiContract); - return transactionExtention; - } - - /** constructor. */ - public static TransactionExtention triggerConstantContractForExtention( - byte[] contractAddress, - String method, - String argsStr, - Boolean isHex, - long callValue, - long feeLimit, - String tokenId, - long tokenValue, - byte[] ownerAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - if (argsStr.equalsIgnoreCase("#")) { - logger.info("argsstr is #"); - argsStr = ""; - } - if (tokenId.equalsIgnoreCase("") || tokenId.equalsIgnoreCase("#")) { - logger.info("tokenid is 0"); - tokenId = "0"; - } - - byte[] owner = ownerAddress; - byte[] input = Hex.decode(AbiUtil.parseMethod(method, argsStr, isHex)); - TriggerSmartContract.Builder builder = TriggerSmartContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - builder.setData(ByteString.copyFrom(input)); - builder.setCallValue(callValue); - builder.setTokenId(Long.parseLong(tokenId)); - builder.setCallTokenValue(tokenValue); - TriggerSmartContract triggerContract = builder.build(); - TransactionExtention transactionExtention = - blockingStubFull.triggerConstantContract(triggerContract); - return transactionExtention; - } - - /** constructor. */ - public static TransactionExtention triggerSolidityContractForExtention( - byte[] contractAddress, - String method, - String argsStr, - Boolean isHex, - long callValue, - long feeLimit, - String tokenId, - long tokenValue, - byte[] ownerAddress, - String priKey, - WalletSolidityGrpc.WalletSolidityBlockingStub solidityBlockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - if (argsStr.equalsIgnoreCase("#")) { - logger.info("argsstr is #"); - argsStr = ""; - } - - byte[] owner = ownerAddress; - byte[] input = Hex.decode(AbiUtil.parseMethod(method, argsStr, isHex)); - - TriggerSmartContract.Builder builder = TriggerSmartContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - builder.setData(ByteString.copyFrom(input)); - builder.setCallValue(callValue); - builder.setTokenId(Long.parseLong(tokenId)); - builder.setCallTokenValue(tokenValue); - TriggerSmartContract triggerContract = builder.build(); - - TransactionExtention transactionExtention = - solidityBlockingStubFull.triggerConstantContract(triggerContract); - return transactionExtention; - } - - /** constructor. */ - public static TransactionExtention triggerContractForExtention( - byte[] contractAddress, - String method, - String argsStr, - Boolean isHex, - long callValue, - long feeLimit, - String tokenId, - long tokenValue, - byte[] ownerAddress, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - if (argsStr.equalsIgnoreCase("#")) { - logger.info("argsstr is #"); - argsStr = ""; - } - - byte[] owner = ownerAddress; - byte[] input = Hex.decode(AbiUtil.parseMethod(method, argsStr, isHex)); - - TriggerSmartContract.Builder builder = TriggerSmartContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - builder.setData(ByteString.copyFrom(input)); - builder.setCallValue(callValue); - builder.setTokenId(Long.parseLong(tokenId)); - builder.setCallTokenValue(tokenValue); - TriggerSmartContract triggerContract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.triggerContract(triggerContract); - return transactionExtention; - } - - /** constructor. */ - public static String create2(String[] parameters) { - if (parameters == null || parameters.length != 3) { - logger.error("create2 needs 3 parameter:\ncreate2 address code salt"); - return null; - } - - byte[] address = WalletClient.decodeFromBase58Check(parameters[0]); - if (!WalletClient.addressValid(address)) { - logger.error("length of address must be 21 bytes."); - return null; - } - - byte[] code = Hex.decode(parameters[1]); - byte[] temp = Longs.toByteArray(Long.parseLong(parameters[2])); - if (temp.length != 8) { - logger.error("Invalid salt!"); - return null; - } - byte[] salt = new byte[32]; - System.arraycopy(temp, 0, salt, 24, 8); - - byte[] mergedData = ByteUtil.merge(address, salt, sha3(code)); - String create2Address = Base58.encode58Check(sha3omit12(mergedData)); - - logger.info("create2 Address: " + create2Address); - - return create2Address; - } - - /** constructor. */ - public static boolean sendShieldCoin( - byte[] publicZenTokenOwnerAddress, - long fromAmount, - ShieldAddressInfo shieldAddressInfo, - NoteTx noteTx, - List shieldOutputList, - byte[] publicZenTokenToAddress, - long toAmount, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - PrivateParameters.Builder builder = PrivateParameters.newBuilder(); - if (!ByteUtil.isNullOrZeroArray(publicZenTokenOwnerAddress)) { - builder.setTransparentFromAddress(ByteString.copyFrom(publicZenTokenOwnerAddress)); - builder.setFromAmount(fromAmount); - } - if (!ByteUtil.isNullOrZeroArray(publicZenTokenToAddress)) { - builder.setTransparentToAddress(ByteString.copyFrom(publicZenTokenToAddress)); - builder.setToAmount(toAmount); - } - - if (shieldAddressInfo != null) { - OutputPointInfo.Builder request = OutputPointInfo.newBuilder(); - - // ShieldNoteInfo noteInfo = shieldWrapper.getUtxoMapNote().get(shieldInputList.get(i)); - OutputPoint.Builder outPointBuild = OutputPoint.newBuilder(); - outPointBuild.setHash(ByteString.copyFrom(noteTx.getTxid().toByteArray())); - outPointBuild.setIndex(noteTx.getIndex()); - request.addOutPoints(outPointBuild.build()); - - // ShieldNoteInfo noteInfo = shieldWrapper.getUtxoMapNote().get(shieldInputList.get(i)); - - // String shieldAddress = noteInfo.getPaymentAddress(); - // ShieldAddressInfo addressInfo = - // shieldWrapper.getShieldAddressInfoMap().get(shieldAddress); - SpendingKey spendingKey = new SpendingKey(shieldAddressInfo.getSk()); - try { - ExpandedSpendingKey expandedSpendingKey = spendingKey.expandedSpendingKey(); - builder.setAsk(ByteString.copyFrom(expandedSpendingKey.getAsk())); - builder.setNsk(ByteString.copyFrom(expandedSpendingKey.getNsk())); - builder.setOvk(ByteString.copyFrom(expandedSpendingKey.getOvk())); - } catch (Exception e) { - System.out.println(e); - } - - Note.Builder noteBuild = Note.newBuilder(); - noteBuild.setPaymentAddress(shieldAddressInfo.getAddress()); - noteBuild.setValue(noteTx.getNote().getValue()); - noteBuild.setRcm(ByteString.copyFrom(noteTx.getNote().getRcm().toByteArray())); - noteBuild.setMemo(ByteString.copyFrom(noteTx.getNote().getMemo().toByteArray())); - - // System.out.println("address " + noteInfo.getPaymentAddress()); - // System.out.println("value " + noteInfo.getValue()); - // System.out.println("rcm " + ByteArray.toHexString(noteInfo.getR())); - // System.out.println("trxId " + noteInfo.getTrxId()); - // System.out.println("index " + noteInfo.getIndex()); - // System.out.println("meno " + new String(noteInfo.getMemo())); - - SpendNote.Builder spendNoteBuilder = SpendNote.newBuilder(); - spendNoteBuilder.setNote(noteBuild.build()); - try { - spendNoteBuilder.setAlpha(ByteString.copyFrom(org.tron.core.zen.note.Note.generateR())); - } catch (Exception e) { - System.out.println(e); - } - - IncrementalMerkleVoucherInfo merkleVoucherInfo = - blockingStubFull.getMerkleTreeVoucherInfo(request.build()); - spendNoteBuilder.setVoucher(merkleVoucherInfo.getVouchers(0)); - spendNoteBuilder.setPath(merkleVoucherInfo.getPaths(0)); - - builder.addShieldedSpends(spendNoteBuilder.build()); - - } else { - byte[] ovk = - ByteArray.fromHexString( - "030c8c2bc59fb3eb8afb047a8ea4b028743d23e7d38c6fa30908358431e2314d"); - builder.setOvk(ByteString.copyFrom(ovk)); - } - - if (shieldOutputList.size() > 0) { - for (int i = 0; i < shieldOutputList.size(); ++i) { - builder.addShieldedReceives( - ReceiveNote.newBuilder().setNote(shieldOutputList.get(i)).build()); - } - } - - TransactionExtention transactionExtention = - blockingStubFull.createShieldedTransaction(builder.build()); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - Any any = transaction.getRawData().getContract(0).getParameter(); - - try { - ShieldedTransferContract shieldedTransferContract = - any.unpack(ShieldedTransferContract.class); - if (shieldedTransferContract.getFromAmount() > 0 || fromAmount == 321321) { - transaction = signTransactionForShield(ecKey, transaction); - System.out.println( - "trigger txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - } else { - System.out.println( - "trigger txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - } - } catch (Exception e) { - System.out.println(e); - } - return broadcastTransaction(transaction, blockingStubFull).getResult(); - } - - /** constructor. */ - public static boolean sendShieldCoinWithoutAsk( - byte[] publicZenTokenOwnerAddress, - long fromAmount, - ShieldAddressInfo shieldAddressInfo, - NoteTx noteTx, - List shieldOutputList, - byte[] publicZenTokenToAddress, - long toAmount, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - PrivateParametersWithoutAsk.Builder builder = PrivateParametersWithoutAsk.newBuilder(); - if (!ByteUtil.isNullOrZeroArray(publicZenTokenOwnerAddress)) { - builder.setTransparentFromAddress(ByteString.copyFrom(publicZenTokenOwnerAddress)); - builder.setFromAmount(fromAmount); - } - if (!ByteUtil.isNullOrZeroArray(publicZenTokenToAddress)) { - builder.setTransparentToAddress(ByteString.copyFrom(publicZenTokenToAddress)); - builder.setToAmount(toAmount); - } - - byte[] ask = new byte[32]; - if (shieldAddressInfo != null) { - OutputPointInfo.Builder request = OutputPointInfo.newBuilder(); - - // ShieldNoteInfo noteInfo = shieldWrapper.getUtxoMapNote().get(shieldInputList.get(i)); - OutputPoint.Builder outPointBuild = OutputPoint.newBuilder(); - outPointBuild.setHash(ByteString.copyFrom(noteTx.getTxid().toByteArray())); - outPointBuild.setIndex(noteTx.getIndex()); - request.addOutPoints(outPointBuild.build()); - IncrementalMerkleVoucherInfo merkleVoucherInfo = - blockingStubFull.getMerkleTreeVoucherInfo(request.build()); - if (merkleVoucherInfo.getVouchersCount() != 1) { - System.out.println("Can't get all merkel tree, please check the notes."); - return false; - } - - // ShieldNoteInfo noteInfo = shieldWrapper.getUtxoMapNote().get(shieldInputList.get(i)); - - // String shieldAddress = noteInfo.getPaymentAddress(); - // ShieldAddressInfo addressInfo = - // shieldWrapper.getShieldAddressInfoMap().get(shieldAddress); - String shieldAddress = noteTx.getNote().getPaymentAddress(); - SpendingKey spendingKey = new SpendingKey(shieldAddressInfo.getSk()); - try { - ExpandedSpendingKey expandedSpendingKey = spendingKey.expandedSpendingKey(); - System.arraycopy(expandedSpendingKey.getAsk(), 0, ask, 0, 32); - builder.setAk( - ByteString.copyFrom(ExpandedSpendingKey.getAkFromAsk(expandedSpendingKey.getAsk()))); - builder.setNsk(ByteString.copyFrom(expandedSpendingKey.getNsk())); - builder.setOvk(ByteString.copyFrom(expandedSpendingKey.getOvk())); - } catch (Exception e) { - System.out.println(e); - } - - Note.Builder noteBuild = Note.newBuilder(); - noteBuild.setPaymentAddress(shieldAddressInfo.getAddress()); - noteBuild.setValue(noteTx.getNote().getValue()); - noteBuild.setRcm(ByteString.copyFrom(noteTx.getNote().getRcm().toByteArray())); - noteBuild.setMemo(ByteString.copyFrom(noteTx.getNote().getMemo().toByteArray())); - - // System.out.println("address " + noteInfo.getPaymentAddress()); - // System.out.println("value " + noteInfo.getValue()); - // System.out.println("rcm " + ByteArray.toHexString(noteInfo.getR())); - // System.out.println("trxId " + noteInfo.getTrxId()); - // System.out.println("index " + noteInfo.getIndex()); - // System.out.println("meno " + new String(noteInfo.getMemo())); - - SpendNote.Builder spendNoteBuilder = SpendNote.newBuilder(); - spendNoteBuilder.setNote(noteBuild.build()); - try { - spendNoteBuilder.setAlpha(ByteString.copyFrom(org.tron.core.zen.note.Note.generateR())); - } catch (Exception e) { - System.out.println(e); - } - - spendNoteBuilder.setVoucher(merkleVoucherInfo.getVouchers(0)); - spendNoteBuilder.setPath(merkleVoucherInfo.getPaths(0)); - - builder.addShieldedSpends(spendNoteBuilder.build()); - - } else { - byte[] ovk = - ByteArray.fromHexString( - "030c8c2bc59fb3eb8afb047a8ea4b028743d23e7d38c6fa30908358431e2314d"); - builder.setOvk(ByteString.copyFrom(ovk)); - } - - if (shieldOutputList.size() > 0) { - for (int i = 0; i < shieldOutputList.size(); ++i) { - builder.addShieldedReceives( - ReceiveNote.newBuilder().setNote(shieldOutputList.get(i)).build()); - } - } - - TransactionExtention transactionExtention = - blockingStubFull.createShieldedTransactionWithoutSpendAuthSig(builder.build()); - if (transactionExtention == null) { - System.out.println("sendShieldCoinWithoutAsk failure."); - return false; - } - BytesMessage trxHash = - blockingStubFull.getShieldTransactionHash(transactionExtention.getTransaction()); - if (trxHash == null || trxHash.getValue().toByteArray().length != 32) { - System.out.println("sendShieldCoinWithoutAsk get transaction hash failure."); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction.getRawData().getContract(0).getType() - != ContractType.ShieldedTransferContract) { - System.out.println("This method only for ShieldedTransferContract, please check!"); - return false; - } - Any any = transaction.getRawData().getContract(0).getParameter(); - Transaction transaction1 = transactionExtention.getTransaction(); - try { - ShieldedTransferContract shieldContract = any.unpack(ShieldedTransferContract.class); - List spendDescList = shieldContract.getSpendDescriptionList(); - ShieldedTransferContract.Builder contractBuild = - shieldContract.toBuilder().clearSpendDescription(); - for (int i = 0; i < spendDescList.size(); i++) { - - SpendAuthSigParameters.Builder builder1 = SpendAuthSigParameters.newBuilder(); - builder1.setAsk(ByteString.copyFrom(ask)); - builder1.setTxHash(ByteString.copyFrom(trxHash.getValue().toByteArray())); - builder1.setAlpha(builder.getShieldedSpends(i).getAlpha()); - SpendDescription.Builder spendDescription = spendDescList.get(i).toBuilder(); - BytesMessage authSig = blockingStubFull.createSpendAuthSig(builder1.build()); - spendDescription.setSpendAuthoritySignature( - ByteString.copyFrom(authSig.getValue().toByteArray())); - - contractBuild.addSpendDescription(spendDescription.build()); - } - - Transaction.raw.Builder rawBuilder = - transaction.toBuilder() - .getRawDataBuilder() - .clearContract() - .addContract( - Transaction.Contract.newBuilder() - .setType(ContractType.ShieldedTransferContract) - .setParameter(Any.pack(contractBuild.build())) - .build()); - - transaction = transaction.toBuilder().clearRawData().setRawData(rawBuilder).build(); - - transactionExtention = transactionExtention.toBuilder().setTransaction(transaction).build(); - - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - transaction1 = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - if (transaction1.getRawData().getContract(0).getType() - != ContractType.ShieldedTransferContract) { - transaction1 = signTransaction(ecKey, transaction1); - } else { - Any any1 = transaction1.getRawData().getContract(0).getParameter(); - ShieldedTransferContract shieldedTransferContract = - any1.unpack(ShieldedTransferContract.class); - if (shieldedTransferContract.getFromAmount() > 0) { - transaction1 = signTransactionForShield(ecKey, transaction1); - System.out.println( - "trigger txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction1.getRawData().toByteArray()))); - } - } - } catch (Exception e) { - System.out.println(e); - } - System.out.println( - "trigger txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction1.getRawData().toByteArray()))); - return broadcastTransaction(transaction1, blockingStubFull).getResult(); - } - - /** constructor. */ - public static List addShieldOutputList( - List shieldOutList, String shieldToAddress, String toAmountString, String menoString) { - String shieldAddress = shieldToAddress; - String amountString = toAmountString; - if (menoString.equals("null")) { - menoString = ""; - } - long shieldAmount = 0; - if (!StringUtil.isNullOrEmpty(amountString)) { - shieldAmount = Long.valueOf(amountString); - } - - Note.Builder noteBuild = Note.newBuilder(); - noteBuild.setPaymentAddress(shieldAddress); - noteBuild.setPaymentAddress(shieldAddress); - noteBuild.setValue(shieldAmount); - try { - noteBuild.setRcm(ByteString.copyFrom(org.tron.core.zen.note.Note.generateR())); - } catch (Exception e) { - System.out.println(e); - } - noteBuild.setMemo(ByteString.copyFrom(menoString.getBytes())); - shieldOutList.add(noteBuild.build()); - // logger.info(shieldOutList.toString()); - return shieldOutList; - } - - /** constructor. */ - public static Optional generateShieldAddress() { - ShieldAddressInfo addressInfo = new ShieldAddressInfo(); - try { - DiversifierT diversifier = DiversifierT.random(); - SpendingKey spendingKey = SpendingKey.random(); - FullViewingKey fullViewingKey = spendingKey.fullViewingKey(); - IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - PaymentAddress paymentAddress = incomingViewingKey.address(diversifier).get(); - - addressInfo.setSk(spendingKey.getValue()); - addressInfo.setD(diversifier); - addressInfo.setIvk(incomingViewingKey.getValue()); - addressInfo.setOvk(fullViewingKey.getOvk()); - addressInfo.setPkD(paymentAddress.getPkD()); - - if (addressInfo.validateCheck()) { - return Optional.of(addressInfo); - } - } catch (Exception e) { - e.printStackTrace(); - } - - return Optional.empty(); - } - - /** constructor. */ - public static DecryptNotes listShieldNote( - Optional shieldAddressInfo, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Long startBlockNum = 0L; - if (currentBlockNum > 100) { - startBlockNum = currentBlockNum - 100; - } - logger.info(ByteArray.toHexString(shieldAddressInfo.get().ivk)); - IvkDecryptParameters.Builder builder = IvkDecryptParameters.newBuilder(); - builder.setStartBlockIndex(startBlockNum); - builder.setEndBlockIndex(currentBlockNum + 1); - builder.setIvk(ByteString.copyFrom(shieldAddressInfo.get().getIvk())); - DecryptNotes notes = blockingStubFull.scanNoteByIvk(builder.build()); - logger.info(notes.toString()); - return notes; - } - - /** constructor. */ - public static DecryptNotes getShieldNotesByIvk( - Optional shieldAddressInfo, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Long startBlockNum = 0L; - if (currentBlockNum > 100) { - startBlockNum = currentBlockNum - 100; - } - // startBlockNum = 0L; - logger.info("ivk:" + ByteArray.toHexString(shieldAddressInfo.get().ivk)); - IvkDecryptParameters.Builder builder = IvkDecryptParameters.newBuilder(); - builder.setStartBlockIndex(startBlockNum + 1); - builder.setEndBlockIndex(currentBlockNum + 1); - builder.setIvk(ByteString.copyFrom(shieldAddressInfo.get().getIvk())); - DecryptNotes notes = blockingStubFull.scanNoteByIvk(builder.build()); - logger.info(notes.toString()); - return notes; - } - - /** constructor. */ - public static DecryptNotesMarked getShieldNotesAndMarkByIvk( - Optional shieldAddressInfo, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Long startBlockNum = 0L; - if (currentBlockNum > 100) { - startBlockNum = currentBlockNum - 100; - } - // startBlockNum = 0L; - logger.info("ivk:" + ByteArray.toHexString(shieldAddressInfo.get().ivk)); - try { - IvkDecryptAndMarkParameters.Builder builder = IvkDecryptAndMarkParameters.newBuilder(); - builder.setStartBlockIndex(startBlockNum + 1); - builder.setEndBlockIndex(currentBlockNum + 1); - builder.setIvk(ByteString.copyFrom(shieldAddressInfo.get().getIvk())); - builder.setAk(ByteString.copyFrom(shieldAddressInfo.get().getFullViewingKey().getAk())); - builder.setNk(ByteString.copyFrom(shieldAddressInfo.get().getFullViewingKey().getNk())); - DecryptNotesMarked decryptNotes = blockingStubFull.scanAndMarkNoteByIvk(builder.build()); - logger.info(decryptNotes.toString()); - return decryptNotes; - } catch (Exception e) { - logger.info(e.toString()); - return null; - } - } - - /** constructor. */ - public static DecryptNotesMarked getShieldNotesAndMarkByIvkOnSolidity( - Optional shieldAddressInfo, - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) { - Block currentBlock = - blockingStubSolidity.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Long startBlockNum = 0L; - if (currentBlockNum > 100) { - startBlockNum = currentBlockNum - 100; - } - // startBlockNum = 0L; - logger.info("ivk:" + ByteArray.toHexString(shieldAddressInfo.get().ivk)); - try { - IvkDecryptAndMarkParameters.Builder builder = IvkDecryptAndMarkParameters.newBuilder(); - builder.setStartBlockIndex(startBlockNum + 1); - builder.setEndBlockIndex(currentBlockNum + 1); - builder.setIvk(ByteString.copyFrom(shieldAddressInfo.get().getIvk())); - builder.setAk(ByteString.copyFrom(shieldAddressInfo.get().getFullViewingKey().getAk())); - builder.setNk(ByteString.copyFrom(shieldAddressInfo.get().getFullViewingKey().getNk())); - DecryptNotesMarked decryptNotes = blockingStubSolidity.scanAndMarkNoteByIvk(builder.build()); - logger.info(decryptNotes.toString()); - return decryptNotes; - } catch (Exception e) { - logger.info(e.toString()); - return null; - } - } - - /** constructor. */ - public static DecryptNotes getShieldNotesByIvkOnSolidity( - Optional shieldAddressInfo, - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) { - Block currentBlock = - blockingStubSolidity.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Long startBlockNum = 0L; - if (currentBlockNum > 100) { - startBlockNum = currentBlockNum - 100; - } - IvkDecryptParameters.Builder builder = IvkDecryptParameters.newBuilder(); - builder.setStartBlockIndex(startBlockNum); - builder.setEndBlockIndex(currentBlockNum); - builder.setIvk(ByteString.copyFrom(shieldAddressInfo.get().getIvk())); - DecryptNotes notes = blockingStubSolidity.scanNoteByIvk(builder.build()); - logger.info(notes.toString()); - return notes; - } - - /** constructor. */ - public static DecryptNotes getShieldNotesByOvk( - Optional shieldAddressInfo, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Long startBlockNum = 0L; - if (currentBlockNum > 100) { - startBlockNum = currentBlockNum - 100; - } - logger.info("ovk:" + ByteArray.toHexString(shieldAddressInfo.get().ovk)); - OvkDecryptParameters.Builder builder = OvkDecryptParameters.newBuilder(); - builder.setStartBlockIndex(startBlockNum + 1); - builder.setEndBlockIndex(currentBlockNum + 1); - builder.setOvk(ByteString.copyFrom(shieldAddressInfo.get().getOvk())); - DecryptNotes notes = blockingStubFull.scanNoteByOvk(builder.build()); - logger.info(notes.toString()); - return notes; - } - - /** constructor. */ - public static DecryptNotes getShieldNotesByOvkOnSolidity( - Optional shieldAddressInfo, - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) { - Block currentBlock = - blockingStubSolidity.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Long startBlockNum = 0L; - if (currentBlockNum > 100) { - startBlockNum = currentBlockNum - 100; - } - OvkDecryptParameters.Builder builder = OvkDecryptParameters.newBuilder(); - builder.setStartBlockIndex(startBlockNum); - builder.setEndBlockIndex(currentBlockNum); - builder.setOvk(ByteString.copyFrom(shieldAddressInfo.get().getOvk())); - DecryptNotes notes = blockingStubSolidity.scanNoteByOvk(builder.build()); - logger.info(notes.toString()); - return notes; - } - - /** constructor. */ - public static String getMemo(Note note) { - return ZenUtils.getMemo(note.getMemo().toByteArray()); - } - - /** constructor. */ - public static SpendResult getSpendResult( - ShieldAddressInfo shieldAddressInfo, - NoteTx noteTx, - WalletGrpc.WalletBlockingStub blockingStubFull) { - - OutputPointInfo.Builder request = OutputPointInfo.newBuilder(); - OutputPoint.Builder outPointBuild = OutputPoint.newBuilder(); - outPointBuild.setHash(ByteString.copyFrom(noteTx.getTxid().toByteArray())); - outPointBuild.setIndex(noteTx.getIndex()); - request.addOutPoints(outPointBuild.build()); - Optional merkleVoucherInfo = - Optional.of(blockingStubFull.getMerkleTreeVoucherInfo(request.build())); - - if (merkleVoucherInfo.isPresent() && merkleVoucherInfo.get().getVouchersCount() > 0) { - NoteParameters.Builder builder = NoteParameters.newBuilder(); - try { - builder.setAk(ByteString.copyFrom(shieldAddressInfo.getFullViewingKey().getAk())); - builder.setNk(ByteString.copyFrom(shieldAddressInfo.getFullViewingKey().getNk())); - logger.info("AK:" + ByteArray.toHexString(shieldAddressInfo.getFullViewingKey().getAk())); - logger.info("NK:" + ByteArray.toHexString(shieldAddressInfo.getFullViewingKey().getNk())); - } catch (Exception e) { - Assert.assertTrue(1 == 1); - } - - Note.Builder noteBuild = Note.newBuilder(); - noteBuild.setPaymentAddress(shieldAddressInfo.getAddress()); - noteBuild.setValue(noteTx.getNote().getValue()); - noteBuild.setRcm(ByteString.copyFrom(noteTx.getNote().getRcm().toByteArray())); - noteBuild.setMemo(ByteString.copyFrom(noteTx.getNote().getMemo().toByteArray())); - builder.setNote(noteBuild.build()); - builder.setTxid(ByteString.copyFrom(noteTx.getTxid().toByteArray())); - builder.setIndex(noteTx.getIndex()); - // builder.setVoucher(merkleVoucherInfo.getVouchers(0)); - - SpendResult result = blockingStubFull.isSpend(builder.build()); - return result; - } - return null; - } - - /** constructor. */ - public static SpendResult getSpendResultOnSolidity( - ShieldAddressInfo shieldAddressInfo, - NoteTx noteTx, - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) { - OutputPointInfo.Builder request = OutputPointInfo.newBuilder(); - OutputPoint.Builder outPointBuild = OutputPoint.newBuilder(); - outPointBuild.setHash(ByteString.copyFrom(noteTx.getTxid().toByteArray())); - outPointBuild.setIndex(noteTx.getIndex()); - request.addOutPoints(outPointBuild.build()); - Optional merkleVoucherInfo = - Optional.of(blockingStubSolidity.getMerkleTreeVoucherInfo(request.build())); - - if (merkleVoucherInfo.isPresent() && merkleVoucherInfo.get().getVouchersCount() > 0) { - NoteParameters.Builder builder = NoteParameters.newBuilder(); - try { - builder.setAk(ByteString.copyFrom(shieldAddressInfo.getFullViewingKey().getAk())); - builder.setNk(ByteString.copyFrom(shieldAddressInfo.getFullViewingKey().getNk())); - } catch (Exception e) { - Assert.assertTrue(1 == 1); - } - Note.Builder noteBuild = Note.newBuilder(); - noteBuild.setPaymentAddress(shieldAddressInfo.getAddress()); - noteBuild.setValue(noteTx.getNote().getValue()); - noteBuild.setRcm(ByteString.copyFrom(noteTx.getNote().getRcm().toByteArray())); - noteBuild.setMemo(ByteString.copyFrom(noteTx.getNote().getMemo().toByteArray())); - builder.setNote(noteBuild.build()); - builder.setTxid(ByteString.copyFrom(noteTx.getTxid().toByteArray())); - builder.setIndex(noteTx.getIndex()); - // builder.setVoucher(merkleVoucherInfo.getVouchers(0)); - - SpendResult result = blockingStubSolidity.isSpend(builder.build()); - return result; - } - return null; - } - - /** constructor. */ - public static String getShieldNullifier( - ShieldAddressInfo shieldAddressInfo, - NoteTx noteTx, - WalletGrpc.WalletBlockingStub blockingStubFull) { - OutputPointInfo.Builder request = OutputPointInfo.newBuilder(); - OutputPoint.Builder outPointBuild = OutputPoint.newBuilder(); - outPointBuild.setHash(ByteString.copyFrom(noteTx.getTxid().toByteArray())); - outPointBuild.setIndex(noteTx.getIndex()); - request.addOutPoints(outPointBuild.build()); - IncrementalMerkleVoucherInfo merkleVoucherInfo = - blockingStubFull.getMerkleTreeVoucherInfo(request.build()); - if (merkleVoucherInfo.getVouchersCount() < 1) { - System.out.println("get merkleVoucherInfo failure."); - return null; - } - Note.Builder noteBuild = Note.newBuilder(); - noteBuild.setPaymentAddress(shieldAddressInfo.getAddress()); - noteBuild.setValue(noteTx.getNote().getValue()); - noteBuild.setRcm(ByteString.copyFrom(noteTx.getNote().getRcm().toByteArray())); - noteBuild.setMemo(ByteString.copyFrom(noteTx.getNote().getMemo().toByteArray())); - - String shieldAddress = noteTx.getNote().getPaymentAddress(); - SpendingKey spendingKey = new SpendingKey(shieldAddressInfo.getSk()); - try { - // TODO - FullViewingKey fullViewingKey = spendingKey.fullViewingKey(); - NfParameters.Builder builder = NfParameters.newBuilder(); - builder.setNote(noteBuild.build()); - builder.setVoucher(merkleVoucherInfo.getVouchers(0)); - builder.setAk(ByteString.copyFrom(fullViewingKey.getAk())); - builder.setNk(ByteString.copyFrom(fullViewingKey.getNk())); - - BytesMessage nullifier = blockingStubFull.createShieldNullifier(builder.build()); - return ByteArray.toHexString(nullifier.getValue().toByteArray()); - - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - /** constructor. */ - public static String sendShieldCoinGetTxid( - byte[] publicZenTokenOwnerAddress, - long fromAmount, - ShieldAddressInfo shieldAddressInfo, - NoteTx noteTx, - List shieldOutputList, - byte[] publicZenTokenToAddress, - long toAmount, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - PrivateParameters.Builder builder = PrivateParameters.newBuilder(); - if (!ByteUtil.isNullOrZeroArray(publicZenTokenOwnerAddress)) { - builder.setTransparentFromAddress(ByteString.copyFrom(publicZenTokenOwnerAddress)); - builder.setFromAmount(fromAmount); - } - if (!ByteUtil.isNullOrZeroArray(publicZenTokenToAddress)) { - builder.setTransparentToAddress(ByteString.copyFrom(publicZenTokenToAddress)); - builder.setToAmount(toAmount); - } - - if (shieldAddressInfo != null) { - OutputPointInfo.Builder request = OutputPointInfo.newBuilder(); - - // ShieldNoteInfo noteInfo = shieldWrapper.getUtxoMapNote().get(shieldInputList.get(i)); - OutputPoint.Builder outPointBuild = OutputPoint.newBuilder(); - outPointBuild.setHash(ByteString.copyFrom(noteTx.getTxid().toByteArray())); - outPointBuild.setIndex(noteTx.getIndex()); - request.addOutPoints(outPointBuild.build()); - - // ShieldNoteInfo noteInfo = shieldWrapper.getUtxoMapNote().get(shieldInputList.get(i)); - - // String shieldAddress = noteInfo.getPaymentAddress(); - // ShieldAddressInfo addressInfo = - // shieldWrapper.getShieldAddressInfoMap().get(shieldAddress); - SpendingKey spendingKey = new SpendingKey(shieldAddressInfo.getSk()); - try { - ExpandedSpendingKey expandedSpendingKey = spendingKey.expandedSpendingKey(); - builder.setAsk(ByteString.copyFrom(expandedSpendingKey.getAsk())); - builder.setNsk(ByteString.copyFrom(expandedSpendingKey.getNsk())); - builder.setOvk(ByteString.copyFrom(expandedSpendingKey.getOvk())); - } catch (Exception e) { - System.out.println(e); - } - - Note.Builder noteBuild = Note.newBuilder(); - noteBuild.setPaymentAddress(shieldAddressInfo.getAddress()); - noteBuild.setValue(noteTx.getNote().getValue()); - noteBuild.setRcm(ByteString.copyFrom(noteTx.getNote().getRcm().toByteArray())); - noteBuild.setMemo(ByteString.copyFrom(noteTx.getNote().getMemo().toByteArray())); - - // System.out.println("address " + noteInfo.getPaymentAddress()); - // System.out.println("value " + noteInfo.getValue()); - // System.out.println("rcm " + ByteArray.toHexString(noteInfo.getR())); - // System.out.println("trxId " + noteInfo.getTrxId()); - // System.out.println("index " + noteInfo.getIndex()); - // System.out.println("meno " + new String(noteInfo.getMemo())); - - SpendNote.Builder spendNoteBuilder = SpendNote.newBuilder(); - spendNoteBuilder.setNote(noteBuild.build()); - try { - spendNoteBuilder.setAlpha(ByteString.copyFrom(org.tron.core.zen.note.Note.generateR())); - } catch (Exception e) { - System.out.println(e); - } - - IncrementalMerkleVoucherInfo merkleVoucherInfo = - blockingStubFull.getMerkleTreeVoucherInfo(request.build()); - spendNoteBuilder.setVoucher(merkleVoucherInfo.getVouchers(0)); - spendNoteBuilder.setPath(merkleVoucherInfo.getPaths(0)); - - builder.addShieldedSpends(spendNoteBuilder.build()); - - } else { - byte[] ovk = - ByteArray.fromHexString( - "030c8c2bc59fb3eb8afb047a8ea4b028743d23e7d38c6fa30908358431e2314d"); - builder.setOvk(ByteString.copyFrom(ovk)); - } - - if (shieldOutputList.size() > 0) { - for (int i = 0; i < shieldOutputList.size(); ++i) { - builder.addShieldedReceives( - ReceiveNote.newBuilder().setNote(shieldOutputList.get(i)).build()); - } - } - - TransactionExtention transactionExtention = - blockingStubFull.createShieldedTransaction(builder.build()); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - Any any = transaction.getRawData().getContract(0).getParameter(); - - try { - ShieldedTransferContract shieldedTransferContract = - any.unpack(ShieldedTransferContract.class); - if (shieldedTransferContract.getFromAmount() > 0) { - transaction = signTransactionForShield(ecKey, transaction); - System.out.println( - "trigger txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - } else { - System.out.println( - "trigger txid = " - + ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()))); - } - } catch (Exception e) { - System.out.println(e); - } - broadcastTransaction(transaction, blockingStubFull); - return ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray())); - } - - /** constructor. */ - public static byte[] decode58Check(String input) { - byte[] decodeCheck = org.tron.common.utils.Base58.decode(input); - if (decodeCheck.length <= 4) { - return null; - } - byte[] decodeData = new byte[decodeCheck.length - 4]; - System.arraycopy(decodeCheck, 0, decodeData, 0, decodeData.length); - byte[] hash0 = Sha256Hash.hash(CommonParameter.getInstance().isECKeyCryptoEngine(), decodeData); - byte[] hash1 = Sha256Hash.hash(CommonParameter.getInstance().isECKeyCryptoEngine(), hash0); - if (hash1[0] == decodeCheck[decodeData.length] - && hash1[1] == decodeCheck[decodeData.length + 1] - && hash1[2] == decodeCheck[decodeData.length + 2] - && hash1[3] == decodeCheck[decodeData.length + 3]) { - return decodeData; - } - return null; - } - - /** constructor. */ - public static void freedResource( - byte[] fromAddress, - String priKey, - byte[] toAddress, - WalletGrpc.WalletBlockingStub blockingStubFull) { - long balance = PublicMethed.queryAccount(fromAddress, blockingStubFull).getBalance(); - sendcoin(toAddress, balance - 500000, fromAddress, priKey, blockingStubFull); - } - - /** constructor. */ - public static String parametersString(List parameters) { - String[] inputArr = new String[parameters.size()]; - int i = 0; - for (Object parameter : parameters) { - if (parameter instanceof List) { - StringBuilder sb = new StringBuilder(); - for (Object item : (List) parameter) { - if (sb.length() != 0) { - sb.append(","); - } - sb.append("\"").append(item).append("\""); - } - inputArr[i++] = "[" + sb.toString() + "]"; - } else { - inputArr[i++] = - (parameter instanceof String) ? ("\"" + parameter + "\"") : ("" + parameter); - } - } - String input = StringUtils.join(inputArr, ','); - return input; - } - - /** constructor. */ - public static String bytes32ToString(byte[] bytes) { - if (bytes == null) { - return "null"; - } - int imax = bytes.length - 1; - if (imax == -1) { - return ""; - } - - StringBuilder b = new StringBuilder(); - for (int i = 0; ; i++) { - b.append(bytes[i]); - if (i == imax) { - return b.toString(); - } - } - } - - /** constructor. */ - public static Return transferAssetForReturn( - byte[] to, - byte[] assertName, - long amount, - byte[] address, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferAssetContract contract = builder.build(); - TransactionExtention transaction = blockingStubFull.transferAsset2(contract); - - if (transaction == null) { - return transaction.getResult(); - } - Return ret = transaction.getResult(); - return ret; - } - - /** constructor. */ - public static Return sendcoinForReturn( - byte[] to, - long amount, - byte[] owner, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - // String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferContract.Builder builder = TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferContract contract = builder.build(); - TransactionExtention transaction = blockingStubFull.createTransaction2(contract); - if (transaction == null) { - return transaction.getResult(); - } - Return ret = transaction.getResult(); - return ret; - } - - /** constructor. */ - public static Transaction sendcoinForTransaction( - byte[] to, - long amount, - byte[] owner, - String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - // String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferContract.Builder builder = TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferContract contract = builder.build(); - TransactionExtention extention = blockingStubFull.createTransaction2(contract); - Protocol.Transaction transaction = extention.getTransaction(); - return transaction; - } - - /** constructor. */ - public static String marketSellAsset( - byte[] owner, - String priKey, - byte[] sellTokenId, - long sellTokenQuantity, - byte[] buyTokenId, - long buyTokenQuantity, - WalletGrpc.WalletBlockingStub blockingStubFull) { - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - MarketContract.MarketSellAssetContract.Builder builder = - MarketContract.MarketSellAssetContract.newBuilder(); - builder - .setOwnerAddress(ByteString.copyFrom(owner)) - .setSellTokenId(ByteString.copyFrom(sellTokenId)) - .setSellTokenQuantity(sellTokenQuantity) - .setBuyTokenId(ByteString.copyFrom(buyTokenId)) - .setBuyTokenQuantity(buyTokenQuantity); - - TransactionExtention transactionExtention = blockingStubFull.marketSellAsset(builder.build()); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - - if (transaction.getRawData().getContract(0).getType() - == ContractType.ShieldedTransferContract) { - return null; - } - - transaction = signTransaction(ecKey, transaction); - broadcastTransaction(transaction, blockingStubFull); - - String txid = - ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray())); - - System.out.println("trigger txid = " + txid); - return txid; - } - - /** constructor. */ - public static Return marketSellAssetGetResposne( - byte[] owner, - String priKey, - byte[] sellTokenId, - long sellTokenQuantity, - byte[] buyTokenId, - long buyTokenQuantity, - WalletGrpc.WalletBlockingStub blockingStubFull) { - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - MarketContract.MarketSellAssetContract.Builder builder = - MarketContract.MarketSellAssetContract.newBuilder(); - builder - .setOwnerAddress(ByteString.copyFrom(owner)) - .setSellTokenId(ByteString.copyFrom(sellTokenId)) - .setSellTokenQuantity(sellTokenQuantity) - .setBuyTokenId(ByteString.copyFrom(buyTokenId)) - .setBuyTokenQuantity(buyTokenQuantity); - - TransactionExtention transactionExtention = blockingStubFull.marketSellAsset(builder.build()); - - return transactionExtention.getResult(); - } - - /** constructor. */ - public static String marketCancelOrder( - byte[] owner, String priKey, byte[] orderId, WalletGrpc.WalletBlockingStub blockingStubFull) { - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - MarketContract.MarketCancelOrderContract.Builder builder = - MarketContract.MarketCancelOrderContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)).setOrderId(ByteString.copyFrom(orderId)); - - TransactionExtention transactionExtention = blockingStubFull.marketCancelOrder(builder.build()); - - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret.getMessage().toStringUtf8(); - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - - if (transaction.getRawData().getContract(0).getType() - == ContractType.ShieldedTransferContract) { - return null; - } - - transaction = signTransaction(ecKey, transaction); - broadcastTransaction(transaction, blockingStubFull); - - String txid = - ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray())); - - System.out.println("trigger txid = " + txid); - - return txid; - } - - /** constructor. */ - public static Return marketCancelOrderGetResposne( - byte[] owner, String priKey, byte[] orderId, WalletGrpc.WalletBlockingStub blockingStubFull) { - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - MarketContract.MarketCancelOrderContract.Builder builder = - MarketContract.MarketCancelOrderContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)).setOrderId(ByteString.copyFrom(orderId)); - - TransactionExtention transactionExtention = blockingStubFull.marketCancelOrder(builder.build()); - - if (transactionExtention == null) { - return null; - } - return transactionExtention.getResult(); - } - - /** constructor. */ - public static Optional getMarketOrderByAccount( - byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - BytesMessage request = BytesMessage.newBuilder().setValue(addressBs).build(); - - Protocol.MarketOrderList marketOrderList; - marketOrderList = blockingStubFull.getMarketOrderByAccount(request); - return Optional.ofNullable(marketOrderList); - } - - /** constructor. */ - public static Optional getMarketOrderByAccountSolidity( - byte[] address, WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) { - ByteString addressBs = ByteString.copyFrom(address); - BytesMessage request = BytesMessage.newBuilder().setValue(addressBs).build(); - - Protocol.MarketOrderList marketOrderList; - marketOrderList = blockingStubSolidity.getMarketOrderByAccount(request); - return Optional.ofNullable(marketOrderList); - } - - /** constructor. */ - public static Optional getMarketOrderById( - byte[] order, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString orderBytes = ByteString.copyFrom(order); - BytesMessage request = BytesMessage.newBuilder().setValue(orderBytes).build(); - Protocol.MarketOrder orderPair = blockingStubFull.getMarketOrderById(request); - return Optional.ofNullable(orderPair); - } - - /** constructor. */ - public static Optional getMarketOrderByIdSolidity( - byte[] order, WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) { - ByteString orderBytes = ByteString.copyFrom(order); - BytesMessage request = BytesMessage.newBuilder().setValue(orderBytes).build(); - Protocol.MarketOrder orderPair = blockingStubSolidity.getMarketOrderById(request); - return Optional.ofNullable(orderPair); - } - - /** constructor. */ - public static Optional getMarketPriceByPair( - byte[] sellTokenId, byte[] buyTokenId, WalletGrpc.WalletBlockingStub blockingStubFull) { - Protocol.MarketOrderPair request = - Protocol.MarketOrderPair.newBuilder() - .setSellTokenId(ByteString.copyFrom(sellTokenId)) - .setBuyTokenId(ByteString.copyFrom(buyTokenId)) - .build(); - - Protocol.MarketPriceList marketPriceList = blockingStubFull.getMarketPriceByPair(request); - return Optional.ofNullable(marketPriceList); - } - - /** constructor. */ - public static Optional getMarketOrderListByPair( - byte[] sellTokenId, byte[] buyTokenId, WalletGrpc.WalletBlockingStub blockingStubFull) { - Protocol.MarketOrderPair request = - Protocol.MarketOrderPair.newBuilder() - .setSellTokenId(ByteString.copyFrom(sellTokenId)) - .setBuyTokenId(ByteString.copyFrom(buyTokenId)) - .build(); - - Protocol.MarketOrderList marketOrderList = blockingStubFull.getMarketOrderListByPair(request); - return Optional.ofNullable(marketOrderList); - } - - /** constructor. */ - public static Optional getMarketOrderListByPairSolidity( - byte[] sellTokenId, - byte[] buyTokenId, - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) { - Protocol.MarketOrderPair request = - Protocol.MarketOrderPair.newBuilder() - .setSellTokenId(ByteString.copyFrom(sellTokenId)) - .setBuyTokenId(ByteString.copyFrom(buyTokenId)) - .build(); - - Protocol.MarketOrderList marketOrderList = - blockingStubSolidity.getMarketOrderListByPair(request); - return Optional.ofNullable(marketOrderList); - } - - /** constructor. */ - public static Optional getMarketPairList( - WalletGrpc.WalletBlockingStub blockingStubFull) { - Protocol.MarketOrderPairList marketOrderList = - blockingStubFull.getMarketPairList(EmptyMessage.newBuilder().build()); - return Optional.ofNullable(marketOrderList); - } - - /** constructor. */ - public static Optional getMarketPairListSolidity( - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) { - Protocol.MarketOrderPairList marketOrderList = - blockingStubSolidity.getMarketPairList(EmptyMessage.newBuilder().build()); - return Optional.ofNullable(marketOrderList); - } - - /** constructor. */ - public static String stringToHexString(String s) { - String str = ""; - for (int i = 0; i < s.length(); i++) { - int ch = s.charAt(i); - String s4 = Integer.toHexString(ch); - str = str + s4; - } - return str; - } - - /** constructor. */ - public static String hexStringToString(String s) { - if (s == null || s.equals("")) { - return null; - } - s = s.replace(" ", ""); - byte[] baKeyword = new byte[s.length() / 2]; - for (int i = 0; i < baKeyword.length; i++) { - try { - baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16)); - } catch (Exception e) { - e.printStackTrace(); - } - } - try { - s = new String(baKeyword, "gbk"); - new String(); - } catch (Exception e1) { - e1.printStackTrace(); - } - return s; - } - - /** constructor. */ - public static String removeAll0sAtTheEndOfHexStr(String s) { - return s.replaceAll("(00)+$", ""); - } - - /** constructor. */ - public static String replaceCode(String code, String address) { - if (code.indexOf("__$") == -1) { - return code; - } else { - int index = code.indexOf("_"); - String oldStr = code.substring(index - 1, index + 39); - Pattern p = Pattern.compile(oldStr); - Matcher m = p.matcher(code); - String result = m.replaceAll(address); - return result; - } - } - - /** constructor. */ - public static Map getAllowance2( - Long startNum, Long endNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - final String blackHole = - Configuration.getByPath("testng.conf").getString("defaultParameter.blackHoleAddress"); - Long totalCount = 0L; - Map witnessBlockCount = new HashMap<>(); - Map witnessBrokerage = new HashMap<>(); - Map witnessVoteCount = new HashMap<>(); - Map witnessAllowance = new HashMap<>(); - List witnessList = - PublicMethed.listWitnesses(blockingStubFull).get().getWitnessesList(); - for (Protocol.Witness witness : witnessList) { - witnessVoteCount.put( - ByteArray.toHexString(witness.getAddress().toByteArray()), witness.getVoteCount()); - GrpcAPI.BytesMessage bytesMessage = - GrpcAPI.BytesMessage.newBuilder().setValue(witness.getAddress()).build(); - Long brokerager = blockingStubFull.getBrokerageInfo(bytesMessage).getNum(); - witnessBrokerage.put(ByteArray.toHexString(witness.getAddress().toByteArray()), brokerager); - totalCount += witness.getVoteCount(); - } - Optional infoById = null; - for (Long k = startNum; k < endNum; k++) { - String witnessAdd = - ByteArray.toHexString( - PublicMethed.getBlock(k, blockingStubFull) - .getBlockHeader() - .getRawData() - .getWitnessAddress() - .toByteArray()); - witnessBlockCount.put(witnessAdd, witnessBlockCount.getOrDefault(witnessAdd, 0) + 1); - List transList = - PublicMethed.getBlock(k, blockingStubFull).getTransactionsList(); - for (Transaction tem : transList) { - String txid = - ByteArray.toHexString( - Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), - tem.getRawData().toByteArray())); - logger.info("----ss txid:" + txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long packingFee = infoById.get().getPackingFee(); - - witnessAllowance.put( - witnessAdd, witnessAllowance.getOrDefault(witnessAdd, 0L) + packingFee); - } - } - - logger.info("========totalCount:" + totalCount); - List chainParaList = - blockingStubFull - .getChainParameters(EmptyMessage.newBuilder().build()) - .getChainParameterList(); - Long witness127PayPerBlock = 0L; - Long witnessPayPerBlock = 0L; - for (Protocol.ChainParameters.ChainParameter para : chainParaList) { - if ("getWitness127PayPerBlock".equals(para.getKey())) { - witness127PayPerBlock = para.getValue(); - } - if ("getWitnessPayPerBlock".equals(para.getKey())) { - witnessPayPerBlock = para.getValue(); - } - } - logger.info( - "witness127PayPerBlock:" - + witness127PayPerBlock - + "\n witnessPayPerBlock:" - + witnessPayPerBlock); - - for (Map.Entry entry : witnessBrokerage.entrySet()) { - logger.info("-----witnessBrokerage " + entry.getKey() + " : " + entry.getValue()); - } - for (Map.Entry entry : witnessVoteCount.entrySet()) { - logger.info("-----witnessVoteCount " + entry.getKey() + " : " + entry.getValue()); - } - for (Map.Entry entry : witnessBlockCount.entrySet()) { - logger.info("-----witnessBlockCount " + entry.getKey() + " : " + entry.getValue()); - } - - for (Map.Entry entry : witnessVoteCount.entrySet()) { - String witnessAdd = entry.getKey(); - logger.info( - "----witnessAdd:" - + witnessAdd - + " block count:" - + witnessBlockCount.get(witnessAdd) - + " all: " - + witnessAllowance.getOrDefault(witnessAdd, 0L)); - Long pay = - (witnessBlockCount.get(witnessAdd) * witnessPayPerBlock - + (endNum - startNum) * witness127PayPerBlock * entry.getValue() / totalCount - + witnessAllowance.getOrDefault(witnessAdd, 0L)) - * witnessBrokerage.get(witnessAdd) - / 100; - - witnessAllowance.put(witnessAdd, pay); - logger.info("****** " + witnessAdd + " : " + pay); - } - return witnessAllowance; - } - - public static String getContractStringMsg(byte[] contractMsgArray) { - int resultLenth = ByteArray.toInt(ByteArray.subArray(contractMsgArray, 32, 64)); - return ByteArray.toStr(ByteArray.subArray(contractMsgArray, 64, 64 + resultLenth)); - } - - /** constructor. */ - public boolean updateBrokerage( - byte[] owner, int brokerage, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - UpdateBrokerageContract.Builder updateBrokerageContract = UpdateBrokerageContract.newBuilder(); - updateBrokerageContract.setOwnerAddress(ByteString.copyFrom(owner)).setBrokerage(brokerage); - TransactionExtention transactionExtention = - blockingStubFull.updateBrokerage(updateBrokerageContract.build()); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println( - "Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - - return response.getResult(); - } - - /** constructor. */ - public static Long getAccountBalance( - Protocol.Block block, byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - final Long blockNum = block.getBlockHeader().getRawData().getNumber(); - BlockId blockId = - new BlockId( - org.tron.common.utils.Sha256Hash.of( - CommonParameter.getInstance().isECKeyCryptoEngine(), - block.getBlockHeader().getRawData().toByteArray()), - block.getBlockHeader().getRawData().getNumber()); - - BalanceContract.AccountIdentifier accountIdentifier = - BalanceContract.AccountIdentifier.newBuilder() - .setAddress(ByteString.copyFrom(address)) - .build(); - BalanceContract.BlockBalanceTrace.BlockIdentifier blockIdentifier = - BalanceContract.BlockBalanceTrace.BlockIdentifier.newBuilder() - .setHash(blockId.getByteString()) - .setNumber(blockNum) - .build(); - - BalanceContract.AccountBalanceRequest accountBalanceRequest = - BalanceContract.AccountBalanceRequest.newBuilder() - .setAccountIdentifier(accountIdentifier) - .setBlockIdentifier(blockIdentifier) - .build(); - return blockingStubFull.getAccountBalance(accountBalanceRequest).getBalance(); - } - - /** constructor. */ - public static BalanceContract.BlockBalanceTrace getBlockBalance( - Protocol.Block block, WalletGrpc.WalletBlockingStub blockingStubFull) { - final Long blockNum = block.getBlockHeader().getRawData().getNumber(); - BlockId blockId = - new BlockId( - org.tron.common.utils.Sha256Hash.of( - CommonParameter.getInstance().isECKeyCryptoEngine(), - block.getBlockHeader().getRawData().toByteArray()), - block.getBlockHeader().getRawData().getNumber()); - BalanceContract.BlockBalanceTrace.BlockIdentifier blockIdentifier = - BalanceContract.BlockBalanceTrace.BlockIdentifier.newBuilder() - .setHash(blockId.getByteString()) - .setNumber(blockNum) - .build(); - - return blockingStubFull.getBlockBalanceTrace(blockIdentifier); - } - - /** 61 constructor. */ - public static Optional getTransactionFromPending( - String txId, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString bsTxid = ByteString.copyFrom(ByteArray.fromHexString(txId)); - BytesMessage request = BytesMessage.newBuilder().setValue(bsTxid).build(); - Transaction transaction; - transaction = blockingStubFull.getTransactionFromPending(request); - return Optional.ofNullable(transaction); - } -} diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/PublicMethedForMutiSign.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/PublicMethedForMutiSign.java deleted file mode 100644 index 87256d07453..00000000000 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/PublicMethedForMutiSign.java +++ /dev/null @@ -1,5335 +0,0 @@ -package stest.tron.wallet.common.client.utils; - -import static org.tron.common.crypto.Hash.sha3omit12; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.google.protobuf.Any; -import com.google.protobuf.ByteString; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicLong; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.BytesMessage; -import org.tron.api.GrpcAPI.DecryptNotes.NoteTx; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.ExchangeList; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.GrpcAPI.PrivateParameters; -import org.tron.api.GrpcAPI.ReceiveNote; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.GrpcAPI.SpendNote; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.GrpcAPI.TransactionSignWeight; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletGrpc.WalletBlockingStub; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.crypto.ECKey.ECDSASignature; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.Base58; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.Commons; -import org.tron.core.Wallet; -import org.tron.core.exception.CancelException; -import org.tron.core.zen.address.ExpandedSpendingKey; -import org.tron.core.zen.address.SpendingKey; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Key; -import org.tron.protos.Protocol.Permission; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.Protocol.Transaction.Result; -import org.tron.protos.Protocol.Transaction.raw; -import org.tron.protos.contract.AccountContract.AccountCreateContract; -import org.tron.protos.contract.AccountContract.AccountPermissionUpdateContract; -import org.tron.protos.contract.AccountContract.AccountUpdateContract; -import org.tron.protos.contract.AccountContract.SetAccountIdContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.ParticipateAssetIssueContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.UnfreezeAssetContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.UpdateAssetContract; -import org.tron.protos.contract.BalanceContract.FreezeBalanceContract; -import org.tron.protos.contract.BalanceContract.TransferContract; -import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; -import org.tron.protos.contract.BalanceContract.WithdrawBalanceContract; -import org.tron.protos.contract.ExchangeContract.ExchangeCreateContract; -import org.tron.protos.contract.ExchangeContract.ExchangeInjectContract; -import org.tron.protos.contract.ExchangeContract.ExchangeTransactionContract; -import org.tron.protos.contract.ExchangeContract.ExchangeWithdrawContract; -import org.tron.protos.contract.MarketContract; -import org.tron.protos.contract.ProposalContract.ProposalApproveContract; -import org.tron.protos.contract.ProposalContract.ProposalCreateContract; -import org.tron.protos.contract.ProposalContract.ProposalDeleteContract; -import org.tron.protos.contract.ShieldContract; -import org.tron.protos.contract.ShieldContract.IncrementalMerkleVoucherInfo; -import org.tron.protos.contract.ShieldContract.OutputPoint; -import org.tron.protos.contract.ShieldContract.OutputPointInfo; -import org.tron.protos.contract.SmartContractOuterClass.ClearABIContract; -import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; -import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract.Builder; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; -import org.tron.protos.contract.SmartContractOuterClass.UpdateEnergyLimitContract; -import org.tron.protos.contract.SmartContractOuterClass.UpdateSettingContract; -import org.tron.protos.contract.StorageContract.UpdateBrokerageContract; -import org.tron.protos.contract.WitnessContract.VoteWitnessContract; -import org.tron.protos.contract.WitnessContract.WitnessCreateContract; -import org.tron.protos.contract.WitnessContract.WitnessUpdateContract; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; - - -public class PublicMethedForMutiSign { - - private static final Logger logger = LoggerFactory.getLogger("TestLogger"); - Wallet wallet = new Wallet(); - - /** - * constructor. - */ - - public static Boolean createAssetIssue(byte[] address, String name, Long totalSupply, - Integer trxNum, Integer icoNum, Long startTime, Long endTime, Integer voteScore, - String description, String url, Long freeAssetNetLimit, Long publicFreeAssetNetLimit, - Long fronzenAmount, Long frozenDay, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - try { - AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - builder.setFreeAssetNetLimit(freeAssetNetLimit); - builder.setPublicFreeAssetNetLimit(publicFreeAssetNetLimit); - AssetIssueContract.FrozenSupply.Builder frozenBuilder = AssetIssueContract.FrozenSupply - .newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - builder.addFrozenSupply(0, frozenBuilder); - - TransactionExtention transactionExtention = blockingStubFull - .createAssetIssue2(builder.build()); - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - - /** - * constructor. - */ - - public static Boolean createAssetIssueWithpermissionId(byte[] address, String name, - Long totalSupply, Integer trxNum, Integer icoNum, Long startTime, Long endTime, - Integer voteScore, String description, String url, Long freeAssetNetLimit, - Long publicFreeAssetNetLimit, Long fronzenAmount, Long frozenDay, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, int permissionId, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - try { - AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - builder.setFreeAssetNetLimit(freeAssetNetLimit); - builder.setPublicFreeAssetNetLimit(publicFreeAssetNetLimit); - AssetIssueContract.FrozenSupply.Builder frozenBuilder = AssetIssueContract.FrozenSupply - .newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - builder.addFrozenSupply(0, frozenBuilder); - - TransactionExtention transactionExtention = blockingStubFull - .createAssetIssue2(builder.build()); - Return ret = transactionExtention.getResult(); - if (transactionExtention == null) { - return false; - } - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - /** - * constructor. - */ - - public static String createAssetIssueForTransactionId(byte[] address, String name, - Long totalSupply, Integer trxNum, Integer icoNum, Long startTime, Long endTime, - Integer voteScore, String description, String url, Long freeAssetNetLimit, - Long publicFreeAssetNetLimit, Long fronzenAmount, Long frozenDay, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - try { - AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - builder.setFreeAssetNetLimit(freeAssetNetLimit); - builder.setPublicFreeAssetNetLimit(publicFreeAssetNetLimit); - AssetIssueContract.FrozenSupply.Builder frozenBuilder = AssetIssueContract.FrozenSupply - .newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - builder.addFrozenSupply(0, frozenBuilder); - - Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return null; - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - boolean result = broadcastTransaction(transaction, blockingStubFull); - if (!result) { - return null; - } else { - return ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray())); - } - } catch (Exception ex) { - ex.printStackTrace(); - return null; - } - } - - /** - * constructor. - */ - public static boolean broadcastTransaction(Transaction transaction, - WalletGrpc.WalletBlockingStub blockingStubFull) { - - Return response = PublicMethed.broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - } - - - /** - * constructor. - */ - public static Account queryAccount(byte[] address, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public static Account queryAccount(byte[] address, - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - - /** - * constructor. - */ - - public static Account queryAccount(String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - byte[] address; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - /** - * constructor. - */ - - public static String loadPubKey() { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - /** - * constructor. - */ - - public static byte[] getAddress(ECKey ecKey) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public static Account grpcQueryAccount(byte[] address, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public static Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - GrpcAPI.NumberMessage.Builder builder = GrpcAPI.NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - } - - /** - * constructor. - */ - - public static Transaction signTransaction(ECKey ecKey, Transaction transaction) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - if (ecKey == null || ecKey.getPrivKey() == null) { - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - private static Transaction signTransaction(Transaction transaction, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] priKeys) { - if (transaction.getRawData().getTimestamp() == 0) { - transaction = TransactionUtils.setTimestamp(transaction); - } - - long currentTime = System.currentTimeMillis();//*1000000 + System.nanoTime()%1000000; - Transaction.Builder builder = transaction.toBuilder(); - org.tron.protos.Protocol.Transaction.raw.Builder rowBuilder = transaction.getRawData() - .toBuilder(); - rowBuilder.setTimestamp(currentTime); - builder.setRawData(rowBuilder.build()); - transaction = builder.build(); - - for (int i = 0; i < priKeys.length; i += 1) { - String priKey = priKeys[i]; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - transaction = TransactionUtils.sign(transaction, ecKey); - TransactionSignWeight weight = blockingStubFull.getTransactionSignWeight(transaction); - if (weight.getResult().getCode() - == TransactionSignWeight.Result.response_code.ENOUGH_PERMISSION) { - break; - } - if (weight.getResult().getCode() - == TransactionSignWeight.Result.response_code.NOT_ENOUGH_PERMISSION) { - continue; - } - } - return transaction; - } - - - /** - * constructor. - */ - public static boolean participateAssetIssue(byte[] to, byte[] assertName, long amount, - byte[] from, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - ParticipateAssetIssueContract.Builder builder = ParticipateAssetIssueContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(from); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - ParticipateAssetIssueContract contract = builder.build(); - Transaction transaction = blockingStubFull.participateAssetIssue(contract); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - public static boolean participateAssetIssueWithPermissionId(byte[] to, byte[] assertName, - long amount, byte[] from, String priKey, int permissionId, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - ParticipateAssetIssueContract.Builder builder = ParticipateAssetIssueContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(from); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - ParticipateAssetIssueContract contract = builder.build(); - Transaction transaction = blockingStubFull.participateAssetIssue(contract); - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - public static String participateAssetIssueForTransactionId(byte[] to, byte[] assertName, - long amount, byte[] from, String priKey, int permissionId, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - ParticipateAssetIssueContract.Builder builder = ParticipateAssetIssueContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(from); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - ParticipateAssetIssueContract contract = builder.build(); - Transaction transaction = blockingStubFull.participateAssetIssue(contract); - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - boolean result = broadcastTransaction(transaction, blockingStubFull); - if (!result) { - return null; - } - return ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray())); - } - - /** - * constructor. - */ - - public static Boolean freezeBalance(byte[] addRess, long freezeBalance, long freezeDuration, - String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - Block currentBlock = blockingStubFull.getNowBlock(EmptyMessage.newBuilder().build()); - final Long beforeBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Account beforeFronzen = queryAccount(priKey, blockingStubFull); - Long beforeFrozenBalance = 0L; - //Long beforeBandwidth = beforeFronzen.getBandwidth(); - if (beforeFronzen.getFrozenCount() != 0) { - beforeFrozenBalance = beforeFronzen.getFrozen(0).getFrozenBalance(); - //beforeBandwidth = beforeFronzen.getBandwidth(); - //logger.info(Long.toString(beforeFronzen.getBandwidth())); - logger.info(Long.toString(beforeFronzen.getFrozen(0).getFrozenBalance())); - } - - FreezeBalanceContract.Builder builder = FreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration); - - FreezeBalanceContract contract = builder.build(); - Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction = null"); - return null; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - - } - - /** - * constructor. - */ - - public static Boolean freezeBalanceWithPermissionId(byte[] addRess, long freezeBalance, - long freezeDuration, int permissionId, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - Block currentBlock = blockingStubFull.getNowBlock(EmptyMessage.newBuilder().build()); - final Long beforeBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Account beforeFronzen = queryAccount(priKey, blockingStubFull); - Long beforeFrozenBalance = 0L; - //Long beforeBandwidth = beforeFronzen.getBandwidth(); - if (beforeFronzen.getFrozenCount() != 0) { - beforeFrozenBalance = beforeFronzen.getFrozen(0).getFrozenBalance(); - //beforeBandwidth = beforeFronzen.getBandwidth(); - //logger.info(Long.toString(beforeFronzen.getBandwidth())); - logger.info(Long.toString(beforeFronzen.getFrozen(0).getFrozenBalance())); - } - - FreezeBalanceContract.Builder builder = FreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration); - - FreezeBalanceContract contract = builder.build(); - Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction = null"); - return null; - } - - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - - } - - /** - * constructor. - */ - - public static Boolean unFreezeBalanceWithPermissionId(byte[] address, String priKey, - int resourceCode, byte[] receiverAddress, int permissionId, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - UnfreezeBalanceContract.Builder builder = UnfreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - builder.setOwnerAddress(byteAddreess).setResourceValue(resourceCode); - if (receiverAddress != null) { - ByteString receiverAddressBytes = ByteString.copyFrom(receiverAddress); - builder.setReceiverAddress(receiverAddressBytes); - } - - UnfreezeBalanceContract contract = builder.build(); - Transaction transaction = blockingStubFull.unfreezeBalance(contract); - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static Boolean unFreezeBalance(byte[] address, String priKey, int resourceCode, - byte[] receiverAddress, WalletGrpc.WalletBlockingStub blockingStubFull, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - UnfreezeBalanceContract.Builder builder = UnfreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - builder.setOwnerAddress(byteAddreess).setResourceValue(resourceCode); - if (receiverAddress != null) { - ByteString receiverAddressBytes = ByteString.copyFrom(receiverAddress); - builder.setReceiverAddress(receiverAddressBytes); - } - - UnfreezeBalanceContract contract = builder.build(); - Transaction transaction = blockingStubFull.unfreezeBalance(contract); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static Boolean sendcoin(byte[] to, long amount, byte[] owner, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - //Protocol.Account search = queryAccount(priKey, blockingStubFull); - - TransferContract.Builder builder = TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferContract contract = builder.build(); - Transaction transaction = blockingStubFull.createTransaction(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction ==null"); - return null; - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - - } - - /** - * constructor. - */ - - public static String sendcoinGetTransactionHex(byte[] to, long amount, byte[] owner, - String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - //Protocol.Account search = queryAccount(priKey, blockingStubFull); - - TransferContract.Builder builder = TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferContract contract = builder.build(); - Transaction transaction = blockingStubFull.createTransaction(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction ==null"); - return null; - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - logger.info("HEX transaction is : " + "transaction hex string is " + ByteArray - .toHexString(transaction.toByteArray())); - return ByteArray.toHexString(transaction.toByteArray()); - - } - - - /** - * constructor. - */ - public static boolean updateAsset(byte[] address, byte[] description, byte[] url, long newLimit, - long newPublicLimit, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - UpdateAssetContract.Builder builder = UpdateAssetContract.newBuilder(); - ByteString basAddreess = ByteString.copyFrom(address); - builder.setDescription(ByteString.copyFrom(description)); - builder.setUrl(ByteString.copyFrom(url)); - builder.setNewLimit(newLimit); - builder.setNewPublicLimit(newPublicLimit); - builder.setOwnerAddress(basAddreess); - - UpdateAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.updateAsset(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - public static boolean updateAssetWithPermissionId(byte[] address, byte[] description, byte[] url, - long newLimit, long newPublicLimit, String priKey, int permissionId, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - UpdateAssetContract.Builder builder = UpdateAssetContract.newBuilder(); - ByteString basAddreess = ByteString.copyFrom(address); - builder.setDescription(ByteString.copyFrom(description)); - builder.setUrl(ByteString.copyFrom(url)); - builder.setNewLimit(newLimit); - builder.setNewPublicLimit(newPublicLimit); - builder.setOwnerAddress(basAddreess); - - UpdateAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.updateAsset(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - public static String updateAssetForTransactionId(byte[] address, byte[] description, byte[] url, - long newLimit, long newPublicLimit, String priKey, int permissionId, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - UpdateAssetContract.Builder builder = UpdateAssetContract.newBuilder(); - ByteString basAddreess = ByteString.copyFrom(address); - builder.setDescription(ByteString.copyFrom(description)); - builder.setUrl(ByteString.copyFrom(url)); - builder.setNewLimit(newLimit); - builder.setNewPublicLimit(newPublicLimit); - builder.setOwnerAddress(basAddreess); - - UpdateAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.updateAsset(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return null; - } - - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - boolean result = broadcastTransaction(transaction, blockingStubFull); - if (!result) { - return null; - } else { - return ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray())); - } - } - - /** - * constructor. - */ - - public static boolean transferAsset(byte[] to, byte[] assertName, long amount, byte[] address, - String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.transferAsset(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - if (transaction == null) { - logger.info("transaction == null"); - } else { - logger.info("transaction.getRawData().getContractCount() == 0"); - } - return false; - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static boolean transferAssetWithpermissionId(byte[] to, byte[] assertName, long amount, - byte[] address, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, - int permissionId, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferAssetContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.transferAsset2(contract); - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static String transferAssetForTransactionId(byte[] to, byte[] assertName, long amount, - byte[] address, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.transferAsset(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - if (transaction == null) { - logger.info("transaction == null"); - } else { - logger.info("transaction.getRawData().getContractCount() == 0"); - } - return null; - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - boolean result = broadcastTransaction(transaction, blockingStubFull); - if (!result) { - return null; - } else { - return ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray())); - } - } - - /** - * constructor. - */ - - public static boolean updateAccount(byte[] addressBytes, byte[] accountNameBytes, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - AccountUpdateContract.Builder builder = AccountUpdateContract.newBuilder(); - ByteString basAddreess = ByteString.copyFrom(addressBytes); - ByteString bsAccountName = ByteString.copyFrom(accountNameBytes); - - builder.setAccountName(bsAccountName); - builder.setOwnerAddress(basAddreess); - - AccountUpdateContract contract = builder.build(); - Transaction transaction = blockingStubFull.updateAccount(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("Please check!!! transaction == null"); - return false; - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static boolean waitProduceNextBlock(WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - Block currentBlock = blockingStubFull.getNowBlock(EmptyMessage.newBuilder().build()); - final Long currentNum = currentBlock.getBlockHeader().getRawData().getNumber(); - - Block nextBlock = blockingStubFull.getNowBlock(EmptyMessage.newBuilder().build()); - Long nextNum = nextBlock.getBlockHeader().getRawData().getNumber(); - - Integer wait = 0; - logger.info( - "Block num is " + Long.toString(currentBlock.getBlockHeader().getRawData().getNumber())); - while (nextNum <= currentNum + 1 && wait <= 15) { - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - logger.info("Wait to produce next block"); - nextBlock = blockingStubFull.getNowBlock(EmptyMessage.newBuilder().build()); - nextNum = nextBlock.getBlockHeader().getRawData().getNumber(); - if (wait == 15) { - logger.info("These 45 second didn't produce a block,please check."); - return false; - } - wait++; - } - logger.info("quit normally"); - return true; - } - - /** - * constructor. - */ - - public static boolean createAccount(byte[] ownerAddress, byte[] newAddress, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - AccountCreateContract.Builder builder = AccountCreateContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setAccountAddress(ByteString.copyFrom(newAddress)); - AccountCreateContract contract = builder.build(); - Transaction transaction = blockingStubFull.createAccount(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - - } - - /** - * constructor. - */ - - public static boolean createAccountWhtiPermissionId(byte[] ownerAddress, byte[] newAddress, - String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, int permissionId, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - AccountCreateContract.Builder builder = AccountCreateContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setAccountAddress(ByteString.copyFrom(newAddress)); - AccountCreateContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.createAccount2(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - - } - - /** - * constructor. - */ - - public static boolean createProposal(byte[] ownerAddress, String priKey, - HashMap parametersMap, WalletGrpc.WalletBlockingStub blockingStubFull, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - ProposalCreateContract.Builder builder = ProposalCreateContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.putAllParameters(parametersMap); - - ProposalCreateContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.proposalCreate(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static boolean createProposalWithPermissionId(byte[] ownerAddress, String priKey, - HashMap parametersMap, int permissionId, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - ProposalCreateContract.Builder builder = ProposalCreateContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.putAllParameters(parametersMap); - - ProposalCreateContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.proposalCreate(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static boolean approveProposal(byte[] ownerAddress, String priKey, long id, - boolean isAddApproval, WalletGrpc.WalletBlockingStub blockingStubFull, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - ProposalApproveContract.Builder builder = ProposalApproveContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setProposalId(id); - builder.setIsAddApproval(isAddApproval); - ProposalApproveContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.proposalApprove(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static boolean approveProposalWithPermission(byte[] ownerAddress, String priKey, long id, - boolean isAddApproval, int permissionId, WalletGrpc.WalletBlockingStub blockingStubFull, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - ProposalApproveContract.Builder builder = ProposalApproveContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setProposalId(id); - builder.setIsAddApproval(isAddApproval); - ProposalApproveContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.proposalApprove(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static boolean deleteProposal(byte[] ownerAddress, String priKey, long id, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - ProposalDeleteContract.Builder builder = ProposalDeleteContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setProposalId(id); - - ProposalDeleteContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.proposalDelete(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static boolean deleteProposalWithPermissionId(byte[] ownerAddress, String priKey, long id, - int permissionId, WalletGrpc.WalletBlockingStub blockingStubFull, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - ProposalDeleteContract.Builder builder = ProposalDeleteContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setProposalId(id); - - ProposalDeleteContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.proposalDelete(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static boolean setAccountId(byte[] accountIdBytes, byte[] ownerAddress, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - SetAccountIdContract.Builder builder = SetAccountIdContract.newBuilder(); - ByteString bsAddress = ByteString.copyFrom(owner); - ByteString bsAccountId = ByteString.copyFrom(accountIdBytes); - builder.setAccountId(bsAccountId); - builder.setOwnerAddress(bsAddress); - SetAccountIdContract contract = builder.build(); - Transaction transaction = blockingStubFull.setAccountId(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - } - transaction = signTransaction(ecKey, transaction); - Return response = broadcastTransaction1(transaction, blockingStubFull); - return response.getResult(); - } - - /** - * constructor. - */ - - public static Boolean freezeBalanceGetEnergy(byte[] addRess, long freezeBalance, - long freezeDuration, int resourceCode, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - FreezeBalanceContract.Builder builder = FreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration).setResourceValue(resourceCode); - - FreezeBalanceContract contract = builder.build(); - Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction = null"); - return false; - } - transaction = TransactionUtils.setTimestamp(transaction); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - public static byte[] deployContract(String contractName, String abiString, String code, - String data, Long feeLimit, long value, long consumeUserResourcePercent, - String libraryAddress, String priKey, byte[] ownerAddress, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - return deployContract(contractName, abiString, code, data, feeLimit, value, - consumeUserResourcePercent, 1000L, "0", 0L, libraryAddress, priKey, ownerAddress, - blockingStubFull, permissionKeyString); - } - - /** - * constructor. - */ - - public static byte[] deployContract(String contractName, String abiString, String code, - String data, Long feeLimit, long value, long consumeUserResourcePercent, - long originEnergyLimit, String tokenId, long tokenValue, String libraryAddress, String priKey, - byte[] ownerAddress, WalletGrpc.WalletBlockingStub blockingStubFull, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - SmartContract.ABI abi = jsonStr2Abi(abiString); - if (abi == null) { - logger.error("abi is null"); - return null; - } - //byte[] codeBytes = Hex.decode(code); - SmartContract.Builder builder = SmartContract.newBuilder(); - builder.setName(contractName); - builder.setOriginAddress(ByteString.copyFrom(owner)); - builder.setAbi(abi); - builder.setConsumeUserResourcePercent(consumeUserResourcePercent); - builder.setOriginEnergyLimit(originEnergyLimit); - - if (value != 0) { - - builder.setCallValue(value); - } - - byte[] byteCode; - if (null != libraryAddress) { - byteCode = replaceLibraryAddress(code, libraryAddress); - } else { - byteCode = Hex.decode(code); - } - builder.setBytecode(ByteString.copyFrom(byteCode)); - - Builder contractBuilder = CreateSmartContract.newBuilder(); - contractBuilder.setOwnerAddress(ByteString.copyFrom(owner)); - contractBuilder.setCallTokenValue(tokenValue); - contractBuilder.setTokenId(Long.parseLong(tokenId)); - CreateSmartContract contractDeployContract = contractBuilder.setNewContract(builder.build()) - .build(); - - TransactionExtention transactionExtention = blockingStubFull - .deployContract(contractDeployContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create trx failed!"); - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = transactionExtention.getTransaction().getRawData() - .toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - - byte[] contractAddress = PublicMethed - .generateContractAddress(transactionExtention.getTransaction(), owner); - System.out.println( - "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - System.out.println( - "txid = " + ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()))); - contractAddress = PublicMethed.generateContractAddress(transaction, owner); - System.out.println( - "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); - broadcastTransaction(transaction, blockingStubFull); - return contractAddress; - } - - /** - * constructor. - */ - - public static String deployContractAndGetTransactionInfoById(String contractName, - String abiString, String code, String data, Long feeLimit, long value, - long consumeUserResourcePercent, String libraryAddress, String priKey, byte[] ownerAddress, - WalletGrpc.WalletBlockingStub blockingStubFull) { - return deployContractAndGetTransactionInfoById(contractName, abiString, code, data, feeLimit, - value, consumeUserResourcePercent, 1000L, "0", 0L, libraryAddress, priKey, ownerAddress, - blockingStubFull); - } - - /** - * constructor. - */ - - public static String deployContractAndGetTransactionInfoById(String contractName, - String abiString, String code, String data, Long feeLimit, long value, - long consumeUserResourcePercent, long originEnergyLimit, String tokenId, long tokenValue, - String libraryAddress, String priKey, byte[] ownerAddress, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - SmartContract.ABI abi = jsonStr2Abi(abiString); - if (abi == null) { - logger.error("abi is null"); - return null; - } - //byte[] codeBytes = Hex.decode(code); - SmartContract.Builder builder = SmartContract.newBuilder(); - builder.setName(contractName); - builder.setOriginAddress(ByteString.copyFrom(owner)); - builder.setAbi(abi); - builder.setConsumeUserResourcePercent(consumeUserResourcePercent); - builder.setOriginEnergyLimit(originEnergyLimit); - - if (value != 0) { - - builder.setCallValue(value); - } - - byte[] byteCode; - if (null != libraryAddress) { - byteCode = replaceLibraryAddress(code, libraryAddress); - } else { - byteCode = Hex.decode(code); - } - builder.setBytecode(ByteString.copyFrom(byteCode)); - - Builder contractBuilder = CreateSmartContract.newBuilder(); - contractBuilder.setOwnerAddress(ByteString.copyFrom(owner)); - contractBuilder.setCallTokenValue(tokenValue); - contractBuilder.setTokenId(Long.parseLong(tokenId)); - CreateSmartContract contractDeployContract = contractBuilder.setNewContract(builder.build()) - .build(); - - TransactionExtention transactionExtention = blockingStubFull - .deployContract(contractDeployContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create trx failed!"); - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = transactionExtention.getTransaction().getRawData() - .toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - transaction = signTransaction(ecKey, transaction); - System.out.println( - "txid = " + ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()))); - byte[] contractAddress = PublicMethed.generateContractAddress(transaction, owner); - System.out.println( - "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); - Return response = broadcastTransaction1(transaction, blockingStubFull); - if (response.getResult() == false) { - return null; - } else { - return ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray())); - } - } - - /** - * constructor. - */ - - public static SmartContract.ABI jsonStr2Abi(String jsonStr) { - if (jsonStr == null) { - return null; - } - - JsonParser jsonParser = new JsonParser(); - JsonElement jsonElementRoot = jsonParser.parse(jsonStr); - JsonArray jsonRoot = jsonElementRoot.getAsJsonArray(); - SmartContract.ABI.Builder abiBuilder = SmartContract.ABI.newBuilder(); - for (int index = 0; index < jsonRoot.size(); index++) { - JsonElement abiItem = jsonRoot.get(index); - boolean anonymous = - abiItem.getAsJsonObject().get("anonymous") != null ? abiItem.getAsJsonObject() - .get("anonymous").getAsBoolean() : false; - final boolean constant = - abiItem.getAsJsonObject().get("constant") != null ? abiItem.getAsJsonObject() - .get("constant").getAsBoolean() : false; - final String name = - abiItem.getAsJsonObject().get("name") != null ? abiItem.getAsJsonObject().get("name") - .getAsString() : null; - JsonArray inputs = - abiItem.getAsJsonObject().get("inputs") != null ? abiItem.getAsJsonObject().get("inputs") - .getAsJsonArray() : null; - final JsonArray outputs = - abiItem.getAsJsonObject().get("outputs") != null ? abiItem.getAsJsonObject() - .get("outputs").getAsJsonArray() : null; - String type = - abiItem.getAsJsonObject().get("type") != null ? abiItem.getAsJsonObject().get("type") - .getAsString() : null; - final boolean payable = - abiItem.getAsJsonObject().get("payable") != null ? abiItem.getAsJsonObject() - .get("payable").getAsBoolean() : false; - final String stateMutability = - abiItem.getAsJsonObject().get("stateMutability") != null ? abiItem.getAsJsonObject() - .get("stateMutability").getAsString() : null; - if (type == null) { - logger.error("No type!"); - return null; - } - if (!type.equalsIgnoreCase("fallback") && null == inputs) { - logger.error("No inputs!"); - return null; - } - - SmartContract.ABI.Entry.Builder entryBuilder = SmartContract.ABI.Entry.newBuilder(); - entryBuilder.setAnonymous(anonymous); - entryBuilder.setConstant(constant); - if (name != null) { - entryBuilder.setName(name); - } - - /* { inputs : optional } since fallback function not requires inputs*/ - if (inputs != null) { - for (int j = 0; j < inputs.size(); j++) { - JsonElement inputItem = inputs.get(j); - if (inputItem.getAsJsonObject().get("name") == null - || inputItem.getAsJsonObject().get("type") == null) { - logger.error("Input argument invalid due to no name or no type!"); - return null; - } - String inputName = inputItem.getAsJsonObject().get("name").getAsString(); - String inputType = inputItem.getAsJsonObject().get("type").getAsString(); - SmartContract.ABI.Entry.Param.Builder paramBuilder = SmartContract.ABI.Entry.Param - .newBuilder(); - paramBuilder.setIndexed(false); - paramBuilder.setName(inputName); - paramBuilder.setType(inputType); - entryBuilder.addInputs(paramBuilder.build()); - } - } - - /* { outputs : optional } */ - if (outputs != null) { - for (int k = 0; k < outputs.size(); k++) { - JsonElement outputItem = outputs.get(k); - if (outputItem.getAsJsonObject().get("name") == null - || outputItem.getAsJsonObject().get("type") == null) { - logger.error("Output argument invalid due to no name or no type!"); - return null; - } - String outputName = outputItem.getAsJsonObject().get("name").getAsString(); - String outputType = outputItem.getAsJsonObject().get("type").getAsString(); - SmartContract.ABI.Entry.Param.Builder paramBuilder = SmartContract.ABI.Entry.Param - .newBuilder(); - paramBuilder.setIndexed(false); - paramBuilder.setName(outputName); - paramBuilder.setType(outputType); - entryBuilder.addOutputs(paramBuilder.build()); - } - } - - entryBuilder.setType(getEntryType(type)); - entryBuilder.setPayable(payable); - if (stateMutability != null) { - entryBuilder.setStateMutability(getStateMutability(stateMutability)); - } - - abiBuilder.addEntrys(entryBuilder.build()); - } - - return abiBuilder.build(); - } - - /** - * constructor. - */ - - public static SmartContract.ABI.Entry.EntryType getEntryType(String type) { - switch (type) { - case "constructor": - return SmartContract.ABI.Entry.EntryType.Constructor; - case "function": - return SmartContract.ABI.Entry.EntryType.Function; - case "event": - return SmartContract.ABI.Entry.EntryType.Event; - case "fallback": - return SmartContract.ABI.Entry.EntryType.Fallback; - default: - return SmartContract.ABI.Entry.EntryType.UNRECOGNIZED; - } - } - - /** - * constructor. - */ - - public static SmartContract.ABI.Entry.StateMutabilityType getStateMutability( - String stateMutability) { - switch (stateMutability) { - case "pure": - return SmartContract.ABI.Entry.StateMutabilityType.Pure; - case "view": - return SmartContract.ABI.Entry.StateMutabilityType.View; - case "nonpayable": - return SmartContract.ABI.Entry.StateMutabilityType.Nonpayable; - case "payable": - return SmartContract.ABI.Entry.StateMutabilityType.Payable; - default: - return SmartContract.ABI.Entry.StateMutabilityType.UNRECOGNIZED; - } - } - - /** - * constructor. - */ - - public static SmartContract getContract(byte[] address, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ByteString byteString = ByteString.copyFrom(address); - BytesMessage bytesMessage = BytesMessage.newBuilder().setValue(byteString).build(); - Integer i = 0; - while (blockingStubFull.getContract(bytesMessage).getName().isEmpty() && i++ < 4) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - logger.info("contract name is " + blockingStubFull.getContract(bytesMessage).getName()); - logger.info("contract address is " + WalletClient.encode58Check(address)); - return blockingStubFull.getContract(bytesMessage); - } - - private static byte[] replaceLibraryAddress(String code, String libraryAddressPair) { - - String[] libraryAddressList = libraryAddressPair.split("[,]"); - - for (int i = 0; i < libraryAddressList.length; i++) { - String cur = libraryAddressList[i]; - - int lastPosition = cur.lastIndexOf(":"); - if (-1 == lastPosition) { - throw new RuntimeException("libraryAddress delimit by ':'"); - } - String libraryName = cur.substring(0, lastPosition); - String addr = cur.substring(lastPosition + 1); - String libraryAddressHex = ByteArray.toHexString(Commons.decodeFromBase58Check(addr)) - .substring(2); - - String repeated = new String(new char[40 - libraryName.length() - 2]).replace("\0", "_"); - String beReplaced = "__" + libraryName + repeated; - Matcher m = Pattern.compile(beReplaced).matcher(code); - code = m.replaceAll(libraryAddressHex); - } - - return Hex.decode(code); - } - - private static byte[] replaceLibraryAddress_1(String code, byte[] libraryAddress) { - - String libraryAddressHex = ByteArray.toHexString(libraryAddress).substring(2); - - Matcher m = Pattern.compile("__.*__").matcher(code); - code = m.replaceAll(libraryAddressHex); - return Hex.decode(code); - } - - /** - * constructor. - */ - - public static boolean updateSetting(byte[] contractAddress, long consumeUserResourcePercent, - String priKey, byte[] ownerAddress, WalletGrpc.WalletBlockingStub blockingStubFull, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - UpdateSettingContract.Builder builder = UpdateSettingContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - builder.setConsumeUserResourcePercent(consumeUserResourcePercent); - - UpdateSettingContract updateSettingContract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull - .updateSetting(updateSettingContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create trx failed!"); - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return false; - } - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static boolean updateSettingWithPermissionId(byte[] contractAddress, - long consumeUserResourcePercent, String priKey, byte[] ownerAddress, int permissionId, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - UpdateSettingContract.Builder builder = UpdateSettingContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - builder.setConsumeUserResourcePercent(consumeUserResourcePercent); - - UpdateSettingContract updateSettingContract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull - .updateSetting(updateSettingContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create trx failed!"); - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return false; - } - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static boolean updateEnergyLimitWithPermissionId(byte[] contractAddress, - long originEnergyLimit, String priKey, byte[] ownerAddress, int permissionId, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - UpdateEnergyLimitContract.Builder builder = UpdateEnergyLimitContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - builder.setOriginEnergyLimit(originEnergyLimit); - - UpdateEnergyLimitContract updateEnergyLimitContract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull - .updateEnergyLimit(updateEnergyLimitContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create trx failed!"); - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return false; - } - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - public static String triggerContract(byte[] contractAddress, String method, String argsStr, - Boolean isHex, long callValue, long feeLimit, byte[] ownerAddress, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - return triggerContract(contractAddress, method, argsStr, isHex, callValue, feeLimit, "0", 0, - ownerAddress, priKey, blockingStubFull, permissionKeyString); - } - - /** - * constructor. - */ - - public static String triggerContract(byte[] contractAddress, String method, String argsStr, - Boolean isHex, long callValue, long feeLimit, String tokenId, long tokenValue, - byte[] ownerAddress, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - if (argsStr.equalsIgnoreCase("#")) { - logger.info("argsstr is #"); - argsStr = ""; - } - - byte[] owner = ownerAddress; - byte[] input = Hex.decode(AbiUtil.parseMethod(method, argsStr, isHex)); - - TriggerSmartContract.Builder builder = TriggerSmartContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - builder.setData(ByteString.copyFrom(input)); - builder.setCallValue(callValue); - builder.setTokenId(Long.parseLong(tokenId)); - builder.setCallTokenValue(tokenValue); - TriggerSmartContract triggerContract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.triggerContract(triggerContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create call trx failed!"); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction.getRetCount() != 0 && transactionExtention.getConstantResult(0) != null - && transactionExtention.getResult() != null) { - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = transactionExtention.getTransaction().getRawData() - .toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - System.out.println("trigger txid = " + ByteArray - .toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()))); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - broadcastTransaction(transaction, blockingStubFull); - return ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray())); - } - - /** - * constructor. - */ - - public static Boolean exchangeCreate(byte[] firstTokenId, long firstTokenBalance, - byte[] secondTokenId, long secondTokenBalance, byte[] ownerAddress, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - - ExchangeCreateContract.Builder builder = ExchangeCreateContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)) - .setFirstTokenId(ByteString.copyFrom(firstTokenId)).setFirstTokenBalance(firstTokenBalance) - .setSecondTokenId(ByteString.copyFrom(secondTokenId)) - .setSecondTokenBalance(secondTokenBalance); - ExchangeCreateContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.exchangeCreate(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static Boolean injectExchange(long exchangeId, byte[] tokenId, long quant, - byte[] ownerAddress, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - - ExchangeInjectContract.Builder builder = ExchangeInjectContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)).setExchangeId(exchangeId) - .setTokenId(ByteString.copyFrom(tokenId)).setQuant(quant); - ExchangeInjectContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.exchangeInject(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - public static Optional getExchangeList( - WalletGrpc.WalletBlockingStub blockingStubFull) { - ExchangeList exchangeList = blockingStubFull.listExchanges(EmptyMessage.newBuilder().build()); - return Optional.ofNullable(exchangeList); - } - - /** - * constructor. - */ - - public static boolean exchangeWithdraw(long exchangeId, byte[] tokenId, long quant, - byte[] ownerAddress, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - byte[] owner = ownerAddress; - - ExchangeWithdrawContract.Builder builder = ExchangeWithdrawContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)).setExchangeId(exchangeId) - .setTokenId(ByteString.copyFrom(tokenId)).setQuant(quant); - ExchangeWithdrawContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.exchangeWithdraw(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static boolean exchangeTransaction(long exchangeId, byte[] tokenId, long quant, - long expected, byte[] ownerAddress, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - byte[] owner = ownerAddress; - - ExchangeTransactionContract.Builder builder = ExchangeTransactionContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)).setExchangeId(exchangeId) - .setTokenId(ByteString.copyFrom(tokenId)).setQuant(quant).setExpected(expected); - ExchangeTransactionContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.exchangeTransaction(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static String deployContractWithConstantParame(String contractName, String abiString, - String code, String constructorStr, String argsStr, String data, Long feeLimit, long value, - long consumeUserResourcePercent, String libraryAddress, String priKey, byte[] ownerAddress, - WalletGrpc.WalletBlockingStub blockingStubFull) { - return deployContractWithConstantParame(contractName, abiString, code, constructorStr, argsStr, - data, feeLimit, value, consumeUserResourcePercent, 1000L, "0", 0L, libraryAddress, priKey, - ownerAddress, blockingStubFull); - } - - /** - * constructor. - */ - - public static String deployContractWithConstantParame(String contractName, String abiString, - String code, String constructorStr, String argsStr, String data, Long feeLimit, long value, - long consumeUserResourcePercent, long originEnergyLimit, String tokenId, long tokenValue, - String libraryAddress, String priKey, byte[] ownerAddress, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - SmartContract.ABI abi = jsonStr2Abi(abiString); - if (abi == null) { - logger.error("abi is null"); - return null; - } - - code += Hex.toHexString(AbiUtil.encodeInput(constructorStr, argsStr)); - byte[] owner = ownerAddress; - SmartContract.Builder builder = SmartContract.newBuilder(); - builder.setName(contractName); - builder.setOriginAddress(ByteString.copyFrom(owner)); - builder.setAbi(abi); - builder.setConsumeUserResourcePercent(consumeUserResourcePercent); - builder.setOriginEnergyLimit(originEnergyLimit); - - if (value != 0) { - - builder.setCallValue(value); - } - - byte[] byteCode; - if (null != libraryAddress) { - byteCode = replaceLibraryAddress(code, libraryAddress); - } else { - byteCode = Hex.decode(code); - } - builder.setBytecode(ByteString.copyFrom(byteCode)); - - Builder contractBuilder = CreateSmartContract.newBuilder(); - contractBuilder.setOwnerAddress(ByteString.copyFrom(owner)); - contractBuilder.setCallTokenValue(tokenValue); - contractBuilder.setTokenId(Long.parseLong(tokenId)); - CreateSmartContract contractDeployContract = contractBuilder.setNewContract(builder.build()) - .build(); - - TransactionExtention transactionExtention = blockingStubFull - .deployContract(contractDeployContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create trx failed!"); - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = transactionExtention.getTransaction().getRawData() - .toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - transaction = signTransaction(ecKey, transaction); - System.out.println( - "txid = " + ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()))); - byte[] contractAddress = PublicMethed.generateContractAddress(transaction, owner); - System.out.println( - "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); - Return response = broadcastTransaction1(transaction, blockingStubFull); - if (response.getResult() == false) { - return null; - } else { - //logger.info("brodacast succesfully"); - return ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray())); - } - } - - /** - * constructor. - */ - - public static Boolean freezeBalanceForReceiver(byte[] addRess, long freezeBalance, - long freezeDuration, int resourceCode, ByteString receiverAddressBytes, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - FreezeBalanceContract.Builder builder = FreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration).setResourceValue(resourceCode); - builder.setReceiverAddress(receiverAddressBytes); - FreezeBalanceContract contract = builder.build(); - Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction = null"); - return false; - } - transaction = TransactionUtils.setTimestamp(transaction); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - private static Permission json2Permission(JSONObject json) { - Permission.Builder permissionBuilder = Permission.newBuilder(); - if (json.containsKey("type")) { - int type = json.getInteger("type"); - permissionBuilder.setTypeValue(type); - } - if (json.containsKey("permission_name")) { - String permissionName = json.getString("permission_name"); - permissionBuilder.setPermissionName(permissionName); - } - if (json.containsKey("threshold")) { - // long threshold = json.getLong("threshold"); - long threshold = Long.parseLong(json.getString("threshold")); - permissionBuilder.setThreshold(threshold); - } - if (json.containsKey("parent_id")) { - int parentId = json.getInteger("parent_id"); - permissionBuilder.setParentId(parentId); - } - if (json.containsKey("operations")) { - byte[] operations = ByteArray.fromHexString(json.getString("operations")); - permissionBuilder.setOperations(ByteString.copyFrom(operations)); - } - if (json.containsKey("keys")) { - JSONArray keys = json.getJSONArray("keys"); - List keyList = new ArrayList<>(); - for (int i = 0; i < keys.size(); i++) { - Key.Builder keyBuilder = Key.newBuilder(); - JSONObject key = keys.getJSONObject(i); - String address = key.getString("address"); - // long weight = key.getLong("weight"); - long weight = Long.parseLong(key.getString("weight")); - keyBuilder.setAddress(ByteString.copyFrom(WalletClient.decodeFromBase58Check(address))); - keyBuilder.setWeight(weight); - keyList.add(keyBuilder.build()); - } - permissionBuilder.addAllKeys(keyList); - } - return permissionBuilder.build(); - } - - /** - * constructor. - */ - - public static boolean accountPermissionUpdate(String permissionJson, byte[] owner, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] priKeys) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - AccountPermissionUpdateContract.Builder builder = AccountPermissionUpdateContract.newBuilder(); - - JSONObject permissions = JSONObject.parseObject(permissionJson); - JSONObject ownersPermission = permissions.getJSONObject("owner_permission"); - JSONObject witnesssPermission = permissions.getJSONObject("witness_permission"); - JSONArray activesPermissions = permissions.getJSONArray("active_permissions"); - - if (ownersPermission != null) { - Permission ownerPermission = json2Permission(ownersPermission); - builder.setOwner(ownerPermission); - } - if (witnesssPermission != null) { - Permission witnessPermission = json2Permission(witnesssPermission); - builder.setWitness(witnessPermission); - } - if (activesPermissions != null) { - List activePermissionList = new ArrayList<>(); - for (int j = 0; j < activesPermissions.size(); j++) { - JSONObject permission = activesPermissions.getJSONObject(j); - activePermissionList.add(json2Permission(permission)); - } - builder.addAllActives(activePermissionList); - } - builder.setOwnerAddress(ByteString.copyFrom(owner)); - - AccountPermissionUpdateContract contract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.accountPermissionUpdate(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - - transaction = signTransaction(transaction, blockingStubFull, priKeys); - System.out.println("trigger txid = " + ByteArray - .toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()))); - Return response = broadcastTransaction1(transaction, blockingStubFull); - return response.getResult(); - } - - /** - * constructor. - */ - public static String accountPermissionUpdateForTransactionId(String permissionJson, byte[] owner, - String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, String[] priKeys) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - AccountPermissionUpdateContract.Builder builder = AccountPermissionUpdateContract.newBuilder(); - - JSONObject permissions = JSONObject.parseObject(permissionJson); - JSONObject ownerpermission = permissions.getJSONObject("owner_permission"); - JSONObject witnesspermission = permissions.getJSONObject("witness_permission"); - JSONArray activepermissions = permissions.getJSONArray("active_permissions"); - - if (ownerpermission != null) { - Permission ownerPermission = json2Permission(ownerpermission); - builder.setOwner(ownerPermission); - } - if (witnesspermission != null) { - Permission witnessPermission = json2Permission(witnesspermission); - builder.setWitness(witnessPermission); - } - if (activepermissions != null) { - List activePermissionList = new ArrayList<>(); - for (int j = 0; j < activepermissions.size(); j++) { - JSONObject permission = activepermissions.getJSONObject(j); - activePermissionList.add(json2Permission(permission)); - } - builder.addAllActives(activePermissionList); - } - builder.setOwnerAddress(ByteString.copyFrom(owner)); - - AccountPermissionUpdateContract contract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.accountPermissionUpdate(contract); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = signTransaction(transaction, blockingStubFull, priKeys); - Return response = broadcastTransaction1(transaction, blockingStubFull); - if (response.getResult() == false) { - return null; - } else { - return ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray())); - } - } - - - /** - * constructor. - */ - public static String accountPermissionUpdateForTransactionId1(String permissionJson, byte[] owner, - String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, int permissionId, - String[] priKeys) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - AccountPermissionUpdateContract.Builder builder = AccountPermissionUpdateContract.newBuilder(); - - JSONObject permissions = JSONObject.parseObject(permissionJson); - JSONObject ownerpermission = permissions.getJSONObject("owner_permission"); - JSONObject witnesspermission = permissions.getJSONObject("witness_permission"); - JSONArray activepermissions = permissions.getJSONArray("active_permissions"); - - if (ownerpermission != null) { - Permission ownerPermission = json2Permission(ownerpermission); - builder.setOwner(ownerPermission); - } - if (witnesspermission != null) { - Permission witnessPermission = json2Permission(witnesspermission); - builder.setWitness(witnessPermission); - } - if (activepermissions != null) { - List activePermissionList = new ArrayList<>(); - for (int j = 0; j < activepermissions.size(); j++) { - JSONObject permission = activepermissions.getJSONObject(j); - activePermissionList.add(json2Permission(permission)); - } - builder.addAllActives(activePermissionList); - } - builder.setOwnerAddress(ByteString.copyFrom(owner)); - - AccountPermissionUpdateContract contract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.accountPermissionUpdate(contract); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = signTransaction(transaction, blockingStubFull, priKeys); - Return response = broadcastTransaction1(transaction, blockingStubFull); - if (response.getResult() == false) { - return null; - } else { - return ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray())); - } - } - - /** - * constructor. - */ - public static Transaction addTransactionSign(Transaction transaction, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - Transaction.Builder transactionBuilderSigned = transaction.toBuilder(); - byte[] hash = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()); - - ECDSASignature signature = ecKey.sign(hash); - ByteString bsSign = ByteString.copyFrom(signature.toByteArray()); - transactionBuilderSigned.addSignature(bsSign); - transaction = transactionBuilderSigned.build(); - return transaction; - } - - /** - * constructor. - */ - public static Boolean voteWitness(HashMap witness, byte[] addRess, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - VoteWitnessContract.Builder builder = VoteWitnessContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(addRess)); - for (String addressBase58 : witness.keySet()) { - String value = witness.get(addressBase58); - final long count = Long.parseLong(value); - VoteWitnessContract.Vote.Builder voteBuilder = VoteWitnessContract.Vote.newBuilder(); - byte[] address = WalletClient.decodeFromBase58Check(addressBase58); - if (address == null) { - continue; - } - voteBuilder.setVoteAddress(ByteString.copyFrom(address)); - voteBuilder.setVoteCount(count); - builder.addVotes(voteBuilder.build()); - } - - VoteWitnessContract contract = builder.build(); - - Transaction transaction = blockingStubFull.voteWitnessAccount(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - public static void printPermissionList(List permissionList) { - String result = "\n"; - result += "["; - result += "\n"; - int i = 0; - for (Permission permission : permissionList) { - result += "permission " + i + " :::"; - result += "\n"; - result += "{"; - result += "\n"; - result += printPermission(permission); - result += "\n"; - result += "}"; - result += "\n"; - i++; - } - result += "]"; - System.out.println(result); - } - - /** - * constructor. - */ - public static String printPermission(Permission permission) { - StringBuffer result = new StringBuffer(); - result.append("permission_type: "); - result.append(permission.getType()); - result.append("\n"); - result.append("permission_id: "); - result.append(permission.getId()); - result.append("\n"); - result.append("permission_name: "); - result.append(permission.getPermissionName()); - result.append("\n"); - result.append("threshold: "); - result.append(permission.getThreshold()); - result.append("\n"); - result.append("parent_id: "); - result.append(permission.getParentId()); - result.append("\n"); - result.append("operations: "); - result.append(ByteArray.toHexString(permission.getOperations().toByteArray())); - result.append("\n"); - if (permission.getKeysCount() > 0) { - result.append("keys:"); - result.append("\n"); - result.append("["); - result.append("\n"); - for (Key key : permission.getKeysList()) { - result.append(printKey(key)); - } - result.append("]"); - result.append("\n"); - } - return result.toString(); - } - - /** - * constructor. - */ - public static String printKey(Key key) { - StringBuffer result = new StringBuffer(); - result.append("address: "); - result.append(encode58Check(key.getAddress().toByteArray())); - result.append("\n"); - result.append("weight: "); - result.append(key.getWeight()); - result.append("\n"); - return result.toString(); - } - - /** - * constructor. - */ - public static String encode58Check(byte[] input) { - byte[] hash0 = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), input); - byte[] hash1 = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), hash0); - byte[] inputCheck = new byte[input.length + 4]; - System.arraycopy(input, 0, inputCheck, 0, input.length); - System.arraycopy(hash1, 0, inputCheck, input.length, 4); - return Base58.encode(inputCheck); - } - - /** - * constructor. - */ - public static Transaction sendcoinWithPermissionIdNotSign(byte[] to, long amount, byte[] owner, - int permissionId, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - //Protocol.Account search = queryAccount(priKey, blockingStubFull); - - TransferContract.Builder builder = TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.createTransaction2(contract); - - Transaction transaction = transactionExtention.getTransaction(); - raw rawData = transaction.getRawData(); - Transaction.Contract contract1 = transactionExtention.getTransaction().getRawData() - .getContractList().get(0); - contract1 = contract1.toBuilder().setPermissionId(permissionId).build(); - rawData = rawData.toBuilder().clearContract().addContract(contract1).build(); - transaction = transaction.toBuilder().setRawData(rawData).build(); - - return transaction; - - } - - /** - * constructor. - */ - public static TransactionSignWeight getTransactionSignWeight(Transaction transaction, - WalletGrpc.WalletBlockingStub blockingStubFull) { - return blockingStubFull.getTransactionSignWeight(transaction); - } - - /** - * constructor. - */ - public static Return broadcastTransaction1(Transaction transaction, - WalletGrpc.WalletBlockingStub blockingStubFull) { - - return PublicMethed.broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - public static boolean accountPermissionUpdateWithPermissionId(String permissionJson, byte[] owner, - String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, int permissionId, - String[] priKeys) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - AccountPermissionUpdateContract.Builder builder = AccountPermissionUpdateContract.newBuilder(); - - JSONObject permissions = JSONObject.parseObject(permissionJson); - JSONObject ownersPermission = permissions.getJSONObject("owner_permission"); - JSONObject witnesssPermission = permissions.getJSONObject("witness_permission"); - JSONArray activesPermissions = permissions.getJSONArray("active_permissions"); - - if (ownersPermission != null) { - Permission ownerPermission = json2Permission(ownersPermission); - builder.setOwner(ownerPermission); - } - if (witnesssPermission != null) { - Permission witnessPermission = json2Permission(witnesssPermission); - builder.setWitness(witnessPermission); - } - if (activesPermissions != null) { - List activePermissionList = new ArrayList<>(); - for (int j = 0; j < activesPermissions.size(); j++) { - JSONObject permission = activesPermissions.getJSONObject(j); - activePermissionList.add(json2Permission(permission)); - } - builder.addAllActives(activePermissionList); - } - builder.setOwnerAddress(ByteString.copyFrom(owner)); - - AccountPermissionUpdateContract contract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.accountPermissionUpdate(contract); - - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - - Transaction transaction = transactionExtention.getTransaction(); - raw rawData = transaction.getRawData(); - Transaction.Contract contract1 = transactionExtention.getTransaction().getRawData() - .getContractList().get(0); - contract1 = contract1.toBuilder().setPermissionId(permissionId).build(); - rawData = rawData.toBuilder().clearContract().addContract(contract1).build(); - transaction = transaction.toBuilder().setRawData(rawData).build(); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = signTransaction(transaction, blockingStubFull, priKeys); - Return response = broadcastTransaction1(transaction, blockingStubFull); - return response.getResult(); - } - - /** - * constructor. - */ - public static Transaction accountPermissionUpdateWithoutSign(String permissionJson, byte[] owner, - String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, String[] priKeys) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - AccountPermissionUpdateContract.Builder builder = AccountPermissionUpdateContract.newBuilder(); - - JSONObject permissions = JSONObject.parseObject(permissionJson); - JSONObject ownersPermission = permissions.getJSONObject("owner_permission"); - JSONObject witnesssPermission = permissions.getJSONObject("witness_permission"); - JSONArray activesPermissions = permissions.getJSONArray("active_permissions"); - - if (ownersPermission != null) { - Permission ownerPermission = json2Permission(ownersPermission); - builder.setOwner(ownerPermission); - } - if (witnesssPermission != null) { - Permission witnessPermission = json2Permission(witnesssPermission); - builder.setWitness(witnessPermission); - } - if (activesPermissions != null) { - List activePermissionList = new ArrayList<>(); - for (int j = 0; j < activesPermissions.size(); j++) { - JSONObject permission = activesPermissions.getJSONObject(j); - activePermissionList.add(json2Permission(permission)); - } - builder.addAllActives(activePermissionList); - } - builder.setOwnerAddress(ByteString.copyFrom(owner)); - - AccountPermissionUpdateContract contract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.accountPermissionUpdate(contract); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transaction; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - return transaction; - } - - /** - * constructor. - */ - public static Transaction addTransactionSignWithPermissionId(Transaction transaction, - String priKey, int permissionId, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - - //transaction = setPermissionId(transaction, permissionId); - Transaction.raw.Builder raw = transaction.getRawData().toBuilder(); - Transaction.Contract.Builder contract = raw.getContract(0).toBuilder() - .setPermissionId(permissionId); - raw.clearContract(); - raw.addContract(contract); - transaction = transaction.toBuilder().setRawData(raw).build(); - - Transaction.Builder transactionBuilderSigned = transaction.toBuilder(); - byte[] hash = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()); - ECKey ecKey = temKey; - ECDSASignature signature = ecKey.sign(hash); - ByteString bsSign = ByteString.copyFrom(signature.toByteArray()); - transactionBuilderSigned.addSignature(bsSign); - transaction = transactionBuilderSigned.build(); - return transaction; - } - - /** - * constructor. - */ - public static Transaction setPermissionId(Transaction transaction, int permissionId) - throws CancelException { - if (transaction.getSignatureCount() != 0 - || transaction.getRawData().getContract(0).getPermissionId() != 0) { - return transaction; - } - if (permissionId < 0) { - throw new CancelException("User cancelled"); - } - if (permissionId != 0) { - Transaction.raw.Builder raw = transaction.getRawData().toBuilder(); - Transaction.Contract.Builder contract = raw.getContract(0).toBuilder() - .setPermissionId(permissionId); - raw.clearContract(); - raw.addContract(contract); - transaction = transaction.toBuilder().setRawData(raw).build(); - } - return transaction; - } - - /** - * constructor. - */ - public static int getActivePermissionKeyCount(List permissionList) { - int permissionCount = 0; - for (Permission permission : permissionList) { - permissionCount += permission.getKeysCount(); - } - return permissionCount; - } - - /** - * constructor. - */ - public static Boolean sendcoinWithPermissionId(byte[] to, long amount, byte[] owner, - int permissionId, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - //Protocol.Account search = queryAccount(priKey, blockingStubFull); - - TransferContract.Builder builder = TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.createTransaction2(contract); - - Transaction transaction = transactionExtention.getTransaction(); - raw rawData = transaction.getRawData(); - Transaction.Contract contract1 = transactionExtention.getTransaction().getRawData() - .getContractList().get(0); - contract1 = contract1.toBuilder().setPermissionId(permissionId).build(); - rawData = rawData.toBuilder().clearContract().addContract(contract1).build(); - transaction = transaction.toBuilder().setRawData(rawData).build(); - transactionExtention = transactionExtention.toBuilder().setTransaction(transaction).build(); - - if (transactionExtention == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction ==null"); - return null; - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - - } - - /** - * constructor. - */ - public static void recoverWitnessPermission(String ownerKey, List ownerPermissionKeys, - WalletGrpc.WalletBlockingStub blockingStubFull) { - - PublicMethed.printAddress(ownerKey); - byte[] ownerAddress = new WalletClient(ownerKey).getAddress(); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":1,\"keys\":[" + "{\"address\":\"" + PublicMethed - .getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - - Assert.assertTrue( - accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(1, getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getWitnessPermission() - .getKeysCount()); - } - - /** - * constructor. - */ - public static String getOperations(Integer[] ints) { - List list = new ArrayList<>(Arrays.asList(ints)); - byte[] operations = new byte[32]; - list.forEach(e -> { - operations[e / 8] |= (1 << e % 8); - }); - - System.out.println(ByteArray.toHexString(operations)); - return ByteArray.toHexString(operations); - } - - /** - * constructor. - */ - public static GrpcAPI.Return accountPermissionUpdateForResponse(String permissionJson, - byte[] owner, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, - String[] priKeys) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - AccountPermissionUpdateContract.Builder builder = AccountPermissionUpdateContract.newBuilder(); - - JSONObject permissions = JSONObject.parseObject(permissionJson); - JSONObject ownersPermission = permissions.getJSONObject("owner_permission"); - JSONObject witnesssPermission = permissions.getJSONObject("witness_permission"); - JSONArray activesPermissions = permissions.getJSONArray("active_permissions"); - - if (ownersPermission != null) { - Permission ownerPermission = json2Permission(ownersPermission); - builder.setOwner(ownerPermission); - } - if (witnesssPermission != null) { - Permission witnessPermission = json2Permission(witnesssPermission); - builder.setWitness(witnessPermission); - } - if (activesPermissions != null) { - List activePermissionList = new ArrayList<>(); - for (int j = 0; j < activesPermissions.size(); j++) { - JSONObject permission = activesPermissions.getJSONObject(j); - activePermissionList.add(json2Permission(permission)); - } - builder.addAllActives(activePermissionList); - } - builder.setOwnerAddress(ByteString.copyFrom(owner)); - - AccountPermissionUpdateContract contract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.accountPermissionUpdate(contract); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return ret; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = signTransaction(transaction, blockingStubFull, priKeys); - Return response = broadcastTransaction1(transaction, blockingStubFull); - return response; - } - - /** - * constructor. - */ - public static void recoverAccountPermission(String ownerKey, List ownerPermissionKeys, - WalletGrpc.WalletBlockingStub blockingStubFull) { - - PublicMethed.printAddress(ownerKey); - byte[] ownerAddress = new WalletClient(ownerKey).getAddress(); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - - Assert.assertTrue( - accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(1, getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - } - - /** - * constructor. - */ - public static Transaction sendcoin2(byte[] to, long amount, byte[] owner, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - //Protocol.Account search = queryAccount(priKey, blockingStubFull); - - TransferContract.Builder builder = TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferContract contract = builder.build(); - Transaction transaction = blockingStubFull.createTransaction(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction ==null"); - return null; - } - return transaction; - - } - - /** - * constructor. - */ - public static Protocol.Transaction createFakeTransaction(byte[] toAddrss, Long amount, - byte[] fromAddress) { - - TransferContract contract = TransferContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(fromAddress)) - .setToAddress(ByteString.copyFrom(toAddrss)).setAmount(amount).build(); - Protocol.Transaction transaction = createTransaction(contract, ContractType.TransferContract); - - return transaction; - } - - /** - * constructor. - */ - private static Transaction setReference(Transaction transaction, long blockNum, - byte[] blockHash) { - byte[] refBlockNum = ByteArray.fromLong(blockNum); - Transaction.raw rawData = transaction.getRawData().toBuilder() - .setRefBlockHash(ByteString.copyFrom(blockHash)) - .setRefBlockBytes(ByteString.copyFrom(refBlockNum)).build(); - return transaction.toBuilder().setRawData(rawData).build(); - } - - /** - * constructor. - */ - public static Transaction setExpiration(Transaction transaction, long expiration) { - Transaction.raw rawData = transaction.getRawData().toBuilder().setExpiration(expiration) - .build(); - return transaction.toBuilder().setRawData(rawData).build(); - } - - /** - * constructor. - */ - public static Transaction createTransaction(com.google.protobuf.Message message, - ContractType contractType) { - Transaction.raw.Builder transactionBuilder = Transaction.raw.newBuilder().addContract( - Transaction.Contract.newBuilder().setType(contractType).setParameter(Any.pack(message)) - .build()); - - Transaction transaction = Transaction.newBuilder().setRawData(transactionBuilder.build()) - .build(); - - long time = System.currentTimeMillis(); - AtomicLong count = new AtomicLong(); - long geTime = count.incrementAndGet() + time; - String ref = "" + geTime; - - transaction = setReference(transaction, geTime, ByteArray.fromString(ref)); - - transaction = setExpiration(transaction, geTime); - - return transaction; - } - - /** - * constructor. - */ - - public static String triggerContractWithPermissionId(byte[] contractAddress, String method, - String argsStr, Boolean isHex, long callValue, long feeLimit, String tokenId, long tokenValue, - byte[] ownerAddress, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, - String[] permissionKeyString, int permissionId) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - if (argsStr.equalsIgnoreCase("#")) { - logger.info("argsstr is #"); - argsStr = ""; - } - - byte[] owner = ownerAddress; - byte[] input = Hex.decode(AbiUtil.parseMethod(method, argsStr, isHex)); - - TriggerSmartContract.Builder builder = TriggerSmartContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - builder.setData(ByteString.copyFrom(input)); - builder.setCallValue(callValue); - builder.setTokenId(Long.parseLong(tokenId)); - builder.setCallTokenValue(tokenValue); - TriggerSmartContract triggerContract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.triggerContract(triggerContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create call trx failed!"); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction.getRetCount() != 0 && transactionExtention.getConstantResult(0) != null - && transactionExtention.getResult() != null) { - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = transactionExtention.getTransaction().getRawData() - .toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - - System.out.println("trigger txid = " + ByteArray - .toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()))); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - broadcastTransaction(transaction, blockingStubFull); - return ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray())); - } - - /** - * constructor. - */ - - public static byte[] generateContractAddress(Transaction trx, byte[] owneraddress) { - - // get owner address - // this address should be as same as the onweraddress in trx, DONNOT modify it - byte[] ownerAddress = owneraddress; - - // get tx hash - byte[] txRawDataHash = Sha256Hash.of(CommonParameter.getInstance() - .isECKeyCryptoEngine(), trx.getRawData().toByteArray()).getBytes(); - - // combine - byte[] combined = new byte[txRawDataHash.length + ownerAddress.length]; - System.arraycopy(txRawDataHash, 0, combined, 0, txRawDataHash.length); - System.arraycopy(ownerAddress, 0, combined, txRawDataHash.length, ownerAddress.length); - - return sha3omit12(combined); - - } - - /** - * constructor. - */ - - public static byte[] deployContractWithPermissionId(String contractName, String abiString, - String code, String data, Long feeLimit, long value, long consumeUserResourcePercent, - long originEnergyLimit, String tokenId, long tokenValue, String libraryAddress, String priKey, - byte[] ownerAddress, WalletGrpc.WalletBlockingStub blockingStubFull, - String[] permissionKeyString, int permissionId) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - SmartContract.ABI abi = jsonStr2Abi(abiString); - if (abi == null) { - logger.error("abi is null"); - return null; - } - //byte[] codeBytes = Hex.decode(code); - SmartContract.Builder builder = SmartContract.newBuilder(); - builder.setName(contractName); - builder.setOriginAddress(ByteString.copyFrom(owner)); - builder.setAbi(abi); - builder.setConsumeUserResourcePercent(consumeUserResourcePercent); - builder.setOriginEnergyLimit(originEnergyLimit); - - if (value != 0) { - - builder.setCallValue(value); - } - - byte[] byteCode; - if (null != libraryAddress) { - byteCode = replaceLibraryAddress(code, libraryAddress); - } else { - byteCode = Hex.decode(code); - } - builder.setBytecode(ByteString.copyFrom(byteCode)); - - Builder contractBuilder = CreateSmartContract.newBuilder(); - contractBuilder.setOwnerAddress(ByteString.copyFrom(owner)); - contractBuilder.setCallTokenValue(tokenValue); - contractBuilder.setTokenId(Long.parseLong(tokenId)); - CreateSmartContract contractDeployContract = contractBuilder.setNewContract(builder.build()) - .build(); - - TransactionExtention transactionExtention = blockingStubFull - .deployContract(contractDeployContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create trx failed!"); - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = transactionExtention.getTransaction().getRawData() - .toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - - byte[] contractAddress = generateContractAddress(transactionExtention.getTransaction(), owner); - System.out.println( - "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - System.out.println( - "txid = " + ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()))); - contractAddress = generateContractAddress(transaction, owner); - System.out.println( - "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); - - GrpcAPI.Return response = broadcastTransaction1(transaction, blockingStubFull); - if (response.getResult() == false) { - return null; - } else { - //logger.info("brodacast succesfully"); - return contractAddress; - } - } - - - /** - * constructor. - */ - public static byte[] deployContract1(String contractName, String abiString, String code, - String data, Long feeLimit, long value, long consumeUserResourcePercent, - String libraryAddress, String priKey, byte[] ownerAddress, - WalletGrpc.WalletBlockingStub blockingStubFull, int permissionId, - String[] permissionKeyString) { - - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - SmartContract.ABI abi = jsonStr2Abi(abiString); - if (abi == null) { - logger.error("abi is null"); - return null; - } - //byte[] codeBytes = Hex.decode(code); - SmartContract.Builder builder = SmartContract.newBuilder(); - builder.setName(contractName); - builder.setOriginAddress(ByteString.copyFrom(owner)); - builder.setAbi(abi); - builder.setConsumeUserResourcePercent(consumeUserResourcePercent); - builder.setOriginEnergyLimit(1000L); - - if (value != 0) { - - builder.setCallValue(value); - } - - byte[] byteCode; - if (null != libraryAddress) { - byteCode = replaceLibraryAddress(code, libraryAddress); - } else { - byteCode = Hex.decode(code); - } - builder.setBytecode(ByteString.copyFrom(byteCode)); - - Builder contractBuilder = CreateSmartContract.newBuilder(); - contractBuilder.setOwnerAddress(ByteString.copyFrom(owner)); - contractBuilder.setCallTokenValue(0L); - contractBuilder.setTokenId(Long.parseLong("0")); - CreateSmartContract contractDeployContract = contractBuilder.setNewContract(builder.build()) - .build(); - - TransactionExtention transactionExtention = blockingStubFull - .deployContract(contractDeployContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create trx failed!"); - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = transactionExtention.getTransaction().getRawData() - .toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - - byte[] contractAddress = PublicMethed - .generateContractAddress(transactionExtention.getTransaction(), owner); - System.out.println( - "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - System.out.println( - "txid = " + ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()))); - contractAddress = PublicMethed.generateContractAddress(transaction, owner); - System.out.println( - "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); - broadcastTransaction(transaction, blockingStubFull); - return contractAddress; - } - - /** - * constructor. - */ - public static String triggerContract1(byte[] contractAddress, String method, String argsStr, - Boolean isHex, long callValue, long feeLimit, byte[] ownerAddress, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, int permissionId, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - if (argsStr.equalsIgnoreCase("#")) { - logger.info("argsstr is #"); - argsStr = ""; - } - - byte[] owner = ownerAddress; - byte[] input = Hex.decode(AbiUtil.parseMethod(method, argsStr, isHex)); - - TriggerSmartContract.Builder builder = TriggerSmartContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - builder.setData(ByteString.copyFrom(input)); - builder.setCallValue(callValue); - builder.setTokenId(Long.parseLong("0")); - builder.setCallTokenValue(0L); - TriggerSmartContract triggerContract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.triggerContract(triggerContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create call trx failed!"); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - return null; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction.getRetCount() != 0 && transactionExtention.getConstantResult(0) != null - && transactionExtention.getResult() != null) { - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - return null; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = transactionExtention.getTransaction().getRawData() - .toBuilder(); - rawBuilder.setFeeLimit(feeLimit); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - if (transactionExtention == null) { - return null; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return null; - } - transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return null; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - System.out.println("trigger txid = " + ByteArray - .toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()))); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - broadcastTransaction(transaction, blockingStubFull); - return ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray())); - } - - /** - * constructor. - */ - - public static boolean updateAccountWithPermissionId(byte[] addressBytes, byte[] accountNameBytes, - String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, int permissionId, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - AccountUpdateContract.Builder builder = AccountUpdateContract.newBuilder(); - ByteString basAddreess = ByteString.copyFrom(addressBytes); - ByteString bsAccountName = ByteString.copyFrom(accountNameBytes); - - builder.setAccountName(bsAccountName); - builder.setOwnerAddress(basAddreess); - - AccountUpdateContract contract = builder.build(); - Transaction transaction = blockingStubFull.updateAccount(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("Please check!!! transaction == null"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - - /** - * constructor. - */ - - public static String transferAssetForTransactionId1(byte[] to, byte[] assertName, long amount, - byte[] address, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, - int permissionId, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.transferAsset(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - if (transaction == null) { - logger.info("transaction == null"); - } else { - logger.info("transaction.getRawData().getContractCount() == 0"); - } - return null; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - boolean result = broadcastTransaction(transaction, blockingStubFull); - if (result == false) { - return null; - } else { - return ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray())); - } - } - - - /** - * constructor. - */ - - public static Boolean freezeBalanceGetEnergyWithPermissionId(byte[] addRess, long freezeBalance, - long freezeDuration, int resourceCode, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, int permissionId, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - FreezeBalanceContract.Builder builder = FreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration).setResourceValue(resourceCode); - - FreezeBalanceContract contract = builder.build(); - Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction = null"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - transaction = TransactionUtils.setTimestamp(transaction); - - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - - /** - * constructor. - */ - - public static Boolean freezeBalanceForReceiverWithPermissionId(byte[] addRess, long freezeBalance, - long freezeDuration, int resourceCode, ByteString receiverAddressBytes, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, int permissionId, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - FreezeBalanceContract.Builder builder = FreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration).setResourceValue(resourceCode); - builder.setReceiverAddress(receiverAddressBytes); - FreezeBalanceContract contract = builder.build(); - Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction = null"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - transaction = TransactionUtils.setTimestamp(transaction); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - - /** - * constructor. - */ - - public static boolean createAccount1(byte[] ownerAddress, byte[] newAddress, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, int permissionId, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - AccountCreateContract.Builder builder = AccountCreateContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setAccountAddress(ByteString.copyFrom(newAddress)); - AccountCreateContract contract = builder.build(); - Transaction transaction = blockingStubFull.createAccount(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - - } - - /** - * constructor. - */ - - public static boolean setAccountId1(byte[] accountIdBytes, byte[] ownerAddress, String priKey, - int permissionId, WalletGrpc.WalletBlockingStub blockingStubFull, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - SetAccountIdContract.Builder builder = SetAccountIdContract.newBuilder(); - ByteString bsAddress = ByteString.copyFrom(owner); - ByteString bsAccountId = ByteString.copyFrom(accountIdBytes); - builder.setAccountId(bsAccountId); - builder.setOwnerAddress(bsAddress); - SetAccountIdContract contract = builder.build(); - Transaction transaction = blockingStubFull.setAccountId(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - return broadcastTransaction(transaction, blockingStubFull); - //Return response = broadcastTransaction1(transaction, blockingStubFull); - //if (response.getResult() == false) { - // logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - // return false; - //} else { - // return true; - //} - //return response.getResult(); - } - - - /** - * constructor. - */ - public static Boolean voteWitnessWithPermissionId(HashMap witness, byte[] addRess, - String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, int permissionId, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - VoteWitnessContract.Builder builder = VoteWitnessContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(addRess)); - for (String addressBase58 : witness.keySet()) { - String value = witness.get(addressBase58); - final long count = Long.parseLong(value); - VoteWitnessContract.Vote.Builder voteBuilder = VoteWitnessContract.Vote.newBuilder(); - byte[] address = WalletClient.decodeFromBase58Check(addressBase58); - if (address == null) { - continue; - } - voteBuilder.setVoteAddress(ByteString.copyFrom(address)); - voteBuilder.setVoteCount(count); - builder.addVotes(voteBuilder.build()); - } - - VoteWitnessContract contract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.voteWitnessAccount2(contract); - Transaction transaction = transactionExtention.getTransaction(); - - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static String createAssetIssueForTransactionId1(byte[] address, String name, - Long totalSupply, Integer trxNum, Integer icoNum, Long startTime, Long endTime, - Integer voteScore, String description, String url, Long freeAssetNetLimit, - Long publicFreeAssetNetLimit, Long fronzenAmount, Long frozenDay, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, int permissionId, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - try { - AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - builder.setFreeAssetNetLimit(freeAssetNetLimit); - builder.setPublicFreeAssetNetLimit(publicFreeAssetNetLimit); - AssetIssueContract.FrozenSupply.Builder frozenBuilder = AssetIssueContract.FrozenSupply - .newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - - builder.addFrozenSupply(0, frozenBuilder); - - Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return null; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - boolean result = broadcastTransaction(transaction, blockingStubFull); - if (result == false) { - return null; - } else { - return ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray())); - } - } catch (Exception ex) { - ex.printStackTrace(); - return null; - } - } - - /** - * constructor. - */ - - public static Boolean injectExchange1(long exchangeId, byte[] tokenId, long quant, - byte[] ownerAddress, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, - int permissionId, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - - ExchangeInjectContract.Builder builder = ExchangeInjectContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)).setExchangeId(exchangeId) - .setTokenId(ByteString.copyFrom(tokenId)).setQuant(quant); - ExchangeInjectContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.exchangeInject(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - - /** - * constructor. - */ - - public static boolean exchangeWithdraw1(long exchangeId, byte[] tokenId, long quant, - byte[] ownerAddress, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, - int permissionId, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - byte[] owner = ownerAddress; - - ExchangeWithdrawContract.Builder builder = ExchangeWithdrawContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)).setExchangeId(exchangeId) - .setTokenId(ByteString.copyFrom(tokenId)).setQuant(quant); - ExchangeWithdrawContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.exchangeWithdraw(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - - /** - * constructor. - */ - - public static boolean exchangeTransaction1(long exchangeId, byte[] tokenId, long quant, - long expected, byte[] ownerAddress, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, int permissionId, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - byte[] owner = ownerAddress; - - ExchangeTransactionContract.Builder builder = ExchangeTransactionContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)).setExchangeId(exchangeId) - .setTokenId(ByteString.copyFrom(tokenId)).setQuant(quant).setExpected(expected); - ExchangeTransactionContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.exchangeTransaction(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static Boolean exchangeCreate1(byte[] firstTokenId, long firstTokenBalance, - byte[] secondTokenId, long secondTokenBalance, byte[] ownerAddress, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, int permissionId, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - - ExchangeCreateContract.Builder builder = ExchangeCreateContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)) - .setFirstTokenId(ByteString.copyFrom(firstTokenId)).setFirstTokenBalance(firstTokenBalance) - .setSecondTokenId(ByteString.copyFrom(secondTokenId)) - .setSecondTokenBalance(secondTokenBalance); - ExchangeCreateContract contract = builder.build(); - TransactionExtention transactionExtention = blockingStubFull.exchangeCreate(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - public static boolean clearContractAbi(byte[] contractAddress, byte[] ownerAddress, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, int permissionId, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] owner = ownerAddress; - - ClearABIContract.Builder builder = ClearABIContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setContractAddress(ByteString.copyFrom(contractAddress)); - - ClearABIContract clearABIContract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.clearContractABI(clearABIContract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create call trx failed!"); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction.getRetCount() != 0 && transactionExtention.getConstantResult(0) != null - && transactionExtention.getResult() != null) { - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - return false; - } - - final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); - Transaction.Builder transBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = transactionExtention.getTransaction().getRawData() - .toBuilder(); - transBuilder.setRawData(rawBuilder); - for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { - ByteString s = transactionExtention.getTransaction().getSignature(i); - transBuilder.setSignature(i, s); - } - for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { - Result r = transactionExtention.getTransaction().getRet(i); - transBuilder.setRet(i, r); - } - texBuilder.setTransaction(transBuilder); - texBuilder.setResult(transactionExtention.getResult()); - texBuilder.setTxid(transactionExtention.getTxid()); - transactionExtention = texBuilder.build(); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - System.out.println("trigger txid = " + ByteArray - .toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()))); - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - public static boolean sendShieldCoin(byte[] publicZenTokenOwnerAddress, long fromAmount, - ShieldAddressInfo shieldAddressInfo, NoteTx noteTx, List shieldOutputList, - byte[] publicZenTokenToAddress, long toAmount, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull, Integer permission_id, - String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - PrivateParameters.Builder builder = PrivateParameters.newBuilder(); - if (!ByteUtil.isNullOrZeroArray(publicZenTokenOwnerAddress)) { - builder.setTransparentFromAddress(ByteString.copyFrom(publicZenTokenOwnerAddress)); - builder.setFromAmount(fromAmount); - } - if (!ByteUtil.isNullOrZeroArray(publicZenTokenToAddress)) { - builder.setTransparentToAddress(ByteString.copyFrom(publicZenTokenToAddress)); - builder.setToAmount(toAmount); - } - - if (shieldAddressInfo != null) { - OutputPointInfo.Builder request = OutputPointInfo.newBuilder(); - - //ShieldNoteInfo noteInfo = shieldWrapper.getUtxoMapNote().get(shieldInputList.get(i)); - OutputPoint.Builder outPointBuild = OutputPoint.newBuilder(); - outPointBuild.setHash(ByteString.copyFrom(noteTx.getTxid().toByteArray())); - outPointBuild.setIndex(noteTx.getIndex()); - request.addOutPoints(outPointBuild.build()); - - //ShieldNoteInfo noteInfo = shieldWrapper.getUtxoMapNote().get(shieldInputList.get(i)); - - //String shieldAddress = noteInfo.getPaymentAddress(); - //ShieldAddressInfo addressInfo = - // shieldWrapper.getShieldAddressInfoMap().get(shieldAddress); - SpendingKey spendingKey = new SpendingKey(shieldAddressInfo.getSk()); - try { - ExpandedSpendingKey expandedSpendingKey = spendingKey.expandedSpendingKey(); - builder.setAsk(ByteString.copyFrom(expandedSpendingKey.getAsk())); - builder.setNsk(ByteString.copyFrom(expandedSpendingKey.getNsk())); - builder.setOvk(ByteString.copyFrom(expandedSpendingKey.getOvk())); - } catch (Exception e) { - System.out.println(e); - } - - Note.Builder noteBuild = Note.newBuilder(); - noteBuild.setPaymentAddress(shieldAddressInfo.getAddress()); - noteBuild.setValue(noteTx.getNote().getValue()); - noteBuild.setRcm(ByteString.copyFrom(noteTx.getNote().getRcm().toByteArray())); - noteBuild.setMemo(ByteString.copyFrom(noteTx.getNote().getMemo().toByteArray())); - - //System.out.println("address " + noteInfo.getPaymentAddress()); - //System.out.println("value " + noteInfo.getValue()); - //System.out.println("rcm " + ByteArray.toHexString(noteInfo.getR())); - //System.out.println("trxId " + noteInfo.getTrxId()); - //System.out.println("index " + noteInfo.getIndex()); - //System.out.println("meno " + new String(noteInfo.getMemo())); - - SpendNote.Builder spendNoteBuilder = SpendNote.newBuilder(); - spendNoteBuilder.setNote(noteBuild.build()); - try { - spendNoteBuilder.setAlpha(ByteString.copyFrom(org.tron.core.zen.note.Note.generateR())); - } catch (Exception e) { - System.out.println(e); - } - - IncrementalMerkleVoucherInfo merkleVoucherInfo = blockingStubFull - .getMerkleTreeVoucherInfo(request.build()); - spendNoteBuilder.setVoucher(merkleVoucherInfo.getVouchers(0)); - spendNoteBuilder.setPath(merkleVoucherInfo.getPaths(0)); - - builder.addShieldedSpends(spendNoteBuilder.build()); - - } else { - byte[] ovk = ByteArray - .fromHexString("030c8c2bc59fb3eb8afb047a8ea4b028743d23e7d38c6fa30908358431e2314d"); - builder.setOvk(ByteString.copyFrom(ovk)); - } - - if (shieldOutputList.size() > 0) { - for (int i = 0; i < shieldOutputList.size(); ++i) { - builder - .addShieldedReceives(ReceiveNote.newBuilder().setNote(shieldOutputList.get(i)).build()); - } - } - - TransactionExtention transactionExtention = blockingStubFull - .createShieldedTransaction(builder.build()); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - Any any = transaction.getRawData().getContract(0).getParameter(); - - try { - ShieldContract.ShieldedTransferContract shieldedTransferContract = any - .unpack(ShieldContract.ShieldedTransferContract.class); - if (shieldedTransferContract.getFromAmount() > 0 || fromAmount == 321321) { - Transaction.raw.Builder raw = transaction.getRawData().toBuilder(); - Transaction.Contract.Builder contract = raw.getContract(0).toBuilder() - .setPermissionId(permission_id); - raw.clearContract(); - raw.addContract(contract); - transaction = transaction.toBuilder().setRawData(raw).build(); - - transaction = signTransactionForShield(transaction, blockingStubFull, permissionKeyString); - System.out.println("trigger txid = " + ByteArray - .toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()))); - } else { - System.out.println("trigger txid = " + ByteArray - .toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()))); - } - } catch (Exception e) { - System.out.println(e); - } - return broadcastTransaction(transaction, blockingStubFull); - } - - - /** - * constructor. - */ - private static Transaction signTransactionForShield(Transaction transaction, - WalletGrpc.WalletBlockingStub blockingStubFull, String[] priKeys) { - /* if (transaction.getRawData().getTimestamp() == 0) { - transaction = TransactionUtils.setTimestamp(transaction); - } - - long currentTime = System.currentTimeMillis();//*1000000 + System.nanoTime()%1000000; - Transaction.Builder builder = transaction.toBuilder(); - org.tron.protos.Protocol.Transaction.raw.Builder rowBuilder = transaction.getRawData() - .toBuilder(); - rowBuilder.setTimestamp(currentTime); - builder.setRawData(rowBuilder.build()); - transaction = builder.build();*/ - - for (int i = 0; i < priKeys.length; i += 1) { - String priKey = priKeys[i]; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - transaction = TransactionUtils.sign(transaction, ecKey); - TransactionSignWeight weight = blockingStubFull.getTransactionSignWeight(transaction); - if (weight.getResult().getCode() - == TransactionSignWeight.Result.response_code.ENOUGH_PERMISSION) { - break; - } - if (weight.getResult().getCode() - == TransactionSignWeight.Result.response_code.NOT_ENOUGH_PERMISSION) { - continue; - } - } - logger.info("Sign transaction:" + transaction.toString()); - return transaction; - } - - /** - * constructor. - */ - public static boolean createWitness(String url, byte[] owner, String priKey, int permissionId, - String[] permissionKeyString, WalletGrpc.WalletBlockingStub blockingStubFull) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - byte[] byteurl = url.getBytes(); - WitnessCreateContract.Builder builder = WitnessCreateContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setUrl(ByteString.copyFrom(byteurl)); - WitnessCreateContract contract = builder.build(); - - TransactionExtention transactionExtention = blockingStubFull.createWitness2(contract); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - System.out.println("RPC create trx failed!"); - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return false; - } - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - - public static boolean updateWitness2(byte[] owner, byte[] url, String priKey, int permissionId, - String[] permissionKeyString, WalletGrpc.WalletBlockingStub blockingStubFull) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - WitnessUpdateContract.Builder builder = WitnessUpdateContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setUpdateUrl(ByteString.copyFrom(url)); - WitnessUpdateContract contract = builder.build(); - - GrpcAPI.TransactionExtention transactionExtention = blockingStubFull.updateWitness2(contract); - if (transactionExtention == null) { - return transactionExtention.getResult().getResult(); - } - GrpcAPI.Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Protocol.Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (!response.getResult()) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - logger.info("response.getRestult() == false"); - return false; - } - return true; - } - - /** - * constructor. - */ - public static boolean withdrawBalance(byte[] address, String priKey, int permissionId, - String[] permissionKeyString, WalletGrpc.WalletBlockingStub blockingStubFull) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - WithdrawBalanceContract.Builder builder = WithdrawBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - builder.setOwnerAddress(byteAddreess); - WithdrawBalanceContract contract = builder.build(); - - Transaction transaction = blockingStubFull.withdrawBalance(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = signTransaction(ecKey, transaction); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - return true; - } - - /** - * constructor. - */ - public static boolean unFreezeAsset(byte[] addRess, String priKey, int permissionId, - String[] permissionKeyString, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address = addRess; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - UnfreezeAssetContract.Builder builder = UnfreezeAssetContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - builder.setOwnerAddress(byteAddreess); - UnfreezeAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.unfreezeAsset(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = signTransaction(ecKey, transaction); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - } catch (CancelException e) { - e.printStackTrace(); - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - return true; - } - - /** - * constructor. - */ - - public static Transaction sendcoinGetTransaction(byte[] to, long amount, byte[] owner, - String priKey, WalletGrpc.WalletBlockingStub blockingStubFull, String[] permissionKeyString) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - //Protocol.Account search = queryAccount(priKey, blockingStubFull); - - TransferContract.Builder builder = TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferContract contract = builder.build(); - Transaction transaction = blockingStubFull.createTransaction(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction ==null"); - return null; - } - transaction = signTransaction(transaction, blockingStubFull, permissionKeyString); - - return transaction; - - } - - /** - * constructor. - */ - public static boolean updateBrokerage(byte[] owner, int brokerage, String priKey, - int permissionId, String[] priKeys, WalletGrpc.WalletBlockingStub blockingStubFull) { - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - UpdateBrokerageContract.Builder updateBrokerageContract = UpdateBrokerageContract.newBuilder(); - updateBrokerageContract.setOwnerAddress(ByteString.copyFrom(owner)).setBrokerage(brokerage); - TransactionExtention transactionExtention = blockingStubFull - .updateBrokerage(updateBrokerageContract.build()); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - if (transactionExtention == null || !transactionExtention.getResult().getResult()) { - if (transactionExtention != null) { - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - } - return false; - } - try { - transaction = setPermissionId(transaction, permissionId); - transaction = signTransaction(transaction, blockingStubFull, priKeys); - } catch (Exception e) { - e.printStackTrace(); - } - - System.out.println("trigger txid = " + ByteArray - .toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()))); - - return broadcastTransaction(transaction, blockingStubFull); - } - - /** - * constructor. - */ - public static boolean marketSellAsset(byte[] owner, byte[] sellTokenId, - long sellTokenQuantity, byte[] buyTokenId, long buyTokenQuantity, - int permissionId, String[] priKeys, WalletBlockingStub blockingStubFull) { - - MarketContract.MarketSellAssetContract.Builder builder = MarketContract.MarketSellAssetContract - .newBuilder(); - builder - .setOwnerAddress(ByteString.copyFrom(owner)) - .setSellTokenId(ByteString.copyFrom(sellTokenId)) - .setSellTokenQuantity(sellTokenQuantity) - .setBuyTokenId(ByteString.copyFrom(buyTokenId)) - .setBuyTokenQuantity(buyTokenQuantity); - - TransactionExtention transactionExtention = blockingStubFull.marketSellAsset(builder.build()); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - - if (transaction.getRawData().getContract(0).getType() - != ContractType.MarketSellAssetContract) { - return false; - } - - try { - transaction = setPermissionId(transaction, permissionId); - transaction = signTransaction(transaction, blockingStubFull, priKeys); - } catch (CancelException e) { - e.printStackTrace(); - } - return broadcastTransaction(transaction, blockingStubFull); - - } - - /** - * constructor. - */ - public static boolean marketCancelOrder(byte[] owner, byte[] orderId, - int permissionId, String[] priKeys, - WalletBlockingStub blockingStubFull) { - - MarketContract.MarketCancelOrderContract.Builder builder = MarketContract - .MarketCancelOrderContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)).setOrderId(ByteString.copyFrom(orderId)); - - TransactionExtention transactionExtention = blockingStubFull.marketCancelOrder(builder.build()); - - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - - if (transaction.getRawData().getContract(0).getType() - != ContractType.MarketCancelOrderContract) { - System.out.println("Wrong ContractType :" - + transaction.getRawData().getContract(0).getType()); - return false; - } - - try { - transaction = setPermissionId(transaction, permissionId); - transaction = signTransaction(transaction,blockingStubFull,priKeys); - } catch (CancelException e) { - e.printStackTrace(); - } - return broadcastTransaction(transaction, blockingStubFull); - } -} diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/Retry.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/Retry.java deleted file mode 100644 index 8c9779504f9..00000000000 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/Retry.java +++ /dev/null @@ -1,50 +0,0 @@ -package stest.tron.wallet.common.client.utils; - -import org.testng.IRetryAnalyzer; -import org.testng.ITestResult; - -public class Retry implements IRetryAnalyzer { - - private int retryCount = 0; - private int maxRetryCount = 2; - - // Below method returns 'true' if the test method has to be retried else 'false' - //and it takes the 'Result' as parameter of the test method that just ran - - /** - * constructor. - */ - - public boolean retry(ITestResult result) { - if (retryCount < maxRetryCount) { - System.out.println("Retrying test " + result.getName() + " with status " - + getResultStatusName(result.getStatus()) + " for the " + (retryCount + 1) + " time(s)."); - retryCount++; - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return true; - } - return false; - } - - /** - * constructor. - */ - - public String getResultStatusName(int status) { - String resultName = null; - if (status == 1) { - resultName = "SUCCESS"; - } - if (status == 2) { - resultName = "FAILURE"; - } - if (status == 3) { - resultName = "SKIP"; - } - return resultName; - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/RetryListener.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/RetryListener.java deleted file mode 100644 index 1e2ac832377..00000000000 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/RetryListener.java +++ /dev/null @@ -1,20 +0,0 @@ -package stest.tron.wallet.common.client.utils; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import org.testng.IAnnotationTransformer; -import org.testng.IRetryAnalyzer; -import org.testng.annotations.ITestAnnotation; - -public class RetryListener implements IAnnotationTransformer { - - @Override - public void transform(ITestAnnotation testannotation, Class testClass, - Constructor testConstructor, Method testMethod) { - IRetryAnalyzer retry = testannotation.getRetryAnalyzer(); - - if (retry == null) { - testannotation.setRetryAnalyzer(Retry.class); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/Sha256Hash.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/Sha256Hash.java deleted file mode 100644 index 6dd758a1501..00000000000 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/Sha256Hash.java +++ /dev/null @@ -1,346 +0,0 @@ -package stest.tron.wallet.common.client.utils; - -/* - * Copyright 2011 Google Inc. - * Copyright 2014 Andreas Schildbach - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import static com.google.common.base.Preconditions.checkArgument; - -import com.google.common.io.ByteStreams; -import com.google.common.primitives.Ints; -import com.google.common.primitives.Longs; -import com.google.protobuf.ByteString; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.Serializable; -import java.math.BigInteger; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; -import org.bouncycastle.crypto.digests.SM3Digest; -import org.tron.common.utils.ByteArray; - - -/** - * A Sha256Hash just wraps a byte[] so that equals and hashcode work correctly, allowing it to be - * used as keys in a map. It also checks that the length is correct and provides a bit more type - * safety. - */ -public class Sha256Hash implements Serializable, Comparable { - - public static final int LENGTH = 32; // bytes - public static final Sha256Hash ZERO_HASH = wrap(new byte[LENGTH]); - - private final byte[] bytes; - - private long blockNum; - - - /** - * constructor. - */ - - public Sha256Hash(long num, byte[] hash) { - byte[] rawHashBytes = this.generateBlockId(num, hash); - checkArgument(rawHashBytes.length == LENGTH); - this.bytes = rawHashBytes; - this.blockNum = num; - } - - /** - * constructor. - */ - - public Sha256Hash(long num, Sha256Hash hash) { - byte[] rawHashBytes = this.generateBlockId(num, hash); - checkArgument(rawHashBytes.length == LENGTH); - this.bytes = rawHashBytes; - this.blockNum = num; - } - - /** - * Use {@link #wrap(byte[])} instead. - */ - @Deprecated - public Sha256Hash(byte[] rawHashBytes) { - checkArgument(rawHashBytes.length == LENGTH); - this.bytes = rawHashBytes; - } - - /** - * Creates a new instance that wraps the given hash value. - * - * @param rawHashBytes the raw hash bytes to wrap - * @return a new instance - * @throws IllegalArgumentException if the given array length is not exactly 32 - */ - @SuppressWarnings("deprecation") // the constructor will be made private in the future - public static Sha256Hash wrap(byte[] rawHashBytes) { - return new Sha256Hash(rawHashBytes); - } - - public static Sha256Hash wrap(ByteString rawHashByteString) { - return wrap(rawHashByteString.toByteArray()); - } - - /** - * Use {@link #of(byte[])} instead: this old name is ambiguous. - */ - @Deprecated - public static Sha256Hash create(boolean isSha256, byte[] contents) { - return of(isSha256, contents); - } - - /** - * Creates a new instance containing the calculated (one-time) hash of the given bytes. - * - * @param contents the bytes on which the hash value is calculated - * @return a new instance containing the calculated (one-time) hash - */ - public static Sha256Hash of(boolean isSha256, byte[] contents) { - return wrap(hash(isSha256, contents)); - } - - /** - * Creates a new instance containing the calculated (one-time) hash of the given file's contents. - * The file contents are read fully into memory, so this method should only be used with small - * files. - * - * @param file the file on which the hash value is calculated - * @return a new instance containing the calculated (one-time) hash - * @throws IOException if an error occurs while reading the file - */ - public static Sha256Hash of(boolean isSha256, File file) throws IOException { - - try (FileInputStream in = new FileInputStream(file)) { - return of(isSha256, ByteStreams.toByteArray(in)); - } - } - - /** - * Use {@link #twiceOf(byte[])} instead: this old name is ambiguous. - */ - @Deprecated - public static Sha256Hash createDouble(boolean isSha256, byte[] contents) { - return twiceOf(isSha256, contents); - } - - /** - * Creates a new instance containing the hash of the calculated hash of the given bytes. - * - * @param contents the bytes on which the hash value is calculated - * @return a new instance containing the calculated (two-time) hash - */ - public static Sha256Hash twiceOf(boolean isSha256, byte[] contents) { - return wrap(hashTwice(isSha256, contents)); - } - - /** - * Returns a new SHA-256 MessageDigest instance. This is a convenience method which wraps the - * checked exception that can never occur with a RuntimeException. - * - * @return a new SHA-256 MessageDigest instance - */ - public static MessageDigest newDigest() { - try { - return MessageDigest.getInstance("SHA-256"); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); // Can't happen. - } - } - - /** - * Returns a new SM3 MessageDigest instance. This is a convenience method which wraps the checked - * exception that can never occur with a RuntimeException. - * - * @return a new SM3 MessageDigest instance - */ - public static SM3Digest newSM3Digest() { - return new SM3Digest(); - } - - /** - * Calculates the SHA-256 hash of the given bytes. - * - * @param input the bytes to hash - * @return the hash (in big-endian order) - */ - public static byte[] hash(boolean isSha256, byte[] input) { - return hash(isSha256, input, 0, input.length); - } - - /** - * Calculates the SHA-256 hash of the given byte range. - * - * @param input the array containing the bytes to hash - * @param offset the offset within the array of the bytes to hash - * @param length the number of bytes to hash - * @return the hash (in big-endian order) - */ - public static byte[] hash(boolean isSha256, byte[] input, int offset, int length) { - if (isSha256) { - MessageDigest digest = newDigest(); - digest.update(input, offset, length); - return digest.digest(); - } else { - SM3Digest digest = newSM3Digest(); - digest.update(input, offset, length); - byte[] eHash = new byte[digest.getDigestSize()]; - digest.doFinal(eHash, 0); - return eHash; - } - } - - /** - * Calculates the SHA-256 hash of the given bytes, and then hashes the resulting hash again. - * - * @param input the bytes to hash - * @return the double-hash (in big-endian order) - */ - public static byte[] hashTwice(boolean isSha256, byte[] input) { - return hashTwice(isSha256, input, 0, input.length); - } - - /** - * Calculates the SHA-256 hash of the given byte range, and then hashes the resulting hash again. - * - * @param input the array containing the bytes to hash - * @param offset the offset within the array of the bytes to hash - * @param length the number of bytes to hash - * @return the double-hash (in big-endian order) - */ - public static byte[] hashTwice(boolean isSha256, byte[] input, int offset, int length) { - if (isSha256) { - MessageDigest digest = newDigest(); - digest.update(input, offset, length); - return digest.digest(digest.digest()); - } else { - SM3Digest digest = newSM3Digest(); - digest.update(input, offset, length); - byte[] eHash = new byte[digest.getDigestSize()]; - digest.doFinal(eHash, 0); - digest.reset(); - digest.update(eHash, 0, eHash.length); - digest.doFinal(eHash, 0); - return eHash; - } - } - - /** - * Calculates the hash of hash on the given byte ranges. This is equivalent to concatenating the - * two ranges and then passing the result to {@link #hashTwice(byte[])}. - */ - public static byte[] hashTwice(boolean isSha256, byte[] input1, int offset1, int length1, - byte[] input2, int offset2, int length2) { - if (isSha256) { - MessageDigest digest = newDigest(); - digest.update(input1, offset1, length1); - digest.update(input2, offset2, length2); - return digest.digest(digest.digest()); - } else { - SM3Digest digest = newSM3Digest(); - digest.update(input1, offset1, length1); - digest.update(input2, offset2, length2); - byte[] eHash = new byte[digest.getDigestSize()]; - digest.doFinal(eHash, 0); - return eHash; - } - } - - private byte[] generateBlockId(long blockNum, Sha256Hash blockHash) { - byte[] numBytes = Longs.toByteArray(blockNum); - byte[] hash = blockHash.getBytes(); - System.arraycopy(numBytes, 0, hash, 0, 8); - return hash; - } - - private byte[] generateBlockId(long blockNum, byte[] blockHash) { - byte[] numBytes = Longs.toByteArray(blockNum); - byte[] hash = blockHash; - System.arraycopy(numBytes, 0, hash, 0, 8); - return hash; - } - - public long getBlockNum() { - return blockNum; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || !(o instanceof Sha256Hash)) { - return false; - } - return Arrays.equals(bytes, ((Sha256Hash) o).bytes); - } - - @Override - public String toString() { - return ByteArray.toHexString(bytes); - } - - /** - * Returns the last four bytes of the wrapped hash. This should be unique enough to be a suitable - * hash code even for blocks, where the goal is to try and get the first bytes to be zeros (i.e. - * the value as a big integer lower than the target value). - */ - @Override - public int hashCode() { - // Use the last 4 bytes, not the first 4 which are often zeros in Bitcoin. - return Ints - .fromBytes(bytes[LENGTH - 4], bytes[LENGTH - 3], bytes[LENGTH - 2], bytes[LENGTH - 1]); - } - - /** - * Returns the bytes interpreted as a positive integer. - */ - public BigInteger toBigInteger() { - return new BigInteger(1, bytes); - } - - /** - * Returns the internal byte array, without defensively copying. Therefore do NOT modify the - * returned array. - */ - public byte[] getBytes() { - return bytes; - } - - /** - * For pb return ByteString. - */ - public ByteString getByteString() { - return ByteString.copyFrom(bytes); - } - - @Override - public int compareTo(final Sha256Hash other) { - for (int i = LENGTH - 1; i >= 0; i--) { - final int thisByte = this.bytes[i] & 0xff; - final int otherByte = other.bytes[i] & 0xff; - if (thisByte > otherByte) { - return 1; - } - if (thisByte < otherByte) { - return -1; - } - } - return 0; - } -} diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldWrapper.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldWrapper.java deleted file mode 100644 index 3c89b794ed3..00000000000 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldWrapper.java +++ /dev/null @@ -1,427 +0,0 @@ -package stest.tron.wallet.common.client.utils; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import io.netty.util.internal.StringUtil; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; -import lombok.Getter; -import lombok.Setter; -import org.tron.api.GrpcAPI.DecryptNotes; -import org.tron.api.GrpcAPI.DecryptNotes.NoteTx; -import org.tron.api.GrpcAPI.IvkDecryptParameters; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.GrpcAPI.NoteParameters; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.SpendResult; -import org.tron.api.WalletGrpc; -import org.tron.common.utils.ByteArray; -import org.tron.protos.Protocol.Block; -import org.tron.protos.contract.ShieldContract.IncrementalMerkleVoucherInfo; -import org.tron.protos.contract.ShieldContract.OutputPoint; -import org.tron.protos.contract.ShieldContract.OutputPointInfo; -import stest.tron.wallet.common.client.Configuration; - -//import org.tron.walletserver.WalletApi; -//import stest.tron.wallet.common.client.Parameter.CommonConstant; - -public class ShieldWrapper { - - private static final String PREFIX_FOLDER = "WalletShield"; - private static final String IVK_AND_NUM_FILE_NAME = PREFIX_FOLDER + "/scanblocknumber"; - private static final String UNSPEND_NOTE_FILE_NAME = PREFIX_FOLDER + "/unspendnote"; - private static final String SPEND_NOTE_FILE_NAME = PREFIX_FOLDER + "/spendnote"; - private static final String SHIELD_ADDRESS_FILE_NAME = PREFIX_FOLDER + "/shieldaddress"; - //private WalletApi wallet; - private static AtomicLong nodeIndex = new AtomicLong(0L); - @Getter - @Setter - public Map ivkMapScanBlockNum = new ConcurrentHashMap(); - @Getter - @Setter - public Map utxoMapNote = new ConcurrentHashMap(); - - //Wallet wallet = new Wallet(); - @Getter - @Setter - public List spendUtxoList = new ArrayList<>(); - @Setter - @Getter - Map shieldAddressInfoMap = new ConcurrentHashMap(); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ManagedChannel channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - private WalletGrpc.WalletBlockingStub blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - private Thread thread; - @Setter - private boolean resetNote = false; - - /* public void setWallet(WalletApi walletApi) { - wallet = walletApi; - if (!thread.isAlive()) { - thread.start(); - } - }*/ - - private void resetShieldNote() { - ivkMapScanBlockNum.clear(); - for (Entry entry : getShieldAddressInfoMap().entrySet()) { - ivkMapScanBlockNum.put(ByteArray.toHexString(entry.getValue().getIvk()), 0L); - } - - utxoMapNote.clear(); - spendUtxoList.clear(); - - ZenUtils.clearFile(IVK_AND_NUM_FILE_NAME); - ZenUtils.clearFile(UNSPEND_NOTE_FILE_NAME); - ZenUtils.clearFile(SPEND_NOTE_FILE_NAME); - nodeIndex.set(0L); - - updateIvkAndBlockNumFile(); - } - - private void scanBlockByIvk() { - try { - NumberMessage.Builder builder1 = NumberMessage.newBuilder(); - builder1.setNum(-1); - Block block = blockingStubFull.getBlockByNum(builder1.build()); - if (block != null) { - long blockNum = block.getBlockHeader().toBuilder().getRawData().getNumber(); - for (Entry entry : ivkMapScanBlockNum.entrySet()) { - - long start = entry.getValue(); - long end = start; - while (end < blockNum) { - if (blockNum - start > 1000) { - end = start + 1000; - } else { - end = blockNum; - } - - IvkDecryptParameters.Builder builder = IvkDecryptParameters.newBuilder(); - builder.setStartBlockIndex(start); - builder.setEndBlockIndex(end); - builder.setIvk(ByteString.copyFrom(ByteArray.fromHexString(entry.getKey()))); - DecryptNotes notes = blockingStubFull.scanNoteByIvk(builder.build()); - if (notes != null) { - for (int i = 0; i < notes.getNoteTxsList().size(); ++i) { - NoteTx noteTx = notes.getNoteTxsList().get(i); - ShieldNoteInfo noteInfo = new ShieldNoteInfo(); - noteInfo.setPaymentAddress(noteTx.getNote().getPaymentAddress()); - noteInfo.setR(noteTx.getNote().getRcm().toByteArray()); - noteInfo.setValue(noteTx.getNote().getValue()); - noteInfo.setTrxId(ByteArray.toHexString(noteTx.getTxid().toByteArray())); - noteInfo.setIndex(noteTx.getIndex()); - noteInfo.setNoteIndex(nodeIndex.getAndIncrement()); - noteInfo.setMemo(noteTx.getNote().getMemo().toByteArray()); - - utxoMapNote.put(noteInfo.getNoteIndex(), noteInfo); - } - saveUnspendNoteToFile(); - } - start = end; - } - - ivkMapScanBlockNum.put(entry.getKey(), blockNum); - } - updateIvkAndBlockNumFile(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - private void updateNoteWhetherSpend() { - try { - for (Entry entry : utxoMapNote.entrySet()) { - ShieldNoteInfo noteInfo = entry.getValue(); - - OutputPointInfo.Builder request = OutputPointInfo.newBuilder(); - OutputPoint.Builder outPointBuild = OutputPoint.newBuilder(); - outPointBuild.setHash(ByteString.copyFrom(ByteArray.fromHexString(noteInfo.getTrxId()))); - outPointBuild.setIndex(noteInfo.getIndex()); - request.addOutPoints(outPointBuild.build()); - - IncrementalMerkleVoucherInfo merkleVoucherInfo = blockingStubFull.getMerkleTreeVoucherInfo( - request.build()); - if (merkleVoucherInfo.getVouchersCount() > 0) { - ShieldAddressInfo addressInfo = getShieldAddressInfoMap().get( - noteInfo.getPaymentAddress()); - NoteParameters.Builder builder = NoteParameters.newBuilder(); - builder.setAk(ByteString.copyFrom(addressInfo.getFullViewingKey().getAk())); - builder.setNk(ByteString.copyFrom(addressInfo.getFullViewingKey().getNk())); - - Note.Builder noteBuild = Note.newBuilder(); - noteBuild.setPaymentAddress(noteInfo.getPaymentAddress()); - noteBuild.setValue(noteInfo.getValue()); - noteBuild.setRcm(ByteString.copyFrom(noteInfo.getR())); - noteBuild.setMemo(ByteString.copyFrom(noteInfo.getMemo())); - builder.setNote(noteBuild.build()); - //builder.setVoucher(merkleVoucherInfo.getVouchers(0)); - - SpendResult result = blockingStubFull.isSpend(builder.build()); - - if (result.getResult()) { - spendNote(entry.getKey()); - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - public boolean init() { - ZenUtils.checkFolderExist(PREFIX_FOLDER); - - loadAddressFromFile(); - loadIvkFromFile(); - loadUnSpendNoteFromFile(); - loadSpendNoteFromFile(); - - thread = new Thread(new scanIvkRunable()); - return true; - } - - /** - * constructor. - */ - public boolean spendNote(long noteIndex) { - ShieldNoteInfo noteInfo = utxoMapNote.get(noteIndex); - if (noteInfo != null) { - utxoMapNote.remove(noteIndex); - spendUtxoList.add(noteInfo); - - saveUnspendNoteToFile(); - saveSpendNoteToFile(noteInfo); - } else { - System.err.println("Find note failure. index:" + noteIndex); - } - return true; - } - - /** - * constructor. - */ - public boolean addNewShieldAddress(final ShieldAddressInfo addressInfo) { - appendAddressInfoToFile(addressInfo); - long blockNum = 0; - try { - NumberMessage.Builder builder1 = NumberMessage.newBuilder(); - builder1.setNum(-1); - Block block = blockingStubFull.getBlockByNum(builder1.build()); - if (block != null) { - blockNum = block.getBlockHeader().toBuilder().getRawData().getNumber(); - } - } catch (Exception e) { - e.printStackTrace(); - } - - ivkMapScanBlockNum.put(ByteArray.toHexString(addressInfo.getIvk()), blockNum); - updateIvkAndBlockNum(ByteArray.toHexString(addressInfo.getIvk()), blockNum); - - return true; - } - - /** - * constructor. - */ - private boolean updateIvkAndBlockNum(final String ivk, long blockNum) { - synchronized (IVK_AND_NUM_FILE_NAME) { - String date = ivk + ";" + blockNum; - ZenUtils.appendToFileTail(IVK_AND_NUM_FILE_NAME, date); - } - return true; - } - - /** - * constructor. - */ - private boolean updateIvkAndBlockNumFile() { - synchronized (IVK_AND_NUM_FILE_NAME) { - ZenUtils.clearFile(IVK_AND_NUM_FILE_NAME); - for (Entry entry : ivkMapScanBlockNum.entrySet()) { - String date = entry.getKey() + ";" + entry.getValue(); - ZenUtils.appendToFileTail(IVK_AND_NUM_FILE_NAME, date); - } - } - return true; - } - - /** - * constructor. - */ - private boolean loadIvkFromFile() { - ivkMapScanBlockNum.clear(); - List list = ZenUtils.getListFromFile(IVK_AND_NUM_FILE_NAME); - for (int i = 0; i < list.size(); ++i) { - String[] sourceStrArray = list.get(i).split(";"); - if (sourceStrArray.length != 2) { - System.err.println("len is not right."); - return false; - } - ivkMapScanBlockNum.put(sourceStrArray[0], Long.valueOf(sourceStrArray[1])); - } - return true; - } - - /** - * get shield address list. - */ - public List getShieldAddressList() { - List addressList = new ArrayList<>(); - for (Entry entry : shieldAddressInfoMap.entrySet()) { - addressList.add(entry.getKey()); - } - return addressList; - } - - /** - * update unspend note. - */ - private boolean saveUnspendNoteToFile() { - ZenUtils.clearFile(UNSPEND_NOTE_FILE_NAME); - for (Entry entry : utxoMapNote.entrySet()) { - String date = entry.getValue().encode(); - ZenUtils.appendToFileTail(UNSPEND_NOTE_FILE_NAME, date); - } - return true; - } - - /** - * load unspend note from file. - */ - private boolean loadUnSpendNoteFromFile() { - utxoMapNote.clear(); - - List list = ZenUtils.getListFromFile(UNSPEND_NOTE_FILE_NAME); - for (int i = 0; i < list.size(); ++i) { - ShieldNoteInfo noteInfo = new ShieldNoteInfo(); - noteInfo.decode(list.get(i)); - utxoMapNote.put(noteInfo.getNoteIndex(), noteInfo); - - if (noteInfo.getNoteIndex() > nodeIndex.get()) { - nodeIndex.set(noteInfo.getNoteIndex()); - } - } - return true; - } - - /** - * append spend note to file tail. - */ - private boolean saveSpendNoteToFile(ShieldNoteInfo noteInfo) { - String date = noteInfo.encode(); - ZenUtils.appendToFileTail(SPEND_NOTE_FILE_NAME, date); - return true; - } - - /** - * load spend note from file. - */ - private boolean loadSpendNoteFromFile() { - spendUtxoList.clear(); - List list = ZenUtils.getListFromFile(SPEND_NOTE_FILE_NAME); - for (int i = 0; i < list.size(); ++i) { - ShieldNoteInfo noteInfo = new ShieldNoteInfo(); - noteInfo.decode(list.get(i)); - spendUtxoList.add(noteInfo); - } - return true; - } - - /** - * load shield address from file. - */ - public boolean loadAddressFromFile() { - List addressList = ZenUtils.getListFromFile(SHIELD_ADDRESS_FILE_NAME); - - shieldAddressInfoMap.clear(); - for (String addressString : addressList) { - ShieldAddressInfo addressInfo = new ShieldAddressInfo(); - if (addressInfo.decode(addressString)) { - shieldAddressInfoMap.put(addressInfo.getAddress(), addressInfo); - } else { - System.out.println("*******************"); - } - } - return true; - } - - /** - * constructor. - */ - public boolean appendAddressInfoToFile(final ShieldAddressInfo addressInfo) { - String shieldAddress = addressInfo.getAddress(); - if (!StringUtil.isNullOrEmpty(shieldAddress)) { - String addressString = addressInfo.encode(); - ZenUtils.appendToFileTail(SHIELD_ADDRESS_FILE_NAME, addressString); - - shieldAddressInfoMap.put(shieldAddress, addressInfo); - } - return true; - } - - /** - * sort by value of UTXO. - */ - public List getvalidateSortUtxoList() { - List> list = new ArrayList<>(utxoMapNote.entrySet()); - Collections.sort(list, (Entry o1, Entry o2) -> { - if (o1.getValue().getValue() < o2.getValue().getValue()) { - return 1; - } else { - return -1; - } - }); - - List utxoList = new ArrayList<>(); - for (Map.Entry entry : list) { - String string = entry.getKey() + " " + entry.getValue().getPaymentAddress() + " "; - string += entry.getValue().getValue(); - string += " "; - string += entry.getValue().getTrxId(); - string += " "; - string += entry.getValue().getIndex(); - string += " "; - string += "UnSpend"; - string += " "; - string += ZenUtils.getMemo(entry.getValue().getMemo()); - utxoList.add(string); - } - return utxoList; - } - - public class scanIvkRunable implements Runnable { - - public void run() { - for (; ; ) { - try { - scanBlockByIvk(); - updateNoteWhetherSpend(); - //wait for 2.5 seconds - for (int i = 0; i < 5; ++i) { - Thread.sleep(500); - if (resetNote) { - resetShieldNote(); - resetNote = false; - System.out.println("Reset shield note success!"); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldedAddressInfo.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldedAddressInfo.java deleted file mode 100644 index b1bbf70cc80..00000000000 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldedAddressInfo.java +++ /dev/null @@ -1,122 +0,0 @@ -package stest.tron.wallet.common.client.utils; - -import java.util.Arrays; -import java.util.Optional; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; -import org.tron.common.utils.Base58; -import org.tron.core.exception.ZksnarkException; -import org.tron.core.zen.address.DiversifierT; -import org.tron.core.zen.address.FullViewingKey; -import org.tron.core.zen.address.IncomingViewingKey; -import org.tron.core.zen.address.KeyIo; -import org.tron.core.zen.address.PaymentAddress; -import org.tron.core.zen.address.SpendingKey; - -@AllArgsConstructor -public class ShieldedAddressInfo { - - @Setter - @Getter - public byte[] sk; - @Setter - @Getter - public byte[] ivk; // 256 - @Setter - @Getter - public byte[] ovk; // 256 - @Setter - @Getter - DiversifierT d; - @Setter - @Getter - byte[] pkD; // 256 - - public ShieldedAddressInfo() { - } - - public FullViewingKey getFullViewingKey() throws ZksnarkException { - SpendingKey spendingKey = new SpendingKey(sk); - return spendingKey.fullViewingKey(); - } - - /** - * check parameters - */ - public boolean validateCheck() { - try { - SpendingKey spendingKey = new SpendingKey(sk); - FullViewingKey fullViewingKey = spendingKey.fullViewingKey(); - if (!Arrays.equals(fullViewingKey.getOvk(), ovk)) { - System.out.println("ovk check failure!"); - return false; - } - IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); - if (!Arrays.equals(incomingViewingKey.getValue(), ivk)) { - System.out.println("ivk check failure!"); - return false; - } - Optional optionalPaymentAddress = incomingViewingKey.address(d); - if (!optionalPaymentAddress.isPresent() - || !Arrays.equals(optionalPaymentAddress.get().getPkD(), pkD)) { - System.out.println("pkd check failure!"); - return false; - } - return true; - } catch (Exception e) { - e.printStackTrace(); - } - return false; - } - - public String getAddress() { - return getShieldedAddress(d, pkD); - } - - public static String getShieldedAddress(DiversifierT d, byte[] pkD) { - try { - PaymentAddress paymentAddress = new PaymentAddress(d, pkD); - return KeyIo.encodePaymentAddress(paymentAddress); - } catch (Exception e) { - e.printStackTrace(); - } - return ""; - } - - /** - * format shielded address info to a string - */ - public String encode(byte[] encryptKey) throws CipherException { - byte[] text = new byte[sk.length + ivk.length + ovk.length + d.getData().length + pkD.length]; - System.arraycopy(sk, 0, text, 0, sk.length); - System.arraycopy(ivk, 0, text, sk.length, ivk.length); - System.arraycopy(ovk, 0, text, sk.length + ivk.length, ovk.length); - System.arraycopy(d.getData(), 0, text, sk.length + ivk.length + ovk.length, d.getData().length); - System.arraycopy(pkD, 0, text, sk.length + ivk.length + ovk.length + d.getData().length, - pkD.length); - - byte[] cipherText = ZenUtils.aesCtrEncrypt(text, encryptKey); - return Base58.encode(cipherText); - } - - /** - * parse string to get a shielded address info - */ - public boolean decode(final String data, byte[] encryptKey) throws CipherException { - byte[] cipherText = Base58.decode(data); - byte[] text = ZenUtils.aesCtrDecrypt(cipherText, encryptKey); - - sk = Arrays.copyOfRange(text, 0, 32); - ivk = Arrays.copyOfRange(text, 32, 64); - ovk = Arrays.copyOfRange(text, 64, 96); - d = new DiversifierT(Arrays.copyOfRange(text, 96, 107)); - pkD = Arrays.copyOfRange(text, 107, 139); - - if (validateCheck()) { - return true; - } else { - return false; - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldedTRC20NoteInfo.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldedTRC20NoteInfo.java deleted file mode 100644 index 96b38ce06c0..00000000000 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/ShieldedTRC20NoteInfo.java +++ /dev/null @@ -1,96 +0,0 @@ -package stest.tron.wallet.common.client.utils; - -import io.netty.util.internal.StringUtil; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; -import org.tron.common.utils.Base58; -import org.tron.common.utils.ByteArray; - -@AllArgsConstructor -public class ShieldedTRC20NoteInfo { - - @Setter - @Getter - public long value = 0; - @Setter - @Getter - public String paymentAddress; - @Setter - @Getter - public byte[] r; // 256 - @Setter - @Getter - public String trxId; - @Setter - @Getter - public int index; - @Setter - @Getter - public long noteIndex; - @Setter - @Getter - public long position; - @Setter - @Getter - public byte[] memo; - - public ShieldedTRC20NoteInfo() { - } - - /** - * format shieldedTRC20 note to a string - */ - public String encode(byte[] encryptKey) throws CipherException { - String encodeString = noteIndex + ";"; - encodeString += paymentAddress; - encodeString += ";"; - encodeString += ByteArray.toHexString(r); - encodeString += ";"; - encodeString += trxId; - encodeString += ";"; - encodeString += String.valueOf(value); - encodeString += ";"; - encodeString += String.valueOf(index); - encodeString += ";"; - encodeString += String.valueOf(position); - encodeString += ";"; - String stringMemo = ByteArray.toHexString(memo); - if (StringUtil.isNullOrEmpty(stringMemo)) { - encodeString += "null"; - } else { - encodeString += stringMemo; - } - byte[] chipherText = ZenUtils.aesCtrEncrypt(encodeString.getBytes(), encryptKey); - encodeString = Base58.encode(chipherText); - return encodeString; - } - - /** - * parse string to get shieldedTRC20 note - */ - public boolean decode(String data, byte[] encryptKey) throws CipherException { - byte[] chipherText = Base58.decode(data); - byte[] text = ZenUtils.aesCtrDecrypt(chipherText, encryptKey); - data = new String(text); - - String[] sourceStrArray = data.split(";"); - if (sourceStrArray.length != 8) { - System.out.println("len is not right."); - return false; - } - noteIndex = Long.valueOf(sourceStrArray[0]); - paymentAddress = sourceStrArray[1]; - r = ByteArray.fromHexString(sourceStrArray[2]); - trxId = sourceStrArray[3]; - value = Long.valueOf(sourceStrArray[4]); - index = Integer.valueOf(sourceStrArray[5]); - position = Long.valueOf(sourceStrArray[6]); - if (sourceStrArray[7].equals("null")) { - memo = ByteArray.fromHexString(""); - } else { - memo = ByteArray.fromHexString(sourceStrArray[7]); - } - return true; - } -} diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/ZenTrc20Base.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/ZenTrc20Base.java deleted file mode 100644 index 21d03f2c26b..00000000000 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/ZenTrc20Base.java +++ /dev/null @@ -1,1724 +0,0 @@ -package stest.tron.wallet.common.client.utils; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.google.gson.JsonObject; -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import io.grpc.Status; -import io.netty.util.internal.StringUtil; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.Random; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpPost; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.BeforeSuite; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.BytesMessage; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.GrpcAPI.ShieldedTRC20Parameters; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.Commons; -import org.tron.core.Wallet; -import org.tron.core.exception.ZksnarkException; -import org.tron.core.zen.address.DiversifierT; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.ShieldContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; - -@Slf4j -public class ZenTrc20Base { - - public final String foundationAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - public final byte[] foundationAccountAddress = PublicMethed.getFinalAddress(foundationAccountKey); - public static final String zenTrc20TokenOwnerKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTrc20TokenOwnerKey"); - public static final byte[] zenTrc20TokenOwnerAddress = PublicMethed - .getFinalAddress(zenTrc20TokenOwnerKey); - public static final String zenTrc20TokenOwnerAddressString = PublicMethed - .getAddressString(zenTrc20TokenOwnerKey); - public ManagedChannel channelFull = null; - public WalletGrpc.WalletBlockingStub blockingStubFull = null; - public ManagedChannel channelSolidity = null; - public ManagedChannel channelPbft = null; - - public WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - public WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPbft = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - public static long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - public com.google.protobuf.ByteString contractAddressByteString; - public static byte[] contractAddressByte; - public static String contractAddress; - public static com.google.protobuf.ByteString shieldAddressByteString; - public static byte[] shieldAddressByte; - public static String shieldAddress; - public static String deployShieldTrc20Txid; - public static String deployShieldTxid; - public static String mint = "mint(uint256,bytes32[9],bytes32[2],bytes32[21])"; - public static String transfer = - "transfer(bytes32[10][],bytes32[2][],bytes32[9][],bytes32[2],bytes32[21][])"; - public static String burn = "burn(bytes32[10],bytes32[2],uint256,bytes32[2],address," - + "bytes32[3],bytes32[9][],bytes32[21][])"; - public Wallet wallet = new Wallet(); - static HttpResponse response; - static HttpPost httppost; - static JSONObject responseContent; - public static Integer scalingFactorLogarithm = 0; - public static Long totalSupply = 1000000000000L; - - - /** - * constructor. - */ - @BeforeSuite(enabled = true, description = "Deploy shield trc20 depend contract") - public void deployShieldTrc20DependContract() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - getDailyBuildStartNum(); - Assert.assertTrue(PublicMethed.sendcoin(zenTrc20TokenOwnerAddress, 10000000000000L, - foundationAccountAddress, foundationAccountKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "shieldTrc20Token"; - - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_shieldTrc20Token"); - String code = Configuration.getByPath("testng.conf") - .getString("code.code_shieldTrc20Token"); - String constructorStr = "constructor(uint256,string,string)"; - String data = totalSupply.toString() + "," + "\"TokenTRC20\"" + "," + "\"zen20\""; - logger.info("data:" + data); - deployShieldTrc20Txid = PublicMethed - .deployContractWithConstantParame(contractName, abi, code, constructorStr, data, "", - maxFeeLimit, 0L, 100, null, - zenTrc20TokenOwnerKey, zenTrc20TokenOwnerAddress, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info(deployShieldTrc20Txid); - Optional infoById = PublicMethed - .getTransactionInfoById(deployShieldTrc20Txid, blockingStubFull); - contractAddressByteString = infoById.get().getContractAddress(); - contractAddressByte = infoById.get().getContractAddress().toByteArray(); - contractAddress = Base58.encode58Check(contractAddressByte); - logger.info(contractAddress); - - contractName = "shield"; - abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_shield"); - code = Configuration.getByPath("testng.conf") - .getString("code.code_shield"); - data = "\"" + contractAddress + "\"" + "," + scalingFactorLogarithm; - constructorStr = "constructor(address,uint256)"; - deployShieldTxid = PublicMethed - .deployContractWithConstantParame(contractName, abi, code, constructorStr, data, "", - maxFeeLimit, 0L, 100, null, - zenTrc20TokenOwnerKey, zenTrc20TokenOwnerAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info(deployShieldTxid); - infoById = PublicMethed - .getTransactionInfoById(deployShieldTxid, blockingStubFull); - shieldAddressByteString = infoById.get().getContractAddress(); - shieldAddressByte = infoById.get().getContractAddress().toByteArray(); - shieldAddress = Base58.encode58Check(shieldAddressByte); - logger.info(shieldAddress); - - data = "\"" + shieldAddress + "\"" + "," + totalSupply.toString(); - String txid = PublicMethed.triggerContract(contractAddressByte, - "approve(address,uint256)", data, false, - 0, maxFeeLimit, zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("approve:" + txid); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - - - } - - /** - * constructor. - */ - public void getDailyBuildStartNum() { - DailyBuildReport.startBlockNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder() - .build()).getBlockHeader().getRawData().getNumber(); - System.out.println("!!!!!!! 222222222startnum:" + DailyBuildReport.startBlockNum); - } - - - /** - * constructor. - */ - public GrpcAPI.ShieldedTRC20Parameters createShieldedTrc20Parameters(BigInteger publicFromAmount, - GrpcAPI.DecryptNotesTRC20 inputNoteList, List shieldedAddressInfoList, - List outputNoteList, String publicToAddress, Long pubicToAmount, - WalletGrpc.WalletBlockingStub blockingStubFull, - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) throws ZksnarkException { - - GrpcAPI.PrivateShieldedTRC20Parameters.Builder builder - = GrpcAPI.PrivateShieldedTRC20Parameters.newBuilder(); - - //Mint type should set public from amount to parameter - if (publicFromAmount.compareTo(BigInteger.ZERO) > 0) { - builder.setFromAmount(publicFromAmount.toString()); - } - - builder.setShieldedTRC20ContractAddress(ByteString.copyFrom(shieldAddressByte)); - long valueBalance = 0; - - if (inputNoteList != null) { - logger.info("Enter transfer type code"); - List rootAndPath = new ArrayList<>(); - for (int i = 0; i < inputNoteList.getNoteTxsCount(); i++) { - long position = inputNoteList.getNoteTxs(i).getPosition(); - rootAndPath.add(getRootAndPath(position, blockingStubSolidity)); - } - if (rootAndPath.isEmpty() || rootAndPath.size() != inputNoteList.getNoteTxsCount()) { - System.out.println("Can't get all merkle tree, please check the notes."); - return null; - } - for (int i = 0; i < rootAndPath.size(); i++) { - if (rootAndPath.get(i) == null) { - System.out.println("Can't get merkle path, please check the note " + i + "."); - return null; - } - } - - for (int i = 0; i < inputNoteList.getNoteTxsCount(); ++i) { - if (i == 0) { - String shieldedAddress = inputNoteList.getNoteTxs(i).getNote().getPaymentAddress(); - - String spendingKey = ByteArray.toHexString(shieldedAddressInfoList.get(0).getSk()); - BytesMessage sk = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(spendingKey))).build(); - Optional esk = Optional - .of(blockingStubFull.getExpandedSpendingKey(sk)); - - //ExpandedSpendingKey expandedSpendingKey = spendingKey.expandedSpendingKey(); - builder.setAsk(esk.get().getAsk()); - builder.setNsk(esk.get().getNsk()); - builder.setOvk(esk.get().getOvk()); - } - Note.Builder noteBuild = Note.newBuilder(); - noteBuild.setPaymentAddress(shieldedAddressInfoList.get(0).getAddress()); - noteBuild.setValue(inputNoteList.getNoteTxs(i).getNote().getValue()); - noteBuild.setRcm(inputNoteList.getNoteTxs(i).getNote().getRcm()); - noteBuild.setMemo(inputNoteList.getNoteTxs(i).getNote().getMemo()); - - System.out.println("address " + shieldedAddressInfoList.get(0).getAddress()); - System.out.println("value " + inputNoteList.getNoteTxs(i).getNote().getValue()); - System.out.println("trxId " + inputNoteList.getNoteTxs(i).getTxid()); - System.out.println("index " + inputNoteList.getNoteTxs(i).getIndex()); - System.out.println("position " + inputNoteList.getNoteTxs(i).getPosition()); - - byte[] eachRootAndPath = ByteArray.fromHexString(rootAndPath.get(i)); - byte[] root = Arrays.copyOfRange(eachRootAndPath, 0, 32); - byte[] path = Arrays.copyOfRange(eachRootAndPath, 32, 1056); - GrpcAPI.SpendNoteTRC20.Builder spendTrc20NoteBuilder = GrpcAPI.SpendNoteTRC20.newBuilder(); - spendTrc20NoteBuilder.setNote(noteBuild.build()); - spendTrc20NoteBuilder.setAlpha(ByteString.copyFrom(blockingStubFull.getRcm( - EmptyMessage.newBuilder().build()).getValue().toByteArray())); - spendTrc20NoteBuilder.setRoot(ByteString.copyFrom(root)); - spendTrc20NoteBuilder.setPath(ByteString.copyFrom(path)); - spendTrc20NoteBuilder.setPos(inputNoteList.getNoteTxs(i).getPosition()); - - valueBalance = Math.addExact(valueBalance, inputNoteList.getNoteTxs(i).getNote() - .getValue()); - builder.addShieldedSpends(spendTrc20NoteBuilder.build()); - } - } else { - //@TODO remove randomOvk by sha256.of(privateKey) - byte[] ovk = getRandomOvk(); - if (ovk != null) { - builder.setOvk(ByteString.copyFrom(ovk)); - } else { - System.out.println("Get random ovk from Rpc failure,please check config"); - return null; - } - } - - if (outputNoteList != null) { - for (int i = 0; i < outputNoteList.size(); i++) { - GrpcAPI.Note note = outputNoteList.get(i); - valueBalance = Math.subtractExact(valueBalance, note.getValue()); - builder.addShieldedReceives( - GrpcAPI.ReceiveNote.newBuilder().setNote(note).build()); - } - } - - if (!StringUtil.isNullOrEmpty(publicToAddress)) { - byte[] to = Commons.decodeFromBase58Check(publicToAddress); - if (to == null) { - return null; - } - builder.setTransparentToAddress(ByteString.copyFrom(to)); - builder.setToAmount(pubicToAmount.toString()); - } - - try { - return blockingStubFull.createShieldedContractParameters(builder.build()); - } catch (Exception e) { - Status status = Status.fromThrowable(e); - System.out.println("createShieldedContractParameters failed,error " - + status.getDescription()); - } - return null; - } - - - /** - * constructor. - */ - public GrpcAPI.ShieldedTRC20Parameters createShieldedTrc20ParametersWithoutAsk( - BigInteger publicFromAmount, - GrpcAPI.DecryptNotesTRC20 inputNoteList, List shieldedAddressInfoList, - List outputNoteList, String publicToAddress, byte[] receiverAddressbyte, - Long pubicToAmount, - WalletGrpc.WalletBlockingStub blockingStubFull, - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) throws ZksnarkException { - - GrpcAPI.PrivateShieldedTRC20ParametersWithoutAsk.Builder builder - = GrpcAPI.PrivateShieldedTRC20ParametersWithoutAsk.newBuilder(); - - //Mint type should set public from amount to parameter - if (publicFromAmount.compareTo(BigInteger.ZERO) > 0) { - builder.setFromAmount(publicFromAmount.toString()); - } - - builder.setShieldedTRC20ContractAddress(ByteString.copyFrom(shieldAddressByte)); - - long valueBalance = 0; - byte[] ask = new byte[32]; - if (inputNoteList != null) { - List rootAndPath = new ArrayList<>(); - for (int i = 0; i < inputNoteList.getNoteTxsCount(); i++) { - long position = inputNoteList.getNoteTxs(i).getPosition(); - rootAndPath.add(getRootAndPath(position, blockingStubSolidity)); - } - if (rootAndPath.isEmpty() || rootAndPath.size() != inputNoteList.getNoteTxsCount()) { - System.out.println("Can't get all merkle tree, please check the notes."); - return null; - } - for (int i = 0; i < rootAndPath.size(); i++) { - if (rootAndPath.get(i) == null) { - System.out.println("Can't get merkle path, please check the note " + i + "."); - return null; - } - } - - for (int i = 0; i < inputNoteList.getNoteTxsCount(); ++i) { - if (i == 0) { - String spendingKey = ByteArray.toHexString(shieldedAddressInfoList.get(i).getSk()); - BytesMessage sk = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(spendingKey))).build(); - Optional esk = Optional - .of(blockingStubFull.getExpandedSpendingKey(sk)); - System.arraycopy(esk.get().getAsk().toByteArray(), 0, ask, 0, 32); - - String ask1 = ByteArray.toHexString(esk.get().getAsk().toByteArray()); - - BytesMessage ask2 = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(ask1))).build(); - Optional ak = Optional.of(blockingStubFull.getAkFromAsk(ask2)); - String akString = ByteArray.toHexString(ak.get().getValue().toByteArray()); - - builder.setAk(ByteString.copyFrom(ByteArray.fromHexString(akString))); - builder.setOvk(esk.get().getOvk()); - builder.setNsk(esk.get().getNsk()); - - } - Note.Builder noteBuild = Note.newBuilder(); - noteBuild.setPaymentAddress(shieldedAddressInfoList.get(i).getAddress()); - noteBuild.setValue(inputNoteList.getNoteTxs(i).getNote().getValue()); - noteBuild.setRcm(inputNoteList.getNoteTxs(i).getNote().getRcm()); - noteBuild.setMemo(inputNoteList.getNoteTxs(i).getNote().getMemo()); - - System.out.println("address " + shieldedAddressInfoList.get(i).getAddress()); - System.out.println("value " + inputNoteList.getNoteTxs(i).getNote().getValue()); - System.out.println("trxId " + ByteArray.toHexString(inputNoteList.getNoteTxs(i) - .getTxid().toByteArray())); - System.out.println("index " + inputNoteList.getNoteTxs(i).getIndex()); - System.out.println("position " + inputNoteList.getNoteTxs(i).getPosition()); - - byte[] eachRootAndPath = ByteArray.fromHexString(rootAndPath.get(i)); - byte[] root = Arrays.copyOfRange(eachRootAndPath, 0, 32); - byte[] path = Arrays.copyOfRange(eachRootAndPath, 32, 1056); - GrpcAPI.SpendNoteTRC20.Builder spendTrc20NoteBuilder = GrpcAPI.SpendNoteTRC20.newBuilder(); - spendTrc20NoteBuilder.setNote(noteBuild.build()); - spendTrc20NoteBuilder.setAlpha(ByteString.copyFrom(blockingStubFull.getRcm( - EmptyMessage.newBuilder().build()).getValue().toByteArray())); - spendTrc20NoteBuilder.setRoot(ByteString.copyFrom(root)); - spendTrc20NoteBuilder.setPath(ByteString.copyFrom(path)); - spendTrc20NoteBuilder.setPos(inputNoteList.getNoteTxs(i).getPosition()); - - builder.addShieldedSpends(spendTrc20NoteBuilder.build()); - valueBalance = Math.addExact(valueBalance, inputNoteList.getNoteTxs(i) - .getNote().getValue()); - } - } else { - //@TODO remove randomOvk by sha256.of(privateKey) - byte[] ovk = getRandomOvk(); - if (ovk != null) { - builder.setOvk(ByteString.copyFrom(ovk)); - } else { - System.out.println("Get random ovk from Rpc failure,please check config"); - return null; - } - } - - if (outputNoteList != null) { - for (int i = 0; i < outputNoteList.size(); i++) { - GrpcAPI.Note note = outputNoteList.get(i); - valueBalance = Math.subtractExact(valueBalance, note.getValue()); - builder.addShieldedReceives( - GrpcAPI.ReceiveNote.newBuilder().setNote(note).build()); - } - } - - if (!StringUtil.isNullOrEmpty(publicToAddress)) { - byte[] to = Commons.decodeFromBase58Check(publicToAddress); - if (to == null) { - return null; - } - builder.setTransparentToAddress(ByteString.copyFrom(to)); - builder.setToAmount(pubicToAmount.toString()); - } - - ShieldedTRC20Parameters parameters = blockingStubFull - .createShieldedContractParametersWithoutAsk(builder.build()); - if (parameters == null) { - System.out.println("createShieldedContractParametersWithoutAsk failed!"); - return null; - } - - GrpcAPI.ShieldedTRC20TriggerContractParameters.Builder stBuilder = - GrpcAPI.ShieldedTRC20TriggerContractParameters.newBuilder(); - stBuilder.setShieldedTRC20Parameters(parameters); - - if (parameters.getParameterType().equals("burn")) { - stBuilder.setAmount(pubicToAmount.toString()); - stBuilder.setTransparentToAddress(ByteString.copyFrom(receiverAddressbyte)); - } - - ByteString messageHash = parameters.getMessageHash(); - List spendDescList = parameters.getSpendDescriptionList(); - ShieldedTRC20Parameters.Builder newBuilder = - ShieldedTRC20Parameters.newBuilder().mergeFrom(parameters); - for (int i = 0; i < spendDescList.size(); i++) { - GrpcAPI.SpendAuthSigParameters.Builder builder1 = GrpcAPI.SpendAuthSigParameters.newBuilder(); - builder1.setAsk(ByteString.copyFrom(ask)); - builder1.setTxHash(messageHash); - builder1.setAlpha(builder.build().getShieldedSpends(i).getAlpha()); - - BytesMessage authSig = blockingStubFull.createSpendAuthSig(builder1.build()); - newBuilder.getSpendDescriptionBuilder(i) - .setSpendAuthoritySignature( - ByteString.copyFrom(authSig.getValue().toByteArray())); - - stBuilder.addSpendAuthoritySignature(authSig); - BytesMessage triggerInputData; - try { - triggerInputData = blockingStubFull.getTriggerInputForShieldedTRC20Contract(stBuilder - .build()); - } catch (Exception e) { - triggerInputData = null; - System.out.println("getTriggerInputForShieldedTRC20Contract error, please retry!"); - } - if (triggerInputData == null) { - return null; - } - newBuilder.setTriggerContractInput(ByteArray.toHexString(triggerInputData.getValue() - .toByteArray())); - - - } - return newBuilder.build(); - } - - - /** - * constructor. - */ - public String getRootAndPath(long position, WalletSolidityGrpc.WalletSolidityBlockingStub - blockingStubSolidity) { - String methodStr = "getPath(uint256)"; - byte[] indexBytes = ByteArray.fromLong(position); - String argsStr = ByteArray.toHexString(indexBytes); - argsStr = "000000000000000000000000000000000000000000000000" + argsStr; - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtentionOnSolidity(shieldAddressByte, methodStr, argsStr, - true, 0, 1000000000L, "0", 0, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubSolidity); - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - return ByteArray.toHexString(result); - } - - - /** - * constructor. - */ - public String encodeMintParamsToHexString(GrpcAPI.ShieldedTRC20Parameters parameters, - BigInteger value) { - byte[] mergedBytes; - ShieldContract.ReceiveDescription revDesc = parameters.getReceiveDescription(0); - mergedBytes = ByteUtil.merge( - ByteUtil.bigIntegerToBytes(value, 32), - revDesc.getNoteCommitment().toByteArray(), - revDesc.getValueCommitment().toByteArray(), - revDesc.getEpk().toByteArray(), - revDesc.getZkproof().toByteArray(), - parameters.getBindingSignature().toByteArray(), - revDesc.getCEnc().toByteArray(), - revDesc.getCOut().toByteArray(), - new byte[12] - ); - return ByteArray.toHexString(mergedBytes); - } - - /** - * constructor. - */ - public static HttpResponse getNewShieldedAddress(String httpNode) { - try { - String requestUrl = "http://" + httpNode + "/wallet/getnewshieldedaddress"; - response = HttpMethed.createConnect(requestUrl); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - - /** - * constructor. - */ - public Optional getNewShieldedAddress(WalletGrpc.WalletBlockingStub - blockingStubFull) { - ShieldedAddressInfo addressInfo = new ShieldedAddressInfo(); - - try { - Optional sk = Optional.of(blockingStubFull - .getSpendingKey(EmptyMessage.newBuilder().build())); - final Optional d = Optional.of(blockingStubFull.getDiversifier( - EmptyMessage.newBuilder().build())); - - Optional expandedSpendingKeyMessage - = Optional.of(blockingStubFull - .getExpandedSpendingKey(sk.get())); - - BytesMessage.Builder askBuilder = BytesMessage.newBuilder(); - askBuilder.setValue(expandedSpendingKeyMessage.get().getAsk()); - Optional ak = Optional.of(blockingStubFull.getAkFromAsk(askBuilder.build())); - - BytesMessage.Builder nskBuilder = BytesMessage.newBuilder(); - nskBuilder.setValue(expandedSpendingKeyMessage.get().getNsk()); - Optional nk = Optional.of(blockingStubFull.getNkFromNsk(nskBuilder.build())); - - GrpcAPI.ViewingKeyMessage.Builder viewBuilder = GrpcAPI.ViewingKeyMessage.newBuilder(); - viewBuilder.setAk(ak.get().getValue()); - viewBuilder.setNk(nk.get().getValue()); - Optional ivk = Optional.of(blockingStubFull - .getIncomingViewingKey(viewBuilder.build())); - - GrpcAPI.IncomingViewingKeyDiversifierMessage.Builder builder - = GrpcAPI.IncomingViewingKeyDiversifierMessage - .newBuilder(); - builder.setD(d.get()); - builder.setIvk(ivk.get()); - Optional addressMessage = Optional.of(blockingStubFull - .getZenPaymentAddress(builder.build())); - addressInfo.setSk(sk.get().getValue().toByteArray()); - addressInfo.setD(new DiversifierT(d.get().getD().toByteArray())); - addressInfo.setIvk(ivk.get().getIvk().toByteArray()); - addressInfo.setOvk(expandedSpendingKeyMessage.get().getOvk().toByteArray()); - addressInfo.setPkD(addressMessage.get().getPkD().toByteArray()); - - System.out.println("ivk " + ByteArray.toHexString(ivk.get().getIvk().toByteArray())); - System.out.println("ovk " + ByteArray.toHexString(expandedSpendingKeyMessage.get() - .getOvk().toByteArray())); - - return Optional.of(addressInfo); - - } catch (Exception e) { - e.printStackTrace(); - } - - return Optional.empty(); - } - - - /** - * constructor. - */ - public static List addShieldTrc20OutputList(List shieldOutList, - String shieldToAddress, String toAmountString, String menoString, - WalletGrpc.WalletBlockingStub blockingStubFull) { - String shieldAddress = shieldToAddress; - String amountString = toAmountString; - if (menoString.equals("null")) { - menoString = ""; - } - long shieldAmount = 0; - if (!StringUtil.isNullOrEmpty(amountString)) { - shieldAmount = Long.valueOf(amountString); - } - - Note.Builder noteBuild = Note.newBuilder(); - noteBuild.setPaymentAddress(shieldAddress); - //noteBuild.setPaymentAddress(shieldAddress); - noteBuild.setValue(shieldAmount); - noteBuild.setRcm(ByteString.copyFrom(blockingStubFull.getRcm(EmptyMessage.newBuilder().build()) - .getValue().toByteArray())); - noteBuild.setMemo(ByteString.copyFrom(menoString.getBytes())); - shieldOutList.add(noteBuild.build()); - return shieldOutList; - } - - - /** - * constructor. - */ - public Long getBalanceOfShieldTrc20(String queryAddress, byte[] ownerAddress, - String ownerKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - String paramStr = "\"" + queryAddress + "\""; - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddressByte, "balanceOf(address)", - paramStr, false, 0, 0, "0", 0, - ownerAddress, ownerKey, blockingStubFull); - - String hexBalance = Hex.toHexString(transactionExtention - .getConstantResult(0).toByteArray()); - for (int i = 0; i < hexBalance.length(); i++) { - if (hexBalance.charAt(i) != '0') { - hexBalance = hexBalance.substring(i); - break; - } - } - logger.info(hexBalance); - return Long.parseLong(hexBalance, 16); - } - - - /** - * constructor. - */ - public String getBalanceOfShieldTrc20String(String queryAddress, byte[] ownerAddress, - String ownerKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - String paramStr = "\"" + queryAddress + "\""; - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddressByte, "balanceOf(address)", - paramStr, false, 0, 0, "0", 0, - ownerAddress, ownerKey, blockingStubFull); - - String hexBalance = Hex.toHexString(transactionExtention - .getConstantResult(0).toByteArray()); - for (int i = 0; i < hexBalance.length(); i++) { - if (hexBalance.charAt(i) != '0') { - hexBalance = hexBalance.substring(i); - break; - } - } - logger.info(hexBalance); - return hexBalance; - } - - - /** - * constructor. - */ - public GrpcAPI.DecryptNotesTRC20 scanShieldedTrc20NoteByIvk(ShieldedAddressInfo - shieldedAddressInfo, WalletGrpc.WalletBlockingStub blockingStubFull, - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) throws Exception { - long currentBlockNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - - Long startNum = currentBlockNum - 90L; - final Long endNum = currentBlockNum; - if (currentBlockNum < 100) { - startNum = 1L; - } - - String spendingKey = ByteArray.toHexString(shieldedAddressInfo.getSk()); - BytesMessage sk = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(spendingKey))).build(); - Optional esk = Optional - .of(blockingStubFull.getExpandedSpendingKey(sk)); - - String ask = ByteArray.toHexString(esk.get().getAsk().toByteArray()); - - BytesMessage ask1 = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(ask))).build(); - Optional ak = Optional.of(blockingStubFull.getAkFromAsk(ask1)); - String akString = ByteArray.toHexString(ak.get().getValue().toByteArray()); - //System.out.println("ak:" + ByteArray.toHexString(ak.get().getValue().toByteArray())); - - String nsk = ByteArray.toHexString(esk.get().getNsk().toByteArray()); - - BytesMessage nsk1 = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(nsk))).build(); - Optional nk = Optional.of(blockingStubFull.getNkFromNsk(nsk1)); - //System.out.println("nk:" + ByteArray.toHexString(nk.get().getValue().toByteArray())); - String nkString = ByteArray.toHexString(nk.get().getValue().toByteArray()); - - GrpcAPI.ViewingKeyMessage.Builder viewBuilder = GrpcAPI.ViewingKeyMessage.newBuilder(); - viewBuilder.setAk(ak.get().getValue()); - viewBuilder.setNk(nk.get().getValue()); - GrpcAPI.IncomingViewingKeyMessage ivk = blockingStubFull - .getIncomingViewingKey(viewBuilder.build()); - - //ivk.getIvk() - String ivkString = ByteArray.toHexString(ivk.getIvk().toByteArray()); - String ivkStringOld = ByteArray.toHexString(shieldedAddressInfo.getIvk()); - GrpcAPI.IvkDecryptTRC20Parameters parameters = GrpcAPI.IvkDecryptTRC20Parameters - .newBuilder() - .setStartBlockIndex(startNum) - .setEndBlockIndex(endNum) - .setShieldedTRC20ContractAddress(ByteString.copyFrom(Commons.decode58Check(shieldAddress))) - .setIvk(ByteString.copyFrom(ByteArray.fromHexString(ivkString))) - .setAk(ByteString.copyFrom(ByteArray.fromHexString(akString))) - .setNk(ByteString.copyFrom(ByteArray.fromHexString(nkString))) - .build(); - try { - return blockingStubSolidity.scanShieldedTRC20NotesByIvk(parameters); - } catch (Exception e) { - System.out.println(e); - Status status = Status.fromThrowable(e); - System.out.println("ScanShieldedTRC20NoteByIvk failed,error " + status.getDescription()); - - } - return null; - } - - - /** - * constructor. - */ - public GrpcAPI.DecryptNotesTRC20 scanShieldedTrc20NoteByIvk(ShieldedAddressInfo - shieldedAddressInfo, WalletGrpc.WalletBlockingStub blockingStubFull) throws Exception { - long currentBlockNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - - Long startNum = currentBlockNum - 90L; - final Long endNum = currentBlockNum; - if (currentBlockNum < 100) { - startNum = 1L; - } - - String spendingKey = ByteArray.toHexString(shieldedAddressInfo.getSk()); - BytesMessage sk = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(spendingKey))).build(); - Optional esk = Optional - .of(blockingStubFull.getExpandedSpendingKey(sk)); - - String ask = ByteArray.toHexString(esk.get().getAsk().toByteArray()); - - BytesMessage ask1 = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(ask))).build(); - Optional ak = Optional.of(blockingStubFull.getAkFromAsk(ask1)); - String akString = ByteArray.toHexString(ak.get().getValue().toByteArray()); - - String nsk = ByteArray.toHexString(esk.get().getNsk().toByteArray()); - - BytesMessage nsk1 = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(nsk))).build(); - Optional nk = Optional.of(blockingStubFull.getNkFromNsk(nsk1)); - String nkString = ByteArray.toHexString(nk.get().getValue().toByteArray()); - - GrpcAPI.ViewingKeyMessage.Builder viewBuilder = GrpcAPI.ViewingKeyMessage.newBuilder(); - viewBuilder.setAk(ak.get().getValue()); - viewBuilder.setNk(nk.get().getValue()); - GrpcAPI.IncomingViewingKeyMessage ivk = blockingStubFull - .getIncomingViewingKey(viewBuilder.build()); - - String ivkString = ByteArray.toHexString(ivk.getIvk().toByteArray()); - GrpcAPI.IvkDecryptTRC20Parameters parameters = GrpcAPI.IvkDecryptTRC20Parameters - .newBuilder() - .setStartBlockIndex(startNum) - .setEndBlockIndex(endNum) - .setShieldedTRC20ContractAddress(ByteString.copyFrom(Commons.decode58Check(shieldAddress))) - .setIvk(ByteString.copyFrom(ByteArray.fromHexString(ivkString))) - .setAk(ByteString.copyFrom(ByteArray.fromHexString(akString))) - .setNk(ByteString.copyFrom(ByteArray.fromHexString(nkString))) - //.setEvents() - .build(); - try { - return blockingStubFull.scanShieldedTRC20NotesByIvk(parameters); - } catch (Exception e) { - System.out.println(e); - Status status = Status.fromThrowable(e); - System.out.println("ScanShieldedTRC20NoteByIvk failed,error " + status.getDescription()); - - } - return null; - } - - - /** - * constructor. - */ - public GrpcAPI.DecryptNotesTRC20 scanShieldedTrc20NoteByIvkWithRange(ShieldedAddressInfo - shieldedAddressInfo, Long startNum, Long endNum, - WalletGrpc.WalletBlockingStub blockingStubFull) throws Exception { - - String spendingKey = ByteArray.toHexString(shieldedAddressInfo.getSk()); - BytesMessage sk = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(spendingKey))).build(); - Optional esk = Optional - .of(blockingStubFull.getExpandedSpendingKey(sk)); - - String ask = ByteArray.toHexString(esk.get().getAsk().toByteArray()); - - BytesMessage ask1 = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(ask))).build(); - Optional ak = Optional.of(blockingStubFull.getAkFromAsk(ask1)); - String akString = ByteArray.toHexString(ak.get().getValue().toByteArray()); - - String nsk = ByteArray.toHexString(esk.get().getNsk().toByteArray()); - - BytesMessage nsk1 = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(nsk))).build(); - Optional nk = Optional.of(blockingStubFull.getNkFromNsk(nsk1)); - String nkString = ByteArray.toHexString(nk.get().getValue().toByteArray()); - - GrpcAPI.ViewingKeyMessage.Builder viewBuilder = GrpcAPI.ViewingKeyMessage.newBuilder(); - viewBuilder.setAk(ak.get().getValue()); - viewBuilder.setNk(nk.get().getValue()); - GrpcAPI.IncomingViewingKeyMessage ivk = blockingStubFull - .getIncomingViewingKey(viewBuilder.build()); - - String ivkString = ByteArray.toHexString(ivk.getIvk().toByteArray()); - GrpcAPI.DecryptNotesTRC20 result = GrpcAPI.DecryptNotesTRC20.newBuilder().build(); - GrpcAPI.DecryptNotesTRC20 tempNoteTxs; - while (startNum < endNum) { - GrpcAPI.IvkDecryptTRC20Parameters parameters = GrpcAPI.IvkDecryptTRC20Parameters - .newBuilder() - .setStartBlockIndex(startNum) - .setEndBlockIndex(startNum + 99) - .setShieldedTRC20ContractAddress(ByteString - .copyFrom(Commons.decode58Check(shieldAddress))) - .setIvk(ByteString.copyFrom(ByteArray.fromHexString(ivkString))) - .setAk(ByteString.copyFrom(ByteArray.fromHexString(akString))) - .setNk(ByteString.copyFrom(ByteArray.fromHexString(nkString))) - .build(); - tempNoteTxs = blockingStubFull.scanShieldedTRC20NotesByIvk(parameters); - logger.info("tempNoteTxs size:" + tempNoteTxs.getNoteTxsCount()); - - result = result.toBuilder().addAllNoteTxs(tempNoteTxs.getNoteTxsList()).build(); - - startNum = startNum + 99; - } - try { - return result; - } catch (Exception e) { - System.out.println(e); - Status status = Status.fromThrowable(e); - System.out.println("ScanShieldedTRC20NoteByIvk failed,error " + status.getDescription()); - - } - return null; - } - - - /** - * constructor. - */ - public GrpcAPI.DecryptNotesTRC20 scanShieldedTrc20NoteByOvk(ShieldedAddressInfo - shieldedAddressInfo, WalletGrpc.WalletBlockingStub blockingStubFull) throws Exception { - long currentBlockNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - Long startNum = currentBlockNum - 90L; - Long endNum = currentBlockNum; - if (currentBlockNum < 100) { - startNum = 1L; - } - - String ovkString = ByteArray.toHexString(shieldedAddressInfo.getOvk()); - GrpcAPI.OvkDecryptTRC20Parameters parameters = GrpcAPI.OvkDecryptTRC20Parameters.newBuilder() - .setStartBlockIndex(startNum) - .setEndBlockIndex(endNum) - .setOvk(ByteString.copyFrom(ByteArray.fromHexString(ovkString))) - .setShieldedTRC20ContractAddress(ByteString.copyFrom(Commons.decode58Check(shieldAddress))) - .build(); - - try { - return blockingStubFull.scanShieldedTRC20NotesByOvk(parameters); - } catch (Exception e) { - System.out.println(e); - Status status = Status.fromThrowable(e); - System.out.println("ScanShieldedTRC20NoteByovk failed,error " + status.getDescription()); - - } - return null; - } - - - /** - * constructor. - */ - public GrpcAPI.DecryptNotesTRC20 scanShieldedTrc20NoteByOvk(ShieldedAddressInfo - shieldedAddressInfo, WalletGrpc.WalletBlockingStub blockingStubFull, - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) throws Exception { - long currentBlockNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - Long startNum = currentBlockNum - 90L; - Long endNum = currentBlockNum; - if (currentBlockNum < 100) { - startNum = 1L; - } - - String ovkString = ByteArray.toHexString(shieldedAddressInfo.getOvk()); - GrpcAPI.OvkDecryptTRC20Parameters parameters = GrpcAPI.OvkDecryptTRC20Parameters.newBuilder() - .setStartBlockIndex(startNum) - .setEndBlockIndex(endNum) - .setOvk(ByteString.copyFrom(ByteArray.fromHexString(ovkString))) - .setShieldedTRC20ContractAddress(ByteString.copyFrom(Commons.decode58Check(shieldAddress))) - .build(); - - try { - return blockingStubSolidity.scanShieldedTRC20NotesByOvk(parameters); - } catch (Exception e) { - System.out.println(e); - Status status = Status.fromThrowable(e); - System.out.println("ScanShieldedTRC20NoteByovk failed,error " + status.getDescription()); - - } - return null; - } - - /** - * constructor. - */ - public static Boolean getTrc20SpendResult( - ShieldedAddressInfo shieldAddressInfo, GrpcAPI.DecryptNotesTRC20.NoteTx noteTx, - WalletGrpc.WalletBlockingStub blockingStubFull) { - - GrpcAPI.NfTRC20Parameters.Builder builder = GrpcAPI.NfTRC20Parameters.newBuilder(); - - String spendingKey = ByteArray.toHexString(shieldAddressInfo.getSk()); - BytesMessage sk = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(spendingKey))).build(); - Optional esk = Optional - .of(blockingStubFull.getExpandedSpendingKey(sk)); - - String ask = ByteArray.toHexString(esk.get().getAsk().toByteArray()); - BytesMessage ask1 = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(ask))).build(); - Optional ak = Optional.of(blockingStubFull.getAkFromAsk(ask1)); - String nsk = ByteArray.toHexString(esk.get().getNsk().toByteArray()); - BytesMessage nsk1 = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(nsk))).build(); - Optional nk = Optional.of(blockingStubFull.getNkFromNsk(nsk1)); - builder.setAk(ak.get().getValue()); - builder.setNk(nk.get().getValue()); - builder.setPosition(noteTx.getPosition()); - builder.setShieldedTRC20ContractAddress(ByteString.copyFrom(shieldAddressByte)); - - Note.Builder noteBuild = Note.newBuilder(); - noteBuild.setPaymentAddress(shieldAddressInfo.getAddress()); - noteBuild.setValue(noteTx.getNote().getValue()); - noteBuild.setRcm(noteTx.getNote().getRcm()); - noteBuild.setMemo(noteTx.getNote().getMemo()); - builder.setNote(noteBuild.build()); - - Optional result = Optional.of(blockingStubFull - .isShieldedTRC20ContractNoteSpent(builder.build())); - return result.get().getIsSpent(); - } - - - /** - * constructor. - */ - public static Boolean getTrc20SpendResult( - ShieldedAddressInfo shieldAddressInfo, GrpcAPI.DecryptNotesTRC20.NoteTx noteTx, - WalletGrpc.WalletBlockingStub blockingStubFull, - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) { - - GrpcAPI.NfTRC20Parameters.Builder builder = GrpcAPI.NfTRC20Parameters.newBuilder(); - - String spendingKey = ByteArray.toHexString(shieldAddressInfo.getSk()); - BytesMessage sk = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(spendingKey))).build(); - Optional esk = Optional - .of(blockingStubFull.getExpandedSpendingKey(sk)); - - String ask = ByteArray.toHexString(esk.get().getAsk().toByteArray()); - BytesMessage ask1 = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(ask))).build(); - Optional ak = Optional.of(blockingStubFull.getAkFromAsk(ask1)); - String nsk = ByteArray.toHexString(esk.get().getNsk().toByteArray()); - BytesMessage nsk1 = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(nsk))).build(); - Optional nk = Optional.of(blockingStubFull.getNkFromNsk(nsk1)); - builder.setAk(ak.get().getValue()); - builder.setNk(nk.get().getValue()); - builder.setPosition(noteTx.getPosition()); - builder.setShieldedTRC20ContractAddress(ByteString.copyFrom(shieldAddressByte)); - - Note.Builder noteBuild = Note.newBuilder(); - noteBuild.setPaymentAddress(shieldAddressInfo.getAddress()); - noteBuild.setValue(noteTx.getNote().getValue()); - noteBuild.setRcm(noteTx.getNote().getRcm()); - noteBuild.setMemo(noteTx.getNote().getMemo()); - builder.setNote(noteBuild.build()); - - Optional result = Optional.of(blockingStubSolidity - .isShieldedTRC20ContractNoteSpent(builder.build())); - return result.get().getIsSpent(); - } - - - /** - * constructor. - */ - public byte[] getRandomOvk() { - try { - Optional sk = Optional.of(blockingStubFull - .getSpendingKey(EmptyMessage.newBuilder().build())); - Optional expandedSpendingKeyMessage - = Optional.of(blockingStubFull - .getExpandedSpendingKey(sk.get())); - return expandedSpendingKeyMessage.get().getOvk().toByteArray(); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - /** - * constructor. - */ - public BigInteger getRandomAmount() { - Random random = new Random(); - int x = random.nextInt(100000) + 100; - return BigInteger.valueOf(x); - } - - /** - * constructor. - */ - public Long getRandomLongAmount() { - Random random = new Random(); - int x = random.nextInt(100000) + 100; - return Long.valueOf(x); - } - - /** - * constructor. - */ - public String encodeTransferParamsToHexString(GrpcAPI.ShieldedTRC20Parameters parameters) { - byte[] input = new byte[0]; - byte[] spendAuthSig = new byte[0]; - byte[] output = new byte[0]; - byte[] c = new byte[0]; - byte[] bindingSig; - final byte[] mergedBytes; - List spendDescs = parameters.getSpendDescriptionList(); - for (ShieldContract.SpendDescription spendDesc : spendDescs) { - input = ByteUtil.merge(input, - spendDesc.getNullifier().toByteArray(), - spendDesc.getAnchor().toByteArray(), - spendDesc.getValueCommitment().toByteArray(), - spendDesc.getRk().toByteArray(), - spendDesc.getZkproof().toByteArray() - ); - spendAuthSig = ByteUtil.merge( - spendAuthSig, spendDesc.getSpendAuthoritySignature().toByteArray()); - } - byte[] inputOffsetbytes = longTo32Bytes(192); - long spendCount = spendDescs.size(); - byte[] spendCountBytes = longTo32Bytes(spendCount); - byte[] authOffsetBytes = longTo32Bytes(192 + 32 + 320 * spendCount); - List recvDescs = parameters.getReceiveDescriptionList(); - for (ShieldContract.ReceiveDescription recvDesc : recvDescs) { - output = ByteUtil.merge(output, - recvDesc.getNoteCommitment().toByteArray(), - recvDesc.getValueCommitment().toByteArray(), - recvDesc.getEpk().toByteArray(), - recvDesc.getZkproof().toByteArray() - ); - c = ByteUtil.merge(c, - recvDesc.getCEnc().toByteArray(), - recvDesc.getCOut().toByteArray(), - new byte[12] - ); - } - long recvCount = recvDescs.size(); - byte[] recvCountBytes = longTo32Bytes(recvCount); - byte[] outputOffsetbytes = longTo32Bytes(192 + 32 + 320 * spendCount + 32 + 64 * spendCount); - byte[] coffsetBytes = longTo32Bytes(192 + 32 + 320 * spendCount + 32 + 64 * spendCount + 32 - + 288 * recvCount); - bindingSig = parameters.getBindingSignature().toByteArray(); - mergedBytes = ByteUtil.merge(inputOffsetbytes, - authOffsetBytes, - outputOffsetbytes, - bindingSig, - coffsetBytes, - spendCountBytes, - input, - spendCountBytes, - spendAuthSig, - recvCountBytes, - output, - recvCountBytes, - c - ); - return ByteArray.toHexString(mergedBytes); - } - - /** - * constructor. - */ - public String encodeBurnParamsToHexString(GrpcAPI.ShieldedTRC20Parameters parameters, - BigInteger value, - String transparentToAddress) { - byte[] mergedBytes; - byte[] payTo = new byte[32]; - byte[] transparentToAddressBytes = Commons.decodeFromBase58Check(transparentToAddress); - System.arraycopy(transparentToAddressBytes, 0, payTo, 11, 21); - ShieldContract.SpendDescription spendDesc = parameters.getSpendDescription(0); - mergedBytes = ByteUtil.merge( - spendDesc.getNullifier().toByteArray(), - spendDesc.getAnchor().toByteArray(), - spendDesc.getValueCommitment().toByteArray(), - spendDesc.getRk().toByteArray(), - spendDesc.getZkproof().toByteArray(), - spendDesc.getSpendAuthoritySignature().toByteArray(), - ByteUtil.bigIntegerToBytes(value, 32), - parameters.getBindingSignature().toByteArray(), - payTo - ); - return ByteArray.toHexString(mergedBytes); - } - - - /** - * constructor. - */ - public byte[] longTo32Bytes(long value) { - byte[] longBytes = ByteArray.fromLong(value); - byte[] zeroBytes = new byte[24]; - return ByteUtil.merge(zeroBytes, longBytes); - } - - /** - * constructor. - */ - public JSONArray getHttpShieldedReceivesJsonArray(JSONArray shieldReceives, Long value, - String paymentAddress, String rcm) { - JSONObject note = new JSONObject(); - note.put("value", value); - note.put("payment_address", paymentAddress); - note.put("rcm", rcm); - JSONObject noteIndex = new JSONObject(); - noteIndex.put("note", note); - shieldReceives.add(noteIndex); - return shieldReceives; - - } - - - /** - * constructor. - */ - public static HttpResponse createShieldContractParameters(String httpNode, Long fromAmount, - JSONObject shieldAccountInfo, JSONArray shiledReceives) { - try { - final String requestUrl = "http://" + httpNode + "/wallet/createshieldedcontractparameters"; - - JSONObject rawBody = new JSONObject(); - rawBody.put("ovk", "4364c875deeb663781a2f1530f9e4f87ea81cc3c757ca2a30fa4768940de2f98"); - rawBody.put("from_amount", fromAmount.toString()); - rawBody.put("shielded_receives", shiledReceives); - rawBody.put("shielded_TRC20_contract_address", shieldAddress); - rawBody.put("visible", true); - - response = HttpMethed.createConnectForShieldTrc20(requestUrl, rawBody); - - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - /** - * constructor. - */ - public static HttpResponse createShieldContractParametersForBurn(String httpNode, - JSONObject shieldAccountInfo, JSONArray shieldedSpends, String toAddress, Long toAmount) { - return createShieldContractParametersForBurn(httpNode, shieldAccountInfo, shieldedSpends, - toAddress, toAmount, null); - - } - - /** - * constructor. - */ - public static HttpResponse createShieldContractParametersForBurn(String httpNode, - JSONObject shieldAccountInfo, JSONArray shieldedSpends, String toAddress, Long toAmount, - JSONArray shieldedReceiver) { - try { - final String requestUrl = "http://" + httpNode + "/wallet/createshieldedcontractparameters"; - JSONObject rawBody = new JSONObject(); - rawBody.put("ovk", shieldAccountInfo.getString("ovk")); - rawBody.put("ask", shieldAccountInfo.getString("ask")); - rawBody.put("nsk", shieldAccountInfo.getString("nsk")); - rawBody.put("shielded_spends", shieldedSpends); - if (shieldedReceiver != null) { - rawBody.put("shielded_receives", shieldedReceiver); - } - rawBody.put("shielded_TRC20_contract_address", shieldAddress); - rawBody.put("transparent_to_address", toAddress); - rawBody.put("to_amount", toAmount.toString()); - rawBody.put("visible", true); - - response = HttpMethed.createConnectForShieldTrc20(requestUrl, rawBody); - - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - /** - * constructor. - */ - public static HttpResponse createShieldContractParametersWithoutAskForBurn(String httpNode, - JSONObject shieldAccountInfo, JSONArray shieldedSpends, String toAddress, Long toAmount) { - return createShieldContractParametersWithoutAskForBurn(httpNode, shieldAccountInfo, - shieldedSpends, toAddress, toAmount, null); - } - - /** - * constructor. - */ - public static HttpResponse createShieldContractParametersWithoutAskForBurn(String httpNode, - JSONObject shieldAccountInfo, JSONArray shieldedSpends, String toAddress, Long toAmount, - JSONArray shieldedReceiver) { - try { - final String requestUrl - = "http://" + httpNode + "/wallet/createshieldedcontractparameterswithoutask"; - - JSONObject rawBody = new JSONObject(); - rawBody.put("ovk", shieldAccountInfo.getString("ovk")); - rawBody.put("ak", shieldAccountInfo.getString("ak")); - rawBody.put("nsk", shieldAccountInfo.getString("nsk")); - rawBody.put("shielded_spends", shieldedSpends); - rawBody.put("shielded_TRC20_contract_address", shieldAddress); - rawBody.put("transparent_to_address", toAddress); - rawBody.put("to_amount", toAmount.toString()); - rawBody.put("visible", true); - if (shieldedReceiver != null) { - rawBody.put("shielded_receives", shieldedReceiver); - } - - response = HttpMethed.createConnectForShieldTrc20(requestUrl, rawBody); - - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - - /** - * constructor. - */ - public static HttpResponse createShieldContractParametersForTransfer(String httpNode, - JSONObject shieldAccountInfo, JSONArray shieldedSpends, JSONArray shieldedReceives) { - try { - final String requestUrl = "http://" + httpNode + "/wallet/createshieldedcontractparameters"; - JSONObject rawBody = new JSONObject(); - rawBody.put("ovk", shieldAccountInfo.getString("ovk")); - rawBody.put("ask", shieldAccountInfo.getString("ask")); - rawBody.put("nsk", shieldAccountInfo.getString("nsk")); - rawBody.put("shielded_spends", shieldedSpends); - rawBody.put("shielded_TRC20_contract_address", shieldAddress); - rawBody.put("shielded_receives", shieldedReceives); - rawBody.put("visible", true); - logger.info(rawBody.toString()); - response = HttpMethed.createConnectForShieldTrc20(requestUrl, rawBody); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - - /** - * constructor. - */ - public static HttpResponse createShieldContractParametersWithoutAskForTransfer(String httpNode, - JSONObject shieldAccountInfo, JSONArray shieldedSpends, JSONArray shieldedReceives) { - try { - final String requestUrl = "http://" + httpNode - + "/wallet/createshieldedcontractparameterswithoutask"; - JSONObject rawBody = new JSONObject(); - rawBody.put("ovk", shieldAccountInfo.getString("ovk")); - rawBody.put("ak", shieldAccountInfo.getString("ak")); - rawBody.put("nsk", shieldAccountInfo.getString("nsk")); - rawBody.put("shielded_spends", shieldedSpends); - rawBody.put("shielded_TRC20_contract_address", shieldAddress); - rawBody.put("shielded_receives", shieldedReceives); - rawBody.put("visible", true); - logger.info(rawBody.toString()); - response = HttpMethed.createConnectForShieldTrc20(requestUrl, rawBody); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - /** - * constructor. - */ - public static JSONObject createSpendAuthSig(String httpNode, - JSONObject shieldAccountInfo, String messageHash, String alpha) { - try { - final String requestUrl = "http://" + httpNode + "/wallet/createspendauthsig"; - JSONObject rawBody = new JSONObject(); - rawBody.put("ask", shieldAccountInfo.getString("ask")); - rawBody.put("tx_hash", messageHash); - rawBody.put("alpha", alpha); - logger.info("createSpendAuthSig:" + rawBody.toString()); - response = HttpMethed.createConnectForShieldTrc20(requestUrl, rawBody); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return HttpMethed.parseResponseContent(response); - } - - - /** - * constructor. - */ - public static JSONArray scanShieldTrc20NoteByIvk(String httpNode, - JSONObject shieldAddressInfo) { - try { - Long endScanNumber = HttpMethed.getNowBlockNum(httpNode); - Long startScanNumer = endScanNumber > 99 ? endScanNumber - 90 : 1; - - final String requestUrl = "http://" + httpNode + "/wallet/scanshieldedtrc20notesbyivk"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("start_block_index", startScanNumer); - userBaseObj2.addProperty("end_block_index", endScanNumber); - userBaseObj2.addProperty("shielded_TRC20_contract_address", shieldAddress); - userBaseObj2.addProperty("ivk", shieldAddressInfo.getString("ivk")); - userBaseObj2.addProperty("ak", shieldAddressInfo.getString("ak")); - userBaseObj2.addProperty("nk", shieldAddressInfo.getString("nk")); - userBaseObj2.addProperty("visible", true); - logger.info("scanShieldTrc20NoteByIvk:" + userBaseObj2.toString()); - response = HttpMethed.createConnect(requestUrl, userBaseObj2); - - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = responseContent.getJSONArray("noteTxs"); - - return jsonArray; - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - } - - - /** - * constructor. - */ - public static JSONArray scanShieldTrc20NoteByIvkOnSolidity(String httpNode, - JSONObject shieldAddressInfo) { - try { - Long endScanNumber = HttpMethed.getNowBlockNumOnSolidity(httpNode); - Long startScanNumer = endScanNumber > 99 ? endScanNumber - 90 : 1; - - final String requestUrl = - "http://" + httpNode + "/walletsolidity/scanshieldedtrc20notesbyivk"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("start_block_index", startScanNumer); - userBaseObj2.addProperty("end_block_index", endScanNumber); - userBaseObj2.addProperty("shielded_TRC20_contract_address", shieldAddress); - userBaseObj2.addProperty("ivk", shieldAddressInfo.getString("ivk")); - userBaseObj2.addProperty("ak", shieldAddressInfo.getString("ak")); - userBaseObj2.addProperty("nk", shieldAddressInfo.getString("nk")); - userBaseObj2.addProperty("visible", true); - logger.info("scanShieldTrc20NoteByIvk:" + userBaseObj2.toString()); - response = HttpMethed.createConnect(requestUrl, userBaseObj2); - - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = responseContent.getJSONArray("noteTxs"); - - return jsonArray; - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - } - - /** - * constructor. - */ - public static JSONArray scanShieldTrc20NoteByIvkOnPbft(String httpPbftNode, - JSONObject shieldAddressInfo) { - try { - - response = HttpMethed.getNowBlockFromPbft(httpPbftNode); - Long endScanNumber = HttpMethed.parseResponseContent(response).getJSONObject("block_header") - .getJSONObject("raw_data").getLong("number"); - Long startScanNumer = endScanNumber > 99 ? endScanNumber - 90 : 1; - - final String requestUrl = - "http://" + httpPbftNode + "/walletpbft/scanshieldedtrc20notesbyivk"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("start_block_index", startScanNumer); - userBaseObj2.addProperty("end_block_index", endScanNumber); - userBaseObj2.addProperty("shielded_TRC20_contract_address", shieldAddress); - userBaseObj2.addProperty("ivk", shieldAddressInfo.getString("ivk")); - userBaseObj2.addProperty("ak", shieldAddressInfo.getString("ak")); - userBaseObj2.addProperty("nk", shieldAddressInfo.getString("nk")); - userBaseObj2.addProperty("visible", true); - logger.info("scanShieldTrc20NoteByIvk:" + userBaseObj2.toString()); - response = HttpMethed.createConnect(requestUrl, userBaseObj2); - - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = responseContent.getJSONArray("noteTxs"); - - return jsonArray; - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - } - - - /** - * constructor. - */ - public static JSONArray scanShieldTrc20NoteByOvk(String httpNode, - JSONObject shieldAddressInfo) { - try { - Long endScanNumber = HttpMethed.getNowBlockNum(httpNode); - Long startScanNumer = endScanNumber > 99 ? endScanNumber - 90 : 1; - - final String requestUrl = "http://" + httpNode + "/wallet/scanshieldedtrc20notesbyovk"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("start_block_index", startScanNumer); - userBaseObj2.addProperty("end_block_index", endScanNumber); - userBaseObj2.addProperty("shielded_TRC20_contract_address", shieldAddress); - userBaseObj2.addProperty("ovk", shieldAddressInfo.getString("ovk")); - userBaseObj2.addProperty("visible", true); - logger.info("userBaseObj2:" + userBaseObj2.toString()); - response = HttpMethed.createConnect(requestUrl, userBaseObj2); - - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = responseContent.getJSONArray("noteTxs"); - - return jsonArray; - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - } - - - /** - * constructor. - */ - public static JSONArray scanShieldTrc20NoteByOvkOnSolidity(String httpNode, - JSONObject shieldAddressInfo) { - try { - Long endScanNumber = HttpMethed.getNowBlockNumOnSolidity(httpNode); - Long startScanNumer = endScanNumber > 99 ? endScanNumber - 90 : 1; - - final String requestUrl = - "http://" + httpNode + "/walletsolidity/scanshieldedtrc20notesbyovk"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("start_block_index", startScanNumer); - userBaseObj2.addProperty("end_block_index", endScanNumber); - userBaseObj2.addProperty("shielded_TRC20_contract_address", shieldAddress); - userBaseObj2.addProperty("ovk", shieldAddressInfo.getString("ovk")); - userBaseObj2.addProperty("visible", true); - logger.info("userBaseObj2:" + userBaseObj2.toString()); - response = HttpMethed.createConnect(requestUrl, userBaseObj2); - - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = responseContent.getJSONArray("noteTxs"); - - return jsonArray; - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - } - - /** - * constructor. - */ - public static JSONArray scanShieldTrc20NoteByOvkOnPbft(String httpPbftNode, - JSONObject shieldAddressInfo) { - try { - response = HttpMethed.getNowBlockFromPbft(httpPbftNode); - Long endScanNumber = HttpMethed.parseResponseContent(response).getJSONObject("block_header") - .getJSONObject("raw_data").getLong("number"); - Long startScanNumer = endScanNumber > 99 ? endScanNumber - 90 : 1; - - final String requestUrl = - "http://" + httpPbftNode + "/walletpbft/scanshieldedtrc20notesbyovk"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("start_block_index", startScanNumer); - userBaseObj2.addProperty("end_block_index", endScanNumber); - userBaseObj2.addProperty("shielded_TRC20_contract_address", shieldAddress); - userBaseObj2.addProperty("ovk", shieldAddressInfo.getString("ovk")); - userBaseObj2.addProperty("visible", true); - logger.info("userBaseObj2:" + userBaseObj2.toString()); - response = HttpMethed.createConnect(requestUrl, userBaseObj2); - - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = responseContent.getJSONArray("noteTxs"); - - return jsonArray; - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - } - - /** - * constructor. - */ - public static String getRootAndPathByHttp(String httpNode, Integer position) { - try { - final String requestUrl = "http://" + httpNode + "/wallet/triggerconstantcontract"; - JsonObject userBaseObj2 = new JsonObject(); - - userBaseObj2.addProperty("owner_address", zenTrc20TokenOwnerAddressString); - userBaseObj2.addProperty("contract_address", shieldAddress); - userBaseObj2.addProperty("function_selector", "getPath(uint256)"); - byte[] indexBytes = ByteArray.fromLong(position); - String argsStr = ByteArray.toHexString(indexBytes); - String parameter = "000000000000000000000000000000000000000000000000" + argsStr; - userBaseObj2.addProperty("parameter", parameter); - userBaseObj2.addProperty("fee_limit", maxFeeLimit); - userBaseObj2.addProperty("visible", true); - - response = HttpMethed.createConnect(requestUrl, userBaseObj2); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return HttpMethed.parseResponseContent(response).getJSONArray("constant_result").getString(0); - } - - /** - * constructor. - */ - public static JSONArray createAndSetShieldedSpends(String httpNode, - JSONArray shieldedSpends, JSONObject noteTxs) { - JSONObject shieldedSpend = new JSONObject(); - shieldedSpend.put("note", noteTxs.getJSONObject("note")); - shieldedSpend.put("alpha", noteTxs.getJSONObject("note").getString("rcm")); - Integer position = noteTxs.containsKey("position") ? noteTxs.getInteger("position") : 0; - String rootAndPath = getRootAndPathByHttp(httpNode, position); - String root = rootAndPath.substring(0, 64); - String path = rootAndPath.substring(64); - shieldedSpend.put("root", root); - shieldedSpend.put("path", path); - shieldedSpend.put("pos", position); - shieldedSpends.add(shieldedSpend); - return shieldedSpends; - } - - - /** - * constructor. - */ - public static String getRcm(String httpNode) { - try { - String requestUrl = "http://" + httpNode + "/wallet/getrcm"; - response = HttpMethed.createConnect(requestUrl); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return HttpMethed.parseResponseContent(response).getString("value"); - } - - - /** - * constructor. - */ - public static Boolean isShieldedTrc20ContractNoteSpent(String httpNode, - JSONObject accountInfo, JSONObject noteTxs) { - try { - final String requestUrl = "http://" + httpNode + "/wallet/isshieldedtrc20contractnotespent"; - JSONObject userBaseObj2 = new JSONObject(); - userBaseObj2.put("note", noteTxs.getJSONObject("note")); - userBaseObj2.put("ak", accountInfo.getString("ak")); - userBaseObj2.put("nk", accountInfo.getString("nk")); - userBaseObj2.put("position", noteTxs.containsKey("position") - ? noteTxs.getInteger("position") : 0); - userBaseObj2.put("visible", true); - userBaseObj2.put("shielded_TRC20_contract_address", shieldAddress); - logger.info(userBaseObj2.toString()); - response = HttpMethed.createConnectForShieldTrc20(requestUrl, userBaseObj2); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - return responseContent.containsKey("is_spent") - ? responseContent.getBoolean("is_spent") : false; - } - - /** - * constructor. - */ - public static Boolean isShieldedTrc20ContractNoteSpentOnSolidity(String httpNode, - JSONObject accountInfo, JSONObject noteTxs) { - try { - final String requestUrl - = "http://" + httpNode + "/walletsolidity/isshieldedtrc20contractnotespent"; - JSONObject userBaseObj2 = new JSONObject(); - userBaseObj2.put("note", noteTxs.getJSONObject("note")); - userBaseObj2.put("ak", accountInfo.getString("ak")); - userBaseObj2.put("nk", accountInfo.getString("nk")); - userBaseObj2.put("position", noteTxs.containsKey("position") - ? noteTxs.getInteger("position") : 0); - userBaseObj2.put("visible", true); - userBaseObj2.put("shielded_TRC20_contract_address", shieldAddress); - logger.info(userBaseObj2.toString()); - response = HttpMethed.createConnectForShieldTrc20(requestUrl, userBaseObj2); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - return responseContent.containsKey("is_spent") ? responseContent.getBoolean("is_spent") : false; - } - - /** - * constructor. - */ - public static Boolean isShieldedTrc20ContractNoteSpentOnPbft(String httpPbftNode, - JSONObject accountInfo, JSONObject noteTxs) { - try { - final String requestUrl - = "http://" + httpPbftNode + "/walletpbft/isshieldedtrc20contractnotespent"; - JSONObject userBaseObj2 = new JSONObject(); - userBaseObj2.put("note", noteTxs.getJSONObject("note")); - userBaseObj2.put("ak", accountInfo.getString("ak")); - userBaseObj2.put("nk", accountInfo.getString("nk")); - userBaseObj2.put("position", noteTxs.containsKey("position") - ? noteTxs.getInteger("position") : 0); - userBaseObj2.put("visible", true); - userBaseObj2.put("shielded_TRC20_contract_address", shieldAddress); - logger.info(userBaseObj2.toString()); - response = HttpMethed.createConnectForShieldTrc20(requestUrl, userBaseObj2); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - return responseContent.containsKey("is_spent") ? responseContent.getBoolean("is_spent") : false; - } - - /** - * constructor. - */ - public static HttpResponse getTriggerInputForShieldedTrc20Contract(String httpNode, - JSONObject shieldedTrc20Parameters, JSONArray spendAuthoritySignature) { - try { - final String requestUrl = "http://" + httpNode - + "/wallet/gettriggerinputforshieldedtrc20contract"; - JSONObject userBaseObj2 = new JSONObject(); - userBaseObj2.put("shielded_TRC20_Parameters", shieldedTrc20Parameters); - userBaseObj2.put("spend_authority_signature", spendAuthoritySignature); - - logger.info("gettriggerinputforshieldedtrc20contract:" + userBaseObj2.toString()); - response = HttpMethed.createConnectForShieldTrc20(requestUrl, userBaseObj2); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - /** - * constructor. - */ - public static HttpResponse getTriggerInputForShieldedTrc20BurnContract(String httpNode, - JSONObject shieldedTrc20Parameters, JSONArray spendAuthoritySignature, Long amount, - String toAddress) { - try { - final String requestUrl = "http://" - + httpNode + "/wallet/gettriggerinputforshieldedtrc20contract"; - JSONObject userBaseObj2 = new JSONObject(); - userBaseObj2.put("shielded_TRC20_Parameters", shieldedTrc20Parameters); - userBaseObj2.put("spend_authority_signature", spendAuthoritySignature); - userBaseObj2.put("amount", amount.toString()); - userBaseObj2.put("transparent_to_address", toAddress); - userBaseObj2.put("visible", true); - - logger.info("gettriggerinputforshieldedtrc20contract:" + userBaseObj2.toString()); - response = HttpMethed.createConnectForShieldTrc20(requestUrl, userBaseObj2); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/ZenUtils.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/ZenUtils.java deleted file mode 100644 index f14b91670b7..00000000000 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/ZenUtils.java +++ /dev/null @@ -1,154 +0,0 @@ -package stest.tron.wallet.common.client.utils; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.nio.charset.Charset; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; - -public class ZenUtils { - - public static List getListFromFile(final String fileName) { - List list = new ArrayList<>(); - try { - FileInputStream inputStream = new FileInputStream(fileName); - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); - - String str = null; - while ((str = bufferedReader.readLine()) != null) { - System.out.println(str); - list.add(str); - } - inputStream.close(); - bufferedReader.close(); - } catch (Exception e) { - if (e.getMessage() != null) { - System.out.println(e.getMessage()); - } else { - System.out.println(e.getClass()); - } - } - return list; - } - - public static boolean appendToFileTail(final String fileName, final String content) { - BufferedWriter out = null; - try { - out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName, true))); - out.write(content + "\n"); - out.flush(); - } catch (Exception e) { - e.printStackTrace(); - } finally { - try { - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - return true; - } - - public static void clearFile(String fileName) { - File file = new File(fileName); - try { - if (file.exists()) { - FileWriter fileWriter = new FileWriter(file); - fileWriter.write(""); - fileWriter.flush(); - fileWriter.close(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static void checkFolderExist(final String filePath) { - try { - File file = new File(filePath); - if (file.exists()) { - if (file.isDirectory()) { - return; - } else { - file.delete(); - } - } - file.mkdir(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static String getMemo(byte[] memo) { - int index = memo.length; - for (; index > 0; --index) { - if (memo[index - 1] != 0) { - break; - } - } - - byte[] inputCheck = new byte[index]; - System.arraycopy(memo, 0, inputCheck, 0, index); - return new String(inputCheck, Charset.forName("UTF-8")); - } - - - public static byte[] aesCtrEncrypt(byte[] text, byte[] encryptKey) throws CipherException { - try { - byte[] iv = new byte[16]; - new SecureRandom().nextBytes(iv); - IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); - Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); - - SecretKeySpec secretKeySpec = new SecretKeySpec(encryptKey, "AES"); - cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); - byte[] cipherText = cipher.doFinal(text); - byte[] result = new byte[cipherText.length + iv.length]; - System.arraycopy(iv, 0, result, 0, iv.length); - System.arraycopy(cipherText, 0, result, iv.length, cipherText.length); - return result; - } catch (NoSuchPaddingException | NoSuchAlgorithmException - | InvalidAlgorithmParameterException | InvalidKeyException - | BadPaddingException | IllegalBlockSizeException e) { - throw new CipherException("Error performing cipher operation", e); - } - } - - public static byte[] aesCtrDecrypt(byte[] cipherText, byte[] encryptKey) throws CipherException { - try { - byte[] iv = Arrays.copyOfRange(cipherText, 0, 16); - cipherText = Arrays.copyOfRange(cipherText, iv.length, cipherText.length); - - IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); - Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); - - SecretKeySpec secretKeySpec = new SecretKeySpec(encryptKey, "AES"); - cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); - return cipher.doFinal(cipherText); - } catch (NoSuchPaddingException | NoSuchAlgorithmException - | InvalidAlgorithmParameterException | InvalidKeyException - | BadPaddingException | IllegalBlockSizeException e) { - throw new CipherException("Error performing cipher operation", e); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage002.java b/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage002.java deleted file mode 100644 index f4e1b335649..00000000000 --- a/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage002.java +++ /dev/null @@ -1,271 +0,0 @@ -package stest.tron.wallet.contract.linkage; - -import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS_VALUE; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractLinkage002 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] linkage002Address = ecKey1.getAddress(); - String linkage002Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(linkage002Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - @Test(enabled = true) - public void updateSetting() { - String sendcoin = PublicMethed - .sendcoinGetTransactionId(linkage002Address, 200000000000L, fromAddress, - testKey002, blockingStubFull); - Account info; - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById0 = null; - infoById0 = PublicMethed.getTransactionInfoById(sendcoin, blockingStubFull); - logger.info("infoById0 " + infoById0.get()); - Assert.assertEquals(ByteArray.toHexString(infoById0.get().getContractResult(0).toByteArray()), - ""); - Assert.assertEquals(infoById0.get().getResult().getNumber(), 0); - Optional ById = PublicMethed.getTransactionById(sendcoin, blockingStubFull); - Assert.assertEquals(ById.get().getRet(0).getContractRet().getNumber(), - SUCCESS_VALUE); - Assert.assertEquals(ById.get().getRet(0).getContractRetValue(), SUCCESS_VALUE); - Assert.assertEquals(ById.get().getRet(0).getContractRet(), contractResult.SUCCESS); - - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(linkage002Address, 50000000L, - 3, 1, linkage002Key, blockingStubFull)); - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(linkage002Address, - blockingStubFull); - info = PublicMethed.queryAccount(linkage002Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyLimit = resourceInfo.getEnergyLimit(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeFreeNetLimit = resourceInfo.getFreeNetLimit(); - Long beforeNetLimit = resourceInfo.getNetLimit(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyLimit:" + beforeEnergyLimit); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeFreeNetLimit:" + beforeFreeNetLimit); - logger.info("beforeNetLimit:" + beforeNetLimit); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/contractLinkage002.sol"; - String contractName = "divideIHaveArgsReturnStorage"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - //Set the consumeUserResourcePercent is -1,Nothing change. - byte[] contractAddress; - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", - maxFeeLimit, 0L, -1, null, linkage002Key, linkage002Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account infoafter = PublicMethed.queryAccount(linkage002Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(linkage002Address, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyLimit = resourceInfoafter.getEnergyLimit(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterFreeNetLimit = resourceInfoafter.getFreeNetLimit(); - Long afterNetLimit = resourceInfoafter.getNetLimit(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyLimit:" + afterEnergyLimit); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterFreeNetLimit:" + afterFreeNetLimit); - logger.info("afterNetLimit:" + afterNetLimit); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertEquals(beforeBalance, afterBalance); - Assert.assertTrue(afterNetUsed == 0); - Assert.assertTrue(afterEnergyUsed == 0); - Assert.assertTrue(afterFreeNetUsed > 0); - - //Set the consumeUserResourcePercent is 101,Nothing change. - AccountResourceMessage resourceInfo3 = PublicMethed.getAccountResource(linkage002Address, - blockingStubFull); - Account info3 = PublicMethed.queryAccount(linkage002Address, blockingStubFull); - Long beforeBalance3 = info3.getBalance(); - Long beforeEnergyLimit3 = resourceInfo3.getEnergyLimit(); - Long beforeEnergyUsed3 = resourceInfo3.getEnergyUsed(); - Long beforeFreeNetLimit3 = resourceInfo3.getFreeNetLimit(); - Long beforeNetLimit3 = resourceInfo3.getNetLimit(); - Long beforeNetUsed3 = resourceInfo3.getNetUsed(); - Long beforeFreeNetUsed3 = resourceInfo3.getFreeNetUsed(); - logger.info("beforeBalance3:" + beforeBalance3); - logger.info("beforeEnergyLimit3:" + beforeEnergyLimit3); - logger.info("beforeEnergyUsed3:" + beforeEnergyUsed3); - logger.info("beforeFreeNetLimit3:" + beforeFreeNetLimit3); - logger.info("beforeNetLimit3:" + beforeNetLimit3); - logger.info("beforeNetUsed3:" + beforeNetUsed3); - logger.info("beforeFreeNetUsed3:" + beforeFreeNetUsed3); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 101, null, linkage002Key, linkage002Address, blockingStubFull); - Account infoafter3 = PublicMethed.queryAccount(linkage002Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter3 = PublicMethed.getAccountResource(linkage002Address, - blockingStubFull1); - Long afterBalance3 = infoafter3.getBalance(); - Long afterEnergyLimit3 = resourceInfoafter3.getEnergyLimit(); - Long afterEnergyUsed3 = resourceInfoafter3.getEnergyUsed(); - Long afterFreeNetLimit3 = resourceInfoafter3.getFreeNetLimit(); - Long afterNetLimit3 = resourceInfoafter3.getNetLimit(); - Long afterNetUsed3 = resourceInfoafter3.getNetUsed(); - Long afterFreeNetUsed3 = resourceInfoafter3.getFreeNetUsed(); - logger.info("afterBalance3:" + afterBalance3); - logger.info("afterEnergyLimit3:" + afterEnergyLimit3); - logger.info("afterEnergyUsed3:" + afterEnergyUsed3); - logger.info("afterFreeNetLimit3:" + afterFreeNetLimit3); - logger.info("afterNetLimit3:" + afterNetLimit3); - logger.info("afterNetUsed3:" + afterNetUsed3); - logger.info("afterFreeNetUsed3:" + afterFreeNetUsed3); - - Assert.assertEquals(beforeBalance3, afterBalance3); - Assert.assertTrue(afterNetUsed3 == 0); - Assert.assertTrue(afterEnergyUsed3 == 0); - Assert.assertTrue(afterFreeNetUsed3 > 0); - - //Set consumeUserResourcePercent is 100,balance not change,use FreeNet freezeBalanceGetEnergy. - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, linkage002Key, linkage002Address, blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getConsumeUserResourcePercent() == 100); - - //Set the consumeUserResourcePercent is 0,balance not change,use FreeNet freezeBalanceGetEnergy. - AccountResourceMessage resourceInfo2 = PublicMethed.getAccountResource(linkage002Address, - blockingStubFull); - Account info2 = PublicMethed.queryAccount(linkage002Address, blockingStubFull); - Long beforeBalance2 = info2.getBalance(); - Long beforeEnergyLimit2 = resourceInfo2.getEnergyLimit(); - Long beforeEnergyUsed2 = resourceInfo2.getEnergyUsed(); - Long beforeFreeNetLimit2 = resourceInfo2.getFreeNetLimit(); - Long beforeNetLimit2 = resourceInfo2.getNetLimit(); - Long beforeNetUsed2 = resourceInfo2.getNetUsed(); - Long beforeFreeNetUsed2 = resourceInfo2.getFreeNetUsed(); - logger.info("beforeBalance2:" + beforeBalance2); - logger.info("beforeEnergyLimit2:" + beforeEnergyLimit2); - logger.info("beforeEnergyUsed2:" + beforeEnergyUsed2); - logger.info("beforeFreeNetLimit2:" + beforeFreeNetLimit2); - logger.info("beforeNetLimit2:" + beforeNetLimit2); - logger.info("beforeNetUsed2:" + beforeNetUsed2); - logger.info("beforeFreeNetUsed2:" + beforeFreeNetUsed2); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 0, null, linkage002Key, linkage002Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account infoafter2 = PublicMethed.queryAccount(linkage002Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter2 = PublicMethed.getAccountResource(linkage002Address, - blockingStubFull1); - Long afterBalance2 = infoafter2.getBalance(); - Long afterEnergyLimit2 = resourceInfoafter2.getEnergyLimit(); - Long afterEnergyUsed2 = resourceInfoafter2.getEnergyUsed(); - Long afterFreeNetLimit2 = resourceInfoafter2.getFreeNetLimit(); - Long afterNetLimit2 = resourceInfoafter2.getNetLimit(); - Long afterNetUsed2 = resourceInfoafter2.getNetUsed(); - Long afterFreeNetUsed2 = resourceInfoafter2.getFreeNetUsed(); - logger.info("afterBalance2:" + afterBalance2); - logger.info("afterEnergyLimit2:" + afterEnergyLimit2); - logger.info("afterEnergyUsed2:" + afterEnergyUsed2); - logger.info("afterFreeNetLimit2:" + afterFreeNetLimit2); - logger.info("afterNetLimit2:" + afterNetLimit2); - logger.info("afterNetUsed2:" + afterNetUsed2); - logger.info("afterFreeNetUsed2:" + afterFreeNetUsed2); - - Assert.assertEquals(beforeBalance2, afterBalance2); - Assert.assertTrue(afterNetUsed2 == 0); - Assert.assertTrue(afterEnergyUsed2 > 0); - Assert.assertTrue(afterFreeNetUsed2 > 0); - smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getConsumeUserResourcePercent() == 0); - - //Update the consumeUserResourcePercent setting. - Assert.assertTrue(PublicMethed.updateSetting(contractAddress, 66L, - linkage002Key, linkage002Address, blockingStubFull)); - smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getConsumeUserResourcePercent() == 66); - - //Updaate the consumeUserResourcePercent setting with -1 and 101 - Assert.assertFalse(PublicMethed.updateSetting(contractAddress, -1L, - linkage002Key, linkage002Address, blockingStubFull)); - Assert.assertFalse(PublicMethed.updateSetting(contractAddress, 101L, - linkage002Key, linkage002Address, blockingStubFull)); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage003.java b/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage003.java deleted file mode 100644 index 190867bba00..00000000000 --- a/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage003.java +++ /dev/null @@ -1,157 +0,0 @@ -package stest.tron.wallet.contract.linkage; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractLinkage003 { - - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey003); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] linkage003Address = ecKey1.getAddress(); - String linkage002Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(linkage002Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - @Test(enabled = true) - public void deployWhenNoEnergy() { - Assert.assertTrue(PublicMethed.sendcoin(linkage003Address, 200000000L, fromAddress, - testKey003, blockingStubFull)); - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(linkage003Address, - blockingStubFull); - info = PublicMethed.queryAccount(linkage003Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyLimit = resourceInfo.getEnergyLimit(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeFreeNetLimit = resourceInfo.getFreeNetLimit(); - Long beforeNetLimit = resourceInfo.getNetLimit(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyLimit:" + beforeEnergyLimit); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeFreeNetLimit:" + beforeFreeNetLimit); - logger.info("beforeNetLimit:" + beforeNetLimit); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "src/test/resources/soliditycode//contractLinkage003.sol"; - String contractName = "divideIHaveArgsReturnStorage"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - //use FreeNet and balance,EnergyUsed==0. - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 0, null, linkage002Key, linkage003Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - byte[] contractAddress = infoById.get().getContractAddress().toByteArray(); - Long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - Long fee = infoById.get().getFee(); - Long energyFee = infoById.get().getReceipt().getEnergyFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - logger.info("energyUsageTotal:" + energyUsageTotal); - logger.info("fee:" + fee); - logger.info("energyFee:" + energyFee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - - Account infoafter = PublicMethed.queryAccount(linkage003Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(linkage003Address, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyLimit = resourceInfoafter.getEnergyLimit(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterFreeNetLimit = resourceInfoafter.getFreeNetLimit(); - Long afterNetLimit = resourceInfoafter.getNetLimit(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyLimit:" + afterEnergyLimit); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterFreeNetLimit:" + afterFreeNetLimit); - logger.info("afterNetLimit:" + afterNetLimit); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getName().isEmpty()); - Assert.assertTrue((beforeBalance - fee) == afterBalance); - Assert.assertTrue(afterEnergyUsed == 0L); - Assert.assertTrue(afterFreeNetUsed > 0L); - Assert.assertTrue(afterNetUsed == 0L); - - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage004.java b/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage004.java deleted file mode 100644 index 159411040d4..00000000000 --- a/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage004.java +++ /dev/null @@ -1,320 +0,0 @@ -package stest.tron.wallet.contract.linkage; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractLinkage004 { - - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey003); - String contractName; - String code; - String abi; - Long currentFee; - Account info; - Long beforeBalance; - Long beforeNetLimit; - Long beforeFreeNetLimit; - Long beforeFreeNetUsed; - Long beforeNetUsed; - Long beforeEnergyLimit; - Long beforeEnergyUsed; - Long afterBalance; - Long afterNetLimit; - Long afterFreeNetLimit; - Long afterFreeNetUsed; - Long afterNetUsed; - Long afterEnergyLimit; - Long afterEnergyUsed; - Long energyUsed; - Long netUsed; - Long energyFee; - Long fee; - Long energyUsageTotal; - Long netFee; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] linkage004Address = ecKey1.getAddress(); - String linkage004Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(linkage004Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - @Test(enabled = true) - public void test1GetTransactionInfoById() { - ecKey1 = new ECKey(Utils.getRandom()); - linkage004Address = ecKey1.getAddress(); - linkage004Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - Assert.assertTrue(PublicMethed.sendcoin(linkage004Address, 2000000000000L, fromAddress, - testKey003, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalance(linkage004Address, 10000000L, - 3, linkage004Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(linkage004Address, - blockingStubFull); - info = PublicMethed.queryAccount(linkage004Address, blockingStubFull); - beforeBalance = info.getBalance(); - beforeEnergyLimit = resourceInfo.getEnergyLimit(); - beforeEnergyUsed = resourceInfo.getEnergyUsed(); - beforeFreeNetLimit = resourceInfo.getFreeNetLimit(); - beforeNetLimit = resourceInfo.getNetLimit(); - beforeNetUsed = resourceInfo.getNetUsed(); - beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyLimit:" + beforeEnergyLimit); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeFreeNetLimit:" + beforeFreeNetLimit); - logger.info("beforeNetLimit:" + beforeNetLimit); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/contractLinkage004.sol"; - String contractName = "divideIHaveArgsReturnStorage"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - //use freezeBalanceGetNet,Balance .No freezeBalanceGetenergy - String txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, - "", maxFeeLimit, 0L, 50, null, linkage004Key, linkage004Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - fee = infoById.get().getFee(); - currentFee = fee; - energyFee = infoById.get().getReceipt().getEnergyFee(); - netUsed = infoById.get().getReceipt().getNetUsage(); - energyUsed = infoById.get().getReceipt().getEnergyUsage(); - netFee = infoById.get().getReceipt().getNetFee(); - logger.info("energyUsageTotal:" + energyUsageTotal); - logger.info("fee:" + fee); - logger.info("energyFee:" + energyFee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - - Account infoafter = PublicMethed.queryAccount(linkage004Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(linkage004Address, - blockingStubFull1); - afterBalance = infoafter.getBalance(); - afterEnergyLimit = resourceInfoafter.getEnergyLimit(); - afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - afterFreeNetLimit = resourceInfoafter.getFreeNetLimit(); - afterNetLimit = resourceInfoafter.getNetLimit(); - afterNetUsed = resourceInfoafter.getNetUsed(); - afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyLimit:" + afterEnergyLimit); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterFreeNetLimit:" + afterFreeNetLimit); - logger.info("afterNetLimit:" + afterNetLimit); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("---------------:"); - Assert.assertTrue(infoById.isPresent()); - Assert.assertTrue((beforeBalance - fee) == afterBalance); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterEnergyUsed == 0); - Assert.assertTrue(afterFreeNetUsed > 0); - } - - @Test(enabled = true) - public void test2FeeLimitIsTooSmall() { - //When the fee limit is only short with 1 sun,failed.use freezeBalanceGetNet. - maxFeeLimit = currentFee - 1L; - AccountResourceMessage resourceInfo1 = PublicMethed.getAccountResource(linkage004Address, - blockingStubFull); - Account info1 = PublicMethed.queryAccount(linkage004Address, blockingStubFull); - Long beforeBalance1 = info1.getBalance(); - Long beforeEnergyLimit1 = resourceInfo1.getEnergyLimit(); - Long beforeEnergyUsed1 = resourceInfo1.getEnergyUsed(); - Long beforeFreeNetLimit1 = resourceInfo1.getFreeNetLimit(); - Long beforeNetLimit1 = resourceInfo1.getNetLimit(); - Long beforeNetUsed1 = resourceInfo1.getNetUsed(); - Long beforeFreeNetUsed1 = resourceInfo1.getFreeNetUsed(); - logger.info("beforeBalance1:" + beforeBalance1); - logger.info("beforeEnergyLimit1:" + beforeEnergyLimit1); - logger.info("beforeEnergyUsed1:" + beforeEnergyUsed1); - logger.info("beforeFreeNetLimit1:" + beforeFreeNetLimit1); - logger.info("beforeNetLimit1:" + beforeNetLimit1); - logger.info("beforeNetUsed1:" + beforeNetUsed1); - logger.info("beforeFreeNetUsed1:" + beforeFreeNetUsed1); - - String filePath = "./src/test/resources/soliditycode/contractLinkage004.sol"; - String contractName = "divideIHaveArgsReturnStorage"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, - "", maxFeeLimit, 0L, 50, null, linkage004Key, linkage004Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - - Optional infoById1 = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Long energyUsageTotal1 = infoById1.get().getReceipt().getEnergyUsageTotal(); - Long fee1 = infoById1.get().getFee(); - Long energyFee1 = infoById1.get().getReceipt().getEnergyFee(); - Long netUsed1 = infoById1.get().getReceipt().getNetUsage(); - Long energyUsed1 = infoById1.get().getReceipt().getEnergyUsage(); - Long netFee1 = infoById1.get().getReceipt().getNetFee(); - logger.info("energyUsageTotal1:" + energyUsageTotal1); - logger.info("fee1:" + fee1); - logger.info("energyFee1:" + energyFee1); - logger.info("netUsed1:" + netUsed1); - logger.info("energyUsed1:" + energyUsed1); - logger.info("netFee1:" + netFee1); - - Account infoafter1 = PublicMethed.queryAccount(linkage004Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter1 = PublicMethed.getAccountResource(linkage004Address, - blockingStubFull1); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyLimit1 = resourceInfoafter1.getEnergyLimit(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterFreeNetLimit1 = resourceInfoafter1.getFreeNetLimit(); - Long afterNetLimit1 = resourceInfoafter1.getNetLimit(); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - logger.info("afterBalance1:" + afterBalance1); - logger.info("afterEnergyLimit1:" + afterEnergyLimit1); - logger.info("afterEnergyUsed1:" + afterEnergyUsed1); - logger.info("afterFreeNetLimit1:" + afterFreeNetLimit1); - logger.info("afterNetLimit1:" + afterNetLimit1); - logger.info("afterNetUsed1:" + afterNetUsed1); - logger.info("afterFreeNetUsed1:" + afterFreeNetUsed1); - - Assert.assertTrue((beforeBalance1 - fee1) == afterBalance1); - Assert.assertTrue(infoById1.get().getResultValue() == 1); - Assert.assertTrue(energyUsageTotal1 > 0); - Assert.assertTrue(afterEnergyUsed1 == 0); - Assert.assertTrue(beforeNetUsed1 < afterNetUsed1); - - //When the fee limit is just ok.use energyFee,freezeBalanceGetNet,balance change. - maxFeeLimit = currentFee; - AccountResourceMessage resourceInfo2 = PublicMethed.getAccountResource(linkage004Address, - blockingStubFull); - Account info2 = PublicMethed.queryAccount(linkage004Address, blockingStubFull); - Long beforeBalance2 = info2.getBalance(); - Long beforeEnergyLimit2 = resourceInfo2.getEnergyLimit(); - Long beforeEnergyUsed2 = resourceInfo2.getEnergyUsed(); - Long beforeFreeNetLimit2 = resourceInfo2.getFreeNetLimit(); - Long beforeNetLimit2 = resourceInfo2.getNetLimit(); - Long beforeNetUsed2 = resourceInfo2.getNetUsed(); - Long beforeFreeNetUsed2 = resourceInfo2.getFreeNetUsed(); - logger.info("beforeBalance2:" + beforeBalance2); - logger.info("beforeEnergyLimit2:" + beforeEnergyLimit2); - logger.info("beforeEnergyUsed2:" + beforeEnergyUsed2); - logger.info("beforeFreeNetLimit2:" + beforeFreeNetLimit2); - logger.info("beforeNetLimit2:" + beforeNetLimit2); - logger.info("beforeNetUsed2:" + beforeNetUsed2); - logger.info("beforeFreeNetUsed2:" + beforeFreeNetUsed2); - txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, - "", maxFeeLimit, 0L, 50, null, linkage004Key, linkage004Address, blockingStubFull); - //logger.info("testFeeLimitIsTooSmall, the txid is " + txid); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById2 = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Long energyUsageTotal2 = infoById2.get().getReceipt().getEnergyUsageTotal(); - Long fee2 = infoById2.get().getFee(); - Long energyFee2 = infoById2.get().getReceipt().getEnergyFee(); - Long netUsed2 = infoById2.get().getReceipt().getNetUsage(); - Long energyUsed2 = infoById2.get().getReceipt().getEnergyUsage(); - Long netFee2 = infoById2.get().getReceipt().getNetFee(); - logger.info("energyUsageTotal2:" + energyUsageTotal2); - logger.info("fee2:" + fee2); - logger.info("energyFee2:" + energyFee2); - logger.info("netUsed2:" + netUsed2); - logger.info("energyUsed2:" + energyUsed2); - logger.info("netFee2:" + netFee2); - Account infoafter2 = PublicMethed.queryAccount(linkage004Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter2 = PublicMethed.getAccountResource(linkage004Address, - blockingStubFull1); - Long afterBalance2 = infoafter2.getBalance(); - Long afterEnergyLimit2 = resourceInfoafter2.getEnergyLimit(); - Long afterEnergyUsed2 = resourceInfoafter2.getEnergyUsed(); - Long afterFreeNetLimit2 = resourceInfoafter2.getFreeNetLimit(); - Long afterNetLimit2 = resourceInfoafter2.getNetLimit(); - Long afterNetUsed2 = resourceInfoafter2.getNetUsed(); - Long afterFreeNetUsed2 = resourceInfoafter2.getFreeNetUsed(); - logger.info("afterBalance2:" + afterBalance2); - logger.info("afterEnergyLimit2:" + afterEnergyLimit2); - logger.info("afterEnergyUsed2:" + afterEnergyUsed2); - logger.info("afterFreeNetLimit2:" + afterFreeNetLimit2); - logger.info("afterNetLimit2:" + afterNetLimit2); - logger.info("afterNetUsed2:" + afterNetUsed2); - logger.info("afterFreeNetUsed2:" + afterFreeNetUsed2); - - Assert.assertTrue(infoById2.get().getResultValue() == 0); - Assert.assertTrue(infoById2.get().getReceipt().getEnergyUsageTotal() > 0); - Assert.assertTrue((beforeBalance2 - fee2) == afterBalance2); - Assert.assertTrue((beforeNetUsed2 + netUsed2) >= afterNetUsed2); - - currentFee = fee2; - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage007.java b/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage007.java deleted file mode 100644 index 3b9867466db..00000000000 --- a/framework/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage007.java +++ /dev/null @@ -1,350 +0,0 @@ -package stest.tron.wallet.contract.linkage; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractLinkage007 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String contractName; - String code; - String abi; - byte[] contractAddress; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] linkage007Address = ecKey1.getAddress(); - String linkage007Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(linkage007Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - } - - @Test(enabled = true) - public void testRangeOfFeeLimit() { - - //Now the feelimit range is 0-1000000000,including 0 and 1000000000 - Assert.assertTrue(PublicMethed.sendcoin(linkage007Address, 2000000000L, fromAddress, - testKey002, blockingStubFull)); - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(linkage007Address, - blockingStubFull); - Account info; - info = PublicMethed.queryAccount(linkage007Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyLimit = resourceInfo.getEnergyLimit(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeFreeNetLimit = resourceInfo.getFreeNetLimit(); - Long beforeNetLimit = resourceInfo.getNetLimit(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyLimit:" + beforeEnergyLimit); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeFreeNetLimit:" + beforeFreeNetLimit); - logger.info("beforeNetLimit:" + beforeNetLimit); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - //When the feelimit is large, the deploy will be failed,No used everything. - - String filePath = "./src/test/resources/soliditycode/contractLinkage002.sol"; - String contractName = "divideIHaveArgsReturnStorage"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid; - txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, - "", maxFeeLimit + 1, 0L, 100, null, linkage007Key, - linkage007Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account infoafter = PublicMethed.queryAccount(linkage007Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(linkage007Address, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyLimit = resourceInfoafter.getEnergyLimit(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterFreeNetLimit = resourceInfoafter.getFreeNetLimit(); - Long afterNetLimit = resourceInfoafter.getNetLimit(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyLimit:" + afterEnergyLimit); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterFreeNetLimit:" + afterFreeNetLimit); - logger.info("afterNetLimit:" + afterNetLimit); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertEquals(beforeBalance, afterBalance); - Assert.assertTrue(afterEnergyUsed == 0); - Assert.assertTrue(afterNetUsed == 0); - Assert.assertTrue(afterFreeNetUsed == 0); - - Assert.assertTrue(txid == null); - AccountResourceMessage resourceInfo1 = PublicMethed.getAccountResource(linkage007Address, - blockingStubFull); - Account info1 = PublicMethed.queryAccount(linkage007Address, blockingStubFull); - Long beforeBalance1 = info1.getBalance(); - Long beforeEnergyLimit1 = resourceInfo1.getEnergyLimit(); - Long beforeEnergyUsed1 = resourceInfo1.getEnergyUsed(); - Long beforeFreeNetLimit1 = resourceInfo1.getFreeNetLimit(); - Long beforeNetLimit1 = resourceInfo1.getNetLimit(); - Long beforeNetUsed1 = resourceInfo1.getNetUsed(); - Long beforeFreeNetUsed1 = resourceInfo1.getFreeNetUsed(); - logger.info("beforeBalance1:" + beforeBalance1); - logger.info("beforeEnergyLimit1:" + beforeEnergyLimit1); - logger.info("beforeEnergyUsed1:" + beforeEnergyUsed1); - logger.info("beforeFreeNetLimit1:" + beforeFreeNetLimit1); - logger.info("beforeNetLimit1:" + beforeNetLimit1); - logger.info("beforeNetUsed1:" + beforeNetUsed1); - logger.info("beforeFreeNetUsed1:" + beforeFreeNetUsed1); - //When the feelimit is 0, the deploy will be failed.Only use FreeNet,balance not change. - txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, - "", 0L, 0L, 100, null, linkage007Key, - linkage007Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account infoafter1 = PublicMethed.queryAccount(linkage007Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter1 = PublicMethed.getAccountResource(linkage007Address, - blockingStubFull1); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyLimit1 = resourceInfoafter1.getEnergyLimit(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterFreeNetLimit1 = resourceInfoafter1.getFreeNetLimit(); - Long afterNetLimit1 = resourceInfoafter1.getNetLimit(); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - logger.info("afterBalance1:" + afterBalance1); - logger.info("afterEnergyLimit1:" + afterEnergyLimit1); - logger.info("afterEnergyUsed1:" + afterEnergyUsed1); - logger.info("afterFreeNetLimit1:" + afterFreeNetLimit1); - logger.info("afterNetLimit1:" + afterNetLimit1); - logger.info("afterNetUsed1:" + afterNetUsed1); - logger.info("afterFreeNetUsed1:" + afterFreeNetUsed1); - logger.info("---------------:"); - Assert.assertEquals(beforeBalance1, afterBalance1); - Assert.assertTrue(afterFreeNetUsed1 > 0); - Assert.assertTrue(afterNetUsed1 == 0); - Assert.assertTrue(afterEnergyUsed1 == 0); - Optional infoById; - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 1); - - //Deploy the contract.success.use FreeNet,EnergyFee.balcne change - AccountResourceMessage resourceInfo2 = PublicMethed.getAccountResource(linkage007Address, - blockingStubFull); - Account info2 = PublicMethed.queryAccount(linkage007Address, blockingStubFull); - Long beforeBalance2 = info2.getBalance(); - Long beforeEnergyLimit2 = resourceInfo2.getEnergyLimit(); - Long beforeEnergyUsed2 = resourceInfo2.getEnergyUsed(); - Long beforeFreeNetLimit2 = resourceInfo2.getFreeNetLimit(); - Long beforeNetLimit2 = resourceInfo2.getNetLimit(); - Long beforeNetUsed2 = resourceInfo2.getNetUsed(); - Long beforeFreeNetUsed2 = resourceInfo2.getFreeNetUsed(); - logger.info("beforeBalance2:" + beforeBalance2); - logger.info("beforeEnergyLimit2:" + beforeEnergyLimit2); - logger.info("beforeEnergyUsed2:" + beforeEnergyUsed2); - logger.info("beforeFreeNetLimit2:" + beforeFreeNetLimit2); - logger.info("beforeNetLimit2:" + beforeNetLimit2); - logger.info("beforeNetUsed2:" + beforeNetUsed2); - logger.info("beforeFreeNetUsed2:" + beforeFreeNetUsed2); - txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, - "", maxFeeLimit, 0L, 100, null, linkage007Key, - linkage007Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById2 = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Long energyUsageTotal2 = infoById2.get().getReceipt().getEnergyUsageTotal(); - Long fee2 = infoById2.get().getFee(); - Long energyFee2 = infoById2.get().getReceipt().getEnergyFee(); - Long netUsed2 = infoById2.get().getReceipt().getNetUsage(); - Long energyUsed2 = infoById2.get().getReceipt().getEnergyUsage(); - Long netFee2 = infoById2.get().getReceipt().getNetFee(); - logger.info("energyUsageTotal2:" + energyUsageTotal2); - logger.info("fee2:" + fee2); - logger.info("energyFee2:" + energyFee2); - logger.info("netUsed2:" + netUsed2); - logger.info("energyUsed2:" + energyUsed2); - logger.info("netFee2:" + netFee2); - Account infoafter2 = PublicMethed.queryAccount(linkage007Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter2 = PublicMethed.getAccountResource(linkage007Address, - blockingStubFull1); - Long afterBalance2 = infoafter2.getBalance(); - Long afterEnergyLimit2 = resourceInfoafter2.getEnergyLimit(); - Long afterEnergyUsed2 = resourceInfoafter2.getEnergyUsed(); - Long afterFreeNetLimit2 = resourceInfoafter2.getFreeNetLimit(); - Long afterNetLimit2 = resourceInfoafter2.getNetLimit(); - Long afterNetUsed2 = resourceInfoafter2.getNetUsed(); - Long afterFreeNetUsed2 = resourceInfoafter2.getFreeNetUsed(); - logger.info("afterBalance2:" + afterBalance2); - logger.info("afterEnergyLimit2:" + afterEnergyLimit2); - logger.info("afterEnergyUsed2:" + afterEnergyUsed2); - logger.info("afterFreeNetLimit2:" + afterFreeNetLimit2); - logger.info("afterNetLimit2:" + afterNetLimit2); - logger.info("afterNetUsed2:" + afterNetUsed2); - logger.info("afterFreeNetUsed2:" + afterFreeNetUsed2); - logger.info("---------------:"); - Assert.assertTrue((beforeBalance2 - fee2) == afterBalance2); - Assert.assertTrue(afterEnergyUsed2 == 0); - Assert.assertTrue(afterFreeNetUsed2 > beforeFreeNetUsed2); - Assert.assertTrue(infoById2.get().getResultValue() == 0); - contractAddress = infoById2.get().getContractAddress().toByteArray(); - - //When the feelimit is large, the trigger will be failed.Only use FreeNetUsed,Balance not change - AccountResourceMessage resourceInfo3 = PublicMethed.getAccountResource(linkage007Address, - blockingStubFull); - Account info3 = PublicMethed.queryAccount(linkage007Address, blockingStubFull); - Long beforeBalance3 = info3.getBalance(); - Long beforeEnergyLimit3 = resourceInfo3.getEnergyLimit(); - Long beforeEnergyUsed3 = resourceInfo3.getEnergyUsed(); - Long beforeFreeNetLimit3 = resourceInfo3.getFreeNetLimit(); - Long beforeNetLimit3 = resourceInfo3.getNetLimit(); - Long beforeNetUsed3 = resourceInfo3.getNetUsed(); - Long beforeFreeNetUsed3 = resourceInfo3.getFreeNetUsed(); - logger.info("beforeBalance3:" + beforeBalance3); - logger.info("beforeEnergyLimit3:" + beforeEnergyLimit3); - logger.info("beforeEnergyUsed3:" + beforeEnergyUsed3); - logger.info("beforeFreeNetLimit3:" + beforeFreeNetLimit3); - logger.info("beforeNetLimit3:" + beforeNetLimit3); - logger.info("beforeNetUsed3:" + beforeNetUsed3); - logger.info("beforeFreeNetUsed3:" + beforeFreeNetUsed3); - //String initParmes = "\"" + Base58.encode58Check(fromAddress) + "\",\"63\""; - String num = "4" + "," + "2"; - txid = PublicMethed.triggerContract(contractAddress, - "divideIHaveArgsReturn(int256,int256)", num, false, - 1000, maxFeeLimit + 1, linkage007Address, linkage007Key, blockingStubFull); - Account infoafter3 = PublicMethed.queryAccount(linkage007Address, blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - AccountResourceMessage resourceInfoafter3 = PublicMethed.getAccountResource(linkage007Address, - blockingStubFull1); - Long afterBalance3 = infoafter3.getBalance(); - Long afterEnergyLimit3 = resourceInfoafter3.getEnergyLimit(); - Long afterEnergyUsed3 = resourceInfoafter3.getEnergyUsed(); - Long afterFreeNetLimit3 = resourceInfoafter3.getFreeNetLimit(); - Long afterNetLimit3 = resourceInfoafter3.getNetLimit(); - Long afterNetUsed3 = resourceInfoafter3.getNetUsed(); - Long afterFreeNetUsed3 = resourceInfoafter3.getFreeNetUsed(); - logger.info("afterBalance3:" + afterBalance3); - logger.info("afterEnergyLimit3:" + afterEnergyLimit3); - logger.info("afterEnergyUsed3:" + afterEnergyUsed3); - logger.info("afterFreeNetLimit3:" + afterFreeNetLimit3); - logger.info("afterNetLimit3:" + afterNetLimit3); - logger.info("afterNetUsed3:" + afterNetUsed3); - logger.info("afterFreeNetUsed3:" + afterFreeNetUsed3); - logger.info("---------------:"); - Assert.assertTrue(txid == null); - Assert.assertEquals(beforeBalance3, afterBalance3); - Assert.assertTrue(afterFreeNetUsed3 > beforeNetUsed3); - Assert.assertTrue(afterNetUsed3 == 0); - Assert.assertTrue(afterEnergyUsed3 == 0); - //When the feelimit is 0, the trigger will be failed.Only use FreeNetUsed,Balance not change - AccountResourceMessage resourceInfo4 = PublicMethed.getAccountResource(linkage007Address, - blockingStubFull); - Account info4 = PublicMethed.queryAccount(linkage007Address, blockingStubFull); - Long beforeBalance4 = info4.getBalance(); - Long beforeEnergyLimit4 = resourceInfo4.getEnergyLimit(); - Long beforeEnergyUsed4 = resourceInfo4.getEnergyUsed(); - Long beforeFreeNetLimit4 = resourceInfo4.getFreeNetLimit(); - Long beforeNetLimit4 = resourceInfo4.getNetLimit(); - Long beforeNetUsed4 = resourceInfo4.getNetUsed(); - Long beforeFreeNetUsed4 = resourceInfo4.getFreeNetUsed(); - logger.info("beforeBalance4:" + beforeBalance4); - logger.info("beforeEnergyLimit4:" + beforeEnergyLimit4); - logger.info("beforeEnergyUsed4:" + beforeEnergyUsed4); - logger.info("beforeFreeNetLimit4:" + beforeFreeNetLimit4); - logger.info("beforeNetLimit4:" + beforeNetLimit4); - logger.info("beforeNetUsed4:" + beforeNetUsed4); - logger.info("beforeFreeNetUsed4:" + beforeFreeNetUsed4); - txid = PublicMethed.triggerContract(contractAddress, - "divideIHaveArgsReturn(int256,int256)", num, false, - 1000, maxFeeLimit + 1, linkage007Address, linkage007Key, blockingStubFull); - Account infoafter4 = PublicMethed.queryAccount(linkage007Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter4 = PublicMethed.getAccountResource(linkage007Address, - blockingStubFull1); - Long afterBalance4 = infoafter4.getBalance(); - Long afterEnergyLimit4 = resourceInfoafter4.getEnergyLimit(); - Long afterEnergyUsed4 = resourceInfoafter4.getEnergyUsed(); - Long afterFreeNetLimit4 = resourceInfoafter4.getFreeNetLimit(); - Long afterNetLimit4 = resourceInfoafter4.getNetLimit(); - Long afterNetUsed4 = resourceInfoafter4.getNetUsed(); - Long afterFreeNetUsed4 = resourceInfoafter4.getFreeNetUsed(); - logger.info("afterBalance4:" + afterBalance4); - logger.info("afterEnergyLimit4:" + afterEnergyLimit4); - logger.info("afterEnergyUsed4:" + afterEnergyUsed4); - logger.info("afterFreeNetLimit4:" + afterFreeNetLimit4); - logger.info("afterNetLimit4:" + afterNetLimit4); - logger.info("afterNetUsed4:" + afterNetUsed4); - logger.info("afterFreeNetUsed4:" + afterFreeNetUsed4); - logger.info("---------------:"); - Assert.assertEquals(beforeBalance4, afterBalance4); - Assert.assertTrue(afterFreeNetUsed4 > beforeNetUsed4); - Assert.assertTrue(afterNetUsed4 == 0); - Assert.assertTrue(afterEnergyUsed4 == 0); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(Integer.toString(infoById.get().getResultValue())); - Assert.assertTrue(infoById.get().getFee() == 0); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario001.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario001.java deleted file mode 100644 index 4f2945ad443..00000000000 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario001.java +++ /dev/null @@ -1,129 +0,0 @@ -package stest.tron.wallet.contract.scenario; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractScenario001 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contract001Address = ecKey1.getAddress(); - String contract001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - @Test(enabled = true) - public void deployAddressDemo() { - ecKey1 = new ECKey(Utils.getRandom()); - contract001Address = ecKey1.getAddress(); - contract001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.printAddress(contract001Key); - - Assert.assertTrue(PublicMethed.sendcoin(contract001Address, 20000000L, toAddress, - testKey003, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(contract001Address, 15000000L, - 3, 1, contract001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - AccountResourceMessage accountResource = PublicMethed.getAccountResource(contract001Address, - blockingStubFull); - Long energyLimit = accountResource.getEnergyLimit(); - Long energyUsage = accountResource.getEnergyUsed(); - Long balanceBefore = PublicMethed.queryAccount(contract001Key, blockingStubFull).getBalance(); - - logger.info("before energy limit is " + Long.toString(energyLimit)); - logger.info("before energy usage is " + Long.toString(energyUsage)); - logger.info("before balance is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/contractScenario001.sol"; - String contractName = "divideIHaveArgsReturnStorage"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contract001Key, contract001Address, blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi() != null); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - accountResource = PublicMethed.getAccountResource(contract001Address, blockingStubFull1); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - Long balanceAfter = PublicMethed.queryAccount(contract001Key, blockingStubFull1).getBalance(); - - logger.info("after energy limit is " + Long.toString(energyLimit)); - logger.info("after energy usage is " + Long.toString(energyUsage)); - logger.info("after balance is " + Long.toString(balanceAfter)); - - Assert.assertTrue(energyLimit > 0); - Assert.assertTrue(energyUsage > 0); - Assert.assertEquals(balanceBefore, balanceAfter); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario003.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario003.java deleted file mode 100644 index 9a04c761c9b..00000000000 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario003.java +++ /dev/null @@ -1,135 +0,0 @@ -package stest.tron.wallet.contract.scenario; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractScenario003 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contract003Address = ecKey1.getAddress(); - String contract003Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contract003Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - logger.info(Long.toString(PublicMethed.queryAccount(contract003Key, blockingStubFull) - .getBalance())); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - @Test(enabled = true) - public void deployErc223() { - ecKey1 = new ECKey(Utils.getRandom()); - contract003Address = ecKey1.getAddress(); - contract003Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - Assert.assertTrue(PublicMethed.sendcoin(contract003Address, 500000000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - AccountResourceMessage accountResource = PublicMethed.getAccountResource(contract003Address, - blockingStubFull); - Long energyLimit = accountResource.getEnergyLimit(); - Long energyUsage = accountResource.getEnergyUsed(); - Long balanceBefore = PublicMethed.queryAccount(contract003Key, blockingStubFull).getBalance(); - - logger.info("before energy limit is " + Long.toString(energyLimit)); - logger.info("before energy usage is " + Long.toString(energyUsage)); - logger.info("before balance is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/contractScenario003.sol"; - String contractName = "divideIHaveArgsReturnStorage"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 100, null, contract003Key, contract003Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - logger.info(txid); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - com.google.protobuf.ByteString contractAddress = infoById.get().getContractAddress(); - SmartContract smartContract = PublicMethed - .getContract(contractAddress.toByteArray(), blockingStubFull); - Assert.assertTrue(smartContract.getAbi() != null); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - - PublicMethed.waitProduceNextBlock(blockingStubFull1); - accountResource = PublicMethed.getAccountResource(contract003Address, blockingStubFull1); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - Long balanceAfter = PublicMethed.queryAccount(contract003Address, blockingStubFull1) - .getBalance(); - - logger.info("after energy limit is " + Long.toString(energyLimit)); - logger.info("after energy usage is " + Long.toString(energyUsage)); - logger.info("after balance is " + Long.toString(balanceAfter)); - logger.info("transaction fee is " + Long.toString(infoById.get().getFee())); - - Assert.assertTrue(energyLimit == 0); - Assert.assertTrue(energyUsage == 0); - Assert.assertTrue(balanceBefore == balanceAfter + infoById.get().getFee()); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario004.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario004.java deleted file mode 100644 index ac3286b339e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario004.java +++ /dev/null @@ -1,131 +0,0 @@ -package stest.tron.wallet.contract.scenario; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractScenario004 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contract004Address = ecKey1.getAddress(); - String contract004Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contract004Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void deployErc20TronTokenWithoutData() { - Assert.assertTrue(PublicMethed.sendcoin(contract004Address, 200000000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(contract004Address, 100000000L, - 3, 1, contract004Key, blockingStubFull)); - AccountResourceMessage accountResource = PublicMethed.getAccountResource(contract004Address, - blockingStubFull); - Long energyLimit = accountResource.getEnergyLimit(); - Long energyUsage = accountResource.getEnergyUsed(); - - logger.info("before energy limit is " + Long.toString(energyLimit)); - logger.info("before energy usage is " + Long.toString(energyUsage)); - - String filePath = "./src/test/resources/soliditycode//contractScenario004.sol"; - String contractName = "TronToken"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contract004Key, contract004Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - System.out.println(info); - Assert.assertTrue(info.get().getResultValue() == 1); - } - - @Test(enabled = true) - public void deployErc20TronTokenWithData() { - Assert.assertTrue(PublicMethed - .sendcoin(contract004Address, 200000000L, fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(contract004Address, 100000000L, - 3, 1, contract004Key, blockingStubFull)); - AccountResourceMessage accountResource = PublicMethed.getAccountResource(contract004Address, - blockingStubFull); - Long energyLimit = accountResource.getEnergyLimit(); - Long energyUsage = accountResource.getEnergyUsed(); - - logger.info("before energy limit is " + Long.toString(energyLimit)); - logger.info("before energy usage is " + Long.toString(energyUsage)); - - String filePath = "./src/test/resources/soliditycode//contractScenario004.sol"; - String contractName = "TronToken"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String constructorStr = "constructor(address)"; - String data = "\"" + Base58.encode58Check(contract004Address) + "\""; - String txid = PublicMethed - .deployContractWithConstantParame(contractName, abi, code, constructorStr, data, "", - maxFeeLimit, 0L, 100, null, contract004Key, contract004Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - System.out.println(info); - Assert.assertTrue(info.get().getResultValue() == 0); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario005.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario005.java deleted file mode 100644 index 6787c22ca83..00000000000 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario005.java +++ /dev/null @@ -1,110 +0,0 @@ -package stest.tron.wallet.contract.scenario; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractScenario005 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contract005Address = ecKey1.getAddress(); - String contract005Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contract005Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = false) - public void deployIcoContract() { - Assert.assertTrue(PublicMethed.sendcoin(contract005Address, 200000000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(contract005Address, 10000000L, - 3, 1, contract005Key, blockingStubFull)); - AccountResourceMessage accountResource = PublicMethed.getAccountResource(contract005Address, - blockingStubFull); - Long energyLimit = accountResource.getEnergyLimit(); - Long energyUsage = accountResource.getEnergyUsed(); - - logger.info("before energy limit is " + Long.toString(energyLimit)); - logger.info("before energy usage is " + Long.toString(energyUsage)); - - String filePath = "./src/test/resources/soliditycode/contractScenario005.sol"; - String contractName = "Crowdsale"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contract005Key, contract005Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("Txid is " + txid); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - Assert.assertEquals(1, infoById.get().getResultValue()); - accountResource = PublicMethed.getAccountResource(contract005Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - Assert.assertTrue(energyLimit > 0); - Assert.assertTrue(energyUsage > 0); - logger.info("after energy limit is " + Long.toString(energyLimit)); - logger.info("after energy usage is " + Long.toString(energyUsage)); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario006.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario006.java deleted file mode 100644 index 6938c5c875d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario006.java +++ /dev/null @@ -1,123 +0,0 @@ -package stest.tron.wallet.contract.scenario; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractScenario006 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contract006Address = ecKey1.getAddress(); - String contract006Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void deployFomo3D() { - ecKey1 = new ECKey(Utils.getRandom()); - contract006Address = ecKey1.getAddress(); - contract006Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.printAddress(contract006Key); - - PublicMethed.sendcoin(contract006Address, 2000000000L, toAddress, - testKey003, blockingStubFull); - logger.info(Long.toString(PublicMethed.queryAccount(contract006Key, blockingStubFull) - .getBalance())); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(contract006Address, 100000000L, - 3, 1, contract006Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - AccountResourceMessage accountResource = PublicMethed.getAccountResource(contract006Address, - blockingStubFull); - Long energyLimit = accountResource.getEnergyLimit(); - Long energyUsage = accountResource.getEnergyUsed(); - - logger.info("before energy limit is " + Long.toString(energyLimit)); - logger.info("before energy usage is " + Long.toString(energyUsage)); - - String filePath = "./src/test/resources/soliditycode/contractScenario006.sol"; - String contractName = "FoMo3Dlong"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - byte[] contractAddress; - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contract006Key, contract006Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - contractAddress = infoById.get().getContractAddress().toByteArray(); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - accountResource = PublicMethed.getAccountResource(contract006Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - Assert.assertTrue(energyLimit > 0); - Assert.assertTrue(energyUsage > 0); - logger.info("after energy limit is " + Long.toString(energyLimit)); - logger.info("after energy usage is " + Long.toString(energyUsage)); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario007.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario007.java deleted file mode 100644 index 630bcbffeba..00000000000 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario007.java +++ /dev/null @@ -1,111 +0,0 @@ -package stest.tron.wallet.contract.scenario; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractScenario007 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contract007Address = ecKey1.getAddress(); - String contract007Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contract007Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void deployErc721CardMigration() { - ecKey1 = new ECKey(Utils.getRandom()); - contract007Address = ecKey1.getAddress(); - contract007Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed.sendcoin(contract007Address, 20000000000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(contract007Address, 100000000L, - 3, 1, contract007Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - AccountResourceMessage accountResource = PublicMethed.getAccountResource(contract007Address, - blockingStubFull); - Long energyLimit = accountResource.getEnergyLimit(); - Long energyUsage = accountResource.getEnergyUsed(); - Account account = PublicMethed.queryAccount(contract007Key, blockingStubFull); - logger.info("before balance is " + Long.toString(account.getBalance())); - logger.info("before energy limit is " + Long.toString(energyLimit)); - logger.info("before energy usage is " + Long.toString(energyUsage)); - String contractName = "ERC721Token"; - - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractScenario007_deployErc721CardMigration"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractScenario007_deployErc721CardMigration"); - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contract007Key, contract007Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - accountResource = PublicMethed.getAccountResource(contract007Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - account = PublicMethed.queryAccount(contract007Key, blockingStubFull); - logger.info("after balance is " + Long.toString(account.getBalance())); - logger.info("after energy limit is " + Long.toString(energyLimit)); - logger.info("after energy usage is " + Long.toString(energyUsage)); - Assert.assertTrue(energyLimit > 0); - Assert.assertTrue(energyUsage > 0); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario008.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario008.java deleted file mode 100644 index 4575d7545bb..00000000000 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario008.java +++ /dev/null @@ -1,114 +0,0 @@ -package stest.tron.wallet.contract.scenario; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractScenario008 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contract008Address = ecKey1.getAddress(); - String contract008Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void deployErc721CryptoKitties() { - ecKey1 = new ECKey(Utils.getRandom()); - contract008Address = ecKey1.getAddress(); - contract008Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.printAddress(contract008Key); - Assert.assertTrue(PublicMethed.sendcoin(contract008Address, 5000000000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(contract008Address, 1000000L, - 3, 1, contract008Key, blockingStubFull)); - AccountResourceMessage accountResource = PublicMethed.getAccountResource(contract008Address, - blockingStubFull); - Long energyLimit = accountResource.getEnergyLimit(); - Long energyUsage = accountResource.getEnergyUsed(); - Account account = PublicMethed.queryAccount(contract008Key, blockingStubFull); - logger.info("before balance is " + Long.toString(account.getBalance())); - logger.info("before energy limit is " + Long.toString(energyLimit)); - logger.info("before energy usage is " + Long.toString(energyUsage)); - Long shortFeeLimit = 900L; - - String filePath = "./src/test/resources/soliditycode/contractScenario008.sol"; - String contractName = "KittyCore"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", shortFeeLimit, - 0L, 100, null, contract008Key, contract008Address, blockingStubFull); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contract008Key, contract008Address, blockingStubFull); - - final SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - accountResource = PublicMethed.getAccountResource(contract008Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - account = PublicMethed.queryAccount(contract008Key, blockingStubFull); - logger.info("after balance is " + Long.toString(account.getBalance())); - logger.info("after energy limit is " + Long.toString(energyLimit)); - logger.info("after energy usage is " + Long.toString(energyUsage)); - Assert.assertTrue(energyLimit > 0); - Assert.assertTrue(energyUsage > 0); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario009.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario009.java deleted file mode 100644 index 170a64c1ecd..00000000000 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario009.java +++ /dev/null @@ -1,126 +0,0 @@ -package stest.tron.wallet.contract.scenario; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractScenario009 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contract009Address = ecKey1.getAddress(); - String contract009Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String compilerVersion = Configuration.getByPath("testng.conf") - .getString("defaultParameter.solidityCompilerVersion"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contract009Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void deployContainLibraryContract() { - Assert.assertTrue(PublicMethed.sendcoin(contract009Address, 20000000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(contract009Address, 1000000L, - 3, 1, contract009Key, blockingStubFull)); - AccountResourceMessage accountResource = PublicMethed.getAccountResource(contract009Address, - blockingStubFull); - Long energyLimit = accountResource.getEnergyLimit(); - Long energyUsage = accountResource.getEnergyUsed(); - - logger.info("before energy limit is " + Long.toString(energyLimit)); - logger.info("before energy usage is " + Long.toString(energyUsage)); - String filePath = "./src/test/resources/soliditycode/contractScenario009.sol"; - String contractName = "Set"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - byte[] libraryContractAddress; - libraryContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contract009Key, contract009Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - contractName = "C"; - retMap = PublicMethed.getBycodeAbiForLibrary(filePath, contractName); - code = retMap.get("byteCode").toString(); - abi = retMap.get("abI").toString(); - String library = retMap.get("library").toString(); - - //String libraryAddress = - // "browser/TvmTest_p1_Grammar_002.sol:Set:" + Base58.encode58Check(libraryContractAddress); - String libraryAddress; - libraryAddress = library - + Base58.encode58Check(libraryContractAddress); - - byte[] contractAddress = PublicMethed - .deployContractForLibrary(contractName, abi, code, "", maxFeeLimit, 0L, 100, libraryAddress, - contract009Key, contract009Address, compilerVersion, blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - logger.info(ByteArray.toHexString(smartContract.getContractAddress().toByteArray())); - accountResource = PublicMethed.getAccountResource(contract009Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - Assert.assertTrue(energyLimit > 0); - Assert.assertTrue(energyUsage > 0); - - logger.info("after energy limit is " + Long.toString(energyLimit)); - logger.info("after energy usage is " + Long.toString(energyUsage)); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario010.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario010.java deleted file mode 100644 index 3eeeaeb5cc5..00000000000 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario010.java +++ /dev/null @@ -1,114 +0,0 @@ -package stest.tron.wallet.contract.scenario; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractScenario010 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contract009Address = ecKey1.getAddress(); - String contract009Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contract009Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void deployContainLibraryContract() { - ecKey1 = new ECKey(Utils.getRandom()); - contract009Address = ecKey1.getAddress(); - contract009Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed.sendcoin(contract009Address, 600000000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(contract009Address, 10000000L, - 3, 1, contract009Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - AccountResourceMessage accountResource = PublicMethed.getAccountResource(contract009Address, - blockingStubFull); - Long energyLimit = accountResource.getEnergyLimit(); - Long energyUsage = accountResource.getEnergyUsed(); - Long netUsage = accountResource.getNetUsed(); - - logger.info("before energy limit is " + Long.toString(energyLimit)); - logger.info("before energy usage is " + Long.toString(energyUsage)); - logger.info("before Net usage is " + Long.toString(netUsage)); - String filePath = "./src/test/resources/soliditycode/contractScenario010.sol"; - String contractName = "TRON_ERC721"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - byte[] libraryAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contract009Key, contract009Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(libraryAddress, blockingStubFull); - - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - logger.info(ByteArray.toHexString(smartContract.getContractAddress().toByteArray())); - accountResource = PublicMethed.getAccountResource(contract009Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - netUsage = accountResource.getNetUsed(); - Assert.assertTrue(energyLimit > 0); - Assert.assertTrue(energyUsage > 0); - - logger.info("after energy limit is " + Long.toString(energyLimit)); - logger.info("after energy usage is " + Long.toString(energyUsage)); - logger.info("after Net usage is " + Long.toString(netUsage)); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario012.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario012.java deleted file mode 100644 index 50c45589b33..00000000000 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario012.java +++ /dev/null @@ -1,198 +0,0 @@ -package stest.tron.wallet.contract.scenario; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractScenario012 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - byte[] contractAddress = null; - String txid = ""; - Optional infoById = null; - String receiveAddressParam; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contract012Address = ecKey1.getAddress(); - String contract012Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] receiverAddress = ecKey2.getAddress(); - String receiverKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contract012Key); - PublicMethed.printAddress(receiverKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void test1DeployTransactionCoin() { - ecKey1 = new ECKey(Utils.getRandom()); - contract012Address = ecKey1.getAddress(); - contract012Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - Assert.assertTrue(PublicMethed.sendcoin(contract012Address, 2000000000L, fromAddress, - testKey002, blockingStubFull)); - AccountResourceMessage accountResource = PublicMethed.getAccountResource(contract012Address, - blockingStubFull); - Long energyLimit = accountResource.getEnergyLimit(); - Long energyUsage = accountResource.getEnergyUsed(); - - logger.info("before energy limit is " + Long.toString(energyLimit)); - logger.info("before energy usage is " + Long.toString(energyUsage)); - String filePath = "./src/test/resources/soliditycode/contractScenario012.sol"; - String contractName = "PayTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100, - null, contract012Key, contract012Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - Assert.assertTrue(infoById.get().getResultValue() == 0); - logger.info("energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi() != null); - } - - - @Test(enabled = true) - public void test2TriggerTransactionCoin() { - Account account = PublicMethed.queryAccount(contractAddress, blockingStubFull); - logger.info("contract Balance : -- " + account.getBalance()); - receiveAddressParam = "\"" + Base58.encode58Check(fromAddress) - + "\""; - //When the contract has no money,transaction coin failed. - txid = PublicMethed.triggerContract(contractAddress, - "sendToAddress2(address)", receiveAddressParam, false, - 0, 100000000L, contract012Address, contract012Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info(txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - Assert.assertTrue(infoById.get().getResultValue() == 1); - logger.info("energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 0); - Assert.assertTrue(infoById.get().getFee() == infoById.get().getReceipt().getEnergyFee()); - Assert.assertFalse(infoById.get().getContractAddress().isEmpty()); - } - - - @Test(enabled = true) - public void test3TriggerTransactionCanNotCreateAccount() { - ecKey2 = new ECKey(Utils.getRandom()); - receiverAddress = ecKey2.getAddress(); - receiverKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - //Send some trx to the contract account. - Account account = PublicMethed.queryAccount(contractAddress, blockingStubFull); - logger.info("contract Balance : -- " + account.getBalance()); - receiveAddressParam = "\"" + Base58.encode58Check(receiverAddress) - + "\""; - //In smart contract, you can create account - txid = PublicMethed.triggerContract(contractAddress, - "sendToAddress2(address)", receiveAddressParam, false, - 1000000000L, 100000000L, contract012Address, contract012Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info(txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - logger.info("result is " + infoById.get().getResultValue()); - logger.info("energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 0); - Assert.assertTrue(infoById.get().getFee() == infoById.get().getReceipt().getEnergyFee()); - Assert.assertFalse(infoById.get().getContractAddress().isEmpty()); - - Account account2 = PublicMethed.queryAccount(receiverAddress, blockingStubFull); - Assert.assertEquals(5L, account2.getBalance()); - - } - - - @Test(enabled = true) - public void test4TriggerTransactionCoin() { - receiveAddressParam = "\"" + Base58.encode58Check(receiverAddress) - + "\""; - Account account = PublicMethed.queryAccount(contractAddress, blockingStubFull); - logger.info("contract Balance : -- " + account.getBalance()); - //This time, trigger the methed sendToAddress2 is OK. - Assert.assertTrue(PublicMethed.sendcoin(receiverAddress, 10000000L, toAddress, - testKey003, blockingStubFull)); - txid = PublicMethed.triggerContract(contractAddress, - "sendToAddress2(address)", receiveAddressParam, false, - 0, 100000000L, contract012Address, contract012Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info(txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - logger.info("result is " + infoById.get().getResultValue()); - logger.info("energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 0); - Assert.assertTrue(infoById.get().getFee() == infoById.get().getReceipt().getEnergyFee()); - Assert.assertFalse(infoById.get().getContractAddress().isEmpty()); - - } - - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario013.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario013.java deleted file mode 100644 index 11025ede0ce..00000000000 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario013.java +++ /dev/null @@ -1,142 +0,0 @@ -package stest.tron.wallet.contract.scenario; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractScenario013 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - byte[] contractAddress = null; - String txid = ""; - Optional infoById = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contract013Address = ecKey1.getAddress(); - String contract013Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contract013Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void deployTronTrxAndSunContract() { - Assert.assertTrue(PublicMethed.sendcoin(contract013Address, 20000000000L, fromAddress, - testKey002, blockingStubFull)); - AccountResourceMessage accountResource = PublicMethed.getAccountResource(contract013Address, - blockingStubFull); - Long energyLimit = accountResource.getEnergyLimit(); - Long energyUsage = accountResource.getEnergyUsed(); - - logger.info("before energy limit is " + Long.toString(energyLimit)); - logger.info("before energy usage is " + Long.toString(energyUsage)); - - String filePath = "./src/test/resources/soliditycode/contractScenario013.sol"; - String contractName = "timetest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 100, null, contract013Key, contract013Address, blockingStubFull); - logger.info(txid); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 0); - Assert.assertFalse(infoById.get().getContractAddress().isEmpty()); - } - - @Test(enabled = true) - public void triggerTronTrxAndSunContract() { - AccountResourceMessage accountResource = PublicMethed.getAccountResource(contract013Address, - blockingStubFull); - Long energyLimit = accountResource.getEnergyLimit(); - Long energyUsage = accountResource.getEnergyUsed(); - - logger.info("before energy limit is " + Long.toString(energyLimit)); - logger.info("before energy usage is " + Long.toString(energyUsage)); - - String filePath = "./src/test/resources/soliditycode/contractScenario013.sol"; - String contractName = "timetest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contract013Key, contract013Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - logger.info("energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - - txid = PublicMethed.triggerContract(contractAddress, - "time()", "#", false, - 0, 100000000L, contract013Address, contract013Key, blockingStubFull); - logger.info(txid); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("result is " + infoById.get().getResultValue()); - logger.info("energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 0); - Assert.assertTrue(infoById.get().getFee() == infoById.get().getReceipt().getEnergyFee()); - Assert.assertFalse(infoById.get().getContractAddress().isEmpty()); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario014.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario014.java deleted file mode 100644 index 4dcb217815d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario014.java +++ /dev/null @@ -1,158 +0,0 @@ -package stest.tron.wallet.contract.scenario; - -import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS_VALUE; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractScenario014 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Clear a contract with ABI created by itself") - public void testClearAbi() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/ClearAbi001.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String txid = PublicMethed - .clearContractAbi(contractAddress, contractExcAddress, contractExcKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("", - ByteArray.toHexString(infoById.get().getResMessage().toByteArray())); - - Optional byId = PublicMethed.getTransactionById(txid, blockingStubFull); - Assert.assertEquals(byId.get().getRet(0).getContractRet().getNumber(), - SUCCESS_VALUE); - Assert.assertEquals(byId.get().getRet(0).getContractRetValue(), SUCCESS_VALUE); - Assert.assertEquals(byId.get().getRet(0).getContractRet(), contractResult.SUCCESS); - - smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario015.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario015.java deleted file mode 100644 index 345ea9dc67f..00000000000 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario015.java +++ /dev/null @@ -1,142 +0,0 @@ -package stest.tron.wallet.contract.scenario; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractScenario015 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "TriggerConstantContract a constant function ") - public void testTriggerConstantContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/ClearAbi001.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "testPayable()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - logger.info("message:" + transaction.getRet(0).getRet()); - logger.info(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - logger.info("Result:" + Hex.toHexString(result)); - logger.info("getCode" + transactionExtention.getResult().getCode().getNumber()); - Assert.assertEquals("SUCESS", transaction.getRet(0).getRet().toString()); - Assert.assertEquals(1, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result)))); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario016.java b/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario016.java deleted file mode 100644 index 3ee8e164328..00000000000 --- a/framework/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario016.java +++ /dev/null @@ -1,193 +0,0 @@ -package stest.tron.wallet.contract.scenario; - -import static org.tron.protos.Protocol.Transaction.Result.contractResult.BAD_JUMP_DESTINATION_VALUE; -import static org.tron.protos.Protocol.Transaction.Result.contractResult.REVERT_VALUE; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractScenario016 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] grammarAddress = ecKey1.getAddress(); - String testKeyForGrammarAddress = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String compilerVersion = Configuration.getByPath("testng.conf") - .getString("defaultParameter.solidityCompilerVersion"); - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKeyForGrammarAddress); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - @Test(enabled = true, description = "ContractResult is BAD_JUMP_DESTINATION") - public void test1Grammar001() { - Assert.assertTrue(PublicMethed - .sendcoin(grammarAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "Test"; - - String code = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600" - + "080fd5b5061011f8061003a6000396000f30060806040526004361060485763ffffffff7c01000000000000" - + "000000000000000000000000000000000000000000006000350416634ef5a0088114604d5780639093b95b1" - + "4608c575b600080fd5b348015605857600080fd5b50d38015606457600080fd5b50d28015607057600080fd" - + "5b50607a60043560b8565b60408051918252519081900360200190f35b348015609757600080fd5b50d3801" - + "560a357600080fd5b50d2801560af57600080fd5b5060b660ee565b005b6000606082604051908082528060" - + "20026020018201604052801560e5578160200160208202803883390190505b50905050919050565b6001805" - + "600a165627a7a7230582092ba162087e13f41c6d6c00ba493edc5a5a6250a3840ece5f99aa38b66366a7000" - + "29"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\"" - + ":\"testOutOfMem\",\"outputs\":[{\"name\":\"r\",\"type\":\"bytes32\"}],\"payable\":false" - + ",\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs" - + "\":[],\"name\":\"testBadJumpDestination\",\"outputs\":[],\"payable\":false,\"stateMutab" - + "ility\":\"nonpayable\",\"type\":\"function\"}]"; - - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, - "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress, grammarAddress, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - org.testng.Assert.assertTrue(smartContract.getAbi().toString() != null); - String txid = null; - Optional infoById = null; - txid = PublicMethed.triggerContract(contractAddress, - "testBadJumpDestination()", "#", false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("Txid is " + txid); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Optional byId = PublicMethed.getTransactionById(txid, blockingStubFull); - logger.info("getRet:" + byId.get().getRet(0)); - logger.info("getNumber:" + byId.get().getRet(0).getContractRet().getNumber()); - logger.info("getContractRetValue:" + byId.get().getRet(0).getContractRetValue()); - logger.info("getContractRet:" + byId.get().getRet(0).getContractRet()); - logger.info("ById:" + byId); - - logger.info("infoById:" + infoById); - - Assert.assertEquals(byId.get().getRet(0).getContractRetValue(), BAD_JUMP_DESTINATION_VALUE); - Assert.assertEquals(byId.get().getRet(0).getContractRet(), contractResult.BAD_JUMP_DESTINATION); - - Assert - .assertEquals(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()), ""); - Assert - .assertEquals(contractResult.BAD_JUMP_DESTINATION, infoById.get().getReceipt().getResult()); - - Assert.assertEquals(byId.get().getRet(0).getRet().getNumber(), 0); - Assert.assertEquals(byId.get().getRet(0).getRetValue(), 0); - - - } - - - @Test(enabled = true, description = "ContractResult is OUT_OF_ENERGY") - public void test2Grammar002() { - - String filePath = "src/test/resources/soliditycode/contractUnknownException.sol"; - String contractName = "testC"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 20L, 100, null, testKeyForGrammarAddress, - grammarAddress, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("Txid is " + txid); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Optional byId = PublicMethed.getTransactionById(txid, blockingStubFull); - logger.info("getRet:" + byId.get().getRet(0)); - logger.info("getNumber:" + byId.get().getRet(0).getContractRet().getNumber()); - logger.info("getContractRetValue:" + byId.get().getRet(0).getContractRetValue()); - logger.info("getContractRet:" + byId.get().getRet(0).getContractRet()); - logger.info("ById:" + byId); - - logger.info("infoById:" + infoById); - - Assert.assertEquals(byId.get().getRet(0).getContractRetValue(), REVERT_VALUE); - Assert.assertEquals(byId.get().getRet(0).getContractRet(), contractResult.REVERT); - - Assert - .assertEquals(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()), - "4e487b710000000000000000000000000000000000000000000000000000000000000001"); - Assert - .assertEquals(contractResult.REVERT, infoById.get().getReceipt().getResult()); - - Assert.assertEquals(byId.get().getRet(0).getRet().getNumber(), 0); - Assert.assertEquals(byId.get().getRet(0).getRetValue(), 0); - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/account/GetAccountBalance001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/account/GetAccountBalance001.java deleted file mode 100644 index 01cb4d3c738..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/account/GetAccountBalance001.java +++ /dev/null @@ -1,129 +0,0 @@ -package stest.tron.wallet.dailybuild.account; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.contract.BalanceContract.BlockBalanceTrace; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j - -public class GetAccountBalance001 { - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress = ecKey1.getAddress(); - final String testKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Integer sendAmount = 1234; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - Long beforeFromBalance; - Long beforeToBalance; - Long afterFromBalance; - Long afterToBalance; - private final String blackHoleAdd = Configuration.getByPath("testng.conf") - .getString("defaultParameter.blackHoleAddress"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Test get account balance") - public void test01GetAccountBalance() { - Protocol.Block currentBlock = blockingStubFull - .getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - - beforeFromBalance = PublicMethed.getAccountBalance(currentBlock,fromAddress,blockingStubFull); - beforeToBalance = PublicMethed.getAccountBalance(currentBlock,testAddress,blockingStubFull); - - - } - - @Test(enabled = true, description = "Test get block balance") - public void test02GetBlockBalance() { - String txid = PublicMethed.sendcoinGetTransactionId(testAddress, sendAmount, fromAddress, - testKey002, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Long blockNum = infoById.get().getBlockNumber(); - - Protocol.Block currentBlock = PublicMethed.getBlock(blockNum,blockingStubFull); - - BlockBalanceTrace blockBalanceTrace - = PublicMethed.getBlockBalance(currentBlock,blockingStubFull); - - - Assert.assertEquals(ByteString.copyFrom(fromAddress),blockBalanceTrace - .getTransactionBalanceTrace(0).getOperation(0).getAddress()); - Assert.assertEquals(-100000L,blockBalanceTrace.getTransactionBalanceTrace(0) - .getOperation(0).getAmount()); - - - Assert.assertEquals(ByteString.copyFrom(fromAddress),blockBalanceTrace - .getTransactionBalanceTrace(0).getOperation(1).getAddress()); - Assert.assertEquals(-sendAmount,blockBalanceTrace.getTransactionBalanceTrace(0) - .getOperation(1).getAmount()); - - - - Assert.assertEquals(ByteString.copyFrom(testAddress),blockBalanceTrace - .getTransactionBalanceTrace(0).getOperation(2).getAddress()); - Assert.assertEquals(-sendAmount,-blockBalanceTrace.getTransactionBalanceTrace(0) - .getOperation(2).getAmount()); - - - afterFromBalance = PublicMethed.getAccountBalance(currentBlock,fromAddress,blockingStubFull); - afterToBalance = PublicMethed.getAccountBalance(currentBlock,testAddress,blockingStubFull); - - Assert.assertTrue(afterToBalance - beforeToBalance == sendAmount); - Assert.assertTrue(beforeFromBalance - afterFromBalance >= sendAmount + 100000L); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(testAddress, testKey, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/account/TransactionFee001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/account/TransactionFee001.java deleted file mode 100644 index 89894e8666c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/account/TransactionFee001.java +++ /dev/null @@ -1,662 +0,0 @@ -package stest.tron.wallet.dailybuild.account; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Commons; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; -import stest.tron.wallet.common.client.utils.Retry; -import stest.tron.wallet.common.client.utils.Sha256Hash; - - - -@Slf4j - -public class TransactionFee001 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private final String witnessKey01 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress01 = PublicMethed.getFinalAddress(witnessKey01); - private final String witnessKey02 = Configuration.getByPath("testng.conf") - .getString("witness.key2"); - private final byte[] witnessAddress02 = PublicMethed.getFinalAddress(witnessKey02); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private final String blackHoleAdd = Configuration.getByPath("testng.conf") - .getString("defaultParameter.blackHoleAddress"); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private ManagedChannel channelSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPbft = null; - private ManagedChannel channelPbft = null; - - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] deployAddress = ecKey1.getAddress(); - final String deployKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String soliInPbft = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(2); - - Long startNum = 0L; - Long endNum = 0L; - Long witness01Allowance1 = 0L; - Long witness02Allowance1 = 0L; - Long blackHoleBalance1 = 0L; - Long witness01Allowance2 = 0L; - Long witness02Allowance2 = 0L; - Long blackHoleBalance2 = 0L; - Long witness01Increase = 0L; - Long witness02Increase = 0L; - Long beforeBurnTrxAmount = 0L; - Long afterBurnTrxAmount = 0L; - String txid = null; - - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext() - .build(); - blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); - } - - @Test(enabled = true, description = "Test deploy contract with energy fee to sr") - public void test01DeployContractEnergyFeeToSr() { - Assert.assertTrue(PublicMethed.sendcoin(deployAddress, 20000000000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode//contractLinkage003.sol"; - String contractName = "divideIHaveArgsReturnStorage"; - HashMap retMap = null; - String code = null; - String abi = null; - retMap = PublicMethed.getBycodeAbi(filePath, contractName); - code = retMap.get("byteCode").toString(); - abi = retMap.get("abI").toString(); - - startNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - witness01Allowance1 = PublicMethed.queryAccount(witnessAddress01, blockingStubFull) - .getAllowance(); - witness02Allowance1 = PublicMethed.queryAccount(witnessAddress02, blockingStubFull) - .getAllowance(); - blackHoleBalance1 = PublicMethed.queryAccount(Commons.decode58Check(blackHoleAdd), - blockingStubFull).getBalance(); - beforeBurnTrxAmount = blockingStubFull - .getBurnTrx(EmptyMessage.newBuilder().build()).getNum(); - - txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, - "", maxFeeLimit, 0L, 0, null, - deployKey, deployAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - endNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - witness01Allowance2 = PublicMethed.queryAccount(witnessAddress01, blockingStubFull) - .getAllowance(); - witness02Allowance2 = PublicMethed.queryAccount(witnessAddress02, blockingStubFull) - .getAllowance(); - blackHoleBalance2 = PublicMethed.queryAccount(Commons.decode58Check(blackHoleAdd), - blockingStubFull).getBalance(); - witness02Increase = witness02Allowance2 - witness02Allowance1; - witness01Increase = witness01Allowance2 - witness01Allowance1; - //blackHoleIncrease = blackHoleBalance2 - blackHoleBalance1; - logger.info("----startNum:" + startNum + " endNum:" + endNum); - logger.info("====== witness02Allowance1 :" + witness02Allowance1 + " witness02Allowance2 :" - + witness02Allowance2 + "increase :" + witness02Increase); - logger.info("====== witness01Allowance1 :" + witness01Allowance1 + " witness01Allowance2 :" - + witness01Allowance2 + " increase :" + witness01Increase); - - Map witnessAllowance = PublicMethed.getAllowance2(startNum, endNum, - blockingStubFull); - - Assert.assertTrue((Math.abs(witnessAllowance.get(ByteArray.toHexString(witnessAddress01)) - - witness01Increase)) <= 2); - Assert.assertTrue((Math.abs(witnessAllowance.get(ByteArray.toHexString(witnessAddress02)) - - witness02Increase)) <= 2); - Assert.assertEquals(blackHoleBalance1, blackHoleBalance2); - Optional infoById = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(infoById.get().getFee(),infoById.get().getPackingFee()); - afterBurnTrxAmount = blockingStubFull - .getBurnTrx(EmptyMessage.newBuilder().build()).getNum(); - Assert.assertEquals(beforeBurnTrxAmount,afterBurnTrxAmount); - } - - @Test(enabled = true, retryAnalyzer = Retry.class, - description = "Test update account permission fee to black hole," - + "trans with multi sign and fee to sr") - public void test02UpdateAccountPermissionAndMultiSiginTrans() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey1.getAddress(); - final String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - byte[] tmpAddr02 = tmpEcKey02.getAddress(); - final String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2 + multiSignFee; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(witnessKey01); - activePermissionKeys.add(tmpKey02); - - logger.info("** update owner and active permission to two address"); - startNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - witness01Allowance1 = - PublicMethed.queryAccount(witnessAddress01, blockingStubFull).getAllowance(); - witness02Allowance1 = - PublicMethed.queryAccount(witnessAddress02, blockingStubFull).getAllowance(); - blackHoleBalance1 = PublicMethed.queryAccount(Commons.decode58Check(blackHoleAdd), - blockingStubFull).getBalance(); - beforeBurnTrxAmount = blockingStubFull - .getBurnTrx(EmptyMessage.newBuilder().build()).getNum(); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner1\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"" - + ",\"threshold\":2," - + "\"operations\"" - + ":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey01) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" - + "]}]}"; - - txid = PublicMethedForMutiSign.accountPermissionUpdateForTransactionId(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()])); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(infoById.get().getPackingFee(),0); - Assert.assertEquals(infoById.get().getFee(),100000000L); - - endNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - witness01Allowance2 = - PublicMethed.queryAccount(witnessAddress01, blockingStubFull).getAllowance(); - witness02Allowance2 = - PublicMethed.queryAccount(witnessAddress02, blockingStubFull).getAllowance(); - blackHoleBalance2 = PublicMethed.queryAccount(Commons.decode58Check(blackHoleAdd), - blockingStubFull).getBalance(); - witness02Increase = witness02Allowance2 - witness02Allowance1; - witness01Increase = witness01Allowance2 - witness01Allowance1; - //blackHoleIncrease = blackHoleBalance2 - blackHoleBalance1; - logger.info("----startNum:" + startNum + " endNum:" + endNum); - logger.info("====== witness02Allowance1 :" + witness02Allowance1 + " witness02Allowance2 :" - + witness02Allowance2 + "increase :" + witness02Increase); - logger.info("====== witness01Allowance1 :" + witness01Allowance1 + " witness01Allowance2 :" - + witness01Allowance2 + " increase :" + witness01Increase); - - Map witnessAllowance = - PublicMethed.getAllowance2(startNum, endNum, blockingStubFull); - - Assert.assertTrue((Math.abs(witnessAllowance.get(ByteArray.toHexString(witnessAddress01)) - - witness01Increase)) <= 2); - Assert.assertTrue((Math.abs(witnessAllowance.get(ByteArray.toHexString(witnessAddress02)) - - witness02Increase)) <= 2); - Assert.assertEquals(blackHoleBalance2, blackHoleBalance1); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - logger.info(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - - startNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - witness01Allowance1 = - PublicMethed.queryAccount(witnessAddress01, blockingStubFull).getAllowance(); - witness02Allowance1 = - PublicMethed.queryAccount(witnessAddress02, blockingStubFull).getAllowance(); - blackHoleBalance1 = PublicMethed.queryAccount(Commons.decode58Check(blackHoleAdd), - blockingStubFull).getBalance(); - - afterBurnTrxAmount = blockingStubFull - .getBurnTrx(EmptyMessage.newBuilder().build()).getNum(); - Assert.assertTrue(afterBurnTrxAmount - beforeBurnTrxAmount == 100000000L); - - - beforeBurnTrxAmount = blockingStubFull - .getBurnTrx(EmptyMessage.newBuilder().build()).getNum(); - - Protocol.Transaction transaction = PublicMethedForMutiSign - .sendcoin2(fromAddress, 1000_000, ownerAddress, ownerKey, blockingStubFull); - txid = ByteArray.toHexString(Sha256Hash - .hash(CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray())); - logger.info("-----transaction: " + txid); - - Protocol.Transaction transaction1 = PublicMethedForMutiSign.addTransactionSignWithPermissionId( - transaction, tmpKey02, 2, blockingStubFull); - txid = ByteArray.toHexString(Sha256Hash - .hash(CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction1.getRawData().toByteArray())); - logger.info("-----transaction1: " + txid); - - Protocol.Transaction transaction2 = PublicMethedForMutiSign.addTransactionSignWithPermissionId( - transaction1, witnessKey01, 2, blockingStubFull); - - logger.info("transaction hex string is " + ByteArray.toHexString(transaction2.toByteArray())); - - GrpcAPI.TransactionSignWeight txWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("TransactionSignWeight info : " + txWeight); - - Assert.assertTrue(PublicMethedForMutiSign.broadcastTransaction(transaction2, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - endNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - witness01Allowance2 = - PublicMethed.queryAccount(witnessAddress01, blockingStubFull).getAllowance(); - witness02Allowance2 = - PublicMethed.queryAccount(witnessAddress02, blockingStubFull).getAllowance(); - blackHoleBalance2 = PublicMethed.queryAccount(Commons.decode58Check(blackHoleAdd), - blockingStubFull).getBalance(); - witness02Increase = witness02Allowance2 - witness02Allowance1; - witness01Increase = witness01Allowance2 - witness01Allowance1; - logger.info("----startNum:" + startNum + " endNum:" + endNum); - logger.info("====== witness02Allowance1 :" + witness02Allowance1 + " witness02Allowance2 :" - + witness02Allowance2 + "increase :" + witness02Increase); - logger.info("====== witness01Allowance1 :" + witness01Allowance1 + " witness01Allowance2 :" - + witness01Allowance2 + " increase :" + witness01Increase); - - witnessAllowance = PublicMethed.getAllowance2(startNum, endNum, blockingStubFull); - - Assert.assertTrue((Math.abs(witnessAllowance.get(ByteArray.toHexString(witnessAddress01)) - - witness01Increase)) <= 2); - Assert.assertTrue((Math.abs(witnessAllowance.get(ByteArray.toHexString(witnessAddress02)) - - witness02Increase)) <= 2); - Assert.assertEquals(blackHoleBalance2, blackHoleBalance1); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(infoById.get().getPackingFee(),0); - Assert.assertEquals(infoById.get().getFee(),1000000L); - afterBurnTrxAmount = blockingStubFull - .getBurnTrx(EmptyMessage.newBuilder().build()).getNum(); - Assert.assertTrue(afterBurnTrxAmount - beforeBurnTrxAmount == 1000000L); - } - - @Test(enabled = true, description = "Test trigger result is \"OUT_OF_TIME\"" - + " with energy fee to sr") - public void test03OutOfTimeEnergyFeeToBlackHole() { - Random rand = new Random(); - Integer randNum = rand.nextInt(4000); - - Assert.assertTrue(PublicMethed.sendcoin(deployAddress, maxFeeLimit * 10, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName = "StorageAndCpu" + Integer.toString(randNum); - String code = Configuration.getByPath("testng.conf") - .getString("code.code_TestStorageAndCpu_storageAndCpu"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_TestStorageAndCpu_storageAndCpu"); - byte[] contractAddress = null; - contractAddress = PublicMethed.deployContract(contractName, abi, code, - "", maxFeeLimit, - 0L, 100, null, deployKey, deployAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - startNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - witness01Allowance1 = - PublicMethed.queryAccount(witnessAddress01, blockingStubFull).getAllowance(); - witness02Allowance1 = - PublicMethed.queryAccount(witnessAddress02, blockingStubFull).getAllowance(); - blackHoleBalance1 = PublicMethed.queryAccount(Commons.decode58Check(blackHoleAdd), - blockingStubFull).getBalance(); - beforeBurnTrxAmount = blockingStubFull - .getBurnTrx(EmptyMessage.newBuilder().build()).getNum(); - txid = PublicMethed.triggerContract(contractAddress, - "testUseCpu(uint256)", "90100", false, - 0, maxFeeLimit, deployAddress, deployKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - endNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - witness01Allowance2 = - PublicMethed.queryAccount(witnessAddress01, blockingStubFull).getAllowance(); - witness02Allowance2 = - PublicMethed.queryAccount(witnessAddress02, blockingStubFull).getAllowance(); - blackHoleBalance2 = PublicMethed.queryAccount(Commons.decode58Check(blackHoleAdd), - blockingStubFull).getBalance(); - witness02Increase = witness02Allowance2 - witness02Allowance1; - witness01Increase = witness01Allowance2 - witness01Allowance1; - - logger.info("----startNum:" + startNum + " endNum:" + endNum); - logger.info("====== witness02Allowance1 :" + witness02Allowance1 + " witness02Allowance2 :" - + witness02Allowance2 + "increase :" + witness02Increase); - logger.info("====== witness01Allowance1 :" + witness01Allowance1 + " witness01Allowance2 :" - + witness01Allowance2 + " increase :" + witness01Increase); - Optional infoById = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - logger.info("InfoById:" + infoById); - - Map witnessAllowance = - PublicMethed.getAllowance2(startNum, endNum, blockingStubFull); - Assert.assertTrue((Math.abs(witnessAllowance.get(ByteArray.toHexString(witnessAddress01)) - - witness01Increase)) <= 2); - Assert.assertTrue((Math.abs(witnessAllowance.get(ByteArray.toHexString(witnessAddress02)) - - witness02Increase)) <= 2); - Assert.assertEquals(blackHoleBalance2, blackHoleBalance1); - Long packingFee = infoById.get().getPackingFee(); - logger.info("receipt:" + infoById.get().getReceipt()); - Assert.assertTrue(packingFee == 0L); - Assert.assertTrue(infoById.get().getFee() >= maxFeeLimit); - afterBurnTrxAmount = blockingStubFull - .getBurnTrx(EmptyMessage.newBuilder().build()).getNum(); - Assert.assertTrue(afterBurnTrxAmount - beforeBurnTrxAmount == maxFeeLimit); - } - - @Test(enabled = true, description = "Test create account with netFee to sr") - public void test04AccountCreate() { - startNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - witness01Allowance1 = - PublicMethed.queryAccount(witnessAddress01, blockingStubFull).getAllowance(); - witness02Allowance1 = - PublicMethed.queryAccount(witnessAddress02, blockingStubFull).getAllowance(); - blackHoleBalance1 = PublicMethed.queryAccount(Commons.decode58Check(blackHoleAdd), - blockingStubFull).getBalance(); - beforeBurnTrxAmount = blockingStubFull - .getBurnTrx(EmptyMessage.newBuilder().build()).getNum(); - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] lowBalAddress = ecKey.getAddress(); - txid = PublicMethed.createAccountGetTxid(fromAddress, lowBalAddress, - testKey002, blockingStubFull); - - - PublicMethed.waitProduceNextBlock(blockingStubFull); - endNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - witness01Allowance2 = - PublicMethed.queryAccount(witnessAddress01, blockingStubFull).getAllowance(); - witness02Allowance2 = - PublicMethed.queryAccount(witnessAddress02, blockingStubFull).getAllowance(); - blackHoleBalance2 = PublicMethed.queryAccount(Commons.decode58Check(blackHoleAdd), - blockingStubFull).getBalance(); - - witness02Increase = witness02Allowance2 - witness02Allowance1; - witness01Increase = witness01Allowance2 - witness01Allowance1; - logger.info("----startNum:" + startNum + " endNum:" + endNum); - logger.info("====== witness01Allowance1 :" + witness01Allowance1 + " witness01Allowance2 :" - + witness01Allowance2 + " increase :" + witness01Increase); - logger.info("====== witness02Allowance1 :" + witness02Allowance1 + " witness02Allowance2 :" - + witness02Allowance2 + " increase :" + witness02Increase); - - Map witnessAllowance = - PublicMethed.getAllowance2(startNum, endNum, blockingStubFull); - Assert.assertTrue((Math.abs(witnessAllowance.get(ByteArray.toHexString(witnessAddress01)) - - witness01Increase)) <= 2); - Assert.assertTrue((Math.abs(witnessAllowance.get(ByteArray.toHexString(witnessAddress02)) - - witness02Increase)) <= 2); - Assert.assertEquals(blackHoleBalance1,blackHoleBalance2); - Optional infoById = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getPackingFee() == 0L); - Assert.assertTrue(infoById.get().getFee() == 100000L); - afterBurnTrxAmount = blockingStubFull - .getBurnTrx(EmptyMessage.newBuilder().build()).getNum(); - Assert.assertTrue(afterBurnTrxAmount - beforeBurnTrxAmount == 100000L); - } - - @Test(enabled = true, description = "Test trigger contract with netFee and energyFee to sr") - public void test05NetFeeAndEnergyFee2Sr() { - Random rand = new Random(); - Integer randNum = rand.nextInt(30) + 1; - randNum = rand.nextInt(4000); - - Assert.assertTrue(PublicMethed.sendcoin(deployAddress, maxFeeLimit * 10, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName = "StorageAndCpu" + Integer.toString(randNum); - String code = Configuration.getByPath("testng.conf") - .getString("code.code_TestStorageAndCpu_storageAndCpu"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_TestStorageAndCpu_storageAndCpu"); - byte[] contractAddress = null; - contractAddress = PublicMethed.deployContract(contractName, abi, code, - "", maxFeeLimit, - 0L, 100, null, deployKey, deployAddress, blockingStubFull); - for (int i = 0; i < 15; i++) { - txid = PublicMethed.triggerContract(contractAddress, - "testUseCpu(uint256)", "700", false, - 0, maxFeeLimit, deployAddress, deployKey, blockingStubFull); - } - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - startNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - witness01Allowance1 = - PublicMethed.queryAccount(witnessAddress01, blockingStubFull).getAllowance(); - witness02Allowance1 = - PublicMethed.queryAccount(witnessAddress02, blockingStubFull).getAllowance(); - blackHoleBalance1 = PublicMethed.queryAccount(Commons.decode58Check(blackHoleAdd), - blockingStubFull).getBalance(); - beforeBurnTrxAmount = blockingStubFull - .getBurnTrx(EmptyMessage.newBuilder().build()).getNum(); - txid = PublicMethed.triggerContract(contractAddress, - "testUseCpu(uint256)", "700", false, - 0, maxFeeLimit, deployAddress, deployKey, blockingStubFull); - // PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - endNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - witness01Allowance2 = - PublicMethed.queryAccount(witnessAddress01, blockingStubFull).getAllowance(); - witness02Allowance2 = - PublicMethed.queryAccount(witnessAddress02, blockingStubFull).getAllowance(); - blackHoleBalance2 = PublicMethed.queryAccount(Commons.decode58Check(blackHoleAdd), - blockingStubFull).getBalance(); - witness02Increase = witness02Allowance2 - witness02Allowance1; - witness01Increase = witness01Allowance2 - witness01Allowance1; - - logger.info("----startNum:" + startNum + " endNum:" + endNum); - logger.info("====== witness02Allowance1 :" + witness02Allowance1 + " witness02Allowance2 :" - + witness02Allowance2 + "increase :" + witness02Increase); - logger.info("====== witness01Allowance1 :" + witness01Allowance1 + " witness01Allowance2 :" - + witness01Allowance2 + " increase :" + witness01Increase); - Optional infoById = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("InfoById:" + infoById); - Map witnessAllowance = - PublicMethed.getAllowance2(startNum, endNum, blockingStubFull); - Assert.assertTrue((Math.abs(witnessAllowance.get(ByteArray.toHexString(witnessAddress01)) - - witness01Increase)) <= 2); - Assert.assertTrue((Math.abs(witnessAllowance.get(ByteArray.toHexString(witnessAddress02)) - - witness02Increase)) <= 2); - Assert.assertEquals(blackHoleBalance1,blackHoleBalance2); - afterBurnTrxAmount = blockingStubFull - .getBurnTrx(EmptyMessage.newBuilder().build()).getNum(); - Assert.assertEquals(beforeBurnTrxAmount,afterBurnTrxAmount); - } - - /** - * constructor. - */ - - @Test(enabled = true, description = "Test create trc10 token with fee not to sr") - public void test06CreateAssetIssue() { - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] tokenAccountAddress = ecKey1.getAddress(); - final String tokenAccountKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - PublicMethed.printAddress(tokenAccountKey); - - Assert.assertTrue(PublicMethed - .sendcoin(tokenAccountAddress, 1028000000L, fromAddress, testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - startNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - witness01Allowance1 = - PublicMethed.queryAccount(witnessAddress01, blockingStubFull).getAllowance(); - witness02Allowance1 = - PublicMethed.queryAccount(witnessAddress02, blockingStubFull).getAllowance(); - blackHoleBalance1 = PublicMethed.queryAccount(Commons.decode58Check(blackHoleAdd), - blockingStubFull).getBalance(); - beforeBurnTrxAmount = blockingStubFull - .getBurnTrx(EmptyMessage.newBuilder().build()).getNum(); - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - long now = System.currentTimeMillis(); - long totalSupply = now; - String description = "for case assetissue016"; - String url = "https://stest.assetissue016.url/"; - String name = "AssetIssue016_" + Long.toString(now); - txid = PublicMethed.createAssetIssueGetTxid(tokenAccountAddress, name, name,totalSupply, - 1, 1, start, end, 1, description, url, 0L, - 0L, 1L, 1L, tokenAccountKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - endNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - witness01Allowance2 = - PublicMethed.queryAccount(witnessAddress01, blockingStubFull).getAllowance(); - witness02Allowance2 = - PublicMethed.queryAccount(witnessAddress02, blockingStubFull).getAllowance(); - blackHoleBalance2 = PublicMethed.queryAccount(Commons.decode58Check(blackHoleAdd), - blockingStubFull).getBalance(); - - witness02Increase = witness02Allowance2 - witness02Allowance1; - witness01Increase = witness01Allowance2 - witness01Allowance1; - logger.info("----startNum:" + startNum + " endNum:" + endNum); - logger.info("====== witness01Allowance1 :" + witness01Allowance1 + " witness01Allowance2 :" - + witness01Allowance2 + " increase :" + witness01Increase); - logger.info("====== witness02Allowance1 :" + witness02Allowance1 + " witness02Allowance2 :" - + witness02Allowance2 + " increase :" + witness02Increase); - - Map witnessAllowance = - PublicMethed.getAllowance2(startNum, endNum, blockingStubFull); - Assert.assertTrue((Math.abs(witnessAllowance.get(ByteArray.toHexString(witnessAddress01)) - - witness01Increase)) <= 2); - Assert.assertTrue((Math.abs(witnessAllowance.get(ByteArray.toHexString(witnessAddress02)) - - witness02Increase)) <= 2); - Assert.assertEquals(blackHoleBalance1,blackHoleBalance2); - Optional infoById = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getPackingFee() == 0L); - Assert.assertTrue(infoById.get().getFee() == 1024000000L); - afterBurnTrxAmount = blockingStubFull - .getBurnTrx(EmptyMessage.newBuilder().build()).getNum(); - Assert.assertTrue(afterBurnTrxAmount - beforeBurnTrxAmount == 1024000000L); - - - } - - /** - * constructor. - */ - - @Test(enabled = true, description = "Test getburntrx api from solidity or pbft") - public void test07GetBurnTrxFromSolidityOrPbft() { - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull,blockingStubSolidity); - Assert.assertEquals(blockingStubFull - .getBurnTrx(EmptyMessage.newBuilder().build()),blockingStubSolidity.getBurnTrx( - EmptyMessage.newBuilder().build())); - Assert.assertEquals(blockingStubFull.getBurnTrx(EmptyMessage.newBuilder().build()), - blockingStubPbft.getBurnTrx( - EmptyMessage.newBuilder().build())); - } - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.unFreezeBalance(deployAddress, deployKey, 1, deployAddress, - blockingStubFull); - PublicMethed.freedResource(deployAddress, deployKey, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/account/WalletTestAccount012.java b/framework/src/test/java/stest/tron/wallet/dailybuild/account/WalletTestAccount012.java deleted file mode 100644 index 3dd38dbd80a..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/account/WalletTestAccount012.java +++ /dev/null @@ -1,204 +0,0 @@ -package stest.tron.wallet.dailybuild.account; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAccount012 { - private static final long sendAmount = 10000000000L; - private static final long frozenAmountForTronPower = 3456789L; - private static final long frozenAmountForNet = 7000000L; - private final String foundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] foundationAddress = PublicMethed.getFinalAddress(foundationKey); - - private final String witnessKey = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress = PublicMethed.getFinalAddress(witnessKey); - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] frozenAddress = ecKey1.getAddress(); - String frozenKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(frozenKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - @Test(enabled = true, description = "Freeze balance to get tron power") - public void test01FreezeBalanceGetTronPower() { - - - final Long beforeFrozenTime = System.currentTimeMillis(); - Assert.assertTrue(PublicMethed.sendcoin(frozenAddress, sendAmount, - foundationAddress, foundationKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - - AccountResourceMessage accountResource = PublicMethed - .getAccountResource(frozenAddress, blockingStubFull); - final Long beforeTotalTronPowerWeight = accountResource.getTotalTronPowerWeight(); - final Long beforeTronPowerLimit = accountResource.getTronPowerLimit(); - - - Assert.assertTrue(PublicMethed.freezeBalanceGetTronPower(frozenAddress,frozenAmountForTronPower, - 0,2,null,frozenKey,blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceGetTronPower(frozenAddress,frozenAmountForNet, - 0,0,null,frozenKey,blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long afterFrozenTime = System.currentTimeMillis(); - Account account = PublicMethed.queryAccount(frozenAddress,blockingStubFull); - Assert.assertEquals(account.getTronPower().getFrozenBalance(),frozenAmountForTronPower); - Assert.assertTrue(account.getTronPower().getExpireTime() > beforeFrozenTime - && account.getTronPower().getExpireTime() < afterFrozenTime); - - accountResource = PublicMethed - .getAccountResource(frozenAddress, blockingStubFull); - Long afterTotalTronPowerWeight = accountResource.getTotalTronPowerWeight(); - Long afterTronPowerLimit = accountResource.getTronPowerLimit(); - Long afterTronPowerUsed = accountResource.getTronPowerUsed(); - Assert.assertEquals(afterTotalTronPowerWeight - beforeTotalTronPowerWeight, - frozenAmountForTronPower / 1000000L); - - Assert.assertEquals(afterTronPowerLimit - beforeTronPowerLimit, - frozenAmountForTronPower / 1000000L); - - - - Assert.assertTrue(PublicMethed.freezeBalanceGetTronPower(frozenAddress, - 6000000 - frozenAmountForTronPower, - 0,2,null,frozenKey,blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - accountResource = PublicMethed - .getAccountResource(frozenAddress, blockingStubFull); - afterTronPowerLimit = accountResource.getTronPowerLimit(); - - Assert.assertEquals(afterTronPowerLimit - beforeTronPowerLimit, - 6); - - - } - - - @Test(enabled = true,description = "Vote witness by tron power") - public void test02VotePowerOnlyComeFromTronPower() { - AccountResourceMessage accountResource = PublicMethed - .getAccountResource(frozenAddress, blockingStubFull); - final Long beforeTronPowerUsed = accountResource.getTronPowerUsed(); - - - HashMap witnessMap = new HashMap<>(); - witnessMap.put(witnessAddress,frozenAmountForNet / 1000000L); - Assert.assertFalse(PublicMethed.voteWitness(frozenAddress,frozenKey,witnessMap, - blockingStubFull)); - witnessMap.put(witnessAddress,frozenAmountForTronPower / 1000000L); - Assert.assertTrue(PublicMethed.voteWitness(frozenAddress,frozenKey,witnessMap, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed - .getAccountResource(frozenAddress, blockingStubFull); - Long afterTronPowerUsed = accountResource.getTronPowerUsed(); - Assert.assertEquals(afterTronPowerUsed - beforeTronPowerUsed, - frozenAmountForTronPower / 1000000L); - - final Long secondBeforeTronPowerUsed = afterTronPowerUsed; - witnessMap.put(witnessAddress,(frozenAmountForTronPower / 1000000L) - 1); - Assert.assertTrue(PublicMethed.voteWitness(frozenAddress,frozenKey,witnessMap, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - accountResource = PublicMethed - .getAccountResource(frozenAddress, blockingStubFull); - afterTronPowerUsed = accountResource.getTronPowerUsed(); - Assert.assertEquals(secondBeforeTronPowerUsed - afterTronPowerUsed, - 1); - - - } - - @Test(enabled = true,description = "Tron power is not allow to others") - public void test03TronPowerIsNotAllowToOthers() { - Assert.assertFalse(PublicMethed.freezeBalanceGetTronPower(frozenAddress, - frozenAmountForTronPower, 0,2, - ByteString.copyFrom(foundationAddress),frozenKey,blockingStubFull)); - } - - - @Test(enabled = true,description = "Unfreeze balance for tron power") - public void test04UnfreezeBalanceForTronPower() { - AccountResourceMessage accountResource = PublicMethed - .getAccountResource(foundationAddress, blockingStubFull); - final Long beforeTotalTronPowerWeight = accountResource.getTotalTronPowerWeight(); - - - Assert.assertTrue(PublicMethed.unFreezeBalance(frozenAddress,frozenKey,2, - null,blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed - .getAccountResource(frozenAddress, blockingStubFull); - Long afterTotalTronPowerWeight = accountResource.getTotalTronPowerWeight(); - Assert.assertEquals(beforeTotalTronPowerWeight - afterTotalTronPowerWeight, - 6); - - Assert.assertEquals(accountResource.getTronPowerLimit(),0L); - Assert.assertEquals(accountResource.getTronPowerUsed(),0L); - - Account account = PublicMethed.queryAccount(frozenAddress,blockingStubFull); - Assert.assertEquals(account.getTronPower().getFrozenBalance(),0); - - - } - - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - PublicMethed.unFreezeBalance(frozenAddress, frozenKey, 2, null, - blockingStubFull); - PublicMethed.unFreezeBalance(frozenAddress, frozenKey, 0, null, - blockingStubFull); - PublicMethed.freedResource(frozenAddress, frozenKey, foundationAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletExchange001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletExchange001.java deleted file mode 100644 index 233c8a64947..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletExchange001.java +++ /dev/null @@ -1,394 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.ExchangeList; -import org.tron.api.GrpcAPI.PaginatedMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Exchange; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletExchange001 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = 1000000001L; - private static String name1 = "exchange001_1_" + Long.toString(now); - private static String name2 = "exchange001_2_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - String description = "just-test"; - String url = "https://github.com/tronprotocol/wallet-cli/"; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] exchange001Address = ecKey1.getAddress(); - String exchange001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] secondExchange001Address = ecKey2.getAddress(); - String secondExchange001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - Long secondTransferAssetToFirstAccountNum = 100000000L; - Account firstAccount; - ByteString assetAccountId1; - ByteString assetAccountId2; - Optional listExchange; - Optional exchangeIdInfo; - Integer exchangeId = 0; - Integer exchangeRate = 10; - Long firstTokenInitialBalance = 10000L; - Long secondTokenInitialBalance = firstTokenInitialBalance * exchangeRate; - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private ManagedChannel channelPbft = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPbft = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - private String soliInPbft = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(2); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext() - .build(); - blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); - } - - @Test(enabled = true,description = "Create two asset issue to create exchange") - public void test1CreateUsedAsset() { - ecKey1 = new ECKey(Utils.getRandom()); - exchange001Address = ecKey1.getAddress(); - exchange001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - secondExchange001Address = ecKey2.getAddress(); - secondExchange001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - PublicMethed.printAddress(exchange001Key); - PublicMethed.printAddress(secondExchange001Key); - - Assert.assertTrue(PublicMethed.sendcoin(exchange001Address, 10240000000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(secondExchange001Address, 10240000000L, toAddress, - testKey003, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long start = System.currentTimeMillis() + 5000L; - Long end = System.currentTimeMillis() + 5000000L; - Assert.assertTrue(PublicMethed.createAssetIssue(exchange001Address, name1, totalSupply, 1, - 1, start, end, 1, description, url, 10000L, 10000L, - 1L, 1L, exchange001Key, blockingStubFull)); - Assert.assertTrue(PublicMethed.createAssetIssue(secondExchange001Address, name2, totalSupply, 1, - 1, start, end, 1, description, url, 10000L, 10000L, - 1L, 1L, secondExchange001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true,description = "Test create exchange") - public void test2CreateExchange() { - listExchange = PublicMethed.getExchangeList(blockingStubFull); - final Integer beforeCreateExchangeNum = listExchange.get().getExchangesCount(); - exchangeId = listExchange.get().getExchangesCount(); - - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - assetAccountId1 = getAssetIdFromThisAccount.getAssetIssuedID(); - - getAssetIdFromThisAccount = PublicMethed - .queryAccount(secondExchange001Address, blockingStubFull); - assetAccountId2 = getAssetIdFromThisAccount.getAssetIssuedID(); - - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long token1BeforeBalance = 0L; - for (String name : firstAccount.getAssetMap().keySet()) { - token1BeforeBalance = firstAccount.getAssetMap().get(name); - } - Assert.assertTrue(PublicMethed.transferAsset(exchange001Address, assetAccountId2.toByteArray(), - secondTransferAssetToFirstAccountNum, secondExchange001Address, - secondExchange001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long token2BeforeBalance = secondTransferAssetToFirstAccountNum; - - //logger.info("name1 is " + name1); - //logger.info("name2 is " + name2); - //logger.info("first balance is " + Long.toString(token1BeforeBalance)); - //logger.info("second balance is " + token2BeforeBalance.toString()); - //CreateExchange - Assert.assertTrue( - PublicMethed.exchangeCreate(assetAccountId1.toByteArray(), firstTokenInitialBalance, - assetAccountId2.toByteArray(), secondTokenInitialBalance, exchange001Address, - exchange001Key, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - listExchange = PublicMethed.getExchangeList(blockingStubFull); - Integer afterCreateExchangeNum = listExchange.get().getExchangesCount(); - Assert.assertTrue(afterCreateExchangeNum - beforeCreateExchangeNum == 1); - exchangeId = listExchange.get().getExchangesCount(); - - } - - @Test(enabled = true,description = "Test list exchange api") - public void test3ListExchange() { - listExchange = PublicMethed.getExchangeList(blockingStubFull); - for (Integer i = 0; i < listExchange.get().getExchangesCount(); i++) { - Assert.assertFalse(ByteArray.toHexString(listExchange.get().getExchanges(i) - .getCreatorAddress().toByteArray()).isEmpty()); - Assert.assertTrue(listExchange.get().getExchanges(i).getExchangeId() > 0); - Assert.assertFalse(ByteArray.toStr(listExchange.get().getExchanges(i).getFirstTokenId() - .toByteArray()).isEmpty()); - Assert.assertTrue(listExchange.get().getExchanges(i).getFirstTokenBalance() > 0); - } - } - - @Test(enabled = true,description = "Test inject exchange") - public void test4InjectExchange() { - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - final Long beforeExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - final Long beforeExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long beforeToken1Balance = 0L; - Long beforeToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - logger.info("before token 1 balance is " + Long.toString(beforeToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(beforeToken2Balance)); - Integer injectBalance = 100; - Assert.assertTrue( - PublicMethed.injectExchange(exchangeId, assetAccountId1.toByteArray(), injectBalance, - exchange001Address, exchange001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long afterToken1Balance = 0L; - Long afterToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - afterToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - afterToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - logger.info("before token 1 balance is " + Long.toString(afterToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(afterToken2Balance)); - - Assert.assertTrue(beforeToken1Balance - afterToken1Balance == injectBalance); - Assert.assertTrue(beforeToken2Balance - afterToken2Balance == injectBalance - * exchangeRate); - - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - Long afterExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - Long afterExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - Assert.assertTrue(afterExchangeToken1Balance - beforeExchangeToken1Balance - == injectBalance); - Assert.assertTrue(afterExchangeToken2Balance - beforeExchangeToken2Balance - == injectBalance * exchangeRate); - } - - @Test(enabled = true,description = "Test withdraw exchange") - public void test5WithdrawExchange() { - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - final Long beforeExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - final Long beforeExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long beforeToken1Balance = 0L; - Long beforeToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - - logger.info("before token 1 balance is " + Long.toString(beforeToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(beforeToken2Balance)); - Integer withdrawNum = 200; - Assert.assertTrue( - PublicMethed.exchangeWithdraw(exchangeId, assetAccountId1.toByteArray(), withdrawNum, - exchange001Address, exchange001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long afterToken1Balance = 0L; - Long afterToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - afterToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - afterToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - - logger.info("before token 1 balance is " + Long.toString(afterToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(afterToken2Balance)); - - Assert.assertTrue(afterToken1Balance - beforeToken1Balance == withdrawNum); - Assert.assertTrue(afterToken2Balance - beforeToken2Balance == withdrawNum - * exchangeRate); - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - Long afterExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - Long afterExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - Assert.assertTrue(afterExchangeToken1Balance - beforeExchangeToken1Balance - == -withdrawNum); - Assert.assertTrue(afterExchangeToken2Balance - beforeExchangeToken2Balance - == -withdrawNum * exchangeRate); - - - } - - @Test(enabled = true,description = "Test exchange transaction") - public void test6TransactionExchange() { - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - final Long beforeExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - final Long beforeExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - logger.info("beforeExchangeToken1Balance" + beforeExchangeToken1Balance); - logger.info("beforeExchangeToken2Balance" + beforeExchangeToken2Balance); - - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long beforeToken1Balance = 0L; - Long beforeToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - - logger.info("before token 1 balance is " + Long.toString(beforeToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(beforeToken2Balance)); - Integer transactionNum = 50; - Assert.assertTrue( - PublicMethed - .exchangeTransaction(exchangeId, assetAccountId1.toByteArray(), transactionNum, 1, - exchange001Address, exchange001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long afterToken1Balance = 0L; - Long afterToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - afterToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - afterToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - logger.info("before token 1 balance is " + Long.toString(afterToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(afterToken2Balance)); - - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - Long afterExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - Long afterExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - logger.info("afterExchangeToken1Balance" + afterExchangeToken1Balance); - logger.info("afterExchangeToken2Balance" + afterExchangeToken2Balance); - Assert.assertTrue(afterExchangeToken1Balance - beforeExchangeToken1Balance - == beforeToken1Balance - afterToken1Balance); - Assert.assertTrue(afterExchangeToken2Balance - beforeExchangeToken2Balance - == beforeToken2Balance - afterToken2Balance); - } - - @Test(enabled = true,description = "Test GetExchangeListPaginated api") - public void test7GetExchangeListPaginated() { - PaginatedMessage.Builder pageMessageBuilder = PaginatedMessage.newBuilder(); - pageMessageBuilder.setOffset(0); - pageMessageBuilder.setLimit(100); - ExchangeList exchangeList = blockingStubFull - .getPaginatedExchangeList(pageMessageBuilder.build()); - Assert.assertTrue(exchangeList.getExchangesCount() >= 1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - //Solidity support getExchangeId - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubSolidity); - logger.info("createtime is" + exchangeIdInfo.get().getCreateTime()); - Assert.assertTrue(exchangeIdInfo.get().getCreateTime() > 0); - - //Solidity support listexchange - listExchange = PublicMethed.getExchangeList(blockingStubSolidity); - Assert.assertTrue(listExchange.get().getExchangesCount() > 0); - } - - /** - * constructor. - */ - @Test(enabled = true,description = "Test get exchange list from pbft") - public void test8GetExchangeListFromPbft() { - //Pbft support listexchange - listExchange = PublicMethed.getExchangeList(blockingStubPbft); - Assert.assertTrue(listExchange.get().getExchangesCount() > 0); - } - - /** - * constructor. - */ - @Test(enabled = true,description = "Test get exchange by id from pbft") - public void test9GetExchangeByIdFromPbft() { - Assert.assertEquals(PublicMethed.getExchange(exchangeId.toString(), blockingStubPbft), - PublicMethed.getExchange(exchangeId.toString(), blockingStubSolidity)); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelPbft != null) { - channelPbft.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue001.java deleted file mode 100644 index d384793d2d4..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue001.java +++ /dev/null @@ -1,333 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.UnfreezeAssetContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class WalletTestAssetIssue001 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "testAssetIssue001_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] noBandwitchAddress = ecKey.getAddress(); - String noBandwitch = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Transfer asset use Bandwitch") - public void testTransferAssetBandwitchDecreaseWithin10Second() { - //get account - ecKey = new ECKey(Utils.getRandom()); - noBandwitchAddress = ecKey.getAddress(); - noBandwitch = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - PublicMethed.printAddress(noBandwitch); - - Assert.assertTrue(PublicMethed.sendcoin(noBandwitchAddress, 2048000000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long start = System.currentTimeMillis() + 5000; - Long end = System.currentTimeMillis() + 1000000000; - - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(noBandwitchAddress, name, totalSupply, 1, - 100, start, end, 1, description, url, 10000L, 10000L, - 1L, 1L, noBandwitch, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed.queryAccount(noBandwitch, blockingStubFull); - ByteString assetAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - - Assert.assertTrue(transferAsset(toAddress, assetAccountId.toByteArray(), 100L, - noBandwitchAddress, noBandwitch)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //Transfer Asset failed when transfer to yourself - Assert.assertFalse(transferAsset(toAddress, assetAccountId.toByteArray(), 100L, - toAddress, testKey003)); - //Transfer Asset failed when the transfer amount is large than the asset balance you have. - Assert.assertFalse( - transferAsset(fromAddress, assetAccountId.toByteArray(), 9100000000000000000L, - toAddress, testKey003)); - //Transfer Asset failed when the transfer amount is 0 - Assert.assertFalse(transferAsset(fromAddress, assetAccountId.toByteArray(), 0L, - toAddress, testKey003)); - //Transfer Asset failed when the transfer amount is -1 - Assert.assertFalse(transferAsset(fromAddress, assetAccountId.toByteArray(), -1L, - toAddress, testKey003)); - - //Transfer success. - Assert.assertTrue(transferAsset(fromAddress, assetAccountId.toByteArray(), 1L, - toAddress, testKey003)); - - //No freeze asset, try to unfreeze asset failed. - Assert.assertFalse(unFreezeAsset(noBandwitchAddress, noBandwitch)); - - //Not create asset, try to unfreeze asset failed.No exception. - Assert.assertFalse(unFreezeAsset(toAddress, testKey003)); - - - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(noBandwitchAddress, noBandwitch, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean createAssetIssue(byte[] address, String name, Long totalSupply, Integer trxNum, - Integer icoNum, Long startTime, Long endTime, - Integer voteScore, String description, String url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - try { - AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - builder.setFreeAssetNetLimit(20000); - builder.setPublicFreeAssetNetLimit(20000); - Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (!response.getResult()) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - logger.info(name); - return true; - } - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - - public boolean transferAsset(byte[] to, byte[] assertName, long amount, byte[] address, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.transferAsset(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null || transaction.getRawData().getContractCount() == 0"); - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (!response.getResult()) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - Account search = queryAccount(ecKey, blockingStubFull); - return true; - } - - } - - /** - * constructor. - */ - - public boolean unFreezeAsset(byte[] addRess, String priKey) { - byte[] address = addRess; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - UnfreezeAssetContract.Builder builder = UnfreezeAssetContract - .newBuilder(); - ByteString byteAddress = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddress); - - UnfreezeAssetContract contract = builder.build(); - - Transaction transaction = blockingStubFull.unfreezeAsset(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (!response.getResult()) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - } - return response.getResult(); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue002.java deleted file mode 100644 index be0cc3de7d3..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue002.java +++ /dev/null @@ -1,346 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.ParticipateAssetIssueContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class WalletTestAssetIssue002 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "testAssetIssue002_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - - } - - @Test(enabled = true, description = "Participate token") - public void testParticipateAssetissue() { - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] participateAccountAddress = ecKey1.getAddress(); - final String participateAccountKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] toAddress = ecKey2.getAddress(); - final String testKey003 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - //send coin to the new account - Assert.assertTrue(PublicMethed.sendcoin(participateAccountAddress, 2048000000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.sendcoin(toAddress, 2048000000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //Create a new Asset Issue - Assert.assertTrue(PublicMethed.createAssetIssue(participateAccountAddress, - name, totalSupply, 1, 1, System.currentTimeMillis() + 5000, - System.currentTimeMillis() + 1000000000, 1, description, url, - 2000L, 2000L, 1L, 1L, - participateAccountKey, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed.queryAccount(participateAccountKey, blockingStubFull); - final ByteString assetAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - - //Participate AssetIssue success - logger.info(name); - //Freeze amount to get bandwitch. - logger.info("toaddress balance is " - + PublicMethed.queryAccount(toAddress, blockingStubFull).getBalance()); - Assert.assertTrue(PublicMethed.freezeBalance(toAddress, 10000000, 3, testKey003, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.participateAssetIssue(participateAccountAddress, - assetAccountId.toByteArray(), - 100L, toAddress, testKey003, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //The amount is large than the total supply, participate failed. - Assert.assertFalse(PublicMethed.participateAssetIssue(participateAccountAddress, - assetAccountId.toByteArray(), 9100000000000000000L, toAddress, testKey003, - blockingStubFull)); - - //The amount is 0, participate asset issue failed. - Assert.assertFalse(PublicMethed.participateAssetIssue(participateAccountAddress, - assetAccountId.toByteArray(), 0L, toAddress, testKey003, blockingStubFull)); - - //The amount is -1, participate asset issue failed. - Assert.assertFalse(PublicMethed.participateAssetIssue(participateAccountAddress, - assetAccountId.toByteArray(), -1L, toAddress, testKey003, blockingStubFull)); - - //The asset issue owner address is not correct, participate asset issue failed. - Assert.assertFalse(PublicMethed.participateAssetIssue(fromAddress, - assetAccountId.toByteArray(), 100L, - toAddress, testKey003, blockingStubFull)); - - PublicMethed.freedResource(participateAccountAddress, participateAccountKey, fromAddress, - blockingStubFull); - PublicMethed.freedResource(toAddress, testKey003, fromAddress, blockingStubFull); - - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public boolean participateAssetIssue(byte[] to, byte[] assertName, long amount, byte[] from, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - ParticipateAssetIssueContract.Builder builder = ParticipateAssetIssueContract - .newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(from); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - ParticipateAssetIssueContract contract = builder.build(); - - Transaction transaction = blockingStubFull.participateAssetIssue(contract); - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - logger.info(name); - return true; - } - } - - /** - * constructor. - */ - - public Boolean createAssetIssue(byte[] address, String name, Long totalSupply, Integer trxNum, - Integer icoNum, Long startTime, Long endTime, - Integer voteScore, String description, String url, Long fronzenAmount, Long frozenDay, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - try { - AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - builder.setFreeAssetNetLimit(20000); - builder.setPublicFreeAssetNetLimit(20000); - AssetIssueContract.FrozenSupply.Builder frozenBuilder = - AssetIssueContract.FrozenSupply.newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - builder.addFrozenSupply(0, frozenBuilder); - - Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (!response.getResult()) { - logger.info(name); - } - return response.getResult(); - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - /** - * constructor. - */ - - public Account queryAccount(String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - - public boolean transferAsset(byte[] to, byte[] assertName, long amount, byte[] address, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.transferAsset(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null || transaction.getRawData().getContractCount() == 0"); - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - //Account search = queryAccount(ecKey, blockingStubFull); - return true; - } - - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue003.java deleted file mode 100644 index 60969accc18..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue003.java +++ /dev/null @@ -1,416 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.AssetIssueContractOuterClass.ParticipateAssetIssueContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.UnfreezeAssetContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class WalletTestAssetIssue003 { - - private static final long now = System.currentTimeMillis(); - private static final String name = "testAssetIssue003_" + Long.toString(now); - private static final String shortname = "a"; - private static final String tooLongName = "qazxswedcvfrtgbnhyujmkiolpoiuytre"; - private static final String chineseAssetIssuename = "中文都名字"; - private static final String tooLongAbbreviation = "wazxswedcvfrtgbnhyujmkiolpoiuytre"; - private static final String chineseAbbreviation = "中文的简称"; - private static final String tooLongDescription = - "1qazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqa" - + "zxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvq" - + "azxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcv"; - private static final String tooLongUrl = - "qaswqaswqaswqaswqaswqaswqaswqaswqaswqaswqaswqaswqaswqasw1qazxswedcvqazxswedcv" - + "qazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedc" - + "vqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqaz" - + "xswedcvqazxswedcvqazxswedcvqazxswedcv"; - private static final long totalSupply = now; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - //get account - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] asset003Address = ecKey.getAddress(); - String asset003Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Create token with exception condition") - public void testExceptionOfAssetIssuew() { - PublicMethed.sendcoin(asset003Address, 2048000000L, fromAddress, testKey002, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long start = System.currentTimeMillis() + 100000; - Long end = System.currentTimeMillis() + 1000000000; - //Freeze amount is large than total supply, create asset issue failed. - Assert.assertFalse(PublicMethed.createAssetIssue(asset003Address, name, totalSupply, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 9000000000000000000L, 1L, asset003Key, blockingStubFull)); - //Freeze day is 0, create failed - Assert.assertFalse(PublicMethed.createAssetIssue(asset003Address, name, totalSupply, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 100L, 0L, asset003Key, blockingStubFull)); - //Freeze amount is 0, create failed - Assert.assertFalse(PublicMethed.createAssetIssue(asset003Address, name, totalSupply, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 0L, 1L, asset003Key, blockingStubFull)); - //Freeze day is -1, create failed - Assert.assertFalse(PublicMethed.createAssetIssue(asset003Address, name, totalSupply, 1, 10, - start, end, 2, description, url, 1000L, 1000L, - 1000L, -1L, asset003Key, blockingStubFull)); - //Freeze amount is -1, create failed - Assert.assertFalse(PublicMethed.createAssetIssue(asset003Address, name, totalSupply, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - -1L, 1L, asset003Key, blockingStubFull)); - //Freeze day is 3653(10 years + 1 day), create failed - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, totalSupply, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3653L, asset003Key, blockingStubFull)); - //Start time is late than end time. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, totalSupply, 1, 10, - end, start, 2, description, url, 10000L, 10000L, - 1L, 2L, asset003Key, blockingStubFull)); - //Start time is early than currently time. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, totalSupply, 1, 10, - start - 1000000L, end, 2, description, url, 10000L, - 10000L, 1L, 2L, asset003Key, blockingStubFull)); - //totalSupply is zero. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, 0L, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, asset003Key, blockingStubFull)); - //Total supply is -1. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, -1L, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, asset003Key, blockingStubFull)); - //TrxNum is zero. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, totalSupply, 0, 10, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, asset003Key, blockingStubFull)); - //TrxNum is -1. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, totalSupply, -1, 10, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, asset003Key, blockingStubFull)); - //IcoNum is 0. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, totalSupply, 1, 0, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, asset003Key, blockingStubFull)); - //IcoNum is -1. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, totalSupply, 1, -1, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, asset003Key, blockingStubFull)); - //The asset issue name is null. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, "", totalSupply, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, asset003Key, blockingStubFull)); - //The asset issue name is large than 33 char. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, tooLongName, totalSupply, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, asset003Key, blockingStubFull)); - //The asset issue name is chinese name. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, chineseAssetIssuename, - totalSupply, 1, 10, start, end, 2, description, url, 10000L, - 10000L, 1L, 3652L, asset003Key, blockingStubFull)); - //The abbreviation is null. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, "", totalSupply, - 1, 10, start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, asset003Key, blockingStubFull)); - //The abbreviation is large than 33 char. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, tooLongAbbreviation, - totalSupply, 1, 10, start, end, 2, description, url, 10000L, - 10000L, 1L, 3652L, asset003Key, blockingStubFull)); - //The abbreviation is chinese name. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, chineseAbbreviation, - totalSupply, 1, 10, start, end, 2, description, url, 10000L, - 10000L, 1L, 3652L, asset003Key, blockingStubFull)); - //The URL is null. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, totalSupply, 1, 10, - start, end, 2, description, "", 10000L, 10000L, - 1L, 3652L, asset003Key, blockingStubFull)); - //The URL is too long. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, totalSupply, - 1, 10, start, end, 2, description, tooLongUrl, 10000L, - 10000L, 1L, 3652L, asset003Key, blockingStubFull)); - //The description is null. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, totalSupply, - 1, 10, start, end, 2, "", url, 10000L, - 10000L, 1L, 3652L, asset003Key, blockingStubFull)); - //The description is too long, create failed. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, totalSupply, 1, 10, - start, end, 2, tooLongDescription, url, 10000L, - 10000L, 1L, 3652L, asset003Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Get asset issue list") - public void testGetAllAssetIssue() { - GrpcAPI.AssetIssueList assetIssueList = blockingStubFull - .getAssetIssueList(GrpcAPI.EmptyMessage.newBuilder().build()); - Assert.assertTrue(assetIssueList.getAssetIssueCount() >= 1); - Integer times = assetIssueList.getAssetIssueCount(); - if (assetIssueList.getAssetIssueCount() >= 10) { - times = 10; - } - for (Integer j = 0; j < times; j++) { - Assert.assertFalse(assetIssueList.getAssetIssue(j).getOwnerAddress().isEmpty()); - Assert.assertFalse(assetIssueList.getAssetIssue(j).getName().isEmpty()); - Assert.assertFalse(assetIssueList.getAssetIssue(j).getUrl().isEmpty()); - Assert.assertTrue(assetIssueList.getAssetIssue(j).getTotalSupply() > 0); - logger.info("test get all assetissue"); - } - - //Improve coverage. - assetIssueList.equals(assetIssueList); - assetIssueList.equals(null); - GrpcAPI.AssetIssueList newAssetIssueList = blockingStubFull - .getAssetIssueList(GrpcAPI.EmptyMessage.newBuilder().build()); - assetIssueList.equals(newAssetIssueList); - assetIssueList.hashCode(); - assetIssueList.getSerializedSize(); - - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(asset003Address, asset003Key, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - - public boolean transferAsset(byte[] to, byte[] assertName, long amount, byte[] address, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.transferAsset(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (!response.getResult()) { - return false; - } else { - Account search = queryAccount(ecKey, blockingStubFull); - return true; - } - - } - - /** - * constructor. - */ - - public boolean unFreezeAsset(byte[] addRess, String priKey) { - byte[] address = addRess; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - UnfreezeAssetContract.Builder builder = UnfreezeAssetContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess); - - UnfreezeAssetContract contract = builder.build(); - - Transaction transaction = blockingStubFull.unfreezeAsset(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (!response.getResult()) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public boolean participateAssetIssue(byte[] to, byte[] assertName, long amount, byte[] from, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - ParticipateAssetIssueContract.Builder builder = ParticipateAssetIssueContract - .newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(from); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - ParticipateAssetIssueContract contract = builder.build(); - - Transaction transaction = blockingStubFull.participateAssetIssue(contract); - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - logger.info(name); - return true; - } - } - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue004.java deleted file mode 100644 index 773e066ece8..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue004.java +++ /dev/null @@ -1,294 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class WalletTestAssetIssue004 { - - //testng001、testng002、testng003、testng004 - /* private static final byte[] fromAddress = Base58 - .decodeFromBase58Check("THph9K2M2nLvkianrMGswRhz5hjSA9fuH7");*/ - private static final byte[] NO_ASSET_ADDRESS = Base58 - .decodeFromBase58Check("27XeWZUtufGk8jdjF3m1tuPnnRqqKgzS3pT"); - private static final byte[] INVALID_ADDRESS = Base58 - .decodeFromBase58Check("27cu1ozb4mX3m2afY68FSAqn3HmMp815d48"); - private static final long now = System.currentTimeMillis(); - private static final String name = "testAssetIssue004_" + Long.toString(now); - private static final long totalSupply = now; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - String description = "just-test"; - String url = "https://github.com/tronprotocol/wallet-cli/"; - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - ByteString addressBs1 = ByteString.copyFrom(fromAddress); - Account request1 = Account.newBuilder().setAddress(addressBs1).build(); - GrpcAPI.AssetIssueList assetIssueList1 = blockingStubFull - .getAssetIssueByAccount(request1); - Optional queryAssetByAccount = Optional.ofNullable(assetIssueList1); - if (queryAssetByAccount.get().getAssetIssueCount() == 0) { - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - //Create a new asset issue - Assert.assertTrue(PublicMethed.createAssetIssue(fromAddress, name, totalSupply, 6, 1000, - start, end, 2, description, url, 10000L, 10000L, - 1L, 1L, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } else { - logger.info("This account already create an assetisue"); - } - - } - - @Test(enabled = true, description = "Get asset issue by account") - public void testGetAssetIssueByAccount() { - ByteString addressBs = ByteString.copyFrom(fromAddress); - Account request = Account.newBuilder().setAddress(addressBs).build(); - GrpcAPI.AssetIssueList assetIssueList = blockingStubFull - .getAssetIssueByAccount(request); - Optional queryAssetIssueByAccount = Optional.ofNullable(assetIssueList); - logger.info(Integer.toString(queryAssetIssueByAccount.get().getAssetIssueCount())); - Assert.assertTrue(queryAssetIssueByAccount.get().getAssetIssueCount() == 1); - for (Integer j = 0; j < queryAssetIssueByAccount.get().getAssetIssueCount(); j++) { - if (queryAssetIssueByAccount.get().getAssetIssue(j).getTotalSupply() == totalSupply) { - Assert.assertTrue(queryAssetIssueByAccount.isPresent()); - //Assert.assertTrue(queryAssetIssueByAccount.get().getAssetIssue(j).getDecayRatio() > 0); - Assert.assertTrue(queryAssetIssueByAccount.get().getAssetIssue(j).getTrxNum() > 0); - Assert.assertTrue(queryAssetIssueByAccount.get().getAssetIssue(j).getVoteScore() > 0); - Assert.assertFalse(queryAssetIssueByAccount.get().getAssetIssue(j).getUrl().isEmpty()); - logger.info("TestGetAssetIssueByAccount ok!"); - } - } - - //No exception when the address didn't create asset issue. - ByteString addressBS1 = ByteString.copyFrom(NO_ASSET_ADDRESS); - Account request1 = Account.newBuilder().setAddress(addressBS1).build(); - GrpcAPI.AssetIssueList assetIssueList1 = blockingStubFull - .getAssetIssueByAccount(request1); - Optional queryNoAssetByAccount = Optional.ofNullable(assetIssueList1); - Assert.assertTrue(queryNoAssetByAccount.get().getAssetIssueCount() == 0); - logger.info("No asset account queryed nothing"); - - //No exception when the address is invalid. - addressBS1 = ByteString.copyFrom(INVALID_ADDRESS); - request1 = Account.newBuilder().setAddress(addressBS1).build(); - assetIssueList1 = blockingStubFull - .getAssetIssueByAccount(request1); - queryNoAssetByAccount = Optional.ofNullable(assetIssueList1); - Assert.assertTrue(queryNoAssetByAccount.get().getAssetIssueCount() == 0); - logger.info("No asset account queryed nothing"); - - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean createAssetIssue(byte[] address, String name, Long totalSupply, Integer trxNum, - Integer icoNum, Long startTime, Long endTime, - Integer voteScore, String description, String url, Long fronzenAmount, Long frozenDay, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - try { - AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - builder.setFreeAssetNetLimit(20000); - builder.setPublicFreeAssetNetLimit(20000); - AssetIssueContract.FrozenSupply.Builder - frozenBuilder = AssetIssueContract.FrozenSupply - .newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - builder.addFrozenSupply(0, frozenBuilder); - - Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult()) { - logger.info(name); - } - return response.getResult(); - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - - public boolean transferAsset(byte[] to, byte[] assertName, long amount, byte[] address, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.transferAsset(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult()) { - Account search = queryAccount(ecKey, blockingStubFull); - } - return response.getResult(); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue005.java deleted file mode 100644 index 742d5a52ca1..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue005.java +++ /dev/null @@ -1,297 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class WalletTestAssetIssue005 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "testAssetIssue005_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - String description = "just-test"; - String url = "https://github.com/tronprotocol/wallet-cli/"; - - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Get asset issue by name") - public void testGetAssetIssueByName() { - ByteString addressBS1 = ByteString.copyFrom(fromAddress); - Account request1 = Account.newBuilder().setAddress(addressBS1).build(); - GrpcAPI.AssetIssueList assetIssueList1 = blockingStubFull - .getAssetIssueByAccount(request1); - Optional queryAssetByAccount = Optional.ofNullable(assetIssueList1); - if (queryAssetByAccount.get().getAssetIssueCount() == 0) { - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - //Create a new asset issue - Assert.assertTrue(PublicMethed.createAssetIssue(fromAddress, name, totalSupply, 1, 100, - start, end, 1, description, url, 10000L, 10000L, - 1L, 1L, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } else { - logger.info("This account already create an assetisue"); - Optional queryAssetByAccount1 = Optional.ofNullable(assetIssueList1); - name = ByteArray.toStr(queryAssetByAccount1.get().getAssetIssue(0).getName().toByteArray()); - } - - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed.queryAccount(testKey002, blockingStubFull); - ByteString assetAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - - //Get asset issue by name success. - - GrpcAPI.BytesMessage request = GrpcAPI.BytesMessage.newBuilder().setValue(assetAccountId) - .build(); - AssetIssueContract assetIssueByName = - blockingStubFull.getAssetIssueByName(request); - - Assert.assertFalse(assetIssueByName.getUrl().isEmpty()); - Assert.assertFalse(assetIssueByName.getDescription().isEmpty()); - Assert.assertTrue(assetIssueByName.getTotalSupply() > 0); - Assert.assertTrue(assetIssueByName.getTrxNum() > 0); - - //Get asset issue by name failed when the name is not correct.There is no exception. - String wrongName = name + "_wrong"; - ByteString assetNameBs = ByteString.copyFrom(name.getBytes()); - assetNameBs = ByteString.copyFrom(wrongName.getBytes()); - request = GrpcAPI.BytesMessage.newBuilder().setValue(assetNameBs).build(); - assetIssueByName = blockingStubFull.getAssetIssueByName(request); - - Assert.assertFalse(assetIssueByName.getTotalSupply() > 0); - Assert.assertFalse(assetIssueByName.getTrxNum() > 0); - Assert.assertTrue(assetIssueByName.getUrl().isEmpty()); - Assert.assertTrue(assetIssueByName.getDescription().isEmpty()); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean createAssetIssue(byte[] address, String name, Long totalSupply, Integer trxNum, - Integer icoNum, Long startTime, Long endTime, - Integer voteScore, String description, String url, Long fronzenAmount, Long frozenDay, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - try { - AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - builder.setFreeAssetNetLimit(20000); - builder.setPublicFreeAssetNetLimit(20000); - AssetIssueContract.FrozenSupply.Builder frozenBuilder = - AssetIssueContract.FrozenSupply - .newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - builder.addFrozenSupply(0, frozenBuilder); - - Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult()) { - logger.info(name); - } - return response.getResult(); - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - - public boolean transferAsset(byte[] to, byte[] assertName, long amount, byte[] address, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.transferAsset(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null || transaction.getRawData().getContractCount() == 0"); - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (!response.getResult()) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - Account search = queryAccount(ecKey, blockingStubFull); - return true; - } - - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue006.java deleted file mode 100644 index 97ffdb472c5..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue006.java +++ /dev/null @@ -1,213 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAssetIssue006 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "assetissue006" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - String description = "test query assetissue by timestamp from soliditynode"; - String url = "https://testqueryassetissue.com/bytimestamp/from/soliditynode/"; - //get account - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] queryAssetIssueFromSoliAddress = ecKey.getAddress(); - String queryAssetIssueKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - /* @Test(enabled = true) - public void testGetAssetIssueListByTimestamp() { - Assert.assertTrue(PublicMethed.freezeBalance(fromAddress,10000000,3,testKey002, - blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(queryAssetIssueFromSoliAddress,2048000000,fromAddress, - testKey002,blockingStubFull)); - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(queryAssetIssueFromSoliAddress, name, - totalSupply, 1, 100, start, end, 1, description, url, 1000L, - 1000L,1L,1L,queryAssetIssueKey,blockingStubFull)); - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Block solidityCurrentBlock = blockingStubSolidity.getNowBlock(GrpcAPI.EmptyMessage - .newBuilder().build()); - Integer wait = 0; - while (solidityCurrentBlock.getBlockHeader().getRawData().getNumber() - < currentBlock.getBlockHeader().getRawData().getNumber() + 1 && wait < 10) { - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - logger.info("Solidity didn't synchronize the fullnode block,please wait"); - solidityCurrentBlock = blockingStubSolidity.getNowBlock(GrpcAPI.EmptyMessage.newBuilder() - .build()); - wait++; - if (wait == 9) { - logger.info("Didn't syn,skip to next case."); - } - } - - - long time = now; - NumberMessage.Builder timeStamp = NumberMessage.newBuilder(); - timeStamp.setNum(time); - GrpcAPI.AssetIssueList assetIssueList = blockingStubSolidity - .getAssetIssueListByTimestamp(timeStamp.build()); - Optional getAssetIssueListByTimestamp = Optional - .ofNullable(assetIssueList); - - Assert.assertTrue(getAssetIssueListByTimestamp.isPresent()); - Assert.assertTrue(getAssetIssueListByTimestamp.get().getAssetIssueCount() > 0); - logger.info(Integer.toString(getAssetIssueListByTimestamp.get().getAssetIssueCount())); - for (Integer j = 0; j < getAssetIssueListByTimestamp.get().getAssetIssueCount(); j++) { - Assert.assertFalse(getAssetIssueListByTimestamp.get().getAssetIssue(j).getName().isEmpty()); - Assert.assertTrue(getAssetIssueListByTimestamp.get().getAssetIssue(j).getTotalSupply() > 0); - Assert.assertTrue(getAssetIssueListByTimestamp.get().getAssetIssue(j).getNum() > 0); - logger.info( - Long.toString(getAssetIssueListByTimestamp.get().getAssetIssue(j).getTotalSupply())); - } - - } - - @Test(enabled = true) - public void testExceptionGetAssetIssueListByTimestamp() { - //Time stamp is below zero. - long time = -1000000000; - NumberMessage.Builder timeStamp = NumberMessage.newBuilder(); - timeStamp.setNum(time); - GrpcAPI.AssetIssueList assetIssueList = blockingStubSolidity - .getAssetIssueListByTimestamp(timeStamp.build()); - Optional getAssetIssueListByTimestamp = Optional - .ofNullable(assetIssueList); - Assert.assertTrue(getAssetIssueListByTimestamp.get().getAssetIssueCount() == 0); - - //No asset issue was create - time = 1000000000; - timeStamp = NumberMessage.newBuilder(); - timeStamp.setNum(time); - assetIssueList = blockingStubSolidity.getAssetIssueListByTimestamp(timeStamp.build()); - getAssetIssueListByTimestamp = Optional.ofNullable(assetIssueList); - Assert.assertTrue(getAssetIssueListByTimestamp.get().getAssetIssueCount() == 0); - - }*/ - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - - } - - /** - * constructor. - */ - - @AfterClass(enabled = false) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue007.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue007.java deleted file mode 100644 index df91b54f8dd..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue007.java +++ /dev/null @@ -1,173 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountNetMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAssetIssue007 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static final long sendAmount = 10000000000L; - private static final long netCostMeasure = 200L; - private static final Integer trxNum = 1; - private static final Integer icoNum = 1; - private static String name = "AssetIssue007_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - Long freeAssetNetLimit = 10000L; - Long publicFreeAssetNetLimit = 10000L; - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf").getString("defaultParameter.assetUrl"); - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] asset007Address = ecKey1.getAddress(); - String testKeyForAssetIssue007 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] participateAssetAddress = ecKey2.getAddress(); - String participateAssetCreateKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKeyForAssetIssue007); - PublicMethed.printAddress(participateAssetCreateKey); - - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Participate asset issue use participate bandwidth") - public void testParticipateAssetIssueUseParticipateBandwidth() { - Assert.assertTrue(PublicMethed - .sendcoin(asset007Address, sendAmount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long start = System.currentTimeMillis() + 5000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed - .createAssetIssue(asset007Address, name, totalSupply, trxNum, icoNum, start, end, 1, - description, url, freeAssetNetLimit, publicFreeAssetNetLimit, 1L, 1L, - testKeyForAssetIssue007, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info(name); - //Assert.assertTrue(PublicMethed.waitProduceNextBlock(blockingStubFull)); - //When no balance, participate an asset issue - Assert.assertFalse(PublicMethed - .participateAssetIssue(asset007Address, name.getBytes(), 1L, participateAssetAddress, - participateAssetCreateKey, blockingStubFull)); - - ByteString addressBs = ByteString.copyFrom(asset007Address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - AccountNetMessage asset007NetMessage = blockingStubFull.getAccountNet(request); - final Long asset007BeforeFreeNetUsed = asset007NetMessage.getFreeNetUsed(); - - //SendCoin to participate account. - Assert.assertTrue(PublicMethed - .sendcoin(participateAssetAddress, 10000000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - addressBs = ByteString.copyFrom(participateAssetAddress); - request = Account.newBuilder().setAddress(addressBs).build(); - AccountNetMessage participateAccountNetMessage = blockingStubFull.getAccountNet(request); - final Long participateAccountBeforeNetUsed = participateAccountNetMessage.getFreeNetUsed(); - Assert.assertTrue(participateAccountBeforeNetUsed == 0); - - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed.queryAccount(asset007Address, blockingStubFull); - ByteString assetAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - logger.info(assetAccountId.toString()); - - //Participate an assetIssue, then query the net information. - Assert.assertTrue(PublicMethed - .participateAssetIssue(asset007Address, assetAccountId.toByteArray(), 1L, - participateAssetAddress, participateAssetCreateKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - addressBs = ByteString.copyFrom(asset007Address); - request = Account.newBuilder().setAddress(addressBs).build(); - asset007NetMessage = blockingStubFull.getAccountNet(request); - final Long asset007AfterFreeNetUsed = asset007NetMessage.getFreeNetUsed(); - - addressBs = ByteString.copyFrom(participateAssetAddress); - request = Account.newBuilder().setAddress(addressBs).build(); - participateAccountNetMessage = blockingStubFull.getAccountNet(request); - final Long participateAccountAfterNetUsed = participateAccountNetMessage.getFreeNetUsed(); - - logger.info(Long.toString(asset007BeforeFreeNetUsed)); - logger.info(Long.toString(asset007AfterFreeNetUsed)); - logger.info(Long.toString(participateAccountBeforeNetUsed)); - logger.info(Long.toString(participateAccountAfterNetUsed)); - Assert.assertTrue(asset007AfterFreeNetUsed <= asset007BeforeFreeNetUsed); - Assert.assertTrue(participateAccountAfterNetUsed - participateAccountBeforeNetUsed > 150); - - Assert.assertTrue(PublicMethed - .participateAssetIssue(asset007Address, assetAccountId.toByteArray(), 1L, - participateAssetAddress, participateAssetCreateKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed - .participateAssetIssue(asset007Address, assetAccountId.toByteArray(), 1L, - participateAssetAddress, participateAssetCreateKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account participateInfo = PublicMethed - .queryAccount(participateAssetCreateKey, blockingStubFull); - final Long beforeBalance = participateInfo.getBalance(); - Assert.assertTrue(PublicMethed - .participateAssetIssue(asset007Address, assetAccountId.toByteArray(), 1L, - participateAssetAddress, participateAssetCreateKey, blockingStubFull)); - participateInfo = PublicMethed.queryAccount(participateAssetCreateKey, blockingStubFull); - final Long afterBalance = participateInfo.getBalance(); - - Assert.assertTrue(beforeBalance - trxNum * 1 * icoNum >= afterBalance); - } - - @AfterMethod - public void aftertest() { - PublicMethed - .freedResource(asset007Address, testKeyForAssetIssue007, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue008.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue008.java deleted file mode 100644 index 258e0168094..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue008.java +++ /dev/null @@ -1,282 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.UnfreezeAssetContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class WalletTestAssetIssue008 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "assetissue008" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - String description = "test query assetissue from soliditynode"; - String url = "https://testqueryassetissue.com/from/soliditynode/"; - //get account - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] queryAssetIssueFromSoliAddress = ecKey.getAddress(); - String queryAssetIssueKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - logger.info(ByteArray.toHexString(ecKey.getPrivKeyBytes())); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Get asset issue list from Solidity") - public void testGetAllAssetIssueFromSolidity() { - Assert.assertTrue(PublicMethed.sendcoin(queryAssetIssueFromSoliAddress, 2048000000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(queryAssetIssueFromSoliAddress, name, - totalSupply, 1, 100, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, queryAssetIssueKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - GrpcAPI.AssetIssueList assetIssueList = blockingStubSolidity - .getAssetIssueList(GrpcAPI.EmptyMessage.newBuilder().build()); - logger.info(Long.toString(assetIssueList.getAssetIssueCount())); - - if (assetIssueList.getAssetIssueCount() == 0) { - Assert.assertTrue(PublicMethed.freezeBalance(fromAddress, 10000000L, 3, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(toAddress, 999999L, fromAddress, - testKey002, blockingStubFull)); - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - logger.info("fullnode block num is " + Long.toString(currentBlock.getBlockHeader() - .getRawData().getNumber())); - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - } - - assetIssueList = blockingStubSolidity - .getAssetIssueList(GrpcAPI.EmptyMessage.newBuilder().build()); - Assert.assertTrue(assetIssueList.getAssetIssueCount() >= 1); - for (Integer j = 0; j < assetIssueList.getAssetIssueCount(); j++) { - Assert.assertFalse(assetIssueList.getAssetIssue(j).getOwnerAddress().isEmpty()); - Assert.assertFalse(assetIssueList.getAssetIssue(j).getName().isEmpty()); - Assert.assertFalse(assetIssueList.getAssetIssue(j).getUrl().isEmpty()); - Assert.assertTrue(assetIssueList.getAssetIssue(j).getTotalSupply() > 0); - logger.info("test get all assetissue from solidity"); - } - - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(queryAssetIssueFromSoliAddress, queryAssetIssueKey, fromAddress, - blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - - public boolean transferAsset(byte[] to, byte[] assertName, long amount, byte[] address, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.transferAsset(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (!response.getResult()) { - return false; - } else { - Account search = queryAccount(ecKey, blockingStubFull); - return true; - } - - } - - /** - * constructor. - */ - - public boolean unFreezeAsset(byte[] addRess, String priKey) { - byte[] address = addRess; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - //Account search = queryAccount(ecKey, blockingStubFull); - - UnfreezeAssetContract.Builder builder = UnfreezeAssetContract - .newBuilder(); - ByteString byteAddress = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddress); - - UnfreezeAssetContract contract = builder.build(); - - Transaction transaction = blockingStubFull.unfreezeAsset(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (!response.getResult()) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - } - return response.getResult(); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue009.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue009.java deleted file mode 100644 index 9d27d2781a5..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue009.java +++ /dev/null @@ -1,171 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class WalletTestAssetIssue009 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - - - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - - /* @Test(enabled = true) - public void testGetAssetIssueByAccountOrNameFromSolidity() { - //By name - ByteString addressBs = ByteString.copyFrom(fromAddress); - Account request = Account.newBuilder().setAddress(addressBs).build(); - GrpcAPI.AssetIssueList assetIssueList = blockingStubSolidity - .getAssetIssueByAccount(request); - Optional queryAssetIssueByAccount = Optional.ofNullable(assetIssueList); - logger.info(Integer.toString(queryAssetIssueByAccount.get().getAssetIssueCount())); - Assert.assertTrue(queryAssetIssueByAccount.get().getAssetIssueCount() >= 1); - for (Integer j = 0; j < queryAssetIssueByAccount.get().getAssetIssueCount(); j++) { - Assert.assertTrue(queryAssetIssueByAccount.get().getAssetIssue(j).getTotalSupply() > 0); - Assert.assertFalse(queryAssetIssueByAccount.get().getAssetIssue(j).getName().isEmpty()); - logger.info("TestGetAssetIssueByAccount in soliditynode ok!!!"); - - } - - //By ID - ByteString assetName = queryAssetIssueByAccount.get().getAssetIssue(0).getName(); - GrpcAPI.BytesMessage requestAsset = GrpcAPI.BytesMessage.newBuilder().setValue(assetName) - .build(); - Contract.AssetIssueContract assetIssueByName = blockingStubSolidity - .getAssetIssueByName(requestAsset); - - Assert.assertFalse(assetIssueByName.getUrl().isEmpty()); - Assert.assertFalse(assetIssueByName.getDescription().isEmpty()); - Assert.assertTrue(assetIssueByName.getTotalSupply() > 0); - Assert.assertTrue(assetIssueByName.getTrxNum() > 0); - - logger.info("TestGetAssetIssueByNameFromSolidity"); - }*/ - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - /** - * constructor. - */ - - @AfterClass(enabled = false) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue010.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue010.java deleted file mode 100644 index d367411244c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue010.java +++ /dev/null @@ -1,443 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.ParticipateAssetIssueContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.UnfreezeAssetContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class WalletTestAssetIssue010 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static final long sendAmount = 10000000000L; - private static final String tooLongDescription = - "1qazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcv" - + "qazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswe" - + "dcvqazxswedcvqazxswedcvqazxswedcvqazxswedcv"; - private static final String tooLongUrl = "qaswqaswqaswqaswqaswqaswqaswqaswqaswqaswqaswqas" - + "wqaswqasw1qazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazx" - + "swedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedc" - + "vqazxswedcvqazxswedcvqazxswedcvqazxswedcv"; - private static String name = "testAssetIssue010_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - String description = "just-test"; - String url = "https://github.com/tronprotocol/wallet-cli/"; - String updateDescription = "This is test for update asset issue, case AssetIssue_010"; - String updateUrl = "www.updateassetissue.010.cn"; - Long freeAssetNetLimit = 1000L; - Long publicFreeAssetNetLimit = 1000L; - Long updateFreeAssetNetLimit = 10001L; - Long updatePublicFreeAssetNetLimit = 10001L; - //get account - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] asset010Address = ecKey.getAddress(); - String testKeyForAssetIssue010 = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Update asset issue") - public void testUpdateAssetIssue() { - ecKey = new ECKey(Utils.getRandom()); - asset010Address = ecKey.getAddress(); - testKeyForAssetIssue010 = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - PublicMethed.printAddress(testKeyForAssetIssue010); - - Assert.assertTrue(PublicMethed - .sendcoin(asset010Address, sendAmount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalance(asset010Address, 200000000L, 0, testKeyForAssetIssue010, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed.createAssetIssue(asset010Address, name, totalSupply, 1, 1, - start, end, 1, description, url, freeAssetNetLimit, publicFreeAssetNetLimit, - 1L, 1L, testKeyForAssetIssue010, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed - .queryAccount(testKeyForAssetIssue010, blockingStubFull); - ByteString assetAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - - //Query the description and url,freeAssetNetLimit and publicFreeAssetNetLimit - GrpcAPI.BytesMessage request = GrpcAPI.BytesMessage.newBuilder() - .setValue(assetAccountId).build(); - AssetIssueContract assetIssueByName = blockingStubFull.getAssetIssueByName(request); - - Assert.assertTrue( - ByteArray.toStr(assetIssueByName.getDescription().toByteArray()).equals(description)); - Assert.assertTrue(ByteArray.toStr(assetIssueByName.getUrl().toByteArray()).equals(url)); - Assert.assertTrue(assetIssueByName.getFreeAssetNetLimit() == freeAssetNetLimit); - Assert.assertTrue(assetIssueByName.getPublicFreeAssetNetLimit() == publicFreeAssetNetLimit); - - //Test update asset issue - Assert.assertTrue(PublicMethed - .updateAsset(asset010Address, updateDescription.getBytes(), updateUrl.getBytes(), - updateFreeAssetNetLimit, - updatePublicFreeAssetNetLimit, testKeyForAssetIssue010, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //After update asset issue ,query the description and url, - // freeAssetNetLimit and publicFreeAssetNetLimit - assetIssueByName = blockingStubFull.getAssetIssueByName(request); - - Assert.assertTrue( - ByteArray.toStr(assetIssueByName.getDescription().toByteArray()).equals(updateDescription)); - Assert.assertTrue(ByteArray.toStr(assetIssueByName.getUrl().toByteArray()).equals(updateUrl)); - Assert.assertTrue(assetIssueByName.getFreeAssetNetLimit() == updateFreeAssetNetLimit); - Assert - .assertTrue(assetIssueByName.getPublicFreeAssetNetLimit() == updatePublicFreeAssetNetLimit); - } - - @Test(enabled = true, description = "Update asset issue with exception condition") - public void testUpdateAssetIssueException() { - //Test update asset issue for wrong parameter - //publicFreeAssetNetLimit is -1 - Assert.assertFalse(PublicMethed - .updateAsset(asset010Address, updateDescription.getBytes(), updateUrl.getBytes(), - updateFreeAssetNetLimit, - -1L, testKeyForAssetIssue010, blockingStubFull)); - //publicFreeAssetNetLimit is 0 - Assert.assertTrue(PublicMethed - .updateAsset(asset010Address, updateDescription.getBytes(), updateUrl.getBytes(), - updateFreeAssetNetLimit, - 0, testKeyForAssetIssue010, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //FreeAssetNetLimit is -1 - Assert.assertFalse(PublicMethed - .updateAsset(asset010Address, updateDescription.getBytes(), updateUrl.getBytes(), -1, - publicFreeAssetNetLimit, testKeyForAssetIssue010, blockingStubFull)); - //FreeAssetNetLimit is 0 - Assert.assertTrue(PublicMethed - .updateAsset(asset010Address, updateDescription.getBytes(), updateUrl.getBytes(), 0, - publicFreeAssetNetLimit, testKeyForAssetIssue010, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Description is null - Assert.assertTrue(PublicMethed - .updateAsset(asset010Address, "".getBytes(), updateUrl.getBytes(), freeAssetNetLimit, - publicFreeAssetNetLimit, testKeyForAssetIssue010, blockingStubFull)); - //Url is null - Assert.assertFalse(PublicMethed - .updateAsset(asset010Address, description.getBytes(), "".getBytes(), freeAssetNetLimit, - publicFreeAssetNetLimit, testKeyForAssetIssue010, blockingStubFull)); - //Too long discription - Assert.assertFalse(PublicMethed - .updateAsset(asset010Address, tooLongDescription.getBytes(), url.getBytes(), - freeAssetNetLimit, - publicFreeAssetNetLimit, testKeyForAssetIssue010, blockingStubFull)); - //Too long URL - Assert.assertFalse(PublicMethed - .updateAsset(asset010Address, description.getBytes(), tooLongUrl.getBytes(), - freeAssetNetLimit, - publicFreeAssetNetLimit, testKeyForAssetIssue010, blockingStubFull)); - } - - @AfterMethod - public void aftertest() { - PublicMethed - .freedResource(asset010Address, testKeyForAssetIssue010, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(asset010Address, testKeyForAssetIssue010, 0, asset010Address, - blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean createAssetIssue(byte[] address, String name, Long totalSupply, Integer trxNum, - Integer icoNum, Long startTime, Long endTime, - Integer voteScore, String description, String url, Long fronzenAmount, Long frozenDay, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account search = PublicMethed.queryAccount(priKey, blockingStubFull); - - try { - AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - AssetIssueContract.FrozenSupply.Builder frozenBuilder = - AssetIssueContract.FrozenSupply - .newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - builder.addFrozenSupply(0, frozenBuilder); - - Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - logger.info(name); - return true; - } - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - - public boolean transferAsset(byte[] to, byte[] assertName, long amount, byte[] address, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.transferAsset(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return false; - } else { - Account search = queryAccount(ecKey, blockingStubFull); - return true; - } - - } - - /** - * constructor. - */ - - public boolean unFreezeAsset(byte[] addRess, String priKey) { - byte[] address = addRess; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - UnfreezeAssetContract.Builder builder = UnfreezeAssetContract - .newBuilder(); - ByteString byteAddress = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddress); - - UnfreezeAssetContract contract = builder.build(); - - Transaction transaction = blockingStubFull.unfreezeAsset(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public boolean participateAssetIssue(byte[] to, byte[] assertName, long amount, byte[] from, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - ParticipateAssetIssueContract.Builder builder = ParticipateAssetIssueContract - .newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(from); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - ParticipateAssetIssueContract contract = builder.build(); - - Transaction transaction = blockingStubFull.participateAssetIssue(contract); - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - logger.info(name); - return true; - } - } - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue011.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue011.java deleted file mode 100644 index cac82c366ec..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue011.java +++ /dev/null @@ -1,133 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAssetIssue011 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static final long sendAmount = 10000000000L; - private static final String updateMostLongName = Long.toString(now) + "w234567890123456789"; - private static String name = "testAssetIssue011_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - Long freeAssetNetLimit = 10000L; - Long publicFreeAssetNetLimit = 10000L; - String description = "just-test"; - String url = "https://github.com/tronprotocol/wallet-cli/"; - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] asset011Address = ecKey1.getAddress(); - String testKeyForAssetIssue011 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] transferAssetCreateAddress = ecKey2.getAddress(); - String transferAssetCreateKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKeyForAssetIssue011); - PublicMethed.printAddress(transferAssetCreateKey); - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Transfer asset to create account") - public void testTransferAssetCreateAccount() { - //get account - ecKey1 = new ECKey(Utils.getRandom()); - asset011Address = ecKey1.getAddress(); - testKeyForAssetIssue011 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - transferAssetCreateAddress = ecKey2.getAddress(); - transferAssetCreateKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - Assert.assertTrue(PublicMethed - .sendcoin(asset011Address, sendAmount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalance(asset011Address, 100000000L, 3, testKeyForAssetIssue011, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed - .createAssetIssue(asset011Address, name, totalSupply, 1, 1, start, end, 1, description, - url, freeAssetNetLimit, publicFreeAssetNetLimit, 1L, 1L, testKeyForAssetIssue011, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed.queryAccount(asset011Address, blockingStubFull); - ByteString assetAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - - //Transfer asset to create an account. - Assert.assertTrue(PublicMethed - .transferAsset(transferAssetCreateAddress, assetAccountId.toByteArray(), 1L, - asset011Address, testKeyForAssetIssue011, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account queryTransferAssetAccount = PublicMethed - .queryAccount(transferAssetCreateKey, blockingStubFull); - Assert.assertTrue(queryTransferAssetAccount.getAssetV2Count() == 1); - Assert.assertTrue(PublicMethed.updateAccount(asset011Address, Long.toString(now) - .getBytes(), testKeyForAssetIssue011, blockingStubFull)); - Assert.assertTrue(PublicMethed.updateAccount(transferAssetCreateAddress, updateMostLongName - .getBytes(), transferAssetCreateKey, blockingStubFull)); - queryTransferAssetAccount = PublicMethed.queryAccount(transferAssetCreateKey, blockingStubFull); - Assert.assertFalse(queryTransferAssetAccount.getAccountName().isEmpty()); - PublicMethed - .freedResource(asset011Address, testKeyForAssetIssue011, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(asset011Address, testKeyForAssetIssue011, 0, asset011Address, - blockingStubFull); - - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue012.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue012.java deleted file mode 100644 index 9e265d0ee33..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue012.java +++ /dev/null @@ -1,155 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountNetMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAssetIssue012 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static final long sendAmount = 10000000000L; - private static final long netCostMeasure = 200L; - private static String name = "AssetIssue012_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - Long freeAssetNetLimit = 10000L; - Long publicFreeAssetNetLimit = 10000L; - String description = "for case assetissue012"; - String url = "https://stest.assetissue012.url/"; - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] asset012Address = ecKey1.getAddress(); - String testKeyForAssetIssue012 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] transferAssetAddress = ecKey2.getAddress(); - String transferAssetCreateKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - logger.info(testKeyForAssetIssue012); - logger.info(transferAssetCreateKey); - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Transfer asset use token owner net") - public void testTransferAssetUseCreatorNet() { - //get account - ecKey1 = new ECKey(Utils.getRandom()); - asset012Address = ecKey1.getAddress(); - testKeyForAssetIssue012 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - transferAssetAddress = ecKey2.getAddress(); - transferAssetCreateKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - PublicMethed.printAddress(testKeyForAssetIssue012); - PublicMethed.printAddress(transferAssetCreateKey); - - Assert.assertTrue(PublicMethed - .sendcoin(asset012Address, sendAmount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalance(asset012Address, 100000000L, 3, testKeyForAssetIssue012, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed - .createAssetIssue(asset012Address, name, totalSupply, 1, 1, start, end, 1, description, - url, freeAssetNetLimit, publicFreeAssetNetLimit, 1L, 1L, testKeyForAssetIssue012, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed.queryAccount(asset012Address, blockingStubFull); - ByteString assetAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - - //Transfer asset to an account. - Assert.assertTrue(PublicMethed.transferAsset( - transferAssetAddress, assetAccountId.toByteArray(), 10000000L, asset012Address, - testKeyForAssetIssue012, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //Before transfer asset issue, query the net used from creator and transfer. - AccountNetMessage assetCreatorNet = PublicMethed - .getAccountNet(asset012Address, blockingStubFull); - AccountNetMessage assetTransferNet = PublicMethed - .getAccountNet(transferAssetAddress, blockingStubFull); - Long creatorBeforeNetUsed = assetCreatorNet.getNetUsed(); - Long transferBeforeFreeNetUsed = assetTransferNet.getFreeNetUsed(); - logger.info(Long.toString(creatorBeforeNetUsed)); - logger.info(Long.toString(transferBeforeFreeNetUsed)); - - //Transfer send some asset issue to default account, to test if this - // transaction use the creator net. - Assert.assertTrue(PublicMethed.transferAsset(toAddress, assetAccountId.toByteArray(), 1L, - transferAssetAddress, transferAssetCreateKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetCreatorNet = PublicMethed - .getAccountNet(asset012Address, blockingStubFull); - assetTransferNet = PublicMethed - .getAccountNet(transferAssetAddress, blockingStubFull); - Long creatorAfterNetUsed = assetCreatorNet.getNetUsed(); - Long transferAfterFreeNetUsed = assetTransferNet.getFreeNetUsed(); - logger.info(Long.toString(creatorAfterNetUsed)); - logger.info(Long.toString(transferAfterFreeNetUsed)); - - Assert.assertTrue(creatorAfterNetUsed - creatorBeforeNetUsed > netCostMeasure); - Assert.assertTrue(transferAfterFreeNetUsed - transferBeforeFreeNetUsed < netCostMeasure); - - PublicMethed - .freedResource(asset012Address, testKeyForAssetIssue012, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(asset012Address, testKeyForAssetIssue012, 0, asset012Address, - blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue013.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue013.java deleted file mode 100644 index ca0ce33895c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue013.java +++ /dev/null @@ -1,157 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountNetMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAssetIssue013 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static final long sendAmount = 10000000000L; - private static final long netCostMeasure = 200L; - private static String name = "AssetIssue013_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - Long freeAssetNetLimit = 300L; - Long publicFreeAssetNetLimit = 3000L; - String description = "for case assetissue013"; - String url = "https://stest.assetissue013.url/"; - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] asset013Address = ecKey1.getAddress(); - String testKeyForAssetIssue013 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] transferAssetAddress = ecKey2.getAddress(); - String transferAssetCreateKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Use transfer net when token owner has no enough net") - public void testWhenNoEnoughFreeAssetNetLimitUseTransferNet() { - - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] asset013Address = ecKey1.getAddress(); - final String testKeyForAssetIssue013 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ECKey ecKey2 = new ECKey(Utils.getRandom()); - final byte[] transferAssetAddress = ecKey2.getAddress(); - final String transferAssetCreateKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - logger.info(testKeyForAssetIssue013); - logger.info(transferAssetCreateKey); - - Assert.assertTrue(PublicMethed - .sendcoin(asset013Address, sendAmount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalance(asset013Address, 100000000L, 3, testKeyForAssetIssue013, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed - .createAssetIssue(asset013Address, name, totalSupply, 1, 1, start, end, 1, description, - url, freeAssetNetLimit, publicFreeAssetNetLimit, 1L, 1L, testKeyForAssetIssue013, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed.queryAccount(asset013Address, blockingStubFull); - ByteString assetAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - - //Transfer asset to an account. - Assert.assertTrue(PublicMethed.transferAsset( - transferAssetAddress, assetAccountId.toByteArray(), - 10000000L, asset013Address, testKeyForAssetIssue013, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //Transfer send some asset issue to default account, to test if this - // transaction use the creator net. - Assert.assertTrue(PublicMethed.transferAsset(toAddress, assetAccountId.toByteArray(), 1L, - transferAssetAddress, transferAssetCreateKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Before use transfer net, query the net used from creator and transfer. - AccountNetMessage assetCreatorNet = PublicMethed - .getAccountNet(asset013Address, blockingStubFull); - AccountNetMessage assetTransferNet = PublicMethed - .getAccountNet(transferAssetAddress, blockingStubFull); - Long creatorBeforeNetUsed = assetCreatorNet.getNetUsed(); - Long transferBeforeFreeNetUsed = assetTransferNet.getFreeNetUsed(); - logger.info(Long.toString(creatorBeforeNetUsed)); - logger.info(Long.toString(transferBeforeFreeNetUsed)); - - //Transfer send some asset issue to default account, to test if this - // transaction use the transaction free net. - Assert.assertTrue(PublicMethed.transferAsset(toAddress, assetAccountId.toByteArray(), 1L, - transferAssetAddress, transferAssetCreateKey, blockingStubFull)); - assetCreatorNet = PublicMethed - .getAccountNet(asset013Address, blockingStubFull); - assetTransferNet = PublicMethed - .getAccountNet(transferAssetAddress, blockingStubFull); - Long creatorAfterNetUsed = assetCreatorNet.getNetUsed(); - Long transferAfterFreeNetUsed = assetTransferNet.getFreeNetUsed(); - logger.info(Long.toString(creatorAfterNetUsed)); - logger.info(Long.toString(transferAfterFreeNetUsed)); - - Assert.assertTrue(creatorAfterNetUsed - creatorBeforeNetUsed < netCostMeasure); - Assert.assertTrue(transferAfterFreeNetUsed - transferBeforeFreeNetUsed > netCostMeasure); - - PublicMethed - .freedResource(asset013Address, testKeyForAssetIssue013, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(asset013Address, testKeyForAssetIssue013, 0, asset013Address, - blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue014.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue014.java deleted file mode 100644 index 4af6e9a1c72..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue014.java +++ /dev/null @@ -1,154 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountNetMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAssetIssue014 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static final long sendAmount = 10000000000L; - private static final long netCostMeasure = 200L; - private static String name = "AssetIssue014_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - Long freeAssetNetLimit = 3000L; - Long publicFreeAssetNetLimit = 300L; - String description = "for case assetissue014"; - String url = "https://stest.assetissue014.url/"; - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] asset014Address = ecKey1.getAddress(); - String testKeyForAssetIssue014 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] transferAssetAddress = ecKey2.getAddress(); - String transferAssetCreateKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - logger.info(testKeyForAssetIssue014); - logger.info(transferAssetCreateKey); - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Use transfer net when no enough public free asset net") - public void testWhenNoEnoughPublicFreeAssetNetLimitUseTransferNet() { - //get account - ecKey1 = new ECKey(Utils.getRandom()); - asset014Address = ecKey1.getAddress(); - testKeyForAssetIssue014 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - transferAssetAddress = ecKey2.getAddress(); - transferAssetCreateKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - Assert.assertTrue(PublicMethed - .sendcoin(asset014Address, sendAmount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed - .createAssetIssue(asset014Address, name, totalSupply, 1, 1, start, end, 1, description, - url, freeAssetNetLimit, publicFreeAssetNetLimit, 1L, 1L, testKeyForAssetIssue014, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed.queryAccount(asset014Address, blockingStubFull); - ByteString assetAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - - //Transfer asset to an account. - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed - .transferAsset(transferAssetAddress, assetAccountId.toByteArray(), 10000000L, - asset014Address, testKeyForAssetIssue014, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //Transfer send some asset issue to default account, to test if this - // transaction use the creator net. - Assert.assertTrue(PublicMethed.transferAsset(toAddress, assetAccountId.toByteArray(), 1L, - transferAssetAddress, transferAssetCreateKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //Before use transfer net, query the net used from creator and transfer. - AccountNetMessage assetCreatorNet = PublicMethed - .getAccountNet(asset014Address, blockingStubFull); - AccountNetMessage assetTransferNet = PublicMethed - .getAccountNet(transferAssetAddress, blockingStubFull); - Long creatorBeforeNetUsed = assetCreatorNet.getNetUsed(); - Long transferBeforeFreeNetUsed = assetTransferNet.getFreeNetUsed(); - logger.info(Long.toString(creatorBeforeNetUsed)); - logger.info(Long.toString(transferBeforeFreeNetUsed)); - - //Transfer send some asset issue to default account, to test if this - // transaction use the transaction free net. - Assert.assertTrue(PublicMethed.transferAsset(toAddress, assetAccountId.toByteArray(), 1L, - transferAssetAddress, transferAssetCreateKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetCreatorNet = PublicMethed - .getAccountNet(asset014Address, blockingStubFull); - assetTransferNet = PublicMethed - .getAccountNet(transferAssetAddress, blockingStubFull); - Long creatorAfterNetUsed = assetCreatorNet.getNetUsed(); - Long transferAfterFreeNetUsed = assetTransferNet.getFreeNetUsed(); - logger.info(Long.toString(creatorAfterNetUsed)); - logger.info(Long.toString(transferAfterFreeNetUsed)); - - Assert.assertTrue(creatorAfterNetUsed - creatorBeforeNetUsed < netCostMeasure); - Assert.assertTrue(transferAfterFreeNetUsed - transferBeforeFreeNetUsed > netCostMeasure); - - PublicMethed - .freedResource(asset014Address, testKeyForAssetIssue014, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(asset014Address, testKeyForAssetIssue014, 0, asset014Address, - blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue015.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue015.java deleted file mode 100644 index 3541d7fd191..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue015.java +++ /dev/null @@ -1,218 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountNetMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAssetIssue015 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static final long sendAmount = 10000000000L; - private static final long netCostMeasure = 200L; - private static String name = "AssetIssue015_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - Long freeAssetNetLimit = 30000L; - Long publicFreeAssetNetLimit = 30000L; - String description = "for case assetissue015"; - String url = "https://stest.assetissue015.url/"; - ByteString assetAccountId; - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] asset015Address = ecKey1.getAddress(); - String testKeyForAssetIssue015 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] transferAssetAddress = ecKey2.getAddress(); - String transferAssetCreateKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] newAddress = ecKey3.getAddress(); - String testKeyForNewAddress = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - logger.info(testKeyForAssetIssue015); - logger.info(transferAssetCreateKey); - logger.info(testKeyForNewAddress); - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Use transfer net when token owner has not enough bandwidth") - public void atestWhenCreatorHasNoEnoughBandwidthUseTransferNet() { - ecKey1 = new ECKey(Utils.getRandom()); - asset015Address = ecKey1.getAddress(); - testKeyForAssetIssue015 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - transferAssetAddress = ecKey2.getAddress(); - transferAssetCreateKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - ecKey3 = new ECKey(Utils.getRandom()); - newAddress = ecKey3.getAddress(); - testKeyForNewAddress = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - - Assert.assertTrue(PublicMethed - .sendcoin(asset015Address, sendAmount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed - .createAssetIssue(asset015Address, name, totalSupply, 1, 1, start, end, 1, description, - url, freeAssetNetLimit, publicFreeAssetNetLimit, 1L, 1L, testKeyForAssetIssue015, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed.queryAccount(asset015Address, blockingStubFull); - assetAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - - //Transfer asset to an account. - Assert.assertTrue(PublicMethed - .transferAsset(transferAssetAddress, assetAccountId.toByteArray(), 10000000L, - asset015Address, testKeyForAssetIssue015, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //Before use transfer net, query the net used from creator and transfer. - AccountNetMessage assetCreatorNet = PublicMethed - .getAccountNet(asset015Address, blockingStubFull); - AccountNetMessage assetTransferNet = PublicMethed - .getAccountNet(transferAssetAddress, blockingStubFull); - Long creatorBeforeFreeNetUsed = assetCreatorNet.getFreeNetUsed(); - Long transferBeforeFreeNetUsed = assetTransferNet.getFreeNetUsed(); - logger.info(Long.toString(creatorBeforeFreeNetUsed)); - logger.info(Long.toString(transferBeforeFreeNetUsed)); - - //Transfer send some asset issue to default account, to test if this - // transaction use the transaction free net. - Assert.assertTrue(PublicMethed.transferAsset(toAddress, assetAccountId.toByteArray(), 1L, - transferAssetAddress, transferAssetCreateKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetCreatorNet = PublicMethed - .getAccountNet(asset015Address, blockingStubFull); - assetTransferNet = PublicMethed - .getAccountNet(transferAssetAddress, blockingStubFull); - Long creatorAfterFreeNetUsed = assetCreatorNet.getFreeNetUsed(); - Long transferAfterFreeNetUsed = assetTransferNet.getFreeNetUsed(); - logger.info(Long.toString(creatorAfterFreeNetUsed)); - logger.info(Long.toString(transferAfterFreeNetUsed)); - - Assert.assertTrue(creatorAfterFreeNetUsed - creatorBeforeFreeNetUsed < netCostMeasure); - Assert.assertTrue(transferAfterFreeNetUsed - transferBeforeFreeNetUsed > netCostMeasure); - } - - @Test(enabled = true, description = "Use balance when transfer has not enough net") - public void btestWhenTransferHasNoEnoughBandwidthUseBalance() { - Integer i = 0; - AccountNetMessage assetTransferNet = PublicMethed - .getAccountNet(transferAssetAddress, blockingStubFull); - while (assetTransferNet.getNetUsed() < 4700 && i++ < 200) { - PublicMethed.transferAsset(toAddress, assetAccountId.toByteArray(), 1L, - transferAssetAddress, transferAssetCreateKey, blockingStubFull); - assetTransferNet = PublicMethed - .getAccountNet(transferAssetAddress, blockingStubFull); - } - - logger.info(Long.toString(assetTransferNet.getFreeNetUsed())); - Assert.assertTrue(assetTransferNet.getFreeNetUsed() >= 4700); - - Assert.assertTrue(PublicMethed.sendcoin(transferAssetAddress, - 20000000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account transferAccount = PublicMethed.queryAccount(transferAssetCreateKey, blockingStubFull); - Long beforeBalance = transferAccount.getBalance(); - logger.info(Long.toString(beforeBalance)); - - Assert.assertTrue(PublicMethed.transferAsset(toAddress, assetAccountId.toByteArray(), 1L, - transferAssetAddress, transferAssetCreateKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - transferAccount = PublicMethed.queryAccount(transferAssetCreateKey, blockingStubFull); - Long afterBalance = transferAccount.getBalance(); - logger.info(Long.toString(afterBalance)); - - Assert.assertTrue(beforeBalance - afterBalance > 2000); - } - - @Test(enabled = true, description = "Transfer asset use bandwidth when freeze balance") - public void ctestWhenFreezeBalanceUseNet() { - Assert.assertTrue(PublicMethed.freezeBalance(transferAssetAddress, 5000000, - 3, transferAssetCreateKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - AccountNetMessage assetTransferNet = PublicMethed - .getAccountNet(transferAssetAddress, blockingStubFull); - Account transferAccount = PublicMethed.queryAccount(transferAssetCreateKey, blockingStubFull); - - final Long transferNetUsedBefore = assetTransferNet.getNetUsed(); - final Long transferBalanceBefore = transferAccount.getBalance(); - logger.info("before " + Long.toString(transferBalanceBefore)); - - Assert.assertTrue(PublicMethed.transferAsset(toAddress, assetAccountId.toByteArray(), 1L, - transferAssetAddress, transferAssetCreateKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetTransferNet = PublicMethed - .getAccountNet(transferAssetAddress, blockingStubFull); - transferAccount = PublicMethed.queryAccount(transferAssetCreateKey, blockingStubFull); - final Long transferNetUsedAfter = assetTransferNet.getNetUsed(); - final Long transferBalanceAfter = transferAccount.getBalance(); - logger.info("after " + Long.toString(transferBalanceAfter)); - - Assert.assertTrue(transferBalanceAfter - transferBalanceBefore == 0); - Assert.assertTrue(transferNetUsedAfter - transferNetUsedBefore > 200); - - - } - - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(asset015Address, testKeyForAssetIssue015, fromAddress, blockingStubFull); - PublicMethed - .freedResource(transferAssetAddress, transferAssetCreateKey, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue016.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue016.java deleted file mode 100644 index 17838c49434..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue016.java +++ /dev/null @@ -1,236 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AccountNetMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAssetIssue016 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static final long sendAmount = 10000000000L; - private static final long netCostMeasure = 200L; - private static String name = "AssetIssue016_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - Long freeAssetNetLimit = 30000L; - Long publicFreeAssetNetLimit = 30000L; - String description = "for case assetissue016"; - String url = "https://stest.assetissue016.url/"; - ByteString assetAccountId; - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] asset016Address = ecKey1.getAddress(); - String testKeyForAssetIssue016 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] transferAssetAddress = ecKey2.getAddress(); - String transferAssetCreateKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private ManagedChannel channelSoliInFull = null; - private ManagedChannel channelPbft = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSoliInFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPbft = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String soliInFullnode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - private String soliInPbft = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(2); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelSoliInFull = ManagedChannelBuilder.forTarget(soliInFullnode) - .usePlaintext() - .build(); - blockingStubSoliInFull = WalletSolidityGrpc.newBlockingStub(channelSoliInFull); - - channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext() - .build(); - blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); - } - - @Test(enabled = true, description = "Get asset issue net resource") - public void test01GetAssetIssueNet() { - //get account - ecKey1 = new ECKey(Utils.getRandom()); - asset016Address = ecKey1.getAddress(); - testKeyForAssetIssue016 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - transferAssetAddress = ecKey2.getAddress(); - transferAssetCreateKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - PublicMethed.printAddress(testKeyForAssetIssue016); - PublicMethed.printAddress(transferAssetCreateKey); - - Assert.assertTrue(PublicMethed - .sendcoin(asset016Address, sendAmount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed - .createAssetIssue(asset016Address, name, totalSupply, 1, 1, start, end, 1, description, - url, freeAssetNetLimit, publicFreeAssetNetLimit, 1L, 1L, testKeyForAssetIssue016, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed.queryAccount(asset016Address, blockingStubFull); - assetAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - - AccountNetMessage assetIssueInfo = PublicMethed - .getAccountNet(asset016Address, blockingStubFull); - Assert.assertTrue(assetIssueInfo.getAssetNetLimitCount() == 1); - Assert.assertTrue(assetIssueInfo.getAssetNetUsedCount() == 1); - Assert.assertFalse(assetIssueInfo.getAssetNetLimitMap().isEmpty()); - Assert.assertFalse(assetIssueInfo.getAssetNetUsedMap().isEmpty()); - - GrpcAPI.BytesMessage request = GrpcAPI.BytesMessage.newBuilder() - .setValue(assetAccountId).build(); - AssetIssueContract assetIssueByName = blockingStubFull.getAssetIssueByName(request); - Assert.assertTrue(assetIssueByName.getFreeAssetNetLimit() == freeAssetNetLimit); - Assert.assertTrue(assetIssueByName.getPublicFreeAssetNetLimit() == publicFreeAssetNetLimit); - Assert.assertTrue(assetIssueByName.getPublicLatestFreeNetTime() == 0); - assetIssueInfo.hashCode(); - assetIssueInfo.getSerializedSize(); - assetIssueInfo.equals(assetIssueInfo); - - PublicMethed.transferAsset(transferAssetAddress, assetAccountId.toByteArray(), 1000L, - asset016Address, testKeyForAssetIssue016, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.transferAsset(toAddress, assetAccountId.toByteArray(), 100L, - transferAssetAddress, transferAssetCreateKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetIssueByName = blockingStubFull.getAssetIssueByName(request); - Assert.assertTrue(assetIssueByName.getPublicLatestFreeNetTime() == 0); - Assert.assertTrue(assetIssueByName.getPublicFreeAssetNetUsage() == 0); - - Assert.assertTrue(PublicMethed.freezeBalance(asset016Address, 30000000L, - 3, testKeyForAssetIssue016, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.transferAsset(toAddress, assetAccountId.toByteArray(), 100L, - transferAssetAddress, transferAssetCreateKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetIssueByName = blockingStubFull.getAssetIssueByName(request); - Assert.assertTrue(assetIssueByName.getPublicLatestFreeNetTime() > 0); - Assert.assertTrue(assetIssueByName.getPublicFreeAssetNetUsage() > 150); - - PublicMethed - .freedResource(asset016Address, testKeyForAssetIssue016, fromAddress, blockingStubFull); - - - } - - @Test(enabled = true, description = "Get asset issue by name from Solidity") - public void test02GetAssetIssueByNameFromSolidity() { - Assert.assertEquals(PublicMethed.getAssetIssueByNameFromSolidity(name, - blockingStubSolidity).getTotalSupply(), totalSupply); - } - - @Test(enabled = true, description = "Get asset issue by name from PBFT") - public void test03GetAssetIssueByNameFromPbft() { - Assert.assertEquals(PublicMethed.getAssetIssueByNameFromSolidity(name, - blockingStubPbft).getTotalSupply(), totalSupply); - } - - @Test(enabled = true, description = "Get asset issue list from PBFT") - public void test04GetAssetIssueListFromPbft() { - Assert.assertTrue(PublicMethed.listAssetIssueFromSolidity( - blockingStubPbft).get().getAssetIssueCount() >= 1); - } - - - @Test(enabled = true, description = "Get asset issue list from Solidity") - public void test05GetAssetIssueListFromSolidity() { - Assert.assertTrue(PublicMethed.listAssetIssueFromSolidity( - blockingStubSoliInFull).get().getAssetIssueCount() >= 1); - Assert.assertTrue(PublicMethed.listAssetIssueFromSolidity( - blockingStubSolidity).get().getAssetIssueCount() >= 1); - } - - @Test(enabled = true, description = "Get asset issue list paginated from PBFT") - public void test06GetAssetIssetListPaginatedFromPbft() { - Assert.assertTrue(PublicMethed.listAssetIssuepaginatedFromSolidity( - blockingStubPbft, 0L, 1L).get().getAssetIssueCount() == 1); - } - - - @Test(enabled = true, description = "Get asset issue list paginated from Solidity") - public void test05GetAssetIssueListPaginatedFromSolidity() { - Assert.assertTrue(PublicMethed.listAssetIssuepaginatedFromSolidity( - blockingStubSolidity, 0L, 1L).get().getAssetIssueCount() == 1); - Assert.assertTrue(PublicMethed.listAssetIssuepaginatedFromSolidity( - blockingStubSoliInFull, 0L, 1L).get().getAssetIssueCount() == 1); - } - - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelPbft != null) { - channelPbft.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSoliInFull != null) { - channelSoliInFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue020.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue020.java deleted file mode 100644 index c4c4af4bfce..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue020.java +++ /dev/null @@ -1,225 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.contract.AssetIssueContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAssetIssue020 { - - private static final long now = System.currentTimeMillis(); - private static final String name = "Assetissue020_" + Long.toString(now); - private static final String char33Name = "To_long_asset_name_a" + Long.toString(now); - private static final long totalSupply = now; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - String description = "just-test"; - String url = "https://github.com/tronprotocol/wallet-cli/"; - Account assetIssue020Account; - ByteString assetAccountId; - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] asset020Address = ecKey1.getAddress(); - String asset020Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] asset020SecondAddress = ecKey2.getAddress(); - String asset020SecondKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private ManagedChannel channelSoliInFull = null; - private ManagedChannel channelPbft = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSoliInFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPbft = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String soliInFullnode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - private String soliInPbft = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(2); - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelSoliInFull = ManagedChannelBuilder.forTarget(soliInFullnode) - .usePlaintext() - .build(); - blockingStubSoliInFull = WalletSolidityGrpc.newBlockingStub(channelSoliInFull); - - channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext() - .build(); - blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); - } - - @Test(enabled = true, description = "Asset issue support precision") - public void test01AssetIssueSupportPrecision() { - //get account - ecKey1 = new ECKey(Utils.getRandom()); - asset020Address = ecKey1.getAddress(); - asset020Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.printAddress(asset020Key); - - ecKey2 = new ECKey(Utils.getRandom()); - asset020SecondAddress = ecKey2.getAddress(); - asset020SecondKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - PublicMethed.printAddress(asset020SecondKey); - logger.info(name); - - Assert.assertTrue(PublicMethed.sendcoin(asset020Address, 2048000000, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(asset020SecondAddress, 2048000000, fromAddress, - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Can create 32 char token name. - Long start = System.currentTimeMillis() + 2000000; - Long end = System.currentTimeMillis() + 1000000000; - - //When precision is -1, can not create asset issue - Assert.assertFalse(PublicMethed.createAssetIssue(asset020Address, - name, totalSupply, 1, 1, -1, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, asset020Key, blockingStubFull)); - - //When precision is 7, can not create asset issue - Assert.assertFalse(PublicMethed.createAssetIssue(asset020Address, - name, totalSupply, 1, 1, 7, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, asset020Key, blockingStubFull)); - - //When precision is 6, is equal to default. - Assert.assertTrue(PublicMethed.createAssetIssue(asset020Address, - name, totalSupply, 1, 1, 6, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, asset020Key, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed.queryAccount(asset020Address, blockingStubFull); - assetAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - - AssetIssueContractOuterClass.AssetIssueContract assetIssueInfo = PublicMethed - .getAssetIssueByName(name, blockingStubFull); - final Integer preCisionByName = assetIssueInfo.getPrecision(); - final Long TotalSupplyByName = assetIssueInfo.getTotalSupply(); - - assetIssueInfo = PublicMethed.getAssetIssueById(ByteArray.toStr(assetAccountId - .toByteArray()), blockingStubFull); - final Integer preCisionById = assetIssueInfo.getPrecision(); - final Long TotalSupplyById = assetIssueInfo.getTotalSupply(); - - assetIssueInfo = PublicMethed.getAssetIssueListByName(name, blockingStubFull) - .get().getAssetIssue(0); - final Integer preCisionByListName = assetIssueInfo.getPrecision(); - final Long TotalSupplyByListName = assetIssueInfo.getTotalSupply(); - - logger.info("precision is " + preCisionByName); - logger.info("precision is " + preCisionById); - logger.info("precision is " + preCisionByListName); - logger.info("totalsupply is " + TotalSupplyByName); - logger.info("totalsupply is " + TotalSupplyById); - logger.info("totalsupply is " + TotalSupplyByListName); - Assert.assertEquals(preCisionById, preCisionByListName); - Assert.assertEquals(preCisionById, preCisionByName); - Assert.assertEquals(TotalSupplyById, TotalSupplyByListName); - Assert.assertEquals(TotalSupplyById, TotalSupplyByName); - - //When precision is 6, is equal to default. - Assert.assertTrue(PublicMethed.createAssetIssue(asset020SecondAddress, - name, totalSupply, 1, 1, 1, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, asset020SecondKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetIssueInfo = PublicMethed.getAssetIssueByName(name, blockingStubFull); - Assert.assertTrue(assetIssueInfo.getName().isEmpty()); - - } - - @Test(enabled = true, description = "Get asset issue by id from Solidity") - public void test02GetAssetIssueByidFromSolidity() { - Assert.assertEquals(PublicMethed.getAssetIssueById(ByteArray.toStr(assetAccountId - .toByteArray()), blockingStubFull), - PublicMethed.getAssetIssueByIdFromSolidity(ByteArray.toStr(assetAccountId - .toByteArray()), blockingStubSolidity)); - Assert.assertEquals(PublicMethed.getAssetIssueById(ByteArray.toStr(assetAccountId - .toByteArray()), blockingStubFull), - PublicMethed.getAssetIssueByIdFromSolidity(ByteArray.toStr(assetAccountId - .toByteArray()), blockingStubSoliInFull)); - } - - @Test(enabled = true, description = "Get asset issue by id from PBFT") - public void test03GetAssetIssueByIdFromPbft() { - Assert.assertEquals(PublicMethed.getAssetIssueById(ByteArray.toStr(assetAccountId - .toByteArray()), blockingStubFull), - PublicMethed.getAssetIssueByIdFromSolidity(ByteArray.toStr(assetAccountId - .toByteArray()), blockingStubPbft)); - } - - @Test(enabled = true, description = "Get asset issue list by name from Solidity") - public void test04GetAssetIssueListByNameFromSolidity() { - Assert.assertEquals(PublicMethed.getAssetIssueListByNameFromSolidity(name, - blockingStubSolidity).get().getAssetIssueList().get(0).getTotalSupply(), totalSupply); - } - - @Test(enabled = true, description = "Get asset issue list by name from PBFT") - public void test05GetAssetIssueListByNameFromPbft() { - Assert.assertEquals(PublicMethed.getAssetIssueListByNameFromSolidity(name, - blockingStubPbft).get().getAssetIssue(0).getTotalSupply(), totalSupply); - } - - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelPbft != null) { - channelPbft.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSoliInFull != null) { - channelSoliInFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue017.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue017.java deleted file mode 100644 index f46f741ac60..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue017.java +++ /dev/null @@ -1,347 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue.exchangeandtoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AssetIssueList; -import org.tron.api.GrpcAPI.PaginatedMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.db.Manager; -import org.tron.protos.Protocol; -import org.tron.protos.contract.AssetIssueContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class WalletTestAssetIssue017 { - - private static final long sendAmount = 10000000000L; - private static final long netCostMeasure = 200L; - private static long start; - private static long end; - private static long now = System.currentTimeMillis(); - private static String name = "AssetIssue017_" + Long.toString(now); - private static long totalSupply = now; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - Long freeAssetNetLimit = 30000L; - Long publicFreeAssetNetLimit = 30000L; - String description = "for case assetissue017"; - String url = "https://stest.assetissue016.url/"; - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] asset017Address = ecKey1.getAddress(); - String testKeyForAssetIssue017 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Manager dbManager; - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - /** - * constructor. - */ - - public static Boolean createAssetIssue(byte[] address, String name, Long totalSupply, - Integer trxNum, Integer icoNum, Long startTime, Long endTime, Integer voteScore, - String description, String url, Long freeAssetNetLimit, Long publicFreeAssetNetLimit, - Long fronzenAmount, Long frozenDay, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - //Protocol.Account search = queryAccount(ecKey, blockingStubFull); - try { - AssetIssueContractOuterClass.AssetIssueContract.Builder builder = - AssetIssueContractOuterClass.AssetIssueContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - builder.setFreeAssetNetLimit(freeAssetNetLimit); - builder.setPublicFreeAssetNetLimit(publicFreeAssetNetLimit); - AssetIssueContractOuterClass.AssetIssueContract.FrozenSupply.Builder frozenBuilder = - AssetIssueContractOuterClass.AssetIssueContract.FrozenSupply.newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - builder.addFrozenSupply(0, frozenBuilder); - - Protocol.Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info("failed reason is " + ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - return true; - } - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - /** - * constructor. - */ - - public static Protocol.Transaction signTransaction(ECKey ecKey, - Protocol.Transaction transaction) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - if (ecKey == null || ecKey.getPrivKey() == null) { - //logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - logger.info(testKeyForAssetIssue017); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true) - public void atestGetPaginatedAssetIssueList() { - //get account - ecKey1 = new ECKey(Utils.getRandom()); - asset017Address = ecKey1.getAddress(); - testKeyForAssetIssue017 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - Assert.assertTrue(PublicMethed - .sendcoin(asset017Address, sendAmount, fromAddress, testKey002, blockingStubFull)); - start = System.currentTimeMillis() + 2000; - end = System.currentTimeMillis() + 1000000000; - now = System.currentTimeMillis(); - name = "AssetIssue017_" + Long.toString(now); - totalSupply = now; - Assert.assertTrue(createAssetIssue(asset017Address, name, totalSupply, 1, 1, - start, end, 1, description, url, freeAssetNetLimit, publicFreeAssetNetLimit, 1L, - 1L, testKeyForAssetIssue017, blockingStubFull)); - - Integer offset = 0; - Integer limit = 100; - - PaginatedMessage.Builder pageMessageBuilder = PaginatedMessage.newBuilder(); - pageMessageBuilder.setOffset(offset); - pageMessageBuilder.setLimit(limit); - - AssetIssueList assetIssueList = blockingStubFull - .getPaginatedAssetIssueList(pageMessageBuilder.build()); - Optional assetIssueListPaginated = Optional.ofNullable(assetIssueList); - logger.info(Long.toString(assetIssueListPaginated.get().getAssetIssueCount())); - Assert.assertTrue(assetIssueListPaginated.get().getAssetIssueCount() >= 1); - for (Integer i = 0; i < assetIssueListPaginated.get().getAssetIssueCount(); i++) { - Assert.assertTrue(assetIssueListPaginated.get().getAssetIssue(i).getTotalSupply() > 0); - } - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - } - - @Test(enabled = true) - public void btestGetPaginatedAssetIssueListException() { - //offset is 0, limit is 0. - Integer offset = 0; - Integer limit = 0; - PaginatedMessage.Builder pageMessageBuilder = PaginatedMessage.newBuilder(); - pageMessageBuilder.setOffset(offset); - pageMessageBuilder.setLimit(limit); - AssetIssueList assetIssueList = blockingStubFull - .getPaginatedAssetIssueList(pageMessageBuilder.build()); - Optional assetIssueListPaginated = Optional.ofNullable(assetIssueList); - logger.info(Long.toString(assetIssueListPaginated.get().getAssetIssueCount())); - Assert.assertTrue(assetIssueListPaginated.get().getAssetIssueCount() == 0); - - //offset is -1, limit is 100. - offset = -1; - limit = 100; - pageMessageBuilder = PaginatedMessage.newBuilder(); - pageMessageBuilder.setOffset(offset); - pageMessageBuilder.setLimit(limit); - assetIssueList = blockingStubFull - .getPaginatedAssetIssueList(pageMessageBuilder.build()); - assetIssueListPaginated = Optional.ofNullable(assetIssueList); - logger.info(Long.toString(assetIssueListPaginated.get().getAssetIssueCount())); - Assert.assertTrue(assetIssueListPaginated.get().getAssetIssueCount() == 0); - - //offset is 0, limit is -1. - offset = 0; - limit = -1; - pageMessageBuilder = PaginatedMessage.newBuilder(); - pageMessageBuilder.setOffset(offset); - pageMessageBuilder.setLimit(limit); - assetIssueList = blockingStubFull - .getPaginatedAssetIssueList(pageMessageBuilder.build()); - assetIssueListPaginated = Optional.ofNullable(assetIssueList); - logger.info(Long.toString(assetIssueListPaginated.get().getAssetIssueCount())); - Assert.assertTrue(assetIssueListPaginated.get().getAssetIssueCount() == 0); - - //offset is 0, limit is 50. - offset = 0; - limit = 50; - pageMessageBuilder = PaginatedMessage.newBuilder(); - pageMessageBuilder.setOffset(offset); - pageMessageBuilder.setLimit(limit); - assetIssueList = blockingStubFull - .getPaginatedAssetIssueList(pageMessageBuilder.build()); - assetIssueListPaginated = Optional.ofNullable(assetIssueList); - logger.info(Long.toString(assetIssueListPaginated.get().getAssetIssueCount())); - Assert.assertTrue(assetIssueListPaginated.get().getAssetIssueCount() >= 1); - } - - @Test(enabled = true) - public void ctestGetPaginatedAssetIssueListOnSolidityNode() { - - Integer offset = 0; - Integer limit = 100; - - PaginatedMessage.Builder pageMessageBuilder = PaginatedMessage.newBuilder(); - pageMessageBuilder.setOffset(offset); - pageMessageBuilder.setLimit(limit); - Assert.assertTrue(PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, - blockingStubSolidity)); - AssetIssueList assetIssueList = blockingStubSolidity - .getPaginatedAssetIssueList(pageMessageBuilder.build()); - Optional assetIssueListPaginated = Optional.ofNullable(assetIssueList); - - logger.info(Long.toString(assetIssueListPaginated.get().getAssetIssueCount())); - Assert.assertTrue(assetIssueListPaginated.get().getAssetIssueCount() >= 1); - for (Integer i = 0; i < assetIssueListPaginated.get().getAssetIssueCount(); i++) { - Assert.assertTrue(assetIssueListPaginated.get().getAssetIssue(i).getTotalSupply() > 0); - } - } - - @Test(enabled = true) - public void dtestGetPaginatedAssetIssueListExceptionOnSolidityNode() { - //offset is 0, limit is 0. - Integer offset = 0; - Integer limit = 0; - PaginatedMessage.Builder pageMessageBuilder = PaginatedMessage.newBuilder(); - pageMessageBuilder.setOffset(offset); - pageMessageBuilder.setLimit(limit); - AssetIssueList assetIssueList = blockingStubSolidity - .getPaginatedAssetIssueList(pageMessageBuilder.build()); - Optional assetIssueListPaginated = Optional.ofNullable(assetIssueList); - logger.info(Long.toString(assetIssueListPaginated.get().getAssetIssueCount())); - Assert.assertTrue(assetIssueListPaginated.get().getAssetIssueCount() == 0); - - //offset is 0, limit is -1. - offset = 0; - limit = -1; - pageMessageBuilder = PaginatedMessage.newBuilder(); - pageMessageBuilder.setOffset(offset); - pageMessageBuilder.setLimit(limit); - assetIssueList = blockingStubSolidity - .getPaginatedAssetIssueList(pageMessageBuilder.build()); - assetIssueListPaginated = Optional.ofNullable(assetIssueList); - logger.info(Long.toString(assetIssueListPaginated.get().getAssetIssueCount())); - Assert.assertTrue(assetIssueListPaginated.get().getAssetIssueCount() == 0); - - //offset is 0, limit is 50. - offset = 0; - limit = 50; - pageMessageBuilder = PaginatedMessage.newBuilder(); - pageMessageBuilder.setOffset(offset); - pageMessageBuilder.setLimit(limit); - assetIssueList = blockingStubSolidity - .getPaginatedAssetIssueList(pageMessageBuilder.build()); - assetIssueListPaginated = Optional.ofNullable(assetIssueList); - logger.info(Long.toString(assetIssueListPaginated.get().getAssetIssueCount())); - Assert.assertTrue(assetIssueListPaginated.get().getAssetIssueCount() >= 1); - - //offset is 0, limit is 1000. - offset = 0; - limit = 1000; - pageMessageBuilder = PaginatedMessage.newBuilder(); - pageMessageBuilder.setOffset(offset); - pageMessageBuilder.setLimit(limit); - assetIssueList = blockingStubSolidity - .getPaginatedAssetIssueList(pageMessageBuilder.build()); - assetIssueListPaginated = Optional.ofNullable(assetIssueList); - logger.info(Long.toString(assetIssueListPaginated.get().getAssetIssueCount())); - Assert.assertTrue(assetIssueListPaginated.get().getAssetIssueCount() >= 1); - - //offset is -1, limit is 100. - offset = -1; - limit = 100; - pageMessageBuilder = PaginatedMessage.newBuilder(); - pageMessageBuilder.setOffset(offset); - pageMessageBuilder.setLimit(limit); - assetIssueList = blockingStubSolidity - .getPaginatedAssetIssueList(pageMessageBuilder.build()); - assetIssueListPaginated = Optional.ofNullable(assetIssueList); - logger.info(Long.toString(assetIssueListPaginated.get().getAssetIssueCount())); - Assert.assertTrue(assetIssueListPaginated.get().getAssetIssueCount() == 0); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue018.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue018.java deleted file mode 100644 index f21ce45a756..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue018.java +++ /dev/null @@ -1,238 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue.exchangeandtoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AssetIssueList; -import org.tron.api.GrpcAPI.BytesMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAssetIssue018 { - - private static final long now = System.currentTimeMillis(); - private static final String name = "Asset008_" + Long.toString(now); - private static final String char32Name = "To_long_asset_name_" + Long.toString(now); - private static final String char33Name = "To_long_asset_name_a" + Long.toString(now); - private static final long totalSupply = now; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - String description = "just-test"; - String url = "https://github.com/tronprotocol/wallet-cli/"; - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] assetAccount1Address = ecKey1.getAddress(); - String assetAccount1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] assetAccount2Address = ecKey2.getAddress(); - String assetAccount2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] assetAccount3Address = ecKey3.getAddress(); - String assetAccount3Key = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] assetAccount4Address = ecKey4.getAddress(); - String assetAccount4Key = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - ECKey ecKey5 = new ECKey(Utils.getRandom()); - byte[] assetAccount5Address = ecKey5.getAddress(); - String assetAccount5Key = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); - ECKey ecKey6 = new ECKey(Utils.getRandom()); - byte[] assetAccount6Address = ecKey6.getAddress(); - String assetAccount6Key = ByteArray.toHexString(ecKey6.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(1); - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - PublicMethed.printAddress(assetAccount1Key); - PublicMethed.printAddress(assetAccount2Key); - PublicMethed.printAddress(assetAccount3Key); - PublicMethed.printAddress(assetAccount4Key); - PublicMethed.printAddress(assetAccount5Key); - PublicMethed.printAddress(assetAccount6Key); - } - - @Test(enabled = true) - public void test1AssetIssueNameBelow32Char() { - - ecKey4 = new ECKey(Utils.getRandom()); - assetAccount4Address = ecKey4.getAddress(); - assetAccount4Key = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - - ecKey5 = new ECKey(Utils.getRandom()); - assetAccount5Address = ecKey5.getAddress(); - assetAccount5Key = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); - - ecKey6 = new ECKey(Utils.getRandom()); - assetAccount6Address = ecKey6.getAddress(); - assetAccount6Key = ByteArray.toHexString(ecKey6.getPrivKeyBytes()); - - Assert.assertTrue(PublicMethed.sendcoin(assetAccount4Address, 2048000000, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(assetAccount5Address, 2048000000, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(assetAccount6Address, 2048000000, fromAddress, - testKey002, blockingStubFull)); - - //Can create 32 char token name. - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed.createAssetIssue(assetAccount4Address, - char32Name, totalSupply, 1, 1, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, assetAccount4Key, blockingStubFull)); - - //Can't create 33 char token name. - start = System.currentTimeMillis() + 2000; - end = System.currentTimeMillis() + 1000000000; - Assert.assertFalse(PublicMethed.createAssetIssue(assetAccount5Address, - char33Name, totalSupply, 1, 1, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, assetAccount5Key, blockingStubFull)); - - // - start = System.currentTimeMillis() + 2000; - end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed.createAssetIssue(assetAccount6Address, - char32Name, totalSupply, 1, 1, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, assetAccount6Key, blockingStubFull)); - - } - - @Test(enabled = true) - public void test2SameAssetissueName() { - //get account - ecKey1 = new ECKey(Utils.getRandom()); - assetAccount1Address = ecKey1.getAddress(); - assetAccount1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - assetAccount2Address = ecKey2.getAddress(); - assetAccount2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - ecKey3 = new ECKey(Utils.getRandom()); - assetAccount3Address = ecKey3.getAddress(); - assetAccount3Key = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - - logger.info(name); - logger.info("total supply is " + Long.toString(totalSupply)); - //send coin to the new account - Assert.assertTrue(PublicMethed.sendcoin(assetAccount1Address, 2048000000, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(assetAccount2Address, 2048000000, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(assetAccount3Address, 2048000000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Create 3 the same name token. - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed.createAssetIssue(assetAccount1Address, - name, totalSupply, 1, 1, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, assetAccount1Key, blockingStubFull)); - start = System.currentTimeMillis() + 2000; - end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed.createAssetIssue(assetAccount2Address, - name, totalSupply, 2, 2, start, end, 2, description, url, - 3000L, 3000L, 2L, 2L, assetAccount2Key, blockingStubFull)); - start = System.currentTimeMillis() + 2000; - end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed.createAssetIssue(assetAccount3Address, - name, totalSupply, 3, 3, start, end, 3, description, url, - 4000L, 4000L, 3L, 3L, assetAccount3Key, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Get asset issue by name - String asset1Name = name; - ByteString assetNameBs = ByteString.copyFrom(asset1Name.getBytes()); - - BytesMessage request = BytesMessage.newBuilder().setValue(assetNameBs).build(); - - AssetIssueList assetIssueList = blockingStubFull.getAssetIssueListByName(request); - Assert.assertTrue(assetIssueList.getAssetIssueCount() == 3); - for (AssetIssueContract assetIssue : assetIssueList.getAssetIssueList()) { - Assert.assertTrue(assetIssue.getTotalSupply() == totalSupply); - - } - - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed.queryAccount(assetAccount1Key, blockingStubFull); - final ByteString assetAccount1Id = getAssetIdFromThisAccount.getAssetIssuedID(); - - getAssetIdFromThisAccount = PublicMethed.queryAccount(assetAccount2Key, blockingStubFull); - final ByteString assetAccount2Id = getAssetIdFromThisAccount.getAssetIssuedID(); - - getAssetIdFromThisAccount = PublicMethed.queryAccount(assetAccount3Key, blockingStubFull); - final ByteString assetAccount3Id = getAssetIdFromThisAccount.getAssetIssuedID(); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Transfer asset issue. - Assert.assertTrue(PublicMethed.transferAsset(assetAccount2Address, assetAccount1Id - .toByteArray(), 1L, assetAccount1Address, assetAccount1Key, blockingStubFull)); - - Assert.assertTrue(PublicMethed.transferAsset(assetAccount3Address, assetAccount2Id - .toByteArray(), 2L, assetAccount2Address, assetAccount2Key, blockingStubFull)); - - Assert.assertTrue(PublicMethed.transferAsset(assetAccount1Address, assetAccount3Id - .toByteArray(), 3L, assetAccount3Address, assetAccount3Key, blockingStubFull)); - - Assert.assertFalse(PublicMethed.transferAsset(assetAccount1Address, assetAccount2Id - .toByteArray(), 3L, assetAccount3Address, assetAccount3Key, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //Participate asset issue. - Assert.assertTrue(PublicMethed.participateAssetIssue(assetAccount3Address, assetAccount3Id - .toByteArray(), 1L, assetAccount2Address, assetAccount2Key, blockingStubFull)); - - Assert.assertTrue(PublicMethed.participateAssetIssue(assetAccount1Address, assetAccount1Id - .toByteArray(), 2L, assetAccount3Address, assetAccount3Key, blockingStubFull)); - - Assert.assertTrue(PublicMethed.participateAssetIssue(assetAccount2Address, assetAccount2Id - .toByteArray(), 3L, assetAccount1Address, assetAccount1Key, blockingStubFull)); - - Assert.assertFalse(PublicMethed.participateAssetIssue(assetAccount2Address, assetAccount3Id - .toByteArray(), 3L, assetAccount1Address, assetAccount1Key, blockingStubFull)); - - - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue019.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue019.java deleted file mode 100644 index 80e8f990e1e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/exchangeandtoken/WalletTestAssetIssue019.java +++ /dev/null @@ -1,171 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue.exchangeandtoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAssetIssue019 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = "just-test"; - String url = "https://github.com/tronprotocol/wallet-cli/"; - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] asset019Address = ecKey1.getAddress(); - String asset019Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] asset019SecondAddress = ecKey2.getAddress(); - String asset019SecondKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void testCanNotCreateTokenNameByTrx() { - //get account - ecKey1 = new ECKey(Utils.getRandom()); - asset019Address = ecKey1.getAddress(); - asset019Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.printAddress(asset019Key); - - ecKey2 = new ECKey(Utils.getRandom()); - asset019SecondAddress = ecKey2.getAddress(); - asset019SecondKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - PublicMethed.printAddress(asset019SecondKey); - - Assert.assertTrue(PublicMethed.sendcoin(asset019Address, 2048000000, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(asset019SecondAddress, 2048000000, fromAddress, - testKey002, blockingStubFull)); - - //Can create 32 char token name. - Long start = System.currentTimeMillis() + 20000000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertFalse(PublicMethed.createAssetIssue(asset019Address, - "trx", totalSupply, 1, 1, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, asset019Key, blockingStubFull)); - - Assert.assertFalse(PublicMethed.createAssetIssue(asset019Address, - "TRX", totalSupply, 1, 1, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, asset019Key, blockingStubFull)); - - Assert.assertFalse(PublicMethed.createAssetIssue(asset019Address, - "Trx", totalSupply, 1, 1, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, asset019Key, blockingStubFull)); - - Assert.assertFalse(PublicMethed.createAssetIssue(asset019Address, - "tRx", totalSupply, 1, 1, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, asset019Key, blockingStubFull)); - - Assert.assertFalse(PublicMethed.createAssetIssue(asset019Address, - "trX", totalSupply, 1, 1, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, asset019Key, blockingStubFull)); - - Assert.assertFalse(PublicMethed.createAssetIssue(asset019Address, - "TRx", totalSupply, 1, 1, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, asset019Key, blockingStubFull)); - - Assert.assertFalse(PublicMethed.createAssetIssue(asset019Address, - "TrX", totalSupply, 1, 1, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, asset019Key, blockingStubFull)); - - Assert.assertFalse(PublicMethed.createAssetIssue(asset019Address, - "tRX", totalSupply, 1, 1, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, asset019Key, blockingStubFull)); - - Assert.assertTrue(PublicMethed.createAssetIssue(asset019Address, - "trxtrx", totalSupply, 1, 1, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, asset019Key, blockingStubFull)); - - Assert.assertTrue(PublicMethed.createAssetIssue(asset019SecondAddress, - "_", totalSupply, 1, 1, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, asset019SecondKey, blockingStubFull)); - } - - @Test(enabled = true) - public void testGetAssetLastOperationTimeAndAssetIssueFreeNetUsed() { - Assert.assertTrue(PublicMethed.freezeBalance(asset019Address, 100000000L, 3, - asset019Key, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalance(asset019SecondAddress, 100000000L, 3, - asset019SecondKey, blockingStubFull)); - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed.queryAccount(asset019Address, blockingStubFull); - ByteString asset019AccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - - getAssetIdFromThisAccount = PublicMethed.queryAccount(asset019SecondAddress, blockingStubFull); - ByteString asset019SecondAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - - PublicMethed.transferAsset(asset019SecondAddress, asset019AccountId.toByteArray(), 100L, - asset019Address, asset019Key, blockingStubFull); - PublicMethed.transferAsset(asset019Address, asset019SecondAccountId.toByteArray(), 100L, - asset019SecondAddress, asset019SecondKey, blockingStubFull); - - PublicMethed.transferAsset(asset019Address, asset019AccountId.toByteArray(), 10L, - asset019SecondAddress, asset019SecondKey, blockingStubFull); - PublicMethed.transferAsset(asset019SecondAddress, asset019SecondAccountId.toByteArray(), - 10L, asset019Address, asset019Key, blockingStubFull); - - getAssetIdFromThisAccount = PublicMethed.queryAccount(asset019Address, blockingStubFull); - for (String id : getAssetIdFromThisAccount.getFreeAssetNetUsageV2Map().keySet()) { - if (asset019SecondAccountId.toStringUtf8().equalsIgnoreCase(id)) { - Assert.assertTrue(getAssetIdFromThisAccount.getFreeAssetNetUsageV2Map().get(id) > 0); - } - } - - getAssetIdFromThisAccount = PublicMethed.queryAccount(asset019SecondAddress, blockingStubFull); - for (String id : getAssetIdFromThisAccount.getLatestAssetOperationTimeV2Map().keySet()) { - if (asset019AccountId.toStringUtf8().equalsIgnoreCase(id)) { - Assert.assertTrue(getAssetIdFromThisAccount.getLatestAssetOperationTimeV2Map().get(id) > 0); - } - } - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar001.java deleted file mode 100644 index fb47cae025e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar001.java +++ /dev/null @@ -1,375 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue.grammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractGrammar001 { - - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] grammarAddress = ecKey1.getAddress(); - String testKeyForGrammarAddress = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String compilerVersion = Configuration.getByPath("testng.conf") - .getString("defaultParameter.solidityCompilerVersion"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKeyForGrammarAddress); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - @Test(enabled = true, description = "Support function type") - public void test1Grammar001() { - ecKey1 = new ECKey(Utils.getRandom()); - grammarAddress = ecKey1.getAddress(); - testKeyForGrammarAddress = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed - .sendcoin(grammarAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/contractGrammar001test1Grammar001.sol"; - String contractName = "FunctionSelector"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress, - grammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String txid = ""; - String num = "true" + "," + "10"; - txid = PublicMethed.triggerContract(contractAddress, - "select(bool,uint256)", num, false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long returnnumber = ByteArray.toLong(ByteArray.fromHexString(ByteArray.toHexString( - infoById.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(returnnumber == 20); - - String num2 = "false" + "," + "10"; - txid = PublicMethed.triggerContract(contractAddress, - "select(bool,uint256)", num2, false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById:" + infoById); - Optional ById = PublicMethed.getTransactionById(txid, blockingStubFull); - logger.info("getRet:" + ById.get().getRet(0)); - logger.info("getNumber:" + ById.get().getRet(0).getContractRet().getNumber()); - logger.info("getContractRetValue:" + ById.get().getRet(0).getContractRetValue()); - logger.info("getContractRet:" + ById.get().getRet(0).getContractRet()); - - Assert.assertEquals(ById.get().getRet(0).getContractRet().getNumber(), - contractResult.SUCCESS_VALUE); - Assert.assertEquals(ById.get().getRet(0).getContractRetValue(), 1); - Assert.assertEquals(ById.get().getRet(0).getContractRet(), contractResult.SUCCESS); - - Assert - .assertEquals(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()), - "0000000000000000000000000000000000000000000000000000000000000064"); - Assert.assertEquals(contractResult.SUCCESS, infoById.get().getReceipt().getResult()); - - logger.info("ById:" + ById); - Assert.assertEquals(ById.get().getRet(0).getRet().getNumber(), 0); - Assert.assertEquals(ById.get().getRet(0).getRetValue(), 0); - - Long returnnumber2 = ByteArray.toLong(ByteArray.fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(returnnumber2 == 100); - } - - @Test(enabled = true, description = "Ordinary library contract") - public void test2Grammar002() { - String filePath = "src/test/resources/soliditycode/contractGrammar001test2Grammar002.sol"; - String contractName = "Set"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress, - grammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String txid = ""; - String num = "1"; - byte[] contractAddress1 = null; - String filePath1 = "src/test/resources/soliditycode/contractGrammar001test2Grammar002.sol"; - String contractName1 = "C"; - HashMap retMap1 = PublicMethed.getBycodeAbiForLibrary(filePath1, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - String library = retMap1.get("library").toString(); - String libraryAddress = library + Base58.encode58Check(contractAddress); - contractAddress1 = PublicMethed - .deployContractForLibrary(contractName1, abi1, code1, "", maxFeeLimit, - 0L, 100, libraryAddress, testKeyForGrammarAddress, - grammarAddress, compilerVersion, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - txid = PublicMethed.triggerContract(contractAddress1, - "register(uint256)", num, false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull1); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - } - - @Test(enabled = true, description = "Library contract") - public void test3Grammar003() { - String filePath = "src/test/resources/soliditycode/contractGrammar001test3Grammar003.sol"; - String contractName = "Set"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress, - grammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String txid = ""; - String num = "1"; - byte[] contractAddress1 = null; - String contractName1 = "C"; - HashMap retMap1 = PublicMethed.getBycodeAbiForLibrary(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - String library = retMap1.get("library").toString(); - String libraryAddress = library - + Base58.encode58Check(contractAddress); - contractAddress1 = PublicMethed - .deployContractForLibrary(contractName1, abi1, code1, "", maxFeeLimit, - 0L, 100, libraryAddress, testKeyForGrammarAddress, - grammarAddress, compilerVersion, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - txid = PublicMethed.triggerContract(contractAddress1, - "register(uint256)", num, false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull1); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - } - - - @Test(enabled = true, description = "Extended type") - public void test4Grammar004() { - ecKey1 = new ECKey(Utils.getRandom()); - grammarAddress = ecKey1.getAddress(); - testKeyForGrammarAddress = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed - .sendcoin(grammarAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/contractGrammar001test4Grammar004.sol"; - String contractName = "Search"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress, - grammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - byte[] contractAddress1 = null; - String contractName1 = "C"; - HashMap retMap1 = PublicMethed.getBycodeAbiForLibrary(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - String library = retMap1.get("library").toString(); - String libraryAddress = null; - libraryAddress = library - + Base58.encode58Check(contractAddress); - contractAddress1 = PublicMethed - .deployContractForLibrary(contractName1, abi1, code1, "", maxFeeLimit, - 0L, 100, libraryAddress, testKeyForGrammarAddress, - grammarAddress, compilerVersion, blockingStubFull); - String txid = ""; - String num = "1"; - PublicMethed.waitProduceNextBlock(blockingStubFull); - txid = PublicMethed.triggerContract(contractAddress1, - "append(uint256)", num, false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String num1 = "0"; - String txid1 = PublicMethed.triggerContract(contractAddress1, - "getData(uint256)", num1, false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(returnnumber == 1); - - String num2 = "1" + "," + "2"; - String txid2 = PublicMethed.triggerContract(contractAddress1, - "replace(uint256,uint256)", num2, false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById2 = null; - infoById2 = PublicMethed.getTransactionInfoById(txid2, blockingStubFull); - Assert.assertTrue(infoById2.get().getResultValue() == 0); - String txid3 = PublicMethed.triggerContract(contractAddress1, - "getData(uint256)", num1, false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid3, blockingStubFull); - Long returnnumber1 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(returnnumber1 == 2); - - } - - @Test(enabled = true, description = "Solidity assembly") - public void test5Grammar006() { - String filePath = "src/test/resources/soliditycode/contractGrammar001test5Grammar006.sol"; - String contractName = "InfoFeed"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress, - grammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String txid = ""; - String number = "1"; - final String txid1 = PublicMethed.triggerContract(contractAddress, - "f(uint256)", number, false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - final String txid2 = PublicMethed.triggerContract(contractAddress, - "d(uint256)", number, false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - final String txid3 = PublicMethed.triggerContract(contractAddress, - "d1(uint256)", number, false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - final String txid4 = PublicMethed.triggerContract(contractAddress, - "d2(uint256)", number, false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - final String txid5 = PublicMethed.triggerContract(contractAddress, - "d5(uint256)", number, false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - final String txid6 = PublicMethed.triggerContract(contractAddress, - "d4(uint256)", number, false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - final String txid8 = PublicMethed.triggerContract(contractAddress, - "d6(uint256)", number, false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull1); - - Optional infoById1 = PublicMethed - .getTransactionInfoById(txid1, blockingStubFull1); - Assert.assertTrue(infoById1.get().getResultValue() == 0); - - Optional infoById2 = PublicMethed - .getTransactionInfoById(txid2, blockingStubFull1); - Assert.assertTrue(infoById2.get().getResultValue() == 0); - Assert.assertEquals(133,ByteArray.toInt(infoById2.get().getContractResult(0).toByteArray())); - - Optional infoById3 = PublicMethed - .getTransactionInfoById(txid3, blockingStubFull1); - Assert.assertTrue(infoById3.get().getResultValue() == 0); - - Optional infoById4 = PublicMethed - .getTransactionInfoById(txid4, blockingStubFull1); - Assert.assertTrue(infoById4.get().getResultValue() == 0); - - Optional infoById5 = PublicMethed - .getTransactionInfoById(txid5, blockingStubFull1); - Assert.assertTrue(infoById5.get().getResultValue() == 0); - - Optional infoById6 = PublicMethed - .getTransactionInfoById(txid6, blockingStubFull1); - Assert.assertTrue(infoById6.get().getResultValue() == 0); - - Optional infoById8 = PublicMethed - .getTransactionInfoById(txid8, blockingStubFull1); - Assert.assertTrue(infoById8.get().getResultValue() == 0); - - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(grammarAddress, testKeyForGrammarAddress, testNetAccountAddress, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar002.java deleted file mode 100644 index 3dc3eb5884d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar002.java +++ /dev/null @@ -1,335 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue.grammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractGrammar002 { - - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] grammarAddress2 = ecKey1.getAddress(); - String testKeyForGrammarAddress2 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKeyForGrammarAddress2); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - logger.info(Long.toString(PublicMethed.queryAccount(testNetAccountKey, blockingStubFull) - .getBalance())); - } - - - @Test(enabled = true, description = "Interface type function") - public void test1Grammar007() { - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed - .sendcoin(grammarAddress2, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/contractGrammar002test1Grammar007_1.sol"; - String contractName = "Doug"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress2, - grammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String initParmes = ByteArray.toHexString(contractAddress); - String filePath1 = "src/test/resources/soliditycode/contractGrammar002test1Grammar007_2.sol"; - String contractName1 = "main"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath1, contractName1); - String code1 = retMap1.get("byteCode").toString() + "0000000000000000000000" - + initParmes; - String abi1 = retMap1.get("abI").toString(); - byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress2, - grammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - String txid = ""; - String number = "1"; - String txid1 = PublicMethed.triggerContract(contractAddress1, - "dougOfage(uint256)", number, false, - 0, maxFeeLimit, grammarAddress2, testKeyForGrammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - Optional infoById1 = PublicMethed - .getTransactionInfoById(txid1, blockingStubFull1); - - Assert.assertTrue(infoById1.get().getResultValue() == 0); - - String number1 = "687777"; - String txid2 = PublicMethed.triggerContract(contractAddress1, - "uintOfName(bytes32)", number1, false, - 0, maxFeeLimit, grammarAddress2, testKeyForGrammarAddress2, blockingStubFull); - // PublicMethed.waitProduceNextBlock(blockingStubFull); - // PublicMethed.waitProduceNextBlock(blockingStubFull1); - Optional infoById2 = PublicMethed - .getTransactionInfoById(txid2, blockingStubFull1); - - Assert.assertTrue(infoById2.get().getResultValue() == 0); - } - - @Test(enabled = true, description = "Abstract function") - public void test2Grammar008() { - String filePath = "src/test/resources/soliditycode/contractGrammar002test2Grammar008.sol"; - String contractName = "Cat"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress2, - grammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "getContractName()", "#", false, - 0, maxFeeLimit, grammarAddress2, testKeyForGrammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - String returnString = ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals(returnString, - "0000000000000000000000000000000000000000000000000000000000000020000000000000000000" - + "000000000000000000000000000000000000000000000646656c696e650000000000000000000000000" - + "000000000000000000000000000"); - String txid1 = PublicMethed.triggerContract(contractAddress, - "utterance()", "#", false, - 0, maxFeeLimit, grammarAddress2, testKeyForGrammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - String returnString1 = ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals(returnString1, - "6d69616f77000000000000000000000000000000000000000000000000000000"); - } - - @Test(enabled = true, description = "Gas, value test") - public void test3Grammar010() { - String filePath = "src/test/resources/soliditycode/contractGrammar002test3Grammar010.sol"; - String contractName = "Consumer"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 2000L, 100, null, testKeyForGrammarAddress2, - grammarAddress2, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "InfoFeed"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - - byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 0, 100, null, testKeyForGrammarAddress2, - grammarAddress2, blockingStubFull); - String txid = ""; - String initParmes = "\"" + Base58.encode58Check(contractAddress1) + "\""; - txid = PublicMethed.triggerContract(contractAddress, - "setFeed(address)", initParmes, false, - 0, maxFeeLimit, grammarAddress2, testKeyForGrammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String txid1 = PublicMethed.triggerContract(contractAddress, - "callFeed()", "#", false, - 0, maxFeeLimit, grammarAddress2, testKeyForGrammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid1, blockingStubFull1); - Assert.assertTrue(infoById.get().getResultValue() == 0); - } - - - @Test(enabled = true, description = "Call a named function") - public void test4Grammar011() { - String filePath = "src/test/resources/soliditycode/contractGrammar002test4Grammar011.sol"; - String contractName = "C"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress2, - grammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - String number = "1" + "," + "2"; - String txid = PublicMethed.triggerContract(contractAddress, - "f(uint256,uint256)", number, false, - 0, maxFeeLimit, grammarAddress2, testKeyForGrammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(returnnumber == 1); - - Optional infoById1 = null; - String txid1 = PublicMethed.triggerContract(contractAddress, - "g()", "#", false, - 0, maxFeeLimit, grammarAddress2, testKeyForGrammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - Assert.assertTrue(infoById1.get().getResultValue() == 0); - } - - - @Test(enabled = true, description = "Call a native function") - public void test5Grammar012() { - String filePath = "src/test/resources/soliditycode/contractGrammar002test4Grammar012.sol"; - String contractName = "rTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress2, - grammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - String txid = PublicMethed.triggerContract(contractAddress, - "info()", "#", false, - 0, maxFeeLimit, grammarAddress2, testKeyForGrammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - - } - - @Test(enabled = true, description = "Call a Destructor function") - public void test6Grammar013() { - String filePath = "src/test/resources/soliditycode/contractGrammar002test6Grammar013.sol"; - String contractName = "Counter"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress2, - grammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - String txid = PublicMethed.triggerContract(contractAddress, - "getCount()", "#", false, - 0, maxFeeLimit, grammarAddress2, testKeyForGrammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(returnnumber == 0); - - Optional infoById1 = null; - String txid1 = PublicMethed.triggerContract(contractAddress, - "increment()", "#", false, - 0, maxFeeLimit, grammarAddress2, testKeyForGrammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - - Assert.assertTrue(infoById1.get().getResultValue() == 0); - Optional infoById2 = null; - String txid2 = PublicMethed.triggerContract(contractAddress, - "getCount()", "#", false, - 0, maxFeeLimit, grammarAddress2, testKeyForGrammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById2 = PublicMethed.getTransactionInfoById(txid2, blockingStubFull); - - Assert.assertTrue(infoById2.get().getResultValue() == 0); - - Long returnnumber1 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById2.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(returnnumber1 == 10); - - Optional infoById3 = null; - String txid3 = PublicMethed.triggerContract(contractAddress, - "kill()", "#", false, - 0, maxFeeLimit, grammarAddress2, testKeyForGrammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById3 = PublicMethed.getTransactionInfoById(txid3, blockingStubFull); - Assert.assertTrue(infoById3.get().getResultValue() == 0); - - Optional infoById4 = null; - String txid4 = PublicMethed.triggerContract(contractAddress, - "getCount()", "#", false, - 0, maxFeeLimit, grammarAddress2, testKeyForGrammarAddress2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(txid4 == null); - - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(grammarAddress2, testKeyForGrammarAddress2, testNetAccountAddress, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar003.java deleted file mode 100644 index c2aa82cf48f..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar003.java +++ /dev/null @@ -1,522 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue.grammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.crypto.Hash; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractGrammar003 { - - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] grammarAddress3 = ecKey1.getAddress(); - String testKeyForGrammarAddress3 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKeyForGrammarAddress3); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - - @Test(enabled = true, description = "Complex structure") - public void test1Grammar014() { - ecKey1 = new ECKey(Utils.getRandom()); - grammarAddress3 = ecKey1.getAddress(); - testKeyForGrammarAddress3 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed - .sendcoin(grammarAddress3, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/contractGrammar003test1Grammar014.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress3, - grammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "B"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress3, - grammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String txid = PublicMethed.triggerContract(contractAddress, - "getnumberForB()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String txid1 = PublicMethed.triggerContract(contractAddress1, - "getnumberForB()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(returnnumber == 0); - - Long returnnumber1 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(infoById1.get().getResultValue() == 0); - Assert.assertTrue(returnnumber1 == 0); - Optional infoById4 = null; - String initParmes = "\"" + Base58.encode58Check(contractAddress1) + "\",\"1\""; - String txid4 = PublicMethed.triggerContract(contractAddress, - "callTest(address,uint256)", initParmes, false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById4 = PublicMethed.getTransactionInfoById(txid4, blockingStubFull); - - Assert.assertTrue(infoById4.get().getResultValue() == 0); - - String txid5 = PublicMethed.triggerContract(contractAddress, - "getnumberForB()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById5 = null; - infoById5 = PublicMethed.getTransactionInfoById(txid5, blockingStubFull); - Long returnnumber5 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById5.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(returnnumber5 == 0); - - String txid6 = PublicMethed.triggerContract(contractAddress1, - "getnumberForB()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById6 = null; - infoById6 = PublicMethed.getTransactionInfoById(txid6, blockingStubFull); - Long returnnumber6 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById6.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(returnnumber6 == 1); - - String txid7 = PublicMethed.triggerContract(contractAddress, - "callcodeTest(address,uint256)", initParmes, false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById7 = null; - infoById7 = PublicMethed.getTransactionInfoById(txid7, blockingStubFull); - - Assert.assertTrue(infoById7.get().getResultValue() == 0); - - String txid8 = PublicMethed.triggerContract(contractAddress, - "getnumberForB()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById8 = null; - infoById8 = PublicMethed.getTransactionInfoById(txid8, blockingStubFull); - Long returnnumber8 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById8.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(returnnumber8 == 1); - - String txid9 = PublicMethed.triggerContract(contractAddress1, - "getnumberForB()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById9 = null; - infoById9 = PublicMethed.getTransactionInfoById(txid9, blockingStubFull); - Long returnnumber9 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById9.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(returnnumber9 == 1); - - String txid10 = PublicMethed.triggerContract(contractAddress, - "delegatecallTest(address,uint256)", initParmes, false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById10 = null; - infoById10 = PublicMethed.getTransactionInfoById(txid10, blockingStubFull); - - Assert.assertTrue(infoById10.get().getResultValue() == 0); - - String txid11 = PublicMethed.triggerContract(contractAddress, - "getnumberForB()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById11 = null; - infoById11 = PublicMethed.getTransactionInfoById(txid11, blockingStubFull); - Long returnnumber11 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById11.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(returnnumber11 == 1); - - String txid12 = PublicMethed.triggerContract(contractAddress1, - "getnumberForB()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById12 = null; - infoById12 = PublicMethed.getTransactionInfoById(txid12, blockingStubFull); - Long returnnumber12 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById12.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(returnnumber12 == 1); - - String initParmes1 = "\"" + Base58.encode58Check(contractAddress1) + "\""; - String txid13 = PublicMethed.triggerContract(contractAddress, - "callAddTest(address)", initParmes1, false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById13 = null; - infoById13 = PublicMethed.getTransactionInfoById(txid13, blockingStubFull); - - Assert.assertTrue(infoById13.get().getResultValue() == 0); - - String txid14 = PublicMethed.triggerContract(contractAddress, - "getnumberForB()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById14 = null; - infoById14 = PublicMethed.getTransactionInfoById(txid14, blockingStubFull); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById14.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(returnnumber14 == 1); - - String txid15 = PublicMethed.triggerContract(contractAddress1, - "getnumberForB()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById15 = null; - infoById15 = PublicMethed.getTransactionInfoById(txid15, blockingStubFull); - Long returnnumber15 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById15.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(returnnumber15 == 3); - } - - - @Test(enabled = true, description = "Fallback function ") - public void test2Grammar015() { - String filePath = "src/test/resources/soliditycode/contractGrammar003test2Grammar015.sol"; - String contractName = "ExecuteFallback"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress3, - grammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - String txid = PublicMethed.triggerContract(contractAddress, - "callExistFunc()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - String i = ByteArray.toHexString(Hash.sha3("ExistFuncCalled(bytes,uint256)".getBytes())); - String resultvalue = ByteArray - .toHexString(infoById.get().getLogList().get(0).getTopicsList().get(0).toByteArray()); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertEquals(i, resultvalue); - - Optional infoById1 = null; - String txid1 = PublicMethed.triggerContract(contractAddress, - "callNonExistFunc()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - String value = ByteArray.toHexString(Hash.sha3("FallbackCalled(bytes)".getBytes())); - String resultvalue1 = ByteArray - .toHexString(infoById1.get().getLogList().get(0).getTopicsList().get(0).toByteArray()); - - Assert.assertTrue(infoById1.get().getResultValue() == 0); - Assert.assertEquals(value, resultvalue1); - - } - - @Test(enabled = true, description = "Permission control ") - public void test3Grammar016() { - String filePath = "src/test/resources/soliditycode/contractGrammar003test3Grammar016.sol"; - String contractName = "D"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress3, - grammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - String txid = PublicMethed.triggerContract(contractAddress, - "readData()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - String contractName1 = "E"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - - byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress3, - grammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = null; - String txid1 = PublicMethed.triggerContract(contractAddress1, - "g()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - - Assert.assertTrue(infoById1.get().getResultValue() == 0); - - Optional infoById2 = null; - String num = "3"; - String txid2 = PublicMethed.triggerContract(contractAddress1, - "setData(uint256)", num, false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById2 = PublicMethed.getTransactionInfoById(txid2, blockingStubFull); - - Assert.assertTrue(infoById2.get().getResultValue() == 0); - - String txid3 = PublicMethed.triggerContract(contractAddress1, - "getData()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById3 = null; - infoById3 = PublicMethed.getTransactionInfoById(txid3, blockingStubFull); - Long returnnumber3 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById3.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(returnnumber3 == 3); - Assert.assertTrue(infoById3.get().getResultValue() == 0); - - } - - @Test(enabled = true, description = "Structure") - public void test4Grammar017() { - String filePath = "src/test/resources/soliditycode/contractGrammar003test4Grammar017.sol"; - String contractName = "CrowdFunding"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] contractAddress1 = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress3, - grammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - String initParmes = "\"" + Base58.encode58Check(grammarAddress3) + "\",\"1\""; - Optional infoById = null; - String txid = PublicMethed.triggerContract(contractAddress1, - "candidate(address,uint256)", initParmes, false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long returnnumber1 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(returnnumber1 == 1); - - String txid1 = PublicMethed.triggerContract(contractAddress1, - "check(uint256)", "1", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = PublicMethed - .getTransactionInfoById(txid1, blockingStubFull1); - Long returnnumber2 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(returnnumber2 == 1); - - String txid2 = PublicMethed.triggerContract(contractAddress1, - "vote(uint256)", "1", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById2 = PublicMethed - .getTransactionInfoById(txid2, blockingStubFull); - - Assert.assertTrue(infoById2.get().getResultValue() == 0); - - } - - @Test(enabled = true, description = "Built-in function") - public void test5Grammar018() { - String filePath = "src/test/resources/soliditycode/contractGrammar003test5Grammar018.sol"; - String contractName = "Grammar18"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress3, - grammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - String txid = PublicMethed.triggerContract(contractAddress, - "testAddmod()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(returnnumber == 1); - Optional infoById1 = null; - String txid1 = PublicMethed.triggerContract(contractAddress, - "testMulmod()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - Long returnnumber1 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(infoById1.get().getResultValue() == 0); - Assert.assertTrue(returnnumber1 == 2); - - String txid2 = PublicMethed.triggerContract(contractAddress, - "testKeccak256()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById2 = null; - infoById2 = PublicMethed.getTransactionInfoById(txid2, blockingStubFull); - - Assert.assertTrue(infoById2.get().getResultValue() == 0); - - String txid3 = PublicMethed.triggerContract(contractAddress, - "testSha256()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById3 = null; - infoById3 = PublicMethed.getTransactionInfoById(txid3, blockingStubFull); - - Assert.assertTrue(infoById3.get().getResultValue() == 0); - - String txid4 = PublicMethed.triggerContract(contractAddress, - "testSha3()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - Optional infoById4 = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById4 = PublicMethed.getTransactionInfoById(txid4, blockingStubFull); - Assert.assertTrue(infoById4.get().getResultValue() == 0); - } - - - @Test(enabled = true, description = "Time unit") - public void test6Grammar019() { - - String filePath = "src/test/resources/soliditycode/contractGrammar003test6Grammar019.sol"; - String contractName = "timetest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress3, - grammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String txid = PublicMethed.triggerContract(contractAddress, - "timetest()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 1); - - } - - - @Test(enabled = true, description = "Trx and sun unit conversion.") - public void test7Grammar020() { - String filePath = "src/test/resources/soliditycode/contractGrammar003test7Grammar020.sol"; - String contractName = "trxtest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress3, - grammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - String txid = PublicMethed.triggerContract(contractAddress, - "test()", "#", false, - 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(grammarAddress3, testKeyForGrammarAddress3, testNetAccountAddress, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar004.java deleted file mode 100644 index 02717194a3c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetissue/grammar/ContractGrammar004.java +++ /dev/null @@ -1,638 +0,0 @@ -package stest.tron.wallet.dailybuild.assetissue.grammar; - -import static org.tron.protos.Protocol.Transaction.Result.contractResult.BAD_JUMP_DESTINATION_VALUE; -import static org.tron.protos.Protocol.Transaction.Result.contractResult.OUT_OF_MEMORY_VALUE; -import static org.tron.protos.Protocol.Transaction.Result.contractResult.OUT_OF_TIME_VALUE; -import static org.tron.protos.Protocol.Transaction.Result.contractResult.REVERT_VALUE; -import static org.tron.protos.Protocol.Transaction.Result.contractResult.STACK_TOO_LARGE_VALUE; -import static org.tron.protos.Protocol.Transaction.Result.contractResult.STACK_TOO_SMALL_VALUE; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractGrammar004 { - - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] grammarAddress = ecKey1.getAddress(); - String testKeyForGrammarAddress = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(1); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String compilerVersion = Configuration.getByPath("testng.conf") - .getString("defaultParameter.solidityCompilerVersion"); - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKeyForGrammarAddress); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - @Test(enabled = true, description = "ContractResult is OUT_OF_TIME") - public void test1Grammar001() { - Assert.assertTrue(PublicMethed - .sendcoin(grammarAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "./src/test/resources/soliditycode/walletTestMutiSign004.sol"; - String contractName = "timeoutTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - byte[] contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, - testKeyForGrammarAddress, grammarAddress, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - org.testng.Assert.assertTrue(smartContract.getAbi().toString() != null); - String txid = null; - Optional infoById = null; - String initParmes = "\"" + "100000" + "\""; - txid = PublicMethed - .triggerContract(contractAddress, "testUseCpu(uint256)", initParmes, false, 0, maxFeeLimit, - grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("Txid is " + txid); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Optional byId = PublicMethed.getTransactionById(txid, blockingStubFull); - logger.info("getRet:" + byId.get().getRet(0)); - logger.info("getNumber:" + byId.get().getRet(0).getContractRet().getNumber()); - logger.info("getContractRetValue:" + byId.get().getRet(0).getContractRetValue()); - logger.info("getContractRet:" + byId.get().getRet(0).getContractRet()); - logger.info("ById:" + byId); - - Assert.assertEquals(byId.get().getRet(0).getContractRetValue(), OUT_OF_TIME_VALUE); - Assert.assertEquals(byId.get().getRet(0).getContractRet(), contractResult.OUT_OF_TIME); - - Assert - .assertEquals(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()), ""); - Assert.assertEquals(contractResult.OUT_OF_TIME, infoById.get().getReceipt().getResult()); - - Assert.assertEquals(byId.get().getRet(0).getRet().getNumber(), 0); - Assert.assertEquals(byId.get().getRet(0).getRetValue(), 0); - - - } - - - @Test(enabled = true, description = "ContractResult is OUT_OF_MEMORY") - public void test2Grammar002() { - String filePath = "./src/test/resources/soliditycode/testOutOfMem.sol"; - String contractName = "Test"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - byte[] contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, - testKeyForGrammarAddress, grammarAddress, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - org.testng.Assert.assertTrue(smartContract.getAbi().toString() != null); - String txid = null; - Optional infoById = null; - String initParmes = "\"" + "31457280" + "\""; - txid = PublicMethed - .triggerContract(contractAddress, "testOutOfMem(uint256)", initParmes, false, 0, - maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("Txid is " + txid); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Optional byId = PublicMethed.getTransactionById(txid, blockingStubFull); - logger.info("getRet:" + byId.get().getRet(0)); - logger.info("getNumber:" + byId.get().getRet(0).getContractRet().getNumber()); - logger.info("getContractRetValue:" + byId.get().getRet(0).getContractRetValue()); - logger.info("getContractRet:" + byId.get().getRet(0).getContractRet()); - logger.info("ById:" + byId); - - logger.info("infoById:" + infoById); - - Assert.assertEquals(byId.get().getRet(0).getContractRetValue(), OUT_OF_MEMORY_VALUE); - Assert.assertEquals(byId.get().getRet(0).getContractRet(), contractResult.OUT_OF_MEMORY); - - Assert - .assertEquals(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()), ""); - Assert.assertEquals(contractResult.OUT_OF_MEMORY, infoById.get().getReceipt().getResult()); - - Assert.assertEquals(byId.get().getRet(0).getRet().getNumber(), 0); - Assert.assertEquals(byId.get().getRet(0).getRetValue(), 0); - - - } - - - @Test(enabled = true, description = "ContractResult is BAD_JUMP_DESTINATION") - public void test3Grammar003() { - String contractName = "Test"; - - String code = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600" - + "080fd5b5061011f8061003a6000396000f30060806040526004361060485763ffffffff7c01000000000000" - + "000000000000000000000000000000000000000000006000350416634ef5a0088114604d5780639093b95b1" - + "4608c575b600080fd5b348015605857600080fd5b50d38015606457600080fd5b50d28015607057600080fd" - + "5b50607a60043560b8565b60408051918252519081900360200190f35b348015609757600080fd5b50d3801" - + "560a357600080fd5b50d2801560af57600080fd5b5060b660ee565b005b6000606082604051908082528060" - + "20026020018201604052801560e5578160200160208202803883390190505b50905050919050565b6001805" - + "600a165627a7a7230582092ba162087e13f41c6d6c00ba493edc5a5a6250a3840ece5f99aa38b66366a7000" - + "29"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\"" - + ":\"testOutOfMem\",\"outputs\":[{\"name\":\"r\",\"type\":\"bytes32\"}],\"payable\":false" - + ",\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs" - + "\":[],\"name\":\"testBadJumpDestination\",\"outputs\":[],\"payable\":false,\"stateMutab" - + "ility\":\"nonpayable\",\"type\":\"function\"}]"; - - byte[] contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, - testKeyForGrammarAddress, grammarAddress, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - org.testng.Assert.assertTrue(smartContract.getAbi().toString() != null); - String txid = null; - Optional infoById = null; - txid = PublicMethed - .triggerContract(contractAddress, "testBadJumpDestination()", "#", false, 0, maxFeeLimit, - grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("Txid is " + txid); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Optional byId = PublicMethed.getTransactionById(txid, blockingStubFull); - logger.info("getRet:" + byId.get().getRet(0)); - logger.info("getNumber:" + byId.get().getRet(0).getContractRet().getNumber()); - logger.info("getContractRetValue:" + byId.get().getRet(0).getContractRetValue()); - logger.info("getContractRet:" + byId.get().getRet(0).getContractRet()); - logger.info("ById:" + byId); - - logger.info("infoById:" + infoById); - - Assert.assertEquals(byId.get().getRet(0).getContractRetValue(), BAD_JUMP_DESTINATION_VALUE); - Assert.assertEquals(byId.get().getRet(0).getContractRet(), contractResult.BAD_JUMP_DESTINATION); - - Assert - .assertEquals(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()), ""); - Assert - .assertEquals(contractResult.BAD_JUMP_DESTINATION, infoById.get().getReceipt().getResult()); - - Assert.assertEquals(byId.get().getRet(0).getRet().getNumber(), 0); - Assert.assertEquals(byId.get().getRet(0).getRetValue(), 0); - - - } - - - @Test(enabled = true, description = "ContractResult is OUT_OF_ENERGY") - public void test4Grammar004() { - - String filePath = "src/test/resources/soliditycode/contractUnknownException.sol"; - String contractName = "testC"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 20L, 100, - null, testKeyForGrammarAddress, grammarAddress, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("Txid is " + txid); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Optional byId = PublicMethed.getTransactionById(txid, blockingStubFull); - logger.info("getRet:" + byId.get().getRet(0)); - logger.info("getNumber:" + byId.get().getRet(0).getContractRet().getNumber()); - logger.info("getContractRetValue:" + byId.get().getRet(0).getContractRetValue()); - logger.info("getContractRet:" + byId.get().getRet(0).getContractRet()); - logger.info("ById:" + byId); - - logger.info("infoById:" + infoById); - - Assert.assertEquals(byId.get().getRet(0).getContractRetValue(), REVERT_VALUE); - Assert.assertEquals(byId.get().getRet(0).getContractRet(), contractResult.REVERT); - - Assert.assertEquals(ByteArray.toHexString(infoById.get() - .getContractResult(0).toByteArray()), - "4e487b710000000000000000000000000000000000000000000000000000000000000001"); - Assert.assertEquals(contractResult.REVERT, infoById.get().getReceipt().getResult()); - - Assert.assertEquals(byId.get().getRet(0).getRet().getNumber(), 0); - Assert.assertEquals(byId.get().getRet(0).getRetValue(), 0); - - } - - - @Test(enabled = true, description = "ContractResult is ILLEGAL_OPERATION") - public void test5Grammar005() { - - String filePath = "src/test/resources/soliditycode/assertExceptiontest1DivideInt.sol"; - String contractName = "divideIHaveArgsReturnStorage"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, - testKeyForGrammarAddress, grammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String txid = ""; - String num = "4" + "," + "0"; - - txid = PublicMethed - .triggerContract(contractAddress, "divideIHaveArgsReturn(int256,int256)", num, false, 0, - maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById:" + infoById); - Optional byId = PublicMethed.getTransactionById(txid, blockingStubFull); - logger.info("getRet:" + byId.get().getRet(0)); - logger.info("getNumber:" + byId.get().getRet(0).getContractRet().getNumber()); - logger.info("getContractRetValue:" + byId.get().getRet(0).getContractRetValue()); - logger.info("getContractRet:" + byId.get().getRet(0).getContractRet()); - - Assert.assertEquals(byId.get().getRet(0).getContractRet().getNumber(), REVERT_VALUE); - Assert.assertEquals(byId.get().getRet(0).getContractRetValue(), REVERT_VALUE); - Assert.assertEquals(byId.get().getRet(0).getContractRet(), contractResult.REVERT); - - Assert - .assertEquals(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()), - "4e487b710000000000000000000000000000000000000000000000000000000000000012"); - Assert.assertEquals(contractResult.REVERT, infoById.get().getReceipt().getResult()); - - } - - - @Test(enabled = true, description = "ContractResult is REVERT") - public void test6Grammar006() { - - String filePath = - "src/test/resources/soliditycode/requireExceptiontest1TestRequireContract.sol"; - String contractName = "TestThrowsContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, - testKeyForGrammarAddress, grammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - final String txid = PublicMethed - .triggerContract(contractAddress, "testRequire()", "#", false, 0, maxFeeLimit, - grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById:" + infoById); - Optional byId = PublicMethed.getTransactionById(txid, blockingStubFull); - logger.info("getRet:" + byId.get().getRet(0)); - logger.info("getNumber:" + byId.get().getRet(0).getContractRet().getNumber()); - logger.info("getContractRetValue:" + byId.get().getRet(0).getContractRetValue()); - logger.info("getContractRet:" + byId.get().getRet(0).getContractRet()); - - Assert.assertEquals(byId.get().getRet(0).getContractRet().getNumber(), REVERT_VALUE); - Assert.assertEquals(byId.get().getRet(0).getContractRetValue(), REVERT_VALUE); - Assert.assertEquals(byId.get().getRet(0).getContractRet(), contractResult.REVERT); - - Assert - .assertEquals(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()), ""); - Assert.assertEquals(contractResult.REVERT, infoById.get().getReceipt().getResult()); - - } - - @Test(enabled = true, description = "ContractResult is SUCCESS") - public void test7Grammar007() { - - String filePath = "src/test/resources/soliditycode/assertExceptiontest1DivideInt.sol"; - String contractName = "divideIHaveArgsReturnStorage"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, - testKeyForGrammarAddress, grammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String txid = ""; - String num = "4" + "," + "2"; - - txid = PublicMethed - .triggerContract(contractAddress, "divideIHaveArgsReturn(int256,int256)", num, false, 0, - maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById:" + infoById); - Optional byId = PublicMethed.getTransactionById(txid, blockingStubFull); - logger.info("getRet:" + byId.get().getRet(0)); - logger.info("getNumber:" + byId.get().getRet(0).getContractRet().getNumber()); - logger.info("getContractRetValue:" + byId.get().getRet(0).getContractRetValue()); - logger.info("getContractRet:" + byId.get().getRet(0).getContractRet()); - - Assert.assertEquals(byId.get().getRet(0).getContractRet().getNumber(), - contractResult.SUCCESS_VALUE); - Assert.assertEquals(byId.get().getRet(0).getContractRetValue(), contractResult.SUCCESS_VALUE); - Assert.assertEquals(byId.get().getRet(0).getContractRet(), contractResult.SUCCESS); - - Assert.assertEquals(contractResult.SUCCESS, infoById.get().getReceipt().getResult()); - - Assert.assertEquals(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()), - "0000000000000000000000000000000000000000000000000000000000000002"); - - } - - - @Test(enabled = true, description = "ContractResult is TRANSFER_FAILED") - public void test8Grammar008() { - String filePath = "src/test/resources/soliditycode/TransferFailed001.sol"; - String contractName = "EnergyOfTransferFailedTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 1000000L, 100, null, - testKeyForGrammarAddress, grammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(grammarAddress, blockingStubFull); - info = PublicMethed.queryAccount(testKeyForGrammarAddress, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] nonexistentAddress = ecKey2.getAddress(); - String txid = ""; - String num = "1" + ",\"" + Base58.encode58Check(nonexistentAddress) + "\""; - - txid = PublicMethed - .triggerContract(contractAddress, "testTransferTrxNonexistentTarget(uint256,address)", num, - false, 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(testKeyForGrammarAddress, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(grammarAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - logger.info( - "infoById.get().getReceipt().getResult(): " + infoById.get().getReceipt().getResult()); - logger.info("ByteArray.toStr(infoById.get().getResMessage().toByteArray()): " + ByteArray - .toStr(infoById.get().getResMessage().toByteArray())); - /*Assert.assertEquals( - "transfer trx failed: Validate InternalTransfer error, no ToAccount." - + " And not allowed to create account in smart contract.", - ByteArray.toStr(infoById.get().getResMessage().toByteArray()));*/ - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertNotEquals(10000000, energyUsageTotal); - - - } - - - @Test(enabled = true, description = "ContractResult is STACK_TOO_SMALL") - public void test9Grammar009() { - - String contractName = "TestThrowsContract"; - String abi = "[{\"constant\":false,\"inputs\":[],\"name\":\"testStackTooSmall\",\"outputs\":[]" - + ",\"payable\":false,\"type\":\"function\",\"stateMutability\":\"nonpayable\"}]"; - String code = "60606040523415600b57fe5b5b60608060196000396000f300606060405263ffffffff60e060020" - + "a6000350416632f3a24cc81146020575bfe5b3415602757fe5b602d602f565b005b50505b5600a165627a7a" - + "723058208184f2ff2627a8a490bfd1233a891f2f4605375d0fec375e237ffc188cdd7ec70029"; - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, - testKeyForGrammarAddress, grammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - final String txid = PublicMethed - .triggerContract(contractAddress, "testStackTooSmall()", "#", false, 0, maxFeeLimit, - grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById:" + infoById); - Optional byId = PublicMethed.getTransactionById(txid, blockingStubFull); - logger.info("getRet:" + byId.get().getRet(0)); - logger.info("getNumber:" + byId.get().getRet(0).getContractRet().getNumber()); - logger.info("getContractRetValue:" + byId.get().getRet(0).getContractRetValue()); - logger.info("getContractRet:" + byId.get().getRet(0).getContractRet()); - - Assert.assertEquals(byId.get().getRet(0).getContractRet().getNumber(), STACK_TOO_SMALL_VALUE); - Assert.assertEquals(byId.get().getRet(0).getContractRetValue(), STACK_TOO_SMALL_VALUE); - Assert.assertEquals(byId.get().getRet(0).getContractRet(), contractResult.STACK_TOO_SMALL); - - Assert - .assertEquals(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()), ""); - Assert.assertEquals(contractResult.STACK_TOO_SMALL, infoById.get().getReceipt().getResult()); - - } - - @Test(enabled = true, description = "ContractResult is STACK_TOO_LARGE") - public void test9Grammar010() { - - String contractName = "TestThrowsContract"; - String abi = "[{\"constant\":false,\"inputs\":[],\"name\":\"testStackTooLarge\",\"outputs\":[]" - + ",\"payable\":false,\"type\":\"function\",\"stateMutability\":\"nonpayable\"}]"; - String code = "6060604052341561000c57fe5b5b610b658061001c6000396000f300606060405263ffffffff60e" - + "060020a600035041663f7d9c5c68114610021575bfe5b341561002957fe5b610031610033565b005b600060" - + "0160026003600460056006600760086009600a600b600c600d600e600f60106011601260136014601560166" - + "01760186019601a601b601c601d601e601f6020602160226023602460256026602760286029602a602b602c" - + "602d602e602f6030603160326033603460356036603760386039603a603b603c603d603e603f60406041604" - + "26043604460456046604760486049604a604b604c604d604e604f6050605160526053605460556056605760" - + "586059605a605b605c605d605e605f6060606160626063606460656066606760686069606a606b606c606d6" - + "06e606f6070607160726073607460756076607760786079607a607b607c607d607e607f6080608160826083" - + "608460856086608760886089608a608b608c608d608e608f609060916092609360946095609660976098609" - + "9609a609b609c609d609e609f60a060a160a260a360a460a560a660a760a860a960aa60ab60ac60ad60ae60" - + "af60b060b160b260b360b460b560b660b760b860b960ba60bb60bc60bd60be60bf60c060c160c260c360c46" - + "0c560c660c760c860c960ca60cb60cc60cd60ce60cf60d060d160d260d360d460d560d660d760d860d960da" - + "60db60dc60dd60de60df60e060e160e260e360e460e560e660e760e860e960ea60eb60ec60ed60ee60ef60f" - + "060f160f260f360f460f560f660f760f860f960fa60fb60fc60fd60fe60ff61010061010161010261010361" - + "010461010561010661010761010861010961010a61010b61010c61010d61010e61010f61011061011161011" - + "261011361011461011561011661011761011861011961011a61011b61011c61011d61011e61011f61012061" - + "012161012261012361012461012561012661012761012861012961012a61012b61012c61012d61012e61012" - + "f61013061013161013261013361013461013561013661013761013861013961013a61013b61013c61013d61" - + "013e61013f61014061014161014261014361014461014561014661014761014861014961014a61014b61014" - + "c61014d61014e61014f61015061015161015261015361015461015561015661015761015861015961015a61" - + "015b61015c61015d61015e61015f61016061016161016261016361016461016561016661016761016861016" - + "961016a61016b61016c61016d61016e61016f61017061017161017261017361017461017561017661017761" - + "017861017961017a61017b61017c61017d61017e61017f61018061018161018261018361018461018561018" - + "661018761018861018961018a61018b61018c61018d61018e61018f61019061019161019261019361019461" - + "019561019661019761019861019961019a61019b61019c61019d61019e61019f6101a06101a16101a26101a" - + "36101a46101a56101a66101a76101a86101a96101aa6101ab6101ac6101ad6101ae6101af6101b06101b161" - + "01b26101b36101b46101b56101b66101b76101b86101b96101ba6101bb6101bc6101bd6101be6101bf6101c" - + "06101c16101c26101c36101c46101c56101c66101c76101c86101c96101ca6101cb6101cc6101cd6101ce61" - + "01cf6101d06101d16101d26101d36101d46101d56101d66101d76101d86101d96101da6101db6101dc6101d" - + "d6101de6101df6101e06101e16101e26101e36101e46101e56101e66101e76101e86101e96101ea6101eb61" - + "01ec6101ed6101ee6101ef6101f06101f16101f26101f36101f46101f56101f66101f76101f86101f96101f" - + "a6101fb6101fc6101fd6101fe6101ff61020061020161020261020361020461020561020661020761020861" - + "020961020a61020b61020c61020d61020e61020f61021061021161021261021361021461021561021661021" - + "761021861021961021a61021b61021c61021d61021e61021f61022061022161022261022361022461022561" - + "022661022761022861022961022a61022b61022c61022d61022e61022f61023061023161023261023361023" - + "461023561023661023761023861023961023a61023b61023c61023d61023e61023f61024061024161024261" - + "024361024461024561024661024761024861024961024a61024b61024c61024d61024e61024f61025061025" - + "161025261025361025461025561025661025761025861025961025a61025b61025c61025d61025e61025f61" - + "026061026161026261026361026461026561026661026761026861026961026a61026b61026c61026d61026" - + "e61026f61027061027161027261027361027461027561027661027761027861027961027a61027b61027c61" - + "027d61027e61027f61028061028161028261028361028461028561028661028761028861028961028a61028" - + "b61028c61028d61028e61028f61029061029161029261029361029461029561029661029761029861029961" - + "029a61029b61029c61029d61029e61029f6102a06102a16102a26102a36102a46102a56102a66102a76102a" - + "86102a96102aa6102ab6102ac6102ad6102ae6102af6102b06102b16102b26102b36102b46102b56102b661" - + "02b76102b86102b96102ba6102bb6102bc6102bd6102be6102bf6102c06102c16102c26102c36102c46102c" - + "56102c66102c76102c86102c96102ca6102cb6102cc6102cd6102ce6102cf6102d06102d16102d26102d361" - + "02d46102d56102d66102d76102d86102d96102da6102db6102dc6102dd6102de6102df6102e06102e16102e" - + "26102e36102e46102e56102e66102e76102e86102e96102ea6102eb6102ec6102ed6102ee6102ef6102f061" - + "02f16102f26102f36102f46102f56102f66102f76102f86102f96102fa6102fb6102fc6102fd6102fe6102f" - + "f61030061030161030261030361030461030561030661030761030861030961030a61030b61030c61030d61" - + "030e61030f61031061031161031261031361031461031561031661031761031861031961031a61031b61031" - + "c61031d61031e61031f61032061032161032261032361032461032561032661032761032861032961032a61" - + "032b61032c61032d61032e61032f61033061033161033261033361033461033561033661033761033861033" - + "961033a61033b61033c61033d61033e61033f61034061034161034261034361034461034561034661034761" - + "034861034961034a61034b61034c61034d61034e61034f61035061035161035261035361035461035561035" - + "661035761035861035961035a61035b61035c61035d61035e61035f61036061036161036261036361036461" - + "036561036661036761036861036961036a61036b61036c61036d61036e61036f61037061037161037261037" - + "361037461037561037661037761037861037961037a61037b61037c61037d61037e61037f61038061038161" - + "038261038361038461038561038661038761038861038961038a61038b61038c61038d61038e61038f61039" - + "061039161039261039361039461039561039661039761039861039961039a61039b61039c61039d61039e61" - + "039f6103a06103a16103a26103a36103a46103a56103a66103a76103a86103a96103aa6103ab6103ac6103a" - + "d6103ae6103af6103b06103b16103b26103b36103b46103b56103b66103b76103b86103b96103ba6103bb61" - + "03bc6103bd6103be6103bf6103c06103c16103c26103c36103c46103c56103c66103c76103c86103c96103c" - + "a6103cb6103cc6103cd6103ce6103cf6103d06103d16103d26103d36103d46103d56103d66103d76103d861" - + "03d96103da6103db6103dc6103dd6103de6103df6103e06103e16103e26103e36103e46103e56103e66103e" - + "76103e86103e96103ea6103eb6103ec6103ed6103ee6103ef6103f06103f16103f26103f36103f46103f561" - + "03f66103f76103f86103f96103fa6103fb6103fc6103fd6103fe6103ff6104005b5600a165627a7a7230582" - + "0998f09cc267db91352a3d0a4ab60ea08fc306fa8bc6dd78dc324a06109dcf0420029"; - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, - testKeyForGrammarAddress, grammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - final String txid = PublicMethed - .triggerContract(contractAddress, "testStackTooLarge()", "#", false, 0, maxFeeLimit, - grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById:" + infoById); - Optional byId = PublicMethed.getTransactionById(txid, blockingStubFull); - logger.info("getRet:" + byId.get().getRet(0)); - logger.info("getNumber:" + byId.get().getRet(0).getContractRet().getNumber()); - logger.info("getContractRetValue:" + byId.get().getRet(0).getContractRetValue()); - logger.info("getContractRet:" + byId.get().getRet(0).getContractRet()); - - Assert.assertEquals(byId.get().getRet(0).getContractRet().getNumber(), STACK_TOO_LARGE_VALUE); - Assert.assertEquals(byId.get().getRet(0).getContractRetValue(), STACK_TOO_LARGE_VALUE); - Assert.assertEquals(byId.get().getRet(0).getContractRet(), contractResult.STACK_TOO_LARGE); - - Assert - .assertEquals(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()), ""); - Assert.assertEquals(contractResult.STACK_TOO_LARGE, infoById.get().getReceipt().getResult()); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(grammarAddress, testKeyForGrammarAddress, testNetAccountAddress, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset001.java deleted file mode 100644 index 03aafbaa558..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset001.java +++ /dev/null @@ -1,316 +0,0 @@ -package stest.tron.wallet.dailybuild.assetmarket; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.GrpcAPI.Return.response_code; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.MarketOrder; -import org.tron.protos.Protocol.MarketOrderList; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Result.code; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class MarketSellAsset001 { - - private static final long now = System.currentTimeMillis(); - private static final String name = "testAssetIssue003_" + Long.toString(now); - private static final String shortname = "a"; - private final String foundationKey001 = - Configuration.getByPath("testng.conf").getString("foundationAccount.key1"); - private final String foundationKey002 = - Configuration.getByPath("testng.conf").getString("foundationAccount.key2"); - private final byte[] foundationAddress001 = PublicMethed.getFinalAddress(foundationKey001); - private final byte[] foundationAddress002 = PublicMethed.getFinalAddress(foundationKey002); - String description = - Configuration.getByPath("testng.conf").getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf").getString("defaultParameter.assetUrl"); - - ECKey ecKey001 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey001.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey001.getPrivKeyBytes()); - byte[] assetAccountId001; - - ECKey ecKey002 = new ECKey(Utils.getRandom()); - byte[] testAddress002 = ecKey002.getAddress(); - String testKey002 = ByteArray.toHexString(ecKey002.getPrivKeyBytes()); - byte[] assetAccountId002; - - long sellTokenQuantity = 100; - long buyTokenQuantity = 50; - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - public ManagedChannel channelSolidity = null; - public WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - - private String fullnode = - Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list").get(1); - public String solidityNode = - Configuration.getByPath("testng.conf").getStringList("solidityNode.ip.list").get(0); - - /** constructor. */ - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(solidityNode).usePlaintext().build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - PublicMethed.printAddress(testKey001); - PublicMethed.printAddress(testKey002); - - Assert.assertTrue( - PublicMethed.sendcoin( - testAddress001, - 20000_000000L, - foundationAddress001, - foundationKey001, - blockingStubFull)); - Assert.assertTrue( - PublicMethed.sendcoin( - testAddress002, - 20000_000000L, - foundationAddress001, - foundationKey001, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long start = System.currentTimeMillis() + 5000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue( - PublicMethed.createAssetIssue( - testAddress001, - name, - 10000_000000L, - 1, - 1, - start, - end, - 1, - description, - url, - 10000L, - 10000L, - 1L, - 1L, - testKey001, - blockingStubFull)); - - start = System.currentTimeMillis() + 5000; - end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue( - PublicMethed.createAssetIssue( - testAddress002, - name, - 10000_000000L, - 1, - 1, - start, - end, - 1, - description, - url, - 10000L, - 10000L, - 1L, - 1L, - testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountId001 = - PublicMethed.queryAccount(testAddress001, blockingStubFull) - .getAssetIssuedID() - .toByteArray(); - - assetAccountId002 = - PublicMethed.queryAccount(testAddress002, blockingStubFull) - .getAssetIssuedID() - .toByteArray(); - } - - @Test(enabled = true, description = "create sellOrder") - void marketSellAssetTest001() { - - String txid = - PublicMethed.marketSellAsset( - testAddress001, - testKey001, - assetAccountId001, - sellTokenQuantity, - assetAccountId002, - buyTokenQuantity, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(txid); - - Optional transaction = PublicMethed.getTransactionById(txid, blockingStubFull); - - Assert.assertEquals(transaction.get().getRet(0).getRet(), code.SUCESS); - - Optional orderList = - PublicMethed.getMarketOrderByAccount(testAddress001, blockingStubFull); - Assert.assertTrue(orderList.get().getOrdersCount() > 0); - - byte[] orderId = orderList.get().getOrders(0).getOrderId().toByteArray(); - - MarketOrder order = PublicMethed.getMarketOrderById(orderId, blockingStubFull).get(); - - Assert.assertEquals(order.getOrderId().toByteArray(), orderId); - Assert.assertEquals(order.getOwnerAddress().toByteArray(), testAddress001); - Assert.assertEquals(order.getSellTokenId().toByteArray(), assetAccountId001); - Assert.assertEquals(order.getSellTokenQuantity(), sellTokenQuantity); - Assert.assertEquals(order.getBuyTokenId().toByteArray(), assetAccountId002); - Assert.assertEquals(order.getBuyTokenQuantity(), buyTokenQuantity); - - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - Optional transactionFromSolidity = - PublicMethed.getTransactionByIdSolidity(txid, blockingStubSolidity); - Assert.assertEquals(transaction, transactionFromSolidity); - } - - @Test(enabled = true, description = "create sellOrder with value excption") - void marketSellAssetTest002() { - - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] testAddress = ecKey.getAddress(); - String testKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - long sendCoinValue = 10000_000000L; - Assert.assertTrue( - PublicMethed.sendcoin( - testAddress, sendCoinValue, foundationAddress001, foundationKey001, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long sellTokenQuantity = 100; - long buyTokenQuantity = 50; - - Return resposne = - PublicMethed.marketSellAssetGetResposne( - testAddress, - testKey, - assetAccountId001, - sellTokenQuantity, - assetAccountId002, - buyTokenQuantity, - blockingStubFull); - Assert.assertEquals( - ByteArray.toStr(resposne.getMessage().toByteArray()), - "Contract validate error : SellToken balance is not enough !"); - Assert.assertEquals(resposne.getCode(), response_code.CONTRACT_VALIDATE_ERROR); - - resposne = - PublicMethed.marketSellAssetGetResposne( - testAddress, - testKey, - assetAccountId001, - 0, - assetAccountId002, - buyTokenQuantity, - blockingStubFull); - Assert.assertEquals( - ByteArray.toStr(resposne.getMessage().toByteArray()), - "Contract validate error : token quantity must greater than zero"); - Assert.assertEquals(resposne.getCode(), response_code.CONTRACT_VALIDATE_ERROR); - - Account account = PublicMethed.queryAccount(testAddress, blockingStubFull); - Assert.assertEquals(account.getBalance(), sendCoinValue); - } - - @Test(enabled = true, description = "create sellOrder with tokenId excption") - void marketSellAssetTest003() { - - long beforeBalance = PublicMethed.queryAccount(testAddress001, blockingStubFull).getBalance(); - logger.info("BeforeBalance: " + beforeBalance); - - Return resposne = - PublicMethed.marketSellAssetGetResposne( - testAddress001, - testKey001, - "xxxx".getBytes(), - sellTokenQuantity, - assetAccountId002, - buyTokenQuantity, - blockingStubFull); - Assert.assertEquals( - ByteArray.toStr(resposne.getMessage().toByteArray()), - "Contract validate error : sellTokenId is not a valid number"); - Assert.assertEquals(resposne.getCode(), response_code.CONTRACT_VALIDATE_ERROR); - - resposne = - PublicMethed.marketSellAssetGetResposne( - testAddress001, - testKey001, - assetAccountId001, - sellTokenQuantity, - "xxx".getBytes(), - buyTokenQuantity, - blockingStubFull); - Assert.assertEquals( - ByteArray.toStr(resposne.getMessage().toByteArray()), - "Contract validate error : buyTokenId is not a valid number"); - Assert.assertEquals(resposne.getCode(), response_code.CONTRACT_VALIDATE_ERROR); - - resposne = - PublicMethed.marketSellAssetGetResposne( - testAddress001, - testKey001, - "10001039999".getBytes(), - sellTokenQuantity, - assetAccountId002, - buyTokenQuantity, - blockingStubFull); - Assert.assertEquals( - ByteArray.toStr(resposne.getMessage().toByteArray()), - "Contract validate error : No sellTokenId !"); - Assert.assertEquals(resposne.getCode(), response_code.CONTRACT_VALIDATE_ERROR); - - resposne = - PublicMethed.marketSellAssetGetResposne( - testAddress001, - testKey001, - assetAccountId001, - sellTokenQuantity, - "10001039999".getBytes(), - buyTokenQuantity, - blockingStubFull); - Assert.assertEquals( - ByteArray.toStr(resposne.getMessage().toByteArray()), - "Contract validate error : No buyTokenId !"); - Assert.assertEquals(resposne.getCode(), response_code.CONTRACT_VALIDATE_ERROR); - - resposne = - PublicMethed.marketSellAssetGetResposne( - testAddress001, - testKey001, - assetAccountId001, - sellTokenQuantity, - assetAccountId001, - buyTokenQuantity, - blockingStubFull); - Assert.assertEquals( - ByteArray.toStr(resposne.getMessage().toByteArray()), - "Contract validate error : cannot exchange same tokens"); - Assert.assertEquals(resposne.getCode(), response_code.CONTRACT_VALIDATE_ERROR); - - long afterBalance = PublicMethed.queryAccount(testAddress002, blockingStubFull).getBalance(); - logger.info("AfterBalance: " + afterBalance); - - Assert.assertEquals(beforeBalance, afterBalance); - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset002.java deleted file mode 100644 index 15cee662117..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset002.java +++ /dev/null @@ -1,374 +0,0 @@ -package stest.tron.wallet.dailybuild.assetmarket; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Map; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.GrpcAPI.Return.response_code; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.MarketOrder; -import org.tron.protos.Protocol.MarketOrderList; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Result.code; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class MarketSellAsset002 { - - private static final long now = System.currentTimeMillis(); - private static final String name = "testAssetIssue003_" + Long.toString(now); - private static final String shortname = "a"; - private final String foundationKey001 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String foundationKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] foundationAddress001 = PublicMethed.getFinalAddress(foundationKey001); - private final byte[] foundationAddress002 = PublicMethed.getFinalAddress(foundationKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - ECKey ecKey001 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey001.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey001.getPrivKeyBytes()); - byte[] assetAccountId001; - - ECKey ecKey002 = new ECKey(Utils.getRandom()); - byte[] testAddress002 = ecKey002.getAddress(); - String testKey002 = ByteArray.toHexString(ecKey002.getPrivKeyBytes()); - byte[] assetAccountId002; - - long sellTokenQuantity = 100; - long buyTokenQuantity = 50; - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(1); - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(testKey001); - PublicMethed.printAddress(testKey002); - - Assert.assertTrue(PublicMethed.sendcoin(testAddress001, 20000_000000L, foundationAddress001, - foundationKey001, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(testAddress002, 20000_000000L, foundationAddress001, - foundationKey001, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long start = System.currentTimeMillis() + 5000; - Long end = System.currentTimeMillis() + 1000000000; - Assert - .assertTrue(PublicMethed.createAssetIssue(testAddress001, name, 10000_000000L, 1, 1, start, - end, 1, description, url, 10000L, 10000L, 1L, 1L, testKey001, blockingStubFull)); - - start = System.currentTimeMillis() + 5000; - end = System.currentTimeMillis() + 1000000000; - Assert - .assertTrue(PublicMethed.createAssetIssue(testAddress002, name, 10000_000000L, 1, 1, start, - end, 1, description, url, 10000L, 10000L, 1L, 1L, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountId001 = - PublicMethed.queryAccount(testAddress001, blockingStubFull).getAssetIssuedID() - .toByteArray(); - - assetAccountId002 = - PublicMethed.queryAccount(testAddress002, blockingStubFull).getAssetIssuedID() - .toByteArray(); - } - - - @Test(enabled = true, description = "create sellOrder and Match Order") - void marketSellAssetTest001() { - - Map beforeAsset001 = PublicMethed - .queryAccount(testAddress001, blockingStubFull).getAssetV2Map(); - Map beforeAsset002 = PublicMethed - .queryAccount(testAddress002, blockingStubFull).getAssetV2Map(); - - logger.info("beforeAsset001: " + beforeAsset001); - logger.info("beforeAsset002: " + beforeAsset002); - - String txid = PublicMethed - .marketSellAsset(testAddress001, testKey001, assetAccountId001, sellTokenQuantity, - assetAccountId002, buyTokenQuantity, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(txid); - - Optional transaction = PublicMethed - .getTransactionById(txid, blockingStubFull); - Assert.assertEquals(transaction.get().getRet(0).getRet(), code.SUCESS); - - Optional orderList = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull); - Assert.assertTrue(orderList.get().getOrdersCount() > 0); - - byte[] orderId = orderList.get().getOrders(0).getOrderId().toByteArray(); - - String txid2 = PublicMethed.marketSellAsset(testAddress002, testKey002, assetAccountId002, - buyTokenQuantity, assetAccountId001, sellTokenQuantity, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(txid2); - - transaction = PublicMethed - .getTransactionById(txid2, blockingStubFull); - Assert.assertEquals(transaction.get().getRet(0).getRet(), code.SUCESS); - - Map afterAsset001 = PublicMethed.queryAccount(testAddress001, blockingStubFull) - .getAssetV2Map(); - Map afterAsset002 = PublicMethed.queryAccount(testAddress002, blockingStubFull) - .getAssetV2Map(); - - logger.info("afterAsset001: " + afterAsset001); - logger.info("afterAsset002: " + afterAsset002); - - String assetId001 = ByteArray.toStr(assetAccountId001); - String assetId002 = ByteArray.toStr(assetAccountId002); - Assert.assertEquals((beforeAsset001.get(assetId001) - sellTokenQuantity), - afterAsset001.get(assetId001).longValue()); - Assert.assertEquals((buyTokenQuantity), afterAsset001.get(assetId002).longValue()); - - Assert.assertEquals(beforeAsset002.get(assetId002) - buyTokenQuantity, - afterAsset002.get(assetId002).longValue()); - Assert.assertEquals(sellTokenQuantity, afterAsset002.get(assetId001).longValue()); - - - } - - @Test(enabled = true, description = "create sellOrder and Match Order twice") - void marketSellAssetTest002() { - Map beforeAsset001 = PublicMethed.queryAccount(testAddress001, blockingStubFull) - .getAssetV2Map(); - Map beforeAsset002 = PublicMethed.queryAccount(testAddress002, blockingStubFull) - .getAssetV2Map(); - - logger.info("beforeAsset001: " + beforeAsset001); - logger.info("beforeAsset002: " + beforeAsset002); - - String txid = PublicMethed.marketSellAsset(testAddress001, testKey001, assetAccountId001, - sellTokenQuantity * 2, - assetAccountId002, buyTokenQuantity * 2, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(txid); - - logger.info("beforeAsset001 :" - + PublicMethed.queryAccount(testAddress001, blockingStubFull).getAssetV2Map()); - logger.info("beforeAsset002 :" - + PublicMethed.queryAccount(testAddress002, blockingStubFull).getAssetV2Map()); - - Optional transaction = PublicMethed - .getTransactionById(txid, blockingStubFull); - Assert.assertEquals(transaction.get().getRet(0).getRet(), code.SUCESS); - - Optional orderList = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull); - Assert.assertTrue(orderList.get().getOrdersCount() > 0); - - byte[] orderId; - orderId = orderList.get().getOrders(0).getOrderId().toByteArray(); - - String txid2 = PublicMethed.marketSellAsset(testAddress002, testKey002, assetAccountId002, - buyTokenQuantity, assetAccountId001, sellTokenQuantity, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(txid2); - - transaction = PublicMethed - .getTransactionById(txid2, blockingStubFull); - Assert.assertEquals(transaction.get().getRet(0).getRet(), code.SUCESS); - - // get order Message and RemainSellTokenQuantity - MarketOrder order001 = PublicMethed - .getMarketOrderById(orderId, blockingStubFull).get(); - Assert.assertEquals(order001.getSellTokenQuantityRemain(), sellTokenQuantity); - - Map afterAsset001 = PublicMethed.queryAccount(testAddress001, blockingStubFull) - .getAssetV2Map(); - Map afterAsset002 = PublicMethed.queryAccount(testAddress002, blockingStubFull) - .getAssetV2Map(); - - logger.info("afterAsset001: " + afterAsset001); - logger.info("afterAsset002: " + afterAsset002); - - String assetId001 = ByteArray.toStr(assetAccountId001); - String assetId002 = ByteArray.toStr(assetAccountId002); - Assert.assertEquals((beforeAsset001.get(assetId001) - sellTokenQuantity * 2), - afterAsset001.get(assetId001).longValue()); - Assert.assertEquals((beforeAsset001.get(assetId002) + buyTokenQuantity), - afterAsset001.get(assetId002).longValue()); - - Assert.assertEquals(beforeAsset002.get(assetId002) - buyTokenQuantity, - afterAsset002.get(assetId002).longValue()); - Assert.assertEquals(beforeAsset002.get(assetId001) + sellTokenQuantity, - afterAsset002.get(assetId001).longValue()); - - - String txid3 = PublicMethed.marketSellAsset(testAddress002, testKey002, assetAccountId002, - buyTokenQuantity, assetAccountId001, sellTokenQuantity, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(txid3); - - transaction = PublicMethed - .getTransactionById(txid3, blockingStubFull); - Assert.assertEquals(transaction.get().getRet(0).getRet(), code.SUCESS); - - // get order Message and RemainSellTokenQuantity - order001 = PublicMethed - .getMarketOrderById(orderId, blockingStubFull).get(); - Assert.assertEquals(order001.getSellTokenQuantityRemain(), 0); - - afterAsset001 = PublicMethed.queryAccount(testAddress001, blockingStubFull) - .getAssetV2Map(); - afterAsset002 = PublicMethed.queryAccount(testAddress002, blockingStubFull) - .getAssetV2Map(); - - logger.info("afterAsset001: " + afterAsset001); - logger.info("afterAsset002: " + afterAsset002); - - Assert.assertEquals((beforeAsset001.get(assetId001) - sellTokenQuantity * 2), - afterAsset001.get(assetId001).longValue()); - Assert.assertEquals((beforeAsset001.get(assetId002) + buyTokenQuantity * 2), - afterAsset001.get(assetId002).longValue()); - - Assert.assertEquals(beforeAsset002.get(assetId002) - buyTokenQuantity * 2, - afterAsset002.get(assetId002).longValue()); - Assert.assertEquals(beforeAsset002.get(assetId001) + sellTokenQuantity * 2, - afterAsset002.get(assetId001).longValue()); - - - - } - - @Test(enabled = true, description = "create sellOrder and not Match Order") - void marketSellAssetTest003() { - - Map beforeAsset001 = PublicMethed - .queryAccount(testAddress001, blockingStubFull).getAssetV2Map(); - Map beforeAsset002 = PublicMethed - .queryAccount(testAddress002, blockingStubFull).getAssetV2Map(); - - logger.info("beforeAsset001: " + beforeAsset001); - logger.info("beforeAsset002: " + beforeAsset002); - - String txid = PublicMethed - .marketSellAsset(testAddress001, testKey001, assetAccountId001, sellTokenQuantity, - assetAccountId002, buyTokenQuantity, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(txid); - - Optional transaction = PublicMethed - .getTransactionById(txid, blockingStubFull); - Assert.assertEquals(transaction.get().getRet(0).getRet(), code.SUCESS); - - Optional orderList = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull); - Assert.assertTrue(orderList.get().getOrdersCount() > 0); - - byte[] orderId = orderList.get().getOrders(0).getOrderId().toByteArray(); - - String txid2 = PublicMethed.marketSellAsset(testAddress002, testKey002, assetAccountId002, - buyTokenQuantity * 2, assetAccountId001, sellTokenQuantity * 5, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(txid2); - - transaction = PublicMethed - .getTransactionById(txid2, blockingStubFull); - Assert.assertEquals(transaction.get().getRet(0).getRet(), code.SUCESS); - - Map afterAsset001 = PublicMethed.queryAccount(testAddress001, blockingStubFull) - .getAssetV2Map(); - Map afterAsset002 = PublicMethed.queryAccount(testAddress002, blockingStubFull) - .getAssetV2Map(); - - logger.info("afterAsset001: " + afterAsset001); - logger.info("afterAsset002: " + afterAsset002); - - String assetId001 = ByteArray.toStr(assetAccountId001); - String assetId002 = ByteArray.toStr(assetAccountId002); - Assert.assertEquals((beforeAsset001.get(assetId001) - sellTokenQuantity), - afterAsset001.get(assetId001).longValue()); - Assert.assertEquals((beforeAsset001.get(assetId002).longValue()), - afterAsset001.get(assetId002).longValue()); - - Assert.assertEquals(beforeAsset002.get(assetId002) - buyTokenQuantity * 2, - afterAsset002.get(assetId002).longValue()); - Assert.assertEquals(beforeAsset002.get(assetId001).longValue(), - afterAsset002.get(assetId001).longValue()); - } - - @Test(enabled = true, description = "CancelOrder") - void marketSellAssetTest004() { - - Map beforeAsset001 = PublicMethed - .queryAccount(testAddress001, blockingStubFull).getAssetV2Map(); - - logger.info("beforeAsset001: " + beforeAsset001); - - Optional orderList = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull); - Assert.assertTrue(orderList.get().getOrdersCount() > 0); - - Long sellTokenQuantity001; - byte[] tokenId; - byte[] orderId001; - - orderId001 = orderList.get().getOrders(0).getOrderId().toByteArray(); - tokenId = orderList.get().getOrders(0).getSellTokenId().toByteArray(); - sellTokenQuantity001 = orderList.get().getOrders(0).getSellTokenQuantityRemain(); - - String txid = PublicMethed.marketCancelOrder(testAddress001, testKey001, orderId001, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(txid); - - Optional transaction = PublicMethed - .getTransactionById(txid, blockingStubFull); - Assert.assertEquals(transaction.get().getRet(0).getRet(), code.SUCESS); - - Map afterAsset001 = PublicMethed.queryAccount(testAddress001, blockingStubFull) - .getAssetV2Map(); - - logger.info("afterAsset001: " + afterAsset001); - - String assetId001 = ByteArray.toStr(tokenId); - - Assert.assertEquals(beforeAsset001.get(assetId001) + sellTokenQuantity001, - afterAsset001.get(assetId001).longValue()); - - Return response = PublicMethed - .marketCancelOrderGetResposne(testAddress001, testKey001, orderId001, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(response); - Assert.assertEquals(response.getCode(), response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ByteArray.toStr(response.getMessage().toByteArray()).toLowerCase(), - "contract validate error : Order is not active!".toLowerCase()); - - - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset003.java deleted file mode 100644 index 16dd38a5cee..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset003.java +++ /dev/null @@ -1,155 +0,0 @@ -package stest.tron.wallet.dailybuild.assetmarket; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.MarketOrderList; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j - -public class MarketSellAsset003 { - - private static final long now = System.currentTimeMillis(); - private static final String name = "testAssetIssue003_" + Long.toString(now); - private static final String shortname = "a"; - private final String foundationKey001 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String foundationKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] foundationAddress001 = PublicMethed.getFinalAddress(foundationKey001); - private final byte[] foundationAddress002 = PublicMethed.getFinalAddress(foundationKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - byte [] trx = ByteArray.fromString("_"); - - - ECKey ecKey001 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey001.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey001.getPrivKeyBytes()); - byte[] assetAccountId001; - - ECKey ecKey002 = new ECKey(Utils.getRandom()); - byte[] testAddress002 = ecKey002.getAddress(); - String testKey002 = ByteArray.toHexString(ecKey002.getPrivKeyBytes()); - byte[] assetAccountId002; - - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(1); - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(testKey001); - PublicMethed.printAddress(testKey002); - - Assert.assertTrue(PublicMethed.sendcoin(testAddress001, 20000_000000L, foundationAddress001, - foundationKey001, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(testAddress002, 20000_000000L, foundationAddress001, - foundationKey001, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long start = System.currentTimeMillis() + 5000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed.createAssetIssue(testAddress001, name, 10000_000000L, - 1, 1, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, testKey001, blockingStubFull)); - - start = System.currentTimeMillis() + 5000; - end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed.createAssetIssue(testAddress002, name, 10000_000000L, - 1, 1, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountId001 = PublicMethed.queryAccount(testAddress001, blockingStubFull) - .getAssetIssuedID().toByteArray(); - - assetAccountId002 = PublicMethed.queryAccount(testAddress002, blockingStubFull) - .getAssetIssuedID().toByteArray(); - } - - - @Test(enabled = true, description = "CancelOrder") - void marketCancelAssetTest001() { - - String txid = PublicMethed.marketSellAsset(testAddress001, testKey001, assetAccountId001, 100, - trx, 50, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional transaction = PublicMethed - .getTransactionById(txid, blockingStubFull); - logger.info("transaction: " + transaction); - Assert.assertEquals(transaction.get().getRet(0).getRet().toString(), "SUCESS"); - - Optional orderList = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(orderList.get().getOrdersCount() > 0); - byte[] orderId = orderList.get().getOrders(0).getOrderId().toByteArray(); - txid = PublicMethed.marketCancelOrder(testAddress001, testKey001, orderId, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - transaction = PublicMethed - .getTransactionById(txid, blockingStubFull); - Assert.assertEquals(transaction.get().getRet(0).getRet().toString(), "SUCESS"); - - orderList = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull); - Assert.assertTrue(orderList.get().getOrdersCount() == 0); - - } - - @Test(enabled = true, description = "Cancel a cancelled order ") - void marketCancelAssetTest002() { - - String txid = PublicMethed.marketSellAsset(testAddress001, testKey001, assetAccountId001, 100, - trx, 50, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional transaction = PublicMethed - .getTransactionById(txid, blockingStubFull); - logger.info("transaction: " + transaction); - Assert.assertEquals(transaction.get().getRet(0).getRet().toString(), "SUCESS"); - - Optional orderList = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(orderList.get().getOrdersCount() > 0); - byte[] orderId = orderList.get().getOrders(0).getOrderId().toByteArray(); - txid = PublicMethed.marketCancelOrder(testAddress001, testKey001, orderId, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - transaction = PublicMethed - .getTransactionById(txid, blockingStubFull); - Assert.assertEquals(transaction.get().getRet(0).getRet().toString(), "SUCESS"); - orderList = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull); - Assert.assertTrue(orderList.get().getOrdersCount() == 0); - - Assert.assertEquals(PublicMethed.marketCancelOrder(testAddress001, testKey001, orderId, - blockingStubFull).toLowerCase(), - "contract validate error : Order is not active!".toLowerCase()); - - - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset004.java deleted file mode 100644 index fae498c2a1f..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset004.java +++ /dev/null @@ -1,113 +0,0 @@ -package stest.tron.wallet.dailybuild.assetmarket; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.MarketOrderList; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j - -public class MarketSellAsset004 { - private static final long now = System.currentTimeMillis(); - private static final String name = "testAssetIssue003_" + Long.toString(now); - private static final String shortname = "a"; - private final String foundationKey001 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String foundationKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] foundationAddress001 = PublicMethed.getFinalAddress(foundationKey001); - private final byte[] foundationAddress002 = PublicMethed.getFinalAddress(foundationKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - byte [] trx = ByteArray.fromString("_"); - - - ECKey ecKey001 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey001.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey001.getPrivKeyBytes()); - byte[] assetAccountId001; - - ECKey ecKey002 = new ECKey(Utils.getRandom()); - byte[] testAddress002 = ecKey002.getAddress(); - String testKey002 = ByteArray.toHexString(ecKey002.getPrivKeyBytes()); - byte[] assetAccountId002; - - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(1); - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(testKey001); - PublicMethed.printAddress(testKey002); - - Assert.assertTrue(PublicMethed.sendcoin(testAddress001,20000_000000L,foundationAddress001, - foundationKey001,blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(testAddress002,20000_000000L,foundationAddress001, - foundationKey001,blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long start = System.currentTimeMillis() + 5000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed.createAssetIssue(testAddress001,name,10000_000000L,1,1,start, - end,1,description,url,10000L,10000L,1L, 1L,testKey001,blockingStubFull)); - - start = System.currentTimeMillis() + 5000; - end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed.createAssetIssue(testAddress002,name,10000_000000L,1,1,start, - end,1,description,url,10000L,10000L,1L, 1L,testKey002,blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountId001 = PublicMethed.queryAccount(testAddress001, blockingStubFull) - .getAssetIssuedID().toByteArray(); - - assetAccountId002 = PublicMethed.queryAccount(testAddress002, blockingStubFull) - .getAssetIssuedID().toByteArray(); - } - - - @Test(enabled = true,description = "The order amount exceeds the balance") - void marketCancelAssetTest002() { - - String txid = PublicMethed.marketSellAsset(testAddress001,testKey001,assetAccountId001,100, - trx,50,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional transaction = PublicMethed - .getTransactionById(txid, blockingStubFull); - logger.info("transaction: " + transaction); - Assert.assertEquals(transaction.get().getRet(0).getRet().toString(), "SUCESS"); - - Optional orderList = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(orderList.get().getOrdersCount() > 0); - byte[] orderId = orderList.get().getOrders(0).getOrderId().toByteArray(); - txid = PublicMethed.marketCancelOrder(testAddress001,testKey001,orderId,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - - - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset005.java deleted file mode 100644 index e0cbb6caee6..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset005.java +++ /dev/null @@ -1,160 +0,0 @@ -package stest.tron.wallet.dailybuild.assetmarket; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Map; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j - -public class MarketSellAsset005 { - - private static final long now = System.currentTimeMillis(); - private static final String name = "testAssetIssue003_" + Long.toString(now); - private static final String shortname = "a"; - private final String foundationKey001 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String foundationKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] foundationAddress001 = PublicMethed.getFinalAddress(foundationKey001); - private final byte[] foundationAddress002 = PublicMethed.getFinalAddress(foundationKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - long sellTokenQuantity = 100; - long buyTokenQuantity = 50; - byte [] trx = ByteArray.fromString("_"); - - - ECKey ecKey001 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey001.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey001.getPrivKeyBytes()); - byte[] assetAccountId001; - ByteString assetAccountId; - - ECKey ecKey002 = new ECKey(Utils.getRandom()); - byte[] testAddress002 = ecKey002.getAddress(); - String testKey002 = ByteArray.toHexString(ecKey002.getPrivKeyBytes()); - byte[] assetAccountId002; - - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(1); - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(testKey001); - PublicMethed.printAddress(testKey002); - - Assert.assertTrue(PublicMethed.sendcoin(testAddress001,2024_000000L,foundationAddress001, - foundationKey001,blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(testAddress002,2024_000000L,foundationAddress001, - foundationKey001,blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long start = System.currentTimeMillis() + 5000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed.createAssetIssue(testAddress001,name,10000_000000L,1,1,start, - end,1,description,url,10000L,10000L,1L, 1L,testKey001,blockingStubFull)); - - - assetAccountId001 = PublicMethed.queryAccount(testAddress001, blockingStubFull) - .getAssetIssuedID().toByteArray(); - - assetAccountId = PublicMethed.queryAccount(testAddress001, blockingStubFull).getAssetIssuedID(); - - - } - - - @Test(enabled = true,description = "Create an order to sell Trx and buy Trc10") - void test01SellTrxBuyTrc10() { - long balanceAfter = PublicMethed.queryAccount(testKey001, blockingStubFull).getBalance(); - PublicMethed.transferAsset(testAddress002, assetAccountId001, 10000, testAddress001, - testKey001, blockingStubFull); - final Map beforeAsset001 = PublicMethed.queryAccount(testAddress001, - blockingStubFull).getAssetV2Map(); - - String txid = PublicMethed.marketSellAsset(testAddress002,testKey002,trx, - sellTokenQuantity,assetAccountId001, - buyTokenQuantity,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional transaction = PublicMethed - .getTransactionById(txid, blockingStubFull); - logger.info("transaction: " + transaction); - Assert.assertEquals(transaction.get().getRet(0).getRet().toString(), "SUCESS"); - - logger.info("beforeAsset001: " + beforeAsset001); - - txid = PublicMethed.marketSellAsset(testAddress001, testKey001, assetAccountId001, - sellTokenQuantity * 2, - trx, buyTokenQuantity * 2, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(txid); - - - Map afterAsset001 = PublicMethed.queryAccount(testAddress001, blockingStubFull) - .getAssetV2Map(); - - logger.info("afterAsset001: " + afterAsset001); - - String assetId001 = ByteArray.toStr(assetAccountId001); - Assert.assertEquals((beforeAsset001.get(assetId001) - sellTokenQuantity * 2), - afterAsset001.get(assetId001).longValue()); - - } - - @Test(enabled = true,description = "Create an order to sell Trc10 and buy Trx") - void test02SellTrc10BuyTrx() { - long balanceAfter = PublicMethed.queryAccount(testKey001, blockingStubFull).getBalance(); - - final Map beforeAsset001 = PublicMethed.queryAccount(testAddress001, - blockingStubFull).getAssetV2Map(); - - String txid = PublicMethed.marketSellAsset(testAddress002,testKey002,assetAccountId001, - sellTokenQuantity,trx, - buyTokenQuantity,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional transaction = PublicMethed - .getTransactionById(txid, blockingStubFull); - logger.info("transaction: " + transaction); - Assert.assertEquals(transaction.get().getRet(0).getRet().toString(), "SUCESS"); - - logger.info("beforeAsset001: " + beforeAsset001); - - txid = PublicMethed.marketSellAsset(testAddress001, testKey001, trx, - sellTokenQuantity * 2, - assetAccountId001, buyTokenQuantity * 2, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(txid); - - - - } - - - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset006.java deleted file mode 100644 index 8499963ccd2..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/assetmarket/MarketSellAsset006.java +++ /dev/null @@ -1,288 +0,0 @@ -package stest.tron.wallet.dailybuild.assetmarket; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.MarketOrder; -import org.tron.protos.Protocol.MarketOrderList; -import org.tron.protos.Protocol.MarketOrderPairList; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Result.code; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j - - -public class MarketSellAsset006 { - - private static final long now = System.currentTimeMillis(); - private static final String name = "testAssetIssue003_" + Long.toString(now); - private static final String shortname = "a"; - private final String foundationKey001 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String foundationKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] foundationAddress001 = PublicMethed.getFinalAddress(foundationKey001); - private final byte[] foundationAddress002 = PublicMethed.getFinalAddress(foundationKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - ECKey ecKey001 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey001.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey001.getPrivKeyBytes()); - byte[] assetAccountId001; - - ECKey ecKey002 = new ECKey(Utils.getRandom()); - byte[] testAddress002 = ecKey002.getAddress(); - String testKey002 = ByteArray.toHexString(ecKey002.getPrivKeyBytes()); - byte[] assetAccountId002; - - long sellTokenQuantity = 100; - long buyTokenQuantity = 50; - - private ManagedChannel channelFull = null; - - private ManagedChannel channelSolidity = null; - - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - - public ManagedChannel channelPbft = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubRealSolidity = null; - public WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPbft = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String realSoliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - private String soliInPbft = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(2); - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext() - .build(); - blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); - PublicMethed.printAddress(testKey001); - PublicMethed.printAddress(testKey002); - - Assert.assertTrue(PublicMethed.sendcoin(testAddress001, 20000_000000L, foundationAddress001, - foundationKey001, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(testAddress002, 20000_000000L, foundationAddress001, - foundationKey001, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long start = System.currentTimeMillis() + 5000; - Long end = System.currentTimeMillis() + 1000000000; - Assert - .assertTrue(PublicMethed.createAssetIssue(testAddress001, name, 10000_000000L, 1, 1, start, - end, 1, description, url, 10000L, 10000L, 1L, 1L, testKey001, blockingStubFull)); - - start = System.currentTimeMillis() + 5000; - end = System.currentTimeMillis() + 1000000000; - Assert - .assertTrue(PublicMethed.createAssetIssue(testAddress002, name, 10000_000000L, 1, 1, start, - end, 1, description, url, 10000L, 10000L, 1L, 1L, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountId001 = PublicMethed.queryAccount(testAddress001, blockingStubFull) - .getAssetIssuedID().toByteArray(); - - assetAccountId002 = PublicMethed.queryAccount(testAddress002, blockingStubFull) - .getAssetIssuedID().toByteArray(); - } - - - @Test(enabled = true, description = "create sellOrder") - void marketSellAssetTest001() { - - String txid = PublicMethed.marketSellAsset(testAddress001, testKey001, assetAccountId001, - sellTokenQuantity, assetAccountId002, buyTokenQuantity, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(txid); - - Optional transaction = PublicMethed - .getTransactionById(txid, blockingStubFull); - Assert.assertEquals(transaction.get().getRet(0).getRet(), code.SUCESS); - - Optional orderList = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull); - Assert.assertTrue(orderList.get().getOrdersCount() > 0); - - byte[] orderId = orderList.get().getOrders(0).getOrderId().toByteArray(); - - MarketOrder order = PublicMethed - .getMarketOrderById(orderId, blockingStubFull).get(); - - Assert.assertEquals(order.getOrderId().toByteArray(), orderId); - Assert.assertEquals(order.getOwnerAddress().toByteArray(), testAddress001); - Assert.assertEquals(order.getSellTokenId().toByteArray(), assetAccountId001); - Assert.assertEquals(order.getSellTokenQuantity(), sellTokenQuantity); - Assert.assertEquals(order.getBuyTokenId().toByteArray(), assetAccountId002); - Assert.assertEquals(order.getBuyTokenQuantity(), buyTokenQuantity); - - } - - @Test(enabled = false, description = "getMarketPairList from solidity and pbft") - void marketSellAssetTest002() { - Optional pairList = PublicMethed - .getMarketPairList(blockingStubFull); - - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull,blockingStubSolidity); - - Optional pairList2 = PublicMethed - .getMarketPairListSolidity(blockingStubSolidity); - - - Optional pairList3 = PublicMethed - .getMarketPairListSolidity(blockingStubPbft); - - Assert.assertEquals(pairList,pairList2); - Assert.assertEquals(pairList,pairList3); - - - - } - - @Test(enabled = true, description = "getMarketOrderListByPair from solidity and pbft") - void marketSellAssetTest003() { - Optional orderList = PublicMethed - .getMarketOrderListByPair(assetAccountId001,assetAccountId002,blockingStubFull); - - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull,blockingStubSolidity); - - Optional orderList2 = PublicMethed - .getMarketOrderListByPairSolidity(assetAccountId001,assetAccountId002,blockingStubSolidity); - - - Optional orderList3 = PublicMethed - .getMarketOrderListByPairSolidity(assetAccountId001,assetAccountId002,blockingStubPbft); - - System.out.println(orderList3); - - Assert.assertEquals(orderList,orderList2); - Assert.assertEquals(orderList,orderList3); - - } - - - @Test(enabled = true, description = "GetMarketOrderById from solidity and pbft") - void marketSellAssetTest004() { - Optional orderList = PublicMethed - .getMarketOrderListByPair(assetAccountId001,assetAccountId002,blockingStubFull); - - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull,blockingStubSolidity); - - Optional orderList2 = PublicMethed - .getMarketOrderListByPairSolidity(assetAccountId001,assetAccountId002,blockingStubSolidity); - - - Optional orderList3 = PublicMethed - .getMarketOrderListByPairSolidity(assetAccountId001,assetAccountId002,blockingStubPbft); - - System.out.println(orderList3); - - Assert.assertEquals(orderList,orderList2); - Assert.assertEquals(orderList,orderList3); - - } - - - @Test(enabled = true, description = "GetMarketOrderByAccount from solidity and pbft") - void marketSellAssetTest005() { - - Optional orderList = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull); - Assert.assertTrue(orderList.get().getOrdersCount() > 0); - - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull,blockingStubSolidity); - - Optional orderList2 = PublicMethed - .getMarketOrderByAccountSolidity(testAddress001, blockingStubSolidity); - Assert.assertTrue(orderList2.get().getOrdersCount() > 0); - - - Optional orderList3 = PublicMethed - .getMarketOrderByAccountSolidity(testAddress001, blockingStubPbft); - Assert.assertTrue(orderList3.get().getOrdersCount() > 0); - Assert.assertEquals(orderList,orderList2); - Assert.assertEquals(orderList,orderList3); - - } - - @Test(enabled = true, description = "GetMarketOrderById from solidity and pbft") - void marketSellAssetTest006() { - - Optional orderList = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull); - - byte[] orderId = orderList.get().getOrders(0).getOrderId().toByteArray(); - - MarketOrder order = PublicMethed - .getMarketOrderById(orderId, blockingStubFull).get(); - - Assert.assertEquals(order.getOrderId().toByteArray(), orderId); - Assert.assertEquals(order.getOwnerAddress().toByteArray(), testAddress001); - Assert.assertEquals(order.getSellTokenId().toByteArray(), assetAccountId001); - Assert.assertEquals(order.getSellTokenQuantity(), sellTokenQuantity); - Assert.assertEquals(order.getBuyTokenId().toByteArray(), assetAccountId002); - Assert.assertEquals(order.getBuyTokenQuantity(), buyTokenQuantity); - - MarketOrder order2 = PublicMethed - .getMarketOrderByIdSolidity(orderId, blockingStubSolidity).get(); - - Assert.assertEquals(order2.getOrderId().toByteArray(), orderId); - Assert.assertEquals(order2.getOwnerAddress().toByteArray(), testAddress001); - Assert.assertEquals(order2.getSellTokenId().toByteArray(), assetAccountId001); - Assert.assertEquals(order2.getSellTokenQuantity(), sellTokenQuantity); - Assert.assertEquals(order2.getBuyTokenId().toByteArray(), assetAccountId002); - Assert.assertEquals(order2.getBuyTokenQuantity(), buyTokenQuantity); - - MarketOrder order3 = PublicMethed - .getMarketOrderByIdSolidity(orderId, blockingStubPbft).get(); - - Assert.assertEquals(order3.getOrderId().toByteArray(), orderId); - Assert.assertEquals(order3.getOwnerAddress().toByteArray(), testAddress001); - Assert.assertEquals(order3.getSellTokenId().toByteArray(), assetAccountId001); - Assert.assertEquals(order3.getSellTokenQuantity(), sellTokenQuantity); - Assert.assertEquals(order3.getBuyTokenId().toByteArray(), assetAccountId002); - Assert.assertEquals(order3.getBuyTokenQuantity(), buyTokenQuantity); - - - } - - - - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventLog2.java b/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventLog2.java deleted file mode 100644 index 77362ed8284..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventLog2.java +++ /dev/null @@ -1,117 +0,0 @@ -package stest.tron.wallet.dailybuild.eventquery; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.contract.SmartContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - - - - -@Slf4j -public class EventLog2 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] mapKeyContract = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 300100_000_000L, - testNetAccountAddress, testNetAccountKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/eventLog2.sol"; - String contractName = "Event"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - mapKeyContract = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContractOuterClass.SmartContract smartContract = PublicMethed.getContract(mapKeyContract, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - - @Test(enabled = true, description = "test opcode log2") - public void test01EmitLog2() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "messageI()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - String logStr1 = ByteArray.toHexString(transactionExtention.getLogs(0).getData().toByteArray()); - Assert.assertTrue(logStr1.contains("000000000000000000000000000000000000000" - + "000000000000000000000000100000000000000000" - + "000000000000000000000000000000000000000000000010000000000000000" - + "000000000000000000000000000000000000000000000001")); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals(1, trueRes); - } - - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(contractExcAddress, contractExcKey, - testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery001.java deleted file mode 100644 index 9e4832bcea9..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery001.java +++ /dev/null @@ -1,152 +0,0 @@ -package stest.tron.wallet.dailybuild.eventquery; - -import com.alibaba.fastjson.JSONObject; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.core.Wallet; -import org.zeromq.ZMQ; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import zmq.ZMQ.Event; - -@Slf4j -public class EventQuery001 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String eventnode = Configuration.getByPath("testng.conf") - .getStringList("eventnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Event query for block") - public void test01EventQueryForBlock() { - ZMQ.Context context = ZMQ.context(1); - ZMQ.Socket req = context.socket(ZMQ.SUB); - - req.subscribe("blockTrigger"); - final ZMQ.Socket moniter = context.socket(ZMQ.PAIR); - moniter.connect("inproc://reqmoniter"); - new Thread(new Runnable() { - public void run() { - while (true) { - Event event = Event.read(moniter.base()); - System.out.println(event.event + " " + event.addr); - } - } - - }).start(); - req.connect(eventnode); - req.setReceiveTimeOut(10000); - String blockMessage = ""; - - Integer retryTimes = 20; - while (retryTimes-- > 0) { - byte[] message = req.recv(); - if (message != null) { - //System.out.println("receive : " + new String(message)); - blockMessage = new String(message); - if (!blockMessage.equals("blockTrigger") && !blockMessage.isEmpty()) { - break; - } - } - } - - Assert.assertTrue(retryTimes > 0); - logger.info("block message:" + blockMessage); - JSONObject blockObject = JSONObject.parseObject(blockMessage); - Assert.assertTrue(blockObject.containsKey("timeStamp")); - Assert.assertEquals(blockObject.getString("triggerName"), "blockTrigger"); - Assert.assertTrue(blockObject.getLong("blockNumber") > 0); - Assert.assertTrue(blockObject.containsKey("blockHash")); - Assert.assertTrue(blockObject.getInteger("transactionSize") >= 0); - } - - - @Test(enabled = true, description = "Event query for block on solidity") - public void test02EventQueryForBlockOnSolidity() { - ZMQ.Context context = ZMQ.context(1); - ZMQ.Socket req = context.socket(ZMQ.SUB); - - req.subscribe("solidityTrigger"); - final ZMQ.Socket moniter = context.socket(ZMQ.PAIR); - moniter.connect("inproc://reqmoniter"); - new Thread(new Runnable() { - public void run() { - while (true) { - Event event = Event.read(moniter.base()); - System.out.println(event.event + " " + event.addr); - } - } - - }).start(); - req.connect(eventnode); - req.setReceiveTimeOut(10000); - String blockMessage = ""; - - Integer retryTimes = 20; - - while (retryTimes-- > 0) { - byte[] message = req.recv(); - if (message != null) { - System.out.println("receive : " + new String(message)); - blockMessage = new String(message); - if (!blockMessage.equals("solidityTrigger") && !blockMessage.isEmpty()) { - break; - } - } - } - - Assert.assertTrue(retryTimes > 0); - logger.info("block message:" + blockMessage); - JSONObject blockObject = JSONObject.parseObject(blockMessage); - Assert.assertTrue(blockObject.containsKey("timeStamp")); - Assert.assertEquals(blockObject.getString("triggerName"), "solidityTrigger"); - Assert.assertTrue(blockObject.getLong("latestSolidifiedBlockNumber") > 0); - } - - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery002.java deleted file mode 100644 index 889b5f37cd1..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery002.java +++ /dev/null @@ -1,147 +0,0 @@ -package stest.tron.wallet.dailybuild.eventquery; - -import com.alibaba.fastjson.JSONObject; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.zeromq.ZMQ; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import zmq.ZMQ.Event; - -@Slf4j -public class EventQuery002 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String eventnode = Configuration.getByPath("testng.conf") - .getStringList("eventnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - byte[] contractAddress; - String txid; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] event001Address = ecKey1.getAddress(); - String event001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - ecKey1 = new ECKey(Utils.getRandom()); - event001Address = ecKey1.getAddress(); - event001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.printAddress(event001Key); - - Assert.assertTrue(PublicMethed.sendcoin(event001Address, maxFeeLimit * 30, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName = "addressDemo"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractEventAndLog1"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractEventAndLog1"); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 50, null, event001Key, event001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - - } - - @Test(enabled = true, description = "Event query for transaction") - public void test01EventQueryForTransaction() { - ZMQ.Context context = ZMQ.context(1); - ZMQ.Socket req = context.socket(ZMQ.SUB); - - req.subscribe("transactionTrigger"); - final ZMQ.Socket moniter = context.socket(ZMQ.PAIR); - moniter.connect("inproc://reqmoniter"); - new Thread(new Runnable() { - public void run() { - while (true) { - Event event = Event.read(moniter.base()); - System.out.println(event.event + " " + event.addr); - } - } - - }).start(); - req.connect(eventnode); - req.setReceiveTimeOut(10000); - String transactionMessage = ""; - Boolean sendTransaction = true; - Integer retryTimes = 20; - - while (retryTimes-- > 0) { - byte[] message = req.recv(); - if (sendTransaction) { - txid = PublicMethed.triggerContract(contractAddress, - "triggerUintEvent()", "#", false, - 0, maxFeeLimit, event001Address, event001Key, blockingStubFull); - logger.info(txid); - if (PublicMethed.getTransactionInfoById(txid,blockingStubFull).get() - .getResultValue() == 0) { - sendTransaction = false; - } - } - - if (message != null) { - transactionMessage = new String(message); - if (!transactionMessage.equals("transactionTrigger") && !transactionMessage.isEmpty()) { - break; - } - } - } - - Assert.assertTrue(retryTimes > 0); - logger.info("transaction message:" + transactionMessage); - JSONObject blockObject = JSONObject.parseObject(transactionMessage); - Assert.assertTrue(blockObject.containsKey("timeStamp")); - Assert.assertEquals(blockObject.getString("triggerName"), "transactionTrigger"); - - Assert.assertEquals(blockObject.getString("transactionId"), txid); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery003.java deleted file mode 100644 index 21046bdde8d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery003.java +++ /dev/null @@ -1,214 +0,0 @@ -package stest.tron.wallet.dailybuild.eventquery; - -import com.alibaba.fastjson.JSONObject; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.zeromq.ZMQ; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import zmq.ZMQ.Event; - -@Slf4j -public class EventQuery003 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String eventnode = Configuration.getByPath("testng.conf") - .getStringList("eventnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - byte[] contractAddress; - String txid; - - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private ManagedChannel channelSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] event001Address = ecKey1.getAddress(); - String event001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - ecKey1 = new ECKey(Utils.getRandom()); - event001Address = ecKey1.getAddress(); - event001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.printAddress(event001Key); - - Assert.assertTrue(PublicMethed.sendcoin(event001Address, maxFeeLimit * 30, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName = "addressDemo"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractEventAndLog1"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractEventAndLog1"); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 50, null, event001Key, event001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - - } - - @Test(enabled = true, description = "Event query for contract event") - public void test01EventQueryForContractEvent() { - ZMQ.Context context = ZMQ.context(1); - ZMQ.Socket req = context.socket(ZMQ.SUB); - - req.subscribe("contractEventTrigger"); - final ZMQ.Socket moniter = context.socket(ZMQ.PAIR); - moniter.connect("inproc://reqmoniter"); - new Thread(new Runnable() { - public void run() { - while (true) { - Event event = Event.read(moniter.base()); - System.out.println(event.event + " " + event.addr); - } - } - - }).start(); - req.connect(eventnode); - req.setReceiveTimeOut(10000); - String transactionMessage = ""; - Boolean sendTransaction = true; - Integer retryTimes = 20; - - while (retryTimes-- > 0) { - byte[] message = req.recv(); - if (sendTransaction) { - txid = PublicMethed.triggerContract(contractAddress, - "triggerUintEvent()", "#", false, - 0, maxFeeLimit, event001Address, event001Key, blockingStubFull); - logger.info(txid); - if (PublicMethed.getTransactionInfoById(txid,blockingStubFull).get() - .getResultValue() == 0) { - sendTransaction = false; - } - } - - if (message != null) { - transactionMessage = new String(message); - if (!transactionMessage.equals("contractEventTrigger") && !transactionMessage.isEmpty()) { - break; - } - } - } - Assert.assertTrue(retryTimes > 0); - logger.info("transaction message:" + transactionMessage); - JSONObject blockObject = JSONObject.parseObject(transactionMessage); - Assert.assertTrue(blockObject.containsKey("timeStamp")); - Assert.assertEquals(blockObject.getString("triggerName"), "contractEventTrigger"); - - Assert.assertEquals(blockObject.getString("transactionId"), txid); - } - - - @Test(enabled = true, description = "Event query for solidity contract event") - public void test02EventQueryForContractSolidityEvent() { - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - ZMQ.Context context = ZMQ.context(1); - ZMQ.Socket req = context.socket(ZMQ.SUB); - - req.subscribe("solidityEventTrigger"); - final ZMQ.Socket moniter = context.socket(ZMQ.PAIR); - moniter.connect("inproc://reqmoniter"); - new Thread(new Runnable() { - public void run() { - while (true) { - Event event = Event.read(moniter.base()); - System.out.println(event.event + " " + event.addr); - } - } - - }).start(); - req.connect(eventnode); - req.setReceiveTimeOut(10000); - String transactionMessage = ""; - Boolean sendTransaction = true; - Integer retryTimes = 40; - - while (retryTimes-- > 0) { - byte[] message = req.recv(); - if (sendTransaction) { - txid = PublicMethed.triggerContract(contractAddress, - "triggerUintEvent()", "#", false, - 0, maxFeeLimit, event001Address, event001Key, blockingStubFull); - logger.info(txid); - if (PublicMethed.getTransactionInfoById(txid,blockingStubFull).get() - .getResultValue() == 0) { - sendTransaction = false; - } - } - - if (message != null) { - - transactionMessage = new String(message); - logger.info("transaction message:" + transactionMessage); - if (!transactionMessage.equals("solidityEventTrigger") && !transactionMessage.isEmpty()) { - break; - } - } - } - Assert.assertTrue(retryTimes > 0); - logger.info("transaction message:" + transactionMessage); - JSONObject blockObject = JSONObject.parseObject(transactionMessage); - Assert.assertTrue(blockObject.containsKey("timeStamp")); - Assert.assertEquals(blockObject.getString("triggerName"), "solidityEventTrigger"); - - Assert.assertEquals(blockObject.getString("transactionId"), txid); - } - - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery004.java deleted file mode 100644 index a261f1bcf47..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/eventquery/EventQuery004.java +++ /dev/null @@ -1,223 +0,0 @@ -package stest.tron.wallet.dailybuild.eventquery; - -import com.alibaba.fastjson.JSONObject; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.zeromq.ZMQ; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import zmq.ZMQ.Event; - -@Slf4j -public class EventQuery004 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - byte[] contractAddress; - String txid; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] event001Address = ecKey1.getAddress(); - String event001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String eventnode = Configuration.getByPath("testng.conf") - .getStringList("eventnode.ip.list").get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private ManagedChannel channelSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - ecKey1 = new ECKey(Utils.getRandom()); - event001Address = ecKey1.getAddress(); - event001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.printAddress(event001Key); - - Assert.assertTrue(PublicMethed.sendcoin(event001Address, maxFeeLimit * 30, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName = "addressDemo"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractEventAndLog1"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractEventAndLog1"); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 50, null, event001Key, event001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - - } - - @Test(enabled = true, description = "Event query for contract log") - public void test01EventQueryForContractLog() { - ZMQ.Context context = ZMQ.context(1); - ZMQ.Socket req = context.socket(ZMQ.SUB); - - req.subscribe("contractLogTrigger"); - final ZMQ.Socket moniter = context.socket(ZMQ.PAIR); - moniter.connect("inproc://reqmoniter"); - new Thread(new Runnable() { - public void run() { - while (true) { - Event event = Event.read(moniter.base()); - System.out.println(event.event + " " + event.addr); - } - } - - }).start(); - req.connect(eventnode); - req.setReceiveTimeOut(10000); - String transactionMessage = ""; - Boolean sendTransaction = true; - Integer retryTimes = 20; - - while (retryTimes-- > 0) { - byte[] message = req.recv(); - if (sendTransaction) { - txid = PublicMethed.triggerContract(contractAddress, - "depositForLog()", "#", false, - 1L, 100000000L, event001Address, event001Key, blockingStubFull); - logger.info(txid); - if (PublicMethed.getTransactionInfoById(txid,blockingStubFull).get() - .getResultValue() == 0) { - sendTransaction = false; - } - } - - if (message != null) { - transactionMessage = new String(message); - if (!transactionMessage.equals("contractLogTrigger") && !transactionMessage.isEmpty()) { - break; - } - } - } - Assert.assertTrue(retryTimes > 0); - logger.info("transaction message:" + transactionMessage); - JSONObject blockObject = JSONObject.parseObject(transactionMessage); - Assert.assertTrue(blockObject.containsKey("timeStamp")); - Assert.assertEquals(blockObject.getString("triggerName"), "contractLogTrigger"); - - Assert.assertEquals(blockObject.getString("transactionId"), txid); - } - - - @Test(enabled = true, description = "Event query for solidity contract log") - public void test02EventQueryForContractSolidityLog() { - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - ZMQ.Context context = ZMQ.context(1); - ZMQ.Socket req = context.socket(ZMQ.SUB); - - req.subscribe("solidityLogTrigger"); - final ZMQ.Socket moniter = context.socket(ZMQ.PAIR); - moniter.connect("inproc://reqmoniter"); - new Thread(new Runnable() { - public void run() { - while (true) { - Event event = Event.read(moniter.base()); - System.out.println(event.event + " " + event.addr); - } - } - - }).start(); - req.connect(eventnode); - req.setReceiveTimeOut(10000); - String transactionMessage = ""; - Boolean sendTransaction = true; - Integer retryTimes = 40; - String txid1 = ""; - String txid2 = ""; - String txid3 = ""; - - while (retryTimes-- > 0) { - byte[] message = req.recv(); - if (sendTransaction) { - txid1 = PublicMethed.triggerContract(contractAddress, - "depositForLog()", "#", false, - 1L, 100000000L, event001Address, event001Key, blockingStubFull); - txid2 = PublicMethed.triggerContract(contractAddress, - "depositForLog()", "#", false, - 1L, 100000000L, event001Address, event001Key, blockingStubFull); - txid3 = PublicMethed.triggerContract(contractAddress, - "depositForLog()", "#", false, - 1L, 100000000L, event001Address, event001Key, blockingStubFull); - logger.info(txid); - if (PublicMethed.getTransactionInfoById(txid,blockingStubFull).get() - .getResultValue() == 0) { - sendTransaction = false; - } - - } - - if (message != null) { - - transactionMessage = new String(message); - logger.info("transaction message:" + transactionMessage); - if (!transactionMessage.equals("solidityLogTrigger") && !transactionMessage.isEmpty()) { - break; - } - } - } - Assert.assertTrue(retryTimes > 0); - logger.info("transaction message:" + transactionMessage); - JSONObject blockObject = JSONObject.parseObject(transactionMessage); - Assert.assertTrue(blockObject.containsKey("timeStamp")); - Assert.assertEquals(blockObject.getString("triggerName"), "solidityLogTrigger"); - txid = blockObject.getString("transactionId"); - - Assert.assertTrue(txid1.equals(txid) || txid2.equals(txid) || txid3.equals(txid)); - } - - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/exceptionfee/AssertException.java b/framework/src/test/java/stest/tron/wallet/dailybuild/exceptionfee/AssertException.java deleted file mode 100644 index 25d2c6afb68..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/exceptionfee/AssertException.java +++ /dev/null @@ -1,566 +0,0 @@ -package stest.tron.wallet.dailybuild.exceptionfee; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class AssertException { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Trigger contract Divide 0") - public void test1DivideInt() { - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/assertExceptiontest1DivideInt.sol"; - String contractName = "divideIHaveArgsReturnStorage"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - Account info; - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - String num = "4" + "," + "0"; - - txid = PublicMethed.triggerContract(contractAddress, - "divideIHaveArgsReturn(int256,int256)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById:" + infoById); - Optional ById = PublicMethed.getTransactionById(txid, blockingStubFull); - logger.info("getRet:" + ById.get().getRet(0)); - logger.info("getNumber:" + ById.get().getRet(0).getContractRet().getNumber()); - logger.info("getContractRetValue:" + ById.get().getRet(0).getContractRetValue()); - logger.info("getContractRet:" + ById.get().getRet(0).getContractRet()); - - Assert.assertEquals(ById.get().getRet(0).getContractRet().getNumber(), - contractResult.REVERT.getNumber()); - Assert.assertEquals(ById.get().getRet(0).getContractRetValue(), 2); - Assert.assertEquals(ById.get().getRet(0).getContractRet(), contractResult.REVERT); - - Assert - .assertEquals(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()), - "4e487b710000000000000000000000000000000000000000000000000000000000000012"); - Assert.assertEquals(contractResult.REVERT, infoById.get().getReceipt().getResult()); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "Trigger contract index out of bounds") - public void test2FindArgsContractMinTest() { - String filePath = - "src/test/resources/soliditycode/assertExceptiontest2FindArgsContractMinTest.sol"; - String contractName = "findArgsIContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("11:" + Base58.encode58Check(contractAddress)); - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - Integer triggerNum = -1; - txid = PublicMethed.triggerContract(contractAddress, - "findArgsByIndex1(uint256)", triggerNum.toString(), false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - } - - @Test(enabled = true, description = "Trigger contract Bytes array index out of bounds") - public void test3ByteMinContract() { - String filePath = "src/test/resources/soliditycode/assertExceptiontest3ByteMinContract.sol"; - String contractName = "byteContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - Integer triggerNum = -1; - txid = PublicMethed.triggerContract(contractAddress, - "testBytesGet(uint256)", triggerNum.toString(), false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - } - - @Test(enabled = true, description = "Trigger contract convert too large value to enumerated type") - public void test4Enum() { - String filePath = "src/test/resources/soliditycode/assertExceptiontest4Enum.sol"; - String contractName = "enumContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - Integer triggerNum = 22; - - txid = PublicMethed.triggerContract(contractAddress, - "setGoStraight(uint8)", triggerNum.toString(), false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - Optional infoById = null; - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = false, description = "Trigger contract move a negative value to a binary") - public void test5MoveRight() { - String filePath = "src/test/resources/soliditycode/assertExceptiontest5MoveRight.sol"; - String contractName = "binaryRightContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - Integer triggerNum = -1; - txid = PublicMethed.triggerContract(contractAddress, - "binaryMoveR(uint256)", triggerNum.toString(), false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertTrue(afterBalance + maxFeeLimit + netFee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "Trigger contract Call an uninitialized " - + "internal function type variable") - public void test6UninitializedContract() { - String filePath = - "src/test/resources/soliditycode/assertExceptiontest6UninitializedContract.sol"; - String contractName = "uni"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - txid = PublicMethed.triggerContract(contractAddress, - "test2()", "#", false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - } - - @Test(enabled = true, description = "Trigger contract assert exception") - public void test7TestAssertContract() { - String filePath = "src/test/resources/soliditycode/assertExceptiontest7TestAssertContract.sol"; - String contractName = "TestThrowsContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "testAssert()", "#", false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertTrue((beforeBalance - fee) == afterBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpRateLimite001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpRateLimite001.java deleted file mode 100644 index 63a9e642d23..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpRateLimite001.java +++ /dev/null @@ -1,132 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpRateLimite001 { - - private final String testKey002 = - Configuration.getByPath("testng.conf").getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private JSONObject responseContent; - private HttpResponse response; - private String httpnode = - Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list").get(0); - private String httpSoliditynode = - Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list").get(3); - private String realHttpSoliditynode = - Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list").get(2); - private String httpPbftNode = - Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list").get(4); - - - - /** constructor. */ - @BeforeClass - public void beforeClass() {} - - /** constructor. */ - @Test(enabled = true, description = "Rate limit QpsStrategy for ListWitness interface") - public void test1QpsStrategyForListWitnessInterface() { - Long startTimeStamp = System.currentTimeMillis(); - Integer repeatTimes = 0; - while (repeatTimes++ < 15) { - HttpMethed.listwitnesses(httpnode); - } - Long endTimesStap = System.currentTimeMillis(); - logger.info("startTimeStamp - endTimesStap:" + (endTimesStap - startTimeStamp)); - Assert.assertTrue(endTimesStap - startTimeStamp > 4000); - } - - /** constructor. */ - @Test(enabled = true, description = "Rate limit IpQpsStrategy for ListNodes interface") - public void test2IpQpsStrategyForListNodesInterface() { - Long startTimeStamp = System.currentTimeMillis(); - Integer repeatTimes = 0; - while (repeatTimes++ < 15) { - HttpMethed.listNodes(httpnode); - } - Long endTimesStap = System.currentTimeMillis(); - logger.info("startTimeStamp - endTimesStap:" + (endTimesStap - startTimeStamp)); - Assert.assertTrue(endTimesStap - startTimeStamp > 4000); - } - - /** constructor. */ - @Test( - enabled = true, - description = - "Rate limit IpQpsStrategy for GetBlockByLatestNumOnSolidity " - + "interface on fullnode's solidity service") - public void test3IpQpsStrategyForGetBlockByLatestNumOnSolidityInterface() { - Long startTimeStamp = System.currentTimeMillis(); - Integer repeatTimes = 0; - while (repeatTimes++ < 15) { - HttpMethed.getBlockByLastNumFromSolidity(httpSoliditynode, 5); - HttpMethed.getBlockByLastNumFromPbft(httpPbftNode, 5); - } - Long endTimesStap = System.currentTimeMillis(); - logger.info("startTimeStamp - endTimesStap:" + (endTimesStap - startTimeStamp)); - Assert.assertTrue(endTimesStap - startTimeStamp > 4000); - } - - /** constructor. */ - @Test( - enabled = true, - description = - "Rate limit QpsStrategy for getBlockByNum " + "interface on fullnode's solidity service") - public void test4QpsStrategyForgetBlockByNumResourceInterfaceOnFullnodeSolidityService() { - Long startTimeStamp = System.currentTimeMillis(); - Integer repeatTimes = 0; - while (repeatTimes++ < 15) { - HttpMethed.getBlockByLastNumFromSolidity(httpSoliditynode, 5); - HttpMethed.getBlockByLastNumFromPbft(httpPbftNode, 5); - } - Long endTimesStap = System.currentTimeMillis(); - logger.info("startTimeStamp - endTimesStap:" + (endTimesStap - startTimeStamp)); - Assert.assertTrue(endTimesStap - startTimeStamp > 4000); - } - - @Test( - enabled = false, - description = - "Rate limit QpsStrategy for " - + "getTransactionsFromThisFromSolidity " - + "interface on real solidity") - public void test6QpsStrategyForgetTransactionsToThisFromSolidity() { - Long startTimeStamp = System.currentTimeMillis(); - Integer repeatTimes = 0; - while (repeatTimes++ < 15) { - logger.info(realHttpSoliditynode); - HttpMethed.getTransactionsToThisFromSolidity(realHttpSoliditynode, fromAddress, 0, 50); - } - Long endTimesStap = System.currentTimeMillis(); - logger.info("startTimeStamp - endTimesStap:" + (endTimesStap - startTimeStamp)); - Assert.assertTrue(endTimesStap - startTimeStamp > 4000); - } - - @Test(enabled = true, description = "Verify getstatsinfo Interface has been disabled") - public void test7GetStatsInfo() { - response = HttpMethed.getStatsInfo(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("responseContent:" + responseContent); - String resultForGetstatsinfo = responseContent.getString("Error"); - logger.info("resultForGetstatsinfo:" + resultForGetstatsinfo); - Assert.assertEquals(resultForGetstatsinfo, "this API is unavailable due to config"); - } - - /** constructor. */ - @AfterClass - public void shutdown() throws InterruptedException {} -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount001.java deleted file mode 100644 index 12870a5ae5c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount001.java +++ /dev/null @@ -1,107 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestAccount001 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private JSONObject responseContent; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(0); - private String httpSoliditynode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String httpPbftNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(4); - - /** - * constructor. - */ - @Test(enabled = true, description = "Get account by http") - public void getAccount() { - response = HttpMethed.getAccount(httpnode, fromAddress); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.size() > 3); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get account from solidity by http") - public void getAccountFromSolidity() { - response = HttpMethed.getAccountFromSolidity(httpSoliditynode, fromAddress); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.size() > 3); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get account from PBFT by http") - public void getAccountFromPbftNode() { - response = HttpMethed.getAccountFromPbft(httpPbftNode, fromAddress); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.size() > 3); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "Get accountNet by http") - public void getAccountNet() { - response = HttpMethed.getAccountNet(httpnode, fromAddress); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(Integer.parseInt(responseContent.get("freeNetLimit").toString()), 5000); - Assert.assertEquals(Long.parseLong(responseContent.get("TotalNetLimit").toString()), - 43200000000L); - Assert.assertTrue(responseContent.size() >= 2); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get accountResource by http") - public void getAccountResource() { - response = HttpMethed.getAccountReource(httpnode, fromAddress); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue( - Long.parseLong(responseContent.get("TotalEnergyLimit").toString()) >= 50000000000L); - Assert.assertTrue(responseContent.size() >= 3); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.disConnect(); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount002.java deleted file mode 100644 index d1d8f587580..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount002.java +++ /dev/null @@ -1,335 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestAccount002 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] freezeBalanceAddress = ecKey1.getAddress(); - String freezeBalanceKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] receiverResourceAddress = ecKey2.getAddress(); - String receiverResourceKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - Long berforeBalance; - Long afterBalance; - Long amount = 10000000L; - Long frozenBalance = 2000000L; - private JSONObject responseContent; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(1); - private String httpSoliditynode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String httpPbftNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(4); - - /** - * constructor. - */ - @Test(enabled = true, description = "FreezeBalance for bandwidth by http") - public void test001FreezebalanceForBandwidth() { - PublicMethed.printAddress(freezeBalanceKey); - //Send trx to test account - response = HttpMethed.sendCoin(httpnode, fromAddress, freezeBalanceAddress, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - berforeBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - - //Freeze balance - response = HttpMethed - .freezeBalance(httpnode, freezeBalanceAddress, frozenBalance, 0, 0, freezeBalanceKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - afterBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - Assert.assertTrue(berforeBalance - afterBalance == frozenBalance); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "UnFreezeBalance for bandwidth by http") - public void test002UnFreezebalanceForBandwidth() { - berforeBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - - //UnFreeze balance for bandwidth - response = HttpMethed.unFreezeBalance(httpnode, freezeBalanceAddress, 0, freezeBalanceKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - afterBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - Assert.assertTrue(afterBalance - berforeBalance == frozenBalance); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "FreezeBalance for energy by http") - public void test003FreezebalanceForEnergy() { - berforeBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - - //Freeze balance for energy - response = HttpMethed - .freezeBalance(httpnode, freezeBalanceAddress, frozenBalance, 0, 1, freezeBalanceKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - afterBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - Assert.assertTrue(berforeBalance - afterBalance == frozenBalance); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "UnFreezeBalance for energy by http") - public void test004UnFreezebalanceForEnergy() { - - berforeBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - HttpMethed.waitToProduceOneBlock(httpnode); - //UnFreeze balance for energy - response = HttpMethed.unFreezeBalance(httpnode, freezeBalanceAddress, 1, freezeBalanceKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - afterBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - Assert.assertTrue(afterBalance - berforeBalance == frozenBalance); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "FreezeBalance with bandwidth for others by http") - public void test005FreezebalanceOfBandwidthForOthers() { - response = HttpMethed - .sendCoin(httpnode, fromAddress, receiverResourceAddress, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - berforeBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - - //Freeze balance with bandwidth for others - response = HttpMethed - .freezeBalance(httpnode, freezeBalanceAddress, frozenBalance, 0, 0, receiverResourceAddress, - freezeBalanceKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - afterBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - Assert.assertTrue(berforeBalance - afterBalance == frozenBalance); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get Delegated Resource by http") - public void test006GetDelegatedResource() { - response = HttpMethed - .getDelegatedResource(httpnode, freezeBalanceAddress, receiverResourceAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = JSONArray.parseArray(responseContent.get("delegatedResource").toString()); - Assert.assertTrue(jsonArray.size() >= 1); - Assert.assertEquals(jsonArray.getJSONObject(0).getString("from"), - ByteArray.toHexString(freezeBalanceAddress)); - Assert.assertEquals(jsonArray.getJSONObject(0).getString("to"), - ByteArray.toHexString(receiverResourceAddress)); - Assert.assertEquals(jsonArray.getJSONObject(0).getLong("frozen_balance_for_bandwidth"), - frozenBalance); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get Delegated Resource from solidity by http") - public void test007GetDelegatedResourceFromSolidity() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - HttpMethed.waitToProduceOneBlockFromPbft(httpnode, httpPbftNode); - response = HttpMethed.getDelegatedResourceFromSolidity(httpSoliditynode, freezeBalanceAddress, - receiverResourceAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = JSONArray.parseArray(responseContent.get("delegatedResource").toString()); - Assert.assertTrue(jsonArray.size() >= 1); - Assert.assertEquals(jsonArray.getJSONObject(0).getString("from"), - ByteArray.toHexString(freezeBalanceAddress)); - Assert.assertEquals(jsonArray.getJSONObject(0).getString("to"), - ByteArray.toHexString(receiverResourceAddress)); - Assert.assertEquals(jsonArray.getJSONObject(0).getLong("frozen_balance_for_bandwidth"), - frozenBalance); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get Delegated Resource from PBFT by http") - public void test008GetDelegatedResourceFromPbft() { - HttpMethed.waitToProduceOneBlockFromPbft(httpnode, httpPbftNode); - response = HttpMethed - .getDelegatedResourceFromPbft(httpPbftNode, freezeBalanceAddress, receiverResourceAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = JSONArray.parseArray(responseContent.get("delegatedResource").toString()); - Assert.assertTrue(jsonArray.size() >= 1); - Assert.assertEquals(jsonArray.getJSONObject(0).getString("from"), - ByteArray.toHexString(freezeBalanceAddress)); - Assert.assertEquals(jsonArray.getJSONObject(0).getString("to"), - ByteArray.toHexString(receiverResourceAddress)); - Assert.assertEquals(jsonArray.getJSONObject(0).getLong("frozen_balance_for_bandwidth"), - frozenBalance); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "Get Delegated Resource Account Index by http") - public void test009GetDelegatedResourceAccountIndex() { - response = HttpMethed.getDelegatedResourceAccountIndex(httpnode, freezeBalanceAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertFalse(responseContent.get("toAccounts").toString().isEmpty()); - String toAddress = responseContent.getJSONArray("toAccounts").get(0).toString(); - Assert.assertEquals(toAddress, ByteArray.toHexString(receiverResourceAddress)); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get Delegated Resource Account Index from solidity by http") - public void test010GetDelegatedResourceAccountIndexFromSolidity() { - response = HttpMethed - .getDelegatedResourceAccountIndexFromSolidity(httpSoliditynode, freezeBalanceAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertFalse(responseContent.get("toAccounts").toString().isEmpty()); - String toAddress = responseContent.getJSONArray("toAccounts").get(0).toString(); - Assert.assertEquals(toAddress, ByteArray.toHexString(receiverResourceAddress)); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get Delegated Resource Account Index from PBFT by http") - public void test011GetDelegatedResourceAccountIndexFromPbft() { - response = HttpMethed - .getDelegatedResourceAccountIndexFromPbft(httpPbftNode, freezeBalanceAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertFalse(responseContent.get("toAccounts").toString().isEmpty()); - String toAddress = responseContent.getJSONArray("toAccounts").get(0).toString(); - Assert.assertEquals(toAddress, ByteArray.toHexString(receiverResourceAddress)); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "UnFreezeBalance with bandwidth for others by http") - public void test012UnFreezebalanceOfBandwidthForOthers() { - HttpMethed.waitToProduceOneBlock(httpnode); - berforeBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - - //UnFreeze balance with bandwidth for others - response = HttpMethed - .unFreezeBalance(httpnode, freezeBalanceAddress, 0, receiverResourceAddress, - freezeBalanceKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - afterBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - Assert.assertTrue(afterBalance - berforeBalance == frozenBalance); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "FreezeBalance with energy for others by http") - public void test013FreezebalanceOfEnergyForOthers() { - response = HttpMethed - .sendCoin(httpnode, fromAddress, receiverResourceAddress, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - berforeBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - - //Freeze balance with energy for others - response = HttpMethed - .freezeBalance(httpnode, freezeBalanceAddress, frozenBalance, 0, 1, receiverResourceAddress, - freezeBalanceKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - afterBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - Assert.assertTrue(berforeBalance - afterBalance == frozenBalance); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "UnFreezeBalance with energy for others by http") - public void test014UnFreezebalanceOfEnergyForOthers() { - berforeBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - - //UnFreeze balance with energy for others - response = HttpMethed - .unFreezeBalance(httpnode, freezeBalanceAddress, 1, receiverResourceAddress, - freezeBalanceKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - afterBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - Assert.assertTrue(afterBalance - berforeBalance == frozenBalance); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "FreezeBlance for tron power by http") - public void test015FreezeTronPower() { - HttpMethed.waitToProduceOneBlock(httpnode); - berforeBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - - response = HttpMethed - .freezeBalance(httpnode, freezeBalanceAddress, frozenBalance, 0, 2, null, - freezeBalanceKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - afterBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - Assert.assertTrue(berforeBalance - afterBalance == frozenBalance); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "UnFreezeBalance for tron power by http") - public void test016UnFreezeBalanceForTronPower() { - berforeBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - - //UnFreeze balance with energy for others - response = HttpMethed - .unFreezeBalance(httpnode, freezeBalanceAddress, 2, null, - freezeBalanceKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - afterBalance = HttpMethed.getBalance(httpnode, freezeBalanceAddress); - Assert.assertTrue(afterBalance - berforeBalance == frozenBalance); - } - - - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.freedResource(httpnode, freezeBalanceAddress, fromAddress, freezeBalanceKey); - HttpMethed.disConnect(); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount003.java deleted file mode 100644 index a63d3e7f6c0..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount003.java +++ /dev/null @@ -1,230 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestAccount003 { - - private static String updateAccountName = - "updateAccount_" + System.currentTimeMillis(); - private static String updateUrl = - "http://www.update.url/" + System.currentTimeMillis(); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witness1Address = PublicMethed.getFinalAddress(witnessKey001); - private final String witnessKey002 = Configuration.getByPath("testng.conf") - .getString("witness.key2"); - private final byte[] witness2Address = PublicMethed.getFinalAddress(witnessKey002); - private final Long createWitnessAmount = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.createWitnessAmount"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] newAccountAddress = ecKey1.getAddress(); - String newAccountKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] updateAccountAddress = ecKey2.getAddress(); - String updateAccountKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - Long amount = 50000000L; - JsonArray voteKeys = new JsonArray(); - JsonObject voteElement = new JsonObject(); - private JSONObject responseContent; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(0); - private String httpSoliditynode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String httpPbftNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(4); - - /** - * constructor. - */ - @Test(enabled = true, description = "Update account by http") - public void test01UpdateAccount() { - response = HttpMethed.sendCoin(httpnode, fromAddress, updateAccountAddress, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed - .updateAccount(httpnode, updateAccountAddress, updateAccountName, updateAccountKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed.getAccount(httpnode, updateAccountAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getString("account_name") - .equalsIgnoreCase(HttpMethed.str2hex(updateAccountName))); - - Assert.assertFalse(responseContent.getString("active_permission").isEmpty()); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Vote witness account by http") - public void test02VoteWitnessAccount() { - //Freeze balance - response = HttpMethed - .freezeBalance(httpnode, updateAccountAddress, 40000000L, 0, 2, updateAccountKey); - responseContent = HttpMethed.parseResponseContent(response); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.printJsonContent(responseContent); - HttpMethed.waitToProduceOneBlock(httpnode); - voteElement.addProperty("vote_address", ByteArray.toHexString(witness1Address)); - voteElement.addProperty("vote_count", 11); - voteKeys.add(voteElement); - - voteElement.remove("vote_address"); - voteElement.remove("vote_count"); - voteElement.addProperty("vote_address", ByteArray.toHexString(witness2Address)); - voteElement.addProperty("vote_count", 12); - voteKeys.add(voteElement); - - response = HttpMethed - .voteWitnessAccount(httpnode, updateAccountAddress, voteKeys, updateAccountKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getAccount(httpnode, updateAccountAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(!responseContent.getString("votes").isEmpty()); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "List witnesses by http") - public void test03ListWitness() { - response = HttpMethed.listwitnesses(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = JSONArray.parseArray(responseContent.getString("witnesses")); - Assert.assertTrue(jsonArray.size() >= 2); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "List witnesses from solidity by http") - public void test04ListWitnessFromSolidity() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - response = HttpMethed.listwitnessesFromSolidity(httpSoliditynode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = JSONArray.parseArray(responseContent.getString("witnesses")); - Assert.assertTrue(jsonArray.size() >= 2); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "List witnesses from PBFT by http") - public void test05ListWitnessFromPbft() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - response = HttpMethed.listwitnessesFromPbft(httpPbftNode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = JSONArray.parseArray(responseContent.getString("witnesses")); - Assert.assertTrue(jsonArray.size() >= 2); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "Update witness by http") - public void test06UpdateWitness() { - response = HttpMethed.updateWitness(httpnode, witness1Address, updateUrl, witnessKey001); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed.listwitnesses(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getString("witnesses").indexOf(updateUrl) != -1); - //logger.info("result is " + responseContent.getString("witnesses").indexOf(updateUrl)); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Create account by http") - public void test07CreateAccount() { - PublicMethed.printAddress(newAccountKey); - response = HttpMethed.createAccount(httpnode, fromAddress, newAccountAddress, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getAccount(httpnode, newAccountAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getLong("create_time") > 3); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Create witness by http") - public void test08CreateWitness() { - response = HttpMethed - .sendCoin(httpnode, fromAddress, newAccountAddress, createWitnessAmount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - PublicMethed.printAddress(newAccountKey); - - response = HttpMethed.createWitness(httpnode, newAccountAddress, updateUrl); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(!responseContent.getString("txID").isEmpty()); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Withdraw by http") - public void test09Withdraw() { - response = HttpMethed.withdrawBalance(httpnode, witness1Address); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert - .assertTrue(responseContent.getString("Error").indexOf("is a guard representative") != -1); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Unfreeze balance for tron power by http") - public void test10UnfreezeTronPower() { - response = HttpMethed.unFreezeBalance(httpnode, updateAccountAddress,2,updateAccountKey); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.freedResource(httpnode, updateAccountAddress, fromAddress, updateAccountKey); - HttpMethed.disConnect(); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount004.java deleted file mode 100644 index 5ae5089d057..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount004.java +++ /dev/null @@ -1,115 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestAccount004 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] setAccountIdAddress = ecKey1.getAddress(); - String setAccountIdKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Long amount = 10000000L; - String accountId; - private JSONObject responseContent; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(0); - private String httpSoliditynode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - - - private String httpPbftNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(4); - - - /** - * constructor. - */ - @Test(enabled = true, description = "Set account by http") - public void test1setAccountId() { - response = HttpMethed.sendCoin(httpnode, fromAddress, setAccountIdAddress, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed - .setAccountId(httpnode, setAccountIdAddress, System.currentTimeMillis() + "id", false, - setAccountIdKey); - Assert.assertFalse(HttpMethed.verificationResult(response)); - - //Set account id. - accountId = System.currentTimeMillis() + "id"; - response = HttpMethed - .setAccountId(httpnode, setAccountIdAddress, accountId, true, setAccountIdKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get account by id via http") - public void test2getAccountId() { - response = HttpMethed.getAccountById(httpnode, accountId, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(responseContent.get("account_id"), accountId); - Assert.assertTrue(responseContent.size() >= 10); - - response = HttpMethed.getAccountById(httpnode, accountId, false); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.size() <= 1); - - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get account by id via http") - public void test3getAccountIdFromSolidity() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - response = HttpMethed.getAccountByIdFromSolidity(httpSoliditynode, accountId, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(responseContent.get("account_id"), accountId); - Assert.assertTrue(responseContent.size() >= 10); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get account by id via PBFT http") - public void test4getAccountIdFromPbft() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - response = HttpMethed.getAccountByIdFromPbft(httpPbftNode, accountId, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(responseContent.get("account_id"), accountId); - Assert.assertTrue(responseContent.size() >= 10); - } - - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.freedResource(httpnode, setAccountIdAddress, fromAddress, setAccountIdKey); - HttpMethed.disConnect(); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount005.java deleted file mode 100644 index 4d45d5e8b0e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount005.java +++ /dev/null @@ -1,62 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestAccount005 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] toAddress = ecKey1.getAddress(); - String toAddressKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Long amount = 1L; - String sendText = "Decentralize the WEB!"; - private JSONObject responseContent; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(0); - - /** - * constructor. - */ - @Test(enabled = true, description = "Test transfer with notes by http") - public void test01TransferWithNotes() { - PublicMethed.printAddress(toAddressKey); - //Send trx to test account - String txid = HttpMethed - .sendCoin(httpnode, fromAddress, toAddress, amount, sendText, testKey002); - HttpMethed.waitToProduceOneBlock(httpnode); - HttpResponse response = HttpMethed.getTransactionById(httpnode, txid); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - String rawData = responseContent.getString("raw_data"); - JSONObject rawDataObject = JSON.parseObject(rawData); - Assert.assertTrue(rawDataObject.containsKey("data")); - String hexData = rawDataObject.getString("data"); - String recoveredString = new String(ByteUtil.hexToBytes(hexData)); - Assert.assertEquals(sendText, recoveredString); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.freedResource(httpnode, toAddress, fromAddress, toAddressKey); - HttpMethed.disConnect(); - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAsset001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAsset001.java deleted file mode 100644 index f57780e5bc7..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAsset001.java +++ /dev/null @@ -1,311 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestAsset001 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "testAssetIssue002_" + now; - private static String assetIssueId; - private static String updateDescription = "Description_update_" + now; - private static String updateUrl = "Url_update_" + now; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] assetAddress = ecKey1.getAddress(); - String assetKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] participateAddress = ecKey2.getAddress(); - String participateKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - Long amount = 2048000000L; - - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf").getString("defaultParameter.assetUrl"); - private JSONObject responseContent; - private JSONObject getAssetIssueByIdContent; - private JSONObject getAssetIssueByNameContent; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(1); - private String httpSoliditynode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String httpPbftNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(4); - - - /** - * constructor. - */ - @Test(enabled = true, description = "Create asset issue by http") - public void test01CreateAssetIssue() { - response = HttpMethed.sendCoin(httpnode, fromAddress, assetAddress, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed - .sendCoin(httpnode, fromAddress, participateAddress, 10000000L, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - //Create an asset issue - response = HttpMethed.assetIssue(httpnode, assetAddress, name, name, totalSupply, 1, 1, - System.currentTimeMillis() + 5000, System.currentTimeMillis() + 50000000, 2, 3, description, - url, 1000L, 1000L, assetKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getAccount(httpnode, assetAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - assetIssueId = responseContent.getString("asset_issued_ID"); - logger.info(assetIssueId); - Assert.assertTrue(Integer.parseInt(assetIssueId) > 1000000); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetAssetIssueById by http") - public void test02GetAssetIssueById() { - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getAssetIssueById(httpnode, assetIssueId); - getAssetIssueByIdContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getAssetIssueByIdContent); - Assert.assertTrue(totalSupply == getAssetIssueByIdContent.getLong("total_supply")); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetAssetIssueById from solidity by http") - public void test03GetAssetIssueByIdFromSolidity() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - response = HttpMethed.getAssetIssueByIdFromSolidity(httpSoliditynode, assetIssueId); - getAssetIssueByIdContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getAssetIssueByIdContent); - Assert.assertTrue(totalSupply == getAssetIssueByIdContent.getLong("total_supply")); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetAssetIssueById from PBFT by http") - public void test04GetAssetIssueByIdFromPbft() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - response = HttpMethed.getAssetIssueByIdFromPbft(httpPbftNode, assetIssueId); - getAssetIssueByIdContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getAssetIssueByIdContent); - Assert.assertTrue(totalSupply == getAssetIssueByIdContent.getLong("total_supply")); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "GetAssetIssueByName by http") - public void test05GetAssetIssueByName() { - response = HttpMethed.getAssetIssueByName(httpnode, name); - getAssetIssueByNameContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getAssetIssueByNameContent); - Assert.assertTrue(totalSupply == getAssetIssueByNameContent.getLong("total_supply")); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetAssetIssueByName from solidity by http") - public void test06GetAssetIssueByNameFromSolidity() { - response = HttpMethed.getAssetIssueByNameFromSolidity(httpSoliditynode, name); - getAssetIssueByNameContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getAssetIssueByNameContent); - Assert.assertTrue(totalSupply == getAssetIssueByNameContent.getLong("total_supply")); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetAssetIssueByName from PBFT by http") - public void test07GetAssetIssueByNameFromPbft() { - response = HttpMethed.getAssetIssueByNameFromPbft(httpPbftNode, name); - getAssetIssueByNameContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getAssetIssueByNameContent); - Assert.assertTrue(totalSupply == getAssetIssueByNameContent.getLong("total_supply")); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "TransferAsset by http") - public void test08TransferAsset() { - logger.info("Transfer asset."); - response = HttpMethed - .transferAsset(httpnode, assetAddress, participateAddress, assetIssueId, 100L, assetKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getAccount(httpnode, participateAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(!responseContent.getString("assetV2").isEmpty()); - //logger.info(responseContent.get("assetV2").toString()); - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Participate asset issue by http") - public void test09ParticipateAssetIssue() { - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed - .participateAssetIssue(httpnode, assetAddress, participateAddress, assetIssueId, 1000L, - participateKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getAccount(httpnode, participateAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Update asset issue by http") - public void test10UpdateAssetIssue() { - response = HttpMethed - .updateAssetIssue(httpnode, assetAddress, updateDescription, updateUrl, 290L, 390L, - assetKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getAssetIssueById(httpnode, assetIssueId); - getAssetIssueByIdContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getAssetIssueByIdContent); - - Assert.assertTrue(getAssetIssueByIdContent.getLong("public_free_asset_net_limit") == 390L); - Assert.assertTrue(getAssetIssueByIdContent.getLong("free_asset_net_limit") == 290L); - Assert.assertTrue(getAssetIssueByIdContent.getString("description") - .equalsIgnoreCase(HttpMethed.str2hex(updateDescription))); - Assert.assertTrue( - getAssetIssueByIdContent.getString("url").equalsIgnoreCase(HttpMethed.str2hex(updateUrl))); - } - - - /** - * * constructor. * - */ - @Test(enabled = true, description = "Get asset issue list by http") - public void test11GetAssetissueList() { - - response = HttpMethed.getAssetissueList(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - - JSONArray jsonArray = JSONArray.parseArray(responseContent.getString("assetIssue")); - Assert.assertTrue(jsonArray.size() >= 1); - } - - - /** - * * constructor. * - */ - @Test(enabled = true, description = "Get asset issue list from solidity by http") - public void test12GetAssetissueListFromSolidity() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - response = HttpMethed.getAssetIssueListFromSolidity(httpSoliditynode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - - JSONArray jsonArray = JSONArray.parseArray(responseContent.getString("assetIssue")); - Assert.assertTrue(jsonArray.size() >= 1); - } - - /** - * * constructor. * - */ - @Test(enabled = true, description = "Get asset issue list from PBFT by http") - public void test13GetAssetissueListFromPbft() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - response = HttpMethed.getAssetIssueListFromPbft(httpPbftNode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - - JSONArray jsonArray = JSONArray.parseArray(responseContent.getString("assetIssue")); - Assert.assertTrue(jsonArray.size() >= 1); - } - - - /** - * * constructor. * - */ - @Test(enabled = true, description = "Get paginated asset issue list by http") - public void test14GetPaginatedAssetissueList() { - response = HttpMethed.getPaginatedAssetissueList(httpnode, 0, 1); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - - JSONArray jsonArray = JSONArray.parseArray(responseContent.getString("assetIssue")); - Assert.assertTrue(jsonArray.size() == 1); - } - - - /** - * * constructor. * - */ - @Test(enabled = true, description = "Get paginated asset issue list from solidity by http") - public void test15GetPaginatedAssetissueListFromSolidity() { - response = HttpMethed.getPaginatedAssetissueListFromSolidity(httpSoliditynode, 0, 1); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - - JSONArray jsonArray = JSONArray.parseArray(responseContent.getString("assetIssue")); - Assert.assertTrue(jsonArray.size() == 1); - } - - - /** - * * constructor. * - */ - @Test(enabled = true, description = "Get paginated asset issue list from PBFT by http") - public void test16GetPaginatedAssetissueListFromPbft() { - response = HttpMethed.getPaginatedAssetissueListFromPbft(httpPbftNode, 0, 1); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - - JSONArray jsonArray = JSONArray.parseArray(responseContent.getString("assetIssue")); - Assert.assertTrue(jsonArray.size() == 1); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.freedResource(httpnode, assetAddress, fromAddress, assetKey); - HttpMethed.freedResource(httpnode, participateAddress, fromAddress, participateKey); - HttpMethed.disConnect(); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestBlock001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestBlock001.java deleted file mode 100644 index f091e8f4b05..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestBlock001.java +++ /dev/null @@ -1,383 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestBlock001 { - - private JSONObject responseContent; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(0); - private String httpSoliditynode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String httpPbftNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(4); - private Integer currentBlockNum; - private JSONObject blockContent; - private JSONObject blockContentWithVisibleTrue; - private String blockId; - - - /** - * constructor. - */ - @Test(enabled = true, description = "Get now block by http") - public void get01NowBlock() { - response = HttpMethed.getNowBlock(httpnode); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - blockContent = responseContent; - blockId = responseContent.get("blockID").toString(); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.size() >= 2); - responseContent = HttpMethed.parseStringContent(responseContent.get("block_header").toString()); - Assert.assertTrue(responseContent.size() >= 2); - Assert.assertFalse(responseContent.get("witness_signature").toString().isEmpty()); - HttpMethed.printJsonContent(responseContent); - responseContent = HttpMethed.parseStringContent(responseContent.get("raw_data").toString()); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(Integer.parseInt(responseContent.get("number").toString()) > 0); - currentBlockNum = Integer.parseInt(responseContent.get("number").toString()); - Assert.assertTrue(Long.parseLong(responseContent.get("timestamp").toString()) > 1550724114000L); - Assert.assertFalse(responseContent.get("witness_address").toString().isEmpty()); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get now block from solidity by http") - public void get02NowBlockFromSolidity() { - response = HttpMethed.getNowBlockFromSolidity(httpSoliditynode); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - blockContent = responseContent; - blockId = responseContent.get("blockID").toString(); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.size() >= 2); - responseContent = HttpMethed.parseStringContent(responseContent.get("block_header").toString()); - Assert.assertTrue(responseContent.size() >= 2); - Assert.assertFalse(responseContent.get("witness_signature").toString().isEmpty()); - HttpMethed.printJsonContent(responseContent); - responseContent = HttpMethed.parseStringContent(responseContent.get("raw_data").toString()); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(Integer.parseInt(responseContent.get("number").toString()) > 0); - currentBlockNum = Integer.parseInt(responseContent.get("number").toString()); - Assert.assertTrue(Long.parseLong(responseContent.get("timestamp").toString()) > 1550724114000L); - Assert.assertFalse(responseContent.get("witness_address").toString().isEmpty()); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get now block from pbft by http") - public void get03NowBlockFromPbft() { - response = HttpMethed.getNowBlockFromPbft(httpPbftNode); - logger.info("code is " + response.getStatusLine().getStatusCode()); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - blockContent = responseContent; - blockId = responseContent.get("blockID").toString(); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.size() >= 2); - responseContent = HttpMethed.parseStringContent(responseContent.get("block_header").toString()); - Assert.assertTrue(responseContent.size() >= 2); - Assert.assertFalse(responseContent.get("witness_signature").toString().isEmpty()); - HttpMethed.printJsonContent(responseContent); - responseContent = HttpMethed.parseStringContent(responseContent.get("raw_data").toString()); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(Integer.parseInt(responseContent.get("number").toString()) > 0); - currentBlockNum = Integer.parseInt(responseContent.get("number").toString()); - Assert.assertTrue(Long.parseLong(responseContent.get("timestamp").toString()) > 1550724114000L); - Assert.assertFalse(responseContent.get("witness_address").toString().isEmpty()); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "Get block by num by http") - public void get04BlockByNum() { - response = HttpMethed.getBlockByNum(httpnode, currentBlockNum); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - Assert.assertEquals(responseContent, blockContent); - - //visible=true - response = HttpMethed.getBlockByNum(httpnode, currentBlockNum, true); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - Assert.assertEquals(responseContent.getString("blockID"), - blockContent.getString("blockID")); - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get block by num from solidity by http") - public void get05BlockByNumFromSolidity() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - response = HttpMethed.getBlockByNumFromSolidity(httpSoliditynode, currentBlockNum); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - Assert.assertEquals(responseContent, blockContent); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get block by num from PBFT by http") - public void get06BlockByNumFromPbft() { - response = HttpMethed.getBlockByNumFromPbft(httpPbftNode, currentBlockNum); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - Assert.assertEquals(responseContent, blockContent); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "GetBlockByLimitNext by http") - public void get07BlockByLimitNext() { - response = HttpMethed.getBlockByLimitNext(httpnode, currentBlockNum - 10, currentBlockNum); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - logger.info(responseContent.get("block").toString()); - JSONArray jsonArray = JSONArray.parseArray(responseContent.get("block").toString()); - Assert.assertEquals(jsonArray.size(), 10); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetBlockByLastNum by http") - public void get08BlockByLastNum() { - response = HttpMethed.getBlockByLastNum(httpnode, 8); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - logger.info(responseContent.get("block").toString()); - JSONArray jsonArray = JSONArray.parseArray(responseContent.get("block").toString()); - Assert.assertEquals(jsonArray.size(), 8); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetBlockById by http") - public void get09BlockById() { - response = HttpMethed.getBlockById(httpnode, blockId); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(blockId, responseContent.get("blockID").toString()); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetBlockById by Solidity http") - public void get10BlockByIdFromSolidity() { - response = HttpMethed.getBlockByIdFromSolidity(httpSoliditynode, blockId); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(blockId, responseContent.get("blockID").toString()); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetBlockById by PBFT http") - public void get11BlockByIdFromPbft() { - response = HttpMethed.getBlockByIdFromPbft(httpPbftNode, blockId); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(blockId, responseContent.get("blockID").toString()); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "List nodes by http") - public void get12ListNodes() { - response = HttpMethed.listNodes(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "get next maintenance time by http") - public void get13NextMaintaenanceTime() { - response = HttpMethed.getNextmaintenanceTime(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertFalse(responseContent.get("num").toString().isEmpty()); - Assert.assertTrue(responseContent.getLong("num") >= System.currentTimeMillis()); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "get chain parameter by http") - public void get14ChainParameter() { - response = HttpMethed.getChainParameter(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = JSONArray.parseArray(responseContent.get("chainParameter").toString()); - Assert.assertTrue(jsonArray.size() >= 26); - Boolean exsistDelegated = false; - for (int i = 0; i < jsonArray.size(); i++) { - if (jsonArray.getJSONObject(i).getString("key").equals("getAllowDelegateResource")) { - exsistDelegated = true; - Assert.assertTrue(jsonArray.getJSONObject(i).getString("value").equals("1")); - } - } - Assert.assertTrue(exsistDelegated); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "get Node Info by http") - public void get15NodeInfo() { - response = HttpMethed.getNodeInfo(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertFalse(responseContent.get("configNodeInfo").toString().isEmpty()); - Assert.assertTrue(responseContent.getString("configNodeInfo").contains("\"dbVersion\":2")); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get transaction count by blocknum from solidity by http") - public void get16TransactionCountByBlocknumFromSolidity() { - response = HttpMethed - .getTransactionCountByBlocknumFromSolidity(httpSoliditynode, currentBlockNum); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.size() == 1); - Assert.assertTrue(Integer.parseInt(responseContent.get("count").toString()) >= 0); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get transaction count by blocknum from PBFT by http") - public void get17TransactionCountByBlocknumFromPbft() { - response = HttpMethed.getTransactionCountByBlocknumFromPbft(httpPbftNode, currentBlockNum); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.size() == 1); - Assert.assertTrue(Integer.parseInt(responseContent.get("count").toString()) >= 0); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "GetBlockByLimitNext by Solidity http") - public void get18BlockByLimitNextFromSolidity() { - response = HttpMethed - .getBlockByLimitNextFromSolidity(httpSoliditynode, currentBlockNum - 10, currentBlockNum); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - logger.info(responseContent.get("block").toString()); - JSONArray jsonArray = JSONArray.parseArray(responseContent.get("block").toString()); - Assert.assertEquals(jsonArray.size(), 10); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetBlockByLimitNext by PBFT http") - public void get19BlockByLimitNextFromPbft() { - response = HttpMethed - .getBlockByLimitNextFromPbft(httpPbftNode, currentBlockNum - 10, currentBlockNum); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - logger.info(responseContent.get("block").toString()); - JSONArray jsonArray = JSONArray.parseArray(responseContent.get("block").toString()); - Assert.assertEquals(jsonArray.size(), 10); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "GetBlockByLastNum by solidity http") - public void get20BlockByLastNumFromSolidity() { - response = HttpMethed.getBlockByLastNumFromSolidity(httpSoliditynode, 8); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - logger.info(responseContent.get("block").toString()); - JSONArray jsonArray = JSONArray.parseArray(responseContent.get("block").toString()); - Assert.assertEquals(jsonArray.size(), 8); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetBlockByLastNum by PBFT http") - public void get21BlockByLastNumFromPbft() { - response = HttpMethed.getBlockByLastNumFromPbft(httpPbftNode, 8); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - logger.info(responseContent.get("block").toString()); - JSONArray jsonArray = JSONArray.parseArray(responseContent.get("block").toString()); - Assert.assertEquals(jsonArray.size(), 8); - } - - - /** - * constructor. - */ - @Test(enabled = false, description = "Get block by num by http") - public void get16TestResponse() { - Integer times = 1000; - String testKey002 = "7400E3D0727F8A61041A8E8BF86599FE5597CE19DE451E59AED07D60967A5E25"; - byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - Long duration = HttpMethed.getBlockByNumForResponse(httpnode, 4942435, times); - /* Long duration = HttpMethed.getAccountForResponse(httpnode, fromAddress, times);*/ - /* Long duration = HttpMethed.getTransactionByIdForResponse(httpnode, - "a265fc457551fd9cfa55daec0550268b1a2da54018cc700f1559454836de411c", times);*/ - logger.info("Total duration : " + duration); - logger.info("Average duration: " + duration / times); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.disConnect(); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestClearAbiContract001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestClearAbiContract001.java deleted file mode 100644 index a5c6ed1a903..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestClearAbiContract001.java +++ /dev/null @@ -1,185 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import static org.hamcrest.core.StringContains.containsString; - -import com.alibaba.fastjson.JSONObject; -import java.util.HashMap; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestClearAbiContract001 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "testAssetIssue002_" + now; - private static String assetIssueId; - private static String contractName; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] assetOwnerAddress = ecKey2.getAddress(); - String assetOwnerKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - String contractAddress; - String abi; - Long amount = 2048000000L; - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf").getString("defaultParameter.assetUrl"); - private JSONObject responseContent; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(0); - private String httpSoliditynode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String httpPbftnode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(4); - - /** - * constructor. - */ - @Test(enabled = true, description = "Deploy smart contract by http") - public void test1DeployContract() { - PublicMethed.printAddress(assetOwnerKey); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.sendCoin(httpnode, fromAddress, assetOwnerAddress, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed.getAccount(httpnode, assetOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - String filePath = "src/test/resources/soliditycode/TriggerConstant003.sol"; - contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - abi = retMap.get("abI").toString(); - logger.info("abi:" + abi); - logger.info("code:" + code); - - String txid = HttpMethed - .deployContractGetTxid(httpnode, contractName, abi, code, 1000000L, 1000000000L, 100, - 11111111111111L, 0L, 0, 0L, assetOwnerAddress, assetOwnerKey); - - HttpMethed.waitToProduceOneBlock(httpnode); - logger.info(txid); - response = HttpMethed.getTransactionById(httpnode, txid); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertFalse(responseContent.getString("contract_address").isEmpty()); - contractAddress = responseContent.getString("contract_address"); - - response = HttpMethed.getTransactionInfoById(httpnode, txid); - responseContent = HttpMethed.parseResponseContent(response); - String receiptString = responseContent.getString("receipt"); - Assert - .assertEquals(HttpMethed.parseStringContent(receiptString).getString("result"), "SUCCESS"); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get contract by http") - public void test2GetContract() { - response = HttpMethed.getContract(httpnode, contractAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(responseContent.getString("consume_user_resource_percent"), "100"); - Assert.assertEquals(responseContent.getString("contract_address"), contractAddress); - Assert.assertEquals(responseContent.getString("origin_address"), - ByteArray.toHexString(assetOwnerAddress)); - Assert.assertThat(responseContent.getString("abi"), containsString("testView")); - - Assert.assertEquals(responseContent.getString("origin_energy_limit"), "11111111111111"); - Assert.assertEquals(responseContent.getString("name"), contractName); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Trigger contract by http") - public void test3TriggerConstantContract() { - - HttpResponse httpResponse = HttpMethed - .triggerConstantContract(httpnode, assetOwnerAddress, contractAddress, "testView()", ""); - - responseContent = HttpMethed.parseResponseContent(httpResponse); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(responseContent.getString("result"), "{\"result\":true}"); - Assert.assertEquals(responseContent.getString("constant_result"), - "[\"0000000000000000000000000000000000000000000000000000000000000001\"]"); - - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode,httpSoliditynode); - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode,httpSoliditynode); - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode,httpSoliditynode); - httpResponse = HttpMethed.triggerConstantContractFromSolidity(httpSoliditynode, - assetOwnerAddress, contractAddress, "testView()", ""); - - responseContent = HttpMethed.parseResponseContent(httpResponse); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(responseContent.getString("result"), "{\"result\":true}"); - Assert.assertEquals(responseContent.getString("constant_result"), - "[\"0000000000000000000000000000000000000000000000000000000000000001\"]"); - - httpResponse = HttpMethed.triggerConstantContractFromPbft(httpPbftnode, assetOwnerAddress, - contractAddress, "testView()", ""); - - responseContent = HttpMethed.parseResponseContent(httpResponse); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(responseContent.getString("result"), "{\"result\":true}"); - Assert.assertEquals(responseContent.getString("constant_result"), - "[\"0000000000000000000000000000000000000000000000000000000000000001\"]"); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Trigger contract by http") - public void test4ClearAbiContract() { - - HttpResponse httpResponse = HttpMethed - .clearABiGetTxid(httpnode, assetOwnerAddress, contractAddress, assetOwnerKey); - - responseContent = HttpMethed.parseResponseContent(httpResponse); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(responseContent.getString("result"), "true"); - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get contract by http") - public void test5GetContract() { - response = HttpMethed.getContract(httpnode, contractAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(responseContent.getString("consume_user_resource_percent"), "100"); - Assert.assertEquals(responseContent.getString("contract_address"), contractAddress); - Assert.assertEquals(responseContent.getString("origin_address"), - ByteArray.toHexString(assetOwnerAddress)); - Assert.assertEquals(responseContent.getString("abi"), "{}"); - Assert.assertEquals(responseContent.getString("origin_energy_limit"), "11111111111111"); - Assert.assertEquals(responseContent.getString("name"), contractName); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.freedResource(httpnode, assetOwnerAddress, fromAddress, assetOwnerKey); - HttpMethed.disConnect(); - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestConstantContract001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestConstantContract001.java deleted file mode 100644 index 811a0b44cc7..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestConstantContract001.java +++ /dev/null @@ -1,119 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import java.util.HashMap; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestConstantContract001 { - - private static String contractName; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] assetOwnerAddress = ecKey2.getAddress(); - String assetOwnerKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - String contractAddress; - Long amount = 2048000000L; - private JSONObject responseContent; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(0); - - /** - * constructor. - */ - @Test(enabled = true, description = "Deploy constant contract by http") - public void test1DeployConstantContract() { - PublicMethed.printAddress(assetOwnerKey); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.sendCoin(httpnode, fromAddress, assetOwnerAddress, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - String filePath = "src/test/resources/soliditycode/constantContract001.sol"; - contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String txid = HttpMethed - .deployContractGetTxid(httpnode, contractName, abi, code, 1000000L, 1000000000L, 100, - 11111111111111L, 0L, 0, 0L, assetOwnerAddress, assetOwnerKey); - - HttpMethed.waitToProduceOneBlock(httpnode); - logger.info(txid); - response = HttpMethed.getTransactionById(httpnode, txid); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(!responseContent.getString("contract_address").isEmpty()); - contractAddress = responseContent.getString("contract_address"); - - response = HttpMethed.getTransactionInfoById(httpnode, txid); - responseContent = HttpMethed.parseResponseContent(response); - String receiptString = responseContent.getString("receipt"); - Assert - .assertEquals(HttpMethed.parseStringContent(receiptString).getString("result"), "SUCCESS"); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get constant contract by http") - public void test2GetConstantContract() { - response = HttpMethed.getContract(httpnode, contractAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(responseContent.getString("consume_user_resource_percent"), "100"); - Assert.assertEquals(responseContent.getString("contract_address"), contractAddress); - Assert.assertEquals(responseContent.getString("origin_address"), - ByteArray.toHexString(assetOwnerAddress)); - Assert.assertEquals(responseContent.getString("origin_energy_limit"), "11111111111111"); - Assert.assertEquals(responseContent.getString("name"), contractName); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Trigger constant contract without parameterString by http") - public void test3TriggerConstantContract() { - String param1 = - "000000000000000000000000000000000000000000000000000000000000000" + Integer.toHexString(3); - String param2 = - "00000000000000000000000000000000000000000000000000000000000000" + Integer.toHexString(30); - logger.info(param1); - logger.info(param2); - String param = param1 + param2; - logger.info(ByteArray.toHexString(assetOwnerAddress)); - response = HttpMethed.triggerConstantContract(httpnode, assetOwnerAddress, contractAddress, - "testPure(uint256,uint256)", param, 1000000000L, assetOwnerKey); - HttpMethed.waitToProduceOneBlock(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(!responseContent.getString("transaction").isEmpty()); - JSONObject transactionObject = HttpMethed - .parseStringContent(responseContent.getString("transaction")); - Assert.assertTrue(!transactionObject.getString("raw_data").isEmpty()); - Assert.assertTrue(!transactionObject.getString("raw_data_hex").isEmpty()); - Assert.assertTrue(responseContent.getIntValue("energy_used") > 400 - && responseContent.getIntValue("energy_used") < 500); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.freedResource(httpnode, assetOwnerAddress, fromAddress, assetOwnerKey); - HttpMethed.disConnect(); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestExchange001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestExchange001.java deleted file mode 100644 index 7d38b0540c6..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestExchange001.java +++ /dev/null @@ -1,314 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestExchange001 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "testAssetIssue002_" + now; - private static String assetIssueId1; - private static String assetIssueId2; - private static Integer exchangeId; - private static Long beforeInjectBalance; - private static Long afterInjectBalance; - private static Long beforeWithdrawBalance; - private static Long afterWithdrawBalance; - private static Long beforeTransactionBalance; - private static Long afterTransactionBalance; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] exchangeOwnerAddress = ecKey1.getAddress(); - String exchangeOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] asset2Address = ecKey2.getAddress(); - String asset2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - Long amount = 2048000000L; - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf").getString("defaultParameter.assetUrl"); - private JSONObject responseContent; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(1); - private String httpSoliditynode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String httpPbftNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(4); - - - /** - * constructor. - */ - @Test(enabled = true, description = "Create asset issue by http") - public void test01CreateExchange() { - response = HttpMethed - .sendCoin(httpnode, fromAddress, exchangeOwnerAddress, 2048000000L, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.sendCoin(httpnode, fromAddress, asset2Address, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - //Create an asset issue - response = HttpMethed.assetIssue(httpnode, exchangeOwnerAddress, name, name, totalSupply, 1, 1, - System.currentTimeMillis() + 5000, System.currentTimeMillis() + 50000000, 2, 3, description, - url, 1000L, 1000L, exchangeOwnerKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.assetIssue(httpnode, asset2Address, name, name, totalSupply, 1, 1, - System.currentTimeMillis() + 5000, System.currentTimeMillis() + 50000000, 2, 3, description, - url, 1000L, 1000L, asset2Key); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed.getAccount(httpnode, exchangeOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - assetIssueId1 = responseContent.getString("asset_issued_ID"); - Assert.assertTrue(Integer.parseInt(assetIssueId1) > 1000000); - - response = HttpMethed.getAccount(httpnode, asset2Address); - responseContent = HttpMethed.parseResponseContent(response); - assetIssueId2 = responseContent.getString("asset_issued_ID"); - Assert.assertTrue(Integer.parseInt(assetIssueId2) > 1000000); - - response = HttpMethed - .transferAsset(httpnode, asset2Address, exchangeOwnerAddress, assetIssueId2, 10000000000L, - asset2Key); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - //Create exchange. - response = HttpMethed - .exchangeCreate(httpnode, exchangeOwnerAddress, assetIssueId1, 1000000L, assetIssueId2, - 1000000L, exchangeOwnerKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "List exchanges by http") - public void test02ListExchange() { - response = HttpMethed.listExchanges(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = JSONArray.parseArray(responseContent.getString("exchanges")); - Assert.assertTrue(jsonArray.size() >= 1); - exchangeId = jsonArray.size(); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "List exchanges from solidity by http") - public void test03ListExchangeFromSolidity() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - response = HttpMethed.listExchangesFromSolidity(httpSoliditynode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = JSONArray.parseArray(responseContent.getString("exchanges")); - Assert.assertTrue(jsonArray.size() >= 1); - exchangeId = jsonArray.size(); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "List exchanges from PBFT by http") - public void test04ListExchangeFromPbft() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - response = HttpMethed.listExchangesFromPbft(httpPbftNode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = JSONArray.parseArray(responseContent.getString("exchanges")); - Assert.assertTrue(jsonArray.size() >= 1); - exchangeId = jsonArray.size(); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "GetExchangeById by http") - public void test05GetExchangeById() { - response = HttpMethed.getExchangeById(httpnode, exchangeId); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getInteger("exchange_id").equals(exchangeId)); - Assert.assertEquals(responseContent.getString("creator_address"), - ByteArray.toHexString(exchangeOwnerAddress)); - beforeInjectBalance = responseContent.getLong("first_token_balance"); - - logger.info("beforeInjectBalance" + beforeInjectBalance); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetExchangeById from solidity by http") - public void test06GetExchangeByIdFromSolidity() { - response = HttpMethed.getExchangeByIdFromSolidity(httpSoliditynode, exchangeId); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getInteger("exchange_id").equals(exchangeId)); - Assert.assertEquals(responseContent.getString("creator_address"), - ByteArray.toHexString(exchangeOwnerAddress)); - beforeInjectBalance = responseContent.getLong("first_token_balance"); - - logger.info("beforeInjectBalance" + beforeInjectBalance); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetExchangeById from Pbft by http") - public void test07GetExchangeByIdFromPbft() { - response = HttpMethed.getExchangeByIdFromPbft(httpPbftNode, exchangeId); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getInteger("exchange_id").equals(exchangeId)); - Assert.assertEquals(responseContent.getString("creator_address"), - ByteArray.toHexString(exchangeOwnerAddress)); - beforeInjectBalance = responseContent.getLong("first_token_balance"); - - logger.info("beforeInjectBalance" + beforeInjectBalance); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "Inject exchange by http") - public void test08InjectExchange() { - //Inject exchange. - response = HttpMethed - .exchangeInject(httpnode, exchangeOwnerAddress, exchangeId, assetIssueId1, 300L, - exchangeOwnerKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getExchangeById(httpnode, exchangeId); - responseContent = HttpMethed.parseResponseContent(response); - afterInjectBalance = responseContent.getLong("first_token_balance"); - response = HttpMethed.getExchangeById(httpnode, exchangeId); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - logger.info("afterInjectBalance" + afterInjectBalance); - Assert.assertTrue(afterInjectBalance - beforeInjectBalance == 300L); - beforeWithdrawBalance = afterInjectBalance; - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Withdraw exchange by http") - public void test09WithdrawExchange() { - //Withdraw exchange. - response = HttpMethed - .exchangeWithdraw(httpnode, exchangeOwnerAddress, exchangeId, assetIssueId1, 170L, - exchangeOwnerKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getExchangeById(httpnode, exchangeId); - responseContent = HttpMethed.parseResponseContent(response); - afterWithdrawBalance = responseContent.getLong("first_token_balance"); - response = HttpMethed.getExchangeById(httpnode, exchangeId); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(beforeWithdrawBalance - afterWithdrawBalance == 170L); - beforeTransactionBalance = afterWithdrawBalance; - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Transaction exchange by http") - public void test10TransactionExchange() { - //Transaction exchange. - response = HttpMethed - .exchangeTransaction(httpnode, exchangeOwnerAddress, exchangeId, assetIssueId1, 100L, 1L, - exchangeOwnerKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getExchangeById(httpnode, exchangeId); - responseContent = HttpMethed.parseResponseContent(response); - afterTransactionBalance = responseContent.getLong("first_token_balance"); - response = HttpMethed.getExchangeById(httpnode, exchangeId); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(afterTransactionBalance - beforeTransactionBalance >= 1); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "Get asset issue list by name by http") - public void test11GetAssetIssueListByName() { - response = HttpMethed.getAssetIssueListByName(httpnode, name); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = JSONArray.parseArray(responseContent.get("assetIssue").toString()); - Assert.assertTrue(jsonArray.size() >= 2); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get asset issue list by name from solidity and pbft by http") - public void test12GetAssetIssueListByNameFromSolidityAndPbft() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - response = HttpMethed.getAssetIssueListByNameFromSolidity(httpSoliditynode, name); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = JSONArray.parseArray(responseContent.get("assetIssue").toString()); - Assert.assertTrue(jsonArray.size() >= 2); - - response = HttpMethed.getAssetIssueListByNameFromPbft(httpPbftNode, name); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - jsonArray = JSONArray.parseArray(responseContent.get("assetIssue").toString()); - Assert.assertTrue(jsonArray.size() >= 2); - } - - /** - * * constructor. * - */ - @Test(enabled = true, description = "Get paginated exchange list by http") - public void test13GetPaginatedExchangeList() { - - response = HttpMethed.getPaginatedExchangeList(httpnode, 0, 1); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - - JSONArray jsonArray = JSONArray.parseArray(responseContent.getString("exchanges")); - Assert.assertTrue(jsonArray.size() == 1); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.freedResource(httpnode, asset2Address, fromAddress, asset2Key); - HttpMethed.disConnect(); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestGetAccountBalance001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestGetAccountBalance001.java deleted file mode 100644 index 4ce34f4cefe..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestGetAccountBalance001.java +++ /dev/null @@ -1,218 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestGetAccountBalance001 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private JSONObject responseContent; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(0); - private String httpPbftNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(4); - private String httpSolidityNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] assetOwnerAddress = ecKey2.getAddress(); - String assetOwnerKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] randomAddress = ecKey3.getAddress(); - Long amount = 2048000000L; - String txid; - Integer sendcoinBlockNumber; - String sendcoinBlockHash; - Integer deployContractBlockNumber; - String deployContractBlockHash; - Long fee; - - /** - * constructor. - */ - @BeforeClass(enabled = true, description = "Deploy smart contract by http") - public void test01DeployContractForTest() { - HttpMethed.waitToProduceOneBlock(httpnode); - PublicMethed.printAddress(assetOwnerKey); - txid = HttpMethed.sendCoin(httpnode, fromAddress, assetOwnerAddress, amount, "", testKey002); - HttpMethed.waitToProduceOneBlock(httpnode); - txid = HttpMethed.sendCoin(httpnode, assetOwnerAddress, randomAddress, - amount / 1000000L, "", assetOwnerKey); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getTransactionInfoById(httpnode, txid); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - sendcoinBlockNumber = responseContent.getInteger("blockNumber"); - Assert.assertTrue(sendcoinBlockNumber > 0); - - response = HttpMethed.getBlockByNum(httpnode, sendcoinBlockNumber); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - sendcoinBlockHash = responseContent.getString("blockID"); - - String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken001_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken001_transferTokenContract"); - txid = HttpMethed - .deployContractGetTxid(httpnode, contractName, abi, code, 1000000L, 1000000000L, 100, - 11111111111111L, 0L, 0, 0L, assetOwnerAddress, assetOwnerKey); - - HttpMethed.waitToProduceOneBlock(httpnode); - logger.info(txid); - - response = HttpMethed.getTransactionInfoById(httpnode, txid); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - fee = responseContent.getLong("fee"); - deployContractBlockNumber = responseContent.getInteger("blockNumber"); - String receiptString = responseContent.getString("receipt"); - Assert - .assertEquals(HttpMethed.parseStringContent(receiptString).getString("result"), "SUCCESS"); - - response = HttpMethed.getBlockByNum(httpnode, deployContractBlockNumber); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - deployContractBlockHash = responseContent.getString("blockID"); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get account balance by http") - public void test01GetAccountBalance() { - response = HttpMethed.getAccountBalance(httpnode, assetOwnerAddress, - sendcoinBlockNumber, sendcoinBlockHash); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.size() >= 2); - final Long beforeBalance = responseContent.getLong("balance"); - - response = HttpMethed.getAccountBalance(httpnode, assetOwnerAddress, - deployContractBlockNumber, deployContractBlockHash); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.size() >= 2); - Long afterBalance = responseContent.getLong("balance"); - - Assert.assertTrue(beforeBalance - afterBalance == fee); - - - response = HttpMethed.getAccountBalance(httpnode, assetOwnerAddress, - deployContractBlockNumber, deployContractBlockHash); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.size() >= 2); - - - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "Get block balance by http") - public void test02GetBlockBalance() { - response = HttpMethed.getBlockBalance(httpnode, - sendcoinBlockNumber, sendcoinBlockHash); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.size() >= 2); - Assert.assertEquals(sendcoinBlockNumber, responseContent.getJSONObject("block_identifier") - .getInteger("number")); - JSONObject transactionObject = responseContent.getJSONArray("transaction_balance_trace") - .getJSONObject(0); - Assert.assertEquals(transactionObject.getString("type"), "TransferContract"); - Assert.assertTrue(Math.abs(transactionObject.getJSONArray("operation") - .getJSONObject(0).getLong("amount")) == 100000L); - Assert.assertTrue(Math.abs(transactionObject.getJSONArray("operation") - .getJSONObject(1).getLong("amount")) == amount / 1000000L); - Assert.assertTrue(Math.abs(transactionObject.getJSONArray("operation") - .getJSONObject(2).getLong("amount")) == amount / 1000000L); - - response = HttpMethed.getBlockBalance(httpnode, - deployContractBlockNumber, deployContractBlockHash); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.size() >= 2); - - transactionObject = responseContent.getJSONArray("transaction_balance_trace").getJSONObject(0); - Assert.assertEquals(transactionObject.getString("transaction_identifier"), txid); - Assert.assertEquals(transactionObject.getString("type"), "CreateSmartContract"); - Assert.assertTrue(transactionObject.getJSONArray("operation") - .getJSONObject(0).getLong("amount") == -fee); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get burn trx by http") - public void test03GetBurnTrx() { - - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] assetOwnerAddress = ecKey2.getAddress(); - String assetOwnerKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - HttpMethed.sendCoin(httpnode, fromAddress, assetOwnerAddress, amount, "", testKey002); - HttpMethed.waitToProduceOneBlock(httpnode); - final Long beforeBurnTrxAmount = HttpMethed.getBurnTrx(httpnode); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] receiverAddress = ecKey3.getAddress(); - - HttpMethed.sendCoin(httpnode, assetOwnerAddress, receiverAddress, amount - 103000L, - "", assetOwnerKey); - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSolidityNode); - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSolidityNode); - Long afterBurnTrxAmount = HttpMethed.getBurnTrx(httpnode); - logger.info(afterBurnTrxAmount + " : " + beforeBurnTrxAmount); - Assert.assertTrue(afterBurnTrxAmount - beforeBurnTrxAmount == 100000L); - - Assert.assertEquals(afterBurnTrxAmount, HttpMethed.getBurnTrxFromSolidity(httpSolidityNode)); - Assert.assertEquals(afterBurnTrxAmount, HttpMethed.getBurnTrxFromPbft(httpPbftNode)); - } - - /** - * constructor. - */ - @Test(enabled = false, description = "Get receipt root by http") - public void test04GetReceiptRootByHttp() { - response = HttpMethed.getBlockByNum(httpnode,sendcoinBlockNumber); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - String receiptsRoot = responseContent.getJSONObject("block_header").getJSONObject("raw_data") - .getString("receiptsRoot"); - Assert.assertNotEquals(receiptsRoot, - "0000000000000000000000000000000000000000000000000000000000000000"); - Assert.assertFalse(receiptsRoot.isEmpty()); - - } - - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.disConnect(); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMarket001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMarket001.java deleted file mode 100644 index 8dfe0701288..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMarket001.java +++ /dev/null @@ -1,533 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestMarket001 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "testAssetIssue002_" + now; - private static String assetIssueId1; - private static String assetIssueId2; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] sellAddress = ecKey1.getAddress(); - String sellKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] dev002Address = ecKey2.getAddress(); - private String dev002Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - String txId1; - String txId2; - String orderId; - String orderId1; - String orderId2; - - Long amount = 2048000000L; - - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf").getString("defaultParameter.assetUrl"); - private JSONObject responseContent; - private JSONObject getMarketOrderByIdContent; - private JSONObject getMarketOrderByIdContentFromSolidity; - private JSONObject getMarketOrderByIdContentFromPbft; - private JSONObject getMarketOrderByAccountContent; - private JSONObject getMarketOrderByAccountContentFromSolidity; - private JSONObject getMarketOrderByAccountContentFromPbft; - private JSONObject getMarketPairListContent; - private JSONObject getMarketPairListContentFromSolidity; - private JSONObject getMarketPairListContentFromPbft; - private JSONObject getMarketOrderListByPairContent; - private JSONObject getMarketOrderListByPairContentFromSolidity; - private JSONObject getMarketOrderListByPairContentFromPbft; - private JSONObject getMarketPriceByPairContent; - private JSONObject getMarketPriceByPairContentFromSolidity; - private JSONObject getMarketPriceByPairContentFromPbft; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(1); - private String httpSolidityNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String httpPbftNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(4); - - - /** - * constructor. - */ - @Test(enabled = true, description = "MarketSellAsset trx with trc10 by http") - public void test01MarketSellAsset() { - PublicMethed.printAddress(sellKey); - PublicMethed.printAddress(dev002Key); - - response = HttpMethed.sendCoin(httpnode, fromAddress, sellAddress, amount, testKey002); - response = HttpMethed.sendCoin(httpnode, fromAddress, dev002Address, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - //Create an asset issue - response = HttpMethed.assetIssue(httpnode, sellAddress, name, name, totalSupply, 1, 1, - System.currentTimeMillis() + 5000, System.currentTimeMillis() + 50000000, 2, 3, description, - url, 1000L, 1000L, sellKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getAccount(httpnode, sellAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - assetIssueId1 = responseContent.getString("asset_issued_ID"); - logger.info(assetIssueId1); - Assert.assertTrue(Integer.parseInt(assetIssueId1) > 1000000); - - response = HttpMethed.assetIssue(httpnode, dev002Address, name, name, totalSupply, 1, 1, - System.currentTimeMillis() + 5000, System.currentTimeMillis() + 50000000, 2, 3, description, - url, 1000L, 1000L, dev002Key); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getAccount(httpnode, dev002Address); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - assetIssueId2 = responseContent.getString("asset_issued_ID"); - logger.info(assetIssueId2); - Assert.assertTrue(Integer.parseInt(assetIssueId2) > 1000000); - - // transferAsset - response = HttpMethed - .transferAsset(httpnode, dev002Address, sellAddress, assetIssueId2, 10000L, dev002Key); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getAccount(httpnode, sellAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - // marketsellasset trc10-trc10 - txId2 = HttpMethed - .marketSellAssetGetTxId(httpnode, sellAddress, assetIssueId1, 10L, assetIssueId2, 500L, - sellKey, "true"); - HttpMethed.waitToProduceOneBlock(httpnode); - logger.info(txId2); - response = HttpMethed.getTransactionInfoById(httpnode, txId2); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(!responseContent.getString("orderId").isEmpty()); - orderId = responseContent.getString("orderId"); - logger.info("orderId:" + orderId); - - // marketsellasset trx-trc10 - txId1 = HttpMethed - .marketSellAssetGetTxId(httpnode, sellAddress, "_", 1000L, assetIssueId1, 20L, sellKey, - "false"); - HttpMethed.waitToProduceOneBlock(httpnode); - logger.info(txId1); - response = HttpMethed.getTransactionInfoById(httpnode, txId1); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(!responseContent.getString("orderId").isEmpty()); - orderId1 = responseContent.getString("orderId"); - logger.info("orderId1:" + orderId1); - - // marketsellasset trc10-trx - txId2 = HttpMethed - .marketSellAssetGetTxId(httpnode, sellAddress, assetIssueId1, 10L, "_", 500L, sellKey, - "true"); - HttpMethed.waitToProduceOneBlock(httpnode); - logger.info(txId2); - response = HttpMethed.getTransactionInfoById(httpnode, txId2); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONObject orderDetails = responseContent.getJSONArray("orderDetails").getJSONObject(0); - Assert.assertTrue(!responseContent.getString("orderId").isEmpty()); - Assert.assertTrue(500L == orderDetails.getLong("fillBuyQuantity")); - Assert.assertTrue(10L == orderDetails.getLong("fillSellQuantity")); - Assert - .assertEquals(responseContent.getString("orderId"), orderDetails.getString("takerOrderId")); - Assert.assertEquals(orderId1, orderDetails.getString("makerOrderId")); - orderId2 = responseContent.getString("orderId"); - logger.info("orderId2:" + orderId2); - - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketOrderById by http") - public void test02GetMarketOrderById() { - // getMarketOrderById orderId1 - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getMarketOrderById(httpnode, orderId1, "true"); - getMarketOrderByIdContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderByIdContent); - Assert.assertEquals(Base58.encode58Check(sellAddress), - getMarketOrderByIdContent.getString("owner_address")); - Assert.assertEquals("_", getMarketOrderByIdContent.getString("sell_token_id")); - Assert.assertTrue(1000L == getMarketOrderByIdContent.getLong("sell_token_quantity")); - Assert.assertEquals(assetIssueId1, getMarketOrderByIdContent.getString("buy_token_id")); - Assert.assertTrue(20L == getMarketOrderByIdContent.getLong("buy_token_quantity")); - Assert.assertTrue(500L == getMarketOrderByIdContent.getLong("sell_token_quantity_remain")); - - // getMarketOrderById orderId2 - HttpResponse response2 = HttpMethed.getMarketOrderById(httpnode, orderId2, "false"); - JSONObject getMarketOrderByIdContent2 = HttpMethed.parseResponseContent(response2); - HttpMethed.printJsonContent(getMarketOrderByIdContent2); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketOrderById by http from solidity") - public void test03GetMarketOrderByIdFromSolidity() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSolidityNode); - response = HttpMethed.getMarketOrderByIdFromSolidity(httpSolidityNode, orderId1, "true"); - getMarketOrderByIdContentFromSolidity = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderByIdContentFromSolidity); - Assert.assertEquals(Base58.encode58Check(sellAddress), - getMarketOrderByIdContentFromSolidity.getString("owner_address")); - Assert.assertEquals("_", getMarketOrderByIdContentFromSolidity.getString("sell_token_id")); - Assert - .assertTrue(1000L == getMarketOrderByIdContentFromSolidity.getLong("sell_token_quantity")); - Assert.assertEquals(assetIssueId1, - getMarketOrderByIdContentFromSolidity.getString("buy_token_id")); - Assert.assertTrue(20L == getMarketOrderByIdContentFromSolidity.getLong("buy_token_quantity")); - Assert.assertTrue( - 500L == getMarketOrderByIdContentFromSolidity.getLong("sell_token_quantity_remain")); - Assert.assertEquals(getMarketOrderByIdContent, getMarketOrderByIdContentFromSolidity); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketOrderById by http from pbft") - public void test04GetMarketOrderByIdFromPbft() { - HttpMethed.waitToProduceOneBlockFromPbft(httpnode, httpPbftNode); - response = HttpMethed.getMarketOrderByIdFromPbft(httpPbftNode, orderId1, "true"); - getMarketOrderByIdContentFromPbft = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderByIdContentFromPbft); - Assert.assertEquals(Base58.encode58Check(sellAddress), - getMarketOrderByIdContentFromPbft.getString("owner_address")); - Assert.assertEquals("_", getMarketOrderByIdContentFromPbft.getString("sell_token_id")); - Assert - .assertTrue(1000L == getMarketOrderByIdContentFromPbft.getLong("sell_token_quantity")); - Assert.assertEquals(assetIssueId1, - getMarketOrderByIdContentFromPbft.getString("buy_token_id")); - Assert.assertTrue(20L == getMarketOrderByIdContentFromPbft.getLong("buy_token_quantity")); - Assert.assertTrue( - 500L == getMarketOrderByIdContentFromPbft.getLong("sell_token_quantity_remain")); - Assert.assertEquals(getMarketOrderByIdContent, getMarketOrderByIdContentFromPbft); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketOrderByAccount by http") - public void test05GetMarketOrderByAccount() { - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getMarketOrderByAccount(httpnode, sellAddress, "true"); - getMarketOrderByAccountContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderByAccountContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - JSONObject orders = getMarketOrderByAccountContent.getJSONArray("orders").getJSONObject(1); - Assert.assertEquals(Base58.encode58Check(sellAddress), orders.getString("owner_address")); - Assert.assertEquals("_", orders.getString("sell_token_id")); - Assert.assertTrue(1000L == orders.getLong("sell_token_quantity")); - Assert.assertEquals(assetIssueId1, orders.getString("buy_token_id")); - Assert.assertTrue(20L == orders.getLong("buy_token_quantity")); - Assert.assertTrue(500L == orders.getLong("sell_token_quantity_remain")); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketOrderByAccount by http from solidity") - public void test06GetMarketOrderByAccountFromSolidity() { - response = HttpMethed - .getMarketOrderByAccountFromSolidity(httpSolidityNode, sellAddress, "true"); - getMarketOrderByAccountContentFromSolidity = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderByAccountContentFromSolidity); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - JSONObject orders = getMarketOrderByAccountContentFromSolidity.getJSONArray("orders") - .getJSONObject(1); - Assert.assertEquals(Base58.encode58Check(sellAddress), orders.getString("owner_address")); - Assert.assertEquals("_", orders.getString("sell_token_id")); - Assert.assertTrue(1000L == orders.getLong("sell_token_quantity")); - Assert.assertEquals(assetIssueId1, orders.getString("buy_token_id")); - Assert.assertTrue(20L == orders.getLong("buy_token_quantity")); - Assert.assertTrue(500L == orders.getLong("sell_token_quantity_remain")); - Assert.assertEquals(getMarketOrderByAccountContent, getMarketOrderByAccountContentFromSolidity); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketOrderByAccount by http from pbft") - public void test07GetMarketOrderByAccountFromPbft() { - response = HttpMethed.getMarketOrderByAccountFromPbft(httpPbftNode, sellAddress, "true"); - getMarketOrderByAccountContentFromPbft = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderByAccountContentFromPbft); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - JSONObject orders = getMarketOrderByAccountContentFromPbft.getJSONArray("orders") - .getJSONObject(1); - Assert.assertEquals(Base58.encode58Check(sellAddress), orders.getString("owner_address")); - Assert.assertEquals("_", orders.getString("sell_token_id")); - Assert.assertTrue(1000L == orders.getLong("sell_token_quantity")); - Assert.assertEquals(assetIssueId1, orders.getString("buy_token_id")); - Assert.assertTrue(20L == orders.getLong("buy_token_quantity")); - Assert.assertTrue(500L == orders.getLong("sell_token_quantity_remain")); - Assert.assertEquals(getMarketOrderByAccountContent, getMarketOrderByAccountContentFromPbft); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketPairList by http") - public void test08GetMarketPairList() { - response = HttpMethed.getMarketPairList(httpnode, "true"); - getMarketPairListContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketPairListContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - int orderPairSize = getMarketPairListContent.getJSONArray("orderPair").size(); - Assert.assertTrue(orderPairSize > 0); - Assert.assertEquals("_", - getMarketPairListContent.getJSONArray("orderPair").getJSONObject(orderPairSize - 1) - .getString("sell_token_id")); - Assert.assertEquals(assetIssueId1, - getMarketPairListContent.getJSONArray("orderPair").getJSONObject(orderPairSize - 1) - .getString("buy_token_id")); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketPairList by http from solidity") - public void test09GetMarketPairListFromSolidity() { - response = HttpMethed.getMarketPairListFromSolidity(httpSolidityNode, "true"); - getMarketPairListContentFromSolidity = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketPairListContentFromSolidity); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - int orderPairSize = getMarketPairListContentFromSolidity.getJSONArray("orderPair").size(); - Assert.assertTrue(orderPairSize > 0); - Assert.assertEquals("_", - getMarketPairListContentFromSolidity.getJSONArray("orderPair") - .getJSONObject(orderPairSize - 1) - .getString("sell_token_id")); - Assert.assertEquals(assetIssueId1, - getMarketPairListContentFromSolidity.getJSONArray("orderPair") - .getJSONObject(orderPairSize - 1) - .getString("buy_token_id")); - Assert.assertEquals(getMarketPairListContent, getMarketPairListContentFromSolidity); - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketPairList by http from pbft") - public void test10GetMarketPairListFromPbft() { - response = HttpMethed.getMarketPairListFromPbft(httpPbftNode, "true"); - getMarketPairListContentFromPbft = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketPairListContentFromPbft); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - int orderPairSize = getMarketPairListContentFromPbft.getJSONArray("orderPair").size(); - Assert.assertTrue(orderPairSize > 0); - Assert.assertEquals("_", - getMarketPairListContentFromPbft.getJSONArray("orderPair") - .getJSONObject(orderPairSize - 1) - .getString("sell_token_id")); - Assert.assertEquals(assetIssueId1, - getMarketPairListContentFromPbft.getJSONArray("orderPair") - .getJSONObject(orderPairSize - 1) - .getString("buy_token_id")); - Assert.assertEquals(getMarketPairListContent, getMarketPairListContentFromPbft); - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketOrderListByPair by http") - public void test11GetMarketOrderListByPair() { - response = HttpMethed.getMarketOrderListByPair(httpnode, "_", assetIssueId1, "true"); - getMarketOrderListByPairContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderListByPairContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - JSONObject orders = getMarketOrderListByPairContent.getJSONArray("orders") - .getJSONObject(getMarketOrderListByPairContent.getJSONArray("orders").size() - 1); - Assert.assertEquals(Base58.encode58Check(sellAddress), orders.getString("owner_address")); - Assert.assertEquals("_", orders.getString("sell_token_id")); - Assert.assertTrue(1000L == orders.getLong("sell_token_quantity")); - Assert.assertEquals(assetIssueId1, orders.getString("buy_token_id")); - Assert.assertTrue(20L == orders.getLong("buy_token_quantity")); - Assert.assertEquals(getMarketOrderListByPairContent.getLong("sell_token_quantity"), - getMarketOrderListByPairContent.getLong("sell_token_quantity_remain")); - - Assert.assertTrue(getMarketOrderListByPairContent.getJSONArray("orders").size() > 0); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketOrderListByPair by http from solidity") - public void test12GetMarketOrderListByPairFromSolidity() { - response = HttpMethed - .getMarketOrderListByPairFromSolidity(httpSolidityNode, "_", assetIssueId1, "true"); - getMarketOrderListByPairContentFromSolidity = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderListByPairContentFromSolidity); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - JSONObject orders = getMarketOrderListByPairContentFromSolidity.getJSONArray("orders") - .getJSONObject( - getMarketOrderListByPairContentFromSolidity.getJSONArray("orders").size() - 1); - Assert.assertEquals(Base58.encode58Check(sellAddress), orders.getString("owner_address")); - Assert.assertEquals("_", orders.getString("sell_token_id")); - Assert.assertTrue(1000L == orders.getLong("sell_token_quantity")); - Assert.assertEquals(assetIssueId1, orders.getString("buy_token_id")); - Assert.assertTrue(20L == orders.getLong("buy_token_quantity")); - Assert.assertEquals(getMarketOrderListByPairContentFromSolidity.getLong("sell_token_quantity"), - getMarketOrderListByPairContentFromSolidity.getLong("sell_token_quantity_remain")); - - Assert - .assertTrue(getMarketOrderListByPairContentFromSolidity.getJSONArray("orders").size() > 0); - Assert - .assertEquals(getMarketOrderListByPairContent, getMarketOrderListByPairContentFromSolidity); - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketOrderListByPair by http from pbft") - public void test13GetMarketOrderListByPairFromPbft() { - response = HttpMethed - .getMarketOrderListByPairFromPbft(httpPbftNode, "_", assetIssueId1, "true"); - getMarketOrderListByPairContentFromPbft = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderListByPairContentFromPbft); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - JSONObject orders = getMarketOrderListByPairContentFromPbft.getJSONArray("orders") - .getJSONObject( - getMarketOrderListByPairContentFromPbft.getJSONArray("orders").size() - 1); - Assert.assertEquals(Base58.encode58Check(sellAddress), orders.getString("owner_address")); - Assert.assertEquals("_", orders.getString("sell_token_id")); - Assert.assertTrue(1000L == orders.getLong("sell_token_quantity")); - Assert.assertEquals(assetIssueId1, orders.getString("buy_token_id")); - Assert.assertTrue(20L == orders.getLong("buy_token_quantity")); - Assert.assertEquals(getMarketOrderListByPairContentFromPbft.getLong("sell_token_quantity"), - getMarketOrderListByPairContentFromPbft.getLong("sell_token_quantity_remain")); - - Assert - .assertTrue(getMarketOrderListByPairContentFromPbft.getJSONArray("orders").size() > 0); - Assert - .assertEquals(getMarketOrderListByPairContent, getMarketOrderListByPairContentFromPbft); - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketPriceByPair from by http") - public void test14GetMarketPriceByPair() { - response = HttpMethed.getMarketPriceByPair(httpnode, "_", assetIssueId1, "true"); - getMarketPriceByPairContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketPriceByPairContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - Assert.assertEquals("_", getMarketPriceByPairContent.getString("sell_token_id")); - Assert.assertEquals(assetIssueId1, getMarketPriceByPairContent.getString("buy_token_id")); - JSONObject prices = getMarketPriceByPairContent.getJSONArray("prices").getJSONObject(0); - Assert.assertEquals("50", prices.getString("sell_token_quantity")); - Assert.assertEquals("1", prices.getString("buy_token_quantity")); - Assert.assertTrue(getMarketPriceByPairContent.getJSONArray("prices").size() > 0); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketPriceByPair from by http from solidity") - public void test15GetMarketPriceByPairFromSolidity() { - response = HttpMethed - .getMarketPriceByPairFromSolidity(httpSolidityNode, "_", assetIssueId1, "true"); - getMarketPriceByPairContentFromSolidity = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketPriceByPairContentFromSolidity); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - Assert.assertEquals("_", getMarketPriceByPairContentFromSolidity.getString("sell_token_id")); - Assert - .assertEquals(assetIssueId1, - getMarketPriceByPairContentFromSolidity.getString("buy_token_id")); - JSONObject prices = getMarketPriceByPairContentFromSolidity.getJSONArray("prices") - .getJSONObject(0); - Assert.assertEquals("50", prices.getString("sell_token_quantity")); - Assert.assertEquals("1", prices.getString("buy_token_quantity")); - Assert.assertTrue(getMarketPriceByPairContentFromSolidity.getJSONArray("prices").size() > 0); - Assert.assertEquals(getMarketPriceByPairContent, getMarketPriceByPairContentFromSolidity); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketPriceByPair from by http from pbft") - public void test16GetMarketPriceByPairFromPbft() { - response = HttpMethed - .getMarketPriceByPairFromPbft(httpPbftNode, "_", assetIssueId1, "true"); - getMarketPriceByPairContentFromPbft = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketPriceByPairContentFromPbft); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - Assert.assertEquals("_", getMarketPriceByPairContentFromPbft.getString("sell_token_id")); - Assert - .assertEquals(assetIssueId1, - getMarketPriceByPairContentFromPbft.getString("buy_token_id")); - JSONObject prices = getMarketPriceByPairContentFromPbft.getJSONArray("prices") - .getJSONObject(0); - Assert.assertEquals("50", prices.getString("sell_token_quantity")); - Assert.assertEquals("1", prices.getString("buy_token_quantity")); - Assert.assertTrue(getMarketPriceByPairContentFromPbft.getJSONArray("prices").size() > 0); - Assert.assertEquals(getMarketPriceByPairContent, getMarketPriceByPairContentFromPbft); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "MarketCancelOrder trx with trc10 by http") - public void test17MarketCancelOrder() { - response = HttpMethed.getMarketOrderByAccount(httpnode, sellAddress, "true"); - getMarketOrderByAccountContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderByAccountContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - Assert.assertEquals(2, getMarketOrderByAccountContent.getJSONArray("orders").size()); - - // MarketCancelOrder - String txId = HttpMethed.marketCancelOrder(httpnode, sellAddress, orderId1, sellKey, "true"); - HttpMethed.waitToProduceOneBlock(httpnode); - logger.info(txId); - response = HttpMethed.getTransactionInfoById(httpnode, txId); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - - response = HttpMethed.getMarketOrderByAccount(httpnode, sellAddress, "true"); - getMarketOrderByAccountContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderByAccountContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - Assert.assertEquals(1, getMarketOrderByAccountContent.getJSONArray("orders").size()); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.freedResource(httpnode, sellAddress, fromAddress, sellKey); - HttpMethed.disConnect(); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMarket002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMarket002.java deleted file mode 100644 index 91217ff06ea..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMarket002.java +++ /dev/null @@ -1,534 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestMarket002 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "testAssetIssue002_" + now; - private static String assetIssueId1; - private static String assetIssueId2; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] sellAddress = ecKey1.getAddress(); - String sellKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] dev002Address = ecKey2.getAddress(); - private String dev002Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - String txId1; - String txId2; - String orderId; - String orderId1; - String orderId2; - - Long amount = 2048000000L; - - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf").getString("defaultParameter.assetUrl"); - private JSONObject responseContent; - private JSONObject getMarketOrderByIdContent; - private JSONObject getMarketOrderByIdContentFromSolidity; - private JSONObject getMarketOrderByIdContentFromPbft; - private JSONObject getMarketOrderByAccountContent; - private JSONObject getMarketOrderByAccountContentFromSolidity; - private JSONObject getMarketOrderByAccountContentFromPbft; - private JSONObject getMarketPairListContent; - private JSONObject getMarketPairListContentFromSolidity; - private JSONObject getMarketPairListContentFromPbft; - private JSONObject getMarketOrderListByPairContent; - private JSONObject getMarketOrderListByPairContentFromSolidity; - private JSONObject getMarketOrderListByPairContentFromPbft; - private JSONObject getMarketPriceByPairContent; - private JSONObject getMarketPriceByPairContentFromSolidity; - private JSONObject getMarketPriceByPairContentFromPbft; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(1); - private String httpSolidityNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String httpPbftNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(4); - - - /** - * constructor. - */ - @Test(enabled = true, description = "MarketSellAsset trx with trc10 by http") - public void test01MarketSellAsset() { - PublicMethed.printAddress(sellKey); - PublicMethed.printAddress(dev002Key); - - response = HttpMethed.sendCoin(httpnode, fromAddress, sellAddress, amount, testKey002); - response = HttpMethed.sendCoin(httpnode, fromAddress, dev002Address, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - //Create an asset issue - response = HttpMethed.assetIssue(httpnode, sellAddress, name, name, totalSupply, 1, 1, - System.currentTimeMillis() + 5000, System.currentTimeMillis() + 50000000, 2, 3, description, - url, 1000L, 1000L, sellKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getAccount(httpnode, sellAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - assetIssueId1 = responseContent.getString("asset_issued_ID"); - logger.info(assetIssueId1); - Assert.assertTrue(Integer.parseInt(assetIssueId1) > 1000000); - - response = HttpMethed.assetIssue(httpnode, dev002Address, name, name, totalSupply, 1, 1, - System.currentTimeMillis() + 5000, System.currentTimeMillis() + 50000000, 2, 3, description, - url, 1000L, 1000L, dev002Key); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getAccount(httpnode, dev002Address); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - assetIssueId2 = responseContent.getString("asset_issued_ID"); - logger.info(assetIssueId2); - Assert.assertTrue(Integer.parseInt(assetIssueId2) > 1000000); - - // transferAsset - response = HttpMethed - .transferAsset(httpnode, dev002Address, sellAddress, assetIssueId2, 10000L, dev002Key); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getAccount(httpnode, sellAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - // marketsellasset trc10-trc10 - txId2 = HttpMethed - .marketSellAssetGetTxId(httpnode, sellAddress, assetIssueId1, 10L, assetIssueId2, 500L, - sellKey, "false"); - HttpMethed.waitToProduceOneBlock(httpnode); - logger.info(txId2); - response = HttpMethed.getTransactionInfoById(httpnode, txId2); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(!responseContent.getString("orderId").isEmpty()); - orderId = responseContent.getString("orderId"); - logger.info("orderId:" + orderId); - - // marketsellasset trx-trc10 - txId1 = HttpMethed - .marketSellAssetGetTxId(httpnode, sellAddress, "_", 1000L, assetIssueId1, 20L, sellKey, - "false"); - HttpMethed.waitToProduceOneBlock(httpnode); - logger.info(txId1); - response = HttpMethed.getTransactionInfoById(httpnode, txId1); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(!responseContent.getString("orderId").isEmpty()); - orderId1 = responseContent.getString("orderId"); - logger.info("orderId1:" + orderId1); - - // marketsellasset trc10-trx - txId2 = HttpMethed - .marketSellAssetGetTxId(httpnode, sellAddress, assetIssueId1, 10L, "_", 500L, sellKey, - "false"); - HttpMethed.waitToProduceOneBlock(httpnode); - logger.info(txId2); - response = HttpMethed.getTransactionInfoById(httpnode, txId2); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONObject orderDetails = responseContent.getJSONArray("orderDetails").getJSONObject(0); - Assert.assertTrue(!responseContent.getString("orderId").isEmpty()); - Assert.assertTrue(500L == orderDetails.getLong("fillBuyQuantity")); - Assert.assertTrue(10L == orderDetails.getLong("fillSellQuantity")); - Assert - .assertEquals(responseContent.getString("orderId"), orderDetails.getString("takerOrderId")); - Assert.assertEquals(orderId1, orderDetails.getString("makerOrderId")); - orderId2 = responseContent.getString("orderId"); - logger.info("orderId2:" + orderId2); - - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketOrderById by http") - public void test02GetMarketOrderById() { - // getMarketOrderById orderId1 - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getMarketOrderById(httpnode, orderId1, "false"); - getMarketOrderByIdContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderByIdContent); - Assert.assertEquals(ByteArray.toHexString(sellAddress), - getMarketOrderByIdContent.getString("owner_address")); - Assert.assertEquals("5f", getMarketOrderByIdContent.getString("sell_token_id")); - Assert.assertTrue(1000L == getMarketOrderByIdContent.getLong("sell_token_quantity")); - Assert.assertEquals(HttpMethed.str2hex(assetIssueId1), - getMarketOrderByIdContent.getString("buy_token_id")); - Assert.assertTrue(20L == getMarketOrderByIdContent.getLong("buy_token_quantity")); - Assert.assertTrue(500L == getMarketOrderByIdContent.getLong("sell_token_quantity_remain")); - - // getMarketOrderById orderId2 - HttpResponse response2 = HttpMethed.getMarketOrderById(httpnode, orderId2, "false"); - JSONObject getMarketOrderByIdContent2 = HttpMethed.parseResponseContent(response2); - HttpMethed.printJsonContent(getMarketOrderByIdContent2); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketOrderById by http from solidity") - public void test03GetMarketOrderByIdFromSolidity() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSolidityNode); - response = HttpMethed.getMarketOrderByIdFromSolidity(httpSolidityNode, orderId1, "false"); - getMarketOrderByIdContentFromSolidity = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderByIdContentFromSolidity); - Assert.assertEquals(ByteArray.toHexString(sellAddress), - getMarketOrderByIdContentFromSolidity.getString("owner_address")); - Assert.assertEquals("5f", getMarketOrderByIdContentFromSolidity.getString("sell_token_id")); - Assert - .assertTrue(1000L == getMarketOrderByIdContentFromSolidity.getLong("sell_token_quantity")); - Assert.assertEquals(HttpMethed.str2hex(assetIssueId1), - getMarketOrderByIdContentFromSolidity.getString("buy_token_id")); - Assert.assertTrue(20L == getMarketOrderByIdContentFromSolidity.getLong("buy_token_quantity")); - Assert.assertTrue( - 500L == getMarketOrderByIdContentFromSolidity.getLong("sell_token_quantity_remain")); - Assert.assertEquals(getMarketOrderByIdContent, getMarketOrderByIdContentFromSolidity); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketOrderById by http from pbft") - public void test04GetMarketOrderByIdFromPbft() { - HttpMethed.waitToProduceOneBlockFromPbft(httpnode, httpPbftNode); - response = HttpMethed.getMarketOrderByIdFromPbft(httpPbftNode, orderId1, "false"); - getMarketOrderByIdContentFromPbft = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderByIdContentFromPbft); - Assert.assertEquals(ByteArray.toHexString(sellAddress), - getMarketOrderByIdContentFromPbft.getString("owner_address")); - Assert.assertEquals("5f", getMarketOrderByIdContentFromPbft.getString("sell_token_id")); - Assert - .assertTrue(1000L == getMarketOrderByIdContentFromPbft.getLong("sell_token_quantity")); - Assert.assertEquals(HttpMethed.str2hex(assetIssueId1), - getMarketOrderByIdContentFromPbft.getString("buy_token_id")); - Assert.assertTrue(20L == getMarketOrderByIdContentFromPbft.getLong("buy_token_quantity")); - Assert.assertTrue( - 500L == getMarketOrderByIdContentFromPbft.getLong("sell_token_quantity_remain")); - Assert.assertEquals(getMarketOrderByIdContent, getMarketOrderByIdContentFromPbft); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketOrderByAccount by http") - public void test05GetMarketOrderByAccount() { - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getMarketOrderByAccount(httpnode, sellAddress, "false"); - getMarketOrderByAccountContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderByAccountContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - JSONObject orders = getMarketOrderByAccountContent.getJSONArray("orders").getJSONObject(1); - Assert.assertEquals(ByteArray.toHexString(sellAddress), orders.getString("owner_address")); - Assert.assertEquals("5f", orders.getString("sell_token_id")); - Assert.assertTrue(1000L == orders.getLong("sell_token_quantity")); - Assert.assertEquals(HttpMethed.str2hex(assetIssueId1), orders.getString("buy_token_id")); - Assert.assertTrue(20L == orders.getLong("buy_token_quantity")); - Assert.assertTrue(500L == orders.getLong("sell_token_quantity_remain")); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketOrderByAccount by http from solidity") - public void test06GetMarketOrderByAccountFromSolidity() { - response = HttpMethed - .getMarketOrderByAccountFromSolidity(httpSolidityNode, sellAddress, "false"); - getMarketOrderByAccountContentFromSolidity = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderByAccountContentFromSolidity); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - JSONObject orders = getMarketOrderByAccountContentFromSolidity.getJSONArray("orders") - .getJSONObject(1); - Assert.assertEquals(ByteArray.toHexString(sellAddress), orders.getString("owner_address")); - Assert.assertEquals("5f", orders.getString("sell_token_id")); - Assert.assertTrue(1000L == orders.getLong("sell_token_quantity")); - Assert.assertEquals(HttpMethed.str2hex(assetIssueId1), orders.getString("buy_token_id")); - Assert.assertTrue(20L == orders.getLong("buy_token_quantity")); - Assert.assertTrue(500L == orders.getLong("sell_token_quantity_remain")); - Assert.assertEquals(getMarketOrderByAccountContent, getMarketOrderByAccountContentFromSolidity); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketOrderByAccount by http from pbft") - public void test07GetMarketOrderByAccountFromPbft() { - response = HttpMethed.getMarketOrderByAccountFromPbft(httpPbftNode, sellAddress, "false"); - getMarketOrderByAccountContentFromPbft = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderByAccountContentFromPbft); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - JSONObject orders = getMarketOrderByAccountContentFromPbft.getJSONArray("orders") - .getJSONObject(1); - Assert.assertEquals(ByteArray.toHexString(sellAddress), orders.getString("owner_address")); - Assert.assertEquals("5f", orders.getString("sell_token_id")); - Assert.assertTrue(1000L == orders.getLong("sell_token_quantity")); - Assert.assertEquals(HttpMethed.str2hex(assetIssueId1), orders.getString("buy_token_id")); - Assert.assertTrue(20L == orders.getLong("buy_token_quantity")); - Assert.assertTrue(500L == orders.getLong("sell_token_quantity_remain")); - Assert.assertEquals(getMarketOrderByAccountContent, getMarketOrderByAccountContentFromPbft); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketPairList by http") - public void test08GetMarketPairList() { - response = HttpMethed.getMarketPairList(httpnode, "false"); - getMarketPairListContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketPairListContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - int orderPairSize = getMarketPairListContent.getJSONArray("orderPair").size(); - Assert.assertTrue(orderPairSize > 0); - Assert.assertEquals("5f", - getMarketPairListContent.getJSONArray("orderPair").getJSONObject(orderPairSize - 1) - .getString("sell_token_id")); - Assert.assertEquals(HttpMethed.str2hex(assetIssueId1), - getMarketPairListContent.getJSONArray("orderPair").getJSONObject(orderPairSize - 1) - .getString("buy_token_id")); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketPairList by http from solidity") - public void test09GetMarketPairListFromSolidity() { - response = HttpMethed.getMarketPairListFromSolidity(httpSolidityNode, "false"); - getMarketPairListContentFromSolidity = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketPairListContentFromSolidity); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - int orderPairSize = getMarketPairListContentFromSolidity.getJSONArray("orderPair").size(); - Assert.assertTrue(orderPairSize > 0); - Assert.assertEquals("5f", - getMarketPairListContentFromSolidity.getJSONArray("orderPair") - .getJSONObject(orderPairSize - 1) - .getString("sell_token_id")); - Assert.assertEquals(HttpMethed.str2hex(assetIssueId1), - getMarketPairListContentFromSolidity.getJSONArray("orderPair") - .getJSONObject(orderPairSize - 1) - .getString("buy_token_id")); - Assert.assertEquals(getMarketPairListContent, getMarketPairListContentFromSolidity); - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketPairList by http from pbft") - public void test10GetMarketPairListFromPbft() { - response = HttpMethed.getMarketPairListFromPbft(httpPbftNode, "false"); - getMarketPairListContentFromPbft = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketPairListContentFromPbft); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - int orderPairSize = getMarketPairListContentFromPbft.getJSONArray("orderPair").size(); - Assert.assertTrue(orderPairSize > 0); - Assert.assertEquals("5f", - getMarketPairListContentFromPbft.getJSONArray("orderPair") - .getJSONObject(orderPairSize - 1) - .getString("sell_token_id")); - Assert.assertEquals(HttpMethed.str2hex(assetIssueId1), - getMarketPairListContentFromPbft.getJSONArray("orderPair") - .getJSONObject(orderPairSize - 1) - .getString("buy_token_id")); - Assert.assertEquals(getMarketPairListContent, getMarketPairListContentFromPbft); - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketOrderListByPair by http") - public void test11GetMarketOrderListByPair() { - response = HttpMethed.getMarketOrderListByPair(httpnode, "_", assetIssueId1, "false"); - getMarketOrderListByPairContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderListByPairContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - JSONObject orders = getMarketOrderListByPairContent.getJSONArray("orders") - .getJSONObject(getMarketOrderListByPairContent.getJSONArray("orders").size() - 1); - Assert.assertEquals(ByteArray.toHexString(sellAddress), orders.getString("owner_address")); - Assert.assertEquals("5f", orders.getString("sell_token_id")); - Assert.assertTrue(1000L == orders.getLong("sell_token_quantity")); - Assert.assertEquals(HttpMethed.str2hex(assetIssueId1), orders.getString("buy_token_id")); - Assert.assertTrue(20L == orders.getLong("buy_token_quantity")); - Assert.assertEquals(getMarketOrderListByPairContent.getLong("sell_token_quantity"), - getMarketOrderListByPairContent.getLong("sell_token_quantity_remain")); - - Assert.assertTrue(getMarketOrderListByPairContent.getJSONArray("orders").size() > 0); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketOrderListByPair by http from solidity") - public void test12GetMarketOrderListByPairFromSolidity() { - response = HttpMethed - .getMarketOrderListByPairFromSolidity(httpSolidityNode, "_", assetIssueId1, "false"); - getMarketOrderListByPairContentFromSolidity = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderListByPairContentFromSolidity); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - JSONObject orders = getMarketOrderListByPairContentFromSolidity.getJSONArray("orders") - .getJSONObject( - getMarketOrderListByPairContentFromSolidity.getJSONArray("orders").size() - 1); - Assert.assertEquals(ByteArray.toHexString(sellAddress), orders.getString("owner_address")); - Assert.assertEquals("5f", orders.getString("sell_token_id")); - Assert.assertTrue(1000L == orders.getLong("sell_token_quantity")); - Assert.assertEquals(HttpMethed.str2hex(assetIssueId1), orders.getString("buy_token_id")); - Assert.assertTrue(20L == orders.getLong("buy_token_quantity")); - Assert.assertEquals(getMarketOrderListByPairContentFromSolidity.getLong("sell_token_quantity"), - getMarketOrderListByPairContentFromSolidity.getLong("sell_token_quantity_remain")); - - Assert - .assertTrue(getMarketOrderListByPairContentFromSolidity.getJSONArray("orders").size() > 0); - Assert - .assertEquals(getMarketOrderListByPairContent, getMarketOrderListByPairContentFromSolidity); - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketOrderListByPair by http from pbft") - public void test13GetMarketOrderListByPairFromPbft() { - response = HttpMethed - .getMarketOrderListByPairFromPbft(httpPbftNode, "_", assetIssueId1, "false"); - getMarketOrderListByPairContentFromPbft = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderListByPairContentFromPbft); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - JSONObject orders = getMarketOrderListByPairContentFromPbft.getJSONArray("orders") - .getJSONObject( - getMarketOrderListByPairContentFromPbft.getJSONArray("orders").size() - 1); - Assert.assertEquals(ByteArray.toHexString(sellAddress), orders.getString("owner_address")); - Assert.assertEquals("5f", orders.getString("sell_token_id")); - Assert.assertTrue(1000L == orders.getLong("sell_token_quantity")); - Assert.assertEquals(HttpMethed.str2hex(assetIssueId1), orders.getString("buy_token_id")); - Assert.assertTrue(20L == orders.getLong("buy_token_quantity")); - Assert.assertEquals(getMarketOrderListByPairContentFromPbft.getLong("sell_token_quantity"), - getMarketOrderListByPairContentFromPbft.getLong("sell_token_quantity_remain")); - - Assert - .assertTrue(getMarketOrderListByPairContentFromPbft.getJSONArray("orders").size() > 0); - Assert - .assertEquals(getMarketOrderListByPairContent, getMarketOrderListByPairContentFromPbft); - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketPriceByPair from by http") - public void test14GetMarketPriceByPair() { - response = HttpMethed.getMarketPriceByPair(httpnode, "_", assetIssueId1, "false"); - getMarketPriceByPairContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketPriceByPairContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - Assert.assertEquals("5f", getMarketPriceByPairContent.getString("sell_token_id")); - Assert.assertEquals(HttpMethed.str2hex(assetIssueId1), - getMarketPriceByPairContent.getString("buy_token_id")); - JSONObject prices = getMarketPriceByPairContent.getJSONArray("prices").getJSONObject(0); - Assert.assertEquals("50", prices.getString("sell_token_quantity")); - Assert.assertEquals("1", prices.getString("buy_token_quantity")); - Assert.assertTrue(getMarketPriceByPairContent.getJSONArray("prices").size() > 0); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketPriceByPair from by http from solidity") - public void test15GetMarketPriceByPairFromSolidity() { - response = HttpMethed - .getMarketPriceByPairFromSolidity(httpSolidityNode, "_", assetIssueId1, "false"); - getMarketPriceByPairContentFromSolidity = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketPriceByPairContentFromSolidity); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - Assert.assertEquals("5f", getMarketPriceByPairContentFromSolidity.getString("sell_token_id")); - Assert - .assertEquals(HttpMethed.str2hex(assetIssueId1), - getMarketPriceByPairContentFromSolidity.getString("buy_token_id")); - JSONObject prices = getMarketPriceByPairContentFromSolidity.getJSONArray("prices") - .getJSONObject(0); - Assert.assertEquals("50", prices.getString("sell_token_quantity")); - Assert.assertEquals("1", prices.getString("buy_token_quantity")); - Assert.assertTrue(getMarketPriceByPairContentFromSolidity.getJSONArray("prices").size() > 0); - Assert.assertEquals(getMarketPriceByPairContent, getMarketPriceByPairContentFromSolidity); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetMarketPriceByPair from by http from pbft") - public void test16GetMarketPriceByPairFromPbft() { - response = HttpMethed - .getMarketPriceByPairFromPbft(httpPbftNode, "_", assetIssueId1, "false"); - getMarketPriceByPairContentFromPbft = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketPriceByPairContentFromPbft); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - Assert.assertEquals("5f", getMarketPriceByPairContentFromPbft.getString("sell_token_id")); - Assert - .assertEquals(HttpMethed.str2hex(assetIssueId1), - getMarketPriceByPairContentFromPbft.getString("buy_token_id")); - JSONObject prices = getMarketPriceByPairContentFromPbft.getJSONArray("prices") - .getJSONObject(0); - Assert.assertEquals("50", prices.getString("sell_token_quantity")); - Assert.assertEquals("1", prices.getString("buy_token_quantity")); - Assert.assertTrue(getMarketPriceByPairContentFromPbft.getJSONArray("prices").size() > 0); - Assert.assertEquals(getMarketPriceByPairContent, getMarketPriceByPairContentFromPbft); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "MarketCancelOrder trx with trc10 by http") - public void test17MarketCancelOrder() { - response = HttpMethed.getMarketOrderByAccount(httpnode, sellAddress, "false"); - getMarketOrderByAccountContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderByAccountContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - Assert.assertEquals(2, getMarketOrderByAccountContent.getJSONArray("orders").size()); - - // MarketCancelOrder - String txId = HttpMethed.marketCancelOrder(httpnode, sellAddress, orderId1, sellKey, "false"); - HttpMethed.waitToProduceOneBlock(httpnode); - logger.info(txId); - response = HttpMethed.getTransactionInfoById(httpnode, txId); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - - response = HttpMethed.getMarketOrderByAccount(httpnode, sellAddress, "false"); - getMarketOrderByAccountContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(getMarketOrderByAccountContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - Assert.assertEquals(1, getMarketOrderByAccountContent.getJSONArray("orders").size()); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.freedResource(httpnode, sellAddress, fromAddress, sellKey); - HttpMethed.disConnect(); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMortgageMechanism01.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMortgageMechanism01.java deleted file mode 100644 index d41e49ead51..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMortgageMechanism01.java +++ /dev/null @@ -1,214 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import java.math.BigInteger; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestMortgageMechanism01 { - - private static final long now = System.currentTimeMillis(); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress = PublicMethed.getFinalAddress(witnessKey); - private final String witnessKey2 = Configuration.getByPath("testng.conf") - .getString("witness.key2"); - private final byte[] witnessAddress2 = PublicMethed.getFinalAddress(witnessKey2); - Long amount = 2048000000L; - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf").getString("defaultParameter.assetUrl"); - private JSONObject responseContent; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(1); - private String httpSoliditynode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String httpPbftNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(4); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - /** - * constructor. - */ - @Test(enabled = true, description = "GetBrokerage by http") - public void test01GetBrokerage() { - response = HttpMethed.getBrokerage(httpnode, witnessAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals("20", responseContent.getString("brokerage")); - - response = HttpMethed.getBrokerageOnVisible(httpnode, witnessAddress2, "true"); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals("20", responseContent.getString("brokerage")); - - response = HttpMethed.getBrokerageOnVisible(httpnode, fromAddress, "false"); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals("20", responseContent.getString("brokerage")); - } - - @Test(enabled = true, description = "GetBrokerage from solidity by http") - public void test02GetBrokerageFromSolidity() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - response = HttpMethed.getBrokerageFromSolidity(httpSoliditynode, witnessAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals("20", responseContent.getString("brokerage")); - - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - response = HttpMethed - .getBrokerageFromSolidityOnVisible(httpSoliditynode, witnessAddress2, "true"); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals("20", responseContent.getString("brokerage")); - - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - response = HttpMethed.getBrokerageFromSolidityOnVisible(httpSoliditynode, fromAddress, "false"); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals("20", responseContent.getString("brokerage")); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetBrokerage from PBFT by http") - public void test03GetBrokerageFromPbft() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - response = HttpMethed.getBrokerageFromPbft(httpPbftNode, witnessAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals("20", responseContent.getString("brokerage")); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "UpdateBrokerage by http") - public void test04UpdateBrokerage() { - response = HttpMethed.sendCoin(httpnode, fromAddress, witnessAddress, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - //update brokerage - response = HttpMethed.updateBrokerage(httpnode, witnessAddress, 11L, witnessKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed.sendCoin(httpnode, fromAddress, witnessAddress2, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - //update brokerage onvisible true - response = HttpMethed - .updateBrokerageOnVisible(httpnode, witnessAddress2, 24L, witnessKey2, "true"); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - //update brokerage onvisible false - response = HttpMethed - .updateBrokerageOnVisible(httpnode, witnessAddress, 88L, witnessKey, "false"); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - //update brokerage onvisible false for notwitness - response = HttpMethed.sendCoin(httpnode, fromAddress, dev001Address, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed.updateBrokerageOnVisible(httpnode, dev001Address, 78L, dev001Key, "true"); - Assert.assertFalse(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetReward by http") - public void test05GetReward() { - response = HttpMethed.getReward(httpnode, witnessAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue( - (new BigInteger(responseContent.getString("reward")).compareTo(new BigInteger("0"))) == 1); - - response = HttpMethed.getRewardOnVisible(httpnode, witnessAddress2, "true"); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue( - (new BigInteger(responseContent.getString("reward")).compareTo(new BigInteger("0"))) == 1); - - response = HttpMethed.getRewardOnVisible(httpnode, witnessAddress, "false"); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue( - (new BigInteger(responseContent.getString("reward")).compareTo(new BigInteger("0"))) == 1); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetReward from solidity by http") - public void test06GetRewardFromSolidity() { - response = HttpMethed.getRewardFromSolidity(httpSoliditynode, witnessAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue( - (new BigInteger(responseContent.getString("reward")).compareTo(new BigInteger("0"))) == 1); - - response = HttpMethed.getRewardFromSolidityOnVisible(httpSoliditynode, witnessAddress, "true"); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue( - (new BigInteger(responseContent.getString("reward")).compareTo(new BigInteger("0"))) == 1); - - response = HttpMethed.getRewardFromSolidityOnVisible(httpSoliditynode, witnessAddress, "false"); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue( - (new BigInteger(responseContent.getString("reward")).compareTo(new BigInteger("0"))) == 1); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetReward from PBFT by http") - public void test07GetRewardFromPbft() { - response = HttpMethed.getRewardFromPbft(httpPbftNode, witnessAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue( - (new BigInteger(responseContent.getString("reward")).compareTo(new BigInteger("0")) == 0) - || (new BigInteger(responseContent.getString("reward")).compareTo(new BigInteger("0"))) - == 1); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - //update brokerage - HttpMethed.freedResource(httpnode, witnessAddress, fromAddress, witnessKey); - HttpMethed.disConnect(); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMutiSign001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMutiSign001.java deleted file mode 100644 index fe3c2a832d9..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMutiSign001.java +++ /dev/null @@ -1,224 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class HttpTestMutiSign001 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String manager1Key = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] manager1Address = PublicMethed.getFinalAddress(manager1Key); - private final String manager2Key = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] manager2Address = PublicMethed.getFinalAddress(manager2Key); - private final String manager3Key = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] manager3Address = PublicMethed.getFinalAddress(manager3Key); - private final String manager4Key = Configuration.getByPath("testng.conf") - .getString("witness.key2"); - private final byte[] manager4Address = PublicMethed.getFinalAddress(manager4Key); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey1.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] hexTestAddress = ecKey2.getAddress(); - String hexTestKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - String[] permissionKeyString; - Long amount = 1000000000L; - JsonArray keys = new JsonArray(); - JsonArray activeKeys = new JsonArray(); - JsonObject manager1Wight = new JsonObject(); - JsonObject manager2Wight = new JsonObject(); - JsonObject manager3Wight = new JsonObject(); - JsonObject manager4Wight = new JsonObject(); - JsonObject ownerObject = new JsonObject(); - JsonObject witnessObject = new JsonObject(); - JsonObject activeObject = new JsonObject(); - private JSONObject responseContent; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(1); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Account Permission Up Date by http") - public void test1AccountPermissionUpDate() { - PublicMethed.printAddress(ownerKey); - response = HttpMethed.sendCoin(httpnode, fromAddress, ownerAddress, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - manager1Wight.addProperty("address", ByteArray.toHexString(manager1Address)); - manager1Wight.addProperty("weight", 1); - - logger.info(manager1Wight.toString()); - manager2Wight.addProperty("address", ByteArray.toHexString(manager2Address)); - manager2Wight.addProperty("weight", 1); - - logger.info(manager2Wight.toString()); - - keys.add(manager1Wight); - keys.add(manager2Wight); - - ownerObject.addProperty("type", 0); - ownerObject.addProperty("permission_name", "owner"); - ownerObject.addProperty("threshold", 2); - ownerObject.add("keys", keys); - - manager3Wight.addProperty("address", ByteArray.toHexString(manager3Address)); - manager3Wight.addProperty("weight", 1); - - logger.info(manager3Wight.toString()); - manager4Wight.addProperty("address", ByteArray.toHexString(manager4Address)); - manager4Wight.addProperty("weight", 1); - - logger.info(manager4Wight.toString()); - - activeKeys.add(manager3Wight); - activeKeys.add(manager4Wight); - - activeObject.addProperty("type", 2); - activeObject.addProperty("permission_name", "active0"); - activeObject.addProperty("threshold", 2); - activeObject.addProperty("operations", - "7fff1fc0037e0000000000000000000000000000000000000000000000000000"); - activeObject.add("keys", activeKeys); - - response = HttpMethed - .accountPermissionUpdate(httpnode, ownerAddress, ownerObject, witnessObject, activeObject, - ownerKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Add transaction sign by http with permission id") - public void test2AddTransactionSign() { - - HttpMethed.waitToProduceOneBlock(httpnode); - permissionKeyString = new String[2]; - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - - String[] permissionKeyActive = new String[2]; - permissionKeyActive[0] = manager3Key; - permissionKeyActive[1] = manager4Key; - - response = HttpMethed - .sendCoin(httpnode, ownerAddress, fromAddress, 10L, 0, permissionKeyString); - Assert.assertTrue(HttpMethed.verificationResult(response)); - - response = HttpMethed - .sendCoin(httpnode, ownerAddress, fromAddress, 10L, 2, permissionKeyString); - Assert.assertFalse(HttpMethed.verificationResult(response)); - - logger.info("start permission id 2"); - response = HttpMethed - .sendCoin(httpnode, ownerAddress, fromAddress, 12L, 2, permissionKeyActive); - Assert.assertTrue(HttpMethed.verificationResult(response)); - - response = HttpMethed - .sendCoin(httpnode, ownerAddress, fromAddress, 12L, 0, permissionKeyActive); - Assert.assertFalse(HttpMethed.verificationResult(response)); - - response = HttpMethed - .sendCoin(httpnode, ownerAddress, fromAddress, 11L, 1, permissionKeyActive); - Assert.assertFalse(HttpMethed.verificationResult(response)); - - response = HttpMethed - .sendCoin(httpnode, ownerAddress, fromAddress, 11L, 3, permissionKeyString); - Assert.assertFalse(HttpMethed.verificationResult(response)); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Add broadcasthex http interface to " - + "broadcast hex transaction string") - public void test3Broadcasthex() { - PublicMethed.printAddress(hexTestKey); - String transactionHex = PublicMethed - .sendcoinGetTransactionHex(hexTestAddress, 1000L, fromAddress, testKey002, - blockingStubFull); - - //Wrong type of hex - response = HttpMethed.broadcasthex(httpnode, transactionHex); - Assert.assertTrue(HttpMethed.verificationResult(response)); - - String wrongTransactionHex = transactionHex + "wrong"; - response = HttpMethed.broadcasthex(httpnode, wrongTransactionHex); - logger.info("transaction wrong:"); - Assert.assertFalse(HttpMethed.verificationResult(response)); - - //SingleSign for broadcastHex - response = HttpMethed.broadcasthex(httpnode, transactionHex); - Assert.assertFalse(HttpMethed.verificationResult(response)); - - //Mutisign for broadcastHex - String mutiSignTransactionHex = PublicMethedForMutiSign - .sendcoinGetTransactionHex(hexTestAddress, 999L, ownerAddress, ownerKey, blockingStubFull, - permissionKeyString); - response = HttpMethed.broadcasthex(httpnode, mutiSignTransactionHex); - Assert.assertTrue(HttpMethed.verificationResult(response)); - - //Hex is null - response = HttpMethed.broadcasthex(httpnode, ""); - Assert.assertFalse(HttpMethed.verificationResult(response)); - - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.disConnect(); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestProposal001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestProposal001.java deleted file mode 100644 index 8fdaa8ddaa3..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestProposal001.java +++ /dev/null @@ -1,144 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import org.tron.common.utils.ByteArray; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestProposal001 { - - private static Integer proposalId; - private final String testKey002 = - Configuration.getByPath("testng.conf").getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = - Configuration.getByPath("testng.conf").getString("witness.key1"); - private final byte[] witness1Address = PublicMethed.getFinalAddress(witnessKey001); - private final String witnessKey002 = - Configuration.getByPath("testng.conf").getString("witness.key2"); - private final byte[] witness2Address = PublicMethed.getFinalAddress(witnessKey002); - private String httpnode = - Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list").get(0); - private JSONObject responseContent; - private HttpResponse response; - - /** constructor. */ - @Test(enabled = true, description = "Create proposal by http") - public void test1CreateProposal() { - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.createProposal(httpnode, witness1Address, 21L, 1L, witnessKey001); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - } - - /** * constructor. * */ - @Test(enabled = true, description = "List proposals by http") - public void test2ListProposals() { - response = HttpMethed.listProposals(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = JSONArray.parseArray(responseContent.getString("proposals")); - Assert.assertTrue(jsonArray.size() >= 1); - proposalId = jsonArray.size(); - } - - /** constructor. */ - @Test(enabled = true, description = "GetProposalById by http") - public void test3GetExchangeById() { - response = HttpMethed.getProposalById(httpnode, proposalId); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getInteger("proposal_id") == proposalId); - Assert.assertEquals( - responseContent.getString("proposer_address"), ByteArray.toHexString(witness1Address)); - } - - /** constructor. */ - @Test(enabled = true, description = "Approval proposal by http") - public void test4ApprovalProposal() { - response = - HttpMethed.approvalProposal(httpnode, witness1Address, proposalId, true, witnessKey001); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = - HttpMethed.approvalProposal(httpnode, witness2Address, proposalId, true, witnessKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getProposalById(httpnode, proposalId); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = JSONArray.parseArray(responseContent.getString("approvals")); - Assert.assertTrue(jsonArray.size() == 2); - } - - /** * constructor. * */ - @Test(enabled = true, description = "Get paginated proposal list by http") - public void test5GetPaginatedProposalList() { - - response = HttpMethed.getPaginatedProposalList(httpnode, 0, 1); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - - JSONArray jsonArray = JSONArray.parseArray(responseContent.getString("proposals")); - Assert.assertTrue(jsonArray.size() == 1); - } - - /** constructor. */ - @Test(enabled = true, description = "Delete proposal by http") - public void test6DeleteProposal() { - response = HttpMethed.deleteProposal(httpnode, witness1Address, proposalId, witnessKey001); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getProposalById(httpnode, proposalId); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(responseContent.getString("state"), "CANCELED"); - } - - /** constructor. */ - @Test(enabled = true, description = "Get chain parameters by http") - public void test7GetChainParameters() { - response = HttpMethed.getChainParameters(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals( - "getMaintenanceTimeInterval", - responseContent.getJSONArray("chainParameter").getJSONObject(0).get("key")); - Assert.assertEquals( - 300000, responseContent.getJSONArray("chainParameter").getJSONObject(0).get("value")); - Assert.assertEquals( - "getCreateAccountFee", - responseContent.getJSONArray("chainParameter").getJSONObject(2).get("key")); - Assert.assertEquals( - 100000, responseContent.getJSONArray("chainParameter").getJSONObject(2).get("value")); - } - /** constructor. */ - - @Test(enabled = true, description = "Get energy price by http") - public void test8GetEnergyPrice() { - response = HttpMethed.getEnergyPric(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - String prices = responseContent.getString("prices"); - String expectPrices = "0:100"; - logger.info("prices:" + prices); - Assert.assertEquals(prices, expectPrices); - } - - /** constructor. */ - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.disConnect(); - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestSendCoin001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestSendCoin001.java deleted file mode 100644 index 5741bcc6d65..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestSendCoin001.java +++ /dev/null @@ -1,164 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestSendCoin001 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] receiverAddress = ecKey1.getAddress(); - String receiverKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Long amount = 1000L; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(1); - private String httpSoliditynode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String httpPbftNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(4); - private JSONObject responseContent; - private HttpResponse response; - - /** - * constructor. - */ - @Test(enabled = true, description = "SendCoin by http") - public void test1SendCoin() { - response = HttpMethed.sendCoin(httpnode, fromAddress, receiverAddress, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - Assert.assertEquals(HttpMethed.getBalance(httpnode, receiverAddress), amount); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get transaction by id from solidity by http") - public void test2GetTransactionByIdFromSolidity() { - String txid = HttpMethed - .sendCoinGetTxid(httpnode, fromAddress, receiverAddress, amount, testKey002); - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - - response = HttpMethed.getTransactionByIdFromSolidity(httpSoliditynode, txid); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - String retString = responseContent.getString("ret"); - JSONArray array = JSONArray.parseArray(retString); - Assert.assertEquals( - HttpMethed.parseStringContent(array.get(0).toString()).getString("contractRet"), "SUCCESS"); - Assert.assertTrue(responseContent.size() > 4); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get transaction by id from PBFT by http") - public void test3GetTransactionByIdFromPbft() { - String txid = HttpMethed - .sendCoinGetTxid(httpnode, fromAddress, receiverAddress, amount, testKey002); - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - - response = HttpMethed.getTransactionByIdFromPbft(httpPbftNode, txid); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - String retString = responseContent.getString("ret"); - JSONArray array = JSONArray.parseArray(retString); - Assert.assertEquals( - HttpMethed.parseStringContent(array.get(0).toString()).getString("contractRet"), "SUCCESS"); - Assert.assertTrue(responseContent.size() > 4); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "Get transaction info by id from solidity by http") - public void test4GetTransactionInfoByIdFromSolidity() { - String txid = HttpMethed - .sendCoinGetTxid(httpnode, fromAddress, receiverAddress, amount, testKey002); - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - response = HttpMethed.getTransactionInfoByIdFromSolidity(httpSoliditynode, txid); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.size() > 4); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get transaction info by id from PBFT by http") - public void test5GetTransactionInfoByIdFromPbft() { - String txid = HttpMethed - .sendCoinGetTxid(httpnode, fromAddress, receiverAddress, amount, testKey002); - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSoliditynode); - response = HttpMethed.getTransactionInfoByIdFromPbft(httpPbftNode, txid); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.size() > 4); - } - - - /** - * constructor. - */ - @Test(enabled = false, description = "Get transactions from this from solidity by http") - public void test4GetTransactionsFromThisFromSolidity() { - response = HttpMethed - .getTransactionsFromThisFromSolidity(httpSoliditynode, fromAddress, 0, 100); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONObject transactionObject = HttpMethed.parseStringContent( - JSONArray.parseArray(responseContent.getString("transaction")).get(0).toString()); - String retString = transactionObject.getString("ret"); - JSONArray array = JSONArray.parseArray(retString); - Assert.assertEquals( - HttpMethed.parseStringContent(array.get(0).toString()).getString("contractRet"), "SUCCESS"); - Assert.assertTrue(responseContent.size() == 1); - } - - /** - * constructor. - */ - @Test(enabled = false, description = "Get transactions to this from solidity by http") - public void test5GetTransactionsToThisFromSolidity() { - response = HttpMethed - .getTransactionsFromThisFromSolidity(httpSoliditynode, fromAddress, 0, 100); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONObject transactionObject = HttpMethed.parseStringContent( - JSONArray.parseArray(responseContent.getString("transaction")).get(0).toString()); - String retString = transactionObject.getString("ret"); - JSONArray array = JSONArray.parseArray(retString); - Assert.assertEquals( - HttpMethed.parseStringContent(array.get(0).toString()).getString("contractRet"), "SUCCESS"); - Assert.assertTrue(responseContent.size() == 1); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.freedResource(httpnode, receiverAddress, fromAddress, receiverKey); - HttpMethed.disConnect(); - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestSmartContract001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestSmartContract001.java deleted file mode 100644 index 8f1d7c17ee7..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestSmartContract001.java +++ /dev/null @@ -1,373 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import java.util.List; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestSmartContract001 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "testAssetIssue002_" + now; - private static String assetIssueId; - private static String contractName; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] assetOwnerAddress = ecKey2.getAddress(); - String assetOwnerKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] assetReceiverAddress = ecKey3.getAddress(); - String assetReceiverKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - String contractAddress; - Long amount = 2048000000L; - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf").getString("defaultParameter.assetUrl"); - private JSONObject responseContent; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(0); - private String httpSolidityNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String httpRealSolidityNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(3); - - /** - * constructor. - */ - @Test(enabled = true, description = "Deploy smart contract by http") - public void test1DeployContract() { - PublicMethed.printAddress(assetOwnerKey); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.sendCoin(httpnode, fromAddress, assetOwnerAddress, amount, testKey002); - response = HttpMethed.sendCoin(httpnode, fromAddress, assetReceiverAddress, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - //Create an asset issue - response = HttpMethed - .freezeBalance(httpnode, assetOwnerAddress, 100000000L, 3, 1, assetOwnerKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - response = HttpMethed.assetIssue(httpnode, assetOwnerAddress, name, name, totalSupply, 1, 1, - System.currentTimeMillis() + 5000, System.currentTimeMillis() + 50000000, 2, 3, description, - url, 1000L, 1000L, assetOwnerKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed.getAccount(httpnode, assetOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - assetIssueId = responseContent.getString("asset_issued_ID"); - - contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken001_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken001_transferTokenContract"); - - long tokenValue = 100000; - long callValue = 5000; - - //This deploy is test too large call_token_value will made the witness node cpu 100% - /*response = HttpMethed.deployContractGetTxidWithTooBigLong(httpnode, - contractName, abi, code, 1000000L,1000000000L, 100, 11111111111111L, - callValue, Integer.parseInt(assetIssueId), tokenValue, assetOwnerAddress, assetOwnerKey); - responseContent = HttpMethed.parseResponseContent(response); - Assert.assertTrue(responseContent.getString("Error").contains("Overflow"));*/ - - String txid = HttpMethed - .deployContractGetTxid(httpnode, contractName, abi, code, 1000000L, 1000000000L, 100, - 11111111111111L, callValue, Integer.parseInt(assetIssueId), tokenValue, - assetOwnerAddress, assetOwnerKey); - - HttpMethed.waitToProduceOneBlock(httpnode); - logger.info(txid); - response = HttpMethed.getTransactionById(httpnode, txid); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(!responseContent.getString("contract_address").isEmpty()); - contractAddress = responseContent.getString("contract_address"); - - response = HttpMethed.getTransactionInfoById(httpnode, txid); - responseContent = HttpMethed.parseResponseContent(response); - String receiptString = responseContent.getString("receipt"); - Assert - .assertEquals(HttpMethed.parseStringContent(receiptString).getString("result"), "SUCCESS"); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get contract by http") - public void test2GetContract() { - response = HttpMethed.getContract(httpnode, contractAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(responseContent.getString("consume_user_resource_percent"), "100"); - Assert.assertEquals(responseContent.getString("contract_address"), contractAddress); - Assert.assertEquals(responseContent.getString("origin_address"), - ByteArray.toHexString(assetOwnerAddress)); - Assert.assertEquals(responseContent.getString("call_value"), "5000"); - Assert.assertEquals(responseContent.getString("origin_energy_limit"), "11111111111111"); - Assert.assertEquals(responseContent.getString("name"), contractName); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Trigger contract by http") - public void test3TriggerContract() { - - String hexReceiverAddress = ByteArray.toHexString(assetReceiverAddress); - String addressParam = "000000000000000000000000" + hexReceiverAddress.substring(2);//[0,3) - - String tokenIdParam = "00000000000000000000000000000000000000000000000000000000000" + Integer - .toHexString(Integer.parseInt(assetIssueId)); - - String tokenValueParam = "0000000000000000000000000000000000000000000000000000000000000001"; - logger.info(addressParam); - logger.info(tokenIdParam); - logger.info(tokenValueParam); - final Long beforeBalance = HttpMethed.getBalance(httpnode, assetOwnerAddress); - String param = addressParam + tokenIdParam + tokenValueParam; - Long callValue = 10L; - String txid = HttpMethed.triggerContractGetTxid(httpnode, assetOwnerAddress, contractAddress, - "TransferTokenTo(address,trcToken,uint256)", param, 1000000000L, callValue, - Integer.parseInt(assetIssueId), 20L, assetOwnerKey); - - HttpMethed.waitToProduceOneBlock(httpnode); - //String txid = "49a30653d6e648da1e9a104b051b1b55c185fcaa0c2885405ae1d2fb258e3b3c"; - logger.info(txid); - response = HttpMethed.getTransactionById(httpnode, txid); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(txid, responseContent.getString("txID")); - Assert.assertTrue(!responseContent.getString("raw_data").isEmpty()); - Assert.assertTrue(!responseContent.getString("raw_data_hex").isEmpty()); - Long afterBalance = HttpMethed.getBalance(httpnode, assetOwnerAddress); - logger.info("beforeBalance: " + beforeBalance); - logger.info("afterBalance: " + afterBalance); - Assert.assertTrue(beforeBalance - afterBalance == callValue); - - response = HttpMethed.getTransactionInfoById(httpnode, txid); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - String receiptString = responseContent.getString("receipt"); - Assert - .assertEquals(HttpMethed.parseStringContent(receiptString).getString("result"), "SUCCESS"); - Assert.assertTrue(HttpMethed.parseStringContent(receiptString).getLong("energy_usage") > 0); - Assert.assertTrue(responseContent.getLong("blockNumber") > 0); - - response = HttpMethed.getAccount(httpnode, assetReceiverAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(!responseContent.getString("assetV2").isEmpty()); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get transaction info by http") - public void test4GetTransactionInfoByBlocknum() { - String hexReceiverAddress = ByteArray.toHexString(assetReceiverAddress); - String addressParam = "000000000000000000000000" + hexReceiverAddress.substring(2);//[0,3) - String tokenIdParam = "00000000000000000000000000000000000000000000000000000000000" + Integer - .toHexString(Integer.parseInt(assetIssueId)); - String tokenValueParam = "0000000000000000000000000000000000000000000000000000000000000001"; - String param = addressParam + tokenIdParam + tokenValueParam; - Long callValue = 10L; - String txid1 = HttpMethed.triggerContractGetTxid(httpnode, assetOwnerAddress, contractAddress, - "TransferTokenTo(address,trcToken,uint256)", param, 1000000000L, callValue, - Integer.parseInt(assetIssueId), 20L, assetOwnerKey); - String txid2 = HttpMethed.triggerContractGetTxid(httpnode, assetOwnerAddress, contractAddress, - "TransferTokenTo(address,trcToken,uint256)", param, 1000000000L, callValue, - Integer.parseInt(assetIssueId), 20L, assetOwnerKey); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getTransactionInfoById(httpnode, txid1); - HttpResponse response2 = HttpMethed.getTransactionInfoById(httpnode, txid2); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONObject responseContent2 = HttpMethed.parseResponseContent(response2); - HttpMethed.printJsonContent(responseContent2); - if (responseContent.getLong("blockNumber").equals(responseContent2.getLong("blockNumber"))) { - HttpResponse responseByBlocknum = HttpMethed - .getTransactionInfoByBlocknum(httpnode, responseContent.getLong("blockNumber")); - List responseContentByBlocknum = HttpMethed - .parseResponseContentArray(responseByBlocknum); - Assert.assertEquals(2, responseContentByBlocknum.size()); - HttpMethed.printJsonContent(responseContentByBlocknum.get(0)); - HttpMethed.printJsonContent(responseContentByBlocknum.get(1)); - if (responseContent.getString("id") - .equals(responseContentByBlocknum.get(0).getString("id"))) { - Assert.assertEquals(responseContent, responseContentByBlocknum.get(0)); - Assert.assertEquals(responseContent2, responseContentByBlocknum.get(1)); - } else { - Assert.assertEquals(responseContent, responseContentByBlocknum.get(1)); - Assert.assertEquals(responseContent2, responseContentByBlocknum.get(0)); - } - } - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get transaction info by http from solidity") - public void test5GetTransactionInfoByBlocknumFromSolidity() { - String hexReceiverAddress = ByteArray.toHexString(assetReceiverAddress); - String addressParam = "000000000000000000000000" + hexReceiverAddress.substring(2);//[0,3) - String tokenIdParam = "00000000000000000000000000000000000000000000000000000000000" + Integer - .toHexString(Integer.parseInt(assetIssueId)); - String tokenValueParam = "0000000000000000000000000000000000000000000000000000000000000001"; - String param = addressParam + tokenIdParam + tokenValueParam; - Long callValue = 10L; - String txid1 = HttpMethed.triggerContractGetTxid(httpnode, assetOwnerAddress, contractAddress, - "TransferTokenTo(address,trcToken,uint256)", param, 1000000000L, callValue, - Integer.parseInt(assetIssueId), 20L, assetOwnerKey); - String txid2 = HttpMethed.triggerContractGetTxid(httpnode, assetOwnerAddress, contractAddress, - "TransferTokenTo(address,trcToken,uint256)", param, 1000000000L, callValue, - Integer.parseInt(assetIssueId), 20L, assetOwnerKey); - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSolidityNode); - response = HttpMethed.getTransactionInfoById(httpnode, txid1); - HttpResponse response2 = HttpMethed.getTransactionInfoById(httpnode, txid2); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONObject responseContent2 = HttpMethed.parseResponseContent(response2); - HttpMethed.printJsonContent(responseContent2); - if (responseContent.getLong("blockNumber").equals(responseContent2.getLong("blockNumber"))) { - HttpResponse responseByBlocknum = HttpMethed - .getTransactionInfoByBlocknumFromSolidity(httpSolidityNode, - responseContent.getLong("blockNumber")); - List responseContentByBlocknum = HttpMethed - .parseResponseContentArray(responseByBlocknum); - Assert.assertEquals(2, responseContentByBlocknum.size()); - HttpMethed.printJsonContent(responseContentByBlocknum.get(0)); - HttpMethed.printJsonContent(responseContentByBlocknum.get(1)); - if (responseContent.getString("id") - .equals(responseContentByBlocknum.get(0).getString("id"))) { - Assert.assertEquals(responseContent, responseContentByBlocknum.get(0)); - Assert.assertEquals(responseContent2, responseContentByBlocknum.get(1)); - } else { - Assert.assertEquals(responseContent, responseContentByBlocknum.get(1)); - Assert.assertEquals(responseContent2, responseContentByBlocknum.get(0)); - } - } - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get transaction info by http from real solidity") - public void test6GetTransactionInfoByBlocknumFromRealSolidity() { - String hexReceiverAddress = ByteArray.toHexString(assetReceiverAddress); - String addressParam = "000000000000000000000000" + hexReceiverAddress.substring(2);//[0,3) - String tokenIdParam = "00000000000000000000000000000000000000000000000000000000000" + Integer - .toHexString(Integer.parseInt(assetIssueId)); - String tokenValueParam = "0000000000000000000000000000000000000000000000000000000000000001"; - String param = addressParam + tokenIdParam + tokenValueParam; - Long callValue = 10L; - String txid1 = HttpMethed.triggerContractGetTxid(httpnode, assetOwnerAddress, contractAddress, - "TransferTokenTo(address,trcToken,uint256)", param, 1000000000L, callValue, - Integer.parseInt(assetIssueId), 20L, assetOwnerKey); - String txid2 = HttpMethed.triggerContractGetTxid(httpnode, assetOwnerAddress, contractAddress, - "TransferTokenTo(address,trcToken,uint256)", param, 1000000000L, callValue, - Integer.parseInt(assetIssueId), 20L, assetOwnerKey); - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpRealSolidityNode); - response = HttpMethed.getTransactionInfoById(httpnode, txid1); - HttpResponse response2 = HttpMethed.getTransactionInfoById(httpnode, txid2); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONObject responseContent2 = HttpMethed.parseResponseContent(response2); - HttpMethed.printJsonContent(responseContent2); - if (responseContent.getLong("blockNumber").equals(responseContent2.getLong("blockNumber"))) { - HttpResponse responseByBlocknum = HttpMethed - .getTransactionInfoByBlocknumFromSolidity(httpRealSolidityNode, - responseContent.getLong("blockNumber")); - List responseContentByBlocknum = HttpMethed - .parseResponseContentArray(responseByBlocknum); - Assert.assertEquals(2, responseContentByBlocknum.size()); - HttpMethed.printJsonContent(responseContentByBlocknum.get(0)); - HttpMethed.printJsonContent(responseContentByBlocknum.get(1)); - if (responseContent.getString("id") - .equals(responseContentByBlocknum.get(0).getString("id"))) { - Assert.assertEquals(responseContent, responseContentByBlocknum.get(0)); - Assert.assertEquals(responseContent2, responseContentByBlocknum.get(1)); - } else { - Assert.assertEquals(responseContent, responseContentByBlocknum.get(1)); - Assert.assertEquals(responseContent2, responseContentByBlocknum.get(0)); - } - } - } - - /** - * constructor. - */ - @Test(enabled = true, description = "UpdateSetting contract by http") - public void test7UpdateSetting() { - - //assetOwnerAddress, assetOwnerKey - response = HttpMethed - .updateSetting(httpnode, assetOwnerAddress, contractAddress, 75, assetOwnerKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - response = HttpMethed.getContract(httpnode, contractAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(responseContent.getString("consume_user_resource_percent"), "75"); - Assert.assertEquals(responseContent.getString("contract_address"), contractAddress); - Assert.assertEquals(responseContent.getString("origin_address"), - ByteArray.toHexString(assetOwnerAddress)); - Assert.assertEquals(responseContent.getString("call_value"), "5000"); - Assert.assertEquals(responseContent.getString("origin_energy_limit"), "11111111111111"); - Assert.assertEquals(responseContent.getString("name"), contractName); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "UpdateEnergyLimit contract by http") - public void test8UpdateEnergyLimit() { - - //assetOwnerAddress, assetOwnerKey - response = HttpMethed - .updateEnergyLimit(httpnode, assetOwnerAddress, contractAddress, 1234567, assetOwnerKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - response = HttpMethed.getContract(httpnode, contractAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertEquals(responseContent.getString("consume_user_resource_percent"), "75"); - Assert.assertEquals(responseContent.getString("contract_address"), contractAddress); - Assert.assertEquals(responseContent.getString("origin_address"), - ByteArray.toHexString(assetOwnerAddress)); - Assert.assertEquals(responseContent.getString("call_value"), "5000"); - Assert.assertEquals(responseContent.getString("origin_energy_limit"), "1234567"); - Assert.assertEquals(responseContent.getString("name"), contractName); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.freedResource(httpnode, assetOwnerAddress, fromAddress, assetOwnerKey); - HttpMethed.freedResource(httpnode, assetReceiverAddress, fromAddress, assetReceiverKey); - HttpMethed.disConnect(); - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestTransactionPending001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestTransactionPending001.java deleted file mode 100644 index 58c09f1836d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestTransactionPending001.java +++ /dev/null @@ -1,100 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestTransactionPending001 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private JSONObject responseContent; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(0); - private String httpSoliditynode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String httpPbftNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(4); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] receiverAddress = ecKey1.getAddress(); - String receiverKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - String txid; - JSONObject transaction; - - /** - * constructor. - */ - @Test(enabled = true, description = "Get transaction pending size by http") - public void test01GetTransactionPendingSize() { - int pendingSize = 0; - int retryTimes = 50; - - while (pendingSize == 0 && retryTimes-- > 0) { - HttpMethed.sendCoin(httpnode,fromAddress,receiverAddress,1L,testKey002); - if (retryTimes % 5 == 0) { - pendingSize = HttpMethed.getTransactionPendingSize(httpnode); - } - } - - Assert.assertNotEquals(pendingSize,0); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get pending transaction list by http") - public void test02GetPendingTransactionList() { - int transactionSize = 0; - int retryTimes = 50; - - while (transactionSize == 0 && retryTimes-- > 0) { - HttpMethed.sendCoin(httpnode,fromAddress,receiverAddress,1L,testKey002); - if (retryTimes % 5 == 0) { - response = HttpMethed.getTransactionListFromPending(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - transactionSize = responseContent.getJSONArray("txId").size(); - } - } - Assert.assertNotEquals(transactionSize,0); - - txid = responseContent.getJSONArray("txId").getString(0); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "Get transaction from pending by http") - public void test03GetPendingTransactionList() { - response = HttpMethed.getTransactionFromPending(httpnode,txid); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - Assert.assertEquals(txid,responseContent.getString("txID")); - Assert.assertNotEquals(null,responseContent); - } - - - - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.disConnect(); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken001.java deleted file mode 100644 index bb070512fe7..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken001.java +++ /dev/null @@ -1,382 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.Note; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.config.args.Args; -import org.tron.core.zen.address.DiversifierT; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; -import stest.tron.wallet.common.client.utils.ShieldNoteInfo; - -@Slf4j -public class HttpTestZenToken001 { - - List shieldOutList = new ArrayList<>(); - Optional shieldAddressOptionalInfo1; - Optional shieldAddressOptionalInfo2; - Optional shieldAddressOptionalInfo3; - ShieldAddressInfo shieldAddressInfo1 = new ShieldAddressInfo(); - ShieldAddressInfo shieldAddressInfo2 = new ShieldAddressInfo(); - ShieldAddressInfo shieldAddressInfo3 = new ShieldAddressInfo(); - String assetIssueId; - ShieldNoteInfo shieldNote1; - ShieldNoteInfo shieldNote2; - ShieldNoteInfo shieldNote3; - String memo; - String sk; - String d1; - String d2; - String d3; - String ask; - String nsk; - String ovk; - String ak; - String nk; - String ivk; - String pkD1; - String pkD2; - String pkD3; - String paymentAddress1; - String paymentAddress2; - String paymentAddress3; - String rcm; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey1.getAddress(); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(0); - private String httpSolidityNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String httpPbftNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(4); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private String tokenId = zenTokenId; - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long costTokenAmount = 20 * zenTokenFee; - private Long sendTokenAmount = 8 * zenTokenFee; - private JSONObject responseContent; - private HttpResponse response; - - /** - * constructor. - */ - @BeforeClass(enabled = false) - public void beforeClass() { - Args.setFullNodeAllowShieldedTransaction(true); - PublicMethed.printAddress(foundationZenTokenKey); - PublicMethed.printAddress(zenTokenOwnerKey); - } - - @Test(enabled = false, description = "Get spending key by http") - public void test01GetSpendingKey() { - response = HttpMethed.getSpendingKey(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - sk = responseContent.getString("value"); - logger.info("sk: " + sk); - - } - - @Test(enabled = false, description = "Get diversifier by http") - public void test02GetDiversifier() { - response = HttpMethed.getDiversifier(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - d1 = responseContent.getString("d"); - logger.info("d1: " + d1); - - response = HttpMethed.getDiversifier(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - d2 = responseContent.getString("d"); - logger.info("d2: " + d2); - - response = HttpMethed.getDiversifier(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - d3 = responseContent.getString("d"); - logger.info("d3: " + d3); - } - - @Test(enabled = false, description = "Get expanded spending key by http") - public void test03GetExpandedSpendingKey() { - response = HttpMethed.getExpandedSpendingKey(httpnode, sk); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - ask = responseContent.getString("ask"); - nsk = responseContent.getString("nsk"); - ovk = responseContent.getString("ovk"); - logger.info("ask: " + ask); - logger.info("nsk: " + nsk); - logger.info("ovk: " + ovk); - } - - @Test(enabled = false, description = "Get AK from ASK by http") - public void test04GetAkFromAsk() { - response = HttpMethed.getAkFromAsk(httpnode, ask); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - ak = responseContent.getString("value"); - logger.info("ak: " + ak); - } - - @Test(enabled = false, description = "Get Nk from Nsk by http") - public void test05GetNkFromNsk() { - response = HttpMethed.getNkFromNsk(httpnode, nsk); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - nk = responseContent.getString("value"); - logger.info("nk: " + nk); - } - - @Test(enabled = false, description = "Get incoming viewing Key by http") - public void test06GetIncomingViewingKey() { - response = HttpMethed.getIncomingViewingKey(httpnode, ak, nk); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - ivk = responseContent.getString("ivk"); - logger.info("ivk: " + ivk); - } - - @Test(enabled = false, description = "Get Zen Payment Address by http") - public void test07GetZenPaymentAddress() { - response = HttpMethed.getZenPaymentAddress(httpnode, ivk, d1); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - pkD1 = responseContent.getString("pkD"); - paymentAddress1 = responseContent.getString("payment_address"); - System.out.println("pkd1: " + pkD1); - System.out.println("address1: " + paymentAddress1); - shieldAddressInfo1.setSk(ByteArray.fromHexString(sk)); - shieldAddressInfo1.setD(new DiversifierT(ByteArray.fromHexString(d1))); - shieldAddressInfo1.setIvk(ByteArray.fromHexString(ivk)); - shieldAddressInfo1.setOvk(ByteArray.fromHexString(ovk)); - shieldAddressInfo1.setPkD(ByteArray.fromHexString(pkD1)); - shieldAddressOptionalInfo1 = Optional.of(shieldAddressInfo1); - - response = HttpMethed.getZenPaymentAddress(httpnode, ivk, d2); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - pkD2 = responseContent.getString("pkD"); - paymentAddress2 = responseContent.getString("payment_address"); - System.out.println("pkd2: " + pkD2); - System.out.println("address2: " + paymentAddress2); - shieldAddressInfo2.setSk(ByteArray.fromHexString(sk)); - shieldAddressInfo2.setD(new DiversifierT(ByteArray.fromHexString(d2))); - shieldAddressInfo2.setIvk(ByteArray.fromHexString(ivk)); - shieldAddressInfo2.setOvk(ByteArray.fromHexString(ovk)); - shieldAddressInfo2.setPkD(ByteArray.fromHexString(pkD2)); - shieldAddressOptionalInfo2 = Optional.of(shieldAddressInfo2); - - response = HttpMethed.getZenPaymentAddress(httpnode, ivk, d3); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - pkD3 = responseContent.getString("pkD"); - paymentAddress3 = responseContent.getString("payment_address"); - System.out.println("pkd3: " + pkD3); - System.out.println("address3: " + paymentAddress3); - shieldAddressInfo3.setSk(ByteArray.fromHexString(sk)); - shieldAddressInfo3.setD(new DiversifierT(ByteArray.fromHexString(d3))); - shieldAddressInfo3.setIvk(ByteArray.fromHexString(ivk)); - shieldAddressInfo3.setOvk(ByteArray.fromHexString(ovk)); - shieldAddressInfo3.setPkD(ByteArray.fromHexString(pkD3)); - shieldAddressOptionalInfo3 = Optional.of(shieldAddressInfo3); - } - - @Test(enabled = false, description = "Get rcm by http") - public void test08GetRcm() { - response = HttpMethed.getRcm(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - rcm = responseContent.getString("value"); - logger.info("rcm: " + rcm); - } - - @Test(enabled = false, description = "Public to shield transaction withoutask by http") - public void test09PublicToShieldTransactionWithoutAsk() { - response = HttpMethed - .transferAsset(httpnode, foundationZenTokenAddress, zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenKey); - org.junit.Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed.getAccount(httpnode, foundationZenTokenAddress); - responseContent = HttpMethed.parseResponseContent(response); - assetIssueId = responseContent.getString("asset_issued_ID"); - - final Long beforeAssetBalance = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, zenTokenOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - final Long beforeNetUsed = responseContent.getLong("freeNetUsed"); - - String memo1 = "Shield memo11 in " + System.currentTimeMillis(); - String memo2 = "Shield memo22 in " + System.currentTimeMillis(); - Long sendSheldAddressAmount1 = zenTokenFee * 2; - Long sendSheldAddressAmount2 = zenTokenFee * 3; - Long sendAmount = sendSheldAddressAmount1 + sendSheldAddressAmount2 + zenTokenFee; - shieldOutList.clear(); - shieldOutList = HttpMethed - .addShieldOutputList(httpnode, shieldOutList, shieldAddressOptionalInfo1.get().getAddress(), - "" + sendSheldAddressAmount1, memo1); - shieldOutList = HttpMethed - .addShieldOutputList(httpnode, shieldOutList, shieldAddressOptionalInfo2.get().getAddress(), - "" + sendSheldAddressAmount2, memo2); - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSolidityNode); - response = HttpMethed - .sendShieldCoinWithoutAsk(httpnode, httpSolidityNode, httpPbftNode, zenTokenOwnerAddress, - sendAmount, null, null, shieldOutList, null, 0, zenTokenOwnerKey); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - HttpMethed.waitToProduceOneBlock(httpnode); - Long afterAssetBalance = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - - response = HttpMethed.getAccountReource(httpnode, zenTokenOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - Long afterNetUsed = responseContent.getLong("freeNetUsed"); - - Assert.assertTrue(beforeAssetBalance - afterAssetBalance == sendAmount); - Assert.assertTrue(beforeNetUsed == afterNetUsed); - - String memo3 = "Shield memo33 in " + System.currentTimeMillis(); - Long sendSheldAddressAmount3 = costTokenAmount - sendAmount - zenTokenFee; - shieldOutList.clear(); - shieldOutList = HttpMethed - .addShieldOutputList(httpnode, shieldOutList, shieldAddressOptionalInfo3.get().getAddress(), - "" + sendSheldAddressAmount3, memo3); - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSolidityNode); - response = HttpMethed - .sendShieldCoinWithoutAsk(httpnode, httpSolidityNode, httpPbftNode, zenTokenOwnerAddress, - sendSheldAddressAmount3 + zenTokenFee, null, null, shieldOutList, null, 0, - zenTokenOwnerKey); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - - List shieldNoteInfoByIvkList = HttpMethed - .scanNoteByIvk(httpnode, shieldAddressOptionalInfo1.get()); - logger.info("size are:" + shieldNoteInfoByIvkList.size()); - Assert.assertTrue(shieldNoteInfoByIvkList.size() == 3); - List shieldNoteInfoByMarkList = HttpMethed - .scanAndMarkNoteByIvk(httpnode, shieldAddressOptionalInfo2.get()); - Assert.assertTrue(shieldNoteInfoByMarkList.size() == 3); - - shieldNote1 = shieldNoteInfoByIvkList.get(0); - shieldNote2 = shieldNoteInfoByIvkList.get(1); - shieldNote3 = shieldNoteInfoByIvkList.get(2); - Assert.assertTrue(shieldNote1.getValue() == sendSheldAddressAmount1); - Assert.assertEquals(memo1.getBytes(), shieldNote1.getMemo()); - Assert.assertTrue(shieldNote2.getValue() == sendSheldAddressAmount2); - Assert.assertEquals(memo2.getBytes(), shieldNote2.getMemo()); - Assert.assertTrue(shieldNote3.getValue() == sendSheldAddressAmount3); - Assert.assertEquals(memo3.getBytes(), shieldNote3.getMemo()); - Assert.assertFalse(shieldNoteInfoByMarkList.get(0).getIsSpend()); - Assert.assertFalse(shieldNoteInfoByMarkList.get(1).getIsSpend()); - Assert.assertFalse(shieldNoteInfoByMarkList.get(2).getIsSpend()); - } - - @Test(enabled = false, description = "Shield to shield transaction withoutask by http") - public void test10ShieldToShieldTransactionWithoutAsk() { - Optional receiverShieldAddressInfo1 = HttpMethed - .generateShieldAddress(httpnode); - String receiverShieldAddress1 = receiverShieldAddressInfo1.get().getAddress(); - logger.info("receiverShieldAddress1:" + receiverShieldAddress1); - Optional receiverShieldAddressInfo2 = HttpMethed - .generateShieldAddress(httpnode); - String receiverShieldAddress2 = receiverShieldAddressInfo2.get().getAddress(); - logger.info("receiverShieldAddress2:" + receiverShieldAddress2); - Optional receiverShieldAddressInfo3 = HttpMethed - .generateShieldAddress(httpnode); - String receiverShieldAddress3 = receiverShieldAddressInfo3.get().getAddress(); - logger.info("receiverShieldAddress3:" + receiverShieldAddress3); - - shieldOutList.clear(); - String receiverMemo1 = "Shield memo1 in " + System.currentTimeMillis(); - shieldOutList = HttpMethed.addShieldOutputList(httpnode, shieldOutList, receiverShieldAddress1, - "" + (shieldNote1.getValue() - zenTokenFee), receiverMemo1); - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSolidityNode); - response = HttpMethed - .sendShieldCoinWithoutAsk(httpnode, httpSolidityNode, httpPbftNode, null, 0, - shieldAddressOptionalInfo1.get(), shieldNote1, shieldOutList, null, 0, null); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - /*shieldOutList.clear(); - String receiverMemo2 = "Shield memo2 in " + System.currentTimeMillis(); - shieldOutList = HttpMethed - .addShieldOutputList(httpnode, shieldOutList, receiverShieldAddress2, - "" + (shieldNote2.getValue() - zenTokenFee), receiverMemo2); - response = HttpMethed - .sendShieldCoinWithoutAsk(httpnode, null, 0, shieldAddressOptionalInfo2.get(), shieldNote2, - shieldOutList, - null, 0, null); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent);*/ - shieldOutList.clear(); - String receiverMemo3 = "Shield memo3 in " + System.currentTimeMillis(); - shieldOutList = HttpMethed.addShieldOutputList(httpnode, shieldOutList, receiverShieldAddress3, - "" + (shieldNote3.getValue() - zenTokenFee), receiverMemo3); - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSolidityNode); - response = HttpMethed - .sendShieldCoinWithoutAsk(httpnode, httpSolidityNode, httpPbftNode, null, 0, - shieldAddressOptionalInfo3.get(), shieldNote3, shieldOutList, null, 0, null); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - - List shieldNoteInfoByOvkList = HttpMethed - .scanNoteByOvk(httpnode, shieldAddressOptionalInfo3.get()); - Assert.assertTrue(shieldNoteInfoByOvkList.size() == 2); - List shieldNoteInfoByMarkList = HttpMethed - .scanAndMarkNoteByIvk(httpnode, shieldAddressOptionalInfo2.get()); - Assert.assertTrue(shieldNoteInfoByMarkList.size() == 3); - - Assert.assertTrue( - shieldNoteInfoByOvkList.get(0).getValue() == shieldNote1.getValue() - zenTokenFee); - Assert.assertEquals(receiverMemo1.getBytes(), shieldNoteInfoByOvkList.get(0).getMemo()); - /*Assert.assertTrue( - shieldNoteInfoByOvkList.get(1).getValue() == shieldNote2.getValue() - zenTokenFee); - Assert.assertEquals(receiverMemo2.getBytes(), shieldNoteInfoByOvkList.get(1).getMemo());*/ - Assert.assertTrue( - shieldNoteInfoByOvkList.get(1).getValue() == shieldNote3.getValue() - zenTokenFee); - Assert.assertEquals(receiverMemo3.getBytes(), shieldNoteInfoByOvkList.get(1).getMemo()); - Assert.assertTrue(shieldNoteInfoByMarkList.get(0).getIsSpend()); - Assert.assertFalse(shieldNoteInfoByMarkList.get(1).getIsSpend()); - Assert.assertTrue(shieldNoteInfoByMarkList.get(2).getIsSpend()); - } - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - final Long assetBalance = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - HttpMethed - .transferAsset(httpnode, zenTokenOwnerAddress, foundationZenTokenAddress, assetIssueId, - assetBalance, zenTokenOwnerKey); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken002.java deleted file mode 100644 index 7355cff0dfe..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken002.java +++ /dev/null @@ -1,332 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.Note; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.config.args.Args; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; -import stest.tron.wallet.common.client.utils.ShieldNoteInfo; - -@Slf4j -public class HttpTestZenToken002 { - - Optional sendShieldAddressInfo; - Optional receiverShieldAddressInfo; - String sendShieldAddress; - String receiverShieldAddress; - List shieldOutList = new ArrayList<>(); - String memo1; - String memo2; - ShieldNoteInfo sendNote; - ShieldNoteInfo receiverNote; - ShieldNoteInfo noteByOvk; - ShieldNoteInfo noteByIvk; - String assetIssueId; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey1.getAddress(); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(0); - private String httpSolidityNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String httpPbftNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(4); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long sendTokenAmount = 7 * zenTokenFee; - private JSONObject responseContent; - private HttpResponse response; - - /** - * constructor. - */ - @BeforeClass(enabled = false) - public void beforeClass() { - PublicMethed.printAddress(foundationZenTokenKey); - PublicMethed.printAddress(zenTokenOwnerKey); - response = HttpMethed - .transferAsset(httpnode, foundationZenTokenAddress, zenTokenOwnerAddress, zenTokenId, - sendTokenAmount, foundationZenTokenKey); - org.junit.Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - Args.setFullNodeAllowShieldedTransaction(true); - - } - - @Test(enabled = false, description = "Public to shield transaction by http") - public void test01PublicToShieldTransaction() { - response = HttpMethed.getAccount(httpnode, foundationZenTokenAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - assetIssueId = responseContent.getString("asset_issued_ID"); - - final Long beforeAssetBalance = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, zenTokenOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - final Long beforeNetUsed = responseContent.getLong("freeNetUsed"); - - sendShieldAddressInfo = HttpMethed.generateShieldAddress(httpnode); - sendShieldAddress = sendShieldAddressInfo.get().getAddress(); - logger.info("sendShieldAddress:" + sendShieldAddress); - memo1 = "Shield memo1 in " + System.currentTimeMillis(); - shieldOutList = HttpMethed.addShieldOutputList(httpnode, shieldOutList, sendShieldAddress, - "" + (sendTokenAmount - zenTokenFee), memo1); - - response = HttpMethed - .sendShieldCoin(httpnode, zenTokenOwnerAddress, sendTokenAmount, null, null, shieldOutList, - null, 0, zenTokenOwnerKey); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - HttpMethed.waitToProduceOneBlock(httpnode); - - Long afterAssetBalance = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, zenTokenOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - Long afterNetUsed = responseContent.getLong("freeNetUsed"); - - Assert.assertTrue(beforeAssetBalance - afterAssetBalance == sendTokenAmount); - Assert.assertTrue(beforeNetUsed == afterNetUsed); - - sendNote = HttpMethed.scanNoteByIvk(httpnode, sendShieldAddressInfo.get()).get(0); - Assert.assertTrue(sendNote.getValue() == sendTokenAmount - zenTokenFee); - Assert.assertEquals(memo1.getBytes(), sendNote.getMemo()); - - ShieldNoteInfo scanAndMarkNoteSendNote = HttpMethed - .scanAndMarkNoteByIvk(httpnode, sendShieldAddressInfo.get()).get(0); - Assert.assertFalse(scanAndMarkNoteSendNote.getIsSpend()); - } - - @Test(enabled = false, description = "Shield to shield transaction by http") - public void test02ShieldToShieldTransaction() { - receiverShieldAddressInfo = HttpMethed.generateShieldAddress(httpnode); - receiverShieldAddress = receiverShieldAddressInfo.get().getAddress(); - - shieldOutList.clear(); - memo2 = "Send shield to receiver shield memo in" + System.currentTimeMillis(); - shieldOutList = HttpMethed.addShieldOutputList(httpnode, shieldOutList, receiverShieldAddress, - "" + (sendNote.getValue() - zenTokenFee), memo2); - - response = HttpMethed - .sendShieldCoin(httpnode, null, 0, sendShieldAddressInfo.get(), sendNote, shieldOutList, - null, 0, null); - org.junit.Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - Long afterAssetBalance = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - - receiverNote = HttpMethed.scanNoteByIvk(httpnode, receiverShieldAddressInfo.get()).get(0); - - Assert.assertTrue(receiverNote.getValue() == sendNote.getValue() - zenTokenFee); - Assert.assertEquals(ByteArray.toHexString(memo2.getBytes()), - ByteArray.toHexString(receiverNote.getMemo())); - - Assert.assertTrue(HttpMethed.getSpendResult(httpnode, sendShieldAddressInfo.get(), sendNote)); - Assert.assertFalse( - HttpMethed.getSpendResult(httpnode, receiverShieldAddressInfo.get(), receiverNote)); - } - - @Test(enabled = false, description = "Scan note by ivk and scan not by ivk on FullNode by http") - public void test03ScanNoteByIvkAndOvk() { - //Scan sender note by ovk equals scan receiver note by ivk on FullNode - noteByOvk = HttpMethed.scanNoteByOvk(httpnode, sendShieldAddressInfo.get()).get(0); - noteByIvk = HttpMethed.scanNoteByIvk(httpnode, receiverShieldAddressInfo.get()).get(0); - Assert.assertEquals(noteByIvk.getValue(), noteByOvk.getValue()); - Assert.assertEquals(noteByIvk.getMemo(), noteByOvk.getMemo()); - Assert.assertEquals(noteByIvk.getR(), noteByOvk.getR()); - Assert.assertEquals(noteByIvk.getPaymentAddress(), noteByOvk.getPaymentAddress()); - } - - @Test(enabled = false, description = "Scan note by ivk and scan not by ivk on Solidity by http") - public void test04ScanNoteByIvkAndOvkFromSolidity() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSolidityNode); - //Scan sender note by ovk equals scan receiver note by ivk on Solidity - noteByOvk = HttpMethed.scanNoteByOvkFromSolidity(httpSolidityNode, sendShieldAddressInfo.get()) - .get(0); - noteByIvk = HttpMethed - .scanNoteByIvkFromSolidity(httpSolidityNode, receiverShieldAddressInfo.get()).get(0); - Assert.assertEquals(noteByIvk.getValue(), noteByOvk.getValue()); - Assert.assertEquals(noteByIvk.getMemo(), noteByOvk.getMemo()); - Assert.assertEquals(noteByIvk.getR(), noteByOvk.getR()); - Assert.assertEquals(noteByIvk.getPaymentAddress(), noteByOvk.getPaymentAddress()); - } - - @Test(enabled = false, description = "Scan note by ivk and scan not by ivk on PBFT by http") - public void test05ScanNoteByIvkAndOvkFromPbft() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSolidityNode); - //Scan sender note by ovk equals scan receiver note by ivk on Solidity - noteByOvk = HttpMethed.scanNoteByOvkFromPbft(httpPbftNode, sendShieldAddressInfo.get()).get(0); - noteByIvk = HttpMethed.scanNoteByIvkFromPbft(httpPbftNode, receiverShieldAddressInfo.get()) - .get(0); - Assert.assertEquals(noteByIvk.getValue(), noteByOvk.getValue()); - Assert.assertEquals(noteByIvk.getMemo(), noteByOvk.getMemo()); - Assert.assertEquals(noteByIvk.getR(), noteByOvk.getR()); - Assert.assertEquals(noteByIvk.getPaymentAddress(), noteByOvk.getPaymentAddress()); - } - - - /** - * constructor. - */ - @Test(enabled = false, description = "Query whether note is spend on solidity by http") - public void test06QueryNoteIsSpendOnSolidity() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSolidityNode); - Assert.assertTrue(HttpMethed - .getSpendResultFromSolidity(httpnode, httpSolidityNode, sendShieldAddressInfo.get(), - sendNote)); - Assert.assertFalse(HttpMethed - .getSpendResultFromSolidity(httpnode, httpSolidityNode, receiverShieldAddressInfo.get(), - receiverNote)); - } - - /** - * constructor. - */ - @Test(enabled = false, description = "Query whether note is spend on PBFT by http") - public void test07QueryNoteIsSpendOnSolidity() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSolidityNode); - Assert.assertTrue(HttpMethed - .getSpendResultFromPbft(httpnode, httpPbftNode, sendShieldAddressInfo.get(), sendNote)); - Assert.assertFalse(HttpMethed - .getSpendResultFromPbft(httpnode, httpPbftNode, receiverShieldAddressInfo.get(), - receiverNote)); - } - - - /** - * constructor. - */ - @Test(enabled = false, description = "Query note and spend status on fullnode") - public void test08QueryNoteAndSpendStatusOnFullnode() { - ShieldNoteInfo scanAndMarkNoteSendNote = HttpMethed - .scanAndMarkNoteByIvk(httpnode, sendShieldAddressInfo.get()).get(0); - Assert.assertTrue(scanAndMarkNoteSendNote.isSpend); - Assert.assertEquals(scanAndMarkNoteSendNote.getValue(), sendNote.getValue()); - Assert.assertEquals(scanAndMarkNoteSendNote.getMemo(), sendNote.getMemo()); - Assert.assertEquals(scanAndMarkNoteSendNote.getR(), sendNote.getR()); - Assert.assertEquals(scanAndMarkNoteSendNote.getPaymentAddress(), sendNote.getPaymentAddress()); - - ShieldNoteInfo scanAndMarkNoteReceiverNote = HttpMethed - .scanAndMarkNoteByIvk(httpnode, receiverShieldAddressInfo.get()).get(0); - Assert.assertFalse(scanAndMarkNoteReceiverNote.getIsSpend()); - Assert.assertEquals(scanAndMarkNoteReceiverNote.getValue(), receiverNote.getValue()); - Assert.assertEquals(scanAndMarkNoteReceiverNote.getMemo(), receiverNote.getMemo()); - Assert.assertEquals(scanAndMarkNoteReceiverNote.getR(), receiverNote.getR()); - Assert.assertEquals(scanAndMarkNoteReceiverNote.getPaymentAddress(), - receiverNote.getPaymentAddress()); - } - - @Test(enabled = false, description = "Query note and spend status on solidity") - public void test09QueryNoteAndSpendStatusOnSolidity() { - ShieldNoteInfo scanAndMarkNoteSendNote = HttpMethed - .scanAndMarkNoteByIvkFromSolidity(httpnode, httpSolidityNode, sendShieldAddressInfo.get()) - .get(0); - Assert.assertTrue(scanAndMarkNoteSendNote.isSpend); - Assert.assertEquals(scanAndMarkNoteSendNote.getValue(), sendNote.getValue()); - Assert.assertEquals(scanAndMarkNoteSendNote.getMemo(), sendNote.getMemo()); - Assert.assertEquals(scanAndMarkNoteSendNote.getR(), sendNote.getR()); - Assert.assertEquals(scanAndMarkNoteSendNote.getPaymentAddress(), sendNote.getPaymentAddress()); - - ShieldNoteInfo scanAndMarkNoteReceiverNote = HttpMethed - .scanAndMarkNoteByIvkFromSolidity(httpnode, httpSolidityNode, - receiverShieldAddressInfo.get()).get(0); - Assert.assertFalse(scanAndMarkNoteReceiverNote.getIsSpend()); - Assert.assertEquals(scanAndMarkNoteReceiverNote.getValue(), receiverNote.getValue()); - Assert.assertEquals(scanAndMarkNoteReceiverNote.getMemo(), receiverNote.getMemo()); - Assert.assertEquals(scanAndMarkNoteReceiverNote.getR(), receiverNote.getR()); - Assert.assertEquals(scanAndMarkNoteReceiverNote.getPaymentAddress(), - receiverNote.getPaymentAddress()); - - } - - @Test(enabled = false, description = "Query note and spend status on PBFT") - public void test10QueryNoteAndSpendStatusOnPbft() { - ShieldNoteInfo scanAndMarkNoteSendNote = HttpMethed - .scanAndMarkNoteByIvkFromPbft(httpnode, httpPbftNode, sendShieldAddressInfo.get()).get(0); - Assert.assertTrue(scanAndMarkNoteSendNote.isSpend); - Assert.assertEquals(scanAndMarkNoteSendNote.getValue(), sendNote.getValue()); - Assert.assertEquals(scanAndMarkNoteSendNote.getMemo(), sendNote.getMemo()); - Assert.assertEquals(scanAndMarkNoteSendNote.getR(), sendNote.getR()); - Assert.assertEquals(scanAndMarkNoteSendNote.getPaymentAddress(), sendNote.getPaymentAddress()); - - ShieldNoteInfo scanAndMarkNoteReceiverNote = HttpMethed - .scanAndMarkNoteByIvkFromPbft(httpnode, httpPbftNode, receiverShieldAddressInfo.get()) - .get(0); - Assert.assertFalse(scanAndMarkNoteReceiverNote.getIsSpend()); - Assert.assertEquals(scanAndMarkNoteReceiverNote.getValue(), receiverNote.getValue()); - Assert.assertEquals(scanAndMarkNoteReceiverNote.getMemo(), receiverNote.getMemo()); - Assert.assertEquals(scanAndMarkNoteReceiverNote.getR(), receiverNote.getR()); - Assert.assertEquals(scanAndMarkNoteReceiverNote.getPaymentAddress(), - receiverNote.getPaymentAddress()); - - } - - - @Test(enabled = false, description = "Shield to public transaction by http") - public void test11ShieldToPublicTransaction() { - final Long beforeAssetBalance = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, zenTokenOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - final Long beforeNetUsed = responseContent.getLong("freeNetUsed"); - - shieldOutList.clear(); - response = HttpMethed - .sendShieldCoin(httpnode, null, 0, receiverShieldAddressInfo.get(), receiverNote, - shieldOutList, zenTokenOwnerAddress, receiverNote.getValue() - zenTokenFee, null); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - HttpMethed.waitToProduceOneBlock(httpnode); - - Long afterAssetBalance = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, zenTokenOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - Long afterNetUsed = responseContent.getLong("freeNetUsed"); - - logger.info("beforeAssetBalance:" + beforeAssetBalance); - logger.info("afterAssetBalance:" + afterAssetBalance); - Assert.assertTrue( - afterAssetBalance - beforeAssetBalance == receiverNote.getValue() - zenTokenFee); - Assert.assertTrue(beforeNetUsed == afterNetUsed); - - Assert.assertTrue( - HttpMethed.getSpendResult(httpnode, receiverShieldAddressInfo.get(), receiverNote)); - } - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - final Long assetBalance = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - HttpMethed - .transferAsset(httpnode, zenTokenOwnerAddress, foundationZenTokenAddress, assetIssueId, - assetBalance, zenTokenOwnerKey); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken003.java deleted file mode 100644 index ca1889b0423..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken003.java +++ /dev/null @@ -1,308 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.Note; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.config.args.Args; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; -import stest.tron.wallet.common.client.utils.ShieldNoteInfo; - -@Slf4j -public class HttpTestZenToken003 { - - Optional receiverShieldAddressInfo1; - Optional receiverShieldAddressInfo2; - Optional receiverShieldAddressInfo3; - Optional receiverShieldAddressInfo4; - Optional receiverShieldAddressInfo5; - String receiverShieldAddress1; - String receiverShieldAddress2; - String receiverShieldAddress3; - String receiverShieldAddress4; - String receiverShieldAddress5; - List shieldOutList = new ArrayList<>(); - String memo1; - String memo2; - String memo3; - String memo4; - String memo5; - ShieldNoteInfo receiverNote1; - ShieldNoteInfo receiverNote2; - ShieldNoteInfo receiverNote3; - ShieldNoteInfo receiverNote4; - ShieldNoteInfo receiverNote5; - String assetIssueId; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey1.getAddress(); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] receiverPublicAddress = ecKey2.getAddress(); - String receiverPublicKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(0); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long zenTokenWhenCreateNewAddress = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenWhenCreateNewAddress"); - private Long sendTokenAmount = 18 * zenTokenFee; - private JSONObject responseContent; - private HttpResponse response; - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(foundationZenTokenKey); - PublicMethed.printAddress(zenTokenOwnerKey); - Args.setFullNodeAllowShieldedTransaction(true); - - } - - @Test(enabled = false, description = "Public to two shield transaction by http") - public void test01PublicToTwoShieldTransaction() { - response = HttpMethed - .transferAsset(httpnode, foundationZenTokenAddress, zenTokenOwnerAddress, zenTokenId, - sendTokenAmount, foundationZenTokenKey); - HttpMethed.waitToProduceOneBlock(httpnode); - - receiverShieldAddressInfo1 = HttpMethed.generateShieldAddress(httpnode); - receiverShieldAddressInfo2 = HttpMethed.generateShieldAddress(httpnode); - receiverShieldAddress1 = receiverShieldAddressInfo1.get().getAddress(); - receiverShieldAddress2 = receiverShieldAddressInfo2.get().getAddress(); - logger.info("receiverShieldAddress1:" + receiverShieldAddress1); - logger.info("receiverShieldAddress2:" + receiverShieldAddress2); - memo1 = "Shield memo1 in " + System.currentTimeMillis(); - memo2 = "Shield memo2 in " + System.currentTimeMillis(); - Long sendToShiledAddress1Amount = 1 * zenTokenFee; - Long sendToShiledAddress2Amount = sendTokenAmount - sendToShiledAddress1Amount - zenTokenFee; - shieldOutList = HttpMethed.addShieldOutputList(httpnode, shieldOutList, receiverShieldAddress1, - "" + sendToShiledAddress1Amount, memo1); - shieldOutList = HttpMethed.addShieldOutputList(httpnode, shieldOutList, receiverShieldAddress2, - "" + sendToShiledAddress2Amount, memo2); - - response = HttpMethed.getAccount(httpnode, foundationZenTokenAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - assetIssueId = responseContent.getString("asset_issued_ID"); - final Long beforeAssetBalance = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - - response = HttpMethed.getAccountReource(httpnode, zenTokenOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - final Long beforeNetUsed = responseContent.getLong("freeNetUsed"); - - response = HttpMethed - .sendShieldCoin(httpnode, zenTokenOwnerAddress, sendTokenAmount, null, null, shieldOutList, - null, 0, zenTokenOwnerKey); - org.junit.Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - HttpMethed.waitToProduceOneBlock(httpnode); - Long afterAssetBalance = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, zenTokenOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - Long afterNetUsed = responseContent.getLong("freeNetUsed"); - Assert.assertTrue(beforeAssetBalance - afterAssetBalance == sendTokenAmount); - Assert.assertTrue(beforeNetUsed == afterNetUsed); - - receiverNote1 = HttpMethed.scanNoteByIvk(httpnode, receiverShieldAddressInfo1.get()).get(0); - receiverNote2 = HttpMethed.scanNoteByIvk(httpnode, receiverShieldAddressInfo2.get()).get(0); - Assert.assertTrue(receiverNote1.getValue() == sendToShiledAddress1Amount); - Assert.assertTrue(receiverNote2.getValue() == sendToShiledAddress2Amount); - Assert.assertEquals(memo1.getBytes(), receiverNote1.getMemo()); - Assert.assertEquals(memo2.getBytes(), receiverNote2.getMemo()); - } - - @Test(enabled = false, description = "Public to one public and one shield transaction by http") - public void test02ShieldToOneShieldAndOnePublicTransaction() { - response = HttpMethed - .transferAsset(httpnode, foundationZenTokenAddress, zenTokenOwnerAddress, zenTokenId, - sendTokenAmount, foundationZenTokenKey); - HttpMethed.waitToProduceOneBlock(httpnode); - - receiverShieldAddressInfo3 = HttpMethed.generateShieldAddress(httpnode); - receiverShieldAddress3 = receiverShieldAddressInfo3.get().getAddress(); - - final Long beforeAssetBalanceSendAddress = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, zenTokenOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - final Long beforeNetUsedSendAddress = responseContent.getLong("freeNetUsed"); - response = HttpMethed.getAccount(httpnode, zenTokenOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - Long beforeBalanceSendAddress = responseContent.getLong("balance"); - - final Long beforeAssetBalanceReceiverAddress = HttpMethed - .getAssetIssueValue(httpnode, receiverPublicAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, receiverPublicAddress); - responseContent = HttpMethed.parseResponseContent(response); - final Long beforeNetUsedReceiverAddress = responseContent.getLong("freeNetUsed"); - - shieldOutList.clear(); - Long sendToPublicAddressAmount = 1 * zenTokenFee; - Long sendToShiledAddressAmount = - sendTokenAmount - sendToPublicAddressAmount - zenTokenWhenCreateNewAddress; - memo3 = "Send shield to receiver shield memo in" + System.currentTimeMillis(); - shieldOutList = HttpMethed.addShieldOutputList(httpnode, shieldOutList, receiverShieldAddress3, - "" + sendToShiledAddressAmount, memo3); - - PublicMethed.printAddress(receiverPublicKey); - response = HttpMethed - .sendShieldCoin(httpnode, zenTokenOwnerAddress, sendTokenAmount, null, null, shieldOutList, - receiverPublicAddress, sendToPublicAddressAmount, zenTokenOwnerKey); - org.junit.Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - HttpMethed.waitToProduceOneBlock(httpnode); - - Long afterAssetBalanceSendAddress = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, zenTokenOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - Long afterNetUsedSendAddress = responseContent.getLong("freeNetUsed"); - response = HttpMethed.getAccount(httpnode, zenTokenOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - Long afterBalanceSendAddress = responseContent.getLong("balance"); - - final Long afterAssetBalanceReceiverAddress = HttpMethed - .getAssetIssueValue(httpnode, receiverPublicAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, receiverPublicAddress); - responseContent = HttpMethed.parseResponseContent(response); - final Long afterNetUsedReceiverAddress = responseContent.getLong("freeNetUsed"); - - Assert.assertTrue( - beforeAssetBalanceSendAddress - afterAssetBalanceSendAddress == sendTokenAmount); - Assert.assertTrue(beforeNetUsedSendAddress == afterNetUsedSendAddress); - Assert.assertTrue(beforeBalanceSendAddress == afterBalanceSendAddress); - - Assert.assertTrue(afterAssetBalanceReceiverAddress - beforeAssetBalanceReceiverAddress - == sendToPublicAddressAmount); - Assert.assertTrue(beforeNetUsedReceiverAddress == afterNetUsedReceiverAddress); - - receiverNote3 = HttpMethed.scanNoteByIvk(httpnode, receiverShieldAddressInfo3.get()).get(0); - - Assert.assertTrue(receiverNote3.getValue() == sendToShiledAddressAmount); - Assert.assertEquals(memo3.getBytes(), receiverNote3.getMemo()); - } - - @Test(enabled = false, description = "Public to one public and two shield transaction by http") - public void test03ShieldToOneShieldAndTwoPublicTransaction() { - response = HttpMethed - .transferAsset(httpnode, foundationZenTokenAddress, zenTokenOwnerAddress, zenTokenId, - sendTokenAmount, foundationZenTokenKey); - HttpMethed.waitToProduceOneBlock(httpnode); - - receiverShieldAddressInfo4 = HttpMethed.generateShieldAddress(httpnode); - receiverShieldAddress4 = receiverShieldAddressInfo4.get().getAddress(); - receiverShieldAddressInfo5 = HttpMethed.generateShieldAddress(httpnode); - receiverShieldAddress5 = receiverShieldAddressInfo5.get().getAddress(); - - final Long beforeAssetBalanceSendAddress = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, zenTokenOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - final Long beforeNetUsedSendAddress = responseContent.getLong("freeNetUsed"); - response = HttpMethed.getAccount(httpnode, zenTokenOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - Long beforeBalanceSendAddress = responseContent.getLong("balance"); - - final Long beforeAssetBalanceReceiverAddress = HttpMethed - .getAssetIssueValue(httpnode, receiverPublicAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, receiverPublicAddress); - responseContent = HttpMethed.parseResponseContent(response); - final Long beforeNetUsedReceiverAddress = responseContent.getLong("freeNetUsed"); - - shieldOutList.clear(); - Long sendToPublicAddressAmount = 1 * zenTokenFee; - Long sendToShiledAddress1Amount = 2 * zenTokenFee; - Long sendToShiledAddress2Amount = - sendTokenAmount - sendToPublicAddressAmount - sendToShiledAddress1Amount - zenTokenFee; - memo4 = "Send shield to receiver shield memo in" + System.currentTimeMillis(); - memo5 = "Send shield to receiver shield memo in" + System.currentTimeMillis(); - shieldOutList = HttpMethed.addShieldOutputList(httpnode, shieldOutList, receiverShieldAddress4, - "" + sendToShiledAddress1Amount, memo4); - shieldOutList = HttpMethed.addShieldOutputList(httpnode, shieldOutList, receiverShieldAddress5, - "" + sendToShiledAddress2Amount, memo5); - - PublicMethed.printAddress(receiverPublicKey); - response = HttpMethed - .sendShieldCoin(httpnode, zenTokenOwnerAddress, sendTokenAmount, null, null, shieldOutList, - receiverPublicAddress, sendToPublicAddressAmount, zenTokenOwnerKey); - org.junit.Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - HttpMethed.waitToProduceOneBlock(httpnode); - - Long afterAssetBalanceSendAddress = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, zenTokenOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - Long afterNetUsedSendAddress = responseContent.getLong("freeNetUsed"); - response = HttpMethed.getAccount(httpnode, zenTokenOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - Long afterBalanceSendAddress = responseContent.getLong("balance"); - - final Long afterAssetBalanceReceiverAddress = HttpMethed - .getAssetIssueValue(httpnode, receiverPublicAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, receiverPublicAddress); - responseContent = HttpMethed.parseResponseContent(response); - final Long afterNetUsedReceiverAddress = responseContent.getLong("freeNetUsed"); - - Assert.assertTrue( - beforeAssetBalanceSendAddress - afterAssetBalanceSendAddress == sendTokenAmount); - Assert.assertTrue(beforeNetUsedSendAddress == afterNetUsedSendAddress); - Assert.assertTrue(beforeBalanceSendAddress == afterBalanceSendAddress); - - Assert.assertTrue(afterAssetBalanceReceiverAddress - beforeAssetBalanceReceiverAddress - == sendToPublicAddressAmount); - Assert.assertTrue(beforeNetUsedReceiverAddress == afterNetUsedReceiverAddress); - - receiverNote4 = HttpMethed.scanNoteByIvk(httpnode, receiverShieldAddressInfo4.get()).get(0); - Assert.assertTrue(receiverNote4.getValue() == sendToShiledAddress1Amount); - Assert.assertEquals(memo4.getBytes(), receiverNote4.getMemo()); - - receiverNote5 = HttpMethed.scanNoteByIvk(httpnode, receiverShieldAddressInfo5.get()).get(0); - Assert.assertTrue(receiverNote5.getValue() == sendToShiledAddress2Amount); - Assert.assertEquals(memo5.getBytes(), receiverNote5.getMemo()); - } - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - final Long assetBalance1 = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - HttpMethed - .transferAsset(httpnode, zenTokenOwnerAddress, foundationZenTokenAddress, assetIssueId, - assetBalance1, zenTokenOwnerKey); - - final Long assetBalance2 = HttpMethed - .getAssetIssueValue(httpnode, receiverPublicAddress, assetIssueId); - HttpMethed - .transferAsset(httpnode, receiverPublicAddress, foundationZenTokenAddress, assetIssueId, - assetBalance2, receiverPublicKey); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken004.java deleted file mode 100644 index d7d9bcb6e5d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken004.java +++ /dev/null @@ -1,289 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.Note; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.config.args.Args; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; -import stest.tron.wallet.common.client.utils.ShieldNoteInfo; - -@Slf4j -public class HttpTestZenToken004 { - - Optional sendShieldAddressInfo; - Optional receiverShieldAddressInfo1; - Optional receiverShieldAddressInfo2; - Optional receiverShieldAddressInfo3; - Optional receiverShieldAddressInfo4; - Optional receiverShieldAddressInfo5; - String sendShieldAddress; - String receiverShieldAddress1; - String receiverShieldAddress2; - String receiverShieldAddress3; - String receiverShieldAddress4; - String receiverShieldAddress5; - List shieldOutList = new ArrayList<>(); - String memo1; - String memo2; - String memo3; - String memo4; - String memo5; - ShieldNoteInfo sendNote; - ShieldNoteInfo receiverNote1; - ShieldNoteInfo receiverNote2; - ShieldNoteInfo receiverNote3; - ShieldNoteInfo receiverNote4; - ShieldNoteInfo receiverNote5; - String assetIssueId; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] receiverPublicAddress = ecKey1.getAddress(); - String receiverPublicKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(0); - private String httpSolidityNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long zenTokenWhenCreateNewAddress = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenWhenCreateNewAddress"); - private Long sendTokenAmount = 18 * zenTokenFee; - private JSONObject responseContent; - private HttpResponse response; - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(foundationZenTokenKey); - Args.setFullNodeAllowShieldedTransaction(true); - } - - @Test(enabled = false, description = "Shield to two shield transaction by http") - public void test01ShieldToTwoShieldTransaction() { - sendShieldAddressInfo = HttpMethed.generateShieldAddress(httpnode); - sendShieldAddress = sendShieldAddressInfo.get().getAddress(); - logger.info("sendShieldAddress:" + sendShieldAddress); - String memo = "Shield memo in " + System.currentTimeMillis(); - shieldOutList = HttpMethed - .addShieldOutputList(httpnode, shieldOutList, sendShieldAddress, "" + sendTokenAmount, - memo); - response = HttpMethed - .sendShieldCoin(httpnode, foundationZenTokenAddress, sendTokenAmount + zenTokenFee, null, - null, shieldOutList, null, 0, foundationZenTokenKey); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - HttpMethed.waitToProduceOneBlock(httpnode); - sendNote = HttpMethed.scanNoteByIvk(httpnode, sendShieldAddressInfo.get()).get(0); - - receiverShieldAddressInfo1 = HttpMethed.generateShieldAddress(httpnode); - receiverShieldAddressInfo2 = HttpMethed.generateShieldAddress(httpnode); - receiverShieldAddress1 = receiverShieldAddressInfo1.get().getAddress(); - receiverShieldAddress2 = receiverShieldAddressInfo2.get().getAddress(); - logger.info("receiverShieldAddress1:" + receiverShieldAddress1); - logger.info("receiverShieldAddress2:" + receiverShieldAddress2); - memo1 = "Shield memo1 in " + System.currentTimeMillis(); - memo2 = "Shield memo2 in " + System.currentTimeMillis(); - Long sendToShiledAddress1Amount = 1 * zenTokenFee; - Long sendToShiledAddress2Amount = sendTokenAmount - sendToShiledAddress1Amount - zenTokenFee; - shieldOutList.clear(); - shieldOutList = HttpMethed.addShieldOutputList(httpnode, shieldOutList, receiverShieldAddress1, - "" + sendToShiledAddress1Amount, memo1); - shieldOutList = HttpMethed.addShieldOutputList(httpnode, shieldOutList, receiverShieldAddress2, - "" + sendToShiledAddress2Amount, memo2); - - response = HttpMethed - .sendShieldCoin(httpnode, null, 0, sendShieldAddressInfo.get(), sendNote, shieldOutList, - null, 0, null); - org.junit.Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - HttpMethed.waitToProduceOneBlock(httpnode); - - receiverNote1 = HttpMethed.scanNoteByIvk(httpnode, receiverShieldAddressInfo1.get()).get(0); - receiverNote2 = HttpMethed.scanNoteByIvk(httpnode, receiverShieldAddressInfo2.get()).get(0); - Assert.assertTrue(receiverNote1.getValue() == sendToShiledAddress1Amount); - Assert.assertTrue(receiverNote2.getValue() == sendToShiledAddress2Amount); - Assert.assertEquals(memo1.getBytes(), receiverNote1.getMemo()); - Assert.assertEquals(memo2.getBytes(), receiverNote2.getMemo()); - - Assert.assertTrue(HttpMethed.getSpendResult(httpnode, sendShieldAddressInfo.get(), sendNote)); - } - - @Test(enabled = false, description = "Shield to one public and one shield transaction by http") - public void test02ShieldToOnePublicAndOneShieldTransaction() { - sendShieldAddressInfo = HttpMethed.generateShieldAddress(httpnode); - sendShieldAddress = sendShieldAddressInfo.get().getAddress(); - logger.info("sendShieldAddress:" + sendShieldAddress); - String memo = "Shield memo in " + System.currentTimeMillis(); - shieldOutList.clear(); - shieldOutList = HttpMethed - .addShieldOutputList(httpnode, shieldOutList, sendShieldAddress, "" + sendTokenAmount, - memo); - response = HttpMethed - .sendShieldCoin(httpnode, foundationZenTokenAddress, sendTokenAmount + zenTokenFee, null, - null, shieldOutList, null, 0, foundationZenTokenKey); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - HttpMethed.waitToProduceOneBlock(httpnode); - sendNote = HttpMethed.scanNoteByIvk(httpnode, sendShieldAddressInfo.get()).get(0); - - receiverShieldAddressInfo3 = HttpMethed.generateShieldAddress(httpnode); - receiverShieldAddress3 = receiverShieldAddressInfo3.get().getAddress(); - - response = HttpMethed.getAccount(httpnode, foundationZenTokenAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - assetIssueId = responseContent.getString("asset_issued_ID"); - - final Long beforeAssetBalance = HttpMethed - .getAssetIssueValue(httpnode, receiverPublicAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, receiverPublicAddress); - responseContent = HttpMethed.parseResponseContent(response); - final Long beforeNetUsed = responseContent.getLong("freeNetUsed"); - - shieldOutList.clear(); - Long sendToPublicAddressAmount = 1 * zenTokenFee; - Long sendToShiledAddressAmount = - sendTokenAmount - sendToPublicAddressAmount - zenTokenWhenCreateNewAddress; - memo3 = "Send shield to receiver shield memo in" + System.currentTimeMillis(); - shieldOutList = HttpMethed.addShieldOutputList(httpnode, shieldOutList, receiverShieldAddress3, - "" + sendToShiledAddressAmount, memo3); - - PublicMethed.printAddress(receiverPublicKey); - response = HttpMethed - .sendShieldCoin(httpnode, null, 0, sendShieldAddressInfo.get(), sendNote, shieldOutList, - receiverPublicAddress, sendToPublicAddressAmount, null); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - HttpMethed.waitToProduceOneBlock(httpnode); - - final Long afterAssetBalance = HttpMethed - .getAssetIssueValue(httpnode, receiverPublicAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, receiverPublicAddress); - responseContent = HttpMethed.parseResponseContent(response); - final Long afterNetUsed = responseContent.getLong("freeNetUsed"); - - Assert.assertTrue(afterAssetBalance - beforeAssetBalance == sendToPublicAddressAmount); - Assert.assertTrue(beforeNetUsed == afterNetUsed); - - receiverNote3 = HttpMethed.scanNoteByIvk(httpnode, receiverShieldAddressInfo3.get()).get(0); - Assert.assertTrue(receiverNote3.getValue() == sendToShiledAddressAmount); - Assert.assertEquals(memo3.getBytes(), receiverNote3.getMemo()); - - Assert.assertTrue(HttpMethed.getSpendResult(httpnode, sendShieldAddressInfo.get(), sendNote)); - - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSolidityNode); - Assert.assertTrue(HttpMethed - .getSpendResultFromSolidity(httpnode, httpSolidityNode, sendShieldAddressInfo.get(), - sendNote)); - Assert.assertFalse(HttpMethed - .getSpendResultFromSolidity(httpnode, httpSolidityNode, receiverShieldAddressInfo3.get(), - receiverNote3)); - - Assert.assertTrue( - HttpMethed.scanAndMarkNoteByIvk(httpnode, sendShieldAddressInfo.get()).get(0).getIsSpend()); - Assert.assertFalse( - HttpMethed.scanAndMarkNoteByIvk(httpnode, receiverShieldAddressInfo3.get()).get(0) - .getIsSpend()); - } - - @Test(enabled = false, description = "Shield to one public and two shield transaction by http") - public void test03ShieldToOnePublicAndTwoShieldTransaction() { - sendShieldAddressInfo = HttpMethed.generateShieldAddress(httpnode); - sendShieldAddress = sendShieldAddressInfo.get().getAddress(); - logger.info("sendShieldAddress:" + sendShieldAddress); - String memo = "Shield memo in " + System.currentTimeMillis(); - shieldOutList.clear(); - shieldOutList = HttpMethed - .addShieldOutputList(httpnode, shieldOutList, sendShieldAddress, "" + sendTokenAmount, - memo); - response = HttpMethed - .sendShieldCoin(httpnode, foundationZenTokenAddress, sendTokenAmount + zenTokenFee, null, - null, shieldOutList, null, 0, foundationZenTokenKey); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - HttpMethed.waitToProduceOneBlock(httpnode); - sendNote = HttpMethed.scanNoteByIvk(httpnode, sendShieldAddressInfo.get()).get(0); - - receiverShieldAddressInfo4 = HttpMethed.generateShieldAddress(httpnode); - receiverShieldAddress4 = receiverShieldAddressInfo4.get().getAddress(); - receiverShieldAddressInfo5 = HttpMethed.generateShieldAddress(httpnode); - receiverShieldAddress5 = receiverShieldAddressInfo5.get().getAddress(); - - final Long beforeAssetBalance = HttpMethed - .getAssetIssueValue(httpnode, receiverPublicAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, receiverPublicAddress); - responseContent = HttpMethed.parseResponseContent(response); - final Long beforeNetUsed = responseContent.getLong("freeNetUsed"); - - shieldOutList.clear(); - Long sendToPublicAddressAmount = 1 * zenTokenFee; - Long sendToShiledAddress1Amount = 2 * zenTokenFee; - Long sendToShiledAddress2Amount = - sendTokenAmount - sendToPublicAddressAmount - sendToShiledAddress1Amount - zenTokenFee; - memo4 = "Send shield to receiver shield memo in" + System.currentTimeMillis(); - memo5 = "Send shield to receiver shield memo in" + System.currentTimeMillis(); - shieldOutList = HttpMethed.addShieldOutputList(httpnode, shieldOutList, receiverShieldAddress4, - "" + sendToShiledAddress1Amount, memo4); - shieldOutList = HttpMethed.addShieldOutputList(httpnode, shieldOutList, receiverShieldAddress5, - "" + sendToShiledAddress2Amount, memo5); - - PublicMethed.printAddress(receiverPublicKey); - response = HttpMethed - .sendShieldCoin(httpnode, null, 0, sendShieldAddressInfo.get(), sendNote, shieldOutList, - receiverPublicAddress, sendToPublicAddressAmount, null); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - HttpMethed.waitToProduceOneBlock(httpnode); - - final Long afterAssetBalance = HttpMethed - .getAssetIssueValue(httpnode, receiverPublicAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, receiverPublicAddress); - responseContent = HttpMethed.parseResponseContent(response); - final Long afterNetUsed = responseContent.getLong("freeNetUsed"); - - Assert.assertTrue(afterAssetBalance - beforeAssetBalance == sendToPublicAddressAmount); - Assert.assertTrue(beforeNetUsed == afterNetUsed); - - receiverNote4 = HttpMethed.scanNoteByIvk(httpnode, receiverShieldAddressInfo4.get()).get(0); - Assert.assertTrue(receiverNote4.getValue() == sendToShiledAddress1Amount); - Assert.assertEquals(memo4.getBytes(), receiverNote4.getMemo()); - - receiverNote5 = HttpMethed.scanNoteByIvk(httpnode, receiverShieldAddressInfo5.get()).get(0); - Assert.assertTrue(receiverNote5.getValue() == sendToShiledAddress2Amount); - Assert.assertEquals(memo5.getBytes(), receiverNote5.getMemo()); - - Assert.assertTrue(HttpMethed.getSpendResult(httpnode, sendShieldAddressInfo.get(), sendNote)); - } - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - final Long assetBalance = HttpMethed - .getAssetIssueValue(httpnode, receiverPublicAddress, assetIssueId); - HttpMethed - .transferAsset(httpnode, receiverPublicAddress, foundationZenTokenAddress, assetIssueId, - assetBalance, receiverPublicKey); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken005.java deleted file mode 100644 index 2075fd37b8c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken005.java +++ /dev/null @@ -1,174 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.Note; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.config.args.Args; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; -import stest.tron.wallet.common.client.utils.ShieldNoteInfo; - -@Slf4j -public class HttpTestZenToken005 { - - Optional sendShieldAddressInfo; - Optional receiverShieldAddressInfo; - String sendShieldAddress; - String receiverShieldAddress; - List shieldOutList = new ArrayList<>(); - String memo1; - String memo2; - ShieldNoteInfo sendNote; - ShieldNoteInfo receiveNote; - String assetIssueId; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey1.getAddress(); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(0); - private String httpSolidityNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String httpPbftNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(4); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long sendTokenAmount = 7 * zenTokenFee; - private JSONObject responseContent; - private HttpResponse response; - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(foundationZenTokenKey); - PublicMethed.printAddress(zenTokenOwnerKey); - response = HttpMethed - .transferAsset(httpnode, foundationZenTokenAddress, zenTokenOwnerAddress, zenTokenId, - sendTokenAmount, foundationZenTokenKey); - org.junit.Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - Args.setFullNodeAllowShieldedTransaction(true); - sendShieldAddressInfo = HttpMethed.generateShieldAddress(httpnode); - sendShieldAddress = sendShieldAddressInfo.get().getAddress(); - logger.info("sendShieldAddress:" + sendShieldAddress); - memo1 = "Shield memo1 in " + System.currentTimeMillis(); - shieldOutList = HttpMethed.addShieldOutputList(httpnode, shieldOutList, sendShieldAddress, - "" + (sendTokenAmount - zenTokenFee), memo1); - - response = HttpMethed - .sendShieldCoin(httpnode, zenTokenOwnerAddress, sendTokenAmount, null, null, shieldOutList, - null, 0, zenTokenOwnerKey); - org.junit.Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - shieldOutList.clear(); - HttpMethed.waitToProduceOneBlock(httpnode); - sendNote = HttpMethed.scanNoteByIvk(httpnode, sendShieldAddressInfo.get()).get(0); - } - - @Test(enabled = false, description = "Shield to shield transaction without ask by http") - public void test01ShieldToShieldWithoutAskTransaction() { - receiverShieldAddressInfo = HttpMethed.generateShieldAddress(httpnode); - receiverShieldAddress = receiverShieldAddressInfo.get().getAddress(); - - shieldOutList.clear(); - memo2 = "Send shield to receiver shield memo in" + System.currentTimeMillis(); - shieldOutList = HttpMethed.addShieldOutputList(httpnode, shieldOutList, receiverShieldAddress, - "" + (sendNote.getValue() - zenTokenFee), memo2); - - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSolidityNode); - response = HttpMethed - .sendShieldCoinWithoutAsk(httpnode, httpSolidityNode, httpPbftNode, null, 0, - sendShieldAddressInfo.get(), sendNote, shieldOutList, null, 0, null); - org.junit.Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); - logger.info("response:" + response); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("responseContent:" + responseContent); - HttpMethed.printJsonContent(responseContent); - HttpMethed.waitToProduceOneBlock(httpnode); - - receiveNote = HttpMethed.scanNoteByIvk(httpnode, receiverShieldAddressInfo.get()).get(0); - - Assert.assertTrue(receiveNote.getValue() == sendNote.getValue() - zenTokenFee); - Assert.assertEquals(ByteArray.toHexString(memo2.getBytes()), - ByteArray.toHexString(receiveNote.getMemo())); - - Assert.assertTrue(HttpMethed.getSpendResult(httpnode, sendShieldAddressInfo.get(), sendNote)); - } - - @Test(enabled = false, description = "Get merkle tree voucher info by http") - public void test02GetMerkleTreeVoucherInfo() { - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed - .getMerkleTreeVoucherInfo(httpnode, sendNote.getTrxId(), sendNote.getIndex(), 1); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.toJSONString().contains("tree")); - Assert.assertTrue(responseContent.toJSONString().contains("rt")); - Assert.assertTrue(responseContent.toJSONString().contains("paths")); - - response = HttpMethed - .getMerkleTreeVoucherInfo(httpnode, receiveNote.getTrxId(), receiveNote.getIndex(), 1000); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.toJSONString().contains( - "synBlockNum is too large, cmBlockNum plus synBlockNum must be <= latestBlockNumber")); - } - - @Test(enabled = false, description = "Get merkle tree voucher info by http from solidity") - public void test03GetMerkleTreeVoucherInfoFromSolidity() { - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed - .getMerkleTreeVoucherInfoFromSolidity(httpSolidityNode, sendNote.getTrxId(), - sendNote.getIndex(), 1); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.toJSONString().contains("tree")); - Assert.assertTrue(responseContent.toJSONString().contains("rt")); - Assert.assertTrue(responseContent.toJSONString().contains("paths")); - - response = HttpMethed - .getMerkleTreeVoucherInfoFromSolidity(httpSolidityNode, receiveNote.getTrxId(), - receiveNote.getIndex(), 1000); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.toJSONString().contains( - "synBlockNum is too large, cmBlockNum plus synBlockNum must be <= latestBlockNumber")); - } - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - response = HttpMethed.getAccount(httpnode, foundationZenTokenAddress); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - assetIssueId = responseContent.getString("asset_issued_ID"); - final Long assetBalance = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - HttpMethed - .transferAsset(httpnode, zenTokenOwnerAddress, foundationZenTokenAddress, assetIssueId, - assetBalance, zenTokenOwnerKey); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken006.java deleted file mode 100644 index 8cb5b71a406..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestZenToken006.java +++ /dev/null @@ -1,176 +0,0 @@ -package stest.tron.wallet.dailybuild.http; - -import com.alibaba.fastjson.JSONObject; -import java.util.ArrayList; -import java.util.List; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.Note; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.config.args.Args; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpTestZenToken006 { - - List shieldOutList = new ArrayList<>(); - String assetIssueId; - String sk; - String d1; - String ask; - String nsk; - String ovk; - String ak; - String nk; - String ivk; - String pkD1; - String paymentAddress1; - String rcm; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey1.getAddress(); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(0); - private String httpSolidityNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private String tokenId = zenTokenId; - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long costTokenAmount = 20 * zenTokenFee; - private Long sendTokenAmount = 8 * zenTokenFee; - private JSONObject responseContent; - private HttpResponse response; - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - Args.setFullNodeAllowShieldedTransaction(true); - PublicMethed.printAddress(foundationZenTokenKey); - PublicMethed.printAddress(zenTokenOwnerKey); - } - - @Test(enabled = false, description = "Get new shielded address by http") - public void test01GetNewShieldedAddress() { - response = HttpMethed.getNewShieldedAddress(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.size() == 10); - Assert.assertTrue(responseContent.containsKey("d")); - Assert.assertTrue(responseContent.containsKey("ovk")); - Assert.assertTrue(responseContent.containsKey("nsk")); - Assert.assertTrue(responseContent.containsKey("payment_address")); - Assert.assertTrue(responseContent.containsKey("sk")); - Assert.assertTrue(responseContent.containsKey("ask")); - Assert.assertTrue(responseContent.containsKey("pkD")); - Assert.assertTrue(responseContent.containsKey("ak")); - Assert.assertTrue(responseContent.containsKey("nk")); - Assert.assertTrue(responseContent.containsKey("ivk")); - - sk = responseContent.getString("sk"); - d1 = responseContent.getString("d"); - ask = responseContent.getString("ask"); - nsk = responseContent.getString("nsk"); - ovk = responseContent.getString("ovk"); - ak = responseContent.getString("ak"); - nk = responseContent.getString("nk"); - ivk = responseContent.getString("ivk"); - pkD1 = responseContent.getString("pkD"); - paymentAddress1 = responseContent.getString("payment_address"); - } - - @Test(enabled = false, description = "Get expanded spending key by http") - public void test02GetExpandedSpendingKey() { - response = HttpMethed.getExpandedSpendingKey(httpnode, sk); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - String askFromSk = responseContent.getString("ask"); - String nskFromSk = responseContent.getString("nsk"); - String ovkFromSk = responseContent.getString("ovk"); - Assert.assertEquals(ask, askFromSk); - Assert.assertEquals(nsk, nskFromSk); - Assert.assertEquals(ovk, ovkFromSk); - - } - - - @Test(enabled = false, description = "Get rcm by http") - public void test03GetRcm() { - response = HttpMethed.getRcm(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - rcm = responseContent.getString("value"); - logger.info("rcm: " + rcm); - } - - @Test(enabled = false, description = "Public to shield transaction withoutask by http") - public void test04PublicToShieldTransactionWithoutAsk() { - response = HttpMethed - .transferAsset(httpnode, foundationZenTokenAddress, zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenKey); - org.junit.Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - - response = HttpMethed.getAccount(httpnode, foundationZenTokenAddress); - responseContent = HttpMethed.parseResponseContent(response); - assetIssueId = responseContent.getString("asset_issued_ID"); - - final Long beforeAssetBalance = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - response = HttpMethed.getAccountReource(httpnode, zenTokenOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - final Long beforeNetUsed = responseContent.getLong("freeNetUsed"); - - String memo1 = "Shield memo11 in " + System.currentTimeMillis(); - Long sendSheldAddressAmount1 = zenTokenFee * 2; - Long sendAmount = sendSheldAddressAmount1 + zenTokenFee; - shieldOutList.clear(); - shieldOutList = HttpMethed - .addShieldOutputList(httpnode, shieldOutList, paymentAddress1, "" + sendSheldAddressAmount1, - memo1); - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSolidityNode); - response = HttpMethed - .sendShieldCoinWithoutAsk(httpnode, httpSolidityNode, httpnode, zenTokenOwnerAddress, - sendAmount, null, null, shieldOutList, null, 0, zenTokenOwnerKey); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - HttpMethed.waitToProduceOneBlock(httpnode); - Long afterAssetBalance = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - - response = HttpMethed.getAccountReource(httpnode, zenTokenOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - Long afterNetUsed = responseContent.getLong("freeNetUsed"); - - Assert.assertTrue(beforeAssetBalance - afterAssetBalance == sendAmount); - Assert.assertTrue(beforeNetUsed == afterNetUsed); - - } - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - final Long assetBalance = HttpMethed - .getAssetIssueValue(httpnode, zenTokenOwnerAddress, assetIssueId); - HttpMethed - .transferAsset(httpnode, zenTokenOwnerAddress, foundationZenTokenAddress, assetIssueId, - assetBalance, zenTokenOwnerKey); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction001.java deleted file mode 100644 index be2e605ae71..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction001.java +++ /dev/null @@ -1,503 +0,0 @@ -package stest.tron.wallet.dailybuild.internaltransaction; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j - -public class ContractInternalTransaction001 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] internalTxsAddress = ecKey1.getAddress(); - String testKeyForinternalTxsAddress = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKeyForinternalTxsAddress); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - logger.info(Long.toString(PublicMethed.queryAccount(testNetAccountKey, blockingStubFull) - .getBalance())); - } - - @Test(enabled = true, description = "Create->call.Two-level nesting") - public void testInternalTransaction001() { - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/" - + "contractInternalTransaction001testInternalTransaction001.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName1 = "C"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - - byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String txid = ""; - String initParmes = "\"" + Base58.encode58Check(contractAddress1) + "\""; - txid = PublicMethed.triggerContract(contractAddress, - "test1(address)", initParmes, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(7, transactionsCount); - dupInternalTrsansactionHash(infoById.get().getInternalTransactionsList()); - for (int i = 0; i < transactionsCount; i++) { - Assert.assertFalse(infoById.get().getInternalTransactions(i).getRejected()); - } - String initParmes2 = "\"" + Base58.encode58Check(contractAddress1) + "\",\"1\""; - String txid1 = PublicMethed.triggerContract(contractAddress, - "test2(address,uint256)", initParmes2, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - Assert.assertTrue(infoById1.get().getResultValue() == 0); - int transactionsCount1 = infoById1.get().getInternalTransactionsCount(); - Assert.assertEquals(10, transactionsCount1); - dupInternalTrsansactionHash(infoById1.get().getInternalTransactionsList()); - for (int i = 0; i < transactionsCount1; i++) { - Assert.assertFalse(infoById1.get().getInternalTransactions(i).getRejected()); - } - } - - @Test(enabled = true, description = "There is one internalTransaction.Only call") - public void testInternalTransaction002() { - Assert.assertTrue(PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/" - + "contractInternalTransaction001testInternalTransaction002.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName1 = "C"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String initParmes2 = "\"" + Base58.encode58Check(contractAddress1) + "\",\"1\""; - String txid1 = PublicMethed.triggerContract(contractAddress, - "test2(address,uint256)", initParmes2, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - Assert.assertTrue(infoById1.get().getResultValue() == 0); - int transactionsCount1 = infoById1.get().getInternalTransactionsCount(); - Assert.assertEquals(1, transactionsCount1); - dupInternalTrsansactionHash(infoById1.get().getInternalTransactionsList()); - Assert.assertFalse(infoById1.get().getInternalTransactions(0).getRejected()); - String note = ByteArray - .toStr(infoById1.get().getInternalTransactions(0).getNote().toByteArray()); - Assert.assertEquals("call", note); - Assert.assertEquals(1, - infoById1.get().getInternalTransactions(0).getCallValueInfo(0).getCallValue()); - - } - - @Test(enabled = true, description = "There is one internalTransaction.Only create") - public void testInternalTransaction003() { - Assert.assertTrue(PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/" - + "contractInternalTransaction001testInternalTransaction003.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String txid1 = PublicMethed.triggerContract(contractAddress, - "transfer()", "#", false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - Assert.assertTrue(infoById1.get().getResultValue() == 0); - int transactionsCount1 = infoById1.get().getInternalTransactionsCount(); - Assert.assertEquals(1, transactionsCount1); - dupInternalTrsansactionHash(infoById1.get().getInternalTransactionsList()); - - Assert.assertFalse(infoById1.get().getInternalTransactions(0).getRejected()); - String note = ByteArray - .toStr(infoById1.get().getInternalTransactions(0).getNote().toByteArray()); - Assert.assertEquals("create", note); - Assert.assertEquals(10, - infoById1.get().getInternalTransactions(0).getCallValueInfo(0).getCallValue()); - - } - - @Test(enabled = true, description = "Test suicide type in internalTransaction") - public void testInternalTransaction004() { - Assert.assertTrue(PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/" - + "contractInternalTransaction001testInternalTransaction004.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName1 = "B"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 0, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String txid = ""; - String initParmes = "\"" + Base58.encode58Check(contractAddress) - + "\",\"" + Base58.encode58Check(contractAddress1) + "\""; - txid = PublicMethed.triggerContract(contractAddress1, - "kill(address,address)", initParmes, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(2, transactionsCount); - dupInternalTrsansactionHash(infoById.get().getInternalTransactionsList()); - for (int i = 0; i < transactionsCount; i++) { - Assert.assertFalse(infoById.get().getInternalTransactions(i).getRejected()); - } - String note = ByteArray - .toStr(infoById.get().getInternalTransactions(0).getNote().toByteArray()); - String note1 = ByteArray - .toStr(infoById.get().getInternalTransactions(1).getNote().toByteArray()); - Long vaule1 = infoById.get().getInternalTransactions(0).getCallValueInfo(0).getCallValue(); - Long vaule2 = infoById.get().getInternalTransactions(1).getCallValueInfo(0).getCallValue(); - Assert.assertEquals("call", note); - Assert.assertEquals("suicide", note1); - Assert.assertTrue(0 == vaule1); - Assert.assertTrue(1000000L == vaule2); - - String txid1 = PublicMethed.triggerContract(contractAddress1, - "kill2()", "#", false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - Assert.assertTrue(infoById1.get().getResultValue() == 0); - int transactionsCount1 = infoById1.get().getInternalTransactionsCount(); - Assert.assertEquals(3, transactionsCount1); - dupInternalTrsansactionHash(infoById1.get().getInternalTransactionsList()); - String note3 = ByteArray - .toStr(infoById1.get().getInternalTransactions(0).getNote().toByteArray()); - String note4 = ByteArray - .toStr(infoById1.get().getInternalTransactions(1).getNote().toByteArray()); - String note5 = ByteArray - .toStr(infoById1.get().getInternalTransactions(2).getNote().toByteArray()); - Assert.assertEquals("create", note3); - Assert.assertEquals("call", note4); - Assert.assertEquals("suicide", note5); - for (int i = 0; i < transactionsCount1; i++) { - Assert.assertFalse(infoById1.get().getInternalTransactions(i).getRejected()); - Assert.assertEquals(0, - infoById1.get().getInternalTransactions(i).getCallValueInfo(0).getCallValue()); - - } - } - - @Test(enabled = true, description = "Type is create call") - public void testInternalTransaction005() { - Assert.assertTrue(PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/" - + "contractInternalTransaction001testInternalTransaction005.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String txid = ""; - - txid = PublicMethed.triggerContract(contractAddress, - "test1()", "#", false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 1); - int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(2, transactionsCount); - dupInternalTrsansactionHash(infoById.get().getInternalTransactionsList()); - for (int i = 0; i < transactionsCount; i++) { - Assert.assertTrue(infoById.get().getInternalTransactions(i).getRejected()); - } - String note = ByteArray - .toStr(infoById.get().getInternalTransactions(0).getNote().toByteArray()); - String note1 = ByteArray - .toStr(infoById.get().getInternalTransactions(1).getNote().toByteArray()); - Long vaule1 = infoById.get().getInternalTransactions(0).getCallValueInfo(0).getCallValue(); - Long vaule2 = infoById.get().getInternalTransactions(1).getCallValueInfo(0).getCallValue(); - Assert.assertEquals("create", note); - Assert.assertEquals("call", note1); - Assert.assertTrue(10 == vaule1); - Assert.assertTrue(0 == vaule2); - - String txid1 = PublicMethed.triggerContract(contractAddress, - "test2()", "#", false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - Assert.assertTrue(infoById1.get().getResultValue() == 1); - int transactionsCount1 = infoById1.get().getInternalTransactionsCount(); - Assert.assertEquals(2, transactionsCount1); - dupInternalTrsansactionHash(infoById1.get().getInternalTransactionsList()); - - String note3 = ByteArray - .toStr(infoById1.get().getInternalTransactions(0).getNote().toByteArray()); - String note4 = ByteArray - .toStr(infoById1.get().getInternalTransactions(1).getNote().toByteArray()); - - Long vaule3 = infoById1.get().getInternalTransactions(0).getCallValueInfo(0).getCallValue(); - Long vaule4 = infoById1.get().getInternalTransactions(1).getCallValueInfo(0).getCallValue(); - Assert.assertTrue(10 == vaule3); - Assert.assertTrue(0 == vaule4); - Assert.assertEquals("create", note3); - Assert.assertEquals("call", note4); - for (int i = 0; i < transactionsCount1; i++) { - Assert.assertTrue(infoById1.get().getInternalTransactions(i).getRejected()); - - - } - } - - @Test(enabled = true, description = "Type is create call call") - public void testInternalTransaction006() { - Assert.assertTrue(PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/" - + "contractInternalTransaction001testInternalTransaction006.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String txid = ""; - - txid = PublicMethed.triggerContract(contractAddress, - "test1()", "#", false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 1); - int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(3, transactionsCount); - dupInternalTrsansactionHash(infoById.get().getInternalTransactionsList()); - - for (int i = 0; i < transactionsCount; i++) { - Assert.assertTrue(infoById.get().getInternalTransactions(i).getRejected()); - } - String note = ByteArray - .toStr(infoById.get().getInternalTransactions(0).getNote().toByteArray()); - String note1 = ByteArray - .toStr(infoById.get().getInternalTransactions(1).getNote().toByteArray()); - String note2 = ByteArray - .toStr(infoById.get().getInternalTransactions(1).getNote().toByteArray()); - Long vaule1 = infoById.get().getInternalTransactions(0).getCallValueInfo(0).getCallValue(); - Long vaule2 = infoById.get().getInternalTransactions(1).getCallValueInfo(0).getCallValue(); - Long vaule3 = infoById.get().getInternalTransactions(2).getCallValueInfo(0).getCallValue(); - - Assert.assertEquals("create", note); - Assert.assertEquals("call", note1); - Assert.assertEquals("call", note2); - Assert.assertTrue(10 == vaule1); - Assert.assertTrue(0 == vaule2); - Assert.assertTrue(0 == vaule3); - - String txid1 = PublicMethed.triggerContract(contractAddress, - "test2()", "#", false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - Assert.assertTrue(infoById1.get().getResultValue() == 1); - int transactionsCount1 = infoById1.get().getInternalTransactionsCount(); - Assert.assertEquals(3, transactionsCount1); - dupInternalTrsansactionHash(infoById1.get().getInternalTransactionsList()); - - String note4 = ByteArray - .toStr(infoById1.get().getInternalTransactions(0).getNote().toByteArray()); - String note5 = ByteArray - .toStr(infoById1.get().getInternalTransactions(1).getNote().toByteArray()); - String note6 = ByteArray - .toStr(infoById1.get().getInternalTransactions(2).getNote().toByteArray()); - Long vaule4 = infoById1.get().getInternalTransactions(0).getCallValueInfo(0).getCallValue(); - Long vaule5 = infoById1.get().getInternalTransactions(1).getCallValueInfo(0).getCallValue(); - Long vaule6 = infoById1.get().getInternalTransactions(2).getCallValueInfo(0).getCallValue(); - - Assert.assertTrue(10 == vaule4); - Assert.assertTrue(0 == vaule5); - Assert.assertTrue(0 == vaule6); - Assert.assertEquals("create", note4); - Assert.assertEquals("call", note5); - Assert.assertEquals("call", note6); - - for (int i = 0; i < transactionsCount1; i++) { - Assert.assertTrue(infoById1.get().getInternalTransactions(i).getRejected()); - } - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(internalTxsAddress, testKeyForinternalTxsAddress, testNetAccountAddress, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - - /** - * constructor. - */ - - public void dupInternalTrsansactionHash( - List internalTransactionList) { - List hashList = new ArrayList<>(); - internalTransactionList.forEach( - internalTransaction -> hashList - .add(Hex.toHexString(internalTransaction.getHash().toByteArray()))); - List dupHash = hashList.stream() - .collect(Collectors.toMap(e -> e, e -> 1, (a, b) -> a + b)) - .entrySet().stream().filter(entry -> entry.getValue() > 1).map(entry -> entry.getKey()) - .collect(Collectors.toList()); - Assert.assertEquals(dupHash.size(), 0); - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction002.java deleted file mode 100644 index 8f52fc059ea..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction002.java +++ /dev/null @@ -1,580 +0,0 @@ -package stest.tron.wallet.dailybuild.internaltransaction; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j - -public class ContractInternalTransaction002 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] internalTxsAddress = ecKey1.getAddress(); - String testKeyForinternalTxsAddress = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKeyForinternalTxsAddress); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - logger.info(Long.toString(PublicMethed.queryAccount(testNetAccountKey, blockingStubFull) - .getBalance())); - } - - - @Test(enabled = true, description = "Type is create create call call") - public void test1InternalTransaction007() { - Assert.assertTrue(PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/" - + "contractInternalTransaction002test1InternalTransaction007.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName1 = "C"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String initParmes = "\"" + Base58.encode58Check(contractAddress1) + "\""; - - String txid = ""; - - txid = PublicMethed.triggerContract(contractAddress, - "test1(address)", initParmes, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertNotNull(infoById); - Assert.assertTrue(infoById.get().getResultValue() == 1); - int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(4, transactionsCount); - dupInternalTrsansactionHash(infoById.get().getInternalTransactionsList()); - for (int i = 0; i < transactionsCount; i++) { - Assert.assertTrue(infoById.get().getInternalTransactions(i).getRejected()); - } - String note = ByteArray - .toStr(infoById.get().getInternalTransactions(0).getNote().toByteArray()); - String note1 = ByteArray - .toStr(infoById.get().getInternalTransactions(1).getNote().toByteArray()); - String note2 = ByteArray - .toStr(infoById.get().getInternalTransactions(2).getNote().toByteArray()); - String note3 = ByteArray - .toStr(infoById.get().getInternalTransactions(3).getNote().toByteArray()); - Long vaule1 = infoById.get().getInternalTransactions(0).getCallValueInfo(0).getCallValue(); - Long vaule2 = infoById.get().getInternalTransactions(1).getCallValueInfo(0).getCallValue(); - Long vaule3 = infoById.get().getInternalTransactions(2).getCallValueInfo(0).getCallValue(); - Long vaule4 = infoById.get().getInternalTransactions(3).getCallValueInfo(0).getCallValue(); - Assert.assertEquals("create", note); - Assert.assertEquals("create", note1); - Assert.assertEquals("call", note2); - Assert.assertEquals("call", note3); - Assert.assertTrue(10 == vaule1); - Assert.assertTrue(0 == vaule2); - Assert.assertTrue(5 == vaule3); - Assert.assertTrue(0 == vaule4); - String initParmes1 = "\"" + Base58.encode58Check(contractAddress1) + "\",\"1\""; - String txid1 = PublicMethed.triggerContract(contractAddress, - "test2(address,uint256)", initParmes1, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - Assert.assertTrue(infoById1.get().getResultValue() == 0); - int transactionsCount1 = infoById1.get().getInternalTransactionsCount(); - Assert.assertEquals(1, transactionsCount1); - dupInternalTrsansactionHash(infoById1.get().getInternalTransactionsList()); - - String note5 = ByteArray - .toStr(infoById1.get().getInternalTransactions(0).getNote().toByteArray()); - Long vaule5 = infoById1.get().getInternalTransactions(0).getCallValueInfo(0).getCallValue(); - Assert.assertTrue(1 == vaule5); - Assert.assertEquals("call", note5); - Assert.assertTrue(infoById1.get().getInternalTransactions(0).getRejected()); - - - } - - @Test(enabled = true, description = "Type is call call") - public void test2InternalTransaction008() { - Assert.assertTrue(PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/" - + "contractInternalTransaction002test2InternalTransaction008.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "B"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String initParmes = "\"" + Base58.encode58Check(contractAddress1) + "\",\"1\""; - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "testAssert(address,uint256)", initParmes, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(2, transactionsCount); - dupInternalTrsansactionHash(infoById.get().getInternalTransactionsList()); - Assert.assertTrue(infoById.get().getInternalTransactions(0).getRejected()); - Assert.assertFalse(infoById.get().getInternalTransactions(1).getRejected()); - - String note = ByteArray - .toStr(infoById.get().getInternalTransactions(0).getNote().toByteArray()); - String note1 = ByteArray - .toStr(infoById.get().getInternalTransactions(1).getNote().toByteArray()); - Long vaule1 = infoById.get().getInternalTransactions(0).getCallValueInfo(0).getCallValue(); - Long vaule2 = infoById.get().getInternalTransactions(1).getCallValueInfo(0).getCallValue(); - Assert.assertEquals("call", note); - Assert.assertEquals("call", note1); - Assert.assertTrue(1 == vaule1); - Assert.assertTrue(1 == vaule2); - String contractName2 = "C"; - HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); - String code2 = retMap2.get("byteCode").toString(); - String abi2 = retMap2.get("abI").toString(); - - byte[] contractAddress2 = PublicMethed - .deployContract(contractName2, abi2, code2, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String initParmes1 = "\"" + Base58.encode58Check(contractAddress2) + "\",\"1\""; - String txid1 = PublicMethed.triggerContract(contractAddress, - "testRequire(address,uint256)", initParmes1, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - Assert.assertTrue(infoById1.get().getResultValue() == 0); - int transactionsCount1 = infoById1.get().getInternalTransactionsCount(); - Assert.assertEquals(2, transactionsCount1); - dupInternalTrsansactionHash(infoById1.get().getInternalTransactionsList()); - Assert.assertTrue(infoById1.get().getInternalTransactions(0).getRejected()); - Assert.assertFalse(infoById1.get().getInternalTransactions(1).getRejected()); - String note2 = ByteArray - .toStr(infoById1.get().getInternalTransactions(0).getNote().toByteArray()); - String note3 = ByteArray - .toStr(infoById1.get().getInternalTransactions(1).getNote().toByteArray()); - Long vaule3 = infoById1.get().getInternalTransactions(0).getCallValueInfo(0).getCallValue(); - Long vaule4 = infoById1.get().getInternalTransactions(1).getCallValueInfo(0).getCallValue(); - Assert.assertEquals("call", note2); - Assert.assertEquals("call", note3); - Assert.assertTrue(1 == vaule3); - Assert.assertTrue(1 == vaule4); - - String txid2 = PublicMethed.triggerContract(contractAddress, - "testAssert1(address,uint256)", initParmes, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById2 = null; - infoById2 = PublicMethed.getTransactionInfoById(txid2, blockingStubFull); - Assert.assertTrue(infoById2.get().getResultValue() == 0); - int transactionsCount2 = infoById2.get().getInternalTransactionsCount(); - Assert.assertEquals(2, transactionsCount2); - dupInternalTrsansactionHash(infoById2.get().getInternalTransactionsList()); - Assert.assertFalse(infoById2.get().getInternalTransactions(0).getRejected()); - Assert.assertTrue(infoById2.get().getInternalTransactions(1).getRejected()); - - String note5 = ByteArray - .toStr(infoById2.get().getInternalTransactions(0).getNote().toByteArray()); - String note6 = ByteArray - .toStr(infoById2.get().getInternalTransactions(1).getNote().toByteArray()); - Long vaule5 = infoById2.get().getInternalTransactions(0).getCallValueInfo(0).getCallValue(); - Long vaule6 = infoById2.get().getInternalTransactions(1).getCallValueInfo(0).getCallValue(); - Assert.assertEquals("call", note5); - Assert.assertEquals("call", note6); - Assert.assertTrue(1 == vaule5); - Assert.assertTrue(1 == vaule6); - - String txid3 = PublicMethed.triggerContract(contractAddress, - "testtRequire2(address,uint256)", initParmes1, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById3 = null; - infoById3 = PublicMethed.getTransactionInfoById(txid3, blockingStubFull); - Assert.assertTrue(infoById3.get().getResultValue() == 0); - int transactionsCount3 = infoById3.get().getInternalTransactionsCount(); - Assert.assertEquals(2, transactionsCount3); - dupInternalTrsansactionHash(infoById3.get().getInternalTransactionsList()); - - Assert.assertFalse(infoById3.get().getInternalTransactions(0).getRejected()); - Assert.assertTrue(infoById3.get().getInternalTransactions(1).getRejected()); - String note7 = ByteArray - .toStr(infoById3.get().getInternalTransactions(0).getNote().toByteArray()); - String note8 = ByteArray - .toStr(infoById3.get().getInternalTransactions(1).getNote().toByteArray()); - Long vaule7 = infoById3.get().getInternalTransactions(0).getCallValueInfo(0).getCallValue(); - Long vaule8 = infoById3.get().getInternalTransactions(1).getCallValueInfo(0).getCallValue(); - Assert.assertEquals("call", note7); - Assert.assertEquals("call", note8); - Assert.assertTrue(1 == vaule7); - Assert.assertTrue(1 == vaule8); - - } - - @Test(enabled = true, description = "Test suicide type in internalTransaction after call") - public void test3InternalTransaction009() { - Assert.assertTrue(PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/" - + "contractInternalTransaction002test3InternalTransaction009.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "B"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName2 = "C"; - HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); - String code2 = retMap2.get("byteCode").toString(); - String abi2 = retMap2.get("abI").toString(); - byte[] contractAddress2 = PublicMethed - .deployContract(contractName2, abi2, code2, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName3 = "D"; - HashMap retMap3 = PublicMethed.getBycodeAbi(filePath, contractName3); - String code3 = retMap3.get("byteCode").toString(); - String abi3 = retMap3.get("abI").toString(); - byte[] contractAddress3 = PublicMethed - .deployContract(contractName3, abi3, code3, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String initParmes = "\"" + Base58.encode58Check(contractAddress2) - + "\",\"" + Base58.encode58Check(contractAddress3) + "\",\"" + Base58 - .encode58Check(contractAddress1) + "\""; - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "test1(address,address,address)", initParmes, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(7, transactionsCount); - dupInternalTrsansactionHash(infoById.get().getInternalTransactionsList()); - for (int i = 0; i < transactionsCount; i++) { - Assert.assertFalse(infoById.get().getInternalTransactions(i).getRejected()); - } - - String note = ByteArray - .toStr(infoById.get().getInternalTransactions(0).getNote().toByteArray()); - String note1 = ByteArray - .toStr(infoById.get().getInternalTransactions(1).getNote().toByteArray()); - String note2 = ByteArray - .toStr(infoById.get().getInternalTransactions(6).getNote().toByteArray()); - Long vaule1 = infoById.get().getInternalTransactions(0).getCallValueInfo(0).getCallValue(); - Long vaule2 = infoById.get().getInternalTransactions(1).getCallValueInfo(0).getCallValue(); - Assert.assertEquals("create", note); - Assert.assertEquals("call", note1); - Assert.assertEquals("suicide", note2); - Assert.assertTrue(10 == vaule1); - Assert.assertTrue(5 == vaule2); - - String txid1 = ""; - txid1 = PublicMethed.triggerContract(contractAddress, - "test1(address,address,address)", initParmes, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - Assert.assertTrue(infoById1.get().getResultValue() == 0); - int transactionsCount1 = infoById1.get().getInternalTransactionsCount(); - Assert.assertEquals(6, transactionsCount1); - dupInternalTrsansactionHash(infoById1.get().getInternalTransactionsList()); - - for (int i = 0; i < transactionsCount1; i++) { - Assert.assertFalse(infoById.get().getInternalTransactions(i).getRejected()); - } - } - - @Test(enabled = false, description = "Test maxfeelimit can trigger create type max time") - public void test4InternalTransaction010() { - Assert.assertTrue(PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/" - + "contractInternalTransaction002test4InternalTransaction010.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "transfer()", "#", false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(76, transactionsCount); - dupInternalTrsansactionHash(infoById.get().getInternalTransactionsList()); - - for (int i = 0; i < transactionsCount; i++) { - Assert.assertFalse(infoById.get().getInternalTransactions(i).getRejected()); - Assert.assertEquals("create", ByteArray - .toStr(infoById.get().getInternalTransactions(i).getNote().toByteArray())); - Assert.assertEquals(1, - infoById.get().getInternalTransactions(i).getCallValueInfo(0).getCallValue()); - } - PublicMethed.waitProduceNextBlock(blockingStubFull); - String txid1 = PublicMethed.triggerContract(contractAddress, - "transfer2()", "#", false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - Assert.assertTrue(infoById1.get().getResultValue() == 1); - int transactionsCount1 = infoById1.get().getInternalTransactionsCount(); - Assert.assertEquals(76, transactionsCount1); - dupInternalTrsansactionHash(infoById1.get().getInternalTransactionsList()); - - for (int i = 0; i < transactionsCount1; i++) { - Assert.assertTrue(infoById1.get().getInternalTransactions(i).getRejected()); - Assert.assertEquals("create", ByteArray - .toStr(infoById1.get().getInternalTransactions(i).getNote().toByteArray())); - Assert.assertEquals(1, - infoById1.get().getInternalTransactions(i).getCallValueInfo(0).getCallValue()); - - } - - - } - - - @Test(enabled = true, description = "Type is call create->call->call.Three-level nesting") - public void test5InternalTransaction012() { - Assert.assertTrue(PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/" - + "contractInternalTransaction002test5InternalTransaction012.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "B"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName2 = "E"; - HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); - String code2 = retMap1.get("byteCode").toString(); - String abi2 = retMap1.get("abI").toString(); - byte[] contractAddress2 = PublicMethed - .deployContract(contractName2, abi2, code2, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String initParmes = "\"" + Base58.encode58Check(contractAddress1) - + "\",\"" + Base58.encode58Check(contractAddress2) + "\""; - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "test1(address,address)", initParmes, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(4, transactionsCount); - dupInternalTrsansactionHash(infoById.get().getInternalTransactionsList()); - for (int i = 0; i < transactionsCount; i++) { - Assert.assertFalse(infoById.get().getInternalTransactions(i).getRejected()); - } - - String note = ByteArray - .toStr(infoById.get().getInternalTransactions(0).getNote().toByteArray()); - String note1 = ByteArray - .toStr(infoById.get().getInternalTransactions(1).getNote().toByteArray()); - String note2 = ByteArray - .toStr(infoById.get().getInternalTransactions(2).getNote().toByteArray()); - String note3 = ByteArray - .toStr(infoById.get().getInternalTransactions(3).getNote().toByteArray()); - Assert.assertEquals("call", note); - Assert.assertEquals("create", note1); - Assert.assertEquals("call", note2); - Assert.assertEquals("call", note3); - - Long vaule1 = infoById.get().getInternalTransactions(0).getCallValueInfo(0).getCallValue(); - Long vaule2 = infoById.get().getInternalTransactions(1).getCallValueInfo(0).getCallValue(); - Long vaule3 = infoById.get().getInternalTransactions(2).getCallValueInfo(0).getCallValue(); - Long vaule4 = infoById.get().getInternalTransactions(3).getCallValueInfo(0).getCallValue(); - Assert.assertTrue(1 == vaule1); - Assert.assertTrue(1000 == vaule2); - Assert.assertTrue(0 == vaule3); - Assert.assertTrue(1 == vaule4); - - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(internalTxsAddress, testKeyForinternalTxsAddress, testNetAccountAddress, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - - /** - * constructor. - */ - - public void dupInternalTrsansactionHash( - List internalTransactionList) { - List hashList = new ArrayList<>(); - internalTransactionList.forEach( - internalTransaction -> hashList - .add(Hex.toHexString(internalTransaction.getHash().toByteArray()))); - List dupHash = hashList.stream() - .collect(Collectors.toMap(e -> e, e -> 1, (a, b) -> a + b)) - .entrySet().stream().filter(entry -> entry.getValue() > 1).map(entry -> entry.getKey()) - .collect(Collectors.toList()); - Assert.assertEquals(dupHash.size(), 0); - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction003.java deleted file mode 100644 index 56408c239d6..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction003.java +++ /dev/null @@ -1,584 +0,0 @@ -package stest.tron.wallet.dailybuild.internaltransaction; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.Retry; - -@Slf4j - -public class ContractInternalTransaction003 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] internalTxsAddress = ecKey1.getAddress(); - String testKeyForinternalTxsAddress = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKeyForinternalTxsAddress); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - logger.info(Long.toString(PublicMethed.queryAccount(testNetAccountKey, blockingStubFull) - .getBalance())); - } - - - @Test(enabled = true, description = "Three-level nesting.Type is Create call->call->create") - public void testInternalTransaction013() { - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/" - + "contractInternalTransaction003testInternalTransaction013.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "D"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String initParmes = "\"" + Base58.encode58Check(contractAddress1) + "\""; - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "test1(address)", initParmes, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(4, transactionsCount); - for (int i = 0; i < transactionsCount; i++) { - Assert.assertFalse(infoById.get().getInternalTransactions(i).getRejected()); - } - dupInternalTrsansactionHash(infoById.get().getInternalTransactionsList()); - String note = ByteArray - .toStr(infoById.get().getInternalTransactions(0).getNote().toByteArray()); - String note1 = ByteArray - .toStr(infoById.get().getInternalTransactions(1).getNote().toByteArray()); - String note2 = ByteArray - .toStr(infoById.get().getInternalTransactions(2).getNote().toByteArray()); - String note3 = ByteArray - .toStr(infoById.get().getInternalTransactions(3).getNote().toByteArray()); - Assert.assertEquals("create", note); - Assert.assertEquals("call", note1); - Assert.assertEquals("call", note2); - Assert.assertEquals("create", note3); - Long vaule1 = infoById.get().getInternalTransactions(0).getCallValueInfo(0).getCallValue(); - Long vaule2 = infoById.get().getInternalTransactions(1).getCallValueInfo(0).getCallValue(); - Long vaule3 = infoById.get().getInternalTransactions(2).getCallValueInfo(0).getCallValue(); - Long vaule4 = infoById.get().getInternalTransactions(3).getCallValueInfo(0).getCallValue(); - Assert.assertTrue(10 == vaule1); - Assert.assertTrue(0 == vaule2); - Assert.assertTrue(2 == vaule3); - Assert.assertTrue(5 == vaule4); - - - } - - - @Test(enabled = true, description = "Test delegatecall and callcode.") - public void testInternalTransaction014() { - Assert.assertTrue(PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/" - + "contractInternalTransaction003testInternalTransaction014.sol"; - String contractName = "callerContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName1 = "calledContract"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName2 = "c"; - HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); - String code2 = retMap2.get("byteCode").toString(); - String abi2 = retMap2.get("abI").toString(); - byte[] contractAddress2 = PublicMethed - .deployContract(contractName2, abi2, code2, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String initParmes = "\"" + Base58.encode58Check(contractAddress1) - + "\",\"" + Base58.encode58Check(contractAddress2) + "\""; - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "sendToB(address,address)", initParmes, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(2, transactionsCount); - for (int i = 0; i < transactionsCount; i++) { - Assert.assertFalse(infoById.get().getInternalTransactions(i).getRejected()); - Assert.assertEquals("call", ByteArray - .toStr(infoById.get().getInternalTransactions(i).getNote().toByteArray())); - } - Assert.assertEquals(ByteArray - .toHexString(infoById.get().getInternalTransactions(0).getCallerAddress() - .toByteArray()), - ByteArray.toHexString( - infoById.get().getInternalTransactions(0).getTransferToAddress().toByteArray())); - - Assert.assertEquals(ByteArray - .toHexString(contractAddress2), - ByteArray.toHexString( - infoById.get().getInternalTransactions(1).getTransferToAddress().toByteArray())); - String txid2 = ""; - txid2 = PublicMethed.triggerContract(contractAddress, - "sendToB2(address,address)", initParmes, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById2 = null; - infoById2 = PublicMethed.getTransactionInfoById(txid2, blockingStubFull); - Assert.assertTrue(infoById2.get().getResultValue() == 0); - int transactionsCount2 = infoById2.get().getInternalTransactionsCount(); - Assert.assertEquals(2, transactionsCount2); - for (int i = 0; i < transactionsCount2; i++) { - Assert.assertFalse(infoById2.get().getInternalTransactions(i).getRejected()); - Assert.assertEquals("call", ByteArray - .toStr(infoById2.get().getInternalTransactions(i).getNote().toByteArray())); - } - Assert.assertEquals(ByteArray - .toHexString(contractAddress), - ByteArray.toHexString( - infoById2.get().getInternalTransactions(0).getCallerAddress().toByteArray())); - Assert.assertEquals(ByteArray - .toHexString(contractAddress1), - ByteArray.toHexString( - infoById2.get().getInternalTransactions(0).getTransferToAddress().toByteArray())); - Assert.assertEquals(ByteArray - .toHexString(contractAddress1), - ByteArray.toHexString( - infoById2.get().getInternalTransactions(1).getCallerAddress().toByteArray())); - Assert.assertEquals(ByteArray - .toHexString(contractAddress2), - ByteArray.toHexString( - infoById2.get().getInternalTransactions(1).getTransferToAddress().toByteArray())); - - String txid3 = ""; - txid3 = PublicMethed.triggerContract(contractAddress, - "sendToB3(address,address)", initParmes, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById3 = null; - infoById3 = PublicMethed.getTransactionInfoById(txid3, blockingStubFull); - Assert.assertTrue(infoById3.get().getResultValue() == 0); - int transactionsCount3 = infoById3.get().getInternalTransactionsCount(); - Assert.assertEquals(2, transactionsCount3); - for (int i = 0; i < transactionsCount3; i++) { - Assert.assertFalse(infoById3.get().getInternalTransactions(i).getRejected()); - Assert.assertEquals("call", ByteArray - .toStr(infoById3.get().getInternalTransactions(i).getNote().toByteArray())); - } - Assert.assertEquals(ByteArray - .toHexString(infoById3.get().getInternalTransactions(0).getCallerAddress() - .toByteArray()), - ByteArray.toHexString( - infoById3.get().getInternalTransactions(0).getTransferToAddress().toByteArray())); - Assert.assertEquals(ByteArray - .toHexString(contractAddress2), - ByteArray.toHexString( - infoById3.get().getInternalTransactions(1).getTransferToAddress().toByteArray())); - dupInternalTrsansactionHash(infoById.get().getInternalTransactionsList()); - dupInternalTrsansactionHash(infoById2.get().getInternalTransactionsList()); - dupInternalTrsansactionHash(infoById3.get().getInternalTransactionsList()); - - } - - @Test(enabled = true, description = "Three-level nesting.Type " - + "is create call->call->create call->suicide") - public void testInternalTransaction015() { - Assert.assertTrue(PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/" - + "contractInternalTransaction003testInternalTransaction015.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "D"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName2 = "E"; - HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); - String code2 = retMap2.get("byteCode").toString(); - String abi2 = retMap2.get("abI").toString(); - byte[] contractAddress2 = PublicMethed - .deployContract(contractName2, abi2, code2, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String initParmes = "\"" + Base58.encode58Check(contractAddress1) - + "\",\"" + Base58.encode58Check(contractAddress2) + "\""; - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "test1(address,address)", initParmes, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(6, transactionsCount); - dupInternalTrsansactionHash(infoById.get().getInternalTransactionsList()); - - - } - - - @Test(enabled = false, description = "After create 80 times,then suicide") - public void testInternalTransaction016() { - Assert.assertTrue(PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/" - + "contractInternalTransaction003testInternalTransaction016.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "transfer()", "#", false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(69, transactionsCount); - for (int i = 0; i < transactionsCount; i++) { - Assert.assertFalse(infoById.get().getInternalTransactions(i).getRejected()); - } - Assert.assertEquals("suicide", ByteArray - .toStr(infoById.get().getInternalTransactions(68).getNote().toByteArray())); - Assert.assertEquals("call", ByteArray - .toStr(infoById.get().getInternalTransactions(67).getNote().toByteArray())); - Assert.assertEquals(0, - infoById.get().getInternalTransactions(67).getCallValueInfo(0).getCallValue()); - Assert.assertEquals(1, - infoById.get().getInternalTransactions(68).getCallValueInfo(0).getCallValue()); - for (int i = 0; i < transactionsCount - 2; i++) { - Assert.assertEquals("create", ByteArray - .toStr(infoById.get().getInternalTransactions(i).getNote().toByteArray())); - Assert.assertEquals(1, - infoById.get().getInternalTransactions(i).getCallValueInfo(0).getCallValue()); - } - String txid1 = ""; - txid1 = PublicMethed.triggerContract(contractAddress, - "transfer2()", "#", false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - int transactionsCount1 = infoById1.get().getInternalTransactionsCount(); - - Assert.assertEquals(68, transactionsCount1); - for (int i = 0; i < transactionsCount1; i++) { - Assert.assertTrue(infoById1.get().getInternalTransactions(i).getRejected()); - Assert.assertEquals("create", ByteArray - .toStr(infoById1.get().getInternalTransactions(i).getNote().toByteArray())); - - } - dupInternalTrsansactionHash(infoById.get().getInternalTransactionsList()); - dupInternalTrsansactionHash(infoById1.get().getInternalTransactionsList()); - - } - - @Test(enabled = false, description = "After create 88 times,then suicide") - public void testInternalTransaction017() { - Assert.assertTrue(PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/" - + "contractInternalTransaction003testInternalTransaction017.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String initParmes = "\"" + Base58.encode58Check(contractAddress) + "\""; - - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "transfer(address)", initParmes, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(77, transactionsCount); - for (int i = 0; i < transactionsCount; i++) { - Assert.assertFalse(infoById.get().getInternalTransactions(i).getRejected()); - } - Assert.assertEquals("suicide", ByteArray - .toStr(infoById.get().getInternalTransactions(76).getNote().toByteArray())); - Assert.assertEquals(1000000 - 76, - infoById.get().getInternalTransactions(76).getCallValueInfo(0).getCallValue()); - for (int i = 0; i < transactionsCount - 1; i++) { - Assert.assertEquals("create", ByteArray - .toStr(infoById.get().getInternalTransactions(i).getNote().toByteArray())); - Assert.assertEquals(1, - infoById.get().getInternalTransactions(i).getCallValueInfo(0).getCallValue()); - } - dupInternalTrsansactionHash(infoById.get().getInternalTransactionsList()); - } - - @Test(enabled = true,retryAnalyzer = Retry.class, - description = "Test maxfeelimit can trigger call create call max time") - public void testInternalTransaction018() { - Assert.assertTrue(PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/" - + "contractInternalTransaction003testInternalTransaction018.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "B"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName2 = "E"; - HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); - - String code2 = retMap2.get("byteCode").toString(); - String abi2 = retMap2.get("abI").toString(); - byte[] contractAddress2 = PublicMethed - .deployContract(contractName2, abi2, code2, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed - .sendcoin(internalTxsAddress, 2000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String initParmes = "\"" + Base58.encode58Check(contractAddress1) - + "\",\"" + Base58.encode58Check(contractAddress2) + "\""; - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "test1(address,address)", initParmes, false, - 100000, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("InfoById:" + infoById); - - int retryTimes = 1; - while (retryTimes++ < 5 && infoById.get().getResultValue() != 0) { - // retry 5 times - txid = PublicMethed.triggerContract(contractAddress, - "test1(address,address)", initParmes, false, - 100000, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("InfoById retry " + retryTimes + " : " + infoById); - } - - - - Assert.assertEquals(0, infoById.get().getResultValue()); - int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(184, transactionsCount); - for (int i = 0; i < transactionsCount; i++) { - Assert.assertFalse(infoById.get().getInternalTransactions(i).getRejected()); - } - dupInternalTrsansactionHash(infoById.get().getInternalTransactionsList()); - String note = ByteArray - .toStr(infoById.get().getInternalTransactions(0).getNote().toByteArray()); - String note1 = ByteArray - .toStr(infoById.get().getInternalTransactions(1).getNote().toByteArray()); - String note2 = ByteArray - .toStr(infoById.get().getInternalTransactions(2).getNote().toByteArray()); - String note3 = ByteArray - .toStr(infoById.get().getInternalTransactions(3).getNote().toByteArray()); - Long vaule1 = infoById.get().getInternalTransactions(0).getCallValueInfo(0).getCallValue(); - Long vaule2 = infoById.get().getInternalTransactions(1).getCallValueInfo(0).getCallValue(); - Long vaule3 = infoById.get().getInternalTransactions(2).getCallValueInfo(0).getCallValue(); - Long vaule4 = infoById.get().getInternalTransactions(3).getCallValueInfo(0).getCallValue(); - - Assert.assertEquals("call", note); - Assert.assertEquals("create", note1); - Assert.assertEquals("call", note2); - Assert.assertEquals("call", note3); - Assert.assertTrue(1 == vaule1); - Assert.assertTrue(100 == vaule2); - Assert.assertTrue(0 == vaule3); - Assert.assertTrue(1 == vaule4); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(internalTxsAddress, testKeyForinternalTxsAddress, testNetAccountAddress, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - - /** - * constructor. - */ - - public void dupInternalTrsansactionHash( - List internalTransactionList) { - List hashList = new ArrayList<>(); - internalTransactionList.forEach( - internalTransaction -> hashList - .add(Hex.toHexString(internalTransaction.getHash().toByteArray()))); - List dupHash = hashList.stream() - .collect(Collectors.toMap(e -> e, e -> 1, (a, b) -> a + b)) - .entrySet().stream().filter(entry -> entry.getValue() > 1).map(entry -> entry.getKey()) - .collect(Collectors.toList()); - Assert.assertEquals(dupHash.size(), 0); - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts001.java deleted file mode 100644 index fd22c9bb213..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts001.java +++ /dev/null @@ -1,1225 +0,0 @@ -package stest.tron.wallet.dailybuild.jsonrpc; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.utils.ByteArray; -import org.tron.protos.Protocol.Block; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.JsonRpcBase; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Accounts001 extends JsonRpcBase { - private JSONObject responseContent; - private HttpResponse response; - String realGasPrice; - String bid = null; - int indexNum = 0; - String indexHex = null; - JSONObject result = null; - String transacionHash = null; - String blockHash = null; - String blockNumHex = null; - String parentHash = null; - String txTrieRoot = null; - String witnessAddress = null; - String feeLimit = null; - String accountStateRoot = null; - String energyUsed = "0x135c6"; - - List transactionIdList = null; - long size = 0; - long gas = 0; - long blockTimeStamp = 0; - long gasPriceFromHttp = 0; - - /** constructor. */ - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Json rpc api of eth_accounts") - public void test01JsonRpcApiTestForEthAccounts() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_accounts", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - List result = new ArrayList(); - logger.info(String.valueOf(result)); - Assert.assertEquals(responseContent.get("result"), result); - } - - @Test(enabled = true, description = "Json rpc api of eth_blockNumber") - public void test02JsonRpcApiTestForEthBlockNumber() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_blockNumber", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - responseContent.get("result"); - String blockNum = responseContent.getString("result").substring(2); - long blockNumFromJsonRpcNode = Long.parseLong(blockNum, 16); - response = HttpMethed.getNowBlock(httpFullNode); - responseContent = HttpMethed.parseResponseContent(response); - long blockNumFromHttp = - responseContent.getJSONObject("block_header").getJSONObject("raw_data").getLong("number"); - logger.info("blocknumFromJsonRpcNode:" + blockNumFromJsonRpcNode); - logger.info("blocknumFromHttp:" + blockNumFromHttp); - Assert.assertTrue(Math.abs(blockNumFromJsonRpcNode - blockNumFromHttp) <= 3); - } - - @Test(enabled = true, description = "Json rpc api of eth_call") - public void test03JsonRpcApiTestForEthCall() throws Exception { - JsonObject param = new JsonObject(); - HttpMethed.waitToProduceOneBlock(httpFullNode); - param.addProperty("from", ByteArray.toHexString(jsonRpcOwnerAddress)); - param.addProperty("to", trc20AddressHex); - param.addProperty("gas", "0x0"); - param.addProperty("gasPrice", "0x0"); - param.addProperty("value", "0x0"); - param.addProperty("data", "0x06fdde03"); - JsonArray params = new JsonArray(); - params.add(param); - params.add("latest"); - JsonObject requestBody = getJsonRpcBody("eth_call", params); - logger.info("03params:" + params); - logger.info("requestBody:" + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String dataResult = responseContent.getString("result"); - Assert.assertEquals( - "0x000000000000000000000000000000000000000000000000000" - + "00000000000200000000000000000000000000000000000000000" - + "00000000000000000000000a546f6b656e5452433230000000000" - + "00000000000000000000000000000000000", - dataResult); - } - - @Test(enabled = true, description = "Json rpc api of eth_chainId") - public void test04JsonRpcApiTestForEthChainId() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_chainId", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - responseContent.get("result"); - String blockIdFromJsonRpcNode = responseContent.get("result").toString().substring(2); - response = HttpMethed.getBlockByNum(httpFullNode, 0); - responseContent = HttpMethed.parseResponseContent(response); - String blockIdFromHttp = responseContent.getString("blockID").substring(56); - logger.info("blockIdFromJsonRpcNode:" + blockIdFromJsonRpcNode); - logger.info("blockIdFromHttp:" + blockIdFromHttp); - Assert.assertEquals(blockIdFromJsonRpcNode, blockIdFromHttp); - } - - @Test(enabled = true, description = "Json rpc api of eth_coinbase") - public void test05JsonRpcApiTestForEthCoinbase() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_coinbase", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - - Assert.assertEquals( - "0x410be88a918d74d0dfd71dc84bd4abf036d0562991", responseContent.getString("result")); - } - - @Test(enabled = true, description = "Json rpc api of eth_estimateGas") - public void test06JsonRpcApiTestForEthEstimateGas() throws Exception { - JsonObject param = new JsonObject(); - param.addProperty("from", ByteArray.toHexString(jsonRpcOwnerAddress)); - param.addProperty("to", trc20AddressHex); - param.addProperty("gas", "0x0"); - param.addProperty("gasPrice", "0x0"); - param.addProperty("value", "0x0"); - param.addProperty("data", "0x1249c58b"); - JsonArray params = new JsonArray(); - params.add(param); - JsonObject requestBody = getJsonRpcBody("eth_estimateGas", params); - response = getJsonRpc(jsonRpcNode, requestBody); - logger.info("test06requestBody:" + requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String dataResult = responseContent.getString("result"); - Assert.assertEquals("0x147", dataResult); - } - - @Test(enabled = true, description = "Json rpc api of eth_estimateGasHasPayable") - public void test07JsonRpcApiTestForEthEstimateGasHasPayable() throws Exception { - response = HttpMethed.getTransactionInfoById(httpFullNode, txid); - responseContent = HttpMethed.parseResponseContent(response); - Long realEnergyUsed = responseContent.getJSONObject("receipt").getLong("energy_usage_total"); - logger.info("realEnergyUsed:" + realEnergyUsed); - JsonObject param = new JsonObject(); - param.addProperty("from", "0x" + ByteArray.toHexString(jsonRpcOwnerAddress).substring(2)); - param.addProperty("to", "0x" + contractAddressFrom58); - param.addProperty("gas", "0x0"); - param.addProperty("gasPrice", "0x0"); - param.addProperty("value", "0x1389"); - param.addProperty("data", data); - JsonArray params = new JsonArray(); - params.add(param); - JsonObject requestBody = getJsonRpcBody("eth_estimateGas", params); - response = getJsonRpc(jsonRpcNode, requestBody); - logger.info("test07requestBody:" + requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String dataResult = responseContent.getString("result"); - Assert.assertEquals((long) realEnergyUsed, Long.parseLong(dataResult.substring(2), 16)); - } - - @Test(enabled = true, description = "Json rpc api of eth_estimateGasWithoutTo") - public void test08JsonRpcApiTestForEthEstimateGasWithoutTo() throws Exception { - JsonObject param = new JsonObject(); - param.addProperty("from", "0x6C0214C9995C6F3A61AB23F0EB84B0CDE7FD9C7C"); - param.addProperty("gas", "0x0"); - param.addProperty("gasPrice", "0x0"); - param.addProperty("value", "0x0"); - param.addProperty( - "data", - "0x6080604052d3600055d2600155346002556101418061001f6000396000f30060806040" - + "52600436106100565763ffffffff7c010000000000000000000000000000000000000000" - + "000000000000000060003504166305c24200811461005b5780633be9ece7146100815780" - + "6371dc08ce146100aa575b600080fd5b6100636100b2565b6040805193845260208401929" - + "0925282820152519081900360600190f35b6100a873ffffffffffffffffffffffffffffff" - + "ffffffffff600435166024356044356100c0565b005b61006361010d565b60005460015460" - + "0254909192565b60405173ffffffffffffffffffffffffffffffffffffffff841690821561" - + "08fc029083908590600081818185878a8ad0945050505050158015610107573d6000803e3d" - + "6000fd5b50505050565bd3d2349091925600a165627a7a72305820a2fb39541e90eda9a2f5" - + "f9e7905ef98e66e60dd4b38e00b05de418da3154e757002900000000000000000000000000" - + "00000000000000000000000000000090fa17bb"); - JsonArray params = new JsonArray(); - params.add(param); - JsonObject requestBody = getJsonRpcBody("eth_estimateGas", params); - response = getJsonRpc(jsonRpcNode, requestBody); - logger.info("test08requestBody:" + requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String dataResult = responseContent.getString("result"); - logger.info("dataResult:" + dataResult); - Assert.assertEquals(energyUsed, dataResult); - } - - @Test(enabled = true, description = "Json rpc api of eth_estimateGasSendTrx") - public void test09JsonRpcApiTestForEthEstimateGasSendTrx() throws Exception { - JsonObject param = new JsonObject(); - param.addProperty("from", ByteArray.toHexString(jsonRpcOwnerAddress)); - param.addProperty("to", "0xC1A74CD01732542093F5A87910A398AD70F04BD7"); - param.addProperty("gas", "0x0"); - param.addProperty("gasPrice", "0x0"); - param.addProperty("value", "0x1"); - param.addProperty("data", "0x0"); - JsonArray params = new JsonArray(); - params.add(param); - JsonObject requestBody = getJsonRpcBody("eth_estimateGas", params); - response = getJsonRpc(jsonRpcNode, requestBody); - logger.info("test09requestBody:" + requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String dataResult = responseContent.getString("result"); - Assert.assertEquals("0x0", dataResult); - } - - @Test(enabled = true, description = "Json rpc api of eth_gasPrice") - public void test10JsonRpcApiTestForEthGasPrice() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_gasPrice", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - responseContent.get("result"); - String gasPrice = responseContent.get("result").toString().substring(2); - long gasPriceFromJsonrpc = Long.parseLong(gasPrice, 16); - logger.info(String.valueOf(gasPriceFromJsonrpc)); - response = HttpMethed.getChainParameter(httpFullNode); - responseContent = HttpMethed.parseResponseContent(response); - JSONArray temp; - temp = responseContent.getJSONArray("chainParameter"); - for (int i = 0; i < temp.size(); i++) { - if (temp.getJSONObject(i).get("key").equals("getEnergyFee")) { - gasPriceFromHttp = temp.getJSONObject(i).getLong("value"); - } - } - logger.info("gasPriceFromHttp:" + gasPriceFromHttp); - Assert.assertEquals(gasPriceFromJsonrpc, gasPriceFromHttp); - } - - @Test(enabled = true, description = "Json rpc api of eth_getBalance") - public void test11JsonRpcApiTestForEthGetBalance() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x" + ByteArray.toHexString(foundationAccountAddress).substring(2)); - params.add("latest"); - JsonObject requestBody = getJsonRpcBody("eth_getBalance", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String balance = responseContent.getString("result").substring(2); - Long balance1 = Long.parseLong(balance, 16); - Long balance2 = HttpMethed.getBalance(httpFullNode, foundationAccountAddress); - logger.info(balance1.toString()); - logger.info(balance2.toString()); - Assert.assertEquals(balance1, balance2); - } - - @Test(enabled = true, description = "Json rpc api of eth_getBlockTransactionCountByNumber") - public void test12JsonRpcApiTestForEthGetBlockTransactionCountByNum() throws Exception { - response = HttpMethed.getNowBlock(httpFullNode); - responseContent = HttpMethed.parseResponseContent(response); - JsonArray params = new JsonArray(); - params.add("earliest"); - JsonObject requestBody = getJsonRpcBody("eth_getBlockTransactionCountByNumber", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String transactionNum = responseContent.getString("result").substring(2); - int transactionNum1 = Integer.parseInt(transactionNum, 16); - logger.info(String.valueOf(transactionNum1)); - response = HttpMethed.getTransactionCountByBlocknum(httpFullNode, 0); - responseContent = HttpMethed.parseResponseContent(response); - int transactionNum2 = responseContent.getInteger("count"); - logger.info(String.valueOf(transactionNum2)); - Assert.assertEquals(transactionNum1, transactionNum2); - } - - @Test(enabled = true, description = "Json rpc api of eth_getCode") - public void test13JsonRpcApiTestForEthGetCode() throws Exception { - - JsonArray params = new JsonArray(); - params.add(contractAddressFrom58); - params.add("latest"); - JsonObject requestBody = getJsonRpcBody("eth_getCode", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String codeFromJsonRpc = responseContent.getString("result").substring(2); - logger.info(codeFromJsonRpc); - response = HttpMethed.getContractInfo(httpFullNode, contractAddressFrom58); - logger.info("13contractAddressFrom58:" + contractAddressFrom58); - responseContent = HttpMethed.parseResponseContent(response); - String codeFromHttp = responseContent.getString("runtimecode"); - logger.info(codeFromHttp); - Assert.assertEquals(codeFromJsonRpc, codeFromHttp); - } - - @Test(enabled = true, description = "Json rpc api of eth_getStorageAt") - public void test14JsonRpcApiTestForEthGetStorageAt01() throws Exception { - - JsonArray params = new JsonArray(); - params.add(contractAddressFrom58); - params.add("0x0"); - params.add("latest"); - JsonObject requestBody = getJsonRpcBody("eth_getStorageAt", params); - logger.info("requestBody:" + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("14responseContent:" + responseContent); - String result = responseContent.getString("result").substring(2); - long resultExpect = Long.parseLong(result, 16); - logger.info("result:" + resultExpect); - Assert.assertEquals("1234", String.valueOf(resultExpect)); - } - - @Test(enabled = true, description = "Json rpc api of eth_getStorageAt") - public void test15JsonRpcApiTestForEthGetStorageAt02() throws Exception { - - String address = - "000000000000000000000000" + ByteArray.toHexString(jsonRpcOwnerAddress).substring(2); - String str = address + "0000000000000000000000000000000000000000000000000000000000000001"; - logger.info("str:" + str); - JsonArray paramsForSha3 = new JsonArray(); - paramsForSha3.add(str); - JsonObject requestBodyForSha3 = getJsonRpcBody("web3_sha3", paramsForSha3); - logger.info("requestBodyForSha3:" + requestBodyForSha3); - response = getJsonRpc(jsonRpcNode, requestBodyForSha3); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("responseContent:" + responseContent); - String resultForSha3 = responseContent.getString("result"); - logger.info("resultForSha3:" + resultForSha3); - JsonArray params = new JsonArray(); - params.add(contractAddressFrom58); - params.add(resultForSha3); - params.add("latest"); - JsonObject requestBody = getJsonRpcBody("eth_getStorageAt", params); - logger.info("requestBody:" + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("15responseContent:" + responseContent); - String result = responseContent.getString("result").substring(2); - logger.info("15result:" + result); - logger.info("mapResult:" + Integer.parseInt(result, 16)); - Assert.assertEquals("5678", String.valueOf(Integer.parseInt(result, 16))); - } - - @Test(enabled = true, description = "Json rpc api of eth_getTransactionByBlockNumberAndIndex") - public void test16JsonRpcApiTestForEthGetTransactionByBlockNumberAndIndex() throws Exception { - logger.info("16blockNum:" + blockNum); - blockNumHex = "0x" + Integer.toHexString(blockNum); - logger.info("16blockNumHex:" + blockNumHex); - JsonArray params = new JsonArray(); - params.add(blockNumHex); - indexNum = 0; - response = HttpMethed.getBlockByNum(httpFullNode, blockNum); - responseContent = HttpMethed.parseResponseContent(response); - parentHash = - responseContent - .getJSONObject("block_header") - .getJSONObject("raw_data") - .getString("parentHash"); - txTrieRoot = - responseContent - .getJSONObject("block_header") - .getJSONObject("raw_data") - .getString("txTrieRoot"); - witnessAddress = - responseContent - .getJSONObject("block_header") - .getJSONObject("raw_data") - .getString("witness_address"); - feeLimit = - responseContent - .getJSONArray("transactions") - .getJSONObject(0) - .getJSONObject("raw_data") - .getString("fee_limit"); - logger.info(feeLimit); - - JSONObject getBlockByNumResult = null; - for (int i = 0; i < responseContent.getJSONArray("transactions").size(); i++) { - if (txid.equals( - responseContent.getJSONArray("transactions").getJSONObject(i).getString("txID"))) { - indexNum = i; - getBlockByNumResult = responseContent.getJSONArray("transactions").getJSONObject(i); - bid = responseContent.getString("blockID"); - break; - } - } - transactionIdList = new ArrayList<>(); - if (responseContent.getJSONArray("transactions").size() > 0) { - for (int i = 0; i < responseContent.getJSONArray("transactions").size(); i++) { - transactionIdList.add( - "0x" + responseContent.getJSONArray("transactions").getJSONObject(i).getString("txID")); - } - } - logger.info("16transactionIdList:" + transactionIdList); - logger.info(String.valueOf(indexNum)); - indexHex = "0x" + Integer.toHexString(indexNum); - logger.info("16indexHex:" + indexHex); - params.add(indexHex); - JsonObject requestBody = getJsonRpcBody("eth_getTransactionByBlockNumberAndIndex", params); - logger.info("16requestBody:" + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - result = responseContent.getJSONObject("result"); - logger.info("16 result" + result); - Map jsonrpcResult = new HashMap(); - for (Map.Entry entry : result.entrySet()) { - jsonrpcResult.put(entry.getKey(), entry.getValue()); - } - transacionHash = jsonrpcResult.get("hash").toString(); - logger.info("16transactionHash:" + transacionHash); - blockHash = jsonrpcResult.get("blockHash").toString(); - logger.info("16jsonrpcResult:" + jsonrpcResult); - response = HttpMethed.getTransactionInfoByBlocknum(httpFullNode, blockNum); - logger.info("16response:" + response); - List responseContent1 = HttpMethed.parseResponseContentArray(response); - logger.info("16responseContent1:" + responseContent1); - blockTimeStamp = responseContent1.get(0).getLong("blockTimeStamp"); - - for (int i = 0; i < responseContent1.size(); i++) { - if (responseContent1.get(i).getString("id").equals(transactionIdList.get(0).substring(2))) { - gas = responseContent1.get(i).getJSONObject("receipt").getLong("energy_usage_total"); - logger.info("gas:" + gas); - break; - } - } - - Assert.assertEquals(jsonrpcResult.get("gas").toString(), "0x" + Long.toHexString(gas)); - Assert.assertNull(jsonrpcResult.get("nonce")); - Assert.assertEquals( - jsonrpcResult.get("hash").toString(), "0x" + getBlockByNumResult.getString("txID")); - Assert.assertEquals(jsonrpcResult.get("blockHash").toString(), "0x" + bid); - Assert.assertEquals(jsonrpcResult.get("blockNumber").toString(), blockNumHex); - Assert.assertEquals(jsonrpcResult.get("transactionIndex").toString(), indexHex); - Assert.assertEquals( - jsonrpcResult.get("from").toString(), - "0x" - + getBlockByNumResult - .getJSONObject("raw_data") - .getJSONArray("contract") - .getJSONObject(0) - .getJSONObject("parameter") - .getJSONObject("value") - .getString("owner_address") - .substring(2)); - Assert.assertEquals( - jsonrpcResult.get("to").toString(), - "0x" - + getBlockByNumResult - .getJSONObject("raw_data") - .getJSONArray("contract") - .getJSONObject(0) - .getJSONObject("parameter") - .getJSONObject("value") - .getString("contract_address") - .substring(2)); - - Assert.assertEquals(jsonrpcResult.get("value").toString(), "0x1389"); - String data; - if (getBlockByNumResult.getJSONObject("raw_data").getString("data") == null) { - data = "0x"; - } else { - data = getBlockByNumResult.getJSONObject("raw_data").getString("data").substring(2); - } - Assert.assertEquals(jsonrpcResult.get("input").toString(), data); - - long temp = Long.parseLong(getBlockByNumResult.getString("signature").substring(130, 131), 16); - long v = Long.parseLong(getBlockByNumResult.getString("signature").substring(130, 132), 16); - if (temp < 27) { - v += 27; - } - Assert.assertEquals(Long.parseLong(jsonrpcResult.get("v").toString().substring(2), 16), v); - Assert.assertEquals( - jsonrpcResult.get("r").toString().substring(2), - getBlockByNumResult.getString("signature").substring(2, 66)); - Assert.assertEquals( - jsonrpcResult.get("s").toString().substring(2), - getBlockByNumResult.getString("signature").substring(66, 130)); - } - - @Test(enabled = true, description = "Json rpc api of eth_getBlockTransactionCountByHash") - public void test17JsonRpcApiTestForEthGetBlockTransactionCountByHash() throws Exception { - logger.info("17blockNum:" + blockNum); - JsonArray params = new JsonArray(); - params.add(blockHash); - logger.info("17blockHash:" + blockHash); - JsonObject requestBody = getJsonRpcBody("eth_getBlockTransactionCountByHash", params); - logger.info("17requestBody:" + requestBody); - HttpMethed.waitToProduceOneBlock(httpFullNode); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("17responseContent:" + responseContent); - String transactionNum = responseContent.getString("result").substring(2); - int transactionNumFromJsonRpcNode = Integer.parseInt(transactionNum, 16); - logger.info("17transactionNumFromJsonRpcNode:" + transactionNumFromJsonRpcNode); - response = HttpMethed.getTransactionCountByBlocknum(httpFullNode, blockNum); - responseContent = HttpMethed.parseResponseContent(response); - int transactionNumFromHttp = responseContent.getInteger("count"); - logger.info("transactionNumFromHttp:" + transactionNumFromHttp); - Assert.assertEquals(transactionNumFromHttp, transactionNumFromJsonRpcNode); - } - - @Test(enabled = true, description = "Json rpc api of eth_getBlockTransactionCountByNumber") - public void test18JsonRpcApiTestForEthGetBlockTransactionCountByNum() throws Exception { - JsonArray params = new JsonArray(); - params.add(blockNum); - logger.info(String.valueOf(blockNum)); - JsonObject requestBody = getJsonRpcBody("eth_getBlockTransactionCountByNumber", params); - logger.info("requestBody:" + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - logger.info("response:" + response); - HttpMethed.waitToProduceOneBlock(httpFullNode); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("responseContent:" + responseContent); - String transactionNum = responseContent.getString("result").substring(2); - int transactionNum1 = Integer.parseInt(transactionNum, 16); - logger.info(String.valueOf(transactionNum1)); - response = HttpMethed.getTransactionCountByBlocknum(httpFullNode, blockNum); - responseContent = HttpMethed.parseResponseContent(response); - int transactionNum2 = responseContent.getInteger("count"); - logger.info(String.valueOf(transactionNum2)); - Assert.assertEquals(transactionNum1, transactionNum2); - } - - @Test(enabled = true, description = "Json rpc api of eth_getTransactionByBlockHashAndIndex") - public void test19JsonRpcApiTestForEthGetTransactionByBlockHashAndIndex() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x" + bid); - params.add(indexHex); - logger.info("indexHex:" + indexHex); - JsonObject requestBody = getJsonRpcBody("eth_getTransactionByBlockHashAndIndex", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - JSONObject resultForGetTransactionByBlockHashAndIndex = responseContent.getJSONObject("result"); - Assert.assertEquals(result, resultForGetTransactionByBlockHashAndIndex); - } - - @Test(enabled = true, description = "Json rpc api of eth_getTransactionByHash") - public void test20JsonRpcApiTestForEthGetTransactionByHash() throws Exception { - logger.info("20transacionHash:" + transacionHash); - JsonArray params = new JsonArray(); - params.add(transacionHash); - JsonObject requestBody = getJsonRpcBody("eth_getTransactionByHash", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("20responseContent:" + responseContent); - JSONObject result1 = responseContent.getJSONObject("result"); - Assert.assertEquals(result, result1); - } - - @Test(enabled = true, description = "Json rpc api of eth_getTransactionReceipt") - public void test21JsonRpcApiTestForEthGetTransactionReceipt() throws Exception { - logger.info("trc20Txid:" + trc20Txid); - JsonArray params = new JsonArray(); - Thread.sleep(6000); - params.add(trc20Txid); - JsonObject requestBody = getJsonRpcBody("eth_getTransactionReceipt", params); - logger.info("21requestBody:" + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - logger.info("21response:" + response); - responseContent = HttpMethed.parseResponseContent(response); - JSONObject resultFromTransactionReceipt = responseContent.getJSONObject("result"); - logger.info("21resultFromTransactionReceipt:" + resultFromTransactionReceipt); - JSONArray logs = resultFromTransactionReceipt.getJSONArray("logs"); - logger.info("21logs:" + logs); - logger.info("21result:" + resultFromTransactionReceipt.toString()); - response = HttpMethed.getBlockByNum(httpFullNode, blockNumForTrc20); - responseContent = HttpMethed.parseResponseContent(response); - int index = 0; - for (int i = 0; i < responseContent.getJSONArray("transactions").size(); i++) { - if (trc20Txid.equals( - responseContent.getJSONArray("transactions").getJSONObject(i).getString("txID"))) { - index = i; - break; - } - } - - JsonArray paramsForTransactionByBlockNumberAndIndex = new JsonArray(); - paramsForTransactionByBlockNumberAndIndex.add("0x" + Integer.toHexString(blockNumForTrc20)); - paramsForTransactionByBlockNumberAndIndex.add("0x" + Integer.toHexString(index)); - JsonObject requestBody1 = - getJsonRpcBody( - "eth_getTransactionByBlockNumberAndIndex", paramsForTransactionByBlockNumberAndIndex); - response = getJsonRpc(jsonRpcNode, requestBody1); - logger.info("requestBody1:" + requestBody1); - responseContent = HttpMethed.parseResponseContent(response); - JSONObject resultFromTransactionByBlockNumberAndIndex = responseContent.getJSONObject("result"); - logger.info( - "resultFromTransactionByBlockNumberAndIndex:" + resultFromTransactionByBlockNumberAndIndex); - Assert.assertEquals( - resultFromTransactionReceipt.getString("blockHash"), - resultFromTransactionByBlockNumberAndIndex.getString("blockHash")); - Assert.assertEquals( - resultFromTransactionReceipt.getString("blockNumber"), - resultFromTransactionByBlockNumberAndIndex.getString("blockNumber")); - Assert.assertEquals( - resultFromTransactionReceipt.getString("transactionIndex"), - resultFromTransactionByBlockNumberAndIndex.getString("transactionIndex")); - Assert.assertEquals( - resultFromTransactionReceipt.getString("transactionHash"), "0x" + trc20Txid); - Assert.assertEquals( - resultFromTransactionReceipt.getString("from"), - resultFromTransactionByBlockNumberAndIndex.getString("from")); - Assert.assertEquals( - resultFromTransactionReceipt.getString("to"), - resultFromTransactionByBlockNumberAndIndex.getString("to")); - logger.info("effectiveGasPrice:" + resultFromTransactionReceipt.getString("effectiveGasPrice")); - logger.info("gasPriceFromHttp:" + Long.toHexString(gasPriceFromHttp)); - Assert.assertEquals( - resultFromTransactionReceipt.getString("effectiveGasPrice"), - "0x" + Long.toHexString(gasPriceFromHttp)); - /* Assert.assertEquals( - resultFromTransactionReceipt.getString("contractAddress").substring(2), - trc20AddressHex.substring(2));*/ - Assert.assertNull(resultFromTransactionReceipt.getString("contractAddress")); - Assert.assertEquals( - resultFromTransactionReceipt.getString("logsBloom"), - "0x000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000"); - Assert.assertEquals("0x1", resultFromTransactionReceipt.getString("status")); - Assert.assertEquals("0x0", resultFromTransactionReceipt.getString("type")); - logger.info("gas:" + resultFromTransactionByBlockNumberAndIndex.getString("gas")); - Assert.assertEquals( - resultFromTransactionReceipt.getString("gasUsed"), - resultFromTransactionByBlockNumberAndIndex.getString("gas")); - Assert.assertEquals( - resultFromTransactionReceipt.getString("cumulativeGasUsed"), - resultFromTransactionByBlockNumberAndIndex.getString("gas")); - Assert.assertEquals( - logs.getJSONObject(0).getString("logIndex"), "0x" + Integer.toHexString(index)); - Assert.assertEquals(logs.getJSONObject(0).getString("removed"), "false"); - Assert.assertEquals( - logs.getJSONObject(0).getString("blockHash"), - resultFromTransactionReceipt.getString("blockHash")); - Assert.assertEquals( - logs.getJSONObject(0).getString("blockNumber"), - resultFromTransactionReceipt.getString("blockNumber")); - Assert.assertEquals( - logs.getJSONObject(0).getString("transactionIndex"), - resultFromTransactionReceipt.getString("transactionIndex")); - Assert.assertEquals( - logs.getJSONObject(0).getString("transactionHash"), - resultFromTransactionReceipt.getString("transactionHash")); - Assert.assertEquals( - logs.getJSONObject(0).getString("address"), resultFromTransactionReceipt.getString("to")); - response = HttpMethed.getTransactionInfoByBlocknum(httpFullNode, blockNumForTrc20); - List responseContent1 = HttpMethed.parseResponseContentArray(response); - logger.info("21responseContent1:" + responseContent1); - - response = HttpMethed.getBlockByNum(httpFullNode, blockNumForTrc20); - responseContent = HttpMethed.parseResponseContent(response); - Assert.assertEquals( - logs.getJSONObject(0).getString("data").substring(2), - responseContent1.get(index).getJSONArray("log").getJSONObject(0).getString("data")); - - Assert.assertEquals( - logs.getJSONObject(0).getString("topics").replace("0x", ""), - responseContent1.get(index).getJSONArray("log").getJSONObject(0).getString("topics")); - } - - @Test(enabled = true, description = "Json rpc api of eth_getUncleByBlockHashAndIndex") - public void test22JsonRpcApiTestForEthGetUncleByBlockHashAndIndex() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x0000000000f9cc56243898cbe88685678855e07f51c5af91322c225ce3693868"); - params.add("0x"); - JsonObject requestBody = getJsonRpcBody("eth_getUncleByBlockHashAndIndex", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String result = responseContent.getString("result"); - logger.info(result); - Assert.assertNull(result); - } - - @Test(enabled = true, description = "Json rpc api of eth_getUncleByBlockNumberAndIndex") - public void test23JsonRpcApiTestForEthGetUncleByBlockNumberAndIndex() throws Exception { - JsonArray params = new JsonArray(); - params.add("0xeb82f0"); - params.add("0x"); - JsonObject requestBody = getJsonRpcBody("eth_getUncleByBlockNumberAndIndex", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String result = responseContent.getString("result"); - logger.info(result); - Assert.assertNull(result); - } - - @Test(enabled = true, description = "Json rpc api of eth_getUncleCountByBlockHash") - public void test24JsonRpcApiTestForEthGetUncleCountByBlockHash() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x0000000000f9cc56243898cbe88685678855e07f51c5af91322c225ce3693868"); - JsonObject requestBody = getJsonRpcBody("eth_getUncleCountByBlockHash", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String result = responseContent.getString("result"); - logger.info(result); - Assert.assertEquals(result, "0x0"); - } - - @Test(enabled = true, description = "Json rpc api of eth_getUncleCountByBlockNumber") - public void test25JsonRpcApiTestForEthGetUncleCountByBlockNumber() throws Exception { - JsonArray params = new JsonArray(); - params.add("eth_getUncleCountByBlockNumber"); - JsonObject requestBody = getJsonRpcBody("eth_getUncleCountByBlockNumber", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String result = responseContent.getString("result"); - logger.info(result); - Assert.assertEquals(result, "0x0"); - } - - @Test(enabled = true, description = "Json rpc api of eth_getWork") - public void test26JsonRpcApiTestForEthGetWork() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_getWork", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String result = responseContent.getString("result"); - int resultLen = result.length(); - String resultFromJsonRpcNode = result.substring(4, resultLen - 12); - response = HttpMethed.getNowBlock(httpFullNode); - responseContent = HttpMethed.parseResponseContent(response); - String resultFromHttp = responseContent.getString("blockID"); - logger.info("resultFromJsonRpcNode:" + resultFromJsonRpcNode); - logger.info("resultFromHttp:" + resultFromHttp); - Assert.assertEquals(resultFromJsonRpcNode, resultFromHttp); - } - - @Test(enabled = true, description = "Json rpc api of eth_hashrate") - public void test27JsonRpcApiTestForEthHashRate() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_hashrate", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String result = responseContent.getString("result"); - logger.info(result); - Assert.assertEquals("0x0", result); - } - - @Test(enabled = true, description = "Json rpc api of eth_mining") - public void test28JsonRpcApiTestForEthMining() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_mining", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String result = responseContent.getString("result"); - logger.info(result); - Assert.assertEquals(result, "true"); - } - - @Test(enabled = true, description = "Json rpc api of eth_protocolVersion") - public void test29JsonRpcApiTestForEthProtocolVersion() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_protocolVersion", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String protocolVersion = responseContent.getString("result").substring(2); - Long protocolVersion1 = Long.parseLong(protocolVersion, 16); - response = HttpMethed.getNowBlock(httpFullNode); - responseContent = HttpMethed.parseResponseContent(response); - Long protocolVersion2 = - responseContent.getJSONObject("block_header").getJSONObject("raw_data").getLong("version"); - logger.info(protocolVersion1.toString()); - logger.info(protocolVersion2.toString()); - Assert.assertEquals(protocolVersion1, protocolVersion2); - } - - @Test(enabled = true, description = "Json rpc api of eth_syncing") - public void test30JsonRpcApiTestForEthSyncing() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_syncing", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - JSONObject temp = responseContent.getJSONObject("result"); - String currentNumFromRpc = temp.getString("currentBlock"); - logger.info(currentNumFromRpc); - logger.info(temp.toString()); - response = HttpMethed.getNowBlock(httpFullNode); - responseContent = HttpMethed.parseResponseContent(response); - long currentNum = - responseContent.getJSONObject("block_header").getJSONObject("raw_data").getLong("number"); - logger.info("currentNum:" + currentNum); - logger.info("currentNumFromRpc:" + Long.parseLong(currentNumFromRpc.substring(2), 16)); - Assert.assertEquals(currentNum, Long.parseLong(currentNumFromRpc.substring(2), 16)); - Assert.assertTrue(temp.containsKey("startingBlock")); - Assert.assertTrue(temp.containsKey("currentBlock")); - Assert.assertTrue(temp.containsKey("highestBlock")); - } - - @Test(enabled = true, description = "Json rpc api of net_listening") - public void test31JsonRpcApiTestForNetListening() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("net_listening", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - Boolean temp = responseContent.getBoolean("result"); - logger.info(temp.toString()); - response = HttpMethed.getNodeInfo(httpFullNode); - responseContent = HttpMethed.parseResponseContent(response); - boolean expect = false; - int num = responseContent.getInteger("activeConnectCount"); - if (num >= 1) { - expect = true; - } - Assert.assertEquals(temp, expect); - } - - @Test(enabled = true, description = "Json rpc api of net_peerCount") - public void test32JsonRpcApiTestForNetPeerCount() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("net_peerCount", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String result = responseContent.getString("result"); - logger.info(result); - Assert.assertNotNull(result); - } - - @Test(enabled = true, description = "Json rpc api of net_version") - public void test33JsonRpcApiTestForEthVersion() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("net_version", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String firstBlockHashFromJsonRpc = responseContent.getString("result").substring(2); - response = HttpMethed.getBlockByNum(httpFullNode, 0); - responseContent = HttpMethed.parseResponseContent(response); - String firstBlockHashFromHttp = responseContent.getString("blockID").substring(56); - logger.info("firstBlockHashFromJsonRpc" + firstBlockHashFromJsonRpc); - logger.info("firstBlockHashFromHttp" + firstBlockHashFromHttp); - Assert.assertEquals(firstBlockHashFromJsonRpc, firstBlockHashFromHttp); - } - - @Test(enabled = true, description = "Json rpc api of web3_clientVersion") - public void test34JsonRpcApiTestForWeb3ClientVersion() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("web3_clientVersion", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String result = responseContent.getString("result"); - List resultList = new ArrayList<>(); - for (String str : result.split("/")) { - resultList.add(str); - } - Assert.assertEquals(resultList.size(), 5); - Assert.assertEquals(resultList.get(0), "TRON"); - Assert.assertEquals(resultList.get(1).substring(0, 1), "v"); - Assert.assertEquals(resultList.get(2), "Linux"); - Assert.assertEquals(resultList.get(3), "Java1.8"); - Assert.assertEquals(resultList.get(4).substring(0, 11), "GreatVoyage"); - } - - @Test(enabled = true, description = "Json rpc api of web3_sha3") - public void test35JsonRpcApiTestForWeb3Sha3() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x08"); - JsonObject requestBody1 = getJsonRpcBody("web3_sha3", params); - response = getEthHttps(ethHttpsNode, requestBody1); - responseContent = HttpMethed.parseResponseContent(response); - String result1 = responseContent.getString("result"); - JsonObject requestBody2 = getJsonRpcBody("web3_sha3", params); - response = getJsonRpc(jsonRpcNode, requestBody2); - responseContent = HttpMethed.parseResponseContent(response); - String result2 = responseContent.getString("result"); - Assert.assertEquals(result1, result2); - } - - @Test(enabled = true, description = "Json rpc api of eth_compileLLL") - public void test36JsonRpcApiTestForEthCompileLll() throws Exception { - JsonArray params = new JsonArray(); - params.add("(returnlll (suicide (caller)))"); - JsonObject requestBody1 = getJsonRpcBody("eth_compileLLL", params); - response = getJsonRpc(jsonRpcNode, requestBody1); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals(errorMessage, "the method eth_compileLLL does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_compileSerpent") - public void test37JsonRpcApiTestForEthCompileSerpent() throws Exception { - JsonArray params = new JsonArray(); - params.add("/* some serpent */"); - JsonObject requestBody = getJsonRpcBody("eth_compileSerpent", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals( - errorMessage, "the method eth_compileSerpent does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_compileSolidity") - public void test38JsonRpcApiTestForEthCompileSolidity() throws Exception { - JsonArray params = new JsonArray(); - params.add("contract test { function multiply(uint a) returns(uint d) { return a * 7; } }"); - JsonObject requestBody = getJsonRpcBody("eth_compileSolidity", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals( - errorMessage, "the method eth_compileSolidity does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_getCompilers") - public void test39JsonRpcApiTestForEthCompileSolidity() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_getCompilers", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals( - errorMessage, "the method eth_getCompilers does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_getTransactionCount") - public void test40JsonRpcApiTestForEthGetTransactionCount() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x407d73d8a49eeb85d32cf465507dd71d507100c1"); - params.add("latest"); - JsonObject requestBody = getJsonRpcBody("eth_getTransactionCount", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals( - errorMessage, "the method eth_getTransactionCount does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_sendRawTransaction") - public void test41JsonRpcApiTestForEthSendRawTransaction() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x234"); - JsonObject requestBody = getJsonRpcBody("eth_sendRawTransaction", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals( - errorMessage, "the method eth_sendRawTransaction does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_sendTransaction") - public void test42JsonRpcApiTestForEthSendTransaction() throws Exception { - JsonArray params = new JsonArray(); - JsonObject temp = new JsonObject(); - params.add(temp); - temp.addProperty("from", "0xb60e8dd61c5d32be8058bb8eb970870f07233155"); - temp.addProperty("to", "0xd46e8dd67c5d32be8058bb8eb970870f07244567"); - temp.addProperty("gas", "0x76c0"); - temp.addProperty("gasPrice", "0x9184e72a000"); - temp.addProperty( - "data", - "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"); - temp.addProperty("value", "0x9184e72a"); - - JsonObject requestBody = getJsonRpcBody("eth_sendTransaction", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals( - errorMessage, "the method eth_sendTransaction does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_sign") - public void test43JsonRpcApiTestForEthSign() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x9b2055d370f73ec7d8a03e965129118dc8f5bf83"); - params.add("0xdeadbeaf"); - JsonObject requestBody = getJsonRpcBody("eth_sign", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals(errorMessage, "the method eth_sign does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_signTransaction") - public void test44JsonRpcApiTestForEthSignTransaction() throws Exception { - JsonArray params = new JsonArray(); - JsonObject temp = new JsonObject(); - params.add(temp); - temp.addProperty( - "data", - "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"); - temp.addProperty("from", "0xb60e8dd61c5d32be8058bb8eb970870f07233155"); - temp.addProperty("gas", "0x76c0"); - temp.addProperty("gasPrice", "0x9184e72a000"); - temp.addProperty("to", "0xd46e8dd67c5d32be8058bb8eb970870f07244567"); - temp.addProperty("value", "0x9184e72a"); - - JsonObject requestBody = getJsonRpcBody("eth_signTransaction", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals( - errorMessage, "the method eth_signTransaction does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_submitWork") - public void test45JsonRpcApiTestForEthSubmitWork() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x0000000000000001"); - params.add("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"); - params.add("0xD1GE5700000000000000000000000000D1GE5700000000000000000000000000"); - JsonObject requestBody = getJsonRpcBody("eth_submitWork", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals(errorMessage, "the method eth_submitWork does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of parity_nextNonce") - public void test46JsonRpcApiTestForParityNextNonce() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x9b2055d370f73ec7d8a03e965129118dc8f5bf83"); - JsonObject requestBody = getJsonRpcBody("parity_nextNonce", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals( - errorMessage, "the method parity_nextNonce does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_submitHashrate") - public void test47JsonRpcApiTestForEthSubmitHashrate() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x0000000000000000000000000000000000000000000000000000000000500000"); - params.add("0x59daa26581d0acd1fce254fb7e85952f4c09d0915afd33d3886cd914bc7d283c"); - JsonObject requestBody = getJsonRpcBody("eth_submitHashrate", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals( - errorMessage, "the method eth_submitHashrate does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_getBlockByHash params is false") - public void test48JsonRpcApiTestForEthGetBlockByHash() throws Exception { - response = HttpMethed.getBlockByNum(httpFullNode, blockNum); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("48getBlockByNumFromHttp:" + responseContent); - accountStateRoot = - responseContent - .getJSONObject("block_header") - .getJSONObject("raw_data") - .getString("accountStateRoot"); - if (accountStateRoot == null) { - accountStateRoot = ""; - } - JsonArray params = new JsonArray(); - params.add(blockHash); - params.add(false); - JsonObject requestBody = getJsonRpcBody("eth_getBlockByHash", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - JSONObject getBlockByHashResult = responseContent.getJSONObject("result"); - - Assert.assertNull(getBlockByHashResult.getString("nonce")); - Assert.assertNull(getBlockByHashResult.getString("sha3Uncles")); - Assert.assertNull(getBlockByHashResult.getString("receiptsRoot")); - Assert.assertNull(getBlockByHashResult.getString("difficulty")); - Assert.assertNull(getBlockByHashResult.getString("totalDifficulty")); - Assert.assertNull(getBlockByHashResult.getString("extraData")); - Assert.assertNull(getBlockByHashResult.getString("baseFeePerGas")); - Assert.assertNull(getBlockByHashResult.getString("mixHash")); - Assert.assertEquals(getBlockByHashResult.getString("uncles"), new ArrayList<>().toString()); - Assert.assertEquals(getBlockByHashResult.getString("stateRoot"), "0x" + accountStateRoot); - - Assert.assertEquals( - getBlockByHashResult.getString("logsBloom"), - "0x00000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "00000000000000000000000000000000000000000000000000000000000000000000000" - + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000000000000" - + "00000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000"); - Assert.assertEquals(getBlockByHashResult.getString("number"), blockNumHex); - Assert.assertEquals(getBlockByHashResult.getString("hash"), "0x" + bid); - Assert.assertEquals(getBlockByHashResult.getString("parentHash"), "0x" + parentHash); - Assert.assertEquals(getBlockByHashResult.getString("transactionsRoot"), "0x" + txTrieRoot); - Assert.assertEquals( - getBlockByHashResult.getString("miner"), "0x" + witnessAddress.substring(2)); - Assert.assertEquals(getBlockByHashResult.getString("gasUsed"), "0x" + Long.toHexString(gas)); - Assert.assertEquals( - String.valueOf(Long.parseLong(getBlockByHashResult.getString("gasLimit").substring(2), 16)), - feeLimit); - Assert.assertEquals( - Long.parseLong(getBlockByHashResult.getString("timestamp").substring(2), 16), - blockTimeStamp); - final GrpcAPI.NumberMessage message = - GrpcAPI.NumberMessage.newBuilder().setNum(blockNum).build(); - HttpMethed.waitToProduceOneBlock(httpFullNode); - Block block = blockingStubFull.getBlockByNum(message); - logger.info("48sizeFromJrpc:" + block.getSerializedSize()); - logger.info( - "48sizeFromJsonRPc:" - + Long.parseLong(getBlockByHashResult.getString("size").substring(2), 16)); - size = block.getSerializedSize(); - Assert.assertEquals( - Long.parseLong(getBlockByHashResult.getString("size").substring(2), 16), - block.getSerializedSize()); - - Long.parseLong(getBlockByHashResult.getString("timestamp").substring(2), 16); - JSONArray transactionId = getBlockByHashResult.getJSONArray("transactions"); - List transactionIdListFromGetBlockByHash = new ArrayList<>(); - if (transactionId.size() > 0) { - for (int i = 0; i < transactionId.size(); i++) { - transactionIdListFromGetBlockByHash.add(transactionId.get(i).toString()); - } - } - Assert.assertEquals(transactionIdListFromGetBlockByHash, transactionIdList); - } - - @Test(enabled = true, description = "Json rpc api of eth_getBlockByNumber params is true") - public void test49JsonRpcApiTestForEthGetBlockByNumber() throws Exception { - - JsonArray params = new JsonArray(); - params.add(blockNumHex); - logger.info("49blockNumHex:" + blockNumHex); - params.add(true); - JsonObject requestBody = getJsonRpcBody("eth_getBlockByNumber", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - JSONObject getBlockByNumberResult = responseContent.getJSONObject("result"); - logger.info("49getBlockByHashResult:" + getBlockByNumberResult); - - Assert.assertNull(getBlockByNumberResult.getString("nonce")); - Assert.assertNull(getBlockByNumberResult.getString("sha3Uncles")); - Assert.assertNull(getBlockByNumberResult.getString("receiptsRoot")); - Assert.assertNull(getBlockByNumberResult.getString("difficulty")); - Assert.assertNull(getBlockByNumberResult.getString("totalDifficulty")); - Assert.assertNull(getBlockByNumberResult.getString("extraData")); - Assert.assertNull(getBlockByNumberResult.getString("baseFeePerGas")); - Assert.assertNull(getBlockByNumberResult.getString("mixHash")); - Assert.assertEquals(getBlockByNumberResult.getString("uncles"), new ArrayList<>().toString()); - Assert.assertEquals(getBlockByNumberResult.getString("stateRoot"), "0x" + accountStateRoot); - Assert.assertEquals( - getBlockByNumberResult.getString("logsBloom"), - "0x00000000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000000000" - + "00000000000000000000000000000000000000000000000000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000"); - Assert.assertEquals(getBlockByNumberResult.getString("number"), blockNumHex); - Assert.assertEquals(getBlockByNumberResult.getString("hash"), "0x" + bid); - Assert.assertEquals(getBlockByNumberResult.getString("parentHash"), "0x" + parentHash); - Assert.assertEquals(getBlockByNumberResult.getString("transactionsRoot"), "0x" + txTrieRoot); - Assert.assertEquals( - getBlockByNumberResult.getString("miner"), "0x" + witnessAddress.substring(2)); - Assert.assertEquals(getBlockByNumberResult.getString("gasUsed"), "0x" + Long.toHexString(gas)); - Assert.assertEquals( - String.valueOf( - Long.parseLong(getBlockByNumberResult.getString("gasLimit").substring(2), 16)), - feeLimit); - Assert.assertEquals( - Long.parseLong(getBlockByNumberResult.getString("timestamp").substring(2), 16), - blockTimeStamp); - logger.info("49size:" + size); - Assert.assertEquals( - Long.parseLong(getBlockByNumberResult.getString("size").substring(2), 16), size); - - JSONArray transactionsList = getBlockByNumberResult.getJSONArray("transactions"); - logger.info("49transactionsList:" + transactionsList); - List transactionInfoListFromGetBlockByHash = new ArrayList<>(); - if (transactionsList.size() > 0) { - for (int i = 0; i < transactionsList.size(); i++) { - transactionInfoListFromGetBlockByHash.add(transactionsList.get(i).toString()); - } - } - List transactionInfoListFromTransactionByBlockNumberAndIndex = new ArrayList<>(); - for (int i = 0; i < transactionsList.size(); i++) { - JsonArray paramsForEthGetTransactionByBlockNumberAndIndex = new JsonArray(); - paramsForEthGetTransactionByBlockNumberAndIndex.add(blockNumHex); - String index = "0x" + Integer.toHexString(i); - logger.info("49index:" + index); - paramsForEthGetTransactionByBlockNumberAndIndex.add(index); - logger.info( - "paramsForEthGetTransactionByBlockNumberAndIndex:" - + paramsForEthGetTransactionByBlockNumberAndIndex); - JsonObject requestBodyForTransactionByBlockNumberAndIndex = - getJsonRpcBody( - "eth_getTransactionByBlockNumberAndIndex", - paramsForEthGetTransactionByBlockNumberAndIndex); - response = getJsonRpc(jsonRpcNode, requestBodyForTransactionByBlockNumberAndIndex); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("49responseContent:" + responseContent); - result = responseContent.getJSONObject("result"); - logger.info("49result:" + result); - transactionInfoListFromTransactionByBlockNumberAndIndex.add(result.toString()); - } - Assert.assertEquals( - transactionInfoListFromGetBlockByHash, - transactionInfoListFromTransactionByBlockNumberAndIndex); - } - - /** constructor. */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts002.java deleted file mode 100644 index 303c3f060dc..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts002.java +++ /dev/null @@ -1,1290 +0,0 @@ -package stest.tron.wallet.dailybuild.jsonrpc; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import io.grpc.ManagedChannelBuilder; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.utils.ByteArray; -import org.tron.protos.Protocol.Block; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.JsonRpcBase; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Accounts002 extends JsonRpcBase { - private JSONObject responseContent; - private HttpResponse response; - String realGasPrice; - String bid = null; - int indexNum = 0; - String indexHex = null; - JSONObject result = null; - String transacionHash = null; - String blockHash = null; - String blockNumHex = null; - String parentHash = null; - String txTrieRoot = null; - String witnessAddress = null; - String feeLimit = null; - String accountStateRoot = null; - String energyUsed = "0x135c6"; - - List transactionIdList = null; - long size = 0; - long gas = 0; - long blockTimeStamp = 0; - long gasPriceFromHttp = 0; - - /** constructor. */ - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Json rpc api of eth_accounts from solidity") - public void test01JsonRpcApiTestForEthAccounts() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_accounts", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - List result = new ArrayList(); - logger.info(String.valueOf(result)); - Assert.assertEquals(responseContent.get("result"), result); - } - - @Test(enabled = true, description = "Json rpc api of eth_blockNumber from solidity") - public void test02JsonRpcApiTestForEthBlockNumber() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_blockNumber", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - responseContent.get("result"); - String blockNum = responseContent.getString("result").substring(2); - long blockNumFromjsonRpcNodeForSolidity = Long.parseLong(blockNum, 16); - response = HttpMethed.getNowBlockFromSolidity(httpsolidityNode); - responseContent = HttpMethed.parseResponseContent(response); - long blockNumFromHttp = - responseContent.getJSONObject("block_header").getJSONObject("raw_data").getLong("number"); - logger.info("blocknumFromjsonRpcNodeForSolidity:" + blockNumFromjsonRpcNodeForSolidity); - logger.info("blocknumFromHttp:" + blockNumFromHttp); - Assert.assertTrue(Math.abs(blockNumFromjsonRpcNodeForSolidity - blockNumFromHttp) <= 3); - } - - @Test(enabled = true, description = "Json rpc api of eth_call from solidity") - public void test03JsonRpcApiTestForEthCall() throws Exception { - JsonObject param = new JsonObject(); - HttpMethed.waitToProduceOneBlock(httpFullNode); - param.addProperty("from", ByteArray.toHexString(jsonRpcOwnerAddress)); - param.addProperty("to", trc20AddressHex); - param.addProperty("gas", "0x0"); - param.addProperty("gasPrice", "0x0"); - param.addProperty("value", "0x0"); - param.addProperty("data", "0x06fdde03"); - JsonArray params = new JsonArray(); - params.add(param); - params.add("latest"); - JsonObject requestBody = getJsonRpcBody("eth_call", params); - logger.info("03params:" + params); - logger.info("requestBody:" + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String dataResult = responseContent.getString("result"); - Assert.assertEquals( - "0x000000000000000000000000000000000000000000000000000" - + "00000000000200000000000000000000000000000000000000000" - + "00000000000000000000000a546f6b656e5452433230000000000" - + "00000000000000000000000000000000000", - dataResult); - } - - @Test(enabled = true, description = "Json rpc api of eth_chainId from solidity") - public void test04JsonRpcApiTestForEthChainId() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_chainId", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - responseContent.get("result"); - String blockIdFromjsonRpcNodeForSolidity = - responseContent.get("result").toString().substring(2); - response = HttpMethed.getBlockByNumFromSolidity(httpsolidityNode, 0); - responseContent = HttpMethed.parseResponseContent(response); - String blockIdFromHttp = responseContent.getString("blockID").substring(56); - logger.info("blockIdFromjsonRpcNodeForSolidity:" + blockIdFromjsonRpcNodeForSolidity); - logger.info("blockIdFromHttp:" + blockIdFromHttp); - Assert.assertEquals(blockIdFromjsonRpcNodeForSolidity, blockIdFromHttp); - } - - @Test(enabled = true, description = "Json rpc api of eth_coinbase from solidity") - public void test05JsonRpcApiTestForEthCoinbase() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_coinbase", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - - Assert.assertEquals( - "0x410be88a918d74d0dfd71dc84bd4abf036d0562991", responseContent.getString("result")); - } - - @Test(enabled = true, description = "Json rpc api of eth_estimateGas from solidity") - public void test06JsonRpcApiTestForEthEstimateGas() throws Exception { - JsonObject param = new JsonObject(); - param.addProperty("from", ByteArray.toHexString(jsonRpcOwnerAddress)); - param.addProperty("to", trc20AddressHex); - param.addProperty("gas", "0x0"); - param.addProperty("gasPrice", "0x0"); - param.addProperty("value", "0x0"); - param.addProperty("data", "0x1249c58b"); - JsonArray params = new JsonArray(); - params.add(param); - JsonObject requestBody = getJsonRpcBody("eth_estimateGas", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - logger.info("test06requestBody:" + requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String dataResult = responseContent.getString("result"); - Assert.assertEquals("0x147", dataResult); - } - - @Test(enabled = true, description = "Json rpc api of eth_estimateGasHasPayable") - public void test07JsonRpcApiTestForEthEstimateGasHasPayable() throws Exception { - response = HttpMethed.getTransactionInfoByIdFromSolidity(httpsolidityNode, txid); - responseContent = HttpMethed.parseResponseContent(response); - Long realEnergyUsed = responseContent.getJSONObject("receipt").getLong("energy_usage_total"); - logger.info("realEnergyUsed:" + realEnergyUsed); - JsonObject param = new JsonObject(); - param.addProperty("from", "0x" + ByteArray.toHexString(jsonRpcOwnerAddress).substring(2)); - param.addProperty("to", "0x" + contractAddressFrom58); - param.addProperty("gas", "0x0"); - param.addProperty("gasPrice", "0x0"); - param.addProperty("value", "0x1389"); - param.addProperty("data", data); - JsonArray params = new JsonArray(); - params.add(param); - JsonObject requestBody = getJsonRpcBody("eth_estimateGas", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - logger.info("test07requestBody:" + requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String dataResult = responseContent.getString("result"); - Assert.assertEquals((long) realEnergyUsed, Long.parseLong(dataResult.substring(2), 16)); - } - - @Test(enabled = true, description = "Json rpc api of eth_estimateGasWithoutTo from solidity") - public void test08JsonRpcApiTestForEthEstimateGasWithoutTo() throws Exception { - JsonObject param = new JsonObject(); - param.addProperty("from", "0x6C0214C9995C6F3A61AB23F0EB84B0CDE7FD9C7C"); - param.addProperty("gas", "0x0"); - param.addProperty("gasPrice", "0x0"); - param.addProperty("value", "0x0"); - param.addProperty( - "data", - "0x6080604052d3600055d2600155346002556101418061001f6000396000f30060806040" - + "52600436106100565763ffffffff7c010000000000000000000000000000000000000000" - + "000000000000000060003504166305c24200811461005b5780633be9ece7146100815780" - + "6371dc08ce146100aa575b600080fd5b6100636100b2565b6040805193845260208401929" - + "0925282820152519081900360600190f35b6100a873ffffffffffffffffffffffffffffff" - + "ffffffffff600435166024356044356100c0565b005b61006361010d565b60005460015460" - + "0254909192565b60405173ffffffffffffffffffffffffffffffffffffffff841690821561" - + "08fc029083908590600081818185878a8ad0945050505050158015610107573d6000803e3d" - + "6000fd5b50505050565bd3d2349091925600a165627a7a72305820a2fb39541e90eda9a2f5" - + "f9e7905ef98e66e60dd4b38e00b05de418da3154e757002900000000000000000000000000" - + "00000000000000000000000000000090fa17bb"); - JsonArray params = new JsonArray(); - params.add(param); - JsonObject requestBody = getJsonRpcBody("eth_estimateGas", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - logger.info("test08requestBody:" + requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String dataResult = responseContent.getString("result"); - logger.info("dataResult:" + dataResult); - Assert.assertEquals(energyUsed, dataResult); - } - - @Test(enabled = true, description = "Json rpc api of eth_estimateGasSendTrx from solidity") - public void test09JsonRpcApiTestForEthEstimateGasSendTrx() throws Exception { - JsonObject param = new JsonObject(); - param.addProperty("from", ByteArray.toHexString(jsonRpcOwnerAddress)); - param.addProperty("to", "0xC1A74CD01732542093F5A87910A398AD70F04BD7"); - param.addProperty("gas", "0x0"); - param.addProperty("gasPrice", "0x0"); - param.addProperty("value", "0x1"); - param.addProperty("data", "0x0"); - JsonArray params = new JsonArray(); - params.add(param); - JsonObject requestBody = getJsonRpcBody("eth_estimateGas", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - logger.info("test09requestBody:" + requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String dataResult = responseContent.getString("result"); - Assert.assertEquals("0x0", dataResult); - } - - @Test(enabled = true, description = "Json rpc api of eth_gasPrice from solidity") - public void test10JsonRpcApiTestForEthGasPrice() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_gasPrice", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - responseContent.get("result"); - String gasPrice = responseContent.get("result").toString().substring(2); - long gasPriceFromJsonrpc = Long.parseLong(gasPrice, 16); - logger.info(String.valueOf(gasPriceFromJsonrpc)); - response = HttpMethed.getChainParameters(httpFullNode); - responseContent = HttpMethed.parseResponseContent(response); - JSONArray temp; - temp = responseContent.getJSONArray("chainParameter"); - for (int i = 0; i < temp.size(); i++) { - if (temp.getJSONObject(i).get("key").equals("getEnergyFee")) { - gasPriceFromHttp = temp.getJSONObject(i).getLong("value"); - } - } - logger.info("gasPriceFromHttp:" + gasPriceFromHttp); - Assert.assertEquals(gasPriceFromJsonrpc, gasPriceFromHttp); - } - - @Test(enabled = true, description = "Json rpc api of eth_getBalance from solidity") - public void test11JsonRpcApiTestForEthGetBalance() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x" + ByteArray.toHexString(foundationAccountAddress).substring(2)); - params.add("latest"); - JsonObject requestBody = getJsonRpcBody("eth_getBalance", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String balance = responseContent.getString("result").substring(2); - Long balance1 = Long.parseLong(balance, 16); - logger.info("balance1:" + balance1); - response = HttpMethed.getAccountFromSolidity(httpsolidityNode, foundationAccountAddress); - responseContent = HttpMethed.parseResponseContent(response); - Long balance2 = responseContent.getLong("balance"); - logger.info(balance1.toString()); - logger.info(balance2.toString()); - Assert.assertEquals(balance1, balance2); - } - - @Test( - enabled = true, - description = "Json rpc api of eth_getBlockTransactionCountByNumber from solidity") - public void test12JsonRpcApiTestForEthGetBlockTransactionCountByNum() throws Exception { - response = HttpMethed.getNowBlockFromSolidity(httpsolidityNode); - responseContent = HttpMethed.parseResponseContent(response); - JsonArray params = new JsonArray(); - params.add("earliest"); - JsonObject requestBody = getJsonRpcBody("eth_getBlockTransactionCountByNumber", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String transactionNum = responseContent.getString("result").substring(2); - int transactionNum1 = Integer.parseInt(transactionNum, 16); - logger.info(String.valueOf(transactionNum1)); - response = HttpMethed.getTransactionCountByBlocknumFromSolidity(httpsolidityNode, 0); - responseContent = HttpMethed.parseResponseContent(response); - int transactionNum2 = responseContent.getInteger("count"); - logger.info(String.valueOf(transactionNum2)); - Assert.assertEquals(transactionNum1, transactionNum2); - } - - @Test(enabled = true, description = "Json rpc api of eth_getCode from solidity") - public void test13JsonRpcApiTestForEthGetCode() throws Exception { - - JsonArray params = new JsonArray(); - params.add(contractAddressFrom58); - params.add("latest"); - JsonObject requestBody = getJsonRpcBody("eth_getCode", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String codeFromJsonRpc = responseContent.getString("result").substring(2); - logger.info(codeFromJsonRpc); - response = HttpMethed.getContractInfo(httpFullNode, contractAddressFrom58); - logger.info("13contractAddressFrom58:" + contractAddressFrom58); - responseContent = HttpMethed.parseResponseContent(response); - String codeFromHttp = responseContent.getString("runtimecode"); - logger.info(codeFromHttp); - Assert.assertEquals(codeFromJsonRpc, codeFromHttp); - } - - @Test(enabled = true, description = "Json rpc api of eth_getStorageAt from solidity") - public void test14JsonRpcApiTestForEthGetStorageAt01() throws Exception { - - JsonArray params = new JsonArray(); - params.add(contractAddressFrom58); - params.add("0x0"); - params.add("latest"); - JsonObject requestBody = getJsonRpcBody("eth_getStorageAt", params); - logger.info("requestBody:" + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("14responseContent:" + responseContent); - String result = responseContent.getString("result").substring(2); - long resultExpect = Long.parseLong(result, 16); - logger.info("result:" + resultExpect); - Assert.assertEquals("1234", String.valueOf(resultExpect)); - } - - @Test(enabled = true, description = "Json rpc api of eth_getStorageAt from solidity") - public void test15JsonRpcApiTestForEthGetStorageAt02() throws Exception { - - String address = - "000000000000000000000000" + ByteArray.toHexString(jsonRpcOwnerAddress).substring(2); - String str = address + "0000000000000000000000000000000000000000000000000000000000000001"; - logger.info("str:" + str); - JsonArray paramsForSha3 = new JsonArray(); - paramsForSha3.add(str); - JsonObject requestBodyForSha3 = getJsonRpcBody("web3_sha3", paramsForSha3); - logger.info("requestBodyForSha3:" + requestBodyForSha3); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBodyForSha3); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("responseContent:" + responseContent); - String resultForSha3 = responseContent.getString("result"); - logger.info("resultForSha3:" + resultForSha3); - JsonArray params = new JsonArray(); - params.add(contractAddressFrom58); - params.add(resultForSha3); - params.add("latest"); - JsonObject requestBody = getJsonRpcBody("eth_getStorageAt", params); - logger.info("requestBody:" + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("15responseContent:" + responseContent); - String result = responseContent.getString("result").substring(2); - logger.info("15result:" + result); - logger.info("mapResult:" + Integer.parseInt(result, 16)); - Assert.assertEquals("5678", String.valueOf(Integer.parseInt(result, 16))); - } - - @Test( - enabled = true, - description = "Json rpc api of eth_getTransactionByBlockNumberAndIndex from solidity") - public void test16JsonRpcApiTestForEthGetTransactionByBlockNumberAndIndex() throws Exception { - logger.info("16blockNum:" + blockNum); - blockNumHex = "0x" + Integer.toHexString(blockNum); - logger.info("blockNumHex:" + blockNumHex); - JsonArray params = new JsonArray(); - params.add(blockNumHex); - indexNum = 0; - response = HttpMethed.getBlockByNumFromSolidity(httpsolidityNode, blockNum); - responseContent = HttpMethed.parseResponseContent(response); - parentHash = - responseContent - .getJSONObject("block_header") - .getJSONObject("raw_data") - .getString("parentHash"); - txTrieRoot = - responseContent - .getJSONObject("block_header") - .getJSONObject("raw_data") - .getString("txTrieRoot"); - witnessAddress = - responseContent - .getJSONObject("block_header") - .getJSONObject("raw_data") - .getString("witness_address"); - feeLimit = - responseContent - .getJSONArray("transactions") - .getJSONObject(0) - .getJSONObject("raw_data") - .getString("fee_limit"); - logger.info(feeLimit); - - JSONObject getBlockByNumFromSolidityResult = null; - for (int i = 0; i < responseContent.getJSONArray("transactions").size(); i++) { - if (txid.equals( - responseContent.getJSONArray("transactions").getJSONObject(i).getString("txID"))) { - indexNum = i; - getBlockByNumFromSolidityResult = - responseContent.getJSONArray("transactions").getJSONObject(i); - bid = responseContent.getString("blockID"); - break; - } - } - transactionIdList = new ArrayList<>(); - if (responseContent.getJSONArray("transactions").size() > 0) { - for (int i = 0; i < responseContent.getJSONArray("transactions").size(); i++) { - transactionIdList.add( - "0x" + responseContent.getJSONArray("transactions").getJSONObject(i).getString("txID")); - } - } - logger.info("16transactionIdList:" + transactionIdList); - logger.info(String.valueOf(indexNum)); - indexHex = "0x" + Integer.toHexString(indexNum); - logger.info("indexHex:" + indexHex); - params.add(indexHex); - JsonObject requestBody = getJsonRpcBody("eth_getTransactionByBlockNumberAndIndex", params); - logger.info("13requestBody:" + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - result = responseContent.getJSONObject("result"); - logger.info("16 result" + result); - Map jsonrpcResult = new HashMap(); - for (Map.Entry entry : result.entrySet()) { - jsonrpcResult.put(entry.getKey(), entry.getValue()); - } - transacionHash = jsonrpcResult.get("hash").toString(); - logger.info("transactionHash:" + transacionHash); - blockHash = jsonrpcResult.get("blockHash").toString(); - logger.info("jsonrpcResult:" + jsonrpcResult); - response = HttpMethed.getTransactionInfoByBlocknumFromSolidity(httpsolidityNode, blockNum); - logger.info("response:" + response); - List responseContent1 = HttpMethed.parseResponseContentArray(response); - logger.info("responseContent1:" + responseContent1); - blockTimeStamp = responseContent1.get(0).getLong("blockTimeStamp"); - - for (int i = 0; i < responseContent1.size(); i++) { - if (responseContent1.get(i).getString("id").equals(transactionIdList.get(0).substring(2))) { - gas = responseContent1.get(i).getJSONObject("receipt").getLong("energy_usage_total"); - logger.info("gas:" + gas); - break; - } - } - - Assert.assertEquals(jsonrpcResult.get("gas").toString(), "0x" + Long.toHexString(gas)); - Assert.assertNull(jsonrpcResult.get("nonce")); - Assert.assertEquals( - jsonrpcResult.get("hash").toString(), - "0x" + getBlockByNumFromSolidityResult.getString("txID")); - Assert.assertEquals(jsonrpcResult.get("blockHash").toString(), "0x" + bid); - Assert.assertEquals(jsonrpcResult.get("blockNumber").toString(), blockNumHex); - Assert.assertEquals(jsonrpcResult.get("transactionIndex").toString(), indexHex); - Assert.assertEquals( - jsonrpcResult.get("from").toString(), - "0x" - + getBlockByNumFromSolidityResult - .getJSONObject("raw_data") - .getJSONArray("contract") - .getJSONObject(0) - .getJSONObject("parameter") - .getJSONObject("value") - .getString("owner_address") - .substring(2)); - Assert.assertEquals( - jsonrpcResult.get("to").toString(), - "0x" - + getBlockByNumFromSolidityResult - .getJSONObject("raw_data") - .getJSONArray("contract") - .getJSONObject(0) - .getJSONObject("parameter") - .getJSONObject("value") - .getString("contract_address") - .substring(2)); - - Assert.assertEquals(jsonrpcResult.get("value").toString(), "0x1389"); - String data; - if (getBlockByNumFromSolidityResult.getJSONObject("raw_data").getString("data") == null) { - data = "0x"; - } else { - data = - getBlockByNumFromSolidityResult.getJSONObject("raw_data").getString("data").substring(2); - } - Assert.assertEquals(jsonrpcResult.get("input").toString(), data); - - long temp = - Long.parseLong( - getBlockByNumFromSolidityResult.getString("signature").substring(130, 131), 16); - long v = - Long.parseLong( - getBlockByNumFromSolidityResult.getString("signature").substring(130, 132), 16); - if (temp < 27) { - v += 27; - } - Assert.assertEquals(Long.parseLong(jsonrpcResult.get("v").toString().substring(2), 16), v); - Assert.assertEquals( - jsonrpcResult.get("r").toString().substring(2), - getBlockByNumFromSolidityResult.getString("signature").substring(2, 66)); - Assert.assertEquals( - jsonrpcResult.get("s").toString().substring(2), - getBlockByNumFromSolidityResult.getString("signature").substring(66, 130)); - } - - @Test( - enabled = true, - description = "Json rpc api of eth_getBlockTransactionCountByHash from solidity") - public void test17JsonRpcApiTestForEthGetBlockTransactionCountByHash() throws Exception { - logger.info("blockNum:" + blockNum); - JsonArray params = new JsonArray(); - params.add(blockHash); - logger.info("blockHash:" + blockHash); - JsonObject requestBody = getJsonRpcBody("eth_getBlockTransactionCountByHash", params); - logger.info("requestBody:" + requestBody); - HttpMethed.waitToProduceOneBlock(httpFullNode); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("responseContent:" + responseContent); - String transactionNum = responseContent.getString("result").substring(2); - int transactionNumFromjsonRpcNodeForSolidity = Integer.parseInt(transactionNum, 16); - logger.info( - "transactionNumFromjsonRpcNodeForSolidity:" + transactionNumFromjsonRpcNodeForSolidity); - response = HttpMethed.getTransactionCountByBlocknumFromSolidity(httpsolidityNode, blockNum); - responseContent = HttpMethed.parseResponseContent(response); - int transactionNumFromHttp = responseContent.getInteger("count"); - logger.info("transactionNumFromHttp:" + transactionNumFromHttp); - Assert.assertEquals(transactionNumFromHttp, transactionNumFromjsonRpcNodeForSolidity); - } - - @Test( - enabled = true, - description = "Json rpc api of eth_getBlockTransactionCountByNumber from solidity") - public void test18JsonRpcApiTestForEthGetBlockTransactionCountByNum() throws Exception { - JsonArray params = new JsonArray(); - params.add(blockNum); - logger.info(String.valueOf(blockNum)); - JsonObject requestBody = getJsonRpcBody("eth_getBlockTransactionCountByNumber", params); - logger.info("requestBody:" + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - logger.info("response:" + response); - HttpMethed.waitToProduceOneBlock(httpFullNode); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("responseContent:" + responseContent); - String transactionNum = responseContent.getString("result").substring(2); - int transactionNum1 = Integer.parseInt(transactionNum, 16); - logger.info(String.valueOf(transactionNum1)); - response = HttpMethed.getTransactionCountByBlocknumFromSolidity(httpsolidityNode, blockNum); - responseContent = HttpMethed.parseResponseContent(response); - int transactionNum2 = responseContent.getInteger("count"); - logger.info(String.valueOf(transactionNum2)); - Assert.assertEquals(transactionNum1, transactionNum2); - } - - @Test( - enabled = true, - description = "Json rpc api of eth_getTransactionByBlockHashAndIndex from solidity") - public void test19JsonRpcApiTestForEthGetTransactionByBlockHashAndIndex() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x" + bid); - params.add(indexHex); - logger.info("indexHex:" + indexHex); - JsonObject requestBody = getJsonRpcBody("eth_getTransactionByBlockHashAndIndex", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - JSONObject resultForGetTransactionByBlockHashAndIndex = responseContent.getJSONObject("result"); - Assert.assertEquals(result, resultForGetTransactionByBlockHashAndIndex); - } - - @Test(enabled = true, description = "Json rpc api of eth_getTransactionByHash from solidity") - public void test20JsonRpcApiTestForEthGetTransactionByHash() throws Exception { - JsonArray params = new JsonArray(); - params.add(transacionHash); - JsonObject requestBody = getJsonRpcBody("eth_getTransactionByHash", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - JSONObject result1 = responseContent.getJSONObject("result"); - Assert.assertEquals(result, result1); - } - - @Test(enabled = true, description = "Json rpc api of eth_getTransactionReceipt from solidity") - public void test21JsonRpcApiTestForEthGetTransactionReceipt() throws Exception { - JsonArray params = new JsonArray(); - Thread.sleep(6000); - params.add(trc20Txid); - JsonObject requestBody = getJsonRpcBody("eth_getTransactionReceipt", params); - logger.info("requestBody:" + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - logger.info("response:" + response); - responseContent = HttpMethed.parseResponseContent(response); - JSONObject resultFromTransactionReceipt = responseContent.getJSONObject("result"); - logger.info("resultFromTransactionReceipt:" + resultFromTransactionReceipt); - JSONArray logs = resultFromTransactionReceipt.getJSONArray("logs"); - logger.info("logs:" + logs); - logger.info("result:" + resultFromTransactionReceipt.toString()); - response = HttpMethed.getBlockByNumFromSolidity(httpsolidityNode, blockNumForTrc20); - responseContent = HttpMethed.parseResponseContent(response); - int index = 0; - for (int i = 0; i < responseContent.getJSONArray("transactions").size(); i++) { - if (trc20Txid.equals( - responseContent.getJSONArray("transactions").getJSONObject(i).getString("txID"))) { - index = i; - break; - } - } - - JsonArray paramsForTransactionByBlockNumberAndIndex = new JsonArray(); - paramsForTransactionByBlockNumberAndIndex.add("0x" + Integer.toHexString(blockNumForTrc20)); - paramsForTransactionByBlockNumberAndIndex.add("0x" + Integer.toHexString(index)); - JsonObject requestBody1 = - getJsonRpcBody( - "eth_getTransactionByBlockNumberAndIndex", paramsForTransactionByBlockNumberAndIndex); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody1); - logger.info("requestBody1:" + requestBody1); - responseContent = HttpMethed.parseResponseContent(response); - JSONObject resultFromTransactionByBlockNumberAndIndex = responseContent.getJSONObject("result"); - logger.info( - "resultFromTransactionByBlockNumberAndIndex:" + resultFromTransactionByBlockNumberAndIndex); - Assert.assertEquals( - resultFromTransactionReceipt.getString("blockHash"), - resultFromTransactionByBlockNumberAndIndex.getString("blockHash")); - Assert.assertEquals( - resultFromTransactionReceipt.getString("blockNumber"), - resultFromTransactionByBlockNumberAndIndex.getString("blockNumber")); - Assert.assertEquals( - resultFromTransactionReceipt.getString("transactionIndex"), - resultFromTransactionByBlockNumberAndIndex.getString("transactionIndex")); - Assert.assertEquals( - resultFromTransactionReceipt.getString("transactionHash"), "0x" + trc20Txid); - Assert.assertEquals( - resultFromTransactionReceipt.getString("from"), - resultFromTransactionByBlockNumberAndIndex.getString("from")); - Assert.assertEquals( - resultFromTransactionReceipt.getString("to"), - resultFromTransactionByBlockNumberAndIndex.getString("to")); - logger.info("effectiveGasPrice:" + resultFromTransactionReceipt.getString("effectiveGasPrice")); - logger.info("gasPriceFromHttp:" + Long.toHexString(gasPriceFromHttp)); - Assert.assertEquals( - resultFromTransactionReceipt.getString("effectiveGasPrice"), - "0x" + Long.toHexString(gasPriceFromHttp)); - /* Assert.assertEquals( - resultFromTransactionReceipt.getString("contractAddress").substring(2), - trc20AddressHex.substring(2));*/ - Assert.assertNull(resultFromTransactionReceipt.getString("contractAddress")); - Assert.assertEquals( - resultFromTransactionReceipt.getString("logsBloom"), - "0x000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000"); - Assert.assertEquals("0x1", resultFromTransactionReceipt.getString("status")); - Assert.assertEquals("0x0", resultFromTransactionReceipt.getString("type")); - logger.info("gas:" + resultFromTransactionByBlockNumberAndIndex.getString("gas")); - Assert.assertEquals( - resultFromTransactionReceipt.getString("gasUsed"), - resultFromTransactionByBlockNumberAndIndex.getString("gas")); - Assert.assertEquals( - resultFromTransactionReceipt.getString("cumulativeGasUsed"), - resultFromTransactionByBlockNumberAndIndex.getString("gas")); - Assert.assertEquals( - logs.getJSONObject(0).getString("logIndex"), "0x" + Integer.toHexString(index)); - Assert.assertEquals(logs.getJSONObject(0).getString("removed"), "false"); - Assert.assertEquals( - logs.getJSONObject(0).getString("blockHash"), - resultFromTransactionReceipt.getString("blockHash")); - Assert.assertEquals( - logs.getJSONObject(0).getString("blockNumber"), - resultFromTransactionReceipt.getString("blockNumber")); - Assert.assertEquals( - logs.getJSONObject(0).getString("transactionIndex"), - resultFromTransactionReceipt.getString("transactionIndex")); - Assert.assertEquals( - logs.getJSONObject(0).getString("transactionHash"), - resultFromTransactionReceipt.getString("transactionHash")); - Assert.assertEquals( - logs.getJSONObject(0).getString("address"), resultFromTransactionReceipt.getString("to")); - response = - HttpMethed.getTransactionInfoByBlocknumFromSolidity(httpsolidityNode, blockNumForTrc20); - List responseContent1 = HttpMethed.parseResponseContentArray(response); - logger.info("responseContent1:" + responseContent1); - - response = HttpMethed.getBlockByNumFromSolidity(httpsolidityNode, blockNumForTrc20); - responseContent = HttpMethed.parseResponseContent(response); - Assert.assertEquals( - logs.getJSONObject(0).getString("data").substring(2), - responseContent1.get(index).getJSONArray("log").getJSONObject(0).getString("data")); - - Assert.assertEquals( - logs.getJSONObject(0).getString("topics").replace("0x", ""), - responseContent1.get(index).getJSONArray("log").getJSONObject(0).getString("topics")); - } - - @Test( - enabled = true, - description = "Json rpc api of eth_getUncleByBlockHashAndIndex from solidity") - public void test22JsonRpcApiTestForEthGetUncleByBlockHashAndIndex() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x0000000000f9cc56243898cbe88685678855e07f51c5af91322c225ce3693868"); - params.add("0x"); - JsonObject requestBody = getJsonRpcBody("eth_getUncleByBlockHashAndIndex", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String result = responseContent.getString("result"); - logger.info(result); - Assert.assertNull(result); - } - - @Test( - enabled = true, - description = "Json rpc api of eth_getUncleByBlockNumberAndIndex from solidity") - public void test23JsonRpcApiTestForEthGetUncleByBlockNumberAndIndex() throws Exception { - JsonArray params = new JsonArray(); - params.add("0xeb82f0"); - params.add("0x"); - JsonObject requestBody = getJsonRpcBody("eth_getUncleByBlockNumberAndIndex", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String result = responseContent.getString("result"); - logger.info(result); - Assert.assertNull(result); - } - - @Test(enabled = true, description = "Json rpc api of eth_getUncleCountByBlockHash from solidity") - public void test24JsonRpcApiTestForEthGetUncleCountByBlockHash() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x0000000000f9cc56243898cbe88685678855e07f51c5af91322c225ce3693868"); - JsonObject requestBody = getJsonRpcBody("eth_getUncleCountByBlockHash", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String result = responseContent.getString("result"); - logger.info(result); - Assert.assertEquals(result, "0x0"); - } - - @Test( - enabled = true, - description = "Json rpc api of eth_getUncleCountByBlockNumber from solidity") - public void test25JsonRpcApiTestForEthGetUncleCountByBlockNumber() throws Exception { - JsonArray params = new JsonArray(); - params.add("eth_getUncleCountByBlockNumber"); - JsonObject requestBody = getJsonRpcBody("eth_getUncleCountByBlockNumber", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String result = responseContent.getString("result"); - logger.info(result); - Assert.assertEquals(result, "0x0"); - } - - @Test(enabled = true, description = "Json rpc api of eth_getWork from solidity") - public void test26JsonRpcApiTestForEthGetWork() throws Exception { - String resultFromjsonRpcNodeForSolidity = ""; - String resultFromHttp = ""; - for (int i = 0; i < 5; i++) { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_getWork", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String result = responseContent.getString("result"); - int resultLen = result.length(); - resultFromjsonRpcNodeForSolidity = result.substring(4, resultLen - 12); - response = HttpMethed.getNowBlockFromSolidity(httpsolidityNode); - responseContent = HttpMethed.parseResponseContent(response); - resultFromHttp = responseContent.getString("blockID"); - logger.info("resultFromjsonRpcNodeForSolidity" + i + ":" + resultFromjsonRpcNodeForSolidity); - logger.info("resultFromHttp" + i + ":" + resultFromHttp); - if (resultFromjsonRpcNodeForSolidity.equals(resultFromHttp)) { - break; - } - HttpMethed.waitToProduceOneBlock(httpFullNode); - } - Assert.assertEquals(resultFromjsonRpcNodeForSolidity, resultFromHttp); - } - - @Test(enabled = true, description = "Json rpc api of eth_hashrate from solidity ") - public void test27JsonRpcApiTestForEthHashRate() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_hashrate", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String result = responseContent.getString("result"); - logger.info(result); - Assert.assertEquals("0x0", result); - } - - @Test(enabled = true, description = "Json rpc api of eth_mining from solidity") - public void test28JsonRpcApiTestForEthMining() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_mining", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String result = responseContent.getString("result"); - logger.info(result); - Assert.assertEquals(result, "true"); - } - - @Test(enabled = true, description = "Json rpc api of eth_protocolVersion from solidity") - public void test29JsonRpcApiTestForEthProtocolVersion() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_protocolVersion", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String protocolVersion = responseContent.getString("result").substring(2); - Long protocolVersion1 = Long.parseLong(protocolVersion, 16); - response = HttpMethed.getNowBlockFromSolidity(httpsolidityNode); - responseContent = HttpMethed.parseResponseContent(response); - Long protocolVersion2 = - responseContent.getJSONObject("block_header").getJSONObject("raw_data").getLong("version"); - logger.info(protocolVersion1.toString()); - logger.info(protocolVersion2.toString()); - Assert.assertEquals(protocolVersion1, protocolVersion2); - } - - @Test(enabled = true, description = "Json rpc api of eth_syncing from solidity") - public void test30JsonRpcApiTestForEthSyncing() throws Exception { - long currentNumFromHttp = 0; - long currentNumFromJsonRpc = 0; - JSONObject temp = responseContent; - for (int i = 0; i < 5; i++) { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_syncing", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - temp = responseContent.getJSONObject("result"); - String currentNumFromRpc = temp.getString("currentBlock"); - logger.info(currentNumFromRpc); - logger.info(temp.toString()); - response = HttpMethed.getNowBlockFromSolidity(httpsolidityNode); - responseContent = HttpMethed.parseResponseContent(response); - currentNumFromHttp = - responseContent.getJSONObject("block_header").getJSONObject("raw_data").getLong("number"); - currentNumFromJsonRpc = Long.parseLong(currentNumFromRpc.substring(2), 16); - logger.info("currentNumFromHttp" + i + ":" + currentNumFromHttp); - logger.info("currentNumFromJsonRpc:" + currentNumFromJsonRpc); - if (currentNumFromHttp == currentNumFromJsonRpc) { - break; - } - HttpMethed.waitToProduceOneBlock(httpFullNode); - } - Assert.assertEquals(currentNumFromHttp, currentNumFromJsonRpc); - Assert.assertTrue(temp.containsKey("startingBlock")); - Assert.assertTrue(temp.containsKey("currentBlock")); - Assert.assertTrue(temp.containsKey("highestBlock")); - } - - @Test(enabled = true, description = "Json rpc api of net_listening from solidity") - public void test31JsonRpcApiTestForNetListening() throws Exception { - boolean temp = false; - boolean expect = false; - for (int i = 0; i < 5; i++) { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("net_listening", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - temp = responseContent.getBoolean("result"); - response = HttpMethed.getNodeInfo(httpsolidityNode); - responseContent = HttpMethed.parseResponseContent(response); - int num = responseContent.getInteger("activeConnectCount"); - logger.info("num" + i + ":" + num); - if (num >= 1) { - expect = true; - } - logger.info("temp" + i + ":" + temp); - logger.info("expect" + i + ":" + expect); - if (temp == true && expect == true) { - break; - } - HttpMethed.waitToProduceOneBlock(httpFullNode); - } - Assert.assertEquals(expect, temp); - } - - @Test(enabled = true, description = "Json rpc api of net_peerCount from solidity") - public void test32JsonRpcApiTestForNetPeerCount() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("net_peerCount", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String result = responseContent.getString("result"); - logger.info(result); - Assert.assertNotNull(result); - } - - @Test(enabled = true, description = "Json rpc api of net_version from solidity") - public void test33JsonRpcApiTestForEthVersion() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("net_version", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String firstBlockHashFromJsonRpc = responseContent.getString("result").substring(2); - response = HttpMethed.getBlockByNumFromSolidity(httpsolidityNode, 0); - responseContent = HttpMethed.parseResponseContent(response); - String firstBlockHashFromHttp = responseContent.getString("blockID").substring(56); - logger.info("firstBlockHashFromJsonRpc" + firstBlockHashFromJsonRpc); - logger.info("firstBlockHashFromHttp" + firstBlockHashFromHttp); - Assert.assertEquals(firstBlockHashFromJsonRpc, firstBlockHashFromHttp); - } - - @Test(enabled = true, description = "Json rpc api of web3_clientVersion from solidity") - public void test34JsonRpcApiTestForWeb3ClientVersion() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("web3_clientVersion", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String result = responseContent.getString("result"); - List resultList = new ArrayList<>(); - for (String str : result.split("/")) { - resultList.add(str); - } - Assert.assertEquals(resultList.size(), 5); - Assert.assertEquals(resultList.get(0), "TRON"); - Assert.assertEquals(resultList.get(1).substring(0, 1), "v"); - Assert.assertEquals(resultList.get(2), "Linux"); - Assert.assertEquals(resultList.get(3), "Java1.8"); - Assert.assertEquals(resultList.get(4).substring(0, 11), "GreatVoyage"); - } - - @Test(enabled = true, description = "Json rpc api of web3_sha3 from solidity") - public void test35JsonRpcApiTestForWeb3Sha3() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x08"); - JsonObject requestBody1 = getJsonRpcBody("web3_sha3", params); - response = getEthHttps(ethHttpsNode, requestBody1); - responseContent = HttpMethed.parseResponseContent(response); - String result1 = responseContent.getString("result"); - JsonObject requestBody2 = getJsonRpcBody("web3_sha3", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody2); - responseContent = HttpMethed.parseResponseContent(response); - String result2 = responseContent.getString("result"); - Assert.assertEquals(result1, result2); - } - - @Test(enabled = true, description = "Json rpc api of eth_compileLLL from solidity") - public void test36JsonRpcApiTestForEthCompileLll() throws Exception { - JsonArray params = new JsonArray(); - params.add("(returnlll (suicide (caller)))"); - JsonObject requestBody1 = getJsonRpcBody("eth_compileLLL", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody1); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals(errorMessage, "the method eth_compileLLL does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_compileSerpent from solidity") - public void test37JsonRpcApiTestForEthCompileSerpent() throws Exception { - JsonArray params = new JsonArray(); - params.add("/* some serpent */"); - JsonObject requestBody = getJsonRpcBody("eth_compileSerpent", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals( - errorMessage, "the method eth_compileSerpent does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_compileSolidity from solidity") - public void test38JsonRpcApiTestForEthCompileSolidity() throws Exception { - JsonArray params = new JsonArray(); - params.add("contract test { function multiply(uint a) returns(uint d) { return a * 7; } }"); - JsonObject requestBody = getJsonRpcBody("eth_compileSolidity", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals( - errorMessage, "the method eth_compileSolidity does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_getCompilers from solidity") - public void test39JsonRpcApiTestForEthCompileSolidity() throws Exception { - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_getCompilers", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals( - errorMessage, "the method eth_getCompilers does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_getTransactionCount from solidity") - public void test40JsonRpcApiTestForEthGetTransactionCount() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x407d73d8a49eeb85d32cf465507dd71d507100c1"); - params.add("latest"); - JsonObject requestBody = getJsonRpcBody("eth_getTransactionCount", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals( - errorMessage, "the method eth_getTransactionCount does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_sendRawTransaction from solidity") - public void test41JsonRpcApiTestForEthSendRawTransaction() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x234"); - JsonObject requestBody = getJsonRpcBody("eth_sendRawTransaction", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals( - errorMessage, "the method eth_sendRawTransaction does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_sendTransaction") - public void test42JsonRpcApiTestForEthSendTransaction() throws Exception { - JsonArray params = new JsonArray(); - JsonObject temp = new JsonObject(); - params.add(temp); - temp.addProperty("from", "0xb60e8dd61c5d32be8058bb8eb970870f07233155"); - temp.addProperty("to", "0xd46e8dd67c5d32be8058bb8eb970870f07244567"); - temp.addProperty("gas", "0x76c0"); - temp.addProperty("gasPrice", "0x9184e72a000"); - temp.addProperty( - "data", - "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"); - temp.addProperty("value", "0x9184e72a"); - - JsonObject requestBody = getJsonRpcBody("eth_sendTransaction", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals( - errorMessage, "the method eth_sendTransaction does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_sign from solidity") - public void test43JsonRpcApiTestForEthSign() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x9b2055d370f73ec7d8a03e965129118dc8f5bf83"); - params.add("0xdeadbeaf"); - JsonObject requestBody = getJsonRpcBody("eth_sign", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals(errorMessage, "the method eth_sign does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_signTransaction from solidity") - public void test44JsonRpcApiTestForEthSignTransaction() throws Exception { - JsonArray params = new JsonArray(); - JsonObject temp = new JsonObject(); - params.add(temp); - temp.addProperty( - "data", - "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"); - temp.addProperty("from", "0xb60e8dd61c5d32be8058bb8eb970870f07233155"); - temp.addProperty("gas", "0x76c0"); - temp.addProperty("gasPrice", "0x9184e72a000"); - temp.addProperty("to", "0xd46e8dd67c5d32be8058bb8eb970870f07244567"); - temp.addProperty("value", "0x9184e72a"); - - JsonObject requestBody = getJsonRpcBody("eth_signTransaction", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals( - errorMessage, "the method eth_signTransaction does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_submitWork from solidity") - public void test45JsonRpcApiTestForEthSubmitWork() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x0000000000000001"); - params.add("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"); - params.add("0xD1GE5700000000000000000000000000D1GE5700000000000000000000000000"); - JsonObject requestBody = getJsonRpcBody("eth_submitWork", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals(errorMessage, "the method eth_submitWork does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of parity_nextNonce from solidity") - public void test46JsonRpcApiTestForParityNextNonce() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x9b2055d370f73ec7d8a03e965129118dc8f5bf83"); - JsonObject requestBody = getJsonRpcBody("parity_nextNonce", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals( - errorMessage, "the method parity_nextNonce does not exist/is not available"); - } - - @Test(enabled = true, description = "Json rpc api of eth_submitHashrate from solidity") - public void test47JsonRpcApiTestForEthSubmitHashrate() throws Exception { - JsonArray params = new JsonArray(); - params.add("0x0000000000000000000000000000000000000000000000000000000000500000"); - params.add("0x59daa26581d0acd1fce254fb7e85952f4c09d0915afd33d3886cd914bc7d283c"); - JsonObject requestBody = getJsonRpcBody("eth_submitHashrate", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String errorMessage = responseContent.getJSONObject("error").getString("message"); - Assert.assertEquals( - errorMessage, "the method eth_submitHashrate does not exist/is not available"); - } - - @Test( - enabled = true, - description = "Json rpc api of eth_getBlockByHash params is false from solidity") - public void test48JsonRpcApiTestForEthGetBlockByHash() throws Exception { - response = HttpMethed.getBlockByNumFromSolidity(httpsolidityNode, blockNum); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("45getBlockByNumFromSolidityFromHttp:" + responseContent); - accountStateRoot = - responseContent - .getJSONObject("block_header") - .getJSONObject("raw_data") - .getString("accountStateRoot"); - JsonArray params = new JsonArray(); - params.add(blockHash); - params.add(false); - JsonObject requestBody = getJsonRpcBody("eth_getBlockByHash", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - JSONObject getBlockByHashResult = responseContent.getJSONObject("result"); - - Assert.assertNull(getBlockByHashResult.getString("nonce")); - Assert.assertNull(getBlockByHashResult.getString("sha3Uncles")); - Assert.assertNull(getBlockByHashResult.getString("receiptsRoot")); - Assert.assertNull(getBlockByHashResult.getString("difficulty")); - Assert.assertNull(getBlockByHashResult.getString("totalDifficulty")); - Assert.assertNull(getBlockByHashResult.getString("extraData")); - Assert.assertNull(getBlockByHashResult.getString("baseFeePerGas")); - Assert.assertNull(getBlockByHashResult.getString("mixHash")); - Assert.assertEquals(getBlockByHashResult.getString("uncles"), new ArrayList<>().toString()); - Assert.assertEquals(getBlockByHashResult.getString("stateRoot"), "0x" + accountStateRoot); - - Assert.assertEquals( - getBlockByHashResult.getString("logsBloom"), - "0x00000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "00000000000000000000000000000000000000000000000000000000000000000000000" - + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000000000000" - + "00000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000"); - Assert.assertEquals(getBlockByHashResult.getString("number"), blockNumHex); - Assert.assertEquals(getBlockByHashResult.getString("hash"), "0x" + bid); - Assert.assertEquals(getBlockByHashResult.getString("parentHash"), "0x" + parentHash); - Assert.assertEquals(getBlockByHashResult.getString("transactionsRoot"), "0x" + txTrieRoot); - Assert.assertEquals( - getBlockByHashResult.getString("miner"), "0x" + witnessAddress.substring(2)); - Assert.assertEquals(getBlockByHashResult.getString("gasUsed"), "0x" + Long.toHexString(gas)); - Assert.assertEquals( - String.valueOf(Long.parseLong(getBlockByHashResult.getString("gasLimit").substring(2), 16)), - feeLimit); - Assert.assertEquals( - Long.parseLong(getBlockByHashResult.getString("timestamp").substring(2), 16), - blockTimeStamp); - final GrpcAPI.NumberMessage message = - GrpcAPI.NumberMessage.newBuilder().setNum(blockNum).build(); - HttpMethed.waitToProduceOneBlock(httpFullNode); - Block block = blockingStubFull.getBlockByNum(message); - logger.info("sizeFromJrpc:" + block.getSerializedSize()); - logger.info( - "sizeFromJsonRPc:" - + Long.parseLong(getBlockByHashResult.getString("size").substring(2), 16)); - size = block.getSerializedSize(); - Assert.assertEquals( - Long.parseLong(getBlockByHashResult.getString("size").substring(2), 16), - block.getSerializedSize()); - - Long.parseLong(getBlockByHashResult.getString("timestamp").substring(2), 16); - JSONArray transactionId = getBlockByHashResult.getJSONArray("transactions"); - List transactionIdListFromGetBlockByHash = new ArrayList<>(); - if (transactionId.size() > 0) { - for (int i = 0; i < transactionId.size(); i++) { - transactionIdListFromGetBlockByHash.add(transactionId.get(i).toString()); - } - } - Assert.assertEquals(transactionIdListFromGetBlockByHash, transactionIdList); - } - - @Test( - enabled = true, - description = "Json rpc api of eth_getBlockByNumFromSolidityber params is true from solidity") - public void test49JsonRpcApiTestForEthgetBlockByNumFromSolidityber() throws Exception { - - JsonArray params = new JsonArray(); - params.add(blockNumHex); - logger.info("46blockNumHex:" + blockNumHex); - params.add(true); - JsonObject requestBody = getJsonRpcBody("eth_getBlockByNumber", params); - logger.info("requestBody:" + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("responseContent:" + responseContent); - JSONObject getBlockByNumFromSolidityberResult = responseContent.getJSONObject("result"); - logger.info("getBlockByHashResult:" + getBlockByNumFromSolidityberResult); - - Assert.assertNull(getBlockByNumFromSolidityberResult.getString("nonce")); - Assert.assertNull(getBlockByNumFromSolidityberResult.getString("sha3Uncles")); - Assert.assertNull(getBlockByNumFromSolidityberResult.getString("receiptsRoot")); - Assert.assertNull(getBlockByNumFromSolidityberResult.getString("difficulty")); - Assert.assertNull(getBlockByNumFromSolidityberResult.getString("totalDifficulty")); - Assert.assertNull(getBlockByNumFromSolidityberResult.getString("extraData")); - Assert.assertNull(getBlockByNumFromSolidityberResult.getString("baseFeePerGas")); - Assert.assertNull(getBlockByNumFromSolidityberResult.getString("mixHash")); - Assert.assertEquals( - getBlockByNumFromSolidityberResult.getString("uncles"), new ArrayList<>().toString()); - Assert.assertEquals( - getBlockByNumFromSolidityberResult.getString("stateRoot"), "0x" + accountStateRoot); - Assert.assertEquals( - getBlockByNumFromSolidityberResult.getString("logsBloom"), - "0x00000000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000000000" - + "00000000000000000000000000000000000000000000000000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000"); - Assert.assertEquals(getBlockByNumFromSolidityberResult.getString("number"), blockNumHex); - Assert.assertEquals(getBlockByNumFromSolidityberResult.getString("hash"), "0x" + bid); - Assert.assertEquals( - getBlockByNumFromSolidityberResult.getString("parentHash"), "0x" + parentHash); - Assert.assertEquals( - getBlockByNumFromSolidityberResult.getString("transactionsRoot"), "0x" + txTrieRoot); - Assert.assertEquals( - getBlockByNumFromSolidityberResult.getString("miner"), "0x" + witnessAddress.substring(2)); - Assert.assertEquals( - getBlockByNumFromSolidityberResult.getString("gasUsed"), "0x" + Long.toHexString(gas)); - Assert.assertEquals( - String.valueOf( - Long.parseLong( - getBlockByNumFromSolidityberResult.getString("gasLimit").substring(2), 16)), - feeLimit); - Assert.assertEquals( - Long.parseLong(getBlockByNumFromSolidityberResult.getString("timestamp").substring(2), 16), - blockTimeStamp); - logger.info("size:" + size); - Assert.assertEquals( - Long.parseLong(getBlockByNumFromSolidityberResult.getString("size").substring(2), 16), - size); - - JSONArray transactionsList = getBlockByNumFromSolidityberResult.getJSONArray("transactions"); - logger.info("transactionsList:" + transactionsList); - List transactionInfoListFromGetBlockByHash = new ArrayList<>(); - if (transactionsList.size() > 0) { - for (int i = 0; i < transactionsList.size(); i++) { - transactionInfoListFromGetBlockByHash.add(transactionsList.get(i).toString()); - } - } - List transactionInfoListFromTransactionByBlockNumberAndIndex = new ArrayList<>(); - for (int i = 0; i < transactionsList.size(); i++) { - JsonArray paramsForEthGetTransactionByBlockNumberAndIndex = new JsonArray(); - paramsForEthGetTransactionByBlockNumberAndIndex.add(blockNumHex); - String index = "0x" + Integer.toHexString(i); - logger.info("index:" + index); - paramsForEthGetTransactionByBlockNumberAndIndex.add(index); - logger.info( - "paramsForEthGetTransactionByBlockNumberAndIndex:" - + paramsForEthGetTransactionByBlockNumberAndIndex); - JsonObject requestBodyForTransactionByBlockNumberAndIndex = - getJsonRpcBody( - "eth_getTransactionByBlockNumberAndIndex", - paramsForEthGetTransactionByBlockNumberAndIndex); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBodyForTransactionByBlockNumberAndIndex); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("responseContent:" + responseContent); - result = responseContent.getJSONObject("result"); - logger.info("result:" + result); - transactionInfoListFromTransactionByBlockNumberAndIndex.add(result.toString()); - } - Assert.assertEquals( - transactionInfoListFromGetBlockByHash, - transactionInfoListFromTransactionByBlockNumberAndIndex); - } - - /** constructor. */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts003.java deleted file mode 100644 index c566fc5532c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts003.java +++ /dev/null @@ -1,373 +0,0 @@ -package stest.tron.wallet.dailybuild.jsonrpc; - -import com.alibaba.fastjson.JSONObject; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.Test; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.JsonRpcBase; - -@Slf4j -public class Accounts003 extends JsonRpcBase { - JSONObject responseContent; - HttpResponse response; - String topic0 = null; - String topic1 = null; - String fromBlock = null; - String toBlock = null; - String newFilterResultIdfrom01 = null; - String newFilterResultIdfrom02 = null; - String blockHash = null; - - @Test(enabled = true, description = "Eth api of eth_newFilter contains nothing.") - public void test01GetNewFilterContainNothing() { - JsonObject paramBody = new JsonObject(); - JsonArray params = new JsonArray(); - params.add(paramBody); - JsonObject requestBody = getJsonRpcBody("eth_newFilter", params); - logger.info("test01GetNewFilterContainNothing_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test01GetNewFilterContainNothing_responseContent" + responseContent); - logger.info("result:" + responseContent.getString("result")); - Assert.assertNotNull(responseContent.getString("result")); - } - - @Test( - enabled = true, - description = "Eth api of eth_newFilter contains address,fromBlock and toBlock.") - public void test02GetNewFilterContainAddress() { - if (blockNumForTrc20 - 10 < 0) { - fromBlock = "0"; - } else { - fromBlock = "0x" + Integer.toHexString(blockNumForTrc20 - 10); - } - toBlock = "0x" + Integer.toHexString(blockNumForTrc20 + 10); - JsonArray addressArray = new JsonArray(); - addressArray.add(contractAddressFrom58.substring(2)); - JsonObject paramBody = new JsonObject(); - paramBody.add("address", addressArray); - paramBody.addProperty("fromBlock", fromBlock); - paramBody.addProperty("toBlock", toBlock); - JsonArray params = new JsonArray(); - params.add(paramBody); - JsonObject requestBody = getJsonRpcBody("eth_newFilter", params); - logger.info("test02GetNewFilterContainAddress_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test02GetNewFilterContainAddress_responseContent" + responseContent); - newFilterResultIdfrom01 = responseContent.getString("result"); - logger.info("test02GetNewFilterContainAddress_id:" + responseContent.getString("result")); - } - - @Test( - enabled = true, - description = "Eth api of eth_newFilter contains topic fromBlock and toBlock.") - public void test03GetNewFilterContainTopic() { - response = HttpMethed.getBlockByNum(httpFullNode, blockNumForTrc20); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("responseContent:" + responseContent); - logger.info("blockHash:" + responseContent.getString("blockID")); - - blockHash = responseContent.getString("blockID"); - JsonArray topicArray = new JsonArray(); - topicArray.add("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"); - JsonObject paramBody = new JsonObject(); - paramBody.add("topics", topicArray); - paramBody.addProperty("fromBlock", fromBlock); - paramBody.addProperty("toBlock", toBlock); - JsonArray params = new JsonArray(); - params.add(paramBody); - JsonObject requestBody = getJsonRpcBody("eth_newFilter", params); - logger.info("test03GetNewFilterContainTopic_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test03GetNewFilterContainTopic_responseContent" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - newFilterResultIdfrom02 = responseContent.getString("result"); - logger.info("test03GetNewFilterContainTopic_id:" + newFilterResultIdfrom02); - } - - @Test(enabled = true, description = "Eth api of eth_newFilter contains topic and address.") - public void test04GetNewFilterContainsTopicAndAddress() { - - JsonArray addressArray = new JsonArray(); - addressArray.add(contractAddressFrom58.substring(2)); - JsonArray topicArray = new JsonArray(); - topicArray.add("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"); - JsonObject paramBody = new JsonObject(); - paramBody.add("address", addressArray); - paramBody.add("topics", topicArray); - paramBody.addProperty("fromBlock", fromBlock); - paramBody.addProperty("toBlock", toBlock); - JsonArray params = new JsonArray(); - params.add(paramBody); - JsonObject requestBody = getJsonRpcBody("eth_newFilter", params); - logger.info("test04GetNewFilterContainsTopicAndAddress_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test04GetNewFilterContainsTopicAndAddress_responseContent" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - } - - @Test(enabled = true, description = "Eth api of eth_newFilter only contain topic and blockHash.") - public void test05GetNewFilterOnlyContainTopic() { - JsonObject paramBody = new JsonObject(); - paramBody.addProperty("blockHash", blockHash); - JsonArray topicArray = new JsonArray(); - topicArray.add("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"); - paramBody.add("topics", topicArray); - JsonArray params = new JsonArray(); - params.add(paramBody); - JsonObject requestBody = getJsonRpcBody("eth_newFilter", params); - logger.info("test05GetNewFilterOnlyContainTopic_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test05GetNewFilterOnlyContainTopic_responseContent" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - } - - @Test(enabled = true, description = "Eth api of eth_newFilter which only contains blockHash.") - public void test06GetNewFilterHasOnlyBlockHash() { - - response = HttpMethed.getNowBlock(httpFullNode); - responseContent = HttpMethed.parseResponseContent(response); - String blockHash = responseContent.getString("blockID"); - JsonObject paramBody = new JsonObject(); - paramBody.addProperty("blockHash", blockHash); - JsonArray params = new JsonArray(); - params.add(paramBody); - JsonObject requestBody = getJsonRpcBody("eth_newFilter", params); - logger.info("test06GetNewFilterHasOnlyBlockHash_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test06GetNewFilterHasOnlyBlockHash_responseContent" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - } - - @Test(enabled = true, description = "Eth api of eth_newFilter check new and after block.") - public void test07GetNewFilterCheckNewBlock() { - JsonObject paramBody = new JsonObject(); - JsonArray topicArray = new JsonArray(); - topicArray.add("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"); - paramBody.add("topics", topicArray); - JsonArray params = new JsonArray(); - params.add(paramBody); - JsonObject requestBody = getJsonRpcBody("eth_newFilter", params); - logger.info("test07GetNewFilterCheckNewBlock_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test07GetNewFilterCheckNewBlock_responseContent" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - } - - @Test(enabled = true, description = "Eth api of eth_newBlockFilter") - public void test08GetEthNewBlockFilter() { - - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_newBlockFilter", params); - logger.info("test08GetEthNewBlockFilter_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test08GetEthNewBlockFilter_responseContent:" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - } - - @Test(enabled = true, description = "Eth api of eth_getFilterChanges has less 20 elements.") - public void test09GetFilterChanges() { - - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_newBlockFilter", params); - logger.info("test15EthUninstallFilter_newBlockFilter " + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test15EthUninstallFilter_newBlockFilter_responseContentr" + responseContent); - String ethNewBlockFilterResult = responseContent.get("result").toString(); - logger.info("ethNewBlockFilterResult:" + ethNewBlockFilterResult); - String newFilterId = responseContent.getString("result"); - logger.info("newFilterId:" + newFilterId); - params = new JsonArray(); - params.add(newFilterId); - requestBody = getJsonRpcBody("eth_getFilterChanges", params); - logger.info("test09GetFilterChanges_requestBody: " + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test09GetFilterChanges_responseContent:" + responseContent); - Assert.assertEquals("[]", responseContent.getString("result")); - } - - @Test( - enabled = true, - description = "Eth api of eth_getLogs contains address ,fromBlock and toBlock.") - public void test10GetLogsOnlyContainAddress() { - JsonArray addressArray = new JsonArray(); - logger.info("contractTrc20AddressFrom58:" + contractTrc20AddressFrom58); - addressArray.add(contractTrc20AddressFrom58.substring(2)); - JsonObject paramBody = new JsonObject(); - paramBody.add("address", addressArray); - logger.info("blockNumForTrc20:" + blockNumForTrc20); - paramBody.addProperty("fromBlock", "0x" + (Integer.toHexString(blockNumForTrc20 - 20))); - paramBody.addProperty("toBlock", "0x" + (Integer.toHexString(blockNumForTrc20 + 20))); - JsonArray params = new JsonArray(); - params.add(paramBody); - JsonObject requestBody = getJsonRpcBody("eth_getLogs", params); - logger.info("test10GetLogsOnlyContainAddress_requestBody:" + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test10GetLogsOnlyContainAddress_responseContent:" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - String address = - responseContent.getJSONArray("result").getJSONObject(0).getString("address").substring(2); - Assert.assertEquals(address, contractTrc20AddressFrom58.substring(2)); - topic0 = responseContent.getJSONArray("result").getJSONObject(0).getString("topic"); - } - - @Test(enabled = true, description = "Eth api of eth_getLogs both contains topic and address.") - public void test11GetLogsContainsTopicAndAddress() { - JsonArray topicArray = new JsonArray(); - topicArray.add(topic0); - JsonObject paramBody = new JsonObject(); - paramBody.add("topics", topicArray); - paramBody.addProperty("fromBlock", "0x" + (Integer.toHexString(blockNumForTrc20 - 10))); - paramBody.addProperty("toBlock", "0x" + (Integer.toHexString(blockNumForTrc20 + 10))); - JsonArray params = new JsonArray(); - params.add(paramBody); - JsonObject requestBody = getJsonRpcBody("eth_getLogs", params); - logger.info("test11GetLogsContainsTopicAndAddress_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test11GetLogsContainsTopicAndAddress_responseContent" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - String topicFromResult = - responseContent.getJSONArray("result").getJSONObject(0).getString("topic"); - Assert.assertEquals(topicFromResult, topic0); - } - - @Test(enabled = true, description = "Eth api of eth_getFilterLogs .") - public void test12GetFilterLogsContainsAddress() { - - JsonArray params = new JsonArray(); - params.add(newFilterResultIdfrom01); - JsonObject requestBody = getJsonRpcBody("eth_getFilterLogs", params); - logger.info("test12GetFilterLogsContainsAddress_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test12GetFilterLogsContainsAddress_responseContent" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - } - - @Test(enabled = true, description = "Eth api of eth_getFilterLogs .") - public void test13GetFilterLogsContainsTopic() { - - JsonArray params = new JsonArray(); - params.add(newFilterResultIdfrom02); - JsonObject requestBody = getJsonRpcBody("eth_getFilterLogs", params); - logger.info("test13GetFilterLogsContainsTopic_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test13GetFilterLogsContainsTopic_responseContent" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - } - - @Test( - enabled = true, - description = - "Eth api of eth_uninstallFilter which method is eth_newFilter" - + " and params has one element ") - public void test14EthUninstallFilter() { - // create ID - JsonArray addressArray = new JsonArray(); - addressArray.add(contractAddressFrom58.substring(2)); - JsonObject paramBody = new JsonObject(); - paramBody.add("address", addressArray); - paramBody.addProperty("fromBlock", "0x1f8b6a7"); - paramBody.addProperty("toBlock", "0x1f8b6a7"); - JsonArray params = new JsonArray(); - params.add(paramBody); - JsonObject requestBody = getJsonRpcBody("eth_newFilter", params); - logger.info("test14_newfilter " + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test14_newfilter_responseContentr" + responseContent); - String ethNewFilterResult = responseContent.get("result").toString(); - logger.info("EthNewFilterResult:" + ethNewFilterResult); - Assert.assertNotNull(responseContent.getString("result")); - - // verify ID invalid - - // first time - params = new JsonArray(); - params.add(responseContent.get("result").toString()); - requestBody = getJsonRpcBody("eth_uninstallFilter", params); - logger.info("test14_eth_uninstallFilter " + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test14_eth_uninstallFilter_responseContentr_first" + responseContent); - Assert.assertEquals(responseContent.get("result"), true); - // second time - logger.info("test14_eth_uninstallFilter_second " + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test14_eth_uninstallFilter_responseContentr_second " + responseContent); - Assert.assertEquals( - responseContent.getJSONObject("error").getString("message"), "filter not found"); - - // query getFilterChanges to verify ID has invalid - params = new JsonArray(); - params.add(ethNewFilterResult); - requestBody = getJsonRpcBody("getFilterChanges", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test14EthUninstallFilter_responseContent" + responseContent); - String expectResult = "{\"code\":-32000,\"data\":\"{}\",\"message\":\"filter not found\"}"; - Assert.assertEquals(responseContent.get("error").toString(), expectResult); - } - - @Test( - enabled = true, - description = - "Eth api of eth_uninstallFilter which method is eth_newBlockFilter" - + " and params has one element ") - public void test15EthUninstallFilter() { - // create ID - - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_newBlockFilter", params); - logger.info("test15EthUninstallFilter_newBlockFilter " + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test15EthUninstallFilter_newBlockFilter_responseContentr" + responseContent); - String ethNewBlockFilterResult = responseContent.get("result").toString(); - logger.info("ethNewBlockFilterResult:" + ethNewBlockFilterResult); - Assert.assertNotNull(responseContent.getString("result")); - - // verify ID invalid - // first time - params = new JsonArray(); - params.add(responseContent.get("result").toString()); - requestBody = getJsonRpcBody("eth_uninstallFilter", params); - logger.info("test15_eth_uninstallFilter " + requestBody); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test15_eth_uninstallFilter_responseContentr_first" + responseContent); - Assert.assertEquals(responseContent.get("result"), true); - // second time - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test15_eth_uninstallFilter_responseContentr_second" + responseContent); - Assert.assertEquals( - responseContent.getJSONObject("error").getString("message"), "filter not found"); - // query getFilterChanges to verify ID has invalid - params = new JsonArray(); - params.add(ethNewBlockFilterResult); - requestBody = getJsonRpcBody("getFilterChanges", params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test15EthUninstallFilter_responseContent" + responseContent); - String expectResult = "{\"code\":-32000,\"data\":\"{}\",\"message\":\"filter not found\"}"; - Assert.assertEquals(responseContent.get("error").toString(), expectResult); - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts004.java deleted file mode 100644 index 6a1a67f00c4..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/Accounts004.java +++ /dev/null @@ -1,388 +0,0 @@ -package stest.tron.wallet.dailybuild.jsonrpc; - -import com.alibaba.fastjson.JSONObject; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.Test; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.JsonRpcBase; - -@Slf4j -public class Accounts004 extends JsonRpcBase { - JSONObject responseContent; - HttpResponse response; - String topic0 = null; - String topic1 = null; - String fromBlock = null; - String toBlock = null; - String newFilterResultIdfrom01 = null; - String newFilterResultIdfrom02 = null; - String blockHash = null; - - @Test(enabled = true, description = "Eth api of eth_newFilter contains nothing from solidity.") - public void test01GetNewFilterContainNothing() { - JsonObject paramBody = new JsonObject(); - JsonArray params = new JsonArray(); - params.add(paramBody); - JsonObject requestBody = getJsonRpcBody("eth_newFilter", params); - logger.info("test01GetNewFilterContainNothing_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test01GetNewFilterContainNothing_responseContent" + responseContent); - logger.info("result:" + responseContent.getString("result")); - Assert.assertNotNull(responseContent.getString("result")); - } - - @Test( - enabled = true, - description = - "Eth api of eth_newFilter contains address,fromBlock and toBlock from solidity.") - public void test02GetNewFilterContainAddress() { - if (blockNumForTrc20 - 10 < 0) { - fromBlock = "0"; - } else { - fromBlock = "0x" + Integer.toHexString(blockNumForTrc20 - 10); - } - toBlock = "0x" + Integer.toHexString(blockNumForTrc20 + 10); - JsonArray addressArray = new JsonArray(); - addressArray.add(contractAddressFrom58.substring(2)); - JsonObject paramBody = new JsonObject(); - paramBody.add("address", addressArray); - paramBody.addProperty("fromBlock", fromBlock); - paramBody.addProperty("toBlock", toBlock); - JsonArray params = new JsonArray(); - params.add(paramBody); - JsonObject requestBody = getJsonRpcBody("eth_newFilter", params); - logger.info("test02GetNewFilterContainAddress_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test02GetNewFilterContainAddress_responseContent" + responseContent); - newFilterResultIdfrom01 = responseContent.getString("result"); - logger.info("test02GetNewFilterContainAddress_id:" + responseContent.getString("result")); - } - - @Test( - enabled = true, - description = "Eth api of eth_newFilter contains topic fromBlock and toBlock from solidity.") - public void test03GetNewFilterContainTopic() { - response = HttpMethed.getBlockByNumFromSolidity(httpsolidityNode, blockNumForTrc20); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("responseContent:" + responseContent); - logger.info("blockHash:" + responseContent.getString("blockID")); - blockHash = responseContent.getString("blockID"); - JsonArray topicArray = new JsonArray(); - topicArray.add("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"); - JsonObject paramBody = new JsonObject(); - paramBody.add("topics", topicArray); - paramBody.addProperty("fromBlock", fromBlock); - paramBody.addProperty("toBlock", toBlock); - JsonArray params = new JsonArray(); - params.add(paramBody); - JsonObject requestBody = getJsonRpcBody("eth_newFilter", params); - logger.info("test03GetNewFilterContainTopic_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test03GetNewFilterContainTopic_responseContent" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - newFilterResultIdfrom02 = responseContent.getString("result"); - logger.info("test03GetNewFilterContainTopic_id:" + newFilterResultIdfrom02); - } - - @Test( - enabled = true, - description = "Eth api of eth_newFilter contains topic and address from solidity.") - public void test04GetNewFilterContainsTopicAndAddress() { - - JsonArray addressArray = new JsonArray(); - addressArray.add(contractAddressFrom58.substring(2)); - JsonArray topicArray = new JsonArray(); - topicArray.add("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"); - JsonObject paramBody = new JsonObject(); - paramBody.add("address", addressArray); - paramBody.add("topics", topicArray); - paramBody.addProperty("fromBlock", fromBlock); - paramBody.addProperty("toBlock", toBlock); - JsonArray params = new JsonArray(); - params.add(paramBody); - JsonObject requestBody = getJsonRpcBody("eth_newFilter", params); - logger.info("test04GetNewFilterContainsTopicAndAddress_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test04GetNewFilterContainsTopicAndAddress_responseContent" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - } - - @Test( - enabled = true, - description = "Eth api of eth_newFilter only contain topic and blockHash from solidity.") - public void test05GetNewFilterOnlyContainTopic() throws InterruptedException { - JsonObject paramBody = new JsonObject(); - paramBody.addProperty("blockHash", blockHash); - JsonArray topicArray = new JsonArray(); - topicArray.add("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"); - paramBody.add("topics", topicArray); - JsonArray params = new JsonArray(); - params.add(paramBody); - JsonObject requestBody = getJsonRpcBody("eth_newFilter", params); - logger.info("test05GetNewFilterOnlyContainTopic_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test05GetNewFilterOnlyContainTopic_responseContent" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - } - - @Test( - enabled = true, - description = "Eth api of eth_newFilter which only contains blockHash from solidity.") - public void test06GetNewFilterHasOnlyBlockHash() throws InterruptedException { - response = HttpMethed.getNowBlockFromSolidity(httpsolidityNode); - responseContent = HttpMethed.parseResponseContent(response); - String blockHash = responseContent.getString("blockID"); - Thread.sleep(30000); - JsonObject paramBody = new JsonObject(); - paramBody.addProperty("blockHash", blockHash); - JsonArray params = new JsonArray(); - params.add(paramBody); - JsonObject requestBody = getJsonRpcBody("eth_newFilter", params); - logger.info("test06GetNewFilterHasOnlyBlockHash_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test06GetNewFilterHasOnlyBlockHash_responseContent" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - } - - @Test( - enabled = true, - description = "Eth api of eth_newFilter check new and after block from solidity.") - public void test07GetNewFilterCheckNewBlock() { - JsonObject paramBody = new JsonObject(); - JsonArray topicArray = new JsonArray(); - topicArray.add("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"); - paramBody.add("topics", topicArray); - JsonArray params = new JsonArray(); - params.add(paramBody); - JsonObject requestBody = getJsonRpcBody("eth_newFilter", params); - logger.info("test07GetNewFilterCheckNewBlock_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test07GetNewFilterCheckNewBlock_responseContent" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - } - - @Test(enabled = true, description = "Eth api of eth_newBlockFilter from solidity") - public void test08GetEthNewBlockFilter() { - - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_newBlockFilter", params); - logger.info("test08GetEthNewBlockFilter_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test08GetEthNewBlockFilter_responseContent:" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - } - - @Test( - enabled = true, - description = "Eth api of eth_getFilterChanges has less 20 elements from solidity.") - public void test09GetFilterChanges() { - - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_newBlockFilter", params); - logger.info("test15EthUninstallFilter_newBlockFilter " + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test15EthUninstallFilter_newBlockFilter_responseContentr" + responseContent); - String ethNewBlockFilterResult = responseContent.get("result").toString(); - logger.info("ethNewBlockFilterResult:" + ethNewBlockFilterResult); - String newFilterId = responseContent.getString("result"); - logger.info("newFilterId:" + newFilterId); - params = new JsonArray(); - params.add(newFilterId); - requestBody = getJsonRpcBody("eth_getFilterChanges", params); - logger.info("test09GetFilterChanges_requestBody: " + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test09GetFilterChanges_responseContent:" + responseContent); - Assert.assertEquals("[]", responseContent.getString("result")); - } - - @Test( - enabled = true, - description = - "Eth api of eth_getLogs contains address ,fromBlock and toBlock from solidity.") - public void test10GetLogsOnlyContainAddress() { - JsonArray addressArray = new JsonArray(); - logger.info("contractTrc20AddressFrom58:" + contractTrc20AddressFrom58); - addressArray.add(contractTrc20AddressFrom58.substring(2)); - JsonObject paramBody = new JsonObject(); - paramBody.add("address", addressArray); - logger.info("blockNumForTrc20:" + blockNumForTrc20); - paramBody.addProperty("fromBlock", "0x" + (Integer.toHexString(blockNumForTrc20 - 20))); - paramBody.addProperty("toBlock", "0x" + (Integer.toHexString(blockNumForTrc20 + 20))); - JsonArray params = new JsonArray(); - params.add(paramBody); - HttpMethed.waitToProduceOneBlockFromSolidity(httpFullNode, httpsolidityNode); - JsonObject requestBody = getJsonRpcBody("eth_getLogs", params); - logger.info("test10GetLogsOnlyContainAddress_requestBody:" + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test10GetLogsOnlyContainAddress_responseContent:" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - String address = - responseContent.getJSONArray("result").getJSONObject(0).getString("address").substring(2); - Assert.assertEquals(address, contractTrc20AddressFrom58.substring(2)); - topic0 = responseContent.getJSONArray("result").getJSONObject(0).getString("topic"); - } - - @Test( - enabled = true, - description = "Eth api of eth_getLogs both contains topic and address from solidity.") - public void test11GetLogsContainsTopicAndAddress() { - JsonArray topicArray = new JsonArray(); - topicArray.add(topic0); - JsonObject paramBody = new JsonObject(); - paramBody.add("topics", topicArray); - paramBody.addProperty("fromBlock", "0x" + (Integer.toHexString(blockNumForTrc20 - 10))); - paramBody.addProperty("toBlock", "0x" + (Integer.toHexString(blockNumForTrc20 + 10))); - JsonArray params = new JsonArray(); - params.add(paramBody); - HttpMethed.waitToProduceOneBlockFromSolidity(httpFullNode, httpsolidityNode); - JsonObject requestBody = getJsonRpcBody("eth_getLogs", params); - logger.info("test11GetLogsContainsTopicAndAddress_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test11GetLogsContainsTopicAndAddress_responseContent" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - String topicFromResult = - responseContent.getJSONArray("result").getJSONObject(0).getString("topic"); - Assert.assertEquals(topicFromResult, topic0); - } - - @Test(enabled = true, description = "Eth api of eth_getFilterLogs from solidity.") - public void test12GetFilterLogsContainsAddress() { - - JsonArray params = new JsonArray(); - params.add(newFilterResultIdfrom01); - JsonObject requestBody = getJsonRpcBody("eth_getFilterLogs", params); - logger.info("test12GetFilterLogsContainsAddress_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test12GetFilterLogsContainsAddress_responseContent" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - } - - @Test(enabled = true, description = "Eth api of eth_getFilterLogs from solidity.") - public void test13GetFilterLogsContainsTopic() { - - JsonArray params = new JsonArray(); - params.add(newFilterResultIdfrom02); - JsonObject requestBody = getJsonRpcBody("eth_getFilterLogs", params); - logger.info("test13GetFilterLogsContainsTopic_requestBody " + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test13GetFilterLogsContainsTopic_responseContent" + responseContent); - Assert.assertNotNull(responseContent.getString("result")); - } - - @Test( - enabled = true, - description = - "Eth api of eth_uninstallFilter which method is eth_newFilter from solidity" - + " and params has one element ") - public void test14EthUninstallFilter() { - // create ID - JsonArray addressArray = new JsonArray(); - addressArray.add(contractAddressFrom58.substring(2)); - JsonObject paramBody = new JsonObject(); - paramBody.add("address", addressArray); - paramBody.addProperty("fromBlock", "0x1f8b6a7"); - paramBody.addProperty("toBlock", "0x1f8b6a7"); - JsonArray params = new JsonArray(); - params.add(paramBody); - JsonObject requestBody = getJsonRpcBody("eth_newFilter", params); - logger.info("test14_newfilter " + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test14_newfilter_responseContentr" + responseContent); - String ethNewFilterResult = responseContent.get("result").toString(); - logger.info("EthNewFilterResult:" + ethNewFilterResult); - Assert.assertNotNull(responseContent.getString("result")); - - // verify ID invalid - - // first time - params = new JsonArray(); - params.add(responseContent.get("result").toString()); - requestBody = getJsonRpcBody("eth_uninstallFilter", params); - logger.info("test14_eth_uninstallFilter " + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test14_eth_uninstallFilter_responseContentr_first" + responseContent); - Assert.assertEquals(responseContent.get("result"), true); - // second time - logger.info("test14_eth_uninstallFilter_second " + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test14_eth_uninstallFilter_responseContentr_second " + responseContent); - Assert.assertEquals( - responseContent.getJSONObject("error").getString("message"), "filter not found"); - - // query getFilterChanges to verify ID has invalid - params = new JsonArray(); - params.add(ethNewFilterResult); - requestBody = getJsonRpcBody("getFilterChanges", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test14EthUninstallFilter_responseContent" + responseContent); - String expectResult = "{\"code\":-32000,\"data\":\"{}\",\"message\":\"filter not found\"}"; - Assert.assertEquals(responseContent.get("error").toString(), expectResult); - } - - @Test( - enabled = true, - description = - "Eth api of eth_uninstallFilter which method is eth_newBlockFilter" - + " and params has one element from solidity") - public void test15EthUninstallFilter() { - // create ID - - JsonArray params = new JsonArray(); - JsonObject requestBody = getJsonRpcBody("eth_newBlockFilter", params); - logger.info("test15EthUninstallFilter_newBlockFilter " + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test15EthUninstallFilter_newBlockFilter_responseContentr" + responseContent); - String ethNewBlockFilterResult = responseContent.get("result").toString(); - logger.info("ethNewBlockFilterResult:" + ethNewBlockFilterResult); - Assert.assertNotNull(responseContent.getString("result")); - - // verify ID invalid - // first time - params = new JsonArray(); - params.add(responseContent.get("result").toString()); - requestBody = getJsonRpcBody("eth_uninstallFilter", params); - logger.info("test15_eth_uninstallFilter " + requestBody); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test15_eth_uninstallFilter_responseContentr_first" + responseContent); - Assert.assertEquals(responseContent.get("result"), true); - // second time - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test15_eth_uninstallFilter_responseContentr_second" + responseContent); - Assert.assertEquals( - responseContent.getJSONObject("error").getString("message"), "filter not found"); - // query getFilterChanges to verify ID has invalid - params = new JsonArray(); - params.add(ethNewBlockFilterResult); - requestBody = getJsonRpcBody("getFilterChanges", params); - response = getJsonRpc(jsonRpcNodeForSolidity, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - logger.info("test15EthUninstallFilter_responseContent" + responseContent); - String expectResult = "{\"code\":-32000,\"data\":\"{}\",\"message\":\"filter not found\"}"; - Assert.assertEquals(responseContent.get("error").toString(), expectResult); - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/BuildTransaction001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/BuildTransaction001.java deleted file mode 100644 index d7f68a5f3eb..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/BuildTransaction001.java +++ /dev/null @@ -1,121 +0,0 @@ -package stest.tron.wallet.dailybuild.jsonrpc; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.JsonRpcBase; -import stest.tron.wallet.common.client.utils.PublicMethed; - - - -@Slf4j - -public class BuildTransaction001 extends JsonRpcBase { - - JSONArray jsonRpcReceives = new JSONArray(); - //String txid; - private JSONObject responseContent; - private HttpResponse response; - String transactionString; - String transactionSignString; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] receiverAddress = ecKey1.getAddress(); - final String receiverKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - - - @Test(enabled = true, description = "Json rpc api of buildTransaction for transfer trx") - public void test01JsonRpcApiTestOfBuildTransactionForTransferTrx() throws Exception { - final Long beforeRecevierBalance = HttpMethed.getBalance(httpFullNode, receiverAddress); - - - JsonObject param = new JsonObject(); - param.addProperty("from", ByteArray.toHexString(jsonRpcOwnerAddress)); - param.addProperty("to", ByteArray.toHexString(receiverAddress)); - param.addProperty("value", "0x1"); - JsonArray params = new JsonArray(); - params.add(param); - JsonObject requestBody = getJsonRpcBody("buildTransaction",params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - transactionString = responseContent.getJSONObject("result").getString("transaction"); - transactionSignString = HttpMethed.gettransactionsign(httpFullNode, transactionString, - jsonRpcOwnerKey); - response = HttpMethed.broadcastTransaction(httpFullNode, transactionSignString); - Assert.assertTrue(HttpMethed.verificationResult(response)); - - HttpMethed.waitToProduceOneBlock(httpFullNode); - Long afterRecevierBalance = HttpMethed.getBalance(httpFullNode, receiverAddress); - - Assert.assertEquals(afterRecevierBalance - beforeRecevierBalance,1L); - - } - - @Test(enabled = true, description = "Json rpc api of buildTransaction for transfer trc10") - public void test02JsonRpcApiTestOfBuildTransactionForTransferTrc10() throws Exception { - PublicMethed.waitProduceNextBlock(blockingStubFull); - final Long beforeTokenBalance = PublicMethed.getAssetBalanceByAssetId(ByteString - .copyFromUtf8(jsonRpcAssetId), receiverKey, blockingStubFull); - JsonObject param = new JsonObject(); - param.addProperty("from", ByteArray.toHexString(jsonRpcOwnerAddress)); - param.addProperty("to", ByteArray.toHexString(receiverAddress)); - param.addProperty("tokenId", Long.valueOf(jsonRpcAssetId)); - param.addProperty("tokenValue", 1); - JsonArray params = new JsonArray(); - params.add(param); - JsonObject requestBody = getJsonRpcBody("buildTransaction",params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - transactionString = responseContent.getJSONObject("result").getString("transaction"); - transactionSignString = HttpMethed.gettransactionsign(httpFullNode, transactionString, - jsonRpcOwnerKey); - response = HttpMethed.broadcastTransaction(httpFullNode, transactionSignString); - Assert.assertTrue(HttpMethed.verificationResult(response)); - - HttpMethed.waitToProduceOneBlock(httpFullNode); - Long afterTokenBalance = PublicMethed.getAssetBalanceByAssetId(ByteString - .copyFromUtf8(jsonRpcAssetId), receiverKey, blockingStubFull); - - Assert.assertEquals(afterTokenBalance - beforeTokenBalance,1L); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/EthSmartContract001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/EthSmartContract001.java deleted file mode 100644 index 0fe564ad177..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/EthSmartContract001.java +++ /dev/null @@ -1,80 +0,0 @@ -package stest.tron.wallet.dailybuild.jsonrpc; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.protobuf.ByteString; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.JsonRpcBase; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ZenTrc20Base; - - -@Slf4j - -public class EthSmartContract001 extends JsonRpcBase { - private JSONObject responseContent; - private HttpResponse response; - - @Test(enabled = true, description = "Json rpc api of eth_call") - public void test01JsonRpcApiTestForEthCall() throws Exception { - JsonObject param = new JsonObject(); - param.addProperty("from", ByteArray.toHexString(jsonRpcOwnerAddress)); - param.addProperty("to", trc20AddressHex); - param.addProperty("gas", "0x0"); - param.addProperty("gasPrice", "0x0"); - param.addProperty("value", "0x0"); - param.addProperty("data", "0x06fdde03"); - JsonArray params = new JsonArray(); - params.add(param); - params.add("latest"); - JsonObject requestBody = getJsonRpcBody("eth_call",params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String dataResult = responseContent.getString("result"); - Assert.assertEquals(dataResult,"0x000000000000000000000000000000000000000000000000000" - + "0000000000020000000000000000000000000000000000000000000000000000000000000000a546f6b65" - + "6e545243323000000000000000000000000000000000000000000000"); - } - - - @Test(enabled = true, description = "Json rpc api of eth_estimateGas") - public void test02JsonRpcApiTestForEthEstimateGas() throws Exception { - JsonObject param = new JsonObject(); - param.addProperty("from", ByteArray.toHexString(jsonRpcOwnerAddress)); - param.addProperty("to", trc20AddressHex); - param.addProperty("gas", "0x0"); - param.addProperty("gasPrice", "0x0"); - param.addProperty("value", "0x0"); - param.addProperty("data", "0x1249c58b"); - JsonArray params = new JsonArray(); - params.add(param); - JsonObject requestBody = getJsonRpcBody("eth_estimateGas",params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String dataResult = responseContent.getString("result"); - Assert.assertEquals(dataResult,"0x147"); - } - - - @Test(enabled = true, description = "Json rpc api of eth_getCode") - public void test03JsonRpcApiTestForEthGetCode() throws Exception { - JsonArray params = new JsonArray(); - params.add(trc20AddressHex); - params.add("latest"); - JsonObject requestBody = getJsonRpcBody("eth_getCode",params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - String dataResult = responseContent.getString("result"); - Assert.assertTrue(dataResult.length() > 1000L); - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/GetBlock001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/GetBlock001.java deleted file mode 100644 index 2614d7e8681..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/jsonrpc/GetBlock001.java +++ /dev/null @@ -1,69 +0,0 @@ -package stest.tron.wallet.dailybuild.jsonrpc; - -import com.alibaba.fastjson.JSONObject; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.utils.ByteArray; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.JsonRpcBase; - - -@Slf4j - -public class GetBlock001 extends JsonRpcBase { - private JSONObject responseContent; - private HttpResponse response; - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - - - - @Test(enabled = true, description = "Json rpc api of eth_getBlockByHash") - public void test01JsonRpcApiTestForEthGetBlockByHash() throws Exception { - JsonArray params = new JsonArray(); - params.add(blockId); - params.add("true"); - JsonObject requestBody = getJsonRpcBody("eth_getBlockByHash",params); - response = getJsonRpc(jsonRpcNode, requestBody); - responseContent = HttpMethed.parseResponseContent(response); - - Assert.assertEquals(Integer.toHexString(blockNum), responseContent.getJSONObject("result") - .getString("number").substring(2)); - Assert.assertEquals(blockId, responseContent.getJSONObject("result").getString("hash") - .substring(2)); - Assert.assertTrue(responseContent.getJSONObject("result") - .getJSONArray("transactions").size() >= 1); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage001.java deleted file mode 100644 index c1ae1bd3f8e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage001.java +++ /dev/null @@ -1,343 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractLinkage001 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] linkage001Address = ecKey1.getAddress(); - String linkage001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(linkage001Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - } - - @Test(enabled = true, description = "Deploy contract with valid or invalid value") - public void deployContentValue() { - Assert.assertTrue(PublicMethed.sendcoin(linkage001Address, 20000000000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(linkage001Address, - blockingStubFull); - info = PublicMethed.queryAccount(linkage001Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeNetLimit = resourceInfo.getNetLimit(); - Long beforeFreeNetLimit = resourceInfo.getFreeNetLimit(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeEnergyLimit = resourceInfo.getEnergyLimit(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyLimit:" + beforeEnergyLimit); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeFreeNetLimit:" + beforeFreeNetLimit); - logger.info("beforeNetLimit:" + beforeNetLimit); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - //Value is equal balance,this will be failed.Only use FreeNet,Other not change. - String filePath = "./src/test/resources/soliditycode/contractLinkage001.sol"; - String contractName = "divideIHaveArgsReturnStorage"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String payableCode = retMap.get("byteCode").toString(); - String payableAbi = retMap.get("abI").toString(); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account accountGet = PublicMethed.queryAccount(linkage001Key, blockingStubFull); - Long accountBalance = accountGet.getBalance(); - String txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, payableAbi, - payableCode, "", maxFeeLimit, accountBalance, 100, null, - linkage001Key, linkage001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - Long fee = infoById.get().getFee(); - Long energyFee = infoById.get().getReceipt().getEnergyFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - logger.info("energyUsageTotal:" + energyUsageTotal); - logger.info("fee:" + fee); - logger.info("energyFee:" + energyFee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - - Account infoafter = PublicMethed.queryAccount(linkage001Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(linkage001Address, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyLimit = resourceInfoafter.getEnergyLimit(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterFreeNetLimit = resourceInfoafter.getFreeNetLimit(); - Long afterNetLimit = resourceInfoafter.getNetLimit(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyLimit:" + afterEnergyLimit); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterFreeNetLimit:" + afterFreeNetLimit); - logger.info("afterNetLimit:" + afterNetLimit); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertEquals(beforeBalance, afterBalance); - Assert.assertTrue(fee == 0); - Assert.assertTrue(afterNetUsed == 0); - Assert.assertTrue(afterEnergyUsed == 0); - Assert.assertTrue(afterFreeNetUsed > 0); - - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(linkage001Address, 50000000L, - 0, 1, linkage001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - maxFeeLimit = maxFeeLimit - 50000000L; - PublicMethed.waitProduceNextBlock(blockingStubFull); - AccountResourceMessage resourceInfo1 = PublicMethed.getAccountResource(linkage001Address, - blockingStubFull); - Account info1 = PublicMethed.queryAccount(linkage001Address, blockingStubFull); - Long beforeBalance1 = info1.getBalance(); - Long beforeEnergyLimit1 = resourceInfo1.getEnergyLimit(); - Long beforeEnergyUsed1 = resourceInfo1.getEnergyUsed(); - Long beforeFreeNetLimit1 = resourceInfo1.getFreeNetLimit(); - Long beforeNetLimit1 = resourceInfo1.getNetLimit(); - Long beforeNetUsed1 = resourceInfo1.getNetUsed(); - Long beforeFreeNetUsed1 = resourceInfo1.getFreeNetUsed(); - logger.info("beforeBalance1:" + beforeBalance1); - logger.info("beforeEnergyLimit1:" + beforeEnergyLimit1); - logger.info("beforeEnergyUsed1:" + beforeEnergyUsed1); - logger.info("beforeFreeNetLimit1:" + beforeFreeNetLimit1); - logger.info("beforeNetLimit1:" + beforeNetLimit1); - logger.info("beforeNetUsed1:" + beforeNetUsed1); - logger.info("beforeFreeNetUsed1:" + beforeFreeNetUsed1); - - //Value is 1,use BalanceGetEnergy,use FreeNet,fee==0. - txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, payableAbi, payableCode, - "", maxFeeLimit, 1L, 100, null, linkage001Key, - linkage001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Long energyUsageTotal1 = infoById1.get().getReceipt().getEnergyUsageTotal(); - Long fee1 = infoById1.get().getFee(); - Long energyFee1 = infoById1.get().getReceipt().getEnergyFee(); - Long netUsed1 = infoById1.get().getReceipt().getNetUsage(); - Long energyUsed1 = infoById1.get().getReceipt().getEnergyUsage(); - Long netFee1 = infoById1.get().getReceipt().getNetFee(); - logger.info("energyUsageTotal1:" + energyUsageTotal1); - logger.info("fee1:" + fee1); - logger.info("energyFee1:" + energyFee1); - logger.info("netUsed1:" + netUsed1); - logger.info("energyUsed1:" + energyUsed1); - logger.info("netFee1:" + netFee1); - Assert.assertTrue(infoById1.get().getResultValue() == 0); - - Account infoafter1 = PublicMethed.queryAccount(linkage001Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter1 = PublicMethed.getAccountResource(linkage001Address, - blockingStubFull1); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyLimit1 = resourceInfoafter1.getEnergyLimit(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterFreeNetLimit1 = resourceInfoafter1.getFreeNetLimit(); - Long afterNetLimit1 = resourceInfoafter1.getNetLimit(); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - logger.info("afterBalance1:" + afterBalance1); - logger.info("afterEnergyLimit1:" + afterEnergyLimit1); - logger.info("afterEnergyUsed1:" + afterEnergyUsed1); - logger.info("afterFreeNetLimit1:" + afterFreeNetLimit1); - logger.info("afterNetLimit1:" + afterNetLimit1); - logger.info("afterNetUsed1:" + afterNetUsed1); - logger.info("afterFreeNetUsed1:" + afterFreeNetUsed1); - - Assert.assertTrue(beforeBalance1 - fee1 - 1L == afterBalance1); - byte[] contractAddress = infoById1.get().getContractAddress().toByteArray(); - Account account = PublicMethed.queryAccount(contractAddress, blockingStubFull); - Assert.assertTrue(account.getBalance() == 1L); - Assert.assertTrue(afterNetUsed1 == 0); - Assert.assertTrue(afterEnergyUsed1 > 0); - Assert.assertTrue(afterFreeNetUsed1 > 0); - - //Value is account all balance plus 1. balance is not sufficient,Nothing changde. - AccountResourceMessage resourceInfo2 = PublicMethed.getAccountResource(linkage001Address, - blockingStubFull); - Account info2 = PublicMethed.queryAccount(linkage001Address, blockingStubFull); - Long beforeBalance2 = info2.getBalance(); - Long beforeEnergyLimit2 = resourceInfo2.getEnergyLimit(); - Long beforeEnergyUsed2 = resourceInfo2.getEnergyUsed(); - Long beforeFreeNetLimit2 = resourceInfo2.getFreeNetLimit(); - Long beforeNetLimit2 = resourceInfo2.getNetLimit(); - Long beforeNetUsed2 = resourceInfo2.getNetUsed(); - Long beforeFreeNetUsed2 = resourceInfo2.getFreeNetUsed(); - logger.info("beforeBalance2:" + beforeBalance2); - logger.info("beforeEnergyLimit2:" + beforeEnergyLimit2); - logger.info("beforeEnergyUsed2:" + beforeEnergyUsed2); - logger.info("beforeFreeNetLimit2:" + beforeFreeNetLimit2); - logger.info("beforeNetLimit2:" + beforeNetLimit2); - logger.info("beforeNetUsed2:" + beforeNetUsed2); - logger.info("beforeFreeNetUsed2:" + beforeFreeNetUsed2); - - account = PublicMethed.queryAccount(linkage001Key, blockingStubFull); - Long valueBalance = account.getBalance(); - contractAddress = PublicMethed.deployContract(contractName, payableAbi, payableCode, "", - maxFeeLimit, valueBalance + 1, 100, null, linkage001Key, - linkage001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue(contractAddress == null); - Account infoafter2 = PublicMethed.queryAccount(linkage001Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter2 = PublicMethed.getAccountResource(linkage001Address, - blockingStubFull1); - Long afterBalance2 = infoafter2.getBalance(); - Long afterEnergyLimit2 = resourceInfoafter2.getEnergyLimit(); - Long afterEnergyUsed2 = resourceInfoafter2.getEnergyUsed(); - Long afterFreeNetLimit2 = resourceInfoafter2.getFreeNetLimit(); - Long afterNetLimit2 = resourceInfoafter2.getNetLimit(); - Long afterNetUsed2 = resourceInfoafter2.getNetUsed(); - Long afterFreeNetUsed2 = resourceInfoafter2.getFreeNetUsed(); - logger.info("afterBalance2:" + afterBalance2); - logger.info("afterEnergyLimit2:" + afterEnergyLimit2); - logger.info("afterEnergyUsed2:" + afterEnergyUsed2); - logger.info("afterFreeNetLimit2:" + afterFreeNetLimit2); - logger.info("afterNetLimit2:" + afterNetLimit2); - logger.info("afterNetUsed2:" + afterNetUsed2); - logger.info("afterFreeNetUsed2:" + afterFreeNetUsed2); - Assert.assertTrue(afterNetUsed2 == 0); - Assert.assertTrue(afterEnergyUsed2 > 0); - Assert.assertTrue(afterFreeNetUsed2 > 0); - Assert.assertEquals(beforeBalance2, afterBalance2); - - //Value is account all balance.use freezeBalanceGetEnergy ,freezeBalanceGetNet .Balance ==0 - Assert.assertTrue(PublicMethed.freezeBalance(linkage001Address, 5000000L, - 0, linkage001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - AccountResourceMessage resourceInfo3 = PublicMethed.getAccountResource(linkage001Address, - blockingStubFull); - Account info3 = PublicMethed.queryAccount(linkage001Address, blockingStubFull); - Long beforeBalance3 = info3.getBalance(); - Long beforeEnergyLimit3 = resourceInfo3.getEnergyLimit(); - Long beforeEnergyUsed3 = resourceInfo3.getEnergyUsed(); - Long beforeFreeNetLimit3 = resourceInfo3.getFreeNetLimit(); - Long beforeNetLimit3 = resourceInfo3.getNetLimit(); - Long beforeNetUsed3 = resourceInfo3.getNetUsed(); - Long beforeFreeNetUsed3 = resourceInfo3.getFreeNetUsed(); - logger.info("beforeBalance3:" + beforeBalance3); - logger.info("beforeEnergyLimit3:" + beforeEnergyLimit3); - logger.info("beforeEnergyUsed3:" + beforeEnergyUsed3); - logger.info("beforeFreeNetLimit3:" + beforeFreeNetLimit3); - logger.info("beforeNetLimit3:" + beforeNetLimit3); - logger.info("beforeNetUsed3:" + beforeNetUsed3); - logger.info("beforeFreeNetUsed3:" + beforeFreeNetUsed3); - account = PublicMethed.queryAccount(linkage001Key, blockingStubFull); - valueBalance = account.getBalance(); - txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, payableAbi, payableCode, - "", maxFeeLimit, valueBalance, 100, null, linkage001Key, - linkage001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - fee = infoById.get().getFee(); - Assert.assertTrue(infoById.get().getResultValue() == 0); - contractAddress = infoById.get().getContractAddress().toByteArray(); - Account infoafter3 = PublicMethed.queryAccount(linkage001Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter3 = PublicMethed.getAccountResource(linkage001Address, - blockingStubFull1); - Long afterBalance3 = infoafter3.getBalance(); - Long afterEnergyLimit3 = resourceInfoafter3.getEnergyLimit(); - Long afterEnergyUsed3 = resourceInfoafter3.getEnergyUsed(); - Long afterFreeNetLimit3 = resourceInfoafter3.getFreeNetLimit(); - Long afterNetLimit3 = resourceInfoafter3.getNetLimit(); - Long afterNetUsed3 = resourceInfoafter3.getNetUsed(); - Long afterFreeNetUsed3 = resourceInfoafter3.getFreeNetUsed(); - logger.info("afterBalance3:" + afterBalance3); - logger.info("afterEnergyLimit3:" + afterEnergyLimit3); - logger.info("afterEnergyUsed3:" + afterEnergyUsed3); - logger.info("afterFreeNetLimit3:" + afterFreeNetLimit3); - logger.info("afterNetLimit3:" + afterNetLimit3); - logger.info("afterNetUsed3:" + afterNetUsed3); - logger.info("afterFreeNetUsed3:" + afterFreeNetUsed3); - - Assert.assertTrue(afterNetUsed3 > 0); - Assert.assertTrue(afterEnergyUsed3 > 0); - Assert.assertTrue(afterFreeNetUsed3 > 0); - Assert.assertTrue(beforeBalance2 - fee == afterBalance2); - Assert.assertTrue(afterBalance3 == 0); - Assert.assertTrue(PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance() == valueBalance); - PublicMethed - .unFreezeBalance(linkage001Address, linkage001Key, 1, - linkage001Address, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(linkage001Address, linkage001Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage005.java deleted file mode 100644 index 2dd70c55335..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage005.java +++ /dev/null @@ -1,345 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractLinkage005 { - - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey003); - String contractName; - String code; - String abi; - Long zeroForCycleCost; - Long firstForCycleCost; - Long secondForCycleCost; - Long thirdForCycleCost; - Long forthForCycleCost; - Long fifthForCycleCost; - Long zeroForCycleTimes = 498L; - Long firstForCycleTimes = 500L; - Long secondForCycleTimes = 502L; - Long thirdForCycleTimes = 504L; - Long forthForCycleTimes = 506L; - Long fifthForCycleTimes = 508L; - byte[] contractAddress; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] linkage005Address = ecKey1.getAddress(); - String linkage005Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(linkage005Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - @Test(enabled = true, description = "Every same trigger use same energy and net") - public void testEnergyCostDetail() { - PublicMethed.waitProduceNextBlock(blockingStubFull1); - Assert.assertTrue(PublicMethed.sendcoin(linkage005Address, 5000000000000L, fromAddress, - testKey003, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalance(linkage005Address, 250000000000L, - 0, linkage005Key, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(linkage005Address, 250000000000L, - 0, 1, linkage005Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(linkage005Address, - blockingStubFull); - Account info; - info = PublicMethed.queryAccount(linkage005Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyLimit = resourceInfo.getEnergyLimit(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeFreeNetLimit = resourceInfo.getFreeNetLimit(); - Long beforeNetLimit = resourceInfo.getNetLimit(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyLimit:" + beforeEnergyLimit); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeFreeNetLimit:" + beforeFreeNetLimit); - logger.info("beforeNetLimit:" + beforeNetLimit); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/contractLinkage005.sol"; - String contractName = "timeoutTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, - "", maxFeeLimit, 0L, 100, null, linkage005Key, - linkage005Address, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Account infoafter = PublicMethed.queryAccount(linkage005Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(linkage005Address, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyLimit = resourceInfoafter.getEnergyLimit(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterFreeNetLimit = resourceInfoafter.getFreeNetLimit(); - Long afterNetLimit = resourceInfoafter.getNetLimit(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyLimit:" + afterEnergyLimit); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterFreeNetLimit:" + afterFreeNetLimit); - logger.info("afterNetLimit:" + afterNetLimit); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("---------------:"); - long fee = infoById.get().getFee(); - - Assert.assertTrue(beforeBalance - fee == afterBalance); - //Assert.assertTrue(afterEnergyUsed > 0); - //Assert.assertTrue(afterFreeNetUsed > 0); - firstForCycleTimes = 1000L; - secondForCycleTimes = 1002L; - thirdForCycleTimes = 1004L; - - AccountResourceMessage resourceInfo1 = PublicMethed.getAccountResource(linkage005Address, - blockingStubFull); - Account info1 = PublicMethed.queryAccount(linkage005Address, blockingStubFull); - Long beforeBalance1 = info1.getBalance(); - Long beforeEnergyLimit1 = resourceInfo1.getEnergyLimit(); - Long beforeEnergyUsed1 = resourceInfo1.getEnergyUsed(); - Long beforeFreeNetLimit1 = resourceInfo1.getFreeNetLimit(); - Long beforeNetLimit1 = resourceInfo1.getNetLimit(); - Long beforeNetUsed1 = resourceInfo1.getNetUsed(); - Long beforeFreeNetUsed1 = resourceInfo1.getFreeNetUsed(); - logger.info("beforeBalance1:" + beforeBalance1); - logger.info("beforeEnergyLimit1:" + beforeEnergyLimit1); - logger.info("beforeEnergyUsed1:" + beforeEnergyUsed1); - logger.info("beforeFreeNetLimit1:" + beforeFreeNetLimit1); - logger.info("beforeNetLimit1:" + beforeNetLimit1); - logger.info("beforeNetUsed1:" + beforeNetUsed1); - logger.info("beforeFreeNetUsed1:" + beforeFreeNetUsed1); - byte[] contractAddress = infoById.get().getContractAddress().toByteArray(); - txid = PublicMethed.triggerContract(contractAddress, - "testUseCpu(uint256)", firstForCycleTimes.toString(), false, - 0, 100000000L, linkage005Address, linkage005Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - Account infoafter1 = PublicMethed.queryAccount(linkage005Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter1 = PublicMethed.getAccountResource(linkage005Address, - blockingStubFull1); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyLimit1 = resourceInfoafter1.getEnergyLimit(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterFreeNetLimit1 = resourceInfoafter1.getFreeNetLimit(); - Long afterNetLimit1 = resourceInfoafter1.getNetLimit(); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - logger.info("afterBalance1:" + afterBalance1); - logger.info("afterEnergyLimit1:" + afterEnergyLimit1); - logger.info("afterEnergyUsed1:" + afterEnergyUsed1); - logger.info("afterFreeNetLimit1:" + afterFreeNetLimit1); - logger.info("afterNetLimit1:" + afterNetLimit1); - logger.info("afterNetUsed1:" + afterNetUsed1); - logger.info("afterFreeNetUsed1:" + afterFreeNetUsed1); - logger.info("---------------:"); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - fee = infoById.get().getFee(); - firstForCycleCost = infoById.get().getReceipt().getEnergyUsageTotal(); - Assert.assertTrue((beforeBalance1 - fee) == afterBalance1); - Assert.assertTrue(afterEnergyUsed1 > beforeEnergyUsed1); - Assert.assertTrue(afterNetUsed1 > beforeNetUsed1); - //use EnergyUsed and NetUsed.balance not change - - String txid6 = PublicMethed.triggerContract(contractAddress, - "testUseCpu(uint256)", secondForCycleTimes.toString(), false, - 0, 100000000L, linkage005Address, linkage005Key, blockingStubFull); - final String txid7 = PublicMethed.triggerContract(contractAddress, - "testUseCpu(uint256)", thirdForCycleTimes.toString(), false, - 0, 100000000L, linkage005Address, linkage005Key, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed.getTransactionInfoById(txid6, blockingStubFull); - secondForCycleCost = infoById.get().getReceipt().getEnergyUsageTotal(); - - infoById = PublicMethed.getTransactionInfoById(txid7, blockingStubFull); - thirdForCycleCost = infoById.get().getReceipt().getEnergyUsageTotal(); - - Assert.assertTrue(thirdForCycleCost - secondForCycleCost - == secondForCycleCost - firstForCycleCost); - - zeroForCycleTimes = 498L; - firstForCycleTimes = 500L; - secondForCycleTimes = 502L; - thirdForCycleTimes = 504L; - forthForCycleTimes = 506L; - fifthForCycleTimes = 508L; - AccountResourceMessage resourceInfo4 = PublicMethed.getAccountResource(linkage005Address, - blockingStubFull); - Account info4 = PublicMethed.queryAccount(linkage005Address, blockingStubFull); - Long beforeBalance4 = info4.getBalance(); - Long beforeEnergyLimit4 = resourceInfo4.getEnergyLimit(); - Long beforeEnergyUsed4 = resourceInfo4.getEnergyUsed(); - Long beforeFreeNetLimit4 = resourceInfo4.getFreeNetLimit(); - Long beforeNetLimit4 = resourceInfo4.getNetLimit(); - Long beforeNetUsed4 = resourceInfo4.getNetUsed(); - Long beforeFreeNetUsed4 = resourceInfo4.getFreeNetUsed(); - logger.info("beforeBalance4:" + beforeBalance4); - logger.info("beforeEnergyLimit4:" + beforeEnergyLimit4); - logger.info("beforeEnergyUsed4:" + beforeEnergyUsed4); - logger.info("beforeFreeNetLimit4:" + beforeFreeNetLimit4); - logger.info("beforeNetLimit4:" + beforeNetLimit4); - logger.info("beforeNetUsed4:" + beforeNetUsed4); - logger.info("beforeFreeNetUsed4:" + beforeFreeNetUsed4); - txid = PublicMethed.triggerContract(contractAddress, - "testUseStorage(uint256)", zeroForCycleTimes.toString(), false, - 0, 100000000L, linkage005Address, linkage005Key, blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - fee = infoById.get().getFee(); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - Account infoafter4 = PublicMethed.queryAccount(linkage005Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter4 = PublicMethed.getAccountResource(linkage005Address, - blockingStubFull1); - Long afterBalance4 = infoafter4.getBalance(); - Long afterEnergyLimit4 = resourceInfoafter4.getEnergyLimit(); - Long afterEnergyUsed4 = resourceInfoafter4.getEnergyUsed(); - Long afterFreeNetLimit4 = resourceInfoafter4.getFreeNetLimit(); - Long afterNetLimit4 = resourceInfoafter4.getNetLimit(); - Long afterNetUsed4 = resourceInfoafter4.getNetUsed(); - Long afterFreeNetUsed4 = resourceInfoafter4.getFreeNetUsed(); - logger.info("afterBalance4:" + afterBalance4); - logger.info("afterEnergyLimit4:" + afterEnergyLimit4); - logger.info("afterEnergyUsed4:" + afterEnergyUsed4); - logger.info("afterFreeNetLimit4:" + afterFreeNetLimit4); - logger.info("afterNetLimit4:" + afterNetLimit4); - logger.info("afterNetUsed4:" + afterNetUsed4); - logger.info("afterFreeNetUsed4:" + afterFreeNetUsed4); - logger.info("---------------:"); - Assert.assertTrue(beforeBalance4 - fee == afterBalance4); - Assert.assertTrue(afterEnergyUsed4 > beforeEnergyUsed4); - Assert.assertTrue(afterNetUsed4 > beforeNetUsed4); - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - zeroForCycleCost = infoById.get().getReceipt().getEnergyUsageTotal(); - - String txid1 = PublicMethed.triggerContract(contractAddress, - "testUseStorage(uint256)", firstForCycleTimes.toString(), false, - 0, 100000000L, linkage005Address, linkage005Key, blockingStubFull); - - final String txid2 = PublicMethed.triggerContract(contractAddress, - "testUseStorage(uint256)", secondForCycleTimes.toString(), false, - 0, 100000000L, linkage005Address, linkage005Key, blockingStubFull); - - final String txid3 = PublicMethed.triggerContract(contractAddress, - "testUseStorage(uint256)", thirdForCycleTimes.toString(), false, - 0, 100000000L, linkage005Address, linkage005Key, blockingStubFull); - - final String txid4 = PublicMethed.triggerContract(contractAddress, - "testUseStorage(uint256)", forthForCycleTimes.toString(), false, - 0, 100000000L, linkage005Address, linkage005Key, blockingStubFull); - - final String txid5 = PublicMethed.triggerContract(contractAddress, - "testUseStorage(uint256)", fifthForCycleTimes.toString(), false, - 0, 100000000L, linkage005Address, linkage005Key, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - firstForCycleCost = infoById.get().getReceipt().getEnergyUsageTotal(); - - infoById = PublicMethed.getTransactionInfoById(txid2, blockingStubFull); - secondForCycleCost = infoById.get().getReceipt().getEnergyUsageTotal(); - - infoById = PublicMethed.getTransactionInfoById(txid3, blockingStubFull); - thirdForCycleCost = infoById.get().getReceipt().getEnergyUsageTotal(); - - infoById = PublicMethed.getTransactionInfoById(txid4, blockingStubFull); - forthForCycleCost = infoById.get().getReceipt().getEnergyUsageTotal(); - - infoById = PublicMethed.getTransactionInfoById(txid5, blockingStubFull); - fifthForCycleCost = infoById.get().getReceipt().getEnergyUsageTotal(); - - Assert.assertTrue(thirdForCycleCost - secondForCycleCost - == secondForCycleCost - firstForCycleCost); - Assert.assertTrue(fifthForCycleCost - forthForCycleCost - == forthForCycleCost - thirdForCycleCost); - - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.unFreezeBalance(linkage005Address, linkage005Key, 1, - linkage005Address, blockingStubFull); - PublicMethed.unFreezeBalance(linkage005Address, linkage005Key, 0, - linkage005Address, blockingStubFull); - PublicMethed.freedResource(linkage005Address, linkage005Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage006.java deleted file mode 100644 index ab70dfed487..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage006.java +++ /dev/null @@ -1,331 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractLinkage006 { - - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey003); - String contractName; - String code; - String abi; - byte[] contractAddress; - String txid; - Optional infoById; - String initParmes; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] linkage006Address = ecKey1.getAddress(); - String linkage006Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] linkage006Address2 = ecKey2.getAddress(); - String linkage006Key2 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(linkage006Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - @Test(enabled = true, description = "Deploy contract with stack function") - public void teststackOutByContract() { - - Assert.assertTrue(PublicMethed.sendcoin(linkage006Address, 20000000000L, fromAddress, - testKey003, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalance(linkage006Address, 1000000L, - 0, linkage006Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(linkage006Address, 1000000L, - 0, 1, linkage006Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(linkage006Address, - blockingStubFull); - Account info; - info = PublicMethed.queryAccount(linkage006Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyLimit = resourceInfo.getEnergyLimit(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeFreeNetLimit = resourceInfo.getFreeNetLimit(); - Long beforeNetLimit = resourceInfo.getNetLimit(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyLimit:" + beforeEnergyLimit); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeFreeNetLimit:" + beforeFreeNetLimit); - logger.info("beforeNetLimit:" + beforeNetLimit); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/contractLinkage006.sol"; - String contractName = "AA"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - //success ,balnace change.use EnergyUsed and NetUsed - txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, - "", maxFeeLimit, 1000L, 100, null, linkage006Key, - linkage006Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("txid is " + txid); - contractAddress = infoById.get().getContractAddress().toByteArray(); - Long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - Long fee = infoById.get().getFee(); - Long energyFee = infoById.get().getReceipt().getEnergyFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - logger.info("energyUsageTotal:" + energyUsageTotal); - logger.info("fee:" + fee); - logger.info("energyFee:" + energyFee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - Account infoafter = PublicMethed.queryAccount(linkage006Address, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(linkage006Address, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyLimit = resourceInfoafter.getEnergyLimit(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterFreeNetLimit = resourceInfoafter.getFreeNetLimit(); - Long afterNetLimit = resourceInfoafter.getNetLimit(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyLimit:" + afterEnergyLimit); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterFreeNetLimit:" + afterFreeNetLimit); - logger.info("afterNetLimit:" + afterNetLimit); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue((beforeBalance - fee - 1000L) == afterBalance); - Assert.assertTrue((beforeNetUsed + netUsed) >= afterNetUsed); - Assert.assertTrue((beforeEnergyUsed + energyUsed) >= afterEnergyUsed); - PublicMethed.unFreezeBalance(linkage006Address, linkage006Key, 1, - null, blockingStubFull); - } - - @Test(enabled = true, description = "Boundary value for contract stack(63 is the largest level)") - public void teststackOutByContract1() { - Assert.assertTrue(PublicMethed.sendcoin(linkage006Address2, 20000000000L, fromAddress, - testKey003, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalance(linkage006Address2, 1000000L, - 0, linkage006Key2, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(linkage006Address2, 1000000L, - 0, 1, linkage006Key2, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - AccountResourceMessage resourceInfo1 = PublicMethed.getAccountResource(linkage006Address2, - blockingStubFull); - Account info1 = PublicMethed.queryAccount(linkage006Address2, blockingStubFull); - Long beforeBalance1 = info1.getBalance(); - Long beforeEnergyLimit1 = resourceInfo1.getEnergyLimit(); - Long beforeEnergyUsed1 = resourceInfo1.getEnergyUsed(); - Long beforeFreeNetLimit1 = resourceInfo1.getFreeNetLimit(); - Long beforeNetLimit1 = resourceInfo1.getNetLimit(); - Long beforeNetUsed1 = resourceInfo1.getNetUsed(); - Long beforeFreeNetUsed1 = resourceInfo1.getFreeNetUsed(); - logger.info("beforeBalance1:" + beforeBalance1); - logger.info("beforeEnergyLimit1:" + beforeEnergyLimit1); - logger.info("beforeEnergyUsed1:" + beforeEnergyUsed1); - logger.info("beforeFreeNetLimit1:" + beforeFreeNetLimit1); - logger.info("beforeNetLimit1:" + beforeNetLimit1); - logger.info("beforeNetUsed1:" + beforeNetUsed1); - logger.info("beforeFreeNetUsed1:" + beforeFreeNetUsed1); - - //success ,balance change.use EnergyUsed and NetUsed - initParmes = "\"" + Base58.encode58Check(fromAddress) + "\",\"63\""; - txid = PublicMethed.triggerContract(contractAddress, - "init(address,uint256)", initParmes, false, - 0, 100000000L, linkage006Address2, linkage006Key2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById1 = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Long energyUsageTotal1 = infoById1.get().getReceipt().getEnergyUsageTotal(); - Long fee1 = infoById1.get().getFee(); - Long energyFee1 = infoById1.get().getReceipt().getEnergyFee(); - Long netUsed1 = infoById1.get().getReceipt().getNetUsage(); - Long energyUsed1 = infoById1.get().getReceipt().getEnergyUsage(); - Long netFee1 = infoById1.get().getReceipt().getNetFee(); - logger.info("energyUsageTotal1:" + energyUsageTotal1); - logger.info("fee1:" + fee1); - logger.info("energyFee1:" + energyFee1); - logger.info("netUsed1:" + netUsed1); - logger.info("energyUsed1:" + energyUsed1); - logger.info("netFee1:" + netFee1); - Account infoafter1 = PublicMethed.queryAccount(linkage006Address2, blockingStubFull1); - AccountResourceMessage resourceInfoafter1 = PublicMethed - .getAccountResource(linkage006Address2, - blockingStubFull1); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyLimit1 = resourceInfoafter1.getEnergyLimit(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterFreeNetLimit1 = resourceInfoafter1.getFreeNetLimit(); - Long afterNetLimit1 = resourceInfoafter1.getNetLimit(); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - logger.info("afterBalance1:" + afterBalance1); - logger.info("afterEnergyLimit1:" + afterEnergyLimit1); - logger.info("afterEnergyUsed1:" + afterEnergyUsed1); - logger.info("afterFreeNetLimit1:" + afterFreeNetLimit1); - logger.info("afterNetLimit1:" + afterNetLimit1); - logger.info("afterNetUsed1:" + afterNetUsed1); - logger.info("afterFreeNetUsed1:" + afterFreeNetUsed1); - logger.info("---------------:"); - Assert.assertTrue((beforeBalance1 - fee1) == afterBalance1); - Assert.assertTrue(afterNetUsed1 > beforeNetUsed1); - Assert.assertTrue((beforeEnergyUsed1 + energyUsed1) >= afterEnergyUsed1); - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - } - - @Test(enabled = true, description = "Boundary value for contract stack" - + "(Trigger 64 level can't success)") - public void teststackOutByContract2() { - PublicMethed.waitProduceNextBlock(blockingStubFull); - initParmes = "\"" + Base58.encode58Check(fromAddress) + "\",\"64\""; - AccountResourceMessage resourceInfo2 = PublicMethed.getAccountResource(linkage006Address2, - blockingStubFull); - Account info2 = PublicMethed.queryAccount(linkage006Address2, blockingStubFull); - Long beforeBalance2 = info2.getBalance(); - Long beforeEnergyLimit2 = resourceInfo2.getEnergyLimit(); - Long beforeEnergyUsed2 = resourceInfo2.getEnergyUsed(); - Long beforeFreeNetLimit2 = resourceInfo2.getFreeNetLimit(); - Long beforeNetLimit2 = resourceInfo2.getNetLimit(); - Long beforeNetUsed2 = resourceInfo2.getNetUsed(); - Long beforeFreeNetUsed2 = resourceInfo2.getFreeNetUsed(); - logger.info("beforeBalance2:" + beforeBalance2); - logger.info("beforeEnergyLimit2:" + beforeEnergyLimit2); - logger.info("beforeEnergyUsed2:" + beforeEnergyUsed2); - logger.info("beforeFreeNetLimit2:" + beforeFreeNetLimit2); - logger.info("beforeNetLimit2:" + beforeNetLimit2); - logger.info("beforeNetUsed2:" + beforeNetUsed2); - logger.info("beforeFreeNetUsed2:" + beforeFreeNetUsed2); - //failed ,use EnergyUsed and NetUsed - txid = PublicMethed.triggerContract(contractAddress, - "init(address,uint256)", initParmes, false, - 1000, 100000000L, linkage006Address2, linkage006Key2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById2 = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Long energyUsageTotal2 = infoById2.get().getReceipt().getEnergyUsageTotal(); - Long fee2 = infoById2.get().getFee(); - Long energyFee2 = infoById2.get().getReceipt().getEnergyFee(); - Long netUsed2 = infoById2.get().getReceipt().getNetUsage(); - Long energyUsed2 = infoById2.get().getReceipt().getEnergyUsage(); - Long netFee2 = infoById2.get().getReceipt().getNetFee(); - logger.info("energyUsageTotal2:" + energyUsageTotal2); - logger.info("fee2:" + fee2); - logger.info("energyFee2:" + energyFee2); - logger.info("netUsed2:" + netUsed2); - logger.info("energyUsed2:" + energyUsed2); - logger.info("netFee2:" + netFee2); - - Account infoafter2 = PublicMethed.queryAccount(linkage006Address2, blockingStubFull1); - AccountResourceMessage resourceInfoafter2 = PublicMethed.getAccountResource(linkage006Address2, - blockingStubFull1); - Long afterBalance2 = infoafter2.getBalance(); - Long afterEnergyLimit2 = resourceInfoafter2.getEnergyLimit(); - Long afterEnergyUsed2 = resourceInfoafter2.getEnergyUsed(); - Long afterFreeNetLimit2 = resourceInfoafter2.getFreeNetLimit(); - Long afterNetLimit2 = resourceInfoafter2.getNetLimit(); - Long afterNetUsed2 = resourceInfoafter2.getNetUsed(); - Long afterFreeNetUsed2 = resourceInfoafter2.getFreeNetUsed(); - logger.info("afterBalance2:" + afterBalance2); - logger.info("afterEnergyLimit2:" + afterEnergyLimit2); - logger.info("afterEnergyUsed2:" + afterEnergyUsed2); - logger.info("afterFreeNetLimit2:" + afterFreeNetLimit2); - logger.info("afterNetLimit2:" + afterNetLimit2); - logger.info("afterNetUsed2:" + afterNetUsed2); - logger.info("afterFreeNetUsed2:" + afterFreeNetUsed2); - - Assert.assertTrue((beforeBalance2 - fee2) == afterBalance2); - Assert.assertTrue((beforeEnergyUsed2 + energyUsed2) >= afterEnergyUsed2); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 1); - PublicMethed.unFreezeBalance(linkage006Address2, linkage006Key2, 1, - linkage006Address2, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.unFreezeBalance(linkage006Address, linkage006Key, 1, - linkage006Address, blockingStubFull); - PublicMethed.unFreezeBalance(linkage006Address, linkage006Key, 0, - linkage006Address, blockingStubFull); - PublicMethed.unFreezeBalance(linkage006Address2, linkage006Key2, 1, - linkage006Address2, blockingStubFull); - PublicMethed.unFreezeBalance(linkage006Address2, linkage006Key2, 0, - linkage006Address2, blockingStubFull); - PublicMethed.freedResource(linkage006Address, linkage006Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(linkage006Address2, linkage006Key2, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario002.java deleted file mode 100644 index b642e7487d0..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario002.java +++ /dev/null @@ -1,239 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractScenario002 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contract002Address = ecKey1.getAddress(); - String contract002Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private String txid; - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private ManagedChannel channelSoliInFull = null; - private ManagedChannel channelPbft = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSoliInFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPbft = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String soliInFullnode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - private String soliInPbft = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(2); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contract002Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelSoliInFull = ManagedChannelBuilder.forTarget(soliInFullnode) - .usePlaintext() - .build(); - blockingStubSoliInFull = WalletSolidityGrpc.newBlockingStub(channelSoliInFull); - - channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext() - .build(); - blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); - - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - } - - @Test(enabled = true, description = "Deploy contract with java-tron support interface") - public void test01DeployTronNative() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contract002Address = ecKey1.getAddress(); - String contract002Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - Assert.assertTrue(PublicMethed.sendcoin(contract002Address, 500000000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(contract002Address, 1000000L, - 0, 1, contract002Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - AccountResourceMessage accountResource = PublicMethed.getAccountResource(contract002Address, - blockingStubFull); - Long energyLimit = accountResource.getEnergyLimit(); - Long energyUsage = accountResource.getEnergyUsed(); - Long balanceBefore = PublicMethed.queryAccount(contract002Key, blockingStubFull).getBalance(); - - logger.info("before energy limit is " + Long.toString(energyLimit)); - logger.info("before energy usage is " + Long.toString(energyUsage)); - logger.info("before balance is " + Long.toString(balanceBefore)); - - String contractName = "TronNative"; - String filePath = "./src/test/resources/soliditycode/contractScenario002.sol"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 100, null, contract002Key, contract002Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - - logger.info(txid); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - com.google.protobuf.ByteString contractAddress = infoById.get().getContractAddress(); - SmartContract smartContract = PublicMethed - .getContract(contractAddress.toByteArray(), blockingStubFull); - Assert.assertTrue(smartContract.getAbi() != null); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - accountResource = PublicMethed.getAccountResource(contract002Address, blockingStubFull1); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - Long balanceAfter = PublicMethed.queryAccount(contract002Address, blockingStubFull1) - .getBalance(); - - logger.info("after energy limit is " + Long.toString(energyLimit)); - logger.info("after energy usage is " + Long.toString(energyUsage)); - logger.info("after balance is " + Long.toString(balanceAfter)); - logger.info("transaction fee is " + Long.toString(infoById.get().getFee())); - - Assert.assertTrue(energyUsage > 0); - Assert.assertTrue(balanceBefore == balanceAfter + infoById.get().getFee()); - PublicMethed.unFreezeBalance(contract002Address, contract002Key, 1, - contract002Address, blockingStubFull); - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get smart contract with invalid address") - public void test02GetContractWithInvalidAddress() { - byte[] contractAddress = contract002Address; - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - logger.info(smartContract.getAbi().toString()); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get transaction by id from solidity") - public void test03GetTransactionByIdFromSolidity() { - Assert.assertFalse(PublicMethed.getTransactionById(txid, blockingStubSolidity) - .get().getSignature(0).isEmpty()); - Assert.assertEquals(PublicMethed.getTransactionById(txid, blockingStubFull), - PublicMethed.getTransactionById(txid, blockingStubSolidity)); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get transaction by id from PBFT") - public void test04GetTransactionByIdFromPbft() { - Assert.assertFalse(PublicMethed.getTransactionById(txid, blockingStubPbft) - .get().getSignature(0).isEmpty()); - Assert.assertEquals(PublicMethed.getTransactionById(txid, blockingStubSoliInFull), - PublicMethed.getTransactionById(txid, blockingStubPbft)); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get transaction by id from Solidity") - public void test05GetTransactionInfoByIdFromSolidity() throws Exception { - long netUsage = PublicMethed.getTransactionInfoById(txid, blockingStubFull).get().getReceipt() - .getNetUsage(); - - Assert.assertEquals(PublicMethed.getTransactionInfoByIdFromSolidity(txid, blockingStubSolidity) - .get().getReceipt().getNetUsage(), netUsage); - - Assert - .assertEquals(PublicMethed.getTransactionInfoByIdFromSolidity(txid, blockingStubSoliInFull) - .get().getReceipt().getNetUsage(), netUsage); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get transaction by id from PBFT") - public void test06GetTransactionInfoByIdFromPbft() { - long energyUsage = PublicMethed.getTransactionInfoById(txid, blockingStubFull).get() - .getReceipt() - .getEnergyUsage(); - - Assert.assertEquals(PublicMethed.getTransactionInfoByIdFromSolidity(txid, blockingStubPbft) - .get().getReceipt().getEnergyUsage(), energyUsage); - } - - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(contract002Address, contract002Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelPbft != null) { - channelPbft.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSoliInFull != null) { - channelSoliInFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario011.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario011.java deleted file mode 100644 index cb1ba01dbba..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario011.java +++ /dev/null @@ -1,511 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.springframework.util.StringUtils; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractScenario011 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String kittyCoreAddressAndCut = ""; - byte[] kittyCoreContractAddress = null; - byte[] saleClockAuctionContractAddress = null; - byte[] siringClockAuctionContractAddress = null; - byte[] geneScienceInterfaceContractAddress = null; - Integer consumeUserResourcePercent = 50; - String txid = ""; - Optional infoById = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] deployAddress = ecKey1.getAddress(); - String deployKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] triggerAddress = ecKey2.getAddress(); - String triggerKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(deployKey); - PublicMethed.printAddress(triggerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - Assert.assertTrue(PublicMethed.sendcoin(deployAddress, 50000000000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue(PublicMethed.sendcoin(triggerAddress, 50000000000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - @Test(enabled = true, description = "Deploy Erc721 contract \"Kitty Core\"") - public void deployErc721KittyCore() { - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(deployAddress, 100000000L, - 0, 1, deployKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - Assert.assertTrue(PublicMethed.freezeBalance(deployAddress, 100000000L, 0, - deployKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - Assert.assertTrue(PublicMethed.freezeBalance(triggerAddress, 100000000L, 0, - triggerKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - AccountResourceMessage accountResource = PublicMethed.getAccountResource(deployAddress, - blockingStubFull); - Long cpuLimit = accountResource.getEnergyLimit(); - Long cpuUsage = accountResource.getEnergyUsed(); - Account account = PublicMethed.queryAccount(deployAddress, blockingStubFull); - logger.info("before balance is " + Long.toString(account.getBalance())); - logger.info("before cpu limit is " + Long.toString(cpuLimit)); - logger.info("before cpu usage is " + Long.toString(cpuUsage)); - String contractName = "KittyCore"; - String filePath = "./src/test/resources/soliditycode/contractScenario011.sol"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - logger.info("Kitty Core"); - kittyCoreContractAddress = PublicMethed.deployContract(contractName, abi, code, "", - maxFeeLimit, 0L, consumeUserResourcePercent, null, deployKey, - deployAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(kittyCoreContractAddress, - blockingStubFull); - Assert.assertFalse(StringUtils.isEmpty(smartContract.getBytecode())); - - Assert.assertTrue(smartContract.getAbi() != null); - accountResource = PublicMethed.getAccountResource(deployAddress, blockingStubFull); - cpuLimit = accountResource.getEnergyLimit(); - cpuUsage = accountResource.getEnergyUsed(); - account = PublicMethed.queryAccount(deployKey, blockingStubFull); - logger.info("after balance is " + Long.toString(account.getBalance())); - logger.info("after cpu limit is " + Long.toString(cpuLimit)); - logger.info("after cpu usage is " + Long.toString(cpuUsage)); - logger.info(ByteArray.toHexString(kittyCoreContractAddress)); - logger.info(ByteArray.toHexString(kittyCoreContractAddress).substring(2)); - - kittyCoreAddressAndCut = "000000000000000000000000" + ByteArray - .toHexString(kittyCoreContractAddress).substring(2); - kittyCoreAddressAndCut = kittyCoreAddressAndCut + "0000000000000000000000000000000000000000000" - + "000000000000000000100"; - } - - @Test(enabled = true, description = "Deploy Erc721 contract \"Sale Clock Auction\"") - public void deploySaleClockAuction() { - AccountResourceMessage accountResource = PublicMethed.getAccountResource(deployAddress, - blockingStubFull); - Long cpuLimit = accountResource.getEnergyLimit(); - Long cpuUsage = accountResource.getEnergyUsed(); - Account account = PublicMethed.queryAccount(deployKey, blockingStubFull); - logger.info("before balance is " + Long.toString(account.getBalance())); - logger.info("before cpu limit is " + Long.toString(cpuLimit)); - logger.info("before cpu usage is " + Long.toString(cpuUsage)); - String contractName = "SaleClockAuction"; - String filePath = "./src/test/resources/soliditycode/contractScenario011.sol"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - logger.info("Sale Clock Auction"); - //saleClockAuctionContractAddress; - String data = "\"" + Base58.encode58Check(kittyCoreContractAddress) + "\"," + 100; - String deplTxid = PublicMethed - .deployContractWithConstantParame(contractName, abi, code, "constructor(address,uint256)", - data, "", maxFeeLimit, 0L, consumeUserResourcePercent, null, deployKey, deployAddress, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = PublicMethed - .getTransactionInfoById(deplTxid, blockingStubFull); - Assert.assertTrue(info.get().getResultValue() == 0); - - saleClockAuctionContractAddress = info.get().getContractAddress().toByteArray(); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(saleClockAuctionContractAddress, - blockingStubFull); - Assert.assertFalse(StringUtils.isEmpty(smartContract.getBytecode())); - Assert.assertTrue(smartContract.getAbi() != null); - accountResource = PublicMethed.getAccountResource(deployAddress, blockingStubFull); - cpuLimit = accountResource.getEnergyLimit(); - cpuUsage = accountResource.getEnergyUsed(); - account = PublicMethed.queryAccount(deployKey, blockingStubFull); - logger.info("after balance is " + Long.toString(account.getBalance())); - logger.info("after cpu limit is " + Long.toString(cpuLimit)); - logger.info("after cpu usage is " + Long.toString(cpuUsage)); - - String triggerTxid = PublicMethed - .triggerContract(saleClockAuctionContractAddress, "isSaleClockAuction()", "#", false, 0, - maxFeeLimit, deployAddress, deployKey, blockingStubFull); - Optional inFoByid = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Ttttt " + triggerTxid); - Assert.assertTrue(inFoByid.get().getResultValue() == 0); - } - - @Test(enabled = true, description = "Deploy Erc721 contract \"Siring Clock Auction\"") - public void deploySiringClockAuction() { - AccountResourceMessage accountResource = PublicMethed.getAccountResource(deployAddress, - blockingStubFull); - Long cpuLimit = accountResource.getEnergyLimit(); - Long cpuUsage = accountResource.getEnergyUsed(); - Account account = PublicMethed.queryAccount(deployKey, blockingStubFull); - logger.info("before balance is " + Long.toString(account.getBalance())); - logger.info("before cpu limit is " + Long.toString(cpuLimit)); - logger.info("before cpu usage is " + Long.toString(cpuUsage)); - String contractName = "SiringClockAuction"; - String filePath = "./src/test/resources/soliditycode/contractScenario011.sol"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String data = "\"" + Base58.encode58Check(kittyCoreContractAddress) + "\"," + 100; - String siringClockAuctionContractAddressTxid = PublicMethed - .deployContractWithConstantParame(contractName, abi, code, "constructor(address,uint256)", - data, - "", maxFeeLimit, 0L, consumeUserResourcePercent, null, deployKey, - deployAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info2 = PublicMethed - .getTransactionInfoById(siringClockAuctionContractAddressTxid, blockingStubFull); - siringClockAuctionContractAddress = info2.get().getContractAddress().toByteArray(); - Assert.assertTrue(info2.get().getResultValue() == 0); - SmartContract smartContract = PublicMethed.getContract(siringClockAuctionContractAddress, - blockingStubFull); - Assert.assertFalse(StringUtils.isEmpty(smartContract.getBytecode())); - Assert.assertTrue(smartContract.getAbi() != null); - accountResource = PublicMethed.getAccountResource(deployAddress, blockingStubFull); - cpuLimit = accountResource.getEnergyLimit(); - cpuUsage = accountResource.getEnergyUsed(); - account = PublicMethed.queryAccount(deployKey, blockingStubFull); - logger.info("after balance is " + Long.toString(account.getBalance())); - logger.info("after cpu limit is " + Long.toString(cpuLimit)); - logger.info("after cpu usage is " + Long.toString(cpuUsage)); - } - - @Test(enabled = true, description = "Deploy Erc721 contract \"Gene Science Interface\"") - public void deployGeneScienceInterface() { - AccountResourceMessage accountResource = PublicMethed.getAccountResource(deployAddress, - blockingStubFull); - Long cpuLimit = accountResource.getEnergyLimit(); - Long cpuUsage = accountResource.getEnergyUsed(); - Account account = PublicMethed.queryAccount(deployKey, blockingStubFull); - logger.info("before balance is " + Long.toString(account.getBalance())); - logger.info("before cpu limit is " + Long.toString(cpuLimit)); - logger.info("before cpu usage is " + Long.toString(cpuUsage)); - String contractName = "GeneScienceInterface"; - String filePath = "./src/test/resources/soliditycode/contractScenario011.sol"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, - "", maxFeeLimit, - 0L, consumeUserResourcePercent, null, deployKey, deployAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info2 = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - geneScienceInterfaceContractAddress = info2.get().getContractAddress().toByteArray(); - Assert.assertTrue(info2.get().getResultValue() == 0); - - SmartContract smartContract = PublicMethed.getContract(geneScienceInterfaceContractAddress, - blockingStubFull); - Assert.assertFalse(StringUtils.isEmpty(smartContract.getBytecode())); - Assert.assertTrue(smartContract.getAbi() != null); - accountResource = PublicMethed.getAccountResource(deployAddress, blockingStubFull); - cpuLimit = accountResource.getEnergyLimit(); - cpuUsage = accountResource.getEnergyUsed(); - account = PublicMethed.queryAccount(deployKey, blockingStubFull); - logger.info("after balance is " + Long.toString(account.getBalance())); - logger.info("after cpu limit is " + Long.toString(cpuLimit)); - logger.info("after cpu usage is " + Long.toString(cpuUsage)); - } - - @Test(enabled = true, description = "Set three contract address for Kitty Core, " - + "set three CXO roles") - public void triggerToSetThreeContractAddressToKittyCore() { - //Set SaleAuctionAddress to kitty core. - String saleContractString = "\"" + Base58.encode58Check(saleClockAuctionContractAddress) + "\""; - txid = PublicMethed.triggerContract(kittyCoreContractAddress, "setSaleAuctionAddress(address)", - saleContractString, false, 0, 10000000L, deployAddress, deployKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info(txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - //Set SiringAuctionAddress to kitty core. - String siringContractString = "\"" + Base58.encode58Check(siringClockAuctionContractAddress) - + "\""; - txid = PublicMethed - .triggerContract(kittyCoreContractAddress, "setSiringAuctionAddress(address)", - siringContractString, false, 0, 10000000L, deployAddress, deployKey, blockingStubFull); - logger.info(txid); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - //Set gen contract to kitty core - String genContractString = "\"" + Base58.encode58Check(geneScienceInterfaceContractAddress) - + "\""; - txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "setGeneScienceAddress(address)", genContractString, - false, 0, 10000000L, deployAddress, deployKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info(txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - //Start the game. - Integer result = 1; - Integer times = 0; - while (result == 1) { - txid = PublicMethed.triggerContract(kittyCoreContractAddress, "unpause()", "", false, 0, - 10000000L, deployAddress, deployKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - result = infoById.get().getResultValue(); - if (times++ == 3) { - break; - } - } - - Assert.assertTrue(result == 0); - logger.info("start the game " + txid); - - //Create one gen0 cat. - txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "createGen0Auction(uint256)", "-1000000000000000", false, - 0, 100000000L, deployAddress, deployKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "gen0CreatedCount()", "#", false, - 0, 100000000L, deployAddress, deployKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "getKitty(uint256)", "1", false, 0, 10000000, triggerAddress, - triggerKey, blockingStubFull); - logger.info("getKitty " + txid); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - String newCxoAddress = "\"" + Base58.encode58Check(triggerAddress) - + "\""; - - txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "setCOO(address)", newCxoAddress, false, 0, 10000000, deployAddress, - deployKey, blockingStubFull); - logger.info("COO " + txid); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "setCFO(address)", newCxoAddress, false, 0, 10000000, deployAddress, - deployKey, blockingStubFull); - logger.info("CFO " + txid); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "setCEO(address)", newCxoAddress, false, 0, 1000000, deployAddress, - deployKey, blockingStubFull); - logger.info("CEO " + txid); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - } - - @Test(enabled = true, description = "Create Gen0 cat") - public void triggerUseTriggerEnergyUsage() { - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] triggerUseTriggerEnergyUsageAddress = ecKey3.getAddress(); - final String triggerUseTriggerEnergyUsageKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - Assert.assertTrue( - PublicMethed.sendcoin(triggerUseTriggerEnergyUsageAddress, 100000000000L, - fromAddress, testKey002, blockingStubFull)); - String newCxoAddress = "\"" + Base58.encode58Check(triggerUseTriggerEnergyUsageAddress) - + "\""; - PublicMethed.waitProduceNextBlock(blockingStubFull); - final String txid1; - final String txid2; - final String txid3; - txid1 = PublicMethed.triggerContract(kittyCoreContractAddress, - "setCOO(address)", newCxoAddress, false, 0, maxFeeLimit, triggerAddress, - triggerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("COO " + txid); - - txid2 = PublicMethed.triggerContract(kittyCoreContractAddress, - "setCFO(address)", newCxoAddress, false, 0, maxFeeLimit, triggerAddress, - triggerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("CFO " + txid); - - txid3 = PublicMethed.triggerContract(kittyCoreContractAddress, - "setCEO(address)", newCxoAddress, false, 0, maxFeeLimit, triggerAddress, - triggerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("CEO " + txid); - - infoById = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - infoById = PublicMethed.getTransactionInfoById(txid2, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - infoById = PublicMethed.getTransactionInfoById(txid3, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long beforeBalance = PublicMethed - .queryAccount(triggerUseTriggerEnergyUsageKey, blockingStubFull).getBalance(); - logger.info("before balance is " + Long.toString(beforeBalance)); - txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "createGen0Auction(uint256)", "0", false, - 0, 100000000L, triggerUseTriggerEnergyUsageAddress, triggerUseTriggerEnergyUsageKey, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull1); - logger.info("Q " + Long - .toString(infoById.get().getReceipt().getEnergyFee())); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsage() == 0); - Assert.assertTrue(infoById.get().getReceipt().getEnergyFee() > 10000); - // Assert.assertTrue(infoById.get().getReceipt().getOriginEnergyUsage() > 10000); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() - == infoById.get().getReceipt().getEnergyFee() / 100 + infoById.get().getReceipt() - .getOriginEnergyUsage()); - - Long fee = infoById.get().getFee(); - Long afterBalance = PublicMethed - .queryAccount(triggerUseTriggerEnergyUsageKey, blockingStubFull1).getBalance(); - logger.info("after balance is " + Long.toString(afterBalance)); - logger.info("fee is " + Long.toString(fee)); - Assert.assertTrue(beforeBalance == afterBalance + fee); - - logger.info("before EnergyUsage is " + infoById.get().getReceipt().getEnergyUsage()); - logger.info("before EnergyFee is " + infoById.get().getReceipt().getEnergyFee()); - logger.info("before OriginEnergyUsage is " + infoById.get().getReceipt() - .getOriginEnergyUsage()); - logger.info("before EnergyTotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Assert.assertTrue( - PublicMethed.freezeBalanceGetEnergy(triggerUseTriggerEnergyUsageAddress, 100000000L, - 0, 1, triggerUseTriggerEnergyUsageKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - beforeBalance = PublicMethed.queryAccount(triggerUseTriggerEnergyUsageKey, blockingStubFull) - .getBalance(); - logger.info("before balance is " + Long.toString(beforeBalance)); - - AccountResourceMessage accountResource = PublicMethed - .getAccountResource(triggerUseTriggerEnergyUsageAddress, blockingStubFull); - Long energyLimit = accountResource.getEnergyLimit(); - logger.info("before EnergyLimit is " + Long.toString(energyLimit)); - - txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "createGen0Auction(uint256)", "0", false, - 0, 100000000L, triggerUseTriggerEnergyUsageAddress, triggerUseTriggerEnergyUsageKey, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull1); - logger.info("after EnergyUsage is " + infoById.get().getReceipt().getEnergyUsage()); - logger.info("after EnergyFee is " + infoById.get().getReceipt().getEnergyFee()); - logger.info("after OriginEnergyUsage is " + infoById.get().getReceipt().getOriginEnergyUsage()); - logger.info("after EnergyTotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - fee = infoById.get().getFee(); - afterBalance = PublicMethed.queryAccount(triggerUseTriggerEnergyUsageKey, blockingStubFull1) - .getBalance(); - logger.info("after balance is " + Long.toString(afterBalance)); - logger.info("fee is " + Long.toString(fee)); - - accountResource = PublicMethed - .getAccountResource(triggerUseTriggerEnergyUsageAddress, blockingStubFull1); - energyLimit = accountResource.getEnergyLimit(); - - logger.info("after EnergyLimit is " + Long.toString(energyLimit)); - - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsage() > 10000); - Assert.assertTrue(infoById.get().getReceipt().getEnergyFee() == 0); - - //Assert.assertTrue(infoById.get().getReceipt().getOriginEnergyUsage() > 10000); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() == infoById.get() - .getReceipt().getEnergyUsage() + infoById.get().getReceipt().getOriginEnergyUsage()); - // Assert.assertTrue(infoById.get().getReceipt().getEnergyUsage() == infoById.get() - // .getReceipt().getOriginEnergyUsage()); - - Assert.assertTrue(beforeBalance == afterBalance + fee); - PublicMethed.unFreezeBalance(deployAddress, deployKey, 1, - deployAddress, blockingStubFull); - PublicMethed.unFreezeBalance(triggerAddress, triggerKey, 1, - triggerAddress, blockingStubFull); - - PublicMethed - .unFreezeBalance(triggerUseTriggerEnergyUsageAddress, triggerUseTriggerEnergyUsageKey, 1, - triggerUseTriggerEnergyUsageAddress, blockingStubFull); - PublicMethed.freedResource(triggerUseTriggerEnergyUsageAddress, triggerUseTriggerEnergyUsageKey, - fromAddress, blockingStubFull); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario014.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario014.java deleted file mode 100644 index 119b1800412..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario014.java +++ /dev/null @@ -1,231 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractScenario014 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - byte[] contractAddress1 = null; - byte[] contractAddress2 = null; - byte[] contractAddress3 = null; - String txid = ""; - Optional infoById = null; - String contractName = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contract014Address = ecKey1.getAddress(); - String contract014Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - String priKey014 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] receiverAddress = ecKey2.getAddress(); - String receiverKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Triple trigger in smart contract") - public void testTripleTrigger() { - - ecKey2 = new ECKey(Utils.getRandom()); - receiverAddress = ecKey2.getAddress(); - receiverKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - PublicMethed.printAddress(contract014Key); - PublicMethed.printAddress(receiverKey); - - Assert.assertTrue(PublicMethed.sendcoin(contract014Address, 50_000_000_000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceGetEnergy(contract014Address, 10_000_000_000L, 0, 1, priKey014, - blockingStubFull)); - - logger.info("contract014Address : == " + contract014Key); - //Deploy contract1, contract1 has a function to transaction 5 sun to target account - String contractName = "Contract1"; - String filePath = "./src/test/resources/soliditycode/contractScenario014.sol"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 1000000L, 100, null, contract014Key, contract014Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - contractAddress1 = infoById.get().getContractAddress().toByteArray(); - - //Deploy contract2, contract2 has a function to call contract1 transaction sun function. - // and has a revert function. - contractName = "contract2"; - String filePath1 = "./src/test/resources/soliditycode/contractScenario014.sol"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath1, contractName); - - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - String parame = "\"" + Base58.encode58Check(contractAddress1) + "\""; - - txid = PublicMethed.deployContractWithConstantParame(contractName, abi1, code1, - "constructor(address)", parame, "", maxFeeLimit, 1000000L, 100, null, - contract014Key, contract014Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - contractAddress2 = infoById.get().getContractAddress().toByteArray(); - - //Deploy contract3, trigger contrct2 function. - contractName = "contract3"; - String filePath2 = "./src/test/resources/soliditycode/contractScenario014.sol"; - HashMap retMap2 = PublicMethed.getBycodeAbi(filePath2, contractName); - - String code2 = retMap2.get("byteCode").toString(); - String abi2 = retMap2.get("abI").toString(); - parame = "\"" + Base58.encode58Check(contractAddress2) + "\""; - - txid = PublicMethed.deployContractWithConstantParame(contractName, abi2, code2, - "constructor(address)", parame, "", maxFeeLimit, 1000000L, 100, null, - contract014Key, contract014Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - contractAddress3 = infoById.get().getContractAddress().toByteArray(); - - Assert.assertTrue(PublicMethed.sendcoin(receiverAddress, 1000000L, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Test contract2 trigger contract1 to test call function - Account contract2AccountInfo = PublicMethed.queryAccount(contractAddress2, blockingStubFull); - final Long contract2BeforeBalance = contract2AccountInfo.getBalance(); - Account receiverAccountInfo = PublicMethed.queryAccount(receiverAddress, blockingStubFull); - Long receiverBeforeBalance = receiverAccountInfo.getBalance(); - Account contract1AccountInfo = PublicMethed.queryAccount(contractAddress1, blockingStubFull); - Long contract1BeforeBalance = contract1AccountInfo.getBalance(); - logger.info("before contract1 balance is " + Long.toString(contract1BeforeBalance)); - logger.info("before receiver balance is " + Long.toString(receiverBeforeBalance)); - String receiveAddress = "\"" + Base58.encode58Check(receiverAddress) + "\""; - txid = PublicMethed.triggerContract(contractAddress2, - "triggerContract1(address)", receiveAddress, false, - 0, maxFeeLimit, contract014Address, contract014Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - contract2AccountInfo = PublicMethed.queryAccount(contractAddress2, blockingStubFull); - final Long contract2AfterBalance = contract2AccountInfo.getBalance(); - //contract2AccountInfo.getAccountResource().getFrozenBalanceForEnergy(); - receiverAccountInfo = PublicMethed.queryAccount(receiverAddress, blockingStubFull); - Long receiverAfterBalance = receiverAccountInfo.getBalance(); - contract1AccountInfo = PublicMethed.queryAccount(contractAddress1, blockingStubFull); - Long contract1AfterBalance = contract1AccountInfo.getBalance(); - logger.info("after contract1 balance is " + Long.toString(contract1AfterBalance)); - Assert.assertTrue(receiverAfterBalance - receiverBeforeBalance == 5); - Assert.assertTrue(contract2BeforeBalance - contract2AfterBalance == 0); - Assert.assertTrue(contract1BeforeBalance - contract1AfterBalance == 5); - - //Test contract2 trigger contract1 but revert - contract1AccountInfo = PublicMethed.queryAccount(contractAddress1, blockingStubFull); - contract1BeforeBalance = contract1AccountInfo.getBalance(); - receiverAccountInfo = PublicMethed.queryAccount(receiverAddress, blockingStubFull); - receiverBeforeBalance = receiverAccountInfo.getBalance(); - receiveAddress = "\"" + Base58.encode58Check(receiverAddress) + "\""; - txid = PublicMethed.triggerContract(contractAddress2, - "triggerContract1ButRevert(address)", receiveAddress, false, - 0, 10000000L, contract014Address, contract014Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 1); - contract1AccountInfo = PublicMethed.queryAccount(contractAddress1, blockingStubFull); - contract1AfterBalance = contract1AccountInfo.getBalance(); - receiverAccountInfo = PublicMethed.queryAccount(receiverAddress, blockingStubFull); - receiverAfterBalance = receiverAccountInfo.getBalance(); - logger.info("after receiver balance is " + Long.toString(receiverAfterBalance)); - Assert.assertTrue(receiverAfterBalance - receiverBeforeBalance == 0); - Assert.assertTrue(contract1BeforeBalance - contract1AfterBalance == 0); - - //Test contract3 trigger contract2 to call contract1 - contract1AccountInfo = PublicMethed.queryAccount(contractAddress1, blockingStubFull); - contract1BeforeBalance = contract1AccountInfo.getBalance(); - Account contract3AccountInfo = PublicMethed.queryAccount(contractAddress3, blockingStubFull); - final Long contract3BeforeBalance = contract3AccountInfo.getBalance(); - receiverAccountInfo = PublicMethed.queryAccount(receiverAddress, blockingStubFull); - receiverBeforeBalance = receiverAccountInfo.getBalance(); - logger.info("before receiver balance is " + Long.toString(receiverBeforeBalance)); - logger.info("before contract3 balance is " + Long.toString(contract3BeforeBalance)); - receiveAddress = "\"" + Base58.encode58Check(receiverAddress) + "\""; - txid = PublicMethed.triggerContract(contractAddress3, - "triggerContract2(address)", receiveAddress, false, - 0, 10000000L, contract014Address, contract014Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - contract3AccountInfo = PublicMethed.queryAccount(contractAddress3, blockingStubFull); - final Long contract3AfterBalance = contract3AccountInfo.getBalance(); - receiverAccountInfo = PublicMethed.queryAccount(receiverAddress, blockingStubFull); - receiverAfterBalance = receiverAccountInfo.getBalance(); - logger.info("after receiver balance is " + Long.toString(receiverAfterBalance)); - logger.info("after contract3 balance is " + Long.toString(contract3AfterBalance)); - contract1AccountInfo = PublicMethed.queryAccount(contractAddress1, blockingStubFull); - contract1AfterBalance = contract1AccountInfo.getBalance(); - - Assert.assertTrue(receiverAfterBalance - receiverBeforeBalance == 5); - Assert.assertTrue(contract3BeforeBalance - contract3AfterBalance == 0); - Assert.assertTrue(contract1BeforeBalance - contract1AfterBalance == 5); - - - } - - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.unFreezeBalance(contract014Address, contract014Key, 1, contract014Address, - blockingStubFull); - PublicMethed.freedResource(contract014Address, contract014Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario015.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario015.java deleted file mode 100644 index 531b4a85a41..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario015.java +++ /dev/null @@ -1,132 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractScenario015 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - byte[] contractAddress1 = null; - byte[] contractAddress2 = null; - byte[] contractAddress3 = null; - String txid = ""; - Optional infoById = null; - String contractName = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contract014Address = ecKey1.getAddress(); - String contract014Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] receiverAddress = ecKey2.getAddress(); - String receiverKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "TRON TRC20 transfer token") - public void trc20Tron() { - ecKey1 = new ECKey(Utils.getRandom()); - contract014Address = ecKey1.getAddress(); - contract014Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - receiverAddress = ecKey2.getAddress(); - receiverKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - PublicMethed.printAddress(contract014Key); - PublicMethed.printAddress(receiverKey); - - Assert.assertTrue(PublicMethed.sendcoin(contract014Address, 500000000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Deploy contract1, contract1 has a function to transaction 5 sun to target account - String contractName = "TRON TRC20"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_Scenario015_TRC20_TRON"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_Scenario015_TRC20_TRON"); - txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 100, null, contract014Key, contract014Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info(txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - contractAddress1 = infoById.get().getContractAddress().toByteArray(); - //Set SiringAuctionAddress to kitty core. - String siringContractString = "\"" + Base58.encode58Check(fromAddress) + "\""; - txid = PublicMethed - .triggerContract(contractAddress1, "balanceOf(address)", siringContractString, - false, 0, 10000000L, contract014Address, contract014Key, blockingStubFull); - logger.info(txid); - - siringContractString = "\"" + Base58.encode58Check(fromAddress) + "\",\"" + 17 + "\""; - txid = PublicMethed.triggerContract(contractAddress1, "transfer(address,uint256)", - siringContractString, false, 0, 10000000L, contract014Address, - contract014Key, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - siringContractString = "\"" + Base58.encode58Check(fromAddress) + "\""; - txid = PublicMethed - .triggerContract(contractAddress1, "balanceOf(address)", - siringContractString, false, 0, 10000000L, contract014Address, - contract014Key, blockingStubFull); - logger.info(txid); - } - - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(contract014Address, contract014Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractTrc1155.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractTrc1155.java deleted file mode 100644 index 5800459911b..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractTrc1155.java +++ /dev/null @@ -1,696 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.contract.SmartContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.dailybuild.exceptionfee.AssertException; - -@Slf4j -public class ContractTrc1155 { - - private final String testKey002 = - Configuration.getByPath("testng.conf").getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private final String fullnode = - Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = - Configuration.getByPath("testng.conf").getLong("defaultParameter.maxFeeLimit"); - Optional infoById = null; - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] ownerAddressByte = ecKey2.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - String ownerAddressString = null; - String holderAddressString = null; - String noHolderAddress = null; - String txid = null; - byte[] trc1155AddressByte = null; - /** constructor. */ - - @BeforeSuite - public void beforeSuite() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - /** constructor. */ - @BeforeClass(enabled = true) - public void beforeClass() throws Exception { - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - deployTrc1155(); - - deployHolder(); - deployNoHolder(); - } - - @Test(enabled = true, description = "Trigger Trc1155 balanceOf method") - public void test01triggerTrc1155BalanceOfMethod() { - int coinType = 3; - List parameters = Arrays.asList(ownerAddressString, coinType); - String data = PublicMethed.parametersString(parameters); - - logger.info("data:" + data); - GrpcAPI.TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtention( - trc1155AddressByte, - "balanceOf(address,uint256)", - data, - false, - 0, - 0, - "0", - 0, - ownerAddressByte, - ownerKey, - blockingStubFull); - String hexBalance = Hex.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - long result = Long.parseLong(hexBalance, 16); - Assert.assertEquals((long) Math.pow(10, 4), result); - } - - @Test(enabled = true, description = "Trigger Trc1155 balanceOfBatch method") - public void test02triggerTrc1155BalanceOfBatchMethod() { - List address = - Stream.of( - ownerAddressString, - ownerAddressString, - ownerAddressString, - ownerAddressString, - ownerAddressString, - ownerAddressString) - .collect(Collectors.toList()); - List coinType = Stream.of(0, 1, 2, 3, 4, 5).collect(Collectors.toList()); - List parameters = Arrays.asList(address, coinType); - String data = PublicMethed.parametersString(parameters); - logger.info("data:" + data); - GrpcAPI.TransactionExtention transactionExtention1 = - PublicMethed.triggerConstantContractForExtention( - trc1155AddressByte, - "balanceOfBatch(address[],uint256[])", - data, - false, - 0, - 0, - "0", - 0, - ownerAddressByte, - ownerKey, - blockingStubFull); - String hexBalance = Hex.toHexString(transactionExtention1.getConstantResult(0).toByteArray()); - logger.info("hexBalance:" + hexBalance); - final long trxAmount = (long) Math.pow(10, 3); - final long bttAmount = (long) Math.pow(10, 2); - final long winAmount = (long) Math.pow(10, 5); - final long sunAmount = (long) Math.pow(10, 4); - final long apenftAmount = 1L; - final long apenft1Amount = 1L; - Assert.assertEquals(trxAmount, Long.parseLong(hexBalance.substring(128, 192), 16)); - Assert.assertEquals(bttAmount, Long.parseLong(hexBalance.substring(192, 256), 16)); - Assert.assertEquals(winAmount, Long.parseLong(hexBalance.substring(256, 320), 16)); - Assert.assertEquals(sunAmount, Long.parseLong(hexBalance.substring(320, 384), 16)); - Assert.assertEquals(apenftAmount, Long.parseLong(hexBalance.substring(384, 448), 16)); - Assert.assertEquals(apenft1Amount, Long.parseLong(hexBalance.substring(448, 512), 16)); - } - - @Test(enabled = true, description = "Trigger Trc1155 safeTransferFrom function") - public void test03triggerTrc1155SafeTransferFromFunction() { - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] contract003Address = ecKey3.getAddress(); - String sendAddress = WalletClient.encode58Check(contract003Address); - logger.info(sendAddress); - int coinType = 3; - final int coinAmount = 2; - List parameters1 = Arrays.asList(ownerAddressString, coinType); - String data = PublicMethed.parametersString(parameters1); - logger.info("data1:" + data); - GrpcAPI.TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtention( - trc1155AddressByte, - "balanceOf(address,uint256)", - data, - false, - 0, - 0, - "0", - 0, - ownerAddressByte, - ownerKey, - blockingStubFull); - String hexBalance = Hex.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - long result = Long.parseLong(hexBalance, 16); - Assert.assertEquals((long) Math.pow(10, 4), result); - String bytes = "0000000000000000000000000000000000e6b58be8af95e5ad97e7aca6e4b8b2"; - List parameters = - Arrays.asList(ownerAddressString, sendAddress, coinType, coinAmount, bytes); - data = PublicMethed.parametersString(parameters); - logger.info("data2:" + data); - String txid = - PublicMethed.triggerContract( - trc1155AddressByte, - "safeTransferFrom(address,address,uint256,uint256,bytes)", - data, - false, - 0, - maxFeeLimit, - ownerAddressByte, - ownerKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info(txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - Optional byId = PublicMethed.getTransactionById(txid, blockingStubFull); - String s = ByteArray.toHexString(byId.get().getRawData().getContract(0).toByteArray()); - Assert.assertTrue(s.contains(bytes)); - - List parameters3 = Arrays.asList(ownerAddressString, coinType); - data = PublicMethed.parametersString(parameters3); - logger.info("data3:" + data); - GrpcAPI.TransactionExtention transactionExtention3 = - PublicMethed.triggerConstantContractForExtention( - trc1155AddressByte, - "balanceOf(address,uint256)", - data, - false, - 0, - 0, - "0", - 0, - ownerAddressByte, - ownerKey, - blockingStubFull); - hexBalance = Hex.toHexString(transactionExtention3.getConstantResult(0).toByteArray()); - result = Long.parseLong(hexBalance, 16); - Assert.assertEquals((long) Math.pow(10, 4) - coinAmount, result); - - parameters = Arrays.asList(sendAddress, coinType); - data = PublicMethed.parametersString(parameters); - - logger.info("data2:" + data); - transactionExtention = - PublicMethed.triggerConstantContractForExtention( - trc1155AddressByte, - "balanceOf(address,uint256)", - data, - false, - 0, - 0, - "0", - 0, - ownerAddressByte, - ownerKey, - blockingStubFull); - hexBalance = Hex.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - result = Long.parseLong(hexBalance, 16); - Assert.assertEquals(coinAmount, result); - } - - @Test(enabled = true, description = "trigger Trc1155 SafeBatchTransferFrom function") - public void test04triggerTrc1155SafeBatchTransferFromFunction() { - - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] receiverAddress = ecKey4.getAddress(); - String sendAddress = WalletClient.encode58Check(receiverAddress); - List coinType = Stream.of(0, 1, 5).collect(Collectors.toList()); - List coinAccount = Stream.of(50, 10, 1).collect(Collectors.toList()); - String bytes = "0000000000000000000000000000000000e6b58be8af95e5ad97e7aca6e4b8b2"; - List parameters = - Arrays.asList(ownerAddressString, sendAddress, coinType, coinAccount, bytes); - String input = PublicMethed.parametersString(parameters); - logger.info("input:" + input); - String txid = - PublicMethed.triggerContract( - trc1155AddressByte, - "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)", - input, - false, - 0, - maxFeeLimit, - ownerAddressByte, - ownerKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info(txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - Optional byId = PublicMethed.getTransactionById(txid, blockingStubFull); - String s = ByteArray.toHexString(byId.get().getRawData().getContract(0).toByteArray()); - Assert.assertTrue(s.contains(bytes)); - List address = - Stream.of( - ownerAddressString, - ownerAddressString, - ownerAddressString, - ownerAddressString, - ownerAddressString, - ownerAddressString) - .collect(Collectors.toList()); - List coinType1 = Stream.of(0, 1, 2, 3, 4, 5).collect(Collectors.toList()); - List parameters1 = Arrays.asList(address, coinType1); - String data = PublicMethed.parametersString(parameters1); - - logger.info("data2:" + data); - GrpcAPI.TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtention( - trc1155AddressByte, - "balanceOfBatch(address[],uint256[])", - data, - false, - 0, - 0, - "0", - 0, - ownerAddressByte, - ownerKey, - blockingStubFull); - String hexBalance = Hex.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("hexBalance:" + hexBalance); - Assert.assertEquals( - (long) Math.pow(10, 3) - 50, Long.parseLong(hexBalance.substring(128, 192), 16)); - Assert.assertEquals( - (long) Math.pow(10, 2) - 10, Long.parseLong(hexBalance.substring(192, 256), 16)); - Assert.assertEquals((long) Math.pow(10, 5), Long.parseLong(hexBalance.substring(256, 320), 16)); - Assert.assertEquals( - (long) Math.pow(10, 4) - 2, Long.parseLong(hexBalance.substring(320, 384), 16)); - Assert.assertEquals(1, Long.parseLong(hexBalance.substring(384, 448), 16)); - Assert.assertEquals(0, Long.parseLong(hexBalance.substring(448, 512), 16)); - - address = - Stream.of( - sendAddress, - sendAddress, - ownerAddressString, - ownerAddressString, - ownerAddressString, - sendAddress) - .collect(Collectors.toList()); - coinType = Stream.of(0, 1, 2, 3, 4, 5).collect(Collectors.toList()); - parameters = Arrays.asList(address, coinType); - data = PublicMethed.parametersString(parameters); - - logger.info("data2:" + data); - transactionExtention = - PublicMethed.triggerConstantContractForExtention( - trc1155AddressByte, - "balanceOfBatch(address[],uint256[])", - data, - false, - 0, - 0, - "0", - 0, - ownerAddressByte, - ownerKey, - blockingStubFull); - hexBalance = Hex.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(50, Long.parseLong(hexBalance.substring(128, 192), 16)); - Assert.assertEquals(10, Long.parseLong(hexBalance.substring(192, 256), 16)); - Assert.assertEquals((long) Math.pow(10, 5), Long.parseLong(hexBalance.substring(256, 320), 16)); - Assert.assertEquals( - (long) Math.pow(10, 4) - 2, Long.parseLong(hexBalance.substring(320, 384), 16)); - Assert.assertEquals(1, Long.parseLong(hexBalance.substring(384, 448), 16)); - Assert.assertEquals(1, Long.parseLong(hexBalance.substring(448, 512), 16)); - } - - @Test(enabled = true, description = "Trc1155Holder can receive trc1155") - public void test05Trc1155HolderCanReceiveTrc1155() { - List parameters = Arrays.asList(holderAddressString, true); - String data = PublicMethed.parametersString(parameters); - logger.info("data:" + data); - txid = - PublicMethed.triggerContract( - trc1155AddressByte, - "setApprovalForAll(address,bool)", - data, - false, - 0, - maxFeeLimit, - ownerAddressByte, - ownerKey, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("setApprovalForAll_txid:" + txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - int coinType = 0; - int coinAmount = 10; - String bytes = "0000000000000000000000000000000000e6b58be8af95e5ad97e7aca6e4b8b2"; - parameters = - Arrays.asList(ownerAddressString, holderAddressString, coinType, coinAmount, bytes); - data = PublicMethed.parametersString(parameters); - logger.info("data:" + data); - txid = - PublicMethed.triggerContract( - trc1155AddressByte, - "safeTransferFrom(address,address,uint256,uint256,bytes)", - data, - false, - 0, - maxFeeLimit, - ownerAddressByte, - ownerKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("safeTransferFrom_txid:" + txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Optional byId = PublicMethed.getTransactionById(txid, blockingStubFull); - String s = ByteArray.toHexString(byId.get().getRawData().getContract(0).toByteArray()); - Assert.assertTrue(s.contains(bytes)); - logger.info("infobyid1 : --- " + byId); - - logger.info("infobyid1 : --- " + infoById); - - parameters = Arrays.asList(holderAddressString, coinType); - data = PublicMethed.parametersString(parameters); - logger.info("data2:" + data); - GrpcAPI.TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtention( - trc1155AddressByte, - "balanceOf(address,uint256)", - data, - false, - 0, - 0, - "0", - 0, - ownerAddressByte, - ownerKey, - blockingStubFull); - - String hexBalance = Hex.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - long result = Long.parseLong(hexBalance, 16); - Assert.assertEquals(coinAmount, result); - } - - @Test(enabled = true, description = "Trc1155Holder can receive trc1155[]") - public void test06Trc1155HolderCanReceiveTrc1155_01() { - - List parameters = Arrays.asList(holderAddressString, true); - String data = PublicMethed.parametersString(parameters); - logger.info("data:" + data); - txid = - PublicMethed.triggerContract( - trc1155AddressByte, - "setApprovalForAll(address,bool)", - data, - false, - 0, - maxFeeLimit, - ownerAddressByte, - ownerKey, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("setApprovalForAll_txid:" + txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - int trxAmount = 50; - int bttAmount = 30; - int winAmount = 25; - int sunAmount = 10; - int apenftAmount = 1; - List coinType = Stream.of(0, 1, 2, 3, 4).collect(Collectors.toList()); - List coinAmount = - Stream.of(trxAmount, bttAmount, winAmount, sunAmount, apenftAmount) - .collect(Collectors.toList()); - String bytes = "0000000000000000000000000000000000e6b58be8af95e5ad97e7aca6e4b8b2"; - parameters = - Arrays.asList(ownerAddressString, holderAddressString, coinType, coinAmount, bytes); - data = PublicMethed.parametersString(parameters); - logger.info("data1:" + data); - txid = - PublicMethed.triggerContract( - trc1155AddressByte, - "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)", - data, - false, - 0, - maxFeeLimit, - ownerAddressByte, - ownerKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("safeBatchTransferFrom_txid:" + txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid1 : --- " + infoById); - Optional byId = PublicMethed.getTransactionById(txid, blockingStubFull); - String s = ByteArray.toHexString(byId.get().getRawData().getContract(0).toByteArray()); - Assert.assertTrue(s.contains(bytes)); - List address = - Stream.of( - holderAddressString, - holderAddressString, - holderAddressString, - holderAddressString, - holderAddressString, - holderAddressString) - .collect(Collectors.toList()); - coinType = Stream.of(0, 1, 2, 3, 4, 5).collect(Collectors.toList()); - parameters = Arrays.asList(address, coinType); - data = PublicMethed.parametersString(parameters); - logger.info("data2:" + data); - GrpcAPI.TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtention( - trc1155AddressByte, - "balanceOfBatch(address[],uint256[])", - data, - false, - 0, - 0, - "0", - 0, - ownerAddressByte, - ownerKey, - blockingStubFull); - String hexBalance = Hex.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(trxAmount + 10, Long.parseLong(hexBalance.substring(128, 192), 16)); - Assert.assertEquals(bttAmount, Long.parseLong(hexBalance.substring(192, 256), 16)); - Assert.assertEquals(winAmount, Long.parseLong(hexBalance.substring(256, 320), 16)); - Assert.assertEquals(sunAmount, Long.parseLong(hexBalance.substring(320, 384), 16)); - Assert.assertEquals(apenftAmount, Long.parseLong(hexBalance.substring(384, 448), 16)); - Assert.assertEquals(0, Long.parseLong(hexBalance.substring(448, 512), 16)); - } - - @Test(enabled = true, description = "Non-trc1155Holder can not receive trc1155") - public void test07NonTrc1155HolderCanNotReceiveTrc1155() { - List parameters = Arrays.asList(noHolderAddress, true); - String data = PublicMethed.parametersString(parameters); - logger.info("data:" + data); - txid = - PublicMethed.triggerContract( - trc1155AddressByte, - "setApprovalForAll(address,bool)", - data, - false, - 0, - maxFeeLimit, - ownerAddressByte, - ownerKey, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("setApprovalForAll_txid:" + txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - String bytes = "0000000000000000000000000000000000e6b58be8af95e5ad97e7aca6e4b8b2"; - List parameters1 = Arrays.asList(ownerAddressString, noHolderAddress, 1, 1, bytes); - String data1 = PublicMethed.parametersString(parameters1); - logger.info("data:" + data1); - txid = - PublicMethed.triggerContract( - trc1155AddressByte, - "safeTransferFrom(address,address,uint256,uint256,bytes)", - data1, - false, - 0, - maxFeeLimit, - ownerAddressByte, - ownerKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("safeTransferFrom_txid:" + txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid1 : --- " + infoById); - parameters = Arrays.asList(noHolderAddress, 1); - data = PublicMethed.parametersString(parameters); - logger.info("data2:" + data); - GrpcAPI.TransactionExtention transactionExtention1 = - PublicMethed.triggerConstantContractForExtention( - trc1155AddressByte, - "balanceOf(address,uint256)", - data, - false, - 0, - 0, - "0", - 0, - ownerAddressByte, - ownerKey, - blockingStubFull); - - String hexBalance = Hex.toHexString(transactionExtention1.getConstantResult(0).toByteArray()); - long result = Long.parseLong(hexBalance, 16); - Assert.assertEquals(0, result); - } - - /** constructor. */ - public void deployTrc1155() throws Exception { - Assert.assertTrue( - PublicMethed.sendcoin( - ownerAddressByte, 500000000000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "TronCoins"; - String filePath = "./src/test/resources/soliditycode/contractTrc1155.sol"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - int deploySuccessFlag = 1; - Integer retryTimes = 5; - - while (retryTimes-- > 0 && deploySuccessFlag != 0) { - String txid = - PublicMethed.deployContractAndGetTransactionInfoById( - contractName, - abi, - code, - "", - maxFeeLimit, - 0L, - 100, - null, - ownerKey, - ownerAddressByte, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("Deploy IssueCoins txid:" + txid); - Optional infoById = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - com.google.protobuf.ByteString contractAddress = infoById.get().getContractAddress(); - SmartContractOuterClass.SmartContract smartContract = - PublicMethed.getContract(contractAddress.toByteArray(), blockingStubFull); - logger.info("smartContract:" + smartContract); - trc1155AddressByte = contractAddress.toByteArray(); - ownerAddressString = WalletClient.encode58Check(ownerAddressByte); - logger.info("trc1155AddressByte:" + trc1155AddressByte); - logger.info("ownerAddressString:" + ownerAddressString); - deploySuccessFlag = infoById.get().getResult().getNumber(); - } - - Assert.assertEquals(deploySuccessFlag, 0); - } - - /** constructor. */ - public void deployHolder() throws Exception { - String contractName = "MyContractCanReceiver"; - String filePath = "./src/test/resources/soliditycode/contractTrc1155.sol"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = - PublicMethed.deployContractAndGetTransactionInfoById( - contractName, - abi, - code, - "", - maxFeeLimit, - 0L, - 100, - null, - ownerKey, - ownerAddressByte, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("Deploy IssueCoins txid:" + txid); - Optional infoById = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - com.google.protobuf.ByteString contractAddress = infoById.get().getContractAddress(); - SmartContractOuterClass.SmartContract smartContract = - PublicMethed.getContract(contractAddress.toByteArray(), blockingStubFull); - - holderAddressString = WalletClient.encode58Check(contractAddress.toByteArray()); - - logger.info("HolderAddress:" + holderAddressString); - Assert.assertTrue(smartContract.getAbi() != null); - Assert.assertEquals(infoById.get().getResult().getNumber(), 0); - } - - /** constructor. */ - public void deployNoHolder() throws Exception { - String contractName = "MyContractCanNotReceiver"; - String filePath = "./src/test/resources/soliditycode/contractTrc1155.sol"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = - PublicMethed.deployContractAndGetTransactionInfoById( - contractName, - abi, - code, - "", - maxFeeLimit, - 0L, - 100, - null, - ownerKey, - ownerAddressByte, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("Deploy IssueCoins txid:" + txid); - Optional infoById = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - com.google.protobuf.ByteString contractAddress = infoById.get().getContractAddress(); - SmartContractOuterClass.SmartContract smartContract = - PublicMethed.getContract(contractAddress.toByteArray(), blockingStubFull); - - noHolderAddress = WalletClient.encode58Check(contractAddress.toByteArray()); - logger.info("NoHolderAddress:" + noHolderAddress); - Assert.assertTrue(smartContract.getAbi() != null); - Assert.assertEquals(infoById.get().getResult().getNumber(), 0); - } - - /** constructor. */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(fromAddress, ownerKey, ownerAddressByte, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractUnknownException.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractUnknownException.java deleted file mode 100644 index e6d10e00fa9..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractUnknownException.java +++ /dev/null @@ -1,343 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractUnknownException { - - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] grammarAddress = ecKey1.getAddress(); - String testKeyForGrammarAddress = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] grammarAddress2 = ecKey2.getAddress(); - String testKeyForGrammarAddress2 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] grammarAddress3 = ecKey3.getAddress(); - String testKeyForGrammarAddress3 = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] grammarAddress4 = ecKey4.getAddress(); - String testKeyForGrammarAddress4 = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKeyForGrammarAddress); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - logger.info(Long.toString(PublicMethed.queryAccount(testNetAccountKey, blockingStubFull) - .getBalance())); - } - - @Test(enabled = true, description = "trigger selfdestruct method") - public void testGrammar001() { - Assert.assertTrue(PublicMethed - .sendcoin(grammarAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(grammarAddress, 204800000, - 0, 1, testKeyForGrammarAddress, blockingStubFull)); - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(grammarAddress, - blockingStubFull); - info = PublicMethed.queryAccount(grammarAddress, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - long beforeenergyLimit = resourceInfo.getEnergyLimit(); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("beforeenergyLimit:" + beforeenergyLimit); - String filePath = "src/test/resources/soliditycode/contractUnknownException.sol"; - String contractName = "testA"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 20L, 100, null, testKeyForGrammarAddress, - grammarAddress, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - final String s = infoById.get().getResMessage().toStringUtf8(); - long fee = infoById.get().getFee(); - long energyUsage = infoById.get().getReceipt().getEnergyUsage(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - Account infoafter = PublicMethed.queryAccount(grammarAddress, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(grammarAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfo.getNetUsed(); - Long afterFreeNetUsed = resourceInfo.getFreeNetUsed(); - long aftereenergyLimit = resourceInfo.getEnergyLimit(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterenergyLimit:" + aftereenergyLimit); - Assert.assertThat(s, containsString("REVERT opcode executed")); - PublicMethed.unFreezeBalance(grammarAddress, testKeyForGrammarAddress, 1, grammarAddress, - blockingStubFull); - PublicMethed.freedResource(grammarAddress, testKeyForGrammarAddress, testNetAccountAddress, - blockingStubFull); - } - - @Test(enabled = true, description = "trigger revert method") - public void testGrammar002() { - Assert.assertTrue(PublicMethed - .sendcoin(grammarAddress2, 100000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(grammarAddress2, 10000000L, - 0, 1, testKeyForGrammarAddress2, blockingStubFull)); - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(grammarAddress2, - blockingStubFull); - info = PublicMethed.queryAccount(grammarAddress2, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - long beforeenergyLimit = resourceInfo.getEnergyLimit(); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("beforeenergyLimit:" + beforeenergyLimit); - String filePath = "src/test/resources/soliditycode/contractUnknownException.sol"; - String contractName = "testB"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 20L, 100, null, testKeyForGrammarAddress2, - grammarAddress2, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - final long fee = infoById.get().getFee(); - final long energyUsage = infoById.get().getReceipt().getEnergyUsage(); - final long energyFee = infoById.get().getReceipt().getEnergyFee(); - - final String s = infoById.get().getResMessage().toStringUtf8(); - - Account infoafter = PublicMethed.queryAccount(grammarAddress2, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(grammarAddress2, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfo.getNetUsed(); - Long afterFreeNetUsed = resourceInfo.getFreeNetUsed(); - long aftereenergyLimit = resourceInfo.getEnergyLimit(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterenergyLimit:" + aftereenergyLimit); - Assert.assertThat(s, containsString("REVERT opcode executed")); - Assert.assertFalse(energyFee == 1000000000); - - Assert.assertTrue(beforeBalance - fee == afterBalance); - PublicMethed.unFreezeBalance(grammarAddress2, testKeyForGrammarAddress2, 1, grammarAddress2, - blockingStubFull); - PublicMethed.freedResource(grammarAddress2, testKeyForGrammarAddress2, testNetAccountAddress, - blockingStubFull); - - } - - @Test(enabled = true, description = "trigger assert method") - public void testGrammar003() { - Assert.assertTrue(PublicMethed - .sendcoin(grammarAddress3, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(grammarAddress3, 1000000000L, - 0, 1, testKeyForGrammarAddress3, blockingStubFull)); - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(grammarAddress3, - blockingStubFull); - info = PublicMethed.queryAccount(grammarAddress3, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - long beforeenergyLimit = resourceInfo.getEnergyLimit(); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("beforeenergyLimit:" + beforeenergyLimit); - String filePath = "src/test/resources/soliditycode/contractUnknownException.sol"; - String contractName = "testC"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 20L, 100, null, testKeyForGrammarAddress3, - grammarAddress3, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - final long fee = infoById.get().getFee(); - final long energyUsage = infoById.get().getReceipt().getEnergyUsage(); - final long energyFee = infoById.get().getReceipt().getEnergyFee(); - String s = infoById.get().getResMessage().toStringUtf8(); - Account infoafter = PublicMethed.queryAccount(grammarAddress3, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(grammarAddress3, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfo.getNetUsed(); - Long afterFreeNetUsed = resourceInfo.getFreeNetUsed(); - long aftereenergyLimit = resourceInfo.getEnergyLimit(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterenergyLimit:" + aftereenergyLimit); - logger.info("s:" + s); - Assert.assertThat(s, containsString("REVERT opcode executed")); - Assert.assertTrue(beforeBalance - fee == afterBalance); - PublicMethed.unFreezeBalance(grammarAddress3, testKeyForGrammarAddress3, 1, grammarAddress3, - blockingStubFull); - PublicMethed.freedResource(grammarAddress3, testKeyForGrammarAddress3, testNetAccountAddress, - blockingStubFull); - - } - - - @Test(enabled = true, description = "trigger require method") - public void testGrammar004() { - Assert.assertTrue(PublicMethed - .sendcoin(grammarAddress4, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(grammarAddress4, 100000000L, - 0, 1, testKeyForGrammarAddress4, blockingStubFull)); - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(grammarAddress4, - blockingStubFull); - info = PublicMethed.queryAccount(grammarAddress4, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - long beforeenergyLimit = resourceInfo.getEnergyLimit(); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("beforeenergyLimit:" + beforeenergyLimit); - String filePath = "src/test/resources/soliditycode/contractUnknownException.sol"; - String contractName = "testD"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 20L, 100, null, testKeyForGrammarAddress4, - grammarAddress4, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - final String s = infoById.get().getResMessage().toStringUtf8(); - final long fee = infoById.get().getFee(); - long energyUsage = infoById.get().getReceipt().getEnergyUsage(); - final long energyFee = infoById.get().getReceipt().getEnergyFee(); - - Account infoafter = PublicMethed.queryAccount(grammarAddress4, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(grammarAddress4, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfo.getNetUsed(); - Long afterFreeNetUsed = resourceInfo.getFreeNetUsed(); - long aftereenergyLimit = resourceInfo.getEnergyLimit(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterenergyLimit:" + aftereenergyLimit); - Assert.assertThat(s, containsString("REVERT opcode executed")); - Assert.assertTrue(beforeBalance - fee == afterBalance); - Assert.assertFalse(energyFee == 1000000000); - PublicMethed.unFreezeBalance(grammarAddress4, testKeyForGrammarAddress4, 1, grammarAddress4, - blockingStubFull); - PublicMethed.freedResource(grammarAddress4, testKeyForGrammarAddress4, testNetAccountAddress, - blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/GetTransactionInfoByBlockNumFromSolidity.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/GetTransactionInfoByBlockNumFromSolidity.java deleted file mode 100644 index 3fa52bb619f..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/GetTransactionInfoByBlockNumFromSolidity.java +++ /dev/null @@ -1,53 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import org.junit.Assert; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -public class GetTransactionInfoByBlockNumFromSolidity { - - public ManagedChannel channelFull = null; - public WalletGrpc.WalletBlockingStub blockingStubFull = null; - public ManagedChannel channelSolidity = null; - public WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - public String fullNode = - Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list").get(0); - public String solidityNode = - Configuration.getByPath("testng.conf").getStringList("solidityNode.ip.list").get(0); - - @Test(enabled = true, description = "test getTransactionInfoByBlockNumFromSolidity") - public void test01GetTransactionInfoByBlockNumFromSolidity() { - channelFull = ManagedChannelBuilder.forTarget(fullNode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelSolidity = ManagedChannelBuilder.forTarget(solidityNode).usePlaintext().build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - Protocol.Block solidityCurrentBlock = - blockingStubSolidity.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - long block = solidityCurrentBlock.getBlockHeader().getRawData().getNumber(); - long targetBlock; - for (targetBlock = block; targetBlock > 0; targetBlock--) { - GrpcAPI.NumberMessage.Builder builder = GrpcAPI.NumberMessage.newBuilder(); - builder.setNum(targetBlock); - if (blockingStubSolidity.getTransactionCountByBlockNum(builder.build()).getNum() > 0) { - break; - } - } - - GrpcAPI.TransactionInfoList transactionList = - PublicMethed.getTransactionInfoByBlockNum(targetBlock, blockingStubFull).get(); - - GrpcAPI.TransactionInfoList transactionListFromSolidity = - PublicMethed.getTransactionInfoByBlockNum(targetBlock, blockingStubFull).get(); - Assert.assertEquals(transactionList, transactionListFromSolidity); - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/RateLimite001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/RateLimite001.java deleted file mode 100644 index 2036dc78ebb..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/RateLimite001.java +++ /dev/null @@ -1,176 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; - -@Slf4j -public class RateLimite001 { - - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private ManagedChannel channelRealSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub realBlockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - private String realSoliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - channelRealSolidity = ManagedChannelBuilder.forTarget(realSoliditynode) - .usePlaintext() - .build(); - realBlockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelRealSolidity); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Rate limit IpQpsStrategy for ListWitness interface") - public void test1QpsStrategyForListWitnessInterface() { - Long startTimeStamp = System.currentTimeMillis(); - Integer repeatTimes = 0; - while (repeatTimes++ < 20) { - blockingStubFull.listWitnesses(EmptyMessage.newBuilder().build()); - } - Long endTimesStap = System.currentTimeMillis(); - logger.info("startTimeStamp - endTimesStap:" + (endTimesStap - startTimeStamp)); - Assert.assertTrue(endTimesStap - startTimeStamp > 5000); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Rate limit IpQpsStrategy for ListNodes interface") - public void test2IpQpsStrategyForListNodesInterface() { - Long startTimeStamp = System.currentTimeMillis(); - Integer repeatTimes = 0; - while (repeatTimes++ < 20) { - blockingStubFull.listNodes(EmptyMessage.newBuilder().build()); - } - Long endTimesStap = System.currentTimeMillis(); - logger.info("startTimeStamp - endTimesStap:" + (endTimesStap - startTimeStamp)); - Assert.assertTrue(endTimesStap - startTimeStamp > 5000); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Rate limit IpQpsStrategy for getBlockByNum2 " - + "interface on fullnode's solidity service") - public void test3IpQpsStrategyForgetBlockByNum2ResourceInterfaceOnFullnodeSolidityService() { - Long startTimeStamp = System.currentTimeMillis(); - Integer repeatTimes = 0; - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(5); - - while (repeatTimes++ < 20) { - blockingStubSolidity.getBlockByNum2(builder.build()); - } - Long endTimesStap = System.currentTimeMillis(); - logger.info("startTimeStamp - endTimesStap:" + (endTimesStap - startTimeStamp)); - Assert.assertTrue(endTimesStap - startTimeStamp > 5000); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Rate limit QpsStrategy for getBlockByNum " - + "interface on fullnode's solidity service") - public void test4QpsStrategyForgetBlockByNumResourceInterfaceOnFullnodeSolidityService() { - Long startTimeStamp = System.currentTimeMillis(); - Integer repeatTimes = 0; - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(5); - while (repeatTimes++ < 20) { - blockingStubSolidity.getBlockByNum(builder.build()); - } - Long endTimesStap = System.currentTimeMillis(); - logger.info("startTimeStamp - endTimesStap:" + (endTimesStap - startTimeStamp)); - Assert.assertTrue(endTimesStap - startTimeStamp > 5000); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Rate limit IpQpsStrategy for getBlockByNum2 " - + "interface on real solidity") - public void test5IpQpsStrategyForgetBlockByNum2ResourceInterfaceOnFullnodeSolidityService() { - Long startTimeStamp = System.currentTimeMillis(); - Integer repeatTimes = 0; - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(5); - - while (repeatTimes++ < 20) { - realBlockingStubSolidity.getBlockByNum2(builder.build()); - } - Long endTimesStap = System.currentTimeMillis(); - logger.info("startTimeStamp - endTimesStap:" + (endTimesStap - startTimeStamp)); - Assert.assertTrue(endTimesStap - startTimeStamp > 5000); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Rate limit QpsStrategy for getBlockByNum " - + "interface on real solidity") - public void test6QpsStrategyForgetBlockByNumResourceInterfaceOnFullnodeSolidityService() { - Long startTimeStamp = System.currentTimeMillis(); - Integer repeatTimes = 0; - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(5); - while (repeatTimes++ < 20) { - realBlockingStubSolidity.getBlockByNum(builder.build()); - } - Long endTimesStap = System.currentTimeMillis(); - logger.info("startTimeStamp - endTimesStap:" + (endTimesStap - startTimeStamp)); - Assert.assertTrue(endTimesStap - startTimeStamp > 5000); - } - - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/RequireException.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/RequireException.java deleted file mode 100644 index 2d06f119e39..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/RequireException.java +++ /dev/null @@ -1,791 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class RequireException { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] asset016Address = ecKey1.getAddress(); - String testKeyForAssetIssue016 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private ManagedChannel channelFull2 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull2 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKeyForAssetIssue016); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Require Exception") - public void test1TestRequireContract() { - ecKey1 = new ECKey(Utils.getRandom()); - asset016Address = ecKey1.getAddress(); - testKeyForAssetIssue016 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - logger.info(Long.toString(PublicMethed.queryAccount(testNetAccountKey, blockingStubFull) - .getBalance())); - - Assert.assertTrue(PublicMethed - .sendcoin(asset016Address, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = - "src/test/resources/soliditycode/requireExceptiontest1TestRequireContract.sol"; - String contractName = "TestThrowsContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForAssetIssue016, - asset016Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(asset016Address, - blockingStubFull); - info = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - final String txid = PublicMethed.triggerContract(contractAddress, - "testRequire()", "#", false, - 0, maxFeeLimit, asset016Address, testKeyForAssetIssue016, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - - Account infoafter = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(asset016Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - } - - @Test(enabled = true, description = "Throw Exception") - public void test2TestThrowsContract() { - String filePath = - "src/test/resources/soliditycode/requireExceptiontest2TestThrowsContract.sol"; - String contractName = "TestThrowsContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForAssetIssue016, - asset016Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(asset016Address, - blockingStubFull); - info = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - final String txid = PublicMethed.triggerContract(contractAddress, - "testThrow()", "#", false, - 0, maxFeeLimit, asset016Address, testKeyForAssetIssue016, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - - Account infoafter = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(asset016Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("testTestThrowsContract"); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - - @Test(enabled = true, description = "Call Revert ") - public void test3TestRevertContract() { - String filePath = - "src/test/resources/soliditycode/requireExceptiontest3TestRevertContract.sol"; - String contractName = "TestThrowsContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForAssetIssue016, - asset016Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(asset016Address, - blockingStubFull); - info = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - final String txid = PublicMethed.triggerContract(contractAddress, - "testRevert()", "#", false, - 0, maxFeeLimit, asset016Address, testKeyForAssetIssue016, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - - Account infoafter = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(asset016Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - } - - @Test(enabled = false, description = "No payable function call value") - public void test4noPayableContract() { - String filePath = - "src/test/resources/soliditycode/requireExceptiontest4noPayableContract_1.sol"; - String contractName = "noPayableContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForAssetIssue016, - asset016Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(asset016Address, - blockingStubFull); - info = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - final String txid = PublicMethed.triggerContract(contractAddress, - "noPayable()", "#", false, - 22, maxFeeLimit, asset016Address, testKeyForAssetIssue016, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - Account infoafter = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(asset016Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - } - - @Test(enabled = false, description = "No payable Constructor") - public void test5noPayableConstructor() { - - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(asset016Address, - blockingStubFull); - info = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String filePath = - "src/test/resources/soliditycode/requireExceptiontest5noPayableConstructor_1.sol"; - String contractName = "MyContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - final String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 22L, 100, null, - testKeyForAssetIssue016, asset016Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - - Account infoafter = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(asset016Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - - } - - @Test(enabled = true, description = "Transfer failed") - public void test6transferTestContract() { - String filePath = - "src/test/resources/soliditycode/requireExceptiontest6transferTestContract.sol"; - String contractName = "transferTestContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForAssetIssue016, - asset016Address, blockingStubFull); - final Account info; - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(asset016Address, - blockingStubFull); - info = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String newCxoAddress = "\"" + Base58.encode58Check(testNetAccountAddress) - + "\""; - final String txid = PublicMethed.triggerContract(contractAddress, - "tranferTest(address) ", newCxoAddress, false, - 5, maxFeeLimit, asset016Address, testKeyForAssetIssue016, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - - Account infoafter = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(asset016Address, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("transferTestContract"); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - } - - @Test(enabled = true, description = "No payable fallback call value") - public void test7payableFallbakContract() { - String filePath = - "src/test/resources/soliditycode/requireExceptiontest7payableFallbakContract.sol"; - String contractName = "Caller"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForAssetIssue016, - asset016Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Integer times = 0; - String contractName1 = "Test"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - byte[] contractAddress1; - contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 0L, - 100, null, testKeyForAssetIssue016, - asset016Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(asset016Address, - blockingStubFull); - Account info; - info = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String saleContractString = "\"" + Base58.encode58Check(contractAddress) + "\""; - final String txid = PublicMethed.triggerContract(contractAddress1, - "callTest(address)", saleContractString, false, - 5, maxFeeLimit, asset016Address, testKeyForAssetIssue016, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - - Account infoafter = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(asset016Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - } - - @Test(enabled = true, description = "New contract gas not enough") - public void test8newContractGasNoenough() { - String filePath = - "src/test/resources/soliditycode/requireExceptiontest8newContractGasNoenough.sol"; - String contractName = "Account"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForAssetIssue016, - asset016Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName1 = "Initialize"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - - final byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 0L, 100, null, - testKeyForAssetIssue016, asset016Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(asset016Address, - blockingStubFull); - info = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - final String txid = PublicMethed.triggerContract(contractAddress1, - "newAccount()", "#", false, - 0, 5226000, asset016Address, testKeyForAssetIssue016, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - - Account infoafter = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(asset016Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - - } - - @Test(enabled = true, description = "Message used error") - public void test9MessageUsedErrorFeed() { - String filePath = - "src/test/resources/soliditycode/requireExceptiontest9MessageUsedErrorFeed.sol"; - String contractName = "MathedFeed"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForAssetIssue016, - asset016Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - final String saleContractString = "\"" + Base58.encode58Check(contractAddress) + "\""; - String contractName1 = "MathedUseContract"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - - final byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 0L, 100, null, - testKeyForAssetIssue016, asset016Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(asset016Address, - blockingStubFull); - info = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - final String txid = PublicMethed.triggerContract(contractAddress1, - "messageUse(address)", saleContractString, false, - 0, maxFeeLimit, asset016Address, testKeyForAssetIssue016, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - - Account infoafter = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(asset016Address, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - } - - @Test(enabled = true, description = "Function used error") - public void testFunctionUsedErrorFeed() { - String filePath = - "src/test/resources/soliditycode/requireExceptiontestFunctionUsedErrorFeed.sol"; - String contractName = "MessageFeed"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForAssetIssue016, - asset016Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - final String saleContractString = "\"" + Base58.encode58Check(contractAddress) + "\""; - - String contractName1 = "MessageUseContract"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - final byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 0L, - 100, null, testKeyForAssetIssue016, - asset016Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(asset016Address, - blockingStubFull); - info = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - final String txid = PublicMethed.triggerContract(contractAddress1, - "messageUse(address)", saleContractString, false, - 0, maxFeeLimit, asset016Address, testKeyForAssetIssue016, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - - Account infoafter = PublicMethed.queryAccount(testKeyForAssetIssue016, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(asset016Address, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - PublicMethed.freedResource(asset016Address, testKeyForAssetIssue016, testNetAccountAddress, - blockingStubFull); - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount002.java deleted file mode 100644 index d77bcf889c9..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount002.java +++ /dev/null @@ -1,163 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Comparator; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAccount002 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private ManagedChannel searchChannelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletGrpc.WalletBlockingStub searchBlockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String searchFullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /* @Test(enabled = true) - public void TestGetAllAccount(){ - GrpcAPI.AccountList accountlist = - blockingStubFull.listAccounts(GrpcAPI.EmptyMessage.newBuilder().build()); - Optional result = Optional.ofNullable(accountlist); - if (result.isPresent()) { - GrpcAPI.AccountList accountList = result.get(); - List list = accountList.getAccountsList(); - List newList = new ArrayList(); - newList.addAll(list); - newList.sort(new AccountComparator()); - GrpcAPI.AccountList.Builder builder = GrpcAPI.AccountList.newBuilder(); - newList.forEach(account -> builder.addAccounts(account)); - result = Optional.of(builder.build()); - } - Assert.assertTrue(result.get().getAccountsCount() > 0); - logger.info(Integer.toString(result.get().getAccountsCount())); - for (int j = 0; j < result.get().getAccountsCount(); j++){ - Assert.assertFalse(result.get().getAccounts(j).getAddress().isEmpty()); - } - - - }*/ - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext() - .build(); - searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (searchChannelFull != null) { - searchChannelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - class AccountComparator implements Comparator { - - public int compare(Object o1, Object o2) { - return Long.compare(((Account) o2).getBalance(), ((Account) o1).getBalance()); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount010.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount010.java deleted file mode 100644 index af151e8cf56..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount010.java +++ /dev/null @@ -1,128 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAccount010 { - - private static final long now = System.currentTimeMillis(); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] account010Address = ecKey1.getAddress(); - String account010Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] account010SecondAddress = ecKey2.getAddress(); - String account010SecondKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] account010InvalidAddress = ecKey3.getAddress(); - String account010InvalidKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - PublicMethed.printAddress(account010Key); - PublicMethed.printAddress(account010SecondKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - - } - - @Test(enabled = false) - public void testGetStorage() { - Assert.assertTrue(PublicMethed.sendcoin(account010Address, 100000000, - fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(account010SecondAddress, 100000000, - fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(account010InvalidAddress, 100000000, - fromAddress, testKey002, blockingStubFull)); - Account account010Info = PublicMethed.queryAccount(account010Key, blockingStubFull); - Assert.assertTrue(account010Info.getAccountResource().getStorageLimit() == 0); - Assert.assertTrue(account010Info.getAccountResource().getLatestExchangeStorageTime() == 0); - - Assert.assertTrue(PublicMethed.buyStorage(100000000L, account010Address, account010Key, - blockingStubFull)); - - account010Info = PublicMethed.queryAccount(account010Key, blockingStubFull); - Assert.assertTrue(account010Info.getAccountResource().getStorageLimit() > 0); - Assert.assertTrue(account010Info.getAccountResource().getLatestExchangeStorageTime() > 0); - - AccountResourceMessage account010Resource = PublicMethed.getAccountResource(account010Address, - blockingStubFull); - Assert.assertTrue(account010Resource.getStorageLimit() > 0); - } - - @Test(enabled = false) - public void testSellStorage() { - AccountResourceMessage account010Resource = PublicMethed.getAccountResource(account010Address, - blockingStubFull); - Long storageLimit = account010Resource.getStorageLimit(); - Account account001Info = PublicMethed.queryAccount(account010Key, blockingStubFull); - Assert.assertTrue(account001Info.getBalance() == 0); - //When there is no enough storage,sell failed. - Assert.assertFalse(PublicMethed.sellStorage(storageLimit + 1, account010Address, account010Key, - blockingStubFull)); - //Can not sell 0 storage - Assert.assertFalse(PublicMethed.sellStorage(0, account010Address, account010Key, - blockingStubFull)); - //Sell all storage. - Assert.assertTrue(PublicMethed.sellStorage(storageLimit, account010Address, account010Key, - blockingStubFull)); - account010Resource = PublicMethed.getAccountResource(account010Address, - blockingStubFull); - storageLimit = account010Resource.getStorageLimit(); - Assert.assertTrue(storageLimit == 0); - account001Info = PublicMethed.queryAccount(account010Key, blockingStubFull); - Assert.assertTrue(account001Info.getBalance() > 0); - - - } - - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount012.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount012.java deleted file mode 100644 index 3a3a72c3ce1..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount012.java +++ /dev/null @@ -1,188 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Optional; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAccount012 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("mainWitness.key25"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("mainWitness.key2"); - private final byte[] testAddress003 = PublicMethed.getFinalAddress(testKey003); - - private final String testKey004 = Configuration.getByPath("testng.conf") - .getString("mainWitness.key3"); - private final byte[] testAddress004 = PublicMethed.getFinalAddress(testKey004); - ArrayList txidList = new ArrayList(); - Optional infoById = null; - Long beforeTime; - Long afterTime; - Long beforeBlockNum; - Long afterBlockNum; - Block currentBlock; - Long currentBlockNum; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - //get account - - /** - * constructor. - */ - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKey002); - PublicMethed.printAddress(testKey003); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - currentBlock = blockingStubFull1.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - beforeBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - beforeTime = System.currentTimeMillis(); - } - - @Test(enabled = false, threadPoolSize = 20, invocationCount = 20) - public void storageAndCpu() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] asset011Address = ecKey1.getAddress(); - String testKeyForAssetIssue011 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.printAddress(testKeyForAssetIssue011); - - PublicMethed - .sendcoin(asset011Address, 100000000000000L, fromAddress, testKey002, blockingStubFull); - Random rand = new Random(); - Integer randNum = rand.nextInt(30) + 1; - randNum = rand.nextInt(4000); - - Long maxFeeLimit = 1000000000L; - String contractName = "StorageAndCpu" + Integer.toString(randNum); - String code = Configuration.getByPath("testng.conf") - .getString("code.code_WalletTestAccount012_storageAndCpu"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_WalletTestAccount012_storageAndCpu"); - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, - "", maxFeeLimit, - 0L, 100, null, testKeyForAssetIssue011, asset011Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - String txid; - - Integer i = 1; - AccountResourceMessage accountResource = PublicMethed.getAccountResource(asset011Address, - blockingStubFull); - accountResource = PublicMethed.getAccountResource(asset011Address, - blockingStubFull); - Long beforeEnergyLimit = accountResource.getEnergyLimit(); - Long afterEnergyLimit; - Long beforeTotalEnergyLimit = accountResource.getTotalEnergyLimit(); - Account account = PublicMethed.queryAccount(testKeyForAssetIssue011, blockingStubFull); - Long afterTotalEnergyLimit; - while (i++ < 20000) { - accountResource = PublicMethed.getAccountResource(asset011Address, - blockingStubFull); - beforeEnergyLimit = accountResource.getEnergyLimit(); - beforeTotalEnergyLimit = accountResource.getTotalEnergyLimit(); - String initParmes = "\"" + "21" + "\""; - /* txid = PublicMethed.triggerContract(contractAddress, - "storage8Char()", "", false, - 0, maxFeeLimit, asset011Address, testKeyForAssetIssue011, blockingStubFull);*/ - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - txid = PublicMethed.triggerContract(contractAddress, - "add2(uint256)", initParmes, false, - 0, maxFeeLimit, asset011Address, testKeyForAssetIssue011, blockingStubFull); - accountResource = PublicMethed.getAccountResource(asset011Address, - blockingStubFull); - //logger.info("Current limit is " + accountResource.getTotalEnergyLimit()); - //PublicMethed.freezeBalanceGetEnergy(asset011Address,1000000L,3, - // 1,testKeyForAssetIssue011,blockingStubFull); - - accountResource = PublicMethed.getAccountResource(asset011Address, - blockingStubFull); - afterEnergyLimit = accountResource.getEnergyLimit(); - afterTotalEnergyLimit = accountResource.getTotalEnergyLimit(); - - logger.info("Total energy limit is " + (float) afterTotalEnergyLimit / 50000000000L); - Float rate = - (float) (afterTotalEnergyLimit - beforeTotalEnergyLimit) / beforeTotalEnergyLimit; - //logger.info("rate is " + rate); - //Assert.assertTrue(rate >= 0.001001000 && rate <= 0.001001002); - //txidList.add(txid); - try { - Thread.sleep(30); - } catch (InterruptedException e) { - e.printStackTrace(); - } - account = PublicMethed.queryAccount(testKeyForAssetIssue011, blockingStubFull); - Float energyrate = (float) (beforeEnergyLimit) / account.getAccountResource() - .getFrozenBalanceForEnergy().getFrozenBalance(); - //logger.info("energy rate is " + energyrate); - if (i % 20 == 0) { - PublicMethed.freezeBalanceForReceiver(fromAddress, 1000000L, 3, 1, - ByteString.copyFrom(asset011Address), testKey002, blockingStubFull); - } - } - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount013.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount013.java deleted file mode 100644 index 09c5849e97e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount013.java +++ /dev/null @@ -1,515 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAccount013 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - Optional infoById = null; - long account013BeforeBalance; - long freezeAmount = 10000000L; - long freezeDuration = 0; - byte[] account013Address; - String testKeyForAccount013; - byte[] receiverDelegateAddress; - String receiverDelegateKey; - byte[] emptyAddress; - String emptyKey; - byte[] account4DelegatedResourceAddress; - String account4DelegatedResourceKey; - byte[] account5DelegatedResourceAddress; - String account5DelegatedResourceKey; - byte[] accountForDeployAddress; - String accountForDeployKey; - byte[] accountForAssetIssueAddress; - String accountForAssetIssueKey; - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private ManagedChannel channelSoliInFull = null; - private ManagedChannel channelPbft = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSoliInFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPbft = null; - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String soliInFullnode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - private String soliInPbft = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(2); - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelSoliInFull = ManagedChannelBuilder.forTarget(soliInFullnode) - .usePlaintext() - .build(); - blockingStubSoliInFull = WalletSolidityGrpc.newBlockingStub(channelSoliInFull); - - channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext() - .build(); - blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); - } - - @Test(enabled = true, description = "Delegate resource for bandwidth and energy") - public void test1DelegateResourceForBandwidthAndEnergy() { - //Create account013 - ECKey ecKey1 = new ECKey(Utils.getRandom()); - account013Address = ecKey1.getAddress(); - testKeyForAccount013 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.printAddress(testKeyForAccount013); - //Create receiver - ECKey ecKey2 = new ECKey(Utils.getRandom()); - receiverDelegateAddress = ecKey2.getAddress(); - receiverDelegateKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - PublicMethed.printAddress(receiverDelegateKey); - //Create Empty account - ECKey ecKey3 = new ECKey(Utils.getRandom()); - emptyAddress = ecKey3.getAddress(); - emptyKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - - //sendcoin to Account013 - Assert.assertTrue(PublicMethed - .sendcoin(account013Address, 10000000000L, fromAddress, testKey002, blockingStubFull)); - //sendcoin to receiver - Assert.assertTrue(PublicMethed - .sendcoin(receiverDelegateAddress, 10000000000L, toAddress, testKey003, blockingStubFull)); - - //getAccountResource account013 - PublicMethed.waitProduceNextBlock(blockingStubFull); - AccountResourceMessage account013Resource = PublicMethed - .getAccountResource(account013Address, blockingStubFull); - logger.info("013 energy limit is " + account013Resource.getEnergyLimit()); - logger.info("013 net limit is " + account013Resource.getNetLimit()); - //getAccountResource receiver - AccountResourceMessage receiverResource = PublicMethed - .getAccountResource(receiverDelegateAddress, blockingStubFull); - logger.info("receiver energy limit is " + receiverResource.getEnergyLimit()); - logger.info("receiver net limit is " + receiverResource.getNetLimit()); - Protocol.Account account013infoBefore = PublicMethed - .queryAccount(account013Address, blockingStubFull); - //get resources of account013 before DelegateResource - account013BeforeBalance = account013infoBefore.getBalance(); - AccountResourceMessage account013ResBefore = PublicMethed - .getAccountResource(account013Address, blockingStubFull); - final long account013BeforeBandWidth = account013ResBefore.getNetLimit(); - AccountResourceMessage receiverResourceBefore = PublicMethed - .getAccountResource(receiverDelegateAddress, blockingStubFull); - long receiverBeforeBandWidth = receiverResourceBefore.getNetLimit(); - //Account013 DelegateResource for BandWidth to receiver - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(account013Address, freezeAmount, freezeDuration, 0, - ByteString.copyFrom(receiverDelegateAddress), testKeyForAccount013, blockingStubFull)); - Protocol.Account account013infoAfter = PublicMethed - .queryAccount(account013Address, blockingStubFull); - //get balance of account013 after DelegateResource - long account013AfterBalance = account013infoAfter.getBalance(); - AccountResourceMessage account013ResAfter = PublicMethed - .getAccountResource(account013Address, blockingStubFull); - //get BandWidth of account013 after DelegateResource - long account013AfterBandWidth = account013ResAfter.getNetLimit(); - AccountResourceMessage receiverResourceAfter = PublicMethed - .getAccountResource(receiverDelegateAddress, blockingStubFull); - //Bandwidth of receiver after DelegateResource - long receiverAfterBandWidth = receiverResourceAfter.getNetLimit(); - //Balance of Account013 reduced amount same as DelegateResource - Assert.assertTrue(account013BeforeBalance == account013AfterBalance + freezeAmount); - //Bandwidth of account013 is equally before and after DelegateResource - Assert.assertTrue(account013AfterBandWidth == account013BeforeBandWidth); - //Bandwidth of receiver after DelegateResource is greater than before - Assert.assertTrue(receiverAfterBandWidth > receiverBeforeBandWidth); - Protocol.Account account013Before1 = PublicMethed - .queryAccount(account013Address, blockingStubFull); - //balance of account013 before DelegateResource - long account013BeforeBalance1 = account013Before1.getBalance(); - AccountResourceMessage account013ResBefore1 = PublicMethed - .getAccountResource(account013Address, blockingStubFull); - //Energy of account013 before DelegateResource - long account013BeforeEnergy = account013ResBefore1.getEnergyLimit(); - AccountResourceMessage receiverResourceBefore1 = PublicMethed - .getAccountResource(receiverDelegateAddress, blockingStubFull); - //Energy of receiver before DelegateResource - long receiverBeforeEnergy = receiverResourceBefore1.getEnergyLimit(); - //Account013 DelegateResource Energy to receiver - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(account013Address, freezeAmount, freezeDuration, 1, - ByteString.copyFrom(receiverDelegateAddress), testKeyForAccount013, blockingStubFull)); - Protocol.Account account013infoAfter1 = PublicMethed - .queryAccount(account013Address, blockingStubFull); - //balance of account013 after DelegateResource - long account013AfterBalance1 = account013infoAfter1.getBalance(); - AccountResourceMessage account013ResAfter1 = PublicMethed - .getAccountResource(account013Address, blockingStubFull); - long account013AfterEnergy = account013ResAfter1.getEnergyLimit(); - //Energy of account013 after DelegateResource - AccountResourceMessage receiverResourceAfter1 = PublicMethed - .getAccountResource(receiverDelegateAddress, blockingStubFull); - //Energy of receiver after DelegateResource - long receiverAfterEnergy = receiverResourceAfter1.getEnergyLimit(); - //Balance of Account013 reduced amount same as DelegateResource - Assert.assertTrue(account013BeforeBalance1 == account013AfterBalance1 + freezeAmount); - //Bandwidth of account013 is equally before and after DelegateResource - Assert.assertTrue(account013AfterEnergy == account013BeforeEnergy); - //Bandwidth of receiver after DelegateResource is greater than before - Assert.assertTrue(receiverAfterEnergy > receiverBeforeEnergy); - //account013 DelegateResource to Empty failed - Assert.assertFalse(PublicMethed - .freezeBalanceForReceiver(account013Address, freezeAmount, freezeDuration, 0, - ByteString.copyFrom(emptyAddress), testKeyForAccount013, blockingStubFull)); - //account013 DelegateResource to account013 failed - Assert.assertFalse(PublicMethed - .freezeBalanceForReceiver(account013Address, freezeAmount, freezeDuration, 0, - ByteString.copyFrom(account013Address), testKeyForAccount013, blockingStubFull)); - account013Resource = PublicMethed.getAccountResource(account013Address, blockingStubFull); - logger.info("After 013 energy limit is " + account013Resource.getEnergyLimit()); - logger.info("After 013 net limit is " + account013Resource.getNetLimit()); - - receiverResource = PublicMethed.getAccountResource(receiverDelegateAddress, blockingStubFull); - logger.info("After receiver energy limit is " + receiverResource.getEnergyLimit()); - logger.info("After receiver net limit is " + receiverResource.getNetLimit()); - } - - @Test(enabled = true, description = "Get delegate resource") - public void test2getDelegatedResource() { - //Create Account4 - ECKey ecKey4 = new ECKey(Utils.getRandom()); - account4DelegatedResourceAddress = ecKey4.getAddress(); - account4DelegatedResourceKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - //Create Account5 - ECKey ecKey5 = new ECKey(Utils.getRandom()); - account5DelegatedResourceAddress = ecKey5.getAddress(); - account5DelegatedResourceKey = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); - - //sendcoin to Account4 - Assert.assertTrue(PublicMethed - .sendcoin(account4DelegatedResourceAddress, 10000000000L, fromAddress, testKey002, - blockingStubFull)); - - //sendcoin to Account5 - Assert.assertTrue(PublicMethed - .sendcoin(account5DelegatedResourceAddress, 20000000000L, toAddress, testKey003, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Protocol.Account account4infoBefore = PublicMethed - .queryAccount(account4DelegatedResourceAddress, blockingStubFull); - //Balance of Account4 before DelegateResource - final long account4BeforeBalance = account4infoBefore.getBalance(); - //account013 DelegateResource of bandwidth to Account4 - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(account013Address, freezeAmount, freezeDuration, 0, - ByteString.copyFrom(account4DelegatedResourceAddress), testKeyForAccount013, - blockingStubFull)); - //Account4 DelegateResource of energy to Account5 - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(account4DelegatedResourceAddress, freezeAmount, freezeDuration, 1, - ByteString.copyFrom(account5DelegatedResourceAddress), account4DelegatedResourceKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //check DelegatedResourceList,from:account013 to:Account4 - Optional delegatedResourceResult1 = PublicMethed - .getDelegatedResource(account013Address, account4DelegatedResourceAddress, - blockingStubFull); - long afterFreezeBandwidth = delegatedResourceResult1.get().getDelegatedResource(0) - .getFrozenBalanceForBandwidth(); - //check DelegatedResourceList,from:Account4 to:Account5 - Optional delegatedResourceResult2 = PublicMethed - .getDelegatedResource(account4DelegatedResourceAddress, account5DelegatedResourceAddress, - blockingStubFull); - long afterFreezeEnergy = delegatedResourceResult2.get().getDelegatedResource(0) - .getFrozenBalanceForEnergy(); - //FrozenBalanceForBandwidth > 0 - Assert.assertTrue(afterFreezeBandwidth > 0); - //FrozenBalanceForEnergy > 0 - Assert.assertTrue(afterFreezeEnergy > 0); - - //check DelegatedResourceAccountIndex for Account4 - Optional delegatedResourceIndexResult1 = PublicMethed - .getDelegatedResourceAccountIndex(account4DelegatedResourceAddress, blockingStubFull); - //result of From list, first Address is same as account013 address - Assert.assertTrue(new String(account013Address) - .equals(new String(delegatedResourceIndexResult1.get().getFromAccounts(0).toByteArray()))); - //result of To list, first Address is same as Account5 address - Assert.assertTrue(new String(account5DelegatedResourceAddress) - .equals(new String(delegatedResourceIndexResult1.get().getToAccounts(0).toByteArray()))); - - //unfreezebalance of bandwidth from Account013 to Account4 - Assert.assertTrue(PublicMethed.unFreezeBalance(account013Address, testKeyForAccount013, 0, - account4DelegatedResourceAddress, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //check DelegatedResourceAccountIndex of Account4 - Optional delegatedResourceIndexResult1AfterUnfreeze = - PublicMethed - .getDelegatedResourceAccountIndex(account4DelegatedResourceAddress, blockingStubFull); - //result of From list is empty - Assert.assertTrue( - delegatedResourceIndexResult1AfterUnfreeze.get().getFromAccountsList().isEmpty()); - Assert.assertFalse( - delegatedResourceIndexResult1AfterUnfreeze.get().getToAccountsList().isEmpty()); - //Balance of Account013 after unfreezeBalance - // (013 -> receiver(bandwidth), 013 -> receiver(Energy), 013 -> Account4(bandwidth)) - Assert.assertTrue(PublicMethed.queryAccount(account013Address, blockingStubFull).getBalance() - == account013BeforeBalance - 2 * freezeAmount); - //bandwidth from Account013 to Account4 gone - Assert.assertTrue( - PublicMethed.getAccountResource(account4DelegatedResourceAddress, blockingStubFull) - .getNetLimit() == 0); - - //unfreezebalance of Energy from Account4 to Account5 - Assert.assertTrue(PublicMethed - .unFreezeBalance(account4DelegatedResourceAddress, account4DelegatedResourceKey, 1, - account5DelegatedResourceAddress, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Protocol.Account account4infoAfterUnfreezeEnergy = PublicMethed - .queryAccount(account4DelegatedResourceAddress, blockingStubFull); - //balance of Account4 after unfreezebalance - long account4BalanceAfterUnfreezeEnergy = account4infoAfterUnfreezeEnergy.getBalance(); - //balance of Account4 is same as before - Assert.assertTrue(account4BeforeBalance == account4BalanceAfterUnfreezeEnergy); - //Energy from Account4 to Account5 gone - Assert.assertTrue( - PublicMethed.getAccountResource(account5DelegatedResourceAddress, blockingStubFull) - .getEnergyLimit() == 0); - - //Unfreezebalance of Bandwidth from Account4 to Account5 fail - Assert.assertFalse(PublicMethed - .unFreezeBalance(account4DelegatedResourceAddress, account4DelegatedResourceKey, 0, - account5DelegatedResourceAddress, blockingStubFull)); - } - - @Test(enabled = true, description = "Prepare delegate resource token") - public void test3PrepareToken() { - //Create Account7 - ECKey ecKey7 = new ECKey(Utils.getRandom()); - accountForAssetIssueAddress = ecKey7.getAddress(); - accountForAssetIssueKey = ByteArray.toHexString(ecKey7.getPrivKeyBytes()); - //sendcoin to Account7 - Assert.assertTrue(PublicMethed - .sendcoin(accountForAssetIssueAddress, 10000000000L, toAddress, testKey003, - blockingStubFull)); - //account013 DelegateResource of bandwidth to accountForAssetIssue - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(account013Address, 1000000000L, freezeDuration, 0, - ByteString.copyFrom(accountForAssetIssueAddress), testKeyForAccount013, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //accountForAssetIssue AssetIssue - long now = System.currentTimeMillis(); - String name = "testAccount013_" + Long.toString(now); - long totalSupply = 100000000000L; - String description = "zfbnb"; - String url = "aaa.com"; - Assert.assertTrue(PublicMethed - .createAssetIssue(accountForAssetIssueAddress, name, totalSupply, 1, 1, - System.currentTimeMillis() + 2000, System.currentTimeMillis() + 1000000000, 1, - description, url, 2000L, 2000L, 500L, 1L, accountForAssetIssueKey, blockingStubFull)); - - } - - @Test(enabled = true, description = "Delegate resource about transfer asset") - public void test4DelegateResourceAboutTransferAsset() { - //Wait for 3s - PublicMethed.waitProduceNextBlock(blockingStubFull); - //get AssetIssue Id - Protocol.Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed - .queryAccount(accountForAssetIssueAddress, blockingStubFull); - ByteString assetAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - //Account5 Participate AssetIssue - Assert.assertTrue(PublicMethed - .participateAssetIssue(accountForAssetIssueAddress, assetAccountId.toByteArray(), 1000000, - account5DelegatedResourceAddress, account5DelegatedResourceKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //get account013,accountForAssetIssue,Account5 account resources before transferAssets - final long account013CurrentBandwidth = PublicMethed - .getAccountResource(account013Address, blockingStubFull).getNetUsed(); - long accountForAssetIssueCurrentBandwidth = PublicMethed - .getAccountResource(accountForAssetIssueAddress, blockingStubFull).getNetUsed(); - final long account5CurrentBandwidth = PublicMethed - .getAccountResource(account5DelegatedResourceAddress, blockingStubFull).getNetUsed(); - //Account5 transfer Assets receiver - Assert.assertTrue(PublicMethed - .transferAsset(receiverDelegateAddress, assetAccountId.toByteArray(), 100000, - account5DelegatedResourceAddress, account5DelegatedResourceKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.printAddress(accountForAssetIssueKey); - PublicMethed.printAddress(account5DelegatedResourceKey); - - //get account013,accountForAssetIssue,Account5 resource after transferAsset - final long account013CurrentBandwidthAfterTrans = PublicMethed - .getAccountResource(account013Address, blockingStubFull).getNetUsed(); - final long accountForAssetIssueCurrentBandwidthAfterTrans = PublicMethed - .getAccountResource(accountForAssetIssueAddress, blockingStubFull).getFreeNetUsed(); - final long account5CurrentBandwidthAfterTrans = PublicMethed - .getAccountResource(account5DelegatedResourceAddress, blockingStubFull).getNetUsed(); - AccountResourceMessage account5ResourceAfterTrans = PublicMethed - .getAccountResource(account5DelegatedResourceAddress, blockingStubFull); - - String result = ""; - if (account5ResourceAfterTrans.getAssetNetLimitCount() > 0) { - logger.info("getAssetNetLimitCount > 0 "); - for (String name1 : account5ResourceAfterTrans.getAssetNetLimitMap().keySet()) { - logger.info(name1); - result += account5ResourceAfterTrans.getAssetNetUsedMap().get(name1); - - } - } - logger.info(result); - PublicMethed.printAddress(receiverDelegateKey); - PublicMethed.printAddress(account5DelegatedResourceKey); - long account5FreeAssetNetUsed = accountForAssetIssueCurrentBandwidthAfterTrans; - - //check resource diff - Assert.assertTrue(Long.parseLong(result) > 0); - Assert.assertTrue(account013CurrentBandwidth == account013CurrentBandwidthAfterTrans); - Assert.assertTrue(account5CurrentBandwidth == account5CurrentBandwidthAfterTrans); - } - - @Test(enabled = true, description = "Can't delegate resource for contract") - public void test5CanNotDelegateResourceToContract() { - //Create Account6 - ECKey ecKey6 = new ECKey(Utils.getRandom()); - accountForDeployAddress = ecKey6.getAddress(); - accountForDeployKey = ByteArray.toHexString(ecKey6.getPrivKeyBytes()); - //PublicMethed.printAddress(accountForDeployKey); - //sendcoin to Account6 - Assert.assertTrue(PublicMethed - .sendcoin(accountForDeployAddress, 10000000000L, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //deploy contract under Account6 - Integer consumeUserResourcePercent = 0; - Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - String contractName = "TestSStore"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_WalletTestAccount013"); - String abi = Configuration.getByPath("testng.conf").getString("abi.abi_WalletTestAccount013"); - - logger.info("TestSStore"); - final byte[] contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, consumeUserResourcePercent, - null, accountForDeployKey, accountForDeployAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Account4 DelegatedResource of Energy to Contract - //After 3.6 can not delegate resource to contract - Assert.assertFalse(PublicMethed - .freezeBalanceForReceiver(account4DelegatedResourceAddress, freezeAmount, freezeDuration, 1, - ByteString.copyFrom(contractAddress), account4DelegatedResourceKey, blockingStubFull)); - } - - - @Test(enabled = true, description = "Get delegate resource from solidity") - public void test6GetDelegateResourceFromSolidity() { - Optional delegateResource = PublicMethed - .getDelegatedResourceFromSolidity(account013Address, receiverDelegateAddress, - blockingStubSolidity); - Assert.assertTrue(delegateResource.get().getDelegatedResource(0) - .getFrozenBalanceForEnergy() == 10000000); - Assert.assertTrue(delegateResource.get().getDelegatedResource(0) - .getFrozenBalanceForBandwidth() == 10000000); - } - - @Test(enabled = true, description = "Get delegate resource from PBFT") - public void test7GetDelegateResourceFromPbft() { - Optional delegateResource = PublicMethed - .getDelegatedResourceFromSolidity(account013Address, receiverDelegateAddress, - blockingStubPbft); - Assert.assertTrue(delegateResource.get().getDelegatedResource(0) - .getFrozenBalanceForEnergy() == 10000000); - Assert.assertTrue(delegateResource.get().getDelegatedResource(0) - .getFrozenBalanceForBandwidth() == 10000000); - } - - @Test(enabled = true, description = "Get delegate resource index from solidity") - public void test8GetDelegateResourceIndexFromSolidity() { - Optional delegateResourceIndex = PublicMethed - .getDelegatedResourceAccountIndexFromSolidity(account013Address, - blockingStubSolidity); - Assert.assertTrue(delegateResourceIndex.get().getToAccountsCount() == 2); - } - - @Test(enabled = true, description = "Get delegate resource index from PBFT") - public void test9GetDelegateResourceIndexFromPbft() { - Optional delegateResourceIndex = PublicMethed - .getDelegatedResourceAccountIndexFromSolidity(account013Address, - blockingStubSolidity); - Assert.assertTrue(delegateResourceIndex.get().getToAccountsCount() == 2); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(account013Address, testKeyForAccount013, - fromAddress, blockingStubFull); - PublicMethed.freedResource(receiverDelegateAddress, receiverDelegateKey, fromAddress, - blockingStubFull); - PublicMethed.freedResource(account4DelegatedResourceAddress, account4DelegatedResourceKey, - fromAddress, blockingStubFull); - PublicMethed.freedResource(account5DelegatedResourceAddress, account5DelegatedResourceKey, - fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelPbft != null) { - channelPbft.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSoliInFull != null) { - channelSoliInFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount014.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount014.java deleted file mode 100644 index fbeb31307cb..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount014.java +++ /dev/null @@ -1,229 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAccount014 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] account014Address = ecKey1.getAddress(); - String account014Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] account014SecondAddress = ecKey2.getAddress(); - String account014SecondKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private ManagedChannel channelSoliInFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSoliInFull = null; - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String soliInFullnode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKey002); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelSoliInFull = ManagedChannelBuilder.forTarget(soliInFullnode) - .usePlaintext() - .build(); - blockingStubSoliInFull = WalletSolidityGrpc.newBlockingStub(channelSoliInFull); - } - - @Test(enabled = true, description = "Query freeNetUsage in 50061") - public void fullAndSoliMerged1ForFreeNetUsage() { - //Create account014 - ecKey1 = new ECKey(Utils.getRandom()); - account014Address = ecKey1.getAddress(); - account014Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ecKey2 = new ECKey(Utils.getRandom()); - account014SecondAddress = ecKey2.getAddress(); - account014SecondKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - PublicMethed.printAddress(account014Key); - PublicMethed.printAddress(account014SecondKey); - Assert.assertTrue(PublicMethed.sendcoin(account014Address, 1000000000L, fromAddress, - testKey002, blockingStubFull)); - - //Test freeNetUsage in fullnode and soliditynode. - Assert.assertTrue(PublicMethed.sendcoin(account014SecondAddress, 5000000L, - account014Address, account014Key, - blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(account014SecondAddress, 5000000L, - account014Address, account014Key, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account account014 = PublicMethed.queryAccount(account014Address, blockingStubFull); - final long freeNetUsageInFullnode = account014.getFreeNetUsage(); - final long createTimeInFullnode = account014.getCreateTime(); - final long lastOperationTimeInFullnode = account014.getLatestOprationTime(); - final long lastCustomeFreeTimeInFullnode = account014.getLatestConsumeFreeTime(); - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSoliInFull); - account014 = PublicMethed.queryAccount(account014Address, blockingStubSoliInFull); - final long freeNetUsageInSoliInFull = account014.getFreeNetUsage(); - final long createTimeInSoliInFull = account014.getCreateTime(); - final long lastOperationTimeInSoliInFull = account014.getLatestOprationTime(); - final long lastCustomeFreeTimeInSoliInFull = account014.getLatestConsumeFreeTime(); - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - account014 = PublicMethed.queryAccount(account014Address, blockingStubSolidity); - final long freeNetUsageInSolidity = account014.getFreeNetUsage(); - final long createTimeInSolidity = account014.getCreateTime(); - final long lastOperationTimeInSolidity = account014.getLatestOprationTime(); - final long lastCustomeFreeTimeInSolidity = account014.getLatestConsumeFreeTime(); - Assert.assertTrue(freeNetUsageInSoliInFull > 0 && freeNetUsageInSolidity > 0 - && freeNetUsageInFullnode > 0); - Assert.assertTrue(freeNetUsageInFullnode <= freeNetUsageInSoliInFull + 5 - && freeNetUsageInFullnode >= freeNetUsageInSoliInFull - 5); - Assert.assertTrue(freeNetUsageInFullnode <= freeNetUsageInSolidity + 5 - && freeNetUsageInFullnode >= freeNetUsageInSolidity - 5); - Assert.assertTrue(createTimeInFullnode == createTimeInSolidity && createTimeInFullnode - == createTimeInSoliInFull); - Assert.assertTrue(createTimeInSoliInFull != 0); - Assert.assertTrue(lastOperationTimeInFullnode == lastOperationTimeInSolidity - && lastOperationTimeInFullnode == lastOperationTimeInSoliInFull); - Assert.assertTrue(lastOperationTimeInSoliInFull != 0); - Assert.assertTrue(lastCustomeFreeTimeInFullnode == lastCustomeFreeTimeInSolidity - && lastCustomeFreeTimeInFullnode == lastCustomeFreeTimeInSoliInFull); - Assert.assertTrue(lastCustomeFreeTimeInSoliInFull != 0); - } - - @Test(enabled = true, description = "Query net usage in 50061") - public void fullAndSoliMerged2ForNetUsage() { - - Assert.assertTrue(PublicMethed.freezeBalance(account014Address, 1000000L, 3, - account014Key, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(account014SecondAddress, 1000000L, - account014Address, account014Key, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(account014Address, 1000000, - 3, 1, account014Key, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(account014Address, 1000000, - 3, 0, ByteString.copyFrom( - account014SecondAddress), account014Key, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(account014Address, 1000000, - 3, 1, ByteString.copyFrom( - account014SecondAddress), account014Key, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(account014SecondAddress, 1000000, - 3, 0, ByteString.copyFrom( - account014Address), account014SecondKey, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(account014SecondAddress, 1000000, - 3, 1, ByteString.copyFrom( - account014Address), account014SecondKey, blockingStubFull)); - - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSoliInFull); - Account account014 = PublicMethed.queryAccount(account014Address, blockingStubFull); - final long lastCustomeTimeInFullnode = account014.getLatestConsumeTime(); - final long netUsageInFullnode = account014.getNetUsage(); - final long acquiredForBandwidthInFullnode = account014 - .getAcquiredDelegatedFrozenBalanceForBandwidth(); - final long delegatedBandwidthInFullnode = account014.getDelegatedFrozenBalanceForBandwidth(); - final long acquiredForEnergyInFullnode = account014 - .getAccountResource().getAcquiredDelegatedFrozenBalanceForEnergy(); - final long delegatedForEnergyInFullnode = account014 - .getAccountResource().getDelegatedFrozenBalanceForEnergy(); - logger.info("delegatedForEnergyInFullnode " + delegatedForEnergyInFullnode); - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSoliInFull); - account014 = PublicMethed.queryAccount(account014Address, blockingStubSoliInFull); - final long lastCustomeTimeInSoliInFull = account014.getLatestConsumeTime(); - logger.info("freeNetUsageInSoliInFull " + lastCustomeTimeInSoliInFull); - final long netUsageInSoliInFull = account014.getNetUsage(); - final long acquiredForBandwidthInSoliInFull = account014 - .getAcquiredDelegatedFrozenBalanceForBandwidth(); - final long delegatedBandwidthInSoliInFull = account014.getDelegatedFrozenBalanceForBandwidth(); - final long acquiredForEnergyInSoliInFull = account014 - .getAccountResource().getAcquiredDelegatedFrozenBalanceForEnergy(); - final long delegatedForEnergyInSoliInFull = account014 - .getAccountResource().getDelegatedFrozenBalanceForEnergy(); - logger.info("delegatedForEnergyInSoliInFull " + delegatedForEnergyInSoliInFull); - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - account014 = PublicMethed.queryAccount(account014Address, blockingStubSolidity); - final long netUsageInSolidity = account014.getNetUsage(); - final long lastCustomeTimeInSolidity = account014.getLatestConsumeTime(); - final long acquiredForBandwidthInSolidity = account014 - .getAcquiredDelegatedFrozenBalanceForBandwidth(); - final long delegatedBandwidthInSolidity = account014.getDelegatedFrozenBalanceForBandwidth(); - final long acquiredForEnergyInSolidity = account014.getAccountResource() - .getAcquiredDelegatedFrozenBalanceForEnergy(); - final long delegatedForEnergyInSolidity = account014.getAccountResource() - .getDelegatedFrozenBalanceForEnergy(); - - logger.info("delegatedForEnergyInSolidity " + delegatedForEnergyInSolidity); - Assert.assertTrue(netUsageInSoliInFull > 0 && netUsageInSolidity > 0 - && netUsageInFullnode > 0); - Assert.assertTrue(netUsageInFullnode <= netUsageInSoliInFull + 5 - && netUsageInFullnode >= netUsageInSoliInFull - 5); - Assert.assertTrue(netUsageInFullnode <= netUsageInSolidity + 5 - && netUsageInFullnode >= netUsageInSolidity - 5); - Assert.assertTrue(acquiredForBandwidthInFullnode == acquiredForBandwidthInSoliInFull - && acquiredForBandwidthInFullnode == acquiredForBandwidthInSolidity); - Assert.assertTrue(delegatedBandwidthInFullnode == delegatedBandwidthInSoliInFull - && delegatedBandwidthInFullnode == delegatedBandwidthInSolidity); - Assert.assertTrue(acquiredForEnergyInFullnode == acquiredForEnergyInSoliInFull - && acquiredForEnergyInFullnode == acquiredForEnergyInSolidity); - Assert.assertTrue(delegatedForEnergyInFullnode == delegatedForEnergyInSoliInFull - && delegatedForEnergyInFullnode == delegatedForEnergyInSolidity); - Assert.assertTrue(acquiredForBandwidthInSoliInFull == 1000000 - && delegatedBandwidthInSoliInFull == 1000000 && acquiredForEnergyInSoliInFull == 1000000 - && delegatedForEnergyInSoliInFull == 1000000); - logger.info("lastCustomeTimeInSoliInFull " + lastCustomeTimeInSoliInFull); - Assert.assertTrue(lastCustomeTimeInFullnode == lastCustomeTimeInSolidity - && lastCustomeTimeInFullnode == lastCustomeTimeInSoliInFull); - logger.info("lastCustomeTimeInSoliInFull " + lastCustomeTimeInSoliInFull); - Assert.assertTrue(lastCustomeTimeInSoliInFull != 0); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(account014Address, account014Key, fromAddress, blockingStubFull); - PublicMethed - .freedResource(account014SecondAddress, account014SecondKey, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount015.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount015.java deleted file mode 100644 index 5d93cfa9bc1..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount015.java +++ /dev/null @@ -1,171 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestAccount015 { - - private static final long now = System.currentTimeMillis(); - private static long amount = 100000000L; - private static String accountId = "accountid_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] account015Address = ecKey1.getAddress(); - String account015Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private ManagedChannel channelSoliInFull = null; - private ManagedChannel channelPbft = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSoliInFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPbft = null; - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String soliInFullnode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - private String soliInPbft = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(2); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKey002); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelSoliInFull = ManagedChannelBuilder.forTarget(soliInFullnode) - .usePlaintext() - .build(); - blockingStubSoliInFull = WalletSolidityGrpc.newBlockingStub(channelSoliInFull); - - channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext() - .build(); - blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); - - Random rand = new Random(); - amount = amount + rand.nextInt(10000); - } - - @Test(enabled = true, description = "Set account id") - public void test01SetAccountId() { - //Create account014 - ecKey1 = new ECKey(Utils.getRandom()); - account015Address = ecKey1.getAddress(); - account015Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - PublicMethed.printAddress(account015Key); - Assert.assertTrue(PublicMethed.sendcoin(account015Address, amount, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue(PublicMethed.setAccountId(accountId.getBytes(), - account015Address, account015Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Get account by id") - public void test02GetAccountById() { - Assert.assertEquals(amount, PublicMethed.getAccountById( - accountId, blockingStubFull).getBalance()); - } - - - @Test(enabled = true, description = "Get account by id from solidity") - public void test03GetAccountByIdFromSolidity() { - Assert.assertEquals(amount, PublicMethed.getAccountByIdFromSolidity( - accountId, blockingStubSoliInFull).getBalance()); - } - - @Test(enabled = true, description = "Get account by id from PBFT") - public void test04GetAccountByIdFromPbft() { - Assert.assertEquals(amount, PublicMethed.getAccountByIdFromSolidity( - accountId, blockingStubPbft).getBalance()); - } - - - @Test(enabled = true, description = "Get account from PBFT") - public void test05GetAccountFromPbft() { - Assert.assertEquals(amount, PublicMethed.queryAccount( - account015Address, blockingStubPbft).getBalance()); - } - - - @Test(enabled = true, description = "List witnesses") - public void test06ListWitness() { - Assert.assertTrue(PublicMethed.listWitnesses(blockingStubFull) - .get().getWitnessesCount() >= 2); - } - - @Test(enabled = true, description = "List witnesses from solidity node") - public void test07ListWitnessFromSolidity() { - Assert.assertTrue(PublicMethed.listWitnessesFromSolidity(blockingStubSolidity) - .get().getWitnessesCount() >= 2); - Assert.assertTrue(PublicMethed.listWitnessesFromSolidity(blockingStubSoliInFull) - .get().getWitnessesCount() >= 2); - } - - @Test(enabled = true, description = "List witnesses from PBFT node") - public void test08ListWitnessFromPbft() { - Assert.assertTrue(PublicMethed.listWitnessesFromSolidity(blockingStubPbft) - .get().getWitnessesCount() >= 2); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(account015Address, account015Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelPbft != null) { - channelPbft.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSoliInFull != null) { - channelSoliInFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestBlock001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestBlock001.java deleted file mode 100644 index a2515b390ba..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestBlock001.java +++ /dev/null @@ -1,177 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; - -@Slf4j -public class WalletTestBlock001 { - - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - /** - * constructor. - */ - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get now block from fullnode") - public void testCurrentBlock() { - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Assert.assertTrue(currentBlock.hasBlockHeader()); - Assert.assertFalse(currentBlock.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertTrue(currentBlock.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(currentBlock.getBlockHeader().getRawData().getWitnessAddress().isEmpty()); - Assert.assertTrue(currentBlock.getBlockHeader().getRawData().getNumber() > 0); - Assert.assertFalse(currentBlock.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(currentBlock.getBlockHeader().getRawData().getWitnessId() >= 0); - logger.info("test getcurrentblock is " + Long.toString(currentBlock.getBlockHeader() - .getRawData().getNumber())); - - //Improve coverage. - currentBlock.equals(currentBlock); - Block newBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - newBlock.equals(currentBlock); - newBlock.hashCode(); - newBlock.getSerializedSize(); - newBlock.getTransactionsCount(); - newBlock.getTransactionsList(); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Get now block from solidity") - public void testCurrentBlockFromSolidity() { - Block currentBlock = blockingStubSolidity - .getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Assert.assertTrue(currentBlock.hasBlockHeader()); - Assert.assertFalse(currentBlock.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertTrue(currentBlock.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(currentBlock.getBlockHeader().getRawData().getWitnessAddress().isEmpty()); - Assert.assertTrue(currentBlock.getBlockHeader().getRawData().getNumber() > 0); - Assert.assertFalse(currentBlock.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(currentBlock.getBlockHeader().getRawData().getWitnessId() >= 0); - logger.info("test getcurrentblock in soliditynode is " + Long.toString(currentBlock - .getBlockHeader().getRawData().getNumber())); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestBlock002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestBlock002.java deleted file mode 100644 index 86e9d5bd382..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestBlock002.java +++ /dev/null @@ -1,381 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestBlock002 { - - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private ManagedChannel channelSoliInFull = null; - private ManagedChannel channelPbft = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSoliInFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPbft = null; - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String soliInFullnode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - private String soliInPbft = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(2); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelSoliInFull = ManagedChannelBuilder.forTarget(soliInFullnode) - .usePlaintext() - .build(); - blockingStubSoliInFull = WalletSolidityGrpc.newBlockingStub(channelSoliInFull); - - channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext() - .build(); - blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "GetBlockByNum from fullnode") - public void test01GetBlockByNum() { - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Assert.assertFalse(currentBlockNum < 0); - if (currentBlockNum == 1) { - logger.info("Now has very little block, Please test this case by manual"); - Assert.assertTrue(currentBlockNum == 1); - } - - //The number is large than the currently number, there is no exception when query this number. - Long outOfCurrentBlockNum = currentBlockNum + 10000L; - NumberMessage.Builder builder1 = NumberMessage.newBuilder(); - builder1.setNum(outOfCurrentBlockNum); - Block outOfCurrentBlock = blockingStubFull.getBlockByNum(builder1.build()); - Assert.assertFalse(outOfCurrentBlock.hasBlockHeader()); - - //Query the first block. - NumberMessage.Builder builder2 = NumberMessage.newBuilder(); - builder2.setNum(1); - Block firstBlock = blockingStubFull.getBlockByNum(builder2.build()); - Assert.assertTrue(firstBlock.hasBlockHeader()); - Assert.assertFalse(firstBlock.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertTrue(firstBlock.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(firstBlock.getBlockHeader().getRawData().getWitnessAddress().isEmpty()); - Assert.assertTrue(firstBlock.getBlockHeader().getRawData().getNumber() == 1); - Assert.assertFalse(firstBlock.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(firstBlock.getBlockHeader().getRawData().getWitnessId() >= 0); - - //Query the second latest block. - NumberMessage.Builder builder3 = NumberMessage.newBuilder(); - builder3.setNum(currentBlockNum - 1); - Block lastSecondBlock = blockingStubFull.getBlockByNum(builder3.build()); - Assert.assertTrue(lastSecondBlock.hasBlockHeader()); - Assert.assertFalse(lastSecondBlock.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertTrue(lastSecondBlock.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(lastSecondBlock.getBlockHeader().getRawData().getWitnessAddress().isEmpty()); - Assert.assertTrue( - lastSecondBlock.getBlockHeader().getRawData().getNumber() + 1 == currentBlockNum); - Assert.assertFalse(lastSecondBlock.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(lastSecondBlock.getBlockHeader().getRawData().getWitnessId() >= 0); - } - - @Test(enabled = true, description = "GetBlockByNum from solidity") - public void test02GetBlockByNumFromSolidity() { - Block currentBlock = blockingStubSolidity - .getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Assert.assertFalse(currentBlockNum < 0); - if (currentBlockNum == 1) { - logger.info("Now has very little block, Please test this case by manual"); - Assert.assertTrue(currentBlockNum == 1); - } - - //The number is large than the currently number, there is no exception when query this number. - Long outOfCurrentBlockNum = currentBlockNum + 10000L; - NumberMessage.Builder builder1 = NumberMessage.newBuilder(); - builder1.setNum(outOfCurrentBlockNum); - Block outOfCurrentBlock = blockingStubSolidity.getBlockByNum(builder1.build()); - Assert.assertFalse(outOfCurrentBlock.hasBlockHeader()); - - //Query the first block. - NumberMessage.Builder builder2 = NumberMessage.newBuilder(); - builder2.setNum(1); - Block firstBlock = blockingStubSolidity.getBlockByNum(builder2.build()); - Assert.assertTrue(firstBlock.hasBlockHeader()); - Assert.assertFalse(firstBlock.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertTrue(firstBlock.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(firstBlock.getBlockHeader().getRawData().getWitnessAddress().isEmpty()); - Assert.assertTrue(firstBlock.getBlockHeader().getRawData().getNumber() == 1); - Assert.assertFalse(firstBlock.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(firstBlock.getBlockHeader().getRawData().getWitnessId() >= 0); - logger.info("firstblock test from solidity succesfully"); - - //Query the second latest block. - NumberMessage.Builder builder3 = NumberMessage.newBuilder(); - builder3.setNum(currentBlockNum - 1); - Block lastSecondBlock = blockingStubSolidity.getBlockByNum(builder3.build()); - Assert.assertTrue(lastSecondBlock.hasBlockHeader()); - Assert.assertFalse(lastSecondBlock.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertTrue(lastSecondBlock.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(lastSecondBlock.getBlockHeader().getRawData().getWitnessAddress().isEmpty()); - Assert.assertTrue( - lastSecondBlock.getBlockHeader().getRawData().getNumber() + 1 == currentBlockNum); - Assert.assertFalse(lastSecondBlock.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(lastSecondBlock.getBlockHeader().getRawData().getWitnessId() >= 0); - logger.info("Last second test from solidity succesfully"); - } - - @Test(enabled = true, description = "Get block by id") - public void test03GetBlockById() { - - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - ByteString currentHash = currentBlock.getBlockHeader().getRawData().getParentHash(); - GrpcAPI.BytesMessage request = GrpcAPI.BytesMessage.newBuilder().setValue(currentHash).build(); - Block setIdOfBlock = blockingStubFull.getBlockById(request); - Assert.assertTrue(setIdOfBlock.hasBlockHeader()); - Assert.assertFalse(setIdOfBlock.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertTrue(setIdOfBlock.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(setIdOfBlock.getBlockHeader().getRawData().getWitnessAddress().isEmpty()); - logger.info(Long.toString(setIdOfBlock.getBlockHeader().getRawData().getNumber())); - logger.info(Long.toString(currentBlock.getBlockHeader().getRawData().getNumber())); - Assert.assertTrue( - setIdOfBlock.getBlockHeader().getRawData().getNumber() + 1 == currentBlock.getBlockHeader() - .getRawData().getNumber()); - Assert.assertFalse(setIdOfBlock.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(setIdOfBlock.getBlockHeader().getRawData().getWitnessId() >= 0); - logger.info("By ID test succesfully"); - } - - - @Test(enabled = true, description = "Get transaction count by block num") - public void test04GetTransactionCountByBlockNum() { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(0); - - Assert.assertTrue(blockingStubFull.getTransactionCountByBlockNum(builder.build()) - .getNum() > 3); - } - - @Test(enabled = true, description = "Get transaction count by block num from solidity") - public void test05GetTransactionCountByBlockNumFromSolidity() { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(0); - - Assert.assertTrue(blockingStubSolidity.getTransactionCountByBlockNum(builder.build()) - .getNum() > 3); - Assert.assertTrue(blockingStubSoliInFull.getTransactionCountByBlockNum(builder.build()) - .getNum() > 3); - } - - @Test(enabled = true, description = "Get transaction count by block num from PBFT") - public void test06GetTransactionCountByBlockNumFromPbft() { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(0); - - Assert.assertTrue(blockingStubPbft.getTransactionCountByBlockNum(builder.build()) - .getNum() > 3); - } - - @Test(enabled = true, description = "Get now block from PBFT") - public void test07GetNowBlockFromPbft() { - Block nowBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long nowBlockNum = nowBlock.getBlockHeader().getRawData().getNumber(); - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubPbft); - Block pbftNowBlock = blockingStubPbft.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long nowPbftBlockNum = pbftNowBlock.getBlockHeader().getRawData().getNumber(); - logger.info("nowBlockNum:" + nowBlockNum + " , nowPbftBlockNum:" + nowPbftBlockNum); - Assert.assertTrue(nowPbftBlockNum >= nowBlockNum); - - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubPbft); - GrpcAPI.BlockExtention pbftNowBlock2 = blockingStubPbft.getNowBlock2(GrpcAPI.EmptyMessage - .newBuilder().build()); - Long nowPbftBlockNum2 = pbftNowBlock2.getBlockHeader().getRawData().getNumber(); - logger.info("nowBlockNum:" + nowBlockNum + " , nowPbftBlockNum2:" + nowPbftBlockNum2); - Assert.assertTrue(nowPbftBlockNum2 >= nowBlockNum); - } - - - @Test(enabled = true, description = "Get block by num from PBFT") - public void test08GetBlockByNumFromPbft() { - Block currentBlock = blockingStubPbft - .getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Assert.assertFalse(currentBlockNum < 0); - if (currentBlockNum == 1) { - logger.info("Now has very little block, Please test this case by manual"); - Assert.assertTrue(currentBlockNum == 1); - } - - //The number is large than the currently number, there is no exception when query this number. - Long outOfCurrentBlockNum = currentBlockNum + 10000L; - NumberMessage.Builder builder1 = NumberMessage.newBuilder(); - builder1.setNum(outOfCurrentBlockNum); - Block outOfCurrentBlock = blockingStubPbft.getBlockByNum(builder1.build()); - Assert.assertFalse(outOfCurrentBlock.hasBlockHeader()); - - //Query the first block. - NumberMessage.Builder builder2 = NumberMessage.newBuilder(); - builder2.setNum(1); - Block firstBlock = blockingStubPbft.getBlockByNum(builder2.build()); - Assert.assertTrue(firstBlock.hasBlockHeader()); - Assert.assertFalse(firstBlock.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertTrue(firstBlock.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(firstBlock.getBlockHeader().getRawData().getWitnessAddress().isEmpty()); - Assert.assertTrue(firstBlock.getBlockHeader().getRawData().getNumber() == 1); - Assert.assertFalse(firstBlock.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(firstBlock.getBlockHeader().getRawData().getWitnessId() >= 0); - logger.info("firstblock test from solidity succesfully"); - - //Query the second latest block. - NumberMessage.Builder builder3 = NumberMessage.newBuilder(); - builder3.setNum(currentBlockNum - 1); - Block lastSecondBlock = blockingStubPbft.getBlockByNum(builder3.build()); - Assert.assertTrue(lastSecondBlock.hasBlockHeader()); - Assert.assertFalse(lastSecondBlock.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertTrue(lastSecondBlock.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(lastSecondBlock.getBlockHeader().getRawData().getWitnessAddress().isEmpty()); - Assert.assertTrue( - lastSecondBlock.getBlockHeader().getRawData().getNumber() + 1 == currentBlockNum); - Assert.assertFalse(lastSecondBlock.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(lastSecondBlock.getBlockHeader().getRawData().getWitnessId() >= 0); - logger.info("Last second test from solidity succesfully"); - - //Query the second latest block getBlockByNum2. - NumberMessage.Builder builder4 = NumberMessage.newBuilder(); - builder4.setNum(currentBlockNum - 1); - GrpcAPI.BlockExtention lastSecondBlock1 = blockingStubPbft.getBlockByNum2(builder4.build()); - Assert.assertTrue(lastSecondBlock1.hasBlockHeader()); - Assert.assertFalse(lastSecondBlock1.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertTrue(lastSecondBlock1.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(lastSecondBlock1.getBlockHeader().getRawData().getWitnessAddress() - .isEmpty()); - Assert.assertTrue( - lastSecondBlock1.getBlockHeader().getRawData().getNumber() + 1 == currentBlockNum); - Assert.assertFalse(lastSecondBlock1.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(lastSecondBlock1.getBlockHeader().getRawData().getWitnessId() >= 0); - logger.info("Last second test from getBlockByNum2 succesfully"); - - } - - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelPbft != null) { - channelPbft.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSoliInFull != null) { - channelSoliInFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - - } - - /** - * constructor. - */ - - public Account queryAccount(String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestMutiSign002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestMutiSign002.java deleted file mode 100644 index a2dc1ee6bf0..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestMutiSign002.java +++ /dev/null @@ -1,459 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.ExchangeList; -import org.tron.api.GrpcAPI.PaginatedMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Exchange; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class WalletTestMutiSign002 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = 1000000001L; - private static String name1 = "exchange001_1_" + Long.toString(now); - private static String name2 = "exchange001_2_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = "just-test"; - String url = "https://github.com/tronprotocol/wallet-cli/"; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] exchange001Address = ecKey1.getAddress(); - String exchange001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] secondExchange001Address = ecKey2.getAddress(); - String secondExchange001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - Long secondTransferAssetToFirstAccountNum = 100000000L; - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey3.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey4.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[3]; - String accountPermissionJson = ""; - Account firstAccount; - ByteString assetAccountId1; - ByteString assetAccountId2; - Optional listExchange; - Optional exchangeIdInfo; - Integer exchangeId = 0; - Integer exchangeRate = 10; - Long firstTokenInitialBalance = 10000L; - Long secondTokenInitialBalance = firstTokenInitialBalance * exchangeRate; - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "MutiSign for create token") - public void test1CreateUsedAsset() { - ecKey1 = new ECKey(Utils.getRandom()); - exchange001Address = ecKey1.getAddress(); - exchange001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - secondExchange001Address = ecKey2.getAddress(); - secondExchange001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - PublicMethed.printAddress(exchange001Key); - PublicMethed.printAddress(secondExchange001Key); - - Assert.assertTrue(PublicMethed.sendcoin(exchange001Address, 10240000000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(secondExchange001Address, 10240000000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(exchange001Address), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long start = System.currentTimeMillis() + 5000L; - Long end = System.currentTimeMillis() + 5000000L; - Assert.assertTrue(PublicMethed.createAssetIssue(exchange001Address, name1, totalSupply, 1, - 1, start, end, 1, description, url, 10000L, 10000L, - 1L, 1L, exchange001Key, blockingStubFull)); - Assert.assertTrue(PublicMethed.createAssetIssue(secondExchange001Address, name2, totalSupply, 1, - 1, start, end, 1, description, url, 10000L, 10000L, - 1L, 1L, secondExchange001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "MutiSign for create exchange") - public void test2CreateExchange() { - ecKey3 = new ECKey(Utils.getRandom()); - manager1Address = ecKey3.getAddress(); - manager1Key = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - - ecKey4 = new ECKey(Utils.getRandom()); - manager2Address = ecKey4.getAddress(); - manager2Key = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - - Long balanceBefore = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - PublicMethed.waitProduceNextBlock(blockingStubFull); - ownerKeyString[0] = exchange001Key; - ownerKeyString[1] = manager1Key; - ownerKeyString[2] = manager2Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":3,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(exchange001Key) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - logger.info(accountPermissionJson); - PublicMethedForMutiSign.accountPermissionUpdate( - accountPermissionJson, exchange001Address, exchange001Key, - blockingStubFull, ownerKeyString); - - listExchange = PublicMethed.getExchangeList(blockingStubFull); - final Integer beforeCreateExchangeNum = listExchange.get().getExchangesCount(); - exchangeId = listExchange.get().getExchangesCount(); - - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - assetAccountId1 = getAssetIdFromThisAccount.getAssetIssuedID(); - - getAssetIdFromThisAccount = PublicMethed - .queryAccount(secondExchange001Address, blockingStubFull); - assetAccountId2 = getAssetIdFromThisAccount.getAssetIssuedID(); - - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long token1BeforeBalance = 0L; - for (String name : firstAccount.getAssetMap().keySet()) { - token1BeforeBalance = firstAccount.getAssetMap().get(name); - } - Assert.assertTrue(PublicMethed.transferAsset(exchange001Address, assetAccountId2.toByteArray(), - secondTransferAssetToFirstAccountNum, secondExchange001Address, - secondExchange001Key, blockingStubFull)); - Long token2BeforeBalance = secondTransferAssetToFirstAccountNum; - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //logger.info("name1 is " + name1); - //logger.info("name2 is " + name2); - //logger.info("first balance is " + Long.toString(token1BeforeBalance)); - //logger.info("second balance is " + token2BeforeBalance.toString()); - //CreateExchange - Assert.assertTrue( - PublicMethedForMutiSign.exchangeCreate( - assetAccountId1.toByteArray(), firstTokenInitialBalance, - assetAccountId2.toByteArray(), secondTokenInitialBalance, exchange001Address, - exchange001Key, blockingStubFull, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - listExchange = PublicMethed.getExchangeList(blockingStubFull); - exchangeId = listExchange.get().getExchangesCount(); - - Long balanceAfter = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - long needCoin = updateAccountPermissionFee + multiSignFee; - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1024_000_000L); - - } - - @Test(enabled = true, description = "List exchange after create exchange by MutiSign") - public void test3ListExchange() { - PublicMethed.waitProduceNextBlock(blockingStubFull); - listExchange = PublicMethed.getExchangeList(blockingStubFull); - for (Integer i = 0; i < listExchange.get().getExchangesCount(); i++) { - Assert.assertFalse(ByteArray.toHexString(listExchange.get().getExchanges(i) - .getCreatorAddress().toByteArray()).isEmpty()); - Assert.assertTrue(listExchange.get().getExchanges(i).getExchangeId() > 0); - Assert.assertFalse(ByteArray.toStr(listExchange.get().getExchanges(i).getFirstTokenId() - .toByteArray()).isEmpty()); - Assert.assertTrue(listExchange.get().getExchanges(i).getFirstTokenBalance() > 0); - } - } - - @Test(enabled = true, description = "Mutisign for inject exchange") - public void test4InjectExchange() { - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - final Long beforeExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - final Long beforeExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - - Long balanceBefore = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long beforeToken1Balance = 0L; - Long beforeToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - logger.info("before token 1 balance is " + Long.toString(beforeToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(beforeToken2Balance)); - Integer injectBalance = 100; - Assert.assertTrue( - PublicMethedForMutiSign.injectExchange( - exchangeId, assetAccountId1.toByteArray(), injectBalance, - exchange001Address, exchange001Key, blockingStubFull, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long afterToken1Balance = 0L; - Long afterToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - afterToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - afterToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - logger.info("before token 1 balance is " + Long.toString(afterToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(afterToken2Balance)); - - Assert.assertTrue(beforeToken1Balance - afterToken1Balance == injectBalance); - Assert.assertTrue(beforeToken2Balance - afterToken2Balance == injectBalance - * exchangeRate); - - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - Long afterExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - Long afterExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - Assert.assertTrue(afterExchangeToken1Balance - beforeExchangeToken1Balance - == injectBalance); - Assert.assertTrue(afterExchangeToken2Balance - beforeExchangeToken2Balance - == injectBalance * exchangeRate); - Long balanceAfter = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - long needCoin = multiSignFee; - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @Test(enabled = true, description = "MutiSign for withdraw exchange") - public void test5WithdrawExchange() { - - Long balanceBefore = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - final Long beforeExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - final Long beforeExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long beforeToken1Balance = 0L; - Long beforeToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - - logger.info("before token 1 balance is " + Long.toString(beforeToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(beforeToken2Balance)); - Integer withdrawNum = 200; - Assert.assertTrue( - PublicMethedForMutiSign.exchangeWithdraw( - exchangeId, assetAccountId1.toByteArray(), withdrawNum, - exchange001Address, exchange001Key, blockingStubFull, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long afterToken1Balance = 0L; - Long afterToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - afterToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - afterToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - - logger.info("before token 1 balance is " + Long.toString(afterToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(afterToken2Balance)); - - Assert.assertTrue(afterToken1Balance - beforeToken1Balance == withdrawNum); - Assert.assertTrue(afterToken2Balance - beforeToken2Balance == withdrawNum - * exchangeRate); - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - Long afterExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - Long afterExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - Assert.assertTrue(afterExchangeToken1Balance - beforeExchangeToken1Balance - == -withdrawNum); - Assert.assertTrue(afterExchangeToken2Balance - beforeExchangeToken2Balance - == -withdrawNum * exchangeRate); - Long balanceAfter = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - long needCoin = multiSignFee; - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - } - - @Test(enabled = true, description = "MutiSign for transaction exchange") - public void test6TransactionExchange() { - Long balanceBefore = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - final Long beforeExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - final Long beforeExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - logger.info("beforeExchangeToken1Balance" + beforeExchangeToken1Balance); - logger.info("beforeExchangeToken2Balance" + beforeExchangeToken2Balance); - - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long beforeToken1Balance = 0L; - Long beforeToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - - logger.info("before token 1 balance is " + Long.toString(beforeToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(beforeToken2Balance)); - Integer transactionNum = 50; - Assert.assertTrue( - PublicMethedForMutiSign - .exchangeTransaction(exchangeId, assetAccountId1.toByteArray(), transactionNum, 1, - exchange001Address, exchange001Key, blockingStubFull, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long afterToken1Balance = 0L; - Long afterToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - afterToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - afterToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - logger.info("before token 1 balance is " + Long.toString(afterToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(afterToken2Balance)); - - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - Long afterExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - Long afterExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - logger.info("afterExchangeToken1Balance" + afterExchangeToken1Balance); - logger.info("afterExchangeToken2Balance" + afterExchangeToken2Balance); - Assert.assertTrue(afterExchangeToken1Balance - beforeExchangeToken1Balance - == beforeToken1Balance - afterToken1Balance); - Assert.assertTrue(afterExchangeToken2Balance - beforeExchangeToken2Balance - == beforeToken2Balance - afterToken2Balance); - - Long balanceAfter = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - long needCoin = multiSignFee; - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - - @Test(enabled = true, description = "GetExchangeListPaginated after " - + "MutiSign exchange kind of transaction") - - public void test7GetExchangeListPaginated() { - PaginatedMessage.Builder pageMessageBuilder = PaginatedMessage.newBuilder(); - pageMessageBuilder.setOffset(0); - pageMessageBuilder.setLimit(100); - ExchangeList exchangeList = blockingStubFull - .getPaginatedExchangeList(pageMessageBuilder.build()); - Assert.assertTrue(exchangeList.getExchangesCount() >= 1); - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - - //Solidity support getExchangeId - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubSolidity); - logger.info("createtime is" + exchangeIdInfo.get().getCreateTime()); - Assert.assertTrue(exchangeIdInfo.get().getCreateTime() > 0); - - //Solidity support listexchange - listExchange = PublicMethed.getExchangeList(blockingStubSolidity); - Assert.assertTrue(listExchange.get().getExchangesCount() > 0); - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, exchange001Address, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .unFreezeBalance(exchange001Address, exchange001Key, 0, fromAddress, blockingStubFull); - PublicMethed.freedResource(exchange001Address, exchange001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(secondExchange001Address, secondExchange001Key, fromAddress, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestNode001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestNode001.java deleted file mode 100644 index 8fe5bf28f15..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestNode001.java +++ /dev/null @@ -1,106 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestNode001 { - - private ManagedChannel channelFull = null; - private ManagedChannel channelFull1 = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - } - - - @Test(enabled = true, description = "List all nodes") - public void testGetAllNode() { - GrpcAPI.NodeList nodeList = blockingStubFull - .listNodes(GrpcAPI.EmptyMessage.newBuilder().build()); - GrpcAPI.NodeList nodeList1 = blockingStubFull1 - .listNodes(GrpcAPI.EmptyMessage.newBuilder().build()); - Integer times = 0; - while (nodeList.getNodesCount() == 0 && times++ < 5) { - nodeList = blockingStubFull - .listNodes(GrpcAPI.EmptyMessage.newBuilder().build()); - nodeList1 = blockingStubFull1 - .listNodes(GrpcAPI.EmptyMessage.newBuilder().build()); - if (nodeList.getNodesCount() != 0 || nodeList1.getNodesCount() != 0) { - break; - } - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - //Assert.assertTrue(nodeList.getNodesCount() != 0 || nodeList1.getNodesCount() != 0); - - for (Integer j = 0; j < nodeList.getNodesCount(); j++) { - //Assert.assertTrue(nodeList.getNodes(j).hasAddress()); - //Assert.assertFalse(nodeList.getNodes(j).getAddress().getHost().isEmpty()); - //Assert.assertTrue(nodeList.getNodes(j).getAddress().getPort() < 65535); - //logger.info(ByteArray.toStr(nodeList.getNodes(j).getAddress().getHost().toByteArray())); - } - logger.info("get listnode succesuflly"); - - //Improve coverage. - GrpcAPI.NodeList newNodeList = blockingStubFull - .listNodes(GrpcAPI.EmptyMessage.newBuilder().build()); - nodeList.equals(nodeList); - nodeList.equals(newNodeList); - nodeList.getNodesList(); - nodeList.hashCode(); - nodeList.isInitialized(); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer002.java deleted file mode 100644 index a7cfc9d0f8a..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer002.java +++ /dev/null @@ -1,208 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletExtensionGrpc; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.BalanceContract.TransferContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class WalletTestTransfer002 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletExtensionGrpc.WalletExtensionBlockingStub blockingStubExtension = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - blockingStubExtension = WalletExtensionGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false) - public void testGetTotalTransaction() { - NumberMessage beforeGetTotalTransaction = blockingStubFull - .totalTransaction(GrpcAPI.EmptyMessage.newBuilder().build()); - logger.info(Long.toString(beforeGetTotalTransaction.getNum())); - Long beforeTotalTransaction = beforeGetTotalTransaction.getNum(); - Assert.assertTrue(PublicMethed.sendcoin(toAddress, 1000000, fromAddress, - testKey002, blockingStubFull)); - NumberMessage afterGetTotalTransaction = blockingStubFull - .totalTransaction(GrpcAPI.EmptyMessage.newBuilder().build()); - logger.info(Long.toString(afterGetTotalTransaction.getNum())); - Long afterTotalTransaction = afterGetTotalTransaction.getNum(); - Assert.assertTrue(afterTotalTransaction - beforeTotalTransaction > 0); - - //Improve coverage. - afterGetTotalTransaction.equals(beforeGetTotalTransaction); - afterGetTotalTransaction.equals(afterGetTotalTransaction); - afterGetTotalTransaction.hashCode(); - afterGetTotalTransaction.isInitialized(); - afterGetTotalTransaction.getSerializedSize(); - afterGetTotalTransaction.getDefaultInstanceForType(); - afterGetTotalTransaction.getParserForType(); - afterGetTotalTransaction.getUnknownFields(); - - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(toAddress, testKey003, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean sendcoin(byte[] to, long amount, byte[] owner, String priKey) { - - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account search = queryAccount(ecKey, blockingStubFull); - - TransferContract.Builder builder = TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferContract contract = builder.build(); - Transaction transaction = blockingStubFull.createTransaction(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - return response.getResult(); - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer005.java deleted file mode 100644 index f6465143cc5..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer005.java +++ /dev/null @@ -1,227 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AccountPaginated; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletExtensionGrpc; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - - -@Slf4j -public class WalletTestTransfer005 { - - private static final byte[] INVAILD_ADDRESS = - Base58.decodeFromBase58Check("27cu1ozb4mX3m2afY68FSAqn3HmMp815d48"); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletExtensionGrpc.WalletExtensionBlockingStub blockingStubExtension = null; - - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - blockingStubExtension = WalletExtensionGrpc.newBlockingStub(channelSolidity); - - - } - - @Test(enabled = false) - public void testgetTransactionsFromThis() { - //Create a transfer. - //Assert.assertTrue(PublicMethed.sendcoin(toAddress,1000000,fromAddress, - // testKey002,blockingStubFull)); - - ByteString addressBs = ByteString.copyFrom(fromAddress); - Account account = Account.newBuilder().setAddress(addressBs).build(); - AccountPaginated.Builder accountPaginated = AccountPaginated.newBuilder().setAccount(account); - accountPaginated.setOffset(1000); - accountPaginated.setLimit(0); - GrpcAPI.TransactionList transactionList = blockingStubExtension - .getTransactionsFromThis(accountPaginated.build()); - Optional gettransactionsfromthis = Optional - .ofNullable(transactionList); - - if (gettransactionsfromthis.get().getTransactionCount() == 0) { - Assert.assertTrue(PublicMethed.sendcoin(toAddress, 1000000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, - blockingStubSolidity)); - } - - Assert.assertTrue(gettransactionsfromthis.isPresent()); - Integer beforecount = gettransactionsfromthis.get().getTransactionCount(); - logger.info(Integer.toString(beforecount)); - for (Integer j = 0; j < beforecount; j++) { - Assert.assertFalse(gettransactionsfromthis.get().getTransaction(j) - .getRawData().getContractList().isEmpty()); - } - } - - @Test(enabled = false) - public void testgetTransactionsFromThisByInvaildAddress() { - //Invaild address. - ByteString addressBs = ByteString.copyFrom(INVAILD_ADDRESS); - Account account = Account.newBuilder().setAddress(addressBs).build(); - AccountPaginated.Builder accountPaginated = AccountPaginated.newBuilder().setAccount(account); - accountPaginated.setOffset(1000); - accountPaginated.setLimit(0); - GrpcAPI.TransactionList transactionList = blockingStubExtension - .getTransactionsFromThis(accountPaginated.build()); - Optional gettransactionsfromthisByInvaildAddress = Optional - .ofNullable(transactionList); - - Assert.assertTrue(gettransactionsfromthisByInvaildAddress.get().getTransactionCount() == 0); - - //Limit is -1 - addressBs = ByteString.copyFrom(INVAILD_ADDRESS); - account = Account.newBuilder().setAddress(addressBs).build(); - accountPaginated = AccountPaginated.newBuilder().setAccount(account); - accountPaginated.setOffset(1000); - accountPaginated.setLimit(-1); - transactionList = blockingStubExtension - .getTransactionsFromThis(accountPaginated.build()); - gettransactionsfromthisByInvaildAddress = Optional - .ofNullable(transactionList); - - Assert.assertTrue(gettransactionsfromthisByInvaildAddress.get().getTransactionCount() == 0); - - //offset is -1 - addressBs = ByteString.copyFrom(INVAILD_ADDRESS); - account = Account.newBuilder().setAddress(addressBs).build(); - accountPaginated = AccountPaginated.newBuilder().setAccount(account); - accountPaginated.setOffset(-1); - accountPaginated.setLimit(100); - transactionList = blockingStubExtension - .getTransactionsFromThis(accountPaginated.build()); - gettransactionsfromthisByInvaildAddress = Optional - .ofNullable(transactionList); - - Assert.assertTrue(gettransactionsfromthisByInvaildAddress.get().getTransactionCount() == 0); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(toAddress, testKey003, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer006.java deleted file mode 100644 index ec741fd0889..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestTransfer006.java +++ /dev/null @@ -1,229 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AccountPaginated; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletExtensionGrpc; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - - -@Slf4j -public class WalletTestTransfer006 { - - private static final byte[] INVAILD_ADDRESS = - Base58.decodeFromBase58Check("27cu1ozb4mX3m2afY68FSAqn3HmMp815d48"); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletExtensionGrpc.WalletExtensionBlockingStub blockingStubExtension = null; - - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - blockingStubExtension = WalletExtensionGrpc.newBlockingStub(channelSolidity); - - - } - - @Test(enabled = false) - public void testgetTransactionsToThis() { - //Create a transfer. - Assert.assertTrue(PublicMethed.sendcoin(toAddress, 1000000, fromAddress, - testKey002, blockingStubFull)); - - ByteString addressBs = ByteString.copyFrom(toAddress); - Account account = Account.newBuilder().setAddress(addressBs).build(); - AccountPaginated.Builder accountPaginated = AccountPaginated.newBuilder().setAccount(account); - accountPaginated.setOffset(1000); - accountPaginated.setLimit(0); - GrpcAPI.TransactionList transactionList = blockingStubExtension - .getTransactionsToThis(accountPaginated.build()); - - Optional gettransactionstothis = Optional - .ofNullable(transactionList); - - if (gettransactionstothis.get().getTransactionCount() == 0) { - Assert.assertTrue(PublicMethed.sendcoin(toAddress, 1000000L, fromAddress, testKey002, - blockingStubFull)); - Assert.assertTrue(PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, - blockingStubSolidity)); - //logger.info("This account didn't transfation any coin to other"); - } - - Assert.assertTrue(gettransactionstothis.isPresent()); - Integer beforecount = gettransactionstothis.get().getTransactionCount(); - logger.info(Integer.toString(beforecount)); - for (Integer j = 0; j < beforecount; j++) { - Assert.assertFalse(gettransactionstothis.get().getTransaction(j) - .getRawData().getContractList().isEmpty()); - } - } - - @Test(enabled = false) - public void testgetTransactionsToThisByInvaildAddress() { - //Invaild address. - ByteString addressBs = ByteString.copyFrom(INVAILD_ADDRESS); - Account account = Account.newBuilder().setAddress(addressBs).build(); - AccountPaginated.Builder accountPaginated = AccountPaginated.newBuilder().setAccount(account); - accountPaginated.setOffset(1000); - accountPaginated.setLimit(0); - GrpcAPI.TransactionList transactionList = blockingStubExtension - .getTransactionsToThis(accountPaginated.build()); - Optional gettransactionstothisByInvaildAddress = Optional - .ofNullable(transactionList); - - Assert.assertTrue(gettransactionstothisByInvaildAddress.get().getTransactionCount() == 0); - - //Limit is -1 - addressBs = ByteString.copyFrom(INVAILD_ADDRESS); - account = Account.newBuilder().setAddress(addressBs).build(); - accountPaginated = AccountPaginated.newBuilder().setAccount(account); - accountPaginated.setOffset(1000); - accountPaginated.setLimit(-1); - transactionList = blockingStubExtension - .getTransactionsToThis(accountPaginated.build()); - gettransactionstothisByInvaildAddress = Optional - .ofNullable(transactionList); - - Assert.assertTrue(gettransactionstothisByInvaildAddress.get().getTransactionCount() == 0); - - //offset is -1 - addressBs = ByteString.copyFrom(INVAILD_ADDRESS); - account = Account.newBuilder().setAddress(addressBs).build(); - accountPaginated = AccountPaginated.newBuilder().setAccount(account); - accountPaginated.setOffset(-1); - accountPaginated.setLimit(100); - transactionList = blockingStubExtension - .getTransactionsToThis(accountPaginated.build()); - gettransactionstothisByInvaildAddress = Optional - .ofNullable(transactionList); - - Assert.assertTrue(gettransactionstothisByInvaildAddress.get().getTransactionCount() == 0); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(toAddress, testKey003, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestWitness003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestWitness003.java deleted file mode 100644 index 4c287b78df9..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestWitness003.java +++ /dev/null @@ -1,326 +0,0 @@ -package stest.tron.wallet.dailybuild.manual; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.WitnessList; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.contract.BalanceContract.TransferContract; -import org.tron.protos.contract.WitnessContract.WitnessCreateContract; -import org.tron.protos.contract.WitnessContract.WitnessUpdateContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -//import stest.tron.wallet.common.client.AccountComparator; - -@Slf4j -public class WalletTestWitness003 { - - private static final byte[] INVAILD_ADDRESS = Base58 - .decodeFromBase58Check("27cu1ozb4mX3m2afY68FSAqn3HmMp815d48"); - private static final Long costForCreateWitness = 9999000000L; - private static final String tooLongUrl = "qagwqaswqaswqaswqaswqaswqaswqaswqaswqaswqaswqas" - + "wqaswqasw1qazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazx" - + "swedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedc" - + "vqazxswedcvqazxswedcvqazxswedcvqazxswedcv"; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - private final String testUpdateWitnessKey = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] updateAddress = PublicMethed.getFinalAddress(testUpdateWitnessKey); - String createWitnessUrl = "http://www.createwitnessurl.com/"; - String updateWitnessUrl = "http://www.updatewitnessurl.com/"; - String nullUrl = ""; - String spaceUrl = " ##################~!@#$%^&*()_+}{|:'/.,<>?|]=-"; - byte[] createUrl = createWitnessUrl.getBytes(); - byte[] updateUrl = updateWitnessUrl.getBytes(); - byte[] wrongUrl = nullUrl.getBytes(); - byte[] updateSpaceUrl = spaceUrl.getBytes(); - //get account - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] lowBalAddress = ecKey.getAddress(); - String lowBalTest = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - logger.info(lowBalTest); - logger.info(ByteArray.toHexString(PublicMethed.getFinalAddress(lowBalTest))); - logger.info(Base58.encode58Check(PublicMethed.getFinalAddress(lowBalTest))); - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Invaild account to apply create witness") - public void testInvaildToApplyBecomeWitness() { - Assert.assertFalse(createWitnessNotBroadcast(INVAILD_ADDRESS, createUrl, testKey002)); - } - - @Test(enabled = true, description = "Create witness") - public void testCreateWitness() { - //If you are already is witness, apply failed - //createWitness(fromAddress, createUrl, testKey002); - //Assert.assertFalse(createWitness(fromAddress, createUrl, testKey002)); - - //No balance,try to create witness. - Assert.assertFalse(createWitnessNotBroadcast(lowBalAddress, createUrl, lowBalTest)); - - //Send enough coin to the apply account to make that account - // has ability to apply become witness. - GrpcAPI.WitnessList witnesslist = blockingStubFull - .listWitnesses(GrpcAPI.EmptyMessage.newBuilder().build()); - Optional result = Optional.ofNullable(witnesslist); - GrpcAPI.WitnessList witnessList = result.get(); - if (result.get().getWitnessesCount() < 6) { - Assert.assertTrue(PublicMethed - .sendcoin(lowBalAddress, costForCreateWitness, fromAddress, testKey002, - blockingStubFull)); - //null url, update failed - Assert.assertFalse(createWitnessNotBroadcast(lowBalAddress, wrongUrl, testUpdateWitnessKey)); - //too long url, update failed - Assert.assertFalse(createWitnessNotBroadcast(lowBalAddress, - tooLongUrl.getBytes(), testUpdateWitnessKey)); - Assert.assertTrue(createWitnessNotBroadcast(lowBalAddress, createUrl, lowBalTest)); - - } - } - - @Test(enabled = true, description = "Update witness") - public void testUpdateWitness() { - GrpcAPI.WitnessList witnesslist = blockingStubFull - .listWitnesses(GrpcAPI.EmptyMessage.newBuilder().build()); - Optional result = Optional.ofNullable(witnesslist); - GrpcAPI.WitnessList witnessList = result.get(); - if (result.get().getWitnessesCount() < 6) { - //null url, update failed - Assert.assertFalse(updateWitness(updateAddress, wrongUrl, testUpdateWitnessKey)); - //too long url, update failed - Assert.assertFalse(updateWitness(updateAddress, tooLongUrl.getBytes(), testUpdateWitnessKey)); - //Content space and special char, update success - Assert.assertTrue(updateWitness(updateAddress, updateSpaceUrl, testUpdateWitnessKey)); - //update success - Assert.assertTrue(updateWitness(updateAddress, updateUrl, testUpdateWitnessKey)); - } else { - logger.info("Update witness case had been test.This time skip it."); - } - - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean createWitnessNotBroadcast(byte[] owner, byte[] url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - WitnessCreateContract.Builder builder = WitnessCreateContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setUrl(ByteString.copyFrom(url)); - WitnessCreateContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createWitness(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - return true; - } - - /** - * constructor. - */ - - public Boolean updateWitness(byte[] owner, byte[] url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - WitnessUpdateContract.Builder builder = WitnessUpdateContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setUpdateUrl(ByteString.copyFrom(url)); - WitnessUpdateContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.updateWitness(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = PublicMethed.broadcastTransaction(transaction, blockingStubFull); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - logger.info("response.getRestult() == false"); - return false; - } else { - return true; - } - - } - - /** - * constructor. - */ - - public Boolean sendcoin(byte[] to, long amount, byte[] owner, String priKey) { - - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferContract.Builder builder = TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createTransaction(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public Account queryAccount(String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Protocol.Transaction signTransaction(ECKey ecKey, Protocol.Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign01.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign01.java deleted file mode 100644 index 2c1edea5b06..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign01.java +++ /dev/null @@ -1,894 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign01 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Owner permission_name is owner") - public void testOwnerName01() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2 + multiSignFee; - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - - ownerPermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - ownerPermissionKeys.add(witnessKey001); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @Test(enabled = true, description = "Owner permission_name is owner1") - public void testOwnerName02() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - final byte[] ownerAddress = ecKey1.getAddress(); - final String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2; - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = "{\"owner_permission\":{\"type\":0," - + "\"permission_name\":\"owner1\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - } - - @Test(enabled = true, description = "Owner permission_name is string \"123\"") - public void testOwnerName03() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"123\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - } - - @Test(enabled = true, description = "Owner permission_name is string \"\"") - public void testOwnerName04() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2; - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @Test(enabled = true, description = "Owner permission_name is null") - public void testOwnerName05() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, 1_000000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - // null - String accountPermissionJson = "{\"owner_permission\":{\"type\":0,\"permission_name\":" + null - + ",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"" - + "keys\":[{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - boolean ret = false; - try { - PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("Expected NullPointerException!"); - ret = true; - } - Assert.assertTrue(ret); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore, balanceAfter); - - } - - @Test(enabled = true, description = "Owner without permission_name") - public void testOwnerName06() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @Test(enabled = true, description = "Owner permission_name is numbers") - public void testOwnerName07() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2; - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":123,\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - } - - @Test(enabled = true, description = "Owner permission_name is 0.1") - public void testOwnerName08() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1000000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"0.1\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - } - - @Test(enabled = true, description = "Owner permission_name length is 32") - public void testOwnerName09() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1000000, fromAddress, - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0," - + "\"permission_name\":\"abcdefghijklmnopqrstuvwxyzabcdef\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - } - - - @Test(enabled = true, description = "Owner permission_name length is 33") - public void testOwnerName10() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, 1000000, fromAddress, - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0," - + "\"permission_name\":\"abcdefghijklmnopqrstuvwxyzabcdefg\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's name is too long", - response.getMessage().toStringUtf8()); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore, balanceAfter); - - } - - @Test(enabled = true, description = "Owner permission_name contains special char") - public void testOwnerName11() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1000000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"0&^%\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0&^%%09\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - logger.info("1111___" + PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getOwnerPermission().toString()); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("22222___" + PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getOwnerPermission().toString()); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign02.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign02.java deleted file mode 100644 index 63623df347b..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign02.java +++ /dev/null @@ -1,719 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign02 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Owner threshold in exception condition") - public void testOwnerThreshold01() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - ownerPermissionKeys.add(ownerKey); - - // threshold = Integer.MIN_VALUE - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":-2147483648," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's" - + " threshold should be greater than 0", - response.getMessage().toStringUtf8()); - - // threshold = 0 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":0," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's" - + " threshold should be greater than 0", - response.getMessage().toStringUtf8()); - - // threshold = -1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":-1," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's" - + " threshold should be greater than 0", - response.getMessage().toStringUtf8()); - - // threshold = long.min - logger.info("** update owner and active permission to two address"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\"," - + "\"threshold\":-9223372036854775808,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's" - + " threshold should be greater than 0", - response.getMessage().toStringUtf8()); - - // threshold = long.min - 1000020 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\"," - + "\"threshold\":-9223372036855775828,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - boolean ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // threshold = long.min - 1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\"," - + "\"threshold\":-9223372036854775809,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":2}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // threshold = "12a" - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\"," - + "\"threshold\":\"12a\",\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // threshold = "" - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\"," - + "\"threshold\":\"\",\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // theshold = - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\"," - + "\"threshold\":,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (com.alibaba.fastjson.JSONException e) { - logger.info("JSONException !"); - ret = true; - } - Assert.assertTrue(ret); - - // theshold = null - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\"," - + "\"threshold\":" + null + ",\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // theshold = 1.1 - accountPermissionJson = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\"," - + "\"threshold\": 1.1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // theshold = Long.MAX_VALUE < sum(weight) - accountPermissionJson = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\"," - + "\"threshold\": 9223372036854775807,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2147483647}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":9223372036854775807}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : long overflow", - response.getMessage().toStringUtf8()); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore, balanceAfter); - } - - @Test(enabled = true, description = "Owner threshold is 1") - public void testOwnerThreshold02() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2; - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\"," - + "\"threshold\": 1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @Test(enabled = true, description = "Owner threshold is more than sum of keys' weight") - public void testOwnerThreshold03() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - // theshold = Long.MAX_VALUE > sum(weight) - String accountPermissionJson = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\"," - + "\"threshold\": 9223372036854775807,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":214748364}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":214748364}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : sum of all key's weight should not" - + " be less than threshold in permission Owner", - response.getMessage().toStringUtf8()); - - // theshold = Integer.MAX_VALUE > sum(weight) - accountPermissionJson = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\"," - + "\"threshold\": 2147483647,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":214748364}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":214748364}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : sum of all key's weight " - + "should not be less than threshold in permission Owner", - response.getMessage().toStringUtf8()); - - // theshold = Long.MAX_VALUE + 1 > sum(weight) - accountPermissionJson = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\"," - + "\"threshold\": 9223372036854775808,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":9223372036854775806}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - boolean ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore, balanceAfter); - } - - @Test(enabled = true, description = "Owner threshold is Long.MAX_VALUE and equal sum(weight)") - public void testOwnerThreshold04() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2 + multiSignFee; - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\"," - + "\"threshold\": 9223372036854775807,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":9223372036854775806}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @Test(enabled = true, description = "Owner threshold is Integer.MAX_VALUE") - public void testOwnerThreshold05() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2; - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\"," - + "\"threshold\": 2147483647,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2147483647}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2147483647}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(tmpKey02); - ownerPermissionKeys.add(witnessKey001); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(3, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign03.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign03.java deleted file mode 100644 index ec70ac4b8a4..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign03.java +++ /dev/null @@ -1,541 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign03 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull); - } - - @Test(enabled = true, description = "Owner doesn't have parent_id") - public void testOwnerParent01() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @Test(enabled = true, description = "Owner parent_id in exception condition") - public void testOwnerParent02() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - // parent_id = "123" - String accountPermissionJson = - "{\"owner_permission\":{\"parent_id\":\"123\",\"type\":0," - + "\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = "abc" - accountPermissionJson = - "{\"owner_permission\":{\"parent_id\":\"abc\",\"type\":0," - + "\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - boolean ret = false; - try { - PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("Expected NumberFormatException!"); - ret = true; - } - Assert.assertTrue(ret); - - // parent_id = "" - accountPermissionJson = - "{\"owner_permission\":{\"parent_id\":\"\",\"type\":0," - + "\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("Expected NullPointerException!"); - ret = true; - } - Assert.assertTrue(ret); - - // parent_id = null - - accountPermissionJson = - "{\"owner_permission\":{\"parent_id\":" + null + ",\"type\":0," - + "\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("Expected NullPointerException!"); - ret = true; - } - Assert.assertTrue(ret); - - // parent_id = 1 - accountPermissionJson = - "{\"owner_permission\":{\"parent_id\":1,\"type\":0," - + "\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = 2 - accountPermissionJson = - "{\"owner_permission\":{\"parent_id\":2,\"type\":0," - + "\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = 3 - accountPermissionJson = - "{\"owner_permission\":{\"parent_id\":3,\"type\":0," - + "\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = -1 - accountPermissionJson = - "{\"owner_permission\":{\"parent_id\":3,\"type\":0," - + "\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = Integer.MAX_VALUE - accountPermissionJson = - "{\"owner_permission\":{\"parent_id\":2147483647,\"type\":0," - + "\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = Integer.MAX_VALUE +1 - accountPermissionJson = - "{\"owner_permission\":{\"parent_id\":2147483648,\"type\":0," - + "\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = Integer.MIN_VALUE - accountPermissionJson = - "{\"owner_permission\":{\"parent_id\":-2147483648,\"type\":0," - + "\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = Integer.MIN_VALUE -1 - accountPermissionJson = - "{\"owner_permission\":{\"parent_id\":-2147483649,\"type\":0," - + "\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore, balanceAfter); - } - - @Test(enabled = true, description = "Owner parent_id is 0") - public void testOwnerParent03() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"parent_id\":0,\"type\":0," - + "\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign04.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign04.java deleted file mode 100644 index ca7a80ab15e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign04.java +++ /dev/null @@ -1,550 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign04 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull); - } - - @Test(enabled = true, description = "Owner weight in exception condition") - public void testOwnerWeight01() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - - // weight = Integer.MIN_VALUE - String accountPermissionJson = "{\"owner_permission\":{\"type\":0," - + ",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":-2147483647}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : key's weight" - + " should be greater than 0", - response.getMessage().toStringUtf8()); - - // weight = 0 - accountPermissionJson = "{\"owner_permission\":{\"type\":0," - + ",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":0}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":0}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : key's weight" - + " should be greater than 0", - response.getMessage().toStringUtf8()); - - // weight = -1 - accountPermissionJson = "{\"owner_permission\":{\"type\":0," - + ",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":-1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : key's weight" - + " should be greater than 0", - response.getMessage().toStringUtf8()); - - // weight = long.min - accountPermissionJson = "{\"owner_permission\":{\"type\":0," - + ",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":-9223372036854775808}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : key's weight" - + " should be greater than 0", - response.getMessage().toStringUtf8()); - - // weight = long.min - 1000020 - accountPermissionJson = "{\"owner_permission\":{\"type\":0," - + ",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":-9223372036855775828}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - boolean ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // weight = "12a" - accountPermissionJson = "{\"owner_permission\":{\"type\":0," - + ",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":\"12a\"}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // weight = "" - accountPermissionJson = "{\"owner_permission\":{\"type\":0," - + ",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":\"\"}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // weight = - accountPermissionJson = "{\"owner_permission\":{\"type\":0," - + ",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (com.alibaba.fastjson.JSONException e) { - logger.info("JSONException !"); - ret = true; - } - Assert.assertTrue(ret); - - // weight = null - accountPermissionJson = "{\"owner_permission\":{\"type\":0," - + ",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":" + null + "}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // sum(weight) > Long.MAX_VALUE - accountPermissionJson = "{\"owner_permission\":{\"type\":0," - + ",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":9223372036854775807}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : long overflow", - response.getMessage().toStringUtf8()); - - // weight = 1.1 - accountPermissionJson = "{\"owner_permission\":{\"type\":0," - + ",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1.1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore, balanceAfter); - - } - - @Test(enabled = true, description = "Owner weight is 1") - public void testOwnerWeight02() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = "{\"owner_permission\":{\"type\":0," - + ",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - - - @Test(enabled = true, description = "Owner weight is Long.MAX_VALUE") - public void testOwnerWeight04() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = "{\"owner_permission\":{\"type\":0," - + ",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":9223372036854775807}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign05.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign05.java deleted file mode 100644 index 5f60c562b21..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign05.java +++ /dev/null @@ -1,746 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign05 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - private final String contractTronDiceAddr = "TMYcx6eoRXnePKT1jVn25ZNeMNJ6828HWk"; - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull); - } - - @Test(enabled = true, description = "Owner key-address is witness account") - public void testOwnerKeyAddress01() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2 + multiSignFee; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(witnessKey001); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - - @Test(enabled = true, description = "Owner key-address is contract address") - public void testOwnerKeyAddress02() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + contractTronDiceAddr + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @Test(enabled = true, description = "Owner key-address is inactive address") - public void testOwnerKeyAddress03() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2 + multiSignFee; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(tmpKey01); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @Test(enabled = true, description = "Owner key-address is owner address") - public void testOwnerKeyAddress04() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - } - - @Test(enabled = true, description = "Owner key-address in exception condition") - public void testOwnerKeyAddress05() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - // address = owner_address more than once - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : address should be distinct " - + "in permission Owner", - response.getMessage().toStringUtf8()); - - // address = not exist - String fakeAddress = "THph9K2M2nLvkianrMGswRhz5hjSA9fuH1"; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + fakeAddress + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - boolean ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException !"); - ret = true; - } - Assert.assertTrue(ret); - - // address = long address - fakeAddress = "TR3FAbhiSeP7kSh39RjGYpwCqfMDHPMhX4d121"; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + fakeAddress + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException !"); - ret = true; - } - Assert.assertTrue(ret); - - // address = short address - fakeAddress = "THph9K2M2nLvkianrMGswRhz5hj"; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + fakeAddress + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException !"); - ret = true; - } - Assert.assertTrue(ret); - - // address = - fakeAddress = ""; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":5,\"keys\":[" - + "{\"address\":\"" + fakeAddress + "\",\"weight\":5}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException!"); - ret = true; - } - - Assert.assertTrue(ret); - - // address = null - - fakeAddress = null; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":5,\"keys\":[" - + "{\"address\":\"" + fakeAddress - + "\",\"weight\":5}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, fakeAddress.getBytes(), ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException!"); - ret = true; - } - - Assert.assertTrue(ret); - - // address = "1.1" - fakeAddress = "1.1"; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":5,\"keys\":[" - + "{\"address\":\"" + fakeAddress - + "\",\"weight\":5}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (IllegalArgumentException e) { - logger.info("IllegalArgumentException!"); - ret = true; - } - - Assert.assertTrue(ret); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore, balanceAfter); - - } - - @Test(enabled = true, description = "Owner key-address count is 5") - public void testOwnerKeyAddress06() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2 + multiSignFee; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":5,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(5, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - ownerPermissionKeys.add(testKey002); - ownerPermissionKeys.add(witnessKey001); - ownerPermissionKeys.add(tmpKey01); - ownerPermissionKeys.add(tmpKey02); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @Test(enabled = true, description = "Owner key-address count in exception condition") - public void testOwnerKeyAddress07() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - // address count = 6 - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":5,\"keys\":[" - + "{\"address\":\"" + contractTronDiceAddr + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : number of keys in permission should" - + " not be greater than 5", - response.getMessage().toStringUtf8()); - - // address count = 0 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":5," - + "\"keys\":[]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : key's count should be greater than 0", - response.getMessage().toStringUtf8()); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - } - - - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign06.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign06.java deleted file mode 100644 index 6ef136a70e9..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign06.java +++ /dev/null @@ -1,689 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign06 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Owner type in exception condition") - public void testOwnerType01() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - final byte[] ownerAddress = ecKey1.getAddress(); - final String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - // type = 1 - String accountPermissionJson = - "{\"owner_permission\":{\"type\":1,\"permission_name\":\"owner\",\"threshold\":1," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : owner permission type is error", - response.getMessage().toStringUtf8()); - - // type = 2 - accountPermissionJson = - "{\"owner_permission\":{\"type\":2,\"permission_name\":\"owner\",\"threshold\":1," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : owner permission type is error", - response.getMessage().toStringUtf8()); - - // type = -1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":-1,\"permission_name\":\"owner\",\"threshold\":1," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : owner permission type is error", - response.getMessage().toStringUtf8()); - - // type = long.min - 1000020 - accountPermissionJson = - "{\"owner_permission\":{\"type\":-9223372036855775828,\"permission_name\":\"\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : owner permission type is error", - response.getMessage().toStringUtf8()); - - // type = "12a" - accountPermissionJson = - "{\"owner_permission\":{\"type\":\"12a\",\"permission_name\":\"\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - boolean ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException: For input string: \"12a\""); - ret = true; - } - Assert.assertTrue(ret); - - // type = "" - accountPermissionJson = - "{\"owner_permission\":{\"type\":\"\",\"permission_name\":\"\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException !"); - ret = true; - } - Assert.assertTrue(ret); - - // type = - accountPermissionJson = - "{\"owner_permission\":{\"type\":,\"permission_name\":\"\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (com.alibaba.fastjson.JSONException e) { - logger.info("JSONException !"); - ret = true; - } - Assert.assertTrue(ret); - - // type = null - accountPermissionJson = - "{\"owner_permission\":{\"type\":" + null + ",\"permission_name\":\"\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException !"); - ret = true; - } - Assert.assertTrue(ret); - // type = Integer.MAX_VALUE - accountPermissionJson = - "{\"owner_permission\":{\"type\":2147483647,\"permission_name\":\"\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : owner permission type is error", - response.getMessage().toStringUtf8()); - - // type = Long.MAX_VALUE - accountPermissionJson = - "{\"owner_permission\":{\"type\":9223372036854775807,\"permission_name\":\"\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : owner permission type is error", - response.getMessage().toStringUtf8()); - - // type = long.min - 1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":-9223372036854775809,\"permission_name\":\"owner\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : owner permission type is error", - response.getMessage().toStringUtf8()); - - // type = Long.MAX_VALUE + 10 - accountPermissionJson = "{\"owner_permission\":{\"type\":9223372036854775817," - + "\"permission_name\":\"owner\",\"threshold\": 1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":9223372036854775806}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : owner permission type is error", - response.getMessage().toStringUtf8()); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore, balanceAfter); - } - - @Test(enabled = true, description = "Owner type is 0") - public void testOwnerType02() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - final byte[] ownerAddress = ecKey1.getAddress(); - final String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - - @Test(enabled = true, description = "Owner type is Long.Min") - public void testOwnerType03() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - final byte[] ownerAddress = ecKey1.getAddress(); - final String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":-9223372036854775808,\"permission_name\":\"\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @Test(enabled = true, description = "Owner type is Long.MAX_VALUE + 1") - public void testOwnerType04() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - final byte[] ownerAddress = ecKey1.getAddress(); - final String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":9223372036854775808,\"permission_name\":\"Owner\"," - + "\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":9223372036854775806}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - - @Test(enabled = true, description = "Owner type is 0.1") - public void testOwnerType05() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - final byte[] ownerAddress = ecKey1.getAddress(); - final String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = "{\"owner_permission\":{\"type\":0.1," - + "\"permission_name\":\"owner\",\"threshold\": 1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":9223372036854775806}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign07.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign07.java deleted file mode 100644 index 65b2b586337..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign07.java +++ /dev/null @@ -1,662 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign07 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Owner permission_name is owner") - public void testActiveName01() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - long needCoin = updateAccountPermissionFee + multiSignFee; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1000000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(witnessKey001); - activePermissionKeys.add(tmpKey02); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"owner\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - - } - - @Test(enabled = true, description = "Owner permission_name is active") - public void testActiveName02() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee + multiSignFee; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1_000000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(witnessKey001); - activePermissionKeys.add(tmpKey02); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - - } - - @Test(enabled = true, description = "Owner permission_name is activea") - public void testActiveName03() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee + multiSignFee; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(witnessKey001); - activePermissionKeys.add(tmpKey02); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"activea\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - } - - @Test(enabled = true, description = "Owner permission_name is \"123\"") - public void testActiveName04() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee + multiSignFee; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(witnessKey001); - activePermissionKeys.add(tmpKey02); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"123\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - } - - @Test(enabled = true, description = "Owner permission_name is \"\"") - public void testActiveName05() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee + multiSignFee; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(witnessKey001); - activePermissionKeys.add(tmpKey02); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - } - - @Test(enabled = true, description = "Owner permission_name in exception condition") - public void testActiveName06() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" + null - + ",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - boolean ret = false; - try { - GrpcAPI.Return response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NullPointerException e) { - logger.info("Expected NullPointerException!"); - ret = true; - } - Assert.assertTrue(ret); - - // name = - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":,\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (com.alibaba.fastjson.JSONException e) { - logger.info("Expected com.alibaba.fastjson.JSONException!"); - ret = true; - } - Assert.assertTrue(ret); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore, balanceAfter); - } - - @Test(enabled = true, description = "Owner permission_name is 1.1") - public void testActiveName07() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee + multiSignFee; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(witnessKey001); - activePermissionKeys.add(tmpKey02); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":1.1,\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - } - - @Test(enabled = true, description = "Active permission_name length is 32") - public void testActiveName08() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1000000, fromAddress, testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2," - + "\"permission_name\":\"abcdefghijklmnopqrstuvwxyzabcdef\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - } - - - @Test(enabled = true, description = "Active permission_name length is 33") - public void testActiveName09() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, 1000000, fromAddress, testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - String accountPermissionJson = "{\"owner_permission\":{\"type\":0," - + "\"permission_name\":\"owner001\",\"threshold\":1,\"keys\":[" + "{\"address\":\"" - + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2," - + "\"permission_name\":\"abcdefghijklmnopqrstuvwxyzabcdefg\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - GrpcAPI.Return response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's name is too long", - response.getMessage().toStringUtf8()); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore, balanceAfter); - - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign08.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign08.java deleted file mode 100644 index 070e1fd46ae..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign08.java +++ /dev/null @@ -1,623 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign08 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Active threshold is exception condition") - public void testActiveTheshold01() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - // threshold = Integer.Min_Value - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":-2147483648," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - GrpcAPI.Return response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals( - "contract validate error : permission's" + " threshold should be greater than 0", - response.getMessage().toStringUtf8()); - - // threshold = 0 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":0," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals( - "contract validate error : permission's" + " threshold should be greater than 0", - response.getMessage().toStringUtf8()); - - // threshold = -1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":-1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals( - "contract validate error : permission's" + " threshold should be greater than 0", - response.getMessage().toStringUtf8()); - - // threshold = long.min - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":-9223372036854775808," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals( - "contract validate error : permission's" + " threshold should be greater than 0", - response.getMessage().toStringUtf8()); - - // threshold = long.min - 1000020 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":-9223372036855775828," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - boolean ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // threshold = long.min - 1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":-9223372036854775809," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // threshold = "12a" - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":\"-12a\"," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException : -12a !"); - ret = true; - } - Assert.assertTrue(ret); - - // threshold = "" - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":\"\"," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // threshold = - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (com.alibaba.fastjson.JSONException e) { - logger.info("JSONException !"); - ret = true; - } - Assert.assertTrue(ret); - - // threshold = null - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":" + null + "," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // threshold = 1.9 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1.9," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":21}" + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // threshold = Long.MAX_VALUE - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":9223372036854775807," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":9223372036854775807}," + "{\"address\":\"" + PublicMethed - .getAddressString(ownerKey) + "\",\"weight\":1}" + "]}]}"; - - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : long overflow", - response.getMessage().toStringUtf8()); - - // theshold = 1.1 > sum(weight) - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1.1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":9223372036854775806}," + "{\"address\":\"" + PublicMethed - .getAddressString(ownerKey) + "\",\"weight\":1}" + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore, balanceAfter); - } - - @Test(enabled = true, description = "Active threshold is 1") - public void testActiveTheshold02() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - long needCoin = updateAccountPermissionFee; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(tmpKey02); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(1, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - } - - @Test(enabled = true, description = "Active threshold is more than sum of weight") - public void testActiveTheshold03() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - // threshold = Integer.MAX_VALUE *2 + 5 > sum(weight) - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":4294967299," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2147483647}," + "{\"address\":\"" + PublicMethed - .getAddressString(witnessKey001) + "\",\"weight\":3}," + "{\"address\":\"" - + PublicMethed.getAddressString(tmpKey01) + "\",\"weight\":2147483647}" + "]}]}"; - GrpcAPI.Return response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : sum of all key's weight should not" - + " be less than threshold in permission Active", response.getMessage().toStringUtf8()); - - } - - @Test(enabled = true, description = "Active threshold is Long.MAX_VALUE") - public void testActiveTheshold04() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee + multiSignFee; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(witnessKey001); - activePermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":9223372036854775807," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":9223372036854775806}," + "{\"address\":\"" + PublicMethed - .getAddressString(ownerKey) + "\",\"weight\":1}" + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - } - - @Test(enabled = true, description = "Active threshold is Integer.MAX_VALUE") - public void testActiveTheshold05() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee + multiSignFee; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(witnessKey001); - activePermissionKeys.add(ownerKey); - activePermissionKeys.add(tmpKey01); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":2147483647," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2147483646}," + "{\"address\":\"" + PublicMethed - .getAddressString(ownerKey) + "\",\"weight\":2147483647}" + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign09.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign09.java deleted file mode 100644 index 6814116b3ba..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign09.java +++ /dev/null @@ -1,489 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign09 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Active doesn't have parent_id") - public void testActiveParent01() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":4," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @Test(enabled = true, description = "Active parent_id is exception condition") - public void testActiveParent02() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - // parent_id = "123" - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[" - + "{\"parent_id\":\"123\",\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - GrpcAPI.Return response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - - // parent_id = "abc" - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[" - + "{\"parent_id\":\"abc\",\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - boolean ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NumberFormatException e) { - logger.info("Expected NumberFormatException!"); - ret = true; - } - Assert.assertTrue(ret); - - // parent_id = "" - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[" - + "{\"parent_id\":\"\",\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NullPointerException e) { - logger.info("Expected NullPointerException!"); - ret = true; - } - Assert.assertTrue(ret); - - // parent_id = null - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[" + "{\"parent_id\":" + null - + ",\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NullPointerException e) { - logger.info("Expected NullPointerException!"); - ret = true; - } - Assert.assertTrue(ret); - - // parent_id = 1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[" - + "{\"parent_id\":1,\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = 2 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[" - + "{\"parent_id\":2,\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = 3 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[" - + "{\"parent_id\":3,\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = -1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[" - + "{\"parent_id\":-1,\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = Integer.MAX_VALUE - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[" + "{\"parent_id\":2147483647,\"type\":2," - + "\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = Integer.MAX_VALUE +1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[" + "{\"parent_id\":2147483648,\"type\":2," - + "\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = Integer.MIN_VALUE - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[" + "{\"parent_id\":-2147483648,\"type\":2," - + "\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = Integer.MIN_VALUE -1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[" + "{\"parent_id\":-2147483649,\"type\":2," - + "\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - } - - @Test(enabled = true, description = "Active parent_id is 0") - public void testActiveParent03() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}]}," - + "\"active_permissions\":[" - + "{\"parent_id\":0,\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign10.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign10.java deleted file mode 100644 index 69fafd0c8d1..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign10.java +++ /dev/null @@ -1,651 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign10 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Active weight is exception condition") - public void testActiveWeight01() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - // weight = Integer.MIN_VALUE - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":-2147483648}" - + "]}]}"; - - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : key's weight" - + " should be greater than 0", - response.getMessage().toStringUtf8()); - - // weight = 0 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":0}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : key's weight" - + " should be greater than 0", - response.getMessage().toStringUtf8()); - - // weight = -1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":-1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : key's weight" - + " should be greater than 0", - response.getMessage().toStringUtf8()); - - // weight = long.min - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":-9223372036854775808}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : key's weight" - + " should be greater than 0", - response.getMessage().toStringUtf8()); - - // weight = long.min - 1000020 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":-9223372036855775828}" - + "]}]}"; - - boolean ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // weight = "12a" - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":\"12a\"}" - + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // weight = "" - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":\"\"}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":-9223372036855775828}" - + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // weight = - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (com.alibaba.fastjson.JSONException e) { - logger.info("JSONException !"); - ret = true; - } - Assert.assertTrue(ret); - - // weight = null - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":" - + null + "}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // weight = Long.MIN -1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":-9223372036854775809}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // weight = 1.1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1.1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - } - - @Test(enabled = true, description = "Active weight is 1") - public void testActiveWeight02() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee + multiSignFee; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(witnessKey001); - activePermissionKeys.add(ownerKey); - activePermissionKeys.add(tmpKey02); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(3, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(3, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - } - - @Test(enabled = true, description = "Active weight is Integer.MAX_VALUE") - public void testActiveWeight03() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(witnessKey001); - activePermissionKeys.add(tmpKey02); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2147483647}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2147483647}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":21474836471}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":21474836471}" - + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(tmpKey02); - ownerPermissionKeys.add(witnessKey001); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(3, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - } - - @Test(enabled = true, description = "Active sum of weight is more than Long.MAX_VALUE") - public void testActiveWeight04() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2147483647}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2147483647}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":9223372036854775807}" - + "]}]}"; - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : long overflow", - response.getMessage().toStringUtf8()); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - } - - @Test(enabled = true, description = "Active weight is Long.MAX_VALUE") - public void testActiveWeight05() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(witnessKey001); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":9223372036854775807}" - + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(1, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign11.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign11.java deleted file mode 100644 index cb8a6a8ee10..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign11.java +++ /dev/null @@ -1,1089 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign11 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - private final String contractTronDiceAddr = "TMYcx6eoRXnePKT1jVn25ZNeMNJ6828HWk"; - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Active address is witness") - public void testActiveAddress01() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee + multiSignFee; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(witnessKey001); - activePermissionKeys.add(tmpKey02); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":4," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(witnessKey001); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - } - - @Test(enabled = true, description = "Active address is contract address") - public void testActiveAddress02() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(tmpKey02); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + contractTronDiceAddr + "\",\"weight\":1}," + "{\"address\":\"" - + PublicMethed.getAddressString(testKey002) + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + contractTronDiceAddr + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":3}" - + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(3, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - } - - @Test(enabled = true, description = "Active address is inactive address") - public void testActiveAddress03() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee + multiSignFee; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(witnessKey001); - activePermissionKeys.add(tmpKey02); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":5," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}" + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(tmpKey01); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - } - - @Test(enabled = true, description = "Active address is owner address") - public void testActiveAddress04() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":3}" + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(1, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - } - - @Test(enabled = true, description = "Active address is exception condition") - public void testActiveAddress05() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - // address = same address more than once - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":3}," + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":3}" + "]}]}"; - - GrpcAPI.Return response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals( - "contract validate error : address should be distinct" + " in permission Active", - response.getMessage().toStringUtf8()); - - // address = not exist - String fakeAddress = "THph9K2M2nLvkianrMGswRhz5hjSA9fuH1"; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + fakeAddress + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}" - + "]}]}"; - - boolean ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException !"); - ret = true; - } - Assert.assertTrue(ret); - - // address = long address - fakeAddress = "TR3FAbhiSeP7kSh39RjGYpwCqfMDHPMhX4d121"; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + fakeAddress + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException !"); - ret = true; - } - Assert.assertTrue(ret); - - // address = short address - fakeAddress = "THph9K2M2nLvkianrMGswRhz5hj"; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + fakeAddress + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException !"); - ret = true; - } - Assert.assertTrue(ret); - - // address = - fakeAddress = ""; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + fakeAddress + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) + "\",\"weight\":3}" - + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, fakeAddress.getBytes(), - ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException!"); - ret = true; - } - - Assert.assertTrue(ret); - - // address = null - fakeAddress = null; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + fakeAddress + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) + "\",\"weight\":3}" - + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, fakeAddress.getBytes(), - ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException!"); - ret = true; - } - - Assert.assertTrue(ret); - - // address = 1.1 - fakeAddress = "1.1"; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + fakeAddress + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) + "\",\"weight\":3}" - + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, fakeAddress.getBytes(), - ownerKey, blockingStubFull); - } catch (IllegalArgumentException e) { - logger.info("IllegalArgumentException!"); - ret = true; - } - Assert.assertTrue(ret); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - - - } - - @Test(enabled = true, description = "Active address count is 5") - public void testActiveAddress06() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee + multiSignFee; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(witnessKey001); - activePermissionKeys.add(ownerKey); - activePermissionKeys.add(tmpKey01); - activePermissionKeys.add(tmpKey02); - activePermissionKeys.add(testKey002); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"" - + ",\"threshold\":10," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(5, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - ownerPermissionKeys.add(tmpKey01); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - - - } - - @Test(enabled = true, description = "Active address count is more than 5") - public void testActiveAddress07() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + contractTronDiceAddr + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) + "\",\"weight\":3}" - + "]}]}"; - GrpcAPI.Return response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals( - "contract validate error : number of keys in permission should" + " not be greater than 5", - response.getMessage().toStringUtf8()); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - } - - @Test(enabled = true, description = "Active address count is 0") - public void testActiveAddress08() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[]}]}"; - GrpcAPI.Return response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : key's count should be greater than 0", - response.getMessage().toStringUtf8()); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - } - - @Test(enabled = true, description = "Active address count is 1") - public void testActiveAddress09() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(tmpKey01); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(1, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - ownerPermissionKeys.add(witnessKey001); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - } - - @Test(enabled = true, description = "Active permission count is 8") - public void testActiveAddress10() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee + multiSignFee; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(witnessKey001); - activePermissionKeys.add(ownerKey); - activePermissionKeys.add(tmpKey01); - activePermissionKeys.add(tmpKey02); - activePermissionKeys.add(testKey002); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":2147483647}]}," + "\"active_permissions\":[" - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active1\",\"threshold\":5," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active2\",\"threshold\":7," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active3\",\"threshold\":9," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active4\",\"threshold\":10," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active5\",\"threshold\":11," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active6\",\"threshold\":10," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active7\",\"threshold\":11," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}]}"; - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(40, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - ownerPermissionKeys.add(tmpKey01); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 9, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - } - - @Test(enabled = true, description = "Active permission count is 9") - public void testActiveAddress11() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":2147483647}]}," + "\"active_permissions\":[" - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active1\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active2\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active3\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active4\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active5\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active6\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active7\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active8\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}]}"; - - GrpcAPI.Return response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : active permission is too many", - response.getMessage().toStringUtf8()); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - } - - @Test(enabled = true, description = "Active permission count is 8, " - + "sum of weight is less than threshold") - public void testActiveAddress12() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":2147483647}]}," + "\"active_permissions\":[" - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active1\",\"threshold\":9223372036854775807," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active2\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active3\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active4\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active5\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active6\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}," - + "{\"type\":2,\"permission_name\":\"active7\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) - + "\",\"weight\":3}" + "]}]}"; - - GrpcAPI.Return response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : sum of all key's weight should" - + " not be less than threshold in permission Active", response.getMessage().toStringUtf8()); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign12.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign12.java deleted file mode 100644 index 3225ab8210f..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign12.java +++ /dev/null @@ -1,501 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign12 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key2"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Active type is exception condition") - public void testActiveType01() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - // type = Integer.MIN_VALUE - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":-2147483648,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : active permission type is error", - response.getMessage().toStringUtf8()); - - // type = 0 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":0,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : active permission type is error", - response.getMessage().toStringUtf8()); - - // type = -1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":-1,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : active permission type is error", - response.getMessage().toStringUtf8()); - - // type = long.min - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":-9223372036854775808," - + "\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : active permission type is error", - response.getMessage().toStringUtf8()); - - // type = long.min - 1000020 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":-9223372036855775828," - + "\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : active permission type is error", - response.getMessage().toStringUtf8()); - - // type = long.min - 1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":-9223372036854775809," - + "\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : active permission type is error", - response.getMessage().toStringUtf8()); - - // type = "12a" - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":\"12a\",\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - boolean ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // type = "" - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":\"\",\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException !"); - ret = true; - } - Assert.assertTrue(ret); - - // type = - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - ret = false; - try { - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (com.alibaba.fastjson.JSONException e) { - logger.info("JSONException !"); - ret = true; - } - Assert.assertTrue(ret); - - // type = null - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":" + null + ",\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException !"); - ret = true; - } - Assert.assertTrue(ret); - - // type = 1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":1,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : active permission type is error", - response.getMessage().toStringUtf8()); - - // type = Long.MAX_VALUE - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":9223372036854775807," - + "\"permission_name\":\"active0\"," - + "\"threshold\":9223372036854775807," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":9223372036854775806}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : active permission type is error", - response.getMessage().toStringUtf8()); - - // type = Long.MAX_VALUE + 1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":9223372036854775808," - + "\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":9223372036854775806}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : active permission type is error", - response.getMessage().toStringUtf8()); - - // type = 1.1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":1.1,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":9223372036854775806}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : active permission type is error", - response.getMessage().toStringUtf8()); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - - } - - @Test(enabled = true, description = "Active type is 2.9") - public void testActiveType02() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.waitProduceNextBlock(blockingStubFull); - long needCoin = updateAccountPermissionFee; - - PublicMethed - .sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, testKey002, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(tmpKey02); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2.9,\"permission_name\":\"active0\"," - + "\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":21}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(1, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign13.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign13.java deleted file mode 100644 index 1b915b7ae77..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign13.java +++ /dev/null @@ -1,845 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign13 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Witness permission_name is witness") - public void testWitnessName01() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed - .sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - - ownerPermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - @Test(enabled = true, description = "Witness permission_name is witness12") - public void testWitnessName02() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000L, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - - ownerPermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness12\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - @Test(enabled = true, description = "Witness permission_name is \"123\"") - public void testWitnessName03() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - - ownerPermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"123\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - @Test(enabled = true, description = "Witness permission_name is \"\"") - public void testWitnessName04() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - - } - - @Test(enabled = true, description = "Witness permission_name is null") - public void testWitnessName05() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - PublicMethed.sendcoin(ownerAddress, 1_000000, fromAddress, testKey002, blockingStubFull); - - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":" + null - + ",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - boolean ret = false; - try { - GrpcAPI.Return response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("Expected NullPointerException!"); - ret = true; - } - Assert.assertTrue(ret); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - - } - - @Test(enabled = true, description = "Witness doesn't have permission_name") - public void testWitnessName06() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - - } - - @Test(enabled = true, description = "Witness permission_name is 123") - public void testWitnessName07() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"permission_name\":123,\"type\":1," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - @Test(enabled = true, description = "Witness permission_name is 0.1") - public void testWitnessName08() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"permission_name\":\"0.1\",\"type\":1," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - @Test(enabled = true, description = "Witness permission_name length is 32") - public void testWitnessName09() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1000000, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000L, 0, 0, - ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":" - + "{\"permission_name\":\"abcdefghijklmnopqrstuvwxyzabcdef\",\"type\":1," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - - } - - - @Test(enabled = true, description = "Witness permission_name length is 33") - public void testWitnessName10() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, 1000000, fromAddress, - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":" - + "{\"permission_name\":\"abcdefghijklmnopqrstuvwxyzabcdefg\",\"type\":1," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's name is too long", - response.getMessage().toStringUtf8()); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore, balanceAfter); - - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign14.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign14.java deleted file mode 100644 index 1de83a9b1fd..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign14.java +++ /dev/null @@ -1,699 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign14 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Witness threshold is exception condition") - public void testWitnessThreshold01() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - PublicMethed.sendcoin(ownerAddress, 1_000000, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - // theshold = Integer.MIN_VALUE - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":-2147483648,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's" - + " threshold should be greater than 0", - response.getMessage().toStringUtf8()); - - // theshold = 0 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":0,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's" - + " threshold should be greater than 0", - response.getMessage().toStringUtf8()); - - // theshold = -1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":-1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's" - + " threshold should be greater than 0", - response.getMessage().toStringUtf8()); - - // theshold = long.min - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":-9223372036854775808,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's" - + " threshold should be greater than 0", - response.getMessage().toStringUtf8()); - - // theshold = long.min - 1000020 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":-9223372036855775828,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - boolean ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // theshold = long.min - 1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":-9223372036854775809,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // theshold = "12a" - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":\"12a\",\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // theshold = "" - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":\"\",\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // theshold = - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (com.alibaba.fastjson.JSONException e) { - logger.info("JSONException !"); - ret = true; - } - Assert.assertTrue(ret); - - // theshold = null - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":" + null + ",\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // theshold = Long.MAX_VALUE < sum(weight) - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":9223372036854775807,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":9223372036854775806}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : sum of all key's weight should not be" - + " less than threshold in permission Witness", - response.getMessage().toStringUtf8()); - - // theshold = Long.MAX_VALUE + 1 > sum(weight) - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":9223372036854775808,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":9223372036854775806}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // theshold = 1.1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":1.1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":9223372036854775806}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - - Assert.assertTrue(PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull)); - - } - - @Test(enabled = true, description = "Witness threshold is 1") - public void testWitnessThreshold02() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - - } - - @Test(enabled = true, description = "Witness threshold is more than sum of weight") - public void testWitnessThreshold03() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - PublicMethed.sendcoin(ownerAddress, 1_000000, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - // threshold > sum(weight) - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":4294967299,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":214748364}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : sum of all key's weight should not be" - + " less than threshold in permission Witness", - response.getMessage().toStringUtf8()); - - // threshold = Integer.MAX_VALUE > sum(weight) - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":2147483647,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":214748364}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : sum of all key's weight " - + "should not be less than threshold in permission Witness", - response.getMessage().toStringUtf8()); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - @Test(enabled = true, description = "Witness threshold is Long.MAX_VALUE") - public void testWitnessThreshold04() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":9223372036854775807,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":9223372036854775807}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign15.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign15.java deleted file mode 100644 index 9138d4ba71e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign15.java +++ /dev/null @@ -1,597 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign15 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull); - } - - @Test(enabled = true, description = "Witness doesn't have parent_id") - public void testWitnessParent01() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - @Test(enabled = true, description = "Witness parent_id is exception condition") - public void testWitnessParent02() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.sendcoin(ownerAddress, 1_000000, fromAddress, testKey002, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - // parent_id = "123" - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"parent_id\":\"123\",\"type\":1," - + "\"permission_name\":\"witness\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = 123 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"parent_id\":123,\"type\":1," - + "\"permission_name\":\"witness\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = "abc" - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"parent_id\":\"abc\",\"type\":1," - + "\"permission_name\":\"witness\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - boolean ret = false; - try { - PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("Expected NumberFormatException!"); - ret = true; - } - Assert.assertTrue(ret); - - // parent_id = "" - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"parent_id\":\"\",\"type\":1," - + "\"permission_name\":\"witness\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - ret = false; - try { - PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("Expected NullPointerException!"); - ret = true; - } - Assert.assertTrue(ret); - - // parent_id = null - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"parent_id\":" + null + ",\"type\":1," - + "\"permission_name\":\"witness\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - ret = false; - try { - PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("Expected NullPointerException!"); - ret = true; - } - Assert.assertTrue(ret); - - // parent_id = 1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"parent_id\":1,\"type\":1," - + "\"permission_name\":\"witness\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = 2 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"parent_id\":2,\"type\":1," - + "\"permission_name\":\"witness\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = 3 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"parent_id\":3,\"type\":1," - + "\"permission_name\":\"witness\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = -1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"parent_id\":-1,\"type\":1," - + "\"permission_name\":\"witness\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = Integer.MAX_VALUE - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"parent_id\":2147483647,\"type\":1," - + "\"permission_name\":\"witness\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = Integer.MAX_VALUE +1 - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"parent_id\":2147483648,\"type\":1," - + "\"permission_name\":\"witness\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = Integer.MIN_VALUE - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"parent_id\":-2147483648,\"type\":1," - + "\"permission_name\":\"witness\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - - // parent_id = Integer.MIN_VALUE -1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"parent_id\":-2147483649,\"type\":1," - + "\"permission_name\":\"witness\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : permission's parent should be owner", - response.getMessage().toStringUtf8()); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - - } - - @Test(enabled = true, description = "Witness parent_id is 0") - public void testWitnessParent03() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"parent_id\":0,\"type\":1," - + "\"permission_name\":\"witness\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign16.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign16.java deleted file mode 100644 index 15be0aff99c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign16.java +++ /dev/null @@ -1,574 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign16 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Witness weight is exception condition") - public void testWitnessWeight01() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - PublicMethed.sendcoin(ownerAddress, 1_000000, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - // weight = Integer.MIN_VALUE - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"threshold\":1,\"keys\":[" + "{\"address\":\"" - + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":-2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - GrpcAPI.Return response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : key's weight" + " should be greater than 0", - response.getMessage().toStringUtf8()); - - // weight = 0 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"threshold\":1,\"keys\":[" + "{\"address\":\"" - + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":0}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : key's weight" + " should be greater than 0", - response.getMessage().toStringUtf8()); - - // weight = -1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"threshold\":1,\"keys\":[" + "{\"address\":\"" - + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":-1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : key's weight" + " should be greater than 0", - response.getMessage().toStringUtf8()); - - // weight = long.min - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"threshold\":1,\"keys\":[" + "{\"address\":\"" - + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":-9223372036854775808}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : key's weight" + " should be greater than 0", - response.getMessage().toStringUtf8()); - - // weight = long.min - 1000020 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"threshold\":1,\"keys\":[" + "{\"address\":\"" - + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":-9223372036855775828}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - boolean ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // weight = "12a" - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"threshold\":1,\"keys\":[" + "{\"address\":\"" - + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":\"12a\"}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // weight = "" - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"threshold\":1,\"keys\":[" + "{\"address\":\"" - + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":\"\"}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // weight = - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"threshold\":1,\"keys\":[" + "{\"address\":\"" - + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (com.alibaba.fastjson.JSONException e) { - logger.info("JSONException !"); - ret = true; - } - Assert.assertTrue(ret); - - // weight = null - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"threshold\":1,\"keys\":[" + "{\"address\":\"" - + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":" + null + "}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // Long.MAX_VALUE + 1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"threshold\":1,\"keys\":[" + "{\"address\":\"" - + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":9223372036854775808}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - // weight = 1.1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"threshold\":1,\"keys\":[" + "{\"address\":\"" - + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1.1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } - Assert.assertTrue(ret); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - - Assert.assertTrue( - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull)); - - } - - @Test(enabled = true, description = "Witness weight is 1") - public void testWitnessWeight02() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"threshold\":1,\"keys\":[" + "{\"address\":\"" - + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getWitnessPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getWitnessPermission())); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - @Test(enabled = true, description = "Witness weight is Integer.MAX_VALUE") - public void testWitnessWeight03() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"threshold\":1,\"keys\":[" + "{\"address\":\"" - + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":2147483647}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getWitnessPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - - } - - @Test(enabled = true, description = "Witness weight is Long.MAX_VALUE") - public void testWitnessWeight04() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"threshold\":9223372036854775807,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":9223372036854775807}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getWitnessPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign17.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign17.java deleted file mode 100644 index 132c75282ec..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign17.java +++ /dev/null @@ -1,735 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign17 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - private final String contractTronDiceAddr = "TMYcx6eoRXnePKT1jVn25ZNeMNJ6828HWk"; - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Witness address is witness") - public void testWitnessAddress01() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness12\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - - } - - @Test(enabled = true, description = "Witness address is contract") - public void testWitnessAddress02() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness12\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + contractTronDiceAddr + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - - } - - @Test(enabled = true, description = "Witness address is inactive address") - public void testWitnessAddress03() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness12\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - - } - - @Test(enabled = true, description = "Witness address is owner_address") - public void testWitnessAddress04() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness12\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - - } - - @Test(enabled = true, description = "Witness address is exception condition") - public void testWitnessAddress05() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - PublicMethed.sendcoin(ownerAddress, 1_000000, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - // address = owner_address more than once - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness12\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : Witness permission's key count should be 1", - response.getMessage().toStringUtf8()); - - // address = not exist - String fakeAddress = "THph9K2M2nLvkianrMGswRhz5hjSA9fuH1"; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness12\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + fakeAddress + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - boolean ret = false; - try { - PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("Expected NullPointerException!"); - ret = true; - } - Assert.assertTrue(ret); - - // address = long address - fakeAddress = "TR3FAbhiSeP7kSh39RjGYpwCqfMDHPMhX4d121"; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness12\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + fakeAddress + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - ret = false; - try { - PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("Expected NullPointerException!"); - ret = true; - } - Assert.assertTrue(ret); - - // address = short address - fakeAddress = "THph9K2M2nLvkianrMGswRhz5hj"; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness12\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + fakeAddress + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - ret = false; - try { - PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("Expected NullPointerException!"); - ret = true; - } - Assert.assertTrue(ret); - - // address = - fakeAddress = ""; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness12\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + fakeAddress + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException!"); - ret = true; - } - - Assert.assertTrue(ret); - - // address = null - fakeAddress = null; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness12\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + fakeAddress + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, fakeAddress.getBytes(), ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException!"); - ret = true; - } - - Assert.assertTrue(ret); - - // address = "1.1" - fakeAddress = "1.1"; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness12\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + fakeAddress + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (IllegalArgumentException e) { - logger.info("IllegalArgumentException!"); - ret = true; - } - - Assert.assertTrue(ret); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - @Test(enabled = true, description = "Witness address account is 5") - public void testWitnessAddress06() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - PublicMethed.sendcoin(ownerAddress, 1_000000, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness12\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : Witness permission's key count should be 1", - response.getMessage().toStringUtf8()); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - - } - - @Test(enabled = true, description = "Witness address account is 0") - public void testWitnessAddress07() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - PublicMethed.sendcoin(ownerAddress, 1_000000, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness12\"," - + "\"threshold\":1,\"keys\":[]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : key's count should be greater than 0", - response.getMessage().toStringUtf8()); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign18.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign18.java deleted file mode 100644 index 67cb3f0d217..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign18.java +++ /dev/null @@ -1,612 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign18 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Witness type is 1") - public void testWitnessType01() { - // type = 1 - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - @Test(enabled = true, description = "Witness type is exception condition") - public void testWitnessType02() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - PublicMethed.sendcoin(ownerAddress, 1_000000, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - // type = 2 - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":2,\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : witness permission type is error", - response.getMessage().toStringUtf8()); - - // type = 0 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":0,\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : witness permission type is error", - response.getMessage().toStringUtf8()); - - // type = -1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":-1,\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : witness permission type is error", - response.getMessage().toStringUtf8()); - - // type = long.min - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":-9223372036854775808,\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : witness permission type is error", - response.getMessage().toStringUtf8()); - - // type = long.min - 1000020 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":-9223372036855775828,\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : witness permission type is error", - response.getMessage().toStringUtf8()); - - // type = "12a" - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":\"12a\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - boolean ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException: For input string: \"12a\""); - ret = true; - } - Assert.assertTrue(ret); - - // type = "" - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":\"\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException !"); - ret = true; - } - Assert.assertTrue(ret); - - // type = - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":,\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (com.alibaba.fastjson.JSONException e) { - logger.info("JSONException !"); - ret = true; - } - Assert.assertTrue(ret); - - // type = null - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":" + null + ",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException !"); - ret = true; - } - Assert.assertTrue(ret); - - // type = Integer.MAX_VALUE - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":2147483647,\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : witness permission type is error", - response.getMessage().toStringUtf8()); - - // type = Long.MAX_VALUE - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":9223372036854775807,\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : witness permission type is error", - response.getMessage().toStringUtf8()); - - // type = long.MAX_VALUE + 1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":9223372036854775808,\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : witness permission type is error", - response.getMessage().toStringUtf8()); - - // type = long.min - 1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":-9223372036854775809,\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : witness permission type is error", - response.getMessage().toStringUtf8()); - - // type = Long.MAX_VALUE + 1 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":9223372036854775808,\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : witness permission type is error", - response.getMessage().toStringUtf8()); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore, balanceAfter); - - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - @Test(enabled = true, description = "Witness type is 1.5") - public void testWitnessType03() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1.5,\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign19.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign19.java deleted file mode 100644 index b92a85b421c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign19.java +++ /dev/null @@ -1,647 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign19 { - - public static final String DEFAULT_OPERATION = - "7fff1fc0033e0000000000000000000000000000000000000000000000000000"; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Active operation is ContractType.TransferContract_VALUE") - public void testActiveOperations01() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - List activePermissionKeys2 = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(ownerKey); - activePermissionKeys2.add(witnessKey001); - - Integer[] ints = {ContractType.TransferContract_VALUE}; - String operationsTransfer = PublicMethedForMutiSign.getOperations(ints); - Integer[] ints2 = {ContractType.TransferAssetContract_VALUE}; - String operationsTransferAsset = PublicMethedForMutiSign.getOperations(ints2); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"" + operationsTransfer + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"" + operationsTransferAsset + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "]}]}"; - - Assert.assertTrue( - PublicMethedForMutiSign.accountPermissionUpdateWithPermissionId(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, 0, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign - .getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Assert.assertFalse(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 3, ownerKey, - blockingStubFull, - activePermissionKeys2.toArray(new String[activePermissionKeys2.size()]))); - - Assert.assertFalse(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys2.toArray(new String[activePermissionKeys2.size()]))); - - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - - - } - - @Test(enabled = true, description = "Active operation is" - + " 0000000000000000000000000000000000000000000000000000000000000000") - public void testActiveOperations02() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - long needCoin = updateAccountPermissionFee; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1000000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(testKey002); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"0000000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue( - PublicMethedForMutiSign.accountPermissionUpdateWithPermissionId(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, 0, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(1, PublicMethedForMutiSign - .getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - Assert.assertFalse(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - } - - @Test(enabled = true, description = "Active operation include invalid contract") - public void testActiveOperations03() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - // operation include invalid 99 contract - Integer[] ints = {0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 31, - 32, 33, 41, 42, 43, 44, 45, 99}; - String operations = PublicMethedForMutiSign.getOperations(ints); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : 99 isn't a validate ContractType", - response.getMessage().toStringUtf8()); - - // operation's length is less then 64, - // 63: 7fff1fc0033e000000000000000000000000000000000000000000000000000 - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - logger.info(accountPermissionJson); - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : 21 isn't a validate ContractType", - response.getMessage().toStringUtf8()); - - // operation's length is less then 64, - // 62: 7fff1fc0033e00000000000000000000000000000000000000000000000000 - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e00000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - logger.info(accountPermissionJson); - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : operations size must 32", - response.getMessage().toStringUtf8()); - - // operation's length is more then 64, - // 65: 7fff1fc0033e00000000000000000000000000000000000000000000000000000 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":" - + "\"7fff1fc0033e00000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - logger.info(accountPermissionJson); - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : operations size must 32", - response.getMessage().toStringUtf8()); - - // operation's length is more then 64, - // 66: 7fff1fc0033e00000000000000000000000000000000000000000000000000000 - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":" - + "\"7fff1fc0033e000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - logger.info(accountPermissionJson); - - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : operations size must 32", - response.getMessage().toStringUtf8()); - - // oprations = "12aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - // same result 12eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee - - operations = "12aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - logger.info(accountPermissionJson); - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : 21 isn't a validate ContractType", - response.getMessage().toStringUtf8()); - - // operation = "" - - operations = ""; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - logger.info(accountPermissionJson); - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : operations size must 32", - response.getMessage().toStringUtf8()); - - // Operation = - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - boolean ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (com.alibaba.fastjson.JSONException e) { - logger.info("JSONException !"); - ret = true; - } - Assert.assertTrue(ret); - - // Operation = null - operations = null; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (org.bouncycastle.util.encoders.DecoderException e) { - logger.info("org.bouncycastle.util.encoders.DecoderException !"); - ret = true; - } - Assert.assertTrue(ret); - - // no Operation - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - logger.info(accountPermissionJson); - response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : operations size must 32", - response.getMessage().toStringUtf8()); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - - } - - @Test(enabled = true, description = "Owner sets operation") - public void testActiveOperations04() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1," - + "\"operations\":\"" + DEFAULT_OPERATION + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"" + DEFAULT_OPERATION + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - logger.info(accountPermissionJson); - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : Owner permission needn't operations", - response.getMessage().toStringUtf8()); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - } - - @Test(enabled = true, description = "Witness sets operation") - public void testActiveOperations05() { - String ownerKey = witnessKey001; - byte[] ownerAddress = new WalletClient(ownerKey).getAddress(); - PublicMethed.sendcoin(ownerAddress, 1_000000, fromAddress, testKey002, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"owner\",\"threshold\":1," - + "\"operations\":\"" + DEFAULT_OPERATION + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"" + DEFAULT_OPERATION + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - logger.info(accountPermissionJson); - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : Witness permission needn't operations", - response.getMessage().toStringUtf8()); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign20.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign20.java deleted file mode 100644 index 416ad33e8ca..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign20.java +++ /dev/null @@ -1,518 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign20 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - private final String contractTronDiceAddr = "TMYcx6eoRXnePKT1jVn25ZNeMNJ6828HWk"; - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Owner address is witness") - public void testOwnerAddress01() { - // address = witness - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed - .freezeBalanceForReceiver(fromAddress, 50000000L, 0, 1, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull); - PublicMethed - .freezeBalanceForReceiver(fromAddress, 50000000L, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull); - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - ownerPermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"owner\"," - + "\"threshold\":1,\"keys\":[" + "{\"address\":\"" + PublicMethed - .getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(1, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getWitnessPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getWitnessPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":1,\"keys\":[" + "{\"address\":\"" + PublicMethed - .getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - } - - @Test(enabled = true, description = "Owner address is witness with exception condition") - public void testOwnerAddress02() { - // address = witness, without witness permission - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - PublicMethed.sendcoin(ownerAddress, 1_000000, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - - GrpcAPI.Return response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : witness permission is missed", - response.getMessage().toStringUtf8()); - - // address = witness, without active permission - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":1,\"keys\":[" + "{\"address\":\"" + PublicMethed - .getAddressString(ownerKey) + "\",\"weight\":1}]}}"; - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : active permission is missed", - response.getMessage().toStringUtf8()); - - // address = witness, without owner permission - accountPermissionJson = "{\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":1,\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : owner permission is missed", - response.getMessage().toStringUtf8()); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - @Test(enabled = true, description = "Owner address is normal address with exception condition") - public void testOwnerAddress03() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - - ownerPermissionKeys.add(ownerKey); - - // address = normal address, with witness permission - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"witness\"," - + "\"threshold\":1,\"keys\":[" + "{\"address\":\"" + PublicMethed - .getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - - GrpcAPI.Return response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals( - "contract validate error : account isn't witness can't set" + " witness permission", - response.getMessage().toStringUtf8()); - - // address = normal address, without owner permission - accountPermissionJson = - "{\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : owner permission is missed", - response.getMessage().toStringUtf8()); - - // address = normal address, without active permission - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}}"; - - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : active permission is missed", - response.getMessage().toStringUtf8()); - - // address = contract address - byte[] ownerAddress02 = contractTronDiceAddr.getBytes(); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress02, ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : invalidate ownerAddress", - response.getMessage().toStringUtf8()); - - // address = not active address - ECKey ecKeyTmp = new ECKey(Utils.getRandom()); - final byte[] ownerAddressTmp = ecKeyTmp.getAddress(); - final String ownerKeyTmp = ByteArray.toHexString(ecKeyTmp.getPrivKeyBytes()); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddressTmp, ownerKeyTmp, - blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : ownerAddress account does not exist", - response.getMessage().toStringUtf8()); - - // address = not exist - String fakeAddress = "THph9K2M2nLvkianrMGswRhz5hjSA9fuH1"; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, fakeAddress.getBytes(), ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : invalidate ownerAddress", - response.getMessage().toStringUtf8()); - - // address = long address - fakeAddress = "TR3FAbhiSeP7kSh39RjGYpwCqfMDHPMhX4d121"; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, fakeAddress.getBytes(), ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : invalidate ownerAddress", - response.getMessage().toStringUtf8()); - - // address = short address - - fakeAddress = "THph9K2M2nLvkianrMGswRhz5hj"; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, fakeAddress.getBytes(), ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : invalidate ownerAddress", - response.getMessage().toStringUtf8()); - - // address = - fakeAddress = ""; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, fakeAddress.getBytes(), ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : invalidate ownerAddress", - response.getMessage().toStringUtf8()); - - // address = null - fakeAddress = null; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - boolean ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, fakeAddress.getBytes(), - ownerKey, blockingStubFull); - } catch (NullPointerException e) { - logger.info("NullPointerException !"); - ret = true; - } - Assert.assertTrue(ret); - - // address = "1ab(*c" - fakeAddress = "1ab(*c"; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) - + "\",\"weight\":1}" + "]}]}"; - - response = PublicMethed - .accountPermissionUpdateForResponse(accountPermissionJson, fakeAddress.getBytes(), ownerKey, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : invalidate ownerAddress", - response.getMessage().toStringUtf8()); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - } - - @AfterMethod - public void aftertest() { - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, ownerAddress, blockingStubFull); - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign21.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign21.java deleted file mode 100644 index 5fbd6edf69c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign21.java +++ /dev/null @@ -1,228 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign21 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Permission Count is in exception condition") - public void testPermissionCount01() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - - ownerPermissionKeys.add(ownerKey); - - // count = 1 - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}]}}"; - - GrpcAPI.Return response = PublicMethed.accountPermissionUpdateForResponse(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull); - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : active permission is missed", - response.getMessage().toStringUtf8()); - - // count = 0 - accountPermissionJson = "[]"; - - boolean ret = false; - try { - PublicMethed.accountPermissionUpdateForResponse( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull); - } catch (com.alibaba.fastjson.JSONException e) { - logger.info("com.alibaba.fastjson.JSONException !"); - ret = true; - } - Assert.assertTrue(ret); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - - } - - @Test(enabled = true, description = "Permission Count is 4") - public void testPermissionCount02() { - ownerKey = witnessKey001; - ownerAddress = new WalletClient(ownerKey).getAddress(); - long needCoin = updateAccountPermissionFee * 2; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"owner\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"owner\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(1, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getWitnessPermission())); - - PublicMethedForMutiSign - .recoverWitnessPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign22.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign22.java deleted file mode 100644 index 3d2823ced04..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign22.java +++ /dev/null @@ -1,682 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.hamcrest.CoreMatchers.containsString; -import static org.tron.api.GrpcAPI.Return.response_code.SIGERROR; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign22 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Sign permission transaction by owner permission") - public void test01SignByOwnerKey() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2 + multiSignFee; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - List ownerPermissionKeys = new ArrayList<>(); - PublicMethed.printAddress(ownerKey); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - - ownerPermissionKeys.add(ownerKey); - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(1, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - ownerPermissionKeys.add(testKey002); - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, 0, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(1, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - } - - - @Test(enabled = true, description = "Sign normal transaction by owner permission") - public void test02SignByOwnerKeyForNormal() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee + multiSignFee; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1_000000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - PublicMethed.printAddress(ownerKey); - - logger.info("** update owner permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - - ownerPermissionKeys.add(ownerKey); - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(1, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - ownerPermissionKeys.add(testKey002); - - logger.info("** trigger a normal permission"); - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 0, ownerKey, - blockingStubFull, ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1_000000); - } - - - @Test(enabled = true, description = "Sign normal transaction by active permission") - public void test03SignByActiveKey() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee + multiSignFee; - - Assert.assertTrue(PublicMethed - .sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - - List activePermissionKeys = new ArrayList<>(); - List ownerPermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(testKey002); - activePermissionKeys.add(normalKey001); - - logger.info("** update active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(normalKey001) - + "\",\"weight\":1}" + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - logger.info("** update owner permission to two address"); - logger.info("** trigger a normal permission"); - Assert.assertFalse(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 0, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - - Assert.assertTrue(PublicMethedForMutiSign - .sendcoinWithPermissionId(fromAddress, 1_000000, ownerAddress, 2, ownerKey, - blockingStubFull, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - - } - - - @Test(enabled = true, description = "Sign permission transaction by active permission") - public void test04SignByActiveKeyForPermission() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2 + multiSignFee; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - Integer[] ints = {ContractType.AccountPermissionUpdateContract_VALUE}; - final String operations = PublicMethedForMutiSign.getOperations(ints); - - PublicMethed.printAddress(ownerKey); - - List activePermissionKeys = new ArrayList<>(); - List ownerPermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(testKey002); - activePermissionKeys.add(normalKey001); - - logger.info("** update active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," + "\"keys\":[" + "{\"address\":\"" - + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}," + "{\"address\":\"" - + PublicMethed.getAddressString(normalKey001) + "\",\"weight\":1}" + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, 2, - activePermissionKeys.toArray(new String[activePermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(1, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @Test(enabled = true, description = "Sign permission transaction" - + " by address which is out of permission list") - public void test06SignByOtherKey() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, 1000000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - PublicMethed.printAddress(ownerKey); - - logger.info("** update active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - - ownerPermissionKeys.add(normalKey001); - GrpcAPI.Return response = PublicMethedForMutiSign - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()])); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(SIGERROR, response.getCode()); - Assert.assertThat(response.getMessage().toStringUtf8(), - containsString("it is not contained of permission")); - - Assert.assertEquals(1, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - - } - - @Test(enabled = true, description = "Sign permission transaction " + "by empty permission list") - public void test07SignByEmptyObjectKey() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - String[] ownerPermissionKeys = new String[0]; - PublicMethed.printAddress(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - - GrpcAPI.Return response = PublicMethedForMutiSign - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerPermissionKeys); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(SIGERROR, response.getCode()); - Assert.assertEquals("validate signature error miss sig or contract", - response.getMessage().toStringUtf8()); - - Assert.assertEquals(1, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - } - - @Test(enabled = true, description = "Sign permission transaction by empty address") - public void test08SignByEmptyKey() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - String[] ownerPermissionKeys = new String[1]; - PublicMethed.printAddress(ownerKey); - ownerPermissionKeys[0] = ""; - - logger.info("** update active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - - boolean ret = false; - try { - PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys); - } catch (NumberFormatException e) { - logger.info("NumberFormatException !"); - ret = true; - } catch (NullPointerException e) { - logger.info("NullPointerException !"); - ret = true; - } - - Assert.assertTrue(ret); - Assert.assertEquals(1, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - - } - - @Test(enabled = true, description = "Sign permission transaction by invalid address") - public void test07SignByStringKey() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - String emptyKey = "abc1222"; - - logger.info("** update active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + emptyKey + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed - .getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - - ownerPermissionKeys.add(emptyKey); - - boolean ret = false; - try { - GrpcAPI.Return response = PublicMethedForMutiSign - .accountPermissionUpdateForResponse(accountPermissionJson, ownerKey.getBytes(), ownerKey, - blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()])); - } catch (NullPointerException e) { - logger.info("NullPointerException !"); - ret = true; - } - Assert.assertTrue(ret); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - } - - @Test(enabled = true, description = "Set same permission") - public void test08RepeatUpdateSamePermission() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - PublicMethedForMutiSign - .recoverAccountPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - PublicMethedForMutiSign - .recoverAccountPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - Assert.assertEquals(1, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @Test(enabled = true, description = "Sign permission transaction " - + "by active address and default permissionId") - public void test09SignListMoreThanPermissionKeys() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - PublicMethed.printAddress(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}" + "]}]}"; - - ownerPermissionKeys.add(testKey002); - ownerPermissionKeys.add(ownerKey); - - GrpcAPI.Return response = PublicMethedForMutiSign - .accountPermissionUpdateForResponse(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()])); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(SIGERROR, response.getCode()); - Assert.assertEquals( - "validate signature error Signature count " + "is 2 more than key counts of permission : 1", - response.getMessage().toStringUtf8()); - - Assert.assertEquals(1, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission() - .getKeysCount()); - - PublicMethedForMutiSign.printPermissionList( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList()); - - System.out.printf(PublicMethedForMutiSign.printPermission( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getOwnerPermission())); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign23.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign23.java deleted file mode 100644 index 732fc3838a1..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign23.java +++ /dev/null @@ -1,1015 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.hamcrest.CoreMatchers.containsString; -import static org.tron.api.GrpcAPI.TransactionSignWeight.Result.response_code.ENOUGH_PERMISSION; -import static org.tron.api.GrpcAPI.TransactionSignWeight.Result.response_code.NOT_ENOUGH_PERMISSION; -import static org.tron.api.GrpcAPI.TransactionSignWeight.Result.response_code.PERMISSION_ERROR; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.GrpcAPI.TransactionSignWeight; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.contract.AccountContract.AccountPermissionUpdateContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign23 { - - private static final String AVAILABLE_OPERATION = - "7fff1fc0037e0000000000000000000000000000000000000000000000000000"; - private static final String DEFAULT_OPERATION = - "7fff1fc0033e0000000000000000000000000000000000000000000000000000"; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Add sign for multi sign normal transaction") - public void test01MultiSignNormalTransaction() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2 + multiSignFee; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(witnessKey001); - activePermissionKeys.add(tmpKey02); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner1\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(1, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Transaction transaction = PublicMethedForMutiSign - .sendcoin2(fromAddress, 1000_000, ownerAddress, ownerKey, blockingStubFull); - - Transaction transaction1 = PublicMethedForMutiSign.addTransactionSignWithPermissionId( - transaction, tmpKey02, 2, blockingStubFull); - - Transaction transaction2 = PublicMethedForMutiSign.addTransactionSignWithPermissionId( - transaction1, witnessKey001, 2, blockingStubFull); - - logger.info("transaction hex string is " + ByteArray.toHexString(transaction2.toByteArray())); - - TransactionSignWeight txWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("TransactionSignWeight info : " + txWeight); - - Assert.assertTrue(PublicMethedForMutiSign.broadcastTransaction(transaction2, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - PublicMethedForMutiSign - .recoverAccountPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - - txWeight = PublicMethedForMutiSign.getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("TransactionSignWeight info : " + txWeight); - - Transaction transaction3 = PublicMethedForMutiSign - .sendcoin2(fromAddress, 1000_000, ownerAddress, ownerKey, blockingStubFull); - - Transaction transaction4 = PublicMethedForMutiSign.addTransactionSignWithPermissionId( - transaction, tmpKey02, 2, blockingStubFull); - Assert.assertFalse(PublicMethedForMutiSign.broadcastTransaction(transaction3,blockingStubFull)); - Assert.assertFalse(PublicMethedForMutiSign.broadcastTransaction(transaction4,blockingStubFull)); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - - } - - - @Test(enabled = true, description = "Add sign for multi sign permission transaction") - public void test02MultiSignPermissionTransaction() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2 + multiSignFee; - - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(ownerKey); - - Integer[] ints = {ContractType.AccountPermissionUpdateContract_VALUE}; - String operations = PublicMethedForMutiSign.getOperations(ints); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner1\"," - + "\"threshold\":5,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"" + operations + "\",\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(testKey002); - activePermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a permission transaction"); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - Transaction transaction = PublicMethedForMutiSign.accountPermissionUpdateWithoutSign( - accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()])); - - Transaction transaction1 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction, tmpKey02, 2, blockingStubFull); - - Transaction transaction2 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction1, ownerKey, 2, blockingStubFull); - - TransactionSignWeight txWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("TransactionSignWeight info : " + txWeight); - - Assert.assertTrue(PublicMethedForMutiSign.broadcastTransaction(transaction2, blockingStubFull)); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @Test(enabled = true, description = "" - + "Add sign for single sign normal transaction,get approve list") - public void test03SingleSignNormalTransaction() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(ownerKey); - - Integer[] ints = {ContractType.TransferContract_VALUE}; - String operations = PublicMethedForMutiSign.getOperations(ints); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner1\"," - + "\"threshold\":5,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"" + operations + "\",\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission()); - - logger.info("** trigger a normal transaction"); - Transaction transaction = PublicMethedForMutiSign - .sendcoin2(fromAddress, 1000_000, ownerAddress, ownerKey, blockingStubFull); - - Transaction transaction1 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction, tmpKey02, 2, blockingStubFull); - - TransactionSignWeight txWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("TransactionSignWeight info : " + txWeight); - - Assert.assertTrue(PublicMethedForMutiSign.broadcastTransaction(transaction1, blockingStubFull)); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - - GrpcAPI.TransactionApprovedList transactionApprovedList = PublicMethed - .getTransactionApprovedList(transaction1, blockingStubFull); - - logger.info("transactionApprovedList:" + transactionApprovedList); - Assert.assertEquals(Base58.encode58Check(tmpAddr02), Base58 - .encode58Check(transactionApprovedList.getApprovedList(0).toByteArray())); - Assert.assertEquals(2, - transactionApprovedList.getTransaction().getTransaction().getRawData().getContract(0) - .getPermissionId()); - Assert.assertEquals(1, transactionApprovedList.getApprovedListCount()); - - } - - @Test(enabled = true, description = "Add sign for normal transaction " - + "with address not in permission list") - public void test06SignFailedTransaction() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - long needCoin = updateAccountPermissionFee; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner1\"," - + "\"threshold\":5,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"" + AVAILABLE_OPERATION + "\",\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission()); - - ownerPermissionKeys.add(testKey002); - activePermissionKeys.add(tmpKey02); - - logger.info("** trigger a normal transaction"); - Transaction transaction = PublicMethedForMutiSign - .sendcoin2(fromAddress, 1000_000, ownerAddress, ownerKey, blockingStubFull); - - Transaction transaction1 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction, testKey002, 2, blockingStubFull); - - TransactionSignWeight txWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("TransactionSignWeight info : " + txWeight); - - Assert - .assertFalse(PublicMethedForMutiSign.broadcastTransaction(transaction1, blockingStubFull)); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - } - - @Test(enabled = true, description = "Add sign for timeout normal transaction,get approve list") - public void test07TimeoutTransaction() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - ownerPermissionKeys.add(testKey002); - activePermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner1\"," - + "\"threshold\":5,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"" + AVAILABLE_OPERATION + "\",\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission()); - - ownerPermissionKeys.add(testKey002); - activePermissionKeys.add(tmpKey02); - - logger.info("** trigger a normal transaction"); - Transaction transaction = PublicMethedForMutiSign - .sendcoin2(fromAddress, 1000_000, ownerAddress, ownerKey, blockingStubFull); - - try { - Thread.sleep(70000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - Transaction transaction1 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction, tmpKey02, 2, blockingStubFull); - - TransactionSignWeight txWeight = PublicMethedForMutiSign.getTransactionSignWeight( - transaction1, blockingStubFull); - logger.info("TransactionSignWeight info : " + txWeight); - - Assert - .assertFalse(PublicMethedForMutiSign.broadcastTransaction(transaction1, blockingStubFull)); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - GrpcAPI.TransactionApprovedList transactionApprovedList = PublicMethed - .getTransactionApprovedList(transaction1, blockingStubFull); - - logger.info("transactionApprovedList:" + transactionApprovedList); - logger.info("Base58.encode58Check(test001Address)1:" + Base58 - .encode58Check(transactionApprovedList.getApprovedList(0).toByteArray())); - Assert.assertEquals(1, transactionApprovedList.getApprovedListCount()); - Assert.assertEquals(Base58.encode58Check(tmpAddr02), Base58 - .encode58Check(transactionApprovedList.getApprovedList(0).toByteArray())); - Assert.assertEquals(2, - transactionApprovedList.getTransaction().getTransaction().getRawData().getContract(0) - .getPermissionId()); - - } - - @Test(enabled = true, description = "Add sign for empty transaction,get approve list") - public void test08EmptyTransaction() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - - logger.info("** created an empty transaction"); - - AccountPermissionUpdateContract.Builder builder = - AccountPermissionUpdateContract.newBuilder(); - - AccountPermissionUpdateContract contract = builder.build(); - TransactionExtention transactionExtention = - blockingStubFull.accountPermissionUpdate(contract); - Transaction transaction = transactionExtention.getTransaction(); - - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, ownerKey, blockingStubFull); - - TransactionSignWeight txWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("TransactionSignWeight info : " + txWeight); - - Assert - .assertFalse(PublicMethedForMutiSign.broadcastTransaction(transaction1, blockingStubFull)); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore, balanceAfter); - logger.info("transaction hex string is " + ByteArray.toHexString(transaction.toByteArray())); - GrpcAPI.TransactionApprovedList transactionApprovedList = PublicMethed - .getTransactionApprovedList(transaction, blockingStubFull); - logger.info("Before broadcast transactionApprovedList info :\n" + transactionApprovedList); - Assert.assertEquals("class java.lang.IndexOutOfBoundsException : Index: 0", - transactionApprovedList.getResult().getMessage()); - Assert.assertFalse(PublicMethedForMutiSign - .broadcastTransaction(transaction1, blockingStubFull)); - logger.info("transaction hex string is " + ByteArray.toHexString(transaction1.toByteArray())); - transactionApprovedList = PublicMethed - .getTransactionApprovedList(transaction1, blockingStubFull); - Assert.assertEquals("class java.lang.IndexOutOfBoundsException : Index: 0", - transactionApprovedList.getResult().getMessage()); - } - - @Test(enabled = true, description = "Add sign for fake transaction,get approve list") - public void test09ErrorTransaction() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner1\"," - + "\"threshold\":5,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"" + AVAILABLE_OPERATION + "\",\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":2}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(2, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission()); - - ownerPermissionKeys.add(testKey002); - activePermissionKeys.add(tmpKey02); - - logger.info("** trigger a fake transaction"); - Transaction transaction = PublicMethedForMutiSign - .createFakeTransaction(ownerAddress, 1_000_000L, ownerAddress); - Transaction transaction1 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction, tmpKey02, 2, blockingStubFull); - - logger.info("transaction hex string is " + ByteArray.toHexString(transaction1.toByteArray())); - TransactionSignWeight txWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("Before broadcast permission TransactionSignWeight info :\n" + txWeight); - Assert.assertEquals(ENOUGH_PERMISSION, txWeight.getResult().getCode()); - Assert.assertEquals(2, txWeight.getCurrentWeight()); - - Assert - .assertFalse(PublicMethedForMutiSign.broadcastTransaction(transaction1, blockingStubFull)); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - GrpcAPI.TransactionApprovedList transactionApprovedList = PublicMethed - .getTransactionApprovedList(transaction1, blockingStubFull); - Assert.assertEquals(1, transactionApprovedList.getApprovedListCount()); - Assert.assertEquals(Base58.encode58Check(tmpAddr02), Base58 - .encode58Check(transactionApprovedList.getApprovedList(0).toByteArray())); - Assert.assertEquals(2, - transactionApprovedList.getTransaction().getTransaction().getRawData().getContract(0) - .getPermissionId()); - } - - @Test(enabled = true, description = "Add sign transaction with mix order") - public void test10MultiSignNormalTransactionWithMixOrder() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee + multiSignFee; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner1\"," - + "\"threshold\":5,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"" + DEFAULT_OPERATION + "\",\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(3, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission()); - - logger.info("** trigger a normal transaction"); - Transaction transaction = PublicMethedForMutiSign - .sendcoin2(fromAddress, 1000_000, ownerAddress, ownerKey, blockingStubFull); - - logger.info("transaction hex string is " + ByteArray.toHexString(transaction.toByteArray())); - TransactionSignWeight txWeight = PublicMethedForMutiSign.getTransactionSignWeight( - transaction, blockingStubFull); - logger.info("Before Sign TransactionSignWeight info :\n" + txWeight); - Assert.assertEquals(NOT_ENOUGH_PERMISSION, txWeight.getResult().getCode()); - Assert.assertEquals(0, txWeight.getCurrentWeight()); - - Transaction transaction1 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction, tmpKey02, 2, blockingStubFull); - - logger.info("transaction hex string is " + ByteArray.toHexString( - transaction1.toByteArray())); - txWeight = PublicMethedForMutiSign.getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("Before broadcast1 TransactionSignWeight info :\n" + txWeight); - Assert.assertEquals(NOT_ENOUGH_PERMISSION, txWeight.getResult().getCode()); - Assert.assertEquals(1, txWeight.getCurrentWeight()); - - Transaction transaction2 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction1, ownerKey, 2, blockingStubFull); - - logger.info("transaction hex string is " + ByteArray.toHexString(transaction2.toByteArray())); - txWeight = PublicMethedForMutiSign.getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("Before broadcast2 TransactionSignWeight info :\n" + txWeight); - Assert.assertEquals(NOT_ENOUGH_PERMISSION, txWeight.getResult().getCode()); - Assert.assertEquals(2, txWeight.getCurrentWeight()); - - Transaction transaction3 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction2, witnessKey001, 2, blockingStubFull); - - logger.info("transaction hex string is " + ByteArray.toHexString(transaction3.toByteArray())); - txWeight = PublicMethedForMutiSign.getTransactionSignWeight(transaction3, blockingStubFull); - logger.info("Before broadcast2 TransactionSignWeight info :\n" + txWeight); - Assert.assertEquals(ENOUGH_PERMISSION, txWeight.getResult().getCode()); - Assert.assertEquals(3, txWeight.getCurrentWeight()); - - Assert.assertTrue(PublicMethedForMutiSign.broadcastTransaction(transaction3, blockingStubFull)); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - } - - @Test(enabled = true, description = "Add sign transaction with same address") - public void test11MultiSignNormalTransactionBySameAccount() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - logger.info("** update owner and active permission to two address"); - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner1\"," - + "\"threshold\":5,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"" + DEFAULT_OPERATION + "\",\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(3, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission()); - - logger.info("** trigger a normal transaction"); - Transaction transaction = PublicMethedForMutiSign - .sendcoin2(fromAddress, 1000_000, ownerAddress, ownerKey, blockingStubFull); - - logger.info("transaction hex string is " + ByteArray.toHexString(transaction.toByteArray())); - TransactionSignWeight txWeight = - PublicMethedForMutiSign.getTransactionSignWeight(transaction, blockingStubFull); - logger.info("Before Sign TransactionSignWeight info :\n" + txWeight); - Assert.assertEquals(NOT_ENOUGH_PERMISSION, txWeight.getResult().getCode()); - Assert.assertEquals(0, txWeight.getCurrentWeight()); - - Transaction transaction1 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction, tmpKey02, 2, blockingStubFull); - - logger.info("transaction hex string is " + ByteArray.toHexString(transaction1.toByteArray())); - txWeight = PublicMethedForMutiSign.getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("Before broadcast1 TransactionSignWeight info :\n" + txWeight); - Assert.assertEquals(NOT_ENOUGH_PERMISSION, txWeight.getResult().getCode()); - Assert.assertEquals(1, txWeight.getCurrentWeight()); - - Transaction transaction2 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction1, ownerKey, 2, blockingStubFull); - - logger.info("transaction hex string is " + ByteArray.toHexString(transaction2.toByteArray())); - txWeight = PublicMethedForMutiSign.getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("Before broadcast2 TransactionSignWeight info :\n" + txWeight); - Assert.assertEquals(NOT_ENOUGH_PERMISSION, txWeight.getResult().getCode()); - Assert.assertEquals(2, txWeight.getCurrentWeight()); - - Transaction transaction3 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction2, ownerKey, 2, blockingStubFull); - - logger.info("transaction hex string is " + ByteArray.toHexString(transaction3.toByteArray())); - txWeight = PublicMethedForMutiSign.getTransactionSignWeight(transaction3, blockingStubFull); - logger.info("Before broadcast2 TransactionSignWeight info :\n" + txWeight); - Assert.assertEquals(PERMISSION_ERROR, txWeight.getResult().getCode()); - Assert.assertEquals(0, txWeight.getCurrentWeight()); - Assert.assertThat(txWeight.getResult().getMessage(), - containsString("has signed twice!")); - - Assert.assertFalse(PublicMethedForMutiSign.broadcastTransaction( - transaction3, blockingStubFull)); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @Test(enabled = true, description = "Add sign transaction with null address") - public void test12MultiSignNormalTransactionByNullKey() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - long needCoin = updateAccountPermissionFee; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - ownerPermissionKeys.add(ownerKey); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner1\"," - + "\"threshold\":5,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"" + DEFAULT_OPERATION + "\",\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(testKey002); - - Assert.assertEquals(3, - PublicMethedForMutiSign.getActivePermissionKeyCount(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission()); - - logger.info("** trigger a normal transaction"); - Transaction transaction = PublicMethedForMutiSign - .sendcoin2(fromAddress, 1000_000, ownerAddress, ownerKey, blockingStubFull); - - logger.info("transaction hex string is " + ByteArray.toHexString(transaction.toByteArray())); - TransactionSignWeight txWeight = - PublicMethedForMutiSign.getTransactionSignWeight(transaction, blockingStubFull); - logger.info("Before Sign TransactionSignWeight info :\n" + txWeight); - Assert.assertEquals(NOT_ENOUGH_PERMISSION, txWeight.getResult().getCode()); - Assert.assertEquals(0, txWeight.getCurrentWeight()); - - Transaction transaction1 = null; - boolean ret = false; - try { - transaction1 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction, null, 2, blockingStubFull); - } catch (NullPointerException e) { - logger.info("java.lang.NullPointerException"); - ret = true; - } - Assert.assertTrue(ret); - - ret = false; - try { - transaction1 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction, "", 2, blockingStubFull); - } catch (NumberFormatException e) { - logger.info("NumberFormatException: Zero length BigInteger"); - ret = true; - } catch (NullPointerException e) { - logger.info("NullPointerException"); - ret = true; - } - Assert.assertTrue(ret); - - ret = false; - try { - transaction1 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction, "abcd1234", 2, blockingStubFull); - } catch (Exception e) { - logger.info("Exception!!"); - ret = true; - } - Assert.assertFalse(ret); - - logger.info("transaction hex string is " + ByteArray.toHexString(transaction1.toByteArray())); - txWeight = PublicMethedForMutiSign.getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("Before broadcast TransactionSignWeight info :\n" + txWeight); - Assert.assertEquals(PERMISSION_ERROR, txWeight.getResult().getCode()); - Assert.assertEquals(0, txWeight.getCurrentWeight()); - Assert.assertThat(txWeight.getResult().getMessage(), - containsString("but it is not contained of permission")); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign24.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign24.java deleted file mode 100644 index d3e823953fa..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign24.java +++ /dev/null @@ -1,280 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.tron.api.GrpcAPI.TransactionSignWeight.Result.response_code.ENOUGH_PERMISSION; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.GrpcAPI.TransactionSignWeight; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.contract.AccountContract.AccountPermissionUpdateContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign24 { - - private static final String AVAILABLE_OPERATION - = "7fff1fc0037e0000000000000000000000000000000000000000000000000000"; - private static final String DEFAULT_OPERATION - = "7fff1fc0033e0000000000000000000000000000000000000000000000000000"; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] ownerAddress = ecKey1.getAddress(); - private String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] normalAddr001 = ecKey2.getAddress(); - private String normalKey001 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ECKey tmpEcKey01 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr01 = tmpEcKey01.getAddress(); - private String tmpKey01 = ByteArray.toHexString(tmpEcKey01.getPrivKeyBytes()); - private ECKey tmpEcKey02 = new ECKey(Utils.getRandom()); - private byte[] tmpAddr02 = tmpEcKey02.getAddress(); - private String tmpKey02 = ByteArray.toHexString(tmpEcKey02.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Broadcast multi sign normal transaction") - public void test01BroadcastMultiSignNormalTransaction() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee * 2 + multiSignFee * 2; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - PublicMethed.printAddress(ownerKey); - PublicMethed.printAddress(tmpKey02); - - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - ownerPermissionKeys.add(ownerKey); - ownerPermissionKeys.add(testKey002); - activePermissionKeys.add(ownerKey); - - String accountPermissionJson = "{\"owner_permission\":{\"type\":0," - + "\"permission_name\":\"owner1\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.clear(); - ownerPermissionKeys.add(tmpKey02); - ownerPermissionKeys.add(testKey002); - activePermissionKeys.add(witnessKey001); - activePermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Transaction transaction = PublicMethedForMutiSign - .sendcoin2(fromAddress, 1000_000, ownerAddress, ownerKey, blockingStubFull); - - Transaction transaction1 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction, tmpKey02, 0, blockingStubFull); - - Transaction transaction2 = PublicMethedForMutiSign.addTransactionSignWithPermissionId( - transaction1, testKey002, 0, blockingStubFull); - - logger.info("transaction hex string is " + ByteArray.toHexString(transaction2.toByteArray())); - - TransactionSignWeight txWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("TransactionSignWeight info : " + txWeight); - - Assert.assertTrue(PublicMethedForMutiSign.broadcastTransaction(transaction2, blockingStubFull)); - - PublicMethedForMutiSign - .recoverAccountPermission(ownerKey, ownerPermissionKeys, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - txWeight = PublicMethedForMutiSign.getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("TransactionSignWeight info : " + txWeight); - - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - PublicMethed - .unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - - } - - @Test(enabled = true, description = "Broadcast single owner sign normal transaction") - public void test03BroadcastSingleSignNormalTransaction() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey1.getAddress(); - ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - long needCoin = updateAccountPermissionFee; - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, needCoin + 1_000_000, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - List ownerPermissionKeys = new ArrayList<>(); - List activePermissionKeys = new ArrayList<>(); - - PublicMethed.printAddress(ownerKey); - - ownerPermissionKeys.add(ownerKey); - activePermissionKeys.add(ownerKey); - - Integer[] ints = {ContractType.TransferContract_VALUE}; - String operations = PublicMethedForMutiSign.getOperations(ints); - - String accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner1\"," - + "\"threshold\":1,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) + "\",\"weight\":3}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"" + operations + "\",\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, - ownerAddress, ownerKey, blockingStubFull, - ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerPermissionKeys.add(testKey002); - activePermissionKeys.add(tmpKey02); - - Assert.assertEquals(2, PublicMethedForMutiSign.getActivePermissionKeyCount( - PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList())); - - Assert.assertEquals(2, PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission().getKeysCount()); - - PublicMethedForMutiSign.printPermissionList(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getActivePermissionList()); - - System.out - .printf(PublicMethedForMutiSign.printPermission(PublicMethed.queryAccount(ownerAddress, - blockingStubFull).getOwnerPermission())); - - logger.info("** trigger a normal transaction"); - Transaction transaction = PublicMethedForMutiSign - .sendcoin2(fromAddress, 1000_000, ownerAddress, ownerKey, blockingStubFull); - - Transaction transaction1 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction, testKey002, 0, blockingStubFull); - - TransactionSignWeight txWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("TransactionSignWeight info : " + txWeight); - - Assert.assertTrue(PublicMethedForMutiSign.broadcastTransaction(transaction1, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1000000); - - } - - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(ownerAddress, ownerKey, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign26.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign26.java deleted file mode 100644 index 9ae775126c5..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign26.java +++ /dev/null @@ -1,780 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.GrpcAPI.TransactionSignWeight; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Permission; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign26 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - - private final String testWitnesses = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessesKey = PublicMethed.getFinalAddress(testWitnesses); - private ManagedChannel channelFull = null; - private ManagedChannel searchChannelFull = null; - - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidityInFullnode = null; - - private WalletGrpc.WalletBlockingStub searchBlockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] test001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] test002Address = ecKey2.getAddress(); - private String sendAccountKey2 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] test003Address = ecKey3.getAddress(); - String sendAccountKey3 = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] test004Address = ecKey4.getAddress(); - String sendAccountKey4 = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private ECKey ecKey5 = new ECKey(Utils.getRandom()); - byte[] test005Address = ecKey5.getAddress(); - String sendAccountKey5 = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - - } - - - @Test(enabled = true, description = "Sendcoin,use acticve address to sign," - + "not meet the requirements.Delete the address,broadcastTransaction.") - public void testMultiUpdatepermissions_BeforeSign() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = 2 * updateAccountPermissionFee + 1; - - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - final long balance = test001AddressAccount.getBalance(); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0100000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - Assert - .assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert - .assertThat(transactionSignWeight.getResult().getMessage(), - containsString("Permission denied")); - logger.info("transactionSignWeight:" + transactionSignWeight); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - String accountPermissionJson2 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0100000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey4) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson2, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - - Account test001AddressAccount3 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList3 = test001AddressAccount3.getActivePermissionList(); - Permission ownerPermission3 = test001AddressAccount3.getOwnerPermission(); - Permission witnessPermission3 = test001AddressAccount3.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList3); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission3)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission3)); - - final Return returnResult = PublicMethedForMutiSign - .broadcastTransaction1(transaction1, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - long balance3 = test001AddressAccount3.getBalance(); - Assert.assertEquals(balance2 - balance3, updateAccountPermissionFee); - logger.info("returnResult:"); - Assert - .assertThat(returnResult.getCode().toString(), containsString("SIGERROR")); - Assert - .assertThat(returnResult.getMessage().toStringUtf8(), - containsString("Permission denied")); - - - } - - @Test(enabled = true, description = "Sendcoin,use acticve address to sign," - + "meet the all requirements.Delete the address,broadcastTransaction.") - public void testMultiUpdatepermissions_BeforeSign_1() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = 2 * updateAccountPermissionFee + 1; - - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - final long balance = test001AddressAccount.getBalance(); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1, test001Address, 2, dev001Key, - blockingStubFull); - final Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - - GrpcAPI.TransactionApprovedList transactionApprovedList = PublicMethed - .getTransactionApprovedList(transaction, blockingStubFull); - - logger.info("transactionApprovedList:" + transactionApprovedList); - Assert.assertEquals(0, transactionApprovedList.getApprovedListCount()); - Assert.assertEquals(2, - transactionApprovedList.getTransaction().getTransaction().getRawData().getContract(0) - .getPermissionId()); - - String accountPermissionJson2 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey4) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson2, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - Assert - .assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert - .assertThat(transactionSignWeight.getResult().getMessage(), - containsString("but it is not contained of permission")); - final Return returnResult = PublicMethedForMutiSign - .broadcastTransaction1(transaction1, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList2 = test001AddressAccount2.getActivePermissionList(); - Permission ownerPermission2 = test001AddressAccount2.getOwnerPermission(); - Permission witnessPermission2 = test001AddressAccount2.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList2); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission2)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission2)); - Assert - .assertThat(returnResult.getCode().toString(), containsString("SIGERROR")); - Assert - .assertThat(returnResult.getMessage().toStringUtf8(), - containsString("but it is not contained of permission")); - - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1 - balance2, updateAccountPermissionFee); - } - - - @Test(enabled = true, description = "Sendcoin,use owner address to sign," - + "Delete the address,broadcastTransaction.") - public void testMultiUpdatepermissions_BeforeSign_2() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = 2 * updateAccountPermissionFee + 1; - - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - final long balance = test001AddressAccount.getBalance(); - - String[] permissionKeyString = new String[2]; - permissionKeyString[0] = dev001Key; - permissionKeyString[1] = sendAccountKey2; - - String accountPermissionJson1 = - "{\"owner_permission\":{\"type\":0,\"permission_name" - + "\":\"owner\",\"threshold\":1,\"keys\":[{" - + "\"address\":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1, test001Address, 0, dev001Key, - blockingStubFull); - final Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - - String accountPermissionJson2 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address" - + "\":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"" - + "active0\",\"threshold\":1,\"operations\":" - + "\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - String[] permissionKeyString1 = new String[1]; - permissionKeyString1[0] = dev001Key; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson2, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString1)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList2 = test001AddressAccount2.getActivePermissionList(); - Permission ownerPermission2 = test001AddressAccount2.getOwnerPermission(); - final Permission witnessPermission2 = test001AddressAccount2.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList2); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1 - balance2, updateAccountPermissionFee); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission2)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission2)); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transactionSignWeight:" + transactionSignWeight); - Assert - .assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert - .assertThat(transactionSignWeight.getResult().getMessage(), - containsString("but it is not contained of permission")); - Return returnResult = PublicMethedForMutiSign - .broadcastTransaction1(transaction1, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert - .assertThat(returnResult.getCode().toString(), containsString("SIGERROR")); - Assert - .assertThat(returnResult.getMessage().toStringUtf8(), - containsString("but it is not contained of permission")); - Account test001AddressAccount3 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance3 = test001AddressAccount3.getBalance(); - Assert.assertEquals(balance2 - balance3, 0); - } - - @Test(enabled = true, description = "AccountPermissionUpdate transaction," - + "use owner address to sign,Delete the address,broadcastTransaction.") - public void testMultiUpdatepermissions_BeforeSign_3() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = 2 * updateAccountPermissionFee + 1; - - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - final long balance = test001AddressAccount.getBalance(); - - String[] permissionKeyString = new String[2]; - permissionKeyString[0] = dev001Key; - permissionKeyString[1] = sendAccountKey2; - - String accountPermissionJson1 = - "{\"owner_permission\":{\"type\":0,\"permission_name" - + "\":\"owner\",\"threshold\":1,\"keys\":[{" - + "\"address\":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - String accountPermissionJson3 = - "{\"owner_permission\":{\"type\":0,\"permission_name" - + "\":\"owner\",\"threshold\":1,\"keys\":[{" - + "\"address\":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey4) - + "\",\"weight\":1}]}]} "; - - Transaction transaction = PublicMethedForMutiSign - .accountPermissionUpdateWithoutSign(accountPermissionJson3, test001Address, dev001Key, - blockingStubFull, - permissionKeyString); - final Transaction transaction1 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction, sendAccountKey2, 0, blockingStubFull); - String accountPermissionJson2 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address" - + "\":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"" - + "active0\",\"threshold\":1,\"operations\":" - + "\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - String[] permissionKeyString1 = new String[1]; - permissionKeyString1[0] = dev001Key; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson2, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString1)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList2 = test001AddressAccount2.getActivePermissionList(); - Permission ownerPermission2 = test001AddressAccount2.getOwnerPermission(); - Permission witnessPermission2 = test001AddressAccount2.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList2); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission2)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission2)); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1 - balance2, updateAccountPermissionFee); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transactionSignWeight:" + transactionSignWeight); - Assert - .assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert - .assertThat(transactionSignWeight.getResult().getMessage(), - containsString("but it is not contained of permission")); - Return returnResult = PublicMethedForMutiSign - .broadcastTransaction1(transaction1, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert - .assertThat(returnResult.getCode().toString(), containsString("SIGERROR")); - Assert - .assertThat(returnResult.getMessage().toStringUtf8(), - containsString("but it is not contained of permission")); - - Account test001AddressAccount3 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance3 = test001AddressAccount3.getBalance(); - Assert.assertEquals(balance2 - balance3, 0); - } - - - - - @Test(enabled = true, description = "Sendcoin,Delete the owner address," - + "use the address to sign,broadcastTransaction.") - public void testMultiUpdatepermissions_AfterSign() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = 2 * updateAccountPermissionFee + 1; - - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - final long balance = test001AddressAccount.getBalance(); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - logger.info("1-----------------------"); - - final Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1, test001Address, 0, dev001Key, - blockingStubFull); - - String accountPermissionJson2 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(sendAccountKey2) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey4) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson2, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList2 = test001AddressAccount2.getActivePermissionList(); - Permission ownerPermission2 = test001AddressAccount2.getOwnerPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList2); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1 - balance2, updateAccountPermissionFee); - Permission witnessPermission2 = test001AddressAccount2.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission2)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission2)); - - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, dev001Key, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - Assert - .assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert - .assertThat(transactionSignWeight.getResult().getMessage(), - containsString("but it is not contained of permission")); - Assert - .assertFalse(PublicMethedForMutiSign.broadcastTransaction(transaction1, blockingStubFull)); - Account test001AddressAccount3 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance3 = test001AddressAccount3.getBalance(); - Assert.assertEquals(balance2 - balance3, 0); - - } - - @Test(enabled = true, description = "AccountPermissionUpdate transaction," - + "Delete the owner address,use the address to sign,broadcastTransaction.") - public void testMultiUpdatepermissions_AfterSign_4() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = 3 * updateAccountPermissionFee + 1; - - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - final long balance = test001AddressAccount.getBalance(); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - String accountPermissionJson3 = - "{\"owner_permission\":{\"type\":0,\"permission_name" - + "\":\"owner\",\"threshold\":1,\"keys\":[{" - + "\"address\":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey4) - + "\",\"weight\":1}]}]} "; - - final Transaction transaction = PublicMethedForMutiSign - .accountPermissionUpdateWithoutSign(accountPermissionJson3, test001Address, dev001Key, - blockingStubFull, - permissionKeyString); - - String accountPermissionJson2 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(sendAccountKey2) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey4) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson2, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList2 = test001AddressAccount2.getActivePermissionList(); - Permission ownerPermission2 = test001AddressAccount2.getOwnerPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList2); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1 - balance2, updateAccountPermissionFee); - Permission witnessPermission2 = test001AddressAccount2.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission2)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission2)); - - Transaction transaction1 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction, dev001Key, 0, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - Assert - .assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert - .assertThat(transactionSignWeight.getResult().getMessage(), - containsString("but it is not contained of permission")); - Assert - .assertFalse(PublicMethedForMutiSign.broadcastTransaction(transaction1, blockingStubFull)); - - Account test001AddressAccount3 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance3 = test001AddressAccount3.getBalance(); - Assert.assertEquals(balance2 - balance3, 0); - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(test001Address, dev001Key, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign27.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign27.java deleted file mode 100644 index 04fde1798dc..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign27.java +++ /dev/null @@ -1,604 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.GrpcAPI.TransactionSignWeight; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Permission; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign27 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - - private final String testWitnesses = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessesKey = PublicMethed.getFinalAddress(testWitnesses); - private ManagedChannel channelFull = null; - - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] test001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] test002Address = ecKey2.getAddress(); - private String sendAccountKey2 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] test003Address = ecKey3.getAddress(); - String sendAccountKey3 = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] test004Address = ecKey4.getAddress(); - String sendAccountKey4 = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private ECKey ecKey5 = new ECKey(Utils.getRandom()); - byte[] test005Address = ecKey5.getAddress(); - String sendAccountKey5 = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - - } - - - @Test(enabled = true, description = "Sendcoin,use active address sign, meet all requirements." - + "Then use permissionID not same in activelist address to sign," - + "not meet the requirements,broadcastTransaction.") - public void testMultiUpdatepermissions_3() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - final long balance = test001AddressAccount.getBalance(); - - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":" - + "\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations" - + "\":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}]}," - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1,\"operations" - + "\":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, sendAccountKey3, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Signature count is 2 more than key counts of permission : 1")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("Signature count is 2 more than key counts of permission : 1")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - - @Test(enabled = true, description = "Sendcoin,use active address sign, not meet the requirements." - + "Then use permissionID not same in activelist address to sign," - + "not meet the requirements,broadcastTransaction.") - public void testMultiUpdatepermissions_4() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - final long balance = test001AddressAccount.getBalance(); - - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":" - + "\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations" - + "\":\"0100000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}]}," - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1,\"operations" - + "\":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - Assert.assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight.getResult().getMessage(), - containsString("Permission denied")); - - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, sendAccountKey3, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Permission denied")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert - .assertThat(returnResult1.getMessage().toStringUtf8(), containsString("Permission denied")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - - @Test(enabled = true, description = "Sendcoin,use active address sign, meet all requirements." - + "Then use permissionID not same in activelist address to sign," - + "meet all requirements,broadcastTransaction.") - public void testMultiUpdatepermissions_6() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - final long balance = test001AddressAccount.getBalance(); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":" - + "\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations" - + "\":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}]}," - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1,\"operations" - + "\":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1, test001Address, 3, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey3, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - - Transaction transaction2 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction1, sendAccountKey2, 2, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Signature count is 2 more than key counts of permission : 1")); - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("Signature count is 2 more than key counts of permission : 1")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - @Test(enabled = true, description = "Sendcoin,use owner address sign, meet all requirements." - + "Then use not in permissionlist address to sign," - + "not meet the requirements,broadcastTransaction.") - public void testMultiUpdatepermissions_7() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - final long balance = test001AddressAccount.getBalance(); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 0, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, dev001Key, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, sendAccountKey4, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Signature count is 2 more than key counts of permission : 1")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("Signature count is 2 more than key counts of permission : 1")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - - @Test(enabled = true, description = "Sendcoin,use owner address sign, meet all requirements." - + "Then use in active address to sign,not meet the requirements,broadcastTransaction.") - public void testMultiUpdatepermissions_8() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - final long balance = test001AddressAccount.getBalance(); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0100000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 0, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, dev001Key, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - - Transaction transaction2 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction1, sendAccountKey2, 2, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Permission denied")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert - .assertThat(returnResult1.getMessage().toStringUtf8(), containsString("Permission denied")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - @Test(enabled = true, description = "Sendcoin,use owner address sign, meet all requirements." - + "Then use in active address to sign, meet all requirements,broadcastTransaction.") - public void testMultiUpdatepermissions_9() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - final long balance = test001AddressAccount.getBalance(); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1, test001Address, 0, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, dev001Key, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - - Transaction transaction2 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction1, sendAccountKey2, 2, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("but it is not contained of permission")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("but it is not contained of permission")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(test001Address, dev001Key, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign28.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign28.java deleted file mode 100644 index 837488dff2a..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign28.java +++ /dev/null @@ -1,1134 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.GrpcAPI.TransactionSignWeight; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Permission; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign28 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - - private ManagedChannel channelFull = null; - - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] test001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] test002Address = ecKey2.getAddress(); - private String sendAccountKey2 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] test003Address = ecKey3.getAddress(); - String sendAccountKey3 = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] test004Address = ecKey4.getAddress(); - String sendAccountKey4 = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private ECKey ecKey5 = new ECKey(Utils.getRandom()); - byte[] test005Address = ecKey5.getAddress(); - String sendAccountKey5 = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - - } - - - @Test(enabled = true, description = - "Sendcoin permission id 2,use not in permissionlist address sign." - + "Then use in active address permission id 2 to sign ,broadcastTransaction.") - public void testMultiUpdatepermissions_10() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - final long balance = test001AddressAccount.getBalance(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - - PublicMethedForMutiSign.printPermissionList(permissionsList1); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, - blockingStubFull); - - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey4, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - - logger.info("transaction:" + transactionSignWeight); - Assert.assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight.getResult().getMessage(), - containsString("but it is not contained of permission")); - - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, sendAccountKey2, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("but it is not contained of permission")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("but it is not contained of permission")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - - } - - @Test(enabled = true, description = - "Sendcoin permission id 2,use not in permissionlist address sign." - + "Then use in active address to sign,no right to sendcoin,broadcastTransaction.") - public void testMultiUpdatepermissions_11() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - final long balance = test001AddressAccount.getBalance(); - - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0100000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, - blockingStubFull); - - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey4, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - - logger.info("transaction:" + transactionSignWeight); - Assert.assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight.getResult().getMessage(), - containsString("Permission denied")); - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, sendAccountKey2, blockingStubFull); - - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Permission denied")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert - .assertThat(returnResult1.getMessage().toStringUtf8(), containsString("Permission denied")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - - long balance2 = test001AddressAccount2.getBalance(); - logger.info("balance2:" + balance2); - - Assert.assertEquals(balance1, balance2); - - } - - @Test(enabled = true, description = "Sendcoin permission id 2" - + ",use active address in permission id 3 sign." - + "Then use active address in permission id 2to sign.broadcastTransaction.") - public void testMultiUpdatepermissions_12() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - final long balance = test001AddressAccount.getBalance(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":" - + "\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations" - + "\":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}]}," - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1,\"operations" - + "\":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey3, blockingStubFull); - - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - Assert.assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight.getResult().getMessage(), - containsString("but it is not contained of permission")); - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, sendAccountKey2, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Signature count is 2 more than key counts of permission : 1")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("Signature count is 2 more than key counts of permission : 1")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - @Test(enabled = true, description = "Sendcoin,use active address sign, meet all requirements." - + "sum weight > threshold") - public void testMultiUpdatepermissions_13() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + multiSignFee + 1; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - long balance = test001AddressAccount.getBalance(); - - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - final long balance1 = test001AddressAccount1.getBalance(); - - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey3, blockingStubFull); - - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, sendAccountKey2, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("returnResult1:" + returnResult1); - Assert.assertTrue(returnResult1.getResult()); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1 - balance2, multiSignFee + 1); - - - } - - @Test(enabled = true, description = "Sendcoin,use active address sign, meet all requirements." - + "Then use permissionId not same in active address to sign,broadcastTransaction.") - public void testMultiUpdatepermissions_14() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - final long balance = test001AddressAccount.getBalance(); - - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":" - + "\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations" - + "\":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}]}," - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1,\"operations" - + "\":\"0100000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]}"; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - Assert.assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("ENOUGH_PERMISSION")); - - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, sendAccountKey3, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Signature count is 2 more than key counts of permission : 1")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("Signature count is 2 more than key counts of permission : 1")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - @Test(enabled = true, description = "Sendcoin,use active address sign, not meet the requirements." - + "Then use permissionId not same active address to sign,broadcastTransaction.") - public void testMultiUpdatepermissions_15() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - final long balance = test001AddressAccount.getBalance(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":" - + "\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations" - + "\":\"0100000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}]}," - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1,\"operations" - + "\":\"0100000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]}"; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey3, blockingStubFull); - - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - Assert.assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight.getResult().getMessage(), - containsString("Permission denied")); - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, sendAccountKey2, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Permission denied")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert - .assertThat(returnResult1.getMessage().toStringUtf8(), containsString("Permission denied")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - @Test(enabled = true, description = - "Sendcoin,use not in permissionlist address sign," - + "Then use owner address to sign,meet all requirements,broadcastTransaction.") - public void testMultiUpdatepermissions_16() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 0, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey4, blockingStubFull); - - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - Assert.assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight.getResult().getMessage(), - containsString("but it is not contained of permission")); - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, dev001Key, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Signature count is 2 more than key counts of permission : 1")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("Signature count is 2 more than key counts of permission : 1")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - @Test(enabled = true, description = - "Sendcoin,use not in permissionlist address sign, meet all requirements." - + "Then use owner address to sign,,broadcastTransaction.") - public void testMultiUpdatepermissions_17() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey4, blockingStubFull); - - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - Assert.assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight.getResult().getMessage(), - containsString("but it is not contained of permission")); - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, dev001Key, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("but it is not contained of permission")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("but it is not contained of permission")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - @Test(enabled = true, description = "Sendcoin permission id 2" - + ",use active address sign, meet all requirements." - + "Then use owner address to sign,broadcastTransaction.") - public void testMultiUpdatepermissions_18() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, dev001Key, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("but it is not contained of permission")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("but it is not contained of permission")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - @Test(enabled = true, description = "Sendcoin permission id 2" - + ",use active address sign, meet all requirements." - + "Then use owner address to sign with permission id 0,broadcastTransaction.") - public void testMultiUpdatepermissions_19() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - final long balance = test001AddressAccount.getBalance(); - - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - - Transaction transaction2 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction1, dev001Key, 0, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Signature count is 2 more than key counts of permission : 1")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("Signature count is 2 more than key counts of permission : 1")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - @Test(enabled = true, description = "Sendcoin permission id 2,use owner address sign." - + "Then use active address to sign, meet permission id.broadcastTransaction.") - public void testMultiUpdatepermissions_20() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - long balance = test001AddressAccount.getBalance(); - - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - final long balance1 = test001AddressAccount1.getBalance(); - - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, dev001Key, blockingStubFull); - - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - - Transaction transaction2 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction1, sendAccountKey2, 2, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("but it is not contained of permission")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("but it is not contained of permission")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - @Test(enabled = true, description = "Sendcoin permission id 2" - + ",use not in permissionlist address sign." - + "Then use owner address to sign,broadcastTransaction.") - public void testMultiUpdatepermissions_21() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - final long balance = test001AddressAccount.getBalance(); - - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey4, blockingStubFull); - - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - - Transaction transaction2 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction1, dev001Key, 2, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("but it is not contained of permission")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("but it is not contained of permission")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(test001Address, dev001Key, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign29.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign29.java deleted file mode 100644 index 254e166a4a7..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign29.java +++ /dev/null @@ -1,656 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.GrpcAPI.TransactionSignWeight; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Permission; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign29 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - - private ManagedChannel channelFull = null; - - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] test001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] test002Address = ecKey2.getAddress(); - private String sendAccountKey2 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] test003Address = ecKey3.getAddress(); - String sendAccountKey3 = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] test004Address = ecKey4.getAddress(); - String sendAccountKey4 = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private ECKey ecKey5 = new ECKey(Utils.getRandom()); - byte[] test005Address = ecKey5.getAddress(); - String sendAccountKey5 = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - - } - - - @Test(enabled = true, description = "Sendcoin,use active address sign, not meet the requirements." - + "Then use permissionID same in active address to sign,broadcastTransaction.") - public void testMultiUpdatepermissions_23() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 2000000; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"" - + "owner\",\"threshold\":1,\"keys\":[{\"address\":\"" + "" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name" - + "\":\"active0\",\"threshold\":1,\"operations\":\"" - + "0100000000000000000000000000000000000000000000000000000000000000\"" - + ",\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) + "\"," - + "\"weight\":1},{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - Assert.assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight.getResult().getMessage(), - containsString("Permission denied")); - - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, sendAccountKey3, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - logger.info("transaction:" + transactionSignWeight); - Assert.assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight.getResult().getMessage(), - containsString("Permission denied")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("validate signature error Permission denied")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - @Test(enabled = true, description = "Sendcoin with permission id 0,use owner address sign," - + "Then use owner address to sign, sum weight > threshold,broadcastTransaction.") - public void testMultiUpdatepermissions_24() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 2000000; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":" - + "\"owner\",\"threshold\":1,\"keys\":[{\"address\":" + "\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed - .getAddressString(sendAccountKey2) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1,\"operations\":" - + "\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 0, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, dev001Key, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - logger.info("returnResult1:" + returnResult1); - Assert.assertTrue(returnResult1.getResult()); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1 - balance2, multiSignFee + 1); - - } - - - @Test(enabled = true, description = "Sendcoin,use active address sign, not meet the requirements." - + "Then use owner address to sign, not meet the requirements,broadcastTransaction.") - public void testMultiUpdatepermissions_25() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1000000; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"" - + "owner\",\"threshold\":1,\"keys\":[{\"address\":\"" + "" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name" - + "\":\"active0\",\"threshold\":1,\"operations\":\"" - + "0100000000000000000000000000000000000000000000000000000000000000\"" - + ",\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) + "\"," - + "\"weight\":1},{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - Assert.assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight.getResult().getMessage(), - containsString("Permission denied")); - - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, dev001Key, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Permission denied")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("validate signature error Permission denied")); - - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - - @Test(enabled = true, description = "Sendcoin,use active address sign, not meet the requirements." - + "Then use owner address to sign with permission id 0,broadcastTransaction.") - public void testMultiUpdatepermissions_27() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1000000; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"" - + "owner\",\"threshold\":1,\"keys\":[{\"address\":\"" + "" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name" - + "\":\"active0\",\"threshold\":1,\"operations\":\"" - + "0100000000000000000000000000000000000000000000000000000000000000\"" - + ",\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) + "\"," - + "\"weight\":1},{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - Assert.assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight.getResult().getMessage(), - containsString("Permission denied")); - - Transaction transaction2 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction1, dev001Key, 0, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Signature count is 2 more than key counts of permission : 1")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("Signature count is 2 more than key counts of permission : 1")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - - @Test(enabled = true, description = "Sendcoin,use active address sign,meet all requirements." - + "Then use owner address to sign with permission id 0,broadcastTransaction.") - public void testMultiUpdatepermissions_28() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1000000; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"" - + "owner\",\"threshold\":1,\"keys\":[{\"address\":\"" + "" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name" - + "\":\"active0\",\"threshold\":1,\"operations\":\"" - + "0200000000000000000000000000000000000000000000000000000000000000\"" - + ",\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) + "\"," - + "\"weight\":1},{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - - Transaction transaction2 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction1, dev001Key, 0, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Signature count is 2 more than key counts of permission : 1")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("Signature count is 2 more than key counts of permission : 1")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - @Test(enabled = true, description = "Sendcoin,use owner address sign, meet all requirements." - + "Then use active address to sign no permission id,broadcastTransaction.") - public void testMultiUpdatepermissions_29() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1000000; - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"" - + "owner\",\"threshold\":1,\"keys\":[{\"address\":\"" + "" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name" - + "\":\"active0\",\"threshold\":1,\"operations\":\"" - + "0200000000000000000000000000000000000000000000000000000000000000\"" - + ",\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) + "\"," - + "\"weight\":1},{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance, balance1, updateAccountPermissionFee); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 0, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, dev001Key, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, sendAccountKey2, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Signature count is 2 more than key counts of permission : 1")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("Signature count is 2 more than key counts of permission : 1")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - @Test(enabled = true, description = "Sendcoin,use owner address sign, meet all requirements." - + "Then use active address to sign with permission id 2,broadcastTransaction.") - public void testMultiUpdatepermissions_30() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1000000; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"" - + "owner\",\"threshold\":1,\"keys\":[{\"address\":\"" + "" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name" - + "\":\"active0\",\"threshold\":1,\"operations\":\"" - + "0200000000000000000000000000000000000000000000000000000000000000\"" - + ",\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) + "\"," - + "\"weight\":1},{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 0, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, dev001Key, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - - Transaction transaction2 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction1, sendAccountKey3, 2, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("but it is not contained of permission")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - logger.info("returnResult1:" + returnResult1); - Assert.assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert.assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("but it is not contained of permission")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - /** - * constructor. - */ - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(test001Address, dev001Key, fromAddress, blockingStubFull); - } - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign30.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign30.java deleted file mode 100644 index 8c3f522d109..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign30.java +++ /dev/null @@ -1,198 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.GrpcAPI.TransactionSignWeight; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Permission; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign30 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - - private ManagedChannel channelFull = null; - - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] test001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] test002Address = ecKey2.getAddress(); - private String sendAccountKey2 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] test003Address = ecKey3.getAddress(); - String sendAccountKey3 = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] test004Address = ecKey4.getAddress(); - String sendAccountKey4 = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private ECKey ecKey5 = new ECKey(Utils.getRandom()); - byte[] test005Address = ecKey5.getAddress(); - String sendAccountKey5 = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - - } - - @Test(enabled = true, description = - "Sendcoin,use active address no right to sendcoin sign(weight< threshold)." - + "Then use the same address to sign(weight>=threshold),broadcastTransaction.") - public void testMultiUpdatepermissions_32() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1000000; - - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\":" - + "\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":2,\"operations\":\"" - + "0100000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey4) - + "\",\"weight\":1}" - + ",{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1, test001Address, 2, dev001Key, - blockingStubFull); - - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey4, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - - logger.info("transaction:" + transactionSignWeight); - Assert - .assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert - .assertThat(transactionSignWeight.getResult().getMessage(), - containsString("Permission denied")); - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, sendAccountKey4, blockingStubFull); - - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Assert - .assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert - .assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Permission denied")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - logger.info("returnResult1:" + returnResult1); - Assert - .assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert - .assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("validate signature error Permission denied")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - } - - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(test001Address, dev001Key, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign31.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign31.java deleted file mode 100644 index 89c7ad0845c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign31.java +++ /dev/null @@ -1,681 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.GrpcAPI.TransactionSignWeight; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Permission; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign31 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - - private final String testWitnesses = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private ManagedChannel channelFull = null; - private ManagedChannel searchChannelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String searchFullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - private ManagedChannel channelSolidity = null; - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] test001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] test002Address = ecKey2.getAddress(); - private String sendAccountKey2 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] test003Address = ecKey3.getAddress(); - String sendAccountKey3 = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] test004Address = ecKey4.getAddress(); - String sendAccountKey4 = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private ECKey ecKey5 = new ECKey(Utils.getRandom()); - byte[] test005Address = ecKey5.getAddress(); - String sendAccountKey5 = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - - } - - - @Test(enabled = true, description = - "Sendcoin,use active address sign, meet all requirements,broadcast,Then use the same" - + " permissionID active address to sign, meet all requirements,broadcast.") - public void testMultiUpdatepermissions_34() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1000000; - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - long balance = test001AddressAccount.getBalance(); - logger.info("balance:" + balance); - PublicMethedForMutiSign.printPermissionList(permissionsList); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"" - + "owner\",\"threshold\":1,\"keys\":[{\"address\":\"" - + "" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name" - + "\":\"active0\",\"threshold\":1,\"operations\":\"" - + "0200000000000000000000000000000000000000000000000000000000000000\"" - + ",\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) + "\"," - + "\"weight\":1},{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - long balance1 = test001AddressAccount1.getBalance(); - logger.info("balance1:" + balance1); - - PublicMethedForMutiSign.printPermissionList(permissionsList1); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, - blockingStubFull); - - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transactionSignWeight:" + transactionSignWeight); - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction1, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("returnResult1:" + returnResult1); - Assert.assertTrue(returnResult1.getResult()); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - logger.info("balance2:" + balance2); - - Assert.assertEquals(balance1 - balance2, 1L); - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, sendAccountKey3, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Return returnResult2 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("returnResult2:" + returnResult2); - Assert - .assertThat(returnResult2.getCode().toString(), containsString("DUP_TRANSACTION_ERROR")); - Account test001AddressAccount3 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance3 = test001AddressAccount3.getBalance(); - Assert.assertEquals(balance3, balance2); - - - } - - - @Test(enabled = true, description = - "Sendcoin,use active address sign," - + "not meet the requirements broadcastTransaction.Then use the same" - + " permissionID active address to sign,broadcastTransaction.") - public void testMultiUpdatepermissions_35() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"" - + "owner\",\"threshold\":1,\"keys\":[{\"address\":\"" - + "" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name" - + "\":\"active0\",\"threshold\":1,\"operations\":\"" - + "0100000000000000000000000000000000000000000000000000000000000000\"" - + ",\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) + "\"," - + "\"weight\":1},{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - Assert - .assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert - .assertThat(transactionSignWeight.getResult().getMessage(), - containsString("Permission denied")); - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction1, blockingStubFull); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - logger.info("balance2:" + balance2); - Assert.assertEquals(balance1, balance2); - - logger.info("returnResult1:" + returnResult1); - Assert - .assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert - .assertThat(returnResult1.getMessage().toStringUtf8().toLowerCase(), - containsString("validate signature error: permission denied".toLowerCase())); - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, sendAccountKey3, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - - logger.info("transaction1:" + transactionSignWeight1); - - Assert - .assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert - .assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Permission denied")); - - Return returnResult2 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - logger.info("returnResult2:" + returnResult2); - Assert - .assertThat(returnResult2.getCode().toString(), containsString("SIGERROR")); - Account test001AddressAccount3 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance3 = test001AddressAccount3.getBalance(); - logger.info("balance3:" + balance3); - Assert.assertEquals(balance3, balance2); - - - } - - @Test(enabled = true, description = - "Sendcoin,use owner address sign, broadcast,Then use other owner address to sign,broadcast.") - public void testMultiUpdatepermissions_36() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":" - + "\"owner\",\"threshold\":1,\"keys\":[{\"address\":" - + "\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1,\"operations\":" - + "\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1, test001Address, 0, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction1, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(returnResult1.getResult()); - - logger.info("returnResult1:" + returnResult1); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1 - balance2, 1); - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, dev001Key, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - - Return returnResult2 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - logger.info("returnResult1:" + returnResult2); - Assert - .assertThat(returnResult2.getCode().toString(), containsString("DUP_TRANSACTION_ERROR")); - Account test001AddressAccount3 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance3 = test001AddressAccount3.getBalance(); - Assert.assertEquals(balance2, balance3); - } - - @Test(enabled = true, description = - "Sendcoin permission id 3,use active address in permission id 2 sign," - + "Then use active address" - + " in permission id 3 to sign, meet all requirements.broadcastTransaction.") - public void testMultiUpdatepermissions_37() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":" - + "\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations" - + "\":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}]}," - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1,\"operations" - + "\":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]}"; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 3, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - Assert - .assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert - .assertThat(transactionSignWeight.getResult().getMessage(), - containsString("but it is not contained of permission")); - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction1, blockingStubFull); - - logger.info("returnResult1:" + returnResult1); - Assert - .assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert - .assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("but it is not contained of permission")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1, balance2); - //Assert.assertTrue(returnResult1.getResult()); - Transaction transaction2 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction1, sendAccountKey3, 3, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - Assert - .assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert - .assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Signature count is 2 more than key counts of permission : 1")); - - Return returnResult2 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - logger.info("returnResult2:" + returnResult2); - Assert - .assertThat(returnResult2.getCode().toString(), containsString("SIGERROR")); - Account test001AddressAccount3 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance3 = test001AddressAccount3.getBalance(); - Assert.assertEquals(balance2, balance3); - - } - - @Test(enabled = true, description = - "Sendcoin,use active address sign meet all requirements,broadcast,Then use active address" - + "in wrong permission id to sign,not meet the requirements.broadcast.") - public void testMultiUpdatepermissions_38() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 2; - - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":" - + "\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations" - + "\":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}]}," - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1,\"operations" - + "\":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]}"; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1, test001Address, 3, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey3, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction1, blockingStubFull); - logger.info("returnResult1:" + returnResult1); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1 - balance2, 1); - - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, sendAccountKey2, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - Assert - .assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert - .assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Signature count is 2 more than key counts of permission : 1")); - - Return returnResult2 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - logger.info("returnResult2:" + returnResult2); - Assert - .assertThat(returnResult2.getCode().toString(), containsString("SIGERROR")); - Account test001AddressAccount3 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance3 = test001AddressAccount3.getBalance(); - Assert.assertEquals(balance3, balance2); - - } - - @Test(enabled = true, description = - "Sendcoin,use active address sign, meet all requirements,Then use the other permissionID " - + "in active address to sign, meet all requirements.broadcastTransaction.") - public void testMultiUpdatepermissions_39() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 2; - - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":" - + "\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations" - + "\":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}]}," - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1,\"operations" - + "\":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]}"; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - long balance1 = test001AddressAccount1.getBalance(); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 3, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey3, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction1, blockingStubFull); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1 - balance2, 1L); - - logger.info("returnResult1:" + returnResult1); - Assert.assertTrue(returnResult1.getResult()); - Transaction transaction2 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction1, sendAccountKey2, 2, blockingStubFull); - - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - Assert - .assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert - .assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Signature count is 2 more than key counts of permission : 1")); - logger.info("transaction1:" + transactionSignWeight1); - - Return returnResult2 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - logger.info("returnResult2:" + returnResult2); - Assert - .assertThat(returnResult2.getCode().toString(), containsString("SIGERROR")); - Account test001AddressAccount3 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance3 = test001AddressAccount3.getBalance(); - Assert.assertEquals(balance3, balance2); - - } - - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(test001Address, dev001Key, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign33.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign33.java deleted file mode 100644 index 3c01db480ad..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign33.java +++ /dev/null @@ -1,168 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Permission; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign33 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - - - private ManagedChannel channelFull = null; - - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] test001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] test002Address = ecKey2.getAddress(); - private String sendAccountKey2 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] test003Address = ecKey3.getAddress(); - String sendAccountKey3 = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] test004Address = ecKey4.getAddress(); - String sendAccountKey4 = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private ECKey ecKey5 = new ECKey(Utils.getRandom()); - byte[] test005Address = ecKey5.getAddress(); - String sendAccountKey5 = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - - } - - @Test(enabled = true, description = "Active address fall back into only myself") - public void testMultiSignActiveAddress() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = 2 * updateAccountPermissionFee; - - Assert.assertTrue( - PublicMethed.sendcoin(test001Address, amount, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":" - + "\"owner\",\"threshold\":1,\"keys\":[{\"address\"" + ":\"" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations" - + "\":\"0100000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(dev001Key) - + "\",\"weight\":1}]}," - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1,\"operations" - + "\":\"0100000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]}"; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - final long balance1 = test001AddressAccount1.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - String accountPermissionJson2 = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"" - + "owner\",\"threshold\":1,\"keys\":[{\"address\":\"" + "" + PublicMethed - .getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name" - + "\":\"active0\",\"threshold\":1,\"operations\":\"" - + "0200000000000000000000000000000000000000000000000000000000000000\"" - + ",\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(dev001Key) + "\"," - + "\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson2, test001Address, dev001Key, - blockingStubFull, 0, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList2 = test001AddressAccount2.getActivePermissionList(); - Permission ownerPermission2 = test001AddressAccount2.getOwnerPermission(); - long balance2 = test001AddressAccount2.getBalance(); - Assert.assertEquals(balance1 - balance2, updateAccountPermissionFee); - Permission witnessPermission2 = test001AddressAccount2.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList2); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission2)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission2)); - - - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(test001Address, dev001Key, fromAddress, blockingStubFull); - } - - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign34.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign34.java deleted file mode 100644 index 649cf12e4e7..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign34.java +++ /dev/null @@ -1,231 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.GrpcAPI.TransactionSignWeight; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Permission; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign34 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - - private final String testWitnesses = Configuration.getByPath("testng.conf") - .getString("witness.key2"); - private final byte[] witnessesKey = PublicMethed.getFinalAddress(testWitnesses); - private ManagedChannel channelFull = null; - - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] test002Address = ecKey2.getAddress(); - private String sendAccountKey2 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] test003Address = ecKey3.getAddress(); - String sendAccountKey3 = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] test004Address = ecKey4.getAddress(); - String sendAccountKey4 = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private ECKey ecKey5 = new ECKey(Utils.getRandom()); - byte[] test005Address = ecKey5.getAddress(); - String sendAccountKey5 = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - - } - - - @Test(enabled = true, description = "SR witness,sendcoin, use witnessPermission address sign.") - public void testMultiUpdatepermissions_42() { - Assert.assertTrue(PublicMethed - .sendcoin(witnessesKey, 1000000000, fromAddress, testKey002, - blockingStubFull)); - Account test001AddressAccount = PublicMethed.queryAccount(witnessesKey, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, witnessesKey, 1, testWitnesses, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, testWitnesses, blockingStubFull); - final TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(witnessesKey, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - final long balance1 = test001AddressAccount1.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - Assert.assertEquals(balance, balance1); - logger.info("transaction:" + transactionSignWeight); - Assert - .assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert - .assertThat(transactionSignWeight.getResult().getMessage(), - containsString("Permission for this, does not exist!")); - - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction1, blockingStubFull); - logger.info("returnResult1:" + returnResult1); - Assert - .assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert - .assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("permission isn't exit")); - - } - - @Test(enabled = true, description = "SR witness,sendcoin, use active address sign.") - public void testMultiUpdatepermissions_43() { - Assert.assertTrue(PublicMethed - .sendcoin(witnessesKey, 1000000000, fromAddress, testKey002, - blockingStubFull)); - Account test001AddressAccount = PublicMethed.queryAccount(witnessesKey, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, witnessesKey, 2, testWitnesses, - blockingStubFull); - final Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, testWitnesses, blockingStubFull); - final TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transaction:" + transactionSignWeight); - Assert - .assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert - .assertThat(transactionSignWeight.getResult().getMessage(), - containsString("Permission for this, does not exist!")); - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction1, blockingStubFull); - logger.info("returnResult1:" + returnResult1); - Account test001AddressAccount1 = PublicMethed.queryAccount(witnessesKey, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - final long balance1 = test001AddressAccount1.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - Assert.assertEquals(balance, balance1); - Assert - .assertThat(returnResult1.getCode().toString(), containsString("SIGERROR")); - Assert - .assertThat(returnResult1.getMessage().toStringUtf8(), - containsString("permission isn't exit")); - - } - - - @Test(enabled = true, description = "SR witness,sendcoin, use owner address sign.") - public void testMultiUpdatepermissions_44() { - Assert.assertTrue(PublicMethed - .sendcoin(witnessesKey, 1000000000, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account test001AddressAccount = PublicMethed.queryAccount(witnessesKey, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info("balance: " + balance); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, witnessesKey, 0, testWitnesses, - blockingStubFull); - final Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, testWitnesses, blockingStubFull); - Return returnResult1 = PublicMethedForMutiSign - .broadcastTransaction1(transaction1, blockingStubFull); - logger.info("returnResult1:" + returnResult1); - Assert.assertTrue(returnResult1.getResult()); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account test001AddressAccount1 = PublicMethed.queryAccount(witnessesKey, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - final long balance1 = test001AddressAccount1.getBalance(); - logger.info("balance1: " + balance1); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - Assert.assertEquals(balance - balance1, 1); - - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign35.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign35.java deleted file mode 100644 index 19db32ab69c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign35.java +++ /dev/null @@ -1,299 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.GrpcAPI.TransactionSignWeight; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Permission; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign35 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - - - private ManagedChannel channelFull = null; - - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] test001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] test002Address = ecKey2.getAddress(); - private String sendAccountKey2 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] test003Address = ecKey3.getAddress(); - String sendAccountKey3 = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] test004Address = ecKey4.getAddress(); - String sendAccountKey4 = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private ECKey ecKey5 = new ECKey(Utils.getRandom()); - byte[] test005Address = ecKey5.getAddress(); - String sendAccountKey5 = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - - } - - @Test(enabled = true, description = "update active operation," - + " use active address meet all requirement") - public void testMultiUpdatepermissions_45() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = 2 * updateAccountPermissionFee; - - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[5]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"" - + "keys\":[{\"address\":\"" + PublicMethed.getAddressString(dev001Key) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey5) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1,\"operations\":\"" - + "7fff1fc0037e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey4) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - final long balance1 = test001AddressAccount1.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - String accountPermissionJson2 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey4) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - String[] permissionKeyString1 = new String[5]; - permissionKeyString1[0] = sendAccountKey4; - Transaction transaction = PublicMethedForMutiSign - .accountPermissionUpdateWithoutSign(accountPermissionJson2, test001Address, dev001Key, - blockingStubFull, - permissionKeyString); - Transaction transaction1 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction, sendAccountKey4, 2, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transactionSignWeight:" + transactionSignWeight); - - Return returnResult = PublicMethedForMutiSign - .broadcastTransaction1(transaction1, blockingStubFull); - logger.info("returnResult:" + returnResult); - Assert.assertTrue(returnResult.getResult()); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList2 = test001AddressAccount2.getActivePermissionList(); - Permission ownerPermission2 = test001AddressAccount2.getOwnerPermission(); - Permission witnessPermission2 = test001AddressAccount2.getWitnessPermission(); - final long balance2 = test001AddressAccount2.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList2); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission2)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission2)); - Assert.assertEquals(balance1 - balance2, updateAccountPermissionFee); - - - } - - @Test(enabled = true, description = "update active operation," - + " use active address no right update sign, broadcast") - public void testMultiUpdatepermissions_46() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee; - - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - final long balance = test001AddressAccount.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[5]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"" - + "keys\":[{\"address\":\"" + PublicMethed.getAddressString(dev001Key) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey5) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1,\"operations\":\"" - + "7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey4) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - final long balance1 = test001AddressAccount1.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - String accountPermissionJson2 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey4) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - String[] permissionKeyString1 = new String[5]; - permissionKeyString1[0] = sendAccountKey4; - Transaction transaction = PublicMethedForMutiSign - .accountPermissionUpdateWithoutSign(accountPermissionJson2, test001Address, dev001Key, - blockingStubFull, - permissionKeyString); - Transaction transaction1 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction, sendAccountKey4, 2, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transactionSignWeight:" + transactionSignWeight); - Assert - .assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert - .assertThat(transactionSignWeight.getResult().getMessage(), - containsString("Permission denied")); - Return returnResult = PublicMethedForMutiSign - .broadcastTransaction1(transaction1, blockingStubFull); - logger.info("returnResult:" + returnResult); - - Assert - .assertThat(returnResult.getCode().toString(), containsString("SIGERROR")); - Assert - .assertThat(returnResult.getMessage().toStringUtf8(), - containsString("Permission denied")); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList2 = test001AddressAccount2.getActivePermissionList(); - Permission ownerPermission2 = test001AddressAccount2.getOwnerPermission(); - Permission witnessPermission2 = test001AddressAccount2.getWitnessPermission(); - final long balance2 = test001AddressAccount2.getBalance(); - PublicMethedForMutiSign.printPermissionList(permissionsList2); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission2)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission2)); - Assert.assertEquals(balance1, balance2); - - - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(test001Address, dev001Key, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign36.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign36.java deleted file mode 100644 index 008194c81e6..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign36.java +++ /dev/null @@ -1,549 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import com.google.protobuf.Any; -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionApprovedList; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Permission; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.contract.BalanceContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign36 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - - private final String testWitnesses = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessesKey = PublicMethed.getFinalAddress(testWitnesses); - private ManagedChannel channelFull = null; - private ManagedChannel searchChannelFull = null; - - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] test001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] test002Address = ecKey2.getAddress(); - private String sendAccountKey2 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] test003Address = ecKey3.getAddress(); - String sendAccountKey3 = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] test004Address = ecKey4.getAddress(); - String sendAccountKey4 = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private ECKey ecKey5 = new ECKey(Utils.getRandom()); - byte[] test005Address = ecKey5.getAddress(); - String sendAccountKey5 = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - @Test(enabled = true, description = "two owner address sign update permission transaction " - + "sum(weight)==threshold,get approve list") - public void getTransactionApprovedList_01() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee; - - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[2]; - permissionKeyString[0] = dev001Key; - permissionKeyString[1] = sendAccountKey2; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":" - + "\"owner\",\"threshold\":2,\"keys\":[{\"address\":" - + "\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1,\"operations\":" - + "\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Transaction transaction = PublicMethedForMutiSign - .accountPermissionUpdateWithoutSign(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, - permissionKeyString); - - Transaction transaction1 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction, dev001Key, 0, blockingStubFull); - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, sendAccountKey2, blockingStubFull); - TransactionApprovedList transactionApprovedList = PublicMethed - .getTransactionApprovedList(transaction2, blockingStubFull); - logger.info("test001Address:" + Base58.encode58Check(test001Address)); - logger.info( - "transactionApprovedList:" + Base58 - .encode58Check(transactionApprovedList.getApprovedList(0).toByteArray())); - Assert.assertEquals(Base58.encode58Check(test001Address), Base58 - .encode58Check(transactionApprovedList.getApprovedList(0).toByteArray())); - Assert.assertEquals(Base58.encode58Check(test002Address), Base58 - .encode58Check(transactionApprovedList.getApprovedList(1).toByteArray())); - Assert.assertEquals(2, transactionApprovedList.getApprovedListCount()); - Assert.assertEquals(0, - transactionApprovedList.getTransaction().getTransaction().getRawData().getContract(0) - .getPermissionId()); - Account test001AddressAccount1 = PublicMethed - .queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - - } - - - @Test(enabled = true, description = - "sendcoin,use active address sign meet all requirement,delete " - + "the used active address," - + "and change active no right to sendcoin. get first transaction approve list") - public void getTransactionApprovedList_02() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = 2 * updateAccountPermissionFee + 1; - - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction, sendAccountKey2, 2, blockingStubFull); - - String accountPermissionJson2 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0100000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey4) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson2, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - TransactionApprovedList transactionApprovedList = PublicMethed - .getTransactionApprovedList(transaction1, blockingStubFull); - - logger.info("transactionSignWeight:" + transactionApprovedList); - logger.info("transactionSignWeight:" + transactionApprovedList); - logger.info("test001Address:" + Base58.encode58Check(test001Address)); - logger.info( - "transactionApprovedList:" + Base58 - .encode58Check(transactionApprovedList.getApprovedList(0).toByteArray())); - Assert.assertEquals(Base58.encode58Check(test002Address), Base58 - .encode58Check(transactionApprovedList.getApprovedList(0).toByteArray())); - Assert.assertEquals(1, transactionApprovedList.getApprovedListCount()); - Assert.assertEquals(2, - transactionApprovedList.getTransaction().getTransaction().getRawData().getContract(0) - .getPermissionId()); - Account test001AddressAccount2 = PublicMethed.queryAccount(sendAccountKey2, blockingStubFull); - List permissionsList2 = test001AddressAccount2.getActivePermissionList(); - Permission ownerPermission2 = test001AddressAccount2.getOwnerPermission(); - Permission witnessPermission2 = test001AddressAccount2.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList2); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission2)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission2)); - - - } - - @Test(enabled = true, description = "sendcoin,use active address sign," - + "sum(weight)==threshold,get approve list") - public void getTransactionApprovedList_03() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":2,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(test005Address, 1L, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - Transaction transaction2 = PublicMethed - .addTransactionSign(transaction1, sendAccountKey3, blockingStubFull); - TransactionApprovedList transactionApprovedList = PublicMethed - .getTransactionApprovedList(transaction2, blockingStubFull); - - logger.info("transactionSignWeight:" + transactionApprovedList); - logger.info("test001Address:" + Base58.encode58Check(test001Address)); - logger.info( - "transactionApprovedList:" + Base58 - .encode58Check(transactionApprovedList.getApprovedList(0).toByteArray())); - Assert.assertEquals(Base58.encode58Check(test002Address), Base58 - .encode58Check(transactionApprovedList.getApprovedList(0).toByteArray())); - Assert.assertEquals(Base58.encode58Check(test003Address), Base58 - .encode58Check(transactionApprovedList.getApprovedList(1).toByteArray())); - Assert.assertEquals(2, transactionApprovedList.getApprovedListCount()); - Assert.assertEquals(2, - transactionApprovedList.getTransaction().getTransaction().getRawData().getContract(0) - .getPermissionId()); - } - - @Test(enabled = true, description = "Multi-signature unfinished transaction,get approve list") - public void getTransactionApprovedList_06() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1; - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":2,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(test005Address, 1L, test001Address, 2, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - TransactionApprovedList transactionApprovedList = PublicMethed - .getTransactionApprovedList(transaction1, blockingStubFull); - - logger.info("transactionSignWeight:" + transactionApprovedList); - logger.info("test001Address:" + Base58.encode58Check(test001Address)); - - Assert.assertEquals(1, transactionApprovedList.getApprovedListCount()); - Assert.assertEquals(Base58.encode58Check(test002Address), Base58 - .encode58Check(transactionApprovedList.getApprovedList(0).toByteArray())); - Assert.assertEquals(2, - transactionApprovedList.getTransaction().getTransaction().getRawData().getContract(0) - .getPermissionId()); - } - - - @Test(enabled = true, description = "sendcoin transaction in owner permission," - + "but sign use active address," - + "get approve list") - public void getTransactionApprovedList_07() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1; - - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":2,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(test005Address, 1L, test001Address, 0, dev001Key, - blockingStubFull); - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, sendAccountKey2, blockingStubFull); - TransactionApprovedList transactionApprovedList = PublicMethed - .getTransactionApprovedList(transaction1, blockingStubFull); - - logger.info("transactionSignWeight:" + transactionApprovedList); - - Assert.assertEquals(1, transactionApprovedList.getApprovedListCount()); - Assert.assertEquals(Base58.encode58Check(test002Address), Base58 - .encode58Check(transactionApprovedList.getApprovedList(0).toByteArray())); - Assert.assertEquals(0, - transactionApprovedList.getTransaction().getTransaction().getRawData().getContract(0) - .getPermissionId()); - } - - - /** - * constructor. - */ - public Protocol.Transaction createFakeTransaction(byte[] toAddrss, Long amount, - byte[] fromAddress) { - - BalanceContract.TransferContract contract = BalanceContract.TransferContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(fromAddress)) - .setToAddress(ByteString.copyFrom(toAddrss)) - .setAmount(amount) - .build(); - Protocol.Transaction transaction = createTransaction(contract, ContractType.TransferContract); - - return transaction; - } - - private Transaction setReference(Transaction transaction, long blockNum, - byte[] blockHash) { - byte[] refBlockNum = ByteArray.fromLong(blockNum); - Transaction.raw rawData = transaction.getRawData().toBuilder() - .setRefBlockHash(ByteString.copyFrom(blockHash)) - .setRefBlockBytes(ByteString.copyFrom(refBlockNum)) - .build(); - return transaction.toBuilder().setRawData(rawData).build(); - } - - - /** - * constructor. - */ - - public Transaction setExpiration(Transaction transaction, long expiration) { - Transaction.raw rawData = transaction.getRawData().toBuilder().setExpiration(expiration) - .build(); - return transaction.toBuilder().setRawData(rawData).build(); - } - - - /** - * constructor. - */ - - public Transaction createTransaction(com.google.protobuf.Message message, - ContractType contractType) { - Transaction.raw.Builder transactionBuilder = Transaction.raw.newBuilder().addContract( - Transaction.Contract.newBuilder().setType(contractType).setParameter( - Any.pack(message)).build()); - - Transaction transaction = Transaction.newBuilder().setRawData(transactionBuilder.build()) - .build(); - - long time = System.currentTimeMillis(); - AtomicLong count = new AtomicLong(); - long gtime = count.incrementAndGet() + time; - String ref = "" + gtime; - - transaction = setReference(transaction, gtime, ByteArray.fromString(ref)); - - transaction = setExpiration(transaction, gtime); - - return transaction; - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(test001Address, dev001Key, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign37.java b/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign37.java deleted file mode 100644 index f9d810ec589..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign37.java +++ /dev/null @@ -1,416 +0,0 @@ -package stest.tron.wallet.dailybuild.multisign; - -import static org.hamcrest.core.StringContains.containsString; - -import com.google.protobuf.Any; -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.GrpcAPI.TransactionSignWeight; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Permission; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MultiSign37 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - - private final String testWitnesses = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessesKey = PublicMethed.getFinalAddress(testWitnesses); - private ManagedChannel channelFull = null; - private ManagedChannel searchChannelFull = null; - - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] test001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] test002Address = ecKey2.getAddress(); - private String sendAccountKey2 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] test003Address = ecKey3.getAddress(); - String sendAccountKey3 = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] test004Address = ecKey4.getAddress(); - String sendAccountKey4 = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private ECKey ecKey5 = new ECKey(Utils.getRandom()); - byte[] test005Address = ecKey5.getAddress(); - String sendAccountKey5 = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - - @Test(enabled = true, description = - "Sendcoin with permission id 0,use owner address sign, weight permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - final Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - long balance = test001AddressAccount.getBalance(); - logger.info("balance:" + balance); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":" - + "\"owner\",\"threshold\":2,\"keys\":[{\"address\":" - + "\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1,\"operations\":" - + "\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - final Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - long balance1 = test001AddressAccount1.getBalance(); - logger.info("balance1:" + balance1); - - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 0, dev001Key, - blockingStubFull); - - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, dev001Key, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transactionSignWeight:" + transactionSignWeight); - Assert - .assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("NOT_ENOUGH_PERMISSION")); - Transaction transaction2 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction1, sendAccountKey3, 2, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - Assert - .assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert - .assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Signature count is 2 more than key counts of permission : 1")); - Return returnResult2 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - logger.info("returnResult2:" + returnResult2); - Assert - .assertThat(returnResult2.getCode().toString(), containsString("SIGERROR")); - Account test001AddressAccount3 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance3 = test001AddressAccount3.getBalance(); - Assert - .assertThat(returnResult2.getMessage().toStringUtf8(), - containsString( - "Signature count is 2 more than key counts of permission : 1")); - Assert.assertEquals(balance1, balance3); - } - - - @Test(enabled = true, description = - "Sendcoin,use owner address sign, not meet all requirements.Then use " - + " active address to sign, not meet all requirements,broadcastTransaction.") - public void testMultiUpdatepermissions_48() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + 1000000; - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - final Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - long balance = test001AddressAccount.getBalance(); - logger.info("balance:" + balance); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":" - + "\"owner\",\"threshold\":2,\"keys\":[{\"address\":" - + "\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1,\"operations\":" - + "\"0100000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - final Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - long balance1 = test001AddressAccount1.getBalance(); - logger.info("balance1:" + balance1); - - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 0, dev001Key, - blockingStubFull); - - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, dev001Key, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transactionSignWeight:" + transactionSignWeight); - Assert.assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("NOT_ENOUGH_PERMISSION")); - Transaction transaction2 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction1, sendAccountKey3, 2, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - Assert.assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("PERMISSION_ERROR")); - Assert.assertThat(transactionSignWeight1.getResult().getMessage(), - containsString("Permission denied")); - Return returnResult2 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - logger.info("returnResult2:" + returnResult2); - Assert - .assertThat(returnResult2.getCode().toString(), containsString("SIGERROR")); - Account test001AddressAccount3 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance3 = test001AddressAccount3.getBalance(); - Assert.assertThat(returnResult2.getMessage().toStringUtf8(), - containsString("Permission denied")); - Assert.assertEquals(balance1, balance3); - } - - @Test(enabled = true, description = - "Sendcoin,use two owner address sign,sum(weight)==threshold,broadcastTransaction.") - public void testMultiUpdatepermissions_49() { - ECKey ecKey = new ECKey(Utils.getRandom()); - test001Address = ecKey.getAddress(); - long amount = updateAccountPermissionFee + multiSignFee + 1000000; - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, amount, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - final Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - long balance = test001AddressAccount.getBalance(); - logger.info("balance:" + balance); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = "{\"owner_permission\":{\"type\":0,\"permission_name\":" - + "\"owner\",\"threshold\":2,\"keys\":[{\"address\":" - + "\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1,\"operations\":" - + "\"0100000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - final Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - long balance1 = test001AddressAccount1.getBalance(); - logger.info("balance1:" + balance1); - - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - Assert.assertEquals(balance - balance1, updateAccountPermissionFee); - - Transaction transaction = PublicMethedForMutiSign - .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 0, dev001Key, - blockingStubFull); - - Transaction transaction1 = PublicMethed - .addTransactionSign(transaction, dev001Key, blockingStubFull); - TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign - .getTransactionSignWeight(transaction1, blockingStubFull); - logger.info("transactionSignWeight:" + transactionSignWeight); - Assert - .assertThat(transactionSignWeight.getResult().getCode().toString(), - containsString("NOT_ENOUGH_PERMISSION")); - Transaction transaction2 = PublicMethedForMutiSign - .addTransactionSignWithPermissionId(transaction1, sendAccountKey2, 0, blockingStubFull); - TransactionSignWeight transactionSignWeight1 = PublicMethedForMutiSign - .getTransactionSignWeight(transaction2, blockingStubFull); - logger.info("transaction1:" + transactionSignWeight1); - Assert - .assertThat(transactionSignWeight1.getResult().getCode().toString(), - containsString("ENOUGH_PERMISSION")); - Return returnResult2 = PublicMethedForMutiSign - .broadcastTransaction1(transaction2, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("returnResult2:" + returnResult2); - Account test001AddressAccount3 = PublicMethed.queryAccount(test001Address, blockingStubFull); - long balance3 = test001AddressAccount3.getBalance(); - Assert.assertEquals(balance1 - balance3, multiSignFee + 1); - Assert.assertTrue(returnResult2.getResult()); - } - - /** - * constructor. - */ - - private Transaction setReference(Transaction transaction, long blockNum, - byte[] blockHash) { - byte[] refBlockNum = ByteArray.fromLong(blockNum); - Transaction.raw rawData = transaction.getRawData().toBuilder() - .setRefBlockHash(ByteString.copyFrom(blockHash)) - .setRefBlockBytes(ByteString.copyFrom(refBlockNum)) - .build(); - return transaction.toBuilder().setRawData(rawData).build(); - } - - - /** - * constructor. - */ - - public Transaction setExpiration(Transaction transaction, long expiration) { - Transaction.raw rawData = transaction.getRawData().toBuilder().setExpiration(expiration) - .build(); - return transaction.toBuilder().setRawData(rawData).build(); - } - - - /** - * constructor. - */ - - public Transaction createTransaction(com.google.protobuf.Message message, - ContractType contractType) { - Transaction.raw.Builder transactionBuilder = Transaction.raw.newBuilder().addContract( - Transaction.Contract.newBuilder().setType(contractType).setParameter( - Any.pack(message)).build()); - - Transaction transaction = Transaction.newBuilder().setRawData(transactionBuilder.build()) - .build(); - - long time = System.currentTimeMillis(); - AtomicLong count = new AtomicLong(); - long gtime = count.incrementAndGet() + time; - String ref = "" + gtime; - - transaction = setReference(transaction, gtime, ByteArray.fromString(ref)); - - transaction = setExpiration(transaction, gtime); - - return transaction; - } - - @AfterMethod - public void aftertest() { - PublicMethed.freedResource(test001Address, dev001Key, fromAddress, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountPermissionUpdateTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountPermissionUpdateTest.java deleted file mode 100644 index 244f75ab280..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountPermissionUpdateTest.java +++ /dev/null @@ -1,192 +0,0 @@ -package stest.tron.wallet.dailybuild.operationupdate; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MutiSignAccountPermissionUpdateTest { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "MutiSign001_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey001 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress01 = PublicMethed.getFinalAddress(testKey001); - private final String operations = Configuration.getByPath("testng.conf") - .getString("defaultParameter.operations"); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ByteString assetAccountId1; - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[2]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey3.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] participateAddress = ecKey4.getAddress(); - String participateKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void testMutiSign1UpdatePermission() { - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - manager2Address = ecKey2.getAddress(); - manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - ecKey3 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey3.getAddress(); - ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - PublicMethed.printAddress(ownerKey); - - long needCoin = updateAccountPermissionFee * 2 + multiSignFee * 3; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - String[] permissionKeyString1 = new String[1]; - permissionKeyString1[0] = ownerKey; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - - logger.info(accountPermissionJson); - String txid = PublicMethedForMutiSign - .accountPermissionUpdateForTransactionId(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - - long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - long netFee = infoById.get().getReceipt().getNetFee(); - long fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + updateAccountPermissionFee); - - balanceBefore = balanceAfter; - String accountPermissionJson1 = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - txid = PublicMethedForMutiSign - .accountPermissionUpdateForTransactionId1(accountPermissionJson1, ownerAddress, ownerKey, - blockingStubFull, 0, ownerKeyString); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertNotNull(txid); - - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - energyFee = infoById.get().getReceipt().getEnergyFee(); - netFee = infoById.get().getReceipt().getNetFee(); - fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - - } - - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountPermissionUpdateTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountPermissionUpdateTest002.java deleted file mode 100644 index bfd91578a42..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountPermissionUpdateTest002.java +++ /dev/null @@ -1,192 +0,0 @@ -package stest.tron.wallet.dailybuild.operationupdate; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MutiSignAccountPermissionUpdateTest002 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "MutiSign001_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey001 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress01 = PublicMethed.getFinalAddress(testKey001); - private final String operations = Configuration.getByPath("testng.conf") - .getString("defaultParameter.operations"); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ByteString assetAccountId1; - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[2]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey3.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] participateAddress = ecKey4.getAddress(); - String participateKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void testMutiSign1UpdatePermission() { - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - manager2Address = ecKey2.getAddress(); - manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - ecKey3 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey3.getAddress(); - ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - PublicMethed.printAddress(ownerKey); - - long needCoin = updateAccountPermissionFee * 2 + multiSignFee * 3; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needCoin, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - String[] permissionKeyString1 = new String[1]; - permissionKeyString1[0] = ownerKey; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - - logger.info(accountPermissionJson); - String txid = PublicMethedForMutiSign - .accountPermissionUpdateForTransactionId(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - - long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - long netFee = infoById.get().getReceipt().getNetFee(); - long fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + updateAccountPermissionFee); - - balanceBefore = balanceAfter; - String accountPermissionJson1 = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - txid = PublicMethedForMutiSign - .accountPermissionUpdateForTransactionId1(accountPermissionJson1, ownerAddress, ownerKey, - blockingStubFull, 2, permissionKeyString); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertNotNull(txid); - - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - energyFee = infoById.get().getReceipt().getEnergyFee(); - netFee = infoById.get().getReceipt().getNetFee(); - fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - - } - - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountTest.java deleted file mode 100644 index 6431929b8a9..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountTest.java +++ /dev/null @@ -1,227 +0,0 @@ -package stest.tron.wallet.dailybuild.operationupdate; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MutiSignAccountTest { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress = PublicMethed.getFinalAddress(witnessKey001); - private String operations = Configuration.getByPath("testng.conf") - .getString("defaultParameter.operations"); - ByteString assetAccountId1; - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[3]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey3.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] newAddress = ecKey4.getAddress(); - String newKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - /** - * constructor. - */ - - public static byte[] randomBytes(int length) { - // generate the random number - byte[] result = new byte[length]; - new Random().nextBytes(result); - result[0] = Wallet.getAddressPreFixByte(); - return result; - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - //operations = "77ff1fc0037e0100000000000000000000000000000000000000000000000000"; - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void testMutiSignForAccount() { - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - manager2Address = ecKey2.getAddress(); - manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - ecKey3 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey3.getAddress(); - ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - PublicMethed.printAddress(ownerKey); - - ecKey4 = new ECKey(Utils.getRandom()); - newAddress = ecKey4.getAddress(); - newKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - - long needCoin = updateAccountPermissionFee * 1 + multiSignFee * 10; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needCoin + 100000000L, fromAddress, testKey002, - blockingStubFull)); - - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - ownerKeyString[2] = manager2Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":3,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - logger.info(accountPermissionJson); - String txid = PublicMethedForMutiSign - .accountPermissionUpdateForTransactionId(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString); - - final String updateName = Long.toString(System.currentTimeMillis()); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(txid); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - long netFee = infoById.get().getReceipt().getNetFee(); - long fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + updateAccountPermissionFee); - - balanceBefore = balanceAfter; - byte[] accountName = String.valueOf(System.currentTimeMillis()).getBytes(); - Assert.assertTrue(PublicMethedForMutiSign.createAccount1( - ownerAddress, newAddress, ownerKey, blockingStubFull, 0, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue( - PublicMethedForMutiSign.setAccountId1(accountName, - ownerAddress, ownerKey, 0, blockingStubFull, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethedForMutiSign.sendcoinWithPermissionId( - newAddress, 100L, ownerAddress, 0, ownerKey, blockingStubFull, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethedForMutiSign.freezeBalanceWithPermissionId( - ownerAddress, 1000000L, 0, 0, ownerKey, blockingStubFull, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethedForMutiSign.freezeBalanceGetEnergyWithPermissionId( - ownerAddress, 1000000L, 0, 1, ownerKey, blockingStubFull, 0, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethedForMutiSign.freezeBalanceGetEnergyWithPermissionId( - ownerAddress, 1000000L, 0, 2, ownerKey, blockingStubFull, 0, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethedForMutiSign.freezeBalanceForReceiverWithPermissionId( - ownerAddress, 1000000L, 0, 0, ByteString.copyFrom(newAddress), - ownerKey, blockingStubFull, 0, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethedForMutiSign.unFreezeBalanceWithPermissionId( - ownerAddress, ownerKey, 0, null, 0, blockingStubFull, ownerKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.unFreezeBalanceWithPermissionId( - ownerAddress, ownerKey, 0, newAddress, 0, blockingStubFull, ownerKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.updateAccountWithPermissionId( - ownerAddress, updateName.getBytes(), ownerKey, blockingStubFull, 0, ownerKeyString)); - - String voteStr = Base58.encode58Check(witnessAddress); - HashMap smallVoteMap = new HashMap(); - smallVoteMap.put(voteStr, "1"); - Assert.assertTrue(PublicMethedForMutiSign.voteWitnessWithPermissionId( - smallVoteMap, ownerAddress, ownerKey, blockingStubFull, 0, ownerKeyString)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, multiSignFee * 11 + 2000000 + 100); - - Assert.assertTrue( - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull)); - - } - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountTest002.java deleted file mode 100644 index 3d6c6e83d46..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAccountTest002.java +++ /dev/null @@ -1,217 +0,0 @@ -package stest.tron.wallet.dailybuild.operationupdate; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MutiSignAccountTest002 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress = PublicMethed.getFinalAddress(witnessKey001); - private final String operations = Configuration.getByPath("testng.conf") - .getString("defaultParameter.operations"); - ByteString assetAccountId1; - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[3]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey3.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] newAddress = ecKey4.getAddress(); - String newKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - /** - * constructor. - */ - - public static byte[] randomBytes(int length) { - // generate the random number - byte[] result = new byte[length]; - new Random().nextBytes(result); - result[0] = Wallet.getAddressPreFixByte(); - return result; - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void testMutiSignForAccount() { - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - manager2Address = ecKey2.getAddress(); - manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - ecKey3 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey3.getAddress(); - ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - PublicMethed.printAddress(ownerKey); - - ecKey4 = new ECKey(Utils.getRandom()); - newAddress = ecKey4.getAddress(); - newKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - - long needCoin = updateAccountPermissionFee * 1 + multiSignFee * 10; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needCoin + 100000000L, fromAddress, testKey002, - blockingStubFull)); - - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - ownerKeyString[2] = manager2Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":3,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - logger.info(accountPermissionJson); - String txid = PublicMethedForMutiSign - .accountPermissionUpdateForTransactionId(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString); - - final String updateName = Long.toString(System.currentTimeMillis()); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(txid); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - long netFee = infoById.get().getReceipt().getNetFee(); - long fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + updateAccountPermissionFee); - - balanceBefore = balanceAfter; - byte[] accountName = "11z2112310".getBytes(); - Assert.assertTrue(PublicMethedForMutiSign.createAccount1( - ownerAddress, newAddress, ownerKey, blockingStubFull, 2, permissionKeyString)); - Assert.assertTrue( - PublicMethedForMutiSign.setAccountId1(accountName, - ownerAddress, ownerKey, 2, blockingStubFull, permissionKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.sendcoinWithPermissionId( - newAddress, 100L, ownerAddress, 2, ownerKey, blockingStubFull, permissionKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.freezeBalanceWithPermissionId( - ownerAddress, 1000000L, 0, 2, ownerKey, blockingStubFull, permissionKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.freezeBalanceGetEnergyWithPermissionId( - ownerAddress, 1000000L, 0, 1, ownerKey, blockingStubFull, 2, permissionKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.freezeBalanceForReceiverWithPermissionId( - ownerAddress, 1000000L, 0, 0, ByteString.copyFrom(newAddress), - ownerKey, blockingStubFull, 2, permissionKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.unFreezeBalanceWithPermissionId( - ownerAddress, ownerKey, 0, null, 2, blockingStubFull, permissionKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.unFreezeBalanceWithPermissionId( - ownerAddress, ownerKey, 0, newAddress, 2, blockingStubFull, permissionKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.updateAccountWithPermissionId( - ownerAddress, updateName.getBytes(), ownerKey, blockingStubFull, 2, permissionKeyString)); - - String voteStr = Base58.encode58Check(witnessAddress); - HashMap smallVoteMap = new HashMap(); - smallVoteMap.put(voteStr, "1"); - Assert.assertTrue(PublicMethedForMutiSign.voteWitnessWithPermissionId( - smallVoteMap, ownerAddress, ownerKey, blockingStubFull, 2, permissionKeyString)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, multiSignFee * 10 + 1000000 + 100); - - Assert.assertTrue( - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull)); - - } - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAssetTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAssetTest.java deleted file mode 100644 index 0b7aaf59c98..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAssetTest.java +++ /dev/null @@ -1,348 +0,0 @@ -package stest.tron.wallet.dailybuild.operationupdate; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MutiSignAssetTest { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "MutiSign001_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey001 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress01 = PublicMethed.getFinalAddress(testKey001); - private final String operations = Configuration.getByPath("testng.conf") - .getString("defaultParameter.operations"); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ByteString assetAccountId1; - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[2]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey3.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] participateAddress = ecKey4.getAddress(); - String participateKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void testMutiSign1CreateAssetissue() { - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - manager2Address = ecKey2.getAddress(); - manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - ecKey3 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey3.getAddress(); - ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - PublicMethed.printAddress(ownerKey); - - long needCoin = updateAccountPermissionFee * 1 + multiSignFee * 3; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needCoin + 2048000000L, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - String[] permissionKeyString1 = new String[1]; - permissionKeyString1[0] = ownerKey; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - - logger.info(accountPermissionJson); - String txid = PublicMethedForMutiSign - .accountPermissionUpdateForTransactionId(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - - long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - long netFee = infoById.get().getReceipt().getNetFee(); - long fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + updateAccountPermissionFee); - - balanceBefore = balanceAfter; - - Long start = System.currentTimeMillis() + 5000; - Long end = System.currentTimeMillis() + 1000000000; - logger.info("try create asset issue"); - - txid = PublicMethedForMutiSign - .createAssetIssueForTransactionId1(ownerAddress, name, totalSupply, 1, - 1, start, end, 1, description, url, 2000L, 2000L, - 1L, 1L, ownerKey, blockingStubFull, 0, ownerKeyString); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertNotNull(txid); - - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - energyFee = infoById.get().getReceipt().getEnergyFee(); - netFee = infoById.get().getReceipt().getNetFee(); - fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + multiSignFee + 1024_000000L); - - logger.info(" create asset end"); - } - - /** - * constructor. - */ - - @Test(enabled = true) - public void testMutiSign2TransferAssetissue() { - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.printAddress(manager1Key); - Account getAssetIdFromOwnerAccount; - getAssetIdFromOwnerAccount = PublicMethed.queryAccount(ownerAddress, blockingStubFull); - assetAccountId1 = getAssetIdFromOwnerAccount.getAssetIssuedID(); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - String txid = PublicMethedForMutiSign.transferAssetForTransactionId1(manager1Address, - assetAccountId1.toByteArray(), 10, ownerAddress, ownerKey, blockingStubFull, - 0, ownerKeyString); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertNotNull(txid); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - long netFee = infoById.get().getReceipt().getNetFee(); - long fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + multiSignFee); - } - - /** - * constructor. - */ - - @Test(enabled = true) - public void testMutiSign3ParticipateAssetissue() { - ecKey4 = new ECKey(Utils.getRandom()); - participateAddress = ecKey4.getAddress(); - participateKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - - long needCoin = updateAccountPermissionFee * 1 + multiSignFee * 2; - - Assert.assertTrue( - PublicMethed.sendcoin(participateAddress, needCoin + 2048000000L, fromAddress, testKey002, - blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(participateAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - ownerKeyString[0] = participateKey; - ownerKeyString[1] = manager1Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(participateKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - logger.info(accountPermissionJson); - String txid = PublicMethedForMutiSign - .accountPermissionUpdateForTransactionId(accountPermissionJson, participateAddress, - participateKey, blockingStubFull, ownerKeyString); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertNotNull(txid); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - long balanceAfter = PublicMethed.queryAccount(participateAddress, blockingStubFull) - .getBalance(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - long netFee = infoById.get().getReceipt().getNetFee(); - long fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + updateAccountPermissionFee); - - balanceBefore = balanceAfter; - - txid = PublicMethedForMutiSign.participateAssetIssueForTransactionId(ownerAddress, - assetAccountId1.toByteArray(), 10, participateAddress, participateKey, 0, - blockingStubFull, ownerKeyString); - - Assert.assertNotNull(txid); - - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - balanceAfter = PublicMethed.queryAccount(participateAddress, blockingStubFull) - .getBalance(); - energyFee = infoById.get().getReceipt().getEnergyFee(); - netFee = infoById.get().getReceipt().getNetFee(); - fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee + 10); - Assert.assertEquals(fee, energyFee + netFee + multiSignFee); - } - - /** - * constructor. - */ - - @Test(enabled = true) - public void testMutiSign4updateAssetissue() { - url = "MutiSign001_update_url" + Long.toString(now); - ownerKeyString[0] = ownerKey; - description = "MutiSign001_update_description" + Long.toString(now); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - String txid = PublicMethedForMutiSign - .updateAssetForTransactionId(ownerAddress, description.getBytes(), url.getBytes(), 100L, - 100L, ownerKey, 0, blockingStubFull, ownerKeyString); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(txid); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - long netFee = infoById.get().getReceipt().getNetFee(); - long fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + multiSignFee); - } - - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAssetTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAssetTest002.java deleted file mode 100644 index cead81819fb..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignAssetTest002.java +++ /dev/null @@ -1,348 +0,0 @@ -package stest.tron.wallet.dailybuild.operationupdate; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MutiSignAssetTest002 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "MutiSign001_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey001 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress01 = PublicMethed.getFinalAddress(testKey001); - private final String operations = Configuration.getByPath("testng.conf") - .getString("defaultParameter.operations"); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ByteString assetAccountId1; - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[2]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey3.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] participateAddress = ecKey4.getAddress(); - String participateKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void testMutiSign1CreateAssetissue() { - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - manager2Address = ecKey2.getAddress(); - manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - ecKey3 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey3.getAddress(); - ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - PublicMethed.printAddress(ownerKey); - - long needCoin = updateAccountPermissionFee * 1 + multiSignFee * 3; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needCoin + 2048000000L, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - String[] permissionKeyString1 = new String[1]; - permissionKeyString1[0] = ownerKey; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - - logger.info(accountPermissionJson); - String txid = PublicMethedForMutiSign - .accountPermissionUpdateForTransactionId(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - - long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - long netFee = infoById.get().getReceipt().getNetFee(); - long fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + updateAccountPermissionFee); - - balanceBefore = balanceAfter; - - Long start = System.currentTimeMillis() + 5000; - Long end = System.currentTimeMillis() + 1000000000; - logger.info("try create asset issue"); - - txid = PublicMethedForMutiSign - .createAssetIssueForTransactionId1(ownerAddress, name, totalSupply, 1, - 1, start, end, 1, description, url, 2000L, 2000L, - 1L, 1L, ownerKey, blockingStubFull, 2, permissionKeyString); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertNotNull(txid); - - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - energyFee = infoById.get().getReceipt().getEnergyFee(); - netFee = infoById.get().getReceipt().getNetFee(); - fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + multiSignFee + 1024_000000L); - - logger.info(" create asset end"); - } - - /** - * constructor. - */ - - @Test(enabled = true) - public void testMutiSign2TransferAssetissue() { - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.printAddress(manager1Key); - Account getAssetIdFromOwnerAccount; - getAssetIdFromOwnerAccount = PublicMethed.queryAccount(ownerAddress, blockingStubFull); - assetAccountId1 = getAssetIdFromOwnerAccount.getAssetIssuedID(); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - String txid = PublicMethedForMutiSign.transferAssetForTransactionId1(manager1Address, - assetAccountId1.toByteArray(), 10, ownerAddress, ownerKey, blockingStubFull, - 2, permissionKeyString); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertNotNull(txid); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - long netFee = infoById.get().getReceipt().getNetFee(); - long fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + multiSignFee); - } - - /** - * constructor. - */ - - @Test(enabled = true) - public void testMutiSign3ParticipateAssetissue() { - ecKey4 = new ECKey(Utils.getRandom()); - participateAddress = ecKey4.getAddress(); - participateKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - - long needCoin = updateAccountPermissionFee * 1 + multiSignFee * 2; - - Assert.assertTrue( - PublicMethed.sendcoin(participateAddress, needCoin + 2048000000L, fromAddress, testKey002, - blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(participateAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - ownerKeyString[0] = participateKey; - ownerKeyString[1] = manager1Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(participateKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - logger.info(accountPermissionJson); - String txid = PublicMethedForMutiSign - .accountPermissionUpdateForTransactionId(accountPermissionJson, participateAddress, - participateKey, blockingStubFull, ownerKeyString); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertNotNull(txid); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - long balanceAfter = PublicMethed.queryAccount(participateAddress, blockingStubFull) - .getBalance(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - long netFee = infoById.get().getReceipt().getNetFee(); - long fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + updateAccountPermissionFee); - - balanceBefore = balanceAfter; - - txid = PublicMethedForMutiSign.participateAssetIssueForTransactionId(ownerAddress, - assetAccountId1.toByteArray(), 10, participateAddress, participateKey, 2, - blockingStubFull, permissionKeyString); - - Assert.assertNotNull(txid); - - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - balanceAfter = PublicMethed.queryAccount(participateAddress, blockingStubFull) - .getBalance(); - energyFee = infoById.get().getReceipt().getEnergyFee(); - netFee = infoById.get().getReceipt().getNetFee(); - fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee + 10); - Assert.assertEquals(fee, energyFee + netFee + multiSignFee); - } - - /** - * constructor. - */ - - @Test(enabled = true) - public void testMutiSign4updateAssetissue() { - url = "MutiSign001_update_url" + Long.toString(now); - ownerKeyString[0] = ownerKey; - description = "MutiSign001_update_description" + Long.toString(now); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - String txid = PublicMethedForMutiSign - .updateAssetForTransactionId(ownerAddress, description.getBytes(), url.getBytes(), 100L, - 100L, ownerKey, 2, blockingStubFull, permissionKeyString); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(txid); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - long netFee = infoById.get().getReceipt().getNetFee(); - long fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + multiSignFee); - } - - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignClearContractAbiTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignClearContractAbiTest.java deleted file mode 100644 index fd873fc0bb3..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignClearContractAbiTest.java +++ /dev/null @@ -1,311 +0,0 @@ -package stest.tron.wallet.dailybuild.operationupdate; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MutiSignClearContractAbiTest { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String operations = Configuration.getByPath("testng.conf") - .getString("defaultParameter.operations"); - ArrayList txidList = new ArrayList(); - Optional infoById = null; - Long beforeTime; - Long afterTime; - Long beforeBlockNum; - Long afterBlockNum; - Block currentBlock; - Long currentBlockNum; - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[2]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey3.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - @Test(enabled = true, threadPoolSize = 1, invocationCount = 1) - public void test1MutiSignForClearContractAbi() { - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - manager2Address = ecKey2.getAddress(); - manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - ecKey3 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey3.getAddress(); - ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - PublicMethed.printAddress(ownerKey); - - long needcoin = updateAccountPermissionFee + multiSignFee * 4; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needcoin + 100000000L, fromAddress, testKey002, - blockingStubFull)); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 1, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - PublicMethed.waitProduceNextBlock(blockingStubFull); - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - logger.info(accountPermissionJson); - PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString); - - Long maxFeeLimit = 1000000000L; - String filePath = "src/test/resources/soliditycode/TriggerConstant004.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] contractAddress = PublicMethedForMutiSign.deployContract1(contractName, abi, code, - "", maxFeeLimit, - 0L, 100, null, ownerKey, ownerAddress, blockingStubFull, 2, permissionKeyString); - logger.info("address:" + Base58.encode58Check(contractAddress)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString() != null); - Assert.assertTrue(PublicMethedForMutiSign - .clearContractAbi(contractAddress, ownerAddress, ownerKey, - blockingStubFull, 2, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue( - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull)); - Assert.assertTrue( - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, ownerAddress, blockingStubFull)); - } - - @Test(enabled = true, threadPoolSize = 1, invocationCount = 1) - public void test2MutiSignForClearContractAbiForDefault() { - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - manager2Address = ecKey2.getAddress(); - manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - ecKey3 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey3.getAddress(); - ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - PublicMethed.printAddress(ownerKey); - - long needcoin = updateAccountPermissionFee + multiSignFee * 4; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needcoin + 100000000L, fromAddress, testKey002, - blockingStubFull)); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 1, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - PublicMethed.waitProduceNextBlock(blockingStubFull); - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - logger.info(accountPermissionJson); - PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString); - - Long maxFeeLimit = 1000000000L; - String filePath = "src/test/resources/soliditycode/TriggerConstant004.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] contractAddress = PublicMethedForMutiSign.deployContract1(contractName, abi, code, - "", maxFeeLimit, - 0L, 100, null, ownerKey, ownerAddress, blockingStubFull, 2, permissionKeyString); - logger.info("address:" + Base58.encode58Check(contractAddress)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString() != null); - Assert.assertTrue(PublicMethedForMutiSign - .clearContractAbi(contractAddress, ownerAddress, ownerKey, - blockingStubFull, 2, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue( - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull)); - Assert.assertTrue( - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, ownerAddress, blockingStubFull)); - } - - - @Test(enabled = true, threadPoolSize = 1, invocationCount = 1) - public void test3MutiSignForClearContractAbiForDefault() { - ecKey3 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey3.getAddress(); - ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - PublicMethed.printAddress(ownerKey); - - long needcoin = updateAccountPermissionFee + multiSignFee * 4; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needcoin + 100000000L, fromAddress, testKey002, - blockingStubFull)); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 1, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - String[] activeDefaultKeyString = new String[1]; - - activeDefaultKeyString[0] = ownerKey; - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long maxFeeLimit = 1000000000L; - String filePath = "src/test/resources/soliditycode/TriggerConstant004.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] contractAddress = PublicMethedForMutiSign.deployContract1(contractName, abi, code, - "", maxFeeLimit, - 0L, 100, null, ownerKey, ownerAddress, blockingStubFull, 2, activeDefaultKeyString); - logger.info("address:" + Base58.encode58Check(contractAddress)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString() != null); - Assert.assertTrue(PublicMethedForMutiSign - .clearContractAbi(contractAddress, ownerAddress, ownerKey, - blockingStubFull, 2, activeDefaultKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue( - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull)); - Assert.assertTrue( - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, ownerAddress, blockingStubFull)); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignExchangeContractTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignExchangeContractTest.java deleted file mode 100644 index 291d28352e4..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignExchangeContractTest.java +++ /dev/null @@ -1,414 +0,0 @@ -package stest.tron.wallet.dailybuild.operationupdate; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.ExchangeList; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Exchange; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MutiSignExchangeContractTest { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = 1000000001L; - private static String name1 = "exchange001_1_" + Long.toString(now); - private static String name2 = "exchange001_2_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String operations = Configuration.getByPath("testng.conf") - .getString("defaultParameter.operations"); - String description = "just-test"; - String url = "https://github.com/tronprotocol/wallet-cli/"; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] exchange001Address = ecKey1.getAddress(); - String exchange001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] secondExchange001Address = ecKey2.getAddress(); - String secondExchange001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - Long secondTransferAssetToFirstAccountNum = 100000000L; - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey3.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey4.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[3]; - String accountPermissionJson = ""; - Account firstAccount; - ByteString assetAccountId1; - ByteString assetAccountId2; - Optional listExchange; - Optional exchangeIdInfo; - Integer exchangeId = 0; - Integer exchangeRate = 10; - Long firstTokenInitialBalance = 10000L; - Long secondTokenInitialBalance = firstTokenInitialBalance * exchangeRate; - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "MutiSign for create token") - public void test1CreateUsedAsset() { - ecKey1 = new ECKey(Utils.getRandom()); - exchange001Address = ecKey1.getAddress(); - exchange001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - secondExchange001Address = ecKey2.getAddress(); - secondExchange001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - PublicMethed.printAddress(exchange001Key); - PublicMethed.printAddress(secondExchange001Key); - - Assert.assertTrue(PublicMethed.sendcoin(exchange001Address, 10240000000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(secondExchange001Address, 10240000000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(exchange001Address), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long start = System.currentTimeMillis() + 5000L; - Long end = System.currentTimeMillis() + 5000000L; - Assert.assertTrue(PublicMethed.createAssetIssue(exchange001Address, name1, totalSupply, 1, - 1, start, end, 1, description, url, 10000L, 10000L, - 1L, 1L, exchange001Key, blockingStubFull)); - Assert.assertTrue(PublicMethed.createAssetIssue(secondExchange001Address, name2, totalSupply, 1, - 1, start, end, 1, description, url, 10000L, 10000L, - 1L, 1L, secondExchange001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "MutiSign for create exchange") - public void test2CreateExchange() { - ecKey3 = new ECKey(Utils.getRandom()); - manager1Address = ecKey3.getAddress(); - manager1Key = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - - ecKey4 = new ECKey(Utils.getRandom()); - manager2Address = ecKey4.getAddress(); - manager2Key = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - - final long needCoin = updateAccountPermissionFee + multiSignFee; - Long balanceBefore = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - PublicMethed.waitProduceNextBlock(blockingStubFull); - ownerKeyString[0] = exchange001Key; - ownerKeyString[1] = manager1Key; - ownerKeyString[2] = manager2Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":3,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(exchange001Key) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - logger.info(accountPermissionJson); - PublicMethedForMutiSign.accountPermissionUpdate( - accountPermissionJson, exchange001Address, exchange001Key, - blockingStubFull, ownerKeyString); - - listExchange = PublicMethed.getExchangeList(blockingStubFull); - final Integer beforeCreateExchangeNum = listExchange.get().getExchangesCount(); - exchangeId = listExchange.get().getExchangesCount(); - - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - assetAccountId1 = getAssetIdFromThisAccount.getAssetIssuedID(); - - getAssetIdFromThisAccount = PublicMethed - .queryAccount(secondExchange001Address, blockingStubFull); - assetAccountId2 = getAssetIdFromThisAccount.getAssetIssuedID(); - - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long token1BeforeBalance = 0L; - for (String name : firstAccount.getAssetMap().keySet()) { - token1BeforeBalance = firstAccount.getAssetMap().get(name); - } - Assert.assertTrue(PublicMethed.transferAsset(exchange001Address, assetAccountId2.toByteArray(), - secondTransferAssetToFirstAccountNum, secondExchange001Address, - secondExchange001Key, blockingStubFull)); - Long token2BeforeBalance = secondTransferAssetToFirstAccountNum; - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //logger.info("name1 is " + name1); - //logger.info("name2 is " + name2); - //logger.info("first balance is " + Long.toString(token1BeforeBalance)); - //logger.info("second balance is " + token2BeforeBalance.toString()); - //CreateExchange - Assert.assertTrue( - PublicMethedForMutiSign.exchangeCreate1( - assetAccountId1.toByteArray(), firstTokenInitialBalance, - assetAccountId2.toByteArray(), secondTokenInitialBalance, exchange001Address, - exchange001Key, blockingStubFull, 0, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - listExchange = PublicMethed.getExchangeList(blockingStubFull); - exchangeId = listExchange.get().getExchangesCount(); - - Long balanceAfter = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1024_000_000L); - - } - - - @Test(enabled = true, description = "Mutisign for inject exchange") - public void test4InjectExchange() { - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - final Long beforeExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - final Long beforeExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - final long needCoin = multiSignFee; - Long balanceBefore = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long beforeToken1Balance = 0L; - Long beforeToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - logger.info("before token 1 balance is " + Long.toString(beforeToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(beforeToken2Balance)); - Integer injectBalance = 100; - Assert.assertTrue( - PublicMethedForMutiSign.injectExchange1( - exchangeId, assetAccountId1.toByteArray(), injectBalance, - exchange001Address, exchange001Key, blockingStubFull, 0, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long afterToken1Balance = 0L; - Long afterToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - afterToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - afterToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - logger.info("before token 1 balance is " + Long.toString(afterToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(afterToken2Balance)); - - Assert.assertTrue(beforeToken1Balance - afterToken1Balance == injectBalance); - Assert.assertTrue(beforeToken2Balance - afterToken2Balance == injectBalance - * exchangeRate); - - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - Long afterExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - Long afterExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - Assert.assertTrue(afterExchangeToken1Balance - beforeExchangeToken1Balance - == injectBalance); - Assert.assertTrue(afterExchangeToken2Balance - beforeExchangeToken2Balance - == injectBalance * exchangeRate); - Long balanceAfter = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @Test(enabled = true, description = "MutiSign for withdraw exchange") - public void test5WithdrawExchange() { - final long needCoin = multiSignFee; - Long balanceBefore = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - final Long beforeExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - final Long beforeExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long beforeToken1Balance = 0L; - Long beforeToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - - logger.info("before token 1 balance is " + Long.toString(beforeToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(beforeToken2Balance)); - Integer withdrawNum = 200; - Assert.assertTrue( - PublicMethedForMutiSign.exchangeWithdraw1( - exchangeId, assetAccountId1.toByteArray(), withdrawNum, - exchange001Address, exchange001Key, blockingStubFull, 0, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long afterToken1Balance = 0L; - Long afterToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - afterToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - afterToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - - logger.info("before token 1 balance is " + Long.toString(afterToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(afterToken2Balance)); - - Assert.assertTrue(afterToken1Balance - beforeToken1Balance == withdrawNum); - Assert.assertTrue(afterToken2Balance - beforeToken2Balance == withdrawNum - * exchangeRate); - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - Long afterExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - Long afterExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - Assert.assertTrue(afterExchangeToken1Balance - beforeExchangeToken1Balance - == -withdrawNum); - Assert.assertTrue(afterExchangeToken2Balance - beforeExchangeToken2Balance - == -withdrawNum * exchangeRate); - Long balanceAfter = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - } - - @Test(enabled = true, description = "MutiSign for transaction exchange") - public void test6TransactionExchange() { - final long needCoin = multiSignFee; - Long balanceBefore = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - final Long beforeExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - final Long beforeExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - logger.info("beforeExchangeToken1Balance" + beforeExchangeToken1Balance); - logger.info("beforeExchangeToken2Balance" + beforeExchangeToken2Balance); - - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long beforeToken1Balance = 0L; - Long beforeToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - - logger.info("before token 1 balance is " + Long.toString(beforeToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(beforeToken2Balance)); - Integer transactionNum = 50; - Assert.assertTrue( - PublicMethedForMutiSign - .exchangeTransaction1(exchangeId, assetAccountId1.toByteArray(), transactionNum, 1, - exchange001Address, exchange001Key, blockingStubFull, 0, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long afterToken1Balance = 0L; - Long afterToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - afterToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - afterToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - logger.info("before token 1 balance is " + Long.toString(afterToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(afterToken2Balance)); - - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - Long afterExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - Long afterExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - logger.info("afterExchangeToken1Balance" + afterExchangeToken1Balance); - logger.info("afterExchangeToken2Balance" + afterExchangeToken2Balance); - Assert.assertTrue(afterExchangeToken1Balance - beforeExchangeToken1Balance - == beforeToken1Balance - afterToken1Balance); - Assert.assertTrue(afterExchangeToken2Balance - beforeExchangeToken2Balance - == beforeToken2Balance - afterToken2Balance); - - Long balanceAfter = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignExchangeContractTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignExchangeContractTest002.java deleted file mode 100644 index 0a04c46a1ca..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignExchangeContractTest002.java +++ /dev/null @@ -1,414 +0,0 @@ -package stest.tron.wallet.dailybuild.operationupdate; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.ExchangeList; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Exchange; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MutiSignExchangeContractTest002 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = 1000000001L; - private static String name1 = "exchange001_1_" + Long.toString(now); - private static String name2 = "exchange001_2_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String operations = Configuration.getByPath("testng.conf") - .getString("defaultParameter.operations"); - String description = "just-test"; - String url = "https://github.com/tronprotocol/wallet-cli/"; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] exchange001Address = ecKey1.getAddress(); - String exchange001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] secondExchange001Address = ecKey2.getAddress(); - String secondExchange001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - Long secondTransferAssetToFirstAccountNum = 100000000L; - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey3.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey4.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[3]; - String accountPermissionJson = ""; - Account firstAccount; - ByteString assetAccountId1; - ByteString assetAccountId2; - Optional listExchange; - Optional exchangeIdInfo; - Integer exchangeId = 0; - Integer exchangeRate = 10; - Long firstTokenInitialBalance = 10000L; - Long secondTokenInitialBalance = firstTokenInitialBalance * exchangeRate; - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "MutiSign for create token") - public void test1CreateUsedAsset() { - ecKey1 = new ECKey(Utils.getRandom()); - exchange001Address = ecKey1.getAddress(); - exchange001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - secondExchange001Address = ecKey2.getAddress(); - secondExchange001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - PublicMethed.printAddress(exchange001Key); - PublicMethed.printAddress(secondExchange001Key); - - Assert.assertTrue(PublicMethed.sendcoin(exchange001Address, 10240000000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(secondExchange001Address, 10240000000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(exchange001Address), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long start = System.currentTimeMillis() + 5000L; - Long end = System.currentTimeMillis() + 5000000L; - Assert.assertTrue(PublicMethed.createAssetIssue(exchange001Address, name1, totalSupply, 1, - 1, start, end, 1, description, url, 10000L, 10000L, - 1L, 1L, exchange001Key, blockingStubFull)); - Assert.assertTrue(PublicMethed.createAssetIssue(secondExchange001Address, name2, totalSupply, 1, - 1, start, end, 1, description, url, 10000L, 10000L, - 1L, 1L, secondExchange001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "MutiSign for create exchange") - public void test2CreateExchange() { - ecKey3 = new ECKey(Utils.getRandom()); - manager1Address = ecKey3.getAddress(); - manager1Key = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - - ecKey4 = new ECKey(Utils.getRandom()); - manager2Address = ecKey4.getAddress(); - manager2Key = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - - final long needCoin = updateAccountPermissionFee + multiSignFee; - Long balanceBefore = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - PublicMethed.waitProduceNextBlock(blockingStubFull); - ownerKeyString[0] = exchange001Key; - ownerKeyString[1] = manager1Key; - ownerKeyString[2] = manager2Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":3,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(exchange001Key) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - logger.info(accountPermissionJson); - PublicMethedForMutiSign.accountPermissionUpdate( - accountPermissionJson, exchange001Address, exchange001Key, - blockingStubFull, ownerKeyString); - - listExchange = PublicMethed.getExchangeList(blockingStubFull); - final Integer beforeCreateExchangeNum = listExchange.get().getExchangesCount(); - exchangeId = listExchange.get().getExchangesCount(); - - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - assetAccountId1 = getAssetIdFromThisAccount.getAssetIssuedID(); - - getAssetIdFromThisAccount = PublicMethed - .queryAccount(secondExchange001Address, blockingStubFull); - assetAccountId2 = getAssetIdFromThisAccount.getAssetIssuedID(); - - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long token1BeforeBalance = 0L; - for (String name : firstAccount.getAssetMap().keySet()) { - token1BeforeBalance = firstAccount.getAssetMap().get(name); - } - Assert.assertTrue(PublicMethed.transferAsset(exchange001Address, assetAccountId2.toByteArray(), - secondTransferAssetToFirstAccountNum, secondExchange001Address, - secondExchange001Key, blockingStubFull)); - Long token2BeforeBalance = secondTransferAssetToFirstAccountNum; - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //logger.info("name1 is " + name1); - //logger.info("name2 is " + name2); - //logger.info("first balance is " + Long.toString(token1BeforeBalance)); - //logger.info("second balance is " + token2BeforeBalance.toString()); - //CreateExchange - Assert.assertTrue( - PublicMethedForMutiSign.exchangeCreate1( - assetAccountId1.toByteArray(), firstTokenInitialBalance, - assetAccountId2.toByteArray(), secondTokenInitialBalance, exchange001Address, - exchange001Key, blockingStubFull, 2, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - listExchange = PublicMethed.getExchangeList(blockingStubFull); - exchangeId = listExchange.get().getExchangesCount(); - - Long balanceAfter = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin + 1024_000_000L); - - } - - - @Test(enabled = true, description = "Mutisign for inject exchange") - public void test4InjectExchange() { - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - final Long beforeExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - final Long beforeExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - final long needCoin = multiSignFee; - Long balanceBefore = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long beforeToken1Balance = 0L; - Long beforeToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - logger.info("before token 1 balance is " + Long.toString(beforeToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(beforeToken2Balance)); - Integer injectBalance = 100; - Assert.assertTrue( - PublicMethedForMutiSign.injectExchange1( - exchangeId, assetAccountId1.toByteArray(), injectBalance, - exchange001Address, exchange001Key, blockingStubFull, 2, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long afterToken1Balance = 0L; - Long afterToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - afterToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - afterToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - logger.info("before token 1 balance is " + Long.toString(afterToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(afterToken2Balance)); - - Assert.assertTrue(beforeToken1Balance - afterToken1Balance == injectBalance); - Assert.assertTrue(beforeToken2Balance - afterToken2Balance == injectBalance - * exchangeRate); - - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - Long afterExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - Long afterExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - Assert.assertTrue(afterExchangeToken1Balance - beforeExchangeToken1Balance - == injectBalance); - Assert.assertTrue(afterExchangeToken2Balance - beforeExchangeToken2Balance - == injectBalance * exchangeRate); - Long balanceAfter = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - @Test(enabled = true, description = "MutiSign for withdraw exchange") - public void test5WithdrawExchange() { - final long needCoin = multiSignFee; - Long balanceBefore = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - final Long beforeExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - final Long beforeExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long beforeToken1Balance = 0L; - Long beforeToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - - logger.info("before token 1 balance is " + Long.toString(beforeToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(beforeToken2Balance)); - Integer withdrawNum = 200; - Assert.assertTrue( - PublicMethedForMutiSign.exchangeWithdraw1( - exchangeId, assetAccountId1.toByteArray(), withdrawNum, - exchange001Address, exchange001Key, blockingStubFull, 2, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long afterToken1Balance = 0L; - Long afterToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - afterToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - afterToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - - logger.info("before token 1 balance is " + Long.toString(afterToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(afterToken2Balance)); - - Assert.assertTrue(afterToken1Balance - beforeToken1Balance == withdrawNum); - Assert.assertTrue(afterToken2Balance - beforeToken2Balance == withdrawNum - * exchangeRate); - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - Long afterExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - Long afterExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - Assert.assertTrue(afterExchangeToken1Balance - beforeExchangeToken1Balance - == -withdrawNum); - Assert.assertTrue(afterExchangeToken2Balance - beforeExchangeToken2Balance - == -withdrawNum * exchangeRate); - Long balanceAfter = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - - } - - @Test(enabled = true, description = "MutiSign for transaction exchange") - public void test6TransactionExchange() { - final long needCoin = multiSignFee; - Long balanceBefore = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - final Long beforeExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - final Long beforeExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - logger.info("beforeExchangeToken1Balance" + beforeExchangeToken1Balance); - logger.info("beforeExchangeToken2Balance" + beforeExchangeToken2Balance); - - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long beforeToken1Balance = 0L; - Long beforeToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - beforeToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - - logger.info("before token 1 balance is " + Long.toString(beforeToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(beforeToken2Balance)); - Integer transactionNum = 50; - Assert.assertTrue( - PublicMethedForMutiSign - .exchangeTransaction1(exchangeId, assetAccountId1.toByteArray(), transactionNum, 1, - exchange001Address, exchange001Key, blockingStubFull, 2, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - firstAccount = PublicMethed.queryAccount(exchange001Address, blockingStubFull); - Long afterToken1Balance = 0L; - Long afterToken2Balance = 0L; - for (String id : firstAccount.getAssetV2Map().keySet()) { - if (assetAccountId1.toStringUtf8().equalsIgnoreCase(id)) { - afterToken1Balance = firstAccount.getAssetV2Map().get(id); - } - if (assetAccountId2.toStringUtf8().equalsIgnoreCase(id)) { - afterToken2Balance = firstAccount.getAssetV2Map().get(id); - } - } - logger.info("before token 1 balance is " + Long.toString(afterToken1Balance)); - logger.info("before token 2 balance is " + Long.toString(afterToken2Balance)); - - exchangeIdInfo = PublicMethed.getExchange(exchangeId.toString(), blockingStubFull); - Long afterExchangeToken1Balance = exchangeIdInfo.get().getFirstTokenBalance(); - Long afterExchangeToken2Balance = exchangeIdInfo.get().getSecondTokenBalance(); - logger.info("afterExchangeToken1Balance" + afterExchangeToken1Balance); - logger.info("afterExchangeToken2Balance" + afterExchangeToken2Balance); - Assert.assertTrue(afterExchangeToken1Balance - beforeExchangeToken1Balance - == beforeToken1Balance - afterToken1Balance); - Assert.assertTrue(afterExchangeToken2Balance - beforeExchangeToken2Balance - == beforeToken2Balance - afterToken2Balance); - - Long balanceAfter = PublicMethed.queryAccount(exchange001Address, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, needCoin); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignMarketAssetTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignMarketAssetTest.java deleted file mode 100644 index da1c25cb649..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignMarketAssetTest.java +++ /dev/null @@ -1,217 +0,0 @@ -package stest.tron.wallet.dailybuild.operationupdate; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.MarketOrder; -import org.tron.protos.Protocol.MarketOrderList; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - - -@Slf4j -public class MutiSignMarketAssetTest { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - ECKey ecKey0 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey0.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey0.getPrivKeyBytes()); - - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[2]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - Assert.assertTrue(PublicMethed - .sendcoin(testAddress001, 20000_000000L, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - - Assert.assertTrue(PublicMethed.createAssetIssue(testAddress001, - "MarketAsset" + start, - 100_000000L, - 1,1, - start, end,1,"MarketAsset","MarketAsset.com",10000L,10000L,1L, 1L,testKey001, - blockingStubFull)); - Long balanceBefore = PublicMethed.queryAccount(testAddress001, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - PublicMethed.waitProduceNextBlock(blockingStubFull); - ownerKeyString[0] = testKey001; - ownerKeyString[1] = testKey002; - - // operation include MarketSellAssetContract(52) - Integer[] ints = {0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 31, - 32, 33, 41, 42, 43, 44, 45, 48, 49, 52, 53}; - String operations = PublicMethedForMutiSign.getOperations(ints); - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(testKey001) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - logger.info(accountPermissionJson); - PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, testAddress001, testKey001, - blockingStubFull, ownerKeyString); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - } - - @Test(enabled = true, description = "MutiSignForMarketSellAsset with active_permissions") - public void testMutiSignForMarketSellAsset001() { - // MarketSellAsset - ByteString assetAccountId = PublicMethed - .queryAccount(testAddress001, blockingStubFull).getAssetIssuedID(); - - int marketOrderCountBefore = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull).get().getOrdersCount(); - - Assert.assertTrue(PublicMethedForMutiSign - .marketSellAsset(testAddress001,assetAccountId.toByteArray(),10,"_".getBytes(),10,2, - permissionKeyString,blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - MarketOrderList marketOrder = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull).get(); - Assert.assertEquals(marketOrderCountBefore + 1, marketOrder.getOrdersCount()); - } - - @Test(enabled = true, description = "MutiSignForMarketSellAsset with owner_permission") - public void testMutiSignForMarketSellAsset002() { - // MarketSellAsset - ByteString assetAccountId = PublicMethed - .queryAccount(testAddress001, blockingStubFull).getAssetIssuedID(); - - int marketOrderCountBefore = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull).get().getOrdersCount(); - - - Assert.assertTrue(PublicMethedForMutiSign - .marketSellAsset(testAddress001,assetAccountId.toByteArray(),10,"_".getBytes(),10,0, - ownerKeyString,blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - MarketOrderList marketOrder = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull).get(); - Assert.assertEquals(marketOrderCountBefore + 1, marketOrder.getOrdersCount()); - } - - - @Test(enabled = true, dependsOnMethods = "testMutiSignForMarketSellAsset001", - description = "MutiSignForMarketOrderCancel with active_permissions") - public void testMutiSignForMarketOrderCancel001() { - // MarketOrderCancel - - ByteString orderId = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull).get().getOrders(0).getOrderId(); - int marketOrderCountBefore = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull).get().getOrdersCount(); - - - Assert.assertTrue(PublicMethedForMutiSign.marketCancelOrder(testAddress001, - orderId.toByteArray(),2,permissionKeyString,blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(marketOrderCountBefore - 1, PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull).get().getOrdersCount()); - - } - - @Test(enabled = true, dependsOnMethods = "testMutiSignForMarketSellAsset002", - description = "MutiSignForMarketOrderCancel with owner_permission") - public void testMutiSignForMarketOrderCancel002() { - // MarketOrderCancel - - ByteString orderId = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull).get().getOrders(0).getOrderId(); - int marketOrderCountBefore = PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull).get().getOrdersCount(); - - - Assert.assertTrue(PublicMethedForMutiSign.marketCancelOrder(testAddress001, - orderId.toByteArray(),0,ownerKeyString,blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(marketOrderCountBefore - 1, PublicMethed - .getMarketOrderByAccount(testAddress001, blockingStubFull).get().getOrdersCount()); - - } - - - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignProposalTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignProposalTest.java deleted file mode 100644 index 68308bda11a..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignProposalTest.java +++ /dev/null @@ -1,170 +0,0 @@ -package stest.tron.wallet.dailybuild.operationupdate; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.ProposalList; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - - -@Slf4j -public class MutiSignProposalTest { - - private static final long now = System.currentTimeMillis(); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key2"); - private final byte[] witness001Address = PublicMethed.getFinalAddress(witnessKey001); - private final String operations = Configuration.getByPath("testng.conf") - .getString("defaultParameter.operations"); - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[2]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true) - public void testMutiSignForProposal() { - long needcoin = updateAccountPermissionFee + multiSignFee * 5; - Assert.assertTrue(PublicMethed.sendcoin(witness001Address, needcoin + 10000000L, - fromAddress, testKey002, blockingStubFull)); - - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - manager2Address = ecKey2.getAddress(); - manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(witness001Address, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - PublicMethed.waitProduceNextBlock(blockingStubFull); - ownerKeyString[0] = witnessKey001; - ownerKeyString[1] = testKey002; - - accountPermissionJson = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\"" - + ",\"threshold\":2,\"keys\":[{\"address\":\"" + PublicMethed - .getAddressString(witnessKey001) + "\"," - + "\"weight\":1},{\"address\":\"" + PublicMethed.getAddressString(testKey002) - + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"owner\",\"threshold\":1," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"7fff1fc0037e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(manager1Key) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}]}]} "; - logger.info(accountPermissionJson); - PublicMethedForMutiSign.accountPermissionUpdate( - accountPermissionJson, witness001Address, witnessKey001, - blockingStubFull, ownerKeyString); - - //Create a proposal - - PublicMethed.waitProduceNextBlock(blockingStubFull); - HashMap proposalMap = new HashMap(); - proposalMap.put(0L, 81000L); - Assert.assertTrue( - PublicMethedForMutiSign.createProposalWithPermissionId(witness001Address, witnessKey001, - proposalMap, 0, blockingStubFull, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Get proposal list - ProposalList proposalList = blockingStubFull.listProposals(EmptyMessage.newBuilder().build()); - Optional listProposals = Optional.ofNullable(proposalList); - final Integer proposalId = listProposals.get().getProposalsCount(); - logger.info(Integer.toString(proposalId)); - - Assert.assertTrue(PublicMethedForMutiSign.approveProposalWithPermission( - witness001Address, witnessKey001, proposalId, - true, 0, blockingStubFull, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Delete proposal list after approve - Assert.assertTrue(PublicMethedForMutiSign.deleteProposalWithPermissionId( - witness001Address, witnessKey001, proposalId, 0, blockingStubFull, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(witness001Address, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignProposalTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignProposalTest002.java deleted file mode 100644 index 8c8a9b14975..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignProposalTest002.java +++ /dev/null @@ -1,169 +0,0 @@ -package stest.tron.wallet.dailybuild.operationupdate; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.ProposalList; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - - -@Slf4j -public class MutiSignProposalTest002 { - - private static final long now = System.currentTimeMillis(); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witness001Address = PublicMethed.getFinalAddress(witnessKey001); - private final String operations = Configuration.getByPath("testng.conf") - .getString("defaultParameter.operations"); - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[1]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true) - public void testMutiSignForProposal() { - long needcoin = updateAccountPermissionFee + multiSignFee * 3; - Assert.assertTrue(PublicMethed.sendcoin(witness001Address, needcoin + 10000000L, - fromAddress, testKey002, blockingStubFull)); - - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - manager2Address = ecKey2.getAddress(); - manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(witness001Address, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - PublicMethed.waitProduceNextBlock(blockingStubFull); - ownerKeyString[0] = witnessKey001; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"owner\",\"threshold\":1,\"" - + "keys\":[{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - logger.info(accountPermissionJson); - PublicMethedForMutiSign.accountPermissionUpdate( - accountPermissionJson, witness001Address, witnessKey001, - blockingStubFull, ownerKeyString); - - //Create a proposal - - PublicMethed.waitProduceNextBlock(blockingStubFull); - HashMap proposalMap = new HashMap(); - proposalMap.put(0L, 81000L); - Assert.assertTrue( - PublicMethedForMutiSign.createProposalWithPermissionId(witness001Address, witnessKey001, - proposalMap, 2, blockingStubFull, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Get proposal list - ProposalList proposalList = blockingStubFull.listProposals(EmptyMessage.newBuilder().build()); - Optional listProposals = Optional.ofNullable(proposalList); - final Integer proposalId = listProposals.get().getProposalsCount(); - logger.info(Integer.toString(proposalId)); - - Assert.assertTrue(PublicMethedForMutiSign.approveProposalWithPermission( - witness001Address, witnessKey001, proposalId, - true, 2, blockingStubFull, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Delete proposal list after approve - Assert.assertTrue(PublicMethedForMutiSign.deleteProposalWithPermissionId( - witness001Address, witnessKey001, proposalId, 2, blockingStubFull, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(witness001Address, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertTrue(balanceBefore - balanceAfter >= needcoin); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignSmartContractTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignSmartContractTest.java deleted file mode 100644 index 522bc66ceb0..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignSmartContractTest.java +++ /dev/null @@ -1,195 +0,0 @@ -package stest.tron.wallet.dailybuild.operationupdate; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Optional; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MutiSignSmartContractTest { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String operations = Configuration.getByPath("testng.conf") - .getString("defaultParameter.operations"); - ArrayList txidList = new ArrayList(); - Optional infoById = null; - Long beforeTime; - Long afterTime; - Long beforeBlockNum; - Long afterBlockNum; - Block currentBlock; - Long currentBlockNum; - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[2]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey3.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - @Test(enabled = true, threadPoolSize = 1, invocationCount = 1) - public void testMutiSignForSmartContract() { - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - manager2Address = ecKey2.getAddress(); - manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - ecKey3 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey3.getAddress(); - ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - PublicMethed.printAddress(ownerKey); - - long needcoin = updateAccountPermissionFee + multiSignFee * 4; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needcoin + 100000000L, fromAddress, testKey002, - blockingStubFull)); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 1, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - PublicMethed.waitProduceNextBlock(blockingStubFull); - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - logger.info(accountPermissionJson); - PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString); - - Random rand = new Random(); - Integer randNum = rand.nextInt(30) + 1; - randNum = rand.nextInt(4000); - - Long maxFeeLimit = 1000000000L; - String contractName = "StorageAndCpu" + Integer.toString(randNum); - String code = Configuration.getByPath("testng.conf") - .getString("code.code_TestStorageAndCpu_storageAndCpu"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_TestStorageAndCpu_storageAndCpu"); - byte[] contractAddress = PublicMethedForMutiSign.deployContract1(contractName, abi, code, - "", maxFeeLimit, - 0L, 100, null, ownerKey, ownerAddress, blockingStubFull, 0, ownerKeyString); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString() != null); - String txid; - String initParmes = "\"" + "930" + "\""; - txid = PublicMethedForMutiSign.triggerContract1(contractAddress, - "testUseCpu(uint256)", initParmes, false, - 0, maxFeeLimit, ownerAddress, ownerKey, blockingStubFull, 0, ownerKeyString); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.getTransactionById(txid, blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue( - PublicMethedForMutiSign.updateSettingWithPermissionId(contractAddress, 50, ownerKey, - ownerAddress, 0, blockingStubFull, ownerKeyString)); - Assert.assertTrue( - PublicMethedForMutiSign.updateEnergyLimitWithPermissionId(contractAddress, 50, ownerKey, - ownerAddress, 0, blockingStubFull, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertTrue( - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull)); - Assert.assertTrue( - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, ownerAddress, blockingStubFull)); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignSmartContractTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignSmartContractTest002.java deleted file mode 100644 index 4d1f891925a..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignSmartContractTest002.java +++ /dev/null @@ -1,195 +0,0 @@ -package stest.tron.wallet.dailybuild.operationupdate; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Optional; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MutiSignSmartContractTest002 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String operations = Configuration.getByPath("testng.conf") - .getString("defaultParameter.operations"); - ArrayList txidList = new ArrayList(); - Optional infoById = null; - Long beforeTime; - Long afterTime; - Long beforeBlockNum; - Long afterBlockNum; - Block currentBlock; - Long currentBlockNum; - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[2]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey3.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - @Test(enabled = true, threadPoolSize = 1, invocationCount = 1) - public void testMutiSignForSmartContract() { - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - manager2Address = ecKey2.getAddress(); - manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - ecKey3 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey3.getAddress(); - ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - PublicMethed.printAddress(ownerKey); - - long needcoin = updateAccountPermissionFee + multiSignFee * 4; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needcoin + 100000000L, fromAddress, testKey002, - blockingStubFull)); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 1, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - PublicMethed.waitProduceNextBlock(blockingStubFull); - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - logger.info(accountPermissionJson); - PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString); - - Random rand = new Random(); - Integer randNum = rand.nextInt(30) + 1; - randNum = rand.nextInt(4000); - - Long maxFeeLimit = 1000000000L; - String contractName = "StorageAndCpu" + Integer.toString(randNum); - String code = Configuration.getByPath("testng.conf") - .getString("code.code_TestStorageAndCpu_storageAndCpu"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_TestStorageAndCpu_storageAndCpu"); - byte[] contractAddress = PublicMethedForMutiSign.deployContract1(contractName, abi, code, - "", maxFeeLimit, - 0L, 100, null, ownerKey, ownerAddress, blockingStubFull, 2, permissionKeyString); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString() != null); - String txid; - String initParmes = "\"" + "930" + "\""; - txid = PublicMethedForMutiSign.triggerContract1(contractAddress, - "testUseCpu(uint256)", initParmes, false, - 0, maxFeeLimit, ownerAddress, ownerKey, blockingStubFull, 2, permissionKeyString); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.getTransactionById(txid, blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue( - PublicMethedForMutiSign.updateSettingWithPermissionId(contractAddress, 50, ownerKey, - ownerAddress, 2, blockingStubFull, permissionKeyString)); - Assert.assertTrue( - PublicMethedForMutiSign.updateEnergyLimitWithPermissionId(contractAddress, 50, ownerKey, - ownerAddress, 2, blockingStubFull, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertTrue( - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull)); - Assert.assertTrue( - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, ownerAddress, blockingStubFull)); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignUpdataBrokerageTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignUpdataBrokerageTest.java deleted file mode 100644 index bd8f2c87827..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/operationupdate/MutiSignUpdataBrokerageTest.java +++ /dev/null @@ -1,163 +0,0 @@ -package stest.tron.wallet.dailybuild.operationupdate; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - - -@Slf4j -public class MutiSignUpdataBrokerageTest { - - private static final long now = System.currentTimeMillis(); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key2"); - private final byte[] witness001Address = PublicMethed.getFinalAddress(witnessKey001); - private final String operations = Configuration.getByPath("testng.conf") - .getString("defaultParameter.operations"); - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[2]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode).usePlaintext().build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true) - public void testMutiSignForUpdateBrokerage() { - long needcoin = updateAccountPermissionFee * 2 + multiSignFee * 5; - Assert.assertTrue(PublicMethed - .sendcoin(witness001Address, needcoin + 1000000L, fromAddress, testKey002, - blockingStubFull)); - - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - manager2Address = ecKey2.getAddress(); - manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(witness001Address, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - PublicMethed.waitProduceNextBlock(blockingStubFull); - ownerKeyString[0] = witnessKey001; - ownerKeyString[1] = testKey002; - - accountPermissionJson = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\"" - + ",\"threshold\":2,\"keys\":[{\"address\":\"" + PublicMethed - .getAddressString(witnessKey001) + "\"," + "\"weight\":1},{\"address\":\"" + PublicMethed - .getAddressString(testKey002) + "\",\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"owner\",\"threshold\":1," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0300000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(manager1Key) - + "\",\"weight\":1}," + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) - + "\",\"weight\":1}]}]} "; - logger.info(accountPermissionJson); - PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, witness001Address, witnessKey001, - blockingStubFull, ownerKeyString); - - //Update brokerage - - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethedForMutiSign - .updateBrokerage(witness001Address, 70, witnessKey001, 2, permissionKeyString, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // wait a MaintenanceTimeInterval - accountPermissionJson = "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\"" - + ",\"threshold\":1,\"keys\":[{\"address\":\"" + PublicMethed - .getAddressString(witnessKey001) + "\"," + "\"weight\":1}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"owner\",\"threshold\":1," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"7fff1fc0033e0300000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}]}]} "; - logger.info(accountPermissionJson); - PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, witness001Address, witnessKey001, - blockingStubFull, ownerKeyString); - - Long balanceAfter = PublicMethed.queryAccount(witness001Address, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit001.java deleted file mode 100644 index 4ac013f8e52..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit001.java +++ /dev/null @@ -1,145 +0,0 @@ -package stest.tron.wallet.dailybuild.originenergylimit; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractOriginEnergyLimit001 { - - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] grammarAddress3 = ecKey1.getAddress(); - String testKeyForGrammarAddress3 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKeyForGrammarAddress3); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - - //Origin_energy_limit001,028,029 - @Test(enabled = true, description = "Boundary value and update test") - public void testOrigin_energy_limit001() { - Assert.assertTrue(PublicMethed - .sendcoin(grammarAddress3, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/contractOriginEnergyLimit001.sol"; - String contractName = "findArgsContractTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String contractAddress = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, -1, "0", 0, - null, testKeyForGrammarAddress3, - grammarAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue(contractAddress == null); - - String contractAddress1 = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, 0, "0", 0, - null, testKeyForGrammarAddress3, - grammarAddress3, blockingStubFull); - - Assert.assertTrue(contractAddress1 == null); - - byte[] contractAddress2 = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, 9223372036854775807L, "0", - 0, null, testKeyForGrammarAddress3, - grammarAddress3, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertFalse(PublicMethed.updateEnergyLimit(contractAddress2, -1L, - testKeyForGrammarAddress3, grammarAddress3, blockingStubFull)); - SmartContract smartContract = PublicMethed.getContract(contractAddress2, blockingStubFull); - Assert.assertTrue(smartContract.getOriginEnergyLimit() == 9223372036854775807L); - - Assert.assertFalse(PublicMethed.updateEnergyLimit(contractAddress2, 0L, - testKeyForGrammarAddress3, grammarAddress3, blockingStubFull)); - SmartContract smartContract1 = PublicMethed.getContract(contractAddress2, blockingStubFull); - Assert.assertTrue(smartContract1.getOriginEnergyLimit() == 9223372036854775807L); - - Assert.assertTrue(PublicMethed.updateEnergyLimit(contractAddress2, - 9223372036854775807L, testKeyForGrammarAddress3, - grammarAddress3, blockingStubFull)); - SmartContract smartContract2 = PublicMethed.getContract(contractAddress2, blockingStubFull); - Assert.assertTrue(smartContract2.getOriginEnergyLimit() == 9223372036854775807L); - - Assert.assertTrue(PublicMethed.updateEnergyLimit(contractAddress2, 'c', - testKeyForGrammarAddress3, grammarAddress3, blockingStubFull)); - SmartContract smartContract3 = PublicMethed.getContract(contractAddress2, blockingStubFull); - Assert.assertEquals(smartContract3.getOriginEnergyLimit(), 99); - - Assert.assertFalse(PublicMethed.updateEnergyLimit(contractAddress2, 1L, - testNetAccountKey, testNetAccountAddress, blockingStubFull)); - SmartContract smartContract4 = PublicMethed.getContract(contractAddress2, blockingStubFull); - Assert.assertEquals(smartContract4.getOriginEnergyLimit(), 99); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(grammarAddress3, testKeyForGrammarAddress3, testNetAccountAddress, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit004.java deleted file mode 100644 index 496c4097a6d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit004.java +++ /dev/null @@ -1,378 +0,0 @@ -package stest.tron.wallet.dailybuild.originenergylimit; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractOriginEnergyLimit004 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - private long getAvailableFrozenEnergy(byte[] accountAddress) { - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(accountAddress, - blockingStubFull); - long energyLimit = resourceInfo.getEnergyLimit(); - long energyUsed = resourceInfo.getEnergyUsed(); - return energyLimit - energyUsed; - } - - private long getUserAvailableEnergy(byte[] userAddress) { - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(userAddress, - blockingStubFull); - Account info = PublicMethed.queryAccount(userAddress, blockingStubFull); - long balance = info.getBalance(); - long energyLimit = resourceInfo.getEnergyLimit(); - long userAvaliableFrozenEnergy = getAvailableFrozenEnergy(userAddress); - return balance / 100 + userAvaliableFrozenEnergy; - } - - private long getFeeLimit(String txid) { - Optional trsById = PublicMethed.getTransactionById(txid, blockingStubFull); - return trsById.get().getRawData().getFeeLimit(); - } - - private long getUserMax(byte[] userAddress, long feelimit) { - logger.info("User feeLimit: " + feelimit / 100); - logger.info("User UserAvaliableEnergy: " + getUserAvailableEnergy(userAddress)); - return Math.min(feelimit / 100, getUserAvailableEnergy(userAddress)); - } - - private long getOriginalEnergyLimit(byte[] contractAddress) { - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - return smartContract.getOriginEnergyLimit(); - } - - private long getConsumeUserResourcePercent(byte[] contractAddress) { - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - return smartContract.getConsumeUserResourcePercent(); - } - - private long getDevMax(byte[] devAddress, byte[] userAddress, long feeLimit, - byte[] contractAddress) { - long devMax = Math.min(getAvailableFrozenEnergy(devAddress), - getOriginalEnergyLimit(contractAddress)); - long p = getConsumeUserResourcePercent(contractAddress); - if (p != 0) { - logger.info("p: " + p); - devMax = Math.min(devMax, getUserMax(userAddress, feeLimit) * (100 - p) / p); - logger.info("Dev byUserPercent: " + getUserMax(userAddress, feeLimit) * (100 - p) / p); - } - logger.info("Dev AvaliableFrozenEnergy: " + getAvailableFrozenEnergy(devAddress)); - logger.info("Dev OriginalEnergyLimit: " + getOriginalEnergyLimit(contractAddress)); - return devMax; - } - - @Test(enabled = true, description = "Contract use Origin_energy_limit") - public void testOriginEnergyLimit() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1000000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 1000000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - // A2B1 - - //dev balance and Energy - long devTargetBalance = 10_000_000; - long devTargetEnergy = 70000; - - // deploy contract parameters - final long deployFeeLimit = maxFeeLimit; - final long consumeUserResourcePercent = 0; - final long originEnergyLimit = 1000; - - //dev balance and Energy - final long devTriggerTargetBalance = 0; - final long devTriggerTargetEnergy = 592; - - // user balance and Energy - final long userTargetBalance = 0; - final long userTargetEnergy = 2000L; - - // trigger contract parameter, maxFeeLimit 10000000 - final long triggerFeeLimit = maxFeeLimit; - final boolean expectRet = true; - - // count dev energy, balance - long devFreezeBalanceSun = PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, - devTargetEnergy, blockingStubFull); - - long devNeedBalance = devTargetBalance + devFreezeBalanceSun; - - logger.info("need balance:" + devNeedBalance); - - // get balance - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, devNeedBalance, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - // get energy - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(dev001Address, devFreezeBalanceSun, - 0, 1, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("before deploy, dev energy limit is " + Long.toString(devEnergyLimitBefore)); - logger.info("before deploy, dev energy usage is " + Long.toString(devEnergyUsageBefore)); - logger.info("before deploy, dev balance is " + Long.toString(devBalanceBefore)); - - String filePath = "src/test/resources/soliditycode/contractOriginEnergyLimit004.sol"; - String contractName = "findArgsContractTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String deployTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - deployFeeLimit, 0L, consumeUserResourcePercent, originEnergyLimit, "0", - 0, null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after deploy, dev energy limit is " + Long.toString(devEnergyLimitAfter)); - logger.info("after deploy, dev energy usage is " + Long.toString(devEnergyUsageAfter)); - logger.info("after deploy, dev balance is " + Long.toString(devBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - - ByteString contractAddressString = infoById.get().getContractAddress(); - contractAddress = contractAddressString.toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - - Assert.assertTrue(smartContract.getAbi() != null); - - Assert.assertTrue(devEnergyLimitAfter > 0); - Assert.assertTrue(devEnergyUsageAfter > 0); - Assert.assertEquals(devBalanceBefore, devBalanceAfter); - - // count dev energy, balance - devFreezeBalanceSun = PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, - devTriggerTargetEnergy, blockingStubFull); - - devNeedBalance = devTriggerTargetBalance + devFreezeBalanceSun; - logger.info("dev need balance:" + devNeedBalance); - - // count user energy, balance - long userFreezeBalanceSun = PublicMethed.getFreezeBalanceCount(user001Address, user001Key, - userTargetEnergy, blockingStubFull); - - long userNeedBalance = userTargetBalance + userFreezeBalanceSun; - - logger.info("User need balance:" + userNeedBalance); - - // get balance - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, devNeedBalance, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, userNeedBalance, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // get energy - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(dev001Address, devFreezeBalanceSun, - 0, 1, dev001Key, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(user001Address, userFreezeBalanceSun, - 0, 1, user001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - devEnergyLimitBefore = accountResource.getEnergyLimit(); - devEnergyUsageBefore = accountResource.getEnergyUsed(); - devBalanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("before trigger, dev devEnergyLimitBefore is " - + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, dev devEnergyUsageBefore is " - + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, dev devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount( - user001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, user userEnergyLimitBefore is " - + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, user userEnergyUsageBefore is " - + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, user userBalanceBefore is " + Long.toString(userBalanceBefore)); - - logger.info("=================================="); - long userMax = getUserMax(user001Address, triggerFeeLimit); - long devMax = getDevMax(dev001Address, user001Address, triggerFeeLimit, contractAddress); - - logger.info("userMax: " + userMax); - logger.info("devMax: " + devMax); - logger.info("=================================="); - - String param = "\"" + 0 + "\""; - final String triggerTxid = PublicMethed - .triggerContract(contractAddress, "findArgsByIndexTest(uint256)", - param, false, 0, triggerFeeLimit, - user001Address, user001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - devEnergyLimitAfter = accountResource.getEnergyLimit(); - devEnergyUsageAfter = accountResource.getEnergyUsed(); - devBalanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after trigger, dev devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, dev devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, dev devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, - blockingStubFull).getBalance(); - - logger.info("after trigger, user userEnergyLimitAfter is " - + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, user userEnergyUsageAfter is " - + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, user userBalanceAfter is " + Long.toString(userBalanceAfter)); - - infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); - boolean isSuccess = true; - if (triggerTxid == null || infoById.get().getResultValue() != 0) { - logger.info("transaction failed with message: " + infoById.get().getResMessage()); - isSuccess = false; - } - - long fee = infoById.get().getFee(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - long energyUsage = infoById.get().getReceipt().getEnergyUsage(); - long originEnergyUsage = infoById.get().getReceipt().getOriginEnergyUsage(); - long energyTotalUsage = infoById.get().getReceipt().getEnergyUsageTotal(); - long netUsage = infoById.get().getReceipt().getNetUsage(); - long netFee = infoById.get().getReceipt().getNetFee(); - - logger.info("fee: " + fee); - logger.info("energyFee: " + energyFee); - logger.info("energyUsage: " + energyUsage); - logger.info("originEnergyUsage: " + originEnergyUsage); - logger.info("energyTotalUsage: " + energyTotalUsage); - logger.info("netUsage: " + netUsage); - logger.info("netFee: " + netFee); - - smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - - long devExpectCost = energyTotalUsage * (100 - consumeUserPercent) / 100; - long userExpectCost = energyTotalUsage - devExpectCost; - final long totalCost = devExpectCost + userExpectCost; - - logger.info("devExpectCost: " + devExpectCost); - logger.info("userExpectCost: " + userExpectCost); - - Assert.assertTrue(devEnergyLimitAfter > 0); - Assert.assertEquals(devBalanceBefore, devBalanceAfter); - - // dev original is the dev max expense A2B1 - Assert.assertEquals(getOriginalEnergyLimit(contractAddress), devMax); - - // DEV is enough to pay - Assert.assertEquals(originEnergyUsage, devExpectCost); - // Assert.assertEquals(devEnergyUsageAfter,devExpectCost + devEnergyUsageBefore); - // User Energy is enough to pay"); - Assert.assertEquals(energyUsage, userExpectCost); - Assert.assertEquals(userBalanceBefore, userBalanceAfter); - Assert.assertEquals(userEnergyUsageAfter, userEnergyUsageBefore); - Assert.assertEquals(userBalanceBefore, userBalanceAfter); - Assert.assertEquals(totalCost, energyTotalUsage); - - if (expectRet) { - Assert.assertTrue(isSuccess); - } else { - Assert.assertFalse(isSuccess); - } - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.unFreezeBalance(user001Address, user001Key, 1, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(dev001Address, dev001Key, 1, dev001Address, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/transaction/TransactionPendingQuery001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/transaction/TransactionPendingQuery001.java deleted file mode 100644 index a815f840fc4..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/transaction/TransactionPendingQuery001.java +++ /dev/null @@ -1,138 +0,0 @@ -package stest.tron.wallet.dailybuild.transaction; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.TransactionIdList; -import org.tron.api.GrpcAPI.TransactionList; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.Sha256Hash; - - -@Slf4j - -public class TransactionPendingQuery001 { - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private ManagedChannel channelSolidity = null; - public ManagedChannel channelPbft = null; - public WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPbft = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] receiverAddress = ecKey1.getAddress(); - final String receiverKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String soliInPbft = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(2); - String txid = null; - - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext() - .build(); - blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); - - } - - @Test(enabled = true, description = "Test get pending size") - public void test01GetPendingSize() { - long pendingSizeInFullNode = 0; - int retryTimes = 100; - while (pendingSizeInFullNode == 0 && retryTimes-- > 0) { - PublicMethed.sendcoin(receiverAddress,1L,fromAddress,testKey002,blockingStubFull); - if (retryTimes % 5 == 0) { - pendingSizeInFullNode = blockingStubFull - .getPendingSize(EmptyMessage.newBuilder().build()).getNum(); - } - } - Assert.assertNotEquals(pendingSizeInFullNode,0); - } - - - @Test(enabled = true, description = "Test get pending transaction list") - public void test02GetPendingTransactionList() { - int retryTimes = 100; - TransactionIdList transactionList = blockingStubFull - .getTransactionListFromPending(EmptyMessage.newBuilder().build()); - while (transactionList.getTxIdCount() == 0 && retryTimes-- > 0) { - PublicMethed.sendcoin(receiverAddress,1L,fromAddress,testKey002,blockingStubFull); - if (retryTimes % 5 == 0) { - transactionList = blockingStubFull - .getTransactionListFromPending(EmptyMessage.newBuilder().build()); - } - } - Assert.assertNotEquals(transactionList.getTxIdCount(),0); - - txid = transactionList.getTxId(0); - - logger.info("txid:" + txid); - - } - - - @Test(enabled = true, description = "Test transaction from pending") - public void test03GetTransactionFromPending() { - Transaction transaction = PublicMethed.getTransactionFromPending(txid,blockingStubFull).get(); - Assert.assertEquals(ByteArray.toHexString(Sha256Hash - .hash(true, transaction.getRawData().toByteArray())),txid); - } - - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.unFreezeBalance(receiverAddress, receiverKey, 1, receiverAddress, - blockingStubFull); - PublicMethed.freedResource(receiverAddress, receiverKey, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken001.java deleted file mode 100644 index 18b28eeb8e2..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken001.java +++ /dev/null @@ -1,214 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken001 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - - @Test(enabled = true, description = "DeployContract with correct tokenValue and tokenId") - public void deployTransferTokenContract() { - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 3100_000_000L, fromAddress, testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 130000L, blockingStubFull), 0, - 1, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, 0, 0, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed - .createAssetIssue(dev001Address, tokenName, TotalSupply, 1, 10000, start, end, 1, - description, url, 100000L, 100000L, 1L, 1L, dev001Key, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed - .getAccountResource(dev001Address, blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balanceBefore is " + balanceBefore); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken001.sol"; - String contractName = "tokenTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String tokenId = assetAccountId.toStringUtf8(); - long tokenValue = 200; - long callValue = 5; - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callValue, 0, 10000, tokenId, tokenValue, null, dev001Key, dev001Address, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(transferTokenContractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long contractAssetCount = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(tokenValue), - Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(tokenValue), contractAssetCount); - - final String triggerTxid = PublicMethed - .triggerContract(transferTokenContractAddress, "getResultInCon()", "#", false, 0, - 1000000000L, "0", 0, dev001Address, dev001Key, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - List retList = PublicMethed - .getStrings(infoById.get().getContractResult(0).toByteArray()); - - Long msgId = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - Long msgTokenValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - Long msgCallValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(2))); - - logger.info("msgId: " + msgId); - logger.info("msgTokenValue: " + msgTokenValue); - logger.info("msgCallValue: " + msgCallValue); - - Assert.assertEquals(msgId.toString(), tokenId); - Assert.assertEquals(Long.valueOf(msgTokenValue), Long.valueOf(tokenValue)); - Assert.assertEquals(Long.valueOf(msgCallValue), Long.valueOf(callValue)); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken002.java deleted file mode 100644 index 81055f9435d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken002.java +++ /dev/null @@ -1,285 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken002 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "TriggerContract with correct tokenValue and tokenId") - public void deployTransferTokenContract() { - - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 3100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 300_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 70000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, - 100000L, 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed.getAssetIssueValue( - dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balanceBefore is " + balanceBefore); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountBefore: " + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken002.sol"; - String contractName = "tokenTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String tokenId = assetAccountId.toStringUtf8(); - long tokenValue = 200; - long callValue = 0; - - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, callValue, 0, 10000, - tokenId, tokenValue, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(transferTokenContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed.getAssetIssueValue( - dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountAfter: " + devAssetCountAfter); - - Assert.assertFalse(PublicMethed.transferAsset(transferTokenContractAddress, - assetAccountId.toByteArray(), 100L, dev001Address, dev001Key, blockingStubFull)); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() - + ", Count: " + contractAssetCount); - - Assert.assertEquals(Long.valueOf(200), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(200), contractAssetCount); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - - Assert.assertTrue(PublicMethed.transferAsset(user001Address, - assetAccountId.toByteArray(), 10L, dev001Address, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + devEnergyLimitBefore); - logger.info("before trigger, devEnergyUsageBefore is " + devEnergyUsageBefore); - logger.info("before trigger, devBalanceBefore is " + devBalanceBefore); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + userEnergyLimitBefore); - logger.info("before trigger, userEnergyUsageBefore is " + userEnergyUsageBefore); - logger.info("before trigger, userBalanceBefore is " + userBalanceBefore); - - - PublicMethed - .sendcoin(transferTokenContractAddress, 5000000, fromAddress, testKey002, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - tokenId = assetAccountId.toStringUtf8(); - tokenValue = 10; - callValue = 0; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "msgTokenValueAndTokenIdTest()", "#", false, callValue, - 1000000000L, tokenId, tokenValue, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + devEnergyLimitAfter); - logger.info("after trigger, devEnergyUsageAfter is " + devEnergyUsageAfter); - logger.info("after trigger, devBalanceAfter is " + devBalanceAfter); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, - blockingStubFull).getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + userEnergyLimitAfter); - logger.info("after trigger, userEnergyUsageAfter is " + userEnergyUsageAfter); - logger.info("after trigger, userBalanceAfter is " + userBalanceAfter); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (triggerTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - List retList = PublicMethed - .getStrings(infoById.get().getContractResult(0).toByteArray()); - - Long msgId = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - Long msgTokenValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - Long msgCallValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(2))); - - logger.info("msgId: " + msgId); - logger.info("msgTokenValue: " + msgTokenValue); - logger.info("msgCallValue: " + msgCallValue); - - Assert.assertEquals(msgId.toString(), tokenId); - Assert.assertEquals(Long.valueOf(msgTokenValue), Long.valueOf(tokenValue)); - Assert.assertEquals(Long.valueOf(msgCallValue), Long.valueOf(callValue)); - contractAssetCount = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("after user trigger Contract has AssetId: " + assetAccountId.toStringUtf8() - + ", Count: " + contractAssetCount); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken003.java deleted file mode 100644 index 64147ba7f44..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken003.java +++ /dev/null @@ -1,354 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class ContractTrcToken003 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountDev = null; - private static ByteString assetAccountUser = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - - } - - @Test(enabled = true, description = "DeployContract with exception condition") - public void deployTransferTokenContract() { - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 1100_000_000L, fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed - .sendcoin(user001Address, 1100_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 50000L, blockingStubFull), 0, - 1, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, 0, 0, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //dev Create a new AssetIssue - Assert.assertTrue(PublicMethed - .createAssetIssue(dev001Address, tokenName, TotalSupply, 1, 10000, start, end, 1, - description, url, 100000L, 100000L, 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountDev = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - logger.info("The assetAccountDev token name: " + tokenName); - logger.info("The assetAccountDev token ID: " + assetAccountDev.toStringUtf8()); - - start = System.currentTimeMillis() + 2000; - end = System.currentTimeMillis() + 1000000000; - //user Create a new AssetIssue - Assert.assertTrue(PublicMethed - .createAssetIssue(user001Address, tokenName, TotalSupply, 1, 10000, start, end, 1, - description, url, 100000L, 100000L, 1L, 1L, user001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountUser = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getAssetIssuedID(); - logger.info("The assetAccountUser token name: " + tokenName); - logger.info("The assetAccountUser token ID: " + assetAccountUser.toStringUtf8()); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed - .getAccountResource(dev001Address, blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountDev, blockingStubFull); - Long userAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountUser, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balanceBefore is " + balanceBefore); - logger.info( - "before dev has AssetId: " + assetAccountDev.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - logger.info( - "before dev has AssetId: " + assetAccountUser.toStringUtf8() + ", userAssetCountBefore: " - + userAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken003.sol"; - String contractName = "tokenTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - // the tokenId is not exist - String fakeTokenId = Long.toString(Long.valueOf(assetAccountDev.toStringUtf8()) + 100); - Long fakeTokenValue = 100L; - - GrpcAPI.Return response = PublicMethed - .deployContractAndGetResponse(contractName, abi, code, "", maxFeeLimit, 0L, 0, 10000, - fakeTokenId, fakeTokenValue, null, dev001Key, dev001Address, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert - .assertEquals("contract validate error : No asset !".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - // deployer didn't have any such token - fakeTokenId = assetAccountUser.toStringUtf8(); - fakeTokenValue = 100L; - - response = PublicMethed - .deployContractAndGetResponse(contractName, abi, code, "", maxFeeLimit, 0L, 0, 10000, - fakeTokenId, fakeTokenValue, null, dev001Key, dev001Address, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : assetBalance must greater than 0.".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - // deployer didn't have any Long.MAX_VALUE - fakeTokenId = Long.toString(Long.MAX_VALUE); - fakeTokenValue = 100L; - - response = PublicMethed - .deployContractAndGetResponse(contractName, abi, code, "", maxFeeLimit, 0L, 0, 10000, - fakeTokenId, fakeTokenValue, null, dev001Key, dev001Address, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : No asset !".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - // the tokenValue is not enough - fakeTokenId = assetAccountDev.toStringUtf8(); - fakeTokenValue = devAssetCountBefore + 100; - - response = PublicMethed - .deployContractAndGetResponse(contractName, abi, code, "", maxFeeLimit, 0L, 0, 10000, - fakeTokenId, fakeTokenValue, null, dev001Key, dev001Address, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : assetBalance is not sufficient.".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - // tokenid is -1 - fakeTokenId = Long.toString(-1); - response = PublicMethed - .deployContractAndGetResponse(contractName, abi, code, "", maxFeeLimit, 0L, 0, 10000, - fakeTokenId, 100, null, dev001Key, dev001Address, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : tokenId must be > 1000000".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // tokenid is 100_0000L - fakeTokenId = Long.toString(100_0000L); - response = PublicMethed - .deployContractAndGetResponse(contractName, abi, code, "", maxFeeLimit, 0L, 0, 10000, - fakeTokenId, 100, null, dev001Key, dev001Address, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : tokenId must be > 1000000".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - // tokenid is Long.MIN_VALUE - fakeTokenId = Long.toString(Long.MIN_VALUE); - response = PublicMethed - .deployContractAndGetResponse(contractName, abi, code, "", maxFeeLimit, 0L, 0, 10000, - fakeTokenId, 100, null, dev001Key, dev001Address, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : tokenId must be > 1000000".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // tokenid is 0 - fakeTokenId = Long.toString(0); - - response = PublicMethed - .deployContractAndGetResponse(contractName, abi, code, "", maxFeeLimit, 0L, 0, 10000, - fakeTokenId, 100, null, dev001Key, dev001Address, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals( - ("contract validate error : invalid arguments " - + "with tokenValue = 100, tokenId = 0").toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - // tokenvalue is less than 0 - fakeTokenValue = -1L; - - response = PublicMethed - .deployContractAndGetResponse(contractName, abi, code, "", maxFeeLimit, 0L, 0, 10000, - assetAccountDev.toStringUtf8(), fakeTokenValue, null, dev001Key, dev001Address, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : tokenValue must be >= 0".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // tokenvalue is long.min - fakeTokenValue = Long.MIN_VALUE; - - response = PublicMethed - .deployContractAndGetResponse(contractName, abi, code, "", maxFeeLimit, 0L, 0, 10000, - assetAccountDev.toStringUtf8(), fakeTokenValue, null, dev001Key, dev001Address, - blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : tokenValue must be >= 0".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - String tokenId = Long.toString(-1); - long tokenValue = 0; - long callValue = 10; - - response = PublicMethed - .deployContractAndGetResponse(contractName, abi, code, "", maxFeeLimit, callValue, 0, 10000, - tokenId, tokenValue, null, dev001Key, dev001Address, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : tokenId must be > 1000000".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - tokenId = Long.toString(Long.MIN_VALUE); - tokenValue = 0; - callValue = 10; - - response = PublicMethed - .deployContractAndGetResponse(contractName, abi, code, "", maxFeeLimit, callValue, 0, 10000, - tokenId, tokenValue, null, dev001Key, dev001Address, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : tokenId must be > 1000000".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - tokenId = Long.toString(1000000); - tokenValue = 0; - callValue = 10; - - response = PublicMethed - .deployContractAndGetResponse(contractName, abi, code, "", maxFeeLimit, callValue, 0, 10000, - tokenId, tokenValue, null, dev001Key, dev001Address, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : tokenId must be > 1000000".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountDev, blockingStubFull); - Long userAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountUser, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info( - "after dev has AssetId: " + assetAccountDev.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - logger.info( - "after user has AssetId: " + assetAccountDev.toStringUtf8() + ", userAssetCountAfter: " - + userAssetCountAfter); - - Assert.assertEquals(devAssetCountBefore, devAssetCountAfter); - Assert.assertEquals(userAssetCountBefore, userAssetCountAfter); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken005.java deleted file mode 100644 index f4513bfdfef..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken005.java +++ /dev/null @@ -1,422 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken005 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - - @Test(enabled = true, description = "TriggerContract with exception condition") - public void deployTransferTokenContract() { - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 1100_000_000L, fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed - .sendcoin(user001Address, 1_000_000L, fromAddress, testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 70000L, blockingStubFull), 0, - 1, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, 0, 0, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed - .createAssetIssue(dev001Address, tokenName, TotalSupply, 1, 10000, start, end, 1, - description, url, 100000L, 100000L, 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed - .getAccountResource(dev001Address, blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balanceBefore is " + balanceBefore); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken005.sol"; - String contractName = "tokenTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String tokenId = assetAccountId.toStringUtf8(); - long tokenValue = 200; - long callValue = 0; - - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callValue, 0, 10000, tokenId, tokenValue, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(transferTokenContractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - - Long contractAssetCount = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(200), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(200), contractAssetCount); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, blockingStubFull), 0, - 1, ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + devEnergyLimitBefore); - logger.info("before trigger, devEnergyUsageBefore is " + devEnergyUsageBefore); - logger.info("before trigger, devBalanceBefore is " + devBalanceBefore); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + userEnergyLimitBefore); - logger.info("before trigger, userEnergyUsageBefore is " + userEnergyUsageBefore); - logger.info("before trigger, userBalanceBefore is " + userBalanceBefore); - - Long transferAssetBefore = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - logger.info( - "before trigger, transferTokenContractAddress has AssetId " + assetAccountId.toStringUtf8() - + ", Count is " + transferAssetBefore); - - Long userAssetId = PublicMethed - .getAssetIssueValue(user001Address, ByteString.copyFromUtf8(tokenId), blockingStubFull); - logger.info("before userAssetId has AssetId " + tokenId + ", Count is " + userAssetId); - - // not such tokenId - tokenId = Long.toString(Long.valueOf(assetAccountId.toStringUtf8()) + 100000); - tokenValue = 10; - callValue = 5; - - GrpcAPI.Return response = PublicMethed - .triggerContractAndGetResponse(transferTokenContractAddress, - "msgTokenValueAndTokenIdTest()", "#", false, callValue, 1000000000L, tokenId, - tokenValue, user001Address, user001Key, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert - .assertEquals("contract validate error : No asset !".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - // not have this tokenId - tokenId = assetAccountId.toStringUtf8(); - tokenValue = 10; - callValue = 5; - - response = PublicMethed.triggerContractAndGetResponse(transferTokenContractAddress, - "msgTokenValueAndTokenIdTest()", "#", false, callValue, 1000000000L, tokenId, tokenValue, - user001Address, user001Key, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : Owner no asset!".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - // tokenId is Long.MAX_VALUE - tokenId = Long.toString(Long.MAX_VALUE); - tokenValue = 10; - callValue = 5; - - response = PublicMethed.triggerContractAndGetResponse(transferTokenContractAddress, - "msgTokenValueAndTokenIdTest()", "#", false, callValue, 1000000000L, tokenId, tokenValue, - user001Address, user001Key, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert - .assertEquals("contract validate error : No asset !".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - Assert.assertTrue(PublicMethed - .transferAsset(user001Address, assetAccountId.toByteArray(), 10L, dev001Address, dev001Key, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // tokenValue is not enough - tokenId = assetAccountId.toStringUtf8(); - tokenValue = 100; - callValue = 5; - - response = PublicMethed.triggerContractAndGetResponse(transferTokenContractAddress, - "msgTokenValueAndTokenIdTest()", "#", false, callValue, 1000000000L, tokenId, tokenValue, - user001Address, user001Key, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : assetBalance is not sufficient.".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - // tokenvalue is less than 0 - tokenId = assetAccountId.toStringUtf8(); - tokenValue = -1; - callValue = 5; - - response = PublicMethed.triggerContractAndGetResponse(transferTokenContractAddress, - "msgTokenValueAndTokenIdTest()", "#", false, callValue, 1000000000L, tokenId, tokenValue, - user001Address, user001Key, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : tokenValue must be >= 0".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - tokenId = assetAccountId.toStringUtf8(); - tokenValue = Long.MIN_VALUE; - callValue = 5; - - response = PublicMethed.triggerContractAndGetResponse(transferTokenContractAddress, - "msgTokenValueAndTokenIdTest()", "#", false, callValue, 1000000000L, tokenId, tokenValue, - user001Address, user001Key, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : tokenValue must be >= 0".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - /*PublicMethed - .sendcoin(transferTokenContractAddress, 5000000, fromAddress, testKey002, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull);*/ - - // tokenId is 100_0000 - tokenId = Long.toString(100_0000); - tokenValue = 10; - callValue = 5; - - response = PublicMethed.triggerContractAndGetResponse(transferTokenContractAddress, - "msgTokenValueAndTokenIdTest()", "#", false, callValue, 1000000000L, tokenId, tokenValue, - user001Address, user001Key, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : tokenId must be > 1000000".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - // tokenId is long.min - tokenId = Long.toString(Long.MIN_VALUE); - tokenValue = 10; - callValue = 5; - - response = PublicMethed.triggerContractAndGetResponse(transferTokenContractAddress, - "msgTokenValueAndTokenIdTest()", "#", false, callValue, 1000000000L, tokenId, tokenValue, - user001Address, user001Key, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : tokenId must be > 1000000".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - // tokenId is 0 - tokenId = Long.toString(0); - tokenValue = 10; - callValue = 5; - - response = PublicMethed.triggerContractAndGetResponse(transferTokenContractAddress, - "msgTokenValueAndTokenIdTest()", "#", false, callValue, 1000000000L, tokenId, tokenValue, - user001Address, user001Key, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals( - "contract validate error : invalid arguments with tokenValue = 10, tokenId = 0" - .toLowerCase(), response.getMessage().toStringUtf8().toLowerCase()); - - /*PublicMethed - .sendcoin(transferTokenContractAddress, 5000000, fromAddress, testKey002, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull);*/ - - tokenId = Long.toString(Long.MIN_VALUE); - tokenValue = 0; - callValue = 5; - - response = PublicMethed.triggerContractAndGetResponse(transferTokenContractAddress, - "msgTokenValueAndTokenIdTest()", "#", false, callValue, 1000000000L, tokenId, tokenValue, - user001Address, user001Key, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : tokenId must be > 1000000".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - - tokenId = Long.toString(-1); - tokenValue = 0; - callValue = 5; - - response = PublicMethed.triggerContractAndGetResponse(transferTokenContractAddress, - "msgTokenValueAndTokenIdTest()", "#", false, callValue, 1000000000L, tokenId, tokenValue, - user001Address, user001Key, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : tokenId must be > 1000000".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - - tokenId = Long.toString(100_0000L); - tokenValue = 0; - callValue = 5; - - response = PublicMethed.triggerContractAndGetResponse(transferTokenContractAddress, - "msgTokenValueAndTokenIdTest()", "#", false, callValue, 1000000000L, tokenId, tokenValue, - user001Address, user001Key, blockingStubFull); - - Assert.assertFalse(response.getResult()); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, response.getCode()); - Assert.assertEquals("contract validate error : tokenId must be > 1000000".toLowerCase(), - response.getMessage().toStringUtf8().toLowerCase()); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + devEnergyLimitAfter); - logger.info("after trigger, devEnergyUsageAfter is " + devEnergyUsageAfter); - logger.info("after trigger, devBalanceAfter is " + devBalanceAfter); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + userEnergyLimitAfter); - logger.info("after trigger, userEnergyUsageAfter is " + userEnergyUsageAfter); - logger.info("after trigger, userBalanceAfter is " + userBalanceAfter); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, user001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken011.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken011.java deleted file mode 100644 index 98f92a36572..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken011.java +++ /dev/null @@ -1,476 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionInfoList; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken011 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - private byte[] resultContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "TransferToken with correct value, deploy transfer contract") - public void test01DeployTransferTokenContract001() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 15048_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 14048_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, 100000L, - 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account getAssetIdFromThisAccount = PublicMethed - .queryAccount(dev001Address, blockingStubFull); - assetAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balanceBefore is " + balanceBefore); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountBefore: " + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken011.sol"; - String contractName = "transferTokenContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - assetAccountId.toStringUtf8(), 200, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountAfter: " + devAssetCountAfter); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(transferTokenContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - /*Assert.assertFalse(PublicMethed.transferAsset(transferTokenContractAddress, - assetAccountId.toByteArray(), 100L, dev001Address, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull);*/ - - Long contractAssetCount = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(200), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(200), contractAssetCount); - } - - - @Test(enabled = true, description = "TransferToken with correct value, deploy receive contract") - public void test02DeployRevContract002() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balance is " + balanceBefore); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountBefore: " + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken011.sol"; - String contractName = "Result"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - final String recieveTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, 1000, assetAccountId.toStringUtf8(), - 100, null, dev001Key, dev001Address, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - // after deploy, check account resource - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountAfter: " + devAssetCountAfter); - - Optional infoById = PublicMethed - .getTransactionInfoById(recieveTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy receive failed with message: " + infoById.get().getResMessage()); - } - - resultContractAddress = infoById.get().getContractAddress().toByteArray(); - - SmartContract smartContract = PublicMethed - .getContract(resultContractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(resultContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(100), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(100), contractAssetCount); - } - - @Test(enabled = true, description = "TransferToken with correct value, transfer to a contract") - public void test03TriggerContract003() { - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.transferAsset(user001Address, - assetAccountId.toByteArray(), 10L, dev001Address, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + devEnergyLimitBefore); - logger.info("before trigger, devEnergyUsageBefore is " + devEnergyUsageBefore); - logger.info("before trigger, devBalanceBefore is " + devBalanceBefore); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + userEnergyLimitBefore); - logger.info("before trigger, userEnergyUsageBefore is " + userEnergyUsageBefore); - logger.info("before trigger, userBalanceBefore is " + userBalanceBefore); - - Long transferAssetBefore = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, - blockingStubFull); - logger.info("before trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + transferAssetBefore); - - Long receiveAssetBefore = PublicMethed.getAssetIssueValue(resultContractAddress, assetAccountId, - blockingStubFull); - logger.info("before trigger, resultContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + receiveAssetBefore); - - String tokenId = assetAccountId.toStringUtf8(); - Long tokenValue = Long.valueOf(1); - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(resultContractAddress) - + "\",\"" + tokenValue + "\"," + tokenId; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + devEnergyLimitAfter); - logger.info("after trigger, devEnergyUsageAfter is " + devEnergyUsageAfter); - logger.info("after trigger, devBalanceAfter is " + devBalanceAfter); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + userEnergyLimitAfter); - logger.info("after trigger, userEnergyUsageAfter is " + userEnergyUsageAfter); - logger.info("after trigger, userBalanceAfter is " + userBalanceAfter); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - TransactionInfo transactionInfo = infoById.get(); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long msgId = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - Long msgTokenValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - Long msgCallValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(2))); - - logger.info("msgId: " + msgId); - logger.info("msgTokenValue: " + msgTokenValue); - logger.info("msgCallValue: " + msgCallValue); - - Assert.assertEquals(tokenId, msgId.toString()); - Assert.assertEquals(tokenValue, msgTokenValue); - Assert.assertEquals(callValue, msgCallValue); - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - Long transferAssetAfter = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("after trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", transferAssetAfter is " + transferAssetAfter); - - Long receiveAssetAfter = PublicMethed.getAssetIssueValue(resultContractAddress, - assetAccountId, blockingStubFull); - logger.info("after trigger, resultContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", receiveAssetAfter is " + receiveAssetAfter); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - - Assert.assertEquals(receiveAssetAfter - receiveAssetBefore, - transferAssetBefore + 2L - transferAssetAfter); - - } - - @Test(enabled = true, description = "TransferToken with correct value, get contract tokenBalance") - public void test04TriggerTokenBalanceContract004() { - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(user001Address, 1000_000_000L, - 0, 1, user001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("before trigger, dev energy limit is " + devEnergyLimitBefore); - logger.info("before trigger, dev energy usage is " + devEnergyUsageBefore); - logger.info("before trigger, dev balance is " + devBalanceBefore); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, - blockingStubFull).getBalance(); - - logger.info("before trigger, user energy limit is " + userEnergyLimitBefore); - logger.info("before trigger, user energy usage is " + userEnergyUsageBefore); - logger.info("before trigger, user balance is " + userBalanceBefore); - - String param = "\"" + Base58.encode58Check(resultContractAddress) + "\",\"" - + assetAccountId.toStringUtf8() + "\""; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "getTokenBalnce(address,trcToken)", - param, false, 0, 1000000000L, user001Address, - user001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + devEnergyLimitAfter); - logger.info("after trigger, devEnergyUsageAfter is " + devEnergyUsageAfter); - logger.info("after trigger, devBalanceAfter is " + devBalanceAfter); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + userEnergyLimitAfter); - logger.info("after trigger, userEnergyUsageAfter is " + userEnergyUsageAfter); - logger.info("after trigger, userBalanceAfter is " + userBalanceAfter); - - Optional infoById = PublicMethed.getTransactionInfoById(triggerTxid, - blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - - Long triggerResult = ByteArray - .toLong(infoById.get().getContractResult(0).toByteArray()); - logger.info("the receivercontract token by trigger contract: " + triggerResult); - Long assetIssueCount = PublicMethed - .getAssetIssueValue(resultContractAddress, assetAccountId, - blockingStubFull); - logger.info("the receivercontract token(getaccount): " + assetIssueCount); - Assert.assertTrue(assetIssueCount == triggerResult); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken012.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken012.java deleted file mode 100644 index 51924b918b8..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken012.java +++ /dev/null @@ -1,373 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken012 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "deploy transfer contract with correct value") - public void test01DeployTransferTokenContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 15048_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 14048_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, 100000L, - 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed - .queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balanceBefore is " + balanceBefore); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountBefore: " + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken012.sol"; - String contractName = "transferTokenContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - assetAccountId.toStringUtf8(), 200, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountAfter: " + devAssetCountAfter); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(transferTokenContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - /*Assert.assertFalse(PublicMethed.transferAsset(transferTokenContractAddress, - assetAccountId.toByteArray(), 100L, dev001Address, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull);*/ - - Long contractAssetCount = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(200), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(200), contractAssetCount); - } - - - @Test(description = "TransferToken with correct value, transfer to a normal account") - public void test02TriggerContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.transferAsset(user001Address, - assetAccountId.toByteArray(), 10L, dev001Address, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + devEnergyLimitBefore); - logger.info("before trigger, devEnergyUsageBefore is " + devEnergyUsageBefore); - logger.info("before trigger, devBalanceBefore is " + devBalanceBefore); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + userEnergyLimitBefore); - logger.info("before trigger, userEnergyUsageBefore is " + userEnergyUsageBefore); - logger.info("before trigger, userBalanceBefore is " + userBalanceBefore); - - Long transferAssetBefore = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, - blockingStubFull); - logger.info("before trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + transferAssetBefore); - - Long receiveAssetBefore = PublicMethed.getAssetIssueValue(dev001Address, assetAccountId, - blockingStubFull); - logger.info("before trigger, receiveTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + receiveAssetBefore); - - String tokenId = assetAccountId.toStringUtf8(); - Long tokenValue = Long.valueOf(1); - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(dev001Address) - + "\",\"" + tokenValue + "\"," + tokenId; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + devEnergyLimitAfter); - logger.info("after trigger, devEnergyUsageAfter is " + devEnergyUsageAfter); - logger.info("after trigger, devBalanceAfter is " + devBalanceAfter); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + userEnergyLimitAfter); - logger.info("after trigger, userEnergyUsageAfter is " + userEnergyUsageAfter); - logger.info("after trigger, userBalanceAfter is " + userBalanceAfter); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (triggerTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - Long transferAssetAfter = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("after trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", transferAssetAfter is " + transferAssetAfter); - - Long receiveAssetAfter = PublicMethed.getAssetIssueValue(dev001Address, - assetAccountId, blockingStubFull); - logger.info("after trigger, resultContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", receiveAssetAfter is " + receiveAssetAfter); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - - Assert.assertEquals(receiveAssetAfter - receiveAssetBefore, - transferAssetBefore + 2L - transferAssetAfter); - } - - @Test(description = "TransferToken with correct value, get account tokenBalance") - public void test03TriggerTokenBalanceContract() { - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(user001Address, 1000_000_000L, - 0, 1, user001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("before trigger, dev energy limit is " + devEnergyLimitBefore); - logger.info("before trigger, dev energy usage is " + devEnergyUsageBefore); - logger.info("before trigger, dev balance is " + devBalanceBefore); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, - blockingStubFull).getBalance(); - - logger.info("before trigger, user energy limit is " + userEnergyLimitBefore); - logger.info("before trigger, user energy usage is " + userEnergyUsageBefore); - logger.info("before trigger, user balance is " + userBalanceBefore); - - String param = "\"" + Base58.encode58Check(dev001Address) + "\",\"" - + assetAccountId.toStringUtf8() + "\""; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "getTokenBalnce(address,trcToken)", - param, false, 0, 1000000000L, user001Address, - user001Key, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + devEnergyLimitAfter); - logger.info("after trigger, devEnergyUsageAfter is " + devEnergyUsageAfter); - logger.info("after trigger, devBalanceAfter is " + devBalanceAfter); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + userEnergyLimitAfter); - logger.info("after trigger, userEnergyUsageAfter is " + userEnergyUsageAfter); - logger.info("after trigger, userBalanceAfter is " + userBalanceAfter); - - Optional infoById = PublicMethed.getTransactionInfoById(triggerTxid, - blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (triggerTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - - infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - Long assetAccountCount = ByteArray - .toLong(infoById.get().getContractResult(0).toByteArray()); - logger.info("the receivercontract token from contract: " + assetAccountCount); - Long assetIssueCount = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("the receivercontract token(getaccount): " + assetIssueCount); - Assert.assertEquals(assetIssueCount, assetAccountCount); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - // unfreeze resource - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, user001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken014.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken014.java deleted file mode 100644 index e87790c6c96..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken014.java +++ /dev/null @@ -1,544 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import static org.tron.protos.Protocol.TransactionInfo.code.FAILED; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken014 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private static ByteString assetAccountUser = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - private byte[] resultContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "TransferToken with tokenId in exception condition," - + " deploy transfer contract") - public void test01DeployTransferTokenContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 1100_000_000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //dev Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, - 1, 10000, start, end, 1, description, url, 100000L, - 100000L, 1L, 1L, dev001Key, blockingStubFull)); - - start = System.currentTimeMillis() + 2000; - end = System.currentTimeMillis() + 1000000000; - //user Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(user001Address, tokenName, TotalSupply, - 1, 10000, start, end, 1, description, url, 100000L, - 100000L, 1L, 1L, user001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountUser = PublicMethed.queryAccount( - user001Address, blockingStubFull).getAssetIssuedID(); - logger.info("The assetAccountUser token name: " + tokenName); - logger.info("The assetAccountUser token ID: " + assetAccountUser.toStringUtf8()); - - assetAccountId = PublicMethed.queryAccount( - dev001Address, blockingStubFull).getAssetIssuedID(); - logger.info("The assetAccountId token name: " + tokenName); - logger.info("The assetAccountId token ID: " + assetAccountId.toStringUtf8()); - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed.getAssetIssueValue( - dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balanceBefore is " + balanceBefore); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountBefore: " + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken014.sol"; - String contractName = "transferTokenContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - assetAccountId.toStringUtf8(), 100, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(transferTokenContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountAfter: " + devAssetCountAfter); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(100), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(100), contractAssetCount); - } - - @Test(enabled = true, description = "TransferToken with tokenId in exception condition," - + " deploy receiver contract") - public void test02DeployRevContract() { - - // before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balance is " + balanceBefore); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountBefore: " + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken014.sol"; - String contractName = "Result"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String recieveTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, 1000, assetAccountId.toStringUtf8(), - 100, null, dev001Key, dev001Address, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(recieveTokenTxid, blockingStubFull); - - if (recieveTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy receive failed with message: " + infoById.get().getResMessage()); - } - - resultContractAddress = infoById.get().getContractAddress().toByteArray(); - - SmartContract smartContract = PublicMethed - .getContract(resultContractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(resultContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - // after deploy, check account resource - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountAfter: " + devAssetCountAfter); - - Assert.assertEquals(Long.valueOf(100), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(100), contractAssetCount); - } - - @Test(enabled = true, description = "TransferToken with tokenId in exception condition," - + " transfer to contract") - public void test03TriggerContract() { - Assert.assertTrue(PublicMethed.transferAsset(user001Address, - assetAccountId.toByteArray(), 10L, dev001Address, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + devEnergyLimitBefore); - logger.info("before trigger, devEnergyUsageBefore is " + devEnergyUsageBefore); - logger.info("before trigger, devBalanceBefore is " + devBalanceBefore); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + userEnergyLimitBefore); - logger.info("before trigger, userEnergyUsageBefore is " + userEnergyUsageBefore); - logger.info("before trigger, userBalanceBefore is " + userBalanceBefore); - - Long transferAssetBefore = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("before trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + transferAssetBefore); - - Long receiveAssetBefore = PublicMethed.getAssetIssueValue(resultContractAddress, - assetAccountId, blockingStubFull); - logger.info("before trigger, resultContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + receiveAssetBefore); - - Long devAssetBefore = PublicMethed.getAssetIssueValue(dev001Address, - assetAccountId, blockingStubFull); - logger.info("before trigger, dev001Address has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + devAssetBefore); - - - // transfer a not exist TokenId, to a contract - String tokenId = assetAccountUser.toStringUtf8(); - Long tokenValue = Long.valueOf(1); - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(resultContractAddress) - + "\",\"" + tokenValue + "\"," + tokenId; - - String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - // transfer a not exist TokenId, to a normal account - tokenId = assetAccountUser.toStringUtf8(); - tokenValue = Long.valueOf(1); - callValue = Long.valueOf(0); - - param = "\"" + Base58.encode58Check(dev001Address) - + "\",\"" + tokenValue + "\"," + tokenId; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - // tokenValue is not enough - tokenId = assetAccountId.toStringUtf8(); - tokenValue = transferAssetBefore + 100; - callValue = Long.valueOf(0); - - param = "\"" + Base58.encode58Check(resultContractAddress) - + "\",\"" + tokenValue + "\"," + tokenId; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); - - - // tokenValue is not enough, transfer to a normal account - tokenId = assetAccountId.toStringUtf8(); - tokenValue = transferAssetBefore + 100; - callValue = Long.valueOf(0); - - param = "\"" + Base58.encode58Check(dev001Address) - + "\",\"" + tokenValue + "\"," + tokenId; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); - - // TokenId is long.max, to a contract - String fackTokenId = Long.toString(Long.MAX_VALUE); - Long fakeValue = 1L; - - param = "\"" + Base58.encode58Check(resultContractAddress) - + "\"," + fakeValue + ",\"" + fackTokenId + "\""; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, 0, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); - - - // TokenId is not exist, to a contract - fackTokenId = Long.toString(Long.valueOf(assetAccountId.toStringUtf8()) + 10000); - fakeValue = 1L; - - param = "\"" + Base58.encode58Check(resultContractAddress) - + "\"," + fakeValue + ",\"" + fackTokenId + "\""; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, 0, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); - - // TokenId is long.max, to a normal account - fackTokenId = Long.toString(Long.MAX_VALUE); - fakeValue = 1L; - - param = "\"" + Base58.encode58Check(dev001Address) - + "\"," + fakeValue + ",\"" + fackTokenId + "\""; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, 0, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); - - - // TokenId is not exist, to a normal account - fackTokenId = Long.toString(Long.valueOf(assetAccountId.toStringUtf8()) + 10000); - fakeValue = 1L; - - param = "\"" + Base58.encode58Check(dev001Address) - + "\"," + fakeValue + ",\"" + fackTokenId + "\""; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, 0, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); - - // tokenValue is long.min, transfer to a contract - tokenId = assetAccountId.toStringUtf8(); - tokenValue = Long.MIN_VALUE; - callValue = Long.valueOf(0); - - param = "\"" + Base58.encode58Check(resultContractAddress) - + "\",\"" + tokenValue + "\"," + tokenId; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("endowment out of long range", - infoById.get().getResMessage().toStringUtf8()); - - // tokenValue is long.min, transfer to a normal account - param = "\"" + Base58.encode58Check(dev001Address) - + "\",\"" + tokenValue + "\"," + tokenId; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("endowment out of long range", - infoById.get().getResMessage().toStringUtf8()); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + devEnergyLimitAfter); - logger.info("after trigger, devEnergyUsageAfter is " + devEnergyUsageAfter); - logger.info("after trigger, devBalanceAfter is " + devBalanceAfter); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + userEnergyLimitAfter); - logger.info("after trigger, userEnergyUsageAfter is " + userEnergyUsageAfter); - logger.info("after trigger, userBalanceAfter is " + userBalanceAfter); - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - Long transferAssetAfter = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("after trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", transferAssetAfter is " + transferAssetAfter); - - Long receiveAssetAfter = PublicMethed.getAssetIssueValue(resultContractAddress, - assetAccountId, blockingStubFull); - logger.info("after trigger, resultContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", receiveAssetAfter is " + receiveAssetAfter); - - Long devAssetAfter = PublicMethed.getAssetIssueValue(dev001Address, - assetAccountId, blockingStubFull); - logger.info("after trigger, dev001Address has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + devAssetAfter); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - - Assert.assertEquals(receiveAssetBefore, receiveAssetAfter); - Assert.assertEquals(devAssetBefore, devAssetAfter); - Assert.assertEquals(transferAssetBefore, transferAssetAfter); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken018.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken018.java deleted file mode 100644 index f795162f2a2..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken018.java +++ /dev/null @@ -1,286 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import static org.tron.protos.Protocol.TransactionInfo.code.SUCESS; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class ContractTrcToken018 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - private byte[] receiveTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - private byte[] tmpAddress = ecKey3.getAddress(); - private String tmp001Key = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "Transfer token to an inactive account") - public void testDeployTransferTokenContract() { - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 1100_000_000L, fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed - .sendcoin(user001Address, 100_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 50000L, blockingStubFull), 0, - 1, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, 0, 0, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed - .createAssetIssue(dev001Address, tokenName, TotalSupply, 1, 10000, start, end, 1, - description, url, 100000L, 100000L, 1L, 1L, dev001Key, blockingStubFull)); - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed - .getAccountResource(dev001Address, blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balanceBefore is " + balanceBefore); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken023.sol"; - String contractName = "tokenTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 0, - 10000, assetAccountId.toStringUtf8(), 200, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - logger.info("Delpoy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(transferTokenContractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - - /*Assert.assertFalse(PublicMethed - .transferAsset(transferTokenContractAddress, assetAccountId.toByteArray(), 100L, - dev001Address, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull);*/ - Long contractAssetCount = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(200), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(200), contractAssetCount); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, blockingStubFull), 0, - 1, ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed - .transferAsset(user001Address, assetAccountId.toByteArray(), 10L, dev001Address, dev001Key, - blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + devEnergyLimitBefore); - logger.info("before trigger, devEnergyUsageBefore is " + devEnergyUsageBefore); - logger.info("before trigger, devBalanceBefore is " + devBalanceBefore); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + userEnergyLimitBefore); - logger.info("before trigger, userEnergyUsageBefore is " + userEnergyUsageBefore); - logger.info("before trigger, userBalanceBefore is " + userBalanceBefore); - - Long transferAssetBefore = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - logger.info( - "before trigger, transferTokenContractAddress has AssetId " + assetAccountId.toStringUtf8() - + ", Count is " + transferAssetBefore); - - Long receiveAssetBefore = PublicMethed - .getAssetIssueValue(tmpAddress, assetAccountId, blockingStubFull); - logger.info( - "before trigger, receiveTokenContractAddress has AssetId " + assetAccountId.toStringUtf8() - + ", Count is " + receiveAssetBefore); - - String param = - "\"" + Base58.encode58Check(tmpAddress) + "\"," + assetAccountId.toStringUtf8() + ",\"1\""; - - final String triggerTxid = PublicMethed - .triggerContract(transferTokenContractAddress, "TransferTokenTo(address,trcToken,uint256)", - param, false, 0, 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, - user001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + devEnergyLimitAfter); - logger.info("after trigger, devEnergyUsageAfter is " + devEnergyUsageAfter); - logger.info("after trigger, devBalanceAfter is " + devBalanceAfter); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + userEnergyLimitAfter); - logger.info("after trigger, userEnergyUsageAfter is " + userEnergyUsageAfter); - logger.info("after trigger, userBalanceAfter is " + userBalanceAfter); - - infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertEquals(SUCESS, infoById.get().getResult()); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - logger.info("infoById.get().getResMessage().toStringUtf8(): " + infoById.get().getResMessage() - .toStringUtf8()); - /*Assert.assertEquals( - "transfer trc10 failed: Validate InternalTransfer error, no ToAccount. " - + "And not allowed to create account in smart contract.", - infoById.get().getResMessage().toStringUtf8());*/ - - Long transferAssetAfter = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - logger.info( - "after trigger, transferTokenContractAddress has AssetId " + assetAccountId.toStringUtf8() - + ", transferAssetAfter is " + transferAssetAfter); - - Long receiveAssetAfter = PublicMethed - .getAssetIssueValue(tmpAddress, assetAccountId, blockingStubFull); - logger.info( - "after trigger, receiveTokenAddress has AssetId " + assetAccountId.toStringUtf8() - + ", receiveAssetAfter is " + receiveAssetAfter); - - Assert.assertEquals(receiveAssetAfter, Long.valueOf(receiveAssetBefore + 1)); - Assert.assertEquals(transferAssetBefore, Long.valueOf(transferAssetAfter - 1)); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, user001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken023.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken023.java deleted file mode 100644 index 05508808114..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken023.java +++ /dev/null @@ -1,235 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken023 { - - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 10000000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - byte[] transferTokenContractAddress; - byte[] btestAddress; - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private static int randomInt(int minInt, int maxInt) { - return (int) Math.round(Math.random() * (maxInt - minInt) + minInt); - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "deploy contract for transfer token") - public void deploy01TransferTokenContract() { - - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 4048000000L, fromAddress, testKey002, blockingStubFull)); - - // freeze balance - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(dev001Address, 204800000, - 0, 1, dev001Key, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, - 100000L, 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - int i = randomInt(6666666, 9999999); - ByteString tokenId1 = ByteString.copyFromUtf8(String.valueOf(i)); - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - // deploy transferTokenContract - int originEnergyLimit = 50000; - String filePath2 = "src/test/resources/soliditycode/contractTrcToken023.sol"; - String contractName2 = "tokenTest"; - HashMap retMap2 = PublicMethed.getBycodeAbi(filePath2, contractName2); - String code2 = retMap2.get("byteCode").toString(); - String abi2 = retMap2.get("abI").toString(); - transferTokenContractAddress = PublicMethed - .deployContract(contractName2, abi2, code2, "", maxFeeLimit, - 1000000000L, 0, originEnergyLimit, "0", - 0, null, dev001Key, dev001Address, - blockingStubFull); - String contractName = "B"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath2, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - btestAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000000L, 0, originEnergyLimit, "0", - 0, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - /*Assert - .assertFalse(PublicMethed.sendcoin(transferTokenContractAddress, 1000000000L, fromAddress, - testKey002, blockingStubFull)); - Assert - .assertFalse(PublicMethed.sendcoin(btestAddress, 1000000000L, fromAddress, - testKey002, blockingStubFull));*/ - - // devAddress transfer token to userAddress - PublicMethed.transferAsset(transferTokenContractAddress, assetAccountId.toByteArray(), - 100, dev001Address, dev001Key, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "transfer token which from address does not have") - public void deploy02TransferTokenContract() { - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - info = PublicMethed.queryAccount(dev001Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long beforeAssetIssueDevAddress = PublicMethed.getAssetIssueValue(dev001Address, - assetAccountId,blockingStubFull); - - Long beforeAssetIssueContractAddress = PublicMethed.getAssetIssueValue( - transferTokenContractAddress, assetAccountId,blockingStubFull); - Long beforeAssetIssueBAddress = PublicMethed.getAssetIssueValue(btestAddress, - assetAccountId, blockingStubFull); - - Long beforeBalanceContractAddress = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("beforeAssetIssueContractAddress:" + beforeAssetIssueContractAddress); - logger.info("beforeAssetIssueBAddress:" + beforeAssetIssueBAddress); - - logger.info("beforeAssetIssueDevAddress:" + beforeAssetIssueDevAddress); - logger.info("beforeBalanceContractAddress:" + beforeBalanceContractAddress); - - String param = "\"" + Base58.encode58Check(btestAddress) + "\",\"" - + assetAccountId.toStringUtf8() + "\",\"1\""; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "TransferTokenTo(address,trcToken,uint256)", param, false, 0, - 1000000000L, "0", 0, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account infoafter = PublicMethed.queryAccount(dev001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueBAddress = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - - Long afterBalanceContractAddress = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterAssetIssueCount:" + afterAssetIssueDevAddress); - logger.info("afterAssetIssueDevAddress:" + afterAssetIssueContractAddress); - logger.info("afterAssetIssueBAddress:" + afterAssetIssueBAddress); - logger.info("afterBalanceContractAddress:" + afterBalanceContractAddress); - - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 1); - - Assert.assertEquals(afterBalanceContractAddress, beforeBalanceContractAddress); - Assert.assertTrue(afterAssetIssueContractAddress == beforeAssetIssueContractAddress); - Assert.assertTrue(afterAssetIssueBAddress == beforeAssetIssueBAddress); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken026.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken026.java deleted file mode 100644 index 0747a38f68b..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken026.java +++ /dev/null @@ -1,514 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken026 { - - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 10000000L; - private static ByteString assetAccountId = null; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - byte[] btestAddress; - byte[] ctestAddress; - byte[] transferTokenContractAddress; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private static int randomInt(int minInt, int maxInt) { - return (int) Math.round(Math.random() * (maxInt - minInt) + minInt); - } - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - @Test(enabled = true, description = "Deploy transferToken contract") - public void deploy01TransferTokenContract001() { - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 4048000000L, - fromAddress, testKey002, blockingStubFull)); - - - // freeze balance - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(dev001Address, 204800000, - 0, 1, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - // deploy transferTokenContract - int originEnergyLimit = 50000; - String filePath = "src/test/resources/soliditycode/contractTrcToken026.sol"; - String contractName = "B"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - btestAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 0, originEnergyLimit, assetAccountId.toStringUtf8(), - 100, null, dev001Key, dev001Address, blockingStubFull); - - String contractName1 = "C"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - ctestAddress = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 0L, 0, originEnergyLimit, assetAccountId.toStringUtf8(), - 100, null, dev001Key, dev001Address, - blockingStubFull); - - String contractName2 = "token"; - HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); - String code2 = retMap2.get("byteCode").toString(); - String abi2 = retMap2.get("abI").toString(); - transferTokenContractAddress = PublicMethed - .deployContract(contractName2, abi2, code2, "", maxFeeLimit, - 1000000000L, 0, originEnergyLimit, assetAccountId.toStringUtf8(), - 100, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - } - - @Test(enabled = true, description = "Multistage call transferToken use right tokenID") - public void deploy02TransferTokenContract002() { - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - info = PublicMethed.queryAccount(dev001Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long beforeAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long beforeAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long beforeAssetIssueBAddress = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - Long beforeAssetIssueCAddress = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - Long beforeBalanceContractAddress = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("beforeAssetIssueContractAddress:" + beforeAssetIssueContractAddress); - logger.info("beforeAssetIssueBAddress:" + beforeAssetIssueBAddress); - logger.info("beforeAssetIssueCAddress:" + beforeAssetIssueCAddress); - - logger.info("beforeAssetIssueDevAddress:" + beforeAssetIssueDevAddress); - logger.info("beforeBalanceContractAddress:" + beforeBalanceContractAddress); - // 1.user trigger A to transfer token to B - String param = - "\"" + Base58.encode58Check(btestAddress) + "\",\"" + Base58.encode58Check(ctestAddress) - + "\",\"" + Base58.encode58Check(transferTokenContractAddress) - + "\",1,\"" + assetAccountId.toStringUtf8() + "\""; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "testInCall(address,address,address,uint256,trcToken)", - param, false, 0, 1000000000L, "0", - 0, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account infoafter = PublicMethed.queryAccount(dev001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueBAddress = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueCAddress = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - Long afterBalanceContractAddress = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterAssetIssueCount:" + afterAssetIssueDevAddress); - logger.info("afterAssetIssueDevAddress:" + afterAssetIssueContractAddress); - logger.info("afterAssetIssueBAddress:" + afterAssetIssueBAddress); - logger.info("afterAssetIssueCAddress:" + afterAssetIssueCAddress); - logger.info("afterBalanceContractAddress:" + afterBalanceContractAddress); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertEquals(afterBalanceContractAddress, beforeBalanceContractAddress); - Assert.assertTrue(afterAssetIssueContractAddress == beforeAssetIssueContractAddress + 1); - Assert.assertTrue(afterAssetIssueBAddress == beforeAssetIssueBAddress); - Assert.assertTrue(afterAssetIssueCAddress == beforeAssetIssueCAddress - 1); - } - - @Test(enabled = true, description = "Multistage call transferToken use fake tokenID") - public void deploy03TransferTokenContract003() { - Account infoafter = PublicMethed.queryAccount(dev001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueBAddress = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueCAddress = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - Long afterBalanceContractAddress = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterAssetIssueCount:" + afterAssetIssueDevAddress); - logger.info("afterAssetIssueDevAddress:" + afterAssetIssueContractAddress); - logger.info("afterAssetIssueBAddress:" + afterAssetIssueBAddress); - logger.info("afterAssetIssueCAddress:" + afterAssetIssueCAddress); - logger.info("afterBalanceContractAddress:" + afterBalanceContractAddress); - //3. user trigger A to transfer token to B - int i = randomInt(6666666, 9999999); - - ByteString tokenId1 = ByteString.copyFromUtf8(String.valueOf(i)); - - String param1 = - "\"" + Base58.encode58Check(btestAddress) + "\",\"" + Base58.encode58Check(ctestAddress) - + "\",\"" + Base58.encode58Check(transferTokenContractAddress) - + "\",1,\"" + tokenId1 - .toStringUtf8() - + "\""; - - final String triggerTxid1 = PublicMethed.triggerContract(transferTokenContractAddress, - "testInCall(address,address,address,uint256,trcToken)", - param1, false, 0, 1000000000L, "0", - 0, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account infoafter1 = PublicMethed.queryAccount(dev001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter1 = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterAssetIssueDevAddress1 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - final Long afterAssetIssueContractAddress1 = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueBAddress1 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueCAddress1 = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - Long afterBalanceContractAddress1 = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - - logger.info("afterBalance1:" + afterBalance1); - logger.info("afterEnergyUsed1:" + afterEnergyUsed1); - logger.info("afterNetUsed1:" + afterNetUsed1); - logger.info("afterFreeNetUsed1:" + afterFreeNetUsed1); - logger.info("afterAssetIssueCount1:" + afterAssetIssueDevAddress1); - logger.info("afterAssetIssueDevAddress1:" + afterAssetIssueContractAddress1); - logger.info("afterAssetIssueBAddress1:" + afterAssetIssueBAddress1); - logger.info("afterAssetIssueCAddress1:" + afterAssetIssueCAddress1); - logger.info("afterBalanceContractAddress1:" + afterBalanceContractAddress1); - - Optional infoById1 = PublicMethed - .getTransactionInfoById(triggerTxid1, blockingStubFull); - Assert.assertTrue(infoById1.get().getResultValue() == 0); - Assert.assertEquals(afterBalanceContractAddress, afterBalanceContractAddress1); - Assert.assertTrue(afterAssetIssueContractAddress == afterAssetIssueContractAddress1); - Assert.assertTrue(afterAssetIssueBAddress == afterAssetIssueBAddress1); - Assert.assertTrue(afterAssetIssueCAddress == afterAssetIssueCAddress1); - } - - @Test(enabled = true, description = "Multistage call transferToken token value not enough") - public void deploy04TransferTokenContract004() { - - final Long afterAssetIssueContractAddress1 = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueBAddress1 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueCAddress1 = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - final Long afterBalanceContractAddress1 = - PublicMethed.queryAccount(transferTokenContractAddress, blockingStubFull).getBalance(); - logger.info("afterAssetIssueDevAddress:" + afterAssetIssueContractAddress1); - logger.info("afterAssetIssueBAddress:" + afterAssetIssueBAddress1); - logger.info("afterAssetIssueCAddress:" + afterAssetIssueCAddress1); - logger.info("afterBalanceContractAddress:" + afterBalanceContractAddress1); - - //4. user trigger A to transfer token to B - String param2 = - "\"" + Base58.encode58Check(btestAddress) + "\",\"" + Base58.encode58Check(ctestAddress) - + "\",\"" + Base58.encode58Check(transferTokenContractAddress) - + "\",10000000,\"" + assetAccountId - .toStringUtf8() - + "\""; - - final String triggerTxid2 = PublicMethed.triggerContract(transferTokenContractAddress, - "testInCall(address,address,address,uint256,trcToken)", - param2, false, 0, 1000000000L, "0", - 0, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById2 = PublicMethed - .getTransactionInfoById(triggerTxid2, blockingStubFull); - Assert.assertTrue(infoById2.get().getResultValue() == 0); - Long afterAssetIssueContractAddress2 = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueBAddress2 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueCAddress2 = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - Long afterBalanceContractAddress2 = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - - logger.info("afterAssetIssueDevAddress2:" + afterAssetIssueContractAddress2); - logger.info("afterAssetIssueBAddress2:" + afterAssetIssueBAddress2); - logger.info("afterAssetIssueCAddress2:" + afterAssetIssueCAddress2); - logger.info("afterBalanceContractAddress2:" + afterBalanceContractAddress2); - - Assert.assertEquals(afterBalanceContractAddress1, afterBalanceContractAddress2); - Assert.assertTrue(afterAssetIssueContractAddress1 == afterAssetIssueContractAddress2); - Assert.assertTrue(afterAssetIssueBAddress1 == afterAssetIssueBAddress2); - Assert.assertTrue(afterAssetIssueCAddress1 == afterAssetIssueCAddress2); - } - - @Test(enabled = true, description = "Multistage call transferToken calltoken ID not exist") - public void deploy05TransferTokenContract005() { - - final Long afterAssetIssueContractAddress2 = PublicMethed.getAssetIssueValue( - transferTokenContractAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueBAddress2 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueCAddress2 = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - final Long afterBalanceContractAddress2 = PublicMethed - .queryAccount(transferTokenContractAddress, blockingStubFull).getBalance(); - //5. user trigger A to transfer token to B - String param3 = - "\"" + Base58.encode58Check(btestAddress) + "\",\"" + Base58.encode58Check(ctestAddress) - + "\",\"" + Base58.encode58Check(transferTokenContractAddress) - + "\",1,\"" + assetAccountId - .toStringUtf8() - + "\""; - int i = randomInt(6666666, 9999999); - - ByteString tokenId1 = ByteString.copyFromUtf8(String.valueOf(i)); - final String triggerTxid3 = PublicMethed.triggerContract(transferTokenContractAddress, - "testInCall(address,address,address,uint256,trcToken)", - param3, false, 0, 1000000000L, tokenId1 - .toStringUtf8(), 1, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(triggerTxid3 == null); - - Long afterAssetIssueDevAddress3 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterAssetIssueContractAddress3 = PublicMethed.getAssetIssueValue( - transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueBAddress3 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueCAddress3 = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - Long afterBalanceContractAddress3 = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - - logger.info("afterAssetIssueCount3:" + afterAssetIssueDevAddress3); - logger.info("afterAssetIssueDevAddress3:" + afterAssetIssueContractAddress3); - logger.info("afterAssetIssueBAddress3:" + afterAssetIssueBAddress3); - logger.info("afterAssetIssueCAddress3:" + afterAssetIssueCAddress3); - logger.info("afterBalanceContractAddress3:" + afterBalanceContractAddress3); - - Assert.assertEquals(afterBalanceContractAddress2, afterBalanceContractAddress3); - Assert.assertTrue(afterAssetIssueContractAddress2 == afterAssetIssueContractAddress3); - Assert.assertTrue(afterAssetIssueBAddress2 == afterAssetIssueBAddress3); - Assert.assertTrue(afterAssetIssueCAddress2 == afterAssetIssueCAddress3); - } - - @Test(enabled = true, description = "Multistage call transferToken calltoken value not enough") - public void deploy06TransferTokenContract006() { - - final Long afterAssetIssueContractAddress3 = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueBAddress3 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueCAddress3 = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - final Long afterBalanceContractAddress3 = - PublicMethed.queryAccount(transferTokenContractAddress, blockingStubFull).getBalance(); - //6. user trigger A to transfer token to B - String param4 = - "\"" + Base58.encode58Check(btestAddress) + "\",\"" + Base58.encode58Check(ctestAddress) - + "\",\"" + Base58.encode58Check(transferTokenContractAddress) - + "\",1,\"" + assetAccountId.toStringUtf8() + "\""; - - final String triggerTxid4 = PublicMethed.triggerContract(transferTokenContractAddress, - "testInCall(address,address,address,uint256,trcToken)", - param4, false, 0, 1000000000L, assetAccountId - .toStringUtf8(), 100000000, dev001Address, dev001Key, blockingStubFull); - Assert.assertTrue(triggerTxid4 == null); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long afterAssetIssueContractAddress4 = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueBAddress4 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueCAddress4 = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - Long afterBalanceContractAddress4 = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - - logger.info("afterAssetIssueDevAddress4:" + afterAssetIssueContractAddress4); - logger.info("afterAssetIssueBAddress4:" + afterAssetIssueBAddress4); - logger.info("afterAssetIssueCAddress4:" + afterAssetIssueCAddress4); - logger.info("afterBalanceContractAddress4:" + afterBalanceContractAddress4); - - Assert.assertEquals(afterBalanceContractAddress3, afterBalanceContractAddress4); - Assert.assertTrue(afterAssetIssueContractAddress3 == afterAssetIssueContractAddress4); - Assert.assertTrue(afterAssetIssueBAddress3 == afterAssetIssueBAddress4); - Assert.assertTrue(afterAssetIssueCAddress3 == afterAssetIssueCAddress4); - } - - @Test(enabled = true, description = "Multistage call transferToken use right tokenID,tokenvalue") - public void deploy07TransferTokenContract007() { - final Long afterAssetIssueDevAddress4 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - final Long afterAssetIssueContractAddress4 = PublicMethed.getAssetIssueValue( - transferTokenContractAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueBAddress4 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueCAddress4 = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - final Long afterBalanceContractAddress4 = - PublicMethed.queryAccount(transferTokenContractAddress, blockingStubFull).getBalance(); - //2. user trigger A to transfer token to B - String param5 = - "\"" + Base58.encode58Check(btestAddress) + "\",\"" + Base58.encode58Check(ctestAddress) - + "\",\"" + Base58.encode58Check(transferTokenContractAddress) - + "\",1,\"" + assetAccountId.toStringUtf8() + "\""; - - final String triggerTxid5 = PublicMethed.triggerContract(transferTokenContractAddress, - "testInCall(address,address,address,uint256,trcToken)", - param5, false, 0, 1000000000L, assetAccountId - .toStringUtf8(), 1, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long afterAssetIssueContractAddress5 = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueBAddress5 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueCAddress5 = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - Long afterBalanceContractAddress5 = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - - logger.info("afterAssetIssueDevAddress5:" + afterAssetIssueContractAddress5); - logger.info("afterAssetIssueBAddress5:" + afterAssetIssueBAddress5); - logger.info("afterAssetIssueCAddress5:" + afterAssetIssueCAddress5); - logger.info("afterBalanceContractAddress5:" + afterBalanceContractAddress5); - - Optional infoById5 = PublicMethed - .getTransactionInfoById(triggerTxid5, blockingStubFull); - Assert.assertTrue(infoById5.get().getResultValue() == 0); - Assert.assertEquals(afterBalanceContractAddress4, afterBalanceContractAddress5); - Assert.assertTrue(afterAssetIssueContractAddress4 + 2 == afterAssetIssueContractAddress5); - Assert.assertTrue(afterAssetIssueBAddress4 == afterAssetIssueBAddress5); - Assert.assertTrue(afterAssetIssueCAddress4 - 1 == afterAssetIssueCAddress5); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken027.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken027.java deleted file mode 100644 index cc372212f3b..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken027.java +++ /dev/null @@ -1,490 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken027 { - - - private static final long TotalSupply = 10000000L; - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - byte[] btestAddress; - byte[] ctestAddress; - byte[] transferTokenContractAddress; - int i1 = randomInt(6666666, 9999999); - ByteString tokenId1 = ByteString.copyFromUtf8(String.valueOf(i1)); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - /** - * constructor. - */ - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private static int randomInt(int minInt, int maxInt) { - return (int) Math.round(Math.random() * (maxInt - minInt) + minInt); - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - @Test(enabled = true, description = "Deploy transferToken contract") - public void deploy01TransferTokenContract() { - PublicMethed.printAddress(dev001Key); - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 4048000000L, - fromAddress, testKey002, blockingStubFull)); - - - // freeze balance - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(dev001Address, 204800000, - 0, 1, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String tokenName = "testAI_" + randomInt(10000, 90000); - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - // deploy transferTokenContract - int originEnergyLimit = 50000; - String filePath = "src/test/resources/soliditycode/contractTrcToken027.sol"; - String contractName = "B"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - btestAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 0, originEnergyLimit, assetAccountId.toStringUtf8(), - 100, null, dev001Key, dev001Address, blockingStubFull); - - String contractName1 = "C"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - ctestAddress = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 0L, 0, originEnergyLimit, assetAccountId.toStringUtf8(), - 100, null, dev001Key, dev001Address, - blockingStubFull); - - - String contractName2 = "token"; - HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); - - String code2 = retMap2.get("byteCode").toString(); - String abi2 = retMap2.get("abI").toString(); - transferTokenContractAddress = PublicMethed - .deployContract(contractName2, abi2, code2, "", maxFeeLimit, - 1000000000L, 0, originEnergyLimit, assetAccountId.toStringUtf8(), - 100, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - /*Assert.assertFalse(PublicMethed.sendcoin(transferTokenContractAddress, 1000000000L, - fromAddress, testKey002, blockingStubFull));*/ - } - - @Test(enabled = true, description = "Multistage delegatecall transferToken use right tokenID") - public void deploy02TransferTokenContract() { - - Long beforeAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - Long beforeAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long beforeAssetIssueBAddress = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - Long beforeAssetIssueCAddress = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - Long beforeBalanceContractAddress = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - logger.info("beforeAssetIssueContractAddress:" + beforeAssetIssueContractAddress); - logger.info("beforeAssetIssueBAddress:" + beforeAssetIssueBAddress); - logger.info("beforeAssetIssueCAddress:" + beforeAssetIssueCAddress); - - logger.info("beforeAssetIssueDevAddress:" + beforeAssetIssueDevAddress); - logger.info("beforeBalanceContractAddress:" + beforeBalanceContractAddress); - // 1.user trigger A to transfer token to B - String param = - "\"" + Base58.encode58Check(btestAddress) + "\",\"" + Base58.encode58Check(ctestAddress) - + "\",\"" + Base58.encode58Check(transferTokenContractAddress) - + "\",1,\"" + assetAccountId.toStringUtf8() + "\""; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "testIndelegateCall(address,address,address,uint256,trcToken)", - param, false, 0, 1000000000L, "0", - 0, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - Account infoafter = PublicMethed.queryAccount(dev001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueBAddress = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueCAddress = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - - Long afterBalanceContractAddress = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterAssetIssueCount:" + afterAssetIssueDevAddress); - logger.info("afterAssetIssueDevAddress:" + afterAssetIssueContractAddress); - logger.info("afterAssetIssueBAddress:" + afterAssetIssueBAddress); - logger.info("afterAssetIssueCAddress:" + afterAssetIssueCAddress); - logger.info("afterBalanceContractAddress:" + afterBalanceContractAddress); - Assert.assertEquals(afterBalanceContractAddress, beforeBalanceContractAddress); - Assert.assertTrue(afterAssetIssueContractAddress == beforeAssetIssueContractAddress + 1); - Assert.assertTrue(afterAssetIssueBAddress == beforeAssetIssueBAddress); - Assert.assertTrue(afterAssetIssueCAddress == beforeAssetIssueCAddress - 1); - - } - - @Test(enabled = true, description = "Multistage delegatecall transferToken use fake tokenID") - public void deploy03TransferTokenContract() { - Long afterAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - final Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueBAddress = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueCAddress = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - final Long afterBalanceContractAddress = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - - String param1 = - "\"" + Base58.encode58Check(btestAddress) + "\",\"" + Base58.encode58Check(ctestAddress) - + "\",\"" + Base58.encode58Check(transferTokenContractAddress) - + "\",1,\"" + tokenId1.toStringUtf8() + "\""; - - final String triggerTxid1 = PublicMethed.triggerContract(transferTokenContractAddress, - "testIndelegateCall(address,address,address,uint256,trcToken)", - param1, false, 0, 1000000000L, "0", - 0, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = PublicMethed - .getTransactionInfoById(triggerTxid1, blockingStubFull); - Assert.assertTrue(infoById1.get().getResultValue() == 0); - Long afterAssetIssueDevAddress1 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterAssetIssueContractAddress1 = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueBAddress1 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueCAddress1 = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - Long afterBalanceContractAddress1 = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - logger.info("afterAssetIssueCount1:" + afterAssetIssueDevAddress1); - logger.info("afterAssetIssueDevAddress1:" + afterAssetIssueContractAddress1); - logger.info("afterAssetIssueBAddress1:" + afterAssetIssueBAddress1); - logger.info("afterAssetIssueCAddress1:" + afterAssetIssueCAddress1); - logger.info("afterBalanceContractAddress1:" + afterBalanceContractAddress1); - - - Assert.assertEquals(afterBalanceContractAddress, afterBalanceContractAddress1); - Assert.assertTrue(afterAssetIssueContractAddress == afterAssetIssueContractAddress1); - Assert.assertTrue(afterAssetIssueBAddress == afterAssetIssueBAddress1); - Assert.assertTrue(afterAssetIssueCAddress == afterAssetIssueCAddress1); - } - - - @Test(enabled = true, description = "Multistage delegatecall transferToken token value" - + " not enough") - public void deploy04TransferTokenContract() { - - Long afterAssetIssueDevAddress1 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - final Long afterAssetIssueContractAddress1 = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueBAddress1 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueCAddress1 = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - final Long afterBalanceContractAddress1 = PublicMethed - .queryAccount(transferTokenContractAddress, blockingStubFull).getBalance(); - String param2 = - "\"" + Base58.encode58Check(btestAddress) + "\",\"" + Base58.encode58Check(ctestAddress) - + "\",\"" + Base58.encode58Check(transferTokenContractAddress) - + "\",10000000,\"" + assetAccountId.toStringUtf8() + "\""; - - final String triggerTxid2 = PublicMethed.triggerContract(transferTokenContractAddress, - "testIndelegateCall(address,address,address,uint256,trcToken)", - param2, false, 0, 1000000000L, "0", - 0, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById2 = PublicMethed - .getTransactionInfoById(triggerTxid2, blockingStubFull); - Assert.assertTrue(infoById2.get().getResultValue() == 0); - - Long afterAssetIssueDevAddress2 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterAssetIssueContractAddress2 = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueBAddress2 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueCAddress2 = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - Long afterBalanceContractAddress2 = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - - logger.info("afterAssetIssueCount2:" + afterAssetIssueDevAddress2); - logger.info("afterAssetIssueDevAddress2:" + afterAssetIssueContractAddress2); - logger.info("afterAssetIssueBAddress2:" + afterAssetIssueBAddress2); - logger.info("afterAssetIssueCAddress2:" + afterAssetIssueCAddress2); - logger.info("afterBalanceContractAddress2:" + afterBalanceContractAddress2); - - Assert.assertEquals(afterBalanceContractAddress1, afterBalanceContractAddress2); - Assert.assertTrue(afterAssetIssueContractAddress1 == afterAssetIssueContractAddress2); - Assert.assertTrue(afterAssetIssueBAddress1 == afterAssetIssueBAddress2); - Assert.assertTrue(afterAssetIssueCAddress1 == afterAssetIssueCAddress2); - } - - @Test(enabled = true, description = "Multistage delegatecall transferToken calltoken ID" - + " not exist") - public void deploy05TransferTokenContract() { - - Long afterAssetIssueDevAddress2 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - final Long afterAssetIssueContractAddress2 = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueBAddress2 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueCAddress2 = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - final Long afterBalanceContractAddress2 = PublicMethed - .queryAccount(transferTokenContractAddress, blockingStubFull).getBalance(); - - String param3 = - "\"" + Base58.encode58Check(btestAddress) + "\",\"" + Base58.encode58Check(ctestAddress) - + "\",\"" + Base58.encode58Check(transferTokenContractAddress) - + "\",1,\"" + assetAccountId.toStringUtf8() + "\""; - - final String triggerTxid3 = PublicMethed.triggerContract(transferTokenContractAddress, - "testIndelegateCall(address,address,address,uint256,trcToken)", - param3, false, 0, 1000000000L, tokenId1.toStringUtf8(), - 1, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(triggerTxid3 == null); - - Long afterAssetIssueDevAddress3 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, - blockingStubFull); - Long afterAssetIssueContractAddress3 = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueBAddress3 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueCAddress3 = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - Long afterBalanceContractAddress3 = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - - logger.info("afterAssetIssueCount3:" + afterAssetIssueDevAddress3); - logger.info("afterAssetIssueDevAddress3:" + afterAssetIssueContractAddress3); - logger.info("afterAssetIssueBAddress3:" + afterAssetIssueBAddress3); - logger.info("afterAssetIssueCAddress3:" + afterAssetIssueCAddress3); - logger.info("afterBalanceContractAddress3:" + afterBalanceContractAddress3); - - Assert.assertEquals(afterBalanceContractAddress2, afterBalanceContractAddress3); - Assert.assertTrue(afterAssetIssueContractAddress2 == afterAssetIssueContractAddress3); - Assert.assertTrue(afterAssetIssueBAddress2 == afterAssetIssueBAddress3); - Assert.assertTrue(afterAssetIssueCAddress2 == afterAssetIssueCAddress3); - } - - @Test(enabled = true, description = "Multistage delegatecall transferToken calltoken value " - + "not enough") - public void deploy06TransferTokenContract() { - Long afterAssetIssueDevAddress3 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - final Long afterAssetIssueContractAddress3 = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueBAddress3 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueCAddress3 = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - final Long afterBalanceContractAddress3 = PublicMethed - .queryAccount(transferTokenContractAddress, blockingStubFull).getBalance(); - String param4 = - "\"" + Base58.encode58Check(btestAddress) + "\",\"" + Base58.encode58Check(ctestAddress) - + "\",\"" + Base58.encode58Check(transferTokenContractAddress) - + "\",1,\"" + assetAccountId.toStringUtf8() + "\""; - - final String triggerTxid4 = PublicMethed.triggerContract(transferTokenContractAddress, - "testIndelegateCall(address,address,address,uint256,trcToken)", - param4, false, 0, 1000000000L, assetAccountId.toStringUtf8(), - 100000000, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(triggerTxid4 == null); - Long afterAssetIssueDevAddress4 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterAssetIssueContractAddress4 = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueBAddress4 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueCAddress4 = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - Long afterBalanceContractAddress4 = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - Long afterUserBalance4 = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("afterAssetIssueCount4:" + afterAssetIssueDevAddress4); - logger.info("afterAssetIssueDevAddress4:" + afterAssetIssueContractAddress4); - logger.info("afterAssetIssueBAddress4:" + afterAssetIssueBAddress4); - logger.info("afterAssetIssueCAddress4:" + afterAssetIssueCAddress4); - logger.info("afterBalanceContractAddress4:" + afterBalanceContractAddress4); - logger.info("afterUserBalance4:" + afterUserBalance4); - - Assert.assertEquals(afterBalanceContractAddress3, afterBalanceContractAddress4); - Assert.assertTrue(afterAssetIssueContractAddress3 == afterAssetIssueContractAddress4); - Assert.assertTrue(afterAssetIssueBAddress3 == afterAssetIssueBAddress4); - Assert.assertTrue(afterAssetIssueCAddress3 == afterAssetIssueCAddress4); - } - - @Test(enabled = true, description = "Multistage delegatecall transferToken use right tokenID," - + "tokenvalue") - public void deploy07TransferTokenContract() { - final Long afterAssetIssueDevAddress4 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - final Long afterAssetIssueContractAddress4 = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueBAddress4 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueCAddress4 = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - final Long afterBalanceContractAddress4 = PublicMethed - .queryAccount(transferTokenContractAddress, blockingStubFull).getBalance(); - String param5 = - "\"" + Base58.encode58Check(btestAddress) + "\",\"" + Base58.encode58Check(ctestAddress) - + "\",\"" + Base58.encode58Check(transferTokenContractAddress) - + "\",1,\"" + assetAccountId.toStringUtf8() + "\""; - - final String triggerTxid5 = PublicMethed.triggerContract(transferTokenContractAddress, - "testIndelegateCall(address,address,address,uint256,trcToken)", - param5, false, 0, 1000000000L, assetAccountId - .toStringUtf8(), 1, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById5 = PublicMethed - .getTransactionInfoById(triggerTxid5, blockingStubFull); - Assert.assertTrue(infoById5.get().getResultValue() == 0); - - Long afterAssetIssueDevAddress5 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterAssetIssueContractAddress5 = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueBAddress5 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueCAddress5 = PublicMethed - .getAssetIssueValue(ctestAddress, assetAccountId, blockingStubFull); - Long afterBalanceContractAddress5 = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - - logger.info("afterAssetIssueCount5:" + afterAssetIssueDevAddress5); - logger.info("afterAssetIssueDevAddress5:" + afterAssetIssueContractAddress5); - logger.info("afterAssetIssueBAddress5:" + afterAssetIssueBAddress5); - logger.info("afterAssetIssueCAddress5:" + afterAssetIssueCAddress5); - logger.info("afterBalanceContractAddress5:" + afterBalanceContractAddress5); - - Assert.assertEquals(afterBalanceContractAddress4, afterBalanceContractAddress5); - Assert.assertTrue(afterAssetIssueContractAddress4 + 2 == afterAssetIssueContractAddress5); - Assert.assertTrue(afterAssetIssueBAddress4 == afterAssetIssueBAddress5); - Assert.assertTrue(afterAssetIssueCAddress4 - 1 == afterAssetIssueCAddress5); - Assert.assertTrue(afterAssetIssueDevAddress4 - 1 == afterAssetIssueDevAddress5); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken028.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken028.java deleted file mode 100644 index 20ec1e96c18..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken028.java +++ /dev/null @@ -1,189 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken028 { - - private static final long TotalSupply = 10000000L; - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - int i1 = randomInt(6666666, 9999999); - ByteString tokenId1 = ByteString.copyFromUtf8(String.valueOf(i1)); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private byte[] transferTokenContractAddress; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private static int randomInt(int minInt, int maxInt) { - return (int) Math.round(Math.random() * (maxInt - minInt) + minInt); - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - @Test(enabled = true, description = "Deploy tokenBalanceWithSameName contract") - public void deploy01TransferTokenContract() { - PublicMethed.printAddress(dev001Key); - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 4048000000L, - fromAddress, testKey002, blockingStubFull)); - - - // freeze balance - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(dev001Address, 204800000, - 3, 1, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String tokenName = "testAI_" + randomInt(10000, 90000); - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - // deploy transferTokenContract - int originEnergyLimit = 50000; - String filePath = "src/test/resources/soliditycode/contractTrcToken028.sol"; - String contractName = "token"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - transferTokenContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000000L, 0, originEnergyLimit, assetAccountId.toStringUtf8(), - 100, null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - } - - - @Test(enabled = true, description = "Trigger tokenBalanceWithSameName") - public void deploy02TransferTokenContract() { - Long beforeAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long beforeAssetIssueUserAddress = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, blockingStubFull); - - Long beforeAssetIssueContractAddress = PublicMethed.getAssetIssueValue( - transferTokenContractAddress, assetAccountId, blockingStubFull); - Long beforeBalanceContractAddress = PublicMethed - .queryAccount(transferTokenContractAddress, blockingStubFull).getBalance(); - logger.info("beforeAssetIssueCount:" + beforeAssetIssueContractAddress); - logger.info("beforeAssetIssueDevAddress:" + beforeAssetIssueDevAddress); - logger.info("beforeAssetIssueUserAddress:" + beforeAssetIssueUserAddress); - logger.info("beforeBalanceContractAddress:" + beforeBalanceContractAddress); - String param = - "\"" + tokenId1 - .toStringUtf8() - + "\""; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "tokenBalanceWithSameName(trcToken)", - param, false, 0, 1000000000L, "0", - 0, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - Long afterAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterBalanceContractAddress = PublicMethed - .queryAccount(transferTokenContractAddress, blockingStubFull).getBalance(); - Long afterUserBalance = PublicMethed - .queryAccount(user001Address, blockingStubFull).getBalance(); - - logger.info("afterAssetIssueCount:" + afterAssetIssueDevAddress); - logger.info("afterAssetIssueDevAddress:" + afterAssetIssueContractAddress); - logger.info("afterBalanceContractAddress:" + afterBalanceContractAddress); - logger.info("afterUserBalance:" + afterUserBalance); - - Assert.assertEquals(afterBalanceContractAddress, beforeBalanceContractAddress); - Assert.assertTrue(afterAssetIssueContractAddress == beforeAssetIssueContractAddress); - - String triggerTxid1 = PublicMethed.triggerContract(transferTokenContractAddress, - "getA()", - "#", false, 0, 1000000000L, "0", - 0, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(triggerTxid1, blockingStubFull); - Long returnnumber1 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(returnnumber1 == 9); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken029.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken029.java deleted file mode 100644 index 9d719619b84..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken029.java +++ /dev/null @@ -1,174 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken029 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 10000000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - byte[] transferTokenContractAddress; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - @Test(enabled = true, description = "Deploy transferTokenwithSameName contract") - public void deploy01TransferTokenContract() { - - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 4048000000L, - fromAddress, testKey002, blockingStubFull)); - PublicMethed.printAddress(dev001Key); - - - // freeze balance - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(dev001Address, 204800000, - 0, 1, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, dev001Key, blockingStubFull)); - - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - // deploy transferTokenContract - int originEnergyLimit = 50000; - String filePath = "src/test/resources/soliditycode/contractTrcToken029.sol"; - String contractName = "token"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - transferTokenContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000000L, 0, originEnergyLimit, assetAccountId.toStringUtf8(), - 100, null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - /*Assert.assertFalse(PublicMethed.sendcoin(transferTokenContractAddress, - 1000000000L, fromAddress, testKey002, blockingStubFull));*/ - } - - /** - * constructor. - */ - - @Test(enabled = true, description = "Trigger transferTokenwithSameName") - public void deploy02TransferTokenContract() { - - Long beforeAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - Long beforeAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long beforeBalanceContractAddress = PublicMethed - .queryAccount(transferTokenContractAddress, blockingStubFull).getBalance(); - logger.info("beforeAssetIssueCount:" + beforeAssetIssueContractAddress); - logger.info("beforeAssetIssueDevAddress:" + beforeAssetIssueDevAddress); - logger.info("beforeBalanceContractAddress:" + beforeBalanceContractAddress); - - // user trigger A to transfer token to B - ByteString assetAccountDev = PublicMethed - .queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - ByteString fakeTokenId = ByteString - .copyFromUtf8(Long.toString(Long.valueOf(assetAccountDev.toStringUtf8()) + 100)); - String param = "\"" + fakeTokenId.toStringUtf8() + "\",\"1\""; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenWithSameName(trcToken,uint256)", - param, false, 0, 1000000000L, "0", - 0, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - Long afterAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterBalanceContractAddress = PublicMethed - .queryAccount(transferTokenContractAddress, blockingStubFull).getBalance(); - - logger.info("afterAssetIssueDevAddress:" + afterAssetIssueDevAddress); - logger.info("afterAssetIssueCount:" + afterAssetIssueContractAddress); - logger.info("afterBalanceContractAddress:" + afterBalanceContractAddress); - - - Assert.assertEquals(afterBalanceContractAddress, beforeBalanceContractAddress); - Assert.assertTrue(afterAssetIssueContractAddress == beforeAssetIssueContractAddress); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken030.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken030.java deleted file mode 100644 index 0562ab5a840..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken030.java +++ /dev/null @@ -1,187 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken030 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 10000000L; - private static ByteString assetAccountId = null; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - byte[] transferTokenContractAddress; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - - @Test(enabled = true, description = "Deploy suicide contract") - public void deploy01TransferTokenContract() { - - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 4048000000L, - fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 4048000000L, - fromAddress, testKey002, blockingStubFull)); - - - - // freeze balance - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(dev001Address, 204800000, - 0, 1, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, dev001Key, blockingStubFull)); - - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - // deploy transferTokenContract - int originEnergyLimit = 50000; - String filePath = "src/test/resources/soliditycode/contractTrcToken030.sol"; - String contractName = "token"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - transferTokenContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000000L, 0, originEnergyLimit, assetAccountId.toStringUtf8(), - 100, null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Trigger suicide contract,toaddress is other") - public void deploy02TransferTokenContract() { - Long beforeAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long beforeAssetIssueUserAddress = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, blockingStubFull); - - Long beforeAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long beforeBalanceContractAddress = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - final Long beforeUserBalance = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - logger.info("beforeAssetIssueCount:" + beforeAssetIssueContractAddress); - logger.info("beforeAssetIssueDevAddress:" + beforeAssetIssueDevAddress); - logger.info("beforeAssetIssueUserAddress:" + beforeAssetIssueUserAddress); - logger.info("beforeBalanceContractAddress:" + beforeBalanceContractAddress); - - // user trigger A to transfer token to B - String param = - "\"" + Base58.encode58Check(user001Address) - + "\""; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "kill(address)", - param, false, 0, 1000000000L, "0", - 0, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - Long afterAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueUserAddress = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, blockingStubFull); - Long afterBalanceContractAddress = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - final Long afterUserBalance = PublicMethed - .queryAccount(user001Address, blockingStubFull).getBalance(); - - logger.info("afterAssetIssueCount:" + afterAssetIssueDevAddress); - logger.info("afterAssetIssueDevAddress:" + afterAssetIssueContractAddress); - logger.info("afterAssetIssueUserAddress:" + afterAssetIssueUserAddress); - logger.info("afterBalanceContractAddress:" + afterBalanceContractAddress); - - Assert.assertTrue(afterBalanceContractAddress == 0); - Assert.assertTrue(beforeAssetIssueUserAddress + beforeAssetIssueContractAddress - == afterAssetIssueUserAddress); - Assert.assertTrue(beforeUserBalance + beforeBalanceContractAddress - == afterUserBalance); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - - PublicMethed.unFreezeBalance(dev001Address, dev001Key, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(user001Address, user001Key, 1, user001Address, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken031.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken031.java deleted file mode 100644 index 598bf4faac3..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken031.java +++ /dev/null @@ -1,171 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken031 { - - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 10000000L; - private static ByteString assetAccountId = null; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - byte[] transferTokenContractAddress; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - @Test(enabled = true, description = "Deploy suicide contract") - public void deploy01TransferTokenContract() { - PublicMethed.printAddress(dev001Key); - - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 4048000000L, fromAddress, - testKey002, blockingStubFull)); - // freeze balance - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(dev001Address, 204800000, - 0, 1, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - logger.info("assetId: " + assetAccountId); - // deploy transferTokenContract - int originEnergyLimit = 50000; - String filePath = "src/test/resources/soliditycode/contractTrcToken031.sol"; - String contractName = "token"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - transferTokenContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000000L, 0, originEnergyLimit, assetAccountId.toStringUtf8(), - 100, null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(transferTokenContractAddress); - - /*Assert.assertFalse(PublicMethed.sendcoin(transferTokenContractAddress, - 1000000000L, fromAddress, testKey002, blockingStubFull));*/ - } - - @Test(enabled = true, description = "Trigger suicide contract,toaddress is myself") - public void deploy02TransferTokenContract() { - Long beforeAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - Long beforeAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long beforeBalanceContractAddress = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - - logger.info("beforeAssetIssueCount:" + beforeAssetIssueContractAddress); - logger.info("beforeAssetIssueDevAddress:" + beforeAssetIssueDevAddress); - logger.info("beforeBalanceContractAddress:" + beforeBalanceContractAddress); - - String param = - "\"" + Base58.encode58Check(transferTokenContractAddress) - + "\""; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "kill(address)", param, false, 0, 1000000000L, - "0", 0, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - - Long afterAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterBalanceContractAddress = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - - logger.info("afterAssetIssueCount:" + afterAssetIssueDevAddress); - logger.info("afterAssetIssueDevAddress:" + afterAssetIssueContractAddress); - logger.info("afterBalanceContractAddress:" + afterBalanceContractAddress); - - - Assert.assertTrue(afterBalanceContractAddress == 0); - Assert.assertTrue(afterAssetIssueContractAddress == 0); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.unFreezeBalance(dev001Address, dev001Key, 1, dev001Address, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken034.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken034.java deleted file mode 100644 index b58777a69f9..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken034.java +++ /dev/null @@ -1,195 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken034 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 10000000L; - private static ByteString assetAccountId = null; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - byte[] transferTokenContractAddress; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 4048000000L, - fromAddress, testKey002, blockingStubFull)); - logger.info( - "dev001Address:" + Base58.encode58Check(dev001Address)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 4048000000L, - fromAddress, testKey002, blockingStubFull)); - logger.info( - "user001Address:" + Base58.encode58Check(user001Address)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - - @Test(enabled = true, description = "Deploy after transfertoken execute require contract") - public void deploy01TransferTokenContract() { - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - // deploy transferTokenContract - int originEnergyLimit = 50000; - String filePath = "src/test/resources/soliditycode/contractTrcToken034.sol"; - String contractName = "token"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - transferTokenContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 100000000L, 0, originEnergyLimit, assetAccountId.toStringUtf8(), - 50, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - } - - @Test(enabled = true, description = "Trigger after transfertoken execute require contract") - public void deploy02TransferTokenContract() { - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - info = PublicMethed.queryAccount(dev001Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long beforeAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long beforeAssetIssueUserAddress = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, blockingStubFull); - - Long beforeAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("beforeAssetIssueCount:" + beforeAssetIssueContractAddress); - logger.info("beforeAssetIssueDevAddress:" + beforeAssetIssueDevAddress); - logger.info("beforeAssetIssueUserAddress:" + beforeAssetIssueUserAddress); - - String param = - "\"" + Base58.encode58Check(user001Address) + "\",1,\"" + assetAccountId - .toStringUtf8() - + "\""; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "failTransferTokenRevert(address,uint256,trcToken)", - param, false, 0, 1000000000L, "0", - 0, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 1); - - Account infoafter = PublicMethed.queryAccount(dev001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueUserAddress = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, blockingStubFull); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterAssetIssueCount:" + afterAssetIssueDevAddress); - logger.info("afterAssetIssueDevAddress:" + afterAssetIssueContractAddress); - logger.info("afterAssetIssueUserAddress:" + afterAssetIssueUserAddress); - - Assert.assertEquals(beforeAssetIssueDevAddress, afterAssetIssueDevAddress); - Assert.assertEquals(beforeAssetIssueUserAddress, afterAssetIssueUserAddress); - Assert.assertEquals(beforeAssetIssueContractAddress, afterAssetIssueContractAddress); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(dev001Address, dev001Key, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(user001Address, user001Key, 1, user001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken035.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken035.java deleted file mode 100644 index 73ec82928cf..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken035.java +++ /dev/null @@ -1,195 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken035 { - - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 10000000L; - private static ByteString assetAccountId = null; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - byte[] transferTokenContractAddress; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - - @Test(enabled = true, description = "Deploy after transfertoken execute assert contract") - public void deploy01TransferTokenContract() { - - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 9999000000L, fromAddress, - testKey002, blockingStubFull)); - logger.info( - "dev001Address:" + Base58.encode58Check(dev001Address)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 4048000000L, fromAddress, - testKey002, blockingStubFull)); - logger.info( - "user001Address:" + Base58.encode58Check(user001Address)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - // deploy transferTokenContract - int originEnergyLimit = 50000; - String filePath = "src/test/resources/soliditycode/contractTrcToken035.sol"; - String contractName = "token"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - transferTokenContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 100000000L, 0, originEnergyLimit, assetAccountId.toStringUtf8(), - 50, null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Trigger after transfertoken execute assert contract") - public void deploy02TransferTokenContract() { - Account info; - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(dev001Address, blockingStubFull); - info = PublicMethed.queryAccount(dev001Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long beforeAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long beforeAssetIssueUserAddress = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, blockingStubFull); - - Long beforeAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("beforeAssetIssueCount:" + beforeAssetIssueContractAddress); - logger.info("beforeAssetIssueDevAddress:" + beforeAssetIssueDevAddress); - logger.info("beforeAssetIssueUserAddress:" + beforeAssetIssueUserAddress); - - String param = - "\"" + Base58.encode58Check(user001Address) + "\",1,\"" + assetAccountId - .toStringUtf8() - + "\""; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "failTransferTokenError(address,uint256,trcToken)", - param, false, 0, 1000000000L, "0", - 0, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 1); - - Account infoafter = PublicMethed.queryAccount(dev001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(dev001Address, blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueUserAddress = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, blockingStubFull); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterAssetIssueCount:" + afterAssetIssueDevAddress); - logger.info("afterAssetIssueDevAddress:" + afterAssetIssueContractAddress); - logger.info("afterAssetIssueUserAddress:" + afterAssetIssueUserAddress); - - Assert.assertEquals(beforeAssetIssueDevAddress, afterAssetIssueDevAddress); - Assert.assertEquals(beforeAssetIssueUserAddress, afterAssetIssueUserAddress); - Assert.assertEquals(beforeAssetIssueContractAddress, afterAssetIssueContractAddress); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(dev001Address, dev001Key, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(user001Address, user001Key, 1, user001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken036.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken036.java deleted file mode 100644 index 8d020a433fe..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken036.java +++ /dev/null @@ -1,527 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken036 { - - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 10000000L; - private static ByteString assetAccountId = null; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - byte[] transferTokenContractAddress; - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - int originEnergyLimit = 50000; - byte[] transferTokenWithPureTestAddress; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - - @Test(enabled = false, description = "Deploy contract") - public void deploy01TransferTokenContract() { - - Assert - .assertTrue(PublicMethed.sendcoin(dev001Address, 9999000000L, fromAddress, - testKey002, blockingStubFull)); - logger.info( - "dev001Address:" + Base58.encode58Check(dev001Address)); - Assert - .assertTrue(PublicMethed.sendcoin(user001Address, 4048000000L, fromAddress, - testKey002, blockingStubFull)); - logger.info( - "user001Address:" + Base58.encode58Check(user001Address)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - // deploy transferTokenContract - // String filePath = "src/test/resources/soliditycode/contractTrcToken036.sol"; - // String contractName = "IllegalDecorate"; - // HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - // String code = retMap.get("byteCode").toString(); - // String abi = retMap.get("abI").toString(); - // transferTokenContractAddress = PublicMethed - // .deployContract(contractName, abi, code, "", maxFeeLimit, - // 0L, 0, originEnergyLimit, "0", - // 0, null, dev001Key, dev001Address, - // blockingStubFull); - - - // - // // devAddress transfer token to userAddress - // PublicMethed - // .transferAsset(transferTokenContractAddress, assetAccountId.toByteArray(), 100, - // dev001Address, - // dev001Key, - // blockingStubFull); - // Assert - // .assertTrue(PublicMethed.sendcoin(transferTokenContractAddress, 100, fromAddress, - // testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = false, description = "Trigger transferTokenWithPure contract") - public void deploy02TransferTokenContract() { - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - info = PublicMethed.queryAccount(dev001Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long beforeAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, - blockingStubFull); - Long beforeAssetIssueUserAddress = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, - blockingStubFull); - - Long beforeAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, - assetAccountId, - blockingStubFull); - Long user001AddressAddressBalance = PublicMethed - .queryAccount(user001Address, blockingStubFull).getBalance(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("beforeAssetIssueCount:" + beforeAssetIssueContractAddress); - logger.info("beforeAssetIssueDevAddress:" + beforeAssetIssueDevAddress); - logger.info("beforeAssetIssueUserAddress:" + beforeAssetIssueUserAddress); - logger.info("user001AddressAddressBalance:" + user001AddressAddressBalance); - - // user trigger A to transfer token to B - String param = - "\"" + Base58.encode58Check(user001Address) + "\",\"1\""; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenWithPure(address,uint256)", - param, false, 10, 1000000000L, assetAccountId - .toStringUtf8(), - 10, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account infoafter = PublicMethed.queryAccount(dev001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, - blockingStubFull); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, - assetAccountId, - blockingStubFull); - Long afterAssetIssueUserAddress = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, - blockingStubFull); - Long afteruser001AddressAddressBalance = PublicMethed - .queryAccount(user001Address, blockingStubFull).getBalance(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterAssetIssueCount:" + afterAssetIssueDevAddress); - logger.info("afterAssetIssueDevAddress:" + afterAssetIssueContractAddress); - logger.info("afterAssetIssueUserAddress:" + afterAssetIssueUserAddress); - logger.info("afterContractAddressBalance:" + afteruser001AddressAddressBalance); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(beforeAssetIssueDevAddress - 10 == afterAssetIssueDevAddress); - Assert.assertTrue(beforeAssetIssueUserAddress + 10 == afterAssetIssueUserAddress); - Assert.assertTrue(user001AddressAddressBalance + 10 == afteruser001AddressAddressBalance); - - String filePath = "src/test/resources/soliditycode/contractTrcToken036.sol"; - String contractName1 = "IllegalDecorate1"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - transferTokenWithPureTestAddress = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 0L, 0, originEnergyLimit, "0", - 0, null, dev001Key, dev001Address, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // devAddress transfer token to userAddress - PublicMethed - .transferAsset(transferTokenWithPureTestAddress, assetAccountId.toByteArray(), 100, - dev001Address, - dev001Key, - blockingStubFull); - Assert - .assertTrue(PublicMethed.sendcoin(transferTokenWithPureTestAddress, 100, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = false, description = "Trigger transferTokenWithConstant contract") - public void deploy03TransferTokenContract() { - Account info1; - AccountResourceMessage resourceInfo1 = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - info1 = PublicMethed.queryAccount(dev001Address, blockingStubFull); - Long beforeBalance1 = info1.getBalance(); - Long beforeEnergyUsed1 = resourceInfo1.getEnergyUsed(); - Long beforeNetUsed1 = resourceInfo1.getNetUsed(); - Long beforeFreeNetUsed1 = resourceInfo1.getFreeNetUsed(); - Long beforeAssetIssueDevAddress1 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, - blockingStubFull); - Long beforeAssetIssueUserAddress1 = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, - blockingStubFull); - - Long beforeAssetIssueContractAddress1 = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, - assetAccountId, - blockingStubFull); - Long user001AddressAddressBalance1 = PublicMethed - .queryAccount(user001Address, blockingStubFull).getBalance(); - logger.info("beforeBalance:" + beforeBalance1); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed1); - logger.info("beforeNetUsed:" + beforeNetUsed1); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed1); - logger.info("beforeAssetIssueCount:" + beforeAssetIssueContractAddress1); - logger.info("beforeAssetIssueDevAddress:" + beforeAssetIssueDevAddress1); - logger.info("beforeAssetIssueUserAddress:" + beforeAssetIssueUserAddress1); - logger.info("user001AddressAddressBalance:" + user001AddressAddressBalance1); - - // user trigger A to transfer token to B - String param1 = - "\"" + Base58.encode58Check(user001Address) + "\",\"1\""; - - final String triggerTxid1 = PublicMethed.triggerContract(transferTokenWithPureTestAddress, - "transferTokenWithConstant(address,uint256)", - param1, false, 10, 1000000000L, assetAccountId - .toStringUtf8(), - 10, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account infoafter1 = PublicMethed.queryAccount(dev001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter1 = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterAssetIssueDevAddress1 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, - blockingStubFull); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - Long afterAssetIssueContractAddress1 = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, - assetAccountId, - blockingStubFull); - Long afterAssetIssueUserAddress1 = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, - blockingStubFull); - Long afteruser001AddressAddressBalance1 = PublicMethed - .queryAccount(user001Address, blockingStubFull).getBalance(); - - logger.info("afterBalance:" + afterBalance1); - logger.info("afterEnergyUsed:" + afterEnergyUsed1); - logger.info("afterNetUsed:" + afterNetUsed1); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed1); - logger.info("afterAssetIssueCount:" + afterAssetIssueDevAddress1); - logger.info("afterAssetIssueDevAddress:" + afterAssetIssueContractAddress1); - logger.info("afterAssetIssueUserAddress:" + afterAssetIssueUserAddress1); - logger.info("afterContractAddressBalance:" + afteruser001AddressAddressBalance1); - - Optional infoById1 = PublicMethed - .getTransactionInfoById(triggerTxid1, blockingStubFull); - Assert.assertEquals(beforeBalance1, afterBalance1); - Assert.assertEquals(beforeAssetIssueDevAddress1, afterAssetIssueDevAddress1); - Assert.assertEquals(beforeAssetIssueUserAddress1, afterAssetIssueUserAddress1); - Assert.assertEquals(user001AddressAddressBalance1, afteruser001AddressAddressBalance1); - } - - @Test(enabled = false, description = "Trigger transferTokenWithView contract") - public void deploy04TransferTokenContract() { - String filePath2 = "src/test/resources/soliditycode/contractTrcToken036.sol"; - String contractName2 = "IllegalDecorate2"; - HashMap retMap2 = PublicMethed.getBycodeAbi(filePath2, contractName2); - - String code2 = retMap2.get("byteCode").toString(); - String abi2 = retMap2.get("abI").toString(); - byte[] transferTokenWithViewAddress = PublicMethed - .deployContract(contractName2, abi2, code2, "", maxFeeLimit, - 0L, 0, originEnergyLimit, "0", - 0, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // devAddress transfer token to userAddress - PublicMethed - .transferAsset(transferTokenWithViewAddress, assetAccountId.toByteArray(), 100, - dev001Address, - dev001Key, - blockingStubFull); - Assert - .assertTrue(PublicMethed.sendcoin(transferTokenWithViewAddress, 100, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account info2; - AccountResourceMessage resourceInfo2 = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - info2 = PublicMethed.queryAccount(dev001Address, blockingStubFull); - Long beforeBalance2 = info2.getBalance(); - Long beforeEnergyUsed2 = resourceInfo2.getEnergyUsed(); - Long beforeNetUsed2 = resourceInfo2.getNetUsed(); - Long beforeFreeNetUsed2 = resourceInfo2.getFreeNetUsed(); - Long beforeAssetIssueDevAddress2 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, - blockingStubFull); - Long beforeAssetIssueUserAddress2 = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, - blockingStubFull); - - Long beforeAssetIssueContractAddress2 = PublicMethed - .getAssetIssueValue(transferTokenWithViewAddress, - assetAccountId, - blockingStubFull); - Long user001AddressAddressBalance2 = PublicMethed - .queryAccount(user001Address, blockingStubFull).getBalance(); - logger.info("beforeAssetIssueContractAddress2:" + beforeAssetIssueContractAddress2); - logger.info("beforeAssetIssueDevAddress2:" + beforeAssetIssueDevAddress2); - logger.info("beforeAssetIssueUserAddress2:" + beforeAssetIssueUserAddress2); - logger.info("user001AddressAddressBalance2:" + user001AddressAddressBalance2); - - // user trigger A to transfer token to B - String param2 = - "\"" + Base58.encode58Check(user001Address) + "\",\"1\""; - - String triggerTxid2 = PublicMethed.triggerContract(transferTokenWithViewAddress, - "transferTokenWithView(address,uint256)", - param2, false, 10, 1000000000L, assetAccountId - .toStringUtf8(), - 10, dev001Address, dev001Key, - blockingStubFull); - - Account infoafter2 = PublicMethed.queryAccount(dev001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter2 = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance2 = infoafter2.getBalance(); - Long afterEnergyUsed2 = resourceInfoafter2.getEnergyUsed(); - Long afterAssetIssueDevAddress2 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, - blockingStubFull); - Long afterNetUsed2 = resourceInfoafter2.getNetUsed(); - Long afterFreeNetUsed2 = resourceInfoafter2.getFreeNetUsed(); - Long afterAssetIssueContractAddress2 = PublicMethed - .getAssetIssueValue(transferTokenWithViewAddress, - assetAccountId, - blockingStubFull); - Long afterAssetIssueUserAddress2 = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, - blockingStubFull); - Long afteruser001AddressAddressBalance2 = PublicMethed - .queryAccount(user001Address, blockingStubFull).getBalance(); - - logger.info("afterAssetIssueDevAddress2:" + afterAssetIssueDevAddress2); - logger.info("afterAssetIssueContractAddress2:" + afterAssetIssueContractAddress2); - logger.info("afterAssetIssueUserAddress2:" + afterAssetIssueUserAddress2); - logger.info("afteruser001AddressAddressBalance2:" + afteruser001AddressAddressBalance2); - - Optional infoById2 = PublicMethed - .getTransactionInfoById(triggerTxid2, blockingStubFull); - - Assert.assertEquals(beforeAssetIssueDevAddress2, afterAssetIssueDevAddress2); - Assert.assertEquals(beforeAssetIssueUserAddress2, afterAssetIssueUserAddress2); - Assert.assertEquals(user001AddressAddressBalance2, afteruser001AddressAddressBalance2); - } - - @Test(enabled = false, description = "Trigger transferTokenWithNoPayable contract") - public void deploy05TransferTokenContract() { - String filePath = "src/test/resources/soliditycode/contractTrcToken036.sol"; - String contractName3 = "IllegalDecorate3"; - HashMap retMap3 = PublicMethed.getBycodeAbi(filePath, contractName3); - - String code3 = retMap3.get("byteCode").toString(); - String abi3 = retMap3.get("abI").toString(); - byte[] transferTokenWithOutPayableTestAddress = PublicMethed - .deployContract(contractName3, abi3, code3, "", maxFeeLimit, - 0L, 0, originEnergyLimit, "0", - 0, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - PublicMethed - .transferAsset(transferTokenWithOutPayableTestAddress, assetAccountId.toByteArray(), 100, - dev001Address, - dev001Key, - blockingStubFull); - Assert - .assertTrue(PublicMethed.sendcoin(transferTokenWithOutPayableTestAddress, 100, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info3; - AccountResourceMessage resourceInfo3 = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - info3 = PublicMethed.queryAccount(dev001Address, blockingStubFull); - Long beforeBalance3 = info3.getBalance(); - Long beforeEnergyUsed3 = resourceInfo3.getEnergyUsed(); - Long beforeNetUsed3 = resourceInfo3.getNetUsed(); - Long beforeFreeNetUsed3 = resourceInfo3.getFreeNetUsed(); - Long beforeAssetIssueDevAddress3 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, - blockingStubFull); - Long beforeAssetIssueUserAddress3 = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, - blockingStubFull); - - Long beforeAssetIssueContractAddress3 = PublicMethed - .getAssetIssueValue( - transferTokenWithOutPayableTestAddress, - assetAccountId, - blockingStubFull); - Long user001AddressAddressBalance3 = PublicMethed - .queryAccount(user001Address, blockingStubFull).getBalance(); - logger.info("beforeBalance:" + beforeBalance3); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed3); - logger.info("beforeNetUsed:" + beforeNetUsed3); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed3); - logger.info("beforeAssetIssueCount:" + beforeAssetIssueContractAddress3); - logger.info("beforeAssetIssueDevAddress:" + beforeAssetIssueDevAddress3); - logger.info("beforeAssetIssueUserAddress:" + beforeAssetIssueUserAddress3); - logger.info("user001AddressAddressBalance:" + user001AddressAddressBalance3); - - String param3 = - "\"" + Base58.encode58Check(user001Address) + "\",\"1\""; - - String triggerTxid3 = PublicMethed.triggerContract(transferTokenWithOutPayableTestAddress, - "transferTokenWithOutPayable(address,uint256)", - param3, false, 10, 1000000000L, assetAccountId - .toStringUtf8(), - 10, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account infoafter3 = PublicMethed.queryAccount(dev001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter3 = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance3 = infoafter3.getBalance(); - Long afterEnergyUsed3 = resourceInfoafter3.getEnergyUsed(); - Long afterAssetIssueDevAddress3 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, - blockingStubFull); - Long afterNetUsed3 = resourceInfoafter3.getNetUsed(); - Long afterFreeNetUsed3 = resourceInfoafter3.getFreeNetUsed(); - Long afterAssetIssueContractAddress3 = PublicMethed - .getAssetIssueValue( - transferTokenWithOutPayableTestAddress, assetAccountId, - blockingStubFull); - Long afterAssetIssueUserAddress3 = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, - blockingStubFull); - Long afteruser001AddressAddressBalance3 = PublicMethed - .queryAccount(user001Address, blockingStubFull).getBalance(); - - Optional infoById3 = PublicMethed - .getTransactionInfoById(triggerTxid3, blockingStubFull); - Assert.assertTrue(infoById3.get().getResultValue() == 1); - - Assert.assertEquals(beforeAssetIssueDevAddress3, afterAssetIssueDevAddress3); - Assert.assertEquals(beforeAssetIssueUserAddress3, afterAssetIssueUserAddress3); - Assert.assertEquals(user001AddressAddressBalance3, afteruser001AddressAddressBalance3); - PublicMethed.unFreezeBalance(dev001Address, dev001Key, 1, - null, blockingStubFull); - PublicMethed.unFreezeBalance(user001Address, user001Key, 1, - null, blockingStubFull); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken037.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken037.java deleted file mode 100644 index caa2d493bed..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken037.java +++ /dev/null @@ -1,205 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken037 { - - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 10000000L; - private static ByteString assetAccountId = null; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - - @Test(enabled = true, description = "Multi-level call transferToken tokenBalance") - public void deploy01TransferTokenContract() { - - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 4048000000L, - fromAddress, testKey002, blockingStubFull)); - logger.info("dev001Address:" + Base58.encode58Check(dev001Address)); - - // freeze balance - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(dev001Address, 204800000, - 0, 1, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - // deploy transferTokenContract - int originEnergyLimit = 50000; - - String filePath = "src/test/resources/soliditycode/contractTrcToken037.sol"; - String contractName = "receiveTrc10"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] btestAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, - 0, originEnergyLimit, "0", 0, - null, dev001Key, dev001Address, blockingStubFull); - - String contractName1 = "transferTrc10"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - byte[] transferTokenContractAddress = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 0L, 0, originEnergyLimit, "0", - 0, null, dev001Key, dev001Address, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - info = PublicMethed.queryAccount(dev001Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long beforeAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - Long beforeAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long beforeAssetIssueBAddress = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - - Long beforeBalanceContractAddress = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("beforeAssetIssueContractAddress:" + beforeAssetIssueContractAddress); - logger.info("beforeAssetIssueBAddress:" + beforeAssetIssueBAddress); - - logger.info("beforeAssetIssueDevAddress:" + beforeAssetIssueDevAddress); - logger.info("beforeBalanceContractAddress:" + beforeBalanceContractAddress); - - String param = - "\"" + Base58.encode58Check(btestAddress) + "\""; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "receive(address)", - param, false, 0, 1000000000L, assetAccountId.toStringUtf8(), - 10, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - Account infoafter = PublicMethed.queryAccount(dev001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueBAddress = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - - Long afterBalanceContractAddress = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterAssetIssueCount:" + afterAssetIssueDevAddress); - logger.info("afterAssetIssueDevAddress:" + afterAssetIssueContractAddress); - logger.info("afterAssetIssueBAddress:" + afterAssetIssueBAddress); - logger.info("afterBalanceContractAddress:" + afterBalanceContractAddress); - - Assert.assertEquals(afterBalanceContractAddress, beforeBalanceContractAddress); - Assert.assertTrue(afterAssetIssueDevAddress == beforeAssetIssueDevAddress - 10); - Assert.assertTrue(afterAssetIssueBAddress == beforeAssetIssueBAddress + 10); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(dev001Address, dev001Key, 1, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken038.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken038.java deleted file mode 100644 index 63d88c71765..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken038.java +++ /dev/null @@ -1,209 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken038 { - - - private static final long TotalSupply = 10000000L; - private static final long now = System.currentTimeMillis(); - private static ByteString assetAccountId = null; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - - @Test(enabled = true, description = "Multi-level call transferToken assert tokenBalance ") - public void deployTransferTokenContract() { - - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 4048000000L, - fromAddress, testKey002, blockingStubFull)); - logger.info("dev001Address:" + Base58.encode58Check(dev001Address)); - - // freeze balance - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(dev001Address, 204800000, - 3, 1, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, dev001Key, blockingStubFull)); - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertFalse(assetAccountId.toStringUtf8().equals("")); - - // deploy transferTokenContract - int originEnergyLimit = 50000; - - String filePath = "src/test/resources/soliditycode/contractTrcToken038.sol"; - String contractName2 = "transferTrc10"; - HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); - String code2 = retMap2.get("byteCode").toString(); - String abi2 = retMap2.get("abI").toString(); - final byte[] transferTokenContractAddress = PublicMethed - .deployContract(contractName2, abi2, code2, "", maxFeeLimit, - 0L, 0, originEnergyLimit, "0", - 0, null, dev001Key, dev001Address, blockingStubFull); - - String contractName = "receiveTrc10"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] btestAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 0, originEnergyLimit, "0", - 0, null, dev001Key, dev001Address, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - /*Assert.assertFalse(PublicMethed.sendcoin(transferTokenContractAddress, 1000000000L, - fromAddress, testKey002, blockingStubFull)); - Assert.assertFalse(PublicMethed.sendcoin(btestAddress, 1000000000L, - fromAddress, testKey002, blockingStubFull));*/ - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - info = PublicMethed.queryAccount(dev001Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long beforeAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - Long beforeAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long beforeAssetIssueBAddress = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - - Long beforeBalanceContractAddress = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("beforeAssetIssueContractAddress:" + beforeAssetIssueContractAddress); - logger.info("beforeAssetIssueBAddress:" + beforeAssetIssueBAddress); - logger.info("beforeAssetIssueDevAddress:" + beforeAssetIssueDevAddress); - logger.info("beforeBalanceContractAddress:" + beforeBalanceContractAddress); - - String param = - "\"" + Base58.encode58Check(btestAddress) + "\""; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "receive(address)", - param, false, 0, 1000000000L, assetAccountId.toStringUtf8(), - 1, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 1); - - Account infoafter = PublicMethed.queryAccount(dev001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueBAddress = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, blockingStubFull); - - Long afterBalanceContractAddress = PublicMethed.queryAccount(transferTokenContractAddress, - blockingStubFull).getBalance(); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterAssetIssueCount:" + afterAssetIssueDevAddress); - logger.info("afterAssetIssueDevAddress:" + afterAssetIssueContractAddress); - logger.info("afterAssetIssueBAddress:" + afterAssetIssueBAddress); - logger.info("afterBalanceContractAddress:" + afterBalanceContractAddress); - - Assert.assertEquals(afterBalanceContractAddress, beforeBalanceContractAddress); - Assert.assertTrue(afterAssetIssueContractAddress == beforeAssetIssueContractAddress); - Assert.assertTrue(afterAssetIssueBAddress == beforeAssetIssueBAddress); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(dev001Address, dev001Key, 1, null, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken039.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken039.java deleted file mode 100644 index 85a910193ba..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken039.java +++ /dev/null @@ -1,345 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken039 { - - private static final long TotalSupply = 10000000L; - private static final long now = System.currentTimeMillis(); - private static ByteString assetAccountId = null; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - byte[] proxyTestAddress; - byte[] atestAddress; - byte[] btestAddress; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - - @Test(enabled = true, description = "Deploy Proxy contract") - public void deploy01TransferTokenContract() { - Assert - .assertTrue(PublicMethed.sendcoin(dev001Address, 4048000000L, fromAddress, - testKey002, blockingStubFull)); - logger.info("dev001Address:" + Base58.encode58Check(dev001Address)); - Assert - .assertTrue(PublicMethed.sendcoin(user001Address, 4048000000L, fromAddress, - testKey002, blockingStubFull)); - logger.info("user001Address:" + Base58.encode58Check(user001Address)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // freeze balance - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(dev001Address, 204800000, - 0, 1, dev001Key, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(user001Address, 2048000000, - 0, 1, user001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - // deploy transferTokenContract - int originEnergyLimit = 50000; - - String filePath = "src/test/resources/soliditycode/contractTrcToken039.sol"; - String contractName = "Proxy"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - proxyTestAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 1000L, 0, originEnergyLimit, assetAccountId.toStringUtf8(), - 1000, null, dev001Key, dev001Address, - blockingStubFull); - - String contractName1 = "A"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - atestAddress = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 0L, 0, originEnergyLimit, "0", - 0, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName2 = "B"; - HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); - String code2 = retMap2.get("byteCode").toString(); - String abi2 = retMap2.get("abI").toString(); - btestAddress = PublicMethed - .deployContract(contractName2, abi2, code2, "", maxFeeLimit, - 0L, 0, originEnergyLimit, "0", - 0, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - } - - @Test(enabled = true, dependsOnMethods = "deploy01TransferTokenContract", - description = "Trigger Proxy contract use AddressA") - public void deploy02TransferTokenContract() { - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - info = PublicMethed.queryAccount(dev001Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - - Long beforeAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long beforeAssetIssueUserAddress = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, - blockingStubFull); - - Long beforeAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(proxyTestAddress, assetAccountId, - blockingStubFull); - Long beforeAssetIssueBAddress = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, - blockingStubFull); - Long beforeAssetIssueAAddress = PublicMethed - .getAssetIssueValue(atestAddress, assetAccountId, - blockingStubFull); - Long beforeBalanceContractAddress = PublicMethed.queryAccount(proxyTestAddress, - blockingStubFull).getBalance(); - Long beforeUserBalance = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - logger.info("beforeBalance:" + beforeBalance); - - logger.info("beforeAssetIssueContractAddress:" + beforeAssetIssueContractAddress); - logger.info("beforeAssetIssueBAddress:" + beforeAssetIssueBAddress); - - logger.info("beforeAssetIssueDevAddress:" + beforeAssetIssueDevAddress); - logger.info("beforeAssetIssueUserAddress:" + beforeAssetIssueUserAddress); - - String param = - "\"" + Base58.encode58Check(atestAddress) + "\""; - String param1 = - "\"" + "1" + "\",\"" + Base58.encode58Check(user001Address) + "\",\"" + assetAccountId - .toStringUtf8() - + "\""; - - String triggerTxid = PublicMethed.triggerContract(proxyTestAddress, - "upgradeTo(address)", - param, false, 0, 1000000000L, "0", - 0, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - final String triggerTxid1 = PublicMethed.triggerContract(proxyTestAddress, - "trans(uint256,address,trcToken)", - param1, false, 0, 1000000000L, assetAccountId - .toStringUtf8(), - 1, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long afterAssetIssueDevAddress = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(proxyTestAddress, assetAccountId, - blockingStubFull); - Long afterAssetIssueBAddress = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, - blockingStubFull); - Long afterAssetIssueAAddress = PublicMethed - .getAssetIssueValue(atestAddress, assetAccountId, - blockingStubFull); - Long afterAssetIssueUserAddress = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, blockingStubFull); - Long afterBalanceContractAddress = PublicMethed.queryAccount(proxyTestAddress, - blockingStubFull).getBalance(); - Long afterUserBalance = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - logger.info("afterAssetIssueCount:" + afterAssetIssueDevAddress); - logger.info("afterAssetIssueDevAddress:" + afterAssetIssueContractAddress); - logger.info("afterAssetIssueBAddress:" + afterAssetIssueBAddress); - logger.info("afterAssetIssueUserAddress:" + afterAssetIssueUserAddress); - logger.info("afterBalanceContractAddress:" + afterBalanceContractAddress); - logger.info("afterUserBalance:" + afterUserBalance); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid1, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterAssetIssueUserAddress == beforeAssetIssueUserAddress); - Assert.assertTrue(afterBalanceContractAddress == beforeBalanceContractAddress - 1); - Assert.assertTrue(afterAssetIssueContractAddress == beforeAssetIssueContractAddress + 1); - Assert.assertTrue(afterAssetIssueDevAddress == beforeAssetIssueDevAddress - 1); - Assert.assertTrue(afterUserBalance == beforeUserBalance + 1); - Assert.assertTrue(afterAssetIssueUserAddress == afterAssetIssueUserAddress); - Assert.assertTrue(afterAssetIssueBAddress == beforeAssetIssueBAddress); - } - - @Test(enabled = true,dependsOnMethods = "deploy02TransferTokenContract", - description = "Trigger Proxy contract use AddressB") - public void deploy03TransferTokenContract() { - Account info1; - AccountResourceMessage resourceInfo1 = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - info1 = PublicMethed.queryAccount(dev001Address, blockingStubFull); - Long beforeBalance1 = info1.getBalance(); - Long beforeAssetIssueDevAddress1 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long beforeAssetIssueUserAddress1 = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, - blockingStubFull); - - Long beforeAssetIssueContractAddress1 = PublicMethed - .getAssetIssueValue(proxyTestAddress, assetAccountId, - blockingStubFull); - Long beforeAssetIssueBAddress1 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, - blockingStubFull); - - Long beforeBalanceContractAddress1 = PublicMethed.queryAccount(proxyTestAddress, - blockingStubFull).getBalance(); - Long beforeUserBalance1 = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - logger.info("beforeBalance1:" + beforeBalance1); - logger.info("beforeAssetIssueContractAddress1:" + beforeAssetIssueContractAddress1); - logger.info("beforeAssetIssueBAddress1:" + beforeAssetIssueBAddress1); - - logger.info("beforeAssetIssueDevAddress1:" + beforeAssetIssueDevAddress1); - logger.info("beforeAssetIssueUserAddress1:" + beforeAssetIssueUserAddress1); - logger.info("beforeBalanceContractAddress1:" + beforeBalanceContractAddress1); - logger.info("beforeUserBalance1:" + beforeUserBalance1); - String param3 = - "\"" + Base58.encode58Check(btestAddress) + "\""; - String param2 = - "\"" + "1" + "\",\"" + Base58.encode58Check(user001Address) + "\",\"" + assetAccountId - .toStringUtf8() - + "\""; - - String triggerTxid2 = PublicMethed.triggerContract(proxyTestAddress, - "upgradeTo(address)", param3, false, 0, 1000000000L, - assetAccountId.toStringUtf8(), 1, dev001Address, dev001Key, blockingStubFull); - String triggerTxid3 = PublicMethed.triggerContract(proxyTestAddress, - "trans(uint256,address,trcToken)", - param2, false, 0, 1000000000L, assetAccountId - .toStringUtf8(), - 1, dev001Address, dev001Key, - blockingStubFull); - Account infoafter1 = PublicMethed.queryAccount(dev001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter1 = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance1 = infoafter1.getBalance(); - Long afterAssetIssueDevAddress1 = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - Long afterAssetIssueContractAddress1 = PublicMethed - .getAssetIssueValue(proxyTestAddress, assetAccountId, - blockingStubFull); - Long afterAssetIssueBAddress1 = PublicMethed - .getAssetIssueValue(btestAddress, assetAccountId, - blockingStubFull); - - Long afterAssetIssueUserAddress1 = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, - blockingStubFull); - Long afterBalanceContractAddress1 = PublicMethed.queryAccount(proxyTestAddress, - blockingStubFull).getBalance(); - Long afterUserBalance1 = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("afterBalance1:" + afterBalance1); - logger.info("afterAssetIssueCount1:" + afterAssetIssueDevAddress1); - logger.info("afterAssetIssueDevAddress1:" + afterAssetIssueContractAddress1); - logger.info("afterAssetIssueBAddress1:" + afterAssetIssueBAddress1); - logger.info("afterAssetIssueUserAddress1:" + afterAssetIssueUserAddress1); - logger.info("afterBalanceContractAddress1:" + afterBalanceContractAddress1); - logger.info("afterUserBalance1:" + afterUserBalance1); - - Optional infoById2 = PublicMethed - .getTransactionInfoById(triggerTxid3, blockingStubFull); - Assert.assertTrue(infoById2.get().getResultValue() == 0); - Assert.assertTrue(afterAssetIssueUserAddress1 == beforeAssetIssueUserAddress1); - Assert.assertTrue(afterBalanceContractAddress1 == beforeBalanceContractAddress1 - 1); - Assert.assertTrue(afterAssetIssueContractAddress1 == beforeAssetIssueContractAddress1 + 1); - Assert.assertTrue(afterAssetIssueDevAddress1 == beforeAssetIssueDevAddress1 - 1); - Assert.assertTrue(afterUserBalance1 == beforeUserBalance1 + 1); - Assert.assertTrue(afterAssetIssueUserAddress1 == afterAssetIssueUserAddress1); - PublicMethed.unFreezeBalance(dev001Address, dev001Key, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(user001Address, user001Key, 1, - user001Address, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken041.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken041.java deleted file mode 100644 index 541811f51c3..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken041.java +++ /dev/null @@ -1,198 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken041 { - - - private static final long TotalSupply = 10000000L; - private static final long now = System.currentTimeMillis(); - private static ByteString assetAccountId = null; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private static int randomInt(int minInt, int maxInt) { - return (int) Math.round(Math.random() * (maxInt - minInt) + minInt); - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - @Test(enabled = true, description = "Trigger contract msg.tokenId add 1,msg.tokenValue add 1") - public void deployTransferTokenContract() { - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 2048000000, - fromAddress, testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 4048000000L, - fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - // freeze balance - PublicMethed.freezeBalanceGetEnergy(dev001Address, 204800000, - 0, 1, dev001Key, blockingStubFull); - - PublicMethed.freezeBalanceGetEnergy(user001Address, 2048000000, - 0, 1, user001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - final ByteString fakeTokenId = ByteString - .copyFromUtf8(Long.toString(Long.valueOf(assetAccountId.toStringUtf8()) + 100)); - - // deploy transferTokenContract - String filePath = "src/test/resources/soliditycode/contractTrcToken041.sol"; - String contractName = "tokenTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] transferTokenContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, 10000, assetAccountId.toStringUtf8(), - 0, null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(user001Address, - blockingStubFull); - info = PublicMethed.queryAccount(user001Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long beforeAssetIssueCount = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, blockingStubFull); - Long beforeAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("beforeAssetIssueCount:" + beforeAssetIssueCount); - logger.info("beforeAssetIssueContractAddress:" + beforeAssetIssueContractAddress); - - // user trigger A to transfer token to B - String param = - "\"" + Base58.encode58Check(dev001Address) + "\",\"" + fakeTokenId - .toStringUtf8() - + "\",\"105\""; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "TransferTokenTo(address,trcToken,uint256)", - param, false, 0, 100000000L, fakeTokenId.toStringUtf8(), - 10000000L, user001Address, user001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - Account infoafter = PublicMethed.queryAccount(user001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(user001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterAssetIssueCount = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, blockingStubFull); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterAssetIssueCount:" + afterAssetIssueCount); - logger.info("afterAssetIssueContractAddress:" + afterAssetIssueContractAddress); - - Assert.assertEquals(beforeBalance, afterBalance); - Assert.assertEquals(beforeAssetIssueCount, afterAssetIssueCount); - Assert.assertEquals(beforeAssetIssueContractAddress, afterAssetIssueContractAddress); - Assert.assertTrue(afterEnergyUsed == 0L); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(dev001Address, dev001Key, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(user001Address, user001Key, 1, user001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken043.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken043.java deleted file mode 100644 index 2af2e6a386b..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken043.java +++ /dev/null @@ -1,466 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import static org.tron.protos.Protocol.TransactionInfo.code.FAILED; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken043 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private static ByteString assetAccountUser = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - private byte[] resultContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - private byte[] user002Address = ecKey3.getAddress(); - private String user002Key = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - - @Test(enabled = true, description = "TransferToken with invalid tokenId, deploy transferContract") - public void test01DeployTransferTokenContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 5048_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 5048_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user002Address, 5048_000_000L, fromAddress, - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, 100000L, - 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountId = PublicMethed - .queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balanceBefore is " + balanceBefore); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountBefore: " + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken043.sol"; - String contractName = "transferTokenContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - assetAccountId.toStringUtf8(), 100, null, dev001Key, - dev001Address, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(transferTokenContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountAfter: " + devAssetCountAfter); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(100), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(100), contractAssetCount); - } - - @Test(enabled = true, description = "TransferToken with invalid tokenId, deploy receive contract") - public void test02DeployRevContract() { - - // before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balance is " + balanceBefore); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountBefore: " + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken043.sol"; - String contractName = "Result"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String recieveTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, 1000, assetAccountId.toStringUtf8(), - 100, null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(recieveTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (recieveTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy receive failed with message: " + infoById.get().getResMessage()); - } - - resultContractAddress = infoById.get().getContractAddress().toByteArray(); - - SmartContract smartContract = PublicMethed - .getContract(resultContractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - // after deploy, check account resource - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountAfter: " + devAssetCountAfter); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(resultContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(100), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(100), contractAssetCount); - } - - @Test(enabled = true, description = "TransferToken with invalid tokenId, transferToken") - public void test03TriggerContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.transferAsset(user001Address, - assetAccountId.toByteArray(), 10L, dev001Address, dev001Key, blockingStubFull)); - - Assert.assertTrue(PublicMethed.transferAsset(user002Address, - assetAccountId.toByteArray(), 10L, dev001Address, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + devEnergyLimitBefore); - logger.info("before trigger, devEnergyUsageBefore is " + devEnergyUsageBefore); - logger.info("before trigger, devBalanceBefore is " + devBalanceBefore); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + userEnergyLimitBefore); - logger.info("before trigger, userEnergyUsageBefore is " + userEnergyUsageBefore); - logger.info("before trigger, userBalanceBefore is " + userBalanceBefore); - - Long transferAssetBefore = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, - blockingStubFull); - logger.info("before trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + transferAssetBefore); - - Long receiveAssetBefore = PublicMethed.getAssetIssueValue(resultContractAddress, assetAccountId, - blockingStubFull); - logger.info("before trigger, resultContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + receiveAssetBefore); - - // tokenId is 100_0000 - String tokenId = Long.toString(100_0000); - Long tokenValue = Long.valueOf(1); - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(resultContractAddress) - + "\",\"" + tokenValue + "\"," + tokenId; - - String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Triger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - // tokenId is -1 - tokenId = Long.toString(-1); - tokenValue = Long.valueOf(1); - callValue = Long.valueOf(0); - - param = "\"" + Base58.encode58Check(resultContractAddress) - + "\",\"" + tokenValue + "\"," + tokenId; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - //Assert.assertEquals("validateForSmartContract failure, not valid token id", - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - // tokenId is long.min - tokenId = Long.toString(Long.MIN_VALUE); - tokenValue = Long.valueOf(1); - callValue = Long.valueOf(0); - - param = "\"" + Base58.encode58Check(resultContractAddress) - + "\",\"" + tokenValue + "\"," + tokenId; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - // tokenId is 0, contract not have trx - tokenId = Long.toString(0); - tokenValue = Long.valueOf(1); - callValue = Long.valueOf(0); - - param = "\"" + Base58.encode58Check(resultContractAddress) - + "\",\"" + tokenValue + "\"," + tokenId; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - Assert.assertFalse(PublicMethed - .sendcoin(transferTokenContractAddress, 5000000, fromAddress, testKey002, - blockingStubFull)); - Assert.assertTrue(PublicMethed - .sendcoin(user002Address, 5000000, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //tokenId is 0, transfer contract has trx, transfer to normal account - tokenId = Long.toString(0); - tokenValue = Long.valueOf(1); - callValue = Long.valueOf(1); - - param = "\"" + Base58.encode58Check(dev001Address) - + "\",\"" + tokenValue + "\"," + tokenId; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user002Address, user002Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - // tokenid bigger than long.max, trigger to a contract - callValue = Long.valueOf(0); - - param = "\"" + Base58.encode58Check(resultContractAddress) + "\""; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTestIDOverBigInteger(address)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user002Address, user002Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - - Long transferAssetAfter = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("after trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", transferAssetAfter is " + transferAssetAfter); - - Long receiveAssetAfter = PublicMethed.getAssetIssueValue(resultContractAddress, - assetAccountId, blockingStubFull); - logger.info("after trigger, resultContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", receiveAssetAfter is " + receiveAssetAfter); - - Assert.assertEquals(receiveAssetAfter, receiveAssetBefore); - Assert.assertEquals(transferAssetBefore, transferAssetAfter); - - // unfreeze resource - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user002Address, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken048.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken048.java deleted file mode 100644 index f340114a45c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken048.java +++ /dev/null @@ -1,193 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken048 { - - private static final long TotalSupply = 10000000L; - private static final long now = System.currentTimeMillis(); - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - - @Test(enabled = true, description = "TransferToken msg.value msg,tokenvalue is negative number") - public void deployTransferTokenContract() { - - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 2048000000, - fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 4048000000L, - fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // freeze balance - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(dev001Address, 204800000, - 0, 1, dev001Key, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(user001Address, 2048000000, - 0, 1, user001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - final ByteString fakeassetAccountId = ByteString - .copyFromUtf8(Long.toString(Long.valueOf(assetAccountId.toStringUtf8()) + 100)); - - // deploy transferTokenContract - String filePath = "./src/test/resources/soliditycode/contractTrcToken048.sol"; - String contractName = "Test"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - byte[] transferTokenContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, 10000, "0", - 0, null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(user001Address, - blockingStubFull); - info = PublicMethed.queryAccount(user001Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long beforeAssetIssueCount = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, blockingStubFull); - Long beforeAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("beforeAssetIssueCount:" + beforeAssetIssueCount); - logger.info("beforeAssetIssueContractAddress:" + beforeAssetIssueContractAddress); - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "testMsgTokenValue()", - "#", false, 0, 100000000L, fakeassetAccountId.toStringUtf8(), - -1000, user001Address, user001Key, blockingStubFull); - - String triggerTxid1 = PublicMethed.triggerContract(transferTokenContractAddress, - "testMsgValue()", - "#", false, -1000, 100000000L, "0", - 0, user001Address, user001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account infoafter = PublicMethed.queryAccount(user001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(user001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterAssetIssueCount = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, blockingStubFull); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterAssetIssueCount:" + afterAssetIssueCount); - logger.info("afterAssetIssueContractAddress:" + afterAssetIssueContractAddress); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Assert.assertEquals(beforeBalance, afterBalance); - Assert.assertEquals(beforeAssetIssueCount, afterAssetIssueCount); - Assert.assertEquals(beforeAssetIssueContractAddress, afterAssetIssueContractAddress); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(dev001Address, dev001Key, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(user001Address, user001Key, 1, user001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken049.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken049.java deleted file mode 100644 index bb901e48016..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken049.java +++ /dev/null @@ -1,228 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.AssetIssueList; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken049 { - - - private static final long TotalSupply = 10000000L; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private static int randomInt(int minInt, int maxInt) { - return (int) Math.round(Math.random() * (maxInt - minInt) + minInt); - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - /** - * constructor. - */ - - public ByteString createAssetissue(byte[] devAddress, String devKey, String tokenName) { - - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - - logger.info("The token name: " + tokenName); - - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(devAddress, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, 10000L, - 1L, 1L, devKey, blockingStubFull)); - - ByteString assetAccountId = PublicMethed.queryAccount(devAddress, blockingStubFull) - .getAssetIssuedID(); - logger.info("The tokenID: " + assetAccountId); - - return assetAccountId; - } - - @Test(enabled = true, description = "TransferToken to myself") - public void deployTransferTokenContract() { - - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 2048000000, - fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 4048000000L, - fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // freeze balance - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(dev001Address, 204800000, - 0, 1, dev001Key, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(user001Address, 2048000000, - 0, 1, user001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String tokenName = "testAI_" + randomInt(10000, 90000); - ByteString tokenId = createAssetissue(user001Address, user001Key, tokenName); - - PublicMethed.transferAsset(dev001Address, tokenId.toByteArray(), 101, user001Address, - user001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // deploy transferTokenContract - String filePath = "./src/test/resources/soliditycode/contractTrcToken049.sol"; - String contractName = "tokenTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, 10000, tokenId.toStringUtf8(), - 0, null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - byte[] transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(user001Address, - blockingStubFull); - - Long beforeBalance = PublicMethed - .queryAccount(user001Address, blockingStubFull).getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long beforeAssetIssueCount = - PublicMethed.getAssetIssueValue(user001Address, tokenId, blockingStubFull); - Long beforeAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, tokenId, blockingStubFull); - final Long beforeAssetIssueDev = PublicMethed.getAssetIssueValue(dev001Address, tokenId, - blockingStubFull); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("beforeAssetIssueCount:" + beforeAssetIssueCount); - logger.info("beforeAssetIssueContractAddress:" + beforeAssetIssueContractAddress); - - // user trigger A to transfer token to B - String param = - "\"" + Base58.encode58Check(dev001Address) + "\",\"" + tokenId - .toStringUtf8() - + "\",\"1\""; - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "TransferTokenTo(address,trcToken,uint256)", - param, false, 0, 100000000L, "0", - 0, user001Address, user001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account infoafter = PublicMethed.queryAccount(user001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(user001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterAssetIssueCount = - PublicMethed.getAssetIssueValue(user001Address, tokenId, blockingStubFull); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, tokenId, blockingStubFull); - final Long afterAssetIssueDev = PublicMethed.getAssetIssueValue(dev001Address, tokenId, - blockingStubFull); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterAssetIssueCount:" + afterAssetIssueCount); - logger.info("afterAssetIssueContractAddress:" + afterAssetIssueContractAddress); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertEquals(beforeBalance, afterBalance); - Assert.assertEquals(beforeAssetIssueCount, afterAssetIssueCount); - Assert.assertTrue(beforeAssetIssueContractAddress == afterAssetIssueContractAddress); - - Assert.assertTrue(beforeAssetIssueDev == afterAssetIssueDev); - PublicMethed.unFreezeBalance(dev001Address, dev001Key, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(user001Address, user001Key, 1, - user001Address, blockingStubFull); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken050.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken050.java deleted file mode 100644 index 67becbcaafc..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken050.java +++ /dev/null @@ -1,203 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken050 { - - private static final long TotalSupply = 10000000L; - private static final long now = System.currentTimeMillis(); - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - - @Test(enabled = true, description = "TransferToken to contract address ") - public void deployTransferTokenContract() { - - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 2048000000, - fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 4048000000L, - fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - // freeze balance - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(dev001Address, 204800000, - 0, 1, dev001Key, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(user001Address, 2048000000, - 0, 1, user001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken050.sol"; - String contractName = "tokenTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - byte[] transferTokenContractAddress; - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, 10000, assetAccountId.toStringUtf8(), - 0, null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(user001Address, - blockingStubFull); - info = PublicMethed.queryAccount(user001Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long beforeAssetIssueCount = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, - blockingStubFull); - Long beforeAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, - assetAccountId, - blockingStubFull); - final Long beforeAssetIssueDev = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("beforeAssetIssueCount:" + beforeAssetIssueCount); - logger.info("beforeAssetIssueContractAddress:" + beforeAssetIssueContractAddress); - logger.info("beforeAssetIssueDev:" + beforeAssetIssueDev); - - // user trigger A to transfer token to B - String param = - "\"" + Base58.encode58Check(transferTokenContractAddress) + "\",\"" + assetAccountId - .toStringUtf8() - + "\",\"1\""; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "TransferTokenTo(address,trcToken,uint256)", - param, false, 0, 100000000L, "0", - 0, user001Address, user001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account infoafter = PublicMethed.queryAccount(user001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(user001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterAssetIssueCount = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, blockingStubFull); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - final Long afterAssetIssueDev = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterAssetIssueCount:" + afterAssetIssueCount); - logger.info("afterAssetIssueContractAddress:" + afterAssetIssueContractAddress); - logger.info("afterAssetIssueDev:" + afterAssetIssueDev); - - infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertEquals(beforeAssetIssueCount, afterAssetIssueCount); - Assert.assertTrue(beforeAssetIssueContractAddress == afterAssetIssueContractAddress); - Assert.assertEquals(beforeAssetIssueDev, afterAssetIssueDev); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(dev001Address, dev001Key, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(user001Address, user001Key, 1, user001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken051.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken051.java deleted file mode 100644 index bbfbccefe49..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken051.java +++ /dev/null @@ -1,203 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import static org.tron.protos.Protocol.TransactionInfo.code.FAILED; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken051 { - - private static final long TotalSupply = 10000000L; - private static final long now = System.currentTimeMillis(); - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - - @Test(enabled = true, description = "TransferToken to contract developer tokenID is 0") - public void deployTransferTokenContract() { - - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 2048000000, - fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 6048000000L, - fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // freeze balance - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(dev001Address, 204800000, - 0, 1, dev001Key, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(user001Address, 2048000000, - 0, 1, user001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - // deploy transferTokenContract - String filePath = "./src/test/resources/soliditycode/contractTrcToken051.sol"; - String contractName = "tokenTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] transferTokenContractAddress; - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, 10000, assetAccountId.toStringUtf8(), - 0, null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(user001Address, - blockingStubFull); - info = PublicMethed.queryAccount(user001Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long beforeAssetIssueCount = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, blockingStubFull); - Long beforeAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long beforeAssetIssueDev = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("beforeAssetIssueCount:" + beforeAssetIssueCount); - logger.info("beforeAssetIssueContractAddress:" + beforeAssetIssueContractAddress); - logger.info("beforeAssetIssueDev:" + beforeAssetIssueDev); - - String fakeassetAccountId = Long.toString(0L); - - String param = "\"" + Base58.encode58Check(dev001Address) - + "\"," + fakeassetAccountId + ",\"1\""; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "TransferTokenTo(address,trcToken,uint256)", - param, false, 0, 100000000L, "0", - 0, user001Address, user001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertFalse(infoById.get().getResultValue() == 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - Account infoafter = PublicMethed.queryAccount(user001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(user001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterAssetIssueCount = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, blockingStubFull); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueDev = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterAssetIssueCount:" + afterAssetIssueCount); - logger.info("afterAssetIssueContractAddress:" + afterAssetIssueContractAddress); - logger.info("afterAssetIssueDev:" + afterAssetIssueDev); - - Assert.assertEquals(beforeAssetIssueCount, afterAssetIssueCount); - Assert.assertEquals(beforeAssetIssueContractAddress, afterAssetIssueContractAddress); - Assert.assertEquals(beforeAssetIssueDev, afterAssetIssueDev); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.unFreezeBalance(dev001Address, dev001Key, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(user001Address, user001Key, 1, user001Address, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken052.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken052.java deleted file mode 100644 index 5f76a458d4f..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken052.java +++ /dev/null @@ -1,207 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken052 { - - private static final long TotalSupply = 10000000L; - private static final long now = System.currentTimeMillis(); - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - - @Test(enabled = true, description = "TransferToken to contract address tokenID is 0") - public void deployTransferTokenContract() { - - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 2048000000, - fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 6048000000L, - fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // freeze balance - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(dev001Address, 204800000, - 0, 1, dev001Key, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(user001Address, 2048000000, - 0, 1, user001Key, blockingStubFull)); - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, - 10000L, 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - // deploy transferTokenContract - String filePath = "./src/test/resources/soliditycode/contractTrcToken052.sol"; - String contractName = "tokenTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] transferTokenContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, 10000, assetAccountId.toStringUtf8(), - 0, null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - /*Assert.assertFalse(PublicMethed.sendcoin(transferTokenContractAddress, 2048000000, - fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull);*/ - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(user001Address, - blockingStubFull); - info = PublicMethed.queryAccount(user001Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long beforeAssetIssueCount = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, blockingStubFull); - Long beforeAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long beforeAssetIssueDev = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - final Long beforetransferTokenContractAddressBalance = PublicMethed - .queryAccount(transferTokenContractAddress, blockingStubFull).getBalance(); - final Long beforeDevBalance = PublicMethed - .queryAccount(dev001Address, blockingStubFull).getBalance(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("beforeAssetIssueCount:" + beforeAssetIssueCount); - logger.info("beforeAssetIssueContractAddress:" + beforeAssetIssueContractAddress); - logger.info("beforeAssetIssueDev:" + beforeAssetIssueDev); - String fakeassetAccountId = Long.toString(0L); - - String param = "\"" + Base58.encode58Check(transferTokenContractAddress) - + "\"," + fakeassetAccountId + ",\"1\""; - // user trigger A to transfer token to B - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "TransferTokenTo(address,trcToken,uint256)", - param, false, 0, 100000000L, "0", - 0, user001Address, user001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 1); - Account infoafter = PublicMethed.queryAccount(user001Address, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(user001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterAssetIssueCount = PublicMethed - .getAssetIssueValue(user001Address, assetAccountId, blockingStubFull); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long afterAssetIssueContractAddress = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - Long afterAssetIssueDev = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - final Long aftertransferTokenContractAddressBalance = PublicMethed - .queryAccount(transferTokenContractAddress, blockingStubFull).getBalance(); - final Long afterDevBalance = PublicMethed - .queryAccount(dev001Address, blockingStubFull).getBalance(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("afterAssetIssueCount:" + afterAssetIssueCount); - logger.info("afterAssetIssueContractAddress:" + afterAssetIssueContractAddress); - logger.info("afterAssetIssueDev:" + afterAssetIssueDev); - - Assert.assertEquals(beforeAssetIssueCount, afterAssetIssueCount); - Assert.assertEquals( - beforetransferTokenContractAddressBalance, aftertransferTokenContractAddressBalance); - Assert.assertEquals(beforeDevBalance, afterDevBalance); - Assert.assertEquals(beforeAssetIssueCount, afterAssetIssueCount); - Assert.assertEquals(beforeAssetIssueContractAddress, afterAssetIssueContractAddress); - Assert.assertEquals(beforeAssetIssueDev, afterAssetIssueDev); - - } - - /** - * constructor. - */ - - - @AfterClass - public void shutdown() throws InterruptedException { - - PublicMethed.unFreezeBalance(dev001Address, dev001Key, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(user001Address, user001Key, 1, user001Address, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken054.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken054.java deleted file mode 100644 index 7d03fc94753..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken054.java +++ /dev/null @@ -1,272 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken054 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "Trigger transferToken with 0 tokenValue") - public void testTriggerTransferTokenContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 70000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, 100000L, - 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balanceBefore is " + balanceBefore); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountBefore: " + devAssetCountBefore); - - //String contractName = "transferTokenContract"; - - String filePath = "./src/test/resources/soliditycode/contractTrcToken054.sol"; - String contractName = "tokenTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String tokenId = assetAccountId.toStringUtf8(); - long tokenValue = 200; - long callValue = 0; - - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, callValue, 0, 10000, - tokenId, tokenValue, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(transferTokenContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountAfter: " + devAssetCountAfter); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("before trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + contractAssetCount); - - Assert.assertEquals(Long.valueOf(200), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(200), contractAssetCount); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.transferAsset(user001Address, - assetAccountId.toByteArray(), 10L, dev001Address, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + devEnergyLimitBefore); - logger.info("before trigger, devEnergyUsageBefore is " + devEnergyUsageBefore); - logger.info("before trigger, devBalanceBefore is " + devBalanceBefore); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + userEnergyLimitBefore); - logger.info("before trigger, userEnergyUsageBefore is " + userEnergyUsageBefore); - logger.info("before trigger, userBalanceBefore is " + userBalanceBefore); - - tokenId = assetAccountId.toStringUtf8(); - tokenValue = 0; - callValue = 5; - - String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "msgTokenValueAndTokenIdTest()", "#", false, callValue, - 1000000000L, tokenId, tokenValue, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (triggerTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - logger.info( - "the value: " + PublicMethed.getStrings(infoById.get().getContractResult(0).toByteArray())); - - List retList = PublicMethed - .getStrings(infoById.get().getContractResult(0).toByteArray()); - - Long msgId = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - Long msgTokenValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - Long msgCallValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(2))); - - logger.info("msgId: " + msgId); - logger.info("msgTokenValue: " + msgTokenValue); - logger.info("msgCallValue: " + msgCallValue); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + devEnergyLimitAfter); - logger.info("after trigger, devEnergyUsageAfter is " + devEnergyUsageAfter); - logger.info("after trigger, devBalanceAfter is " + devBalanceAfter); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + userEnergyLimitAfter); - logger.info("after trigger, userEnergyUsageAfter is " + userEnergyUsageAfter); - logger.info("after trigger, userBalanceAfter is " + userBalanceAfter); - - Assert.assertEquals(msgId.toString(), tokenId); - Assert.assertEquals(Long.valueOf(msgTokenValue), Long.valueOf(tokenValue)); - Assert.assertEquals(Long.valueOf(msgCallValue), Long.valueOf(callValue)); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, user001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken055.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken055.java deleted file mode 100644 index 5d48630e192..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken055.java +++ /dev/null @@ -1,277 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken055 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Trigger TransferToken with long.max tokenId," - + " and 0tokenValue") - public void triggerTransferTokenContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 70000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, 100000L, - 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed - .queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balanceBefore is " + balanceBefore); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountBefore: " + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken055.sol"; - String contractName = "tokenTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String tokenId = assetAccountId.toStringUtf8(); - long tokenValue = 200; - long callValue = 0; - - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, callValue, 0, 10000, - tokenId, tokenValue, null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(transferTokenContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(200), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(200), contractAssetCount); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.transferAsset(user001Address, - assetAccountId.toByteArray(), 10L, dev001Address, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + devEnergyLimitBefore); - logger.info("before trigger, devEnergyUsageBefore is " + devEnergyUsageBefore); - logger.info("before trigger, devBalanceBefore is " + devBalanceBefore); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + userEnergyLimitBefore); - logger.info("before trigger, userEnergyUsageBefore is " + userEnergyUsageBefore); - logger.info("before trigger, userBalanceBefore is " + userBalanceBefore); - - Long transferAssetBefore = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - logger.info("before trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + transferAssetBefore); - - tokenId = Long.toString(Long.MAX_VALUE); - tokenValue = 0; - callValue = 5; - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "msgTokenValueAndTokenIdTest()", "", false, callValue, - 1000000000L, tokenId, tokenValue, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + devEnergyLimitAfter); - logger.info("after trigger, devEnergyUsageAfter is " + devEnergyUsageAfter); - logger.info("after trigger, devBalanceAfter is " + devBalanceAfter); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + userEnergyLimitAfter); - logger.info("after trigger, userEnergyUsageAfter is " + userEnergyUsageAfter); - logger.info("after trigger, userBalanceAfter is " + userBalanceAfter); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (triggerTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - logger.info( - "the value: " + PublicMethed.getStrings(infoById.get().getContractResult(0).toByteArray())); - - List retList = PublicMethed - .getStrings(infoById.get().getContractResult(0).toByteArray()); - - Long msgId = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - Long msgTokenValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - Long msgCallValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(2))); - - logger.info("msgId: " + msgId); - logger.info("msgTokenValue: " + msgTokenValue); - logger.info("msgCallValue: " + msgCallValue); - - Assert.assertEquals(msgId.toString(), tokenId); - Assert.assertEquals(Long.valueOf(msgTokenValue), Long.valueOf(tokenValue)); - Assert.assertEquals(Long.valueOf(msgCallValue), Long.valueOf(callValue)); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken060.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken060.java deleted file mode 100644 index 088178a880c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken060.java +++ /dev/null @@ -1,232 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken060 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - @Test(enabled = true, description = "DeployContract with 0 tokenValue") - public void deployTransferTokenContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 130000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, 100000L, - 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balanceBefore is " + balanceBefore); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken060.sol"; - String contractName = "tokenTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String tokenId = assetAccountId.toStringUtf8(); - long tokenValue = 0; - long callValue = 5; - - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callValue, 0, 10000, tokenId, tokenValue, - null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(transferTokenContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - Long contractAssetCount = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(tokenValue), - Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(tokenValue), contractAssetCount); - - // get and verify the msg.value and msg.id - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + devEnergyLimitBefore); - logger.info("before trigger, devEnergyUsageBefore is " + devEnergyUsageBefore); - logger.info("before trigger, devBalanceBefore is " + devBalanceBefore); - - Long transferAssetBefore = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("before trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + transferAssetBefore); - - final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "getResultInCon()", "#", false, 0, - 1000000000L, "0", 0, dev001Address, dev001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + devEnergyLimitAfter); - logger.info("after trigger, devEnergyUsageAfter is " + devEnergyUsageAfter); - logger.info("after trigger, devBalanceAfter is " + devBalanceAfter); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (triggerTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - logger.info("The msg value: " + PublicMethed.getStrings(infoById.get() - .getContractResult(0).toByteArray())); - - List retList = PublicMethed.getStrings(infoById.get() - .getContractResult(0).toByteArray()); - - Long msgId = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - Long msgTokenValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - Long msgCallValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(2))); - - logger.info("msgId: " + msgId); - logger.info("msgTokenValue: " + msgTokenValue); - logger.info("msgCallValue: " + msgCallValue); - - Assert.assertEquals(msgId.toString(), tokenId); - Assert.assertEquals(Long.valueOf(msgTokenValue), Long.valueOf(tokenValue)); - Assert.assertEquals(Long.valueOf(msgCallValue), Long.valueOf(callValue)); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken061.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken061.java deleted file mode 100644 index 6c78226dab7..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken061.java +++ /dev/null @@ -1,218 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken061 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - @Test(enabled = true, description = "DeployContract with 0 tokenValue and long.max tokenId") - public void deployTransferTokenContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 130000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, 100000L, - 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed - .queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed.getAssetIssueValue(dev001Address, - assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balanceBefore is " + balanceBefore); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken061.sol"; - String contractName = "tokenTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String tokenId = Long.toString(Long.MAX_VALUE); - long tokenValue = 0; - long callValue = 10; - - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callValue, 0, 10000, tokenId, tokenValue, - null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(transferTokenContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed.getAssetIssueValue(dev001Address, - assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(tokenValue), - Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(tokenValue), contractAssetCount); - - // get and verify the msg.value and msg.id - - Long transferAssetBefore = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("before trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + transferAssetBefore); - - String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "getResultInCon()", "#", false, 0, - 1000000000L, "0", 0, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (triggerTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - logger.info("The msg value: " + PublicMethed.getStrings(infoById.get() - .getContractResult(0).toByteArray())); - - List retList = PublicMethed.getStrings(infoById.get() - .getContractResult(0).toByteArray()); - - Long msgId = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - Long msgTokenValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - Long msgCallValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(2))); - - logger.info("msgId: " + msgId); - logger.info("msgTokenValue: " + msgTokenValue); - logger.info("msgCallValue: " + msgCallValue); - - Assert.assertEquals(msgId.toString(), tokenId); - Assert.assertEquals(Long.valueOf(msgTokenValue), Long.valueOf(tokenValue)); - Assert.assertEquals(Long.valueOf(msgCallValue), Long.valueOf(callValue)); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken064.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken064.java deleted file mode 100644 index 58426f66f2b..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken064.java +++ /dev/null @@ -1,450 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import static org.tron.protos.Protocol.TransactionInfo.code.FAILED; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken064 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private static ByteString assetAccountUser = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - private byte[] resultContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "TransferToken with 0 tokenValue and " - + "tokenId in exception condition, deploy transfer contract") - public void test01DeployTransferTokenContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 1100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, 100000L, - 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - start = System.currentTimeMillis() + 2000; - end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(user001Address, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, 100000L, - 1L, 1L, user001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountUser = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getAssetIssuedID(); - logger.info("The assetAccountUser token name: " + tokenName); - logger.info("The assetAccountUser token ID: " + assetAccountUser.toStringUtf8()); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balanceBefore is " + balanceBefore); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken064.sol"; - String contractName = "transferTokenContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - assetAccountId.toStringUtf8(), 100, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(transferTokenContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(100), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(100), contractAssetCount); - } - - @Test(enabled = true, description = "TransferToken with 0 tokenValue and " - + "tokenId in exception condition, deploy receiver contract") - public void test02DeployRevContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - // before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balance is " + balanceBefore); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken064.sol"; - String contractName = "Result"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String recieveTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, 1000, assetAccountId.toStringUtf8(), - 100, null, dev001Key, dev001Address, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(recieveTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (recieveTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy receive failed with message: " + infoById.get().getResMessage()); - } - resultContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(resultContractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - // after deploy, check account resource - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(resultContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(100), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(100), contractAssetCount); - } - - @Test(enabled = true, description = "TransferToken with 0 tokenValue and " - + "tokenId in exception condition, trigger contract") - public void test03TriggerContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.transferAsset(user001Address, - assetAccountId.toByteArray(), 10L, dev001Address, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - - Long transferAssetBefore = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("before trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + transferAssetBefore); - - Long receiveAssetBefore = PublicMethed.getAssetIssueValue(resultContractAddress, assetAccountId, - blockingStubFull); - logger.info("before trigger, resultContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + receiveAssetBefore); - - Long callValue = Long.valueOf(0); - String param = "\"" + Base58.encode58Check(resultContractAddress) + "\""; - String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTestValue0IdBigInteger(address)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info(infoById.get().getResMessage().toStringUtf8()); - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - //Assert.assertEquals("BigInteger out of long range", - infoById.get().getResMessage().toStringUtf8()); - - //transfer to a normal account - param = "\"" + Base58.encode58Check(dev001Address) + "\""; - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTestValue0IdBigInteger(address)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - //Assert.assertEquals("BigInteger out of long range", - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - String tokenId = Long.toString(Long.MIN_VALUE); - Long tokenValue = Long.valueOf(0); - callValue = Long.valueOf(0); - - param = "\"" + Base58.encode58Check(resultContractAddress) - + "\",\"" + tokenValue + "\"," + tokenId; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - tokenId = Long.toString(100_0000); - tokenValue = Long.valueOf(0); - callValue = Long.valueOf(0); - - param = "\"" + Base58.encode58Check(resultContractAddress) - + "\",\"" + tokenValue + "\"," + tokenId; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - tokenId = Long.toString(-1); - tokenValue = Long.valueOf(0); - callValue = Long.valueOf(0); - - param = "\"" + Base58.encode58Check(resultContractAddress) - + "\",\"" + tokenValue + "\"," + tokenId; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - tokenId = Long.toString(0); - tokenValue = Long.valueOf(0); - callValue = Long.valueOf(0); - - param = "\"" + Base58.encode58Check(resultContractAddress) - + "\",\"" + tokenValue + "\"," + tokenId; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - callValue = Long.valueOf(0); - - param = "\"" + Base58.encode58Check(resultContractAddress) + "\""; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTestValueMaxLong(address)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //transfer to a normal account - param = "\"" + Base58.encode58Check(dev001Address) + "\""; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTestValueMaxLong(address)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); - - Long transferAssetAfter = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("after trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", transferAssetAfter is " + transferAssetAfter); - - Long receiveAssetAfter = PublicMethed.getAssetIssueValue(resultContractAddress, - assetAccountId, blockingStubFull); - logger.info("after trigger, resultContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", receiveAssetAfter is " + receiveAssetAfter); - - Assert.assertEquals(receiveAssetAfter, receiveAssetBefore); - Assert.assertEquals(transferAssetBefore, transferAssetAfter); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, user001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken066.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken066.java deleted file mode 100644 index 68836cc079b..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken066.java +++ /dev/null @@ -1,333 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken066 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - private byte[] resultContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "TransferToken with 0 tokenValue, deploy transferContract") - public void test01DeployTransferTokenContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 5048_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 4048_000_000L, fromAddress, - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, 100000L, - 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + energyLimit); - logger.info("before energyUsage is " + energyUsage); - logger.info("before balanceBefore is " + balanceBefore); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken066.sol"; - String contractName = "transferTokenContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - assetAccountId.toStringUtf8(), 100, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(transferTokenContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + energyLimit); - logger.info("after energyUsage is " + energyUsage); - logger.info("after balanceAfter is " + balanceAfter); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(100), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(100), contractAssetCount); - } - - @Test(enabled = true, description = "TransferToken with 0 tokenValue, deploy receive contract") - public void test02DeployRevContract() { - - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken066.sol"; - String contractName = "Result"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String recieveTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, 1000, assetAccountId.toStringUtf8(), - 100, null, dev001Key, dev001Address, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(recieveTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (recieveTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy receive failed with message: " + infoById.get().getResMessage()); - } - - resultContractAddress = infoById.get().getContractAddress().toByteArray(); - - SmartContract smartContract = PublicMethed - .getContract(resultContractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(resultContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(100), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(100), contractAssetCount); - } - - @Test(enabled = true, description = "TransferToken with 0 tokenValue, trigger transferContract") - public void test03TriggerContract() { - - Assert.assertTrue(PublicMethed.transferAsset(user001Address, - assetAccountId.toByteArray(), 10L, dev001Address, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - - Long transferAssetBefore = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - logger.info("before trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + transferAssetBefore); - - Long receiveAssetBefore = PublicMethed.getAssetIssueValue(resultContractAddress, assetAccountId, - blockingStubFull); - logger.info("before trigger, resultContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + receiveAssetBefore); - - String tokenId = assetAccountId.toStringUtf8(); - Long tokenValue = Long.valueOf(0); - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(resultContractAddress) - + "\",\"" + tokenValue + "\"," + tokenId; - - String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - TransactionInfo transactionInfo = infoById.get(); - if (triggerTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - logger.info("the value: " + retList); - - Long msgId = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - Long msgTokenValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - Long msgCallValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(2))); - - logger.info("msgId: " + msgId); - logger.info("msgTokenValue: " + msgTokenValue); - logger.info("msgCallValue: " + msgCallValue); - - Assert.assertEquals(tokenId, msgId.toString()); - Assert.assertEquals(tokenValue, msgTokenValue); - Assert.assertEquals(callValue, msgCallValue); - - Long transferAssetAfter = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("after trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", transferAssetAfter is " + transferAssetAfter); - - Long receiveAssetAfter = PublicMethed.getAssetIssueValue(resultContractAddress, - assetAccountId, blockingStubFull); - logger.info("after trigger, resultContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", receiveAssetAfter is " + receiveAssetAfter); - - Assert.assertEquals(receiveAssetAfter - receiveAssetBefore, - transferAssetBefore + 2L - transferAssetAfter); - - } - - @Test(enabled = true, description = "TransferToken with 0 tokenValue, get contract tokenBalance") - public void test04TriggerTokenBalanceContract() { - - - String param = "\"" + Base58.encode58Check(resultContractAddress) + "\",\"" - + assetAccountId.toStringUtf8() + "\""; - - String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "getTokenBalnce(address,trcToken)", - param, false, 0, 1000000000L, user001Address, - user001Key, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed.getTransactionInfoById(triggerTxid, - blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (triggerTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - logger.info("the receivercontract token: " + ByteArray - .toLong(infoById.get().getContractResult(0).toByteArray())); - Long assetIssueCount = PublicMethed.getAssetIssueValue(resultContractAddress, assetAccountId, - blockingStubFull); - logger.info("the receivercontract token(getaccount): " + assetIssueCount); - - Assert.assertTrue(assetIssueCount == ByteArray - .toLong(ByteArray.fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, user001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken067.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken067.java deleted file mode 100644 index fa6931be987..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken067.java +++ /dev/null @@ -1,339 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken067 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - private byte[] resultContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "TransferToken with 0 tokenValue, " - + "and not existed tokenId, deploy transfer contract") - public void test01DeployTransferTokenContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 5048_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 4048_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, 100000L, - 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken067.sol"; - String contractName = "transferTokenContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - assetAccountId.toStringUtf8(), 100, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(transferTokenContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(100), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(100), contractAssetCount); - } - - @Test(enabled = true, description = "TransferToken with 0 tokenValue, " - + "and not existed tokenId, deploy receive contract") - public void test02DeployRevContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken067.sol"; - String contractName = "Result"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String recieveTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, 1000, assetAccountId.toStringUtf8(), - 100, null, dev001Key, dev001Address, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(recieveTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (recieveTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy receive failed with message: " + infoById.get().getResMessage()); - } - - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - - resultContractAddress = infoById.get().getContractAddress().toByteArray(); - - SmartContract smartContract = PublicMethed - .getContract(resultContractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(resultContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(100), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(100), contractAssetCount); - } - - @Test(enabled = true, description = "TransferToken with 0 tokenValue, " - + "and not existed tokenId, trigger transfer contract") - public void test03TriggerContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.transferAsset(user001Address, - assetAccountId.toByteArray(), 10L, dev001Address, dev001Key, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long transferAssetBefore = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("before trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + transferAssetBefore); - - Long receiveAssetBefore = PublicMethed.getAssetIssueValue(resultContractAddress, assetAccountId, - blockingStubFull); - logger.info("before trigger, resultContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + receiveAssetBefore); - - String tokenId = Long.toString(Long.MAX_VALUE); - Long tokenValue = Long.valueOf(0); - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(resultContractAddress) - + "\",\"" + tokenValue + "\"," + tokenId; - - String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "transferTokenTest(address,uint256,trcToken)", param, false, callValue, - 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (triggerTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info( - "the value: " + PublicMethed.getStrings(transactionInfo.getLogList().get(0).getData() - .toByteArray())); - - List retList = PublicMethed.getStrings(transactionInfo.getLogList().get(0) - .getData().toByteArray()); - - Long msgId = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - Long msgTokenValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - Long msgCallValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(2))); - - logger.info("msgId: " + msgId); - logger.info("msgTokenValue: " + msgTokenValue); - logger.info("msgCallValue: " + msgCallValue); - - Assert.assertEquals(tokenId, msgId.toString()); - Assert.assertEquals(tokenValue, msgTokenValue); - Assert.assertEquals(callValue, msgCallValue); - - Long transferAssetAfter = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("after trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", transferAssetAfter is " + transferAssetAfter); - - Long receiveAssetAfter = PublicMethed.getAssetIssueValue(resultContractAddress, - assetAccountId, blockingStubFull); - logger.info("after trigger, resultContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", receiveAssetAfter is " + receiveAssetAfter); - - Assert.assertEquals(receiveAssetAfter - receiveAssetBefore, - transferAssetBefore + 2L - transferAssetAfter); - } - - @Test(enabled = true, description = "TransferToken with 0 tokenValue, " - + "and not existed tokenId, get tokenBalance") - public void test04TriggerTokenBalanceContract() { - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(user001Address, 1000_000_000L, - 0, 1, user001Key, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String param = "\"" + Base58.encode58Check(resultContractAddress) + "\",\"" - + assetAccountId.toStringUtf8() + "\""; - - String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "getTokenBalnce(address,trcToken)", - param, false, 0, 1000000000L, user001Address, - user001Key, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed.getTransactionInfoById(triggerTxid, - blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (triggerTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - logger.info("the receivercontract token: " + ByteArray - .toLong(infoById.get().getContractResult(0).toByteArray())); - Long assetIssueCount = PublicMethed.getAssetIssueValue(resultContractAddress, assetAccountId, - blockingStubFull); - logger.info("the receivercontract token(getaccount): " + assetIssueCount); - Assert.assertTrue(assetIssueCount == ByteArray - .toLong(ByteArray.fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, user001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken073.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken073.java deleted file mode 100644 index 1db7cd8ee4d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken073.java +++ /dev/null @@ -1,260 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken073 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - @Test(enabled = true, description = "TokenBalance with correct tokenValue and tokenId") - public void testTokenBalanceContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 11000_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 300000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, 100000L, - 1L, 1L, dev001Key, blockingStubFull)); - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - - Long devAssetCountBefore = PublicMethed.getAssetIssueValue(dev001Address, - assetAccountId, blockingStubFull); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken073.sol"; - String contractName = "Dest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String tokenId = assetAccountId.toStringUtf8(); - long tokenValue = 200; - long callValue = 5; - - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callValue, 0, 10000, tokenId, tokenValue, - null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(transferTokenContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long devAssetCountAfter = PublicMethed.getAssetIssueValue(dev001Address, - assetAccountId, blockingStubFull); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(tokenValue), - Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(tokenValue), contractAssetCount); - - // get and verify the msg.value and msg.id - Long transferAssetBefore = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("before trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + transferAssetBefore); - - Long devAssetBefore = PublicMethed.getAssetIssueValue(dev001Address, - assetAccountId, blockingStubFull); - logger.info("before trigger, dev001Address has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + devAssetBefore); - - tokenId = assetAccountId.toStringUtf8(); - String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "getToken(trcToken)", tokenId, false, 0, - 1000000000L, "0", 0, dev001Address, dev001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (triggerTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - logger.info("The msg value: " + infoById.get().getLogList().get(0).getTopicsList()); - - Long msgTokenBalance = ByteArray - .toLong(infoById.get().getLogList().get(0).getTopicsList().get(1).toByteArray()); - Long msgId = ByteArray - .toLong(infoById.get().getLogList().get(0).getTopicsList().get(2).toByteArray()); - Long msgTokenValue = ByteArray - .toLong(infoById.get().getLogList().get(0).getTopicsList().get(3).toByteArray()); - - logger.info("msgTokenBalance: " + msgTokenBalance); - logger.info("msgId: " + msgId); - logger.info("msgTokenValue: " + msgTokenValue); - - Assert.assertEquals(msgTokenBalance, devAssetBefore); - - tokenId = Long.toString(Long.valueOf(assetAccountId.toStringUtf8()) + 1000); - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "getToken(trcToken)", tokenId, false, 0, - 1000000000L, "0", 0, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (triggerTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - logger.info("The msg value: " + infoById.get().getLogList().get(0).getTopicsList()); - - msgTokenBalance = ByteArray - .toLong(infoById.get().getLogList().get(0).getTopicsList().get(1).toByteArray()); - msgId = ByteArray - .toLong(infoById.get().getLogList().get(0).getTopicsList().get(2).toByteArray()); - msgTokenValue = ByteArray - .toLong(infoById.get().getLogList().get(0).getTopicsList().get(3).toByteArray()); - - logger.info("msgTokenBalance: " + msgTokenBalance); - logger.info("msgId: " + msgId); - logger.info("msgTokenValue: " + msgTokenValue); - - Assert.assertEquals(Long.valueOf(0), msgTokenBalance); - - tokenId = Long.toString(Long.MAX_VALUE); - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "getToken(trcToken)", tokenId, false, 0, - 1000000000L, "0", 0, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (triggerTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - logger.info("The msg value: " + infoById.get().getLogList().get(0).getTopicsList()); - - msgTokenBalance = ByteArray - .toLong(infoById.get().getLogList().get(0).getTopicsList().get(1).toByteArray()); - msgId = ByteArray - .toLong(infoById.get().getLogList().get(0).getTopicsList().get(2).toByteArray()); - msgTokenValue = ByteArray - .toLong(infoById.get().getLogList().get(0).getTopicsList().get(3).toByteArray()); - - logger.info("msgTokenBalance: " + msgTokenBalance); - logger.info("msgId: " + msgId); - logger.info("msgTokenValue: " + msgTokenValue); - - Assert.assertEquals(Long.valueOf(0), msgTokenBalance); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken075.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken075.java deleted file mode 100644 index 3f959f772b5..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken075.java +++ /dev/null @@ -1,268 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import static org.tron.protos.Protocol.TransactionInfo.code.FAILED; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken075 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - @Test(enabled = true, description = "TokenBalance with exception condition") - public void testTokenBalanceContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 11000_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 130000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, 100000L, - 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed - .queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - - Long devAssetCountBefore = PublicMethed.getAssetIssueValue(dev001Address, - assetAccountId, blockingStubFull); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken075.sol"; - String contractName = "Dest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String tokenId = assetAccountId.toStringUtf8(); - long tokenValue = 200; - long callValue = 5; - - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callValue, 0, 10000, tokenId, tokenValue, - null, dev001Key, dev001Address, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(transferTokenContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long devAssetCountAfter = PublicMethed.getAssetIssueValue(dev001Address, - assetAccountId, blockingStubFull); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(tokenValue), - Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(tokenValue), contractAssetCount); - - // get and verify the msg.value and msg.id - - Long transferAssetBefore = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("before trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + transferAssetBefore); - - Long devAssetBefore = PublicMethed.getAssetIssueValue(dev001Address, - assetAccountId, blockingStubFull); - logger.info("before trigger, dev001Address has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + devAssetBefore); - - tokenId = Long.toString(100_0000); - - String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "getToken(trcToken)", tokenId, false, 0, - 1000000000L, "0", 0, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - tokenId = Long.toString(0); - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "getToken(trcToken)", tokenId, false, 0, - 1000000000L, "0", 0, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - tokenId = Long.toString(-1); - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "getToken(trcToken)", tokenId, false, 0, - 1000000000L, "0", 0, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - tokenId = Long.toString(Long.MIN_VALUE); - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "getToken(trcToken)", tokenId, false, 0, - 1000000000L, "0", 0, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "getTokenLongMin()", "#", false, 0, - 1000000000L, "0", 0, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "getTokenLongMax()", "#", false, 0, - 1000000000L, "0", 0, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert.assertEquals(FAILED, infoById.get().getResult()); - //Assert.assertEquals("BigInteger out of long range", - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken076.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken076.java deleted file mode 100644 index 23092b86f7a..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken076.java +++ /dev/null @@ -1,138 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken076 { - - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] grammarAddress = ecKey1.getAddress(); - String testKeyForGrammarAddress = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKeyForGrammarAddress); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - logger.info(Long.toString(PublicMethed.queryAccount(testNetAccountKey, blockingStubFull) - .getBalance())); - } - - @Test(enabled = true, description = "Origin test ") - public void testDeployTransferTokenContract() { - PublicMethed - .sendcoin(grammarAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken076.sol"; - String contractName = "Test"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress, - grammarAddress, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - - PublicMethed.triggerContract(contractAddress, - "test()", "#", false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - txid = PublicMethed.triggerContract(contractAddress, - "getResult1()", "#", false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - logger.info("infoById:" + infoById); - Long returnnumber = ByteArray.toLong(ByteArray.fromHexString(ByteArray.toHexString( - infoById.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(returnnumber == 1); - - txid = PublicMethed.triggerContract(contractAddress, - "getResult2()", "#", false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - logger.info("-------------------------"); - - logger.info("infoById:" + infoById); - Long returnnumber2 = ByteArray.toLong(ByteArray.fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - - Assert.assertTrue(returnnumber2 == 1); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(grammarAddress, testKeyForGrammarAddress, testNetAccountAddress, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken077.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken077.java deleted file mode 100644 index e9eb6d3e1f1..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken077.java +++ /dev/null @@ -1,184 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken077 { - - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] grammarAddress = ecKey1.getAddress(); - String testKeyForGrammarAddress = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKeyForGrammarAddress); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - logger.info(Long.toString(PublicMethed.queryAccount(testNetAccountKey, blockingStubFull) - .getBalance())); - } - - @Test(enabled = false) - public void testAddress001() { - PublicMethed - .sendcoin(grammarAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken077.sol"; - String contractName = "trcToken077"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String deployTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress, - grammarAddress, blockingStubFull); - Optional deployInfo = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - contractAddress = deployInfo.get().getContractAddress().toByteArray(); - logger.info("Deploy energy is " + deployInfo.get().getReceipt().getEnergyUsageTotal()); - - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "addressTest()", "#", false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById:" + infoById); - logger.info("Trigger energy is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - } - - @Test(enabled = true, description = "The value of address is not at the beginning of 41") - public void testAddress002() { - PublicMethed - .sendcoin(grammarAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName = "trcToken077"; - - String code = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600" - + "080fd5b5060b0806100396000396000f3fe6080604052348015600f57600080fd5b50d38015601b57600080" - + "fd5b50d28015602757600080fd5b5060043610605c577c01000000000000000000000000000000000000000" - + "0000000000000000060003504636241c1d881146061575b600080fd5b60676079565b604080519182525190" - + "81900360200190f35b60405130908190529056fea165627a7a723058207b9b52e71420f2fa4cb55ffd55641" - + "355ec84e09d6d4545c629dde7cc01d74a100029"; - String abi = "[{\"constant\":false,\"inputs\":[],\"name\":\"addressTest\",\"outputs\":[{\"name" - + "\":\"addressValue\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonp" - + "ayable\",\"type\":\"function\"}]"; - - String deploytxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress, - grammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional deployById = PublicMethed - .getTransactionInfoById(deploytxid, blockingStubFull); - contractAddress = deployById.get().getContractAddress().toByteArray(); - logger.info("infoById:" + deployById); - - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "addressTest()", "#", false, - 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById:" + infoById); - - Assert.assertNotNull(infoById); - byte[] a = infoById.get().getContractResult(0).toByteArray(); - byte[] b = subByte(a, 11, 1); - byte[] c = subByte(a, 0, 11); - byte[] e = "41".getBytes(); - byte[] d = subByte(a, 12, 20); - - logger.info("a:" + ByteArray.toHexString(a)); - - logger.info("b:" + ByteArray.toHexString(b)); - logger.info("c:" + ByteArray.toHexString(c)); - - logger.info("d:" + ByteArray.toHexString(d)); - - logger.info("41" + ByteArray.toHexString(d)); - String exceptedResult = "41" + ByteArray.toHexString(d); - String realResult = ByteArray.toHexString(b); - Assert.assertEquals(realResult, "00"); - Assert.assertNotEquals(realResult, "41"); - - Assert.assertEquals(exceptedResult, ByteArray.toHexString(contractAddress)); - - } - - - /** - * constructor. - */ - - public byte[] subByte(byte[] b, int off, int length) { - byte[] b1 = new byte[length]; - System.arraycopy(b, off, b1, 0, length); - return b1; - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(grammarAddress, testKeyForGrammarAddress, testNetAccountAddress, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken078.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken078.java deleted file mode 100644 index f872d6a0a9b..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken078.java +++ /dev/null @@ -1,275 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j - -public class ContractTrcToken078 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] internalTxsAddress = ecKey1.getAddress(); - String testKeyForinternalTxsAddress = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - String priKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - /** - * constructor. - */ - - public static String byte2HexStr(byte[] b, int offset, int length) { - String stmp = ""; - StringBuilder sb = new StringBuilder(""); - for (int n = offset; n < offset + length && n < b.length; n++) { - stmp = Integer.toHexString(b[n] & 0xFF); - sb.append((stmp.length() == 1) ? "0" + stmp : stmp); - } - return sb.toString().toUpperCase().trim(); - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKeyForinternalTxsAddress); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - logger.info(Long.toString(PublicMethed.queryAccount(testNetAccountKey, blockingStubFull) - .getBalance())); - } - - @Test(enabled = true, description = "Origin test call") - public void testOriginCall001() { - PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken078.sol"; - String contractName = "callerContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById : " + infoById); - contractAddress = infoById.get().getContractAddress().toByteArray(); - - String filePath1 = "./src/test/resources/soliditycode/contractTrcToken078.sol"; - String contractName1 = "calledContract"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath1, contractName1); - - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - - txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName1, abi1, code1, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById : " + infoById); - byte[] contractAddress1; - contractAddress1 = infoById.get().getContractAddress().toByteArray(); - - String filePath2 = "./src/test/resources/soliditycode/contractTrcToken078.sol"; - String contractName2 = "c"; - HashMap retMap2 = PublicMethed.getBycodeAbi(filePath2, contractName2); - - String code2 = retMap2.get("byteCode").toString(); - String abi2 = retMap2.get("abI").toString(); - - txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName2, abi2, code2, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - byte[] contractAddress2 = infoById.get().getContractAddress().toByteArray(); - logger.info("infoById : " + infoById); - - String initParmes = "\"" + Base58.encode58Check(contractAddress1) - + "\",\"" + Base58.encode58Check(contractAddress2) + "\""; - - String txid2 = ""; - txid2 = PublicMethed.triggerContract(contractAddress, - "sendToB2(address,address)", initParmes, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById2 = null; - infoById2 = PublicMethed.getTransactionInfoById(txid2, blockingStubFull); - logger.info("Trigger InfobyId: " + infoById2); - Account info1 = PublicMethed.queryAccount(internalTxsAddress, blockingStubFull); - AccountResourceMessage resourceInfo1 = PublicMethed.getAccountResource(internalTxsAddress, - blockingStubFull); - logger.info("getEnergyUsed " + resourceInfo1.getEnergyUsed()); - logger.info("getEnergyLimit " + resourceInfo1.getEnergyLimit()); - Assert.assertTrue(infoById2.get().getResultValue() == 0); - - - } - - @Test(enabled = true, description = "Origin test delegatecall") - public void testOriginDelegatecall001() { - PublicMethed - .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken078.sol"; - String contractName = "callerContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById : " + infoById); - contractAddress = infoById.get().getContractAddress().toByteArray(); - - String filePath1 = "./src/test/resources/soliditycode/contractTrcToken078.sol"; - String contractName1 = "calledContract"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath1, contractName1); - - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName1, abi1, code1, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById : " + infoById); - byte[] contractAddress1; - contractAddress1 = infoById.get().getContractAddress().toByteArray(); - - String filePath2 = "./src/test/resources/soliditycode/contractTrcToken078.sol"; - String contractName2 = "c"; - HashMap retMap2 = PublicMethed.getBycodeAbi(filePath2, contractName2); - - String code2 = retMap2.get("byteCode").toString(); - String abi2 = retMap2.get("abI").toString(); - txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName2, abi2, code2, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById : " + infoById); - byte[] contractAddress2 = infoById.get().getContractAddress().toByteArray(); - - String initParmes = "\"" + Base58.encode58Check(contractAddress1) - + "\",\"" + Base58.encode58Check(contractAddress2) + "\""; - - String txid2 = ""; - txid2 = PublicMethed.triggerContract(contractAddress, - "sendToB(address,address)", initParmes, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById2 = null; - infoById2 = PublicMethed.getTransactionInfoById(txid2, blockingStubFull); - logger.info("infoById : " + infoById2); - - Assert.assertTrue(infoById2.get().getResultValue() == 0); - - - } - - private List getStrings(byte[] data) { - int index = 0; - List ret = new ArrayList<>(); - while (index < data.length) { - ret.add(byte2HexStr(data, index, 32)); - index += 32; - } - return ret; - } - - /** - * constructor. - */ - - public byte[] subByte(byte[] b, int off, int length) { - byte[] b1 = new byte[length]; - System.arraycopy(b, off, b1, 0, length); - return b1; - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(internalTxsAddress, testKeyForinternalTxsAddress, testNetAccountAddress, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken079.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken079.java deleted file mode 100644 index f7a6d452e46..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken079.java +++ /dev/null @@ -1,220 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken079 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "Trigger transferToken with 0 tokenValue and tokenId") - public void triggerTransferTokenContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 70000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, 100000L, - 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - Long devAssetCountBefore = PublicMethed.getAssetIssueValue(dev001Address, - assetAccountId, blockingStubFull); - - logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken079.sol"; - String contractName = "tokenTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String tokenId = assetAccountId.toStringUtf8(); - long tokenValue = 200; - long callValue = 0; - - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, callValue, 0, 10000, - tokenId, tokenValue, null, dev001Key, - dev001Address, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(transferTokenContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long devAssetCountAfter = PublicMethed.getAssetIssueValue(dev001Address, - assetAccountId, blockingStubFull); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(200), Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(200), contractAssetCount); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.transferAsset(user001Address, - assetAccountId.toByteArray(), 10L, dev001Address, dev001Key, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long transferAssetBefore = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("before trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + transferAssetBefore); - - PublicMethed - .sendcoin(transferTokenContractAddress, 5000000, fromAddress, testKey002, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - tokenId = Long.toString(0); - tokenValue = 0; - callValue = 5; - - String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "msgTokenValueAndTokenIdTest()", "#", false, callValue, - 1000000000L, tokenId, tokenValue, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - if (triggerTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - List retList = PublicMethed.getStrings(infoById.get() - .getContractResult(0).toByteArray()); - logger.info("the value: " + retList); - - Long msgId = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - Long msgTokenValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - Long msgCallValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(2))); - - logger.info("msgId: " + msgId); - logger.info("msgTokenValue: " + msgTokenValue); - logger.info("msgCallValue: " + msgCallValue); - - Assert.assertEquals(msgId.toString(), tokenId); - Assert.assertEquals(Long.valueOf(msgTokenValue), Long.valueOf(tokenValue)); - Assert.assertEquals(Long.valueOf(msgCallValue), Long.valueOf(callValue)); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, user001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken080.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken080.java deleted file mode 100644 index 9c980ebdc66..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken080.java +++ /dev/null @@ -1,195 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTrcToken080 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - @Test(enabled = true, description = "DeployContract with 0 tokenValue and tokenId") - public void deployTransferTokenContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 130000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(dev001Address, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, 100000L, - 1L, 1L, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - Long devAssetCountBefore = PublicMethed.getAssetIssueValue(dev001Address, - assetAccountId, blockingStubFull); - - logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken080.sol"; - String contractName = "tokenTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String tokenId = assetAccountId.toStringUtf8(); - long tokenValue = 100; - long callValue = 10; - - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callValue, 0, 10000, tokenId, tokenValue, - null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(transferTokenContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long devAssetCountAfter = PublicMethed.getAssetIssueValue(dev001Address, - assetAccountId, blockingStubFull); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - - Long contractAssetCount = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(tokenValue), - Long.valueOf(devAssetCountBefore - devAssetCountAfter)); - Assert.assertEquals(Long.valueOf(tokenValue), contractAssetCount); - - // get and verify the msg.value and msg.id - Long transferAssetBefore = PublicMethed.getAssetIssueValue(transferTokenContractAddress, - assetAccountId, blockingStubFull); - logger.info("before trigger, transferTokenContractAddress has AssetId " - + assetAccountId.toStringUtf8() + ", Count is " + transferAssetBefore); - - String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "getResultInCon()", "#", false, 0, - 1000000000L, "0", 0, dev001Address, dev001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - List retList = PublicMethed.getStrings(infoById.get() - .getContractResult(0).toByteArray()); - logger.info("The msg value: " + retList); - - Long msgId = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - Long msgTokenValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - Long msgCallValue = ByteArray.toLong(ByteArray.fromHexString(retList.get(2))); - - logger.info("msgId: " + msgId); - logger.info("msgTokenValue: " + msgTokenValue); - logger.info("msgCallValue: " + msgCallValue); - - Assert.assertEquals(msgId.toString(), tokenId); - Assert.assertEquals(Long.valueOf(msgTokenValue), Long.valueOf(tokenValue)); - Assert.assertEquals(Long.valueOf(msgCallValue), Long.valueOf(callValue)); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken081.java b/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken081.java deleted file mode 100644 index f2324b3cea2..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken081.java +++ /dev/null @@ -1,239 +0,0 @@ -package stest.tron.wallet.dailybuild.trctoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class ContractTrcToken081 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] tokenReceiver = null; - private byte[] tokenSender = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 3100_000_000L, fromAddress, testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 130000L, blockingStubFull), 0, - 1, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, 0, 0, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed - .createAssetIssue(dev001Address, tokenName, TotalSupply, 1, 10000, start, end, 1, - description, url, 100000L, 100000L, 1L, 1L, dev001Key, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - - String filePath = "./src/test/resources/soliditycode/contractTrcToken081.sol"; - String contractName = "TokenReceiver"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String tokenId = assetAccountId.toStringUtf8(); - - tokenReceiver = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 500000000L, 100, null, dev001Key, dev001Address, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed - .getContract(tokenReceiver, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - - contractName = "TokenSender"; - retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - code = retMap.get("byteCode").toString(); - abi = retMap.get("abI").toString(); - tokenSender = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 500000000L, 100, 10000L, assetAccountId.toStringUtf8(), - 10L, null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - smartContract = PublicMethed.getContract(tokenSender, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long contractAssetCount = PublicMethed - .getAssetIssueValue(tokenSender, assetAccountId, blockingStubFull); - logger.info("tokenSender has AssetId before: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Long devAssetCountAfterDeploy = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - logger.info("after deploy tokenSender AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountAfter: " + devAssetCountAfterDeploy); - Assert.assertTrue(10 == devAssetCountBefore - devAssetCountAfterDeploy); - Assert.assertTrue(10 == contractAssetCount); - - } - - - @Test(enabled = true, description = "transfer 1 trc10 to contract by assembly") - public void transferTokenToContract() { - Long senderAssetCountBefore = PublicMethed - .getAssetIssueValue(tokenSender, assetAccountId, blockingStubFull); - logger.info("before trigger tokenSender has AssetId before: " + assetAccountId.toStringUtf8() - + ", Count: " + senderAssetCountBefore); - - Long receiverAssetCountBefore = PublicMethed - .getAssetIssueValue(tokenReceiver, assetAccountId, blockingStubFull); - logger.info("before trigger tokenReceiver AssetId: " + assetAccountId.toStringUtf8() - + ", Count: " + receiverAssetCountBefore); - String args = "\"" + Base58.encode58Check(tokenReceiver) + "\""; - logger.info("args: " + args); - String triggerTxid = PublicMethed - .triggerContract(tokenSender, "sendTRC10(address)", args, false, 0, 1000000000L, - assetAccountId.toStringUtf8(), 0, dev001Address, dev001Key, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = - PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - Long senderAssetCountAfter = PublicMethed - .getAssetIssueValue(tokenSender, assetAccountId, blockingStubFull); - logger.info("tokenSender has AssetId After trigger: " + assetAccountId.toStringUtf8() - + ", Count: " + senderAssetCountAfter); - - Long receiverAssetCountAfterTrigger = PublicMethed - .getAssetIssueValue(tokenReceiver, assetAccountId, blockingStubFull); - logger.info("after trigger AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + receiverAssetCountAfterTrigger); - Assert.assertTrue(1 == senderAssetCountBefore - senderAssetCountAfter); - Assert.assertTrue(1 == receiverAssetCountAfterTrigger - receiverAssetCountBefore); - - } - - @Test(enabled = true, description = "transfer 1 trc10 to normal address by assembly") - public void transferTokenToNormalAddress() { - long senderAssetCountBefore = PublicMethed - .getAssetIssueValue(tokenSender, assetAccountId, blockingStubFull); - logger.info("tokenSender has AssetId After trigger: " + assetAccountId.toStringUtf8() - + ", Count: " + senderAssetCountBefore); - - long devAssetCountBeforeTrigger = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - logger.info("after trigger AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountAfterTrigger: " + devAssetCountBeforeTrigger); - - String args = "\"" + Base58.encode58Check(dev001Address) + "\""; - logger.info("args: " + args); - String triggerTxid = PublicMethed - .triggerContract(tokenSender, "sendTRC10(address)", args, false, 0, 1000000000L, - assetAccountId.toStringUtf8(), 0, dev001Address, dev001Key, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = - PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - long senderAssetCountAfter = PublicMethed - .getAssetIssueValue(tokenSender, assetAccountId, blockingStubFull); - logger.info("tokenSender has AssetId After trigger: " + assetAccountId.toStringUtf8() - + ", Count: " + senderAssetCountAfter); - - long devAssetCountAfterTrigger = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - logger.info("after trigger AssetId: " + assetAccountId.toStringUtf8() - + ", devAssetCountAfterTrigger: " + devAssetCountAfterTrigger); - Assert.assertTrue(1 == senderAssetCountBefore - senderAssetCountAfter); - Assert.assertTrue(1 == devAssetCountAfterTrigger - devAssetCountBeforeTrigger); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/addressStrictCheck/AddressStrictCheck001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/addressStrictCheck/AddressStrictCheck001.java deleted file mode 100644 index 597b8541ac4..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/addressStrictCheck/AddressStrictCheck001.java +++ /dev/null @@ -1,144 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.addressStrictCheck; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class AddressStrictCheck001 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - - @Test(enabled = true, description = "Open experimental check address ") - public void test01CheckAddressNew() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/addressCheckNew.sol"; - String contractName = "testIsContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String txid = ""; - String num = "00000000000000000000004108362A6DB594586C035758ECA382A49FDF13EF61"; - txid = PublicMethed.triggerContract(contractAddress, - "checkAddress(address)", num, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "checkAddress2(address)", num, true, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - - num = "10000000000000000000004108362A6DB594586C035758ECA382A49FDF13EF61"; - txid = PublicMethed.triggerContract(contractAddress, - "checkAddress(address)", num, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(1, infoById.get().getResultValue()); - Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); - - transactionExtention = PublicMethed.triggerConstantContractForExtention(contractAddress, - "checkAddress2(address)", num, true, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - logger.info("AAAAA:" + transactionExtention.toString()); - Assert.assertEquals("FAILED", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("REVERT opcode executed", - transactionExtention.getResult().getMessage().toStringUtf8()); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed.sendcoin(testNetAccountAddress, balance, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/addressStrictCheck/AddressStrictCheck002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/addressStrictCheck/AddressStrictCheck002.java deleted file mode 100644 index 13fd24c62dc..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/addressStrictCheck/AddressStrictCheck002.java +++ /dev/null @@ -1,142 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.addressStrictCheck; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class AddressStrictCheck002 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - - @Test(enabled = true, description = "Close experimental check address") - public void test01AddressOld() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/addressCheckOld.sol"; - String contractName = "testIsContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String txid = ""; - String num = "00000000000000000000004108362A6DB594586C035758ECA382A49FDF13EF61"; - txid = PublicMethed.triggerContract(contractAddress, - "checkAddress(address)", num, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - logger.info(infoById.toString()); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "checkAddress2(address)", num, true, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - - num = "10000000000000000000004108362A6DB594586C035758ECA382A49FDF13EF61"; - txid = PublicMethed.triggerContract(contractAddress, - "checkAddress(address)", num, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(1, infoById.get().getResultValue()); - logger.info(infoById.toString()); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "checkAddress2(address)", num, true, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert.assertEquals("REVERT opcode executed", - transactionExtention.getResult().getMessage().toStringUtf8()); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed.sendcoin(testNetAccountAddress, balance, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract001.java deleted file mode 100644 index 239a11c10a2..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract001.java +++ /dev/null @@ -1,368 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.batchValidateSignContract; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.crypto.Hash; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class batchValidateSignContract001 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - String txid = ""; - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/batchvalidatesign001.sol"; - String contractName = "Demo"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Correct 16 signatures test pure multivalidatesign") - public void test01Correct16signatures() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertEquals( - "class org.tron.core.vm.program.Program$OutOfTimeException " - + ": CPU timeout for 'ISZERO' operation executing", - transactionExtention.getResult().getMessage().toStringUtf8()); - } else { - Assert.assertEquals("11111111111111110000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "14 signatures with 1st incorrect signatures test" - + " pure multivalidatesign") - public void test02Incorrect1stSignatures() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 14; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - byte[] sign = new ECKey().sign(Hash.sha3("sdifhsdfihyw888w7".getBytes())).toByteArray(); - signatures.set(0, Hex.toHexString(sign)); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("01111111111111000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "13 signatures with 1st incorrect address test" - + " pure multivalidatesign") - public void test03Incorrect1stAddress() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 13; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - addresses.set(0, StringUtil.encode58Check(new ECKey().getAddress())); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("01111111111110000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "16 signatures with 15th incorrect signatures" - + " test pure multivalidatesign") - public void test04Incorrect15thSignatures() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - if (i == 14) { - signatures.add( - Hex.toHexString(key.sign("dgjjsldgjljvjjfdshkh123770807779".getBytes()).toByteArray())); - } else { - signatures.add(Hex.toHexString(sign)); - } - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("11111111111111010000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "15 signatures with 10th-15th incorrect address" - + " test pure multivalidatesign") - public void test05Incorrect15thTo30thAddress() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 15; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - for (int i = 9; i < 14; i++) { - addresses.set(i, StringUtil.encode58Check(new ECKey().getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("11111111100000100000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "16 signatures with 2nd/16th incorrect signatures" - + " test pure multivalidatesign") - public void test06Incorrect2ndAnd32ndIncorrectSignatures() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - if (i == 1 || i == 15) { - signatures.add( - Hex.toHexString(key.sign("dgjjsldgjljvjjfdshkh1hgsk0807779".getBytes()).toByteArray())); - } else { - signatures.add(Hex.toHexString(sign)); - } - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("10111111111111100000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "16 signatures with 6th/9th/11th/13nd incorrect address" - + " test pure multivalidatesign") - public void test07IncorrectAddress() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - addresses.set(5, StringUtil.encode58Check(new ECKey().getAddress())); - addresses.set(8, StringUtil.encode58Check(new ECKey().getAddress())); - addresses.set(10, StringUtil.encode58Check(new ECKey().getAddress())); - addresses.set(12, StringUtil.encode58Check(new ECKey().getAddress())); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("11111011010101110000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "16 signatures with Incorrect hash" - + " test pure multivalidatesign") - public void test08IncorrectHash() { - String txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - String incorrecttxid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays - .asList("0x" + Hex.toHexString(Hash.sha3(incorrecttxid.getBytes())), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed.sendcoin(testNetAccountAddress, balance, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract002.java deleted file mode 100644 index 2900554f345..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract002.java +++ /dev/null @@ -1,675 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.batchValidateSignContract; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.crypto.Hash; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class batchValidateSignContract002 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - String txid = ""; - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/batchvalidatesign001.sol"; - String contractName = "Demo"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Correct 16 signatures test multivalidatesign") - public void test01Correct16signatures() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("11111111111111110000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "14 signatures with 1st incorrect signatures" - + " test multivalidatesign") - public void test02Incorrect1stSignatures() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 14; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - byte[] sign = new ECKey().sign(Hash.sha3("sdifhsdfihyw888w7".getBytes())).toByteArray(); - signatures.set(0, Hex.toHexString(sign)); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("01111111111111000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "13 signatures with 1st incorrect address" - + " test multivalidatesign") - public void test03Incorrect1stAddress() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 13; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - addresses.set(0, StringUtil.encode58Check(new ECKey().getAddress())); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("01111111111110000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "16 signatures with 15th incorrect signatures" - + " test multivalidatesign") - public void test04Incorrect15thSignatures() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - if (i == 14) { - signatures.add( - Hex.toHexString(key.sign("dgjjsldgjljvjjfdshkh123770807779".getBytes()).toByteArray())); - } else { - signatures.add(Hex.toHexString(sign)); - } - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("11111111111111010000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "15 signatures with 10th-15th incorrect address" - + " test multivalidatesign") - public void test05Incorrect15thTo30thAddress() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 15; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - for (int i = 9; i < 14; i++) { - addresses.set(i, StringUtil.encode58Check(new ECKey().getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("11111111100000100000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "16 signatures with 2nd、16th incorrect signatures" - + " test multivalidatesign") - public void test06Incorrect2ndAnd32ndIncorrectSignatures() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - if (i == 1 || i == 15) { - signatures.add( - Hex.toHexString(key.sign("dgjjsldgjljvjjfdshkh1hgsk0807779".getBytes()).toByteArray())); - } else { - signatures.add(Hex.toHexString(sign)); - } - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("10111111111111100000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "16 signatures with 6th/9th/11th/13nd incorrect address" - + " test multivalidatesign") - public void test07IncorrectAddress() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - addresses.set(5, StringUtil.encode58Check(new ECKey().getAddress())); - addresses.set(8, StringUtil.encode58Check(new ECKey().getAddress())); - addresses.set(10, StringUtil.encode58Check(new ECKey().getAddress())); - addresses.set(12, StringUtil.encode58Check(new ECKey().getAddress())); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("11111011010101110000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "16 signatures with Incorrect hash test multivalidatesign") - public void test08IncorrectHash() { - String incorrecttxid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays - .asList("0x" + Hex.toHexString(Hash.sha3(incorrecttxid.getBytes())), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed.sendcoin(testNetAccountAddress, balance, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract003.java deleted file mode 100644 index 4f2b62354f1..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract003.java +++ /dev/null @@ -1,302 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.batchValidateSignContract; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.crypto.Hash; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class batchValidateSignContract003 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - String txid = ""; - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/batchvalidatesign001.sol"; - String contractName = "Demo"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "13 signatures and 12 address test pure multivalidatesign") - public void test01With25SignaturesAnd24Address() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 12; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - byte[] sign = new ECKey().sign(Hash.sha3("sdifhsdfihyw888w7".getBytes())).toByteArray(); - signatures.add(Hex.toHexString(sign)); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "7 signatures and 8 address test pure multivalidatesign") - public void test02With15SignaturesAnd16Address() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 7; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - addresses.add(StringUtil.encode58Check(new ECKey().getAddress())); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "150 signatures and 1 address test pure multivalidatesign") - public void test03With150SignaturesAnd1Address() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 150; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - } - addresses.add(StringUtil.encode58Check(new ECKey().getAddress())); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "1 signatures and 160 address test pure multivalidatesign") - public void test04With1SignaturesAnd160Address() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 160; i++) { - ECKey key = new ECKey(); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - byte[] sign = new ECKey().sign(Hash.sha3("sdifhsdfihyw888w7".getBytes())).toByteArray(); - signatures.add(Hex.toHexString(sign)); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "16 signatures and 17 address test pure multivalidatesign") - public void test05With32SignaturesAnd33Address() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - addresses.add(StringUtil.encode58Check(new ECKey().getAddress())); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "17 signatures and 16 address test pure multivalidatesign") - public void test06With33SignaturesAnd32Address() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - byte[] sign = new ECKey().sign(Hash.sha3("sdifhsdfihyw888w7".getBytes())).toByteArray(); - signatures.add(Hex.toHexString(sign)); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed.sendcoin(testNetAccountAddress, balance, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - private String parametersString(List parameters) { - String[] inputArr = new String[parameters.size()]; - int i = 0; - for (Object parameter : parameters) { - if (parameter instanceof List) { - StringBuilder sb = new StringBuilder(); - for (Object item : (List) parameter) { - if (sb.length() != 0) { - sb.append(","); - } - sb.append("\"").append(item).append("\""); - } - inputArr[i++] = "[" + sb.toString() + "]"; - } else { - inputArr[i++] = - (parameter instanceof String) ? ("\"" + parameter + "\"") : ("" + parameter); - } - } - String input = StringUtils.join(inputArr, ','); - return input; - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract004.java deleted file mode 100644 index ca1da710088..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract004.java +++ /dev/null @@ -1,534 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.batchValidateSignContract; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.crypto.Hash; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class batchValidateSignContract004 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - String txid = ""; - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/batchvalidatesign001.sol"; - String contractName = "Demo"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "10 signatures and 9 address test multivalidatesign") - public void test01With25SignaturesAnd24Address() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 9; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - byte[] sign = new ECKey().sign(Hash.sha3("sdifhsdfihyw888w7".getBytes())).toByteArray(); - signatures.add(Hex.toHexString(sign)); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "14 signatures and 15 address test multivalidatesign") - public void test02With15SignaturesAnd16Address() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 14; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - addresses.add(StringUtil.encode58Check(new ECKey().getAddress())); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "40 signatures and 1 address test multivalidatesign") - public void test03With40SignaturesAnd1Address() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 40; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - } - addresses.add(StringUtil.encode58Check(new ECKey().getAddress())); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "1 signatures and 50 address test multivalidatesign") - public void test04With1SignaturesAnd50Address() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 50; i++) { - ECKey key = new ECKey(); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - byte[] sign = new ECKey().sign(Hash.sha3("sdifhsdfihyw888w7".getBytes())).toByteArray(); - signatures.add(Hex.toHexString(sign)); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "16 signatures and 17 address test multivalidatesign") - public void test05With32SignaturesAnd33Address() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - addresses.add(StringUtil.encode58Check(new ECKey().getAddress())); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "17 signatures and 16 address test multivalidatesign") - public void test06With33SignaturesAnd32Address() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - byte[] sign = new ECKey().sign(Hash.sha3("sdifhsdfihyw888w7".getBytes())).toByteArray(); - signatures.add(Hex.toHexString(sign)); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed.sendcoin(testNetAccountAddress, balance, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - private String parametersString(List parameters) { - String[] inputArr = new String[parameters.size()]; - int i = 0; - for (Object parameter : parameters) { - if (parameter instanceof List) { - StringBuilder sb = new StringBuilder(); - for (Object item : (List) parameter) { - if (sb.length() != 0) { - sb.append(","); - } - sb.append("\"").append(item).append("\""); - } - inputArr[i++] = "[" + sb.toString() + "]"; - } else { - inputArr[i++] = - (parameter instanceof String) ? ("\"" + parameter + "\"") : ("" + parameter); - } - } - String input = StringUtils.join(inputArr, ','); - return input; - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract005.java deleted file mode 100644 index 3575ecd3751..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract005.java +++ /dev/null @@ -1,233 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.batchValidateSignContract; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.crypto.Hash; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j - -public class batchValidateSignContract005 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - String txid = ""; - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/batchvalidatesign001.sol"; - String contractName = "Demo"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Hash is empty test multivalidatesign") - public void test01HashIsEmpty() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays.asList("0x" + "", signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "Address is empty test multivalidatesign") - public void test02AddressIsEmpty() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "Signatures is empty test multivalidatesign") - public void test03SignaturesIsEmpty() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "Signatures and addresses are empty test multivalidatesign") - public void test04SignaturesAndAddressesAreEmpty() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "All empty test multivalidatesign") - public void test05AllEmpty() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - List parameters = Arrays.asList("0x" + "", signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed.sendcoin(testNetAccountAddress, balance, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract006.java deleted file mode 100644 index f64d71de7c1..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract006.java +++ /dev/null @@ -1,426 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.batchValidateSignContract; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.crypto.Hash; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j - -public class batchValidateSignContract006 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - String txid = ""; - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/batchvalidatesign001.sol"; - String contractName = "Demo"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Hash is empty test multivalidatesign") - public void test01HashIsEmpty() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays.asList("0x" + "", signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContract(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "Address is empty test multivalidatesign") - public void test02AddressIsEmpty() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContract(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "Signatures is empty test multivalidatesign") - public void test03SignaturesIsEmpty() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContract(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "Signatures and addresses are empty test multivalidatesign") - public void test04SignaturesAndAddressesAreEmpty() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContract(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "All empty test multivalidatesign") - public void test05AllEmpty() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - List parameters = Arrays.asList("0x" + "", signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContract(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed.sendcoin(testNetAccountAddress, balance, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract007.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract007.java deleted file mode 100644 index 5a2a6f2b383..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract007.java +++ /dev/null @@ -1,196 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.batchValidateSignContract; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.crypto.Hash; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class batchValidateSignContract007 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - @Test(enabled = true, description = "Constructor test multivalidatesign") - public void test01Constructor() { - String txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 2000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "src/test/resources/soliditycode/batchvalidatesign007.sol"; - String contractName = "Demo"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String data = PublicMethed.parametersString(parameters); - String constructorStr = "constructor(bytes32,bytes[],address[])"; - txid = PublicMethed - .deployContractWithConstantParame(contractName, abi, code, constructorStr, data, "", - maxFeeLimit, 0L, 100, null, contractExcKey, contractExcAddress, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Long fee1 = infoById.get().getFee(); - Long netUsed1 = infoById.get().getReceipt().getNetUsage(); - Long energyUsed1 = infoById.get().getReceipt().getEnergyUsage(); - Long netFee1 = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal1 = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee1:" + fee1); - logger.info("netUsed1:" + netUsed1); - logger.info("energyUsed1:" + energyUsed1); - logger.info("netFee1:" + netFee1); - logger.info("energyUsageTotal1:" + energyUsageTotal1); - contractAddress = infoById.get().getContractAddress().toByteArray(); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testConstructorPure()", "", false, 0, - 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Assert.assertEquals("11111111111111110000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - - txid = PublicMethed - .triggerContract(contractAddress, "testConstructor()", "", false, 0, maxFeeLimit, - contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById2 = null; - infoById2 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById2.get().getResultValue() == 0) { - Assert.assertEquals("11111111111111110000000000000000", - PublicMethed.bytes32ToString(infoById2.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById2.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById2.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Long fee2 = infoById2.get().getFee(); - Long netUsed2 = infoById2.get().getReceipt().getNetUsage(); - Long energyUsed2 = infoById2.get().getReceipt().getEnergyUsage(); - Long netFee2 = infoById2.get().getReceipt().getNetFee(); - long energyUsageTotal2 = infoById2.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee2:" + fee2); - logger.info("netUsed2:" + netUsed2); - logger.info("energyUsed2:" + energyUsed2); - logger.info("netFee2:" + netFee2); - logger.info("energyUsageTotal2:" + energyUsageTotal2); - - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee1 + fee2 == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed1 + energyUsed2 >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed1 + netUsed2 >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed1 + netUsed2 >= afterNetUsed); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed.sendcoin(testNetAccountAddress, balance, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract008.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract008.java deleted file mode 100644 index 7181272948a..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract008.java +++ /dev/null @@ -1,146 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.batchValidateSignContract; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class batchValidateSignContract008 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - String txid = ""; - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/batchvalidatesign001.sol"; - String contractName = "Demo"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Incorrect address hex test pure multivalidatesign") - public void test01IncorrectAddressHex() { - String input = "7d889f42b4a56ebe78264631a3b4daf21019e1170cce71929fb396761cdf532e00000000000000" - + "000000000000000000000000000000000000000000000000600000000000000000000000000000000000000" - + "0000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000" - + "000200000000000000000000000000000000000000000000000000000000000000400000000000000000000" - + "0000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000" - + "0000000000000000000041ad7ca8100cf0ce028b83ac719c8458655a6605317abfd071b91f5cc14d53e87a2" - + "99fe0cdf6a8567074e9be3944affba33b1e15d14b7cb9003ec2c87cb1a56405000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - + "000000000000000417ce31e565fb99451f87db65e75f46672e8a8f7b29e6589e60fd11e076550d0a66d0b05" - + "e4b4d7d40bd34140f13dc3632d3ce0f25e4cf75840238b6fe2346c94fa01000000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - + "0000000000020000000000000000000000410d6b1de9e84c1d7a9a5b43d93dbe4a5aae79b18900000000000" - + "00000000000123456"; - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, true, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - Assert.assertEquals("", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("REVERT opcode executed", - ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - Assert.assertEquals("FAILED", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - - @Test(enabled = true, description = "Empty address and signatures hex" - + " test pure multivalidatesign") - public void test02EmptyAddressAndSignaturesHex() { - String input = "da586d881362c0c38eb31b556ce0f7c2837a3ebb60080e8e665a6b92c7541837b95064ba000000" - + "000000000000000000000000000000000000000000000000000000006000000000000000000000000000000" - + "000000000000000000000000000000001200000000000000000000000000000000000000000000000000000" - + "000000000001000000000000000000000000000000000000000000000000000000000000002000000000000" - + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - + "000000000000000000000000000000000000000000000001000000000000000000000000000000000000000" - + "0000000000000000000000000"; - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, true, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - Assert.assertEquals("", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("REVERT opcode executed", - ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - Assert.assertEquals("FAILED", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed.sendcoin(testNetAccountAddress, balance, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract009.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract009.java deleted file mode 100644 index 0ed65c032a4..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract009.java +++ /dev/null @@ -1,225 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.batchValidateSignContract; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class batchValidateSignContract009 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - String txid = ""; - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/batchvalidatesign001.sol"; - String contractName = "Demo"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Incorrect address hex test multivalidatesign") - public void test02IncorrectAddressHex() { - Protocol.Account info; - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String input = "7d889f42b4a56ebe78264631a3b4daf21019e1170cce71929fb396761cdf532e00000000000000" - + "000000000000000000000000000000000000000000000000600000000000000000000000000000000000000" - + "0000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000" - + "000200000000000000000000000000000000000000000000000000000000000000400000000000000000000" - + "0000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000" - + "0000000000000000000041ad7ca8100cf0ce028b83ac719c8458655a6605317abfd071b91f5cc14d53e87a2" - + "99fe0cdf6a8567074e9be3944affba33b1e15d14b7cb9003ec2c87cb1a56405000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - + "000000000000000417ce31e565fb99451f87db65e75f46672e8a8f7b29e6589e60fd11e076550d0a66d0b05" - + "e4b4d7d40bd34140f13dc3632d3ce0f25e4cf75840238b6fe2346c94fa01000000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - + "0000000000020000000000000000000000410d6b1de9e84c1d7a9a5b43d93dbe4a5aae79b18900000000000" - + "00000000000123456"; - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, true, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(1, infoById.get().getResultValue()); - Assert.assertTrue( - infoById.get().getResMessage().toStringUtf8().contains("REVERT opcode executed")); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "Empty address and signatures hex test multivalidatesign") - public void test03EmptyAddressAndSignaturesHex() { - Protocol.Account info; - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String input = "da586d881362c0c38eb31b556ce0f7c2837a3ebb60080e8e665a6b92c7541837b95064ba000000" - + "000000000000000000000000000000000000000000000000000000006000000000000000000000000000000" - + "000000000000000000000000000000001200000000000000000000000000000000000000000000000000000" - + "000000000001000000000000000000000000000000000000000000000000000000000000002000000000000" - + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - + "000000000000000000000000000000000000000000000001000000000000000000000000000000000000000" - + "0000000000000000000000000"; - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, true, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(1, infoById.get().getResultValue()); - Assert.assertTrue( - infoById.get().getResMessage().toStringUtf8().contains("REVERT opcode executed")); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed.sendcoin(testNetAccountAddress, balance, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract010.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract010.java deleted file mode 100644 index 58ee1e4ef9c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract010.java +++ /dev/null @@ -1,358 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.batchValidateSignContract; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.crypto.Hash; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class batchValidateSignContract010 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - String txid = ""; - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/batchvalidatesign001.sol"; - String contractName = "Demo"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Correct 50 signatures test multivalidatesign") - public void test01Correct50Signatures() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 50; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "2 signatures with 1st incorrect signatures" - + " test multivalidatesign") - public void test02Incorrect1stSignatures() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 2; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - byte[] sign = new ECKey().sign(Hash.sha3("sdifhsdfihyw888w7".getBytes())).toByteArray(); - signatures.set(0, Hex.toHexString(sign)); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("01000000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "3 signatures with 1st incorrect address" - + " test multivalidatesign") - public void test03Incorrect1stAddress() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 3; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - addresses.set(0, StringUtil.encode58Check(new ECKey().getAddress())); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("01100000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "9 signatures with 7th incorrect signatures" - + " test multivalidatesign") - public void test04Incorrect15thSignatures() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 9; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - byte[] sign = new ECKey().sign(Hash.sha3("sdifhsdfihyw888w7".getBytes())).toByteArray(); - signatures.set(6, Hex.toHexString(sign)); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("11111101100000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "5 signatures with 2th-4th incorrect address" - + " test multivalidatesign") - public void test05Incorrect15thTo30thAddress() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 5; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - for (int i = 1; i < 4; i++) { - addresses.set(i, StringUtil.encode58Check(new ECKey().getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("10001000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "150 signatures with 2nd/32nd incorrect signatures" - + " test multivalidatesign") - public void test06Incorrect2ndAnd32ndIncorrectSignatures() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 150; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - if (i == 1 || i == 31) { - signatures.add( - Hex.toHexString(key.sign("dgjjsldgjljvjjfdshkh1hgsk0807779".getBytes()).toByteArray())); - } else { - signatures.add(Hex.toHexString(sign)); - } - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "88 signatures with 9th/11th/28th/32nd incorrect address" - + " test multivalidatesign") - public void test07IncorrectAddress() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 88; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - addresses.set(8, StringUtil.encode58Check(new ECKey().getAddress())); - addresses.set(10, StringUtil.encode58Check(new ECKey().getAddress())); - addresses.set(27, StringUtil.encode58Check(new ECKey().getAddress())); - addresses.set(31, StringUtil.encode58Check(new ECKey().getAddress())); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - @Test(enabled = true, description = "105 signatures with Incorrect hash test multivalidatesign") - public void test08IncorrectHash() { - String incorrecttxid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 105; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays - .asList("0x" + Hex.toHexString(Hash.sha3(incorrecttxid.getBytes())), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPure(bytes32,bytes[],address[])", - input, false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - if (transactionExtention.getResult().getCode().toString().equals("CONTRACT_EXE_ERROR")) { - Assert.assertTrue(transactionExtention.getResult().getMessage().toStringUtf8().contains( - "class org.tron.core.vm.program.Program$OutOfTimeException : CPU timeout for")); - } else { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed.sendcoin(testNetAccountAddress, balance, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract011.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract011.java deleted file mode 100644 index 8286211defb..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract011.java +++ /dev/null @@ -1,695 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.batchValidateSignContract; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.crypto.Hash; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class batchValidateSignContract011 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - String txid = ""; - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/batchvalidatesign001.sol"; - String contractName = "Demo"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Correct 17 signatures test multivalidatesign") - public void test01Correct33Signatures() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 17; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - Assert.assertTrue(afterBalance + fee == beforeBalance); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - Assert.assertTrue(afterBalance == 0); - txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "14 signatures with 1st incorrect signatures" - + " test multivalidatesign") - public void test02Incorrect1stSignatures() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 14; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - byte[] sign = new ECKey().sign(Hash.sha3("sdifhsdfihyw888w7".getBytes())).toByteArray(); - signatures.set(0, Hex.toHexString(sign)); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("01111111111111000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "8 signatures with 1st incorrect address" - + " test multivalidatesign") - public void test03Incorrect1stAddress() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 8; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - addresses.set(0, StringUtil.encode58Check(new ECKey().getAddress())); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("01111111000000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "6 signatures with 3th incorrect signatures" - + " test multivalidatesign") - public void test04Incorrect15thSignatures() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 6; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - byte[] sign = new ECKey().sign(Hash.sha3("sdifhsdfihyw888w7".getBytes())).toByteArray(); - signatures.set(2, Hex.toHexString(sign)); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("11011100000000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "11 signatures with 7th-9th incorrect address" - + " test multivalidatesign") - public void test05Incorrect15thTo30thAddress() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 11; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - for (int i = 6; i < 9; i++) { - addresses.set(i, StringUtil.encode58Check(new ECKey().getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("11111100011000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "40 signatures with 2nd、32nd incorrect signatures" - + " test multivalidatesign") - public void test06Incorrect2ndAnd32ndIncorrectSignatures() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 40; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - if (i == 1 || i == 31) { - signatures.add( - Hex.toHexString(key.sign("dgjjsldgjljvjjfdshkh1hgsk0807779".getBytes()).toByteArray())); - } else { - signatures.add(Hex.toHexString(sign)); - } - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - Assert.assertTrue(afterBalance + fee == beforeBalance); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - Assert.assertTrue(afterBalance == 0); - txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "44 signatures with 9th/11th/28th/32nd incorrect address" - + " test multivalidatesign") - public void test07IncorrectAddress() { - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 44; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - addresses.set(8, StringUtil.encode58Check(new ECKey().getAddress())); - addresses.set(10, StringUtil.encode58Check(new ECKey().getAddress())); - addresses.set(27, StringUtil.encode58Check(new ECKey().getAddress())); - addresses.set(31, StringUtil.encode58Check(new ECKey().getAddress())); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - Assert.assertTrue(afterBalance + fee == beforeBalance); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - Assert.assertTrue(afterBalance == 0); - txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "16 signatures with Incorrect hash test multivalidatesign") - public void test08IncorrectHash() { - String incorrecttxid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays - .asList("0x" + Hex.toHexString(Hash.sha3(incorrecttxid.getBytes())), signatures, addresses); - String input = PublicMethed.parametersString(parameters); - txid = PublicMethed - .triggerContractBoth(contractAddress, "testArray(bytes32,bytes[],address[])", input, false, - 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - if (infoById.get().getResultValue() == 0) { - Assert.assertEquals("00000000000000000000000000000000", - PublicMethed.bytes32ToString(infoById.get().getContractResult(0).toByteArray())); - Assert.assertTrue(afterBalance + fee == beforeBalance); - } else { - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8().contains("CPU timeout for") - || "Already Time Out".equals(infoById.get().getResMessage().toStringUtf8())); - Assert.assertTrue(afterBalance == 0); - txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed.sendcoin(testNetAccountAddress, balance, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract012.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract012.java deleted file mode 100644 index c8a92174265..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/batchValidateSignContract/batchValidateSignContract012.java +++ /dev/null @@ -1,172 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.batchValidateSignContract; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.crypto.Hash; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.AbiUtil; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class batchValidateSignContract012 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - String txid; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 10000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/batchvalidatesign005.sol"; - String contractName = "Demo"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Trigger precompile multivalisign function with correct data") - public void test01TriggerPrecompileMultivalisignWithCorrectData() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String argsStr = PublicMethed.parametersString(parameters); - - String input = AbiUtil.parseParameters("batchvalidatesign(bytes32,bytes[],address[])", argsStr); - String method = "testArray2(bytes)"; - txid = PublicMethed.triggerContractBoth(contractAddress, method, - AbiUtil.parseParameters(method, Arrays.asList(input)), true, 0, maxFeeLimit, - contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - PublicMethed.getTransactionById(txid, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - logger.info( - "infoById:" + ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - Assert.assertTrue(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()) - .equals("0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000040" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0101010101010101010101010101010100000000000000000000000000000000")); - } - - @Test(enabled = true, description = "Trigger precompile multivalidatesign function with incor" - + "rect data") - public void test02TriggerPrecompileMultivalisignWithIncorrectData() { - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = Hash.sha3(txid.getBytes()); - for (int i = 0; i < 16; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - byte[] sign = new ECKey().sign(Hash.sha3("sdifhsdfihyw888w7".getBytes())).toByteArray(); - signatures.set(0, Hex.toHexString(sign)); - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String argsStr = PublicMethed.parametersString(parameters); - - String input = AbiUtil.parseParameters("batchvalidatesign(bytes32,bytes[],address[])", argsStr); - String method = "testArray2(bytes)"; - txid = PublicMethed.triggerContractBoth(contractAddress, method, - AbiUtil.parseParameters(method, Arrays.asList(input)), true, 0, maxFeeLimit, - contractExcAddress, contractExcKey, blockingStubFull, blockingStubFull1); - PublicMethed.getTransactionById(txid, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - logger.info( - "infoById:" + ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - Assert.assertTrue(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()) - .equals("0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000040" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0001010101010101010101010101010100000000000000000000000000000000")); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed.sendcoin(testNetAccountAddress, balance, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi001.java deleted file mode 100644 index 8ae62939860..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi001.java +++ /dev/null @@ -1,301 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.clearabi; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ClearAbi001 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress1 = ecKey2.getAddress(); - String contractExcKey1 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress1, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Clear a contract created by other account") - public void testClearAbi001() { - String filePath = "src/test/resources/soliditycode/ClearAbi001.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .clearContractAbiForExtention(contractAddress, contractExcAddress1, contractExcKey1, - blockingStubFull); - Assert - .assertThat(transactionExtention.getResult().getCode().toString(), - containsString("CONTRACT_VALIDATE_ERROR")); - Assert - .assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("is not the owner of the contract")); - - smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - - - } - - - @Test(enabled = true, description = "Clear a contract with ABI created by itself") - public void testClearAbi002() { - - String contractName = "testConstantContract"; - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String txid = PublicMethed - .clearContractAbi(contractAddress, contractExcAddress, contractExcKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - String txid1 = PublicMethed - .clearContractAbi(contractAddress, contractExcAddress, contractExcKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - Assert.assertTrue(infoById1.get().getResultValue() == 0); - - smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - } - - - @Test(enabled = true, description = "Clear a contract without ABI") - public void testClearAbi003() { - - String contractName = "testConstantContract"; - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String txid = PublicMethed - .clearContractAbi(contractAddress, contractExcAddress, contractExcKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - - - } - - @Test(enabled = true, description = "Clear a account address") - public void testClearAbi004() { - TransactionExtention transactionExtention = PublicMethed - .clearContractAbiForExtention(contractExcAddress, contractExcAddress, contractExcKey, - blockingStubFull); - Assert - .assertThat(transactionExtention.getResult().getCode().toString(), - containsString("CONTRACT_VALIDATE_ERROR")); - Assert - .assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Contract validate error : Contract not exists")); - } - - - @Test(enabled = true, description = "Clear a uninitialized account") - public void testClearAbi005() { - - ECKey ecKeyN = new ECKey(Utils.getRandom()); - byte[] contractExcAddressN = ecKeyN.getAddress(); - String contractExcKeyN = ByteArray.toHexString(ecKeyN.getPrivKeyBytes()); - - TransactionExtention transactionExtention = PublicMethed - .clearContractAbiForExtention(contractExcAddressN, contractExcAddress, contractExcKey, - blockingStubFull); - Assert.assertThat(transactionExtention.getResult().getCode().toString(), - containsString("CONTRACT_VALIDATE_ERROR")); - Assert.assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Contract validate error : Contract not exists")); - - } - - @Test(enabled = true, description = "Clear a not meet the rules address") - public void testClearAbi006() { - byte[] fakeAddress = "412B5D".getBytes(); - TransactionExtention transactionExtention = PublicMethed - .clearContractAbiForExtention(fakeAddress, contractExcAddress, contractExcKey, - blockingStubFull); - Assert - .assertThat(transactionExtention.getResult().getCode().toString(), - containsString("CONTRACT_VALIDATE_ERROR")); - Assert - .assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Contract validate error : Contract not exists")); - byte[] fakeAddress1 = "412B5D3405B2D26767C9C09886D53DEAFF6EB718AC111".getBytes(); - - TransactionExtention transactionExtention1 = PublicMethed - .clearContractAbiForExtention(fakeAddress1, contractExcAddress, contractExcKey, - blockingStubFull); - Assert - .assertThat(transactionExtention1.getResult().getCode().toString(), - containsString("CONTRACT_VALIDATE_ERROR")); - Assert - .assertThat(transactionExtention1.getResult().getMessage().toStringUtf8(), - containsString("Contract validate error : Contract not exists")); - - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - PublicMethed.freedResource(contractExcAddress1, contractExcKey1, testNetAccountAddress, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi002.java deleted file mode 100644 index 4b8c50b980e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi002.java +++ /dev/null @@ -1,149 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.clearabi; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ClearAbi002 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Clear a contract with ABI created by itself") - public void testClearAbi() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/ClearAbi001.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String txid = PublicMethed - .clearContractAbi(contractAddress, contractExcAddress, contractExcKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi003.java deleted file mode 100644 index b6553e1e755..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi003.java +++ /dev/null @@ -1,148 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.clearabi; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ClearAbi003 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Clear a contract without ABI") - public void testClearAbi() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/ClearAbi001.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, "[]", code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String txid = PublicMethed - .clearContractAbi(contractAddress, contractExcAddress, contractExcKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi004.java deleted file mode 100644 index 4e2a940bef1..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi004.java +++ /dev/null @@ -1,115 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.clearabi; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ClearAbi004 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Clear a account address") - public void testClearAbi() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - TransactionExtention transactionExtention = PublicMethed - .clearContractAbiForExtention(contractExcAddress, contractExcAddress, contractExcKey, - blockingStubFull); - Assert - .assertThat(transactionExtention.getResult().getCode().toString(), - containsString("CONTRACT_VALIDATE_ERROR")); - Assert - .assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Contract validate error : Contract not exists")); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi005.java deleted file mode 100644 index 149d512c336..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi005.java +++ /dev/null @@ -1,197 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.clearabi; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ClearAbi005 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Clear a contract created by create2 (without ABI)") - public void testClearAbi() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/ClearAbi005.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String contractName1 = "TestConstract"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - String txid = ""; - String num = "\"" + code1 + "\"" + "," + 1; - txid = PublicMethed - .triggerContract(contractAddress, - "deploy(bytes,uint256)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - byte[] returnAddressBytes = infoById.get().getInternalTransactions(0).getTransferToAddress() - .toByteArray(); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - SmartContract smartContract = PublicMethed.getContract(returnAddressBytes, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - TransactionExtention transactionExtention = PublicMethed - .clearContractAbiForExtention(returnAddressBytes, contractExcAddress, contractExcKey, - blockingStubFull); - Assert - .assertThat(transactionExtention.getResult().getCode().toString(), - containsString("CONTRACT_VALIDATE_ERROR")); - Assert - .assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("is not the owner of the contract")); - - smartContract = PublicMethed.getContract(returnAddressBytes, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - } - - - /** - * testClearAbitestClearAbi constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi006.java deleted file mode 100644 index 19e52757f07..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi006.java +++ /dev/null @@ -1,114 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.clearabi; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ClearAbi006 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress1 = ecKey2.getAddress(); - String contractExcKey1 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Clear a uninitialized account") - public void testClearAbi() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - TransactionExtention transactionExtention = PublicMethed - .clearContractAbiForExtention(contractExcAddress1, contractExcAddress, contractExcKey, - blockingStubFull); - Assert.assertThat(transactionExtention.getResult().getCode().toString(), - containsString("CONTRACT_VALIDATE_ERROR")); - Assert.assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Contract validate error : Contract not exists")); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi007.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi007.java deleted file mode 100644 index 5ee23abd611..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi007.java +++ /dev/null @@ -1,129 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.clearabi; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ClearAbi007 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress1 = ecKey2.getAddress(); - String contractExcKey1 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Clear a not meet the rules address") - public void testClearAbi() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - byte[] fakeAddress = "412B5D".getBytes(); - TransactionExtention transactionExtention = PublicMethed - .clearContractAbiForExtention(fakeAddress, contractExcAddress, contractExcKey, - blockingStubFull); - Assert - .assertThat(transactionExtention.getResult().getCode().toString(), - containsString("CONTRACT_VALIDATE_ERROR")); - Assert - .assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Contract validate error : Contract not exists")); - byte[] fakeAddress1 = "412B5D3405B2D26767C9C09886D53DEAFF6EB718AC111".getBytes(); - - TransactionExtention transactionExtention1 = PublicMethed - .clearContractAbiForExtention(fakeAddress1, contractExcAddress, contractExcKey, - blockingStubFull); - Assert - .assertThat(transactionExtention1.getResult().getCode().toString(), - containsString("CONTRACT_VALIDATE_ERROR")); - Assert - .assertThat(transactionExtention1.getResult().getMessage().toStringUtf8(), - containsString("Contract validate error : Contract not exists")); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi008.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi008.java deleted file mode 100644 index 76d9b04804d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/ClearAbi008.java +++ /dev/null @@ -1,162 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.clearabi; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ClearAbi008 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Clear a contract with ABI created by itself," - + "clear a contract by itself again") - public void testClearAbi() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/ClearAbi001.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String txid = PublicMethed - .clearContractAbi(contractAddress, contractExcAddress, contractExcKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - - String txid1 = PublicMethed - .clearContractAbi(contractAddress, contractExcAddress, contractExcKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - Assert.assertTrue(infoById1.get().getResultValue() == 0); - - smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/NoAbi009.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/NoAbi009.java deleted file mode 100644 index 328e00b19f0..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/clearabi/NoAbi009.java +++ /dev/null @@ -1,356 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.clearabi; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import org.tron.protos.contract.SmartContractOuterClass.SmartContractDataWrapper; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class NoAbi009 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress1 = ecKey2.getAddress(); - String contractExcKey1 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress1, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "clearabi contract with event") - public void testNoAbi001() { - String filePath = "src/test/resources/soliditycode/NoAbi001.sol"; - String contractName = "testNoABiContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String txid = PublicMethed - .clearContractAbi(contractAddress, contractExcAddress, contractExcKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - // getcontract - smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - System.out.println("smartContract:" + smartContract.toString()); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - - // getcontractinfo - SmartContractDataWrapper contractInfo = PublicMethed - .getContractInfo(contractAddress, blockingStubFull); - System.out.println("contractInfo.toString():" + contractInfo.toString()); - Assert.assertTrue(contractInfo.getSmartContract().getAbi().toString().isEmpty()); - Assert.assertTrue(contractInfo.getSmartContract().getName().equalsIgnoreCase(contractName)); - Assert.assertTrue(contractInfo.getRuntimecode().size() > 0); - Assert.assertFalse(contractInfo.getSmartContract().getBytecode().toString().isEmpty()); - - // triggerconstantcontract fullnode - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testTrigger()", "#", false, 0, - 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - logger.info("Code = " + transactionExtention.getResult().getCode()); - logger.info("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - Assert.assertThat(transactionExtention.getResult().getCode().toString(), - containsString("SUCCESS")); - Assert.assertEquals(3, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - // triggercontract - txid = PublicMethed - .triggerContract(contractAddress, "testTrigger()", "#", false, 0, maxFeeLimit, "0", 0, - contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Long returnNumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(3 == returnNumber); - List retList = PublicMethed - .getStrings(infoById.get().getLogList().get(0).getData().toByteArray()); - logger.info("retList:" + retList.toString()); - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(1)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - Assert.assertEquals(WalletClient.encode58Check(contractExcAddress),addressFinal); - Long actualNum = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - Assert.assertEquals(returnNumber,actualNum); - - // triggerconstantcontract solidity - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - transactionExtention = PublicMethed - .triggerConstantContractForExtentionOnSolidity(contractAddress, "testTrigger()", "#", - false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubSolidity); - logger.info("Code = " + transactionExtention.getResult().getCode()); - logger.info("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - Assert.assertThat(transactionExtention.getResult().getCode().toString(), - containsString("SUCCESS")); - Assert.assertEquals(4, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - } - - @Test(enabled = true, description = "create2 contract with event") - public void testNoAbi002() { - String filePath = "./src/test/resources/soliditycode/NoAbi002.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, contractExcKey1, - contractExcAddress1, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - byte[] factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - contractName = "testNoABiContract"; - retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String testNoABiContractCode = retMap.get("byteCode").toString(); - Long salt = 1L; - String param = "\"" + testNoABiContractCode + "\"," + salt; - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, Long.valueOf(0), - 1000000000L, "0", 0, contractExcAddress1, contractExcKey1, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - byte[] testNoABiContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - // getcontract - smartContract = PublicMethed.getContract(testNoABiContractAddress, blockingStubFull); - System.out.println("smartContract:" + smartContract.toString()); - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - // Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - - // getcontractinfo - SmartContractDataWrapper contractInfo = PublicMethed - .getContractInfo(testNoABiContractAddress, blockingStubFull); - System.out.println("contractInfo.toString():" + contractInfo.toString()); - Assert.assertTrue(contractInfo.getSmartContract().getAbi().toString().isEmpty()); - // Assert.assertTrue(contractInfo.getSmartContract().getName().equalsIgnoreCase(contractName)); - Assert.assertTrue(contractInfo.getRuntimecode().size() > 0); - Assert.assertFalse(contractInfo.getSmartContract().getBytecode().toString().isEmpty()); - - // triggerconstantcontract fullnode - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(testNoABiContractAddress, "plusOne()", "#", false, 0, - 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - logger.info("Code = " + transactionExtention.getResult().getCode()); - logger.info("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - Assert.assertThat(transactionExtention.getResult().getCode().toString(), - containsString("SUCCESS")); - Assert.assertEquals(1, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - // triggercontract - String txid = PublicMethed - .triggerContract(testNoABiContractAddress, "plusOne()", "#", false, 0, maxFeeLimit, "0", 0, - contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Long returnNumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnNumber); - retList = PublicMethed - .getStrings(infoById.get().getLogList().get(0).getData().toByteArray()); - logger.info("retList:" + retList.toString()); - tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(1)), 12, tmpAddress, 0, 20); - addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - Assert.assertEquals(WalletClient.encode58Check(contractExcAddress),addressFinal); - Long actualNum = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - Assert.assertEquals(returnNumber,actualNum); - - // triggerconstantcontract solidity - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - transactionExtention = PublicMethed - .triggerConstantContractForExtentionOnSolidity(testNoABiContractAddress, "plusOne()", "#", - false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubSolidity); - logger.info("Code = " + transactionExtention.getResult().getCode()); - logger.info("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - Assert.assertThat(transactionExtention.getResult().getCode().toString(), - containsString("SUCCESS")); - Assert.assertEquals(2, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - PublicMethed.freedResource(contractExcAddress1, contractExcKey1, testNetAccountAddress, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test001.java deleted file mode 100644 index 8e64dcde4e3..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test001.java +++ /dev/null @@ -1,558 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test001 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] factoryContractAddress = null; - private byte[] factoryContractAddress2 = null; - private byte[] testContractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "Deploy factory contract generated by new solidity") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 10000_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 10000_000_000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = true, description = "Trigger create2 command with test bytecode using factory. ") - public void test02TriggerCreate2ToDeployTestContract() { - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - - // different contract address with different bytecode, same salt and address - Assert.assertNotEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(testContractAddress)); - } - - @Test(enabled = true, description = "Trigger create2 command with factory bytecode") - public void test02TriggerCreate2ToDeployFactory2Contract() { - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - factoryContractAddress2 = WalletClient.decodeFromBase58Check(addressFinal); - - SmartContract smartContract = PublicMethed - .getContract(factoryContractAddress2, blockingStubFull); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - @Test(enabled = true, description = "Trigger create2 command with test bytecode using factory2") - public void test03TriggerCreate2ToDeployTestContract2() { - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress2, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - // Istanbul change create2 algorithm - Assert.assertEquals(0, infoById.get().getResultValue()); - } - - @Test(enabled = true, description = "Trigger create2 command without meta data hash in bytecode") - public void test04TriggerCreate2ToDeployTestContract() { - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String testContractCode = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801" - + "561002a57600080fd5b5060c9806100396000396000f3fe6080604052348015600f57600080fd5b50d38015" - + "601b57600080fd5b50d28015602757600080fd5b50600436106066577c01000000000000000000000000000" - + "00000000000000000000000000000600035046368e5c0668114606b578063e5aa3d58146083575b600080fd" - + "5b60716089565b60408051918252519081900360200190f35b60716097565b6000805460010190819055905" - + "65b6000548156fe"; - - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - - String msgSender = Base58.encode58Check(ByteArray.fromHexString(retList.get(2))); - Assert.assertNotEquals(msgSender, Base58.encode58Check(user001Address)); - } - - @Test(enabled = true, description = "Trigger create2 command with 0 extended bytecode") - public void test05TriggerCreate2ToDeployTestContract() { - Long callValue = Long.valueOf(0); - - String testContractCode = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801" - + "561002a57600080fd5b5060c9806100396000396000f3fe6080604052348015600f57600080fd5b50d38015" - + "601b57600080fd5b50d28015602757600080fd5b50600436106066577c01000000000000000000000000000" - + "00000000000000000000000000000600035046368e5c0668114606b578063e5aa3d58146083575b600080fd" - + "5b60716089565b60408051918252519081900360200190f35b60716097565b6000805460010190819055905" - + "65b6000548156fe0000000000000000000000000000000000000000000000000000000000000000000000"; - - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - - } - - @Test(enabled = true, description = "Trigger Test contact") - public void test04TriggerTestContract() { - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - final String triggerTxid = PublicMethed.triggerContract(testContractAddress, - "plusOne()", "#", false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - Long ret = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - - logger.info("ret: " + ret); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test002.java deleted file mode 100644 index e891e2847c3..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test002.java +++ /dev/null @@ -1,324 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test002 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] testContractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = false, description = "Deploy factory contract") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - //PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - - @Test(enabled = false, description = "Trigger create2 command without meta data hash in bytecode") - public void test02TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - Long callValue = Long.valueOf(0); - - String testContractCode = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801" - + "561002a57600080fd5b5060c9806100396000396000f3fe6080604052348015600f57600080fd5b50d38015" - + "601b57600080fd5b50d28015602757600080fd5b50600436106066577c01000000000000000000000000000" - + "00000000000000000000000000000600035046368e5c0668114606b578063e5aa3d58146083575b600080fd" - + "5b60716089565b60408051918252519081900360200190f35b60716097565b6000805460010190819055905" - + "65b6000548156fe"; - - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - - String msgSender = Base58.encode58Check(ByteArray.fromHexString(retList.get(2))); - Assert.assertNotEquals(msgSender, Base58.encode58Check(user001Address)); - } - - - @Test(enabled = false, description = "Trigger Test contract") - public void test03TriggerTestContract() { - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - final String triggerTxid = PublicMethed.triggerContract(testContractAddress, - "plusOne()", "#", false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - Long ret = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - - logger.info("ret: " + ret); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test003.java deleted file mode 100644 index f381432548c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test003.java +++ /dev/null @@ -1,489 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import static org.hamcrest.core.StringContains.containsString; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test003 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] testContractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "Deploy factory contract") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = true, description = "Trigger create2 command with invalid bytecode") - public void test02TriggerCreate2WithInvalidBytecode() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String testContractCode = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801" - + "561002a57600080fd5b5060c9806100396000396000f5fe6080604052348015600f57600080fd5b50d38015" - + "601b57600080fd5b50d28015602757600080fd5b50600436106066577c01000000000000000000000000000" - + "00000000000000000000000000000600035046368e5c0668114606b578063e5aa3d58146083575b600080fd" - + "5b60716089565b60408051918252519081900360200190f35b60716097565b6000805460010190819055905" - + "65b6000548156fea165627a7a72305820f3e3c0646a8c8d521fe819f10a592327469f611f0d9e8206697f7f" - + "3436ff3c7d0029"; - - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - Assert.assertEquals(1, infoById.get().getResultValue()); - Assert - .assertThat(infoById.get().getResMessage().toStringUtf8(), - containsString("REVERT opcode executed")); - } - - @Test(enabled = true, description = "Trigger create2 command with empty bytecode") - public void test03TriggerCreate2WithEmptyBytecode() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String testContractCode = ""; - - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - Assert.assertEquals(1, infoById.get().getResultValue()); - Assert - .assertThat(infoById.get().getResMessage().toStringUtf8(), - containsString("REVERT opcode executed")); - } - - @Test(enabled = true, description = "Trigger create2 command with \"6080\" bytecode") - public void test04TriggerCreate2WithShortBytecode() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String testContractCode = "6080"; - - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - Assert.assertEquals(1, infoById.get().getResultValue()); - Assert - .assertThat(infoById.get().getResMessage().toStringUtf8(), - containsString("REVERT opcode executed")); - } - - @Test(enabled = true, description = "Trigger create2 command with \"00000000000\" bytecode") - public void test05TriggerCreate2WithZeroBytecode() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String testContractCode = "000000000000000000000000000000"; - - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - Assert.assertEquals(1, infoById.get().getResultValue()); - Assert - .assertThat(infoById.get().getResMessage().toStringUtf8(), - containsString("REVERT opcode executed")); - } - - @Test(enabled = true, description = "Trigger create2 command with NULL bytecode") - public void test06TriggerCreate2WithNullBytecode() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String testContractCode = null; - - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - boolean ret = false; - - try { - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - } catch (org.bouncycastle.util.encoders.DecoderException e) { - logger.info("Expected org.bouncycastle.util.encoders.DecoderException!"); - ret = true; - } - Assert.assertTrue(ret); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test004.java deleted file mode 100644 index 40b6e6bf769..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test004.java +++ /dev/null @@ -1,470 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import static org.hamcrest.core.StringContains.containsString; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test004 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] factoryContractAddress2 = null; - private byte[] testContractAddress = null; - private byte[] testContractAddress2 = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = false, description = "Deploy factory contract") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - /*AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore));*/ - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - /*accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter));*/ - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = false, description = "Trigger create2 command with factory bytecode") - public void test02TriggerCreate2ToDeployFactory2Contract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 150000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - /*AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore));*/ - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - /*accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter));*/ - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - factoryContractAddress2 = WalletClient.decodeFromBase58Check(addressFinal); - - SmartContract smartContract = PublicMethed - .getContract(factoryContractAddress2, blockingStubFull); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - - @Test(enabled = false, description = "Trigger create2 command with test bytecode using factory") - public void test03TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 80000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - /*AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore));*/ - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - /*accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter));*/ - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - - // different contract address with different bytecode, same salt and address - Assert.assertNotEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(testContractAddress)); - } - - @Test(enabled = false, description = "Trigger create2 command with test bytecode using factory2") - public void test04TriggerCreate2ToDeployTestContract2() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 80000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - /*AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore));*/ - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress2, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - /*accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter));*/ - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - Assert.assertEquals(1, infoById.get().getResultValue()); - Assert - .assertThat(infoById.get().getResMessage().toStringUtf8(), - containsString("Not enough energy for 'SWAP1' operation executing")); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test005.java deleted file mode 100644 index cfc817ce2f3..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test005.java +++ /dev/null @@ -1,358 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test005 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] testContractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = false, description = "Deploy factory contract") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - - @Test(enabled = false, description = "Trigger create2 command with 0 extended bytecode") - public void test02TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String testContractCode = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801" - + "561002a57600080fd5b5060c9806100396000396000f3fe6080604052348015600f57600080fd5b50d38015" - + "601b57600080fd5b50d28015602757600080fd5b50600436106066577c01000000000000000000000000000" - + "00000000000000000000000000000600035046368e5c0668114606b578063e5aa3d58146083575b600080fd" - + "5b60716089565b60408051918252519081900360200190f35b60716097565b6000805460010190819055905" - + "65b6000548156fe0000000000000000000000000000000000000000000000000000000000000000000000"; - - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - @Test(enabled = false, description = "Trigger test contract") - public void test03TriggerTestContract() { - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - final String triggerTxid = PublicMethed.triggerContract(testContractAddress, - "plusOne()", "#", false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - Long ret = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - - logger.info("ret: " + ret); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test006.java deleted file mode 100644 index 20d316e34ac..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test006.java +++ /dev/null @@ -1,1014 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test006 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] testContractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "Deploy factory contract") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = true, description = "Trigger create2 with salt empty") - public void test02TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - String param = "\"" + testContractCode + "\"," + null; - boolean ret = false; - try { - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - } catch (NullPointerException e) { - logger.info("Expected NullPointerException!"); - ret = true; - } - Assert.assertTrue(ret); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - @Test(enabled = true, description = "Trigger create2 with salt 0") - public void test03TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - Long salt = 0L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - Assert.assertEquals(salt, actualSalt); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - @Test(enabled = true, description = "Trigger create2 with salt -1") - public void test04TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - Long salt = -1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - Assert.assertEquals(salt, actualSalt); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - @Test(enabled = true, description = "Trigger create2 with salt 100") - public void test05TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - Long salt = 100L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - Assert.assertEquals(salt, actualSalt); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - // Istanbul change create2 algorithm - @Test(enabled = false, description = "Trigger create2 with salt f * 64") - public void test06TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - String saltHexString = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; - logger.info("saltHexString: " + saltHexString); - - String param = "\"" + testContractCode + "\",\"" + saltHexString + "\""; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,bytes32)", param, false, callValue, - 1000000000L, "0", 0, dev001Address, dev001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - // The first - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("addressHex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("addressFinal: " + addressFinal); - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - String actualSalt = retList.get(1); - logger.info("actualSalt: " + actualSalt); - - byte[] tmpSenderAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(2)), 12, tmpSenderAddress, 0, 20); - String senderAddressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("senderAddressHex: " + senderAddressHex); - String senderAddressFinal = Base58.encode58Check(ByteArray.fromHexString(senderAddressHex)); - logger.info("senderAddressFinal: " + senderAddressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - Assert.assertEquals(saltHexString, actualSalt); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - @Test(enabled = true, description = "Trigger create2 with salt efffe") - public void test07TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - final String saltHexString = "EFFFE"; - final String expectedSalt = "0EFFFE0000000000000000000000000000000000000000000000000000000000"; - - logger.info("saltHexString: " + saltHexString); - - String param = "\"" + testContractCode + "\",\"" + saltHexString + "\""; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,bytes32)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - // The first - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("addressHex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("addressFinal: " + addressFinal); - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - String actualSalt = retList.get(1); - logger.info("actualSalt: " + actualSalt); - - byte[] tmpSenderAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(2)), 12, tmpSenderAddress, 0, 20); - String senderAddressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("senderAddressHex: " + senderAddressHex); - String senderAddressFinal = Base58.encode58Check(ByteArray.fromHexString(senderAddressHex)); - logger.info("senderAddressFinal: " + senderAddressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - Assert.assertEquals(expectedSalt, actualSalt); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - @Test(enabled = true, description = "Trigger create2 with salt affffa") - public void test08TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - final String saltHexString = "AFFFFA"; - final String expectedSalt = "AFFFFA0000000000000000000000000000000000000000000000000000000000"; - logger.info("saltHexString: " + saltHexString); - - String param = "\"" + testContractCode + "\",\"" + saltHexString + "\""; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,bytes32)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - // The first - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("addressHex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("addressFinal: " + addressFinal); - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - String actualSalt = retList.get(1); - logger.info("actualSalt: " + actualSalt); - - byte[] tmpSenderAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(2)), 12, tmpSenderAddress, 0, 20); - String senderAddressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("senderAddressHex: " + senderAddressHex); - String senderAddressFinal = Base58.encode58Check(ByteArray.fromHexString(senderAddressHex)); - logger.info("senderAddressFinal: " + senderAddressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - Assert.assertEquals(expectedSalt, actualSalt); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - @Test(enabled = true, description = "Trigger test contract") - public void test09TriggerTestContract() { - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - final String triggerTxid = PublicMethed.triggerContract(testContractAddress, - "plusOne()", "#", false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - Long ret = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - - logger.info("ret: " + ret); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test007.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test007.java deleted file mode 100644 index 1f25e90dc13..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test007.java +++ /dev/null @@ -1,358 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test007 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] testContractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = false, description = "Deploy factory contract") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = false, description = "Trigger create2 with salt -1") - public void test02TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - Long salt = -1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - Assert.assertEquals(salt, actualSalt); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - @Test(enabled = false, description = "Trigger test contract") - public void test03TriggerTestContract() { - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - final String triggerTxid = PublicMethed.triggerContract(testContractAddress, - "plusOne()", "#", false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - Long ret = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - - logger.info("ret: " + ret); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test008.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test008.java deleted file mode 100644 index ed382c537e8..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test008.java +++ /dev/null @@ -1,358 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test008 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] testContractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = false, description = "Deploy factory contract") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = false, description = "Trigger create2 with salt 100") - public void test02TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - Long salt = 100L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - Assert.assertEquals(salt, actualSalt); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - @Test(enabled = false, description = "Trigger test contract") - public void test03TriggerTestContract() { - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - final String triggerTxid = PublicMethed.triggerContract(testContractAddress, - "plusOne()", "#", false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - Long ret = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - - logger.info("ret: " + ret); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test009.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test009.java deleted file mode 100644 index 2d041d41ff2..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test009.java +++ /dev/null @@ -1,365 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test009 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] testContractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = false, description = "Deploy factory contract generated by new solidity") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - - @Test(enabled = false, description = "Trigger create2 function to deploy test contract") - public void test02TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - - String[] parameter = {Base58.encode58Check(user001Address), testContractCode, salt.toString()}; - logger.info(PublicMethed.create2(parameter)); - - Assert.assertEquals(Base58.encode58Check(testContractAddress), PublicMethed.create2(parameter)); - - } - - - @Test(enabled = false, description = "Trigger Test contact") - public void test03TriggerTestContract() { - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - final String triggerTxid = PublicMethed.triggerContract(testContractAddress, - "plusOne()", "#", false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - Long ret = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - - logger.info("ret: " + ret); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test010.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test010.java deleted file mode 100644 index a5df4271070..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test010.java +++ /dev/null @@ -1,210 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test010 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] testContractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = false, description = "TransferToken with correct value, deploy transfer contract") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - - @Test(enabled = false, description = "Trigger create2 with salt empty") - public void test02TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - String param = "\"" + testContractCode + "\"," + null; - boolean ret = false; - try { - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - } catch (NullPointerException e) { - logger.info("Expected NullPointerException!"); - ret = true; - } - Assert.assertTrue(ret); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test011.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test011.java deleted file mode 100644 index 3d8aa9a3cb6..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test011.java +++ /dev/null @@ -1,369 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test011 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] testContractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = false, description = "Deploy factory contract") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "FactoryBytes"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - - @Test(enabled = false, description = "Trigger create2 with salt f * 64") - public void test02TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - String saltHexString = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; - logger.info("saltHexString: " + saltHexString); - - String param = "\"" + testContractCode + "\",\"" + saltHexString + "\""; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,bytes32)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - // The first - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("addressHex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("addressFinal: " + addressFinal); - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - String actualSalt = retList.get(1); - logger.info("actualSalt: " + actualSalt); - - byte[] tmpSenderAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(2)), 12, tmpSenderAddress, 0, 20); - String senderAddressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("senderAddressHex: " + senderAddressHex); - String senderAddressFinal = Base58.encode58Check(ByteArray.fromHexString(senderAddressHex)); - logger.info("senderAddressFinal: " + senderAddressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - Assert.assertEquals(saltHexString, actualSalt); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - - @Test(enabled = false, description = "Trigger test contract") - public void test03TriggerTestContract() { - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - final String triggerTxid = PublicMethed.triggerContract(testContractAddress, - "plusOne()", "#", false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - Long ret = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - - logger.info("ret: " + ret); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test012.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test012.java deleted file mode 100644 index c77da670bd3..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test012.java +++ /dev/null @@ -1,396 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test012 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] testContractAddress = null; - private byte[] testContractAddress2 = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = false, description = "Deploy factory contract") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - - @Test(enabled = false, description = "Trigger create2 command with test bytecode and salt 1") - public void test02TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 80000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - Assert.assertEquals(salt, actualSalt); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - - @Test(enabled = false, description = "Trigger create2 command with test bytecode and salt 2") - public void test03TriggerCreate2ToDeployTestContract2() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 80000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - Long salt = 2L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress2 = WalletClient.decodeFromBase58Check(addressFinal); - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - Assert.assertEquals(salt, actualSalt); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - - // contract address are different with different salt - Assert.assertNotEquals(Base58.encode58Check(testContractAddress), - Base58.encode58Check(testContractAddress2)); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test013.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test013.java deleted file mode 100644 index 9e4b13a896e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test013.java +++ /dev/null @@ -1,436 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import static org.hamcrest.core.StringContains.containsString; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test013 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] testContractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = false, description = "Deploy factory contract") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = false, description = "Trigger factory contract to deploy test contract") - public void test02TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - @Test(enabled = false, description = "Trigger factory contract to deploy test contract again " - + "with same code, salt and address") - public void test03TriggerCreate2ToDeployTestContractAgain() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - Assert.assertEquals(1, infoById.get().getResultValue()); - Assert - .assertThat(infoById.get().getResMessage().toStringUtf8(), - containsString("Not enough energy for 'SWAP1' operation executing")); - } - - @Test(enabled = false, description = "Trigger test1 contract") - public void test04TriggerTestContract() { - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - final String triggerTxid = PublicMethed.triggerContract(testContractAddress, - "plusOne()", "#", false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - Long ret = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - - logger.info("ret: " + ret); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test014.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test014.java deleted file mode 100644 index d276eab67ab..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test014.java +++ /dev/null @@ -1,641 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import static org.hamcrest.core.StringContains.containsString; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test014 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] testContractAddress = null; - private byte[] testContractAddress2 = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "Deploy factory contract") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - - @Test(enabled = true, description = "Trigger factory contract with Test " - + "bytecode and salt using user account") - public void test02TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - @Test(enabled = true, description = "Trigger factory contract to deploy test contract again " - + "with same code, salt and address") - public void test02TriggerCreate2ToDeployTestContractAgain() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - Assert.assertEquals(1, infoById.get().getResultValue()); - Assert - .assertThat(infoById.get().getResMessage().toStringUtf8(), - containsString("REVERT opcode executed")); - } - - // Istanbul change create2 algorithm - @Test(enabled = false, description = "Same code, salt and address," - + " create contract using develop account") - public void test03TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, dev001Address, dev001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress2 = WalletClient.decodeFromBase58Check(addressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress2, blockingStubFull); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - - // contract address are different - Assert.assertNotEquals(Base58.encode58Check(testContractAddress), - Base58.encode58Check(testContractAddress2)); - } - - @Test(enabled = true, description = "Trigger test1 contract") - public void test04TriggerTest1Contract() { - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - final String triggerTxid = PublicMethed.triggerContract(testContractAddress, - "plusOne()", "#", false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - Long ret = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - - logger.info("ret: " + ret); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - } - - // Istanbul change create2 algorithm - @Test(enabled = false, description = "Trigger test2 contract") - public void test05TriggerTest2Contract() { - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - final String triggerTxid = PublicMethed.triggerContract(testContractAddress2, - "plusOne()", "#", false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - Long ret = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - - logger.info("ret: " + ret); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test015.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test015.java deleted file mode 100644 index 890704c3d93..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test015.java +++ /dev/null @@ -1,499 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test015 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] callerContractAddress = null; - private byte[] callContractAddress = null; - private byte[] delegateCallContractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "Deploy caller contract") - public void test01DeployCallerContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2CallContract.sol"; - String contractName = "callerContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - callerContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(callerContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = true, description = "Deploy factory contract") - public void test02DeployFactoryContract() { - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = true, description = "Trigger callCreate2 function in caller contract " - + "with factory contract address") - public void test03TriggerCreate2ToDeployTestContract() { - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - Long salt = 1L; - - String param = "\"" + Base58.encode58Check(factoryContractAddress) - + "\",\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(callerContractAddress, - "callCreate2(address,bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), - 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - callContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(callContractAddress, blockingStubFull); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // call type make the caller contract to be the owner of - // test contract (the contract address in transaction info) - Assert.assertEquals(Base58.encode58Check(callerContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - @Test(enabled = true, description = "Trigger delegateCallCreate2 function in caller contract " - + "with factory contract address") - public void test04TriggerCreate2ToDeployTestContract() { - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - Long salt = 1L; - - String param = "\"" + Base58.encode58Check(factoryContractAddress) - + "\",\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(callerContractAddress, - "delegateCallCreate2(address,bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - delegateCallContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed - .getContract(delegateCallContractAddress, blockingStubFull); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // delegatecall type make the caller contract to be the owner of test contract (contract info) - Assert.assertEquals(Base58.encode58Check(callerContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // call type make the caller contract to be the owner of test contract - // (the contract address in transaction info) - Assert.assertEquals(Base58.encode58Check(callerContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - @Test(enabled = true, description = "Trigger test contract") - public void test09TriggerTestContract() { - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - final String triggerTxid = PublicMethed.triggerContract(callContractAddress, - "plusOne()", "#", false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - Long ret = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - - logger.info("ret: " + ret); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test016.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test016.java deleted file mode 100644 index 2934a55d909..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test016.java +++ /dev/null @@ -1,422 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test016 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] callerContractAddress = null; - private byte[] testContractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = false, description = "Deploy caller contract") - public void test01DeployCallerContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2CallContract.sol"; - String contractName = "callerContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - callerContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(callerContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = false, description = "Deploy factory contract") - public void test02DeployFactoryContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = false, description = "Trigger delegateCallCreate2 function in caller contract " - + "with factory contract address") - public void test03TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - Long salt = 1L; - - String param = "\"" + Base58.encode58Check(factoryContractAddress) - + "\",\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(callerContractAddress, - "delegateCallCreate2(address,bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // delegatecall type make the caller contract to be the owner of test contract (contract info) - Assert.assertEquals(Base58.encode58Check(callerContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // call type make the caller contract to be the owner of test contract - // (the contract address in transaction info) - Assert.assertEquals(Base58.encode58Check(callerContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - @Test(enabled = false, description = "Trigger test contract") - public void test04TriggerTestContract() { - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - final String triggerTxid = PublicMethed.triggerContract(testContractAddress, - "plusOne()", "#", false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - Long ret = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - - logger.info("ret: " + ret); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test017.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test017.java deleted file mode 100644 index 337ec84b1a6..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test017.java +++ /dev/null @@ -1,405 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test017 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] testContractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = false, description = "Deploy factory contract") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "FactoryBytes"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = false, description = "Trigger create2 with salt efffe") - public void test02TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - final String saltHexString = "EFFFE"; - final String expectedSalt = "0EFFFE0000000000000000000000000000000000000000000000000000000000"; - - logger.info("saltHexString: " + saltHexString); - - String param = "\"" + testContractCode + "\",\"" + saltHexString + "\""; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,bytes32)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - // The first - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("addressHex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("addressFinal: " + addressFinal); - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - String actualSalt = retList.get(1); - logger.info("actualSalt: " + actualSalt); - - byte[] tmpSenderAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(2)), 12, tmpSenderAddress, 0, 20); - String senderAddressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("senderAddressHex: " + senderAddressHex); - String senderAddressFinal = Base58.encode58Check(ByteArray.fromHexString(senderAddressHex)); - logger.info("senderAddressFinal: " + senderAddressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - Assert.assertEquals(expectedSalt, actualSalt); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - @Test(enabled = false, description = "Trigger create2 with salt affffa") - public void test03TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - - final String saltHexString = "AFFFFA"; - final String expectedSalt = "AFFFFA0000000000000000000000000000000000000000000000000000000000"; - logger.info("saltHexString: " + saltHexString); - - String param = "\"" + testContractCode + "\",\"" + saltHexString + "\""; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,bytes32)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - // The first - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("addressHex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("addressFinal: " + addressFinal); - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - String actualSalt = retList.get(1); - logger.info("actualSalt: " + actualSalt); - - byte[] tmpSenderAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(2)), 12, tmpSenderAddress, 0, 20); - String senderAddressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("senderAddressHex: " + senderAddressHex); - String senderAddressFinal = Base58.encode58Check(ByteArray.fromHexString(senderAddressHex)); - logger.info("senderAddressFinal: " + senderAddressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - Assert.assertEquals(expectedSalt, actualSalt); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test018.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test018.java deleted file mode 100644 index 33608b3ad85..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test018.java +++ /dev/null @@ -1,358 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test018 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] testContractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key2"); - private byte[] witnessAddress001 = PublicMethed.getFinalAddress(witnessKey001); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(witnessKey001); - } - - @Test(enabled = false, description = "Deploy factory contract generated by new solidity") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(witnessAddress001, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - - @Test(enabled = false, description = "Trigger create2 function to deploy test contract " - + "using Witness account") - public void test02TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 9000_000_000_000L, 0, 1, - ByteString.copyFrom(witnessAddress001), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(witnessAddress001, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(witnessAddress001, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - Long salt = new Random().nextLong(); - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, witnessAddress001, witnessKey001, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(witnessAddress001, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(witnessAddress001, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - - @Test(enabled = false, description = "Trigger Test contact") - public void test03TriggerTestContract() { - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(witnessAddress001, witnessKey001, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(witnessAddress001), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(witnessAddress001, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(witnessAddress001, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - final String triggerTxid = PublicMethed.triggerContract(testContractAddress, - "plusOne()", "#", false, callValue, - 1000000000L, "0", 0, witnessAddress001, witnessKey001, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(witnessAddress001, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(witnessAddress001, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - Long ret = ByteArray.toLong(ByteArray.fromHexString(retList.get(0))); - - logger.info("ret: " + ret); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); - } - - SmartContract smartContract = PublicMethed.getContract(infoById.get().getContractAddress() - .toByteArray(), blockingStubFull); - - long consumeUserPercent = smartContract.getConsumeUserResourcePercent(); - logger.info("ConsumeURPercent: " + consumeUserPercent); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - witnessAddress001, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - witnessAddress001, blockingStubFull); - - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test019.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test019.java deleted file mode 100644 index bd77817c636..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test019.java +++ /dev/null @@ -1,297 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import static org.hamcrest.core.StringContains.containsString; -import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS_VALUE; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test019 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "seted Value of Contract that created by create2," - + " should not be stored after contact suicided ande create2 again") - public void testTriggerContract() { - String sendcoin = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, testNetAccountAddress, - testNetAccountKey, - blockingStubFull); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById0 = null; - infoById0 = PublicMethed.getTransactionInfoById(sendcoin, blockingStubFull); - logger.info("infoById0 " + infoById0.get()); - Assert.assertEquals(ByteArray.toHexString(infoById0.get().getContractResult(0).toByteArray()), - ""); - Assert.assertEquals(infoById0.get().getResult().getNumber(), 0); - Optional ById = PublicMethed.getTransactionById(sendcoin, blockingStubFull); - Assert.assertEquals(ById.get().getRet(0).getContractRet().getNumber(), - SUCCESS_VALUE); - Assert.assertEquals(ById.get().getRet(0).getContractRetValue(), SUCCESS_VALUE); - Assert.assertEquals(ById.get().getRet(0).getContractRet(), contractResult.SUCCESS); - String filePath = "src/test/resources/soliditycode/create2contractn2.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String contractName1 = "TestConstract"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - String txid = ""; - String num = "\"" + code1 + "\"" + "," + 1; - txid = PublicMethed - .triggerContract(contractAddress, - "deploy(bytes,uint256)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - byte[] returnAddressBytes = infoById.get().getInternalTransactions(0).getTransferToAddress() - .toByteArray(); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - txid = PublicMethed - .triggerContract(returnAddressBytes, - "i()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee1 = infoById1.get().getFee(); - Long netUsed1 = infoById1.get().getReceipt().getNetUsage(); - Long energyUsed1 = infoById1.get().getReceipt().getEnergyUsage(); - Long netFee1 = infoById1.get().getReceipt().getNetFee(); - long energyUsageTotal1 = infoById1.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee1:" + fee1); - logger.info("netUsed1:" + netUsed1); - logger.info("energyUsed1:" + energyUsed1); - logger.info("netFee1:" + netFee1); - logger.info("energyUsageTotal1:" + energyUsageTotal1); - - Account infoafter1 = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter1 = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance1); - logger.info("afterEnergyUsed:" + afterEnergyUsed1); - logger.info("afterNetUsed:" + afterNetUsed1); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed1); - - Assert.assertTrue(infoById1.get().getResultValue() == 0); - Assert.assertTrue(afterBalance1 + fee1 == afterBalance); - Assert.assertTrue(afterEnergyUsed + energyUsed1 >= afterEnergyUsed1); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - txid = PublicMethed - .triggerContract(returnAddressBytes, - "set()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - txid = PublicMethed - .triggerContract(returnAddressBytes, - "i()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById1 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(5 == returnnumber); - - String param1 = "\"" + Base58.encode58Check(returnAddressBytes) + "\""; - - txid = PublicMethed - .triggerContract(returnAddressBytes, - "testSuicideNonexistentTarget(address)", param1, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById2 = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - - Assert.assertEquals("suicide", ByteArray - .toStr(infoById2.get().getInternalTransactions(0).getNote().toByteArray())); - TransactionExtention transactionExtention = PublicMethed - .triggerContractForExtention(returnAddressBytes, - "i()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert - .assertThat(transactionExtention.getResult().getCode().toString(), - containsString("CONTRACT_VALIDATE_ERROR")); - Assert - .assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Contract validate error : No contract or not a valid smart contract")); - - txid = PublicMethed - .triggerContract(contractAddress, - "deploy(bytes,uint256)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById3 = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - byte[] returnAddressBytes1 = infoById3.get().getInternalTransactions(0).getTransferToAddress() - .toByteArray(); - String returnAddress1 = Base58.encode58Check(returnAddressBytes1); - Assert.assertEquals(returnAddress1, returnAddress); - txid = PublicMethed - .triggerContract(returnAddressBytes1, - "i()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById1 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test020.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test020.java deleted file mode 100644 index 9ec6ad9f1d9..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test020.java +++ /dev/null @@ -1,896 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test020 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Deploy Factory contract, create2 with salt type : trcToken") - public void testTriggerContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 500000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/create2contract22.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String contractName1 = "TestConstract"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - String txid = ""; - String num = "\"" + code1 + "\"" + "," + 1000001; - txid = PublicMethed - .triggerContract(contractAddress, - "deploy(bytes,trcToken)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - byte[] returnAddressBytes = infoById.get().getInternalTransactions(0).getTransferToAddress() - .toByteArray(); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - txid = PublicMethed - .triggerContract(returnAddressBytes, - "i()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee1 = infoById1.get().getFee(); - Long netUsed1 = infoById1.get().getReceipt().getNetUsage(); - Long energyUsed1 = infoById1.get().getReceipt().getEnergyUsage(); - Long netFee1 = infoById1.get().getReceipt().getNetFee(); - long energyUsageTotal1 = infoById1.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee1:" + fee1); - logger.info("netUsed1:" + netUsed1); - logger.info("energyUsed1:" + energyUsed1); - logger.info("netFee1:" + netFee1); - logger.info("energyUsageTotal1:" + energyUsageTotal1); - - Account infoafter1 = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter1 = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance1); - logger.info("afterEnergyUsed:" + afterEnergyUsed1); - logger.info("afterNetUsed:" + afterNetUsed1); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed1); - - Assert.assertTrue(infoById1.get().getResultValue() == 0); - Assert.assertTrue(afterBalance1 + fee1 == afterBalance); - Assert.assertTrue(afterEnergyUsed + energyUsed1 >= afterEnergyUsed1); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - - } - - - @Test(enabled = true, description = "Deploy Factory contract, create2 with salt type : uint8") - public void testTriggerContract1() { - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String contractName1 = "TestConstract"; - String filePath = "src/test/resources/soliditycode/create2contract22.sol"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - String txid = ""; - String num = "\"" + code1 + "\"" + "," + 1000031; - txid = PublicMethed - .triggerContract(contractAddress, - "deploy1(bytes,uint256)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - byte[] returnAddressBytes = infoById.get().getInternalTransactions(0).getTransferToAddress() - .toByteArray(); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - txid = PublicMethed - .triggerContract(returnAddressBytes, - "i()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee1 = infoById1.get().getFee(); - Long netUsed1 = infoById1.get().getReceipt().getNetUsage(); - Long energyUsed1 = infoById1.get().getReceipt().getEnergyUsage(); - Long netFee1 = infoById1.get().getReceipt().getNetFee(); - long energyUsageTotal1 = infoById1.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee1:" + fee1); - logger.info("netUsed1:" + netUsed1); - logger.info("energyUsed1:" + energyUsed1); - logger.info("netFee1:" + netFee1); - logger.info("energyUsageTotal1:" + energyUsageTotal1); - - Account infoafter1 = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter1 = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance1); - logger.info("afterEnergyUsed:" + afterEnergyUsed1); - logger.info("afterNetUsed:" + afterNetUsed1); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed1); - - Assert.assertTrue(infoById1.get().getResultValue() == 0); - Assert.assertTrue(afterBalance1 + fee1 == afterBalance); - Assert.assertTrue(afterEnergyUsed + energyUsed1 >= afterEnergyUsed1); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - - - } - - - @Test(enabled = true, description = "Deploy Factory contract, create2 with salt type : address") - public void testTriggerContract2() { - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String contractName1 = "TestConstract"; - String filePath = "src/test/resources/soliditycode/create2contract22.sol"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - String txid = ""; - String num = "\"" + code1 + "\"" + ",\"" + Base58.encode58Check(contractExcAddress) + "\""; - txid = PublicMethed - .triggerContract(contractAddress, - "deploy2(bytes,address)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - byte[] returnAddressBytes = infoById.get().getInternalTransactions(0).getTransferToAddress() - .toByteArray(); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - txid = PublicMethed - .triggerContract(returnAddressBytes, - "i()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee1 = infoById1.get().getFee(); - Long netUsed1 = infoById1.get().getReceipt().getNetUsage(); - Long energyUsed1 = infoById1.get().getReceipt().getEnergyUsage(); - Long netFee1 = infoById1.get().getReceipt().getNetFee(); - long energyUsageTotal1 = infoById1.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee1:" + fee1); - logger.info("netUsed1:" + netUsed1); - logger.info("energyUsed1:" + energyUsed1); - logger.info("netFee1:" + netFee1); - logger.info("energyUsageTotal1:" + energyUsageTotal1); - - Account infoafter1 = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter1 = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance1); - logger.info("afterEnergyUsed:" + afterEnergyUsed1); - logger.info("afterNetUsed:" + afterNetUsed1); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed1); - - Assert.assertTrue(infoById1.get().getResultValue() == 0); - Assert.assertTrue(afterBalance1 + fee1 == afterBalance); - Assert.assertTrue(afterEnergyUsed + energyUsed1 >= afterEnergyUsed1); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - - - } - - - @Test(enabled = true, description = "Deploy Factory contract, create2 with salt type : string") - public void testTriggerContract3() { - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String contractName1 = "TestConstract"; - String filePath = "src/test/resources/soliditycode/create2contract22.sol"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - String txid = ""; - String num = "\"" + code1 + "\"" + ",\"" + Base58.encode58Check(contractExcAddress) + "\""; - txid = PublicMethed - .triggerContract(contractAddress, - "deploy3(bytes,string)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - byte[] returnAddressBytes = infoById.get().getInternalTransactions(0).getTransferToAddress() - .toByteArray(); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - txid = PublicMethed - .triggerContract(returnAddressBytes, - "i()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee1 = infoById1.get().getFee(); - Long netUsed1 = infoById1.get().getReceipt().getNetUsage(); - Long energyUsed1 = infoById1.get().getReceipt().getEnergyUsage(); - Long netFee1 = infoById1.get().getReceipt().getNetFee(); - long energyUsageTotal1 = infoById1.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee1:" + fee1); - logger.info("netUsed1:" + netUsed1); - logger.info("energyUsed1:" + energyUsed1); - logger.info("netFee1:" + netFee1); - logger.info("energyUsageTotal1:" + energyUsageTotal1); - - Account infoafter1 = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter1 = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance1); - logger.info("afterEnergyUsed:" + afterEnergyUsed1); - logger.info("afterNetUsed:" + afterNetUsed1); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed1); - - Assert.assertTrue(infoById1.get().getResultValue() == 0); - Assert.assertTrue(afterBalance1 + fee1 == afterBalance); - Assert.assertTrue(afterEnergyUsed + energyUsed1 >= afterEnergyUsed1); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - - - } - - - @Test(enabled = true, description = "TriggerContract a constant function created by create2" - + "can not create2 twice if salt type is string") - public void testTriggerContract4() { - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String contractName1 = "TestConstract1"; - String filePath = "src/test/resources/soliditycode/create2contract22.sol"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - String txid = ""; - String num = "\"" + code1 + "\"" + ",\"" + Base58.encode58Check(contractAddress) + "\""; - txid = PublicMethed - .triggerContract(contractAddress, - "deploy3(bytes,string)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - byte[] returnAddressBytes = infoById.get().getInternalTransactions(0).getTransferToAddress() - .toByteArray(); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - txid = PublicMethed - .triggerContract(returnAddressBytes, - "i()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee1 = infoById1.get().getFee(); - Long netUsed1 = infoById1.get().getReceipt().getNetUsage(); - Long energyUsed1 = infoById1.get().getReceipt().getEnergyUsage(); - Long netFee1 = infoById1.get().getReceipt().getNetFee(); - long energyUsageTotal1 = infoById1.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee1:" + fee1); - logger.info("netUsed1:" + netUsed1); - logger.info("energyUsed1:" + energyUsed1); - logger.info("netFee1:" + netFee1); - logger.info("energyUsageTotal1:" + energyUsageTotal1); - - Account infoafter1 = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter1 = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance1); - logger.info("afterEnergyUsed:" + afterEnergyUsed1); - logger.info("afterNetUsed:" + afterNetUsed1); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed1); - - Assert.assertTrue(infoById1.get().getResultValue() == 0); - Assert.assertTrue(afterBalance1 + fee1 == afterBalance); - Assert.assertTrue(afterEnergyUsed + energyUsed1 >= afterEnergyUsed1); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(2 == returnnumber); - - txid = PublicMethed - .triggerContract(contractAddress, - "deploy3(bytes,string)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById2 = null; - infoById2 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - Assert.assertTrue(infoById2.get().getResultValue() != 0); - Assert - .assertThat(ByteArray - .toStr(infoById2.get().getResMessage().toByteArray()), - containsString("REVERT opcode executed")); - } - - - @Test(enabled = true, description = "TriggerContract a constant function created by create2" - + "can not create2 twice if salt type is string") - public void testTriggerContract5() { - - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String contractName1 = "TestConstract2"; - String filePath = "src/test/resources/soliditycode/create2contract22.sol"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - String txid = ""; - String num = "\"" + code1 + "\"" + ",\"" + Base58.encode58Check(contractAddress) + "\""; - txid = PublicMethed - .triggerContract(contractAddress, - "deploy3(bytes,string)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - byte[] returnAddressBytes = infoById.get().getInternalTransactions(0).getTransferToAddress() - .toByteArray(); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - txid = PublicMethed - .triggerContract(returnAddressBytes, - "i()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee1 = infoById1.get().getFee(); - Long netUsed1 = infoById1.get().getReceipt().getNetUsage(); - Long energyUsed1 = infoById1.get().getReceipt().getEnergyUsage(); - Long netFee1 = infoById1.get().getReceipt().getNetFee(); - long energyUsageTotal1 = infoById1.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee1:" + fee1); - logger.info("netUsed1:" + netUsed1); - logger.info("energyUsed1:" + energyUsed1); - logger.info("netFee1:" + netFee1); - logger.info("energyUsageTotal1:" + energyUsageTotal1); - - Account infoafter1 = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter1 = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance1); - logger.info("afterEnergyUsed:" + afterEnergyUsed1); - logger.info("afterNetUsed:" + afterNetUsed1); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed1); - - Assert.assertTrue(infoById1.get().getResultValue() == 0); - Assert.assertTrue(afterBalance1 + fee1 == afterBalance); - Assert.assertTrue(afterEnergyUsed + energyUsed1 >= afterEnergyUsed1); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(3 == returnnumber); - num = "\"" + code1 + "\"" + ",\"" + Base58.encode58Check(testNetAccountAddress) + "\""; - - txid = PublicMethed - .triggerContract(contractAddress, - "deploy3(bytes,string)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById2 = null; - infoById2 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - Assert.assertTrue(infoById2.get().getResultValue() != 0); - Assert - .assertThat(ByteArray - .toStr(infoById2.get().getResMessage().toByteArray()), - containsString("REVERT opcode executed")); - } - - - @Test(enabled = true, description = "TriggerContract a constant function created by create2" - + "can not create2 twice if salt type is string") - public void testTriggerContract6() { - - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String contractName1 = "TestConstract3"; - String filePath = "src/test/resources/soliditycode/create2contract22.sol"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - String txid = ""; - String num = "\"" + code1 + "\"" + ",\"" + Base58.encode58Check(contractAddress) + "\""; - txid = PublicMethed - .triggerContract(contractAddress, - "deploy3(bytes,string)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - byte[] returnAddressBytes = infoById.get().getInternalTransactions(0).getTransferToAddress() - .toByteArray(); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - txid = PublicMethed - .triggerContract(returnAddressBytes, - "i()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee1 = infoById1.get().getFee(); - Long netUsed1 = infoById1.get().getReceipt().getNetUsage(); - Long energyUsed1 = infoById1.get().getReceipt().getEnergyUsage(); - Long netFee1 = infoById1.get().getReceipt().getNetFee(); - long energyUsageTotal1 = infoById1.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee1:" + fee1); - logger.info("netUsed1:" + netUsed1); - logger.info("energyUsed1:" + energyUsed1); - logger.info("netFee1:" + netFee1); - logger.info("energyUsageTotal1:" + energyUsageTotal1); - - Account infoafter1 = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter1 = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance1); - logger.info("afterEnergyUsed:" + afterEnergyUsed1); - logger.info("afterNetUsed:" + afterNetUsed1); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed1); - - Assert.assertTrue(infoById1.get().getResultValue() == 0); - Assert.assertTrue(afterBalance1 + fee1 == afterBalance); - Assert.assertTrue(afterEnergyUsed + energyUsed1 >= afterEnergyUsed1); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(4 == returnnumber); - String fakeAddress = "FFFFFFF"; - - num = "\"" + code1 + "\"" + ",\"" + fakeAddress + "\""; - - txid = PublicMethed - .triggerContract(contractAddress, - "deploy3(bytes,string)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById2 = null; - infoById2 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - Assert.assertTrue(infoById2.get().getResultValue() != 0); - Assert - .assertThat(ByteArray - .toStr(infoById2.get().getResMessage().toByteArray()), - containsString("REVERT opcode executed")); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test021.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test021.java deleted file mode 100644 index 847a6f6577e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test021.java +++ /dev/null @@ -1,372 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test021 { - - private static final long now = System.currentTimeMillis(); - private static final String name = "Asset008_" + Long.toString(now); - private static final long totalSupply = now; - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] bytes; - String description = "just-test"; - String url = "https://github.com/tronprotocol/wallet-cli/"; - ByteString assetAccountId = null; - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] resourceOnwerAddress = ecKey2.getAddress(); - String resourceOnwerKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - ECKey ecKey3 = new ECKey(Utils.getRandom()); - private byte[] contractExcAddress = ecKey3.getAddress(); - private String contractExcKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - PublicMethed.printAddress(resourceOnwerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - } - - @Test(enabled = true, description = "resource delegate with create2 contract, and suicide ") - public void test1TriggerContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - Assert.assertTrue(PublicMethed - .sendcoin(resourceOnwerAddress, 1000000000L + 1024000000L, testNetAccountAddress, - testNetAccountKey, - blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Create 3 the same name token. - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed.createAssetIssue(resourceOnwerAddress, - name, totalSupply, 1, 1, start, end, 1, description, url, - 2000L, 2000L, 1L, 1L, resourceOnwerKey, blockingStubFull)); - String filePath = "src/test/resources/soliditycode/create2contractn.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - - Long beforeExcAccountBalance = PublicMethed - .queryAccount(resourceOnwerAddress, blockingStubFull).getBalance(); - // create2 TestContract - String contractName1 = "TestConstract"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String txid = ""; - String num = "\"" + code1 + "\"" + "," + 1; - txid = PublicMethed - .triggerContract(contractAddress, - "deploy(bytes,uint256)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - - byte[] returnAddressBytes = infoById.get().getInternalTransactions(0).getTransferToAddress() - .toByteArray(); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - - bytes = returnAddressBytes; - - - // freezeBalanceForReceiver to create2 contract Address, transaction Failed - - Assert.assertFalse(PublicMethed.freezeBalanceForReceiver(resourceOnwerAddress, 5000000L, 0, 0, - ByteString.copyFrom(bytes), resourceOnwerKey, blockingStubFull)); - Assert.assertFalse(PublicMethed.freezeBalanceForReceiver(resourceOnwerAddress, 5000000L, 0, 1, - ByteString.copyFrom(bytes), resourceOnwerKey, blockingStubFull)); - Long afterExcAccountBalance = PublicMethed.queryAccount(resourceOnwerAddress, blockingStubFull) - .getBalance(); - Assert.assertTrue(PublicMethed.getAccountResource(bytes, blockingStubFull).getNetLimit() == 0); - Assert - .assertTrue(PublicMethed.getAccountResource(bytes, blockingStubFull).getEnergyLimit() == 0); - logger.info("afterExcAccountBalance: " + afterExcAccountBalance); - logger.info("beforeExcAccountBalance:" + beforeExcAccountBalance); - - Assert.assertTrue(afterExcAccountBalance - beforeExcAccountBalance == 0); - - - // create2 Address Suicide - String param2 = "\"" + Base58.encode58Check(contractExcAddress) + "\""; - String txidn = PublicMethed - .triggerContract(bytes, - "testSuicideNonexistentTarget(address)", param2, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - - // active create2 Address to normal Address - Assert.assertTrue(PublicMethed - .sendcoin(bytes, 1000000L, contractExcAddress, contractExcKey, blockingStubFull)); - //Trigger contract to transfer trx and token. - Account getAssetIdFromAccount = PublicMethed - .queryAccount(resourceOnwerAddress, blockingStubFull); - assetAccountId = getAssetIdFromAccount.getAssetIssuedID(); - Long contractBeforeBalance = PublicMethed.queryAccount(bytes, blockingStubFull).getBalance(); - - Assert.assertTrue( - PublicMethed.transferAsset(bytes, assetAccountId.toByteArray(), 100, resourceOnwerAddress, - resourceOnwerKey, - blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account account1 = PublicMethed.queryAccount(bytes, blockingStubFull); - int typeValue1 = account1.getTypeValue(); - Assert.assertEquals(0, typeValue1); - - // freezeBalanceForReceiver to "create2" contract Address, transaction SUCCESS - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(resourceOnwerAddress, 1000000L, 0, 0, - ByteString.copyFrom(bytes), resourceOnwerKey, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(resourceOnwerAddress, 1000000L, 0, 1, - ByteString.copyFrom(bytes), resourceOnwerKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - beforeExcAccountBalance = PublicMethed.queryAccount(resourceOnwerAddress, blockingStubFull) - .getBalance(); - - Assert.assertTrue(PublicMethed.unFreezeBalance(resourceOnwerAddress, resourceOnwerKey, - 0, bytes, blockingStubFull)); - Assert.assertTrue(PublicMethed.unFreezeBalance(resourceOnwerAddress, resourceOnwerKey, - 1, bytes, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long afterUnfreezeBalance = PublicMethed.queryAccount(resourceOnwerAddress, blockingStubFull) - .getBalance(); - Assert.assertTrue(afterUnfreezeBalance == beforeExcAccountBalance + 1000000L * 2); - - - // create2 TestContract to turn AccountType To create2 Contract Address - txid = PublicMethed - .triggerContract(contractAddress, - "deploy(bytes,uint256)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - // triggercontract Create2 address, function normal - txid = PublicMethed - .triggerContract(returnAddressBytes, - "i()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee1 = infoById1.get().getFee(); - Long netUsed1 = infoById1.get().getReceipt().getNetUsage(); - Long energyUsed1 = infoById1.get().getReceipt().getEnergyUsage(); - Long netFee1 = infoById1.get().getReceipt().getNetFee(); - long energyUsageTotal1 = infoById1.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee1:" + fee1); - logger.info("netUsed1:" + netUsed1); - logger.info("energyUsed1:" + energyUsed1); - logger.info("netFee1:" + netFee1); - logger.info("energyUsageTotal1:" + energyUsageTotal1); - - Account infoafter1 = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter1 = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance1); - logger.info("afterEnergyUsed:" + afterEnergyUsed1); - logger.info("afterNetUsed:" + afterNetUsed1); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed1); - - Assert.assertTrue(infoById1.get().getResultValue() == 0); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - Account account = PublicMethed.queryAccount(returnAddressBytes, blockingStubFull); - int typeValue = account.getTypeValue(); - Assert.assertEquals(2, typeValue); - Assert.assertEquals(account.getBalance(), 1000000); - } - - @Test(enabled = true, description = "Create2 contract can transfer trx and token.") - public void test2TriggerContract() { - Account accountbefore = PublicMethed.queryAccount(bytes, blockingStubFull); - int typeValue = accountbefore.getTypeValue(); - Assert.assertEquals(2, typeValue); - long accountbeforeBalance = accountbefore.getBalance(); - Assert.assertEquals(accountbeforeBalance, 1000000); - Account contractExcAddressbefore = PublicMethed - .queryAccount(contractExcAddress, blockingStubFull); - long contractExcAddressbeforeBalance = contractExcAddressbefore.getBalance(); - - String num = "1"; - - String txid = PublicMethed - .triggerContract(bytes, - "testTransfer(uint256)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional transactionInfoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(transactionInfoById.get().getResultValue() == 0); - Long fee1 = transactionInfoById.get().getFee(); - - Account accountafter = PublicMethed.queryAccount(bytes, blockingStubFull); - long accountafterBalance = accountafter.getBalance(); - Assert.assertTrue(accountbeforeBalance - 1 == accountafterBalance); - - Account contractExcAddressafter = PublicMethed - .queryAccount(contractExcAddress, blockingStubFull); - long contractExcAddressafterBalance = contractExcAddressafter.getBalance(); - Assert.assertTrue(contractExcAddressbeforeBalance + 1 - fee1 == contractExcAddressafterBalance); - - num = "1" + ",\"" + assetAccountId.toStringUtf8() + "\""; - Long returnAddressBytesAccountCountBefore = PublicMethed - .getAssetIssueValue(bytes, assetAccountId, blockingStubFull); - Long contractExcAddressAccountCountBefore = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - String txid1 = PublicMethed - .triggerContract(bytes, - "testTransferToken(uint256,trcToken)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional transactionInfoById1 = PublicMethed - .getTransactionInfoById(txid1, blockingStubFull); - Assert.assertTrue(transactionInfoById1.get().getResultValue() == 0); - Long returnAddressBytesAccountCountAfter = PublicMethed - .getAssetIssueValue(bytes, assetAccountId, blockingStubFull); - - Long contractExcAddressAccountCountAfter = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Assert.assertTrue( - returnAddressBytesAccountCountBefore - 1 == returnAddressBytesAccountCountAfter); - Assert.assertTrue( - contractExcAddressAccountCountBefore + 1 == contractExcAddressAccountCountAfter); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test023.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test023.java deleted file mode 100644 index 9ebc0295c32..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test023.java +++ /dev/null @@ -1,282 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test023 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] testContractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - - public byte[] subByte(byte[] b, int off, int length) { - byte[] b1 = new byte[length]; - System.arraycopy(b, off, b1, 0, length); - return b1; - - } - - @Test(enabled = true, description = "Deploy factory contract") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 10000_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 10000_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/Create2Test023.sol"; - String contractName = "factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = true, description = "contract A new B contract,A suicide,contract B still exist") - public void test02TriggerTestContract() { - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "testCreate()", "#", false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - byte[] a = infoById.get().getContractResult(0).toByteArray(); - byte[] b = subByte(a, 11, 1); - byte[] c = subByte(a, 0, 11); - byte[] e = "41".getBytes(); - byte[] d = subByte(a, 12, 20); - - logger.info("a:" + ByteArray.toHexString(a)); - - logger.info("b:" + ByteArray.toHexString(b)); - logger.info("c:" + ByteArray.toHexString(c)); - - logger.info("d:" + ByteArray.toHexString(d)); - - logger.info("41" + ByteArray.toHexString(d)); - String exceptedResult = "41" + ByteArray.toHexString(d); - String realResult = ByteArray.toHexString(b); - Assert.assertEquals(realResult, "00"); - Assert.assertNotEquals(realResult, "41"); - - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(exceptedResult)); - logger.info("B Address : " + addressFinal); - - //B Address is created by A, Trigger contract B - triggerTxid = PublicMethed.triggerContract(ByteArray.fromHexString(exceptedResult), - "test()", "#", false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertEquals(infoById.get().getResultValue(), 0); - Assert.assertEquals(ByteArray.toLong(infoById.get().getContractResult(0).toByteArray()), 1); - Assert.assertEquals("SUCESS", infoById.get().getResult().toString()); - - triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "kill()", "#", false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - String note = ByteArray - .toStr(infoById.get().getInternalTransactions(0).getNote().toByteArray()); - - Assert.assertEquals(infoById.get().getResultValue(), 0); - Assert.assertEquals("SUCESS", infoById.get().getResult().toString()); - Assert.assertEquals("suicide", note); - - triggerTxid = PublicMethed.triggerContract(ByteArray.fromHexString(exceptedResult), - "test()", "#", false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertEquals(infoById.get().getResultValue(), 0); - Assert.assertEquals("SUCESS", infoById.get().getResult().toString()); - Assert.assertEquals(1, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test024.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test024.java deleted file mode 100644 index f406a294e7b..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test024.java +++ /dev/null @@ -1,277 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test024 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] testContractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - - public byte[] subByte(byte[] b, int off, int length) { - byte[] b1 = new byte[length]; - System.arraycopy(b, off, b1, 0, length); - return b1; - - } - - @Test(enabled = true, description = "Deploy factory contract") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 10000_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 10000_000_000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/Create2Test024.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = true, description = "create2 not allowed create2 twice in function") - public void test02TriggerTestContract() { - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/Create2Test024.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - Long salt = 4L; - - String param = "\"" + testContractCode + "\"," + salt; - - String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - byte[] a = infoById.get().getContractResult(0).toByteArray(); - byte[] b = subByte(a, 11, 1); - byte[] c = subByte(a, 0, 11); - byte[] e = "41".getBytes(); - byte[] d = subByte(a, 12, 20); - - logger.info("a:" + ByteArray.toHexString(a)); - - logger.info("b:" + ByteArray.toHexString(b)); - logger.info("c:" + ByteArray.toHexString(c)); - - logger.info("d:" + ByteArray.toHexString(d)); - - logger.info("41" + ByteArray.toHexString(d)); - String exceptedResult = "41" + ByteArray.toHexString(d); - String realResult = ByteArray.toHexString(b); - Assert.assertEquals(realResult, "00"); - Assert.assertNotEquals(realResult, "41"); - - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(exceptedResult)); - logger.info("create2 Address : " + addressFinal); - - Assert.assertEquals(infoById.get().getResult().toString(), "SUCESS"); - Assert.assertEquals(infoById.get().getResultValue(), 0); - - triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy2(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - devEnergyLimitAfter = accountResource.getEnergyLimit(); - devEnergyUsageAfter = accountResource.getEnergyUsed(); - devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - userEnergyLimitAfter = accountResource.getEnergyLimit(); - userEnergyUsageAfter = accountResource.getEnergyUsed(); - userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - Assert.assertEquals(infoById.get().getResultValue(), 1); - Assert.assertEquals(infoById.get().getResult().toString(), "FAILED"); - Assert.assertThat(ByteArray.toStr(infoById.get().getResMessage().toByteArray()), - containsString("REVERT opcode executed")); - - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test025.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test025.java deleted file mode 100644 index ca0a9a2d9c7..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test025.java +++ /dev/null @@ -1,263 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.create2; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Create2Test025 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] testContractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = false, description = "Deploy factory contract") - public void test01DeployFactoryContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 10000_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 10000_000_000L, fromAddress, - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/Create2Test025.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - code += "05"; - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = false, description = "create2 bytecode with parm") - public void test02TriggerTestContract() { - //Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - // PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - // blockingStubFull), 0, 1, - // ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - String filePath = "./src/test/resources/soliditycode/Create2Test025.sol"; - String contractName = "TestContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - testContractCode += "0000000000000000000000000000000000000000000000000000000000000005"; - Long salt = 4L; - - String param = "\"" + testContractCode + "\"," + salt; - - String triggerTxid = null; - triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "create2(bytes,uint256)", param, false, 0L, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - String txid = PublicMethed.triggerContract(testContractAddress, - "getNum()", "#", false, 0L, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - Optional infoById2 = PublicMethed.getTransactionInfoById(txid, - blockingStubFull); - TransactionInfo transactionInfo2 = infoById2.get(); - final int Num = ByteArray.toInt(transactionInfo2.getContractResult(0).toByteArray()); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - userEnergyLimitAfter = accountResource.getEnergyLimit(); - userEnergyUsageAfter = accountResource.getEnergyUsed(); - userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - logger.info("NUM :" + Num); - Assert.assertEquals(infoById.get().getResult().toString(), "SUCESS"); - Assert.assertEquals(infoById.get().getResultValue(), 0); - Assert.assertEquals(5, Num); - - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest001.java deleted file mode 100644 index e6da831111f..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest001.java +++ /dev/null @@ -1,689 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.extCodeHash; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.crypto.Hash; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ExtCodeHashTest001 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] extCodeHashContractAddress = null; - private byte[] testContractAddress = null; - private String testContractAddress2 = null; - - private String expectedCodeHash = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - private byte[] testAddress = ecKey3.getAddress(); - private String testKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "Deploy extcodehash contract") - public void test01DeployExtCodeHashContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/extCodeHash.sol"; - String contractName = "TestExtCodeHash"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - expectedCodeHash = ByteArray.toHexString(Hash.sha3(Hex.decode(code))); - logger.info("expectedCodeHash: " + expectedCodeHash); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - extCodeHashContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(extCodeHashContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = false, description = "Get the extcodehash of a normal address") - public void test02GetNormalAddressCodeHash() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(dev001Address) + "\""; - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr(address)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("transaction failed with message: " - + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info( - "the value: " + retList); - - Assert.assertEquals("C5D2460186F7233C927E7DB2DCC703C0E500B653CA82273B7BFAD8045D85A470", - retList.get(0)); - - } - - @Test(enabled = true, description = "Get a contract extcodehash") - public void test03GetContactCodeHash() { - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(extCodeHashContractAddress) + "\""; - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr(address)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - - Assert.assertFalse(retList.isEmpty()); - Assert.assertNotEquals("C5D2460186F7233C927E7DB2DCC703C0E500B653CA82273B7BFAD8045D85A470", - retList.get(0)); - Assert.assertNotEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - @Test(enabled = true, description = "Get a not exist account extcodehash") - public void test04GetNotExistAddressCodeHash() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(testAddress) + "\""; - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr(address)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info( - "the value: " + retList); - - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - - SmartContract smartContract = PublicMethed - .getContract(extCodeHashContractAddress, blockingStubFull); - logger.info(smartContract.getBytecode().toStringUtf8()); - } - - @Test(enabled = true, description = "Active the account and get extcodehash again") - public void test05ActiveAccountGetCodeHash() { - - Assert.assertTrue(PublicMethed.sendcoin(testAddress, 1000000, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(testAddress) + "\""; - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr(address)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - - Assert.assertEquals("C5D2460186F7233C927E7DB2DCC703C0E500B653CA82273B7BFAD8045D85A470", - retList.get(0)); - - SmartContract smartContract = PublicMethed - .getContract(extCodeHashContractAddress, blockingStubFull); - logger.info(smartContract.getBytecode().toStringUtf8()); - - } - - @Test(enabled = true, description = "Get a not deployed create2 extcodehash") - public void test06GetCreate2CodeHash() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - String filePath = "./src/test/resources/soliditycode/extCodeHash.sol"; - String contractName = "TestExtCodeHash"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - final String abi = retMap.get("abI").toString(); - - Long salt = 100L; - String[] parameter = {Base58.encode58Check(user001Address), code, salt.toString()}; - logger.info(PublicMethed.create2(parameter)); - testContractAddress2 = PublicMethed.create2(parameter); - - Long callValue = Long.valueOf(0); - - String param = "\"" - + Base58.encode58Check(WalletClient.decodeFromBase58Check(testContractAddress2)) + "\""; - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr(address)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info( - "the value: " + retList); - - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - - /*PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull);*/ - } - - @Test(enabled = true, description = "Get the EXTCODEHASH of an account created " - + "in the current transaction") - public void test07DeployExtCodeHashContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/extCodeHashConstruct.sol"; - String contractName = "CounterConstruct"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - extCodeHashContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(extCodeHashContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getTopics(0).toByteArray()); - - logger.info("the value: " + retList); - - Assert.assertFalse(retList.isEmpty()); - Assert.assertNotEquals("C5D2460186F7233C927E7DB2DCC703C0E500B653CA82273B7BFAD8045D85A470", - retList.get(0)); - Assert.assertNotEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest002.java deleted file mode 100644 index 933e9c4b7d6..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest002.java +++ /dev/null @@ -1,246 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.extCodeHash; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ExtCodeHashTest002 { - - private final boolean AllTest = false; - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] extCodeHashContractAddress = null; - private byte[] testContractAddress = null; - - private String expectedCodeHash = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = AllTest, description = "Deploy extcodehash contract") - public void test01DeployExtCodeHashContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/extCodeHash.sol"; - String contractName = "TestExtCodeHash"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - extCodeHashContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(extCodeHashContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = AllTest, description = "Get a contract extcodehash") - public void test02GetContactCodeHash() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(extCodeHashContractAddress) + "\""; - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr(address)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - - Assert.assertFalse(retList.isEmpty()); - Assert.assertNotEquals("C5D2460186F7233C927E7DB2DCC703C0E500B653CA82273B7BFAD8045D85A470", - retList.get(0)); - Assert.assertNotEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest003.java deleted file mode 100644 index 1d036eae6f7..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest003.java +++ /dev/null @@ -1,336 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.extCodeHash; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ExtCodeHashTest003 { - - private final boolean AllTest = false; - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] extCodeHashContractAddress = null; - private byte[] testContractAddress = null; - - private String expectedCodeHash = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - private byte[] testAddress = ecKey3.getAddress(); - private String testKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = AllTest, description = "Deploy extcodehash contract") - public void test01DeployExtCodeHashContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/extCodeHash.sol"; - String contractName = "TestExtCodeHash"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - extCodeHashContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(extCodeHashContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = AllTest, description = "Get a not exist account extcodehash") - public void test02GetNotExistAddressCodeHash() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(testAddress) + "\""; - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr(address)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info( - "the value: " + retList); - - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - - SmartContract smartContract = PublicMethed - .getContract(extCodeHashContractAddress, blockingStubFull); - logger.info(smartContract.getBytecode().toStringUtf8()); - } - - @Test(enabled = AllTest, description = "Active the account and get extcodehash again") - public void test03ActiveAccountGetCodeHash() { - - Assert.assertTrue(PublicMethed.sendcoin(testAddress, 1000000, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(testAddress) + "\""; - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr(address)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - - Assert.assertEquals("C5D2460186F7233C927E7DB2DCC703C0E500B653CA82273B7BFAD8045D85A470", - retList.get(0)); - - SmartContract smartContract = PublicMethed - .getContract(extCodeHashContractAddress, blockingStubFull); - logger.info(smartContract.getBytecode().toStringUtf8()); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest004.java deleted file mode 100644 index 4b68380ff9e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest004.java +++ /dev/null @@ -1,256 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.extCodeHash; - -import static org.tron.common.crypto.Hash.sha3; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ExtCodeHashTest004 { - - private final boolean AllTest = false; - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] extCodeHashContractAddress = null; - private String testContractAddress = null; - - private String expectedCodeHash = null; - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = AllTest, description = "Deploy extcodehash contract") - public void test01DeployExtCodeHashContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/extCodeHash.sol"; - String contractName = "TestExtCodeHash"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - final String abi = retMap.get("abI").toString(); - - expectedCodeHash = ByteArray.toHexString(sha3(Hex.decode(code))); - logger.info("expectedCodeHash: " + expectedCodeHash); - - Long salt = 100L; - String[] parameter = {Base58.encode58Check(user001Address), code, salt.toString()}; - logger.info(PublicMethed.create2(parameter)); - testContractAddress = PublicMethed.create2(parameter); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - extCodeHashContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(extCodeHashContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = AllTest, description = "Get a not deployed create2 extcodehash") - public void test02GetCreate2CodeHash() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String param = - "\"" + Base58.encode58Check(WalletClient.decodeFromBase58Check(testContractAddress)) + "\""; - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr(address)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info( - "the value: " + retList); - - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest005.java deleted file mode 100644 index 0f95573a1ea..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest005.java +++ /dev/null @@ -1,713 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.extCodeHash; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.runtime.vm.DataWord; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ExtCodeHashTest005 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] extCodeHashContractAddress = null; - private byte[] testContractAddress = null; - - private String contractCodeHash = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - private byte[] testAddress = ecKey3.getAddress(); - private String testKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - - String fakeAddress = ""; - - logger.info("realAddress: " + fakeAddress); - byte[] fullHexAddr = new DataWord(fakeAddress).getData(); - logger.info("fullHexAddr ++= " + Hex.toHexString(fullHexAddr)); - - fakeAddress = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; - - logger.info("realAddress: " + fakeAddress); - fullHexAddr = new DataWord(fakeAddress).getData(); - logger.info("fullHexAddr ++= " + Hex.toHexString(fullHexAddr)); - - } - - @Test(enabled = true, description = "Deploy extcodehash contract") - public void test01DeployExtCodeHashContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/extCodeHash.sol"; - String contractName = "TestExtCodeHash"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - extCodeHashContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(extCodeHashContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = true, description = "Get codehash of a real contract by uint") - public void test02GetContractCodeHash() { - - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String testAddress = ByteArray.toHexString(extCodeHashContractAddress); - logger.info("realAddress: " + testAddress); - byte[] fullHexAddr = new DataWord(testAddress).getData(); - - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByUint(uint256)", Hex.toHexString(fullHexAddr), true, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - - Assert.assertFalse(retList.isEmpty()); - Assert.assertNotEquals("C5D2460186F7233C927E7DB2DCC703C0E500B653CA82273B7BFAD8045D85A470", - retList.get(0)); - Assert.assertNotEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - - contractCodeHash = retList.get(0); - - SmartContract smartContract = PublicMethed - .getContract(extCodeHashContractAddress, blockingStubFull); - logger.info(smartContract.getBytecode().toStringUtf8()); - } - - @Test(enabled = true, description = "Get codehash of a fake address by uint") - public void test03GetInvalidAddressCodeHash() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String fakeAddress = "41660757B2543F4849D3F42B90F58DE1C14C7E0038"; - logger.info("realAddress: " + fakeAddress); - byte[] fullHexAddr = new DataWord(fakeAddress).getData(); - - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByUint(uint256)", Hex.toHexString(fullHexAddr), true, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - - Assert.assertFalse(retList.isEmpty()); - - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - - SmartContract smartContract = PublicMethed - .getContract(extCodeHashContractAddress, blockingStubFull); - logger.info(smartContract.getBytecode().toStringUtf8()); - } - - @Test(enabled = true, description = "Get codehash of a normal account by uint") - public void test04GetNormalAddressCodeHash() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String fakeAddress = ByteArray.toHexString(user001Address); - logger.info("realAddress: " + fakeAddress); - byte[] fullHexAddr = new DataWord(fakeAddress).getData(); - - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByUint(uint256)", Hex.toHexString(fullHexAddr), true, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - Assert.assertFalse(retList.isEmpty()); - - Assert.assertEquals("C5D2460186F7233C927E7DB2DCC703C0E500B653CA82273B7BFAD8045D85A470", - retList.get(0)); - - SmartContract smartContract = PublicMethed - .getContract(extCodeHashContractAddress, blockingStubFull); - logger.info(smartContract.getBytecode().toStringUtf8()); - } - - @Test(enabled = true, description = "Get codehash of a empty address by uint") - public void test05GetEmptyAddressCodeHash() { - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String fakeAddress = ""; - - logger.info("realAddress: " + fakeAddress); - byte[] fullHexAddr = new DataWord(fakeAddress).getData(); - logger.info("fullHexAddr ++= " + Hex.toHexString(fullHexAddr)); - - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByUint(uint256)", Hex.toHexString(fullHexAddr), true, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - Assert.assertFalse(retList.isEmpty()); - - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - - SmartContract smartContract = PublicMethed - .getContract(extCodeHashContractAddress, blockingStubFull); - logger.info(smartContract.getBytecode().toStringUtf8()); - } - - @Test(enabled = true, description = "Get codehash of a fffffff*64 address by uint") - public void test06GetFakeAddressCodeHash() { - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String fakeAddress = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; - - logger.info("realAddress: " + fakeAddress); - byte[] fullHexAddr = new DataWord(fakeAddress).getData(); - logger.info("fullHexAddr ++= " + Hex.toHexString(fullHexAddr)); - - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByUint(uint256)", Hex.toHexString(fullHexAddr), true, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - Assert.assertFalse(retList.isEmpty()); - - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - - SmartContract smartContract = PublicMethed - .getContract(extCodeHashContractAddress, blockingStubFull); - logger.info(smartContract.getBytecode().toStringUtf8()); - } - - @Test(enabled = true, description = "Get codehash of a real contract plus 2**160 by uint") - public void test07GetContractAddress96CodeHash() { - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - BigInteger bigIntAddr = new DataWord(extCodeHashContractAddress).sValue(); - String bigIntAddrChange = BigInteger.valueOf(2).pow(160).add(bigIntAddr).toString(16); - byte[] fullHexAddr = new DataWord(bigIntAddrChange).getData(); - - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByUint(uint256)", Hex.toHexString(fullHexAddr), true, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - Assert.assertFalse(retList.isEmpty()); - - // expect the code hash same - Assert.assertEquals(contractCodeHash, retList.get(0)); - - SmartContract smartContract = PublicMethed - .getContract(extCodeHashContractAddress, blockingStubFull); - logger.info(smartContract.getBytecode().toStringUtf8()); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest006.java deleted file mode 100644 index e68bb5907ae..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest006.java +++ /dev/null @@ -1,185 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.extCodeHash; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ExtCodeHashTest006 { - - private final boolean AllTest = false; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] extCodeHashContractAddress = null; - private byte[] testContractAddress = null; - - private String expectedCodeHash = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - private byte[] testAddress = ecKey3.getAddress(); - private String testKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = AllTest, description = "Get the EXTCODEHASH of an account created " - + "in the current transaction") - public void test01DeployExtCodeHashContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/extCodeHashConstruct.sol"; - String contractName = "CounterConstruct"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - extCodeHashContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(extCodeHashContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getTopics(0).toByteArray()); - - logger.info("the value: " + retList); - - Assert.assertFalse(retList.isEmpty()); - Assert.assertNotEquals("C5D2460186F7233C927E7DB2DCC703C0E500B653CA82273B7BFAD8045D85A470", - retList.get(0)); - Assert.assertNotEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest007.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest007.java deleted file mode 100644 index 31751de1346..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest007.java +++ /dev/null @@ -1,617 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.extCodeHash; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ExtCodeHashTest007 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] testAddressOld = null; - private byte[] testAddressNew = null; - private byte[] testAddress2 = null; - private byte[] extCodeHashContractAddress = null; - - private String expectedCodeHash = null; - private String expectedCodeHashOld = null; - - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "Deploy testNoPayable contract using old solidity") - public void test01DeployTestContractOld() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String contractName = "testExtHashContract"; - String code = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a576000" - + "80fd5b5060ef806100396000396000f30060806040526004361060485763ffffffff7c010000000000000000" - + "0000000000000000000000000000000000000000600035041663c518aa0f8114604d578063e5aa3d58146089" - + "575b600080fd5b348015605857600080fd5b50d38015606457600080fd5b50d28015607057600080fd5b5060" - + "7760b3565b60408051918252519081900360200190f35b348015609457600080fd5b50d3801560a057600080" - + "fd5b50d2801560ac57600080fd5b50607760bd565b6001600081905590565b600054815600a165627a7a7230" - + "5820766b4e2fca9081689cd89419411d2cbc5588a17a5c9fa900fd9cfe4b0d9652be0029"; - String abi = "[{\"constant\":false,\"inputs\":[],\"name\":\"testNoPayable\"," - + "\"outputs\":[{\"name\":\"z\",\"type\":\"uint256\"}],\"payable\":false," - + "\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true," - + "\"inputs\":[],\"name\":\"i\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}]," - + "\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]"; - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - testAddressOld = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(testAddressOld, - blockingStubFull); - } - - @Test(enabled = true, description = "Deploy testNoPayable contract using new solidity") - public void test02DeployTestContractNew() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String contractName = "testConstantContract"; - String code = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a5760" - + "0080fd5b5060c5806100396000396000f3fe6080604052348015600f57600080fd5b50d38015601b576000" - + "80fd5b50d28015602757600080fd5b50600436106066577c01000000000000000000000000000000000000" - + "000000000000000000006000350463c518aa0f8114606b578063e5aa3d58146083575b600080fd5b607160" - + "89565b60408051918252519081900360200190f35b60716093565b6001600081905590565b6000548156fe" - + "a165627a7a723058205c5aadfbd06ea264db7b73e7b7f3c36ac64a9d520ba46b4bc7f1dc56252f17ac0029"; - String abi = "[{\"constant\":false,\"inputs\":[],\"name\":\"testNoPayable\",\"outputs\":[{\"" - + "name\":\"z\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable" - + "\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"i\",\"outputs\":" - + "[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"" - + "type\":\"function\"}]"; - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - testAddressNew = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(testAddressNew, - blockingStubFull); - } - - @Test(enabled = true, description = "Deploy extcodehash contract") - public void test03DeployExtCodeHashContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/extCodeHash.sol"; - String contractName = "TestExtCodeHash"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - extCodeHashContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(extCodeHashContractAddress, - blockingStubFull); - } - - @Test(enabled = true, description = "Get contract code hash with old solidity") - public void test04GetTestOldCodeHash() { - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(testAddressOld) + "\""; - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr(address)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info( - "the value: " + retList); - - expectedCodeHashOld = retList.get(0); - Assert.assertEquals( - "B4AB5B9FF1A4FF7793E60EBFF0C769443AF66D0A6F9455AF145432CE8BA78175", expectedCodeHashOld); - Assert.assertFalse(retList.isEmpty()); - } - - @Test(enabled = true, description = "Get contract code hash with new solidity") - public void test05GetTestNewCodeHash() { - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(testAddressNew) + "\""; - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr(address)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - Assert.assertFalse(retList.isEmpty()); - - Assert.assertNotEquals(retList.get(0), expectedCodeHashOld); - expectedCodeHash = retList.get(0); - Assert.assertEquals( - "34DB53BD1F7214367E8D6B2A7A6FBBF0E3B7DDB4939ECADE4CDEF6749C27A2DA", expectedCodeHash); - } - - @Test(enabled = true, description = "Deploy contract using new solidity again") - public void test06DeployTest2Contract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String contractName = "testConstantContract"; - String code = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a5760" - + "0080fd5b5060c5806100396000396000f3fe6080604052348015600f57600080fd5b50d38015601b576000" - + "80fd5b50d28015602757600080fd5b50600436106066577c01000000000000000000000000000000000000" - + "000000000000000000006000350463c518aa0f8114606b578063e5aa3d58146083575b600080fd5b607160" - + "89565b60408051918252519081900360200190f35b60716093565b6001600081905590565b6000548156fe" - + "a165627a7a723058205c5aadfbd06ea264db7b73e7b7f3c36ac64a9d520ba46b4bc7f1dc56252f17ac0029"; - String abi = "[{\"constant\":false,\"inputs\":[],\"name\":\"testNoPayable\",\"outputs\":[{\"" - + "name\":\"z\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable" - + "\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"i\",\"outputs\":" - + "[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"" - + "type\":\"function\"}]"; - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - testAddress2 = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(testAddress2, - blockingStubFull); - } - - @Test(enabled = true, description = "Get contract code hash with test2") - public void test07GetTest2CodeHash() { - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(testAddress2) + "\""; - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr(address)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - Assert.assertFalse(retList.isEmpty()); - - Assert.assertEquals(expectedCodeHash, retList.get(0)); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest008.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest008.java deleted file mode 100644 index 5e2f90ce186..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest008.java +++ /dev/null @@ -1,512 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.extCodeHash; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ExtCodeHashTest008 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] extCodeHashContractAddress = null; - private byte[] testContractAddress = null; - - private String expectedCodeHash = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "Deploy extcodehash contract") - public void test01DeployExtCodeHashContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/extCodeHash.sol"; - String contractName = "TestExtCodeHash"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - extCodeHashContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(extCodeHashContractAddress, - blockingStubFull); - } - - @Test(enabled = true, description = "Get code hash of create2 empty contract") - public void test02GetTestContractCodeHash() { - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - Long salt = 1L; - - String[] parameter = {Base58.encode58Check(user001Address), testContractCode, salt.toString()}; - logger.info(PublicMethed.create2(parameter)); - - Long callValue = Long.valueOf(0); - - String param = "\"" + PublicMethed.create2(parameter) + "\""; - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr(address)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - - Assert.assertFalse(retList.isEmpty()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - } - - @Test(enabled = true, description = "Deploy factory contract") - public void test03DeployFactoryContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = true, description = "Trigger create2 function to deploy test contract") - public void test04TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - @Test(enabled = true, description = "Get code hash of test contract") - public void test05GetTestContractCodeHash() { - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(testContractAddress) + "\""; - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr(address)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - - Assert.assertFalse(retList.isEmpty()); - Assert.assertNotEquals("C5D2460186F7233C927E7DB2DCC703C0E500B653CA82273B7BFAD8045D85A470", - retList.get(0)); - Assert.assertNotEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest009.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest009.java deleted file mode 100644 index e3f97cdf25a..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest009.java +++ /dev/null @@ -1,512 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.extCodeHash; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ExtCodeHashTest009 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] extCodeHashContractAddress = null; - private byte[] testContractAddress = null; - - private String expectedCodeHash = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "Deploy extcodehash contract") - public void test01DeployExtCodeHashContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/extCodeHash.sol"; - String contractName = "TestExtCodeHash"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - extCodeHashContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(extCodeHashContractAddress, - blockingStubFull); - } - - @Test(enabled = true, description = "Get code hash of create2 empty contract") - public void test02GetTestContractCodeHash() { - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - Long salt = 1L; - - String[] parameter = {Base58.encode58Check(user001Address), testContractCode, salt.toString()}; - logger.info(PublicMethed.create2(parameter)); - - Long callValue = Long.valueOf(0); - - String param = "\"" + PublicMethed.create2(parameter) + "\""; - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr(address)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - - Assert.assertFalse(retList.isEmpty()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - } - - @Test(enabled = true, description = "Deploy factory contract") - public void test03DeployFactoryContract() { - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - factoryContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(factoryContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = true, description = "Trigger create2 function to deploy test contract") - public void test04TriggerCreate2ToDeployTestContract() { - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String filePath = "./src/test/resources/soliditycode/create2contract.sol"; - String contractName = "TestConstract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String testContractCode = retMap.get("byteCode").toString(); - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - final String triggerTxid = PublicMethed.triggerContract(factoryContractAddress, - "deploy(bytes,uint256)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - - logger.info("actualSalt: " + actualSalt); - - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - - testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - SmartContract smartContract = PublicMethed.getContract(testContractAddress, blockingStubFull); - - // contract created by create2, doesn't have ABI - Assert.assertEquals(0, smartContract.getAbi().getEntrysCount()); - - // the contract owner of contract created by create2 is the factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(smartContract.getOriginAddress().toByteArray())); - - // the contract address in transaction info, - // contract address of create2 contract is factory contract - Assert.assertEquals(Base58.encode58Check(factoryContractAddress), - Base58.encode58Check(infoById.get().getContractAddress().toByteArray())); - } - - @Test(enabled = true, description = "Get code hash of test contract") - public void test05GetTestContractCodeHash() { - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(testContractAddress) + "\""; - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr(address)", param, false, callValue, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - - Assert.assertFalse(retList.isEmpty()); - Assert.assertNotEquals("C5D2460186F7233C927E7DB2DCC703C0E500B653CA82273B7BFAD8045D85A470", - retList.get(0)); - Assert.assertNotEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - dev001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - user001Address, blockingStubFull); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest010.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest010.java deleted file mode 100644 index fa52442915a..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest010.java +++ /dev/null @@ -1,370 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.extCodeHash; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ExtCodeHashTest010 { - - final boolean AllTest = false; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] factoryContractAddress = null; - private byte[] extCodeHashContractAddress = null; - private byte[] testContractAddress = null; - - private String expectedCodeHash = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = AllTest, description = "Deploy extcodehash contract") - public void test01DeployExtCodeHashContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/ExtCodeHashTest010.sol"; - String contractName = "Counter"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - extCodeHashContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(extCodeHashContractAddress, - blockingStubFull); - } - - - @Test(enabled = AllTest, description = "The EXTCODEHASH of an account that selfdestructed in the " - + "current transaction. but later been revert") - public void test02GetTestContractCodeHash() { - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashRevert()", "#", false, 0L, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - - Assert.assertFalse(retList.isEmpty()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - } - - - @Test(enabled = AllTest, description = "The EXTCODEHASH of an account that create in the current " - + "transaction. but later been revert") - public void test03GetTestContractCodeHash() { - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashCreate()", "#", false, 0L, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - - Assert.assertFalse(retList.isEmpty()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - } - - @Test(enabled = AllTest, description = "The EXTCODEHASH of an account that selfdestructed in the" - + " current transaction.") - public void test04GetTestContractCodeHash() { - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long devEnergyLimitBefore = accountResource.getEnergyLimit(); - long devEnergyUsageBefore = accountResource.getEnergyUsed(); - long devBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("before trigger, devEnergyLimitBefore is " + Long.toString(devEnergyLimitBefore)); - logger.info("before trigger, devEnergyUsageBefore is " + Long.toString(devEnergyUsageBefore)); - logger.info("before trigger, devBalanceBefore is " + Long.toString(devBalanceBefore)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitBefore = accountResource.getEnergyLimit(); - long userEnergyUsageBefore = accountResource.getEnergyUsed(); - long userBalanceBefore = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("before trigger, userEnergyLimitBefore is " + Long.toString(userEnergyLimitBefore)); - logger.info("before trigger, userEnergyUsageBefore is " + Long.toString(userEnergyUsageBefore)); - logger.info("before trigger, userBalanceBefore is " + Long.toString(userBalanceBefore)); - - String param = "\"" + Base58.encode58Check(extCodeHashContractAddress) + "\""; - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashSuicide(address)", param, false, 0L, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - long devEnergyLimitAfter = accountResource.getEnergyLimit(); - long devEnergyUsageAfter = accountResource.getEnergyUsed(); - long devBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull).getBalance(); - - logger.info("after trigger, devEnergyLimitAfter is " + Long.toString(devEnergyLimitAfter)); - logger.info("after trigger, devEnergyUsageAfter is " + Long.toString(devEnergyUsageAfter)); - logger.info("after trigger, devBalanceAfter is " + Long.toString(devBalanceAfter)); - - accountResource = PublicMethed.getAccountResource(user001Address, blockingStubFull); - long userEnergyLimitAfter = accountResource.getEnergyLimit(); - long userEnergyUsageAfter = accountResource.getEnergyUsed(); - long userBalanceAfter = PublicMethed.queryAccount(user001Address, blockingStubFull) - .getBalance(); - - logger.info("after trigger, userEnergyLimitAfter is " + Long.toString(userEnergyLimitAfter)); - logger.info("after trigger, userEnergyUsageAfter is " + Long.toString(userEnergyUsageAfter)); - logger.info("after trigger, userBalanceAfter is " + Long.toString(userBalanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info("the value: " + retList); - - Assert.assertFalse(retList.isEmpty()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000000", - retList.get(0)); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest011.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest011.java deleted file mode 100644 index 1efc05049af..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest011.java +++ /dev/null @@ -1,369 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.extCodeHash; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.crypto.Hash; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ExtCodeHashTest011 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] extCodeHashContractAddress = null; - private byte[] testContractAddress = null; - - private String expectedCodeHash = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "Deploy extcodehash contract") - public void test01DeployExtCodeHashContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/extCodeHash11.sol"; - String contractName = "Counter"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - expectedCodeHash = ByteArray.toHexString(Hash.sha3(Hex.decode(code))); - logger.info("expectedCodeHash: " + expectedCodeHash); - - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - extCodeHashContractAddress = infoById.get().getContractAddress().toByteArray(); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - transferTokenTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr()", "#", false, 0, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - Assert.assertTrue(infoById.get().getResultValue() != 0); - Assert - .assertThat(ByteArray - .toStr(infoById.get().getResMessage().toByteArray()), - containsString("REVERT opcode executed")); - } - - - @Test(enabled = true, description = "Deploy extcodehash contract") - public void test01DeployExtCodeHashContract1() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/extCodeHash11.sol"; - String contractName = "Counter1"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - expectedCodeHash = ByteArray.toHexString(Hash.sha3(Hex.decode(code))); - logger.info("expectedCodeHash: " + expectedCodeHash); - - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - extCodeHashContractAddress = infoById.get().getContractAddress().toByteArray(); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - transferTokenTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr()", "#", false, 0, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info( - "the value: " + retList); - - Assert.assertEquals(retList.get(1), - retList.get(0)); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - extCodeHashContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(extCodeHashContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - - @Test(enabled = true, description = "Deploy extcodehash contract") - public void test01DeployExtCodeHashContract2() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/extCodeHash11.sol"; - String contractName = "Counter2"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - expectedCodeHash = ByteArray.toHexString(Hash.sha3(Hex.decode(code))); - logger.info("expectedCodeHash: " + expectedCodeHash); - - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - extCodeHashContractAddress = infoById.get().getContractAddress().toByteArray(); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - String num = "\"" + Base58.encode58Check(dev001Address) + "\""; - - transferTokenTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr(address)", num, false, 0, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info( - "the value: " + retList); - Assert.assertEquals(retList.get(1), - retList.get(0)); - } - - - @Test(enabled = true, description = "Deploy extcodehash contract") - public void test01DeployExtCodeHashContract3() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/extCodeHash11.sol"; - String contractName = "Counter2"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - expectedCodeHash = ByteArray.toHexString(Hash.sha3(Hex.decode(code))); - logger.info("expectedCodeHash: " + expectedCodeHash); - - String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - extCodeHashContractAddress = infoById.get().getContractAddress().toByteArray(); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - String num = "\"" + Base58.encode58Check(dev001Address) + "\""; - - transferTokenTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "getCodeHashByAddr(address)", num, false, 0, - 1000000000L, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - List retList = PublicMethed - .getStrings(transactionInfo.getContractResult(0).toByteArray()); - - logger.info( - "the value: " + retList); - Assert.assertEquals(retList.get(1), - retList.get(0)); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(user001Address, user001Key, fromAddress, blockingStubFull); - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, dev001Address, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand001.java deleted file mode 100644 index 2c9bba20ccb..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand001.java +++ /dev/null @@ -1,340 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.isContract; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class isContractCommand001 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] nonexistentAddress = ecKey2.getAddress(); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - PublicMethed - .sendcoin(contractExcAddress, 1000_000_000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TvmIsContract001.sol"; - String contractName = "testIsContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - } - - - @Test(enabled = true, description = "Correct contract address test") - public void test01CorrectContractAddress() { - PublicMethed.waitProduceNextBlock(blockingStubFull); - Protocol.Account info; - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - String num = "\"" + Base58.encode58Check(contractAddress) + "\""; - txid = PublicMethed - .triggerContract(contractAddress, "testIsContractCommand(address)", num, false, 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertEquals(1, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testIsContractView(address)", num, - false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(1, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - } - - @Test(enabled = true, description = "Account address test") - public void test02AccountAddress() { - PublicMethed.waitProduceNextBlock(blockingStubFull); - Protocol.Account info; - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - String num = "\"" + Base58.encode58Check(contractExcAddress) + "\""; - txid = PublicMethed - .triggerContract(contractAddress, "testIsContractCommand(address)", num, false, 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertEquals(0, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testIsContractView(address)", num, - false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(0, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - } - - @Test(enabled = true, description = "Nonexistent account address test") - public void test03NonexistentAddress() { - PublicMethed.waitProduceNextBlock(blockingStubFull); - Protocol.Account info; - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - String num = "\"" + Base58.encode58Check(nonexistentAddress) + "\""; - txid = PublicMethed - .triggerContract(contractAddress, "testIsContractCommand(address)", num, false, 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertEquals(0, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testIsContractView(address)", num, - false, 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(0, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - } - - @Test(enabled = true, description = "Constructor return test") - public void test04ConstructorReturn() { - PublicMethed.waitProduceNextBlock(blockingStubFull); - Protocol.Account info; - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - txid = PublicMethed - .triggerContract(contractAddress, "testConstructor()", "", false, 0, maxFeeLimit, - contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertEquals(1, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testConstructorView()", "", false, 0, - 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(1, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed.sendcoin(testNetAccountAddress, balance, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand002.java deleted file mode 100644 index f1c588d6889..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand002.java +++ /dev/null @@ -1,190 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.isContract; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class isContractCommand002 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - byte[] selfdestructContractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - byte[] selfdestructContractExcAddress = ecKey1.getAddress(); - String selfdestructContractKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - PublicMethed.printAddress(selfdestructContractKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - - @Test(enabled = true, description = "Selfdestruct contract test isContract Command") - public void test01SelfdestructContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TvmIsContract001.sol"; - String contractName = "testIsContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String txid = ""; - String num = "\"" + Base58.encode58Check(contractAddress) + "\""; - Assert.assertTrue(PublicMethed - .sendcoin(selfdestructContractExcAddress, 10000000000L, testNetAccountAddress, - testNetAccountKey, - blockingStubFull)); - - selfdestructContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, selfdestructContractKey, - selfdestructContractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - txid = PublicMethed.triggerContract(selfdestructContractAddress, - "testIsContractCommand(address)", num, false, - 0, maxFeeLimit, selfdestructContractExcAddress, selfdestructContractKey, blockingStubFull); - Optional infoById1 = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById1 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(1, ByteArray.toInt(infoById1.get().getContractResult(0).toByteArray())); - logger.info(infoById1.toString()); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(selfdestructContractAddress, - "testIsContractView(address)", num, false, - 0, 0, "0", 0, selfdestructContractExcAddress, selfdestructContractKey, - blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(1, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - String txid1 = ""; - txid1 = PublicMethed.triggerContract(contractAddress, - "selfdestructContract(address)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - logger.info(infoById1.toString()); - - txid1 = PublicMethed.triggerContract(selfdestructContractAddress, - "testIsContractCommand(address)", num, false, - 0, maxFeeLimit, selfdestructContractExcAddress, selfdestructContractKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - Assert.assertEquals(0, ByteArray.toInt(infoById1.get().getContractResult(0).toByteArray())); - logger.info(infoById1.toString()); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(selfdestructContractAddress, - "testIsContractView(address)", num, false, - 0, 0, "0", 0, selfdestructContractExcAddress, selfdestructContractKey, - blockingStubFull); - logger.info("transactionExtention:" + transactionExtention.toString()); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(0, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - } - - @Test(enabled = true, description = "No constructor test isContract Command") - public void test02NoConstructorContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TvmIsContract002.sol"; - String contractName = "testIsContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(info.get().toString()); - Assert.assertEquals(0, info.get().getResultValue()); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed.sendcoin(testNetAccountAddress, balance, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand003.java deleted file mode 100644 index 0f492396a92..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/isContract/isContractCommand003.java +++ /dev/null @@ -1,252 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.isContract; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class isContractCommand003 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - byte[] selfdestructContractExcAddress = ecKey1.getAddress(); - String selfdestructContractKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - PublicMethed.printAddress(selfdestructContractKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - @Test(enabled = true, description = "Incorrect address hex test isContract Command") - public void test01IncorrectHashContract() { - PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TvmIsContract001.sol"; - String contractName = "testIsContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Protocol.Account info; - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String input = "ac5a3e290000000000000000000000123456789123456789"; - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "testIsContractCommand(address)", input, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8() - .contains("REVERT opcode executed")); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "testIsContractView(address)", input, true, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("FAILED", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("REVERT opcode executed", - transactionExtention.getResult().getMessage().toStringUtf8()); - } - - @Test(enabled = true, description = "Empty addresses hash test isContract Command") - public void test02EmptyAddressHashContract() { - PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TvmIsContract001.sol"; - String contractName = "testIsContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Protocol.Account info; - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String input = "ac5a3e29"; - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "testIsContractCommand(address)", input, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertTrue(infoById.get().getResMessage().toStringUtf8() - .contains("REVERT opcode executed")); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "testIsContractView(address)", input, true, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("FAILED", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("REVERT opcode executed", - transactionExtention.getResult().getMessage().toStringUtf8()); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed.sendcoin(testNetAccountAddress, balance, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/AltbnTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/AltbnTest001.java deleted file mode 100644 index 4324d68104d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/AltbnTest001.java +++ /dev/null @@ -1,161 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.istanbul; - -import static org.tron.protos.Protocol.Transaction.Result.contractResult.OUT_OF_TIME; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class AltbnTest001 { - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private byte[] contractAddress; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed - .sendcoin(testAddress001, 1000_000_000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/altbn.sol"; - String contractName = "AltBn128"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKey001, - testAddress001, blockingStubFull); - } - - @Test(enabled = true, description = "bn256add energyCost reduced from 500 to 150") - public void bn256addTest001() { - - String methodStr = "callBn256Add(bytes32,bytes32,bytes32,bytes32)"; - String data = "" - + "\"0000000000000000000000000000000000000000000000000000000000000001\"," - + "\"0000000000000000000000000000000000000000000000000000000000000002\"," - + "\"0000000000000000000000000000000000000000000000000000000000000001\"," - + "\"0000000000000000000000000000000000000000000000000000000000000002\""; - - logger.info("data: " + data); - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, data, false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - TransactionInfo option = PublicMethed - .getTransactionInfoById(txid, blockingStubFull).get(); - - long energyCost = option.getReceipt().getEnergyUsageTotal(); - logger.info("energyCost: " + energyCost); - - Assert.assertEquals(0,option.getResultValue()); - } - - @Test(enabled = true, description = "bn256add energyCost reduced from 40000 to 6000") - public void bn256ScalarMulTest001() { - String methodStr = "callBn256ScalarMul(bytes32,bytes32,bytes32)"; - String data = "" - + "\"0000000000000000000000000000000000000000000000000000000000000001\"," - + "\"0000000000000000000000000000000000000000000000000000000000000002\"," - + "\"0000000000000000000000000000000000000000000000000000000000000001\""; - - logger.info("data: " + data); - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, data, false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - TransactionInfo option = PublicMethed - .getTransactionInfoById(txid, blockingStubFull).get(); - - long energyCost = option.getReceipt().getEnergyUsageTotal(); - logger.info("energyCost: " + energyCost); - - Assert.assertEquals(0,option.getResultValue()); - Assert.assertTrue(energyCost < 40000L); - Assert.assertTrue(energyCost > 6000L); - } - - @Test(enabled = true, description = "bn256add energyCost reduced from ( 80000 * pairNum + 100000)" - + "to ( 34000 * pairNum + 45000) ") - public void bn256paringTest001() { - String methodStr = "callBn256Pairing(bytes)"; - String data = "" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000180" - + "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59" - + "3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41" - + "209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7" - + "04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678" - + "2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d" - + "120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550" - + "111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c" - + "2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411" - + "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2" - + "1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed" - + "090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b" - + "12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"; - - logger.info("data: " + data); - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, data, true, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - TransactionInfo option = PublicMethed - .getTransactionInfoById(txid, blockingStubFull).get(); - - long energyCost = option.getReceipt().getEnergyUsageTotal(); - logger.info("energyCost: " + energyCost); - if (option.getResultValue() == 1) { - Assert.assertEquals(option.getReceipt().getResult(), OUT_OF_TIME); - return; - } - - Assert.assertEquals(0,option.getResultValue()); - Assert.assertTrue(energyCost < 80000L * 2 + 100000L); - Assert.assertTrue(energyCost > 34000L * 2 + 45000L); - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/ChainidAndSelfBalance001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/ChainidAndSelfBalance001.java deleted file mode 100644 index ef638ec0f58..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/ChainidAndSelfBalance001.java +++ /dev/null @@ -1,158 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.istanbul; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.BlockExtention; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -public class ChainidAndSelfBalance001 { - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private byte[] contractAddress; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed - .sendcoin(testAddress001, 1000_000_000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/chainid001.sol"; - String contractName = "IstanbulTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 123456789L, 100, null, testKey001, - testAddress001, blockingStubFull); - } - - @Test(enabled = true, description = "chainId should be block zero`s Hash") - public void chainidTest001() { - String methodStr = "getId()"; - TransactionExtention returns = PublicMethed - .triggerConstantContractForExtention(contractAddress, methodStr, "#", - false, 0, maxFeeLimit, "0", 0, testAddress001, testKey001, blockingStubFull); - - String chainIdHex = ByteArray.toHexString(returns.getConstantResult(0).toByteArray()); - - BlockExtention blockZero = PublicMethed.getBlock2(0, blockingStubFull); - String tem = ByteArray.toHexString(blockZero.getBlockid().toByteArray()).substring(56); - String blockZeroId = "00000000000000000000000000000000000000000000000000000000" + tem; - - Assert.assertEquals(chainIdHex, blockZeroId); - } - - /* - * New command selfBalance for solidity compiler, - * optimize address.balance when contract`s balance - */ - - @Test(enabled = true, description = "selfBalance of addres(this).balance") - public void getBalanceTest001() { - - String methodStr = "getBalance()"; - String argsStr = ""; - TransactionExtention returns = PublicMethed - .triggerConstantContractForExtention(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, "", 0, testAddress001, testKey001, blockingStubFull); - Long getBalance = ByteArray.toLong(returns.getConstantResult(0).toByteArray()); - - Long contractBalance = PublicMethed - .queryAccount(contractAddress, blockingStubFull).getBalance(); - - Assert.assertEquals(contractBalance, getBalance); - - } - - - @Test(enabled = true, description = "selfBalance of contractAddress") - public void getBalanceTest002() { - - String methodStr = "getBalance(address)"; - String argsStr = "\"" + Base58.encode58Check(contractAddress) + "\""; - TransactionExtention returns = PublicMethed - .triggerConstantContractForExtention(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, "", 0, testAddress001, testKey001, blockingStubFull); - Long getBalance = ByteArray.toLong(returns.getConstantResult(0).toByteArray()); - - Long contractBalance = PublicMethed - .queryAccount(contractAddress, blockingStubFull).getBalance(); - - Assert.assertEquals(contractBalance, getBalance); - - } - - @Test(enabled = true, description = "selfBalance of normal Address") - public void getBalanceTest003() { - String methodStr = "getBalance(address)"; - String argsStr = "\"" + Base58.encode58Check(testFoundationAddress) + "\""; - TransactionExtention returns = PublicMethed - .triggerConstantContractForExtention(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, "", 0, testAddress001, testKey001, blockingStubFull); - Long getBalance = ByteArray.toLong(returns.getConstantResult(0).toByteArray()); - - Long accountBalance = PublicMethed - .queryAccount(testFoundationAddress, blockingStubFull).getBalance(); - - Assert.assertEquals(accountBalance, getBalance); - - } - - @Test(enabled = true, description = "selfBalance of unActive Address") - public void getBalanceTest004() { - String methodStr = "getBalance(address)"; - - byte[] unActiveAddress = new ECKey(Utils.getRandom()).getAddress(); - - String argsStr = "\"" + Base58.encode58Check(unActiveAddress) + "\""; - TransactionExtention returns = PublicMethed - .triggerConstantContractForExtention(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, "", 0, testAddress001, testKey001, blockingStubFull); - Long getBalance = ByteArray.toLong(returns.getConstantResult(0).toByteArray()); - - Assert.assertEquals(0, getBalance.longValue()); - - } - - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/Create2IstanbulTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/Create2IstanbulTest001.java deleted file mode 100644 index 89799615d99..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/istanbul/Create2IstanbulTest001.java +++ /dev/null @@ -1,105 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.istanbul; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -public class Create2IstanbulTest001 { - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private byte[] contractAddress; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed - .sendcoin(testAddress001, 1000_000_000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/create2Istanbul.sol"; - String contractName = "create2Istanbul"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKey001, - testAddress001, blockingStubFull); - } - - /** - * Create2 Algorithm Changed - * Before: according to msg.sender`s Address, salt, bytecode to get create2 Address - * After : according to contract`s Address, salt, bytecode to get create2 Address - * The calculated Create2 address should be same as get(bytes1,bytes,uint256) - */ - - @Test(enabled = true, description = "create2 Algorithm Change") - public void create2IstanbulTest001() { - String filePath = "src/test/resources/soliditycode/create2Istanbul.sol"; - String contractName = "B"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - - String methodStr = "deploy(bytes,uint256)"; - String argStr = "\"" + code + "\"," + "1"; - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, argStr, false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - TransactionInfo option = PublicMethed - .getTransactionInfoById(txid, blockingStubFull).get(); - String returnHex = ByteArray.toHexString(option.getContractResult(0).toByteArray()); - - Assert.assertEquals(0,option.getResultValue()); - - String methodStr2 = "get(bytes1,bytes,uint256)"; - String argStr2 = "\"41\",\"" + code + "\"," + 1; - TransactionExtention returns = PublicMethed - .triggerConstantContractForExtention(contractAddress, methodStr2, argStr2, - false, 0, - maxFeeLimit, "0", 0, testAddress001, testKey001, blockingStubFull); - String getHex = ByteArray.toHexString(returns.getConstantResult(0).toByteArray()); - - Assert.assertEquals(returnHex,getHex); - - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AbiEncodeTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AbiEncodeTest.java deleted file mode 100644 index 8ff57cca43a..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AbiEncodeTest.java +++ /dev/null @@ -1,269 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class AbiEncodeTest { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - @Test(enabled = true, description = "Deploy contract") - public void test01DeployContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1000_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 100_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(dev001Key, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = accountResource.getEnergyUsed(); - Long beforeNetUsed = accountResource.getNetUsed(); - Long beforeFreeNetUsed = accountResource.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/abiencode.sol"; - String contractName = "AbiEncode"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - logger.info("abi:" + abi); - - final String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Protocol.Account infoafter = PublicMethed.queryAccount(dev001Key, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "Trigger contract with ") - public void test02TriggerContract() { - String methodStr = "h(int256[2][])"; - String argStr = "00000000000000000000000000000000000000000000000000000000000000200000000000000" - + "000000000000000000000000000000000000000000000000003000000000000000000000000000000000000" - + "000000000000000000000000000300000000000000000000000000000000000000000000000000000000000" - + "000040000000000000000000000000000000000000000000000000000000000000000000000000000000000" - + "000000000000000000000000000000000000000000006300000000000000000000000000000000000000000" - + "000000000000000000000060000000000000000000000000000000000000000000000000000000000000008"; - String txid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, true, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById.get().getResMessage()); - } - logger.info("infoById" + infoById); - String contractResult = - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals( - "000000000000000000000000000000000000000000000000000000000000002000000000000000000" - + "00000000000000000000000000000000000000000000100000000000000000000000000000000000000" - + "00000000000000000000000000200000000000000000000000000000000000000000000000000000000" - + "00000000300000000000000000000000000000000000000000000000000000000000000030000000000" - + "00000000000000000000000000000000000000000000000000000400000000000000000000000000000" - + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000" - + "00000000000000630000000000000000000000000000000000000000000000000000000000000006000" - + "0000000000000000000000000000000000000000000000000000000000008", - contractResult); - - String methodStr1 = "i(int256[2][2])"; - String argStr1 = "0000000000000000000000000000000000000000000000000000000000000005000000000000" - + "000000000000000000000000000000000000000000000000000700000000000000000000000000000000000" - + "000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000" - + "000065"; - String txid1 = PublicMethed.triggerContract(contractAddress, methodStr1, argStr1, true, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = PublicMethed - .getTransactionInfoById(txid1, blockingStubFull); - if (infoById1.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById1.get().getResMessage()); - } - logger.info("infoById1" + infoById1); - String contractResult1 = - ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()); - Assert.assertEquals( - "000000000000000000000000000000000000000000000000000000000000002000000000000000000" - + "00000000000000000000000000000000000000000000080000000000000000000000000000000000000" - + "00000000000000000000000000050000000000000000000000000000000000000000000000000000000" - + "00000000700000000000000000000000000000000000000000000000000000000000003e80000000000" - + "000000000000000000000000000000000000000000000000000065", - contractResult1); - } - - @Test(enabled = true, description = "Trigger contract with negative number") - public void test03TriggerContract() { - String methodStr = "h(int256[2][])"; - String argStr = "00000000000000000000000000000000000000000000000000000000000000200000000000000" - + "000000000000000000000000000000000000000000000000003ffffffffffffffffffffffffffffffffffff" - + "ffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000" - + "000090000000000000000000000000000000000000000000000000000000000000042ffffffffffffffffff" - + "ffffffffffffffffffffffffffffffffffffffffffffbe00000000000000000000000000000000000000000" - + "000000000000000000000b1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa8"; - String txid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, true, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById.get().getResMessage()); - } - logger.info("infoById" + infoById); - String contractResult = - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals( - "000000000000000000000000000000000000000000000000000000000000002000000000000000000" - + "00000000000000000000000000000000000000000000100000000000000000000000000000000000000" - + "00000000000000000000000000200000000000000000000000000000000000000000000000000000000" - + "000000003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000" - + "00000000000000000000000000000000000000000000000000000900000000000000000000000000000" - + "00000000000000000000000000000000042ffffffffffffffffffffffffffffffffffffffffffffffff" - + "ffffffffffffffbe00000000000000000000000000000000000000000000000000000000000000b1fff" - + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa8", - contractResult); - - String methodStr1 = "i(int256[2][2])"; - String argStr1 = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000" - + "000000000000000000000000000000000000000000000000000900000000000000000000000000000000000" - + "00000000000000000000000000042ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - + "ffffbe"; - String txid1 = PublicMethed.triggerContract(contractAddress, methodStr1, argStr1, true, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = PublicMethed - .getTransactionInfoById(txid1, blockingStubFull); - if (infoById1.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById1.get().getResMessage()); - } - logger.info("infoById1" + infoById1); - String contractResult1 = - ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()); - Assert.assertEquals( - "00000000000000000000000000000000000000000000000000000000000000200000000000000000" - + "000000000000000000000000000000000000000000000080ffffffffffffffffffffffffffffffffff" - + "ffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000" - + "0000000000090000000000000000000000000000000000000000000000000000000000000042ffffff" - + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffbe", - contractResult1); - } - - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - PublicMethed.sendcoin(fromAddress, balance, dev001Address, dev001Key, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AbstractTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AbstractTest.java deleted file mode 100644 index e0f163a6362..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AbstractTest.java +++ /dev/null @@ -1,78 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class AbstractTest { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "compile abstract contract 001") - public void test01CompileAbstractContract001() { - String filePath = "./src/test/resources/soliditycode/abstract001.sol"; - String contractName = "abstract001"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - Assert.assertTrue(abi.length() > 0); - Assert.assertTrue(code.length() == 0); - } - - @Test(enabled = true, description = "compile abstract contract 002") - public void test02CompileAbstractContract002() { - String filePath = "./src/test/resources/soliditycode/abstract002.sol"; - String contractName = "abstract002"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - Assert.assertTrue(abi.length() > 0); - Assert.assertTrue(code.length() == 0); - } - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AddressChange.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AddressChange.java deleted file mode 100644 index 60f7f27a19e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AddressChange.java +++ /dev/null @@ -1,149 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class AddressChange { - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - byte[] contractAddressOld = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - PublicMethed - .sendcoin(contractExcAddress, 1000_000_000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/getAddressChange.sol"; - String contractName = "getAddressChange"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_getAddressChange"); - code = Configuration.getByPath("testng.conf") - .getString("code.code_getAddressChange"); - contractName = "getAddressChangeOldVersion"; - contractAddressOld = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "get external function address") - public void test01GetExternalAddress() { - String txid = ""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testaddress1()", "#", false, 0, 0, - "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - byte[] b1 = new byte[21]; - b1[0] = 0x41; - System.arraycopy(result, 12, b1, 1, 20); - Assert.assertEquals(Base58.encode58Check(contractAddress), Base58.encode58Check(b1)); - } - - @Test(enabled = true, description = "get external function address, solidity version < 0.6.0") - public void test02GetExternalAddressOldVersion() { - String txid = ""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddressOld, "testaddress1()", "#", false, 0, 0, - "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - byte[] b1 = new byte[21]; - b1[0] = 0x41; - System.arraycopy(result, 12, b1, 1, 20); - Assert.assertEquals(Base58.encode58Check(contractAddressOld), Base58.encode58Check(b1)); - } - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - PublicMethed - .freedResource(contractAddressOld, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AssignToExternalTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AssignToExternalTest.java deleted file mode 100644 index 9ec27a7d473..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/AssignToExternalTest.java +++ /dev/null @@ -1,249 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class AssignToExternalTest { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - @Test(enabled = true, description = "Deploy contract") - public void test01DeployContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1000_000_000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(dev001Key, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = accountResource.getEnergyUsed(); - Long beforeNetUsed = accountResource.getNetUsed(); - Long beforeFreeNetUsed = accountResource.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/AssignToExternal.sol"; - String contractName = "AssignToExternal"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Protocol.Account infoafter = PublicMethed.queryAccount(dev001Key, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "Trigger contract with ") - public void test02TriggerContract() { - String methodStr = "f(uint256)"; - String argStr = "2"; - String txid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById.get().getResMessage()); - } - logger.info("infoById" + infoById); - int contractResult = - ByteArray.toInt(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals(3, contractResult); - } - - @Test(enabled = true, description = "Trigger contract with ") - public void test03TriggerContract() { - String methodStr = "StringSet(string)"; - String argStr = "\"test\""; - String txid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById.get().getResMessage()); - } - logger.info("infoById" + infoById); - String contractResult = - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000004" - + "7465737400000000000000000000000000000000000000000000000000000000", contractResult); - } - - @Test(enabled = true, description = "Trigger contract with ") - public void test04TriggerContract() { - String methodStr = "ByteSet(bytes32)"; - String argStr = "00000000000000000000000000000000000000000000000000000000000003e9"; - String txid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, true, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById.get().getResMessage()); - } - logger.info("infoById" + infoById); - int contractResult = - ByteArray.toInt(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals(1001, contractResult); - } - - @Test(enabled = true, description = "Trigger contract with ") - public void test05TriggerContract() { - String methodStr = "UintArraySet(uint256[2])"; - String argStr = "00000000000000000000000000000000000000000000000000000000000003e9" - + "00000000000000000000000000000000000000000000000000000000000003e9"; - String txid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, true, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById.get().getResMessage()); - } - logger.info("infoById" + infoById); - String contractResult = - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals("00000000000000000000000000000000000000000000000000000000000003e9" - + "00000000000000000000000000000000000000000000000000000000000003e9", contractResult); - } - - @Test(enabled = true, description = "Trigger contract with ") - public void test06TriggerContract() { - String methodStr = "AddSet(address)"; - String argStr = "\"TYVT8YJYis13NdrzdE7yVuwVxjsaRy2UsM\""; - String txid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById.get().getResMessage()); - } - logger.info("infoById" + infoById); - String contractResult = - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals("000000000000000000000000f70b0a56acf4b0af44723c329ff113a677b5f589", - contractResult); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - PublicMethed.sendcoin(fromAddress, balance, dev001Address, dev001Key, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/BlockhashTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/BlockhashTest.java deleted file mode 100644 index c4d47afd163..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/BlockhashTest.java +++ /dev/null @@ -1,170 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class BlockhashTest { - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "./src/test/resources/soliditycode/BlockHash.sol"; - String contractName = "TestBlockHash"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "BlockHash should not be change after command OR") - public void test01BlockHashWithOR() { - String methodStr = "testOR1(bytes32)"; - String argStr = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; - String txid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, true, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - String ContractResult = ByteArray.toHexString(infoById.get() - .getContractResult(0).toByteArray()); - // 3 bytes32 - Assert.assertEquals(192, ContractResult.length()); - // blockHash before OR should equals to blockHash after OR - Assert.assertEquals(ContractResult.substring(0,64),ContractResult.substring(128)); - - methodStr = "testOR2(bytes32)"; - txid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, true, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - ContractResult = ByteArray.toHexString(infoById.get() - .getContractResult(0).toByteArray()); - // 3 bytes32 - Assert.assertEquals(192, ContractResult.length()); - // blockHash before OR should equals to blockHash after OR - Assert.assertEquals(ContractResult.substring(0,64),ContractResult.substring(128)); - } - - @Test(enabled = true, description = "BlockHash should not be change after command AND") - public void test02BlockHashWithAND() { - String methodStr = "testAND1(bytes32)"; - String argStr = "0000000000000000000000000000000000000000000000000000000000000000"; - String txid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, true, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - String ContractResult = ByteArray.toHexString(infoById.get() - .getContractResult(0).toByteArray()); - // 3 bytes32 - Assert.assertEquals(192, ContractResult.length()); - // blockHash before AND should equals to blockHash after AND - Assert.assertEquals(ContractResult.substring(0,64),ContractResult.substring(128)); - - methodStr = "testAND2(bytes32)"; - txid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, true, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - ContractResult = ByteArray.toHexString(infoById.get() - .getContractResult(0).toByteArray()); - // 3 bytes32 - Assert.assertEquals(192, ContractResult.length()); - // blockHash before AND should equals to blockHash after AND - Assert.assertEquals(ContractResult.substring(0,64),ContractResult.substring(128)); - } - - @Test(enabled = true, description = "BlockHash should not be change after command XOR") - public void test03BlockHashWithXOR() { - String methodStr = "testXOR1(bytes32)"; - String argStr = "00000000000000000000000000000000ffffffffffffffffffffffffffffffff"; - String txid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, true, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - String ContractResult = ByteArray.toHexString(infoById.get() - .getContractResult(0).toByteArray()); - // 3 bytes32 - Assert.assertEquals(192, ContractResult.length()); - // blockHash before XOR should equals to blockHash after XOR - Assert.assertEquals(ContractResult.substring(0,64),ContractResult.substring(128)); - - methodStr = "testXOR2(bytes32)"; - txid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, true, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - ContractResult = ByteArray.toHexString(infoById.get() - .getContractResult(0).toByteArray()); - // 3 bytes32 - Assert.assertEquals(192, ContractResult.length()); - // blockHash before XOR should equals to blockHash after XOR - Assert.assertEquals(ContractResult.substring(0,64),ContractResult.substring(128)); - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/CallValueGasPureTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/CallValueGasPureTest.java deleted file mode 100644 index df5befec7d8..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/CallValueGasPureTest.java +++ /dev/null @@ -1,136 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class CallValueGasPureTest { - - private final String foundationKey001 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] foundationAddress001 = PublicMethed.getFinalAddress(foundationKey001); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] testAddress001 = ecKey1.getAddress(); - private String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(testKey001); - } - - @Test(enabled = true, description = "call.value.gas be pure") - public void test01DeployContract() { - Assert.assertTrue(PublicMethed - .sendcoin(testAddress001, 1000_000_000L, foundationAddress001, foundationKey001, - blockingStubFull)); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(foundationAddress001, 100_000_000L, 0, 0, - ByteString.copyFrom(testAddress001), foundationKey001, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed - .getAccountResource(testAddress001, blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(testKey001, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = accountResource.getEnergyUsed(); - Long beforeNetUsed = accountResource.getNetUsed(); - Long beforeFreeNetUsed = accountResource.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/callValueGasPure.sol"; - String contractName = "C"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 0, - 10000, "0", 0, null, testKey001, testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - String param = "\"" + Base58.encode58Check(testAddress001) + "\""; - TransactionExtention extention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "check(address)", - param, false, 0, 1000000000L, "0", 0, testAddress001, - testKey001, blockingStubFull); - - Assert.assertNotNull(extention); - Assert.assertTrue(extention.hasResult()); - Assert.assertTrue(extention.getResult().getResult()); - - } - - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(testKey001, blockingStubFull).getBalance(); - PublicMethed - .sendcoin(foundationAddress001, balance, testAddress001, testKey001, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/CallvalueTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/CallvalueTest.java deleted file mode 100644 index bb139eccc16..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/CallvalueTest.java +++ /dev/null @@ -1,205 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class CallvalueTest { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - @Test(enabled = true, description = "Deploy contract") - public void test01DeployContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 3147483647L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 100_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(dev001Key, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = accountResource.getEnergyUsed(); - Long beforeNetUsed = accountResource.getNetUsed(); - Long beforeFreeNetUsed = accountResource.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/callvalue.sol"; - String contractName = "Callvalue"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Protocol.Account infoafter = PublicMethed.queryAccount(dev001Key, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "Trigger contract") - public void test02TriggerContract() { - String methodStr = "check()"; - // 15 - String triggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, "", true, - 15, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById.get().getResMessage()); - } - logger.info("infoById" + infoById); - String contractResult = - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()); - logger.info("contractResult:" + contractResult); - Assert.assertEquals(Long.parseLong(contractResult, 16), 15); - - // 0 - String triggerTxid1 = PublicMethed.triggerContract(contractAddress, methodStr, "", true, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = PublicMethed - .getTransactionInfoById(triggerTxid1, blockingStubFull); - if (infoById1.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById1.get().getResMessage()); - } - logger.info("infoById1" + infoById1); - String contractResult1 = - ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()); - logger.info("contractResult1:" + contractResult1); - Assert.assertEquals(Long.parseLong(contractResult1, 16), 0); - - // Integer.MAX_VALUE - String triggerTxid2 = PublicMethed.triggerContract(contractAddress, methodStr, "", true, - Integer.MAX_VALUE, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById2 = PublicMethed - .getTransactionInfoById(triggerTxid2, blockingStubFull); - if (infoById2.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById2.get().getResMessage()); - } - logger.info("infoById2" + infoById2); - String contractResult2 = - ByteArray.toHexString(infoById2.get().getContractResult(0).toByteArray()); - logger.info("contractResult2:" + contractResult2); - Assert.assertEquals(Long.parseLong(contractResult2, 16), Integer.MAX_VALUE); - } - - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - PublicMethed.sendcoin(fromAddress, balance, dev001Address, dev001Key, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage001.java deleted file mode 100644 index 4d49194477c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage001.java +++ /dev/null @@ -1,255 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ConstantCallStorage001 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerconstantContract trigger modidy storage date") - public void testConstantCallStorage001() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/constantCallStorage001.sol"; - String contractName = "NotView"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, "[]", code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - //Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "setnum()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - logger.info("transactionExtention: " + transactionExtention); - Assert.assertTrue(transactionExtention.getResult().getResult()); - Assert.assertEquals(138, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - logger.info("transactionExtention: " + transactionExtention); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "num()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertTrue(transactionExtention.getResult().getResult()); - Assert.assertEquals(123, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - } - - @Test(enabled = false, description = "TriggerconstantContract storage date by another contract ") - public void testConstantCallStorage002() { - - String filePath = "src/test/resources/soliditycode/constantCallStorage001.sol"; - String contractName = "UseNotView"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] contractAddress002 = PublicMethed - .deployContract(contractName, "[]", code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress002, blockingStubFull); - //Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress002, - "setnumuseproxy(address)", "\"" + WalletClient.encode58Check(contractAddress) + "\"", - false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - logger.info("transactionExtention: " + transactionExtention); - Assert.assertEquals(138, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "num()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertTrue(transactionExtention.getResult().getResult()); - Assert.assertEquals(123, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - } - - - @Test(enabled = false, description = "TriggerconstantContract storage date by another contract " - + "view function, use 0.5.* version solidity complier") - public void testConstantCallStorage003() { - String filePath = "src/test/resources/soliditycode/constantCallStorage002.sol"; - String contractName = "UseNotView"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] contractAddress002 = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress002, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress002, - "setnumuseproxy(address)", "\"" + WalletClient.encode58Check(contractAddress) + "\"", - false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - logger.info("transactionExtention: " + transactionExtention); - Assert.assertFalse(transactionExtention.getResult().getResult()); - Assert.assertThat(ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray()), - containsString("Not enough energy")); - } - - - @Test(enabled = false, description = "TriggerconstantContract storage date by another contract " - + "view function, use 0.4.* version solidity complier") - public void testConstantCallStorage004() { - String filePath = "src/test/resources/soliditycode/constantCallStorage002.sol"; - String contractName = "UseNotView"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] contractAddress002 = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress002, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress002, - "setnumuseproxy(address)", "\"" + WalletClient.encode58Check(contractAddress) + "\"", - false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - logger.info("transactionExtention: " + transactionExtention); - Assert.assertEquals(138, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "num()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertTrue(transactionExtention.getResult().getResult()); - Assert.assertEquals(123, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage002.java deleted file mode 100644 index fff67eb8a0d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage002.java +++ /dev/null @@ -1,421 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ConstantCallStorage002 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerconstantContract trigger modidy storage date with " - + "difference date type") - public void testConstantCallStorage001() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/constantCallStorage001.sol"; - String contractName = "viewCall"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, "[]", code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - // modify bool type - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "changeBool(bool)", "true", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(1, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "getBool()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(0, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - // modify NegativeInt type - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "changeNegativeInt(int256)", "-2", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(-2, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "getNegativeInt()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(-32482989, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - // modify address type - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "changeAddress(address)", "\"" + WalletClient.encode58Check(contractAddress) + "\"", - false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - String ContractResult = - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - String tmpAddress = - Base58.encode58Check(ByteArray.fromHexString("41" + ContractResult.substring(24))); - Assert.assertEquals(WalletClient.encode58Check(contractAddress), tmpAddress); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "getAddress()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("000000000000000000000000dcad3a6d3569df655070ded06cb7a1b2ccd1d3af", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - - // modify byte32s type - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "changeBytes32(bytes32)", "\"0xdCad3a6d3569DF655070DEd1\"", - false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("dcad3a6d3569df655070ded10000000000000000000000000000000000000000", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "getBytes32()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("0000000000000000000000000000000000000000dcad3a6d3569df655070ded0", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - - // modify bytes type - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "changeBytes(bytes)", "\"0x05\"", - false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "0500000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "getBytes()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000003" - + "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - - // modify string type - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "changeString(string)", "\"321test\"", - false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("321test", - ByteArray.toStr(transactionExtention - .getConstantResult(0).substring(64, 64 + 7).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "getString()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("123qwe", - ByteArray.toStr(transactionExtention - .getConstantResult(0).substring(64, 64 + 6).toByteArray())); - - // modify enum type - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "changeActionChoices(uint8)", "3", - false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(3, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "getActionChoices()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(1, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - // modify Int64NegativeArray type - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "changeInt64NegativeArray(int64[])", - "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "0000000000000000000000000000000000000000000000000000000000000003" - + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - true, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "0000000000000000000000000000000000000000000000000000000000000003" - + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - ByteArray.toHexString(transactionExtention - .getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "getInt64NegativeArray()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000003" - + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", - ByteArray.toHexString(transactionExtention - .getConstantResult(0).toByteArray())); - - // modify Int32Array[2][] type - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "changeInt32Array(int32[2][])", - "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000005" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "0000000000000000000000000000000000000000000000000000000000000003" - + "0000000000000000000000000000000000000000000000000000000000000004" - + "0000000000000000000000000000000000000000000000000000000000000005" - + "0000000000000000000000000000000000000000000000000000000000000006" - + "0000000000000000000000000000000000000000000000000000000000000007" - + "0000000000000000000000000000000000000000000000000000000000000008" - + "0000000000000000000000000000000000000000000000000000000000000009" - + "000000000000000000000000000000000000000000000000000000000000000a", - true, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000005" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "0000000000000000000000000000000000000000000000000000000000000003" - + "0000000000000000000000000000000000000000000000000000000000000004" - + "0000000000000000000000000000000000000000000000000000000000000005" - + "0000000000000000000000000000000000000000000000000000000000000006" - + "0000000000000000000000000000000000000000000000000000000000000007" - + "0000000000000000000000000000000000000000000000000000000000000008" - + "0000000000000000000000000000000000000000000000000000000000000009" - + "000000000000000000000000000000000000000000000000000000000000000a", - ByteArray.toHexString(transactionExtention - .getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "getInt32Array()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000003" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "0000000000000000000000000000000000000000000000000000000000000003" - + "0000000000000000000000000000000000000000000000000000000000000004" - + "0000000000000000000000000000000000000000000000000000000000000005" - + "0000000000000000000000000000000000000000000000000000000000000006", - ByteArray.toHexString(transactionExtention - .getConstantResult(0).toByteArray())); - - // modify Int256Array[2][2] type - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "changeInt256Array(int256[2][2])", - - "0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "0000000000000000000000000000000000000000000000000000000000000003" - + "0000000000000000000000000000000000000000000000000000000000000004", - true, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "0000000000000000000000000000000000000000000000000000000000000003" - + "0000000000000000000000000000000000000000000000000000000000000004", - ByteArray.toHexString(transactionExtention - .getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "getInt256Array()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals( - "000000000000000000000000000000000000000000000000000000000000000b" - + "0000000000000000000000000000000000000000000000000000000000000016" - + "0000000000000000000000000000000000000000000000000000000000000021" - + "000000000000000000000000000000000000000000000000000000000000002c", - ByteArray.toHexString(transactionExtention - .getConstantResult(0).toByteArray())); - - // modify mapping type - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "setMapping(uint256)", "55", - false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(55, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "mapa(address)", "\"T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb\"", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(34, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - } - - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage0425.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage0425.java deleted file mode 100644 index b36b257d678..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/ConstantCallStorage0425.java +++ /dev/null @@ -1,462 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ConstantCallStorage0425 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = false) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1000_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 100_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = false, description = "Deploy contract without abi") - public void test01DeployContract() { - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(dev001Key, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = accountResource.getEnergyUsed(); - Long beforeNetUsed = accountResource.getNetUsed(); - Long beforeFreeNetUsed = accountResource.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/constantCallStorage0425.sol"; - String contractName = "constantCall"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, "[]", code, "", - maxFeeLimit, 0L, 0, 1000000000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Protocol.Account infoafter = PublicMethed.queryAccount(dev001Key, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = false, description = "Trigger contract constant function without ABI") - public void test02TriggerContract() { - String triggerTxid = PublicMethed - .triggerContract(contractAddress, "changeBool(bool)", "true", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(1, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(1, ByteArray.toInt(infoById.get().getLog(0).getData().toByteArray())); - - String triggerTxid2 = PublicMethed - .triggerContract(contractAddress, "getBool()", "", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = PublicMethed - .getTransactionInfoById(triggerTxid2, blockingStubFull); - Assert.assertEquals(0, infoById1.get().getResultValue()); - Assert.assertEquals(1, ByteArray.toInt(infoById1.get().getContractResult(0).toByteArray())); - Assert.assertEquals(1, ByteArray.toInt(infoById1.get().getLog(0).getData().toByteArray())); - } - - @Test(enabled = false, description = "TriggerConstantContract bool constant function") - public void test03TriggerConstantContract() { - // bool - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "changeBool(bool)", "false", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert - .assertEquals(0, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getBool()", "", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert - .assertEquals(1, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - // int - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "changeInt(int256)", "30", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert - .assertEquals(30, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getInt()", "", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(32482989, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - // negative int - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "changeNegativeInt(int256)", "-111", - false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert - .assertEquals(-111, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getNegativeInt()", "", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert - .assertEquals(-32482989, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - // uint - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "changeUint(uint256)", "1024", false, - 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert - .assertEquals(1024, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getUint()", "", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert - .assertEquals(23487823, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - // address - String param = "\"" + Base58.encode58Check(dev001Address) + "\""; - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "changeAddress(address)", param, - false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - byte[] tmpAddress = new byte[20]; - System - .arraycopy(transactionExtention.getConstantResult(0).toByteArray(), 12, tmpAddress, 0, 20); - Assert.assertEquals(Base58.encode58Check(dev001Address), - Base58.encode58Check(ByteArray.fromHexString("41" + ByteArray.toHexString(tmpAddress)))); - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getAddress()", "", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - tmpAddress = new byte[20]; - System - .arraycopy(transactionExtention.getConstantResult(0).toByteArray(), 12, tmpAddress, 0, 20); - Assert.assertEquals("TW63BNR5M7LuH1fjXS7Smyza3PZXfHAAs2", - Base58.encode58Check(ByteArray.fromHexString("41" + ByteArray.toHexString(tmpAddress)))); - - // bytes32 - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "changeBytes32(bytes32)", - "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a", - true, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getBytes32()", "", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105c", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - - // bytes - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "changeBytes(bytes)", "\"0x06\"", - false, - 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals( - "0000000000000000000000000000000000000000000000000000000000000020000000000000000000" - + "000000000000000000000000000000000000000000000106000000000000000000000000000000000000" - + "00000000000000000000000000", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getBytes()", "", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals( - "0000000000000000000000000000000000000000000000000000000000000020000000000000000000" - + "000000000000000000000000000000000000000000000900000000000000000000000000000000000000" - + "00000000000000000000000000", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - - // string - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "changeString(string)", - "\"1q2w\"", - false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("000000000000000000000000000000000000000000000000000000000000002000" - + "000000000000000000000000000000000000000000000000000000000000043171327700000000000000" - + "000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getString()", "", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("000000000000000000000000000000000000000000000000000000000000002000" - + "000000000000000000000000000000000000000000000000000000000000063132337177650000000000" - + "000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - - // enum - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "changeActionChoices(uint8)", - "1", - false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getActionChoices()", "", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000003", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - - // int64[] include negative number - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "changeInt64NegativeArray(int64[])", - "0000000000000000000000000000000000000000000000000000000000000020000000000000000" - + "00000000000000000000000000000000000000000000000040000000000000000000000000000000" - + "00000000000000000000000000000000b00000000000000000000000000000000000000000000000" - + "00000000000000063000000000000000000000000000000000000000000000000000000000000004" - + "1000000000000000000000000000000000000000000000000000000000000005a", - true, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("000000000000000000000000000000000000000000000000000000000000002000" - + "000000000000000000000000000000000000000000000000000000000000040000000000000000000000" - + "00000000000000000000000000000000000000000b000000000000000000000000000000000000000000" - + "000000000000000000006300000000000000000000000000000000000000000000000000000000000000" - + "41000000000000000000000000000000000000000000000000000000000000005a", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getInt64NegativeArray()", "", false, - 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("000000000000000000000000000000000000000000000000000000000000002000" - + "000000000000000000000000000000000000000000000000000000000000030000000000000000000000" - + "00000000000000000000000000000000000000005b000000000000000000000000000000000000000000" - + "000000000000000000000200000000000000000000000000000000000000000000000000000000000001" - + "4d", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - - // int32[2][] - String argsStr = - "0000000000000000000000000000000000000000000000000000000000000020000000000000000" - + "00000000000000000000000000000000000000000000000030000000000000000000000000000000" - + "00000000000000000000000000000000d00000000000000000000000000000000000000000000000" - + "00000000000000058fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - + "70000000000000000000000000000000000000000000000000000000000000022000000000000000" - + "0000000000000000000000000000000000000000000000063fffffffffffffffffffffffffffffff" - + "fffffffffffffffffffffffffffffffc8"; - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "changeInt32Array(int32[2][])", - argsStr, true, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(argsStr, - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getInt32Array()", "", false, - 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("000000000000000000000000000000000000000000000000000000000000002000" - + "000000000000000000000000000000000000000000000000000000000000030000000000000000000000" - + "000000000000000000000000000000000000000001000000000000000000000000000000000000000000" - + "000000000000000000000200000000000000000000000000000000000000000000000000000000000000" - + "030000000000000000000000000000000000000000000000000000000000000004000000000000000000" - + "000000000000000000000000000000000000000000000500000000000000000000000000000000000000" - + "00000000000000000000000006", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - - // int256[2][2] - String argsStr1 = - "0000000000000000000000000000000000000000000000000000000000000013000000000000000" - + "00000000000000000000000000000000000000000000000440000000000000000000000000000000" - + "000000000000000000000000000000037fffffffffffffffffffffffffffffffffffffffffffffff" - + "fffffffffffffffde"; - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "changeInt256Array(int256[2][2])", - argsStr1, true, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(argsStr1, - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getInt256Array()", "", false, - 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("000000000000000000000000000000000000000000000000000000000000000b00" - + "000000000000000000000000000000000000000000000000000000000000160000000000000000000000" - + "000000000000000000000000000000000000000021000000000000000000000000000000000000000000" - + "000000000000000000002c", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - - // modify mapping type - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "setMapping(uint256)", "39", - false, - 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(39, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "mapa(address)", "\"T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb\"", false, - 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(88, - ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - } - - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - PublicMethed.sendcoin(fromAddress, balance, dev001Address, dev001Key, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/EthGrammer.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/EthGrammer.java deleted file mode 100644 index 887d94dc351..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/EthGrammer.java +++ /dev/null @@ -1,539 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.contract.SmartContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - - - -@Slf4j -public class EthGrammer { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witness001Address = PublicMethed.getFinalAddress(witnessKey001); - byte[] contractC = null; - byte[] contractD = null; - byte[] create2Address; - String create2Str; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 300100_000_000L, - testNetAccountAddress, testNetAccountKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/EthGrammer.sol"; - String contractName = "C"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractC = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 500000000L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContractOuterClass.SmartContract smartContract = PublicMethed.getContract(contractC, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - contractName = "D"; - retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - code = retMap.get("byteCode").toString(); - abi = retMap.get("abI").toString(); - contractD = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 500000000L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - smartContract = PublicMethed.getContract(contractD, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - - @Test(enabled = true, description = "test get base fee value = commit.No 11 energy fee") - public void test01baseFee() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractC, - "baseFee()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - long basefee = ByteArray.toLong(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("basefee: " + basefee); - long energyfee; - Protocol.ChainParameters chainParameters = blockingStubFull - .getChainParameters(GrpcAPI.EmptyMessage.newBuilder().build()); - Optional getChainParameters = Optional.ofNullable(chainParameters); - logger.info(Long.toString(getChainParameters.get().getChainParameterCount())); - String key = ""; - boolean flag = false; - for (Integer i = 0; i < getChainParameters.get().getChainParameterCount(); i++) { - key = getChainParameters.get().getChainParameter(i).getKey(); - if ("getEnergyFee".equals(key)) { - energyfee = getChainParameters.get().getChainParameter(i).getValue(); - logger.info("energyfee: " + energyfee); - Assert.assertEquals(basefee, energyfee); - flag = true; - } - } - Assert.assertTrue(flag); - } - - @Test(enabled = true, description = "test get gas price value = commit.No 11 energy fee") - public void test02GasPrice() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractC, - "gasPrice()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - - @Test(enabled = true, description = "get create2 address, test get base fee ") - public void test03BaseFeeFromCreate2() { - String methedStr = "deploy(uint256)"; - String argsStr = "1"; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - info.get().getReceipt().getResult()); - - String create2Str = - "41" + ByteArray.toHexString(info.get().getContractResult(0).toByteArray()) - .substring(24); - logger.info("hex create2 address: " + create2Str); - create2Address = ByteArray.fromHexString(create2Str); - logger.info("create2Address: " + Base58.encode58Check(create2Address)); - - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(create2Address, - "baseFeeOnly()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - long basefee = ByteArray.toLong(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("basefee: " + basefee); - long energyfee; - Protocol.ChainParameters chainParameters = blockingStubFull - .getChainParameters(GrpcAPI.EmptyMessage.newBuilder().build()); - Optional getChainParameters = Optional.ofNullable(chainParameters); - logger.info(Long.toString(getChainParameters.get().getChainParameterCount())); - String key = ""; - boolean flag = false; - for (Integer i = 0; i < getChainParameters.get().getChainParameterCount(); i++) { - key = getChainParameters.get().getChainParameter(i).getKey(); - if ("getEnergyFee".equals(key)) { - energyfee = getChainParameters.get().getChainParameter(i).getValue(); - logger.info("energyfee: " + energyfee); - Assert.assertEquals(basefee, energyfee); - flag = true; - } - } - Assert.assertTrue(flag); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(create2Address, - "gasPriceOnly()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - long gasprice = ByteArray.toLong(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("gasprice: " + gasprice); - Assert.assertEquals(basefee, gasprice); - } - - @Test(enabled = true, description = "call can use 63/64 energy in new contract") - public void test04CallEnergy() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] transferToAddress = ecKey1.getAddress(); - String transferToKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.printAddress(transferToKey); - - Long temMaxLimitFee = 200000000L; - String methedStr = "testCall(address,address)"; - String argsStr = "\"" + Base58.encode58Check(contractD) + "\"," + "\"" - + Base58.encode58Check(transferToAddress) + "\""; - String txid = PublicMethed.triggerContract(contractC, methedStr, argsStr, - false, 0, temMaxLimitFee, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Protocol.Account testAccount = - PublicMethed.queryAccountByAddress(transferToAddress, blockingStubFull); - logger.info("testAccount: " + testAccount.toString()); - Assert.assertEquals(1, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.REVERT, - info.get().getReceipt().getResult()); - Assert.assertTrue(info.get().getInternalTransactions(0).getRejected()); - Assert.assertTrue(info.get().getReceipt().getEnergyFee() < temMaxLimitFee); - } - - @Test(enabled = true, description = "create2 address call can use 63/64 energy in new contract") - public void test05Create2AddressCallEnergy() { - String methedStr = "deploy(uint256)"; - String argsStr = "2"; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - info.get().getReceipt().getResult()); - - String create2Str = - "41" + ByteArray.toHexString(info.get().getContractResult(0).toByteArray()) - .substring(24); - logger.info("hex create2 address: " + create2Str); - create2Address = ByteArray.fromHexString(create2Str); - logger.info("create2Address: " + Base58.encode58Check(create2Address)); - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] transferToAddress = ecKey1.getAddress(); - String transferToKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.printAddress(transferToKey); - - Long temMaxLimitFee = 200000000L; - methedStr = "testCall(address,address)"; - argsStr = "\"" + Base58.encode58Check(contractD) + "\"," + "\"" - + Base58.encode58Check(transferToAddress) + "\""; - txid = PublicMethed.triggerContract(create2Address, methedStr, argsStr, - false, 0, temMaxLimitFee, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - info = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - Protocol.Account testAccount = - PublicMethed.queryAccountByAddress(transferToAddress, blockingStubFull); - Assert.assertEquals("", testAccount.toString()); - Assert.assertEquals(1, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.REVERT, - info.get().getReceipt().getResult()); - Assert.assertTrue(info.get().getInternalTransactions(0).getRejected()); - Assert.assertTrue(info.get().getReceipt().getEnergyFee() < temMaxLimitFee); - } - - @Test(enabled = true, description = "create2 address delegatecall " - + "can use 63/64 energy in new contract") - public void test06Create2AddressDelegateCallEnergy() { - String methedStr = "deploy(uint256)"; - String argsStr = "5"; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - info.get().getReceipt().getResult()); - - String create2Str = - "41" + ByteArray.toHexString(info.get().getContractResult(0).toByteArray()) - .substring(24); - logger.info("hex create2 address: " + create2Str); - create2Address = ByteArray.fromHexString(create2Str); - logger.info("create2Address: " + Base58.encode58Check(create2Address)); - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] transferToAddress = ecKey1.getAddress(); - String transferToKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.printAddress(transferToKey); - - Long temMaxLimitFee = 200000000L; - methedStr = "testDelegateCall(address,address)"; - argsStr = "\"" + Base58.encode58Check(contractD) + "\"," + "\"" - + Base58.encode58Check(transferToAddress) + "\""; - txid = PublicMethed.triggerContract(create2Address, methedStr, argsStr, - false, 0, temMaxLimitFee, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - info = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - Protocol.Account testAccount = - PublicMethed.queryAccountByAddress(transferToAddress, blockingStubFull); - Assert.assertEquals("", testAccount.toString()); - Assert.assertEquals(1, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.REVERT, - info.get().getReceipt().getResult()); - Assert.assertTrue(info.get().getInternalTransactions(0).getRejected()); - Assert.assertTrue(info.get().getReceipt().getEnergyFee() < temMaxLimitFee); - } - - @Test(enabled = true, description = "create2 address this.function " - + "can use 63/64 energy in new contract") - public void test07Create2AddressCallFunctionEnergy() { - String methedStr = "deploy(uint256)"; - String argsStr = "6"; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - info.get().getReceipt().getResult()); - - String create2Str = - "41" + ByteArray.toHexString(info.get().getContractResult(0).toByteArray()) - .substring(24); - logger.info("hex create2 address: " + create2Str); - create2Address = ByteArray.fromHexString(create2Str); - logger.info("create2Address: " + Base58.encode58Check(create2Address)); - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] transferToAddress = ecKey1.getAddress(); - String transferToKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.printAddress(transferToKey); - - Long temMaxLimitFee = 200000000L; - methedStr = "testCallFunctionInContract(address)"; - argsStr = "\"" + Base58.encode58Check(transferToAddress) + "\""; - txid = PublicMethed.triggerContract(create2Address, methedStr, argsStr, - false, 0, temMaxLimitFee, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - info = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - Protocol.Account testAccount = - PublicMethed.queryAccountByAddress(transferToAddress, blockingStubFull); - Assert.assertEquals("", testAccount.toString()); - Assert.assertEquals(1, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.REVERT, - info.get().getReceipt().getResult()); - Assert.assertTrue(info.get().getInternalTransactions(0).getRejected()); - Assert.assertTrue(info.get().getReceipt().getEnergyFee() < temMaxLimitFee); - } - - // - @Test(enabled = true, description = "test get Ripemd160 input is 123") - public void test08getRipemd160() { - String args = "\"123\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractC, - "getRipemd160(string)", args, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - String result = ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("e3431a8e0adbf96fd140103dc6f63a3f8fa343ab000000000000000000000000", result); - } - - @Test(enabled = true, description = "test get Ripemd160 input is empty") - public void test09getRipemd160() { - String args = "\"\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractC, - "getRipemd160(string)", args, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - String result = ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("9c1185a5c5e9fc54612808977ee8f548b2258d31000000000000000000000000", result); - } - - @Test(enabled = true, description = "test get Ripemd160 input length is greater than 256") - public void test10getRipemd160() { - String args = "\"111111111111ddddddddddddd0x0000000000000000000000008b56a0602cc81fb0" - + "b99bce992b3198c0bab181ac111111111111ddddddddddddd0x0000000000000000000000008b56" - + "a0602cc81fb0b99bce992b3198c0bab181ac%^$#0000008b56a0602cc81fb0b99bce99" - + "2b3198c0bab181ac%^$#0000008b56a0602cc81fb0b99bce992b3198c0bab181ac%^$#\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractC, - "getRipemd160(string)", args, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - String result = ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("173c283ebcbad0e1c623a5c0f6813cb663338369000000000000000000000000", result); - } - - @Test(enabled = true, description = "test get Ripemd160 input is string " - + "and do not convert to bytes") - public void test11getRipemd160Str() { - String args = "\"data\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractC, - "getRipemd160Str(string)", args, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - String result = ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("cd43325b85172ca28e96785d0cb4832fd62cdf43000000000000000000000000", result); - } - - @Test(enabled = true, description = "test get Ripemd160 input is string and " - + "do not convert to bytes") - public void test12getRipemd160Str() { - String args = "\"000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractC, - "getRipemd160Str(string)", args, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - String result = ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("efe2df697b79b5eb73a577251ce3911078811fa4000000000000000000000000", result); - } - - @Test(enabled = true, description = "test blake2f") - public void test13getBlak2f() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractC, - "callF()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - String result = ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals("ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac" - + "4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923", - result); - - } - - @Test(enabled = true, description = "when call create2, stack depth will be checked" - + "if stack depth is greater than 64, then create command will revert" - + "but run environment can not compute so much, so the actual result is time out") - public void test14FixCreate2StackDepth() { - String methedStr = "fixCreate2StackDepth(uint256)"; - String argsStr = "123"; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractD, - methedStr, argsStr, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - logger.info("transactionExtention: " + transactionExtention.toString()); - String message = ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray()); - Assert.assertTrue(message.contains("CPU timeout")); - /*int interCount = transactionExtention.getInternalTransactionsCount(); - int createCount = 0; - for(int i=0;i= 15 && createCount <= 64);*/ - } - - @Test(enabled = true, description = "when call create, stack depth will be checked." - + "if stack depth is greater than 64, then create command will revert" - + "but run environment can not compute so much, so the actual result is time out") - public void test15FixCreateStackDepth() { - - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractD, - "fixCreateStackDepth()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - String message = ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray()); - logger.info("transactionExtention: " + transactionExtention.toString()); - Assert.assertTrue(message.contains("CPU timeout")); - /*int interCount = transactionExtention.getInternalTransactionsCount(); - int createCount = 0; - for(int i=0;i= 15 && createCount <= 64);*/ - - } - - @Test(enabled = false, description = "test max Energy Limit For trigger Constant contract") - public void test16MaxEnergyLimitForConstant() { - String methedStr = "transfer(address)"; - String argsStr = "\"" + Base58.encode58Check(testNetAccountAddress) + "\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractD, - methedStr, argsStr, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - System.out.println("transactionExtention: " + transactionExtention.toString()); - } - - @Test(enabled = true, description = "commit NO.47 value can be 1e17 if commit No.63 opened") - public void test17Commit47Value() { - HashMap proposalMap = new HashMap(); - proposalMap.put(47L, 100000000000000000L); - org.testng.Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(contractExcAddress, contractExcKey, - testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/EthGrammer02.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/EthGrammer02.java deleted file mode 100644 index 97ea2d08963..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/EthGrammer02.java +++ /dev/null @@ -1,556 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.contract.SmartContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - - - -@Slf4j -public class EthGrammer02 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractD = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - int salt = 11; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 300100_000_000L, - testNetAccountAddress, testNetAccountKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/EthGrammer02.sol"; - String contractName = "D"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractD = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 500000000L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContractOuterClass.SmartContract smartContract = PublicMethed.getContract(contractD, - blockingStubFull); - Assert.assertEquals(1, smartContract.getVersion()); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = true, description = "can not deploy contract with bytecode ef") - public void test16forbiddenBytecodeStartWithEf() { - String code = "60ef60005360016000f3"; - String abi = "[{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"constructor\"}]"; - String txid = PublicMethed.deployContractAndGetTransactionInfoById("test", - abi, code, "", maxFeeLimit, - 500000000L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("info: " + info.get().toString()); - Assert.assertEquals(1, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.INVALID_CODE, - info.get().getReceipt().getResult()); - Assert.assertEquals("invalid code: must not begin with 0xef".toLowerCase(), - ByteArray.toStr(info.get().getResMessage().toByteArray()).toLowerCase()); - } - - @Test(enabled = true, description = "can not deploy contract with bytecode ef00") - public void test17forbiddenBytecodeStartWithEf() { - String code = "60ef60005360026000f3"; - String abi = "[{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"constructor\"}]"; - String txid = PublicMethed.deployContractAndGetTransactionInfoById("test", - abi, code, "", maxFeeLimit, 500000000L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("info: " + info.get().toString()); - Assert.assertEquals(1, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.INVALID_CODE, - info.get().getReceipt().getResult()); - Assert.assertEquals("invalid code: must not begin with 0xef".toLowerCase(), - ByteArray.toStr(info.get().getResMessage().toByteArray()).toLowerCase()); - } - - @Test(enabled = true, description = "can not deploy contract with bytecode ef0000") - public void test18forbiddenBytecodeStartWithEf() { - String code = "60ef60005360036000f3"; - String abi = "[{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"constructor\"}]"; - String txid = PublicMethed.deployContractAndGetTransactionInfoById("test", abi, - code, "", maxFeeLimit, 500000000L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("info: " + info.get().toString()); - Assert.assertEquals(1, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.INVALID_CODE, - info.get().getReceipt().getResult()); - Assert.assertEquals("invalid code: must not begin with 0xef".toLowerCase(), - ByteArray.toStr(info.get().getResMessage().toByteArray()).toLowerCase()); - } - - @Test(enabled = true, description = "can not deploy contract with bytecode" - + " ef00000000000000000000000000000000000000000000000000000000000000") - public void test19forbiddenBytecodeStartWithEf() { - String code = "60ef60005360206000f3"; - String abi = "[{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"constructor\"}]"; - String txid = PublicMethed.deployContractAndGetTransactionInfoById("test", abi, - code, "", maxFeeLimit, 500000000L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("info: " + info.get().toString()); - Assert.assertEquals(1, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.INVALID_CODE, - info.get().getReceipt().getResult()); - Assert.assertEquals("invalid code: must not begin with 0xef".toLowerCase(), - ByteArray.toStr(info.get().getResMessage().toByteArray()).toLowerCase()); - } - - @Test(enabled = true, description = "can deploy contract with bytecode fe") - public void test20forbiddenBytecodeStartWithEf() { - String code = "60fe60005360016000f3"; - String abi = "[{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"constructor\"}]"; - String txid = PublicMethed.deployContractAndGetTransactionInfoById("test", abi, - code, "", maxFeeLimit, 500000000L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("info: " + info.get().toString()); - Assert.assertEquals(0, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - info.get().getReceipt().getResult()); - } - - @Test(enabled = true, description = "can not deploy contract by create with bytecode ef") - public void test21forbiddenBytecodeStartWithEf() { - String methedStr = "createDeployEf(bytes)"; - String argsStr = "\"0x60ef60005360016000f3\""; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(1, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.REVERT, - info.get().getReceipt().getResult()); - } - - @Test(enabled = true, description = "can not deploy contract by create with bytecode ef00") - public void test22forbiddenBytecodeStartWithEf() { - String methedStr = "createDeployEf(bytes)"; - String argsStr = "\"0x60ef60005360026000f3\""; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(1, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.REVERT, - info.get().getReceipt().getResult()); - } - - @Test(enabled = true, description = "can not deploy contract by create with bytecode ef0000") - public void test23forbiddenBytecodeStartWithEf() { - String methedStr = "createDeployEf(bytes)"; - String argsStr = "\"0x60ef60005360036000f3\""; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(1, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.REVERT, - info.get().getReceipt().getResult()); - } - - @Test(enabled = true, description = "can not deploy contract by create with bytecode " - + "ef00000000000000000000000000000000000000000000000000000000000000") - public void test24forbiddenBytecodeStartWithEf() { - String methedStr = "createDeployEf(bytes)"; - String argsStr = "\"0x60ef60005360206000f3\""; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(1, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.REVERT, - info.get().getReceipt().getResult()); - } - - @Test(enabled = true, description = "can deploy contract by create with bytecode fe") - public void test25forbiddenBytecodeStartWithEf() { - String methedStr = "createDeployEf(bytes)"; - String argsStr = "\"0x60fe60005360016000f3\""; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - info.get().getReceipt().getResult()); - } - - @Test(enabled = true, description = "can not deploy contract by create2 with bytecode ef") - public void test26forbiddenBytecodeStartWithEf() { - String methedStr = "create2DeployEf(bytes,uint256)"; - String argsStr = "\"0x60ef60005360016000f3\"," + salt; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(1, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.REVERT, - info.get().getReceipt().getResult()); - } - - @Test(enabled = true, description = "can not deploy contract by create2 with bytecode ef00") - public void test27forbiddenBytecodeStartWithEf() { - salt++; - String methedStr = "create2DeployEf(bytes,uint256)"; - String argsStr = "\"0x60ef60005360026000f3\"," + salt; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(1, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.REVERT, - info.get().getReceipt().getResult()); - } - - @Test(enabled = true, description = "can not deploy contract by create2 with bytecode ef0000") - public void test28forbiddenBytecodeStartWithEf() { - salt++; - String methedStr = "create2DeployEf(bytes,uint256)"; - String argsStr = "\"0x60ef60005360036000f3\"," + salt; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(1, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.REVERT, - info.get().getReceipt().getResult()); - } - - @Test(enabled = true, description = "can not deploy contract by create2 with bytecode " - + "ef00000000000000000000000000000000000000000000000000000000000000") - public void test29forbiddenBytecodeStartWithEf() { - salt++; - String methedStr = "create2DeployEf(bytes,uint256)"; - String argsStr = "\"0x60ef60005360206000f3\"," + salt; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(1, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.REVERT, - info.get().getReceipt().getResult()); - } - - @Test(enabled = true, description = "can deploy contract by create2 with bytecode fe") - public void test30forbiddenBytecodeStartWithEf() { - salt++; - String methedStr = "create2DeployEf(bytes,uint256)"; - String argsStr = "\"0x60fe60005360016000f3\"," + salt; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - info.get().getReceipt().getResult()); - } - - @Test(enabled = true, description = "can not sendcoin to contract") - public void test31forbiddenSendTrxToContract() { - Assert.assertFalse(PublicMethed - .sendcoin(contractD, 100_000_000L, - testNetAccountAddress, testNetAccountKey, blockingStubFull)); - } - - @Test(enabled = true, description = "db key can use high 16 bytes," - + "0x6162630000000000000000000000000000000000000000000000000000000000") - public void test32DbKeyUseHigh16Bytes() { - String slot = "0x6162630000000000000000000000000000000000000000000000000000000000"; - long value = 121; - String methedStr = "setSlot(bytes,uint256)"; - String argsStr = "\"" + slot + "\"," + value; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - info.get().getReceipt().getResult()); - - methedStr = "getSlot(bytes)"; - argsStr = "\"" + slot + "\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractD, - methedStr, argsStr, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - long result = ByteArray.toLong(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("result: " + result); - Assert.assertEquals(value, result); - } - - @Test(enabled = true, description = "slot high 16bytes all f," - + "0xffffffffffffffffffffffffffffffff00000000000000000000000000000000") - public void test33DbKeyUseHigh16Bytes() { - String slot = "0xffffffffffffffffffffffffffffffff00000000000000000000000000000000"; - long value = 122; - String methedStr = "setSlot(bytes,uint256)"; - String argsStr = "\"" + slot + "\"," + value; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - info.get().getReceipt().getResult()); - - methedStr = "getSlot(bytes)"; - argsStr = "\"" + slot + "\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractD, - methedStr, argsStr, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - long result = ByteArray.toLong(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("result: " + result); - Assert.assertEquals(value, result); - } - - @Test(enabled = true, description = "slot high 16bytes 1," - + " 0x0000000000000000000000000000000100000000000000000000000000000000") - public void test34DbKeyUseHigh16Bytes() { - String slot = "0x0000000000000000000000000000000100000000000000000000000000000000"; - long value = 123; - String methedStr = "setSlot(bytes,uint256)"; - String argsStr = "\"" + slot + "\"," + value; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - info.get().getReceipt().getResult()); - - methedStr = "getSlot(bytes)"; - argsStr = "\"" + slot + "\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractD, - methedStr, argsStr, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - long result = ByteArray.toLong(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("result: " + result); - Assert.assertEquals(value, result); - } - - @Test(enabled = true, description = "slot high 16bytes all 0,low 16bytes 1." - + " 0x0000000000000000000000000000000000000000000000000000000000000001") - public void test35DbKeyUseHigh16Bytes() { - String slot = "0x0000000000000000000000000000000000000000000000000000000000000001"; - long value = 124; - String methedStr = "setSlot(bytes,uint256)"; - String argsStr = "\"" + slot + "\"," + value; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - info.get().getReceipt().getResult()); - - methedStr = "getSlot(bytes)"; - argsStr = "\"" + slot + "\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractD, - methedStr, argsStr, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - long result = ByteArray.toLong(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("result: " + result); - Assert.assertEquals(value, result); - } - - @Test(enabled = true, description = "slot all 0," - + " 0x0000000000000000000000000000000000000000000000000000000000000000") - public void test36DbKeyUseHigh16BytesAllBytes0() { - String slot = "0x0000000000000000000000000000000000000000000000000000000000000000"; - long value = 125; - String methedStr = "setSlot(bytes,uint256)"; - String argsStr = "\"" + slot + "\"," + value; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - info.get().getReceipt().getResult()); - - methedStr = "getSlot(bytes)"; - argsStr = "\"" + slot + "\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractD, - methedStr, argsStr, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - long result = ByteArray.toLong(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("result: " + result); - Assert.assertEquals(value, result); - } - - @Test(enabled = true, description = "slot all f," - + " 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") - public void test37DbKeyUseHigh16BytesAllBytesF() { - String slot = "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; - long value = 126; - String methedStr = "setSlot(bytes,uint256)"; - String argsStr = "\"" + slot + "\"," + value; - String txid = PublicMethed.triggerContract(contractD, methedStr, argsStr, - false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = - PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, info.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - info.get().getReceipt().getResult()); - - methedStr = "getSlot(bytes)"; - argsStr = "\"" + slot + "\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractD, - methedStr, argsStr, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - long result = ByteArray.toLong(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("result: " + result); - Assert.assertEquals(value, result); - } - - @Test(enabled = true, description = "TransactionExtention has logs and internal_transactions") - public void test38ConstantLogEven() { - salt++; - String methedStr = "create2DeployEf(bytes,uint256)"; - String argsStr = "\"0x60fe60005360016000f3\"," + salt; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractD, - methedStr, argsStr, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(1, transactionExtention.getLogsCount()); - Assert.assertEquals(1, transactionExtention.getInternalTransactionsCount()); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(contractExcAddress, contractExcKey, - testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/FixbugTest086.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/FixbugTest086.java deleted file mode 100644 index 268f3bdd4d9..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/FixbugTest086.java +++ /dev/null @@ -1,147 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.contract.SmartContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - - - - -@Slf4j -public class FixbugTest086 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] mapKeyContract = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 300100_000_000L, - testNetAccountAddress, testNetAccountKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = - "src/test/resources/soliditycode/abstractContractWithMapParamsConstructor.sol"; - String contractName = "Cat"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - mapKeyContract = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContractOuterClass.SmartContract smartContract = PublicMethed.getContract(mapKeyContract, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - - @Test(enabled = true, description = "abstract With Map Params") - public void test01ContractWithMapParams() { - String triggerTxid = PublicMethed.triggerContract(mapKeyContract, "getMapValue()", "#", false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - Assert.assertEquals(20, - ByteArray.toInt(transactionInfo.get().getContractResult(0).toByteArray())); - } - - - @Test(enabled = true, description = " super skip unimplemented in abstract contract") - public void test02SkipUnimplemented() { - String filePath = - "src/test/resources/soliditycode/super_skip_unimplemented_in_abstract_contract.sol"; - String contractName = "B"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - mapKeyContract = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContractOuterClass.SmartContract smartContract = PublicMethed.getContract(mapKeyContract, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - String triggerTxid = PublicMethed.triggerContract(mapKeyContract, "f()", "#", false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - Assert.assertEquals(42, - ByteArray.toInt(transactionInfo.get().getContractResult(0).toByteArray())); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(contractExcAddress, contractExcKey, - testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/FunctionArray2Storage086.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/FunctionArray2Storage086.java deleted file mode 100644 index b5527f9cf32..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/FunctionArray2Storage086.java +++ /dev/null @@ -1,158 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.contract.SmartContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - - - - -@Slf4j -public class FunctionArray2Storage086 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] mapKeyContract = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 300100_000_000L, - testNetAccountAddress, testNetAccountKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/function_type_array_to_storage.sol"; - String contractName = "C"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - mapKeyContract = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 500000000L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContractOuterClass.SmartContract smartContract = PublicMethed.getContract(mapKeyContract, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - - @Test(enabled = true, description = "function array test view to default") - public void test01View2Default() { - String triggerTxid = - PublicMethed.triggerContract(mapKeyContract, "testViewToDefault()", "#", false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - Assert.assertEquals(12, - ByteArray.toInt(transactionInfo.get().getContractResult(0).substring(0, 32).toByteArray())); - Assert.assertEquals(22, - ByteArray.toInt(transactionInfo.get().getContractResult(0) - .substring(32, 64).toByteArray())); - } - - @Test(enabled = true, description = "function array pure to default") - public void test02Pure2Default() { - String triggerTxid = - PublicMethed.triggerContract(mapKeyContract, "testPureToDefault()", "#", false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - Assert.assertEquals(13, - ByteArray.toInt(transactionInfo.get().getContractResult(0).substring(0, 32).toByteArray())); - Assert.assertEquals(23, - ByteArray.toInt(transactionInfo.get().getContractResult(0) - .substring(32, 64).toByteArray())); - - } - - @Test(enabled = true, description = "function array pure to view ") - public void test03Pure2View() { - String triggerTxid = - PublicMethed.triggerContract(mapKeyContract, "testPureToView()", "#", false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - Assert.assertEquals(13, - ByteArray.toInt(transactionInfo.get().getContractResult(0).substring(0, 32).toByteArray())); - Assert.assertEquals(23, - ByteArray.toInt(transactionInfo.get().getContractResult(0) - .substring(32, 64).toByteArray())); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(contractExcAddress, contractExcKey, - testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/LengthTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/LengthTest.java deleted file mode 100644 index 8c1a685113e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/LengthTest.java +++ /dev/null @@ -1,285 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class LengthTest { - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private byte[] contractAddress; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed - .sendcoin(testAddress001, 10000_000_000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - - String filePath = "src/test/resources/soliditycode/arrayLength001.sol"; - String contractName = "arrayLength"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0, 100, null, - testFoundationKey, testFoundationAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "push() increase Array length") - public void arrayLengthTest001() { - - String methodStr = "arrayPush()"; - String argStr = ""; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals("" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "push(value) increase Array length") - public void arrayLengthTest002() { - - String methodStr = "arrayPushValue()"; - String argStr = ""; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals("" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0100000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "pop() decrease Array length") - public void arrayLengthTest003() { - - String methodStr = "arrayPop()"; - String argStr = ""; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals("" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "push() return no value") - public void arrayLengthTest004() { - - String methodStr = "arrayPushReturn()"; - String argStr = ""; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals("" - + "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "push(value) return value") - public void arrayLengthTest005() { - - String methodStr = "arrayPushValueReturn()"; - String argStr = ""; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals("", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "pop() return no value") - public void arrayLengthTest006() { - - String methodStr = "arrayPopReturn()"; - String argStr = ""; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals("", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "bytes push() return value") - public void arrayLengthTest007() { - - String methodStr = "bytesPush()"; - String argStr = ""; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals("" - + "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "bytes push(value) return no value") - public void arrayLengthTest008() { - - String methodStr = "bytesPushValue()"; - String argStr = ""; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals("", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "bytes pop() return no value") - public void arrayLengthTest009() { - - String methodStr = "bytesPop()"; - String argStr = ""; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals("", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - } - - - @Test(enabled = true, description = "array length change before v0.5.15") - public void arrayLengthV0515() { - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_arrayLenth_0.5.15"); - String code = Configuration.getByPath("testng.conf") - .getString("code.code_arrayLength_0.5.15"); - String contractName = "arrayLength"; - byte[] v0515Address = PublicMethed.deployContract(contractName,abi,code,"",maxFeeLimit,0,100, - null, testKey001, testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String Txid = PublicMethed.triggerContract(v0515Address,"ChangeSize()","",false,0,maxFeeLimit, - testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(Txid, blockingStubFull); - - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertEquals("" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "0100000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/MappingFixTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/MappingFixTest.java deleted file mode 100644 index 849a08020ab..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/MappingFixTest.java +++ /dev/null @@ -1,186 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class MappingFixTest { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - // after solidity version 0.5.4. - // Tron Solidity compiler is no longer compatible with Ethereum - // Tron handles 41 Address in contract, and Ethereum do not - - @Test(enabled = true, description = "Deploy contract") - public void test01DeployContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1000_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 100_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(dev001Key, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = accountResource.getEnergyUsed(); - Long beforeNetUsed = accountResource.getNetUsed(); - Long beforeFreeNetUsed = accountResource.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/SolidityMappingFix.sol"; - String contractName = "Tests"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - } - - @Test(enabled = true, description = "Trigger contract,set balances[msg.sender]") - public void test02TriggerContract() { - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(dev001Key, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = accountResource.getEnergyUsed(); - Long beforeNetUsed = accountResource.getNetUsed(); - Long beforeFreeNetUsed = accountResource.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String methodStr = "update(uint256)"; - String argStr = "123"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - TransactionInfo transactionInfo = infoById.get(); - logger.info("infoById" + infoById); - - String ContractResult = - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()); - String tmpAddress = - Base58.encode58Check(ByteArray.fromHexString("41" + ContractResult.substring(24))); - Assert.assertEquals(WalletClient.encode58Check(dev001Address), tmpAddress); - - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - methodStr = "balances(address)"; - argStr = "\"" + WalletClient.encode58Check(dev001Address) + "\""; - TransactionExtention return1 = PublicMethed - .triggerContractForExtention(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, "0", 0L, dev001Address, dev001Key, blockingStubFull); - logger.info("return1: " + return1); - logger.info(Hex.toHexString(return1.getConstantResult(0).toByteArray())); - int ContractRestult = ByteArray.toInt(return1.getConstantResult(0).toByteArray()); - - Assert.assertEquals(123, ContractRestult); - - } - - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - PublicMethed.sendcoin(fromAddress, balance, dev001Address, dev001Key, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/MappingPopingTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/MappingPopingTest.java deleted file mode 100644 index 13fcc4f09e3..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/MappingPopingTest.java +++ /dev/null @@ -1,183 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class MappingPopingTest { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - @Test(enabled = true, description = "Deploy contract") - public void test01DeployContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1000_000_000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(dev001Key, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = accountResource.getEnergyUsed(); - Long beforeNetUsed = accountResource.getNetUsed(); - Long beforeFreeNetUsed = accountResource.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/TestMappings_array_pop.sol"; - String contractName = "C"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Protocol.Account infoafter = PublicMethed.queryAccount(dev001Key, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "Trigger contract ") - public void test02TriggerContract() { - String methodStr = "n1(uint256,uint256)"; - String argStr = "1,1001"; - String txid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById.get().getResMessage()); - } - logger.info("infoById" + infoById); - } - - @Test(enabled = true, description = "Trigger contract ") - public void test03TriggerContract() { - String methodStr = "p()"; - String argStr = ""; - String txid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById.get().getResMessage()); - } - logger.info("infoById" + infoById); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - PublicMethed.sendcoin(fromAddress, balance, dev001Address, dev001Key, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NegativeArrayTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NegativeArrayTest.java deleted file mode 100644 index 891e9303f3f..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NegativeArrayTest.java +++ /dev/null @@ -1,259 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class NegativeArrayTest { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - @Test(enabled = true, description = "Deploy contract") - public void test01DeployContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1000_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 100_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(dev001Key, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = accountResource.getEnergyUsed(); - Long beforeNetUsed = accountResource.getNetUsed(); - Long beforeFreeNetUsed = accountResource.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/negativeArray.sol"; - String contractName = "NegativeArray"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Protocol.Account infoafter = PublicMethed.queryAccount(dev001Key, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @Test(enabled = true, description = "Trigger contract") - public void test02TriggerContract() { - // get[2] - String methodStr = "get(uint256)"; - String argStr = "2"; - String triggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById.get().getResMessage()); - } - logger.info("infoById" + infoById); - String contractResult = - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()); - logger.info("contractResult:" + contractResult); - Assert.assertEquals(new BigInteger(contractResult, 16).intValue(), -3); - - // get[1] - String argStr1 = "1"; - String triggerTxid1 = PublicMethed.triggerContract(contractAddress, methodStr, argStr1, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = PublicMethed - .getTransactionInfoById(triggerTxid1, blockingStubFull); - if (infoById1.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById1.get().getResMessage()); - } - logger.info("infoById1" + infoById1); - String contractResult1 = - ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()); - logger.info("contractResult1:" + contractResult1); - Assert.assertEquals(new BigInteger(contractResult1, 16).intValue(), 2); - - // change array value - String triggerTxid2 = PublicMethed.triggerContract(contractAddress, "set()", "", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById2 = PublicMethed - .getTransactionInfoById(triggerTxid2, blockingStubFull); - if (infoById2.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById2.get().getResMessage()); - } - logger.info("infoById2" + infoById2); - String log1 = - ByteArray.toHexString(infoById2.get().getLog(0).getData().toByteArray()); - logger.info("log1:" + log1); - Assert.assertEquals(new BigInteger(log1, 16).intValue(), -1); - String log2 = ByteArray.toHexString(infoById2.get().getLog(1).getData().toByteArray()); - logger.info("log2:" + log2); - Assert.assertEquals(new BigInteger(log2, 16).intValue(), 3); - String log3 = - ByteArray.toHexString(infoById2.get().getLog(2).getData().toByteArray()); - logger.info("log3:" + log3); - Assert.assertEquals(new BigInteger(log3, 16).intValue(), -8); - - // get[2] - String triggerTxid3 = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById3 = PublicMethed - .getTransactionInfoById(triggerTxid3, blockingStubFull); - if (infoById3.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById3.get().getResMessage()); - } - logger.info("infoById3" + infoById3); - String contractResult3 = - ByteArray.toHexString(infoById3.get().getContractResult(0).toByteArray()); - logger.info("contractResult3:" + contractResult3); - Assert.assertEquals(new BigInteger(contractResult3, 16).intValue(), -8); - - // get[1] - String triggerTxid4 = PublicMethed.triggerContract(contractAddress, methodStr, argStr1, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById4 = PublicMethed - .getTransactionInfoById(triggerTxid4, blockingStubFull); - if (infoById4.get().getResultValue() != 0) { - Assert.fail("trigger contract failed with message: " + infoById4.get().getResMessage()); - } - logger.info("infoById4" + infoById4); - String contractResult4 = - ByteArray.toHexString(infoById4.get().getContractResult(0).toByteArray()); - logger.info("contractResult4:" + contractResult4); - Assert.assertEquals(new BigInteger(contractResult4, 16).intValue(), 3); - - // get[3] - String triggerTxid5 = PublicMethed.triggerContract(contractAddress, methodStr, "3", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById5 = PublicMethed - .getTransactionInfoById(triggerTxid5, blockingStubFull); - logger.info("infoById5" + infoById5); - Assert.assertEquals(1, infoById5.get().getResultValue()); - Assert.assertEquals("REVERT opcode executed", infoById5.get() - .getResMessage().toStringUtf8()); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - PublicMethed.sendcoin(fromAddress, balance, dev001Address, dev001Key, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc068.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc068.java deleted file mode 100644 index 8a2c8059221..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc068.java +++ /dev/null @@ -1,269 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.contract.SmartContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - - - -@Slf4j -public class NewFeatureForSolc068 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] getSelectorContract = null; - byte[] mapKeyContract = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 300100_000_000L, - testNetAccountAddress, testNetAccountKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/NewFeature068.sol"; - String contractName = "testMapKey"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - mapKeyContract = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContractOuterClass.SmartContract smartContract = PublicMethed.getContract(mapKeyContract, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - - @Test(enabled = true, description = "map with enum key") - public void test01MapWithEnumKey() { - String txid = PublicMethed.triggerContract(mapKeyContract, - "setEnumValue(uint256)", "1", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("txid: " + txid + "\n" + infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "getEnumValue()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals(1, trueRes); - } - - @Test(enabled = true, description = "map with contract key") - public void test02MapWithContractKey() { - - String txid = PublicMethed.triggerContract(mapKeyContract, - "setContractValue()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("txid: " + txid + "\n" + infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "getContractValue()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals(2, trueRes); - } - - @Test(enabled = true, description = "get function selector during compile period") - public void test03GetSelectorDuringCompile() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "getfunctionSelector()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - String trueRes = ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("trueRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertTrue(trueRes.startsWith("48593bae")); - } - - @Test(enabled = true, description = "test storage variable init before been used") - public void test04StorageValInit() { - - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "testStorage()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - String trueRes = PublicMethed - .getContractStringMsg(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals("test", trueRes); - } - - @Test(enabled = true, description = "test immutable variable inited when declared") - public void test05ImmutableInit() { - - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "getOwner()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - String trueRes = ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals(ByteArray.toHexString(PublicMethed - .getFinalAddress(contractExcKey)).substring(2), trueRes.substring(24)); - - } - - @Test(enabled = true, description = "test immutable variable inited in construct") - public void test06ImmutableInit() { - - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "getImmutableVal()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals(5, trueRes); - } - - @Test(enabled = true, description = "get interface id," - + "interface id is result of all function selector's XOR ") - public void test07GetInterfaceId() { - - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "getInterfaceId()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - String trueRes = ByteArray.toHexString(ByteArray.subArray(result, 0, 4)); - String trueRes1 = ByteArray.toHexString(ByteArray.subArray(result, 32, 36)); - - logger.info("truerRes: " + trueRes + " truerRes1: " + trueRes1 - + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals("a9ab72bd", trueRes); - Assert.assertEquals(trueRes, trueRes1); - - } - - @Test(enabled = true, description = "abstract contract can have vitrual modifier with empty body") - public void test08VirtualModifier() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "requireOwner()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - int trueRes = ByteArray.toInt(result); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals(6, trueRes); - - } - - @Test(enabled = true, description = "uint256 max and mine") - public void test09Uint256MaxMine() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "getUint256MinAndMax()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - String trueRes = ByteArray.toHexString(ByteArray.subArray(result, 0, 32)); - String trueRes1 = ByteArray.toHexString(ByteArray.subArray(result, 32, 64)); - logger.info("truerRes: " + trueRes + "truerRes1: " + trueRes1 - + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000000", - trueRes); - Assert.assertEquals("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - trueRes1); - - } - - @Test(enabled = true, description = "solidity 0.6.12 test Reference " - + "variable can be marked by calldata") - public void test10CalldataModifier() { - String hexAdd = ByteArray.toHexString(PublicMethed.getFinalAddress(contractExcKey)); - String args = "\"0x" + hexAdd + "\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "calldataModifier(bytes)", args, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - String trueRes = ByteArray.toHexString(result); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertTrue(trueRes.contains(hexAdd)); - } - - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(contractExcAddress, contractExcKey, - testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc076.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc076.java deleted file mode 100644 index 5348521896c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc076.java +++ /dev/null @@ -1,133 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.contract.SmartContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - - - -@Slf4j -public class NewFeatureForSolc076 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] mapKeyContract = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 300100_000_000L, - testNetAccountAddress, testNetAccountKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/NewFeature076.sol"; - String contractName = "C"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - mapKeyContract = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContractOuterClass.SmartContract smartContract = PublicMethed.getContract(mapKeyContract, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - - @Test(enabled = true, description = "call method outside contract") - public void test01CallOutsideMethod() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "getOutsideMethod()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals(1, trueRes); - } - - @Test(enabled = true, description = "get abstract contract and interface name") - public void test02GetTypeName() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "getAbstractName()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - String trueRes = ByteArray.toStr(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertTrue(trueRes.contains("abvd")); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "getInterfaceName()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - transaction = transactionExtention.getTransaction(); - trueRes = ByteArray.toStr(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertTrue(trueRes.contains("qwer")); - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(contractExcAddress, contractExcKey, - testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc080.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc080.java deleted file mode 100644 index 0fab29bcb22..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc080.java +++ /dev/null @@ -1,313 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.contract.SmartContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class NewFeatureForSolc080 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] mapKeyContract = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 300100_000_000L, - testNetAccountAddress, testNetAccountKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/NewFeature080.sol"; - String contractName = "C"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - mapKeyContract = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 5000000L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContractOuterClass.SmartContract smartContract = PublicMethed.getContract(mapKeyContract, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - - @Test(enabled = true, description = "math sub without unchecked, transaction revert") - public void test01MathSubNoUncheck() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "subNoUncheck()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("REVERT opcode executed", - transactionExtention.getResult().getMessage().toStringUtf8()); - Assert.assertEquals("FAILED", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - - } - - @Test(enabled = true, description = "math sub with uncheck,transaction success") - public void test02SubWithUncheck() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "subWithUncheck()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(255, trueRes); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertTrue(transactionExtention.getEnergyUsed() > 300); - - } - - @Test(enabled = true, description = "math add overflow without unchecked, transaction revert") - public void test03MathAddNoUncheck() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "addNoUncheck()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("REVERT opcode executed", - transactionExtention.getResult().getMessage().toStringUtf8()); - Assert.assertEquals("FAILED", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - - } - - @Test(enabled = true, description = "math divide zero without unchecked, transaction revert") - public void test04DivideZeroNoUncheck() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "divideZeroNoUncheck()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("REVERT opcode executed", - transactionExtention.getResult().getMessage().toStringUtf8()); - Assert.assertEquals("FAILED", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - - } - - @Test(enabled = true, description = "assert fail without unchecked, transaction revert") - public void test05AssertFailNoUncheck() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "assertFailNoUncheck()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("REVERT opcode executed", - transactionExtention.getResult().getMessage().toStringUtf8()); - Assert.assertEquals("FAILED", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - - @Test(enabled = true, description = "array out of index without unchecked, transaction revert") - public void test06AssertFailNoUncheck() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "arrayOutofIndex()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals("REVERT opcode executed", - transactionExtention.getResult().getMessage().toStringUtf8()); - Assert.assertEquals("FAILED", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - - @Test(enabled = true, description = "type convert") - public void test07TypeConvert() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "typeConvert()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(65535, trueRes); - Assert.assertEquals(true, - transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - - @Test(enabled = true, description = "power multi by default turn: right to left") - public void test08PowerMultiRightToLeft() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "powerMultiRightToLeft()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(2, trueRes); - Assert.assertEquals(true, - transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - - @Test(enabled = true, description = "power multi: left to right ") - public void test09PowerMultiLeftToRight() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "powerMultiLeftToRight()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(64, trueRes); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - - @Test(enabled = true, description = "power multi with 2 params ") - public void test10PowerMultiWith2Params() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "powerMultiWith2Params()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(8, trueRes); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - - @Test(enabled = true, description = "get block chain id ") - public void test11GetBlockChainId() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "getBlockChainId()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - String chainId = ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("chainId: " + chainId); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - - @Test(enabled = true, description = "get normal account address hashcode ") - public void test12GetAccountHashCode() { - String argStr = "\"" + Base58.encode58Check(contractExcAddress) + "\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "getAddressCodehash(address)", argStr, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - logger.info(transactionExtention.toString()); - String trueRes = ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("0000000: " + trueRes); - } - - @Test(enabled = true, description = "get contract address hashcode ") - public void test13GetContractAddressHashCode() { - String argStr = "\"" + Base58.encode58Check(mapKeyContract) + "\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "getAddressCodehash(address)", argStr, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - logger.info(transactionExtention.toString()); - String trueRes = ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("0000000: " + trueRes); - } - - @Test(enabled = true, description = "transfer trx to tx.origin address with payable") - public void test14TransferToTxoriginAddress() { - Protocol.Account info = PublicMethed.queryAccount(mapKeyContract, blockingStubFull); - Long beforeBalance = info.getBalance(); - logger.info("beforeBalance: " + beforeBalance); - - String methodStr = "transferToTxorigin(uint64)"; - String triggerTxid = PublicMethed.triggerContract(mapKeyContract, methodStr, "1000000", false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - - info = PublicMethed.queryAccount(mapKeyContract, blockingStubFull); - Long afterBalance = info.getBalance(); - logger.info("afterBalance: " + afterBalance); - Assert.assertTrue(beforeBalance == afterBalance + 1000000); - } - - @Test(enabled = true, description = "transfer trx to literal address with payable") - public void test15TransferToLiteralAddress() { - Protocol.Account info = PublicMethed.queryAccount(mapKeyContract, blockingStubFull); - Long beforeBalance = info.getBalance(); - logger.info("beforeBalance: " + beforeBalance); - - String methodStr = "transferToLiteralAddress(uint64)"; - String triggerTxid = PublicMethed.triggerContract(mapKeyContract, methodStr, "1000000", false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - - info = PublicMethed.queryAccount(mapKeyContract, blockingStubFull); - Long afterBalance = info.getBalance(); - logger.info("afterBalance: " + afterBalance); - Assert.assertTrue(beforeBalance == afterBalance + 1000000); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(contractExcAddress, contractExcKey, - testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc0811.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc0811.java deleted file mode 100644 index 4b2c475566d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc0811.java +++ /dev/null @@ -1,240 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.contract.SmartContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class NewFeatureForSolc0811 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] mapKeyContract = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 300100_000_000L, - testNetAccountAddress, testNetAccountKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/NewFeature0811.sol"; - String contractName = "C"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - mapKeyContract = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContractOuterClass.SmartContract smartContract = PublicMethed.getContract(mapKeyContract, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = true, description = "Get enum.min or enum.max") - public void test001GetEnumMinOrMax() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "getEnumMin()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - int result = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(0, result); - - - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "getEnumMax()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - result = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(3, result); - - } - - - @Test(enabled = true,description = "User defined type of data") - public void test002SupportUserDefinedTypeOfData() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "getUserDefinedValue()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - int result = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(45, result); - } - - - @Test(enabled = true,description = "Get assembly address") - public void test003GetAssemblyAddress() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "testGetAddress()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertTrue(ByteArray.toHexString(transactionExtention.getConstantResult(0) - .toByteArray()).contains(ByteArray.toHexString(mapKeyContract).substring(2))); - } - - - @Test(enabled = true,description = "Get assembly selector") - public void test004GetAssemblySelector() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "testGetSelector()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - long result = ByteArray.toLong(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(3781905051L, result); - } - - - @Test(enabled = true,description = "Get ABI-Encode calldata") - public void test005GetAbiEncodedCalldata() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "fSignatureFromLiteralCall()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - - Assert.assertEquals("" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000084" - + "33d8581000000000000000000000000000000000000000000000000000000000" - + "0000000100000000000000000000000000000000000000000000000000000000" - + "0000004000000000000000000000000000000000000000000000000000000000" - + "0000000331323300000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - } - - - @Test(enabled = true,description = "Support constructor read immutable value") - public void test006SupportConstructorReadImmutableValue() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "readX()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - int result = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(33, result); - - - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "readI()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - result = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(33, result); - - - } - - - @Test(enabled = true,description = "Fix immutable symbol bug") - public void test007FixImmutableSymbol() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "fixBugTest()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - - Assert.assertEquals("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(contractExcAddress, contractExcKey, - testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc086.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc086.java deleted file mode 100644 index 6947cfbe03a..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolc086.java +++ /dev/null @@ -1,305 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.contract.SmartContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - - - - -@Slf4j -public class NewFeatureForSolc086 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] mapKeyContract = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 300100_000_000L, - testNetAccountAddress, testNetAccountKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/NewFeature086.sol"; - String contractName = "C"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - mapKeyContract = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 500000000L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContractOuterClass.SmartContract smartContract = PublicMethed.getContract(mapKeyContract, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - - @Test(enabled = true, description = "catch assert fail") - public void test01TrtCatchAssertFail() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "catchAssertFail()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(1, trueRes); - - } - - @Test(enabled = true, description = "catch under flow") - public void test02CatchUnderFlow() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "catchUnderFlow()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(17, trueRes); - - } - - @Test(enabled = true, description = "catch divide zero") - public void test03CatchDivideZero() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "catchDivideZero()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - Assert.assertEquals(18, trueRes); - } - - @Test(enabled = true, description = "get address code length") - public void test04GetAddressCodeLength() { - String triggerTxid = PublicMethed.triggerContract(mapKeyContract, "getAddressCodeLength()", - "#", false, 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - Assert.assertTrue(transactionInfo.get().getFee() < 40000); - } - - @Test(enabled = true, description = "fix kecca256 bug: differt length return same code") - public void test05Kecca256BugFix() { - String args = "\"abcd123\""; - String triggerTxid = PublicMethed.triggerContract(mapKeyContract, "keccak256Bug(string)", - args, false, 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - Assert.assertEquals(0, - ByteArray.toInt(transactionInfo.get().getContractResult(0).toByteArray())); - logger.info(transactionInfo.toString()); - } - - @Test(enabled = true, description = "revert error type with params") - public void test06RevertErrorType() { - String args = "\"T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb\",1000000000"; - String triggerTxid = PublicMethed.triggerContract(mapKeyContract, "transfer(address,uint256)", - args, false, 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info(transactionInfo.toString()); - Assert.assertEquals(1, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.REVERT, - transactionInfo.get().getReceipt().getResult()); - Assert.assertEquals("cf479181", - ByteArray.toHexString(transactionInfo.get() - .getContractResult(0).substring(0, 4).toByteArray())); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionInfo.get().getContractResult(0) - .substring(4, 36).toByteArray())); - Assert.assertEquals("000000000000000000000000000000000000000000000000000000003b9aca00", - ByteArray.toHexString(transactionInfo.get().getContractResult(0) - .substring(36, 68).toByteArray())); - - } - - @Test(enabled = true, description = "revert error type no params") - public void test07RevertErrorType() { - String triggerTxid = PublicMethed.triggerContract(mapKeyContract, "withdraw()", "#", false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertEquals(1, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.REVERT, - transactionInfo.get().getReceipt().getResult()); - Assert.assertEquals("82b42900", - ByteArray.toHexString(transactionInfo.get().getContractResult(0) - .substring(0, 4).toByteArray())); - } - - @Test(enabled = true, description = "test bytes concat") - public void test08bytesConcat() { - String args = "\"0x1234\",\"p2\",\"0x48e2f56f2c57e3532146eef2587a2a72\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "bytesConcat(bytes,string,bytes16)", args, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals(36, trueRes); - } - - @Test(enabled = true, description = "test emit event") - public void test09EmitEvent() { - String triggerTxid = PublicMethed.triggerContract(mapKeyContract, "testEmitEvent()", "#", false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info(transactionInfo.toString()); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - Assert.assertEquals(6, - ByteArray.toInt(transactionInfo.get().getLog(0).getData().toByteArray())); - } - - - @Test(enabled = true, description = "test bytes convert to byteN overflow") - public void test10Bytes2ByteN() { - String args = "\"0x12345678\""; - String triggerTxid = PublicMethed.triggerContract(mapKeyContract, "bytes2BytesN(bytes)", - args, false, 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info(transactionInfo.toString()); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - Assert.assertEquals("1234560000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "test bytes convert to byteN underflow") - public void test11Bytes2ByteN() { - String args = "\"0x1234\""; - String triggerTxid = PublicMethed.triggerContract(mapKeyContract, "bytes2BytesN(bytes)", - args, false, 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info(transactionInfo.toString()); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - Assert.assertEquals("1234000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "get contract address by different function") - public void test12GetConcatAddress() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "getContractAddress()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - String res1 = ByteArray.toHexString(transactionExtention.getConstantResult(0) - .substring(0, 32).toByteArray()); - String res2 = ByteArray.toHexString(transactionExtention.getConstantResult(0) - .substring(32, 64).toByteArray()); - Assert.assertEquals(res1, res2); - } - - @Test(enabled = true, description = "test bytes concat with empty string") - public void test13bytesConcatWithEmptyStr() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "bytesConcatWithEmptyStr()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertEquals(true, transactionExtention.getResult().getResult()); - Assert.assertEquals("SUCESS", - transactionExtention.getTransaction().getRet(0).getRet().toString()); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(contractExcAddress, contractExcKey, - testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolidity062.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolidity062.java deleted file mode 100644 index 0212ac308f7..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/NewFeatureForSolidity062.java +++ /dev/null @@ -1,306 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import static org.tron.protos.Protocol.TransactionInfo.code.FAILED; -import static org.tron.protos.Protocol.TransactionInfo.code.SUCESS; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class NewFeatureForSolidity062 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] getSelectorContract = null; - byte[] gasValueContract = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 300100_000_000L, - testNetAccountAddress, testNetAccountKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/ExternalSelector.sol"; - String contractName = "TestGasValue"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - gasValueContract = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 10000000L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - - @Test(enabled = true, description = "get selector from contract or interface's external function") - public void test01GetFunctionSelector() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(gasValueContract, - "getContractSelectorNoParam()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - String truerRes = ByteArray.toHexString(transactionExtention - .getConstantResult(0).toByteArray()); - logger.info("truerRes: " + truerRes + " message:" + transaction.getRet(0).getRet()); - logger.info("transactionExtention: " + transactionExtention); - Assert.assertTrue(truerRes.startsWith("6c4959fa")); - - transactionExtention = PublicMethed.triggerConstantContractForExtention(gasValueContract, - "getContractSelectorWithParam()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - transaction = transactionExtention.getTransaction(); - truerRes = ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + truerRes + " message:" + transaction.getRet(0).getRet()); - logger.info("transactionExtention: " + transactionExtention); - Assert.assertTrue(truerRes.startsWith("fbb94ff8")); - - transactionExtention = PublicMethed.triggerConstantContractForExtention(gasValueContract, - "getInterfaceSelectorNoParam()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - transaction = transactionExtention.getTransaction(); - truerRes = ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + truerRes + " message:" + transaction.getRet(0).getRet()); - logger.info("transactionExtention: " + transactionExtention); - Assert.assertTrue(truerRes.startsWith("034899bc")); - } - - @Test(enabled = true, description = "call external function like " - + "c.f{gas: 0, value: 1}()") - public void test02Call0GasAnd1Value() { - - String txid = PublicMethed.triggerContract(gasValueContract, - "callWithGasAndValue(uint256,uint256)", "0,1", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("txid: " + txid + "\n" + infoById.toString()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000159", - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - byte[] internalReceiver = infoById.get().getInternalTransactions(0) - .getTransferToAddress().toByteArray(); - - long balanceReceiver = PublicMethed.queryAccount(internalReceiver, blockingStubFull) - .getBalance(); - logger.info("transfer to address: " + Base58.encode58Check(internalReceiver) - + "\n balance:" + balanceReceiver); - Assert.assertEquals(1, balanceReceiver); - } - - @Test(enabled = true, description = "call external function like " - + "c.f{gas: 0, value: 0}()") - public void test03Call0GasAnd0Value() { - String txid = PublicMethed.triggerContract(gasValueContract, - "callWithGasAndValue(uint256,uint256)", "0,0", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("txid: " + txid + "\n" + infoById.toString()); - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("REVERT opcode executed", - infoById.get().getResMessage().toStringUtf8()); - - } - - @Test(enabled = true, description = "inline assembly allow true and false") - public void test04AssembleTrueFalse() { - - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(gasValueContract, - "testAssemblyTrue()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - int truerRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + truerRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals(1, truerRes); - - transactionExtention = PublicMethed.triggerConstantContractForExtention(gasValueContract, - "testAssemblyFalse()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - transaction = transactionExtention.getTransaction(); - int falseRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("res: " + falseRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals(0, falseRes); - - } - - @Test(enabled = true, description = "test new create2") - public void test05NewCreate2() { - - String txid = PublicMethed.triggerContract(gasValueContract, - "testCreate2()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("txid: " + txid + "\n" + infoById.toString()); - byte[] internalReceiver = infoById.get() - .getInternalTransactions(0).getTransferToAddress().toByteArray(); - - long balanceReceiver = PublicMethed.queryAccount(internalReceiver, blockingStubFull) - .getBalance(); - logger.info("transfer to address: " + Base58.encode58Check(internalReceiver) - + "\n balance:" + balanceReceiver); - Assert.assertEquals(1000000, balanceReceiver); - - } - - @Test(enabled = true, description = "test Interface Succeed") - public void test06InterfaceSucceed() { - - String filePath = "src/test/resources/soliditycode/ExternalSelector.sol"; - String contractName = "implementContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] implementContract = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 10000000L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(implementContract, - "getSelector()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - int truerRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + truerRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals(66, truerRes); - } - - @Test(enabled = true, description = "call in contract external function like " - + "c.f{gas: 0, value: 1}()") - public void test07CallThis0GasAnd1Value() { - - String txid = PublicMethed.triggerContract(gasValueContract, - "callThisNoGasAnd1Value()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("txid: " + txid + "\n" + infoById.toString()); - Assert.assertEquals(FAILED, infoById.get().getResult()); - - } - - @Test(enabled = true, description = "call external function like " - + "c.f{gas: 440000, value: 0}()") - public void test08CallWithGasAnd0Value() { - String txid = PublicMethed.triggerContract(gasValueContract, - "callWithGasAndValue(uint256,uint256)", "440000,0", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("txid: " + txid + "\n" + infoById.toString()); - Assert.assertEquals(SUCESS, infoById.get().getResult()); - - } - - @Test(enabled = true, description = "call external function like " - + "c.f{gas: 1, value: 0}()") - public void test09CallWith1GasAnd0Value() { - String txid = PublicMethed.triggerContract(gasValueContract, - "callWithGasAndValue(uint256,uint256)", "1,0", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("txid: " + txid + "\n" + infoById.toString()); - Assert.assertEquals(FAILED, infoById.get().getResult()); - - } - - @Test(enabled = true, description = "call external function like " - + "c.f{gas: 0, value: > balance}()") - public void test10CallWith0GasAndBigValue() { - String txid = PublicMethed.triggerContract(gasValueContract, - "callWithGasAndValue(uint256,uint256)", "0,9223372036854775800", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("txid: " + txid + "\n" + infoById.toString()); - Assert.assertEquals(FAILED, infoById.get().getResult()); - } - - @Test(enabled = true, description = "call external function like " - + "c.f{gas: 9223372036854775800, value: 0}()") - public void test11CallWithBigGasAnd0Value() { - String txid = PublicMethed.triggerContract(gasValueContract, - "callWithGasAndValue(uint256,uint256)", "9223372036854775800,0", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("txid: " + txid + "\n" + infoById.toString()); - Assert.assertEquals(SUCESS, infoById.get().getResult()); - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(contractExcAddress, contractExcKey, - testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/Opcode.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/Opcode.java deleted file mode 100644 index 95292006f7c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/Opcode.java +++ /dev/null @@ -1,509 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.contract.SmartContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - - - -@Slf4j -public class Opcode { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] mapKeyContract = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 300100_000_000L, - testNetAccountAddress, testNetAccountKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/opCode.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbiNoOptimize(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - mapKeyContract = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContractOuterClass.SmartContract smartContract = PublicMethed.getContract(mapKeyContract, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - } - - - @Test(enabled = true, description = "test opcode smod, used for int") - public void test01Smod() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "sssmod()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals(1, trueRes); - } - - @Test(enabled = true, description = "test opcode extcodecopy return contract bytecode") - public void test02Extcodecopy() { - String base58 = Base58.encode58Check(mapKeyContract); - String txid = PublicMethed.triggerContract(mapKeyContract, - "eextcodecopy(address)", "\"" + base58 + "\"", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("txid: " + txid + "\n" + infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertTrue(ByteArray.toHexString( - infoById.get().getContractResult(0).toByteArray()).length() > 0); - - } - - @Test(enabled = true, description = "test opcode coinbase," - + "block.coinbase is sr address which produced the block") - public void test03Coinbase() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "cccoinbase()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - String trueRes = ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals("SUCESS", transaction.getRet(0).getRet().toString()); - Assert.assertTrue(trueRes.startsWith("00000000000000000000000" - + "0bafb56091591790e00aa05eaddcc7dc1474b5d4b") - || trueRes.startsWith("0000000000000000000000000be88a918d74d0dfd71dc84bd4abf036d0562991")); - - } - - @Test(enabled = true, description = "test opcode difficulty,block.difficulty is always 0") - public void test04Difficulty() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "ddifficulty()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals("SUCESS", transaction.getRet(0).getRet().toString()); - Assert.assertEquals(0, trueRes); - - } - - @Test(enabled = true, description = "test opcode gaslimit,block.gaslimit is always 0") - public void test05Gaslimit() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "gggaslimit()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals("SUCESS", transaction.getRet(0).getRet().toString()); - Assert.assertEquals(0, trueRes); - - } - - @Test(enabled = true, description = "test opcode pc,return current position, " - + "ppppc() can refer to opCode.sol") - public void test06Pc() { - String code = "608060405260838060116000396000f3fe608060405234" - + "8015600f57600080fd5b506004361060285760003560e01c806" - + "36d3a027714602d575b600080fd5b60336045565b6040805191825251" - + "9081900360200190f35b60005890509056fea264697" - + "0667358221220fe03cbd3d2aae7454565f203b9abd76ce74cf0ac" - + "a079b151cf6b8e2bfda2d5c464736f6c634300060c0033"; - String abi = "[\n" - + "\t{\n" - + "\t\t\"inputs\": [],\n" - + "\t\t\"stateMutability\": \"payable\",\n" - + "\t\t\"type\": \"constructor\"\n" - + "\t},\n" - + "\t{\n" - + "\t\t\"inputs\": [],\n" - + "\t\t\"name\": \"ppppc\",\n" - + "\t\t\"outputs\": [\n" - + "\t\t\t{\n" - + "\t\t\t\t\"internalType\": \"uint256\",\n" - + "\t\t\t\t\"name\": \"a\",\n" - + "\t\t\t\t\"type\": \"uint256\"\n" - + "\t\t\t}\n" - + "\t\t],\n" - + "\t\t\"stateMutability\": \"nonpayable\",\n" - + "\t\t\"type\": \"function\"\n" - + "\t}\n" - + "]"; - byte[] temContract = PublicMethed.deployContract("A", abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContractOuterClass.SmartContract smartContract = PublicMethed.getContract(temContract, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(temContract, - "ppppc()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals("SUCESS", transaction.getRet(0).getRet().toString()); - Assert.assertEquals(72, trueRes); - - } - - @Test(enabled = true, description = "test opcode msize,return size of memory, " - + "msize cannot be used if optimize is open, mmmsize() can refer to opCode.sol") - public void test07Msize() { - String code = "608060405260b5806100126000396000f3fe6080604052348015600f5760" - + "0080fd5b506004361060285760003560e01c8063bf1a725d14602d575b600080fd5b60" - + "336047565b604051603e9190605c565b60405180910390f35b600059905090565b6056" - + "816075565b82525050565b6000602082019050606f6000830184604f565b9291505056" - + "5b600081905091905056fea26469706673582212202252652aad4bca9a4aa9db179e03" - + "f7b3bf439f47152e31f45d8587b710bce79664736f6c63430008060033"; - String abi = "[\n" - + "\t{\n" - + "\t\t\"inputs\": [],\n" - + "\t\t\"stateMutability\": \"payable\",\n" - + "\t\t\"type\": \"constructor\"\n" - + "\t},\n" - + "\t{\n" - + "\t\t\"inputs\": [],\n" - + "\t\t\"name\": \"mmmsize\",\n" - + "\t\t\"outputs\": [\n" - + "\t\t\t{\n" - + "\t\t\t\t\"internalType\": \"uint256\",\n" - + "\t\t\t\t\"name\": \"a\",\n" - + "\t\t\t\t\"type\": \"uint256\"\n" - + "\t\t\t}\n" - + "\t\t],\n" - + "\t\t\"stateMutability\": \"nonpayable\",\n" - + "\t\t\"type\": \"function\"\n" - + "\t}\n" - + "]"; - byte[] temContract = PublicMethed.deployContract("A", abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContractOuterClass.SmartContract smartContract = PublicMethed.getContract(temContract, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(temContract, - "mmmsize()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals("SUCESS", transaction.getRet(0).getRet().toString()); - Assert.assertEquals(96, trueRes); - - } - - - @Test(enabled = true, description = "test opcode swap14-16,solidity cannot use optimize") - public void test08Swap() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "ssswap()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals("SUCESS", transaction.getRet(0).getRet().toString()); - Assert.assertEquals(1, trueRes); - - } - - @Test(enabled = true, description = "test opcode push13-30 but exclude push20 and push29," - + "solidity cannot use optimize") - public void test08Pushx() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "pppushx()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - String trueRes = ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + trueRes + " message:" + transaction.getRet(0).getRet()); - Assert.assertEquals("SUCESS", transaction.getRet(0).getRet().toString()); - Assert.assertTrue(trueRes.contains("000000000000000000000000000000000000001" - + "1223344556677889900112233")); - } - - @Test(enabled = true, description = "test opcode callcode,difference with delegatecall " - + "is caller and callvalue,the bytecode is compiled with solidity 0.4.22, " - + "can refer to opCode.sol for code") - public void test09Callcode() { - String code = "60806040526103b4806100136000396000f3006080604052600436106100565763" - + "ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634" - + "cb335db811461005b578063ae02d91d14610081578063ea856db2146100a5575b600080fd5b61007f" - + "73ffffffffffffffffffffffffffffffffffffffff600435166024356100c9565b005b61007f73ffff" - + "ffffffffffffffffffffffffffffffffffff600435166024356101b6565b61007f73ffffffffffffff" - + "ffffffffffffffffffffffffff600435166024356102a3565b604080516024808201849052825180830" - + "39091018152604490910182526020810180517bffffffffffffffffffffffffffffffffffffffffffff" - + "ffffffffffff167f66c99139000000000000000000000000000000000000000000000000000000001781529" - + "151815173ffffffffffffffffffffffffffffffffffffffff861693600a93929182919080838360005b8" - + "3811015610170578181015183820152602001610158565b50505050905090810190601f16801561019d5" - + "780820380516001836020036101000a031916815260200191505b5091505060006040518083038185875" - + "af1505050505050565b60408051602480820184905282518083039091018152604490910182526020810" - + "180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f66c99139000000000" - + "000000000000000000000000000000000000000000000001781529151815173fffffffffffffffffffff" - + "fffffffffffffffffff861693600a93929182919080838360005b8381101561025d57818101518382015" - + "2602001610245565b50505050905090810190601f16801561028a5780820380516001836020036101000" - + "a031916815260200191505b5091505060006040518083038185875af2505050505050565b60408051602" - + "480820184905282518083039091018152604490910182526020810180517bfffffffffffffffffffffff" - + "fffffffffffffffffffffffffffffffff167f66c991390000000000000000000000000000000000000000" - + "00000000000000001781529151815173ffffffffffffffffffffffffffffffffffffffff8616938291808" - + "38360005b8381101561034457818101518382015260200161032c565b50505050905090810190601f1680" - + "156103715780820380516001836020036101000a031916815260200191505b50915050600060405180830" - + "381855af450505050505600a165627a7a72305820210d132d0c4006264ef113f342556c616d9e69acc20" - + "bfa80cf440a4eac170de80029"; - String abi = "[\n" - + "\t{\n" - + "\t\t\"constant\": false,\n" - + "\t\t\"inputs\": [\n" - + "\t\t\t{\n" - + "\t\t\t\t\"name\": \"callCAddress\",\n" - + "\t\t\t\t\"type\": \"address\"\n" - + "\t\t\t},\n" - + "\t\t\t{\n" - + "\t\t\t\t\"name\": \"amount\",\n" - + "\t\t\t\t\"type\": \"uint256\"\n" - + "\t\t\t}\n" - + "\t\t],\n" - + "\t\t\"name\": \"testInCall\",\n" - + "\t\t\"outputs\": [],\n" - + "\t\t\"payable\": true,\n" - + "\t\t\"stateMutability\": \"payable\",\n" - + "\t\t\"type\": \"function\"\n" - + "\t},\n" - + "\t{\n" - + "\t\t\"constant\": false,\n" - + "\t\t\"inputs\": [\n" - + "\t\t\t{\n" - + "\t\t\t\t\"name\": \"callCAddress\",\n" - + "\t\t\t\t\"type\": \"address\"\n" - + "\t\t\t},\n" - + "\t\t\t{\n" - + "\t\t\t\t\"name\": \"amount\",\n" - + "\t\t\t\t\"type\": \"uint256\"\n" - + "\t\t\t}\n" - + "\t\t],\n" - + "\t\t\"name\": \"testInCallcode\",\n" - + "\t\t\"outputs\": [],\n" - + "\t\t\"payable\": true,\n" - + "\t\t\"stateMutability\": \"payable\",\n" - + "\t\t\"type\": \"function\"\n" - + "\t},\n" - + "\t{\n" - + "\t\t\"constant\": false,\n" - + "\t\t\"inputs\": [\n" - + "\t\t\t{\n" - + "\t\t\t\t\"name\": \"callCAddress\",\n" - + "\t\t\t\t\"type\": \"address\"\n" - + "\t\t\t},\n" - + "\t\t\t{\n" - + "\t\t\t\t\"name\": \"amount\",\n" - + "\t\t\t\t\"type\": \"uint256\"\n" - + "\t\t\t}\n" - + "\t\t],\n" - + "\t\t\"name\": \"testIndelegateCall\",\n" - + "\t\t\"outputs\": [],\n" - + "\t\t\"payable\": true,\n" - + "\t\t\"stateMutability\": \"payable\",\n" - + "\t\t\"type\": \"function\"\n" - + "\t},\n" - + "\t{\n" - + "\t\t\"inputs\": [],\n" - + "\t\t\"payable\": true,\n" - + "\t\t\"stateMutability\": \"payable\",\n" - + "\t\t\"type\": \"constructor\"\n" - + "\t}\n" - + "]"; - byte[] contractA = PublicMethed.deployContract("A", abi, code, "", maxFeeLimit, - 1000000L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContractOuterClass.SmartContract smartContract = PublicMethed.getContract(contractA, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - code = "608060405260d2806100126000396000f300608060405260043610603e5763ffffffff7c0" - + "10000000000000000000000000000000000000000000000000000000060003504166366c99" - + "13981146043575b600080fd5b604c600435604e565b005b6040805173fffffffffffffffff" - + "fffffffffffffffffffffff3316815234602082015280820183905290517fac74fdf75f0e5" - + "a43f870f7135801b44f404be82b1dcad73423c542b840d1d64b9181900360600190a150560" - + "0a165627a7a72305820c460a35f70e363777be22b3a4ace5f95533de626073ab4e06d9bf3bbb2cffceb0029"; - abi = "[\n" - + "\t{\n" - + "\t\t\"constant\": false,\n" - + "\t\t\"inputs\": [\n" - + "\t\t\t{\n" - + "\t\t\t\t\"name\": \"amount\",\n" - + "\t\t\t\t\"type\": \"uint256\"\n" - + "\t\t\t}\n" - + "\t\t],\n" - + "\t\t\"name\": \"trans\",\n" - + "\t\t\"outputs\": [],\n" - + "\t\t\"payable\": true,\n" - + "\t\t\"stateMutability\": \"payable\",\n" - + "\t\t\"type\": \"function\"\n" - + "\t},\n" - + "\t{\n" - + "\t\t\"inputs\": [],\n" - + "\t\t\"payable\": true,\n" - + "\t\t\"stateMutability\": \"payable\",\n" - + "\t\t\"type\": \"constructor\"\n" - + "\t},\n" - + "\t{\n" - + "\t\t\"anonymous\": false,\n" - + "\t\t\"inputs\": [\n" - + "\t\t\t{\n" - + "\t\t\t\t\"indexed\": false,\n" - + "\t\t\t\t\"name\": \"\",\n" - + "\t\t\t\t\"type\": \"address\"\n" - + "\t\t\t},\n" - + "\t\t\t{\n" - + "\t\t\t\t\"indexed\": false,\n" - + "\t\t\t\t\"name\": \"\",\n" - + "\t\t\t\t\"type\": \"uint256\"\n" - + "\t\t\t},\n" - + "\t\t\t{\n" - + "\t\t\t\t\"indexed\": false,\n" - + "\t\t\t\t\"name\": \"\",\n" - + "\t\t\t\t\"type\": \"uint256\"\n" - + "\t\t\t}\n" - + "\t\t],\n" - + "\t\t\"name\": \"clog\",\n" - + "\t\t\"type\": \"event\"\n" - + "\t}\n" - + "]"; - byte[] contractC = PublicMethed.deployContract("C", abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - smartContract = PublicMethed.getContract(contractC, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - String base58C = Base58.encode58Check(contractC); - - String txid = PublicMethed.triggerContract(contractA, - "testInCall(address,uint256)", "\"" + base58C + "\",1", false, - 1, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - String logRes = ByteArray.toHexString(infoById.get().getLog(0).getData().toByteArray()); - System.out.println("000000: " + logRes); - String b = "41" + logRes.substring(24, 64); - String c = logRes.substring(64, 128); - String x = ByteArray.toHexString(contractA); - Assert.assertEquals(b, x); - Assert.assertEquals("000000000000000000000000000000000000000000000000000000000000000a", c); - - txid = PublicMethed.triggerContract(contractA, - "testIndelegateCall(address,uint256)", "\"" + base58C + "\",1", false, - 2, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("txid: " + txid + "\n" + infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - logRes = ByteArray.toHexString(infoById.get().getLog(0).getData().toByteArray()); - System.out.println("000000: " + logRes); - b = "41" + logRes.substring(24, 64); - c = logRes.substring(64, 128); - x = ByteArray.toHexString(contractExcAddress); - Assert.assertEquals(b, x); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000002", c); - - - txid = PublicMethed.triggerContract(contractA, - "testInCallcode(address,uint256)", "\"" + base58C + "\",1", false, - 3, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("txid: " + txid + "\n" + infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - logRes = ByteArray.toHexString(infoById.get().getLog(0).getData().toByteArray()); - System.out.println("000000: " + logRes); - b = "41" + logRes.substring(24, 64); - c = logRes.substring(64, 128); - x = ByteArray.toHexString(contractA); - Assert.assertEquals(b, x); - Assert.assertEquals("000000000000000000000000000000000000000000000000000000000000000a", c); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(contractExcAddress, contractExcKey, - testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/OverridePrivateFunction.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/OverridePrivateFunction.java deleted file mode 100644 index ec42f439078..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/OverridePrivateFunction.java +++ /dev/null @@ -1,106 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class OverridePrivateFunction { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] gasValueContract = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - - @Test(enabled = false, description = "test override private function") - public void test01OverridePrivateFunction() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/overridePrivateFunction.sol"; - String contractName = "B"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - gasValueContract = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(gasValueContract, - "testOverridePrivate()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Protocol.Transaction transaction = transactionExtention.getTransaction(); - int truerRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("truerRes: " + truerRes + " message:" + transaction.getRet(0).getRet()); - logger.info("transactionExtention: " + transactionExtention); - Assert.assertEquals(2, truerRes); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(contractExcAddress, contractExcKey, - testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/OverrideTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/OverrideTest001.java deleted file mode 100644 index 298311113e8..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/OverrideTest001.java +++ /dev/null @@ -1,455 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class OverrideTest001 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1000_000_000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Deploy 0.5.15 about override(Base1,Base2)") - public void test01OverrideContract515() { - String contractName = "override001"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_override001"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_override001"); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed.getTransactionInfoById(txid, - blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - txid = PublicMethed.triggerContract(contractAddress, "setValue(uint256)", "5", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "x()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(0, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "y()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(5, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - } - - @Test(enabled = true, description = "Deploy 0.6.0 about not need override") - public void test02NotNeedOverride() { - String filePath = "./src/test/resources/soliditycode/override002.sol"; - String contractName = "D"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed.getTransactionInfoById(txid, - blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - txid = PublicMethed.triggerContract(contractAddress, "setValue(uint256)", "5", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "x()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(5, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - } - - @Test(enabled = true, description = "Deploy 0.6.0 about override(Base1,Base2)") - public void test03OverrideMultipleFunctionsWithTheSameName() { - String filePath = "./src/test/resources/soliditycode/override003.sol"; - String contractName = "C"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed.getTransactionInfoById(txid, - blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - txid = PublicMethed.triggerContract(contractAddress, "setValue(uint256)", "5", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "x()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(5, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "y()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(0, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - } - - @Test(enabled = true, description = "Deploy 0.6.0 about override modifier") - public void test04OverrideModifier060() { - String filePath = "./src/test/resources/soliditycode/override004.sol"; - String contractName = "C"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed.getTransactionInfoById(txid, - blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - txid = PublicMethed.triggerContract(contractAddress, "setValue(uint256)", "7", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(1,infoById.get().getResultValue()); - Assert.assertTrue(infoById.get().getContractResult(0).toStringUtf8().contains("x must >= 6")); - - txid = PublicMethed.triggerContract(contractAddress, "setValue2(uint256)", "6", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - - txid = PublicMethed.triggerContract(contractAddress, "setValue(uint256)", "8", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "x()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(8, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - } - - @Test(enabled = true, description = "Deploy 0.5.15 about override modifier") - public void test05OverrideModifier515() { - String contractName = "C"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_override002"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_override002"); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed.getTransactionInfoById(txid, - blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - txid = PublicMethed.triggerContract(contractAddress, "setValue(uint256)", "7", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(1,infoById.get().getResultValue()); - Assert.assertTrue(infoById.get().getContractResult(0).toStringUtf8().contains("x must >= 6")); - - txid = PublicMethed.triggerContract(contractAddress, "setValue2(uint256)", "6", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - - txid = PublicMethed.triggerContract(contractAddress, "setValue(uint256)", "8", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "x()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(8, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - } - - @Test(enabled = true, description = "Deploy 0.6.0 public override external function") - public void test06PublicOverrideExternalFunction060() { - String filePath = "./src/test/resources/soliditycode/override005.sol"; - String contractName = "Test"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed.getTransactionInfoById(txid, - blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "stopped()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(0, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "i()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(32482989, ByteArray.toInt(transactionExtention.getConstantResult(0) - .toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "i2()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(-32482989, ByteArray.toInt(transactionExtention.getConstantResult(0) - .toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "ui()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(23487823, ByteArray.toInt(transactionExtention.getConstantResult(0) - .toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "origin()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - byte[] tmpAddress = new byte[20]; - System - .arraycopy(transactionExtention.getConstantResult(0).toByteArray(), 12, tmpAddress, 0, 20); - Assert.assertEquals("TW63BNR5M7LuH1fjXS7Smyza3PZXfHAAs2", - Base58.encode58Check(ByteArray.fromHexString("41" + ByteArray.toHexString(tmpAddress)))); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "b32()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert.assertEquals("b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105c", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "choice()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000003", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - } - - @Test(enabled = true, description = "Deploy 0.5.15 public override external function") - public void test07PublicOverrideExternalFunction515() { - String contractName = "Test"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_override003"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_override003"); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed.getTransactionInfoById(txid, - blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "stopped()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(0, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "i()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(32482989, ByteArray.toInt(transactionExtention.getConstantResult(0) - .toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "i2()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(-32482989, ByteArray.toInt(transactionExtention.getConstantResult(0) - .toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "ui()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(23487823, ByteArray.toInt(transactionExtention.getConstantResult(0) - .toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "origin()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - byte[] tmpAddress = new byte[20]; - System - .arraycopy(transactionExtention.getConstantResult(0).toByteArray(), 12, tmpAddress, 0, 20); - Assert.assertEquals("TW63BNR5M7LuH1fjXS7Smyza3PZXfHAAs2", - Base58.encode58Check(ByteArray.fromHexString("41" + ByteArray.toHexString(tmpAddress)))); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "b32()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert.assertEquals("b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105c", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "choice()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000003", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - } - - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - PublicMethed.sendcoin(fromAddress, balance, dev001Address, dev001Key, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/PayableTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/PayableTest.java deleted file mode 100644 index d343542d350..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/PayableTest.java +++ /dev/null @@ -1,158 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class PayableTest { - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private byte[] contractAddress; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed - .sendcoin(testAddress001, 1000_000_000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - - String filePath = "src/test/resources/soliditycode/payable001.sol"; - String contractName = "PayableTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 10000, 100, null, - testFoundationKey, testFoundationAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "payable(address) transfer") - public void tryCatchTest001() { - - Account account = PublicMethed - .queryAccount(PublicMethed.decode58Check( - "TBXSw8fM4jpQkGc6zZjsVABFpVN7UvXPdV"), blockingStubFull); - Long balanceBefore = account.getBalance(); - - String methodStr = "receiveMoneyTransfer(address,uint256)"; - String argStr = "\"TBXSw8fM4jpQkGc6zZjsVABFpVN7UvXPdV\",3"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Long balanceAfter = PublicMethed.queryAccount(PublicMethed.decode58Check( - "TBXSw8fM4jpQkGc6zZjsVABFpVN7UvXPdV"), blockingStubFull).getBalance(); - Assert.assertEquals(balanceBefore + 3,balanceAfter.longValue()); - } - - @Test(enabled = true, description = "payable(address) send") - public void tryCatchTest002() { - - Account account = PublicMethed - .queryAccount(PublicMethed.decode58Check( - "TBXSw8fM4jpQkGc6zZjsVABFpVN7UvXPdV"), blockingStubFull); - Long balanceBefore = account.getBalance(); - - String methodStr = "receiveMoneySend(address,uint256)"; - String argStr = "\"TBXSw8fM4jpQkGc6zZjsVABFpVN7UvXPdV\",3"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Long balanceAfter = PublicMethed.queryAccount(PublicMethed.decode58Check( - "TBXSw8fM4jpQkGc6zZjsVABFpVN7UvXPdV"), blockingStubFull).getBalance(); - Assert.assertEquals(balanceBefore + 3,balanceAfter.longValue()); - } - - @Test(enabled = true, description = "payable(address(contract)) transfer") - public void tryCatchTest003() { - - String filePath = "src/test/resources/soliditycode/payable001.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] AContract = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0, 100, null, - testKey001, testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - - Account account = PublicMethed - .queryAccount(AContract, blockingStubFull); - Long balanceBefore = account.getBalance(); - - String methodStr = "receiveMoneyTransferWithContract(address,uint256)"; - String argStr = "\"" + Base58.encode58Check(AContract) + "\",3"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Long balanceAfter = PublicMethed.queryAccount(AContract, blockingStubFull).getBalance(); - Assert.assertEquals(balanceBefore + 3,balanceAfter.longValue()); - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/SelectorTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/SelectorTest.java deleted file mode 100644 index ed322d8970c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/SelectorTest.java +++ /dev/null @@ -1,104 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class SelectorTest { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "./src/test/resources/soliditycode/selector.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - final String aContractAddress = ByteArray.toHexString(contractAddress); - - contractName = "testSelector"; - retMap = PublicMethed.getBycodeAbi(filePath, contractName); - abi = retMap.get("abI").toString(); - code = retMap.get("byteCode").toString(); - code = PublicMethed.replaceCode(code, aContractAddress.substring(1)); - logger.info("code:" + code); - - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Get the selector of public or external library functions " - + "through member variables") - public void test01GetSelector() { - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getselector2()", "#", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertThat(transactionExtention.getResult().getCode().toString(), - containsString("SUCCESS")); - logger.info("result: " + ByteArray - .toHexString(transactionExtention.getConstantResult(0).toByteArray())); - Assert.assertEquals("f8b2cb4f", PublicMethed.removeAll0sAtTheEndOfHexStr(ByteArray - .toHexString(transactionExtention.getConstantResult(0).toByteArray()).substring(0, 64))); - Assert.assertEquals("b4cef28d", PublicMethed.removeAll0sAtTheEndOfHexStr(ByteArray - .toHexString(transactionExtention.getConstantResult(0).toByteArray()).substring(64))); - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/SlotAndOffsetNewGrammer.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/SlotAndOffsetNewGrammer.java deleted file mode 100644 index 94ef107b365..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/SlotAndOffsetNewGrammer.java +++ /dev/null @@ -1,153 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class SlotAndOffsetNewGrammer { - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1000_000_000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - /** - * trigger contract and assert. - */ - public void assertResult(byte[] contractAddress) { - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, "getA()", "", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - - String res = "0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000000"; - System.out.println(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(res, - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - - txid = PublicMethed.triggerContract(contractAddress, "getE()", "", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - res = "0000000000000000000000000000000000000000000000000000000000000004" - + "0000000000000000000000000000000000000000000000000000000000000000"; - System.out.println(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(res, - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - - } - - @Test(enabled = true, description = "Deploy 0.6.x new grammer") - public void testSlotAndOffsetOldVersion() { - String contractName = "A"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_slotAndOffset_06x"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_slotAndOffset_06x"); - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed.getTransactionInfoById(txid, - blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - assertResult(contractAddress); - - } - - @Test(enabled = true, description = "Deploy 0.7.0 new grammer") - public void testSlotAndOffsetNew() { - String filePath = "./src/test/resources/soliditycode/slotAndOffsetNewGrammer.sol"; - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed.getTransactionInfoById(txid, - blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - assertResult(contractAddress); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/StringSplitTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/StringSplitTest.java deleted file mode 100644 index 0938f4d165e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/StringSplitTest.java +++ /dev/null @@ -1,167 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class StringSplitTest { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "./src/test/resources/soliditycode/stringSplit.sol"; - String contractName = "testStringSplit"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "get s1 n1") - public void test01GetS1N1() { - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getS1()", "#", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertThat(transactionExtention.getResult().getCode().toString(), - containsString("SUCCESS")); - Assert.assertEquals("s12,./", - PublicMethed.hexStringToString(PublicMethed.removeAll0sAtTheEndOfHexStr( - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())) - .substring(128))); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getS1N1()", "#", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertThat(transactionExtention.getResult().getCode().toString(), - containsString("SUCCESS")); - Assert.assertEquals("s12,./", - PublicMethed.hexStringToString(PublicMethed.removeAll0sAtTheEndOfHexStr( - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())) - .substring(128))); - } - - @Test(enabled = true, description = "get s2 n2") - public void test01GetS2N2() { - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getS2()", "#", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertThat(transactionExtention.getResult().getCode().toString(), - containsString("SUCCESS")); - Assert.assertEquals("s123?\\'.", - PublicMethed.hexStringToString(PublicMethed.removeAll0sAtTheEndOfHexStr( - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())) - .substring(128))); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getS2N2()", "#", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertThat(transactionExtention.getResult().getCode().toString(), - containsString("SUCCESS")); - Assert.assertEquals("s123?\'.", - PublicMethed.hexStringToString(PublicMethed.removeAll0sAtTheEndOfHexStr( - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())) - .substring(128))); - } - - @Test(enabled = true, description = "get s3 n3") - public void test01GetS3N3() { - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getS3()", "#", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertThat(transactionExtention.getResult().getCode().toString(), - containsString("SUCCESS")); - Assert.assertEquals("AB", - PublicMethed.hexStringToString(PublicMethed.removeAll0sAtTheEndOfHexStr( - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())) - .substring(128))); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getS3N3()", "#", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertThat(transactionExtention.getResult().getCode().toString(), - containsString("SUCCESS")); - Assert.assertEquals("AB", - PublicMethed.hexStringToString(PublicMethed.removeAll0sAtTheEndOfHexStr( - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())) - .substring(128))); - } - - @Test(enabled = true, description = "get s4 n4") - public void test01GetS4N4() { - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getS4()", "#", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertThat(transactionExtention.getResult().getCode().toString(), - containsString("SUCCESS")); - Assert.assertEquals("AB", - PublicMethed.hexStringToString(PublicMethed.removeAll0sAtTheEndOfHexStr( - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())) - .substring(128))); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "getS4N4()", "#", false, 0, - 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertThat(transactionExtention.getResult().getCode().toString(), - containsString("SUCCESS")); - Assert.assertEquals("AB", - PublicMethed.hexStringToString(PublicMethed.removeAll0sAtTheEndOfHexStr( - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())) - .substring(128))); - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/TvmVote.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/TvmVote.java deleted file mode 100644 index b6d80521c87..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/TvmVote.java +++ /dev/null @@ -1,334 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.contract.SmartContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class TvmVote { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - private final String witnessKey = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress = PublicMethed.getFinalAddress(witnessKey); - byte[] mapKeyContract = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - int freezeCount = 100000000; - int voteCount = 1; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 300100_000_000L, - testNetAccountAddress, testNetAccountKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/tvmVote.sol"; - String contractName = "TestVote"; - - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - mapKeyContract = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000000L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContractOuterClass.SmartContract smartContract = PublicMethed.getContract(mapKeyContract, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = true, description = "query reward balance") - public void test01QueryRewardBalance() { - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "queryRewardBalance()", "#", true, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - long trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info("result: " + trueRes); - Assert.assertEquals(0, trueRes); - - GrpcAPI.BytesMessage bytesMessage = GrpcAPI.BytesMessage.newBuilder().setValue(ByteString - .copyFrom(mapKeyContract)) - .build(); - long reward = blockingStubFull.getRewardInfo(bytesMessage).getNum(); - org.testng.Assert.assertEquals(trueRes, reward); - } - - - @Test(enabled = true, description = "freeze balance and vote witness") - public void test02VoteWitness() { - String methodStr = "freeze(address,uint256,uint256)"; - String receiverAdd = Base58.encode58Check(mapKeyContract); - String args = "\"" + receiverAdd + "\"," + freezeCount + ",1"; - String triggerTxid = PublicMethed.triggerContract(mapKeyContract, - methodStr, args, false, 0, maxFeeLimit, "0", 0, - contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - Protocol.InternalTransaction internal = transactionInfo.get().getInternalTransactions(0); - String note = internal.getNote().toStringUtf8(); - Assert.assertEquals("freezeForEnergy", note); - Assert.assertEquals(freezeCount, internal.getCallValueInfo(0).getCallValue()); - - String witness58Add = Base58.encode58Check(witnessAddress); - args = "[\"" + witness58Add + "\"],[" + voteCount + "]"; - logger.info("vote args: " + args); - methodStr = "voteWitness(address[],uint256[])"; - triggerTxid = PublicMethed.triggerContract(mapKeyContract, methodStr, args, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - internal = transactionInfo.get().getInternalTransactions(0); - note = internal.getNote().toStringUtf8(); - Assert.assertEquals("voteWitness", note); - Assert.assertTrue(internal.getExtra().length() > 1); - - Protocol.Account info = PublicMethed.queryAccount(mapKeyContract, blockingStubFull); - int voteCount = info.getVotesCount(); - logger.info("voteCount: " + voteCount); - Assert.assertEquals(1, voteCount); - } - - @Test(enabled = true, description = "query contract address is Sr Candidate or not") - public void test03IsSrCandidate() { - String args = "\"" + Base58.encode58Check(mapKeyContract) + "\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "isWitness(address)", args, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info(trueRes + ""); - Assert.assertEquals(0, 0); - } - - @Test(enabled = true, description = "query sr address is Sr Candidate or not") - public void test04IsSrCandidate() { - String args = "\"" + Base58.encode58Check(witnessAddress) + "\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "isWitness(address)", args, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info(trueRes + ""); - Assert.assertEquals(1, 1); - } - - @Test(enabled = true, description = "query zero address is Sr Candidate or not") - public void test05IsSrCandidate() { - String args = "\"T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "isWitness(address)", args, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info(trueRes + ""); - Assert.assertEquals(0, 0); - } - - @Test(enabled = true, description = "query sr's total vote count") - public void test06querySrTotalVoteCount() { - String args = "\"" + Base58.encode58Check(witnessAddress) + "\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "queryTotalVoteCount(address)", args, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info(trueRes + ""); - Assert.assertEquals(0, trueRes); - } - - @Test(enabled = true, description = "query contract's total vote count") - public void test07queryContractTotalVoteCount() { - String args = "\"" + Base58.encode58Check(mapKeyContract) + "\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "queryTotalVoteCount(address)", args, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info(trueRes + ""); - Assert.assertEquals(freezeCount / 1000000, trueRes); - } - - @Test(enabled = true, description = "query vote count") - public void test08queryVoteCount() { - String from = Base58.encode58Check(mapKeyContract); - String to = Base58.encode58Check(witnessAddress); - String args = "\"" + from + "\",\"" + to + "\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "queryVoteCount(address,address)", args, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info(trueRes + ""); - Assert.assertEquals(voteCount, trueRes); - } - - @Test(enabled = true, description = "query contract used vote count") - public void test09queryUsedVoteCount() { - String from = Base58.encode58Check(mapKeyContract); - String args = "\"" + from + "\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "queryUsedVoteCount(address)", args, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info(trueRes + ""); - Assert.assertEquals(voteCount, trueRes); - } - - @Test(enabled = true, description = "query witnesses received vote count") - public void test10queryReceivedVoteCount() { - String witness = Base58.encode58Check(witnessAddress); - String args = "\"" + witness + "\""; - GrpcAPI.TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(mapKeyContract, - "queryReceivedVoteCount(address)", args, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - int trueRes = ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray()); - logger.info(trueRes + ""); - Assert.assertTrue(trueRes > 0); - Optional list = PublicMethed.listWitnesses(blockingStubFull); - long receiveCount = 0; - String temAdd; - for (int i = 0; i < list.get().getWitnessesCount(); i++) { - temAdd = Base58.encode58Check(list.get().getWitnesses(i).getAddress().toByteArray()); - if (witness.equals(temAdd)) { - receiveCount = list.get().getWitnesses(i).getVoteCount(); - break; - } - } - Assert.assertEquals(trueRes, receiveCount); - } - - @Test(enabled = true, description = "withdraw reward") - public void test11WithdrawReward() { - String methodStr = "withdrawReward()"; - String triggerTxid = PublicMethed.triggerContract(mapKeyContract, methodStr, "#", false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Protocol.InternalTransaction internal = transactionInfo.get().getInternalTransactions(0); - String note = internal.getNote().toStringUtf8(); - Assert.assertEquals("withdrawReward", note); - Assert.assertEquals(1, internal.getCallValueInfoCount()); - Assert.assertEquals("", internal.getCallValueInfo(0).toString()); - } - - @Test(enabled = true, description = "unfreeze energy") - public void test12Unfreeze() { - String methodStr = "unfreeze(address,uint256)"; - String args = "\"" + Base58.encode58Check(mapKeyContract) + "\",1"; - String triggerTxid = PublicMethed.triggerContract(mapKeyContract, methodStr, args, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - - Protocol.InternalTransaction internal = transactionInfo.get().getInternalTransactions(0); - String note = internal.getNote().toStringUtf8(); - Assert.assertEquals("unfreezeForEnergy", note); - Assert.assertEquals(freezeCount, internal.getCallValueInfo(0).getCallValue()); - } - - @Test(enabled = true, description = "kill me") - public void test13Suicide() { - String methodStr = "killme(address)"; - String args = "\"" + Base58.encode58Check(witnessAddress) + "\""; - String triggerTxid = PublicMethed.triggerContract(mapKeyContract, methodStr, args, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional transactionInfo = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(Protocol.Transaction.Result.contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContractOuterClass.SmartContract smartContract = PublicMethed - .getContract(mapKeyContract, blockingStubFull); - Assert.assertEquals("", smartContract.getAbi().toString()); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(contractExcAddress, contractExcKey, - testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/VirtualTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/VirtualTest001.java deleted file mode 100644 index 6657c66035e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/VirtualTest001.java +++ /dev/null @@ -1,207 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class VirtualTest001 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1000_000_000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Deploy 0.5.15 about virtual") - public void test01OverrideContract515() { - String contractName = "Z"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_virtual001"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_virtual001"); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed.getTransactionInfoById(txid, - blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - txid = PublicMethed.triggerContract(contractAddress, "setValue(uint256)", "5", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - - txid = PublicMethed.triggerContract(contractAddress, "setBool(bool)", "true", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - - txid = PublicMethed.triggerContract(contractAddress, "setString(string)", "\"1q2w\"", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "x()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(5, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "y()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(1, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "z()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals("0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000004" - + "3171327700000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - } - - @Test(enabled = true, description = "Deploy 0.6.0 about virtual") - public void test02OverrideContract060() { - String filePath = "./src/test/resources/soliditycode/virtual001.sol"; - String contractName = "Z"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed.getTransactionInfoById(txid, - blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - txid = PublicMethed.triggerContract(contractAddress, "setValue(uint256)", "5", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - - txid = PublicMethed.triggerContract(contractAddress, "setBool(bool)", "true", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - - txid = PublicMethed.triggerContract(contractAddress, "setString(string)", "\"1q2w\"", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "x()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(5, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "y()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals(1, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "z()", "#", - false, 0, 0, "0", 0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals("SUCCESS", transactionExtention.getResult().getCode().toString()); - Assert - .assertEquals("0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000004" - + "3171327700000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionExtention.getConstantResult(0).toByteArray())); - } - - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - PublicMethed.sendcoin(fromAddress, balance, dev001Address, dev001Key, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/assemblyTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/assemblyTest.java deleted file mode 100644 index 601c23ecd7c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/assemblyTest.java +++ /dev/null @@ -1,118 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class assemblyTest { - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "./src/test/resources/soliditycode/assemblyTest.sol"; - String contractName = "assemblyTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "get assembly references fuction number, type: uint") - public void test01AssemblyReferencesUint() { - String methodStr = "getZuint()"; - String argStr = ""; - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit,"0",0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals(1,ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - methodStr = "getZuint2()"; - String txid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - int ContractResult = ByteArray.toInt(infoById.get() - .getContractResult(0).toByteArray()); - Assert.assertEquals(1,ContractResult); - - - } - - @Test(enabled = true, description = "get assembly references fuction number, type: boolen") - public void test02AssemblyReferencesBoolen() { - String methodStr = "getZbool()"; - String argStr = ""; - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit,"0",0, dev001Address, dev001Key, blockingStubFull); - Assert.assertEquals(1,ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - - methodStr = "getZbool2()"; - String txid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0,infoById.get().getResultValue()); - int ContractResult = ByteArray.toInt(infoById.get() - .getContractResult(0).toByteArray()); - Assert.assertEquals(1,ContractResult); - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/calldataTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/calldataTest.java deleted file mode 100644 index dc0d0359f9f..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/calldataTest.java +++ /dev/null @@ -1,155 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class calldataTest { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - @Test(enabled = true, description = "Deploy contract") - public void test01DeployContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1000_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 100_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(dev001Key, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = accountResource.getEnergyUsed(); - Long beforeNetUsed = accountResource.getNetUsed(); - Long beforeFreeNetUsed = accountResource.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/calldata.sol"; - String contractName = "C"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Protocol.Account infoafter = PublicMethed.queryAccount(dev001Key, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - PublicMethed.sendcoin(fromAddress, balance, dev001Address, dev001Key, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/constructorDefaultsTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/constructorDefaultsTest.java deleted file mode 100644 index 7c6a906b5ff..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/constructorDefaultsTest.java +++ /dev/null @@ -1,105 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class constructorDefaultsTest { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(dev001Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Constructor default test") - public void Test01ConstructorDefault() { - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 200000000L, fromAddress, testKey002, blockingStubFull)); - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - String filePath = "./src/test/resources/soliditycode/ConstructorDefaults.sol"; - String contractName = "testIsContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String constructorStr = "constructor(bool)"; - String data = "0"; - String txid = PublicMethed - .deployContractWithConstantParame(contractName, abi, code, constructorStr, data, "", - maxFeeLimit, 0L, 100, null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - byte[] contractaddress = null; - Optional info = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(info.toString()); - Assert.assertTrue(info.get().getResultValue() == 0); - data = "false"; - txid = PublicMethed - .deployContractWithConstantParame(contractName, abi, code, constructorStr, data, "", - maxFeeLimit, 0L, 100, null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - info = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(info.toString()); - Assert.assertTrue(info.get().getResultValue() == 0); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - PublicMethed.sendcoin(fromAddress, balance, dev001Address, dev001Key, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/enumAndStructTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/enumAndStructTest.java deleted file mode 100644 index ddffd357881..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/enumAndStructTest.java +++ /dev/null @@ -1,89 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class enumAndStructTest { - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private byte[] contractAddress; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - String filePath = "src/test/resources/soliditycode/enumAndStruct.sol"; - String contractName = "enumAndStructTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0, 100, null, - testFoundationKey, testFoundationAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "get Enum and Struct") - public void EnumAndStructTest001() { - - - String methodStr = "getvalue()"; - String argStr = ""; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testFoundationAddress, testFoundationKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals(1, - ByteArray.toInt(transactionInfo.get().getContractResult(0).toByteArray())); - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/fallbackOldVersion.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/fallbackOldVersion.java deleted file mode 100644 index aa5839b9b86..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/fallbackOldVersion.java +++ /dev/null @@ -1,156 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class fallbackOldVersion { - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddressCall = null; - byte[] contractAddressTest0 = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - PublicMethed - .sendcoin(contractExcAddress, 1000_000_000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_fallbackOldVersionTest"); - String code = Configuration.getByPath("testng.conf") - .getString("code.code_fallbackOldVersionTest"); - String contractName = "Test0"; - contractAddressTest0 = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, - 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_fallbackOldversionCall"); - code = Configuration.getByPath("testng.conf") - .getString("code.code_fallbackOldVersionCall"); - contractName = "Call"; - contractAddressCall = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, - 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "test fallback") - public void test01FallbakTest() { - Protocol.Account info; - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - logger.info("beforeBalance:" + beforeBalance); - String txid = ""; - String method = "call(address)"; - long value = 10000; - String para = "\"" + Base58.encode58Check(contractAddressTest0) + "\""; - txid = PublicMethed.triggerContract(contractAddressCall, method, para, false, value, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - logger.info("fee:" + fee); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - logger.info("afterBalance:" + afterBalance); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee + value == beforeBalance); - - txid = PublicMethed.triggerContract(contractAddressCall, method, para, false, 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - logger.info(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001", - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - } - - //@AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractAddressCall, contractExcKey, testNetAccountAddress, - blockingStubFull); - PublicMethed - .freedResource(contractAddressTest0, contractExcKey, testNetAccountAddress, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/fallbackReceive.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/fallbackReceive.java deleted file mode 100644 index 517d9f1aa18..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/fallbackReceive.java +++ /dev/null @@ -1,376 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class fallbackReceive { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddressCaller = null; - byte[] contractAddressTest0 = null; - byte[] contractAddressTest1 = null; - byte[] contractAddressTest2 = null; - byte[] contractAddressTestPayable = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - PublicMethed - .sendcoin(contractExcAddress, 1000_000_000_000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/fallbackUpgrade.sol"; - String contractName = "Caller"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddressCaller = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, - null, contractExcKey, - contractExcAddress, blockingStubFull); - contractName = "Test0"; - retMap = PublicMethed.getBycodeAbi(filePath, contractName); - code = retMap.get("byteCode").toString(); - abi = retMap.get("abI").toString(); - contractAddressTest0 = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, - 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - contractName = "Test1"; - retMap = PublicMethed.getBycodeAbi(filePath, contractName); - code = retMap.get("byteCode").toString(); - abi = retMap.get("abI").toString(); - contractAddressTest1 = PublicMethed - .deployContractFallback(contractName, abi, code, "", maxFeeLimit, 0L, - 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - contractName = "Test2"; - retMap = PublicMethed.getBycodeAbi(filePath, contractName); - code = retMap.get("byteCode").toString(); - abi = retMap.get("abI").toString(); - contractAddressTest2 = PublicMethed - .deployContractFallback(contractName, abi, code, "", maxFeeLimit, 0L, - 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - contractName = "TestPayable"; - retMap = PublicMethed.getBycodeAbi(filePath, contractName); - code = retMap.get("byteCode").toString(); - abi = retMap.get("abI").toString(); - contractAddressTestPayable = PublicMethed - .deployContractFallback(contractName, abi, code, "", maxFeeLimit, 0L, - 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "contract test0 has no fallback method") - public void test001NoFallback() { - String txid = ""; - String method = "hello()"; - txid = PublicMethed.triggerContract(contractAddressTest0, - method, "#", false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("getResult: " + infoById.get().getResultValue()); - Assert.assertEquals("FAILED", infoById.get().getResult().toString()); - } - - @Test(enabled = true, description = "contract test0 has no fallback method") - public void test002NoFallback() { - String txid = ""; - String method = "callTest0(address)"; - String para = "\"" + Base58.encode58Check(contractAddressTest0) + "\""; - txid = PublicMethed.triggerContract(contractAddressCaller, - method, para, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("getResult: " + infoById.get().getResultValue()); - Assert.assertEquals("FAILED", infoById.get().getResult().toString()); - } - - @Test(enabled = true, description = "contract test01 has fallback method") - public void test011Fallback() { - String txid = ""; - String method = "callTest1(address)"; - String para = "\"" + Base58.encode58Check(contractAddressTest1) + "\""; - txid = PublicMethed.triggerContract(contractAddressCaller, - method, para, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("getResult: " + infoById.get().getResultValue()); - Assert.assertEquals("SUCESS", infoById.get().getResult().toString()); - List logList = infoById.get().getLogList(); - if (!Objects.isNull(logList)) { - for (Protocol.TransactionInfo.Log log : logList) { - //logger.info("LOG data info:" + tmp); - Assert.assertEquals("fallback", - PublicMethed.getContractStringMsg(log.getData().toByteArray())); - } - } - } - - @Test(enabled = true, description = "contract test01 has fallback method") - public void test012Fallback() { - String txid = ""; - String method = "callTest2(address)"; - String para = "\"" + Base58.encode58Check(contractAddressTest1) + "\""; - txid = PublicMethed.triggerContract(contractAddressCaller, - method, para, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("getResult: " + infoById.get().getResultValue()); - Assert.assertEquals("REVERT", infoById.get().getReceipt().getResult().toString()); - } - - @Test(enabled = true, description = "contract test01 has fallback method") - public void test013Fallback() { - String txid = ""; - txid = PublicMethed.triggerContract(contractAddressTest1, - "hello()", "#", false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("getResult: " + infoById.get().getResultValue()); - Assert.assertEquals("SUCESS", infoById.get().getResult().toString()); - - txid = PublicMethed.triggerContract(contractAddressTest1, - "hello2()", "#", false, - 100000, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("result:" + infoById.get().getReceipt().getResult()); - Assert.assertEquals("REVERT", infoById.get().getReceipt().getResult().toString()); - } - - @Test(enabled = true, description = "contract test02 has fallback payable method") - public void test021FallbackPayable() { - Protocol.Account info; - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - logger.info("beforeBalance:" + beforeBalance); - String txid = ""; - long value = 10000; - txid = PublicMethed.triggerContract(contractAddressTest2, "hello()", "#", false, value, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("result:" + infoById.get().getReceipt().getResult()); - Assert.assertEquals("SUCESS", infoById.get().getResult().toString()); - Long fee = infoById.get().getFee(); - logger.info("fee:" + fee); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - logger.info("afterBalance:" + afterBalance); - Assert.assertTrue(afterBalance + fee + value == beforeBalance); - - String method = "callTest2(address)"; - String para = "\"" + Base58.encode58Check(contractAddressTest2) + "\""; - txid = PublicMethed.triggerContract(contractAddressCaller, method, para, false, value, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("callTest2 result:" + infoById.get().getReceipt().getResult()); - Assert.assertEquals("SUCESS", infoById.get().getResult().toString()); - fee = infoById.get().getFee(); - logger.info("callTest2 fee:" + fee); - infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance2 = infoafter.getBalance(); - logger.info("callTest2 afterBalance:" + afterBalance); - Assert.assertTrue(afterBalance2 + fee + value == afterBalance); - } - - @Test(enabled = true, description = "contract TestPayable has fallback and receive") - public void test041FallbackReceive() { - String txid = ""; - String method = "callTestPayable1(address)"; - String para = "\"" + Base58.encode58Check(contractAddressTestPayable) + "\""; - txid = PublicMethed.triggerContract(contractAddressCaller, - method, para, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("getResult: " + infoById.get().getResultValue()); - Assert.assertEquals("SUCESS", infoById.get().getResult().toString()); - Assert.assertEquals("fallback", - PublicMethed.getContractStringMsg(infoById.get().getLog(0).getData().toByteArray())); - Assert.assertEquals("receive", - PublicMethed.getContractStringMsg(infoById.get().getLog(1).getData().toByteArray())); - } - - @Test(enabled = true, description = "contract TestPayable has fallback and receive") - public void test042FallbackReceive() { - Protocol.Account info; - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - String txid = ""; - Long beforeBalance = info.getBalance(); - logger.info("beforeBalance:" + beforeBalance); - String method = "callTest2(address)"; - long value = 10000; - String para = "\"" + Base58.encode58Check(contractAddressTestPayable) + "\""; - txid = PublicMethed.triggerContract(contractAddressCaller, - method, para, false, - value, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals("fallback", - PublicMethed.getContractStringMsg(infoById.get().getLog(0).getData().toByteArray())); - - Long fee = infoById.get().getFee(); - logger.info("fee:" + fee); - Protocol.Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - logger.info("afterBalance:" + afterBalance); - Assert.assertTrue(afterBalance + fee + value == beforeBalance); - } - - @Test(enabled = true, description = "contract TestPayable has fallback and receive") - public void test05FallbackReceive() { - String txid = ""; - long value = 10000; - txid = PublicMethed.triggerContract(contractAddressTestPayable, - "method()", "#", false, - value, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals("SUCESS", infoById.get().getResult().toString()); - Assert.assertEquals("fallback", - PublicMethed.getContractStringMsg(infoById.get().getLog(0).getData().toByteArray())); - - Protocol.Account infoafter = PublicMethed - .queryAccount(contractAddressTestPayable, blockingStubFull); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractAddressTestPayable, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - logger.info("contract balance:" + afterBalance.longValue()); - Assert.assertEquals(11000, afterBalance.longValue()); - - txid = PublicMethed.triggerContract(contractAddressTestPayable, - "#", "#", false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.get().getResult().toString()); - Assert.assertEquals("SUCESS", infoById.get().getResult().toString()); - Assert.assertEquals("receive", - PublicMethed.getContractStringMsg(infoById.get().getLog(0).getData().toByteArray())); - - } - - //@AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractAddressTest0, contractExcKey, testNetAccountAddress, - blockingStubFull); - PublicMethed - .freedResource(contractAddressTest1, contractExcKey, testNetAccountAddress, - blockingStubFull); - PublicMethed - .freedResource(contractAddressTest2, contractExcKey, testNetAccountAddress, - blockingStubFull); - PublicMethed - .freedResource(contractAddressTestPayable, contractExcKey, testNetAccountAddress, - blockingStubFull); - PublicMethed - .freedResource(contractAddressCaller, contractExcKey, testNetAccountAddress, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/mappingGetterTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/mappingGetterTest.java deleted file mode 100644 index 07e4eefa4c9..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/mappingGetterTest.java +++ /dev/null @@ -1,158 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class mappingGetterTest { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - @Test(enabled = true, description = "Deploy contract") - public void test01DeployContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1000_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 100_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(dev001Key, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = accountResource.getEnergyUsed(); - Long beforeNetUsed = accountResource.getNetUsed(); - Long beforeFreeNetUsed = accountResource.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/mappingGetter.sol"; - String contractName = "mappingGetter"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Protocol.Account infoafter = PublicMethed.queryAccount(dev001Key, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - PublicMethed.sendcoin(fromAddress, balance, dev001Address, dev001Key, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/stateVariableShadowing.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/stateVariableShadowing.java deleted file mode 100644 index a5b78970469..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/stateVariableShadowing.java +++ /dev/null @@ -1,140 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class stateVariableShadowing { - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed - .sendcoin(contractExcAddress, 1000_000_000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/stateVariableShadowing.sol"; - String contractName = "stateVariableShadowing"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Verify that the compilation is successful") - public void test01VerifyCompile() { - Protocol.Account info; - GrpcAPI.AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - ArrayList methods = new ArrayList(); - methods.add("setValue2(uint256)"); - methods.add("setValue3(uint256)"); - for (String tmp : methods) { - System.out.println(tmp); - txid = PublicMethed.triggerContract(contractAddress, - tmp, "100", false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertEquals(100, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - } - } - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/typeNameTest.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/typeNameTest.java deleted file mode 100644 index 4d3b3162448..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/newGrammar/typeNameTest.java +++ /dev/null @@ -1,174 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.newGrammar; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class typeNameTest { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - @Test(enabled = true, description = "Deploy contract") - public void test01DeployContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1000_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 100_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(dev001Key, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = accountResource.getEnergyUsed(); - Long beforeNetUsed = accountResource.getNetUsed(); - Long beforeFreeNetUsed = accountResource.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/typeName.sol"; - String contractName = "TypeName"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Protocol.Account infoafter = PublicMethed.queryAccount(dev001Key, blockingStubFull); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(dev001Address, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - - @Test(enabled = true, description = "Trigger testTypeName function") - public void test02TriggerTestTypeNameFunction() { - final String txid = PublicMethed.triggerContract(contractAddress, - "testTypeName()", "#", false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - logger.info("infoById:" + infoById.get()); - Assert.assertTrue(infoById.get().getContractResult(0).toStringUtf8() - .contains("TypeName")); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - PublicMethed.sendcoin(fromAddress, balance, dev001Address, dev001Key, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand001.java deleted file mode 100644 index 5c917469f58..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand001.java +++ /dev/null @@ -1,253 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.shiftcommand; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ShiftCommand001 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - - @Test(enabled = true, description = "Trigger old ShiftLeft ShiftRight") - public void test1OldInstruction() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TvmOldCommand001.sol"; - String contractName = "binaryRightContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - String num = "1"; - txid = PublicMethed.triggerContract(contractAddress, - "binaryMoveR(uint256)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - txid = PublicMethed.triggerContract(contractAddress, - "binaryLiftR(uint256)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - - } - - @Test(enabled = true, description = "Trigger new ShiftLeft ShiftRight ShiftRightSigned") - public void test2NewInstruction() { - String filePath = "src/test/resources/soliditycode/ShiftCommand001.sol"; - String contractName = "TestBitwiseShift"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - String num = "1" + "," + "5"; - - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(uint256,uint256)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - txid = PublicMethed.triggerContract(contractAddress, - "shlTest(uint256,uint256)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertEquals(10, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - txid = PublicMethed.triggerContract(contractAddress, - "shrTest(uint256,uint256)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertEquals(2, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand002.java deleted file mode 100644 index 51ba064d336..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand002.java +++ /dev/null @@ -1,265 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.shiftcommand; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ShiftCommand002 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode).usePlaintext().build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - - @Test(enabled = true, description = "OLd compiler compile shift instruction") - public void test1Oldcompile() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "TestBitwiseShift"; - String code = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a5" - + "7600080fd5b506101478061003a6000396000f3006080604052600436106100565763ffffffff7c0100" - + "000000000000000000000000000000000000000000000000000000600035041663614eb4da811461005" - + "b578063b5675d6d146100a2578063baf27c0c146100d7575b600080fd5b34801561006757600080fd5b" - + "50d3801561007457600080fd5b50d2801561008157600080fd5b5061009060043560243561010c565b6" - + "0408051918252519081900360200190f35b3480156100ae57600080fd5b50d380156100bb57600080fd" - + "5b50d280156100c857600080fd5b50610090600435602435610111565b3480156100e357600080fd5b5" - + "0d380156100f057600080fd5b50d280156100fd57600080fd5b50610090600435602435610116565b90" - + "1b90565b901d90565b901c905600a165627a7a723058200d5cc53ffdc6db62c4d7414d8b7d95c98218e" - + "50b4c1ea5961d527de1439733450029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"num\",\"type\":\"uint256\"}," - + "{\"name\":\"input\",\"type\":\"uint256\"}],\"name\":\"shlTest\",\"outputs\":" - + "[{\"name\":\"out\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":" - + "\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":" - + "\"num\",\"type\":\"uint256\"},{\"name\":\"input\",\"type\":\"uint256\"}],\"name" - + "\":\"sarTest\",\"outputs\":[{\"name\":\"out\",\"type\":\"bytes32\"}],\"payable" - + "\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant" - + "\":false,\"inputs\":[{\"name\":\"num\",\"type\":\"uint256\"},{\"name\":\"input\"" - + ",\"type\":\"uint256\"}],\"name\":\"shrTest\",\"outputs\":[{\"name\":\"out\",\"" - + "type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"" - + "type\":\"function\"}]"; - - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - String num = "1" + "," + "5"; - - txid = PublicMethed - .triggerContract(contractAddress, "sarTest(uint256,uint256)", num, false, 0, maxFeeLimit, - contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - txid = PublicMethed - .triggerContract(contractAddress, "shlTest(uint256,uint256)", num, false, 0, maxFeeLimit, - contractExcAddress, contractExcKey, blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - txid = PublicMethed - .triggerContract(contractAddress, "shrTest(uint256,uint256)", num, false, 0, maxFeeLimit, - contractExcAddress, contractExcKey, blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - } - - @Test(enabled = true, description = "New compiler compile shift instruction") - public void test2Newcompile() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - String filePath = "src/test/resources/soliditycode/ShiftCommand001.sol"; - String contractName = "TestBitwiseShift"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - String num = "1" + "," + "5"; - - txid = PublicMethed - .triggerContract(contractAddress, "sarTest(uint256,uint256)", num, false, 0, maxFeeLimit, - contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - txid = PublicMethed - .triggerContract(contractAddress, "shlTest(uint256,uint256)", num, false, 0, maxFeeLimit, - contractExcAddress, contractExcKey, blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - txid = PublicMethed - .triggerContract(contractAddress, "shrTest(uint256,uint256)", num, false, 0, maxFeeLimit, - contractExcAddress, contractExcKey, blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand003.java deleted file mode 100644 index b974a52c3ce..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand003.java +++ /dev/null @@ -1,332 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.shiftcommand; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.DataWord; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ShiftCommand003 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Trigger new ShiftLeft with displacement number too short ") - public void test1ShiftLeft() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/ShiftCommand001.sol"; - String contractName = "TestBitwiseShift"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x01")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - logger.info("param:" + param); - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "shlTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - - @Test(enabled = true, description = "Trigger new ShiftRight with displacement number too short ") - public void test2ShiftRight() { - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x01")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - logger.info("param:" + param); - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "shrTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("00007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - - @Test(enabled = true, description = "Trigger new ShiftRightSigned " - + "with displacement number too short ") - public void test3ShiftRightSigned() { - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x01")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - logger.info("param:" + param); - String txid = ""; - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("00007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand004.java deleted file mode 100644 index 9c5f7148b67..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand004.java +++ /dev/null @@ -1,1040 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.shiftcommand; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.DataWord; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ShiftCommand004 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Trigger new ShiftLeft,value is " - + "0x0000000000000000000000000000000000000000000000000000000000000001 and Displacement number" - + "is 0x00") - public void test1ShiftLeft() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/ShiftCommand001.sol"; - String contractName = "TestBitwiseShift"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000001")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x00")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shlTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000001")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftLeft,value is " - + "0x0000000000000000000000000000000000000000000000000000000000000001 and Displacement number" - + "is 0x01") - public void test2ShiftLeft() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000001")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray - .fromHexString("0x01")) - .getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shlTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000002")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - - @Test(enabled = true, description = "Trigger new ShiftLeft,value is " - + "0x0000000000000000000000000000000000000000000000000000000000000001 and Displacement number" - + "is 0xff") - public void test3ShiftLeft() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000001")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray - .fromHexString("0xff")) - .getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shlTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x8000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - - @Test(enabled = true, description = "Trigger new ShiftLeft,value is " - + "0x0000000000000000000000000000000000000000000000000000000000000001 and Displacement number" - + "is 0x0100") - public void test4ShiftLeft() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000001")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x0100")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - txid = PublicMethed.triggerContract(contractAddress, - "shlTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftLeft,value is " - + "0x0000000000000000000000000000000000000000000000000000000000000001 and Displacement number" - + "is 0x0101") - public void test5ShiftLeft() { - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000001")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x0101")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - txid = PublicMethed.triggerContract(contractAddress, - "shlTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftLeft,value is " - + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0x00") - public void test6ShiftLeft() { - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x00")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - txid = PublicMethed.triggerContract(contractAddress, - "shlTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftLeft,value is " - + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0x01") - public void test7ShiftLeft() { - String filePath = "src/test/resources/soliditycode/ShiftCommand001.sol"; - String contractName = "TestBitwiseShift"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x01")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shlTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - - @Test(enabled = true, description = "Trigger new ShiftLeft,value is " - + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0xff") - public void test8ShiftLeft() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0xff")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shlTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x8000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - - @Test(enabled = true, description = "Trigger new ShiftLeft,value is " - + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0x0100") - public void test9ShiftLeft() { - - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x0100")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shlTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - - @Test(enabled = true, description = "Trigger new ShiftLeft,value is " - + "0x0000000000000000000000000000000000000000000000000000000000000000 and Displacement number" - + "is 0x01") - public void testShiftLeft10() { - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x01")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shlTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftLeft,value is " - + "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0x01") - public void testShiftLeft11() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x01")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shlTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftLeft,value is " - + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0x0101") - public void testShiftLeft12() { - - String filePath = "src/test/resources/soliditycode/TvmNewCommand043.sol"; - String contractName = "TestBitwiseShift"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x0101")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shlTest(int256,int256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand005.java deleted file mode 100644 index 880b435e321..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand005.java +++ /dev/null @@ -1,1049 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.shiftcommand; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.DataWord; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ShiftCommand005 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Trigger new ShiftRight,value is " - + "0x0000000000000000000000000000000000000000000000000000000000000001 and Displacement number" - + "is 0x00") - public void test1ShiftRight() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/ShiftCommand001.sol"; - String contractName = "TestBitwiseShift"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000001")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x00")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shrTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000001")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRight,value is " - + "0x0000000000000000000000000000000000000000000000000000000000000001 and Displacement number" - + "is 0x01") - public void test2ShiftRight() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000001")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x01")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shrTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRight,value is " - + "0x8000000000000000000000000000000000000000000000000000000000000000 and Displacement number" - + "is 0x01") - public void test3ShiftRight() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - String originNumber = String.valueOf(ByteArray.toLong(ByteArray - .fromHexString("0x8000000000000000000000000000000000000000000000000000000000000000"))); - String valueNumber = String.valueOf(ByteArray.toLong((ByteArray - .fromHexString("0x01")))); - String num = valueNumber + "," + originNumber; - - logger.info("returnnumber:" + originNumber); - logger.info("returnnumber1:" + valueNumber); - - txid = PublicMethed.triggerContract(contractAddress, - "shrTest(uint256,uint256)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x4000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRight,value is " - + "0x8000000000000000000000000000000000000000000000000000000000000000 and Displacement number" - + "is 0xff") - public void test4ShiftRight() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x8000000000000000000000000000000000000000000000000000000000000000")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray - .fromHexString("0xff")) - .getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - txid = PublicMethed.triggerContract(contractAddress, - "shrTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000001")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - - @Test(enabled = true, description = "Trigger new ShiftRight,value is " - + "0x8000000000000000000000000000000000000000000000000000000000000000 and Displacement number" - + "is 0x0100") - public void test5ShiftRight() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x8000000000000000000000000000000000000000000000000000000000000000")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x0100")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shrTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRight,value is " - + "0x8000000000000000000000000000000000000000000000000000000000000000 and Displacement number" - + "is 0x0101") - public void test6ShiftRight() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x8000000000000000000000000000000000000000000000000000000000000000")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x0101")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shrTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRight,value is " - + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0x00") - public void test7ShiftRight() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x00")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shrTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRight,value is " - + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0x01") - public void test8ShiftRight() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x01")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shrTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRight,value is " - + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0xff") - public void test9ShiftRight() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0xff")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shrTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000001")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRight,value is " - + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0x0100") - public void testShiftRight10() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x0100")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shrTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRight,value is " - + "0x0000000000000000000000000000000000000000000000000000000000000000 and Displacement number" - + "is 0x01") - public void testShiftRight11() { - - String filePath = "src/test/resources/soliditycode/ShiftCommand001.sol"; - String contractName = "TestBitwiseShift"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x01")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shrTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - - @Test(enabled = true, description = "Trigger new ShiftRight,value is " - + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0x0101") - public void testShiftRight12() { - - String filePath = "src/test/resources/soliditycode/TvmNewCommand043.sol"; - String contractName = "TestBitwiseShift"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x0101")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "shrTest(int256,int256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand006.java deleted file mode 100644 index beece0ef5d6..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/shiftcommand/ShiftCommand006.java +++ /dev/null @@ -1,1539 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.shiftcommand; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.DataWord; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ShiftCommand006 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Trigger new ShiftRightSigned,value is " - + "0x0000000000000000000000000000000000000000000000000000000000000001 and Displacement number" - + "is 0x00") - public void test1ShiftRightSigned() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/ShiftCommand001.sol"; - String contractName = "TestBitwiseShift"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000001")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x00")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000001")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRightSigned,value is " - + "0x0000000000000000000000000000000000000000000000000000000000000001 and Displacement number" - + "is 0x01") - public void test2ShiftRightSigned() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000001")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x01")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRightSigned,value is " - + "0x8000000000000000000000000000000000000000000000000000000000000000 and Displacement number" - + "is 0x01") - public void test3ShiftRightSigned() { - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x8000000000000000000000000000000000000000000000000000000000000000")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x01")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0xc000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRightSigned,value is " - + "0x8000000000000000000000000000000000000000000000000000000000000000 and Displacement number" - + "is 0xff") - public void test4ShiftRightSigned() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x8000000000000000000000000000000000000000000000000000000000000000")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray - .fromHexString("0xff")) - .getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRightSigned,value is " - + "0x8000000000000000000000000000000000000000000000000000000000000000 and Displacement number" - + "is 0x0100") - public void test5ShiftRightSigned() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x8000000000000000000000000000000000000000000000000000000000000000")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x0100")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRightSigned,value is " - + "0x8000000000000000000000000000000000000000000000000000000000000000 and Displacement number" - + "is 0x0101") - public void test6ShiftRightSigned() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x8000000000000000000000000000000000000000000000000000000000000000")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x0101")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRightSigned,value is " - + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0x00") - public void test7ShiftRightSigned() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray - .fromHexString("0x00")) - .getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - - } - - @Test(enabled = true, description = "Trigger new ShiftRightSigned,value is " - + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0x01") - public void test8ShiftRightSigned() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray - .fromHexString("0x01")) - .getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRightSigned,value is " - + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0xff") - public void test9ShiftRightSigned() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray - .fromHexString("0xff")) - .getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - - @Test(enabled = true, description = "Trigger new ShiftRightSigned,value is " - + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0x0100") - public void testShiftRightSigned10() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray - .fromHexString("0x0100")) - .getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - - @Test(enabled = true, description = "Trigger new ShiftRightSigned,value is " - + "0x0000000000000000000000000000000000000000000000000000000000000000 and Displacement number" - + "is 0x01") - public void testShiftRightSigned11() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray - .fromHexString("0x01")) - .getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - - @Test(enabled = true, description = "Trigger new ShiftRightSigned,value is " - + "0x4000000000000000000000000000000000000000000000000000000000000000 and Displacement number" - + "is 0xfe") - public void testShiftRightSigned12() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x4000000000000000000000000000000000000000000000000000000000000000")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray - .fromHexString("0xfe")) - .getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000001")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRightSigned,value is " - + "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0xf8") - public void testShiftRightSigned13() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray - .fromHexString("0xf8")) - .getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x000000000000000000000000000000000000000000000000000000000000007f")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - - @Test(enabled = true, description = "Trigger new ShiftRightSigned,value is " - + "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0xfe") - public void testShiftRightSigned14() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0xfe")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000001")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRightSigned,value is " - + "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0xff") - public void testShiftRightSigned15() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0xff")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - - String param = Hex.toHexString(paramBytes); - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - - @Test(enabled = true, description = "Trigger new ShiftRightSigned,value is " - + "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0x0100") - public void testShiftRightSigned16() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x0100")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - - String param = Hex.toHexString(paramBytes); - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(uint256,uint256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRightSigned,value is " - + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0x0101") - public void testShiftRightSigned17() { - - String filePath = "src/test/resources/soliditycode/TvmNewCommand043.sol"; - String contractName = "TestBitwiseShift"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray - .fromHexString("0x0101")) - .getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - String param = Hex.toHexString(paramBytes); - - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(int256,int256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber14 = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - @Test(enabled = true, description = "Trigger new ShiftRightSigned,value is " - + "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and Displacement number" - + "is 0x0101") - public void testShiftRightSigned18() { - - String filePath = "src/test/resources/soliditycode/TvmNewCommand043.sol"; - String contractName = "TestBitwiseShift"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - byte[] originNumber = new DataWord( - ByteArray - .fromHexString("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) - .getData(); - byte[] valueNumber = new DataWord( - ByteArray.fromHexString("0x0101")).getData(); - byte[] paramBytes = new byte[originNumber.length + valueNumber.length]; - System.arraycopy(valueNumber, 0, paramBytes, 0, valueNumber.length); - System.arraycopy(originNumber, 0, paramBytes, valueNumber.length, originNumber.length); - - String param = Hex.toHexString(paramBytes); - txid = PublicMethed.triggerContract(contractAddress, - "sarTest(int256,int256)", param, true, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - String returnString = (ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray())); - logger.info("returnString:" + returnString); - Assert.assertEquals(ByteArray.toLong(ByteArray - .fromHexString("0x0000000000000000000000000000000000000000000000000000000000000000")), - ByteArray.toLong(ByteArray - .fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())))); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/ContractTestSendCoin001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/ContractTestSendCoin001.java deleted file mode 100644 index ede5fa69460..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/ContractTestSendCoin001.java +++ /dev/null @@ -1,624 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.transferfailed; - -import static org.hamcrest.core.StringContains.containsString; -import static org.tron.api.GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR; -import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS_VALUE; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractTestSendCoin001 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 1000L; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] transferTokenContractAddress = null; - - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - @Test(enabled = true, description = "Sendcoin and transferAsset to contractAddresss ," - + "then selfdestruct") - public void testSendCoinAndTransferAssetContract001() { - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 3100_000_000L, fromAddress, testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(dev001Address, dev001Key, 130000L, blockingStubFull), 0, - 1, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 10_000_000L, 0, 0, - ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed - .createAssetIssue(dev001Address, tokenName, TotalSupply, 1, 10000, start, end, 1, - description, url, 100000L, 100000L, 1L, 1L, dev001Key, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed - .getAccountResource(dev001Address, blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - - String filePath = "src/test/resources/soliditycode/contractTrcToken031.sol"; - String contractName = "token"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String tokenId = assetAccountId.toStringUtf8(); - long tokenValue = 100; - long callValue = 5; - - final String deployContractTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callValue, 0, 10000, tokenId, tokenValue, null, dev001Key, dev001Address, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - - Optional infoById = PublicMethed - .getTransactionInfoById(deployContractTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - if (deployContractTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(transferTokenContractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - Return ret = PublicMethed - .transferAssetForReturn(transferTokenContractAddress, assetAccountId.toByteArray(), 100L, - dev001Address, dev001Key, blockingStubFull); - - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, ret.getCode()); - Assert.assertEquals("Contract validate error : Cannot transfer asset to smartContract.", - ret.getMessage().toStringUtf8()); - Long contractAssetCount = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(tokenValue), contractAssetCount); - - Return ret1 = PublicMethed - .sendcoinForReturn(transferTokenContractAddress, 1_000_000L, fromAddress, testKey002, - blockingStubFull); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, ret1.getCode()); - Assert.assertEquals("Contract validate error : Cannot transfer TRX to a smartContract.", - ret1.getMessage().toStringUtf8()); - - String num = "\"" + Base58.encode58Check(dev001Address) + "\""; - - String txid = PublicMethed - .triggerContract(transferTokenContractAddress, "kill(address)", num, false, 0, maxFeeLimit, - dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long contractAssetCountBefore = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - long contractBefore = PublicMethed.queryAccount(transferTokenContractAddress, blockingStubFull) - .getBalance(); - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - Assert.assertTrue(PublicMethed - .transferAsset(transferTokenContractAddress, assetAccountId.toByteArray(), 100L, - dev001Address, dev001Key, blockingStubFull)); - - Assert.assertTrue(PublicMethed - .sendcoin(transferTokenContractAddress, 1_000_000L, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long contractAssetCountAfter = PublicMethed - .getAssetIssueValue(transferTokenContractAddress, assetAccountId, blockingStubFull); - long contractAfetr = PublicMethed.queryAccount(transferTokenContractAddress, blockingStubFull) - .getBalance(); - - Assert.assertTrue(contractAssetCountBefore + 100L == contractAssetCountAfter); - Assert.assertTrue(contractBefore + 1_000_000L == contractAfetr); - - } - - - @Test(enabled = true, description = "Use create to generate a contract address " - + "Sendcoin and transferAsset to contractAddresss ,then selfdestruct,") - public void testSendCoinAndTransferAssetContract002() { - - assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); - - logger.info("The token name: " + tokenName); - logger.info("The token ID: " + assetAccountId.toStringUtf8()); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed - .getAccountResource(dev001Address, blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountBefore = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " - + devAssetCountBefore); - - String filePath = "src/test/resources/soliditycode/contractTransferToken001.sol"; - - String contractName = "A"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String tokenId = assetAccountId.toStringUtf8(); - long tokenValue = 100; - long callValue = 5; - - final String deployContractTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callValue, 0, 10000, tokenId, tokenValue, null, dev001Key, dev001Address, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(deployContractTxid, blockingStubFull); - - transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); - - accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - Long devAssetCountAfter = PublicMethed - .getAssetIssueValue(dev001Address, assetAccountId, blockingStubFull); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - logger.info("after AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountAfter: " - + devAssetCountAfter); - - String txid = PublicMethed - .triggerContract(transferTokenContractAddress, "newB()", "#", false, 0, maxFeeLimit, - dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - byte[] a = infoById.get().getContractResult(0).toByteArray(); - byte[] b = subByte(a, 11, 1); - byte[] c = subByte(a, 0, 11); - byte[] e = "41".getBytes(); - byte[] d = subByte(a, 12, 20); - - logger.info("a:" + ByteArray.toHexString(a)); - - logger.info("b:" + ByteArray.toHexString(b)); - logger.info("c:" + ByteArray.toHexString(c)); - - logger.info("d:" + ByteArray.toHexString(d)); - - logger.info("41" + ByteArray.toHexString(d)); - String exceptedResult = "41" + ByteArray.toHexString(d); - String realResult = ByteArray.toHexString(b); - Assert.assertEquals(realResult, "00"); - Assert.assertNotEquals(realResult, "41"); - - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(exceptedResult)); - logger.info("create Address : " + addressFinal); - byte[] testContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - Return ret = PublicMethed - .transferAssetForReturn(testContractAddress, assetAccountId.toByteArray(), 100L, - dev001Address, dev001Key, blockingStubFull); - - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, ret.getCode()); - Assert.assertEquals("Contract validate error : Cannot transfer asset to smartContract.", - ret.getMessage().toStringUtf8()); - Long contractAssetCount = PublicMethed - .getAssetIssueValue(testContractAddress, assetAccountId, blockingStubFull); - logger.info("Contract has AssetId: " + assetAccountId.toStringUtf8() + ", Count: " - + contractAssetCount); - - Assert.assertEquals(Long.valueOf(0L), contractAssetCount); - - Return ret1 = PublicMethed - .sendcoinForReturn(testContractAddress, 1_000_000L, fromAddress, testKey002, - blockingStubFull); - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, ret1.getCode()); - Assert.assertEquals("Contract validate error : Cannot transfer TRX to a smartContract.", - ret1.getMessage().toStringUtf8()); - - String num = "\"" + Base58.encode58Check(dev001Address) + "\""; - - txid = PublicMethed - .triggerContract(testContractAddress, "kill(address)", num, false, 0, maxFeeLimit, - dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long contractAssetCountBefore = PublicMethed - .getAssetIssueValue(testContractAddress, assetAccountId, blockingStubFull); - long contractBefore = PublicMethed.queryAccount(testContractAddress, blockingStubFull) - .getBalance(); - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - Assert.assertTrue(PublicMethed - .transferAsset(testContractAddress, assetAccountId.toByteArray(), 100L, dev001Address, - dev001Key, blockingStubFull)); - - Assert.assertTrue(PublicMethed - .sendcoin(testContractAddress, 1_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long contractAssetCountAfter = PublicMethed - .getAssetIssueValue(testContractAddress, assetAccountId, blockingStubFull); - long contractAfetr = PublicMethed.queryAccount(testContractAddress, blockingStubFull) - .getBalance(); - - Assert.assertTrue(contractAssetCountBefore + 100L == contractAssetCountAfter); - Assert.assertTrue(contractBefore + 1_000_000L == contractAfetr); - } - - - @Test(enabled = true, description = "Use create2 to generate a contract address " - + "Sendcoin and transferAsset to contractAddresss ,then selfdestruct") - public void testSendCoinAndTransferAssetContract003() { - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - String sendcoin = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 1000000000L, fromAddress, testKey002, - blockingStubFull); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById0 = null; - infoById0 = PublicMethed.getTransactionInfoById(sendcoin, blockingStubFull); - logger.info("infoById0 " + infoById0.get()); - Assert.assertEquals(ByteArray.toHexString(infoById0.get().getContractResult(0).toByteArray()), - ""); - Assert.assertEquals(infoById0.get().getResult().getNumber(), 0); - Optional ById = PublicMethed.getTransactionById(sendcoin, blockingStubFull); - Assert.assertEquals(ById.get().getRet(0).getContractRet().getNumber(), SUCCESS_VALUE); - Assert.assertEquals(ById.get().getRet(0).getContractRetValue(), SUCCESS_VALUE); - Assert.assertEquals(ById.get().getRet(0).getContractRet(), contractResult.SUCCESS); - String filePath = "src/test/resources/soliditycode/create2contractn2.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - byte[] contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String contractName1 = "TestConstract"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - String txid = ""; - String num = "\"" + code1 + "\"" + "," + 1; - txid = PublicMethed - .triggerContract(contractAddress, "deploy(bytes,uint256)", num, false, 0, maxFeeLimit, "0", - 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - byte[] returnAddressBytes = infoById.get().getInternalTransactions(0).getTransferToAddress() - .toByteArray(); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - - Return ret = PublicMethed - .transferAssetForReturn(returnAddressBytes, assetAccountId.toByteArray(), 100L, - dev001Address, dev001Key, blockingStubFull); - - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, ret.getCode()); - Assert.assertEquals("Contract validate error : Cannot transfer asset to smartContract.", - ret.getMessage().toStringUtf8()); - - Return ret1 = PublicMethed - .transferAssetForReturn(returnAddressBytes, assetAccountId.toByteArray(), 100L, - dev001Address, dev001Key, blockingStubFull); - - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, ret1.getCode()); - Assert.assertEquals("Contract validate error : Cannot transfer asset to smartContract.", - ret1.getMessage().toStringUtf8()); - - txid = PublicMethed - .triggerContract(returnAddressBytes, "i()", "#", false, 0, maxFeeLimit, "0", 0, - contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee1 = infoById1.get().getFee(); - Long netUsed1 = infoById1.get().getReceipt().getNetUsage(); - Long energyUsed1 = infoById1.get().getReceipt().getEnergyUsage(); - Long netFee1 = infoById1.get().getReceipt().getNetFee(); - long energyUsageTotal1 = infoById1.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee1:" + fee1); - logger.info("netUsed1:" + netUsed1); - logger.info("energyUsed1:" + energyUsed1); - logger.info("netFee1:" + netFee1); - logger.info("energyUsageTotal1:" + energyUsageTotal1); - - Account infoafter1 = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter1 = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance1); - logger.info("afterEnergyUsed:" + afterEnergyUsed1); - logger.info("afterNetUsed:" + afterNetUsed1); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed1); - - Assert.assertTrue(infoById1.get().getResultValue() == 0); - Assert.assertTrue(afterBalance1 + fee1 == afterBalance); - Assert.assertTrue(afterEnergyUsed + energyUsed1 >= afterEnergyUsed1); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - txid = PublicMethed - .triggerContract(returnAddressBytes, "set()", "#", false, 0, maxFeeLimit, "0", 0, - contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - txid = PublicMethed - .triggerContract(returnAddressBytes, "i()", "#", false, 0, maxFeeLimit, "0", 0, - contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById1 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(5 == returnnumber); - - String param1 = "\"" + Base58.encode58Check(returnAddressBytes) + "\""; - - txid = PublicMethed - .triggerContract(returnAddressBytes, "testSuicideNonexistentTarget(address)", param1, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById2 = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - - Assert.assertEquals("suicide", - ByteArray.toStr(infoById2.get().getInternalTransactions(0).getNote().toByteArray())); - TransactionExtention transactionExtention = PublicMethed - .triggerContractForExtention(returnAddressBytes, "i()", "#", false, 0, maxFeeLimit, "0", 0, - contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertThat(transactionExtention.getResult().getCode().toString(), - containsString("CONTRACT_VALIDATE_ERROR")); - Assert.assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Contract validate error : No contract or not a valid smart contract")); - - Assert.assertTrue(PublicMethed - .transferAsset(returnAddressBytes, assetAccountId.toByteArray(), 100L, dev001Address, - dev001Key, blockingStubFull)); - - Assert.assertTrue(PublicMethed - .sendcoin(returnAddressBytes, 1_000_000L, fromAddress, testKey002, blockingStubFull)); - - txid = PublicMethed - .triggerContract(contractAddress, "deploy(bytes,uint256)", num, false, 0, maxFeeLimit, "0", - 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById3 = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - byte[] returnAddressBytes1 = infoById3.get().getInternalTransactions(0).getTransferToAddress() - .toByteArray(); - String returnAddress1 = Base58.encode58Check(returnAddressBytes1); - Assert.assertEquals(returnAddress1, returnAddress); - txid = PublicMethed - .triggerContract(returnAddressBytes1, "i()", "#", false, 0, maxFeeLimit, "0", 0, - contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById1 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - - ret = PublicMethed - .transferAssetForReturn(returnAddressBytes1, assetAccountId.toByteArray(), 100L, - dev001Address, dev001Key, blockingStubFull); - - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, ret.getCode()); - Assert.assertEquals("Contract validate error : Cannot transfer asset to smartContract.", - ret.getMessage().toStringUtf8()); - - ret1 = PublicMethed - .transferAssetForReturn(returnAddressBytes1, assetAccountId.toByteArray(), 100L, - dev001Address, dev001Key, blockingStubFull); - - Assert.assertEquals(CONTRACT_VALIDATE_ERROR, ret1.getCode()); - Assert.assertEquals("Contract validate error : Cannot transfer asset to smartContract.", - ret1.getMessage().toStringUtf8()); - - } - - - public byte[] subByte(byte[] b, int off, int length) { - byte[] b1 = new byte[length]; - System.arraycopy(b, off, b1, 0, length); - return b1; - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TestResourceReceiver.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TestResourceReceiver.java deleted file mode 100644 index 4be2a319dc4..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TestResourceReceiver.java +++ /dev/null @@ -1,189 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.transferfailed; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TestResourceReceiver { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - - @Test(enabled = false, description = "Suicide existent Target") - public void test1SuicideExistentTarget() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TransferFailed001.sol"; - String contractName = "EnergyOfTransferFailedTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed - .sendcoin(contractAddress, 3000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(testNetAccountAddress, - 1000000, 0, 1, - ByteString.copyFrom(contractAddress), testNetAccountKey, blockingStubFull)); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] existentAddress = ecKey2.getAddress(); - Assert.assertTrue(PublicMethed - .sendcoin(contractAddress, 1000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String txid = ""; - String num = "\"" + Base58.encode58Check(contractAddress) + "\""; - txid = PublicMethed.triggerContract(contractAddress, - "testSuicideNonexistentTarget(address)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Account contractafter = PublicMethed.queryAccount(contractAddress, blockingStubFull1); - long contractBalance = contractafter.getBalance(); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertEquals(contractBalance, 0); - txid = PublicMethed.triggerContract(contractAddress, - "testSuicideNonexistentTarget(address)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Assert.assertNull(txid); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - PublicMethed.unFreezeBalance(testNetAccountAddress, testNetAccountKey, 1, - contractAddress, blockingStubFull); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed001.java deleted file mode 100644 index e82fb89464a..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed001.java +++ /dev/null @@ -1,920 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.transferfailed; - -import static org.tron.protos.Protocol.TransactionInfo.code.FAILED; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.vm.EnergyCost; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TransferFailed001 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Transfer trx insufficient balance") - public void test001TransferTrxInsufficientBalance() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TransferFailed001.sol"; - String contractName = "EnergyOfTransferFailedTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 2000000L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - String num = "2000001"; - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTrxInsufficientBalance(uint256)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("infoById:" + infoById); - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertEquals(contractResult.REVERT, infoById.get().getReceipt().getResult()); - Assert.assertEquals( - "REVERT opcode executed", - ByteArray.toStr(infoById.get().getResMessage().toByteArray())); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertNotEquals(10000000, energyUsageTotal); - - - } - - - @Test(enabled = true, description = "Transfer balance enough") - public void test002TransferEnough() { - - //Assert.assertTrue(PublicMethed - // .sendcoin(contractAddress, 3000000L, testNetAccountAddress, testNetAccountKey, - // blockingStubFull)); - //PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - String num = "1"; - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTrxInsufficientBalance(uint256)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - logger.info("infoById" + infoById); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee - 1 == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - - } - - - @Test(enabled = true, description = "Transfer trx nonexistent target") - public void test003TransferTrxNonexistentTarget() { - - //Assert.assertTrue(PublicMethed - // .sendcoin(contractAddress, 1000000L, testNetAccountAddress, testNetAccountKey, - // blockingStubFull)); - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] nonexistentAddress = ecKey2.getAddress(); - String txid = ""; - String num = "1" + ",\"" + Base58.encode58Check(nonexistentAddress) + "\""; - - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTrxNonexistentTarget(uint256,address)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Account nonexistentAddressAccount = PublicMethed - .queryAccount(nonexistentAddress, blockingStubFull1); - Assert.assertEquals(1, nonexistentAddressAccount.getBalance()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertNotEquals(10000000, energyUsageTotal); - - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTrxNonexistentTarget(uint256,address)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - - fee = infoById.get().getFee(); - netUsed = infoById.get().getReceipt().getNetUsage(); - energyUsed = infoById.get().getReceipt().getEnergyUsage(); - netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal2 = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal2); - - infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - afterBalance = infoafter.getBalance(); - afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - afterNetUsed = resourceInfoafter.getNetUsed(); - afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - nonexistentAddressAccount = PublicMethed - .queryAccount(nonexistentAddress, blockingStubFull1); - Assert.assertEquals(2, nonexistentAddressAccount.getBalance()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - Assert.assertEquals(energyUsageTotal2 + EnergyCost.getNewAcctCall(), - energyUsageTotal); - - } - - - @Test(enabled = true, description = "Transfer trx to myself") - public void test004TransferTrxSelf() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - String num = "1"; - - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTrxSelf(uint256)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertEquals(contractResult.TRANSFER_FAILED, infoById.get().getReceipt().getResult()); - Assert.assertEquals("transfer trx failed: Cannot transfer TRX to yourself.", - ByteArray.toStr(infoById.get().getResMessage().toByteArray())); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertNotEquals(10000000, energyUsageTotal); - - - } - - - @Test(enabled = true, description = "Transfer trx nonexistent target and insufficient balance") - public void test005TransferTrxNonexistentTarget() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] nonexistentAddress = ecKey2.getAddress(); - String txid = ""; - String num = "10000000" + ",\"" + Base58.encode58Check(nonexistentAddress) + "\""; - - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTrxNonexistentTarget(uint256,address)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull1); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertEquals(contractResult.REVERT, infoById.get().getReceipt().getResult()); - Assert.assertEquals( - "REVERT opcode executed", - ByteArray.toStr(infoById.get().getResMessage().toByteArray())); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertNotEquals(10000000, energyUsageTotal); - - - } - - - @Test(enabled = true, description = "Transfer trx to myself and insufficient balance") - public void test006TransferTrxSelf() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - String txid = ""; - String num = "1000000000"; - - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTrxSelf(uint256)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertEquals(contractResult.REVERT, infoById.get().getReceipt().getResult()); - Assert.assertEquals( - "REVERT opcode executed", - ByteArray.toStr(infoById.get().getResMessage().toByteArray())); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertNotEquals(10000000, energyUsageTotal); - - - } - - @Test(enabled = true, description = "PreCompiled transfertoken with value," - + " long.max < value or long.min > value") - public void test007TransferTrckenPreCompiled() { - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String txid = ""; - String num = "1"; - - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTokenCompiledLongMax1()", "#", false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - beforeBalance = info.getBalance(); - beforeEnergyUsed = resourceInfo.getEnergyUsed(); - beforeNetUsed = resourceInfo.getNetUsed(); - beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertTrue(energyUsageTotal < maxFeeLimit / 10); - Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); - - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTokenCompiledLongMin1()", "#", false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - fee = infoById.get().getFee(); - netUsed = infoById.get().getReceipt().getNetUsage(); - energyUsed = infoById.get().getReceipt().getEnergyUsage(); - netFee = infoById.get().getReceipt().getNetFee(); - energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - beforeBalance = info.getBalance(); - beforeEnergyUsed = resourceInfo.getEnergyUsed(); - beforeNetUsed = resourceInfo.getNetUsed(); - beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertTrue(energyUsageTotal < maxFeeLimit / 10); - Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); - - } - - @Test(enabled = false, description = "PreCompiled tokenbalance") - public void test008TransferTrctoken() { - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000_000_000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - ByteString assetAccountId = null; - final long TotalSupply = 10000000L; - long now = System.currentTimeMillis(); - String tokenName = "testAssetIssue_" + Long.toString(now); - - //Create a new AssetIssue success. - Assert - .assertTrue(PublicMethed.createAssetIssue(contractExcAddress, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, - 100000L, 1L, 1L, contractExcKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed.queryAccount(contractExcAddress, blockingStubFull) - .getAssetIssuedID(); - - String filePath = "src/test/resources/soliditycode/TransferFailed001.sol"; - String contractName = "EnergyOfTransferFailedTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.transferAsset(contractAddress, - assetAccountId.toByteArray(), 100L, contractExcAddress, contractExcKey, - blockingStubFull)); - - Long returnAddressBytesAccountCountBefore = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("returnAddressBytesAccountCountBefore : " + returnAddressBytesAccountCountBefore); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long testNetAccountCountBefore = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountBefore = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("testNetAccountCountBefore:" + testNetAccountCountBefore); - logger.info("contractAccountCountBefore:" + contractAccountCountBefore); - String txid = ""; - String num = - "\"" + Base58.encode58Check(contractAddress) + "\"," + "\"" + assetAccountId.toStringUtf8() - + "\""; - //String num = "\""+Base58.encode58Check(contractAddress) +"\","+ "\"" + -1 + "\""; - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTokenTest(address,uint256)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long testNetAccountCountAfter = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("testNetAccountCountAfter:" + testNetAccountCountAfter); - logger.info("contractAccountCountAfter:" + contractAccountCountAfter); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(energyUsageTotal < maxFeeLimit / 10); - Assert.assertEquals(100, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - - } - - @Test(enabled = true, description = "PreCompiled address(0x1) query tokenbalance") - public void test009TransferTrctoken() { - //address: 410000000000000000000000000000000000000001 - String addressx = "T9yD14Nj9j7xAB4dbGeiX9h8unkKLxmGkn"; - byte[] addressxx = WalletClient.decodeFromBase58Check(addressx); - - Assert.assertTrue(PublicMethed - .sendcoin(addressxx, 1000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - - ByteString assetAccountId = null; - final long TotalSupply = 10000000L; - long now = System.currentTimeMillis(); - String tokenName = "testAssetIssue_" + Long.toString(now); - - //Create a new AssetIssue success. - Assert - .assertTrue(PublicMethed.createAssetIssue(contractExcAddress, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, - 100000L, 1L, 1L, contractExcKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetAccountId = PublicMethed.queryAccount(contractExcAddress, blockingStubFull) - .getAssetIssuedID(); - - Assert.assertTrue(PublicMethed.transferAsset(addressxx, - assetAccountId.toByteArray(), 100L, contractExcAddress, contractExcKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long returnAddressBytesAccountCountBefore = PublicMethed - .getAssetIssueValue(addressxx, assetAccountId, blockingStubFull); - logger.info("returnAddressBytesAccountCountBefore : " + returnAddressBytesAccountCountBefore); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long testNetAccountCountBefore = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountBefore = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("testNetAccountCountBefore:" + testNetAccountCountBefore); - logger.info("contractAccountCountBefore:" + contractAccountCountBefore); - String txid = ""; - //String num = "\""+Base58.encode58Check(contractAddress) - // +"\","+ "\"" + assetAccountId.toStringUtf8() + "\""; - String num = "\"" + assetAccountId.toStringUtf8() + "\""; - //String num = "\""+Base58.encode58Check(contractAddress) +"\","+ "\"" + -1 + "\""; - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTokenCompiledTokenId(uint256)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long testNetAccountCountAfter = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("testNetAccountCountAfter:" + testNetAccountCountAfter); - logger.info("contractAccountCountAfter:" + contractAccountCountAfter); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(energyUsageTotal < maxFeeLimit / 10); - Assert.assertEquals(100, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "transferTrx to nonexistent target ,but revert") - public void test010TransferRevert() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] nonexistentAddress = ecKey2.getAddress(); - String txid = ""; - String num = "1" + ",\"" + Base58.encode58Check(nonexistentAddress) + "\""; - - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTrxrevert(uint256,address)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Account nonexistentAddressAccount = PublicMethed - .queryAccount(nonexistentAddress, blockingStubFull1); - Assert.assertEquals(0, nonexistentAddressAccount.getBalance()); - Assert.assertEquals(1, infoById.get().getResultValue()); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertTrue(energyUsageTotal > EnergyCost.getNewAcctCall()); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed002.java deleted file mode 100644 index 599e4b4c835..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed002.java +++ /dev/null @@ -1,582 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.transferfailed; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.vm.EnergyCost; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TransferFailed002 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode).usePlaintext().build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "Send balance not enough") - public void test1SendNotEnough() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 100000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TransferFailed001.sol"; - String contractName = "EnergyOfTransferFailedTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 3000000L, 100, null, - contractExcKey, contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - String num = "3000001"; - txid = PublicMethed - .triggerContract(contractAddress, "testSendTrxInsufficientBalance(uint256)", num, false, 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("infoById:" + infoById); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertNotEquals(10000000, energyUsageTotal); - - - } - - @Test(enabled = true, description = "Send balance enough") - public void test2SendEnough() { - //Assert.assertTrue(PublicMethed - // .sendcoin(contractAddress, 3000000L, testNetAccountAddress, testNetAccountKey, - // blockingStubFull)); - //PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - String num = "1"; - txid = PublicMethed - .triggerContract(contractAddress, "testSendTrxInsufficientBalance(uint256)", num, false, 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("infoById:" + infoById); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee - 1 == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - } - - - @Test(enabled = true, description = "Send trx nonexistent target") - public void test3SendTrxNonexistentTarget() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] nonexistentAddress = ecKey2.getAddress(); - String txid = ""; - String num = "1" + ",\"" + Base58.encode58Check(nonexistentAddress) + "\""; - - txid = PublicMethed - .triggerContract(contractAddress, "testSendTrxNonexistentTarget(uint256,address)", num, - false, 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertEquals(0, infoById.get().getResultValue()); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertNotEquals(10000000, energyUsageTotal); - - Account nonexistentAddressAccount = PublicMethed - .queryAccount(nonexistentAddress, blockingStubFull1); - Assert.assertEquals(1, nonexistentAddressAccount.getBalance()); - - txid = PublicMethed - .triggerContract(contractAddress, "testSendTrxNonexistentTarget(uint256,address)", num, - false, 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - - fee = infoById.get().getFee(); - netUsed = infoById.get().getReceipt().getNetUsage(); - energyUsed = infoById.get().getReceipt().getEnergyUsage(); - netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal2 = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal2); - - infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, blockingStubFull1); - afterBalance = infoafter.getBalance(); - afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - afterNetUsed = resourceInfoafter.getNetUsed(); - afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertEquals(0, infoById.get().getResultValue()); - - Assert.assertNotEquals(energyUsageTotal2, - energyUsageTotal + EnergyCost.getNewAcctCall()); - - nonexistentAddressAccount = PublicMethed.queryAccount(nonexistentAddress, blockingStubFull1); - Assert.assertEquals(2, nonexistentAddressAccount.getBalance()); - - } - - - @Test(enabled = true, description = "Send trx self") - public void test4SendTrxSelf() { - Account info; - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - String num = "1"; - txid = PublicMethed - .triggerContract(contractAddress, "testSendTrxSelf(uint256)", num, false, 0, maxFeeLimit, - contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertEquals(contractResult.TRANSFER_FAILED, infoById.get().getReceipt().getResult()); - Assert.assertEquals("transfer trx failed: Cannot transfer TRX to yourself.", - ByteArray.toStr(infoById.get().getResMessage().toByteArray())); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertNotEquals(10000000, energyUsageTotal); - Assert.assertNotEquals(10000000, energyUsageTotal); - - - } - - - @Test(enabled = true, description = "Send trx nonexistent target and balance not enough") - public void test5SendTrxNonexistentTarget() { - Account info; - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] nonexistentAddress = ecKey2.getAddress(); - String txid = ""; - - String num = "100000000" + ",\"" + Base58.encode58Check(contractExcAddress) + "\""; - - txid = PublicMethed - .triggerContract(contractAddress, "testSendTrxNonexistentTarget(uint256,address)", num, - false, 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertNotEquals(10000000, energyUsageTotal); - - } - - - @Test(enabled = true, description = "Send trx self and balance not enough") - public void test6SendTrxSelf() { - Account info; - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - String txid = ""; - - String num = "1000000000"; - - txid = PublicMethed - .triggerContract(contractAddress, "testSendTrxSelf(uint256)", num, false, 0, maxFeeLimit, - contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertNotEquals(10000000, energyUsageTotal); - - - } - - @Test(enabled = true, description = "Send trx nonexistent target, but revert") - public void test7SendTrxNonexistentTargetRevert() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] nonexistentAddress = ecKey2.getAddress(); - String txid = ""; - String num = "1" + ",\"" + Base58.encode58Check(nonexistentAddress) + "\""; - - txid = PublicMethed - .triggerContract(contractAddress, "testSendTrxRevert(uint256,address)", num, false, 0, - maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Account nonexistentAddressAccount = PublicMethed - .queryAccount(nonexistentAddress, blockingStubFull1); - Assert.assertEquals(0, nonexistentAddressAccount.getBalance()); - Assert.assertEquals(1, infoById.get().getResultValue()); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertTrue(energyUsageTotal > EnergyCost.getNewAcctCall()); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed003.java deleted file mode 100644 index 4f4194e0b3e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed003.java +++ /dev/null @@ -1,817 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.transferfailed; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.vm.EnergyCost; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TransferFailed003 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 10000000L; - private static ByteString assetAccountId = null; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - - @Test(enabled = true, description = "TransferToken enough tokenBalance") - public void test1TransferTokenEnough() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000_000_000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - - //Create a new AssetIssue success. - Assert - .assertTrue(PublicMethed.createAssetIssue(contractExcAddress, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, - 100000L, 1L, 1L, contractExcKey, blockingStubFull)); - - String filePath = "src/test/resources/soliditycode/TransferFailed001.sol"; - String contractName = "EnergyOfTransferFailedTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - assetAccountId = PublicMethed.queryAccount(contractExcAddress, blockingStubFull) - .getAssetIssuedID(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, 1000000000L, - assetAccountId.toStringUtf8(), 100L, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //Assert.assertTrue(PublicMethed.transferAsset(contractAddress, - // assetAccountId.toByteArray(), 100L, contractExcAddress, contractExcKey, - // blockingStubFull)); - //PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long testNetAccountCountBefore = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountBefore = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("testNetAccountCountBefore:" + testNetAccountCountBefore); - logger.info("contractAccountCountBefore:" + contractAccountCountBefore); - String txid = ""; - String num = "1" + ",\"" + assetAccountId.toStringUtf8() + "\""; - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTokenInsufficientBalance(uint256,trcToken)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long testNetAccountCountAfter = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("testNetAccountCountAfter:" + testNetAccountCountAfter); - logger.info("contractAccountCountAfter:" + contractAccountCountAfter); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(testNetAccountCountBefore + 1 == testNetAccountCountAfter); - Assert.assertTrue(contractAccountCountBefore - 1 == contractAccountCountAfter); - - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - - } - - @Test(enabled = true, description = "TransferToken insufficient tokenBalance") - public void test2TransferTokenNotEnough() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long testNetAccountCountBefore = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountBefore = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("testNetAccountCountBefore:" + testNetAccountCountBefore); - logger.info("contractAccountCountBefore:" + contractAccountCountBefore); - String txid = ""; - String num = "1000" + ",\"" + assetAccountId.toStringUtf8() + "\""; - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTokenInsufficientBalance(uint256,trcToken)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long testNetAccountCountAfter = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("testNetAccountCountAfter:" + testNetAccountCountAfter); - logger.info("contractAccountCountAfter:" + contractAccountCountAfter); - logger.info("infoById:" + infoById); - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertEquals(contractResult.REVERT, infoById.get().getReceipt().getResult()); - Assert.assertEquals( - "REVERT opcode executed", - ByteArray.toStr(infoById.get().getResMessage().toByteArray())); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertEquals(testNetAccountCountBefore, testNetAccountCountAfter); - Assert.assertEquals(contractAccountCountBefore, contractAccountCountAfter); - - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertNotEquals(10000000, energyUsageTotal); - - } - - - @Test(enabled = true, description = "TransferToken to nonexistent target") - public void test3TransferTokenNonexistentTarget() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long testNetAccountCountBefore = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountBefore = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("testNetAccountCountBefore:" + testNetAccountCountBefore); - logger.info("contractAccountCountBefore:" + contractAccountCountBefore); - String txid = ""; - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] nonexistentAddress = ecKey2.getAddress(); - String num = - "\"1" + "\",\"" + Base58.encode58Check(nonexistentAddress) + "\",\"" + assetAccountId - .toStringUtf8() + "\""; - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTokenNonexistentTarget(uint256,address,trcToken)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById:" + infoById); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long testNetAccountCountAfter = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("testNetAccountCountAfter:" + testNetAccountCountAfter); - logger.info("contractAccountCountAfter:" + contractAccountCountAfter); - - Assert.assertEquals(0, infoById.get().getResultValue()); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertEquals(testNetAccountCountBefore, testNetAccountCountAfter); - Assert.assertEquals(contractAccountCountBefore - 1, contractAccountCountAfter.longValue()); - - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertNotEquals(10000000, energyUsageTotal); - - Long nonexistentAddressAccount = PublicMethed - .getAssetIssueValue(nonexistentAddress, assetAccountId, blockingStubFull1); - Assert.assertEquals(1L, nonexistentAddressAccount.longValue()); - - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTokenNonexistentTarget(uint256,address,trcToken)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById:" + infoById); - fee = infoById.get().getFee(); - netUsed = infoById.get().getReceipt().getNetUsage(); - energyUsed = infoById.get().getReceipt().getEnergyUsage(); - netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal2 = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal2); - - infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - afterBalance = infoafter.getBalance(); - afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - afterNetUsed = resourceInfoafter.getNetUsed(); - afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - testNetAccountCountAfter = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("testNetAccountCountAfter:" + testNetAccountCountAfter); - logger.info("contractAccountCountAfter:" + contractAccountCountAfter); - - Assert.assertEquals(0, infoById.get().getResultValue()); - - Assert.assertEquals(testNetAccountCountBefore, testNetAccountCountAfter); - Assert.assertEquals(contractAccountCountBefore - 2, contractAccountCountAfter.longValue()); - - Assert.assertEquals(energyUsageTotal, - energyUsageTotal2 + EnergyCost.getNewAcctCall()); - - nonexistentAddressAccount = PublicMethed - .getAssetIssueValue(nonexistentAddress, assetAccountId, blockingStubFull1); - Assert.assertEquals(2L, nonexistentAddressAccount.longValue()); - } - - - @Test(enabled = true, description = "TransferToken to myself") - public void test4TransferTokenSelf() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long testNetAccountCountBefore = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountBefore = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("testNetAccountCountBefore:" + testNetAccountCountBefore); - logger.info("contractAccountCountBefore:" + contractAccountCountBefore); - String txid = ""; - String num = "1" + ",\"" + assetAccountId.toStringUtf8() + "\""; - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTokenSelf(uint256,trcToken)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById:" + infoById); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long testNetAccountCountAfter = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("testNetAccountCountAfter:" + testNetAccountCountAfter); - logger.info("contractAccountCountAfter:" + contractAccountCountAfter); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertEquals(contractResult.TRANSFER_FAILED, infoById.get().getReceipt().getResult()); - Assert.assertEquals( - "transfer trc10 failed: Cannot transfer asset to yourself.", - ByteArray.toStr(infoById.get().getResMessage().toByteArray())); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertEquals(testNetAccountCountBefore, testNetAccountCountAfter); - Assert.assertEquals(contractAccountCountBefore, contractAccountCountAfter); - - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertNotEquals(10000000, energyUsageTotal); - - - } - - - @Test(enabled = true, description = "TransferToken notexist tokenID ") - public void test5TransferTokenNotexist() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long testNetAccountCountBefore = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountBefore = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("testNetAccountCountBefore:" + testNetAccountCountBefore); - logger.info("contractAccountCountBefore:" + contractAccountCountBefore); - String txid = ""; - String fakeassetAccountId = Long.toString(0L); - - String num = "1" + ",\"" + fakeassetAccountId + "\""; - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTokenInsufficientBalance(uint256,trcToken)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById:" + infoById); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long testNetAccountCountAfter = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("testNetAccountCountAfter:" + testNetAccountCountAfter); - logger.info("contractAccountCountAfter:" + contractAccountCountAfter); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertEquals(contractResult.REVERT, infoById.get().getReceipt().getResult()); - Assert.assertEquals( - "REVERT opcode executed", - ByteArray.toStr(infoById.get().getResMessage().toByteArray())); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertEquals(testNetAccountCountBefore, testNetAccountCountAfter); - Assert.assertEquals(contractAccountCountBefore, contractAccountCountAfter); - - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - - } - - - @Test(enabled = true, description = "TransferToken to nonexistent target and " - + "insufficient tokenBalance") - public void test7TransferTokenNonexistentTarget() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long testNetAccountCountBefore = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountBefore = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("testNetAccountCountBefore:" + testNetAccountCountBefore); - logger.info("contractAccountCountBefore:" + contractAccountCountBefore); - String txid = ""; - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] nonexistentAddress = ecKey2.getAddress(); - String num = - "\"100000000000" + "\",\"" + Base58.encode58Check(nonexistentAddress) + "\",\"" - + assetAccountId - .toStringUtf8() + "\""; - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTokenNonexistentTarget(uint256,address,trcToken)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById:" + infoById); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long testNetAccountCountAfter = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("testNetAccountCountAfter:" + testNetAccountCountAfter); - logger.info("contractAccountCountAfter:" + contractAccountCountAfter); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertEquals(contractResult.REVERT, infoById.get().getReceipt().getResult()); - Assert.assertEquals( - "REVERT opcode executed", - ByteArray.toStr(infoById.get().getResMessage().toByteArray())); - Assert.assertEquals(afterBalance + fee, beforeBalance.longValue()); - Assert.assertEquals(testNetAccountCountBefore, testNetAccountCountAfter); - Assert.assertEquals(contractAccountCountBefore, contractAccountCountAfter); - - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertNotEquals(10000000, energyUsageTotal); - - Long nonexistentAddressAccount = PublicMethed - .getAssetIssueValue(nonexistentAddress, assetAccountId, blockingStubFull1); - Assert.assertEquals(0L, nonexistentAddressAccount.longValue()); - - - } - - - @Test(enabled = true, description = "TransferToken to myself and insufficient tokenBalance") - public void test8TransferTokenSelf() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long testNetAccountCountBefore = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountBefore = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("testNetAccountCountBefore:" + testNetAccountCountBefore); - logger.info("contractAccountCountBefore:" + contractAccountCountBefore); - String txid = ""; - String num = "1000000000000000" + ",\"" + assetAccountId.toStringUtf8() + "\""; - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTokenSelf(uint256,trcToken)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById:" + infoById); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long testNetAccountCountAfter = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("testNetAccountCountAfter:" + testNetAccountCountAfter); - logger.info("contractAccountCountAfter:" + contractAccountCountAfter); - - Assert.assertTrue(infoById.get().getResultValue() == 1); - Assert.assertEquals(contractResult.REVERT, infoById.get().getReceipt().getResult()); - Assert.assertEquals( - "REVERT opcode executed", - ByteArray.toStr(infoById.get().getResMessage().toByteArray())); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertEquals(testNetAccountCountBefore, testNetAccountCountAfter); - Assert.assertEquals(contractAccountCountBefore, contractAccountCountAfter); - - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - - Assert.assertNotEquals(10000000, energyUsageTotal); - - } - - @Test(enabled = true, description = "TransferToken to nonexistent target, but revert") - public void test9TransferTokenNonexistentTargetRevert() { - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long testNetAccountCountBefore = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountBefore = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("testNetAccountCountBefore:" + testNetAccountCountBefore); - logger.info("contractAccountCountBefore:" + contractAccountCountBefore); - String txid = ""; - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] nonexistentAddress = ecKey2.getAddress(); - String num = - "\"1" + "\",\"" + Base58.encode58Check(nonexistentAddress) + "\",\"" + assetAccountId - .toStringUtf8() + "\""; - txid = PublicMethed.triggerContract(contractAddress, - "testTransferTokenRevert(uint256,address,trcToken)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById:" + infoById); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long testNetAccountCountAfter = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("testNetAccountCountAfter:" + testNetAccountCountAfter); - logger.info("contractAccountCountAfter:" + contractAccountCountAfter); - - Assert.assertEquals(1, infoById.get().getResultValue()); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertEquals(testNetAccountCountBefore, testNetAccountCountAfter); - Assert.assertEquals(contractAccountCountBefore, contractAccountCountAfter); - - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertTrue(energyUsageTotal > EnergyCost.getNewAcctCall()); - - Long nonexistentAddressAccount = PublicMethed - .getAssetIssueValue(nonexistentAddress, assetAccountId, blockingStubFull1); - Assert.assertEquals(0L, nonexistentAddressAccount.longValue()); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed004.java deleted file mode 100644 index cd8cea864e6..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed004.java +++ /dev/null @@ -1,576 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.transferfailed; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TransferFailed004 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - byte[] contractAddress2 = null; - byte[] contractAddress3 = null; - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 10000000L; - private static ByteString assetAccountId = null; - private static ByteString assetAccountId2 = null; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress3 = ecKey3.getAddress(); - String contractExcKey3 = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] nonexistentAddress = ecKey2.getAddress(); - long energyUsageTotal = 0; - long energyUsageTotal2 = 0; - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - - //Create a new AssetIssue success. - Assert - .assertTrue(PublicMethed.createAssetIssue(contractExcAddress, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, - 100000L, 1L, 1L, contractExcKey, blockingStubFull)); - - assetAccountId = PublicMethed.queryAccount(contractExcAddress, blockingStubFull) - .getAssetIssuedID(); - - } - - @Test(enabled = true, description = "Suicide nonexistent target") - public void test1SuicideNonexistentTarget() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TransferFailed001.sol"; - String contractName = "EnergyOfTransferFailedTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContractFallbackReceive(contractName, abi, code, "", - maxFeeLimit, 1000000L, 100,1000L, assetAccountId.toStringUtf8(), 1000L, - null, contractExcKey, contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long testNetAccountCountBefore = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountBefore = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("testNetAccountCountBefore:" + testNetAccountCountBefore); - logger.info("contractAccountCountBefore:" + contractAccountCountBefore); - String txid = ""; - String num = "\"" + Base58.encode58Check(nonexistentAddress) + "\""; - - txid = PublicMethed.triggerContract(contractAddress, - "testSuicideNonexistentTarget(address)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - final Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - final Long netFee = infoById.get().getReceipt().getNetFee(); - energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - Long testNetAccountCountAfter = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - logger.info("testNetAccountCountAfter:" + testNetAccountCountAfter); - logger.info("contractAccountCountAfter:" + contractAccountCountAfter); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertEquals(0, infoById.get().getResultValue()); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertEquals(testNetAccountCountBefore, testNetAccountCountAfter); - Assert.assertEquals(0L, contractAccountCountAfter.longValue()); - Assert.assertNotEquals(10000000, energyUsageTotal); - String assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetIssuedID().toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - Assert.assertEquals(0, assetIssueId.length()); - - Account nonexistentAddressAccountTrxBalance = PublicMethed - .queryAccount(nonexistentAddress, blockingStubFull1); - Assert.assertEquals(1000000L, nonexistentAddressAccountTrxBalance.getBalance()); - Long nonexistentAddressAccountTokenBalance = PublicMethed - .getAssetIssueValue(nonexistentAddress, assetAccountId, blockingStubFull1); - Assert.assertEquals(1000L, nonexistentAddressAccountTokenBalance.longValue()); - } - - @Test(enabled = true, description = "Suicide existent target") - public void test2SuicideExistentTarget() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - String filePath = "src/test/resources/soliditycode/TransferFailed001.sol"; - String contractName = "EnergyOfTransferFailedTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress2 = PublicMethed.deployContractFallbackReceive(contractName, abi, code, "", - maxFeeLimit, 1000000L, 100,1000L, assetAccountId.toStringUtf8(), - 1000L,null, contractExcKey, contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long testNetAccountCountBefore = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountBefore = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("testNetAccountCountBefore:" + testNetAccountCountBefore); - logger.info("contractAccountCountBefore:" + contractAccountCountBefore); - - Assert.assertTrue(PublicMethed - .sendcoin(nonexistentAddress, 1000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String txid = ""; - String num = "\"" + Base58.encode58Check(nonexistentAddress) + "\""; - txid = PublicMethed.triggerContract(contractAddress2, - "testSuicideNonexistentTarget(address)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - final Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - final Long netFee = infoById.get().getReceipt().getNetFee(); - energyUsageTotal2 = infoById.get().getReceipt().getEnergyUsageTotal(); - Long testNetAccountCountAfter = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal2); - logger.info("testNetAccountCountAfter:" + testNetAccountCountAfter); - logger.info("contractAccountCountAfter:" + contractAccountCountAfter); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Account contractafter = PublicMethed.queryAccount(contractAddress2, blockingStubFull1); - long contractBalance = contractafter.getBalance(); - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertEquals(contractBalance, 0); - - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertEquals(testNetAccountCountBefore, testNetAccountCountAfter); - Assert.assertEquals(0L, contractAccountCountAfter.longValue()); - Assert.assertEquals(energyUsageTotal, energyUsageTotal2); - - Account nonexistentAddressAccountTrxBalance = PublicMethed - .queryAccount(nonexistentAddress, blockingStubFull1); - Assert.assertEquals(3000000L, nonexistentAddressAccountTrxBalance.getBalance()); - Long nonexistentAddressAccountTokenBalance = PublicMethed - .getAssetIssueValue(nonexistentAddress, assetAccountId, blockingStubFull1); - Assert.assertEquals(2000L, nonexistentAddressAccountTokenBalance.longValue()); - - } - - @Test(enabled = true, description = "Suicide nonexistent target, but revert") - public void test3SuicideNonexistentTargetRevert() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - String filePath = "src/test/resources/soliditycode/TransferFailed001.sol"; - String contractName = "EnergyOfTransferFailedTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress3 = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Assert.assertTrue(PublicMethed - //.sendcoin(contractAddress, 1000000L, testNetAccountAddress, testNetAccountKey, - // blockingStubFull)); - //PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] nonexistentAddress1 = ecKey2.getAddress(); - - String txid = ""; - String num = "\"" + Base58.encode58Check(nonexistentAddress1) + "\""; - - txid = PublicMethed.triggerContract(contractAddress3, - "testSuicideRevert(address)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infobyid : --- " + infoById); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - final Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - final Long netFee = infoById.get().getReceipt().getNetFee(); - energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertEquals(0, infoById.get().getResultValue()); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertTrue(energyUsageTotal < 1000000000L); - - Account nonexistentAddressAccount = PublicMethed - .queryAccount(nonexistentAddress1, blockingStubFull1); - Assert.assertEquals(1000000L, nonexistentAddressAccount.getBalance()); - } - - @Test(enabled = true, description = "transfer to a suicide contract address same token") - public void test4transferToSuicideContractSameToken() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - String filePath = "src/test/resources/soliditycode/TransferFailed001.sol"; - String contractName = "EnergyOfTransferFailedTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final byte[] contractAddress4 = PublicMethed.deployContract(contractName, abi, code, "", - maxFeeLimit, 1000000L, 100, 1000000000L, - assetAccountId.toStringUtf8(), 1000L,null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Account info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String txid = ""; - String num = "1" + ",\"" + Base58.encode58Check(contractAddress) + "\""; - - txid = PublicMethed.triggerContract(contractAddress4, - "testTransferTrxNonexistentTarget(uint256,address)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("infoById:" + infoById); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(contractResult.SUCCESS, infoById.get().getReceipt().getResult()); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertNotEquals(10000000, energyUsageTotal); - - Account nonexistentAddressAccount = PublicMethed - .queryAccount(contractAddress, blockingStubFull1); - Assert.assertEquals(1L, nonexistentAddressAccount.getBalance()); - - num = - "\"1" + "\",\"" + Base58.encode58Check(contractAddress) + "\",\"" + assetAccountId - .toStringUtf8() + "\""; - txid = PublicMethed.triggerContract(contractAddress4, - "testTransferTokenNonexistentTarget(uint256,address,trcToken)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - - Long contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - Assert.assertEquals(1L, contractAccountCountAfter.longValue()); - } - - @Test(enabled = true, description = "transfer to a suicide contract address different token") - public void test5transferToSuicideContractDifferentToken() { - // create different token - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress3, 10000_000_000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - //Create a new AssetIssue success. - Assert - .assertTrue(PublicMethed.createAssetIssue(contractExcAddress3, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, - 100000L, 1L, 1L, contractExcKey3, blockingStubFull)); - assetAccountId2 = PublicMethed.queryAccount(contractExcAddress3, blockingStubFull) - .getAssetIssuedID(); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress3, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - String filePath = "src/test/resources/soliditycode/TransferFailed001.sol"; - String contractName = "EnergyOfTransferFailedTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final byte[] contractAddress4 = PublicMethed.deployContract(contractName, abi, code, "", - maxFeeLimit, 1000000L, 100, 1000000000L, - assetAccountId2.toStringUtf8(), 1000L,null, contractExcKey3, - contractExcAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account info; - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress3, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey3, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - Account nonexistentAddressAccount = PublicMethed - .queryAccount(contractAddress, blockingStubFull1); - Assert.assertEquals(1L, nonexistentAddressAccount.getBalance()); - - String num = - "\"1" + "\",\"" + Base58.encode58Check(contractAddress) + "\",\"" + assetAccountId2 - .toStringUtf8() + "\""; - String txid = PublicMethed.triggerContract(contractAddress4, - "testTransferTokenNonexistentTarget(uint256,address,trcToken)", num, false, - 0, maxFeeLimit, contractExcAddress3, contractExcKey3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - - Long contractAccountCountTokenBalance = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - Assert.assertEquals(1L, contractAccountCountTokenBalance.longValue()); - Long contractAccountCountTokenBalance2 = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId2, blockingStubFull); - Assert.assertEquals(1L, contractAccountCountTokenBalance2.longValue()); - - String assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetIssuedID().toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - Assert.assertEquals(0, assetIssueId.length()); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed005.java deleted file mode 100644 index 63c589482bb..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed005.java +++ /dev/null @@ -1,493 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.transferfailed; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.Return.response_code; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TransferFailed005 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - private final Long maxFeeLimit = Configuration.getByPath("testng.cong") - .getLong("defaultParameter.maxFeeLimit"); - byte[] contractAddress = null; - byte[] contractAddress1 = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] accountExcAddress = ecKey1.getAddress(); - String accountExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(accountExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - { - Assert.assertTrue(PublicMethed - .sendcoin(accountExcAddress, 10000_000_000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/TransferFailed005.sol"; - String contractName = "EnergyOfTransferFailedTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 100L, 100L, null, accountExcKey, - accountExcAddress, blockingStubFull); - - filePath = "src/test/resources/soliditycode/TransferFailed005.sol"; - contractName = "Caller"; - retMap = PublicMethed.getBycodeAbi(filePath, contractName); - code = retMap.get("byteCode").toString(); - abi = retMap.get("abI").toString(); - - contractAddress1 = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100L, null, accountExcKey, - accountExcAddress, blockingStubFull); - } - } - - @Test(enabled = false, description = "Deploy contract for trigger") - public void deployContract() { - Assert.assertTrue(PublicMethed - .sendcoin(accountExcAddress, 10000_000_000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/TransferFailed005.sol"; - String contractName = "EnergyOfTransferFailedTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100L, null, accountExcKey, - accountExcAddress, blockingStubFull); - String txid1 = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100L, - null, accountExcKey, accountExcAddress, blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid1, blockingStubFull); - contractAddress = infoById.get().getContractAddress().toByteArray(); - Assert.assertEquals(0, infoById.get().getResultValue()); - - filePath = "src/test/resources/soliditycode/TransferFailed005.sol"; - contractName = "Caller"; - retMap = PublicMethed.getBycodeAbi(filePath, contractName); - code = retMap.get("byteCode").toString(); - abi = retMap.get("abI").toString(); - - contractAddress1 = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100L, null, accountExcKey, - accountExcAddress, blockingStubFull); - txid1 = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100L, - null, accountExcKey, accountExcAddress, blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - contractAddress1 = infoById.get().getContractAddress().toByteArray(); - logger.info("caller address : " + Base58.encode58Check(contractAddress1)); - Assert.assertEquals(0, infoById.get().getResultValue()); - } - - @Test(enabled = true, description = "TransferFailed for function call_value ") - public void triggerContract01() { - Account info = null; - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(accountExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(accountExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - //Assert.assertTrue(PublicMethed - // .sendcoin(contractAddress, 1000100L, accountExcAddress, accountExcKey, blockingStubFull)); - //Assert.assertTrue(PublicMethed - // .sendcoin(contractAddress1, 1, accountExcAddress, accountExcKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("contractAddress balance before: " + PublicMethed - .queryAccount(contractAddress, blockingStubFull).getBalance()); - logger.info("callerAddress balance before: " + PublicMethed - .queryAccount(contractAddress1, blockingStubFull).getBalance()); - long paramValue = 1; - - // transfer trx to self`s account - String param = "\"" + paramValue + "\",\"" + Base58.encode58Check(contractAddress) + "\""; - String triggerTxid = PublicMethed - .triggerContract(contractAddress, "testCallTrxInsufficientBalance(uint256,address)", param, - false, 0L, maxFeeLimit, accountExcAddress, accountExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - Assert.assertEquals(infoById.get().getResultValue(), 1); - Assert.assertEquals("FAILED", infoById.get().getResult().toString()); - Assert.assertEquals("TRANSFER_FAILED", infoById.get().getReceipt().getResult().toString()); - Assert.assertEquals("transfer trx failed: Cannot transfer TRX to yourself.", - infoById.get().getResMessage().toStringUtf8()); - Assert.assertEquals(100L, - PublicMethed.queryAccount(contractAddress, blockingStubFull).getBalance()); - Assert.assertEquals(0L, - PublicMethed.queryAccount(contractAddress1, blockingStubFull).getBalance()); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() < 10000000); - - // transfer trx to unactivate account - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] accountExcAddress2 = ecKey2.getAddress(); - param = "\"" + paramValue + "\",\"" + Base58.encode58Check(accountExcAddress2) + "\""; - triggerTxid = PublicMethed - .triggerContract(contractAddress, "testCallTrxInsufficientBalance(uint256,address)", param, - false, 0L, maxFeeLimit, accountExcAddress, accountExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); - - Assert.assertEquals(infoById.get().getResultValue(), 0); - Assert.assertEquals("SUCESS", infoById.get().getResult().toString()); - - Assert.assertEquals(99L, - PublicMethed.queryAccount(contractAddress, blockingStubFull).getBalance()); - Assert.assertEquals(0L, - PublicMethed.queryAccount(contractAddress1, blockingStubFull).getBalance()); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() < 10000000); - - // transfer trx to caller, value enough , function success contractResult(call_value) successed - param = "\"" + paramValue + "\",\"" + Base58.encode58Check(contractAddress1) + "\""; - triggerTxid = PublicMethed - .triggerContract(contractAddress, "testCallTrxInsufficientBalance(uint256,address)", param, - false, 0L, maxFeeLimit, accountExcAddress, accountExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info(infoById.get().getReceipt().getResult() + ""); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - int contractResult = ByteArray.toInt(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals(1, contractResult); - - Assert.assertEquals(infoById.get().getResultValue(), 0); - Assert.assertEquals(infoById.get().getResult().toString(), "SUCESS"); - Assert.assertEquals(98L, - PublicMethed.queryAccount(contractAddress, blockingStubFull).getBalance()); - Assert.assertEquals(1L, - PublicMethed.queryAccount(contractAddress1, blockingStubFull).getBalance()); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() < 10000000); - - // transfer trx to caller, value not enough, function success - // but contractResult(call_value) failed - param = "\"" + 100 + "\",\"" + Base58.encode58Check(contractAddress1) + "\""; - triggerTxid = PublicMethed - .triggerContract(contractAddress, "testCallTrxInsufficientBalance(uint256,address)", param, - false, 0L, maxFeeLimit, accountExcAddress, accountExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); - fee = infoById.get().getFee(); - netUsed = infoById.get().getReceipt().getNetUsage(); - energyUsed = infoById.get().getReceipt().getEnergyUsage(); - netFee = infoById.get().getReceipt().getNetFee(); - energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - //contractResult`s first boolean value - contractResult = ByteArray.toInt(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals(0, contractResult); - Assert.assertEquals(infoById.get().getResultValue(), 0); - Assert.assertEquals(infoById.get().getResult().toString(), "SUCESS"); - Assert.assertEquals(98L, - PublicMethed.queryAccount(contractAddress, blockingStubFull).getBalance()); - Assert.assertEquals(1L, - PublicMethed.queryAccount(contractAddress1, blockingStubFull).getBalance()); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() < 10000000); - - - } - - @Test(enabled = true, description = "TransferFailed for create") - public void triggerContract02() { - final Long contractBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Account info = null; - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(accountExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(accountExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - //Assert.assertTrue(PublicMethed - // .sendcoin(contractAddress, 1000100L, accountExcAddress, accountExcKey, blockingStubFull)); - //Assert.assertTrue(PublicMethed - // .sendcoin(contractAddress1, 1, accountExcAddress, accountExcKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info("contractAddress balance before: " + PublicMethed - .queryAccount(contractAddress, blockingStubFull).getBalance()); - logger.info("callerAddress balance before: " + PublicMethed - .queryAccount(contractAddress1, blockingStubFull).getBalance()); - long paramValue = 1; - String param = "\"" + paramValue + "\""; - - String triggerTxid = PublicMethed - .triggerContract(contractAddress, "testCreateTrxInsufficientBalance(uint256)", param, false, - 0L, maxFeeLimit, accountExcAddress, accountExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info(infoById.get().getReceipt().getResult() + ""); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - logger.info("contractAddress balance before: " + PublicMethed - .queryAccount(contractAddress, blockingStubFull).getBalance()); - logger.info("callerAddress balance before: " + PublicMethed - .queryAccount(contractAddress1, blockingStubFull).getBalance()); - Assert.assertEquals(infoById.get().getResultValue(), 0); - Assert.assertFalse(infoById.get().getInternalTransactions(0).getRejected()); - Assert.assertEquals(contractBalance - 1, - PublicMethed.queryAccount(contractAddress, blockingStubFull).getBalance()); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() < 10000000); - - param = "\"" + (contractBalance + 1) + "\""; - triggerTxid = PublicMethed - .triggerContract(contractAddress, "testCreateTrxInsufficientBalance(uint256)", param, false, - 0L, maxFeeLimit, accountExcAddress, accountExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); - fee = infoById.get().getFee(); - netUsed = infoById.get().getReceipt().getNetUsage(); - energyUsed = infoById.get().getReceipt().getEnergyUsage(); - netFee = infoById.get().getReceipt().getNetFee(); - energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - logger.info("contractAddress balance before: " + PublicMethed - .queryAccount(contractAddress, blockingStubFull).getBalance()); - logger.info("callerAddress balance before: " + PublicMethed - .queryAccount(contractAddress1, blockingStubFull).getBalance()); - - Assert.assertEquals(infoById.get().getResultValue(), 1); - Assert.assertEquals(infoById.get().getResMessage().toStringUtf8(), "REVERT opcode executed"); - Assert.assertEquals(contractBalance - 1, - PublicMethed.queryAccount(contractAddress, blockingStubFull).getBalance()); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() < 10000000); - - - } - - @Test(enabled = true, description = "TransferFailed for create2") - public void triggerContract03() { - final Long contractBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(accountExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(accountExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - //Assert.assertTrue(PublicMethed - // .sendcoin(contractAddress, 15L, accountExcAddress, accountExcKey, blockingStubFull)); - logger.info("contractAddress balance before: " + PublicMethed - .queryAccount(contractAddress, blockingStubFull).getBalance()); - - String filePath = "./src/test/resources/soliditycode/TransferFailed007.sol"; - String contractName = "Caller"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String testContractCode = retMap.get("byteCode").toString(); - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - String triggerTxid = PublicMethed - .triggerContract(contractAddress, "deploy(bytes,uint256)", param, false, 0L, maxFeeLimit, - accountExcAddress, accountExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Long afterBalance = 0L; - afterBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull).getBalance(); - logger.info("contractAddress balance after : " + PublicMethed - .queryAccount(contractAddress, blockingStubFull).getBalance()); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("SUCESS", infoById.get().getResult().toString()); - Assert.assertEquals(contractBalance - 10L, afterBalance.longValue()); - Assert.assertFalse(infoById.get().getInternalTransactions(0).getRejected()); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() < 10000000); - - triggerTxid = PublicMethed - .triggerContract(contractAddress, "deploy2(bytes,uint256)", param, false, 0L, maxFeeLimit, - accountExcAddress, accountExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); - - fee = infoById.get().getFee(); - netUsed = infoById.get().getReceipt().getNetUsage(); - energyUsed = infoById.get().getReceipt().getEnergyUsage(); - netFee = infoById.get().getReceipt().getNetFee(); - energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - afterBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull).getBalance(); - logger.info("contractAddress balance after : " + PublicMethed - .queryAccount(contractAddress, blockingStubFull).getBalance()); - Assert.assertEquals(1, infoById.get().getResultValue()); - Assert.assertEquals("FAILED", infoById.get().getResult().toString()); - Assert.assertEquals(contractBalance - 10L, afterBalance.longValue()); - Assert.assertEquals(0, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() < 10000000); - - } - - @Test(enabled = true, description = "Triggerconstant a transfer function") - public void triggerContract04() { - Account account = PublicMethed.queryAccount(accountExcAddress, blockingStubFull); - Account contractAccount = PublicMethed.queryAccount(contractAddress, blockingStubFull); - - final Long AccountBeforeBalance = account.getBalance(); - final Long contractAccountBalance = contractAccount.getBalance(); - - TransactionExtention return1 = PublicMethed.triggerConstantContractForExtention(contractAddress, - "testTransferTrxInsufficientBalance(uint256)", "1", false, 0L, 1000000000, "0", 0L, - accountExcAddress, accountExcKey, blockingStubFull); - Assert.assertEquals(response_code.SUCCESS, return1.getResult().getCode()); - /*Assert.assertEquals( - "class org.tron.core.vm.program.Program$StaticCallModificationException " - + ": Attempt to call a state modifying opcode inside STATICCALL", - return1.getResult().getMessage().toStringUtf8());*/ - - logger.info("return1: " + return1); - - account = PublicMethed.queryAccount(accountExcAddress, blockingStubFull); - contractAccount = PublicMethed.queryAccount(contractAddress, blockingStubFull); - - Assert.assertEquals(AccountBeforeBalance.longValue(), account.getBalance()); - Assert.assertEquals(contractAccountBalance.longValue(), contractAccount.getBalance()); - } - - /** - * constructor. - */ - @AfterClass - - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(accountExcAddress, accountExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed006.java deleted file mode 100644 index 1dbcf672b96..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed006.java +++ /dev/null @@ -1,229 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.transferfailed; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TransferFailed006 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - private final Long maxFeeLimit = Configuration.getByPath("testng.cong") - .getLong("defaultParameter.maxFeeLimit"); - byte[] contractAddress = null; - byte[] contractAddress1 = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] accountExcAddress = ecKey1.getAddress(); - String accountExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(accountExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - } - - @Test(enabled = false, description = "Deploy contract for trigger") - public void deployContract() { - Assert.assertTrue(PublicMethed - .sendcoin(accountExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/TransferFailed006.sol"; - String contractName = "EnergyOfTransferFailedTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid1 = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100L, - null, accountExcKey, accountExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid1, blockingStubFull); - contractAddress = infoById.get().getContractAddress().toByteArray(); - Assert.assertEquals(0, infoById.get().getResultValue()); - - filePath = "src/test/resources/soliditycode/TransferFailed006.sol"; - contractName = "Caller"; - retMap = PublicMethed.getBycodeAbi(filePath, contractName); - code = retMap.get("byteCode").toString(); - abi = retMap.get("abI").toString(); - - txid1 = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100L, - null, accountExcKey, accountExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid1, blockingStubFull); - contractAddress1 = infoById.get().getContractAddress().toByteArray(); - logger.info("caller address : " + Base58.encode58Check(contractAddress1)); - Assert.assertEquals(0, infoById.get().getResultValue()); - } - - @Test(enabled = false, description = "TransferFailed for create") - public void triggerContract() { - Account info = null; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(accountExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(accountExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - Assert.assertTrue(PublicMethed - .sendcoin(contractAddress, 1000100L, accountExcAddress, accountExcKey, blockingStubFull)); - Assert.assertTrue(PublicMethed - .sendcoin(contractAddress1, 1, accountExcAddress, accountExcKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - logger.info( - "contractAddress balance before: " + PublicMethed - .queryAccount(contractAddress, blockingStubFull) - .getBalance()); - logger.info( - "callerAddress balance before: " + PublicMethed - .queryAccount(contractAddress1, blockingStubFull) - .getBalance()); - long paramValue = 1000000; - String param = "\"" + paramValue + "\""; - - String triggerTxid = PublicMethed.triggerContract(contractAddress, - "testCreateTrxInsufficientBalance(uint256)", param, false, 0L, - maxFeeLimit, accountExcAddress, accountExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - logger.info(infoById.get().getReceipt().getResult() + ""); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - logger.info( - "contractAddress balance before: " + PublicMethed - .queryAccount(contractAddress, blockingStubFull) - .getBalance()); - logger.info( - "callerAddress balance before: " + PublicMethed - .queryAccount(contractAddress1, blockingStubFull) - .getBalance()); - Assert.assertEquals(infoById.get().getResultValue(), 0); - Assert.assertFalse(infoById.get().getInternalTransactions(0).getRejected()); - Assert.assertEquals(100L, - PublicMethed.queryAccount(contractAddress, blockingStubFull).getBalance()); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() < 10000000); - - triggerTxid = PublicMethed.triggerContract(contractAddress, - "testCreateTrxInsufficientBalance(uint256)", param, false, 0L, - maxFeeLimit, accountExcAddress, accountExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); - fee = infoById.get().getFee(); - netUsed = infoById.get().getReceipt().getNetUsage(); - energyUsed = infoById.get().getReceipt().getEnergyUsage(); - netFee = infoById.get().getReceipt().getNetFee(); - energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - logger.info( - "contractAddress balance before: " + PublicMethed - .queryAccount(contractAddress, blockingStubFull) - .getBalance()); - logger.info( - "callerAddress balance before: " + PublicMethed - .queryAccount(contractAddress1, blockingStubFull) - .getBalance()); - - Assert.assertEquals(infoById.get().getResultValue(), 1); - Assert.assertEquals(infoById.get().getResMessage().toStringUtf8(), "REVERT opcode executed"); - Assert.assertEquals(100L, - PublicMethed.queryAccount(contractAddress, blockingStubFull).getBalance()); - Assert.assertEquals(1L, - PublicMethed.queryAccount(contractAddress1, blockingStubFull).getBalance()); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() < 10000000); - - - } - - /** - * constructor. - */ - @AfterClass - - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(accountExcAddress, accountExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed007.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed007.java deleted file mode 100644 index 652922245c9..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed007.java +++ /dev/null @@ -1,201 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.transferfailed; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TransferFailed007 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - private final Long maxFeeLimit = Configuration.getByPath("testng.cong") - .getLong("defaultParameter.maxFeeLimit"); - byte[] contractAddress = null; - byte[] contractAddress1 = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] accountExcAddress = ecKey1.getAddress(); - String accountExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(accountExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - } - - @Test(enabled = false, description = "Deploy contract for trigger") - public void deployContract() { - Assert.assertTrue(PublicMethed - .sendcoin(accountExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/TransferFailed007.sol"; - String contractName = "EnergyOfTransferFailedTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid1 = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100L, - null, accountExcKey, accountExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid1, blockingStubFull); - contractAddress = infoById.get().getContractAddress().toByteArray(); - Assert.assertEquals(0, infoById.get().getResultValue()); - } - - @Test(enabled = false, description = "TransferFailed for create2") - public void triggerContract() { - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(accountExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(accountExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - Assert.assertTrue(PublicMethed - .sendcoin(contractAddress, 15L, accountExcAddress, accountExcKey, blockingStubFull)); - logger.info( - "contractAddress balance before: " + PublicMethed - .queryAccount(contractAddress, blockingStubFull) - .getBalance()); - - String filePath = "./src/test/resources/soliditycode/TransferFailed007.sol"; - String contractName = "Caller"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String testContractCode = retMap.get("byteCode").toString(); - Long salt = 1L; - - String param = "\"" + testContractCode + "\"," + salt; - - String triggerTxid = PublicMethed.triggerContract(contractAddress, - "deploy(bytes,uint256)", param, false, 0L, - maxFeeLimit, accountExcAddress, accountExcKey, blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - long afterBalance = 0L; - afterBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - logger.info( - "contractAddress balance after : " + PublicMethed - .queryAccount(contractAddress, blockingStubFull) - .getBalance()); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("SUCESS", infoById.get().getResult().toString()); - Assert.assertEquals(5L, afterBalance); - Assert.assertFalse(infoById.get().getInternalTransactions(0).getRejected()); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() < 10000000); - - triggerTxid = PublicMethed.triggerContract(contractAddress, - "deploy(bytes,uint256)", param, false, 0L, - maxFeeLimit, accountExcAddress, accountExcKey, blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - fee = infoById.get().getFee(); - netUsed = infoById.get().getReceipt().getNetUsage(); - energyUsed = infoById.get().getReceipt().getEnergyUsage(); - netFee = infoById.get().getReceipt().getNetFee(); - energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - afterBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull).getBalance(); - logger.info( - "contractAddress balance after : " + PublicMethed - .queryAccount(contractAddress, blockingStubFull) - .getBalance()); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("SUCESS", infoById.get().getResult().toString()); - Assert.assertEquals(5L, afterBalance); - Assert.assertEquals(0, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() < 10000000); - - } - - /** - * constructor. - */ - @AfterClass - - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(accountExcAddress, accountExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed008.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed008.java deleted file mode 100644 index 02446c6f04b..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/transferfailed/TransferFailed008.java +++ /dev/null @@ -1,485 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.transferfailed; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TransferFailed008 { - - private static final long now = System.currentTimeMillis(); - private static final long TotalSupply = 10000000L; - private static ByteString assetAccountId = null; - private static ByteString assetAccountId2 = null; - private static String tokenName = "testAssetIssue_" + Long.toString(now); - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - byte[] contractAddress = null; - byte[] contractAddress2 = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress3 = ecKey3.getAddress(); - String contractExcKey3 = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] nonexistentAddress = ecKey2.getAddress(); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000_000_000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - - //Create a new AssetIssue success. - Assert - .assertTrue(PublicMethed.createAssetIssue(contractExcAddress, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, - 100000L, 1L, 1L, contractExcKey, blockingStubFull)); - - assetAccountId = PublicMethed.queryAccount(contractExcAddress, blockingStubFull) - .getAssetIssuedID(); - System.out.println("assetAccountId:" + assetAccountId.toStringUtf8()); - - Long testNetAccountCountBefore = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - logger.info("testNetAccountCountBefore:" + testNetAccountCountBefore); - } - - - @Test(enabled = false, description = "TransferToken to old contractAddress") - public void test1TransferToOldContractAddress() { - String filePath = "src/test/resources/soliditycode/accountAssert.sol"; - String contractName = "transferTokenTestB"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, 1000000000L, - assetAccountId.toStringUtf8(), 1000L, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long contractAccountTokenBalance = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - Assert.assertEquals(1000L, contractAccountTokenBalance.longValue()); - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long testNetAccountCountBefore = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountBefore = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("testNetAccountCountBefore:" + testNetAccountCountBefore); - logger.info("contractAccountCountBefore:" + contractAccountCountBefore); - String txid = ""; - // TUtbvvfggwQLrDZCNqYpfieCvCaKgKk5k9 selfdestruct contractAddress - // TQ1sSomxqmgqKiGqL3Lt8iybHt28FvUTwN exist accountAddress have token - // TWvKUjxH37F9BoeBrdD1hhWf7Es4CDTsRP exist contractAddress haven't token - // TKK8PhmACsJVX9T7Jkwr2QuWmhB8LjvwUW exist accountAddress haven't token - // v4.1.2 contract address ----Manual input - String oldContractAddress = "TV1ExzvFmSTMj67sxnzHrkZmjpsG5QWSne"; - String num = - "\"" + oldContractAddress + "\",\"1\",\"" + assetAccountId.toStringUtf8() + "\""; - txid = PublicMethed.triggerContract(contractAddress, - "transferTokenTest(address,uint256,trcToken)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById:" + infoById); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long testNetAccountCountAfter = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("testNetAccountCountAfter:" + testNetAccountCountAfter); - logger.info("contractAccountCountAfter:" + contractAccountCountAfter); - - Assert.assertEquals(0, infoById.get().getResultValue()); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertEquals(testNetAccountCountBefore, testNetAccountCountAfter); - Assert.assertEquals(contractAccountCountBefore - 1, contractAccountCountAfter.longValue()); - - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertNotEquals(10000000, energyUsageTotal); - - Long oldContractAddressAccount = PublicMethed.getAssetIssueValue( - PublicMethed.decode58Check(oldContractAddress), assetAccountId, blockingStubFull1); - Assert.assertEquals(1L, oldContractAddressAccount.longValue()); - } - - @Test(enabled = true, description = "TransferToken to new contract") - public void test1TransferToNewContract() { - String filePath = "src/test/resources/soliditycode/accountAssert.sol"; - String contractName = "transferTokenTestB"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, 1000000000L, - assetAccountId.toStringUtf8(), 1000L, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long contractAccountTokenBalance = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - Assert.assertEquals(1000L, contractAccountTokenBalance.longValue()); - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - Long testNetAccountCountBefore = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountBefore = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - logger.info("testNetAccountCountBefore:" + testNetAccountCountBefore); - logger.info("contractAccountCountBefore:" + contractAccountCountBefore); - String txid = ""; - String num = "\"1" + "\",\"" + assetAccountId.toStringUtf8() + "\""; - txid = PublicMethed.triggerContract(contractAddress, - "createContractTest(uint256,trcToken)", num, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("infoById:" + infoById); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull1); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull1); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - Long testNetAccountCountAfter = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - logger.info("testNetAccountCountAfter:" + testNetAccountCountAfter); - logger.info("contractAccountCountAfter:" + contractAccountCountAfter); - - Assert.assertEquals(0, infoById.get().getResultValue()); - - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertEquals(testNetAccountCountBefore, testNetAccountCountAfter); - Assert.assertEquals(contractAccountCountBefore - 1, contractAccountCountAfter.longValue()); - - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Assert.assertNotEquals(10000000, energyUsageTotal); - - String addressHex = - "41" + ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()) - .substring(24); - logger.info("address_hex: " + addressHex); - byte[] contractAddressA = ByteArray.fromHexString(addressHex); - logger.info("contractAddressA: " + Base58.encode58Check(contractAddressA)); - Long nonexistentAddressAccount = PublicMethed - .getAssetIssueValue(contractAddressA, assetAccountId, blockingStubFull1); - Assert.assertEquals(1L, nonexistentAddressAccount.longValue()); - } - - @Test(enabled = true, description = "TransferToken nonexistent target in constructor") - public void test2TransferToNonexistentTargetInConstructor() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long testNetAccountCountBefore = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountBefore = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("testNetAccountCountBefore:" + testNetAccountCountBefore); - logger.info("contractAccountCountBefore:" + contractAccountCountBefore); - - String filePath = "src/test/resources/soliditycode/accountAssert.sol"; - String contractName = "transferTokenTestA"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String constructorStr = "constructor(address,uint256,trcToken)"; - String argsStr = - "\"" + Base58.encode58Check(nonexistentAddress) + "\",\"1\",\"" + assetAccountId - .toStringUtf8() + "\""; - - String deplTxid = PublicMethed.deployContractWithConstantParame(contractName, abi, code, - constructorStr, argsStr, "", maxFeeLimit, 1000000L, 100,1000L, - assetAccountId.toStringUtf8(), 1000L, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = PublicMethed - .getTransactionInfoById(deplTxid, blockingStubFull); - Assert.assertTrue(info.get().getResultValue() == 0); - contractAddress = info.get().getContractAddress().toByteArray(); - - Long testNetAccountCountAfter = PublicMethed - .getAssetIssueValue(contractExcAddress, assetAccountId, blockingStubFull); - Long contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("testNetAccountCountAfter:" + testNetAccountCountAfter); - logger.info("contractAccountCountAfter:" + contractAccountCountAfter); - - Assert.assertEquals(testNetAccountCountBefore.longValue() - 1000L, - testNetAccountCountAfter.longValue()); - Assert.assertEquals(999L, contractAccountCountAfter.longValue()); - - Account nonexistentAddressAccountTrxBalance = PublicMethed - .queryAccount(nonexistentAddress, blockingStubFull1); - Assert.assertEquals(0L, nonexistentAddressAccountTrxBalance.getBalance()); - Long nonexistentAddressAccountTokenBalance = PublicMethed - .getAssetIssueValue(nonexistentAddress, assetAccountId, blockingStubFull1); - Assert.assertEquals(1L, nonexistentAddressAccountTokenBalance.longValue()); - } - - @Test(enabled = true, description = "TransferToken existent target in constructor") - public void test3TransferToExistentTargetInConstructor() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress3, 10000_000_000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long start = System.currentTimeMillis() + 2000; - long end = System.currentTimeMillis() + 1000000000; - - //Create a new AssetIssue success. - Assert - .assertTrue(PublicMethed.createAssetIssue(contractExcAddress3, tokenName, TotalSupply, 1, - 10000, start, end, 1, description, url, 100000L, - 100000L, 1L, 1L, contractExcKey3, blockingStubFull)); - - assetAccountId2 = PublicMethed.queryAccount(contractExcAddress3, blockingStubFull) - .getAssetIssuedID(); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress3, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long testNetAccountCountBefore = PublicMethed - .getAssetIssueValue(contractExcAddress3, assetAccountId2, blockingStubFull); - Long contractAccountCountBefore = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId2, blockingStubFull); - logger.info("testNetAccountCountBefore:" + testNetAccountCountBefore); - logger.info("contractAccountCountBefore:" + contractAccountCountBefore); - - String filePath = "src/test/resources/soliditycode/accountAssert.sol"; - String contractName = "transferTokenTestA"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String constructorStr = "constructor(address,uint256,trcToken)"; - String argsStr = - "\"" + Base58.encode58Check(nonexistentAddress) + "\",\"1\",\"" + assetAccountId2 - .toStringUtf8() + "\""; - - String deplTxid = PublicMethed.deployContractWithConstantParame(contractName, abi, code, - constructorStr, argsStr, "", maxFeeLimit, 1000000L, 100, - 1000L, assetAccountId2.toStringUtf8(), 1000L, null, contractExcKey3, - contractExcAddress3, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = PublicMethed - .getTransactionInfoById(deplTxid, blockingStubFull); - Assert.assertTrue(info.get().getResultValue() == 0); - contractAddress = info.get().getContractAddress().toByteArray(); - - Long testNetAccountCountAfter = PublicMethed - .getAssetIssueValue(contractExcAddress3, assetAccountId2, blockingStubFull); - Long contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId2, blockingStubFull); - logger.info("testNetAccountCountAfter:" + testNetAccountCountAfter); - logger.info("contractAccountCountAfter:" + contractAccountCountAfter); - - Assert.assertEquals(testNetAccountCountBefore.longValue() - 1000L, - testNetAccountCountAfter.longValue()); - Assert.assertEquals(999L, contractAccountCountAfter.longValue()); - - Account nonexistentAddressAccountTrxBalance = PublicMethed - .queryAccount(nonexistentAddress, blockingStubFull1); - Assert.assertEquals(0L, nonexistentAddressAccountTrxBalance.getBalance()); - Long nonexistentAddressAccountTokenBalance = PublicMethed - .getAssetIssueValue(nonexistentAddress, assetAccountId, blockingStubFull1); - Assert.assertEquals(1L, nonexistentAddressAccountTokenBalance.longValue()); - Long nonexistentAddressAccountTokenBalance2 = PublicMethed - .getAssetIssueValue(nonexistentAddress, assetAccountId2, blockingStubFull1); - Assert.assertEquals(1L, nonexistentAddressAccountTokenBalance2.longValue()); - } - - @Test(enabled = true, description = "TransferToken existent target in constructor") - public void test4GetTokenBalanceInConstructor() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 10000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/accountAssert.sol"; - String contractName = "transferTokenTestC"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - String constructorStr = "constructor(trcToken)"; - String argsStr = "\"" + assetAccountId.toStringUtf8() + "\""; - - String deplTxid = PublicMethed.deployContractWithConstantParame(contractName, abi, code, - constructorStr, argsStr, "", maxFeeLimit, 1000000L, 100,1000L, - "0", 0L, null, contractExcKey, contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = PublicMethed - .getTransactionInfoById(deplTxid, blockingStubFull); - Assert.assertTrue(info.get().getResultValue() == 0); - contractAddress = info.get().getContractAddress().toByteArray(); - - Long contractAccountCountAfter = PublicMethed - .getAssetIssueValue(contractAddress, assetAccountId, blockingStubFull); - logger.info("contractAccountCountAfter:" + contractAccountCountAfter); - - Assert.assertEquals(0L, contractAccountCountAfter.longValue()); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant001.java deleted file mode 100644 index 7b2a9da9e35..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant001.java +++ /dev/null @@ -1,1684 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant001 { - - private final String testNetAccountKey = - Configuration.getByPath("testng.conf").getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddressNoAbi = null; - byte[] contractAddressWithAbi = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = - Configuration.getByPath("testng.conf").getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private ManagedChannel channelSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private ManagedChannel channelRealSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubRealSolidity = null; - private String fullnode = - Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list").get(0); - private String fullnode1 = - Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list").get(1); - private String soliditynode = - Configuration.getByPath("testng.conf").getStringList("solidityNode.ip.list").get(0); - private String realSoliditynode = - Configuration.getByPath("testng.conf").getStringList("solidityNode.ip.list").get(1); - - /** constructor. */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode).usePlaintext().build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelRealSolidity = - ManagedChannelBuilder.forTarget(realSoliditynode).usePlaintext().build(); - blockingStubRealSolidity = WalletSolidityGrpc.newBlockingStub(channelRealSolidity); - - { - Assert.assertTrue( - PublicMethed.sendcoin( - contractExcAddress, - 10000_000_000L, - testNetAccountAddress, - testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant001.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - final String abi = retMap.get("abI").toString(); - - contractAddressNoAbi = - PublicMethed.deployContract( - contractName, - "[]", - code, - "", - maxFeeLimit, - 0L, - 100, - null, - contractExcKey, - contractExcAddress, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = - PublicMethed.getContract(contractAddressNoAbi, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - - contractAddressWithAbi = - PublicMethed.deployContract( - contractName, - abi, - code, - "", - maxFeeLimit, - 0L, - 100, - null, - contractExcKey, - contractExcAddress, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract2 = - PublicMethed.getContract(contractAddressWithAbi, blockingStubFull); - Assert.assertFalse(smartContract2.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract2.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract2.getBytecode().toString().isEmpty()); - } - } - - @Test(enabled = true, description = "TriggerConstantContract a payable function without ABI") - public void test01TriggerConstantContract() { - - String txid = ""; - - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtention( - contractAddressNoAbi, - "testPayable()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert.assertThat( - transactionExtention.getResult().getCode().toString(), containsString("SUCCESS")); - Assert.assertEquals( - 1, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - /*Assert.assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL"));*/ - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - TransactionExtention transactionExtentionFromSolidity = - PublicMethed.triggerSolidityContractForExtention( - contractAddressNoAbi, - "testPayable()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubSolidity); - System.out.println("Code = " + transactionExtentionFromSolidity.getResult().getCode()); - System.out.println( - "Message = " + transactionExtentionFromSolidity.getResult().getMessage().toStringUtf8()); - - Assert.assertThat( - transactionExtention.getResult().getCode().toString(), containsString("SUCCESS")); - } - - @Test( - enabled = true, - description = "TriggerConstantContract a payable function" + " without ABI on solidity") - public void test01TriggerConstantContractOnSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressNoAbi, - "testPayable()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubSolidity); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert.assertThat( - transactionExtention.getResult().getCode().toString(), containsString("SUCCESS")); - Assert.assertEquals( - 1, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - /*Assert.assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL"));*/ - } - - @Test( - enabled = true, - description = "TriggerConstantContract a payable function" + " without ABI on real solidity") - public void test01TriggerConstantContractOnRealSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressNoAbi, - "testPayable()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubRealSolidity); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert.assertThat( - transactionExtention.getResult().getCode().toString(), containsString("SUCCESS")); - Assert.assertEquals( - 1, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - /*Assert.assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL"));*/ - } - - @Test( - enabled = true, - description = "TriggerConstantContract a non-payable function" + " without ABI") - public void test02TriggerConstantContract() { - - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtention( - contractAddressNoAbi, - "testNoPayable()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert.assertThat( - transactionExtention.getResult().getCode().toString(), containsString("SUCCESS")); - Assert.assertEquals( - 1, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - /*Assert.assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL"));*/ - } - - @Test( - enabled = true, - description = "TriggerConstantContract a non-payable function" + " without ABI on solidity") - public void test02TriggerConstantContractOnSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressNoAbi, - "testNoPayable()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubSolidity); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert.assertThat( - transactionExtention.getResult().getCode().toString(), containsString("SUCCESS")); - Assert.assertEquals( - 1, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - /*Assert.assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL"));*/ - } - - @Test( - enabled = true, - description = - "TriggerConstantContract a non-payable function" + " without ABI on real solidity") - public void test02TriggerConstantContractOnRealSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressNoAbi, - "testNoPayable()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubRealSolidity); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert.assertThat( - transactionExtention.getResult().getCode().toString(), containsString("SUCCESS")); - Assert.assertEquals( - 1, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - /*Assert.assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL"));*/ - } - - @Test(enabled = true, description = "TriggerConstantContract a view function without ABI") - public void test03TriggerConstantContract() { - - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtention( - contractAddressNoAbi, - "testView()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray.fromHexString(Hex.toHexString(result)))); - } - - @Test( - enabled = true, - description = "TriggerConstantContract a view function" + " without ABI on solidity") - public void test03TriggerConstantContractOnSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressNoAbi, - "testView()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubSolidity); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray.fromHexString(Hex.toHexString(result)))); - } - - @Test( - enabled = true, - description = "TriggerConstantContract a view function" + " without ABI on real solidity") - public void test03TriggerConstantContractOnRealSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressNoAbi, - "testView()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubRealSolidity); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray.fromHexString(Hex.toHexString(result)))); - } - - @Test(enabled = true, description = "TriggerConstantContract a pure function without ABI") - public void test04TriggerConstantContract() { - - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtention( - contractAddressNoAbi, - "testPure()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray.fromHexString(Hex.toHexString(result)))); - } - - @Test( - enabled = true, - description = "TriggerConstantContract a pure function" + " without ABI on solidity") - public void test04TriggerConstantContractOnSolidity() { - - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressNoAbi, - "testPure()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubSolidity); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray.fromHexString(Hex.toHexString(result)))); - } - - @Test( - enabled = true, - description = "TriggerConstantContract a pure function" + " without ABI on real solidity") - public void test04TriggerConstantContractOnRealSolidity() { - - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressNoAbi, - "testPure()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubRealSolidity); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray.fromHexString(Hex.toHexString(result)))); - } - - @Test(enabled = true, description = "TriggerConstantContract a payable function with ABI") - public void test05TriggerConstantContract() { - - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtention( - contractAddressNoAbi, - "testPayable()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert.assertThat( - transactionExtention.getResult().getCode().toString(), containsString("SUCCESS")); - Assert.assertEquals( - 1, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - /*Assert.assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL"));*/ - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test( - enabled = true, - description = "TriggerConstantContract a payable function" + " with ABI on solidity") - public void test05TriggerConstantContractOnSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressNoAbi, - "testPayable()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubSolidity); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert.assertThat( - transactionExtention.getResult().getCode().toString(), containsString("SUCCESS")); - Assert.assertEquals( - 1, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - /*Assert.assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL"));*/ - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test( - enabled = true, - description = "TriggerConstantContract a payable function" + " with ABI on real solidity") - public void test05TriggerConstantContractOnRealSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressNoAbi, - "testPayable()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubRealSolidity); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert.assertThat( - transactionExtention.getResult().getCode().toString(), containsString("SUCCESS")); - Assert.assertEquals( - 1, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - /*Assert.assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL"));*/ - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "TriggerConstantContract a non-payable function with ABI") - public void test06TriggerConstantContract() { - - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtention( - contractAddressWithAbi, - "testNoPayable()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert.assertThat( - transactionExtention.getResult().getCode().toString(), containsString("SUCCESS")); - Assert.assertEquals( - 1, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - /*Assert.assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL"));*/ - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test( - enabled = true, - description = "TriggerConstantContract a non-payable function" + " with ABI on solidity") - public void test06TriggerConstantContractOnSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressWithAbi, - "testNoPayable()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubSolidity); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert.assertThat( - transactionExtention.getResult().getCode().toString(), containsString("SUCCESS")); - Assert.assertEquals( - 1, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - /*Assert.assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL"));*/ - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test( - enabled = true, - description = "TriggerConstantContract a non-payable function" + " with ABI on real solidity") - public void test06TriggerConstantContractOnRealSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressWithAbi, - "testNoPayable()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubRealSolidity); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert.assertThat( - transactionExtention.getResult().getCode().toString(), containsString("SUCCESS")); - Assert.assertEquals( - 1, ByteArray.toInt(transactionExtention.getConstantResult(0).toByteArray())); - /*Assert.assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL"));*/ - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "TriggerConstantContract a view function with ABI") - public void test07TriggerConstantContract() { - - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtention( - contractAddressWithAbi, - "testView()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray.fromHexString(Hex.toHexString(result)))); - } - - @Test( - enabled = true, - description = "TriggerConstantContract a view function" + " with ABI on solidity") - public void test07TriggerConstantContractOnSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressWithAbi, - "testView()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubSolidity); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray.fromHexString(Hex.toHexString(result)))); - } - - @Test( - enabled = true, - description = "TriggerConstantContract a view function" + " with ABI on real solidity") - public void test07TriggerConstantContractOnRealSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressWithAbi, - "testView()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubRealSolidity); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray.fromHexString(Hex.toHexString(result)))); - } - - @Test(enabled = true, description = "TriggerConstantContract a pure function with ABI") - public void test08TriggerConstantContract() { - - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtention( - contractAddressWithAbi, - "testPure()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray.fromHexString(Hex.toHexString(result)))); - } - - @Test( - enabled = true, - description = "TriggerConstantContract a pure function" + " with ABI on solidity") - public void test08TriggerConstantContractOnSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressWithAbi, - "testPure()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubSolidity); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray.fromHexString(Hex.toHexString(result)))); - } - - @Test( - enabled = true, - description = "TriggerConstantContract a pure function" + " with ABI on real solidity") - public void test08TriggerConstantContractOnRealSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressWithAbi, - "testPure()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubRealSolidity); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray.fromHexString(Hex.toHexString(result)))); - } - - @Test(enabled = true, description = "TriggerContract a payable function without ABI") - public void test09TriggerContract() { - Account info; - - AccountResourceMessage resourceInfo = - PublicMethed.getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - txid = - PublicMethed.triggerContract( - contractAddressNoAbi, - "testPayable()", - "#", - false, - 0, - maxFeeLimit, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = - PublicMethed.getAccountResource(contractExcAddress, blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber = - ByteArray.toLong( - ByteArray.fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - } - - @Test(enabled = true, description = "TriggerContract a non-payable function without ABI") - public void test10TriggerContract() { - Account info; - - AccountResourceMessage resourceInfo = - PublicMethed.getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - txid = - PublicMethed.triggerContract( - contractAddressNoAbi, - "testNoPayable()", - "#", - false, - 0, - maxFeeLimit, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = - PublicMethed.getAccountResource(contractExcAddress, blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber = - ByteArray.toLong( - ByteArray.fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - } - - @Test(enabled = true, description = "TriggerContract a view function without ABI") - public void test11TriggerContract() { - - Account info; - - AccountResourceMessage resourceInfo = - PublicMethed.getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - txid = - PublicMethed.triggerContract( - contractAddressNoAbi, - "testView()", - "#", - false, - 0, - maxFeeLimit, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = - PublicMethed.getAccountResource(contractExcAddress, blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber = - ByteArray.toLong( - ByteArray.fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - } - - @Test(enabled = true, description = "TriggerContract a pure function without ABI") - public void test12TriggerContract() { - - Account info; - - AccountResourceMessage resourceInfo = - PublicMethed.getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - txid = - PublicMethed.triggerContract( - contractAddressNoAbi, - "testPure()", - "#", - false, - 0, - maxFeeLimit, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = - PublicMethed.getAccountResource(contractExcAddress, blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber = - ByteArray.toLong( - ByteArray.fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - } - - @Test(enabled = true, description = "TriggerContract a pure function with ABI") - public void test18TriggerContract() { - - TransactionExtention transactionExtention = - PublicMethed.triggerContractForExtention( - contractAddressWithAbi, - "testPure()", - "#", - false, - 0, - maxFeeLimit, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray.fromHexString(Hex.toHexString(result)))); - } - - @Test(enabled = true, description = "TriggerContract a payable function with ABI") - public void test19TriggerContract() { - - Account info; - - AccountResourceMessage resourceInfo = - PublicMethed.getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - txid = - PublicMethed.triggerContract( - contractAddressWithAbi, - "testPayable()", - "#", - false, - 0, - maxFeeLimit, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = - PublicMethed.getAccountResource(contractExcAddress, blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber = - ByteArray.toLong( - ByteArray.fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - } - - @Test(enabled = true, description = "TriggerContract a non-payable function with ABI") - public void test20TriggerContract() { - Account info; - - AccountResourceMessage resourceInfo = - PublicMethed.getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - txid = - PublicMethed.triggerContract( - contractAddressNoAbi, - "testNoPayable()", - "#", - false, - 0, - maxFeeLimit, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = - PublicMethed.getAccountResource(contractExcAddress, blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber = - ByteArray.toLong( - ByteArray.fromHexString( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - } - - @Test(enabled = true, description = "TriggerContract a view function with ABI") - public void test21TriggerConstantContract() { - - TransactionExtention transactionExtention = - PublicMethed.triggerContractForExtention( - contractAddressWithAbi, - "testView()", - "#", - false, - 0, - maxFeeLimit, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray.fromHexString(Hex.toHexString(result)))); - } - - @Test(enabled = true, description = "TriggerContract a view function with ABI on solidity") - public void test21TriggerConstantContractOnSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressWithAbi, - "testView()", - "#", - false, - 0, - maxFeeLimit, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubSolidity); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray.fromHexString(Hex.toHexString(result)))); - } - - @Test(enabled = true, description = "TriggerContract a view function with ABI on real solidity") - public void test21TriggerConstantContractOnRealSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressWithAbi, - "testView()", - "#", - false, - 0, - maxFeeLimit, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubRealSolidity); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray.fromHexString(Hex.toHexString(result)))); - } - - @Test( - enabled = true, - description = "TriggerConstantContract a view method with ABI ,method has " + "revert()") - public void test24TriggerConstantContract() { - - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtention( - contractAddressWithAbi, - "testView2()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - - Assert.assertThat(transaction.getRet(0).getRet().toString(), containsString("FAILED")); - Assert.assertThat( - ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray()), - containsString("REVERT opcode executed")); - } - - @Test( - enabled = true, - description = - "TriggerConstantContract a view method with ABI ,method has " + "revert() on solidity") - public void test24TriggerConstantContractOnSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressWithAbi, - "testView2()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubSolidity); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - - Assert.assertThat(transaction.getRet(0).getRet().toString(), containsString("FAILED")); - Assert.assertThat( - ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray()), - containsString("REVERT opcode executed")); - } - - @Test( - enabled = true, - description = - "TriggerConstantContract a view method with ABI ,method has " - + "revert() on real solidity") - public void test24TriggerConstantContractOnRealSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressWithAbi, - "testView2()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubRealSolidity); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - - Assert.assertThat(transaction.getRet(0).getRet().toString(), containsString("FAILED")); - Assert.assertThat( - ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray()), - containsString("REVERT opcode executed")); - } - - @Test( - enabled = true, - description = "TriggerContract a view method with ABI ,method has " + "revert()") - public void test25TriggerConstantContract() { - - TransactionExtention transactionExtention = - PublicMethed.triggerContractForExtention( - contractAddressWithAbi, - "testView2()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - - Assert.assertThat(transaction.getRet(0).getRet().toString(), containsString("FAILED")); - Assert.assertThat( - ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray()), - containsString("REVERT opcode executed")); - } - - @Test( - enabled = true, - description = "TriggerContract a view method with ABI ,method has " + "revert() on solidity") - public void test25TriggerConstantContractOnSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressWithAbi, - "testView2()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubSolidity); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - - Assert.assertThat(transaction.getRet(0).getRet().toString(), containsString("FAILED")); - Assert.assertThat( - ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray()), - containsString("REVERT opcode executed")); - } - - @Test( - enabled = true, - description = - "TriggerContract a view method with ABI ,method has " + "revert() on real solidity") - public void test25TriggerConstantContractOnRealSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressWithAbi, - "testView2()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubRealSolidity); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - - Assert.assertThat(transaction.getRet(0).getRet().toString(), containsString("FAILED")); - Assert.assertThat( - ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray()), - containsString("REVERT opcode executed")); - } - - @Test( - enabled = true, - description = "TriggerConstantContract a view method without ABI,method has" + "revert()") - public void testTriggerConstantContract() { - - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtention( - contractAddressNoAbi, - "testView2()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertThat(transaction.getRet(0).getRet().toString(), containsString("FAILED")); - Assert.assertThat( - ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray()), - containsString("REVERT opcode executed")); - } - - @Test( - enabled = true, - description = - "TriggerConstantContract a view method without ABI,method has" + "revert() on solidity") - public void testTriggerConstantContractOnSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressNoAbi, - "testView2()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubSolidity); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertThat(transaction.getRet(0).getRet().toString(), containsString("FAILED")); - Assert.assertThat( - ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray()), - containsString("REVERT opcode executed")); - } - - @Test( - enabled = true, - description = - "TriggerConstantContract a view method without ABI,method has" - + "revert() on real solidity") - public void testTriggerConstantContractOnRealSolidity() { - TransactionExtention transactionExtention = - PublicMethed.triggerConstantContractForExtentionOnSolidity( - contractAddressNoAbi, - "testView2()", - "#", - false, - 0, - 0, - "0", - 0, - contractExcAddress, - contractExcKey, - blockingStubRealSolidity); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertThat(transaction.getRet(0).getRet().toString(), containsString("FAILED")); - Assert.assertThat( - ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray()), - containsString("REVERT opcode executed")); - } - - /** constructor. */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant002.java deleted file mode 100644 index fdd17a35ccf..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant002.java +++ /dev/null @@ -1,150 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant002 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerConstantContract a non-payable function without ABI") - public void testTriggerConstantContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant002.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, "[]", code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "testNoPayable()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert - .assertThat(transactionExtention.getResult().getCode().toString(), - containsString("CONTRACT_EXE_ERROR")); - Assert - .assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL")); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant003.java deleted file mode 100644 index bf8fc22f827..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant003.java +++ /dev/null @@ -1,243 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant003 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant003.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, "[]", code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - - } - - @Test(enabled = true, description = "TriggerConstantContract a view function without ABI") - public void test001TriggerConstantContract() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "testView()", "#", false, - 0, 1000000000, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result)))); - } - - @Test(enabled = true, description = "TriggerConstantContract a pure function without ABI") - public void test002TriggerConstantContract() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "testPure()", "#", false, - 0, 1000000000, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result)))); - } - - @Test(enabled = true, description = "TriggerConstantContract a payable function without ABI") - public void test003TriggerConstantContract() { - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "testPayable()", "#", false, - 0, 1000000000, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - Assert.assertEquals("SUCESS", transaction.getRet(0).getRet().toString()); - Assert.assertEquals(1, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result)))); - - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "testPayable()", "#", false, - 1L, 1000000000, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - transaction = transactionExtention.getTransaction(); - System.out.println(transactionExtention.toString()); - result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result)))); - Assert.assertEquals("SUCESS", transaction.getRet(0).getRet().toString()); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant004.java deleted file mode 100644 index 53ac6dcf445..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant004.java +++ /dev/null @@ -1,153 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant004 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerConstantContract a pure function without ABI") - public void testTriggerConstantContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant004.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, "[]", code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "testPure()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result)))); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant005.java deleted file mode 100644 index 677cc740345..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant005.java +++ /dev/null @@ -1,141 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant005 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode).usePlaintext().build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerConstantContract a payable function with ABI") - public void testTriggerConstantContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant001.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, "testPayable()", "#", false, 0, 0, - "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert.assertThat(transactionExtention.getResult().getCode().toString(), - containsString("SUCCESS")); - /*Assert.assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL"));*/ - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant006.java deleted file mode 100644 index 208be0ee96d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant006.java +++ /dev/null @@ -1,150 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant006 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerConstantContract a non-payable function with ABI") - public void testTriggerConstantContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant002.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "testNoPayable()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert.assertThat(transactionExtention.getResult().getCode().toString(), - containsString("CONTRACT_EXE_ERROR")); - Assert.assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL")); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant007.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant007.java deleted file mode 100644 index b91bdb8ec8b..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant007.java +++ /dev/null @@ -1,153 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant007 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerConstantContract a view function with ABI") - public void testTriggerConstantContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant003.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "testView()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result)))); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant008.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant008.java deleted file mode 100644 index 908997a168f..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant008.java +++ /dev/null @@ -1,153 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant008 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerConstantContract a pure function with ABI") - public void testTriggerConstantContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant004.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "testPure()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result)))); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant009.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant009.java deleted file mode 100644 index a1a4bc82863..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant009.java +++ /dev/null @@ -1,176 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant009 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerContract a payable function without ABI") - public void testTriggerContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant001.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, "[]", code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - txid = PublicMethed - .triggerContract(contractAddress, - "testPayable()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant010.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant010.java deleted file mode 100644 index 2d461689d23..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant010.java +++ /dev/null @@ -1,176 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant010 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerContract a non-payable function without ABI") - public void testTriggerContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant002.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, "[]", code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - txid = PublicMethed - .triggerContract(contractAddress, - "testNoPayable()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant011.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant011.java deleted file mode 100644 index d54d607d404..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant011.java +++ /dev/null @@ -1,177 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant011 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerContract a view function without ABI") - public void testTriggerContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant003.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, "[]", code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - txid = PublicMethed - .triggerContract(contractAddress, - "testView()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant012.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant012.java deleted file mode 100644 index 978ab515113..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant012.java +++ /dev/null @@ -1,177 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant012 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerContract a pure function without ABI") - public void testTriggerContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant004.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, "[]", code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - - txid = PublicMethed - .triggerContract(contractAddress, - "testPure()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant013.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant013.java deleted file mode 100644 index 187623f508b..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant013.java +++ /dev/null @@ -1,338 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant013 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - byte[] returnAddressBytes = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private ManagedChannel channelSolidity = null; - public ManagedChannel channelPbft = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private ManagedChannel channelRealSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubRealSolidity = null; - public WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPbft = null; - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String realSoliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - private String soliInPbft = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(2); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - channelRealSolidity = ManagedChannelBuilder.forTarget(realSoliditynode) - .usePlaintext() - .build(); - blockingStubRealSolidity = WalletSolidityGrpc.newBlockingStub(channelRealSolidity); - channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext() - .build(); - blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); - } - - @Test(enabled = true, description = "triggerContract a constant function created by create2") - public void test01TriggerContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant015.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String contractName1 = "TestConstract"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - String txid = ""; - String num = "\"" + code1 + "\"" + "," + 1; - txid = PublicMethed - .triggerContract(contractAddress, - "deploy(bytes,uint256)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - returnAddressBytes = infoById.get().getInternalTransactions(0).getTransferToAddress() - .toByteArray(); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - txid = PublicMethed - .triggerContract(returnAddressBytes, - "plusOne()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee1 = infoById1.get().getFee(); - Long netUsed1 = infoById1.get().getReceipt().getNetUsage(); - Long energyUsed1 = infoById1.get().getReceipt().getEnergyUsage(); - Long netFee1 = infoById1.get().getReceipt().getNetFee(); - long energyUsageTotal1 = infoById1.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee1:" + fee1); - logger.info("netUsed1:" + netUsed1); - logger.info("energyUsed1:" + energyUsed1); - logger.info("netFee1:" + netFee1); - logger.info("energyUsageTotal1:" + energyUsageTotal1); - - Account infoafter1 = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter1 = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance1); - logger.info("afterEnergyUsed:" + afterEnergyUsed1); - logger.info("afterNetUsed:" + afterNetUsed1); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed1); - - Assert.assertTrue(infoById1.get().getResultValue() == 0); - Assert.assertTrue(afterBalance1 + fee1 == afterBalance); - Assert.assertTrue(afterEnergyUsed + energyUsed1 >= afterEnergyUsed1); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - - } - - - @Test(enabled = true, description = "TriggerConstantContract a constant function " - + "created by create2") - public void test15TriggerConstantContract() { - - SmartContract smartContract = PublicMethed.getContract(returnAddressBytes, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(returnAddressBytes, - "plusOne()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result)))); - } - - @Test(enabled = true, description = "TriggerConstantContract a constant function " - + "created by create2 on solidity") - public void test15TriggerConstantContractOnSolidity() { - SmartContract smartContract = PublicMethed.getContract(returnAddressBytes, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtentionOnSolidity(returnAddressBytes, - "plusOne()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubSolidity); - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result)))); - } - - @Test(enabled = true, description = "TriggerConstantContract a constant function " - + "created by create2 on real solidity") - public void test15TriggerConstantContractOnRealSolidity() { - SmartContract smartContract = PublicMethed.getContract(returnAddressBytes, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtentionOnSolidity(returnAddressBytes, - "plusOne()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubRealSolidity); - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result)))); - } - - @Test(enabled = true, description = "TriggerConstantContract a constant function " - + "created by create2 on pbft") - public void test17TriggerConstantContractOnPbft() { - SmartContract smartContract = PublicMethed.getContract(returnAddressBytes, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtentionOnSolidity(returnAddressBytes, - "plusOne()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubPbft); - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result)))); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant014.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant014.java deleted file mode 100644 index 90ae8ecd158..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant014.java +++ /dev/null @@ -1,277 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant014 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - byte[] returnAddressBytes = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private ManagedChannel channelSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private ManagedChannel channelRealSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubRealSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String realSoliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode).usePlaintext().build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - channelRealSolidity = ManagedChannelBuilder.forTarget(realSoliditynode).usePlaintext() - .build(); - blockingStubRealSolidity = WalletSolidityGrpc.newBlockingStub(channelRealSolidity); - } - - @Test(enabled = true, description = "TriggerContract a non-constant function created by create2") - public void test01TriggerContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/ClearAbi005.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String contractName1 = "TestConstract"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - String txid = ""; - String num = "\"" + code1 + "\"" + "," + 1; - txid = PublicMethed - .triggerContract(contractAddress, "deploy(bytes,uint256)", num, false, 0, maxFeeLimit, "0", - 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - returnAddressBytes = infoById.get().getInternalTransactions(0).getTransferToAddress() - .toByteArray(); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - txid = PublicMethed - .triggerContract(returnAddressBytes, "plusOne()", "#", false, 0, maxFeeLimit, "0", 0, - contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById1 = null; - infoById1 = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee1 = infoById1.get().getFee(); - Long netUsed1 = infoById1.get().getReceipt().getNetUsage(); - Long energyUsed1 = infoById1.get().getReceipt().getEnergyUsage(); - Long netFee1 = infoById1.get().getReceipt().getNetFee(); - long energyUsageTotal1 = infoById1.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee1:" + fee1); - logger.info("netUsed1:" + netUsed1); - logger.info("energyUsed1:" + energyUsed1); - logger.info("netFee1:" + netFee1); - logger.info("energyUsageTotal1:" + energyUsageTotal1); - - Account infoafter1 = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter1 = PublicMethed - .getAccountResource(contractExcAddress, blockingStubFull); - Long afterBalance1 = infoafter1.getBalance(); - Long afterEnergyUsed1 = resourceInfoafter1.getEnergyUsed(); - Long afterNetUsed1 = resourceInfoafter1.getNetUsed(); - Long afterFreeNetUsed1 = resourceInfoafter1.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance1); - logger.info("afterEnergyUsed:" + afterEnergyUsed1); - logger.info("afterNetUsed:" + afterNetUsed1); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed1); - - Assert.assertTrue(infoById1.get().getResultValue() == 0); - Assert.assertTrue(afterBalance1 + fee1 == afterBalance); - Assert.assertTrue(afterEnergyUsed + energyUsed1 >= afterEnergyUsed1); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById1.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - } - - @Test(enabled = true, description = "TriggerConstantContract a non-constant function " - + "created by create2") - public void test16TriggerConstantContract() { - - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(returnAddressBytes, "plusOne()", "#", false, 0, - maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert - .assertThat(transactionExtention.getResult().getCode().toString(), - containsString("SUCCESS")); - /*Assert - .assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL"));*/ - } - - @Test(enabled = true, description = "TriggerConstantContract a non-constant function " - + "created by create2 on solidity") - public void test16TriggerConstantContractOnSolidity() { - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtentionOnSolidity(returnAddressBytes, "plusOne()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubSolidity); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert - .assertThat(transactionExtention.getResult().getCode().toString(), - containsString("SUCCESS")); - /*Assert - .assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL"));*/ - } - - @Test(enabled = true, description = "TriggerConstantContract a non-constant function " - + "created by create2 on real solidity") - public void test16TriggerConstantContractOnRealSolidity() { - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtentionOnSolidity(returnAddressBytes, "plusOne()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubRealSolidity); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out.println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert - .assertThat(transactionExtention.getResult().getCode().toString(), - containsString("SUCCESS")); - /*Assert - .assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL"));*/ - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant015.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant015.java deleted file mode 100644 index fa1c5715f45..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant015.java +++ /dev/null @@ -1,201 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant015 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerConstantContract a constant function " - + "created by create2") - public void testTriggerConstantContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant015.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String contractName1 = "TestConstract"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - String txid = ""; - String num = "\"" + code1 + "\"" + "," + 1; - txid = PublicMethed - .triggerContract(contractAddress, - "deploy(bytes,uint256)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - byte[] returnAddressBytes = infoById.get().getInternalTransactions(0).getTransferToAddress() - .toByteArray(); - SmartContract smartContract = PublicMethed.getContract(returnAddressBytes, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(returnAddressBytes, - "plusOne()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result)))); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant016.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant016.java deleted file mode 100644 index 77181e1af98..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant016.java +++ /dev/null @@ -1,196 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant016 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerConstantContract a non-constant function " - + "created by create2") - public void testTriggerConstantContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/ClearAbi005.sol"; - String contractName = "Factory"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String contractName1 = "TestConstract"; - HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); - String code1 = retMap1.get("byteCode").toString(); - String abi1 = retMap1.get("abI").toString(); - String txid = ""; - String num = "\"" + code1 + "\"" + "," + 1; - txid = PublicMethed - .triggerContract(contractAddress, - "deploy(bytes,uint256)", num, false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - byte[] returnAddressBytes = infoById.get().getInternalTransactions(0).getTransferToAddress() - .toByteArray(); - String returnAddress = Base58.encode58Check(returnAddressBytes); - logger.info("returnAddress:" + returnAddress); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(returnAddressBytes, - "plusOne()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert - .assertThat(transactionExtention.getResult().getCode().toString(), - containsString("CONTRACT_EXE_ERROR")); - Assert - .assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL")); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant017.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant017.java deleted file mode 100644 index 6e60d9280f2..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant017.java +++ /dev/null @@ -1,175 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant017 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true, description = "TriggerConstantContract a constant function which is " - + "deployed with ABI, but cleared ABI later") - public void testTriggerConstantContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/ClearAbi001.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "testPayable()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result)))); - String txid = ""; - txid = PublicMethed - .clearContractAbi(contractAddress, contractExcAddress, contractExcKey, blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - - TransactionExtention transactionExtention1 = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "testPayable()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - Transaction transaction1 = transactionExtention1.getTransaction(); - - byte[] result1 = transactionExtention1.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction1.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention1.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result1)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result1)))); - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant018.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant018.java deleted file mode 100644 index 5cd429fccca..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant018.java +++ /dev/null @@ -1,151 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant018 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerContract a pure function with ABI") - public void testTriggerContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant004.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - TransactionExtention transactionExtention = PublicMethed - .triggerContractForExtention(contractAddress, - "testPure()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result)))); - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant019.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant019.java deleted file mode 100644 index 48e0ada0559..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant019.java +++ /dev/null @@ -1,175 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant019 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerContract a payable function with ABI") - public void testTriggerContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant001.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - txid = PublicMethed - .triggerContract(contractAddress, - "testPayable()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant020.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant020.java deleted file mode 100644 index 0d6c7fae2fe..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant020.java +++ /dev/null @@ -1,175 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant020 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerContract a non-payable function with ABI") - public void testTriggerContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant002.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String txid = ""; - txid = PublicMethed - .triggerContract(contractAddress, - "testNoPayable()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - - Account infoafter = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - - Assert.assertTrue(infoById.get().getResultValue() == 0); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - Long returnnumber = ByteArray.toLong(ByteArray - .fromHexString(ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()))); - Assert.assertTrue(1 == returnnumber); - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant021.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant021.java deleted file mode 100644 index dd64fd02a91..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant021.java +++ /dev/null @@ -1,149 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant021 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerContract a view function with ABI") - public void testTriggerContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant003.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - TransactionExtention transactionExtention = PublicMethed - .triggerContractForExtention(contractAddress, - "testView()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert.assertEquals(1, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result)))); - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant022.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant022.java deleted file mode 100644 index a0296a8afda..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant022.java +++ /dev/null @@ -1,154 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant022 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerContract a non-payable function " - + "with ABI(constant ABI)") - public void testTriggerContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant002.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = "[{\"constant\":true,\"inputs\":[],\"name\":\"testNoPayable\",\"outputs\":[{\"" - + "name\":\"z\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable" - + "\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"i\",\"outputs\":" - + "[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\"," - + "\"type\":\"function\"}]"; - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - TransactionExtention transactionExtention = PublicMethed - .triggerContractForExtention(contractAddress, - "testNoPayable()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert - .assertThat(transactionExtention.getResult().getCode().toString(), - containsString("CONTRACT_EXE_ERROR")); - Assert - .assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL")); - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant023.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant023.java deleted file mode 100644 index 35d5d014434..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant023.java +++ /dev/null @@ -1,154 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant023 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerConstantContract a non-payable function with" - + " ABI(constant ABI )") - public void testTriggerConstantContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant002.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = "[{\"constant\":true,\"inputs\":[],\"name\":\"testNoPayable\",\"outputs\":[{\"name" - + "\":\"z\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"" - + "type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"i\",\"outputs\":[{\"na" - + "me\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\"" - + ":\"function\"}]"; - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "testNoPayable()", "#", false, - 0, maxFeeLimit, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - System.out.println("Code = " + transactionExtention.getResult().getCode()); - System.out - .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); - - Assert - .assertThat(transactionExtention.getResult().getCode().toString(), - containsString("CONTRACT_EXE_ERROR")); - Assert - .assertThat(transactionExtention.getResult().getMessage().toStringUtf8(), - containsString("Attempt to call a state modifying opcode inside STATICCALL")); - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant024.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant024.java deleted file mode 100644 index 7d1f63e933d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant024.java +++ /dev/null @@ -1,158 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant024 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerConstantContract a view method with ABI ,method has " - + "revert()") - public void testTriggerConstantContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant024.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "testView()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - - Assert - .assertThat(transaction.getRet(0).getRet().toString(), - containsString("FAILED")); - Assert - .assertThat(ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray()), - containsString("REVERT opcode executed")); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant025.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant025.java deleted file mode 100644 index 15da8c6e904..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant025.java +++ /dev/null @@ -1,155 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant025 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerContract a view method with ABI ,method has " - + "revert()") - public void testTriggerContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant024.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerContractForExtention(contractAddress, - "testView()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - - Assert.assertThat(transaction.getRet(0).getRet().toString(), - containsString("FAILED")); - Assert.assertThat(ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray()), - containsString("REVERT opcode executed")); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant026.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant026.java deleted file mode 100644 index 89c346f920f..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant026.java +++ /dev/null @@ -1,159 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant026 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerConstantContract a view method without ABI," - + "method has revert()") - public void testTriggerConstantContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant004.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, "[]", code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "testView()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert - .assertThat(transaction.getRet(0).getRet().toString(), - containsString("FAILED")); - Assert - .assertThat(ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray()), - containsString("REVERT opcode executed")); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant027.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant027.java deleted file mode 100644 index 54a39d526d2..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/triggerconstant/TriggerConstant027.java +++ /dev/null @@ -1,159 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.triggerconstant; - -import static org.hamcrest.core.StringContains.containsString; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TriggerConstant027 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = false, description = "TriggerConstantContract a view method without ABI," - + "method has revert()") - public void testTriggerConstantContract() { - Assert.assertTrue(PublicMethed - .sendcoin(contractExcAddress, 1000000000L, testNetAccountAddress, testNetAccountKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/TriggerConstant004.sol"; - String contractName = "testConstantContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - contractAddress = PublicMethed.deployContract(contractName, "[]", code, "", maxFeeLimit, - 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - Account info; - - AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(contractExcAddress, - blockingStubFull); - info = PublicMethed.queryAccount(contractExcKey, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, - "testView()", "#", false, - 0, 0, "0", 0, contractExcAddress, contractExcKey, blockingStubFull); - - Transaction transaction = transactionExtention.getTransaction(); - - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println(":" + ByteArray - .toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - - Assert - .assertThat(transaction.getRet(0).getRet().toString(), - containsString("FAILED")); - Assert - .assertThat(ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray()), - containsString("REVERT opcode executed")); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed - .freedResource(contractExcAddress, contractExcKey, testNetAccountAddress, blockingStubFull); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tryCatch/tryCatchTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tryCatch/tryCatchTest001.java deleted file mode 100644 index 5e715cc10f6..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tryCatch/tryCatchTest001.java +++ /dev/null @@ -1,254 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tryCatch; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class tryCatchTest001 { - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private byte[] contractAddress; - private byte[] errorContractAddress; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed - .sendcoin(testAddress001, 10000_000_000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "src/test/resources/soliditycode/tryCatch001.sol"; - String contractName = "tryTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0, 100, null, - testFoundationKey, testFoundationAddress, blockingStubFull); - - contractName = "errorContract"; - retMap = PublicMethed.getBycodeAbi(filePath, contractName); - code = retMap.get("byteCode").toString(); - abi = retMap.get("abI").toString(); - errorContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0, 100, null, - testFoundationKey, testFoundationAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - } - - - @Test(enabled = true, description = "try catch revert no msg") - public void tryCatchTest001() { - String methodStr = "getErrorSwitch(address,uint256)"; - String argStr = "\"" + Base58.encode58Check(errorContractAddress) + "\",0"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals("NoErrorMsg", PublicMethed - .getContractStringMsg(transactionInfo.get().getContractResult(0).toByteArray())); - - - } - - @Test(enabled = true, description = "try catch revert msg") - public void tryCatchTest002() { - String methodStr = "getErrorSwitch(address,uint256)"; - String argStr = "\"" + Base58.encode58Check(errorContractAddress) + "\",1"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals("Revert Msg.", PublicMethed - .getContractStringMsg(transactionInfo.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "try catch Require no msg") - public void tryCatchTest003() { - String methodStr = "getErrorSwitch(address,uint256)"; - String argStr = "\"" + Base58.encode58Check(errorContractAddress) + "\",2"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals("NoErrorMsg", PublicMethed - .getContractStringMsg(transactionInfo.get().getContractResult(0).toByteArray())); - - } - - @Test(enabled = true, description = "try catch Require msg") - public void tryCatchTest004() { - String methodStr = "getErrorSwitch(address,uint256)"; - String argStr = "\"" + Base58.encode58Check(errorContractAddress) + "\",3"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals("Require Msg.", PublicMethed - .getContractStringMsg(transactionInfo.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "try catch assert") - public void tryCatchTest005() { - String methodStr = "getErrorSwitch(address,uint256)"; - String argStr = "\"" + Base58.encode58Check(errorContractAddress) + "\",4"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - - } - - @Test(enabled = true, description = "try catch transfer fail") - public void tryCatchTest006() { - String methodStr = "getErrorSwitch(address,uint256)"; - String argStr = "\"" + Base58.encode58Check(errorContractAddress) + "\",5"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals("NoErrorMsg", PublicMethed - .getContractStringMsg(transactionInfo.get().getContractResult(0).toByteArray())); - - } - - @Test(enabled = true, description = "try catch Send_Error") - public void tryCatchTest007() { - String methodStr = "getErrorSwitch(address,uint256)"; - String argStr = "\"" + Base58.encode58Check(errorContractAddress) + "\",6"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals("success", PublicMethed - .getContractStringMsg(transactionInfo.get().getContractResult(0).toByteArray())); - - } - - @Test(enabled = true, description = "try catch Math_Error") - public void tryCatchTest008() { - String methodStr = "getErrorSwitch(address,uint256)"; - String argStr = "\"" + Base58.encode58Check(errorContractAddress) + "\",7"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - - } - - @Test(enabled = true, description = "try catch ArrayOverFlow_Error") - public void tryCatchTest009() { - String methodStr = "getErrorSwitch(address,uint256)"; - String argStr = "\"" + Base58.encode58Check(errorContractAddress) + "\",8"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0, transactionInfo.get().getResultValue()); - Assert.assertEquals(contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - - } - -} - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tryCatch/tryCatchTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tryCatch/tryCatchTest002.java deleted file mode 100644 index debe21b95d1..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tryCatch/tryCatchTest002.java +++ /dev/null @@ -1,252 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tryCatch; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class tryCatchTest002 { - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private byte[] contractAddress; - private byte[] errorContractAddress; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * miraculous.wong. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed - .sendcoin(testAddress001, 10000_000_000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/tryCatch001.sol"; - String contractName = "tryTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0, 100, null, - testFoundationKey, testFoundationAddress, blockingStubFull); - - - } - - - @Test(enabled = true, description = "try catch [new] revert no msg") - public void tryCatchTest001() { - String methodStr = "catchNewErrorSwitch(uint256)"; - String argStr = "0"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals( - "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "try catch [new] revert msg") - public void tryCatchTest002() { - String methodStr = "catchNewErrorSwitch(uint256)"; - String argStr = "1"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals( - "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "try catch [new] Require no msg") - public void tryCatchTest003() { - String methodStr = "catchNewErrorSwitch(uint256)"; - String argStr = "2"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals( - "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - - } - - @Test(enabled = true, description = "try catch [new] Require msg") - public void tryCatchTest004() { - String methodStr = "catchNewErrorSwitch(uint256)"; - String argStr = "3"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals( - "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "try catch [new] assert") - public void tryCatchTest005() { - String methodStr = "catchNewErrorSwitch(uint256)"; - String argStr = "4"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertEquals(contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals( - "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "try catch [new] transfer fail") - public void tryCatchTest006() { - String methodStr = "catchNewErrorSwitch(uint256)"; - String argStr = "5"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals( - "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - - } - - @Test(enabled = true, description = "try catch [new] Send_Error") - public void tryCatchTest007() { - String methodStr = "catchNewErrorSwitch(uint256)"; - String argStr = "6"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertNotEquals( - "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(transactionInfo.get().getContractResult(0).toByteArray())); - - } - - @Test(enabled = true, description = "try catch [new] Math_Error") - public void tryCatchTest008() { - String methodStr = "catchNewErrorSwitch(uint256)"; - String argStr = "7"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals(contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - - } - - @Test(enabled = true, description = "try catch [new] ArrayOverFlow_Error") - public void tryCatchTest009() { - String methodStr = "catchNewErrorSwitch(uint256)"; - String argStr = "8"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, argStr, false, - 0, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional transactionInfo = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("transactionInfo: " + transactionInfo.get()); - Assert.assertEquals(0,transactionInfo.get().getResultValue()); - Assert.assertTrue(transactionInfo.get().getFee() < maxFeeLimit); - Assert.assertEquals(contractResult.SUCCESS, - transactionInfo.get().getReceipt().getResult()); - - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeContractTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeContractTest001.java deleted file mode 100644 index 3dcbc9504c8..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeContractTest001.java +++ /dev/null @@ -1,506 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tvmFreeze; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.Protocol.TransactionInfo.code; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class FreezeContractTest001 { - - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private byte[] contractAddress; - - - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] testAddress002 = ecKey2.getAddress(); - String testKey002 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] testAddress003 = ecKey3.getAddress(); - String testKey003 = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - - private long freezeEnergyUseage; - private byte[] create2Address; - private final long freezeCount = 1000_123456L; - - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - PublicMethed.printAddress(testKey001); - PublicMethed.printAddress(testKey002); - - PublicMethed.printAddress(testFoundationKey); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - Assert.assertTrue(PublicMethed.sendcoin(testAddress001,2000_000000L, - testFoundationAddress,testFoundationKey,blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(testAddress002,10_000000L, - testFoundationAddress,testFoundationKey,blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(testAddress003,12000_000000L, - testFoundationAddress,testFoundationKey,blockingStubFull)); - - String filePath = "src/test/resources/soliditycode/freezeContract001.sol"; - String contractName = "TestFreeze"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 10000_000000L, - 100, null, testFoundationKey, - testFoundationAddress, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - - @Test(description = "contract freeze to account") - void FreezeContractTest001() { - - AccountResourceMessage account002_before = PublicMethed - .getAccountResource(testAddress002,blockingStubFull); - Account contractAccount_before = PublicMethed.queryAccount(contractAddress,blockingStubFull); - - // freeze(address payable receiver, uint amount, uint res) - String methedStr = "freeze(address,uint256,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testAddress002) + "\"," + freezeCount + "," + "1"; - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage account002_after = PublicMethed - .getAccountResource(testAddress002,blockingStubFull); - Account contractAccount_after = PublicMethed.queryAccount(contractAddress, blockingStubFull); - - logger.info("account002_before.getEnergyLimit : " + account002_before.getEnergyLimit()); - logger.info("account002_after.getEnergyLimit : " + account002_after.getEnergyLimit()); - Assert.assertTrue(account002_before.getEnergyLimit() < account002_after.getEnergyLimit()); - Assert.assertEquals(contractAccount_before.getAccountResource() - .getDelegatedFrozenBalanceForEnergy() + freezeCount, - contractAccount_after.getAccountResource().getDelegatedFrozenBalanceForEnergy()); - Assert.assertEquals(contractAccount_before.getBalance() - freezeCount, - contractAccount_after.getBalance()); - - TransactionInfo info = PublicMethed.getTransactionInfoById(txid, blockingStubFull).get(); - freezeEnergyUseage = info.getReceipt().getEnergyUsageTotal(); - - - } - - @Test(description = "contract freeze to self") - void FreezeContractTest002() { - AccountResourceMessage contractResource_before = PublicMethed - .getAccountResource(contractAddress,blockingStubFull); - Account contractAccount_before = PublicMethed.queryAccount(contractAddress,blockingStubFull); - - // freeze(address payable receiver, uint amount, uint res) - String methedStr = "freeze(address,uint256,uint256)"; - String argsStr = "\"" + Base58.encode58Check(contractAddress) + "\"," + freezeCount + "," + "1"; - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage contractResource_after = PublicMethed - .getAccountResource(contractAddress,blockingStubFull); - Account contractAccount_after = PublicMethed.queryAccount(contractAddress, blockingStubFull); - - logger.info("account002_before.getEnergyLimit : " + contractResource_before.getEnergyLimit()); - logger.info("account002_after.getEnergyLimit : " + contractResource_after.getEnergyLimit()); - Assert.assertTrue( - contractResource_before.getEnergyLimit() < contractResource_after.getEnergyLimit()); - Assert.assertEquals(contractAccount_before.getAccountResource() - .getFrozenBalanceForEnergy().getFrozenBalance() + freezeCount, - contractAccount_after.getAccountResource().getFrozenBalanceForEnergy().getFrozenBalance()); - - } - - @Test(description = "contract freeze to other contract") - void FreezeContractTest003() { - String filePath = "src/test/resources/soliditycode/freezeContract001.sol"; - String contractName = "TestFreeze"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - byte[] newContract = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 100_000000L, - 100, null, testFoundationKey, - testFoundationAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - - Account contractAccount_before = PublicMethed.queryAccount(contractAddress,blockingStubFull); - - // freeze(address payable receiver, uint amount, uint res) - String methedStr = "freeze(address,uint256,uint256)"; - String argsStr = "\"" + Base58.encode58Check(newContract) + "\"," + freezeCount + "," + "1"; - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - TransactionInfo info = PublicMethed.getTransactionInfoById(txid, blockingStubFull).get(); - Assert.assertEquals(TransactionInfo.code.FAILED,info.getResult()); - - AccountResourceMessage contractResource_after = PublicMethed - .getAccountResource(newContract,blockingStubFull); - Account contractAccount_after = PublicMethed.queryAccount(contractAddress, blockingStubFull); - - logger.info("account002_after.getEnergyLimit : " + contractResource_after.getEnergyLimit()); - Assert.assertEquals(contractResource_after.getEnergyLimit(),0); - Assert.assertEquals(contractAccount_before.getAccountResource() - .getDelegatedFrozenBalanceForEnergy(), - contractAccount_after.getAccountResource().getDelegatedFrozenBalanceForEnergy()); - Assert.assertEquals(contractAccount_before.getBalance(),contractAccount_after.getBalance()); - - } - - @Test(description = "contract freeze to unactive account", - dependsOnMethods = "FreezeContractTest001") - void FreezeContractTest004() { - - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] testAddress = ecKey.getAddress(); - String testKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - Account contractAccount_before = PublicMethed.queryAccount(contractAddress,blockingStubFull); - - // freeze(address payable receiver, uint amount, uint res) - String methedStr = "freeze(address,uint256,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testAddress) + "\"," + freezeCount + "," + "1"; - logger.info("argsStr: " + argsStr); - - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage account002_after = PublicMethed - .getAccountResource(testAddress,blockingStubFull); - Account contractAccount_after = PublicMethed.queryAccount(contractAddress, blockingStubFull); - - logger.info("account002_after.getEnergyLimit : " + account002_after.getEnergyLimit()); - Assert.assertTrue(account002_after.getEnergyLimit() > 0); - Assert.assertEquals(contractAccount_before.getAccountResource() - .getDelegatedFrozenBalanceForEnergy() + freezeCount, - contractAccount_after.getAccountResource().getDelegatedFrozenBalanceForEnergy()); - Assert.assertEquals(contractAccount_before.getBalance() - freezeCount, - contractAccount_after.getBalance()); - - // check active account status - Account testAccount = PublicMethed.queryAccount(testAddress,blockingStubFull); - Assert.assertTrue(testAccount.getCreateTime() > 0); - Assert.assertNotNull(testAccount.getOwnerPermission()); - Assert.assertNotNull(testAccount.getActivePermissionList()); - - - TransactionInfo info = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get(); - Assert.assertEquals(freezeEnergyUseage + 25000L, info.getReceipt().getEnergyUsageTotal()); - - - } - - @Test(description = "contract freeze to pre create2 address, and UnFreeze", - dependsOnMethods = "FreezeContractTest001") - void FreezeContractTest005() { - String create2ArgsStr = "1"; - String create2MethedStr = "deploy(uint256)"; - TransactionExtention exten = PublicMethed.triggerConstantContractForExtention( - contractAddress, create2MethedStr, create2ArgsStr, false, 0, maxFeeLimit, - "#", 0, testAddress001, testKey001, blockingStubFull); - - String addressHex = - "41" + ByteArray.toHexString(exten.getConstantResult(0).toByteArray()) - .substring(24); - logger.info("address_hex: " + addressHex); - create2Address = ByteArray.fromHexString(addressHex); - logger.info("create2Address: " + Base58.encode58Check(create2Address)); - - - Account contractAccount_before = PublicMethed.queryAccount(contractAddress,blockingStubFull); - - // freeze(address payable receiver, uint amount, uint res) - String methedStr = "freeze(address,uint256,uint256)"; - String argsStr = "\"" + Base58.encode58Check(create2Address) + "\"," + freezeCount + "," + "1"; - logger.info("argsStr: " + argsStr); - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage account002_after = PublicMethed - .getAccountResource(create2Address,blockingStubFull); - Account contractAccount_after = PublicMethed.queryAccount(contractAddress, blockingStubFull); - - logger.info("account002_after.getEnergyLimit : " + account002_after.getEnergyLimit()); - Assert.assertTrue(account002_after.getEnergyLimit() > 0); - Assert.assertEquals(contractAccount_before.getAccountResource() - .getDelegatedFrozenBalanceForEnergy() + freezeCount, - contractAccount_after.getAccountResource().getDelegatedFrozenBalanceForEnergy()); - Assert.assertEquals(contractAccount_before.getBalance() - freezeCount, - contractAccount_after.getBalance()); - - TransactionInfo info = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get(); - Assert.assertEquals(freezeEnergyUseage + 25000L, info.getReceipt().getEnergyUsageTotal()); - - txid = PublicMethed.triggerContract(contractAddress,create2MethedStr, - create2ArgsStr,false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - - contractAccount_before = PublicMethed.queryAccount(contractAddress,blockingStubFull); - - // freeze(address payable receiver, uint amount, uint res) - methedStr = "getExpireTime(address,uint256)"; - argsStr = "\"" + Base58.encode58Check(create2Address) + "\"" + ",1"; - TransactionExtention extention = PublicMethed - .triggerConstantContractForExtention(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,"#",0, testAddress001,testKey001,blockingStubFull); - Long ExpireTime = ByteArray.toLong(extention.getConstantResult(0).toByteArray()); - logger.info("ExpireTime: " + ExpireTime); - Assert.assertTrue(ExpireTime > 0); - - methedStr = "unfreeze(address,uint256)"; - txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - contractAccount_after = PublicMethed.queryAccount(contractAddress, blockingStubFull); - - Assert.assertEquals(contractAccount_before.getAccountResource() - .getDelegatedFrozenBalanceForEnergy() - freezeCount, - contractAccount_after.getAccountResource().getDelegatedFrozenBalanceForEnergy()); - Assert.assertEquals(contractAccount_before.getBalance() + freezeCount, - contractAccount_after.getBalance()); - - } - - @Test(description = "Unfreeze when freeze to account", - dependsOnMethods = "FreezeContractTest001") - void UnFreezeContractTest001() { - - AccountResourceMessage account002_before = PublicMethed - .getAccountResource(testAddress002,blockingStubFull); - Account contractAccount_before = PublicMethed.queryAccount(contractAddress,blockingStubFull); - - // freeze(address payable receiver, uint amount, uint res) - String methedStr = "getExpireTime(address,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testAddress002) + "\"" + ",1"; - TransactionExtention extention = PublicMethed - .triggerConstantContractForExtention(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,"#",0, testAddress001,testKey001,blockingStubFull); - Long ExpireTime = ByteArray.toLong(extention.getConstantResult(0).toByteArray()); - logger.info("ExpireTime: " + ExpireTime); - Assert.assertTrue(ExpireTime > 0); - - methedStr = "unfreeze(address,uint256)"; - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage account002_after = PublicMethed - .getAccountResource(testAddress002,blockingStubFull); - Account contractAccount_after = PublicMethed.queryAccount(contractAddress, blockingStubFull); - - logger.info("account002_before.getEnergyLimit : " + account002_before.getEnergyLimit()); - logger.info("account002_after.getEnergyLimit : " + account002_after.getEnergyLimit()); - - Assert.assertEquals(contractAccount_before.getAccountResource() - .getDelegatedFrozenBalanceForEnergy() - freezeCount, - contractAccount_after.getAccountResource().getDelegatedFrozenBalanceForEnergy()); - - Assert.assertTrue(account002_before.getEnergyLimit() > account002_after.getEnergyLimit()); - - } - - @Test(description = "Unfreeze when freeze to contract self", - dependsOnMethods = "FreezeContractTest002") - void UnFreezeContractTest002() { - - Account contractAccount_before = PublicMethed.queryAccount(contractAddress,blockingStubFull); - - // freeze(address payable receiver, uint amount, uint res) - String methedStr = "getExpireTime(address,uint256)"; - String argsStr = "\"" + Base58.encode58Check(contractAddress) + "\"" + ",1"; - TransactionExtention extention = PublicMethed - .triggerConstantContractForExtention(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,"#",0, testAddress001,testKey001,blockingStubFull); - Long ExpireTime = ByteArray.toLong(extention.getConstantResult(0).toByteArray()); - logger.info("ExpireTime: " + ExpireTime); - Assert.assertTrue(ExpireTime > 0); - - methedStr = "unfreeze(address,uint256)"; - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage account002_after = PublicMethed - .getAccountResource(testAddress002,blockingStubFull); - Account contractAccount_after = PublicMethed.queryAccount(contractAddress, blockingStubFull); - - logger.info("account002_after.getEnergyLimit : " + account002_after.getEnergyLimit()); - - Assert.assertEquals(contractAccount_before.getAccountResource() - .getFrozenBalanceForEnergy().getFrozenBalance() - freezeCount, - contractAccount_after.getAccountResource().getFrozenBalanceForEnergy().getFrozenBalance()); - - - } - - @Test(description = "energy caulate after transaction end") - public void freezeEnergyCaulate() { - - String methedStr = "freeze(address,uint256,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testAddress001) + "\"," + freezeCount + "," + "1"; - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - TransactionInfo info = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get(); - AccountResourceMessage testAccount001 = PublicMethed - .getAccountResource(testAddress001,blockingStubFull); - - - Assert.assertTrue(testAccount001.getEnergyLimit() > 0); - Assert.assertTrue(info.getReceipt().getEnergyFee() > 0); - Assert.assertTrue(testAccount001.getEnergyLimit() > info.getReceipt().getEnergyUsageTotal()); - - methedStr = "unfreeze(address,uint256)"; - argsStr = "\"" + Base58.encode58Check(testAddress001) + "\",1"; - txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - info = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get(); - testAccount001 = PublicMethed.getAccountResource(testAddress001,blockingStubFull); - - Assert.assertEquals(code.SUCESS,info.getResult()); - Assert.assertEquals(contractResult.SUCCESS,info.getReceipt().getResult()); - - - Assert.assertEquals(0, info.getReceipt().getEnergyFee()); - Assert.assertEquals(0, testAccount001.getEnergyLimit()); - Assert.assertTrue(testAccount001.getEnergyUsed() > 0); - } - - @Test(description = "get Zero Address ExpirTime,used to be that freeze to contract self", - dependsOnMethods = "FreezeContractTest002") - public void getZeroExpireTimeTest() { - String ExpireTimeMethedStr = "getExpireTime(address,uint256)"; - String ExpireTimeArgsStr = "\"T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb\"" + ",0"; - TransactionExtention extention = PublicMethed - .triggerConstantContractForExtention(contractAddress,ExpireTimeMethedStr,ExpireTimeArgsStr, - false,0,maxFeeLimit,"#",0, testAddress001,testKey001,blockingStubFull); - Long ExpireTime1 = ByteArray.toLong(extention.getConstantResult(0).toByteArray()); - logger.info("ExpireTime1: " + ExpireTime1); - Assert.assertEquals(0,ExpireTime1.longValue()); - - ExpireTimeArgsStr = "\"T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb\"" + ",1"; - extention = PublicMethed - .triggerConstantContractForExtention(contractAddress,ExpireTimeMethedStr,ExpireTimeArgsStr, - false,0,maxFeeLimit,"#",0, testAddress001,testKey001,blockingStubFull); - Long ExpireTime2 = ByteArray.toLong(extention.getConstantResult(0).toByteArray()); - logger.info("ExpireTime2: " + ExpireTime2); - Assert.assertEquals(0,ExpireTime2.longValue()); - - // freeze(address payable receiver, uint amount, uint res) - String methedStr = "freeze(address,uint256,uint256)"; - String argsStr = "\"" + "T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb" + "\"," + freezeCount + "," + "1"; - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - TransactionInfo info = PublicMethed.getTransactionInfoById(txid, blockingStubFull).get(); - Assert.assertEquals(code.SUCESS,info.getResult()); - Assert.assertEquals(contractResult.SUCCESS,info.getReceipt().getResult()); - - extention = PublicMethed - .triggerConstantContractForExtention(contractAddress,ExpireTimeMethedStr,ExpireTimeArgsStr, - false,0,maxFeeLimit,"#",0, testAddress001,testKey001,blockingStubFull); - Long ExpireTime = ByteArray.toLong(extention.getConstantResult(0).toByteArray()); - logger.info("ExpireTime: " + ExpireTime); - Assert.assertEquals((ExpireTime + 3) * 1000, info.getBlockTimeStamp()); - - - } - - @Test(description = "freeze in constructor") - public void FreezeContractTest006() { - - AccountResourceMessage account003_before = PublicMethed - .getAccountResource(testAddress003,blockingStubFull); - - String filePath = "src/test/resources/soliditycode/freezeContract001.sol"; - String contractName = "D"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - long callValue = 10000_000000L; - byte[] contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, callValue, - 100, null, testKey003, - testAddress003, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage account003_after = PublicMethed - .getAccountResource(testAddress003,blockingStubFull); - Account contractAccount_after = PublicMethed.queryAccount(contractAddress, blockingStubFull); - - logger.info("account002_before.getEnergyLimit : " + account003_before.getEnergyLimit()); - logger.info("account002_after.getEnergyLimit : " + account003_after.getEnergyLimit()); - Assert.assertTrue(account003_before.getEnergyLimit() < account003_after.getEnergyLimit()); - Assert.assertEquals(callValue, - contractAccount_after.getAccountResource().getDelegatedFrozenBalanceForEnergy()); - Assert.assertEquals(0, contractAccount_after.getBalance()); - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeContractTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeContractTest002.java deleted file mode 100644 index bc0d8aca23b..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeContractTest002.java +++ /dev/null @@ -1,271 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tvmFreeze; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.Protocol.TransactionInfo.code; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class FreezeContractTest002 { - - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private byte[] contractAddress; - - - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] testAddress002 = ecKey2.getAddress(); - String testKey002 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private long freezeEnergyUseage; - - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - PublicMethed.printAddress(testKey001); - PublicMethed.printAddress(testKey002); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - Assert.assertTrue(PublicMethed.sendcoin(testAddress001,2000_000000L, - testFoundationAddress,testFoundationKey,blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(testAddress002,10_000000L, - testFoundationAddress,testFoundationKey,blockingStubFull)); - - String filePath = "src/test/resources/soliditycode/freezeContract001.sol"; - String contractName = "TestFreeze"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 100_000000L, - 100, null, testFoundationKey, - testFoundationAddress, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "contract freeze over balance") - void FreezeContract001() { - - AccountResourceMessage account002_before = PublicMethed - .getAccountResource(testAddress002,blockingStubFull); - Account contractAccount_before = PublicMethed.queryAccount(contractAddress,blockingStubFull); - - // freeze(address payable receiver, uint amount, uint res) - Long freezeCount = contractAccount_before.getBalance() + 1; - String methedStr = "freeze(address,uint256,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testAddress002) + "\"," + freezeCount + "," + "1"; - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage account002_after = PublicMethed - .getAccountResource(testAddress002,blockingStubFull); - Account contractAccount_after = PublicMethed.queryAccount(contractAddress, blockingStubFull); - - logger.info("account002_before.getEnergyLimit : " + account002_before.getEnergyLimit()); - logger.info("account002_after.getEnergyLimit : " + account002_after.getEnergyLimit()); - Assert.assertEquals(account002_before.getEnergyLimit(), account002_after.getEnergyLimit()); - Assert.assertEquals(contractAccount_before.getAccountResource() - .getDelegatedFrozenBalanceForEnergy(), - contractAccount_after.getAccountResource().getDelegatedFrozenBalanceForEnergy()); - Assert.assertEquals(contractAccount_before.getBalance(), - contractAccount_after.getBalance()); - - TransactionInfo info = PublicMethed.getTransactionInfoById(txid, blockingStubFull).get(); - freezeEnergyUseage = info.getReceipt().getEnergyUsageTotal(); - - Assert.assertEquals(code.FAILED,info.getResult()); - Assert.assertEquals(contractResult.REVERT,info.getReceipt().getResult()); - - } - - @Test(enabled = true, description = "contract freeze amount < 1 TRX") - void FreezeContract002() { - - Account account002_before = PublicMethed - .queryAccount(testAddress002,blockingStubFull); - Account contractAccount_before = PublicMethed.queryAccount(contractAddress,blockingStubFull); - - // freeze(address payable receiver, uint amount, uint res) - Long freezeCount = 999999L; - String methedStr = "freeze(address,uint256,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testAddress002) + "\"," + freezeCount + "," + "1"; - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account account002_after = PublicMethed - .queryAccount(testAddress002,blockingStubFull); - Account contractAccount_after = PublicMethed.queryAccount(contractAddress, blockingStubFull); - logger.info("account002_before.getAccountResource : " + account002_before.getAccountResource()); - logger.info("account002_after.getAccountResource : " + account002_after.getAccountResource()); - - Assert.assertEquals( - account002_before.getAccountResource().getAcquiredDelegatedFrozenBalanceForEnergy(), - account002_after.getAccountResource().getAcquiredDelegatedFrozenBalanceForEnergy()); - Assert.assertEquals(contractAccount_before.getAccountResource() - .getDelegatedFrozenBalanceForEnergy(), - contractAccount_after.getAccountResource().getDelegatedFrozenBalanceForEnergy()); - Assert.assertEquals(contractAccount_before.getBalance(), - contractAccount_after.getBalance()); - - - TransactionInfo info = PublicMethed.getTransactionInfoById(txid, blockingStubFull).get(); - freezeEnergyUseage = info.getReceipt().getEnergyUsageTotal(); - - Assert.assertEquals(code.FAILED,info.getResult()); - Assert.assertEquals(contractResult.REVERT,info.getReceipt().getResult()); - - } - - @Test(enabled = true, description = "contract transfer all balance, then freeze") - void FreezeContract003() { - - AccountResourceMessage account002_before = PublicMethed - .getAccountResource(testAddress002,blockingStubFull); - Account contractAccount_before = PublicMethed.queryAccount(contractAddress,blockingStubFull); - - // freeze(address payable receiver, uint amount, uint res) - Long freezeCount = contractAccount_before.getBalance(); - String methedStr = "freezeAndSend(address,uint256,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testAddress002) + "\"," + freezeCount + "," + "1"; - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage account002_after = PublicMethed - .getAccountResource(testAddress002,blockingStubFull); - Account contractAccount_after = PublicMethed.queryAccount(contractAddress, blockingStubFull); - - logger.info("account002_before.getEnergyLimit : " + account002_before.getEnergyLimit()); - logger.info("account002_after.getEnergyLimit : " + account002_after.getEnergyLimit()); - Assert.assertEquals(account002_before.getEnergyLimit(), account002_after.getEnergyLimit()); - Assert.assertEquals(contractAccount_before.getAccountResource() - .getDelegatedFrozenBalanceForEnergy(), - contractAccount_after.getAccountResource().getDelegatedFrozenBalanceForEnergy()); - Assert.assertEquals(contractAccount_before.getBalance(), - contractAccount_after.getBalance()); - - TransactionInfo info = PublicMethed.getTransactionInfoById(txid, blockingStubFull).get(); - freezeEnergyUseage = info.getReceipt().getEnergyUsageTotal(); - - Assert.assertEquals(code.FAILED,info.getResult()); - Assert.assertEquals(contractResult.REVERT,info.getReceipt().getResult()); - } - - @Test(enabled = true, description = "contract freeze to ger Net") - void FreezeContract004() { - - AccountResourceMessage account002_before = PublicMethed - .getAccountResource(testAddress002,blockingStubFull); - Account contractAccount_before = PublicMethed.queryAccount(contractAddress,blockingStubFull); - - // freeze(address payable receiver, uint amount, uint res) - Long freezeCount = 1_000000L; - String methedStr = "freeze(address,uint256,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testAddress002) + "\"," + freezeCount + "," + "0"; - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage account002_after = PublicMethed - .getAccountResource(testAddress002,blockingStubFull); - Account contractAccount_after = PublicMethed.queryAccount(contractAddress, blockingStubFull); - - logger.info("account002_before.getNetLimit : " + account002_before.getNetLimit()); - logger.info("account002_after.getNetLimit : " + account002_after.getNetLimit()); - Assert.assertTrue(account002_before.getNetLimit() < account002_after.getNetLimit()); - Assert.assertEquals(contractAccount_before - .getDelegatedFrozenBalanceForBandwidth() + freezeCount, - contractAccount_after.getDelegatedFrozenBalanceForBandwidth()); - Assert.assertEquals(contractAccount_before.getBalance() - freezeCount, - contractAccount_after.getBalance()); - } - - @Test(enabled = true, description = "contract freeze to ger Net") - void FreezeContract005() { - // freeze(address payable receiver, uint amount, uint res) - Long freezeCount = 1000000L; - String methedStr = "freeze(address,uint256,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testAddress001) + "\"," + freezeCount + "," + "1"; - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // freeze(address payable receiver, uint amount, uint res) - String ExpireTimeMethedStr = "getExpireTime(address,uint256)"; - String ExpireTimeArgsStr = "\"" + Base58.encode58Check(testAddress001) + "\"" + ",1"; - TransactionExtention extention = PublicMethed - .triggerConstantContractForExtention(contractAddress,ExpireTimeMethedStr,ExpireTimeArgsStr, - false,0,maxFeeLimit,"#",0, testAddress001,testKey001,blockingStubFull); - Long ExpireTime1 = ByteArray.toLong(extention.getConstantResult(0).toByteArray()); - logger.info("ExpireTime1: " + ExpireTime1); - - txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - TransactionInfo info = PublicMethed.getTransactionInfoById(txid, blockingStubFull).get(); - freezeEnergyUseage = info.getReceipt().getEnergyUsageTotal(); - Assert.assertEquals(code.SUCESS,info.getResult()); - Assert.assertEquals(contractResult.SUCCESS,info.getReceipt().getResult()); - - extention = PublicMethed - .triggerConstantContractForExtention(contractAddress,ExpireTimeMethedStr,ExpireTimeArgsStr, - false,0,maxFeeLimit,"#",0, testAddress001,testKey001,blockingStubFull); - Long ExpireTime2 = ByteArray.toLong(extention.getConstantResult(0).toByteArray()); - logger.info("ExpireTime2: " + ExpireTime2); - - // Test - Assert.assertEquals((ExpireTime2 + 3) * 1000, info.getBlockTimeStamp()); - // Online - // Assert.assertEquals((ExpireTime2.longValue() + 10800) * 1000, info.getBlockTimeStamp()); - - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeSuicideTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeSuicideTest001.java deleted file mode 100644 index 865aea5fe57..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmFreeze/FreezeSuicideTest001.java +++ /dev/null @@ -1,290 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tvmFreeze; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.Protocol.TransactionInfo.code; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class FreezeSuicideTest001 { - - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private byte[] contractAddress; - - - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] testAddress002 = ecKey2.getAddress(); - String testKey002 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private long freezeEnergyUseage; - private long callValue; - private byte[] create2Address; - private final Long freezeCount = 1000_000000L; - - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - PublicMethed.printAddress(testKey001); - PublicMethed.printAddress(testKey002); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - Assert.assertTrue(PublicMethed.sendcoin(testAddress001,2000_000000L, - testFoundationAddress,testFoundationKey,blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(testAddress002,200_0000_000000L, - testFoundationAddress,testFoundationKey,blockingStubFull)); - - String filePath = "src/test/resources/soliditycode/freezeContract001.sol"; - String contractName = "TestFreeze"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - callValue = 50000_000000L; - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, callValue, - 100, null, testFoundationKey, - testFoundationAddress, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(testAddress002, - 100_0000_000000L,0,0,testKey002,blockingStubFull)); - } - - @Test(enabled = true, description = "when delegate freeze, cannot suicide") - public void FreezeSuicideTest001() { - - Account contractAccount_before = PublicMethed.queryAccount(contractAddress,blockingStubFull); - - // freeze(address payable receiver, uint amount, uint res) - String methedStr = "freeze(address,uint256,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testAddress002) + "\"," + freezeCount + "," + "1"; - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account contractAccount_after = PublicMethed.queryAccount(contractAddress, blockingStubFull); - - Assert.assertEquals(contractAccount_before.getAccountResource() - .getDelegatedFrozenBalanceForEnergy() + freezeCount, - contractAccount_after.getAccountResource().getDelegatedFrozenBalanceForEnergy()); - Assert.assertEquals(contractAccount_before.getBalance() - freezeCount, - contractAccount_after.getBalance()); - - methedStr = "destroy(address)"; - argsStr = "\"" + Base58.encode58Check(testAddress002) + "\""; - txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - TransactionInfo info = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get(); - Assert.assertEquals(code.FAILED,info.getResult()); - Assert.assertEquals(contractResult.REVERT,info.getReceipt().getResult()); - - - methedStr = "unfreeze(address,uint256)"; - argsStr = "\"" + Base58.encode58Check(testAddress002) + "\"," + "1"; - PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - } - - @Test(enabled = true, description = "when delegate freeze to self, then suicide") - public void FreezeSuicideTest002() { - - Account contractAccount_before = PublicMethed.queryAccount(contractAddress,blockingStubFull); - AccountResourceMessage freezeAccount_before = PublicMethed - .getAccountResource(testAddress002,blockingStubFull); - - // freeze(address payable receiver, uint amount, uint res) - String methedStr = "freeze(address,uint256,uint256)"; - String argsStr = "\"" + Base58.encode58Check(contractAddress) + "\"," + freezeCount + "," + "0"; - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - AccountResourceMessage freezeAccount_after = PublicMethed - .getAccountResource(testAddress002,blockingStubFull); - Account contractAccount_after = PublicMethed.queryAccount(contractAddress, blockingStubFull); - - Assert.assertEquals(freezeCount.longValue(), - contractAccount_after.getFrozen(0).getFrozenBalance()); - Assert.assertEquals(contractAccount_before.getBalance() - freezeCount, - contractAccount_after.getBalance()); - - logger.info("freezeAccount_before.getNetLimit : " + freezeAccount_before.getNetLimit()); - logger.info("freezeAccount_after.getNetLimit : " + freezeAccount_after.getNetLimit()); - Assert.assertTrue(freezeAccount_after.getNetLimit() < freezeAccount_before.getNetLimit()); - - - Long beforeBalance = PublicMethed.queryAccount(testAddress002,blockingStubFull).getBalance(); - methedStr = "destroy(address)"; - argsStr = "\"" + Base58.encode58Check(testAddress002) + "\""; - txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - TransactionInfo info = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get(); - Assert.assertEquals(code.SUCESS,info.getResult()); - Assert.assertEquals(contractResult.SUCCESS,info.getReceipt().getResult()); - - freezeAccount_after = PublicMethed - .getAccountResource(testAddress002,blockingStubFull); - Assert.assertEquals(freezeAccount_before.getNetLimit(), - freezeAccount_after.getNetLimit()); - - Long AfterBalance = PublicMethed.queryAccount(testAddress002,blockingStubFull).getBalance(); - Assert.assertEquals(beforeBalance + callValue, AfterBalance.longValue()); - - - } - - @Test(enabled = true, description = "suicide、freeze、unfreeze、getExpireTime " - + "with suicided create2 address") - public void FreezeSuicideTest003() { - - String filePath = "src/test/resources/soliditycode/freezeContract001.sol"; - String contractName = "TestFreeze"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String bytecode = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - callValue = 10000_000000L; - contractAddress = PublicMethed - .deployContract(contractName, abi, bytecode, "", maxFeeLimit, callValue, - 100, null, testFoundationKey, - testFoundationAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // triggerconstant create2 function, and get create2 Address - String create2ArgsStr = "1"; - String create2MethedStr = "deploy(uint256)"; - TransactionExtention exten = PublicMethed.triggerConstantContractForExtention( - contractAddress, create2MethedStr, create2ArgsStr, false, 0, maxFeeLimit, - "#", 0, testAddress001, testKey001, blockingStubFull); - - String addressHex = - "41" + ByteArray.toHexString(exten.getConstantResult(0).toByteArray()) - .substring(24); - logger.info("address_hex: " + addressHex); - create2Address = ByteArray.fromHexString(addressHex); - logger.info("create2Address: " + Base58.encode58Check(create2Address)); - - // freeze to create2 Address, active create2 address - String methedStr = "freeze(address,uint256,uint256)"; - String argsStr = "\"" + Base58.encode58Check(create2Address) + "\"," + freezeCount + "," + "1"; - logger.info("argsStr: " + argsStr); - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - TransactionInfo info = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get(); - Assert.assertEquals(code.SUCESS,info.getResult()); - Assert.assertEquals(contractResult.SUCCESS,info.getReceipt().getResult()); - - // create2 contract Address, turn create2 address to contract type - txid = PublicMethed.triggerContract(contractAddress,create2MethedStr, - create2ArgsStr,false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - info = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get(); - Assert.assertEquals(code.SUCESS,info.getResult()); - Assert.assertEquals(contractResult.SUCCESS,info.getReceipt().getResult()); - - - // create2 contract suicide - methedStr = "destroy(address)"; - argsStr = "\"" + Base58.encode58Check(testAddress002) + "\""; - txid = PublicMethed.triggerContract(create2Address,methedStr,argsStr,false,0, - maxFeeLimit,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - info = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get(); - Assert.assertEquals(code.SUCESS,info.getResult()); - Assert.assertEquals(contractResult.SUCCESS,info.getReceipt().getResult()); - - // get create2 account ExpireTime - methedStr = "getExpireTime(address,uint256)"; - argsStr = "\"" + Base58.encode58Check(create2Address) + "\"" + ",1"; - TransactionExtention extention = PublicMethed - .triggerConstantContractForExtention(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,"#",0, testAddress001,testKey001,blockingStubFull); - Long ExpireTime = ByteArray.toLong(extention.getConstantResult(0).toByteArray()); - logger.info("ExpireTime: " + ExpireTime); - Assert.assertTrue(ExpireTime > 0); - - // suicide FreezeTest contract, and should be failed - methedStr = "destroy(address)"; - argsStr = "\"" + Base58.encode58Check(testAddress002) + "\""; - txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr,false,0, - maxFeeLimit,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - info = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get(); - Assert.assertEquals(code.FAILED,info.getResult()); - Assert.assertEquals(contractResult.REVERT,info.getReceipt().getResult()); - - Account contract_before = PublicMethed.queryAccount(contractAddress,blockingStubFull); - - // unfreeze suicide create2 account - methedStr = "unfreeze(address,uint256)"; - argsStr = "\"" + Base58.encode58Check(create2Address) + "\"," + "1"; - txid = PublicMethed.triggerContract(contractAddress,methedStr,argsStr, - false,0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - info = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get(); - Assert.assertEquals(code.SUCESS,info.getResult()); - Assert.assertEquals(contractResult.SUCCESS,info.getReceipt().getResult()); - - Account contract_after = PublicMethed.queryAccount(contractAddress,blockingStubFull); - Assert.assertEquals(contract_before.getBalance() + freezeCount, contract_after.getBalance()); - Assert.assertEquals(contract_after.getAccountResource().getDelegatedFrozenBalanceForEnergy(), - contract_before.getAccountResource().getDelegatedFrozenBalanceForEnergy() - freezeCount); - - - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue001.java deleted file mode 100644 index 4de382f52af..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue001.java +++ /dev/null @@ -1,282 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tvmassetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TvmAssetIssue001 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = 10000000000L; - private static String name = "testAssetIssue_" + Long.toString(now); - private static String abbr = "testAsset_" + Long.toString(now); - private static String description = "desc_" + Long.toString(now); - private static String url = "url_" + Long.toString(now); - private static String assetIssueId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] dev002Address = ecKey2.getAddress(); - private String dev002Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = false) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(dev002Key); - } - - @Test(enabled = false, description = "tokenIssue normal") - public void tokenIssueNormal() { - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 3100_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "./src/test/resources/soliditycode/tvmAssetIssue001.sol"; - String contractName = "tvmAssetIssue001"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - long callvalue = 1050000000L; - - final String deployTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callvalue, 0, 10000, "0", 0L, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - if (deployTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(contractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - long contractAddressBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(callvalue, contractAddressBalance); - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(dev001Address, blockingStubFull); - Account info = PublicMethed.queryAccount(dev001Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - /*String param = "0000000000000000000000000000000000007465737441737365744973737565" - + "0000000000000000000074657374417373657431353938333439363637393631" - + "0000000000000000000000000000000000000000000000000000000000989680" - + "0000000000000000000000000000000000000000000000000000000000000001";*/ - String tokenName = PublicMethed.stringToHexString(name); - String tokenAbbr = PublicMethed.stringToHexString(abbr); - String param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 6; - logger.info("param: " + param); - String methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - String txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - long returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - logger.info("returnAssetId: " + returnAssetId); - Assert.assertEquals(returnAssetId, Long.parseLong(assetIssueId)); - logger.info("getAssetV2Map(): " + PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map()); - long assetIssueValue = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - Assert.assertEquals(totalSupply, assetIssueValue); - AssetIssueContract assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert.assertEquals(totalSupply, assetIssueById.getTotalSupply()); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(dev001Address, blockingStubFull); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(dev001Address, blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - long contractAddressBalance2 = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(contractAddressBalance - 1024000000L, contractAddressBalance2); - - param = "\"" + Base58.encode58Check(dev002Address) + "\"," + 100 + ",\"" + assetIssueId + "\""; - String methodTransferToken = "transferToken(address,uint256,trcToken)"; - txid = PublicMethed.triggerContract(contractAddress, methodTransferToken, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - long assetIssueValueAfter = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - long dev002AssetValue = PublicMethed - .getAssetIssueValue(dev002Address, ByteString.copyFrom(assetIssueId.getBytes()), - blockingStubFull); - Assert.assertEquals(assetIssueValue - 100L, assetIssueValueAfter); - Assert.assertEquals(100L, dev002AssetValue); - } - - @Test(enabled = false, description = "updateAsset normal") - public void updateAssetNormal() { - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(dev001Address, blockingStubFull); - Account info = PublicMethed.queryAccount(dev001Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String param = "\"" + assetIssueId + "\",\"" + url + "\",\"" + description + "\""; - logger.info("param: " + param); - String methodUpdateAsset = "updateAsset(trcToken,string,string)"; - String txid = PublicMethed.triggerContract(contractAddress, methodUpdateAsset, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - long returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(1, returnAssetId); - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - AssetIssueContract assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert - .assertEquals(description, ByteArray.toStr(assetIssueById.getDescription().toByteArray())); - Assert.assertEquals(url, ByteArray.toStr(assetIssueById.getUrl().toByteArray())); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(dev001Address, blockingStubFull); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(dev001Address, blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue002.java deleted file mode 100644 index 5997bd84075..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue002.java +++ /dev/null @@ -1,744 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tvmassetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TvmAssetIssue002 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = 10000000000L; - private static String name = "testAssetIssue_" + Long.toString(now); - private static String abbr = "testAsset_" + Long.toString(now); - private static String assetIssueId = null; - long contractAddressBalance; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] dev002Address = ecKey2.getAddress(); - private String dev002Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = false) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(dev002Key); - } - - @Test(enabled = false, description = "tokenIssue illegal parameter verification") - public void tokenIssue001IllegalParameterVerification() { - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 3100_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "./src/test/resources/soliditycode/tvmAssetIssue001.sol"; - String contractName = "tvmAssetIssue001"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - long callvalue = 2050000000L; - - final String deployTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callvalue, 0, 10000, "0", 0L, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - if (deployTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(contractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - long contractAddressBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(callvalue, contractAddressBalance); - - /*String param = "0000000000000000000000000000000000007465737441737365744973737565" - + "0000000000000000000074657374417373657431353938333439363637393631" - + "0000000000000000000000000000000000000000000000000000000000989680" - + "0000000000000000000000000000000000000000000000000000000000000001";*/ - // assetName is trx - String tokenName = PublicMethed.stringToHexString("trx"); - String tokenAbbr = PublicMethed.stringToHexString(abbr); - String param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 6; - logger.info("param: " + param); - String methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - String txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - long returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - Map assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map(); - Assert.assertEquals(0, assetV2Map.size()); - - // assetName.length > 32 compile fail - /*tokenName = PublicMethed.stringToHexString("testAssetIssue_testAssetIssue_tes"); - tokenAbbr = PublicMethed.stringToHexString(abbr); - param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 6; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, true, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetV2Map(); - Assert.assertEquals(0, assetV2Map.size());*/ - - // assetName is "" - tokenName = PublicMethed.stringToHexString(""); - tokenAbbr = PublicMethed.stringToHexString(abbr); - param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 6; - logger.info("param: " + param); - methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map(); - Assert.assertEquals(0, assetV2Map.size()); - - // assetName is chinese - tokenName = PublicMethed.stringToHexString("名字"); - tokenAbbr = PublicMethed.stringToHexString(abbr); - param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 6; - logger.info("param: " + param); - methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map(); - Assert.assertEquals(0, assetV2Map.size()); - - // assetAbbr is null - tokenName = PublicMethed.stringToHexString(name); - tokenAbbr = PublicMethed.stringToHexString(""); - param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 6; - logger.info("param: " + param); - methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map(); - Assert.assertEquals(0, assetV2Map.size()); - - // assetAbbr is chinese - tokenName = PublicMethed.stringToHexString(name); - tokenAbbr = PublicMethed.stringToHexString("简称"); - param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 6; - logger.info("param: " + param); - methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map(); - Assert.assertEquals(0, assetV2Map.size()); - - // totalSupply is Long.MAX_VALUE+1 - param = "a8547918" - + "74657374417373657449737375655f3136303034333636393333333600000000" - + "7472780000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000008000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000006"; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, true, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map(); - Assert.assertEquals(0, assetV2Map.size()); - - // totalSupply is -1 - tokenName = PublicMethed.stringToHexString(name); - tokenAbbr = PublicMethed.stringToHexString("trx"); - param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + -1 + "," + 6; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - logger.info("totalSupply is -1"); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("SUCCESS", infoById.get().getReceipt().getResult().toString()); - Assert.assertTrue(infoById.get().getFee() < 1000000000); - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map(); - Assert.assertEquals(0, assetV2Map.size()); - - // totalSupply is 0 - tokenName = PublicMethed.stringToHexString(name); - tokenAbbr = PublicMethed.stringToHexString("trx"); - param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + 0 + "," + 6; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - logger.info("totalSupply is 0"); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("SUCCESS", infoById.get().getReceipt().getResult().toString()); - Assert.assertTrue(infoById.get().getFee() < 1000000000); - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map(); - Assert.assertEquals(0, assetV2Map.size()); - - // precision is 7 - tokenName = PublicMethed.stringToHexString(name); - tokenAbbr = PublicMethed.stringToHexString(abbr); - param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 7; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map(); - Assert.assertEquals(0, assetV2Map.size()); - - // precision is -1 - tokenName = PublicMethed.stringToHexString(name); - tokenAbbr = PublicMethed.stringToHexString(abbr); - param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + -1; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map(); - Assert.assertEquals(0, assetV2Map.size()); - - // assetAbbr is trx will success - tokenName = PublicMethed.stringToHexString(name); - tokenAbbr = PublicMethed.stringToHexString("trx"); - param = "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 6; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(returnAssetId, Long.parseLong(assetIssueId)); - AssetIssueContract assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals("trx", ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map(); - Assert.assertEquals(1, assetV2Map.size()); - - // created multiple times will fail - txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map(); - Assert.assertEquals(1, assetV2Map.size()); - String assetIssueId1 = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetIssuedID() - .toStringUtf8(); - Assert.assertEquals(assetIssueId, assetIssueId1); - } - - @Test(enabled = false, description = "tokenIssue trx balance insufficient") - public void tokenIssue002TrxBalanceInsufficient() { - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 3100_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "./src/test/resources/soliditycode/tvmAssetIssue001.sol"; - String contractName = "tvmAssetIssue001"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - long callvalue = 1023999999L; - - final String deployTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callvalue, 0, 10000, "0", 0L, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - if (deployTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(contractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - long contractAddressBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(callvalue, contractAddressBalance); - - // trx balance insufficient - String tokenName = PublicMethed.stringToHexString(name); - String tokenAbbr = PublicMethed.stringToHexString(abbr); - String param = "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 6; - logger.info("param: " + param); - String methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - String txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - long returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - Map assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map(); - Assert.assertEquals(0, assetV2Map.size()); - } - - @Test(enabled = false, description = "tokenIssue called multiple times in one contract") - public void tokenIssue003CalledMultipleTimesInOneContract() { - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 3100_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "./src/test/resources/soliditycode/tvmAssetIssue002.sol"; - String contractName = "tvmAssetIssue002"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - long callvalue = 1024000000L; - - final String deployTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callvalue, 0, 10000, "0", 0L, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - if (deployTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(contractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - long contractAddressBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(callvalue, contractAddressBalance); - - String tokenName = PublicMethed.stringToHexString(name); - String tokenAbbr = PublicMethed.stringToHexString(abbr); - String param = "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 5; - logger.info("param: " + param); - String methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - String txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - long returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - - Map assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map(); - Assert.assertEquals(1, assetV2Map.size()); - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - long assetIssueValue = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - Assert.assertEquals(totalSupply, assetIssueValue); - AssetIssueContract assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert.assertEquals(totalSupply, assetIssueById.getTotalSupply()); - Assert.assertEquals(5, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - } - - @Test(enabled = false, description = "tokenIssue revert") - public void tokenIssue004Revert() { - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 3100_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "./src/test/resources/soliditycode/tvmAssetIssue003.sol"; - String contractName = "tvmAssetIssue003"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - long callvalue = 2500000000L; - - final String deployTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callvalue, 0, 10000, "0", 0L, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - if (deployTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(contractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - long contractAddressBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(callvalue, contractAddressBalance); - - String tokenName = PublicMethed.stringToHexString(name); - String tokenAbbr = PublicMethed.stringToHexString(abbr); - String param = "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 4; - logger.info("param: " + param); - String methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - String txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - Map assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map(); - Assert.assertEquals(1, assetV2Map.size()); - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - long returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(returnAssetId, Long.parseLong(assetIssueId)); - long assetIssueValue = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - Assert.assertEquals(totalSupply, assetIssueValue); - AssetIssueContract assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert.assertEquals(totalSupply, assetIssueById.getTotalSupply()); - Assert.assertEquals(4, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - - String tokenName1 = PublicMethed.stringToHexString(name + "_rev"); - String tokenAbbr1 = PublicMethed.stringToHexString(abbr + "_rev"); - param = - "\"" + tokenName1 + "\",\"" + tokenAbbr1 + "\",\"" + 1000000 + "\",\"" + 3 + "\",\"" - + Base58.encode58Check(dev002Address) + "\""; - logger.info("param: " + param); - String methodTokenIssueRevert = "tokenIssueAndTransfer(bytes32,bytes32,uint64,uint8,address)"; - txid = PublicMethed.triggerContract(contractAddress, methodTokenIssueRevert, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map(); - Assert.assertEquals(1, assetV2Map.size()); - String assetIssueId1 = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId1: " + assetIssueId1); - Assert.assertEquals(assetIssueId, assetIssueId1); - assetIssueValue = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - Assert.assertEquals(totalSupply, assetIssueValue); - assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert.assertEquals(totalSupply, assetIssueById.getTotalSupply()); - Assert.assertEquals(4, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - - long balance = PublicMethed.queryAccount(dev002Address, blockingStubFull).getBalance(); - Assert.assertEquals(200000000L, balance); - } - - @Test(enabled = false, description = "tokenIssue call another contract in one contract") - public void tokenIssue005CallAnotherInOneContract() { - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 3100_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "./src/test/resources/soliditycode/tvmAssetIssue004.sol"; - String contractName = "tvmAssetIssue004"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - long callvalue = 1030000000L; - String deployTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callvalue, 0, 10000, "0", 0L, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - if (deployTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(contractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - callvalue = 1024000000L; - String txid = PublicMethed.triggerContract(contractAddress, "getContractAddress()", "#", false, - callvalue, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - String addressHex = - "41" + ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()) - .substring(24); - logger.info("address_hex: " + addressHex); - byte[] contractAddressA = ByteArray.fromHexString(addressHex); - logger.info("contractAddressA: " + Base58.encode58Check(contractAddressA)); - contractAddressBalance = PublicMethed.queryAccount(contractAddressA, blockingStubFull) - .getBalance(); - Assert.assertEquals(callvalue, contractAddressBalance); - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(dev001Address, blockingStubFull); - Account info = PublicMethed.queryAccount(dev001Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String tokenName = PublicMethed.stringToHexString(name); - String tokenAbbr = PublicMethed.stringToHexString(abbr); - String param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 2; - logger.info("param: " + param); - String methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - assetIssueId = PublicMethed.queryAccount(contractAddressA, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - long returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - logger.info("returnAssetId: " + returnAssetId); - Assert.assertEquals(returnAssetId, Long.parseLong(assetIssueId)); - Map assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map(); - Assert.assertEquals(0, assetV2Map.size()); - long assetIssueValue = PublicMethed.queryAccount(contractAddressA, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - Assert.assertEquals(totalSupply, assetIssueValue); - AssetIssueContract assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert.assertEquals(totalSupply, assetIssueById.getTotalSupply()); - Assert.assertEquals(2, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddressA), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(dev001Address, blockingStubFull); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(dev001Address, blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - long contractAddressBalance2 = PublicMethed.queryAccount(contractAddressA, blockingStubFull) - .getBalance(); - Assert.assertEquals(contractAddressBalance - 1024000000L, contractAddressBalance2); - - param = "\"" + Base58.encode58Check(dev002Address) + "\"," + 100 + ",\"" + assetIssueId + "\""; - String methodTransferToken = "transferToken(address,uint256,trcToken)"; - txid = PublicMethed.triggerContract(contractAddressA, methodTransferToken, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - long assetIssueValueAfter = PublicMethed.queryAccount(contractAddressA, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - long dev002AssetValue = PublicMethed - .getAssetIssueValue(dev002Address, ByteString.copyFrom(assetIssueId.getBytes()), - blockingStubFull); - Assert.assertEquals(assetIssueValue - 100L, assetIssueValueAfter); - Assert.assertEquals(100L, dev002AssetValue); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue003.java deleted file mode 100644 index 88885f1fd15..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue003.java +++ /dev/null @@ -1,864 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tvmassetissue; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TvmAssetIssue003 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = 10000000000L; - private static String name = "testAssetIssue_" + Long.toString(now); - private static String abbr = "testAsset_" + Long.toString(now); - private static String description = "desc_" + Long.toString(now); - private static String url = "url_" + Long.toString(now); - private static String assetIssueId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] dev002Address = ecKey2.getAddress(); - private String dev002Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = false) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(dev002Key); - } - - @Test(enabled = false, description = "updateAsset illegal parameter verification") - public void updateAsset001IllegalParameterVerification() { - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 1100_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "./src/test/resources/soliditycode/tvmAssetIssue001.sol"; - String contractName = "tvmAssetIssue001"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - long callvalue = 1024000000L; - - final String deployTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callvalue, 0, 10000, "0", 0L, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - if (deployTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(contractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - long contractAddressBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(callvalue, contractAddressBalance); - - String tokenName = PublicMethed.stringToHexString(name); - String tokenAbbr = PublicMethed.stringToHexString(abbr); - String param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 6; - logger.info("param: " + param); - String methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - String txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - long returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - logger.info("returnAssetId: " + returnAssetId); - Assert.assertEquals(returnAssetId, Long.parseLong(assetIssueId)); - long assetIssueValue = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - Assert.assertEquals(totalSupply, assetIssueValue); - AssetIssueContract assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert.assertEquals(totalSupply, assetIssueById.getTotalSupply()); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - long contractAddressBalance2 = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(contractAddressBalance - 1024000000L, contractAddressBalance2); - - // desc and url is trx, will success - url = "trx"; - description = "trx"; - param = "\"" + assetIssueId + "\",\"" + url + "\",\"" + description + "\""; - logger.info("param: " + param); - String methodUpdateAsset = "updateAsset(trcToken,string,string)"; - txid = PublicMethed.triggerContract(contractAddress, methodUpdateAsset, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(1, returnAssetId); - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert - .assertEquals(description, ByteArray.toStr(assetIssueById.getDescription().toByteArray())); - Assert.assertEquals(url, ByteArray.toStr(assetIssueById.getUrl().toByteArray())); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - - // desc.length is 201, will fail - String descriptions = - "desc_1234567890desc_1234567890desc_1234567890desc_1234567890desc_1234567890" - + "desc_1234567890desc_1234567890desc_1234567890desc_1234567890desc_1234567890desc" - + "_1234567890" - + "desc_1234567890desc_1234567890desc_1"; - param = "\"" + assetIssueId + "\",\"" + url + "\",\"" + descriptions + "\""; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(contractAddress, methodUpdateAsset, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert - .assertEquals(description, ByteArray.toStr(assetIssueById.getDescription().toByteArray())); - Assert.assertEquals(url, ByteArray.toStr(assetIssueById.getUrl().toByteArray())); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - - // desc.length is "", will success - param = "\"" + assetIssueId + "\",\"" + url + "\",\"\""; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(contractAddress, methodUpdateAsset, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(1, returnAssetId); - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert.assertEquals(0, assetIssueById.getDescription().size()); - Assert.assertEquals(url, ByteArray.toStr(assetIssueById.getUrl().toByteArray())); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - - // desc.length is chinese, will success - description = "token说明"; - param = "\"" + assetIssueId + "\",\"" + url + "\",\"" + description + "\""; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(contractAddress, methodUpdateAsset, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(1, returnAssetId); - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert - .assertEquals(description, ByteArray.toStr(assetIssueById.getDescription().toByteArray())); - Assert.assertEquals(url, ByteArray.toStr(assetIssueById.getUrl().toByteArray())); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - - // url.length is 257, will fail - String urls = - "url_12345678901url_12345678901url_12345678901url_12345678901url_12345678901url_12345678901" - + "url_12345678901url_12345678901url_12345678901url_12345678901url_12345678901url" - + "_12345678901" - + "url_12345678901url_12345678901url_12345678901url_12345678901url_12345678901ur"; - param = "\"" + assetIssueId + "\",\"" + urls + "\",\"" + description + "\""; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(contractAddress, methodUpdateAsset, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert - .assertEquals(description, ByteArray.toStr(assetIssueById.getDescription().toByteArray())); - Assert.assertEquals(url, ByteArray.toStr(assetIssueById.getUrl().toByteArray())); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - - // url.length is "", will fail - param = "\"" + assetIssueId + "\",\"\",\"" + description + "\""; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(contractAddress, methodUpdateAsset, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert - .assertEquals(description, ByteArray.toStr(assetIssueById.getDescription().toByteArray())); - Assert.assertEquals(url, ByteArray.toStr(assetIssueById.getUrl().toByteArray())); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - - // url.length is chinese, will success - url = "官网"; - param = "\"" + assetIssueId + "\",\"" + url + "\",\"" + description + "\""; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(contractAddress, methodUpdateAsset, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(1, returnAssetId); - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert - .assertEquals(description, ByteArray.toStr(assetIssueById.getDescription().toByteArray())); - Assert.assertEquals(url, ByteArray.toStr(assetIssueById.getUrl().toByteArray())); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - } - - @Test(enabled = false, description = "updateAsset called multiple times in one contract") - public void updateAsset002CalledMultipleTimesInOneContract() { - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 1100_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "./src/test/resources/soliditycode/tvmAssetIssue002.sol"; - String contractName = "tvmAssetIssue002"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - long callvalue = 1024000000L; - - final String deployTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callvalue, 0, 10000, "0", 0L, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - logger.info("infoById: " + infoById.get().getReceipt().getEnergyUsageTotal()); - if (deployTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(contractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - long contractAddressBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(callvalue, contractAddressBalance); - - String tokenName = PublicMethed.stringToHexString(name); - String tokenAbbr = PublicMethed.stringToHexString(abbr); - String param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 6; - logger.info("param: " + param); - String methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - String txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - long returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - long assetIssueValue = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - Assert.assertEquals(totalSupply, assetIssueValue); - AssetIssueContract assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert.assertEquals(totalSupply, assetIssueById.getTotalSupply()); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - long contractAddressBalance2 = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(contractAddressBalance - 1024000000L, contractAddressBalance2); - - // updateAsset - description = "desc1_" + Long.toString(now); - url = "url1_" + Long.toString(now); - String description2 = "desc2_" + Long.toString(now); - String url2 = "url2_" + Long.toString(now); - param = "\"" + assetIssueId + "\",\"" + url + "\",\"" + description + "\",\"" + url2 + "\",\"" - + description2 + "\""; - logger.info("param: " + param); - String methodUpdateAsset = "updateAsset(trcToken,string,string,string,string)"; - txid = PublicMethed.triggerContract(contractAddress, methodUpdateAsset, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(1, returnAssetId); - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert - .assertEquals(description2, ByteArray.toStr(assetIssueById.getDescription().toByteArray())); - Assert.assertEquals(url2, ByteArray.toStr(assetIssueById.getUrl().toByteArray())); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - } - - @Test(enabled = false, description = "updateAsset revert") - public void updateAsset003Revert() { - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 1500_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "./src/test/resources/soliditycode/tvmAssetIssue003.sol"; - String contractName = "tvmAssetIssue003"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - long callvalue = 1225000000L; - - final String deployTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callvalue, 0, 10000, "0", 0L, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - logger.info("infoById: " + infoById.get().getReceipt().getEnergyUsageTotal()); - if (deployTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(contractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - long contractAddressBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(callvalue, contractAddressBalance); - - String tokenName = PublicMethed.stringToHexString(name); - String tokenAbbr = PublicMethed.stringToHexString(abbr); - String param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 6; - logger.info("param: " + param); - String methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - String txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - long returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(returnAssetId, Long.parseLong(assetIssueId)); - long assetIssueValue = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - Assert.assertEquals(totalSupply, assetIssueValue); - AssetIssueContract assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert.assertEquals(totalSupply, assetIssueById.getTotalSupply()); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - long contractAddressBalance2 = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(contractAddressBalance - 1024000000L, contractAddressBalance2); - - // updateAsset - String description1 = - "desc_1234567890desc_1234567890desc_1234567890desc_1234567890desc_1234567890" - + "desc_1234567890desc_1234567890desc_1234567890desc_1234567890desc_1234567890desc" - + "_1234567890" - + "desc_1234567890desc_1234567890desc_1"; - String url1 = "url1_" + Long.toString(now); - param = "\"" + assetIssueId + "\",\"" + url1 + "\",\"" + description1 + "\",\"" + Base58 - .encode58Check(dev002Address) + "\""; - logger.info("param: " + param); - String methodUpdateAsset = "updateAssetAndTransfer(trcToken,string,string,address)"; - txid = PublicMethed.triggerContract(contractAddress, methodUpdateAsset, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnAssetId); - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - logger.info("assetIssueById: " + assetIssueById); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert.assertEquals(0, assetIssueById.getDescription().size()); - Assert.assertEquals(0, assetIssueById.getUrl().size()); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - - long balance = PublicMethed.queryAccount(dev002Address, blockingStubFull).getBalance(); - Assert.assertEquals(200000000L, balance); - } - - @Test(enabled = false, description = "updateAsset call another contract in one contract") - public void updateAsset004CallAnotherInOneContract() { - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 3100_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "./src/test/resources/soliditycode/tvmAssetIssue004.sol"; - String contractName = "tvmAssetIssue004"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - long callvalue = 1030000000L; - String deployTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callvalue, 0, 10000, "0", 0L, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - if (deployTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(contractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - callvalue = 1024000000L; - String txid = PublicMethed.triggerContract(contractAddress, "getContractAddress()", "#", false, - callvalue, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - String addressHex = - "41" + ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()) - .substring(24); - logger.info("address_hex: " + addressHex); - byte[] contractAddressA = ByteArray.fromHexString(addressHex); - logger.info("contractAddressA: " + Base58.encode58Check(contractAddressA)); - long contractAddressBalance = PublicMethed.queryAccount(contractAddressA, blockingStubFull) - .getBalance(); - Assert.assertEquals(callvalue, contractAddressBalance); - - AccountResourceMessage resourceInfo = PublicMethed - .getAccountResource(dev001Address, blockingStubFull); - Account info = PublicMethed.queryAccount(dev001Address, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = resourceInfo.getEnergyUsed(); - Long beforeNetUsed = resourceInfo.getNetUsed(); - Long beforeFreeNetUsed = resourceInfo.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String tokenName = PublicMethed.stringToHexString(name); - String tokenAbbr = PublicMethed.stringToHexString(abbr); - String param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 2; - logger.info("param: " + param); - String methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - assetIssueId = PublicMethed.queryAccount(contractAddressA, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - long returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - logger.info("returnAssetId: " + returnAssetId); - Assert.assertEquals(returnAssetId, Long.parseLong(assetIssueId)); - Map assetV2Map = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map(); - Assert.assertEquals(0, assetV2Map.size()); - long assetIssueValue = PublicMethed.queryAccount(contractAddressA, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - Assert.assertEquals(totalSupply, assetIssueValue); - AssetIssueContract assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert.assertEquals(totalSupply, assetIssueById.getTotalSupply()); - Assert.assertEquals(2, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddressA), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - - Long fee = infoById.get().getFee(); - Long netUsed = infoById.get().getReceipt().getNetUsage(); - Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); - Long netFee = infoById.get().getReceipt().getNetFee(); - long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("fee:" + fee); - logger.info("netUsed:" + netUsed); - logger.info("energyUsed:" + energyUsed); - logger.info("netFee:" + netFee); - logger.info("energyUsageTotal:" + energyUsageTotal); - Protocol.Account infoafter = PublicMethed.queryAccount(dev001Address, blockingStubFull); - GrpcAPI.AccountResourceMessage resourceInfoafter = PublicMethed - .getAccountResource(dev001Address, blockingStubFull); - Long afterBalance = infoafter.getBalance(); - Long afterEnergyUsed = resourceInfoafter.getEnergyUsed(); - Long afterNetUsed = resourceInfoafter.getNetUsed(); - Long afterFreeNetUsed = resourceInfoafter.getFreeNetUsed(); - logger.info("afterBalance:" + afterBalance); - logger.info("afterEnergyUsed:" + afterEnergyUsed); - logger.info("afterNetUsed:" + afterNetUsed); - logger.info("afterFreeNetUsed:" + afterFreeNetUsed); - Assert.assertTrue(afterBalance + fee == beforeBalance); - Assert.assertTrue(beforeEnergyUsed + energyUsed >= afterEnergyUsed); - Assert.assertTrue(beforeFreeNetUsed + netUsed >= afterFreeNetUsed); - Assert.assertTrue(beforeNetUsed + netUsed >= afterNetUsed); - long contractAddressBalance2 = PublicMethed.queryAccount(contractAddressA, blockingStubFull) - .getBalance(); - Assert.assertEquals(contractAddressBalance - 1024000000L, contractAddressBalance2); - - // updateAsset - param = "\"" + assetIssueId + "\",\"" + url + "\",\"" + description + "\""; - logger.info("param: " + param); - String methodUpdateAsset = "updateAsset(trcToken,string,string)"; - txid = PublicMethed.triggerContract(contractAddress, methodUpdateAsset, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(1, returnAssetId); - assetIssueId = PublicMethed.queryAccount(contractAddressA, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert - .assertEquals(description, ByteArray.toStr(assetIssueById.getDescription().toByteArray())); - Assert.assertEquals(url, ByteArray.toStr(assetIssueById.getUrl().toByteArray())); - Assert.assertEquals(2, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddressA), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - } - - @Test(enabled = false, description = "updateAsset verify token") - public void updateAsset005VerifyTokenId() { - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 1100_000_000L, fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed - .sendcoin(dev002Address, 50_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "./src/test/resources/soliditycode/tvmAssetIssue001.sol"; - String contractName = "tvmAssetIssue001"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - long callvalue = 1024000000L; - - final String deployTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callvalue, 0, 10000, "0", 0L, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - if (deployTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(contractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - long contractAddressBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(callvalue, contractAddressBalance); - - String tokenName = PublicMethed.stringToHexString(name); - String tokenAbbr = PublicMethed.stringToHexString(abbr); - String param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 6; - logger.info("param: " + param); - String methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - String txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - long returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - logger.info("returnAssetId: " + returnAssetId); - Assert.assertEquals(returnAssetId, Long.parseLong(assetIssueId)); - long assetIssueValue = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - Assert.assertEquals(totalSupply, assetIssueValue); - AssetIssueContract assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert.assertEquals(totalSupply, assetIssueById.getTotalSupply()); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - long contractAddressBalance2 = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(contractAddressBalance - 1024000000L, contractAddressBalance2); - - // token id does not exist, will update myself - url = "trx"; - description = "trx"; - param = "\"1119125\",\"" + url + "\",\"" + description + "\""; - logger.info("param: " + param); - String methodUpdateAsset = "updateAsset(trcToken,string,string)"; - txid = PublicMethed.triggerContract(contractAddress, methodUpdateAsset, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(1, returnAssetId); - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - logger.info("assetIssueById: " + assetIssueById); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert - .assertEquals(description, ByteArray.toStr(assetIssueById.getDescription().toByteArray())); - Assert.assertEquals(url, ByteArray.toStr(assetIssueById.getUrl().toByteArray())); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - - // not owner's asset, will update myself - AssetIssueContract assetIssueByIdBefore = PublicMethed - .getAssetIssueById("1000004", blockingStubFull); - final String nameBefore = ByteArray.toStr(assetIssueByIdBefore.getName().toByteArray()); - final String abbrBefore = ByteArray.toStr(assetIssueByIdBefore.getAbbr().toByteArray()); - final String descBefore = assetIssueByIdBefore.getDescription().size() == 0 ? "" - : ByteArray.toStr(assetIssueByIdBefore.getDescription().toByteArray()); - final String urlBefore = assetIssueByIdBefore.getUrl().size() == 0 ? "" - : ByteArray.toStr(assetIssueByIdBefore.getUrl().toByteArray()); - final long precisionBefore = assetIssueByIdBefore.getPrecision(); - url = url + "123456"; - description = description + "123"; - param = "\"" + url + "\",\"" + description + "\""; - logger.info("param: " + param); - txid = PublicMethed - .triggerContract(contractAddress, "updateOtherAccountAsset(string,string)", param, false, - 0, maxFeeLimit, dev002Address, dev002Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(1, returnAssetId); - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - logger.info("assetIssueById: " + assetIssueById); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert - .assertEquals(description, ByteArray.toStr(assetIssueById.getDescription().toByteArray())); - Assert.assertEquals(url, ByteArray.toStr(assetIssueById.getUrl().toByteArray())); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - - AssetIssueContract assetIssueByIdAfter = PublicMethed - .getAssetIssueById("1000004", blockingStubFull); - String descAfter = assetIssueByIdBefore.getDescription().size() == 0 ? "" - : ByteArray.toStr(assetIssueByIdAfter.getDescription().toByteArray()); - String urlAfter = assetIssueByIdBefore.getUrl().size() == 0 ? "" - : ByteArray.toStr(assetIssueByIdAfter.getUrl().toByteArray()); - Assert.assertEquals(nameBefore, ByteArray.toStr(assetIssueByIdAfter.getName().toByteArray())); - Assert.assertEquals(abbrBefore, ByteArray.toStr(assetIssueByIdAfter.getAbbr().toByteArray())); - Assert.assertEquals(descBefore, descAfter); - Assert.assertEquals(urlBefore, urlAfter); - Assert.assertEquals(precisionBefore, assetIssueByIdAfter.getPrecision()); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue004.java deleted file mode 100644 index 43f99347ee6..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue004.java +++ /dev/null @@ -1,205 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tvmassetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TvmAssetIssue004 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = 10000000000L; - private static String name = "testAssetIssue_" + Long.toString(now); - private static String abbr = "testAsset_" + Long.toString(now); - private static String description = "desc_" + Long.toString(now); - private static String url = "url_" + Long.toString(now); - private static String assetIssueId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] dev002Address = ecKey2.getAddress(); - private String dev002Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - private byte[] dev003Address = ecKey3.getAddress(); - private String dev003Key = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = false) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(dev002Key); - PublicMethed.printAddress(dev003Key); - } - - @Test(enabled = false, description = "tokenIssue and transfer to account") - public void tokenIssueAndTransferToAccount() { - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 3100_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String filePath = "./src/test/resources/soliditycode/tvmAssetIssue001.sol"; - String contractName = "tvmAssetIssue001"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - long callvalue = 1050000000L; - - final String deployTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callvalue, 0, 10000, "0", 0L, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - if (deployTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(contractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - long contractAddressBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(callvalue, contractAddressBalance); - - String tokenName = PublicMethed.stringToHexString(name); - String tokenAbbr = PublicMethed.stringToHexString(abbr); - String param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 6; - logger.info("param: " + param); - String methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - String txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - long returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - logger.info("returnAssetId: " + returnAssetId); - Assert.assertEquals(returnAssetId, Long.parseLong(assetIssueId)); - logger.info("getAssetV2Map(): " + PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map()); - long assetIssueValue = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - Assert.assertEquals(totalSupply, assetIssueValue); - AssetIssueContract assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert.assertEquals(totalSupply, assetIssueById.getTotalSupply()); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - - long contractAddressBalance2 = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(contractAddressBalance - 1024000000L, contractAddressBalance2); - - // transfer token to create exist account - Assert.assertTrue(PublicMethed - .sendcoin(dev003Address, 10_000_000L, dev001Address, dev001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - long dev001AddressBalanceBefore = PublicMethed.queryAccount(dev001Address, blockingStubFull) - .getBalance(); - logger.info("dev001AddressBalanceBefore: " + dev001AddressBalanceBefore); - param = "\"" + Base58.encode58Check(dev003Address) + "\"," + 100 + ",\"" + assetIssueId + "\""; - String methodTransferToken = "transferToken(address,uint256,trcToken)"; - txid = PublicMethed.triggerContract(contractAddress, methodTransferToken, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - long dev001AddressBalanceAfter = PublicMethed.queryAccount(dev001Address, blockingStubFull) - .getBalance(); - logger.info("dev001AddressBalanceAfter: " + dev001AddressBalanceAfter); - long assetIssueValueAfter = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - long dev003AssetValue = PublicMethed - .getAssetIssueValue(dev003Address, ByteString.copyFrom(assetIssueId.getBytes()), - blockingStubFull); - Assert.assertEquals(assetIssueValue - 100L, assetIssueValueAfter); - Assert.assertEquals(100L, dev003AssetValue); - - // transfer token to create new account - long dev001AddressBalanceBefore1 = PublicMethed.queryAccount(dev001Address, blockingStubFull) - .getBalance(); - logger.info("dev001AddressBalanceBefore1: " + dev001AddressBalanceBefore1); - param = "\"" + Base58.encode58Check(dev002Address) + "\"," + 100 + ",\"" + assetIssueId + "\""; - txid = PublicMethed.triggerContract(contractAddress, methodTransferToken, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 30000); - long dev001AddressBalanceAfter2 = PublicMethed.queryAccount(dev001Address, blockingStubFull) - .getBalance(); - logger.info("dev001AddressBalanceAfter2: " + dev001AddressBalanceAfter2); - long assetIssueValueAfter1 = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - long dev002AssetValue = PublicMethed - .getAssetIssueValue(dev002Address, ByteString.copyFrom(assetIssueId.getBytes()), - blockingStubFull); - Assert.assertEquals(assetIssueValueAfter - 100L, assetIssueValueAfter1); - Assert.assertEquals(100L, dev002AssetValue); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue005.java deleted file mode 100644 index 4eb87691228..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmassetissue/TvmAssetIssue005.java +++ /dev/null @@ -1,703 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tvmassetissue; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TvmAssetIssue005 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = 10000000000L; - private static String name = "testAssetIssue_" + Long.toString(now); - private static String abbr = "testAsset_" + Long.toString(now); - private static String description = "desc_" + Long.toString(now); - private static String url = "url_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] contractAddress = null; - private long contractAddressBalance; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] dev002Address = ecKey2.getAddress(); - private String dev002Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - private byte[] dev003Address = ecKey3.getAddress(); - private String dev003Key = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private ECKey ecKey4 = new ECKey(Utils.getRandom()); - private byte[] dev004Address = ecKey4.getAddress(); - private String dev004Key = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = false) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(dev002Key); - PublicMethed.printAddress(dev003Key); - PublicMethed.printAddress(dev004Key); - Assert.assertTrue(PublicMethed - .sendcoin(dev001Address, 7000_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = false, description = "tokenIssue and updateAsset with suicide to account") - public void tokenIssue001AndSuicideToAccount() { - String filePath = "./src/test/resources/soliditycode/tvmAssetIssue005.sol"; - String contractName = "tvmAssetIssue005"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - long callvalue = 1050000000L; - - // deploy - final String deployTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callvalue, 0, 10000, "0", 0L, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - if (deployTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(contractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - contractAddressBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(callvalue, contractAddressBalance); - - // tokenIssue - name = "testAssetIssu1_" + Long.toString(now); - abbr = "testAsse1_" + Long.toString(now); - String methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - String tokenName = PublicMethed.stringToHexString(name); - String tokenAbbr = PublicMethed.stringToHexString(abbr); - String param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 6; - logger.info("param: " + param); - String txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - String assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetIssuedID().toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - long returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - logger.info("returnAssetId: " + returnAssetId); - Assert.assertEquals(returnAssetId, Long.parseLong(assetIssueId)); - logger.info("getAssetV2Map(): " + PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map()); - long assetIssueValue = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - Assert.assertEquals(totalSupply, assetIssueValue); - AssetIssueContract assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert.assertEquals(totalSupply, assetIssueById.getTotalSupply()); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - AssetIssueContract assetIssueByName = PublicMethed.getAssetIssueByName(name, blockingStubFull); - AssetIssueContract assetIssueByAccount = PublicMethed - .getAssetIssueByAccount(contractAddress, blockingStubFull).get().getAssetIssue(0); - AssetIssueContract assetIssueListByName = PublicMethed - .getAssetIssueListByName(name, blockingStubFull) - .get().getAssetIssue(0); - Assert.assertEquals(assetIssueId, assetIssueByName.getId()); - Assert.assertEquals(name, ByteArray.toStr(assetIssueByAccount.getName().toByteArray())); - Assert.assertEquals(assetIssueId, assetIssueListByName.getId()); - long contractAddressBalance2 = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(contractAddressBalance - 1024000000L, contractAddressBalance2); - - // transferToken - String methodTransferToken = "transferToken(address,uint256,trcToken)"; - param = "\"" + Base58.encode58Check(dev002Address) + "\"," + 100 + ",\"" + assetIssueId + "\""; - txid = PublicMethed.triggerContract(contractAddress, methodTransferToken, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - long assetIssueValueAfter = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - long dev002AssetValue = PublicMethed - .getAssetIssueValue(dev002Address, ByteString.copyFrom(assetIssueId.getBytes()), - blockingStubFull); - Assert.assertEquals(assetIssueValue - 100L, assetIssueValueAfter); - Assert.assertEquals(100L, dev002AssetValue); - - // updateAsset - String methodUpdateAsset = "updateAsset(trcToken,string,string)"; - param = "\"" + assetIssueId + "\",\"" + url + "\",\"" + description + "\""; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(contractAddress, methodUpdateAsset, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - long returnId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(1, returnId); - assetIssueId = PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert - .assertEquals(description, ByteArray.toStr(assetIssueById.getDescription().toByteArray())); - Assert.assertEquals(url, ByteArray.toStr(assetIssueById.getUrl().toByteArray())); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - - // selfdestruct - String methodSuicide = "SelfdestructTest(address)"; - param = "\"" + Base58.encode58Check(dev003Address) + "\""; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(contractAddress, methodSuicide, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(0, - PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID().size()); - Assert.assertEquals(0, - PublicMethed.getAssetIssueByAccount(dev003Address, blockingStubFull).get() - .getAssetIssueCount()); - Assert.assertEquals(0, - PublicMethed.queryAccount(dev003Address, blockingStubFull).getAssetIssuedID().size()); - long contractAssetCountDev003 = PublicMethed - .getAssetIssueValue(dev003Address, ByteString.copyFrom(assetIssueId.getBytes()), - blockingStubFull); - Assert.assertEquals(assetIssueValueAfter, contractAssetCountDev003); - assetIssueValue = PublicMethed.queryAccount(dev003Address, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - Assert.assertEquals(assetIssueValueAfter, assetIssueValue); - assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert.assertEquals(totalSupply, assetIssueById.getTotalSupply()); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - assetIssueByName = PublicMethed.getAssetIssueByName(name, blockingStubFull); - assetIssueByAccount = PublicMethed - .getAssetIssueByAccount(contractAddress, blockingStubFull).get().getAssetIssue(0); - assetIssueListByName = PublicMethed - .getAssetIssueListByName(name, blockingStubFull) - .get().getAssetIssue(0); - Assert.assertEquals(assetIssueId, assetIssueByName.getId()); - Assert.assertEquals(name, ByteArray.toStr(assetIssueByAccount.getName().toByteArray())); - Assert.assertEquals(assetIssueId, assetIssueListByName.getId()); - dev002AssetValue = PublicMethed - .getAssetIssueValue(dev002Address, ByteString.copyFrom(assetIssueId.getBytes()), - blockingStubFull); - Assert.assertEquals(100L, dev002AssetValue); - - Assert.assertTrue(PublicMethed - .sendcoin(dev002Address, 100_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // transferAsset,success - Assert.assertTrue(PublicMethed.transferAsset(dev002Address, assetIssueId.getBytes(), 100L, - dev003Address, dev003Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - long assetIssueValueDev002 = PublicMethed - .getAssetIssueValue(dev002Address, ByteString.copyFrom(assetIssueId.getBytes()), - blockingStubFull); - long assetIssueValueDev003 = PublicMethed - .getAssetIssueValue(dev003Address, ByteString.copyFrom(assetIssueId.getBytes()), - blockingStubFull); - Assert.assertEquals(200L, assetIssueValueDev002); - Assert.assertEquals(assetIssueValue - 100L, assetIssueValueDev003); - - Assert.assertTrue(PublicMethed.transferAsset(dev004Address, assetIssueId.getBytes(), 102L, - dev002Address, dev002Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - long assetIssueValueDev002After = PublicMethed - .getAssetIssueValue(dev002Address, ByteString.copyFrom(assetIssueId.getBytes()), - blockingStubFull); - long assetIssueValueDev004 = PublicMethed - .getAssetIssueValue(dev004Address, ByteString.copyFrom(assetIssueId.getBytes()), - blockingStubFull); - Assert.assertEquals(102L, assetIssueValueDev004); - Assert.assertEquals(assetIssueValueDev002 - 102L, assetIssueValueDev002After); - - // updateAsset,will fail - Assert.assertFalse(PublicMethed - .updateAsset(dev003Address, "updateDesc1".getBytes(), "updateURL1".getBytes(), 1L, 2L, - dev003Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertFalse(PublicMethed - .updateAsset(contractAddress, "updateDesc2".getBytes(), "updateURL2".getBytes(), 3L, 4L, - dev003Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert - .assertEquals(description, ByteArray.toStr(assetIssueById.getDescription().toByteArray())); - Assert.assertEquals(url, ByteArray.toStr(assetIssueById.getUrl().toByteArray())); - Assert.assertEquals(Base58.encode58Check(contractAddress), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - } - - @Test(enabled = false, description = "tokenIssue and updateAsset with suicide to contract") - public void tokenIssue002AndSuicideToContract() { - String filePath = "./src/test/resources/soliditycode/tvmAssetIssue005.sol"; - String contractName = "tvmAssetIssue005"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - long callvalue = 1050000000L; - - // deploy - String deployTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callvalue, 0, 10000, "0", 0L, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - if (deployTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - byte[] contractAddress2 = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(contractAddress2, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - long contractAddressBalance2 = PublicMethed.queryAccount(contractAddress2, blockingStubFull) - .getBalance(); - Assert.assertEquals(callvalue, contractAddressBalance2); - - deployTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - callvalue, 0, 10000, "0", 0L, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - if (deployTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - contractAddress = infoById.get().getContractAddress().toByteArray(); - smartContract = PublicMethed - .getContract(contractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - contractAddressBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(callvalue, contractAddressBalance); - - // tokenIssue - name = "testAssetIssu2_" + Long.toString(now); - abbr = "testAsse2_" + Long.toString(now); - String methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - String tokenName = PublicMethed.stringToHexString(name); - String tokenAbbr = PublicMethed.stringToHexString(abbr); - String param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 6; - logger.info("param: " + param); - String txid = PublicMethed.triggerContract(contractAddress2, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - String assetIssueId = PublicMethed.queryAccount(contractAddress2, blockingStubFull) - .getAssetIssuedID() - .toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - long returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - logger.info("returnAssetId: " + returnAssetId); - Assert.assertEquals(returnAssetId, Long.parseLong(assetIssueId)); - logger.info("getAssetV2Map(): " + PublicMethed.queryAccount(contractAddress2, blockingStubFull) - .getAssetV2Map()); - long assetIssueValue = PublicMethed.queryAccount(contractAddress2, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - Assert.assertEquals(totalSupply, assetIssueValue); - AssetIssueContract assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert.assertEquals(totalSupply, assetIssueById.getTotalSupply()); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress2), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - AssetIssueContract assetIssueByName = PublicMethed.getAssetIssueByName(name, blockingStubFull); - AssetIssueContract assetIssueByAccount = PublicMethed - .getAssetIssueByAccount(contractAddress2, blockingStubFull).get().getAssetIssue(0); - AssetIssueContract assetIssueListByName = PublicMethed - .getAssetIssueListByName(name, blockingStubFull) - .get().getAssetIssue(0); - Assert.assertEquals(assetIssueId, assetIssueByName.getId()); - Assert.assertEquals(name, ByteArray.toStr(assetIssueByAccount.getName().toByteArray())); - Assert.assertEquals(assetIssueId, assetIssueListByName.getId()); - long contractAddressBalanceAfter2 = PublicMethed - .queryAccount(contractAddress2, blockingStubFull) - .getBalance(); - Assert.assertEquals(contractAddressBalance2 - 1024000000L, contractAddressBalanceAfter2); - - // transferToken - String methodTransferToken = "transferToken(address,uint256,trcToken)"; - param = "\"" + Base58.encode58Check(dev002Address) + "\"," + 100 + ",\"" + assetIssueId + "\""; - txid = PublicMethed.triggerContract(contractAddress2, methodTransferToken, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - long assetIssueValueAfter = PublicMethed.queryAccount(contractAddress2, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - long dev002AssetValue = PublicMethed - .getAssetIssueValue(dev002Address, ByteString.copyFrom(assetIssueId.getBytes()), - blockingStubFull); - Assert.assertEquals(assetIssueValue - 100L, assetIssueValueAfter); - Assert.assertEquals(100L, dev002AssetValue); - - param = - "\"" + Base58.encode58Check(contractAddress) + "\"," + 50 + ",\"" + assetIssueId + "\""; - txid = PublicMethed.triggerContract(contractAddress2, methodTransferToken, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - long assetIssueValueAfter2 = PublicMethed.queryAccount(contractAddress2, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - long contractAssetValue = PublicMethed - .getAssetIssueValue(contractAddress, ByteString.copyFrom(assetIssueId.getBytes()), - blockingStubFull); - Assert.assertEquals(assetIssueValueAfter - 50L, assetIssueValueAfter2); - Assert.assertEquals(50L, contractAssetValue); - - // selfdestruct - String methodSuicide = "SelfdestructTest(address)"; - param = "\"" + Base58.encode58Check(contractAddress) + "\""; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(contractAddress2, methodSuicide, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(0, - PublicMethed.queryAccount(contractAddress2, blockingStubFull).getAssetIssuedID().size()); - Assert.assertEquals(0, - PublicMethed.getAssetIssueByAccount(contractAddress, blockingStubFull).get() - .getAssetIssueCount()); - Assert.assertEquals(0, - PublicMethed.queryAccount(contractAddress, blockingStubFull).getAssetIssuedID().size()); - assetIssueValue = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - Assert.assertEquals(assetIssueValueAfter2 + 50L, assetIssueValue); - assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(assetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(assetIssueById.getAbbr().toByteArray())); - Assert.assertEquals(totalSupply, assetIssueById.getTotalSupply()); - Assert.assertEquals(6, assetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(contractAddress2), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - assetIssueByName = PublicMethed.getAssetIssueByName(name, blockingStubFull); - assetIssueByAccount = PublicMethed - .getAssetIssueByAccount(contractAddress2, blockingStubFull).get().getAssetIssue(0); - assetIssueListByName = PublicMethed - .getAssetIssueListByName(name, blockingStubFull) - .get().getAssetIssue(0); - Assert.assertEquals(assetIssueId, assetIssueByName.getId()); - Assert.assertEquals(name, ByteArray.toStr(assetIssueByAccount.getName().toByteArray())); - Assert.assertEquals(assetIssueId, assetIssueListByName.getId()); - - // transferToken,success - methodTransferToken = "transferToken(address,uint256,trcToken)"; - param = "\"" + Base58.encode58Check(dev002Address) + "\"," + 100 + ",\"" + assetIssueId + "\""; - txid = PublicMethed.triggerContract(contractAddress, methodTransferToken, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - assetIssueValueAfter = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getAssetV2Map().get(assetIssueId); - dev002AssetValue = PublicMethed - .getAssetIssueValue(dev002Address, ByteString.copyFrom(assetIssueId.getBytes()), - blockingStubFull); - Assert.assertEquals(assetIssueValue - 100L, assetIssueValueAfter); - Assert.assertEquals(200L, dev002AssetValue); - - Assert.assertTrue(PublicMethed.transferAsset(dev004Address, assetIssueId.getBytes(), 12L, - dev002Address, dev002Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - long assetIssueValueDev002After = PublicMethed - .getAssetIssueValue(dev002Address, ByteString.copyFrom(assetIssueId.getBytes()), - blockingStubFull); - long assetIssueValueDev004 = PublicMethed - .getAssetIssueValue(dev004Address, ByteString.copyFrom(assetIssueId.getBytes()), - blockingStubFull); - Assert.assertEquals(12L, assetIssueValueDev004); - Assert.assertEquals(dev002AssetValue - 12L, assetIssueValueDev002After); - - // updateAsset,will fail - String methodUpdateAsset = "updateAsset(trcToken,string,string)"; - param = "\"" + assetIssueId + "\",\"updateUrl\",\"updateDesc\""; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(contractAddress, methodUpdateAsset, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - long returnId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(0, returnId); - assetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(0, assetIssueById.getDescription().size()); - Assert.assertEquals(0, assetIssueById.getUrl().size()); - Assert.assertEquals(Base58.encode58Check(contractAddress2), - Base58.encode58Check(assetIssueById.getOwnerAddress().toByteArray())); - } - - @Test(enabled = false, description = "tokenIssue and updateAsset suicide with create2") - public void tokenIssue003AndSuicideWithCreate2() { - String filePath = "./src/test/resources/soliditycode/tvmAssetIssue005.sol"; - String contractName = "B"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String deployTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, - 0, 0, 10000, "0", 0L, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - if (deployTxid == null || infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed - .getContract(contractAddress, blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - String methodTokenIssue = "deploy(uint256)"; - String param = "" + 6; - logger.info("param: " + param); - String txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - logger.info( - "the value: " + PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray())); - List retList = PublicMethed - .getStrings(transactionInfo.getLogList().get(0).getData().toByteArray()); - Long actualSalt = ByteArray.toLong(ByteArray.fromHexString(retList.get(1))); - logger.info("actualSalt: " + actualSalt); - byte[] tmpAddress = new byte[20]; - System.arraycopy(ByteArray.fromHexString(retList.get(0)), - 12, tmpAddress, 0, 20); - String addressHex = "41" + ByteArray.toHexString(tmpAddress); - logger.info("address_hex: " + addressHex); - String addressFinal = Base58.encode58Check(ByteArray.fromHexString(addressHex)); - logger.info("address_final: " + addressFinal); - byte[] callContractAddress = WalletClient.decodeFromBase58Check(addressFinal); - - Assert.assertTrue(PublicMethed - .sendcoin(callContractAddress, 1500_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - name = "testAssetIssu3_" + Long.toString(now); - abbr = "testAsse3_" + Long.toString(now); - methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - String tokenName = PublicMethed.stringToHexString(name); - String tokenAbbr = PublicMethed.stringToHexString(abbr); - param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 6; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(callContractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - String assetIssueId = PublicMethed.queryAccount(callContractAddress, blockingStubFull) - .getAssetIssuedID().toStringUtf8(); - logger.info("assetIssueId: " + assetIssueId); - long returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - logger.info("returnAssetId: " + returnAssetId); - Assert.assertEquals(returnAssetId, Long.parseLong(assetIssueId)); - - String methodSuicide = "SelfdestructTest(address)"; - param = "\"" + Base58.encode58Check(dev003Address) + "\"," + 10000000; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(callContractAddress, methodSuicide, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - methodTokenIssue = "deploy(uint256)"; - param = "" + 6; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(contractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue(PublicMethed - .sendcoin(callContractAddress, 1500_000_000L, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - methodTokenIssue = "tokenIssue(bytes32,bytes32,uint64,uint8)"; - tokenName = PublicMethed.stringToHexString("testAssetIssue_11111"); - tokenAbbr = PublicMethed.stringToHexString("testAssetIssue_22222"); - param = - "\"" + tokenName + "\",\"" + tokenAbbr + "\"," + totalSupply + "," + 6; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(callContractAddress, methodTokenIssue, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - - String assetIssueId2 = PublicMethed.queryAccount(callContractAddress, blockingStubFull) - .getAssetIssuedID().toStringUtf8(); - logger.info("assetIssueId2: " + assetIssueId2); - returnAssetId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - logger.info("returnAssetId: " + returnAssetId); - Assert.assertEquals(returnAssetId, Long.parseLong(assetIssueId2)); - Assert.assertEquals(Long.parseLong(assetIssueId) + 1, Long.parseLong(assetIssueId2)); - Assert.assertEquals(2, - PublicMethed.getAssetIssueByAccount(callContractAddress, blockingStubFull).get() - .getAssetIssueCount()); - - // updateAsset - String methodUpdateAsset = "updateAsset(trcToken,string,string)"; - param = "\"123\",\"updateURLURL\",\"updateDESCDESC\""; - logger.info("param: " + param); - txid = PublicMethed.triggerContract(callContractAddress, methodUpdateAsset, param, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - long returnId = ByteArray.toLong((infoById.get().getContractResult(0).toByteArray())); - Assert.assertEquals(1, returnId); - String newAssetIssueId = PublicMethed.queryAccount(callContractAddress, blockingStubFull) - .getAssetIssuedID() - .toStringUtf8(); - logger.info("newAssetIssueId: " + newAssetIssueId); - AssetIssueContract newAssetIssueById = PublicMethed - .getAssetIssueById(newAssetIssueId, blockingStubFull); - Assert.assertEquals("testAssetIssue_11111", - ByteArray.toStr(newAssetIssueById.getName().toByteArray())); - Assert.assertEquals("testAssetIssue_22222", - ByteArray.toStr(newAssetIssueById.getAbbr().toByteArray())); - Assert - .assertEquals("updateDESCDESC", - ByteArray.toStr(newAssetIssueById.getDescription().toByteArray())); - Assert.assertEquals("updateURLURL", ByteArray.toStr(newAssetIssueById.getUrl().toByteArray())); - Assert.assertEquals(6, newAssetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(callContractAddress), - Base58.encode58Check(newAssetIssueById.getOwnerAddress().toByteArray())); - - AssetIssueContract oldAssetIssueById = PublicMethed - .getAssetIssueById(assetIssueId, blockingStubFull); - Assert.assertEquals(name, ByteArray.toStr(oldAssetIssueById.getName().toByteArray())); - Assert.assertEquals(abbr, ByteArray.toStr(oldAssetIssueById.getAbbr().toByteArray())); - Assert.assertEquals(0, oldAssetIssueById.getDescription().size()); - Assert.assertEquals(0, oldAssetIssueById.getUrl().size()); - Assert.assertEquals(6, oldAssetIssueById.getPrecision()); - Assert.assertEquals(Base58.encode58Check(callContractAddress), - Base58.encode58Check(oldAssetIssueById.getOwnerAddress().toByteArray())); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(dev001Address, dev001Key, fromAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/ContractRewardTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/ContractRewardTest001.java deleted file mode 100644 index ee08016ebb0..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/ContractRewardTest001.java +++ /dev/null @@ -1,233 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tvmstake; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.BytesMessage; -import org.tron.api.GrpcAPI.Return.response_code; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.Protocol.TransactionInfo.code; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ContractRewardTest001 { - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String witnessKey = Configuration.getByPath("testng.conf").getString("witness.key1"); - private String witnessAddress = PublicMethed.getAddressString(witnessKey); - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private byte[] contractAddress; - //= Base58.decode58Check("TQYK8QPAFtxjmse1dShHWYXEMsF836jxxe"); - - @BeforeSuite(enabled = false, description = "stake beforeSuite delete") - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - - PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed - .sendcoin(testAddress001, 1000_000_000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - - String filePath = "src/test/resources/soliditycode/stackContract001.sol"; - String contractName = "B"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 100_000_000L, 100, null, - testFoundationKey, testFoundationAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - PublicMethed.triggerContract(contractAddress,"Stake(address,uint256)", - "\"" + witnessAddress + "\",10000000",false,0,maxFeeLimit, - testFoundationAddress, testFoundationKey,blockingStubFull); - } - - @Test(enabled = false,description = "querry SR account, reward should equal to gerRewardInfo") - void rewardbalanceTest001() { - BytesMessage bytesMessage = BytesMessage.newBuilder().setValue(ByteString - .copyFrom(PublicMethed.getFinalAddress(witnessKey))) - .build(); - long reward = blockingStubFull.getRewardInfo(bytesMessage).getNum(); - - String methedStr = "rewardBalance(address)"; - String argStr = "\"" + witnessAddress + "\""; - TransactionExtention txen = PublicMethed.triggerConstantContractForExtention(contractAddress, - methedStr,argStr,false,0,maxFeeLimit,"0",0,testAddress001,testKey001,blockingStubFull); - System.out.println(txen); - long rewardBalance = ByteArray.toLong(txen.getConstantResult(0).toByteArray()); - - Assert.assertEquals(txen.getResult().getCode(), response_code.SUCCESS); - Assert.assertEquals(reward,rewardBalance); - } - - @Test(enabled = false,description = "querry 0x00, reward should be 0") - void rewardbalanceTest002() { - String methedStr = "nullAddressTest()"; - String argStr = ""; - TransactionExtention txen = PublicMethed.triggerConstantContractForExtention(contractAddress, - methedStr,argStr,false,0,maxFeeLimit,"0",0,testAddress001,testKey001,blockingStubFull); - - long rewardBalance = ByteArray.toLong(txen.getConstantResult(0).toByteArray()); - - Assert.assertEquals(txen.getResult().getCode(), response_code.SUCCESS); - Assert.assertEquals(rewardBalance,0); - } - - @Test(enabled = false,description = "querry UnActive account , reward should be 0") - void rewardbalanceTest003() { - ECKey ecKey2 = new ECKey(Utils.getRandom()); - String key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - String methedStr = "rewardBalance(address)"; - String argStr = "\"" + PublicMethed.getAddressString(key) + "\""; - TransactionExtention txen = PublicMethed.triggerConstantContractForExtention(contractAddress, - methedStr,argStr,false,0,maxFeeLimit,"0",0,testAddress001,testKey001,blockingStubFull); - - long rewardBalance = ByteArray.toLong(txen.getConstantResult(0).toByteArray()); - - Assert.assertEquals(txen.getResult().getCode(), response_code.SUCCESS); - Assert.assertEquals(rewardBalance,0); - } - - @Test(enabled = false,description = "querry contract account,reward should equal to " - + "gerRewardInfo") - void rewardbalanceTest004() { - BytesMessage bytesMessage = BytesMessage.newBuilder().setValue(ByteString - .copyFrom(contractAddress)) - .build(); - long reward = blockingStubFull.getRewardInfo(bytesMessage).getNum(); - - String methedStr = "rewardBalance(address)"; - String argStr = "\"" + Base58.encode58Check(contractAddress) + "\""; - TransactionExtention txen = PublicMethed.triggerConstantContractForExtention(contractAddress, - methedStr,argStr,false,0,maxFeeLimit,"0",0,testAddress001,testKey001,blockingStubFull); - - long rewardBalance = ByteArray.toLong(txen.getConstantResult(0).toByteArray()); - - logger.info("rewardBalance: " + rewardBalance); - logger.info("reward: " + reward); - Assert.assertEquals(txen.getResult().getCode(), response_code.SUCCESS); - Assert.assertEquals(rewardBalance,reward); - } - - @Test(enabled = false,description = "querry ZeroReward account, reward should be 0") - void rewardbalanceTest005() { - BytesMessage bytesMessage = BytesMessage.newBuilder().setValue(ByteString - .copyFrom(PublicMethed.getFinalAddress(testFoundationKey))) - .build(); - long reward = blockingStubFull.getRewardInfo(bytesMessage).getNum(); - - String methedStr = "rewardBalance(address)"; - String argStr = "\"" + PublicMethed.getAddressString(testFoundationKey) + "\""; - TransactionExtention txen = PublicMethed.triggerConstantContractForExtention(contractAddress, - methedStr,argStr,false,0,maxFeeLimit,"0",0,testAddress001,testKey001,blockingStubFull); - - long rewardBalance = ByteArray.toLong(txen.getConstantResult(0).toByteArray()); - - Assert.assertEquals(txen.getResult().getCode(), response_code.SUCCESS); - Assert.assertEquals(reward,rewardBalance,0); - } - - @Test(enabled = false,description = "withdrawBalance") - void withdrawBalanceTest006() { - //contractAddress = Base58.decode58Check("TBsf2FCSht83CEA8CSZ1ReQTRDByNB7FCe"); - - String methedStr = "withdrawRewardTest()"; - String argStr = ""; - String txid = PublicMethed.triggerContract(contractAddress, - methedStr,argStr,false,0,maxFeeLimit,"0",0,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - TransactionInfo ext = PublicMethed.getTransactionInfoById(txid, blockingStubFull).get(); - int result = ByteArray.toInt(ext.getContractResult(0).toByteArray()); - Assert.assertEquals(result,0); - Assert.assertEquals(ext.getResult(), code.SUCESS); - } - - @Test(enabled = false,description = "withdrawBalance twice") - void withdrawBalanceTest007() { - String methedStr = "withdrawRewardTest()"; - String argStr = ""; - String txid = PublicMethed.triggerContract(contractAddress, - methedStr,argStr,false,0,maxFeeLimit,"0",0,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - TransactionInfo ext = PublicMethed.getTransactionInfoById(txid, blockingStubFull).get(); - int result = ByteArray.toInt(ext.getContractResult(0).toByteArray()); - Assert.assertEquals(result,0); - Assert.assertEquals(ext.getResult(), code.SUCESS); - } - - @Test(enabled = false,description = "withdrawBalance other contract") - void withdrawBalanceTest008() { - String filePath = "src/test/resources/soliditycode/stackContract001.sol"; - String contractName = "B"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] otherContract = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 100_000_000L, 100, null, - testFoundationKey, testFoundationAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - - String methedStr = "contractBWithdrawRewardTest(address)"; - String argStr = "\"" + Base58.encode58Check(otherContract) + "\""; - String txid = PublicMethed.triggerContract(contractAddress, - methedStr,argStr,false,0,maxFeeLimit,"0",0,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - TransactionInfo ext = PublicMethed.getTransactionInfoById(txid, blockingStubFull).get(); - int result = ByteArray.toInt(ext.getContractResult(0).toByteArray()); - Assert.assertEquals(result,0); - Assert.assertEquals(ext.getResult(), TransactionInfo.code.SUCESS); - } - - @Test(enabled = false,description = "new withdrawBalance constructor") - void withdrawBalanceTest009() { - String methedStr = "createA()"; - String argStr = ""; - String txid = PublicMethed.triggerContract(contractAddress, - methedStr,argStr,false,0,maxFeeLimit,"0",0,testAddress001,testKey001,blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - TransactionInfo ext = PublicMethed.getTransactionInfoById(txid, blockingStubFull).get(); - - int result = ByteArray.toInt(ext.getLog(0).getData().toByteArray()); - Assert.assertEquals(result,0); - int result2 = ByteArray.toInt(ext.getLog(1).getData().toByteArray()); - Assert.assertEquals(result2,0); - Assert.assertEquals(ext.getResult(), code.SUCESS); - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/IsSrCandidateTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/IsSrCandidateTest001.java deleted file mode 100644 index 39837c2fe70..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/IsSrCandidateTest001.java +++ /dev/null @@ -1,118 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tvmstake; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -public class IsSrCandidateTest001 { - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - private String testWitnessKey = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private byte[] contractAddress; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed - .sendcoin(testAddress001, 1000_000_000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/isSRCandidate.sol"; - String contractName = "TestIsSRCandidate"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKey001, - testAddress001, blockingStubFull); - } - - @Test(enabled = false, description = "Witness Address should be true") - void tvmStakeTest001() { - String methodStr = "isSRCandidateTest(address)"; - String argsStr = "\"" + PublicMethed.getAddressString(testWitnessKey) + "\""; - TransactionExtention returns = PublicMethed - .triggerConstantContractForExtention(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, "", 0, testAddress001, testKey001, blockingStubFull); - int isSR = ByteArray.toInt(returns.getConstantResult(0).toByteArray()); - - Assert.assertEquals(isSR,1); - } - - @Test(enabled = false, description = "Account Address should be false") - void tvmStakeTest002() { - String methodStr = "isSRCandidateTest(address)"; - String argsStr = "\"" + Base58.encode58Check(testAddress001) + "\""; - TransactionExtention returns = PublicMethed - .triggerConstantContractForExtention(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, "", 0, testAddress001, testKey001, blockingStubFull); - int isSR = ByteArray.toInt(returns.getConstantResult(0).toByteArray()); - - Assert.assertEquals(isSR,0); - } - - @Test(enabled = false, description = "zero Address(0x00) should be false") - void tvmStakeTest003() { - String methodStr = "zeroAddressTest()"; - String argsStr = ""; - TransactionExtention returns = PublicMethed - .triggerConstantContractForExtention(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, "", 0, testAddress001, testKey001, blockingStubFull); - int isSR = ByteArray.toInt(returns.getConstantResult(0).toByteArray()); - - Assert.assertEquals(isSR,0); - } - - @Test(enabled = false, description = "Contract Address should be false") - void tvmStakeTest004() { - String methodStr = "localContractAddrTest()"; - String argsStr = ""; - TransactionExtention returns = PublicMethed - .triggerConstantContractForExtention(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, "", 0, testAddress001, testKey001, blockingStubFull); - int isSR = ByteArray.toInt(returns.getConstantResult(0).toByteArray()); - - Assert.assertEquals(isSR,0); - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StackSuicideTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StackSuicideTest001.java deleted file mode 100644 index 5758439a9da..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StackSuicideTest001.java +++ /dev/null @@ -1,247 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tvmstake; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.HashMap; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Account.Frozen; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class StackSuicideTest001 { - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - private String testWitnessKey = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private String testWitnessAddress = PublicMethed.getAddressString(testWitnessKey); - - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private byte[] contractAddress; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed - .sendcoin(testAddress001, 1000_000_000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - } - - @Test(enabled = false, description = "targetAddress no TRX, and no frozen") - public void stackSuicideTest001() { - - String filePath = "src/test/resources/soliditycode/stackSuicide001.sol"; - String contractName = "testStakeSuicide"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 10000000L, 100, null, testKey001, - testAddress001, blockingStubFull); - - final byte[] targetAddress = PublicMethed.deployContract(contractName, abi, code, "", - maxFeeLimit, 0, 100, null, testKey001, testAddress001, blockingStubFull); - - - String txid = PublicMethed.triggerContract(contractAddress,"Stake(address,uint256)", - "\"" + testWitnessAddress + "\",10000000",false,0,maxFeeLimit, - testFoundationAddress, testFoundationKey,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional ex = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - Assert.assertEquals(ByteArray.toInt(ex.get().getContractResult(0).toByteArray()),1); - - Account ownerAccount = PublicMethed.queryAccount(contractAddress,blockingStubFull); - final Frozen ownerFrozen = ownerAccount.getFrozen(0); - - String methedStr = "SelfdestructTest(address)"; - String argStr = "\"" + Base58.encode58Check(targetAddress) + "\""; - txid = PublicMethed.triggerContract(contractAddress,methedStr,argStr,false, - 0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ex = PublicMethed.getTransactionInfoById(txid,blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - - - Account targetAccount = PublicMethed.queryAccount(targetAddress,blockingStubFull); - Frozen targetFrozen = targetAccount.getFrozen(0); - - - Assert.assertEquals(ownerFrozen.getExpireTime(),targetFrozen.getExpireTime()); - Assert.assertEquals(ownerFrozen.getFrozenBalance(),targetFrozen.getFrozenBalance()); - - } - - @Test(enabled = false, description = "targetAddress has TRX, but no frozen") - public void stackSuicideTest002() { - String filePath = "src/test/resources/soliditycode/stackSuicide001.sol"; - String contractName = "testStakeSuicide"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 10000000L, 100, null, testKey001, - testAddress001, blockingStubFull); - - - Long targetBalance = 10_000_000L; - final byte[] targetAddress = PublicMethed.deployContract(contractName, abi, code, "", - maxFeeLimit, targetBalance, 100, null, testKey001, testAddress001, blockingStubFull); - - String methedStr = "Stake(address,uint256)"; - String argStr = "\"" + testWitnessAddress + "\",10000000"; - String txid = PublicMethed.triggerContract(contractAddress,methedStr, - argStr,false,0,maxFeeLimit, - testFoundationAddress, testFoundationKey,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional ex = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - Assert.assertEquals(ByteArray.toInt(ex.get().getContractResult(0).toByteArray()),1); - - Account ownerAccount = PublicMethed.queryAccount(contractAddress,blockingStubFull); - final Frozen ownerFrozen = ownerAccount.getFrozen(0); - - methedStr = "SelfdestructTest(address)"; - argStr = "\"" + Base58.encode58Check(targetAddress) + "\""; - txid = PublicMethed.triggerContract(contractAddress,methedStr,argStr,false, - 0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ex = PublicMethed.getTransactionInfoById(txid,blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - - - Account targetAccount = PublicMethed.queryAccount(targetAddress,blockingStubFull); - Frozen targetFrozen = targetAccount.getFrozen(0); - - - Assert.assertEquals(ownerFrozen.getExpireTime(),targetFrozen.getExpireTime()); - Assert.assertEquals(ownerFrozen.getFrozenBalance(),targetFrozen.getFrozenBalance()); - - methedStr = "transfer(address,uint256)"; - argStr = "\"" + Base58.encode58Check(testAddress001) + "\"," + targetBalance; - txid = PublicMethed.triggerContract(targetAddress,methedStr,argStr,false,0, - maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(0,PublicMethed.queryAccount(targetAddress,blockingStubFull).getBalance()); - } - - @Test(enabled = false, description = "targetAddress has TRX, and has frozen") - public void stackSuicideTest003() { - Long targetBalance = 10_000_000L; - - String filePath = "src/test/resources/soliditycode/stackSuicide001.sol"; - String contractName = "testStakeSuicide"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, targetBalance, 100, - null, testKey001, testAddress001, blockingStubFull); - - final byte[] targetAddress = PublicMethed.deployContract(contractName, abi, code, "", - maxFeeLimit, 12_345_678L, 100, null, testKey001, testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String methedStr = "Stake(address,uint256)"; - String argStr = "\"" + testWitnessAddress + "\"," + targetBalance; - String txid = PublicMethed.triggerContract(contractAddress,methedStr, - argStr,false,0,maxFeeLimit, testFoundationAddress, testFoundationKey,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional ex = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - Assert.assertEquals(ByteArray.toInt(ex.get().getContractResult(0).toByteArray()),1); - - argStr = "\"" + testWitnessAddress + "\"," + 12_000_000L; - String txid2 = PublicMethed.triggerContract(targetAddress,methedStr,argStr,false, - 0,maxFeeLimit,testFoundationAddress,testFoundationKey,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ex = PublicMethed.getTransactionInfoById(txid2,blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - Assert.assertEquals(ByteArray.toInt(ex.get().getContractResult(0).toByteArray()),1); - - Account ownerAccount = PublicMethed.queryAccount(contractAddress,blockingStubFull); - final Frozen ownerFrozen = ownerAccount.getFrozen(0); - - Account targetAccount = PublicMethed.queryAccount(targetAddress,blockingStubFull); - final Frozen targetFrozen = targetAccount.getFrozen(0); - - methedStr = "SelfdestructTest(address)"; - argStr = "\"" + Base58.encode58Check(targetAddress) + "\""; - txid = PublicMethed.triggerContract(contractAddress,methedStr,argStr,false, - 0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ex = PublicMethed.getTransactionInfoById(txid,blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - - - targetAccount = PublicMethed.queryAccount(targetAddress,blockingStubFull); - Frozen targetFrozenAfter = targetAccount.getFrozen(0); - - BigInteger expected = - BigInteger.valueOf(ownerFrozen.getExpireTime()) - .multiply(BigInteger.valueOf(ownerFrozen.getFrozenBalance())) - .add(BigInteger.valueOf(targetFrozen.getExpireTime()) - .multiply(BigInteger.valueOf(targetFrozen.getFrozenBalance()))) - .divide(BigInteger.valueOf(ownerFrozen.getFrozenBalance()) - .add(BigInteger.valueOf(targetFrozen.getFrozenBalance()))); - - Assert.assertEquals(expected.longValue(), targetFrozenAfter.getExpireTime()); - Assert.assertEquals(targetFrozenAfter.getFrozenBalance(), - ownerFrozen.getFrozenBalance() + targetFrozen.getFrozenBalance()); - - methedStr = "transfer(address,uint256)"; - argStr = "\"" + Base58.encode58Check(testAddress001) + "\"," + 345678; - txid = PublicMethed.triggerContract(targetAddress,methedStr,argStr,false,0, - maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertEquals(0,PublicMethed.queryAccount(targetAddress,blockingStubFull).getBalance()); - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest002.java deleted file mode 100644 index 3aa1f7c9793..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest002.java +++ /dev/null @@ -1,186 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tvmstake; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Account.Frozen; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class StakeSuicideTest002 { - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - private String testWitnessKey = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private String testWitnessAddress = PublicMethed.getAddressString(testWitnessKey); - - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private byte[] contractAddress; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - String filePath = "src/test/resources/soliditycode/stackSuicide001.sol"; - String contractName = "B"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 10000000L, - 100, null, testFoundationKey, - testFoundationAddress, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = false, description = "create2 -> stake -> suicide -> create2 the same Address") - public void stackSuicideAndCreate2Test001() { - - String filePath = "src/test/resources/soliditycode/stackSuicide001.sol"; - String contractName = "testStakeSuicide"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - - String methedStr = "deploy(bytes,uint256)"; - String argStr = "\"" + code + "\"," + 1; - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argStr,false, - 0,maxFeeLimit,testFoundationAddress,testFoundationKey,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional ex = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - String hex = "41" + ByteArray.toHexString(ex.get().getContractResult(0).toByteArray()) - .substring(24); - logger.info("Deploy Address : " + Base58.encode58Check(ByteArray.fromHexString(hex))); - byte[] ownerAddress = ByteArray.fromHexString(hex); - - methedStr = "Stake(address,uint256)"; - argStr = "\"" + testWitnessAddress + "\"," + 10_000_000; - txid = PublicMethed.triggerContract(ownerAddress,methedStr, - argStr,false,10_000_000,maxFeeLimit, - testFoundationAddress, testFoundationKey,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - ex = PublicMethed.getTransactionInfoById(txid,blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - - Account ownerAccount = PublicMethed.queryAccount(ownerAddress,blockingStubFull); - final Frozen ownerFrozen = ownerAccount.getFrozen(0); - - methedStr = "SelfdestructTest(address)"; - argStr = "\"" + Base58.encode58Check(contractAddress) + "\""; - txid = PublicMethed.triggerContract(ownerAddress,methedStr,argStr,false, - 0,maxFeeLimit,testFoundationAddress,testFoundationKey,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - methedStr = "deploy(bytes,uint256)"; - argStr = "\"" + code + "\"," + 1; - txid = PublicMethed.triggerContract(contractAddress,methedStr,argStr,false, - 0,maxFeeLimit,testFoundationAddress,testFoundationKey,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerAccount = PublicMethed.queryAccount(ownerAddress,blockingStubFull); - Assert.assertEquals(ownerAccount.getBalance(),0); - Assert.assertEquals(ownerAccount.getFrozenCount(),0); - Assert.assertEquals(ownerAccount.getVotesCount(),0); - - Account targetAccount = PublicMethed.queryAccount(contractAddress,blockingStubFull); - Frozen targetFrozen = targetAccount.getFrozen(0); - - Assert.assertEquals(ownerFrozen.getExpireTime(),targetFrozen.getExpireTime()); - Assert.assertEquals(ownerFrozen.getFrozenBalance(),targetFrozen.getFrozenBalance()); - - } - - @Test(enabled = false, description = "create2 -> stake -> suicide -> sendcoin to create2 Address") - public void stackSuicideAndCreate2Test002() { - String filePath = "src/test/resources/soliditycode/stackSuicide001.sol"; - String contractName = "testStakeSuicide"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - - String methedStr = "deploy(bytes,uint256)"; - String argStr = "\"" + code + "\"," + 2; - String txid = PublicMethed.triggerContract(contractAddress,methedStr,argStr,false, - 0,maxFeeLimit,testFoundationAddress,testFoundationKey,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional ex = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - String hex = "41" + ByteArray.toHexString(ex.get().getContractResult(0).toByteArray()) - .substring(24); - logger.info("Deploy Address : " + Base58.encode58Check(ByteArray.fromHexString(hex))); - byte[] ownerAddress = ByteArray.fromHexString(hex); - - methedStr = "Stake(address,uint256)"; - argStr = "\"" + testWitnessAddress + "\"," + 10_000_000; - txid = PublicMethed.triggerContract(ownerAddress,methedStr, - argStr,false,10_000_000,maxFeeLimit, - testFoundationAddress, testFoundationKey,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - ex = PublicMethed.getTransactionInfoById(txid,blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - - Account ownerAccount = PublicMethed.queryAccount(ownerAddress,blockingStubFull); - final Frozen ownerFrozen = ownerAccount.getFrozen(0); - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - - methedStr = "SelfdestructTest(address)"; - argStr = "\"" + Base58.encode58Check(testAddress001) + "\""; - txid = PublicMethed.triggerContract(ownerAddress,methedStr,argStr,false, - 0,maxFeeLimit,testFoundationAddress,testFoundationKey,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long sendcoin = 1; - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress,sendcoin,testFoundationAddress, - testFoundationKey,blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ownerAccount = PublicMethed.queryAccount(ownerAddress,blockingStubFull); - Assert.assertEquals(ownerAccount.getBalance(),sendcoin); - Assert.assertEquals(ownerAccount.getFrozenCount(),0); - Assert.assertEquals(ownerAccount.getVotesCount(),0); - - Account targetAccount = PublicMethed.queryAccount(testAddress001,blockingStubFull); - Frozen targetFrozen = targetAccount.getFrozen(0); - - Assert.assertEquals(ownerFrozen.getExpireTime(),targetFrozen.getExpireTime()); - Assert.assertEquals(ownerFrozen.getFrozenBalance(),targetFrozen.getFrozenBalance()); - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest003.java deleted file mode 100644 index 212e686b0ec..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest003.java +++ /dev/null @@ -1,196 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tvmstake; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Account.Frozen; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -public class StakeSuicideTest003 { - - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - private String testWitnessKey = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private String testWitnessAddress = PublicMethed.getAddressString(testWitnessKey); - - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private byte[] contractAddress; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - PublicMethed.sendcoin(testAddress001,10000000,testFoundationAddress, - testFoundationKey,blockingStubFull); - } - - @Test(enabled = false, description = "suicide target Address is owner Address") - public void stakeSuicideTest001() { - String filePath = "src/test/resources/soliditycode/stackSuicide001.sol"; - String contractName = "testStakeSuicide"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 10000000L, - 100, null, testFoundationKey, - testFoundationAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String txid = PublicMethed.triggerContract(contractAddress,"Stake(address,uint256)", - "\"" + testWitnessAddress + "\",10000000",false,0,maxFeeLimit, - testFoundationAddress, testFoundationKey,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional ex = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - Assert.assertEquals(ByteArray.toInt(ex.get().getContractResult(0).toByteArray()),1); - - Account ownerAccount = PublicMethed.queryAccount(contractAddress,blockingStubFull); - Frozen ownerFrozen = ownerAccount.getFrozen(0); - - String methedStr = "SelfdestructTest(address)"; - String argStr = "\"" + Base58.encode58Check(contractAddress) + "\""; - txid = PublicMethed.triggerContract(contractAddress,methedStr,argStr,false, - 0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ex = PublicMethed.getTransactionInfoById(txid,blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - - Account account = PublicMethed.queryAccount(contractAddress,blockingStubFull); - Assert.assertEquals(account.getFrozenCount(),0); - - } - - @Test(enabled = false, description = "suicide target Address is BlackHoleAddress Address") - public void stakeSuicideTest002() { - String filePath = "src/test/resources/soliditycode/stackSuicide001.sol"; - String contractName = "testStakeSuicide"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 10000000L, - 100, null, testFoundationKey, - testFoundationAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String txid = PublicMethed.triggerContract(contractAddress,"Stake(address,uint256)", - "\"" + testWitnessAddress + "\",10000000",false,0,maxFeeLimit, - testFoundationAddress, testFoundationKey,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional ex = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - Assert.assertEquals(ByteArray.toInt(ex.get().getContractResult(0).toByteArray()),1); - - Account ownerAccount = PublicMethed.queryAccount(contractAddress,blockingStubFull); - Frozen ownerFrozen = ownerAccount.getFrozen(0); - - String blackHoleAddress = "TLsV52sRDL79HXGGm9yzwKibb6BeruhUzy"; - final Account accountBefore = PublicMethed - .queryAccount(PublicMethed.decode58Check(blackHoleAddress), - blockingStubFull); - - String methedStr = "SelfdestructTest(address)"; - String argStr = "\"" + blackHoleAddress + "\""; - txid = PublicMethed.triggerContract(contractAddress,methedStr,argStr,false, - 0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ex = PublicMethed.getTransactionInfoById(txid,blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - - Account account = PublicMethed.queryAccount(contractAddress,blockingStubFull); - Assert.assertEquals(account.getFrozenCount(),0); - - Account accountAfter = PublicMethed - .queryAccount(PublicMethed.decode58Check(blackHoleAddress), - blockingStubFull); - Assert.assertEquals(accountBefore.getBalance() + ex.get().getReceipt().getEnergyFee() - + 10000000, accountAfter.getBalance()); - } - - @Test(enabled = false, description = "suicide target Address is BlackHoleAddress Address") - public void stakeSuicideTest003() { - String filePath = "src/test/resources/soliditycode/stackSuicide001.sol"; - String contractName = "testStakeSuicide"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 10000000L, - 100, null, testFoundationKey, - testFoundationAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String txid = PublicMethed.triggerContract(contractAddress,"Stake(address,uint256)", - "\"" + testWitnessAddress + "\",10000000",false,0,maxFeeLimit, - testFoundationAddress, testFoundationKey,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional ex = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - Assert.assertEquals(ByteArray.toInt(ex.get().getContractResult(0).toByteArray()),1); - - Account ownerAccount = PublicMethed.queryAccount(contractAddress,blockingStubFull); - Frozen ownerFrozen = ownerAccount.getFrozen(0); - - final Account accountBefore = PublicMethed - .queryAccount(PublicMethed.decode58Check("T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb"), - blockingStubFull); - - String methedStr = "SelfdestructTest(address)"; - String argStr = "\"" + "T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb" + "\""; - txid = PublicMethed.triggerContract(contractAddress,methedStr,argStr,false, - 0,maxFeeLimit,testAddress001,testKey001,blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - ex = PublicMethed.getTransactionInfoById(txid,blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - - Account account = PublicMethed.queryAccount(contractAddress,blockingStubFull); - Assert.assertEquals(account.getFrozenCount(),0); - - Account accountAfter = PublicMethed - .queryAccount(PublicMethed.decode58Check("T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb"), - blockingStubFull); - Assert.assertEquals(accountBefore.getBalance() + 10000000, accountAfter.getBalance()); - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest004.java deleted file mode 100644 index 93d69f3b17b..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest004.java +++ /dev/null @@ -1,397 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tvmstake; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.HashMap; -import java.util.Optional; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Account.Frozen; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -public class StakeSuicideTest004 { - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - private String testWitnessKey = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private String testWitnessKey2 = Configuration.getByPath("testng.conf") - .getString("witness.key3"); - private byte[] testWitnessAddress = PublicMethed.getFinalAddress(testWitnessKey); - private byte[] testWitnessAddress2 = PublicMethed.getFinalAddress(testWitnessKey2); - - - - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] testAddress002 = ecKey2.getAddress(); - String testKey002 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private byte[] contractAddress; - String filePath = "src/test/resources/soliditycode/testStakeSuicide.sol"; - String contractName = "testStakeSuicide"; - String code = ""; - String abi = ""; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - System.out.println(testKey001); - PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed - .sendcoin(testAddress001, 1000_000_00000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - code = retMap.get("byteCode").toString(); - abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 1000_000000L, 100, - null, testKey001, testAddress001, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = false, description = "targetAddress has frozen 1,suicide contract stake 1") - void tvmStakeSuicideTest001() { - ECKey ecKeyTargetAddress = new ECKey(Utils.getRandom()); - byte[] targetAddress = ecKeyTargetAddress.getAddress(); - String testKeyTargetAddress = ByteArray.toHexString(ecKeyTargetAddress.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed - .sendcoin(targetAddress, 10_000000L, testFoundationAddress, testFoundationKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue(PublicMethed - .freezeBalance(targetAddress,1_000000L,3,testKeyTargetAddress,blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account targetAccount = PublicMethed.queryAccount(targetAddress,blockingStubFull); - final Frozen targetFrozenBefore = targetAccount.getFrozen(0); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000_000000L, 100, null, testKey001, testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String methodStr = "Stake(address,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testWitnessAddress) + "\"," + 1000000; - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional ex = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - Assert.assertEquals(ByteArray.toInt(ex.get().getContractResult(0).toByteArray()),1); - - Account ownerAccount = PublicMethed.queryAccount(contractAddress,blockingStubFull); - final Frozen ownerFrozen = ownerAccount.getFrozen(0); - Long ownerBalance = ownerAccount.getBalance(); - String methodStrSuicide = "SelfdestructTest(address)"; - String argsStrSuicide = "\"" + Base58.encode58Check(targetAddress) + "\""; - String txidSuicide = PublicMethed - .triggerContract(contractAddress, methodStrSuicide, argsStrSuicide, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - ex = PublicMethed.getTransactionInfoById(txidSuicide, blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account targetAccountAfter = PublicMethed.queryAccount(targetAddress,blockingStubFull); - Frozen targetFrozenAfter = targetAccountAfter.getFrozen(0); - - BigInteger expected = - BigInteger.valueOf(ownerFrozen.getExpireTime()) - .multiply(BigInteger.valueOf(ownerFrozen.getFrozenBalance())) - .add(BigInteger.valueOf(targetFrozenBefore.getExpireTime()) - .multiply(BigInteger.valueOf(targetFrozenBefore.getFrozenBalance()))) - .divide(BigInteger.valueOf(ownerFrozen.getFrozenBalance()) - .add(BigInteger.valueOf(targetFrozenBefore.getFrozenBalance()))); - - Assert.assertEquals(expected.longValue(), targetFrozenAfter.getExpireTime()); - Assert.assertEquals(targetFrozenAfter.getFrozenBalance(), - ownerFrozen.getFrozenBalance() + targetFrozenBefore.getFrozenBalance()); - - } - - @Test(enabled = false, description = "targetAddress has frozen 1,suicide contract stake all") - void tvmStakeSuicideTest002() { - ECKey ecKeyTargetAddress = new ECKey(Utils.getRandom()); - byte[] targetAddress = ecKeyTargetAddress.getAddress(); - String testKeyTargetAddress = ByteArray.toHexString(ecKeyTargetAddress.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed - .sendcoin(targetAddress, 10_000000L, testFoundationAddress, testFoundationKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue(PublicMethed - .freezeBalance(targetAddress,1_000000L,3,testKeyTargetAddress,blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account targetAccount = PublicMethed.queryAccount(targetAddress,blockingStubFull); - final Frozen targetFrozenBefore = targetAccount.getFrozen(0); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 100_000000L, 100, null, testKey001, testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String methodStr = "Stake(address,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testWitnessAddress) + "\"," + 100_000000L; - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional ex = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - Assert.assertEquals(ByteArray.toInt(ex.get().getContractResult(0).toByteArray()),1); - - Account ownerAccount = PublicMethed.queryAccount(contractAddress,blockingStubFull); - final Frozen ownerFrozen = ownerAccount.getFrozen(0); - Long ownerBalance = ownerAccount.getBalance(); - String methodStrSuicide = "SelfdestructTest(address)"; - String argsStrSuicide = "\"" + Base58.encode58Check(targetAddress) + "\""; - String txidSuicide = PublicMethed - .triggerContract(contractAddress, methodStrSuicide, argsStrSuicide, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - ex = PublicMethed.getTransactionInfoById(txidSuicide, blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account targetAccountAfter = PublicMethed.queryAccount(targetAddress,blockingStubFull); - Frozen targetFrozenAfter = targetAccountAfter.getFrozen(0); - - BigInteger expected = - BigInteger.valueOf(ownerFrozen.getExpireTime()) - .multiply(BigInteger.valueOf(ownerFrozen.getFrozenBalance())) - .add(BigInteger.valueOf(targetFrozenBefore.getExpireTime()) - .multiply(BigInteger.valueOf(targetFrozenBefore.getFrozenBalance()))) - .divide(BigInteger.valueOf(ownerFrozen.getFrozenBalance()) - .add(BigInteger.valueOf(targetFrozenBefore.getFrozenBalance()))); - - Assert.assertEquals(expected.longValue(), targetFrozenAfter.getExpireTime()); - Assert.assertEquals(targetFrozenAfter.getFrozenBalance(), - ownerFrozen.getFrozenBalance() + targetFrozenBefore.getFrozenBalance()); - - } - - @Test(enabled = false, description = "targetAddress has frozen all,suicide contract stake all") - void tvmStakeSuicideTest003() { - ECKey ecKeyTargetAddress = new ECKey(Utils.getRandom()); - byte[] targetAddress = ecKeyTargetAddress.getAddress(); - String testKeyTargetAddress = ByteArray.toHexString(ecKeyTargetAddress.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed - .sendcoin(targetAddress, 20_000000L, testFoundationAddress, testFoundationKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(targetAddress,5_000000L, - 3,1, ByteString.copyFrom(testAddress001),testKeyTargetAddress,blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue(PublicMethed - .freezeBalance(targetAddress,10_000000L,3,testKeyTargetAddress,blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account targetAccount = PublicMethed.queryAccount(targetAddress,blockingStubFull); - final Frozen targetFrozenBefore = targetAccount.getFrozen(0); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 100_000000L, 100, null, testKey001, testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String methodStr = "Stake(address,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testWitnessAddress) + "\"," + 100_000000L; - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional ex = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - Assert.assertEquals(ByteArray.toInt(ex.get().getContractResult(0).toByteArray()),1); - - Account ownerAccount = PublicMethed.queryAccount(contractAddress,blockingStubFull); - final Frozen ownerFrozen = ownerAccount.getFrozen(0); - Long ownerBalance = ownerAccount.getBalance(); - String methodStrSuicide = "SelfdestructTest(address)"; - String argsStrSuicide = "\"" + Base58.encode58Check(targetAddress) + "\""; - String txidSuicide = PublicMethed - .triggerContract(contractAddress, methodStrSuicide, argsStrSuicide, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - ex = PublicMethed.getTransactionInfoById(txidSuicide, blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account targetAccountAfter = PublicMethed.queryAccount(targetAddress,blockingStubFull); - Frozen targetFrozenAfter = targetAccountAfter.getFrozen(0); - - BigInteger expected = - BigInteger.valueOf(ownerFrozen.getExpireTime()) - .multiply(BigInteger.valueOf(ownerFrozen.getFrozenBalance())) - .add(BigInteger.valueOf(targetFrozenBefore.getExpireTime()) - .multiply(BigInteger.valueOf(targetFrozenBefore.getFrozenBalance()))) - .divide(BigInteger.valueOf(ownerFrozen.getFrozenBalance()) - .add(BigInteger.valueOf(targetFrozenBefore.getFrozenBalance()))); - - Assert.assertEquals(expected.longValue(), targetFrozenAfter.getExpireTime()); - Assert.assertEquals(targetFrozenAfter.getFrozenBalance(), - ownerFrozen.getFrozenBalance() + targetFrozenBefore.getFrozenBalance()); - - } - - @Test(enabled = false, description = "targetAddress is new account ,suicide contract stake all") - void tvmStakeSuicideTest004() { - ECKey ecKeyTargetAddress = new ECKey(Utils.getRandom()); - byte[] targetAddress = ecKeyTargetAddress.getAddress(); - String testKeyTargetAddress = ByteArray.toHexString(ecKeyTargetAddress.getPrivKeyBytes()); - System.out.println(Base58.encode58Check(targetAddress)); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 100_000000L, 100, null, testKey001, testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String methodStr = "Stake(address,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testWitnessAddress) + "\"," + 100_000000L; - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional ex = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - Assert.assertEquals(ByteArray.toInt(ex.get().getContractResult(0).toByteArray()),1); - - Account ownerAccount = PublicMethed.queryAccount(contractAddress,blockingStubFull); - final Frozen ownerFrozen = ownerAccount.getFrozen(0); - Long ownerBalance = ownerAccount.getBalance(); - String methodStrSuicide = "SelfdestructTest(address)"; - String argsStrSuicide = "\"" + Base58.encode58Check(targetAddress) + "\""; - String txidSuicide = PublicMethed - .triggerContract(contractAddress, methodStrSuicide, argsStrSuicide, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - ex = PublicMethed.getTransactionInfoById(txidSuicide, blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account targetAccountAfter = PublicMethed.queryAccount(targetAddress,blockingStubFull); - Frozen targetFrozenAfter = targetAccountAfter.getFrozen(0); - - - Assert.assertEquals(ownerFrozen.getExpireTime(), targetFrozenAfter.getExpireTime()); - Assert.assertEquals(targetFrozenAfter.getFrozenBalance(), - ownerFrozen.getFrozenBalance()); - - } - - @Test(enabled = false, description = "targetAddress frozen to other address ,suicide contract " - + "stake all") - void tvmStakeSuicideTest005() { - ECKey ecKeyTargetAddress = new ECKey(Utils.getRandom()); - byte[] targetAddress = ecKeyTargetAddress.getAddress(); - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] address = ecKey.getAddress(); - String testKeyTargetAddress = ByteArray.toHexString(ecKeyTargetAddress.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed - .sendcoin(targetAddress, 10_000000L, testFoundationAddress, testFoundationKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(targetAddress,5_000000L, - 3,1, ByteString.copyFrom(testAddress001),testKeyTargetAddress,blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - System.out.println("aaaa" + Base58.encode58Check(targetAddress)); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 100_000000L, 100, null, testKey001, testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String methodStr = "Stake(address,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testWitnessAddress) + "\"," + 100_000000L; - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional ex = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - System.out.println("aaaaa" + Base58.encode58Check(contractAddress)); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - Assert.assertEquals(ByteArray.toInt(ex.get().getContractResult(0).toByteArray()),1); - - - Account ownerAccount = PublicMethed.queryAccount(contractAddress,blockingStubFull); - final Frozen ownerFrozen = ownerAccount.getFrozen(0); - Long ownerBalance = ownerAccount.getBalance(); - String methodStrSuicide = "SelfdestructTest(address)"; - String argsStrSuicide = "\"" + Base58.encode58Check(targetAddress) + "\""; - String txidSuicide = PublicMethed - .triggerContract(contractAddress, methodStrSuicide, argsStrSuicide, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account targetAccount = PublicMethed.queryAccount(targetAddress,blockingStubFull); - final Frozen targetFrozenAfter = targetAccount.getFrozen(0); - ex = PublicMethed.getTransactionInfoById(txidSuicide, blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - - Assert.assertEquals(ownerFrozen.getExpireTime(), targetFrozenAfter.getExpireTime()); - Assert.assertEquals(targetFrozenAfter.getFrozenBalance(), - ownerFrozen.getFrozenBalance()); - - } - - - - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest005.java deleted file mode 100644 index 3dc87def0e5..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeSuicideTest005.java +++ /dev/null @@ -1,204 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tvmstake; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Account.Frozen; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -public class StakeSuicideTest005 { - - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - private String testWitnessKey = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private String testWitnessKey2 = Configuration.getByPath("testng.conf") - .getString("witness.key3"); - private byte[] testWitnessAddress = PublicMethed.getFinalAddress(testWitnessKey); - private byte[] testWitnessAddress2 = PublicMethed.getFinalAddress(testWitnessKey2); - - - - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] testAddress002 = ecKey2.getAddress(); - String testKey002 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private byte[] contractAddress; - String filePath = "src/test/resources/soliditycode/testStakeSuicide.sol"; - String contractName = "testStakeSuicide"; - String code = ""; - String abi = ""; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - @BeforeClass(enabled = false) - public void beforeClass() { - System.out.println(testKey001); - PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed - .sendcoin(testAddress001, 1000_000_00000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - code = retMap.get("byteCode").toString(); - abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000_000000L, 100, null, testKey001, testAddress001, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = false, description = "targetAddress is account no TRX, and no frozen") - void tvmStakeSuicideTest001() { - ECKey ecKeyTargetAddress = new ECKey(Utils.getRandom()); - byte[] targetAddress = ecKeyTargetAddress.getAddress(); - String testKeyTargetAddress = ByteArray.toHexString(ecKeyTargetAddress.getPrivKeyBytes()); - - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 1000_000000L, 100, - null, testKey001, testAddress001, blockingStubFull); - - Account ownerAccount = PublicMethed.queryAccount(contractAddress,blockingStubFull); - final Long ownerBalance = ownerAccount.getBalance(); - - String methodStrSuicide = "SelfdestructTest(address)"; - String argsStrSuicide = "\"" + Base58.encode58Check(targetAddress) + "\""; - String txidSuicide = PublicMethed - .triggerContract(contractAddress, methodStrSuicide, argsStrSuicide, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional ex = PublicMethed.getTransactionInfoById(txidSuicide, - blockingStubFull); - ex = PublicMethed.getTransactionInfoById(txidSuicide,blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - - Account targetAccount = PublicMethed.queryAccount(targetAddress,blockingStubFull); - Long targetBalance = targetAccount.getBalance(); - - System.out.println(targetBalance); - Assert.assertEquals(ownerBalance,targetBalance); - - } - - @Test(enabled = false, description = "targetAddress is account 1 TRX, and no frozen") - void tvmStakeSuicideTest002() { - ECKey ecKeyTargetAddress = new ECKey(Utils.getRandom()); - byte[] targetAddress = ecKeyTargetAddress.getAddress(); - final String testKeyTargetAddress = ByteArray.toHexString(ecKeyTargetAddress.getPrivKeyBytes()); - - PublicMethed - .sendcoin(targetAddress, 1_000000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000_000000L, 100, null, testKey001, testAddress001, blockingStubFull); - - Account ownerAccount = PublicMethed.queryAccount(contractAddress,blockingStubFull); - final Long ownerBalance = ownerAccount.getBalance(); - - String methodStrSuicide = "SelfdestructTest(address)"; - String argsStrSuicide = "\"" + Base58.encode58Check(targetAddress) + "\""; - String txidSuicide = PublicMethed - .triggerContract(contractAddress, methodStrSuicide, argsStrSuicide, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional ex = PublicMethed.getTransactionInfoById(txidSuicide, - blockingStubFull); - ex = PublicMethed.getTransactionInfoById(txidSuicide,blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - - Account targetAccount = PublicMethed.queryAccount(targetAddress,blockingStubFull); - Long targetBalance = targetAccount.getBalance() - 1_000000L; - - Assert.assertEquals(ownerBalance,targetBalance); - - Assert.assertTrue(PublicMethed - .freezeBalance(targetAddress,1_000000L,3,testKeyTargetAddress,blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - } - - @Test(enabled = false, description = "targetAddress is account 1 TRX, and 1 frozen") - void tvmStakeSuicideTest003() { - ECKey ecKeyTargetAddress = new ECKey(Utils.getRandom()); - byte[] targetAddress = ecKeyTargetAddress.getAddress(); - String testKeyTargetAddress = ByteArray.toHexString(ecKeyTargetAddress.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed - .sendcoin(targetAddress, 10_000000L, testFoundationAddress, testFoundationKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue(PublicMethed - .freezeBalance(targetAddress,1_000000L,3,testKeyTargetAddress,blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account targetAccount = PublicMethed.queryAccount(targetAddress,blockingStubFull); - final Frozen targetFrozenBefore = targetAccount.getFrozen(0); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000_000000L, 100, null, testKey001, testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account ownerAccount = PublicMethed.queryAccount(contractAddress,blockingStubFull); - final Long ownerBalance = ownerAccount.getBalance(); - String methodStrSuicide = "SelfdestructTest(address)"; - String argsStrSuicide = "\"" + Base58.encode58Check(targetAddress) + "\""; - String txidSuicide = PublicMethed - .triggerContract(contractAddress, methodStrSuicide, argsStrSuicide, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional ex = PublicMethed.getTransactionInfoById(txidSuicide, - blockingStubFull); - Assert.assertEquals(ex.get().getResult(), TransactionInfo.code.SUCESS); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account targetAccountAfter = PublicMethed.queryAccount(targetAddress,blockingStubFull); - Frozen targetFrozenAfter = targetAccountAfter.getFrozen(0); - Long targetBalance = targetAccountAfter.getBalance() - 9_000000L; - Assert.assertEquals(targetFrozenBefore,targetFrozenAfter); - Assert.assertEquals(ownerBalance,targetBalance); - - } - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeTest001.java deleted file mode 100644 index b51208bd8e9..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/StakeTest001.java +++ /dev/null @@ -1,312 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tvmstake; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class StakeTest001 { - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - private String testWitnessKey = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private String testWitnessKey2 = Configuration.getByPath("testng.conf") - .getString("witness.key3"); - private byte[] testWitnessAddress = PublicMethed.getFinalAddress(testWitnessKey); - private byte[] testWitnessAddress2 = PublicMethed.getFinalAddress(testWitnessKey2); - - - - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private byte[] contractAddress; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed - .sendcoin(testAddress001, 1000_000_00000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/testStakeSuicide.sol"; - String contractName = "testStakeSuicide"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000_000_0000L, 100, null, testKey001, testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = false, description = "Vote for witness") - void tvmStakeTest001() { - long balanceBefore = PublicMethed.queryAccount(contractAddress, blockingStubFull).getBalance(); - String methodStr = "Stake(address,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testWitnessAddress) + "\"," + 1000000; - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = PublicMethed.getTransactionInfoById(txid,blockingStubFull); - int contractResult = ByteArray.toInt(info.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult,1); - - Account request = Account.newBuilder().setAddress(ByteString.copyFrom(contractAddress)).build(); - long balanceAfter = PublicMethed.queryAccount(contractAddress, blockingStubFull).getBalance(); - Assert.assertEquals(balanceAfter,balanceBefore - 1000000); - byte[] voteAddress = (blockingStubFull.getAccount(request).getVotesList().get(0) - .getVoteAddress().toByteArray()); - Assert.assertEquals(testWitnessAddress,voteAddress); - Assert.assertEquals(1,blockingStubFull.getAccount(request).getVotes(0).getVoteCount()); - - - - } - - @Test(enabled = false, description = "Non-witness account") - void tvmStakeTest002() { - //account address - String methodStr = "Stake(address,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testAddress001) + "\"," + 1000000; - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = PublicMethed.getTransactionInfoById(txid,blockingStubFull); - int contractResult = ByteArray.toInt(info.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult,0); - - //contract address - methodStr = "Stake(address,uint256)"; - argsStr = "\"" + Base58.encode58Check(contractAddress) + "\"," + 1000000; - txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - info = PublicMethed.getTransactionInfoById(txid,blockingStubFull); - contractResult = ByteArray.toInt(info.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult,0); - - - } - - - @Test(enabled = false, description = "Number of votes over balance") - void tvmStakeTest003() { - String methodStr = "Stake(address,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testWitnessAddress) + "\"," + Long.MAX_VALUE; - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = PublicMethed.getTransactionInfoById(txid,blockingStubFull); - int contractResult = ByteArray.toInt(info.get().getContractResult(0).toByteArray()); - - Assert.assertEquals(contractResult,0); - - } - - - @Test(enabled = false, description = "Enough votes for a second ballot") - void tvmStakeTest004() { - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String methodStr = "Stake(address,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testWitnessAddress) + "\"," + 21000000; - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = PublicMethed.getTransactionInfoById(txid,blockingStubFull); - int contractResult = ByteArray.toInt(info.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult,1); - Account request = Account.newBuilder().setAddress(ByteString.copyFrom(contractAddress)).build(); - byte[] voteAddress = (blockingStubFull.getAccount(request).getVotesList().get(0) - .getVoteAddress().toByteArray()); - Assert.assertEquals(testWitnessAddress,voteAddress); - System.out.println(blockingStubFull.getAccount(request).getVotesCount()); - Assert.assertEquals(21,blockingStubFull.getAccount(request).getVotes(0).getVoteCount()); - - argsStr = "\"" + Base58.encode58Check(testWitnessAddress) + "\"," + 11000000; - txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - info = PublicMethed.getTransactionInfoById(txid,blockingStubFull); - contractResult = ByteArray.toInt(info.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult,1); - request = Account.newBuilder().setAddress(ByteString.copyFrom(contractAddress)).build(); - voteAddress = (blockingStubFull.getAccount(request).getVotesList().get(0).getVoteAddress() - .toByteArray()); - Assert.assertEquals(testWitnessAddress,voteAddress); - Assert.assertEquals(11,blockingStubFull.getAccount(request).getVotes(0).getVoteCount()); - - } - - - @Test(enabled = false, description = "Revert test") - void tvmStakeTest005() { - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String methodStr = "revertTest1(address,uint256,address)"; - String argsStr = "\"" + Base58.encode58Check(testWitnessAddress) + "\"," + 1000000 + ",\"" - + Base58.encode58Check(testAddress001) + "\""; - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = PublicMethed.getTransactionInfoById(txid,blockingStubFull); - int contractResult = ByteArray.toInt(info.get().getContractResult(0).toByteArray()); - - Assert.assertEquals(contractResult,0); - - } - - - @Test(enabled = false, description = "Contract Call Contract stake") - void tvmStakeTest006() { - String methodStr = "deployB()"; - String argsStr = ""; - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("txid:" + txid); - - methodStr = "BStake(address,uint256)"; - argsStr = "\"" + Base58.encode58Check(testWitnessAddress) + "\"," + 1000000; - txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long callvalue = 1000000000L; - txid = PublicMethed.triggerContract(contractAddress, "deployB()", "#", false, - callvalue, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - String addressHex = - "41" + ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()) - .substring(24); - byte[] contractAddressB = ByteArray.fromHexString(addressHex); - long contractAddressBBalance = PublicMethed.queryAccount(contractAddressB, blockingStubFull) - .getBalance(); - Assert.assertEquals(callvalue, contractAddressBBalance); - - methodStr = "BStake(address,uint256)"; - argsStr = "\"" + Base58.encode58Check(testWitnessAddress) + "\"," + 10000000; - txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - int contractResult = ByteArray.toInt(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult, 1); - Account account = PublicMethed.queryAccount(contractAddressB, blockingStubFull); - long frozenBalance = account.getFrozen(0).getFrozenBalance(); - byte[] voteAddress = account.getVotes(0).getVoteAddress().toByteArray(); - long voteCount = account.getVotes(0).getVoteCount(); - long balanceAfter = account.getBalance(); - Assert.assertEquals(voteCount, 10); - Assert.assertEquals(voteAddress, testWitnessAddress); - Assert.assertEquals(frozenBalance, 10000000); - Assert.assertEquals(balanceAfter, contractAddressBBalance - 10000000); - - } - - @Test(enabled = false, description = "Vote for the first witness and then vote for the second " - + "witness.") - void tvmStakeTest007() { - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String methodStr = "Stake(address,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testWitnessAddress) + "\"," + 21000000; - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = PublicMethed.getTransactionInfoById(txid,blockingStubFull); - int contractResult = ByteArray.toInt(info.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult,1); - Account request = Account.newBuilder().setAddress(ByteString.copyFrom(contractAddress)).build(); - byte[] voteAddress = (blockingStubFull.getAccount(request).getVotesList().get(0) - .getVoteAddress().toByteArray()); - Assert.assertEquals(testWitnessAddress,voteAddress); - System.out.println(blockingStubFull.getAccount(request).getVotesCount()); - Assert.assertEquals(21,blockingStubFull.getAccount(request).getVotes(0).getVoteCount()); - - argsStr = "\"" + Base58.encode58Check(testWitnessAddress2) + "\"," + 11000000; - txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - info = PublicMethed.getTransactionInfoById(txid,blockingStubFull); - contractResult = ByteArray.toInt(info.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult,1); - request = Account.newBuilder().setAddress(ByteString.copyFrom(contractAddress)).build(); - voteAddress = (blockingStubFull.getAccount(request).getVotesList().get(0).getVoteAddress() - .toByteArray()); - Assert.assertEquals(testWitnessAddress2,voteAddress); - Assert.assertEquals(11,blockingStubFull.getAccount(request).getVotes(0).getVoteCount()); - - } - -} - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/UnStakeTest001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/UnStakeTest001.java deleted file mode 100644 index c738b9ad3d7..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/tvmstake/UnStakeTest001.java +++ /dev/null @@ -1,471 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.tvmstake; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class UnStakeTest001 { - - private String testFoundationKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private byte[] testFoundationAddress = PublicMethed.getFinalAddress(testFoundationKey); - private String testWitnessKey = Configuration.getByPath("testng.conf") - .getString("witness.key4"); - private byte[] testWitnessAddress = PublicMethed.getFinalAddress(testWitnessKey); - - - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] testAddress001 = ecKey1.getAddress(); - String testKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] testAddress002 = ecKey2.getAddress(); - private String testKey002 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private byte[] contractAddress; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - PublicMethed.printAddress(testKey001); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = false, description = "unstake normal") - public void tvmStakeTest001Normal() { - PublicMethed - .sendcoin(testAddress001, 1120_000_000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "./src/test/resources/soliditycode/unStake001.sol"; - String contractName = "unStakeTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 1000000000L, 100, null, - testKey001, testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String methodStr = "Stake(address,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testWitnessAddress) + "\"," + 10000000; - long balanceBefore = PublicMethed.queryAccount(contractAddress, blockingStubFull).getBalance(); - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - int contractResult = ByteArray.toInt(info.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult, 1); - Account account = PublicMethed.queryAccount(contractAddress, blockingStubFull); - long balanceAfter = account.getBalance(); - Assert.assertEquals(balanceAfter, balanceBefore - 10000000); - long frozenBalance = account.getFrozen(0).getFrozenBalance(); - byte[] voteAddress = account.getVotes(0).getVoteAddress().toByteArray(); - long voteCount = account.getVotes(0).getVoteCount(); - Assert.assertEquals(voteCount, 10); - Assert.assertEquals(voteAddress, testWitnessAddress); - Assert.assertEquals(frozenBalance, 10000000); - - methodStr = "unStake()"; - txid = PublicMethed - .triggerContract(contractAddress, methodStr, "#", false, 0, maxFeeLimit, testAddress001, - testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - contractResult = ByteArray.toInt(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult, 1); - account = PublicMethed.queryAccount(contractAddress, blockingStubFull); - int frozenCount = account.getFrozenCount(); - int votesCount = account.getVotesCount(); - Assert.assertEquals(0, frozenCount); - Assert.assertEquals(0, votesCount); - Assert.assertEquals(account.getBalance(), balanceBefore); - } - - @Test(enabled = false, description = "unstake when no stake") - public void tvmUnstakeTest002NoStake() { - PublicMethed - .sendcoin(testAddress001, 1120_000_000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "./src/test/resources/soliditycode/unStake001.sol"; - String contractName = "unStakeTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 1000000000L, 100, null, - testKey001, testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String methodStr = "unStake()"; - long balanceBefore = PublicMethed.queryAccount(contractAddress, blockingStubFull).getBalance(); - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, "", false, 0, maxFeeLimit, testAddress001, - testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Account account = PublicMethed.queryAccount(contractAddress, blockingStubFull); - Assert.assertEquals(account.getBalance(), balanceBefore); - int contractResult = ByteArray.toInt(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult, 0); - int frozenCount = account.getFrozenCount(); - int votesCount = account.getVotesCount(); - Assert.assertEquals(0, frozenCount); - Assert.assertEquals(0, votesCount); - } - - @Test(enabled = false, description = "unstake twice") - public void tvmUnstakeTest003UnstakeTwice() { - PublicMethed - .sendcoin(testAddress001, 1120_000_000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "./src/test/resources/soliditycode/unStake001.sol"; - String contractName = "unStakeTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 1000000000L, 100, null, - testKey001, testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String methodStr = "Stake(address,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testWitnessAddress) + "\"," + 10000000; - long balanceBefore = PublicMethed.queryAccount(contractAddress, blockingStubFull).getBalance(); - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - int contractResult = ByteArray.toInt(info.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult, 1); - Account account = PublicMethed.queryAccount(contractAddress, blockingStubFull); - long balanceAfter = account.getBalance(); - Assert.assertEquals(balanceAfter, balanceBefore - 10000000); - long frozenBalance = account.getFrozen(0).getFrozenBalance(); - byte[] voteAddress = account.getVotes(0).getVoteAddress().toByteArray(); - long voteCount = account.getVotes(0).getVoteCount(); - Assert.assertEquals(voteCount, 10); - Assert.assertEquals(voteAddress, testWitnessAddress); - Assert.assertEquals(frozenBalance, 10000000); - - methodStr = "unStake2()"; - txid = PublicMethed - .triggerContract(contractAddress, methodStr, "", false, 0, maxFeeLimit, testAddress001, - testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - contractResult = ByteArray.toInt(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult, 0); - account = PublicMethed.queryAccount(contractAddress, blockingStubFull); - int frozenCount = account.getFrozenCount(); - int votesCount = account.getVotesCount(); - Assert.assertEquals(0, frozenCount); - Assert.assertEquals(0, votesCount); - Assert.assertEquals(account.getBalance(), balanceBefore); - } - - @Test(enabled = false, description = "unstake revert") - public void tvmUnstakeTest004Revert() { - PublicMethed - .sendcoin(testAddress001, 1120_000_000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "./src/test/resources/soliditycode/unStake001.sol"; - String contractName = "unStakeTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 1000000000L, 100, null, - testKey001, testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String methodStr = "Stake(address,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testWitnessAddress) + "\"," + 10000000; - long balanceBefore = PublicMethed.queryAccount(contractAddress, blockingStubFull).getBalance(); - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - int contractResult = ByteArray.toInt(info.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult, 1); - Account account = PublicMethed.queryAccount(contractAddress, blockingStubFull); - long balanceAfter = account.getBalance(); - Assert.assertEquals(balanceAfter, balanceBefore - 10000000); - long frozenBalance = account.getFrozen(0).getFrozenBalance(); - byte[] voteAddress = account.getVotes(0).getVoteAddress().toByteArray(); - long voteCount = account.getVotes(0).getVoteCount(); - Assert.assertEquals(voteCount, 10); - Assert.assertEquals(voteAddress, testWitnessAddress); - Assert.assertEquals(frozenBalance, 10000000); - - methodStr = "revertTest2(address)"; - argsStr = "\"" + Base58.encode58Check(testAddress002) + "\""; - txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, false, 0, maxFeeLimit, testAddress001, - testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - contractResult = ByteArray.toInt(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult, 0); - account = PublicMethed.queryAccount(contractAddress, blockingStubFull); - int frozenCount = account.getFrozenCount(); - int votesCount = account.getVotesCount(); - Assert.assertEquals(0, frozenCount); - Assert.assertEquals(0, votesCount); - Assert.assertEquals(account.getBalance(), 993000000L); - long balance = PublicMethed.queryAccount(testAddress002, blockingStubFull).getBalance(); - Assert.assertEquals(7000000L, balance); - } - - @Test(enabled = false, description = "unstake call another contract in one contract") - public void tvmUnstakeTest005CallAnotherInOneContract() { - PublicMethed - .sendcoin(testAddress001, 2120_000_000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "./src/test/resources/soliditycode/unStake001.sol"; - String contractName = "unStakeTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 1000000000L, 100, null, - testKey001, testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long callvalue = 1000000000L; - String txid = PublicMethed.triggerContract(contractAddress, "deployB()", "#", false, - callvalue, maxFeeLimit, testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - String addressHex = - "41" + ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()) - .substring(24); - logger.info("address_hex: " + addressHex); - byte[] contractAddressB = ByteArray.fromHexString(addressHex); - logger.info("contractAddressB: " + Base58.encode58Check(contractAddressB)); - long contractAddressBBalance = PublicMethed.queryAccount(contractAddressB, blockingStubFull) - .getBalance(); - Assert.assertEquals(callvalue, contractAddressBBalance); - - String methodStr = "BStake(address,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testWitnessAddress) + "\"," + 10000000; - txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - int contractResult = ByteArray.toInt(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult, 1); - Account account = PublicMethed.queryAccount(contractAddressB, blockingStubFull); - long frozenBalance = account.getFrozen(0).getFrozenBalance(); - byte[] voteAddress = account.getVotes(0).getVoteAddress().toByteArray(); - long voteCount = account.getVotes(0).getVoteCount(); - long balanceAfter = account.getBalance(); - Assert.assertEquals(voteCount, 10); - Assert.assertEquals(voteAddress, testWitnessAddress); - Assert.assertEquals(frozenBalance, 10000000); - Assert.assertEquals(balanceAfter, contractAddressBBalance - 10000000); - long contractAddressBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(contractAddressBalance, 1000000000); - - methodStr = "BUnStake()"; - txid = PublicMethed - .triggerContract(contractAddress, methodStr, "", false, 0, maxFeeLimit, testAddress001, - testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - contractResult = ByteArray.toInt(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult, 1); - account = PublicMethed.queryAccount(contractAddressB, blockingStubFull); - int frozenCount = account.getFrozenCount(); - int votesCount = account.getVotesCount(); - Assert.assertEquals(0, frozenCount); - Assert.assertEquals(0, votesCount); - Assert.assertEquals(account.getBalance(), contractAddressBBalance); - contractAddressBalance = PublicMethed.queryAccount(contractAddress, blockingStubFull) - .getBalance(); - Assert.assertEquals(contractAddressBalance, 1000000000); - } - - @Test(enabled = false, description = "unstake with reward balance") - public void tvmUnstakeTest006WithRewardBalance() { - PublicMethed - .sendcoin(testAddress001, 1120_000_000L, testFoundationAddress, testFoundationKey, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "./src/test/resources/soliditycode/unStake001.sol"; - String contractName = "unStakeTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 1000000000L, 100, null, - testKey001, testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String methodStr = "Stake(address,uint256)"; - String argsStr = "\"" + Base58.encode58Check(testWitnessAddress) + "\"," + 10000000; - long balanceBefore = PublicMethed.queryAccount(contractAddress, blockingStubFull).getBalance(); - String txid = PublicMethed - .triggerContract(contractAddress, methodStr, argsStr, - false, 0, maxFeeLimit, - testAddress001, testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional info = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - int contractResult = ByteArray.toInt(info.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult, 1); - Account account = PublicMethed.queryAccount(contractAddress, blockingStubFull); - long balanceAfter = account.getBalance(); - Assert.assertEquals(balanceAfter, balanceBefore - 10000000); - long frozenBalance = account.getFrozen(0).getFrozenBalance(); - byte[] voteAddress = account.getVotes(0).getVoteAddress().toByteArray(); - long voteCount = account.getVotes(0).getVoteCount(); - Assert.assertEquals(voteCount, 10); - Assert.assertEquals(voteAddress, testWitnessAddress); - Assert.assertEquals(frozenBalance, 10000000); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - methodStr = "rewardBalance(address)"; - argsStr = "\"" + Base58.encode58Check(contractAddress) + "\""; - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, methodStr, argsStr, false, 0, 0, "0", - 0, testAddress001, testKey001, blockingStubFull); - Transaction transaction = transactionExtention.getTransaction(); - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - org.junit.Assert.assertEquals(0, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result)))); - - methodStr = "withdrawReward()"; - txid = PublicMethed - .triggerContract(contractAddress, methodStr, "", false, 0, maxFeeLimit, testAddress001, - testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - contractResult = ByteArray.toInt(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult, 0); - account = PublicMethed.queryAccount(contractAddress, blockingStubFull); - long balanceAfter2 = account.getBalance(); - Assert.assertEquals(balanceAfter, balanceAfter2); - - methodStr = "unStake2()"; - txid = PublicMethed - .triggerContract(contractAddress, methodStr, "", false, 0, maxFeeLimit, testAddress001, - testKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(infoById.toString()); - Assert.assertEquals(0, infoById.get().getResultValue()); - contractResult = ByteArray.toInt(infoById.get().getContractResult(0).toByteArray()); - Assert.assertEquals(contractResult, 0); - account = PublicMethed.queryAccount(contractAddress, blockingStubFull); - int frozenCount = account.getFrozenCount(); - int votesCount = account.getVotesCount(); - Assert.assertEquals(0, frozenCount); - Assert.assertEquals(0, votesCount); - Assert.assertEquals(account.getBalance(), balanceBefore); - - methodStr = "rewardBalance(address)"; - argsStr = "\"" + Base58.encode58Check(contractAddress) + "\""; - transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddress, methodStr, argsStr, false, 0, 0, "0", - 0, testAddress001, testKey001, blockingStubFull); - transaction = transactionExtention.getTransaction(); - result = transactionExtention.getConstantResult(0).toByteArray(); - System.out.println("message:" + transaction.getRet(0).getRet()); - System.out.println( - ":" + ByteArray.toStr(transactionExtention.getResult().getMessage().toByteArray())); - System.out.println("Result:" + Hex.toHexString(result)); - org.junit.Assert.assertEquals(0, ByteArray.toLong(ByteArray - .fromHexString(Hex - .toHexString(result)))); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - PublicMethed.freedResource(testAddress001, testKey001, testFoundationAddress, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign001.java deleted file mode 100644 index 831679cb4de..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign001.java +++ /dev/null @@ -1,506 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.validatemultisign; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; -import stest.tron.wallet.common.client.utils.Sha256Hash; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class TestValidatemultisign001 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ByteString assetAccountId1; - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[2]; - String accountPermissionJson = ""; - ECKey ecKey001 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey001.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey001.getPrivKeyBytes()); - ECKey ecKey002 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey002.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey002.getPrivKeyBytes()); - ECKey ecKey003 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey003.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey003.getPrivKeyBytes()); - ECKey ecKey004 = new ECKey(Utils.getRandom()); - byte[] participateAddress = ecKey004.getAddress(); - String participateKey = ByteArray.toHexString(ecKey004.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private byte[] contractAddress = null; - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - @Test(enabled = true, description = "Deploy validatemultisign contract") - public void test001DeployContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1000_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 100_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(dev001Key, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = accountResource.getEnergyUsed(); - Long beforeNetUsed = accountResource.getNetUsed(); - Long beforeFreeNetUsed = accountResource.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/validatemultisign001.sol"; - String contractName = "validatemultisignTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - PublicMethed.printAddress(ownerKey); - - long needCoin = updateAccountPermissionFee * 1 + multiSignFee * 3; - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needCoin + 2048000000L, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - - logger.info(accountPermissionJson); - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Trigger validatemultisign contract with " - + "Permission(address) case") - public void test002validatemultisign() { - List signatures = new ArrayList<>(); - - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - - Transaction transaction = PublicMethedForMutiSign.sendcoinGetTransaction( - fromAddress, 1L, ownerAddress, ownerKey, blockingStubFull, ownerKeyString); - byte[] hash = Sha256Hash.of(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()).getBytes(); - - byte[] merged = ByteUtil.merge(ownerAddress, ByteArray.fromInt(0), hash); - byte[] tosign = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), merged); - - signatures.add(Hex.toHexString(ecKey003.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - - // Trigger with correct Permission address - List parameters = Arrays.asList(StringUtil.encode58Check(ownerAddress), - 0, "0x" + Hex.toHexString(hash), signatures); - String input = PublicMethed.parametersString(parameters); - - String methodStr = "testmulti(address,uint256,bytes32,bytes[])"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(1, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - // Trigger with wrong Permission address - merged = ByteUtil.merge(dev001Address, ByteArray.fromInt(0), hash); - tosign = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), merged); - - signatures.clear(); - signatures.add(Hex.toHexString(ecKey003.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - - parameters = Arrays.asList(StringUtil.encode58Check(dev001Address), - 0, "0x" + Hex.toHexString(hash), signatures); - input = PublicMethed.parametersString(parameters); - - TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(0, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - // Trigger with address that have not permission - merged = ByteUtil.merge(fromAddress, ByteArray.fromInt(0), hash); - tosign = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), merged); - - signatures.clear(); - signatures.add(Hex.toHexString(ecKey003.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - - parameters = Arrays.asList(StringUtil.encode58Check(fromAddress), - 0, "0x" + Hex.toHexString(hash), signatures); - input = PublicMethed.parametersString(parameters); - - TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(0, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - // Trigger with not exist address - merged = ByteUtil.merge(manager1Address, ByteArray.fromInt(0), hash); - tosign = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), merged); - - signatures.clear(); - signatures.add(Hex.toHexString(ecKey003.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - - parameters = Arrays.asList(StringUtil.encode58Check(manager1Address), - 0, "0x" + Hex.toHexString(hash), signatures); - input = PublicMethed.parametersString(parameters); - - TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(0, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - // Trigger with error format address - merged = ByteUtil.merge(manager1Address, ByteArray.fromInt(0), hash); - tosign = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), merged); - - signatures.clear(); - signatures.add(Hex.toHexString(ecKey003.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - - parameters = Arrays.asList("TVgXWwGWE9huXiE4FuzDuGnCPUowsbZ8VZ", - 0, "0x" + Hex.toHexString(hash), signatures); - input = PublicMethed.parametersString(parameters); - - TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(0, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "Trigger validatemultisign contract with " - + "Permission(permissionId) case") - public void test003validatemultisign() { - List signatures = new ArrayList<>(); - - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - - Transaction transaction = PublicMethedForMutiSign.sendcoinGetTransaction( - fromAddress, 1L, ownerAddress, ownerKey, blockingStubFull, ownerKeyString); - byte[] hash = Sha256Hash.of(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()).getBytes(); - - // Trigger with wrong PermissionID - long permissionId = 2; - - byte[] merged = ByteUtil.merge(ownerAddress, ByteArray.fromLong(permissionId), hash); - byte[] tosign = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), merged); - - signatures.add(Hex.toHexString(ecKey003.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - - List parameters = Arrays.asList(StringUtil.encode58Check(ownerAddress), - permissionId, "0x" + Hex.toHexString(hash), signatures); - String input = PublicMethed.parametersString(parameters); - - String methodStr = "testmulti(address,uint256,bytes32,bytes[])"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(0, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - // Trigger with error format PermissionID - permissionId = 100; - merged = ByteUtil.merge(ownerAddress, ByteArray.fromLong(permissionId), hash); - tosign = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), merged); - - signatures.clear(); - signatures.add(Hex.toHexString(ecKey003.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - - parameters = Arrays.asList(StringUtil.encode58Check(ownerAddress), - permissionId, "0x" + Hex.toHexString(hash), signatures); - input = PublicMethed.parametersString(parameters); - - TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(0, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - // Trigger with Long.MAX_VALUE + 1 PermissionID - permissionId = Long.MAX_VALUE + 1; - merged = ByteUtil.merge(ownerAddress, ByteArray.fromLong(permissionId), hash); - tosign = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), merged); - - signatures.clear(); - signatures.add(Hex.toHexString(ecKey003.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - - parameters = Arrays.asList(StringUtil.encode58Check(ownerAddress), - permissionId, "0x" + Hex.toHexString(hash), signatures); - input = PublicMethed.parametersString(parameters); - - TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(0, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - // Trigger with Long.MIN_VALUE - 1 PermissionID - permissionId = Long.MIN_VALUE - 1; - merged = ByteUtil.merge(ownerAddress, ByteArray.fromLong(permissionId), hash); - tosign = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), merged); - - signatures.clear(); - signatures.add(Hex.toHexString(ecKey003.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - - parameters = Arrays.asList(StringUtil.encode58Check(ownerAddress), - permissionId, "0x" + Hex.toHexString(hash), signatures); - input = PublicMethed.parametersString(parameters); - - TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(0, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "Trigger validatemultisign contract with " - + "Permission(hash) case") - public void test004validatemultisign() { - List signatures = new ArrayList<>(); - - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - - Transaction transaction = PublicMethedForMutiSign.sendcoinWithPermissionIdNotSign( - fromAddress, 1L, ownerAddress, 0, ownerKey, blockingStubFull); - transaction = TransactionUtils.setTimestamp(transaction); - byte[] hash = Sha256Hash.of(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()).getBytes(); - - byte[] merged = ByteUtil.merge(ownerAddress, ByteArray.fromInt(0), hash); - byte[] tosign = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), merged); - - signatures.add(Hex.toHexString(ecKey003.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - - // Trigger with no sign hash - List parameters = Arrays.asList(StringUtil.encode58Check(ownerAddress), - 0, "0x" + Hex.toHexString(hash), signatures); - String input = PublicMethed.parametersString(parameters); - - String methodStr = "testmulti(address,uint256,bytes32,bytes[])"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(1, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - // Trigger with wrong hash - transaction = PublicMethedForMutiSign.sendcoinWithPermissionIdNotSign( - fromAddress, 1L, ownerAddress, 0, ownerKey, blockingStubFull); - logger.info("hash: {}", Sha256Hash.of(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()).getBytes()); - - hash = Sha256Hash.of(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()).getBytes(); - - merged = ByteUtil.merge(ownerAddress, ByteArray.fromInt(0), hash); - tosign = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), merged); - - signatures.clear(); - signatures.add(Hex.toHexString(ecKey003.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - - transaction = TransactionUtils.setTimestamp(transaction); - hash = Sha256Hash.of(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()).getBytes(); - - parameters = Arrays.asList(StringUtil.encode58Check(ownerAddress), - 0, "0x" + Hex.toHexString(hash), signatures); - input = PublicMethed.parametersString(parameters); - - TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(0, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - // 1) address B create transaction_1, but address A`s permission address sign - // 2) user address A verify transaction_1 that created by B - transaction = PublicMethedForMutiSign.sendcoinWithPermissionIdNotSign( - fromAddress, 1L, dev001Address, 0, dev001Key, blockingStubFull); - transaction = TransactionUtils.setTimestamp(transaction); - - hash = Sha256Hash.of(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()).getBytes(); - - merged = ByteUtil.merge(ownerAddress, ByteArray.fromInt(0), hash); - tosign = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), merged); - - signatures.clear(); - signatures.add(Hex.toHexString(ecKey003.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - - parameters = Arrays.asList(StringUtil.encode58Check(ownerAddress), - 0, "0x" + Hex.toHexString(hash), signatures); - input = PublicMethed.parametersString(parameters); - - TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(1, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign002.java deleted file mode 100644 index c4350af2c07..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign002.java +++ /dev/null @@ -1,378 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.validatemultisign; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; -import stest.tron.wallet.common.client.utils.Sha256Hash; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class TestValidatemultisign002 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ByteString assetAccountId1; - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[2]; - String accountPermissionJson = ""; - ECKey ecKey001 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey001.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey001.getPrivKeyBytes()); - ECKey ecKey002 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey002.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey002.getPrivKeyBytes()); - ECKey ecKey003 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey003.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey003.getPrivKeyBytes()); - ECKey ecKey004 = new ECKey(Utils.getRandom()); - byte[] manager4Address = ecKey004.getAddress(); - String manager4Key = ByteArray.toHexString(ecKey004.getPrivKeyBytes()); - ECKey ecKey005 = new ECKey(Utils.getRandom()); - byte[] manager5Address = ecKey005.getAddress(); - String manager5Key = ByteArray.toHexString(ecKey005.getPrivKeyBytes()); - ECKey ecKey006 = new ECKey(Utils.getRandom()); - byte[] manager6Address = ecKey006.getAddress(); - String manager6Key = ByteArray.toHexString(ecKey006.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private byte[] contractAddress = null; - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - @Test(enabled = true, description = "Deploy validatemultisign contract") - public void test001DeployContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1000_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 100_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(dev001Key, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = accountResource.getEnergyUsed(); - Long beforeNetUsed = accountResource.getNetUsed(); - Long beforeFreeNetUsed = accountResource.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/validatemultisign001.sol"; - String contractName = "validatemultisignTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - PublicMethed.printAddress(ownerKey); - - long needCoin = updateAccountPermissionFee * 1 + multiSignFee * 3; - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needCoin + 2048000000L, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":3," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":2}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":3}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager4Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager5Key) + "\",\"weight\":1}," - + "]}]}"; - - logger.info(accountPermissionJson); - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Trigger validatemultisign with signatures num") - public void test002validatemultisign() { - List signatures = new ArrayList<>(); - int permissionId = 2; - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - - Transaction transaction = PublicMethedForMutiSign.sendcoinWithPermissionIdNotSign( - fromAddress, 1L, ownerAddress, permissionId, ownerKey, blockingStubFull); - transaction = TransactionUtils.setTimestamp(transaction); - byte[] hash = Sha256Hash.of(CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray()).getBytes(); - - byte[] merged = ByteUtil.merge(ownerAddress, ByteArray.fromInt(permissionId), hash); - byte[] tosign = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), merged); - signatures.add(Hex.toHexString(ecKey003.sign(tosign).toByteArray())); - - // Trigger with one signature - List parameters = Arrays.asList(StringUtil.encode58Check(ownerAddress), - permissionId, "0x" + Hex.toHexString(hash), signatures); - String input = PublicMethed.parametersString(parameters); - - String methodStr = "testmulti(address,uint256,bytes32,bytes[])"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(1, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - // Trigger with five signature - signatures.clear(); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey002.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey003.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey004.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey005.sign(tosign).toByteArray())); - - parameters = Arrays.asList(StringUtil.encode58Check(ownerAddress), - permissionId, "0x" + Hex.toHexString(hash), signatures); - input = PublicMethed.parametersString(parameters); - - TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(1, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - // Trigger with six signature - signatures.clear(); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey002.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey003.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey004.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey005.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey006.sign(tosign).toByteArray())); - - parameters = Arrays.asList(StringUtil.encode58Check(ownerAddress), - permissionId, "0x" + Hex.toHexString(hash), signatures); - input = PublicMethed.parametersString(parameters); - - TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(0, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - } - - @Test(enabled = true, description = "Trigger validatemultisign with Duplicate signatures") - public void test003validatemultisign() { - List signatures = new ArrayList<>(); - int permissionId = 2; - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - - Transaction transaction = PublicMethedForMutiSign.sendcoinWithPermissionIdNotSign( - fromAddress, 1L, ownerAddress, permissionId, ownerKey, blockingStubFull); - transaction = TransactionUtils.setTimestamp(transaction); - byte[] hash = Sha256Hash.of(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()).getBytes(); - - byte[] merged = ByteUtil.merge(ownerAddress, ByteArray.fromInt(permissionId), hash); - byte[] tosign = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), merged); - - // signatures with Duplicate signatures but weight enough - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey002.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey004.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey004.sign(tosign).toByteArray())); - - List parameters = Arrays.asList(StringUtil.encode58Check(ownerAddress), - permissionId, "0x" + Hex.toHexString(hash), signatures); - String input = PublicMethed.parametersString(parameters); - - String methodStr = "testmulti(address,uint256,bytes32,bytes[])"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(1, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - // Trigger with Duplicate signatures and weight not enough - signatures.clear(); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey004.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey004.sign(tosign).toByteArray())); - - parameters = Arrays.asList(StringUtil.encode58Check(ownerAddress), - permissionId, "0x" + Hex.toHexString(hash), signatures); - input = PublicMethed.parametersString(parameters); - - TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(0, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - // Trigger with Duplicate signatures and fix signatures - signatures.clear(); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey004.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey004.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey005.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey005.sign(tosign).toByteArray())); - - parameters = Arrays.asList(StringUtil.encode58Check(ownerAddress), - permissionId, "0x" + Hex.toHexString(hash), signatures); - input = PublicMethed.parametersString(parameters); - - TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(0, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - } - - @Test(enabled = true, description = "Trigger validatemultisign with weight") - public void test004validatemultisign() { - List signatures = new ArrayList<>(); - int permissionId = 2; - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - - Transaction transaction = PublicMethedForMutiSign.sendcoinWithPermissionIdNotSign( - fromAddress, 1L, ownerAddress, permissionId, ownerKey, blockingStubFull); - transaction = TransactionUtils.setTimestamp(transaction); - byte[] hash = Sha256Hash.of(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()).getBytes(); - - byte[] merged = ByteUtil.merge(ownerAddress, ByteArray.fromInt(permissionId), hash); - byte[] tosign = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), merged); - - // signatures with weight not enough - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey004.sign(tosign).toByteArray())); - - List parameters = Arrays.asList(StringUtil.encode58Check(ownerAddress), - permissionId, "0x" + Hex.toHexString(hash), signatures); - String input = PublicMethed.parametersString(parameters); - - String methodStr = "testmulti(address,uint256,bytes32,bytes[])"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, input, false, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(0, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign003.java deleted file mode 100644 index a1adf048b8a..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/validatemultisign/TestValidatemultisign003.java +++ /dev/null @@ -1,242 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.validatemultisign; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.Sha256Hash; -import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.AbiUtil; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class TestValidatemultisign003 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ByteString assetAccountId1; - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[2]; - String accountPermissionJson = ""; - ECKey ecKey001 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey001.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey001.getPrivKeyBytes()); - ECKey ecKey002 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey002.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey002.getPrivKeyBytes()); - ECKey ecKey003 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey003.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey003.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private byte[] contractAddress = null; - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] dev001Address = ecKey1.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - } - - @Test(enabled = true, description = "Deploy validatemultisign contract") - public void test001DeployContract() { - Assert.assertTrue(PublicMethed.sendcoin(dev001Address, 1000_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, 100_000_000L, - 0, 0, ByteString.copyFrom(dev001Address), testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(dev001Key, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = accountResource.getEnergyUsed(); - Long beforeNetUsed = accountResource.getNetUsed(); - Long beforeFreeNetUsed = accountResource.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/validatemultisign001.sol"; - String contractName = "validatemultisignTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - PublicMethed.printAddress(ownerKey); - - long needCoin = updateAccountPermissionFee * 1 + multiSignFee * 3; - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needCoin + 2048000000L, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - - logger.info(accountPermissionJson); - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Trigger validatemultisign precompiled contract, " - + "with wrong hash bytes") - public void test002validatemultisign() { - List signatures = new ArrayList<>(); - - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - - Transaction transaction = PublicMethedForMutiSign.sendcoinGetTransaction( - fromAddress, 1L, ownerAddress, ownerKey, blockingStubFull, ownerKeyString); - byte[] hash = Sha256Hash.of(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()).getBytes(); - - byte[] merged = ByteUtil.merge(ownerAddress, ByteArray.fromInt(0), hash); - byte[] tosign = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), merged); - signatures.add(Hex.toHexString(ecKey003.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - - List parameters = Arrays.asList(StringUtil.encode58Check(ownerAddress), - 0, "0x" + Hex.toHexString(hash), signatures); - String argsStr = PublicMethed.parametersString(parameters); - - byte[] inputBytesArray = Hex.decode(AbiUtil.parseMethod( - "validatemultisign(address,uint256,bytes32,bytes[])", argsStr, false)); - String input = ByteArray.toHexString(inputBytesArray); - - String methodStr = "testMultiPrecompileContract(bytes)"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, - AbiUtil.parseParameters(methodStr, Arrays.asList(input)), true, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(0, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - } - - @Test(enabled = true, description = "Trigger validatemultisign precompiled contract, " - + "with correct hash bytes") - public void test003validatemultisign() { - List signatures = new ArrayList<>(); - - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - - Transaction transaction = PublicMethedForMutiSign.sendcoinGetTransaction( - fromAddress, 1L, ownerAddress, ownerKey, blockingStubFull, ownerKeyString); - byte[] hash = Sha256Hash.of(CommonParameter.getInstance() - .isECKeyCryptoEngine(), transaction.getRawData().toByteArray()).getBytes(); - - byte[] merged = ByteUtil.merge(ownerAddress, ByteArray.fromInt(0), hash); - byte[] tosign = Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), merged); - - signatures.add(Hex.toHexString(ecKey003.sign(tosign).toByteArray())); - signatures.add(Hex.toHexString(ecKey001.sign(tosign).toByteArray())); - - List parameters = Arrays.asList(StringUtil.encode58Check(ownerAddress), - 0, "0x" + Hex.toHexString(hash), signatures); - String argsStr = PublicMethed.parametersString(parameters); - - String input = AbiUtil.parseParameters( - "validatemultisign(address,uint256,bytes32,bytes[])", argsStr); - - String methodStr = "testMultiPrecompileContract(bytes)"; - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methodStr, - AbiUtil.parseParameters(methodStr, Arrays.asList(input)), true, - 0, maxFeeLimit, dev001Address, dev001Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - infoById = PublicMethed.getTransactionInfoById(TriggerTxid, blockingStubFull); - logger.info("infoById" + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals(1, ByteArray.toInt(infoById.get().getContractResult(0).toByteArray())); - - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/VerifyBurnProof001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/VerifyBurnProof001.java deleted file mode 100644 index 3acb6f21b44..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/VerifyBurnProof001.java +++ /dev/null @@ -1,326 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.zenProofCommand; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class VerifyBurnProof001 { - - private final String foundationKey001 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] foundationAddress001 = PublicMethed.getFinalAddress(foundationKey001); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] testAddress001 = ecKey1.getAddress(); - private String testPriKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(testPriKey001); - Assert.assertTrue(PublicMethed.sendcoin(testAddress001, 1000_000_000L, foundationAddress001, - foundationKey001, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Deploy VerfyMintProof contract ") - public void verifyBurnProof001() { - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(testAddress001, - blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(testPriKey001, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = accountResource.getEnergyUsed(); - Long beforeNetUsed = accountResource.getNetUsed(); - Long beforeFreeNetUsed = accountResource.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/VerifyBurnProof001.sol"; - String contractName = "VerifyBurnProof001Test"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, testPriKey001, - testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - Assert.assertEquals(0, infoById.get().getResultValue()); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - } - - @Test(enabled = true, description = "data length != 512") - public void verifyBurnProofTest002() { - - String argsStr = "\"" - + "c9cf924134dd8fbd11d3b245b00adf4797b48c42e001673e7c566ce229b8fdf6" - + "24097774778540c2c4d5acbeffe333e1f595a1b731cbe10848e3d3a527ba4d1b" - + "a079c66e70cae2225cd702a7c0977635755ad104a87f435634d4e5382ac2afc8" - + "1c47919273d4861ad815855ba1b4db5f90cc7e922b65c930c291eddc6d49a6c4" - + "90771325afc8e6e4a506f9dca0889dff75bcb4c46030702a33899b4d1e81122a" - + "a236433cf4c8ff426c66446de2f375b08575c4a18802e19a5fa5500922f7d570" - + "aac680208d05f9f2a9beaef0d9adede10e4a0242a3d1e048dd2a65034ef3f348" - + "0c108652d93da2ed13a0720fce9dce3a01a25cfa898bbaa8730f3fa8bba4b8a9" - + "7a609fd9f4d008a9334dea39acc838298c989ae0f31cbaa08e4b00342ba2c0b1" - + "ba37ac7be8084e0aeb01045f121e87e9cc942ecdc3b5e52933b79aad6f005d8e" - - + "dfc2aabf584106dfb2f6d3eb7f4584f5f2d9cba8340b0f73ba5fab4a4a024db2" - + "d00c5f0b3aba1f98cba6d1c9750591628daca165bac2de6fd694df833110ee01" - - + "0000000000000000000000000000000000000000000000000000000000000064" - - + "19389f87908cb5f1ede2a9fe0c3047d2ad5fce424d133bacb655ae1179a81084" - + "102ce5ad22d815a64374da9e2207d722b1c9a3099b292eaea0862edc886ff70d" - - + "b85285dd55258a2fbd04cc6ef365677b286d728f73db42c06ecc0a5822a6334a" - /// add more 32bytes - + "0000000000000000000000000000000000000000000000000000000000000064\""; - - //argsStr = argsStr + "0000000000000000000000000000000000000000000000000000000000000064"; - - String methedStr = "VerifyBurnProofSize002(bytes)"; - - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methedStr, argsStr, false, - 0, maxFeeLimit, testAddress001, testPriKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("TriggerTxid: " + TriggerTxid); - - Optional infoById = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("infoById : " + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - String contractResult = ByteArray.toHexString( - infoById.get().getContractResult(0).toByteArray()); - - Assert.assertEquals("" - + "0000000000000000000000000000000000000000000000000000000000000001" // 1 : true - + "0000000000000000000000000000000000000000000000000000000000000040" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000000", contractResult); - - - } - - @Test(enabled = true, description = "data is empty") - public void verifyBurnProofTest003() { - - String methedStr = "VerifyBurnProofSize003()"; - - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methedStr, "", false, - 0, maxFeeLimit, testAddress001, testPriKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("TriggerTxid: " + TriggerTxid); - - Optional infoById = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("infoById : " + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - String contractResult = ByteArray.toHexString( - infoById.get().getContractResult(0).toByteArray()); - - Assert.assertEquals("" - + "0000000000000000000000000000000000000000000000000000000000000001" // 1 : true - + "0000000000000000000000000000000000000000000000000000000000000040" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000000", contractResult); - - - } - - @Test(enabled = true, description = "value greate than Long.MAX_VALUE") - public void verifyBurnProofTest004() { - - //String methedStr = "VerifyBurnProofSize002(bytes)"; - String methedStr = "VerifyBurnProofSize001(bytes32[10],bytes32[2],uint64,bytes32[2],bytes32)"; - String argsStr = "" - + "c9cf924134dd8fbd11d3b245b00adf4797b48c42e001673e7c566ce229b8fdf6" - + "24097774778540c2c4d5acbeffe333e1f595a1b731cbe10848e3d3a527ba4d1b" - + "a079c66e70cae2225cd702a7c0977635755ad104a87f435634d4e5382ac2afc8" - + "1c47919273d4861ad815855ba1b4db5f90cc7e922b65c930c291eddc6d49a6c4" - + "90771325afc8e6e4a506f9dca0889dff75bcb4c46030702a33899b4d1e81122a" - + "a236433cf4c8ff426c66446de2f375b08575c4a18802e19a5fa5500922f7d570" - + "aac680208d05f9f2a9beaef0d9adede10e4a0242a3d1e048dd2a65034ef3f348" - + "0c108652d93da2ed13a0720fce9dce3a01a25cfa898bbaa8730f3fa8bba4b8a9" - + "7a609fd9f4d008a9334dea39acc838298c989ae0f31cbaa08e4b00342ba2c0b1" - + "ba37ac7be8084e0aeb01045f121e87e9cc942ecdc3b5e52933b79aad6f005d8e" - - + "dfc2aabf584106dfb2f6d3eb7f4584f5f2d9cba8340b0f73ba5fab4a4a024db2" - + "d00c5f0b3aba1f98cba6d1c9750591628daca165bac2de6fd694df833110ee01" - - + "0000000000000000000000000000000000000000000000000fffffffffffffff" - - + "19389f87908cb5f1ede2a9fe0c3047d2ad5fce424d133bacb655ae1179a81084" - + "102ce5ad22d815a64374da9e2207d722b1c9a3099b292eaea0862edc886ff70d" - - + "b85285dd55258a2fbd04cc6ef365677b286d728f73db42c06ecc0a5822a6334a"; - - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methedStr, argsStr, true, - 0, maxFeeLimit, testAddress001, testPriKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("TriggerTxid: " + TriggerTxid); - - Optional infoById = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("infoById : " + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - String contractResult = ByteArray.toHexString( - infoById.get().getContractResult(0).toByteArray()); - - // parseLong will return Long.MAX_VALUE and checkResult false - - Assert.assertEquals("" - + "0000000000000000000000000000000000000000000000000000000000000000", contractResult); - } - - @Test(enabled = true, description = "verify success with address call") - public void verifyBurnProofTest005() { - String argsStr = "\"" - + "c9cf924134dd8fbd11d3b245b00adf4797b48c42e001673e7c566ce229b8fdf6" - + "24097774778540c2c4d5acbeffe333e1f595a1b731cbe10848e3d3a527ba4d1b" - + "a079c66e70cae2225cd702a7c0977635755ad104a87f435634d4e5382ac2afc8" - + "1c47919273d4861ad815855ba1b4db5f90cc7e922b65c930c291eddc6d49a6c4" - + "90771325afc8e6e4a506f9dca0889dff75bcb4c46030702a33899b4d1e81122a" - + "a236433cf4c8ff426c66446de2f375b08575c4a18802e19a5fa5500922f7d570" - + "aac680208d05f9f2a9beaef0d9adede10e4a0242a3d1e048dd2a65034ef3f348" - + "0c108652d93da2ed13a0720fce9dce3a01a25cfa898bbaa8730f3fa8bba4b8a9" - + "7a609fd9f4d008a9334dea39acc838298c989ae0f31cbaa08e4b00342ba2c0b1" - + "ba37ac7be8084e0aeb01045f121e87e9cc942ecdc3b5e52933b79aad6f005d8e" - - + "dfc2aabf584106dfb2f6d3eb7f4584f5f2d9cba8340b0f73ba5fab4a4a024db2" - + "d00c5f0b3aba1f98cba6d1c9750591628daca165bac2de6fd694df833110ee01" - - + "0000000000000000000000000000000000000000000000000000000000000064" - - + "19389f87908cb5f1ede2a9fe0c3047d2ad5fce424d133bacb655ae1179a81084" - + "102ce5ad22d815a64374da9e2207d722b1c9a3099b292eaea0862edc886ff70d" - - + "b85285dd55258a2fbd04cc6ef365677b286d728f73db42c06ecc0a5822a6334a" - + "\""; - - String methedStr = "VerifyBurnProofSize002(bytes)"; - - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methedStr, argsStr, false, - 0, maxFeeLimit, testAddress001, testPriKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("TriggerTxid: " + TriggerTxid); - - Optional infoById = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("infoById : " + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - String contractResult = ByteArray.toHexString( - infoById.get().getContractResult(0).toByteArray()); - - Assert.assertEquals("" - + "0000000000000000000000000000000000000000000000000000000000000001" // 1 : true - + "0000000000000000000000000000000000000000000000000000000000000040" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000001", contractResult); - } - - @Test(enabled = true, description = "verify success with fuction call") - public void verifyBurnProofTest006() { - String argsStr = "" - + "c9cf924134dd8fbd11d3b245b00adf4797b48c42e001673e7c566ce229b8fdf6" - + "24097774778540c2c4d5acbeffe333e1f595a1b731cbe10848e3d3a527ba4d1b" - + "a079c66e70cae2225cd702a7c0977635755ad104a87f435634d4e5382ac2afc8" - + "1c47919273d4861ad815855ba1b4db5f90cc7e922b65c930c291eddc6d49a6c4" - + "90771325afc8e6e4a506f9dca0889dff75bcb4c46030702a33899b4d1e81122a" - + "a236433cf4c8ff426c66446de2f375b08575c4a18802e19a5fa5500922f7d570" - + "aac680208d05f9f2a9beaef0d9adede10e4a0242a3d1e048dd2a65034ef3f348" - + "0c108652d93da2ed13a0720fce9dce3a01a25cfa898bbaa8730f3fa8bba4b8a9" - + "7a609fd9f4d008a9334dea39acc838298c989ae0f31cbaa08e4b00342ba2c0b1" - + "ba37ac7be8084e0aeb01045f121e87e9cc942ecdc3b5e52933b79aad6f005d8e" - - + "dfc2aabf584106dfb2f6d3eb7f4584f5f2d9cba8340b0f73ba5fab4a4a024db2" - + "d00c5f0b3aba1f98cba6d1c9750591628daca165bac2de6fd694df833110ee01" - - + "0000000000000000000000000000000000000000000000000000000000000064" - - + "19389f87908cb5f1ede2a9fe0c3047d2ad5fce424d133bacb655ae1179a81084" - + "102ce5ad22d815a64374da9e2207d722b1c9a3099b292eaea0862edc886ff70d" - - + "b85285dd55258a2fbd04cc6ef365677b286d728f73db42c06ecc0a5822a6334a"; - - String methedStr = "VerifyBurnProofSize001(bytes32[10],bytes32[2],uint64,bytes32[2],bytes32)"; - - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methedStr, argsStr, true, - 0, maxFeeLimit, testAddress001, testPriKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("TriggerTxid: " + TriggerTxid); - - Optional infoById = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("infoById : " + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - String contractResult = ByteArray.toHexString( - infoById.get().getContractResult(0).toByteArray()); - - Assert.assertEquals("" - + "0000000000000000000000000000000000000000000000000000000000000001", contractResult); - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/VerifyMintProof001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/VerifyMintProof001.java deleted file mode 100644 index 2ef5bb671db..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/VerifyMintProof001.java +++ /dev/null @@ -1,457 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.zenProofCommand; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class VerifyMintProof001 { - - private final String foundationKey001 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] foundationAddress001 = PublicMethed.getFinalAddress(foundationKey001); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] contractAddress = null; - - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - private byte[] testAddress001 = ecKey1.getAddress(); - private String testPriKey001 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(testPriKey001); - Assert.assertTrue(PublicMethed.sendcoin(testAddress001, 1000_000_000L, foundationAddress001, - foundationKey001, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "Deploy VerfyMintProof contract ") - public void verifyMintProofTest001() { - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(testAddress001, - blockingStubFull); - Protocol.Account info = PublicMethed.queryAccount(testPriKey001, blockingStubFull); - Long beforeBalance = info.getBalance(); - Long beforeEnergyUsed = accountResource.getEnergyUsed(); - Long beforeNetUsed = accountResource.getNetUsed(); - Long beforeFreeNetUsed = accountResource.getFreeNetUsed(); - logger.info("beforeBalance:" + beforeBalance); - logger.info("beforeEnergyUsed:" + beforeEnergyUsed); - logger.info("beforeNetUsed:" + beforeNetUsed); - logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - - String filePath = "./src/test/resources/soliditycode/VerifyMintProof001.sol"; - String contractName = "VerifyMintProof001Test"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - String txid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, testPriKey001, - testAddress001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - Assert.assertEquals(0, infoById.get().getResultValue()); - - contractAddress = infoById.get().getContractAddress().toByteArray(); - SmartContract smartContract = PublicMethed.getContract(contractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - } - - @Test(enabled = true, description = "data length != 1504") - public void verifyMintProofTest002() { - - String argsStr = "\"" - + "a634da705bbacb108a276ce26470568873d573e6f1f00d3a2b2e93b93f4b1a0c" - + "2eb2b8ae07c858dafd7d99f4487a779878b1f87fb632c7fccff14d44c0b23e56" - + "61ba88273d52c44cf4e1939ce6e76b97ef2611ce4cf472c5e8a61e66463f948d" - + "8ffed5e9e6125a292dcb2f2855a753893467176b19ed366b3fc7c182e5b62cc1" - + "d01bb22cba6ca8a514f36c5f24e6dcaf953f77db33c5e6db4f2a756b2e4793b7" - + "be6e29b29309c37b9a1a5fe1e6ad42b1ed17c6d84d0fb4ed39772dceb5af6d23" - + "01ed5d94ce6b69efc2bbe863f7798d871ae5bfc3db4eb36073fd9b8eb08d6c0c" - + "52439f429ee437454cd59b8068ec9350b611f9b41cf5fa840c911227a2db3546" - + "f0d190023a929d821aaf0529066bd81eac321ad0c9cf98c4a39060d636140a99" - - + "2ac86687e4c5284a8272390684e557d9a70bcd8dbaec6b8c8cb6114b13e01f22" - + "c1dd79631dc9bd508f87d77bae4bebf31917c981d1ed1f8d8d9e637a7e56db0b" - - + "0000000000000000000000000000000000000000000000000000000000000064" - - + "33e4e8db7e8d3c127620de9901e7c6e65ca675b1c69455784a98aa7e4ed31a91" - - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - - + "0000000000000000000000000000000000000000000000000000000000000000" - // add more bytes32 - + "0000000000000000000000000000000000000000000000000000000000000064" - + "\""; - - String methedStr = "VerifyMintProofSize002(bytes)"; - - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methedStr, argsStr, false, - 0, maxFeeLimit, testAddress001, testPriKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("TriggerTxid: " + TriggerTxid); - - Optional infoById = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("infoById : " + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - String contractResult = ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray()); - - Assert.assertEquals("" - + "0000000000000000000000000000000000000000000000000000000000000001" // 1 : true - + "0000000000000000000000000000000000000000000000000000000000000040" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000000", contractResult); - - - } - - @Test(enabled = true, description = "data is empty") - public void verifyMintProofTest003() { - String methedStr = "VerifyMintProofSize003()"; - - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methedStr, "", false, - 0, maxFeeLimit, testAddress001, testPriKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("TriggerTxid: " + TriggerTxid); - - Optional infoById = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("infoById : " + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - String contractResult = ByteArray - .toHexString(infoById.get().getContractResult(0).toByteArray()); - - Assert.assertEquals("" - + "0000000000000000000000000000000000000000000000000000000000000001" // 1 : true - + "0000000000000000000000000000000000000000000000000000000000000040" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000000", contractResult); - - } - - @Test(enabled = true, description = "leafCount greate than 2^32-1") - public void verifyMintProofTest004() { - - String methedStr = "VerifyMintProofSize002(bytes)"; - - String argsStr = "\"" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - - + "000000000000000000000000000000000000000000000000000000000000000a" - - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - + "b55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105a" - - + "0000000000000000000000000000000000000000000000000000000100000002" - + "\""; - - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methedStr, argsStr, false, - 0, maxFeeLimit, testAddress001, testPriKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("TriggerTxid: " + TriggerTxid); - - Optional infoById = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("infoById : " + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - String contractResult = ByteArray.toHexString(infoById.get() - .getContractResult(0).toByteArray()); - - Assert.assertEquals("" - + "" // 1 : true - + "0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000040" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000000", contractResult); - } - - @Test(enabled = true, description = "verify success with address call") - public void verifyMintProofTest005() { - String argsStr = - "\"a634da705bbacb108a276ce26470568873d573e6f1f00d3a2b2e93b93f4b1a0c" - + "2eb2b8ae07c858dafd7d99f4487a779878b1f87fb632c7fccff14d44c0b23e56" - + "61ba88273d52c44cf4e1939ce6e76b97ef2611ce4cf472c5e8a61e66463f948d" - + "8ffed5e9e6125a292dcb2f2855a753893467176b19ed366b3fc7c182e5b62cc1" - + "d01bb22cba6ca8a514f36c5f24e6dcaf953f77db33c5e6db4f2a756b2e4793b7" - + "be6e29b29309c37b9a1a5fe1e6ad42b1ed17c6d84d0fb4ed39772dceb5af6d23" - + "01ed5d94ce6b69efc2bbe863f7798d871ae5bfc3db4eb36073fd9b8eb08d6c0c" - + "52439f429ee437454cd59b8068ec9350b611f9b41cf5fa840c911227a2db3546" - + "f0d190023a929d821aaf0529066bd81eac321ad0c9cf98c4a39060d636140a99" - - + "2ac86687e4c5284a8272390684e557d9a70bcd8dbaec6b8c8cb6114b13e01f22" - + "c1dd79631dc9bd508f87d77bae4bebf31917c981d1ed1f8d8d9e637a7e56db0b" - - + "0000000000000000000000000000000000000000000000000000000000000064" - - + "33e4e8db7e8d3c127620de9901e7c6e65ca675b1c69455784a98aa7e4ed31a91" - - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - - + "0000000000000000000000000000000000000000000000000000000000000000\""; - - String methedStr = "VerifyMintProofSize002(bytes)"; - - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methedStr, argsStr, false, - 0, maxFeeLimit, testAddress001, testPriKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("TriggerTxid: " + TriggerTxid); - - Optional infoById = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("infoById : " + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - String contractResult = ByteArray.toHexString(infoById.get() - .getContractResult(0).toByteArray()); - - Assert.assertEquals("" - + "0000000000000000000000000000000000000000000000000000000000000001" // 1 : true - + "0000000000000000000000000000000000000000000000000000000000000040" - + "0000000000000000000000000000000000000000000000000000000000000060" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "39e261b362110781a20878cc19f480cb50df5e6b896ed9a1fea8b8a9a4239a17", contractResult); - - } - - @Test(enabled = true, description = "verify success with fuction call") - public void verifyMintProofTest006() { - String argsStr = - "a634da705bbacb108a276ce26470568873d573e6f1f00d3a2b2e93b93f4b1a0c" - + "2eb2b8ae07c858dafd7d99f4487a779878b1f87fb632c7fccff14d44c0b23e56" - + "61ba88273d52c44cf4e1939ce6e76b97ef2611ce4cf472c5e8a61e66463f948d" - + "8ffed5e9e6125a292dcb2f2855a753893467176b19ed366b3fc7c182e5b62cc1" - + "d01bb22cba6ca8a514f36c5f24e6dcaf953f77db33c5e6db4f2a756b2e4793b7" - + "be6e29b29309c37b9a1a5fe1e6ad42b1ed17c6d84d0fb4ed39772dceb5af6d23" - + "01ed5d94ce6b69efc2bbe863f7798d871ae5bfc3db4eb36073fd9b8eb08d6c0c" - + "52439f429ee437454cd59b8068ec9350b611f9b41cf5fa840c911227a2db3546" - + "f0d190023a929d821aaf0529066bd81eac321ad0c9cf98c4a39060d636140a99" - - + "2ac86687e4c5284a8272390684e557d9a70bcd8dbaec6b8c8cb6114b13e01f22" - + "c1dd79631dc9bd508f87d77bae4bebf31917c981d1ed1f8d8d9e637a7e56db0b" - - + "0000000000000000000000000000000000000000000000000000000000000064" - - + "33e4e8db7e8d3c127620de9901e7c6e65ca675b1c69455784a98aa7e4ed31a91" - - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - - + "0000000000000000000000000000000000000000000000000000000000000000"; - - String methedStr = - "VerifyMintProofSize001(bytes32[9],bytes32[2],uint64,bytes32,bytes32[33],uint256)"; - - String TriggerTxid = PublicMethed.triggerContract(contractAddress, methedStr, argsStr, true, - 0, maxFeeLimit, testAddress001, testPriKey001, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info("TriggerTxid: " + TriggerTxid); - - Optional infoById = PublicMethed - .getTransactionInfoById(TriggerTxid, blockingStubFull); - - logger.info("infoById : " + infoById); - - Assert.assertEquals(0, infoById.get().getResultValue()); - String contractResult = ByteArray.toHexString(infoById.get() - .getContractResult(0).toByteArray()); - - Assert.assertTrue(contractResult.length() > 1000); - - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/pedersenHash001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/pedersenHash001.java deleted file mode 100644 index 62f53d03455..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/pedersenHash001.java +++ /dev/null @@ -1,166 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.zenProofCommand; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class pedersenHash001 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - String txid; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 10000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/pedersenHash001.sol"; - String contractName = "pedersenHashTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "data is empty") - public void test01DataIsEmpty() { - String method = "test1()"; - txid = PublicMethed - .triggerContract(contractAddress, method, "", false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("SUCESS", infoById.get().getResult().toString()); - byte[] result = infoById.get().getContractResult(0).toByteArray(); - String boolResult = ByteArray.toHexString(ByteArray.subArray(result, 0, 32)); - System.out.println("boolResult: " + boolResult); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000000", - boolResult); - - } - - @Test(enabled = true, description = "data length limit") - public void test02DataLengthLimit() { - String method = "test2(bytes)"; - // length:64 - String argsStr1 = "\"0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000002\""; - Optional infoById = null; - txid = PublicMethed.triggerContract(contractAddress, method, argsStr1, false, 0, maxFeeLimit, - contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("SUCESS", infoById.get().getResult().toString()); - int boolResult = ByteArray.toInt(infoById.get().getContractResult(0).toByteArray()); - Assert.assertFalse(Boolean.valueOf(String.valueOf(boolResult))); - Assert.assertTrue(maxFeeLimit > infoById.get().getFee()); - - // length:128 - String argsStr2 = "\"0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "0000000000000000000000000000000000000000000000000000000000000002\""; - txid = PublicMethed.triggerContract(contractAddress, method, argsStr2, false, 0, maxFeeLimit, - contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000040" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "7d6b910840eb7b47f76492aca4a3344888b8fa5aab77a49e9445cda718d75040", - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "normal") - public void test02Normal() { - String method = "test3(uint32,bytes32,bytes32)"; - String argsStr1 = "0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000002"; - Optional infoById = null; - txid = PublicMethed.triggerContract(contractAddress, method, argsStr1, true, 0, maxFeeLimit, - contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("7d6b910840eb7b47f76492aca4a3344888b8fa5aab77a49e9445cda718d75040", - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - } - - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed - .sendcoin(testNetAccountAddress, balance - 1000000, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/pedersenHash002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/pedersenHash002.java deleted file mode 100644 index 3d82e7a05b8..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/pedersenHash002.java +++ /dev/null @@ -1,476 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.zenProofCommand; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import io.grpc.Status; -import io.netty.util.internal.StringUtil; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.Random; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpPost; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.BytesMessage; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.Commons; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.exception.ZksnarkException; -import org.tron.core.zen.address.DiversifierT; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldedAddressInfo; - -@Slf4j -public class pedersenHash002 { - - public final String foundationAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - public final byte[] foundationAccountAddress = PublicMethed.getFinalAddress(foundationAccountKey); - public static final String zenTrc20TokenOwnerKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTrc20TokenOwnerKey"); - public static final byte[] zenTrc20TokenOwnerAddress = PublicMethed - .getFinalAddress(zenTrc20TokenOwnerKey); - public static final String zenTrc20TokenOwnerAddressString = PublicMethed - .getAddressString(zenTrc20TokenOwnerKey); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - public ManagedChannel channelFull = null; - public WalletGrpc.WalletBlockingStub blockingStubFull = null; - public ManagedChannel channelSolidity = null; - public WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - public static long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - public ByteString contractAddressByteString; - public static byte[] contractAddressByte; - public static String contractAddress; - public static ByteString shieldAddressByteString; - public static byte[] shieldAddressByte; - public static String shieldAddress; - public static String deployShieldTrc20Txid; - public static String deployShieldTxid; - private BigInteger publicFromAmount; - Optional receiverShieldAddressInfo; - List shieldOutList = new ArrayList<>(); - public static String transfer = - "transfer(bytes32[10][],bytes32[2][],bytes32[9][],bytes32[2],bytes32[21][])"; - public Wallet wallet = new Wallet(); - static HttpResponse response; - static HttpPost httppost; - public static Integer scalingFactorLogarithm = 0; - public static Long totalSupply = 1000000000000L; - - - /** - * constructor. - */ - @BeforeClass(enabled = true, description = "Deploy shield trc20 depend contract") - public void deployShieldTrc20DependContract() { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - Assert.assertTrue(PublicMethed.sendcoin(contractExcAddress, 10000000000000L, - foundationAccountAddress, foundationAccountKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "shieldTrc20Token"; - - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_shieldTrc20Token"); - String code = Configuration.getByPath("testng.conf") - .getString("code.code_shieldTrc20Token"); - String constructorStr = "constructor(uint256,string,string)"; - String data = totalSupply.toString() + "," + "\"TokenTRC20\"" + "," + "\"zen20\""; - logger.info("data:" + data); - deployShieldTrc20Txid = PublicMethed - .deployContractWithConstantParame(contractName, abi, code, constructorStr, data, "", - maxFeeLimit, 0L, 100, null, - contractExcKey, contractExcAddress, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info(deployShieldTrc20Txid); - Optional infoById = PublicMethed - .getTransactionInfoById(deployShieldTrc20Txid, blockingStubFull); - contractAddressByteString = infoById.get().getContractAddress(); - contractAddressByte = infoById.get().getContractAddress().toByteArray(); - contractAddress = Base58.encode58Check(contractAddressByte); - logger.info(contractAddress); - String filePath = "src/test/resources/soliditycode/pedersenHash002.sol"; - contractName = "TokenTRC20"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - code = retMap.get("byteCode").toString(); - abi = retMap.get("abI").toString(); - data = "\"" + contractAddress + "\"" + "," + scalingFactorLogarithm; - constructorStr = "constructor(address,uint256)"; - deployShieldTxid = PublicMethed - .deployContractWithConstantParame(contractName, abi, code, constructorStr, data, "", - maxFeeLimit, 0L, 100, null, - contractExcKey, contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info(deployShieldTxid); - infoById = PublicMethed.getTransactionInfoById(deployShieldTxid, blockingStubFull); - shieldAddressByteString = infoById.get().getContractAddress(); - shieldAddressByte = infoById.get().getContractAddress().toByteArray(); - shieldAddress = Base58.encode58Check(shieldAddressByte); - logger.info(shieldAddress); - - data = "\"" + shieldAddress + "\"" + "," + totalSupply.toString(); - String txid = PublicMethed.triggerContract(contractAddressByte, - "approve(address,uint256)", data, false, - 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info("approve:" + txid); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - publicFromAmount = getRandomAmount(); - } - - - @Test(enabled = true, description = "left and right value is 0") - public void test01LeftAndRightValueIsZero() throws Exception { - //Query account before mint balance - final Long beforeMintAccountBalance = getBalanceOfShieldTrc20(zenTrc20TokenOwnerAddressString, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - //Query contract before mint balance - final Long beforeMintShieldAccountBalance = getBalanceOfShieldTrc20(shieldAddress, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - //Generate new shiled account and set note memo - receiverShieldAddressInfo = getNewShieldedAddress(blockingStubFull); - String memo = "Shield trc20 from T account to shield account in" + System.currentTimeMillis(); - String receiverShieldAddress = receiverShieldAddressInfo.get().getAddress(); - - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, receiverShieldAddress, - "" + publicFromAmount, memo, blockingStubFull); - - //Create shiled trc20 parameters - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters - = createShieldedTrc20Parameters("ByValueIsZero", publicFromAmount, - null, null, shieldOutList, "", 0L, - blockingStubFull, blockingStubSolidity); - } - - /** - * constructor. - */ - public GrpcAPI.ShieldedTRC20Parameters createShieldedTrc20Parameters(String methodSuffix, - BigInteger publicFromAmount, GrpcAPI.DecryptNotesTRC20 inputNoteList, - List shieldedAddressInfoList, List outputNoteList, - String publicToAddress, Long pubicToAmount, WalletGrpc.WalletBlockingStub blockingStubFull, - WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity) throws ZksnarkException { - - GrpcAPI.PrivateShieldedTRC20Parameters.Builder builder - = GrpcAPI.PrivateShieldedTRC20Parameters.newBuilder(); - - //Mint type should set public from amount to parameter - if (publicFromAmount.compareTo(BigInteger.ZERO) > 0) { - builder.setFromAmount(publicFromAmount.toString()); - } - - builder.setShieldedTRC20ContractAddress(ByteString.copyFrom(shieldAddressByte)); - long valueBalance = 0; - - if (inputNoteList != null) { - logger.info("Enter transfer type code"); - List rootAndPath = new ArrayList<>(); - for (int i = 0; i < inputNoteList.getNoteTxsCount(); i++) { - long position = inputNoteList.getNoteTxs(i).getPosition(); - rootAndPath.add(getRootAndPath(methodSuffix, position, blockingStubSolidity)); - } - if (rootAndPath.isEmpty() || rootAndPath.size() != inputNoteList.getNoteTxsCount()) { - System.out.println("Can't get all merkle tree, please check the notes."); - return null; - } - for (int i = 0; i < rootAndPath.size(); i++) { - if (rootAndPath.get(i) == null) { - System.out.println("Can't get merkle path, please check the note " + i + "."); - return null; - } - } - - for (int i = 0; i < inputNoteList.getNoteTxsCount(); ++i) { - if (i == 0) { - String shieldedAddress = inputNoteList.getNoteTxs(i).getNote().getPaymentAddress(); - - String spendingKey = ByteArray.toHexString(shieldedAddressInfoList.get(0).getSk()); - BytesMessage sk = BytesMessage.newBuilder() - .setValue(ByteString.copyFrom(ByteArray.fromHexString(spendingKey))).build(); - Optional esk = Optional - .of(blockingStubFull.getExpandedSpendingKey(sk)); - - //ExpandedSpendingKey expandedSpendingKey = spendingKey.expandedSpendingKey(); - builder.setAsk(esk.get().getAsk()); - builder.setNsk(esk.get().getNsk()); - builder.setOvk(esk.get().getOvk()); - } - Note.Builder noteBuild = Note.newBuilder(); - noteBuild.setPaymentAddress(shieldedAddressInfoList.get(0).getAddress()); - noteBuild.setValue(inputNoteList.getNoteTxs(i).getNote().getValue()); - noteBuild.setRcm(inputNoteList.getNoteTxs(i).getNote().getRcm()); - noteBuild.setMemo(inputNoteList.getNoteTxs(i).getNote().getMemo()); - - byte[] eachRootAndPath = ByteArray.fromHexString(rootAndPath.get(i)); - byte[] root = Arrays.copyOfRange(eachRootAndPath, 0, 32); - byte[] path = Arrays.copyOfRange(eachRootAndPath, 32, 1056); - GrpcAPI.SpendNoteTRC20.Builder spendTRC20NoteBuilder = GrpcAPI.SpendNoteTRC20.newBuilder(); - spendTRC20NoteBuilder.setNote(noteBuild.build()); - spendTRC20NoteBuilder.setAlpha(ByteString.copyFrom(blockingStubFull.getRcm( - EmptyMessage.newBuilder().build()).getValue().toByteArray())); - spendTRC20NoteBuilder.setRoot(ByteString.copyFrom(root)); - spendTRC20NoteBuilder.setPath(ByteString.copyFrom(path)); - spendTRC20NoteBuilder.setPos(inputNoteList.getNoteTxs(i).getPosition()); - - valueBalance = Math - .addExact(valueBalance, inputNoteList.getNoteTxs(i).getNote().getValue()); - builder.addShieldedSpends(spendTRC20NoteBuilder.build()); - } - } else { - //@TODO remove randomOvk by sha256.of(privateKey) - byte[] ovk = getRandomOvk(); - if (ovk != null) { - builder.setOvk(ByteString.copyFrom(ovk)); - } else { - System.out.println("Get random ovk from Rpc failure,please check config"); - return null; - } - } - - if (outputNoteList != null) { - for (int i = 0; i < outputNoteList.size(); i++) { - Note note = outputNoteList.get(i); - valueBalance = Math.subtractExact(valueBalance, note.getValue()); - builder.addShieldedReceives( - GrpcAPI.ReceiveNote.newBuilder().setNote(note).build()); - } - } - - if (!StringUtil.isNullOrEmpty(publicToAddress)) { - byte[] to = Commons.decodeFromBase58Check(publicToAddress); - if (to == null) { - return null; - } - builder.setTransparentToAddress(ByteString.copyFrom(to)); - builder.setToAmount(pubicToAmount.toString()); - } - - try { - return blockingStubFull.createShieldedContractParameters(builder.build()); - } catch (Exception e) { - Status status = Status.fromThrowable(e); - System.out.println("createShieldedContractParameters failed,error " - + status.getDescription()); - } - return null; - } - - public String getRootAndPath(String methodSuffix, long position, - WalletSolidityGrpc.WalletSolidityBlockingStub - blockingStubSolidity) { - String methodStr = "getPath" + methodSuffix + "(uint256)"; - byte[] indexBytes = ByteArray.fromLong(position); - String argsStr = ByteArray.toHexString(indexBytes); - argsStr = "000000000000000000000000000000000000000000000000" + argsStr; - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtentionOnSolidity(shieldAddressByte, methodStr, argsStr, true, - 0, 1000000000L, "0", 0, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubSolidity); - byte[] result = transactionExtention.getConstantResult(0).toByteArray(); - return ByteArray.toHexString(result); - } - - /** - * constructor. - */ - public static HttpResponse getNewShieldedAddress(String httpNode) { - try { - String requestUrl = "http://" + httpNode + "/wallet/getnewshieldedaddress"; - response = HttpMethed.createConnect(requestUrl); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - } - - /** - * constructor. - */ - public Optional getNewShieldedAddress(WalletGrpc.WalletBlockingStub - blockingStubFull) { - ShieldedAddressInfo addressInfo = new ShieldedAddressInfo(); - - try { - Optional sk = Optional.of(blockingStubFull - .getSpendingKey(EmptyMessage.newBuilder().build())); - final Optional d = Optional.of(blockingStubFull.getDiversifier( - EmptyMessage.newBuilder().build())); - - Optional expandedSpendingKeyMessage - = Optional.of(blockingStubFull - .getExpandedSpendingKey(sk.get())); - - BytesMessage.Builder askBuilder = BytesMessage.newBuilder(); - askBuilder.setValue(expandedSpendingKeyMessage.get().getAsk()); - Optional ak = Optional.of(blockingStubFull.getAkFromAsk(askBuilder.build())); - - BytesMessage.Builder nskBuilder = BytesMessage.newBuilder(); - nskBuilder.setValue(expandedSpendingKeyMessage.get().getNsk()); - Optional nk = Optional.of(blockingStubFull.getNkFromNsk(nskBuilder.build())); - - GrpcAPI.ViewingKeyMessage.Builder viewBuilder = GrpcAPI.ViewingKeyMessage.newBuilder(); - viewBuilder.setAk(ak.get().getValue()); - viewBuilder.setNk(nk.get().getValue()); - Optional ivk = Optional.of(blockingStubFull - .getIncomingViewingKey(viewBuilder.build())); - - GrpcAPI.IncomingViewingKeyDiversifierMessage.Builder builder - = GrpcAPI.IncomingViewingKeyDiversifierMessage - .newBuilder(); - builder.setD(d.get()); - builder.setIvk(ivk.get()); - Optional addressMessage = Optional.of(blockingStubFull - .getZenPaymentAddress(builder.build())); - addressInfo.setSk(sk.get().getValue().toByteArray()); - addressInfo.setD(new DiversifierT(d.get().getD().toByteArray())); - addressInfo.setIvk(ivk.get().getIvk().toByteArray()); - addressInfo.setOvk(expandedSpendingKeyMessage.get().getOvk().toByteArray()); - addressInfo.setPkD(addressMessage.get().getPkD().toByteArray()); - - return Optional.of(addressInfo); - - } catch (Exception e) { - e.printStackTrace(); - } - - return Optional.empty(); - } - - /** - * constructor. - */ - public static List addShieldTrc20OutputList(List shieldOutList, - String shieldToAddress, String toAmountString, String menoString, - WalletGrpc.WalletBlockingStub blockingStubFull) { - String shieldAddress = shieldToAddress; - String amountString = toAmountString; - if (menoString.equals("null")) { - menoString = ""; - } - long shieldAmount = 0; - if (!StringUtil.isNullOrEmpty(amountString)) { - shieldAmount = Long.valueOf(amountString); - } - - Note.Builder noteBuild = Note.newBuilder(); - noteBuild.setPaymentAddress(shieldAddress); - //noteBuild.setPaymentAddress(shieldAddress); - noteBuild.setValue(shieldAmount); - noteBuild.setRcm(ByteString.copyFrom(blockingStubFull.getRcm(EmptyMessage.newBuilder().build()) - .getValue().toByteArray())); - noteBuild.setMemo(ByteString.copyFrom(menoString.getBytes())); - shieldOutList.add(noteBuild.build()); - return shieldOutList; - } - - /** - * constructor. - */ - public Long getBalanceOfShieldTrc20(String queryAddress, byte[] ownerAddress, - String ownerKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - String paramStr = "\"" + queryAddress + "\""; - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(contractAddressByte, "balanceOf(address)", - paramStr, false, 0, 0, "0", 0, - ownerAddress, ownerKey, blockingStubFull); - - String hexBalance = Hex.toHexString(transactionExtention - .getConstantResult(0).toByteArray()); - for (int i = 0; i < hexBalance.length(); i++) { - if (hexBalance.charAt(i) != '0') { - hexBalance = hexBalance.substring(i); - break; - } - } - logger.info(hexBalance); - return Long.parseLong(hexBalance, 16); - } - - /** - * constructor. - */ - public byte[] getRandomOvk() { - try { - Optional sk = Optional.of(blockingStubFull - .getSpendingKey(EmptyMessage.newBuilder().build())); - Optional expandedSpendingKeyMessage - = Optional.of(blockingStubFull - .getExpandedSpendingKey(sk.get())); - return expandedSpendingKeyMessage.get().getOvk().toByteArray(); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - /** - * constructor. - */ - public BigInteger getRandomAmount() { - Random random = new Random(); - int x = random.nextInt(100000) + 100; - return BigInteger.valueOf(x); - } - - public byte[] longTo32Bytes(long value) { - byte[] longBytes = ByteArray.fromLong(value); - byte[] zeroBytes = new byte[24]; - return ByteUtil.merge(zeroBytes, longBytes); - } - - - /** - * constructor. - */ - public static String getRcm(String httpNode) { - try { - String requestUrl = "http://" + httpNode + "/wallet/getrcm"; - response = HttpMethed.createConnect(requestUrl); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return HttpMethed.parseResponseContent(response).getString("value"); - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/verifyTransferProof001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/verifyTransferProof001.java deleted file mode 100644 index ac93beef5a1..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/zenProofCommand/verifyTransferProof001.java +++ /dev/null @@ -1,802 +0,0 @@ -package stest.tron.wallet.dailybuild.tvmnewcommand.zenProofCommand; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class verifyTransferProof001 { - - private final String testNetAccountKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - byte[] contractAddress = null; - String txid; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractExcAddress = ecKey1.getAddress(); - String contractExcKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractExcKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - txid = PublicMethed - .sendcoinGetTransactionId(contractExcAddress, 10000000000L, testNetAccountAddress, - testNetAccountKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String filePath = "src/test/resources/soliditycode/verifyTransferProof001.sol"; - String contractName = "verifyTransferProofTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - contractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, - contractExcAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true, description = "data is empty") - public void test01DataIsEmpty() { - String method = "test1()"; - txid = PublicMethed - .triggerContract(contractAddress, method, "", false, 0, maxFeeLimit, contractExcAddress, - contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000040" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "data length limit") - public void test02DataLengthLimit() { - String method = "test2(bytes)"; - Optional infoById = null; - // length:2048 - String argsStr1 = "\"0000000000000000000000000000000000000000000000000000000000000520" - + "0000000000000000000000000000000000000000000000000000000000000680" - + "00000000000000000000000000000000000000000000000000000000000006e0" - + "f3e912b1f0d8e6a6654c1e9ff16d9eb5c2895b35490a5fa825d275d842efb5e5" - + "45ae827a6fb105d6fc6d125c2a8c1253f753b4973a6505b671b0c01b6ef3ac06" - + "4f4aca9fdf2a460e95df34315749ac432cd5154ad42217b7296b3b5bd81dd00b" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "363f4cb9b6605bbd39b3ccf4fdc834721afc8d38cd25becc7830dab5cacf1852" - + "32431ad6d4cfa89730b413b4ca2f744623a0b4b8315fc5e307ed62a043fa4064" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000003" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "66b02f76abecb4de13adc2b9b48edf60edf7e243dba5930276655936b53019ee" - + "626327f3509cadc915c8df9d9f97e17f244c828f3ad82b19f6701ae09dc0e22e" - + "659d5386266aef0a8434fe2ac728a655071f4688ad6cd1dae6e58e4767e1a36a" - + "d2614240434f15b189c8f235e35b281454988d72518df3068d8f512fe992e564" - + "a27d2c53207376e3f179aed8f415acbe1bca1a9ec60188f6fea1d1fd99f80db2" - + "c70271638ea0aa5d99e49fca76157e7692c856f4056b7857ed5ce852e69c713f" - + "42dd888295906c9988cc7fdd6715ea2dac745e97fa8ffd63653ee8e17b8a2ada" - + "1148bed585f91c1ab2f38f77e78a4dacd86587ac899961665e0a6f34d7cf0a41" - + "0f1032d3c26d0ab381ba3fd45f1cbb36b04f889584c1868fdc448eaab9bb8592" - + "d91a58c9e735862cdd346201fb9ab75999c6a57a6a474f2248f71c631375f0a8" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "8dcbff6a27f4e6b39c6e19aab7deb9427368bc8dc1082f0dfe57edc94fbb8c3e" - + "1eb36d9f48c5243dad16ab511dcea3c8489ba0dd774befb12fc58f1ae50e7504" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "9fa6ed64a910bee735eafdb80636852367f6a487f6aec0598708ad80cad8ed09" - + "7aa9686c3cc957f88703e1eea87c5412baba2044c78e9161a7b2ac2b21bfef9b" - + "83ca769ba273d3fe1d4cc0d5d0d1ab8a6540f220c1db981fc8885ee34b51263f" - + "90f31816d21895f518bbb893c62ce296ee8416486c37b9dba9d0cb3cdd5f58c5" - + "7e175a69dbf443509bc060f354862d9787490de120ae665cbcba894854eb8aaf" - + "b811e676c506f7c4f2038afa09fc56b66c0c9cefcc00d780d152f1633d1c90af" - + "058355203f7737de6184b08bbf84248f118c3b540a7dc8f5518676fe0ebb2b35" - + "e4c3ec5f6b2f93138c7e7aa4a9b631dc9786b6df2d317208f220055d3fcab328\""; - txid = PublicMethed.triggerContract(contractAddress, method, argsStr1, false, 0, maxFeeLimit, - contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000040" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - - // length:2784 - String argsStr2 = "\"0000000000000000000000000000000000000000000000000000000000000520" - + "00000000000000000000000000000000000000000000000000000000000007c0" - + "0000000000000000000000000000000000000000000000000000000000000860" - + "898bb618ff2874a2b706e000d663c8e7ff7095ca404e131ce712583d7a3bf717" - + "b7b6ec3705a0823d09524e13c81bd4f44e6c796e63b197ffcdb6ec7bb44ff505" - + "2487fbd8a96638187266aa9c54795e0c14aabcd72d45b6d13ba304b539cbc7ed" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "82f70d55b1d9131cd3d41b7491636291a5ac41ed3372e4fe502d1c4a911cce4b" - + "49c6eaf2968c27437831622072b8f8cfa18791084189e7c4764c104a360bbe70" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "7c62133e78f43c71c49e8b85b145377c51c7d4dfd7c44656d62363144f243575" - + "1f2b46d412955c11a51cd81f6499bd0e9cf9c5a3fa12befe26b1e992e41cfd4c" - + "f1243c6008688639d9dffa4670b74546f66be60209a9c5664a9de7dcca856f6a" - + "fdfb2e8cf0083a20dbf2899042baa469949f7993f7b0f3606d70f443486ebf46" - + "9232a4e7a899e52a7479d9ca981ee7fe96250e4ef8d6899d89e8c33be62ac65c" - + "a97e4cd3d9a58033d35f9a7c45375f0b8866db6db15fcbd185e6c254cd0300b9" - + "364a3c2d9499e474bf207ce2f2b67427df0796d2c221efb28b7fccea210b58ba" - + "01f5a9b4a12eb295ab0fecbe97f01bf4841002e94e1334a513755403f6832ce3" - + "0ab328b11e8772aa922dc7c84768c887b38b35e39df177e3fc4f760051209e1a" - + "9dfef66affba94f21d5a28c39a893419af506faee2217f0c605830427173a7d5" - + "521c7b5bf3ff99421c69c861af0fc30b565332ff1aad344afd9dd7b40e3da769" - + "67ecbac59d221641a28b19134e599c1d20c5cc55ac45217a68b0b9106872b92a" - + "8d55ca2e65e84ccd45a21d88a0eec096d98525d7e6751d4dbc4ddcb6aaec334b" - + "c7061b48ba27b89f193ad9e9f4d9c98aa1316b08f018222a3d92c1da7e8b7611" - + "806764eeb09ac490eea1f01d16ba8378e0c64396a0c06a707ed6027eae76938e" - + "74fa404d1ed9a955c7fe85eabc07b76eb58287d749a8dd304e810f94f680120b" - + "6e792117717f8b5b7f9f01416205900d962ffb69540e85562688604c26db4987" - + "0de0658d072aeb649809bf6f21714975f87e75df545e583c77bd6f786b3cc5c6" - + "08051b7885a732ac9bd49271d7ae9caea7d995d2ce5b18740f2b5b0de32d1337" - + "46f30ae9eb6d1f54ea1e4e228b6a22849a99f0a2decd09c806d8bd7cad6810de" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "c68b0fa0e76ffae969421ef87a0e27e4ad5a94b5bf2b5237c0a0e57259f20e60" - + "60525cfbc22ff838b067110121840a6885bff4516a5dc21eedce04f79b04b403" - + "10e640233b876885329599a78ce1cdc5dff83a29216f7fe58f225338963ec9b4" - + "9811e7479ef258776289394525c1070b70d3aeacb6d9d4a9065024ca21d8ed08" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "73238d94e2ad7575eb6067b1e5889a8445ef29dc377bdba0807f716b0b75b13e" - + "00ef0b6303b098a8af5e2deb8d506aaa710a58805325aa2097c19a63b876e5b4" - + "26e055e92683f24fab7c79b7d8825928fc3dc356d496c09069b8fd0d01df275b" - + "b0a57952d3adc1f31570d3626d2011a725f9caaf857e253b4e4791adfb7babe7" - + "27c0b4791f16050dfdb1a4763f75fd0f970ca19ee66c36462e43dff2899c5d62" - + "3e363389f3dedb855c09e051f20f3f27ee52d2d267ae1f1bf024c2f63068b682" - + "0b578b39aebb57b8fc055a7d13d25574dfcde58656beec84dde4ba439b0bbb5d" - + "0b5b24a2cf71f6b68b56c5ef1bac89888b5b6827bca8cd8b47fc394cf89a6c23" - + "468f7857b566cddf39f06eed6ac079f20044b42381fb0ca969c4f425ed04e166" - + "09e582987c6af094c8afbfeb52e14b0e4e342c82dc784405631f4a985c826e51" - + "4a9b50b6ad41db1a403b0ced0f5f1e4a9ae2964237b6874056c8044233b331e1" - + "a8bcf84d0584c12dc42ebd27cca972b31c475a644450afcfd40c36c739740566" - + "8b377c8ed99dcca1a5ec03ca990d6c4cb846ad561dd204c66c834fc024030b75" - + "106bdca9e57e8d68d19e4183a349bc488b9c3d666f59f9bdca8e92457dbbacf5" - + "1a0e074d5cb64b54e533aef3d1da2b673b7a87cae612c7faed50563a20970a9b" - + "07539d7ea4d57a83defeaefa024832fe6ec1db4c3a4ef6badcc4d95e0d22f4ec" - + "e4f272a22dcfaa2326bc301f2dfac22fa35bd0c9a40262caf424e2e62b3e0a45" - + "c2fa591c482e923a2d6b3c4ba0819df430f4d548105071f7cb561749459f15d2" - + "c2fa591c482e923a2d6b3c4ba0819df430f4d548105071f7cb561749459f15d2\""; - txid = PublicMethed.triggerContract(contractAddress, method, argsStr2, false, 0, maxFeeLimit, - contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000040" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "tree width limit") - public void test03TreeWidthLimit() { - String method = "test2(bytes)"; - txid = PublicMethed.triggerContract(contractAddress, method, - "\"0000000000000000000000000000000000000000000000000000000000000520" - + "0000000000000000000000000000000000000000000000000000000000000680" - + "00000000000000000000000000000000000000000000000000000000000006e0" - + "f3e912b1f0d8e6a6654c1e9ff16d9eb5c2895b35490a5fa825d275d842efb5e5" - + "45ae827a6fb105d6fc6d125c2a8c1253f753b4973a6505b671b0c01b6ef3ac06" - + "4f4aca9fdf2a460e95df34315749ac432cd5154ad42217b7296b3b5bd81dd00b" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "363f4cb9b6605bbd39b3ccf4fdc834721afc8d38cd25becc7830dab5cacf1852" - + "32431ad6d4cfa89730b413b4ca2f744623a0b4b8315fc5e307ed62a043fa4064" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "00000000000000000000000000000000000000000000000000000000ffffffff" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "66b02f76abecb4de13adc2b9b48edf60edf7e243dba5930276655936b53019ee" - + "626327f3509cadc915c8df9d9f97e17f244c828f3ad82b19f6701ae09dc0e22e" - + "659d5386266aef0a8434fe2ac728a655071f4688ad6cd1dae6e58e4767e1a36a" - + "d2614240434f15b189c8f235e35b281454988d72518df3068d8f512fe992e564" - + "a27d2c53207376e3f179aed8f415acbe1bca1a9ec60188f6fea1d1fd99f80db2" - + "c70271638ea0aa5d99e49fca76157e7692c856f4056b7857ed5ce852e69c713f" - + "42dd888295906c9988cc7fdd6715ea2dac745e97fa8ffd63653ee8e17b8a2ada" - + "1148bed585f91c1ab2f38f77e78a4dacd86587ac899961665e0a6f34d7cf0a41" - + "0f1032d3c26d0ab381ba3fd45f1cbb36b04f889584c1868fdc448eaab9bb8592" - + "d91a58c9e735862cdd346201fb9ab75999c6a57a6a474f2248f71c631375f0a8" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "8dcbff6a27f4e6b39c6e19aab7deb9427368bc8dc1082f0dfe57edc94fbb8c3e" - + "1eb36d9f48c5243dad16ab511dcea3c8489ba0dd774befb12fc58f1ae50e7504" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "9fa6ed64a910bee735eafdb80636852367f6a487f6aec0598708ad80cad8ed09" - + "7aa9686c3cc957f88703e1eea87c5412baba2044c78e9161a7b2ac2b21bfef9b" - + "83ca769ba273d3fe1d4cc0d5d0d1ab8a6540f220c1db981fc8885ee34b51263f" - + "90f31816d21895f518bbb893c62ce296ee8416486c37b9dba9d0cb3cdd5f58c5" - + "7e175a69dbf443509bc060f354862d9787490de120ae665cbcba894854eb8aaf" - + "b811e676c506f7c4f2038afa09fc56b66c0c9cefcc00d780d152f1633d1c90af" - + "058355203f7737de6184b08bbf84248f118c3b540a7dc8f5518676fe0ebb2b35" - + "e4c3ec5f6b2f93138c7e7aa4a9b631dc9786b6df2d317208f220055d3fcab328" - + "d50b3131146a9b97443fca616d401b0f5e7c51b3c71b91c3637df35cf4b91864\"", - false, 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000040" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "spend count greater than 2") - public void test04SpendCountGreaterThan2() { - String method = "test2(bytes)"; - txid = PublicMethed.triggerContract(contractAddress, method, - "\"0000000000000000000000000000000000000000000000000000000000000521" - + "0000000000000000000000000000000000000000000000000000000000000680" - + "00000000000000000000000000000000000000000000000000000000000006e0" - + "e5ae9d43a82fc3bc74272dbe20dcf99d2d37ff4ae1689c3f9b53d40113cf5fa8" - + "77e4f78bef9e692985e3a7cd08b92a8380aa0aaec623b7cf3aae5c5a13b41602" - + "9b40cc7690e15b1437f1d88aaf3b44649e23cbd4013b4b41da1efdf31b774779" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "22389ba23e8f871b2a2e71d87c67f03eaace9849e59e8cfd54d5ca783c9b8923" - + "2108740b5326d2802e5a09a263a2668f987425af3f76d61a5d3fa98896ea2a52" - + "db286eec8ac754634b2e099f661b194b79d99c4fc33f9eef975b1b2862f72866" - + "60b225e4f8a010864d82e87cbec9d1fab63a6ae57f04a03f0ced73fb7ba73a71" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000d" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "fa05291a6d8af85cf9dc46f04687c31c12a4de8b2e9b51a55f2b777fb0220ddb" - + "c11bbb1f5025494923823c12fe864d290958384d5bc5e4d920e2bd9db70d005b" - + "b609c343bf7a9b3275ef9419ec1c5dfca574b9e17d67a782b745d2a4c830346d" - + "c77bfd763dfab3fa57596693a828cba2dbbd43fa0daa454136cd61f303e66d72" - + "b91efc162b5a4474b71f9b688af8513bc0e19fbcc834223c02c942f504c4286a" - + "359462bc8993d7b41aead7ac25a25c64b5ae662cea2370ff912e2b2a6ef76bbe" - + "f5ae2a40d920ee79197c99b9ba92df929d445bbd4a0384ce3e637d59939086dc" - + "06042ef2abbb6ea7a599acac186d8fce957c1632d1dc64c9cc04a4a597d42923" - + "491440cfa5bf9c0d387ef77902921343929900044165384c73b30b38c466e4f6" - + "d71f6c1e1b6af43ce2ec0572cd3a28e7c1d5caab600cb001effd07e4182e89be" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "3f153ababa83e18ff39b3149b893d90aebd440521b670b10e8268f7a98f42f06" - + "64efcf611c6c0e11f9edfeca53af7e8fc758f92b713fb4c104df4f6868eb6807" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "4fd0c6e8ed03c4e7797c4da435e5da8b7ecf63c765c8f5817fe29aa4f54e6057" - + "fc5dda67c0109f8ce48344c9c55fb8081a79ad549bd7d162b3f334a9219f8169" - + "a2f5c0f129ac81ab9f93b13a09ec25b40356420dbfe9aa21d367af61415a6a45" - + "82b5efd3f827c7ca99371b1a029e1781156f068e000fdb26ea1b078ce24ae4e1" - + "571001515de0d6d55d2eb7ed4371397b993b2fe4df3addd53248e3adfc24c6fe" - + "81e7b3679ba49fb7e5ef8c13661e7d442210cac48e93398f6d731b3770fcb23e" - + "01c0d34d139df0c31c1dbdf8b08fe0d6029845b1abc990986408191905d04e76" - + "44dd0fc25446d753e94638ee48bb5e088f4483ce9e648093e654ba762ea516df" - + "5bb29cb95cfe347fc2f109ff86d5596bdb89c116b4805b9c6bdc019049b597f3" - + "ee52b22ececc9c7bc4d2c4dd61f9e16bc9feb07a5575f28e577a2d67c1eb3d24" - + "d6583d39f9ea3fe2de10132de6303217cca345201a194ecde8ad098f49d3f63b" - + "2f1f12c99a24d5779e7b4d1e6aa4fc3e1f0bd671701f42e43f3530501e7e2c00" - + "b47f9f2c332b75a849eb94a260a9d2a846212562ec57e927e071962ddc5dda5c" - + "dd9d38d346666659216b4897492ee991b359f9d3adf8bb576720f3b1d49be957" - + "a5c39e894b98bea2538645b434d47e4e7c71fdf765aeae264dd916ff41542eee" - + "063bbed2ff1e40ee1a2a949d5bd197e5936709cdb68151108221b8478fa15d86" - + "d8aff952d21265677a1a363cf7f492de8c0715cb95960d149842e3cee99bdb32\"", - false, 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000040" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "duplicate nullifiers") - public void test05DuplicateNullifiers() { - String method = "test2(bytes)"; - txid = PublicMethed.triggerContract(contractAddress, method, - "\"0000000000000000000000000000000000000000000000000000000000000520" - + "00000000000000000000000000000000000000000000000000000000000007c0" - + "0000000000000000000000000000000000000000000000000000000000000860" - + "f95c0de8b0b573b6a302be34f42cab92fb84ad87be4c9e7c5016ccf4e5692552" - + "79279550d90ed369e0c60b07bc0ace565391941aff977ea101b221c26c14490d" - + "43b5d1b2f29511ff3425e353eb022493f3771203daff96e326477afbe34f7357" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0d9a42f99c055f6218415145bdd3b18496273ccd579c9370cbb312505e65ac2f" - + "88a987bdf381b7a6c41f5683334f9becdec01ab10fa4976a9b15191b9e33fc5c" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "0a43f2568d0aca1a589ff1b76a5147123e1b2c76634970378d742088d68187d7" - + "ed942fe6a584633ab56c66b5824fa24e1380d371abf8aedbcae1b45927fcc236" - + "216f0eafbbdee5f09a136f5dedd86ac5a1ebe7317942bc1999cd0b0b1c11b707" - + "295f566ff309ea8510919d2507b558d7f88151746aab05866a8708d1d70acf42" - + "80f40957fe79d81223cbe9f4eef86be1d4ab19fd3f26f6e08aa27477a8b2160f" - + "44de6d5ce257eccdf91ab3de59461420b20ee95a75bd031f117796e9d1995e85" - + "0c8900a176dd7fc60694716ef82d6ba5d72698f5580503575cecf09a912574d0" - + "02d9761fef0f283242404cbadaa10a70270dae33899c626f27cc626e2c7737d7" - + "5cf62af8190938d92f04d9cb4fcab07d98482843c9b062d5a3c48b1d6259f94c" - + "fa6961c578ecd8b87052edd19b7dc9fa168349cc125ed8e9beddb04450e0558b" - + "0a43f2568d0aca1a589ff1b76a5147123e1b2c76634970378d742088d68187d7" - + "ad182389453f849cf316d7d8c1c8b0da2675c404d09a8a7efb6ab4f81e5d253e" - + "2ab630a209d6dbd4446cc274859a4a97175cac7fc9d20544f5df8d5e6cc37856" - + "a305d5f20688846a81e57dd6141049691495e48ad37cf38183408b4e7ff9a250" - + "b449788c9ef60787fa698915b959979713e800c36966dc737032ab5455374854" - + "e31eebc49b73fc73e709962c69da79e4a3eb55c7311d245e671c83213562da8f" - + "751483514e1c9fead10186b95783a29b880f1c443fcb0c12fad1c8f4f1f1f8b2" - + "10792470322970e28ff0f1cff37531a594a164a4af755fa0d7bb9f24c2d4d7df" - + "2ebe0ff20d7a8a01bbc19ea13f92fe1ea3a8676cdb81efaee30ed4a0e15de0e4" - + "7ce1f4304ad9b824b08f26d655c2c04cdb1e1bf69f8796d5360af32193cceb26" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "36ecefb9a2264d4515ef9c1dc23bd8de87930c2434c3426df4b12afc17ccde46" - + "8e6a99a43572ea6c6110db239cd60627e927d339dfad1920bb88ce2335d91e07" - + "eb6968339a770e46c2c7acbedfdcf93678493f2d3ea03c4a78a2f28925e0e5b4" - + "632d959daaa129e79901713f5b8e3a233219371473b5c8f494dc28bceb399508" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "14c1d485df7f471413cf90be5bae3909ccb5812fbee683f91e1fc5b7178d8852" - + "51a559f6632e3beb24ed1e781de05d6fbb2a4600dd9b2195cdf378a18e2a31ed" - + "49936339e06e29754fe00956cde97338c627806596d681de95db6653d110a7a3" - + "95617c958e1c4d81d4baa99b295bddd6c3da2d4fb9dddc886d31461224ed423a" - + "68c4b504cbed65a19a43efe8c7f721cc9406d8251ca03bbdc6217f6f02077b45" - + "02a1db7de8fab00edc14df913fd7369c4e28294086bd2cb86bd1559133f211b6" - + "1382886e7feb401fdb9fc6ac186dd133d456a7a220615bb410ad79da8b0fb7b7" - + "c404341cf42246820f2afb70466b08658d55b24d3a53707ed88b82827e1358d0" - + "2fe7e8c746f6f7124d2dd3d1717d2859e8390f8f76147e1c767831924058ce70\"", - false, 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000040" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "duplicate output note") - public void test06DuplicateOutputNote() { - String method = "test2(bytes)"; - txid = PublicMethed.triggerContract(contractAddress, method, - "\"0000000000000000000000000000000000000000000000000000000000000520" - + "0000000000000000000000000000000000000000000000000000000000000680" - + "00000000000000000000000000000000000000000000000000000000000006e0" - + "9144cda061b41702bbf641dc3864fa94bc934511895058f01b7bfbdbdb301f8c" - + "d43a44ccd4b131e6b37bd673f8ac6e554eb5b4ab599b6d2b66bc294b7767f506" - + "24614ac147e95287ff8351ed22aa43f2b3e82460dc79b57952e8a39bf4027c47" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "73792777f50b3c5cf7fcf88c7d24baf975c0b4132f2affa898df03874b3e8163" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "92a3ddb4b05a3903fd1d9693e047c7136ac048fd12a7384bfd569e57a265b1f9" - + "2e96a076fcd5722ff4e04bc31cec8aeb2fa5ee3006104a3046c28c4a1584293f" - + "d02e3f11e3ca072628d2fa4755699958223e3467ef7c2039ff699fd9616a5921" - + "0624e9ba16fc55a77d6d872854c638a1c3b6570267130cb43770661793fa9fda" - + "9406c39d8388060ece340e133238f9452e990d1adcc2a91a0bfe46403489043b" - + "51ac2c88e5f0f4fe74b65eb30ec50400a5334a59f3f7f425073edf66bc3ca8cf" - + "f599d1f6742d1ebf0e40dce32d81a4a5cafb1c0ec078a692b95c97265cce277c" - + "11bf7216ff5df3d0d916359abe8b1a5dedf30e5bd5ccf24e6659adc9a4db9558" - + "6369477f2a15447a56249fa1703f31b7b3800aff0cf67772d132bd74cf888ee5" - + "4f45236c6687ac59c89a6157e001bd5190fadba40d515f739636a7dbd77b5108" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "59eca5d4562a891db660355de4de8c14afa64332a8c58afc44108798fc070cba" - + "e90d708016a0f09278a895325c538a0773a011aa9f132dce77e073f39b864606" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "23540e10b3989fc8efdcadda1bcb840cce8580b45718082d5ace9fc4a6f4d45b" - + "d3ad992cbf4a32ece6a7911992c82b94a54705f7fbe680b5250c9b05cb1a31ca" - + "0d26babfd7f9614d5b3cbe84c7006f4aebcea2977d31c9761c5f7ef9c4b0a8eb" - + "98c35f51cd4ed7eef014a56ae50b4efb6555d497991ff7b282183d82f19282d5" - + "5ce8b8f286f6bdeae73981db2a615c7cb9c4fdaa7618502480945647aa1e98eb" - + "4dab59853f9bb3327f7ecbfd92fde4e2f49968562b468ca060447f1036172075" - + "163840bd0f1dca2495392228e23bf49b0934e14a145be29a9e42fb8477925c9f" - + "5a18093e51748a2494ee9191e16511bbae6d8c71d188c46286dd6dc5213b1d7f" - + "95eab6bade1ee763656b06c95d8e907dd8f3310722024cb9322d17724757f686" - + "23540e10b3989fc8efdcadda1bcb840cce8580b45718082d5ace9fc4a6f4d45b" - + "77b1609896bde81495ab555869c6ddbc5c7aac7274830f505486682093284fb6" - + "6f4aeab08e6417ab85026d97aeedfa26407b867227639653ec7a2fb529eb3e9f" - + "a207cb75c8eeb1c77fc3fc9949fc9c95e4b98806a9c6d7558f1f4e8f2a87df47" - + "375dc915db5332f6abbd87967796875ea8922e70e9ba135cdeabd171273884a9" - + "107992ee1a521f648c499620299a45031821e0639abadeec464a3ec3f439a823" - + "15bfe031aaaba0e3bc80fc359d7c7722e448e1e671447c41592cc0f27d35e1bc" - + "b5a4dd42ac75418f70f1a23f0de47fb6a2985ff86958816e52067612df232aa6" - + "9b5cedeab709b800eacc4b2d81582e4bb4f0a0e51571a5b03816126b39e1c9ab\"", - false, 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000040" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "checkResult is false") - public void test07CheckResultIsFalse() { - String method = "test2(bytes)"; - txid = PublicMethed.triggerContract(contractAddress, method, - "\"0000000000000000000000000000000000000000000000000000000000000520" - + "0000000000000000000000000000000000000000000000000000000000000680" - + "00000000000000000000000000000000000000000000000000000000000006e0" - + "f3e912b1f0d8e6a6654c1e9ff16d9eb5c2895b35490a5fa825d275d842efb5e5" - + "45ae827a6fb105d6fc6d125c2a8c1253f753b4973a6505b671b0c86b6ef8ac86" - + "4f4aca9fdf2a460e95df34315749ac432cd5154ad42217b7296b3b5bd81dd00b" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "363f4cb9b6605bbd39b3ccf4fdc834721afc8d38cd25becc7830dab5cacf1852" - + "32431ad6d4cfa89730b413b4ca2f744623a0b4b8315fc5e307ed62a043fa4064" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000003" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "66b02f76abecb4de13adc2b9b48edf60edf7e243dba5930276655936b53019ee" - + "626327f3509cadc915c8df9d9f97e17f244c828f3ad82b19f6701ae09dc0e22e" - + "659d5386266aef0a8434fe2ac728a655071f4688ad6cd1dae6e58e4767e1a36a" - + "d2614240434f15b189c8f235e35b281454988d72518df3068d8f512fe992e564" - + "a27d2c53207376e3f179aed8f415acbe1bca1a9ec60188f6fea1d1fd99f80db2" - + "c70271638ea0aa5d99e49fca76157e7692c856f4056b7857ed5ce852e69c713f" - + "42dd888295906c9988cc7fdd6715ea2dac745e97fa8ffd63653ee8e17b8a2ada" - + "1148bed585f91c1ab2f38f77e78a4dacd86587ac899961665e0a6f34d7cf0a41" - + "0f1032d3c26d0ab381ba3fd45f1cbb36b04f889584c1868fdc448eaab9bb8592" - + "d91a58c9e735862cdd346201fb9ab75999c6a57a6a474f2248f71c631375f0a8" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "8dcbff6a27f4e6b39c6e19aab7deb9427368bc8dc1082f0dfe57edc94fbb8c3e" - + "1eb36d9f48c5243dad16ab511dcea3c8489ba0dd774befb12fc58f1ae50e7504" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "9fa6ed64a910bee735eafdb80636852367f6a487f6aec0598708ad80cad8ed09" - + "7aa9686c3cc957f88703e1eea87c5412baba2044c78e9161a7b2ac2b21bfef9b" - + "83ca769ba273d3fe1d4cc0d5d0d1ab8a6540f220c1db981fc8885ee34b51263f" - + "90f31816d21895f518bbb893c62ce296ee8416486c37b9dba9d0cb3cdd5f58c5" - + "7e175a69dbf443509bc060f354862d9787490de120ae665cbcba894854eb8aaf" - + "b811e676c506f7c4f2038afa09fc56b66c0c9cefcc00d780d152f1633d1c90af" - + "058355203f7737de6184b08bbf84248f118c3b540a7dc8f5518676fe0ebb2b35" - + "e4c3ec5f6b2f93138c7e7aa4a9b631dc9786b6df2d317208f220055d3fcab328" - + "d50b3131146a9b97443fca616d401b0f5e7c51b3c71b91c3637df35cf4b91864\"", - false, 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000040" - + "0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000000", - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray())); - } - - @Test(enabled = true, description = "normal") - public void test08Normal() { - String method = "test3(bytes32[10][],bytes32[2][],bytes32[9][]" - + ",bytes32[2],bytes32,uint64,bytes32[33],uint256)"; - txid = PublicMethed.triggerContract(contractAddress, method, - "0000000000000000000000000000000000000000000000000000000000000520" - + "0000000000000000000000000000000000000000000000000000000000000680" - + "00000000000000000000000000000000000000000000000000000000000006e0" - + "f3e912b1f0d8e6a6654c1e9ff16d9eb5c2895b35490a5fa825d275d842efb5e5" - + "45ae827a6fb105d6fc6d125c2a8c1253f753b4973a6505b671b0c01b6ef3ac06" - + "4f4aca9fdf2a460e95df34315749ac432cd5154ad42217b7296b3b5bd81dd00b" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "363f4cb9b6605bbd39b3ccf4fdc834721afc8d38cd25becc7830dab5cacf1852" - + "32431ad6d4cfa89730b413b4ca2f744623a0b4b8315fc5e307ed62a043fa4064" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000003" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "66b02f76abecb4de13adc2b9b48edf60edf7e243dba5930276655936b53019ee" - + "626327f3509cadc915c8df9d9f97e17f244c828f3ad82b19f6701ae09dc0e22e" - + "659d5386266aef0a8434fe2ac728a655071f4688ad6cd1dae6e58e4767e1a36a" - + "d2614240434f15b189c8f235e35b281454988d72518df3068d8f512fe992e564" - + "a27d2c53207376e3f179aed8f415acbe1bca1a9ec60188f6fea1d1fd99f80db2" - + "c70271638ea0aa5d99e49fca76157e7692c856f4056b7857ed5ce852e69c713f" - + "42dd888295906c9988cc7fdd6715ea2dac745e97fa8ffd63653ee8e17b8a2ada" - + "1148bed585f91c1ab2f38f77e78a4dacd86587ac899961665e0a6f34d7cf0a41" - + "0f1032d3c26d0ab381ba3fd45f1cbb36b04f889584c1868fdc448eaab9bb8592" - + "d91a58c9e735862cdd346201fb9ab75999c6a57a6a474f2248f71c631375f0a8" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "8dcbff6a27f4e6b39c6e19aab7deb9427368bc8dc1082f0dfe57edc94fbb8c3e" - + "1eb36d9f48c5243dad16ab511dcea3c8489ba0dd774befb12fc58f1ae50e7504" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "9fa6ed64a910bee735eafdb80636852367f6a487f6aec0598708ad80cad8ed09" - + "7aa9686c3cc957f88703e1eea87c5412baba2044c78e9161a7b2ac2b21bfef9b" - + "83ca769ba273d3fe1d4cc0d5d0d1ab8a6540f220c1db981fc8885ee34b51263f" - + "90f31816d21895f518bbb893c62ce296ee8416486c37b9dba9d0cb3cdd5f58c5" - + "7e175a69dbf443509bc060f354862d9787490de120ae665cbcba894854eb8aaf" - + "b811e676c506f7c4f2038afa09fc56b66c0c9cefcc00d780d152f1633d1c90af" - + "058355203f7737de6184b08bbf84248f118c3b540a7dc8f5518676fe0ebb2b35" - + "e4c3ec5f6b2f93138c7e7aa4a9b631dc9786b6df2d317208f220055d3fcab328" - + "d50b3131146a9b97443fca616d401b0f5e7c51b3c71b91c3637df35cf4b91864", - true, 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertTrue( - ByteArray.toHexString(infoById.get().getContractResult(0).toByteArray()).length() > 10000); - } - - @AfterClass - public void shutdown() throws InterruptedException { - long balance = PublicMethed.queryAccount(contractExcKey, blockingStubFull).getBalance(); - PublicMethed - .sendcoin(testNetAccountAddress, balance - 1000000, contractExcAddress, contractExcKey, - blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken001.java deleted file mode 100644 index 3e5bd578f5d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken001.java +++ /dev/null @@ -1,262 +0,0 @@ -package stest.tron.wallet.dailybuild.zentoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.DecryptNotes; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.GrpcAPI.SpendResult; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.config.args.Args; -import org.tron.protos.Protocol.Account; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; - -@Slf4j -public class WalletTestZenToken001 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - Optional shieldAddressInfo; - String shieldAddress; - List shieldOutList = new ArrayList<>(); - List shieldInputList = new ArrayList<>(); - DecryptNotes notes; - String memo; - Note note; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey1.getAddress(); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private byte[] tokenId = zenTokenId.getBytes(); - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long costTokenAmount = 8 * zenTokenFee; - private Long sendTokenAmount = 3 * zenTokenFee; - - /** - * constructor. - */ - @BeforeSuite - public void beforeSuite() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - logger.info("enter this"); - if (PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getCreateTime() == 0) { - PublicMethed.sendcoin(foundationZenTokenAddress, 20480000000000L, fromAddress, - testKey002, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String name = "shieldToken"; - Long start = System.currentTimeMillis() + 20000; - Long end = System.currentTimeMillis() + 10000000000L; - Long totalSupply = 15000000000000001L; - String description = "This asset issue is use for exchange transaction stress"; - String url = "This asset issue is use for exchange transaction stress"; - PublicMethed.createAssetIssue(foundationZenTokenAddress, name, totalSupply, 1, 1, - start, end, 1, description, url, 1000L, 1000L, - 1L, 1L, foundationZenTokenKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account getAssetIdFromThisAccount = - PublicMethed.queryAccount(foundationZenTokenAddress, blockingStubFull); - ByteString assetAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - logger.info("AssetId:" + assetAccountId.toString()); - } - } - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(foundationZenTokenKey); - PublicMethed.printAddress(zenTokenOwnerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = false, description = "Public to shield transaction") - public void test1Public2ShieldTransaction() { - Args.setFullNodeAllowShieldedTransaction(true); - shieldAddressInfo = PublicMethed.generateShieldAddress(); - shieldAddress = shieldAddressInfo.get().getAddress(); - logger.info("shieldAddress:" + shieldAddress); - final Long beforeAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - final Long beforeNetUsed = PublicMethed - .getAccountResource(zenTokenOwnerAddress, blockingStubFull).getFreeNetUsed(); - - memo = "aaaaaaa"; - - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress, - "" + (sendTokenAmount - zenTokenFee), memo); - - Assert.assertTrue(PublicMethed.sendShieldCoin( - zenTokenOwnerAddress, sendTokenAmount, - null, null, - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long afterAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - Long afterNetUsed = PublicMethed.getAccountResource(zenTokenOwnerAddress, blockingStubFull) - .getFreeNetUsed(); - Assert.assertTrue(beforeAssetBalance - afterAssetBalance == sendTokenAmount); - Assert.assertTrue(beforeNetUsed == afterNetUsed); - notes = PublicMethed.listShieldNote(shieldAddressInfo, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount = note.getValue(); - Assert.assertTrue(receiverShieldTokenAmount == sendTokenAmount - zenTokenFee); - Assert.assertEquals(memo, PublicMethed.getMemo(note)); - } - - @Test(enabled = false, description = "Shield to public transaction") - public void test2Shield2PublicTransaction() { - note = notes.getNoteTxs(0).getNote(); - SpendResult result = PublicMethed.getSpendResult(shieldAddressInfo.get(), - notes.getNoteTxs(0), blockingStubFull); - Assert.assertTrue(!result.getResult()); - - shieldOutList.clear(); - final Long beforeAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - - Assert.assertTrue(PublicMethed.sendShieldCoin( - null, 0, - shieldAddressInfo.get(), notes.getNoteTxs(0), - shieldOutList, - zenTokenOwnerAddress, note.getValue() - zenTokenFee, - zenTokenOwnerKey, blockingStubFull)); - - //When you want to send shield coin to public account,you should add one zero output amount cm - /* shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress, - "0", memo); - Assert.assertTrue(PublicMethed.sendShieldCoin( - null, 0, - shieldAddressInfo.get(), notes.getNoteTxs(0), - shieldOutList, - zenTokenOwnerAddress, note.getValue() - zenTokenFee, - zenTokenOwnerKey, blockingStubFull));*/ - - PublicMethed.waitProduceNextBlock(blockingStubFull); - result = PublicMethed.getSpendResult(shieldAddressInfo.get(), notes.getNoteTxs(0), - blockingStubFull); - Assert.assertTrue(result.getResult()); - Long afterAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - Assert.assertTrue(afterAssetBalance - beforeAssetBalance == note.getValue() - zenTokenFee); - logger.info("beforeAssetBalance:" + beforeAssetBalance); - logger.info("afterAssetBalance :" + afterAssetBalance); - } - - - @Test(enabled = false, - description = "Output amount can't be zero or below zero") - public void test3Shield2PublicAmountIsZero() { - shieldAddressInfo = PublicMethed.generateShieldAddress(); - shieldAddress = shieldAddressInfo.get().getAddress(); - memo = "Shield to public amount is zero"; - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress, - "" + (sendTokenAmount - zenTokenFee), memo); - Assert.assertTrue(PublicMethed.sendShieldCoin( - zenTokenOwnerAddress, sendTokenAmount, - null, null, - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - notes = PublicMethed.listShieldNote(shieldAddressInfo, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress, - "" + (note.getValue() - zenTokenFee - (zenTokenFee - note.getValue())), memo); - Assert.assertFalse(PublicMethed.sendShieldCoin( - null, 0, - shieldAddressInfo.get(), notes.getNoteTxs(0), - shieldOutList, - zenTokenOwnerAddress, zenTokenFee - note.getValue(), - zenTokenOwnerKey, blockingStubFull)); - - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress, - "" + (note.getValue() - zenTokenFee), memo); - - Assert.assertFalse(PublicMethed.sendShieldCoin( - null, 0, - shieldAddressInfo.get(), notes.getNoteTxs(0), - shieldOutList, - zenTokenOwnerAddress, 0, - zenTokenOwnerKey, blockingStubFull)); - - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress, - "" + (-zenTokenFee), memo); - Assert.assertFalse(PublicMethed.sendShieldCoin( - null, 0, - shieldAddressInfo.get(), notes.getNoteTxs(0), - shieldOutList, - zenTokenOwnerAddress, note.getValue(), - zenTokenOwnerKey, blockingStubFull)); - - - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - PublicMethed.transferAsset(foundationZenTokenAddress, tokenId, - PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull), zenTokenOwnerAddress, zenTokenOwnerKey, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken002.java deleted file mode 100644 index 4e3851fbb59..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken002.java +++ /dev/null @@ -1,403 +0,0 @@ -package stest.tron.wallet.dailybuild.zentoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.DecryptNotes; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.config.args.Args; -import org.tron.protos.contract.ShieldContract.IncrementalMerkleVoucherInfo; -import org.tron.protos.contract.ShieldContract.OutputPoint; -import org.tron.protos.contract.ShieldContract.OutputPointInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; - - -@Slf4j -public class WalletTestZenToken002 { - - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - Optional sendShieldAddressInfo; - Optional receiverShieldAddressInfo; - String sendShieldAddress; - String receiverShieldAddress; - List shieldOutList = new ArrayList<>(); - DecryptNotes notes; - String memo; - Note sendNote; - Note receiverNote; - IncrementalMerkleVoucherInfo firstMerkleVoucherInfo; - IncrementalMerkleVoucherInfo secondMerkleVoucherInfo; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey1.getAddress(); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private ManagedChannel channelSolidity1 = null; - private ManagedChannel channelPbft = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPbft = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String soliditynode1 = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - private String soliInPbft = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(2); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private byte[] tokenId = zenTokenId.getBytes(); - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long costTokenAmount = 10 * zenTokenFee; - private Long sendTokenAmount = 8 * zenTokenFee; - - /** - * constructor. - */ - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(foundationZenTokenKey); - PublicMethed.printAddress(zenTokenOwnerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelSolidity1 = ManagedChannelBuilder.forTarget(soliditynode1) - .usePlaintext() - .build(); - blockingStubSolidity1 = WalletSolidityGrpc.newBlockingStub(channelSolidity1); - - channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext() - .build(); - blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); - - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Args.setFullNodeAllowShieldedTransaction(true); - sendShieldAddressInfo = PublicMethed.generateShieldAddress(); - sendShieldAddress = sendShieldAddressInfo.get().getAddress(); - logger.info("sendShieldAddressInfo:" + sendShieldAddressInfo); - memo = "Shield memo in" + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress, - "" + (sendTokenAmount - zenTokenFee), memo); - Assert.assertTrue(PublicMethed.sendShieldCoin(zenTokenOwnerAddress, sendTokenAmount, null, - null, shieldOutList, null, 0, zenTokenOwnerKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - sendNote = notes.getNoteTxs(0).getNote(); - } - - @Test(enabled = false, description = "Get merkle tree voucher info") - public void test01GetMerkleTreeVoucherInfo() { - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - sendNote = notes.getNoteTxs(0).getNote(); - OutputPointInfo.Builder request = OutputPointInfo.newBuilder(); - - //ShieldNoteInfo noteInfo = shieldWrapper.getUtxoMapNote().get(shieldInputList.get(i)); - OutputPoint.Builder outPointBuild = OutputPoint.newBuilder(); - outPointBuild.setHash(ByteString.copyFrom(notes.getNoteTxs(0).getTxid().toByteArray())); - outPointBuild.setIndex(notes.getNoteTxs(0).getIndex()); - request.addOutPoints(outPointBuild.build()); - firstMerkleVoucherInfo = blockingStubFull - .getMerkleTreeVoucherInfo(request.build()); - } - - - @Test(enabled = false, description = "Shield to shield transaction") - public void test02Shield2ShieldTransaction() { - receiverShieldAddressInfo = PublicMethed.generateShieldAddress(); - receiverShieldAddress = receiverShieldAddressInfo.get().getAddress(); - - shieldOutList.clear(); - ; - memo = "Send shield to receiver shield memo in" + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, receiverShieldAddress, - "" + (sendNote.getValue() - zenTokenFee), memo); - Assert.assertTrue(PublicMethed.sendShieldCoin( - null, 0, - sendShieldAddressInfo.get(), notes.getNoteTxs(0), - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.listShieldNote(receiverShieldAddressInfo, blockingStubFull); - receiverNote = notes.getNoteTxs(0).getNote(); - logger.info("Receiver note:" + receiverNote.toString()); - Assert.assertTrue(receiverNote.getValue() == sendNote.getValue() - zenTokenFee); - - } - - /** - * constructor. - */ - @Test(enabled = false, description = "Scan note by ivk and scan not by ivk on FullNode") - public void test03ScanNoteByIvkAndOvk() { - //Scan sender note by ovk equals scan receiver note by ivk on FullNode - Note scanNoteByIvk = PublicMethed - .getShieldNotesByIvk(receiverShieldAddressInfo, blockingStubFull).getNoteTxs(0).getNote(); - Note scanNoteByOvk = PublicMethed - .getShieldNotesByOvk(sendShieldAddressInfo, blockingStubFull).getNoteTxs(0).getNote(); - Assert.assertEquals(scanNoteByIvk.getValue(), scanNoteByOvk.getValue()); - Assert.assertEquals(scanNoteByIvk.getMemo(), scanNoteByOvk.getMemo()); - Assert.assertEquals(scanNoteByIvk.getRcm(), scanNoteByOvk.getRcm()); - Assert.assertEquals(scanNoteByIvk.getPaymentAddress(), scanNoteByOvk.getPaymentAddress()); - } - - /** - * constructor. - */ - @Test(enabled = false, description = "Scan note by ivk and scan not by ivk on solidity") - public void test04ScanNoteByIvkAndOvkOnSolidityServer() { - - //Scan sender note by ovk equals scan receiver note by ivk in Solidity - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - Note scanNoteByIvk = PublicMethed - .getShieldNotesByIvkOnSolidity(receiverShieldAddressInfo, blockingStubSolidity) - .getNoteTxs(0).getNote(); - Note scanNoteByOvk = PublicMethed - .getShieldNotesByOvkOnSolidity(sendShieldAddressInfo, blockingStubSolidity) - .getNoteTxs(0).getNote(); - Assert.assertEquals(scanNoteByIvk.getValue(), scanNoteByOvk.getValue()); - Assert.assertEquals(scanNoteByIvk.getMemo(), scanNoteByOvk.getMemo()); - Assert.assertEquals(scanNoteByIvk.getRcm(), scanNoteByOvk.getRcm()); - Assert.assertEquals(scanNoteByIvk.getPaymentAddress(), scanNoteByOvk.getPaymentAddress()); - } - - /** - * constructor. - */ - @Test(enabled = false, description = "Scan note by ivk and scan not by ivk on Pbft") - public void test05ScanNoteByIvkAndOvkOnPbftServer() { - - //Scan sender note by ovk equals scan receiver note by ivk in Solidity - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - Note scanNoteByIvk = PublicMethed - .getShieldNotesByIvkOnSolidity(receiverShieldAddressInfo, blockingStubPbft) - .getNoteTxs(0).getNote(); - Note scanNoteByOvk = PublicMethed - .getShieldNotesByOvkOnSolidity(sendShieldAddressInfo, blockingStubPbft) - .getNoteTxs(0).getNote(); - Assert.assertEquals(scanNoteByIvk.getValue(), scanNoteByOvk.getValue()); - Assert.assertEquals(scanNoteByIvk.getMemo(), scanNoteByOvk.getMemo()); - Assert.assertEquals(scanNoteByIvk.getRcm(), scanNoteByOvk.getRcm()); - Assert.assertEquals(scanNoteByIvk.getPaymentAddress(), scanNoteByOvk.getPaymentAddress()); - } - - - /** - * constructor. - */ - @Test(enabled = false, description = "Scan note by ivk and scan not by ivk on solidity") - public void test06ScanNoteByIvkAndOvkOnSolidityServer() { - //Scan sender note by ovk equals scan receiver note by ivk in Solidity - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity1); - Note scanNoteByIvk = PublicMethed - .getShieldNotesByIvkOnSolidity(receiverShieldAddressInfo, blockingStubSolidity1) - .getNoteTxs(0).getNote(); - Note scanNoteByOvk = PublicMethed - .getShieldNotesByOvkOnSolidity(sendShieldAddressInfo, blockingStubSolidity1) - - .getNoteTxs(0).getNote(); - Assert.assertEquals(scanNoteByIvk.getValue(), scanNoteByOvk.getValue()); - Assert.assertEquals(scanNoteByIvk.getMemo(), scanNoteByOvk.getMemo()); - Assert.assertEquals(scanNoteByIvk.getRcm(), scanNoteByOvk.getRcm()); - Assert.assertEquals(scanNoteByIvk.getPaymentAddress(), scanNoteByOvk.getPaymentAddress()); - } - - /** - * constructor. - */ - @Test(enabled = false, description = "Query whether note is spend on solidity") - public void test07QueryNoteIsSpendOnSolidity() { - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - //Scan sender note by ovk equals scan receiver note by ivk in Solidity - Assert.assertTrue(PublicMethed.getSpendResult(sendShieldAddressInfo.get(), - notes.getNoteTxs(0), blockingStubFull).getResult()); - Assert.assertTrue(PublicMethed.getSpendResultOnSolidity(sendShieldAddressInfo.get(), - notes.getNoteTxs(0), blockingStubSolidity).getResult()); - Assert.assertTrue(PublicMethed.getSpendResultOnSolidity(sendShieldAddressInfo.get(), - notes.getNoteTxs(0), blockingStubSolidity1).getResult()); - } - - /** - * constructor. - */ - @Test(enabled = false, description = "Query whether note is spend on PBFT") - public void test08QueryNoteIsSpendOnPbft() { - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - //Scan sender note by ovk equals scan receiver note by ivk in Solidity - Assert.assertTrue(PublicMethed.getSpendResult(sendShieldAddressInfo.get(), - notes.getNoteTxs(0), blockingStubFull).getResult()); - Assert.assertTrue(PublicMethed.getSpendResultOnSolidity(sendShieldAddressInfo.get(), - notes.getNoteTxs(0), blockingStubPbft).getResult()); - } - - - /** - * constructor. - */ - @Test(enabled = false, description = "Query note and spend status on fullnode and solidity") - public void test09QueryNoteAndSpendStatusOnFullnode() { - Assert.assertFalse( - PublicMethed.getShieldNotesAndMarkByIvk(receiverShieldAddressInfo, blockingStubFull) - .getNoteTxs(0).getIsSpend()); - Note scanNoteByIvk = PublicMethed - .getShieldNotesByIvk(receiverShieldAddressInfo, blockingStubFull) - .getNoteTxs(0).getNote(); - Assert.assertEquals(scanNoteByIvk, - PublicMethed.getShieldNotesAndMarkByIvk(receiverShieldAddressInfo, blockingStubFull) - .getNoteTxs(0).getNote()); - - Assert.assertFalse(PublicMethed - .getShieldNotesAndMarkByIvkOnSolidity(receiverShieldAddressInfo, blockingStubSolidity) - .getNoteTxs(0).getIsSpend()); - scanNoteByIvk = PublicMethed - .getShieldNotesByIvkOnSolidity(receiverShieldAddressInfo, blockingStubSolidity) - .getNoteTxs(0).getNote(); - Assert.assertEquals(scanNoteByIvk, PublicMethed - .getShieldNotesAndMarkByIvkOnSolidity(receiverShieldAddressInfo, blockingStubSolidity) - .getNoteTxs(0).getNote()); - Assert.assertEquals(scanNoteByIvk, PublicMethed - .getShieldNotesAndMarkByIvkOnSolidity(receiverShieldAddressInfo, blockingStubPbft) - .getNoteTxs(0).getNote()); - - shieldOutList.clear(); - memo = "Query note and spend status on fullnode " + System.currentTimeMillis(); - notes = PublicMethed.listShieldNote(receiverShieldAddressInfo, blockingStubFull); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress, - "" + (notes.getNoteTxs(0).getNote().getValue() - zenTokenFee), memo); - Assert.assertTrue(PublicMethed.sendShieldCoin( - null, 0, - receiverShieldAddressInfo.get(), notes.getNoteTxs(0), - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - - Assert.assertTrue( - PublicMethed.getShieldNotesAndMarkByIvk(receiverShieldAddressInfo, blockingStubFull) - .getNoteTxs(0).getIsSpend()); - - Assert.assertTrue(PublicMethed - .getShieldNotesAndMarkByIvkOnSolidity(receiverShieldAddressInfo, blockingStubSolidity) - .getNoteTxs(0).getIsSpend()); - } - - @Test(enabled = false, description = "Get merkle tree voucher info") - public void test10GetMerkleTreeVoucherInfo() { - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - sendNote = notes.getNoteTxs(0).getNote(); - OutputPointInfo.Builder request = OutputPointInfo.newBuilder(); - - //ShieldNoteInfo noteInfo = shieldWrapper.getUtxoMapNote().get(shieldInputList.get(i)); - OutputPoint.Builder outPointBuild = OutputPoint.newBuilder(); - outPointBuild.setHash(ByteString.copyFrom(notes.getNoteTxs(0).getTxid().toByteArray())); - outPointBuild.setIndex(notes.getNoteTxs(0).getIndex()); - request.addOutPoints(outPointBuild.build()); - secondMerkleVoucherInfo = blockingStubFull - .getMerkleTreeVoucherInfo(request.build()); - - Assert.assertEquals(firstMerkleVoucherInfo, secondMerkleVoucherInfo); - } - - @Test(enabled = false, description = "Get merkle tree voucher info from Solidity") - public void test11GetMerkleTreeVoucherInfoFromSolidity() { - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - sendNote = notes.getNoteTxs(0).getNote(); - OutputPointInfo.Builder request = OutputPointInfo.newBuilder(); - - //ShieldNoteInfo noteInfo = shieldWrapper.getUtxoMapNote().get(shieldInputList.get(i)); - OutputPoint.Builder outPointBuild = OutputPoint.newBuilder(); - outPointBuild.setHash(ByteString.copyFrom(notes.getNoteTxs(0).getTxid().toByteArray())); - outPointBuild.setIndex(notes.getNoteTxs(0).getIndex()); - request.addOutPoints(outPointBuild.build()); - secondMerkleVoucherInfo = blockingStubSolidity - .getMerkleTreeVoucherInfo(request.build()); - - Assert.assertEquals(firstMerkleVoucherInfo, secondMerkleVoucherInfo); - } - - @Test(enabled = false, description = "Get merkle tree voucher info from Pbft") - public void test12GetMerkleTreeVoucherInfoFromPbft() { - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - sendNote = notes.getNoteTxs(0).getNote(); - OutputPointInfo.Builder request = OutputPointInfo.newBuilder(); - - //ShieldNoteInfo noteInfo = shieldWrapper.getUtxoMapNote().get(shieldInputList.get(i)); - OutputPoint.Builder outPointBuild = OutputPoint.newBuilder(); - outPointBuild.setHash(ByteString.copyFrom(notes.getNoteTxs(0).getTxid().toByteArray())); - outPointBuild.setIndex(notes.getNoteTxs(0).getIndex()); - request.addOutPoints(outPointBuild.build()); - secondMerkleVoucherInfo = blockingStubPbft - .getMerkleTreeVoucherInfo(request.build()); - - Assert.assertEquals(firstMerkleVoucherInfo, secondMerkleVoucherInfo); - } - - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - PublicMethed.transferAsset(foundationZenTokenAddress, tokenId, - PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull), zenTokenOwnerAddress, zenTokenOwnerKey, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity1 != null) { - channelSolidity1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelPbft != null) { - channelPbft.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken003.java deleted file mode 100644 index 1cabccaa80d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken003.java +++ /dev/null @@ -1,474 +0,0 @@ -package stest.tron.wallet.dailybuild.zentoken; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.DecryptNotes; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.config.args.Args; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; - -@Slf4j -public class WalletTestZenToken003 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - List shieldOutList = new ArrayList<>(); - DecryptNotes notes; - Note note; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey1.getAddress(); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] receiverPublicAddress = ecKey2.getAddress(); - String receiverPublicKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private byte[] tokenId = zenTokenId.getBytes(); - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long zenTokenWhenCreateNewAddress = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenWhenCreateNewAddress"); - private Long costTokenAmount = 20 * zenTokenFee; - private String txid; - private Optional infoById; - private Optional byId; - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - /** - * constructor. - */ - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(foundationZenTokenKey); - PublicMethed.printAddress(zenTokenOwnerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Args.setFullNodeAllowShieldedTransaction(true); - } - - @Test(enabled = false, - description = "Public to two shield transaction") - public void test1Public2ShieldTransaction() { - Optional shieldAddressInfo1 = PublicMethed.generateShieldAddress(); - String shieldAddress1 = shieldAddressInfo1.get().getAddress(); - Optional shieldAddressInfo2 = PublicMethed.generateShieldAddress(); - String shieldAddress2 = shieldAddressInfo2.get().getAddress(); - logger.info("shieldAddress1:" + shieldAddress1); - logger.info("shieldAddress2:" + shieldAddress2); - - final Long beforeAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - final Long beforeNetUsed = PublicMethed - .getAccountResource(zenTokenOwnerAddress, blockingStubFull).getFreeNetUsed(); - - Long sendToShiledAddress1Amount = 3 * zenTokenFee; - Long sendToShiledAddress2Amount = costTokenAmount - sendToShiledAddress1Amount - zenTokenFee; - String memo1 = "Public to shield address1 transaction"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress1, - "" + sendToShiledAddress1Amount, memo1); - String memo2 = "Public to shield address2 transaction"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress2, - "" + sendToShiledAddress2Amount, memo2); - txid = PublicMethed.sendShieldCoinGetTxid( - zenTokenOwnerAddress, costTokenAmount, - null, null, - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getShieldedTransactionFee() == zenTokenFee); - byId = PublicMethed.getTransactionById(txid, blockingStubFull); - Assert.assertTrue(byId.get().getSignatureCount() == 1); - Long afterAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - final Long afterNetUsed = PublicMethed - .getAccountResource(zenTokenOwnerAddress, blockingStubFull) - .getFreeNetUsed(); - logger.info("beforeAssetBalance:" + beforeAssetBalance); - logger.info("afterAssetBalance:" + afterAssetBalance); - Assert.assertTrue(beforeAssetBalance - afterAssetBalance == costTokenAmount); - Assert.assertTrue(beforeNetUsed == afterNetUsed); - notes = PublicMethed.listShieldNote(shieldAddressInfo1, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount1 = note.getValue(); - logger.info("receiverShieldTokenAmount1:" + receiverShieldTokenAmount1); - logger.info("sendToShiledAddress1Amount:" + sendToShiledAddress1Amount); - Assert.assertEquals(receiverShieldTokenAmount1, sendToShiledAddress1Amount); - Assert.assertEquals(memo1, PublicMethed.getMemo(note)); - - notes = PublicMethed.listShieldNote(shieldAddressInfo2, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount2 = note.getValue(); - Assert.assertEquals(receiverShieldTokenAmount2, sendToShiledAddress2Amount); - Assert.assertEquals(memo2, PublicMethed.getMemo(note)); - - } - - @Test(enabled = false, - description = "Public to one public and one shield transaction") - public void test2Public2OneShieldAndOnePublicTransaction() { - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional shieldAddressInfo1 = PublicMethed.generateShieldAddress(); - String shieldAddress1 = shieldAddressInfo1.get().getAddress(); - logger.info("shieldAddress1:" + shieldAddress1); - - final Long beforeAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - final Long beforeNetUsed = PublicMethed - .getAccountResource(zenTokenOwnerAddress, blockingStubFull).getFreeNetUsed(); - - final Long beforeBalance = PublicMethed - .queryAccount(receiverPublicAddress, blockingStubFull).getBalance(); - Long sendToShiledAddress1Amount = 1 * zenTokenFee; - //When receiver public address don't active,the fee is 1000000 - Long sendToPublicAddressAmount = costTokenAmount - - sendToShiledAddress1Amount - zenTokenWhenCreateNewAddress; - logger.info("costTokenAmount " + costTokenAmount); - logger.info("sendToShiledAddress1Amount " + sendToShiledAddress1Amount); - logger.info("sendToPublicAddressAmount " + sendToPublicAddressAmount); - shieldOutList.clear(); - String memo1 = "Public to shield address1 transaction"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress1, - "" + sendToShiledAddress1Amount, memo1); - - txid = PublicMethed.sendShieldCoinGetTxid( - zenTokenOwnerAddress, costTokenAmount, - null, null, - shieldOutList, - receiverPublicAddress, sendToPublicAddressAmount, - zenTokenOwnerKey, blockingStubFull); - logger.info("txid:" + txid); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getShieldedTransactionFee() == zenTokenWhenCreateNewAddress); - byId = PublicMethed.getTransactionById(txid, blockingStubFull); - Assert.assertTrue(byId.get().getSignatureCount() == 1); - - Long afterAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - final Long afterNetUsed = PublicMethed - .getAccountResource(zenTokenOwnerAddress, blockingStubFull) - .getFreeNetUsed(); - final Long afterBalance = PublicMethed - .queryAccount(receiverPublicAddress, blockingStubFull).getBalance(); - logger.info("beforeAssetBalance:" + beforeAssetBalance); - logger.info("afterAssetBalance:" + afterAssetBalance); - Assert.assertTrue(beforeAssetBalance - afterAssetBalance == costTokenAmount); - Assert.assertTrue(beforeNetUsed == afterNetUsed); - Assert.assertTrue(beforeBalance - afterBalance == 0); - - notes = PublicMethed.listShieldNote(shieldAddressInfo1, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount1 = note.getValue(); - logger.info("receiverShieldTokenAmount1:" + receiverShieldTokenAmount1); - logger.info("sendToShiledAddress1Amount:" + sendToShiledAddress1Amount); - Assert.assertEquals(receiverShieldTokenAmount1, sendToShiledAddress1Amount); - Assert.assertEquals(memo1, PublicMethed.getMemo(note)); - - Long afterReceiverPublicAssetBalance = PublicMethed.getAssetIssueValue(receiverPublicAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - Assert.assertEquals(afterReceiverPublicAssetBalance, sendToPublicAddressAmount); - } - - @Test(enabled = false, - description = "Public to one public and two shield transaction") - public void test3Public2OneShieldAndOnePublicTransaction() { - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional shieldAddressInfo1 = PublicMethed.generateShieldAddress(); - String shieldAddress1 = shieldAddressInfo1.get().getAddress(); - Optional shieldAddressInfo2 = PublicMethed.generateShieldAddress(); - String shieldAddress2 = shieldAddressInfo2.get().getAddress(); - logger.info("shieldAddress1:" + shieldAddress1); - logger.info("shieldAddress2:" + shieldAddress2); - - final Long beforeAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - final Long beforeNetUsed = PublicMethed - .getAccountResource(zenTokenOwnerAddress, blockingStubFull).getFreeNetUsed(); - - Long sendToShiledAddress1Amount = 1 * zenTokenFee; - Long sendToShiledAddress2Amount = 2 * zenTokenFee; - final Long sendToPublicAddressAmount = costTokenAmount - sendToShiledAddress1Amount - - sendToShiledAddress2Amount - zenTokenFee; - shieldOutList.clear(); - String memo1 = "Public to shield address1 transaction"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress1, - "" + sendToShiledAddress1Amount, memo1); - String memo2 = "Public to shield address2 transaction"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress2, - "" + sendToShiledAddress2Amount, memo2); - final Long beforeReceiverPublicAssetBalance = PublicMethed - .getAssetIssueValue(receiverPublicAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - - txid = PublicMethed.sendShieldCoinGetTxid( - zenTokenOwnerAddress, costTokenAmount, - null, null, - shieldOutList, - receiverPublicAddress, sendToPublicAddressAmount, - zenTokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getShieldedTransactionFee() == zenTokenFee); - byId = PublicMethed.getTransactionById(txid, blockingStubFull); - Assert.assertTrue(byId.get().getSignatureCount() == 1); - - Long afterAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - final Long afterNetUsed = PublicMethed - .getAccountResource(zenTokenOwnerAddress, blockingStubFull) - .getFreeNetUsed(); - logger.info("beforeAssetBalance:" + beforeAssetBalance); - logger.info("afterAssetBalance:" + afterAssetBalance); - Assert.assertTrue(beforeAssetBalance - afterAssetBalance == costTokenAmount); - Assert.assertTrue(beforeNetUsed == afterNetUsed); - - notes = PublicMethed.listShieldNote(shieldAddressInfo1, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount1 = note.getValue(); - Assert.assertEquals(receiverShieldTokenAmount1, sendToShiledAddress1Amount); - Assert.assertEquals(memo1, PublicMethed.getMemo(note)); - - notes = PublicMethed.listShieldNote(shieldAddressInfo2, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount2 = note.getValue(); - Assert.assertEquals(receiverShieldTokenAmount2, sendToShiledAddress2Amount); - Assert.assertEquals(memo2, PublicMethed.getMemo(note)); - - Long afterReceiverPublicAssetBalance = PublicMethed.getAssetIssueValue(receiverPublicAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - Assert.assertTrue(afterReceiverPublicAssetBalance - - beforeReceiverPublicAssetBalance == sendToPublicAddressAmount); - } - - @Test(enabled = false, - description = "Public to one smart contract and one shield transaction") - public void test4Public2OneShieldAndOneSmartContractAddressTransaction() { - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional shieldAddressInfo1 = PublicMethed.generateShieldAddress(); - String shieldAddress1 = shieldAddressInfo1.get().getAddress(); - logger.info("shieldAddress1:" + shieldAddress1); - - final Long beforeAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - final Long beforeNetUsed = PublicMethed - .getAccountResource(zenTokenOwnerAddress, blockingStubFull).getFreeNetUsed(); - - final Long beforeBalance = PublicMethed - .queryAccount(receiverPublicAddress, blockingStubFull).getBalance(); - Long sendToShiledAddress1Amount = 1 * zenTokenFee; - - shieldOutList.clear(); - String memo1 = "Public to shield address1 transaction"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress1, - "" + sendToShiledAddress1Amount, memo1); - - String contractName = "tokenBalanceContract"; - String code = "608060405260ff806100126000396000f30060806040526" - + "004361060485763ffffffff7c010000000000000" - + "0000000000000000000000000000000000000000000600035041663a730416e8114604d578063b69ef8a8146" - + "081575b600080fd5b606f73ffffffffffffffffffffffffffffffffffffffff6004351660243560ab565b604" - + "08051918252519081900360200190f35b348015608c57600080fd5b50d38015609857600080fd5b50d280156" - + "0a457600080fd5b50606f60cd565b73ffffffffffffffffffffffffffffffffffffffff90911690d16000908" - + "15590565b600054815600a165627a7a723058202b6235122df66c062c2e723ad58a9fea93346f3bc19898971" - + "8f211aa1dbd2d7a0029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}," - + "{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getTokenBalnce\",\"outputs\":" - + "[{\"name\":\"b\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":" - + "\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":" - + "\"balance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false," - + "\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true," - + "\"stateMutability\":\"payable\",\"type\":\"constructor\"}]"; - txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 100, null, testKey002, fromAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - logger.info(txid); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - com.google.protobuf.ByteString contractAddress = infoById.get().getContractAddress(); - SmartContract smartContract = PublicMethed - .getContract(contractAddress.toByteArray(), blockingStubFull); - org.junit.Assert.assertTrue(smartContract.getAbi() != null); - Long sendToPublicAddressAmount = costTokenAmount - sendToShiledAddress1Amount - zenTokenFee; - txid = PublicMethed.sendShieldCoinGetTxid( - zenTokenOwnerAddress, costTokenAmount, - null, null, - shieldOutList, - contractAddress.toByteArray(), sendToPublicAddressAmount, - zenTokenOwnerKey, blockingStubFull); - logger.info("txid:" + txid); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getShieldedTransactionFee() == zenTokenFee); - byId = PublicMethed.getTransactionById(txid, blockingStubFull); - Assert.assertTrue(byId.get().getSignatureCount() == 1); - - Long afterAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - final Long afterNetUsed = PublicMethed - .getAccountResource(zenTokenOwnerAddress, blockingStubFull) - .getFreeNetUsed(); - final Long afterBalance = PublicMethed - .queryAccount(receiverPublicAddress, blockingStubFull).getBalance(); - logger.info("beforeAssetBalance:" + beforeAssetBalance); - logger.info("afterAssetBalance:" + afterAssetBalance); - Assert.assertTrue(beforeAssetBalance - afterAssetBalance == costTokenAmount); - Assert.assertTrue(beforeNetUsed == afterNetUsed); - Assert.assertTrue(beforeBalance - afterBalance == 0); - - notes = PublicMethed.listShieldNote(shieldAddressInfo1, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount1 = note.getValue(); - logger.info("receiverShieldTokenAmount1:" + receiverShieldTokenAmount1); - logger.info("sendToShiledAddress1Amount:" + sendToShiledAddress1Amount); - Assert.assertEquals(receiverShieldTokenAmount1, sendToShiledAddress1Amount); - Assert.assertEquals(memo1, PublicMethed.getMemo(note)); - - Long afterReceiverPublicAssetBalance = PublicMethed - .getAssetIssueValue(contractAddress.toByteArray(), - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - Assert.assertEquals(afterReceiverPublicAssetBalance, sendToPublicAddressAmount); - } - - @Test(enabled = false, - description = "Public to two same shield address") - public void test5Public2TwoSameShieldAddress() { - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional shieldAddressInfo1 = PublicMethed.generateShieldAddress(); - String shieldAddress1 = shieldAddressInfo1.get().getAddress(); - - logger.info("shieldAddress1:" + shieldAddress1); - - final Long beforeAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - final Long beforeNetUsed = PublicMethed - .getAccountResource(zenTokenOwnerAddress, blockingStubFull).getFreeNetUsed(); - - Long sendToShiledAddress1Amount = 3 * zenTokenFee; - Long sendToShiledAddress2Amount = costTokenAmount - sendToShiledAddress1Amount - zenTokenFee; - shieldOutList.clear(); - String memo1 = "First public to shield same address transaction"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress1, - "" + sendToShiledAddress1Amount, memo1); - String memo2 = "Second public to shield same address transaction"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress1, - "" + sendToShiledAddress2Amount, memo2); - txid = PublicMethed.sendShieldCoinGetTxid( - zenTokenOwnerAddress, costTokenAmount, - null, null, - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getShieldedTransactionFee() == zenTokenFee); - byId = PublicMethed.getTransactionById(txid, blockingStubFull); - Assert.assertTrue(byId.get().getSignatureCount() == 1); - Long afterAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - final Long afterNetUsed = PublicMethed - .getAccountResource(zenTokenOwnerAddress, blockingStubFull) - .getFreeNetUsed(); - logger.info("beforeAssetBalance:" + beforeAssetBalance); - logger.info("afterAssetBalance:" + afterAssetBalance); - Assert.assertTrue(beforeAssetBalance - afterAssetBalance == costTokenAmount); - Assert.assertTrue(beforeNetUsed == afterNetUsed); - notes = PublicMethed.getShieldNotesByIvk(shieldAddressInfo1, blockingStubFull); - Assert.assertTrue(notes.getNoteTxsCount() == 2); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount1 = note.getValue(); - logger.info("receiverShieldTokenAmount1:" + receiverShieldTokenAmount1); - logger.info("sendToShiledAddress1Amount:" + sendToShiledAddress1Amount); - Assert.assertEquals(receiverShieldTokenAmount1, sendToShiledAddress1Amount); - Assert.assertEquals(memo1, PublicMethed.getMemo(note)); - - note = notes.getNoteTxs(1).getNote(); - Long receiverShieldTokenAmount2 = note.getValue(); - Assert.assertEquals(receiverShieldTokenAmount2, sendToShiledAddress2Amount); - Assert.assertEquals(memo2, PublicMethed.getMemo(note)); - - } - - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - PublicMethed.transferAsset(foundationZenTokenAddress, tokenId, - PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull), zenTokenOwnerAddress, zenTokenOwnerKey, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken004.java deleted file mode 100644 index 51cea166ab1..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken004.java +++ /dev/null @@ -1,286 +0,0 @@ -package stest.tron.wallet.dailybuild.zentoken; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.DecryptNotes; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.config.args.Args; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; - -@Slf4j -public class WalletTestZenToken004 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - List shieldOutList = new ArrayList<>(); - DecryptNotes notes; - Note note; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey1.getAddress(); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] receiverPublicAddress = ecKey2.getAddress(); - String receiverPublicKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - Optional sendShieldAddressInfo; - String sendshieldAddress; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private byte[] tokenId = zenTokenId.getBytes(); - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long costTokenAmount = 20 * zenTokenFee; - private Long zenTokenWhenCreateNewAddress = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenWhenCreateNewAddress"); - - /** - * constructor. - */ - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(foundationZenTokenKey); - PublicMethed.printAddress(zenTokenOwnerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - Args.setFullNodeAllowShieldedTransaction(true); - Assert.assertTrue(PublicMethed.sendcoin(receiverPublicAddress, 1000000L, - fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = false, description = "Shield to two shield transaction") - public void test1Shield2TwoShieldTransaction() { - sendShieldAddressInfo = PublicMethed.generateShieldAddress(); - sendshieldAddress = sendShieldAddressInfo.get().getAddress(); - String memo = "Use to TestZenToken004 shield address"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendshieldAddress, - "" + costTokenAmount, memo); - Assert.assertTrue(PublicMethed.sendShieldCoin( - foundationZenTokenAddress, costTokenAmount + zenTokenFee, - null, null, - shieldOutList, - null, 0, - foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - - Optional shieldAddressInfo1 = PublicMethed.generateShieldAddress(); - String shieldAddress1 = shieldAddressInfo1.get().getAddress(); - Optional shieldAddressInfo2 = PublicMethed.generateShieldAddress(); - String shieldAddress2 = shieldAddressInfo2.get().getAddress(); - logger.info("shieldAddress1:" + shieldAddress1); - logger.info("shieldAddress2:" + shieldAddress2); - - Long sendToShiledAddress1Amount = 3 * zenTokenFee; - Long sendToShiledAddress2Amount = costTokenAmount - sendToShiledAddress1Amount - zenTokenFee; - String memo1 = "Shield to shield address1 transaction"; - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress1, - "" + sendToShiledAddress1Amount, memo1); - String memo2 = "Shield to shield address2 transaction"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress2, - "" + sendToShiledAddress2Amount, memo2); - - Assert.assertTrue(PublicMethed.sendShieldCoin( - null, 0, - sendShieldAddressInfo.get(), notes.getNoteTxs(0), - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - Assert.assertTrue(PublicMethed.getSpendResult(sendShieldAddressInfo.get(), - notes.getNoteTxs(0), blockingStubFull).getResult()); - - notes = PublicMethed.listShieldNote(shieldAddressInfo1, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount1 = note.getValue(); - logger.info("receiverShieldTokenAmount1:" + receiverShieldTokenAmount1); - logger.info("sendToShiledAddress1Amount:" + sendToShiledAddress1Amount); - Assert.assertEquals(receiverShieldTokenAmount1, sendToShiledAddress1Amount); - Assert.assertEquals(memo1, PublicMethed.getMemo(note)); - - notes = PublicMethed.listShieldNote(shieldAddressInfo2, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount2 = note.getValue(); - Assert.assertEquals(receiverShieldTokenAmount2, sendToShiledAddress2Amount); - Assert.assertEquals(memo2, PublicMethed.getMemo(note)); - - } - - @Test(enabled = false, - description = "Shield to one public and one shield transaction") - public void test2Shield2OneShieldAndOnePublicTransaction() { - sendShieldAddressInfo = PublicMethed.generateShieldAddress(); - sendshieldAddress = sendShieldAddressInfo.get().getAddress(); - String memo = "Use to TestZenToken004 shield address"; - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendshieldAddress, - "" + costTokenAmount, memo); - Assert.assertTrue(PublicMethed.sendShieldCoin( - foundationZenTokenAddress, costTokenAmount + zenTokenFee, - null, null, - shieldOutList, - null, 0, - foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - - Optional shieldAddressInfo1 = PublicMethed.generateShieldAddress(); - String shieldAddress1 = shieldAddressInfo1.get().getAddress(); - logger.info("shieldAddress1:" + shieldAddress1); - - Long sendToShiledAddress1Amount = 1 * zenTokenFee; - Long sendToPublicAddressAmount = costTokenAmount - sendToShiledAddress1Amount - zenTokenFee; - shieldOutList.clear(); - String memo1 = "Shield to shield address1 transaction"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress1, - "" + sendToShiledAddress1Amount, memo1); - - Assert.assertTrue(PublicMethed.sendShieldCoin( - null, 0, - sendShieldAddressInfo.get(), notes.getNoteTxs(0), - shieldOutList, - receiverPublicAddress, sendToPublicAddressAmount, - zenTokenOwnerKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - Assert.assertTrue(PublicMethed.getSpendResult(sendShieldAddressInfo.get(), - notes.getNoteTxs(0), blockingStubFull).getResult()); - - notes = PublicMethed.listShieldNote(shieldAddressInfo1, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount1 = note.getValue(); - logger.info("receiverShieldTokenAmount1:" + receiverShieldTokenAmount1); - logger.info("sendToShiledAddress1Amount:" + sendToShiledAddress1Amount); - Assert.assertEquals(receiverShieldTokenAmount1, sendToShiledAddress1Amount); - Assert.assertEquals(memo1, PublicMethed.getMemo(note)); - - Long afterReceiverPublicAssetBalance = PublicMethed.getAssetIssueValue(receiverPublicAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - Assert.assertEquals(afterReceiverPublicAssetBalance, sendToPublicAddressAmount); - } - - @Test(enabled = false, - description = "Shield to one public and two shield transaction") - public void test3Public2OneShieldAndOnePublicTransaction() { - sendShieldAddressInfo = PublicMethed.generateShieldAddress(); - sendshieldAddress = sendShieldAddressInfo.get().getAddress(); - String memo = "Use to TestZenToken004 shield address"; - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendshieldAddress, - "" + costTokenAmount, memo); - Assert.assertTrue(PublicMethed.sendShieldCoin( - foundationZenTokenAddress, costTokenAmount + zenTokenFee, - null, null, - shieldOutList, - null, 0, - foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - - Optional shieldAddressInfo1 = PublicMethed.generateShieldAddress(); - String shieldAddress1 = shieldAddressInfo1.get().getAddress(); - Optional shieldAddressInfo2 = PublicMethed.generateShieldAddress(); - String shieldAddress2 = shieldAddressInfo2.get().getAddress(); - logger.info("shieldAddress1:" + shieldAddress1); - logger.info("shieldAddress2:" + shieldAddress2); - - Long sendToShiledAddress1Amount = 3 * zenTokenFee; - Long sendToShiledAddress2Amount = 4 * zenTokenFee; - final Long sendToPublicAddressAmount = costTokenAmount - sendToShiledAddress1Amount - - sendToShiledAddress2Amount - zenTokenWhenCreateNewAddress; - shieldOutList.clear(); - String memo1 = "Shield to shield address1 transaction"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress1, - "" + sendToShiledAddress1Amount, memo1); - String memo2 = "Shield to shield address2 transaction"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress2, - "" + sendToShiledAddress2Amount, memo2); - //When receiver public address don't active,the fee is 1000000 - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] notActivePublicAddress = ecKey3.getAddress(); - - Assert.assertTrue(PublicMethed.sendShieldCoin( - null, 0, - sendShieldAddressInfo.get(), notes.getNoteTxs(0), - shieldOutList, - notActivePublicAddress, sendToPublicAddressAmount, - zenTokenOwnerKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - Assert.assertTrue(PublicMethed.getSpendResult(sendShieldAddressInfo.get(), - notes.getNoteTxs(0), blockingStubFull).getResult()); - - notes = PublicMethed.listShieldNote(shieldAddressInfo1, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount1 = note.getValue(); - Assert.assertEquals(receiverShieldTokenAmount1, sendToShiledAddress1Amount); - Assert.assertEquals(memo1, PublicMethed.getMemo(note)); - - notes = PublicMethed.listShieldNote(shieldAddressInfo2, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount2 = note.getValue(); - Assert.assertEquals(receiverShieldTokenAmount2, sendToShiledAddress2Amount); - Assert.assertEquals(memo2, PublicMethed.getMemo(note)); - - final Long afterNotActivePublicAssetBalance = PublicMethed - .getAssetIssueValue(notActivePublicAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - logger.info("afterNotActivePublicAssetBalance:" + afterNotActivePublicAssetBalance); - logger.info("sendToPublicAddressAmount:" + sendToPublicAddressAmount); - Assert.assertEquals(afterNotActivePublicAssetBalance, sendToPublicAddressAmount); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - PublicMethed.transferAsset(foundationZenTokenAddress, tokenId, - PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull), zenTokenOwnerAddress, zenTokenOwnerKey, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken005.java deleted file mode 100644 index 802d49e9485..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken005.java +++ /dev/null @@ -1,215 +0,0 @@ -package stest.tron.wallet.dailybuild.zentoken; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.DecryptNotes; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.config.args.Args; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; - -@Slf4j -public class WalletTestZenToken005 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - List shieldOutList = new ArrayList<>(); - DecryptNotes notes; - Note note; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey1.getAddress(); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] receiverPublicAddress = ecKey2.getAddress(); - String receiverPublicKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private byte[] tokenId = zenTokenId.getBytes(); - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long costTokenAmount = 10 * zenTokenFee; - - /** - * constructor. - */ - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(foundationZenTokenKey); - PublicMethed.printAddress(zenTokenOwnerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(receiverPublicAddress, 1000000L, - fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Args.setFullNodeAllowShieldedTransaction(true); - } - - @Test(enabled = false, - description = "The receiver shield address can't more then 2") - public void test1ReceiverShieldAddressCanNotMoreThenTwo() { - Optional shieldAddressInfo1 = PublicMethed.generateShieldAddress(); - String shieldAddress1 = shieldAddressInfo1.get().getAddress(); - Optional shieldAddressInfo2 = PublicMethed.generateShieldAddress(); - String shieldAddress2 = shieldAddressInfo2.get().getAddress(); - Optional shieldAddressInfo3 = PublicMethed.generateShieldAddress(); - String shieldAddress3 = shieldAddressInfo3.get().getAddress(); - logger.info("shieldAddress1:" + shieldAddress1); - logger.info("shieldAddress2:" + shieldAddress2); - logger.info("shieldAddress3:" + shieldAddress3); - - Long sendToShiledAddress1Amount = 3 * zenTokenFee; - Long sendToShiledAddress2Amount = 2 * zenTokenFee; - Long sendToShiledAddress3Amount = costTokenAmount - sendToShiledAddress1Amount - - sendToShiledAddress2Amount - zenTokenFee; - String memo1 = "Shield to shield address1 transaction"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress1, - "" + sendToShiledAddress1Amount, memo1); - String memo2 = "Shield to shield address2 transaction"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress2, - "" + sendToShiledAddress2Amount, memo2); - String memo3 = "Shield to shield address3 transaction"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress3, - "" + sendToShiledAddress3Amount, memo3); - - Assert.assertFalse(PublicMethed.sendShieldCoin( - zenTokenOwnerAddress, costTokenAmount, - null, null, - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - } - - @Test(enabled = false, - description = "The receiver can't only one public address") - public void test2ReceiverPublicCanNotOnlyOnePublic() { - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - shieldOutList.clear(); - Assert.assertFalse(PublicMethed.sendShieldCoin( - zenTokenOwnerAddress, costTokenAmount, - null, null, - shieldOutList, - receiverPublicAddress, costTokenAmount - zenTokenFee, - zenTokenOwnerKey, blockingStubFull)); - } - - @Test(enabled = false, - description = "Public send amount must equal receiver amount + shieldFee") - public void test3SendAmountMustEqualReceiverAmountPlusShieldFee() { - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional shieldAddressInfo1 = PublicMethed.generateShieldAddress(); - String shieldAddress1 = shieldAddressInfo1.get().getAddress(); - Optional shieldAddressInfo2 = PublicMethed.generateShieldAddress(); - String shieldAddress2 = shieldAddressInfo2.get().getAddress(); - logger.info("shieldAddress1:" + shieldAddress1); - logger.info("shieldAddress2:" + shieldAddress2); - - Long sendToShiledAddress1Amount = 1 * zenTokenFee; - Long sendToShiledAddress2Amount = 2 * zenTokenFee; - - shieldOutList.clear(); - String memo1 = "Public to shield address1 transaction"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress1, - "" + sendToShiledAddress1Amount, memo1); - String memo2 = "Public to shield address2 transaction"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress2, - "" + sendToShiledAddress2Amount, memo2); - - //Public receiver amount is wrong - Long sendToPublicAddressAmount = costTokenAmount - sendToShiledAddress1Amount - - sendToShiledAddress2Amount - zenTokenFee; - Assert.assertFalse(PublicMethed.sendShieldCoin( - zenTokenOwnerAddress, costTokenAmount, - null, null, - shieldOutList, - receiverPublicAddress, sendToPublicAddressAmount - 1, - zenTokenOwnerKey, blockingStubFull)); - - //Shield receiver amount is wrong - sendToShiledAddress1Amount = 1 * zenTokenFee; - sendToShiledAddress2Amount = 2 * zenTokenFee; - sendToPublicAddressAmount = costTokenAmount - sendToShiledAddress1Amount - - sendToShiledAddress2Amount - zenTokenFee; - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress1, - "" + (sendToShiledAddress1Amount - 1), memo1); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress2, - "" + sendToShiledAddress2Amount, memo2); - Assert.assertFalse(PublicMethed.sendShieldCoin( - zenTokenOwnerAddress, costTokenAmount, - null, null, - shieldOutList, - receiverPublicAddress, sendToPublicAddressAmount, - zenTokenOwnerKey, blockingStubFull)); - - sendToShiledAddress1Amount = 1 * zenTokenFee; - sendToShiledAddress2Amount = 2 * zenTokenFee; - sendToPublicAddressAmount = costTokenAmount - sendToShiledAddress1Amount - - sendToShiledAddress2Amount - zenTokenFee; - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress1, - "" + sendToShiledAddress1Amount, memo1); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress2, - "" + sendToShiledAddress2Amount, memo2); - Assert.assertTrue(PublicMethed.sendShieldCoin( - zenTokenOwnerAddress, costTokenAmount, - null, null, - shieldOutList, - receiverPublicAddress, sendToPublicAddressAmount, - zenTokenOwnerKey, blockingStubFull)); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - PublicMethed.transferAsset(foundationZenTokenAddress, tokenId, - PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull), zenTokenOwnerAddress, zenTokenOwnerKey, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken006.java deleted file mode 100644 index 774adda8ed6..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken006.java +++ /dev/null @@ -1,266 +0,0 @@ -package stest.tron.wallet.dailybuild.zentoken; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.DecryptNotes; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.config.args.Args; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; - -@Slf4j -public class WalletTestZenToken006 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - Optional shieldAddressInfo; - String shieldAddress; - List shieldOutList = new ArrayList<>(); - List shieldInputList = new ArrayList<>(); - DecryptNotes notes; - String memo; - Note note; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey1.getAddress(); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private byte[] tokenId = zenTokenId.getBytes(); - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long costTokenAmount = 10 * zenTokenFee; - private Long sendTokenAmount = 3 * zenTokenFee; - - /** - * constructor. - */ - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(foundationZenTokenKey); - PublicMethed.printAddress(zenTokenOwnerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Args.setFullNodeAllowShieldedTransaction(true); - } - - @Test(enabled = false, description = "Shield note memo is one char") - public void test1ShieldMemoIsOneChar() { - shieldAddressInfo = PublicMethed.generateShieldAddress(); - shieldAddress = shieldAddressInfo.get().getAddress(); - logger.info("shieldAddress:" + shieldAddress); - - //One char. - memo = "."; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress, - "" + zenTokenFee, memo); - Assert.assertTrue(PublicMethed.sendShieldCoin( - zenTokenOwnerAddress, zenTokenFee * 2, - null, null, - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.listShieldNote(shieldAddressInfo, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount = note.getValue(); - Assert.assertEquals(receiverShieldTokenAmount, zenTokenFee); - Assert.assertEquals(memo, PublicMethed.getMemo(note)); - } - - @Test(enabled = false, description = "Shield note memo is 512 char") - public void test2ShieldMemoIs512Char() { - shieldAddressInfo = PublicMethed.generateShieldAddress(); - shieldAddress = shieldAddressInfo.get().getAddress(); - logger.info("shieldAddress:" + shieldAddress); - - //512 char. - memo = "1234567812345678123456781234567812345678123456781234567812345678123456781234567812" - + "345678123456781234567812345678123456781234567812345678123456781234567812345678123456" - + "781234567812345678123456781234567812345678123456781234567812345678123456781234567812" - + "345678123456781234567812345678123456781234567812345678123456781234567812345678123456" - + "781234567812345678123456781234567812345678123456781234567812345678123456781234567812" - + "345678123456781234567812345678123456781234567812345678123456781234567812345678123456" - + "7812345678"; - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress, - "" + zenTokenFee, memo); - Assert.assertTrue(PublicMethed.sendShieldCoin( - zenTokenOwnerAddress, zenTokenFee * 2, - null, null, - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.listShieldNote(shieldAddressInfo, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount = note.getValue(); - Assert.assertEquals(receiverShieldTokenAmount, zenTokenFee); - Assert.assertEquals(memo, PublicMethed.getMemo(note)); - - Assert.assertFalse(PublicMethed.sendShieldCoin( - zenTokenOwnerAddress, zenTokenFee * 2, - shieldAddressInfo.get(), notes.getNoteTxs(0), - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - } - - @Test(enabled = false, description = "Shield note memo is 514 char") - public void test3ShieldMemoIs513Char() { - shieldAddressInfo = PublicMethed.generateShieldAddress(); - shieldAddress = shieldAddressInfo.get().getAddress(); - logger.info("shieldAddress:" + shieldAddress); - - //514 char. - memo = "-1234567812345678123456781234567812345678123456781234567812345678123456781234567812" - + "345678123456781234567812345678123456781234567812345678123456781234567812345678123456" - + "781234567812345678123456781234567812345678123456781234567812345678123456781234567812" - + "345678123456781234567812345678123456781234567812345678123456781234567812345678123456" - + "781234567812345678123456781234567812345678123456781234567812345678123456781234567812" - + "345678123456781234567812345678123456781234567812345678123456781234567812345678123456" - + "7812345678"; - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress, - "" + zenTokenFee, memo); - Assert.assertTrue(PublicMethed.sendShieldCoin( - zenTokenOwnerAddress, zenTokenFee * 2, - null, null, - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.listShieldNote(shieldAddressInfo, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount = note.getValue(); - Assert.assertEquals(receiverShieldTokenAmount, zenTokenFee); - logger.info(PublicMethed.getMemo(note)); - Assert.assertTrue(PublicMethed.getMemo(note).length() == 512); - Assert.assertEquals(PublicMethed.getMemo(note), memo.substring(0, 512)); - } - - @Test(enabled = false, description = "Shield note memo is empty") - public void test4ShieldMemoIsEmpty() { - shieldAddressInfo = PublicMethed.generateShieldAddress(); - shieldAddress = shieldAddressInfo.get().getAddress(); - logger.info("shieldAddress:" + shieldAddress); - - //Empty memo - memo = ""; - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress, - "" + zenTokenFee, memo); - Assert.assertTrue(PublicMethed.sendShieldCoin( - zenTokenOwnerAddress, 2 * zenTokenFee, - null, null, - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.listShieldNote(shieldAddressInfo, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount = note.getValue(); - Assert.assertEquals(receiverShieldTokenAmount, zenTokenFee); - Assert.assertEquals(memo, PublicMethed.getMemo(note)); - - //Shield send to it self - memo = ""; - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress, - "0", memo); - Assert.assertTrue(PublicMethed.sendShieldCoin( - null, 0, - shieldAddressInfo.get(), - PublicMethed.listShieldNote(shieldAddressInfo, blockingStubFull).getNoteTxs(0), - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - } - - - @Test(enabled = false, description = "Shield note memo is empty") - public void test5ShieldMemoIsEmpty() { - shieldAddressInfo = PublicMethed.generateShieldAddress(); - shieldAddress = shieldAddressInfo.get().getAddress(); - logger.info("shieldAddress:" + shieldAddress); - - memo = "{\n" - + " note {\n" - + " value: 49957\n" - + " payment_address: \"ztron1f42n7h0l3p8mlaq0d0rxdkhq" - + "n6xuq49xhvj593wfduy24kn3xrmxfpqt8lnmh9ysnu5nzt3zgzx\"\n" - + " rcm: \"\\210x\\256\\211\\256v\\0344\\267\\240\\375\\377xs\\3" - + "50\\3558^Y\\200i0$S\\312KK\\326l\\234J\\b\"\n" - + " memo: \"System.exit(1);\"\n" - + " }\n" - + " txid: \"\\215\\332\\304\\241\\362\\vbt\\250\\364\\353\\30" - + "7\\'o\\275\\313ya*)\\320>\\001\\262B%\\371\\'\\005w\\354\\200\"\n" - + "}"; - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress, - "" + zenTokenFee, memo); - Assert.assertTrue(PublicMethed.sendShieldCoin( - zenTokenOwnerAddress, 2 * zenTokenFee, - null, null, - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.listShieldNote(shieldAddressInfo, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount = note.getValue(); - Assert.assertEquals(receiverShieldTokenAmount, zenTokenFee); - Assert.assertEquals(memo, PublicMethed.getMemo(note)); - - - } - - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - PublicMethed.transferAsset(foundationZenTokenAddress, tokenId, - PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull), zenTokenOwnerAddress, zenTokenOwnerKey, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken007.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken007.java deleted file mode 100644 index b8271b859b5..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken007.java +++ /dev/null @@ -1,639 +0,0 @@ -package stest.tron.wallet.dailybuild.zentoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.BytesMessage; -import org.tron.api.GrpcAPI.DecryptNotes; -import org.tron.api.GrpcAPI.DiversifierMessage; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.ExpandedSpendingKeyMessage; -import org.tron.api.GrpcAPI.IncomingViewingKeyDiversifierMessage; -import org.tron.api.GrpcAPI.IncomingViewingKeyMessage; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.GrpcAPI.PaymentAddressMessage; -import org.tron.api.GrpcAPI.ViewingKeyMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.config.args.Args; -import org.tron.core.zen.address.DiversifierT; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; - -@Slf4j -public class WalletTestZenToken007 { - - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - Optional sendShieldAddressInfo1; - Optional sendShieldAddressInfo2; - Optional sendShieldAddressInfo3; - Optional receiverShieldAddressInfo; - String sendShieldAddress1; - String sendShieldAddress2; - String sendShieldAddress3; - String receiverShieldAddress1; - String receiverShieldAddress2; - String receiverShieldAddress3; - List shieldOutList = new ArrayList<>(); - DecryptNotes notes; - String memo1; - String memo2; - String memo3; - Note sendNote1; - Note sendNote2; - Note sendNote3; - Note receiverNote1; - Note receiverNote2; - Note receiverNote3; - BytesMessage ak; - BytesMessage nk; - BytesMessage sk; - ExpandedSpendingKeyMessage expandedSpendingKeyMessage; - DiversifierMessage diversifierMessage1; - DiversifierMessage diversifierMessage2; - DiversifierMessage diversifierMessage3; - IncomingViewingKeyMessage ivk; - ShieldAddressInfo addressInfo1 = new ShieldAddressInfo(); - ShieldAddressInfo addressInfo2 = new ShieldAddressInfo(); - ShieldAddressInfo addressInfo3 = new ShieldAddressInfo(); - Optional receiverAddressInfo1; - Optional receiverAddressInfo2; - Optional receiverAddressInfo3; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress1 = ecKey1.getAddress(); - String zenTokenOwnerKey1 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress2 = ecKey2.getAddress(); - String zenTokenOwnerKey2 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress3 = ecKey3.getAddress(); - String zenTokenOwnerKey3 = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress4 = ecKey4.getAddress(); - String zenTokenOwnerKey4 = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private ManagedChannel channelSolidity1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity1 = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String soliditynode1 = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private byte[] tokenId = zenTokenId.getBytes(); - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long costTokenAmount = 10 * zenTokenFee; - private Long sendTokenAmount = 8 * zenTokenFee; - - /** - * constructor. - */ - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(foundationZenTokenKey); - PublicMethed.printAddress(zenTokenOwnerKey1); - PublicMethed.printAddress(zenTokenOwnerKey2); - PublicMethed.printAddress(zenTokenOwnerKey3); - PublicMethed.printAddress(zenTokenOwnerKey4); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelSolidity1 = ManagedChannelBuilder.forTarget(soliditynode1) - .usePlaintext() - .build(); - blockingStubSolidity1 = WalletSolidityGrpc.newBlockingStub(channelSolidity1); - - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress1, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress2, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress3, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress4, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Args.setFullNodeAllowShieldedTransaction(true); - sendShieldAddressInfo1 = PublicMethed.generateShieldAddress(); - sendShieldAddressInfo2 = PublicMethed.generateShieldAddress(); - sendShieldAddressInfo3 = PublicMethed.generateShieldAddress(); - sendShieldAddress1 = sendShieldAddressInfo1.get().getAddress(); - sendShieldAddress2 = sendShieldAddressInfo2.get().getAddress(); - sendShieldAddress3 = sendShieldAddressInfo3.get().getAddress(); - logger.info("sendShieldAddressInfo1:" + sendShieldAddressInfo1); - logger.info("sendShieldAddressInfo2:" + sendShieldAddressInfo2); - logger.info("sendShieldAddressInfo3:" + sendShieldAddressInfo3); - memo1 = "Shield memo1 in " + System.currentTimeMillis(); - memo2 = "Shield memo2 in " + System.currentTimeMillis(); - memo3 = "Shield memo3 in " + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress1, - "" + (sendTokenAmount - zenTokenFee), memo1); - Assert.assertTrue(PublicMethed.sendShieldCoin(zenTokenOwnerAddress1, sendTokenAmount, null, - null, shieldOutList, null, 0, zenTokenOwnerKey1, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress2, - "" + (sendTokenAmount - zenTokenFee), memo2); - Assert.assertTrue(PublicMethed.sendShieldCoin(zenTokenOwnerAddress2, sendTokenAmount, null, - null, shieldOutList, null, 0, zenTokenOwnerKey2, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress3, - "" + (sendTokenAmount - zenTokenFee), memo3); - Assert.assertTrue(PublicMethed.sendShieldCoin(zenTokenOwnerAddress3, sendTokenAmount, null, - null, shieldOutList, null, 0, zenTokenOwnerKey3, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.listShieldNote(sendShieldAddressInfo1, blockingStubFull); - sendNote1 = notes.getNoteTxs(0).getNote(); - notes = PublicMethed.listShieldNote(sendShieldAddressInfo2, blockingStubFull); - sendNote2 = notes.getNoteTxs(0).getNote(); - notes = PublicMethed.listShieldNote(sendShieldAddressInfo3, blockingStubFull); - sendNote3 = notes.getNoteTxs(0).getNote(); - - } - - /** - * constructor. - */ - @Test(enabled = false, description = "Get spending key") - public void test01GetSpendingKey() { - sk = blockingStubFull.getSpendingKey(EmptyMessage.newBuilder().build()); - logger.info("sk: " + ByteArray.toHexString(sk.getValue().toByteArray())); - - } - - /** - * constructor. - */ - @Test(enabled = false, description = "Get diversifier") - public void test02GetDiversifier() { - diversifierMessage1 = blockingStubFull.getDiversifier(EmptyMessage.newBuilder().build()); - logger.info("d1: " + ByteArray.toHexString(diversifierMessage1.getD().toByteArray())); - diversifierMessage2 = blockingStubFull.getDiversifier(EmptyMessage.newBuilder().build()); - logger.info("d2: " + ByteArray.toHexString(diversifierMessage2.getD().toByteArray())); - diversifierMessage3 = blockingStubFull.getDiversifier(EmptyMessage.newBuilder().build()); - logger.info("d3: " + ByteArray.toHexString(diversifierMessage3.getD().toByteArray())); - - } - - /** - * constructor. - */ - @Test(enabled = false, description = "Get expanded spending key") - public void test03GetExpandedSpendingKey() { - expandedSpendingKeyMessage = blockingStubFull.getExpandedSpendingKey(sk); - logger.info("ask: " + ByteArray.toHexString(expandedSpendingKeyMessage.getAsk().toByteArray())); - logger.info("nsk: " + ByteArray.toHexString(expandedSpendingKeyMessage.getNsk().toByteArray())); - logger.info("ovk: " + ByteArray.toHexString(expandedSpendingKeyMessage.getOvk().toByteArray())); - - } - - /** - * constructor. - */ - @Test(enabled = false, description = "Get AK from ASK") - public void test04GetAkFromAsk() { - BytesMessage.Builder askBuilder = BytesMessage.newBuilder(); - askBuilder.setValue(expandedSpendingKeyMessage.getAsk()); - ak = blockingStubFull.getAkFromAsk(askBuilder.build()); - logger.info("ak: " + ByteArray.toHexString(ak.getValue().toByteArray())); - } - - /** - * constructor. - */ - @Test(enabled = false, description = "Get Nk from Nsk") - public void test05GetNkFromNsk() { - BytesMessage.Builder nskBuilder = BytesMessage.newBuilder(); - nskBuilder.setValue(expandedSpendingKeyMessage.getNsk()); - nk = blockingStubFull.getNkFromNsk(nskBuilder.build()); - logger.info("nk: " + ByteArray.toHexString(nk.getValue().toByteArray())); - } - - /** - * constructor. - */ - @Test(enabled = false, description = "Get incoming viewing Key") - public void test06GetIncomingViewingKey() { - ViewingKeyMessage.Builder viewBuilder = ViewingKeyMessage.newBuilder(); - viewBuilder.setAk(ak.getValue()); - viewBuilder.setNk(nk.getValue()); - ivk = blockingStubFull.getIncomingViewingKey(viewBuilder.build()); - logger.info("ivk: " + ByteArray.toHexString(ivk.getIvk().toByteArray())); - } - - /** - * constructor. - */ - @Test(enabled = false, description = "Get Zen Payment Address") - public void test07GetZenPaymentAddress() { - IncomingViewingKeyDiversifierMessage.Builder builder = - IncomingViewingKeyDiversifierMessage.newBuilder(); - builder.setD(diversifierMessage1); - builder.setIvk(ivk); - PaymentAddressMessage addressMessage = blockingStubFull.getZenPaymentAddress(builder.build()); - System.out.println("pkd1: " + ByteArray.toHexString(addressMessage.getPkD().toByteArray())); - System.out.println("address1: " + addressMessage.getPaymentAddress()); - addressInfo1.setSk(sk.getValue().toByteArray()); - addressInfo1.setD(new DiversifierT(diversifierMessage1.getD().toByteArray())); - addressInfo1.setIvk(ivk.getIvk().toByteArray()); - addressInfo1.setOvk(expandedSpendingKeyMessage.getOvk().toByteArray()); - addressInfo1.setPkD(addressMessage.getPkD().toByteArray()); - receiverAddressInfo1 = Optional.of(addressInfo1); - - builder.clear(); - builder = IncomingViewingKeyDiversifierMessage.newBuilder(); - builder.setD(diversifierMessage2); - builder.setIvk(ivk); - addressMessage = blockingStubFull.getZenPaymentAddress(builder.build()); - System.out.println("pkd2: " + ByteArray.toHexString(addressMessage.getPkD().toByteArray())); - System.out.println("address2: " + addressMessage.getPaymentAddress()); - addressInfo2.setSk(sk.getValue().toByteArray()); - addressInfo2.setD(new DiversifierT(diversifierMessage2.getD().toByteArray())); - addressInfo2.setIvk(ivk.getIvk().toByteArray()); - addressInfo2.setOvk(expandedSpendingKeyMessage.getOvk().toByteArray()); - addressInfo2.setPkD(addressMessage.getPkD().toByteArray()); - receiverAddressInfo2 = Optional.of(addressInfo2); - - builder.clear(); - builder = IncomingViewingKeyDiversifierMessage.newBuilder(); - builder.setD(diversifierMessage3); - builder.setIvk(ivk); - addressMessage = blockingStubFull.getZenPaymentAddress(builder.build()); - System.out.println("pkd3: " + ByteArray.toHexString(addressMessage.getPkD().toByteArray())); - System.out.println("address3: " + addressMessage.getPaymentAddress()); - addressInfo3.setSk(sk.getValue().toByteArray()); - addressInfo3.setD(new DiversifierT(diversifierMessage3.getD().toByteArray())); - addressInfo3.setIvk(ivk.getIvk().toByteArray()); - addressInfo3.setOvk(expandedSpendingKeyMessage.getOvk().toByteArray()); - addressInfo3.setPkD(addressMessage.getPkD().toByteArray()); - receiverAddressInfo3 = Optional.of(addressInfo3); - - - } - - @Test(enabled = false, description = "Shield to shield transaction") - public void test08Shield2ShieldTransaction() { - //S to S address1 - receiverShieldAddress1 = receiverAddressInfo1.get().getAddress(); - shieldOutList.clear(); - ; - memo1 = "Send shield to receiver1 shield memo in" + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, receiverShieldAddress1, - "" + (sendNote1.getValue() - zenTokenFee), memo1); - notes = PublicMethed.listShieldNote(sendShieldAddressInfo1, blockingStubFull); - Assert.assertTrue(PublicMethed.sendShieldCoin( - null, 0, - sendShieldAddressInfo1.get(), notes.getNoteTxs(0), - shieldOutList, - null, 0, - zenTokenOwnerKey1, blockingStubFull)); - - //S to S address2 - receiverShieldAddress2 = receiverAddressInfo2.get().getAddress(); - shieldOutList.clear(); - ; - memo2 = "Send shield2 to receiver shield memo in" + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, receiverShieldAddress2, - "" + (sendNote2.getValue() - zenTokenFee), memo2); - notes = PublicMethed.listShieldNote(sendShieldAddressInfo2, blockingStubFull); - Assert.assertTrue(PublicMethed.sendShieldCoin( - null, 0, - sendShieldAddressInfo2.get(), notes.getNoteTxs(0), - shieldOutList, - null, 0, - zenTokenOwnerKey2, blockingStubFull)); - - //S to S address3 - receiverShieldAddress3 = receiverAddressInfo3.get().getAddress(); - shieldOutList.clear(); - ; - memo3 = "Send shield3 to receiver shield memo in" + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, receiverShieldAddress3, - "" + (sendNote3.getValue() - zenTokenFee), memo3); - notes = PublicMethed.listShieldNote(sendShieldAddressInfo3, blockingStubFull); - Assert.assertTrue(PublicMethed.sendShieldCoin( - null, 0, - sendShieldAddressInfo3.get(), notes.getNoteTxs(0), - shieldOutList, - null, 0, - zenTokenOwnerKey3, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //Same sk and different d can produce different - // shield address,the notes can scan out by same ivk. - notes = PublicMethed.getShieldNotesByIvk(receiverAddressInfo1, blockingStubFull); - Assert.assertTrue(notes.getNoteTxsCount() == 3); - - receiverNote1 = notes.getNoteTxs(0).getNote(); - logger.info("Receiver note1:" + receiverNote1.toString()); - Assert.assertTrue(receiverNote1.getValue() == sendNote1.getValue() - zenTokenFee); - receiverNote2 = notes.getNoteTxs(1).getNote(); - logger.info("Receiver note2:" + receiverNote2.toString()); - Assert.assertTrue(receiverNote2.getValue() == sendNote2.getValue() - zenTokenFee); - receiverNote3 = notes.getNoteTxs(2).getNote(); - logger.info("Receiver note3:" + receiverNote3.toString()); - Assert.assertTrue(receiverNote3.getValue() == sendNote3.getValue() - zenTokenFee); - } - - @Test(enabled = false, - description = "Shield to shield transaction without ask") - public void test09Shield2ShieldTransactionWithoutAsk() { - //Same sk and different d can produce different shield address, - // the notes can use by scan from same ovk. - sendShieldAddressInfo1 = PublicMethed.generateShieldAddress(); - sendShieldAddress1 = sendShieldAddressInfo1.get().getAddress(); - sendShieldAddressInfo2 = PublicMethed.generateShieldAddress(); - sendShieldAddress2 = sendShieldAddressInfo2.get().getAddress(); - sendShieldAddressInfo3 = PublicMethed.generateShieldAddress(); - sendShieldAddress3 = sendShieldAddressInfo3.get().getAddress(); - - notes = PublicMethed.getShieldNotesByIvk(receiverAddressInfo3, blockingStubFull); - receiverNote1 = notes.getNoteTxs(0).getNote(); - receiverNote2 = notes.getNoteTxs(1).getNote(); - receiverNote3 = notes.getNoteTxs(2).getNote(); - shieldOutList.clear(); - ; - memo1 = "Send shield address 1 without ask" + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress1, - "" + (receiverNote1.getValue() - zenTokenFee), memo1); - - Assert.assertTrue(PublicMethed.sendShieldCoinWithoutAsk( - null, 0, - receiverAddressInfo1.get(), notes.getNoteTxs(0), - shieldOutList, - null, 0, - zenTokenOwnerKey1, blockingStubFull)); - - shieldOutList.clear(); - ; - memo2 = "Send shield address 2 without ask" + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress2, - "" + (receiverNote2.getValue() - zenTokenFee), memo2); - Assert.assertTrue(PublicMethed.sendShieldCoinWithoutAsk( - null, 0, - receiverAddressInfo2.get(), notes.getNoteTxs(1), - shieldOutList, - null, 0, - zenTokenOwnerKey2, blockingStubFull)); - - shieldOutList.clear(); - ; - memo3 = "Send shield address 3 without ask" + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress3, - "" + (receiverNote3.getValue() - zenTokenFee), memo3); - Assert.assertTrue(PublicMethed.sendShieldCoin( - null, 0, - receiverAddressInfo3.get(), notes.getNoteTxs(2), - shieldOutList, - null, 0, - zenTokenOwnerKey3, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - notes = PublicMethed.getShieldNotesByOvk(receiverAddressInfo3, blockingStubFull); - logger.info("notes count:" + notes.getNoteTxsCount()); - Assert.assertTrue(notes.getNoteTxsCount() == 3); - sendNote1 = notes.getNoteTxs(0).getNote(); - logger.info("Receiver1 note:" + sendNote1.toString()); - Assert.assertTrue(sendNote1.getValue() == receiverNote1.getValue() - zenTokenFee); - Assert.assertEquals(memo1, PublicMethed.getMemo(sendNote1)); - - sendNote2 = notes.getNoteTxs(1).getNote(); - logger.info("Receiver2 note:" + sendNote2.toString()); - Assert.assertTrue(sendNote2.getValue() == receiverNote2.getValue() - zenTokenFee); - Assert.assertEquals(memo2, PublicMethed.getMemo(sendNote2)); - - sendNote3 = notes.getNoteTxs(2).getNote(); - logger.info("Receiver3 note:" + sendNote3.toString()); - Assert.assertTrue(sendNote3.getValue() == receiverNote3.getValue() - zenTokenFee); - Assert.assertEquals(memo3, PublicMethed.getMemo(sendNote3)); - } - - @Test(enabled = false, description = "Get shield Nulltifier") - public void test10GetShieldNulltifier() { - notes = PublicMethed.listShieldNote(sendShieldAddressInfo1, blockingStubFull); - Assert.assertEquals(PublicMethed.getShieldNullifier(sendShieldAddressInfo1.get(), - notes.getNoteTxs(0), blockingStubFull).length(), 64); - notes = PublicMethed.listShieldNote(receiverAddressInfo1, blockingStubFull); - Assert.assertEquals(PublicMethed.getShieldNullifier(receiverAddressInfo1.get(), - notes.getNoteTxs(0), blockingStubFull).length(), 64); - - Assert.assertTrue(PublicMethed.getSpendResult(receiverAddressInfo1.get(), - notes.getNoteTxs(0), blockingStubFull).getResult()); - } - - @Test(enabled = false, - description = "Same sk transfer shield address note is spent") - public void test11SameSkTransferShieldAddressNoteCanSpent() { - notes = PublicMethed.getShieldNotesByIvk(receiverAddressInfo2, blockingStubFull); - - receiverNote1 = notes.getNoteTxs(0).getNote(); - shieldOutList.clear(); - memo1 = "Send shield address 1 without ask" + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress1, - "" + (receiverNote1.getValue() - zenTokenFee), memo1); - Assert.assertFalse(PublicMethed.sendShieldCoinWithoutAsk( - null, 0, - receiverAddressInfo1.get(), notes.getNoteTxs(0), - shieldOutList, - null, 0, - zenTokenOwnerKey1, blockingStubFull)); - - Assert.assertTrue(PublicMethed.getSpendResult(receiverAddressInfo1.get(), - notes.getNoteTxs(0), blockingStubFull).getResult()); - Assert.assertTrue(PublicMethed.getSpendResult(receiverAddressInfo2.get(), - notes.getNoteTxs(1), blockingStubFull).getResult()); - Assert.assertTrue(PublicMethed.getSpendResult(receiverAddressInfo3.get(), - notes.getNoteTxs(2), blockingStubFull).getResult()); - } - - @Test(enabled = false, description = "Same sk transfer two shield address," - + "in one transaction send to these shield transaction") - public void test12SameSkTransferTwoShieldAddressInOneTransaction() { - shieldOutList.clear(); - memo1 = "Send to first shield address " + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, receiverShieldAddress1, - "" + zenTokenFee, memo1); - memo2 = "Send to second shield address " + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, receiverShieldAddress2, - "" + (costTokenAmount - 2 * zenTokenFee), memo2); - logger.info("address1 receiver amount:" + zenTokenFee); - logger.info("address2 receiver amount:" + (costTokenAmount - 2 * zenTokenFee)); - Assert.assertTrue(PublicMethed.sendShieldCoinWithoutAsk( - zenTokenOwnerAddress4, costTokenAmount, - null, null, - shieldOutList, - null, 0, - zenTokenOwnerKey4, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.getShieldNotesByIvk(receiverAddressInfo2, blockingStubFull); - Assert.assertTrue(notes.getNoteTxsCount() == 5); - Assert.assertTrue(notes.getNoteTxs(3).getNote().getValue() == zenTokenFee); - Assert.assertTrue(notes.getNoteTxs(4).getNote().getValue() - == (costTokenAmount - 2 * zenTokenFee)); - Assert.assertEquals(PublicMethed.getMemo(notes.getNoteTxs(3).getNote()), memo1); - Assert.assertEquals(PublicMethed.getMemo(notes.getNoteTxs(4).getNote()), memo2); - - shieldOutList.clear(); - ; - receiverNote1 = notes.getNoteTxs(3).getNote(); - receiverNote2 = notes.getNoteTxs(4).getNote(); - memo1 = "Send shield address 1 without ask" + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress1, - "" + (receiverNote1.getValue() - zenTokenFee), memo1); - Assert.assertTrue(PublicMethed.sendShieldCoinWithoutAsk( - null, 0, - receiverAddressInfo1.get(), notes.getNoteTxs(3), - shieldOutList, - null, 0, - zenTokenOwnerKey1, blockingStubFull)); - - shieldOutList.clear(); - ; - memo2 = "Send shield address 2 without ask" + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress2, - "" + (receiverNote2.getValue() - zenTokenFee), memo2); - Assert.assertTrue(PublicMethed.sendShieldCoinWithoutAsk( - null, 0, - receiverAddressInfo2.get(), notes.getNoteTxs(4), - shieldOutList, - null, 0, - zenTokenOwnerKey2, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - notes = PublicMethed.getShieldNotesByIvk(sendShieldAddressInfo1, blockingStubFull); - sendNote1 = notes.getNoteTxs(0).getNote(); - shieldOutList.clear(); - memo2 = "Send receiver a note and spend it" + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress2, - "" + (sendNote1.getValue() - zenTokenFee), memo2); - Assert.assertTrue(PublicMethed.sendShieldCoinWithoutAsk( - null, 0, - sendShieldAddressInfo1.get(), notes.getNoteTxs(0), - shieldOutList, - null, 0, - zenTokenOwnerKey2, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.getShieldNotesByIvk(receiverAddressInfo2, blockingStubFull); - - Assert.assertTrue(PublicMethed.getSpendResult(receiverAddressInfo1.get(), - notes.getNoteTxs(3), blockingStubFull).getResult()); - Assert.assertTrue(PublicMethed.getSpendResult(receiverAddressInfo2.get(), - notes.getNoteTxs(4), blockingStubFull).getResult()); - - notes = PublicMethed.getShieldNotesByOvk(receiverAddressInfo1, blockingStubFull); - Assert.assertTrue(PublicMethed.getSpendResult(sendShieldAddressInfo1.get(), - notes.getNoteTxs(0), blockingStubFull).getResult()); - Assert.assertFalse(PublicMethed.getSpendResult(receiverAddressInfo2.get(), - notes.getNoteTxs(1), blockingStubFull).getResult()); - Assert.assertFalse(PublicMethed.getSpendResult(receiverAddressInfo3.get(), - notes.getNoteTxs(2), blockingStubFull).getResult()); - Assert.assertFalse(PublicMethed.getSpendResult(receiverAddressInfo1.get(), - notes.getNoteTxs(3), blockingStubFull).getResult()); - Assert.assertFalse(PublicMethed.getSpendResult(receiverAddressInfo2.get(), - notes.getNoteTxs(4), blockingStubFull).getResult()); - - //Send shield coin without ask when there is no output shield address - shieldOutList.clear(); - memo2 = "Send receiver a note and spend it" + System.currentTimeMillis(); - - Assert.assertTrue(PublicMethed.sendShieldCoinWithoutAsk( - null, 0, - sendShieldAddressInfo2.get(), notes.getNoteTxs(1), - shieldOutList, - zenTokenOwnerAddress1, notes.getNoteTxs(1).getNote().getValue() - zenTokenFee, - zenTokenOwnerKey2, blockingStubFull)); - - shieldOutList.clear(); - memo2 = "Send receiver a note and spend it" + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress2, - "0", memo2); - Assert.assertTrue(PublicMethed.sendShieldCoinWithoutAsk( - null, 0, - sendShieldAddressInfo3.get(), notes.getNoteTxs(2), - shieldOutList, - zenTokenOwnerAddress1, notes.getNoteTxs(2).getNote().getValue() - zenTokenFee, - zenTokenOwnerKey2, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.getShieldNotesByIvk(receiverAddressInfo2, blockingStubFull); - Assert.assertTrue(PublicMethed.getSpendResult(receiverAddressInfo2.get(), - notes.getNoteTxs(1), blockingStubFull).getResult()); - Assert.assertTrue(PublicMethed.getSpendResult(receiverAddressInfo3.get(), - notes.getNoteTxs(2), blockingStubFull).getResult()); - - - } - - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - PublicMethed.transferAsset(foundationZenTokenAddress, tokenId, - PublicMethed.getAssetIssueValue(zenTokenOwnerAddress1, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull), zenTokenOwnerAddress1, zenTokenOwnerKey1, blockingStubFull); - PublicMethed.transferAsset(foundationZenTokenAddress, tokenId, - PublicMethed.getAssetIssueValue(zenTokenOwnerAddress2, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull), zenTokenOwnerAddress2, zenTokenOwnerKey2, blockingStubFull); - PublicMethed.transferAsset(foundationZenTokenAddress, tokenId, - PublicMethed.getAssetIssueValue(zenTokenOwnerAddress3, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull), zenTokenOwnerAddress3, zenTokenOwnerKey3, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity1 != null) { - channelSolidity1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken008.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken008.java deleted file mode 100644 index fc5cc247661..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken008.java +++ /dev/null @@ -1,214 +0,0 @@ -package stest.tron.wallet.dailybuild.zentoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.DecryptNotes; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.config.args.Args; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; - - -@Slf4j -public class WalletTestZenToken008 { - - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - Optional sendShieldAddressInfo; - Optional receiverShieldAddressInfo; - String sendShieldAddress; - String receiverShieldAddress; - List shieldOutList = new ArrayList<>(); - DecryptNotes notes; - String memo; - Note sendNote; - Note receiverNote; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey1.getAddress(); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private ManagedChannel channelSolidity1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity1 = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String soliditynode1 = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private byte[] tokenId = zenTokenId.getBytes(); - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long costTokenAmount = 1 * zenTokenFee + 1; - private Long sendTokenAmount = 1 * zenTokenFee; - - /** - * constructor. - */ - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(foundationZenTokenKey); - PublicMethed.printAddress(zenTokenOwnerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelSolidity1 = ManagedChannelBuilder.forTarget(soliditynode1) - .usePlaintext() - .build(); - blockingStubSolidity1 = WalletSolidityGrpc.newBlockingStub(channelSolidity1); - - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Args.setFullNodeAllowShieldedTransaction(true); - - - } - - @Test(enabled = false, - description = "Public send 1 token to shield transaction") - public void test1Shield2ShieldTransaction() { - sendShieldAddressInfo = PublicMethed.generateShieldAddress(); - sendShieldAddress = sendShieldAddressInfo.get().getAddress(); - logger.info("sendShieldAddressInfo:" + sendShieldAddressInfo); - memo = "Shield 1 token memo in " + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress, - "1", memo); - Assert.assertFalse(PublicMethed.sendShieldCoin(zenTokenOwnerAddress, sendTokenAmount, null, - null, shieldOutList, null, 0, zenTokenOwnerKey, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendShieldCoin(zenTokenOwnerAddress, costTokenAmount, null, - null, shieldOutList, null, 0, zenTokenOwnerKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - sendNote = notes.getNoteTxs(0).getNote(); - Assert.assertTrue(sendNote.getValue() == 1); - - } - - @Test(enabled = false, - description = "Shield send 0 token to shield transaction") - public void test2Shield2ShieldTransaction() { - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - zenTokenFee * 2, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long afterAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - - logger.info("token balance is " + afterAssetBalance); - sendShieldAddressInfo = PublicMethed.generateShieldAddress(); - sendShieldAddress = sendShieldAddressInfo.get().getAddress(); - logger.info("sendShieldAddressInfo:" + sendShieldAddressInfo); - memo = "Shield costFee token memo in " + System.currentTimeMillis(); - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress, - "" + zenTokenFee, memo); - //logger.info(); - Assert.assertTrue(PublicMethed.sendShieldCoin(zenTokenOwnerAddress, zenTokenFee * 2, null, - null, shieldOutList, null, 0, zenTokenOwnerKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - receiverShieldAddressInfo = PublicMethed.generateShieldAddress(); - receiverShieldAddress = receiverShieldAddressInfo.get().getAddress(); - - shieldOutList.clear(); - memo = "Send shield to receiver shield memo in" + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, receiverShieldAddress, - "0", memo); - - //Wrong proof - Assert.assertFalse(PublicMethed.sendShieldCoin( - null, 0, - sendShieldAddressInfo.get(), notes.getNoteTxs(0), - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - - //Amount is -1 - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, receiverShieldAddress, - "-1", memo); - Assert.assertFalse(PublicMethed.sendShieldCoin( - null, 0, - sendShieldAddressInfo.get(), notes.getNoteTxs(0), - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, receiverShieldAddress, - "0", memo); - Assert.assertTrue(PublicMethed.sendShieldCoin( - null, 0, - sendShieldAddressInfo.get(), notes.getNoteTxs(0), - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.listShieldNote(receiverShieldAddressInfo, blockingStubFull); - receiverNote = notes.getNoteTxs(0).getNote(); - logger.info("Receiver note:" + receiverNote.toString()); - Assert.assertTrue(receiverNote.getValue() == 0); - } - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - PublicMethed.transferAsset(foundationZenTokenAddress, tokenId, - PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull), zenTokenOwnerAddress, zenTokenOwnerKey, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity1 != null) { - channelSolidity1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken009.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken009.java deleted file mode 100644 index 8ad9525c200..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken009.java +++ /dev/null @@ -1,222 +0,0 @@ -package stest.tron.wallet.dailybuild.zentoken; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.DecryptNotes; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.config.args.Args; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; - -@Slf4j -public class WalletTestZenToken009 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - Optional shieldAddressInfo; - String shieldAddress; - Optional receiverAddressInfo; - String receiverAddress; - List shieldOutList = new ArrayList<>(); - List shieldInputList = new ArrayList<>(); - DecryptNotes notes; - String memo; - Note note; - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[2]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey3.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey4.getAddress(); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private byte[] tokenId = zenTokenId.getBytes(); - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long costTokenAmount = 5 * zenTokenFee; - private Long sendTokenAmount = 3 * zenTokenFee; - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - - - /** - * constructor. - */ - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(foundationZenTokenKey); - PublicMethed.printAddress(zenTokenOwnerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - long needCoin = updateAccountPermissionFee * 1 + multiSignFee * 3; - Assert.assertTrue( - PublicMethed.sendcoin(zenTokenOwnerAddress, needCoin + 2048000000L, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - ownerKeyString[0] = zenTokenOwnerKey; - ownerKeyString[1] = manager1Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(zenTokenOwnerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - - logger.info(accountPermissionJson); - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, zenTokenOwnerAddress, zenTokenOwnerKey, - blockingStubFull, ownerKeyString)); - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = false, - description = "Public to shield transaction with mutisign") - public void test1Public2ShieldTransaction() { - Args.setFullNodeAllowShieldedTransaction(true); - shieldAddressInfo = PublicMethed.generateShieldAddress(); - shieldAddress = shieldAddressInfo.get().getAddress(); - logger.info("shieldAddress:" + shieldAddress); - final Long beforeAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - final Long beforeBalance = PublicMethed - .queryAccount(zenTokenOwnerAddress, blockingStubFull).getBalance(); - final Long beforeNetUsed = PublicMethed - .getAccountResource(zenTokenOwnerAddress, blockingStubFull).getFreeNetUsed(); - - memo = "aaaaaaa"; - - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress, - "" + (sendTokenAmount - zenTokenFee), memo); - - Assert.assertTrue(PublicMethedForMutiSign.sendShieldCoin( - zenTokenOwnerAddress, sendTokenAmount, - null, null, - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull, 0, ownerKeyString)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long afterAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - Long afterNetUsed = PublicMethed.getAccountResource(zenTokenOwnerAddress, blockingStubFull) - .getFreeNetUsed(); - Assert.assertTrue(beforeAssetBalance - afterAssetBalance == sendTokenAmount); - logger.info("Before net:" + beforeNetUsed); - logger.info("After net:" + afterNetUsed); - Assert.assertEquals(beforeNetUsed, afterNetUsed); - final Long afterBalance = PublicMethed - .queryAccount(zenTokenOwnerAddress, blockingStubFull).getBalance(); - Assert.assertTrue(beforeBalance - afterBalance == multiSignFee); - notes = PublicMethed.listShieldNote(shieldAddressInfo, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - Long receiverShieldTokenAmount = note.getValue(); - Assert.assertTrue(receiverShieldTokenAmount == sendTokenAmount - zenTokenFee); - Assert.assertEquals(memo, PublicMethed.getMemo(note)); - } - - @Test(enabled = false, - description = "When from is shield,sign this transaction is forbidden") - public void test2ShieldFromShouldNotSign() { - receiverAddressInfo = PublicMethed.generateShieldAddress(); - receiverAddress = shieldAddressInfo.get().getAddress(); - logger.info("receiver address:" + shieldAddress); - - notes = PublicMethed.listShieldNote(shieldAddressInfo, blockingStubFull); - note = notes.getNoteTxs(0).getNote(); - - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, receiverAddress, - "" + (note.getValue() - zenTokenFee), memo); - - Assert.assertFalse(PublicMethedForMutiSign.sendShieldCoin( - null, 321321, - shieldAddressInfo.get(), notes.getNoteTxs(0), - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull, 0, ownerKeyString)); - - Assert.assertFalse(PublicMethed.sendShieldCoin( - null, 321321, - shieldAddressInfo.get(), notes.getNoteTxs(0), - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - - Assert.assertFalse(PublicMethed.getSpendResult(shieldAddressInfo.get(), - notes.getNoteTxs(0), blockingStubFull).getResult()); - - - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - PublicMethedForMutiSign.transferAsset(foundationZenTokenAddress, tokenId, - PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull), zenTokenOwnerAddress, - zenTokenOwnerKey, blockingStubFull, ownerKeyString); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken010.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken010.java deleted file mode 100644 index d629a43e6b6..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken010.java +++ /dev/null @@ -1,260 +0,0 @@ -package stest.tron.wallet.dailybuild.zentoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.DecryptNotes; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.config.args.Args; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; - - -@Slf4j -public class WalletTestZenToken010 { - - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - Optional sendShieldAddressInfo; - Optional receiverShieldAddressInfo; - String sendShieldAddress; - String receiverShieldAddress; - List shieldOutList = new ArrayList<>(); - DecryptNotes notes; - String memo; - Note sendNote; - Note receiverNote; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey1.getAddress(); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private ManagedChannel channelSolidity1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity1 = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String soliditynode1 = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private byte[] tokenId = zenTokenId.getBytes(); - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long costTokenAmount = 10 * zenTokenFee; - private Long sendTokenAmount = 8 * zenTokenFee; - private String txid; - private Optional infoById; - private Optional byId; - - /** - * constructor. - */ - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(foundationZenTokenKey); - PublicMethed.printAddress(zenTokenOwnerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelSolidity1 = ManagedChannelBuilder.forTarget(soliditynode1) - .usePlaintext() - .build(); - blockingStubSolidity1 = WalletSolidityGrpc.newBlockingStub(channelSolidity1); - - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Args.setFullNodeAllowShieldedTransaction(true); - sendShieldAddressInfo = PublicMethed.generateShieldAddress(); - sendShieldAddress = sendShieldAddressInfo.get().getAddress(); - logger.info("sendShieldAddressInfo:" + sendShieldAddressInfo); - memo = "Shield memo in" + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress, - "" + (sendTokenAmount - zenTokenFee), memo); - Assert.assertTrue(PublicMethed.sendShieldCoin(zenTokenOwnerAddress, sendTokenAmount, null, - null, shieldOutList, null, 0, zenTokenOwnerKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - sendNote = notes.getNoteTxs(0).getNote(); - - } - - @Test(enabled = false, description = "Shield to itself transaction") - public void test1Shield2ShieldTransaction() { - shieldOutList.clear(); - memo = "Send shield to itself memo1 in " + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress, - "" + zenTokenFee, memo); - - memo = "Send shield to itself memo2 in " + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress, - "" + (sendNote.getValue() - 2 * zenTokenFee), memo); - Assert.assertTrue(PublicMethed.sendShieldCoin( - null, 0, - sendShieldAddressInfo.get(), notes.getNoteTxs(0), - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.getShieldNotesByIvk(sendShieldAddressInfo, blockingStubFull); - Assert.assertTrue(notes.getNoteTxsCount() == 3); - Assert.assertTrue(notes.getNoteTxs(1).getNote().getValue() == zenTokenFee); - Assert.assertTrue(notes.getNoteTxs(2).getNote().getValue() - == sendNote.getValue() - 2 * zenTokenFee); - Assert.assertEquals(notes.getNoteTxs(1).getNote().getPaymentAddress(), - notes.getNoteTxs(2).getNote().getPaymentAddress()); - Assert.assertEquals(notes.getNoteTxs(1).getTxid(), notes.getNoteTxs(2).getTxid()); - Assert.assertTrue(PublicMethed.getSpendResult(sendShieldAddressInfo.get(), - notes.getNoteTxs(0), blockingStubFull).getResult()); - - notes = PublicMethed.getShieldNotesByOvk(sendShieldAddressInfo, blockingStubFull); - Assert.assertTrue(notes.getNoteTxsCount() == 2); - } - - @Test(enabled = false, description = "From shield only have one zenToken fee") - public void test2Shield2ShieldTransaction() { - sendShieldAddressInfo = PublicMethed.generateShieldAddress(); - sendShieldAddress = sendShieldAddressInfo.get().getAddress(); - logger.info("sendShieldAddressInfo:" + sendShieldAddressInfo); - memo = "Shield memo in" + System.currentTimeMillis(); - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress, - "" + zenTokenFee, memo); - Assert.assertTrue(PublicMethed.sendShieldCoin(zenTokenOwnerAddress, 2 * zenTokenFee, null, - null, shieldOutList, null, 0, zenTokenOwnerKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - sendNote = notes.getNoteTxs(0).getNote(); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - shieldOutList.clear(); - memo = "Send shield to itself memo1 in " + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress, - "0", memo); - - memo = "Send shield to itself memo2 in " + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress, - "0", memo); - Assert.assertTrue(PublicMethed.sendShieldCoin( - null, 0, - sendShieldAddressInfo.get(), notes.getNoteTxs(0), - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - notes = PublicMethed.getShieldNotesByIvk(sendShieldAddressInfo, blockingStubFull); - Assert.assertTrue(notes.getNoteTxsCount() == 3); - logger.info("index 0:" + notes.getNoteTxs(0).getNote().getValue()); - logger.info("index 1:" + notes.getNoteTxs(1).getNote().getValue()); - logger.info("index 2:" + notes.getNoteTxs(2).getNote().getValue()); - Assert.assertTrue(notes.getNoteTxs(1).getNote().getValue() == 0); - Assert.assertTrue(notes.getNoteTxs(2).getNote().getValue() == 0); - Assert.assertEquals(notes.getNoteTxs(1).getNote().getPaymentAddress(), - notes.getNoteTxs(2).getNote().getPaymentAddress()); - Assert.assertEquals(notes.getNoteTxs(1).getTxid(), notes.getNoteTxs(2).getTxid()); - } - - @Test(enabled = false, description = "From public and to public is same one") - public void test3Public2ShieldAndPublicItselfTransaction() { - sendShieldAddressInfo = PublicMethed.generateShieldAddress(); - sendShieldAddress = sendShieldAddressInfo.get().getAddress(); - - ecKey1 = new ECKey(Utils.getRandom()); - zenTokenOwnerAddress = ecKey1.getAddress(); - zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - final Long beforeAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenAddress, blockingStubFull).getAccountId(), - blockingStubFull); - final Long beforeBalance = PublicMethed.queryAccount(zenTokenOwnerAddress, blockingStubFull) - .getBalance(); - shieldOutList.clear(); - memo = "From public and to public is same one memo in " + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress, - "" + 2 * zenTokenFee, memo); - - Assert.assertFalse(PublicMethed - .sendShieldCoin(zenTokenOwnerAddress, costTokenAmount, null, null, shieldOutList, - zenTokenOwnerAddress, 7 * zenTokenFee, zenTokenOwnerKey, blockingStubFull)); - - Long afterAssetBalance = PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenAddress, blockingStubFull).getAccountId(), - blockingStubFull); - Long afterBalance = PublicMethed.queryAccount(zenTokenOwnerAddress, blockingStubFull) - .getBalance(); - - Assert.assertEquals(beforeAssetBalance, afterAssetBalance); - Assert.assertEquals(beforeBalance, afterBalance); - - notes = PublicMethed.getShieldNotesByIvk(sendShieldAddressInfo, blockingStubFull); - Assert.assertTrue(notes.getNoteTxsCount() == 0); - - - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - PublicMethed.transferAsset(foundationZenTokenAddress, tokenId, - PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull), zenTokenOwnerAddress, zenTokenOwnerKey, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity1 != null) { - channelSolidity1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken011.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken011.java deleted file mode 100644 index 591ad4d603e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentoken/WalletTestZenToken011.java +++ /dev/null @@ -1,144 +0,0 @@ -package stest.tron.wallet.dailybuild.zentoken; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.DecryptNotes; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.config.args.Args; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; - - -@Slf4j -public class WalletTestZenToken011 { - - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - Optional sendShieldAddressInfo; - Optional receiverShieldAddressInfo; - String sendShieldAddress; - String receiverShieldAddress; - List shieldOutList = new ArrayList<>(); - DecryptNotes notes; - String memo; - Note sendNote; - Note receiverNote; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey1.getAddress(); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private ManagedChannel channelSolidity1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity1 = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String soliditynode1 = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private byte[] tokenId = zenTokenId.getBytes(); - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long costTokenAmount = 10 * zenTokenFee; - private Long sendTokenAmount = 8 * zenTokenFee; - private String txid; - private Optional infoById; - private Optional byId; - - /** - * constructor. - */ - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(foundationZenTokenKey); - PublicMethed.printAddress(zenTokenOwnerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelSolidity1 = ManagedChannelBuilder.forTarget(soliditynode1) - .usePlaintext() - .build(); - blockingStubSolidity1 = WalletSolidityGrpc.newBlockingStub(channelSolidity1); - - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Args.setFullNodeAllowShieldedTransaction(true); - - - } - - @Test(enabled = false, description = "Test get new shield address ") - public void test1Shield2ShieldTransaction() { - sendShieldAddress = blockingStubFull.getNewShieldedAddress(GrpcAPI.EmptyMessage.newBuilder() - .build()).getPaymentAddress(); - memo = "Shield memo in" + System.currentTimeMillis(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress, - "" + (sendTokenAmount - zenTokenFee), memo); - Assert.assertTrue(PublicMethed.sendShieldCoin(zenTokenOwnerAddress, sendTokenAmount, null, - null, shieldOutList, null, 0, zenTokenOwnerKey, blockingStubFull)); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - PublicMethed.transferAsset(foundationZenTokenAddress, tokenId, - PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull), zenTokenOwnerAddress, zenTokenOwnerKey, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity1 != null) { - channelSolidity1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token001.java deleted file mode 100644 index 99d26ce145e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token001.java +++ /dev/null @@ -1,206 +0,0 @@ -package stest.tron.wallet.dailybuild.zentrc20token; - -import com.alibaba.fastjson.JSONObject; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.Note; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.zen.address.DiversifierT; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; -import stest.tron.wallet.common.client.utils.ShieldNoteInfo; -import stest.tron.wallet.common.client.utils.ZenTrc20Base; - -@Slf4j -public class HttpShieldTrc20Token001 extends ZenTrc20Base { - - List shieldOutList = new ArrayList<>(); - Optional shieldAddressOptionalInfo1; - Optional shieldAddressOptionalInfo2; - Optional shieldAddressOptionalInfo3; - ShieldAddressInfo shieldAddressInfo1 = new ShieldAddressInfo(); - ShieldAddressInfo shieldAddressInfo2 = new ShieldAddressInfo(); - ShieldAddressInfo shieldAddressInfo3 = new ShieldAddressInfo(); - String assetIssueId; - ShieldNoteInfo shieldNote1; - ShieldNoteInfo shieldNote2; - ShieldNoteInfo shieldNote3; - String memo; - String sk; - String d1; - String d2; - String d3; - String ask; - String nsk; - String ovk; - String ak; - String nk; - String ivk; - String pkD1; - String pkD2; - String pkD3; - String paymentAddress1; - String paymentAddress2; - String paymentAddress3; - String rcm; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey1.getAddress(); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private String httpnode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(0); - private String httpSolidityNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private JSONObject responseContent; - private HttpResponse response; - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - //Args.getInstance().setFullNodeAllowShieldedTransaction(true); - //PublicMethed.printAddress(foundationZenTokenKey); - //PublicMethed.printAddress(zenTokenOwnerKey); - } - - @Test(enabled = true, description = "Get spending key by http") - public void test01GetSpendingKey() { - response = HttpMethed.getSpendingKey(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - sk = responseContent.getString("value"); - logger.info("sk: " + sk); - - } - - @Test(enabled = true, description = "Get diversifier by http") - public void test02GetDiversifier() { - response = HttpMethed.getDiversifier(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - d1 = responseContent.getString("d"); - logger.info("d1: " + d1); - - response = HttpMethed.getDiversifier(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - d2 = responseContent.getString("d"); - logger.info("d2: " + d2); - - response = HttpMethed.getDiversifier(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - d3 = responseContent.getString("d"); - logger.info("d3: " + d3); - } - - @Test(enabled = true, description = "Get expanded spending key by http") - public void test03GetExpandedSpendingKey() { - response = HttpMethed.getExpandedSpendingKey(httpnode, sk); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - ask = responseContent.getString("ask"); - nsk = responseContent.getString("nsk"); - ovk = responseContent.getString("ovk"); - logger.info("ask: " + ask); - logger.info("nsk: " + nsk); - logger.info("ovk: " + ovk); - } - - @Test(enabled = true, description = "Get AK from ASK by http") - public void test04GetAkFromAsk() { - response = HttpMethed.getAkFromAsk(httpnode, ask); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - ak = responseContent.getString("value"); - logger.info("ak: " + ak); - } - - @Test(enabled = true, description = "Get Nk from Nsk by http") - public void test05GetNkFromNsk() { - response = HttpMethed.getNkFromNsk(httpnode, nsk); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - nk = responseContent.getString("value"); - logger.info("nk: " + nk); - } - - @Test(enabled = true, description = "Get incoming viewing Key by http") - public void test06GetIncomingViewingKey() { - response = HttpMethed.getIncomingViewingKey(httpnode, ak, nk); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - ivk = responseContent.getString("ivk"); - logger.info("ivk: " + ivk); - } - - @Test(enabled = true, description = "Get Zen Payment Address by http") - public void test07GetZenPaymentAddress() { - response = HttpMethed.getZenPaymentAddress(httpnode, ivk, d1); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - pkD1 = responseContent.getString("pkD"); - paymentAddress1 = responseContent.getString("payment_address"); - System.out.println("pkd1: " + pkD1); - System.out.println("address1: " + paymentAddress1); - shieldAddressInfo1.setSk(ByteArray.fromHexString(sk)); - shieldAddressInfo1.setD(new DiversifierT(ByteArray.fromHexString(d1))); - shieldAddressInfo1.setIvk(ByteArray.fromHexString(ivk)); - shieldAddressInfo1.setOvk(ByteArray.fromHexString(ovk)); - shieldAddressInfo1.setPkD(ByteArray.fromHexString(pkD1)); - shieldAddressOptionalInfo1 = Optional.of(shieldAddressInfo1); - - response = HttpMethed.getZenPaymentAddress(httpnode, ivk, d2); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - pkD2 = responseContent.getString("pkD"); - paymentAddress2 = responseContent.getString("payment_address"); - System.out.println("pkd2: " + pkD2); - System.out.println("address2: " + paymentAddress2); - shieldAddressInfo2.setSk(ByteArray.fromHexString(sk)); - shieldAddressInfo2.setD(new DiversifierT(ByteArray.fromHexString(d2))); - shieldAddressInfo2.setIvk(ByteArray.fromHexString(ivk)); - shieldAddressInfo2.setOvk(ByteArray.fromHexString(ovk)); - shieldAddressInfo2.setPkD(ByteArray.fromHexString(pkD2)); - shieldAddressOptionalInfo2 = Optional.of(shieldAddressInfo2); - - response = HttpMethed.getZenPaymentAddress(httpnode, ivk, d3); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - pkD3 = responseContent.getString("pkD"); - paymentAddress3 = responseContent.getString("payment_address"); - System.out.println("pkd3: " + pkD3); - System.out.println("address3: " + paymentAddress3); - shieldAddressInfo3.setSk(ByteArray.fromHexString(sk)); - shieldAddressInfo3.setD(new DiversifierT(ByteArray.fromHexString(d3))); - shieldAddressInfo3.setIvk(ByteArray.fromHexString(ivk)); - shieldAddressInfo3.setOvk(ByteArray.fromHexString(ovk)); - shieldAddressInfo3.setPkD(ByteArray.fromHexString(pkD3)); - shieldAddressOptionalInfo3 = Optional.of(shieldAddressInfo3); - } - - @Test(enabled = true, description = "Get rcm by http") - public void test08GetRcm() { - response = HttpMethed.getRcm(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - rcm = responseContent.getString("value"); - logger.info("rcm: " + rcm); - } - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token002.java deleted file mode 100644 index 67518968128..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token002.java +++ /dev/null @@ -1,200 +0,0 @@ -package stest.tron.wallet.dailybuild.zentrc20token; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.ZenTrc20Base; - -@Slf4j -public class HttpShieldTrc20Token002 extends ZenTrc20Base { - - JSONArray shieldedReceives = new JSONArray(); - String txid; - private String httpnode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(0); - private String anotherHttpnode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(1); - private String httpSolidityNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private JSONObject responseContent; - private HttpResponse response; - private JSONObject shieldAccountInfo; - private JSONArray noteTxs; - private Long publicFromAmount = getRandomLongAmount(); - - @Test(enabled = true, description = "Get new shield account by http") - public void test01GetNewShieldAccountByHttp() { - response = getNewShieldedAddress(httpnode); - shieldAccountInfo = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(shieldAccountInfo); - Assert.assertEquals(shieldAccountInfo.getString("sk").length(), 64); - Assert.assertEquals(shieldAccountInfo.getString("ask").length(), 64); - Assert.assertEquals(shieldAccountInfo.getString("nsk").length(), 64); - Assert.assertEquals(shieldAccountInfo.getString("ovk").length(), 64); - Assert.assertEquals(shieldAccountInfo.getString("ak").length(), 64); - Assert.assertEquals(shieldAccountInfo.getString("nk").length(), 64); - Assert.assertEquals(shieldAccountInfo.getString("ivk").length(), 64); - Assert.assertEquals(shieldAccountInfo.getString("d").length(), 22); - Assert.assertEquals(shieldAccountInfo.getString("pkD").length(), 64); - Assert.assertEquals(shieldAccountInfo.getString("payment_address").length(), 81); - - response = HttpMethed.getRcm(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - } - - @Test(enabled = true, description = "Create mint parameters by http") - public void test02MintByHttp() { - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, publicFromAmount, - shieldAccountInfo.getString("payment_address"), getRcm((httpnode))); - response = createShieldContractParameters(httpnode, publicFromAmount, shieldAccountInfo, - shieldedReceives); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, mint, responseContent - .getString("trigger_contract_input"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getTransactionInfoById(httpnode, txid, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getJSONObject("receipt") - .getLong("energy_usage_total") > 250000L); - Assert.assertEquals(responseContent.getString("contract_address"), shieldAddress); - Assert.assertEquals(responseContent.getJSONObject("receipt").getString("result"), - "SUCCESS"); - - shieldedReceives.clear(); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, publicFromAmount, - shieldAccountInfo.getString("payment_address"), getRcm(httpnode)); - response = createShieldContractParameters(httpnode, publicFromAmount, shieldAccountInfo, - shieldedReceives); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, mint, responseContent - .getString("trigger_contract_input"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getTransactionInfoById(httpnode, txid, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getJSONObject("receipt") - .getLong("energy_usage_total") > 250000L); - Assert.assertEquals(responseContent.getString("contract_address"), shieldAddress); - Assert.assertEquals(responseContent.getJSONObject("receipt").getString("result"), - "SUCCESS"); - - - } - - - @Test(enabled = true, description = "Scan shield TRC20 note by http") - public void test03ScanTrc20NodeByHttp() { - noteTxs = scanShieldTrc20NoteByIvk(httpnode, shieldAccountInfo); - logger.info(noteTxs.toJSONString()); - Assert.assertEquals(noteTxs.size(), 2); - Assert.assertEquals(noteTxs.getJSONObject(1) - .getJSONObject("note").getLong("value"), publicFromAmount); - Assert.assertEquals(noteTxs.getJSONObject(1) - .getJSONObject("note").getString("payment_address"), - shieldAccountInfo.getString("payment_address")); - Assert.assertEquals(noteTxs.getJSONObject(1) - .getString("txid"), txid); - } - - @Test(enabled = true, description = "Shield trc20 burn by http") - public void test04ShiledTrc20BurnByHttp() { - JSONArray shieldSpends = new JSONArray(); - shieldSpends = createAndSetShieldedSpends(httpnode, shieldSpends, noteTxs.getJSONObject(0)); - - logger.info(shieldSpends.toJSONString()); - - response = createShieldContractParametersForBurn(httpnode, shieldAccountInfo, shieldSpends, - zenTrc20TokenOwnerAddressString, publicFromAmount); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, burn, responseContent - .getString("trigger_contract_input"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getTransactionInfoById(httpnode, txid, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getJSONObject("receipt") - .getLong("energy_usage_total") > 150000L); - Assert.assertEquals(responseContent.getString("contract_address"), shieldAddress); - Assert.assertEquals(responseContent.getJSONObject("receipt").getString("result"), - "SUCCESS"); - - noteTxs = scanShieldTrc20NoteByOvk(httpnode, shieldAccountInfo); - logger.info("noteTxs ovk:" + noteTxs); - Assert.assertEquals(noteTxs.getJSONObject(0).getLong("to_amount"), publicFromAmount); - Assert.assertEquals(noteTxs.getJSONObject(0).getString("transparent_to_address"), - zenTrc20TokenOwnerAddressString); - Assert.assertEquals(noteTxs.getJSONObject(0).getString("txid"), txid); - } - - - @Test(enabled = true, description = "Shield trc20 burn with ask by http") - public void test05ShiledTrc20BurnWithoutAskByHttp() { - noteTxs = scanShieldTrc20NoteByIvk(httpnode, shieldAccountInfo); - JSONArray shieldSpends = new JSONArray(); - shieldSpends = createAndSetShieldedSpends(httpnode, shieldSpends, noteTxs.getJSONObject(1)); - - logger.info(shieldSpends.toJSONString()); - - response = createShieldContractParametersWithoutAskForBurn(httpnode, shieldAccountInfo, - shieldSpends, zenTrc20TokenOwnerAddressString, publicFromAmount); - JSONObject shieldedTrc20Parameters = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(shieldedTrc20Parameters); - JSONObject spendAuthSig = createSpendAuthSig(httpnode, shieldAccountInfo, - shieldedTrc20Parameters.getString("message_hash"), noteTxs.getJSONObject(1) - .getJSONObject("note").getString("rcm")); - HttpMethed.printJsonContent(spendAuthSig); - JSONArray spendAuthSigArray = new JSONArray(); - spendAuthSigArray.add(spendAuthSig); - - response = getTriggerInputForShieldedTrc20BurnContract(httpnode, - shieldedTrc20Parameters, spendAuthSigArray, publicFromAmount, - zenTrc20TokenOwnerAddressString); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, burn, responseContent - .getString("value"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getTransactionInfoById(httpnode, txid, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getJSONObject("receipt") - .getLong("energy_usage_total") > 150000L); - Assert.assertEquals(responseContent.getString("contract_address"), shieldAddress); - Assert.assertEquals(responseContent.getJSONObject("receipt").getString("result"), "SUCCESS"); - - } - - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token003.java deleted file mode 100644 index 5fdc4e8039a..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token003.java +++ /dev/null @@ -1,289 +0,0 @@ -package stest.tron.wallet.dailybuild.zentrc20token; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.ZenTrc20Base; - -@Slf4j -public class HttpShieldTrc20Token003 extends ZenTrc20Base { - - JSONArray shieldedReceives = new JSONArray(); - String txid; - JSONArray shieldSpends = new JSONArray(); - private String httpnode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(0); - private String anotherHttpnode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(1); - private String httpSolidityNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private JSONObject responseContent; - private HttpResponse response; - private JSONObject shieldAccountInfo1; - private JSONObject shieldAccountInfo2; - private JSONArray account1IvkNoteTxs = new JSONArray(); - private JSONArray account2IvkNoteTxs = new JSONArray(); - private JSONArray account1OvkNoteTxs = new JSONArray(); - private JSONArray account2OvkNoteTxs = new JSONArray(); - private Long publicFromAmount = getRandomLongAmount(); - private Long account1Receive1V2Amount = 10L; - private Long account2Receive1V2Amount = publicFromAmount - account1Receive1V2Amount; - private Long account1Receive2V2Amount = 13L; - private Long account2Receive2V2Amount = publicFromAmount - + account2Receive1V2Amount - account1Receive2V2Amount; - - /** - * constructor. - */ - @BeforeClass(enabled = true, description = "Prepare for transfer") - public void prepareForTransfer() { - //Create two shield account - response = getNewShieldedAddress(httpnode); - shieldAccountInfo1 = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(shieldAccountInfo1); - - response = getNewShieldedAddress(httpnode); - shieldAccountInfo2 = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(shieldAccountInfo2); - //Send two mint to shield account 1 - shieldedReceives.clear(); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, publicFromAmount, - shieldAccountInfo1.getString("payment_address"), getRcm(httpnode)); - response = createShieldContractParameters(httpnode, publicFromAmount, shieldAccountInfo1, - shieldedReceives); - responseContent = HttpMethed.parseResponseContent(response); - //HttpMethed.printJsonContent(responseContent); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, mint, responseContent - .getString("trigger_contract_input"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - - shieldedReceives.clear(); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, publicFromAmount, - shieldAccountInfo1.getString("payment_address"), getRcm(httpnode)); - response = createShieldContractParameters(httpnode, publicFromAmount, shieldAccountInfo1, - shieldedReceives); - responseContent = HttpMethed.parseResponseContent(response); - //HttpMethed.printJsonContent(responseContent); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, mint, responseContent - .getString("trigger_contract_input"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - - } - - - @Test(enabled = true, description = "Transfer type with 1V1 by http") - public void test01TransferTypeWith1V1ByHttp() { - account1IvkNoteTxs = scanShieldTrc20NoteByIvk(httpnode, shieldAccountInfo1); - shieldSpends.clear(); - shieldSpends = createAndSetShieldedSpends(httpnode, shieldSpends, account1IvkNoteTxs - .getJSONObject(0)); - shieldedReceives.clear(); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, publicFromAmount, - shieldAccountInfo2.getString("payment_address"), getRcm(httpnode)); - response = createShieldContractParametersForTransfer(httpnode, shieldAccountInfo1, - shieldSpends, shieldedReceives); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, transfer, responseContent - .getString("trigger_contract_input"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getTransactionInfoById(httpnode, txid, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getJSONObject("receipt") - .getLong("energy_usage_total") > 300000L); - Assert.assertEquals(responseContent.getString("contract_address"), shieldAddress); - Assert.assertEquals(responseContent.getJSONObject("receipt").getString("result"), - "SUCCESS"); - - account1OvkNoteTxs = scanShieldTrc20NoteByOvk(httpnode, shieldAccountInfo1); - logger.info(account1OvkNoteTxs.toJSONString()); - Assert.assertEquals(account1OvkNoteTxs.size(), 1); - } - - @Test(enabled = true, description = "Transfer type with 1V2 by http") - public void test02TransferTypeWith1V2ByHttp() { - account1IvkNoteTxs = scanShieldTrc20NoteByIvk(httpnode, shieldAccountInfo1); - - Assert.assertTrue(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo1, - account1IvkNoteTxs.getJSONObject(0))); - Assert.assertFalse(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo1, - account1IvkNoteTxs.getJSONObject(1))); - shieldSpends.clear(); - shieldSpends = createAndSetShieldedSpends(httpnode, shieldSpends, account1IvkNoteTxs - .getJSONObject(1)); - - shieldedReceives.clear(); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, account1Receive1V2Amount, - shieldAccountInfo1.getString("payment_address"), getRcm(httpnode)); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, account2Receive1V2Amount, - shieldAccountInfo2.getString("payment_address"), getRcm(httpnode)); - response = createShieldContractParametersForTransfer(httpnode, shieldAccountInfo1, shieldSpends, - shieldedReceives); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.containsKey("trigger_contract_input")); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, transfer, responseContent - .getString("trigger_contract_input"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getTransactionInfoById(httpnode, txid, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getJSONObject("receipt") - .getLong("energy_usage_total") > 300000L); - Assert.assertEquals(responseContent.getString("contract_address"), shieldAddress); - Assert.assertEquals(responseContent.getJSONObject("receipt").getString("result"), - "SUCCESS"); - - account1OvkNoteTxs = scanShieldTrc20NoteByOvk(httpnode, shieldAccountInfo1); - logger.info(account1OvkNoteTxs.toJSONString()); - Assert.assertEquals(account1OvkNoteTxs.size(), 3); - } - - - @Test(enabled = true, description = "Transfer type with 2V2 by http") - public void test03TransferTypeWith2V2ByHttp() { - account2IvkNoteTxs = scanShieldTrc20NoteByIvk(httpnode, shieldAccountInfo2); - - Assert.assertFalse(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo2, - account2IvkNoteTxs.getJSONObject(0))); - Assert.assertFalse(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo2, - account2IvkNoteTxs.getJSONObject(1))); - shieldSpends.clear(); - shieldSpends = createAndSetShieldedSpends(httpnode, shieldSpends, account2IvkNoteTxs - .getJSONObject(0)); - shieldSpends = createAndSetShieldedSpends(httpnode, shieldSpends, account2IvkNoteTxs - .getJSONObject(1)); - shieldedReceives.clear(); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, account1Receive2V2Amount, - shieldAccountInfo1.getString("payment_address"), getRcm(httpnode)); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, account2Receive2V2Amount, - shieldAccountInfo2.getString("payment_address"), getRcm(httpnode)); - response = createShieldContractParametersForTransfer(httpnode, shieldAccountInfo2, shieldSpends, - shieldedReceives); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.containsKey("trigger_contract_input")); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, transfer, responseContent - .getString("trigger_contract_input"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getTransactionInfoById(httpnode, txid, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getJSONObject("receipt") - .getLong("energy_usage_total") > 300000L); - Assert.assertEquals(responseContent.getString("contract_address"), shieldAddress); - Assert.assertEquals(responseContent.getJSONObject("receipt").getString("result"), - "SUCCESS"); - - account2OvkNoteTxs = scanShieldTrc20NoteByOvk(httpnode, shieldAccountInfo2); - logger.info(account1OvkNoteTxs.toJSONString()); - Assert.assertEquals(account2OvkNoteTxs.size(), 2); - - Assert.assertTrue(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo2, - account2IvkNoteTxs.getJSONObject(0))); - Assert.assertTrue(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo2, - account2IvkNoteTxs.getJSONObject(1))); - - } - - @Test(enabled = true, description = "Transfer type with 2V1 by http") - public void test04TransferTypeWith2V1ByHttp() { - account1IvkNoteTxs = scanShieldTrc20NoteByIvk(httpnode, shieldAccountInfo1); - - Assert.assertFalse(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo1, - account1IvkNoteTxs.getJSONObject(2))); - Assert.assertFalse(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo1, - account1IvkNoteTxs.getJSONObject(3))); - shieldSpends.clear(); - shieldSpends = createAndSetShieldedSpends(httpnode, shieldSpends, account1IvkNoteTxs - .getJSONObject(2)); - shieldSpends = createAndSetShieldedSpends(httpnode, shieldSpends, account1IvkNoteTxs - .getJSONObject(3)); - Long account1Receive2V1Amount = account1IvkNoteTxs.getJSONObject(2) - .getJSONObject("note").getLong("value") - + account1IvkNoteTxs.getJSONObject(3).getJSONObject("note").getLong("value"); - shieldedReceives.clear(); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, account1Receive2V1Amount, - shieldAccountInfo1.getString("payment_address"), getRcm(httpnode)); - response = createShieldContractParametersForTransfer(httpnode, shieldAccountInfo1, shieldSpends, - shieldedReceives); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.containsKey("trigger_contract_input")); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, transfer, responseContent - .getString("trigger_contract_input"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getTransactionInfoById(httpnode, txid, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getJSONObject("receipt") - .getLong("energy_usage_total") > 300000L); - Assert.assertEquals(responseContent.getString("contract_address"), shieldAddress); - Assert.assertEquals(responseContent.getJSONObject("receipt").getString("result"), - "SUCCESS"); - - account1OvkNoteTxs = scanShieldTrc20NoteByOvk(httpnode, shieldAccountInfo1); - logger.info(account1OvkNoteTxs.toJSONString()); - Assert.assertEquals(account1OvkNoteTxs.size(), 4); - - account1IvkNoteTxs = scanShieldTrc20NoteByIvk(httpnode, shieldAccountInfo1); - Assert.assertTrue(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo1, - account1IvkNoteTxs.getJSONObject(2))); - Assert.assertTrue(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo1, - account1IvkNoteTxs.getJSONObject(3))); - - } - - - @Test(enabled = true, description = "Query is shielded trc20 contract note spent on " - + "solidity by http") - public void test05QueryIsShieldedTrc20ContractNoteSpentByHttp() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSolidityNode); - Assert.assertTrue(isShieldedTrc20ContractNoteSpentOnSolidity(httpSolidityNode, - shieldAccountInfo1, account1IvkNoteTxs.getJSONObject(2))); - Assert.assertTrue(isShieldedTrc20ContractNoteSpentOnSolidity(httpSolidityNode, - shieldAccountInfo1, account1IvkNoteTxs.getJSONObject(3))); - } - - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token004.java deleted file mode 100644 index c874776919f..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token004.java +++ /dev/null @@ -1,376 +0,0 @@ -package stest.tron.wallet.dailybuild.zentrc20token; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.ZenTrc20Base; - -@Slf4j -public class HttpShieldTrc20Token004 extends ZenTrc20Base { - - JSONArray shieldedReceives = new JSONArray(); - String txid; - JSONArray shieldSpends = new JSONArray(); - private String httpnode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(0); - private String anotherHttpnode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(1); - private String httpSolidityNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private String httpPbftNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(4); - private JSONObject responseContent; - private HttpResponse response; - private JSONObject shieldAccountInfo1; - private JSONObject shieldAccountInfo2; - private JSONArray account1IvkNoteTxs = new JSONArray(); - private JSONArray account2IvkNoteTxs = new JSONArray(); - private JSONArray account1OvkNoteTxs = new JSONArray(); - private JSONArray account2OvkNoteTxs = new JSONArray(); - private Long publicFromAmount = getRandomLongAmount(); - private Long account1Receive1V2Amount = 10L; - private Long account2Receive1V2Amount = publicFromAmount - account1Receive1V2Amount; - private Long account1Receive2V2Amount = 13L; - private Long account2Receive2V2Amount = publicFromAmount + account2Receive1V2Amount - - account1Receive2V2Amount; - - /** - * constructor. - */ - @BeforeClass(enabled = true, description = "Prepare for transfer without ask") - public void prepareForTransfer() { - //Create two shield account - response = getNewShieldedAddress(httpnode); - shieldAccountInfo1 = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(shieldAccountInfo1); - - response = getNewShieldedAddress(httpnode); - shieldAccountInfo2 = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(shieldAccountInfo2); - //Send two mint to shield account 1 - shieldedReceives.clear(); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, publicFromAmount, - shieldAccountInfo1.getString("payment_address"), getRcm(httpnode)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = createShieldContractParameters(httpnode, publicFromAmount, shieldAccountInfo1, - shieldedReceives); - responseContent = HttpMethed.parseResponseContent(response); - //HttpMethed.printJsonContent(responseContent); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, mint, responseContent - .getString("trigger_contract_input"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - shieldedReceives.clear(); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, publicFromAmount, - shieldAccountInfo1.getString("payment_address"), getRcm(httpnode)); - response = createShieldContractParameters(httpnode, publicFromAmount, shieldAccountInfo1, - shieldedReceives); - responseContent = HttpMethed.parseResponseContent(response); - //HttpMethed.printJsonContent(responseContent); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, mint, responseContent - .getString("trigger_contract_input"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - } - - - @Test(enabled = true, description = "Transfer type with 1V1 without ask by http") - public void test01TransferTypeWith1V1WithoutAskByHttp() { - account1IvkNoteTxs = scanShieldTrc20NoteByIvk(httpnode, shieldAccountInfo1); - shieldSpends.clear(); - shieldSpends = createAndSetShieldedSpends(httpnode, shieldSpends, account1IvkNoteTxs - .getJSONObject(0)); - HttpMethed.waitToProduceOneBlock(httpnode); - shieldedReceives.clear(); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, publicFromAmount, - shieldAccountInfo2.getString("payment_address"), getRcm(httpnode)); - response = createShieldContractParametersWithoutAskForTransfer(httpnode, shieldAccountInfo1, - shieldSpends, shieldedReceives); - JSONObject shieldedTrc20Parameters = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(shieldedTrc20Parameters); - JSONObject spendAuthSig = createSpendAuthSig(httpnode, shieldAccountInfo1, - shieldedTrc20Parameters.getString("message_hash"), account1IvkNoteTxs - .getJSONObject(0).getJSONObject("note").getString("rcm")); - HttpMethed.printJsonContent(spendAuthSig); - JSONArray spendAuthSigArray = new JSONArray(); - spendAuthSigArray.add(spendAuthSig); - - response = getTriggerInputForShieldedTrc20Contract(httpnode, shieldedTrc20Parameters, - spendAuthSigArray); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, transfer, responseContent - .getString("value"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getTransactionInfoById(httpnode, txid, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getJSONObject("receipt") - .getLong("energy_usage_total") > 300000L); - Assert.assertEquals(responseContent.getString("contract_address"), shieldAddress); - Assert.assertEquals(responseContent.getJSONObject("receipt").getString("result"), "SUCCESS"); - - account1OvkNoteTxs = scanShieldTrc20NoteByOvk(httpnode, shieldAccountInfo1); - logger.info(account1OvkNoteTxs.toJSONString()); - Assert.assertEquals(account1OvkNoteTxs.size(), 1); - } - - @Test(enabled = true, description = "Transfer type with 1V2 without ask by http") - public void test02TransferTypeWith1V2WithoutAskByHttp() { - - account1IvkNoteTxs = scanShieldTrc20NoteByIvk(httpnode, shieldAccountInfo1); - - Assert.assertTrue(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo1, - account1IvkNoteTxs.getJSONObject(0))); - Assert.assertFalse(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo1, - account1IvkNoteTxs.getJSONObject(1))); - shieldSpends.clear(); - shieldSpends = createAndSetShieldedSpends(httpnode, shieldSpends, account1IvkNoteTxs - .getJSONObject(1)); - - shieldedReceives.clear(); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, account1Receive1V2Amount, - shieldAccountInfo1.getString("payment_address"), getRcm(httpnode)); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, account2Receive1V2Amount, - shieldAccountInfo2.getString("payment_address"), getRcm(httpnode)); - response = createShieldContractParametersWithoutAskForTransfer(httpnode, shieldAccountInfo1, - shieldSpends, shieldedReceives); - JSONObject shieldedTrc20Parameters = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(shieldedTrc20Parameters); - JSONObject spendAuthSig1 = createSpendAuthSig(httpnode, shieldAccountInfo1, - shieldedTrc20Parameters.getString("message_hash"), account1IvkNoteTxs.getJSONObject(1) - .getJSONObject("note").getString("rcm")); - HttpMethed.printJsonContent(spendAuthSig1); - JSONArray spendAuthSigArray = new JSONArray(); - spendAuthSigArray.add(spendAuthSig1); - //spendAuthSigArray.add(spendAuthSig2); - - response = getTriggerInputForShieldedTrc20Contract(httpnode, shieldedTrc20Parameters, - spendAuthSigArray); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, transfer, responseContent - .getString("value"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getTransactionInfoById(httpnode, txid, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getJSONObject("receipt") - .getLong("energy_usage_total") > 300000L); - Assert.assertEquals(responseContent.getString("contract_address"), shieldAddress); - Assert.assertEquals(responseContent.getJSONObject("receipt").getString("result"), - "SUCCESS"); - - account1OvkNoteTxs = scanShieldTrc20NoteByOvk(httpnode, shieldAccountInfo1); - logger.info(account1OvkNoteTxs.toJSONString()); - Assert.assertEquals(account1OvkNoteTxs.size(), 3); - } - - - @Test(enabled = true, description = "Transfer type with 2V2 without ask by http") - public void test03TransferTypeWith2V2WithoutAskByHttp() { - account2IvkNoteTxs = scanShieldTrc20NoteByIvk(httpnode, shieldAccountInfo2); - - Assert.assertFalse(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo2, - account2IvkNoteTxs.getJSONObject(0))); - Assert.assertFalse(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo2, - account2IvkNoteTxs.getJSONObject(1))); - shieldSpends.clear(); - shieldSpends = createAndSetShieldedSpends(httpnode, shieldSpends, account2IvkNoteTxs - .getJSONObject(0)); - shieldSpends = createAndSetShieldedSpends(httpnode, shieldSpends, account2IvkNoteTxs - .getJSONObject(1)); - shieldedReceives.clear(); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, account1Receive2V2Amount, - shieldAccountInfo1.getString("payment_address"), getRcm(httpnode)); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, account2Receive2V2Amount, - shieldAccountInfo2.getString("payment_address"), getRcm(httpnode)); - response = createShieldContractParametersWithoutAskForTransfer(httpnode, shieldAccountInfo2, - shieldSpends, shieldedReceives); - JSONObject shieldedTrc20Parameters = HttpMethed.parseResponseContent(response); - - JSONObject spendAuthSig1 = createSpendAuthSig(httpnode, shieldAccountInfo2, - shieldedTrc20Parameters.getString("message_hash"), account2IvkNoteTxs.getJSONObject(0) - .getJSONObject("note").getString("rcm")); - HttpMethed.printJsonContent(spendAuthSig1); - - JSONObject spendAuthSig2 = createSpendAuthSig(httpnode, shieldAccountInfo2, - shieldedTrc20Parameters.getString("message_hash"), account2IvkNoteTxs.getJSONObject(1) - .getJSONObject("note").getString("rcm")); - JSONArray spendAuthSigArray = new JSONArray(); - spendAuthSigArray.add(spendAuthSig1); - spendAuthSigArray.add(spendAuthSig2); - - response = getTriggerInputForShieldedTrc20Contract(httpnode, shieldedTrc20Parameters, - spendAuthSigArray); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, transfer, responseContent - .getString("value"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getTransactionInfoById(httpnode, txid, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getJSONObject("receipt") - .getLong("energy_usage_total") > 300000L); - Assert.assertEquals(responseContent.getString("contract_address"), shieldAddress); - Assert.assertEquals(responseContent.getJSONObject("receipt").getString("result"), "SUCCESS"); - - account2OvkNoteTxs = scanShieldTrc20NoteByOvk(httpnode, shieldAccountInfo2); - logger.info(account1OvkNoteTxs.toJSONString()); - Assert.assertEquals(account2OvkNoteTxs.size(), 2); - - Assert.assertTrue(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo2, - account2IvkNoteTxs.getJSONObject(0))); - Assert.assertTrue(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo2, - account2IvkNoteTxs.getJSONObject(1))); - - } - - @Test(enabled = true, description = "Transfer type with 2V1 without ask by http") - public void test04TransferTypeWith2V1WithoutAskByHttp() { - account1IvkNoteTxs = scanShieldTrc20NoteByIvk(httpnode, shieldAccountInfo1); - - Assert.assertFalse(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo1, - account1IvkNoteTxs.getJSONObject(2))); - Assert.assertFalse(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo1, - account1IvkNoteTxs.getJSONObject(3))); - shieldSpends.clear(); - shieldSpends = createAndSetShieldedSpends(httpnode, shieldSpends, account1IvkNoteTxs - .getJSONObject(2)); - shieldSpends = createAndSetShieldedSpends(httpnode, shieldSpends, account1IvkNoteTxs - .getJSONObject(3)); - Long account1Receive2V1Amount = account1IvkNoteTxs.getJSONObject(2) - .getJSONObject("note").getLong("value") - + account1IvkNoteTxs.getJSONObject(3).getJSONObject("note").getLong("value"); - shieldedReceives.clear(); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, account1Receive2V1Amount, - shieldAccountInfo1.getString("payment_address"), getRcm(httpnode)); - response = createShieldContractParametersWithoutAskForTransfer(httpnode, shieldAccountInfo1, - shieldSpends, shieldedReceives); - JSONObject shieldedTrc20Parameters = HttpMethed.parseResponseContent(response); - - JSONObject spendAuthSig1 = createSpendAuthSig(httpnode, shieldAccountInfo1, - shieldedTrc20Parameters.getString("message_hash"), account1IvkNoteTxs.getJSONObject(2) - .getJSONObject("note").getString("rcm")); - HttpMethed.printJsonContent(spendAuthSig1); - - JSONObject spendAuthSig2 = createSpendAuthSig(httpnode, shieldAccountInfo1, - shieldedTrc20Parameters.getString("message_hash"), account1IvkNoteTxs.getJSONObject(3) - .getJSONObject("note").getString("rcm")); - HttpMethed.printJsonContent(spendAuthSig2); - - JSONArray spendAuthSigArray = new JSONArray(); - spendAuthSigArray.add(spendAuthSig1); - spendAuthSigArray.add(spendAuthSig2); - - response = getTriggerInputForShieldedTrc20Contract(httpnode, shieldedTrc20Parameters, - spendAuthSigArray); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, transfer, responseContent - .getString("value"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getTransactionInfoById(httpnode, txid, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getJSONObject("receipt") - .getLong("energy_usage_total") > 300000L); - Assert.assertEquals(responseContent.getString("contract_address"), shieldAddress); - Assert.assertEquals(responseContent.getJSONObject("receipt").getString("result"), "SUCCESS"); - - account1OvkNoteTxs = scanShieldTrc20NoteByOvk(httpnode, shieldAccountInfo1); - logger.info(account1OvkNoteTxs.toJSONString()); - Assert.assertEquals(account1OvkNoteTxs.size(), 4); - - account1IvkNoteTxs = scanShieldTrc20NoteByIvk(httpnode, shieldAccountInfo1); - Assert.assertTrue(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo1, - account1IvkNoteTxs.getJSONObject(2))); - Assert.assertTrue(isShieldedTrc20ContractNoteSpentOnPbft(httpPbftNode, shieldAccountInfo1, - account1IvkNoteTxs.getJSONObject(2))); - Assert.assertTrue(isShieldedTrc20ContractNoteSpent(httpnode, shieldAccountInfo1, - account1IvkNoteTxs.getJSONObject(3))); - Assert.assertTrue(isShieldedTrc20ContractNoteSpentOnPbft(httpPbftNode, shieldAccountInfo1, - account1IvkNoteTxs.getJSONObject(3))); - - } - - - @Test(enabled = true, description = "Scan note by ivk and ovk on solidity and pbft by http") - public void test05ScanNoteByIvkAndOvkOnSOlidityAndPbftByHttp() { - HttpMethed.waitToProduceOneBlockFromSolidity(httpnode, httpSolidityNode); - - account1IvkNoteTxs = scanShieldTrc20NoteByIvk(httpnode, shieldAccountInfo1); - JSONArray account1IvkNoteTxsOnSolidity = scanShieldTrc20NoteByIvkOnSolidity(httpSolidityNode, - shieldAccountInfo1); - Assert.assertEquals(account1IvkNoteTxs, account1IvkNoteTxsOnSolidity); - JSONArray account1IvkNoteTxsOnPbft = scanShieldTrc20NoteByIvkOnPbft(httpPbftNode, - shieldAccountInfo1); - Assert.assertEquals(account1IvkNoteTxs, account1IvkNoteTxsOnPbft); - - account1OvkNoteTxs = scanShieldTrc20NoteByOvk(httpnode, shieldAccountInfo1); - JSONArray account1OvkNoteTxsOnSolidity = scanShieldTrc20NoteByOvkOnSolidity(httpSolidityNode, - shieldAccountInfo1); - Assert.assertEquals(account1OvkNoteTxs, account1OvkNoteTxsOnSolidity); - JSONArray account1OvkNoteTxsOnPbft = scanShieldTrc20NoteByOvkOnPbft(httpPbftNode, - shieldAccountInfo1); - Assert.assertEquals(account1OvkNoteTxs, account1OvkNoteTxsOnPbft); - - account2IvkNoteTxs = scanShieldTrc20NoteByIvk(httpnode, shieldAccountInfo2); - JSONArray account2IvkNoteTxsOnSolidity = scanShieldTrc20NoteByIvkOnSolidity(httpSolidityNode, - shieldAccountInfo2); - Assert.assertEquals(account2IvkNoteTxs, account2IvkNoteTxsOnSolidity); - JSONArray account2IvkNoteTxsOnPbft = scanShieldTrc20NoteByIvkOnPbft(httpPbftNode, - shieldAccountInfo2); - Assert.assertEquals(account2IvkNoteTxs, account2IvkNoteTxsOnPbft); - - account2OvkNoteTxs = scanShieldTrc20NoteByOvk(httpnode, shieldAccountInfo2); - JSONArray account2OvkNoteTxsOnSolidity = scanShieldTrc20NoteByOvkOnSolidity(httpSolidityNode, - shieldAccountInfo2); - Assert.assertEquals(account2OvkNoteTxs, account2OvkNoteTxsOnSolidity); - JSONArray account2OvkNoteTxsOnPbft = scanShieldTrc20NoteByOvkOnPbft(httpPbftNode, - shieldAccountInfo2); - Assert.assertEquals(account2OvkNoteTxs, account2OvkNoteTxsOnPbft); - - } - - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token005.java deleted file mode 100644 index 998a97a9322..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/HttpShieldTrc20Token005.java +++ /dev/null @@ -1,197 +0,0 @@ -package stest.tron.wallet.dailybuild.zentrc20token; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.ZenTrc20Base; - -@Slf4j -public class HttpShieldTrc20Token005 extends ZenTrc20Base { - - JSONArray shieldedReceives = new JSONArray(); - String txid; - private String httpnode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(0); - private String anotherHttpnode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(1); - private String httpSolidityNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(2); - private JSONObject responseContent; - private HttpResponse response; - private JSONObject shieldAccountInfo; - private JSONObject shieldReceiverAccountInfo; - private JSONArray noteTxs; - private Long publicFromAmount = getRandomLongAmount(); - - /** - * constructor. - */ - - @BeforeClass(enabled = true, description = "Get new shield account by http") - public void createTwoNote() { - response = getNewShieldedAddress(httpnode); - shieldAccountInfo = HttpMethed.parseResponseContent(response); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, publicFromAmount, - shieldAccountInfo.getString("payment_address"), getRcm((httpnode))); - response = createShieldContractParameters(httpnode, publicFromAmount, shieldAccountInfo, - shieldedReceives); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, mint, responseContent - .getString("trigger_contract_input"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getTransactionInfoById(httpnode, txid, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - shieldedReceives.clear(); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, publicFromAmount, - shieldAccountInfo.getString("payment_address"), getRcm(httpnode)); - response = createShieldContractParameters(httpnode, publicFromAmount, shieldAccountInfo, - shieldedReceives); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, mint, responseContent - .getString("trigger_contract_input"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getTransactionInfoById(httpnode, txid, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - noteTxs = scanShieldTrc20NoteByIvk(httpnode, shieldAccountInfo); - } - - @Test(enabled = true, description = "Shield trc20 burn to one T and one S by http") - public void test01ShiledTrc20BurnToOnePublicAndOneShieldByHttp() { - response = getNewShieldedAddress(httpnode); - shieldReceiverAccountInfo = HttpMethed.parseResponseContent(response); - - JSONArray shieldSpends = new JSONArray(); - shieldSpends = createAndSetShieldedSpends(httpnode, shieldSpends, noteTxs.getJSONObject(0)); - - logger.info(shieldSpends.toJSONString()); - - Long toShieldAmount = 9L; - Long toPublicAmount = publicFromAmount - toShieldAmount; - shieldedReceives.clear(); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, toShieldAmount, - shieldReceiverAccountInfo.getString("payment_address"), getRcm(httpnode)); - - response = createShieldContractParametersForBurn(httpnode, shieldAccountInfo, shieldSpends, - zenTrc20TokenOwnerAddressString, toPublicAmount, shieldedReceives); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, burn, responseContent - .getString("trigger_contract_input"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getTransactionInfoById(httpnode, txid, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getJSONObject("receipt") - .getLong("energy_usage_total") > 150000L); - Assert.assertEquals(responseContent.getString("contract_address"), shieldAddress); - Assert.assertEquals(responseContent.getJSONObject("receipt").getString("result"), - "SUCCESS"); - - noteTxs = scanShieldTrc20NoteByOvk(httpnode, shieldAccountInfo); - logger.info("noteTxs ovk:" + noteTxs); - - Assert.assertEquals(noteTxs.getJSONObject(0).getJSONObject("note") - .getLong("value"), toShieldAmount); - Assert.assertEquals(noteTxs.getJSONObject(0).getJSONObject("note") - .getString("payment_address"), shieldReceiverAccountInfo.getString("payment_address")); - - Assert.assertEquals(noteTxs.getJSONObject(1).getLong("to_amount"), toPublicAmount); - Assert.assertEquals(noteTxs.getJSONObject(1).getString("transparent_to_address"), - zenTrc20TokenOwnerAddressString); - Assert.assertEquals(noteTxs.getJSONObject(1).getString("txid"), txid); - } - - - @Test(enabled = true, description = "Shield trc20 burn without ask to one " - + "public and one shield by http") - public void test02ShiledTrc20BurnWithoutAskToOnePublicAndOneShieldByHttp() { - noteTxs = scanShieldTrc20NoteByIvk(httpnode, shieldAccountInfo); - JSONArray shieldSpends = new JSONArray(); - shieldSpends = createAndSetShieldedSpends(httpnode, shieldSpends, noteTxs.getJSONObject(1)); - - Long toShieldAmount = 8L; - Long toPublicAmount = publicFromAmount - toShieldAmount; - shieldedReceives.clear(); - shieldedReceives = getHttpShieldedReceivesJsonArray(shieldedReceives, toShieldAmount, - shieldReceiverAccountInfo.getString("payment_address"), getRcm(httpnode)); - - response = createShieldContractParametersWithoutAskForBurn(httpnode, shieldAccountInfo, - shieldSpends, zenTrc20TokenOwnerAddressString, toPublicAmount, shieldedReceives); - JSONObject shieldedTrc20Parameters = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(shieldedTrc20Parameters); - JSONObject spendAuthSig = createSpendAuthSig(httpnode, shieldAccountInfo, - shieldedTrc20Parameters.getString("message_hash"), noteTxs.getJSONObject(1) - .getJSONObject("note").getString("rcm")); - HttpMethed.printJsonContent(spendAuthSig); - JSONArray spendAuthSigArray = new JSONArray(); - spendAuthSigArray.add(spendAuthSig); - - response = getTriggerInputForShieldedTrc20BurnContract(httpnode, - shieldedTrc20Parameters, spendAuthSigArray, toPublicAmount, - zenTrc20TokenOwnerAddressString); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - txid = HttpMethed.triggerContractGetTxidWithVisibleTrue(httpnode,anotherHttpnode, - zenTrc20TokenOwnerAddressString, shieldAddress, burn, responseContent - .getString("value"), maxFeeLimit, 0L, 0, 0L, - zenTrc20TokenOwnerKey); - - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getTransactionInfoById(httpnode, txid, true); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - Assert.assertTrue(responseContent.getJSONObject("receipt") - .getLong("energy_usage_total") > 150000L); - Assert.assertEquals(responseContent.getString("contract_address"), shieldAddress); - Assert.assertEquals(responseContent.getJSONObject("receipt").getString("result"), "SUCCESS"); - - noteTxs = scanShieldTrc20NoteByOvk(httpnode, shieldAccountInfo); - logger.info("noteTxs ovk:" + noteTxs); - - Assert.assertEquals(noteTxs.getJSONObject(2).getJSONObject("note") - .getLong("value"), toShieldAmount); - Assert.assertEquals(noteTxs.getJSONObject(2).getJSONObject("note") - .getString("payment_address"), shieldReceiverAccountInfo.getString("payment_address")); - - Assert.assertEquals(noteTxs.getJSONObject(3).getLong("to_amount"), toPublicAmount); - Assert.assertEquals(noteTxs.getJSONObject(3).getString("transparent_to_address"), - zenTrc20TokenOwnerAddressString); - Assert.assertEquals(noteTxs.getJSONObject(3).getString("txid"), txid); - - } - - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token001.java deleted file mode 100644 index 2bc145c23c6..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token001.java +++ /dev/null @@ -1,84 +0,0 @@ -package stest.tron.wallet.dailybuild.zentrc20token; - -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.api.WalletGrpc; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ZenTrc20Base; - -@Slf4j -public class ShieldTrc20Token001 extends ZenTrc20Base { - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "Check shield contract deploy success") - public void test01checkShieldContractDeploySuccess() { - Optional infoById = PublicMethed - .getTransactionInfoById(deployShieldTrc20Txid, blockingStubFull); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - infoById = PublicMethed - .getTransactionInfoById(deployShieldTxid, blockingStubFull); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - - //scalingFactor() - } - - @Test(enabled = true, description = "View scaling factor test") - public void test02ViewScalingFactor() { - String txid = PublicMethed.triggerContract(shieldAddressByte, - "scalingFactor()", "", false, - 0, maxFeeLimit, zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - logger.info(txid); - logger.info(Integer.toString(infoById.get().getResultValue())); - - TransactionExtention transactionExtention = PublicMethed - .triggerConstantContractForExtention(shieldAddressByte, "scalingFactor()", - "", false, 0, 0, "0", 0, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - - logger.info("transactionExtention:" + transactionExtention); - String scalingFactor = PublicMethed - .bytes32ToString(transactionExtention.getConstantResult(0).toByteArray()); - Assert.assertEquals("00000000000000000000000000000001", - scalingFactor); - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token002.java deleted file mode 100644 index b5c03c164ed..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token002.java +++ /dev/null @@ -1,132 +0,0 @@ -package stest.tron.wallet.dailybuild.zentrc20token; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldedAddressInfo; -import stest.tron.wallet.common.client.utils.ZenTrc20Base; - -@Slf4j -public class ShieldTrc20Token002 extends ZenTrc20Base { - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - Optional receiverShieldAddressInfo; - private BigInteger publicFromAmount; - List shieldOutList = new ArrayList<>(); - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - publicFromAmount = getRandomAmount(); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Send shield trc20 from T account to shield account") - public void test01ShieldTrc20TransactionByTypeMint() throws Exception { - //Query account before mint balance - final Long beforeMintAccountBalance = getBalanceOfShieldTrc20(zenTrc20TokenOwnerAddressString, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - //Query contract before mint balance - final Long beforeMintShieldAccountBalance = getBalanceOfShieldTrc20(shieldAddress, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - //Generate new shiled account and set note memo - receiverShieldAddressInfo = getNewShieldedAddress(blockingStubFull); - String memo = "Shield trc20 from T account to shield account in" + System.currentTimeMillis(); - String receiverShieldAddress = receiverShieldAddressInfo.get().getAddress(); - - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, receiverShieldAddress, - "" + publicFromAmount, memo, blockingStubFull); - - //Create shiled trc20 parameters - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters - = createShieldedTrc20Parameters(publicFromAmount, - null, null, shieldOutList, "", 0L, - blockingStubFull, blockingStubSolidity - ); - String data = encodeMintParamsToHexString(shieldedTrc20Parameters, publicFromAmount); - - //Do mint transaction type - String txid = PublicMethed.triggerContract(shieldAddressByte, - mint, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - - logger.info(mint + ":" + txid); - logger.info(mint + infoById.get().getReceipt().getEnergyUsageTotal()); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 250000); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - - //Query account after mint balance - Long afterMintAccountBalance = getBalanceOfShieldTrc20(zenTrc20TokenOwnerAddressString, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - //Query contract after mint balance - Long afterMintShieldAccountBalance = getBalanceOfShieldTrc20(shieldAddress, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - - Assert.assertEquals(BigInteger.valueOf(beforeMintAccountBalance - afterMintAccountBalance), - publicFromAmount); - Assert.assertEquals(BigInteger.valueOf(afterMintShieldAccountBalance - - beforeMintShieldAccountBalance), publicFromAmount); - - GrpcAPI.DecryptNotesTRC20 note = scanShieldedTrc20NoteByIvk(receiverShieldAddressInfo.get(), - blockingStubFull); - logger.info("" + note); - - Assert.assertEquals(note.getNoteTxs(0).getNote().getValue(), publicFromAmount.longValue()); - Assert.assertEquals(note.getNoteTxs(0).getNote().getPaymentAddress(), - receiverShieldAddressInfo.get().getAddress()); - Assert.assertEquals(note.getNoteTxs(0).getNote().getMemo(), ByteString.copyFromUtf8(memo)); - Assert.assertEquals(note.getNoteTxs(0).getTxid(), infoById.get().getId()); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token003.java deleted file mode 100644 index 6eb8ff23790..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token003.java +++ /dev/null @@ -1,216 +0,0 @@ -package stest.tron.wallet.dailybuild.zentrc20token; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldedAddressInfo; -import stest.tron.wallet.common.client.utils.ZenTrc20Base; - -@Slf4j -public class ShieldTrc20Token003 extends ZenTrc20Base { - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - Optional senderShieldAddressInfo; - Optional receiverShieldAddressInfo; - private BigInteger publicFromAmount; - List shieldOutList = new ArrayList<>(); - List inputShieldAddressList = new ArrayList<>(); - GrpcAPI.DecryptNotesTRC20 senderNote; - GrpcAPI.DecryptNotesTRC20 receiverNote; - long senderPosition; - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() throws Exception { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - publicFromAmount = getRandomAmount(); - - //Generate new shiled account for sender and receiver - senderShieldAddressInfo = getNewShieldedAddress(blockingStubFull); - receiverShieldAddressInfo = getNewShieldedAddress(blockingStubFull); - String memo = "Create a note for transfer test " + System.currentTimeMillis(); - String sendShieldAddress = senderShieldAddressInfo.get().getAddress(); - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, sendShieldAddress, - "" + publicFromAmount, memo, blockingStubFull); - //Create mint parameters - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters - = createShieldedTrc20Parameters(publicFromAmount, - null, null, shieldOutList, "", 0L, - blockingStubFull, blockingStubSolidity); - String data = encodeMintParamsToHexString(shieldedTrc20Parameters, publicFromAmount); - //Do mint transaction type - String txid = PublicMethed.triggerContract(shieldAddressByte, - mint, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - - //Scan sender note - senderNote = scanShieldedTrc20NoteByIvk(senderShieldAddressInfo.get(), - blockingStubFull); - Assert.assertEquals(senderNote.getNoteTxs(0).getIsSpent(), false); - logger.info("" + senderNote); - senderPosition = senderNote.getNoteTxs(0).getPosition(); - Assert.assertEquals(senderNote.getNoteTxs(0).getNote().getValue(), - publicFromAmount.longValue()); - - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Shield TRC20 transaction with type transfer") - public void test01ShieldTrc20TransactionWithTypeTransfer() throws Exception { - final Long beforeMintShieldContractBalance = getBalanceOfShieldTrc20(shieldAddress, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - - String transferMemo = "Transfer type test " + System.currentTimeMillis(); - String receiverShieldAddress = receiverShieldAddressInfo.get().getAddress(); - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, receiverShieldAddress, - "" + publicFromAmount, transferMemo, blockingStubFull); - inputShieldAddressList.add(senderShieldAddressInfo.get()); - //inputNoteList.add(senderNote); - //Create transfer parameters - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters - = createShieldedTrc20Parameters(BigInteger.valueOf(0), - senderNote, inputShieldAddressList, shieldOutList, "", 0L, - blockingStubFull, blockingStubSolidity); - - String data = encodeTransferParamsToHexString(shieldedTrc20Parameters); - //String data = shieldedTrc20Parameters.getTriggerContractInput(); - String txid = PublicMethed.triggerContract(shieldAddressByte, - transfer, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 300000); - - //Scan sender note - receiverNote = scanShieldedTrc20NoteByIvk(receiverShieldAddressInfo.get(), - blockingStubFull); - - logger.info("" + receiverNote); - Assert.assertEquals(receiverNote.getNoteTxs(0).getTxid(), infoById.get().getId()); - Assert.assertEquals(receiverNote.getNoteTxs(0).getNote().getMemo(), - ByteString.copyFromUtf8(transferMemo)); - Assert.assertEquals(receiverNote.getNoteTxs(0).getNote().getValue(), - publicFromAmount.longValue()); - Assert.assertEquals(receiverNote.getNoteTxs(0).getNote().getPaymentAddress(), - receiverShieldAddressInfo.get().getAddress()); - - logger.info("scanShieldedTrc20NoteByIvk + senderNote:" + senderNote); - senderNote = scanShieldedTrc20NoteByIvk(senderShieldAddressInfo.get(), - blockingStubFull); - Assert.assertEquals(senderNote.getNoteTxs(0).getIsSpent(), true); - - senderNote = scanShieldedTrc20NoteByOvk(senderShieldAddressInfo.get(), - blockingStubFull); - logger.info("scanShieldedTrc20NoteByOvk + senderNote:" + senderNote); - - final Long afterMintShieldContractBalance = getBalanceOfShieldTrc20(shieldAddress, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - Assert.assertEquals(beforeMintShieldContractBalance, afterMintShieldContractBalance); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Shield TRC20 transaction with type transfer without ask") - public void test02ShieldTrc20TransactionWithTypeTransferWithoutAsk() throws Exception { - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - //Scan receiver note prepare for without type of transfer - receiverNote = scanShieldedTrc20NoteByIvk(receiverShieldAddressInfo.get(), - blockingStubFull); - String transferMemo = "Transfer type without ask test " + System.currentTimeMillis(); - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, senderShieldAddressInfo.get() - .getAddress(), - "" + publicFromAmount, transferMemo, blockingStubFull); - inputShieldAddressList.clear(); - inputShieldAddressList.add(receiverShieldAddressInfo.get()); - - //Create transfer parameters - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters - = createShieldedTrc20ParametersWithoutAsk(BigInteger.valueOf(0), - receiverNote, inputShieldAddressList, shieldOutList, "", null, 0L, - blockingStubFull, blockingStubSolidity); - - String data = encodeTransferParamsToHexString(shieldedTrc20Parameters); - String txid = PublicMethed.triggerContract(shieldAddressByte, - transfer, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 300000); - - senderNote = scanShieldedTrc20NoteByIvk(senderShieldAddressInfo.get(), - blockingStubFull); - - logger.info("" + senderNote); - Assert.assertEquals(senderNote.getNoteTxs(1).getTxid(), infoById.get().getId()); - Assert.assertEquals(senderNote.getNoteTxs(1).getNote().getMemo(), - ByteString.copyFromUtf8(transferMemo)); - Assert.assertEquals(senderNote.getNoteTxs(1).getNote().getValue(), - publicFromAmount.longValue()); - Assert.assertEquals(senderNote.getNoteTxs(1).getNote().getPaymentAddress(), - senderShieldAddressInfo.get().getAddress()); - - //logger.info("scanShieldedTrc20NoteByIvk + senderNote:" + senderNote); - receiverNote = scanShieldedTrc20NoteByIvk(receiverShieldAddressInfo.get(), - blockingStubFull); - Assert.assertEquals(receiverNote.getNoteTxs(0).getIsSpent(), true); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token004.java deleted file mode 100644 index cfbe9e562df..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token004.java +++ /dev/null @@ -1,307 +0,0 @@ -package stest.tron.wallet.dailybuild.zentrc20token; - -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldedAddressInfo; -import stest.tron.wallet.common.client.utils.ZenTrc20Base; - -@Slf4j -public class ShieldTrc20Token004 extends ZenTrc20Base { - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - Optional senderShieldAddressInfo; - Optional secondSenderShieldAddressInfo; - Optional receiverShieldAddressInfo; - private BigInteger publicFromAmount; - List shieldOutList = new ArrayList<>(); - List inputShieldAddressList = new ArrayList<>(); - List inputNoteList = new ArrayList<>(); - GrpcAPI.DecryptNotesTRC20 senderNote; - GrpcAPI.DecryptNotesTRC20 secondSenderNote; - long senderPosition; - - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] receiverAddressbyte = ecKey1.getAddress(); - String receiverKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - String receiverAddressString = PublicMethed.getAddressString(receiverKey); - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() throws Exception { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - publicFromAmount = getRandomAmount(); - - //Generate new shiled account for sender and receiver - senderShieldAddressInfo = getNewShieldedAddress(blockingStubFull); - receiverShieldAddressInfo = getNewShieldedAddress(blockingStubFull); - String memo = "Create a note for burn test " + System.currentTimeMillis(); - String sendShieldAddress = senderShieldAddressInfo.get().getAddress(); - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, sendShieldAddress, - "" + publicFromAmount, memo, blockingStubFull); - //Create mint parameters - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters - = createShieldedTrc20Parameters(publicFromAmount, - null, null, shieldOutList, "", 0L, - blockingStubFull, blockingStubSolidity); - String data = encodeMintParamsToHexString(shieldedTrc20Parameters, publicFromAmount); - //Do mint transaction type - String txid = PublicMethed.triggerContract(shieldAddressByte, - mint, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - - //Scan sender note - senderNote = scanShieldedTrc20NoteByIvk(senderShieldAddressInfo.get(), - blockingStubFull); - Assert.assertEquals(senderNote.getNoteTxs(0).getIsSpent(), false); - logger.info("" + senderNote); - senderPosition = senderNote.getNoteTxs(0).getPosition(); - Assert.assertEquals(senderNote.getNoteTxs(0).getNote().getValue(), - publicFromAmount.longValue()); - - //Generate new shiled account for burn to one public and one shield - secondSenderShieldAddressInfo = getNewShieldedAddress(blockingStubFull); - - memo = "Create a note for burn to one public and one shield test " - + System.currentTimeMillis(); - sendShieldAddress = secondSenderShieldAddressInfo.get().getAddress(); - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, sendShieldAddress, - "" + publicFromAmount, memo, blockingStubFull); - //Create mint parameters - shieldedTrc20Parameters - = createShieldedTrc20Parameters(publicFromAmount, - null, null, shieldOutList, "", 0L, - blockingStubFull, blockingStubSolidity); - data = encodeMintParamsToHexString(shieldedTrc20Parameters, publicFromAmount); - //Do mint transaction type - txid = PublicMethed.triggerContract(shieldAddressByte, - mint, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - - //Scan sender note - secondSenderNote = scanShieldedTrc20NoteByIvk(secondSenderShieldAddressInfo.get(), - blockingStubFull); - Assert.assertEquals(secondSenderNote.getNoteTxs(0).getIsSpent(), false); - logger.info("" + secondSenderNote); - senderPosition = secondSenderNote.getNoteTxs(0).getPosition(); - Assert.assertEquals(secondSenderNote.getNoteTxs(0).getNote().getValue(), - publicFromAmount.longValue()); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Shield TRC20 transaction with type burn") - public void test01ShieldTrc20TransactionWithTypeBurn() throws Exception { - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - //Query account before mint balance - final Long beforeBurnAccountBalance = getBalanceOfShieldTrc20(receiverAddressString, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - //Query contract before mint balance - final Long beforeBurnShieldAccountBalance = getBalanceOfShieldTrc20(shieldAddress, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - - //String burnMemo = "Burn type test " + System.currentTimeMillis(); - inputShieldAddressList.add(senderShieldAddressInfo.get()); - BigInteger receiveAmount = publicFromAmount; - //Create transfer parameters - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters - = createShieldedTrc20Parameters(BigInteger.valueOf(0), - senderNote, inputShieldAddressList, null, receiverAddressString, - receiveAmount.longValue(), blockingStubFull, blockingStubSolidity); - - String data = shieldedTrc20Parameters.getTriggerContractInput(); - String txid = PublicMethed.triggerContract(shieldAddressByte, - burn, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 180000); - - logger.info("scanShieldedTrc20NoteByIvk + senderNote:" + senderNote); - senderNote = scanShieldedTrc20NoteByIvk(senderShieldAddressInfo.get(), - blockingStubFull); - Assert.assertEquals(senderNote.getNoteTxs(0).getIsSpent(), true); - - final Long afterBurnAccountBalance = getBalanceOfShieldTrc20(receiverAddressString, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - //Query contract before mint balance - final Long afterBurnShieldAccountBalance = getBalanceOfShieldTrc20(shieldAddress, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - - logger.info("afterBurnAccountBalance :" + afterBurnAccountBalance); - logger.info("beforeBurnAccountBalance :" + beforeBurnAccountBalance); - logger.info("beforeBurnShieldAccountBalance:" + beforeBurnShieldAccountBalance); - logger.info("afterBurnShieldAccountBalance :" + afterBurnShieldAccountBalance); - Assert.assertEquals(BigInteger.valueOf(afterBurnAccountBalance - beforeBurnAccountBalance), - receiveAmount); - Assert.assertEquals(BigInteger.valueOf(beforeBurnShieldAccountBalance - - afterBurnShieldAccountBalance), receiveAmount); - - senderNote = scanShieldedTrc20NoteByOvk(senderShieldAddressInfo.get(), - blockingStubFull); - Assert.assertEquals(ByteArray.toHexString(senderNote.getNoteTxs(0) - .getTxid().toByteArray()), txid); - Assert.assertEquals(senderNote.getNoteTxs(0).getToAmount(), publicFromAmount.toString()); - - String toAddress = ByteArray.toHexString(senderNote.getNoteTxs(0) - .getTransparentToAddress().toByteArray()); - String receiverHexString = ByteArray.toHexString(PublicMethed.getFinalAddress(receiverKey)); - Assert.assertEquals(toAddress, receiverHexString); - - - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "Shield TRC20 transaction to one T and one S with type burn") - public void test02ShieldTrc20TransactionWithTypeBurnToOnePublicAndOneShield() throws Exception { - secondSenderNote = scanShieldedTrc20NoteByIvk(secondSenderShieldAddressInfo.get(), - blockingStubFull); - - //Query account before mint balance - final Long beforeBurnAccountBalance = getBalanceOfShieldTrc20(receiverAddressString, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - //Query contract before mint balance - final Long beforeBurnShieldAccountBalance = getBalanceOfShieldTrc20(shieldAddress, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - - inputShieldAddressList.clear(); - inputShieldAddressList.add(secondSenderShieldAddressInfo.get()); - BigInteger shieldReceiveAmount = BigInteger.valueOf(9L); - BigInteger receiveAmount = publicFromAmount.subtract(shieldReceiveAmount); - - ShieldedAddressInfo receiverShieldAddressInfo = getNewShieldedAddress(blockingStubFull).get(); - String receiverShieldAddress = receiverShieldAddressInfo.getAddress(); - String memo = "Burn to one shield and one public test " + System.currentTimeMillis(); - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, receiverShieldAddress, - "" + shieldReceiveAmount, memo, blockingStubFull); - - //Create transfer parameters - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters - = createShieldedTrc20Parameters(BigInteger.valueOf(0), - secondSenderNote, inputShieldAddressList, shieldOutList, receiverAddressString, - receiveAmount.longValue(), blockingStubFull, blockingStubSolidity); - - String data = shieldedTrc20Parameters.getTriggerContractInput(); - String txid = PublicMethed.triggerContract(shieldAddressByte, - burn, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 180000); - - logger.info("scanShieldedTrc20NoteByIvk + senderNote:" + senderNote); - senderNote = scanShieldedTrc20NoteByIvk(senderShieldAddressInfo.get(), - blockingStubFull); - Assert.assertEquals(senderNote.getNoteTxs(0).getIsSpent(), true); - - final Long afterBurnAccountBalance = getBalanceOfShieldTrc20(receiverAddressString, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - //Query contract before mint balance - final Long afterBurnShieldAccountBalance = getBalanceOfShieldTrc20(shieldAddress, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - - logger.info("afterBurnAccountBalance :" + afterBurnAccountBalance); - logger.info("beforeBurnAccountBalance :" + beforeBurnAccountBalance); - logger.info("beforeBurnShieldAccountBalance:" + beforeBurnShieldAccountBalance); - logger.info("afterBurnShieldAccountBalance :" + afterBurnShieldAccountBalance); - Assert.assertEquals(BigInteger.valueOf(afterBurnAccountBalance - beforeBurnAccountBalance), - receiveAmount); - Assert.assertEquals(BigInteger.valueOf(beforeBurnShieldAccountBalance - - afterBurnShieldAccountBalance), receiveAmount); - - secondSenderNote = scanShieldedTrc20NoteByOvk(secondSenderShieldAddressInfo.get(), - blockingStubFull); - logger.info(secondSenderNote.toString()); - Assert.assertEquals(secondSenderNote.getNoteTxs(0).getNote().getValue(), - shieldReceiveAmount.longValue()); - - Assert.assertEquals(ByteArray.toHexString(secondSenderNote.getNoteTxs(1) - .getTxid().toByteArray()), txid); - Assert.assertEquals(secondSenderNote.getNoteTxs(1).getToAmount(), receiveAmount.toString()); - - String toAddress = ByteArray.toHexString(secondSenderNote.getNoteTxs(1) - .getTransparentToAddress().toByteArray()); - String receiverHexString = ByteArray.toHexString(PublicMethed.getFinalAddress(receiverKey)); - Assert.assertEquals(toAddress, receiverHexString); - - GrpcAPI.DecryptNotesTRC20 receiverSenderNote - = scanShieldedTrc20NoteByIvk(receiverShieldAddressInfo, - blockingStubFull); - Assert.assertEquals(receiverSenderNote.getNoteTxs(0) - .getIsSpent(), false); - Assert.assertEquals(receiverSenderNote.getNoteTxs(0) - .getNote().getValue(), shieldReceiveAmount.longValue()); - Assert.assertEquals(ByteArray.toHexString(receiverSenderNote - .getNoteTxs(0).getTxid().toByteArray()), txid); - - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token005.java deleted file mode 100644 index fb5768ca316..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token005.java +++ /dev/null @@ -1,276 +0,0 @@ -package stest.tron.wallet.dailybuild.zentrc20token; - -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldedAddressInfo; -import stest.tron.wallet.common.client.utils.ZenTrc20Base; - -@Slf4j -public class ShieldTrc20Token005 extends ZenTrc20Base { - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - Optional senderShieldAddressInfo; - Optional secondSenderShieldAddressInfo; - private BigInteger publicFromAmount; - List shieldOutList = new ArrayList<>(); - List inputShieldAddressList = new ArrayList<>(); - List inputNoteList = new ArrayList<>(); - GrpcAPI.DecryptNotesTRC20 senderNote; - GrpcAPI.DecryptNotesTRC20 secondSenderNote; - GrpcAPI.DecryptNotesTRC20 receiverSenderNote; - long senderPosition; - - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] receiverAddressbyte = ecKey1.getAddress(); - String receiverKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - String receiverAddressString = PublicMethed.getAddressString(receiverKey); - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() throws Exception { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - publicFromAmount = getRandomAmount(); - - //Generate new shiled account for sender and receiver - senderShieldAddressInfo = getNewShieldedAddress(blockingStubFull); - String memo = "Create a note for burn withoutask test " + System.currentTimeMillis(); - String sendShieldAddress = senderShieldAddressInfo.get().getAddress(); - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, sendShieldAddress, - "" + publicFromAmount, memo, blockingStubFull); - //Create mint parameters - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters - = createShieldedTrc20Parameters(publicFromAmount, - null, null, shieldOutList, "", 0L, - blockingStubFull, blockingStubSolidity); - String data = encodeMintParamsToHexString(shieldedTrc20Parameters, publicFromAmount); - //Do mint transaction type - String txid = PublicMethed.triggerContract(shieldAddressByte, - mint, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - - //Create second mint parameters - memo = "Create a note for burn to one public and one shield withoutask test " - + System.currentTimeMillis(); - secondSenderShieldAddressInfo = getNewShieldedAddress(blockingStubFull); - String sesendShieldAddress = secondSenderShieldAddressInfo.get().getAddress(); - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, sesendShieldAddress, - "" + publicFromAmount, memo, blockingStubFull); - - shieldedTrc20Parameters - = createShieldedTrc20Parameters(publicFromAmount, - null, null, shieldOutList, "", 0L, - blockingStubFull, blockingStubSolidity); - data = encodeMintParamsToHexString(shieldedTrc20Parameters, publicFromAmount); - //Do mint transaction type - txid = PublicMethed.triggerContract(shieldAddressByte, - mint, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - - //Scan sender note - senderNote = scanShieldedTrc20NoteByIvk(senderShieldAddressInfo.get(), - blockingStubFull); - Assert.assertEquals(senderNote.getNoteTxs(0).getIsSpent(), false); - logger.info("" + senderNote); - senderPosition = senderNote.getNoteTxs(0).getPosition(); - Assert.assertEquals(senderNote.getNoteTxs(0).getNote().getValue(), - publicFromAmount.longValue()); - - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Shield TRC20 transaction with type burn and without ask") - public void test01ShieldTrc20TransactionWithTypeBurnWithoutAsk() throws Exception { - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - //Query account before mint balance - final Long beforeBurnAccountBalance = getBalanceOfShieldTrc20(receiverAddressString, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - //Query contract before mint balance - final Long beforeBurnShieldAccountBalance = getBalanceOfShieldTrc20(shieldAddress, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - - inputShieldAddressList.add(senderShieldAddressInfo.get()); - BigInteger receiveAmount = publicFromAmount; - //Create burn parameters - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters - = createShieldedTrc20ParametersWithoutAsk(BigInteger.valueOf(0), - senderNote, inputShieldAddressList, null, receiverAddressString, receiverAddressbyte, - receiveAmount.longValue(), blockingStubFull, blockingStubSolidity); - - String data = shieldedTrc20Parameters.getTriggerContractInput(); - String txid = PublicMethed.triggerContract(shieldAddressByte, - burn, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 180000); - - logger.info("scanShieldedTrc20NoteByIvk + senderNote:" + senderNote); - senderNote = scanShieldedTrc20NoteByIvk(senderShieldAddressInfo.get(), - blockingStubFull); - Assert.assertEquals(senderNote.getNoteTxs(0).getIsSpent(), true); - - final Long afterBurnAccountBalance = getBalanceOfShieldTrc20(receiverAddressString, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - //Query contract before mint balance - final Long afterBurnShieldAccountBalance = getBalanceOfShieldTrc20(shieldAddress, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - - logger.info("afterBurnAccountBalance :" + afterBurnAccountBalance); - logger.info("beforeBurnAccountBalance :" + beforeBurnAccountBalance); - logger.info("beforeBurnShieldAccountBalance:" + beforeBurnShieldAccountBalance); - logger.info("afterBurnShieldAccountBalance :" + afterBurnShieldAccountBalance); - Assert.assertEquals(BigInteger.valueOf(afterBurnAccountBalance - beforeBurnAccountBalance), - receiveAmount); - Assert.assertEquals(BigInteger.valueOf(beforeBurnShieldAccountBalance - - afterBurnShieldAccountBalance), - receiveAmount); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Shield TRC20 transaction with type burn to one " - + "T and one Z address and without ask") - public void test02ShieldTrc20TransactionWithTypeBurnWithoutAsk() throws Exception { - //Scan sender note - secondSenderNote = scanShieldedTrc20NoteByIvk(secondSenderShieldAddressInfo.get(), - blockingStubFull); - //Query account before mint balance - final Long beforeBurnAccountBalance = getBalanceOfShieldTrc20(receiverAddressString, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - //Query contract before mint balance - final Long beforeBurnShieldAccountBalance = getBalanceOfShieldTrc20(shieldAddress, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - - inputShieldAddressList.clear(); - inputShieldAddressList.add(secondSenderShieldAddressInfo.get()); - BigInteger shieldReceiveAmount = BigInteger.valueOf(0); - BigInteger receiveAmount = publicFromAmount.subtract(shieldReceiveAmount); - - ShieldedAddressInfo receiverShieldAddressInfo = getNewShieldedAddress(blockingStubFull).get(); - String receiverShieldAddress = receiverShieldAddressInfo.getAddress(); - String memo = "Burn to one shield and one public test " + System.currentTimeMillis(); - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, receiverShieldAddress, - "" + shieldReceiveAmount, memo, blockingStubFull); - - //Create burn parameters - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters - = createShieldedTrc20ParametersWithoutAsk(BigInteger.valueOf(0), - secondSenderNote, inputShieldAddressList, shieldOutList, receiverAddressString, - receiverAddressbyte, - receiveAmount.longValue(), blockingStubFull, blockingStubSolidity); - - String data = shieldedTrc20Parameters.getTriggerContractInput(); - String txid = PublicMethed.triggerContract(shieldAddressByte, - burn, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 180000); - - logger.info("scanShieldedTrc20NoteByIvk + senderNote:" + senderNote); - secondSenderNote = scanShieldedTrc20NoteByIvk(secondSenderShieldAddressInfo.get(), - blockingStubFull); - Assert.assertEquals(secondSenderNote.getNoteTxs(0).getIsSpent(), true); - - final Long afterBurnAccountBalance = getBalanceOfShieldTrc20(receiverAddressString, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - //Query contract before mint balance - final Long afterBurnShieldAccountBalance = getBalanceOfShieldTrc20(shieldAddress, - zenTrc20TokenOwnerAddress, zenTrc20TokenOwnerKey, blockingStubFull); - - logger.info("afterBurnAccountBalance :" + afterBurnAccountBalance); - logger.info("beforeBurnAccountBalance :" + beforeBurnAccountBalance); - logger.info("beforeBurnShieldAccountBalance:" + beforeBurnShieldAccountBalance); - logger.info("afterBurnShieldAccountBalance :" + afterBurnShieldAccountBalance); - Assert.assertEquals(BigInteger.valueOf(afterBurnAccountBalance - beforeBurnAccountBalance), - receiveAmount); - Assert.assertEquals(BigInteger.valueOf(beforeBurnShieldAccountBalance - - afterBurnShieldAccountBalance), - receiveAmount); - - receiverSenderNote = scanShieldedTrc20NoteByIvk(receiverShieldAddressInfo, - blockingStubFull); - Assert.assertEquals(receiverSenderNote.getNoteTxs(0).getIsSpent(), false); - Assert.assertEquals(receiverSenderNote.getNoteTxs(0).getNote() - .getValue(), shieldReceiveAmount.longValue()); - Assert.assertEquals(ByteArray.toHexString(receiverSenderNote.getNoteTxs(0) - .getTxid().toByteArray()), txid); - - secondSenderNote = scanShieldedTrc20NoteByOvk(secondSenderShieldAddressInfo.get(), - blockingStubFull); - logger.info(secondSenderNote.toString()); - Assert.assertEquals(secondSenderNote.getNoteTxs(0).getNote().getValue(), - shieldReceiveAmount.longValue()); - - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token006.java b/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token006.java deleted file mode 100644 index 98137f506c3..00000000000 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/zentrc20token/ShieldTrc20Token006.java +++ /dev/null @@ -1,525 +0,0 @@ -package stest.tron.wallet.dailybuild.zentrc20token; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldedAddressInfo; -import stest.tron.wallet.common.client.utils.ZenTrc20Base; - -@Slf4j -public class ShieldTrc20Token006 extends ZenTrc20Base { - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String soliInPbft = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(2); - Optional shieldAddressInfo1; - Optional shieldAddressInfo2; - String shieldAddress1; - String shieldAddress2; - private BigInteger publicFromAmount; - private BigInteger shield1ReceiveAmountFor1to2; - private BigInteger shield2ReceiveAmountFor1to2; - private BigInteger shield1ReceiveAmountFor2to2; - private BigInteger shield2ReceiveAmountFor2to2; - private BigInteger shield1ReceiveAmountFor2to1; - List shieldOutList = new ArrayList<>(); - List inputShieldAddressList = new ArrayList<>(); - GrpcAPI.DecryptNotesTRC20 shield1Note; - GrpcAPI.DecryptNotesTRC20 shield2Note; - long senderPosition; - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() throws Exception { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelPbft = ManagedChannelBuilder.forTarget(soliInPbft) - .usePlaintext() - .build(); - blockingStubPbft = WalletSolidityGrpc.newBlockingStub(channelPbft); - - publicFromAmount = getRandomAmount(); - - //Generate new shiled account for sender and receiver - shieldAddressInfo1 = getNewShieldedAddress(blockingStubFull); - shieldAddressInfo2 = getNewShieldedAddress(blockingStubFull); - String memo = "Create a note for transfer test " + System.currentTimeMillis(); - shieldAddress1 = shieldAddressInfo1.get().getAddress(); - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, shieldAddress1, - "" + publicFromAmount, memo, blockingStubFull); - //Create mint parameters - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters - = createShieldedTrc20Parameters(publicFromAmount, - null, null, shieldOutList, "", 0L, - blockingStubFull, blockingStubSolidity - ); - String data = encodeMintParamsToHexString(shieldedTrc20Parameters, publicFromAmount); - //Do mint transaction type - String txid = PublicMethed.triggerContract(shieldAddressByte, - mint, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - - //Scan sender note - shield1Note = scanShieldedTrc20NoteByIvk(shieldAddressInfo1.get(), - blockingStubFull); - Assert.assertEquals(shield1Note.getNoteTxs(0).getIsSpent(), false); - logger.info("" + shield1Note); - senderPosition = shield1Note.getNoteTxs(0).getPosition(); - Assert.assertEquals(shield1Note.getNoteTxs(0).getNote().getValue(), - publicFromAmount.longValue()); - - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Shield TRC20 transfer with type 1 to 2") - public void test01ShieldTrc20TransferWith1To2() throws Exception { - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - //Prepare parameters - final String transferMemo1 = "1 to 2 for shieldAddressInfo1 " + System.currentTimeMillis(); - final String transferMemo2 = "1 to 2 for shieldAddressInfo2 " + System.currentTimeMillis(); - shieldAddress1 = shieldAddressInfo1.get().getAddress(); - shieldAddress2 = shieldAddressInfo2.get().getAddress(); - shield1ReceiveAmountFor1to2 = BigInteger.valueOf(30); - shield2ReceiveAmountFor1to2 = publicFromAmount.subtract(shield1ReceiveAmountFor1to2); - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, shieldAddress1, - "" + shield1ReceiveAmountFor1to2, transferMemo1, blockingStubFull); - shieldOutList = addShieldTrc20OutputList(shieldOutList, shieldAddress2, - "" + shield2ReceiveAmountFor1to2, transferMemo2, blockingStubFull); - inputShieldAddressList.clear(); - inputShieldAddressList.add(shieldAddressInfo1.get()); - - //Create transfer parameters - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters - = createShieldedTrc20Parameters(BigInteger.valueOf(0), - shield1Note, inputShieldAddressList, shieldOutList, "", 0L, - blockingStubFull, blockingStubSolidity - ); - - //Create transfer transaction - String data = encodeTransferParamsToHexString(shieldedTrc20Parameters); - String txid = PublicMethed.triggerContract(shieldAddressByte, - transfer, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 300000); - - //Scan 1 to 2 ivk note - shield1Note = scanShieldedTrc20NoteByIvk(shieldAddressInfo1.get(), - blockingStubFull); - shield2Note = scanShieldedTrc20NoteByIvk(shieldAddressInfo2.get(), - blockingStubFull); - logger.info("" + shield1Note); - logger.info("" + shield2Note); - Assert.assertEquals(shield1Note.getNoteTxs(1).getTxid(), infoById.get().getId()); - Assert.assertEquals(shield1Note.getNoteTxs(1).getNote().getMemo(), - ByteString.copyFromUtf8(transferMemo1)); - Assert.assertEquals(shield1Note.getNoteTxs(1).getNote().getValue(), - shield1ReceiveAmountFor1to2.longValue()); - Assert.assertEquals(shield1Note.getNoteTxs(1).getNote().getPaymentAddress(), - shieldAddressInfo1.get().getAddress()); - - Assert.assertEquals(shield2Note.getNoteTxs(0).getTxid(), infoById.get().getId()); - Assert.assertEquals(shield2Note.getNoteTxs(0).getNote().getMemo(), - ByteString.copyFromUtf8(transferMemo2)); - Assert.assertEquals(shield2Note.getNoteTxs(0).getNote().getValue(), - shield2ReceiveAmountFor1to2.longValue()); - Assert.assertEquals(shield2Note.getNoteTxs(0).getNote().getPaymentAddress(), - shieldAddressInfo2.get().getAddress()); - - Assert.assertEquals(shield1Note.getNoteTxs(0).getIsSpent(), true); - - //Scan 1 to 2 ovk note - shield1Note = scanShieldedTrc20NoteByOvk(shieldAddressInfo1.get(), - blockingStubFull); - logger.info("scanShieldedTrc20NoteByOvk + shield1Note:" + shield1Note); - Assert.assertEquals(shield1Note.getNoteTxsCount(), 2); - - Assert.assertEquals(shield1Note.getNoteTxs(0).getTxid(), infoById.get().getId()); - Assert.assertEquals(shield1Note.getNoteTxs(0).getNote().getMemo(), - ByteString.copyFromUtf8(transferMemo1)); - Assert.assertEquals(shield1Note.getNoteTxs(0).getNote().getValue(), - shield1ReceiveAmountFor1to2.longValue()); - Assert.assertEquals(shield1Note.getNoteTxs(0).getNote().getPaymentAddress(), - shieldAddressInfo1.get().getAddress()); - - Assert.assertEquals(shield1Note.getNoteTxs(1).getTxid(), infoById.get().getId()); - Assert.assertEquals(shield1Note.getNoteTxs(1).getNote().getMemo(), - ByteString.copyFromUtf8(transferMemo2)); - Assert.assertEquals(shield1Note.getNoteTxs(1).getNote().getValue(), - shield2ReceiveAmountFor1to2.longValue()); - Assert.assertEquals(shield1Note.getNoteTxs(1).getNote().getPaymentAddress(), - shieldAddressInfo2.get().getAddress()); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "Shield TRC20 transfer with type 2 to 2") - public void test02ShieldTrc20TransferWith2To2() throws Exception { - //Create a new note for 2 to 2 - String memo = "Create a new note for transfer test " + System.currentTimeMillis(); - shieldAddress1 = shieldAddressInfo1.get().getAddress(); - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, shieldAddress1, - "" + publicFromAmount, memo, blockingStubFull); - //Create mint parameters - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters - = createShieldedTrc20Parameters(publicFromAmount, - null, null, shieldOutList, "", 0L, - blockingStubFull, blockingStubSolidity - ); - String data = encodeMintParamsToHexString(shieldedTrc20Parameters, publicFromAmount); - //Do mint transaction type - String txid = PublicMethed.triggerContract(shieldAddressByte, - mint, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - shield1Note = scanShieldedTrc20NoteByIvk(shieldAddressInfo1.get(), - blockingStubFull); - - final GrpcAPI.DecryptNotesTRC20 inputNoteFor2to2 = GrpcAPI.DecryptNotesTRC20.newBuilder() - .addNoteTxs(shield1Note.getNoteTxs(1)) - .addNoteTxs(shield1Note.getNoteTxs(2)).build(); - - //Prepare parameters - final String transferMemo1 = "2 to 2 for shieldAddressInfo1 " + System.currentTimeMillis(); - final String transferMemo2 = "2 to 2 for shieldAddressInfo2 " + System.currentTimeMillis(); - shieldAddress1 = shieldAddressInfo1.get().getAddress(); - shieldAddress2 = shieldAddressInfo2.get().getAddress(); - shield1ReceiveAmountFor2to2 = BigInteger.valueOf(5); - shield2ReceiveAmountFor2to2 = publicFromAmount.add(shield1ReceiveAmountFor1to2) - .subtract(shield1ReceiveAmountFor2to2); - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, shieldAddress1, - "" + shield1ReceiveAmountFor2to2, transferMemo1, blockingStubFull); - shieldOutList = addShieldTrc20OutputList(shieldOutList, shieldAddress2, - "" + shield2ReceiveAmountFor2to2, transferMemo2, blockingStubFull); - inputShieldAddressList.clear(); - inputShieldAddressList.add(shieldAddressInfo1.get()); - inputShieldAddressList.add(shieldAddressInfo1.get()); - - //Create transfer parameters - shieldedTrc20Parameters - = createShieldedTrc20Parameters(BigInteger.valueOf(0), - inputNoteFor2to2, inputShieldAddressList, shieldOutList, "", 0L, - blockingStubFull, blockingStubSolidity - ); - - //Create transfer transaction - data = encodeTransferParamsToHexString(shieldedTrc20Parameters); - txid = PublicMethed.triggerContract(shieldAddressByte, - transfer, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 300000); - - //Scan 2 to 2 ivk note - shield1Note = scanShieldedTrc20NoteByIvk(shieldAddressInfo1.get(), - blockingStubFull); - shield2Note = scanShieldedTrc20NoteByIvk(shieldAddressInfo2.get(), - blockingStubFull); - logger.info("" + shield1Note); - logger.info("" + shield2Note); - Assert.assertEquals(shield1Note.getNoteTxs(3).getTxid(), infoById.get().getId()); - Assert.assertEquals(shield1Note.getNoteTxs(3).getNote().getMemo(), - ByteString.copyFromUtf8(transferMemo1)); - Assert.assertEquals(shield1Note.getNoteTxs(3).getNote().getValue(), - shield1ReceiveAmountFor2to2.longValue()); - Assert.assertEquals(shield1Note.getNoteTxs(3).getNote().getPaymentAddress(), - shieldAddressInfo1.get().getAddress()); - - Assert.assertEquals(shield2Note.getNoteTxs(1).getTxid(), infoById.get().getId()); - Assert.assertEquals(shield2Note.getNoteTxs(1).getNote().getMemo(), - ByteString.copyFromUtf8(transferMemo2)); - Assert.assertEquals(shield2Note.getNoteTxs(1).getNote().getValue(), - shield2ReceiveAmountFor2to2.longValue()); - Assert.assertEquals(shield2Note.getNoteTxs(1).getNote().getPaymentAddress(), - shieldAddressInfo2.get().getAddress()); - - Assert.assertEquals(shield1Note.getNoteTxs(1).getIsSpent(), true); - Assert.assertEquals(shield1Note.getNoteTxs(2).getIsSpent(), true); - - //Scan 2 to 2 ovk note - shield1Note = scanShieldedTrc20NoteByOvk(shieldAddressInfo1.get(), - blockingStubFull); - logger.info("scanShieldedTrc20NoteByOvk + shield1Note:" + shield1Note); - Assert.assertEquals(shield1Note.getNoteTxsCount(), 4); - - Assert.assertEquals(shield1Note.getNoteTxs(2).getTxid(), infoById.get().getId()); - Assert.assertEquals(shield1Note.getNoteTxs(2).getNote().getMemo(), - ByteString.copyFromUtf8(transferMemo1)); - Assert.assertEquals(shield1Note.getNoteTxs(2).getNote().getValue(), - shield1ReceiveAmountFor2to2.longValue()); - Assert.assertEquals(shield1Note.getNoteTxs(2).getNote().getPaymentAddress(), - shieldAddressInfo1.get().getAddress()); - - Assert.assertEquals(shield1Note.getNoteTxs(3).getTxid(), infoById.get().getId()); - Assert.assertEquals(shield1Note.getNoteTxs(3).getNote().getMemo(), - ByteString.copyFromUtf8(transferMemo2)); - Assert.assertEquals(shield1Note.getNoteTxs(3).getNote().getValue(), - shield2ReceiveAmountFor2to2.longValue()); - Assert.assertEquals(shield1Note.getNoteTxs(3).getNote().getPaymentAddress(), - shieldAddressInfo2.get().getAddress()); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Shield TRC20 transfer with type 2 to 1") - public void test03ShieldTrc20TransferWith2To1() throws Exception { - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - shield2Note = scanShieldedTrc20NoteByIvk(shieldAddressInfo2.get(), - blockingStubFull); - - //Prepare parameters - final String transferMemo1 = "2 to 1 for shieldAddressInfo1 " + System.currentTimeMillis(); - - shieldAddress1 = shieldAddressInfo1.get().getAddress(); - shield1ReceiveAmountFor2to1 = BigInteger.valueOf(shield2Note.getNoteTxs(0) - .getNote().getValue() + shield2Note.getNoteTxs(1).getNote().getValue()); - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, shieldAddress1, - "" + shield1ReceiveAmountFor2to1, transferMemo1, blockingStubFull); - inputShieldAddressList.clear(); - inputShieldAddressList.add(shieldAddressInfo2.get()); - inputShieldAddressList.add(shieldAddressInfo2.get()); - - //Create transfer parameters - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters - = createShieldedTrc20Parameters(BigInteger.valueOf(0), - shield2Note, inputShieldAddressList, shieldOutList, "", 0L, - blockingStubFull, blockingStubSolidity - ); - - //Create transfer transaction - String data = encodeTransferParamsToHexString(shieldedTrc20Parameters); - String txid = PublicMethed.triggerContract(shieldAddressByte, - transfer, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getReceipt().getResultValue() == 1); - Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 300000); - - //Scan 2 to 1 ivk note - shield1Note = scanShieldedTrc20NoteByIvk(shieldAddressInfo1.get(), - blockingStubFull); - shield2Note = scanShieldedTrc20NoteByIvk(shieldAddressInfo2.get(), - blockingStubFull); - logger.info("" + shield1Note); - logger.info("" + shield2Note); - Assert.assertEquals(shield1Note.getNoteTxs(4).getTxid(), infoById.get().getId()); - Assert.assertEquals(shield1Note.getNoteTxs(4).getNote().getMemo(), - ByteString.copyFromUtf8(transferMemo1)); - Assert.assertEquals(shield1Note.getNoteTxs(4).getNote().getValue(), - shield1ReceiveAmountFor2to1.longValue()); - Assert.assertEquals(shield1Note.getNoteTxs(4).getNote().getPaymentAddress(), - shieldAddressInfo1.get().getAddress()); - - Assert.assertEquals(shield2Note.getNoteTxs(0).getIsSpent(), true); - Assert.assertEquals(shield2Note.getNoteTxs(1).getIsSpent(), true); - - //Scan 2 to 1 ovk note - shield2Note = scanShieldedTrc20NoteByOvk(shieldAddressInfo2.get(), - blockingStubFull); - logger.info("scanShieldedTrc20NoteByOvk + shield1Note:" + shield2Note); - Assert.assertEquals(shield2Note.getNoteTxsCount(), 1); - - Assert.assertEquals(shield2Note.getNoteTxs(0).getTxid(), infoById.get().getId()); - Assert.assertEquals(shield2Note.getNoteTxs(0).getNote().getValue(), - shield1ReceiveAmountFor2to1.longValue()); - Assert.assertEquals(shield2Note.getNoteTxs(0).getNote().getPaymentAddress(), - shieldAddressInfo1.get().getAddress()); - - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Scan shield trc20 note by ivk and ovk on solidity") - public void test04ScanShieldTrc20NoteByIvkAndOvkOnSolidity() throws Exception { - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - shield1Note = scanShieldedTrc20NoteByIvk(shieldAddressInfo1.get(), - blockingStubFull); - GrpcAPI.DecryptNotesTRC20 shield1NoteOnSolidity - = scanShieldedTrc20NoteByIvk(shieldAddressInfo1.get(), - blockingStubFull, blockingStubSolidity); - Assert.assertEquals(shield1Note, shield1NoteOnSolidity); - - shield2Note = scanShieldedTrc20NoteByIvk(shieldAddressInfo2.get(), - blockingStubFull); - GrpcAPI.DecryptNotesTRC20 shield2NoteOnSolidity - = scanShieldedTrc20NoteByIvk(shieldAddressInfo2.get(), - blockingStubFull, blockingStubSolidity); - Assert.assertEquals(shield2Note, shield2NoteOnSolidity); - - shield1Note = scanShieldedTrc20NoteByOvk(shieldAddressInfo1.get(), - blockingStubFull); - shield1NoteOnSolidity - = scanShieldedTrc20NoteByOvk(shieldAddressInfo1.get(), - blockingStubFull, blockingStubSolidity); - Assert.assertEquals(shield1Note, shield1NoteOnSolidity); - - shield2Note = scanShieldedTrc20NoteByOvk(shieldAddressInfo2.get(), - blockingStubFull); - shield2NoteOnSolidity - = scanShieldedTrc20NoteByOvk(shieldAddressInfo2.get(), - blockingStubFull, blockingStubSolidity); - Assert.assertEquals(shield2Note, shield2NoteOnSolidity); - } - - /** - * constructor. - */ - @Test(enabled = true, description = "Scan shield trc20 note by ivk and ovk on pbft") - public void test04ScanShieldTrc20NoteByIvkAndOvkOnPbft() throws Exception { - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - shield1Note = scanShieldedTrc20NoteByIvk(shieldAddressInfo1.get(), - blockingStubFull); - GrpcAPI.DecryptNotesTRC20 shield1NoteOnPbft - = scanShieldedTrc20NoteByIvk(shieldAddressInfo1.get(), - blockingStubFull, blockingStubPbft); - Assert.assertEquals(shield1Note, shield1NoteOnPbft); - - shield2Note = scanShieldedTrc20NoteByIvk(shieldAddressInfo2.get(), - blockingStubFull); - GrpcAPI.DecryptNotesTRC20 shield2NoteOnPbft - = scanShieldedTrc20NoteByIvk(shieldAddressInfo2.get(), - blockingStubFull, blockingStubPbft); - Assert.assertEquals(shield2Note, shield2NoteOnPbft); - - shield1Note = scanShieldedTrc20NoteByOvk(shieldAddressInfo1.get(), - blockingStubFull); - shield1NoteOnPbft - = scanShieldedTrc20NoteByOvk(shieldAddressInfo1.get(), - blockingStubFull, blockingStubPbft); - Assert.assertEquals(shield1Note, shield1NoteOnPbft); - - shield2Note = scanShieldedTrc20NoteByOvk(shieldAddressInfo2.get(), - blockingStubFull); - shield2NoteOnPbft - = scanShieldedTrc20NoteByOvk(shieldAddressInfo2.get(), - blockingStubFull, blockingStubPbft); - Assert.assertEquals(shield2Note, shield2NoteOnPbft); - } - - - /** - * constructor. - */ - @Test(enabled = true, description = "Query is shield trc20 note spend on solidity and pbft") - public void test05IsShieldTrc20NoteSpendOnSolidityAndPbft() throws Exception { - shield1Note = scanShieldedTrc20NoteByIvk(shieldAddressInfo1.get(), - blockingStubFull); - shield2Note = scanShieldedTrc20NoteByIvk(shieldAddressInfo2.get(), - blockingStubFull); - - Assert.assertEquals(getTrc20SpendResult(shieldAddressInfo1.get(), - shield1Note.getNoteTxs(0), blockingStubFull), true); - - Assert.assertEquals(getTrc20SpendResult(shieldAddressInfo1.get(), - shield1Note.getNoteTxs(0), blockingStubFull), - getTrc20SpendResult(shieldAddressInfo1.get(), - shield1Note.getNoteTxs(0), blockingStubFull, blockingStubSolidity)); - - Assert.assertTrue(getTrc20SpendResult(shieldAddressInfo1.get(), - shield1Note.getNoteTxs(0), blockingStubFull, blockingStubPbft)); - - boolean spend = getTrc20SpendResult(shieldAddressInfo1.get(),shield1Note.getNoteTxs(1), - blockingStubFull); - - Assert.assertEquals(spend, - getTrc20SpendResult(shieldAddressInfo1.get(), shield1Note.getNoteTxs(1), - blockingStubFull, blockingStubSolidity)); - Assert.assertEquals(spend, - getTrc20SpendResult(shieldAddressInfo1.get(), shield1Note.getNoteTxs(1), - blockingStubFull, blockingStubPbft)); - - spend = getTrc20SpendResult(shieldAddressInfo2.get(),shield2Note.getNoteTxs(0), - blockingStubFull); - Assert.assertEquals(spend, - getTrc20SpendResult(shieldAddressInfo2.get(), shield2Note.getNoteTxs(0), - blockingStubFull, blockingStubSolidity)); - Assert.assertEquals(spend, - getTrc20SpendResult(shieldAddressInfo2.get(), shield2Note.getNoteTxs(0), - blockingStubFull, blockingStubPbft)); - - spend = getTrc20SpendResult(shieldAddressInfo2.get(),shield2Note.getNoteTxs(1), - blockingStubFull); - Assert.assertEquals(spend, - getTrc20SpendResult(shieldAddressInfo2.get(), shield2Note.getNoteTxs(1), - blockingStubFull, blockingStubSolidity)); - Assert.assertEquals(spend, - getTrc20SpendResult(shieldAddressInfo2.get(), shield2Note.getNoteTxs(1), - blockingStubFull, blockingStubPbft)); - - } - - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/AttackSendcoin.java b/framework/src/test/java/stest/tron/wallet/fulltest/AttackSendcoin.java deleted file mode 100644 index 7a4fe984bc4..00000000000 --- a/framework/src/test/java/stest/tron/wallet/fulltest/AttackSendcoin.java +++ /dev/null @@ -1,439 +0,0 @@ -package stest.tron.wallet.fulltest; - -import com.google.protobuf.ByteString; -import com.google.protobuf.InvalidProtocolBufferException; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Random; -import lombok.extern.slf4j.Slf4j; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.BalanceContract; -import org.tron.protos.contract.BalanceContract.TransferContract; -import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class AttackSendcoin { - - private static final long now = System.currentTimeMillis(); - private static long start; - private static long end; - private static long beforeFromBalance; - private static long beforeNormal1Balance; - private static long beforeNormal2Balance; - private static long beforeNormal3Balance; - private static long beforeNormal4Balance; - private static long beforeAttackBalance; - private static long afterFromBalance; - private static long afterNormal1Balance; - private static long afterNormal2Balance; - private static long afterNormal3Balance; - private static long afterNormal4Balance; - private static long afterAttackBalance; - //testng001、testng002、testng003、testng004 - //Devaccount - private final String testKey001 = - "8CB4480194192F30907E14B52498F594BD046E21D7C4D8FE866563A6760AC891"; - //Zion - private final String testKey002 = - "FC8BF0238748587B9617EB6D15D47A66C0E07C1A1959033CF249C6532DC29FE6"; - //Sun - private final String testKey003 = - "6815B367FDDE637E53E9ADC8E69424E07724333C9A2B973CFA469975E20753FC"; - //Normal1 - private final String normalKey001 = - "36c0710378a34634e6baba0d3a79d7439a81183030147e7f4a0dd43bfed1a32f"; - //Normal2 - private final String normalKey002 = - "a6bfbcf98bbe07770bf79bc6b2970bae0992771c1dcbf24cc063a3f033f17fbf"; - //Normal3 - private final String normalKey003 = - "8273f6b26202526cbffb77569b830c1ba8a920040e77f6f26062a67315580ed7"; - //Normal4 - private final String normalKey004 = - "271c824fcb55f04a9f86f768424a80edeb26ab79cf12aa56643b595f689c008a"; - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - private final byte[] attackAddress = PublicMethed.getFinalAddress(testKey001); - private final byte[] normal1Address = PublicMethed.getFinalAddress(normalKey001); - private final byte[] normal2Address = PublicMethed.getFinalAddress(normalKey002); - private final byte[] normal3Address = PublicMethed.getFinalAddress(normalKey003); - private final byte[] normal4Address = PublicMethed.getFinalAddress(normalKey004); - private final Long sendNromal1Amount = 1L; - private final Long sendNromal2Amount = 2L; - private final Long sendNromal3Amount = 3L; - private final Long sendNromal4Amount = 4L; - private final Long attackAmount = 5L; - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - /** - * constructor. - */ - - public static Boolean freezeBalance(byte[] addRess, long freezeBalance, long freezeDuration, - String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - Protocol.Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI - .EmptyMessage.newBuilder().build()); - final Long beforeBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Long beforeFrozenBalance = 0L; - //Long beforeBandwidth = beforeFronzen.getBandwidth(); - - BalanceContract.FreezeBalanceContract.Builder builder = BalanceContract.FreezeBalanceContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration); - - BalanceContract.FreezeBalanceContract contract = builder.build(); - Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction = null"); - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - - if (!response.getResult()) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } - - Long afterBlockNum = 0L; - - while (afterBlockNum < beforeBlockNum) { - Protocol.Block currentBlock1 = blockingStubFull.getNowBlock(GrpcAPI - .EmptyMessage.newBuilder().build()); - afterBlockNum = currentBlock1.getBlockHeader().getRawData().getNumber(); - } - return true; - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - final Account fromInfo = PublicMethed.queryAccount(testKey002, blockingStubFull); - final Account attackInfo = PublicMethed.queryAccount(testKey001, blockingStubFull); - final Account normal1Info = PublicMethed.queryAccount(normalKey001, blockingStubFull); - final Account normal2Info = PublicMethed.queryAccount(normalKey002, blockingStubFull); - final Account normal3Info = PublicMethed.queryAccount(normalKey003, blockingStubFull); - final Account normal4Info = PublicMethed.queryAccount(normalKey004, blockingStubFull); - beforeFromBalance = fromInfo.getBalance(); - beforeNormal1Balance = normal1Info.getBalance(); - beforeNormal2Balance = normal2Info.getBalance(); - beforeNormal3Balance = normal3Info.getBalance(); - beforeNormal4Balance = normal4Info.getBalance(); - beforeAttackBalance = attackInfo.getBalance(); - start = System.currentTimeMillis(); - } - - //@Test(enabled = true) - @Test(enabled = false, threadPoolSize = 200, invocationCount = 200) - public void freezeAndSendcoin() throws InterruptedException { - - Integer i = 0; - Random rand = new Random(); - Integer randNum = 0; - Integer n = 0; - - while (i < 20) { - randNum = i % 4; - i++; - fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(randNum); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - if (randNum == 3) { - PublicMethed.sendcoin(attackAddress, attackAmount, fromAddress, testKey002, - blockingStubFull); - PublicMethed.sendcoin(attackAddress, attackAmount, fromAddress, testKey002, - blockingStubFull); - /* PublicMethed.sendcoin(attackAddress, attackAmount, fromAddress, testKey002, - blockingStubFull); - PublicMethed.sendcoin(attackAddress, attackAmount, fromAddress, testKey002, - blockingStubFull); - PublicMethed.sendcoin(attackAddress, attackAmount, fromAddress, testKey002, - blockingStubFull); - PublicMethed.sendcoin(attackAddress, attackAmount, fromAddress, testKey002, - blockingStubFull); - PublicMethed.sendcoin(attackAddress, attackAmount, fromAddress, testKey002, - blockingStubFull); - PublicMethed.sendcoin(attackAddress, attackAmount, fromAddress, testKey002, - blockingStubFull);*/ - } - - if (randNum == 0) { - PublicMethed.sendcoin(normal1Address, sendNromal1Amount, fromAddress, - testKey002, blockingStubFull); - continue; - } - if (randNum == 1) { - PublicMethed.sendcoin(normal2Address, sendNromal2Amount, fromAddress, - testKey002, blockingStubFull); - continue; - } - if (randNum == 2) { - PublicMethed.sendcoin(normal3Address, sendNromal3Amount, fromAddress, - testKey002, blockingStubFull); - continue; - } - if (randNum == 3) { - PublicMethed.sendcoin(normal4Address, sendNromal4Amount, fromAddress, - testKey002, blockingStubFull); - continue; - } - } - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - //Print the duration. - end = System.currentTimeMillis(); - logger.info("The time is " + Long.toString(end - start)); - - //Print 6 account balance information. - final Account fromInfo = PublicMethed.queryAccount(testKey002, blockingStubFull); - final Account attackInfo = PublicMethed.queryAccount(testKey001, blockingStubFull); - final Account normal1Info = PublicMethed.queryAccount(normalKey001, blockingStubFull); - final Account normal2Info = PublicMethed.queryAccount(normalKey002, blockingStubFull); - final Account normal3Info = PublicMethed.queryAccount(normalKey003, blockingStubFull); - final Account normal4Info = PublicMethed.queryAccount(normalKey004, blockingStubFull); - - afterFromBalance = fromInfo.getBalance(); - afterNormal1Balance = normal1Info.getBalance(); - afterNormal2Balance = normal2Info.getBalance(); - afterNormal3Balance = normal3Info.getBalance(); - afterNormal4Balance = normal4Info.getBalance(); - afterAttackBalance = attackInfo.getBalance(); - - logger.info("attack transaction success num is " - + (afterAttackBalance - beforeAttackBalance) / attackAmount); - logger.info("Normal 1 transaction success num is " - + (afterNormal1Balance - beforeNormal1Balance) / sendNromal1Amount); - logger.info("Normal 2 transaction success num is " - + (afterNormal2Balance - beforeNormal2Balance) / sendNromal2Amount); - logger.info("Normal 3 transaction success num is " - + (afterNormal3Balance - beforeNormal3Balance) / sendNromal3Amount); - logger.info("Normal 4 transaction success num is " - + (afterNormal4Balance - beforeNormal4Balance) / sendNromal4Amount); - - Long totalSuccessNum = (afterAttackBalance - beforeAttackBalance) / attackAmount - + (afterNormal1Balance - beforeNormal1Balance) / sendNromal1Amount - + (afterNormal3Balance - beforeNormal3Balance) / sendNromal3Amount - + (afterNormal4Balance - beforeNormal4Balance) / sendNromal4Amount - + (afterNormal2Balance - beforeNormal2Balance) / sendNromal2Amount; - logger.info("Total success transaction is " + Long.toString(totalSuccessNum)); - - Long normaltotalSuccessNum = (afterNormal1Balance - beforeNormal1Balance) / sendNromal1Amount - + (afterNormal3Balance - beforeNormal3Balance) / sendNromal3Amount - + (afterNormal4Balance - beforeNormal4Balance) / sendNromal4Amount - + (afterNormal2Balance - beforeNormal2Balance) / sendNromal2Amount; - logger.info("Total normal success transaction is " + Long.toString(normaltotalSuccessNum)); - - Integer blockTimes = 0; - Integer blockTransNum = 0; - - while (blockTimes < 5) { - blockTimes++; - //Print the current block transaction num. - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentNum = currentBlock.getBlockHeader().getRawData().getNumber(); - logger.info("The block num " + Long.toString(currentNum) - + "total transaction is " + Long.toString(currentBlock.getTransactionsCount())); - //logger.info(Integer.toString(currentBlock.getTransactionsList() - // .get(0).getRawData().getContract(0).getTypeValue())); - - Integer normal1Num = 0; - Integer normal2Num = 0; - Integer normal3Num = 0; - Integer normal4Num = 0; - Integer attackNum = 0; - Long temp = 0L; - for (Integer m = 0; m < currentBlock.getTransactionsCount(); m++) { - try { - temp = currentBlock.getTransactions(m).getRawData().getContract(0).getParameter() - .unpack(TransferContract.class).getAmount(); - } catch (InvalidProtocolBufferException e) { - e.printStackTrace(); - } - if (temp == sendNromal1Amount) { - normal1Num++; - } - if (temp == sendNromal2Amount) { - normal2Num++; - } - if (temp == sendNromal3Amount) { - normal3Num++; - } - if (temp == sendNromal4Amount) { - normal4Num++; - } - if (temp == attackAmount) { - attackNum++; - } - } - logger.info("Block num " + Long.toString(currentNum) + ", Attack num is " - + Integer.toString(attackNum)); - logger.info("Block num " + Long.toString(currentNum) + ", normal 1 num is " - + Integer.toString(normal1Num)); - logger.info("Block num " + Long.toString(currentNum) + ", normal 2 num is " - + Integer.toString(normal2Num)); - logger.info("Block num " + Long.toString(currentNum) + ", normal 3 num is " - + Integer.toString(normal3Num)); - logger.info("Block num " + Long.toString(currentNum) + ", normal 4 num is " - + Integer.toString(normal4Num)); - blockTransNum = blockTransNum + currentBlock.getTransactionsCount(); - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - logger.info("Total block record num is " + Integer.toString(blockTransNum)); - - - } - - /** - * constructor. - */ - - public boolean unFreezeBalance(byte[] addRess, String priKey) { - byte[] address = addRess; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - // Account search = queryAccount(ecKey, blockingStubFull); - - UnfreezeBalanceContract.Builder builder = UnfreezeBalanceContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess); - - UnfreezeBalanceContract contract = builder.build(); - - Transaction transaction = blockingStubFull.unfreezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public boolean withdrawBalance(byte[] address, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - BalanceContract.WithdrawBalanceContract.Builder builder = - BalanceContract.WithdrawBalanceContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - builder.setOwnerAddress(byteAddreess); - BalanceContract.WithdrawBalanceContract contract = builder.build(); - - Transaction transaction = blockingStubFull.withdrawBalance(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return false; - } - logger.info("test withdraw" + priKey); - return true; - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/ContinueVote.java b/framework/src/test/java/stest/tron/wallet/fulltest/ContinueVote.java deleted file mode 100644 index 64d2b3a68eb..00000000000 --- a/framework/src/test/java/stest/tron/wallet/fulltest/ContinueVote.java +++ /dev/null @@ -1,410 +0,0 @@ -package stest.tron.wallet.fulltest; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.HashMap; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AccountNetMessage; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.BalanceContract.FreezeBalanceContract; -import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; -import org.tron.protos.contract.WitnessContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class ContinueVote { - - //testng001、testng002、testng003、testng004 - - private final String testKey002 = - "FC8BF0238748587B9617EB6D15D47A66C0E07C1A1959033CF249C6532DC29FE6"; - - - /* //testng001、testng002、testng003、testng004 - private static final byte[] fromAddress = Base58 - .decodeFromBase58Check("THph9K2M2nLvkianrMGswRhz5hjSA9fuH7");*/ - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - - private ManagedChannel channelFull = null; - private ManagedChannel searchChannelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletGrpc.WalletBlockingStub searchBlockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String searchFullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - - WalletClient.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - logger.info("Pre fix byte ===== " + WalletClient.getAddressPreFixByte()); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext() - .build(); - searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); - } - - @Test(enabled = false, threadPoolSize = 30, invocationCount = 30) - public void testVoteWitness() { - ByteString addressBs = ByteString.copyFrom(fromAddress); - Account request = Account.newBuilder().setAddress(addressBs).build(); - AccountNetMessage accountNetMessage = blockingStubFull.getAccountNet(request); - Random rand = new Random(); - Integer randNum = rand.nextInt(30) + 1; - Base58.encode58Check(fromAddress); - logger.info(Base58.encode58Check(fromAddress)); - String voteStr = "TB4B1RMhoPeivkj4Hebm6tttHjRY9yQFes"; - HashMap smallVoteMap = new HashMap(); - smallVoteMap.put(voteStr, "1"); - Account fromInfo = PublicMethed.queryAccount(testKey002, blockingStubFull); - - Boolean ret = false; - Integer i = 0; - while (fromInfo.getBalance() > 100000000) { - randNum = rand.nextInt(30) + 1; - voteStr = "TB4B1RMhoPeivkj4Hebm6tttHjRY9yQFes"; - smallVoteMap = new HashMap(); - smallVoteMap.put(voteStr, Integer.toString(randNum)); - if (fromInfo.getFrozen(0).getFrozenBalance() < 10000000) { - PublicMethed.freezeBalance(fromAddress, 10000000000L, 3, testKey002, blockingStubFull); - } - ret = voteWitness(smallVoteMap, fromAddress, testKey002); - if (ret) { - logger.info("This vote num is " + Integer.toString(randNum)); - logger.info("Now the fromaddress vote is " + Long.toString(fromInfo - .getVotes(0).getVoteCount())); - logger.info(Integer.toString(i++)); - } - fromInfo = PublicMethed.queryAccount(testKey002, blockingStubFull); - accountNetMessage = blockingStubFull.getAccountNet(request); - logger.info("Now the from net used is " + Long.toString(accountNetMessage.getNetUsed())); - - } - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (searchChannelFull != null) { - searchChannelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean voteWitness(HashMap witness, byte[] addRess, String priKey) { - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account beforeVote = queryAccount(ecKey, blockingStubFull); - Long beforeVoteNum = 0L; - if (beforeVote.getVotesCount() != 0) { - beforeVoteNum = beforeVote.getVotes(0).getVoteCount(); - } - - WitnessContract.VoteWitnessContract.Builder builder = WitnessContract.VoteWitnessContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(addRess)); - for (String addressBase58 : witness.keySet()) { - String value = witness.get(addressBase58); - final long count = Long.parseLong(value); - WitnessContract.VoteWitnessContract.Vote.Builder voteBuilder = - WitnessContract.VoteWitnessContract.Vote - .newBuilder(); - byte[] address = WalletClient.decodeFromBase58Check(addressBase58); - logger.info("address ====== " + ByteArray.toHexString(address)); - if (address == null) { - continue; - } - voteBuilder.setVoteAddress(ByteString.copyFrom(address)); - voteBuilder.setVoteCount(count); - builder.addVotes(voteBuilder.build()); - } - - WitnessContract.VoteWitnessContract contract = builder.build(); - - Transaction transaction = blockingStubFull.voteWitnessAccount(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - Account afterVote = queryAccount(ecKey, searchBlockingStubFull); - //Long afterVoteNum = afterVote.getVotes(0).getVoteCount(); - for (String key : witness.keySet()) { - for (int j = 0; j < afterVote.getVotesCount(); j++) { - logger.info(Long.toString(Long.parseLong(witness.get(key)))); - logger.info(key); - if (key.equals("TB4B1RMhoPeivkj4Hebm6tttHjRY9yQFes")) { - logger.info("catch it"); - logger.info(Long.toString(afterVote.getVotes(j).getVoteCount())); - logger.info(Long.toString(Long.parseLong(witness.get(key)))); - //Assert.assertTrue(afterVote.getVotes(j).getVoteCount() == Long - // .parseLong(witness.get(key))); - } - - } - } - return true; - } - - /** - * constructor. - */ - - public Boolean freezeBalance(byte[] addRess, long freezeBalance, long freezeDuration, - String priKey) { - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account beforeFronzen = queryAccount(ecKey, blockingStubFull); - - Long beforeFrozenBalance = 0L; - //Long beforeBandwidth = beforeFronzen.getBandwidth(); - if (beforeFronzen.getFrozenCount() != 0) { - beforeFrozenBalance = beforeFronzen.getFrozen(0).getFrozenBalance(); - //beforeBandwidth = beforeFronzen.getBandwidth(); - //logger.info(Long.toString(beforeFronzen.getBandwidth())); - logger.info(Long.toString(beforeFronzen.getFrozen(0).getFrozenBalance())); - } - - FreezeBalanceContract.Builder builder = FreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration); - - FreezeBalanceContract contract = builder.build(); - - Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - return false; - } - - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Block searchCurrentBlock = searchBlockingStubFull.getNowBlock(GrpcAPI - .EmptyMessage.newBuilder().build()); - Integer wait = 0; - while (searchCurrentBlock.getBlockHeader().getRawData().getNumber() - < currentBlock.getBlockHeader().getRawData().getNumber() + 1 && wait < 30) { - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - logger.info("Another fullnode didn't syn the first fullnode data"); - searchCurrentBlock = searchBlockingStubFull.getNowBlock(GrpcAPI - .EmptyMessage.newBuilder().build()); - wait++; - if (wait == 9) { - logger.info("Didn't syn,skip to next case."); - } - } - - Account afterFronzen = queryAccount(ecKey, searchBlockingStubFull); - Long afterFrozenBalance = afterFronzen.getFrozen(0).getFrozenBalance(); - //Long afterBandwidth = afterFronzen.getBandwidth(); - //logger.info(Long.toString(afterFronzen.getBandwidth())); - //logger.info(Long.toString(afterFronzen.getFrozen(0).getFrozenBalance())); - //logger.info(Integer.toString(search.getFrozenCount())); - logger.info( - "afterfrozenbalance =" + Long.toString(afterFrozenBalance) + "beforefrozenbalance = " - + beforeFrozenBalance + "freezebalance = " + Long.toString(freezeBalance)); - //logger.info("afterbandwidth = " + Long.toString(afterBandwidth) + " beforebandwidth = - // " + Long.toString(beforeBandwidth)); - //if ((afterFrozenBalance - beforeFrozenBalance != freezeBalance) || - // (freezeBalance * frozen_duration -(afterBandwidth - beforeBandwidth) !=0)){ - // logger.info("After 20 second, two node still not synchronous"); - // } - Assert.assertTrue(afterFrozenBalance - beforeFrozenBalance == freezeBalance); - //Assert.assertTrue(freezeBalance * frozen_duration - (afterBandwidth - - // beforeBandwidth) <= 1000000); - return true; - - - } - - /** - * constructor. - */ - - public boolean unFreezeBalance(byte[] addRess, String priKey) { - byte[] address = addRess; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account search = queryAccount(ecKey, blockingStubFull); - - UnfreezeBalanceContract.Builder builder = UnfreezeBalanceContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess); - - UnfreezeBalanceContract contract = builder.build(); - - Transaction transaction = blockingStubFull.unfreezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/Creatasset.java b/framework/src/test/java/stest/tron/wallet/fulltest/Creatasset.java deleted file mode 100644 index a6fe9beee3d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/fulltest/Creatasset.java +++ /dev/null @@ -1,189 +0,0 @@ -package stest.tron.wallet.fulltest; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class Creatasset { - - private static final String tooLongDescription = - "1qazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqa" - + "zxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvq" - + "azxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcxswedcv"; - private static final String tooLongUrl = - "qaswqaswqaswqaswqaswqaswqaswqaswqaswqaswqaswqaswqaswqasw1qazxswedcvqazxswedcv" - + "qazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedc" - + "vqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqaz" - + "xswedcvqazxswedcvqazxswedcwedcv"; - private static final long now = System.currentTimeMillis(); - private static final long sendAmount = 1025000000L; - private static final long netCostMeasure = 200L; - private static String name = "c_" + Long.toString(now); - //testng001、testng002、testng003、testng004 - private final String testKey002 = - "FC8BF0238748587B9617EB6D15D47A66C0E07C1A1959033CF249C6532DC29FE6"; - private final String testKey003 = - "6815B367FDDE637E53E9ADC8E69424E07724333C9A2B973CFA469975E20753FC"; - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - long totalSupply = now; - Long freeAssetNetLimit = 30000L; - Long publicFreeAssetNetLimit = 30000L; - String description = "f"; - String url = "h"; - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] asset016Address = ecKey1.getAddress(); - String testKeyForAssetIssue016 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] transferAssetAddress = ecKey2.getAddress(); - String transferAssetCreateKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - logger.info(testKeyForAssetIssue016); - logger.info(transferAssetCreateKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - //@Test(enabled = false) - @Test(enabled = false, threadPoolSize = 20, invocationCount = 20) - public void createAssetissue() throws InterruptedException { - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] asset016Address = ecKey1.getAddress(); - String testKeyForAssetIssue016 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Account fromAccountInfo = PublicMethed.queryAccount(testKey002, blockingStubFull); - //Assert.assertTrue(PublicMethed.freezeBalance(fromAddress,100000000, 3, testKey002, - // blockingStubFull)); - - Integer i = 0; - //GrpcAPI.AssetIssueList assetIssueList = blockingStubFull - // .getAssetIssueList(GrpcAPI.EmptyMessage.newBuilder().build()); - //logger.info(Integer.toString(assetIssueList.getAssetIssueCount())); - Boolean ret = false; - Boolean transRet = false; - Boolean updateRet = false; - Boolean participateRet = false; - Random rand = new Random(); - Integer randNum; - - while (fromAccountInfo.getBalance() > 1025000000) { - randNum = rand.nextInt(4); - ManagedChannel channelFull = null; - WalletGrpc.WalletBlockingStub blockingStubFull = null; - fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(randNum); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed - .sendcoin(asset016Address, sendAmount, fromAddress, testKey002, blockingStubFull); - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - name = "c_" + Long.toString(System.currentTimeMillis()); - totalSupply = now; - - ret = PublicMethed - .createAssetIssue(asset016Address, name, totalSupply, 1, 1, start, end, 1, description, - url, freeAssetNetLimit, publicFreeAssetNetLimit, 1L, 1L, testKeyForAssetIssue016, - blockingStubFull); - - if (ret) { - updateRet = PublicMethed - .updateAsset(asset016Address, tooLongDescription.getBytes(), tooLongUrl.getBytes(), - 4000L, 4000L, - testKeyForAssetIssue016, blockingStubFull); - if (updateRet) { - logger.info("update succesfully"); - } - logger.info(Integer.toString(i++)); - //assetIssueList = blockingStubFull - // .getAssetIssueList(GrpcAPI.EmptyMessage.newBuilder().build()); - //logger.info("assetissue num is " + Integer.toString(assetIssueList.getAssetIssueCount())); - try { - randNum = rand.nextInt(10000) + 3000; - Thread.sleep(randNum); - } catch (InterruptedException e) { - e.printStackTrace(); - } - transRet = PublicMethed.transferAsset(toAddress, name.getBytes(), - 1L, asset016Address, testKeyForAssetIssue016, blockingStubFull); - participateRet = PublicMethed - .participateAssetIssue(asset016Address, name.getBytes(), 1L, toAddress, testKey003, - blockingStubFull); - if (participateRet) { - logger.info("participate success"); - } - logger.info(testKeyForAssetIssue016); - if (transRet) { - logger.info("transfer success"); - } - - } - ecKey1 = new ECKey(Utils.getRandom()); - asset016Address = ecKey1.getAddress(); - testKeyForAssetIssue016 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - fromAccountInfo = PublicMethed.queryAccount(testKey002, blockingStubFull); - ret = false; - updateRet = false; - participateRet = false; - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - try { - //randNum = rand.nextInt(10000) + 3000; - Thread.sleep(6000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - } - - - } - } - - /** - * constructor. - */ - - @AfterClass(enabled = false) - public void shutdown() throws InterruptedException { - /* if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - }*/ - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/CreateAddressAndKey.java b/framework/src/test/java/stest/tron/wallet/fulltest/CreateAddressAndKey.java deleted file mode 100644 index 87b662dc8ce..00000000000 --- a/framework/src/test/java/stest/tron/wallet/fulltest/CreateAddressAndKey.java +++ /dev/null @@ -1,234 +0,0 @@ -package stest.tron.wallet.fulltest; - -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.HashMap; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Base64; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class CreateAddressAndKey { - - private static String path = "/Users/wangzihe/Documents/"; - private static String filename = "/Users/wangzihe/Sites/postmanUsedKeyandAddress"; - private static String filenameTemp; - //testng001、testng002、testng003、testng004 - private final String testKey002 = - "FC8BF0238748587B9617EB6D15D47A66C0E07C1A1959033CF249C6532DC29FE6"; - private final String testKey003 = - "6815B367FDDE637E53E9ADC8E69424E07724333C9A2B973CFA469975E20753FC"; - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - - /** - * constructor. - */ - public static boolean createFile(String fileName, String filecontent) { - Boolean bool = false; - filenameTemp = fileName;//文件路径+名称+文件类型 - File file = new File(filenameTemp); - try { - //如果文件不存在,则创建新的文件 - if (!file.exists()) { - file.createNewFile(); - bool = true; - System.out.println("success create file,the file is " + filenameTemp); - //创建文件成功后,写入内容到文件里 - writeFileContent(filenameTemp, filecontent); - } else { - clearInfoForFile(filenameTemp); - writeFileContent(filenameTemp, filecontent); - - } - } catch (Exception e) { - e.printStackTrace(); - - } - - return bool; - } - - /** - * constructor. - */ - public static void clearInfoForFile(String fileName) { - File file = new File(fileName); - try { - if (!file.exists()) { - file.createNewFile(); - } - FileWriter fileWriter = new FileWriter(file); - fileWriter.write(""); - fileWriter.flush(); - fileWriter.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * constructor. - */ - public static boolean writeFileContent(String filepath, String newstr) throws IOException { - Boolean bool = false; - String filein = newstr + "\r\n"; - String temp = ""; - - FileInputStream fis = null; - InputStreamReader isr = null; - BufferedReader br = null; - FileOutputStream fos = null; - PrintWriter pw = null; - try { - File file = new File(filepath); - fis = new FileInputStream(file); - isr = new InputStreamReader(fis); - br = new BufferedReader(isr); - StringBuffer buffer = new StringBuffer(); - - for (int i = 0; (temp = br.readLine()) != null; i++) { - buffer.append(temp); - buffer = buffer.append(System.getProperty("line.separator")); - } - buffer.append(filein); - - fos = new FileOutputStream(file); - pw = new PrintWriter(fos); - pw.write(buffer.toString().toCharArray()); - pw.flush(); - bool = true; - } catch (Exception e) { - // TODO: handle exception - e.printStackTrace(); - } finally { - if (pw != null) { - pw.close(); - } - if (fos != null) { - fos.close(); - } - if (br != null) { - br.close(); - } - if (isr != null) { - isr.close(); - } - if (fis != null) { - fis.close(); - } - } - return bool; - } - - /** - * constructor. - */ - - public static boolean delFile(String fileName) { - Boolean bool = false; - filenameTemp = path + fileName + ".txt"; - File file = new File(filenameTemp); - try { - if (file.exists()) { - file.delete(); - bool = true; - } - } catch (Exception e) { - // TODO: handle exception - } - return bool; - } - - - - /** - * constructor. - */ - @BeforeClass(enabled = false) - public void beforeClass() { - - } - - @Test(enabled = false) - public void createAddressesAndKeys() { - Integer i = 0; - String accountIndex; - String keyIndex; - JsonObject jsonobject = new JsonObject(); - JsonArray jsonarray = new JsonArray(); - HashMap addressAndKey = new HashMap(); - while (i++ < 600) { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] address = ecKey1.getAddress(); - String addressString = ByteArray.toHexString(address); - byte[] key = ecKey1.getPrivKeyBytes(); - final String keyString = ByteArray.toHexString(key); - - logger.info(ByteArray.toStr(Base64.encode(key))); - logger.info(ByteArray.toStr(Base64.encode(address))); - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("address", addressString); - userBaseObj2.addProperty("key", keyString); - //userBaseObj2.addProperty("address",ByteArray.toStr(Base64.encode(address))); - //userBaseObj2.addProperty("key", ByteArray.toStr(Base64.encode(key))); - jsonarray.add(userBaseObj2); - } - Gson gson = new Gson(); - String jsonMap = gson.toJson(addressAndKey); - //createFile(filename,jsonobject.toString()); - createFile(filename, jsonarray.toString()); - - } - - @Test(enabled = true) - public void create() { - Integer i = 0; - String accountIndex; - String keyIndex; - JsonObject jsonobject = new JsonObject(); - JsonArray jsonarray = new JsonArray(); - HashMap addressAndKey = new HashMap(); - while (i++ < 600) { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] address = ecKey1.getAddress(); - String key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ArrayList accountList = new ArrayList(); - accountList = PublicMethed.getAddressInfo(key); - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("address", accountList.get(1)); - userBaseObj2.addProperty("key", accountList.get(0)); - jsonarray.add(userBaseObj2); - } - Gson gson = new Gson(); - String jsonMap = gson.toJson(addressAndKey); - //createFile(filename,jsonobject.toString()); - createFile(filename, jsonarray.toString()); - - } - - @AfterClass(enabled = false) - public void shutdown() throws InterruptedException { - } -} - diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/FreezeAndSendcoin.java b/framework/src/test/java/stest/tron/wallet/fulltest/FreezeAndSendcoin.java deleted file mode 100644 index 203127fb3b4..00000000000 --- a/framework/src/test/java/stest/tron/wallet/fulltest/FreezeAndSendcoin.java +++ /dev/null @@ -1,321 +0,0 @@ -package stest.tron.wallet.fulltest; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.BalanceContract; -import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class FreezeAndSendcoin { - - private static final long now = System.currentTimeMillis(); - //testng001、testng002、testng003、testng004 - private final String testKey002 = - "FC8BF0238748587B9617EB6D15D47A66C0E07C1A1959033CF249C6532DC29FE6"; - private final String testKey003 = - "6815B367FDDE637E53E9ADC8E69424E07724333C9A2B973CFA469975E20753FC"; - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - private final Long sendAmount = 10000000L; - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] freezeAddress = ecKey1.getAddress(); - String testKeyForFreeze = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] transferAssetAddress = ecKey2.getAddress(); - String transferAssetCreateKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - /** - * constructor. - */ - - public static Boolean freezeBalance(byte[] addRess, long freezeBalance, long freezeDuration, - String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - Protocol.Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI - .EmptyMessage.newBuilder().build()); - final Long beforeBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Long beforeFrozenBalance = 0L; - //Long beforeBandwidth = beforeFronzen.getBandwidth(); - - BalanceContract.FreezeBalanceContract.Builder builder = BalanceContract.FreezeBalanceContract - .newBuilder(); - ByteString byteAddress = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddress).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration); - - BalanceContract.FreezeBalanceContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction = null"); - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } - - Long afterBlockNum = 0L; - - while (afterBlockNum < beforeBlockNum) { - Protocol.Block currentBlock1 = blockingStubFull.getNowBlock(GrpcAPI - .EmptyMessage.newBuilder().build()); - afterBlockNum = currentBlock1.getBlockHeader().getRawData().getNumber(); - } - return true; - } - - - - //@Test(enabled = false) - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - /* Random rand = new Random(); - Integer randNum = rand.nextInt(30) + 1; - randNum = rand.nextInt(4); - try { - randNum = rand.nextInt(20000); - Thread.sleep(randNum); - } catch (InterruptedException e) { - e.printStackTrace(); - }*/ - - logger.info(testKeyForFreeze); - logger.info(transferAssetCreateKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = false, threadPoolSize = 500, invocationCount = 1000) - public void freezeAndSendcoin() throws InterruptedException { - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] freezeAddress = ecKey1.getAddress(); - String testKeyForFreeze = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Account toAccountInfo = PublicMethed.queryAccount(testKey003, blockingStubFull); - Account freezeAccountInfo = PublicMethed.queryAccount(testKeyForFreeze, blockingStubFull); - - Integer i = 0; - Boolean ret = false; - Boolean sendRet = false; - Boolean updateRet = false; - Boolean participateRet = false; - Random rand = new Random(); - Integer randNum = rand.nextInt(30) + 1; - - while (toAccountInfo.getBalance() > 10000009L) { - randNum = rand.nextInt(3); - ManagedChannel channelFull = null; - WalletGrpc.WalletBlockingStub blockingStubFull = null; - fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(randNum); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - freezeBalance(freezeAddress, 3000000L, 3L, testKeyForFreeze, blockingStubFull); - PublicMethed - .sendcoin(freezeAddress, sendAmount, toAddress, testKey003, blockingStubFull); - - ret = freezeBalance(freezeAddress, 1000000L, 3L, testKeyForFreeze, blockingStubFull); - freezeBalance(freezeAddress, 1000000L, 3L, testKeyForFreeze, blockingStubFull); - freezeBalance(freezeAddress, 1000000L, 3L, testKeyForFreeze, blockingStubFull); - - if (ret) { - logger.info("New account freeze success " + Integer.toString(i)); - sendRet = PublicMethed.sendcoin(toAddress, 6000000L, freezeAddress, - testKeyForFreeze, blockingStubFull); - if (sendRet) { - logger.info("This account transfer coin back. " + Integer.toString(i)); - freezeAccountInfo = PublicMethed.queryAccount(testKeyForFreeze, blockingStubFull); - logger.info("This account now has balance is " + Long - .toString(freezeAccountInfo.getBalance())); - - } - - } - - unFreezeBalance(freezeAddress, testKeyForFreeze); - withdrawBalance(freezeAddress, testKeyForFreeze); - - ecKey1 = new ECKey(Utils.getRandom()); - freezeAddress = ecKey1.getAddress(); - testKeyForFreeze = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - toAccountInfo = PublicMethed.queryAccount(testKey003, blockingStubFull); - logger.info("Now the toaddress balance is " + Long.toString(toAccountInfo.getBalance())); - NumberMessage beforeGetTotalTransaction = blockingStubFull - .totalTransaction(GrpcAPI.EmptyMessage.newBuilder().build()); - logger.info("Now total transaction is " + Long.toString(beforeGetTotalTransaction.getNum())); - ret = false; - sendRet = false; - i++; - - /* if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - try { - //randNum = rand.nextInt(10000) + 3000; - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - }*/ - - } - } - - /** - * constructor. - */ - - @AfterClass(enabled = false) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public boolean unFreezeBalance(byte[] addRess, String priKey) { - byte[] address = addRess; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - // Account search = queryAccount(ecKey, blockingStubFull); - - UnfreezeBalanceContract.Builder builder = UnfreezeBalanceContract - .newBuilder(); - ByteString byteAddress = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddress); - - UnfreezeBalanceContract contract = builder.build(); - - Transaction transaction = blockingStubFull.unfreezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public boolean withdrawBalance(byte[] address, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - BalanceContract.WithdrawBalanceContract.Builder builder = - BalanceContract.WithdrawBalanceContract - .newBuilder(); - ByteString byteAddress = ByteString.copyFrom(address); - builder.setOwnerAddress(byteAddress); - BalanceContract.WithdrawBalanceContract contract = builder.build(); - - Transaction transaction = blockingStubFull.withdrawBalance(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return false; - } - logger.info("test withdraw" + priKey); - return true; - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/Fuzzytest.java b/framework/src/test/java/stest/tron/wallet/fulltest/Fuzzytest.java deleted file mode 100644 index 3179f5973ae..00000000000 --- a/framework/src/test/java/stest/tron/wallet/fulltest/Fuzzytest.java +++ /dev/null @@ -1,223 +0,0 @@ -package stest.tron.wallet.fulltest; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AssetIssueList; -import org.tron.api.WalletExtensionGrpc; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.db.Manager; -import org.tron.protos.Protocol; -import org.tron.protos.contract.AssetIssueContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class Fuzzytest { - - private static final long sendAmount = 10000000000L; - private static final long netCostMeasure = 200L; - private static long start; - private static long end; - private static long now = System.currentTimeMillis(); - private static String name = "AssetIssue016_" + Long.toString(now); - private static long totalSupply = now; - //testng001、testng002、testng003、testng004 - private final String testKey002 = - "FC8BF0238748587B9617EB6D15D47A66C0E07C1A1959033CF249C6532DC29FE6"; - private final String testKey003 = - "6815B367FDDE637E53E9ADC8E69424E07724333C9A2B973CFA469975E20753FC"; - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - Long freeAssetNetLimit = 30000L; - Long publicFreeAssetNetLimit = 30000L; - String description = "for case assetissue016"; - String url = "https://stest.assetissue016.url/"; - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] asset017Address = ecKey1.getAddress(); - String testKeyForAssetIssue017 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Manager dbManager; - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletExtensionGrpc.WalletExtensionBlockingStub blockingStubExtension = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - /** - * constructor. - */ - - public static Boolean createAssetIssue(byte[] address, String name, Long totalSupply, - Integer trxNum, Integer icoNum, Long startTime, Long endTime, Integer voteScore, - String description, String url, Long freeAssetNetLimit, Long publicFreeAssetNetLimit, - Long fronzenAmount, Long frozenDay, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - //Protocol.Account search = queryAccount(ecKey, blockingStubFull); - try { - AssetIssueContractOuterClass.AssetIssueContract.Builder builder = - AssetIssueContractOuterClass.AssetIssueContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - builder.setFreeAssetNetLimit(freeAssetNetLimit); - builder.setPublicFreeAssetNetLimit(publicFreeAssetNetLimit); - AssetIssueContractOuterClass.AssetIssueContract.FrozenSupply.Builder frozenBuilder = - AssetIssueContractOuterClass.AssetIssueContract.FrozenSupply.newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - builder.addFrozenSupply(0, frozenBuilder); - - Protocol.Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info("failed reason is " + ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - return true; - } - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - /** - * constructor. - */ - - public static Protocol.Transaction signTransaction(ECKey ecKey, - Protocol.Transaction transaction) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - if (ecKey == null || ecKey.getPrivKey() == null) { - //logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - blockingStubExtension = WalletExtensionGrpc.newBlockingStub(channelSolidity); - - AssetIssueList assetIssueList = blockingStubFull - .getAssetIssueList(GrpcAPI.EmptyMessage.newBuilder().build()); - Assert.assertTrue(PublicMethed.freezeBalance(fromAddress, 10000000, 3, testKey002, - blockingStubFull)); - while (assetIssueList.getAssetIssueCount() <= 1) { - //Sendcoin to this account - Assert.assertTrue(PublicMethed - .sendcoin(asset017Address, sendAmount, fromAddress, testKey002, blockingStubFull)); - start = System.currentTimeMillis() + 2000; - end = System.currentTimeMillis() + 1000000000; - now = System.currentTimeMillis(); - name = "AssetIssue017_" + Long.toString(now); - totalSupply = now; - Assert.assertTrue(createAssetIssue(asset017Address, name, totalSupply, 1, 1, - start, end, 1, description, url, freeAssetNetLimit, publicFreeAssetNetLimit, 1L, - 1L, testKeyForAssetIssue017, blockingStubFull)); - - assetIssueList = blockingStubFull - .getAssetIssueList(GrpcAPI.EmptyMessage.newBuilder().build()); - - ecKey1 = new ECKey(Utils.getRandom()); - asset017Address = ecKey1.getAddress(); - testKeyForAssetIssue017 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - } - } - - @Test(enabled = false, threadPoolSize = 5, invocationCount = 5) - public void tooManyChannelFull() { - Integer i = 0; - while (i++ < 20000) { - ManagedChannel channelFull = null; - WalletGrpc.WalletBlockingStub blockingStubFull = null; - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - GrpcAPI.NodeList nodeList = blockingStubFull - .listNodes(GrpcAPI.EmptyMessage.newBuilder().build()); - if (i % 100 == 0) { - logger.info(Integer.toString(i)); - } - - } - - - } - - /** - * constructor. - */ - - @AfterClass(enabled = false) - public void shutdown() throws InterruptedException { - /* if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - }*/ - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/ParticipateAssetIssue.java b/framework/src/test/java/stest/tron/wallet/fulltest/ParticipateAssetIssue.java deleted file mode 100644 index 53642957ea7..00000000000 --- a/framework/src/test/java/stest/tron/wallet/fulltest/ParticipateAssetIssue.java +++ /dev/null @@ -1,341 +0,0 @@ -package stest.tron.wallet.fulltest; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.contract.AssetIssueContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class ParticipateAssetIssue { - - private static final long now = System.currentTimeMillis(); - private static final long sendAmount = 10250000000L; - private static String name = "PartAssetIssue_" + Long.toString(now); - private static long beforeCreateAssetIssueBalance; - private static long afterCreateAssetIssueBalance; - private static long afterParticipateAssetIssueBalance; - private static long start1; - private static long end1; - //testng001、testng002、testng003、testng004 - private final String testKey002 = - "FC8BF0238748587B9617EB6D15D47A66C0E07C1A1959033CF249C6532DC29FE6"; - private final String testKey003 = - "6815B367FDDE637E53E9ADC8E69424E07724333C9A2B973CFA469975E20753FC"; - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - long totalSupply = now; - Long freeAssetNetLimit = 300000000L; - Long publicFreeAssetNetLimit = 300000000L; - String description = "f"; - String url = "h"; - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] createAddress = ecKey1.getAddress(); - String testKeyForCreate = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] participateAssetAddress = ecKey2.getAddress(); - String testKeyForParticipate = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - /** - * constructor. - */ - - public static boolean participateAssetIssue(byte[] to, byte[] assertName, long amount, - byte[] from, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - AssetIssueContractOuterClass.ParticipateAssetIssueContract.Builder builder = - AssetIssueContractOuterClass.ParticipateAssetIssueContract - .newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(from); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - AssetIssueContractOuterClass.ParticipateAssetIssueContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.participateAssetIssue(contract); - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public static Protocol.Transaction signTransaction(ECKey ecKey, - Protocol.Transaction transaction) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - if (ecKey == null || ecKey.getPrivKey() == null) { - //logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - - public static boolean transferAsset(byte[] to, byte[] assertName, long amount, byte[] address, - String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - AssetIssueContractOuterClass.TransferAssetContract.Builder builder = - AssetIssueContractOuterClass.TransferAssetContract - .newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - AssetIssueContractOuterClass.TransferAssetContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.transferAsset(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - if (transaction == null) { - //logger.info("transaction == null"); - } else { - //logger.info("transaction.getRawData().getContractCount() == 0"); - } - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - //logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - //Protocol.Account search = queryAccount(ecKey, blockingStubFull); - return true; - } - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - logger.info(testKeyForCreate); - logger.info(testKeyForParticipate); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - //Send coin to 2 account. - Assert.assertTrue(PublicMethed.sendcoin(createAddress, sendAmount, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(participateAssetAddress, sendAmount, - fromAddress, testKey002, blockingStubFull)); - //Participate account freeze balance to get bandwidth. - Assert.assertTrue(PublicMethed.freezeBalance(participateAssetAddress, - 10000000L, 3, testKeyForParticipate, blockingStubFull)); - //Create an asset issue. - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed.createAssetIssue(createAddress, name, totalSupply, 1, 1, - start, end, 1, description, url, freeAssetNetLimit, publicFreeAssetNetLimit, - 10L, 10L, testKeyForCreate, blockingStubFull)); - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - final Account createInfo = PublicMethed.queryAccount(testKeyForCreate, blockingStubFull); - final Account participateInfo = PublicMethed.queryAccount(testKeyForParticipate, - blockingStubFull); - - Map assetIssueMap = new HashMap(); - - Long temp = 0L; - assetIssueMap = createInfo.getAssetMap(); - for (String key : assetIssueMap.keySet()) { - - logger.info("Name is " + key); - } - for (Long key : assetIssueMap.values()) { - logger.info("Balance are " + Long.toString(key)); - temp = key; - } - beforeCreateAssetIssueBalance = temp; - start1 = System.currentTimeMillis(); - } - - //@Test(enabled = false) - @Test(enabled = false, threadPoolSize = 250, invocationCount = 250) - public void testParticipateAssetIssue() throws InterruptedException { - Integer i = 0; - Integer randNum; - - while (i < 20) { - randNum = i % 4; - i++; - fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(randNum); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - participateAssetIssue(createAddress, name.getBytes(), - 1, participateAssetAddress, testKeyForParticipate, blockingStubFull); - } - } - - /** - * constructor. - */ - - @AfterClass(enabled = false) - public void shutdown() throws InterruptedException { - //Print the duration. - end1 = System.currentTimeMillis(); - logger.info("The time is " + Long.toString(end1 - start1)); - - Account createInfo = PublicMethed.queryAccount(testKeyForCreate, blockingStubFull); - - Map createAssetIssueMap = new HashMap(); - - Long temp = 0L; - createAssetIssueMap = createInfo.getAssetMap(); - for (String key : createAssetIssueMap.keySet()) { - - logger.info("Name is " + key); - } - for (Long key : createAssetIssueMap.values()) { - logger.info("Balance are " + Long.toString(key)); - temp = key; - } - afterCreateAssetIssueBalance = temp; - - temp = 0L; - Account participateInfo = PublicMethed.queryAccount(testKeyForParticipate, blockingStubFull); - Map participateAssetIssueMap = new HashMap(); - participateAssetIssueMap = participateInfo.getAssetMap(); - for (Long key : participateAssetIssueMap.values()) { - logger.info("Balance are " + Long.toString(key)); - temp = key; - } - afterParticipateAssetIssueBalance = temp; - - logger.info("Create account has balance " + Long.toString(beforeCreateAssetIssueBalance) - + " at the beginning"); - logger.info("Create account has balance " + Long.toString(afterCreateAssetIssueBalance) - + " at the end"); - logger.info("Create account reduce balance " + Long.toString(beforeCreateAssetIssueBalance - - afterCreateAssetIssueBalance)); - logger.info("Participate account total success transaction is " - + Long.toString(afterParticipateAssetIssueBalance)); - - Integer blockTimes = 0; - Integer blockTransParticipateNum = 0; - - while (blockTimes < 5) { - blockTimes++; - //Print the current block transaction num. - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentNum = currentBlock.getBlockHeader().getRawData().getNumber(); - logger.info("The block num " + Long.toString(currentNum) - + " total transaction is " + Long.toString(currentBlock.getTransactionsCount())); - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - createInfo = PublicMethed.queryAccount(testKeyForCreate, blockingStubFull); - participateInfo = PublicMethed.queryAccount(testKeyForParticipate, blockingStubFull); - createAssetIssueMap = new HashMap(); - participateAssetIssueMap = new HashMap(); - - temp = 0L; - createAssetIssueMap = createInfo.getAssetMap(); - for (String key : createAssetIssueMap.keySet()) { - - logger.info("Name is " + key); - } - for (Long key : createAssetIssueMap.values()) { - logger.info("Balance are " + Long.toString(key)); - temp = key; - } - afterCreateAssetIssueBalance = temp; - - temp = 0L; - participateAssetIssueMap = participateInfo.getAssetMap(); - for (Long key : participateAssetIssueMap.values()) { - logger.info("Balance are " + Long.toString(key)); - temp = key; - } - afterParticipateAssetIssueBalance = temp; - - logger.info("Create account has balance " + Long.toString(beforeCreateAssetIssueBalance) - + "at the beginning"); - logger.info("Create account has balance " + Long.toString(afterCreateAssetIssueBalance) - + "at the end"); - logger.info("Participate account total success transaction is " - + Long.toString(afterParticipateAssetIssueBalance)); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/SuperWitnessAllowance.java b/framework/src/test/java/stest/tron/wallet/fulltest/SuperWitnessAllowance.java deleted file mode 100644 index 7bcf1458376..00000000000 --- a/framework/src/test/java/stest/tron/wallet/fulltest/SuperWitnessAllowance.java +++ /dev/null @@ -1,398 +0,0 @@ -package stest.tron.wallet.fulltest; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.GrpcAPI.WitnessList; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.BalanceContract; -import org.tron.protos.contract.WitnessContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -//import stest.tron.wallet.common.client.AccountComparator; - -@Slf4j -public class SuperWitnessAllowance { - - /* //testng001、testng002、testng003、testng004 - private static final byte[] fromAddress = Base58 - .decodeFromBase58Check("THph9K2M2nLvkianrMGswRhz5hjSA9fuH7");*/ - private static final byte[] INVAILD_ADDRESS = Base58 - .decodeFromBase58Check("27cu1ozb4mX3m2afY68FSAqn3HmMp815d48"); - private static final Long costForCreateWitness = 10009000000L; - //testng001、testng002、testng003、testng004 - private final String testKey002 = - "FC8BF0238748587B9617EB6D15D47A66C0E07C1A1959033CF249C6532DC29FE6"; - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String createWitnessUrl = "http://www.createwitnessurl.com/"; - String updateWitnessUrl = "http://www.updatewitnessurl.com/"; - String nullUrl = ""; - String spaceUrl = " ##################~!@#$%^&*()_+}{|:'/.,<>?|]=-"; - byte[] createUrl = createWitnessUrl.getBytes(); - byte[] updateUrl = updateWitnessUrl.getBytes(); - byte[] wrongUrl = nullUrl.getBytes(); - byte[] updateSpaceUrl = spaceUrl.getBytes(); - //get account - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] lowBalAddress = ecKey.getAddress(); - String lowBalTest = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - logger.info(lowBalTest); - logger.info(ByteArray.toHexString(PublicMethed.getFinalAddress(lowBalTest))); - logger.info(Base58.encode58Check(PublicMethed.getFinalAddress(lowBalTest))); - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test - public void testInvaildToApplyBecomeWitness() { - Assert.assertFalse(createWitness(INVAILD_ADDRESS, createUrl, testKey002)); - } - - //@Test(enabled = true,threadPoolSize = 10, invocationCount = 10) - @Test(enabled = false) - public void testCreate130Witness() { - WitnessList witnesslist = blockingStubFull - .listWitnesses(GrpcAPI.EmptyMessage.newBuilder().build()); - Optional result = Optional.ofNullable(witnesslist); - WitnessList witnessList = result.get(); - while (witnessList.getWitnessesCount() < 130) { - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] lowBalAddress = ecKey.getAddress(); - String lowBalTest = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - logger.info(lowBalTest); - Assert.assertTrue(sendcoin(lowBalAddress, costForCreateWitness, fromAddress, testKey002)); - Assert.assertTrue(PublicMethed.freezeBalance(lowBalAddress, 1000000, - 3, lowBalTest, blockingStubFull)); - Assert.assertTrue(createWitness(lowBalAddress, createUrl, lowBalTest)); - String voteStr = Base58.encode58Check(PublicMethed.getFinalAddress(lowBalTest)); - HashMap smallVoteMap = new HashMap(); - smallVoteMap.put(voteStr, "1"); - Assert.assertTrue(voteWitness(smallVoteMap, lowBalAddress, lowBalTest)); - witnesslist = blockingStubFull - .listWitnesses(GrpcAPI.EmptyMessage.newBuilder().build()); - result = Optional.ofNullable(witnesslist); - witnessList = result.get(); - - } - - } - - //@Test(enabled = true,threadPoolSize = 10, invocationCount = 10) - @Test(enabled = false) - public void testQueryAllowance() { - WitnessList witnesslist = blockingStubFull - .listWitnesses(GrpcAPI.EmptyMessage.newBuilder().build()); - Optional result = Optional.ofNullable(witnesslist); - WitnessList witnessList = result.get(); - Integer allowanceNum = 0; - for (Integer i = 0; i < witnessList.getWitnessesCount(); i++) { - /* witnessList.getWitnesses(i).getAddress(); - witnessList.getWitnesses(i).getAddress(); - witnessList.getWitnesses(i).getAddress(); - witnessList.getWitnesses(i).getAddress();*/ - ByteString addressBs = witnessList.getWitnesses(i).getAddress(); - Account request = Account.newBuilder().setAddress(addressBs).build(); - request = blockingStubFull.getAccount(request); - if (request.getAllowance() > 0) { - allowanceNum++; - } - logger.info("Account " + Integer.toString(i) + " allowance is " + Long.toString(request - .getAllowance())); - - } - logger.info("Allowance num is " + Integer.toString(allowanceNum)); - - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - - public Boolean createWitness(byte[] owner, byte[] url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - WitnessContract.WitnessCreateContract.Builder builder = WitnessContract.WitnessCreateContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setUrl(ByteString.copyFrom(url)); - WitnessContract.WitnessCreateContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createWitness(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - return response.getResult(); - - } - - /** - * constructor. - */ - - public Boolean updateWitness(byte[] owner, byte[] url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - WitnessContract.WitnessUpdateContract.Builder builder = WitnessContract.WitnessUpdateContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setUpdateUrl(ByteString.copyFrom(url)); - WitnessContract.WitnessUpdateContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.updateWitness(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - logger.info("response.getRestult() == false"); - return false; - } else { - return true; - } - - } - - /** - * constructor. - */ - - public Boolean sendcoin(byte[] to, long amount, byte[] owner, String priKey) { - - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - BalanceContract.TransferContract.Builder builder = BalanceContract.TransferContract - .newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - BalanceContract.TransferContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createTransaction(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public Account queryAccount(String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Protocol.Transaction signTransaction(ECKey ecKey, Protocol.Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - - public Boolean voteWitness(HashMap witness, byte[] addRess, String priKey) { - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - Account beforeVote = PublicMethed.queryAccount(priKey, blockingStubFull); - //Account beforeVote = queryAccount(ecKey, blockingStubFull); - Long beforeVoteNum = 0L; - if (beforeVote.getVotesCount() != 0) { - beforeVoteNum = beforeVote.getVotes(0).getVoteCount(); - } - - WitnessContract.VoteWitnessContract.Builder builder = WitnessContract.VoteWitnessContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(addRess)); - for (String addressBase58 : witness.keySet()) { - String value = witness.get(addressBase58); - final long count = Long.parseLong(value); - WitnessContract.VoteWitnessContract.Vote.Builder voteBuilder = - WitnessContract.VoteWitnessContract.Vote - .newBuilder(); - byte[] address = WalletClient.decodeFromBase58Check(addressBase58); - logger.info("address ====== " + ByteArray.toHexString(address)); - if (address == null) { - continue; - } - voteBuilder.setVoteAddress(ByteString.copyFrom(address)); - voteBuilder.setVoteCount(count); - builder.addVotes(voteBuilder.build()); - } - - WitnessContract.VoteWitnessContract contract = builder.build(); - - Transaction transaction = blockingStubFull.voteWitnessAccount(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - //Long afterVoteNum = afterVote.getVotes(0).getVoteCount(); - return true; - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/TransferAssetIssue.java b/framework/src/test/java/stest/tron/wallet/fulltest/TransferAssetIssue.java deleted file mode 100644 index 94a79770877..00000000000 --- a/framework/src/test/java/stest/tron/wallet/fulltest/TransferAssetIssue.java +++ /dev/null @@ -1,371 +0,0 @@ -package stest.tron.wallet.fulltest; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.BytesMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.AssetIssueContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.Sha256Hash; -import stest.tron.wallet.common.client.utils.TransactionUtils; - - -@Slf4j -public class TransferAssetIssue { - - private static final long now = System.currentTimeMillis(); - private static final long sendAmount = 10250000000L; - private static String name = "PartAssetIssue_" + Long.toString(now); - private static long beforeCreateAssetIssueBalance; - private static long afterCreateAssetIssueBalance; - private static long afterParticipateAssetIssueBalance; - private static long start1; - private static long end1; - //testng001、testng002、testng003、testng004 - private final String testKey002 = - "FC8BF0238748587B9617EB6D15D47A66C0E07C1A1959033CF249C6532DC29FE6"; - private final String testKey003 = - "6815B367FDDE637E53E9ADC8E69424E07724333C9A2B973CFA469975E20753FC"; - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - long totalSupply = now; - Long freeAssetNetLimit = 300000000L; - Long publicFreeAssetNetLimit = 300000000L; - String description = "f"; - String url = "h"; - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] createAddress = ecKey1.getAddress(); - String testKeyForCreate = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] participateAssetAddress = ecKey2.getAddress(); - String testKeyForParticipate = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - /** - * constructor. - */ - - - public static boolean participateAssetIssue(byte[] to, byte[] assertName, long amount, - byte[] from, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - AssetIssueContractOuterClass.ParticipateAssetIssueContract.Builder builder = - AssetIssueContractOuterClass.ParticipateAssetIssueContract - .newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(from); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - AssetIssueContractOuterClass.ParticipateAssetIssueContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.participateAssetIssue(contract); - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public static Protocol.Transaction signTransaction(ECKey ecKey, - Protocol.Transaction transaction) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - if (ecKey == null || ecKey.getPrivKey() == null) { - //logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - - public static boolean transferAsset(byte[] to, byte[] assertName, long amount, byte[] address, - String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - AssetIssueContractOuterClass.TransferAssetContract.Builder builder = - AssetIssueContractOuterClass.TransferAssetContract - .newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - AssetIssueContractOuterClass.TransferAssetContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.transferAsset(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - if (transaction == null) { - //logger.info("transaction == null"); - } else { - //logger.info("transaction.getRawData().getContractCount() == 0"); - } - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - //logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - //Protocol.Account search = queryAccount(ecKey, blockingStubFull); - return true; - } - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - logger.info(testKeyForCreate); - logger.info(testKeyForParticipate); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - //Send coin to 2 account. - Assert.assertTrue(PublicMethed.sendcoin(createAddress, sendAmount, - fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(participateAssetAddress, - sendAmount, fromAddress, testKey002, blockingStubFull)); - //Participate account freeze balance to get bandwidth. - Assert.assertTrue(PublicMethed.freezeBalance(participateAssetAddress, 10000000L, 3, - testKeyForParticipate, blockingStubFull)); - //Create an asset issue. - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed.createAssetIssue(createAddress, name, totalSupply, 1, 1, - start, end, 1, description, url, freeAssetNetLimit, publicFreeAssetNetLimit, - 10L, 10L, testKeyForCreate, blockingStubFull)); - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - final Account createInfo = PublicMethed.queryAccount(testKeyForCreate, blockingStubFull); - final Account participateInfo = PublicMethed.queryAccount(testKeyForParticipate, - blockingStubFull); - - Map assetIssueMap = new HashMap(); - - Long temp = 0L; - assetIssueMap = createInfo.getAssetMap(); - for (String key : assetIssueMap.keySet()) { - - logger.info("Name is " + key); - } - for (Long key : assetIssueMap.values()) { - logger.info("Balance are " + Long.toString(key)); - temp = key; - } - beforeCreateAssetIssueBalance = temp; - start1 = System.currentTimeMillis(); - } - - //@Test(enabled = false) - @Test(enabled = false, threadPoolSize = 200, invocationCount = 200) - public void transferAssetIssue() throws InterruptedException { - Integer i = 0; - Integer randNum; - - while (i < 20) { - randNum = i % 4; - i++; - fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(randNum); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - transferAsset(participateAssetAddress, name.getBytes(), 1, - createAddress, testKeyForCreate, blockingStubFull); - } - } - - /** - * constructor. - */ - - - @AfterClass(enabled = false) - public void shutdown() throws InterruptedException { - //Print the duration. - end1 = System.currentTimeMillis(); - logger.info("The time is " + Long.toString(end1 - start1)); - - Map createAssetIssueMap = new HashMap(); - - Long temp = 0L; - Account createInfo = PublicMethed.queryAccount(testKeyForCreate, blockingStubFull); - createAssetIssueMap = createInfo.getAssetMap(); - for (String key : createAssetIssueMap.keySet()) { - - logger.info("Name is " + key); - } - for (Long key : createAssetIssueMap.values()) { - logger.info("Balance are " + Long.toString(key)); - temp = key; - } - afterCreateAssetIssueBalance = temp; - - temp = 0L; - Account participateInfo = PublicMethed.queryAccount(testKeyForParticipate, blockingStubFull); - Map participateAssetIssueMap = new HashMap(); - participateAssetIssueMap = participateInfo.getAssetMap(); - for (Long key : participateAssetIssueMap.values()) { - logger.info("Balance are " + Long.toString(key)); - temp = key; - } - afterParticipateAssetIssueBalance = temp; - - logger.info("Create account has balance " + Long.toString(beforeCreateAssetIssueBalance) - + " at the beginning"); - logger.info("Create account has balance " + Long.toString(afterCreateAssetIssueBalance) - + " at the end"); - logger.info("Create account reduce balance " + Long.toString(beforeCreateAssetIssueBalance - - afterCreateAssetIssueBalance)); - logger.info("Transfer account total success transaction is " - + Long.toString(afterParticipateAssetIssueBalance)); - - Integer blockTimes = 0; - Integer blockTransParticipateNum = 0; - Integer useNet = 0; - Integer useFee = 0; - - while (blockTimes < 5) { - blockTimes++; - //Print the current block transaction num. - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentNum = currentBlock.getBlockHeader().getRawData().getNumber(); - for (Integer m = 0; m < currentBlock.getTransactionsCount(); m++) { - logger.info(currentBlock.getTransactions(m).getRetList().toString()); - String txId = ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), currentBlock.getTransactions(m) - .getRawData().toByteArray())); - ByteString bsTxid = ByteString.copyFrom(ByteArray.fromHexString(txId)); - BytesMessage request = BytesMessage.newBuilder().setValue(bsTxid).build(); - Transaction transaction = blockingStubFull.getTransactionById(request); - Optional getTransactionById = Optional.ofNullable(transaction); - if (getTransactionById.get().getRet(0).getFee() > 0) { - logger.info(Long.toString(getTransactionById.get().getRet(0).getFee())); - useFee++; - } else { - logger.info("No use fee"); - useNet++; - } - } - - logger.info("The block num " + Long.toString(currentNum) - + " total transaction is " + Long.toString(currentBlock.getTransactionsCount())); - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - logger.info("Use Net num is " + Integer.toString(useNet)); - logger.info("Use Fee num is " + Integer.toString(useFee)); - - createInfo = PublicMethed.queryAccount(testKeyForCreate, blockingStubFull); - participateInfo = PublicMethed.queryAccount(testKeyForParticipate, blockingStubFull); - createAssetIssueMap = new HashMap(); - participateAssetIssueMap = new HashMap(); - - temp = 0L; - createAssetIssueMap = createInfo.getAssetMap(); - for (String key : createAssetIssueMap.keySet()) { - - logger.info("Name is " + key); - } - for (Long key : createAssetIssueMap.values()) { - logger.info("Balance are " + Long.toString(key)); - temp = key; - } - afterCreateAssetIssueBalance = temp; - - temp = 0L; - participateAssetIssueMap = participateInfo.getAssetMap(); - for (Long key : participateAssetIssueMap.values()) { - logger.info("Balance are " + Long.toString(key)); - temp = key; - } - afterParticipateAssetIssueBalance = temp; - - logger.info("Create account has balance " + Long.toString(beforeCreateAssetIssueBalance) - + "at the beginning"); - logger.info("Create account has balance " + Long.toString(afterCreateAssetIssueBalance) - + "at the end"); - logger.info("Participate account total success transaction is " - + Long.toString(afterParticipateAssetIssueBalance)); - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/TronDice.java b/framework/src/test/java/stest/tron/wallet/fulltest/TronDice.java deleted file mode 100644 index 2a30633de27..00000000000 --- a/framework/src/test/java/stest/tron/wallet/fulltest/TronDice.java +++ /dev/null @@ -1,138 +0,0 @@ -package stest.tron.wallet.fulltest; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TronDice { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - byte[] contractAddress; - Long maxFeeLimit = 1000000000L; - Optional infoById = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contract008Address = ecKey1.getAddress(); - String contract008Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ArrayList txidList = new ArrayList(); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contract008Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - PublicMethed.printAddress(testKey002); - AccountResourceMessage accountResource = PublicMethed.getAccountResource(contract008Address, - blockingStubFull); - } - - @Test(enabled = true, threadPoolSize = 30, invocationCount = 30) - public void tronDice() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] tronDiceAddress = ecKey1.getAddress(); - String tronDiceKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed - .sendcoin(tronDiceAddress, 100000000000L, fromAddress, testKey002, blockingStubFull); - String contractName = "TronDice"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_TronDice_tronDice"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_TronDice_tronDice"); - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", - maxFeeLimit, 1000000000L, 100, null, tronDiceKey, tronDiceAddress, blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - Assert.assertTrue(smartContract.getAbi() != null); - - String txid; - - for (Integer i = 0; i < 100; i++) { - String initParmes = "\"" + "10" + "\""; - txid = PublicMethed.triggerContract(contractAddress, - "rollDice(uint256)", initParmes, false, - 1000000, maxFeeLimit, tronDiceAddress, tronDiceKey, blockingStubFull); - logger.info(txid); - txidList.add(txid); - - try { - Thread.sleep(200); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - } - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - try { - Thread.sleep(20000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - Integer successTimes = 0; - Integer failedTimes = 0; - Integer totalTimes = 0; - for (String txid1 : txidList) { - totalTimes++; - infoById = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); - if (infoById.get().getBlockNumber() > 3523732) { - logger.info("blocknum is " + infoById.get().getBlockNumber()); - successTimes++; - } else { - failedTimes++; - } - } - logger.info("Total times is " + totalTimes.toString()); - logger.info("success times is " + successTimes.toString()); - logger.info("failed times is " + failedTimes.toString()); - logger.info("success percent is " + successTimes / totalTimes); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/TvmContract.java b/framework/src/test/java/stest/tron/wallet/fulltest/TvmContract.java deleted file mode 100644 index 40025f12f85..00000000000 --- a/framework/src/test/java/stest/tron/wallet/fulltest/TvmContract.java +++ /dev/null @@ -1,150 +0,0 @@ -package stest.tron.wallet.fulltest; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TvmContract { - - //testng001、testng002、testng003、testng004 - private final String testKey002 = - "FC8BF0238748587B9617EB6D15D47A66C0E07C1A1959033CF249C6532DC29FE6"; - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contract008Address = ecKey1.getAddress(); - String contract008Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - PublicMethed.printAddress(contract008Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - Assert.assertTrue(PublicMethed.sendcoin(contract008Address, 500000000L, fromAddress, - testKey002, blockingStubFull)); - logger.info(Long.toString(PublicMethed.queryAccount(contract008Key, blockingStubFull) - .getBalance())); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(contract008Address, 1000000L, - 3, 1, contract008Key, blockingStubFull)); - Assert.assertTrue(PublicMethed.buyStorage(50000000L, contract008Address, contract008Key, - blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalance(contract008Address, 5000000L, - 3, contract008Key, blockingStubFull)); - - } - - @Test(enabled = false) - public void deployErc721CryptoKitties() { - AccountResourceMessage accountResource = PublicMethed.getAccountResource(contract008Address, - blockingStubFull); - Long energyLimit = accountResource.getEnergyLimit(); - Long storageLimit = accountResource.getStorageLimit(); - Long energyUsage = accountResource.getEnergyUsed(); - Long storageUsage = accountResource.getStorageUsed(); - - logger.info("before energy limit is " + Long.toString(energyLimit)); - logger.info("before energy usage is " + Long.toString(energyUsage)); - logger.info("before storage limit is " + Long.toString(storageLimit)); - logger.info("before storage usaged is " + Long.toString(storageUsage)); - Long maxFeeLimit = 50000000L; - String contractName = "ERC721"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_TvmContract_deployErc721CryptoKitties"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_TvmContract_deployErc721CryptoKitties"); - Long m = 0L; - Long freeNet; - accountResource = PublicMethed.getAccountResource(contract008Address, blockingStubFull); - Long net = accountResource.getFreeNetUsed(); - Account account = PublicMethed.queryAccount(contract008Key, blockingStubFull); - Long netUsed = account.getNetUsage(); - logger.info("before net used is " + Long.toString(netUsed)); - logger.info("before balance is " + account.getBalance()); - - for (Integer i = 0; i < 1; i++) { - byte[] contractAddress = PublicMethed.deployContract("1", abi, code, "", - 30000000L, 0L, 1, null, contract008Key, contract008Address, blockingStubFull); - accountResource = PublicMethed.getAccountResource(contract008Address, blockingStubFull); - freeNet = accountResource.getFreeNetUsed(); - energyUsage = accountResource.getEnergyUsed(); - logger.info( - "Time " + Integer.toString(i) + ": energy usage is " + Long.toString(energyUsage - m)); - logger.info("Time " + Integer.toString(i) + ": free net used is " + Long - .toString(freeNet - net)); - account = PublicMethed.queryAccount(contract008Key, blockingStubFull); - logger.info("after balance is " + account.getBalance()); - netUsed = account.getNetUsage(); - logger.info("after net used is " + Long.toString(netUsed)); - net = freeNet; - m = energyUsage; - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - } - //SmartContract smartContract = PublicMethed.getContract(contractAddress,blockingStubFull); - - //Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - //Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - //Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - //logger.info(smartContract.getName()); - //logger.info(smartContract.getAbi().toString()); - accountResource = PublicMethed.getAccountResource(contract008Address, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - storageLimit = accountResource.getStorageLimit(); - energyUsage = accountResource.getEnergyUsed(); - storageUsage = accountResource.getStorageUsed(); - //Assert.assertTrue(storageUsage > 0); - //Assert.assertTrue(storageLimit > 0); - //Assert.assertTrue(energyLimit > 0); - //Assert.assertTrue(energyUsage > 0); - - logger.info("after energy limit is " + Long.toString(energyLimit)); - logger.info("after energy usage is " + Long.toString(energyUsage)); - logger.info("after storage limit is " + Long.toString(storageLimit)); - logger.info("after storage usaged is " + Long.toString(storageUsage)); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign001.java b/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign001.java deleted file mode 100644 index 99c641e9f72..00000000000 --- a/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign001.java +++ /dev/null @@ -1,342 +0,0 @@ -package stest.tron.wallet.mutisign; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class WalletTestMutiSign001 { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "MutiSign001_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - ByteString assetAccountId1; - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[2]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey3.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] participateAddress = ecKey4.getAddress(); - String participateKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void testMutiSign1CreateAssetissue() { - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - manager2Address = ecKey2.getAddress(); - manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - ecKey3 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey3.getAddress(); - ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - PublicMethed.printAddress(ownerKey); - - long needCoin = updateAccountPermissionFee * 1 + multiSignFee * 3; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needCoin + 2048000000L, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - - logger.info(accountPermissionJson); - String txid = PublicMethedForMutiSign - .accountPermissionUpdateForTransactionId(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - - long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - long netFee = infoById.get().getReceipt().getNetFee(); - long fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + updateAccountPermissionFee); - - balanceBefore = balanceAfter; - - Long start = System.currentTimeMillis() + 5000; - Long end = System.currentTimeMillis() + 1000000000; - logger.info("try create asset issue"); - - txid = PublicMethedForMutiSign - .createAssetIssueForTransactionId(ownerAddress, name, totalSupply, 1, - 1, start, end, 1, description, url, 2000L, 2000L, - 1L, 1L, ownerKey, blockingStubFull, ownerKeyString); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertNotNull(txid); - - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - energyFee = infoById.get().getReceipt().getEnergyFee(); - netFee = infoById.get().getReceipt().getNetFee(); - fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + multiSignFee + 1024_000000L); - - logger.info(" create asset end"); - } - - /** - * constructor. - */ - - @Test(enabled = true) - public void testMutiSign2TransferAssetissue() { - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.printAddress(manager1Key); - Account getAssetIdFromOwnerAccount; - getAssetIdFromOwnerAccount = PublicMethed.queryAccount(ownerAddress, blockingStubFull); - assetAccountId1 = getAssetIdFromOwnerAccount.getAssetIssuedID(); - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - String txid = PublicMethedForMutiSign.transferAssetForTransactionId(manager1Address, - assetAccountId1.toByteArray(), 10, ownerAddress, ownerKey, blockingStubFull, - ownerKeyString); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertNotNull(txid); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - long netFee = infoById.get().getReceipt().getNetFee(); - long fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + multiSignFee); - } - - /** - * constructor. - */ - - @Test(enabled = true) - public void testMutiSign3ParticipateAssetissue() { - ecKey4 = new ECKey(Utils.getRandom()); - participateAddress = ecKey4.getAddress(); - participateKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - - long needCoin = updateAccountPermissionFee * 1 + multiSignFee * 2; - - Assert.assertTrue( - PublicMethed.sendcoin(participateAddress, needCoin + 2048000000L, fromAddress, testKey002, - blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Long balanceBefore = PublicMethed.queryAccount(participateAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - ownerKeyString[0] = participateKey; - ownerKeyString[1] = manager1Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(participateKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - logger.info(accountPermissionJson); - String txid = PublicMethedForMutiSign - .accountPermissionUpdateForTransactionId(accountPermissionJson, participateAddress, - participateKey, blockingStubFull, ownerKeyString); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertNotNull(txid); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - long balanceAfter = PublicMethed.queryAccount(participateAddress, blockingStubFull) - .getBalance(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - long netFee = infoById.get().getReceipt().getNetFee(); - long fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + updateAccountPermissionFee); - - balanceBefore = balanceAfter; - - txid = PublicMethedForMutiSign.participateAssetIssueForTransactionId(ownerAddress, - assetAccountId1.toByteArray(), 10, participateAddress, participateKey, 0, - blockingStubFull, ownerKeyString); - - Assert.assertNotNull(txid); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - balanceAfter = PublicMethed.queryAccount(participateAddress, blockingStubFull) - .getBalance(); - energyFee = infoById.get().getReceipt().getEnergyFee(); - netFee = infoById.get().getReceipt().getNetFee(); - fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee + 10); - Assert.assertEquals(fee, energyFee + netFee + multiSignFee); - } - - /** - * constructor. - */ - - @Test(enabled = true) - public void testMutiSign4updateAssetissue() { - url = "MutiSign001_update_url" + Long.toString(now); - ownerKeyString[0] = ownerKey; - description = "MutiSign001_update_description" + Long.toString(now); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - String txid = PublicMethedForMutiSign - .updateAssetForTransactionId(ownerAddress, description.getBytes(), url.getBytes(), 100L, - 100L, ownerKey, 2, blockingStubFull, permissionKeyString); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(txid); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - long netFee = infoById.get().getReceipt().getNetFee(); - long fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + multiSignFee); - } - - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign003.java b/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign003.java deleted file mode 100644 index d8e5f66cd13..00000000000 --- a/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign003.java +++ /dev/null @@ -1,200 +0,0 @@ -package stest.tron.wallet.mutisign; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class WalletTestMutiSign003 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress = PublicMethed.getFinalAddress(witnessKey001); - ByteString assetAccountId1; - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[3]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey3.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] newAddress = ecKey4.getAddress(); - String newKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void testMutiSignForAccount() { - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - manager2Address = ecKey2.getAddress(); - manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - ecKey3 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey3.getAddress(); - ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - PublicMethed.printAddress(ownerKey); - - ecKey4 = new ECKey(Utils.getRandom()); - newAddress = ecKey4.getAddress(); - newKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - - long needCoin = updateAccountPermissionFee * 1 + multiSignFee * 9; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needCoin + 100000000L, fromAddress, testKey002, - blockingStubFull)); - - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - ownerKeyString[2] = manager2Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":3,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - logger.info(accountPermissionJson); - String txid = PublicMethedForMutiSign - .accountPermissionUpdateForTransactionId(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString); - - final String updateName = Long.toString(System.currentTimeMillis()); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertNotNull(txid); - - Optional infoById = PublicMethed - .getTransactionInfoById(txid, blockingStubFull); - long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - long energyFee = infoById.get().getReceipt().getEnergyFee(); - long netFee = infoById.get().getReceipt().getNetFee(); - long fee = infoById.get().getFee(); - - logger.info("balanceAfter: " + balanceAfter); - logger.info("energyFee: " + energyFee); - logger.info("netFee: " + netFee); - logger.info("fee: " + fee); - - Assert.assertEquals(balanceBefore - balanceAfter, fee); - Assert.assertEquals(fee, energyFee + netFee + updateAccountPermissionFee); - - balanceBefore = balanceAfter; - - Assert.assertTrue(PublicMethedForMutiSign.createAccount( - ownerAddress, newAddress, ownerKey, blockingStubFull, ownerKeyString)); - - Assert.assertTrue(PublicMethedForMutiSign.sendcoinWithPermissionId( - newAddress, 100L, ownerAddress, 2, ownerKey, blockingStubFull, permissionKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.freezeBalanceWithPermissionId( - ownerAddress, 1000000L, 0, 0, ownerKey, blockingStubFull, ownerKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.freezeBalanceGetEnergy( - ownerAddress, 1000000L, 0, 2, ownerKey, blockingStubFull, ownerKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.freezeBalanceForReceiver( - ownerAddress, 1000000L, 0, 0, ByteString.copyFrom(newAddress), - ownerKey, blockingStubFull, ownerKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.unFreezeBalance( - ownerAddress, ownerKey, 0, null, blockingStubFull, ownerKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.unFreezeBalanceWithPermissionId( - ownerAddress, ownerKey, 0, newAddress, 2, blockingStubFull, permissionKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.updateAccount( - ownerAddress, updateName.getBytes(), ownerKey, blockingStubFull, ownerKeyString)); - - String voteStr = Base58.encode58Check(witnessAddress); - HashMap smallVoteMap = new HashMap(); - smallVoteMap.put(voteStr, "1"); - Assert.assertTrue(PublicMethedForMutiSign.voteWitness( - smallVoteMap, ownerAddress, ownerKey, blockingStubFull, ownerKeyString)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - Assert.assertEquals(balanceBefore - balanceAfter, multiSignFee * 9 + 1000000 + 100); - - Assert.assertTrue( - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull)); - - } - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign004.java b/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign004.java deleted file mode 100644 index 721622bf303..00000000000 --- a/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign004.java +++ /dev/null @@ -1,198 +0,0 @@ -package stest.tron.wallet.mutisign; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Optional; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class WalletTestMutiSign004 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ArrayList txidList = new ArrayList(); - Optional infoById = null; - Long beforeTime; - Long afterTime; - Long beforeBlockNum; - Long afterBlockNum; - Block currentBlock; - Long currentBlockNum; - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[2]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey3.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - @Test(enabled = true, threadPoolSize = 1, invocationCount = 1) - public void testMutiSignForSmartContract() { - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - manager2Address = ecKey2.getAddress(); - manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - ecKey3 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey3.getAddress(); - ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - PublicMethed.printAddress(ownerKey); - - long needcoin = updateAccountPermissionFee + multiSignFee * 3; - - Assert.assertTrue( - PublicMethed.sendcoin(ownerAddress, needcoin + 100000000L, fromAddress, testKey002, - blockingStubFull)); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 0, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 1000000000, 0, 1, ByteString.copyFrom(ownerAddress), - testKey002, blockingStubFull)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(ownerAddress, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - PublicMethed.waitProduceNextBlock(blockingStubFull); - ownerKeyString[0] = ownerKey; - ownerKeyString[1] = manager1Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - logger.info(accountPermissionJson); - PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString); - - Random rand = new Random(); - Integer randNum = rand.nextInt(30) + 1; - randNum = rand.nextInt(4000); - - Long maxFeeLimit = 1000000000L; - //String contractName = "StorageAndCpu" + Integer.toString(randNum); - String filePath = "./src/test/resources/soliditycode/walletTestMutiSign004.sol"; - String contractName = "timeoutTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] contractAddress = PublicMethedForMutiSign.deployContract(contractName, abi, code, - "", maxFeeLimit, - 0L, 100, null, ownerKey, ownerAddress, blockingStubFull, ownerKeyString); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString() != null); - String txid; - String initParmes = "\"" + "930" + "\""; - txid = PublicMethedForMutiSign.triggerContract(contractAddress, - "testUseCpu(uint256)", initParmes, false, - 0, maxFeeLimit, ownerAddress, ownerKey, blockingStubFull, ownerKeyString); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - logger.info("Txid is " + txid); - logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); - - Assert.assertTrue(infoById.get().getBlockNumber() > 0); - PublicMethedForMutiSign.updateSettingWithPermissionId(contractAddress, 50, ownerKey, - ownerAddress, 0, blockingStubFull, ownerKeyString); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull).getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertEquals(balanceBefore - balanceAfter, needcoin); - - Assert.assertTrue( - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, ownerAddress, blockingStubFull)); - Assert.assertTrue( - PublicMethed.unFreezeBalance(fromAddress, testKey002, 1, ownerAddress, blockingStubFull)); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign005.java b/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign005.java deleted file mode 100644 index 4ccbe67b8d8..00000000000 --- a/framework/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign005.java +++ /dev/null @@ -1,167 +0,0 @@ -package stest.tron.wallet.mutisign; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.ProposalList; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - - -@Slf4j -public class WalletTestMutiSign005 { - - private static final long now = System.currentTimeMillis(); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witness001Address = PublicMethed.getFinalAddress(witnessKey001); - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[1]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private long updateAccountPermissionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.updateAccountPermissionFee"); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true) - public void testMutiSignForProposal() { - long needcoin = updateAccountPermissionFee + multiSignFee * 3; - Assert.assertTrue(PublicMethed.sendcoin(witness001Address, needcoin + 10000000L, - fromAddress, testKey002, blockingStubFull)); - - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - manager2Address = ecKey2.getAddress(); - manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceBefore = PublicMethed.queryAccount(witness001Address, blockingStubFull) - .getBalance(); - logger.info("balanceBefore: " + balanceBefore); - - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - PublicMethed.waitProduceNextBlock(blockingStubFull); - ownerKeyString[0] = witnessKey001; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":2}]}," - + "\"witness_permission\":{\"type\":1,\"permission_name\":\"owner\",\"threshold\":1,\"" - + "keys\":[{\"address\":\"" + PublicMethed.getAddressString(witnessKey001) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - logger.info(accountPermissionJson); - PublicMethedForMutiSign.accountPermissionUpdate( - accountPermissionJson, witness001Address, witnessKey001, - blockingStubFull, ownerKeyString); - - //Create a proposal - - PublicMethed.waitProduceNextBlock(blockingStubFull); - HashMap proposalMap = new HashMap(); - proposalMap.put(0L, 81000L); - Assert.assertTrue( - PublicMethedForMutiSign.createProposalWithPermissionId(witness001Address, witnessKey001, - proposalMap, 2, blockingStubFull, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Get proposal list - ProposalList proposalList = blockingStubFull.listProposals(EmptyMessage.newBuilder().build()); - Optional listProposals = Optional.ofNullable(proposalList); - final Integer proposalId = listProposals.get().getProposalsCount(); - logger.info(Integer.toString(proposalId)); - - Assert.assertTrue(PublicMethedForMutiSign.approveProposalWithPermission( - witness001Address, witnessKey001, proposalId, - true, 2, blockingStubFull, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Delete proposal list after approve - Assert.assertTrue(PublicMethedForMutiSign.deleteProposalWithPermissionId( - witness001Address, witnessKey001, proposalId, 2, blockingStubFull, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long balanceAfter = PublicMethed.queryAccount(witness001Address, blockingStubFull) - .getBalance(); - logger.info("balanceAfter: " + balanceAfter); - - Assert.assertTrue(balanceBefore - balanceAfter >= needcoin); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateAccount2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateAccount2Test.java deleted file mode 100644 index 162b13c820f..00000000000 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateAccount2Test.java +++ /dev/null @@ -1,120 +0,0 @@ -package stest.tron.wallet.newaddinterface2; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AccountNetMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class CreateAccount2Test { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static final long sendAmount = 10000000000L; - private static final long FREENETLIMIT = 5000L; - private static final long BASELINE = 4800L; - private static String name = "AssetIssue012_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - //owner account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] account007Address = ecKey1.getAddress(); - String account007Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - //Wait to be create account - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] newAccountAddress = ecKey2.getAddress(); - String newAccountKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - logger.info(account007Key); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - Assert.assertTrue(PublicMethed.sendcoin(account007Address, 10000000, - fromAddress, testKey002, blockingStubFull)); - } - - @Test(enabled = true) - public void testCreateAccount2() { - Account accountInfo = PublicMethed.queryAccount(account007Key, blockingStubFull); - final Long beforeBalance = accountInfo.getBalance(); - AccountNetMessage accountNetInfo = PublicMethed.getAccountNet(account007Address, - blockingStubFull); - final Long beforeFreeNet = accountNetInfo.getFreeNetUsed(); - GrpcAPI.Return ret1 = PublicMethed.createAccount2(account007Address, newAccountAddress, - account007Key, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - accountInfo = PublicMethed.queryAccount(account007Key, blockingStubFull); - Long afterBalance = accountInfo.getBalance(); - accountNetInfo = PublicMethed.getAccountNet(account007Address, - blockingStubFull); - Long afterFreeNet = accountNetInfo.getFreeNetUsed(); - logger.info(Long.toString(beforeBalance)); - logger.info(Long.toString(afterBalance)); - //When creator has no bandwidth, he can't use the free net. - Assert.assertTrue(afterFreeNet == beforeFreeNet); - //When the creator has no bandwidth, create a new account should spend 0.1TRX. - Assert.assertTrue(beforeBalance - afterBalance == 100000); - } - - @Test(enabled = true) - public void testExceptionCreateAccount2() { - //Try to create an exist account - GrpcAPI.Return ret1 = PublicMethed - .createAccount2(account007Address, account007Address, account007Key, - blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Account has existed"); - //Try to create an invalid account - byte[] wrongAddress = "wrongAddress".getBytes(); - ret1 = PublicMethed.createAccount2(account007Address, wrongAddress, account007Key, - blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Invalid account address"); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateAssetIssue2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateAssetIssue2Test.java deleted file mode 100644 index c885377dc5c..00000000000 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateAssetIssue2Test.java +++ /dev/null @@ -1,398 +0,0 @@ -package stest.tron.wallet.newaddinterface2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.UnfreezeAssetContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class CreateAssetIssue2Test { - - private static final byte[] INVAILD_ADDRESS = Base58 - .decodeFromBase58Check("27cu1ozb4mX3m2afY68FSAqn3HmMp815d48"); - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "testAssetIssue001_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - String description = "just-test-assetissue-001"; - String url = "https://github.com/tronprotocol/wallet-cli/assetissue001"; - //get account - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] noBandwitchAddress = ecKey.getAddress(); - String noBandwitch = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - logger.info(ByteArray.toHexString(ecKey.getPrivKeyBytes())); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test() - public void testTransferAssetBandwitchDecreaseWithin10Second2() { - ByteString addressBS1 = ByteString.copyFrom(noBandwitchAddress); - Account request1 = Account.newBuilder().setAddress(addressBS1).build(); - GrpcAPI.AssetIssueList assetIssueList1 = blockingStubFull - .getAssetIssueByAccount(request1); - Optional queryAssetByAccount = Optional.ofNullable(assetIssueList1); - if (queryAssetByAccount.get().getAssetIssueCount() == 0) { - Assert.assertTrue(PublicMethed.sendcoin(noBandwitchAddress, 2048000000, - fromAddress, testKey002, blockingStubFull)); - Long start = System.currentTimeMillis() + 2000000; - Long end = System.currentTimeMillis() + 1000000000; - GrpcAPI.Return ret1 = PublicMethed.createAssetIssue2(noBandwitchAddress, name, totalSupply, 1, - 100, start, end, 1, description, url, 10000L, 10000L, - 1L, 1L, noBandwitch, blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - } else { - logger.info("This account already create an assetisue"); - Optional queryAssetByAccount1 = Optional.ofNullable(assetIssueList1); - name = ByteArray.toStr(queryAssetByAccount1.get().getAssetIssue(0).getName().toByteArray()); - } - - Assert.assertTrue( - transferAsset(toAddress, name.getBytes(), 100L, noBandwitchAddress, noBandwitch)); - //Transfer Asset failed when transfer to yourself - //Assert.assertFalse(transferAsset2(toAddress, name.getBytes(), 100L, toAddress, testKey003)); - Return ret1 = transferAsset2(toAddress, name.getBytes(), 100L, toAddress, testKey003); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "contract validate error : Cannot transfer asset to yourself."); - //Transfer Asset failed when the transfer amount is large than the asset balance you have. - ret1 = - transferAsset2(fromAddress, name.getBytes(), 9100000000000000000L, toAddress, testKey003); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "contract validate error : assetBalance is not sufficient."); - //Transfer Asset failed when the transfer amount is 0 - ret1 = transferAsset2(fromAddress, name.getBytes(), 0L, toAddress, testKey003); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "contract validate error : Amount must greater than 0."); - //Transfer Asset failed when the transfer amount is -1 - ret1 = transferAsset2(fromAddress, name.getBytes(), -1L, toAddress, testKey003); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "contract validate error : Amount must greater than 0."); - //Transfer failed when you want to transfer to an invalid address - ret1 = transferAsset2(INVAILD_ADDRESS, name.getBytes(), - 1L, toAddress, testKey003); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "contract validate error : Invalid toAddress"); - //Transfer failed when the asset issue name is not correct. - ret1 = - transferAsset2(fromAddress, (name + "wrong").getBytes(), 1L, toAddress, testKey003); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), "contract validate error : No asset !"); - //Transfer success. - ret1 = transferAsset2(fromAddress, name.getBytes(), 1L, toAddress, testKey003); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - - //No freeze asset, try to unfreeze asset failed. - Assert.assertFalse(unFreezeAsset(noBandwitchAddress, noBandwitch)); - logger.info("Test no asset frozen balance, try to unfreeze asset, no exception. Test OK!!!"); - - //Not create asset, try to unfreeze asset failed.No exception. - Assert.assertFalse(unFreezeAsset(toAddress, testKey003)); - logger.info("Test not create asset issue, try to unfreeze asset, no exception. Test OK!!!"); - - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean createAssetIssue(byte[] address, String name, Long totalSupply, Integer trxNum, - Integer icoNum, Long startTime, Long endTime, - Integer voteScore, String description, String url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - try { - AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - builder.setFreeAssetNetLimit(20000); - builder.setPublicFreeAssetNetLimit(20000); - Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - logger.info(name); - return true; - } - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - - public boolean transferAsset(byte[] to, byte[] assertName, long amount, byte[] address, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - TransferAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.transferAsset(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null || transaction.getRawData().getContractCount() == 0"); - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - Account search = queryAccount(ecKey, blockingStubFull); - return true; - } - - } - - /** - * constructor. - */ - - public Return transferAsset2(byte[] to, byte[] assertName, long amount, byte[] address, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - TransferAssetContract contract = builder.build(); - GrpcAPI.TransactionExtention transactionExtention = blockingStubFull.transferAsset2(contract); - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return response; - } else { - Account search = queryAccount(ecKey, blockingStubFull); - //return true; - } - return ret; - } - - /** - * constructor. - */ - - public boolean unFreezeAsset(byte[] addRess, String priKey) { - byte[] address = addRess; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - UnfreezeAssetContract.Builder builder = UnfreezeAssetContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - builder.setOwnerAddress(byteAddreess); - UnfreezeAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.unfreezeAsset(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - return true; - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateTransaction2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateTransaction2Test.java deleted file mode 100644 index 19d5cc2111a..00000000000 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateTransaction2Test.java +++ /dev/null @@ -1,352 +0,0 @@ -package stest.tron.wallet.newaddinterface2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.BalanceContract.FreezeBalanceContract; -import org.tron.protos.contract.BalanceContract.TransferContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class CreateTransaction2Test { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - - /* //testng001、testng002、testng003、testng004 - private static final byte[] fromAddress = Base58 - .decodeFromBase58Check("THph9K2M2nLvkianrMGswRhz5hjSA9fuH7"); - private static final byte[] toAddress = Base58 - .decodeFromBase58Check("TV75jZpdmP2juMe1dRwGrwpV6AMU6mr1EU");*/ - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - //receipt account - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] receiptAccountAddress = ecKey2.getAddress(); - String receiptAccountKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private ManagedChannel searchChannelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletGrpc.WalletBlockingStub searchBlockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String searchFullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] sendAccountAddress = ecKey1.getAddress(); - String sendAccountKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext() - .build(); - searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); - - } - - @Test - public void testSendCoin2() { - Assert.assertTrue(PublicMethed.sendcoin(sendAccountAddress, 90000000000L, - fromAddress, testKey002, blockingStubFull)); - - logger.info(receiptAccountKey); - Account sendAccount = PublicMethed.queryAccount(sendAccountKey, blockingStubFull); - Long sendAccountBeforeBalance = sendAccount.getBalance(); - Assert.assertTrue(sendAccountBeforeBalance == 90000000000L); - Account receiptAccount = PublicMethed.queryAccount(receiptAccountKey, blockingStubFull); - Long receiptAccountBeforeBalance = receiptAccount.getBalance(); - Assert.assertTrue(receiptAccountBeforeBalance == 0); - //normal sendcoin2 - Return ret1 = PublicMethed.sendcoin2(receiptAccountAddress, 49880000000L, - sendAccountAddress, sendAccountKey, blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - - sendAccount = PublicMethed.queryAccount(sendAccountKey, blockingStubFull); - Long sendAccountAfterBalance = sendAccount.getBalance(); - logger.info(Long.toString(sendAccountAfterBalance)); - Assert.assertTrue(sendAccountAfterBalance == 90000000000L - 49880000000L - 100000L); - - receiptAccount = PublicMethed.queryAccount(receiptAccountKey, blockingStubFull); - Long receiptAccountAfterBalance = receiptAccount.getBalance(); - Assert.assertTrue(receiptAccountAfterBalance == 49880000000L); - //Send coin failed due to no enough balance. - ret1 = PublicMethed - .sendcoin2(receiptAccountAddress, 9199999999999999999L, sendAccountAddress, sendAccountKey, - blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Validate TransferContract error, balance is not sufficient."); - //Send coin failed due to the amount is 0. - ret1 = PublicMethed - .sendcoin2(receiptAccountAddress, 0L, sendAccountAddress, sendAccountKey, blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Amount must be greater than 0."); - //Send coin failed due to the amount is -1Trx. - ret1 = PublicMethed - .sendcoin2(receiptAccountAddress, -1000000L, sendAccountAddress, sendAccountKey, - blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Amount must be greater than 0.."); - - //Send coin to yourself - ret1 = PublicMethed.sendcoin2(sendAccountAddress, 1000000L, sendAccountAddress, sendAccountKey, - blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Cannot transfer trx to yourself."); - //transfer all balance - ret1 = PublicMethed.sendcoin2(receiptAccountAddress, 40119900000L, - sendAccountAddress, sendAccountKey, blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - - sendAccount = PublicMethed.queryAccount(sendAccountKey, blockingStubFull); - Long sendAccountAfterBalance1 = sendAccount.getBalance(); - logger.info(Long.toString(sendAccountAfterBalance1)); - Assert.assertTrue( - sendAccountAfterBalance1 == 90000000000L - 49880000000L - 100000 - 40119900000L); - - receiptAccount = PublicMethed.queryAccount(receiptAccountKey, blockingStubFull); - Long receiptAccountAfterBalance1 = receiptAccount.getBalance(); - logger.info(Long.toString(receiptAccountAfterBalance1)); - Assert.assertTrue(receiptAccountAfterBalance1 == 49880000000L + 40119900000L); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (searchChannelFull != null) { - searchChannelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean freezeBalance(byte[] addRess, long freezeBalance, long freezeDuration, - String priKey) { - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - final Long beforeBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Account beforeFronzen = queryAccount(ecKey, blockingStubFull); - Long beforeFrozenBalance = 0L; - //Long beforeBandwidth = beforeFronzen.getBandwidth(); - if (beforeFronzen.getFrozenCount() != 0) { - beforeFrozenBalance = beforeFronzen.getFrozen(0).getFrozenBalance(); - //beforeBandwidth = beforeFronzen.getBandwidth(); - //logger.info(Long.toString(beforeFronzen.getBandwidth())); - logger.info(Long.toString(beforeFronzen.getFrozen(0).getFrozenBalance())); - } - - FreezeBalanceContract.Builder builder = FreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration); - - FreezeBalanceContract contract = builder.build(); - Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction = null"); - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } - - Long afterBlockNum = 0L; - Integer wait = 0; - while (afterBlockNum < beforeBlockNum + 1 && wait < 10) { - Block currentBlock1 = searchBlockingStubFull - .getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - afterBlockNum = currentBlock1.getBlockHeader().getRawData().getNumber(); - wait++; - try { - Thread.sleep(2000); - logger.info("wait 2 second"); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - Account afterFronzen = queryAccount(ecKey, searchBlockingStubFull); - Long afterFrozenBalance = afterFronzen.getFrozen(0).getFrozenBalance(); - //Long afterBandwidth = afterFronzen.getBandwidth(); - //logger.info(Long.toString(afterFronzen.getBandwidth())); - logger.info(Long.toString(afterFronzen.getFrozen(0).getFrozenBalance())); - //logger.info(Integer.toString(search.getFrozenCount())); - logger.info( - "beforefronen" + beforeFrozenBalance.toString() + " afterfronzen" + afterFrozenBalance - .toString()); - Assert.assertTrue(afterFrozenBalance - beforeFrozenBalance == freezeBalance); - //Assert.assertTrue(afterBandwidth - beforeBandwidth == freezeBalance * frozen_duration); - return true; - - - } - - /** - * constructor. - */ - - public Boolean sendcoin(byte[] to, long amount, byte[] owner, String priKey) { - - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account search = queryAccount(ecKey, blockingStubFull); - - TransferContract.Builder builder = TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferContract contract = builder.build(); - Transaction transaction = blockingStubFull.createTransaction(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateaAndUpdateWitness2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateaAndUpdateWitness2Test.java deleted file mode 100644 index fd8454599b9..00000000000 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/CreateaAndUpdateWitness2Test.java +++ /dev/null @@ -1,433 +0,0 @@ -package stest.tron.wallet.newaddinterface2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.WitnessList; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.contract.BalanceContract; -import org.tron.protos.contract.WitnessContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -//import stest.tron.wallet.common.client.AccountComparator; - -@Slf4j -public class CreateaAndUpdateWitness2Test { - - private static final byte[] INVAILD_ADDRESS = Base58 - .decodeFromBase58Check("27cu1ozb4mX3m2afY68FSAqn3HmMp815d48"); - private static final Long costForCreateWitness = 9999000000L; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String createWitnessUrl = "http://www.createwitnessurl.com/"; - String updateWitnessUrl = "http://www.updatewitnessurl.com/"; - String nullUrl = ""; - String spaceUrl = " ##################~!@#$%^&*()_+}{|:'/.,<>?|]=-"; - byte[] createUrl = createWitnessUrl.getBytes(); - byte[] updateUrl = updateWitnessUrl.getBytes(); - byte[] wrongUrl = nullUrl.getBytes(); - byte[] updateSpaceUrl = spaceUrl.getBytes(); - //get account - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] lowBalAddress = ecKey.getAddress(); - String lowBalTest = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - logger.info(lowBalTest); - logger.info(ByteArray.toHexString(PublicMethed.getFinalAddress(lowBalTest))); - logger.info(Base58.encode58Check(PublicMethed.getFinalAddress(lowBalTest))); - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test - public void testInvaildToApplyBecomeWitness2() { - GrpcAPI.Return ret1 = createWitness2(INVAILD_ADDRESS, createUrl, testKey002); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Invalid address"); - } - - @Test(enabled = true) - public void testCreateWitness2() { - //If you are already is witness, apply failed - createWitness(fromAddress, createUrl, testKey002); - GrpcAPI.Return ret1 = createWitness2(fromAddress, createUrl, testKey002); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Witness[415624c12e308b03a1a6b21d9b86e3942fac1ab92b] " - + "has existed"); - //balance is not enouhg,try to create witness. - Assert.assertTrue(sendcoin(lowBalAddress, 1000000L, fromAddress, testKey002)); - ret1 = createWitness2(lowBalAddress, createUrl, lowBalTest); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : balance < AccountUpgradeCost"); - //Send enough coin to the apply account to make that account - // has ability to apply become witness. - WitnessList witnesslist = blockingStubFull - .listWitnesses(GrpcAPI.EmptyMessage.newBuilder().build()); - Optional result = Optional.ofNullable(witnesslist); - WitnessList witnessList = result.get(); - if (result.get().getWitnessesCount() < 6) { - Assert.assertTrue(sendcoin(lowBalAddress, costForCreateWitness, fromAddress, testKey002)); - ret1 = createWitness2(lowBalAddress, createUrl, lowBalTest); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - } - } - - @Test(enabled = true) - public void testUpdateWitness2() { - WitnessList witnesslist = blockingStubFull - .listWitnesses(GrpcAPI.EmptyMessage.newBuilder().build()); - Optional result = Optional.ofNullable(witnesslist); - WitnessList witnessList = result.get(); - if (result.get().getWitnessesCount() < 6) { - //null url, update failed - GrpcAPI.Return ret1 = updateWitness2(lowBalAddress, wrongUrl, lowBalTest); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Invalid url"); - //Content space and special char, update success - ret1 = updateWitness2(lowBalAddress, updateSpaceUrl, lowBalTest); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - //update success - ret1 = updateWitness2(lowBalAddress, updateUrl, lowBalTest); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - } else { - logger.info("Update witness case had been test.This time skip it."); - } - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean createWitness(byte[] owner, byte[] url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - WitnessContract.WitnessCreateContract.Builder builder = WitnessContract.WitnessCreateContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setUrl(ByteString.copyFrom(url)); - WitnessContract.WitnessCreateContract contract = builder.build(); - - Protocol.Transaction transaction = blockingStubFull.createWitness(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return false; - } else { - return true; - } - - } - - /** - * constructor. - */ - - public GrpcAPI.Return createWitness2(byte[] owner, byte[] url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - WitnessContract.WitnessCreateContract.Builder builder = WitnessContract.WitnessCreateContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setUrl(ByteString.copyFrom(url)); - WitnessContract.WitnessCreateContract contract = builder.build(); - - GrpcAPI.TransactionExtention transactionExtention = blockingStubFull.createWitness2(contract); - - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - GrpcAPI.Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - Protocol.Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return response; - } - return ret; - - } - - /** - * constructor. - */ - - public Boolean updateWitness(byte[] owner, byte[] url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - WitnessContract.WitnessUpdateContract.Builder builder = WitnessContract.WitnessUpdateContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setUpdateUrl(ByteString.copyFrom(url)); - WitnessContract.WitnessUpdateContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.updateWitness(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - logger.info("response.getRestult() == false"); - return false; - } else { - return true; - } - - } - - /** - * constructor. - */ - - public GrpcAPI.Return updateWitness2(byte[] owner, byte[] url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - WitnessContract.WitnessUpdateContract.Builder builder = WitnessContract.WitnessUpdateContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setUpdateUrl(ByteString.copyFrom(url)); - WitnessContract.WitnessUpdateContract contract = builder.build(); - - GrpcAPI.TransactionExtention transactionExtention = blockingStubFull.updateWitness2(contract); - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - GrpcAPI.Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - Protocol.Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - logger.info("response.getRestult() == false"); - return response; - } - return ret; - } - - /** - * constructor. - */ - - public Boolean sendcoin(byte[] to, long amount, byte[] owner, String priKey) { - - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - BalanceContract.TransferContract.Builder builder = BalanceContract.TransferContract - .newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - BalanceContract.TransferContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createTransaction(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public Account queryAccount(String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Protocol.Transaction signTransaction(ECKey ecKey, Protocol.Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/FreezeBalance2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/FreezeBalance2Test.java deleted file mode 100644 index 0618fe08d3d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/FreezeBalance2Test.java +++ /dev/null @@ -1,478 +0,0 @@ -package stest.tron.wallet.newaddinterface2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.BalanceContract.FreezeBalanceContract; -import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class FreezeBalance2Test { - - private final String noFrozenBalanceTestKey = - "8CB4480194192F30907E14B52498F594BD046E21D7C4D8FE866563A6760AC891"; - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] noFrozenAddress = PublicMethed.getFinalAddress(noFrozenBalanceTestKey); - - private ManagedChannel channelFull = null; - private ManagedChannel searchChannelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletGrpc.WalletBlockingStub searchBlockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String searchFullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext() - .build(); - searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); - } - - @Test(enabled = true) - public void testFreezeBalance2() { - //Freeze failed when freeze amount is large than currently balance. - Return ret1 = freezeBalance2(fromAddress, 9000000000000000000L, 3L, testKey002); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : frozenBalance must be less than accountBalance"); - //Freeze failed when freeze amount less than 1Trx - ret1 = freezeBalance2(fromAddress, 999999L, 3L, testKey002); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : frozenBalance must be more than 1TRX"); - //Freeze failed when freeze duration isn't 3 days. - ret1 = freezeBalance2(fromAddress, 1000000L, 2L, testKey002); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : frozenDuration must be less than 3 days and more than 3 days"); - //Unfreeze balance failed when 3 days hasn't come. - ret1 = unFreezeBalance2(fromAddress, testKey002); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : It's not time to unfreeze."); - //Freeze failed when freeze amount is 0. - ret1 = freezeBalance2(fromAddress, 0L, 3L, testKey002); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : frozenBalance must be positive"); - //Freeze failed when freeze amount is -1. - ret1 = freezeBalance2(fromAddress, -1L, 3L, testKey002); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : frozenBalance must be positive"); - //Freeze failed when freeze duration is -1. - ret1 = freezeBalance2(fromAddress, 1000000L, -1L, testKey002); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : frozenDuration must be less than 3 days and more than 3 days"); - //Freeze failed when freeze duration is 0. - ret1 = freezeBalance2(fromAddress, 1000000L, 0L, testKey002); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : frozenDuration must be less than 3 days and more than 3 days"); - - try { - Thread.sleep(16000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - //Freeze balance success. - ret1 = PublicMethed.freezeBalance2(fromAddress, 1000000L, 3L, testKey002, blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - } - - @Test(enabled = true) - public void testUnFreezeBalance2() { - //Unfreeze failed when there is no freeze balance. - Return ret1 = unFreezeBalance2(noFrozenAddress, noFrozenBalanceTestKey); - logger.info("Test unfreezebalance"); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : no frozenBalance(BANDWIDTH)"); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (searchChannelFull != null) { - searchChannelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean freezeBalance(byte[] addRess, long freezeBalance, long freezeDuration, - String priKey) { - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Block currentBlock = blockingStubFull.getNowBlock(EmptyMessage.newBuilder().build()); - final Long beforeBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Account beforeFronzen = queryAccount(ecKey, blockingStubFull); - Long beforeFrozenBalance = 0L; - //Long beforeBandwidth = beforeFronzen.getBandwidth(); - if (beforeFronzen.getFrozenCount() != 0) { - beforeFrozenBalance = beforeFronzen.getFrozen(0).getFrozenBalance(); - //beforeBandwidth = beforeFronzen.getBandwidth(); - //logger.info(Long.toString(beforeFronzen.getBandwidth())); - logger.info(Long.toString(beforeFronzen.getFrozen(0).getFrozenBalance())); - } - - FreezeBalanceContract.Builder builder = FreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration); - - FreezeBalanceContract contract = builder.build(); - Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - return false; - } - - Long afterBlockNum = 0L; - Integer wait = 0; - while (afterBlockNum < beforeBlockNum + 1 && wait < 10) { - Block currentBlock1 = searchBlockingStubFull.getNowBlock(EmptyMessage.newBuilder().build()); - afterBlockNum = currentBlock1.getBlockHeader().getRawData().getNumber(); - wait++; - try { - Thread.sleep(2000); - logger.info("wait 2 second"); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - Account afterFronzen = queryAccount(ecKey, searchBlockingStubFull); - Long afterFrozenBalance = afterFronzen.getFrozen(0).getFrozenBalance(); - //Long afterBandwidth = afterFronzen.getBandwidth(); - //logger.info(Long.toString(afterFronzen.getBandwidth())); - logger.info(Long.toString(afterFronzen.getFrozen(0).getFrozenBalance())); - //logger.info(Integer.toString(search.getFrozenCount())); - logger.info( - "beforefronen" + beforeFrozenBalance.toString() + " afterfronzen" + afterFrozenBalance - .toString()); - Assert.assertTrue(afterFrozenBalance - beforeFrozenBalance == freezeBalance); - //Assert.assertTrue(afterBandwidth - beforeBandwidth == freezeBalance * frozen_duration); - return true; - - - } - - /** - * constructor. - */ - - public Return freezeBalance2(byte[] addRess, long freezeBalance, long freezeDuration, - String priKey) { - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Block currentBlock = blockingStubFull.getNowBlock(EmptyMessage.newBuilder().build()); - final Long beforeBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Account beforeFronzen = queryAccount(ecKey, blockingStubFull); - Long beforeFrozenBalance = 0L; - //Long beforeBandwidth = beforeFronzen.getBandwidth(); - if (beforeFronzen.getFrozenCount() != 0) { - beforeFrozenBalance = beforeFronzen.getFrozen(0).getFrozenBalance(); - //beforeBandwidth = beforeFronzen.getBandwidth(); - //logger.info(Long.toString(beforeFronzen.getBandwidth())); - logger.info(Long.toString(beforeFronzen.getFrozen(0).getFrozenBalance())); - } - - FreezeBalanceContract.Builder builder = FreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration); - - FreezeBalanceContract contract = builder.build(); - - GrpcAPI.TransactionExtention transactionExtention = blockingStubFull.freezeBalance2(contract); - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - return response; - } - - Long afterBlockNum = 0L; - Integer wait = 0; - while (afterBlockNum < beforeBlockNum + 1 && wait < 10) { - Block currentBlock1 = searchBlockingStubFull.getNowBlock(EmptyMessage.newBuilder().build()); - afterBlockNum = currentBlock1.getBlockHeader().getRawData().getNumber(); - wait++; - try { - Thread.sleep(2000); - logger.info("wait 2 second"); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - Account afterFronzen = queryAccount(ecKey, searchBlockingStubFull); - Long afterFrozenBalance = afterFronzen.getFrozen(0).getFrozenBalance(); - //Long afterBandwidth = afterFronzen.getBandwidth(); - //logger.info(Long.toString(afterFronzen.getBandwidth())); - logger.info(Long.toString(afterFronzen.getFrozen(0).getFrozenBalance())); - //logger.info(Integer.toString(search.getFrozenCount())); - logger.info( - "beforefronen" + beforeFrozenBalance.toString() + " afterfronzen" + afterFrozenBalance - .toString()); - Assert.assertTrue(afterFrozenBalance - beforeFrozenBalance == freezeBalance); - //Assert.assertTrue(afterBandwidth - beforeBandwidth == freezeBalance * frozen_duration); - return ret; - - - } - - /** - * constructor. - */ - - public boolean unFreezeBalance(byte[] addRess, String priKey) { - byte[] address = addRess; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account search = queryAccount(ecKey, blockingStubFull); - - UnfreezeBalanceContract.Builder builder = UnfreezeBalanceContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess); - - UnfreezeBalanceContract contract = builder.build(); - - Transaction transaction = blockingStubFull.unfreezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public Return unFreezeBalance2(byte[] addRess, String priKey) { - byte[] address = addRess; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account search = queryAccount(ecKey, blockingStubFull); - - UnfreezeBalanceContract.Builder builder = UnfreezeBalanceContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess); - - UnfreezeBalanceContract contract = builder.build(); - - GrpcAPI.TransactionExtention transactionExtention = blockingStubFull.unfreezeBalance2(contract); - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return response; - } - return ret; - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByLatestNum2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByLatestNum2Test.java deleted file mode 100644 index fbd8a29c3db..00000000000 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByLatestNum2Test.java +++ /dev/null @@ -1,178 +0,0 @@ -package stest.tron.wallet.newaddinterface2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; - -@Slf4j -public class GetBlockByLatestNum2Test { - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void testGetBlockByLatestNum2() { - // - GrpcAPI.BlockExtention currentBlock = blockingStubFull - .getNowBlock2(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Assert.assertFalse(currentBlockNum < 0); - while (currentBlockNum <= 5) { - logger.info("Now the block num is " + Long.toString(currentBlockNum) + " Please wait"); - currentBlock = blockingStubFull.getNowBlock2(GrpcAPI.EmptyMessage.newBuilder().build()); - currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - } - NumberMessage numberMessage = NumberMessage.newBuilder().setNum(3).build(); - GrpcAPI.BlockListExtention blockList = blockingStubFull.getBlockByLatestNum2(numberMessage); - Optional getBlockByLatestNum = Optional.ofNullable(blockList); - Assert.assertTrue(getBlockByLatestNum.isPresent()); - Assert.assertTrue(getBlockByLatestNum.get().getBlockCount() == 3); - Assert.assertTrue(getBlockByLatestNum.get().getBlock(0).hasBlockHeader()); - Assert.assertTrue( - getBlockByLatestNum.get().getBlock(1).getBlockHeader().getRawData().getNumber() > 0); - Assert.assertFalse( - getBlockByLatestNum.get().getBlock(2).getBlockHeader().getRawData().getParentHash() - .isEmpty()); - logger.info("TestGetBlockByLatestNum ok!!!"); - Assert.assertFalse(getBlockByLatestNum.get().getBlock(0).getBlockid().isEmpty()); - Assert.assertFalse(getBlockByLatestNum.get().getBlock(1).getBlockid().isEmpty()); - Assert.assertFalse(getBlockByLatestNum.get().getBlock(2).getBlockid().isEmpty()); - } - - @Test(enabled = true) - public void testGetBlockByExceptionNum2() { - GrpcAPI.BlockExtention currentBlock = blockingStubFull - .getNowBlock2(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Assert.assertFalse(currentBlockNum < 0); - while (currentBlockNum <= 5) { - logger.info("Now the block num is " + Long.toString(currentBlockNum) + " Please wait"); - currentBlock = blockingStubFull.getNowBlock2(GrpcAPI.EmptyMessage.newBuilder().build()); - currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - } - NumberMessage numberMessage = NumberMessage.newBuilder().setNum(-1).build(); - GrpcAPI.BlockListExtention blockList = blockingStubFull.getBlockByLatestNum2(numberMessage); - Optional getBlockByLatestNum = Optional.ofNullable(blockList); - Assert.assertTrue(getBlockByLatestNum.get().getBlockCount() == 0); - //Assert.assertTrue(getBlockByLatestNum.get().getBlock(1).getBlockid().isEmpty()); - - numberMessage = NumberMessage.newBuilder().setNum(0).build(); - blockList = blockingStubFull.getBlockByLatestNum2(numberMessage); - getBlockByLatestNum = Optional.ofNullable(blockList); - Assert.assertTrue(getBlockByLatestNum.get().getBlockCount() == 0); - //Assert.assertTrue(getBlockByLatestNum.get().getBlock(1).getBlockid().isEmpty()); - - numberMessage = NumberMessage.newBuilder().setNum(100).build(); - blockList = blockingStubFull.getBlockByLatestNum2(numberMessage); - getBlockByLatestNum = Optional.ofNullable(blockList); - Assert.assertTrue(getBlockByLatestNum.get().getBlockCount() == 0); - //Assert.assertTrue(getBlockByLatestNum.get().getBlock(10).getBlockid().isEmpty()); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByLimitNext2.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByLimitNext2.java deleted file mode 100644 index 3fd4fb3fa95..00000000000 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByLimitNext2.java +++ /dev/null @@ -1,204 +0,0 @@ -package stest.tron.wallet.newaddinterface2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; - -@Slf4j -public class GetBlockByLimitNext2 { - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true) - public void testGetBlockByLimitNext2() { - // - GrpcAPI.BlockExtention currentBlock = blockingStubFull - .getNowBlock2(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Assert.assertFalse(currentBlockNum < 0); - while (currentBlockNum <= 5) { - logger.info("Now has very little block, Please wait"); - currentBlock = blockingStubFull.getNowBlock2(GrpcAPI.EmptyMessage.newBuilder().build()); - currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - } - GrpcAPI.BlockLimit.Builder builder = GrpcAPI.BlockLimit.newBuilder(); - builder.setStartNum(2); - builder.setEndNum(4); - GrpcAPI.BlockListExtention blockList = blockingStubFull.getBlockByLimitNext2(builder.build()); - Optional getBlockByLimitNext = Optional.ofNullable(blockList); - Assert.assertTrue(getBlockByLimitNext.isPresent()); - Assert.assertTrue(getBlockByLimitNext.get().getBlockCount() == 2); - logger.info(Long.toString( - getBlockByLimitNext.get().getBlock(0).getBlockHeader().getRawData().getNumber())); - logger.info(Long.toString( - getBlockByLimitNext.get().getBlock(1).getBlockHeader().getRawData().getNumber())); - Assert.assertTrue( - getBlockByLimitNext.get().getBlock(0).getBlockHeader().getRawData().getNumber() < 4); - Assert.assertTrue( - getBlockByLimitNext.get().getBlock(1).getBlockHeader().getRawData().getNumber() < 4); - Assert.assertTrue(getBlockByLimitNext.get().getBlock(0).hasBlockHeader()); - Assert.assertTrue(getBlockByLimitNext.get().getBlock(1).hasBlockHeader()); - Assert.assertFalse( - getBlockByLimitNext.get().getBlock(0).getBlockHeader().getRawData().getParentHash() - .isEmpty()); - Assert.assertFalse( - getBlockByLimitNext.get().getBlock(1).getBlockHeader().getRawData().getParentHash() - .isEmpty()); - Assert.assertFalse(getBlockByLimitNext.get().getBlock(0).getBlockid().isEmpty()); - Assert.assertFalse(getBlockByLimitNext.get().getBlock(1).getBlockid().isEmpty()); - } - - @Test(enabled = true) - public void testGetBlockByExceptionLimitNext2() { - GrpcAPI.BlockExtention currentBlock = blockingStubFull - .getNowBlock2(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Assert.assertFalse(currentBlockNum < 0); - while (currentBlockNum <= 5) { - logger.info("Now has very little block, Please wait"); - currentBlock = blockingStubFull.getNowBlock2(GrpcAPI.EmptyMessage.newBuilder().build()); - currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - } - - //From -1 to 1 - GrpcAPI.BlockLimit.Builder builder = GrpcAPI.BlockLimit.newBuilder(); - builder.setStartNum(-1); - builder.setEndNum(1); - GrpcAPI.BlockListExtention blockList = blockingStubFull.getBlockByLimitNext2(builder.build()); - Optional getBlockByLimitNext = Optional.ofNullable(blockList); - Assert.assertTrue(getBlockByLimitNext.get().getBlockCount() == 0); - //check o block is empty - //Assert.assertTrue(getBlockByLimitNext.get().getBlock(1).getBlockid().isEmpty()); - //From 3 to 3 - builder = GrpcAPI.BlockLimit.newBuilder(); - builder.setStartNum(3); - builder.setEndNum(3); - blockList = blockingStubFull.getBlockByLimitNext2(builder.build()); - getBlockByLimitNext = Optional.ofNullable(blockList); - Assert.assertTrue(getBlockByLimitNext.get().getBlockCount() == 0); - //check the third block is empty - //Assert.assertTrue(getBlockByLimitNext.get().getBlock(3).getBlockid().isEmpty()); - //From 4 to 2 - builder = GrpcAPI.BlockLimit.newBuilder(); - builder.setStartNum(4); - builder.setEndNum(2); - blockList = blockingStubFull.getBlockByLimitNext2(builder.build()); - getBlockByLimitNext = Optional.ofNullable(blockList); - Assert.assertTrue(getBlockByLimitNext.get().getBlockCount() == 0); - //Assert.assertTrue(getBlockByLimitNext.get().getBlock(4).getBlockid().isEmpty()); - builder = GrpcAPI.BlockLimit.newBuilder(); - builder.setStartNum(999999990); - builder.setEndNum(999999999); - blockList = blockingStubFull.getBlockByLimitNext2(builder.build()); - getBlockByLimitNext = Optional.ofNullable(blockList); - Assert.assertTrue(getBlockByLimitNext.get().getBlockCount() == 0); - //Assert.assertTrue(getBlockByLimitNext.get().getBlock(999999990).getBlockid().isEmpty()); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByNum2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByNum2Test.java deleted file mode 100644 index 01408f655b9..00000000000 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetBlockByNum2Test.java +++ /dev/null @@ -1,265 +0,0 @@ -package stest.tron.wallet.newaddinterface2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; - -@Slf4j -public class GetBlockByNum2Test { - - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true) - public void testGetBlockByNum2() { - GrpcAPI.BlockExtention currentBlock = blockingStubFull - .getNowBlock2(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Assert.assertFalse(currentBlockNum < 0); - if (currentBlockNum == 1) { - logger.info("Now has very little block, Please test this case by manual"); - Assert.assertTrue(currentBlockNum == 1); - } - - //The number is large than the currently number, there is no exception when query this number. - /* Long outOfCurrentBlockNum = currentBlockNum + 10000L; - NumberMessage.Builder builder1 = NumberMessage.newBuilder(); - builder1.setNum(outOfCurrentBlockNum); - Block outOfCurrentBlock = blockingStubFull.getBlockByNum(builder1.build()); - Assert.assertFalse(outOfCurrentBlock.hasBlockHeader());*/ - - //Query the first block - NumberMessage.Builder builder2 = NumberMessage.newBuilder(); - builder2.setNum(1); - GrpcAPI.BlockExtention firstBlock = blockingStubFull.getBlockByNum2(builder2.build()); - Assert.assertTrue(firstBlock.hasBlockHeader()); - Assert.assertFalse(firstBlock.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertTrue(firstBlock.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(firstBlock.getBlockHeader().getRawData().getWitnessAddress().isEmpty()); - Assert.assertTrue(firstBlock.getBlockHeader().getRawData().getNumber() == 1); - Assert.assertFalse(firstBlock.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(firstBlock.getBlockHeader().getRawData().getWitnessId() >= 0); - Assert.assertFalse(firstBlock.getBlockid().isEmpty()); - - //Query the zero block - NumberMessage.Builder builder21 = NumberMessage.newBuilder(); - builder2.setNum(0); - GrpcAPI.BlockExtention zeroBlock = blockingStubFull.getBlockByNum2(builder21.build()); - Assert.assertTrue(zeroBlock.hasBlockHeader()); - Assert.assertTrue(zeroBlock.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertFalse(zeroBlock.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(zeroBlock.getBlockHeader().getRawData().getWitnessAddress().isEmpty()); - Assert.assertFalse(zeroBlock.getBlockHeader().getRawData().getNumber() == 1); - Assert.assertFalse(zeroBlock.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(zeroBlock.getBlockHeader().getRawData().getWitnessId() >= 0); - Assert.assertFalse(zeroBlock.getBlockid().isEmpty()); - - //Query the -1 block - NumberMessage.Builder builder22 = NumberMessage.newBuilder(); - builder2.setNum(-1); - GrpcAPI.BlockExtention nagtiveBlock = blockingStubFull.getBlockByNum2(builder22.build()); - Assert.assertTrue(nagtiveBlock.hasBlockHeader()); - Assert.assertTrue(nagtiveBlock.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertFalse(nagtiveBlock.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(nagtiveBlock.getBlockHeader().getRawData().getWitnessAddress().isEmpty()); - Assert.assertFalse(nagtiveBlock.getBlockHeader().getRawData().getNumber() == 1); - Assert.assertFalse(nagtiveBlock.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(nagtiveBlock.getBlockHeader().getRawData().getWitnessId() >= 0); - Assert.assertFalse(nagtiveBlock.getBlockid().isEmpty()); - - //Query the second latest block. - NumberMessage.Builder builder3 = NumberMessage.newBuilder(); - builder3.setNum(currentBlockNum - 1); - GrpcAPI.BlockExtention lastSecondBlock = blockingStubFull.getBlockByNum2(builder3.build()); - Assert.assertTrue(lastSecondBlock.hasBlockHeader()); - Assert.assertFalse(lastSecondBlock.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertTrue(lastSecondBlock.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(lastSecondBlock.getBlockHeader().getRawData().getWitnessAddress().isEmpty()); - Assert.assertTrue( - lastSecondBlock.getBlockHeader().getRawData().getNumber() + 1 == currentBlockNum); - Assert.assertFalse(lastSecondBlock.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(lastSecondBlock.getBlockHeader().getRawData().getWitnessId() >= 0); - Assert.assertFalse(lastSecondBlock.getBlockid().isEmpty()); - } - - @Test(enabled = true) - public void testGetBlockByNumFromSolidity2() { - GrpcAPI.BlockExtention currentBlock = blockingStubSolidity - .getNowBlock2(GrpcAPI.EmptyMessage.newBuilder().build()); - Long currentBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Assert.assertFalse(currentBlockNum < 0); - if (currentBlockNum == 1) { - logger.info("Now has very little block, Please test this case by manual"); - Assert.assertTrue(currentBlockNum == 1); - } - - //Query the first block. - NumberMessage.Builder builder2 = NumberMessage.newBuilder(); - builder2.setNum(1); - GrpcAPI.BlockExtention firstBlock = blockingStubSolidity.getBlockByNum2(builder2.build()); - Assert.assertTrue(firstBlock.hasBlockHeader()); - Assert.assertFalse(firstBlock.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertTrue(firstBlock.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(firstBlock.getBlockHeader().getRawData().getWitnessAddress().isEmpty()); - Assert.assertTrue(firstBlock.getBlockHeader().getRawData().getNumber() == 1); - Assert.assertFalse(firstBlock.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(firstBlock.getBlockHeader().getRawData().getWitnessId() >= 0); - logger.info("firstblock test from solidity succesfully"); - Assert.assertFalse(firstBlock.getBlockid().isEmpty()); - - //Query the second latest block. - NumberMessage.Builder builder3 = NumberMessage.newBuilder(); - builder3.setNum(currentBlockNum - 1); - GrpcAPI.BlockExtention lastSecondBlock = blockingStubSolidity.getBlockByNum2(builder3.build()); - Assert.assertTrue(lastSecondBlock.hasBlockHeader()); - Assert.assertFalse(lastSecondBlock.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertTrue(lastSecondBlock.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(lastSecondBlock.getBlockHeader().getRawData().getWitnessAddress().isEmpty()); - Assert.assertTrue( - lastSecondBlock.getBlockHeader().getRawData().getNumber() + 1 == currentBlockNum); - Assert.assertFalse(lastSecondBlock.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(lastSecondBlock.getBlockHeader().getRawData().getWitnessId() >= 0); - logger.info("Last second test from solidity succesfully"); - Assert.assertFalse(lastSecondBlock.getBlockid().isEmpty()); - } - - @Test(enabled = true) - public void testGetBlockById2() { - GrpcAPI.BlockExtention currentBlock = blockingStubFull - .getNowBlock2(GrpcAPI.EmptyMessage.newBuilder().build()); - ByteString currentHash = currentBlock.getBlockHeader().getRawData().getParentHash(); - GrpcAPI.BytesMessage request = GrpcAPI.BytesMessage.newBuilder().setValue(currentHash).build(); - Block setIdOfBlock = blockingStubFull.getBlockById(request); - Assert.assertTrue(setIdOfBlock.hasBlockHeader()); - Assert.assertFalse(setIdOfBlock.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertTrue(setIdOfBlock.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(setIdOfBlock.getBlockHeader().getRawData().getWitnessAddress().isEmpty()); - logger.info(Long.toString(setIdOfBlock.getBlockHeader().getRawData().getNumber())); - logger.info(Long.toString(currentBlock.getBlockHeader().getRawData().getNumber())); - Assert.assertTrue( - setIdOfBlock.getBlockHeader().getRawData().getNumber() + 1 == currentBlock.getBlockHeader() - .getRawData().getNumber()); - Assert.assertFalse(setIdOfBlock.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(setIdOfBlock.getBlockHeader().getRawData().getWitnessId() >= 0); - logger.info("By ID test succesfully"); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public GrpcAPI.BlockExtention getBlock2(long blockNum, - WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum2(builder.build()); - - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetNowBlock2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetNowBlock2Test.java deleted file mode 100644 index b20b8331d4d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetNowBlock2Test.java +++ /dev/null @@ -1,177 +0,0 @@ -package stest.tron.wallet.newaddinterface2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; - -//import stest.tron.wallet.common.client.AccountComparator; - -@Slf4j -public class GetNowBlock2Test { - - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test - public void testCurrentBlock2() { - //Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - GrpcAPI.BlockExtention currentBlock = blockingStubFull - .getNowBlock2(GrpcAPI.EmptyMessage.newBuilder().build()); - Assert.assertTrue(currentBlock.hasBlockHeader()); - Assert.assertFalse(currentBlock.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertTrue(currentBlock.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(currentBlock.getBlockHeader().getRawData().getWitnessAddress().isEmpty()); - Assert.assertTrue(currentBlock.getBlockHeader().getRawData().getNumber() > 0); - Assert.assertFalse(currentBlock.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(currentBlock.getBlockHeader().getRawData().getWitnessId() >= 0); - logger.info("test getcurrentblock is " + Long - .toString(currentBlock.getBlockHeader().getRawData().getNumber())); - Assert.assertFalse(currentBlock.getBlockid().isEmpty()); - - //Improve coverage. - currentBlock.equals(currentBlock); - //Block newBlock = blockingStubFull.getNowBlock2(GrpcAPI.EmptyMessage.newBuilder().build()); - GrpcAPI.BlockExtention newBlock = blockingStubFull - .getNowBlock2(GrpcAPI.EmptyMessage.newBuilder().build()); - newBlock.equals(currentBlock); - newBlock.hashCode(); - newBlock.getSerializedSize(); - newBlock.getTransactionsCount(); - newBlock.getTransactionsList(); - Assert.assertFalse(newBlock.getBlockid().isEmpty()); - } - - @Test - public void testCurrentBlockFromSolidity2() { - GrpcAPI.BlockExtention currentBlock = blockingStubSolidity - .getNowBlock2(GrpcAPI.EmptyMessage.newBuilder().build()); - Assert.assertTrue(currentBlock.hasBlockHeader()); - Assert.assertFalse(currentBlock.getBlockHeader().getWitnessSignature().isEmpty()); - Assert.assertTrue(currentBlock.getBlockHeader().getRawData().getTimestamp() > 0); - Assert.assertFalse(currentBlock.getBlockHeader().getRawData().getWitnessAddress().isEmpty()); - Assert.assertTrue(currentBlock.getBlockHeader().getRawData().getNumber() > 0); - Assert.assertFalse(currentBlock.getBlockHeader().getRawData().getParentHash().isEmpty()); - Assert.assertTrue(currentBlock.getBlockHeader().getRawData().getWitnessId() >= 0); - logger.info("test getcurrentblock in soliditynode is " + Long - .toString(currentBlock.getBlockHeader().getRawData().getNumber())); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - - public Account queryAccount(String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetTransactionsFromThis2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetTransactionsFromThis2Test.java deleted file mode 100644 index 88fa0f01960..00000000000 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetTransactionsFromThis2Test.java +++ /dev/null @@ -1,220 +0,0 @@ -package stest.tron.wallet.newaddinterface2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AccountPaginated; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletExtensionGrpc; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - - -@Slf4j -public class GetTransactionsFromThis2Test { - - private static final byte[] INVAILD_ADDRESS = - Base58.decodeFromBase58Check("27cu1ozb4mX3m2afY68FSAqn3HmMp815d48"); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final String notexist01 = - "DCB620820121A866E4E25905DC37F5025BFA5420B781C69E1BC6E1D83038C88A"; - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletExtensionGrpc.WalletExtensionBlockingStub blockingStubExtension = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - blockingStubExtension = WalletExtensionGrpc.newBlockingStub(channelSolidity); - - } - - @Test(enabled = false) - public void testgetTransactionsFromThis2() { - //Create a transfer. - Assert.assertTrue(PublicMethed.sendcoin(toAddress, 1000000, fromAddress, - testKey002, blockingStubFull)); - - ByteString addressBs = ByteString.copyFrom(fromAddress); - Account account = Account.newBuilder().setAddress(addressBs).build(); - AccountPaginated.Builder accountPaginated = AccountPaginated.newBuilder().setAccount(account); - accountPaginated.setOffset(1000); - accountPaginated.setLimit(0); - GrpcAPI.TransactionListExtention transactionListExtention = blockingStubExtension - .getTransactionsFromThis2(accountPaginated.build()); - Optional gettransactionsfromthis2 = Optional - .ofNullable(transactionListExtention); - - if (gettransactionsfromthis2.get().getTransactionCount() == 0) { - Assert.assertTrue(PublicMethed.sendcoin(toAddress, 1000000L, fromAddress, - testKey002, blockingStubFull)); - } - - Assert.assertTrue(gettransactionsfromthis2.isPresent()); - Integer beforecount = gettransactionsfromthis2.get().getTransactionCount(); - logger.info(Integer.toString(beforecount)); - for (Integer j = 0; j < beforecount; j++) { - Assert.assertFalse( - gettransactionsfromthis2.get().getTransaction(j).getTransaction().getRawData() - .getContractList().isEmpty()); - } - } - - @Test(enabled = false) - public void testgetTransactionsFromThisByInvaildAddress2() { - //Invaild address. - ByteString addressBs = ByteString.copyFrom(INVAILD_ADDRESS); - Account account = Account.newBuilder().setAddress(addressBs).build(); - AccountPaginated.Builder accountPaginated = AccountPaginated.newBuilder().setAccount(account); - accountPaginated.setOffset(1000); - accountPaginated.setLimit(0); - GrpcAPI.TransactionListExtention transactionListExtention = blockingStubExtension - .getTransactionsFromThis2(accountPaginated.build()); - Optional gettransactionsfromthisByInvaildAddress = Optional - .ofNullable(transactionListExtention); - Assert.assertTrue(gettransactionsfromthisByInvaildAddress.get().getTransactionCount() == 0); - - //Limit is -1 - addressBs = ByteString.copyFrom(INVAILD_ADDRESS); - account = Account.newBuilder().setAddress(addressBs).build(); - accountPaginated = AccountPaginated.newBuilder().setAccount(account); - accountPaginated.setOffset(1000); - accountPaginated.setLimit(-1); - transactionListExtention = blockingStubExtension - .getTransactionsFromThis2(accountPaginated.build()); - gettransactionsfromthisByInvaildAddress = Optional - .ofNullable(transactionListExtention); - Assert.assertTrue(gettransactionsfromthisByInvaildAddress.get().getTransactionCount() == 0); - - //offset is -1 - addressBs = ByteString.copyFrom(INVAILD_ADDRESS); - account = Account.newBuilder().setAddress(addressBs).build(); - accountPaginated = AccountPaginated.newBuilder().setAccount(account); - accountPaginated.setOffset(-1); - accountPaginated.setLimit(100); - transactionListExtention = blockingStubExtension - .getTransactionsFromThis2(accountPaginated.build()); - gettransactionsfromthisByInvaildAddress = Optional - .ofNullable(transactionListExtention); - Assert.assertTrue(gettransactionsfromthisByInvaildAddress.get().getTransactionCount() == 0); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetTransactionsToThis2.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetTransactionsToThis2.java deleted file mode 100644 index 29f53fb070e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/GetTransactionsToThis2.java +++ /dev/null @@ -1,234 +0,0 @@ -package stest.tron.wallet.newaddinterface2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AccountPaginated; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletExtensionGrpc; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - - -@Slf4j -public class GetTransactionsToThis2 { - - /* //testng001、testng002、testng003、testng004 - private static final byte[] fromAddress = - Base58.decodeFromBase58Check("THph9K2M2nLvkianrMGswRhz5hjSA9fuH7"); - private static final byte[] toAddress = - Base58.decodeFromBase58Check("TV75jZpdmP2juMe1dRwGrwpV6AMU6mr1EU");*/ - private static final byte[] INVAILD_ADDRESS = - Base58.decodeFromBase58Check("27cu1ozb4mX3m2afY68FSAqn3HmMp815d48"); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final String notexist01 = - "DCB620820121A866E4E25905DC37F5025BFA5420B781C69E1BC6E1D83038C88A"; - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletExtensionGrpc.WalletExtensionBlockingStub blockingStubExtension = null; - - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - blockingStubExtension = WalletExtensionGrpc.newBlockingStub(channelSolidity); - - - } - - @Test(enabled = true) - public void testgetTransactionsToThis2() { - //Create a transfer. - Assert.assertTrue(PublicMethed.sendcoin(toAddress, 1000000, fromAddress, - testKey002, blockingStubFull)); - - ByteString addressBs = ByteString.copyFrom(toAddress); - Account account = Account.newBuilder().setAddress(addressBs).build(); - AccountPaginated.Builder accountPaginated = AccountPaginated.newBuilder().setAccount(account); - accountPaginated.setOffset(1000); - accountPaginated.setLimit(0); - GrpcAPI.TransactionListExtention transactionListExtention = blockingStubExtension - .getTransactionsToThis2(accountPaginated.build()); - - Optional gettransactionstothis2 = Optional - .ofNullable(transactionListExtention); - - if (gettransactionstothis2.get().getTransactionCount() == 0) { - Assert.assertTrue(PublicMethed.sendcoin(toAddress, 1000000L, fromAddress, testKey002, - blockingStubFull)); - } - - Assert.assertTrue(gettransactionstothis2.isPresent()); - Integer beforecount = gettransactionstothis2.get().getTransactionCount(); - logger.info(Integer.toString(beforecount)); - for (Integer j = 0; j < beforecount; j++) { - Assert.assertFalse( - gettransactionstothis2.get().getTransaction(j).getTransaction().getRawData() - .getContractList().isEmpty()); - } - } - - @Test(enabled = true) - public void testgetTransactionsToThisByInvaildAddress2() { - //Invaild address. - ByteString addressBs = ByteString.copyFrom(INVAILD_ADDRESS); - Account account = Account.newBuilder().setAddress(addressBs).build(); - AccountPaginated.Builder accountPaginated = AccountPaginated.newBuilder().setAccount(account); - accountPaginated.setOffset(1000); - accountPaginated.setLimit(0); - GrpcAPI.TransactionListExtention transactionListExtention = blockingStubExtension - .getTransactionsToThis2(accountPaginated.build()); - Optional gettransactionstothisByInvaildAddress = Optional - .ofNullable(transactionListExtention); - - Assert.assertTrue(gettransactionstothisByInvaildAddress.get().getTransactionCount() == 0); - - //Limit is -1 - addressBs = ByteString.copyFrom(INVAILD_ADDRESS); - account = Account.newBuilder().setAddress(addressBs).build(); - accountPaginated = AccountPaginated.newBuilder().setAccount(account); - accountPaginated.setOffset(1000); - accountPaginated.setLimit(-1); - transactionListExtention = blockingStubExtension - .getTransactionsToThis2(accountPaginated.build()); - gettransactionstothisByInvaildAddress = Optional - .ofNullable(transactionListExtention); - - Assert.assertTrue(gettransactionstothisByInvaildAddress.get().getTransactionCount() == 0); - - //offset is -1 - addressBs = ByteString.copyFrom(INVAILD_ADDRESS); - account = Account.newBuilder().setAddress(addressBs).build(); - accountPaginated = AccountPaginated.newBuilder().setAccount(account); - accountPaginated.setOffset(-1); - accountPaginated.setLimit(100); - transactionListExtention = blockingStubExtension - .getTransactionsToThis2(accountPaginated.build()); - gettransactionstothisByInvaildAddress = Optional - .ofNullable(transactionListExtention); - - Assert.assertTrue(gettransactionstothisByInvaildAddress.get().getTransactionCount() == 0); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/ParticipateAssetIssue2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/ParticipateAssetIssue2Test.java deleted file mode 100644 index 765c70ea7ee..00000000000 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/ParticipateAssetIssue2Test.java +++ /dev/null @@ -1,358 +0,0 @@ -package stest.tron.wallet.newaddinterface2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.ParticipateAssetIssueContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class ParticipateAssetIssue2Test { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "testAssetIssue002_" + Long.toString(now); - //testng001、testng002、testng003、testng004 - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - String description = "just-test"; - String url = "https://github.com/tronprotocol/wallet-cli/"; - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] participateAccountAddress = ecKey1.getAddress(); - String participateAccountKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] assetIssueAccount002 = ecKey2.getAddress(); - String testKeyForAssetIssueAccount002 = ByteArray.toHexString(ecKey2 - .getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - @Test(enabled = true) - public void testParticipateAssetissue2() { - ByteString addressBS1 = ByteString.copyFrom(participateAccountAddress); - Account request1 = Account.newBuilder().setAddress(addressBS1).build(); - GrpcAPI.AssetIssueList assetIssueList1 = blockingStubFull - .getAssetIssueByAccount(request1); - Optional queryAssetByAccount = Optional.ofNullable(assetIssueList1); - if (queryAssetByAccount.get().getAssetIssueCount() == 0) { - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - //send coin to the new account - Assert.assertTrue(PublicMethed.sendcoin(participateAccountAddress, 2048000000, fromAddress, - testKey002, blockingStubFull)); - //Create a new Asset Issue - Assert.assertTrue(PublicMethed.createAssetIssue(participateAccountAddress, - name, totalSupply, 1, 1, System.currentTimeMillis() + 2000, - System.currentTimeMillis() + 1000000000, 1, description, url, - 2000L, 2000L, 1L, 1L, - participateAccountKey, blockingStubFull)); - } else { - logger.info("This account already create an assetisue"); - Optional queryAssetByAccount1 = Optional.ofNullable(assetIssueList1); - name = ByteArray.toStr(queryAssetByAccount1.get().getAssetIssue(0).getName().toByteArray()); - - } - - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - //Participate AssetIssue success - logger.info(name); - //Freeze amount to get bandwitch. - Assert.assertTrue(PublicMethed.freezeBalance(toAddress, 10000000, 3, testKey003, - blockingStubFull)); - - //The amount is large than the total supply, participate failed. - Return ret1 = PublicMethed.participateAssetIssue2(participateAccountAddress, - name.getBytes(), 9100000000000000000L, toAddress, testKey003, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : No enough balance !"); - //The asset issue name is not correct, participate failed. - ret1 = PublicMethed.participateAssetIssue2(participateAccountAddress, - (name + "wrong").getBytes(), 100L, toAddress, testKey003, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - //The amount is 0, participate asset issue failed. - ret1 = PublicMethed.participateAssetIssue2(participateAccountAddress, - name.getBytes(), 0L, toAddress, testKey003, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Amount must greater than 0!"); - - //The amount is -1, participate asset issue failed. - ret1 = PublicMethed.participateAssetIssue2(participateAccountAddress, - name.getBytes(), -1L, toAddress, testKey003, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Amount must greater than 0!"); - //The asset issue owner address is not correct, participate asset issue failed. - ret1 = PublicMethed.participateAssetIssue2(fromAddress, name.getBytes(), 100L, - toAddress, testKey003, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public boolean participateAssetIssue(byte[] to, byte[] assertName, long amount, byte[] from, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - ParticipateAssetIssueContract.Builder builder = ParticipateAssetIssueContract - .newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(from); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - ParticipateAssetIssueContract contract = builder.build(); - - Transaction transaction = blockingStubFull.participateAssetIssue(contract); - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - logger.info(name); - return true; - } - } - - /** - * constructor. - */ - - public Boolean createAssetIssue(byte[] address, String name, Long totalSupply, Integer trxNum, - Integer icoNum, Long startTime, Long endTime, - Integer voteScore, String description, String url, Long fronzenAmount, Long frozenDay, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - try { - AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - builder.setFreeAssetNetLimit(20000); - builder.setPublicFreeAssetNetLimit(20000); - AssetIssueContract.FrozenSupply.Builder frozenBuilder = - AssetIssueContract.FrozenSupply.newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - builder.addFrozenSupply(0, frozenBuilder); - - Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return false; - } else { - logger.info(name); - return true; - } - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - /** - * constructor. - */ - - public Account queryAccount(String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - - public boolean transferAsset(byte[] to, byte[] assertName, long amount, byte[] address, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.transferAsset(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null || transaction.getRawData().getContractCount() == 0"); - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - //Account search = queryAccount(ecKey, blockingStubFull); - return true; - } - - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/TransferAsset2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/TransferAsset2Test.java deleted file mode 100644 index 533c05dd002..00000000000 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/TransferAsset2Test.java +++ /dev/null @@ -1,402 +0,0 @@ -package stest.tron.wallet.newaddinterface2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.UnfreezeAssetContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class TransferAsset2Test { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static String name = "testAssetIssue001_" + Long.toString(now); - //testng001、testng002、testng003、testng004 - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - String description = "just-test-assetissue-001"; - String url = "https://github.com/tronprotocol/wallet-cli/assetissue001"; - //get account - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] noBandwitchAddress = ecKey.getAddress(); - String noBandwitch = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - logger.info(ByteArray.toHexString(ecKey.getPrivKeyBytes())); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - - } - - @Test() - public void testTransferAssetBandwitchDecreaseWithin10Second2() { - ByteString addressBS1 = ByteString.copyFrom(noBandwitchAddress); - Account request1 = Account.newBuilder().setAddress(addressBS1).build(); - GrpcAPI.AssetIssueList assetIssueList1 = blockingStubFull - .getAssetIssueByAccount(request1); - Optional queryAssetByAccount = Optional.ofNullable(assetIssueList1); - if (queryAssetByAccount.get().getAssetIssueCount() == 0) { - Assert.assertTrue(PublicMethed.sendcoin(noBandwitchAddress, 2048000000, - fromAddress, testKey002, blockingStubFull)); - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - - Return ret1 = PublicMethed.createAssetIssue2(noBandwitchAddress, name, totalSupply, 1, - 100, start, end, 1, description, url, 10000L, 10000L, - 1L, 1L, noBandwitch, blockingStubFull); - } else { - logger.info("This account already create an assetisue"); - Optional queryAssetByAccount1 = Optional.ofNullable(assetIssueList1); - name = ByteArray.toStr(queryAssetByAccount1.get().getAssetIssue(0).getName().toByteArray()); - - } - - Return ret1 = transferAsset2(toAddress, name.getBytes(), 100L, noBandwitchAddress, noBandwitch); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - //Transfer Asset failed when transfer to yourself - ret1 = transferAsset2(toAddress, name.getBytes(), 100L, toAddress, testKey003); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Cannot transfer asset to yourself."); - //Transfer Asset failed when the transfer amount is large than the asset balance you have. - ret1 = - transferAsset2(fromAddress, name.getBytes(), 9100000000000000000L, toAddress, testKey003); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : assetBalance is not sufficient."); - //Transfer Asset failed when the transfer amount is 0 - ret1 = transferAsset2(fromAddress, name.getBytes(), 0L, toAddress, testKey003); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Amount must greater than 0."); - //Transfer Asset failed when the transfer amount is -1 - ret1 = transferAsset2(fromAddress, name.getBytes(), -1L, toAddress, testKey003); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Amount must greater than 0."); - ret1 = - transferAsset2(fromAddress, (name + "wrong").getBytes(), 1L, toAddress, testKey003); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), "Contract validate error : No asset !"); - //Transfer success. - ret1 = transferAsset2(fromAddress, name.getBytes(), 1L, toAddress, testKey003); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - - //No freeze asset, try to unfreeze asset failed. - Assert.assertFalse(unFreezeAsset(noBandwitchAddress, noBandwitch)); - logger.info("Test no asset frozen balance, try to unfreeze asset, no exception. Test OK!!!"); - //Not create asset, try to unfreeze asset failed.No exception. - Assert.assertFalse(unFreezeAsset(toAddress, testKey003)); - logger.info("Test not create asset issue, try to unfreeze asset, no exception. Test OK!!!"); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean createAssetIssue(byte[] address, String name, Long totalSupply, Integer trxNum, - Integer icoNum, Long startTime, Long endTime, - Integer voteScore, String description, String url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - try { - AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - builder.setFreeAssetNetLimit(20000); - builder.setPublicFreeAssetNetLimit(20000); - Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - logger.info(name); - return true; - } - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - - public boolean transferAsset(byte[] to, byte[] assertName, long amount, byte[] address, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.transferAsset(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null || transaction.getRawData().getContractCount() == 0"); - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - Account search = queryAccount(ecKey, blockingStubFull); - return true; - } - - } - - /** - * constructor. - */ - - public Return transferAsset2(byte[] to, byte[] assertName, long amount, byte[] address, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferAssetContract contract = builder.build(); - - GrpcAPI.TransactionExtention transactionExtention = blockingStubFull.transferAsset2(contract); - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return response; - } else { - Account search = queryAccount(ecKey, blockingStubFull); - } - return ret; - } - - /** - * constructor. - */ - - public boolean unFreezeAsset(byte[] addRess, String priKey) { - byte[] address = addRess; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - UnfreezeAssetContract.Builder builder = UnfreezeAssetContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess); - - UnfreezeAssetContract contract = builder.build(); - - Transaction transaction = blockingStubFull.unfreezeAsset(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - return true; - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/UnfreezeAsset2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/UnfreezeAsset2Test.java deleted file mode 100644 index 7bc23cef344..00000000000 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/UnfreezeAsset2Test.java +++ /dev/null @@ -1,632 +0,0 @@ -package stest.tron.wallet.newaddinterface2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.ParticipateAssetIssueContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.UnfreezeAssetContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class UnfreezeAsset2Test { - - private static final long now = System.currentTimeMillis(); - private static final String name = "testAssetIssue003_" + Long.toString(now); - - /* //testng001、testng002、testng003、testng004 - private static final byte[] fromAddress = Base58 - .decodeFromBase58Check("THph9K2M2nLvkianrMGswRhz5hjSA9fuH7"); - private static final byte[] toAddress = Base58 - .decodeFromBase58Check("TV75jZpdmP2juMe1dRwGrwpV6AMU6mr1EU");*/ - private static final String shortname = "a"; - private static final String tooLongName = "qazxswedcvfrtgbnhyujmkiolpoiuytre"; - private static final String chineseAssetIssuename = "中文都名字"; - private static final String tooLongDescription = - "1qazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqa" - + "zxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvq" - + "azxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcv"; - private static final String tooLongUrl = - "qaswqaswqaswqaswqaswqaswqaswqaswqaswqaswqaswqaswqaswqasw1qazxswedcvqazxswedcv" - + "qazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedc" - + "vqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqaz" - + "xswedcvqazxswedcvqazxswedcvqazxswedcv"; - private static final long totalSupply = now; - //testng001、testng002、testng003、testng004 - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - //get account - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] lowBalAddress = ecKey.getAddress(); - String lowBalTest = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - //get account - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] lowBalAddress2 = ecKey2.getAddress(); - String lowBalTest2 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - String description = "just-test"; - String url = "https://github.com/tronprotocol/wallet-cli/"; - - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - - } - - @Test(enabled = true) - public void testGetAllAssetIssue2() { - Return ret1 = PublicMethed.sendcoin2(lowBalAddress, 2124500000L, - fromAddress, testKey002, blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - - ret1 = PublicMethed.sendcoin2(lowBalAddress2, 21240500000L, - fromAddress, testKey002, blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - ByteString addressBS1 = ByteString.copyFrom(fromAddress); - Account request1 = Account.newBuilder().setAddress(addressBS1).build(); - GrpcAPI.AssetIssueList assetIssueList1 = blockingStubFull.getAssetIssueByAccount(request1); - Optional queryAssetByAccount = Optional.ofNullable(assetIssueList1); - - //if (queryAssetByAccount.get().getAssetIssueCount() == 0) { - Long start = System.currentTimeMillis() + 100000; - Long end = System.currentTimeMillis() + 1000000000; - //Freeze amount is large than total supply, create asset issue failed. - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, totalSupply, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 9000000000000000000L, 1L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Frozen supply cannot exceed total supply"); - //Freeze day is 0, create failed - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, totalSupply, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 100L, 0L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), "Contract validate error : " - + "frozenDuration must be less than 3652 days and more than 1 days"); - //Freeze amount is 0, create failed - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, totalSupply, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 0L, 1L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Frozen supply must be greater than 0!"); - //Freeze day is -1, create failed - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, totalSupply, 1, 10, - start, end, 2, description, url, 1000L, 1000L, - 1000L, -1L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), "Contract validate error : " - + "frozenDuration must be less than 3652 days and more than 1 days"); - //Freeze amount is -1, create failed - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, totalSupply, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - -1L, 1L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Frozen supply must be greater than 0!"); - //Freeze day is 3653(10 years + 1 day), create failed - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, totalSupply, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3653L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), "Contract validate error : " - + "frozenDuration must be less than 3652 days and more than 1 days"); - //Start time is late than end time. - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, totalSupply, 1, 10, - end, start, 2, description, url, 10000L, 10000L, - 1L, 2L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : End time should be greater than start time"); - //Start time is early than currently time. - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, totalSupply, 1, 10, - start - 1000000L, end, 2, description, url, 10000L, - 10000L, 1L, 2L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Start time should be greater than HeadBlockTime"); - //totalSupply is zero. - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, 0L, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : TotalSupply must greater than 0!"); - //Totalsupply is -1. - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, -1L, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : TotalSupply must greater than 0!"); - //TrxNum is zero. - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, totalSupply, 0, 10, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : TrxNum must greater than 0!"); - //TrxNum is -1. - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, totalSupply, -1, 10, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : TrxNum must greater than 0!"); - //IcoNum is 0. - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, totalSupply, 1, 0, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, testKey002, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Num must greater than 0!"); - //IcoNum is -1. - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, totalSupply, 1, -1, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Num must greater than 0!"); - //The asset issue name is null. - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, "", totalSupply, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Invalid assetName"); - //The asset issue name is large than 33 char. - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, tooLongName, totalSupply, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Invalid assetName"); - //The asset issue name is chinese name. - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, chineseAssetIssuename, totalSupply, 1, - 10, start, end, 2, description, url, 10000L, - 10000L, 1L, 3652L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Invalid assetName"); - //The URL is null. - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, totalSupply, 1, 10, - start, end, 2, description, "", 10000L, 10000L, - 1L, 3652L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), "Contract validate error : Invalid url"); - //The URL is too long. - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, totalSupply, 1, 10, - start, end, 2, description, tooLongUrl, 10000L, 10000L, - 1L, 3652L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), "Contract validate error : Invalid url"); - //The description is too long, create failed. - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, totalSupply, 1, 10, - start, end, 2, tooLongDescription, url, 10000L, - 10000L, 1L, 3652L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Invalid description"); - - //FreezeBalance - Assert.assertTrue(PublicMethed.freezeBalance(lowBalAddress, 10000000L, 3, lowBalTest, - blockingStubFull)); - //Create success - start = System.currentTimeMillis() + 6000; - end = System.currentTimeMillis() + 1000000000; - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, totalSupply, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - //Test not in the duration time, participate failed. - ret1 = PublicMethed.participateAssetIssue2(lowBalAddress, name.getBytes(), 1L, - toAddress, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : No longer valid period!"); - //Test another address try to create the same name asset issue, create failed. - ret1 = PublicMethed.createAssetIssue2(lowBalAddress2, name, totalSupply, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, lowBalTest2, blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), "contract validate error : Token exists"); - - try { - Thread.sleep(4000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - GrpcAPI.AssetIssueList assetIssueList = blockingStubFull - .getAssetIssueList(GrpcAPI.EmptyMessage.newBuilder().build()); - logger.info(Integer.toString(assetIssueList.getAssetIssue(0).getFrozenSupplyCount())); - Assert.assertTrue(assetIssueList.getAssetIssue(0).getFrozenSupplyCount() == 1); - //Assert.assertTrue(assetIssueList.getAssetIssue(j).getFrozenSupplyCount() > 0); - Assert.assertTrue(assetIssueList.getAssetIssue(0).getFrozenSupply(0).getFrozenAmount() > 0); - Assert.assertTrue(assetIssueList.getAssetIssue(0).getFrozenSupply(0).getFrozenDays() > 0); - - //Test one account only can create one asset issue. - start = System.currentTimeMillis() + 3000; - end = System.currentTimeMillis() + 1000000000; - ret1 = PublicMethed.createAssetIssue2(lowBalAddress, shortname, totalSupply, 1, 10, - start, end, 2, description, url, 10000L, 10000L, - 1L, 3652L, testKey002, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : An account can only issue one asset"); - logger.info("FROM ADDRESS create asset issue in this case!!!"); - - assetIssueList = blockingStubFull - .getAssetIssueList(GrpcAPI.EmptyMessage.newBuilder().build()); - Assert.assertTrue(assetIssueList.getAssetIssueCount() >= 1); - for (Integer j = 0; j < assetIssueList.getAssetIssueCount(); j++) { - Assert.assertFalse(assetIssueList.getAssetIssue(j).getOwnerAddress().isEmpty()); - Assert.assertFalse(assetIssueList.getAssetIssue(j).getName().isEmpty()); - Assert.assertFalse(assetIssueList.getAssetIssue(j).getUrl().isEmpty()); - Assert.assertTrue(assetIssueList.getAssetIssue(j).getTotalSupply() > 0); - logger.info("test get all assetissue"); - } - - //Improve coverage. - assetIssueList.equals(assetIssueList); - assetIssueList.equals(null); - GrpcAPI.AssetIssueList newAssetIssueList = blockingStubFull - .getAssetIssueList(GrpcAPI.EmptyMessage.newBuilder().build()); - assetIssueList.equals(newAssetIssueList); - assetIssueList.hashCode(); - assetIssueList.getSerializedSize(); - - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean createAssetIssue(byte[] address, String name, Long totalSupply, Integer trxNum, - Integer icoNum, Long startTime, Long endTime, - Integer voteScore, String description, String url, Long fronzenAmount, Long frozenDay, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account search = queryAccount(ecKey, blockingStubFull); - - try { - AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setFreeAssetNetLimit(10000); - builder.setPublicFreeAssetNetLimit(10000); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - AssetIssueContract.FrozenSupply.Builder frozenBuilder = - AssetIssueContract.FrozenSupply - .newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - builder.addFrozenSupply(0, frozenBuilder); - - Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - logger.info(name); - return true; - } - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - - public boolean transferAsset(byte[] to, byte[] assertName, long amount, byte[] address, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - TransferAssetContract.Builder builder = TransferAssetContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - TransferAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.transferAsset(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return false; - } else { - Account search = queryAccount(ecKey, blockingStubFull); - return true; - } - - } - - /** - * constructor. - */ - - public boolean unFreezeAsset(byte[] addRess, String priKey) { - byte[] address = addRess; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - UnfreezeAssetContract.Builder builder = UnfreezeAssetContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess); - - UnfreezeAssetContract contract = builder.build(); - - Transaction transaction = blockingStubFull.unfreezeAsset(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public boolean unFreezeAsset2(byte[] addRess, String priKey) { - byte[] address = addRess; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - UnfreezeAssetContract.Builder builder = UnfreezeAssetContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess); - - UnfreezeAssetContract contract = builder.build(); - - GrpcAPI.TransactionExtention transactionExtention = blockingStubFull.unfreezeAsset2(contract); - if (transactionExtention == null) { - return false; - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return false; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return false; - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public boolean participateAssetIssue(byte[] to, byte[] assertName, long amount, byte[] from, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - ParticipateAssetIssueContract.Builder builder = ParticipateAssetIssueContract - .newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(from); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - ParticipateAssetIssueContract contract = builder.build(); - - Transaction transaction = blockingStubFull.participateAssetIssue(contract); - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - logger.info(name); - return true; - } - } - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/UpdateAccount2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/UpdateAccount2Test.java deleted file mode 100644 index 82b395c24f2..00000000000 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/UpdateAccount2Test.java +++ /dev/null @@ -1,961 +0,0 @@ -package stest.tron.wallet.newaddinterface2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.WitnessList; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.contract.AccountContract.AccountUpdateContract; -import org.tron.protos.contract.AssetIssueContractOuterClass; -import org.tron.protos.contract.BalanceContract; -import org.tron.protos.contract.WitnessContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -//import stest.tron.wallet.common.client.AccountComparator; - -@Slf4j -public class UpdateAccount2Test { - - private static final long now = System.currentTimeMillis(); - private static final String name = "testAssetIssue_" + Long.toString(now); - private static final long TotalSupply = now; - //testng001、testng002、testng003、testng004 - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - String mostLongNamePlusOneChar = "1abcdeabcdefabcdefg1abcdefg10o0og1abcdefg10o0oabcd" - + "efabcdefg1abcdefg10o0og1abcdefg10o0oabcdefabcdefg1abcdefg10o0og1abcdefg10o0oab" - + "cdefabcdefg1abcdefg10o0og1abcdefg10o0ofabcdefg1abcdefg10o0og1abcdefg10o0o"; - String mostLongName = "abcdeabcdefabcdefg1abcdefg10o0og1abcdefg10o0oabcd" - + "efabcdefg1abcdefg10o0og1abcdefg10o0oabcdefabcdefg1abcdefg10o0og1abcdefg10o0oab" - + "cdefabcdefg1abcdefg10o0og1abcdefg10o0ofabcdefg1abcdefg10o0og1abcdefg10o0o"; - String description = "just-test"; - String url = "https://github.com/tronprotocol/wallet-cli/"; - - //get account - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] lowBalAddress = ecKey.getAddress(); - String lowBalTest = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - //System.out.println(); - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] noBandwitchAddress = ecKey1.getAddress(); - String noBandwitch = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - PublicMethed.printAddress(lowBalTest); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test - public void testCreateAccount2() { - Account noCreateAccount = queryAccount(lowBalTest, blockingStubFull); - if (noCreateAccount.getAccountName().isEmpty()) { - Assert.assertTrue(PublicMethed.freezeBalance(fromAddress, 10000000, 3, testKey002, - blockingStubFull)); - //Assert.assertTrue(sendCoin2(lowBalAddress, 1L, fromAddress, testKey002)); - GrpcAPI.Return ret1 = sendCoin2(lowBalAddress, 1000000L, fromAddress, testKey002); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - - //Assert.assertTrue(Sendcoin(Low_Bal_ADDRESS, 1000000L, fromAddress, testKey002)); - noCreateAccount = queryAccount(lowBalTest, blockingStubFull); - logger.info(Long.toString(noCreateAccount.getBalance())); - //Assert.assertTrue(noCreateAccount.getBalance() == 1); - - //TestVoteToNonWitnessAccount - String voteStr = Base58.encode58Check(lowBalAddress); - - HashMap voteToNonWitnessAccount = new HashMap(); - voteToNonWitnessAccount.put(voteStr, "3"); - - HashMap voteToInvaildAddress = new HashMap(); - voteToInvaildAddress.put("27cu1ozb4mX3m2afY68FSAqn3HmMp815d48SS", "4"); - - //TQkJsN2Q2sZV9H2dQ5x2rSneKNyLQgegVv - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] lowBalAddress2 = ecKey2.getAddress(); - - ret1 = PublicMethed.sendcoin2(lowBalAddress2, 21245000000L, - fromAddress, testKey002, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.SUCCESS); - - WitnessList witnesslist = blockingStubFull - .listWitnesses(GrpcAPI.EmptyMessage.newBuilder().build()); - Optional result = Optional.ofNullable(witnesslist); - WitnessList witnessList = result.get(); - if (result.get().getWitnessesCount() < 6) { - String createUrl1 = "adfafds"; - byte[] createUrl = createUrl1.getBytes(); - String lowBalTest2 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ret1 = createWitness2(lowBalAddress2, createUrl, lowBalTest2); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - String voteStr1 = Base58.encode58Check(lowBalAddress2); - HashMap voteToWitAddress = new HashMap(); - voteToWitAddress.put(voteStr1, "1"); - PublicMethed.printAddress(lowBalTest); - ret1 = voteWitness2(voteToWitAddress, fromAddress, testKey002); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - //logger.info("vote to non witness account ok!!!"); - } - - //normal freezeBalance - //Assert.assertTrue(freezeBalance2(fromAddress, 10000000L, 3L, testKey002)) - ret1 = freezeBalance2(fromAddress, 100000000L, 3L, testKey002); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - - //vote To NonWitnessAccount - ret1 = voteWitness2(voteToNonWitnessAccount, fromAddress, testKey002); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - //vote to InvaildAddress - ret1 = voteWitness2(voteToInvaildAddress, fromAddress, testKey002); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : VoteNumber must more than 0"); - - } else { - logger.info( - "Please confirm wither the create account test is pass, or you will do it by manual"); - } - } - - @Test(enabled = true) - public void testUpdateAccount2() { - Account tryToUpdateAccount = queryAccount(lowBalTest, blockingStubFull); - if (tryToUpdateAccount.getAccountName().isEmpty()) { - GrpcAPI.Return ret1 = updateAccount2(lowBalAddress, mostLongNamePlusOneChar.getBytes(), - lowBalTest); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Invalid accountName"); - - ret1 = updateAccount2(lowBalAddress, "".getBytes(), lowBalTest); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : This name is existed"); - - System.out.println("dingwei2:"); - ret1 = updateAccount2(lowBalAddress, mostLongName.getBytes(), lowBalTest); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : This name is existed"); - - ret1 = updateAccount2(lowBalAddress, "secondUpdateName".getBytes(), lowBalTest); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : This name is existed"); - - } - } - - @Test(enabled = true) - public void testNoBalanceCreateAssetIssue2() { - Account lowaccount = queryAccount(lowBalTest, blockingStubFull); - if (lowaccount.getBalance() > 0) { - Assert.assertTrue(sendCoin(toAddress, lowaccount.getBalance(), lowBalAddress, lowBalTest)); - } - - System.out.println("1111112222"); - GrpcAPI.Return ret1 = PublicMethed.createAssetIssue2(lowBalAddress, name, TotalSupply, 1, 1, - now + 100000000L, now + 10000000000L, 2, description, url, 10000L, - 10000L, 1L, 1L, lowBalTest, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : No enough balance for fee!"); - logger.info("nobalancecreateassetissue"); - } - - @Test(enabled = true) - public void testNoBalanceTransferTrx2() { - //Send Coin failed when there is no enough balance. - Assert.assertFalse(sendCoin(toAddress, 100000000000000000L, lowBalAddress, lowBalTest)); - } - - @Test(enabled = true) - public void testNoBalanceCreateWitness2() { - //Apply to be super witness failed when no enough balance. - //Assert.assertFalse(createWitness2(lowBalAddress, fromAddress, lowBalTest)); - System.out.println("1111222333:" + lowBalAddress); - GrpcAPI.Return ret1 = createWitness2(lowBalAddress, fromAddress, lowBalTest); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : balance < AccountUpgradeCost"); - - } - - @Test(enabled = true) - public void testNoFreezeBalanceToUnfreezeBalance2() { - //Unfreeze account failed when no freeze balance - Account noFreezeAccount = queryAccount(lowBalTest, blockingStubFull); - if (noFreezeAccount.getFrozenCount() == 0) { - GrpcAPI.Return ret1 = unFreezeBalance2(lowBalAddress, lowBalTest); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : no frozenBalance(BANDWIDTH)"); - } else { - logger.info("This account has freeze balance, please test this case for manual"); - } - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean createWitness(byte[] owner, byte[] url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - WitnessContract.WitnessCreateContract.Builder builder = WitnessContract.WitnessCreateContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setUrl(ByteString.copyFrom(url)); - WitnessContract.WitnessCreateContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createWitness(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - return response.getResult(); - } - - /** - * constructor. - */ - - public GrpcAPI.Return createWitness2(byte[] owner, byte[] url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - WitnessContract.WitnessCreateContract.Builder builder = WitnessContract.WitnessCreateContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setUrl(ByteString.copyFrom(url)); - WitnessContract.WitnessCreateContract contract = builder.build(); - GrpcAPI.TransactionExtention transactionExtention = blockingStubFull.createWitness2(contract); - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - GrpcAPI.Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - Protocol.Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (!response.getResult()) { - return response; - } - return ret; - } - - /** - * constructor. - */ - - public Boolean sendCoin(byte[] to, long amount, byte[] owner, String priKey) { - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - BalanceContract.TransferContract.Builder builder = BalanceContract.TransferContract - .newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - BalanceContract.TransferContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createTransaction(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (!response.getResult()) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - } - return response.getResult(); - } - - /** - * constructor. - */ - - public GrpcAPI.Return sendCoin2(byte[] to, long amount, byte[] owner, String priKey) { - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - BalanceContract.TransferContract.Builder builder = BalanceContract.TransferContract - .newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - BalanceContract.TransferContract contract = builder.build(); - GrpcAPI.TransactionExtention transactionExtention = blockingStubFull - .createTransaction2(contract); - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - - GrpcAPI.Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - - Protocol.Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return response; - } - return ret; - } - - /** - * constructor. - */ - - public Boolean createAssetIssue(byte[] address, String name, Long totalSupply, Integer trxNum, - Integer icoNum, Long startTime, Long endTime, - Integer voteScore, String description, String url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - try { - AssetIssueContractOuterClass.AssetIssueContract.Builder builder = - AssetIssueContractOuterClass.AssetIssueContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(TotalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - - Protocol.Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("Please check!!! transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info("Please check!!! response.getresult==false"); - return false; - } else { - logger.info(name); - return true; - } - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - /** - * constructor. - */ - - public Account queryAccount(String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Protocol.Transaction signTransaction(ECKey ecKey, Protocol.Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - - public boolean updateAccount(byte[] addressBytes, byte[] accountNameBytes, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - AccountUpdateContract.Builder builder = AccountUpdateContract.newBuilder(); - ByteString basAddress = ByteString.copyFrom(addressBytes); - ByteString bsAccountName = ByteString.copyFrom(accountNameBytes); - - builder.setAccountName(bsAccountName); - builder.setOwnerAddress(basAddress); - - AccountUpdateContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.updateAccount(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("Please check!!! transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info("Please check!!! response.getresult==false"); - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - logger.info(name); - return true; - } - } - - /** - * constructor. - */ - - public GrpcAPI.Return updateAccount2(byte[] addressBytes, byte[] accountNameBytes, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - AccountUpdateContract.Builder builder = AccountUpdateContract.newBuilder(); - ByteString basAddreess = ByteString.copyFrom(addressBytes); - ByteString bsAccountName = ByteString.copyFrom(accountNameBytes); - - builder.setAccountName(bsAccountName); - builder.setOwnerAddress(basAddreess); - - AccountUpdateContract contract = builder.build(); - GrpcAPI.TransactionExtention transactionExtention = blockingStubFull.updateAccount2(contract); - - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - GrpcAPI.Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - Protocol.Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info("Please check!!! response.getresult==false"); - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return response; - } else { - logger.info(name); - return response; - } - } - - /** - * constructor. - */ - - public boolean unFreezeBalance(byte[] address, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - BalanceContract.UnfreezeBalanceContract.Builder builder = - BalanceContract.UnfreezeBalanceContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess); - - BalanceContract.UnfreezeBalanceContract contract = builder.build(); - - Protocol.Transaction transaction = blockingStubFull.unfreezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public GrpcAPI.Return unFreezeBalance2(byte[] address, String priKey) { - //byte[] address = address; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - BalanceContract.UnfreezeBalanceContract.Builder builder = - BalanceContract.UnfreezeBalanceContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess); - - BalanceContract.UnfreezeBalanceContract contract = builder.build(); - GrpcAPI.TransactionExtention transactionExtention = blockingStubFull.unfreezeBalance2(contract); - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - GrpcAPI.Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - Protocol.Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return response; - } - return ret; - } - - /** - * constructor. - */ - - public Boolean voteWitness(HashMap witness, byte[] address, String priKey) { - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - WitnessContract.VoteWitnessContract.Builder builder = WitnessContract.VoteWitnessContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - for (String addressBase58 : witness.keySet()) { - String value = witness.get(addressBase58); - long count = Long.parseLong(value); - WitnessContract.VoteWitnessContract.Vote.Builder voteBuilder = - WitnessContract.VoteWitnessContract.Vote - .newBuilder(); - byte[] addRess = WalletClient.decodeFromBase58Check(addressBase58); - if (addRess == null) { - return false; - } - voteBuilder.setVoteAddress(ByteString.copyFrom(addRess)); - voteBuilder.setVoteCount(count); - builder.addVotes(voteBuilder.build()); - } - - WitnessContract.VoteWitnessContract contract = builder.build(); - - Protocol.Transaction transaction = blockingStubFull.voteWitnessAccount(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - logger.info("response.getresult() == false"); - return false; - } - return true; - } - - /** - * constructor. - */ - - public GrpcAPI.Return voteWitness2(HashMap witness, byte[] address, - String priKey) { - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - WitnessContract.VoteWitnessContract.Builder builder = WitnessContract.VoteWitnessContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - for (String addressBase58 : witness.keySet()) { - String value = witness.get(addressBase58); - long count = Long.parseLong(value); - WitnessContract.VoteWitnessContract.Vote.Builder voteBuilder = - WitnessContract.VoteWitnessContract.Vote - .newBuilder(); - byte[] addRess = WalletClient.decodeFromBase58Check(addressBase58); - if (addRess == null) { - continue; - } - voteBuilder.setVoteAddress(ByteString.copyFrom(addRess)); - voteBuilder.setVoteCount(count); - builder.addVotes(voteBuilder.build()); - } - - WitnessContract.VoteWitnessContract contract = builder.build(); - - GrpcAPI.TransactionExtention transactionExtention = blockingStubFull - .voteWitnessAccount2(contract); - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - GrpcAPI.Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - Protocol.Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - logger.info("response.getresult() == false"); - return response; - } - return ret; - } - - /** - * constructor. - */ - - public Boolean freezeBalance(byte[] addRess, long freezeBalance, long freezeDuration, - String priKey) { - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - BalanceContract.FreezeBalanceContract.Builder builder = BalanceContract.FreezeBalanceContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration); - - BalanceContract.FreezeBalanceContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - - return response.getResult(); - - - } - - /** - * constructor. - */ - - public GrpcAPI.Return freezeBalance2(byte[] addRess, long freezeBalance, long freezeDuration, - String priKey) { - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - BalanceContract.FreezeBalanceContract.Builder builder = BalanceContract.FreezeBalanceContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration); - - BalanceContract.FreezeBalanceContract contract = builder.build(); - GrpcAPI.TransactionExtention transactionExtention = blockingStubFull.freezeBalance2(contract); - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - GrpcAPI.Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - Protocol.Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - return response; - } - return ret; - } - - class AccountComparator implements Comparator { - - public int compare(Object o1, Object o2) { - return Long.compare(((Account) o2).getBalance(), ((Account) o1).getBalance()); - } - } - - -} - - - diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/UpdateAsset2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/UpdateAsset2Test.java deleted file mode 100644 index 5725ba6e625..00000000000 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/UpdateAsset2Test.java +++ /dev/null @@ -1,467 +0,0 @@ -package stest.tron.wallet.newaddinterface2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.AssetIssueContractOuterClass; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class UpdateAsset2Test { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = now; - private static final long sendAmount = 10000000000L; - private static final String tooLongDescription = - "1qazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcv" - + "qazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswe" - + "dcvqazxswedcvqazxswedcvqazxswedcvqazxswedcv"; - private static final String tooLongUrl = "qaswqaswqaswqaswqaswqaswqaswqaswqaswqaswqaswqas" - + "wqaswqasw1qazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazx" - + "swedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedc" - + "vqazxswedcvqazxswedcvqazxswedcvqazxswedcv"; - private static String name = "testAssetIssue010_" + Long.toString(now); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = "just-test"; - String url = "https://github.com/tronprotocol/wallet-cli/"; - String updateDescription = "This is test for update asset issue, case AssetIssue_010"; - String updateUrl = "www.updateassetissue.010.cn"; - Long freeAssetNetLimit = 1000L; - Long publicFreeAssetNetLimit = 1000L; - Long updateFreeAssetNetLimit = 10001L; - Long updatePublicFreeAssetNetLimit = 10001L; - //get account - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] asset010Address = ecKey.getAddress(); - String testKeyForAssetIssue010 = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - - } - - @Test(enabled = true) - public void testUpdateAssetIssue2() { - //Sendcoin to this account - ByteString addressBS1 = ByteString.copyFrom(asset010Address); - Account request1 = Account.newBuilder().setAddress(addressBS1).build(); - GrpcAPI.AssetIssueList assetIssueList1 = blockingStubFull - .getAssetIssueByAccount(request1); - Optional queryAssetByAccount = Optional.ofNullable(assetIssueList1); - if (queryAssetByAccount.get().getAssetIssueCount() == 0) { - //Assert.assertTrue(PublicMethed.freezeBalance(fromAddress,10000000L,3, - // testKey002,blockingStubFull)); - Assert.assertTrue(PublicMethed - .sendcoin(asset010Address, sendAmount, fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed - .freezeBalance(asset010Address, 200000000L, 3, testKeyForAssetIssue010, - blockingStubFull)); - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - Assert.assertTrue(PublicMethed.createAssetIssue(asset010Address, name, totalSupply, 1, 1, - start, end, 1, description, url, freeAssetNetLimit, publicFreeAssetNetLimit, - 1L, 1L, testKeyForAssetIssue010, blockingStubFull)); - } else { - logger.info("This account already create an assetisue"); - Optional queryAssetByAccount1 = Optional.ofNullable(assetIssueList1); - name = ByteArray.toStr(queryAssetByAccount1.get().getAssetIssue(0).getName().toByteArray()); - Assert.assertTrue(PublicMethed - .updateAsset(asset010Address, description.getBytes(), url.getBytes(), freeAssetNetLimit, - publicFreeAssetNetLimit, testKeyForAssetIssue010, blockingStubFull)); - } - - //Query the description and url,freeAssetNetLimit and publicFreeAssetNetLimit - ByteString assetNameBs = ByteString.copyFrom(name.getBytes()); - GrpcAPI.BytesMessage request = GrpcAPI.BytesMessage.newBuilder().setValue(assetNameBs).build(); - AssetIssueContractOuterClass.AssetIssueContract assetIssueByName = blockingStubFull - .getAssetIssueByName(request); - - Assert.assertTrue( - ByteArray.toStr(assetIssueByName.getDescription().toByteArray()).equals(description)); - Assert.assertTrue(ByteArray.toStr(assetIssueByName.getUrl().toByteArray()).equals(url)); - Assert.assertTrue(assetIssueByName.getFreeAssetNetLimit() == freeAssetNetLimit); - Assert.assertTrue(assetIssueByName.getPublicFreeAssetNetLimit() == publicFreeAssetNetLimit); - - //Test update asset issue - Return ret1 = PublicMethed - .updateAsset2(asset010Address, updateDescription.getBytes(), updateUrl.getBytes(), - updateFreeAssetNetLimit, - updatePublicFreeAssetNetLimit, testKeyForAssetIssue010, blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - - //After update asset issue ,query the description and url, - // freeAssetNetLimit and publicFreeAssetNetLimit - assetNameBs = ByteString.copyFrom(name.getBytes()); - request = GrpcAPI.BytesMessage.newBuilder().setValue(assetNameBs).build(); - assetIssueByName = blockingStubFull.getAssetIssueByName(request); - - Assert.assertTrue( - ByteArray.toStr(assetIssueByName.getDescription().toByteArray()).equals(updateDescription)); - Assert.assertTrue(ByteArray.toStr(assetIssueByName.getUrl().toByteArray()).equals(updateUrl)); - Assert.assertTrue(assetIssueByName.getFreeAssetNetLimit() == updateFreeAssetNetLimit); - Assert - .assertTrue(assetIssueByName.getPublicFreeAssetNetLimit() == updatePublicFreeAssetNetLimit); - } - - @Test(enabled = true) - public void testUpdateAssetIssueExcption2() { - //Test update asset issue for wrong parameter - //publicFreeAssetNetLimit is -1 - Return ret1 = PublicMethed - .updateAsset2(asset010Address, updateDescription.getBytes(), updateUrl.getBytes(), - updateFreeAssetNetLimit, - -1L, testKeyForAssetIssue010, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Invalid PublicFreeAssetNetLimit"); - //publicFreeAssetNetLimit is 0 - ret1 = PublicMethed - .updateAsset2(asset010Address, updateDescription.getBytes(), updateUrl.getBytes(), - updateFreeAssetNetLimit, - 0, testKeyForAssetIssue010, blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - //FreeAssetNetLimit is -1 - ret1 = PublicMethed - .updateAsset2(asset010Address, updateDescription.getBytes(), updateUrl.getBytes(), -1, - publicFreeAssetNetLimit, testKeyForAssetIssue010, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Invalid FreeAssetNetLimit"); - //FreeAssetNetLimit is 0 - ret1 = PublicMethed - .updateAsset2(asset010Address, updateDescription.getBytes(), updateUrl.getBytes(), 0, - publicFreeAssetNetLimit, testKeyForAssetIssue010, blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - //Description is null - ret1 = PublicMethed - .updateAsset2(asset010Address, "".getBytes(), updateUrl.getBytes(), freeAssetNetLimit, - publicFreeAssetNetLimit, testKeyForAssetIssue010, blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - //Url is null - ret1 = PublicMethed - .updateAsset2(asset010Address, description.getBytes(), "".getBytes(), freeAssetNetLimit, - publicFreeAssetNetLimit, testKeyForAssetIssue010, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), "Contract validate error : Invalid url"); - //Too long discription - ret1 = PublicMethed - .updateAsset2(asset010Address, tooLongDescription.getBytes(), url.getBytes(), - freeAssetNetLimit, - publicFreeAssetNetLimit, testKeyForAssetIssue010, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : Invalid description"); - //Too long URL - ret1 = PublicMethed - .updateAsset2(asset010Address, description.getBytes(), tooLongUrl.getBytes(), - freeAssetNetLimit, - publicFreeAssetNetLimit, testKeyForAssetIssue010, blockingStubFull); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), "Contract validate error : Invalid url"); - } - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - Return ret1 = PublicMethed - .updateAsset2(asset010Address, description.getBytes(), url.getBytes(), 1999999999, - 199, testKeyForAssetIssue010, blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean createAssetIssue(byte[] address, String name, Long totalSupply, Integer trxNum, - Integer icoNum, Long startTime, Long endTime, - Integer voteScore, String description, String url, Long fronzenAmount, Long frozenDay, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account search = PublicMethed.queryAccount(priKey, blockingStubFull); - - try { - AssetIssueContractOuterClass.AssetIssueContract.Builder builder = - AssetIssueContractOuterClass.AssetIssueContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - AssetIssueContractOuterClass.AssetIssueContract.FrozenSupply.Builder frozenBuilder = - AssetIssueContractOuterClass.AssetIssueContract.FrozenSupply - .newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - builder.addFrozenSupply(0, frozenBuilder); - - Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (!response.getResult()) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - logger.info(name); - return true; - } - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - - public boolean transferAsset(byte[] to, byte[] assertName, long amount, byte[] address, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - AssetIssueContractOuterClass.TransferAssetContract.Builder builder = - AssetIssueContractOuterClass.TransferAssetContract - .newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(address); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - AssetIssueContractOuterClass.TransferAssetContract contract = builder.build(); - Transaction transaction = blockingStubFull.transferAsset(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return false; - } else { - Account search = queryAccount(ecKey, blockingStubFull); - return true; - } - - } - - /** - * constructor. - */ - - public boolean unFreezeAsset(byte[] addRess, String priKey) { - byte[] address = addRess; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - AssetIssueContractOuterClass.UnfreezeAssetContract.Builder builder = - AssetIssueContractOuterClass.UnfreezeAssetContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess); - - AssetIssueContractOuterClass.UnfreezeAssetContract contract = builder.build(); - - Transaction transaction = blockingStubFull.unfreezeAsset(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - return true; - } - } - - /** - * constructor. - */ - - public boolean participateAssetIssue(byte[] to, byte[] assertName, long amount, byte[] from, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - AssetIssueContractOuterClass.ParticipateAssetIssueContract.Builder builder = - AssetIssueContractOuterClass.ParticipateAssetIssueContract - .newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsName = ByteString.copyFrom(assertName); - ByteString bsOwner = ByteString.copyFrom(from); - builder.setToAddress(bsTo); - builder.setAssetName(bsName); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - AssetIssueContractOuterClass.ParticipateAssetIssueContract contract = builder.build(); - - Transaction transaction = blockingStubFull.participateAssetIssue(contract); - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (!response.getResult()) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - logger.info(name); - return true; - } - } - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/VoteWitnessAccount2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/VoteWitnessAccount2Test.java deleted file mode 100644 index 725b4055782..00000000000 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/VoteWitnessAccount2Test.java +++ /dev/null @@ -1,585 +0,0 @@ -package stest.tron.wallet.newaddinterface2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.BalanceContract.FreezeBalanceContract; -import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; -import org.tron.protos.contract.WitnessContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class VoteWitnessAccount2Test { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private ManagedChannel channelFull = null; - private ManagedChannel searchChannelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletGrpc.WalletBlockingStub searchBlockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String searchFullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - - WalletClient.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - logger.info("Pre fix byte ===== " + WalletClient.getAddressPreFixByte()); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext() - .build(); - searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); - - } - - @Test(enabled = true) - public void testVoteWitness2() { - //get account - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] lowBalAddress = ecKey.getAddress(); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] lowBalAddress2 = ecKey2.getAddress(); - String lowBalTest2 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - //sendcoin - Return ret1 = PublicMethed.sendcoin2(lowBalAddress, 21245000000L, - fromAddress, testKey002, blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - ret1 = PublicMethed.sendcoin2(lowBalAddress2, 21245000000L, - fromAddress, testKey002, blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - - //assetissue - String createUrl1 = "adfafds"; - byte[] createUrl = createUrl1.getBytes(); - String lowBalTest = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - ret1 = createWitness2(lowBalAddress, createUrl, lowBalTest); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - - String voteStr1 = Base58.encode58Check(lowBalAddress); - - //Base58.encode58Check(getFinalAddress(key); - //String voteStr = "TB4B1RMhoPeivkj4Hebm6tttHjRY9yQFes"; - String voteStr = voteStr1; - HashMap smallVoteMap = new HashMap(); - smallVoteMap.put(voteStr, "1"); - HashMap wrongVoteMap = new HashMap(); - wrongVoteMap.put(voteStr, "-1"); - HashMap zeroVoteMap = new HashMap(); - zeroVoteMap.put(voteStr, "0"); - - HashMap veryLargeMap = new HashMap(); - veryLargeMap.put(voteStr, "1000000000"); - HashMap wrongDropMap = new HashMap(); - wrongDropMap.put(voteStr, "10000000000000000"); - - //Vote failed due to no freeze balance. - //Assert.assertFalse(VoteWitness(smallVoteMap, NO_FROZEN_ADDRESS, no_frozen_balance_testKey)); - - //Freeze balance to get vote ability. - ret1 = PublicMethed.freezeBalance2(fromAddress, 10000000L, 3L, testKey002, blockingStubFull); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - //Vote failed when the vote is large than the freeze balance. - ret1 = voteWitness2(veryLargeMap, fromAddress, testKey002); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - - //Vote failed due to 0 vote. - ret1 = voteWitness2(zeroVoteMap, fromAddress, testKey002); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : vote count must be greater than 0"); - - ret1 = voteWitness2(wrongVoteMap, fromAddress, testKey002); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : vote count must be greater than 0"); - - ret1 = voteWitness2(wrongDropMap, fromAddress, testKey002); - Assert.assertEquals(ret1.getCode(), Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - "Contract validate error : overflow: checkedMultiply(10000000000000000, 1000000)"); - ret1 = voteWitness2(smallVoteMap, fromAddress, testKey002); - Assert.assertEquals(ret1.getCode(), Return.response_code.SUCCESS); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), ""); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (searchChannelFull != null) { - searchChannelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean voteWitness(HashMap witness, byte[] addRess, String priKey) { - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account beforeVote = queryAccount(ecKey, blockingStubFull); - Long beforeVoteNum = 0L; - if (beforeVote.getVotesCount() != 0) { - beforeVoteNum = beforeVote.getVotes(0).getVoteCount(); - } - - WitnessContract.VoteWitnessContract.Builder builder = WitnessContract.VoteWitnessContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(addRess)); - for (String addressBase58 : witness.keySet()) { - - WitnessContract.VoteWitnessContract.Vote.Builder voteBuilder = - WitnessContract.VoteWitnessContract.Vote - .newBuilder(); - byte[] address = WalletClient.decodeFromBase58Check(addressBase58); - logger.info("address ====== " + ByteArray.toHexString(address)); - String value = witness.get(addressBase58); - if (address == null) { - continue; - } - voteBuilder.setVoteAddress(ByteString.copyFrom(address)); - long count = Long.parseLong(value); - voteBuilder.setVoteCount(count); - builder.addVotes(voteBuilder.build()); - } - - WitnessContract.VoteWitnessContract contract = builder.build(); - - Transaction transaction = blockingStubFull.voteWitnessAccount(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - - if (!response.getResult()) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - Account afterVote = queryAccount(ecKey, searchBlockingStubFull); - //Long afterVoteNum = afterVote.getVotes(0).getVoteCount(); - for (String key : witness.keySet()) { - for (int j = 0; j < afterVote.getVotesCount(); j++) { - logger.info(Long.toString(Long.parseLong(witness.get(key)))); - logger.info(key); - if (key.equals("TB4B1RMhoPeivkj4Hebm6tttHjRY9yQFes")) { - logger.info("catch it"); - logger.info(Long.toString(afterVote.getVotes(j).getVoteCount())); - logger.info(Long.toString(Long.parseLong(witness.get(key)))); - Assert - .assertTrue(afterVote.getVotes(j).getVoteCount() == Long.parseLong(witness.get(key))); - } - - } - } - return true; - } - - /** - * constructor. - */ - - public GrpcAPI.Return createWitness2(byte[] owner, byte[] url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - WitnessContract.WitnessCreateContract.Builder builder = WitnessContract.WitnessCreateContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setUrl(ByteString.copyFrom(url)); - WitnessContract.WitnessCreateContract contract = builder.build(); - - GrpcAPI.TransactionExtention transactionExtention = blockingStubFull.createWitness2(contract); - - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - GrpcAPI.Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - Protocol.Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - return response; - } - return ret; - - } - - /** - * constructor. - */ - - public Return voteWitness2(HashMap witness, byte[] addRess, String priKey) { - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account beforeVote = queryAccount(ecKey, blockingStubFull); - Long beforeVoteNum = 0L; - if (beforeVote.getVotesCount() != 0) { - beforeVoteNum = beforeVote.getVotes(0).getVoteCount(); - } - - WitnessContract.VoteWitnessContract.Builder builder = WitnessContract.VoteWitnessContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(addRess)); - for (String addressBase58 : witness.keySet()) { - - WitnessContract.VoteWitnessContract.Vote.Builder voteBuilder = - WitnessContract.VoteWitnessContract.Vote - .newBuilder(); - byte[] address = WalletClient.decodeFromBase58Check(addressBase58); - logger.info("address ====== " + ByteArray.toHexString(address)); - String value = witness.get(addressBase58); - if (address == null) { - continue; - } - voteBuilder.setVoteAddress(ByteString.copyFrom(address)); - long count = Long.parseLong(value); - voteBuilder.setVoteCount(count); - builder.addVotes(voteBuilder.build()); - } - - WitnessContract.VoteWitnessContract contract = builder.build(); - - //Transaction transaction = blockingStubFull.voteWitnessAccount(contract); - GrpcAPI.TransactionExtention transactionExtention = blockingStubFull - .voteWitnessAccount2(contract); - - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } else { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return response; - } - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - Account afterVote = queryAccount(ecKey, searchBlockingStubFull); - //Long afterVoteNum = afterVote.getVotes(0).getVoteCount(); - for (String key : witness.keySet()) { - for (int j = 0; j < afterVote.getVotesCount(); j++) { - logger.info(Long.toString(Long.parseLong(witness.get(key)))); - logger.info(key); - if (key.equals("TB4B1RMhoPeivkj4Hebm6tttHjRY9yQFes")) { - logger.info("catch it"); - logger.info(Long.toString(afterVote.getVotes(j).getVoteCount())); - logger.info(Long.toString(Long.parseLong(witness.get(key)))); - Assert - .assertTrue(afterVote.getVotes(j).getVoteCount() == Long.parseLong(witness.get(key))); - } - - } - } - return ret; - } - - /** - * constructor. - */ - - public Boolean freezeBalance(byte[] addRess, long freezeBalance, long freezeDuration, - String priKey) { - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account beforeFronzen = queryAccount(ecKey, blockingStubFull); - - Long beforeFrozenBalance = 0L; - //Long beforeBandwidth = beforeFronzen.getBandwidth(); - if (beforeFronzen.getFrozenCount() != 0) { - beforeFrozenBalance = beforeFronzen.getFrozen(0).getFrozenBalance(); - //beforeBandwidth = beforeFronzen.getBandwidth(); - //logger.info(Long.toString(beforeFronzen.getBandwidth())); - logger.info(Long.toString(beforeFronzen.getFrozen(0).getFrozenBalance())); - } - - FreezeBalanceContract.Builder builder = FreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration); - - FreezeBalanceContract contract = builder.build(); - - Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - return false; - } - - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Block searchCurrentBlock = searchBlockingStubFull.getNowBlock(GrpcAPI - .EmptyMessage.newBuilder().build()); - Integer wait = 0; - while (searchCurrentBlock.getBlockHeader().getRawData().getNumber() - < currentBlock.getBlockHeader().getRawData().getNumber() + 1 && wait < 30) { - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - logger.info("Another fullnode didn't syn the first fullnode data"); - searchCurrentBlock = searchBlockingStubFull.getNowBlock(GrpcAPI - .EmptyMessage.newBuilder().build()); - wait++; - if (wait == 9) { - logger.info("Didn't syn,skip to next case."); - } - } - - Account afterFronzen = queryAccount(ecKey, searchBlockingStubFull); - Long afterFrozenBalance = afterFronzen.getFrozen(0).getFrozenBalance(); - //Long afterBandwidth = afterFronzen.getBandwidth(); - //logger.info(Long.toString(afterFronzen.getBandwidth())); - //logger.info(Long.toString(afterFronzen.getFrozen(0).getFrozenBalance())); - //logger.info(Integer.toString(search.getFrozenCount())); - logger.info( - "afterfrozenbalance =" + Long.toString(afterFrozenBalance) + "beforefrozenbalance = " - + beforeFrozenBalance + "freezebalance = " + Long.toString(freezeBalance)); - //logger.info("afterbandwidth = " + Long.toString(afterBandwidth) + " beforebandwidth = - // " + Long.toString(beforeBandwidth)); - //if ((afterFrozenBalance - beforeFrozenBalance != freezeBalance) || - // (freezeBalance * frozen_duration -(afterBandwidth - beforeBandwidth) !=0)){ - // logger.info("After 20 second, two node still not synchronous"); - // } - Assert.assertTrue(afterFrozenBalance - beforeFrozenBalance == freezeBalance); - //Assert.assertTrue(freezeBalance * frozen_duration - (afterBandwidth - - // beforeBandwidth) <= 1000000); - return true; - - - } - - /** - * constructor. - */ - - public boolean unFreezeBalance(byte[] addRess, String priKey) { - byte[] address = addRess; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account search = queryAccount(ecKey, blockingStubFull); - - UnfreezeBalanceContract.Builder builder = UnfreezeBalanceContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess); - - UnfreezeBalanceContract contract = builder.build(); - - Transaction transaction = blockingStubFull.unfreezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - return response.getResult(); - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/newaddinterface2/WithdrawBalance2Test.java b/framework/src/test/java/stest/tron/wallet/newaddinterface2/WithdrawBalance2Test.java deleted file mode 100644 index 4442fd448fe..00000000000 --- a/framework/src/test/java/stest/tron/wallet/newaddinterface2/WithdrawBalance2Test.java +++ /dev/null @@ -1,308 +0,0 @@ -package stest.tron.wallet.newaddinterface2; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.BalanceContract.WithdrawBalanceContract; -import org.tron.protos.contract.WitnessContract.VoteWitnessContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class WithdrawBalance2Test { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - - private final String notWitnessTestKey = - "8CB4480194192F30907E14B52498F594BD046E21D7C4D8FE866563A6760AC891"; - - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] notWitness = PublicMethed.getFinalAddress(notWitnessTestKey); - - private ManagedChannel channelFull = null; - private ManagedChannel searchChannelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletGrpc.WalletBlockingStub searchBlockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String searchFullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext() - .build(); - searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); - - } - - @Test - public void testWithdrawBalance2() { - //Withdraw failed when you are not witness - Return ret1 = withdrawBalance2(notWitness, notWitnessTestKey); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), "Contract validate error : " - + "Account[41688b08971e740d7cecfa5d768f2787c1bb4c1268] is not a witnessAccount"); - - //Withdraw failed when the latest time to withdraw within 1 day. - ret1 = withdrawBalance2(fromAddress, testKey002); - Assert.assertEquals(ret1.getCode(), GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR); - Assert.assertEquals(ret1.getMessage().toStringUtf8(), - " Contract validate error : witnessAccount does not have any allowance"); - } - - /** - * constructor. - */ - - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (searchChannelFull != null) { - searchChannelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public boolean withdrawBalance(byte[] address, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - - WithdrawBalanceContract.Builder builder = WithdrawBalanceContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - builder.setOwnerAddress(byteAddreess); - WithdrawBalanceContract contract = builder.build(); - - Transaction transaction = blockingStubFull.withdrawBalance(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (!response.getResult()) { - return false; - } - logger.info("test withdraw" + priKey); - return true; - } - - /** - * constructor. - */ - - public Return withdrawBalance2(byte[] address, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - - WithdrawBalanceContract.Builder builder = WithdrawBalanceContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - builder.setOwnerAddress(byteAddreess); - WithdrawBalanceContract contract = builder.build(); - - GrpcAPI.TransactionExtention transactionExtention = blockingStubFull.withdrawBalance2(contract); - if (transactionExtention == null) { - return transactionExtention.getResult(); - } - Return ret = transactionExtention.getResult(); - if (!ret.getResult()) { - System.out.println("Code = " + ret.getCode()); - System.out.println("Message = " + ret.getMessage().toStringUtf8()); - return ret; - } - Transaction transaction = transactionExtention.getTransaction(); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - System.out.println("Transaction is empty"); - return transactionExtention.getResult(); - } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - ECKey ecKey = temKey; - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (!response.getResult()) { - return response; - } - logger.info("test withdraw" + priKey); - return ret; - } - - /** - * constructor. - */ - - public Boolean voteWitness(HashMap witness, byte[] address, String priKey) { - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account beforeVote = queryAccount(ecKey, blockingStubFull); - Long beforeVoteNum = 0L; - if (beforeVote.getVotesCount() != 0) { - beforeVoteNum = beforeVote.getVotes(0).getVoteCount(); - } - - VoteWitnessContract.Builder builder = VoteWitnessContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - for (String addressBase58 : witness.keySet()) { - String value = witness.get(addressBase58); - long count = Long.parseLong(value); - VoteWitnessContract.Vote.Builder voteBuilder = VoteWitnessContract.Vote - .newBuilder(); - byte[] addRess = WalletClient.decodeFromBase58Check(addressBase58); - if (addRess == null) { - continue; - } - voteBuilder.setVoteAddress(ByteString.copyFrom(address)); - voteBuilder.setVoteCount(count); - builder.addVotes(voteBuilder.build()); - } - - VoteWitnessContract contract = builder.build(); - - Transaction transaction = blockingStubFull.voteWitnessAccount(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - - if (!response.getResult()) { - return false; - } - Account afterVote = queryAccount(ecKey, searchBlockingStubFull); - //Long afterVoteNum = afterVote.getVotes(0).getVoteCount(); - for (String key : witness.keySet()) { - for (int j = 0; j < afterVote.getVotesCount(); j++) { - if (key.equals(afterVote.getVotes(j).getVoteAddress())) { - Long afterVoteNum = Long.parseLong(witness.get(key)); - Assert.assertTrue(afterVoteNum == afterVote.getVotes(j).getVoteCount()); - logger.info("test equal vote"); - } - } - } - return true; - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/ContractEvent001.java b/framework/src/test/java/stest/tron/wallet/onlinestress/ContractEvent001.java deleted file mode 100644 index 9ff98b87be2..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/ContractEvent001.java +++ /dev/null @@ -1,757 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import com.alibaba.fastjson.JSONObject; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.Charset; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.impl.conn.PoolingClientConnectionManager; -import org.apache.http.params.CoreConnectionPNames; -import org.apache.http.util.EntityUtils; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.crypto.SignInterface; -import org.tron.common.crypto.SignUtils; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import org.zeromq.ZMQ; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.JsonRpcBase; -import stest.tron.wallet.common.client.utils.PublicMethed; -import zmq.ZMQ.Event; - -@Slf4j -public class ContractEvent001 extends JsonRpcBase { - - private final String testKey002 = - Configuration.getByPath("testng.conf").getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = - Configuration.getByPath("testng.conf").getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - String txid; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] event001Address = ecKey1.getAddress(); - String event001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] event002Address = ecKey2.getAddress(); - String event002Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - // byte[] contractAddress = null; - String param = "10"; - static HttpResponse response; - static JSONObject responseContent; - private String fullnode = - Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list").get(0); - private String fullnode1 = - Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = - Configuration.getByPath("testng.conf").getLong("defaultParameter.maxFeeLimit"); - - - - /** constructor. */ - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext().build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1).usePlaintext().build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - @Test(enabled = true) - public void test1ContractEventAndLog() { - ecKey1 = new ECKey(Utils.getRandom()); - event001Address = ecKey1.getAddress(); - event001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.printAddress(event001Key); - - ecKey2 = new ECKey(Utils.getRandom()); - event002Address = ecKey2.getAddress(); - event002Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - PublicMethed.printAddress(event001Key); - PublicMethed.printAddress(testKey002); - - Assert.assertTrue( - PublicMethed.sendcoin( - event001Address, maxFeeLimit * 30, fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue( - PublicMethed.sendcoin( - event002Address, maxFeeLimit * 30, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - - AccountResourceMessage accountResource = - PublicMethed.getAccountResource(event001Address, blockingStubFull); - Long energyLimit = accountResource.getEnergyLimit(); - Long energyUsage = accountResource.getEnergyUsed(); - Long balanceBefore = PublicMethed.queryAccount(event001Key, blockingStubFull).getBalance(); - - logger.info("before energy limit is " + Long.toString(energyLimit)); - logger.info("before energy usage is " + Long.toString(energyUsage)); - logger.info("before balance is " + Long.toString(balanceBefore)); - - String contractName = "addressDemo"; - String code = - Configuration.getByPath("testng.conf").getString("code.code_ContractEventAndLog1"); - String abi = Configuration.getByPath("testng.conf").getString("abi.abi_ContractEventAndLog1"); - byte[] contractAddress = - PublicMethed.deployContract( - contractName, - abi, - code, - "", - maxFeeLimit, - 0L, - 50, - null, - event001Key, - event001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi() != null); - - Integer i = 0; - for (i = 0; i < 1; i++) { - txid = - PublicMethed.triggerContract( - contractAddress, - "depositForEventCycle(uint256)", - "100", - false, - 1L, - 100000000L, - event002Address, - event002Key, - blockingStubFull); - logger.info(txid); - - txid = - PublicMethed.triggerContract( - contractAddress, - "depositForLogCycle(uint256)", - "100", - false, - 2L, - 100000000L, - event002Address, - event002Key, - blockingStubFull); - logger.info(txid); - - txid = - PublicMethed.triggerContract( - contractAddress, - "triggerUintEvent()", - "#", - false, - 0, - maxFeeLimit, - event001Address, - event001Key, - blockingStubFull); - logger.info(txid); - - txid = - PublicMethed.triggerContract( - contractAddress, - "triggerintEvent()", - "#", - false, - 0, - maxFeeLimit, - event001Address, - event001Key, - blockingStubFull); - logger.info(txid); - - txid = - PublicMethed.triggerContract( - contractAddress, - "depositForEventAndLog()", - "#", - false, - 1, - maxFeeLimit, - event001Address, - event001Key, - blockingStubFull); - logger.info(txid); - txid = - PublicMethed.triggerContract( - contractAddress, - "depositForEventNoIndex()", - "#", - false, - 0L, - 100000000L, - event001Address, - event001Key, - blockingStubFull); - logger.info(txid); - txid = - PublicMethed.triggerContract( - contractAddress, - "depositForLog()", - "#", - false, - 1L, - 100000000L, - event001Address, - event001Key, - blockingStubFull); - logger.info(txid); - - txid = - PublicMethed.triggerContract( - contractAddress, - "depositForEventNoIndex()", - "#", - false, - 1L, - 100000000L, - event001Address, - event001Key, - blockingStubFull); - logger.info(txid); - - txid = - PublicMethed.triggerContract( - contractAddress, - "depositForEventOneIndex()", - "#", - false, - 1L, - 100000000L, - event001Address, - event001Key, - blockingStubFull); - logger.info(txid); - - txid = - PublicMethed.triggerContract( - contractAddress, - "depositForEventTwoIndex()", - "#", - false, - 2L, - 100000000L, - event001Address, - event001Key, - blockingStubFull); - logger.info(txid); - - txid = - PublicMethed.triggerContract( - contractAddress, - "depositForEvent()", - "#", - false, - 3L, - 100000000L, - event001Address, - event001Key, - blockingStubFull); - logger.info(txid); - - txid = - PublicMethed.triggerContract( - contractAddress, - "depositForEventCycle(uint256)", - "100", - false, - 1L, - 100000000L, - event002Address, - event002Key, - blockingStubFull); - logger.info(txid); - - txid = - PublicMethed.triggerContract( - contractAddress, - "depositForLogCycle(uint256)", - "100", - false, - 2L, - 100000000L, - event002Address, - event002Key, - blockingStubFull); - logger.info(txid); - - txid = - PublicMethed.triggerContract( - contractAddress, - "depositForAnonymousHasLog()", - "#", - false, - 4L, - 100000000L, - event001Address, - event001Key, - blockingStubFull); - logger.info(txid); - - txid = - PublicMethed.triggerContract( - contractAddress, - "depositForAnonymousNoLog()", - "#", - false, - 5L, - 100000000L, - event001Address, - event001Key, - blockingStubFull); - logger.info(txid); - - String param = "\"" + code + "\"" + "," + "\"" + code + "\""; - txid = - PublicMethed.triggerContract( - contractAddress, - "triggerStringEvent(string,string)", - param, - false, - 0L, - 100000000L, - event001Address, - event001Key, - blockingStubFull); - logger.info(txid); - - param = "\"" + "true1" + "\"" + "," + "\"" + "false1" + "\""; - txid = - PublicMethed.triggerContract( - contractAddress, - "triggerBoolEvent(bool,bool)", - param, - false, - 0L, - 100000000L, - event001Address, - event001Key, - blockingStubFull); - logger.info(txid); - String filename = "/Users/wangzihe/Documents/modify_fullnode/java-tron/tooLongString.txt"; - try { - FileReader fr = new FileReader(filename); - InputStreamReader read = new InputStreamReader(new FileInputStream(new File(filename))); - BufferedReader reader = new BufferedReader(read); - String tooLongString = reader.readLine(); - param = "\"" + tooLongString + "\"" + "," + "\"" + tooLongString + "\""; - txid = - PublicMethed.triggerContract( - contractAddress, - "triggerStringEventAnonymous(string,string)", - param, - false, - 0L, - 100000000L, - event001Address, - event001Key, - blockingStubFull); - logger.info(txid); - - txid = - PublicMethed.triggerContract( - contractAddress, - "triggerStringEvent(string,string)", - param, - false, - 0L, - 100000000L, - event001Address, - event001Key, - blockingStubFull); - logger.info(txid); - - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - - contractName = "addressDemo"; - code = Configuration.getByPath("testng.conf").getString("code.code_ContractEventAndLog2"); - abi = Configuration.getByPath("testng.conf").getString("abi.abi_ContractEventAndLog2"); - contractAddress = - PublicMethed.deployContract( - contractName, - abi, - code, - "", - maxFeeLimit, - 0L, - 50, - null, - event001Key, - event001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi() != null); - - txid = - PublicMethed.triggerContract( - contractAddress, - "triggerEventBytes()", - "#", - false, - 0, - maxFeeLimit, - event001Address, - event001Key, - blockingStubFull); - logger.info(txid); - } - - @Test( - enabled = true, - threadPoolSize = 5, - invocationCount = 5, - description = "test eth_getFilterChanges") - public void testEthGetFilterChanges() throws InterruptedException { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] event001Address = ecKey1.getAddress(); - logger.info("event001Address:" + event001Address); - String event001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] event002Address = ecKey2.getAddress(); - logger.info("event002Address:" + event002Address); - String event002Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - PublicMethed.printAddress(event001Key); - PublicMethed.printAddress(testKey002); - - Assert.assertTrue( - PublicMethed.sendcoin( - event001Address, maxFeeLimit * 30, fromAddress, testKey002, blockingStubFull)); - Assert.assertTrue( - PublicMethed.sendcoin( - event002Address, maxFeeLimit * 30, fromAddress, testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - - String contractName = "SolidityTest"; - String filePath = "./src/test/resources/soliditycode/testGetFilterChange.sol"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] contractAddress = - PublicMethed.deployContract( - contractName, - abi, - code, - "", - maxFeeLimit, - 0L, - 50, - null, - event001Key, - event001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi() != null); - logger.info("11111111111111111111111111111111111"); - Thread.sleep(180000); - - long txidNum = 0; - HttpResponse response = getNowBlock(httpFullNode); - JSONObject responseContent = parseResponseContent(response); - long blockBefore = - responseContent.getJSONObject("block_header").getJSONObject("raw_data").getLong("number"); - logger.info("blockBefore:" + blockBefore); - Thread.sleep(180000); - for (int i = 0; i < 5000; i++) { - String txid = - PublicMethed.triggerContract( - contractAddress, - "getResult(uint256)", - param, - false, - 2L, - 100000000L, - event002Address, - event002Key, - blockingStubFull); - logger.info("txid:" + txid); - txidNum++; - } - Thread.sleep(180000); - response = getNowBlock(httpFullNode); - responseContent = parseResponseContent(response); - long blockAfter = - responseContent.getJSONObject("block_header").getJSONObject("raw_data").getLong("number"); - - logger.info("txidNum:" + txidNum); - - // 扫块 - long sumLogs = 0; - long totalTransactionsSize = 0; - logger.info("blockBefore:" + blockBefore); - logger.info("blockAfter:" + blockAfter); - for (long i = blockBefore; i <= blockAfter; i++) { - - response = getTransactionCountByBlocknum(httpFullNode, (int) i); - responseContent = parseResponseContent(response); - long transactionsSize = responseContent.getLong("count"); - - totalTransactionsSize += transactionsSize; - } - logger.info( - (int) (Thread.currentThread().getId()) - + "sumLogs:" - + totalTransactionsSize * Long.parseLong(param)); - } - - public static String[] arr = - new String[] { - "00", - "0x6b5c9c34aae469576dfcde3655c9036d", - "0x450de4565abf4434d66948fb2a568608", - "0x02a65b2cc37d2d34808a63b50b86e0cd", - "0x7474d244cecf3a943bf8ac6dbd7d60fa", - "0x4ab110c02b04d7781f774eeffa6432a3" - }; - - @Test( - enabled = true, - threadPoolSize = 5, - invocationCount = 5, - description = "Eth api of eth_getFilterChanges .") - public void test09GetFilterChanges() { - long sumSize = 0; - while (true) { - JsonArray params = new JsonArray(); - String id = arr[(int) (Thread.currentThread().getId()) - 16]; - params.add(id); - JsonObject requestBody = getJsonRpcBody("eth_getFilterChanges", params); - HttpResponse response = getJsonRpc(jsonRpcNode, requestBody); - JSONObject responseContent = parseResponseContent(response); - long size = responseContent.getJSONArray("result").size(); - sumSize += size; - logger.info(Thread.currentThread().getId() + ":sumSize:" + sumSize); - } - } - - /** constructor. */ - public static JSONObject parseResponseContent(HttpResponse response) { - try { - String result = EntityUtils.toString(response.getEntity()); - StringEntity entity = new StringEntity(result, Charset.forName("UTF-8")); - response.setEntity(entity); - JSONObject obj = JSONObject.parseObject(result); - return obj; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - /* public static HttpResponse getNowBlock(String httpNode, Boolean visible) { - try { - String requestUrl = "http://" + httpNode + "/wallet/getnowblock"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("visible", visible); - response = createConnect(requestUrl, userBaseObj2); - } catch (Exception e) { - e.printStackTrace(); - httppost.releaseConnection(); - return null; - } - return response; - }*/ - - /** constructor. */ - public static HttpResponse getTransactionCountByBlocknum(String httpNode, long blocknum) { - HttpResponse response; - try { - - String requestUrl = "http://" + httpNode + "/wallet/gettransactioncountbyblocknum"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("num", blocknum); - response = createConnect(requestUrl, userBaseObj2); - } catch (Exception e) { - e.printStackTrace(); - - return null; - } - return response; - } - - public static HttpResponse getNowBlock(String httpNode) { - return getNowBlock(httpNode, false); - } - - /** constructor. */ - public static HttpResponse getNowBlock(String httpNode, Boolean visible) { - - HttpResponse response; - try { - String requestUrl = "http://" + httpNode + "/wallet/getnowblock"; - JsonObject userBaseObj2 = new JsonObject(); - userBaseObj2.addProperty("visible", visible); - response = createConnect(requestUrl, userBaseObj2); - } catch (Exception e) { - e.printStackTrace(); - - return null; - } - return response; - } - - /** constructor. */ - public static HttpResponse createConnect(String url, JsonObject requestBody) { - HttpResponse response; - HttpPost httppost; - HttpClient httpClient; - Integer connectionTimeout = - Configuration.getByPath("testng.conf").getInt("defaultParameter.httpConnectionTimeout"); - Integer soTimeout = - Configuration.getByPath("testng.conf").getInt("defaultParameter.httpSoTimeout"); - PoolingClientConnectionManager pccm = new PoolingClientConnectionManager(); - pccm.setDefaultMaxPerRoute(80); - pccm.setMaxTotal(100); - - httpClient = new DefaultHttpClient(pccm); - try { - - httpClient - .getParams() - .setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, connectionTimeout); - httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, soTimeout); - httppost = new HttpPost(url); - httppost.setHeader("Content-type", "application/json; charset=utf-8"); - httppost.setHeader("Connection", "Close"); - if (requestBody != null) { - StringEntity entity = new StringEntity(requestBody.toString(), Charset.forName("UTF-8")); - entity.setContentEncoding("UTF-8"); - entity.setContentType("application/json"); - httppost.setEntity(entity); - } - - logger.info(httppost.toString()); - response = httpClient.execute(httppost); - } catch (Exception e) { - e.printStackTrace(); - - return null; - } - return response; - } - - /** constructor. */ - public static HttpResponse getJsonRpc(String jsonRpcNode, JsonObject jsonRpcObject) { - HttpResponse response; - try { - String requestUrl = "http://" + jsonRpcNode + "/jsonrpc"; - response = createConnect(requestUrl, jsonRpcObject); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - return response; - } - - @Test(enabled = true, description = "Subscribe event client") - public void testEnergyCostDetail() { - ZMQ.Context context = ZMQ.context(1); - ZMQ.Socket req = context.socket(ZMQ.SUB); - - req.subscribe("blockTrigger"); - req.subscribe("transactionTrigger"); - req.subscribe("contractLogTrigger"); - req.subscribe("contractEventTrigger"); - req.monitor("inproc://reqmoniter", ZMQ.EVENT_CONNECTED | ZMQ.EVENT_DISCONNECTED); - final ZMQ.Socket moniter = context.socket(ZMQ.PAIR); - moniter.connect("inproc://reqmoniter"); - new Thread(new Runnable() { - public void run() { - while (true) { - Event event = Event.read(moniter.base()); - System.out.println(event.event + " " + event.addr); - } - } - - }).start(); - req.connect("tcp://47.94.197.215:55555"); - req.setReceiveTimeOut(10000); - - while (true) { - byte[] message = req.recv(); - if (message != null) { - System.out.println("receive : " + new String(message)); - } - } - } - - @Test(enabled = true) - public void testSingForHex() { - try { - SignInterface cryptoEngine = - SignUtils.fromPrivate( - ByteArray.fromHexString( - "6815B367FDDE637E53E9ADC8E69424E07724333C9A2B973CFA469975E20753FC"), - true); - /* ByteString sig = ByteString.copyFrom(cryptoEngine.Base64toBytes(cryptoEngine - .signHash(Sha256Hash.of(DBConfig.isECKeyCryptoEngine(), - ByteArray.fromHexString( - "ba989430c392dedef66a259a1f1112b178dbe7f2793975d8cf80f9b31ecd33ff")) - .getBytes())));*/ - // - ByteString sig = - ByteString.copyFrom( - cryptoEngine.Base64toBytes( - cryptoEngine.signHash( - ByteArray.fromHexString( - "4f2a4c136f56a41714b42e14d497e38dcbe0f9c4ca2e5957cf3a340c62d133f8")))); - logger.info(ByteArray.toHexString(sig.toByteArray())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** constructor. */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/CycleMultiSign.java b/framework/src/test/java/stest/tron/wallet/onlinestress/CycleMultiSign.java deleted file mode 100644 index 9f0b2983f68..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/CycleMultiSign.java +++ /dev/null @@ -1,253 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.List; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Permission; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class CycleMultiSign { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - - - private ManagedChannel channelFull = null; - private ManagedChannel searchChannelFull = null; - - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidityInFullnode = null; - - private WalletGrpc.WalletBlockingStub searchBlockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String searchFullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - private ManagedChannel channelSolidity = null; - private ManagedChannel channelSolidityInFullnode = null; - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - private ECKey ecKey = new ECKey(Utils.getRandom()); - private byte[] test001Address = ecKey.getAddress(); - private String dev001Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - - - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] test002Address = ecKey2.getAddress(); - private String sendAccountKey2 = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - private ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] test003Address = ecKey3.getAddress(); - String sendAccountKey3 = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - private ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] test004Address = ecKey4.getAddress(); - String sendAccountKey4 = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private ECKey ecKey5 = new ECKey(Utils.getRandom()); - byte[] test005Address = ecKey5.getAddress(); - String sendAccountKey5 = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext() - .build(); - searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - } - - //(use no id) - @Test(enabled = true) - public void testMultiSignActiveAddress() { - Assert.assertTrue(PublicMethed - .sendcoin(test001Address, 10000000000000L, fromAddress, testKey002, - blockingStubFull)); - - Account test001AddressAccount = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList = test001AddressAccount.getActivePermissionList(); - Permission ownerPermission = test001AddressAccount.getOwnerPermission(); - Permission witnessPermission = test001AddressAccount.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission)); - logger.info("wei-----------------------"); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = dev001Key; - - String accountPermissionJson1 = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":1,\"" - + "keys\":[{\"address\":\"" + PublicMethed.getAddressString(dev001Key) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey4) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey5) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\"," - + "\"threshold\":1,\"operations\":\"" - + "0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(dev001Key) - + "\",\"weight\":1}]}]} "; - - Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList1 = test001AddressAccount1.getActivePermissionList(); - Permission ownerPermission1 = test001AddressAccount1.getOwnerPermission(); - Permission witnessPermission1 = test001AddressAccount1.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList1); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission1)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission1)); - logger.info("1-----------------------"); - - String accountPermissionJson2 = - "{\"owner_permission\":{\"type\":0,\"permission_name\"" - + ":\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey4) - + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]} "; - String accountPermissionJson3 = "{\"owner_permission\":{\"type\":0,\"permission_name\":" - + "\"owner\",\"threshold\":1,\"keys\":[{\"address\"" - + ":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":" - + "\"active0\",\"threshold\":1,\"operations" - + "\":\"0100000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(dev001Key) - + "\",\"weight\":1}]}," - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1,\"operations" - + "\":\"0100000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]}"; - String accountPermissionJson4 = "{\"owner_permission\":{\"type\":0,\"" - + "permission_name\":\"owner\",\"threshold\":1,\"keys\":" - + "[{\"address\":\"" + PublicMethed.getAddressString(dev001Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1," - + "\"operations\":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}," - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1,\"operations\":" - + "\"0200000000000000000000000000000000000000000000000000000000000000\",\"keys\":" - + "[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey4) - + "\",\"weight\":1}]},{\"type\":2," - + "\"permission_name\":\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}]}," - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1,\"operations\"" - + ":\"0100000000000000000000000000000000000000000000000000000000000000\",\"keys\"" - + ":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}," - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1,\"operations\":" - + "\"0200000000000000000000000000000000000000000000000000000000000000\",\"keys\"" - + ":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey2) - + "\",\"weight\":1}]},{\"type\":2," - + "\"permission_name\":\"active0\",\"threshold\":1,\"operations\":\"" - + "0200000000000000000000000000000000000000000000000000000000000000\",\"keys\":" - + "[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}," - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1,\"operations\"" - + ":\"0200000000000000000000000000000000000000000000000000000000000000\",\"" - + "keys\":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey5) - + "\",\"weight\":1}]}," - + "{\"type\":2,\"permission_name\":\"active0\",\"threshold\":1,\"operations\":" - + "\"0020000000000000000000000000000000000000000000000000000000000000\",\"keys\"" - + ":[{\"address\":\"" + PublicMethed.getAddressString(sendAccountKey3) - + "\",\"weight\":1}]}]}"; - while (true) { - PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, - dev001Key, - blockingStubFull, 0, - permissionKeyString); - addressPermission(dev001Key, accountPermissionJson2); - addressPermission(dev001Key, accountPermissionJson3); - addressPermission(dev001Key, accountPermissionJson4); - Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); - List permissionsList2 = test001AddressAccount2.getActivePermissionList(); - Permission ownerPermission2 = test001AddressAccount2.getOwnerPermission(); - Permission witnessPermission2 = test001AddressAccount2.getWitnessPermission(); - PublicMethedForMutiSign.printPermissionList(permissionsList2); - logger.info(PublicMethedForMutiSign.printPermission(ownerPermission2)); - logger.info(PublicMethedForMutiSign.printPermission(witnessPermission2)); - } - } - - /** - * constructor. - */ - - public void addressPermission(String addKey, String accountPermissionJson) { - PublicMethed.freezeBalanceForReceiver(test001Address, - 10000000L, 0, 0, - com.google.protobuf.ByteString.copyFrom(fromAddress), testKey002, blockingStubFull); - - String[] permissionKeyString = new String[1]; - permissionKeyString[0] = addKey; - PublicMethedForMutiSign - .accountPermissionUpdateWithPermissionId(accountPermissionJson, test001Address, dev001Key, - blockingStubFull, 0, - permissionKeyString); - PublicMethed.unFreezeBalance(fromAddress, testKey002, 0, - test001Address, blockingStubFull); - } - - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (searchChannelFull != null) { - searchChannelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/DelayTransactionStress.java b/framework/src/test/java/stest/tron/wallet/onlinestress/DelayTransactionStress.java deleted file mode 100644 index 9f34dc8c249..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/DelayTransactionStress.java +++ /dev/null @@ -1,340 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -//import org.tron.protos.Protocol.DeferredTransaction; - -@Slf4j -public class DelayTransactionStress { - - public static final long MAX_DEFERRED_TRANSACTION_DELAY_SECONDS = 45 * 24 * 3_600L; //45 days - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - Optional infoById = null; - //Optional deferredTransactionById = null; - Optional getTransactionById = null; - ECKey ecKey = new ECKey(Utils.getRandom()); - byte[] delayAccount1Address = ecKey.getAddress(); - String delayAccount1Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] delayAccount2Address = ecKey2.getAddress(); - String delayAccount2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] receiverAccountAddress = ecKey3.getAddress(); - String receiverAccountKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] delayAccount3Address = ecKey4.getAddress(); - String delayAccount3Key = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - ECKey ecKey5 = new ECKey(Utils.getRandom()); - byte[] receiverAccount4Address = ecKey5.getAddress(); - String receiverAccount4Key = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private Long delayTransactionFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.delayTransactionFee"); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, threadPoolSize = 30, invocationCount = 2000) - public void test1DelaySendcoinStress() { - String txid = ""; - Integer i = 0; - String cancelId = ""; - while (i++ <= 10000000) { - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] delayAccount2Address = ecKey2.getAddress(); - String delayAccount2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - txid = PublicMethed.sendcoinDelayedGetTxid(delayAccount2Address, 1L, 20, fromAddress, - testKey002, blockingStubFull); - //PublicMethed.waitProduceNextBlock(blockingStubFull); - if (i % 20 == 0) { - cancelId = txid; - //PublicMethed.sendcoin(delayAccount2Address,1L,fromAddress,testKey002,blockingStubFull); - } - if (i % 39 == 0) { - PublicMethed.cancelDeferredTransactionById(cancelId, fromAddress, testKey002, - blockingStubFull); - PublicMethed.sendcoin(delayAccount2Address, 1L, fromAddress, testKey002, - blockingStubFull); - } - - } - - - } - - /* @Test(enabled = true, description = "Get deferred transaction by id") - public void test2getDeferredTransactionByid() { - //get account - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] delayAccount2Address = ecKey2.getAddress(); - String delayAccount2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - ecKey3 = new ECKey(Utils.getRandom()); - receiverAccountAddress = ecKey3.getAddress(); - receiverAccountKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - PublicMethed.printAddress(delayAccount2Key); - PublicMethed.printAddress(receiverAccountKey); - - //Pre sendcoin to the test account - Assert.assertTrue(PublicMethed.sendcoin(delayAccount2Address, 100000000L,fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(receiverAccountAddress, 10L,fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //Do delay send coin transaction. - Long delaySecond = 10L; - Long sendCoinAmout = 100L; - - //Query balance before send coin. - Long deplayAccountBeforeBalance = PublicMethed.queryAccount(delayAccount2Address, - blockingStubFull).getBalance(); - Long recevierAccountBeforeBalance = PublicMethed.queryAccount(receiverAccountAddress, - blockingStubFull).getBalance(); - logger.info("deplayAccountBeforeBalance " + deplayAccountBeforeBalance); - logger.info("recevierAccountBeforeBalance " + recevierAccountBeforeBalance); - String txid = PublicMethed.sendcoinDelayedGetTxid(receiverAccountAddress, sendCoinAmout, - delaySecond,delayAccount2Address, - delayAccount2Key, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //Query balance when pre-sendcoin stage. - Long deplayAccountInDelayBalance = PublicMethed.queryAccount(delayAccount2Address, - blockingStubFull).getBalance(); - Long recevierAccountInDelayalance = PublicMethed.queryAccount(receiverAccountAddress, - blockingStubFull).getBalance(); - logger.info("deplayAccountInDelayBalance " + deplayAccountInDelayBalance); - logger.info("recevierAccountInDelayalance " + recevierAccountInDelayalance); - Assert.assertTrue(recevierAccountBeforeBalance == recevierAccountInDelayalance); - //Assert.assertTrue(); - - - deferredTransactionById = PublicMethed.getDeferredTransactionById(txid,blockingStubFull); - DeferredTransaction transaction = deferredTransactionById.get(); - String finalTxid = ByteArray.toHexString(Sha256Hash.hash(transaction.getTransaction() - .getRawData().toByteArray())); - PublicMethed.getDeferredTransactionById(finalTxid,blockingStubFull); - logger.info(finalTxid); - //logger.info("receiver address is " + Base58.encode58Check(transaction - .getReceiverAddress().toByteArray())); - Assert.assertTrue(Base58.encode58Check(transaction.getReceiverAddress().toByteArray()) - .equalsIgnoreCase(PublicMethed.getAddressString(receiverAccountKey))); - //logger.info("sender address is " + Base58.encode58Check(transaction - .getSenderAddress().toByteArray())); - Assert.assertTrue(Base58.encode58Check(transaction.getSenderAddress().toByteArray()) - .equalsIgnoreCase(PublicMethed.getAddressString(delayAccount2Key))); - // logger.info("delaySeconds is " + transaction.getDelaySeconds()); - Assert.assertTrue(delaySecond == transaction.getDelaySeconds()); - //logger.info("DelayUntil " + transaction.getDelayUntil()); - Assert.assertTrue(transaction.getDelayUntil() > System.currentTimeMillis()); - //logger.info("Expiration " + transaction.getExpiration()); - Assert.assertTrue(transaction.getExpiration() > System.currentTimeMillis()); - //logger.info("PublishTime " + transaction.getPublishTime()); - Assert.assertTrue(transaction.getPublishTime() < System.currentTimeMillis()); - //Assert.assertTrue(transaction.getDelayUntil() + 60000 == transaction.getExpiration()); - getTransactionById = PublicMethed.getTransactionById(txid, blockingStubFull); - logger.info("transaction stage in txid is " + getTransactionById.get().getRawData() - .getDeferredStage().getStage()); - - Assert.assertTrue(getTransactionById.get().getRawData().getDeferredStage().getStage() == 1); - getTransactionById = PublicMethed.getTransactionById(finalTxid, blockingStubFull); - logger.info("transaction stage in final id is " + getTransactionById - .get().getRawData().getDeferredStage().getStage()); - Assert.assertTrue(getTransactionById.get().getRawData().getDeferredStage().getStage() == 0); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - PublicMethed.getDeferredTransactionById(finalTxid,blockingStubFull); - deferredTransactionById = PublicMethed.getDeferredTransactionById(txid,blockingStubFull); - finalTxid = ByteArray.toHexString(Sha256Hash.hash(transaction.getTransaction() - .getRawData().toByteArray())); - transaction = deferredTransactionById.get(); - logger.info(finalTxid); - //logger.info("receiver address is " + Base58.encode58Check(transaction.getReceiverAddress() - .toByteArray())); - //logger.info("receiver address is " + Base58.encode58Check(transaction.getSenderAddress() - .toByteArray())); - //logger.info("delaySeconds is " + transaction.getDelaySeconds()); - //logger.info("DelayUntil " + transaction.getDelayUntil()); - //logger.info("Expiration " + transaction.getExpiration()); - //logger.info("PublishTime " + transaction.getPublishTime()); - getTransactionById = PublicMethed.getTransactionById(txid, blockingStubFull); - logger.info("transaction stage in txid is " + getTransactionById.get().getRawData() - .getDeferredStage().getStage()); - getTransactionById = PublicMethed.getTransactionById(finalTxid, blockingStubFull); - logger.info("transaction stage in final id is " + getTransactionById.get().getRawData() - .getDeferredStage().getStage()); - - - - //Query balance after delay send coin. - Long deplayAccountAfterBalance = PublicMethed.queryAccount(delayAccount2Address, - blockingStubFull).getBalance(); - Long recevierAccountAfterDelayalance = PublicMethed.queryAccount(receiverAccountAddress, - blockingStubFull).getBalance(); - logger.info("deplayAccountAfterBalance " + deplayAccountAfterBalance); - logger.info("recevierAccountAfterDelayalance " + recevierAccountAfterDelayalance); - - Assert.assertTrue(deplayAccountBeforeBalance - deplayAccountAfterBalance == sendCoinAmout - + 100000L); - Assert.assertTrue(recevierAccountAfterDelayalance - recevierAccountBeforeBalance - == sendCoinAmout); - - }*/ - - @Test(enabled = true, description = "Delay send coin") - public void test3DelaySendCoin() { - ecKey4 = new ECKey(Utils.getRandom()); - delayAccount3Address = ecKey4.getAddress(); - delayAccount3Key = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - PublicMethed.printAddress(delayAccount3Key); - - ecKey5 = new ECKey(Utils.getRandom()); - receiverAccount4Address = ecKey5.getAddress(); - receiverAccount4Key = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); - PublicMethed.printAddress(receiverAccount4Key); - - Long sendCoinAmount = 100000000L; - //Pre sendcoin to the test account - Assert.assertTrue(PublicMethed.sendcoin(delayAccount3Address, sendCoinAmount, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //Do delay send coin transaction. - logger.info("----------------No balance to send coin--------------------"); - //Test no balance to send coin. - //Query balance before send coin. - Long deplayAccountBeforeBalance = PublicMethed.queryAccount(delayAccount3Address, - blockingStubFull).getBalance(); - Long recevierAccountBeforeBalance = PublicMethed.queryAccount(receiverAccount4Address, - blockingStubFull).getBalance(); - logger.info("deplayAccountBeforeBalance " + deplayAccountBeforeBalance); - logger.info("recevierAccountBeforeBalance " + recevierAccountBeforeBalance); - Long delaySecond = 4L; - Assert.assertFalse(PublicMethed.sendcoinDelayed(receiverAccount4Address, sendCoinAmount, - delaySecond, delayAccount3Address, delayAccount3Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //Query balance after delay send coin. - Long deplayAccountAfterBalance = PublicMethed.queryAccount(delayAccount3Address, - blockingStubFull).getBalance(); - Long recevierAccountAfterDelayalance = PublicMethed.queryAccount(receiverAccount4Address, - blockingStubFull).getBalance(); - logger.info("deplayAccountAfterBalance " + deplayAccountAfterBalance); - logger.info("recevierAccountAfterDelayalance " + recevierAccountAfterDelayalance); - - Assert.assertTrue(recevierAccountAfterDelayalance == 0); - logger.info("deplayAccountBeforeBalance: " + deplayAccountBeforeBalance); - logger.info("deplayAccountAfterBalance: " + deplayAccountAfterBalance); - - Assert.assertEquals(deplayAccountBeforeBalance, deplayAccountAfterBalance); - - logger.info("----------------No balance to create account send coin--------------------"); - //Test delay send coin to create account. - deplayAccountBeforeBalance = PublicMethed.queryAccount(delayAccount3Address, - blockingStubFull).getBalance(); - recevierAccountBeforeBalance = PublicMethed.queryAccount(receiverAccount4Address, - blockingStubFull).getBalance(); - logger.info("deplayAccountBeforeBalance " + deplayAccountBeforeBalance); - logger.info("recevierAccountBeforeBalance " + recevierAccountBeforeBalance); - Long createAccountFee = 100000L; - Assert.assertTrue(PublicMethed.sendcoinDelayed(receiverAccount4Address, - deplayAccountBeforeBalance - createAccountFee, delaySecond, delayAccount3Address, - delayAccount3Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //Query balance after delay send coin. - deplayAccountAfterBalance = PublicMethed.queryAccount(delayAccount3Address, blockingStubFull) - .getBalance(); - recevierAccountAfterDelayalance = PublicMethed.queryAccount(receiverAccount4Address, - blockingStubFull).getBalance(); - logger.info("deplayAccountAfterBalance " + deplayAccountAfterBalance); - logger.info("recevierAccountAfterDelayalance " + recevierAccountAfterDelayalance); - - Assert.assertTrue(recevierAccountAfterDelayalance == 0); - Assert.assertTrue(deplayAccountBeforeBalance - deplayAccountAfterBalance == 100000); - - logger.info("---------------Balance enough to create account send coin--------------------"); - //Test delay send coin to create account. - createAccountFee = 100000L; - deplayAccountBeforeBalance = PublicMethed.queryAccount(delayAccount3Address, - blockingStubFull).getBalance(); - recevierAccountBeforeBalance = PublicMethed.queryAccount(receiverAccount4Address, - blockingStubFull).getBalance(); - logger.info("deplayAccountBeforeBalance " + deplayAccountBeforeBalance); - logger.info("recevierAccountBeforeBalance " + recevierAccountBeforeBalance); - Assert.assertTrue(PublicMethed.sendcoinDelayed(receiverAccount4Address, - deplayAccountBeforeBalance - createAccountFee - delayTransactionFee, - delaySecond, delayAccount3Address, delayAccount3Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //Query balance after delay send coin. - deplayAccountAfterBalance = PublicMethed.queryAccount(delayAccount3Address, - blockingStubFull).getBalance(); - recevierAccountAfterDelayalance = PublicMethed.queryAccount(receiverAccount4Address, - blockingStubFull).getBalance(); - logger.info("deplayAccountAfterBalance " + deplayAccountAfterBalance); - logger.info("recevierAccountAfterDelayalance " + recevierAccountAfterDelayalance); - Long receiverBalanceShouldBe = deplayAccountBeforeBalance - createAccountFee - - delayTransactionFee; - - Assert.assertEquals(recevierAccountAfterDelayalance, receiverBalanceShouldBe); - Assert.assertTrue(deplayAccountAfterBalance == 0); - } - - - /** - * constructor. - */ - - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/ExtCodeHashStressTest.java b/framework/src/test/java/stest/tron/wallet/onlinestress/ExtCodeHashStressTest.java deleted file mode 100644 index ee29bda3644..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/ExtCodeHashStressTest.java +++ /dev/null @@ -1,619 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class ExtCodeHashStressTest { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2); - private AtomicLong count = new AtomicLong(); - private AtomicLong errorCount = new AtomicLong(); - private long startTime = System.currentTimeMillis(); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private byte[] extCodeHashContractAddress = null; - private byte[] normalContractAddress = null; - private byte[] testContractAddress = null; - private byte[] dev001Address = fromAddress; - private String dev001Key = testKey002; - private ECKey ecKey2 = new ECKey(Utils.getRandom()); - private byte[] user001Address = ecKey2.getAddress(); - private String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - PublicMethed.printAddress(dev001Key); - PublicMethed.printAddress(user001Key); - } - - @Test(enabled = true, description = "Deploy a normal contract to be used for stress testing.") - public void test01DeployNormalContract() { - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/extCodeHashStress.sol"; - String contractName = "TriggerNormal"; //TBVEkA72g1wFoBBVLSXFZ2Bp944oL17NeU - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - normalContractAddress = deployContract(code, abi, contractName, blockingStubFull); - - SmartContract smartContract = PublicMethed.getContract(normalContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = true, description = "Deploy a extcodehash contract.") - public void test02DeployExtCodeHashContract() { - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 100_000_000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(dev001Address, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(dev001Key, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "./src/test/resources/soliditycode/extCodeHashStress.sol"; - String contractName = "Trigger"; //THAx2PcAtRCerwrLGN237dahqSUfq5wLnR - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - extCodeHashContractAddress = deployContract(code, abi, contractName, blockingStubFull); - - SmartContract smartContract = PublicMethed.getContract(extCodeHashContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - /** - * trigger. - */ - public byte[] deployContract(String bytecode, String abi, String contractName, - WalletGrpc.WalletBlockingStub blockingStubFull) { - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, bytecode, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, dev001Key, - dev001Address, blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() - .toStringUtf8()); - } - - return infoById.get().getContractAddress().toByteArray(); - } - - /** - * trigger. - */ - public String triggerContractWithMaxFeeLimit(byte[] testAddress, byte[] user001Address, - String user001Key, long maxFeeLimit) { - Assert.assertTrue(PublicMethed.sendcoin(user001Address, 10000_000_000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(user001Address, user001Key, 50000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(user001Address), testKey002, blockingStubFull)); - - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(testAddress) + "\""; - final String triggerTxid = PublicMethed.triggerContract(extCodeHashContractAddress, - "test(address)", param, false, callValue, - maxFeeLimit, "0", 0, user001Address, user001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - scheduledExecutorService - .schedule(new CheckTask(triggerTxid, blockingStubFull), 15, TimeUnit.SECONDS); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - logger - .info("transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - - if (infoById.get().getResMessage().toStringUtf8().toLowerCase().contains("cpu")) { - throw new IllegalArgumentException(); - } - if (infoById.get().getResMessage().toStringUtf8().toLowerCase().contains("timeout")) { - throw new IllegalArgumentException(); - } - return "ok"; - } - - /** - * trigger. - */ - public String triggerAndGetExtCodeHashList(List testAddress, byte[] user001Address, - String user001Key, long maxFeeLimit, WalletGrpc.WalletBlockingStub blockingStubFull) { - - Long callValue = Long.valueOf(0); - List params = new ArrayList<>(); - for (int i = 0; i < testAddress.size(); i++) { - params.add(Base58.encode58Check(testAddress.get(i))); - } - final String triggerTxid = PublicMethed.triggerParamListContract(extCodeHashContractAddress, - "test(address[])", Arrays.asList(params), false, callValue, - maxFeeLimit, "0", 0, user001Address, user001Key, - blockingStubFull); - - scheduledExecutorService - .schedule(new CheckTask(triggerTxid, blockingStubFull), 15, TimeUnit.SECONDS); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - logger - .info( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - - return "ok"; - - } - - /** - * trigger. - */ - public void triggerAndGetExtCodeHash(byte[] testAddress, byte[] user001Address, - String user001Key, long maxFeeLimit, WalletGrpc.WalletBlockingStub blockingStubFull) { - - Long callValue = Long.valueOf(0); - - String param = "\"" + Base58.encode58Check(testAddress) + "\""; - final String triggerTxid = PublicMethed.triggerContract(normalContractAddress, - "test(address)", param, false, callValue, - 314982000, "0", 0, user001Address, user001Key, - blockingStubFull); - - scheduledExecutorService - .schedule(new CheckTask(triggerTxid, blockingStubFull), 15, TimeUnit.SECONDS); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - logger - .info( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - - private synchronized void wirteLine(String fileName, String line) { - try { - BufferedWriter out = new BufferedWriter(new FileWriter(fileName, true)); - out.write(line); - out.newLine(); - out.flush(); - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Test(enabled = true, description = "Deploy multiple long bytecode contract " - + "and write address to file.") - public void test03DeployMultiLongByteCodeContract() { - - ExecutorService pool = Executors.newFixedThreadPool(30); - Map addressMap = new ConcurrentHashMap<>(); - int size = 50_0_000; - int stubSize = 30; - List stubs = new ArrayList<>(); - for (int i = 0; i < stubSize; i++) { - stubs.add(WalletGrpc.newBlockingStub(channelFull)); - } - - CountDownLatch count = new CountDownLatch(size); - for (int i = 0; i < size; i++) { - - String contractName = "extcodehashContract" + i; - logger.info("[" + i + "]contractName: " + contractName); - pool.submit(new DeployTask(addressMap, i, count, stubs.get(i % stubSize))); - - } - - try { - count.await(); - for (String s : addressMap.keySet()) { - System.out.println(s); - } - - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - @Test(enabled = true, description = "Calculate the contract maxfeelimit.", - threadPoolSize = 1, invocationCount = 1) - public void test04StressGetExtCodeHashContract() { - - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - extCodeHashContractAddress = WalletClient - .decodeFromBase58Check("TEsdDpJQrLBDPmJfDF2Ex53iMfzetqHvn9"); - - // long bytecode contract - testContractAddress = WalletClient.decodeFromBase58Check("TDqSAv8gLFXQRfug5Pr1Ev6zrEj1efC8qe"); - - HashMap retMap = new HashMap<>(); - - long feeLimit = 314982000; - // long feeLimit = 393624800; - // long feeLimit = 406731800; - - long base = 100; - long lastSuccess = feeLimit; - int failed = 0; - - for (int i = 0; i < 1000000000; i++) { - try { - String retCode = triggerContractWithMaxFeeLimit(testContractAddress, user001Address, - user001Key, - feeLimit); - logger.info("[" + i + "]retCode: " + retCode); - logger.info("[" + i + "]feeLimit: " + feeLimit); - lastSuccess = feeLimit; - base *= 2; - feeLimit += base; - failed = 0; - } catch (Exception e) { - failed++; - if (failed > 3) { - break; - } - logger.error("cpu timeout"); - feeLimit = lastSuccess; - base = 100; - } - } - } - - @Test(enabled = true, description = "Trigger extcodeHash contract stress.") - public void test05TriggerContract() throws FileNotFoundException { - - BufferedReader reader = null; - List addresses = new ArrayList<>(); - try { - reader = new BufferedReader(new FileReader("src/test/resources/address2")); - String line = reader.readLine(); - while (line != null) { - System.out.println(line); - // read next line - line = reader.readLine(); - addresses.add(line); - } - reader.close(); - } catch (IOException e) { - e.printStackTrace(); - } - ExecutorService pool = Executors.newFixedThreadPool(50); - int stubSize = 50; - List stubs = new ArrayList<>(); - for (int i = 0; i < stubSize; i++) { - stubs.add(WalletGrpc.newBlockingStub(channelFull)); - } - - int paramsSize = 75; // the address count per trigger - int trigger = 0; - for (int i = 0; i + paramsSize < addresses.size(); i += paramsSize) { - System.err.println(trigger++); - System.err.println(i + " " + (i + paramsSize)); - pool.submit(new TriggerTask(addresses.subList(i, i + paramsSize), stubs.get( - (int) (Math.random() * 100 % stubSize)))); - } - - try { - Thread.sleep(100000000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - /** - * trigger. - */ - public void triggerContact(String[] testList, WalletGrpc.WalletBlockingStub stub) { - - final byte[] user001Address = fromAddress; - final String user001Key = testKey002; - - extCodeHashContractAddress = WalletClient - .decodeFromBase58Check("TJGYcUspHrwPgy72YeaVjD4Skep9Ji8Pnn"); - - final long feeLimit = 102471600; - count.getAndAdd(1); - if (count.get() % 100 == 0) { - long cost = (System.currentTimeMillis() - startTime) / 1000; - logger.info("Count:" + count.get() + ", cost:" + cost - + ", avg:" + count.get() / cost + ", errCount:" + errorCount); - } - - List addressList = new ArrayList<>(); - - for (int k = 0; k < testList.length; k++) { - addressList.add(WalletClient.decodeFromBase58Check(testList[k])); - } - triggerAndGetExtCodeHashList(addressList, user001Address, user001Key, feeLimit, stub); - } - - @Test(enabled = true, description = "Trigger normal contract stress.") - public void test06TriggerNormalContract() throws FileNotFoundException { - - BufferedReader reader = null; - List addresses = new ArrayList<>(); - try { - reader = new BufferedReader(new FileReader( - "src/test/resources/address2")); - String line = reader.readLine(); - while (line != null) { - System.out.println(line); - // read next line - line = reader.readLine(); - addresses.add(line); - } - reader.close(); - } catch (IOException e) { - e.printStackTrace(); - } - ExecutorService pool = Executors.newFixedThreadPool(50); - int stubSize = 50; - List stubs = new ArrayList<>(); - for (int i = 0; i < stubSize; i++) { - stubs.add(WalletGrpc.newBlockingStub(channelFull)); - } - - int paramsSize = 50; - int trigger = 0; - for (int i = 0; i + paramsSize < addresses.size(); i += 1) { - System.err.println(trigger++); - System.err.println(i + " " + (i + paramsSize)); - pool.submit( - new TriggerNormalTask(addresses.subList(0, 0 + paramsSize), stubs.get( - (int) (Math.random() * 100 % stubSize)))); - } - - try { - Thread.sleep(100000000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - /** - * trigger. - */ - public void triggerNormalContact(String[] testList, WalletGrpc.WalletBlockingStub stub) { - - final byte[] user001Address = fromAddress; - final String user001Key = testKey002; - - normalContractAddress = WalletClient - .decodeFromBase58Check("TFUSarvJtCSQhDifdRaioytThohLSLCjq4"); - - final long feeLimit = 51079600; - count.getAndAdd(1); - if (count.get() % 100 == 0) { - long cost = (System.currentTimeMillis() - startTime) / 1000; - logger.info("Count:" + count.get() + ", cost:" + cost - + ", avg:" + count.get() / cost + ", errCount:" + errorCount); - } - - List addressList = new ArrayList<>(); - - for (int k = 0; k < testList.length; k++) { - addressList.add(WalletClient.decodeFromBase58Check(testList[k])); - } - - triggerAndGetExtCodeHash(normalContractAddress, user001Address, - user001Key, feeLimit, stub); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - class DeployTask implements Runnable { - - Map addressList; - CountDownLatch countDownLatch; - WalletGrpc.WalletBlockingStub stub; - int index; - - DeployTask(Map addressList, int index, CountDownLatch countDownLatch, - WalletGrpc.WalletBlockingStub stub) { - this.index = index; - this.addressList = addressList; - this.countDownLatch = countDownLatch; - this.stub = stub; - } - - @Override - public void run() { - logger.info("depoying :" + index); - String code = Configuration.getByPath("testng.conf") - .getString("code.code_veryLarge"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_veryLarge"); - try { - byte[] deployedAddress = deployContract(code, abi, "test" + index, stub); - String address = Base58.encode58Check(deployedAddress); - wirteLine( - "src/test/resources/addresses2", - address); - logger.info("deployed : " + index + " " + address); - } catch (Throwable e) { - logger.error("deploy error: ", e); - } finally { - countDownLatch.countDown(); - } - } - } - - class CheckTask implements Runnable { - - String txid; - WalletGrpc.WalletBlockingStub client; - - CheckTask(String txid, WalletGrpc.WalletBlockingStub client) { - this.txid = txid; - this.client = client; - } - - @Override - public void run() { - - Optional infoById = PublicMethed - .getTransactionInfoById(this.txid, blockingStubFull); - - TransactionInfo transactionInfo = infoById.get(); - if (infoById.get().getResultValue() != 0) { - logger.error("txid:" + this.txid); - logger.error( - "transaction failed with message: " + infoById.get().getResMessage().toStringUtf8()); - } - logger.info("infoById" + infoById); - } - } - - class TriggerTask implements Runnable { - - List addresses; - WalletGrpc.WalletBlockingStub stub; - - TriggerTask(List addresses, WalletGrpc.WalletBlockingStub stub) { - this.addresses = addresses; - this.stub = stub; - } - - @Override - public void run() { - triggerContact(this.addresses.toArray(new String[0]), stub); - } - } - - class TriggerNormalTask implements Runnable { - - List addresses; - WalletGrpc.WalletBlockingStub stub; - - TriggerNormalTask(List addresses, WalletGrpc.WalletBlockingStub stub) { - this.addresses = addresses; - this.stub = stub; - } - - @Override - public void run() { - triggerNormalContact(this.addresses.toArray(new String[0]), stub); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/HttpStressTest.java b/framework/src/test/java/stest/tron/wallet/onlinestress/HttpStressTest.java deleted file mode 100644 index 7a1fd953fb7..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/HttpStressTest.java +++ /dev/null @@ -1,160 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.params.CoreConnectionPNames; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class HttpStressTest { - - private static final long now = System.currentTimeMillis(); - private static final long totalSupply = 10000000000000000L; - static Integer connectionTimeout = Configuration.getByPath("testng.conf") - .getInt("defaultParameter.httpConnectionTimeout"); - static Integer soTimeout = Configuration.getByPath("testng.conf") - .getInt("defaultParameter.httpSoTimeout"); - private static String name = "testAssetIssue002_" + Long.toString(now); - private static String assetIssueId1; - private static String assetIssueId2; - private static Integer exchangeId; - private static Long beforeInjectBalance; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] exchangeOwnerAddress = ecKey1.getAddress(); - String exchangeOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] asset2Address = ecKey2.getAddress(); - String asset2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - Long amount = 2048000000L; - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - private JSONObject responseContent; - private HttpResponse response; - private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") - .get(0); - - /** - * constructor. - */ - @Test(enabled = true, threadPoolSize = 10, invocationCount = 10) - public void test4InjectExchange() { - final long now = System.currentTimeMillis(); - final long totalSupply = 10000000000000000L; - Long beforeInjectBalance; - HttpClient httpClient = new DefaultHttpClient(); - HttpPost httppost; - httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, - connectionTimeout); - httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, soTimeout); - httppost = new HttpPost(url); - httppost.setHeader("Content-type", "application/json; charset=utf-8"); - httppost.setHeader("Connection", "Close"); - - response = HttpMethed - .sendCoin(httpnode, fromAddress, exchangeOwnerAddress, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - response = HttpMethed.sendCoin(httpnode, fromAddress, asset2Address, amount, testKey002); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - //Create an asset issue - response = HttpMethed.assetIssue(httpnode, exchangeOwnerAddress, name, name, totalSupply, 1, 1, - System.currentTimeMillis() + 5000, System.currentTimeMillis() + 50000000, - 2, 3, description, url, 1000L, 1000L, exchangeOwnerKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - response = HttpMethed.assetIssue(httpnode, asset2Address, name, name, totalSupply, 1, 1, - System.currentTimeMillis() + 5000, System.currentTimeMillis() + 50000000, - 2, 3, description, url, 1000L, 1000L, asset2Key); - Assert.assertTrue(HttpMethed.verificationResult(response)); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getAccount(httpnode, exchangeOwnerAddress); - responseContent = HttpMethed.parseResponseContent(response); - assetIssueId1 = responseContent.getString("asset_issued_ID"); - Assert.assertTrue(Integer.parseInt(assetIssueId1) > 1000000); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.getAccount(httpnode, asset2Address); - responseContent = HttpMethed.parseResponseContent(response); - assetIssueId2 = responseContent.getString("asset_issued_ID"); - Assert.assertTrue(Integer.parseInt(assetIssueId2) > 1000000); - - response = HttpMethed - .transferAsset(httpnode, asset2Address, exchangeOwnerAddress, assetIssueId2, - 100000000000000L, asset2Key); - Assert.assertTrue(HttpMethed.verificationResult(response)); - - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - - //Create exchange. - response = HttpMethed.exchangeCreate(httpnode, exchangeOwnerAddress, assetIssueId1, - 50000000000000L, assetIssueId2, 50000000000000L, exchangeOwnerKey); - Assert.assertTrue(HttpMethed.verificationResult(response)); - - HttpMethed.waitToProduceOneBlock(httpnode); - HttpMethed.waitToProduceOneBlock(httpnode); - response = HttpMethed.listExchanges(httpnode); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - JSONArray jsonArray = JSONArray.parseArray(responseContent.getString("exchanges")); - Assert.assertTrue(jsonArray.size() >= 1); - exchangeId = jsonArray.size(); - - response = HttpMethed.getExchangeById(httpnode, exchangeId); - responseContent = HttpMethed.parseResponseContent(response); - HttpMethed.printJsonContent(responseContent); - - Integer times = 0; - while (times++ <= 10000) { - HttpMethed.sendCoin(httpnode, fromAddress, exchangeOwnerAddress, 100L, testKey002); - HttpMethed.sendCoin(httpnode, fromAddress, asset2Address, 100L, testKey002); - //Inject exchange. - HttpMethed.exchangeInject(httpnode, exchangeOwnerAddress, exchangeId, assetIssueId1, - 10L, exchangeOwnerKey); - HttpMethed.exchangeWithdraw(httpnode, exchangeOwnerAddress, exchangeId, assetIssueId1, - 10L, exchangeOwnerKey); - HttpMethed.exchangeTransaction(httpnode, exchangeOwnerAddress, exchangeId, assetIssueId1, - 100L, 1L, exchangeOwnerKey); - HttpMethed.exchangeTransaction(httpnode, exchangeOwnerAddress, exchangeId, assetIssueId2, - 100L, 1L, exchangeOwnerKey); - HttpMethed.transferAsset(httpnode, asset2Address, exchangeOwnerAddress, assetIssueId2, - 1L, asset2Key); - HttpMethed.transferAsset(httpnode, exchangeOwnerAddress, asset2Address, assetIssueId1, - 1L, exchangeOwnerKey); - HttpMethed.participateAssetIssue(httpnode, exchangeOwnerAddress, asset2Address, - assetIssueId1, 1L, asset2Key); - HttpMethed.participateAssetIssue(httpnode, asset2Address, exchangeOwnerAddress, - assetIssueId2, 1L, exchangeOwnerKey); - HttpMethed.freezeBalance(httpnode, fromAddress, 10000000000L, 0, 0, - exchangeOwnerAddress, testKey002); - HttpMethed.freezeBalance(httpnode, fromAddress, 10000000000L, 0, 1, - exchangeOwnerAddress, testKey002); - HttpMethed.unFreezeBalance(httpnode, fromAddress, 0, exchangeOwnerAddress, testKey002); - HttpMethed.unFreezeBalance(httpnode, fromAddress, 1, exchangeOwnerAddress, testKey002); - } - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - HttpMethed.disConnect(); - } -} diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/MainNetTransferSendOrAsset.java b/framework/src/test/java/stest/tron/wallet/onlinestress/MainNetTransferSendOrAsset.java deleted file mode 100644 index 912abb2fe08..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/MainNetTransferSendOrAsset.java +++ /dev/null @@ -1,153 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class MainNetTransferSendOrAsset { - - //testng001、testng002、testng003、testng004 - //fromAssetIssue - private final String testKey001 = - "BC70ADC5A0971BA3F7871FBB7249E345D84CE7E5458828BE1E28BF8F98F2795B"; - //toAssetIssue - private final String testKey002 = - "F153A0E1A65193846A3D48A091CD0335594C0A3D9817B3441390FDFF71684C84"; - //fromSend - private final String testKey003 = - "2514B1DD2942FF07F68C2DDC0EE791BC7FBE96FDD95E89B7B9BB3B4C4770FFAC"; - //toSend - private final String testKey004 = - "56244EE6B33C14C46704DFB67ED5D2BBCBED952EE46F1FD88A50C32C8C5C64CE"; - //Default - private final String defaultKey = - "8DFBB4513AECF779A0803C7CEBF2CDCC51585121FAB1E086465C4E0B40724AF1"; - - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey001); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] fromSendAddress = PublicMethed.getFinalAddress(testKey003); - private final byte[] toSendAddress = PublicMethed.getFinalAddress(testKey004); - private final byte[] defaultAddress = PublicMethed.getFinalAddress(defaultKey); - - - private final Long transferAmount = 1L; - private final Long sendAmount = 1L; - private Long start; - private Long end; - private Long beforeToBalance; - private Long afterToBalance; - private Long beforeToAssetBalance = 0L; - private Long afterToAssetBalance = 0L; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - Account fromAccount = PublicMethed.queryAccount(testKey001, blockingStubFull); - Account toAccount = PublicMethed.queryAccount(testKey002, blockingStubFull); - if (fromAccount.getBalance() < 10000000000L) { - PublicMethed - .sendcoin(fromAddress, 10000000000L, defaultAddress, defaultKey, blockingStubFull); - } - if (fromAccount.getAssetCount() == 0) { - start = System.currentTimeMillis() + 2000; - end = System.currentTimeMillis() + 1000000000; - PublicMethed.createAssetIssue(fromAddress, "testNetAsset", 1000000000000L, - 1, 1, start, end, 1, "wwwwww", "wwwwwwww", 100000L, - 100000L, 1L, 1L, testKey001, blockingStubFull); - } - beforeToBalance = toAccount.getBalance(); - beforeToAssetBalance = toAccount.getAssetMap().get("testNetAsset"); - - Account fromSendAccount = PublicMethed.queryAccount(testKey003, blockingStubFull); - Account toSendAccount = PublicMethed.queryAccount(testKey004, blockingStubFull); - if (fromSendAccount.getBalance() < 1000000000L) { - PublicMethed - .sendcoin(fromSendAddress, 1000000000L, defaultAddress, defaultKey, blockingStubFull); - } - beforeToBalance = toAccount.getBalance(); - logger.info("Before From account balance is " + Long.toString(fromAccount.getBalance())); - logger.info("Before To account balance is " + Long.toString(toAccount.getBalance())); - start = System.currentTimeMillis(); - } - - @Test(enabled = false, threadPoolSize = 20, invocationCount = 100000) - public void freezeAnd() throws InterruptedException { - Random rand = new Random(); - Integer randNum = 0; - randNum = rand.nextInt(1000); - try { - Thread.sleep(randNum); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - Integer i = 0; - while (i < 60) { - PublicMethed - .transferAsset(toAddress, "testNetAsset".getBytes(), transferAmount, fromAddress, - testKey001, blockingStubFull); - try { - Thread.sleep(200); - } catch (InterruptedException e) { - e.printStackTrace(); - } - PublicMethed.sendcoin(toSendAddress, sendAmount, fromSendAddress, testKey003, - blockingStubFull); - try { - Thread.sleep(200); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - /** - * constructor. - */ - - @AfterClass(enabled = false) - public void shutdown() throws InterruptedException { - end = System.currentTimeMillis(); - logger.info("Time is " + Long.toString(end - start)); - Account fromAccount = PublicMethed.queryAccount(testKey001, blockingStubFull); - Account toAccount = PublicMethed.queryAccount(testKey002, blockingStubFull); - afterToBalance = toAccount.getBalance(); - afterToAssetBalance = toAccount.getAssetMap().get("testNetAsset"); - - logger.info("Success times is " + Long.toString(afterToAssetBalance - beforeToAssetBalance)); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/MainNetVoteOrFreezeOrCreate.java b/framework/src/test/java/stest/tron/wallet/onlinestress/MainNetVoteOrFreezeOrCreate.java deleted file mode 100644 index 5d8e86e707d..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/MainNetVoteOrFreezeOrCreate.java +++ /dev/null @@ -1,359 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.HashMap; -import java.util.Optional; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.GrpcAPI.WitnessList; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.BalanceContract; -import org.tron.protos.contract.WitnessContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class MainNetVoteOrFreezeOrCreate { - - private static final long now = System.currentTimeMillis(); - private static String name = "mainNetAsset_" + Long.toString(now); - //testng001、testng002、testng003、testng004 - //Devaccount - private final String testKey001 = - "2514B1DD2942FF07F68C2DDC0EE791BC7FBE96FDD95E89B7B9BB3B4C4770FFAC"; - //Zion - private final String testKey002 = - "56244EE6B33C14C46704DFB67ED5D2BBCBED952EE46F1FD88A50C32C8C5C64CE"; - //Default - private final String defaultKey = - //Mainet - //"8DFBB4513AECF779A0803C7CEBF2CDCC51585121FAB1E086465C4E0B40724AF1"; - //Beta Env - "6815B367FDDE637E53E9ADC8E69424E07724333C9A2B973CFA469975E20753FC"; - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey001); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey002); - private final byte[] defaultAddress = PublicMethed.getFinalAddress(defaultKey); - private final Long sendAmount = 1026000000L; - long totalSupply = now; - Long freeAssetNetLimit = 30000L; - Long publicFreeAssetNetLimit = 30000L; - String description = "f"; - String url = "h"; - Long startTime; - Long endTime; - Boolean ret = false; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] asset016Address = ecKey1.getAddress(); - String testKeyForAssetIssue016 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long start; - private Long end; - private Long beforeToBalance; - private Long afterToBalance; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - /** - * constructor. - */ - - public static Boolean freezeBalance(byte[] addRess, long freezeBalance, long freezeDuration, - String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - Protocol.Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI - .EmptyMessage.newBuilder().build()); - final Long beforeBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - BalanceContract.FreezeBalanceContract.Builder builder = BalanceContract.FreezeBalanceContract - .newBuilder(); - ByteString byteAddress = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddress).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration); - - BalanceContract.FreezeBalanceContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction = null"); - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } - return true; - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - startTime = System.currentTimeMillis(); - } - - //@Test(enabled = false) - @Test(enabled = false, threadPoolSize = 2, invocationCount = 2) - public void freezeAndSendcoin() throws InterruptedException { - Random rand = new Random(); - Integer randNum = 0; - randNum = rand.nextInt(1000); - try { - Thread.sleep(randNum); - } catch (InterruptedException e) { - e.printStackTrace(); - } - GrpcAPI.WitnessList witnesslist = blockingStubFull - .listWitnesses(GrpcAPI.EmptyMessage.newBuilder().build()); - Optional result = Optional.ofNullable(witnesslist); - Integer i = 0; - while (i++ < 3) { - ret = false; - Integer waitTime = 10; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] accountAddress = ecKey1.getAddress(); - String testKeyAccount = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - logger.info(Base58.encode58Check(accountAddress)); - logger.info(testKeyAccount); - Integer tryTimes = 0; - - while (!ret) { - ret = PublicMethed - .createAccount(defaultAddress, accountAddress, defaultKey, blockingStubFull); - logger.info("createAccount"); - - if (tryTimes++ == 10) { - break; - } - } - - ret = false; - while (!ret) { - ret = PublicMethed - .sendcoin(accountAddress, sendAmount, defaultAddress, defaultKey, blockingStubFull); - logger.info("sendcoin"); - } - ret = false; - while (!ret) { - name = "mainNetAsset_" + Long.toString(System.currentTimeMillis()); - totalSupply = System.currentTimeMillis(); - start = System.currentTimeMillis() + 2000; - end = System.currentTimeMillis() + 1000000000; - ret = PublicMethed.createAssetIssue(accountAddress, name, totalSupply, 1, 1, start, end, - 1, description, url, 3000L, 3000L, 1L, 1L, - testKeyAccount, blockingStubFull); - logger.info("createAssetIssue"); - } - ret = false; - while (!ret) { - ret = freezeBalance(accountAddress, 1000000L, 3, testKeyAccount, - blockingStubFull); - logger.info("freezeBalance"); - } - /* ret = false; - while (!ret) { - ret = PublicMethed - .transferAsset(toAddress, name.getBytes(), 10L, accountAddress, testKeyAccount, - blockingStubFull); - logger.info("transferAsset"); - }*/ - ret = false; - while (!ret) { - String voteStr = Base58 - .encode58Check(result.get().getWitnesses(i % 5).getAddress().toByteArray()); - HashMap smallVoteMap = new HashMap(); - smallVoteMap.put(voteStr, "1"); - ret = voteWitness(smallVoteMap, accountAddress, testKeyAccount); - logger.info("voteWitness"); - } - } - } - - /** - * constructor. - */ - - @AfterClass(enabled = false) - public void shutdown() throws InterruptedException { - endTime = System.currentTimeMillis(); - logger.info("Time is " + Long.toString(endTime - startTime)); - Account fromAccount = PublicMethed.queryAccount(testKey001, blockingStubFull); - Account toAccount = PublicMethed.queryAccount(testKey002, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - - } - - /** - * constructor. - */ - - public Boolean voteWitness(HashMap witness, byte[] addRess, String priKey) { - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account beforeVote = queryAccount(ecKey, blockingStubFull); - Long beforeVoteNum = 0L; - if (beforeVote.getVotesCount() != 0) { - beforeVoteNum = beforeVote.getVotes(0).getVoteCount(); - } - - WitnessContract.VoteWitnessContract.Builder builder = WitnessContract.VoteWitnessContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(addRess)); - for (String addressBase58 : witness.keySet()) { - String value = witness.get(addressBase58); - final long count = Long.parseLong(value); - WitnessContract.VoteWitnessContract.Vote.Builder voteBuilder = WitnessContract - .VoteWitnessContract.Vote - .newBuilder(); - byte[] address = WalletClient.decodeFromBase58Check(addressBase58); - logger.info("address = " + ByteArray.toHexString(address)); - if (address == null) { - continue; - } - voteBuilder.setVoteAddress(ByteString.copyFrom(address)); - voteBuilder.setVoteCount(count); - builder.addVotes(voteBuilder.build()); - } - - WitnessContract.VoteWitnessContract contract = builder.build(); - - Transaction transaction = blockingStubFull.voteWitnessAccount(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - //logger.info("transaction == null,\n contract:{},\n transaction:{}" , contract.toString(), - // transaction.toString()); - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - //logger.info(response.getCode().toString()); - return false; - } - /* try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - }*/ - return true; - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } -} - diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/MultiValiSignPerformanceTest.java b/framework/src/test/java/stest/tron/wallet/onlinestress/MultiValiSignPerformanceTest.java deleted file mode 100644 index 1d983e7d8ab..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/MultiValiSignPerformanceTest.java +++ /dev/null @@ -1,336 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class MultiValiSignPerformanceTest { - - private final String fromKey = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(fromKey); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] contractDepAddress = ecKey1.getAddress(); - String contractDepKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] nonexistentAddress = ecKey2.getAddress(); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private byte[] ecrecoverContractAddress = null; - private byte[] multiValiSignContractAddress = null; - - @BeforeSuite - public void beforeSuite() { - Wallet wallet = new Wallet(); - Wallet.setAddressPreFixByte(Parameter.CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(contractDepKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - - @Test(enabled = true, description = "deploy ecrecover contract") - public void test01DeployEcrecoverContract() { - Assert.assertTrue(PublicMethed.sendcoin(contractDepAddress, 1000_000_000L, fromAddress, - fromKey, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(contractDepAddress, contractDepKey, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(contractDepAddress), fromKey, blockingStubFull)); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(contractDepAddress, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(contractDepKey, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "src/test/resources/soliditycode/multiValiSignPerformance01.sol"; - String contractName = "ecrecoverValidateSign"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, contractDepKey, - contractDepAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(contractDepAddress, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(contractDepKey, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - ecrecoverContractAddress = infoById.get().getContractAddress().toByteArray(); - logger.info("ecrecoverContractAddress:" + infoById.get().getContractAddress()); - SmartContract smartContract = PublicMethed.getContract(ecrecoverContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = true, description = "deploy multvalisign contract") - public void test02DeployMultvalisignContract() { - Assert.assertTrue(PublicMethed.sendcoin(contractDepAddress, 1000_000_000L, fromAddress, - fromKey, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, - PublicMethed.getFreezeBalanceCount(contractDepAddress, contractDepKey, 170000L, - blockingStubFull), 0, 1, - ByteString.copyFrom(contractDepAddress), fromKey, blockingStubFull)); - - //before deploy, check account resource - AccountResourceMessage accountResource = PublicMethed.getAccountResource(contractDepAddress, - blockingStubFull); - long energyLimit = accountResource.getEnergyLimit(); - long energyUsage = accountResource.getEnergyUsed(); - long balanceBefore = PublicMethed.queryAccount(contractDepKey, blockingStubFull).getBalance(); - logger.info("before energyLimit is " + Long.toString(energyLimit)); - logger.info("before energyUsage is " + Long.toString(energyUsage)); - logger.info("before balanceBefore is " + Long.toString(balanceBefore)); - - String filePath = "src/test/resources/soliditycode/multiValiSignPerformance02.sol"; - String contractName = "multiValidateSignContract"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - - final String transferTokenTxid = PublicMethed - .deployContractAndGetTransactionInfoById(contractName, abi, code, "", - maxFeeLimit, 0L, 0, 10000, - "0", 0, null, contractDepKey, - contractDepAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - accountResource = PublicMethed.getAccountResource(contractDepAddress, blockingStubFull); - energyLimit = accountResource.getEnergyLimit(); - energyUsage = accountResource.getEnergyUsed(); - long balanceAfter = PublicMethed.queryAccount(contractDepKey, blockingStubFull).getBalance(); - - logger.info("after energyLimit is " + Long.toString(energyLimit)); - logger.info("after energyUsage is " + Long.toString(energyUsage)); - logger.info("after balanceAfter is " + Long.toString(balanceAfter)); - - Optional infoById = PublicMethed - .getTransactionInfoById(transferTokenTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); - } - - TransactionInfo transactionInfo = infoById.get(); - logger.info("EnergyUsageTotal: " + transactionInfo.getReceipt().getEnergyUsageTotal()); - logger.info("NetUsage: " + transactionInfo.getReceipt().getNetUsage()); - - multiValiSignContractAddress = infoById.get().getContractAddress().toByteArray(); - logger.info("multiValiSignContractAddress:" + infoById.get().getContractAddress()); - SmartContract smartContract = PublicMethed.getContract(multiValiSignContractAddress, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - } - - @Test(enabled = true, description = "trigger ecrecover contract test") - public void test03triggerEcrecoverContract() { - /*Assert.assertTrue(PublicMethed.sendcoin(contractDepAddress, 1000_000_000L, fromAddress, - fromKey, blockingStubFull)); - try { - Thread.sleep(new Long(30000)); - } catch (InterruptedException e) { - e.printStackTrace(); - }*/ - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - byte[] hash = ByteArray - .fromHexString("7d889f42b4a56ebe78264631a3b4daf21019e1170cce71929fb396761cdf532e"); - logger.info("hash:" + Hex.toHexString(hash)); - int cnt = 15; - for (int i = 0; i < cnt; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String[] inputArr = new String[parameters.size()]; - int i = 0; - for (Object parameter : parameters) { - if (parameter instanceof List) { - StringBuilder sb = new StringBuilder(); - for (Object item : (List) parameter) { - if (sb.length() != 0) { - sb.append(","); - } - sb.append("\"").append(item).append("\""); - } - inputArr[i++] = "[" + sb.toString() + "]"; - } else { - inputArr[i++] = - (parameter instanceof String) ? ("\"" + parameter + "\"") : ("" + parameter); - } - } - String input = StringUtils.join(inputArr, ','); - - String txid = ""; - long start = System.currentTimeMillis(); - txid = PublicMethed - .triggerContract(PublicMethed.decode58Check("TDgdUs1gmn1JoeGMqQGkkxE1pcMNSo8kFj"), - "validateSign(bytes32,bytes[],address[])", input, - false, 0, maxFeeLimit, contractDepAddress, contractDepKey, blockingStubFull); - long timeCosts = System.currentTimeMillis() - start; - logger.info( - "Ecrecover--cnt:" + cnt + ",timeCost:" + timeCosts + ",ms:" + (timeCosts * 1.0 / cnt)); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - } - - - @Test(enabled = true, description = "trigger mulivalisign contract test") - public void test04triggerMuliValiSignContract() { - /*Assert.assertTrue(PublicMethed.sendcoin(contractDepAddress, 1000_000_000L, fromAddress, - fromKey, blockingStubFull)); - try { - Thread.sleep(new Long(30000)); - } catch (InterruptedException e) { - e.printStackTrace(); - }*/ - List signatures = new ArrayList<>(); - List addresses = new ArrayList<>(); - - byte[] hash = ByteArray - .fromHexString("7d889f42b4a56ebe78264631a3b4daf21019e1170cce71929fb396761cdf532e"); - logger.info("hash:" + Hex.toHexString(hash)); - int cnt = 15; - for (int i = 0; i < cnt; i++) { - ECKey key = new ECKey(); - byte[] sign = key.sign(hash).toByteArray(); - signatures.add(Hex.toHexString(sign)); - addresses.add(StringUtil.encode58Check(key.getAddress())); - } - List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); - String[] inputArr = new String[parameters.size()]; - int i = 0; - for (Object parameter : parameters) { - if (parameter instanceof List) { - StringBuilder sb = new StringBuilder(); - for (Object item : (List) parameter) { - if (sb.length() != 0) { - sb.append(","); - } - sb.append("\"").append(item).append("\""); - } - inputArr[i++] = "[" + sb.toString() + "]"; - } else { - inputArr[i++] = - (parameter instanceof String) ? ("\"" + parameter + "\"") : ("" + parameter); - } - } - String input = StringUtils.join(inputArr, ','); - - String txid = ""; - long start = System.currentTimeMillis(); - txid = PublicMethed - .triggerContract(PublicMethed.decode58Check("TVpTLZbBbP82aufo7p3qmb4ELiowH3mjQW"), - "testArray(bytes32,bytes[],address[])", input, false, - 0, maxFeeLimit, contractDepAddress, contractDepKey, blockingStubFull); - long timeCosts = System.currentTimeMillis() - start; - logger.info( - "MuliValiSign--cnt:" + cnt + ",timeCost:" + timeCosts + ",ms:" + (timeCosts * 1.0 / cnt)); - Optional infoById = null; - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/MutiSignStress.java b/framework/src/test/java/stest/tron/wallet/onlinestress/MutiSignStress.java deleted file mode 100644 index 27ae66e5142..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/MutiSignStress.java +++ /dev/null @@ -1,143 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class MutiSignStress { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress = PublicMethed.getFinalAddress(witnessKey001); - ByteString assetAccountId1; - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[1]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey3.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] newAddress = ecKey4.getAddress(); - String newKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, threadPoolSize = 20, invocationCount = 20) - public void testMutiSignForAccount() { - Integer i = 0; - while (i < 20) { - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - manager2Address = ecKey2.getAddress(); - manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - ecKey3 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey3.getAddress(); - ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - PublicMethed.printAddress(ownerKey); - - ecKey4 = new ECKey(Utils.getRandom()); - newAddress = ecKey4.getAddress(); - newKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - - PublicMethed.sendcoin(ownerAddress, 4000000L, fromAddress, testKey002, - blockingStubFull); - PublicMethed.sendcoin(ownerAddress, 4000000L, fromAddress, testKey002, - blockingStubFull); - PublicMethed.sendcoin(ownerAddress, 4000000L, fromAddress, testKey002, - blockingStubFull); - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - ownerKeyString[0] = ownerKey; - accountPermissionJson = "[{\"keys\":[{\"address\":\"" - + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":2}],\"name\":\"owner\",\"threshold\":2,\"parent\":\"owner\"}," - + "{\"parent\":\"owner\",\"keys\":[{\"address\":\"" - + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1},{\"address\":\"" - + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}],\"name\":\"active\"," - + "\"threshold\":2}]"; - //logger.info(accountPermissionJson); - PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString); - - String updateName = Long.toString(System.currentTimeMillis()); - - PublicMethedForMutiSign.sendcoin(newAddress, 1000000L, ownerAddress, ownerKey, - blockingStubFull, permissionKeyString); - PublicMethedForMutiSign.sendcoin(newAddress, 1000000L, ownerAddress, ownerKey, - blockingStubFull, permissionKeyString); - PublicMethedForMutiSign.sendcoin(newAddress, 1000000L, ownerAddress, ownerKey, - blockingStubFull, permissionKeyString); - PublicMethedForMutiSign.freezeBalance(ownerAddress, 1000000L, 0, - ownerKey, blockingStubFull, permissionKeyString); - PublicMethedForMutiSign.freezeBalance(ownerAddress, 1000000L, 0, - ownerKey, blockingStubFull, permissionKeyString); - PublicMethedForMutiSign.freezeBalance(ownerAddress, 1000000L, 0, - ownerKey, blockingStubFull, permissionKeyString); - PublicMethedForMutiSign.unFreezeBalance(ownerAddress, ownerKey, 0, null, - blockingStubFull, permissionKeyString); - PublicMethedForMutiSign.unFreezeBalance(ownerAddress, ownerKey, 0, null, - blockingStubFull, permissionKeyString); - PublicMethedForMutiSign.unFreezeBalance(ownerAddress, ownerKey, 0, null, - blockingStubFull, permissionKeyString); - } - - - } - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/ScanBlockTools.java b/framework/src/test/java/stest/tron/wallet/onlinestress/ScanBlockTools.java deleted file mode 100644 index 73375d897b0..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/ScanBlockTools.java +++ /dev/null @@ -1,1100 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.google.protobuf.Any; -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.TransactionInfoList; -import org.tron.api.WalletGrpc; -import org.tron.common.utils.Base58; -import org.tron.common.utils.ByteArray; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Account.AccountResource; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.AccountContract.AccountCreateContract; -import org.tron.protos.contract.AccountContract.AccountPermissionUpdateContract; -import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; -import org.tron.protos.contract.BalanceContract.FreezeBalanceContract; -import org.tron.protos.contract.BalanceContract.TransferContract; -import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; -import org.tron.protos.contract.BalanceContract.WithdrawBalanceContract; -import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; -import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; -import org.tron.protos.contract.WitnessContract.VoteWitnessContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.Sha256Hash; -import stest.tron.wallet.common.client.utils.Sha256Sm3Hash; - -@Slf4j -public class ScanBlockTools { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("witness.key5"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("witness.key4"); - private final byte[] testAddress003 = PublicMethed.getFinalAddress(testKey003); - - private final String testKey004 = Configuration.getByPath("testng.conf") - .getString("witness.key3"); - private final byte[] testAddress004 = PublicMethed.getFinalAddress(testKey004); - ArrayList txidList = new ArrayList(); - Optional infoById = null; - Long beforeTime; - Long afterTime; - Long beforeBlockNum; - Long afterBlockNum; - Block currentBlock; - Long currentBlockNum; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = "39.106.110.245:50051"; - private String fullnode1 = "39.106.110.245:50051"; - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKey002); - PublicMethed.printAddress(testKey003); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - currentBlock = blockingStubFull1.getNowBlock(EmptyMessage.newBuilder().build()); - beforeBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - beforeTime = System.currentTimeMillis(); - } - - public static List listForTxid = new ArrayList<>(); - public static HashMap map = new HashMap<>(); - public static HashMap witnessMap = new HashMap<>(); - - @Test(enabled = true,threadPoolSize = 1, invocationCount = 1) - public void test01ScanTransaction() { - getTxidList(); - witnessMap.clear(); - map.clear(); - witnessMap.put(5,"41F08012B4881C320EB40B80F1228731898824E09D"); - witnessMap.put(10,"41DF309FEF25B311E7895562BD9E11AAB2A58816D2"); - witnessMap.put(15,"41BB7322198D273E39B940A5A4C955CB7199A0CDEE"); - witnessMap.put(20,"412080D8A0364E82150DD5235CE7A61A7B40F3F9EF"); - witnessMap.put(25,"4173FC381D3E2AFEFCCED94A57D49520291C38AFBB"); - witnessMap.put(30,"41AF6146B0AD9EE8BBEE811D5858F3252666DFC90C"); - witnessMap.put(35,"41AF6A9D9C0636BD9DF74F687B90C6F44C471A6AB3"); - witnessMap.put(40,"41AF730429E4AB7BF7B53FB15ACB1D45EF5B22F463"); - witnessMap.put(45,"41AF4AEA1C4CBCFA681D98C354C142938381C99389"); - witnessMap.put(50,"41AF53DC31D9DE64DFF59A847125EFCA89D97BC86D"); - witnessMap.put(55,"41AF49468FA1BA966244D76F7D0139FC2CA751FAA5"); - witnessMap.put(60,"41AF5360256F958D2A922D160C429F13D432EFC22F"); - witnessMap.put(65,"41AF5EF33FD79FECB0419A5688035D7BCD3AEFE236"); - witnessMap.put(70,"41AF68F90ED62BA9F6F7A7EABA384E417551CF83E5"); - witnessMap.put(75,"41AF619F8CE75A9E95A19E851BEBE63E89FCB1826E"); - witnessMap.put(80,"41AF71E98F91515D7E5D5379837B9EEFD1AB4650D2"); - witnessMap.put(85,"41AF498B43EE098B26926798CFEAE1AB1154EF4430"); - witnessMap.put(90,"41AF536672333170CB0FBFA78819CD90A05537D872"); - witnessMap.put(95,"41AF5FAC2D62DD1F5C9892BA9D6593337ABBEAAACB"); - witnessMap.put(100,"41AF6981D4562E7B0A6C9E8F8C22D4CCCD03D2F39A"); - witnessMap.put(105,"41AF72A34243836238A533B7E77F3B2B29FD056B14"); - witnessMap.put(110,"41AF49C25D14AED36186B7C89AF405EF37A01EF23D"); - witnessMap.put(115,"41AF53BA37D394575CAD99A2A2C5BE56DEA0227C87"); - witnessMap.put(120,"41AF6A761C941AE2CDC75890D9900AC4B89B7EFCDD"); - witnessMap.put(125,"41AF72B56845F0C4D37388B6E6DC3601A0538ABA71"); - witnessMap.put(130,"41AF4ACF25C1E192285C9BA98522CB3CF20FFBE392"); - witnessMap.put(100000,"416C0214C9995C6F3A61AB23F0EB84B0CDE7FD9C7C"); - - - - for (String txid : listForTxid) { - - long blockNum = PublicMethed.getTransactionInfoById(txid,blockingStubFull) - .get().getBlockNumber(); - String witnessAddress = ByteArray.toHexString(PublicMethed - .getBlock(blockNum,blockingStubFull).getBlockHeader().getRawData() - .getWitnessAddress().toByteArray()); - - map.put(witnessAddress.toLowerCase(), map.getOrDefault(witnessAddress,0) + 1); - logger.info("end"); - } - - } - - - - - @Test(enabled = true,threadPoolSize = 1, invocationCount = 1) - public void test02ScanBlockGetTransactionAndWriteToCsv() { - witnessMap.clear(); - map.clear(); - witnessMap.put(5,"41F08012B4881C320EB40B80F1228731898824E09D"); - witnessMap.put(10,"41DF309FEF25B311E7895562BD9E11AAB2A58816D2"); - witnessMap.put(15,"41BB7322198D273E39B940A5A4C955CB7199A0CDEE"); - witnessMap.put(20,"412080D8A0364E82150DD5235CE7A61A7B40F3F9EF"); - witnessMap.put(25,"4173FC381D3E2AFEFCCED94A57D49520291C38AFBB"); - witnessMap.put(30,"41AF6146B0AD9EE8BBEE811D5858F3252666DFC90C"); - witnessMap.put(35,"41AF6A9D9C0636BD9DF74F687B90C6F44C471A6AB3"); - witnessMap.put(40,"41AF730429E4AB7BF7B53FB15ACB1D45EF5B22F463"); - witnessMap.put(45,"41AF4AEA1C4CBCFA681D98C354C142938381C99389"); - witnessMap.put(50,"41AF53DC31D9DE64DFF59A847125EFCA89D97BC86D"); - witnessMap.put(55,"41AF49468FA1BA966244D76F7D0139FC2CA751FAA5"); - witnessMap.put(60,"41AF5360256F958D2A922D160C429F13D432EFC22F"); - witnessMap.put(65,"41AF5EF33FD79FECB0419A5688035D7BCD3AEFE236"); - witnessMap.put(70,"41AF68F90ED62BA9F6F7A7EABA384E417551CF83E5"); - witnessMap.put(75,"41AF619F8CE75A9E95A19E851BEBE63E89FCB1826E"); - witnessMap.put(80,"41AF71E98F91515D7E5D5379837B9EEFD1AB4650D2"); - witnessMap.put(85,"41AF498B43EE098B26926798CFEAE1AB1154EF4430"); - witnessMap.put(90,"41AF536672333170CB0FBFA78819CD90A05537D872"); - witnessMap.put(95,"41AF5FAC2D62DD1F5C9892BA9D6593337ABBEAAACB"); - witnessMap.put(100,"41AF6981D4562E7B0A6C9E8F8C22D4CCCD03D2F39A"); - witnessMap.put(105,"41AF72A34243836238A533B7E77F3B2B29FD056B14"); - witnessMap.put(110,"41AF49C25D14AED36186B7C89AF405EF37A01EF23D"); - witnessMap.put(115,"41AF53BA37D394575CAD99A2A2C5BE56DEA0227C87"); - witnessMap.put(120,"41AF6A761C941AE2CDC75890D9900AC4B89B7EFCDD"); - witnessMap.put(125,"41AF72B56845F0C4D37388B6E6DC3601A0538ABA71"); - witnessMap.put(130,"41AF4ACF25C1E192285C9BA98522CB3CF20FFBE392"); - witnessMap.put(100000,"416C0214C9995C6F3A61AB23F0EB84B0CDE7FD9C7C"); - - - Long startNum = 30855000L; - Long endNum = 30858000L; - - Integer totalNum = 0; - Integer successNum = 0; - Integer failedNum = 0; - NumberMessage.Builder builder = NumberMessage.newBuilder(); - while (endNum >= startNum) { - logger.info("scan block num:" + endNum); - builder.setNum(endNum); - Block block = blockingStubFull1.getBlockByNum(builder.build()); - List transactionList = block.getTransactionsList(); - map.put(ByteArray.toHexString(block.getBlockHeader().getRawData().getWitnessAddress() - .toByteArray()).toLowerCase(), - map.getOrDefault(ByteArray.toHexString(block.getBlockHeader().getRawData() - .getWitnessAddress().toByteArray()).toLowerCase(),0) + 1); - Integer transactionNumInThisBlock = transactionList.size(); - totalNum = totalNum + transactionNumInThisBlock; - for (Transaction transaction : transactionList) { - String txid = ByteArray.toHexString(Sha256Hash.hash(true, - transaction.getRawData().toByteArray())); - //String writeData = ByteArray.toHexString(Sha256Hash.hash(true, - // transaction.getRawData().toByteArray())); - writeDataToCsvFile("txid-stressss.csv",txid); - //System.out.println("Fee:" + PublicMethed.getTransactionInfoById(txid, - // blockingStubFull).get().getFee()); - } - for (Transaction transaction : transactionList) { - if (transaction.getRet(0).getContractRet().name().equals("SUCCESS")) { - successNum++; - } else { - failedNum++; - - String writeData = ByteArray.toHexString(Sha256Hash.hash(true, - transaction.getRawData().toByteArray())); - logger.info(writeData); - writeDataToCsvFile("28164160L-28167324L.csv",writeData); - } - } - endNum--; - } - - logger.info("successNum:" + successNum); - logger.info("failedNum:" + failedNum); - logger.info("totalNum:" + totalNum); - logger.info("Success rate:" + (double)failedNum / (double)totalNum); - - - } - - public static Account account; - public HashSet addressSet = new HashSet<>(); - public HashSet assetIssueSet = new HashSet<>(); - - @Test(enabled = true, description = "Get account from transaction and compare " - + "account info from two different node") - public void test03CompareTwoNodeAccountStatus() throws Exception { - account = PublicMethed.queryAccount( - "7400E3D0727F8A61041A8E8BF86599FE5597CE19DE451E59AED07D60967A5E25",blockingStubFull); - //扫描到28307530块了 - Long startNum = 29266108L; - Long endNum = 29266208L; - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(startNum); - int retryTimes = 0; - HashSet set = new HashSet<>(); - while (startNum++ <= endNum) { - //Block block = blockingStubFull412.getNowBlock(EmptyMessage.newBuilder().build()); - builder.setNum(startNum); - Block block = blockingStubFull.getBlockByNum(builder.build()); - logger.info("Start to scan block :" + block.getBlockHeader().getRawData().getNumber()); - - List transactionList = block.getTransactionsList(); - for (Transaction transaction : transactionList) { - - Any any = transaction.getRawData().getContract(0).getParameter(); - Integer contractType = transaction.getRawData().getContract(0).getType().getNumber(); - - - try { - switch (contractType) { - case 1: - TransferContract transferContract = any.unpack(TransferContract.class); - set.add(transferContract.getOwnerAddress()); - break; - case 2: - TransferAssetContract transferAssetContract = any.unpack(TransferAssetContract.class); - doCheck(transferAssetContract.getOwnerAddress()); - if (!addressSet.contains(transferAssetContract.getAssetName())) { - Assert.assertEquals(PublicMethed.getAssetIssueById(ByteArray - .toStr(transferAssetContract.getAssetName().toByteArray()), - blockingStubFull), - PublicMethed.getAssetIssueById(ByteArray.toStr(transferAssetContract - .getAssetName().toByteArray()), blockingStubFull)); - addressSet.add(transferAssetContract.getAssetName()); - logger.info("check token " + ByteArray.toStr(transferAssetContract - .getAssetName().toByteArray()) + " successfully"); - } - break; - case 31: - TriggerSmartContract triggerSmartContract = any.unpack(TriggerSmartContract.class); - doCheck(triggerSmartContract.getOwnerAddress()); - break; - case 13: - WithdrawBalanceContract withdrawBalanceContract - = any.unpack(WithdrawBalanceContract.class); - doCheck(withdrawBalanceContract.getOwnerAddress()); - break; - case 11: - FreezeBalanceContract freezeBalanceContract = any.unpack(FreezeBalanceContract.class); - doCheck(freezeBalanceContract.getOwnerAddress()); - break; - case 0: - AccountCreateContract accountCreateContract = any.unpack(AccountCreateContract.class); - doCheck(accountCreateContract.getOwnerAddress()); - break; - /* case 4: - VoteWitnessContract voteWitnessContract = any.unpack(VoteWitnessContract.class); - doCheck(voteWitnessContract.getOwnerAddress());*/ - case 12: - UnfreezeBalanceContract unfreezeBalanceContract - = any.unpack(UnfreezeBalanceContract.class); - doCheck(unfreezeBalanceContract.getOwnerAddress()); - break; - case 30: - CreateSmartContract createSmartContract = any.unpack(CreateSmartContract.class); - doCheck(createSmartContract.getOwnerAddress()); - break; - case 46: - AccountPermissionUpdateContract accountPermissionUpdateContract - = any.unpack(AccountPermissionUpdateContract.class); - doCheck(accountPermissionUpdateContract.getOwnerAddress()); - break; - default: - logger.info("Unknown type:" + contractType); - continue; - - } - } catch (Exception e) { - e.printStackTrace(); - - } - - - - - - } - } - - - } - - - @Test(enabled = true, description = "Get all info from smart contract transaction list") - public void test04GetEventTransactionAllInfoList() throws Exception { - - - - HashSet contractAndTopicList = new HashSet<>(); - - - Long startNum = 33662515L - 9500; - Long endNum = startNum - 1000; - - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(startNum); - int retryTimes = 0; - HashSet set = new HashSet<>(); - while (startNum-- >= endNum) { - logger.info("current block num:" + startNum); - builder.setNum(startNum); - TransactionInfoList transactionInfoList = blockingStubFull - .getTransactionInfoByBlockNum(builder.build()); - - for (TransactionInfo transactionInfo : transactionInfoList.getTransactionInfoList()) { - if (!transactionInfo.getContractAddress().isEmpty() && transactionInfo.getLogCount() > 0) { - try { - String txid = ByteArray.toHexString(transactionInfo.getId().toByteArray()); - Any any = PublicMethed.getTransactionById(txid, blockingStubFull).get().getRawData() - .getContract(0).getParameter(); - TriggerSmartContract triggerSmartContract = any.unpack(TriggerSmartContract.class); - StringBuffer stringBuffer = new StringBuffer(); - stringBuffer.append(ByteArray.toHexString(triggerSmartContract - .getOwnerAddress().toByteArray())); - stringBuffer.append(","); - stringBuffer.append(ByteArray.toHexString(transactionInfo - .getContractAddress().toByteArray())); - stringBuffer.append(","); - stringBuffer.append(ByteArray.toHexString(triggerSmartContract - .getData().toByteArray())); - stringBuffer.append(","); - //stringBuffer.append(blockHash); - //stringBuffer.append(","); - //stringBuffer.append(startNum); - //stringBuffer.append(","); - stringBuffer.append(txid); - - - - - contractAndTopicList.add(stringBuffer.toString()); - - ; - } catch (Exception e) { - e.printStackTrace(); - - } - } - - - - - } - } - - for (String contractAddressAndTopic : contractAndTopicList) { - writeDataToCsvFile("eth_blockHash.csv", contractAddressAndTopic); - } - - - - } - - - @Test(enabled = true, description = "Get eth block query information") - public void test05CreateEthBlockHash() throws Exception { - HashSet contractAndTopicList = new HashSet<>(); - - - Long startNum = 33662515L; - Long endNum = startNum - 20000; - - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(startNum); - int retryTimes = 0; - HashSet set = new HashSet<>(); - while (startNum-- >= endNum) { - logger.info("current block num:" + startNum); - builder.setNum(startNum); - String blockHash = ByteArray.toHexString(PublicMethed.getBlock(startNum + 1, - blockingStubFull).getBlockHeader().getRawData().getParentHash().toByteArray()); - StringBuffer stringBuffer = new StringBuffer(); - stringBuffer.append(blockHash); - stringBuffer.append(","); - stringBuffer.append(startNum); - contractAndTopicList.add(stringBuffer.toString()); - } - - for (String contractAddressAndTopic : contractAndTopicList) { - writeDataToCsvFile("eth_blockHash.csv", contractAddressAndTopic); - } - - - - } - - - ConcurrentHashMap certificationCosts = new ConcurrentHashMap<>(); - Set concurrentHashSet = certificationCosts.newKeySet(); - private static HashSet existAddress = new HashSet<>(); - List list1 = new ArrayList<>(); - - private static AtomicLong blockNum = new AtomicLong(30000523L - 20000L); - private static AtomicLong times = new AtomicLong(5); - - @Test(enabled = true, threadPoolSize = 10, invocationCount = 10) - public void test06ScanMainNetMostActiveAccounts() throws Exception { - getNowAddressList(); - ManagedChannel channelFull = null; - WalletGrpc.WalletBlockingStub blockingStubFull = null; - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - NumberMessage.Builder builder = NumberMessage.newBuilder(); - long blockNumCurrent = blockNum.getAndAdd(-200); - int times = 200; - while (times-- >= 0) { - if (concurrentHashSet.size() > 1000000) { - break; - } - //list1.add(blockNumCurrent); - builder.setNum(blockNumCurrent--); - Block block = blockingStubFull.getBlockByNum(builder.build()); - logger.info("Start to scan block :" + block.getBlockHeader().getRawData().getNumber()); - - List transactionList = block.getTransactionsList(); - for (Transaction transaction : transactionList) { - - Any any = transaction.getRawData().getContract(0).getParameter(); - Integer contractType = transaction.getRawData().getContract(0).getType().getNumber(); - - - try { - switch (contractType) { - case 1: - TransferContract transferContract = any.unpack(TransferContract.class); - isExist(transferContract.getOwnerAddress()); - isExist(transferContract.getToAddress()); - break; - case 2: - TransferAssetContract transferAssetContract = any.unpack(TransferAssetContract.class); - isExist(transferAssetContract.getOwnerAddress()); - isExist(transferAssetContract.getToAddress()); - break; - case 31: - TriggerSmartContract triggerSmartContract = any.unpack(TriggerSmartContract.class); - isExist(triggerSmartContract.getContractAddress()); - isExist(triggerSmartContract.getOwnerAddress()); - break; - case 13: - WithdrawBalanceContract withdrawBalanceContract - = any.unpack(WithdrawBalanceContract.class); - - isExist(withdrawBalanceContract.getOwnerAddress()); - break; - case 11: - FreezeBalanceContract freezeBalanceContract = any.unpack(FreezeBalanceContract.class); - isExist(freezeBalanceContract.getOwnerAddress()); - break; - case 0: - AccountCreateContract accountCreateContract = any.unpack(AccountCreateContract.class); - isExist(accountCreateContract.getOwnerAddress()); - isExist(accountCreateContract.getAccountAddress()); - break; - case 12: - UnfreezeBalanceContract unfreezeBalanceContract - = any.unpack(UnfreezeBalanceContract.class); - isExist(unfreezeBalanceContract.getOwnerAddress()); - break; - case 30: - CreateSmartContract createSmartContract = any.unpack(CreateSmartContract.class); - isExist(createSmartContract.getOwnerAddress()); - break; - case 46: - AccountPermissionUpdateContract accountPermissionUpdateContract - = any.unpack(AccountPermissionUpdateContract.class); - isExist(accountPermissionUpdateContract.getOwnerAddress()); - break; - case 4: - VoteWitnessContract voteWitnessContract = any.unpack(VoteWitnessContract.class); - isExist(voteWitnessContract.getOwnerAddress()); - break; - default: - logger.info("Unknown type:" + contractType); - continue; - - } - } catch (Exception e) { - e.printStackTrace(); - - } - - - - - - - } - } - - - - - } - - - - @Test(enabled = true, threadPoolSize = 1, invocationCount = 1) - public void test07ScanAndCalculateTotalValueOrCallValue() throws Exception { - getNowAddressList(); - ManagedChannel channelFull = null; - WalletGrpc.WalletBlockingStub blockingStubFull = null; - channelFull = ManagedChannelBuilder.forTarget("47.252.19.181:50051") - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - int total1 = 0; - int total2 = 0; - int totalTrx = 0; - for (long blockNum = 20450668L; blockNum <= 20450790L;blockNum++) { - System.out.println("blockNum " + blockNum); - TransactionInfoList transactionList = PublicMethed.getTransactionInfoByBlockNum(blockNum, - blockingStubFull).get(); - for (int i = 0; i < transactionList.getTransactionInfoCount();i++) { - if (ByteArray.toHexString(transactionList.getTransactionInfo(i).getContractAddress() - .toByteArray()).equalsIgnoreCase("41DF42D1936F0DC3689BB65A19F279747084E13FBD")) { - - - if (ByteArray.toHexString(transactionList.getTransactionInfo(i).getLog(0) - .getTopics(0).toByteArray()).equalsIgnoreCase( - "9b217a401a5ddf7c4d474074aff9958a18d48690d77cc2151c4706aa7348b401")) { - total1 += Integer.parseInt(ByteArray.toHexString(transactionList.getTransactionInfo(i) - .getLog(0).getData().toByteArray()),16); - } else if (ByteArray.toHexString(transactionList.getTransactionInfo(i).getLog(0) - .getTopics(0).toByteArray()).equalsIgnoreCase( - "31472eae9e158460fea5622d1fcb0c5bdc65b6ffb51827f7bc9ef5788410c34c")) { - total2 += Integer.parseInt(ByteArray.toHexString(transactionList.getTransactionInfo(i) - .getLog(0).getData().toByteArray()),16); - } else if (ByteArray.toHexString(transactionList.getTransactionInfo(i).getLog(0) - .getTopics(0).toByteArray()).equalsIgnoreCase( - "3e799b2d61372379e767ef8f04d65089179b7a6f63f9be3065806456c7309f1b")) { - totalTrx += transactionList.getTransactionInfo(i).getInternalTransactions(4) - .getCallValueInfo(0).getCallValue(); - } - - } - } - } - - System.out.println("total1 :" + total1); - System.out.println("total2 :" + total2); - System.out.println("total_callValue :" + totalTrx); - - } - - - - @Test - public void test08ScanAndCalculateWitnessProductBlockStatus() { - Long startNum = 33694340L; - Long endNum = 33694388L; - - Integer testgroup014 = 0; - Integer testgroup015 = 0; - Integer testgroup016 = 0; - Integer testgroup017 = 0; - Integer testgroup018 = 0; - - int transfer = 0; - int trigger = 0; - - while (startNum++ <= endNum) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(startNum); - Block block = blockingStubFull.getBlockByNum(builder.build()); - logger.info("current block:" + startNum); - - String currentAddress = ByteArray.toHexString(block.getBlockHeader().getRawData() - .getWitnessAddress().toByteArray()); - List transactionList = block.getTransactionsList(); - for (Transaction transaction : transactionList) { - if (transaction.getRawData().getContract(0).getType().equals(ContractType - .TriggerSmartContract)) { - trigger++; - } else { - transfer++; - } - } - if (currentAddress.equals(getHexAddress( - "0528dc17428585fc4dece68b79fa7912270a1fe8e85f244372f59eb7e8925e04")) - || currentAddress - .equals(getHexAddress( - "dbc78781ad27f3751358333412d5edc85b13e5eee129a1a77f7232baadafae0e")) - || currentAddress - .equals(getHexAddress( - "a79a37a3d868e66456d76b233cb894d664b75fd91861340f3843db05ab3a8c66")) - || currentAddress - .equals(getHexAddress( - "a8107ea1c97c90cd4d84e79cd79d327def6362cc6fd498fc3d3766a6a71924f6")) - || currentAddress - .equals(getHexAddress( - "b5076206430b2ca069ae2f4dc6f20dd0d74551559878990d1df12a723c228039")) - || currentAddress - .equals(getHexAddress( - "87cc8832b1b4860c3c69994bbfcdae9b520e6ce40cbe2a90566e707a7e04fc70")) - ) { - testgroup014++; - continue; - } - - if (currentAddress.equals(getHexAddress( - "553c7b0dee17d3f5b334925f5a90fe99fb0b93d47073d69ec33eead8459d171e")) - || currentAddress - .equals(getHexAddress( - "541a2d585fcea7e9b1803df4eb49af0eb09f1fa2ce06aa5b8ed60ac95655d66d")) - || currentAddress - .equals(getHexAddress( - "7d5a7396d6430edb7f66aa5736ef388f2bea862c9259de8ad8c2cfe080f6f5a0")) - || currentAddress - .equals(getHexAddress( - "7c4977817417495f4ca0c35ab3d5a25e247355d68f89f593f3fea2ab62c8644f")) - || currentAddress - .equals(getHexAddress( - "4521c13f65cc9f5c1daa56923b8598d4015801ad28379675c64106f5f6afec30")) - || currentAddress - .equals(getHexAddress( - "442513e2e801bc42d14d33b8148851dae756d08eeb48881a44e1b2002b3fb700")) - ) { - testgroup015++; - continue; - } - - if (currentAddress.equals(getHexAddress( - "324a2052e491e99026442d81df4d2777292840c1b3949e20696c49096c6bacb8")) - || currentAddress - .equals(getHexAddress( - "f33101ea976d90491dcb9669be568db8bbc1ad23d90be4dede094976b67d550e")) - || currentAddress - .equals(getHexAddress( - "1bb32958909299db452d3c9bbfd15fd745160d63e4985357874ee57708435a00")) - || currentAddress - .equals(getHexAddress( - "29c91bd8b27c807d8dc2d2991aa0fbeafe7f54f4de9fac1e1684aa57242e3922")) - || currentAddress - .equals(getHexAddress( - "97317d4d68a0c5ce14e74ad04dfc7521f142f5c0f247b632c8f94c755bdbe669")) - ) { - testgroup016++; - continue; - } - - if (currentAddress.equals(getHexAddress( - "ff5d867c4434ac17d264afc6696e15365832d5e8000f75733ebb336d66df148d")) - || currentAddress - .equals(getHexAddress( - "1fe1d91bbe3ac4ac5dc9866c157ef7615ec248e3fd4f7d2b49b0428da5e046b2")) - || currentAddress - .equals(getHexAddress( - "7c37ef485e186e07952bcc8e30cd911a6cd9f2a847736c89132762fb67a42329")) - || currentAddress - .equals(getHexAddress( - "bcc142d57d872cd2cc1235bca454f2efd5a87f612856c979cc5b45a7399272a8")) - || currentAddress - .equals(getHexAddress( - "6054824dc03546f903a06da1f405e72409379b83395d0bbb3d4563f56e828d52")) - ) { - testgroup017++; - continue; - } - - testgroup018++; - } - - - logger.info(testgroup014 + " " + testgroup015 + " " - + testgroup016 + " " + testgroup017 + " " + testgroup018); - - logger.info(transfer + " " + trigger); - - - } - - - @Test - public void test09GetEthFilterData() { - - HashSet set = new HashSet<>(); - Integer startBlockNumber = 35129811 - 2000; - Integer endBlockNumber = startBlockNumber - 3000; - - for (int blockNumber = startBlockNumber; blockNumber >= endBlockNumber;blockNumber-- - ) { - set.clear(); - HttpResponse response = HttpMethed - .getTransactionInfoByBlocknum("1.1.1.1:90", blockNumber); - - List content = HttpMethed.parseResponseContentArray(response); - - String blockNumberHex = "0x" + Integer.toHexString(blockNumber); - - System.out.println(content.size()); - for (JSONObject info : content) { - if (!info.containsKey("log")) { - continue; - } - JSONArray logArray = info.getJSONArray("log"); - for (int i = 0; i < logArray.size();i++) { - JSONObject log = logArray.getJSONObject(i); - String address = "0x" + log.getString("address"); - String topic = "0x" + log.getJSONArray("topics").getString(0); - set.add(address + "," + topic + "," + blockNumberHex); - - } - - - - - } - - for (String data : set) { - writeDataToCsvFile("ys_filter_api.csv", data); - } - } - - - } - - public String getHexAddress(String key) { - return ByteArray.toHexString(PublicMethed.getFinalAddress(key)); - } - - private static HashSet getFileList(String fileName,HashSet set) { - String line = null; - try { - BufferedReader bufferedReader = - new BufferedReader(new InputStreamReader(new FileInputStream(fileName),"utf-8")); - - while ((line = bufferedReader.readLine()) != null) { - set.add(line); - } - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - return set; - } - - - - - private static void getNowAddressList() { - String line = null; - try { - //BufferedReader bufferedReader=new BufferedReader(new FileReader(filePath)); - BufferedReader bufferedReader = - new BufferedReader(new InputStreamReader(new FileInputStream("newAddress.csv"),"utf-8")); - - //int i=0; - while ((line = bufferedReader.readLine()) != null) { - existAddress.add(line); - } - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - - /** - * constructor. - */ - public static void writeDataToCsvFile(String fileName,String writeData) { - - { - try { - File file = new File(fileName); - - if (!file.exists()) { - file.createNewFile(); - } - FileWriter fileWritter = new FileWriter(file.getName(), true); - fileWritter.write(writeData + "\n"); - fileWritter.close(); - //System.out.println("finish"); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - - /** - * constructor. - */ - public void doCheck(ByteString address) throws Exception { - if (addressSet.contains(address)) { - //logger.info("skip :" + ByteArray.toHexString(address.toByteArray())); - return; - } else { - addressSet.add(address); - } - logger.info("checking :" + ByteArray.toHexString(address.toByteArray())); - compareTwoAddress(address); - compareNet(address); - compareAccountResource(address); - return; - - } - - /** - * constructor. - */ - public void compareTwoAddress(ByteString address) { - - Assert.assertEquals( - PublicMethed.queryAccount(address.toByteArray(),blockingStubFull).toBuilder() - .clearFreeAssetNetUsageV2() - //.putAllFreeAssetNetUsageV2(account.getFreeAssetNetUsageV2Map()) - .setBalance(1L).setLatestOprationTime(1L) - .setAccountResource(AccountResource.newBuilder()) - .setFreeNetUsage(1L) - .setNetUsage(1L) - .clearAssetV2() - .setLatestConsumeFreeTime(1L) - .setLatestConsumeTime(1L) - .setAllowance(1L) - .clearAccountResource() - //.clearOldVotePower() - .build(), - PublicMethed.queryAccount(address.toByteArray(),blockingStubFull).toBuilder() - .clearFreeAssetNetUsageV2() - //.putAllFreeAssetNetUsageV2(account.getFreeAssetNetUsageV2Map()) - .setBalance(1L).setLatestOprationTime(1L) - .setAccountResource(AccountResource.newBuilder()) - .setFreeNetUsage(1L) - .setNetUsage(1L) - .setLatestConsumeFreeTime(1L) - .setLatestConsumeTime(1L) - .clearAssetV2() - .setAllowance(1L) - .clearAccountResource() - .build() - ); - - } - - - /** - * constructor. - */ - public void compareNet(ByteString address) { - Assert.assertEquals( - PublicMethed.getAccountNet(address.toByteArray(),blockingStubFull) - .toBuilder().setTotalNetWeight(1L) - .setNetUsed(1L) - .setFreeNetUsed(1) - .setNetLimit(1) - .build(), - PublicMethed.getAccountNet(address.toByteArray(),blockingStubFull) - .toBuilder().setTotalNetWeight(1L) - .setNetUsed(1L) - .setFreeNetUsed(1) - .setNetLimit(1) - .build() - ); - } - - /** - * constructor. - */ - public void compareAccountResource(ByteString address) throws Exception { - Assert.assertEquals( - PublicMethed.getAccountResource(address.toByteArray(),blockingStubFull) - .toBuilder() - .setFreeNetUsed(1L) - .setEnergyUsed(1L) - .setTotalEnergyWeight(1L) - .setTotalNetWeight(1L) - .setNetUsed(1L) - .setNetLimit(1L) - .setEnergyLimit(1L) - .build(), - PublicMethed.getAccountResource(address.toByteArray(),blockingStubFull) - .toBuilder() - .setFreeNetUsed(1L) - .setEnergyUsed(1L) - .setNetUsed(1L) - .setNetLimit(1L) - .setTotalEnergyWeight(1L) - .setTotalNetWeight(1L) - .setEnergyLimit(1L) - .build() - ); - - } - - /** - * constructor. - */ - public boolean isEqual(ByteString address) { - return PublicMethed.getAccountResource(address.toByteArray(),blockingStubFull) - .toBuilder() - .setFreeNetUsed(1L) - .setEnergyUsed(1L) - .setTotalEnergyWeight(1L) - .setTotalNetWeight(1L) - .setNetUsed(1L) - .setNetLimit(1L) - .setEnergyLimit(1L) - .build().equals(PublicMethed.getAccountResource(address.toByteArray(),blockingStubFull) - .toBuilder() - .setFreeNetUsed(1L) - .setEnergyUsed(1L) - .setTotalEnergyWeight(1L) - .setTotalNetWeight(1L) - .setNetUsed(1L) - .setNetLimit(1L) - .setEnergyLimit(1L) - .build()); - - } - - /** - * constructor. - */ - public void isExist(ByteString address1) { - byte[] address = address1.toByteArray(); - byte[] hash0 = Sha256Sm3Hash.hash(address); - byte[] hash1 = Sha256Sm3Hash.hash(hash0); - byte[] checkSum = Arrays.copyOfRange(hash1, 0, 4); - byte[] addchecksum = new byte[address.length + 4]; - System.arraycopy(address, 0, addchecksum, 0, address.length); - System.arraycopy(checkSum, 0, addchecksum, address.length, 4); - if (!existAddress.contains(Base58.encode(addchecksum))) { - concurrentHashSet.add(address1); - } - } - - /** - * constructor. - */ - private static void getTxidList() { - String line = null; - try { - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new - FileInputStream("demo.csv"),"utf-8")); - - while ((line = bufferedReader.readLine()) != null) { - listForTxid.add(line.toLowerCase()); - - } - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - List list = new ArrayList<>(concurrentHashSet); - for (ByteString target : list) { - byte[] address = target.toByteArray(); - byte[] hash0 = Sha256Sm3Hash.hash(address); - byte[] hash1 = Sha256Sm3Hash.hash(hash0); - byte[] checkSum = Arrays.copyOfRange(hash1, 0, 4); - byte[] addchecksum = new byte[address.length + 4]; - System.arraycopy(address, 0, addchecksum, 0, address.length); - System.arraycopy(checkSum, 0, addchecksum, address.length, 4); - writeDataToCsvFile("newAddress.csv", Base58.encode(addchecksum)); - } - Collections.sort(list1); - - - int i = 1; - /* - afterTime = System.currentTimeMillis(); - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - currentBlock = blockingStubFull1.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - afterBlockNum = currentBlock.getBlockHeader().getRawData().getNumber() + 2; - Long blockNum = beforeBlockNum; - Integer txsNum = 0; - Integer topNum = 0; - Integer totalNum = 0; - Long energyTotal = 0L; - String findOneTxid = ""; - - NumberMessage.Builder builder = NumberMessage.newBuilder(); - while (blockNum <= afterBlockNum) { - builder.setNum(blockNum); - txsNum = blockingStubFull1.getBlockByNum(builder.build()).getTransactionsCount(); - totalNum = totalNum + txsNum; - if (topNum < txsNum) { - topNum = txsNum; - findOneTxid = ByteArray.toHexString(Sha256Hash.hash(blockingStubFull1 - .getBlockByNum(builder.build()).getTransactionsList().get(2) - .getRawData().toByteArray())); - //logger.info("find one txid is " + findOneTxid); - } - - blockNum++; - } - Long costTime = (afterTime - beforeTime - 31000) / 1000; - logger.info("Duration block num is " + (afterBlockNum - beforeBlockNum - 11)); - logger.info("Cost time are " + costTime); - logger.info("Top block txs num is " + topNum); - logger.info("Total transaction is " + (totalNum - 30)); - logger.info("Average Tps is " + (totalNum / costTime)); - - infoById = PublicMethed.getTransactionInfoById(findOneTxid, blockingStubFull1); - Long oneEnergyTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("EnergyTotal is " + oneEnergyTotal); - logger.info("Average energy is " + oneEnergyTotal * (totalNum / costTime)); - */ - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/ShieldTrc10Stress.java b/framework/src/test/java/stest/tron/wallet/onlinestress/ShieldTrc10Stress.java deleted file mode 100644 index bb89f4da195..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/ShieldTrc10Stress.java +++ /dev/null @@ -1,147 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.DecryptNotes; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.config.args.Args; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; - -@Slf4j -public class ShieldTrc10Stress { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - List shieldOutList = new ArrayList<>(); - DecryptNotes notes; - Note note; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey1.getAddress(); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] receiverPublicAddress = ecKey2.getAddress(); - String receiverPublicKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - Optional sendShieldAddressInfo; - String sendshieldAddress; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private byte[] tokenId = zenTokenId.getBytes(); - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long costTokenAmount = 20000 * zenTokenFee; - private Long zenTokenWhenCreateNewAddress = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenWhenCreateNewAddress"); - - - /** - * constructor. - */ - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - Args.setFullNodeAllowShieldedTransaction(true); - PublicMethed.printAddress(foundationZenTokenKey); - PublicMethed.printAddress(zenTokenOwnerKey); - ManagedChannel channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - WalletGrpc.WalletBlockingStub blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - sendShieldAddressInfo = PublicMethed.generateShieldAddress(); - sendshieldAddress = sendShieldAddressInfo.get().getAddress(); - - String memo = "Use to TestZenToken004 shield address"; - List shieldOutList = new ArrayList<>(); - shieldOutList.clear(); - - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendshieldAddress, - "" + costTokenAmount, memo); - Assert.assertTrue(PublicMethed.sendShieldCoin( - foundationZenTokenAddress, costTokenAmount + zenTokenFee, - null, null, - shieldOutList, - null, 0, - foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - - } - - @Test(enabled = true, threadPoolSize = 100, invocationCount = 100) - public void test1Shield2TwoShieldTransaction() { - ManagedChannel channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - WalletGrpc.WalletBlockingStub blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - DecryptNotes notes; - List shieldOutList = new ArrayList<>(); - - Integer times = 100; - while (times-- > 0) { - notes = PublicMethed.listShieldNote(sendShieldAddressInfo, blockingStubFull); - //logger.info("note size:" + notes.getNoteTxsCount()); - - String memo1 = "Shield to shield address1 transaction" + System.currentTimeMillis(); - shieldOutList.clear(); - Long sendToShiledAddress1Amount = - notes.getNoteTxs(notes.getNoteTxsCount() - 1).getNote().getValue() - zenTokenFee; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendshieldAddress, - "" + sendToShiledAddress1Amount, memo1); - - try { - PublicMethed.sendShieldCoin( - null, 0, - sendShieldAddressInfo.get(), notes.getNoteTxs(notes.getNoteTxsCount() - 1), - shieldOutList, - null, 0, - zenTokenOwnerKey, blockingStubFull); - } catch (Exception e) { - throw e; - } - } - - } - - @AfterClass(enabled = false) - public void shutdown() throws InterruptedException { - PublicMethed.transferAsset(foundationZenTokenAddress, tokenId, - PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull), zenTokenOwnerAddress, zenTokenOwnerKey, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/ShieldTrc20Stress.java b/framework/src/test/java/stest/tron/wallet/onlinestress/ShieldTrc20Stress.java deleted file mode 100644 index 4886502a48b..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/ShieldTrc20Stress.java +++ /dev/null @@ -1,719 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import com.alibaba.fastjson.JSONObject; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldedAddressInfo; -import stest.tron.wallet.common.client.utils.ZenTrc20Base; - -@Slf4j -public class ShieldTrc20Stress extends ZenTrc20Base { - - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - Optional sendShieldAddressInfo; - private BigInteger publicFromAmount; - List shieldOutList = new ArrayList<>(); - - private String httpnode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list").get(0); - - - private AtomicInteger finishMintNumber = new AtomicInteger(0); - private AtomicInteger finishCreateParameterNumber = new AtomicInteger(0); - private AtomicInteger finishTriggerNumber = new AtomicInteger(0); - private AtomicInteger noteNumber = new AtomicInteger(0); - private AtomicInteger dataNumber = new AtomicInteger(0); - private AtomicLong startTriggerNum = new AtomicLong(0); - private AtomicLong endTriggerNum = new AtomicLong(0); - private AtomicLong startmintNum = new AtomicLong(0); - private AtomicLong endmintNum = new AtomicLong(0); - private Integer thread = 40; - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - publicFromAmount = getRandomAmount(); - //startQureyNum = HttpMethed.getNowBlockNum(httpnode); - startmintNum.addAndGet(blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber()); - } - - /** - * wqs constructor. - */ - @Test(enabled = false, threadPoolSize = 50, invocationCount = 50) - public void test01ScanAndCreateThenTrigger() throws Exception { - ManagedChannel channelFull = null; - WalletGrpc.WalletBlockingStub blockingStubFull = null; - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - ManagedChannel channelFull1 = null; - WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - BigInteger publicFromAmount = getRandomAmount(); - Optional sendShieldAddressInfo = getNewShieldedAddress(blockingStubFull); - Optional receiverShieldAddressInfo = getNewShieldedAddress( - blockingStubFull); - String memo = "Shield trc20 from T account to shield account in" + System.currentTimeMillis(); - String sendShieldAddress = sendShieldAddressInfo.get().getAddress(); - - List shieldOutList = new ArrayList<>(); - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, sendShieldAddress, - "" + publicFromAmount, memo, blockingStubFull); - - //Create shiled trc20 parameters - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters - = createShieldedTrc20Parameters(publicFromAmount, - null, null, shieldOutList, "", 0L, - blockingStubFull, blockingStubSolidity - ); - - String data = encodeMintParamsToHexString(shieldedTrc20Parameters, publicFromAmount); - - //Do mint transaction type - String txid = PublicMethed.triggerContract(shieldAddressByte, - mint, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - sendShieldAddress = sendShieldAddressInfo.get().getAddress(); - List inputShieldAddressList = new ArrayList<>(); - GrpcAPI.DecryptNotesTRC20 sendNote; - List inputList = new ArrayList<>(); - inputShieldAddressList.add(sendShieldAddressInfo.get()); - - sendNote = scanShieldedTrc20NoteByIvk(sendShieldAddressInfo.get(), - blockingStubFull1); - - while (sendNote.getNoteTxsCount() == 0) { - sendNote = scanShieldedTrc20NoteByIvk(sendShieldAddressInfo.get(), - blockingStubFull1); - } - - Integer times = 20; - while (times-- > 0) { - //receiverShieldAddressInfo = getNewShieldedAddress(blockingStubFull); - //Scan sender note - /*sendNote = scanShieldedTrc20NoteByIvk(sendShieldAddressInfo.get(), - blockingStubFull1); - - while (sendNote.getNoteTxsCount() == 0) { - sendNote = scanShieldedTrc20NoteByIvk(sendShieldAddressInfo.get(), - blockingStubFull1); - }*/ - - sendNote = scanShieldedTrc20NoteByIvk(sendShieldAddressInfo.get(), - blockingStubFull1); - - String transferMemo = "Transfer type test " + System.currentTimeMillis(); - - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, sendShieldAddress, - "" + publicFromAmount, transferMemo, blockingStubFull); - - //logger.info("send note size:" + sendNote.getNoteTxsCount()); - - //Create transfer parameters - try { - GrpcAPI.DecryptNotesTRC20 inputNoteFor2to2 = GrpcAPI.DecryptNotesTRC20.newBuilder() - .addNoteTxs(sendNote.getNoteTxs(sendNote.getNoteTxsCount() - 1)).build(); - shieldedTrc20Parameters - = createShieldedTrc20Parameters(BigInteger.valueOf(0), - inputNoteFor2to2, inputShieldAddressList, shieldOutList, "", 0L, - blockingStubFull1, blockingStubSolidity); - } catch (Exception e) { - throw e; - } - - Integer exit = 7; - if (exit == 1) { - continue; - } - - data = encodeTransferParamsToHexString(shieldedTrc20Parameters); - txid = PublicMethed.triggerContract(shieldAddressByte, - transfer, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - - //sendShieldAddressInfo = receiverShieldAddressInfo; - } - - } - - - /** - * constructor. - */ - @Test(enabled = false, threadPoolSize = 40, invocationCount = 40) - public void test02FirstScanCreateParameterThenCreateTrigger() throws Exception { - ManagedChannel channelFull = null; - WalletGrpc.WalletBlockingStub blockingStubFull = null; - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - ManagedChannel channelFull1 = null; - WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - Optional sendShieldAddressInfo = getNewShieldedAddress(blockingStubFull); - Optional receiverShieldAddressInfo = getNewShieldedAddress( - blockingStubFull); - - Integer mintNumber = 50; - - while (--mintNumber >= 0) { - BigInteger publicFromAmount = getRandomAmount(); - - String memo = "Shield trc20 from T account to shield account in" + System.currentTimeMillis(); - String sendShieldAddress = sendShieldAddressInfo.get().getAddress(); - - List shieldOutList = new ArrayList<>(); - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, sendShieldAddress, - "" + publicFromAmount, memo, blockingStubFull); - - //Create shiled trc20 parameters - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters - = createShieldedTrc20Parameters(publicFromAmount, - null, null, shieldOutList, "", - 0L, blockingStubFull, blockingStubSolidity - ); - String data = ""; - try { - data = encodeMintParamsToHexString(shieldedTrc20Parameters, publicFromAmount); - } catch (Exception e) { - try { - data = encodeMintParamsToHexString(shieldedTrc20Parameters, publicFromAmount); - } catch (Exception e1) { - continue; - } - - } - - String txid = PublicMethed.triggerContract(shieldAddressByte, - mint, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - } - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - finishMintNumber.addAndGet(1); - endmintNum.getAndAdd(blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber()); - - while (finishMintNumber.get() != thread) { - try { - Thread.sleep(3000); - if (finishMintNumber.get() % 10 == 0) { - logger.info( - "Wait all thread finished mint,current finished thread is :" + finishMintNumber - .get()); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - Long endMintNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - - GrpcAPI.DecryptNotesTRC20 sendNote = scanShieldedTrc20NoteByIvkWithRange( - sendShieldAddressInfo.get(), - startmintNum.get(), endMintNum, blockingStubFull1); - - noteNumber.addAndGet(sendNote.getNoteTxsCount()); - - logger.info("sendNote size :" + sendNote.getNoteTxsCount()); - - List shieldOutList = new ArrayList<>(); - - List inputShieldAddressList = new ArrayList<>(); - - inputShieldAddressList.add(sendShieldAddressInfo.get()); - - List dataList = new ArrayList<>(); - for (int i = 0; i < sendNote.getNoteTxsCount() - 1; i = i + 2) { - GrpcAPI.DecryptNotesTRC20 inputNoteFor2to2 = GrpcAPI.DecryptNotesTRC20.newBuilder() - .addNoteTxs(sendNote.getNoteTxs(i)) - .addNoteTxs(sendNote.getNoteTxs(i + 1)) - .build(); - - String transferMemo1 = "Transfer1 type test " + getRandomLongAmount() + getRandomLongAmount(); - String transferMemo2 = "Transfer2 type test " + getRandomLongAmount() + getRandomLongAmount(); - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, - receiverShieldAddressInfo.get().getAddress(), - "" + sendNote.getNoteTxs(i).getNote().getValue(), transferMemo1, blockingStubFull); - shieldOutList = addShieldTrc20OutputList(shieldOutList, - receiverShieldAddressInfo.get().getAddress(), - "" + sendNote.getNoteTxs(i + 1).getNote().getValue(), transferMemo2, blockingStubFull); - - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters = null; - if (i % 2 == 0) { - try { - shieldedTrc20Parameters - = createShieldedTrc20Parameters(BigInteger.valueOf(0), - inputNoteFor2to2, inputShieldAddressList, shieldOutList, "", - 0L, blockingStubFull1, blockingStubSolidity); - } catch (Exception e) { - try { - shieldedTrc20Parameters - = createShieldedTrc20Parameters(BigInteger.valueOf(0), - inputNoteFor2to2, inputShieldAddressList, shieldOutList, "", - 0L, blockingStubFull, blockingStubSolidity); - } catch (Exception e1) { - throw e1; - } - - } - - } else { - try { - shieldedTrc20Parameters - = createShieldedTrc20Parameters(BigInteger.valueOf(0), - inputNoteFor2to2, inputShieldAddressList, shieldOutList, "", - 0L, blockingStubFull, blockingStubSolidity); - } catch (Exception e) { - try { - shieldedTrc20Parameters - = createShieldedTrc20Parameters(BigInteger.valueOf(0), - inputNoteFor2to2, inputShieldAddressList, shieldOutList, "", - 0L, blockingStubFull1, blockingStubSolidity); - } catch (Exception e2) { - throw e2; - } - - - } - } - - dataList.add(encodeTransferParamsToHexString(shieldedTrc20Parameters)); - //logger.info("dataList size:" + dataList.size()); - - } - - finishCreateParameterNumber.addAndGet(1); - dataNumber.addAndGet(dataList.size()); - while (finishCreateParameterNumber.get() != thread) { - try { - Thread.sleep(3000); - if (finishCreateParameterNumber.get() % 10 == 0) { - logger.info("Wait all thread finished create parameter ,current finished thread is :" - + finishCreateParameterNumber.get()); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - startTriggerNum - .addAndGet(blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber()); - - for (int i = 0; i < dataList.size(); i++) { - if (i % 2 == 0) { - PublicMethed.triggerContract(shieldAddressByte, - transfer, dataList.get(i), true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - } else { - PublicMethed.triggerContract(shieldAddressByte, - transfer, dataList.get(i), true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull1); - } - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - finishTriggerNumber.addAndGet(1); - - while (finishTriggerNumber.get() != thread) { - try { - Thread.sleep(3000); - if (finishTriggerNumber.get() % 10 == 0) { - logger.info( - "Wait all thread finished trigger ,current finished thread is :" + finishTriggerNumber - .get()); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - - } - - /** - * constructor. - */ - @Test(enabled = true, threadPoolSize = 40, invocationCount = 40) - public void test03BurnStress() throws Exception { - ManagedChannel channelFull = null; - WalletGrpc.WalletBlockingStub blockingStubFull = null; - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - ManagedChannel channelFull1 = null; - WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - Optional sendShieldAddressInfo = getNewShieldedAddress(blockingStubFull); - Optional receiverShieldAddressInfo = getNewShieldedAddress( - blockingStubFull); - - Integer mintNumber = 25; - - while (--mintNumber >= 0) { - BigInteger publicFromAmount = getRandomAmount(); - - String memo = "Shield trc20 from T account to shield account in" + System.currentTimeMillis(); - String sendShieldAddress = sendShieldAddressInfo.get().getAddress(); - - List shieldOutList = new ArrayList<>(); - shieldOutList.clear(); - shieldOutList = addShieldTrc20OutputList(shieldOutList, sendShieldAddress, - "" + publicFromAmount, memo, blockingStubFull); - - //Create shiled trc20 parameters - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters - = createShieldedTrc20Parameters(publicFromAmount, - null, null, shieldOutList, "", - 0L, blockingStubFull, blockingStubSolidity - ); - String data = ""; - try { - data = encodeMintParamsToHexString(shieldedTrc20Parameters, publicFromAmount); - } catch (Exception e) { - try { - data = encodeMintParamsToHexString(shieldedTrc20Parameters, publicFromAmount); - } catch (Exception e1) { - continue; - } - - } - - String txid = PublicMethed.triggerContract(shieldAddressByte, - mint, data, true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - } - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - finishMintNumber.addAndGet(1); - endmintNum.getAndAdd(blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber()); - - while (finishMintNumber.get() != thread) { - try { - Thread.sleep(3000); - if (finishMintNumber.get() % 10 == 0) { - logger.info( - "Wait all thread finished mint,current finished thread is :" + finishMintNumber - .get()); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - - Long endMintNum = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber(); - - GrpcAPI.DecryptNotesTRC20 sendNote = scanShieldedTrc20NoteByIvkWithRange( - sendShieldAddressInfo.get(), - startmintNum.get(), endMintNum, blockingStubFull1); - - noteNumber.addAndGet(sendNote.getNoteTxsCount()); - - logger.info("sendNote size :" + sendNote.getNoteTxsCount()); - - List shieldOutList = new ArrayList<>(); - - List inputShieldAddressList = new ArrayList<>(); - - inputShieldAddressList.add(sendShieldAddressInfo.get()); - - List dataList = new ArrayList<>(); - for (int i = 0; i < sendNote.getNoteTxsCount(); i++) { - String burnnMemo1 = "burnnMemo1 type test " + getRandomLongAmount() + getRandomLongAmount(); - GrpcAPI.DecryptNotesTRC20 burnInput = GrpcAPI.DecryptNotesTRC20.newBuilder() - .addNoteTxs(sendNote.getNoteTxs(i)) - .build(); - - GrpcAPI.ShieldedTRC20Parameters shieldedTrc20Parameters = null; - createShieldedTrc20Parameters(BigInteger.valueOf(0), - burnInput, inputShieldAddressList, null, zenTrc20TokenOwnerAddressString, - burnInput.getNoteTxs(0).getNote().getValue(), blockingStubFull, blockingStubSolidity); - - if (i % 2 == 0) { - try { - shieldedTrc20Parameters = createShieldedTrc20Parameters(BigInteger.valueOf(0), - burnInput, inputShieldAddressList, null, zenTrc20TokenOwnerAddressString, - burnInput.getNoteTxs(0).getNote().getValue(), blockingStubFull, blockingStubSolidity); - } catch (Exception e) { - try { - shieldedTrc20Parameters = createShieldedTrc20Parameters(BigInteger.valueOf(0), - burnInput, inputShieldAddressList, null, zenTrc20TokenOwnerAddressString, - burnInput.getNoteTxs(0).getNote().getValue(), blockingStubFull1, - blockingStubSolidity); - } catch (Exception e1) { - throw e1; - } - - } - - } else { - try { - shieldedTrc20Parameters = createShieldedTrc20Parameters(BigInteger.valueOf(0), - burnInput, inputShieldAddressList, null, zenTrc20TokenOwnerAddressString, - burnInput.getNoteTxs(0).getNote().getValue(), blockingStubFull, blockingStubSolidity); - } catch (Exception e) { - try { - shieldedTrc20Parameters = createShieldedTrc20Parameters(BigInteger.valueOf(0), - burnInput, inputShieldAddressList, null, zenTrc20TokenOwnerAddressString, - burnInput.getNoteTxs(0).getNote().getValue(), blockingStubFull1, - blockingStubSolidity); - } catch (Exception e1) { - throw e1; - } - - - } - } - - dataList.add(shieldedTrc20Parameters.getTriggerContractInput()); - - } - - finishCreateParameterNumber.addAndGet(1); - dataNumber.addAndGet(dataList.size()); - while (finishCreateParameterNumber.get() != thread) { - try { - Thread.sleep(3000); - if (finishCreateParameterNumber.get() % 10 == 0) { - logger.info("Wait all thread finished create parameter ,current finished thread is :" - + finishCreateParameterNumber.get()); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - startTriggerNum - .addAndGet(blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber()); - - for (int i = 0; i < dataList.size(); i++) { - if (i % 2 == 0) { - PublicMethed.triggerContract(shieldAddressByte, - burn, dataList.get(i), true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull); - } else { - PublicMethed.triggerContract(shieldAddressByte, - burn, dataList.get(i), true, 0, maxFeeLimit, zenTrc20TokenOwnerAddress, - zenTrc20TokenOwnerKey, blockingStubFull1); - } - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - finishTriggerNumber.addAndGet(1); - - while (finishTriggerNumber.get() != thread) { - try { - Thread.sleep(3000); - if (finishTriggerNumber.get() % 10 == 0) { - logger.info( - "Wait all thread finished trigger ,current finished thread is :" + finishTriggerNumber - .get()); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - - } - - /** - * constructor. - */ - @Test(enabled = true, threadPoolSize = 1, invocationCount = 1) - public void test04QueryResult() throws Exception { - - endTriggerNum.set(blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()) - .getBlockHeader().getRawData().getNumber()); - Long endmintnum = endmintNum.longValue() / thread; - Long starttriggernum = startTriggerNum.longValue() / thread; - logger.info("Start trigger block number: " + starttriggernum); - logger.info("end trigger block number: " + endTriggerNum.get()); - logger.info("Start mint block number: " + startmintNum.get()); - logger.info("End mint block number: " + endmintnum); - - Integer success = 0; - Integer failed = 0; - Integer outOfTime = 0; - Integer notMintContract = 0; - startmintNum.getAndAdd(-5); - endmintnum = endmintnum + 5; - - startmintNum.set(2016); - endmintnum = 2180L; - starttriggernum = 3040L; - endTriggerNum.set(3060); - - while (startmintNum.get() < endmintnum) { - HttpResponse response = HttpMethed - .getTransactionInfoByBlocknum(httpnode, startmintNum.getAndAdd(1)); - List responseContentByBlocknum = HttpMethed - .parseResponseContentArray(response); - for (int i = 0; i < responseContentByBlocknum.size(); i++) { - String result = responseContentByBlocknum.get(i).getJSONObject("receipt") - .getString("result"); - logger.info(result); - if (result == null) { - notMintContract++; - continue; - } - if (result.equals("SUCCESS")) { - success++; - continue; - } - if (result.equals("OUT_OF_TIME")) { - outOfTime++; - continue; - } - failed++; - } - } - - Integer triggerSuccess = 0; - Integer triggerFailed = 0; - Integer triggerOutOfTime = 0; - Integer notTriggerContract = 0; - startTriggerNum.getAndAdd(-5); - endTriggerNum.getAndAdd(5); - - while (starttriggernum < endTriggerNum.get()) { - HttpResponse response = HttpMethed.getTransactionInfoByBlocknum(httpnode, starttriggernum++); - List responseContentByBlocknum = HttpMethed - .parseResponseContentArray(response); - for (int i = 0; i < responseContentByBlocknum.size(); i++) { - String result = responseContentByBlocknum.get(i).getJSONObject("receipt") - .getString("result"); - logger.info(result); - if (result == null) { - notTriggerContract++; - continue; - } - if (result.equals("SUCCESS")) { - triggerSuccess++; - continue; - } - if (result.equals("OUT_OF_TIME")) { - triggerOutOfTime++; - continue; - } - triggerFailed++; - } - } - - logger.info("Mint Success mint times:" + success); - logger.info("Mint Failed mint times:" + failed); - logger.info("Mint Out of times mint times:" + outOfTime); - logger.info("Not mint times:" + notMintContract); - - logger.info("Success trigger times:" + triggerSuccess); - logger.info("Failed trigger times:" + triggerFailed); - logger.info("Out of times trigger times:" + triggerOutOfTime); - logger.info("Not trigger times:" + notTriggerContract); - - logger.info("note size:" + noteNumber.get()); - logger.info("data size:" + dataNumber.get()); - - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - //endNum = HttpMethed.getNowBlockNum(httpnode); - //logger.info("startNum:" + startNum); - //logger.info("endNum:" + endNum); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/SupportTronlinkAutoTest.java b/framework/src/test/java/stest/tron/wallet/onlinestress/SupportTronlinkAutoTest.java deleted file mode 100644 index 65e17d4e8a4..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/SupportTronlinkAutoTest.java +++ /dev/null @@ -1,374 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.contract.WitnessContract; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class SupportTronlinkAutoTest { - - private final String testKey002 - = "7400E3D0727F8A61041A8E8BF86599FE5597CE19DE451E59AED07D60967A5E25"; - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - ByteString assetAccountId1; - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[1]; - String accountPermissionJson = ""; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey3.getAddress(); - String ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] newAddress = ecKey4.getAddress(); - String newKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - //Mainnet fullnode - private String fullnode = "47.252.19.181:50051"; - //dappchain fullnode - //private String fullnode = "47.252.7.241:50051"; - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, threadPoolSize = 1, invocationCount = 1) - public void testMutiSignForAccount() { - Integer i = 0; - System.out.println("Start genterate address"); - while (i++ < 20) { - ecKey1 = new ECKey(Utils.getRandom()); - manager1Address = ecKey1.getAddress(); - manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey3 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey3.getAddress(); - ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - //PublicMethed.printAddress(ownerKey); - - PublicMethed.sendcoin(ownerAddress, 200000000000L, fromAddress, testKey002, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = ownerKey; - ownerKeyString[0] = ownerKey; - //ownerKeyString[1] = manager1Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0," - + "\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2," - + "\"permission_name\":\"active\",\"threshold\":2," - + "\"operations\":\"" - + "7fff1fc0033e0b00000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - //logger.info(accountPermissionJson); - PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString); - System.out.println("owner" + i + " --------------------------------------------------------"); - PublicMethed.printAddress(ownerKey); - System.out.println("mutli sig address for owner " - + i + " ----------------------------------"); - PublicMethed.printAddress(manager1Key); - System.out.println("-------------------------------" - + "-----------------------------------------"); - - } - - - } - - - @Test(enabled = true, threadPoolSize = 1, invocationCount = 1) - public void test002CreateWitness() { - Integer i = 0; - System.out.println("Start genterate witness address"); - while (i++ < 10) { - ecKey3 = new ECKey(Utils.getRandom()); - ownerAddress = ecKey3.getAddress(); - ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - //PublicMethed.printAddress(ownerKey); - - PublicMethed.sendcoin(ownerAddress, 50000000000L, fromAddress, testKey002, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String createWitnessUrl = "IOS-UI-Witness-00" + i; - byte[] createUrl = createWitnessUrl.getBytes(); - createWitness(ownerAddress, createUrl, ownerKey); - PublicMethed.waitProduceNextBlock(blockingStubFull); - System.out.println("witness " + i + " -----------------------------" - + "---------------------------"); - PublicMethed.printAddress(ownerKey); - System.out.println("witness url is : " + createWitnessUrl); - System.out.println("-------------------------------------------" - + "-----------------------------"); - - } - - - } - - - @Test(enabled = true, threadPoolSize = 1, invocationCount = 1) - public void test03MutiSignForAccount() { - HashMap muti = new HashMap(); - muti.put("9a2ba173645be8d37a82084f984ba873fbcf817b589c62a59b3ba1494c3406e0", - "cefba96470224724bde255f3402fca3d67b6c7c5d34deb7a8524c9482c58fe8b"); - muti.put("36f5430b4003f41ee8969421d9366ab1414e62111aec07a73d06eefcda8aad14", - "3adcd73ad1fa03ce2fd4d29e29a7c96ef2f78bece85cba6e58997826682c4c1e"); - muti.put("4b47cf37528724dc8bc99188063f5aec9a7bc32aadfad5a96a9e9cccba7cede1", - "948d856ebeb787aabd495fc13627f7442e7c1f21e9ed784f795e14f13cbebb94"); - muti.put("75d0856799cf2b2c807ed0eb5bb091bb943f2caed830add4b8df14c537f86e9a", - "7fb13ad0b62d4ff116ebd3d901d458697902ce81a8fc30c20c60aba1ca6964ec"); - muti.put("327bf1b4a3193c2bebf239c1c5bda09a8d375251361ea9c7418aa2adf2d17b7e", - "a8236968966db785ffe63d613174ee25e1baff03817b64db905c5940ed3dcc4b"); - muti.put("cf83d9494a9268fd3a75bd76bcfabaa7ec766e9084129a20e1823f81fbdca933", - "1e53c948e949e39f60a3be2382382f9a50f88b658ea79c418ece1c5f9b169441"); - muti.put("19ff919e92462f07c7eced256d4cb588a66ac900d544d0d4d16ae49732de79cb", - "166ddc2cd6379e7971e2c65d224594b709ebb59b3c6051c156214c299129f420"); - muti.put("7901db57a410a26d333b6d7fe4e054ddffbdc646f94ca03577bfd5e87120b9af", - "89d9a47b37f5625e14082b575d5e657b21f6dae125125bee51fafd1e8cdf0804"); - muti.put("e3c7204d652a6fdcda05cbce061904d441dece7bf0a1778c1ddf0906aa36a279", - "7d308998f829c0581447831003d994216a3a003ba00eef6a4e48e28b3178fbb3"); - muti.put("826fc86d572ba9de06f20963fcbfb44f4c397875bd4d7b36fdcb83476df33f05", - "25aa122142a52ea8ba7bdf832c39a194d498774d4f675b8bcb17280c33990a08"); - muti.put("9705dd852465d04be349e94865142fc636d038138a4bfe8f94abc9b49f1dc14a", - "0b675f14c1e06a6473c517dded162472ce2bb5c8934f198df1a791b75c30f983"); - muti.put("075f86d3d4053929714ddedb3e458467e6d494c3d4b0c71dafb63279de1beb89", - "4880695a6e31f4f69d6f261eedfa5dcb5fc1b9194483658f77625ec4e6b2e493"); - muti.put("91ae6c8a1bff0b71f6f2b9de54d3b39502bcab906f980569109ab8425cb0bdc5", - "90ef4adb0772ee49089784ccad234867a10395064749788b461cbe91265424fb"); - muti.put("9acb90c4d15c87dd2a1f322eddaabdde22cd78fe5eab371bfcf0c8be80bef8a8", - "951f03193e1d7d4bff016da100b74f8ac220aabfd9c2841438ee758702c8e3f4"); - muti.put("f8eae7be0fac4e9fab40139e58b405f7e5d5b13a83220a6e4955ffaacbbe2a7d", - "66692c0aaad6cfd349bdffbf3fdd688558a6c7a95ff67f249e0e80847167013a"); - muti.put("2e20c1a4b9a3a79696cbf0d03dedc39d8021657028fbf3dbc5da85ea61ad5dff", - "ae7ecb7fba0d77d116a23f96a4dfecdef09741e363f0be12f99c86b3815d8fff"); - muti.put("e5e60c52f3b11ce0cfbc4e86d078ab53435ebc2422fd851614a25b5063ae7040", - "42c575d8848809082c6872b2dcdb0e81d5f06ca120c636b90d0b062965ea0871"); - muti.put("fd4ee3a678a749c2049d5b1cba757648386c84ac2481be8de02069d41e4fb312", - "ef2095532f572be8d021886780f7e508665ef40c1499273b91813ddc27d1354b"); - muti.put("297f6e034e9366691922ff5394810f724094bd0a07b4ca60f0f281ec71562094", - "4ab67f1c42db0b63bafc0f33cf59575998c3259e96f5f89ea379dac4298d2bd7"); - int i = 1; - for (HashMap.Entry entry : muti.entrySet()) { - //entry.getKey().toString(); - //entry.getValue().toString(); - - ownerKey = entry.getKey().toString(); - ownerAddress = PublicMethed.getFinalAddress(ownerKey); - - manager1Key = entry.getValue().toString(); - manager1Address = PublicMethed.getFinalAddress(manager1Key); - - //System.out.println("ownerKey:" + ownerKey); - //System.out.println("manager1Key:" + manager1Key); - - //System.exit(1); - PublicMethed.sendcoin(ownerAddress, 20000000000L, fromAddress, testKey002, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = ownerKey; - ownerKeyString[0] = ownerKey; - //ownerKeyString[1] = manager1Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"" - + "threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"" - + "active\",\"threshold\":2," - + "\"operations\":\"" - + "7fff1fc0033e0b00000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}" - + "]}]}"; - - //logger.info(accountPermissionJson); - PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString); - System.out.println("owner " + i++ + " -----------------" - + "---------------------------------------"); - PublicMethed.printAddress(ownerKey); - System.out.println("mutli sig address for owner " + i++ + " ------------" - + "----------------------"); - PublicMethed.printAddress(manager1Key); - System.out.println("-----------------------------------" - + "-------------------------------------"); - - } - - } - - - @Test(enabled = true, threadPoolSize = 1, invocationCount = 1) - public void test004CreateWitness() { - - String[] witnessKey = { - - "c74fb4d8101572041c6fab30e1602ba1ec8247e1ead19641fb985b3ed3a8261e", - "25f98ac22c9fd02aa8a2ef354db0aa13ebc2a6c31377ea7e2b342f0d3898af0d", - "939a2cec3768bd2d2834126c20d2b1c513e3711f085ce374f654a7b144aa409f", - "39862f4dd51972ca22ce50b7b9e629043387000120c33bf263399ad9b334da1a", - "79045aab0f3199ac456ce2039e809e6c942983ede0e3a398d571dedddb351348", - "d50fe9c48e95289cde324ffeff095f8275f9ab07375e5e843167a0a54d3e1462", - "61651f2b8a87e1ae0ced5e700807f2abb50e97fe7d3d3e6a8aa58f0a6b0149a6", - "bb03d70e5187258ffb6cddb1becade5c1b2606b7ea84636b7dfaeef6216610a5", - "25858c236634e353d018f310f61e077b78e1410766565ed56ff11ee7410dcf20", - "ede941a01eb8234866f60c7e8e95db4614bb0d05298d82bae0abea81f1861046", - - }; - int i = 1; - for (String ownerKey : witnessKey) { - byte[] ownerAddress = PublicMethed.getFinalAddress(ownerKey); - PublicMethed.sendcoin(ownerAddress, 20000000000L, fromAddress, testKey002, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String createWitnessUrl = "IOS-UI-Witness-00" + i++; - byte[] createUrl = createWitnessUrl.getBytes(); - createWitness(ownerAddress, createUrl, ownerKey); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.printAddress(ownerKey); - System.out.println("witness url is : " + createWitnessUrl); - System.out.println("---------------------------------------------------------------------"); - - } - - - } - - - @Test(enabled = true, threadPoolSize = 1, invocationCount = 1) - public void test005SendTrc20() { - - String[] witnessKey = { - "TR8CyAPJFMjCvphCVuWeeVxBh5iTG7VWxe", - "TMhGDU7NiXwckCW64PqAvWFuC2kR1WSF5J", - "TDf3JZtjDeEqsFdPGp6vT9meG3JxMwmXwA", - "TEtG9fnVi2qythiog6owPrg4sD9rwFBQBN", - "TUvda1oqrNLbqDKhZDxDnrPhiDCdxem218", - "TKEH31jJ2YQ3Bteh1ngjwdT8667ztyYPSp", - "TAzrJHKa57nXnn3dZGFG87PDuWx12dY97s", - "TWhc6AAh6BWRr3k5dV8iMvkp8ys7NHzXCk", - "TSsaSxHnb3xLTop2A8LrDk1P896yiDeupe", - "TMDs8oTj8mVnakqiVyDKdp2ruWPdFeDgbq", - "TWv2FEsoPp5XKxujVHffoNwksgJSxvf3QG", - "TGamEmt6U9ZUg9bFsMq7KT9bRa3uvkdtHM", - "TXhQk442CCGLydh6cfyfqvM6yJanEGeQj1", - "TKktQcbjXsXZDKPYLvUm8sxox2cT83g5rP", - "TBQUhYhdQpMRksBGAbpbTWSiE7WkGgy3Km", - "TALf34yjuLZjF1WQqCaUkf73X8WbhfiEyM", - "TCGp3JAFM5vQZpsdNiKRTci7fVb7A2TPcu", - "TBExF3mNvnhmEFgHW4TmYXXdhevRchnQyb", - "TS8o6WcHroSnzWNt4AiserAuVkye5Msvcm", - "TBtMRD79NkLyAvMkCTTj5VC5KZnz2Po2XZ", - }; - int i = 1; - for (String ownerKey : witnessKey) { - String triggerString = "\"" + ownerKey - + "\"" + ", 20000000000"; - System.out.println(triggerString); - //dapp chain trc20 tract TXkdXbzjoLpxGAD2strP1zwjJzR6osNfD7 - byte[] contractAddress = PublicMethed.decode58Check("TXkdXbzjoLpxGAD2strP1zwjJzR6osNfD7"); - //main chain TRC 20 contract TCCcBZEdTHmS1NfFtCYfwpjBKeTv515n71 - //byte[] contractAddress = PublicMethed.decode58Check("TCCcBZEdTHmS1NfFtCYfwpjBKeTv515n71"); - - PublicMethed - .triggerContract(contractAddress, "transfer(address,uint256)", triggerString, false, - 0, 1000000000, "0", 0, fromAddress, testKey002, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - - } - - - } - - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - public Boolean createWitness(byte[] owner, byte[] url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - WitnessContract.WitnessCreateContract.Builder builder = WitnessContract.WitnessCreateContract - .newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setUrl(ByteString.copyFrom(url)); - WitnessContract.WitnessCreateContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createWitness(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = PublicMethed.signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - return response.getResult(); - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/TestApproveProposal.java b/framework/src/test/java/stest/tron/wallet/onlinestress/TestApproveProposal.java deleted file mode 100644 index 015242b1f94..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/TestApproveProposal.java +++ /dev/null @@ -1,169 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.HashMap; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.ProposalList; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.ChainParameters; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.HttpMethed; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class TestApproveProposal { - - private static final long now = System.currentTimeMillis(); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - //Witness 47.93.33.201 - private final String witnessKey002 = Configuration.getByPath("testng.conf") - .getString("witness.key2"); - //Witness 123.56.10.6 - private final String witnessKey003 = Configuration.getByPath("testng.conf") - .getString("witness.key3"); - //Wtiness 39.107.80.135 - private final String witnessKey004 = Configuration.getByPath("testng.conf") - .getString("witness.key4"); - //Witness 47.93.184.2 - private final String witnessKey005 = Configuration.getByPath("testng.conf") - .getString("witness.key5"); - private final byte[] witness001Address = PublicMethed.getFinalAddress(witnessKey001); - private final byte[] witness002Address = PublicMethed.getFinalAddress(witnessKey002); - private final byte[] witness003Address = PublicMethed.getFinalAddress(witnessKey003); - private final byte[] witness004Address = PublicMethed.getFinalAddress(witnessKey004); - private final byte[] witness005Address = PublicMethed.getFinalAddress(witnessKey005); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true) - public void testApproveProposal() { - HashMap proposalMap = new HashMap(); - //proposalMap.put(25L, 1L); - proposalMap.put(27L, 0L); - //proposalMap.put(28L, 1L); - Assert.assertTrue(PublicMethed.createProposal(witness001Address, witnessKey001, - proposalMap, blockingStubFull)); - try { - Thread.sleep(20000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - //Get proposal list - ProposalList proposalList = blockingStubFull.listProposals(EmptyMessage.newBuilder().build()); - Optional listProposals = Optional.ofNullable(proposalList); - final Integer proposalId = listProposals.get().getProposalsCount(); - logger.info(Integer.toString(proposalId)); - - //Get proposal list after approve - proposalList = blockingStubFull.listProposals(EmptyMessage.newBuilder().build()); - listProposals = Optional.ofNullable(proposalList); - //logger.info(Integer.toString(listProposals.get().getProposals(0).getApprovalsCount())); - - String[] witnessKey = { - - "369F095838EB6EED45D4F6312AF962D5B9DE52927DA9F04174EE49F9AF54BC77", - "9FD8E129DE181EA44C6129F727A6871440169568ADE002943EAD0E7A16D8EDAC", - - }; - byte[] witnessAddress; - for (String key : witnessKey) { - witnessAddress = PublicMethed.getFinalAddress(key); - PublicMethed.approveProposal(witnessAddress, key, proposalId, - true, blockingStubFull); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - @Test(enabled = true) - public void testGetChainParameters() { - //Set the default map - HashMap defaultCommitteeMap = new HashMap(); - defaultCommitteeMap.put("MAINTENANCE_TIME_INTERVAL", 300000L); - defaultCommitteeMap.put("ACCOUNT_UPGRADE_COST", 9999000000L); - defaultCommitteeMap.put("CREATE_ACCOUNT_FEE", 100000L); - defaultCommitteeMap.put("TRANSACTION_FEE", 10L); - defaultCommitteeMap.put("ASSET_ISSUE_FEE", 1024000000L); - defaultCommitteeMap.put("WITNESS_PAY_PER_BLOCK", 32000000L); - defaultCommitteeMap.put("WITNESS_STANDBY_ALLOWANCE", 115200000000L); - defaultCommitteeMap.put("CREATE_NEW_ACCOUNT_FEE_IN_SYSTEM_CONTRACT", 0L); - defaultCommitteeMap.put("CREATE_NEW_ACCOUNT_BANDWIDTH_RATE", 1L); - - ChainParameters chainParameters = blockingStubFull - .getChainParameters(EmptyMessage.newBuilder().build()); - Optional getChainParameters = Optional.ofNullable(chainParameters); - logger.info(Long.toString(getChainParameters.get().getChainParameterCount())); - for (Integer i = 0; i < getChainParameters.get().getChainParameterCount(); i++) { - logger.info("Index is:" + i); - logger.info(getChainParameters.get().getChainParameter(i).getKey()); - logger.info(Long.toString(getChainParameters.get().getChainParameter(i).getValue())); - } - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/TestExchangeTransaction.java b/framework/src/test/java/stest/tron/wallet/onlinestress/TestExchangeTransaction.java deleted file mode 100644 index 5fdfd7f3c73..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/TestExchangeTransaction.java +++ /dev/null @@ -1,176 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import static org.tron.core.config.Parameter.ChainSymbol.TRX_SYMBOL_BYTES; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.ExchangeList; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Exchange; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - - -@Slf4j -public class TestExchangeTransaction { - - private static final long now = System.currentTimeMillis(); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - Optional listExchange; - Optional exchangeIdInfo; - Integer exchangeId = 0; - Integer exchangeRate = 10; - Long firstTokenInitialBalance = 10000L; - Long secondTokenInitialBalance = firstTokenInitialBalance * exchangeRate; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - } - - @Test(enabled = true) - public void testCreateShieldToken() { - String tokenOwnerKey = "2925e186bb1e88988855f11ebf20ea3a6e19ed92328b0ffb576122e769d45b68"; - byte[] tokenOwnerAddress = PublicMethed.getFinalAddress(tokenOwnerKey); - PublicMethed.printAddress(tokenOwnerKey); - Assert.assertTrue(PublicMethed.sendcoin(tokenOwnerAddress, 20480000000L, fromAddress, - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String name = "shieldToken"; - Long start = System.currentTimeMillis() + 20000; - Long end = System.currentTimeMillis() + 10000000000L; - Long totalSupply = 1500000000000001L; - String description = "This asset issue is use for exchange transaction stress"; - String url = "This asset issue is use for exchange transaction stress"; - Assert.assertTrue(PublicMethed.createAssetIssue(tokenOwnerAddress, name, totalSupply, 1, 1, - start, end, 1, description, url, 1000L, 1000L, - 1L, 1L, tokenOwnerKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account getAssetIdFromThisAccount = - PublicMethed.queryAccount(tokenOwnerAddress, blockingStubFull); - ByteString assetAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - logger.info("AssetId:" + assetAccountId.toString()); - - - } - - @Test(enabled = true, threadPoolSize = 20, invocationCount = 20) - public void testExchangeTransaction() { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] exchangeAddress = ecKey1.getAddress(); - String exchangeKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ECKey ecKey2 = new ECKey(Utils.getRandom()); - final byte[] transactionAddress = ecKey2.getAddress(); - String transactionKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - PublicMethed.printAddress(exchangeKey); - PublicMethed.printAddress(transactionKey); - - Assert.assertTrue(PublicMethed.sendcoin(exchangeAddress, 1500000000000000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(transactionAddress, 1500000000000000L, fromAddress, - testKey002, blockingStubFull)); - Long totalSupply = 1500000000000000L; - Random rand = new Random(); - Integer randNum = rand.nextInt(900000000) + 1; - String name = "exchange_" + Long.toString(randNum); - Long start = System.currentTimeMillis() + 20000; - Long end = System.currentTimeMillis() + 10000000000L; - String description = "This asset issue is use for exchange transaction stress"; - String url = "This asset issue is use for exchange transaction stress"; - Assert.assertTrue(PublicMethed.createAssetIssue(exchangeAddress, name, totalSupply, 1, 1, - start, end, 1, description, url, 100000000L, 10000000000L, - 10L, 10L, exchangeKey, blockingStubFull)); - try { - Thread.sleep(30000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - Assert.assertTrue(PublicMethed.transferAsset(transactionAddress, name.getBytes(), - 1500000000L, exchangeAddress, exchangeKey, blockingStubFull)); - try { - Thread.sleep(30000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - //500000000000000L //5000000L - Assert.assertTrue(PublicMethed.exchangeCreate(name.getBytes(), 500000000000000L, - TRX_SYMBOL_BYTES, 500000000000000L, exchangeAddress, exchangeKey, blockingStubFull)); - try { - Thread.sleep(300000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - listExchange = PublicMethed.getExchangeList(blockingStubFull); - exchangeId = listExchange.get().getExchangesCount(); - - Integer i = 0; - while (i++ < 10000) { - PublicMethed.exchangeTransaction(exchangeId, TRX_SYMBOL_BYTES, 100000, 99, - transactionAddress, transactionKey, blockingStubFull); - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - PublicMethed.exchangeTransaction(exchangeId, name.getBytes(), 100000, 1, - transactionAddress, transactionKey, blockingStubFull); - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/TestMapBigLongAndNumbers.java b/framework/src/test/java/stest/tron/wallet/onlinestress/TestMapBigLongAndNumbers.java deleted file mode 100644 index 9864ff100ea..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/TestMapBigLongAndNumbers.java +++ /dev/null @@ -1,183 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -//import java.io.FileWriter; -//import java.io.BufferedWriter; - - -@Slf4j -public class TestMapBigLongAndNumbers { - - //testng001、testng002、testng003、testng004 - //testng001、testng002、testng003、testng004 - private final String testKey002 = - "FC8BF0238748587B9617EB6D15D47A66C0E07C1A1959033CF249C6532DC29FE6"; - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - //private final String testAddress41 = ByteArray.toHexString(fromAddress); - String kittyCoreAddressAndCut = ""; - byte[] kittyCoreContractAddress = null; - byte[] saleClockAuctionContractAddress = null; - byte[] siringClockAuctionContractAddress = null; - byte[] geneScienceInterfaceContractAddress = null; - //Integer consumeUserResourcePercent = 20; - Integer consumeUserResourcePercent = 100; - String txid = ""; - Optional infoById = null; - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] triggerAddress = ecKey2.getAddress(); - String triggerKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(triggerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - - } - - @Test(enabled = true, threadPoolSize = 10, invocationCount = 10) - public void deployErc721KittyCore() { - - Long maxFeeLimit = 1000000000L; - - String contractName = "MappingExample"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_TestMapBigLongAndNumbers_deployErc721KittyCore"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_TestMapBigLongAndNumbers_deployErc721KittyCore"); - kittyCoreContractAddress = PublicMethed.deployContract(contractName, abi, code, "", - maxFeeLimit, 0L, consumeUserResourcePercent, null, testKey002, - fromAddress, blockingStubFull); - - String data1 = "a"; - String data2 = "b"; - String data3 = "c"; - String data4 = "d"; - - for (int i = 0; i < 13; i++) { - data1 += data1; - } - - for (int i = 0; i < 12; i++) { - data2 += data2; - } - for (int i = 0; i < 11; i++) { - data3 += data3; - } - for (int i = 0; i < 10; i++) { - data4 += data4; - } - String data; - data = data1 + data2 + data3 + data4; - - String data5 = "a"; - - Account account = PublicMethed.queryAccountByAddress(fromAddress, blockingStubFull); - System.out.println(Long.toString(account.getBalance())); - long accountBalance = account.getBalance(); - - Random random = new Random(); - int randNumber = random.nextInt(15) + 15; - - System.out.println("random number:" + randNumber); - - try { - Thread.sleep(randNumber); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - for (int ii = 1; ii < 111100000; ii++) { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] userAddress = ecKey1.getAddress(); - String inputKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - String addresstest = Base58.encode58Check(userAddress); - - String saleContractString = "\"" + data + "\"" + "," + "\"" - + Base58.encode58Check(userAddress) + "\""; - - System.out.println("long string address:" + addresstest); - - txid = PublicMethed.triggerContract(kittyCoreContractAddress, "update2(string,address)", - saleContractString, false, 0, 1000000000L, fromAddress, testKey002, blockingStubFull); - logger.info(txid); - - String saleContractString1 = "\"" + data5 + "\"" + "," + "\"" - + Base58.encode58Check(userAddress) + "\""; - - System.out.println("short string address:" + addresstest); - - txid = PublicMethed.triggerContract(kittyCoreContractAddress, "update2(string,address)", - saleContractString1, false, 0, 1000000000L, fromAddress, testKey002, blockingStubFull); - logger.info(txid); - - System.out.println("time out"); - - txid = PublicMethed.triggerContract(kittyCoreContractAddress, "testUseCpu(uint256)", - "1000000000", false, 0, 1000000000L, fromAddress, testKey002, blockingStubFull); - - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - - infoById.get().getResultValue(); - - String isSuccess; - - if (infoById.get().getResultValue() == 0) { - logger.info("success:" + " Number:" + ii); - isSuccess = "success"; - } else { - logger.info("failed" + " Number:" + ii); - isSuccess = "fail"; - } - } - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} - - diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/TestMutiSignStress.java b/framework/src/test/java/stest/tron/wallet/onlinestress/TestMutiSignStress.java deleted file mode 100644 index 7995f85a993..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/TestMutiSignStress.java +++ /dev/null @@ -1,146 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; - -@Slf4j -public class TestMutiSignStress { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress = PublicMethed.getFinalAddress(witnessKey001); - ByteString assetAccountId1; - String[] ownerKeyString = new String[1]; - String accountPermissionJson = ""; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, threadPoolSize = 30, invocationCount = 30) - public void testMutiSignForAccount() { - PublicMethed.printAddress(testKey002); - - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] newAddress = ecKey4.getAddress(); - String newKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] ownerAddress = ecKey3.getAddress(); - - Assert.assertTrue(PublicMethed.sendcoin(ownerAddress, 9968981537400L, fromAddress, testKey002, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - String[] permissionKeyString = new String[3]; - permissionKeyString[0] = manager1Key; - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - permissionKeyString[1] = manager2Key; - String ownerKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - permissionKeyString[2] = ownerKey; - String[] ownerKeyString = new String[1]; - ownerKeyString[0] = ownerKey; - - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":3,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(ownerKey) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - logger.info(accountPermissionJson); - PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, - blockingStubFull, ownerKeyString); - - //permissionKeyString[0] = ownerKey; - - String[] ownerKeyString1 = new String[3]; - ownerKeyString1[0] = ownerKey; - ownerKeyString1[1] = manager1Key; - ownerKeyString1[2] = manager2Key; - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Integer i = 0; - while (i++ <= 1000) { - ecKey4 = new ECKey(Utils.getRandom()); - newAddress = ecKey4.getAddress(); - newKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - PublicMethed.printAddress(newKey); - - PublicMethedForMutiSign.sendcoin( - newAddress, 4000000L, ownerAddress, ownerKey, blockingStubFull, ownerKeyString1); - PublicMethedForMutiSign.freezeBalance( - ownerAddress, 1000000L, 0, ownerKey, blockingStubFull, ownerKeyString1); - PublicMethedForMutiSign.freezeBalanceGetEnergy( - ownerAddress, 1000000L, 0, 1, ownerKey, blockingStubFull, ownerKeyString1); - PublicMethedForMutiSign.freezeBalanceForReceiver( - ownerAddress, 1000000L, 0, 0, ByteString.copyFrom(newAddress), - ownerKey, blockingStubFull, ownerKeyString1); - PublicMethedForMutiSign.unFreezeBalance( - ownerAddress, ownerKey, 0, null, blockingStubFull, ownerKeyString1); - PublicMethedForMutiSign.unFreezeBalance( - ownerAddress, ownerKey, 0, newAddress, blockingStubFull, ownerKeyString1); - PublicMethedForMutiSign.updateAccount( - ownerAddress, Long.toString(System.currentTimeMillis()).getBytes(), ownerKey, - blockingStubFull, ownerKeyString1); - } - - - } - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/TestNetErc721Cat.java b/framework/src/test/java/stest/tron/wallet/onlinestress/TestNetErc721Cat.java deleted file mode 100644 index 600cbbfad9a..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/TestNetErc721Cat.java +++ /dev/null @@ -1,389 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TestNetErc721Cat { - - //testng001、testng002、testng003、testng004 - //testng001、testng002、testng003、testng004 - private final String testKey002 = - //"7306c6044ad7c03709980aa188b8555288b7e0608f5edbf76ff2381c5a7a15a8"; - //"3a54ba30e3ee41b602eca8fb3a3ca1f99f49a3d3ab5d8d646a2ccdd3ffd9c21d"; - //fromAddress - "FC8BF0238748587B9617EB6D15D47A66C0E07C1A1959033CF249C6532DC29FE6"; - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String kittyCoreAddressAndCut = ""; - byte[] kittyCoreContractAddress = null; - byte[] saleClockAuctionContractAddress = null; - byte[] siringClockAuctionContractAddress = null; - byte[] geneScienceInterfaceContractAddress = null; - Integer consumeUserResourcePercent = 20; - String txid = ""; - Optional infoById = null; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] deployAddress = ecKey1.getAddress(); - String deployKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] triggerAddress = ecKey2.getAddress(); - String triggerKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - PublicMethed.printAddress(deployKey); - PublicMethed.printAddress(triggerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - Assert.assertTrue(PublicMethed.sendcoin(deployAddress, 50000000000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.sendcoin(triggerAddress, 50000000000L, fromAddress, - testKey002, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(deployAddress, 100000000L, - 3, 1, deployKey, blockingStubFull)); - /* Assert.assertTrue(PublicMethed.freezeBalanceGetCpu(triggerAddress,100000000L, - 3,1,triggerKey,blockingStubFull));*/ - /*Assert.assertTrue(PublicMethed.buyStorage(500000000L,deployAddress,deployKey, - blockingStubFull)); - Assert.assertTrue(PublicMethed.buyStorage(500000000L,triggerAddress,triggerKey, - blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalance(deployAddress,100000000L,3, - deployKey,blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalance(triggerAddress,100000000L,3, - triggerKey,blockingStubFull));*/ - - } - - @Test(enabled = false) - public void deployErc721KittyCore() { - AccountResourceMessage accountResource = PublicMethed.getAccountResource(deployAddress, - blockingStubFull); - Long cpuLimit = accountResource.getEnergyLimit(); - //Long storageLimit = accountResource.getStorageLimit(); - Long cpuUsage = accountResource.getEnergyUsed(); - //Long storageUsage = accountResource.getStorageUsed(); - Account account = PublicMethed.queryAccount(deployAddress, blockingStubFull); - logger.info("before balance is " + Long.toString(account.getBalance())); - logger.info("before cpu limit is " + Long.toString(cpuLimit)); - logger.info("before cpu usage is " + Long.toString(cpuUsage)); - //logger.info("before storage limit is " + Long.toString(storageLimit)); - //logger.info("before storage usaged is " + Long.toString(storageUsage)); - Long maxFeeLimit = 3900000000L; - String contractName = "KittyCore"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_TestNetErc721Cat_deployErc721KittyCore"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_TestNetErc721Cat_deployErc721KittyCore"); - logger.info("Kitty Core"); - kittyCoreContractAddress = PublicMethed.deployContract(contractName, abi, code, "", - maxFeeLimit, 0L, consumeUserResourcePercent, null, deployKey, - deployAddress, blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(kittyCoreContractAddress, - blockingStubFull); - - Assert.assertTrue(smartContract.getAbi() != null); - accountResource = PublicMethed.getAccountResource(deployAddress, blockingStubFull); - cpuLimit = accountResource.getEnergyLimit(); - //storageLimit = accountResource.getStorageLimit(); - cpuUsage = accountResource.getEnergyUsed(); - //storageUsage = accountResource.getStorageUsed(); - account = PublicMethed.queryAccount(deployKey, blockingStubFull); - logger.info("after balance is " + Long.toString(account.getBalance())); - logger.info("after cpu limit is " + Long.toString(cpuLimit)); - logger.info("after cpu usage is " + Long.toString(cpuUsage)); - //logger.info("after storage limit is " + Long.toString(storageLimit)); - //logger.info("after storage usaged is " + Long.toString(storageUsage)); - logger.info(ByteArray.toHexString(kittyCoreContractAddress)); - logger.info(ByteArray.toHexString(kittyCoreContractAddress).substring(2)); - - kittyCoreAddressAndCut = "000000000000000000000000" + ByteArray - .toHexString(kittyCoreContractAddress).substring(2); - kittyCoreAddressAndCut = kittyCoreAddressAndCut + "0000000000000000000000000000000000000000000" - + "000000000000000000100"; - } - - @Test(enabled = false) - public void deploySaleClockAuction() { - AccountResourceMessage accountResource = PublicMethed.getAccountResource(deployAddress, - blockingStubFull); - Long cpuLimit = accountResource.getEnergyLimit(); - //Long storageLimit = accountResource.getStorageLimit(); - Long cpuUsage = accountResource.getEnergyUsed(); - //Long storageUsage = accountResource.getStorageUsed(); - Account account = PublicMethed.queryAccount(deployKey, blockingStubFull); - logger.info("before balance is " + Long.toString(account.getBalance())); - logger.info("before cpu limit is " + Long.toString(cpuLimit)); - logger.info("before cpu usage is " + Long.toString(cpuUsage)); - //logger.info("before storage limit is " + Long.toString(storageLimit)); - //logger.info("before storage usaged is " + Long.toString(storageUsage)); - Long maxFeeLimit = 3900000000L; - String contractName = "SaleClockAuction"; - logger.info("Sale Clock Auction"); - String code = Configuration.getByPath("testng.conf") - .getString("code.code_TestNetErc721Cat_deploySaleClockAuction"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_TestNetErc721Cat_deploySaleClockAuction"); - saleClockAuctionContractAddress = PublicMethed.deployContract(contractName, abi, code, - "", maxFeeLimit, 0L, consumeUserResourcePercent, null, deployKey, - deployAddress, blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(saleClockAuctionContractAddress, - blockingStubFull); - Assert.assertTrue(smartContract.getAbi() != null); - accountResource = PublicMethed.getAccountResource(deployAddress, blockingStubFull); - cpuLimit = accountResource.getEnergyLimit(); - //storageLimit = accountResource.getStorageLimit(); - cpuUsage = accountResource.getEnergyUsed(); - //storageUsage = accountResource.getStorageUsed(); - account = PublicMethed.queryAccount(deployKey, blockingStubFull); - logger.info("after balance is " + Long.toString(account.getBalance())); - logger.info("after cpu limit is " + Long.toString(cpuLimit)); - logger.info("after cpu usage is " + Long.toString(cpuUsage)); - //logger.info("after storage limit is " + Long.toString(storageLimit)); - //logger.info("after storage usaged is " + Long.toString(storageUsage)); - } - - @Test(enabled = false) - public void deploySiringClockAuction() { - AccountResourceMessage accountResource = PublicMethed.getAccountResource(deployAddress, - blockingStubFull); - Long cpuLimit = accountResource.getEnergyLimit(); - //Long storageLimit = accountResource.getStorageLimit(); - Long cpuUsage = accountResource.getEnergyUsed(); - //Long storageUsage = accountResource.getStorageUsed(); - Account account = PublicMethed.queryAccount(deployKey, blockingStubFull); - logger.info("before balance is " + Long.toString(account.getBalance())); - logger.info("before cpu limit is " + Long.toString(cpuLimit)); - logger.info("before cpu usage is " + Long.toString(cpuUsage)); - //logger.info("before storage limit is " + Long.toString(storageLimit)); - //logger.info("before storage usaged is " + Long.toString(storageUsage)); - Long maxFeeLimit = 3900000000L; - String contractName = "SiringClockAuction"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_TestNetErc721Cat_deploySiringClockAuction"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_TestNetErc721Cat_deploySiringClockAuction"); - logger.info("Siring Clock Auction"); - siringClockAuctionContractAddress = PublicMethed.deployContract(contractName, abi, code, - "", maxFeeLimit, 0L, consumeUserResourcePercent, null, deployKey, - deployAddress, blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(siringClockAuctionContractAddress, - blockingStubFull); - Assert.assertTrue(smartContract.getAbi() != null); - accountResource = PublicMethed.getAccountResource(deployAddress, blockingStubFull); - cpuLimit = accountResource.getEnergyLimit(); - //storageLimit = accountResource.getStorageLimit(); - cpuUsage = accountResource.getEnergyUsed(); - //storageUsage = accountResource.getStorageUsed(); - account = PublicMethed.queryAccount(deployKey, blockingStubFull); - logger.info("after balance is " + Long.toString(account.getBalance())); - logger.info("after cpu limit is " + Long.toString(cpuLimit)); - logger.info("after cpu usage is " + Long.toString(cpuUsage)); - //logger.info("after storage limit is " + Long.toString(storageLimit)); - //logger.info("after storage usaged is " + Long.toString(storageUsage)); - } - - @Test(enabled = false) - public void deployGeneScienceInterface() { - AccountResourceMessage accountResource = PublicMethed.getAccountResource(deployAddress, - blockingStubFull); - Long cpuLimit = accountResource.getEnergyLimit(); - //Long storageLimit = accountResource.getStorageLimit(); - Long cpuUsage = accountResource.getEnergyUsed(); - //Long storageUsage = accountResource.getStorageUsed(); - Account account = PublicMethed.queryAccount(deployKey, blockingStubFull); - logger.info("before balance is " + Long.toString(account.getBalance())); - logger.info("before cpu limit is " + Long.toString(cpuLimit)); - logger.info("before cpu usage is " + Long.toString(cpuUsage)); - //logger.info("before storage limit is " + Long.toString(storageLimit)); - //logger.info("before storage usaged is " + Long.toString(storageUsage)); - Long maxFeeLimit = 3900000000L; - String contractName = "GeneScienceInterface"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_TestNetErc721Cat_deployGeneScienceInterface"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_TestNetErc721Cat_deployGeneScienceInterface"); - logger.info("gene Science Interface"); - geneScienceInterfaceContractAddress = PublicMethed.deployContract(contractName, abi, code, - "", maxFeeLimit, - 0L, consumeUserResourcePercent, null, deployKey, deployAddress, blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(geneScienceInterfaceContractAddress, - blockingStubFull); - Assert.assertTrue(smartContract.getAbi() != null); - accountResource = PublicMethed.getAccountResource(deployAddress, blockingStubFull); - cpuLimit = accountResource.getEnergyLimit(); - //storageLimit = accountResource.getStorageLimit(); - cpuUsage = accountResource.getEnergyUsed(); - //storageUsage = accountResource.getStorageUsed(); - account = PublicMethed.queryAccount(deployKey, blockingStubFull); - logger.info("after balance is " + Long.toString(account.getBalance())); - logger.info("after cpu limit is " + Long.toString(cpuLimit)); - logger.info("after cpu usage is " + Long.toString(cpuUsage)); - //logger.info("after storage limit is " + Long.toString(storageLimit)); - //logger.info("after storage usaged is " + Long.toString(storageUsage)); - } - - @Test(enabled = false) - public void triggerToSetThreeContractAddressToKittyCore() { - //Set SaleAuctionAddress to kitty core. - String saleContractString = "\"" + Base58.encode58Check(saleClockAuctionContractAddress) + "\""; - txid = PublicMethed.triggerContract(kittyCoreContractAddress, "setSaleAuctionAddress(address)", - saleContractString, false, 0, 10000000L, deployAddress, deployKey, blockingStubFull); - logger.info(txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - //Assert.assertTrue(infoById.get().getReceipt().getStorageDelta() > 50); - - //Set SiringAuctionAddress to kitty core. - String siringContractString = "\"" + Base58.encode58Check(siringClockAuctionContractAddress) - + "\""; - txid = PublicMethed - .triggerContract(kittyCoreContractAddress, "setSiringAuctionAddress(address)", - siringContractString, false, 0, 10000000L, - deployAddress, deployKey, blockingStubFull); - logger.info(txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - //Assert.assertTrue(infoById.get().getReceipt().getStorageDelta() > 50); - - //Set gen contract to kitty core - String genContractString = "\"" + Base58.encode58Check(geneScienceInterfaceContractAddress) - + "\""; - txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "setGeneScienceAddress(address)", genContractString, - false, 0, 10000000L, deployAddress, deployKey, blockingStubFull); - logger.info(txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - //Assert.assertTrue(infoById.get().getReceipt().getStorageDelta() > 50); - - //Start the game. - txid = PublicMethed.triggerContract(kittyCoreContractAddress, "unpause()", "", false, 0, - 10000000L, deployAddress, deployKey, blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - logger.info("start the game " + txid); - - //Create one gen0 cat. - txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "createGen0Auction(uint256)", "-1000000000000000", false, - 0, 100000000L, deployAddress, deployKey, blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "gen0CreatedCount()", "#", false, - 0, 100000000L, deployAddress, deployKey, blockingStubFull); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - /* txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "name()","#",false,0,10000000,triggerAddress, - triggerKey,blockingStubFull); - logger.info("getname " + txid);*/ - - txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "getKitty(uint256)", "1", false, 0, 10000000, triggerAddress, - triggerKey, blockingStubFull); - logger.info("getKitty " + txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - String newCxoAddress = "\"" + Base58.encode58Check(triggerAddress) - + "\""; - - txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "setCOO(address)", newCxoAddress, false, 0, 10000000, deployAddress, - deployKey, blockingStubFull); - logger.info("COO " + txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "setCFO(address)", newCxoAddress, false, 0, 10000000, deployAddress, - deployKey, blockingStubFull); - logger.info("CFO " + txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - - txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "setCEO(address)", newCxoAddress, false, 0, 1000000, deployAddress, - deployKey, blockingStubFull); - logger.info("CEO " + txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0); - } - - @Test(enabled = false, threadPoolSize = 1, invocationCount = 1) - public void unCreateKitty() { - Integer times = 0; - logger.info("In create kitty, kitty core address is " + ByteArray - .toHexString(kittyCoreContractAddress)); - while (times++ < 20) { - txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "createGen0Auction(uint256)", "0", false, - 0, 100000000L, triggerAddress, triggerKey, blockingStubFull); - logger.info("createGen0 " + txid); - infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); - //Assert.assertTrue(infoById.get().getResultValue() == 0); - /* String promoKitty = "\"" + times.toString() + "\",\"" - + Base58.encode58Check(kittyCoreContractAddress) + "\""; - logger.info(promoKitty); - txid = PublicMethed.triggerContract(kittyCoreContractAddress, - "createPromoKitty(uint256,address)", promoKitty,false, - 0,10000000L,triggerAddress,triggerKey,blockingStubFull); - logger.info("createPromoKitty " + txid); - infoById = PublicMethed.getTransactionInfoById(txid,blockingStubFull); - Assert.assertTrue(infoById.get().getResultValue() == 0);*/ - try { - Thread.sleep(10); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - } - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/TestNetFomo3D.java b/framework/src/test/java/stest/tron/wallet/onlinestress/TestNetFomo3D.java deleted file mode 100644 index b87ddd99558..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/TestNetFomo3D.java +++ /dev/null @@ -1,207 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import static stest.tron.wallet.common.client.utils.PublicMethed.getTransactionInfoById; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; -import org.tron.api.WalletGrpc; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TestNetFomo3D { - - //testng001、testng002、testng003、testng004 - private final String testNetAccountKey = - "FC8BF0238748587B9617EB6D15D47A66C0E07C1A1959033CF249C6532DC29FE6"; - //"BC70ADC5A0971BA3F7871FBB7249E345D84CE7E5458828BE1E28BF8F98F2795B"; - private final byte[] testNetAccountAddress = PublicMethed.getFinalAddress(testNetAccountKey); - Optional infoById = null; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = false) - public void beforeClass() { - PublicMethed.printAddress(testNetAccountKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - logger.info(Long.toString(PublicMethed.queryAccount(testNetAccountKey, blockingStubFull) - .getBalance())); - //Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(testNetAccountAddress,10000000L, - //3,1,testNetAccountKey,blockingStubFull)); - /* Assert.assertTrue(PublicMethed.buyStorage(50000000L,testNetAccountAddress, - testNetAccountKey, - blockingStubFull));*/ - - } - - @Test(enabled = false) - public void deployErc721CryptoKitties() { - AccountResourceMessage accountResource = PublicMethed.getAccountResource(testNetAccountAddress, - blockingStubFull); - Long cpuLimit = accountResource.getEnergyLimit(); - //Long storageLimit = accountResource.getStorageLimit(); - Long cpuUsage = accountResource.getEnergyUsed(); - //Long storageUsage = accountResource.getStorageUsed(); - Account account = PublicMethed.queryAccount(testNetAccountKey, blockingStubFull); - logger.info("before balance is " + Long.toString(account.getBalance())); - logger.info("before cpu limit is " + Long.toString(cpuLimit)); - logger.info("before cpu usage is " + Long.toString(cpuUsage)); - //logger.info("before storage limit is " + Long.toString(storageLimit)); - //logger.info("before storage usaged is " + Long.toString(storageUsage)); - Long maxFeeLimit = 3900000000L; - String contractName = "Fomo3D"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_TestNetFomo3D_deployErc721CryptoKitties"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_TestNetFomo3D_deployErc721CryptoKitties"); - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testNetAccountKey, testNetAccountAddress, blockingStubFull); - - String code1 = Configuration.getByPath("testng.conf") - .getString("code.code1_TestNetFomo3D_deployErc721CryptoKitties"); - String abi1 = Configuration.getByPath("testng.conf") - .getString("abi.abi1_TestNetFomo3D_deployErc721CryptoKitties"); - String txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi1, - code1, "", maxFeeLimit, 0L, 100, null, - testNetAccountKey, testNetAccountAddress, blockingStubFull); - - final SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - accountResource = PublicMethed.getAccountResource(testNetAccountAddress, blockingStubFull); - cpuLimit = accountResource.getEnergyLimit(); - //storageLimit = accountResource.getStorageLimit(); - cpuUsage = accountResource.getEnergyUsed(); - //storageUsage = accountResource.getStorageUsed(); - account = PublicMethed.queryAccount(testNetAccountKey, blockingStubFull); - logger.info("after balance is " + Long.toString(account.getBalance())); - logger.info("after cpu limit is " + Long.toString(cpuLimit)); - logger.info("after cpu usage is " + Long.toString(cpuUsage)); - //logger.info("after storage limit is " + Long.toString(storageLimit)); - //logger.info("after storage usaged is " + Long.toString(storageUsage)); - //Assert.assertTrue(storageUsage > 0); - //Assert.assertTrue(storageLimit > 0); - Assert.assertTrue(cpuLimit > 0); - Assert.assertTrue(cpuUsage > 0); - - Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); - Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); - Assert.assertFalse(smartContract.getBytecode().toString().isEmpty()); - //logger.info(smartContract.getName()); - //logger.info(smartContract.getAbi().toString()); - - } - - @Test(enabled = false) - public void tooLargeStorage() throws IOException { - AccountResourceMessage accountResource = PublicMethed.getAccountResource(testNetAccountAddress, - blockingStubFull); - Long cpuLimit = accountResource.getEnergyLimit(); - Long cpuUsage = accountResource.getEnergyUsed(); - Account account = PublicMethed.queryAccount(testNetAccountKey, blockingStubFull); - logger.info("before balance is " + Long.toString(account.getBalance())); - logger.info("before cpu limit is " + Long.toString(cpuLimit)); - logger.info("before cpu usage is " + Long.toString(cpuUsage)); - Long maxFeeLimit = 100000000000000000L; - String contractName = "tooLargeStorage"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_TestNetFomo3D_tooLargeStorage"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_TestNetFomo3D_tooLargeStorage"); - String txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, - code, "", maxFeeLimit, 0L, 100, null, - testNetAccountKey, testNetAccountAddress, blockingStubFull); - infoById = getTransactionInfoById(txid, blockingStubFull); - accountResource = PublicMethed.getAccountResource(testNetAccountAddress, blockingStubFull); - cpuLimit = accountResource.getEnergyLimit(); - //storageLimit = accountResource.getStorageLimit(); - cpuUsage = accountResource.getEnergyUsed(); - //storageUsage = accountResource.getStorageUsed(); - account = PublicMethed.queryAccount(testNetAccountKey, blockingStubFull); - logger.info("after balance is " + Long.toString(account.getBalance())); - logger.info("after cpu limit is " + Long.toString(cpuLimit)); - logger.info("after cpu usage is " + Long.toString(cpuUsage)); - - /* String name = readFromXieChang();*/ - String stringTimes = Integer.toString(7); - byte[] contractAddress = infoById.get().getContractAddress().toByteArray(); - txid = PublicMethed.triggerContract(contractAddress, "slice(uint256)", stringTimes, false, - 0, maxFeeLimit, testNetAccountAddress, testNetAccountKey, blockingStubFull); - logger.info("slice " + txid); - logger.info(Integer.toString(infoById.get().getResultValue())); - infoById = getTransactionInfoById(txid, blockingStubFull); - - txid = PublicMethed.triggerContract(contractAddress, "s()", "#", false, - 0, maxFeeLimit, testNetAccountAddress, testNetAccountKey, blockingStubFull); - logger.info(txid); - logger.info(Integer.toString(infoById.get().getResultValue())); - - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public String readFromXieChang() throws IOException { - File file = new File( - "/Users/wangzihe/Desktop/ddd.txt"); - FileReader reader = null; - try { - reader = new FileReader(file); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - BufferedReader reAder = new BufferedReader(reader); - StringBuilder sb = new StringBuilder(); - String s = ""; - while ((s = reAder.readLine()) != null) { - sb.append(s); - } - - String code = sb.toString(); - reAder.close(); - return code; - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/TestOperations.java b/framework/src/test/java/stest/tron/wallet/onlinestress/TestOperations.java deleted file mode 100644 index ece70cb9ccf..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/TestOperations.java +++ /dev/null @@ -1,43 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import lombok.extern.slf4j.Slf4j; -import org.testng.annotations.Test; -import org.tron.common.utils.ByteArray; - -@Slf4j -public class TestOperations { - - @Test(enabled = true) - public void test002() { - //指定需要支持的合约id(查看proto中Transaction.ContractType定义), - // 这里包含除AccountPermissionUpdateContract(id=46)以外的所有合约 - Integer[] contractId = {0, 1, 2, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 30, 31, 33, - 41, 42, 43, 44, 45, 48, 49}; - List list = new ArrayList<>(Arrays.asList(contractId)); - byte[] operations = new byte[32]; - list.forEach(e -> { - operations[e / 8] |= (1 << e % 8); - }); - //77ff07c0023e0300000000000000000000000000000000000000000000000000 - logger.info(ByteArray.toHexString(operations)); - } - - @Test(enabled = true) - public void test003() { - String operations = "77ff07c0023e0300000000000000000000000000000000000000000000000000"; - List contractId = new ArrayList<>(); - for (int i = 0; i < operations.length(); i = i + 2) { - int operation16 = Integer.valueOf(operations.substring(i, i + 2), 16); - for (int n = 0; n < 8; n++) { - int tmp = 1 << n; - if ((tmp & operation16) == tmp) { - contractId.add(i * 4 + n); - } - } - } - logger.info(contractId.toString()); - } -} diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/TestStorageAndCpu.java b/framework/src/test/java/stest/tron/wallet/onlinestress/TestStorageAndCpu.java deleted file mode 100644 index 6123461efe3..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/TestStorageAndCpu.java +++ /dev/null @@ -1,233 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletGrpc; -import org.tron.common.utils.ByteArray; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.ChainParameters; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.Sha256Hash; - -@Slf4j -public class TestStorageAndCpu { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("witness.key5"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("witness.key4"); - private final byte[] testAddress003 = PublicMethed.getFinalAddress(testKey003); - - private final String testKey004 = Configuration.getByPath("testng.conf") - .getString("witness.key3"); - private final byte[] testAddress004 = PublicMethed.getFinalAddress(testKey004); - ArrayList txidList = new ArrayList(); - Optional infoById = null; - Long beforeTime; - Long afterTime; - Long beforeBlockNum; - Long afterBlockNum; - Block currentBlock; - Long currentBlockNum; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = "47.94.243.150:50051"; - private String fullnode1 = "47.94.243.150:50051"; - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(testKey002); - PublicMethed.printAddress(testKey003); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - currentBlock = blockingStubFull1.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - beforeBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - beforeTime = System.currentTimeMillis(); - } - - @Test(enabled = true,threadPoolSize = 1, invocationCount = 1) - public void scanBlock() { - Long startNum = 26165658L; - Long endNum = 26166320L; - Integer totalNum = 0; - Integer successNum = 0; - Integer failedNum = 0; - NumberMessage.Builder builder = NumberMessage.newBuilder(); - while (startNum <= endNum) { - logger.info("scan block num:" + startNum); - builder.setNum(startNum); - List transactionList = blockingStubFull - .getBlockByNum(builder.build()).getTransactionsList(); - Integer transactionNumInThisBlock = transactionList.size(); - totalNum = totalNum + transactionNumInThisBlock; - for (Transaction transaction : transactionList) { - if (transaction.getRet(0).getContractRet().name().equals("SUCCESS")) { - successNum++; - } else { - failedNum++; - logger.info(transaction.getRet(0).getContractRet().name()); - } - } - startNum++; - } - logger.info("successNum:" + successNum); - logger.info("failedNum:" + failedNum); - logger.info("totalNum:" + totalNum); - logger.info("Success rate:" + (double)failedNum / (double)totalNum); - } - - @Test(enabled = true, threadPoolSize = 1, invocationCount = 1) - public void storageAndCpu() { - Random rand = new Random(); - Integer randNum = rand.nextInt(30) + 1; - randNum = rand.nextInt(4000); - - Long maxFeeLimit = 1000000000L; - String contractName = "StorageAndCpu" + Integer.toString(randNum); - String code = Configuration.getByPath("testng.conf") - .getString("code.code_TestStorageAndCpu_storageAndCpu"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_TestStorageAndCpu_storageAndCpu"); - PublicMethed - .freezeBalanceGetEnergy(fromAddress, 1000000000000L, 3, 1, testKey002, blockingStubFull); - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, - "", maxFeeLimit, - 0L, 100, null, testKey002, fromAddress, blockingStubFull); - try { - Thread.sleep(30000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - String txid; - - ChainParameters chainParameters = blockingStubFull - .getChainParameters(EmptyMessage.newBuilder().build()); - Optional getChainParameters = Optional.ofNullable(chainParameters); - - Integer i = 1; - while (i++ < 8000) { - String initParmes = "\"" + "930" + "\""; - txid = PublicMethed.triggerContract(contractAddress, - "testUseCpu(uint256)", "9100", false, - 0, maxFeeLimit, fromAddress, testKey002, blockingStubFull); - txid = PublicMethed.triggerContract(contractAddress, - "storage8Char()", "", false, - 0, maxFeeLimit, fromAddress, testKey002, blockingStubFull); - //storage 9 EnergyUsageTotal is 211533, 10 is 236674, 5 is 110969,21 is 500000 - txid = PublicMethed.triggerContract(contractAddress, - "testUseStorage(uint256)", "21", false, - 0, maxFeeLimit, fromAddress, testKey002, blockingStubFull); - //logger.info("i is " +Integer.toString(i) + " " + txid); - //txidList.add(txid); - try { - Thread.sleep(50); - } catch (InterruptedException e) { - e.printStackTrace(); - } - if (i % 10 == 0) { - chainParameters = blockingStubFull - .getChainParameters(EmptyMessage.newBuilder().build()); - getChainParameters = Optional.ofNullable(chainParameters); - logger.info(getChainParameters.get().getChainParameter(22).getKey()); - logger.info(Long.toString(getChainParameters.get().getChainParameter(22).getValue())); - logger.info(getChainParameters.get().getChainParameter(23).getKey()); - logger.info(Long.toString(getChainParameters.get().getChainParameter(23).getValue())); - - } - } - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - /* - afterTime = System.currentTimeMillis(); - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - currentBlock = blockingStubFull1.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - afterBlockNum = currentBlock.getBlockHeader().getRawData().getNumber() + 2; - Long blockNum = beforeBlockNum; - Integer txsNum = 0; - Integer topNum = 0; - Integer totalNum = 0; - Long energyTotal = 0L; - String findOneTxid = ""; - - NumberMessage.Builder builder = NumberMessage.newBuilder(); - while (blockNum <= afterBlockNum) { - builder.setNum(blockNum); - txsNum = blockingStubFull1.getBlockByNum(builder.build()).getTransactionsCount(); - totalNum = totalNum + txsNum; - if (topNum < txsNum) { - topNum = txsNum; - findOneTxid = ByteArray.toHexString(Sha256Hash.hash(blockingStubFull1 - .getBlockByNum(builder.build()).getTransactionsList().get(2) - .getRawData().toByteArray())); - //logger.info("find one txid is " + findOneTxid); - } - - blockNum++; - } - Long costTime = (afterTime - beforeTime - 31000) / 1000; - logger.info("Duration block num is " + (afterBlockNum - beforeBlockNum - 11)); - logger.info("Cost time are " + costTime); - logger.info("Top block txs num is " + topNum); - logger.info("Total transaction is " + (totalNum - 30)); - logger.info("Average Tps is " + (totalNum / costTime)); - - infoById = PublicMethed.getTransactionInfoById(findOneTxid, blockingStubFull1); - Long oneEnergyTotal = infoById.get().getReceipt().getEnergyUsageTotal(); - logger.info("EnergyTotal is " + oneEnergyTotal); - logger.info("Average energy is " + oneEnergyTotal * (totalNum / costTime)); -*/ - - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/TestTransferTokenInContract.java b/framework/src/test/java/stest/tron/wallet/onlinestress/TestTransferTokenInContract.java deleted file mode 100644 index 7a50f64f922..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/TestTransferTokenInContract.java +++ /dev/null @@ -1,324 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AssetIssueList; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class TestTransferTokenInContract { - - private static final long TotalSupply = 1000000L; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - private AtomicLong count = new AtomicLong(); - private AtomicLong errorCount = new AtomicLong(); - private long startTime = System.currentTimeMillis(); - private ManagedChannel channelFull = null; - private ManagedChannel channelFull1 = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - - private static int randomInt(int minInt, int maxInt) { - return (int) Math.round(Math.random() * (maxInt - minInt) + minInt); - } - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - } - - /** - * constructor. - */ - - public ByteString createAssetissue(byte[] devAddress, String devKey, String tokenName) { - - ByteString assetAccountId = null; - ByteString addressBS1 = ByteString.copyFrom(devAddress); - Account request1 = Account.newBuilder().setAddress(addressBS1).build(); - GrpcAPI.AssetIssueList assetIssueList1 = blockingStubFull - .getAssetIssueByAccount(request1); - Optional queryAssetByAccount = Optional.ofNullable(assetIssueList1); - if (queryAssetByAccount.get().getAssetIssueCount() == 0) { - Long start = System.currentTimeMillis() + 2000; - Long end = System.currentTimeMillis() + 1000000000; - - logger.info("The token name: " + tokenName); - - //Create a new AssetIssue success. - Assert.assertTrue(PublicMethed.createAssetIssue(devAddress, tokenName, TotalSupply, 1, - 100, start, end, 1, description, url, 10000L, 10000L, - 1L, 1L, devKey, blockingStubFull)); - - Account getAssetIdFromThisAccount = PublicMethed.queryAccount(devAddress, blockingStubFull); - assetAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - } else { - logger.info("This account already create an assetisue"); - Optional queryAssetByAccount1 = Optional.ofNullable(assetIssueList1); - tokenName = ByteArray.toStr(queryAssetByAccount1.get().getAssetIssue(0) - .getName().toByteArray()); - } - return assetAccountId; - } - - @Test(enabled = true, threadPoolSize = 2, invocationCount = 2) - public void continueRun() { - - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] dev001Address = ecKey1.getAddress(); - String dev001Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] user001Address = ecKey2.getAddress(); - String user001Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - Assert - .assertTrue(PublicMethed.sendcoin(dev001Address, 2048000000, fromAddress, - testKey002, blockingStubFull)); - Assert - .assertTrue(PublicMethed.sendcoin(user001Address, 4048000000L, fromAddress, - testKey002, blockingStubFull)); - - // freeze balance - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(dev001Address, 204800000, - 0, 1, dev001Key, blockingStubFull)); - - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(user001Address, 2048000000, - 0, 1, user001Key, blockingStubFull)); - - String tokenName = "testAI_" + randomInt(10000, 90000); - ByteString tokenId = createAssetissue(user001Address, user001Key, tokenName); - - // devAddress transfer token to A - PublicMethed.transferAsset(dev001Address, tokenId.toByteArray(), 101, user001Address, - user001Key, blockingStubFull); - - // deploy transferTokenContract - String contractName = "transferTokenContract"; - String code = "608060405260e2806100126000396000f300608060405260043610603e5763ffffffff7c01000000" - + "000000000000000000000000000000000000000000000000006000350416633be9ece781146043575b600080" - + "fd5b606873ffffffffffffffffffffffffffffffffffffffff60043516602435604435606a565b005b604051" - + "73ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8a" - + "d094505050505015801560b0573d6000803e3d6000fd5b505050505600a165627a7a723058200ba246bdb58b" - + "e0f221ad07e1b19de843ab541150b329ddd01558c2f1cefe1e270029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}," - + "{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}]," - + "\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":" - + "\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\"" - + ":\"payable\",\"type\":\"constructor\"}]"; - byte[] transferTokenContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, 10000, tokenId.toStringUtf8(), - 100, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // deploy receiveTokenContract - contractName = "recieveTokenContract"; - code = "60806040526000805560c5806100166000396000f30060806040526004361060485763ffffffff7c0100000" - + "00000000000000000000000000000000000000000000000000060003504166362548c7b8114604a578063890" - + "eba68146050575b005b6048608c565b348015605b57600080fd5b50d38015606757600080fd5b50d28015607" - + "357600080fd5b50607a6093565b60408051918252519081900360200190f35b6001600055565b60005481560" - + "0a165627a7a723058204c4f1bb8eca0c4f1678cc7cc1179e03d99da2a980e6792feebe4d55c89c022830029"; - abi = "[{\"constant\":false,\"inputs\":[],\"name\":\"setFlag\",\"outputs\":[],\"payable\":true," - + "\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[]," - + "\"name\":\"flag\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false," - + "\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true," - + "\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true," - + "\"stateMutability\":\"payable\",\"type\":\"fallback\"}]"; - byte[] receiveTokenContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, dev001Key, dev001Address, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // deploy tokenBalanceContract - contractName = "tokenBalanceContract"; - code = "608060405260ff806100126000396000f30060806040526004361060485763ffffffff7c010000000000000" - + "0000000000000000000000000000000000000000000600035041663a730416e8114604d578063b69ef8a8146" - + "081575b600080fd5b606f73ffffffffffffffffffffffffffffffffffffffff6004351660243560ab565b604" - + "08051918252519081900360200190f35b348015608c57600080fd5b50d38015609857600080fd5b50d280156" - + "0a457600080fd5b50606f60cd565b73ffffffffffffffffffffffffffffffffffffffff90911690d16000908" - + "15590565b600054815600a165627a7a723058202b6235122df66c062c2e723ad58a9fea93346f3bc19898971" - + "8f211aa1dbd2d7a0029"; - abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}," - + "{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getTokenBalnce\",\"outputs\":" - + "[{\"name\":\"b\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":" - + "\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":" - + "\"balance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false," - + "\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true," - + "\"stateMutability\":\"payable\",\"type\":\"constructor\"}]"; - byte[] tokenBalanceContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, dev001Key, dev001Address, blockingStubFull); - - // devAddress transfer token to userAddress - PublicMethed.transferAsset(user001Address, tokenId.toByteArray(), 100, dev001Address, dev001Key, - blockingStubFull); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull1); - - for (int i = 0; i < 1000000000000L; i++) { - logger.info("** This is " + i + "times --------------------------------------------"); - count.getAndAdd(4); - if (count.get() % 500 == 0) { - long cost = (System.currentTimeMillis() - startTime) / 1000; - logger.info("Count:" + count.get() + ", cost:" + cost - + ", avg:" + count.get() / cost + ", errCount:" + errorCount); - } - PublicMethed.freezeBalanceForReceiver(user001Address, - PublicMethed.getFreezeBalanceCount(user001Address, - user001Key, 300000L, blockingStubFull), 0, - 1, ByteString.copyFrom(fromAddress), testKey002, blockingStubFull); - PublicMethed.freezeBalanceForReceiver(user001Address, 10_000_000L, - 0, 0, ByteString.copyFrom(fromAddress), testKey002, blockingStubFull); - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - // user trigger A to transfer token to B - String param = - "\"" + Base58.encode58Check(receiveTokenContractAddress) + "\",\"" + tokenId - .toStringUtf8() - + "\",\"5\""; - - String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "TransferTokenTo(address,trcToken,uint256)", - param, false, 0, 100000000L, tokenId.toStringUtf8(), - 10, user001Address, user001Key, - blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - errorCount.incrementAndGet(); - } - - // user trigger A to transfer token to devAddress - param = - "\"" + Base58.encode58Check(dev001Address) + "\",\"" + tokenId.toStringUtf8() - + "\",\"5\""; - - triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "TransferTokenTo(address,trcToken,uint256)", - param, false, 0, 100000000L, user001Address, - user001Key, blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - errorCount.incrementAndGet(); - } - - // user trigger C to get B's token balance - param = - "\"" + Base58.encode58Check(receiveTokenContractAddress) + "\",\"" + tokenId - .toStringUtf8() - + "\""; - - triggerTxid = PublicMethed - .triggerContract(tokenBalanceContractAddress, "getTokenBalnce(address,trcToken)", - param, false, 0, 1000000000L, user001Address, - user001Key, blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - errorCount.incrementAndGet(); - } - - PublicMethed.triggerContract(tokenBalanceContractAddress, "balance()", - "#", false, 0, 1000000000L, user001Address, - user001Key, blockingStubFull); - - // user trigger C to get devAddress's token balance - param = "\"" + Base58.encode58Check(dev001Address) + "\",\"" + tokenId.toStringUtf8() + "\""; - - triggerTxid = PublicMethed - .triggerContract(tokenBalanceContractAddress, "getTokenBalnce(address,trcToken)", - param, false, 0, 1000000000L, user001Address, - user001Key, blockingStubFull); - - infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); - - if (infoById.get().getResultValue() != 0) { - errorCount.incrementAndGet(); - } - - PublicMethed.triggerContract(tokenBalanceContractAddress, "balance()", - "#", false, 0, 1000000000L, user001Address, - user001Key, blockingStubFull); - - PublicMethed.unFreezeBalance(fromAddress, user001Key, 1, - user001Address, blockingStubFull); - PublicMethed.unFreezeBalance(fromAddress, user001Key, 0, - user001Address, blockingStubFull); - } - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/TransactionCheck.java b/framework/src/test/java/stest/tron/wallet/onlinestress/TransactionCheck.java deleted file mode 100644 index c14e596e378..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/TransactionCheck.java +++ /dev/null @@ -1,52 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import com.google.protobuf.ByteString; -import org.testng.annotations.Test; -import org.tron.common.crypto.ECKey.ECDSASignature; -import org.tron.common.crypto.SignUtils; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.ByteArray; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Sha256Hash; - -public class TransactionCheck { - - @Test - public void hexToTransaction() throws Exception { - String targetHex1 = ""; - String targetHex2 = ""; - String hex = targetHex1; - org.tron.protos.Protocol.Transaction transaction = org.tron.protos.Protocol.Transaction - .parseFrom(ByteArray.fromHexString(hex)); - getBase64FromByteString(transaction.getSignature(0)); - String base64 = getBase64FromByteString(transaction.getSignature(0)); - byte[] address = SignUtils - .signatureToAddress((Sha256Hash - .hash(CommonParameter.getInstance().isECKeyCryptoEngine(), - transaction.getRawData().toByteArray())), base64, - CommonParameter.getInstance().isECKeyCryptoEngine()); - String addressStr = WalletClient.encode58Check(address); - String data = String.valueOf(transaction.getRawData().getData().toStringUtf8()); - System.out.println(addressStr); - System.out.println(data); - } - - - /** - * constructor. - */ - public static String getBase64FromByteString(ByteString sign) { - byte[] r = sign.substring(0, 32).toByteArray(); - byte[] s = sign.substring(32, 64).toByteArray(); - byte v = sign.byteAt(64); - if (v < 27) { - v += 27; //revId -> v - } - ECDSASignature signature = ECDSASignature.fromComponents(r, s, v); - return signature.toBase64(); - } - - - - -} diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/WalletTestZenTokenStress.java b/framework/src/test/java/stest/tron/wallet/onlinestress/WalletTestZenTokenStress.java deleted file mode 100644 index b585bb91036..00000000000 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/WalletTestZenTokenStress.java +++ /dev/null @@ -1,268 +0,0 @@ -package stest.tron.wallet.onlinestress; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.BytesMessage; -import org.tron.api.GrpcAPI.DecryptNotes; -import org.tron.api.GrpcAPI.DiversifierMessage; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.ExpandedSpendingKeyMessage; -import org.tron.api.GrpcAPI.IncomingViewingKeyDiversifierMessage; -import org.tron.api.GrpcAPI.IncomingViewingKeyMessage; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.GrpcAPI.PaymentAddressMessage; -import org.tron.api.GrpcAPI.ViewingKeyMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.config.args.Args; -import org.tron.core.zen.address.DiversifierT; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; - - -@Slf4j -public class WalletTestZenTokenStress { - - private static ByteString assetAccountId = null; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - Optional sendShieldAddressInfo; - Optional receiverShieldAddressInfo; - String sendShieldAddress; - String receiverShieldAddress; - List shieldOutList = new ArrayList<>(); - DecryptNotes notes; - String memo; - Note sendNote; - Note receiverNote; - BytesMessage ak; - BytesMessage nk; - BytesMessage sk; - ExpandedSpendingKeyMessage expandedSpendingKeyMessage; - DiversifierMessage diversifierMessage1; - DiversifierMessage diversifierMessage2; - DiversifierMessage diversifierMessage3; - IncomingViewingKeyMessage ivk; - ShieldAddressInfo addressInfo1 = new ShieldAddressInfo(); - ShieldAddressInfo addressInfo2 = new ShieldAddressInfo(); - ShieldAddressInfo addressInfo3 = new ShieldAddressInfo(); - - Optional receiverAddressInfo1; - Optional receiverAddressInfo2; - Optional receiverAddressInfo3; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey1.getAddress(); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private ManagedChannel channelSolidity1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity1 = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - private String soliditynode1 = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private byte[] tokenId = zenTokenId.getBytes(); - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private Long costTokenAmount = 1 * zenTokenFee + 1; - private Long sendTokenAmount = 1 * zenTokenFee; - - - - /** - * constructor. - */ - @BeforeClass(enabled = true) - public void beforeClass() { - PublicMethed.printAddress(foundationZenTokenKey); - PublicMethed.printAddress(zenTokenOwnerKey); - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - channelSolidity1 = ManagedChannelBuilder.forTarget(soliditynode1) - .usePlaintext() - .build(); - blockingStubSolidity1 = WalletSolidityGrpc.newBlockingStub(channelSolidity1); - - Assert.assertTrue(PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Args.setFullNodeAllowShieldedTransaction(true); - - - } - - @Test(enabled = true, threadPoolSize = 3, invocationCount = 3) - public void test1Shield2ShieldTransaction() throws InterruptedException { - List shieldOutList = new ArrayList<>(); - Integer times = 0; - Optional sendShieldAddressInfo = PublicMethed.generateShieldAddress(); - String sendShieldAddress = sendShieldAddressInfo.get().getAddress(); - String memo = "7"; - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress, - "" + zenTokenFee, memo); - while (times++ < 10000) { - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] zenTokenOwnerAddress = ecKey1.getAddress(); - - PublicMethed.transferAsset(zenTokenOwnerAddress, tokenId, - zenTokenFee * 2, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - memo = times + ":shield note number"; - shieldOutList.clear(); - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, sendShieldAddress, - "" + zenTokenFee, memo); - String zenTokenOwnerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - PublicMethed.sendShieldCoin(zenTokenOwnerAddress, 2 * zenTokenFee, null, - null, shieldOutList, null, 0, zenTokenOwnerKey, blockingStubFull); - /* logger.info("Note number:" - + PublicMethed.getShieldNotesCount(sendShieldAddressInfo,blockingStubFull));*/ - } - - - } - - @Test(enabled = true, threadPoolSize = 30, invocationCount = 30) - public void test2Shield2ShieldTransaction() throws InterruptedException { - BytesMessage ak; - BytesMessage nk; - BytesMessage sk; - ExpandedSpendingKeyMessage expandedSpendingKeyMessage; - DiversifierMessage diversifierMessage1; - DiversifierMessage diversifierMessage2; - DiversifierMessage diversifierMessage3; - IncomingViewingKeyMessage ivk; - ShieldAddressInfo addressInfo1 = new ShieldAddressInfo(); - ShieldAddressInfo addressInfo2 = new ShieldAddressInfo(); - ShieldAddressInfo addressInfo3 = new ShieldAddressInfo(); - - Optional receiverAddressInfo1; - Optional receiverAddressInfo2; - Optional receiverAddressInfo3; - - Integer times = 0; - while (times++ < 10000) { - sk = blockingStubFull.getSpendingKey(EmptyMessage.newBuilder().build()); - //logger.info("sk: " + ByteArray.toHexString(sk.getValue().toByteArray())); - - diversifierMessage1 = blockingStubFull.getDiversifier(EmptyMessage.newBuilder().build()); - //logger.info("d1: " + ByteArray.toHexString(diversifierMessage1.getD().toByteArray())); - diversifierMessage2 = blockingStubFull.getDiversifier(EmptyMessage.newBuilder().build()); - //logger.info("d2: " + ByteArray.toHexString(diversifierMessage2.getD().toByteArray())); - diversifierMessage3 = blockingStubFull.getDiversifier(EmptyMessage.newBuilder().build()); - //logger.info("d3: " + ByteArray.toHexString(diversifierMessage3.getD().toByteArray())); - - expandedSpendingKeyMessage = blockingStubFull.getExpandedSpendingKey(sk); - - BytesMessage.Builder askBuilder = BytesMessage.newBuilder(); - askBuilder.setValue(expandedSpendingKeyMessage.getAsk()); - ak = blockingStubFull.getAkFromAsk(askBuilder.build()); - //logger.info("ak: " + ByteArray.toHexString(ak.getValue().toByteArray())); - - BytesMessage.Builder nskBuilder = BytesMessage.newBuilder(); - nskBuilder.setValue(expandedSpendingKeyMessage.getNsk()); - nk = blockingStubFull.getNkFromNsk(nskBuilder.build()); - //logger.info("nk: " + ByteArray.toHexString(nk.getValue().toByteArray())); - - ViewingKeyMessage.Builder viewBuilder = ViewingKeyMessage.newBuilder(); - viewBuilder.setAk(ak.getValue()); - viewBuilder.setNk(nk.getValue()); - ivk = blockingStubFull.getIncomingViewingKey(viewBuilder.build()); - //logger.info("ivk: " + ByteArray.toHexString(ivk.getIvk().toByteArray())); - - IncomingViewingKeyDiversifierMessage.Builder builder = - IncomingViewingKeyDiversifierMessage.newBuilder(); - builder.setD(diversifierMessage1); - builder.setIvk(ivk); - PaymentAddressMessage addressMessage = blockingStubFull.getZenPaymentAddress(builder.build()); - //System.out.println("address1: " + addressMessage.getPaymentAddress()); - addressInfo1.setSk(sk.getValue().toByteArray()); - addressInfo1.setD(new DiversifierT(diversifierMessage1.getD().toByteArray())); - addressInfo1.setIvk(ivk.getIvk().toByteArray()); - addressInfo1.setOvk(expandedSpendingKeyMessage.getOvk().toByteArray()); - addressInfo1.setPkD(addressMessage.getPkD().toByteArray()); - receiverAddressInfo1 = Optional.of(addressInfo1); - - builder.clear(); - builder = IncomingViewingKeyDiversifierMessage.newBuilder(); - builder.setD(diversifierMessage2); - builder.setIvk(ivk); - addressMessage = blockingStubFull.getZenPaymentAddress(builder.build()); - //System.out.println("address2: " + addressMessage.getPaymentAddress()); - addressInfo2.setSk(sk.getValue().toByteArray()); - addressInfo2.setD(new DiversifierT(diversifierMessage2.getD().toByteArray())); - addressInfo2.setIvk(ivk.getIvk().toByteArray()); - addressInfo2.setOvk(expandedSpendingKeyMessage.getOvk().toByteArray()); - addressInfo2.setPkD(addressMessage.getPkD().toByteArray()); - receiverAddressInfo2 = Optional.of(addressInfo2); - - builder.clear(); - builder = IncomingViewingKeyDiversifierMessage.newBuilder(); - builder.setD(diversifierMessage3); - builder.setIvk(ivk); - addressMessage = blockingStubFull.getZenPaymentAddress(builder.build()); - //System.out.println("address3: " + addressMessage.getPaymentAddress()); - addressInfo3.setSk(sk.getValue().toByteArray()); - addressInfo3.setD(new DiversifierT(diversifierMessage3.getD().toByteArray())); - addressInfo3.setIvk(ivk.getIvk().toByteArray()); - addressInfo3.setOvk(expandedSpendingKeyMessage.getOvk().toByteArray()); - addressInfo3.setPkD(addressMessage.getPkD().toByteArray()); - receiverAddressInfo3 = Optional.of(addressInfo3); - } - - } - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - PublicMethed.transferAsset(foundationZenTokenAddress, tokenId, - PublicMethed.getAssetIssueValue(zenTokenOwnerAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull), zenTokenOwnerAddress, zenTokenOwnerKey, blockingStubFull); - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity1 != null) { - channelSolidity1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} \ No newline at end of file diff --git a/framework/src/test/java/stest/tron/wallet/other/deployMainGateway.java b/framework/src/test/java/stest/tron/wallet/other/deployMainGateway.java deleted file mode 100644 index 2eb4df97095..00000000000 --- a/framework/src/test/java/stest/tron/wallet/other/deployMainGateway.java +++ /dev/null @@ -1,129 +0,0 @@ -package stest.tron.wallet.other; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class deployMainGateway { - - - private final String testDepositTrx = "324a2052e491e99026442d81df4d2777292840c1b3949e20696c49096" - + "c6bacb7"; - private final byte[] testDepositAddress = PublicMethed.getFinalAddress(testDepositTrx); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] depositAddress = ecKey1.getAddress(); - String testKeyFordeposit = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "deploy Main Chain Gateway") - public void test1DepositTrc20001() { - - PublicMethed.printAddress(testKeyFordeposit); - - Assert.assertTrue(PublicMethed - .sendcoin(depositAddress, 1000_000_000L, testDepositAddress, testDepositTrx, - blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Account accountOralce = PublicMethed.queryAccount(depositAddress, blockingStubFull); - long OralceBalance = accountOralce.getBalance(); - logger.info("OralceBalance: " + OralceBalance); - - String contractName = "gateWayContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_MainGateway"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_MainGateway"); - String parame = "\"" + Base58.encode58Check(testDepositAddress) + "\""; - - String deployTxid = PublicMethed - .deployContractWithConstantParame(contractName, abi, code, "constructor(address)", - parame, "", - maxFeeLimit, - 0L, 100, null, testKeyFordeposit, depositAddress, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - byte[] mainChainGateway = infoById.get().getContractAddress().toByteArray(); - String mainChainGatewayAddress = WalletClient.encode58Check(mainChainGateway); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertNotNull(mainChainGateway); - - SmartContract smartContract = PublicMethed.getContract(mainChainGateway, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - String outputPath = "./src/test/resources/mainChainGatewayAddress"; - try { - File mainChainFile = new File(outputPath); - Boolean cun = mainChainFile.createNewFile(); - FileWriter writer = new FileWriter(mainChainFile); - BufferedWriter out = new BufferedWriter(writer); - out.write(mainChainGatewayAddress); - - out.close(); - writer.close(); - } catch (Exception e) { - e.printStackTrace(); - } - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/other/deploySideGateway.java b/framework/src/test/java/stest/tron/wallet/other/deploySideGateway.java deleted file mode 100644 index 326441d0d97..00000000000 --- a/framework/src/test/java/stest/tron/wallet/other/deploySideGateway.java +++ /dev/null @@ -1,122 +0,0 @@ -package stest.tron.wallet.other; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class deploySideGateway { - - - private final String testDepositTrx = "324a2052e491e99026442d81df4d2777292840c1b3949e20696c49096" - + "c6bacb7"; - private final byte[] testDepositAddress = PublicMethed.getFinalAddress(testDepositTrx); - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] depositAddress = ecKey1.getAddress(); - String testKeyFordeposit = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private Long maxFeeLimit = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.maxFeeLimit"); - private String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - private String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = "127.0.0.1:50151"; - - - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - @Test(enabled = true, description = "deploy Side Chain Gateway") - public void test1DepositTrc20001() { - - PublicMethed.printAddress(testKeyFordeposit); - - String contractName = "gateWaysidechainContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_SideGateway"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_SideGateway"); - String parame = "\"" + Base58.encode58Check(testDepositAddress) + "\""; - - String deployTxid = PublicMethed - .deployContractWithConstantParame(contractName, abi, code, "constructor(address)", - parame, "", - maxFeeLimit, - 0L, 100, null, testKeyFordeposit, depositAddress, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionInfoById(deployTxid, blockingStubFull); - byte[] mainChainGateway = infoById.get().getContractAddress().toByteArray(); - String mainChainGatewayAddress = WalletClient.encode58Check(mainChainGateway); - Assert.assertEquals(0, infoById.get().getResultValue()); - Assert.assertNotNull(mainChainGateway); - - SmartContract smartContract = PublicMethed.getContract(mainChainGateway, - blockingStubFull); - Assert.assertNotNull(smartContract.getAbi()); - - String outputPath = "./src/test/resources/sideChainGatewayAddress"; - try { - File mainChainFile = new File(outputPath); - Boolean cun = mainChainFile.createNewFile(); - FileWriter writer = new FileWriter(mainChainFile); - BufferedWriter out = new BufferedWriter(writer); - out.write(mainChainGatewayAddress); - - out.close(); - writer.close(); - } catch (Exception e) { - e.printStackTrace(); - } - - } - - /** - * constructor. - */ - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - -} diff --git a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer001.java b/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer001.java deleted file mode 100644 index 1ff26d3398e..00000000000 --- a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer001.java +++ /dev/null @@ -1,320 +0,0 @@ -package stest.tron.wallet.transfer; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.BalanceContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class WalletTestTransfer001 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - //send account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - final byte[] sendAccountAddress = ecKey1.getAddress(); - String sendAccountKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - //receipt account - ECKey ecKey2 = new ECKey(Utils.getRandom()); - final byte[] receiptAccountAddress = ecKey2.getAddress(); - String receiptAccountKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private ManagedChannel searchChannelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletGrpc.WalletBlockingStub searchBlockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String searchFullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext() - .build(); - searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); - } - - @Test - public void testSendCoin() { - //send account - ecKey1 = new ECKey(Utils.getRandom()); - final byte[] sendAccountAddress = ecKey1.getAddress(); - sendAccountKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - //receipt account - ecKey2 = new ECKey(Utils.getRandom()); - final byte[] receiptAccountAddress = ecKey2.getAddress(); - receiptAccountKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - Assert.assertTrue(PublicMethed.sendcoin(sendAccountAddress, 90000000000L, - fromAddress, testKey002, blockingStubFull)); - - logger.info(receiptAccountKey); - //Test send coin. - Account sendAccount = PublicMethed.queryAccount(sendAccountKey, blockingStubFull); - Long sendAccountBeforeBalance = sendAccount.getBalance(); - Assert.assertTrue(sendAccountBeforeBalance == 90000000000L); - Account receiptAccount = PublicMethed.queryAccount(receiptAccountKey, blockingStubFull); - Long receiptAccountBeforeBalance = receiptAccount.getBalance(); - Assert.assertTrue(receiptAccountBeforeBalance == 0); - - //Test send coin - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert.assertTrue(PublicMethed.sendcoin(receiptAccountAddress, 49880000000L, - sendAccountAddress, sendAccountKey, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - sendAccount = PublicMethed.queryAccount(sendAccountKey, blockingStubFull); - Long sendAccountAfterBalance = sendAccount.getBalance(); - logger.info(Long.toString(sendAccountAfterBalance)); - Assert.assertTrue(sendAccountAfterBalance == 90000000000L - 49880000000L - 100000L); - - receiptAccount = PublicMethed.queryAccount(receiptAccountKey, blockingStubFull); - Long receiptAccountAfterBalance = receiptAccount.getBalance(); - logger.info(Long.toString(receiptAccountAfterBalance)); - Assert.assertTrue(receiptAccountAfterBalance == 49880000000L); - - //Send coin failed due to no enough balance. - Assert.assertFalse(sendcoin(toAddress, 9199999999999999999L, fromAddress, testKey002)); - //Send coin failed due to the amount is 0. - Assert.assertFalse(sendcoin(toAddress, 0L, fromAddress, testKey002)); - //Send coin failed due to the amount is -1Trx. - Assert.assertFalse(sendcoin(toAddress, -1000000L, fromAddress, testKey002)); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (searchChannelFull != null) { - searchChannelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean freezeBalance(byte[] addRess, long freezeBalance, long freezeDuration, - String priKey) { - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - final Long beforeBlockNum = currentBlock.getBlockHeader().getRawData().getNumber(); - Account beforeFronzen = queryAccount(ecKey, blockingStubFull); - Long beforeFrozenBalance = 0L; - //Long beforeBandwidth = beforeFronzen.getBandwidth(); - if (beforeFronzen.getFrozenCount() != 0) { - beforeFrozenBalance = beforeFronzen.getFrozen(0).getFrozenBalance(); - //beforeBandwidth = beforeFronzen.getBandwidth(); - //logger.info(Long.toString(beforeFronzen.getBandwidth())); - logger.info(Long.toString(beforeFronzen.getFrozen(0).getFrozenBalance())); - } - - BalanceContract.FreezeBalanceContract.Builder builder = BalanceContract.FreezeBalanceContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration); - - BalanceContract.FreezeBalanceContract contract = builder.build(); - Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction = null"); - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } - - Long afterBlockNum = 0L; - Integer wait = 0; - while (afterBlockNum < beforeBlockNum + 1 && wait < 10) { - Block currentBlock1 = searchBlockingStubFull - .getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - afterBlockNum = currentBlock1.getBlockHeader().getRawData().getNumber(); - wait++; - try { - Thread.sleep(2000); - logger.info("wait 2 second"); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - Account afterFronzen = queryAccount(ecKey, searchBlockingStubFull); - Long afterFrozenBalance = afterFronzen.getFrozen(0).getFrozenBalance(); - //Long afterBandwidth = afterFronzen.getBandwidth(); - //logger.info(Long.toString(afterFronzen.getBandwidth())); - logger.info(Long.toString(afterFronzen.getFrozen(0).getFrozenBalance())); - //logger.info(Integer.toString(search.getFrozenCount())); - logger.info( - "beforefronen" + beforeFrozenBalance.toString() + " afterfronzen" + afterFrozenBalance - .toString()); - Assert.assertTrue(afterFrozenBalance - beforeFrozenBalance == freezeBalance); - //Assert.assertTrue(afterBandwidth - beforeBandwidth == freezeBalance * frozen_duration); - return true; - - - } - - /** - * constructor. - */ - - public Boolean sendcoin(byte[] to, long amount, byte[] owner, String priKey) { - - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account search = queryAccount(ecKey, blockingStubFull); - - BalanceContract.TransferContract.Builder builder = BalanceContract.TransferContract - .newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - BalanceContract.TransferContract contract = builder.build(); - Transaction transaction = blockingStubFull.createTransaction(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - return response.getResult(); - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer003.java b/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer003.java deleted file mode 100644 index faf3ded16d7..00000000000 --- a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer003.java +++ /dev/null @@ -1,389 +0,0 @@ -package stest.tron.wallet.transfer; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.BytesMessage; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletExtensionGrpc; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; -import org.tron.protos.contract.AccountContract.AccountUpdateContract; -import org.tron.protos.contract.BalanceContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.Sha256Hash; -import stest.tron.wallet.common.client.utils.TransactionUtils; - - -@Slf4j -public class WalletTestTransfer003 { - - private static final long now = System.currentTimeMillis(); - private static final String name = "transaction007_" + Long.toString(now); - private static Protocol.Transaction sendCoinTransaction; - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - private final Long createUseFee = 100000L; - //get account - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] sendCoinAddress = ecKey1.getAddress(); - String testKeyForSendCoin = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] newAccountAddress = ecKey2.getAddress(); - String testKeyForNewAccount = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private ManagedChannel channelFull1 = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull1 = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletExtensionGrpc.WalletExtensionBlockingStub blockingStubExtension = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String fullnode1 = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - private static Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - /** - * constructor. - */ - - public static Protocol.Transaction sendcoin(byte[] to, long amount, byte[] owner, String priKey, - WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - //Protocol.Account search = queryAccount(priKey, blockingStubFull); - - BalanceContract.TransferContract.Builder builder = BalanceContract.TransferContract - .newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - BalanceContract.TransferContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createTransaction(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction ==null"); - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (!response.getResult()) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - } - return transaction; - } - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - logger.info(testKeyForSendCoin); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelFull1 = ManagedChannelBuilder.forTarget(fullnode1) - .usePlaintext() - .build(); - blockingStubFull1 = WalletGrpc.newBlockingStub(channelFull1); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - blockingStubExtension = WalletExtensionGrpc.newBlockingStub(channelSolidity); - - } - - @Test(enabled = true) - public void test1UseFeeOrNet() { - //get account - ecKey1 = new ECKey(Utils.getRandom()); - sendCoinAddress = ecKey1.getAddress(); - testKeyForSendCoin = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - - ecKey2 = new ECKey(Utils.getRandom()); - newAccountAddress = ecKey2.getAddress(); - testKeyForNewAccount = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - - Assert.assertTrue(PublicMethed.sendcoin(sendCoinAddress, 200000L, - fromAddress, testKey002, blockingStubFull)); - Long feeNum = 0L; - Long netNum = 0L; - Long sendNum = 0L; - Long feeCost = 0L; - Long times = 0L; - Account sendAccountInfo = PublicMethed.queryAccount(testKeyForSendCoin, blockingStubFull); - final Long beforeBalance = sendAccountInfo.getBalance(); - Long netUsed1 = 0L; - Long netUsed2 = 1L; - logger.info("Before test, the account balance is " + Long.toString(beforeBalance)); - - while (!(netUsed1.equals(netUsed2))) { - sendAccountInfo = PublicMethed.queryAccount(testKeyForSendCoin, blockingStubFull); - netUsed1 = sendAccountInfo.getFreeNetUsage(); - sendCoinTransaction = sendcoin(fromAddress, 1L, sendCoinAddress, - testKeyForSendCoin, blockingStubFull); - - sendAccountInfo = PublicMethed.queryAccount(testKeyForSendCoin, blockingStubFull); - netUsed2 = sendAccountInfo.getFreeNetUsage(); - - if (times++ < 1) { - PublicMethed.waitProduceNextBlock(blockingStubFull); - //PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull,blockingStubSolidity); - String txId = ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), sendCoinTransaction - .getRawData().toByteArray())); - logger.info(txId); - ByteString bsTxid = ByteString.copyFrom(ByteArray.fromHexString(txId)); - BytesMessage request = BytesMessage.newBuilder().setValue(bsTxid).build(); - TransactionInfo transactionInfo = blockingStubFull.getTransactionInfoById(request); - Optional getTransactionById = Optional.ofNullable(transactionInfo); - logger.info("solidity block num is " + Long.toString(getTransactionById - .get().getBlockNumber())); - Assert.assertTrue(getTransactionById.get().getBlockNumber() > 0); - } - - logger.info(Long.toString(netUsed1)); - logger.info(Long.toString(netUsed2)); - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - Assert.assertTrue(netUsed2 > 4500); - //Next time, use fee - sendCoinTransaction = sendcoin(fromAddress, 1L, sendCoinAddress, - testKeyForSendCoin, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull,blockingStubSolidity); - String txId = ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), sendCoinTransaction - .getRawData().toByteArray())); - logger.info(txId); - ByteString bsTxid = ByteString.copyFrom(ByteArray.fromHexString(txId)); - BytesMessage request = BytesMessage.newBuilder().setValue(bsTxid).build(); - TransactionInfo transactionInfo = blockingStubFull.getTransactionInfoById(request); - Optional getTransactionById = Optional.ofNullable(transactionInfo); - logger.info(getTransactionById.get().toString()); - logger.info("when use fee, the block num is " + Long.toString(getTransactionById - .get().getBlockNumber())); - Assert.assertTrue(getTransactionById.get().getFee() > 0); - Assert.assertTrue(getTransactionById.get().getBlockNumber() > 0); - } - - @Test(enabled = true) - public void test2CreateAccountUseFee() { - Account sendAccountInfo = PublicMethed.queryAccount(testKeyForSendCoin, blockingStubFull); - final Long beforeBalance = sendAccountInfo.getBalance(); - logger.info("before balance " + Long.toString(beforeBalance)); - Long times = 0L; - sendCoinTransaction = sendcoin(newAccountAddress, 1L, sendCoinAddress, - testKeyForSendCoin, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull,blockingStubSolidity); - String txId = ByteArray.toHexString(Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), sendCoinTransaction - .getRawData().toByteArray())); - logger.info(txId); - ByteString bsTxid = ByteString.copyFrom(ByteArray.fromHexString(txId)); - BytesMessage request = BytesMessage.newBuilder().setValue(bsTxid).build(); - TransactionInfo transactionInfo = blockingStubFull.getTransactionInfoById(request); - Optional getTransactionById = Optional.ofNullable(transactionInfo); - - logger.info("In create account case, the fee is " + getTransactionById.get().getFee()); - Assert.assertTrue(getTransactionById.get().getFee() == createUseFee); - - sendAccountInfo = PublicMethed.queryAccount(testKeyForSendCoin, blockingStubFull); - final Long afterBalance = sendAccountInfo.getBalance(); - logger.info("after balance " + Long.toString(afterBalance)); - Assert.assertTrue(afterBalance + 1L + createUseFee == beforeBalance); - } - - @Test(enabled = true) - public void test3InvalidGetTransactionById() { - String txId = ""; - ByteString bsTxid = ByteString.copyFrom(ByteArray.fromHexString(txId)); - BytesMessage request = BytesMessage.newBuilder().setValue(bsTxid).build(); - Transaction transaction = blockingStubFull.getTransactionById(request); - Optional getTransactionById = Optional.ofNullable(transaction); - Assert.assertTrue(getTransactionById.get().getRawData().getContractCount() == 0); - - txId = "1"; - bsTxid = ByteString.copyFrom(ByteArray.fromHexString(txId)); - request = BytesMessage.newBuilder().setValue(bsTxid).build(); - transaction = blockingStubFull.getTransactionById(request); - getTransactionById = Optional.ofNullable(transaction); - Assert.assertTrue(getTransactionById.get().getRawData().getContractCount() == 0); - } - - @Test(enabled = true) - public void test4NoBalanceCanSend() { - Long feeNum = 0L; - Account sendAccountInfo = PublicMethed.queryAccount(testKeyForSendCoin, blockingStubFull); - Long beforeBalance = sendAccountInfo.getBalance(); - logger.info("Before test, the account balance is " + Long.toString(beforeBalance)); - while (feeNum < 250) { - sendCoinTransaction = sendcoin(fromAddress, 10L, sendCoinAddress, - testKeyForSendCoin, blockingStubFull); - feeNum++; - } - Assert.assertTrue(PublicMethed.waitProduceNextBlock(blockingStubFull)); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelFull1 != null) { - channelFull1.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - /** - * constructor. - */ - - public Protocol.Transaction updateAccount(byte[] addressBytes, byte[] accountNameBytes, - String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - AccountUpdateContract.Builder builder = AccountUpdateContract.newBuilder(); - ByteString basAddreess = ByteString.copyFrom(addressBytes); - ByteString bsAccountName = ByteString.copyFrom(accountNameBytes); - - builder.setAccountName(bsAccountName); - builder.setOwnerAddress(basAddreess); - - AccountUpdateContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.updateAccount(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction ==null"); - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (!response.getResult()) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - } - return transaction; - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer004.java b/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer004.java deleted file mode 100644 index 8056f3e9941..00000000000 --- a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer004.java +++ /dev/null @@ -1,288 +0,0 @@ -package stest.tron.wallet.transfer; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletExtensionGrpc; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - - -@Slf4j -public class WalletTestTransfer004 { - - private static final long now = System.currentTimeMillis(); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletExtensionGrpc.WalletExtensionBlockingStub blockingStubExtension = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /* @Test(enabled = true) - public void testGetTransactionsByTimestamp() { - long start = now - 16400000; - long end = now; - GrpcAPI.TimeMessage.Builder timeMessage = GrpcAPI.TimeMessage.newBuilder(); - timeMessage.setBeginInMilliseconds(start); - timeMessage.setEndInMilliseconds(end); - TimePaginatedMessage.Builder timePageMessage = TimePaginatedMessage.newBuilder(); - timePageMessage.setTimeMessage(timeMessage); - timePageMessage.setOffset(0); - timePageMessage.setLimit(999); - TransactionList transactionList = blockingStubExtension - .getTransactionsByTimestamp(timePageMessage.build()); - Optional gettransactionbytimestamp = Optional - .ofNullable(transactionList); - - if (gettransactionbytimestamp.get().getTransactionCount() == 0) { - logger.info("Last one day there is no transfaction,please test for manual!!!"); - } - - Assert.assertTrue(gettransactionbytimestamp.isPresent()); - logger.info(Integer.toString(gettransactionbytimestamp.get().getTransactionCount())); - for (Integer j = 0; j < gettransactionbytimestamp.get().getTransactionCount(); j++) { - Assert.assertTrue(gettransactionbytimestamp.get().getTransaction(j).hasRawData()); - Assert.assertFalse(gettransactionbytimestamp.get().getTransaction(j) - .getRawData().getContractList().isEmpty()); - } - } - - @Test(enabled = true) - public void testExceptionTimeToGetGetTransactionsByTimestamp() { - //Start time is below zero. - long start = -10000; - long end = -1; - GrpcAPI.TimeMessage.Builder timeMessage = GrpcAPI.TimeMessage.newBuilder(); - timeMessage.setBeginInMilliseconds(start); - timeMessage.setEndInMilliseconds(end); - TimePaginatedMessage.Builder timePageMessage = TimePaginatedMessage.newBuilder(); - timePageMessage.setTimeMessage(timeMessage); - timePageMessage.setOffset(0); - timePageMessage.setLimit(999); - TransactionList transactionList = blockingStubExtension - .getTransactionsByTimestamp(timePageMessage.build()); - Optional gettransactionbytimestamp = Optional - .ofNullable(transactionList); - Assert.assertTrue(gettransactionbytimestamp.get().getTransactionCount() == 0); - - //Start time is equal with end time. - long now = System.currentTimeMillis(); - start = now; - end = now; - timeMessage = GrpcAPI.TimeMessage.newBuilder(); - timeMessage.setBeginInMilliseconds(start); - timeMessage.setEndInMilliseconds(end); - timePageMessage = TimePaginatedMessage.newBuilder(); - timePageMessage.setTimeMessage(timeMessage); - timePageMessage.setOffset(0); - timePageMessage.setLimit(999); - transactionList = blockingStubExtension - .getTransactionsByTimestamp(timePageMessage.build()); - gettransactionbytimestamp = Optional - .ofNullable(transactionList); - Assert.assertTrue(gettransactionbytimestamp.get().getTransactionCount() == 0); - - //No transeration occured. - now = System.currentTimeMillis(); - start = now; - end = now + 1; - timeMessage = GrpcAPI.TimeMessage.newBuilder(); - timeMessage.setBeginInMilliseconds(start); - timeMessage.setEndInMilliseconds(end); - timePageMessage = TimePaginatedMessage.newBuilder(); - timePageMessage.setTimeMessage(timeMessage); - timePageMessage.setOffset(0); - timePageMessage.setLimit(999); - transactionList = blockingStubExtension - .getTransactionsByTimestamp(timePageMessage.build()); - gettransactionbytimestamp = Optional - .ofNullable(transactionList); - Assert.assertTrue(gettransactionbytimestamp.get().getTransactionCount() == 0); - - - //Start time is late than currently time,no exception. - start = now + 1000000; - end = start + 1000000; - timeMessage = GrpcAPI.TimeMessage.newBuilder(); - timeMessage.setBeginInMilliseconds(start); - timeMessage.setEndInMilliseconds(end); - timePageMessage = TimePaginatedMessage.newBuilder(); - timePageMessage.setTimeMessage(timeMessage); - timePageMessage.setOffset(0); - timePageMessage.setLimit(999); - transactionList = blockingStubExtension - .getTransactionsByTimestamp(timePageMessage.build()); - gettransactionbytimestamp = Optional - .ofNullable(transactionList); - Assert.assertTrue(gettransactionbytimestamp.get().getTransactionCount() == 0); - - //Start time is late than the end time, no exception. - start = now; - end = now - 10000000; - timeMessage = GrpcAPI.TimeMessage.newBuilder(); - timeMessage.setBeginInMilliseconds(start); - timeMessage.setEndInMilliseconds(end); - timePageMessage = TimePaginatedMessage.newBuilder(); - timePageMessage.setTimeMessage(timeMessage); - timePageMessage.setOffset(0); - timePageMessage.setLimit(999); - transactionList = blockingStubExtension - .getTransactionsByTimestamp(timePageMessage.build()); - gettransactionbytimestamp = Optional - .ofNullable(transactionList); - Assert.assertTrue(gettransactionbytimestamp.get().getTransactionCount() == 0); - - //The offset is -1 - start = now - 10000000; - end = now; - timeMessage = GrpcAPI.TimeMessage.newBuilder(); - timeMessage.setBeginInMilliseconds(start); - timeMessage.setEndInMilliseconds(end); - timePageMessage = TimePaginatedMessage.newBuilder(); - timePageMessage.setTimeMessage(timeMessage); - timePageMessage.setOffset(-1); - timePageMessage.setLimit(999); - transactionList = blockingStubExtension - .getTransactionsByTimestamp(timePageMessage.build()); - gettransactionbytimestamp = Optional - .ofNullable(transactionList); - Assert.assertTrue(gettransactionbytimestamp.get().getTransactionCount() == 0); - - //The setLimit is -1 - start = now - 10000000; - end = now; - timeMessage = GrpcAPI.TimeMessage.newBuilder(); - timeMessage.setBeginInMilliseconds(start); - timeMessage.setEndInMilliseconds(end); - timePageMessage = TimePaginatedMessage.newBuilder(); - timePageMessage.setTimeMessage(timeMessage); - timePageMessage.setOffset(0); - timePageMessage.setLimit(-1); - transactionList = blockingStubExtension - .getTransactionsByTimestamp(timePageMessage.build()); - gettransactionbytimestamp = Optional - .ofNullable(transactionList); - Assert.assertTrue(gettransactionbytimestamp.get().getTransactionCount() == 0); - - - }*/ - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode).usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - blockingStubExtension = WalletExtensionGrpc.newBlockingStub(channelSolidity); - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer007.java b/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer007.java deleted file mode 100644 index 09c63c85fbf..00000000000 --- a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer007.java +++ /dev/null @@ -1,149 +0,0 @@ -package stest.tron.wallet.transfer; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.BytesMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.utils.PublicMethed; - -@Slf4j -public class WalletTestTransfer007 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - - - private ManagedChannel channelFull = null; - private ManagedChannel searchChannelFull = null; - - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidityInFullnode = null; - - private WalletGrpc.WalletBlockingStub searchBlockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String searchFullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - private ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] sendAccountAddress = ecKey1.getAddress(); - String sendAccountKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - private ManagedChannel channelSolidity = null; - private ManagedChannel channelSolidityInFullnode = null; - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - /* private String solidityInFullnode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(1);*/ - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext() - .build(); - searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - - /* channelSolidityInFullnode = ManagedChannelBuilder.forTarget(solidityInFullnode) - .usePlaintext() - .build(); - blockingStubSolidityInFullnode = WalletSolidityGrpc.newBlockingStub(channelSolidityInFullnode); - */ - } - - - @Test - public void testSendCoin() { - String transactionId = PublicMethed.sendcoinGetTransactionId(sendAccountAddress, 90000000000L, - fromAddress, testKey002, blockingStubFull); - Optional infoById = PublicMethed - .getTransactionById(transactionId, blockingStubFull); - Long timestamptis = PublicMethed.printTransactionRow(infoById.get().getRawData()); - Long timestamptispBlockOne = PublicMethed.getBlock(1, blockingStubFull).getBlockHeader() - .getRawData().getTimestamp(); - Assert.assertTrue(timestamptis >= timestamptispBlockOne); - } - - @Test - public void testSendCoin2() { - String transactionId = PublicMethed.sendcoinGetTransactionId(sendAccountAddress, 90000000000L, - fromAddress, testKey002, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Optional infoById = PublicMethed - .getTransactionById(transactionId, blockingStubFull); - Long timestamptis = PublicMethed.printTransactionRow(infoById.get().getRawData()); - Long timestampBlockOne = PublicMethed.getBlock(1, blockingStubFull).getBlockHeader() - .getRawData().getTimestamp(); - Assert.assertTrue(timestamptis >= timestampBlockOne); - PublicMethed.waitSolidityNodeSynFullNodeData(blockingStubFull, blockingStubSolidity); - - infoById = PublicMethed.getTransactionById(transactionId, blockingStubSolidity); - timestamptis = PublicMethed.printTransactionRow(infoById.get().getRawData()); - timestampBlockOne = PublicMethed.getBlock(1, blockingStubFull).getBlockHeader() - .getRawData().getTimestamp(); - Assert.assertTrue(timestamptis >= timestampBlockOne); - - ByteString bsTxid = ByteString.copyFrom(ByteArray.fromHexString(transactionId)); - BytesMessage request = BytesMessage.newBuilder().setValue(bsTxid).build(); - TransactionInfo transactionInfo; - - transactionInfo = blockingStubSolidity.getTransactionInfoById(request); - Assert.assertTrue(transactionInfo.getBlockTimeStamp() >= timestampBlockOne); - - transactionInfo = blockingStubFull.getTransactionInfoById(request); - Assert.assertTrue(transactionInfo.getBlockTimeStamp() >= timestampBlockOne); - - //transactionInfo = blockingStubSolidityInFullnode.getTransactionInfoById(request); - //Assert.assertTrue(transactionInfo.getBlockTimeStamp() >= timestampBlockOne); - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (searchChannelFull != null) { - searchChannelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - -} diff --git a/framework/src/test/java/stest/tron/wallet/updateCompatibility/MutisignOperationerGodicTest.java b/framework/src/test/java/stest/tron/wallet/updateCompatibility/MutisignOperationerGodicTest.java deleted file mode 100644 index 4909f84c4a6..00000000000 --- a/framework/src/test/java/stest/tron/wallet/updateCompatibility/MutisignOperationerGodicTest.java +++ /dev/null @@ -1,504 +0,0 @@ -package stest.tron.wallet.updateCompatibility; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.ExchangeList; -import org.tron.api.GrpcAPI.Note; -import org.tron.api.GrpcAPI.ProposalList; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; -import org.tron.core.Wallet; -import org.tron.core.config.args.Args; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.ChainParameters; -import org.tron.protos.Protocol.Exchange; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.PublicMethedForMutiSign; -import stest.tron.wallet.common.client.utils.ShieldAddressInfo; - -@Slf4j -public class MutisignOperationerGodicTest { - - final String updateName = Long.toString(System.currentTimeMillis()); - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String operations = Configuration.getByPath("testng.conf") - .getString("defaultParameter.operations"); - String[] permissionKeyString = new String[2]; - String[] ownerKeyString = new String[2]; - String accountPermissionJson = ""; - String description = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetDescription"); - String url = Configuration.getByPath("testng.conf") - .getString("defaultParameter.assetUrl"); - Optional shieldAddressInfo; - String shieldAddress; - List shieldOutList = new ArrayList<>(); - Account firstAccount; - ByteString assetAccountId1; - ByteString assetAccountId2; - Optional listExchange; - Optional exchangeIdInfo; - Integer exchangeId = 0; - Integer exchangeRate = 10; - Long firstTokenInitialBalance = 10000L; - Long secondTokenInitialBalance = firstTokenInitialBalance * exchangeRate; - ECKey ecKey1 = new ECKey(Utils.getRandom()); - byte[] manager1Address = ecKey1.getAddress(); - String manager1Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] manager2Address = ecKey2.getAddress(); - String manager2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); - ECKey ecKey3 = new ECKey(Utils.getRandom()); - byte[] mutisignAccountAddress = ecKey3.getAddress(); - String mutisignAccountKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); - ECKey ecKey4 = new ECKey(Utils.getRandom()); - byte[] newAddress = ecKey4.getAddress(); - String newKey = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private String foundationZenTokenKey = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenOwnerKey"); - byte[] foundationZenTokenAddress = PublicMethed.getFinalAddress(foundationZenTokenKey); - private String zenTokenId = Configuration.getByPath("testng.conf") - .getString("defaultParameter.zenTokenId"); - private byte[] tokenId = zenTokenId.getBytes(); - private Long zenTokenFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.zenTokenFee"); - private long multiSignFee = Configuration.getByPath("testng.conf") - .getLong("defaultParameter.multiSignFee"); - private Long costTokenAmount = 8 * zenTokenFee; - private Long sendTokenAmount = 3 * zenTokenFee; - - /** - * constructor. - */ - @BeforeSuite - public void beforeSuite() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - if (PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getCreateTime() == 0) { - PublicMethed.sendcoin(foundationZenTokenAddress, 20480000000000L, fromAddress, - testKey002, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - String name = "shieldToken"; - Long start = System.currentTimeMillis() + 20000; - Long end = System.currentTimeMillis() + 10000000000L; - Long totalSupply = 15000000000000001L; - String description = "This asset issue is use for exchange transaction stress"; - String url = "This asset issue is use for exchange transaction stress"; - PublicMethed.createAssetIssue(foundationZenTokenAddress, name, totalSupply, 1, 1, - start, end, 1, description, url, 1000L, 1000L, - 1L, 1L, foundationZenTokenKey, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Account getAssetIdFromThisAccount = - PublicMethed.queryAccount(foundationZenTokenAddress, blockingStubFull); - ByteString assetAccountId = getAssetIdFromThisAccount.getAssetIssuedID(); - logger.info("AssetId:" + assetAccountId.toString()); - } - } - - /** - * constructor. - */ - - @BeforeClass(enabled = true) - public void beforeClass() { - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - Assert.assertTrue(PublicMethed.sendcoin(mutisignAccountAddress, 1000_000_000_000L, fromAddress, - testKey002, blockingStubFull)); - //updatepermission权限,账户交易所需钱等前置条件写在这 - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - ownerKeyString[0] = manager1Key; - ownerKeyString[1] = manager2Key; - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - - logger.info(accountPermissionJson); - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, mutisignAccountAddress, mutisignAccountKey, - blockingStubFull, new String[]{mutisignAccountKey})); - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true) - public void test001MutiSignGodicAccountTypeTransaction() { - Assert.assertTrue( - PublicMethedForMutiSign.setAccountId1(("" + System.currentTimeMillis()).getBytes(), - mutisignAccountAddress, mutisignAccountKey, 2, blockingStubFull, - permissionKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.createAccountWhtiPermissionId( - mutisignAccountAddress, newAddress, mutisignAccountKey, blockingStubFull, - 2, permissionKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.sendcoinWithPermissionId( - newAddress, 100L, mutisignAccountAddress, 2, - mutisignAccountKey, blockingStubFull, permissionKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.freezeBalanceWithPermissionId( - mutisignAccountAddress, 1000000L, 0, 2, - mutisignAccountKey, blockingStubFull, permissionKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.freezeBalanceGetEnergyWithPermissionId( - mutisignAccountAddress, 1000000L, 0, 1, - mutisignAccountKey, blockingStubFull, 2, permissionKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.freezeBalanceForReceiverWithPermissionId( - mutisignAccountAddress, 1000000L, 0, 0, - ByteString.copyFrom(newAddress), - mutisignAccountKey, blockingStubFull, 2, permissionKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.unFreezeBalanceWithPermissionId( - mutisignAccountAddress, mutisignAccountKey, 0, null, - 2, blockingStubFull, permissionKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.unFreezeBalanceWithPermissionId( - mutisignAccountAddress, mutisignAccountKey, 0, newAddress, - 2, blockingStubFull, permissionKeyString)); - Assert.assertTrue(PublicMethedForMutiSign.updateAccountWithPermissionId( - mutisignAccountAddress, updateName.getBytes(), mutisignAccountKey, blockingStubFull, - 2, permissionKeyString)); - } - - @Test(enabled = true) - public void test002MutiSignGodicContractTypeTransaction() { - Long maxFeeLimit = 1000000000L; - //String contractName = "StorageAndCpu" + Integer.toString(randNum); - String filePath = "./src/test/resources/soliditycode/walletTestMutiSign004.sol"; - String contractName = "timeoutTest"; - HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); - - String code = retMap.get("byteCode").toString(); - String abi = retMap.get("abI").toString(); - byte[] contractAddress = PublicMethedForMutiSign.deployContractWithPermissionId( - contractName, abi, code, "", maxFeeLimit, - 0L, 100, maxFeeLimit, "0", 0L, null, - mutisignAccountKey, mutisignAccountAddress, blockingStubFull, permissionKeyString, 2); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); - Assert.assertTrue(smartContract.getAbi().toString() != null); - String txid; - String initParmes = "\"" + "930" + "\""; - txid = PublicMethedForMutiSign.triggerContractWithPermissionId(contractAddress, - "testUseCpu(uint256)", initParmes, false, - 0, maxFeeLimit, "0", 0L, mutisignAccountAddress, - mutisignAccountKey, blockingStubFull, permissionKeyString, 2); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue( - PublicMethedForMutiSign.updateSettingWithPermissionId( - contractAddress, 50, mutisignAccountKey, - mutisignAccountAddress, 2, blockingStubFull, permissionKeyString)); - Assert.assertTrue( - PublicMethedForMutiSign.updateEnergyLimitWithPermissionId( - contractAddress, 50, mutisignAccountKey, - mutisignAccountAddress, 2, blockingStubFull, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue(PublicMethedForMutiSign - .clearContractAbi(contractAddress, mutisignAccountAddress, mutisignAccountKey, - blockingStubFull, 2, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - } - - @Test(enabled = true) - public void test003MutiSignGodicTokenTypeTransaction() { - - long now = System.currentTimeMillis(); - String name = "MutiSign001_" + Long.toString(now); - long totalSupply = now; - Long start = System.currentTimeMillis() + 5000; - Long end = System.currentTimeMillis() + 1000000000; - logger.info("try create asset issue"); - - Assert.assertTrue(PublicMethedForMutiSign - .createAssetIssueWithpermissionId(mutisignAccountAddress, name, totalSupply, 1, - 1, start, end, 1, description, url, 2000L, 2000L, - 1L, 1L, mutisignAccountKey, blockingStubFull, 2, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - //Assert.assertTrue(PublicMethedForMutiSign.unFreezeAsset(mutisignAccountAddress, - // mutisignAccountKey,2,ownerKeyString,blockingStubFull)); - - Account getAssetIdFromOwnerAccount; - getAssetIdFromOwnerAccount = PublicMethed.queryAccount( - mutisignAccountAddress, blockingStubFull); - assetAccountId1 = getAssetIdFromOwnerAccount.getAssetIssuedID(); - - Assert.assertTrue(PublicMethedForMutiSign.transferAssetWithpermissionId(manager1Address, - assetAccountId1.toByteArray(), 10, mutisignAccountAddress, - mutisignAccountKey, blockingStubFull, 2, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Assert.assertTrue(PublicMethedForMutiSign - .updateAssetWithPermissionId(mutisignAccountAddress, description.getBytes(), url.getBytes(), - 100L, 100L, mutisignAccountKey, - 2, blockingStubFull, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - - } - - @Test(enabled = true) - public void test004MutiSignGodicExchangeTypeTransaction() { - - ECKey ecKey22 = new ECKey(Utils.getRandom()); - byte[] secondExchange001Address = ecKey22.getAddress(); - String secondExchange001Key = ByteArray.toHexString(ecKey22.getPrivKeyBytes()); - Long secondTransferAssetToFirstAccountNum = 100000000L; - - long now = System.currentTimeMillis(); - String name2 = "exchange001_2_" + Long.toString(now); - String name1 = "exchange001_1_" + Long.toString(now); - final long totalSupply = 1000000001L; - - org.junit.Assert - .assertTrue(PublicMethed.sendcoin(secondExchange001Address, 10240000000L, fromAddress, - testKey002, blockingStubFull)); - org.junit.Assert.assertTrue(PublicMethed - .freezeBalanceForReceiver(fromAddress, 100000000000L, 0, 0, - ByteString.copyFrom(secondExchange001Address), - testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - Long start = System.currentTimeMillis() + 5000L; - Long end = System.currentTimeMillis() + 5000000L; - org.junit.Assert - .assertTrue(PublicMethed.createAssetIssue(secondExchange001Address, name2, totalSupply, 1, - 1, start, end, 1, description, url, 10000L, 10000L, - 1L, 1L, secondExchange001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - listExchange = PublicMethed.getExchangeList(blockingStubFull); - exchangeId = listExchange.get().getExchangesCount(); - - Account getAssetIdFromThisAccount; - getAssetIdFromThisAccount = PublicMethed.queryAccount(mutisignAccountAddress, blockingStubFull); - assetAccountId1 = getAssetIdFromThisAccount.getAssetIssuedID(); - - getAssetIdFromThisAccount = PublicMethed - .queryAccount(secondExchange001Address, blockingStubFull); - assetAccountId2 = getAssetIdFromThisAccount.getAssetIssuedID(); - - firstAccount = PublicMethed.queryAccount(mutisignAccountAddress, blockingStubFull); - org.junit.Assert.assertTrue(PublicMethed.transferAsset( - mutisignAccountAddress, assetAccountId2.toByteArray(), - secondTransferAssetToFirstAccountNum, secondExchange001Address, - secondExchange001Key, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - org.junit.Assert.assertTrue( - PublicMethedForMutiSign.exchangeCreate1( - assetAccountId1.toByteArray(), firstTokenInitialBalance, - assetAccountId2.toByteArray(), secondTokenInitialBalance, mutisignAccountAddress, - mutisignAccountKey, blockingStubFull, 2, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - listExchange = PublicMethed.getExchangeList(blockingStubFull); - exchangeId = listExchange.get().getExchangesCount(); - - org.junit.Assert.assertTrue( - PublicMethedForMutiSign.injectExchange1( - exchangeId, assetAccountId1.toByteArray(), 100, - mutisignAccountAddress, mutisignAccountKey, blockingStubFull, 2, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - org.junit.Assert.assertTrue( - PublicMethedForMutiSign.exchangeWithdraw1( - exchangeId, assetAccountId1.toByteArray(), 200, - mutisignAccountAddress, mutisignAccountKey, blockingStubFull, 2, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - firstAccount = PublicMethed.queryAccount(mutisignAccountAddress, blockingStubFull); - - org.junit.Assert.assertTrue( - PublicMethedForMutiSign - .exchangeTransaction1(exchangeId, assetAccountId1.toByteArray(), 50, 1, - mutisignAccountAddress, mutisignAccountKey, blockingStubFull, - 2, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - firstAccount = PublicMethed.queryAccount(mutisignAccountAddress, blockingStubFull); - - Assert.assertTrue(PublicMethedForMutiSign.participateAssetIssueWithPermissionId( - secondExchange001Address, - assetAccountId2.toByteArray(), 1, mutisignAccountAddress, mutisignAccountKey, 2, - blockingStubFull, ownerKeyString)); - - } - - @Test(enabled = true) - public void test005MutiSignGodicShieldTransaction() { - - Assert.assertTrue(PublicMethed.transferAsset(mutisignAccountAddress, tokenId, - costTokenAmount, foundationZenTokenAddress, foundationZenTokenKey, blockingStubFull)); - Args.setFullNodeAllowShieldedTransaction(true); - shieldAddressInfo = PublicMethed.generateShieldAddress(); - shieldAddress = shieldAddressInfo.get().getAddress(); - logger.info("shieldAddress:" + shieldAddress); - final Long beforeAssetBalance = PublicMethed.getAssetIssueValue(mutisignAccountAddress, - PublicMethed.queryAccount(foundationZenTokenKey, blockingStubFull).getAssetIssuedID(), - blockingStubFull); - final Long beforeBalance = PublicMethed - .queryAccount(mutisignAccountAddress, blockingStubFull).getBalance(); - final Long beforeNetUsed = PublicMethed - .getAccountResource(mutisignAccountAddress, blockingStubFull).getFreeNetUsed(); - - String memo = "aaaaaaa"; - - shieldOutList = PublicMethed.addShieldOutputList(shieldOutList, shieldAddress, - "" + (sendTokenAmount - zenTokenFee), memo); - - Assert.assertTrue(PublicMethedForMutiSign.sendShieldCoin( - mutisignAccountAddress, sendTokenAmount, - null, null, - shieldOutList, - null, 0, - mutisignAccountKey, blockingStubFull, 2, permissionKeyString)); - - PublicMethed.waitProduceNextBlock(blockingStubFull); - } - - @Test(enabled = true) - public void test006MutiSignGodicWitnessTransaction() { - permissionKeyString[0] = manager1Key; - permissionKeyString[1] = manager2Key; - ownerKeyString[0] = manager1Key; - ownerKeyString[1] = manager2Key; - PublicMethed.printAddress(newKey); - accountPermissionJson = - "{\"owner_permission\":{\"type\":0,\"permission_name\":\"owner\",\"threshold\":2,\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) - + "\",\"weight\":1}]}," - + "\"active_permissions\":[{\"type\":2,\"permission_name\":\"active0\",\"threshold\":2," - + "\"operations\":\"" + operations + "\"," - + "\"keys\":[" - + "{\"address\":\"" + PublicMethed.getAddressString(manager1Key) + "\",\"weight\":1}," - + "{\"address\":\"" + PublicMethed.getAddressString(manager2Key) + "\",\"weight\":1}" - + "]}]}"; - - Assert.assertTrue(PublicMethed.sendcoin(newAddress, 1000000_000_000L, fromAddress, - testKey002, blockingStubFull)); - logger.info(accountPermissionJson); - Assert.assertTrue(PublicMethedForMutiSign - .accountPermissionUpdate(accountPermissionJson, newAddress, newKey, - blockingStubFull, new String[]{newKey})); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - long now = System.currentTimeMillis(); - String url = "MutiSign001_" + Long.toString(now) + ".com"; - Assert.assertTrue(PublicMethedForMutiSign.createWitness(url, newAddress, - newKey, 2, permissionKeyString, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - Assert - .assertTrue(PublicMethedForMutiSign.updateWitness2(newAddress, "newWitness.com".getBytes(), - newKey, 2, permissionKeyString, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - String voteStr = Base58.encode58Check(newAddress); - HashMap smallVoteMap = new HashMap(); - smallVoteMap.put(voteStr, "1"); - Assert.assertTrue(PublicMethedForMutiSign.voteWitnessWithPermissionId( - smallVoteMap, mutisignAccountAddress, mutisignAccountKey, blockingStubFull, - 2, permissionKeyString)); - - - } - - @Test(enabled = true) - public void test007MutiSignGodicProposalTypeTransaction() { - - PublicMethed.waitProduceNextBlock(blockingStubFull); - HashMap proposalMap = new HashMap(); - proposalMap.put(0L, 81000L); - Assert.assertTrue( - PublicMethedForMutiSign.createProposalWithPermissionId(newAddress, newKey, - proposalMap, 2, blockingStubFull, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Get proposal list - ProposalList proposalList = blockingStubFull.listProposals(EmptyMessage.newBuilder().build()); - Optional listProposals = Optional.ofNullable(proposalList); - final Integer proposalId = listProposals.get().getProposalsCount(); - logger.info(Integer.toString(proposalId)); - - Assert.assertTrue(PublicMethedForMutiSign.approveProposalWithPermission( - newAddress, newKey, proposalId, - true, 2, blockingStubFull, permissionKeyString)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Delete proposal list after approve - Assert.assertTrue(PublicMethedForMutiSign.deleteProposalWithPermissionId( - newAddress, newKey, proposalId, 2, blockingStubFull, permissionKeyString)); - } - - @Test(enabled = true) - public void test008MutiSignGodicWithdrawBanlanceTransaction() { - long MaintenanceTimeInterval = -1L; - ChainParameters chainParameters = blockingStubFull - .getChainParameters(EmptyMessage.newBuilder().build()); - Optional getChainParameters = Optional.ofNullable(chainParameters); - logger.info(Long.toString(getChainParameters.get().getChainParameterCount())); - for (Integer i = 0; i < getChainParameters.get().getChainParameterCount(); i++) { - logger.info("Index is:" + i); - logger.info(getChainParameters.get().getChainParameter(i).getKey()); - logger.info(Long.toString(getChainParameters.get().getChainParameter(i).getValue())); - if (getChainParameters.get().getChainParameter(i).getKey() - .equals("getMaintenanceTimeInterval")) { - MaintenanceTimeInterval = getChainParameters.get().getChainParameter(i).getValue(); - break; - } - } - - try { - Thread.sleep(MaintenanceTimeInterval); - } catch (InterruptedException e) { - e.printStackTrace(); - } - Assert.assertTrue(PublicMethedForMutiSign.withdrawBalance(newAddress, newKey, - 2, permissionKeyString, blockingStubFull)); - } - - - /** - * constructor. - */ - @AfterClass(enabled = true) - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness001.java b/framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness001.java deleted file mode 100644 index 550f31235db..00000000000 --- a/framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness001.java +++ /dev/null @@ -1,399 +0,0 @@ -package stest.tron.wallet.witness; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.WalletGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; -import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.contract.BalanceContract.FreezeBalanceContract; -import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; -import org.tron.protos.contract.WitnessContract.VoteWitnessContract; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; -import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -@Slf4j -public class WalletTestWitness001 { - - private final String testKey002 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key1"); - private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); - private final String testKey003 = Configuration.getByPath("testng.conf") - .getString("foundationAccount.key2"); - private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); - private final String witnessKey001 = Configuration.getByPath("testng.conf") - .getString("witness.key1"); - private final byte[] witnessAddress = PublicMethed.getFinalAddress(witnessKey001); - - - private ManagedChannel channelFull = null; - private ManagedChannel searchChannelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletGrpc.WalletBlockingStub searchBlockingStubFull = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String searchFullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(1); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - - WalletClient.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - logger.info("Pre fix byte ===== " + WalletClient.getAddressPreFixByte()); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - searchChannelFull = ManagedChannelBuilder.forTarget(searchFullnode) - .usePlaintext() - .build(); - searchBlockingStubFull = WalletGrpc.newBlockingStub(searchChannelFull); - } - - @Test(enabled = true) - public void testVoteWitness() { - String voteStr = Base58.encode58Check(witnessAddress); - HashMap smallVoteMap = new HashMap(); - smallVoteMap.put(voteStr, "1"); - HashMap wrongVoteMap = new HashMap(); - wrongVoteMap.put(voteStr, "-1"); - HashMap zeroVoteMap = new HashMap(); - zeroVoteMap.put(voteStr, "0"); - - HashMap veryLargeMap = new HashMap(); - veryLargeMap.put(voteStr, "1000000000"); - HashMap wrongDropMap = new HashMap(); - wrongDropMap.put(voteStr, "10000000000000000"); - - //Vote failed due to no freeze balance. - //Assert.assertFalse(VoteWitness(smallVoteMap, NO_FROZEN_ADDRESS, no_frozen_balance_testKey)); - - //Freeze balance to get vote ability. - Assert.assertTrue(PublicMethed.freezeBalanceGetTronPower(fromAddress, 1200000L, 3L, - 2,null,testKey002, blockingStubFull)); - PublicMethed.waitProduceNextBlock(blockingStubFull); - //Vote failed when the vote is large than the freeze balance. - Assert.assertFalse(voteWitness(veryLargeMap, fromAddress, testKey002)); - //Vote failed due to 0 vote. - Assert.assertFalse(voteWitness(zeroVoteMap, fromAddress, testKey002)); - //Vote failed duo to -1 vote. - Assert.assertFalse(voteWitness(wrongVoteMap, fromAddress, testKey002)); - //Vote is so large, vote failed. - Assert.assertFalse(voteWitness(wrongDropMap, fromAddress, testKey002)); - - //Vote success - Assert.assertTrue(voteWitness(smallVoteMap, fromAddress, testKey002)); - - - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (searchChannelFull != null) { - searchChannelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Boolean voteWitness(HashMap witness, byte[] addRess, String priKey) { - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account beforeVote = queryAccount(ecKey, blockingStubFull); - Long beforeVoteNum = 0L; - if (beforeVote.getVotesCount() != 0) { - beforeVoteNum = beforeVote.getVotes(0).getVoteCount(); - } - - VoteWitnessContract.Builder builder = VoteWitnessContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(addRess)); - for (String addressBase58 : witness.keySet()) { - String value = witness.get(addressBase58); - final long count = Long.parseLong(value); - VoteWitnessContract.Vote.Builder voteBuilder = VoteWitnessContract.Vote - .newBuilder(); - byte[] address = WalletClient.decodeFromBase58Check(addressBase58); - logger.info("address ====== " + ByteArray.toHexString(address)); - if (address == null) { - continue; - } - voteBuilder.setVoteAddress(ByteString.copyFrom(address)); - voteBuilder.setVoteCount(count); - builder.addVotes(voteBuilder.build()); - } - - VoteWitnessContract contract = builder.build(); - - Transaction transaction = blockingStubFull.voteWitnessAccount(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - - if (!response.getResult()) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - Account afterVote = queryAccount(ecKey, searchBlockingStubFull); - //Long afterVoteNum = afterVote.getVotes(0).getVoteCount(); - for (String key : witness.keySet()) { - for (int j = 0; j < afterVote.getVotesCount(); j++) { - logger.info(Long.toString(Long.parseLong(witness.get(key)))); - logger.info(key); - if (key.equals("TB4B1RMhoPeivkj4Hebm6tttHjRY9yQFes")) { - logger.info("catch it"); - logger.info(Long.toString(afterVote.getVotes(j).getVoteCount())); - logger.info(Long.toString(Long.parseLong(witness.get(key)))); - Assert - .assertTrue(afterVote.getVotes(j).getVoteCount() == Long.parseLong(witness.get(key))); - } - - } - } - return true; - } - - /** - * constructor. - */ - - public Boolean freezeBalance(byte[] addRess, long freezeBalance, long freezeDuration, - String priKey) { - byte[] address = addRess; - long frozenBalance = freezeBalance; - long frozenDuration = freezeDuration; - - //String priKey = testKey002; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account beforeFronzen = queryAccount(ecKey, blockingStubFull); - - Long beforeFrozenBalance = 0L; - //Long beforeBandwidth = beforeFronzen.getBandwidth(); - if (beforeFronzen.getFrozenCount() != 0) { - beforeFrozenBalance = beforeFronzen.getFrozen(0).getFrozenBalance(); - //beforeBandwidth = beforeFronzen.getBandwidth(); - //logger.info(Long.toString(beforeFronzen.getBandwidth())); - logger.info(Long.toString(beforeFronzen.getFrozen(0).getFrozenBalance())); - } - - FreezeBalanceContract.Builder builder = FreezeBalanceContract.newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess).setFrozenBalance(frozenBalance) - .setFrozenDuration(frozenDuration); - - FreezeBalanceContract contract = builder.build(); - - Transaction transaction = blockingStubFull.freezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - - if (!response.getResult()) { - return false; - } - - Block currentBlock = blockingStubFull.getNowBlock(GrpcAPI.EmptyMessage.newBuilder().build()); - Block searchCurrentBlock = searchBlockingStubFull.getNowBlock(GrpcAPI - .EmptyMessage.newBuilder().build()); - Integer wait = 0; - while (searchCurrentBlock.getBlockHeader().getRawData().getNumber() - < currentBlock.getBlockHeader().getRawData().getNumber() + 1 && wait < 30) { - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - logger.info("Another fullnode didn't syn the first fullnode data"); - searchCurrentBlock = searchBlockingStubFull.getNowBlock(GrpcAPI - .EmptyMessage.newBuilder().build()); - wait++; - if (wait == 9) { - logger.info("Didn't syn,skip to next case."); - } - } - - Account afterFronzen = queryAccount(ecKey, searchBlockingStubFull); - Long afterFrozenBalance = afterFronzen.getFrozen(0).getFrozenBalance(); - //Long afterBandwidth = afterFronzen.getBandwidth(); - //logger.info(Long.toString(afterFronzen.getBandwidth())); - //logger.info(Long.toString(afterFronzen.getFrozen(0).getFrozenBalance())); - //logger.info(Integer.toString(search.getFrozenCount())); - logger.info( - "afterfrozenbalance =" + Long.toString(afterFrozenBalance) + "beforefrozenbalance = " - + beforeFrozenBalance + "freezebalance = " + Long.toString(freezeBalance)); - //logger.info("afterbandwidth = " + Long.toString(afterBandwidth) + " beforebandwidth = - // " + Long.toString(beforeBandwidth)); - //if ((afterFrozenBalance - beforeFrozenBalance != freezeBalance) || - // (freezeBalance * frozen_duration -(afterBandwidth - beforeBandwidth) !=0)){ - // logger.info("After 20 second, two node still not synchronous"); - // } - Assert.assertTrue(afterFrozenBalance - beforeFrozenBalance == freezeBalance); - //Assert.assertTrue(freezeBalance * frozen_duration - (afterBandwidth - - // beforeBandwidth) <= 1000000); - return true; - - - } - - /** - * constructor. - */ - - public boolean unFreezeBalance(byte[] addRess, String priKey) { - byte[] address = addRess; - - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account search = queryAccount(ecKey, blockingStubFull); - - UnfreezeBalanceContract.Builder builder = UnfreezeBalanceContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - - builder.setOwnerAddress(byteAddreess); - - UnfreezeBalanceContract contract = builder.build(); - - Transaction transaction = blockingStubFull.unfreezeBalance(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); - Return response = blockingStubFull.broadcastTransaction(transaction); - return response.getResult(); - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } -} - - diff --git a/framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness002.java b/framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness002.java deleted file mode 100644 index fd71379b2e5..00000000000 --- a/framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness002.java +++ /dev/null @@ -1,210 +0,0 @@ -package stest.tron.wallet.witness; - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.util.encoders.Hex; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.core.Wallet; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Transaction; -import stest.tron.wallet.common.client.Configuration; -import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.TransactionUtils; - -//import stest.tron.wallet.common.client.WitnessComparator; - -//import stest.tron.wallet.common.client.WitnessComparator; - -@Slf4j -public class WalletTestWitness002 { - - - private ManagedChannel channelFull = null; - private ManagedChannel channelSolidity = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); - private String soliditynode = Configuration.getByPath("testng.conf") - .getStringList("solidityNode.ip.list").get(0); - - public static String loadPubKey() { - char[] buf = new char[0x100]; - return String.valueOf(buf, 32, 130); - } - - - - /** - * constructor. - */ - - @BeforeClass - public void beforeClass() { - WalletClient.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - channelFull = ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - - channelSolidity = ManagedChannelBuilder.forTarget(soliditynode) - .usePlaintext() - .build(); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); - } - - @Test(enabled = true) - public void testQueryAllWitness() { - GrpcAPI.WitnessList witnesslist = blockingStubFull - .listWitnesses(GrpcAPI.EmptyMessage.newBuilder().build()); - Optional result = Optional.ofNullable(witnesslist); - if (result.isPresent()) { - GrpcAPI.WitnessList witnessList = result.get(); - List list = witnessList.getWitnessesList(); - List newList = new ArrayList(); - newList.addAll(list); - newList.sort(new WitnessComparator()); - GrpcAPI.WitnessList.Builder builder = GrpcAPI.WitnessList.newBuilder(); - newList.forEach(witness -> builder.addWitnesses(witness)); - result = Optional.of(builder.build()); - } - logger.info(Integer.toString(result.get().getWitnessesCount())); - Assert.assertTrue(result.get().getWitnessesCount() > 0); - for (int j = 0; j < result.get().getWitnessesCount(); j++) { - Assert.assertFalse(result.get().getWitnesses(j).getAddress().isEmpty()); - Assert.assertFalse(result.get().getWitnesses(j).getUrl().isEmpty()); - //Assert.assertTrue(result.get().getWitnesses(j).getLatestSlotNum() > 0); - result.get().getWitnesses(j).getUrlBytes(); - result.get().getWitnesses(j).getLatestBlockNum(); - result.get().getWitnesses(j).getLatestSlotNum(); - result.get().getWitnesses(j).getTotalMissed(); - result.get().getWitnesses(j).getTotalProduced(); - } - - //Improve coverage. - witnesslist.equals(result.get()); - witnesslist.hashCode(); - witnesslist.getSerializedSize(); - witnesslist.equals(null); - } - - @Test(enabled = true) - public void testSolidityQueryAllWitness() { - GrpcAPI.WitnessList solidityWitnessList = blockingStubSolidity - .listWitnesses(GrpcAPI.EmptyMessage.newBuilder().build()); - Optional result = Optional.ofNullable(solidityWitnessList); - if (result.isPresent()) { - GrpcAPI.WitnessList witnessList = result.get(); - List list = witnessList.getWitnessesList(); - List newList = new ArrayList(); - newList.addAll(list); - newList.sort(new WitnessComparator()); - GrpcAPI.WitnessList.Builder builder = GrpcAPI.WitnessList.newBuilder(); - newList.forEach(witness -> builder.addWitnesses(witness)); - result = Optional.of(builder.build()); - } - logger.info(Integer.toString(result.get().getWitnessesCount())); - Assert.assertTrue(result.get().getWitnessesCount() > 0); - for (int j = 0; j < result.get().getWitnessesCount(); j++) { - Assert.assertFalse(result.get().getWitnesses(j).getAddress().isEmpty()); - Assert.assertFalse(result.get().getWitnesses(j).getUrl().isEmpty()); - } - } - - /** - * constructor. - */ - - @AfterClass - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - if (channelSolidity != null) { - channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - } - - /** - * constructor. - */ - - public Account queryAccount(ECKey ecKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public byte[] getAddress(ECKey ecKey) { - return ecKey.getAddress(); - } - - /** - * constructor. - */ - - public Account grpcQueryAccount(byte[] address, WalletGrpc.WalletBlockingStub blockingStubFull) { - ByteString addressBs = ByteString.copyFrom(address); - Account request = Account.newBuilder().setAddress(addressBs).build(); - return blockingStubFull.getAccount(request); - } - - /** - * constructor. - */ - - public Block getBlock(long blockNum, WalletGrpc.WalletBlockingStub blockingStubFull) { - NumberMessage.Builder builder = NumberMessage.newBuilder(); - builder.setNum(blockNum); - return blockingStubFull.getBlockByNum(builder.build()); - - } - - private Transaction signTransaction(ECKey ecKey, Transaction transaction) { - if (ecKey == null || ecKey.getPrivKey() == null) { - logger.warn("Warning: Can't sign,there is no private key !!"); - return null; - } - transaction = TransactionUtils.setTimestamp(transaction); - return TransactionUtils.sign(transaction, ecKey); - } - - class WitnessComparator implements Comparator { - - public int compare(Object o1, Object o2) { - return Long - .compare(((Protocol.Witness) o2).getVoteCount(), ((Protocol.Witness) o1).getVoteCount()); - } - } -} - - From 1e9c80eb4fdece534b4721776f909c56940688d3 Mon Sep 17 00:00:00 2001 From: forfreeday Date: Thu, 25 May 2023 13:57:56 +0800 Subject: [PATCH 0782/1197] feat(test): checkstyle --- .../src/test/java/org/tron/common/utils/PublicMethod.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/test/java/org/tron/common/utils/PublicMethod.java b/framework/src/test/java/org/tron/common/utils/PublicMethod.java index 1088ff25ba2..018db4b5354 100644 --- a/framework/src/test/java/org/tron/common/utils/PublicMethod.java +++ b/framework/src/test/java/org/tron/common/utils/PublicMethod.java @@ -138,7 +138,7 @@ public static SmartContractOuterClass.SmartContract.ABI jsonStr2Abi(String jsonS /** constructor. */ public static SmartContractOuterClass.SmartContract.ABI.Entry.EntryType - getEntryType(String type) { + getEntryType(String type) { switch (type) { case "constructor": return SmartContractOuterClass.SmartContract.ABI.Entry.EntryType.Constructor; @@ -158,7 +158,7 @@ public static SmartContractOuterClass.SmartContract.ABI jsonStr2Abi(String jsonS /** constructor. */ public static SmartContractOuterClass.SmartContract.ABI.Entry.StateMutabilityType - getStateMutability(String stateMutability) { + getStateMutability(String stateMutability) { switch (stateMutability) { case "pure": return SmartContractOuterClass.SmartContract.ABI.Entry.StateMutabilityType.Pure; From a115aa8d5226cf0b4c360d84130976471c6d6cd7 Mon Sep 17 00:00:00 2001 From: forfreeday Date: Thu, 11 May 2023 16:22:22 +0800 Subject: [PATCH 0783/1197] feat(test): Optimize test cases 1. remove `stest` package 2. optimize test cast code --- framework/build.gradle | 29 ------ .../src/main/resources/config-localtest.conf | 2 +- .../tron/common/crypto/BouncyCastleTest.java | 3 + .../org/tron/common/crypto/ECKeyTest.java | 3 + .../org/tron/common/crypto/SM2KeyTest.java | 3 + .../common/crypto/SignatureInterfaceTest.java | 32 +++---- .../org/tron/common/runtime/TvmTestUtils.java | 1 - .../tron/common/runtime/vm/Create2Test.java | 1 + .../leveldb/LevelDbDataSourceImplTest.java | 15 +-- .../leveldb/RocksDbDataSourceImplTest.java | 13 +-- .../org/tron/common/utils/PublicMethod.java | 95 +++++++++++++++---- .../tron/core/ShieldedTRC20BuilderTest.java | 5 +- .../ShieldedTransferActuatorTest.java | 13 +-- .../tron/core/capsule/BlockCapsuleTest.java | 15 ++- .../org/tron/core/config/args/ArgsTest.java | 22 ++++- .../core/config/args/LocalWitnessTest.java | 10 +- .../java/org/tron/core/db/ManagerTest.java | 23 +++++ .../tron/core/db/TransactionExpireTest.java | 19 ++++ .../tron/core/db/TransactionStoreTest.java | 7 +- .../prometheus/PrometheusApiServiceTest.java | 18 +++- .../services/stop/ConditionallyStopTest.java | 22 ++++- .../test/resources/config-test-mainnet.conf | 2 +- .../resources/config-test-storagetest.conf | 4 +- framework/src/test/resources/config-test.conf | 2 +- work.sh | 4 +- 25 files changed, 250 insertions(+), 113 deletions(-) diff --git a/framework/build.gradle b/framework/build.gradle index 299c5fe611a..3f2d268d835 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -159,35 +159,6 @@ test { } } -task stest(type: Test) { - - useTestNG { - suites(file('src/test/resources/testng.xml')) - parallel 'tests' - threadCount 4 - - } - - testLogging { - exceptionFormat = 'full' - showStackTraces = "true" - } - - jacoco { - destinationFile = file("$buildDir/jacoco/jacocoTest.exec") - classDumpDir = file("$buildDir/jacoco/classpathdumps") - } -} - -task dailyBuild(type: Test) { - useTestNG { - suites(file('src/test/resources/daily-build.xml')) - parallel 'tests' - threadCount 1 - } -} - - jacocoTestReport { reports { xml.enabled true diff --git a/framework/src/main/resources/config-localtest.conf b/framework/src/main/resources/config-localtest.conf index 45254446001..1087f0d3dcf 100644 --- a/framework/src/main/resources/config-localtest.conf +++ b/framework/src/main/resources/config-localtest.conf @@ -256,7 +256,7 @@ genesis.block = { //localWitnessAccountAddress = TN3zfjYUmMFK3ZsHSsrdJoNRtGkQmZLBLz localwitness = [ - f4df789d3210ac881cb900464dd30409453044d2777060a0c391cbdf4c6a4f57 + ] diff --git a/framework/src/test/java/org/tron/common/crypto/BouncyCastleTest.java b/framework/src/test/java/org/tron/common/crypto/BouncyCastleTest.java index ebb12f25284..02fc962fa58 100644 --- a/framework/src/test/java/org/tron/common/crypto/BouncyCastleTest.java +++ b/framework/src/test/java/org/tron/common/crypto/BouncyCastleTest.java @@ -12,6 +12,9 @@ import org.tron.common.crypto.sm2.SM2; import org.tron.common.utils.Sha256Hash; +/** + * The reason the test case uses the private key plaintext is to ensure that, after the ECkey tool or algorithm is upgraded, the upgraded differences can be verified. + */ public class BouncyCastleTest { private String privString = "c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4"; diff --git a/framework/src/test/java/org/tron/common/crypto/ECKeyTest.java b/framework/src/test/java/org/tron/common/crypto/ECKeyTest.java index facdcaccccc..52862001bea 100644 --- a/framework/src/test/java/org/tron/common/crypto/ECKeyTest.java +++ b/framework/src/test/java/org/tron/common/crypto/ECKeyTest.java @@ -19,6 +19,9 @@ import org.tron.common.crypto.ECKey.ECDSASignature; import org.tron.core.Wallet; +/** + * The reason the test case uses the private key plaintext is to ensure that, after the ECkey tool or algorithm is upgraded, the upgraded differences can be verified. + */ @Slf4j public class ECKeyTest { diff --git a/framework/src/test/java/org/tron/common/crypto/SM2KeyTest.java b/framework/src/test/java/org/tron/common/crypto/SM2KeyTest.java index 80d355eb2cf..bd5bbae8525 100644 --- a/framework/src/test/java/org/tron/common/crypto/SM2KeyTest.java +++ b/framework/src/test/java/org/tron/common/crypto/SM2KeyTest.java @@ -19,6 +19,9 @@ import org.tron.common.crypto.sm2.SM2Signer; import org.tron.core.Wallet; +/** + * The reason the test case uses the private key plaintext is to ensure that, after the ECkey tool or algorithm is upgraded, the upgraded differences can be verified. + */ @Slf4j public class SM2KeyTest { diff --git a/framework/src/test/java/org/tron/common/crypto/SignatureInterfaceTest.java b/framework/src/test/java/org/tron/common/crypto/SignatureInterfaceTest.java index bed38852ef3..b413127db53 100644 --- a/framework/src/test/java/org/tron/common/crypto/SignatureInterfaceTest.java +++ b/framework/src/test/java/org/tron/common/crypto/SignatureInterfaceTest.java @@ -8,35 +8,26 @@ import org.bouncycastle.util.encoders.Hex; import org.junit.Test; import org.tron.common.crypto.sm2.SM2; +import org.tron.common.utils.PublicMethod; @Slf4j public class SignatureInterfaceTest { - private String SM2_privString = "128B2FA8BD433C6C068C8D803DFF79792A519A5517" - + "1B1B650C23661D15897263"; + private String SM2_privString = PublicMethod.getSM2RandomPrivateKey(); private byte[] SM2_privateKey = Hex.decode(SM2_privString); - private String SM2_pubString = "04d5548c7825cbb56150a3506cd57464af8a1ae0519" - + "dfaf3c58221dc810caf28dd921073768fe3d59ce54e79a49445cf73fed23086537" - + "027264d168946d479533e"; - private String SM2_compressedPubString = - "02d5548c7825cbb56150a3506cd57464af8a1ae0519dfaf3c58221dc810caf28dd"; + private String SM2_pubString = PublicMethod.getSM2PublicByPrivateKey(SM2_privString); private byte[] SM2_pubKey = Hex.decode(SM2_pubString); - private byte[] SM2_compressedPubKey = Hex.decode(SM2_compressedPubString); - private String SM2_address = "62e49e4c2f4e3c0653a02f8859c1e6991b759e87"; + private String SM2_address = PublicMethod.getSM2AddressByPrivateKey(SM2_privString); - - private String EC_privString = "c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4"; + private String EC_privString = PublicMethod.getRandomPrivateKey(); private byte[] EC_privateKey = Hex.decode(EC_privString); - private String EC_pubString = "040947751e3022ecf3016be03ec77ab0ce3c2662b4843898cb068d74f698ccc" - + "8ad75aa17564ae80a20bb044ee7a6d903e8e8df624b089c95d66a0570f051e5a05b"; - private String EC_compressedPubString = - "030947751e3022ecf3016be03ec77ab0ce3c2662b4843898cb068d74f6" + "98ccc8ad"; + private String EC_pubString = PublicMethod.getPublicByPrivateKey(EC_privString); private byte[] EC_pubKey = Hex.decode(EC_pubString); - private byte[] EC_compressedPubKey = Hex.decode(EC_compressedPubString); - private String EC_address = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826"; + private String EC_address = PublicMethod.getHexAddressByPrivateKey(EC_privString); + @Test @@ -83,11 +74,12 @@ public void testAddress() { SignInterface sign = new SM2(SM2_pubKey, false); byte[] prefix_address = sign.getAddress(); byte[] address = Arrays.copyOfRange(prefix_address, 1, prefix_address.length); - assertEquals(SM2_address, Hex.toHexString(address)); - + byte[] addressTmp = Arrays.copyOfRange(Hex.decode(SM2_address), 1, prefix_address.length); + assertEquals(Hex.toHexString(addressTmp), Hex.toHexString(address)); sign = new ECKey(EC_pubKey, false); prefix_address = sign.getAddress(); address = Arrays.copyOfRange(prefix_address, 1, prefix_address.length); - assertEquals(EC_address, Hex.toHexString(address)); + byte[] ecAddressTmp = Arrays.copyOfRange(Hex.decode(EC_address), 1, prefix_address.length); + assertEquals(Hex.toHexString(ecAddressTmp), Hex.toHexString(address)); } } diff --git a/framework/src/test/java/org/tron/common/runtime/TvmTestUtils.java b/framework/src/test/java/org/tron/common/runtime/TvmTestUtils.java index 5a9a77e108a..ec2cd5a5e02 100644 --- a/framework/src/test/java/org/tron/common/runtime/TvmTestUtils.java +++ b/framework/src/test/java/org/tron/common/runtime/TvmTestUtils.java @@ -10,7 +10,6 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.tron.common.crypto.Hash; -import org.tron.common.utils.PublicMethod; import org.tron.common.utils.WalletUtil; import org.tron.common.utils.client.Parameter.CommonConstant; import org.tron.common.utils.client.WalletClient; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java index 868e7b1c558..8f9ea5c059a 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java @@ -25,6 +25,7 @@ import org.tron.core.services.jsonrpc.TronJsonRpcImpl; import org.tron.protos.Protocol.Transaction; + @Slf4j public class Create2Test extends VMTestBase { /* diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java index e693b90c3fa..eed995f12b5 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java @@ -40,6 +40,7 @@ import org.junit.Test; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; +import org.tron.common.utils.PublicMethod; import org.tron.core.Constant; import org.tron.core.config.args.Args; import org.tron.core.db2.common.WrappedByteArray; @@ -86,7 +87,7 @@ public void initDb() { @Test public void testPutGet() { dataSourceTest.resetDb(); - String key1 = "2c0937534dd1b3832d05d865e8e6f2bf23218300b33a992740d45ccab7d4f519"; + String key1 = PublicMethod.getRandomPrivateKey(); byte[] key = key1.getBytes(); dataSourceTest.initDB(); String value1 = "50000"; @@ -115,9 +116,9 @@ public void testupdateByBatchInner() { Args.getInstance().getOutputDirectory(), "test_updateByBatch"); dataSource.initDB(); dataSource.resetDb(); - String key1 = "431cd8c8d5abe5cb5944b0889b32482d85772fbb98987b10fbb7f17110757350"; + String key1 = PublicMethod.getRandomPrivateKey(); String value1 = "50000"; - String key2 = "431cd8c8d5abe5cb5944b0889b32482d85772fbb98987b10fbb7f17110757351"; + String key2 = PublicMethod.getRandomPrivateKey(); String value2 = "10000"; Map rows = new HashMap<>(); @@ -137,7 +138,7 @@ public void testdeleteData() { LevelDbDataSourceImpl dataSource = new LevelDbDataSourceImpl( Args.getInstance().getOutputDirectory(), "test_delete"); dataSource.initDB(); - String key1 = "431cd8c8d5abe5cb5944b0889b32482d85772fbb98987b10fbb7f17110757350"; + String key1 = PublicMethod.getRandomPrivateKey(); byte[] key = key1.getBytes(); dataSource.deleteData(key); byte[] value = dataSource.getData(key); @@ -153,14 +154,14 @@ public void testallKeys() { dataSource.initDB(); dataSource.resetDb(); - String key1 = "431cd8c8d5abe5cb5944b0889b32482d85772fbb98987b10fbb7f17110757321"; + String key1 = PublicMethod.getRandomPrivateKey(); byte[] key = key1.getBytes(); String value1 = "50000"; byte[] value = value1.getBytes(); dataSource.putData(key, value); - String key3 = "431cd8c8d5abe5cb5944b0889b32482d85772fbb98987b10fbb7f17110757091"; + String key3 = PublicMethod.getRandomPrivateKey(); byte[] key2 = key3.getBytes(); String value3 = "30000"; @@ -331,4 +332,4 @@ public void prefixQueryTest() { dataSource.resetDb(); dataSource.closeDB(); } -} \ No newline at end of file +} diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java index 1b261fd8b98..f0ceb7fcac4 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java @@ -25,6 +25,7 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; import org.tron.common.utils.PropUtil; +import org.tron.common.utils.PublicMethod; import org.tron.core.config.args.Args; import org.tron.core.db2.common.WrappedByteArray; @@ -76,7 +77,7 @@ public static void initDb() { @Test public void testPutGet() { dataSourceTest.resetDb(); - String key1 = "2c0937534dd1b3832d05d865e8e6f2bf23218300b33a992740d45ccab7d4f519"; + String key1 = PublicMethod.getRandomPrivateKey(); byte[] key = key1.getBytes(); dataSourceTest.initDB(); String value1 = "50000"; @@ -105,9 +106,9 @@ public void testupdateByBatchInner() { Args.getInstance().getOutputDirectory(), "test_updateByBatch"); dataSource.initDB(); dataSource.resetDb(); - String key1 = "431cd8c8d5abe5cb5944b0889b32482d85772fbb98987b10fbb7f17110757350"; + String key1 = PublicMethod.getRandomPrivateKey(); String value1 = "50000"; - String key2 = "431cd8c8d5abe5cb5944b0889b32482d85772fbb98987b10fbb7f17110757351"; + String key2 = PublicMethod.getRandomPrivateKey(); String value2 = "10000"; Map rows = new HashMap<>(); @@ -127,7 +128,7 @@ public void testdeleteData() { RocksDbDataSourceImpl dataSource = new RocksDbDataSourceImpl( Args.getInstance().getOutputDirectory(), "test_delete"); dataSource.initDB(); - String key1 = "431cd8c8d5abe5cb5944b0889b32482d85772fbb98987b10fbb7f17110757350"; + String key1 = PublicMethod.getRandomPrivateKey(); byte[] key = key1.getBytes(); dataSource.deleteData(key); byte[] value = dataSource.getData(key); @@ -143,14 +144,14 @@ public void testallKeys() { dataSource.initDB(); dataSource.resetDb(); - String key1 = "431cd8c8d5abe5cb5944b0889b32482d85772fbb98987b10fbb7f17110757321"; + String key1 = PublicMethod.getRandomPrivateKey(); byte[] key = key1.getBytes(); String value1 = "50000"; byte[] value = value1.getBytes(); dataSource.putData(key, value); - String key3 = "431cd8c8d5abe5cb5944b0889b32482d85772fbb98987b10fbb7f17110757091"; + String key3 = PublicMethod.getRandomPrivateKey(); byte[] key2 = key3.getBytes(); String value3 = "30000"; diff --git a/framework/src/test/java/org/tron/common/utils/PublicMethod.java b/framework/src/test/java/org/tron/common/utils/PublicMethod.java index 018db4b5354..5b96a607977 100644 --- a/framework/src/test/java/org/tron/common/utils/PublicMethod.java +++ b/framework/src/test/java/org/tron/common/utils/PublicMethod.java @@ -7,14 +7,19 @@ import java.io.IOException; import java.math.BigInteger; +import java.util.Objects; + +import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.net.InetAddress; import java.net.Socket; import java.util.Random; -import lombok.extern.slf4j.Slf4j; import org.tron.api.GrpcAPI; import org.tron.api.WalletGrpc; import org.tron.common.crypto.ECKey; +import org.tron.common.crypto.sm2.SM2; +import org.tron.common.crypto.sm2.SM2Signer; import org.tron.common.utils.client.utils.TransactionUtils; import org.tron.core.Wallet; import org.tron.protos.Protocol; @@ -24,6 +29,64 @@ @Slf4j public class PublicMethod { + public static ECKey getRandomECKey(String privateKey) { + BigInteger priK = new BigInteger(privateKey, 16); + return ECKey.fromPrivate(priK); + } + + public static String getRandomPrivateKey() { + return Hex.toHexString(Objects + .requireNonNull(new ECKey(Utils.getRandom()).getPrivKeyBytes())); + } + + public static String getHexAddressByPrivateKey(String privateKey) { + return ByteArray.toHexString(getAddressByteByPrivateKey(privateKey)); + } + + public static byte[] getAddressByteByPrivateKey(String privateKey) { + return getRandomECKey(privateKey).getAddress(); + } + + public static String getPublicByPrivateKey(String privateKey) { + return Hex.toHexString(getRandomECKey(privateKey).getPubKey()); + } + + public static byte[] getPublicKeyFromPrivate(String privateKey) { + BigInteger tmpKey = new BigInteger(privateKey, 16); + return ECKey.publicKeyFromPrivate(tmpKey, true); + } + + public static String getSM2RandomPrivateKey() { + SM2 key = new SM2(Utils.getRandom()); + return Hex.toHexString( + Objects.requireNonNull(key.getPrivKeyBytes())); + } + + public static SM2 getSM2byPrivate(String privateKey) { + BigInteger priK = new BigInteger(privateKey, 16); + return SM2.fromPrivate(priK); + } + + public static String getSM2PublicByPrivateKey(String privateKey) { + return Hex.toHexString(getSM2byPrivate(privateKey).getPubKey()); + } + + public static String getSM2AddressByPrivateKey(String privateKey) { + return ByteArray + .toHexString(getSM2byPrivate(privateKey).getAddress()); + } + + public static byte[] getSM2PublicKeyFromPrivate(String privateKey) { + BigInteger tmpKey = new BigInteger(privateKey, 16); + return SM2.publicKeyFromPrivate(tmpKey, true); + } + + public static byte[] getSM2HashByPubKey(byte[] pubKey, String message) { + SM2 key = SM2.fromPublicOnly(pubKey); + SM2Signer signer = key.getSM2SignerForHash(); + return signer.generateSM3Hash(message.getBytes()); + } + /** constructor. */ public static SmartContractOuterClass.SmartContract.ABI jsonStr2Abi(String jsonStr) { if (jsonStr == null) { @@ -38,24 +101,24 @@ public static SmartContractOuterClass.SmartContract.ABI jsonStr2Abi(String jsonS for (int index = 0; index < jsonRoot.size(); index++) { JsonElement abiItem = jsonRoot.get(index); boolean anonymous = - abiItem.getAsJsonObject().get("anonymous") != null - && abiItem.getAsJsonObject().get("anonymous").getAsBoolean(); + abiItem.getAsJsonObject().get("anonymous") != null + && abiItem.getAsJsonObject().get("anonymous").getAsBoolean(); final boolean constant = - abiItem.getAsJsonObject().get("constant") != null - && abiItem.getAsJsonObject().get("constant").getAsBoolean(); + abiItem.getAsJsonObject().get("constant") != null + && abiItem.getAsJsonObject().get("constant").getAsBoolean(); final String name = - abiItem.getAsJsonObject().get("name") != null - ? abiItem.getAsJsonObject().get("name").getAsString() - : null; + abiItem.getAsJsonObject().get("name") != null + ? abiItem.getAsJsonObject().get("name").getAsString() + : null; JsonArray inputs = - abiItem.getAsJsonObject().get("inputs") != null - ? abiItem.getAsJsonObject().get("inputs").getAsJsonArray() : null; + abiItem.getAsJsonObject().get("inputs") != null + ? abiItem.getAsJsonObject().get("inputs").getAsJsonArray() : null; final JsonArray outputs = - abiItem.getAsJsonObject().get("outputs") != null - ? abiItem.getAsJsonObject().get("outputs").getAsJsonArray() : null; + abiItem.getAsJsonObject().get("outputs") != null + ? abiItem.getAsJsonObject().get("outputs").getAsJsonArray() : null; String type = - abiItem.getAsJsonObject().get("type") != null - ? abiItem.getAsJsonObject().get("type").getAsString() : null; + abiItem.getAsJsonObject().get("type") != null + ? abiItem.getAsJsonObject().get("type").getAsString() : null; final boolean payable = abiItem.getAsJsonObject().get("payable") != null && abiItem.getAsJsonObject().get("payable").getAsBoolean(); @@ -138,7 +201,7 @@ public static SmartContractOuterClass.SmartContract.ABI jsonStr2Abi(String jsonS /** constructor. */ public static SmartContractOuterClass.SmartContract.ABI.Entry.EntryType - getEntryType(String type) { + getEntryType(String type) { switch (type) { case "constructor": return SmartContractOuterClass.SmartContract.ABI.Entry.EntryType.Constructor; @@ -158,7 +221,7 @@ public static SmartContractOuterClass.SmartContract.ABI jsonStr2Abi(String jsonS /** constructor. */ public static SmartContractOuterClass.SmartContract.ABI.Entry.StateMutabilityType - getStateMutability(String stateMutability) { + getStateMutability(String stateMutability) { switch (stateMutability) { case "pure": return SmartContractOuterClass.SmartContract.ABI.Entry.StateMutabilityType.Pure; diff --git a/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java b/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java index 6945c044194..095a5b2aa97 100644 --- a/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java +++ b/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java @@ -26,6 +26,7 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; import org.tron.common.utils.client.WalletClient; +import org.tron.common.utils.PublicMethod; import org.tron.common.zksnark.IncrementalMerkleTreeContainer; import org.tron.common.zksnark.IncrementalMerkleVoucherContainer; import org.tron.common.zksnark.JLibrustzcash; @@ -55,7 +56,7 @@ public class ShieldedTRC20BuilderTest extends BaseTest { @Resource private Wallet wallet; - private final String priKey = "650950B193DDDDB35B6E48912DD28F7AB0E7140C1BFDEFD493348F02295BD812"; + private String priKey = PublicMethod.getRandomPrivateKey(); private static final String SHIELDED_CONTRACT_ADDRESS_STR = "TGAmX5AqVUoXCf8MoHxbuhQPmhGfWTnEgA"; private static final byte[] SHIELDED_CONTRACT_ADDRESS; private static final byte[] DEFAULT_OVK; @@ -2173,8 +2174,6 @@ public void createShieldedContractParametersWithoutAskForBurn1to2() @Test public void getTriggerInputForForMint() throws Exception { librustzcashInitZksnarkParams(); - String pubAddress = "TFsrP7YcSSRwHzLPwaCnXyTKagHs8rXKNJ"; - byte[] callerAddress = WalletClient.decodeFromBase58Check(pubAddress); SpendingKey sk = SpendingKey.random(); ExpandedSpendingKey expsk = sk.expandedSpendingKey(); byte[] ovk = expsk.getOvk(); diff --git a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java index a795cf14447..0de313ed360 100755 --- a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java @@ -10,6 +10,7 @@ import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; import org.tron.common.utils.client.utils.TransactionUtils; +import org.tron.common.utils.PublicMethod; import org.tron.common.zksnark.IncrementalMerkleTreeContainer; import org.tron.common.zksnark.IncrementalMerkleVoucherContainer; import org.tron.core.Constant; @@ -27,7 +28,6 @@ import org.tron.core.exception.ValidateSignatureException; import org.tron.core.exception.ZksnarkException; import org.tron.core.services.http.FullNodeHttpApiService; -import org.tron.core.utils.TransactionUtil; import org.tron.core.zen.ZenTransactionBuilder; import org.tron.core.zen.address.DiversifierT; import org.tron.core.zen.address.ExpandedSpendingKey; @@ -70,12 +70,13 @@ public class ShieldedTransferActuatorTest extends BaseTest { static { dbPath = "output_shield_transfer_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - PUBLIC_ADDRESS_ONE = - Wallet.getAddressPreFixString() + "a7d8a35b260395c14aa456297662092ba3b76fc0"; - ADDRESS_ONE_PRIVATE_KEY = "7f7f701e94d4f1dd60ee5205e7ea8ee31121427210417b608a6b2e96433549a7"; + ADDRESS_ONE_PRIVATE_KEY = PublicMethod.getRandomPrivateKey(); + PUBLIC_ADDRESS_ONE = PublicMethod.getHexAddressByPrivateKey(ADDRESS_ONE_PRIVATE_KEY); + + ADDRESS_TWO_PRIVATE_KEY = PublicMethod.getRandomPrivateKey(); PUBLIC_ADDRESS_TWO = - Wallet.getAddressPreFixString() + "8ba2aaae540c642e44e3bed5522c63bbc21fff92"; - ADDRESS_TWO_PRIVATE_KEY = "e4e0edd6bff7b353dfc69a590721e902e6915c5e3e87d36dcb567a9716304720"; + PublicMethod.getHexAddressByPrivateKey(ADDRESS_TWO_PRIVATE_KEY); + DEFAULT_OVK = ByteArray.fromHexString( "030c8c2bc59fb3eb8afb047a8ea4b028743d23e7d38c6fa30908358431e2314d"); } diff --git a/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java index 60766a07863..88d67c3a632 100644 --- a/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java @@ -2,6 +2,8 @@ import com.google.protobuf.ByteString; import java.io.File; +import java.util.Arrays; + import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; import org.junit.Assert; @@ -9,6 +11,8 @@ import org.junit.Test; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; +import org.tron.common.utils.LocalWitnesses; +import org.tron.common.utils.PublicMethod; import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -20,6 +24,9 @@ @Slf4j public class BlockCapsuleTest { + private final String privateKey = PublicMethod.getRandomPrivateKey(); + private LocalWitnesses localWitnesses; + private static BlockCapsule blockCapsule0 = new BlockCapsule(1, Sha256Hash.wrap(ByteString .copyFrom(ByteArray @@ -119,9 +126,15 @@ public void testGetInsHash() { Sha256Hash.wrap(blockCapsule0.getParentHashStr())); } + @Test public void testHasWitnessSignature() { + localWitnesses = new LocalWitnesses(); + localWitnesses.setPrivateKeys(Arrays.asList(privateKey)); + localWitnesses.initWitnessAccountAddress(true); + Args.setLocalWitnesses(localWitnesses); + Assert.assertFalse(blockCapsule0.hasWitnessSignature()); blockCapsule0 .sign(ByteArray.fromHexString(Args.getLocalWitnesses().getPrivateKey())); @@ -133,4 +146,4 @@ public void testGetTimeStamp() { Assert.assertEquals(1234L, blockCapsule0.getTimeStamp()); } -} \ No newline at end of file +} diff --git a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java index 20d9e979fee..143e10706aa 100644 --- a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java @@ -18,6 +18,7 @@ import com.google.common.collect.Lists; import io.grpc.internal.GrpcUtil; import io.grpc.netty.NettyServerBuilder; +import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; @@ -25,11 +26,17 @@ import org.tron.common.args.GenesisBlock; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.LocalWitnesses; +import org.tron.common.utils.PublicMethod; import org.tron.core.Constant; @Slf4j public class ArgsTest { + private final String privateKey = PublicMethod.getRandomPrivateKey(); + private String address; + private LocalWitnesses localWitnesses; + @After public void destroy() { Args.clearParam(); @@ -43,6 +50,13 @@ public void get() { Args.logConfig(); + localWitnesses = new LocalWitnesses(); + localWitnesses.setPrivateKeys(Arrays.asList(privateKey)); + localWitnesses.initWitnessAccountAddress(true); + Args.setLocalWitnesses(localWitnesses); + address = ByteArray.toHexString(Args.getLocalWitnesses() + .getWitnessAccountAddress(CommonParameter.getInstance().isECKeyCryptoEngine())); + Assert.assertEquals(0, parameter.getBackupPriority()); Assert.assertEquals(3000, parameter.getKeepAliveInterval()); @@ -65,7 +79,7 @@ public void get() { genesisBlock.getParentHash()); Assert.assertEquals( - Lists.newArrayList("f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62"), + Lists.newArrayList(privateKey), Args.getLocalWitnesses().getPrivateKeys()); Assert.assertTrue(parameter.isNodeDiscoveryEnable()); @@ -91,10 +105,12 @@ public void get() { Assert.assertEquals(GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE, parameter.getMaxHeaderListSize()); Assert.assertEquals(1L, parameter.getAllowCreationOfContracts()); - Assert.assertEquals("f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62", + Assert.assertEquals(privateKey, Args.getLocalWitnesses().getPrivateKey()); - Assert.assertEquals("a0299f3db80a24b20a254b89ce639d59132f157f13", + + Assert.assertEquals(address, ByteArray.toHexString(Args.getLocalWitnesses() .getWitnessAccountAddress(CommonParameter.getInstance().isECKeyCryptoEngine()))); } } + diff --git a/framework/src/test/java/org/tron/core/config/args/LocalWitnessTest.java b/framework/src/test/java/org/tron/core/config/args/LocalWitnessTest.java index 45466c547d1..d0222254c7d 100644 --- a/framework/src/test/java/org/tron/core/config/args/LocalWitnessTest.java +++ b/framework/src/test/java/org/tron/core/config/args/LocalWitnessTest.java @@ -20,17 +20,19 @@ import org.junit.Before; import org.junit.Test; import org.tron.common.utils.LocalWitnesses; +import org.tron.common.utils.PublicMethod; public class LocalWitnessTest { private LocalWitnesses localWitness = new LocalWitnesses(); + private static String PRIVATE_KEY = PublicMethod.getRandomPrivateKey(); @Before public void setLocalWitness() { localWitness .setPrivateKeys( Lists.newArrayList( - "f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62")); + PRIVATE_KEY)); } @Test @@ -52,16 +54,16 @@ public void whenSetBadFormatPrivateKey() { public void whenSetPrefixPrivateKey() { localWitness .setPrivateKeys(Lists - .newArrayList("0xf31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62")); + .newArrayList("0x" + PRIVATE_KEY)); localWitness .setPrivateKeys(Lists - .newArrayList("0Xf31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62")); + .newArrayList("0X" + PRIVATE_KEY)); } @Test public void getPrivateKey() { Assert.assertEquals(Lists - .newArrayList("f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62"), + .newArrayList(PRIVATE_KEY), localWitness.getPrivateKeys()); } } diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index 916ea784939..6034ccf36bf 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -10,6 +10,7 @@ import com.google.protobuf.ByteString; import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; @@ -28,6 +29,8 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; import org.tron.common.utils.JsonUtil; +import org.tron.common.utils.LocalWitnesses; +import org.tron.common.utils.PublicMethod; import org.tron.common.utils.ReflectUtils; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.StringUtil; @@ -75,6 +78,7 @@ import org.tron.core.store.ExchangeStore; import org.tron.core.store.ExchangeV2Store; import org.tron.core.store.IncrementalMerkleTreeStore; +import org.tron.protos.Protocol; import org.tron.core.store.StoreFactory; import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.Block; @@ -100,6 +104,8 @@ public class ManagerTest extends BlockGenerate { private static AtomicInteger port = new AtomicInteger(0); private static String accountAddress = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + private final String privateKey = PublicMethod.getRandomPrivateKey(); + private LocalWitnesses localWitnesses; @Before public void init() { @@ -113,6 +119,12 @@ public void init() { consensusService = context.getBean(ConsensusService.class); consensusService.start(); chainManager = dbManager.getChainBaseManager(); + + localWitnesses = new LocalWitnesses(); + localWitnesses.setPrivateKeys(Arrays.asList(privateKey)); + localWitnesses.initWitnessAccountAddress(true); + Args.setLocalWitnesses(localWitnesses); + blockCapsule2 = new BlockCapsule( 1, @@ -129,6 +141,16 @@ public void init() { blockCapsule2.sign( ByteArray.fromHexString(Args.getLocalWitnesses().getPrivateKey())); Assert.assertTrue(dbManager.getMaxFlushCount() == 200); + + byte[] address = PublicMethod.getAddressByteByPrivateKey(privateKey); + ByteString addressByte = ByteString.copyFrom(address); + WitnessCapsule witnessCapsule = new WitnessCapsule(addressByte); + chainManager.getWitnessStore().put(addressByte.toByteArray(), witnessCapsule); + chainManager.addWitness(addressByte); + + AccountCapsule accountCapsule = + new AccountCapsule(Protocol.Account.newBuilder().setAddress(addressByte).build()); + chainManager.getAccountStore().put(addressByte.toByteArray(), accountCapsule); } @After @@ -201,6 +223,7 @@ public void setBlockReference() .setToAddress(ByteString.copyFromUtf8("bbb")) .build(); TransactionCapsule trx = new TransactionCapsule(tc, ContractType.TransferContract); + if (chainManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() == 0) { dbManager.pushBlock(blockCapsule); Assert.assertEquals(1, diff --git a/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java b/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java index 26b1e7e7bc1..f9b1a6c44e0 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java @@ -2,6 +2,9 @@ import com.google.protobuf.ByteString; import java.io.File; +import java.lang.reflect.Array; +import java.util.Arrays; + import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; @@ -13,13 +16,20 @@ import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; +import org.tron.common.utils.LocalWitnesses; +import org.tron.common.utils.PublicMethod; import org.tron.common.utils.Sha256Hash; +import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; +import org.tron.core.store.WitnessScheduleStore; +import org.tron.protos.Protocol; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.contract.BalanceContract.TransferContract; @@ -52,6 +62,15 @@ public void init() { dbManager.getDynamicPropertiesStore() .saveLatestBlockHeaderTimestamp(blockCapsule.getTimeStamp()); dbManager.updateRecentBlock(blockCapsule); + initLocalWitness(); + } + + private void initLocalWitness() { + String randomPrivateKey = PublicMethod.getRandomPrivateKey(); + LocalWitnesses localWitnesses = new LocalWitnesses(); + localWitnesses.setPrivateKeys(Arrays.asList(randomPrivateKey)); + localWitnesses.initWitnessAccountAddress(true); + Args.setLocalWitnesses(localWitnesses); } @After diff --git a/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java b/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java index 471a994d4dd..f51a8744c74 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java @@ -7,9 +7,9 @@ import org.junit.BeforeClass; import org.junit.Test; import org.tron.common.BaseTest; -import org.tron.common.application.Application; import org.tron.common.crypto.ECKey; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.PublicMethod; import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -44,8 +44,6 @@ public class TransactionStoreTest extends BaseTest { private static String indexDirectory = "index_TransactionStore_test"; @Resource private TransactionStore transactionStore; - @Resource - private Application AppT; /** * Init data. @@ -185,8 +183,7 @@ public void createAccountTransactionStoreTest() throws BadItemException { public void getUncheckedTransactionTest() { final BlockStore blockStore = chainBaseManager.getBlockStore(); final TransactionStore trxStore = chainBaseManager.getTransactionStore(); - String key = "f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62"; - + String key = PublicMethod.getRandomPrivateKey(); BlockCapsule blockCapsule = new BlockCapsule( 1, diff --git a/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java b/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java index 86fa45a3e59..a2a812ef30b 100644 --- a/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java +++ b/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java @@ -22,9 +22,11 @@ import org.tron.common.prometheus.MetricLabels; import org.tron.common.prometheus.Metrics; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.PublicMethod; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.Utils; import org.tron.consensus.dpos.DposSlot; +import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; @@ -40,7 +42,7 @@ public class PrometheusApiServiceTest extends BaseTest { @Resource private DposSlot dposSlot; final int blocks = 512; - private final String key = "f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62"; + private final String key = PublicMethod.getRandomPrivateKey(); private final byte[] privateKey = ByteArray.fromHexString(key); private static final AtomicInteger port = new AtomicInteger(0); private final long time = ZonedDateTime.of(localDateTime, @@ -49,6 +51,8 @@ public class PrometheusApiServiceTest extends BaseTest { private TronNetDelegate tronNetDelegate; @Resource private ConsensusService consensusService; + @Resource + private ChainBaseManager chainManager; static { dbPath = "output-prometheus-metric"; @@ -82,11 +86,21 @@ protected void check() throws Exception { Assert.assertNull(errorLogs); } - @Before public void init() throws Exception { logger.info("Full node running."); consensusService.start(); + chainBaseManager = dbManager.getChainBaseManager(); + byte[] address = PublicMethod.getAddressByteByPrivateKey(key); + ByteString addressByte = ByteString.copyFrom(address); + WitnessCapsule witnessCapsule = new WitnessCapsule(addressByte); + chainBaseManager.getWitnessStore().put(addressByte.toByteArray(), witnessCapsule); + chainBaseManager.addWitness(addressByte); + + AccountCapsule accountCapsule = + new AccountCapsule(Protocol.Account.newBuilder().setAddress(addressByte).build()); + chainBaseManager.getAccountStore().put(addressByte.toByteArray(), accountCapsule); + } private void generateBlock(Map witnessAndAccount) throws Exception { diff --git a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java index d012587849b..617e824c58f 100644 --- a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java @@ -7,6 +7,8 @@ import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @@ -21,6 +23,8 @@ import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; +import org.tron.common.utils.LocalWitnesses; +import org.tron.common.utils.PublicMethod; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.Utils; import org.tron.consensus.dpos.DposSlot; @@ -43,8 +47,10 @@ public abstract class ConditionallyStopTest extends BlockGenerate { static ChainBaseManager chainManager; private static DposSlot dposSlot; - private final String key = "f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62"; + + private final String key = PublicMethod.getRandomPrivateKey(); private final byte[] privateKey = ByteArray.fromHexString(key); + private final AtomicInteger port = new AtomicInteger(0); protected String dbPath; protected Manager dbManager; @@ -52,6 +58,7 @@ public abstract class ConditionallyStopTest extends BlockGenerate { private TronNetDelegate tronNetDelegate; private TronApplicationContext context; + static LocalDateTime localDateTime = LocalDateTime.now(); private long time = ZonedDateTime.of(localDateTime, ZoneId.systemDefault()).toInstant().toEpochMilli(); @@ -71,6 +78,7 @@ public void init() throws Exception { logger.info("Full node running."); Args.setParam(new String[] {"-d", dbPath, "-w"}, Constant.TEST_CONF); Args.getInstance().setNodeListenPort(10000 + port.incrementAndGet()); + initParameter(Args.getInstance()); context = new TronApplicationContext(DefaultConfig.class); @@ -84,6 +92,16 @@ public void init() throws Exception { tronNetDelegate.setExit(false); currentHeader = dbManager.getDynamicPropertiesStore() .getLatestBlockHeaderNumberFromDB(); + + byte[] address = PublicMethod.getAddressByteByPrivateKey(key); + ByteString addressByte = ByteString.copyFrom(address); + WitnessCapsule witnessCapsule = new WitnessCapsule(addressByte); + chainManager.getWitnessStore().put(addressByte.toByteArray(), witnessCapsule); + chainManager.addWitness(addressByte); + + AccountCapsule accountCapsule = + new AccountCapsule(Protocol.Account.newBuilder().setAddress(addressByte).build()); + chainManager.getAccountStore().put(addressByte.toByteArray(), accountCapsule); } @After @@ -107,8 +125,6 @@ private void generateBlock(Map witnessAndAccount) throws Exc @Test public void testStop() throws Exception { - - final ECKey ecKey = ECKey.fromPrivate(privateKey); Assert.assertNotNull(ecKey); byte[] address = ecKey.getAddress(); diff --git a/framework/src/test/resources/config-test-mainnet.conf b/framework/src/test/resources/config-test-mainnet.conf index 5bcc27b398d..43a01a0feb9 100644 --- a/framework/src/test/resources/config-test-mainnet.conf +++ b/framework/src/test/resources/config-test-mainnet.conf @@ -211,7 +211,7 @@ genesis.block = { } localwitness = [ - f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62 + ] block = { diff --git a/framework/src/test/resources/config-test-storagetest.conf b/framework/src/test/resources/config-test-storagetest.conf index 87e3eabea2d..5098e39b650 100644 --- a/framework/src/test/resources/config-test-storagetest.conf +++ b/framework/src/test/resources/config-test-storagetest.conf @@ -268,7 +268,7 @@ genesis.block = { //localWitnessAccountAddress = localwitness = [ - f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62 + ] block = { @@ -285,4 +285,4 @@ vm = { } committee = { allowCreationOfContracts = 1 //mainnet:0 (reset by committee),test:1 -} \ No newline at end of file +} diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index 2ace5fab538..d506521965f 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -327,7 +327,7 @@ genesis.block = { //localWitnessAccountAddress = localwitness = [ - f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62 + ] block = { diff --git a/work.sh b/work.sh index 91d7247ca57..7681985d76b 100755 --- a/work.sh +++ b/work.sh @@ -5,7 +5,7 @@ # Note: modify the paths and private key to your own. # Auther: haoyouqiang -# Since: 2018/5/27 +# Since: 2018/5/27 # Version: 1.0 if [ $# -ne 1 ]; then @@ -24,7 +24,7 @@ LOG_FILE_PATH="java-tron.log" CONF_FILE_PATH="./build/resources/main/config.conf" -PRIVATE_KEY="650950B193DDDDB35B6E48912DD28F7AB0E7140C1BFDEFD493348F02295BD812" +PRIVATE_KEY="" case "${1}" in start) From 804ea9e0f8545e5721a851d50228e457335f9cf3 Mon Sep 17 00:00:00 2001 From: liukai Date: Fri, 26 May 2023 18:40:39 +0800 Subject: [PATCH 0784/1197] feat(test): clean config --- framework/src/main/resources/config-localtest.conf | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/framework/src/main/resources/config-localtest.conf b/framework/src/main/resources/config-localtest.conf index 1087f0d3dcf..32f57481463 100644 --- a/framework/src/main/resources/config-localtest.conf +++ b/framework/src/main/resources/config-localtest.conf @@ -188,8 +188,6 @@ genesis.block = { accountType = "AssetIssue" address = "TJCnKsPa7y5okkXvQAidZBzqx3QyQ6sxMW" balance = "25000000000000000" - #priKey = D95611A9AF2A2A45359106222ED1AFED48853D9A44DEFF8DC7913F5CBA727366 - #password = 2VYRqa8qKkU1kQYiLtGv7UiFPZpE3v+Nx5E/XLpyc2Y= }, # the account of payment @@ -198,8 +196,6 @@ genesis.block = { accountType = "AssetIssue" address = "TGehVcNhud84JDCGrNHKVz9jEAVKUpbuiv" balance = "10000000000000000" - #priKey = cba92a516ea09f620a16ff7ee95ce0df1d56550a8babe9964981a7144c8a784a - #password = y6kqUW6gn2IKFv9+6Vzg3x1WVQqLq+mWSYGnFEyKeEo= }, # the account of coin burn @@ -208,8 +204,6 @@ genesis.block = { accountType = "AssetIssue" address = "THKrowiEfCe8evdbaBzDDvQjM5DGeB3s3F" balance = "-9223372036854775808" - #priKey = 8E812436A0E3323166E1F0E8BA79E19E217B2C4A53C970D4CCA0CFB1078979DF - #password = joEkNqDjMjFm4fDounnhniF7LEpTyXDUzKDPsQeJed8= } ] @@ -218,27 +212,23 @@ genesis.block = { address: TN3zfjYUmMFK3ZsHSsrdJoNRtGkQmZLBLz url = "http://test.org/", voteCount = 106 - #priKey = f4df789d3210ac881cb900464dd30409453044d2777060a0c391cbdf4c6a4f57 6666 }, // { // address: TPrLL5ckUdMaPNgJYmGv23qtYjBE34aBf8 // url = "http://mercury.org/", // voteCount = 105 - // #priKey = f5583fd20e13073900a513f333ed13db8c9e83e7e3cf37e74adacef96c5afeaa 7777 // }, // { // address: TEZBh76rouEQpB2zqYVopbRXGx7RfyWorT // #address: 27TfVERREG3FeWMHEAQ95tWHG4sb3ANn3Qe // url = "http://venus.org/", // voteCount = 104 - // #priKey = 9f5c5e48bf87cf92017313082e8cf0f58ccfce423097f0fcebf801695fc99bd4 8888 // }, // { // address: TN27wbfCLEN1gP2PZAxHgU3QZrntsLyxdj // #address: 27b8RUuyZnNPFNZGct2bZkNu9MnGWNAdH3Z // url = "http://earth.org/", // voteCount = 103 - // #priKey = 6781f44d9a2083b14fad1702b8e9ba82749162b795e2fc3f136192fc63f80de2 9999 // }, ] From 7df608685670ea9c2ea19b36898517bcdd8595b7 Mon Sep 17 00:00:00 2001 From: liukai Date: Fri, 26 May 2023 19:06:56 +0800 Subject: [PATCH 0785/1197] feat(test): optimized import --- .../tron/common/crypto/BouncyCastleTest.java | 4 +- .../org/tron/common/crypto/ECKeyTest.java | 4 +- .../org/tron/common/crypto/SM2KeyTest.java | 4 +- .../org/tron/common/utils/PublicMethod.java | 7 +- .../ShieldedTransferActuatorTest.java | 2 +- .../java/org/tron/core/db/ManagerTest.java | 2 +- work.sh | 67 ------------------- 7 files changed, 14 insertions(+), 76 deletions(-) delete mode 100755 work.sh diff --git a/framework/src/test/java/org/tron/common/crypto/BouncyCastleTest.java b/framework/src/test/java/org/tron/common/crypto/BouncyCastleTest.java index 02fc962fa58..4e3a78461f2 100644 --- a/framework/src/test/java/org/tron/common/crypto/BouncyCastleTest.java +++ b/framework/src/test/java/org/tron/common/crypto/BouncyCastleTest.java @@ -13,7 +13,9 @@ import org.tron.common.utils.Sha256Hash; /** - * The reason the test case uses the private key plaintext is to ensure that, after the ECkey tool or algorithm is upgraded, the upgraded differences can be verified. + * The reason the test case uses the private key plaintext is to ensure that, + * after the ECkey tool or algorithm is upgraded, + * the upgraded differences can be verified. */ public class BouncyCastleTest { diff --git a/framework/src/test/java/org/tron/common/crypto/ECKeyTest.java b/framework/src/test/java/org/tron/common/crypto/ECKeyTest.java index 52862001bea..bf268f14320 100644 --- a/framework/src/test/java/org/tron/common/crypto/ECKeyTest.java +++ b/framework/src/test/java/org/tron/common/crypto/ECKeyTest.java @@ -20,7 +20,9 @@ import org.tron.core.Wallet; /** - * The reason the test case uses the private key plaintext is to ensure that, after the ECkey tool or algorithm is upgraded, the upgraded differences can be verified. + * The reason the test case uses the private key plaintext is to ensure that, + * after the ECkey tool or algorithm is upgraded, + * the upgraded differences can be verified. */ @Slf4j public class ECKeyTest { diff --git a/framework/src/test/java/org/tron/common/crypto/SM2KeyTest.java b/framework/src/test/java/org/tron/common/crypto/SM2KeyTest.java index bd5bbae8525..62e800679c1 100644 --- a/framework/src/test/java/org/tron/common/crypto/SM2KeyTest.java +++ b/framework/src/test/java/org/tron/common/crypto/SM2KeyTest.java @@ -20,7 +20,9 @@ import org.tron.core.Wallet; /** - * The reason the test case uses the private key plaintext is to ensure that, after the ECkey tool or algorithm is upgraded, the upgraded differences can be verified. + * The reason the test case uses the private key plaintext is to ensure that, + * after the ECkey tool or algorithm is upgraded, + * the upgraded differences can be verified. */ @Slf4j public class SM2KeyTest { diff --git a/framework/src/test/java/org/tron/common/utils/PublicMethod.java b/framework/src/test/java/org/tron/common/utils/PublicMethod.java index 5b96a607977..22204dce1f2 100644 --- a/framework/src/test/java/org/tron/common/utils/PublicMethod.java +++ b/framework/src/test/java/org/tron/common/utils/PublicMethod.java @@ -4,16 +4,15 @@ import com.google.gson.JsonElement; import com.google.gson.JsonParser; import com.google.protobuf.ByteString; - import java.io.IOException; import java.math.BigInteger; +import java.net.InetAddress; +import java.net.Socket; +import java.util.Random; import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import java.net.InetAddress; -import java.net.Socket; -import java.util.Random; import org.tron.api.GrpcAPI; import org.tron.api.WalletGrpc; diff --git a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java index 0de313ed360..5e7d33832b4 100755 --- a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java @@ -9,8 +9,8 @@ import org.junit.Test; import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.client.utils.TransactionUtils; import org.tron.common.utils.PublicMethod; +import org.tron.common.utils.client.utils.TransactionUtils; import org.tron.common.zksnark.IncrementalMerkleTreeContainer; import org.tron.common.zksnark.IncrementalMerkleVoucherContainer; import org.tron.core.Constant; diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index 6034ccf36bf..2c51250d757 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -78,8 +78,8 @@ import org.tron.core.store.ExchangeStore; import org.tron.core.store.ExchangeV2Store; import org.tron.core.store.IncrementalMerkleTreeStore; -import org.tron.protos.Protocol; import org.tron.core.store.StoreFactory; +import org.tron.protos.Protocol; import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.Transaction; diff --git a/work.sh b/work.sh deleted file mode 100755 index 7681985d76b..00000000000 --- a/work.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/bash - -# Function: to start, stop and restart java-tron. -# Usage: bash work.sh start|stop|restart. -# Note: modify the paths and private key to your own. - -# Auther: haoyouqiang -# Since: 2018/5/27 -# Version: 1.0 - -if [ $# -ne 1 ]; then - echo "Usage: bash work.sh start|stop|restart." - exit 1 -fi - -# Increase memory limit that JVM can use to avoid OOM error: -# 80% of your physical memory may be a proper ceiling that JVM can use. -# By default there, JVM initializes with 1g memory and can use 32g at most. -JVM_OPTIONS="-Xms1g -Xmx32g" - -JAR_FILE_PATH="./build/libs/java-tron.jar" -PID_FILE_PATH="java-tron.pid" -LOG_FILE_PATH="java-tron.log" - -CONF_FILE_PATH="./build/resources/main/config.conf" - -PRIVATE_KEY="" - -case "${1}" in - start) - # Already running - if [ -f ${PID_FILE_PATH} ]; then - pid=$(cat ${PID_FILE_PATH}) - if $(ps -p ${pid} > /dev/null); then - echo "Already running [PID: ${pid}], you can stop it and retry." - exit 1 - fi - fi - - nohup java ${JVM_OPTIONS} \ - -jar ${JAR_FILE_PATH} \ - -p ${PRIVATE_KEY} --witness \ - -c ${CONF_FILE_PATH} \ - > ${LOG_FILE_PATH} 2>&1 \ - & echo $! > ${PID_FILE_PATH} - - if [ $? -eq 0 ]; then - echo "Succeeded to start java-tron." - else - echo "Failed to start java-tron." - fi - ;; - stop) - kill $(cat ${PID_FILE_PATH}) - - if [ $? -eq 0 ]; then - rm ${PID_FILE_PATH} - echo "Succeeded to stop java-tron." - else - echo "Failed to stop java-tron." - fi - ;; - restart) - ${0} stop && sleep 1 && ${0} start - ;; -esac - From b7ffe58a635859965ed3eb3e3ec03fe273ae50f1 Mon Sep 17 00:00:00 2001 From: liukai Date: Fri, 26 May 2023 19:20:20 +0800 Subject: [PATCH 0786/1197] feat(test): Optimize import order --- framework/src/test/java/org/tron/common/utils/PublicMethod.java | 2 +- .../src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/test/java/org/tron/common/utils/PublicMethod.java b/framework/src/test/java/org/tron/common/utils/PublicMethod.java index 22204dce1f2..63feab160d4 100644 --- a/framework/src/test/java/org/tron/common/utils/PublicMethod.java +++ b/framework/src/test/java/org/tron/common/utils/PublicMethod.java @@ -8,8 +8,8 @@ import java.math.BigInteger; import java.net.InetAddress; import java.net.Socket; -import java.util.Random; import java.util.Objects; +import java.util.Random; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; diff --git a/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java b/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java index 095a5b2aa97..e7fefd5e121 100644 --- a/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java +++ b/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java @@ -25,8 +25,8 @@ import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.client.WalletClient; import org.tron.common.utils.PublicMethod; +import org.tron.common.utils.client.WalletClient; import org.tron.common.zksnark.IncrementalMerkleTreeContainer; import org.tron.common.zksnark.IncrementalMerkleVoucherContainer; import org.tron.common.zksnark.JLibrustzcash; From e86bcf457eba9c6eff5ea9efe920b3fee326438e Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 29 May 2023 12:13:12 +0800 Subject: [PATCH 0787/1197] feat(test): bump junit from 4.12 to 4.13.2 --- actuator/build.gradle | 2 +- chainbase/build.gradle | 2 +- common/build.gradle | 2 +- consensus/build.gradle | 2 +- crypto/build.gradle | 2 +- framework/build.gradle | 4 ++-- plugins/build.gradle | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/actuator/build.gradle b/actuator/build.gradle index 3db2e55b3de..a230ef4ca7e 100644 --- a/actuator/build.gradle +++ b/actuator/build.gradle @@ -3,7 +3,7 @@ description = "actuator – a series of transactions for blockchain." // Dependency versions // --------------------------------------- -def junitVersion = "4.12" +def junitVersion = "4.13.2" def mockitoVersion = "2.1.0" def testNgVersion = "6.11" def slf4jVersion = "1.7.25" diff --git a/chainbase/build.gradle b/chainbase/build.gradle index cac7efc6fa5..ed9911b0032 100644 --- a/chainbase/build.gradle +++ b/chainbase/build.gradle @@ -3,7 +3,7 @@ description = "chainbase – a decentralized database for blockchain." // Dependency versions // --------------------------------------- -def junitVersion = "4.12" +def junitVersion = "4.13.2" def mockitoVersion = "2.1.0" def testNgVersion = "6.11" def jacocoVersion = "0.8.0" diff --git a/common/build.gradle b/common/build.gradle index d065d3cbf89..95c6312ebcd 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -35,7 +35,7 @@ repositories { } dependencies { - testCompile group: 'junit', name: 'junit', version: '4.12' + testCompile group: 'junit', name: 'junit', version: '4.13.2' compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.13.4.1' compile "com.cedarsoftware:java-util:1.8.0" diff --git a/consensus/build.gradle b/consensus/build.gradle index c2393064d46..c22e961572e 100644 --- a/consensus/build.gradle +++ b/consensus/build.gradle @@ -2,7 +2,7 @@ description = "consensus – a distributed consensus arithmetic for blockchain." // Dependency versions // --------------------------------------- -def junitVersion = "4.12" +def junitVersion = "4.13.2" def mockitoVersion = "2.1.0" def testNgVersion = "6.11" def slf4jVersion = "1.7.25" diff --git a/crypto/build.gradle b/crypto/build.gradle index 9d90368814d..19ae8e805fe 100644 --- a/crypto/build.gradle +++ b/crypto/build.gradle @@ -11,7 +11,7 @@ repositories { } dependencies { - testCompile group: 'junit', name: 'junit', version: '4.12' + testCompile group: 'junit', name: 'junit', version: '4.13.2' compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' compile project(":common") } diff --git a/framework/build.gradle b/framework/build.gradle index 299c5fe611a..f6b67795200 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -40,7 +40,7 @@ dependencies { //local libraries compile fileTree(dir: 'libs', include: '*.jar') // end local libraries - testCompile group: 'junit', name: 'junit', version: '4.12' + testCompile group: 'junit', name: 'junit', version: '4.13.2' testCompile group: 'org.mockito', name: 'mockito-core', version: '2.13.0' testCompile group: 'org.hamcrest', name: 'hamcrest-junit', version: '1.0.0.1' @@ -54,7 +54,7 @@ dependencies { compile group: 'com.beust', name: 'jcommander', version: '1.72' - compile group: 'junit', name: 'junit', version: '4.12' + compile group: 'junit', name: 'junit', version: '4.13.2' compile group: 'net.jcip', name: 'jcip-annotations', version: '1.0' diff --git a/plugins/build.gradle b/plugins/build.gradle index 22e37737731..457fb739058 100644 --- a/plugins/build.gradle +++ b/plugins/build.gradle @@ -26,7 +26,7 @@ configurations.getByName('checkstyleConfig') { dependencies { //local libraries compile fileTree(dir: 'libs', include: '*.jar') - testCompile group: 'junit', name: 'junit', version: '4.12' + testCompile group: 'junit', name: 'junit', version: '4.13.2' testCompile group: 'org.mockito', name: 'mockito-core', version: '2.13.0' testCompile group: 'org.hamcrest', name: 'hamcrest-junit', version: '1.0.0.1' testCompile group: 'org.testng', name: 'testng', version: '6.14.3' From 412f8143bb14c5329abe29d096d6fe5b0e0efdd4 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 29 May 2023 13:37:11 +0800 Subject: [PATCH 0788/1197] feat(ci): remove unused circleci --- .circleci/config.yml | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 74940a5a754..00000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,26 +0,0 @@ -version: 2 -jobs: - build: - branches: - only: - - master - - develop - - addinCircleCI - - docker: - - image: circleci/openjdk:8-jdk-browsers - working_directory: ~/java-tron - steps: - - checkout - - run: - name: multi_os_result - command: echo "curl http://60.205.215.34/multi_os_result" -# -# - run: -# name: Daily Build Report -# command: curl http://47.95.206.44:50080/Daily_Build_Task_Report -# -# - run: -# name: Download Links -# command: sh DownloadLinks.sh - From e2010e5c01aa7b05d330779cae67faa11276ad22 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 30 May 2023 14:29:51 +0800 Subject: [PATCH 0789/1197] feat(test):add tests for hard fork --- .../org/tron/core/ForkControllerTest.java | 294 ++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/ForkControllerTest.java diff --git a/framework/src/test/java/org/tron/core/ForkControllerTest.java b/framework/src/test/java/org/tron/core/ForkControllerTest.java new file mode 100644 index 00000000000..5e6783a46ff --- /dev/null +++ b/framework/src/test/java/org/tron/core/ForkControllerTest.java @@ -0,0 +1,294 @@ +package org.tron.core; + +import com.google.protobuf.ByteString; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.ForkController; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.Parameter; +import org.tron.core.config.args.Args; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.Protocol; + +public class ForkControllerTest { + private static ChainBaseManager chainBaseManager; + private static DynamicPropertiesStore dynamicPropertiesStore; + private static final ForkController forkController = ForkController.instance(); + private static TronApplicationContext context; + private static final String dbPath = "output_fork_test"; + private static long ENERGY_LIMIT_BLOCK_NUM = 4727890L; + + @Before + public void init() { + Args.setParam(new String[]{"-d", dbPath, "-w"}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + dynamicPropertiesStore = context.getBean(DynamicPropertiesStore.class); + chainBaseManager = context.getBean(ChainBaseManager.class); + forkController.init(chainBaseManager); + } + + @Test + public void testPass() { + boolean flag = forkController.pass(Parameter.ForkBlockVersionEnum.ENERGY_LIMIT); + Assert.assertFalse(flag); + + dynamicPropertiesStore.saveLatestBlockHeaderNumber(ENERGY_LIMIT_BLOCK_NUM); + flag = forkController.pass(Parameter.ForkBlockVersionEnum.ENERGY_LIMIT); + Assert.assertTrue(flag); + + flag = forkController.pass(Parameter.ForkBlockVersionEnum.VERSION_3_5); + Assert.assertFalse(flag); + + byte[] stats = new byte[3]; + dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_3_5.getValue(), stats); + flag = forkController.pass(Parameter.ForkBlockVersionEnum.VERSION_3_5); + Assert.assertFalse(flag); + + stats[0] = 1; + stats[1] = 1; + dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_3_5.getValue(), stats); + flag = forkController.pass(Parameter.ForkBlockVersionEnum.VERSION_3_5); + Assert.assertFalse(flag); + + stats[2] = 1; + dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_3_5.getValue(), stats); + flag = forkController.pass(Parameter.ForkBlockVersionEnum.VERSION_3_5); + Assert.assertTrue(flag); + + stats = new byte[5]; + flag = forkController.pass(Parameter.ForkBlockVersionEnum.VERSION_4_4); + Assert.assertFalse(flag); + + stats[0] = 1; + stats[1] = 1; + stats[2] = 1; + dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_4.getValue(), stats); + flag = forkController.pass(Parameter.ForkBlockVersionEnum.VERSION_4_4); + Assert.assertFalse(flag); + + stats[3] = 1; + dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_4.getValue(), stats); + flag = forkController.pass(Parameter.ForkBlockVersionEnum.VERSION_4_4); + Assert.assertFalse(flag); + + dynamicPropertiesStore.saveLatestBlockHeaderTimestamp(1596780000000L); + flag = forkController.pass(Parameter.ForkBlockVersionEnum.VERSION_4_4); + Assert.assertTrue(flag); + } + + @Test + public void testReset() { + List list = new ArrayList<>(); + list.add(ByteString.copyFrom(getBytes(0))); + list.add(ByteString.copyFrom(getBytes(0))); + list.add(ByteString.copyFrom(getBytes(0))); + list.add(ByteString.copyFrom(getBytes(0))); + list.add(ByteString.copyFrom(getBytes(0))); + + chainBaseManager.getWitnessScheduleStore().saveActiveWitnesses(list); + + byte[] stats1 = {1, 1, 1, 1, 1}; + byte[] stats2 = {1, 1, 1, 1, 0}; + byte[] stats3 = {1, 1, 1, 0, 0}; + dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_3_5.getValue(), stats1); + dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_3_6.getValue(), stats2); + dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_4.getValue(), stats2); + dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_5.getValue(), stats3); + + dynamicPropertiesStore.saveLatestBlockHeaderTimestamp(1596780000000L); + forkController.reset(); + + byte[] bytes = dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_3_5.getValue()); + Assert.assertEquals(getSum(bytes), 5); + + bytes = dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_3_6.getValue()); + Assert.assertEquals(getSum(bytes), 0); + + bytes = dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_4.getValue()); + Assert.assertEquals(getSum(bytes), 4); + + bytes = dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_5.getValue()); + Assert.assertEquals(getSum(bytes), 0); + list.add(ByteString.copyFrom(new byte[32])); + chainBaseManager.getWitnessScheduleStore().saveActiveWitnesses(list); + forkController.reset(); + bytes = dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_4.getValue()); + Assert.assertEquals(bytes.length, 5); + bytes = dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_5.getValue()); + Assert.assertEquals(bytes.length, 6); + } + + @Test + public void testUpdate() { + List list = new ArrayList<>(); + list.add(ByteString.copyFrom(getBytes(1))); + list.add(ByteString.copyFrom(getBytes(2))); + list.add(ByteString.copyFrom(getBytes(3))); + list.add(ByteString.copyFrom(getBytes(4))); + list.add(ByteString.copyFrom(getBytes(5))); + + chainBaseManager.getWitnessScheduleStore().saveActiveWitnesses(list); + + byte[] stats1 = {1, 1, 1, 1, 1}; + byte[] stats2 = {1, 1, 1, 1, 0}; + byte[] stats3 = {1, 1, 1, 0, 0}; + + dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_3_5.getValue(), stats1); + dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_3_6.getValue(), stats2); + dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_4.getValue(), stats2); + dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_5.getValue(), stats3); + + BlockCapsule blockCapsule = getBlock(1, Parameter.ForkBlockVersionEnum.VERSION_3_5); + + forkController.update(blockCapsule); + + byte[] bytes = dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_3_6.getValue()); + Assert.assertEquals(0, bytes[0]); + bytes = dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_4.getValue()); + Assert.assertEquals(0, bytes[0]); + bytes = dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_5.getValue()); + Assert.assertEquals(0, bytes[0]); + + blockCapsule = getBlock(1, Parameter.ForkBlockVersionEnum.VERSION_4_5); + forkController.update(blockCapsule); + bytes = dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_3_6.getValue()); + Assert.assertEquals(0, bytes[0]); + bytes = dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_4.getValue()); + Assert.assertEquals(0, bytes[0]); + bytes = dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_5.getValue()); + Assert.assertEquals(1, bytes[0]); + + blockCapsule = getBlock(4, Parameter.ForkBlockVersionEnum.VERSION_4_5); + forkController.update(blockCapsule); + blockCapsule = getBlock(5, Parameter.ForkBlockVersionEnum.VERSION_4_5); + + dynamicPropertiesStore.saveLatestBlockHeaderTimestamp(1596780000000L); + forkController.update(blockCapsule); + + bytes = dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_3_6.getValue()); + Assert.assertEquals(getSum(bytes), 5); + bytes = dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_3.getValue()); + Assert.assertEquals(getSum(bytes), 5); + bytes = dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_4.getValue()); + Assert.assertEquals(getSum(bytes), 5); + bytes = dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_5.getValue()); + Assert.assertEquals(getSum(bytes), 4); + + blockCapsule = getBlock(1, Parameter.ForkBlockVersionEnum.VERSION_4_3); + forkController.update(blockCapsule); + bytes = dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_4.getValue()); + Assert.assertEquals(getSum(bytes), 5); + bytes = dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_4_5.getValue()); + Assert.assertEquals(getSum(bytes), 4); + } + + @Test + public void testCheck() { + byte[] stats1 = {0, 0, 0, 0, 0}; + byte[] stats2 = {1, 1, 1, 1, 1}; + + for (Parameter.ForkBlockVersionEnum version : Parameter.ForkBlockVersionEnum.values()) { + dynamicPropertiesStore.statsByVersion(version.getValue(), stats1); + } + + dynamicPropertiesStore + .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_3_5.getValue(), stats2); + + forkController.checkLocalVersion(); + + Assert.assertEquals(dynamicPropertiesStore.getLatestVersion(), + Parameter.ForkBlockVersionEnum.VERSION_3_5.getValue()); + + + Args.getInstance().setVersionCheckEnable(false); + dynamicPropertiesStore.saveLatestVersion(Integer.MAX_VALUE); + + forkController.checkLocalVersion(); + + Args.getInstance().setVersionCheckEnable(true); + + try { + forkController.checkLocalVersion(); + Assert.fail(); + } catch (Exception e) { + Assert.assertTrue(e instanceof RuntimeException); + } + } + + private BlockCapsule getBlock(int i, Parameter.ForkBlockVersionEnum versionEnum) { + org.tron.protos.Protocol.BlockHeader.raw rawData = + org.tron.protos.Protocol.BlockHeader.raw.newBuilder() + .setVersion(versionEnum.getValue()) + .setWitnessAddress(ByteString.copyFrom(getBytes(i))) + .build(); + + Protocol.BlockHeader blockHeader = Protocol.BlockHeader.newBuilder() + .setRawData(rawData).build(); + + Protocol.Block block = Protocol.Block.newBuilder().setBlockHeader(blockHeader).build(); + + return new BlockCapsule(block); + } + + private int getSum(byte[] bytes) { + int sum = 0; + for (byte aByte : bytes) { + sum += aByte; + } + return sum; + } + + private byte[] getBytes(int i) { + byte[] bytes = new byte[21]; + bytes[i] = 1; + return bytes; + } + + @After + public void removeDb() { + Args.clearParam(); + context.destroy(); + FileUtil.deleteDir(new File(dbPath)); + } + +} From 406c13d813553dcd479cd9c9a887d9c9a0e11eb6 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 1 Jun 2023 19:24:26 +0800 Subject: [PATCH 0790/1197] feat(net):update com.google.protobuf and io.grpc version --- build.gradle | 12 ++++++------ framework/build.gradle | 4 ++-- protocol/build.gradle | 11 +++++------ 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index a4d23e2184e..d58e37743e9 100644 --- a/build.gradle +++ b/build.gradle @@ -70,12 +70,12 @@ subprojects { resolutionStrategy { force group: 'com.google.guava', name: 'guava', version: '30.1-jre' } - resolutionStrategy.eachDependency { details -> - // TODO if update grpc remove - if(details.requested.group == 'io.netty') { - details.useVersion "4.1.27.Final" - } - } + //resolutionStrategy.eachDependency { details -> + // // TODO if update grpc remove + // if(details.requested.group == 'io.netty') { + // details.useVersion "4.1.27.Final" + // } + //} } } diff --git a/framework/build.gradle b/framework/build.gradle index fbe1fc0308b..5f1d9ba9d7e 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -67,8 +67,8 @@ dependencies { compile group: 'com.carrotsearch', name: 'java-sizeof', version: '0.0.5' - compile 'com.googlecode.cqengine:cqengine:2.12.4' - compile group: 'com.google.api.grpc', name: 'googleapis-common-protos', version: '0.0.3' + //compile 'com.googlecode.cqengine:cqengine:2.12.4' + compile group: 'com.google.api.grpc', name: 'proto-google-common-protos', version: '2.15.0' // http compile 'org.eclipse.jetty:jetty-server:9.4.49.v20220914' diff --git a/protocol/build.gradle b/protocol/build.gradle index acdb7f15187..2fe23a84e03 100644 --- a/protocol/build.gradle +++ b/protocol/build.gradle @@ -1,8 +1,7 @@ apply plugin: 'com.google.protobuf' -def protobufVersion = "3.19.2" - -def grpcVersion = "1.14.0" +def grpcVersion = '1.52.1' // CURRENT_GRPC_VERSION +def protobufVersion = '3.21.12' dependencies { compile group: 'com.google.protobuf', name: 'protobuf-java', version: protobufVersion @@ -16,7 +15,7 @@ dependencies { compile group: 'io.grpc', name: 'grpc-stub', version: grpcVersion // end google grpc - compile group: 'com.google.api.grpc', name: 'googleapis-common-protos', version: '0.0.3' + compile group: 'com.google.api.grpc', name: 'proto-google-common-protos', version: '2.15.0' } tasks.matching { it instanceof Test }.all { @@ -39,12 +38,12 @@ sourceSets { protobuf { generatedFilesBaseDir = "$projectDir/src/" protoc { - artifact = "com.google.protobuf:protoc:3.5.1-1" + artifact = "com.google.protobuf:protoc:${protobufVersion}" } plugins { grpc { - artifact = 'io.grpc:protoc-gen-grpc-java:1.9.0' + artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" } } generateProtoTasks { From fc1d238ebc236ce200c52035079d9e78cecb8c75 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 1 Jun 2023 19:36:31 +0800 Subject: [PATCH 0791/1197] feat(net): update protocol/build.gradle --- protocol/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/build.gradle b/protocol/build.gradle index 2fe23a84e03..e790e480fa0 100644 --- a/protocol/build.gradle +++ b/protocol/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.google.protobuf' -def grpcVersion = '1.52.1' // CURRENT_GRPC_VERSION def protobufVersion = '3.21.12' +def grpcVersion = '1.52.1' dependencies { compile group: 'com.google.protobuf', name: 'protobuf-java', version: protobufVersion From 266fbf989e51ec214e0be18451795069c5c3de03 Mon Sep 17 00:00:00 2001 From: vikingzzu Date: Fri, 2 Jun 2023 11:43:32 +0800 Subject: [PATCH 0792/1197] fix refetch block logic --- .../service/fetchblock/FetchBlockService.java | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java b/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java index de20a17af0b..c135782c42b 100644 --- a/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java +++ b/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java @@ -41,9 +41,6 @@ public class FetchBlockService { private final long fetchTimeOut = CommonParameter.getInstance().fetchBlockTimeout; - private static final int BLOCK_FETCH_TIME_OUT_LIMIT = - 2 * Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; - private static final double BLOCK_FETCH_LEFT_TIME_PERCENT = 0.5; private final ScheduledExecutorService fetchBlockWorkerExecutor = @@ -76,13 +73,10 @@ public void fetchBlock(List sha256HashList, PeerConnection peer) { sha256HashList.stream().filter(sha256Hash -> new BlockCapsule.BlockId(sha256Hash).getNum() == chainBaseManager.getHeadBlockNum() + 1) .findFirst().ifPresent(sha256Hash -> { - if (System.currentTimeMillis() - chainBaseManager.getHeadBlockTimeStamp() - < BLOCK_FETCH_TIME_OUT_LIMIT) { - fetchBlockInfo = new FetchBlockInfo(sha256Hash, peer, System.currentTimeMillis()); - logger.info("Set fetchBlockInfo, block: {}, peer: {}, time: {}", sha256Hash, - fetchBlockInfo.getPeer().getInetAddress(), fetchBlockInfo.getTime()); - } - }); + fetchBlockInfo = new FetchBlockInfo(sha256Hash, peer, System.currentTimeMillis()); + logger.info("Set fetchBlockInfo, block: {}, peer: {}, time: {}", sha256Hash, + fetchBlockInfo.getPeer().getInetAddress(), fetchBlockInfo.getTime()); + }); } @@ -99,13 +93,6 @@ private void fetchBlockProcess(FetchBlockInfo fetchBlock) { if (null == fetchBlock) { return; } - if (System.currentTimeMillis() - chainBaseManager.getHeadBlockTimeStamp() - >= BLOCK_FETCH_TIME_OUT_LIMIT) { - this.fetchBlockInfo = null; - logger.info("Clear fetchBlockInfo due to {} ms past head block time", - BLOCK_FETCH_TIME_OUT_LIMIT); - return; - } Item item = new Item(fetchBlock.getHash(), InventoryType.BLOCK); Optional optionalPeerConnection = tronNetDelegate.getActivePeer().stream() .filter(PeerConnection::isIdle) From 5f5b537aafcb54315351f5a353411f74c2f3a9bd Mon Sep 17 00:00:00 2001 From: vikingzzu Date: Fri, 2 Jun 2023 12:17:34 +0800 Subject: [PATCH 0793/1197] format code style --- .../tron/core/net/service/fetchblock/FetchBlockService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java b/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java index c135782c42b..690e9f17099 100644 --- a/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java +++ b/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java @@ -73,10 +73,10 @@ public void fetchBlock(List sha256HashList, PeerConnection peer) { sha256HashList.stream().filter(sha256Hash -> new BlockCapsule.BlockId(sha256Hash).getNum() == chainBaseManager.getHeadBlockNum() + 1) .findFirst().ifPresent(sha256Hash -> { - fetchBlockInfo = new FetchBlockInfo(sha256Hash, peer, System.currentTimeMillis()); - logger.info("Set fetchBlockInfo, block: {}, peer: {}, time: {}", sha256Hash, + fetchBlockInfo = new FetchBlockInfo(sha256Hash, peer, System.currentTimeMillis()); + logger.info("Set fetchBlockInfo, block: {}, peer: {}, time: {}", sha256Hash, fetchBlockInfo.getPeer().getInetAddress(), fetchBlockInfo.getTime()); - }); + }); } From a6e34cd3c96d610bfa4353c4456d46bf7782d80e Mon Sep 17 00:00:00 2001 From: vikingzzu Date: Fri, 2 Jun 2023 12:30:30 +0800 Subject: [PATCH 0794/1197] format code style --- .../org/tron/core/net/service/fetchblock/FetchBlockService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java b/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java index 690e9f17099..6a5b120a896 100644 --- a/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java +++ b/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java @@ -75,7 +75,7 @@ public void fetchBlock(List sha256HashList, PeerConnection peer) { .findFirst().ifPresent(sha256Hash -> { fetchBlockInfo = new FetchBlockInfo(sha256Hash, peer, System.currentTimeMillis()); logger.info("Set fetchBlockInfo, block: {}, peer: {}, time: {}", sha256Hash, - fetchBlockInfo.getPeer().getInetAddress(), fetchBlockInfo.getTime()); + fetchBlockInfo.getPeer().getInetAddress(), fetchBlockInfo.getTime()); }); } From 36054e7ac5c22c8320a0b6aa297eb9a9924d4c13 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Fri, 2 Jun 2023 10:49:06 +0800 Subject: [PATCH 0795/1197] feat(freezeV2): optimize delegate resource lock period --- .../actuator/DelegateResourceActuator.java | 70 +++- .../org/tron/core/utils/ProposalUtil.java | 19 +- .../org/tron/core/utils/TransactionUtil.java | 7 +- .../core/store/DynamicPropertiesStore.java | 31 +- .../common/parameter/CommonParameter.java | 4 + .../java/org/tron/core/config/Parameter.java | 1 + .../src/main/java/org/tron/core/Wallet.java | 5 + .../tron/core/consensus/ProposalService.java | 7 + .../http/DelegateResourceServlet.java | 4 +- .../test/java/org/tron/core/WalletTest.java | 17 +- .../DelegateResourceActuatorTest.java | 383 ++++++++++++++---- .../actuator/utils/TransactionUtilTest.java | 119 ++++-- .../core/contract/balance_contract.proto | 1 + 13 files changed, 511 insertions(+), 157 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index f91c147e3ee..d7dfcd5da14 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -2,7 +2,11 @@ import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; +import static org.tron.core.config.Parameter.ChainConstant.MAX_BLOCK_NUM_DELEGATE_PERIOD; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; @@ -46,8 +50,10 @@ public boolean execute(Object result) throws ContractExeException { long fee = calcFee(); final DelegateResourceContract delegateResourceContract; AccountStore accountStore = chainBaseManager.getAccountStore(); + byte[] ownerAddress; try { - delegateResourceContract = any.unpack(DelegateResourceContract.class); + delegateResourceContract = this.any.unpack(DelegateResourceContract.class); + ownerAddress = getOwnerAddress().toByteArray(); } catch (InvalidProtocolBufferException e) { logger.debug(e.getMessage(), e); ret.setStatus(fee, code.FAILED); @@ -59,21 +65,21 @@ public boolean execute(Object result) throws ContractExeException { long delegateBalance = delegateResourceContract.getBalance(); boolean lock = delegateResourceContract.getLock(); - byte[] ownerAddress = delegateResourceContract.getOwnerAddress().toByteArray(); + long lockPeriod = delegateResourceContract.getLockPeriod(); byte[] receiverAddress = delegateResourceContract.getReceiverAddress().toByteArray(); // delegate resource to receiver switch (delegateResourceContract.getResource()) { case BANDWIDTH: delegateResource(ownerAddress, receiverAddress, true, - delegateBalance, lock); + delegateBalance, lock, lockPeriod); ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(delegateBalance); ownerCapsule.addFrozenBalanceForBandwidthV2(-delegateBalance); break; case ENERGY: delegateResource(ownerAddress, receiverAddress, false, - delegateBalance, lock); + delegateBalance, lock, lockPeriod); ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(delegateBalance); ownerCapsule.addFrozenBalanceForEnergyV2(-delegateBalance); @@ -100,6 +106,7 @@ public boolean validate() throws ContractValidateException { } AccountStore accountStore = chainBaseManager.getAccountStore(); DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore(); if (!any.is(DelegateResourceContract.class)) { throw new ContractValidateException( "contract type error,expected type [DelegateResourceContract],real type[" @@ -116,13 +123,14 @@ public boolean validate() throws ContractValidateException { } final DelegateResourceContract delegateResourceContract; + byte[] ownerAddress; try { delegateResourceContract = this.any.unpack(DelegateResourceContract.class); + ownerAddress = getOwnerAddress().toByteArray(); } catch (InvalidProtocolBufferException e) { logger.debug(e.getMessage(), e); throw new ContractValidateException(e.getMessage()); } - byte[] ownerAddress = delegateResourceContract.getOwnerAddress().toByteArray(); if (!DecodeUtil.addressValid(ownerAddress)) { throw new ContractValidateException("Invalid address"); } @@ -210,6 +218,36 @@ public boolean validate() throws ContractValidateException { + readableOwnerAddress + NOT_EXIST_STR); } + boolean lock = delegateResourceContract.getLock(); + if (lock && dynamicStore.supportAllowOptimizeLockDelegateResource()) { + long lockPeriod = delegateResourceContract.getLockPeriod(); + if (lockPeriod < 0 || lockPeriod > MAX_BLOCK_NUM_DELEGATE_PERIOD) { + throw new ContractValidateException( + "The lock period of delegate resource cannot be less than 0 and cannot exceed 1 year!"); + } + + byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, true); + DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore.get(key); + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + if (delegatedResourceCapsule != null) { + switch (delegateResourceContract.getResource()) { + case BANDWIDTH: { + validRemainTime(BANDWIDTH, lockPeriod, + delegatedResourceCapsule.getExpireTimeForBandwidth(), now); + } + break; + case ENERGY: { + validRemainTime(ENERGY, lockPeriod, + delegatedResourceCapsule.getExpireTimeForEnergy(), now); + } + break; + default: + throw new ContractValidateException( + "ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]"); + } + } + } + if (receiverCapsule.getType() == AccountType.Contract) { throw new ContractValidateException( "Do not allow delegate resources to contract addresses"); @@ -218,6 +256,17 @@ public boolean validate() throws ContractValidateException { return true; } + private void validRemainTime(ResourceCode resourceCode, long lockPeriod, long expireTime, + long now) throws ContractValidateException { + long remainTime = expireTime - now; + if (lockPeriod * 3 * 1000 < remainTime) { + throw new ContractValidateException( + "The lock period for " + resourceCode.name() + " this time cannot be less than the " + + "remaining time[" + remainTime + "s] of the last lock period for " + + resourceCode.name() + "!"); + } + } + @Override public ByteString getOwnerAddress() throws InvalidProtocolBufferException { return any.unpack(DelegateResourceContract.class).getOwnerAddress(); @@ -229,7 +278,7 @@ public long calcFee() { } private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boolean isBandwidth, - long balance, boolean lock) { + long balance, boolean lock, long lockPeriod) { AccountStore accountStore = chainBaseManager.getAccountStore(); DynamicPropertiesStore dynamicPropertiesStore = chainBaseManager.getDynamicPropertiesStore(); DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore(); @@ -241,12 +290,15 @@ private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boole delegatedResourceStore.unLockExpireResource(ownerAddress, receiverAddress, now); //modify DelegatedResourceStore - byte[] key; long expireTime = 0; if (lock) { - expireTime = now + DELEGATE_PERIOD; + if (dynamicPropertiesStore.supportAllowOptimizeLockDelegateResource()) { + expireTime = now + (lockPeriod == 0 ? DELEGATE_PERIOD : lockPeriod * 3 * 1000); + } else { + expireTime = now + DELEGATE_PERIOD; + } } - key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, lock); + byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, lock); DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore.get(key); if (delegatedResourceCapsule == null) { delegatedResourceCapsule = new DelegatedResourceCapsule(ByteString.copyFrom(ownerAddress), diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 9ab68cc1925..0fdb9234bad 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -692,6 +692,22 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7_2)) { + throw new ContractValidateException( + "Bad chain parameter id [ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE]"); + } + if (value != 1) { + throw new ContractValidateException( + "This value[ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE] is only allowed to be 1"); + } + if (dynamicPropertiesStore.getUnfreezeDelayDays() == 0) { + throw new ContractValidateException( + "[UNFREEZE_DELAY_DAYS] proposal must be approved " + + "before [ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE] can be proposed"); + } + break; + } default: break; } @@ -765,7 +781,8 @@ public enum ProposalType { // current value, value range DYNAMIC_ENERGY_THRESHOLD(73), // 0, [0, LONG] DYNAMIC_ENERGY_INCREASE_FACTOR(74), // 0, [0, 10_000] DYNAMIC_ENERGY_MAX_FACTOR(75), // 0, [0, 100_000] - ALLOW_TVM_SHANGHAI(76); // 0, 1 + ALLOW_TVM_SHANGHAI(76), // 0, 1 + ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE(78); // 0, 1 private long code; diff --git a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java index e5cffa49790..e8fe963f89b 100644 --- a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java @@ -17,6 +17,7 @@ import static org.tron.common.crypto.Hash.sha3omit12; import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_COST_BASE_SIZE; +import static org.tron.core.config.Parameter.ChainConstant.MAX_BLOCK_NUM_DELEGATE_PERIOD; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import com.google.common.base.CaseFormat; @@ -279,11 +280,11 @@ public static long consumeBandWidthSize( } - public static long estimateConsumeBandWidthSize( - final AccountCapsule ownerCapsule, - ChainBaseManager chainBaseManager) { + public static long estimateConsumeBandWidthSize(final AccountCapsule ownerCapsule, + ChainBaseManager chainBaseManager) { DelegateResourceContract.Builder builder = DelegateResourceContract.newBuilder() .setLock(true) + .setLockPeriod(MAX_BLOCK_NUM_DELEGATE_PERIOD) .setBalance(ownerCapsule.getFrozenV2BalanceForBandwidth()); TransactionCapsule fakeTransactionCapsule = new TransactionCapsule(builder.build() , ContractType.DelegateResourceContract); diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 001282a0de8..c797c113c77 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -14,7 +14,6 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; import org.tron.core.capsule.BytesCapsule; -import org.tron.core.config.Parameter; import org.tron.core.config.Parameter.ChainConstant; import org.tron.core.db.TronStoreWithRevoking; import org.tron.core.exception.BadItemException; @@ -208,6 +207,9 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_TVM_SHANGHAI = "ALLOW_TVM_SHANGHAI".getBytes(); + private static final byte[] ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE = + "ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE".getBytes(); + @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { super(dbName); @@ -2192,7 +2194,7 @@ public long getNextMaintenanceTime() { } public long getMaintenanceSkipSlots() { - return Parameter.ChainConstant.MAINTENANCE_SKIP_SLOTS; + return ChainConstant.MAINTENANCE_SKIP_SLOTS; } public void saveNextMaintenanceTime(long nextMaintenanceTime) { @@ -2218,6 +2220,9 @@ public void updateNextMaintenanceTime(long blockTime) { //The unit is trx public void addTotalNetWeight(long amount) { + if (amount == 0) { + return; + } long totalNetWeight = getTotalNetWeight(); totalNetWeight += amount; if (allowNewReward()) { @@ -2228,6 +2233,9 @@ public void addTotalNetWeight(long amount) { //The unit is trx public void addTotalEnergyWeight(long amount) { + if (amount == 0) { + return; + } long totalEnergyWeight = getTotalEnergyWeight(); totalEnergyWeight += amount; if (allowNewReward()) { @@ -2238,6 +2246,9 @@ public void addTotalEnergyWeight(long amount) { //The unit is trx public void addTotalTronPowerWeight(long amount) { + if (amount == 0) { + return; + } long totalWeight = getTotalTronPowerWeight(); totalWeight += amount; if (allowNewReward()) { @@ -2769,6 +2780,22 @@ public long getAllowTvmShangHai() { .orElse(CommonParameter.getInstance().getAllowTvmShangHai()); } + public void saveAllowOptimizeLockDelegateResource(long allowOptimizeLockDelegateResource) { + this.put(DynamicPropertiesStore.ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE, + new BytesCapsule(ByteArray.fromLong(allowOptimizeLockDelegateResource))); + } + + public long getAllowOptimizeLockDelegateResource() { + return Optional.ofNullable(getUnchecked(ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElse(CommonParameter.getInstance().getAllowOptimizeLockDelegateResource()); + } + + public boolean supportAllowOptimizeLockDelegateResource() { + return getAllowOptimizeLockDelegateResource() == 1L && getUnfreezeDelayDays() > 0; + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index ef89e01925a..71836c64a40 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -651,6 +651,10 @@ public class CommonParameter { @Setter public long allowTvmShangHai; + @Getter + @Setter + public long allowOptimizeLockDelegateResource; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index 5a170577b99..822a79896cc 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -74,6 +74,7 @@ public class ChainConstant { public static final int BLOCK_VERSION = 28; public static final long FROZEN_PERIOD = 86_400_000L; public static final long DELEGATE_PERIOD = 3 * 86_400_000L; + public static final long MAX_BLOCK_NUM_DELEGATE_PERIOD = 10512000L; public static final long TRX_PRECISION = 1000_000L; public static final long DELEGATE_COST_BASE_SIZE = 275L; } diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index a836b15d59d..c5989e19266 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1325,6 +1325,11 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getAllowTvmShangHai()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getAllowOptimizeLockDelegateResource") + .setValue(dbManager.getDynamicPropertiesStore().getAllowOptimizeLockDelegateResource()) + .build()); + return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 4ca90eae640..f376de4917c 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -343,6 +343,13 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveAllowTvmShangHai(entry.getValue()); break; } + case ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE: { + if (manager.getDynamicPropertiesStore().getAllowOptimizeLockDelegateResource() == 0) { + manager.getDynamicPropertiesStore() + .saveAllowOptimizeLockDelegateResource(entry.getValue()); + } + break; + } default: find = false; break; diff --git a/framework/src/main/java/org/tron/core/services/http/DelegateResourceServlet.java b/framework/src/main/java/org/tron/core/services/http/DelegateResourceServlet.java index 221cc34cf7c..00994238988 100644 --- a/framework/src/main/java/org/tron/core/services/http/DelegateResourceServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/DelegateResourceServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -18,6 +19,7 @@ public class DelegateResourceServlet extends RateLimiterServlet { @Autowired private Wallet wallet; + @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { try { PostParams params = PostParams.getPostParams(request); @@ -26,7 +28,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.DelegateResourceContract) .getInstance(); - JSONObject jsonObject = JSONObject.parseObject(params.getParams()); + JSONObject jsonObject = JSON.parseObject(params.getParams()); tx = Util.setTransactionPermissionId(jsonObject, tx); response.getWriter().println(Util.printCreateTransaction(tx, params.isVisible())); } catch (Exception e) { diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 88fa7b6f8f9..b487a0f8421 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -363,6 +363,7 @@ public void testGetEcKey() { public void ss() { for (int i = 0; i < 4; i++) { ECKey ecKey = new ECKey(Utils.getRandom()); + assertNotNull(ecKey); System.out.println(i + 1); System.out.println("privateKey:" + ByteArray.toHexString(ecKey.getPrivKeyBytes())); System.out.println("publicKey:" + ByteArray.toHexString(ecKey.getPubKey())); @@ -483,14 +484,14 @@ public void getPaginatedAssetIssueList() { AssetIssueList assetList1 = wallet.getAssetIssueList(0, 100); assertEquals("get Asset1", assetList1.getAssetIssue(0).getName(), Asset1.getName()); try { - assetList1.getAssetIssue(1); + assertNotNull(assetList1.getAssetIssue(1)); } catch (Exception e) { Assert.assertTrue("AssetIssueList1 size should be 1", true); } AssetIssueList assetList2 = wallet.getAssetIssueList(0, 0); try { - assetList2.getAssetIssue(0); + assertNotNull(assetList2.getAssetIssue(0)); } catch (Exception e) { Assert.assertTrue("AssetIssueList2 size should be 0", true); } @@ -615,12 +616,8 @@ public void testGetDelegatedResource() { delegatedResourceList.getDelegatedResource(0).getFrozenBalanceForBandwidth()); Assert.assertEquals(0L, delegatedResourceList.getDelegatedResource(0).getExpireTimeForBandwidth()); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); } catch (Exception e) { - Assert.assertEquals(false, true); + Assert.fail(); } } @@ -794,7 +791,7 @@ public void testGetCanDelegatedMaxSizeBandWidth() { GrpcAPI.CanDelegatedMaxSizeResponseMessage message = wallet.getCanDelegatedMaxSize( ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), BANDWIDTH.getNumber()); - Assert.assertEquals(initBalance - 280L, message.getMaxSize()); + Assert.assertEquals(initBalance - 285L, message.getMaxSize()); } @@ -1054,13 +1051,13 @@ public void testEstimateEnergyOutOfTime() { @Test public void testListNodes() { try { - GrpcAPI.NodeList nodeList = wallet.listNodes(); + wallet.listNodes(); } catch (Exception e) { Assert.assertTrue(e instanceof NullPointerException); } Args.getInstance().setP2pDisable(true); GrpcAPI.NodeList nodeList = wallet.listNodes(); - Assert.assertTrue(nodeList.getNodesList().size() == 0); + assertEquals(0, nodeList.getNodesList().size()); } } diff --git a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java index afbe6895bb9..a232729d3de 100644 --- a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java @@ -1,6 +1,13 @@ package org.tron.core.actuator; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; +import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; import com.google.protobuf.Any; import com.google.protobuf.ByteString; @@ -23,8 +30,8 @@ import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.AssetIssueContractOuterClass; +import org.tron.protos.contract.BalanceContract; import org.tron.protos.contract.BalanceContract.DelegateResourceContract; -import org.tron.protos.contract.Common.ResourceCode; @Slf4j public class DelegateResourceActuatorTest extends BaseTest { @@ -108,18 +115,40 @@ private Any getLockedDelegateContractForBandwidth(String ownerAddress, String re .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiveAddress))) .setBalance(unfreezeBalance) - .setResource(ResourceCode.BANDWIDTH) + .setResource(BANDWIDTH) .setLock(lock) .build()); } + private Any getOptimizeLockedDelegateContractForBandwidth(long unfreezeBalance, long lockPeriod) { + return Any.pack(DelegateResourceContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))) + .setBalance(unfreezeBalance) + .setResource(BANDWIDTH) + .setLock(true) + .setLockPeriod(lockPeriod) + .build()); + } + + private Any getOptimizeLockedDelegateContractForEnergy(long unfreezeBalance, long lockPeriod) { + return Any.pack(DelegateResourceContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))) + .setBalance(unfreezeBalance) + .setResource(ENERGY) + .setLock(true) + .setLockPeriod(lockPeriod) + .build()); + } + private Any getDelegateContractForCpu(long unfreezeBalance) { return Any.pack( DelegateResourceContract.newBuilder() .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))) .setBalance(unfreezeBalance) - .setResource(ResourceCode.ENERGY) + .setResource(ENERGY) .build()); } @@ -129,7 +158,7 @@ private Any getDelegateContractForTronPower(long unfreezeBalance) { .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))) .setBalance(unfreezeBalance) - .setResource(ResourceCode.TRON_POWER) + .setResource(TRON_POWER) .build()); } @@ -147,12 +176,12 @@ public void testDelegateResourceWithNoFreeze() { try { actuator.validate(); actuator.execute(ret); - Assert.fail("cannot run here."); + fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertEquals("delegateBalance must be less than available FreezeBandwidthV2 balance", + assertEquals("delegateBalance must be less than available FreezeBandwidthV2 balance", e.getMessage()); } catch (ContractExeException e) { - Assert.fail(); + fail(); } actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( @@ -160,13 +189,13 @@ public void testDelegateResourceWithNoFreeze() { try { actuator.validate(); actuator.execute(ret); - Assert.fail("cannot run here."); + fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertEquals( + assertEquals( "delegateBalance must be less than available FreezeEnergyV2 balance", e.getMessage()); } catch (ContractExeException e) { - Assert.fail(e.getMessage()); + fail(e.getMessage()); } } @@ -190,16 +219,15 @@ public void testDelegateBandwidthWithUsage() { try { actuator.validate(); actuator.execute(ret); - Assert.fail("cannot run here."); + fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertEquals("delegateBalance must be less than available FreezeBandwidthV2 balance", + assertEquals("delegateBalance must be less than available FreezeBandwidthV2 balance", e.getMessage()); } catch (ContractExeException e) { - Assert.fail(e.getMessage()); + fail(e.getMessage()); } } - @Test public void testDelegateCpuWithUsage() { freezeCpuForOwner(); @@ -220,13 +248,13 @@ public void testDelegateCpuWithUsage() { try { actuator.validate(); actuator.execute(ret); - Assert.fail("cannot run here."); + fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertEquals( + assertEquals( "delegateBalance must be less than available FreezeEnergyV2 balance", e.getMessage()); } catch (ContractExeException e) { - Assert.fail(e.getMessage()); + fail(e.getMessage()); } } @@ -252,9 +280,9 @@ public void testDelegateResourceWithContractAddress() { actuator.validate(); actuator.execute(ret); } catch (ContractValidateException e) { - Assert.assertEquals("Do not allow delegate resources to contract addresses", e.getMessage()); + assertEquals("Do not allow delegate resources to contract addresses", e.getMessage()); } catch (ContractExeException e) { - Assert.fail(e.getMessage()); + fail(e.getMessage()); } } @@ -271,9 +299,9 @@ public void testDelegateResourceToSelf() { actuator.validate(); actuator.execute(ret); } catch (ContractValidateException e) { - Assert.assertEquals("receiverAddress must not be the same as ownerAddress", e.getMessage()); + assertEquals("receiverAddress must not be the same as ownerAddress", e.getMessage()); } catch (ContractExeException e) { - Assert.fail(e.getMessage()); + fail(e.getMessage()); } } @@ -292,48 +320,48 @@ public void testDelegateResourceForBandwidth() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); + assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); - Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); - Assert.assertEquals(initBalance - delegateBalance, + assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); + assertEquals(initBalance - delegateBalance, ownerCapsule.getFrozenV2BalanceForBandwidth()); - Assert.assertEquals(initBalance, ownerCapsule.getTronPower()); + assertEquals(initBalance, ownerCapsule.getTronPower()); AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); - Assert.assertEquals(delegateBalance, + assertEquals(delegateBalance, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); - Assert.assertEquals(0L, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy()); - Assert.assertEquals(0L, receiverCapsule.getTronPower()); + assertEquals(0L, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy()); + assertEquals(0L, receiverCapsule.getTronPower()); DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore() .get(DelegatedResourceCapsule .createDbKeyV2(ByteArray.fromHexString(OWNER_ADDRESS), ByteArray.fromHexString(RECEIVER_ADDRESS), false)); - Assert.assertEquals(delegateBalance, delegatedResourceCapsule.getFrozenBalanceForBandwidth()); + assertEquals(delegateBalance, delegatedResourceCapsule.getFrozenBalanceForBandwidth()); long totalNetWeightAfter = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); - Assert.assertEquals(totalNetWeightBefore, totalNetWeightAfter); + assertEquals(totalNetWeightBefore, totalNetWeightAfter); //check DelegatedResourceAccountIndex DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager .getDelegatedResourceAccountIndexStore().getV2Index(owner); - Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); - Assert.assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); - Assert.assertTrue(ownerIndexCapsule.getToAccountsList() + assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); + assertTrue(ownerIndexCapsule.getToAccountsList() .contains(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)))); DelegatedResourceAccountIndexCapsule receiveCapsule = dbManager .getDelegatedResourceAccountIndexStore().getV2Index(receiver); - Assert.assertEquals(0, receiveCapsule.getToAccountsList().size()); - Assert.assertEquals(1, receiveCapsule.getFromAccountsList().size()); - Assert.assertTrue(receiveCapsule.getFromAccountsList() + assertEquals(0, receiveCapsule.getToAccountsList().size()); + assertEquals(1, receiveCapsule.getFromAccountsList().size()); + assertTrue(receiveCapsule.getFromAccountsList() .contains(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)))); } catch (ContractValidateException | ContractExeException e) { - Assert.fail(e.getMessage()); + fail(e.getMessage()); } } @@ -353,22 +381,23 @@ public void testLockedDelegateResourceForBandwidth() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); + assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); - Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); - Assert.assertEquals(initBalance - delegateBalance, + assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); + assertEquals(initBalance - delegateBalance, ownerCapsule.getFrozenV2BalanceForBandwidth()); - Assert.assertEquals(initBalance, ownerCapsule.getTronPower()); + assertEquals(initBalance, ownerCapsule.getTronPower()); AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); - Assert.assertEquals(delegateBalance, + assertEquals(delegateBalance, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); - Assert.assertEquals(0L, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy()); - Assert.assertEquals(0L, receiverCapsule.getTronPower()); + assertEquals(0L, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy()); + assertEquals(0L, receiverCapsule.getTronPower()); + //check DelegatedResource DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore() .get(DelegatedResourceCapsule .createDbKeyV2(ByteArray.fromHexString(OWNER_ADDRESS), @@ -380,30 +409,181 @@ public void testLockedDelegateResourceForBandwidth() { Assert.assertNull(delegatedResourceCapsule); Assert.assertNotNull(lockedResourceCapsule); Assert.assertNotEquals(0, lockedResourceCapsule.getExpireTimeForBandwidth()); - Assert.assertEquals(delegateBalance, lockedResourceCapsule.getFrozenBalanceForBandwidth()); + assertEquals(delegateBalance, lockedResourceCapsule.getFrozenBalanceForBandwidth()); long totalNetWeightAfter = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); - Assert.assertEquals(totalNetWeightBefore, totalNetWeightAfter); + assertEquals(totalNetWeightBefore, totalNetWeightAfter); //check DelegatedResourceAccountIndex DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager .getDelegatedResourceAccountIndexStore().getV2Index(owner); - Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); - Assert.assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); - Assert.assertTrue(ownerIndexCapsule.getToAccountsList() + assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); + assertTrue(ownerIndexCapsule.getToAccountsList() .contains(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)))); DelegatedResourceAccountIndexCapsule receiveCapsule = dbManager .getDelegatedResourceAccountIndexStore().getV2Index(receiver); - Assert.assertEquals(0, receiveCapsule.getToAccountsList().size()); - Assert.assertEquals(1, receiveCapsule.getFromAccountsList().size()); - Assert.assertTrue(receiveCapsule.getFromAccountsList() + assertEquals(0, receiveCapsule.getToAccountsList().size()); + assertEquals(1, receiveCapsule.getFromAccountsList().size()); + assertTrue(receiveCapsule.getFromAccountsList() .contains(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)))); } catch (ContractValidateException | ContractExeException e) { - Assert.fail(e.getMessage()); + fail(e.getMessage()); } } + @Test + public void testOptimizeLockedDelegateResourceForBandwidthWrongLockPeriod1() { + dbManager.getDynamicPropertiesStore().saveAllowOptimizeLockDelegateResource(1); + freezeBandwidthForOwner(); + long delegateBalance = 1_000_000_000L; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getOptimizeLockedDelegateContractForBandwidth( + delegateBalance, 370 * 24 * 3600)); + assertThrows("The lock period of delegate resources cannot exceed 1 year!", + ContractValidateException.class, actuator::validate); + } + + @Test + public void testOptimizeLockedDelegateResourceForBandwidthWrongLockPeriod2() { + dbManager.getDynamicPropertiesStore().saveAllowOptimizeLockDelegateResource(1); + freezeBandwidthForOwner(); + long delegateBalance = 1_000_000_000L; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getOptimizeLockedDelegateContractForBandwidth( + delegateBalance, 60)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + assertEquals(code.SUCESS, ret.getInstance().getRet()); + } catch (ContractValidateException | ContractExeException e) { + fail(e.getMessage()); + } + + DelegateResourceActuator actuator1 = new DelegateResourceActuator(); + actuator1.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getOptimizeLockedDelegateContractForBandwidth( + delegateBalance, 30)); + assertThrows("The lock period for bandwidth this time cannot be less than the remaining" + + " time[60000s] of the last lock period for bandwidth!", + ContractValidateException.class, actuator1::validate); + } + + @Test + public void testOptimizeLockedDelegateResourceForBandwidth() { + dbManager.getDynamicPropertiesStore().saveAllowOptimizeLockDelegateResource(1); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(50_000L); + freezeBandwidthForOwner(); + long delegateBalance = 1_000_000_000L; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getOptimizeLockedDelegateContractForBandwidth( + delegateBalance, 60)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + assertEquals(code.SUCESS, ret.getInstance().getRet()); + } catch (ContractValidateException | ContractExeException e) { + fail(e.getMessage()); + } + + DelegateResourceActuator actuator1 = new DelegateResourceActuator(); + actuator1.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getOptimizeLockedDelegateContractForBandwidth( + delegateBalance, 60)); + + TransactionResultCapsule ret1 = new TransactionResultCapsule(); + try { + actuator1.validate(); + actuator1.execute(ret1); + assertEquals(code.SUCESS, ret1.getInstance().getRet()); + } catch (ContractValidateException | ContractExeException e) { + fail(e.getMessage()); + } + DelegatedResourceCapsule lockedResourceCapsule = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule + .createDbKeyV2(ByteArray.fromHexString(OWNER_ADDRESS), + ByteArray.fromHexString(RECEIVER_ADDRESS), true)); + long expireTimeForBandwidth = lockedResourceCapsule.getExpireTimeForBandwidth(); + assertEquals(50_000L + 60 * 3 * 1000, expireTimeForBandwidth); + assertTrue(expireTimeForBandwidth > 60_000); + } + + @Test + public void testOptimizeLockedDelegateResourceForEnergy() { + dbManager.getDynamicPropertiesStore().saveAllowOptimizeLockDelegateResource(1); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(50_000L); + freezeCpuForOwner(); + long delegateBalance = 1_000_000_000L; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getOptimizeLockedDelegateContractForEnergy( + delegateBalance, 60)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + assertEquals(code.SUCESS, ret.getInstance().getRet()); + } catch (ContractValidateException | ContractExeException e) { + fail(e.getMessage()); + } + + DelegateResourceActuator actuator1 = new DelegateResourceActuator(); + actuator1.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getOptimizeLockedDelegateContractForEnergy( + delegateBalance, 60)); + + TransactionResultCapsule ret1 = new TransactionResultCapsule(); + try { + actuator1.validate(); + actuator1.execute(ret1); + assertEquals(code.SUCESS, ret1.getInstance().getRet()); + } catch (ContractValidateException | ContractExeException e) { + fail(e.getMessage()); + } + DelegatedResourceCapsule lockedResourceCapsule = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule + .createDbKeyV2(ByteArray.fromHexString(OWNER_ADDRESS), + ByteArray.fromHexString(RECEIVER_ADDRESS), true)); + assertTrue(lockedResourceCapsule.getExpireTimeForEnergy() > 60_000); + } + + @Test + public void testOptimizeLockedDelegateResourceForEnergyWrongLockPeriod2() { + dbManager.getDynamicPropertiesStore().saveAllowOptimizeLockDelegateResource(1); + freezeCpuForOwner(); + long delegateBalance = 1_000_000_000L; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getOptimizeLockedDelegateContractForEnergy( + delegateBalance, 60)); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + assertEquals(code.SUCESS, ret.getInstance().getRet()); + } catch (ContractValidateException | ContractExeException e) { + fail(e.getMessage()); + } + + DelegateResourceActuator actuator1 = new DelegateResourceActuator(); + actuator1.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getOptimizeLockedDelegateContractForEnergy( + delegateBalance, 30)); + assertThrows("The lock period for energy this time cannot be less than the remaining" + + " time[60000s] of the last lock period for energy!", + ContractValidateException.class, actuator1::validate); + } + @Test public void testDelegateResourceForCpu() { freezeCpuForOwner(); @@ -419,53 +599,50 @@ public void testDelegateResourceForCpu() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); + assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); - Assert.assertEquals(initBalance, ownerCapsule.getBalance()); - Assert.assertEquals(0L, ownerCapsule.getFrozenBalance()); - Assert.assertEquals(0L, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); - Assert.assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForEnergy()); - Assert.assertEquals(initBalance, ownerCapsule.getTronPower()); + assertEquals(initBalance, ownerCapsule.getBalance()); + assertEquals(0L, ownerCapsule.getFrozenBalance()); + assertEquals(0L, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); + assertEquals(delegateBalance, ownerCapsule.getDelegatedFrozenV2BalanceForEnergy()); + assertEquals(initBalance, ownerCapsule.getTronPower()); AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); - Assert.assertEquals(0L, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); - Assert.assertEquals(delegateBalance, + assertEquals(0L, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); + assertEquals(delegateBalance, receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy()); - Assert.assertEquals(0L, receiverCapsule.getTronPower()); + assertEquals(0L, receiverCapsule.getTronPower()); DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore() .get(DelegatedResourceCapsule.createDbKeyV2(owner, receiver, false)); - Assert.assertEquals(0L, delegatedResourceCapsule.getFrozenBalanceForBandwidth()); - Assert.assertEquals(delegateBalance, delegatedResourceCapsule.getFrozenBalanceForEnergy()); + assertEquals(0L, delegatedResourceCapsule.getFrozenBalanceForBandwidth()); + assertEquals(delegateBalance, delegatedResourceCapsule.getFrozenBalanceForEnergy()); long totalEnergyWeightAfter = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); - Assert.assertEquals(totalEnergyWeightBefore, totalEnergyWeightAfter); + assertEquals(totalEnergyWeightBefore, totalEnergyWeightAfter); //check DelegatedResourceAccountIndex DelegatedResourceAccountIndexCapsule ownerIndexCapsule = dbManager .getDelegatedResourceAccountIndexStore().getV2Index(owner); - Assert - .assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); - Assert.assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); - Assert.assertTrue(ownerIndexCapsule.getToAccountsList() + assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + assertEquals(1, ownerIndexCapsule.getToAccountsList().size()); + assertTrue(ownerIndexCapsule.getToAccountsList() .contains(ByteString.copyFrom(receiver))); DelegatedResourceAccountIndexCapsule receiverIndexCapsule = dbManager .getDelegatedResourceAccountIndexStore().getV2Index(receiver); - Assert - .assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); - Assert - .assertEquals(1, + assertEquals(0, receiverIndexCapsule.getToAccountsList().size()); + assertEquals(1, receiverIndexCapsule.getFromAccountsList().size()); - Assert.assertTrue(receiverIndexCapsule.getFromAccountsList() + assertTrue(receiverIndexCapsule.getFromAccountsList() .contains(ByteString.copyFrom(owner))); } catch (ContractValidateException | ContractExeException e) { - Assert.fail(e.getMessage()); + fail(e.getMessage()); } } @@ -480,11 +657,11 @@ public void delegateLessThanZero() { try { actuator.validate(); actuator.execute(ret); - Assert.fail("cannot run here."); + fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertEquals("delegateBalance must be more than 1TRX", e.getMessage()); + assertEquals("delegateBalance must be more than 1TRX", e.getMessage()); } catch (ContractExeException e) { - Assert.fail(e.getMessage()); + fail(e.getMessage()); } } @@ -498,12 +675,12 @@ public void delegateTronPower() { try { actuator.validate(); actuator.execute(ret); - Assert.fail("cannot run here."); + fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertEquals("ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]", + assertEquals("ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]", e.getMessage()); } catch (ContractExeException e) { - Assert.fail(e.getMessage()); + fail(e.getMessage()); } } @@ -518,12 +695,12 @@ public void delegateMoreThanBalance() { try { actuator.validate(); actuator.execute(ret); - Assert.fail("cannot run here."); + fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertEquals("delegateBalance must be less than available FreezeBandwidthV2 balance", + assertEquals("delegateBalance must be less than available FreezeBandwidthV2 balance", e.getMessage()); } catch (ContractExeException e) { - Assert.fail(e.getMessage()); + fail(e.getMessage()); } } @@ -538,15 +715,25 @@ public void invalidOwnerAddress() { try { actuator.validate(); actuator.execute(ret); - Assert.fail("cannot run here."); + fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertEquals("Invalid address", e.getMessage()); + assertEquals("Invalid address", e.getMessage()); } catch (ContractExeException e) { - Assert.fail(e.getMessage()); + fail(e.getMessage()); } } + @Test + public void invalidReceiverAddress() { + freezeBandwidthForOwner(); + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegateContractForBandwidth( + OWNER_ADDRESS, OWNER_ADDRESS_INVALID, 1_000_000_000L)); + assertThrows("Invalid receiverAddress", ContractValidateException.class, actuator::validate); + } + @Test public void invalidOwnerAccount() { DelegateResourceActuator actuator = new DelegateResourceActuator(); @@ -558,12 +745,12 @@ public void invalidOwnerAccount() { try { actuator.validate(); actuator.execute(ret); - Assert.fail("cannot run here."); + fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertEquals("Account[" + OWNER_ACCOUNT_INVALID + "] not exists", + assertEquals("Account[" + OWNER_ACCOUNT_INVALID + "] not exists", e.getMessage()); } catch (ContractExeException e) { - Assert.fail(e.getMessage()); + fail(e.getMessage()); } } @@ -588,4 +775,20 @@ public void commonErrorCheck() { actuatorTest.setNullDBManagerMsg("No account store or dynamic store!"); actuatorTest.nullDBManger(); } + + @Test + public void testErrorContract() { + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny(getErrorContract()); + assertThrows( + "contract type error, expected type [DelegateResourceContract], " + + "real type[WithdrawExpireUnfreezeContract]", + ContractValidateException.class, actuator::validate); + } + + private Any getErrorContract() { + return Any.pack(BalanceContract.WithdrawExpireUnfreezeContract.newBuilder().setOwnerAddress( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))).build() + ); + } } diff --git a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java index ad8846743e5..6bee877318a 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java @@ -1,22 +1,35 @@ package org.tron.core.actuator.utils; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.tron.core.capsule.utils.TransactionUtil.isNumber; +import static org.tron.core.utils.TransactionUtil.validAccountId; +import static org.tron.core.utils.TransactionUtil.validAccountName; +import static org.tron.core.utils.TransactionUtil.validAssetName; +import static org.tron.core.utils.TransactionUtil.validTokenAbbrName; +import com.google.protobuf.ByteString; import java.nio.charset.StandardCharsets; import lombok.extern.slf4j.Slf4j; +import org.junit.Before; import org.junit.BeforeClass; 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.config.args.Args; import org.tron.core.utils.TransactionUtil; +import org.tron.protos.Protocol.AccountType; @Slf4j(topic = "capsule") public class TransactionUtilTest extends BaseTest { + private static String OWNER_ADDRESS; + /** * Init . */ @@ -24,81 +37,96 @@ public class TransactionUtilTest extends BaseTest { public static void init() { dbPath = "output_transactionUtil_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + + } + + @Before + public void setUp() { + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + AccountCapsule ownerCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(owner), + AccountType.Normal, + 10_000_000_000L); + ownerCapsule.setFrozenForBandwidth(1000000L, 1000000L); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); } @Test public void validAccountNameCheck() { - String account = ""; - assertTrue(TransactionUtil.validAccountName(account.getBytes(StandardCharsets.UTF_8))); + StringBuilder account = new StringBuilder(); + assertTrue(validAccountName(account.toString().getBytes(StandardCharsets.UTF_8))); for (int i = 0; i < 200; i++) { - account += (char) ('a' + (i % 26)); + account.append((char) ('a' + (i % 26))); } - assertTrue(TransactionUtil.validAccountName(account.getBytes(StandardCharsets.UTF_8))); - account += 'z'; - assertFalse(TransactionUtil.validAccountName(account.getBytes(StandardCharsets.UTF_8))); + assertTrue(validAccountName(account.toString().getBytes(StandardCharsets.UTF_8))); + account.append('z'); + assertFalse(validAccountName(account.toString().getBytes(StandardCharsets.UTF_8))); } @Test public void validAccountIdCheck() { - String accountId = ""; - assertFalse(TransactionUtil.validAccountId(accountId.getBytes(StandardCharsets.UTF_8))); + StringBuilder accountId = new StringBuilder(); + assertFalse(validAccountId(accountId.toString().getBytes(StandardCharsets.UTF_8))); for (int i = 0; i < 7; i++) { - accountId += (char) ('a' + (i % 26)); + accountId.append((char) ('a' + (i % 26))); } - assertFalse(TransactionUtil.validAccountId(accountId.getBytes(StandardCharsets.UTF_8))); + assertFalse(validAccountId(accountId.toString().getBytes(StandardCharsets.UTF_8))); for (int i = 0; i < 26; i++) { - accountId += (char) ('a' + (i % 26)); + accountId.append((char) ('a' + (i % 26))); } - assertFalse(TransactionUtil.validAccountId(accountId.getBytes(StandardCharsets.UTF_8))); - accountId = "ab cdefghij"; - assertFalse(TransactionUtil.validAccountId(accountId.getBytes(StandardCharsets.UTF_8))); - accountId = (char) 128 + "abcdefjijk" + (char) 129; - assertFalse(TransactionUtil.validAccountId(accountId.getBytes(StandardCharsets.UTF_8))); - accountId = ""; + assertFalse(validAccountId(accountId.toString().getBytes(StandardCharsets.UTF_8))); + accountId = new StringBuilder("ab cdefghij"); + assertFalse(validAccountId(accountId.toString().getBytes(StandardCharsets.UTF_8))); + accountId = new StringBuilder((char) 128 + "abcdefjijk" + (char) 129); + assertFalse(validAccountId(accountId.toString().getBytes(StandardCharsets.UTF_8))); + accountId = new StringBuilder(); for (int i = 0; i < 30; i++) { - accountId += (char) ('a' + (i % 26)); + accountId.append((char) ('a' + (i % 26))); } - assertTrue(TransactionUtil.validAccountId(accountId.getBytes(StandardCharsets.UTF_8))); + assertTrue(validAccountId(accountId.toString().getBytes(StandardCharsets.UTF_8))); } @Test public void validAssetNameCheck() { - String assetName = ""; - assertFalse(TransactionUtil.validAssetName(assetName.getBytes(StandardCharsets.UTF_8))); + StringBuilder assetName = new StringBuilder(); + assertFalse(validAssetName(assetName.toString().getBytes(StandardCharsets.UTF_8))); for (int i = 0; i < 33; i++) { - assetName += (char) ('a' + (i % 26)); + assetName.append((char) ('a' + (i % 26))); } - assertFalse(TransactionUtil.validAssetName(assetName.getBytes(StandardCharsets.UTF_8))); - assetName = "ab cdefghij"; - assertFalse(TransactionUtil.validAssetName(assetName.getBytes(StandardCharsets.UTF_8))); - assetName = (char) 128 + "abcdefjijk" + (char) 129; - assertFalse(TransactionUtil.validAssetName(assetName.getBytes(StandardCharsets.UTF_8))); - assetName = ""; + assertFalse(validAssetName(assetName.toString().getBytes(StandardCharsets.UTF_8))); + assetName = new StringBuilder("ab cdefghij"); + assertFalse(validAssetName(assetName.toString().getBytes(StandardCharsets.UTF_8))); + assetName = new StringBuilder((char) 128 + "abcdefjijk" + (char) 129); + assertFalse(validAssetName(assetName.toString().getBytes(StandardCharsets.UTF_8))); + assetName = new StringBuilder(); for (int i = 0; i < 20; i++) { - assetName += (char) ('a' + (i % 26)); + assetName.append((char) ('a' + (i % 26))); } - assertTrue(TransactionUtil.validAssetName(assetName.getBytes(StandardCharsets.UTF_8))); + assertTrue(validAssetName(assetName.toString().getBytes(StandardCharsets.UTF_8))); } @Test public void validTokenAbbrNameCheck() { - String abbrName = ""; - assertFalse(TransactionUtil.validTokenAbbrName(abbrName.getBytes(StandardCharsets.UTF_8))); + StringBuilder abbrName = new StringBuilder(); + assertFalse(validTokenAbbrName(abbrName.toString().getBytes(StandardCharsets.UTF_8))); for (int i = 0; i < 6; i++) { - abbrName += (char) ('a' + (i % 26)); + abbrName.append((char) ('a' + (i % 26))); } - assertFalse(TransactionUtil.validTokenAbbrName(abbrName.getBytes(StandardCharsets.UTF_8))); - abbrName = "a bd"; - assertFalse(TransactionUtil.validTokenAbbrName(abbrName.getBytes(StandardCharsets.UTF_8))); - abbrName = "a" + (char) 129 + 'f'; - assertFalse(TransactionUtil.validTokenAbbrName(abbrName.getBytes(StandardCharsets.UTF_8))); - abbrName = ""; + assertFalse(validTokenAbbrName(abbrName.toString().getBytes(StandardCharsets.UTF_8))); + abbrName = new StringBuilder("a bd"); + assertFalse(validTokenAbbrName(abbrName.toString().getBytes(StandardCharsets.UTF_8))); + abbrName = new StringBuilder("a" + (char) 129 + 'f'); + assertFalse(validTokenAbbrName(abbrName.toString().getBytes(StandardCharsets.UTF_8))); + abbrName = new StringBuilder(); for (int i = 0; i < 5; i++) { - abbrName += (char) ('a' + (i % 26)); + abbrName.append((char) ('a' + (i % 26))); } - assertTrue(TransactionUtil.validTokenAbbrName(abbrName.getBytes(StandardCharsets.UTF_8))); + assertTrue(validTokenAbbrName(abbrName.toString().getBytes(StandardCharsets.UTF_8))); } @Test @@ -114,4 +142,13 @@ public void isNumberCheck() { assertTrue(isNumber(number.getBytes(StandardCharsets.UTF_8))); } + @Test + public void testEstimateConsumeBandWidthSize() { + AccountCapsule ownerCapsule = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + long estimateConsumeBandWidthSize = TransactionUtil.estimateConsumeBandWidthSize(ownerCapsule, + dbManager.getChainBaseManager()); + assertEquals(278L, estimateConsumeBandWidthSize); + } + } diff --git a/protocol/src/main/protos/core/contract/balance_contract.proto b/protocol/src/main/protos/core/contract/balance_contract.proto index 90a2dfaa48d..9c0bded1cbc 100644 --- a/protocol/src/main/protos/core/contract/balance_contract.proto +++ b/protocol/src/main/protos/core/contract/balance_contract.proto @@ -103,6 +103,7 @@ message DelegateResourceContract { int64 balance = 3; bytes receiver_address = 4; bool lock = 5; + int64 lock_period = 6; } message UnDelegateResourceContract { From 55ca979401f4599c6c4e9f47108c232b87815b9b Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Mon, 22 May 2023 14:38:20 +0800 Subject: [PATCH 0796/1197] feat(freezeV2): add cancel unfreezeV2 interface --- Tron protobuf protocol document.md | 2 + actuator/build.gradle | 2 +- .../actuator/CancelUnfreezeV2Actuator.java | 229 ++++++++++++++ .../org/tron/core/utils/ProposalUtil.java | 19 +- chainbase/build.gradle | 2 +- .../capsule/TransactionResultCapsule.java | 9 + .../core/capsule/utils/TransactionUtil.java | 1 + .../core/store/DynamicPropertiesStore.java | 31 +- common/build.gradle | 2 +- .../common/parameter/CommonParameter.java | 4 + consensus/build.gradle | 2 +- crypto/build.gradle | 2 +- framework/build.gradle | 4 +- .../src/main/java/org/tron/core/Wallet.java | 5 + .../tron/core/consensus/ProposalService.java | 8 + .../org/tron/core/services/RpcApiService.java | 8 + .../http/CancelUnfreezeV2Servlet.java | 38 +++ .../services/http/FullNodeHttpApiService.java | 4 + .../http/HttpSelfFormatFieldName.java | 2 + .../core/services/jsonrpc/JsonRpcApiUtil.java | 3 + .../AccountPermissionUpdateActuatorTest.java | 40 +-- .../CancelUnfreezeV2ActuatorTest.java | 295 ++++++++++++++++++ .../core/services/http/HttpServletTest.java | 3 + plugins/build.gradle | 2 +- protocol/src/main/protos/api/api.proto | 3 + protocol/src/main/protos/core/Tron.proto | 3 + .../core/contract/balance_contract.proto | 5 + 27 files changed, 694 insertions(+), 34 deletions(-) create mode 100755 actuator/src/main/java/org/tron/core/actuator/CancelUnfreezeV2Actuator.java create mode 100644 framework/src/main/java/org/tron/core/services/http/CancelUnfreezeV2Servlet.java create mode 100644 framework/src/test/java/org/tron/core/actuator/CancelUnfreezeV2ActuatorTest.java diff --git a/Tron protobuf protocol document.md b/Tron protobuf protocol document.md index f6fa2219ce3..0c027ea8dd8 100644 --- a/Tron protobuf protocol document.md +++ b/Tron protobuf protocol document.md @@ -627,6 +627,7 @@ Transaction and transaction-related messages. WithdrawExpireUnfreezeContract = 56; DelegateResourceContract = 57; UnDelegateResourceContract = 58; + CancelUnfreezeV2Contract = 59; } ContractType type = 1; google.protobuf.Any parameter = 2; @@ -887,6 +888,7 @@ Contract and contract-related messages. WithdrawExpireUnfreezeContract = 56; DelegateResourceContract = 57; UnDelegateResourceContract = 58; + CancelUnfreezeV2Contract = 59; } ContractType type = 1; google.protobuf.Any parameter = 2; diff --git a/actuator/build.gradle b/actuator/build.gradle index 3db2e55b3de..a230ef4ca7e 100644 --- a/actuator/build.gradle +++ b/actuator/build.gradle @@ -3,7 +3,7 @@ description = "actuator – a series of transactions for blockchain." // Dependency versions // --------------------------------------- -def junitVersion = "4.12" +def junitVersion = "4.13.2" def mockitoVersion = "2.1.0" def testNgVersion = "6.11" def slf4jVersion = "1.7.25" diff --git a/actuator/src/main/java/org/tron/core/actuator/CancelUnfreezeV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/CancelUnfreezeV2Actuator.java new file mode 100755 index 00000000000..aa0ff2fe64e --- /dev/null +++ b/actuator/src/main/java/org/tron/core/actuator/CancelUnfreezeV2Actuator.java @@ -0,0 +1,229 @@ +package org.tron.core.actuator; + +import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.tuple.Triple; +import org.tron.common.utils.DecodeUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.store.AccountStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.Protocol.Account.UnFreezeV2; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.contract.BalanceContract.CancelUnfreezeV2Contract; + +@Slf4j(topic = "actuator") +public class CancelUnfreezeV2Actuator extends AbstractActuator { + + public CancelUnfreezeV2Actuator() { + super(ContractType.CancelUnfreezeV2Contract, CancelUnfreezeV2Contract.class); + } + + @Override + public boolean execute(Object result) throws ContractExeException { + TransactionResultCapsule ret = (TransactionResultCapsule) result; + if (Objects.isNull(ret)) { + throw new RuntimeException(ActuatorConstant.TX_RESULT_NULL); + } + long fee = calcFee(); + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + final CancelUnfreezeV2Contract cancelUnfreezeV2Contract; + byte[] ownerAddress; + try { + cancelUnfreezeV2Contract = getCancelUnfreezeV2Contract(); + ownerAddress = getOwnerAddress().toByteArray(); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + List indexList = cancelUnfreezeV2Contract.getIndexList() + .stream().sorted().collect(Collectors.toList()); + AccountCapsule ownerCapsule = accountStore.get(ownerAddress); + List unfrozenV2List = ownerCapsule.getUnfrozenV2List(); + long now = dynamicStore.getLatestBlockHeaderTimestamp(); + AtomicLong atomicWithdrawExpireBalance = new AtomicLong(0L); + AtomicLong atomicCancelBalance = new AtomicLong(0L); + Triple triple = + Triple.of(new AtomicLong(0L), new AtomicLong(0L), new AtomicLong(0L)); + List newUnFreezeV2List = null; + if (indexList.isEmpty()) { + for (UnFreezeV2 unFreezeV2 : unfrozenV2List) { + updateAndCalculate(triple, ownerCapsule, now, atomicWithdrawExpireBalance, + atomicCancelBalance, unFreezeV2); + } + } else { + indexList.forEach(index -> { + UnFreezeV2 unFreezeV2 = unfrozenV2List.get(index); + updateAndCalculate(triple, ownerCapsule, now, atomicWithdrawExpireBalance, + atomicCancelBalance, unFreezeV2); + }); + newUnFreezeV2List = unfrozenV2List.stream() + .filter(o -> !indexList.contains(unfrozenV2List.indexOf(o))).collect(Collectors.toList()); + } + ownerCapsule.clearUnfrozenV2(); + ownerCapsule.addAllUnfrozenV2(newUnFreezeV2List); + addTotalResourceWeight(dynamicStore, triple); + + long withdrawExpireBalance = atomicWithdrawExpireBalance.get(); + if (withdrawExpireBalance > 0) { + ownerCapsule.setBalance(ownerCapsule.getBalance() + withdrawExpireBalance); + } + + accountStore.put(ownerCapsule.createDbKey(), ownerCapsule); + ret.setWithdrawExpireAmount(withdrawExpireBalance); + ret.setCancelUnfreezeV2Amount(atomicCancelBalance.get()); + ret.setStatus(fee, code.SUCESS); + return true; + } + + private void addTotalResourceWeight(DynamicPropertiesStore dynamicStore, + Triple triple) { + dynamicStore.addTotalNetWeight(triple.getLeft().get()); + dynamicStore.addTotalEnergyWeight(triple.getMiddle().get()); + dynamicStore.addTotalTronPowerWeight(triple.getRight().get()); + } + + private void updateAndCalculate(Triple triple, + AccountCapsule ownerCapsule, long now, AtomicLong atomicLong, AtomicLong cancelBalance, + UnFreezeV2 unFreezeV2) { + if (unFreezeV2.getUnfreezeExpireTime() > now) { + updateFrozenInfoAndTotalResourceWeight(ownerCapsule, unFreezeV2, triple); + cancelBalance.addAndGet(unFreezeV2.getUnfreezeAmount()); + } else { + atomicLong.addAndGet(unFreezeV2.getUnfreezeAmount()); + } + } + + @Override + public boolean validate() throws ContractValidateException { + if (Objects.isNull(this.any)) { + throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); + } + + if (Objects.isNull(chainBaseManager)) { + throw new ContractValidateException(ActuatorConstant.STORE_NOT_EXIST); + } + + AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); + + if (!this.any.is(CancelUnfreezeV2Contract.class)) { + throw new ContractValidateException("contract type error, expected type " + + "[CancelUnfreezeV2Contract], real type[" + any.getClass() + "]"); + } + + if (!dynamicStore.supportAllowCancelUnfreezeV2()) { + throw new ContractValidateException("Not support CancelUnfreezeV2 transaction," + + " need to be opened by the committee"); + } + + final CancelUnfreezeV2Contract cancelUnfreezeV2Contract; + byte[] ownerAddress; + try { + cancelUnfreezeV2Contract = getCancelUnfreezeV2Contract(); + ownerAddress = getOwnerAddress().toByteArray(); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + throw new ContractValidateException(e.getMessage()); + } + + if (!DecodeUtil.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalid address"); + } + AccountCapsule accountCapsule = accountStore.get(ownerAddress); + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + if (Objects.isNull(accountCapsule)) { + throw new ContractValidateException(ACCOUNT_EXCEPTION_STR + + readableOwnerAddress + NOT_EXIST_STR); + } + + List unfrozenV2List = accountCapsule.getUnfrozenV2List(); + if (unfrozenV2List.isEmpty()) { + throw new ContractValidateException("No unfreezeV2 list to cancel"); + } + + List indexList = cancelUnfreezeV2Contract.getIndexList(); + if (indexList.size() > unfrozenV2List.size()) { + throw new ContractValidateException( + "The size[" + indexList.size() + "] of the index cannot exceed the size[" + + unfrozenV2List.size() + "] of unfreezeV2!"); + } + + for (Integer i : indexList) { + int maxIndex = unfrozenV2List.size() - 1; + if (i < 0 || i > maxIndex) { + throw new ContractValidateException( + "The input index[" + i + "] cannot be less than 0 and cannot be " + + "greater than the maximum index[" + maxIndex + "] of unfreezeV2!"); + } + } + Set set = new HashSet<>(); + List dps = indexList.stream().filter(n -> !set.add(n)).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(dps)) { + throw new ContractValidateException("The element" + dps + " in the index list is duplicated"); + } + return true; + } + + @Override + public ByteString getOwnerAddress() throws InvalidProtocolBufferException { + return getCancelUnfreezeV2Contract().getOwnerAddress(); + } + + private CancelUnfreezeV2Contract getCancelUnfreezeV2Contract() + throws InvalidProtocolBufferException { + return any.unpack(CancelUnfreezeV2Contract.class); + } + + @Override + public long calcFee() { + return 0; + } + + public void updateFrozenInfoAndTotalResourceWeight( + AccountCapsule accountCapsule, UnFreezeV2 unFreezeV2, + Triple triple) { + switch (unFreezeV2.getType()) { + case BANDWIDTH: + long oldNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; + accountCapsule.addFrozenBalanceForBandwidthV2(unFreezeV2.getUnfreezeAmount()); + long newNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; + triple.getLeft().addAndGet(newNetWeight - oldNetWeight); + break; + case ENERGY: + long oldEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; + accountCapsule.addFrozenBalanceForEnergyV2(unFreezeV2.getUnfreezeAmount()); + long newEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; + triple.getMiddle().addAndGet(newEnergyWeight - oldEnergyWeight); + break; + case TRON_POWER: + long oldTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; + accountCapsule.addFrozenForTronPowerV2(unFreezeV2.getUnfreezeAmount()); + long newTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; + triple.getRight().addAndGet(newTPWeight - oldTPWeight); + break; + default: + break; + } + } +} diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 9ab68cc1925..1f957d3324d 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -692,6 +692,22 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case ALLOW_CANCEL_UNFREEZE_V2: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7_2)) { + throw new ContractValidateException( + "Bad chain parameter id [ALLOW_CANCEL_UNFREEZE_V2]"); + } + if (value != 1) { + throw new ContractValidateException( + "This value[ALLOW_CANCEL_UNFREEZE_V2] is only allowed to be 1"); + } + if (dynamicPropertiesStore.getUnfreezeDelayDays() == 0) { + throw new ContractValidateException( + "[UNFREEZE_DELAY_DAYS] proposal must be approved " + + "before [ALLOW_CANCEL_UNFREEZE_V2] can be proposed"); + } + break; + } default: break; } @@ -765,7 +781,8 @@ public enum ProposalType { // current value, value range DYNAMIC_ENERGY_THRESHOLD(73), // 0, [0, LONG] DYNAMIC_ENERGY_INCREASE_FACTOR(74), // 0, [0, 10_000] DYNAMIC_ENERGY_MAX_FACTOR(75), // 0, [0, 100_000] - ALLOW_TVM_SHANGHAI(76); // 0, 1 + ALLOW_TVM_SHANGHAI(76), // 0, 1 + ALLOW_CANCEL_UNFREEZE_V2(77); // 0, 1 private long code; diff --git a/chainbase/build.gradle b/chainbase/build.gradle index cac7efc6fa5..ed9911b0032 100644 --- a/chainbase/build.gradle +++ b/chainbase/build.gradle @@ -3,7 +3,7 @@ description = "chainbase – a decentralized database for blockchain." // Dependency versions // --------------------------------------- -def junitVersion = "4.12" +def junitVersion = "4.13.2" def mockitoVersion = "2.1.0" def testNgVersion = "6.11" def jacocoVersion = "0.8.0" diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionResultCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionResultCapsule.java index 98bb23c4729..4e93a52d2ac 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionResultCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionResultCapsule.java @@ -89,6 +89,15 @@ public void setWithdrawExpireAmount(long amount) { .setWithdrawExpireAmount(amount).build(); } + public long getCancelUnfreezeV2Amount() { + return transactionResult.getCancelUnfreezeV2Amount(); + } + + public void setCancelUnfreezeV2Amount(long amount) { + this.transactionResult = this.transactionResult.toBuilder() + .setCancelUnfreezeV2Amount(amount).build(); + } + public long getExchangeReceivedAmount() { return transactionResult.getExchangeReceivedAmount(); } diff --git a/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java b/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java index 2d438229ee6..ca366a3d8d7 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java +++ b/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java @@ -100,6 +100,7 @@ public static TransactionInfoCapsule buildTransactionInfoInstance(TransactionCap builder.setExchangeId(programResult.getRet().getExchangeId()); builder.setWithdrawAmount(programResult.getRet().getWithdrawAmount()); builder.setWithdrawExpireAmount(programResult.getRet().getWithdrawExpireAmount()); + builder.setCancelUnfreezeV2Amount(programResult.getRet().getCancelUnfreezeV2Amount()); builder.setExchangeReceivedAmount(programResult.getRet().getExchangeReceivedAmount()); builder.setExchangeInjectAnotherAmount(programResult.getRet().getExchangeInjectAnotherAmount()); builder.setExchangeWithdrawAnotherAmount( diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 001282a0de8..5138691d226 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -14,7 +14,6 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; import org.tron.core.capsule.BytesCapsule; -import org.tron.core.config.Parameter; import org.tron.core.config.Parameter.ChainConstant; import org.tron.core.db.TronStoreWithRevoking; import org.tron.core.exception.BadItemException; @@ -208,6 +207,9 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_TVM_SHANGHAI = "ALLOW_TVM_SHANGHAI".getBytes(); + private static final byte[] ALLOW_CANCEL_UNFREEZE_V2 = "ALLOW_CANCEL_UNFREEZE_V2" + .getBytes(); + @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { super(dbName); @@ -2192,7 +2194,7 @@ public long getNextMaintenanceTime() { } public long getMaintenanceSkipSlots() { - return Parameter.ChainConstant.MAINTENANCE_SKIP_SLOTS; + return ChainConstant.MAINTENANCE_SKIP_SLOTS; } public void saveNextMaintenanceTime(long nextMaintenanceTime) { @@ -2218,6 +2220,9 @@ public void updateNextMaintenanceTime(long blockTime) { //The unit is trx public void addTotalNetWeight(long amount) { + if (amount == 0) { + return; + } long totalNetWeight = getTotalNetWeight(); totalNetWeight += amount; if (allowNewReward()) { @@ -2228,6 +2233,9 @@ public void addTotalNetWeight(long amount) { //The unit is trx public void addTotalEnergyWeight(long amount) { + if (amount == 0) { + return; + } long totalEnergyWeight = getTotalEnergyWeight(); totalEnergyWeight += amount; if (allowNewReward()) { @@ -2238,6 +2246,9 @@ public void addTotalEnergyWeight(long amount) { //The unit is trx public void addTotalTronPowerWeight(long amount) { + if (amount == 0) { + return; + } long totalWeight = getTotalTronPowerWeight(); totalWeight += amount; if (allowNewReward()) { @@ -2769,6 +2780,22 @@ public long getAllowTvmShangHai() { .orElse(CommonParameter.getInstance().getAllowTvmShangHai()); } + public void saveAllowCancelUnfreezeV2(long allowCancelUnfreezeV2) { + this.put(DynamicPropertiesStore.ALLOW_CANCEL_UNFREEZE_V2, + new BytesCapsule(ByteArray.fromLong(allowCancelUnfreezeV2))); + } + + public long getAllowCancelUnfreezeV2() { + return Optional.ofNullable(getUnchecked(ALLOW_CANCEL_UNFREEZE_V2)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElse(CommonParameter.getInstance().getAllowCancelUnfreezeV2()); + } + + public boolean supportAllowCancelUnfreezeV2() { + return getAllowCancelUnfreezeV2() == 1L && getUnfreezeDelayDays() > 0; + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/common/build.gradle b/common/build.gradle index d065d3cbf89..95c6312ebcd 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -35,7 +35,7 @@ repositories { } dependencies { - testCompile group: 'junit', name: 'junit', version: '4.12' + testCompile group: 'junit', name: 'junit', version: '4.13.2' compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.13.4.1' compile "com.cedarsoftware:java-util:1.8.0" diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index ef89e01925a..d25f3b29600 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -651,6 +651,10 @@ public class CommonParameter { @Setter public long allowTvmShangHai; + @Getter + @Setter + public long allowCancelUnfreezeV2; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/consensus/build.gradle b/consensus/build.gradle index c2393064d46..c22e961572e 100644 --- a/consensus/build.gradle +++ b/consensus/build.gradle @@ -2,7 +2,7 @@ description = "consensus – a distributed consensus arithmetic for blockchain." // Dependency versions // --------------------------------------- -def junitVersion = "4.12" +def junitVersion = "4.13.2" def mockitoVersion = "2.1.0" def testNgVersion = "6.11" def slf4jVersion = "1.7.25" diff --git a/crypto/build.gradle b/crypto/build.gradle index 9d90368814d..19ae8e805fe 100644 --- a/crypto/build.gradle +++ b/crypto/build.gradle @@ -11,7 +11,7 @@ repositories { } dependencies { - testCompile group: 'junit', name: 'junit', version: '4.12' + testCompile group: 'junit', name: 'junit', version: '4.13.2' compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' compile project(":common") } diff --git a/framework/build.gradle b/framework/build.gradle index 6f6f861a6e9..0451ece2e64 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -40,7 +40,7 @@ dependencies { //local libraries compile fileTree(dir: 'libs', include: '*.jar') // end local libraries - testCompile group: 'junit', name: 'junit', version: '4.12' + testCompile group: 'junit', name: 'junit', version: '4.13.2' testCompile group: 'org.mockito', name: 'mockito-core', version: '2.13.0' testCompile group: 'org.hamcrest', name: 'hamcrest-junit', version: '1.0.0.1' @@ -54,7 +54,7 @@ dependencies { compile group: 'com.beust', name: 'jcommander', version: '1.72' - compile group: 'junit', name: 'junit', version: '4.12' + compile group: 'junit', name: 'junit', version: '4.13.2' compile group: 'net.jcip', name: 'jcip-annotations', version: '1.0' diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index a836b15d59d..c3f15099648 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1325,6 +1325,11 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getAllowTvmShangHai()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getAllowCancelUnfreezeV2") + .setValue(dbManager.getDynamicPropertiesStore().getAllowCancelUnfreezeV2()) + .build()); + return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 4ca90eae640..19c766f91dd 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -343,6 +343,14 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveAllowTvmShangHai(entry.getValue()); break; } + case ALLOW_CANCEL_UNFREEZE_V2: { + if (manager.getDynamicPropertiesStore().getAllowCancelUnfreezeV2() == 0) { + manager.getDynamicPropertiesStore().saveAllowCancelUnfreezeV2(entry.getValue()); + manager.getDynamicPropertiesStore().addSystemContractAndSetPermission( + ContractType.CancelUnfreezeV2Contract_VALUE); + } + break; + } default: find = false; break; diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 1f767eeb237..e99ed96dd46 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -130,6 +130,7 @@ import org.tron.protos.contract.BalanceContract.AccountBalanceRequest; import org.tron.protos.contract.BalanceContract.AccountBalanceResponse; import org.tron.protos.contract.BalanceContract.BlockBalanceTrace; +import org.tron.protos.contract.BalanceContract.CancelUnfreezeV2Contract; import org.tron.protos.contract.BalanceContract.DelegateResourceContract; import org.tron.protos.contract.BalanceContract.FreezeBalanceContract; import org.tron.protos.contract.BalanceContract.TransferContract; @@ -1471,6 +1472,13 @@ public void unDelegateResource(UnDelegateResourceContract request, responseObserver); } + @Override + public void cancelUnfreezeV2(CancelUnfreezeV2Contract request, + StreamObserver responseObserver) { + createTransactionExtention(request, ContractType.CancelUnfreezeV2Contract, + responseObserver); + } + @Override public void proposalCreate(ProposalCreateContract request, StreamObserver responseObserver) { diff --git a/framework/src/main/java/org/tron/core/services/http/CancelUnfreezeV2Servlet.java b/framework/src/main/java/org/tron/core/services/http/CancelUnfreezeV2Servlet.java new file mode 100644 index 00000000000..601379e5547 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/CancelUnfreezeV2Servlet.java @@ -0,0 +1,38 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.contract.BalanceContract.CancelUnfreezeV2Contract; + +@Component +@Slf4j(topic = "API") +public class CancelUnfreezeV2Servlet extends RateLimiterServlet { + + @Autowired + private Wallet wallet; + + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + PostParams params = PostParams.getPostParams(request); + CancelUnfreezeV2Contract.Builder build = CancelUnfreezeV2Contract.newBuilder(); + JsonFormat.merge(params.getParams(), build, params.isVisible()); + Transaction tx = wallet + .createTransactionCapsule(build.build(), ContractType.CancelUnfreezeV2Contract) + .getInstance(); + JSONObject jsonObject = JSON.parseObject(params.getParams()); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, params.isVisible())); + } catch (Exception e) { + Util.processError(e, response); + } + } +} diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index 030adc489ed..cac81174939 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -302,6 +302,8 @@ public class FullNodeHttpApiService implements Service { private DelegateResourceServlet delegateResourceServlet; @Autowired private UnDelegateResourceServlet unDelegateResourceServlet; + @Autowired + private CancelUnfreezeV2Servlet cancelUnfreezeV2Servlet; private static String getParamsFile(String fileName) { InputStream in = Thread.currentThread().getContextClassLoader() @@ -564,6 +566,8 @@ public void start() { "/wallet/delegateresource"); context.addServlet(new ServletHolder(unDelegateResourceServlet), "/wallet/undelegateresource"); + context.addServlet(new ServletHolder(cancelUnfreezeV2Servlet), + "/wallet/cancelunfreezev2"); int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { diff --git a/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java b/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java index 93b726bb0e5..5445a387278 100644 --- a/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java +++ b/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java @@ -144,6 +144,8 @@ public class HttpSelfFormatFieldName { //UnDelegateResourceContract AddressFieldNameMap.put("protocol.UnDelegateResourceContract.owner_address", 1); AddressFieldNameMap.put("protocol.UnDelegateResourceContract.receiver_address", 1); + //CancelUnfreezeV2Contract + AddressFieldNameMap.put("protocol.CancelUnfreezeV2Contract.owner_address", 1); AddressFieldNameMap.put("protocol.CanDelegatedMaxSizeRequestMessage.owner_address", 1); AddressFieldNameMap.put("protocol.GetAvailableUnfreezeCountRequestMessage.owner_address", 1); AddressFieldNameMap.put("protocol.CanWithdrawUnfreezeAmountRequestMessage.owner_address", 1); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java index 00a33f21bff..7b71f354293 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java @@ -334,6 +334,9 @@ public static long getAmountFromTransactionInfo(String hash, ContractType contra case WithdrawExpireUnfreezeContract: amount = transactionInfo.getWithdrawExpireAmount(); break; + case CancelUnfreezeV2Contract: + amount = transactionInfo.getCancelUnfreezeV2Amount(); + break; default: break; } diff --git a/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java index 2b98557e957..888e13f1ae6 100644 --- a/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java @@ -1,5 +1,6 @@ package org.tron.core.actuator; +import static org.testng.Assert.assertNotNull; import static org.testng.Assert.fail; import com.google.protobuf.Any; @@ -165,27 +166,23 @@ private void processAndCheckInvalid(AccountPermissionUpdateActuator actuator, actuator.execute(ret); fail(failMsg); - } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); + } catch (ContractValidateException | RuntimeException e) { + Assert.assertTrue(true); Assert.assertEquals(expectedMsg, e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); - } catch (RuntimeException e) { - Assert.assertTrue(e instanceof RuntimeException); - Assert.assertEquals(expectedMsg, e.getMessage()); + Assert.fail(); } } @Test public void successUpdatePermissionKey() { - String ownerAddress = OWNER_ADDRESS; String keyAddress = KEY_ADDRESS; // step 1, init addDefaultPermission(); // step2, check init data - byte[] owner_name_array = ByteArray.fromHexString(ownerAddress); + byte[] owner_name_array = ByteArray.fromHexString(OWNER_ADDRESS); ByteString address = ByteString.copyFrom(owner_name_array); AccountCapsule owner = dbManager.getAccountStore().get(owner_name_array); @@ -193,7 +190,7 @@ public void successUpdatePermissionKey() { Permission activePermission = AccountCapsule.createDefaultActivePermission(address, dbManager.getDynamicPropertiesStore()); - Assert.assertEquals(owner.getInstance().getActivePermissionCount(), 1); + Assert.assertEquals(1, owner.getInstance().getActivePermissionCount()); Permission ownerPermission1 = owner.getInstance().getOwnerPermission(); Permission activePermission1 = owner.getInstance().getActivePermission(0); @@ -240,21 +237,19 @@ public void successUpdatePermissionKey() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); // step 4, check result after update operation owner = dbManager.getAccountStore().get(owner_name_array); - Assert.assertEquals(owner.getInstance().getActivePermissionCount(), 1); + Assert.assertEquals(1, owner.getInstance().getActivePermissionCount()); ownerPermission1 = owner.getInstance().getOwnerPermission(); activePermission1 = owner.getInstance().getActivePermission(0); Assert.assertEquals(ownerPermission1, ownerPermission); Assert.assertEquals(activePermission1, activePermission); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -295,8 +290,7 @@ public void invalidTransactionResultCapsule() { AccountPermissionUpdateActuator actuator = new AccountPermissionUpdateActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) .setAny(getContract(OWNER_ADDRESS)); - TransactionResultCapsule ret = null; - processAndCheckInvalid(actuator, ret, "TransactionResultCapsule is null", + processAndCheckInvalid(actuator, null, "TransactionResultCapsule is null", "TransactionResultCapsule is null"); } @@ -364,7 +358,7 @@ public void activeToMany() { for (int i = 0; i <= 8; i++) { activeList.add(activePermission); } - + assertNotNull(activeList); AccountPermissionUpdateActuator actuator = new AccountPermissionUpdateActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) .setAny(getContract(address, ownerPermission, null, null)); @@ -930,12 +924,12 @@ public void checkAvailableContractTypeCorrespondingToCode() { // 7fff1fc0037e0000000000000000000000000000000000000000000000000000, // and it should call the addSystemContractAndSetPermission to add new contract // type - // When you add a new contact, you can add its to contractType, + // When you add a new contact, you can add it to contractType, // as '|| contractType = ContractType.XXX', // and you will get the value from the output, // then update the value to checkAvailableContractType // and checkActiveDefaultOperations - String validContractType = "7fff1fc0037ef807000000000000000000000000000000000000000000000000"; + String validContractType = "7fff1fc0037ef80f000000000000000000000000000000000000000000000000"; byte[] availableContractType = new byte[32]; for (ContractType contractType : ContractType.values()) { @@ -962,7 +956,7 @@ public void checkActiveDefaultOperationsCorrespondingToCode() { // 7fff1fc0033e0000000000000000000000000000000000000000000000000000, // and it should call the addSystemContractAndSetPermission to add new contract // type - String validContractType = "7fff1fc0033ef807000000000000000000000000000000000000000000000000"; + String validContractType = "7fff1fc0033ef80f000000000000000000000000000000000000000000000000"; byte[] availableContractType = new byte[32]; for (ContractType contractType : ContractType.values()) { @@ -985,7 +979,7 @@ public void checkActiveDefaultOperationsCorrespondingToCode() { @Test public void checkAvailableContractType() { - String validContractType = "7fff1fc0037ef907000000000000000000000000000000000000000000000000"; + String validContractType = "7fff1fc0037ef90f000000000000000000000000000000000000000000000000"; byte[] availableContractType = new byte[32]; for (ContractType contractType : ContractType.values()) { @@ -1006,7 +1000,7 @@ public void checkAvailableContractType() { @Test public void checkActiveDefaultOperations() { - String validContractType = "7fff1fc0033ef907000000000000000000000000000000000000000000000000"; + String validContractType = "7fff1fc0033ef90f000000000000000000000000000000000000000000000000"; byte[] availableContractType = new byte[32]; for (ContractType contractType : ContractType.values()) { diff --git a/framework/src/test/java/org/tron/core/actuator/CancelUnfreezeV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/CancelUnfreezeV2ActuatorTest.java new file mode 100644 index 00000000000..9af9c42addf --- /dev/null +++ b/framework/src/test/java/org/tron/core/actuator/CancelUnfreezeV2ActuatorTest.java @@ -0,0 +1,295 @@ +package org.tron.core.actuator; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.fail; +import static org.tron.protos.Protocol.Transaction.Result.code.SUCESS; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; + +import com.beust.jcommander.internal.Lists; +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import lombok.extern.slf4j.Slf4j; +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.TransactionResultCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.protos.Protocol; +import org.tron.protos.contract.BalanceContract; + +@Slf4j +public class CancelUnfreezeV2ActuatorTest extends BaseTest { + + private static final String OWNER_ADDRESS; + private static final String RECEIVER_ADDRESS; + private static final String OWNER_ADDRESS_INVALID = "aaaa"; + private static final String OWNER_ACCOUNT_INVALID; + private static final long initBalance = 10_000_000_000L; + + static { + dbPath = "output_cancel_all_unfreeze_v2_test"; + Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; + OWNER_ACCOUNT_INVALID = + Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; + } + + @Before + public void setUp() { + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); + dbManager.getDynamicPropertiesStore().saveAllowCancelUnfreezeV2(1); + + AccountCapsule ownerCapsule = new AccountCapsule(ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), Protocol.AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); + + AccountCapsule receiverCapsule = new AccountCapsule(ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), Protocol.AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); + } + + @Test + public void testCancelUnfreezeV2() { + long now = System.currentTimeMillis(); + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addUnfrozenV2List(BANDWIDTH, 1000000L, now + 14 * 24 * 3600 * 1000); + accountCapsule.addUnfrozenV2List(ENERGY, 2000000L, -1); + accountCapsule.addUnfrozenV2List(BANDWIDTH, 3000000L, now + 14 * 24 * 3600 * 1000); + accountCapsule.addUnfrozenV2List(ENERGY, 4000000L, now + 14 * 24 * 3600 * 1000); + accountCapsule.addUnfrozenV2List(BANDWIDTH, 4000000L, 100); + accountCapsule.addUnfrozenV2List(ENERGY, 4000000L, 100); + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getCancelUnfreezeV2Contract()); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + assertEquals(SUCESS, ret.getInstance().getRet()); + AccountCapsule owner = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + assertEquals(2000000L, ret.getInstance().getWithdrawExpireAmount()); + assertEquals(2, owner.getUnfrozenV2List().size()); + } catch (ContractValidateException | ContractExeException e) { + fail(); + } + } + + @Test + public void testCancelAllUnfreezeV2() { + long now = System.currentTimeMillis(); + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addUnfrozenV2List(BANDWIDTH, 1000000L, now + 14 * 24 * 3600 * 1000); + accountCapsule.addUnfrozenV2List(ENERGY, 2000000L, -1); + accountCapsule.addUnfrozenV2List(BANDWIDTH, 3000000L, now + 14 * 24 * 3600 * 1000); + accountCapsule.addUnfrozenV2List(ENERGY, 4000000L, now + 14 * 24 * 3600 * 1000); + accountCapsule.addUnfrozenV2List(BANDWIDTH, 4000000L, 100); + accountCapsule.addUnfrozenV2List(ENERGY, 4000000L, 100); + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getCancelAllUnfreezeV2Contract()); + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + + assertEquals(SUCESS, ret.getInstance().getRet()); + AccountCapsule owner = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + assertEquals(2000000L, ret.getInstance().getWithdrawExpireAmount()); + assertEquals(0, owner.getUnfrozenV2List().size()); + } catch (ContractValidateException | ContractExeException e) { + fail(); + } + } + + @Test + public void testNullTransactionResultCapsule() { + long now = System.currentTimeMillis(); + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addUnfrozenV2List(BANDWIDTH, 1000000L, now + 14 * 24 * 3600 * 1000); + accountCapsule.addUnfrozenV2List(ENERGY, 2000000L, -1); + accountCapsule.addUnfrozenV2List(BANDWIDTH, 3000000L, now + 14 * 24 * 3600 * 1000); + accountCapsule.addUnfrozenV2List(ENERGY, 4000000L, now + 14 * 24 * 3600 * 1000); + accountCapsule.addUnfrozenV2List(BANDWIDTH, 4000000L, 100); + accountCapsule.addUnfrozenV2List(ENERGY, 4000000L, 100); + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getCancelUnfreezeV2Contract()); + try { + actuator.validate(); + } catch (ContractValidateException e) { + fail(); + } + assertThrows(ActuatorConstant.TX_RESULT_NULL, + RuntimeException.class, () -> actuator.execute(null)); + } + + @Test + public void testInvalidOwnerAddress() { + CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getCancelUnfreezeV2ContractInvalidAddress()); + assertThrows("Invalid address", ContractValidateException.class, actuator::validate); + } + + @Test + public void testInvalidOwnerAccount() { + CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getCancelUnfreezeV2ContractInvalidAccount()); + assertThrows("Account[" + OWNER_ACCOUNT_INVALID + "] does not exist", + ContractValidateException.class, actuator::validate); + } + + @Test + public void testInvalidOwnerUnfreezeV2List() { + CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getCancelUnfreezeV2Contract()); + assertThrows("no unfreezeV2 list to cancel", + ContractValidateException.class, actuator::validate); + } + + @Test + public void testInvalidCancelUnfreezeV2Contract() { + CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny(null); + assertThrows(ActuatorConstant.CONTRACT_NOT_EXIST, + ContractValidateException.class, actuator::validate); + } + + @Test + public void testInvalidAccountStore() { + CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + actuator.setChainBaseManager(null).setAny(getCancelUnfreezeV2Contract()); + assertThrows(ActuatorConstant.STORE_NOT_EXIST, + ContractValidateException.class, actuator::validate); + } + + @Test + public void testSupportAllowCancelUnfreezeV2() { + dbManager.getDynamicPropertiesStore().saveAllowCancelUnfreezeV2(0); + CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getCancelUnfreezeV2Contract()); + assertThrows( + "Not support CancelUnfreezeV2 transaction, need to be opened by the committee", + ContractValidateException.class, actuator::validate); + } + + @Test + public void testWrongIndex() { + dbManager.getDynamicPropertiesStore().saveAllowCancelUnfreezeV2(1); + long now = System.currentTimeMillis(); + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addUnfrozenV2List(BANDWIDTH, 1000000L, now + 14 * 24 * 3600 * 1000); + accountCapsule.addUnfrozenV2List(ENERGY, 2000000L, -1); + accountCapsule.addUnfrozenV2List(BANDWIDTH, 3000000L, now + 14 * 24 * 3600 * 1000); + accountCapsule.addUnfrozenV2List(ENERGY, 4000000L, now + 14 * 24 * 3600 * 1000); + accountCapsule.addUnfrozenV2List(BANDWIDTH, 4000000L, 100); + accountCapsule.addUnfrozenV2List(ENERGY, 4000000L, 100); + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + + CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getWrongIndexCancelUnfreezeV2Contract()); + assertThrows("The input index[-1] cannot be less than 0 and cannot be greater than " + + "the maximum index[5] of unfreezeV2!", + ContractValidateException.class, actuator::validate); + } + + @Test + public void testWrongIndexSize() { + dbManager.getDynamicPropertiesStore().saveAllowCancelUnfreezeV2(1); + long now = System.currentTimeMillis(); + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + accountCapsule.addUnfrozenV2List(BANDWIDTH, 1000000L, now + 14 * 24 * 3600 * 1000); + accountCapsule.addUnfrozenV2List(ENERGY, 2000000L, -1); + accountCapsule.addUnfrozenV2List(BANDWIDTH, 3000000L, now + 14 * 24 * 3600 * 1000); + accountCapsule.addUnfrozenV2List(ENERGY, 4000000L, now + 14 * 24 * 3600 * 1000); + accountCapsule.addUnfrozenV2List(BANDWIDTH, 4000000L, 100); + accountCapsule.addUnfrozenV2List(ENERGY, 4000000L, 100); + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + + CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getWrongIndexSizeCancelUnfreezeV2Contract()); + assertThrows("The size of the index cannot exceed the size of unfrozenV2!", + ContractValidateException.class, actuator::validate); + } + + @Test + public void testErrorContract() { + dbManager.getDynamicPropertiesStore().saveAllowCancelUnfreezeV2(1); + CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny(getErrorContract()); + assertThrows( + "contract type error, expected type [CancelUnfreezeV2Contract], " + + "real type[WithdrawExpireUnfreezeContract]", + ContractValidateException.class, actuator::validate); + } + + private Any getCancelUnfreezeV2Contract() { + return Any.pack(BalanceContract.CancelUnfreezeV2Contract.newBuilder() + .addAllIndex(Lists.newArrayList(0, 1, 2, 3)) + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))).build() + ); + } + + private Any getCancelAllUnfreezeV2Contract() { + return Any.pack(BalanceContract.CancelUnfreezeV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))).build() + ); + } + + private Any getWrongIndexSizeCancelUnfreezeV2Contract() { + return Any.pack(BalanceContract.CancelUnfreezeV2Contract.newBuilder() + .addAllIndex(Lists.newArrayList(0, 1, 2, 1, 3, 2, 4)) + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))).build() + ); + } + + private Any getWrongIndexCancelUnfreezeV2Contract() { + return Any.pack(BalanceContract.CancelUnfreezeV2Contract.newBuilder() + .addAllIndex(Lists.newArrayList(-1, 1, 2, 1, 3, 2)) + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))).build() + ); + } + + private Any getErrorContract() { + return Any.pack(BalanceContract.WithdrawExpireUnfreezeContract.newBuilder().setOwnerAddress( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))).build() + ); + } + + private Any getCancelUnfreezeV2ContractInvalidAddress() { + return Any.pack(BalanceContract.CancelUnfreezeV2Contract.newBuilder().setOwnerAddress( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS_INVALID))).build()); + } + + private Any getCancelUnfreezeV2ContractInvalidAccount() { + return Any.pack(BalanceContract.CancelUnfreezeV2Contract.newBuilder().setOwnerAddress( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ACCOUNT_INVALID))).build() + ); + } +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/services/http/HttpServletTest.java b/framework/src/test/java/org/tron/core/services/http/HttpServletTest.java index 9775db0a954..823a8f7ea1b 100644 --- a/framework/src/test/java/org/tron/core/services/http/HttpServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/HttpServletTest.java @@ -139,6 +139,7 @@ public class HttpServletTest { private VoteWitnessAccountServlet voteWitnessAccountServlet; private WithdrawBalanceServlet withdrawBalanceServlet; private WithdrawExpireUnfreezeServlet withdrawExpireUnfreezeServlet; + private CancelUnfreezeV2Servlet cancelUnfreezeV2Servlet; private MockHttpServletRequest request; private MockHttpServletResponse response; @@ -275,6 +276,7 @@ public void setUp() { voteWitnessAccountServlet = new VoteWitnessAccountServlet(); withdrawBalanceServlet = new WithdrawBalanceServlet(); withdrawExpireUnfreezeServlet = new WithdrawExpireUnfreezeServlet(); + cancelUnfreezeV2Servlet = new CancelUnfreezeV2Servlet(); request = new MockHttpServletRequest(); request.setCharacterEncoding("UTF-8"); response = new MockHttpServletResponse(); @@ -526,6 +528,7 @@ public void doPostTest() { voteWitnessAccountServlet.doPost(request, response); withdrawBalanceServlet.doPost(request, response); withdrawExpireUnfreezeServlet.doPost(request, response); + cancelUnfreezeV2Servlet.doPost(request, response); } } diff --git a/plugins/build.gradle b/plugins/build.gradle index 22e37737731..457fb739058 100644 --- a/plugins/build.gradle +++ b/plugins/build.gradle @@ -26,7 +26,7 @@ configurations.getByName('checkstyleConfig') { dependencies { //local libraries compile fileTree(dir: 'libs', include: '*.jar') - testCompile group: 'junit', name: 'junit', version: '4.12' + testCompile group: 'junit', name: 'junit', version: '4.13.2' testCompile group: 'org.mockito', name: 'mockito-core', version: '2.13.0' testCompile group: 'org.hamcrest', name: 'hamcrest-junit', version: '1.0.0.1' testCompile group: 'org.testng', name: 'testng', version: '6.14.3' diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 70297d0959b..1e37f425f50 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -281,6 +281,9 @@ service Wallet { rpc UnDelegateResource (UnDelegateResourceContract) returns (TransactionExtention) { } + rpc CancelUnfreezeV2 (CancelUnfreezeV2Contract) returns (TransactionExtention) { + } + //Please use UpdateAsset2 instead of this function. rpc UpdateAsset (UpdateAssetContract) returns (Transaction) { option (google.api.http) = { diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index e5145484f05..2ce19ba2708 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -374,6 +374,7 @@ message Transaction { WithdrawExpireUnfreezeContract = 56; DelegateResourceContract = 57; UnDelegateResourceContract = 58; + CancelUnfreezeV2Contract = 59; } ContractType type = 1; google.protobuf.Any parameter = 2; @@ -422,6 +423,7 @@ message Transaction { bytes orderId = 25; repeated MarketOrderDetail orderDetails = 26; int64 withdraw_expire_amount = 27; + int64 cancel_unfreezeV2_amount = 28; } message raw { @@ -482,6 +484,7 @@ message TransactionInfo { int64 packingFee = 27; int64 withdraw_expire_amount = 28; + int64 cancel_unfreezeV2_amount = 29; } message TransactionRet { diff --git a/protocol/src/main/protos/core/contract/balance_contract.proto b/protocol/src/main/protos/core/contract/balance_contract.proto index 90a2dfaa48d..14b531eaa6d 100644 --- a/protocol/src/main/protos/core/contract/balance_contract.proto +++ b/protocol/src/main/protos/core/contract/balance_contract.proto @@ -110,4 +110,9 @@ message UnDelegateResourceContract { ResourceCode resource = 2; int64 balance = 3; bytes receiver_address = 4; +} + +message CancelUnfreezeV2Contract { + bytes owner_address = 1; + repeated int32 index = 2; } \ No newline at end of file From 9260293145e81d0940791db5d040c0fa5f6fc8ce Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 5 Jun 2023 12:08:57 +0800 Subject: [PATCH 0797/1197] fix(net):remove forced io.netty --- build.gradle | 6 ------ 1 file changed, 6 deletions(-) diff --git a/build.gradle b/build.gradle index d58e37743e9..8aad8910153 100644 --- a/build.gradle +++ b/build.gradle @@ -70,12 +70,6 @@ subprojects { resolutionStrategy { force group: 'com.google.guava', name: 'guava', version: '30.1-jre' } - //resolutionStrategy.eachDependency { details -> - // // TODO if update grpc remove - // if(details.requested.group == 'io.netty') { - // details.useVersion "4.1.27.Final" - // } - //} } } From 8fbdd1244caade65ac4023931935132c2c4eed40 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 6 Jun 2023 11:47:47 +0800 Subject: [PATCH 0798/1197] feat(hard_fork):optimize hard fork code --- .../java/org/tron/common/utils/ForkController.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/utils/ForkController.java b/chainbase/src/main/java/org/tron/common/utils/ForkController.java index 16f1f5aadf5..579e76a409c 100644 --- a/chainbase/src/main/java/org/tron/common/utils/ForkController.java +++ b/chainbase/src/main/java/org/tron/common/utils/ForkController.java @@ -38,12 +38,6 @@ public class ForkController { public void init(ChainBaseManager manager) { this.manager = manager; - try { - checkLocalVersion(); - } catch (RuntimeException r) { - logger.warn("Exception caught, detail:{}", r.getMessage()); - System.exit(1); - } } public boolean pass(ForkBlockVersionEnum forkBlockVersionEnum) { @@ -249,8 +243,8 @@ public void checkLocalVersion() { } } if (latestVersion > systemVersion) { - throw new RuntimeException("Version check failed, latestVersion:" - + latestVersion + ", systemVersion:" + systemVersion); + throw new RuntimeException("Version check failed, please upgrade to the latest version," + + " latestVersion:" + latestVersion + ", systemVersion:" + systemVersion); } } } From d94404177d2dbfcb35f43603295300a02e39d68f Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 6 Jun 2023 16:31:57 +0800 Subject: [PATCH 0799/1197] feat(hard_fork):optimize local version checking logic --- framework/src/main/java/org/tron/core/db/Manager.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index a3f8fb8de03..df9cde80632 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -486,6 +486,12 @@ public void init() { System.exit(1); } getChainBaseManager().getForkController().init(this.chainBaseManager); + try { + getChainBaseManager().getForkController().checkLocalVersion(); + } catch (RuntimeException r) { + logger.error("{}", r.getMessage()); + System.exit(1); + } if (Args.getInstance().isNeedToUpdateAsset() && needToUpdateAsset()) { new AssetUpdateHelper(chainBaseManager).doWork(); From c7268c4144b3d2a8e7f503219c70c18f7bb6588d Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 6 Jun 2023 17:29:38 +0800 Subject: [PATCH 0800/1197] fix(net): fix the bug that fails to generate SyncBlockChain --- .../tron/core/net/messagehandler/ChainInventoryMsgHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java index bd2e428418c..a2096aac90e 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java @@ -72,7 +72,7 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep try { BlockId blockId = null; while (!peer.getSyncBlockToFetch().isEmpty() && tronNetDelegate - .containBlock(peer.getSyncBlockToFetch().peek())) { + .containBlockInMainChain(peer.getSyncBlockToFetch().peek())) { blockId = peer.getSyncBlockToFetch().pop(); peer.setBlockBothHave(blockId); } From 47f659ca29fcf7bf8e954c80e7c56f1ef38f7e90 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 7 Jun 2023 14:19:55 +0800 Subject: [PATCH 0801/1197] feat(db): optimize bloom filter for transaction cache --- .../src/main/java/org/tron/core/db/TronStoreWithRevoking.java | 3 ++- .../src/main/java/org/tron/core/db2/common/TxCacheDB.java | 3 +-- .../src/main/java/org/tron/core/db2/core/SnapshotManager.java | 1 + framework/src/main/java/org/tron/core/db/Manager.java | 1 + .../src/main/java/org/tron/core/db/TransactionCache.java | 4 ++++ 5 files changed, 9 insertions(+), 3 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java b/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java index 2dcd370a656..c1da54d84f4 100644 --- a/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java +++ b/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java @@ -51,7 +51,8 @@ public abstract class TronStoreWithRevoking implements I @Autowired private DbStatService dbStatService; - private DB db; + @Getter + private final DB db; protected TronStoreWithRevoking(String dbName) { String dbEngine = CommonParameter.getInstance().getStorage().getDbEngine(); diff --git a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java index 63e020ea1d6..71cf361b06a 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java @@ -86,7 +86,6 @@ public TxCacheDB(String name, RecentTransactionStore recentTransactionStore) { this.bloomFilters[1] = BloomFilter.create(Funnels.byteArrayFunnel(), MAX_BLOCK_SIZE * TRANSACTION_COUNT); - init(); } /** @@ -110,7 +109,7 @@ private void initCache() { System.currentTimeMillis() - start); } - private void init() { + public void init() { long size = recentTransactionStore.size(); if (size != MAX_BLOCK_SIZE) { // 0. load from persistentStore diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java index 85d0f3c2dd0..230a812e093 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java @@ -509,6 +509,7 @@ private void checkV1() { } } recover(checkTmpStore); + logger.info("checkpoint v1 recover success"); unChecked = false; } diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 1929bae1d3d..9c8364c8e7a 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -450,6 +450,7 @@ public void init() { trieService.setChainBaseManager(chainBaseManager); revokingStore.disable(); revokingStore.check(); + transactionCache.initCache(); this.setProposalController(ProposalController.createInstance(this)); this.setMerkleContainer( merkleContainer.createInstance(chainBaseManager.getMerkleTreeStore(), diff --git a/framework/src/main/java/org/tron/core/db/TransactionCache.java b/framework/src/main/java/org/tron/core/db/TransactionCache.java index 715d82185d0..70b42ca7226 100644 --- a/framework/src/main/java/org/tron/core/db/TransactionCache.java +++ b/framework/src/main/java/org/tron/core/db/TransactionCache.java @@ -14,4 +14,8 @@ public TransactionCache(@Value("trans-cache") String dbName, RecentTransactionStore recentTransactionStore) { super(new TxCacheDB(dbName, recentTransactionStore)); } + + public void initCache() { + ((TxCacheDB) getDb()).init(); + } } From f4acc524a39763a9ec518525ac6faf132fb82a13 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Mon, 5 Jun 2023 11:26:11 +0800 Subject: [PATCH 0802/1197] feat(freezeV2): optimize Stake 2.0 APIs Signed-off-by: liuxincheng --- .gitignore | 2 + Tron protobuf protocol document.md | 4 +- ....java => CancelAllUnfreezeV2Actuator.java} | 72 ++------- .../actuator/DelegateResourceActuator.java | 13 +- .../org/tron/core/utils/ProposalUtil.java | 23 +-- .../org/tron/core/utils/TransactionUtil.java | 17 +- .../capsule/TransactionResultCapsule.java | 8 +- .../core/capsule/utils/TransactionUtil.java | 2 +- .../core/store/DynamicPropertiesStore.java | 38 ++--- .../common/parameter/CommonParameter.java | 4 +- .../java/org/tron/core/config/Parameter.java | 1 - .../src/main/java/org/tron/core/Wallet.java | 8 +- .../tron/core/consensus/ProposalService.java | 15 +- .../org/tron/core/services/RpcApiService.java | 6 +- ...t.java => CancelAllUnfreezeV2Servlet.java} | 8 +- .../services/http/FullNodeHttpApiService.java | 6 +- .../http/HttpSelfFormatFieldName.java | 4 +- .../core/services/jsonrpc/JsonRpcApiUtil.java | 6 +- .../common/logsfilter/EventLoaderTest.java | 53 ++++++- .../test/java/org/tron/core/WalletTest.java | 14 +- ...a => CancelAllUnfreezeV2ActuatorTest.java} | 150 ++++-------------- .../DelegateResourceActuatorTest.java | 72 ++++++--- .../actuator/utils/TransactionUtilTest.java | 15 +- .../core/services/http/HttpServletTest.java | 6 +- protocol/src/main/protos/api/api.proto | 2 +- protocol/src/main/protos/core/Tron.proto | 6 +- .../core/contract/balance_contract.proto | 3 +- 27 files changed, 267 insertions(+), 291 deletions(-) rename actuator/src/main/java/org/tron/core/actuator/{CancelUnfreezeV2Actuator.java => CancelAllUnfreezeV2Actuator.java} (69%) rename framework/src/main/java/org/tron/core/services/http/{CancelUnfreezeV2Servlet.java => CancelAllUnfreezeV2Servlet.java} (82%) rename framework/src/test/java/org/tron/core/actuator/{CancelUnfreezeV2ActuatorTest.java => CancelAllUnfreezeV2ActuatorTest.java} (51%) diff --git a/.gitignore b/.gitignore index 9b19aa5de68..6309bbd79a5 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,5 @@ Wallet # vm_trace /vm_trace/ + +/framework/propPath diff --git a/Tron protobuf protocol document.md b/Tron protobuf protocol document.md index 0c027ea8dd8..852ff313797 100644 --- a/Tron protobuf protocol document.md +++ b/Tron protobuf protocol document.md @@ -627,7 +627,7 @@ Transaction and transaction-related messages. WithdrawExpireUnfreezeContract = 56; DelegateResourceContract = 57; UnDelegateResourceContract = 58; - CancelUnfreezeV2Contract = 59; + CancelAllUnfreezeV2Contract = 59; } ContractType type = 1; google.protobuf.Any parameter = 2; @@ -888,7 +888,7 @@ Contract and contract-related messages. WithdrawExpireUnfreezeContract = 56; DelegateResourceContract = 57; UnDelegateResourceContract = 58; - CancelUnfreezeV2Contract = 59; + CancelAllUnfreezeV2Contract = 59; } ContractType type = 1; google.protobuf.Any parameter = 2; diff --git a/actuator/src/main/java/org/tron/core/actuator/CancelUnfreezeV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/CancelAllUnfreezeV2Actuator.java similarity index 69% rename from actuator/src/main/java/org/tron/core/actuator/CancelUnfreezeV2Actuator.java rename to actuator/src/main/java/org/tron/core/actuator/CancelAllUnfreezeV2Actuator.java index aa0ff2fe64e..8fd58124b1a 100755 --- a/actuator/src/main/java/org/tron/core/actuator/CancelUnfreezeV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/CancelAllUnfreezeV2Actuator.java @@ -8,14 +8,10 @@ import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; -import java.util.HashSet; import java.util.List; import java.util.Objects; -import java.util.Set; import java.util.concurrent.atomic.AtomicLong; -import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.tuple.Triple; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; @@ -28,13 +24,13 @@ import org.tron.protos.Protocol.Account.UnFreezeV2; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result.code; -import org.tron.protos.contract.BalanceContract.CancelUnfreezeV2Contract; +import org.tron.protos.contract.BalanceContract.CancelAllUnfreezeV2Contract; @Slf4j(topic = "actuator") -public class CancelUnfreezeV2Actuator extends AbstractActuator { +public class CancelAllUnfreezeV2Actuator extends AbstractActuator { - public CancelUnfreezeV2Actuator() { - super(ContractType.CancelUnfreezeV2Contract, CancelUnfreezeV2Contract.class); + public CancelAllUnfreezeV2Actuator() { + super(ContractType.CancelAllUnfreezeV2Contract, CancelAllUnfreezeV2Contract.class); } @Override @@ -46,18 +42,14 @@ public boolean execute(Object result) throws ContractExeException { long fee = calcFee(); AccountStore accountStore = chainBaseManager.getAccountStore(); DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); - final CancelUnfreezeV2Contract cancelUnfreezeV2Contract; byte[] ownerAddress; try { - cancelUnfreezeV2Contract = getCancelUnfreezeV2Contract(); ownerAddress = getOwnerAddress().toByteArray(); } catch (InvalidProtocolBufferException e) { logger.debug(e.getMessage(), e); ret.setStatus(fee, code.FAILED); throw new ContractExeException(e.getMessage()); } - List indexList = cancelUnfreezeV2Contract.getIndexList() - .stream().sorted().collect(Collectors.toList()); AccountCapsule ownerCapsule = accountStore.get(ownerAddress); List unfrozenV2List = ownerCapsule.getUnfrozenV2List(); long now = dynamicStore.getLatestBlockHeaderTimestamp(); @@ -65,23 +57,11 @@ public boolean execute(Object result) throws ContractExeException { AtomicLong atomicCancelBalance = new AtomicLong(0L); Triple triple = Triple.of(new AtomicLong(0L), new AtomicLong(0L), new AtomicLong(0L)); - List newUnFreezeV2List = null; - if (indexList.isEmpty()) { - for (UnFreezeV2 unFreezeV2 : unfrozenV2List) { - updateAndCalculate(triple, ownerCapsule, now, atomicWithdrawExpireBalance, - atomicCancelBalance, unFreezeV2); - } - } else { - indexList.forEach(index -> { - UnFreezeV2 unFreezeV2 = unfrozenV2List.get(index); - updateAndCalculate(triple, ownerCapsule, now, atomicWithdrawExpireBalance, - atomicCancelBalance, unFreezeV2); - }); - newUnFreezeV2List = unfrozenV2List.stream() - .filter(o -> !indexList.contains(unfrozenV2List.indexOf(o))).collect(Collectors.toList()); + for (UnFreezeV2 unFreezeV2 : unfrozenV2List) { + updateAndCalculate(triple, ownerCapsule, now, atomicWithdrawExpireBalance, + atomicCancelBalance, unFreezeV2); } ownerCapsule.clearUnfrozenV2(); - ownerCapsule.addAllUnfrozenV2(newUnFreezeV2List); addTotalResourceWeight(dynamicStore, triple); long withdrawExpireBalance = atomicWithdrawExpireBalance.get(); @@ -91,7 +71,7 @@ public boolean execute(Object result) throws ContractExeException { accountStore.put(ownerCapsule.createDbKey(), ownerCapsule); ret.setWithdrawExpireAmount(withdrawExpireBalance); - ret.setCancelUnfreezeV2Amount(atomicCancelBalance.get()); + ret.setCancelAllUnfreezeV2Amount(atomicCancelBalance.get()); ret.setStatus(fee, code.SUCESS); return true; } @@ -127,20 +107,18 @@ public boolean validate() throws ContractValidateException { AccountStore accountStore = chainBaseManager.getAccountStore(); DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); - if (!this.any.is(CancelUnfreezeV2Contract.class)) { + if (!this.any.is(CancelAllUnfreezeV2Contract.class)) { throw new ContractValidateException("contract type error, expected type " + - "[CancelUnfreezeV2Contract], real type[" + any.getClass() + "]"); + "[CancelAllUnfreezeV2Contract], real type[" + any.getClass() + "]"); } - if (!dynamicStore.supportAllowCancelUnfreezeV2()) { - throw new ContractValidateException("Not support CancelUnfreezeV2 transaction," + if (!dynamicStore.supportAllowCancelAllUnfreezeV2()) { + throw new ContractValidateException("Not support CancelAllUnfreezeV2 transaction," + " need to be opened by the committee"); } - final CancelUnfreezeV2Contract cancelUnfreezeV2Contract; byte[] ownerAddress; try { - cancelUnfreezeV2Contract = getCancelUnfreezeV2Contract(); ownerAddress = getOwnerAddress().toByteArray(); } catch (InvalidProtocolBufferException e) { logger.debug(e.getMessage(), e); @@ -162,37 +140,17 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("No unfreezeV2 list to cancel"); } - List indexList = cancelUnfreezeV2Contract.getIndexList(); - if (indexList.size() > unfrozenV2List.size()) { - throw new ContractValidateException( - "The size[" + indexList.size() + "] of the index cannot exceed the size[" - + unfrozenV2List.size() + "] of unfreezeV2!"); - } - - for (Integer i : indexList) { - int maxIndex = unfrozenV2List.size() - 1; - if (i < 0 || i > maxIndex) { - throw new ContractValidateException( - "The input index[" + i + "] cannot be less than 0 and cannot be " - + "greater than the maximum index[" + maxIndex + "] of unfreezeV2!"); - } - } - Set set = new HashSet<>(); - List dps = indexList.stream().filter(n -> !set.add(n)).collect(Collectors.toList()); - if (CollectionUtils.isNotEmpty(dps)) { - throw new ContractValidateException("The element" + dps + " in the index list is duplicated"); - } return true; } @Override public ByteString getOwnerAddress() throws InvalidProtocolBufferException { - return getCancelUnfreezeV2Contract().getOwnerAddress(); + return getCancelAllUnfreezeV2Contract().getOwnerAddress(); } - private CancelUnfreezeV2Contract getCancelUnfreezeV2Contract() + private CancelAllUnfreezeV2Contract getCancelAllUnfreezeV2Contract() throws InvalidProtocolBufferException { - return any.unpack(CancelUnfreezeV2Contract.class); + return any.unpack(CancelAllUnfreezeV2Contract.class); } @Override diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index d7dfcd5da14..aab5e076453 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -2,7 +2,6 @@ import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; -import static org.tron.core.config.Parameter.ChainConstant.MAX_BLOCK_NUM_DELEGATE_PERIOD; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import static org.tron.protos.contract.Common.ResourceCode; import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; @@ -219,11 +218,13 @@ public boolean validate() throws ContractValidateException { } boolean lock = delegateResourceContract.getLock(); - if (lock && dynamicStore.supportAllowOptimizeLockDelegateResource()) { + if (lock && dynamicStore.supportMaxDelegateLockPeriod()) { long lockPeriod = delegateResourceContract.getLockPeriod(); - if (lockPeriod < 0 || lockPeriod > MAX_BLOCK_NUM_DELEGATE_PERIOD) { + long maxDelegateLockPeriod = dynamicStore.getMaxDelegateLockPeriod(); + if (lockPeriod < 0 || lockPeriod > maxDelegateLockPeriod) { throw new ContractValidateException( - "The lock period of delegate resource cannot be less than 0 and cannot exceed 1 year!"); + "The lock period of delegate resource cannot be less than 0 and cannot exceed " + + maxDelegateLockPeriod + "!"); } byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, true); @@ -262,7 +263,7 @@ private void validRemainTime(ResourceCode resourceCode, long lockPeriod, long ex if (lockPeriod * 3 * 1000 < remainTime) { throw new ContractValidateException( "The lock period for " + resourceCode.name() + " this time cannot be less than the " - + "remaining time[" + remainTime + "s] of the last lock period for " + + "remaining time[" + remainTime + "ms] of the last lock period for " + resourceCode.name() + "!"); } } @@ -292,7 +293,7 @@ private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boole //modify DelegatedResourceStore long expireTime = 0; if (lock) { - if (dynamicPropertiesStore.supportAllowOptimizeLockDelegateResource()) { + if (dynamicPropertiesStore.supportMaxDelegateLockPeriod()) { expireTime = now + (lockPeriod == 0 ? DELEGATE_PERIOD : lockPeriod * 3 * 1000); } else { expireTime = now + DELEGATE_PERIOD; diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 7cc45a0021a..24e54c1603b 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -692,35 +692,36 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } - case ALLOW_CANCEL_UNFREEZE_V2: { + case ALLOW_CANCEL_ALL_UNFREEZE_V2: { if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7_2)) { throw new ContractValidateException( - "Bad chain parameter id [ALLOW_CANCEL_UNFREEZE_V2]"); + "Bad chain parameter id [ALLOW_CANCEL_ALL_UNFREEZE_V2]"); } if (value != 1) { throw new ContractValidateException( - "This value[ALLOW_CANCEL_UNFREEZE_V2] is only allowed to be 1"); + "This value[ALLOW_CANCEL_ALL_UNFREEZE_V2] is only allowed to be 1"); } if (dynamicPropertiesStore.getUnfreezeDelayDays() == 0) { throw new ContractValidateException( "[UNFREEZE_DELAY_DAYS] proposal must be approved " - + "before [ALLOW_CANCEL_UNFREEZE_V2] can be proposed"); + + "before [ALLOW_CANCEL_ALL_UNFREEZE_V2] can be proposed"); } break; } - case ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE: { + case MAX_DELEGATE_LOCK_PERIOD: { if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7_2)) { throw new ContractValidateException( - "Bad chain parameter id [ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE]"); + "Bad chain parameter id [MAX_DELEGATE_LOCK_PERIOD]"); } - if (value != 1) { + if (value <= 0) { throw new ContractValidateException( - "This value[ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE] is only allowed to be 1"); + "This value[MAX_DELEGATE_LOCK_PERIOD] is only allowed to be " + + "greater than 0"); } if (dynamicPropertiesStore.getUnfreezeDelayDays() == 0) { throw new ContractValidateException( "[UNFREEZE_DELAY_DAYS] proposal must be approved " - + "before [ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE] can be proposed"); + + "before [MAX_DELEGATE_LOCK_PERIOD] can be proposed"); } break; } @@ -798,8 +799,8 @@ public enum ProposalType { // current value, value range DYNAMIC_ENERGY_INCREASE_FACTOR(74), // 0, [0, 10_000] DYNAMIC_ENERGY_MAX_FACTOR(75), // 0, [0, 100_000] ALLOW_TVM_SHANGHAI(76), // 0, 1 - ALLOW_CANCEL_UNFREEZE_V2(77), // 0, 1 - ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE(78); // 0, 1 + ALLOW_CANCEL_ALL_UNFREEZE_V2(77), // 0, 1 + MAX_DELEGATE_LOCK_PERIOD(78); // 0, 1 private long code; diff --git a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java index e8fe963f89b..462a80fa600 100644 --- a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java @@ -17,7 +17,6 @@ import static org.tron.common.crypto.Hash.sha3omit12; import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_COST_BASE_SIZE; -import static org.tron.core.config.Parameter.ChainConstant.MAX_BLOCK_NUM_DELEGATE_PERIOD; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import com.google.common.base.CaseFormat; @@ -279,13 +278,19 @@ public static long consumeBandWidthSize( return bytesSize; } - public static long estimateConsumeBandWidthSize(final AccountCapsule ownerCapsule, ChainBaseManager chainBaseManager) { - DelegateResourceContract.Builder builder = DelegateResourceContract.newBuilder() - .setLock(true) - .setLockPeriod(MAX_BLOCK_NUM_DELEGATE_PERIOD) - .setBalance(ownerCapsule.getFrozenV2BalanceForBandwidth()); + DelegateResourceContract.Builder builder; + if (chainBaseManager.getDynamicPropertiesStore().supportMaxDelegateLockPeriod()) { + builder = DelegateResourceContract.newBuilder() + .setLock(true) + .setLockPeriod(chainBaseManager.getDynamicPropertiesStore().getMaxDelegateLockPeriod()) + .setBalance(ownerCapsule.getFrozenV2BalanceForBandwidth()); + } else { + builder = DelegateResourceContract.newBuilder() + .setLock(true) + .setBalance(ownerCapsule.getFrozenV2BalanceForBandwidth()); + } TransactionCapsule fakeTransactionCapsule = new TransactionCapsule(builder.build() , ContractType.DelegateResourceContract); long size1 = consumeBandWidthSize(fakeTransactionCapsule, chainBaseManager); diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionResultCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionResultCapsule.java index 4e93a52d2ac..be86a95f4f6 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionResultCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionResultCapsule.java @@ -89,13 +89,13 @@ public void setWithdrawExpireAmount(long amount) { .setWithdrawExpireAmount(amount).build(); } - public long getCancelUnfreezeV2Amount() { - return transactionResult.getCancelUnfreezeV2Amount(); + public long getCancelAllUnfreezeV2Amount() { + return transactionResult.getCancelAllUnfreezeV2Amount(); } - public void setCancelUnfreezeV2Amount(long amount) { + public void setCancelAllUnfreezeV2Amount(long amount) { this.transactionResult = this.transactionResult.toBuilder() - .setCancelUnfreezeV2Amount(amount).build(); + .setCancelAllUnfreezeV2Amount(amount).build(); } public long getExchangeReceivedAmount() { diff --git a/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java b/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java index ca366a3d8d7..047a21b68cb 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java +++ b/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java @@ -100,7 +100,7 @@ public static TransactionInfoCapsule buildTransactionInfoInstance(TransactionCap builder.setExchangeId(programResult.getRet().getExchangeId()); builder.setWithdrawAmount(programResult.getRet().getWithdrawAmount()); builder.setWithdrawExpireAmount(programResult.getRet().getWithdrawExpireAmount()); - builder.setCancelUnfreezeV2Amount(programResult.getRet().getCancelUnfreezeV2Amount()); + builder.setCancelAllUnfreezeV2Amount(programResult.getRet().getCancelAllUnfreezeV2Amount()); builder.setExchangeReceivedAmount(programResult.getRet().getExchangeReceivedAmount()); builder.setExchangeInjectAnotherAmount(programResult.getRet().getExchangeInjectAnotherAmount()); builder.setExchangeWithdrawAnotherAmount( diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index d1a4140e461..b5a11be1545 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -207,11 +207,11 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_TVM_SHANGHAI = "ALLOW_TVM_SHANGHAI".getBytes(); - private static final byte[] ALLOW_CANCEL_UNFREEZE_V2 = "ALLOW_CANCEL_UNFREEZE_V2" + private static final byte[] ALLOW_CANCEL_ALL_UNFREEZE_V2 = "ALLOW_CANCEL_ALL_UNFREEZE_V2" .getBytes(); - private static final byte[] ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE = - "ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE".getBytes(); + private static final byte[] MAX_DELEGATE_LOCK_PERIOD = + "MAX_DELEGATE_LOCK_PERIOD".getBytes(); @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { @@ -2783,36 +2783,36 @@ public long getAllowTvmShangHai() { .orElse(CommonParameter.getInstance().getAllowTvmShangHai()); } - public void saveAllowCancelUnfreezeV2(long allowCancelUnfreezeV2) { - this.put(DynamicPropertiesStore.ALLOW_CANCEL_UNFREEZE_V2, - new BytesCapsule(ByteArray.fromLong(allowCancelUnfreezeV2))); + public void saveAllowCancelAllUnfreezeV2(long allowCancelAllUnfreezeV2) { + this.put(DynamicPropertiesStore.ALLOW_CANCEL_ALL_UNFREEZE_V2, + new BytesCapsule(ByteArray.fromLong(allowCancelAllUnfreezeV2))); } - public long getAllowCancelUnfreezeV2() { - return Optional.ofNullable(getUnchecked(ALLOW_CANCEL_UNFREEZE_V2)) + public long getAllowCancelAllUnfreezeV2() { + return Optional.ofNullable(getUnchecked(ALLOW_CANCEL_ALL_UNFREEZE_V2)) .map(BytesCapsule::getData) .map(ByteArray::toLong) - .orElse(CommonParameter.getInstance().getAllowCancelUnfreezeV2()); + .orElse(CommonParameter.getInstance().getAllowCancelAllUnfreezeV2()); } - public boolean supportAllowCancelUnfreezeV2() { - return getAllowCancelUnfreezeV2() == 1L && getUnfreezeDelayDays() > 0; + public boolean supportAllowCancelAllUnfreezeV2() { + return getAllowCancelAllUnfreezeV2() == 1L && getUnfreezeDelayDays() > 0; } - public void saveAllowOptimizeLockDelegateResource(long allowOptimizeLockDelegateResource) { - this.put(DynamicPropertiesStore.ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE, - new BytesCapsule(ByteArray.fromLong(allowOptimizeLockDelegateResource))); + public void saveMaxDelegateLockPeriod(long maxDelegateLockPeriod) { + this.put(DynamicPropertiesStore.MAX_DELEGATE_LOCK_PERIOD, + new BytesCapsule(ByteArray.fromLong(maxDelegateLockPeriod))); } - public long getAllowOptimizeLockDelegateResource() { - return Optional.ofNullable(getUnchecked(ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE)) + public long getMaxDelegateLockPeriod() { + return Optional.ofNullable(getUnchecked(MAX_DELEGATE_LOCK_PERIOD)) .map(BytesCapsule::getData) .map(ByteArray::toLong) - .orElse(CommonParameter.getInstance().getAllowOptimizeLockDelegateResource()); + .orElse(CommonParameter.getInstance().getMaxDelegateLockPeriod()); } - public boolean supportAllowOptimizeLockDelegateResource() { - return getAllowOptimizeLockDelegateResource() == 1L && getUnfreezeDelayDays() > 0; + public boolean supportMaxDelegateLockPeriod() { + return getMaxDelegateLockPeriod() > 0 && getUnfreezeDelayDays() > 0; } private static class DynamicResourceProperties { diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index c6917d0351a..01c07169c08 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -653,11 +653,11 @@ public class CommonParameter { @Getter @Setter - public long allowCancelUnfreezeV2; + public long allowCancelAllUnfreezeV2; @Getter @Setter - public long allowOptimizeLockDelegateResource; + public long maxDelegateLockPeriod; private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index 822a79896cc..5a170577b99 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -74,7 +74,6 @@ public class ChainConstant { public static final int BLOCK_VERSION = 28; public static final long FROZEN_PERIOD = 86_400_000L; public static final long DELEGATE_PERIOD = 3 * 86_400_000L; - public static final long MAX_BLOCK_NUM_DELEGATE_PERIOD = 10512000L; public static final long TRX_PRECISION = 1000_000L; public static final long DELEGATE_COST_BASE_SIZE = 275L; } diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index cf1bcb7f909..b866ab54001 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1326,13 +1326,13 @@ public Protocol.ChainParameters getChainParameters() { .build()); builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() - .setKey("getAllowCancelUnfreezeV2") - .setValue(dbManager.getDynamicPropertiesStore().getAllowCancelUnfreezeV2()) + .setKey("getAllowCancelAllUnfreezeV2") + .setValue(dbManager.getDynamicPropertiesStore().getAllowCancelAllUnfreezeV2()) .build()); builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() - .setKey("getAllowOptimizeLockDelegateResource") - .setValue(dbManager.getDynamicPropertiesStore().getAllowOptimizeLockDelegateResource()) + .setKey("getMaxDelegateLockPeriod") + .setValue(dbManager.getDynamicPropertiesStore().getMaxDelegateLockPeriod()) .build()); return builder.build(); diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 813c7a7931b..2cbf0c053d6 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -343,19 +343,16 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveAllowTvmShangHai(entry.getValue()); break; } - case ALLOW_CANCEL_UNFREEZE_V2: { - if (manager.getDynamicPropertiesStore().getAllowCancelUnfreezeV2() == 0) { - manager.getDynamicPropertiesStore().saveAllowCancelUnfreezeV2(entry.getValue()); + case ALLOW_CANCEL_ALL_UNFREEZE_V2: { + if (manager.getDynamicPropertiesStore().getAllowCancelAllUnfreezeV2() == 0) { + manager.getDynamicPropertiesStore().saveAllowCancelAllUnfreezeV2(entry.getValue()); manager.getDynamicPropertiesStore().addSystemContractAndSetPermission( - ContractType.CancelUnfreezeV2Contract_VALUE); + ContractType.CancelAllUnfreezeV2Contract_VALUE); } break; } - case ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE: { - if (manager.getDynamicPropertiesStore().getAllowOptimizeLockDelegateResource() == 0) { - manager.getDynamicPropertiesStore() - .saveAllowOptimizeLockDelegateResource(entry.getValue()); - } + case MAX_DELEGATE_LOCK_PERIOD: { + manager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(entry.getValue()); break; } default: diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index e99ed96dd46..2a4ebca95b4 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -130,7 +130,7 @@ import org.tron.protos.contract.BalanceContract.AccountBalanceRequest; import org.tron.protos.contract.BalanceContract.AccountBalanceResponse; import org.tron.protos.contract.BalanceContract.BlockBalanceTrace; -import org.tron.protos.contract.BalanceContract.CancelUnfreezeV2Contract; +import org.tron.protos.contract.BalanceContract.CancelAllUnfreezeV2Contract; import org.tron.protos.contract.BalanceContract.DelegateResourceContract; import org.tron.protos.contract.BalanceContract.FreezeBalanceContract; import org.tron.protos.contract.BalanceContract.TransferContract; @@ -1473,9 +1473,9 @@ public void unDelegateResource(UnDelegateResourceContract request, } @Override - public void cancelUnfreezeV2(CancelUnfreezeV2Contract request, + public void cancelAllUnfreezeV2(CancelAllUnfreezeV2Contract request, StreamObserver responseObserver) { - createTransactionExtention(request, ContractType.CancelUnfreezeV2Contract, + createTransactionExtention(request, ContractType.CancelAllUnfreezeV2Contract, responseObserver); } diff --git a/framework/src/main/java/org/tron/core/services/http/CancelUnfreezeV2Servlet.java b/framework/src/main/java/org/tron/core/services/http/CancelAllUnfreezeV2Servlet.java similarity index 82% rename from framework/src/main/java/org/tron/core/services/http/CancelUnfreezeV2Servlet.java rename to framework/src/main/java/org/tron/core/services/http/CancelAllUnfreezeV2Servlet.java index 601379e5547..894126e50da 100644 --- a/framework/src/main/java/org/tron/core/services/http/CancelUnfreezeV2Servlet.java +++ b/framework/src/main/java/org/tron/core/services/http/CancelAllUnfreezeV2Servlet.java @@ -10,11 +10,11 @@ import org.tron.core.Wallet; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.contract.BalanceContract.CancelUnfreezeV2Contract; +import org.tron.protos.contract.BalanceContract.CancelAllUnfreezeV2Contract; @Component @Slf4j(topic = "API") -public class CancelUnfreezeV2Servlet extends RateLimiterServlet { +public class CancelAllUnfreezeV2Servlet extends RateLimiterServlet { @Autowired private Wallet wallet; @@ -23,10 +23,10 @@ public class CancelUnfreezeV2Servlet extends RateLimiterServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) { try { PostParams params = PostParams.getPostParams(request); - CancelUnfreezeV2Contract.Builder build = CancelUnfreezeV2Contract.newBuilder(); + CancelAllUnfreezeV2Contract.Builder build = CancelAllUnfreezeV2Contract.newBuilder(); JsonFormat.merge(params.getParams(), build, params.isVisible()); Transaction tx = wallet - .createTransactionCapsule(build.build(), ContractType.CancelUnfreezeV2Contract) + .createTransactionCapsule(build.build(), ContractType.CancelAllUnfreezeV2Contract) .getInstance(); JSONObject jsonObject = JSON.parseObject(params.getParams()); tx = Util.setTransactionPermissionId(jsonObject, tx); diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index cac81174939..082307fe629 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -303,7 +303,7 @@ public class FullNodeHttpApiService implements Service { @Autowired private UnDelegateResourceServlet unDelegateResourceServlet; @Autowired - private CancelUnfreezeV2Servlet cancelUnfreezeV2Servlet; + private CancelAllUnfreezeV2Servlet cancelAllUnfreezeV2Servlet; private static String getParamsFile(String fileName) { InputStream in = Thread.currentThread().getContextClassLoader() @@ -566,8 +566,8 @@ public void start() { "/wallet/delegateresource"); context.addServlet(new ServletHolder(unDelegateResourceServlet), "/wallet/undelegateresource"); - context.addServlet(new ServletHolder(cancelUnfreezeV2Servlet), - "/wallet/cancelunfreezev2"); + context.addServlet(new ServletHolder(cancelAllUnfreezeV2Servlet), + "/wallet/cancelallunfreezev2"); int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { diff --git a/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java b/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java index 5445a387278..c551259fb3e 100644 --- a/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java +++ b/framework/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java @@ -144,8 +144,8 @@ public class HttpSelfFormatFieldName { //UnDelegateResourceContract AddressFieldNameMap.put("protocol.UnDelegateResourceContract.owner_address", 1); AddressFieldNameMap.put("protocol.UnDelegateResourceContract.receiver_address", 1); - //CancelUnfreezeV2Contract - AddressFieldNameMap.put("protocol.CancelUnfreezeV2Contract.owner_address", 1); + //CancelAllUnfreezeV2Contract + AddressFieldNameMap.put("protocol.CancelAllUnfreezeV2Contract.owner_address", 1); AddressFieldNameMap.put("protocol.CanDelegatedMaxSizeRequestMessage.owner_address", 1); AddressFieldNameMap.put("protocol.GetAvailableUnfreezeCountRequestMessage.owner_address", 1); AddressFieldNameMap.put("protocol.CanWithdrawUnfreezeAmountRequestMessage.owner_address", 1); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java index 7b71f354293..776c74266aa 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java @@ -216,6 +216,7 @@ public static long getTransactionAmount(Transaction.Contract contract, String ha case WithdrawBalanceContract: case WithdrawExpireUnfreezeContract: case UnfreezeBalanceV2Contract: + case CancelAllUnfreezeV2Contract: TransactionInfo transactionInfo = wallet .getTransactionInfoById(ByteString.copyFrom(ByteArray.fromHexString(hash))); amount = getAmountFromTransactionInfo(hash, contract.getType(), transactionInfo); @@ -292,6 +293,7 @@ public static long getTransactionAmount(Transaction.Contract contract, String ha case WithdrawBalanceContract: case WithdrawExpireUnfreezeContract: case UnfreezeBalanceV2Contract: + case CancelAllUnfreezeV2Contract: amount = getAmountFromTransactionInfo(hash, contract.getType(), transactionInfo); break; case UnfreezeAssetContract: @@ -334,8 +336,8 @@ public static long getAmountFromTransactionInfo(String hash, ContractType contra case WithdrawExpireUnfreezeContract: amount = transactionInfo.getWithdrawExpireAmount(); break; - case CancelUnfreezeV2Contract: - amount = transactionInfo.getCancelUnfreezeV2Amount(); + case CancelAllUnfreezeV2Contract: + amount = transactionInfo.getCancelAllUnfreezeV2Amount(); break; default: break; diff --git a/framework/src/test/java/org/tron/common/logsfilter/EventLoaderTest.java b/framework/src/test/java/org/tron/common/logsfilter/EventLoaderTest.java index c2bf24ba383..8ff8167f52e 100644 --- a/framework/src/test/java/org/tron/common/logsfilter/EventLoaderTest.java +++ b/framework/src/test/java/org/tron/common/logsfilter/EventLoaderTest.java @@ -4,6 +4,8 @@ import java.util.List; import org.junit.Assert; import org.junit.Test; +import org.tron.common.logsfilter.trigger.BlockLogTrigger; +import org.tron.common.logsfilter.trigger.TransactionLogTrigger; public class EventLoaderTest { @@ -24,8 +26,57 @@ public void launchNativeQueue() { config.setTriggerConfigList(triggerConfigList); - Assert.assertEquals(true, EventPluginLoader.getInstance().start(config)); + Assert.assertTrue(EventPluginLoader.getInstance().start(config)); EventPluginLoader.getInstance().stopPlugin(); } + + @Test + public void testBlockLogTrigger() { + BlockLogTrigger blt = new BlockLogTrigger(); + blt.setBlockHash(blt.getBlockHash()); + blt.setBlockNumber(blt.getBlockNumber()); + blt.setTransactionSize(blt.getTransactionSize()); + blt.setLatestSolidifiedBlockNumber(blt.getLatestSolidifiedBlockNumber()); + blt.setTriggerName(blt.getTriggerName()); + blt.setTimeStamp(blt.getTimeStamp()); + blt.setTransactionList(blt.getTransactionList()); + Assert.assertNotNull(blt.toString()); + } + + @Test + public void testTransactionLogTrigger() { + TransactionLogTrigger tlt = new TransactionLogTrigger(); + tlt.setBlockHash(tlt.getBlockHash()); + tlt.setBlockNumber(tlt.getBlockNumber()); + tlt.setTransactionId(tlt.getTransactionId()); + tlt.setLatestSolidifiedBlockNumber(tlt.getLatestSolidifiedBlockNumber()); + tlt.setTriggerName(tlt.getTriggerName()); + tlt.setTimeStamp(tlt.getTimeStamp()); + tlt.setEnergyFee(tlt.getEnergyFee()); + tlt.setNetFee(tlt.getNetFee()); + tlt.setEnergyUsage(tlt.getEnergyUsage()); + tlt.setAssetAmount(tlt.getAssetAmount()); + tlt.setContractAddress(tlt.getContractAddress()); + tlt.setResult(tlt.getResult()); + tlt.setContractResult(tlt.getContractResult()); + tlt.setContractType(tlt.getContractType()); + tlt.setContractCallValue(tlt.getContractCallValue()); + tlt.setFromAddress(tlt.getFromAddress()); + tlt.setToAddress(tlt.getToAddress()); + tlt.setTransactionIndex(tlt.getTransactionIndex()); + tlt.setFeeLimit(tlt.getFeeLimit()); + tlt.setCumulativeEnergyUsed(tlt.getCumulativeEnergyUsed()); + tlt.setData(tlt.getData()); + tlt.setOriginEnergyUsage(tlt.getOriginEnergyUsage()); + tlt.setEnergyUsageTotal(tlt.getEnergyUsageTotal()); + tlt.setNetUsage(tlt.getNetUsage()); + tlt.setAssetName(tlt.getAssetName()); + tlt.setInternalTransactionList(tlt.getInternalTransactionList()); + tlt.setPreCumulativeLogCount(tlt.getPreCumulativeLogCount()); + tlt.setLogList(tlt.getLogList()); + tlt.setEnergyUnitPrice(tlt.getEnergyUnitPrice()); + tlt.setTimeStamp(1L); + Assert.assertNotNull(tlt.toString()); + } } diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index b487a0f8421..97f024dddcb 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -791,8 +791,20 @@ public void testGetCanDelegatedMaxSizeBandWidth() { GrpcAPI.CanDelegatedMaxSizeResponseMessage message = wallet.getCanDelegatedMaxSize( ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), BANDWIDTH.getNumber()); - Assert.assertEquals(initBalance - 285L, message.getMaxSize()); + Assert.assertEquals(initBalance - 280L, message.getMaxSize()); + chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(0); + } + @Test + public void testGetCanDelegatedMaxSizeBandWidth2() { + chainBaseManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(14); + chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(1); + freezeBandwidthForOwner(); + GrpcAPI.CanDelegatedMaxSizeResponseMessage message = wallet.getCanDelegatedMaxSize( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + BANDWIDTH.getNumber()); + Assert.assertEquals(initBalance - 282L, message.getMaxSize()); + chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(0); } @Test diff --git a/framework/src/test/java/org/tron/core/actuator/CancelUnfreezeV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/CancelAllUnfreezeV2ActuatorTest.java similarity index 51% rename from framework/src/test/java/org/tron/core/actuator/CancelUnfreezeV2ActuatorTest.java rename to framework/src/test/java/org/tron/core/actuator/CancelAllUnfreezeV2ActuatorTest.java index 9af9c42addf..5b417833c1d 100644 --- a/framework/src/test/java/org/tron/core/actuator/CancelUnfreezeV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/CancelAllUnfreezeV2ActuatorTest.java @@ -7,7 +7,6 @@ import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; import static org.tron.protos.contract.Common.ResourceCode.ENERGY; -import com.beust.jcommander.internal.Lists; import com.google.protobuf.Any; import com.google.protobuf.ByteString; import lombok.extern.slf4j.Slf4j; @@ -26,7 +25,7 @@ import org.tron.protos.contract.BalanceContract; @Slf4j -public class CancelUnfreezeV2ActuatorTest extends BaseTest { +public class CancelAllUnfreezeV2ActuatorTest extends BaseTest { private static final String OWNER_ADDRESS; private static final String RECEIVER_ADDRESS; @@ -46,7 +45,7 @@ public class CancelUnfreezeV2ActuatorTest extends BaseTest { @Before public void setUp() { dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); - dbManager.getDynamicPropertiesStore().saveAllowCancelUnfreezeV2(1); + dbManager.getDynamicPropertiesStore().saveAllowCancelAllUnfreezeV2(1); AccountCapsule ownerCapsule = new AccountCapsule(ByteString.copyFromUtf8("owner"), ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), Protocol.AccountType.Normal, @@ -59,35 +58,6 @@ public void setUp() { dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); } - @Test - public void testCancelUnfreezeV2() { - long now = System.currentTimeMillis(); - AccountCapsule accountCapsule = dbManager.getAccountStore() - .get(ByteArray.fromHexString(OWNER_ADDRESS)); - accountCapsule.addUnfrozenV2List(BANDWIDTH, 1000000L, now + 14 * 24 * 3600 * 1000); - accountCapsule.addUnfrozenV2List(ENERGY, 2000000L, -1); - accountCapsule.addUnfrozenV2List(BANDWIDTH, 3000000L, now + 14 * 24 * 3600 * 1000); - accountCapsule.addUnfrozenV2List(ENERGY, 4000000L, now + 14 * 24 * 3600 * 1000); - accountCapsule.addUnfrozenV2List(BANDWIDTH, 4000000L, 100); - accountCapsule.addUnfrozenV2List(ENERGY, 4000000L, 100); - dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); - CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); - actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getCancelUnfreezeV2Contract()); - TransactionResultCapsule ret = new TransactionResultCapsule(); - try { - actuator.validate(); - actuator.execute(ret); - assertEquals(SUCESS, ret.getInstance().getRet()); - AccountCapsule owner = dbManager.getAccountStore() - .get(ByteArray.fromHexString(OWNER_ADDRESS)); - assertEquals(2000000L, ret.getInstance().getWithdrawExpireAmount()); - assertEquals(2, owner.getUnfrozenV2List().size()); - } catch (ContractValidateException | ContractExeException e) { - fail(); - } - } - @Test public void testCancelAllUnfreezeV2() { long now = System.currentTimeMillis(); @@ -100,7 +70,7 @@ public void testCancelAllUnfreezeV2() { accountCapsule.addUnfrozenV2List(BANDWIDTH, 4000000L, 100); accountCapsule.addUnfrozenV2List(ENERGY, 4000000L, 100); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); - CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + CancelAllUnfreezeV2Actuator actuator = new CancelAllUnfreezeV2Actuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) .setAny(getCancelAllUnfreezeV2Contract()); TransactionResultCapsule ret = new TransactionResultCapsule(); @@ -130,9 +100,9 @@ public void testNullTransactionResultCapsule() { accountCapsule.addUnfrozenV2List(BANDWIDTH, 4000000L, 100); accountCapsule.addUnfrozenV2List(ENERGY, 4000000L, 100); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); - CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + CancelAllUnfreezeV2Actuator actuator = new CancelAllUnfreezeV2Actuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getCancelUnfreezeV2Contract()); + .setAny(getCancelAllUnfreezeV2Contract()); try { actuator.validate(); } catch (ContractValidateException e) { @@ -144,33 +114,33 @@ public void testNullTransactionResultCapsule() { @Test public void testInvalidOwnerAddress() { - CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + CancelAllUnfreezeV2Actuator actuator = new CancelAllUnfreezeV2Actuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getCancelUnfreezeV2ContractInvalidAddress()); + .setAny(getCancelAllUnfreezeV2ContractInvalidAddress()); assertThrows("Invalid address", ContractValidateException.class, actuator::validate); } @Test public void testInvalidOwnerAccount() { - CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + CancelAllUnfreezeV2Actuator actuator = new CancelAllUnfreezeV2Actuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getCancelUnfreezeV2ContractInvalidAccount()); + .setAny(getCancelAllUnfreezeV2ContractInvalidAccount()); assertThrows("Account[" + OWNER_ACCOUNT_INVALID + "] does not exist", ContractValidateException.class, actuator::validate); } @Test public void testInvalidOwnerUnfreezeV2List() { - CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + CancelAllUnfreezeV2Actuator actuator = new CancelAllUnfreezeV2Actuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getCancelUnfreezeV2Contract()); + .setAny(getCancelAllUnfreezeV2Contract()); assertThrows("no unfreezeV2 list to cancel", ContractValidateException.class, actuator::validate); } @Test - public void testInvalidCancelUnfreezeV2Contract() { - CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + public void testInvalidCancelAllUnfreezeV2Contract() { + CancelAllUnfreezeV2Actuator actuator = new CancelAllUnfreezeV2Actuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny(null); assertThrows(ActuatorConstant.CONTRACT_NOT_EXIST, ContractValidateException.class, actuator::validate); @@ -178,100 +148,36 @@ public void testInvalidCancelUnfreezeV2Contract() { @Test public void testInvalidAccountStore() { - CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); - actuator.setChainBaseManager(null).setAny(getCancelUnfreezeV2Contract()); + CancelAllUnfreezeV2Actuator actuator = new CancelAllUnfreezeV2Actuator(); + actuator.setChainBaseManager(null).setAny(getCancelAllUnfreezeV2Contract()); assertThrows(ActuatorConstant.STORE_NOT_EXIST, ContractValidateException.class, actuator::validate); } @Test - public void testSupportAllowCancelUnfreezeV2() { - dbManager.getDynamicPropertiesStore().saveAllowCancelUnfreezeV2(0); - CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + public void testSupportAllowCancelAllUnfreezeV2() { + dbManager.getDynamicPropertiesStore().saveAllowCancelAllUnfreezeV2(0); + CancelAllUnfreezeV2Actuator actuator = new CancelAllUnfreezeV2Actuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getCancelUnfreezeV2Contract()); + .setAny(getCancelAllUnfreezeV2Contract()); assertThrows( - "Not support CancelUnfreezeV2 transaction, need to be opened by the committee", - ContractValidateException.class, actuator::validate); - } - - @Test - public void testWrongIndex() { - dbManager.getDynamicPropertiesStore().saveAllowCancelUnfreezeV2(1); - long now = System.currentTimeMillis(); - AccountCapsule accountCapsule = dbManager.getAccountStore() - .get(ByteArray.fromHexString(OWNER_ADDRESS)); - accountCapsule.addUnfrozenV2List(BANDWIDTH, 1000000L, now + 14 * 24 * 3600 * 1000); - accountCapsule.addUnfrozenV2List(ENERGY, 2000000L, -1); - accountCapsule.addUnfrozenV2List(BANDWIDTH, 3000000L, now + 14 * 24 * 3600 * 1000); - accountCapsule.addUnfrozenV2List(ENERGY, 4000000L, now + 14 * 24 * 3600 * 1000); - accountCapsule.addUnfrozenV2List(BANDWIDTH, 4000000L, 100); - accountCapsule.addUnfrozenV2List(ENERGY, 4000000L, 100); - dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); - - CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); - actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getWrongIndexCancelUnfreezeV2Contract()); - assertThrows("The input index[-1] cannot be less than 0 and cannot be greater than " - + "the maximum index[5] of unfreezeV2!", - ContractValidateException.class, actuator::validate); - } - - @Test - public void testWrongIndexSize() { - dbManager.getDynamicPropertiesStore().saveAllowCancelUnfreezeV2(1); - long now = System.currentTimeMillis(); - AccountCapsule accountCapsule = dbManager.getAccountStore() - .get(ByteArray.fromHexString(OWNER_ADDRESS)); - accountCapsule.addUnfrozenV2List(BANDWIDTH, 1000000L, now + 14 * 24 * 3600 * 1000); - accountCapsule.addUnfrozenV2List(ENERGY, 2000000L, -1); - accountCapsule.addUnfrozenV2List(BANDWIDTH, 3000000L, now + 14 * 24 * 3600 * 1000); - accountCapsule.addUnfrozenV2List(ENERGY, 4000000L, now + 14 * 24 * 3600 * 1000); - accountCapsule.addUnfrozenV2List(BANDWIDTH, 4000000L, 100); - accountCapsule.addUnfrozenV2List(ENERGY, 4000000L, 100); - dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); - - CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); - actuator.setChainBaseManager(dbManager.getChainBaseManager()) - .setAny(getWrongIndexSizeCancelUnfreezeV2Contract()); - assertThrows("The size of the index cannot exceed the size of unfrozenV2!", + "Not support CancelAllUnfreezeV2 transaction, need to be opened by the committee", ContractValidateException.class, actuator::validate); } @Test public void testErrorContract() { - dbManager.getDynamicPropertiesStore().saveAllowCancelUnfreezeV2(1); - CancelUnfreezeV2Actuator actuator = new CancelUnfreezeV2Actuator(); + dbManager.getDynamicPropertiesStore().saveAllowCancelAllUnfreezeV2(1); + CancelAllUnfreezeV2Actuator actuator = new CancelAllUnfreezeV2Actuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny(getErrorContract()); assertThrows( - "contract type error, expected type [CancelUnfreezeV2Contract], " + "contract type error, expected type [CancelAllUnfreezeV2Contract], " + "real type[WithdrawExpireUnfreezeContract]", ContractValidateException.class, actuator::validate); } - private Any getCancelUnfreezeV2Contract() { - return Any.pack(BalanceContract.CancelUnfreezeV2Contract.newBuilder() - .addAllIndex(Lists.newArrayList(0, 1, 2, 3)) - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))).build() - ); - } - private Any getCancelAllUnfreezeV2Contract() { - return Any.pack(BalanceContract.CancelUnfreezeV2Contract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))).build() - ); - } - - private Any getWrongIndexSizeCancelUnfreezeV2Contract() { - return Any.pack(BalanceContract.CancelUnfreezeV2Contract.newBuilder() - .addAllIndex(Lists.newArrayList(0, 1, 2, 1, 3, 2, 4)) - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))).build() - ); - } - - private Any getWrongIndexCancelUnfreezeV2Contract() { - return Any.pack(BalanceContract.CancelUnfreezeV2Contract.newBuilder() - .addAllIndex(Lists.newArrayList(-1, 1, 2, 1, 3, 2)) + return Any.pack(BalanceContract.CancelAllUnfreezeV2Contract.newBuilder() .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))).build() ); } @@ -282,13 +188,13 @@ private Any getErrorContract() { ); } - private Any getCancelUnfreezeV2ContractInvalidAddress() { - return Any.pack(BalanceContract.CancelUnfreezeV2Contract.newBuilder().setOwnerAddress( + private Any getCancelAllUnfreezeV2ContractInvalidAddress() { + return Any.pack(BalanceContract.CancelAllUnfreezeV2Contract.newBuilder().setOwnerAddress( ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS_INVALID))).build()); } - private Any getCancelUnfreezeV2ContractInvalidAccount() { - return Any.pack(BalanceContract.CancelUnfreezeV2Contract.newBuilder().setOwnerAddress( + private Any getCancelAllUnfreezeV2ContractInvalidAccount() { + return Any.pack(BalanceContract.CancelAllUnfreezeV2Contract.newBuilder().setOwnerAddress( ByteString.copyFrom(ByteArray.fromHexString(OWNER_ACCOUNT_INVALID))).build() ); } diff --git a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java index a232729d3de..c5ebd31dd08 100644 --- a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java @@ -120,7 +120,7 @@ private Any getLockedDelegateContractForBandwidth(String ownerAddress, String re .build()); } - private Any getOptimizeLockedDelegateContractForBandwidth(long unfreezeBalance, long lockPeriod) { + private Any getMaxDelegateLockPeriodContractForBandwidth(long unfreezeBalance, long lockPeriod) { return Any.pack(DelegateResourceContract.newBuilder() .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))) @@ -131,7 +131,7 @@ private Any getOptimizeLockedDelegateContractForBandwidth(long unfreezeBalance, .build()); } - private Any getOptimizeLockedDelegateContractForEnergy(long unfreezeBalance, long lockPeriod) { + private Any getMaxDelegateLockPeriodContractForEnergy(long unfreezeBalance, long lockPeriod) { return Any.pack(DelegateResourceContract.newBuilder() .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))) @@ -434,26 +434,27 @@ public void testLockedDelegateResourceForBandwidth() { } @Test - public void testOptimizeLockedDelegateResourceForBandwidthWrongLockPeriod1() { - dbManager.getDynamicPropertiesStore().saveAllowOptimizeLockDelegateResource(1); + public void testMaxDelegateLockPeriodForBandwidthWrongLockPeriod1() { + dbManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(1); freezeBandwidthForOwner(); long delegateBalance = 1_000_000_000L; DelegateResourceActuator actuator = new DelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getOptimizeLockedDelegateContractForBandwidth( + getMaxDelegateLockPeriodContractForBandwidth( delegateBalance, 370 * 24 * 3600)); assertThrows("The lock period of delegate resources cannot exceed 1 year!", ContractValidateException.class, actuator::validate); + dbManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(0); } @Test - public void testOptimizeLockedDelegateResourceForBandwidthWrongLockPeriod2() { - dbManager.getDynamicPropertiesStore().saveAllowOptimizeLockDelegateResource(1); + public void testMaxDelegateLockPeriodForBandwidthWrongLockPeriod2() { + dbManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(864000L); freezeBandwidthForOwner(); long delegateBalance = 1_000_000_000L; DelegateResourceActuator actuator = new DelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getOptimizeLockedDelegateContractForBandwidth( + getMaxDelegateLockPeriodContractForBandwidth( delegateBalance, 60)); TransactionResultCapsule ret = new TransactionResultCapsule(); @@ -467,22 +468,23 @@ public void testOptimizeLockedDelegateResourceForBandwidthWrongLockPeriod2() { DelegateResourceActuator actuator1 = new DelegateResourceActuator(); actuator1.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getOptimizeLockedDelegateContractForBandwidth( + getMaxDelegateLockPeriodContractForBandwidth( delegateBalance, 30)); assertThrows("The lock period for bandwidth this time cannot be less than the remaining" + " time[60000s] of the last lock period for bandwidth!", ContractValidateException.class, actuator1::validate); + dbManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(0); } @Test - public void testOptimizeLockedDelegateResourceForBandwidth() { - dbManager.getDynamicPropertiesStore().saveAllowOptimizeLockDelegateResource(1); + public void testMaxDelegateLockPeriodForBandwidth() { + dbManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(864000L); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(50_000L); freezeBandwidthForOwner(); long delegateBalance = 1_000_000_000L; DelegateResourceActuator actuator = new DelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getOptimizeLockedDelegateContractForBandwidth( + getMaxDelegateLockPeriodContractForBandwidth( delegateBalance, 60)); TransactionResultCapsule ret = new TransactionResultCapsule(); @@ -496,7 +498,7 @@ public void testOptimizeLockedDelegateResourceForBandwidth() { DelegateResourceActuator actuator1 = new DelegateResourceActuator(); actuator1.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getOptimizeLockedDelegateContractForBandwidth( + getMaxDelegateLockPeriodContractForBandwidth( delegateBalance, 60)); TransactionResultCapsule ret1 = new TransactionResultCapsule(); @@ -517,14 +519,14 @@ public void testOptimizeLockedDelegateResourceForBandwidth() { } @Test - public void testOptimizeLockedDelegateResourceForEnergy() { - dbManager.getDynamicPropertiesStore().saveAllowOptimizeLockDelegateResource(1); + public void testMaxDelegateLockPeriodForEnergy() { + dbManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(864000L); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(50_000L); freezeCpuForOwner(); long delegateBalance = 1_000_000_000L; DelegateResourceActuator actuator = new DelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getOptimizeLockedDelegateContractForEnergy( + getMaxDelegateLockPeriodContractForEnergy( delegateBalance, 60)); TransactionResultCapsule ret = new TransactionResultCapsule(); @@ -538,7 +540,7 @@ public void testOptimizeLockedDelegateResourceForEnergy() { DelegateResourceActuator actuator1 = new DelegateResourceActuator(); actuator1.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getOptimizeLockedDelegateContractForEnergy( + getMaxDelegateLockPeriodContractForEnergy( delegateBalance, 60)); TransactionResultCapsule ret1 = new TransactionResultCapsule(); @@ -557,13 +559,13 @@ public void testOptimizeLockedDelegateResourceForEnergy() { } @Test - public void testOptimizeLockedDelegateResourceForEnergyWrongLockPeriod2() { - dbManager.getDynamicPropertiesStore().saveAllowOptimizeLockDelegateResource(1); + public void testMaxDelegateLockPeriodForEnergyWrongLockPeriod2() { + dbManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(864000L); freezeCpuForOwner(); long delegateBalance = 1_000_000_000L; DelegateResourceActuator actuator = new DelegateResourceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getOptimizeLockedDelegateContractForEnergy( + getMaxDelegateLockPeriodContractForEnergy( delegateBalance, 60)); TransactionResultCapsule ret = new TransactionResultCapsule(); @@ -577,7 +579,7 @@ public void testOptimizeLockedDelegateResourceForEnergyWrongLockPeriod2() { DelegateResourceActuator actuator1 = new DelegateResourceActuator(); actuator1.setChainBaseManager(dbManager.getChainBaseManager()).setAny( - getOptimizeLockedDelegateContractForEnergy( + getMaxDelegateLockPeriodContractForEnergy( delegateBalance, 30)); assertThrows("The lock period for energy this time cannot be less than the remaining" + " time[60000s] of the last lock period for energy!", @@ -776,6 +778,34 @@ public void commonErrorCheck() { actuatorTest.nullDBManger(); } + @Test + public void testSupportDelegateResource() { + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(0); + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegateContractForBandwidth( + OWNER_ADDRESS, + RECEIVER_ADDRESS, + 1_000_000_000L)); + assertThrows( + "No support for resource delegate", + ContractValidateException.class, actuator::validate); + } + + @Test + public void testSupportUnfreezeDelay() { + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(0); + DelegateResourceActuator actuator = new DelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegateContractForBandwidth( + OWNER_ADDRESS, + RECEIVER_ADDRESS, + 1_000_000_000L)); + assertThrows( + "Not support Delegate resource transaction, need to be opened by the committee", + ContractValidateException.class, actuator::validate); + } + @Test public void testErrorContract() { DelegateResourceActuator actuator = new DelegateResourceActuator(); diff --git a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java index 6bee877318a..6db02667746 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java @@ -148,7 +148,20 @@ public void testEstimateConsumeBandWidthSize() { dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); long estimateConsumeBandWidthSize = TransactionUtil.estimateConsumeBandWidthSize(ownerCapsule, dbManager.getChainBaseManager()); - assertEquals(278L, estimateConsumeBandWidthSize); + assertEquals(275L, estimateConsumeBandWidthSize); + chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(0); + } + + @Test + public void testEstimateConsumeBandWidthSize2() { + chainBaseManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(14); + chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(864000L); + AccountCapsule ownerCapsule = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + long estimateConsumeBandWidthSize = TransactionUtil.estimateConsumeBandWidthSize(ownerCapsule, + dbManager.getChainBaseManager()); + assertEquals(277L, estimateConsumeBandWidthSize); + chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(0); } } diff --git a/framework/src/test/java/org/tron/core/services/http/HttpServletTest.java b/framework/src/test/java/org/tron/core/services/http/HttpServletTest.java index 823a8f7ea1b..dfd4c569e3e 100644 --- a/framework/src/test/java/org/tron/core/services/http/HttpServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/HttpServletTest.java @@ -139,7 +139,7 @@ public class HttpServletTest { private VoteWitnessAccountServlet voteWitnessAccountServlet; private WithdrawBalanceServlet withdrawBalanceServlet; private WithdrawExpireUnfreezeServlet withdrawExpireUnfreezeServlet; - private CancelUnfreezeV2Servlet cancelUnfreezeV2Servlet; + private CancelAllUnfreezeV2Servlet cancelAllUnfreezeV2Servlet; private MockHttpServletRequest request; private MockHttpServletResponse response; @@ -276,7 +276,7 @@ public void setUp() { voteWitnessAccountServlet = new VoteWitnessAccountServlet(); withdrawBalanceServlet = new WithdrawBalanceServlet(); withdrawExpireUnfreezeServlet = new WithdrawExpireUnfreezeServlet(); - cancelUnfreezeV2Servlet = new CancelUnfreezeV2Servlet(); + cancelAllUnfreezeV2Servlet = new CancelAllUnfreezeV2Servlet(); request = new MockHttpServletRequest(); request.setCharacterEncoding("UTF-8"); response = new MockHttpServletResponse(); @@ -528,7 +528,7 @@ public void doPostTest() { voteWitnessAccountServlet.doPost(request, response); withdrawBalanceServlet.doPost(request, response); withdrawExpireUnfreezeServlet.doPost(request, response); - cancelUnfreezeV2Servlet.doPost(request, response); + cancelAllUnfreezeV2Servlet.doPost(request, response); } } diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 1e37f425f50..d23d6e01729 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -281,7 +281,7 @@ service Wallet { rpc UnDelegateResource (UnDelegateResourceContract) returns (TransactionExtention) { } - rpc CancelUnfreezeV2 (CancelUnfreezeV2Contract) returns (TransactionExtention) { + rpc CancelAllUnfreezeV2 (CancelAllUnfreezeV2Contract) returns (TransactionExtention) { } //Please use UpdateAsset2 instead of this function. diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 2ce19ba2708..f52c21162d6 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -374,7 +374,7 @@ message Transaction { WithdrawExpireUnfreezeContract = 56; DelegateResourceContract = 57; UnDelegateResourceContract = 58; - CancelUnfreezeV2Contract = 59; + CancelAllUnfreezeV2Contract = 59; } ContractType type = 1; google.protobuf.Any parameter = 2; @@ -423,7 +423,7 @@ message Transaction { bytes orderId = 25; repeated MarketOrderDetail orderDetails = 26; int64 withdraw_expire_amount = 27; - int64 cancel_unfreezeV2_amount = 28; + int64 cancel_all_unfreezeV2_amount = 28; } message raw { @@ -484,7 +484,7 @@ message TransactionInfo { int64 packingFee = 27; int64 withdraw_expire_amount = 28; - int64 cancel_unfreezeV2_amount = 29; + int64 cancel_all_unfreezeV2_amount = 29; } message TransactionRet { diff --git a/protocol/src/main/protos/core/contract/balance_contract.proto b/protocol/src/main/protos/core/contract/balance_contract.proto index 512b8fb81eb..ea1c96270d6 100644 --- a/protocol/src/main/protos/core/contract/balance_contract.proto +++ b/protocol/src/main/protos/core/contract/balance_contract.proto @@ -113,7 +113,6 @@ message UnDelegateResourceContract { bytes receiver_address = 4; } -message CancelUnfreezeV2Contract { +message CancelAllUnfreezeV2Contract { bytes owner_address = 1; - repeated int32 index = 2; } \ No newline at end of file From 939fdd35a2ed16ef524286af1d1e78d3cc0cfde5 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Wed, 7 Jun 2023 17:25:52 +0800 Subject: [PATCH 0803/1197] feat(hard_fork):optimize log --- .../src/main/java/org/tron/common/utils/ForkController.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/utils/ForkController.java b/chainbase/src/main/java/org/tron/common/utils/ForkController.java index 579e76a409c..0cb60b934ab 100644 --- a/chainbase/src/main/java/org/tron/common/utils/ForkController.java +++ b/chainbase/src/main/java/org/tron/common/utils/ForkController.java @@ -243,8 +243,7 @@ public void checkLocalVersion() { } } if (latestVersion > systemVersion) { - throw new RuntimeException("Version check failed, please upgrade to the latest version," + - " latestVersion:" + latestVersion + ", systemVersion:" + systemVersion); + throw new RuntimeException("Version check failed, please upgrade to the latest version"); } } } From bacd8c265f92e615d8b1f88828659d0123517c19 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 7 Jun 2023 18:49:29 +0800 Subject: [PATCH 0804/1197] fix(net): use khaosdb to judge if beginBlockId exists --- chainbase/src/main/java/org/tron/core/ChainBaseManager.java | 3 +++ .../src/main/java/org/tron/core/net/TronNetDelegate.java | 4 ++++ .../core/net/messagehandler/ChainInventoryMsgHandler.java | 2 +- .../main/java/org/tron/core/net/service/sync/SyncService.java | 3 ++- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java index c9ced891ee6..adf66527499 100644 --- a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java +++ b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java @@ -362,6 +362,9 @@ public boolean containBlockInMainChain(BlockId blockId) { } } + public BlockCapsule getKhaosDbHead(){ + return this.khaosDb.getHead(); + } /** * Get a BlockCapsule by id. diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index 47e13de6109..4d22f98d680 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -146,6 +146,10 @@ public BlockId getHeadBlockId() { return chainBaseManager.getHeadBlockId(); } + public BlockId getKhaosDbHeadBlockId() { + return chainBaseManager.getKhaosDbHead().getBlockId(); + } + public BlockId getSolidBlockId() { return chainBaseManager.getSolidBlockId(); } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java index a2096aac90e..bd2e428418c 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java @@ -72,7 +72,7 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep try { BlockId blockId = null; while (!peer.getSyncBlockToFetch().isEmpty() && tronNetDelegate - .containBlockInMainChain(peer.getSyncBlockToFetch().peek())) { + .containBlock(peer.getSyncBlockToFetch().peek())) { blockId = peer.getSyncBlockToFetch().pop(); peer.setBlockBothHave(blockId); } diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index eef6c7efc88..dab9a25ddd0 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -169,7 +169,8 @@ private LinkedList getBlockChainSummary(PeerConnection peer) throws P2p if (beginBlockId.getNum() == 0) { highNoFork = high = tronNetDelegate.getHeadBlockId().getNum(); } else { - if (tronNetDelegate.containBlockInMainChain(beginBlockId)) { + if (tronNetDelegate.getKhaosDbHeadBlockId().compareTo(beginBlockId) == 0 + || tronNetDelegate.containBlockInMainChain(beginBlockId)) { highNoFork = high = beginBlockId.getNum(); } else { forkList = tronNetDelegate.getBlockChainHashesOnFork(beginBlockId); From eb8ffa1a7c4a2016fe27553e6c50bf2fcfc28870 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 7 Jun 2023 18:29:03 +0800 Subject: [PATCH 0805/1197] feat(freezeV2): optimize proposal validation --- .../src/main/java/org/tron/core/utils/ProposalUtil.java | 9 +++++---- .../java/org/tron/core/store/DynamicPropertiesStore.java | 6 ++++-- .../java/org/tron/common/parameter/CommonParameter.java | 4 ---- framework/src/test/java/org/tron/core/WalletTest.java | 9 +++++---- .../tron/core/actuator/DelegateResourceActuatorTest.java | 7 ++++--- .../tron/core/actuator/utils/TransactionUtilTest.java | 5 +++-- 6 files changed, 21 insertions(+), 19 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 24e54c1603b..5f558c2dc55 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -713,10 +713,11 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, throw new ContractValidateException( "Bad chain parameter id [MAX_DELEGATE_LOCK_PERIOD]"); } - if (value <= 0) { + long maxDelegateLockPeriod = dynamicPropertiesStore.getMaxDelegateLockPeriod(); + if (value <= maxDelegateLockPeriod || value > 10512000L) { throw new ContractValidateException( - "This value[MAX_DELEGATE_LOCK_PERIOD] is only allowed to be " - + "greater than 0"); + "This value[MAX_DELEGATE_LOCK_PERIOD] is only allowed to be greater than " + + maxDelegateLockPeriod + "and less than or equal to 10512000 !"); } if (dynamicPropertiesStore.getUnfreezeDelayDays() == 0) { throw new ContractValidateException( @@ -800,7 +801,7 @@ public enum ProposalType { // current value, value range DYNAMIC_ENERGY_MAX_FACTOR(75), // 0, [0, 100_000] ALLOW_TVM_SHANGHAI(76), // 0, 1 ALLOW_CANCEL_ALL_UNFREEZE_V2(77), // 0, 1 - MAX_DELEGATE_LOCK_PERIOD(78); // 0, 1 + MAX_DELEGATE_LOCK_PERIOD(78); // (86400, 10512000] private long code; diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index b5a11be1545..796ed9a6396 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -1,5 +1,7 @@ package org.tron.core.store; +import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; + import com.google.protobuf.ByteString; import java.util.Arrays; import java.util.Optional; @@ -2808,11 +2810,11 @@ public long getMaxDelegateLockPeriod() { return Optional.ofNullable(getUnchecked(MAX_DELEGATE_LOCK_PERIOD)) .map(BytesCapsule::getData) .map(ByteArray::toLong) - .orElse(CommonParameter.getInstance().getMaxDelegateLockPeriod()); + .orElse(DELEGATE_PERIOD / 3000); } public boolean supportMaxDelegateLockPeriod() { - return getMaxDelegateLockPeriod() > 0 && getUnfreezeDelayDays() > 0; + return (getMaxDelegateLockPeriod() > DELEGATE_PERIOD / 3000) && getUnfreezeDelayDays() > 0; } private static class DynamicResourceProperties { diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 01c07169c08..0c8e6f74ee3 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -655,10 +655,6 @@ public class CommonParameter { @Setter public long allowCancelAllUnfreezeV2; - @Getter - @Setter - public long maxDelegateLockPeriod; - private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 97f024dddcb..15b51f51edf 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; +import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; import static org.tron.protos.contract.Common.ResourceCode.ENERGY; @@ -792,19 +793,19 @@ public void testGetCanDelegatedMaxSizeBandWidth() { ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), BANDWIDTH.getNumber()); Assert.assertEquals(initBalance - 280L, message.getMaxSize()); - chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(0); + chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(DELEGATE_PERIOD / 3000); } @Test public void testGetCanDelegatedMaxSizeBandWidth2() { chainBaseManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(14); - chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(1); + chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(86401); freezeBandwidthForOwner(); GrpcAPI.CanDelegatedMaxSizeResponseMessage message = wallet.getCanDelegatedMaxSize( ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), BANDWIDTH.getNumber()); - Assert.assertEquals(initBalance - 282L, message.getMaxSize()); - chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(0); + Assert.assertEquals(initBalance - 284L, message.getMaxSize()); + chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(DELEGATE_PERIOD / 3000); } @Test diff --git a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java index c5ebd31dd08..b20d55fd983 100644 --- a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java @@ -4,6 +4,7 @@ import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; import static org.tron.protos.contract.Common.ResourceCode.ENERGY; @@ -435,7 +436,7 @@ public void testLockedDelegateResourceForBandwidth() { @Test public void testMaxDelegateLockPeriodForBandwidthWrongLockPeriod1() { - dbManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(1); + dbManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(86401); freezeBandwidthForOwner(); long delegateBalance = 1_000_000_000L; DelegateResourceActuator actuator = new DelegateResourceActuator(); @@ -444,7 +445,7 @@ public void testMaxDelegateLockPeriodForBandwidthWrongLockPeriod1() { delegateBalance, 370 * 24 * 3600)); assertThrows("The lock period of delegate resources cannot exceed 1 year!", ContractValidateException.class, actuator::validate); - dbManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(0); + dbManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(DELEGATE_PERIOD / 3000); } @Test @@ -473,7 +474,7 @@ public void testMaxDelegateLockPeriodForBandwidthWrongLockPeriod2() { assertThrows("The lock period for bandwidth this time cannot be less than the remaining" + " time[60000s] of the last lock period for bandwidth!", ContractValidateException.class, actuator1::validate); - dbManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(0); + dbManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(DELEGATE_PERIOD / 3000); } @Test diff --git a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java index 6db02667746..0baaad7c962 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java @@ -4,6 +4,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.tron.core.capsule.utils.TransactionUtil.isNumber; +import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; import static org.tron.core.utils.TransactionUtil.validAccountId; import static org.tron.core.utils.TransactionUtil.validAccountName; import static org.tron.core.utils.TransactionUtil.validAssetName; @@ -149,7 +150,7 @@ public void testEstimateConsumeBandWidthSize() { long estimateConsumeBandWidthSize = TransactionUtil.estimateConsumeBandWidthSize(ownerCapsule, dbManager.getChainBaseManager()); assertEquals(275L, estimateConsumeBandWidthSize); - chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(0); + chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(DELEGATE_PERIOD / 3000); } @Test @@ -161,7 +162,7 @@ public void testEstimateConsumeBandWidthSize2() { long estimateConsumeBandWidthSize = TransactionUtil.estimateConsumeBandWidthSize(ownerCapsule, dbManager.getChainBaseManager()); assertEquals(277L, estimateConsumeBandWidthSize); - chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(0); + chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(DELEGATE_PERIOD / 3000); } } From 7fe685f16729addecb8bc352daca05d2d47a8914 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 8 Jun 2023 12:01:51 +0800 Subject: [PATCH 0806/1197] fix(net): use equals to compare BlockId --- .../main/java/org/tron/core/net/service/sync/SyncService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index dab9a25ddd0..87f497b1aa7 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -169,7 +169,7 @@ private LinkedList getBlockChainSummary(PeerConnection peer) throws P2p if (beginBlockId.getNum() == 0) { highNoFork = high = tronNetDelegate.getHeadBlockId().getNum(); } else { - if (tronNetDelegate.getKhaosDbHeadBlockId().compareTo(beginBlockId) == 0 + if (tronNetDelegate.getKhaosDbHeadBlockId().equals(beginBlockId) || tronNetDelegate.containBlockInMainChain(beginBlockId)) { highNoFork = high = beginBlockId.getNum(); } else { From 94e186afb151fe91591c2a5eeab2c51789687570 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Fri, 9 Jun 2023 14:47:29 +0800 Subject: [PATCH 0807/1197] feat(hard_fork):remove local version checking logic --- .../org/tron/common/utils/ForkController.java | 40 ++++++------------- .../common/parameter/CommonParameter.java | 3 -- .../src/main/java/org/tron/core/Constant.java | 2 - .../java/org/tron/core/config/args/Args.java | 4 -- .../main/java/org/tron/core/db/Manager.java | 6 --- .../org/tron/core/ForkControllerTest.java | 33 --------------- 6 files changed, 12 insertions(+), 76 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/utils/ForkController.java b/chainbase/src/main/java/org/tron/common/utils/ForkController.java index 0cb60b934ab..e46bd9aed67 100644 --- a/chainbase/src/main/java/org/tron/common/utils/ForkController.java +++ b/chainbase/src/main/java/org/tron/common/utils/ForkController.java @@ -38,6 +38,18 @@ public class ForkController { public void init(ChainBaseManager manager) { this.manager = manager; + DynamicPropertiesStore store = manager.getDynamicPropertiesStore(); + int latestVersion = store.getLatestVersion(); + if (latestVersion == 0) { + for (ForkBlockVersionEnum version : ForkBlockVersionEnum.values()) { + int v = version.getValue(); + if (pass(v) && latestVersion < v) { + latestVersion = v; + } + } + store.saveLatestVersion(latestVersion); + return; + } } public boolean pass(ForkBlockVersionEnum forkBlockVersionEnum) { @@ -218,32 +230,4 @@ private ForkController getInstance() { } } - public void checkLocalVersion() { - DynamicPropertiesStore store = manager.getDynamicPropertiesStore(); - int latestVersion = store.getLatestVersion(); - if (latestVersion == 0) { - for (ForkBlockVersionEnum version : ForkBlockVersionEnum.values()) { - int v = version.getValue(); - if (pass(v) && latestVersion < v) { - latestVersion = v; - } - } - store.saveLatestVersion(latestVersion); - return; - } - - if (!CommonParameter.getInstance().isVersionCheckEnable()) { - return; - } - - int systemVersion = 0; - for (ForkBlockVersionEnum version : ForkBlockVersionEnum.values()) { - if (version.getValue() > systemVersion) { - systemVersion = version.getValue(); - } - } - if (latestVersion > systemVersion) { - throw new RuntimeException("Version check failed, please upgrade to the latest version"); - } - } } diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 338ca38c602..ef89e01925a 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -395,9 +395,6 @@ public class CommonParameter { public boolean version; @Getter @Setter - public boolean versionCheckEnable; - @Getter - @Setter public String zenTokenId; @Getter @Setter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index e15ace95ec2..dea5a2534b9 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -372,7 +372,5 @@ public class Constant { public static final String DYNAMIC_CONFIG_ENABLE = "node.dynamicConfig.enable"; public static final String DYNAMIC_CONFIG_CHECK_INTERVAL = "node.dynamicConfig.checkInterval"; - public static final String NODE_VERSION_CHECK_ENABLE = "node.versionCheckEnable"; - public static final String COMMITTEE_ALLOW_TVM_SHANGHAI = "committee.allowTvmShangHai"; } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 71c4a50ea7a..50e4dacf6a9 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -233,7 +233,6 @@ public static void clearParam() { PARAMETER.p2pDisable = false; PARAMETER.dynamicConfigEnable = false; PARAMETER.dynamicConfigCheckInterval = 600; - PARAMETER.versionCheckEnable = true; PARAMETER.allowTvmShangHai = 0; } @@ -1180,9 +1179,6 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.dynamicConfigCheckInterval = 600; } - PARAMETER.versionCheckEnable = !config.hasPath(Constant.NODE_VERSION_CHECK_ENABLE) - || config.getBoolean(Constant.NODE_VERSION_CHECK_ENABLE); - PARAMETER.allowTvmShangHai = config.hasPath(Constant.COMMITTEE_ALLOW_TVM_SHANGHAI) ? config .getInt(Constant.COMMITTEE_ALLOW_TVM_SHANGHAI) : 0; diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index df9cde80632..a3f8fb8de03 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -486,12 +486,6 @@ public void init() { System.exit(1); } getChainBaseManager().getForkController().init(this.chainBaseManager); - try { - getChainBaseManager().getForkController().checkLocalVersion(); - } catch (RuntimeException r) { - logger.error("{}", r.getMessage()); - System.exit(1); - } if (Args.getInstance().isNeedToUpdateAsset() && needToUpdateAsset()) { new AssetUpdateHelper(chainBaseManager).doWork(); diff --git a/framework/src/test/java/org/tron/core/ForkControllerTest.java b/framework/src/test/java/org/tron/core/ForkControllerTest.java index 5e6783a46ff..20a28f9b619 100644 --- a/framework/src/test/java/org/tron/core/ForkControllerTest.java +++ b/framework/src/test/java/org/tron/core/ForkControllerTest.java @@ -222,39 +222,6 @@ public void testUpdate() { Assert.assertEquals(getSum(bytes), 4); } - @Test - public void testCheck() { - byte[] stats1 = {0, 0, 0, 0, 0}; - byte[] stats2 = {1, 1, 1, 1, 1}; - - for (Parameter.ForkBlockVersionEnum version : Parameter.ForkBlockVersionEnum.values()) { - dynamicPropertiesStore.statsByVersion(version.getValue(), stats1); - } - - dynamicPropertiesStore - .statsByVersion(Parameter.ForkBlockVersionEnum.VERSION_3_5.getValue(), stats2); - - forkController.checkLocalVersion(); - - Assert.assertEquals(dynamicPropertiesStore.getLatestVersion(), - Parameter.ForkBlockVersionEnum.VERSION_3_5.getValue()); - - - Args.getInstance().setVersionCheckEnable(false); - dynamicPropertiesStore.saveLatestVersion(Integer.MAX_VALUE); - - forkController.checkLocalVersion(); - - Args.getInstance().setVersionCheckEnable(true); - - try { - forkController.checkLocalVersion(); - Assert.fail(); - } catch (Exception e) { - Assert.assertTrue(e instanceof RuntimeException); - } - } - private BlockCapsule getBlock(int i, Parameter.ForkBlockVersionEnum versionEnum) { org.tron.protos.Protocol.BlockHeader.raw rawData = org.tron.protos.Protocol.BlockHeader.raw.newBuilder() From 37c224620e6c1218579e3b970b638f056e9dea98 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Fri, 9 Jun 2023 15:47:29 +0800 Subject: [PATCH 0808/1197] feat(hard_fork):optimize hard fork code --- .../src/main/java/org/tron/common/utils/ForkController.java | 1 - 1 file changed, 1 deletion(-) diff --git a/chainbase/src/main/java/org/tron/common/utils/ForkController.java b/chainbase/src/main/java/org/tron/common/utils/ForkController.java index e46bd9aed67..c3db883a011 100644 --- a/chainbase/src/main/java/org/tron/common/utils/ForkController.java +++ b/chainbase/src/main/java/org/tron/common/utils/ForkController.java @@ -48,7 +48,6 @@ public void init(ChainBaseManager manager) { } } store.saveLatestVersion(latestVersion); - return; } } From 7b50828770a0617188ff46c77d9a7f3021ce0312 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Fri, 9 Jun 2023 14:14:08 +0800 Subject: [PATCH 0809/1197] feat(freezeV2): optimize msg format --- .../actuator/DelegateResourceActuator.java | 18 ++++++++++++++---- .../java/org/tron/core/utils/ProposalUtil.java | 2 +- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index aab5e076453..c54c00b5697 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -61,10 +61,10 @@ public boolean execute(Object result) throws ContractExeException { AccountCapsule ownerCapsule = accountStore .get(delegateResourceContract.getOwnerAddress().toByteArray()); - + DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); long delegateBalance = delegateResourceContract.getBalance(); boolean lock = delegateResourceContract.getLock(); - long lockPeriod = delegateResourceContract.getLockPeriod(); + long lockPeriod = getLockPeriod(dynamicStore, delegateResourceContract); byte[] receiverAddress = delegateResourceContract.getReceiverAddress().toByteArray(); // delegate resource to receiver @@ -219,7 +219,7 @@ public boolean validate() throws ContractValidateException { boolean lock = delegateResourceContract.getLock(); if (lock && dynamicStore.supportMaxDelegateLockPeriod()) { - long lockPeriod = delegateResourceContract.getLockPeriod(); + long lockPeriod = getLockPeriod(dynamicStore, delegateResourceContract); long maxDelegateLockPeriod = dynamicStore.getMaxDelegateLockPeriod(); if (lockPeriod < 0 || lockPeriod > maxDelegateLockPeriod) { throw new ContractValidateException( @@ -257,6 +257,16 @@ public boolean validate() throws ContractValidateException { return true; } + private long getLockPeriod(DynamicPropertiesStore dynamicStore, + DelegateResourceContract delegateResourceContract) { + long lockPeriod = delegateResourceContract.getLockPeriod(); + if (dynamicStore.supportMaxDelegateLockPeriod()) { + return lockPeriod == 0 ? DELEGATE_PERIOD / 3000 : lockPeriod; + } else { + return 0; + } + } + private void validRemainTime(ResourceCode resourceCode, long lockPeriod, long expireTime, long now) throws ContractValidateException { long remainTime = expireTime - now; @@ -294,7 +304,7 @@ private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boole long expireTime = 0; if (lock) { if (dynamicPropertiesStore.supportMaxDelegateLockPeriod()) { - expireTime = now + (lockPeriod == 0 ? DELEGATE_PERIOD : lockPeriod * 3 * 1000); + expireTime = now + lockPeriod * 3 * 1000; } else { expireTime = now + DELEGATE_PERIOD; } diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 5f558c2dc55..0e0cc81446c 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -717,7 +717,7 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, if (value <= maxDelegateLockPeriod || value > 10512000L) { throw new ContractValidateException( "This value[MAX_DELEGATE_LOCK_PERIOD] is only allowed to be greater than " - + maxDelegateLockPeriod + "and less than or equal to 10512000 !"); + + maxDelegateLockPeriod + " and less than or equal to 10512000 !"); } if (dynamicPropertiesStore.getUnfreezeDelayDays() == 0) { throw new ContractValidateException( From da93e0912ac73d4d0191ea993e3316bdc357a202 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 15 Jun 2023 16:19:09 +0800 Subject: [PATCH 0810/1197] feat(protocol): remove deprecated shell --- protocol/src/main/protos/.travis.yml | 24 ------------------- protocol/src/main/protos/README.md | 3 --- .../src/main/protos/install-googleapis.sh | 14 ----------- protocol/src/main/protos/install-protobuf.sh | 10 -------- 4 files changed, 51 deletions(-) delete mode 100644 protocol/src/main/protos/.travis.yml delete mode 100755 protocol/src/main/protos/install-googleapis.sh delete mode 100755 protocol/src/main/protos/install-protobuf.sh diff --git a/protocol/src/main/protos/.travis.yml b/protocol/src/main/protos/.travis.yml deleted file mode 100644 index 34fa71b3d15..00000000000 --- a/protocol/src/main/protos/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -language: ruby - -cache: - directories: - - $HOME/protobuf - -sudo: false - -before_install: - - bash install-protobuf.sh - - bash install-googleapis.sh - -# check what has been installed by listing contents of protobuf folder -before_script: - - ls -R $HOME/protobuf - -# let's use protobuf -script: - - $HOME/protobuf/bin/protoc --java_out=./ ./core/*.proto ./api/*.proto - - $HOME/protobuf/bin/protoc -I. -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis --go_out=./ ./core/*.proto - - $HOME/protobuf/bin/protoc -I. -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis --go_out=./ ./api/*.proto - - $HOME/protobuf/bin/protoc -I. -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis --grpc-gateway_out=logtostderr=true:./ ./api/*.proto - - - ls -l \ No newline at end of file diff --git a/protocol/src/main/protos/README.md b/protocol/src/main/protos/README.md index 6a28119119a..0eaf7b30a80 100644 --- a/protocol/src/main/protos/README.md +++ b/protocol/src/main/protos/README.md @@ -6,6 +6,3 @@ java-tron, wallet-cli and grpc-gateway git subtree pull --prefix src/main/protos/ protocol master - -## Run the included *.sh files to initialize the dependencies - diff --git a/protocol/src/main/protos/install-googleapis.sh b/protocol/src/main/protos/install-googleapis.sh deleted file mode 100755 index e1c1df80124..00000000000 --- a/protocol/src/main/protos/install-googleapis.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -set -e - -go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway -go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger -go get -u github.com/golang/protobuf/protoc-gen-go - -wget https://repo1.maven.org/maven2/com/google/api/grpc/googleapis-common-protos/0.0.3/googleapis-common-protos-0.0.3.jar -jar xvf googleapis-common-protos-0.0.3.jar -cp -r google/ $HOME/protobuf/include/ -ls -l - - - diff --git a/protocol/src/main/protos/install-protobuf.sh b/protocol/src/main/protos/install-protobuf.sh deleted file mode 100755 index b3a8cb5cbb2..00000000000 --- a/protocol/src/main/protos/install-protobuf.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -set -e -# check to see if protobuf folder is empty -if [ ! -d "$HOME/protobuf/lib" ]; then - wget https://github.com/google/protobuf/releases/download/v3.5.1/protobuf-all-3.5.1.tar.gz - tar -xzvf protobuf-all-3.5.1.tar.gz - cd protobuf-3.5.1 && ./configure --prefix=$HOME/protobuf && make && make install -else - echo "Using cached directory." -fi From c352b348f115e9b8af4df2f1411eccf96d56015c Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 12 Jun 2023 12:05:17 +0800 Subject: [PATCH 0811/1197] feat(test): replace testng with junit --- actuator/build.gradle | 21 -------- chainbase/build.gradle | 21 -------- consensus/build.gradle | 20 -------- framework/build.gradle | 2 - .../java/org/tron/common/ComparatorTest.java | 2 +- .../common/backup/KeepAliveMessageTest.java | 6 +-- .../common/backup/UdpMessageTypeEnumTest.java | 2 +- .../logsfilter/EventParserJsonTest.java | 2 +- .../common/logsfilter/EventParserTest.java | 4 +- .../tron/common/runtime/InheritanceTest.java | 2 +- .../InternalTransactionComplexTest.java | 2 +- .../common/runtime/ProgramResultTest.java | 49 ++++++++++--------- .../tron/common/runtime/RuntimeImplTest.java | 2 +- .../runtime/RuntimeTransferComplexTest.java | 2 +- .../runtime/vm/AllowTvmCompatibleEvmTest.java | 8 +-- .../common/runtime/vm/AllowTvmLondonTest.java | 4 +- .../vm/BatchValidateSignContractTest.java | 6 +-- .../tron/common/runtime/vm/ChargeTest.java | 2 +- .../tron/common/runtime/vm/Create2Test.java | 7 +-- .../runtime/vm/CreateContractSuicideTest.java | 2 +- .../runtime/vm/EnergyWhenAssertStyleTest.java | 2 +- .../vm/EnergyWhenRequireStyleTest.java | 2 +- .../vm/EnergyWhenSendAndTransferTest.java | 2 +- .../vm/EnergyWhenTimeoutStyleTest.java | 2 +- .../common/runtime/vm/ExtCodeHashTest.java | 2 +- .../vm/InternalTransactionCallTest.java | 2 +- .../common/runtime/vm/IsContractTest.java | 2 +- .../common/runtime/vm/IsSRCandidateTest.java | 2 +- .../tron/common/runtime/vm/IstanbulTest.java | 2 +- .../tron/common/runtime/vm/MemoryTest.java | 2 +- .../common/runtime/vm/RepositoryTest.java | 28 ++++------- .../common/runtime/vm/RewardBalanceTest.java | 2 +- .../tron/common/runtime/vm/StorageTest.java | 2 +- .../common/runtime/vm/TimeBenchmarkTest.java | 2 +- .../runtime/vm/TransferFailedEnergyTest.java | 10 ++-- .../common/runtime/vm/TransferTokenTest.java | 4 +- .../vm/ValidateMultiSignContractTest.java | 12 ++--- .../common/utils/client/utils/HttpMethed.java | 2 +- .../AccountPermissionUpdateActuatorTest.java | 4 +- .../core/actuator/AssetIssueActuatorTest.java | 2 +- .../actuator/CreateAccountActuatorTest.java | 2 +- .../actuator/ExchangeCreateActuatorTest.java | 2 +- .../actuator/ExchangeInjectActuatorTest.java | 2 +- .../ExchangeTransactionActuatorTest.java | 2 +- .../ExchangeWithdrawActuatorTest.java | 2 +- .../MarketCancelOrderActuatorTest.java | 16 +++--- .../actuator/MarketSellAssetActuatorTest.java | 2 +- .../core/capsule/TransactionCapsuleTest.java | 2 +- .../tron/core/capsule/VotesCapsuleTest.java | 2 +- .../tron/core/db/ByteArrayWrapperTest.java | 2 +- .../org/tron/core/db/KhaosDatabaseTest.java | 2 +- .../java/org/tron/core/db/ManagerTest.java | 2 +- .../org/tron/core/db2/SnapshotRootTest.java | 2 +- .../java/org/tron/core/jsonrpc/BloomTest.java | 2 +- .../core/jsonrpc/SectionBloomStoreTest.java | 2 +- .../services/http/BroadcastServletTest.java | 11 +++-- ...GetTransactionByIdSolidityServletTest.java | 6 ++- .../core/witness/ProposalControllerTest.java | 2 +- .../org/tron/core/zksnark/MerkleTreeTest.java | 2 +- .../tron/core/zksnark/SaplingNoteTest.java | 2 +- .../tron/core/zksnark/SendCoinShieldTest.java | 2 +- plugins/build.gradle | 1 - 62 files changed, 129 insertions(+), 195 deletions(-) diff --git a/actuator/build.gradle b/actuator/build.gradle index a230ef4ca7e..15f661be9bd 100644 --- a/actuator/build.gradle +++ b/actuator/build.gradle @@ -16,8 +16,6 @@ dependencies { testImplementation "junit:junit:$junitVersion" testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.testng:testng:$testNgVersion" - compile "org.slf4j:jcl-over-slf4j:$slf4jVersion" compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' compile group: 'commons-codec', name: 'commons-codec', version: '1.11' @@ -49,23 +47,6 @@ test { } } -task testng(type: Test) { - useTestNG() - testLogging { - events = ["skipped", "failed"] - exceptionFormat = "full" - - debug.events = ["skipped", "failed"] - debug.exceptionFormat = "full" - - info.events = ["failed", "skipped"] - info.exceptionFormat = "full" - - warn.events = ["failed", "skipped"] - warn.exceptionFormat = "full" - } -} - jacocoTestReport { reports { xml.enabled = true @@ -78,5 +59,3 @@ jacocoTestReport { } } } - -check.dependsOn testng diff --git a/chainbase/build.gradle b/chainbase/build.gradle index ed9911b0032..fb1778d2fc6 100644 --- a/chainbase/build.gradle +++ b/chainbase/build.gradle @@ -33,8 +33,6 @@ dependencies { testImplementation "junit:junit:$junitVersion" testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.testng:testng:$testNgVersion" - compile group: leveldbGroup, name: leveldbName, version: leveldbVersion compile "org.fusesource.jansi:jansi:$jansiVersion" compile group: 'org.rocksdb', name: 'rocksdbjni', version: '5.15.10' @@ -73,25 +71,6 @@ test { } } -task testng(type: Test) { - useTestNG() - testLogging { - events = ["skipped", "failed"] - exceptionFormat = "full" - - debug.events = ["skipped", "failed"] - debug.exceptionFormat = "full" - - info.events = ["failed", "skipped"] - info.exceptionFormat = "full" - - warn.events = ["failed", "skipped"] - warn.exceptionFormat = "full" - } -} - -check.dependsOn testng - jacoco { toolVersion = jacocoVersion // See http://www.eclemma.org/jacoco/. } diff --git a/consensus/build.gradle b/consensus/build.gradle index c22e961572e..c12662446f1 100644 --- a/consensus/build.gradle +++ b/consensus/build.gradle @@ -13,7 +13,6 @@ dependencies { compile project(":protocol") testImplementation "junit:junit:$junitVersion" testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.testng:testng:$testNgVersion" compile "org.slf4j:jcl-over-slf4j:$slf4jVersion" compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' compile group: 'commons-codec', name: 'commons-codec', version: '1.11' @@ -44,23 +43,6 @@ test { } } -task testng(type: Test) { - useTestNG() - testLogging { - events = ["skipped", "failed"] - exceptionFormat = "full" - - debug.events = ["skipped", "failed"] - debug.exceptionFormat = "full" - - info.events = ["failed", "skipped"] - info.exceptionFormat = "full" - - warn.events = ["failed", "skipped"] - warn.exceptionFormat = "full" - } -} - jacocoTestReport { reports { xml.enabled = true @@ -73,5 +55,3 @@ jacocoTestReport { } } } - -check.dependsOn testng diff --git a/framework/build.gradle b/framework/build.gradle index fbe1fc0308b..44223296645 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -44,8 +44,6 @@ dependencies { testCompile group: 'org.mockito', name: 'mockito-core', version: '2.13.0' testCompile group: 'org.hamcrest', name: 'hamcrest-junit', version: '1.0.0.1' - testCompile group: 'org.testng', name: 'testng', version: '6.14.3' - compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' compile group: 'com.typesafe', name: 'config', version: '1.3.2' diff --git a/framework/src/test/java/org/tron/common/ComparatorTest.java b/framework/src/test/java/org/tron/common/ComparatorTest.java index 51ae5c2d6d6..fec38624364 100644 --- a/framework/src/test/java/org/tron/common/ComparatorTest.java +++ b/framework/src/test/java/org/tron/common/ComparatorTest.java @@ -1,6 +1,7 @@ package org.tron.common; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; import java.util.Comparator; import java.util.List; import lombok.AllArgsConstructor; @@ -8,7 +9,6 @@ import lombok.extern.slf4j.Slf4j; import org.junit.Assert; import org.junit.Test; -import org.testng.collections.Lists; @Slf4j diff --git a/framework/src/test/java/org/tron/common/backup/KeepAliveMessageTest.java b/framework/src/test/java/org/tron/common/backup/KeepAliveMessageTest.java index a93e044db03..67658331913 100644 --- a/framework/src/test/java/org/tron/common/backup/KeepAliveMessageTest.java +++ b/framework/src/test/java/org/tron/common/backup/KeepAliveMessageTest.java @@ -2,8 +2,8 @@ import static org.tron.common.backup.message.UdpMessageTypeEnum.BACKUP_KEEP_ALIVE; +import org.junit.Assert; import org.junit.Test; -import org.testng.Assert; import org.tron.common.backup.message.KeepAliveMessage; import org.tron.protos.Discover; @@ -15,7 +15,7 @@ public void test() throws Exception { Assert.assertTrue(m1.getFlag()); Assert.assertEquals(m1.getPriority(), 10); Assert.assertEquals(m1.getType(), BACKUP_KEEP_ALIVE); - Assert.assertEquals(m1.getFrom(), null); + Assert.assertNull(m1.getFrom()); Assert.assertEquals(m1.getTimestamp(), 0); Assert.assertEquals(m1.getData().length + 1, m1.getSendData().length); @@ -27,6 +27,6 @@ public void test() throws Exception { Assert.assertEquals(m2.getPriority(), 10); Assert.assertEquals(m2.getType(), BACKUP_KEEP_ALIVE); - Assert.assertEquals(m2.getMessageId().getBytes(), m1.getMessageId().getBytes()); + Assert.assertArrayEquals(m2.getMessageId().getBytes(), m1.getMessageId().getBytes()); } } diff --git a/framework/src/test/java/org/tron/common/backup/UdpMessageTypeEnumTest.java b/framework/src/test/java/org/tron/common/backup/UdpMessageTypeEnumTest.java index e3ded4a23e5..72253fa710e 100644 --- a/framework/src/test/java/org/tron/common/backup/UdpMessageTypeEnumTest.java +++ b/framework/src/test/java/org/tron/common/backup/UdpMessageTypeEnumTest.java @@ -3,8 +3,8 @@ import static org.tron.common.backup.message.UdpMessageTypeEnum.BACKUP_KEEP_ALIVE; import static org.tron.common.backup.message.UdpMessageTypeEnum.UNKNOWN; +import org.junit.Assert; import org.junit.Test; -import org.testng.Assert; import org.tron.common.backup.message.UdpMessageTypeEnum; public class UdpMessageTypeEnumTest { diff --git a/framework/src/test/java/org/tron/common/logsfilter/EventParserJsonTest.java b/framework/src/test/java/org/tron/common/logsfilter/EventParserJsonTest.java index 33ab712e52b..34a8e82c424 100644 --- a/framework/src/test/java/org/tron/common/logsfilter/EventParserJsonTest.java +++ b/framework/src/test/java/org/tron/common/logsfilter/EventParserJsonTest.java @@ -7,8 +7,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import org.junit.Assert; import org.junit.Test; -import org.testng.Assert; import org.tron.common.crypto.Hash; import org.tron.common.utils.ByteArray; import org.tron.core.Wallet; diff --git a/framework/src/test/java/org/tron/common/logsfilter/EventParserTest.java b/framework/src/test/java/org/tron/common/logsfilter/EventParserTest.java index b5339156d9a..eff644b9cd9 100644 --- a/framework/src/test/java/org/tron/common/logsfilter/EventParserTest.java +++ b/framework/src/test/java/org/tron/common/logsfilter/EventParserTest.java @@ -6,8 +6,8 @@ import java.util.List; import java.util.Map; import org.bouncycastle.util.Arrays; +import org.junit.Assert; import org.junit.Test; -import org.testng.Assert; import org.tron.common.crypto.Hash; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.ByteArray; @@ -76,7 +76,7 @@ public synchronized void testEventParser() { } Assert.assertEquals(LogInfoTriggerParser.getEntrySignature(entry), eventSign); - Assert.assertEquals(Hash.sha3(LogInfoTriggerParser.getEntrySignature(entry).getBytes()), + Assert.assertArrayEquals(Hash.sha3(LogInfoTriggerParser.getEntrySignature(entry).getBytes()), topicList.get(0)); Assert.assertNotNull(entry); Map dataMap = ContractEventParserAbi.parseEventData(data, topicList, entry); diff --git a/framework/src/test/java/org/tron/common/runtime/InheritanceTest.java b/framework/src/test/java/org/tron/common/runtime/InheritanceTest.java index 3c021d715cc..4121407fe35 100644 --- a/framework/src/test/java/org/tron/common/runtime/InheritanceTest.java +++ b/framework/src/test/java/org/tron/common/runtime/InheritanceTest.java @@ -2,9 +2,9 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.testng.Assert; import org.tron.common.BaseTest; import org.tron.core.Constant; import org.tron.core.Wallet; diff --git a/framework/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java b/framework/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java index de2c32d2731..923f2386605 100644 --- a/framework/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java +++ b/framework/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java @@ -2,9 +2,9 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.testng.Assert; import org.tron.common.BaseTest; import org.tron.common.runtime.vm.DataWord; import org.tron.core.Constant; diff --git a/framework/src/test/java/org/tron/common/runtime/ProgramResultTest.java b/framework/src/test/java/org/tron/common/runtime/ProgramResultTest.java index 393a68a0794..d083b2c729c 100644 --- a/framework/src/test/java/org/tron/common/runtime/ProgramResultTest.java +++ b/framework/src/test/java/org/tron/common/runtime/ProgramResultTest.java @@ -9,9 +9,9 @@ import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.testng.Assert; import org.tron.common.BaseTest; import org.tron.common.runtime.vm.DataWord; import org.tron.core.Constant; @@ -281,30 +281,31 @@ public void successAndFailResultTest() List internalTransactionsList = runtime.getResult() .getInternalTransactions(); Assert.assertEquals(internalTransactionsList.get(0).getValue(), 10); - Assert.assertEquals(internalTransactionsList.get(0).getSender(), aContract); - Assert.assertEquals( + Assert.assertArrayEquals(internalTransactionsList.get(0).getSender(), aContract); + Assert.assertArrayEquals( new DataWord(internalTransactionsList.get(0).getTransferToAddress()).getLast20Bytes(), new DataWord(bContract).getLast20Bytes()); Assert.assertEquals(internalTransactionsList.get(0).getNote(), "create"); Assert.assertFalse(internalTransactionsList.get(0).isRejected()); Assert.assertEquals(internalTransactionsList.get(1).getValue(), 5); - Assert.assertEquals(internalTransactionsList.get(1).getSender(), aContract); - Assert.assertEquals( + Assert.assertArrayEquals(internalTransactionsList.get(1).getSender(), aContract); + Assert.assertArrayEquals( new DataWord(internalTransactionsList.get(1).getTransferToAddress()).getLast20Bytes(), new DataWord(bContract).getLast20Bytes()); Assert.assertEquals(internalTransactionsList.get(1).getNote(), "call"); Assert.assertFalse(internalTransactionsList.get(1).isRejected()); Assert.assertEquals(internalTransactionsList.get(2).getValue(), 0); - Assert.assertEquals(internalTransactionsList.get(2).getSender(), aContract); - Assert.assertEquals( + Assert.assertArrayEquals(internalTransactionsList.get(2).getSender(), aContract); + Assert.assertArrayEquals( new DataWord(internalTransactionsList.get(2).getTransferToAddress()).getLast20Bytes(), new DataWord(bContract).getLast20Bytes()); Assert.assertEquals(internalTransactionsList.get(2).getNote(), "call"); Assert.assertFalse(internalTransactionsList.get(2).isRejected()); Assert.assertEquals(internalTransactionsList.get(3).getValue(), 1); - Assert.assertEquals(new DataWord(internalTransactionsList.get(3).getSender()).getLast20Bytes(), + Assert.assertArrayEquals( + new DataWord(internalTransactionsList.get(3).getSender()).getLast20Bytes(), new DataWord(bContract).getLast20Bytes()); - Assert.assertEquals(internalTransactionsList.get(3).getTransferToAddress(), cContract); + Assert.assertArrayEquals(internalTransactionsList.get(3).getTransferToAddress(), cContract); Assert.assertEquals(internalTransactionsList.get(3).getNote(), "call"); Assert.assertFalse(internalTransactionsList.get(3).isRejected()); checkTransactionInfo(traceSuccess, trx1, null, internalTransactionsList); @@ -326,31 +327,31 @@ public void successAndFailResultTest() List internalTransactionsListFail = runtime.getResult() .getInternalTransactions(); Assert.assertEquals(internalTransactionsListFail.get(0).getValue(), 10); - Assert.assertEquals(internalTransactionsListFail.get(0).getSender(), aContract); - Assert.assertEquals( + Assert.assertArrayEquals(internalTransactionsListFail.get(0).getSender(), aContract); + Assert.assertArrayEquals( new DataWord(internalTransactionsListFail.get(0).getTransferToAddress()).getLast20Bytes(), new DataWord(bContract2).getLast20Bytes()); Assert.assertEquals(internalTransactionsListFail.get(0).getNote(), "create"); Assert.assertTrue(internalTransactionsListFail.get(0).isRejected()); Assert.assertEquals(internalTransactionsListFail.get(1).getValue(), 5); - Assert.assertEquals(internalTransactionsListFail.get(1).getSender(), aContract); - Assert.assertEquals( + Assert.assertArrayEquals(internalTransactionsListFail.get(1).getSender(), aContract); + Assert.assertArrayEquals( new DataWord(internalTransactionsListFail.get(1).getTransferToAddress()).getLast20Bytes(), new DataWord(bContract2).getLast20Bytes()); Assert.assertEquals(internalTransactionsListFail.get(1).getNote(), "call"); Assert.assertTrue(internalTransactionsListFail.get(1).isRejected()); Assert.assertEquals(internalTransactionsListFail.get(2).getValue(), 0); - Assert.assertEquals(internalTransactionsListFail.get(2).getSender(), aContract); - Assert.assertEquals( + Assert.assertArrayEquals(internalTransactionsListFail.get(2).getSender(), aContract); + Assert.assertArrayEquals( new DataWord(internalTransactionsListFail.get(2).getTransferToAddress()).getLast20Bytes(), new DataWord(bContract2).getLast20Bytes()); Assert.assertEquals(internalTransactionsListFail.get(2).getNote(), "call"); Assert.assertTrue(internalTransactionsListFail.get(2).isRejected()); Assert.assertEquals(internalTransactionsListFail.get(3).getValue(), 1); - Assert.assertEquals( + Assert.assertArrayEquals( new DataWord(internalTransactionsListFail.get(3).getSender()).getLast20Bytes(), new DataWord(bContract2).getLast20Bytes()); - Assert.assertEquals(internalTransactionsListFail.get(3).getTransferToAddress(), cContract); + Assert.assertArrayEquals(internalTransactionsListFail.get(3).getTransferToAddress(), cContract); Assert.assertEquals(internalTransactionsListFail.get(3).getNote(), "call"); Assert.assertTrue(internalTransactionsListFail.get(3).isRejected()); checkTransactionInfo(traceFailed, trx2, null, internalTransactionsListFail); @@ -501,9 +502,10 @@ public void suicideResultTest() .assertEquals(dbManager.getAccountStore().get(Hex.decode(TRANSFER_TO)).getBalance(), 1000); Assert.assertNull(dbManager.getAccountStore().get(suicideContract)); Assert.assertEquals(internalTransactionsList.get(0).getValue(), 1000); - Assert.assertEquals(new DataWord(internalTransactionsList.get(0).getSender()).getLast20Bytes(), + Assert.assertArrayEquals(new DataWord( + internalTransactionsList.get(0).getSender()).getLast20Bytes(), new DataWord(suicideContract).getLast20Bytes()); - Assert.assertEquals(internalTransactionsList.get(0).getTransferToAddress(), + Assert.assertArrayEquals(internalTransactionsList.get(0).getTransferToAddress(), Hex.decode(TRANSFER_TO)); Assert.assertEquals(internalTransactionsList.get(0).getNote(), "suicide"); Assert.assertFalse(internalTransactionsList.get(0).isRejected()); @@ -546,15 +548,16 @@ public void checkTransactionInfo(TransactionTrace trace, Transaction trx, BlockC for (int i = 0; i < internalTransactionListFromProtocol.size(); i++) { Assert.assertEquals(internalTransactionListFromProtocol.get(i).getRejected(), internalTransactionsList.get(i).isRejected()); - Assert - .assertEquals(internalTransactionListFromProtocol.get(i).getCallerAddress().toByteArray(), + Assert.assertArrayEquals( + internalTransactionListFromProtocol.get(i).getCallerAddress().toByteArray(), internalTransactionsList.get(i).getSender()); - Assert.assertEquals(internalTransactionListFromProtocol.get(i).getHash().toByteArray(), + Assert.assertArrayEquals( + internalTransactionListFromProtocol.get(i).getHash().toByteArray(), internalTransactionsList.get(i).getHash()); Assert.assertEquals( new String(internalTransactionListFromProtocol.get(i).getNote().toByteArray()), internalTransactionsList.get(i).getNote()); - Assert.assertEquals( + Assert.assertArrayEquals( internalTransactionListFromProtocol.get(i).getTransferToAddress().toByteArray(), internalTransactionsList.get(i).getTransferToAddress()); List callValueInfoListFromProtocol = diff --git a/framework/src/test/java/org/tron/common/runtime/RuntimeImplTest.java b/framework/src/test/java/org/tron/common/runtime/RuntimeImplTest.java index 04b08d3a58d..585a625668a 100644 --- a/framework/src/test/java/org/tron/common/runtime/RuntimeImplTest.java +++ b/framework/src/test/java/org/tron/common/runtime/RuntimeImplTest.java @@ -5,9 +5,9 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.testng.Assert; import org.tron.common.BaseTest; import org.tron.core.Constant; import org.tron.core.Wallet; diff --git a/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java b/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java index b40b927c5ec..366c631ea6e 100644 --- a/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java +++ b/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java @@ -4,9 +4,9 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.testng.Assert; import org.tron.common.BaseTest; import org.tron.common.utils.WalletUtil; import org.tron.common.utils.client.utils.DataWord; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmCompatibleEvmTest.java b/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmCompatibleEvmTest.java index ffc3a44e730..ded7bb01af3 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmCompatibleEvmTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmCompatibleEvmTest.java @@ -7,9 +7,9 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.testng.Assert; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.WalletUtil; @@ -87,7 +87,7 @@ public void testEthRipemd160() throws ContractExeException, ReceiptCheckErrExcep factoryAddress, Hex.decode(hexInput), 0, feeLimit, manager, null); byte[] returnValue = result.getRuntime().getResult().getHReturn(); Assert.assertNull(result.getRuntime().getRuntimeError()); - Assert.assertEquals(returnValue, + Assert.assertArrayEquals(returnValue, hexToBytes("a76d892cc3522eab763529dfc84b12c080ee1" + "fe8000000000000000000000000")); } @@ -212,7 +212,7 @@ public void testBlake2f() throws ContractExeException, ReceiptCheckErrException, factoryAddress, Hex.decode(hexInput), 0, feeLimit, manager, null); byte[] returnValue = result.getRuntime().getResult().getHReturn(); Assert.assertNull(result.getRuntime().getRuntimeError()); - Assert.assertEquals(returnValue, + Assert.assertArrayEquals(returnValue, hexToBytes("ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87" + "c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923")); } @@ -258,7 +258,7 @@ public void testGasPrice() throws ContractExeException, ReceiptCheckErrException factoryAddress, Hex.decode(hexInput), 0, feeLimit, manager, null); byte[] returnValue = result.getRuntime().getResult().getHReturn(); Assert.assertNull(result.getRuntime().getRuntimeError()); - Assert.assertEquals(returnValue, + Assert.assertArrayEquals(returnValue, longTo32Bytes(manager.getDynamicPropertiesStore().getEnergyFee())); } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmLondonTest.java b/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmLondonTest.java index 864a583050b..e93eca39092 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmLondonTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmLondonTest.java @@ -5,8 +5,8 @@ import java.util.Collections; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Test; -import org.testng.Assert; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.WalletUtil; @@ -74,7 +74,7 @@ public void testBaseFee() throws ContractExeException, ReceiptCheckErrException, factoryAddress, Hex.decode(hexInput), 0, feeLimit, manager, null); byte[] returnValue = result.getRuntime().getResult().getHReturn(); Assert.assertNull(result.getRuntime().getRuntimeError()); - Assert.assertEquals(returnValue, + Assert.assertArrayEquals(returnValue, longTo32Bytes(manager.getDynamicPropertiesStore().getEnergyFee())); } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BatchValidateSignContractTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BatchValidateSignContractTest.java index 524c40ee8fb..d094f1a3d05 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BatchValidateSignContractTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BatchValidateSignContractTest.java @@ -6,8 +6,8 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Test; -import org.testng.Assert; import org.tron.common.crypto.ECKey; import org.tron.common.crypto.Hash; import org.tron.common.utils.StringUtil; @@ -73,7 +73,7 @@ public void staticCallTest() { .add(StringUtil.encode58Check(TransactionTrace.convertToTronAddress(new byte[20]))); ret = validateMultiSign(hash, signatures, addresses); Assert.assertEquals(ret.getValue().length, 32); - Assert.assertEquals(ret.getValue(), new byte[32]); + Assert.assertArrayEquals(ret.getValue(), new byte[32]); System.gc(); // force triggering full gc to avoid timeout for next test } @@ -119,7 +119,7 @@ public void correctionTest() { List incorrectSigns = new ArrayList<>(signatures); incorrectSigns.remove(incorrectSigns.size() - 1); ret = validateMultiSign(hash, incorrectSigns, addresses); - Assert.assertEquals(ret.getValue(), DataWord.ZERO().getData()); + Assert.assertArrayEquals(ret.getValue(), DataWord.ZERO().getData()); System.gc(); // force triggering full gc to avoid timeout for next test } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/ChargeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/ChargeTest.java index 600b81750da..78d5fc9e330 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/ChargeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/ChargeTest.java @@ -2,9 +2,9 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.testng.Assert; import org.tron.common.BaseTest; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java index 8f9ea5c059a..79ed1c7e1f8 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java @@ -7,8 +7,8 @@ import java.util.Collections; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Test; -import org.testng.Assert; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.ByteArray; @@ -173,7 +173,7 @@ public void testCreate2() byte[] expectedContract = generateContractAddress2(address, new DataWord(salt).getData(), Hex.decode(testCode)); // check deployed contract - Assert.assertEquals(actualContract, expectedContract); + Assert.assertArrayEquals(actualContract, expectedContract); // trigger deployed contract String methodToTrigger = "plusOne()"; @@ -184,7 +184,8 @@ public void testCreate2() .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), actualContract, Hex.decode(hexInput), 0, fee, manager, null); Assert.assertNull(result.getRuntime().getRuntimeError()); - Assert.assertEquals(result.getRuntime().getResult().getHReturn(), new DataWord(i).getData()); + Assert.assertArrayEquals(result.getRuntime().getResult().getHReturn(), + new DataWord(i).getData()); } testJsonRpc(actualContract, loop); } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/CreateContractSuicideTest.java b/framework/src/test/java/org/tron/common/runtime/vm/CreateContractSuicideTest.java index 9fe5ac1eed1..917c3dec030 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/CreateContractSuicideTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/CreateContractSuicideTest.java @@ -3,8 +3,8 @@ import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Test; -import org.testng.Assert; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.TvmTestUtils; import org.tron.core.config.Parameter.ForkBlockVersionEnum; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java index aec3f2322a6..20abd7467aa 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java @@ -2,9 +2,9 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.testng.Assert; import org.tron.common.BaseTest; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java index 2356a649e82..125d5220f07 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java @@ -2,9 +2,9 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.testng.Assert; import org.tron.common.BaseTest; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java index 40af27612df..4db1b6a2033 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java @@ -2,9 +2,9 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.testng.Assert; import org.tron.common.BaseTest; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java index c2dc1d524ad..6e99d55b668 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java @@ -2,9 +2,9 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.testng.Assert; import org.tron.common.BaseTest; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/ExtCodeHashTest.java b/framework/src/test/java/org/tron/common/runtime/vm/ExtCodeHashTest.java index d8c8a23a8ee..d2ad875e4b0 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/ExtCodeHashTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/ExtCodeHashTest.java @@ -4,8 +4,8 @@ import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Test; -import org.testng.Assert; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.WalletUtil; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/InternalTransactionCallTest.java b/framework/src/test/java/org/tron/common/runtime/vm/InternalTransactionCallTest.java index 18a279f8292..7f7bfd69ca4 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/InternalTransactionCallTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/InternalTransactionCallTest.java @@ -4,9 +4,9 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.testng.Assert; import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/IsContractTest.java b/framework/src/test/java/org/tron/common/runtime/vm/IsContractTest.java index 540a30a240f..94561e856f1 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/IsContractTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/IsContractTest.java @@ -3,8 +3,8 @@ import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Test; -import org.testng.Assert; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.StringUtil; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/IsSRCandidateTest.java b/framework/src/test/java/org/tron/common/runtime/vm/IsSRCandidateTest.java index 3cec683ed63..f6116dbe97d 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/IsSRCandidateTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/IsSRCandidateTest.java @@ -3,8 +3,8 @@ import java.util.Collections; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Test; -import org.testng.Assert; import org.tron.common.runtime.InternalTransaction; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.StringUtil; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/IstanbulTest.java b/framework/src/test/java/org/tron/common/runtime/vm/IstanbulTest.java index 85fb918376d..1613eab53cd 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/IstanbulTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/IstanbulTest.java @@ -1,8 +1,8 @@ package org.tron.common.runtime.vm; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Test; -import org.testng.Assert; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.WalletUtil; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/MemoryTest.java b/framework/src/test/java/org/tron/common/runtime/vm/MemoryTest.java index 0966d86710a..b6e9cfe109c 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/MemoryTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/MemoryTest.java @@ -25,8 +25,8 @@ import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Test; -import org.testng.Assert; import org.tron.core.vm.program.Memory; @Slf4j diff --git a/framework/src/test/java/org/tron/common/runtime/vm/RepositoryTest.java b/framework/src/test/java/org/tron/common/runtime/vm/RepositoryTest.java index 390b1396337..1e92c67a834 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/RepositoryTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/RepositoryTest.java @@ -3,10 +3,10 @@ import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; -import org.testng.Assert; import org.tron.common.BaseTest; import org.tron.common.parameter.CommonParameter; import org.tron.common.runtime.Runtime; @@ -194,7 +194,6 @@ public void loopCallTest() String params1 = Hex.toHexString(new DataWord(bAddress).getData()) + "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000" + "00000000000000000000000000000000000000002"; - System.err.println(params1); byte[] triggerData = TvmTestUtils .parseAbi("callBcallARevert(address,uint256,uint256)", params1); @@ -215,12 +214,10 @@ public void loopCallTest() .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), aAddress, checkN2Data, 0, fee, dbManager, null); - System.out.println(Hex.toHexString(checkN1.getRuntime().getResult().getHReturn())); - System.out.println(Hex.toHexString(checkN2.getRuntime().getResult().getHReturn())); - Assert.assertEquals(checkN1.getRuntime().getResult().getHReturn(), + Assert.assertArrayEquals(checkN1.getRuntime().getResult().getHReturn(), new DataWord(1).getData()); - Assert.assertEquals(checkN2.getRuntime().getResult().getHReturn(), + Assert.assertArrayEquals(checkN2.getRuntime().getResult().getHReturn(), new DataWord(0).getData()); // trigger contractA @@ -240,12 +237,9 @@ public void loopCallTest() checkN2 = TvmTestUtils .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), aAddress, checkN2Data, 0, fee, dbManager, null); - System.out.println(Hex.toHexString(checkN1.getRuntime().getResult().getHReturn())); - System.out.println(Hex.toHexString(checkN2.getRuntime().getResult().getHReturn())); - Assert.assertEquals(checkN1.getRuntime().getResult().getHReturn(), + Assert.assertArrayEquals(checkN1.getRuntime().getResult().getHReturn(), new DataWord(100).getData()); - Assert - .assertEquals(checkN2.getRuntime().getResult().getHReturn(), + Assert.assertArrayEquals(checkN2.getRuntime().getResult().getHReturn(), new DataWord(1000).getData()); CommonParameter.setENERGY_LIMIT_HARD_FORK(false); } @@ -369,12 +363,10 @@ public void loopCallTestOldVersion() .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), aAddress, checkN2Data, 0, fee, dbManager, null); - System.out.println(Hex.toHexString(checkN1.getRuntime().getResult().getHReturn())); - System.out.println(Hex.toHexString(checkN2.getRuntime().getResult().getHReturn())); - Assert.assertEquals(checkN1.getRuntime().getResult().getHReturn(), + Assert.assertArrayEquals(checkN1.getRuntime().getResult().getHReturn(), new DataWord(1).getData()); - Assert.assertEquals(checkN2.getRuntime().getResult().getHReturn(), + Assert.assertArrayEquals(checkN2.getRuntime().getResult().getHReturn(), new DataWord(2).getData()); // trigger contractA @@ -394,12 +386,10 @@ public void loopCallTestOldVersion() checkN2 = TvmTestUtils .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), aAddress, checkN2Data, 0, fee, dbManager, null); - System.out.println(Hex.toHexString(checkN1.getRuntime().getResult().getHReturn())); - System.out.println(Hex.toHexString(checkN2.getRuntime().getResult().getHReturn())); - Assert.assertEquals(checkN1.getRuntime().getResult().getHReturn(), + Assert.assertArrayEquals(checkN1.getRuntime().getResult().getHReturn(), new DataWord(100).getData()); Assert - .assertEquals(checkN2.getRuntime().getResult().getHReturn(), + .assertArrayEquals(checkN2.getRuntime().getResult().getHReturn(), new DataWord(1000).getData()); CommonParameter.setENERGY_LIMIT_HARD_FORK(false); } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/RewardBalanceTest.java b/framework/src/test/java/org/tron/common/runtime/vm/RewardBalanceTest.java index b9fa24712c9..af95952ebf7 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/RewardBalanceTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/RewardBalanceTest.java @@ -3,8 +3,8 @@ import java.util.Collections; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Test; -import org.testng.Assert; import org.tron.common.runtime.InternalTransaction; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.Base58; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/StorageTest.java b/framework/src/test/java/org/tron/common/runtime/vm/StorageTest.java index fcef572ea99..8ae04761ac3 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/StorageTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/StorageTest.java @@ -3,9 +3,9 @@ import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; -import org.testng.Assert; import org.tron.common.parameter.CommonParameter; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java b/framework/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java index 2c04b302c49..cc79d5f7ad6 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java @@ -2,10 +2,10 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; -import org.testng.Assert; import org.tron.common.BaseTest; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/TransferFailedEnergyTest.java b/framework/src/test/java/org/tron/common/runtime/vm/TransferFailedEnergyTest.java index 8a3bbbbeede..dbc9147de7f 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/TransferFailedEnergyTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/TransferFailedEnergyTest.java @@ -6,8 +6,8 @@ import lombok.Data; import lombok.ToString; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Test; -import org.testng.Assert; import org.tron.common.runtime.ProgramResult; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; @@ -383,12 +383,12 @@ private void checkResult(TestCase testCase, byte[] factoryAddress) factoryAddress, Hex.decode(hexInput), 0, fee, manager, null); ProgramResult programResult = result.getRuntime().getResult(); ReceiptCapsule receiptCapsule = result.getReceipt(); - Assert.assertEquals(receiptCapsule.getResult(), testCase.getReceiptResult(), - testCase.getMethod()); + Assert.assertEquals(testCase.getMethod(), + receiptCapsule.getResult(), testCase.getReceiptResult()); if (testCase.allEnergy) { - Assert.assertEquals(programResult.getEnergyUsed(), 1000000, testCase.getMethod()); + Assert.assertEquals(testCase.getMethod(), programResult.getEnergyUsed(), 1000000); } else { - Assert.assertTrue(programResult.getEnergyUsed() < allEnergy, testCase.getMethod()); + Assert.assertTrue(testCase.getMethod(), programResult.getEnergyUsed() < allEnergy); } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java b/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java index bc9a60a9704..87ff59a785b 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java @@ -132,7 +132,7 @@ public void TransferTokenTest() triggerCallValue, feeLimit, tokenValue, id); runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction, dbManager, null); - org.testng.Assert.assertNull(runtime.getRuntimeError()); + Assert.assertNull(runtime.getRuntimeError()); Assert.assertEquals(100 + tokenValue - 9, dbManager.getAccountStore().get(contractAddress).getAssetV2MapForTest() .get(String.valueOf(id)).longValue()); @@ -157,7 +157,7 @@ public void TransferTokenTest() triggerData2, triggerCallValue, feeLimit, 0, id); runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction2, dbManager, null); - org.testng.Assert.assertNull(runtime.getRuntimeError()); + Assert.assertNull(runtime.getRuntimeError()); Assert.assertEquals(100 + tokenValue - 9 + 9, dbManager.getAccountStore().get(Hex.decode(TRANSFER_TO)).getAssetV2MapForTest() .get(String.valueOf(id)).longValue()); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java b/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java index e6ef013bd85..765a80f3d5f 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java @@ -8,9 +8,9 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.testng.Assert; import org.tron.common.BaseTest; import org.tron.common.crypto.ECKey; import org.tron.common.crypto.Hash; @@ -60,7 +60,7 @@ public void testAddressNonExist() { signs.add(Hex.toHexString(sign)); //Address non exist - Assert.assertEquals( + Assert.assertArrayEquals( validateMultiSign(StringUtil.encode58Check(key.getAddress()), 1, hash, signs) .getValue(), DataWord.ZERO().getData()); } @@ -120,21 +120,21 @@ public void testDifferentCase() { signs.add(Hex.toHexString(key1.sign(toSign).toByteArray())); signs.add(Hex.toHexString(key2.sign(toSign).toByteArray())); - Assert.assertEquals( + Assert.assertArrayEquals( validateMultiSign(StringUtil.encode58Check(key.getAddress()), permissionId, data, signs) .getValue(), DataWord.ONE().getData()); //weight not enough signs = new ArrayList<>(); signs.add(Hex.toHexString(key1.sign(toSign).toByteArray())); - Assert.assertEquals( + Assert.assertArrayEquals( validateMultiSign(StringUtil.encode58Check(key.getAddress()), permissionId, data, signs) .getValue(), DataWord.ZERO().getData()); //put wrong sign signs = new ArrayList<>(); signs.add(Hex.toHexString(key1.sign(toSign).toByteArray())); - Assert.assertEquals( + Assert.assertArrayEquals( validateMultiSign(StringUtil.encode58Check(key.getAddress()), permissionId, data, signs) .getValue(), DataWord.ZERO().getData()); @@ -142,7 +142,7 @@ public void testDifferentCase() { signs.add(Hex.toHexString(key1.sign(toSign).toByteArray())); signs.add(Hex.toHexString(new ECKey().sign(toSign).toByteArray())); - Assert.assertEquals( + Assert.assertArrayEquals( validateMultiSign(StringUtil.encode58Check(key.getAddress()), permissionId, data, signs) .getValue(), DataWord.ZERO().getData()); } diff --git a/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java b/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java index 0d117dd4a45..6839de47434 100644 --- a/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java @@ -2,6 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.google.common.collect.Lists; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; @@ -22,7 +23,6 @@ import org.apache.http.params.CoreConnectionPNames; import org.apache.http.util.EntityUtils; import org.junit.Assert; -import org.testng.collections.Lists; import org.tron.api.GrpcAPI; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; diff --git a/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java index 888e13f1ae6..d46545c5e16 100644 --- a/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java @@ -1,7 +1,7 @@ package org.tron.core.actuator; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.fail; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; import com.google.protobuf.Any; import com.google.protobuf.ByteString; diff --git a/framework/src/test/java/org/tron/core/actuator/AssetIssueActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/AssetIssueActuatorTest.java index 17cf0e2286c..58e3ae8ed29 100755 --- a/framework/src/test/java/org/tron/core/actuator/AssetIssueActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/AssetIssueActuatorTest.java @@ -1,6 +1,6 @@ package org.tron.core.actuator; -import static org.testng.Assert.fail; +import static org.junit.Assert.fail; import com.google.protobuf.Any; import com.google.protobuf.ByteString; diff --git a/framework/src/test/java/org/tron/core/actuator/CreateAccountActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/CreateAccountActuatorTest.java index 11f68c0b8bb..d53b0332f64 100755 --- a/framework/src/test/java/org/tron/core/actuator/CreateAccountActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/CreateAccountActuatorTest.java @@ -1,6 +1,6 @@ package org.tron.core.actuator; -import static org.testng.Assert.fail; +import static org.junit.Assert.fail; import com.google.protobuf.Any; import com.google.protobuf.ByteString; diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java index f37016845d4..f8e4a27bda1 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java @@ -1,6 +1,6 @@ package org.tron.core.actuator; -import static org.testng.Assert.fail; +import static org.junit.Assert.fail; import com.google.protobuf.Any; import com.google.protobuf.ByteString; diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java index 49a80fd3253..553108d5490 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java @@ -1,6 +1,6 @@ package org.tron.core.actuator; -import static org.testng.Assert.fail; +import static org.junit.Assert.fail; import static org.tron.core.config.Parameter.ChainSymbol.TRX_SYMBOL_BYTES; import com.google.protobuf.Any; diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java index dad6b24e03e..5d728a61ff5 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java @@ -1,6 +1,6 @@ package org.tron.core.actuator; -import static org.testng.Assert.fail; +import static org.junit.Assert.fail; import static org.tron.core.config.Parameter.ChainSymbol.TRX_SYMBOL_BYTES; import com.google.protobuf.Any; diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java index ad08b49c9ee..85ea81ed932 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java @@ -1,6 +1,6 @@ package org.tron.core.actuator; -import static org.testng.Assert.fail; +import static org.junit.Assert.fail; import static org.tron.core.config.Parameter.ChainSymbol.TRX_SYMBOL_BYTES; import com.google.protobuf.Any; diff --git a/framework/src/test/java/org/tron/core/actuator/MarketCancelOrderActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/MarketCancelOrderActuatorTest.java index a9daf0871b1..51b20ceab02 100644 --- a/framework/src/test/java/org/tron/core/actuator/MarketCancelOrderActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/MarketCancelOrderActuatorTest.java @@ -1,7 +1,5 @@ package org.tron.core.actuator; -import static org.testng.Assert.fail; - import com.google.protobuf.Any; import com.google.protobuf.ByteString; import java.util.List; @@ -192,7 +190,7 @@ public void invalidOwnerAddress() { try { actuator.validate(); - fail("Invalid address"); + Assert.fail("Invalid address"); } catch (ContractValidateException e) { Assert.assertEquals("Invalid address", e.getMessage()); } @@ -212,7 +210,7 @@ public void notExistAccount() { try { actuator.validate(); - fail("Account does not exist!"); + Assert.fail("Account does not exist!"); } catch (ContractValidateException e) { Assert.assertEquals("Account does not exist!", e.getMessage()); } @@ -231,7 +229,7 @@ public void notExistOrder() { OWNER_ADDRESS_FIRST, orderId)); try { actuator.validate(); - fail("orderId not exists"); + Assert.fail("orderId not exists"); } catch (ContractValidateException e) { Assert.assertEquals("orderId not exists", e.getMessage()); } @@ -265,7 +263,7 @@ public void orderNotActive() throws Exception { try { actuator.validate(); - fail("Order is not active!"); + Assert.fail("Order is not active!"); } catch (ContractValidateException e) { Assert.assertEquals("Order is not active!", e.getMessage()); } @@ -300,7 +298,7 @@ public void notBelongToTheAccount() throws Exception { try { actuator.validate(); actuator.execute(ret); - fail("Order does not belong to the account!"); + Assert.fail("Order does not belong to the account!"); } catch (ContractValidateException e) { Assert.assertEquals("Order does not belong to the account!", e.getMessage()); } catch (ContractExeException e) { @@ -342,7 +340,7 @@ public void noEnoughBalance() throws Exception { try { actuator.validate(); actuator.execute(ret); - fail("No enough balance !"); + Assert.fail("No enough balance !"); } catch (ContractValidateException e) { Assert.assertEquals("No enough balance !", e.getMessage()); } catch (ContractExeException e) { @@ -379,7 +377,7 @@ public void validateSuccess() throws Exception { try { actuator.validate(); } catch (ContractValidateException e) { - fail("validateSuccess error"); + Assert.fail("validateSuccess error"); } } diff --git a/framework/src/test/java/org/tron/core/actuator/MarketSellAssetActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/MarketSellAssetActuatorTest.java index 587a6b5aacd..a2a7cea259e 100644 --- a/framework/src/test/java/org/tron/core/actuator/MarketSellAssetActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/MarketSellAssetActuatorTest.java @@ -1,6 +1,6 @@ package org.tron.core.actuator; -import static org.testng.Assert.fail; +import static org.junit.Assert.fail; import com.google.protobuf.Any; import com.google.protobuf.ByteString; diff --git a/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java index c9d593daf66..28f7bf0e4f5 100644 --- a/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java @@ -2,10 +2,10 @@ import com.google.protobuf.ByteString; import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.testng.Assert; import org.tron.common.BaseTest; import org.tron.common.utils.StringUtil; import org.tron.core.Constant; diff --git a/framework/src/test/java/org/tron/core/capsule/VotesCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/VotesCapsuleTest.java index 467d801996e..d2e4483cdf0 100644 --- a/framework/src/test/java/org/tron/core/capsule/VotesCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/VotesCapsuleTest.java @@ -6,9 +6,9 @@ import java.util.List; import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.testng.Assert; import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.core.Constant; diff --git a/framework/src/test/java/org/tron/core/db/ByteArrayWrapperTest.java b/framework/src/test/java/org/tron/core/db/ByteArrayWrapperTest.java index ef4a60ca1da..fdf5877b87c 100644 --- a/framework/src/test/java/org/tron/core/db/ByteArrayWrapperTest.java +++ b/framework/src/test/java/org/tron/core/db/ByteArrayWrapperTest.java @@ -1,8 +1,8 @@ package org.tron.core.db; import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; import org.junit.Test; -import org.testng.Assert; import org.tron.common.utils.ByteArray; @Slf4j diff --git a/framework/src/test/java/org/tron/core/db/KhaosDatabaseTest.java b/framework/src/test/java/org/tron/core/db/KhaosDatabaseTest.java index 87a38927be1..de895abb4b4 100644 --- a/framework/src/test/java/org/tron/core/db/KhaosDatabaseTest.java +++ b/framework/src/test/java/org/tron/core/db/KhaosDatabaseTest.java @@ -1,5 +1,6 @@ package org.tron.core.db; +import com.google.common.collect.Lists; import com.google.protobuf.ByteString; import java.lang.ref.Reference; import java.lang.ref.WeakReference; @@ -9,7 +10,6 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.testng.collections.Lists; import org.tron.common.BaseTest; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index 2c51250d757..020805c93fa 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -7,6 +7,7 @@ import static org.tron.core.exception.BadBlockException.TypeEnum.CALC_MERKLE_ROOT_FAILED; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import com.google.protobuf.ByteString; import java.io.File; import java.util.ArrayList; @@ -22,7 +23,6 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.testng.collections.Sets; import org.tron.common.application.TronApplicationContext; import org.tron.common.crypto.ECKey; import org.tron.common.runtime.RuntimeImpl; diff --git a/framework/src/test/java/org/tron/core/db2/SnapshotRootTest.java b/framework/src/test/java/org/tron/core/db2/SnapshotRootTest.java index a483be278ff..70b4d9eff30 100644 --- a/framework/src/test/java/org/tron/core/db2/SnapshotRootTest.java +++ b/framework/src/test/java/org/tron/core/db2/SnapshotRootTest.java @@ -1,5 +1,6 @@ package org.tron.core.db2; +import com.google.common.collect.Sets; import java.io.File; import java.util.ArrayList; import java.util.Arrays; @@ -14,7 +15,6 @@ import org.junit.Before; import org.junit.Test; import org.springframework.util.CollectionUtils; -import org.testng.collections.Sets; import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; diff --git a/framework/src/test/java/org/tron/core/jsonrpc/BloomTest.java b/framework/src/test/java/org/tron/core/jsonrpc/BloomTest.java index 2964e24232f..19e232b0f93 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/BloomTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/BloomTest.java @@ -6,8 +6,8 @@ import java.util.ArrayList; import java.util.List; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Test; -import org.testng.Assert; import org.tron.common.bloom.Bloom; import org.tron.common.crypto.Hash; import org.tron.common.runtime.vm.DataWord; diff --git a/framework/src/test/java/org/tron/core/jsonrpc/SectionBloomStoreTest.java b/framework/src/test/java/org/tron/core/jsonrpc/SectionBloomStoreTest.java index fd2b7a66d31..9b107792d86 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/SectionBloomStoreTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/SectionBloomStoreTest.java @@ -6,8 +6,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.annotation.Resource; +import org.junit.Assert; import org.junit.Test; -import org.testng.Assert; import org.tron.common.BaseTest; import org.tron.common.runtime.vm.DataWord; import org.tron.common.runtime.vm.LogInfo; diff --git a/framework/src/test/java/org/tron/core/services/http/BroadcastServletTest.java b/framework/src/test/java/org/tron/core/services/http/BroadcastServletTest.java index 24ec969c08b..37956e71762 100644 --- a/framework/src/test/java/org/tron/core/services/http/BroadcastServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/BroadcastServletTest.java @@ -25,7 +25,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; -import org.testng.annotations.Test; +import org.junit.Test; import org.tron.common.utils.FileUtil; import org.tron.core.services.http.solidity.mockito.HttpUrlStreamHandler; @@ -47,7 +47,12 @@ public class BroadcastServletTest { public static void init() { // Allows for mocking URL connections URLStreamHandlerFactory urlStreamHandlerFactory = mock(URLStreamHandlerFactory.class); - URL.setURLStreamHandlerFactory(urlStreamHandlerFactory); + try { + URL.setURLStreamHandlerFactory(urlStreamHandlerFactory); + } catch (Error e) { + logger.info("Ignore error: {}", e.getMessage()); + } + httpUrlStreamHandler = new HttpUrlStreamHandler(); given(urlStreamHandlerFactory.createURLStreamHandler("http")).willReturn(httpUrlStreamHandler); @@ -83,8 +88,6 @@ public void tearDown() { @Test public void doPostTest() throws IOException { URLStreamHandlerFactory urlStreamHandlerFactory = mock(URLStreamHandlerFactory.class); - URL.setURLStreamHandlerFactory(urlStreamHandlerFactory); - httpUrlStreamHandler = new HttpUrlStreamHandler(); given(urlStreamHandlerFactory.createURLStreamHandler("http")).willReturn(httpUrlStreamHandler); diff --git a/framework/src/test/java/org/tron/core/services/http/solidity/GetTransactionByIdSolidityServletTest.java b/framework/src/test/java/org/tron/core/services/http/solidity/GetTransactionByIdSolidityServletTest.java index 06bc5f561c5..70c74e3a2a7 100644 --- a/framework/src/test/java/org/tron/core/services/http/solidity/GetTransactionByIdSolidityServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/solidity/GetTransactionByIdSolidityServletTest.java @@ -48,7 +48,11 @@ public class GetTransactionByIdSolidityServletTest { public static void init() { // Allows for mocking URL connections URLStreamHandlerFactory urlStreamHandlerFactory = mock(URLStreamHandlerFactory.class); - URL.setURLStreamHandlerFactory(urlStreamHandlerFactory); + try { + URL.setURLStreamHandlerFactory(urlStreamHandlerFactory); + } catch (Error e) { + logger.info("Ignore error: {}", e.getMessage()); + } httpUrlStreamHandler = new HttpUrlStreamHandler(); given(urlStreamHandlerFactory.createURLStreamHandler("http")).willReturn(httpUrlStreamHandler); diff --git a/framework/src/test/java/org/tron/core/witness/ProposalControllerTest.java b/framework/src/test/java/org/tron/core/witness/ProposalControllerTest.java index cb502008bfc..769b09770c2 100644 --- a/framework/src/test/java/org/tron/core/witness/ProposalControllerTest.java +++ b/framework/src/test/java/org/tron/core/witness/ProposalControllerTest.java @@ -1,5 +1,6 @@ package org.tron.core.witness; +import com.google.common.collect.Lists; import com.google.protobuf.ByteString; import java.util.HashMap; import java.util.List; @@ -8,7 +9,6 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.testng.collections.Lists; import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; import org.tron.core.Constant; diff --git a/framework/src/test/java/org/tron/core/zksnark/MerkleTreeTest.java b/framework/src/test/java/org/tron/core/zksnark/MerkleTreeTest.java index b635b55339c..a3048a14375 100644 --- a/framework/src/test/java/org/tron/core/zksnark/MerkleTreeTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/MerkleTreeTest.java @@ -2,6 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.google.common.base.Charsets; +import com.google.common.collect.Lists; import com.google.common.io.Files; import com.google.protobuf.ByteString; import java.io.File; @@ -9,7 +10,6 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.testng.collections.Lists; import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; diff --git a/framework/src/test/java/org/tron/core/zksnark/SaplingNoteTest.java b/framework/src/test/java/org/tron/core/zksnark/SaplingNoteTest.java index 155e0477d65..776e94adc3c 100644 --- a/framework/src/test/java/org/tron/core/zksnark/SaplingNoteTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/SaplingNoteTest.java @@ -1,9 +1,9 @@ package org.tron.core.zksnark; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.testng.Assert; import org.tron.common.utils.ByteArray; import org.tron.core.config.args.Args; import org.tron.core.exception.BadItemException; diff --git a/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java b/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java index cd7a36ab7a4..5b480cd0274 100644 --- a/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONArray; import com.google.common.base.Charsets; +import com.google.common.collect.Lists; import com.google.common.io.Files; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; @@ -18,7 +19,6 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Test; -import org.testng.collections.Lists; import org.tron.api.GrpcAPI; import org.tron.common.BaseTest; import org.tron.common.parameter.CommonParameter; diff --git a/plugins/build.gradle b/plugins/build.gradle index 457fb739058..9f4cb3ef59b 100644 --- a/plugins/build.gradle +++ b/plugins/build.gradle @@ -29,7 +29,6 @@ dependencies { testCompile group: 'junit', name: 'junit', version: '4.13.2' testCompile group: 'org.mockito', name: 'mockito-core', version: '2.13.0' testCompile group: 'org.hamcrest', name: 'hamcrest-junit', version: '1.0.0.1' - testCompile group: 'org.testng', name: 'testng', version: '6.14.3' compile group: 'info.picocli', name: 'picocli', version: '4.6.3' compile group: 'com.typesafe', name: 'config', version: '1.3.2' compile group: 'me.tongfei', name: 'progressbar', version: '0.9.3' From 0c19160839b85b40a128e5bffaec61f677d4257c Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Thu, 15 Jun 2023 17:15:13 +0800 Subject: [PATCH 0812/1197] feat(freezeV2): modify CancelAllUnfreezeV2 return info --- .../actuator/CancelAllUnfreezeV2Actuator.java | 50 ++++++++++++------- .../capsule/TransactionResultCapsule.java | 9 ++-- .../core/capsule/utils/TransactionUtil.java | 2 +- .../core/services/jsonrpc/JsonRpcApiUtil.java | 3 +- .../CancelAllUnfreezeV2ActuatorTest.java | 6 +++ protocol/src/main/protos/core/Tron.proto | 4 +- 6 files changed, 48 insertions(+), 26 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/CancelAllUnfreezeV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/CancelAllUnfreezeV2Actuator.java index 8fd58124b1a..527c88115ac 100755 --- a/actuator/src/main/java/org/tron/core/actuator/CancelAllUnfreezeV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/CancelAllUnfreezeV2Actuator.java @@ -5,13 +5,17 @@ import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; import static org.tron.protos.contract.Common.ResourceCode.ENERGY; +import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.concurrent.atomic.AtomicLong; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Triple; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; @@ -54,12 +58,13 @@ public boolean execute(Object result) throws ContractExeException { List unfrozenV2List = ownerCapsule.getUnfrozenV2List(); long now = dynamicStore.getLatestBlockHeaderTimestamp(); AtomicLong atomicWithdrawExpireBalance = new AtomicLong(0L); - AtomicLong atomicCancelBalance = new AtomicLong(0L); - Triple triple = - Triple.of(new AtomicLong(0L), new AtomicLong(0L), new AtomicLong(0L)); + Triple, Pair, Pair> + triple = Triple.of( + Pair.of(new AtomicLong(0L), new AtomicLong(0L)), + Pair.of(new AtomicLong(0L), new AtomicLong(0L)), + Pair.of(new AtomicLong(0L), new AtomicLong(0L))); for (UnFreezeV2 unFreezeV2 : unfrozenV2List) { - updateAndCalculate(triple, ownerCapsule, now, atomicWithdrawExpireBalance, - atomicCancelBalance, unFreezeV2); + updateAndCalculate(triple, ownerCapsule, now, atomicWithdrawExpireBalance, unFreezeV2); } ownerCapsule.clearUnfrozenV2(); addTotalResourceWeight(dynamicStore, triple); @@ -71,24 +76,29 @@ public boolean execute(Object result) throws ContractExeException { accountStore.put(ownerCapsule.createDbKey(), ownerCapsule); ret.setWithdrawExpireAmount(withdrawExpireBalance); - ret.setCancelAllUnfreezeV2Amount(atomicCancelBalance.get()); + Map cancelUnfreezeV2AmountMap = new HashMap<>(); + cancelUnfreezeV2AmountMap.put(BANDWIDTH.name(), triple.getLeft().getRight().get()); + cancelUnfreezeV2AmountMap.put(ENERGY.name(), triple.getMiddle().getRight().get()); + cancelUnfreezeV2AmountMap.put(TRON_POWER.name(), triple.getRight().getRight().get()); + ret.putAllCancelUnfreezeV2AmountMap(cancelUnfreezeV2AmountMap); ret.setStatus(fee, code.SUCESS); return true; } private void addTotalResourceWeight(DynamicPropertiesStore dynamicStore, - Triple triple) { - dynamicStore.addTotalNetWeight(triple.getLeft().get()); - dynamicStore.addTotalEnergyWeight(triple.getMiddle().get()); - dynamicStore.addTotalTronPowerWeight(triple.getRight().get()); + Triple, + Pair, + Pair> triple) { + dynamicStore.addTotalNetWeight(triple.getLeft().getLeft().get()); + dynamicStore.addTotalEnergyWeight(triple.getMiddle().getLeft().get()); + dynamicStore.addTotalTronPowerWeight(triple.getRight().getLeft().get()); } - private void updateAndCalculate(Triple triple, - AccountCapsule ownerCapsule, long now, AtomicLong atomicLong, AtomicLong cancelBalance, - UnFreezeV2 unFreezeV2) { + private void updateAndCalculate(Triple, Pair, + Pair> triple, + AccountCapsule ownerCapsule, long now, AtomicLong atomicLong, UnFreezeV2 unFreezeV2) { if (unFreezeV2.getUnfreezeExpireTime() > now) { updateFrozenInfoAndTotalResourceWeight(ownerCapsule, unFreezeV2, triple); - cancelBalance.addAndGet(unFreezeV2.getUnfreezeAmount()); } else { atomicLong.addAndGet(unFreezeV2.getUnfreezeAmount()); } @@ -160,25 +170,29 @@ public long calcFee() { public void updateFrozenInfoAndTotalResourceWeight( AccountCapsule accountCapsule, UnFreezeV2 unFreezeV2, - Triple triple) { + Triple, Pair, + Pair> triple) { switch (unFreezeV2.getType()) { case BANDWIDTH: long oldNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; accountCapsule.addFrozenBalanceForBandwidthV2(unFreezeV2.getUnfreezeAmount()); long newNetWeight = accountCapsule.getFrozenV2BalanceWithDelegated(BANDWIDTH) / TRX_PRECISION; - triple.getLeft().addAndGet(newNetWeight - oldNetWeight); + triple.getLeft().getLeft().addAndGet(newNetWeight - oldNetWeight); + triple.getLeft().getRight().addAndGet(unFreezeV2.getUnfreezeAmount()); break; case ENERGY: long oldEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; accountCapsule.addFrozenBalanceForEnergyV2(unFreezeV2.getUnfreezeAmount()); long newEnergyWeight = accountCapsule.getFrozenV2BalanceWithDelegated(ENERGY) / TRX_PRECISION; - triple.getMiddle().addAndGet(newEnergyWeight - oldEnergyWeight); + triple.getMiddle().getLeft().addAndGet(newEnergyWeight - oldEnergyWeight); + triple.getMiddle().getRight().addAndGet(unFreezeV2.getUnfreezeAmount()); break; case TRON_POWER: long oldTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; accountCapsule.addFrozenForTronPowerV2(unFreezeV2.getUnfreezeAmount()); long newTPWeight = accountCapsule.getTronPowerFrozenV2Balance() / TRX_PRECISION; - triple.getRight().addAndGet(newTPWeight - oldTPWeight); + triple.getRight().getLeft().addAndGet(newTPWeight - oldTPWeight); + triple.getRight().getRight().addAndGet(unFreezeV2.getUnfreezeAmount()); break; default: break; diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionResultCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionResultCapsule.java index be86a95f4f6..8ff3064b73c 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionResultCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionResultCapsule.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import java.util.List; +import java.util.Map; import lombok.extern.slf4j.Slf4j; import org.tron.core.exception.BadItemException; import org.tron.protos.Protocol.MarketOrderDetail; @@ -89,13 +90,13 @@ public void setWithdrawExpireAmount(long amount) { .setWithdrawExpireAmount(amount).build(); } - public long getCancelAllUnfreezeV2Amount() { - return transactionResult.getCancelAllUnfreezeV2Amount(); + public Map getCancelUnfreezeV2AmountMap() { + return transactionResult.getCancelUnfreezeV2AmountMap(); } - public void setCancelAllUnfreezeV2Amount(long amount) { + public void putAllCancelUnfreezeV2AmountMap(Map map) { this.transactionResult = this.transactionResult.toBuilder() - .setCancelAllUnfreezeV2Amount(amount).build(); + .putAllCancelUnfreezeV2Amount(map).build(); } public long getExchangeReceivedAmount() { diff --git a/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java b/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java index 047a21b68cb..c9e0d30b1e6 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java +++ b/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java @@ -100,7 +100,7 @@ public static TransactionInfoCapsule buildTransactionInfoInstance(TransactionCap builder.setExchangeId(programResult.getRet().getExchangeId()); builder.setWithdrawAmount(programResult.getRet().getWithdrawAmount()); builder.setWithdrawExpireAmount(programResult.getRet().getWithdrawExpireAmount()); - builder.setCancelAllUnfreezeV2Amount(programResult.getRet().getCancelAllUnfreezeV2Amount()); + builder.putAllCancelUnfreezeV2Amount(programResult.getRet().getCancelUnfreezeV2AmountMap()); builder.setExchangeReceivedAmount(programResult.getRet().getExchangeReceivedAmount()); builder.setExchangeInjectAnotherAmount(programResult.getRet().getExchangeInjectAnotherAmount()); builder.setExchangeWithdrawAnotherAmount( diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java index 776c74266aa..4efc5994c0d 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java @@ -337,7 +337,8 @@ public static long getAmountFromTransactionInfo(String hash, ContractType contra amount = transactionInfo.getWithdrawExpireAmount(); break; case CancelAllUnfreezeV2Contract: - amount = transactionInfo.getCancelAllUnfreezeV2Amount(); + amount = transactionInfo.getCancelUnfreezeV2AmountMap().values() + .stream().mapToLong(v -> v).sum(); break; default: break; diff --git a/framework/src/test/java/org/tron/core/actuator/CancelAllUnfreezeV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/CancelAllUnfreezeV2ActuatorTest.java index 5b417833c1d..fcc545a0fc2 100644 --- a/framework/src/test/java/org/tron/core/actuator/CancelAllUnfreezeV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/CancelAllUnfreezeV2ActuatorTest.java @@ -9,6 +9,7 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; +import java.util.Map; import lombok.extern.slf4j.Slf4j; import org.junit.Before; import org.junit.Test; @@ -81,8 +82,13 @@ public void testCancelAllUnfreezeV2() { assertEquals(SUCESS, ret.getInstance().getRet()); AccountCapsule owner = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); + Map cancelUnfreezeV2AmountMap = ret.getInstance() + .getCancelUnfreezeV2AmountMap(); assertEquals(2000000L, ret.getInstance().getWithdrawExpireAmount()); assertEquals(0, owner.getUnfrozenV2List().size()); + assertEquals(8000000L, cancelUnfreezeV2AmountMap.get("BANDWIDTH").longValue()); + assertEquals(8000000L, cancelUnfreezeV2AmountMap.get("ENERGY").longValue()); + assertEquals(0, cancelUnfreezeV2AmountMap.get("TRON_POWER").longValue()); } catch (ContractValidateException | ContractExeException e) { fail(); } diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index f52c21162d6..05f8b990cb7 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -423,7 +423,7 @@ message Transaction { bytes orderId = 25; repeated MarketOrderDetail orderDetails = 26; int64 withdraw_expire_amount = 27; - int64 cancel_all_unfreezeV2_amount = 28; + map cancel_unfreezeV2_amount = 28; } message raw { @@ -484,7 +484,7 @@ message TransactionInfo { int64 packingFee = 27; int64 withdraw_expire_amount = 28; - int64 cancel_all_unfreezeV2_amount = 29; + map cancel_unfreezeV2_amount = 29; } message TransactionRet { From d4b1636edaae129ba324419d3f02592549f81b3c Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 16 Jun 2023 16:47:02 +0800 Subject: [PATCH 0813/1197] feat(test): add check and logPeerStats in SyncServiceTest --- .../java/org/tron/core/net/services/SyncServiceTest.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java b/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java index 4eebb7da12c..e51ec564886 100644 --- a/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java @@ -151,6 +151,13 @@ public void testStartFetchSyncBlock() throws Exception { PeerManager.add(ctx, c1); peer = PeerManager.getPeers().get(0); + Method method1 = PeerManager.class.getDeclaredMethod("check"); + method1.setAccessible(true); + method1.invoke(PeerManager.class); + Method method2 = PeerManager.class.getDeclaredMethod("logPeerStats"); + method2.setAccessible(true); + method2.invoke(PeerManager.class); + method.invoke(service); Assert.assertTrue(peer.getSyncBlockRequested().get(blockId) == null); From b4876e7d985806900c18a5d4747007ec95b3952d Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 19 Jun 2023 12:18:36 +0800 Subject: [PATCH 0814/1197] fix(net):if num is bigger than head num, get blockid from khaosdb --- .../main/java/org/tron/core/net/service/sync/SyncService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 87f497b1aa7..b70b6fe255d 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -210,7 +210,9 @@ private LinkedList getBlockChainSummary(PeerConnection peer) throws P2p private BlockId getBlockIdByNum(long num) throws P2pException { BlockId head = tronNetDelegate.getHeadBlockId(); - if (num == head.getNum()) { + if (num > head.getNum()) { + return tronNetDelegate.getKhaosDbHeadBlockId(); + } else if (num == head.getNum()) { return head; } return tronNetDelegate.getBlockIdByNum(num); From c14d42e981c2717515593377d956cc902fb165d8 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 19 Jun 2023 15:43:03 +0800 Subject: [PATCH 0815/1197] fix(net):optimize getBlockIdByNum in SyncService --- .../org/tron/core/net/service/sync/SyncService.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index b70b6fe255d..20116ade722 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -209,11 +209,12 @@ private LinkedList getBlockChainSummary(PeerConnection peer) throws P2p } private BlockId getBlockIdByNum(long num) throws P2pException { - BlockId head = tronNetDelegate.getHeadBlockId(); - if (num > head.getNum()) { - return tronNetDelegate.getKhaosDbHeadBlockId(); - } else if (num == head.getNum()) { - return head; + BlockId head1 = tronNetDelegate.getKhaosDbHeadBlockId(); + BlockId head2 = tronNetDelegate.getHeadBlockId(); + if (num == head1.getNum()) { + return head1; + } else if (num == head2.getNum()) { + return head2; } return tronNetDelegate.getBlockIdByNum(num); } From cb3df712f5428b5bf78f143e1bbb885fd1af4892 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 19 Jun 2023 15:50:12 +0800 Subject: [PATCH 0816/1197] fix(net):optimize getBlockIdByNum in SyncService --- .../org/tron/core/net/service/sync/SyncService.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 20116ade722..eae134758cd 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -209,12 +209,13 @@ private LinkedList getBlockChainSummary(PeerConnection peer) throws P2p } private BlockId getBlockIdByNum(long num) throws P2pException { - BlockId head1 = tronNetDelegate.getKhaosDbHeadBlockId(); - BlockId head2 = tronNetDelegate.getHeadBlockId(); - if (num == head1.getNum()) { - return head1; - } else if (num == head2.getNum()) { - return head2; + BlockId head = tronNetDelegate.getKhaosDbHeadBlockId(); + if (num == head.getNum()) { + return head; + } + head = tronNetDelegate.getHeadBlockId(); + if (num == head.getNum()) { + return head; } return tronNetDelegate.getBlockIdByNum(num); } From 2777b4f8d214eaf4c585b0a5a5f3403921b55e43 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 19 Jun 2023 19:40:15 +0800 Subject: [PATCH 0817/1197] fix(net):update libp2p from test-v2.0.0 to 2.0.0 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 95c6312ebcd..a184cab4b74 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v2.0.0',{ + compile group: 'io.github.tronprotocol', name: 'libp2p', version: '2.0.0',{ exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' From a10cfd6552e278f5e08f278b5b1f70e56811951b Mon Sep 17 00:00:00 2001 From: liukai Date: Tue, 20 Jun 2023 12:04:01 +0800 Subject: [PATCH 0818/1197] feat(test): remove solidity file 1. remove file * solcDir/ * soliditycode/ * soliditycode_0.5.15/ * soliditycode_0.6.12/ * soliditycode_0.7.6/ * soliditycode_v0.4.25/ * daily-build.xml * solidityFile.xml * testng.xml --- framework/src/test/resources/daily-build.xml | 16 - .../src/test/resources/solcDir/README.txt | 1 - framework/src/test/resources/solidityFile.xml | 81 - .../soliditycode/AssertException002.sol | 17 - .../soliditycode/AssignToExternal.sol | 30 - .../test/resources/soliditycode/BlockHash.sol | 38 - .../resources/soliditycode/ClearAbi001.sol | 7 - .../resources/soliditycode/ClearAbi005.sol | 26 - .../soliditycode/ConstructorDefaults.sol | 9 - .../resources/soliditycode/Create2Test023.sol | 31 - .../resources/soliditycode/Create2Test024.sol | 56 - .../resources/soliditycode/Create2Test025.sol | 34 - .../resources/soliditycode/EthGrammer.sol | 191 -- .../resources/soliditycode/EthGrammer02.sol | 45 - .../soliditycode/ExtCodeHashTest010.sol | 46 - .../soliditycode/ExternalSelector.sol | 92 - .../resources/soliditycode/NewFeature068.sol | 131 -- .../resources/soliditycode/NewFeature076.sol | 21 - .../resources/soliditycode/NewFeature080.sol | 109 - .../resources/soliditycode/NewFeature0811.sol | 101 - .../resources/soliditycode/NewFeature086.sol | 121 - .../test/resources/soliditycode/NoAbi001.sol | 10 - .../test/resources/soliditycode/NoAbi002.sol | 29 - .../resources/soliditycode/ParentTypeBug.sol | 13 - .../test/resources/soliditycode/SafeMath.sol | 149 -- .../soliditycode/ShiftCommand001.sol | 18 - .../soliditycode/SolidityMappingFix.sol | 9 - .../soliditycode/TestMappings_array_pop.sol | 19 - .../soliditycode/TransferFailed001.sol | 147 -- .../soliditycode/TransferFailed005.sol | 90 - .../soliditycode/TransferFailed006.sol | 90 - .../soliditycode/TransferFailed007.sol | 90 - .../soliditycode/TriggerConstant001.sol | 28 - .../soliditycode/TriggerConstant002.sol | 10 - .../soliditycode/TriggerConstant003.sol | 18 - .../soliditycode/TriggerConstant004.sol | 8 - .../soliditycode/TriggerConstant015.sol | 24 - .../soliditycode/TriggerConstant024.sol | 9 - .../resources/soliditycode/TvmIsContract.sol | 15 - .../soliditycode/TvmIsContract001.sol | 24 - .../soliditycode/TvmIsContract002.sol | 5 - .../soliditycode/TvmNewCommand043.sol | 18 - .../soliditycode/TvmNewCommand103.sol | 8 - .../soliditycode/TvmNewCommand107.sol | 9 - .../soliditycode/TvmNewCommand108.sol | 7 - .../soliditycode/TvmNewCommand109.sol | 7 - .../soliditycode/TvmOldCommand001.sol | 11 - .../soliditycode/VerifyBurnProof001.sol | 20 - .../soliditycode/VerifyMintProof001.sol | 33 - .../test/resources/soliditycode/abiencode.sol | 16 - .../resources/soliditycode/abstract001.sol | 11 - .../resources/soliditycode/abstract002.sol | 13 - ...stractContractWithMapParamsConstructor.sol | 23 - .../resources/soliditycode/accountAssert.sol | 94 - .../soliditycode/addMsg001Nonpayable.sol | 20 - .../resources/soliditycode/addMsg002View.sol | 20 - .../soliditycode/addMsg003Constant.sol | 19 - .../resources/soliditycode/addMsg004Pure.sol | 19 - .../addTransferToken001Nonpayable.sol | 13 - .../addTransferToken001payable.sol | 13 - .../soliditycode/addTransferToken002View.sol | 15 - .../addTransferToken003Constant.sol | 14 - .../soliditycode/addTransferToken004Pure.sol | 15 - .../soliditycode/addTrcToken001Assemble.sol | 62 - .../soliditycode/addTrcToken002Cat.sol | 2051 ---------------- .../addTrcToken002Cat_withFinny.sol | 2051 ---------------- .../soliditycode/addressCheckNew.sol | 9 - .../soliditycode/addressCheckOld.sol | 8 - .../src/test/resources/soliditycode/altbn.sol | 61 - .../resources/soliditycode/arrayLength001.sol | 64 - .../resources/soliditycode/assemblyTest.sol | 61 - .../assertExceptiontest1DivideInt.sol | 7 - ...tExceptiontest2FindArgsContractMinTest.sol | 10 - .../assertExceptiontest3ByteMinContract.sol | 11 - .../soliditycode/assertExceptiontest4Enum.sol | 13 - .../assertExceptiontest5MoveRight.sol | 7 - ...ertExceptiontest6UninitializedContract.sol | 27 - ...assertExceptiontest7TestAssertContract.sol | 14 - .../soliditycode/batchvalidatesign.sol | 14 - .../soliditycode/batchvalidatesign001.sol | 10 - .../soliditycode/batchvalidatesign002.sol | 8 - .../soliditycode/batchvalidatesign003.sol | 11 - .../soliditycode/batchvalidatesign005.sol | 14 - .../soliditycode/batchvalidatesign007.sol | 17 - .../soliditycode/batchvalidatesign02.sol | 8 - .../soliditycode/callValueGasPure.sol | 8 - .../test/resources/soliditycode/calldata.sol | 33 - .../test/resources/soliditycode/callvalue.sol | 9 - .../resources/soliditycode/chainid001.sol | 19 - .../soliditycode/codeSaftySupport.sol | 19 - .../soliditycode/codeSaftyUnsupport.sol | 56 - .../soliditycode/constantCallStorage001.sol | 159 -- .../soliditycode/constantCallStorage002.sol | 16 - .../soliditycode/constantCallStorage0425.sol | 156 -- .../soliditycode/constantContract001.sol | 8 - .../soliditycode/contractGetterContract.sol | 17 - .../contractGrammar001test1Grammar001.sol | 18 - .../contractGrammar001test2Grammar002.sol | 44 - .../contractGrammar001test3Grammar003.sol | 44 - .../contractGrammar001test4Grammar004.sol | 31 - .../contractGrammar001test5Grammar006.sol | 45 - .../contractGrammar002test1Grammar007_1.sol | 60 - .../contractGrammar002test1Grammar007_2.sol | 60 - .../contractGrammar002test2Grammar008.sol | 18 - .../contractGrammar002test3Grammar010.sol | 10 - .../contractGrammar002test4Grammar011.sol | 11 - .../contractGrammar002test4Grammar012.sol | 24 - .../contractGrammar002test6Grammar013.sol | 24 - .../contractGrammar003test1Grammar014.sol | 67 - .../contractGrammar003test2Grammar015.sol | 40 - .../contractGrammar003test3Grammar016.sol | 23 - .../contractGrammar003test4Grammar017.sol | 51 - .../contractGrammar003test5Grammar018.sol | 37 - .../contractGrammar003test6Grammar019.sol | 12 - .../contractGrammar003test7Grammar020.sol | 8 - .../soliditycode/contractInnerContract.sol | 32 - ...ansaction001testInternalTransaction001.sol | 41 - ...ansaction001testInternalTransaction002.sol | 20 - ...ansaction001testInternalTransaction003.sol | 30 - ...ansaction001testInternalTransaction004.sol | 24 - ...ansaction001testInternalTransaction005.sol | 53 - ...ansaction001testInternalTransaction006.sol | 54 - ...nsaction002test1InternalTransaction007.sol | 38 - ...nsaction002test2InternalTransaction008.sol | 60 - ...nsaction002test3InternalTransaction009.sol | 47 - ...nsaction002test4InternalTransaction010.sol | 186 -- ...action002test4InternalTransaction010_1.sol | 210 -- ...nsaction002test5InternalTransaction012.sol | 51 - ...ansaction003testInternalTransaction013.sol | 56 - ...ansaction003testInternalTransaction014.sol | 38 - ...ansaction003testInternalTransaction015.sol | 60 - ...ansaction003testInternalTransaction016.sol | 174 -- ...ansaction003testInternalTransaction017.sol | 199 -- ...ansaction003testInternalTransaction018.sol | 97 - .../soliditycode/contractLinkage001.sol | 9 - .../soliditycode/contractLinkage002.sol | 7 - .../soliditycode/contractLinkage003.sol | 7 - .../soliditycode/contractLinkage004.sol | 7 - .../soliditycode/contractLinkage005.sol | 51 - .../soliditycode/contractLinkage006.sol | 18 - .../contractOriginEnergyLimit001.sol | 11 - .../contractOriginEnergyLimit004.sol | 11 - .../soliditycode/contractOtherToTrcToken.sol | 41 - .../soliditycode/contractScenario001.sol | 7 - .../soliditycode/contractScenario002.sol | 53 - .../soliditycode/contractScenario003.sol | 7 - .../soliditycode/contractScenario004.sol | 88 - .../soliditycode/contractScenario005.sol | 103 - .../soliditycode/contractScenario006.sol | 1963 ---------------- .../soliditycode/contractScenario007.sol | 1432 ------------ .../soliditycode/contractScenario008.sol | 2061 ----------------- .../soliditycode/contractScenario009.sol | 51 - .../soliditycode/contractScenario010.sol | 107 - .../soliditycode/contractScenario011.sol | 2060 ---------------- .../soliditycode/contractScenario012.sol | 57 - .../soliditycode/contractScenario013.sol | 8 - .../soliditycode/contractScenario014.sol | 34 - .../resources/soliditycode/contractTest.sol | 19 - .../soliditycode/contractToMathedFeed.sol | 21 - .../soliditycode/contractTransferToken001.sol | 22 - .../soliditycode/contractTrc1155.sol | 612 ----- .../soliditycode/contractTrcToken001.sol | 41 - .../soliditycode/contractTrcToken002.sol | 30 - .../soliditycode/contractTrcToken003.sol | 16 - .../soliditycode/contractTrcToken005.sol | 16 - .../soliditycode/contractTrcToken011.sol | 35 - .../soliditycode/contractTrcToken012.sol | 26 - .../soliditycode/contractTrcToken014.sol | 34 - .../soliditycode/contractTrcToken018.sol | 26 - .../soliditycode/contractTrcToken023.sol | 26 - .../soliditycode/contractTrcToken026.sol | 31 - .../soliditycode/contractTrcToken027.sol | 30 - .../soliditycode/contractTrcToken028.sol | 25 - .../soliditycode/contractTrcToken029.sol | 24 - .../soliditycode/contractTrcToken030.sol | 17 - .../soliditycode/contractTrcToken031.sol | 18 - .../soliditycode/contractTrcToken034.sol | 25 - .../soliditycode/contractTrcToken035.sol | 24 - .../soliditycode/contractTrcToken036.sol | 52 - .../soliditycode/contractTrcToken036_1.sol | 13 - .../soliditycode/contractTrcToken036_2.sol | 13 - .../soliditycode/contractTrcToken036_3.sol | 13 - .../soliditycode/contractTrcToken036_4.sol | 13 - .../soliditycode/contractTrcToken036_old.sol | 41 - .../soliditycode/contractTrcToken037.sol | 24 - .../soliditycode/contractTrcToken038.sol | 24 - .../soliditycode/contractTrcToken039.sol | 44 - .../soliditycode/contractTrcToken041.sol | 20 - .../soliditycode/contractTrcToken043.sol | 35 - .../soliditycode/contractTrcToken048.sol | 14 - .../soliditycode/contractTrcToken049.sol | 9 - .../soliditycode/contractTrcToken050.sol | 10 - .../soliditycode/contractTrcToken051.sol | 11 - .../soliditycode/contractTrcToken052.sol | 10 - .../soliditycode/contractTrcToken054.sol | 16 - .../soliditycode/contractTrcToken055.sol | 16 - .../soliditycode/contractTrcToken060.sol | 30 - .../soliditycode/contractTrcToken061.sol | 30 - .../soliditycode/contractTrcToken064.sol | 49 - .../soliditycode/contractTrcToken066.sol | 35 - .../soliditycode/contractTrcToken067.sol | 35 - .../soliditycode/contractTrcToken073.sol | 16 - .../soliditycode/contractTrcToken075.sol | 26 - .../soliditycode/contractTrcToken076.sol | 19 - .../soliditycode/contractTrcToken077.sol | 11 - .../soliditycode/contractTrcToken078.sol | 35 - .../soliditycode/contractTrcToken079.sol | 16 - .../soliditycode/contractTrcToken080.sol | 30 - .../soliditycode/contractTrcToken081.sol | 51 - .../soliditycode/contractTrcTokenToOther.sol | 44 - .../soliditycode/contractUnknownException.sol | 64 - .../soliditycode/create2CallContract.sol | 37 - .../soliditycode/create2Istanbul.sol | 28 - .../soliditycode/create2contract.sol | 52 - .../soliditycode/create2contract22.sol | 109 - .../soliditycode/create2contractn.sol | 29 - .../soliditycode/create2contractn2.sol | 26 - .../src/test/resources/soliditycode/demo.sol | 73 - .../resources/soliditycode/enumAndStruct.sol | 43 - .../test/resources/soliditycode/event001.sol | 10 - .../test/resources/soliditycode/event002.sol | 52 - .../test/resources/soliditycode/eventLog2.sol | 8 - .../resources/soliditycode/extCodeHash.sol | 13 - .../resources/soliditycode/extCodeHash11.sol | 103 - .../soliditycode/extCodeHashConstruct.sol | 14 - .../soliditycode/extCodeHashStress.sol | 45 - .../soliditycode/extCodeHashTestNoPayable.sol | 8 - .../soliditycode/fallbackUpgrade.sol | 83 - .../soliditycode/freezeContract001.sol | 63 - .../function_type_array_to_storage.sol | 45 - .../soliditycode/getAddressChange.sol | 12 - .../resources/soliditycode/isSRCandidate.sol | 35 - .../resources/soliditycode/mappingGetter.sol | 4 - .../multiValiSignPerformance01.sol | 37 - .../multiValiSignPerformance02.sol | 10 - .../soliditycode/multivalidatesign.sol | 14 - .../soliditycode/multivalidatesign001.sol | 10 - .../soliditycode/multivalidatesign002.sol | 8 - .../soliditycode/multivalidatesign003.sol | 11 - .../soliditycode/multivalidatesign005.sol | 14 - .../soliditycode/multivalidatesign007.sol | 17 - .../soliditycode/multivalidatesign02.sol | 8 - .../resources/soliditycode/negativeArray.sol | 21 - .../test/resources/soliditycode/opCode.sol | 112 - .../resources/soliditycode/override002.sol | 12 - .../resources/soliditycode/override003.sol | 20 - .../resources/soliditycode/override004.sol | 25 - .../resources/soliditycode/override005.sol | 39 - .../soliditycode/overridePrivateFunction.sol | 22 - .../resources/soliditycode/payable001.sol | 31 - .../soliditycode/pedersenHash001.sol | 18 - .../soliditycode/pedersenHash002.sol | 320 --- ...quireExceptiontest1TestRequireContract.sol | 15 - ...equireExceptiontest2TestThrowsContract.sol | 15 - ...equireExceptiontest3TestRevertContract.sol | 15 - ...requireExceptiontest4noPayableContract.sol | 8 - ...quireExceptiontest4noPayableContract_1.sol | 8 - ...uireExceptiontest5noPayableConstructor.sol | 11 - ...reExceptiontest5noPayableConstructor_1.sol | 11 - ...uireExceptiontest6transferTestContract.sol | 8 - ...reExceptiontest7payableFallbakContract.sol | 14 - ...reExceptiontest8newContractGasNoenough.sol | 19 - ...uireExceptiontest9MessageUsedErrorFeed.sol | 18 - ...uireExceptiontestFunctionUsedErrorFeed.sol | 17 - .../test/resources/soliditycode/selector.sol | 21 - .../soliditycode/slotAndOffsetNewGrammer.sol | 32 - .../soliditycode/stackContract001.sol | 61 - .../soliditycode/stackSuicide001.sol | 84 - .../soliditycode/stateVariableShadowing.sol | 21 - .../resources/soliditycode/stringSplit.sol | 45 - .../resources/soliditycode/suicide001.sol | 32 - .../resources/soliditycode/suicide002.sol | 43 - ...kip_unimplemented_in_abstract_contract.sol | 22 - .../soliditycode/testGetFilterChange.sol | 11 - .../resources/soliditycode/testOutOfMem.sol | 7 - .../soliditycode/testStakeSuicide.sol | 71 - .../resources/soliditycode/tryCatch001.sol | 105 - .../soliditycode/tvmAssetIssue001.sol | 25 - .../soliditycode/tvmAssetIssue002.sol | 15 - .../soliditycode/tvmAssetIssue003.sol | 23 - .../soliditycode/tvmAssetIssue004.sol | 39 - .../soliditycode/tvmAssetIssue005.sol | 45 - .../test/resources/soliditycode/tvmVote.sol | 89 - .../test/resources/soliditycode/typeName.sol | 5 - .../resources/soliditycode/unStake001.sol | 90 - .../soliditycode/validatemultisign001.sol | 15 - .../soliditycode/verifyTransferProof001.sol | 15 - .../resources/soliditycode/virtual001.sol | 19 - .../soliditycode/walletTestMutiSign004.sol | 51 - .../AssertException002.sol | 17 - .../soliditycode_0.5.15/AssignToExternal.sol | 30 - .../soliditycode_0.5.15/BlockHash.sol | 38 - .../soliditycode_0.5.15/ClearAbi001.sol | 7 - .../soliditycode_0.5.15/ClearAbi005.sol | 26 - .../ConstructorDefaults.sol | 9 - .../soliditycode_0.5.15/Create2Test023.sol | 31 - .../soliditycode_0.5.15/Create2Test024.sol | 56 - .../soliditycode_0.5.15/Create2Test025.sol | 34 - .../ExtCodeHashTest010.sol | 46 - .../soliditycode_0.5.15/ParentTypeBug.sol | 13 - .../soliditycode_0.5.15/SafeMath.sol | 149 -- .../soliditycode_0.5.15/ShiftCommand001.sol | 18 - .../SolidityMappingFix.sol | 9 - .../TestMappings_array_pop.sol | 19 - .../soliditycode_0.5.15/TransferFailed001.sol | 147 -- .../soliditycode_0.5.15/TransferFailed005.sol | 90 - .../soliditycode_0.5.15/TransferFailed006.sol | 90 - .../soliditycode_0.5.15/TransferFailed007.sol | 90 - .../TriggerConstant001.sol | 28 - .../TriggerConstant002.sol | 10 - .../TriggerConstant003.sol | 18 - .../TriggerConstant004.sol | 8 - .../TriggerConstant015.sol | 24 - .../TriggerConstant024.sol | 9 - .../soliditycode_0.5.15/TvmIsContract.sol | 15 - .../soliditycode_0.5.15/TvmIsContract001.sol | 24 - .../soliditycode_0.5.15/TvmIsContract002.sol | 5 - .../soliditycode_0.5.15/TvmNewCommand043.sol | 18 - .../soliditycode_0.5.15/TvmNewCommand103.sol | 8 - .../soliditycode_0.5.15/TvmNewCommand107.sol | 9 - .../soliditycode_0.5.15/TvmNewCommand108.sol | 7 - .../soliditycode_0.5.15/TvmNewCommand109.sol | 7 - .../soliditycode_0.5.15/TvmOldCommand001.sol | 11 - .../VerifyBurnProof001.sol | 20 - .../VerifyMintProof001.sol | 33 - .../soliditycode_0.5.15/abiencode.sol | 16 - .../addMsg001Nonpayable.sol | 20 - .../soliditycode_0.5.15/addMsg002View.sol | 20 - .../soliditycode_0.5.15/addMsg003Constant.sol | 19 - .../soliditycode_0.5.15/addMsg004Pure.sol | 19 - .../addTransferToken001Nonpayable.sol | 13 - .../addTransferToken001payable.sol | 13 - .../addTransferToken002View.sol | 15 - .../addTransferToken003Constant.sol | 15 - .../addTransferToken004Pure.sol | 15 - .../addTrcToken001Assemble.sol | 62 - .../soliditycode_0.5.15/addTrcToken002Cat.sol | 2051 ---------------- .../addTrcToken002Cat_withFinny.sol | 2051 ---------------- .../soliditycode_0.5.15/addressCheckNew.sol | 9 - .../soliditycode_0.5.15/addressCheckOld.sol | 8 - .../resources/soliditycode_0.5.15/altbn.sol | 63 - .../soliditycode_0.5.15/arrayLength001.sol | 16 - .../soliditycode_0.5.15/assemblyTest.sol | 62 - .../assertExceptiontest1DivideInt.sol | 7 - ...tExceptiontest2FindArgsContractMinTest.sol | 10 - .../assertExceptiontest3ByteMinContract.sol | 11 - .../assertExceptiontest4Enum.sol | 13 - .../assertExceptiontest5MoveRight.sol | 7 - ...ertExceptiontest6UninitializedContract.sol | 27 - ...assertExceptiontest7TestAssertContract.sol | 15 - .../soliditycode_0.5.15/batchvalidatesign.sol | 14 - .../batchvalidatesign001.sol | 10 - .../batchvalidatesign002.sol | 8 - .../batchvalidatesign003.sol | 11 - .../batchvalidatesign005.sol | 14 - .../batchvalidatesign007.sol | 17 - .../batchvalidatesign02.sol | 8 - .../soliditycode_0.5.15/callValueGasPure.sol | 8 - .../soliditycode_0.5.15/calldata.sol | 33 - .../soliditycode_0.5.15/callvalue.sol | 9 - .../soliditycode_0.5.15/chainid001.sol | 20 - .../soliditycode_0.5.15/codeSaftySupport.sol | 19 - .../codeSaftyUnsupport.sol | 56 - .../constantCallStorage001.sol | 159 -- .../constantCallStorage002.sol | 16 - .../constantCallStorage0425.sol | 156 -- .../constantContract001.sol | 8 - .../contractGetterContract.sol | 17 - .../contractGrammar001test1Grammar001.sol | 18 - .../contractGrammar001test2Grammar002.sol | 44 - .../contractGrammar001test3Grammar003.sol | 44 - .../contractGrammar001test4Grammar004.sol | 31 - .../contractGrammar001test5Grammar006.sol | 38 - .../contractGrammar002test1Grammar007_1.sol | 60 - .../contractGrammar002test1Grammar007_2.sol | 60 - .../contractGrammar002test2Grammar008.sol | 14 - .../contractGrammar002test3Grammar010.sol | 10 - .../contractGrammar002test4Grammar011.sol | 11 - .../contractGrammar002test4Grammar012.sol | 24 - .../contractGrammar002test6Grammar013.sol | 24 - .../contractGrammar003test1Grammar014.sol | 68 - .../contractGrammar003test2Grammar015.sol | 39 - .../contractGrammar003test3Grammar016.sol | 23 - .../contractGrammar003test4Grammar017.sol | 50 - .../contractGrammar003test5Grammar018.sol | 37 - .../contractGrammar003test6Grammar019.sol | 12 - .../contractGrammar003test7Grammar020.sol | 8 - .../contractInnerContract.sol | 32 - ...ansaction001testInternalTransaction001.sol | 42 - ...ansaction001testInternalTransaction002.sol | 21 - ...ansaction001testInternalTransaction003.sol | 31 - ...ansaction001testInternalTransaction004.sol | 25 - ...ansaction001testInternalTransaction005.sol | 54 - ...ansaction001testInternalTransaction006.sol | 54 - ...nsaction002test1InternalTransaction007.sol | 38 - ...nsaction002test2InternalTransaction008.sol | 60 - ...nsaction002test3InternalTransaction009.sol | 47 - ...nsaction002test4InternalTransaction010.sol | 186 -- ...action002test4InternalTransaction010_1.sol | 210 -- ...nsaction002test5InternalTransaction012.sol | 51 - ...ansaction003testInternalTransaction013.sol | 56 - ...ansaction003testInternalTransaction014.sol | 38 - ...ansaction003testInternalTransaction015.sol | 60 - ...ansaction003testInternalTransaction016.sol | 174 -- ...ansaction003testInternalTransaction017.sol | 199 -- ...ansaction003testInternalTransaction018.sol | 97 - .../contractLinkage001.sol | 9 - .../contractLinkage002.sol | 7 - .../contractLinkage003.sol | 7 - .../contractLinkage004.sol | 7 - .../contractLinkage005.sol | 51 - .../contractLinkage006.sol | 18 - .../contractOriginEnergyLimit001.sol | 11 - .../contractOriginEnergyLimit004.sol | 11 - .../contractOtherToTrcToken.sol | 41 - .../contractScenario001.sol | 7 - .../contractScenario002.sol | 53 - .../contractScenario003.sol | 7 - .../contractScenario004.sol | 88 - .../contractScenario005.sol | 103 - .../contractScenario006.sol | 1963 ---------------- .../contractScenario007.sol | 1433 ------------ .../contractScenario008.sol | 2050 ---------------- .../contractScenario009.sol | 51 - .../contractScenario010.sol | 107 - .../contractScenario011.sol | 2050 ---------------- .../contractScenario012.sol | 57 - .../contractScenario013.sol | 8 - .../contractScenario014.sol | 34 - .../soliditycode_0.5.15/contractTest.sol | 19 - .../contractToMathedFeed.sol | 21 - .../contractTransferToken001.sol | 22 - .../contractTrcToken001.sol | 30 - .../contractTrcToken002.sol | 30 - .../contractTrcToken003.sol | 16 - .../contractTrcToken005.sol | 16 - .../contractTrcToken011.sol | 35 - .../contractTrcToken012.sol | 26 - .../contractTrcToken014.sol | 34 - .../contractTrcToken018.sol | 26 - .../contractTrcToken023.sol | 26 - .../contractTrcToken026.sol | 31 - .../contractTrcToken027.sol | 30 - .../contractTrcToken028.sol | 25 - .../contractTrcToken029.sol | 24 - .../contractTrcToken030.sol | 18 - .../contractTrcToken031.sol | 18 - .../contractTrcToken034.sol | 25 - .../contractTrcToken035.sol | 24 - .../contractTrcToken036.sol | 52 - .../contractTrcToken036_1.sol | 13 - .../contractTrcToken036_2.sol | 13 - .../contractTrcToken036_3.sol | 13 - .../contractTrcToken036_4.sol | 13 - .../contractTrcToken036_old.sol | 41 - .../contractTrcToken037.sol | 24 - .../contractTrcToken038.sol | 24 - .../contractTrcToken039.sol | 44 - .../contractTrcToken041.sol | 20 - .../contractTrcToken043.sol | 35 - .../contractTrcToken048.sol | 14 - .../contractTrcToken049.sol | 10 - .../contractTrcToken050.sol | 10 - .../contractTrcToken051.sol | 11 - .../contractTrcToken052.sol | 10 - .../contractTrcToken054.sol | 16 - .../contractTrcToken055.sol | 16 - .../contractTrcToken060.sol | 30 - .../contractTrcToken061.sol | 30 - .../contractTrcToken064.sol | 49 - .../contractTrcToken066.sol | 35 - .../contractTrcToken067.sol | 35 - .../contractTrcToken073.sol | 17 - .../contractTrcToken075.sol | 26 - .../contractTrcToken076.sol | 19 - .../contractTrcToken077.sol | 11 - .../contractTrcToken078.sol | 35 - .../contractTrcToken079.sol | 16 - .../contractTrcToken080.sol | 30 - .../contractTrcTokenToOther.sol | 44 - .../contractUnknownException.sol | 65 - .../create2CallContract.sol | 37 - .../soliditycode_0.5.15/create2Istanbul.sol | 28 - .../soliditycode_0.5.15/create2contract.sol | 52 - .../soliditycode_0.5.15/create2contract22.sol | 109 - .../soliditycode_0.5.15/create2contractn.sol | 29 - .../soliditycode_0.5.15/create2contractn2.sol | 26 - .../resources/soliditycode_0.5.15/demo.sol | 73 - .../soliditycode_0.5.15/event001.sol | 10 - .../soliditycode_0.5.15/event002.sol | 52 - .../soliditycode_0.5.15/extCodeHash.sol | 13 - .../soliditycode_0.5.15/extCodeHash11.sol | 103 - .../extCodeHashConstruct.sol | 14 - .../soliditycode_0.5.15/extCodeHashStress.sol | 45 - .../extCodeHashTestNoPayable.sol | 8 - .../soliditycode_0.5.15/isSRCandidate.sol | 35 - .../soliditycode_0.5.15/mappingGetter.sol | 4 - .../multiValiSignPerformance01.sol | 37 - .../multiValiSignPerformance02.sol | 10 - .../soliditycode_0.5.15/multivalidatesign.sol | 14 - .../multivalidatesign001.sol | 10 - .../multivalidatesign002.sol | 8 - .../multivalidatesign003.sol | 11 - .../multivalidatesign005.sol | 14 - .../multivalidatesign007.sol | 17 - .../multivalidatesign02.sol | 8 - .../soliditycode_0.5.15/negativeArray.sol | 20 - .../soliditycode_0.5.15/payable001.sol | 31 - .../soliditycode_0.5.15/pedersenHash001.sol | 18 - .../soliditycode_0.5.15/pedersenHash002.sol | 321 --- ...quireExceptiontest1TestRequireContract.sol | 15 - ...equireExceptiontest2TestThrowsContract.sol | 15 - ...equireExceptiontest3TestRevertContract.sol | 15 - ...requireExceptiontest4noPayableContract.sol | 8 - ...quireExceptiontest4noPayableContract_1.sol | 8 - ...uireExceptiontest5noPayableConstructor.sol | 11 - ...reExceptiontest5noPayableConstructor_1.sol | 11 - ...uireExceptiontest6transferTestContract.sol | 8 - ...reExceptiontest7payableFallbakContract.sol | 14 - ...reExceptiontest8newContractGasNoenough.sol | 19 - ...uireExceptiontest9MessageUsedErrorFeed.sol | 18 - ...uireExceptiontestFunctionUsedErrorFeed.sol | 17 - .../soliditycode_0.5.15/selector.sol | 21 - .../soliditycode_0.5.15/stackContract001.sol | 61 - .../soliditycode_0.5.15/stackSuicide001.sol | 84 - .../soliditycode_0.5.15/stringSplit.sol | 45 - .../soliditycode_0.5.15/suicide001.sol | 32 - .../soliditycode_0.5.15/suicide002.sol | 43 - .../soliditycode_0.5.15/testOutOfMem.sol | 7 - .../soliditycode_0.5.15/testStakeSuicide.sol | 71 - .../soliditycode_0.5.15/tryCatch001.sol | 105 - .../soliditycode_0.5.15/tvmAssetIssue001.sol | 26 - .../soliditycode_0.5.15/tvmAssetIssue002.sol | 15 - .../soliditycode_0.5.15/tvmAssetIssue003.sol | 23 - .../soliditycode_0.5.15/tvmAssetIssue004.sol | 39 - .../soliditycode_0.5.15/tvmAssetIssue005.sol | 45 - .../soliditycode_0.5.15/typeName.sol | 5 - .../soliditycode_0.5.15/unStake001.sol | 90 - .../validatemultisign001.sol | 15 - .../verifyTransferProof001.sol | 15 - .../walletTestMutiSign004.sol | 51 - .../AssertException002.sol | 17 - .../soliditycode_0.6.12/AssignToExternal.sol | 30 - .../soliditycode_0.6.12/BlockHash.sol | 38 - .../soliditycode_0.6.12/ClearAbi001.sol | 7 - .../soliditycode_0.6.12/ClearAbi005.sol | 26 - .../ConstructorDefaults.sol | 9 - .../soliditycode_0.6.12/Create2Test023.sol | 31 - .../soliditycode_0.6.12/Create2Test024.sol | 56 - .../soliditycode_0.6.12/Create2Test025.sol | 34 - .../ExtCodeHashTest010.sol | 46 - .../soliditycode_0.6.12/ExternalSelector.sol | 92 - .../soliditycode_0.6.12/NewFeature068.sol | 126 - .../soliditycode_0.6.12/ParentTypeBug.sol | 13 - .../soliditycode_0.6.12/SafeMath.sol | 149 -- .../soliditycode_0.6.12/ShiftCommand001.sol | 18 - .../SolidityMappingFix.sol | 9 - .../TestMappings_array_pop.sol | 19 - .../soliditycode_0.6.12/TransferFailed001.sol | 147 -- .../soliditycode_0.6.12/TransferFailed005.sol | 90 - .../soliditycode_0.6.12/TransferFailed006.sol | 90 - .../soliditycode_0.6.12/TransferFailed007.sol | 90 - .../TriggerConstant001.sol | 28 - .../TriggerConstant002.sol | 10 - .../TriggerConstant003.sol | 18 - .../TriggerConstant004.sol | 8 - .../TriggerConstant015.sol | 24 - .../TriggerConstant024.sol | 9 - .../soliditycode_0.6.12/TvmIsContract.sol | 15 - .../soliditycode_0.6.12/TvmIsContract001.sol | 24 - .../soliditycode_0.6.12/TvmIsContract002.sol | 5 - .../soliditycode_0.6.12/TvmNewCommand043.sol | 18 - .../soliditycode_0.6.12/TvmNewCommand103.sol | 8 - .../soliditycode_0.6.12/TvmNewCommand107.sol | 9 - .../soliditycode_0.6.12/TvmNewCommand108.sol | 7 - .../soliditycode_0.6.12/TvmNewCommand109.sol | 7 - .../soliditycode_0.6.12/TvmOldCommand001.sol | 11 - .../VerifyBurnProof001.sol | 20 - .../VerifyMintProof001.sol | 33 - .../soliditycode_0.6.12/abiencode.sol | 16 - .../soliditycode_0.6.12/abstract001.sol | 11 - .../soliditycode_0.6.12/abstract002.sol | 13 - .../soliditycode_0.6.12/accountAssert.sol | 94 - .../addMsg001Nonpayable.sol | 20 - .../soliditycode_0.6.12/addMsg002View.sol | 20 - .../soliditycode_0.6.12/addMsg003Constant.sol | 19 - .../soliditycode_0.6.12/addMsg004Pure.sol | 19 - .../addTransferToken001Nonpayable.sol | 13 - .../addTransferToken001payable.sol | 13 - .../addTransferToken002View.sol | 15 - .../addTransferToken003Constant.sol | 14 - .../addTransferToken004Pure.sol | 15 - .../addTrcToken001Assemble.sol | 62 - .../soliditycode_0.6.12/addTrcToken002Cat.sol | 2051 ---------------- .../addTrcToken002Cat_withFinny.sol | 2051 ---------------- .../soliditycode_0.6.12/addressCheckNew.sol | 9 - .../soliditycode_0.6.12/addressCheckOld.sol | 8 - .../resources/soliditycode_0.6.12/altbn.sol | 61 - .../soliditycode_0.6.12/arrayLength001.sol | 64 - .../soliditycode_0.6.12/assemblyTest.sol | 61 - .../assertExceptiontest1DivideInt.sol | 7 - ...tExceptiontest2FindArgsContractMinTest.sol | 10 - .../assertExceptiontest3ByteMinContract.sol | 11 - .../assertExceptiontest4Enum.sol | 13 - .../assertExceptiontest5MoveRight.sol | 7 - ...ertExceptiontest6UninitializedContract.sol | 27 - ...assertExceptiontest7TestAssertContract.sol | 14 - .../soliditycode_0.6.12/batchvalidatesign.sol | 14 - .../batchvalidatesign001.sol | 10 - .../batchvalidatesign002.sol | 8 - .../batchvalidatesign003.sol | 11 - .../batchvalidatesign005.sol | 14 - .../batchvalidatesign007.sol | 17 - .../batchvalidatesign02.sol | 8 - .../soliditycode_0.6.12/callValueGasPure.sol | 8 - .../soliditycode_0.6.12/calldata.sol | 33 - .../soliditycode_0.6.12/callvalue.sol | 9 - .../soliditycode_0.6.12/chainid001.sol | 19 - .../soliditycode_0.6.12/codeSaftySupport.sol | 19 - .../codeSaftyUnsupport.sol | 56 - .../constantCallStorage001.sol | 159 -- .../constantCallStorage002.sol | 16 - .../constantCallStorage0425.sol | 156 -- .../constantContract001.sol | 8 - .../contractGetterContract.sol | 17 - .../contractGrammar001test1Grammar001.sol | 18 - .../contractGrammar001test2Grammar002.sol | 44 - .../contractGrammar001test3Grammar003.sol | 44 - .../contractGrammar001test4Grammar004.sol | 31 - .../contractGrammar001test5Grammar006.sol | 45 - .../contractGrammar002test1Grammar007_1.sol | 60 - .../contractGrammar002test1Grammar007_2.sol | 60 - .../contractGrammar002test2Grammar008.sol | 18 - .../contractGrammar002test3Grammar010.sol | 10 - .../contractGrammar002test4Grammar011.sol | 11 - .../contractGrammar002test4Grammar012.sol | 24 - .../contractGrammar002test6Grammar013.sol | 24 - .../contractGrammar003test1Grammar014.sol | 67 - .../contractGrammar003test2Grammar015.sol | 40 - .../contractGrammar003test3Grammar016.sol | 23 - .../contractGrammar003test4Grammar017.sol | 50 - .../contractGrammar003test5Grammar018.sol | 37 - .../contractGrammar003test6Grammar019.sol | 12 - .../contractGrammar003test7Grammar020.sol | 8 - .../contractInnerContract.sol | 32 - ...ansaction001testInternalTransaction001.sol | 41 - ...ansaction001testInternalTransaction002.sol | 20 - ...ansaction001testInternalTransaction003.sol | 30 - ...ansaction001testInternalTransaction004.sol | 24 - ...ansaction001testInternalTransaction005.sol | 53 - ...ansaction001testInternalTransaction006.sol | 54 - ...nsaction002test1InternalTransaction007.sol | 38 - ...nsaction002test2InternalTransaction008.sol | 60 - ...nsaction002test3InternalTransaction009.sol | 47 - ...nsaction002test4InternalTransaction010.sol | 186 -- ...action002test4InternalTransaction010_1.sol | 210 -- ...nsaction002test5InternalTransaction012.sol | 51 - ...ansaction003testInternalTransaction013.sol | 56 - ...ansaction003testInternalTransaction014.sol | 38 - ...ansaction003testInternalTransaction015.sol | 60 - ...ansaction003testInternalTransaction016.sol | 174 -- ...ansaction003testInternalTransaction017.sol | 199 -- ...ansaction003testInternalTransaction018.sol | 97 - .../contractLinkage001.sol | 9 - .../contractLinkage002.sol | 7 - .../contractLinkage003.sol | 7 - .../contractLinkage004.sol | 7 - .../contractLinkage005.sol | 51 - .../contractLinkage006.sol | 18 - .../contractOriginEnergyLimit001.sol | 11 - .../contractOriginEnergyLimit004.sol | 11 - .../contractOtherToTrcToken.sol | 41 - .../contractScenario001.sol | 7 - .../contractScenario002.sol | 53 - .../contractScenario003.sol | 7 - .../contractScenario004.sol | 88 - .../contractScenario005.sol | 103 - .../contractScenario006.sol | 1963 ---------------- .../contractScenario007.sol | 1432 ------------ .../contractScenario008.sol | 2061 ----------------- .../contractScenario009.sol | 51 - .../contractScenario010.sol | 107 - .../contractScenario011.sol | 2060 ---------------- .../contractScenario012.sol | 57 - .../contractScenario013.sol | 8 - .../contractScenario014.sol | 34 - .../soliditycode_0.6.12/contractTest.sol | 19 - .../contractToMathedFeed.sol | 21 - .../contractTransferToken001.sol | 22 - .../contractTrcToken001.sol | 30 - .../contractTrcToken002.sol | 30 - .../contractTrcToken003.sol | 16 - .../contractTrcToken005.sol | 16 - .../contractTrcToken011.sol | 35 - .../contractTrcToken012.sol | 26 - .../contractTrcToken014.sol | 34 - .../contractTrcToken018.sol | 26 - .../contractTrcToken023.sol | 26 - .../contractTrcToken026.sol | 31 - .../contractTrcToken027.sol | 30 - .../contractTrcToken028.sol | 25 - .../contractTrcToken029.sol | 24 - .../contractTrcToken030.sol | 17 - .../contractTrcToken031.sol | 18 - .../contractTrcToken034.sol | 25 - .../contractTrcToken035.sol | 24 - .../contractTrcToken036.sol | 52 - .../contractTrcToken036_1.sol | 13 - .../contractTrcToken036_2.sol | 13 - .../contractTrcToken036_3.sol | 13 - .../contractTrcToken036_4.sol | 13 - .../contractTrcToken036_old.sol | 41 - .../contractTrcToken037.sol | 24 - .../contractTrcToken038.sol | 24 - .../contractTrcToken039.sol | 44 - .../contractTrcToken041.sol | 20 - .../contractTrcToken043.sol | 35 - .../contractTrcToken048.sol | 14 - .../contractTrcToken049.sol | 9 - .../contractTrcToken050.sol | 10 - .../contractTrcToken051.sol | 11 - .../contractTrcToken052.sol | 10 - .../contractTrcToken054.sol | 16 - .../contractTrcToken055.sol | 16 - .../contractTrcToken060.sol | 30 - .../contractTrcToken061.sol | 30 - .../contractTrcToken064.sol | 49 - .../contractTrcToken066.sol | 35 - .../contractTrcToken067.sol | 35 - .../contractTrcToken073.sol | 16 - .../contractTrcToken075.sol | 26 - .../contractTrcToken076.sol | 19 - .../contractTrcToken077.sol | 11 - .../contractTrcToken078.sol | 35 - .../contractTrcToken079.sol | 16 - .../contractTrcToken080.sol | 30 - .../contractTrcTokenToOther.sol | 44 - .../contractUnknownException.sol | 64 - .../create2CallContract.sol | 37 - .../soliditycode_0.6.12/create2Istanbul.sol | 28 - .../soliditycode_0.6.12/create2contract.sol | 52 - .../soliditycode_0.6.12/create2contract22.sol | 109 - .../soliditycode_0.6.12/create2contractn.sol | 29 - .../soliditycode_0.6.12/create2contractn2.sol | 26 - .../resources/soliditycode_0.6.12/demo.sol | 73 - .../soliditycode_0.6.12/enumAndStruct.sol | 43 - .../soliditycode_0.6.12/event001.sol | 10 - .../soliditycode_0.6.12/event002.sol | 52 - .../soliditycode_0.6.12/extCodeHash.sol | 13 - .../soliditycode_0.6.12/extCodeHash11.sol | 103 - .../extCodeHashConstruct.sol | 14 - .../soliditycode_0.6.12/extCodeHashStress.sol | 45 - .../extCodeHashTestNoPayable.sol | 8 - .../soliditycode_0.6.12/fallbackUpgrade.sol | 83 - .../soliditycode_0.6.12/freezeContract001.sol | 63 - .../soliditycode_0.6.12/getAddressChange.sol | 12 - .../soliditycode_0.6.12/isSRCandidate.sol | 35 - .../soliditycode_0.6.12/mappingGetter.sol | 4 - .../multiValiSignPerformance01.sol | 37 - .../multiValiSignPerformance02.sol | 10 - .../soliditycode_0.6.12/multivalidatesign.sol | 14 - .../multivalidatesign001.sol | 10 - .../multivalidatesign002.sol | 8 - .../multivalidatesign003.sol | 11 - .../multivalidatesign005.sol | 14 - .../multivalidatesign007.sol | 17 - .../multivalidatesign02.sol | 8 - .../soliditycode_0.6.12/negativeArray.sol | 20 - .../soliditycode_0.6.12/override002.sol | 12 - .../soliditycode_0.6.12/override003.sol | 20 - .../soliditycode_0.6.12/override004.sol | 25 - .../soliditycode_0.6.12/override005.sol | 39 - .../overridePrivateFunction.sol | 22 - .../soliditycode_0.6.12/payable001.sol | 31 - .../soliditycode_0.6.12/pedersenHash001.sol | 18 - .../soliditycode_0.6.12/pedersenHash002.sol | 320 --- ...quireExceptiontest1TestRequireContract.sol | 15 - ...equireExceptiontest2TestThrowsContract.sol | 15 - ...equireExceptiontest3TestRevertContract.sol | 15 - ...requireExceptiontest4noPayableContract.sol | 8 - ...quireExceptiontest4noPayableContract_1.sol | 8 - ...uireExceptiontest5noPayableConstructor.sol | 11 - ...reExceptiontest5noPayableConstructor_1.sol | 11 - ...uireExceptiontest6transferTestContract.sol | 8 - ...reExceptiontest7payableFallbakContract.sol | 14 - ...reExceptiontest8newContractGasNoenough.sol | 19 - ...uireExceptiontest9MessageUsedErrorFeed.sol | 18 - ...uireExceptiontestFunctionUsedErrorFeed.sol | 17 - .../soliditycode_0.6.12/selector.sol | 21 - .../soliditycode_0.6.12/stackContract001.sol | 61 - .../soliditycode_0.6.12/stackSuicide001.sol | 84 - .../stateVariableShadowing.sol | 21 - .../soliditycode_0.6.12/stringSplit.sol | 45 - .../soliditycode_0.6.12/suicide001.sol | 32 - .../soliditycode_0.6.12/suicide002.sol | 43 - .../soliditycode_0.6.12/testOutOfMem.sol | 7 - .../soliditycode_0.6.12/testStakeSuicide.sol | 71 - .../soliditycode_0.6.12/tryCatch001.sol | 105 - .../soliditycode_0.6.12/tvmAssetIssue001.sol | 25 - .../soliditycode_0.6.12/tvmAssetIssue002.sol | 15 - .../soliditycode_0.6.12/tvmAssetIssue003.sol | 23 - .../soliditycode_0.6.12/tvmAssetIssue004.sol | 39 - .../soliditycode_0.6.12/tvmAssetIssue005.sol | 45 - .../soliditycode_0.6.12/typeName.sol | 5 - .../soliditycode_0.6.12/unStake001.sol | 90 - .../validatemultisign001.sol | 15 - .../verifyTransferProof001.sol | 15 - .../soliditycode_0.6.12/virtual001.sol | 19 - .../walletTestMutiSign004.sol | 51 - .../soliditycode_0.7.6/AssertException002.sol | 17 - .../soliditycode_0.7.6/AssignToExternal.sol | 30 - .../soliditycode_0.7.6/BlockHash.sol | 38 - .../soliditycode_0.7.6/ClearAbi001.sol | 7 - .../soliditycode_0.7.6/ClearAbi005.sol | 26 - .../ConstructorDefaults.sol | 9 - .../soliditycode_0.7.6/Create2Test023.sol | 31 - .../soliditycode_0.7.6/Create2Test024.sol | 56 - .../soliditycode_0.7.6/Create2Test025.sol | 34 - .../soliditycode_0.7.6/ExtCodeHashTest010.sol | 46 - .../soliditycode_0.7.6/ExternalSelector.sol | 92 - .../soliditycode_0.7.6/NewFeature068.sol | 126 - .../soliditycode_0.7.6/NewFeature076.sol | 21 - .../soliditycode_0.7.6/ParentTypeBug.sol | 13 - .../resources/soliditycode_0.7.6/SafeMath.sol | 149 -- .../soliditycode_0.7.6/ShiftCommand001.sol | 18 - .../soliditycode_0.7.6/SolidityMappingFix.sol | 9 - .../TestMappings_array_pop.sol | 19 - .../soliditycode_0.7.6/TransferFailed001.sol | 147 -- .../soliditycode_0.7.6/TransferFailed005.sol | 90 - .../soliditycode_0.7.6/TransferFailed006.sol | 90 - .../soliditycode_0.7.6/TransferFailed007.sol | 90 - .../soliditycode_0.7.6/TriggerConstant001.sol | 28 - .../soliditycode_0.7.6/TriggerConstant002.sol | 10 - .../soliditycode_0.7.6/TriggerConstant003.sol | 18 - .../soliditycode_0.7.6/TriggerConstant004.sol | 8 - .../soliditycode_0.7.6/TriggerConstant015.sol | 24 - .../soliditycode_0.7.6/TriggerConstant024.sol | 9 - .../soliditycode_0.7.6/TvmIsContract.sol | 15 - .../soliditycode_0.7.6/TvmIsContract001.sol | 24 - .../soliditycode_0.7.6/TvmIsContract002.sol | 5 - .../soliditycode_0.7.6/TvmNewCommand043.sol | 18 - .../soliditycode_0.7.6/TvmNewCommand103.sol | 8 - .../soliditycode_0.7.6/TvmNewCommand107.sol | 9 - .../soliditycode_0.7.6/TvmNewCommand108.sol | 7 - .../soliditycode_0.7.6/TvmNewCommand109.sol | 7 - .../soliditycode_0.7.6/TvmOldCommand001.sol | 11 - .../soliditycode_0.7.6/VerifyBurnProof001.sol | 20 - .../soliditycode_0.7.6/VerifyMintProof001.sol | 33 - .../soliditycode_0.7.6/abiencode.sol | 16 - .../soliditycode_0.7.6/abstract001.sol | 11 - .../soliditycode_0.7.6/abstract002.sol | 13 - .../soliditycode_0.7.6/accountAssert.sol | 94 - .../addMsg001Nonpayable.sol | 20 - .../soliditycode_0.7.6/addMsg002View.sol | 20 - .../soliditycode_0.7.6/addMsg003Constant.sol | 19 - .../soliditycode_0.7.6/addMsg004Pure.sol | 19 - .../addTransferToken001Nonpayable.sol | 13 - .../addTransferToken001payable.sol | 13 - .../addTransferToken002View.sol | 15 - .../addTransferToken003Constant.sol | 14 - .../addTransferToken004Pure.sol | 15 - .../addTrcToken001Assemble.sol | 62 - .../soliditycode_0.7.6/addTrcToken002Cat.sol | 2051 ---------------- .../addTrcToken002Cat_withFinny.sol | 2051 ---------------- .../soliditycode_0.7.6/addressCheckNew.sol | 9 - .../soliditycode_0.7.6/addressCheckOld.sol | 8 - .../resources/soliditycode_0.7.6/altbn.sol | 61 - .../soliditycode_0.7.6/arrayLength001.sol | 64 - .../soliditycode_0.7.6/assemblyTest.sol | 61 - .../assertExceptiontest1DivideInt.sol | 7 - ...tExceptiontest2FindArgsContractMinTest.sol | 10 - .../assertExceptiontest3ByteMinContract.sol | 11 - .../assertExceptiontest4Enum.sol | 13 - .../assertExceptiontest5MoveRight.sol | 7 - ...ertExceptiontest6UninitializedContract.sol | 27 - ...assertExceptiontest7TestAssertContract.sol | 14 - .../soliditycode_0.7.6/batchvalidatesign.sol | 14 - .../batchvalidatesign001.sol | 10 - .../batchvalidatesign002.sol | 8 - .../batchvalidatesign003.sol | 11 - .../batchvalidatesign005.sol | 14 - .../batchvalidatesign007.sol | 17 - .../batchvalidatesign02.sol | 8 - .../soliditycode_0.7.6/callValueGasPure.sol | 8 - .../resources/soliditycode_0.7.6/calldata.sol | 33 - .../soliditycode_0.7.6/callvalue.sol | 9 - .../soliditycode_0.7.6/chainid001.sol | 19 - .../soliditycode_0.7.6/codeSaftySupport.sol | 19 - .../soliditycode_0.7.6/codeSaftyUnsupport.sol | 56 - .../constantCallStorage001.sol | 159 -- .../constantCallStorage002.sol | 16 - .../constantCallStorage0425.sol | 156 -- .../constantContract001.sol | 8 - .../contractGetterContract.sol | 17 - .../contractGrammar001test1Grammar001.sol | 18 - .../contractGrammar001test2Grammar002.sol | 44 - .../contractGrammar001test3Grammar003.sol | 44 - .../contractGrammar001test4Grammar004.sol | 31 - .../contractGrammar001test5Grammar006.sol | 45 - .../contractGrammar002test1Grammar007_1.sol | 60 - .../contractGrammar002test1Grammar007_2.sol | 60 - .../contractGrammar002test2Grammar008.sol | 18 - .../contractGrammar002test3Grammar010.sol | 10 - .../contractGrammar002test4Grammar011.sol | 11 - .../contractGrammar002test4Grammar012.sol | 24 - .../contractGrammar002test6Grammar013.sol | 24 - .../contractGrammar003test1Grammar014.sol | 67 - .../contractGrammar003test2Grammar015.sol | 40 - .../contractGrammar003test3Grammar016.sol | 23 - .../contractGrammar003test4Grammar017.sol | 51 - .../contractGrammar003test5Grammar018.sol | 37 - .../contractGrammar003test6Grammar019.sol | 12 - .../contractGrammar003test7Grammar020.sol | 8 - .../contractInnerContract.sol | 32 - ...ansaction001testInternalTransaction001.sol | 41 - ...ansaction001testInternalTransaction002.sol | 20 - ...ansaction001testInternalTransaction003.sol | 30 - ...ansaction001testInternalTransaction004.sol | 24 - ...ansaction001testInternalTransaction005.sol | 53 - ...ansaction001testInternalTransaction006.sol | 54 - ...nsaction002test1InternalTransaction007.sol | 38 - ...nsaction002test2InternalTransaction008.sol | 60 - ...nsaction002test3InternalTransaction009.sol | 47 - ...nsaction002test4InternalTransaction010.sol | 186 -- ...action002test4InternalTransaction010_1.sol | 210 -- ...nsaction002test5InternalTransaction012.sol | 51 - ...ansaction003testInternalTransaction013.sol | 56 - ...ansaction003testInternalTransaction014.sol | 38 - ...ansaction003testInternalTransaction015.sol | 60 - ...ansaction003testInternalTransaction016.sol | 174 -- ...ansaction003testInternalTransaction017.sol | 199 -- ...ansaction003testInternalTransaction018.sol | 97 - .../soliditycode_0.7.6/contractLinkage001.sol | 9 - .../soliditycode_0.7.6/contractLinkage002.sol | 7 - .../soliditycode_0.7.6/contractLinkage003.sol | 7 - .../soliditycode_0.7.6/contractLinkage004.sol | 7 - .../soliditycode_0.7.6/contractLinkage005.sol | 51 - .../soliditycode_0.7.6/contractLinkage006.sol | 18 - .../contractOriginEnergyLimit001.sol | 11 - .../contractOriginEnergyLimit004.sol | 11 - .../contractOtherToTrcToken.sol | 41 - .../contractScenario001.sol | 7 - .../contractScenario002.sol | 53 - .../contractScenario003.sol | 7 - .../contractScenario004.sol | 88 - .../contractScenario005.sol | 103 - .../contractScenario006.sol | 1963 ---------------- .../contractScenario007.sol | 1432 ------------ .../contractScenario008.sol | 2061 ----------------- .../contractScenario009.sol | 51 - .../contractScenario010.sol | 107 - .../contractScenario011.sol | 2060 ---------------- .../contractScenario012.sol | 57 - .../contractScenario013.sol | 8 - .../contractScenario014.sol | 34 - .../soliditycode_0.7.6/contractTest.sol | 19 - .../contractToMathedFeed.sol | 21 - .../contractTransferToken001.sol | 22 - .../contractTrcToken001.sol | 30 - .../contractTrcToken002.sol | 30 - .../contractTrcToken003.sol | 16 - .../contractTrcToken005.sol | 16 - .../contractTrcToken011.sol | 35 - .../contractTrcToken012.sol | 26 - .../contractTrcToken014.sol | 34 - .../contractTrcToken018.sol | 26 - .../contractTrcToken023.sol | 26 - .../contractTrcToken026.sol | 31 - .../contractTrcToken027.sol | 30 - .../contractTrcToken028.sol | 25 - .../contractTrcToken029.sol | 24 - .../contractTrcToken030.sol | 17 - .../contractTrcToken031.sol | 18 - .../contractTrcToken034.sol | 25 - .../contractTrcToken035.sol | 24 - .../contractTrcToken036.sol | 52 - .../contractTrcToken036_1.sol | 13 - .../contractTrcToken036_2.sol | 13 - .../contractTrcToken036_3.sol | 13 - .../contractTrcToken036_4.sol | 13 - .../contractTrcToken036_old.sol | 41 - .../contractTrcToken037.sol | 24 - .../contractTrcToken038.sol | 24 - .../contractTrcToken039.sol | 44 - .../contractTrcToken041.sol | 20 - .../contractTrcToken043.sol | 35 - .../contractTrcToken048.sol | 14 - .../contractTrcToken049.sol | 9 - .../contractTrcToken050.sol | 10 - .../contractTrcToken051.sol | 11 - .../contractTrcToken052.sol | 10 - .../contractTrcToken054.sol | 16 - .../contractTrcToken055.sol | 16 - .../contractTrcToken060.sol | 30 - .../contractTrcToken061.sol | 30 - .../contractTrcToken064.sol | 49 - .../contractTrcToken066.sol | 35 - .../contractTrcToken067.sol | 35 - .../contractTrcToken073.sol | 16 - .../contractTrcToken075.sol | 26 - .../contractTrcToken076.sol | 19 - .../contractTrcToken077.sol | 11 - .../contractTrcToken078.sol | 35 - .../contractTrcToken079.sol | 16 - .../contractTrcToken080.sol | 30 - .../contractTrcTokenToOther.sol | 44 - .../contractUnknownException.sol | 64 - .../create2CallContract.sol | 37 - .../soliditycode_0.7.6/create2Istanbul.sol | 28 - .../soliditycode_0.7.6/create2contract.sol | 52 - .../soliditycode_0.7.6/create2contract22.sol | 109 - .../soliditycode_0.7.6/create2contractn.sol | 29 - .../soliditycode_0.7.6/create2contractn2.sol | 26 - .../resources/soliditycode_0.7.6/demo.sol | 73 - .../soliditycode_0.7.6/enumAndStruct.sol | 43 - .../resources/soliditycode_0.7.6/event001.sol | 10 - .../resources/soliditycode_0.7.6/event002.sol | 52 - .../soliditycode_0.7.6/extCodeHash.sol | 13 - .../soliditycode_0.7.6/extCodeHash11.sol | 103 - .../extCodeHashConstruct.sol | 14 - .../soliditycode_0.7.6/extCodeHashStress.sol | 45 - .../extCodeHashTestNoPayable.sol | 8 - .../soliditycode_0.7.6/fallbackUpgrade.sol | 83 - .../soliditycode_0.7.6/freezeContract001.sol | 63 - .../soliditycode_0.7.6/getAddressChange.sol | 12 - .../soliditycode_0.7.6/isSRCandidate.sol | 35 - .../soliditycode_0.7.6/mappingGetter.sol | 4 - .../multiValiSignPerformance01.sol | 37 - .../multiValiSignPerformance02.sol | 10 - .../soliditycode_0.7.6/multivalidatesign.sol | 14 - .../multivalidatesign001.sol | 10 - .../multivalidatesign002.sol | 8 - .../multivalidatesign003.sol | 11 - .../multivalidatesign005.sol | 14 - .../multivalidatesign007.sol | 17 - .../multivalidatesign02.sol | 8 - .../soliditycode_0.7.6/negativeArray.sol | 20 - .../soliditycode_0.7.6/override002.sol | 12 - .../soliditycode_0.7.6/override003.sol | 20 - .../soliditycode_0.7.6/override004.sol | 25 - .../soliditycode_0.7.6/override005.sol | 39 - .../overridePrivateFunction.sol | 22 - .../soliditycode_0.7.6/payable001.sol | 31 - .../soliditycode_0.7.6/pedersenHash001.sol | 18 - .../soliditycode_0.7.6/pedersenHash002.sol | 320 --- ...quireExceptiontest1TestRequireContract.sol | 15 - ...equireExceptiontest2TestThrowsContract.sol | 15 - ...equireExceptiontest3TestRevertContract.sol | 15 - ...requireExceptiontest4noPayableContract.sol | 8 - ...quireExceptiontest4noPayableContract_1.sol | 8 - ...uireExceptiontest5noPayableConstructor.sol | 11 - ...reExceptiontest5noPayableConstructor_1.sol | 11 - ...uireExceptiontest6transferTestContract.sol | 8 - ...reExceptiontest7payableFallbakContract.sol | 14 - ...reExceptiontest8newContractGasNoenough.sol | 19 - ...uireExceptiontest9MessageUsedErrorFeed.sol | 18 - ...uireExceptiontestFunctionUsedErrorFeed.sol | 17 - .../resources/soliditycode_0.7.6/selector.sol | 21 - .../slotAndOffsetNewGrammer.sol | 32 - .../soliditycode_0.7.6/stackContract001.sol | 61 - .../soliditycode_0.7.6/stackSuicide001.sol | 84 - .../stateVariableShadowing.sol | 21 - .../soliditycode_0.7.6/stringSplit.sol | 45 - .../soliditycode_0.7.6/suicide001.sol | 32 - .../soliditycode_0.7.6/suicide002.sol | 43 - .../soliditycode_0.7.6/testOutOfMem.sol | 7 - .../soliditycode_0.7.6/testStakeSuicide.sol | 71 - .../soliditycode_0.7.6/tryCatch001.sol | 105 - .../soliditycode_0.7.6/tvmAssetIssue001.sol | 25 - .../soliditycode_0.7.6/tvmAssetIssue002.sol | 15 - .../soliditycode_0.7.6/tvmAssetIssue003.sol | 23 - .../soliditycode_0.7.6/tvmAssetIssue004.sol | 39 - .../soliditycode_0.7.6/tvmAssetIssue005.sol | 45 - .../resources/soliditycode_0.7.6/typeName.sol | 5 - .../soliditycode_0.7.6/unStake001.sol | 90 - .../validatemultisign001.sol | 15 - .../verifyTransferProof001.sol | 15 - .../soliditycode_0.7.6/virtual001.sol | 19 - .../walletTestMutiSign004.sol | 51 - .../TransferFailed001.sol | 0 .../TransferFailed005.sol | 106 - .../TransferFailed007.sol | 90 - .../addMsg001Nonpayable.sol | 20 - .../soliditycode_v0.4.25/addMsg002View.sol | 20 - .../addMsg003Constant.sol | 19 - .../soliditycode_v0.4.25/addMsg004Pure.sol | 19 - .../addTransferToken001Nonpayable.sol | 15 - .../addTransferToken002View.sol | 15 - .../addTransferToken003Constant.sol | 15 - .../addTransferToken004Pure.sol | 15 - .../addTrcToken001Assemble.sol | 81 - .../addTrcToken002Cat.sol | 2017 ---------------- .../addTrcToken002Cat_withFinny.sol | 2017 ---------------- .../assertExceptiontest1DivideInt.sol | 7 - ...tExceptiontest2FindArgsContractMinTest.sol | 10 - .../assertExceptiontest3ByteMinContract.sol | 11 - .../assertExceptiontest4Enum.sol | 13 - .../assertExceptiontest5MoveRight.sol | 7 - ...ertExceptiontest6UninitializedContract.sol | 27 - ...assertExceptiontest7TestAssertContract.sol | 17 - .../soliditycode_v0.4.25/codeSaftySupport.sol | 19 - .../codeSaftyUnsupport.sol | 50 - .../contractGetterContract.sol | 17 - .../contractGrammar001test1Grammar001.sol | 14 - .../contractGrammar001test2Grammar002.sol | 44 - .../contractGrammar001test3Grammar003.sol | 44 - .../contractGrammar001test4Grammar004.sol | 31 - .../contractGrammar001test5Grammar006.sol | 36 - .../contractGrammar002test1Grammar007_1.sol | 60 - .../contractGrammar002test1Grammar007_2.sol | 60 - .../contractGrammar002test2Grammar008.sol | 14 - .../contractGrammar002test3Grammar010.sol | 10 - .../contractGrammar002test4Grammar011.sol | 11 - .../contractGrammar002test4Grammar012.sol | 24 - .../contractGrammar002test6Grammar013.sol | 22 - .../contractGrammar003test1Grammar014.sol | 59 - .../contractGrammar003test2Grammar015.sol | 37 - .../contractGrammar003test3Grammar016.sol | 23 - .../contractGrammar003test4Grammar017.sol | 47 - .../contractGrammar003test5Grammar018.sol | 36 - .../contractGrammar003test6Grammar019.sol | 12 - .../contractGrammar003test7Grammar020.sol | 7 - .../contractInnerContract.sol | 31 - ...ansaction001testInternalTransaction001.sol | 42 - ...ansaction001testInternalTransaction002.sol | 20 - ...ansaction001testInternalTransaction003.sol | 31 - ...ansaction001testInternalTransaction004.sol | 24 - ...ansaction001testInternalTransaction005.sol | 54 - ...ansaction001testInternalTransaction006.sol | 54 - ...nsaction002test1InternalTransaction007.sol | 38 - ...nsaction002test2InternalTransaction008.sol | 60 - ...nsaction002test3InternalTransaction009.sol | 47 - ...nsaction002test4InternalTransaction010.sol | 188 -- ...nsaction002test5InternalTransaction012.sol | 51 - ...ansaction003testInternalTransaction013.sol | 56 - ...ansaction003testInternalTransaction014.sol | 40 - ...ansaction003testInternalTransaction015.sol | 60 - ...ansaction003testInternalTransaction016.sol | 184 -- ...ansaction003testInternalTransaction017.sol | 194 -- ...ansaction003testInternalTransaction018.sol | 149 -- .../contractLinkage001.sol | 9 - .../contractLinkage002.sol | 7 - .../contractLinkage003.sol | 7 - .../contractLinkage004.sol | 7 - .../contractLinkage005.sol | 51 - .../contractLinkage006.sol | 18 - .../contractOriginEnergyLimit001.sol | 11 - .../contractOriginEnergyLimit004.sol | 11 - .../contractOtherToTrcToken.sol | 40 - .../contractScenario001.sol | 7 - .../contractScenario002.sol | 53 - .../contractScenario003.sol | 7 - .../contractScenario004.sol | 88 - .../contractScenario005.sol | 103 - .../contractScenario006.sol | 1954 ---------------- .../contractScenario007.sol | 1433 ------------ .../contractScenario008.sol | 2016 ---------------- .../contractScenario009.sol | 51 - .../contractScenario010.sol | 107 - .../contractScenario011.sol | 2050 ---------------- .../contractScenario012.sol | 57 - .../contractScenario013.sol | 8 - .../contractScenario014.sol | 34 - .../soliditycode_v0.4.25/contractTest.sol | 19 - .../contractToMathedFeed.sol | 19 - .../contractTrcToken001.sol | 30 - .../contractTrcToken002.sol | 30 - .../contractTrcToken003.sol | 16 - .../contractTrcToken005.sol | 16 - .../contractTrcToken011.sol | 35 - .../contractTrcToken012.sol | 26 - .../contractTrcToken014.sol | 34 - .../contractTrcToken018.sol | 26 - .../contractTrcToken023.sol | 26 - .../contractTrcToken026.sol | 30 - .../contractTrcToken027.sol | 30 - .../contractTrcToken028.sol | 25 - .../contractTrcToken029.sol | 24 - .../contractTrcToken030.sol | 18 - .../contractTrcToken031.sol | 18 - .../contractTrcToken034.sol | 23 - .../contractTrcToken035.sol | 23 - .../contractTrcToken036.sol | 65 - .../contractTrcToken037.sol | 23 - .../contractTrcToken038.sol | 22 - .../contractTrcToken039.sol | 44 - .../contractTrcToken041.sol | 20 - .../contractTrcToken043.sol | 35 - .../contractTrcToken048.sol | 14 - .../contractTrcToken049.sol | 10 - .../contractTrcToken050.sol | 10 - .../contractTrcToken051.sol | 10 - .../contractTrcToken052.sol | 10 - .../contractTrcToken054.sol | 16 - .../contractTrcToken055.sol | 16 - .../contractTrcToken060.sol | 30 - .../contractTrcToken061.sol | 30 - .../contractTrcToken064.sol | 49 - .../contractTrcToken066.sol | 35 - .../contractTrcToken067.sol | 35 - .../contractTrcToken073.sol | 17 - .../contractTrcToken075.sol | 26 - .../contractTrcToken076.sol | 19 - .../contractTrcToken077.sol | 11 - .../contractTrcToken078.sol | 35 - .../contractTrcToken079.sol | 16 - .../contractTrcToken080.sol | 30 - .../contractTrcTokenToOther.sol | 44 - .../contractUnknownException.sol | 65 - ...quireExceptiontest1TestRequireContract.sol | 15 - ...equireExceptiontest2TestThrowsContract.sol | 15 - ...equireExceptiontest3TestRevertContract.sol | 15 - ...requireExceptiontest4noPayableContract.sol | 8 - ...uireExceptiontest5noPayableConstructor.sol | 10 - ...uireExceptiontest6transferTestContract.sol | 8 - ...reExceptiontest7payableFallbakContract.sol | 13 - ...reExceptiontest8newContractGasNoenough.sol | 18 - ...uireExceptiontest9MessageUsedErrorFeed.sol | 18 - ...uireExceptiontestFunctionUsedErrorFeed.sol | 17 - .../walletTestMutiSign004.sol | 52 - framework/src/test/resources/testng.xml | 45 - 1221 files changed, 100270 deletions(-) delete mode 100644 framework/src/test/resources/daily-build.xml delete mode 100644 framework/src/test/resources/solcDir/README.txt delete mode 100644 framework/src/test/resources/solidityFile.xml delete mode 100644 framework/src/test/resources/soliditycode/AssertException002.sol delete mode 100644 framework/src/test/resources/soliditycode/AssignToExternal.sol delete mode 100644 framework/src/test/resources/soliditycode/BlockHash.sol delete mode 100644 framework/src/test/resources/soliditycode/ClearAbi001.sol delete mode 100644 framework/src/test/resources/soliditycode/ClearAbi005.sol delete mode 100644 framework/src/test/resources/soliditycode/ConstructorDefaults.sol delete mode 100644 framework/src/test/resources/soliditycode/Create2Test023.sol delete mode 100644 framework/src/test/resources/soliditycode/Create2Test024.sol delete mode 100644 framework/src/test/resources/soliditycode/Create2Test025.sol delete mode 100644 framework/src/test/resources/soliditycode/EthGrammer.sol delete mode 100644 framework/src/test/resources/soliditycode/EthGrammer02.sol delete mode 100644 framework/src/test/resources/soliditycode/ExtCodeHashTest010.sol delete mode 100644 framework/src/test/resources/soliditycode/ExternalSelector.sol delete mode 100644 framework/src/test/resources/soliditycode/NewFeature068.sol delete mode 100644 framework/src/test/resources/soliditycode/NewFeature076.sol delete mode 100644 framework/src/test/resources/soliditycode/NewFeature080.sol delete mode 100644 framework/src/test/resources/soliditycode/NewFeature0811.sol delete mode 100644 framework/src/test/resources/soliditycode/NewFeature086.sol delete mode 100644 framework/src/test/resources/soliditycode/NoAbi001.sol delete mode 100644 framework/src/test/resources/soliditycode/NoAbi002.sol delete mode 100644 framework/src/test/resources/soliditycode/ParentTypeBug.sol delete mode 100644 framework/src/test/resources/soliditycode/SafeMath.sol delete mode 100644 framework/src/test/resources/soliditycode/ShiftCommand001.sol delete mode 100644 framework/src/test/resources/soliditycode/SolidityMappingFix.sol delete mode 100644 framework/src/test/resources/soliditycode/TestMappings_array_pop.sol delete mode 100644 framework/src/test/resources/soliditycode/TransferFailed001.sol delete mode 100644 framework/src/test/resources/soliditycode/TransferFailed005.sol delete mode 100644 framework/src/test/resources/soliditycode/TransferFailed006.sol delete mode 100644 framework/src/test/resources/soliditycode/TransferFailed007.sol delete mode 100644 framework/src/test/resources/soliditycode/TriggerConstant001.sol delete mode 100644 framework/src/test/resources/soliditycode/TriggerConstant002.sol delete mode 100644 framework/src/test/resources/soliditycode/TriggerConstant003.sol delete mode 100644 framework/src/test/resources/soliditycode/TriggerConstant004.sol delete mode 100644 framework/src/test/resources/soliditycode/TriggerConstant015.sol delete mode 100644 framework/src/test/resources/soliditycode/TriggerConstant024.sol delete mode 100644 framework/src/test/resources/soliditycode/TvmIsContract.sol delete mode 100644 framework/src/test/resources/soliditycode/TvmIsContract001.sol delete mode 100644 framework/src/test/resources/soliditycode/TvmIsContract002.sol delete mode 100644 framework/src/test/resources/soliditycode/TvmNewCommand043.sol delete mode 100644 framework/src/test/resources/soliditycode/TvmNewCommand103.sol delete mode 100644 framework/src/test/resources/soliditycode/TvmNewCommand107.sol delete mode 100644 framework/src/test/resources/soliditycode/TvmNewCommand108.sol delete mode 100644 framework/src/test/resources/soliditycode/TvmNewCommand109.sol delete mode 100644 framework/src/test/resources/soliditycode/TvmOldCommand001.sol delete mode 100644 framework/src/test/resources/soliditycode/VerifyBurnProof001.sol delete mode 100644 framework/src/test/resources/soliditycode/VerifyMintProof001.sol delete mode 100644 framework/src/test/resources/soliditycode/abiencode.sol delete mode 100644 framework/src/test/resources/soliditycode/abstract001.sol delete mode 100644 framework/src/test/resources/soliditycode/abstract002.sol delete mode 100644 framework/src/test/resources/soliditycode/abstractContractWithMapParamsConstructor.sol delete mode 100644 framework/src/test/resources/soliditycode/accountAssert.sol delete mode 100644 framework/src/test/resources/soliditycode/addMsg001Nonpayable.sol delete mode 100644 framework/src/test/resources/soliditycode/addMsg002View.sol delete mode 100644 framework/src/test/resources/soliditycode/addMsg003Constant.sol delete mode 100644 framework/src/test/resources/soliditycode/addMsg004Pure.sol delete mode 100644 framework/src/test/resources/soliditycode/addTransferToken001Nonpayable.sol delete mode 100644 framework/src/test/resources/soliditycode/addTransferToken001payable.sol delete mode 100644 framework/src/test/resources/soliditycode/addTransferToken002View.sol delete mode 100644 framework/src/test/resources/soliditycode/addTransferToken003Constant.sol delete mode 100644 framework/src/test/resources/soliditycode/addTransferToken004Pure.sol delete mode 100644 framework/src/test/resources/soliditycode/addTrcToken001Assemble.sol delete mode 100644 framework/src/test/resources/soliditycode/addTrcToken002Cat.sol delete mode 100644 framework/src/test/resources/soliditycode/addTrcToken002Cat_withFinny.sol delete mode 100644 framework/src/test/resources/soliditycode/addressCheckNew.sol delete mode 100644 framework/src/test/resources/soliditycode/addressCheckOld.sol delete mode 100644 framework/src/test/resources/soliditycode/altbn.sol delete mode 100644 framework/src/test/resources/soliditycode/arrayLength001.sol delete mode 100644 framework/src/test/resources/soliditycode/assemblyTest.sol delete mode 100644 framework/src/test/resources/soliditycode/assertExceptiontest1DivideInt.sol delete mode 100644 framework/src/test/resources/soliditycode/assertExceptiontest2FindArgsContractMinTest.sol delete mode 100644 framework/src/test/resources/soliditycode/assertExceptiontest3ByteMinContract.sol delete mode 100644 framework/src/test/resources/soliditycode/assertExceptiontest4Enum.sol delete mode 100644 framework/src/test/resources/soliditycode/assertExceptiontest5MoveRight.sol delete mode 100644 framework/src/test/resources/soliditycode/assertExceptiontest6UninitializedContract.sol delete mode 100644 framework/src/test/resources/soliditycode/assertExceptiontest7TestAssertContract.sol delete mode 100644 framework/src/test/resources/soliditycode/batchvalidatesign.sol delete mode 100644 framework/src/test/resources/soliditycode/batchvalidatesign001.sol delete mode 100644 framework/src/test/resources/soliditycode/batchvalidatesign002.sol delete mode 100644 framework/src/test/resources/soliditycode/batchvalidatesign003.sol delete mode 100644 framework/src/test/resources/soliditycode/batchvalidatesign005.sol delete mode 100644 framework/src/test/resources/soliditycode/batchvalidatesign007.sol delete mode 100644 framework/src/test/resources/soliditycode/batchvalidatesign02.sol delete mode 100644 framework/src/test/resources/soliditycode/callValueGasPure.sol delete mode 100644 framework/src/test/resources/soliditycode/calldata.sol delete mode 100644 framework/src/test/resources/soliditycode/callvalue.sol delete mode 100644 framework/src/test/resources/soliditycode/chainid001.sol delete mode 100644 framework/src/test/resources/soliditycode/codeSaftySupport.sol delete mode 100644 framework/src/test/resources/soliditycode/codeSaftyUnsupport.sol delete mode 100644 framework/src/test/resources/soliditycode/constantCallStorage001.sol delete mode 100644 framework/src/test/resources/soliditycode/constantCallStorage002.sol delete mode 100644 framework/src/test/resources/soliditycode/constantCallStorage0425.sol delete mode 100644 framework/src/test/resources/soliditycode/constantContract001.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGetterContract.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar001test1Grammar001.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar001test2Grammar002.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar001test3Grammar003.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar001test4Grammar004.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar001test5Grammar006.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar002test1Grammar007_1.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar002test1Grammar007_2.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar002test2Grammar008.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar002test3Grammar010.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar002test4Grammar011.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar002test4Grammar012.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar002test6Grammar013.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar003test1Grammar014.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar003test2Grammar015.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar003test3Grammar016.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar003test4Grammar017.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar003test5Grammar018.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar003test6Grammar019.sol delete mode 100644 framework/src/test/resources/soliditycode/contractGrammar003test7Grammar020.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInnerContract.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction001.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction002.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction003.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction004.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction005.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction006.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInternalTransaction002test1InternalTransaction007.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInternalTransaction002test2InternalTransaction008.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInternalTransaction002test3InternalTransaction009.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInternalTransaction002test4InternalTransaction010.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInternalTransaction002test4InternalTransaction010_1.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInternalTransaction002test5InternalTransaction012.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction013.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction014.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction015.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction016.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction017.sol delete mode 100644 framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction018.sol delete mode 100644 framework/src/test/resources/soliditycode/contractLinkage001.sol delete mode 100644 framework/src/test/resources/soliditycode/contractLinkage002.sol delete mode 100644 framework/src/test/resources/soliditycode/contractLinkage003.sol delete mode 100644 framework/src/test/resources/soliditycode/contractLinkage004.sol delete mode 100644 framework/src/test/resources/soliditycode/contractLinkage005.sol delete mode 100644 framework/src/test/resources/soliditycode/contractLinkage006.sol delete mode 100644 framework/src/test/resources/soliditycode/contractOriginEnergyLimit001.sol delete mode 100644 framework/src/test/resources/soliditycode/contractOriginEnergyLimit004.sol delete mode 100644 framework/src/test/resources/soliditycode/contractOtherToTrcToken.sol delete mode 100644 framework/src/test/resources/soliditycode/contractScenario001.sol delete mode 100644 framework/src/test/resources/soliditycode/contractScenario002.sol delete mode 100644 framework/src/test/resources/soliditycode/contractScenario003.sol delete mode 100644 framework/src/test/resources/soliditycode/contractScenario004.sol delete mode 100644 framework/src/test/resources/soliditycode/contractScenario005.sol delete mode 100644 framework/src/test/resources/soliditycode/contractScenario006.sol delete mode 100644 framework/src/test/resources/soliditycode/contractScenario007.sol delete mode 100644 framework/src/test/resources/soliditycode/contractScenario008.sol delete mode 100644 framework/src/test/resources/soliditycode/contractScenario009.sol delete mode 100644 framework/src/test/resources/soliditycode/contractScenario010.sol delete mode 100644 framework/src/test/resources/soliditycode/contractScenario011.sol delete mode 100644 framework/src/test/resources/soliditycode/contractScenario012.sol delete mode 100644 framework/src/test/resources/soliditycode/contractScenario013.sol delete mode 100644 framework/src/test/resources/soliditycode/contractScenario014.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTest.sol delete mode 100644 framework/src/test/resources/soliditycode/contractToMathedFeed.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTransferToken001.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrc1155.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken001.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken002.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken003.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken005.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken011.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken012.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken014.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken018.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken023.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken026.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken027.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken028.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken029.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken030.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken031.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken034.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken035.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken036.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken036_1.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken036_2.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken036_3.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken036_4.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken036_old.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken037.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken038.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken039.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken041.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken043.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken048.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken049.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken050.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken051.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken052.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken054.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken055.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken060.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken061.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken064.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken066.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken067.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken073.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken075.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken076.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken077.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken078.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken079.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken080.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcToken081.sol delete mode 100644 framework/src/test/resources/soliditycode/contractTrcTokenToOther.sol delete mode 100644 framework/src/test/resources/soliditycode/contractUnknownException.sol delete mode 100644 framework/src/test/resources/soliditycode/create2CallContract.sol delete mode 100644 framework/src/test/resources/soliditycode/create2Istanbul.sol delete mode 100644 framework/src/test/resources/soliditycode/create2contract.sol delete mode 100644 framework/src/test/resources/soliditycode/create2contract22.sol delete mode 100644 framework/src/test/resources/soliditycode/create2contractn.sol delete mode 100644 framework/src/test/resources/soliditycode/create2contractn2.sol delete mode 100644 framework/src/test/resources/soliditycode/demo.sol delete mode 100644 framework/src/test/resources/soliditycode/enumAndStruct.sol delete mode 100644 framework/src/test/resources/soliditycode/event001.sol delete mode 100644 framework/src/test/resources/soliditycode/event002.sol delete mode 100644 framework/src/test/resources/soliditycode/eventLog2.sol delete mode 100644 framework/src/test/resources/soliditycode/extCodeHash.sol delete mode 100644 framework/src/test/resources/soliditycode/extCodeHash11.sol delete mode 100644 framework/src/test/resources/soliditycode/extCodeHashConstruct.sol delete mode 100644 framework/src/test/resources/soliditycode/extCodeHashStress.sol delete mode 100644 framework/src/test/resources/soliditycode/extCodeHashTestNoPayable.sol delete mode 100644 framework/src/test/resources/soliditycode/fallbackUpgrade.sol delete mode 100644 framework/src/test/resources/soliditycode/freezeContract001.sol delete mode 100644 framework/src/test/resources/soliditycode/function_type_array_to_storage.sol delete mode 100644 framework/src/test/resources/soliditycode/getAddressChange.sol delete mode 100644 framework/src/test/resources/soliditycode/isSRCandidate.sol delete mode 100644 framework/src/test/resources/soliditycode/mappingGetter.sol delete mode 100644 framework/src/test/resources/soliditycode/multiValiSignPerformance01.sol delete mode 100644 framework/src/test/resources/soliditycode/multiValiSignPerformance02.sol delete mode 100644 framework/src/test/resources/soliditycode/multivalidatesign.sol delete mode 100644 framework/src/test/resources/soliditycode/multivalidatesign001.sol delete mode 100644 framework/src/test/resources/soliditycode/multivalidatesign002.sol delete mode 100644 framework/src/test/resources/soliditycode/multivalidatesign003.sol delete mode 100644 framework/src/test/resources/soliditycode/multivalidatesign005.sol delete mode 100644 framework/src/test/resources/soliditycode/multivalidatesign007.sol delete mode 100644 framework/src/test/resources/soliditycode/multivalidatesign02.sol delete mode 100644 framework/src/test/resources/soliditycode/negativeArray.sol delete mode 100644 framework/src/test/resources/soliditycode/opCode.sol delete mode 100644 framework/src/test/resources/soliditycode/override002.sol delete mode 100644 framework/src/test/resources/soliditycode/override003.sol delete mode 100644 framework/src/test/resources/soliditycode/override004.sol delete mode 100644 framework/src/test/resources/soliditycode/override005.sol delete mode 100644 framework/src/test/resources/soliditycode/overridePrivateFunction.sol delete mode 100644 framework/src/test/resources/soliditycode/payable001.sol delete mode 100644 framework/src/test/resources/soliditycode/pedersenHash001.sol delete mode 100644 framework/src/test/resources/soliditycode/pedersenHash002.sol delete mode 100644 framework/src/test/resources/soliditycode/requireExceptiontest1TestRequireContract.sol delete mode 100644 framework/src/test/resources/soliditycode/requireExceptiontest2TestThrowsContract.sol delete mode 100644 framework/src/test/resources/soliditycode/requireExceptiontest3TestRevertContract.sol delete mode 100644 framework/src/test/resources/soliditycode/requireExceptiontest4noPayableContract.sol delete mode 100644 framework/src/test/resources/soliditycode/requireExceptiontest4noPayableContract_1.sol delete mode 100644 framework/src/test/resources/soliditycode/requireExceptiontest5noPayableConstructor.sol delete mode 100644 framework/src/test/resources/soliditycode/requireExceptiontest5noPayableConstructor_1.sol delete mode 100644 framework/src/test/resources/soliditycode/requireExceptiontest6transferTestContract.sol delete mode 100644 framework/src/test/resources/soliditycode/requireExceptiontest7payableFallbakContract.sol delete mode 100644 framework/src/test/resources/soliditycode/requireExceptiontest8newContractGasNoenough.sol delete mode 100644 framework/src/test/resources/soliditycode/requireExceptiontest9MessageUsedErrorFeed.sol delete mode 100644 framework/src/test/resources/soliditycode/requireExceptiontestFunctionUsedErrorFeed.sol delete mode 100644 framework/src/test/resources/soliditycode/selector.sol delete mode 100644 framework/src/test/resources/soliditycode/slotAndOffsetNewGrammer.sol delete mode 100644 framework/src/test/resources/soliditycode/stackContract001.sol delete mode 100644 framework/src/test/resources/soliditycode/stackSuicide001.sol delete mode 100644 framework/src/test/resources/soliditycode/stateVariableShadowing.sol delete mode 100644 framework/src/test/resources/soliditycode/stringSplit.sol delete mode 100644 framework/src/test/resources/soliditycode/suicide001.sol delete mode 100644 framework/src/test/resources/soliditycode/suicide002.sol delete mode 100644 framework/src/test/resources/soliditycode/super_skip_unimplemented_in_abstract_contract.sol delete mode 100644 framework/src/test/resources/soliditycode/testGetFilterChange.sol delete mode 100644 framework/src/test/resources/soliditycode/testOutOfMem.sol delete mode 100644 framework/src/test/resources/soliditycode/testStakeSuicide.sol delete mode 100644 framework/src/test/resources/soliditycode/tryCatch001.sol delete mode 100644 framework/src/test/resources/soliditycode/tvmAssetIssue001.sol delete mode 100644 framework/src/test/resources/soliditycode/tvmAssetIssue002.sol delete mode 100644 framework/src/test/resources/soliditycode/tvmAssetIssue003.sol delete mode 100644 framework/src/test/resources/soliditycode/tvmAssetIssue004.sol delete mode 100644 framework/src/test/resources/soliditycode/tvmAssetIssue005.sol delete mode 100644 framework/src/test/resources/soliditycode/tvmVote.sol delete mode 100644 framework/src/test/resources/soliditycode/typeName.sol delete mode 100644 framework/src/test/resources/soliditycode/unStake001.sol delete mode 100644 framework/src/test/resources/soliditycode/validatemultisign001.sol delete mode 100644 framework/src/test/resources/soliditycode/verifyTransferProof001.sol delete mode 100644 framework/src/test/resources/soliditycode/virtual001.sol delete mode 100644 framework/src/test/resources/soliditycode/walletTestMutiSign004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/AssertException002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/AssignToExternal.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/BlockHash.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/ClearAbi001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/ClearAbi005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/ConstructorDefaults.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/Create2Test023.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/Create2Test024.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/Create2Test025.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/ExtCodeHashTest010.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/ParentTypeBug.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/SafeMath.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/ShiftCommand001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/SolidityMappingFix.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TestMappings_array_pop.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TransferFailed001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TransferFailed005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TransferFailed006.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TransferFailed007.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TriggerConstant001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TriggerConstant002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TriggerConstant003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TriggerConstant004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TriggerConstant015.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TriggerConstant024.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TvmIsContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TvmIsContract001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TvmIsContract002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand043.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand103.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand107.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand108.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand109.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/TvmOldCommand001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/VerifyBurnProof001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/VerifyMintProof001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/abiencode.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/addMsg001Nonpayable.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/addMsg002View.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/addMsg003Constant.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/addMsg004Pure.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/addTransferToken001Nonpayable.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/addTransferToken001payable.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/addTransferToken002View.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/addTransferToken003Constant.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/addTransferToken004Pure.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/addTrcToken001Assemble.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/addTrcToken002Cat.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/addTrcToken002Cat_withFinny.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/addressCheckNew.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/addressCheckOld.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/altbn.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/arrayLength001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/assemblyTest.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest1DivideInt.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest2FindArgsContractMinTest.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest3ByteMinContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest4Enum.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest5MoveRight.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest6UninitializedContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest7TestAssertContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign007.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign02.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/callValueGasPure.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/calldata.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/callvalue.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/chainid001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/codeSaftySupport.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/codeSaftyUnsupport.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/constantCallStorage001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/constantCallStorage002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/constantCallStorage0425.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/constantContract001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGetterContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test1Grammar001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test2Grammar002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test3Grammar003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test4Grammar004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test5Grammar006.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test1Grammar007_1.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test1Grammar007_2.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test2Grammar008.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test3Grammar010.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test4Grammar011.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test4Grammar012.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test6Grammar013.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test1Grammar014.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test2Grammar015.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test3Grammar016.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test4Grammar017.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test5Grammar018.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test6Grammar019.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test7Grammar020.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInnerContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction006.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test1InternalTransaction007.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test2InternalTransaction008.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test3InternalTransaction009.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test4InternalTransaction010.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test4InternalTransaction010_1.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test5InternalTransaction012.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction013.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction014.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction015.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction016.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction017.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction018.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractLinkage001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractLinkage002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractLinkage003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractLinkage004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractLinkage005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractLinkage006.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractOriginEnergyLimit001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractOriginEnergyLimit004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractOtherToTrcToken.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractScenario001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractScenario002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractScenario003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractScenario004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractScenario005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractScenario006.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractScenario007.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractScenario008.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractScenario009.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractScenario010.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractScenario011.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractScenario012.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractScenario013.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractScenario014.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTest.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractToMathedFeed.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTransferToken001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken011.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken012.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken014.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken018.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken023.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken026.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken027.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken028.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken029.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken030.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken031.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken034.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken035.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_1.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_2.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_3.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_4.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_old.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken037.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken038.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken039.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken041.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken043.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken048.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken049.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken050.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken051.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken052.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken054.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken055.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken060.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken061.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken064.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken066.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken067.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken073.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken075.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken076.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken077.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken078.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken079.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcToken080.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractTrcTokenToOther.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/contractUnknownException.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/create2CallContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/create2Istanbul.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/create2contract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/create2contract22.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/create2contractn.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/create2contractn2.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/demo.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/event001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/event002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/extCodeHash.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/extCodeHash11.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/extCodeHashConstruct.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/extCodeHashStress.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/extCodeHashTestNoPayable.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/isSRCandidate.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/mappingGetter.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/multiValiSignPerformance01.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/multiValiSignPerformance02.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/multivalidatesign.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/multivalidatesign001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/multivalidatesign002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/multivalidatesign003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/multivalidatesign005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/multivalidatesign007.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/multivalidatesign02.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/negativeArray.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/payable001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/pedersenHash001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/pedersenHash002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest1TestRequireContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest2TestThrowsContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest3TestRevertContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest4noPayableContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest4noPayableContract_1.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest5noPayableConstructor.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest5noPayableConstructor_1.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest6transferTestContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest7payableFallbakContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest8newContractGasNoenough.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest9MessageUsedErrorFeed.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/requireExceptiontestFunctionUsedErrorFeed.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/selector.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/stackContract001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/stackSuicide001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/stringSplit.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/suicide001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/suicide002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/testOutOfMem.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/testStakeSuicide.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/tryCatch001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/typeName.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/unStake001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/validatemultisign001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/verifyTransferProof001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.5.15/walletTestMutiSign004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/AssertException002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/AssignToExternal.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/BlockHash.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/ClearAbi001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/ClearAbi005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/ConstructorDefaults.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/Create2Test023.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/Create2Test024.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/Create2Test025.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/ExtCodeHashTest010.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/ExternalSelector.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/NewFeature068.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/ParentTypeBug.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/SafeMath.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/ShiftCommand001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/SolidityMappingFix.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TestMappings_array_pop.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TransferFailed001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TransferFailed005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TransferFailed006.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TransferFailed007.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TriggerConstant001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TriggerConstant002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TriggerConstant003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TriggerConstant004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TriggerConstant015.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TriggerConstant024.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TvmIsContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TvmIsContract001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TvmIsContract002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand043.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand103.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand107.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand108.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand109.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/TvmOldCommand001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/VerifyBurnProof001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/VerifyMintProof001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/abiencode.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/abstract001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/abstract002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/accountAssert.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/addMsg001Nonpayable.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/addMsg002View.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/addMsg003Constant.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/addMsg004Pure.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/addTransferToken001Nonpayable.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/addTransferToken001payable.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/addTransferToken002View.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/addTransferToken003Constant.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/addTransferToken004Pure.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/addTrcToken001Assemble.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/addTrcToken002Cat.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/addTrcToken002Cat_withFinny.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/addressCheckNew.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/addressCheckOld.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/altbn.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/arrayLength001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/assemblyTest.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest1DivideInt.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest2FindArgsContractMinTest.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest3ByteMinContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest4Enum.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest5MoveRight.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest6UninitializedContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest7TestAssertContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign007.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign02.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/callValueGasPure.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/calldata.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/callvalue.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/chainid001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/codeSaftySupport.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/codeSaftyUnsupport.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/constantCallStorage001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/constantCallStorage002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/constantCallStorage0425.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/constantContract001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGetterContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test1Grammar001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test2Grammar002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test3Grammar003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test4Grammar004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test5Grammar006.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test1Grammar007_1.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test1Grammar007_2.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test2Grammar008.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test3Grammar010.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test4Grammar011.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test4Grammar012.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test6Grammar013.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test1Grammar014.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test2Grammar015.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test3Grammar016.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test4Grammar017.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test5Grammar018.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test6Grammar019.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test7Grammar020.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInnerContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction006.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test1InternalTransaction007.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test2InternalTransaction008.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test3InternalTransaction009.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test4InternalTransaction010.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test4InternalTransaction010_1.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test5InternalTransaction012.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction013.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction014.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction015.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction016.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction017.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction018.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractLinkage001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractLinkage002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractLinkage003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractLinkage004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractLinkage005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractLinkage006.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractOriginEnergyLimit001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractOriginEnergyLimit004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractOtherToTrcToken.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractScenario001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractScenario002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractScenario003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractScenario004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractScenario005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractScenario006.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractScenario007.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractScenario008.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractScenario009.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractScenario010.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractScenario011.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractScenario012.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractScenario013.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractScenario014.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTest.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractToMathedFeed.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTransferToken001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken011.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken012.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken014.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken018.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken023.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken026.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken027.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken028.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken029.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken030.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken031.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken034.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken035.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_1.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_2.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_3.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_4.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_old.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken037.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken038.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken039.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken041.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken043.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken048.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken049.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken050.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken051.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken052.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken054.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken055.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken060.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken061.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken064.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken066.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken067.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken073.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken075.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken076.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken077.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken078.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken079.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcToken080.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractTrcTokenToOther.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/contractUnknownException.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/create2CallContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/create2Istanbul.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/create2contract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/create2contract22.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/create2contractn.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/create2contractn2.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/demo.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/enumAndStruct.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/event001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/event002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/extCodeHash.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/extCodeHash11.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/extCodeHashConstruct.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/extCodeHashStress.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/extCodeHashTestNoPayable.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/fallbackUpgrade.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/freezeContract001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/getAddressChange.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/isSRCandidate.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/mappingGetter.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/multiValiSignPerformance01.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/multiValiSignPerformance02.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/multivalidatesign.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/multivalidatesign001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/multivalidatesign002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/multivalidatesign003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/multivalidatesign005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/multivalidatesign007.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/multivalidatesign02.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/negativeArray.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/override002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/override003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/override004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/override005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/overridePrivateFunction.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/payable001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/pedersenHash001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/pedersenHash002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest1TestRequireContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest2TestThrowsContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest3TestRevertContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest4noPayableContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest4noPayableContract_1.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest5noPayableConstructor.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest5noPayableConstructor_1.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest6transferTestContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest7payableFallbakContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest8newContractGasNoenough.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest9MessageUsedErrorFeed.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/requireExceptiontestFunctionUsedErrorFeed.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/selector.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/stackContract001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/stackSuicide001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/stateVariableShadowing.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/stringSplit.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/suicide001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/suicide002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/testOutOfMem.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/testStakeSuicide.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/tryCatch001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/typeName.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/unStake001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/validatemultisign001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/verifyTransferProof001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/virtual001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.6.12/walletTestMutiSign004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/AssertException002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/AssignToExternal.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/BlockHash.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/ClearAbi001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/ClearAbi005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/ConstructorDefaults.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/Create2Test023.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/Create2Test024.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/Create2Test025.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/ExtCodeHashTest010.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/ExternalSelector.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/NewFeature068.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/NewFeature076.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/ParentTypeBug.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/SafeMath.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/ShiftCommand001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/SolidityMappingFix.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TestMappings_array_pop.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TransferFailed001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TransferFailed005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TransferFailed006.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TransferFailed007.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TriggerConstant001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TriggerConstant002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TriggerConstant003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TriggerConstant004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TriggerConstant015.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TriggerConstant024.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TvmIsContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TvmIsContract001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TvmIsContract002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand043.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand103.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand107.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand108.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand109.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/TvmOldCommand001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/VerifyBurnProof001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/VerifyMintProof001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/abiencode.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/abstract001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/abstract002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/accountAssert.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/addMsg001Nonpayable.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/addMsg002View.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/addMsg003Constant.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/addMsg004Pure.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/addTransferToken001Nonpayable.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/addTransferToken001payable.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/addTransferToken002View.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/addTransferToken003Constant.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/addTransferToken004Pure.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/addTrcToken001Assemble.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/addTrcToken002Cat.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/addTrcToken002Cat_withFinny.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/addressCheckNew.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/addressCheckOld.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/altbn.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/arrayLength001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/assemblyTest.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest1DivideInt.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest2FindArgsContractMinTest.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest3ByteMinContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest4Enum.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest5MoveRight.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest6UninitializedContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest7TestAssertContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign007.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign02.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/callValueGasPure.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/calldata.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/callvalue.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/chainid001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/codeSaftySupport.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/codeSaftyUnsupport.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/constantCallStorage001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/constantCallStorage002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/constantCallStorage0425.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/constantContract001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGetterContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test1Grammar001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test2Grammar002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test3Grammar003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test4Grammar004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test5Grammar006.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test1Grammar007_1.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test1Grammar007_2.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test2Grammar008.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test3Grammar010.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test4Grammar011.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test4Grammar012.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test6Grammar013.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test1Grammar014.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test2Grammar015.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test3Grammar016.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test4Grammar017.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test5Grammar018.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test6Grammar019.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test7Grammar020.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInnerContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction006.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test1InternalTransaction007.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test2InternalTransaction008.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test3InternalTransaction009.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test4InternalTransaction010.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test4InternalTransaction010_1.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test5InternalTransaction012.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction013.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction014.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction015.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction016.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction017.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction018.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractLinkage001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractLinkage002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractLinkage003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractLinkage004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractLinkage005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractLinkage006.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractOriginEnergyLimit001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractOriginEnergyLimit004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractOtherToTrcToken.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractScenario001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractScenario002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractScenario003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractScenario004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractScenario005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractScenario006.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractScenario007.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractScenario008.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractScenario009.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractScenario010.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractScenario011.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractScenario012.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractScenario013.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractScenario014.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTest.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractToMathedFeed.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTransferToken001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken011.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken012.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken014.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken018.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken023.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken026.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken027.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken028.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken029.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken030.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken031.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken034.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken035.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_1.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_2.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_3.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_4.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_old.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken037.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken038.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken039.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken041.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken043.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken048.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken049.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken050.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken051.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken052.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken054.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken055.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken060.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken061.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken064.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken066.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken067.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken073.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken075.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken076.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken077.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken078.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken079.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcToken080.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractTrcTokenToOther.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/contractUnknownException.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/create2CallContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/create2Istanbul.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/create2contract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/create2contract22.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/create2contractn.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/create2contractn2.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/demo.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/enumAndStruct.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/event001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/event002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/extCodeHash.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/extCodeHash11.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/extCodeHashConstruct.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/extCodeHashStress.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/extCodeHashTestNoPayable.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/fallbackUpgrade.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/freezeContract001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/getAddressChange.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/isSRCandidate.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/mappingGetter.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/multiValiSignPerformance01.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/multiValiSignPerformance02.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/multivalidatesign.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/multivalidatesign001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/multivalidatesign002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/multivalidatesign003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/multivalidatesign005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/multivalidatesign007.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/multivalidatesign02.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/negativeArray.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/override002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/override003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/override004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/override005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/overridePrivateFunction.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/payable001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/pedersenHash001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/pedersenHash002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest1TestRequireContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest2TestThrowsContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest3TestRevertContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest4noPayableContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest4noPayableContract_1.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest5noPayableConstructor.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest5noPayableConstructor_1.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest6transferTestContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest7payableFallbakContract.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest8newContractGasNoenough.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest9MessageUsedErrorFeed.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/requireExceptiontestFunctionUsedErrorFeed.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/selector.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/slotAndOffsetNewGrammer.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/stackContract001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/stackSuicide001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/stateVariableShadowing.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/stringSplit.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/suicide001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/suicide002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/testOutOfMem.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/testStakeSuicide.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/tryCatch001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue002.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue003.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue004.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue005.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/typeName.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/unStake001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/validatemultisign001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/verifyTransferProof001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/virtual001.sol delete mode 100644 framework/src/test/resources/soliditycode_0.7.6/walletTestMutiSign004.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/TransferFailed001.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/TransferFailed005.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/TransferFailed007.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/addMsg001Nonpayable.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/addMsg002View.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/addMsg003Constant.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/addMsg004Pure.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/addTransferToken001Nonpayable.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/addTransferToken002View.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/addTransferToken003Constant.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/addTransferToken004Pure.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/addTrcToken001Assemble.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/addTrcToken002Cat.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/addTrcToken002Cat_withFinny.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest1DivideInt.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest2FindArgsContractMinTest.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest3ByteMinContract.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest4Enum.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest5MoveRight.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest6UninitializedContract.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest7TestAssertContract.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/codeSaftySupport.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/codeSaftyUnsupport.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGetterContract.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test1Grammar001.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test2Grammar002.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test3Grammar003.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test4Grammar004.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test5Grammar006.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test1Grammar007_1.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test1Grammar007_2.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test2Grammar008.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test3Grammar010.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test4Grammar011.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test4Grammar012.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test6Grammar013.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test1Grammar014.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test2Grammar015.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test3Grammar016.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test4Grammar017.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test5Grammar018.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test6Grammar019.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test7Grammar020.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractInnerContract.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction001.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction002.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction003.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction004.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction005.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction006.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test1InternalTransaction007.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test2InternalTransaction008.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test3InternalTransaction009.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test4InternalTransaction010.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test5InternalTransaction012.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction013.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction014.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction015.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction016.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction017.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction018.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractLinkage001.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractLinkage002.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractLinkage003.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractLinkage004.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractLinkage005.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractLinkage006.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractOriginEnergyLimit001.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractOriginEnergyLimit004.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractOtherToTrcToken.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractScenario001.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractScenario002.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractScenario003.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractScenario004.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractScenario005.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractScenario006.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractScenario007.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractScenario008.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractScenario009.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractScenario010.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractScenario011.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractScenario012.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractScenario013.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractScenario014.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTest.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractToMathedFeed.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken001.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken002.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken003.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken005.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken011.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken012.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken014.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken018.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken023.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken026.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken027.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken028.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken029.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken030.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken031.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken034.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken035.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken036.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken037.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken038.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken039.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken041.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken043.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken048.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken049.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken050.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken051.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken052.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken054.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken055.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken060.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken061.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken064.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken066.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken067.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken073.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken075.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken076.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken077.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken078.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken079.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken080.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractTrcTokenToOther.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/contractUnknownException.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest1TestRequireContract.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest2TestThrowsContract.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest3TestRevertContract.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest4noPayableContract.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest5noPayableConstructor.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest6transferTestContract.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest7payableFallbakContract.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest8newContractGasNoenough.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest9MessageUsedErrorFeed.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontestFunctionUsedErrorFeed.sol delete mode 100644 framework/src/test/resources/soliditycode_v0.4.25/walletTestMutiSign004.sol delete mode 100644 framework/src/test/resources/testng.xml diff --git a/framework/src/test/resources/daily-build.xml b/framework/src/test/resources/daily-build.xml deleted file mode 100644 index 4120973c34a..00000000000 --- a/framework/src/test/resources/daily-build.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/framework/src/test/resources/solcDir/README.txt b/framework/src/test/resources/solcDir/README.txt deleted file mode 100644 index f390cc49698..00000000000 --- a/framework/src/test/resources/solcDir/README.txt +++ /dev/null @@ -1 +0,0 @@ -to storage solidity compiler \ No newline at end of file diff --git a/framework/src/test/resources/solidityFile.xml b/framework/src/test/resources/solidityFile.xml deleted file mode 100644 index 6082ba41ccd..00000000000 --- a/framework/src/test/resources/solidityFile.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/AssertException002.sol b/framework/src/test/resources/soliditycode/AssertException002.sol deleted file mode 100644 index 15cc07ff984..00000000000 --- a/framework/src/test/resources/soliditycode/AssertException002.sol +++ /dev/null @@ -1,17 +0,0 @@ - - -contract AssertException{ - function divideIHaveArgsReturn(int x,int y) public returns (int z) { - return x / y; - } - function testAssert() public { - require(2==1); - } -} -contract C { - constructor() public payable { - assert(1==2); - } - function fun() public { - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/AssignToExternal.sol b/framework/src/test/resources/soliditycode/AssignToExternal.sol deleted file mode 100644 index d4f09590a36..00000000000 --- a/framework/src/test/resources/soliditycode/AssignToExternal.sol +++ /dev/null @@ -1,30 +0,0 @@ -contract AssignToExternal { - // Not allow: - // function f(uint256[] calldata x, uint256[] calldata y) external pure { - // x = y; - // } - - // allow: - - function f(uint256 a) external returns (uint){ - a = a + 1; - return a; - } - - function StringSet(string calldata a) external returns (string memory){ - return a; - } - - function ByteSet(bytes32 a) external returns (bytes32){ - return a; - } - - function UintArraySet(uint256[2] calldata a) external returns (uint256[2] memory){ - return a; - } - - function AddSet(address a) external returns (address){ - return a; - } - -} diff --git a/framework/src/test/resources/soliditycode/BlockHash.sol b/framework/src/test/resources/soliditycode/BlockHash.sol deleted file mode 100644 index 6603da65e44..00000000000 --- a/framework/src/test/resources/soliditycode/BlockHash.sol +++ /dev/null @@ -1,38 +0,0 @@ -contract TestBlockHash { - - function testOR1(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = blockhash(block.number - 1) | bytes32(value); - return (b1, c, blockhash(block.number - 1)); - } - - function testOR2(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = bytes32(value) | blockhash(block.number - 1); - return (b1, c, blockhash(block.number - 1)); - } - - function testAND1(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = blockhash(block.number - 1) & bytes32(value); - return (b1, c, blockhash(block.number - 1)); - } - - function testAND2(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = bytes32(value) & blockhash(block.number - 1); - return (b1, c, blockhash(block.number - 1)); - } - - function testXOR1(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = blockhash(block.number - 1) ^ bytes32(value); - return (b1, c, blockhash(block.number - 1)); - } - - function testXOR2(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = bytes32(value) ^ blockhash(block.number - 1); - return (b1, c, blockhash(block.number - 1)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/ClearAbi001.sol b/framework/src/test/resources/soliditycode/ClearAbi001.sol deleted file mode 100644 index 39a8e8cf005..00000000000 --- a/framework/src/test/resources/soliditycode/ClearAbi001.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract testConstantContract{ -function testPayable() public view returns (int z) { -return 1; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/ClearAbi005.sol b/framework/src/test/resources/soliditycode/ClearAbi005.sol deleted file mode 100644 index a3115398386..00000000000 --- a/framework/src/test/resources/soliditycode/ClearAbi005.sol +++ /dev/null @@ -1,26 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract TestConstract { - uint public i=0; - constructor () public { - } - function plusOne() public returns(uint){ - i++; - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/ConstructorDefaults.sol b/framework/src/test/resources/soliditycode/ConstructorDefaults.sol deleted file mode 100644 index 4b6186ccb95..00000000000 --- a/framework/src/test/resources/soliditycode/ConstructorDefaults.sol +++ /dev/null @@ -1,9 +0,0 @@ -contract testIsContract{ - bool result; - constructor (bool a) public { - result = a; - } -function test( address a) public returns (bool) { -return result; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/Create2Test023.sol b/framework/src/test/resources/soliditycode/Create2Test023.sol deleted file mode 100644 index ef022a8e83d..00000000000 --- a/framework/src/test/resources/soliditycode/Create2Test023.sol +++ /dev/null @@ -1,31 +0,0 @@ -contract factory { - constructor() payable public { - } - - function deploy(bytes memory code, uint256 salt) public returns(address){ - Caller addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - return address(addr); - } - - function testCreate() payable public returns (address){ - Caller add = (new Caller){value:0}(); - return address(add); - } - - function kill( ) payable public{ - selfdestruct(payable(msg.sender)); - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/Create2Test024.sol b/framework/src/test/resources/soliditycode/Create2Test024.sol deleted file mode 100644 index 5d43c0f4ab2..00000000000 --- a/framework/src/test/resources/soliditycode/Create2Test024.sol +++ /dev/null @@ -1,56 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - TestConstract addr; - TestConstract addr1; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - - addr.testSuicideNonexistentTarget(payable(msg.sender)); - addr.set(); - emit Deployed(address(addr), salt, msg.sender); - return address(addr); - } - - function deploy2(bytes memory code, uint256 salt) public returns(address){ - TestConstract addr; - TestConstract addr1; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - - //addr.testSuicideNonexistentTarget(msg.sender); - //addr.set(); - - assembly { - addr1 := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr1)) { - revert(0, 0) - } - } - emit Deployed(address(addr), salt, msg.sender); - return address(addr); - } -} - - - -contract TestConstract { - uint public i=1; - constructor () public { - } - - function set() public{ - i=9; - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/Create2Test025.sol b/framework/src/test/resources/soliditycode/Create2Test025.sol deleted file mode 100644 index 895dc43e56f..00000000000 --- a/framework/src/test/resources/soliditycode/Create2Test025.sol +++ /dev/null @@ -1,34 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - constructor() public { - } - - function create2(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } - - function get(bytes1 prefix, bytes calldata code, uint256 salt) external view returns(address) { - //bytes32 hash = keccak256(abi.encodePacked(bytes1(0x41),address(this), salt, keccak256(code))); - bytes32 hash = keccak256(abi.encodePacked(prefix,address(this), salt, keccak256(code))); - address addr = address(uint160(uint256(hash))); - return addr; - } -} - -contract TestContract{ - uint256 public num; - constructor(uint256 j) public{ - num = j; - } - function getNum() public returns (uint256){ - return num; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/EthGrammer.sol b/framework/src/test/resources/soliditycode/EthGrammer.sol deleted file mode 100644 index 1be4d2d0881..00000000000 --- a/framework/src/test/resources/soliditycode/EthGrammer.sol +++ /dev/null @@ -1,191 +0,0 @@ -contract C { - constructor() public payable{} - - function baseFee() external view returns (uint ret) { - assembly { - ret := basefee() - } - assert(block.basefee == ret); - } - - function baseFeeOnly() external view returns (uint ret) { - assembly { - ret := basefee() - } - } - - function gasPrice() external view returns (uint ret) { - assembly { - ret := basefee() - } - assert(tx.gasprice == ret); - } - - function gasPriceOnly() external view returns (uint) { - return tx.gasprice; - } - - function testCall(address payable caller, address payable transferTo) public { - (bool success, bytes memory data) = caller.call(abi.encodeWithSignature("transfer(address)",transferTo)); - require(success); - } - - function testDelegateCall(address payable caller, address payable transferTo) public { - (bool success, bytes memory data) = caller.delegatecall(abi.encodeWithSignature("transfer(address)",transferTo)); - require(success); - } - - uint sum = 0; - function transfer(address payable transerTo) public { - for (uint i = 0; i < type(uint256).max; i++) - sum = 0; - for (uint j = 0; j < type(uint8).max; j++) - sum += j; - transerTo.transfer(1); - } - - function testCallFunctionInContract(address payable transferTo) public { - this.transfer(transferTo); - } - - - function getRipemd160(string memory input) public returns(bytes32 output) { - bytes memory tem = bytes(input); - assembly { - if iszero(staticcall(not(0), 0x020003, add(tem, 0x20), mload(tem), output, 0x20)) { - revert(0, 0) - } - output := mload(add(output,0x0c)) - } - } - - function getRipemd160Str(string memory input) public view returns(bytes32 output) { - assembly { - if iszero(staticcall(not(0), 0x020003, add(input, 0x20), mload(input), output, 0x20)) { - revert(0, 0) - } - output := mload(add(output,0x0c)) - } - - } - - function F(uint32 rounds, bytes32[2] memory h, bytes32[4] memory m, bytes8[2] memory t, bool f) public view returns (bytes32[2] memory) { - bytes32[2] memory output; - - bytes memory args = abi.encodePacked(rounds, h[0], h[1], m[0], m[1], m[2], m[3], t[0], t[1], f); - - assembly { - if iszero(staticcall(not(0), 0x020009, add(args, 32), 0xd5, output, 0x40)) { - revert(0, 0) - } - } - - return output; - } - - function callF() public view returns (bytes32[2] memory) { - uint32 rounds = 12; - - bytes32[2] memory h; - h[0] = hex"48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5"; - h[1] = hex"d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b"; - - bytes32[4] memory m; - m[0] = hex"6162630000000000000000000000000000000000000000000000000000000000"; - m[1] = hex"0000000000000000000000000000000000000000000000000000000000000000"; - m[2] = hex"0000000000000000000000000000000000000000000000000000000000000000"; - m[3] = hex"0000000000000000000000000000000000000000000000000000000000000000"; - - bytes8[2] memory t; - t[0] = hex"03000000"; - t[1] = hex"00000000"; - - bool f = true; - - // Expected output: - // ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1 - // 7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923 - return F(rounds, h, m, t, f); - } - - -} - -contract D { - constructor() public payable{} - - function deploy(uint256 salt) public returns(address){ - address addr; - bytes memory code = type(C).creationCode; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - } - return addr; - } - - uint sum = 0; - function transfer(address payable transerTo) public { - for (uint i = 0; i < type(uint256).max; i++) - sum = 0; - for (uint j = 0; j < type(uint8).max; j++) - sum += j; - transerTo.transfer(1); - } - - function callCreate2(uint256 salt) public returns(address){ - address addr; - bytes memory code = type(C).creationCode; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - } - return addr; - } - - function fixCreate2StackDepth(uint salt) public { - if (isEmptyAddress(callCreate2(salt + 1))) { - revert(); - } - this.fixCreate2StackDepth(salt + 1); - } - - function callCreate() public returns(address){ - address addr; - bytes memory code = type(C).creationCode; - assembly { - addr := create(0, add(code, 0x20), mload(code)) - } - return addr; - } - - function fixCreateStackDepth() public { - if (isEmptyAddress(callCreate())) { - revert(); - } - this.fixCreateStackDepth(); - } - - bool constant bool1 = true; - function isEmptyAddress(address add2) public returns(bool result){ - - assembly { - if iszero(extcodesize(add2)) { - result := bool1 - } - } - } - - function deployef(bytes memory code) public payable{ - address addr; - assembly { - addr := create(0, add(code, 0x20), mload(code)) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - } -} - - - - - diff --git a/framework/src/test/resources/soliditycode/EthGrammer02.sol b/framework/src/test/resources/soliditycode/EthGrammer02.sol deleted file mode 100644 index d032b531fa6..00000000000 --- a/framework/src/test/resources/soliditycode/EthGrammer02.sol +++ /dev/null @@ -1,45 +0,0 @@ -contract D { - constructor() public payable{} - - event createAddress(address addr); - function createDeployEf(bytes memory code) public returns(address addr){ - address addr; - assembly { - addr := create(0, add(code, 0x20), mload(code)) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - return addr; - } - - function create2DeployEf(bytes memory code,uint256 salt) public returns(address addr){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit createAddress(addr); - return addr; - } - - function setSlot(bytes memory slot,uint256 value) external { -// uint256 value = 123; - assembly { - sstore(slot, value) - } - } - - function getSlot(bytes memory slot) view external returns(uint res) { - assembly { - res := sload(slot) - } - } -} - - - - - diff --git a/framework/src/test/resources/soliditycode/ExtCodeHashTest010.sol b/framework/src/test/resources/soliditycode/ExtCodeHashTest010.sol deleted file mode 100644 index e54c302addb..00000000000 --- a/framework/src/test/resources/soliditycode/ExtCodeHashTest010.sol +++ /dev/null @@ -1,46 +0,0 @@ -contract Counter { - uint count = 0; - address payable owner; - event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); - constructor() public{ - owner = payable(msg.sender); - } - function getCodeHashSuicide(address addr) public returns (bytes32 _hashBefore){ - assembly{ - _hashBefore := extcodehash(addr) - } - selfdestruct(owner); - return _hashBefore; - } - - function getCodeHashRevert() public returns (bytes32 _hashBefore, bytes32 _hashAfter) { - address addr = address(this); - assembly { - _hashBefore := extcodehash(addr) - } - if (owner == msg.sender) { - selfdestruct(owner); - } - assembly { - _hashAfter := extcodehash(addr) - } - revert(); - emit LogResult(_hashBefore, _hashAfter); - } - - function getCodeHashCreate() public returns (bytes32 _hashBefore){ - TestContract A = (new TestContract){value:0}(); - address addr = address(A); - assembly{ - _hashBefore := extcodehash(addr) - } - revert(); - return _hashBefore; - } -} - -contract TestContract{ - uint256 count = 1; - constructor() public payable{ - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/ExternalSelector.sol b/framework/src/test/resources/soliditycode/ExternalSelector.sol deleted file mode 100644 index 01fddac9e2e..00000000000 --- a/framework/src/test/resources/soliditycode/ExternalSelector.sol +++ /dev/null @@ -1,92 +0,0 @@ -//pragma solidity ^0.6.0; - -contract selectorContract { - function testSelectorNoParam() external pure returns(uint) { - return 11; - } - - function testSelectorWithParam(uint x) external pure returns(uint) { - return 22; - } -} - -interface interfaceSelector { - function getSelector() external pure returns(uint); -} - -interface B is interfaceSelector { - // interface现在可以继承自其他interface - function testImplemention() external pure returns(uint); -} - -contract implementContract is B{ - function getSelector() external override pure returns(uint) { - return 66; - } - - function testImplemention() external override pure returns(uint) { - return 77; - } - - constructor() public payable {} -} - -contract basicContract{ - function testNewUse() external payable returns(uint) { - return 345; - } - - constructor() public payable {} -} - -contract TestGasValue{ - constructor() public payable {} - - function testNewUse() external payable returns(uint) { - return 123; - } - basicContract bc = new basicContract(); - // external方法在调用时可以采用c.f{gas: 10000, value: 4 trx}()的形式 - function callWithGasAndValue(uint x,uint y) external returns(uint) { - return bc.testNewUse{gas:x, value:y}(); - } - - function callThisNoGasAnd1Value() external returns(uint) { - return this.testNewUse{gas:0, value:1}(); - } - - // inline assembly中允许true和false字面量 - function testAssemblyTrue() public pure returns(uint x) { - assembly { - x := true - } - } - - // inline assembly中允许true和false字面量 - function testAssemblyFalse() public pure returns(uint x) { - assembly { - x := false - } - } - - // create2的high-level用法new C{salt: 0x1234, value: 1 ether}(arg1, arg2) - function testCreate2() public returns(address) { - basicContract c = new basicContract{salt: bytes32(bytes1(0x01)), value: 1 trx}(); - return address(c); - } - - - function getContractSelectorNoParam() public pure returns(bytes4) { - return selectorContract.testSelectorNoParam.selector; - } - - function getContractSelectorWithParam() public pure returns(bytes4) { - return selectorContract.testSelectorWithParam.selector; - } - - function getInterfaceSelectorNoParam() public pure returns(bytes4) { - return interfaceSelector.getSelector.selector; - } - -} - diff --git a/framework/src/test/resources/soliditycode/NewFeature068.sol b/framework/src/test/resources/soliditycode/NewFeature068.sol deleted file mode 100644 index 8bfe805450c..00000000000 --- a/framework/src/test/resources/soliditycode/NewFeature068.sol +++ /dev/null @@ -1,131 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -//pragma solidity ^0.6.8; - -abstract contract testModifier { - modifier isOwner() virtual; -} - -abstract contract testInterfaceId { - function getValue() external view virtual returns(uint); - function getOwner() external view virtual returns(uint); - -} - -interface a { - function getValue() external view returns(uint); - function getOwner() external view returns(uint); -} - -contract testMapKey is testModifier{ - - enum size{ - SMALL, - LARGE - } - - mapping(size => uint) public enums; - - mapping(testMapKey => uint) public contracts; - - function setEnumValue(uint value) public { - enums[size.SMALL] = value; - } - - function getEnumValue() public view returns(uint) { - return enums[size.SMALL]; - } - - function setContractValue() public { - contracts[this] = 2; - } - - function getContractValue() public view returns(uint) { - return contracts[this]; - } - - bytes4 constant functionSelector = this.getEnumValue.selector; - - function getfunctionSelector() public pure returns(bytes4) { - return functionSelector; - } - - uint immutable x; - address immutable owner = msg.sender; - - constructor() public { - x = 5; - } - - string b = "test"; - - function testStorage() public view returns(string memory) { - string storage aa; - aa = b; - return aa; - - } - - function getImmutableVal() public view returns(uint) { - return x; - } - - function getOwner() public view returns(address) { - return owner; - } - - function getInterfaceId() public pure returns(bytes4,bytes4) { - return (type(a).interfaceId, type(testInterfaceId).interfaceId); - } - - modifier isOwner() override { - require(msg.sender == owner); - _; - } - - function requireOwner() public view isOwner returns(uint) { - return 6; - } - - - function getUint256MinAndMax() public pure returns(uint, uint) { - return (type(uint).min, type(uint).max); - } - - - function getUint8MinAndMax() public pure returns(uint8, uint8) { - return (type(uint8).min, type(uint8).max); - } - - function calldataModifier(bytes calldata a) external returns(bytes calldata) { - bytes calldata b = a; - return b; - } - -} - - -abstract contract base { - function abstractfun() virtual public returns(uint); -} - -abstract contract callEmptyFunction is base { - function callfun() public returns(uint) { - return abstractfun(); - } -} - - - - - - - - - - - - - - - - diff --git a/framework/src/test/resources/soliditycode/NewFeature076.sol b/framework/src/test/resources/soliditycode/NewFeature076.sol deleted file mode 100644 index 3191acb8f1d..00000000000 --- a/framework/src/test/resources/soliditycode/NewFeature076.sol +++ /dev/null @@ -1,21 +0,0 @@ -function a() returns (uint) { - return 1; -} -abstract contract abvd { - -} -interface qwer { - function getValue() external view returns(uint); - function getOwner() external view returns(uint); -} -contract C { - function getOutsideMethod() external returns (uint) { - return a(); - } - function getAbstractName() public returns(string memory) { - return type(abvd).name; - } - function getInterfaceName() public returns(string memory) { - return type(qwer).name; - } -} diff --git a/framework/src/test/resources/soliditycode/NewFeature080.sol b/framework/src/test/resources/soliditycode/NewFeature080.sol deleted file mode 100644 index 7422e8d34b4..00000000000 --- a/framework/src/test/resources/soliditycode/NewFeature080.sol +++ /dev/null @@ -1,109 +0,0 @@ -contract C { - constructor() public payable{} - - function subNoUncheck() public pure returns (uint) { - uint8 x = 0; - return x--; - } - - function subWithUncheck() public pure returns (uint) { - uint8 x = 0; - unchecked { x--; } - return x; - } - - function addNoUncheck() public pure returns (uint) { - uint8 x = 255; - return x++; - } - - function divideZeroNoUncheck() public pure returns (uint) { - uint8 x = 0; - uint8 y = 1; - return y/x; - } - - function assertFailNoUncheck() public pure { - assert(1==2); - } - - int64[] b = [-1, 2, -3]; - function arrayOutofIndex() public view returns (int) { - return b[3]; - } - - function typeConvert() public pure returns(uint16) { - // return uint16(int8(-1)); //0.8.0报错 之前不报错 - return uint16(int16(int8(-1))); //0xffff - // return uint16(uint8(int8(-1))); // 0xff - } - - function powerMultiRightToLeft() public pure returns(uint) { - return 2**1**2**3; - } - - function powerMultiLeftToRight() public pure returns(uint) { - return ((2**1)**2)**3; - } - - function powerMultiWith2Params() public pure returns(uint) { - return 2**3; - } - //log 0,1,2,3 disallowed in solidity v0.8.0 -// function f2() public payable { -// uint256 x=1; -// uint256 y=2; -// uint256 z=3; -// bytes32 _id = bytes32(x); -// log3( -// bytes32(x), -// bytes32(y), -// bytes32(z), -// _id -// ); -// } - - - function getBlockChainId111111() view public returns(uint256) { - return block.chainid; - } - - - function getBlockChainId() view public returns(uint256) { - uint256 id; - assembly { - id := chainid() - } - assert(block.chainid == id); - return block.chainid; - } - function getAddressCodehash(address addr) view public returns(bytes32 newHash) { - bytes32 _hashBefore; - assembly{ - _hashBefore := extcodehash(addr) - } - bytes32 newHash = addr.codehash; - assert(_hashBefore == newHash); - return newHash; - } - - function transferToTxorigin(uint64 value) payable public { - payable(tx.origin).transfer(value); - } - -// msg.data was removed in receive() function -// event FallbackCalled(bytes data); -// receive() external payable { -// -// emit FallbackCalled(msg.data); -// } - - function transferToLiteralAddress(uint64 value) public{ - uint160 num = type(uint160).max-3; - address add = address(num); - payable(add).transfer(value); - } -} - - - diff --git a/framework/src/test/resources/soliditycode/NewFeature0811.sol b/framework/src/test/resources/soliditycode/NewFeature0811.sol deleted file mode 100644 index bb7cb1ab567..00000000000 --- a/framework/src/test/resources/soliditycode/NewFeature0811.sol +++ /dev/null @@ -1,101 +0,0 @@ - -type TestInt128 is int128; -pragma abicoder v2; -interface I { -function foo() external; -} - -contract C is I { -uint8 immutable i; -uint8 x; - -constructor() { -i = 33; -x = readI(); -} - -function readX() public view returns (uint8) { -return x; -} - -function readI() public view returns (uint8) { -return i; -} - - - - -function fExternal(uint256 p, string memory t) external {} - -function fSignatureFromLiteralCall() public view returns (bytes memory) { -return abi.encodeCall(this.fExternal, (1, "123")); -} - - - - - -enum FreshJuiceSize{ SMALL, MEDIUM, LARGE, FINAL } - - -TestInt128 a = TestInt128.wrap(45); -function getUserDefinedValue() public view returns(TestInt128) { -return a; -} - - - - -function foo() external { // Does not compile without override -} - -function getEnumMin() public view returns (FreshJuiceSize) { -return type(FreshJuiceSize).min; - -} - - -function getEnumMax() public view returns (FreshJuiceSize) { -return type(FreshJuiceSize).max; - -} - - -function testFunction() external {} - -function testYul1() public view returns (address adr) { -function() external fp = this.testFunction; - -assembly { -adr := fp.address -} -} -function testGetAddress() public view returns (address) { -return this.testFunction.address; -} -function testYul2() public view returns (uint32) { -function() external fp = this.testFunction; -uint selectorValue = 0; - -assembly { -selectorValue := fp.selector -} - -// Value is right-aligned, we shift it so it can be compared -return uint32(bytes4(bytes32(selectorValue << (256 - 32)))); -} -function testGetSelector() public view returns (uint32) { -return uint32(this.testFunction.selector); -} - - - -int8 immutable bugValue = -4; -function fixBugTest() public view returns (bytes32 r) { -int8 y = bugValue; -assembly { r := y } -} - - - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/NewFeature086.sol b/framework/src/test/resources/soliditycode/NewFeature086.sol deleted file mode 100644 index f898fadde3e..00000000000 --- a/framework/src/test/resources/soliditycode/NewFeature086.sol +++ /dev/null @@ -1,121 +0,0 @@ -contract C { - constructor() public payable{} - - function catchAssertFail() external view returns(uint) { - try this.assertFail() { - return 0; - } catch Panic(uint _code) { - if (_code == 0x01) { - return 0x01; - } - return 2; - } - return 3; - } - function assertFail() external pure { - assert(0 == 1); - } - function catchUnderFlow() external view returns(uint) { - try this.underflow() { - return 44; - } catch Panic(uint _code) { - if (_code == 0x11) { - return 0x11; - } - return 22; - } - return 33; - } - function underflow() public pure { - uint x = 0; - x--; - } - - function catchDivideZero() external view returns(uint) { - try this.divideZero() { - return 14; - } catch Panic(uint _code) { - if (_code == 0x12) { - return 0x12; - } - return 11; - } - return 13; - } - function divideZero() public pure { - uint8 x = 0; - uint8 y = 1; - uint8 z = y/x; - } - - function convertUint2Int() public pure { - uint16 a = 1; -// int32 b = int32(a); -// int32 b = a; - } - - function getAddressCodeLength() public returns(uint) { - return address(this).code.length; - } - - function keccak256Bug(string memory s) public returns (bool ret) { - assembly { - let a := keccak256(s, 32) - let b := keccak256(s, 8) - ret := eq(a, b) - } - } - - error InsufficientBalance(uint256 available, uint256 required); - mapping(address => uint) balance; - function transfer(address to, uint256 amount) public { - if (amount > balance[msg.sender]) - revert InsufficientBalance({available: balance[msg.sender], required: amount}); - balance[msg.sender] -= amount; - balance[to] += amount; - } - - error Unauthorized(); - function withdraw() public { - address payable owner; - if (msg.sender != owner) - revert Unauthorized(); - owner.transfer(address(this).balance); - } - - bytes s = "Storage"; - function bytesConcat(bytes calldata c, string memory m, bytes16 b) public view returns(uint256) { - bytes memory a = bytes.concat(s, c, c[:2], "Literal", bytes(m), b); - assert((s.length + c.length + 2 + 7 + bytes(m).length + 16) == a.length); - return a.length; - } - - bytes p = "hihello"; - function bytesConcatWithEmptyStr() public view { - bytes memory a = bytes.concat("hi", "", "hello"); - assert(p.length == a.length); - } - - event ssoo(uint256); - function testEmitEvent() public payable { - emit ssoo(6); - } - - function bytes2BytesN(bytes memory c) public returns (bytes8) { - // If c is longer than 8 bytes, truncation happens - return bytes3(c); - } - - function getContractAddress() public view returns (address a1, address a2) { - a1 = address(this); - this.getContractAddress.address; - [this.getContractAddress.address][0]; - a2 = [this.getContractAddress.address][0]; - } - -} - - - - - diff --git a/framework/src/test/resources/soliditycode/NoAbi001.sol b/framework/src/test/resources/soliditycode/NoAbi001.sol deleted file mode 100644 index 8f919cbb153..00000000000 --- a/framework/src/test/resources/soliditycode/NoAbi001.sol +++ /dev/null @@ -1,10 +0,0 @@ -contract testNoABiContract{ - uint public i = 2; - event trigger(uint256 i, address sender); - - function testTrigger() public returns (uint) { - i++; - emit trigger(i, msg.sender); - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/NoAbi002.sol b/framework/src/test/resources/soliditycode/NoAbi002.sol deleted file mode 100644 index 0bb30e78443..00000000000 --- a/framework/src/test/resources/soliditycode/NoAbi002.sol +++ /dev/null @@ -1,29 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract testNoABiContract { - uint public i=0; - event trigger(uint256 i, address sender); - - constructor () public {} - - function plusOne() public returns(uint){ - i++; - emit trigger(i, msg.sender); - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/ParentTypeBug.sol b/framework/src/test/resources/soliditycode/ParentTypeBug.sol deleted file mode 100644 index 897c843ae24..00000000000 --- a/framework/src/test/resources/soliditycode/ParentTypeBug.sol +++ /dev/null @@ -1,13 +0,0 @@ -contract Parent { - uint256 public m_aMember; - address public m_bMember; -} -contract Child is Parent { - function foo() public view returns (uint256) { return Parent.m_aMember; } - function bar() public view returns (address) { return Parent.m_bMember; } - - // complie failed - // function foo() public pure returns (uint256) { return Parent.m_aMember; } - // function bar() public pure returns (address) { return Parent.m_bMember; } - -} diff --git a/framework/src/test/resources/soliditycode/SafeMath.sol b/framework/src/test/resources/soliditycode/SafeMath.sol deleted file mode 100644 index 1a7f1be2b8e..00000000000 --- a/framework/src/test/resources/soliditycode/SafeMath.sol +++ /dev/null @@ -1,149 +0,0 @@ - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/ShiftCommand001.sol b/framework/src/test/resources/soliditycode/ShiftCommand001.sol deleted file mode 100644 index 574ee2b571b..00000000000 --- a/framework/src/test/resources/soliditycode/ShiftCommand001.sol +++ /dev/null @@ -1,18 +0,0 @@ -contract TestBitwiseShift { - - function shlTest(uint256 num, uint256 input) public returns (bytes32 out) { - assembly { - out := shl(num, input) - } - } - function shrTest(uint256 num, uint256 input) public returns (bytes32 out) { - assembly { - out := shr(num, input) - } - } - function sarTest(uint256 num, uint256 input) public returns (bytes32 out) { - assembly { - out := sar(num, input) - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/SolidityMappingFix.sol b/framework/src/test/resources/soliditycode/SolidityMappingFix.sol deleted file mode 100644 index 98f9752e4b3..00000000000 --- a/framework/src/test/resources/soliditycode/SolidityMappingFix.sol +++ /dev/null @@ -1,9 +0,0 @@ -//pragma experimental ABIEncoderV2; -contract Tests { - mapping(address => uint) public balances; - function update(uint256 amount) public returns (address addr) - { - balances[msg.sender] = amount; - return msg.sender; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/TestMappings_array_pop.sol b/framework/src/test/resources/soliditycode/TestMappings_array_pop.sol deleted file mode 100644 index 0d5c4bb7013..00000000000 --- a/framework/src/test/resources/soliditycode/TestMappings_array_pop.sol +++ /dev/null @@ -1,19 +0,0 @@ -contract C { - mapping (uint256 => uint256)[] a; - - function n1(uint256 key, uint256 value) public { - a.push(); - a[a.length - 1][key] = value; - } - - - - function map(uint256 key) public view returns (uint) { - return a[a.length - 1][key]; - } - - function p() public { - a.pop(); - } -} - diff --git a/framework/src/test/resources/soliditycode/TransferFailed001.sol b/framework/src/test/resources/soliditycode/TransferFailed001.sol deleted file mode 100644 index 538a07fdf5c..00000000000 --- a/framework/src/test/resources/soliditycode/TransferFailed001.sol +++ /dev/null @@ -1,147 +0,0 @@ -contract EnergyOfTransferFailedTest { - constructor() payable public { - - } - - function testTransferTokenCompiledLongMax() payable public{ - payable(address(0x1)).transferToken(1,9223372036855775827); - } - - function testTransferTokenCompiled() payable public{ - payable(address(0x1)).transferToken(1,1); - } - - function testTransferTokenCompiledLongMin() payable public{ - //address(0x1).transferToken(1,-9223372036855775828); - } - - function testTransferTokenCompiledLongMin1() payable public returns(uint256){ - return address(0x2).tokenBalance(trcToken(uint256(int256(-9223372036855775828)))); - } - - function testTransferTokenCompiled1() payable public returns(uint256){ - return address(0x1).tokenBalance(trcToken(1)); - } - - function testTransferTokenCompiledLongMax1() payable public returns(uint256){ - return address(0x2).tokenBalance(trcToken(9223372036855775827)); - } - - function testTransferTokenCompiledTokenId(uint256 tokenid) payable public returns(uint256){ - return address(0x1).tokenBalance(trcToken(tokenid)); - } - - function testTransferTokenTest(address addr ,uint256 tokenid) payable public returns(uint256){ - return addr.tokenBalance(trcToken(tokenid)); - } - - // InsufficientBalance - function testTransferTrxInsufficientBalance(uint256 i) payable public{ - payable(msg.sender).transfer(i); - } - - function testSendTrxInsufficientBalance(uint256 i) payable public{ - payable(msg.sender).send(i); - } - - function testTransferTokenInsufficientBalance(uint256 i,trcToken tokenId) payable public{ - payable(msg.sender).transferToken(i, tokenId); - } - - function testCallTrxInsufficientBalance(uint256 i,address payable caller) public { - caller.call{value:i}(abi.encodeWithSignature("test()")); - } - - function testCreateTrxInsufficientBalance(uint256 i) payable public { - (new Caller){value:i}(); - } - - // NonexistentTarget - - function testSendTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - nonexistentTarget.send(i); - } - - function testSendTrxRevert(uint256 i,address payable nonexistentTarget) payable public { - nonexistentTarget.send(i); - revert(); - } - - function testTransferTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - nonexistentTarget.transfer(i); - } - - function testTransferTrxrevert(uint256 i,address payable nonexistentTarget) payable public{ - nonexistentTarget.transfer(i); - revert(); - } - - function testTransferTokenNonexistentTarget(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - nonexistentTarget.transferToken(i, tokenId); - } - - function testTransferTokenRevert(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - nonexistentTarget.transferToken(i, tokenId); - revert(); - } - - function testCallTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - nonexistentTarget.call{value:i}(abi.encodeWithSignature("test()")); - } - - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } - - function testSuicideRevert(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - revert(); - } - - // target is self - function testTransferTrxSelf(uint256 i) payable public{ - address payable self = payable(address(uint160(address(this)))); - self.transfer(i); - } - - function testSendTrxSelf(uint256 i) payable public{ - address payable self = payable(address(uint160(address(this)))); - self.send(i); - } - - function testTransferTokenSelf(uint256 i,trcToken tokenId) payable public{ - address payable self = payable(address(uint160(address(this)))); - self.transferToken(i, tokenId); - } - - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(10, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } - function deploy2(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(300, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/TransferFailed005.sol b/framework/src/test/resources/soliditycode/TransferFailed005.sol deleted file mode 100644 index 66b946199c2..00000000000 --- a/framework/src/test/resources/soliditycode/TransferFailed005.sol +++ /dev/null @@ -1,90 +0,0 @@ -contract EnergyOfTransferFailedTest { - constructor() payable public { - - } - // InsufficientBalance - function testTransferTrxInsufficientBalance(uint256 i) payable public{ - payable(msg.sender).transfer(i); - } - - function testSendTrxInsufficientBalance(uint256 i) payable public{ - payable(msg.sender).send(i); - } - - function testTransferTokenInsufficientBalance(uint256 i,trcToken tokenId) payable public{ - payable(msg.sender).transferToken(i, tokenId); - } - - function testCallTrxInsufficientBalance(uint256 i,address payable caller) public returns (bool,bytes memory){ - return caller.call{value:i}(abi.encodeWithSignature("test()")); - } - - function testCreateTrxInsufficientBalance(uint256 i) payable public { - (new Caller){value:i}(); - } - - // NonexistentTarget - - function testSendTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.send(i); - } - - function testTransferTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.transfer(i); - } - - function testTransferTokenNonexistentTarget(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - require(address(this).balance >= i); - nonexistentTarget.transferToken(i, tokenId); - } - - function testCallTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.call{value:i}(abi.encodeWithSignature("test()")); - } - - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } - - // target is self - function testTransferTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = payable(address(uint160(address(this)))); - self.transfer(i); - } - - function testSendTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = payable(address(uint160(address(this)))); - self.send(i); - } - - function testTransferTokenSelf(uint256 i,trcToken tokenId) payable public{ - require(address(this).balance >= i); - address payable self = payable(address(uint160(address(this)))); - self.transferToken(i, tokenId); - } - - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(10, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256 ){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/TransferFailed006.sol b/framework/src/test/resources/soliditycode/TransferFailed006.sol deleted file mode 100644 index 66b946199c2..00000000000 --- a/framework/src/test/resources/soliditycode/TransferFailed006.sol +++ /dev/null @@ -1,90 +0,0 @@ -contract EnergyOfTransferFailedTest { - constructor() payable public { - - } - // InsufficientBalance - function testTransferTrxInsufficientBalance(uint256 i) payable public{ - payable(msg.sender).transfer(i); - } - - function testSendTrxInsufficientBalance(uint256 i) payable public{ - payable(msg.sender).send(i); - } - - function testTransferTokenInsufficientBalance(uint256 i,trcToken tokenId) payable public{ - payable(msg.sender).transferToken(i, tokenId); - } - - function testCallTrxInsufficientBalance(uint256 i,address payable caller) public returns (bool,bytes memory){ - return caller.call{value:i}(abi.encodeWithSignature("test()")); - } - - function testCreateTrxInsufficientBalance(uint256 i) payable public { - (new Caller){value:i}(); - } - - // NonexistentTarget - - function testSendTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.send(i); - } - - function testTransferTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.transfer(i); - } - - function testTransferTokenNonexistentTarget(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - require(address(this).balance >= i); - nonexistentTarget.transferToken(i, tokenId); - } - - function testCallTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.call{value:i}(abi.encodeWithSignature("test()")); - } - - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } - - // target is self - function testTransferTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = payable(address(uint160(address(this)))); - self.transfer(i); - } - - function testSendTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = payable(address(uint160(address(this)))); - self.send(i); - } - - function testTransferTokenSelf(uint256 i,trcToken tokenId) payable public{ - require(address(this).balance >= i); - address payable self = payable(address(uint160(address(this)))); - self.transferToken(i, tokenId); - } - - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(10, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256 ){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/TransferFailed007.sol b/framework/src/test/resources/soliditycode/TransferFailed007.sol deleted file mode 100644 index 66b946199c2..00000000000 --- a/framework/src/test/resources/soliditycode/TransferFailed007.sol +++ /dev/null @@ -1,90 +0,0 @@ -contract EnergyOfTransferFailedTest { - constructor() payable public { - - } - // InsufficientBalance - function testTransferTrxInsufficientBalance(uint256 i) payable public{ - payable(msg.sender).transfer(i); - } - - function testSendTrxInsufficientBalance(uint256 i) payable public{ - payable(msg.sender).send(i); - } - - function testTransferTokenInsufficientBalance(uint256 i,trcToken tokenId) payable public{ - payable(msg.sender).transferToken(i, tokenId); - } - - function testCallTrxInsufficientBalance(uint256 i,address payable caller) public returns (bool,bytes memory){ - return caller.call{value:i}(abi.encodeWithSignature("test()")); - } - - function testCreateTrxInsufficientBalance(uint256 i) payable public { - (new Caller){value:i}(); - } - - // NonexistentTarget - - function testSendTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.send(i); - } - - function testTransferTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.transfer(i); - } - - function testTransferTokenNonexistentTarget(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - require(address(this).balance >= i); - nonexistentTarget.transferToken(i, tokenId); - } - - function testCallTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.call{value:i}(abi.encodeWithSignature("test()")); - } - - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } - - // target is self - function testTransferTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = payable(address(uint160(address(this)))); - self.transfer(i); - } - - function testSendTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = payable(address(uint160(address(this)))); - self.send(i); - } - - function testTransferTokenSelf(uint256 i,trcToken tokenId) payable public{ - require(address(this).balance >= i); - address payable self = payable(address(uint160(address(this)))); - self.transferToken(i, tokenId); - } - - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(10, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256 ){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/TriggerConstant001.sol b/framework/src/test/resources/soliditycode/TriggerConstant001.sol deleted file mode 100644 index b385850577d..00000000000 --- a/framework/src/test/resources/soliditycode/TriggerConstant001.sol +++ /dev/null @@ -1,28 +0,0 @@ - - -contract testConstantContract{ - uint256 public i; - function testPayable() public payable returns (uint256 z) { - i=1; - z=i; - return z; - } - function testNoPayable() public returns (uint256 z) { - i=1; - z=i; - return z; - } - function testView() public view returns (uint256 z) { - uint256 i=1; - return i; - } - function testPure() public pure returns (uint256 z) { - uint256 i=1; - return i; - } - function testView2() public view returns (uint256 z) { - uint256 i=1; - revert(); - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/TriggerConstant002.sol b/framework/src/test/resources/soliditycode/TriggerConstant002.sol deleted file mode 100644 index 7708d81792a..00000000000 --- a/framework/src/test/resources/soliditycode/TriggerConstant002.sol +++ /dev/null @@ -1,10 +0,0 @@ - - -contract testConstantContract{ - uint256 public i; - function testNoPayable() public returns (uint256 z) { - i=1; - z=i; - return z; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/TriggerConstant003.sol b/framework/src/test/resources/soliditycode/TriggerConstant003.sol deleted file mode 100644 index 947b3f610e6..00000000000 --- a/framework/src/test/resources/soliditycode/TriggerConstant003.sol +++ /dev/null @@ -1,18 +0,0 @@ - - -contract testConstantContract{ - function testView() public view returns (uint256 z) { - uint256 i=1; - return i; - } - - function testPure() public pure returns (uint256 z) { - uint256 i=1; - return i; - } - - function testPayable() public payable returns (uint256 z) { - uint256 i=1; - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/TriggerConstant004.sol b/framework/src/test/resources/soliditycode/TriggerConstant004.sol deleted file mode 100644 index 7fcb44950e7..00000000000 --- a/framework/src/test/resources/soliditycode/TriggerConstant004.sol +++ /dev/null @@ -1,8 +0,0 @@ - - -contract testConstantContract{ -function testPure() public pure returns (uint256 z) { -uint256 i=1; -return i; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/TriggerConstant015.sol b/framework/src/test/resources/soliditycode/TriggerConstant015.sol deleted file mode 100644 index d926c43c824..00000000000 --- a/framework/src/test/resources/soliditycode/TriggerConstant015.sol +++ /dev/null @@ -1,24 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract TestConstract { - constructor () public { - } - function plusOne() public returns(uint){ - return 1; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/TriggerConstant024.sol b/framework/src/test/resources/soliditycode/TriggerConstant024.sol deleted file mode 100644 index 69ad3a2d5b5..00000000000 --- a/framework/src/test/resources/soliditycode/TriggerConstant024.sol +++ /dev/null @@ -1,9 +0,0 @@ - - -contract testConstantContract{ -function testView() public view returns (uint256 z) { -uint256 i=1; -revert(); -return i; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/TvmIsContract.sol b/framework/src/test/resources/soliditycode/TvmIsContract.sol deleted file mode 100644 index 4266b9e92ca..00000000000 --- a/framework/src/test/resources/soliditycode/TvmIsContract.sol +++ /dev/null @@ -1,15 +0,0 @@ -contract testIsContract{ -bool public isContrct; -constructor () public { - isContrct = address(this).isContract; -} -function testIsContractCommand(address a) public returns (bool) { -return (a.isContract); -} -function selfdestructContract(address payable a) public { - selfdestruct(a); -} -function testConstructor() public returns(bool){ - return isContrct; -} -} diff --git a/framework/src/test/resources/soliditycode/TvmIsContract001.sol b/framework/src/test/resources/soliditycode/TvmIsContract001.sol deleted file mode 100644 index 77aae930b59..00000000000 --- a/framework/src/test/resources/soliditycode/TvmIsContract001.sol +++ /dev/null @@ -1,24 +0,0 @@ -contract testIsContract{ -bool public isContrct; -constructor () public { - isContrct = address(this).isContract; -} -function testIsContractCommand(address a) public returns (bool) { -return (a.isContract); -} - -function testIsContractView(address a) view public returns (bool) { -return (a.isContract); -} - -function selfdestructContract(address payable a) public { - selfdestruct(a); -} -function testConstructor() public returns(bool){ - return isContrct; -} - -function testConstructorView() public view returns(bool){ - return isContrct; -} -} diff --git a/framework/src/test/resources/soliditycode/TvmIsContract002.sol b/framework/src/test/resources/soliditycode/TvmIsContract002.sol deleted file mode 100644 index 2fe474fd98c..00000000000 --- a/framework/src/test/resources/soliditycode/TvmIsContract002.sol +++ /dev/null @@ -1,5 +0,0 @@ -contract testIsContract{ -function testIsContractCommand(address a) public returns (bool) { -return (a.isContract); -} -} diff --git a/framework/src/test/resources/soliditycode/TvmNewCommand043.sol b/framework/src/test/resources/soliditycode/TvmNewCommand043.sol deleted file mode 100644 index 04d9f7dde28..00000000000 --- a/framework/src/test/resources/soliditycode/TvmNewCommand043.sol +++ /dev/null @@ -1,18 +0,0 @@ -contract TestBitwiseShift { - - function shlTest(int256 num, int256 input) public returns (bytes32 out) { - assembly { - out := shl(num, input) - } - } - function shrTest(int256 num, int256 input) public returns (bytes32 out) { - assembly { - out := shr(num, input) - } - } - function sarTest(int256 num, int256 input) public returns (bytes32 out) { - assembly { - out := sar(num, input) - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/TvmNewCommand103.sol b/framework/src/test/resources/soliditycode/TvmNewCommand103.sol deleted file mode 100644 index dbc7fd0f0f4..00000000000 --- a/framework/src/test/resources/soliditycode/TvmNewCommand103.sol +++ /dev/null @@ -1,8 +0,0 @@ - - -contract testConstantContract{ -function testView() public constant returns (uint256 z) { -uint256 i=1; -return i; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/TvmNewCommand107.sol b/framework/src/test/resources/soliditycode/TvmNewCommand107.sol deleted file mode 100644 index 5b51cd1842c..00000000000 --- a/framework/src/test/resources/soliditycode/TvmNewCommand107.sol +++ /dev/null @@ -1,9 +0,0 @@ - - - contract testConstantContract{ - int256 public i; - function testPayable() public returns (int z) { - z=1+1; - return z; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/TvmNewCommand108.sol b/framework/src/test/resources/soliditycode/TvmNewCommand108.sol deleted file mode 100644 index 0088054faf9..00000000000 --- a/framework/src/test/resources/soliditycode/TvmNewCommand108.sol +++ /dev/null @@ -1,7 +0,0 @@ - - - contract testConstantContract{ - function test() pure public returns (int z) { - return 1; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/TvmNewCommand109.sol b/framework/src/test/resources/soliditycode/TvmNewCommand109.sol deleted file mode 100644 index dc8dd1e8399..00000000000 --- a/framework/src/test/resources/soliditycode/TvmNewCommand109.sol +++ /dev/null @@ -1,7 +0,0 @@ - - - contract testConstantContract{ - function test() view public returns (int z) { - return 1; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/TvmOldCommand001.sol b/framework/src/test/resources/soliditycode/TvmOldCommand001.sol deleted file mode 100644 index f2927bd8e45..00000000000 --- a/framework/src/test/resources/soliditycode/TvmOldCommand001.sol +++ /dev/null @@ -1,11 +0,0 @@ - - -contract binaryRightContract{ - function binaryMoveR(uint i)public returns (uint z) { - return z = 5 >> i; - } - function binaryLiftR(uint i)public returns (uint z) { - return z = 5 << i; - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/VerifyBurnProof001.sol b/framework/src/test/resources/soliditycode/VerifyBurnProof001.sol deleted file mode 100644 index 4173e84de23..00000000000 --- a/framework/src/test/resources/soliditycode/VerifyBurnProof001.sol +++ /dev/null @@ -1,20 +0,0 @@ - -contract VerifyBurnProof001Test { - // verifyBurnProof(bytes32[10],bytes32[2],uint64,bytes32[2],bytes32) - // size = 512 - // - - function VerifyBurnProofSize001(bytes32[10] memory output, bytes32[2] memory spendAuthoritySignature, uint64 value, bytes32[2] memory bindingSignature,bytes32 signHash) public returns (bool){ - return verifyBurnProof(output, spendAuthoritySignature, value, bindingSignature, signHash); - } - - function VerifyBurnProofSize002(bytes memory data) public returns (bool, bytes memory){ - // bytes memory empty = ""; - return address(0x1000003).delegatecall(data); - } - - function VerifyBurnProofSize003() public returns (bool, bytes memory){ - bytes memory empty = ""; - return address(0x1000003).delegatecall(empty); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/VerifyMintProof001.sol b/framework/src/test/resources/soliditycode/VerifyMintProof001.sol deleted file mode 100644 index cb0812c2ef5..00000000000 --- a/framework/src/test/resources/soliditycode/VerifyMintProof001.sol +++ /dev/null @@ -1,33 +0,0 @@ - -contract VerifyMintProof001Test { - // verifyMintProof(bytes32[9],bytes32[2],uint64,bytes32,bytes32[33],uint256) - - function VerifyMintProofSize001(bytes32[9] memory output, bytes32[2] memory bindingSignature, uint64 value, bytes32 signHash, bytes32[33] memory frontier,uint256 leafCount) public returns (bytes32[] memory){ - return verifyMintProof(output, bindingSignature, value, signHash, frontier, leafCount); - } - - function VerifyMintProofSize002(bytes memory data) public returns (bool, bytes memory){ -// address verifyMint = address (0x1000001); -// -// assembly { -// let succeeded := delegatecall(sub(gas, 5000), verifyMint, add(data, 0x20), mload(data), 0, 0) -// let size := returndatasize -// let response := mload(0x40) -// mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f)))) -// mstore(response, size) -// returndatacopy(add(response, 0x20), 0, size) -// switch iszero(succeeded) -// case 1 { -// // throw if delegatecall failed -// revert(add(response, 0x20), size) -// } -// } - - return address(0x1000001).delegatecall(data); - } - - function VerifyMintProofSize003() public returns (bool, bytes memory){ - bytes memory empty = ""; - return address(0x1000001).call(empty); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/abiencode.sol b/framework/src/test/resources/soliditycode/abiencode.sol deleted file mode 100644 index 38fad3454d6..00000000000 --- a/framework/src/test/resources/soliditycode/abiencode.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma experimental ABIEncoderV2; - -// tests encoding from storage arrays - -contract AbiEncode { - int256[2][] tmp_h; - function h(int256[2][] calldata s) external returns (bytes memory) { - tmp_h = s; - return abi.encode(tmp_h); - } - int256[2][2] tmp_i; - function i(int256[2][2] calldata s) external returns (bytes memory) { - tmp_i = s; - return abi.encode(tmp_i); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/abstract001.sol b/framework/src/test/resources/soliditycode/abstract001.sol deleted file mode 100644 index 741f236925d..00000000000 --- a/framework/src/test/resources/soliditycode/abstract001.sol +++ /dev/null @@ -1,11 +0,0 @@ -//pragma solidity ^0.6.0; - -interface X { - function setValue(uint _x) external; - function setBalance(uint _x) external; -} - -abstract contract abstract001 is X { - uint x; - function setX(uint _x) public { x = _x; } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/abstract002.sol b/framework/src/test/resources/soliditycode/abstract002.sol deleted file mode 100644 index 7358fc8e163..00000000000 --- a/framework/src/test/resources/soliditycode/abstract002.sol +++ /dev/null @@ -1,13 +0,0 @@ -//pragma solidity ^0.6.0; - -interface X { - function setValue(uint _x) external; - function setBalance(uint _x) external; -} - -abstract contract abstract002 is X { - uint x; - function setX(uint _x) public { x = _x; } - function setValue(uint _x) external override{ x = _x; } - function setBalance(uint _x) external override{ x = _x; } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/abstractContractWithMapParamsConstructor.sol b/framework/src/test/resources/soliditycode/abstractContractWithMapParamsConstructor.sol deleted file mode 100644 index 380c57180b8..00000000000 --- a/framework/src/test/resources/soliditycode/abstractContractWithMapParamsConstructor.sol +++ /dev/null @@ -1,23 +0,0 @@ -abstract contract Feline { - - constructor (mapping (uint => uint) storage m) { - m[5] = 20; - } - - function utterance() public virtual returns (bytes32); - - function getContractName() public returns (string memory){ - return "Feline"; - } -} - - -contract Cat is Feline { - mapping (uint => uint) public m; - - constructor() Feline(m) { - } - function utterance() public override returns (bytes32) { return "miaow"; } - function getMapValue() public returns (uint) { return m[5]; } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/accountAssert.sol b/framework/src/test/resources/soliditycode/accountAssert.sol deleted file mode 100644 index ef10d5fedd8..00000000000 --- a/framework/src/test/resources/soliditycode/accountAssert.sol +++ /dev/null @@ -1,94 +0,0 @@ -//pragma solidity ^0.6.0; - -contract transferTokenTestA { - - // transfer trc10 to a new address or exist address in constructor - constructor(address payable toAddress, uint256 tokenValue, trcToken id) payable public{ - toAddress.transferToken(tokenValue, id); - require(toAddress.tokenBalance(id) > 0, "tokenBalance should not be 0"); - } - - fallback() payable external{} - - function transferTest(address payable toAddress, uint256 tokenValue) payable public { - toAddress.transfer(tokenValue); - } - - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - - // suicide to a new address - function selfdestructTest(address payable toAddress) payable public{ - selfdestruct(toAddress); - } - - // transfer to a new contract - function createContractTest(uint256 tokenValue, trcToken id) payable public returns(address){ - Simple s = new Simple(); - require(address(s).tokenBalance(id)==0, "tokenBalance should be 0"); - payable(address(s)).transferToken(tokenValue, id); - require(address(s).tokenBalance(id)==tokenValue, "tokenBalance should not be 0"); - return address(s); - } - - // revert transfer to a new contract - function revertCreateContractTest(uint256 tokenValue, trcToken id) payable public { - Simple s = new Simple(); - payable(address(s)).transferToken(tokenValue, id); - revert(); - } -} - -contract transferTokenTestB { - - constructor() payable public{ - } - - fallback() payable external{} - - function transferTest(address payable toAddress, uint256 tokenValue) payable public { - toAddress.transfer(tokenValue); - } - - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - - // suicide to a new address - function selfdestructTest(address payable toAddress) payable public{ - selfdestruct(toAddress); - } - - // transfer to a new contract - function createContractTest(uint256 tokenValue, trcToken id) payable public returns(address){ - Simple s = new Simple(); - require(address(s).tokenBalance(id)==0, "tokenBalance should be 0"); - payable(address(s)).transferToken(tokenValue, id); - require(address(s).tokenBalance(id)==tokenValue, "tokenBalance should not be 0"); - return address(s); - } - - // revert transfer to a new contract - function revertCreateContractTest(uint256 tokenValue, trcToken id) payable public { - Simple s = new Simple(); - payable(address(s)).transferToken(tokenValue, id); - revert(); - } -} - -contract transferTokenTestC { - Simple public s; - - // transfer to a new address in constructor - constructor(trcToken id) payable public{ - s = new Simple(); - require(address(s).tokenBalance(id)==0, "new contract tokenBalance should be 0"); - require(address(this).tokenBalance(id)==0, "this.tokenBalance should be 0"); - } -} - -contract Simple { - constructor() payable public{} - fallback() payable external{} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/addMsg001Nonpayable.sol b/framework/src/test/resources/soliditycode/addMsg001Nonpayable.sol deleted file mode 100644 index fcd40cdb521..00000000000 --- a/framework/src/test/resources/soliditycode/addMsg001Nonpayable.sol +++ /dev/null @@ -1,20 +0,0 @@ - - -contract IllegalDecorate { - -event log(uint256); -constructor() payable public{} - -fallback() payable external{} - -function transferTokenWithOutPayable(address payable toAddress, uint256 tokenValue)public { -// function transferTokenWithValue(address toAddress, uint256 tokenValue) payable public { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); - -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/addMsg002View.sol b/framework/src/test/resources/soliditycode/addMsg002View.sol deleted file mode 100644 index 0c04b5c0b8a..00000000000 --- a/framework/src/test/resources/soliditycode/addMsg002View.sol +++ /dev/null @@ -1,20 +0,0 @@ - - -contract IllegalDecorate { - -constructor() payable public{} - -fallback() payable external{} - -event log(uint256); - -function transferTokenWithView(address payable toAddress, uint256 tokenValue) public view{ -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} - diff --git a/framework/src/test/resources/soliditycode/addMsg003Constant.sol b/framework/src/test/resources/soliditycode/addMsg003Constant.sol deleted file mode 100644 index 2065802bed1..00000000000 --- a/framework/src/test/resources/soliditycode/addMsg003Constant.sol +++ /dev/null @@ -1,19 +0,0 @@ - - -contract IllegalDecorate { - -constructor() payable public{} - -fallback() payable external{} - -event log(uint256); - -function transferTokenWithConstant(address payable toAddress, uint256 tokenValue) public constant{ -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/addMsg004Pure.sol b/framework/src/test/resources/soliditycode/addMsg004Pure.sol deleted file mode 100644 index 25f1a36d8b7..00000000000 --- a/framework/src/test/resources/soliditycode/addMsg004Pure.sol +++ /dev/null @@ -1,19 +0,0 @@ - - -contract IllegalDecorate { - -constructor() payable public{} - -fallback() payable external{} - -event log(uint256); - -function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public pure{ -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/addTransferToken001Nonpayable.sol b/framework/src/test/resources/soliditycode/addTransferToken001Nonpayable.sol deleted file mode 100644 index 039b341b6ac..00000000000 --- a/framework/src/test/resources/soliditycode/addTransferToken001Nonpayable.sol +++ /dev/null @@ -1,13 +0,0 @@ - - - contract IllegalDecorate { - - constructor() payable public{} - - fallback() payable external{} - - function transferTokenWithOutPayable(address payable toAddress,trcToken id, uint256 tokenValue)public { - - toAddress.transferToken(tokenValue, id); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/addTransferToken001payable.sol b/framework/src/test/resources/soliditycode/addTransferToken001payable.sol deleted file mode 100644 index 17078e30189..00000000000 --- a/framework/src/test/resources/soliditycode/addTransferToken001payable.sol +++ /dev/null @@ -1,13 +0,0 @@ - - - contract IllegalDecorate { - - constructor() payable public{} - - fallback() payable external{} - - function transferTokenWithOutPayable(address payable toAddress,trcToken id, uint256 tokenValue) public payable{ - - toAddress.transferToken(tokenValue, id); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/addTransferToken002View.sol b/framework/src/test/resources/soliditycode/addTransferToken002View.sol deleted file mode 100644 index c50a16390f5..00000000000 --- a/framework/src/test/resources/soliditycode/addTransferToken002View.sol +++ /dev/null @@ -1,15 +0,0 @@ - - -contract IllegalDecorate { - - constructor() payable public{} - - fallback() payable external{} - - function transferTokenWithView(address payable toAddress,trcToken id, uint256 tokenValue) public view{ - - toAddress.transferToken(tokenValue, id); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/addTransferToken003Constant.sol b/framework/src/test/resources/soliditycode/addTransferToken003Constant.sol deleted file mode 100644 index 18721d9b94c..00000000000 --- a/framework/src/test/resources/soliditycode/addTransferToken003Constant.sol +++ /dev/null @@ -1,14 +0,0 @@ - -contract IllegalDecorate { - - constructor() payable public{} - - fallback() payable external{} - - function transferTokenWithConstant(address payable toAddress, uint256 tokenValue) public constant{ - - toAddress.transferToken(tokenValue, 0x6e6d62); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/addTransferToken004Pure.sol b/framework/src/test/resources/soliditycode/addTransferToken004Pure.sol deleted file mode 100644 index f7716ee3874..00000000000 --- a/framework/src/test/resources/soliditycode/addTransferToken004Pure.sol +++ /dev/null @@ -1,15 +0,0 @@ - - -contract IllegalDecorate { - - constructor() payable public{} - - fallback() payable external{} - - function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public pure{ - - toAddress.transferToken(tokenValue, 0x6e6d62); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/addTrcToken001Assemble.sol b/framework/src/test/resources/soliditycode/addTrcToken001Assemble.sol deleted file mode 100644 index fe7a7f4cef8..00000000000 --- a/framework/src/test/resources/soliditycode/addTrcToken001Assemble.sol +++ /dev/null @@ -1,62 +0,0 @@ - - -contract InAssemble { - -mapping(trcToken => uint256) tokenCnt; -mapping(uint256 => mapping(trcToken => trcToken)) cntTokenToken; -constructor () payable public {} -function getBalance (address addr) view public returns(uint256 r) { -assembly{ -r := balance(addr) -} -} - -function getTokenBalanceConstant (address addr, trcToken tokenId) view public returns(uint256 r) { -assembly{ -r := tokenbalance(tokenId, addr) -} -} - -function getTokenBalance (address addr, trcToken tokenId) public returns(uint256 r) { -assembly{ -r := tokenbalance(tokenId, addr) -} -} - -function transferTokenInAssembly(address addr, trcToken tokenId, uint256 tokenValue) public payable { -bytes4 sig = bytes4(keccak256("()")); // function signature - -assembly { -let x := mload(0x40) // get empty storage location -mstore(x,sig) // 4 bytes - place signature in empty storage - -let ret := calltoken(gas, addr, tokenValue, tokenId, -x, // input -0x04, // input size = 4 bytes -x, // output stored at input location, save space -0x0 // output size = 0 bytes -) - -// let ret := calltoken(gas, addr, tokenValue, -// x, // input -// 0x04, // input size = 4 bytes -// x, // output stored at input location, save space -// 0x0 // output size = 0 bytes -// ) // ERROR - - -mstore(0x40, add(x,0x20)) // update free memory pointer -} - -} - -function trcTokenInMap(trcToken tokenId, uint256 tokenValue) public returns(uint256 r) { -tokenCnt[tokenId] += tokenValue; -r = tokenCnt[tokenId]; -} - -function cntTokenTokenInMap(trcToken tokenId1, trcToken tokenId2, uint256 tokenValue) public returns(trcToken r) { -cntTokenToken[tokenValue][tokenId1] = tokenId2; -r = cntTokenToken[tokenValue][tokenId1]; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/addTrcToken002Cat.sol b/framework/src/test/resources/soliditycode/addTrcToken002Cat.sol deleted file mode 100644 index 0cd407079ba..00000000000 --- a/framework/src/test/resources/soliditycode/addTrcToken002Cat.sol +++ /dev/null @@ -1,2051 +0,0 @@ - - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() public { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address payable public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address payable _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() public onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - emit Transfer(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(now), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - uint256 newKittenId = kitties.push(_kitty) - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - emit Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(address(0), _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -contract ERC721 { - // Required methods - function totalSupply() public view returns (uint256 total); - function balanceOf(address _owner) public view returns (uint256 balance); - function ownerOf(uint256 _tokenId) external view returns (address owner); - function approve(address _to, uint256 _tokenId) external; - function transfer(address _to, uint256 _tokenId) external; - function transferFrom(address _from, address _to, uint256 _tokenId) external; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) external view returns (bool); -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is ERC721, KittyBase { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public view returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - emit Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() public view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - external - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { - string memory outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { - require( address(erc721Metadata) != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2 sun; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - msg.sender.transfer(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, address(saleAuction)); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, address(siringAuction)); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10 sun; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, address(saleAuction)); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - address(uint160(address(this))) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - constructor() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(-1), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - emit ContractUpgrade(_v2Address); - } - - /// @notice No tipping! - /// @dev Reject all Ether from being sent here, unless it's from one of the - /// two auction contracts. (Hopefully, we can prevent user accidents.) - fallback() external payable { - require( - msg.sender == address(saleAuction) || - msg.sender == address(siringAuction) - ); - } - - /// @notice Returns all the relevant information about a specific kitty. - /// @param _id The ID of the kitty of interest. - function getKitty(uint256 _id) - external - view - returns ( - bool isGestating, - bool isReady, - uint256 cooldownIndex, - uint256 nextActionAt, - uint256 siringWithId, - uint256 birthTime, - uint256 matronId, - uint256 sireId, - uint256 generation, - uint256 genes - ) { - Kitty storage kit = kitties[_id]; - - // if this variable is 0 then it's not gestating - isGestating = (kit.siringWithId != 0); - isReady = (kit.cooldownEndBlock <= block.number); - cooldownIndex = uint256(kit.cooldownIndex); - nextActionAt = uint256(kit.cooldownEndBlock); - siringWithId = uint256(kit.siringWithId); - birthTime = uint256(kit.birthTime); - matronId = uint256(kit.matronId); - sireId = uint256(kit.sireId); - generation = uint256(kit.generation); - genes = kit.genes; - } - - /// @dev Override unpause so it requires all external contract addresses - /// to be set before contract can be unpaused. Also, we can't have - /// newContractAddress set either, because then the contract was upgraded. - /// @notice This is public rather than external so we can call super.unpause - /// without using an expensive CALL. - - function unpause(address payable toAddress, uint256 tokenValue, trcToken tokenId) public onlyCEO whenPaused returns (uint256 r) { - require(address(saleAuction) != address(0)); - require(address(siringAuction) != address(0)); - require(address(geneScience) != address(0)); - require(address(newContractAddress) == address(0)); - toAddress.transferToken(tokenValue, tokenId); - r = address(this).tokenBalance(tokenId); - // Actually unpause the contract. - super.unpause(); - } - - // @dev Allows the CFO to capture the balance available to the contract. - function withdrawBalance() external onlyCFO { - uint256 balance = address(this).balance; - // Subtract all the currently pregnant kittens we have, plus 1 of margin. - uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - - if (balance > subtractFees) { - cfoAddress.transfer(balance - subtractFees); - } - } -} - - - - - - - - - - - - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - - function isGeneScience() public pure returns (bool){ - return true; - } - - /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor - /// @param genes1 genes of mom - /// @param genes2 genes of sire - /// @return the genes that are supposed to be passed down the child - function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - - return (genes1+genes2+targetBlock)/2; - - -} -} - - - - - - - - - - - - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { - /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. - function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { - if (_tokenId == 1) { - buffer[0] = "Hello World! :D"; - count = 15; - } else if (_tokenId == 2) { - buffer[0] = "I would definitely choose a medi"; - buffer[1] = "um length string."; - count = 49; - } else if (_tokenId == 3) { - buffer[0] = "Lorem ipsum dolor sit amet, mi e"; - buffer[1] = "st accumsan dapibus augue lorem,"; - buffer[2] = " tristique vestibulum id, libero"; - buffer[3] = " suscipit varius sapien aliquam."; - count = 128; - } - } -} - - - - - - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - - // Represents an auction on an NFT - struct Auction { - // Current owner of NFT - address payable seller; - // Price (in wei) at beginning of auction - uint128 startingPrice; - // Price (in wei) at end of auction - uint128 endingPrice; - // Duration (in seconds) of auction - uint64 duration; - // Time when auction started - // NOTE: 0 if this auction has been concluded - uint64 startedAt; - } - - // Reference to contract tracking NFT ownership - ERC721 public nonFungibleContract; - - // Cut owner takes on each auction, measured in basis points (1/100 of a percent). - // Values 0-10,000 map to 0%-100% - uint256 public ownerCut; - - // Map from token ID to their corresponding auction. - mapping (uint256 => Auction) tokenIdToAuction; - - event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); - event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); - event AuctionCancelled(uint256 tokenId); - - /// @dev Returns true if the claimant owns the token. - /// @param _claimant - Address claiming to own the token. - /// @param _tokenId - ID of token whose ownership to verify. - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return (nonFungibleContract.ownerOf(_tokenId) == _claimant); - } - - /// @dev Escrows the NFT, assigning ownership to this contract. - /// Throws if the escrow fails. - /// @param _owner - Current owner address of token to escrow. - /// @param _tokenId - ID of token whose approval to verify. - function _escrow(address _owner, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transferFrom(_owner, address(this), _tokenId); - } - - /// @dev Transfers an NFT owned by this contract to another address. - /// Returns true if the transfer succeeds. - /// @param _receiver - Address to transfer NFT to. - /// @param _tokenId - ID of token to transfer. - function _transfer(address _receiver, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transfer(_receiver, _tokenId); - } - - /// @dev Adds an auction to the list of open auctions. Also fires the - /// AuctionCreated event. - /// @param _tokenId The ID of the token to be put on auction. - /// @param _auction Auction to add. - function _addAuction(uint256 _tokenId, Auction memory _auction) internal { - // Require that all auctions have a duration of - // at least one minute. (Keeps our math from getting hairy!) - require(_auction.duration >= 1 minutes); - - tokenIdToAuction[_tokenId] = _auction; - - emit AuctionCreated( - uint256(_tokenId), - uint256(_auction.startingPrice), - uint256(_auction.endingPrice), - uint256(_auction.duration) - ); - } - - /// @dev Cancels an auction unconditionally. - function _cancelAuction(uint256 _tokenId, address _seller) internal { - _removeAuction(_tokenId); - _transfer(_seller, _tokenId); - emit AuctionCancelled(_tokenId); - } - - /// @dev Computes the price and transfers winnings. - /// Does NOT transfer ownership of token. - function _bid(uint256 _tokenId, uint256 _bidAmount) - internal - returns (uint256) - { - // Get a reference to the auction struct - Auction storage auction = tokenIdToAuction[_tokenId]; - - // Explicitly check that this auction is currently live. - // (Because of how Ethereum mappings work, we can't just count - // on the lookup above failing. An invalid _tokenId will just - // return an auction object that is all zeros.) - require(_isOnAuction(auction)); - - // Check that the bid is greater than or equal to the current price - uint256 price = _currentPrice(auction); - require(_bidAmount >= price); - - // Grab a reference to the seller before the auction struct - // gets deleted. - address payable seller = auction.seller; - - // The bid is good! Remove the auction before sending the fees - // to the sender so we can't have a reentrancy attack. - _removeAuction(_tokenId); - - // Transfer proceeds to seller (if there are any!) - if (price > 0) { - // Calculate the auctioneer's cut. - // (NOTE: _computeCut() is guaranteed to return a - // value <= price, so this subtraction can't go negative.) - uint256 auctioneerCut = _computeCut(price); - uint256 sellerProceeds = price - auctioneerCut; - - // NOTE: Doing a transfer() in the middle of a complex - // method like this is generally discouraged because of - // reentrancy attacks and DoS attacks if the seller is - // a contract with an invalid fallback function. We explicitly - // guard against reentrancy attacks by removing the auction - // before calling transfer(), and the only thing the seller - // can DoS is the sale of their own asset! (And if it's an - // accident, they can call cancelAuction(). ) - seller.transfer(sellerProceeds); - } - - // Calculate any excess funds included with the bid. If the excess - // is anything worth worrying about, transfer it back to bidder. - // NOTE: We checked above that the bid amount is greater than or - // equal to the price so this cannot underflow. - uint256 bidExcess = _bidAmount - price; - - // Return the funds. Similar to the previous transfer, this is - // not susceptible to a re-entry attack because the auction is - // removed before any transfers occur. - msg.sender.transfer(bidExcess); - - // Tell the world! - emit AuctionSuccessful(_tokenId, price, msg.sender); - - return price; - } - - /// @dev Removes an auction from the list of open auctions. - /// @param _tokenId - ID of NFT on auction. - function _removeAuction(uint256 _tokenId) internal { - delete tokenIdToAuction[_tokenId]; - } - - /// @dev Returns true if the NFT is on auction. - /// @param _auction - Auction to check. - function _isOnAuction(Auction storage _auction) internal view returns (bool) { - return (_auction.startedAt > 0); - } - - /// @dev Returns current price of an NFT on auction. Broken into two - /// functions (this one, that computes the duration from the auction - /// structure, and the other that does the price computation) so we - /// can easily test that the price computation works correctly. - function _currentPrice(Auction storage _auction) - internal - view - returns (uint256) - { - uint256 secondsPassed = 0; - - // A bit of insurance against negative values (or wraparound). - // Probably not necessary (since Ethereum guarnatees that the - // now variable doesn't ever go backwards). - if (now > _auction.startedAt) { - secondsPassed = now - _auction.startedAt; - } - - return _computeCurrentPrice( - _auction.startingPrice, - _auction.endingPrice, - _auction.duration, - secondsPassed - ); - } - - /// @dev Computes the current price of an auction. Factored out - /// from _currentPrice so we can run extensive unit tests. - /// When testing, make this function public and turn on - /// `Current price computation` test suite. - function _computeCurrentPrice( - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - uint256 _secondsPassed - ) - internal - pure - returns (uint256) - { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our public functions carefully cap the maximum values for - // time (at 64-bits) and currency (at 128-bits). _duration is - // also known to be non-zero (see the require() statement in - // _addAuction()) - if (_secondsPassed >= _duration) { - // We've reached the end of the dynamic pricing portion - // of the auction, just return the end price. - return _endingPrice; - } else { - // Starting price can be higher than ending price (and often is!), so - // this delta can be negative. - int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - - // This multiplication can't overflow, _secondsPassed will easily fit within - // 64-bits, and totalPriceChange will easily fit within 128-bits, their product - // will always fit within 256-bits. - int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - - // currentPriceChange can be negative, but if so, will have a magnitude - // less that _startingPrice. Thus, this result will always end up positive. - int256 currentPrice = int256(_startingPrice) + currentPriceChange; - - return uint256(currentPrice); - } - } - - /// @dev Computes owner's cut of a sale. - /// @param _price - Sale price of NFT. - function _computeCut(uint256 _price) internal view returns (uint256) { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our entry functions carefully cap the maximum values for - // currency (at 128-bits), and ownerCut <= 10000 (see the require() - // statement in the ClockAuction constructor). The result of this - // function is always guaranteed to be <= _price. - return _price * ownerCut / 10000; - } - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { - event Pause(); - event Unpause(); - - bool public paused = false; - - - /** - * @dev modifier to allow actions only when the contract IS paused - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev modifier to allow actions only when the contract IS NOT paused - */ - modifier whenPaused { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyOwner whenNotPaused public returns (bool) { - paused = true; - emit Pause(); - return true; - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyOwner whenPaused public returns (bool) { - paused = false; - emit Unpause(); - return true; - } -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - - /// @dev The ERC-165 interface signature for ERC-721. - /// Ref: https://github.com/ethereum/EIPs/issues/165 - /// Ref: https://github.com/ethereum/EIPs/issues/721 - bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - - /// @dev Constructor creates a reference to the NFT ownership contract - /// and verifies the owner cut is in the valid range. - /// @param _nftAddress - address of a deployed contract implementing - /// the Nonfungible Interface. - /// @param _cut - percent cut the owner takes on each auction, must be - /// between 0-10,000. - constructor(address _nftAddress, uint256 _cut) public { - require(_cut <= 10000); - ownerCut = _cut; - - ERC721 candidateContract = ERC721(_nftAddress); - require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); - nonFungibleContract = candidateContract; - } - - /// @dev Remove all Ether from the contract, which is the owner's cuts - /// as well as any Ether sent directly to the contract address. - /// Always transfers to the NFT contract, but can be called either by - /// the owner or the NFT contract. - function withdrawBalance() external { - address payable nftAddress = address(uint160(address(nonFungibleContract))); - - require( - msg.sender == owner || - msg.sender == nftAddress - ); - // We are using this boolean method to make sure that even if one fails it will still work - bool res = nftAddress.send(address(this).balance); - } - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of time to move between starting - /// price and ending price (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - whenNotPaused - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(_owns(msg.sender, _tokenId)); - _escrow(msg.sender, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Bids on an open auction, completing the auction and transferring - /// ownership of the NFT if enough Ether is supplied. - /// @param _tokenId - ID of token to bid on. - function bid(uint256 _tokenId) - external - payable - whenNotPaused - { - // _bid will throw if the bid or funds transfer fails - _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - } - - /// @dev Cancels an auction that hasn't been won yet. - /// Returns the NFT to original owner. - /// @notice This is a state-modifying function that can - /// be called while the contract is paused. - /// @param _tokenId - ID of token on auction - function cancelAuction(uint256 _tokenId) - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - address seller = auction.seller; - require(msg.sender == seller); - _cancelAuction(_tokenId, seller); - } - - /// @dev Cancels an auction when the contract is paused. - /// Only the owner may do this, and NFTs are returned to - /// the seller. This should only be used in emergencies. - /// @param _tokenId - ID of the NFT on auction to cancel. - function cancelAuctionWhenPaused(uint256 _tokenId) - whenPaused - onlyOwner - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - _cancelAuction(_tokenId, auction.seller); - } - - /// @dev Returns auction info for an NFT on auction. - /// @param _tokenId - ID of NFT on auction. - function getAuction(uint256 _tokenId) - external - view - returns - ( - address seller, - uint256 startingPrice, - uint256 endingPrice, - uint256 duration, - uint256 startedAt - ) { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return ( - auction.seller, - auction.startingPrice, - auction.endingPrice, - auction.duration, - auction.startedAt - ); - } - - /// @dev Returns the current price of an auction. - /// @param _tokenId - ID of the token price we are checking. - function getCurrentPrice(uint256 _tokenId) - external - view - returns (uint256) - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return _currentPrice(auction); - } - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSiringAuctionAddress() call. - bool public isSiringClockAuction = true; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. Since this function is wrapped, - /// require sender to be KittyCore contract. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Places a bid for siring. Requires the sender - /// is the KittyCore contract because all bid methods - /// should be wrapped. Also returns the kitty to the - /// seller rather than the winner. - function bid(uint256 _tokenId) - external - payable - { - require(msg.sender == address(nonFungibleContract)); - address seller = tokenIdToAuction[_tokenId].seller; - // _bid checks that token ID is valid and will throw if bid fails - _bid(_tokenId, msg.value); - // We transfer the kitty back to the seller, the winner will get - // the offspring - _transfer(seller, _tokenId); - } - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSaleAuctionAddress() call. - bool public isSaleClockAuction = true; - - // Tracks last 5 sale price of gen0 kitty sales - uint256 public gen0SaleCount; - uint256[5] public lastGen0SalePrices; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Updates lastSalePrice if seller is the nft contract - /// Otherwise, works the same as default bid method. - function bid(uint256 _tokenId) - external - payable - { - // _bid verifies token ID size - address seller = tokenIdToAuction[_tokenId].seller; - uint256 price = _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - - // If not a gen0 auction, exit - if (seller == address(nonFungibleContract)) { - // Track gen0 sale prices - lastGen0SalePrices[gen0SaleCount % 5] = price; - gen0SaleCount++; - } - } - - function averageGen0SalePrice() external view returns (uint256) { - uint256 sum = 0; - for (uint256 i = 0; i < 5; i++) { - sum += lastGen0SalePrices[i]; - } - return sum / 5; - } - -} - - - - - - - diff --git a/framework/src/test/resources/soliditycode/addTrcToken002Cat_withFinny.sol b/framework/src/test/resources/soliditycode/addTrcToken002Cat_withFinny.sol deleted file mode 100644 index 24117bc5e6b..00000000000 --- a/framework/src/test/resources/soliditycode/addTrcToken002Cat_withFinny.sol +++ /dev/null @@ -1,2051 +0,0 @@ - - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() public { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address payable public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address payable _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() public onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - emit Transfer(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(now), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - uint256 newKittenId = kitties.push(_kitty) - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - emit Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(address(0), _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -contract ERC721 { - // Required methods - function totalSupply() public view returns (uint256 total); - function balanceOf(address _owner) public view returns (uint256 balance); - function ownerOf(uint256 _tokenId) external view returns (address owner); - function approve(address _to, uint256 _tokenId) external; - function transfer(address _to, uint256 _tokenId) external; - function transferFrom(address _from, address _to, uint256 _tokenId) external; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) external view returns (bool); -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is ERC721, KittyBase { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public view returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - emit Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() public view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - external - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { - string memory outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { - require( address(erc721Metadata) != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2 finney; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - msg.sender.transfer(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, address(saleAuction)); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, address(siringAuction)); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10 finney; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, address(saleAuction)); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - address(uint160(address(this))) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - constructor() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(-1), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - emit ContractUpgrade(_v2Address); - } - - /// @notice No tipping! - /// @dev Reject all Ether from being sent here, unless it's from one of the - /// two auction contracts. (Hopefully, we can prevent user accidents.) - fallback() external payable { - require( - msg.sender == address(saleAuction) || - msg.sender == address(siringAuction) - ); - } - - /// @notice Returns all the relevant information about a specific kitty. - /// @param _id The ID of the kitty of interest. - function getKitty(uint256 _id) - external - view - returns ( - bool isGestating, - bool isReady, - uint256 cooldownIndex, - uint256 nextActionAt, - uint256 siringWithId, - uint256 birthTime, - uint256 matronId, - uint256 sireId, - uint256 generation, - uint256 genes - ) { - Kitty storage kit = kitties[_id]; - - // if this variable is 0 then it's not gestating - isGestating = (kit.siringWithId != 0); - isReady = (kit.cooldownEndBlock <= block.number); - cooldownIndex = uint256(kit.cooldownIndex); - nextActionAt = uint256(kit.cooldownEndBlock); - siringWithId = uint256(kit.siringWithId); - birthTime = uint256(kit.birthTime); - matronId = uint256(kit.matronId); - sireId = uint256(kit.sireId); - generation = uint256(kit.generation); - genes = kit.genes; - } - - /// @dev Override unpause so it requires all external contract addresses - /// to be set before contract can be unpaused. Also, we can't have - /// newContractAddress set either, because then the contract was upgraded. - /// @notice This is public rather than external so we can call super.unpause - /// without using an expensive CALL. - - function unpause(address payable toAddress, uint256 tokenValue, trcToken tokenId) public onlyCEO whenPaused returns (uint256 r) { - require(address(saleAuction) != address(0)); - require(address(siringAuction) != address(0)); - require(address(geneScience) != address(0)); - require(address(newContractAddress) == address(0)); - toAddress.transferToken(tokenValue, tokenId); - r = address(this).tokenBalance(tokenId); - // Actually unpause the contract. - super.unpause(); - } - - // @dev Allows the CFO to capture the balance available to the contract. - function withdrawBalance() external onlyCFO { - uint256 balance = address(this).balance; - // Subtract all the currently pregnant kittens we have, plus 1 of margin. - uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - - if (balance > subtractFees) { - cfoAddress.transfer(balance - subtractFees); - } - } -} - - - - - - - - - - - - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - - function isGeneScience() public pure returns (bool){ - return true; - } - - /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor - /// @param genes1 genes of mom - /// @param genes2 genes of sire - /// @return the genes that are supposed to be passed down the child - function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - - return (genes1+genes2+targetBlock)/2; - - -} -} - - - - - - - - - - - - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { - /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. - function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { - if (_tokenId == 1) { - buffer[0] = "Hello World! :D"; - count = 15; - } else if (_tokenId == 2) { - buffer[0] = "I would definitely choose a medi"; - buffer[1] = "um length string."; - count = 49; - } else if (_tokenId == 3) { - buffer[0] = "Lorem ipsum dolor sit amet, mi e"; - buffer[1] = "st accumsan dapibus augue lorem,"; - buffer[2] = " tristique vestibulum id, libero"; - buffer[3] = " suscipit varius sapien aliquam."; - count = 128; - } - } -} - - - - - - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - - // Represents an auction on an NFT - struct Auction { - // Current owner of NFT - address payable seller; - // Price (in wei) at beginning of auction - uint128 startingPrice; - // Price (in wei) at end of auction - uint128 endingPrice; - // Duration (in seconds) of auction - uint64 duration; - // Time when auction started - // NOTE: 0 if this auction has been concluded - uint64 startedAt; - } - - // Reference to contract tracking NFT ownership - ERC721 public nonFungibleContract; - - // Cut owner takes on each auction, measured in basis points (1/100 of a percent). - // Values 0-10,000 map to 0%-100% - uint256 public ownerCut; - - // Map from token ID to their corresponding auction. - mapping (uint256 => Auction) tokenIdToAuction; - - event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); - event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); - event AuctionCancelled(uint256 tokenId); - - /// @dev Returns true if the claimant owns the token. - /// @param _claimant - Address claiming to own the token. - /// @param _tokenId - ID of token whose ownership to verify. - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return (nonFungibleContract.ownerOf(_tokenId) == _claimant); - } - - /// @dev Escrows the NFT, assigning ownership to this contract. - /// Throws if the escrow fails. - /// @param _owner - Current owner address of token to escrow. - /// @param _tokenId - ID of token whose approval to verify. - function _escrow(address _owner, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transferFrom(_owner, address(this), _tokenId); - } - - /// @dev Transfers an NFT owned by this contract to another address. - /// Returns true if the transfer succeeds. - /// @param _receiver - Address to transfer NFT to. - /// @param _tokenId - ID of token to transfer. - function _transfer(address _receiver, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transfer(_receiver, _tokenId); - } - - /// @dev Adds an auction to the list of open auctions. Also fires the - /// AuctionCreated event. - /// @param _tokenId The ID of the token to be put on auction. - /// @param _auction Auction to add. - function _addAuction(uint256 _tokenId, Auction memory _auction) internal { - // Require that all auctions have a duration of - // at least one minute. (Keeps our math from getting hairy!) - require(_auction.duration >= 1 minutes); - - tokenIdToAuction[_tokenId] = _auction; - - emit AuctionCreated( - uint256(_tokenId), - uint256(_auction.startingPrice), - uint256(_auction.endingPrice), - uint256(_auction.duration) - ); - } - - /// @dev Cancels an auction unconditionally. - function _cancelAuction(uint256 _tokenId, address _seller) internal { - _removeAuction(_tokenId); - _transfer(_seller, _tokenId); - emit AuctionCancelled(_tokenId); - } - - /// @dev Computes the price and transfers winnings. - /// Does NOT transfer ownership of token. - function _bid(uint256 _tokenId, uint256 _bidAmount) - internal - returns (uint256) - { - // Get a reference to the auction struct - Auction storage auction = tokenIdToAuction[_tokenId]; - - // Explicitly check that this auction is currently live. - // (Because of how Ethereum mappings work, we can't just count - // on the lookup above failing. An invalid _tokenId will just - // return an auction object that is all zeros.) - require(_isOnAuction(auction)); - - // Check that the bid is greater than or equal to the current price - uint256 price = _currentPrice(auction); - require(_bidAmount >= price); - - // Grab a reference to the seller before the auction struct - // gets deleted. - address payable seller = auction.seller; - - // The bid is good! Remove the auction before sending the fees - // to the sender so we can't have a reentrancy attack. - _removeAuction(_tokenId); - - // Transfer proceeds to seller (if there are any!) - if (price > 0) { - // Calculate the auctioneer's cut. - // (NOTE: _computeCut() is guaranteed to return a - // value <= price, so this subtraction can't go negative.) - uint256 auctioneerCut = _computeCut(price); - uint256 sellerProceeds = price - auctioneerCut; - - // NOTE: Doing a transfer() in the middle of a complex - // method like this is generally discouraged because of - // reentrancy attacks and DoS attacks if the seller is - // a contract with an invalid fallback function. We explicitly - // guard against reentrancy attacks by removing the auction - // before calling transfer(), and the only thing the seller - // can DoS is the sale of their own asset! (And if it's an - // accident, they can call cancelAuction(). ) - seller.transfer(sellerProceeds); - } - - // Calculate any excess funds included with the bid. If the excess - // is anything worth worrying about, transfer it back to bidder. - // NOTE: We checked above that the bid amount is greater than or - // equal to the price so this cannot underflow. - uint256 bidExcess = _bidAmount - price; - - // Return the funds. Similar to the previous transfer, this is - // not susceptible to a re-entry attack because the auction is - // removed before any transfers occur. - msg.sender.transfer(bidExcess); - - // Tell the world! - emit AuctionSuccessful(_tokenId, price, msg.sender); - - return price; - } - - /// @dev Removes an auction from the list of open auctions. - /// @param _tokenId - ID of NFT on auction. - function _removeAuction(uint256 _tokenId) internal { - delete tokenIdToAuction[_tokenId]; - } - - /// @dev Returns true if the NFT is on auction. - /// @param _auction - Auction to check. - function _isOnAuction(Auction storage _auction) internal view returns (bool) { - return (_auction.startedAt > 0); - } - - /// @dev Returns current price of an NFT on auction. Broken into two - /// functions (this one, that computes the duration from the auction - /// structure, and the other that does the price computation) so we - /// can easily test that the price computation works correctly. - function _currentPrice(Auction storage _auction) - internal - view - returns (uint256) - { - uint256 secondsPassed = 0; - - // A bit of insurance against negative values (or wraparound). - // Probably not necessary (since Ethereum guarnatees that the - // now variable doesn't ever go backwards). - if (now > _auction.startedAt) { - secondsPassed = now - _auction.startedAt; - } - - return _computeCurrentPrice( - _auction.startingPrice, - _auction.endingPrice, - _auction.duration, - secondsPassed - ); - } - - /// @dev Computes the current price of an auction. Factored out - /// from _currentPrice so we can run extensive unit tests. - /// When testing, make this function public and turn on - /// `Current price computation` test suite. - function _computeCurrentPrice( - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - uint256 _secondsPassed - ) - internal - pure - returns (uint256) - { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our public functions carefully cap the maximum values for - // time (at 64-bits) and currency (at 128-bits). _duration is - // also known to be non-zero (see the require() statement in - // _addAuction()) - if (_secondsPassed >= _duration) { - // We've reached the end of the dynamic pricing portion - // of the auction, just return the end price. - return _endingPrice; - } else { - // Starting price can be higher than ending price (and often is!), so - // this delta can be negative. - int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - - // This multiplication can't overflow, _secondsPassed will easily fit within - // 64-bits, and totalPriceChange will easily fit within 128-bits, their product - // will always fit within 256-bits. - int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - - // currentPriceChange can be negative, but if so, will have a magnitude - // less that _startingPrice. Thus, this result will always end up positive. - int256 currentPrice = int256(_startingPrice) + currentPriceChange; - - return uint256(currentPrice); - } - } - - /// @dev Computes owner's cut of a sale. - /// @param _price - Sale price of NFT. - function _computeCut(uint256 _price) internal view returns (uint256) { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our entry functions carefully cap the maximum values for - // currency (at 128-bits), and ownerCut <= 10000 (see the require() - // statement in the ClockAuction constructor). The result of this - // function is always guaranteed to be <= _price. - return _price * ownerCut / 10000; - } - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { - event Pause(); - event Unpause(); - - bool public paused = false; - - - /** - * @dev modifier to allow actions only when the contract IS paused - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev modifier to allow actions only when the contract IS NOT paused - */ - modifier whenPaused { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyOwner whenNotPaused public returns (bool) { - paused = true; - emit Pause(); - return true; - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyOwner whenPaused public returns (bool) { - paused = false; - emit Unpause(); - return true; - } -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - - /// @dev The ERC-165 interface signature for ERC-721. - /// Ref: https://github.com/ethereum/EIPs/issues/165 - /// Ref: https://github.com/ethereum/EIPs/issues/721 - bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - - /// @dev Constructor creates a reference to the NFT ownership contract - /// and verifies the owner cut is in the valid range. - /// @param _nftAddress - address of a deployed contract implementing - /// the Nonfungible Interface. - /// @param _cut - percent cut the owner takes on each auction, must be - /// between 0-10,000. - constructor(address _nftAddress, uint256 _cut) public { - require(_cut <= 10000); - ownerCut = _cut; - - ERC721 candidateContract = ERC721(_nftAddress); - require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); - nonFungibleContract = candidateContract; - } - - /// @dev Remove all Ether from the contract, which is the owner's cuts - /// as well as any Ether sent directly to the contract address. - /// Always transfers to the NFT contract, but can be called either by - /// the owner or the NFT contract. - function withdrawBalance() external { - address payable nftAddress = address(uint160(address(nonFungibleContract))); - - require( - msg.sender == owner || - msg.sender == nftAddress - ); - // We are using this boolean method to make sure that even if one fails it will still work - bool res = nftAddress.send(address(this).balance); - } - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of time to move between starting - /// price and ending price (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - whenNotPaused - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(_owns(msg.sender, _tokenId)); - _escrow(msg.sender, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Bids on an open auction, completing the auction and transferring - /// ownership of the NFT if enough Ether is supplied. - /// @param _tokenId - ID of token to bid on. - function bid(uint256 _tokenId) - external - payable - whenNotPaused - { - // _bid will throw if the bid or funds transfer fails - _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - } - - /// @dev Cancels an auction that hasn't been won yet. - /// Returns the NFT to original owner. - /// @notice This is a state-modifying function that can - /// be called while the contract is paused. - /// @param _tokenId - ID of token on auction - function cancelAuction(uint256 _tokenId) - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - address seller = auction.seller; - require(msg.sender == seller); - _cancelAuction(_tokenId, seller); - } - - /// @dev Cancels an auction when the contract is paused. - /// Only the owner may do this, and NFTs are returned to - /// the seller. This should only be used in emergencies. - /// @param _tokenId - ID of the NFT on auction to cancel. - function cancelAuctionWhenPaused(uint256 _tokenId) - whenPaused - onlyOwner - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - _cancelAuction(_tokenId, auction.seller); - } - - /// @dev Returns auction info for an NFT on auction. - /// @param _tokenId - ID of NFT on auction. - function getAuction(uint256 _tokenId) - external - view - returns - ( - address seller, - uint256 startingPrice, - uint256 endingPrice, - uint256 duration, - uint256 startedAt - ) { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return ( - auction.seller, - auction.startingPrice, - auction.endingPrice, - auction.duration, - auction.startedAt - ); - } - - /// @dev Returns the current price of an auction. - /// @param _tokenId - ID of the token price we are checking. - function getCurrentPrice(uint256 _tokenId) - external - view - returns (uint256) - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return _currentPrice(auction); - } - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSiringAuctionAddress() call. - bool public isSiringClockAuction = true; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. Since this function is wrapped, - /// require sender to be KittyCore contract. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Places a bid for siring. Requires the sender - /// is the KittyCore contract because all bid methods - /// should be wrapped. Also returns the kitty to the - /// seller rather than the winner. - function bid(uint256 _tokenId) - external - payable - { - require(msg.sender == address(nonFungibleContract)); - address seller = tokenIdToAuction[_tokenId].seller; - // _bid checks that token ID is valid and will throw if bid fails - _bid(_tokenId, msg.value); - // We transfer the kitty back to the seller, the winner will get - // the offspring - _transfer(seller, _tokenId); - } - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSaleAuctionAddress() call. - bool public isSaleClockAuction = true; - - // Tracks last 5 sale price of gen0 kitty sales - uint256 public gen0SaleCount; - uint256[5] public lastGen0SalePrices; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Updates lastSalePrice if seller is the nft contract - /// Otherwise, works the same as default bid method. - function bid(uint256 _tokenId) - external - payable - { - // _bid verifies token ID size - address seller = tokenIdToAuction[_tokenId].seller; - uint256 price = _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - - // If not a gen0 auction, exit - if (seller == address(nonFungibleContract)) { - // Track gen0 sale prices - lastGen0SalePrices[gen0SaleCount % 5] = price; - gen0SaleCount++; - } - } - - function averageGen0SalePrice() external view returns (uint256) { - uint256 sum = 0; - for (uint256 i = 0; i < 5; i++) { - sum += lastGen0SalePrices[i]; - } - return sum / 5; - } - -} - - - - - - - diff --git a/framework/src/test/resources/soliditycode/addressCheckNew.sol b/framework/src/test/resources/soliditycode/addressCheckNew.sol deleted file mode 100644 index 3c10b8c680d..00000000000 --- a/framework/src/test/resources/soliditycode/addressCheckNew.sol +++ /dev/null @@ -1,9 +0,0 @@ -pragma experimental ABIEncoderV2; -contract testIsContract{ - function checkAddress(address addr) public returns (address){ - return addr; - } - function checkAddress2(address addr) pure public returns(address){ - return addr; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/addressCheckOld.sol b/framework/src/test/resources/soliditycode/addressCheckOld.sol deleted file mode 100644 index 6c6b15d1736..00000000000 --- a/framework/src/test/resources/soliditycode/addressCheckOld.sol +++ /dev/null @@ -1,8 +0,0 @@ -contract testIsContract{ - function checkAddress(address addr) public returns (address){ - return addr; - } - function checkAddress2(address addr) pure public returns (address){ - return addr; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/altbn.sol b/framework/src/test/resources/soliditycode/altbn.sol deleted file mode 100644 index c3cfcdbe2b9..00000000000 --- a/framework/src/test/resources/soliditycode/altbn.sol +++ /dev/null @@ -1,61 +0,0 @@ -contract AltBn128 { - constructor() public payable {} - function callBn256Add(bytes32 ax, bytes32 ay, bytes32 bx, bytes32 by) public returns (bytes32[2] memory result) { - bytes32[4] memory input; - input[0] = ax; - input[1] = ay; - input[2] = bx; - input[3] = by; - assembly { - let success := call(gas(), 0x06, 0, input, 0x80, result, 0x40) - } - - } - - function callBn256AddNoValue(bytes32 ax, bytes32 ay, bytes32 bx, bytes32 by) public returns - (bytes32[2] memory result) { - bytes32[4] memory input; - input[0] = ax; - input[1] = ay; - input[2] = bx; - input[3] = by; - assembly { - let success := call(gas(), 0xac, 0, input, 0x80, result, 0x40) - } - } - - function callBn256ScalarMul(bytes32 x, bytes32 y, bytes32 scalar) public returns (bytes32[2] memory result) { - bytes32[3] memory input; - input[0] = x; - input[1] = y; - input[2] = scalar; - assembly { - let success := call(gas(), 0x07, 0, input, 0x60, result, 0x40) - switch success - case 0 { - revert(0,0) - } - } - } - - function callBn256Pairing(bytes memory input) public returns (bytes32 result) { - // input is a serialized bytes stream of (a1, b1, a2, b2, ..., ak, bk) from (G_1 x G_2)^k - uint256 len = input.length; - require(len % 192 == 0); - assembly { - let memPtr := mload(0x40) - let success := call(gas(), 0x08, 0, add(input, 0x20), len, memPtr, 0x20) - switch success - case 0 { - revert(0,0) - } default { - result := mload(memPtr) - } - } - } - - function convert(uint256 num) public view returns(bytes32) { - return bytes32(num); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/arrayLength001.sol b/framework/src/test/resources/soliditycode/arrayLength001.sol deleted file mode 100644 index 81a779f059d..00000000000 --- a/framework/src/test/resources/soliditycode/arrayLength001.sol +++ /dev/null @@ -1,64 +0,0 @@ - - -contract arrayLength { - bytes1[] a; - uint256[] IntergerArray; - bytes bs; - - // arrary length - function arrayPushValue() public returns (bytes1[] memory){ - a = new bytes1[](1); - a.push(0x01); - return a; - } - - function arrayPush() public returns(bytes1[] memory){ - a = new bytes1[](1); - a.push(); - return a; - } - - function arrayPop() public returns(bytes1[] memory){ - a = new bytes1[](1); - a.pop(); - return a; - } - - // arrary push/pop return Value - function arrayPushValueReturn() public { - a = new bytes1[](1); - return a.push(0x01); - } - - function arrayPushReturn() public returns (bytes1){ - a = new bytes1[](1); - return a.push(); - } - - function arrayPopReturn() public{ - a = new bytes1[](1); - return a.pop(); - } - - function uint256ArrayPushValue() public returns (bytes1[] memory){ - IntergerArray = [1,2,3]; - IntergerArray.push(); - return a; - } - - - // bytes - function bytesPushValue() public { - - return bs.push(0x01); - } - - function bytesPush() public returns (bytes1){ - return bs.push(); - } - - function bytesPop() public { - return bs.pop(); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/assemblyTest.sol b/framework/src/test/resources/soliditycode/assemblyTest.sol deleted file mode 100644 index 519a5a85fa3..00000000000 --- a/framework/src/test/resources/soliditycode/assemblyTest.sol +++ /dev/null @@ -1,61 +0,0 @@ - -contract assemblyTest { - - uint constant x = 1; - uint constant y = x; - function getZuint() public view returns (uint) { - uint z = y + 1; - assembly { - z := y - } - return z; - } - - function getZuint2() public returns (uint) { - uint z = y + 1; - assembly { - z := y - } - return z; - } - - bool constant bool1 = true; - bool constant bool2 = bool1; - function getZbool() public view returns (bool) { - bool z; - assembly { - z := bool2 - } - return z; - } - - function getZbool2() public returns (bool) { - bool z; - assembly { - z := bool2 - } - return z; - } - - -// string constant string1 = "abc"; -// string constant string2 = string1; -// function getZstring() public view returns (string memory) { -// string memory z; -// assembly { -// z := string2 -// } -// return z; -// } - - -// address origin1 = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; -// address origin2 = origin1; -// function getZaddress() public view returns (address) { -// address z; -// assembly { -// z := origin2 -// } -// return z; -// } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/assertExceptiontest1DivideInt.sol b/framework/src/test/resources/soliditycode/assertExceptiontest1DivideInt.sol deleted file mode 100644 index 92778e42bc9..00000000000 --- a/framework/src/test/resources/soliditycode/assertExceptiontest1DivideInt.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/assertExceptiontest2FindArgsContractMinTest.sol b/framework/src/test/resources/soliditycode/assertExceptiontest2FindArgsContractMinTest.sol deleted file mode 100644 index 75436287805..00000000000 --- a/framework/src/test/resources/soliditycode/assertExceptiontest2FindArgsContractMinTest.sol +++ /dev/null @@ -1,10 +0,0 @@ - -contract findArgsIContract{ -function findArgsByIndex1(uint i) public returns (uint z) { -uint[] memory a = new uint[](3); -a[0]=1; -a[1]=2; -a[2]=3; -return a[i]; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/assertExceptiontest3ByteMinContract.sol b/framework/src/test/resources/soliditycode/assertExceptiontest3ByteMinContract.sol deleted file mode 100644 index c8a2e5e363b..00000000000 --- a/framework/src/test/resources/soliditycode/assertExceptiontest3ByteMinContract.sol +++ /dev/null @@ -1,11 +0,0 @@ - -contract byteContract{ -bytes b; -function testBytesGet(uint i) public returns (bytes1){ -b = new bytes(3); -b[0]=0x0b; -b[1]=0x0c; -b[2]=0x0d; -return b[i]; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/assertExceptiontest4Enum.sol b/framework/src/test/resources/soliditycode/assertExceptiontest4Enum.sol deleted file mode 100644 index 6bd2ade2eea..00000000000 --- a/framework/src/test/resources/soliditycode/assertExceptiontest4Enum.sol +++ /dev/null @@ -1,13 +0,0 @@ - - -contract enumContract { - enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } - ActionChoices _choice; - function setGoStraight(ActionChoices choice) public { - _choice = choice; - } - - function getChoice() public returns (ActionChoices) { - return _choice; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/assertExceptiontest5MoveRight.sol b/framework/src/test/resources/soliditycode/assertExceptiontest5MoveRight.sol deleted file mode 100644 index ad8f6f0f173..00000000000 --- a/framework/src/test/resources/soliditycode/assertExceptiontest5MoveRight.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract binaryRightContract{ - function binaryMoveR(uint i)public returns (uint z) { - return z = 5 >> i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/assertExceptiontest6UninitializedContract.sol b/framework/src/test/resources/soliditycode/assertExceptiontest6UninitializedContract.sol deleted file mode 100644 index c82e0f5806c..00000000000 --- a/framework/src/test/resources/soliditycode/assertExceptiontest6UninitializedContract.sol +++ /dev/null @@ -1,27 +0,0 @@ - -contract uni { -function b(int x, int y) internal returns (int) -{ - return x * y; -} - -function test1() external returns (int) -{ - // Variable containing a function pointer - function (int, int) internal returns (int) funcPtr; - - funcPtr = b; - - // This call to funcPtr will succeed - return funcPtr(4, 5); -} - -function test2() external returns (int) -{ - // Variable containing a function pointer - function (int, int) internal returns (int) funcPtr; - - // This call will fail because funcPtr is still a zero-initialized function pointer - return funcPtr(4, 5); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/assertExceptiontest7TestAssertContract.sol b/framework/src/test/resources/soliditycode/assertExceptiontest7TestAssertContract.sol deleted file mode 100644 index 05b592e0682..00000000000 --- a/framework/src/test/resources/soliditycode/assertExceptiontest7TestAssertContract.sol +++ /dev/null @@ -1,14 +0,0 @@ -contract TestThrowsContract{ - function testAssert() public{ - assert(1==2); - } - function testRequire() public{ - require(2==1); - } - function testRevert() public{ - revert(); - } - function testThrow() public{ - revert(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/batchvalidatesign.sol b/framework/src/test/resources/soliditycode/batchvalidatesign.sol deleted file mode 100644 index 9e1c1b289b5..00000000000 --- a/framework/src/test/resources/soliditycode/batchvalidatesign.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - - function testArray2(bytes memory data) public returns(bool, bytes memory){ - return address(0x9).delegatecall(data); - } - - function testArray4(bytes memory data) public { - //address(0x1).delegatecall(data); - } - //function testArray3(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public { - //address(0x9).delegatecall(hash,signatures,addresses); - //} -} diff --git a/framework/src/test/resources/soliditycode/batchvalidatesign001.sol b/framework/src/test/resources/soliditycode/batchvalidatesign001.sol deleted file mode 100644 index 57e051ce415..00000000000 --- a/framework/src/test/resources/soliditycode/batchvalidatesign001.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - function testPure(bytes32 hash, bytes[] memory signatures, address[] memory addresses) pure public returns(bytes32){ - return batchvalidatesign(hash, signatures, addresses); - } - - function testArray(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public returns(bytes32){ - return batchvalidatesign(hash, signatures, addresses); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/batchvalidatesign002.sol b/framework/src/test/resources/soliditycode/batchvalidatesign002.sol deleted file mode 100644 index 375cec3a2a2..00000000000 --- a/framework/src/test/resources/soliditycode/batchvalidatesign002.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - function testArray(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public returns(bytes32){ - - return batchvalidatesign(hash, signatures, addresses); - - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/batchvalidatesign003.sol b/framework/src/test/resources/soliditycode/batchvalidatesign003.sol deleted file mode 100644 index c43536af499..00000000000 --- a/framework/src/test/resources/soliditycode/batchvalidatesign003.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract Demo { -bytes32 public result; -constructor (bytes32 hash, bytes[] memory signatures, address[] memory addresses) public { - result = batchvalidatesign(hash, signatures, addresses); -} -function testConstructor() public returns(bytes32){ - return result; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/batchvalidatesign005.sol b/framework/src/test/resources/soliditycode/batchvalidatesign005.sol deleted file mode 100644 index 3a6ca362973..00000000000 --- a/framework/src/test/resources/soliditycode/batchvalidatesign005.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - - function testArray2(bytes memory data) public returns(bool, bytes memory){ - return address(0x9).delegatecall(data); - } - - function testArray4(bytes memory data) public { - //address(0x1).delegatecall(data); - } - function testArray3(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public { - //address(0x9).delegatecall(hash,signatures,addresses); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/batchvalidatesign007.sol b/framework/src/test/resources/soliditycode/batchvalidatesign007.sol deleted file mode 100644 index 974ffb34efe..00000000000 --- a/framework/src/test/resources/soliditycode/batchvalidatesign007.sol +++ /dev/null @@ -1,17 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract Demo { - bytes32 public result; - - constructor (bytes32 hash, bytes[] memory signatures, address[] memory addresses) public { - result = batchvalidatesign(hash, signatures, addresses); - } - - function testConstructor() public returns(bytes32){ - return result; - } - - function testConstructorPure() public view returns(bytes32){ - return result; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/batchvalidatesign02.sol b/framework/src/test/resources/soliditycode/batchvalidatesign02.sol deleted file mode 100644 index 375cec3a2a2..00000000000 --- a/framework/src/test/resources/soliditycode/batchvalidatesign02.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - function testArray(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public returns(bytes32){ - - return batchvalidatesign(hash, signatures, addresses); - - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/callValueGasPure.sol b/framework/src/test/resources/soliditycode/callValueGasPure.sol deleted file mode 100644 index 6aab49bab84..00000000000 --- a/framework/src/test/resources/soliditycode/callValueGasPure.sol +++ /dev/null @@ -1,8 +0,0 @@ - -contract C { -function check(address a) external pure returns (bool success) { - a.call{value:42,gas:42}; - a.call{gas:42}; - //a.call.value(1).gas(42)("fwefewf"); -} -} diff --git a/framework/src/test/resources/soliditycode/calldata.sol b/framework/src/test/resources/soliditycode/calldata.sol deleted file mode 100644 index 6e877ac1b2f..00000000000 --- a/framework/src/test/resources/soliditycode/calldata.sol +++ /dev/null @@ -1,33 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract C { - struct S { uint256 a; } - - function f(S calldata s) external returns (bytes memory) { - return abi.encode(s); - } - - function g(S calldata s) external returns (bytes memory) { - return this.f(s); - } - - function m(uint256[] calldata) external pure returns (bytes memory) { - return msg.data; - } - function h(uint8[] calldata s) external pure returns (bytes memory) { - return abi.encode(s); - } - function i(uint8[][2] calldata s, uint256 which) external view returns (bytes memory) { - return this.h(s[which]); - } - function j(bytes calldata s) external pure returns (bytes memory) { - return abi.encode(s); - } - function k(bytes[2] calldata s, uint256 which) external view returns (bytes memory) { - return this.j(s[which]); - } - function l(function() external returns (uint)[] calldata s) external returns (uint, uint, uint) { - assert(s.length == 3); - return (s[0](), s[1](), s[2]()); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/callvalue.sol b/framework/src/test/resources/soliditycode/callvalue.sol deleted file mode 100644 index f01dcf2b52f..00000000000 --- a/framework/src/test/resources/soliditycode/callvalue.sol +++ /dev/null @@ -1,9 +0,0 @@ -contract Callvalue { -function check() public payable returns(uint) { - uint256 wad; - assembly { - wad := callvalue() - } - return wad; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/chainid001.sol b/framework/src/test/resources/soliditycode/chainid001.sol deleted file mode 100644 index 9cf24077dfb..00000000000 --- a/framework/src/test/resources/soliditycode/chainid001.sol +++ /dev/null @@ -1,19 +0,0 @@ - -contract IstanbulTest { - constructor() public payable {} - function getId() public view returns(uint256){ - uint256 id; - assembly { - id := chainid() - } - return id; - } - - function getBalance(address src) public view returns(uint256){ - return address(src).balance; - } - - function getBalance() public view returns(uint256){ - return address(this).balance; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/codeSaftySupport.sol b/framework/src/test/resources/soliditycode/codeSaftySupport.sol deleted file mode 100644 index 1cee8e4646c..00000000000 --- a/framework/src/test/resources/soliditycode/codeSaftySupport.sol +++ /dev/null @@ -1,19 +0,0 @@ - - -contract IllegalDecorate { - -constructor() payable public{} - -fallback() payable external{} - -event log(uint256); - -function transferToken(address payable toAddress, uint256 tokenValue) public payable { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/codeSaftyUnsupport.sol b/framework/src/test/resources/soliditycode/codeSaftyUnsupport.sol deleted file mode 100644 index fa65a134001..00000000000 --- a/framework/src/test/resources/soliditycode/codeSaftyUnsupport.sol +++ /dev/null @@ -1,56 +0,0 @@ - - -contract SubC { - -event log(string); - -fallback() payable external{} - -function receiveToken() payable public{} - -function getBalance() view public returns (uint256 r) { -r = address(this).balance; -} -} - -contract UseDot { -constructor() payable public{} -fallback() payable external{} -mapping(address => mapping(trcToken => uint256)) sender_tokens; - -function trigger1(address payable addr, trcToken tokenInputId) payable public { - //address(SubC(addr)).call.value(1000).tokenId(tokenInputId)(abi.encodeWithSignature("receiveToken()")); // ERROR -} - -function trigger2(address payable addr) payable public { -// addr.transferToken.value(10)(10, 0x6e6d62); // ERROR -} - -function trigger3(address payable addr) payable public { - // address(SubC(addr)).receiveToken.tokenvalue(10)(); // ERROR -} - -function trigger4(address payable addr) payable public { - //SubC(addr).receiveToken.tokenId(0x6e6d62)(); // ERROR -} - -function trigger5(address payable addr) payable public { - SubC(addr).receiveToken{value:10}(); -} - -function trigger6(address payable addr, trcToken tokenId) payable public { -address(SubC(addr)).call{value:1000}(abi.encodeWithSignature("transferToken(uint256, trcToken)", 10, tokenId)); -} - -function trigger7(address addr) payable public { - //sender_tokens[msg.sender][msg.tokenid] += msg.tokenvalue; // compile success, no necessary to trigger -} - -function trigger8(address addr) public payable returns(bytes memory r){ -// r = msg.data; // compile success, no necessary to trigger -} - -function getBalance() public returns (uint256 r){ -r = address(this).balance; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/constantCallStorage001.sol b/framework/src/test/resources/soliditycode/constantCallStorage001.sol deleted file mode 100644 index 1f584923a55..00000000000 --- a/framework/src/test/resources/soliditycode/constantCallStorage001.sol +++ /dev/null @@ -1,159 +0,0 @@ -contract NotView { - uint256 public num = 123; - function setnum() public returns(uint256){ - num = num + 15; - return num; - } -} -contract NotViewInterface{ - function setnum() public returns(uint256); -} -contract UseNotView { - function setnumuseproxy(address contractAddress) public returns(uint256){ - NotViewInterface inter = NotViewInterface(contractAddress); - return inter.setnum(); - } -} -contract viewCall { - bool stopped = false; - int i = 32482989; - int i2 = -32482989; - uint ui = 23487823; - address origin = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; - bytes32 b32 = bytes32(uint256(0xdCad3a6d3569DF655070DEd0)); - bytes bs = new bytes(3); - string s = "123qwe"; - enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } - ActionChoices choice = ActionChoices.GoRight; - int64[] b = [-1, 2, -3]; - int32[2][] tmp_h = [[1,2],[3,4],[5,6]]; - int256[2][2] tmp_i = [[11,22],[33,44]]; - mapping (address => uint256) public mapa; - constructor() payable public{ - mapa[address(0x00)] = 34; - } - event log(int); - event log(uint); - event log(bool); - event log(address); - event log(bytes32); - event log(bytes); - event log(string); - event log(ActionChoices); - event log(int64[]); - event log(int32[2][]); - event log(int256[2][2]); - function changeBool(bool param) public returns (bool){ - stopped = param; - emit log(stopped); - return stopped; - } - function getBool() public returns (bool){ - emit log(stopped); - return stopped; - } - function changeInt(int param) public returns (int){ - i = param; - emit log(i); - return i; - } - function getInt() public returns (int){ - emit log(i); - return i; - } - function changeNegativeInt(int param) public returns (int){ - i2 = param; - emit log(i2); - return i2; - } - function getNegativeInt() public returns (int){ - emit log(i2); - return i2; - } - function changeUint(uint param) public returns (uint){ - ui = param; - emit log(ui); - return ui; - } - function getUint() public returns (uint){ - emit log(ui); - return ui; - } - function changeAddress(address param) public returns (address){ - origin = param; - emit log(origin); - return origin; - } - function getAddress() public returns (address){ - emit log(origin); - return origin; - } - function changeBytes32(bytes32 param) public returns (bytes32){ - b32 = param; - emit log(b32); - return b32; - } - function getBytes32() public returns (bytes32){ - emit log(b32); - return b32; - } - function changeBytes(bytes memory param) public returns (bytes memory){ - bs = param; - emit log(bs); - return bs; - } - function getBytes() public returns (bytes memory){ - emit log(bs); - return bs; - } - function changeString(string memory param) public returns (string memory){ - s = param; - emit log(s); - return s; - } - function getString() public returns (string memory){ - emit log(s); - return s; - } - function changeActionChoices(ActionChoices param) public returns (ActionChoices){ - choice = param; - emit log(choice); - return choice; - } - function getActionChoices() public returns (ActionChoices){ - emit log(choice); - return choice; - } - function changeInt64NegativeArray(int64[] memory param) public returns (int64[] memory){ - b = param; - emit log(b); - return b; - } - function getInt64NegativeArray() public returns (int64[] memory){ - emit log(b); - return b; - } - function changeInt32Array(int32[2][] memory param) public returns (int32[2][] memory){ - tmp_h = param; - emit log(tmp_h); - return tmp_h; - } - function getInt32Array() public returns (int32[2][] memory){ - emit log(tmp_h); - return tmp_h; - } - function changeInt256Array(int256[2][2] memory param) public returns (int256[2][2] memory){ - tmp_i = param; - emit log(tmp_i); - return tmp_i; - } - function getInt256Array() public returns (int256[2][2] memory){ - emit log(tmp_i); - return tmp_i; - } - function setMapping(uint256 param) public returns (uint256){ - mapa[msg.sender] = param; - return mapa[msg.sender]; - - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/constantCallStorage002.sol b/framework/src/test/resources/soliditycode/constantCallStorage002.sol deleted file mode 100644 index 1ceba5e87d2..00000000000 --- a/framework/src/test/resources/soliditycode/constantCallStorage002.sol +++ /dev/null @@ -1,16 +0,0 @@ -contract NotView { - uint256 public num = 123; - function setnum() public returns(uint256){ - num = num + 15; - return num; - } -} -contract NotViewInterface{ - function setnum() public view returns(uint256); -} -contract UseNotView { - function setnumuseproxy(address contractAddress) public view returns(uint256){ - NotViewInterface inter = NotViewInterface(contractAddress); - return inter.setnum(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/constantCallStorage0425.sol b/framework/src/test/resources/soliditycode/constantCallStorage0425.sol deleted file mode 100644 index 8ecf771626d..00000000000 --- a/framework/src/test/resources/soliditycode/constantCallStorage0425.sol +++ /dev/null @@ -1,156 +0,0 @@ -contract constantCall { - bool stopped = false; - int i = 32482989; - int i2 = -32482989; - uint ui = 23487823; - address origin = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; - bytes32 b32 = 0xb55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105c; - bytes bs = new bytes(9); - string s = "123qwe"; - enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } - ActionChoices choice = ActionChoices.SitStill; - int64[] b = [91, 2, 333]; - int32[2][] tmp_h = [[1,2],[3,4],[5,6]]; - int256[2][2] tmp_i = [[11,22],[33,44]]; - mapping (address => uint256) public mapa; - - constructor() payable public{ - mapa[address(0x00)] = 88; - } - event log(int); - event log(uint); - event log(bool); - event log(address); - event log(bytes32); - event log(bytes); - event log(string); - event log(ActionChoices); - event log(int64[]); - event log(int32[2][]); - event log(int256[2][2]); - - function changeBool(bool param) public constant returns (bool){ - stopped = param; - log(stopped); - return stopped; - } - function getBool() public constant returns (bool){ - log(stopped); - return stopped; - } - - function changeInt(int param) public returns (int){ - i = param; - log(i); - return i; - } - function getInt() public returns (int){ - log(i); - return i; - } - - function changeNegativeInt(int param) public constant returns (int){ - i2 = param; - log(i2); - return i2; - } - function getNegativeInt() public constant returns (int){ - log(i2); - return i2; - } - - function changeUint(uint param) public returns (uint){ - ui = param; - log(ui); - return ui; - } - function getUint() public returns (uint){ - log(ui); - return ui; - } - - function changeAddress(address param) public constant returns (address){ - origin = param; - log(origin); - return origin; - } - function getAddress() public constant returns (address){ - log(origin); - return origin; - } - - function changeBytes32(bytes32 param) public constant returns (bytes32){ - b32 = param; - log(b32); - return b32; - } - function getBytes32() public returns (bytes32){ - log(b32); - return b32; - } - - function changeBytes(bytes param) public constant returns (bytes){ - bs = param; - log(bs); - return bs; - } - function getBytes() public constant returns (bytes){ - log(bs); - return bs; - } - - function changeString(string param) public constant returns (string){ - s = param; - log(s); - return s; - } - function getString() public returns (string){ - log(s); - return s; - } - - function changeActionChoices(ActionChoices param) public constant returns (ActionChoices){ - choice = param; - log(choice); - return choice; - } - function getActionChoices() public constant returns (ActionChoices){ - log(choice); - return choice; - } - - function changeInt64NegativeArray(int64[] param) public constant returns (int64[]){ - b = param; - log(b); - return b; - } - function getInt64NegativeArray() public constant returns (int64[]){ - log(b); - return b; - } - - function changeInt32Array(int32[2][] param) public returns (int32[2][]){ - tmp_h = param; - log(tmp_h); - return tmp_h; - } - function getInt32Array() public constant returns (int32[2][]){ - log(tmp_h); - return tmp_h; - } - - function changeInt256Array(int256[2][2] param) public returns (int256[2][2]){ - tmp_i = param; - log(tmp_i); - return tmp_i; - } - function getInt256Array() public constant returns (int256[2][2]){ - log(tmp_i); - return tmp_i; - } - function setMapping(uint256 param) public returns (uint256){ - mapa[msg.sender] = param; - return mapa[msg.sender]; - - } -} diff --git a/framework/src/test/resources/soliditycode/constantContract001.sol b/framework/src/test/resources/soliditycode/constantContract001.sol deleted file mode 100644 index 7d574c5a008..00000000000 --- a/framework/src/test/resources/soliditycode/constantContract001.sol +++ /dev/null @@ -1,8 +0,0 @@ - - -contract testConstantContract{ -function testPure(uint256 x,uint256 y) public pure returns (uint256 z) { -uint256 i=1; -return i + x + y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGetterContract.sol b/framework/src/test/resources/soliditycode/contractGetterContract.sol deleted file mode 100644 index 365b53ebf1a..00000000000 --- a/framework/src/test/resources/soliditycode/contractGetterContract.sol +++ /dev/null @@ -1,17 +0,0 @@ - - - -contract getterContract { - -constructor() public payable{} -fallback() external payable{} - -uint public c = msg.value; - -function getDataUsingAccessor() public payable returns (uint){ - -return c; - -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGrammar001test1Grammar001.sol b/framework/src/test/resources/soliditycode/contractGrammar001test1Grammar001.sol deleted file mode 100644 index 659e56c9150..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar001test1Grammar001.sol +++ /dev/null @@ -1,18 +0,0 @@ - -contract FunctionSelector { - function select(bool useB, uint x) public returns (uint z) { - //var f = a; - //if (useB) f = b; - //return f(x); - if (useB) - return b(x); - else - return a(x); - } -function a(uint x) public returns (uint z) { - return x * x; - } -function b(uint x) public returns (uint z) { - return 2 * x; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGrammar001test2Grammar002.sol b/framework/src/test/resources/soliditycode/contractGrammar001test2Grammar002.sol deleted file mode 100644 index 744b17e9585..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar001test2Grammar002.sol +++ /dev/null @@ -1,44 +0,0 @@ - -library Set { - // We define a new struct datatype that will be used to - // hold its data in the calling contract. - struct Data { mapping(uint => bool) flags; } - - // Note that the first parameter is of type "storage - // reference" and thus only its storage address and not - // its contents is passed as part of the call. This is a - // special feature of library functions. It is idiomatic - // to call the first parameter 'self', if the function can - // be seen as a method of that object. - function insert(Data storage self, uint value) public returns (bool) { - if (self.flags[value]) - return false; // already there - self.flags[value] = true; - return true; - } - - function remove(Data storage self, uint value) public returns (bool) { - if (!self.flags[value]) - return false; // not there - self.flags[value] = false; - return true; - } - - function contains(Data storage self, uint value) public returns (bool) { - return self.flags[value]; - } -} - - -contract C { - Set.Data knownValues; - - function register (uint value) public{ - // The library functions can be called without a - // specific instance of the library, since the - // "instance" will be the current contract. - if (!Set.insert(knownValues, value)) - revert(); - } - // In this contract, we can also directly access knownValues.flags, if we want. -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGrammar001test3Grammar003.sol b/framework/src/test/resources/soliditycode/contractGrammar001test3Grammar003.sol deleted file mode 100644 index 140ba2a8f56..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar001test3Grammar003.sol +++ /dev/null @@ -1,44 +0,0 @@ - - -library Set { - struct Data { mapping(uint => bool) flags; } - - function insert(Data storage self, uint value) public - returns (bool) - { - if (self.flags[value]) - return false; // already there - self.flags[value] = true; - return true; - } - - function remove(Data storage self, uint value) public - returns (bool) - { - if (!self.flags[value]) - return false; // not there - self.flags[value] = false; - return true; - } - - function contains(Data storage self, uint value) public - returns (bool) - { - return self.flags[value]; - } -} - - -contract C { - using Set for Set.Data; // this is the crucial change - Set.Data knownValues; - - function register(uint value) public{ - // Here, all variables of type Set.Data have - // corresponding member functions. - // The following function call is identical to - // Set.insert(knownValues, value) - if (!knownValues.insert(value)) - revert(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGrammar001test4Grammar004.sol b/framework/src/test/resources/soliditycode/contractGrammar001test4Grammar004.sol deleted file mode 100644 index bd7ffbc8360..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar001test4Grammar004.sol +++ /dev/null @@ -1,31 +0,0 @@ - - -library Search { - function indexOf(uint[] storage self, uint value) public returns (uint) { - for (uint i = 0; i < self.length; i++) - if (self[i] == value) return i; - return uint(int256(-1)); - } -} - - -contract C { - using Search for uint[]; - uint[] public data; - - function append(uint value) public{ - data.push(value); - } - - function replace(uint _old, uint _new) public{ - // This performs the library function call - uint index = data.indexOf(_old); - if (index == uint(int256(-1))) - data.push(_new); - else - data[index] = _new; - } - function getData(uint256 index) public returns(uint256){ - return data[index]; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGrammar001test5Grammar006.sol b/framework/src/test/resources/soliditycode/contractGrammar001test5Grammar006.sol deleted file mode 100644 index 275d42d1e71..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar001test5Grammar006.sol +++ /dev/null @@ -1,45 +0,0 @@ -contract InfoFeed { -function d1(uint x1) public{ - - assembly{ - function f(x) -> y { switch x case 0 { y := 1 } default { y := mul(x, f(sub(x, 1))) } } - } - } - function d2(uint x1) public{ - assembly { - let x:=1 - x := mul(1, add(2, 3))} - } - function f(uint x) public{ - assembly { x := sub(x, 1) } - - } - // 0.6.0 Variable declarations cannot shadow declarations outside the assembly block. - function d(uint x1) public returns(uint256){ - uint256 x; - assembly{ - x := add(2, 3) - let y := mload(0x40) - x := add(x, y) - } - return x; - } - function d4(uint x) public{ - // Error: The labels 'repeat' is disallowed. Please use "if", "switch", "for" or function calls instead - //assembly{let x := 10 repeat: x := sub(x, 1) jumpi(repeat, eq(x, 0)) - x = x; - //} - } - function d5(uint x1) public{ - assembly{ - function f(x) -> y { switch x case 0 { y := mul(x, 2) } default { y := 0 } } - - } - } - - function d6(uint x1) public{ - assembly{ - function f(x) -> y { for { let i := 0 } lt(i, x) { i := add(i, 1) } { y := mul(2, y) } } - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGrammar002test1Grammar007_1.sol b/framework/src/test/resources/soliditycode/contractGrammar002test1Grammar007_1.sol deleted file mode 100644 index 020c2a38ca4..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar002test1Grammar007_1.sol +++ /dev/null @@ -1,60 +0,0 @@ -contract Doug{ - mapping (bytes32 => uint) public contracts; - constructor() public{ - contracts['hww'] = 1; - contracts['brian'] = 2; - contracts['zzy'] = 7; - } - - function getDougName(string memory _name) public view returns(string memory) { - return _name; - } - - function getDougAge(uint _age) public pure returns(uint) { - return 3 ** _age; - } -} - -// -abstract contract DogInterface { - function getDougAge(uint _age) public virtual returns (uint); - function contracts(bytes32 name) public virtual returns (uint); -} -contract main{ - - event FetchContract(address dogInterfaceAddress, address sender, bytes32 name); - - address public DOUG; - - address dogInterfaceAddress; - DogInterface dogContract ; - - function setDOUG(address _doug) public { - DOUG = _doug; - } - - constructor(address addr) public{ - dogInterfaceAddress = addr; - dogContract = DogInterface(dogInterfaceAddress); - } - - function dougOfage(uint _age) public returns(uint) { - - uint num = dogContract.getDougAge(_age); - return _age+num; - // return num; - } - - function uintOfName(bytes32 _name) public returns (uint) { - - dogContract.contracts(_name); - emit FetchContract(dogInterfaceAddress, msg.sender, _name); - - } - - // function getTest(string _name) public view returns(string) { - // string memory newName = _name ; - // DogInterface(DOUG).getDougName(newName); - // return newName; - // } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGrammar002test1Grammar007_2.sol b/framework/src/test/resources/soliditycode/contractGrammar002test1Grammar007_2.sol deleted file mode 100644 index 8945b566543..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar002test1Grammar007_2.sol +++ /dev/null @@ -1,60 +0,0 @@ - -contract Doug{ - mapping (bytes32 => uint) public contracts; - constructor() public{ - contracts['hww'] = 1; - contracts['brian'] = 2; - contracts['zzy'] = 7; - } - - function getDougName(string memory _name) public view returns(string memory) { - return _name; - } - - function getDougAge(uint _age) public pure returns(uint) { - return 3 ** _age; - } -} - -abstract contract DogInterface { - function getDougAge(uint _age) public virtual returns (uint); - function contracts(bytes32 name) public virtual returns (uint); -} -contract main{ - - event FetchContract(address dogInterfaceAddress, address sender, bytes32 name); - - address public DOUG; - - address dogInterfaceAddress; - DogInterface dogContract ; - - function setDOUG(address _doug) public { - DOUG = _doug; - } - - constructor(address addr) public{ - dogInterfaceAddress = addr; - dogContract = DogInterface(dogInterfaceAddress); - } - - function dougOfage(uint _age) public returns(uint) { - - uint num = dogContract.getDougAge(_age); - return _age+num; - // return num; - } - - function uintOfName(bytes32 _name) public returns (uint) { - - dogContract.contracts(_name); - emit FetchContract(dogInterfaceAddress, msg.sender, _name); - - } - - // function getTest(string _name) public view returns(string) { - // string memory newName = _name ; - // DogInterface(DOUG).getDougName(newName); - // return newName; - // } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGrammar002test2Grammar008.sol b/framework/src/test/resources/soliditycode/contractGrammar002test2Grammar008.sol deleted file mode 100644 index 956623c3103..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar002test2Grammar008.sol +++ /dev/null @@ -1,18 +0,0 @@ - - -// version 0.6.0 change -// add abstract and override -abstract contract Feline { - - function utterance() public virtual returns (bytes32); - - function getContractName() public returns (string memory){ - return "Feline"; - } -} - - -contract Cat is Feline { - function utterance() public override returns (bytes32) { return "miaow"; } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGrammar002test3Grammar010.sol b/framework/src/test/resources/soliditycode/contractGrammar002test3Grammar010.sol deleted file mode 100644 index 617f96cb4e5..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar002test3Grammar010.sol +++ /dev/null @@ -1,10 +0,0 @@ - -contract InfoFeed { -function info() public payable returns (uint ret) { return 42; } -} -contract Consumer { -constructor() payable public{} -InfoFeed feed; -function setFeed(address addr) public { feed = InfoFeed(addr); } -function callFeed() public payable { feed.info{value:10,gas:800}(); } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGrammar002test4Grammar011.sol b/framework/src/test/resources/soliditycode/contractGrammar002test4Grammar011.sol deleted file mode 100644 index fcd18f438ef..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar002test4Grammar011.sol +++ /dev/null @@ -1,11 +0,0 @@ - -contract C { -function f(uint key, uint value) public returns(uint) { -return key; -// do something -} -function g() public { -// named arguments -f({value: 2, key: 3}); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGrammar002test4Grammar012.sol b/framework/src/test/resources/soliditycode/contractGrammar002test4Grammar012.sol deleted file mode 100644 index cb81d8810cd..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar002test4Grammar012.sol +++ /dev/null @@ -1,24 +0,0 @@ - -contract rTest { -function info() public payable returns (uint,address,bytes4,uint,uint,uint,address,uint) { -//function info() public payable returns (address ,uint,uint,uint,bytes32,uint,bytes,uint,address,bytes4,uint,uint,uint,address,uint) { -//var a = block.coinbase ; -//var b = block.difficulty; -//var c = block.gaslimit; -//var d = block.number; -//var e = block.blockhash(0); -//var e = d; -//var f = block.timestamp; -//bytes memory g = msg.data; -uint256 h = gasleft(); -address payable i = payable(msg.sender); -bytes4 j = msg.sig; -uint256 k = msg.value; -uint256 l = block.timestamp; -uint256 m = tx.gasprice; -address payable n = payable(tx.origin); -uint256 o = address(this).balance; -return (h,i,j,k,l,m,n,o); -//return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGrammar002test6Grammar013.sol b/framework/src/test/resources/soliditycode/contractGrammar002test6Grammar013.sol deleted file mode 100644 index be863303a3d..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar002test6Grammar013.sol +++ /dev/null @@ -1,24 +0,0 @@ - -contract Counter { -uint count = 0; -address payable owner; -//function Counter() public{ -constructor() public{ -owner = payable(msg.sender); -} -function increment() public { -uint step = 10; -if (owner == msg.sender) { -count = count + step; -} -} -function getCount() public returns (uint){ -return count; -} -function kill() public{ -if (owner == msg.sender) { -selfdestruct(owner); -//selfdestruct(address(owner)); -} -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGrammar003test1Grammar014.sol b/framework/src/test/resources/soliditycode/contractGrammar003test1Grammar014.sol deleted file mode 100644 index b2d70b3741c..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar003test1Grammar014.sol +++ /dev/null @@ -1,67 +0,0 @@ -contract A { -uint256 public numberForB; -address public senderForB; -function callTest(address bAddress, uint256 _number) public{ - -//bAddress.call(bytes4(sha3("setValue(uint256)")), _number); // B's storage is set, A is not modified -bAddress.call(abi.encodeWithSignature("setValue(uint256)",_number)); // B's storage is set, A is not modified -} -function callcodeTest(address bAddress, uint256 _number) public{ -//bAddress.callcode(bytes4(sha3("setValue(uint256)")), _number); // A's storage is set, B is not modified -bAddress.delegatecall(abi.encodeWithSignature("setValue(uint256)", _number)); // A's storage is set, B is not modified -} -function delegatecallTest(address bAddress, uint256 _number) public{ -//bAddress.delegatecall(bytes4(sha3("setValue(uint256)")), _number); // A's storage is set, B is not modified -bAddress.delegatecall(abi.encodeWithSignature("setValue(uint256)", _number)); // A's storage is set, B is not modified -} - -function callAddTest(address bAddress) public{ -//bAddress.call(bytes4(sha3("add()"))); // B's storage is set, A is not modified -bAddress.call(abi.encodeWithSignature("add()")); // B's storage is set, A is not modified -//bAddress.call(bytes4(sha3("add()"))); // B's storage is set, A is not modified -bAddress.call(abi.encodeWithSignature("add()")); // B's storage is set, A is not modified -} -function getnumberForB() public returns(uint256){ - return numberForB; - } - function getsenderForB() public returns(address){ - return senderForB; - } -} -contract B { -uint256 public numberForB; -address public senderForB; -address public addr11; -mapping(uint256=>address) public addr1; -mapping(uint256=>address) public addr2; -event ssss(uint256); -function setValue(uint256 _number) public{ - -emit ssss(_number); -numberForB = _number; -senderForB = msg.sender; -// senderForB is A if invoked by A's callTest. B's storage will be updated -// senderForB is A if invoked by A's callcodeTest. None of B's storage is updated -// senderForB is OWNER if invoked by A's delegatecallTest. None of B's storage is updated -} - -function add() public{ -numberForB=numberForB+1; -C c1 = new C(); -addr1[numberForB]=c1.getAddress(); -addr11 = c1.getAddress(); -C c2 = new C(); -addr2[numberForB] = c2.getAddress(); -} -function getnumberForB() public returns(uint256){ - return numberForB; - } - function getsenderForB() public returns(address){ - return senderForB; - } -} -contract C { -function getAddress() public view returns(address){ -return address(this); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGrammar003test2Grammar015.sol b/framework/src/test/resources/soliditycode/contractGrammar003test2Grammar015.sol deleted file mode 100644 index 0aa93e5e94f..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar003test2Grammar015.sol +++ /dev/null @@ -1,40 +0,0 @@ - - -contract ExecuteFallback{ - - //回退事件,会把调用的数据打印出来 - event FallbackCalled(bytes data); - //fallback函数,注意是没有名字的,没有参数,没有返回值的 - // 0.6.0 Split unnamed fallback functions into two cases defined using fallback() and receive() - fallback() external{ - emit FallbackCalled(msg.data); - } - - //调用已存在函数的事件,会把调用的原始数据,请求参数打印出来 - event ExistFuncCalled(bytes data, uint256 para); - //一个存在的函数 - function existFunc(uint256 para) public{ - emit ExistFuncCalled(msg.data, para); - } - - // 模拟从外部对一个存在的函数发起一个调用,将直接调用函数 - function callExistFunc() public{ - bytes4 funcIdentifier = bytes4(keccak256("existFunc(uint256)")); - //this.call(funcIdentifier, uint256(1)); - address(this).call(abi.encode(funcIdentifier, uint256(1))); - } - - //模拟从外部对一个不存在的函数发起一个调用,由于匹配不到函数,将调用回退函数 - function callNonExistFunc() public{ - bytes4 funcIdentifier = bytes4(keccak256("functionNotExist()")); - //this.call(funcIdentifier); - address(this).call(abi.encode(funcIdentifier)); - } - - function ExistFuncCalledTopic() view public returns(bytes32){ - return keccak256("ExistFuncCalled(bytes,uint256)"); - } - function FallbackCalledTopic() view public returns(bytes32){ - return keccak256("FallbackCalled(bytes)"); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGrammar003test3Grammar016.sol b/framework/src/test/resources/soliditycode/contractGrammar003test3Grammar016.sol deleted file mode 100644 index 6a73d7a8d7e..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar003test3Grammar016.sol +++ /dev/null @@ -1,23 +0,0 @@ - -contract C { -uint private data; -function f(uint a) private returns(uint b) { return a + 1; } -function setData(uint a) public { data = a; } -function getData() public returns(uint) { return data; } -function compute(uint a, uint b) internal returns (uint) { return a+b; } -} -contract D { -function readData() public{ -C c = new C(); -//uint local = c.f(7); // error: member "f" is not visible -c.setData(3); -uint local = c.getData(); -// local = c.compute(3, 5); // error: member "compute" is not visible -} -} -contract E is C { -function g() public { -C c = new C(); -uint val = compute(3, 5); // access to internal member (from derived to parent contract) -} -} diff --git a/framework/src/test/resources/soliditycode/contractGrammar003test4Grammar017.sol b/framework/src/test/resources/soliditycode/contractGrammar003test4Grammar017.sol deleted file mode 100644 index 38746d90734..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar003test4Grammar017.sol +++ /dev/null @@ -1,51 +0,0 @@ -contract CrowdFunding{ - struct Funder{ - address addr; - uint amount; - } - - struct Campaign{ - address payable beneficiary; - uint goal; - uint amount; - uint funderNum; - mapping(uint => Funder) funders; - } - - uint compaingnID; - mapping (uint => Campaign) campaigns; - - function candidate(address payable beneficiary, uint goal) public payable returns (uint compaingnID){ - // initialize - Campaign storage c = campaigns[compaingnID++]; - c.beneficiary = beneficiary; - c.goal = goal; - } - - function vote(uint compaingnID) payable public { - Campaign storage c = campaigns[compaingnID]; - - //another way to initialize - c.funders[c.funderNum++] = Funder({addr: msg.sender, amount: msg.value}); - c.amount += msg.value; - } - - function check(uint comapingnId) public payable returns (bool){ - Campaign storage c = campaigns[comapingnId]; - - if(c.amount < c.goal){ - return false; - } - - uint amount = c.amount; - // incase send much more - c.amount = 0; - // address payable addr = address(uint160(c.beneficiary)); - //if(! addr.send(amount)){ - - if (! c.beneficiary.send(amount)){ - revert(); - } - return true; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGrammar003test5Grammar018.sol b/framework/src/test/resources/soliditycode/contractGrammar003test5Grammar018.sol deleted file mode 100644 index ec241f3eae9..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar003test5Grammar018.sol +++ /dev/null @@ -1,37 +0,0 @@ - - - -contract Grammar18{ - function testAddmod() public returns (uint z) { - //计算(x + y)%k,其中以任意精度执行加法,并且不在2 ** 256处围绕 - z=addmod(2, 2, 3); - return z; - } - function testMulmod() public returns (uint z) { -//计算(x * y)%k,其中乘法以任意精度执行,并且不会在2 ** 256处循环。 - z=mulmod(2, 3, 4); - return z; - } - - function testKeccak256() public returns(bytes32){ - //计算的(紧凑)参数的Ethereum-SHA-3(Keccak-256)的散列 - return keccak256("11"); - } - - function testSha256() public returns(bytes32){ - //计算(紧密包装)参数的SHA-256散列 - return sha256("11"); - } - function testSha3() public returns(bytes32){ - //计算(紧密包装)参数的SHA-256散列 - //return sha3("11"); - return keccak256("11"); - } - - function testRipemd160() public returns(bytes32){ - //计算(紧密包装)参数的RIPEMD-160哈希值 - return ripemd160("11"); - } - - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGrammar003test6Grammar019.sol b/framework/src/test/resources/soliditycode/contractGrammar003test6Grammar019.sol deleted file mode 100644 index 727ef7091e7..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar003test6Grammar019.sol +++ /dev/null @@ -1,12 +0,0 @@ - -contract timetest { - -constructor() public { -require( 1 == 1 seconds); -require(1 minutes == 60 seconds); -require(1 hours == 60 minutes); -require(1 days == 24 hours); -require(1 weeks == 7 days); -//require(1 years == 365 days); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractGrammar003test7Grammar020.sol b/framework/src/test/resources/soliditycode/contractGrammar003test7Grammar020.sol deleted file mode 100644 index 39a7fddcb7e..00000000000 --- a/framework/src/test/resources/soliditycode/contractGrammar003test7Grammar020.sol +++ /dev/null @@ -1,8 +0,0 @@ - -contract trxtest { - -function test() public { -require(1 trx == 1000000 sun); - -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractInnerContract.sol b/framework/src/test/resources/soliditycode/contractInnerContract.sol deleted file mode 100644 index 5e6addef105..00000000000 --- a/framework/src/test/resources/soliditycode/contractInnerContract.sol +++ /dev/null @@ -1,32 +0,0 @@ - - - - -contract InnerContract { - - constructor() public payable{} - fallback() external payable{} - - function messageI() payable public returns (uint ret) { - - - - } - -} - - - -contract OuterContract { - - - constructor() public payable{} - fallback() external payable{} - - function callInner(address payable addr) payable public returns (uint) { - - return InnerContract(addr).messageI{value:1}(); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction001.sol b/framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction001.sol deleted file mode 100644 index 52dcfb16fc3..00000000000 --- a/framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction001.sol +++ /dev/null @@ -1,41 +0,0 @@ - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address payable cAddr) public payable{ - B b1 = (new B){value:10}();//1.1 - B b2 = new B();//1.2 - payable(address(b2)).transfer(5);//1.3 - b2.callCGetZero(cAddr, 1);//1.4 - b2.callCGetZero(cAddr,2);//1.6 - } - function test2(address payable cAddress,uint256 amount) public payable{ - cAddress.call{value:amount}(abi.encodeWithSignature("newBAndTransfer()"));//2.1 - cAddress.call{value:amount + 1}(abi.encodeWithSignature("newBAndTransfer()"));//2.6 - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero(address payable cAddress,uint256 amount) public{ - cAddress.call{value:amount}(abi.encodeWithSignature("getZero()"));//1.5,1.7 - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - B b1 = (new B){value:7}();//2.2,2.7 - b1.getOne();//2.3,2.8 - B b2 = (new B){value:3}();//2.4,2.9 - b2.getOne();//2.5,2.10 - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction002.sol b/framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction002.sol deleted file mode 100644 index 502e42d0c7b..00000000000 --- a/framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction002.sol +++ /dev/null @@ -1,20 +0,0 @@ - -contract A{ - constructor() payable public{} - fallback() payable external{} - - function test2(address cAddress,uint256 amount) public payable{ - //cAddress.call.value(amount)();//2.1 - cAddress.call{value:amount}("");//2.1 - } -} - - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction003.sol b/framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction003.sol deleted file mode 100644 index 9d3e38affbd..00000000000 --- a/framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction003.sol +++ /dev/null @@ -1,30 +0,0 @@ - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer() payable public{ - B b = (new B){value:10}();//1 - - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable public returns(bool) { - return true; - } - constructor() public payable {} - function payC(address payable c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - fallback() payable external{} - } - diff --git a/framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction004.sol b/framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction004.sol deleted file mode 100644 index e8f32d7bfd9..00000000000 --- a/framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction004.sol +++ /dev/null @@ -1,24 +0,0 @@ - -contract A{ - constructor () payable public{} - function test(address payable toAddress) public payable{ - selfdestruct(toAddress); - } - fallback() payable external{} - function getBalance() public view returns(uint256){ - return address(this).balance; - } -} -contract B{ - fallback() external payable{} - function kill(address contractAddres, address toAddress) payable public { - contractAddres.call(abi.encodeWithSignature("test(address)",address(this))); - } - function kill2() public{ - A a = new A(); - a.test(payable(address(this))); - } - function getBalance() public view returns(uint256){ - return address(this).balance; - } -} diff --git a/framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction005.sol b/framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction005.sol deleted file mode 100644 index f6bdf294a99..00000000000 --- a/framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction005.sol +++ /dev/null @@ -1,53 +0,0 @@ - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1() public payable{ - B b1 = (new B){value:10}();//1.1 - b1.callCGetZero(false); - b1.callCGetZero(true);//1.4 - } - function test2() public payable{ - C c1 = (new C){value:10}();//1.1 - c1.newBAndTransfer(false); - c1.newBAndTransfer(true);//1.4 - - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero(bool success) public payable{ - if(!success){ - assert(1==2); - } - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract C{ - uint256 public flag=0; - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer(bool success) payable public returns(uint256){ - flag = 1; - if(!success){ - require(2==1); - } - } - function getFlag() public returns(uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction006.sol b/framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction006.sol deleted file mode 100644 index ec574998b29..00000000000 --- a/framework/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction006.sol +++ /dev/null @@ -1,54 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1() public payable{ - B b1 = (new B){value:10}();//1.1 - b1.callCGetZero(true);//1.4 - b1.callCGetZero(false); - } - function test2() public payable{ - C c1 = (new C){value:10}();//1.1 - c1.newBAndTransfer(true);//1.4 - c1.newBAndTransfer(false); - - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero(bool success) public payable{ - if(!success){ - assert(1==2); - } - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract C{ - uint256 public flag=0; - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer(bool success) payable public returns(uint256){ - flag = 1; - if(!success){ - require(2==1); - } - } - function getFlag() public returns(uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractInternalTransaction002test1InternalTransaction007.sol b/framework/src/test/resources/soliditycode/contractInternalTransaction002test1InternalTransaction007.sol deleted file mode 100644 index d14c3d8aa16..00000000000 --- a/framework/src/test/resources/soliditycode/contractInternalTransaction002test1InternalTransaction007.sol +++ /dev/null @@ -1,38 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address cAddr) public payable{ - B b1 = (new B){value:10}();//1.1 - B b2 = new B();//1.2 - payable(address(b2)).transfer(5);//1.3 - b2.callCGetZero();//1.4 - } - function test2(address cAddress,uint256 amount) public payable{ - cAddress.call{value:amount}(abi.encodeWithSignature("newBAndTransfer()"));//2.1 - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero() public{ - assert(1==2); - - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} diff --git a/framework/src/test/resources/soliditycode/contractInternalTransaction002test2InternalTransaction008.sol b/framework/src/test/resources/soliditycode/contractInternalTransaction002test2InternalTransaction008.sol deleted file mode 100644 index 2e57a0e635c..00000000000 --- a/framework/src/test/resources/soliditycode/contractInternalTransaction002test2InternalTransaction008.sol +++ /dev/null @@ -1,60 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - - function testAssert(address bAddress,uint256 amount) public payable{ - bAddress.call{value:amount,gas:1000000}(abi.encodeWithSignature("callCGetZero(bool)",false));//2.1 - bAddress.call{value:amount,gas:1000000}(abi.encodeWithSignature("callCGetZero(bool)",true)); - } - function testRequire(address cAddress,uint256 amount) public payable{ - cAddress.call{value:amount,gas:1000000}(abi.encodeWithSignature("newBAndTransfer(bool)",false));//2.1 - cAddress.call{value:amount,gas:1000000}(abi.encodeWithSignature("newBAndTransfer(bool)",true)); - } - function testAssert1(address bAddress,uint256 amount) public payable{ - bAddress.call{value:amount,gas:1000000}(abi.encodeWithSignature("callCGetZero(bool)",true)); - bAddress.call{value:amount,gas:1000000}(abi.encodeWithSignature("callCGetZero(bool)",false));//2.1 - } - function testtRequire2(address cAddress,uint256 amount) public payable{ - cAddress.call{value:amount,gas:1000000}(abi.encodeWithSignature("newBAndTransfer(bool)",true)); - cAddress.call{value:amount,gas:1000000}(abi.encodeWithSignature("newBAndTransfer(bool)",false));//2.1 - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero(bool success) payable public{ - if(!success){ - assert(1==2); - } - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract C{ - uint256 public flag=0; - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer(bool success) payable public returns(uint256){ - flag = 1; - if(!success){ - require(2==1); - } - } - function getFlag() public returns(uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractInternalTransaction002test3InternalTransaction009.sol b/framework/src/test/resources/soliditycode/contractInternalTransaction002test3InternalTransaction009.sol deleted file mode 100644 index d750df65ea4..00000000000 --- a/framework/src/test/resources/soliditycode/contractInternalTransaction002test3InternalTransaction009.sol +++ /dev/null @@ -1,47 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address cAddr,address dcontract,address baddress) public payable{ - B b1 = (new B){value:10}();//1.1 - payable(address(b1)).transfer(5);//1.3 - b1.callCGetZero(cAddr, 1);//1.4 - b1.getOne(dcontract,baddress); - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne(address contractAddres, address toAddress) payable public{ - contractAddres.call(abi.encodeWithSignature("suicide1(address)",address(this))); - - } - function callCGetZero(address cAddress,uint256 amount) public{ - cAddress.call{value:amount}(abi.encodeWithSignature("getZero()"));//1.5,1.7 - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public{ - B b1 = (new B){value:7}();//2.2,2.7 - B b2 = (new B){value:3}();//2.4,2.9 - } -} - -contract D{ - constructor () payable public{} - function suicide1(address payable toAddress) public payable{ - selfdestruct(toAddress); - } - fallback() payable external{} - function getBalance() public view returns(uint256){ - return address(this).balance; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractInternalTransaction002test4InternalTransaction010.sol b/framework/src/test/resources/soliditycode/contractInternalTransaction002test4InternalTransaction010.sol deleted file mode 100644 index ff5817ea173..00000000000 --- a/framework/src/test/resources/soliditycode/contractInternalTransaction002test4InternalTransaction010.sol +++ /dev/null @@ -1,186 +0,0 @@ - - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer() payable public{ - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - - } - function transfer2() payable public{ - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - - } - function getBalance() public returns(uint256) { - return address(this).balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable public returns(bool) { - return true; - } - constructor() public payable {} - function payC(address payable c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - fallback() payable external{} - } - diff --git a/framework/src/test/resources/soliditycode/contractInternalTransaction002test4InternalTransaction010_1.sol b/framework/src/test/resources/soliditycode/contractInternalTransaction002test4InternalTransaction010_1.sol deleted file mode 100644 index d0c80d14ffb..00000000000 --- a/framework/src/test/resources/soliditycode/contractInternalTransaction002test4InternalTransaction010_1.sol +++ /dev/null @@ -1,210 +0,0 @@ - - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - } - function transfer2() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - - } - function getBalance() returns(uint256){ - return this.balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable returns(bool) { - return true; - } - constructor() public payable {} - function payC(address c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() returns(uint256){ - return this.balance; - } - fallback() payable{} - } - - \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractInternalTransaction002test5InternalTransaction012.sol b/framework/src/test/resources/soliditycode/contractInternalTransaction002test5InternalTransaction012.sol deleted file mode 100644 index 59ffe9f0fe9..00000000000 --- a/framework/src/test/resources/soliditycode/contractInternalTransaction002test5InternalTransaction012.sol +++ /dev/null @@ -1,51 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address bAddr,address eAddr) public payable{ - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - } - -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function testNN(address eAddress) public payable{ - D d1=(new D){value:1000}(); - d1.getOne(eAddress); - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract D{ - constructor() payable public{} - fallback() payable external{} - function getOne(address eAddress) payable public returns(uint256){ - eAddress.call{value:1}(abi.encodeWithSignature("getZero()"));//2.1 - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction013.sol b/framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction013.sol deleted file mode 100644 index 1dae0beb03c..00000000000 --- a/framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction013.sol +++ /dev/null @@ -1,56 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address dAddr) public payable{ - B b1 = (new B){value:10}();//1.1 - b1.testNN(dAddr,2);//1.6 - // C c1 = (new C).value(1000000000000)();//1.2 - // E e1 = (new E).value(1)();//1.2 - } - function test2(address cAddress,uint256 amount) public payable{ - cAddress.call{value:amount}(abi.encodeWithSignature("newBAndTransfer()"));//2.1 - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function testNN(address dAddress,uint256 amount) public payable{ - // D d1=(new D)(); - dAddress.call{value:amount}(abi.encodeWithSignature("getOne()"));//2.1 - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract D{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - E e = (new E){value:5}(); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction014.sol b/framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction014.sol deleted file mode 100644 index 0346cec669b..00000000000 --- a/framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction014.sol +++ /dev/null @@ -1,38 +0,0 @@ -contract callerContract { - constructor() payable public{} - fallback() payable external{} - function sendToB(address called_address,address c) public payable{ - called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); - } - function sendToB2(address called_address,address c) public payable{ - called_address.call(abi.encodeWithSignature("transferTo(address)",c)); - } - function sendToB3(address called_address,address c) public payable{ - called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); - } -} - - contract calledContract { - fallback() payable external {} - constructor() payable public{} - function transferTo(address payable toAddress)public payable{ - toAddress.transfer(5); - } - - function setIinC(address c) public payable{ - c.call{value:5}(abi.encodeWithSignature("setI()")); - } - - } - - contract c{ - uint256 public i=0; - constructor() public payable{} - function getBalance() public view returns(uint256){ - return address(this).balance; - } - function setI() payable public{ - i=5; - } - fallback() payable external{} - } diff --git a/framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction015.sol b/framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction015.sol deleted file mode 100644 index edeb9488454..00000000000 --- a/framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction015.sol +++ /dev/null @@ -1,60 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address dAddr,address eAddr) public payable{ - B b1 = (new B){value:10}();//1.1 - b1.testNN(dAddr,2,eAddr);//1.6 - // C c1 = (new C).value(1000000000000)();//1.2 - // E e1 = (new E).value(1)();//1.2 - } - function test2(address cAddress,uint256 amount) public payable{ - cAddress.call{value:amount}(abi.encodeWithSignature("newBAndTransfer()"));//2.1 - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function testNN(address dAddress,uint256 amount,address eAddress) public payable{ - // D d1=(new D)(); - dAddress.call{value:amount}(abi.encodeWithSignature("getOne(address)",address(this)));//2.1 - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } - function suicide(address payable toAddress) public payable{ - selfdestruct(toAddress); - } -} -contract D{ - constructor() payable public{} - fallback() payable external{} - function getOne(address payable eAddress) payable public{ - E e = (new E){value:5}(); - e.suicide(eAddress); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction016.sol b/framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction016.sol deleted file mode 100644 index 9b01c9e0d31..00000000000 --- a/framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction016.sol +++ /dev/null @@ -1,174 +0,0 @@ - - - contract A{ - uint256 public num = 0; - constructor() public payable{} - fallback() payable external{} - function transfer() payable public{ - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - B b1=(new B){value:1}();//1 - address payable aaa=payable(address(this)); - b1.suicide1(aaa); - } - function transfer2() payable public{ - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - B b1=(new B){value:1}();//1 - address payable aaa=payable(address(this)); - b1.suicide1(aaa); - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable public returns(bool) { - return true; - } - constructor() public payable {} - function payC(address payable c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - fallback() payable external{} - function suicide1(address payable toAddress) public payable{ - selfdestruct(toAddress); - } - } - diff --git a/framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction017.sol b/framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction017.sol deleted file mode 100644 index 32cf9f2a04d..00000000000 --- a/framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction017.sol +++ /dev/null @@ -1,199 +0,0 @@ - - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer(address payable Address) payable public{ - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - - B b=(new B){value:1}();//1 - selfdestruct(Address); - } - function transfer2() payable public{ - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable public returns(bool) { - return true; - } - constructor() public payable {} - function payC(address payable c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - fallback() payable external{} - } - diff --git a/framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction018.sol b/framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction018.sol deleted file mode 100644 index fadb5f84b51..00000000000 --- a/framework/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction018.sol +++ /dev/null @@ -1,97 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address payable bAddr,address eAddr) public payable{ - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - - } - -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function testNN(address eAddress) public payable { - D d1=(new D){value:100}(); - d1.getOne(eAddress); - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract D{ - constructor() payable public{} - fallback() payable external{} - function getOne(address eAddress) payable public returns(uint256){ - eAddress.call{value:1}(abi.encodeWithSignature("getZero()"));//2.1 - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractLinkage001.sol b/framework/src/test/resources/soliditycode/contractLinkage001.sol deleted file mode 100644 index 8d441fba2da..00000000000 --- a/framework/src/test/resources/soliditycode/contractLinkage001.sol +++ /dev/null @@ -1,9 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -constructor() payable public{} -fallback() payable external{} -function divideIHaveArgsReturn(int x,int y) public payable returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractLinkage002.sol b/framework/src/test/resources/soliditycode/contractLinkage002.sol deleted file mode 100644 index 92778e42bc9..00000000000 --- a/framework/src/test/resources/soliditycode/contractLinkage002.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractLinkage003.sol b/framework/src/test/resources/soliditycode/contractLinkage003.sol deleted file mode 100644 index 92778e42bc9..00000000000 --- a/framework/src/test/resources/soliditycode/contractLinkage003.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractLinkage004.sol b/framework/src/test/resources/soliditycode/contractLinkage004.sol deleted file mode 100644 index 92778e42bc9..00000000000 --- a/framework/src/test/resources/soliditycode/contractLinkage004.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractLinkage005.sol b/framework/src/test/resources/soliditycode/contractLinkage005.sol deleted file mode 100644 index 7b943aee5c1..00000000000 --- a/framework/src/test/resources/soliditycode/contractLinkage005.sol +++ /dev/null @@ -1,51 +0,0 @@ -contract timeoutTest { - string public iarray1; - // cpu - function oneCpu() public { - require(1==1); - } - - function storage8Char() public { - iarray1 = "12345678"; - } - - function testUseCpu(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - } - return count; - } - - - uint256[] public iarray; - uint public calculatedFibNumber; - mapping(address=>mapping(address=>uint256)) public m; - - function testUseStorage(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - iarray.push(i); - } - return count; - } - - // stack - //uint n = 0; - uint yy = 0; - function test() public { - //n += 1; - yy += 1; - test(); - } - - function setFibonacci(uint n) public returns (uint256){ - calculatedFibNumber = fibonacci(n); - return calculatedFibNumber; - } - - function fibonacci(uint n) internal returns (uint) { - return fibonacci(n - 1) + fibonacci(n - 2); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractLinkage006.sol b/framework/src/test/resources/soliditycode/contractLinkage006.sol deleted file mode 100644 index 53449f61ce2..00000000000 --- a/framework/src/test/resources/soliditycode/contractLinkage006.sol +++ /dev/null @@ -1,18 +0,0 @@ - -contract AA{ - uint256 public count=0; - constructor () payable public{} - function init(address payable addr, uint256 max) payable public { - count =0; - this.hack(addr,max); - } - function hack(address payable addr, uint256 max) payable public { - while (count < max) { - count = count +1; - this.hack(addr,max); - } - if (count == max) { - addr.send(20); - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractOriginEnergyLimit001.sol b/framework/src/test/resources/soliditycode/contractOriginEnergyLimit001.sol deleted file mode 100644 index 6feb7fff3b8..00000000000 --- a/framework/src/test/resources/soliditycode/contractOriginEnergyLimit001.sol +++ /dev/null @@ -1,11 +0,0 @@ - - -contract findArgsContractTest{ - function findArgsByIndexTest(uint i) public returns (uint z) { - uint[] memory a = new uint[](3); - a[0]=1; - a[1]=2; - a[2]=3; - return a[i]; - } -} diff --git a/framework/src/test/resources/soliditycode/contractOriginEnergyLimit004.sol b/framework/src/test/resources/soliditycode/contractOriginEnergyLimit004.sol deleted file mode 100644 index 6feb7fff3b8..00000000000 --- a/framework/src/test/resources/soliditycode/contractOriginEnergyLimit004.sol +++ /dev/null @@ -1,11 +0,0 @@ - - -contract findArgsContractTest{ - function findArgsByIndexTest(uint i) public returns (uint z) { - uint[] memory a = new uint[](3); - a[0]=1; - a[1]=2; - a[2]=3; - return a[i]; - } -} diff --git a/framework/src/test/resources/soliditycode/contractOtherToTrcToken.sol b/framework/src/test/resources/soliditycode/contractOtherToTrcToken.sol deleted file mode 100644 index c0bb2d7d88e..00000000000 --- a/framework/src/test/resources/soliditycode/contractOtherToTrcToken.sol +++ /dev/null @@ -1,41 +0,0 @@ - - -contract ConvertType { - -constructor() payable public{} - -fallback() payable external{} - -//function stringToTrctoken(address payable toAddress, string memory tokenStr, uint256 tokenValue) public { -// trcToken t = trcToken(tokenStr); // ERROR -// toAddress.transferToken(tokenValue, tokenStr); // ERROR -//} - -function uint256ToTrctoken(address payable toAddress, uint256 tokenValue, uint256 tokenInt) public { - trcToken t = trcToken(tokenInt); // OK - toAddress.transferToken(tokenValue, t); // OK - toAddress.transferToken(tokenValue, tokenInt); // OK -} - -function addressToTrctoken(address payable toAddress, uint256 tokenValue, address adr) public { - trcToken t = trcToken(uint256(uint160(adr))); // OK - toAddress.transferToken(tokenValue, t); // OK -//toAddress.transferToken(tokenValue, adr); // ERROR -} - -//function bytesToTrctoken(address payable toAddress, bytes memory b, uint256 tokenValue) public { - // trcToken t = trcToken(b); // ERROR - // toAddress.transferToken(tokenValue, b); // ERROR -//} - -function bytes32ToTrctoken(address payable toAddress, uint256 tokenValue, bytes32 b32) public { - trcToken t = trcToken(b32); // OK - toAddress.transferToken(tokenValue, t); // OK -// toAddress.transferToken(tokenValue, b32); // ERROR -} - -//function arrayToTrctoken(address payable toAddress, uint256[] memory arr, uint256 tokenValue) public { -//trcToken t = trcToken(arr); // ERROR -// toAddress.transferToken(tokenValue, arr); // ERROR -//} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractScenario001.sol b/framework/src/test/resources/soliditycode/contractScenario001.sol deleted file mode 100644 index 92778e42bc9..00000000000 --- a/framework/src/test/resources/soliditycode/contractScenario001.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractScenario002.sol b/framework/src/test/resources/soliditycode/contractScenario002.sol deleted file mode 100644 index 5b990fe36e8..00000000000 --- a/framework/src/test/resources/soliditycode/contractScenario002.sol +++ /dev/null @@ -1,53 +0,0 @@ - -contract TronNative{ - - address public voteContractAddress= address(0x10001); - address public freezeBalanceAddress = address(0x10002); - address public unFreezeBalanceAddress = address(0x10003); - address public withdrawBalanceAddress = address(0x10004); - address public approveProposalAddress = address(0x10005); - address public createProposalAddress = address(0x10006); - address public deleteProposalAddress = address(0x10007); - constructor () payable public {} - - function voteForSingleWitness (address payable witnessAddr, uint256 voteValue) public{ - // method 1: - voteContractAddress.delegatecall(abi.encode(witnessAddr,voteValue)); - } - - function voteUsingAssembly (address witnessAddr, uint256 voteValue) public{ - // method 2: - assembly{ - mstore(0x80,witnessAddr) - mstore(0xa0,voteValue) - // gas, address, in, size, out, size - if iszero(delegatecall(0, 0x10001, 0x80, 0x40, 0x80, 0x0)) { - revert(0, 0) - } - } - } - - function freezeBalance(uint256 frozen_Balance,uint256 frozen_Duration) public { - freezeBalanceAddress.delegatecall(abi.encode(frozen_Balance,frozen_Duration)); - } - - function unFreezeBalance() public { - unFreezeBalanceAddress.delegatecall(""); - } - - function withdrawBalance() public { - withdrawBalanceAddress.delegatecall(""); - } - - function approveProposal(uint256 id, bool isApprove) public { - approveProposalAddress.delegatecall(abi.encode(id,isApprove)); - } - - function createProposal(bytes32 [] memory data) public { - createProposalAddress.delegatecall(abi.encode(data)); - } - - function deleteProposal(uint256 id) public{ - deleteProposalAddress.delegatecall(abi.encode(id)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractScenario003.sol b/framework/src/test/resources/soliditycode/contractScenario003.sol deleted file mode 100644 index 92778e42bc9..00000000000 --- a/framework/src/test/resources/soliditycode/contractScenario003.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractScenario004.sol b/framework/src/test/resources/soliditycode/contractScenario004.sol deleted file mode 100644 index f6919502914..00000000000 --- a/framework/src/test/resources/soliditycode/contractScenario004.sol +++ /dev/null @@ -1,88 +0,0 @@ - - -contract TronToken { - - string public name = "Tronix"; // token name - string public symbol = "TRX"; // token symbol - uint256 public decimals = 6; // token digit - - mapping (address => uint256) public balanceOf; - mapping (address => mapping (address => uint256)) public allowance; - - uint256 public totalSupply = 0; - bool public stopped = false; - - uint256 constant valueFounder = 100000000000000000; - address owner = address(0x0); - - modifier isOwner { - assert(owner == msg.sender); - _; - } - - modifier isRunning { - assert (!stopped); - _; - } - - modifier validAddress { - assert(address(0x0) != msg.sender); - _; - } - - constructor(address _addressFounder) public { - owner = msg.sender; - totalSupply = valueFounder; - balanceOf[_addressFounder] = valueFounder; - emit Transfer(address(0x0), _addressFounder, valueFounder); - } - - function transfer(address _to, uint256 _value) isRunning validAddress public returns (bool success) { - require(balanceOf[msg.sender] >= _value); - require(balanceOf[_to] + _value >= balanceOf[_to]); - balanceOf[msg.sender] -= _value; - balanceOf[_to] += _value; - emit Transfer(msg.sender, _to, _value); - return true; - } - - function transferFrom(address _from, address _to, uint256 _value) isRunning validAddress public returns (bool success) { - require(balanceOf[_from] >= _value); - require(balanceOf[_to] + _value >= balanceOf[_to]); - require(allowance[_from][msg.sender] >= _value); - balanceOf[_to] += _value; - balanceOf[_from] -= _value; - allowance[_from][msg.sender] -= _value; - emit Transfer(_from, _to, _value); - return true; - } - - function approve(address _spender, uint256 _value) isRunning validAddress public returns (bool success) { - require(_value == 0 || allowance[msg.sender][_spender] == 0); - allowance[msg.sender][_spender] = _value; - emit Approval(msg.sender, _spender, _value); - return true; - } - - function stop() isOwner public { - stopped = true; - } - - function start() isOwner public { - stopped = false; - } - - function setName(string memory _name) isOwner public { - name = _name; - } - - function burn(uint256 _value) public { - require(balanceOf[msg.sender] >= _value); - balanceOf[msg.sender] -= _value; - balanceOf[address(0x0)] += _value; - emit Transfer(msg.sender, address(0x0), _value); - } - - event Transfer(address indexed _from, address indexed _to, uint256 _value); - event Approval(address indexed _owner, address indexed _spender, uint256 _value); -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractScenario005.sol b/framework/src/test/resources/soliditycode/contractScenario005.sol deleted file mode 100644 index 5d20d98c0ba..00000000000 --- a/framework/src/test/resources/soliditycode/contractScenario005.sol +++ /dev/null @@ -1,103 +0,0 @@ - - -interface token { - function transfer(address receiver, uint amount) external; -} - -contract Crowdsale { - address payable public beneficiary = payable(address(uint160(0x1b228F5D9f934c7bb18Aaa86F90418932888E7b4))); // 募资成功后的收款方 - uint public fundingGoal = 10000000; // 募资额度 - uint public amountRaised = 1000000; // 参与数量 - uint public deadline; // 募资截止期 - - uint public price; // token 与以太坊的汇率 , token卖多少钱 - token public tokenReward; // 要卖的token - - mapping(address => uint256) public balanceOf; - - bool fundingGoalReached = false; // 众筹是否达到目标 - bool crowdsaleClosed = false; // 众筹是否结束 - - /** - * 事件可以用来跟踪信息 - **/ - event GoalReached(address recipient, uint totalAmountRaised); - event FundTransfer(address backer, uint amount, bool isContribution); - - /** - * 构造函数, 设置相关属性 - */ - constructor( - address payable ifSuccessfulSendTo, - uint fundingGoalInEthers, - uint durationInMinutes, - uint finneyCostOfEachToken, - address addressOfTokenUsedAsReward) public{ - beneficiary = ifSuccessfulSendTo; - fundingGoal = fundingGoalInEthers * 1 sun; - deadline = block.timestamp + durationInMinutes * 1 minutes; - price = finneyCostOfEachToken * 1 trx; - tokenReward = token(addressOfTokenUsedAsReward); // 传入已发布的 token 合约的地址来创建实例 - } - - /** - * 无函数名的Fallback函数, - * 在向合约转账时,这个函数会被调用 - */ - fallback() payable external{ - require(!crowdsaleClosed); - uint amount = msg.value; - balanceOf[msg.sender] += amount; - amountRaised += amount; - tokenReward.transfer(msg.sender, amount / price); - emit FundTransfer(msg.sender, amount, true); - } - - /** - * 定义函数修改器modifier(作用和Python的装饰器很相似) - * 用于在函数执行前检查某种前置条件(判断通过之后才会继续执行该方法) - * _ 表示继续执行之后的代码 - **/ - modifier afterDeadline() { if (block.timestamp >= deadline) _; } - - /** - * 判断众筹是否完成融资目标, 这个方法使用了afterDeadline函数修改器 - * - */ - function checkGoalReached() afterDeadline public{ - if (amountRaised >= fundingGoal) { - fundingGoalReached = true; - emit GoalReached(beneficiary, amountRaised); - } - crowdsaleClosed = true; - } - - - /** - * 完成融资目标时,融资款发送到收款方 - * 未完成融资目标时,执行退款 - * - */ - function safeWithdrawal() afterDeadline public{ - if (!fundingGoalReached) { - uint amount = balanceOf[msg.sender]; - balanceOf[msg.sender] = 0; - if (amount > 0) { - if (payable(msg.sender).send(amount)) { - emit FundTransfer(msg.sender, amount, false); - } else { - balanceOf[msg.sender] = amount; - } - } - } - - if (fundingGoalReached && beneficiary == msg.sender) { - if (payable(beneficiary).send(amountRaised)) { - emit FundTransfer(beneficiary, amountRaised, false); - } else { - //If we fail to send the funds to beneficiary, unlock funders balance - fundingGoalReached = false; - } - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractScenario006.sol b/framework/src/test/resources/soliditycode/contractScenario006.sol deleted file mode 100644 index 15dca03d162..00000000000 --- a/framework/src/test/resources/soliditycode/contractScenario006.sol +++ /dev/null @@ -1,1963 +0,0 @@ - - -interface PlayerBookInterface { - function getPlayerID(address _addr) external returns (uint256); - function getPlayerName(uint256 _pID) external view returns (bytes32); - function getPlayerLAff(uint256 _pID) external view returns (uint256); - function getPlayerAddr(uint256 _pID) external view returns (address); - function getNameFee() external view returns (uint256); - function registerNameXIDFromDapp(address _addr, bytes32 _name, uint256 _affCode, bool _all) external payable returns(bool, uint256); - function registerNameXaddrFromDapp(address _addr, bytes32 _name, address _affCode, bool _all) external payable returns(bool, uint256); - function registerNameXnameFromDapp(address _addr, bytes32 _name, bytes32 _affCode, bool _all) external payable returns(bool, uint256); - function isDev(address _who) external view returns(bool); -} - - -/** -* @title -Name Filter- v0.1.9 -* ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ -* │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ -* ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ -* _____ _____ -* (, / /) /) /) (, / /) /) -* ┌─┐ / _ (/_ // // / _ // _ __ _(/ -* ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ -* ┴ ┴ / / .-/ _____ (__ / -* (__ / (_/ (, / /)™ -* / __ __ __ __ _ __ __ _ _/_ _ _(/ -* ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ -* ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 -* ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ -* _ __ _ ____ ____ _ _ _____ ____ ___ -*=============| |\ | / /\ | |\/| | |_ =====| |_ | | | | | | | |_ | |_)==============* -*=============|_| \| /_/--\ |_| | |_|__=====|_| |_| |_|__ |_| |_|__ |_| \==============* -* -* ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ -* ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ -* ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ -*/ - -library NameFilter { - /** - * @dev filters name strings - * -converts uppercase to lower case. - * -makes sure it does not start/end with a space - * -makes sure it does not contain multiple spaces in a row - * -cannot be only numbers - * -cannot start with 0x - * -restricts characters to A-Z, a-z, 0-9, and space. - * @return reprocessed string in bytes32 format - */ - function nameFilter(string memory _input) - internal - pure - returns(bytes32) - { - bytes memory _temp = bytes(_input); - uint256 _length = _temp.length; - - //sorry limited to 32 characters - require (_length <= 32 && _length > 0, "string must be between 1 and 32 characters"); - // make sure it doesnt start with or end with space - require(_temp[0] != 0x20 && _temp[_length-1] != 0x20, "string cannot start or end with space"); - // make sure first two characters are not 0x - if (_temp[0] == 0x30) - { - require(_temp[1] != 0x78, "string cannot start with 0x"); - require(_temp[1] != 0x58, "string cannot start with 0X"); - } - - // create a bool to track if we have a non number character - bool _hasNonNumber; - - // convert & check - for (uint256 i = 0; i < _length; i++) - { - // if its uppercase A-Z - if (_temp[i] > 0x40 && _temp[i] < 0x5b) - { - // convert to lower case a-z - _temp[i] = bytes1(uint8(_temp[i]) + 32); - - // we have a non number - if (_hasNonNumber == false) - _hasNonNumber = true; - } else { - require - ( - // require character is a space - _temp[i] == 0x20 || - // OR lowercase a-z - (_temp[i] > 0x60 && _temp[i] < 0x7b) || - // or 0-9 - (_temp[i] > 0x2f && _temp[i] < 0x3a), - "string contains invalid characters" - ); - // make sure theres not 2x spaces in a row - if (_temp[i] == 0x20) - require( _temp[i+1] != 0x20, "string cannot contain consecutive spaces"); - - // see if we have a character other than a number - if (_hasNonNumber == false && (_temp[i] < 0x30 || _temp[i] > 0x39)) - _hasNonNumber = true; - } - } - - require(_hasNonNumber == true, "string cannot be only numbers"); - - bytes32 _ret; - assembly { - _ret := mload(add(_temp, 32)) - } - return (_ret); - } -} - - -library SafeMath { - - /** - * @dev Multiplies two numbers, throws on overflow. - */ - function mul(uint256 a, uint256 b) - internal - pure - returns (uint256 c) - { - if (a == 0) { - return 0; - } - c = a * b; - require(c / a == b, "SafeMath mul failed"); - return c; - } - - /** - * @dev Integer division of two numbers, truncating the quotient. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // assert(b > 0); // Solidity automatically throws when dividing by 0 - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - return c; - } - - /** - * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 a, uint256 b) - internal - pure - returns (uint256) - { - require(b <= a, "SafeMath sub failed"); - return a - b; - } - - /** - * @dev Adds two numbers, throws on overflow. - */ - function add(uint256 a, uint256 b) - internal - pure - returns (uint256 c) - { - c = a + b; - require(c >= a, "SafeMath add failed"); - return c; - } - - /** - * @dev gives square root of given x. - */ - function sqrt(uint256 x) - internal - pure - returns (uint256 y) - { - uint256 z = ((add(x,1)) / 2); - y = x; - while (z < y) - { - y = z; - z = ((add((x / z),z)) / 2); - } - } - - /** - * @dev gives square. multiplies x by x - */ - function sq(uint256 x) - internal - pure - returns (uint256) - { - return (mul(x,x)); - } - - /** - * @dev x to the power of y - */ - function pwr(uint256 x, uint256 y) - internal - pure - returns (uint256) - { - if (x==0) - return (0); - else if (y==0) - return (1); - else - { - uint256 z = x; - for (uint256 i=1; i < y; i++) - z = mul(z,x); - return (z); - } - } -} - -//============================================================================== -// | _ _ _ | _ . -// |<(/_\/ (_(_||(_ . -//=======/====================================================================== -library F3DKeysCalcLong { - using SafeMath for *; - /** - * @dev calculates number of keys received given X eth - * @param _curEth current amount of eth in contract - * @param _newEth eth being spent - * @return amount of ticket purchased - */ - function keysRec(uint256 _curEth, uint256 _newEth) - internal - pure - returns (uint256) - { - return(keys((_curEth).add(_newEth)).sub(keys(_curEth))); - } - - /** - * @dev calculates amount of eth received if you sold X keys - * @param _curKeys current amount of keys that exist - * @param _sellKeys amount of keys you wish to sell - * @return amount of eth received - */ - function ethRec(uint256 _curKeys, uint256 _sellKeys) - internal - pure - returns (uint256) - { - return((eth(_curKeys)).sub(eth(_curKeys.sub(_sellKeys)))); - } - - /** - * @dev calculates how many keys would exist with given an amount of eth - * @param _eth eth "in contract" - * @return number of keys that would exist - */ - function keys(uint256 _eth) - internal - pure - returns(uint256) - { - return ((((((_eth).mul(1000000000000000000)).mul(312500000000000000000000000)).add(5624988281256103515625000000000000000000000000000000000000000000)).sqrt()).sub(74999921875000000000000000000000)) / (156250000); - } - - /** - * @dev calculates how much eth would be in contract given a number of keys - * @param _keys number of keys "in contract" - * @return eth that would exists - */ - function eth(uint256 _keys) - internal - pure - returns(uint256) - { - return ((78125000).mul(_keys.sq()).add(((149999843750000).mul(_keys.mul(1000000000000000000))) / (2))) / ((1000000000000000000).sq()); - } -} - -library F3Ddatasets { - //compressedData key - // [76-33][32][31][30][29][28-18][17][16-6][5-3][2][1][0] - // 0 - new player (bool) - // 1 - joined round (bool) - // 2 - new leader (bool) - // 3-5 - air drop tracker (uint 0-999) - // 6-16 - round end time - // 17 - winnerTeam - // 18 - 28 timestamp - // 29 - team - // 30 - 0 = reinvest (round), 1 = buy (round), 2 = buy (ico), 3 = reinvest (ico) - // 31 - airdrop happened bool - // 32 - airdrop tier - // 33 - airdrop amount won - //compressedIDs key - // [77-52][51-26][25-0] - // 0-25 - pID - // 26-51 - winPID - // 52-77 - rID - struct EventReturns { - uint256 compressedData; - uint256 compressedIDs; - address winnerAddr; // winner address - bytes32 winnerName; // winner name - uint256 amountWon; // amount won - uint256 newPot; // amount in new pot - uint256 P3DAmount; // amount distributed to p3d - uint256 genAmount; // amount distributed to gen - uint256 potAmount; // amount added to pot - } - struct Player { - address payable addr; // player address - bytes32 name; // player name - uint256 win; // winnings vault - uint256 gen; // general vault - uint256 aff; // affiliate vault - uint256 lrnd; // last round played - uint256 laff; // last affiliate id used - } - struct PlayerRounds { - uint256 eth; // eth player has added to round (used for eth limiter) - uint256 keys; // keys - uint256 mask; // player mask - uint256 ico; // ICO phase investment - } - struct Round { - uint256 plyr; // pID of player in lead - uint256 team; // tID of team in lead - uint256 end; // time ends/ended - bool ended; // has round end function been ran - uint256 strt; // time round started - uint256 keys; // keys - uint256 eth; // total eth in - uint256 pot; // eth to pot (during round) / final amount paid to winner (after round ends) - uint256 mask; // global mask - uint256 ico; // total eth sent in during ICO phase - uint256 icoGen; // total eth for gen during ICO phase - uint256 icoAvg; // average key price for ICO phase - } - struct TeamFee { - uint256 gen; // % of buy in thats paid to key holders of current round - uint256 p3d; // % of buy in thats paid to p3d holders - } - struct PotSplit { - uint256 gen; // % of pot thats paid to key holders of current round - uint256 p3d; // % of pot thats paid to p3d holders - } -} - -contract F3Devents { - // fired whenever a player registers a name - event onNewName - ( - uint256 indexed playerID, - address indexed playerAddress, - bytes32 indexed playerName, - bool isNewPlayer, - uint256 affiliateID, - address affiliateAddress, - bytes32 affiliateName, - uint256 amountPaid, - uint256 timeStamp - ); - - // fired at end of buy or reload - event onEndTx - ( - uint256 compressedData, - uint256 compressedIDs, - bytes32 playerName, - address playerAddress, - uint256 ethIn, - uint256 keysBought, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount, - uint256 potAmount, - uint256 airDropPot - ); - - // fired whenever theres a withdraw - event onWithdraw - ( - uint256 indexed playerID, - address playerAddress, - bytes32 playerName, - uint256 ethOut, - uint256 timeStamp - ); - - // fired whenever a withdraw forces end round to be ran - event onWithdrawAndDistribute - ( - address playerAddress, - bytes32 playerName, - uint256 ethOut, - uint256 compressedData, - uint256 compressedIDs, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount - ); - - // (fomo3d long only) fired whenever a player tries a buy after round timer - // hit zero, and causes end round to be ran. - event onBuyAndDistribute - ( - address playerAddress, - bytes32 playerName, - uint256 ethIn, - uint256 compressedData, - uint256 compressedIDs, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount - ); - - // (fomo3d long only) fired whenever a player tries a reload after round timer - // hit zero, and causes end round to be ran. - event onReLoadAndDistribute - ( - address playerAddress, - bytes32 playerName, - uint256 compressedData, - uint256 compressedIDs, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount - ); - - // fired whenever an affiliate is paid - event onAffiliatePayout - ( - uint256 indexed affiliateID, - address affiliateAddress, - bytes32 affiliateName, - uint256 indexed roundID, - uint256 indexed buyerID, - uint256 amount, - uint256 timeStamp - ); - - // received pot swap deposit - event onPotSwapDeposit - ( - uint256 roundID, - uint256 amountAddedToPot - ); -} - - - -contract FoMo3Dlong is F3Devents { - using SafeMath for *; - using NameFilter for string; - using F3DKeysCalcLong for uint256; - - address public otherF3D_; - address public Divies; - address public Jekyll_Island_Inc; - PlayerBookInterface public playerBook;// =PlayerBookInterface(0x0dcd2f752394c41875e259e00bb44fd505297caf);//new PlayerBook();// - // TeamJustInterface constant private teamJust = TeamJustInterface(0x3a5f8140b9213a0f733a6a639857c9df43ee3f5a);// new TeamJust();// - - //============================================================================== - // _ _ _ |`. _ _ _ |_ | _ _ . - // (_(_)| |~|~|(_||_|| (_||_)|(/__\ . (game settings) - //=================_|=========================================================== - string constant public name = "FoMo3D Long Official"; - string constant public symbol = "F3D"; - uint256 private rndExtra_ = 30;//extSettings.getLongExtra(); // length of the very first ICO - uint256 private rndGap_ = 30; //extSettings.getLongGap(); // length of ICO phase, set to 1 year for EOS. - uint256 constant private rndInit_ = 1 hours; // round timer starts at this - uint256 constant private rndInc_ = 30 seconds; // every full key purchased adds this much to the timer - uint256 constant private rndMax_ = 24 hours; // max length a round timer can be - //============================================================================== - // _| _ _|_ _ _ _ _|_ _ . - // (_|(_| | (_| _\(/_ | |_||_) . (data used to store game info that changes) - //=============================|================================================ - uint256 public airDropPot_; // person who gets the airdrop wins part of this pot - uint256 public airDropTracker_ = 0; // incremented each time a "qualified" tx occurs. used to determine winning air drop - uint256 public rID_; // round id number / total rounds that have happened - //**************** - // PLAYER DATA - //**************** - mapping(address => uint256) public pIDxAddr_; // (addr => pID) returns player id by address - mapping(bytes32 => uint256) public pIDxName_; // (name => pID) returns player id by name - mapping(uint256 => F3Ddatasets.Player) public plyr_; // (pID => data) player data - mapping(uint256 => mapping(uint256 => F3Ddatasets.PlayerRounds)) public plyrRnds_; // (pID => rID => data) player round data by player id & round id - mapping(uint256 => mapping(bytes32 => bool)) public plyrNames_; // (pID => name => bool) list of names a player owns. (used so you can change your display name amongst any name you own) - //**************** - // ROUND DATA - //**************** - mapping(uint256 => F3Ddatasets.Round) public round_; // (rID => data) round data - mapping(uint256 => mapping(uint256 => uint256)) public rndTmEth_; // (rID => tID => data) eth in per team, by round id and team id - //**************** - // TEAM FEE DATA - //**************** - mapping(uint256 => F3Ddatasets.TeamFee) public fees_; // (team => fees) fee distribution by team - mapping(uint256 => F3Ddatasets.PotSplit) public potSplit_; // (team => fees) pot split distribution by team - - function setPlayerBook(address _playerBook) external { - require(msg.sender == owner, 'only dev!'); - require(address(playerBook) == address(0), 'already set!'); - playerBook = PlayerBookInterface(_playerBook); - } - - address public owner; - - //============================================================================== - // _ _ _ __|_ _ __|_ _ _ . - // (_(_)| |_\ | | |_|(_ | (_)| . (initial data setup upon contract deploy) - //============================================================================== - constructor() - public - { - owner = msg.sender; - // Team allocation structures - // 0 = whales - // 1 = bears - // 2 = sneks - // 3 = bulls - - // Team allocation percentages - // (F3D, P3D) + (Pot , Referrals, Community) - // Referrals / Community rewards are mathematically designed to come from the winner's share of the pot. - fees_[0] = F3Ddatasets.TeamFee(30, 6); - //50% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - fees_[1] = F3Ddatasets.TeamFee(43, 0); - //43% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - fees_[2] = F3Ddatasets.TeamFee(56, 10); - //20% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - fees_[3] = F3Ddatasets.TeamFee(43, 8); - //35% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - - // how to split up the final pot based on which team was picked - // (F3D, P3D) - potSplit_[0] = F3Ddatasets.PotSplit(15, 10); - //48% to winner, 25% to next round, 2% to com - potSplit_[1] = F3Ddatasets.PotSplit(25, 0); - //48% to winner, 25% to next round, 2% to com - potSplit_[2] = F3Ddatasets.PotSplit(20, 20); - //48% to winner, 10% to next round, 2% to com - potSplit_[3] = F3Ddatasets.PotSplit(30, 10); - //48% to winner, 10% to next round, 2% to com - } - //============================================================================== - // _ _ _ _|. |`. _ _ _ . - // | | |(_)(_||~|~|(/_| _\ . (these are safety checks) - //============================================================================== - /** - * @dev used to make sure no one can interact with contract until it has - * been activated. - */ - modifier isActivated() { - require(activated_ == true, "its not ready yet. check ?eta in discord"); - _; - } - - /** - * @dev prevents contracts from interacting with fomo3d - */ - modifier isHuman() { - address _addr = msg.sender; - uint256 _codeLength; - - assembly {_codeLength := extcodesize(_addr)} - require(_codeLength == 0, "sorry humans only"); - _; - } - - modifier onlyDevs() - { - require(playerBook.isDev(msg.sender) == true, "msg sender is not a dev"); - _; - } - - /** - * @dev sets boundaries for incoming tx - */ - modifier isWithinLimits(uint256 _eth) { - require(_eth >= 1000000000, "pocket lint: not a valid currency"); - require(_eth <= 100000000000000000000000, "no vitalik, no"); - _; - } - - //============================================================================== - // _ |_ |. _ |` _ __|_. _ _ _ . - // |_)|_||_)||(_ ~|~|_|| |(_ | |(_)| |_\ . (use these to interact with contract) - //====|========================================================================= - /** - * @dev emergency buy uses last stored affiliate ID and team snek - */ - fallback() - isActivated() - isHuman() - isWithinLimits(msg.value) - external - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_ ; - _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // buy core - buyCore(_pID, plyr_[_pID].laff, 2, _eventData_); - } - - /** - * @dev converts all incoming ethereum to keys. - * -functionhash- 0x8f38f309 (using ID for affiliate) - * -functionhash- 0x98a0871d (using address for affiliate) - * -functionhash- 0xa65b37a1 (using name for affiliate) - * @param _affCode the ID/address/name of the player who gets the affiliate fee - * @param _team what team is the player playing for? - */ - function buyXid(uint256 _affCode, uint256 _team) - isActivated() - isHuman() - isWithinLimits(msg.value) - public - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_; - _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == 0 || _affCode == _pID) - { - // use last stored affiliate code - _affCode = plyr_[_pID].laff; - - // if affiliate code was given & its not the same as previously stored - } else if (_affCode != plyr_[_pID].laff) { - // update last affiliate - plyr_[_pID].laff = _affCode; - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // buy core - buyCore(_pID, _affCode, _team, _eventData_); - } - - function buyXaddr(address _affCode, uint256 _team) - isActivated() - isHuman() - isWithinLimits(msg.value) - public - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_; - _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == address(0) || _affCode == msg.sender) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxAddr_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // buy core - buyCore(_pID, _affID, _team, _eventData_); - } - - function buyXname(bytes32 _affCode, uint256 _team) - isActivated() - isHuman() - isWithinLimits(msg.value) - public - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_ ; - _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == '' || _affCode == plyr_[_pID].name) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxName_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // buy core - buyCore(_pID, _affID, _team, _eventData_); - } - - /** - * @dev essentially the same as buy, but instead of you sending ether - * from your wallet, it uses your unwithdrawn earnings. - * -functionhash- 0x349cdcac (using ID for affiliate) - * -functionhash- 0x82bfc739 (using address for affiliate) - * -functionhash- 0x079ce327 (using name for affiliate) - * @param _affCode the ID/address/name of the player who gets the affiliate fee - * @param _team what team is the player playing for? - * @param _eth amount of earnings to use (remainder returned to gen vault) - */ - function reLoadXid(uint256 _affCode, uint256 _team, uint256 _eth) - isActivated() - isHuman() - isWithinLimits(_eth) - public - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == 0 || _affCode == _pID) - { - // use last stored affiliate code - _affCode = plyr_[_pID].laff; - - // if affiliate code was given & its not the same as previously stored - } else if (_affCode != plyr_[_pID].laff) { - // update last affiliate - plyr_[_pID].laff = _affCode; - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // reload core - reLoadCore(_pID, _affCode, _team, _eth, _eventData_); - } - - function reLoadXaddr(address _affCode, uint256 _team, uint256 _eth) - isActivated() - isHuman() - isWithinLimits(_eth) - public - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == address(0) || _affCode == msg.sender) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxAddr_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // reload core - reLoadCore(_pID, _affID, _team, _eth, _eventData_); - } - - function reLoadXname(bytes32 _affCode, uint256 _team, uint256 _eth) - isActivated() - isHuman() - isWithinLimits(_eth) - public - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == '' || _affCode == plyr_[_pID].name) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxName_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // reload core - reLoadCore(_pID, _affID, _team, _eth, _eventData_); - } - - /** - * @dev withdraws all of your earnings. - * -functionhash- 0x3ccfd60b - */ - function withdraw() - isActivated() - isHuman() - public - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = block.timestamp; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // setup temp var for player eth - uint256 _eth; - - // check to see if round has ended and no one has run round end yet - if (_now > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // end the round (distributes pot) - round_[_rID].ended = true; - _eventData_ = endRound(_eventData_); - - // get their earnings - _eth = withdrawEarnings(_pID); - - // gib moni - if (_eth > 0) - plyr_[_pID].addr.transfer(_eth); - - // build event data - _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; - - // fire withdraw and distribute event - emit F3Devents.onWithdrawAndDistribute - ( - msg.sender, - plyr_[_pID].name, - _eth, - _eventData_.compressedData, - _eventData_.compressedIDs, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount - ); - - // in any other situation - } else { - // get their earnings - _eth = withdrawEarnings(_pID); - - // gib moni - if (_eth > 0) - plyr_[_pID].addr.transfer(_eth); - - // fire withdraw event - emit F3Devents.onWithdraw(_pID, msg.sender, plyr_[_pID].name, _eth, _now); - } - } - - /** - * @dev use these to register names. they are just wrappers that will send the - * registration requests to the PlayerBook contract. So registering here is the - * same as registering there. UI will always display the last name you registered. - * but you will still own all previously registered names to use as affiliate - * links. - * - must pay a registration fee. - * - name must be unique - * - names will be converted to lowercase - * - name cannot start or end with a space - * - cannot have more than 1 space in a row - * - cannot be only numbers - * - cannot start with 0x - * - name must be at least 1 char - * - max length of 32 characters long - * - allowed characters: a-z, 0-9, and space - * -functionhash- 0x921dec21 (using ID for affiliate) - * -functionhash- 0x3ddd4698 (using address for affiliate) - * -functionhash- 0x685ffd83 (using name for affiliate) - * @param _nameString players desired name - * @param _affCode affiliate ID, address, or name of who referred you - * @param _all set to true if you want this to push your info to all games - * (this might cost a lot of gas) - */ - function registerNameXID(string memory _nameString, uint256 _affCode, bool _all) - isHuman() - public - payable - { - bytes32 _name = _nameString.nameFilter(); - address _addr = msg.sender; - uint256 _paid = msg.value; - (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXIDFromDapp{value:_paid}(_addr, _name, _affCode, _all); - - uint256 _pID = pIDxAddr_[_addr]; - - // fire event - emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, block.timestamp); - } - - function registerNameXaddr(string memory _nameString, address _affCode, bool _all) - isHuman() - public - payable - { - bytes32 _name = _nameString.nameFilter(); - address _addr = msg.sender; - uint256 _paid = msg.value; - (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXaddrFromDapp{value:msg.value}(msg.sender, _name, _affCode, _all); - - uint256 _pID = pIDxAddr_[_addr]; - - // fire event - emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, block.timestamp); - } - - function registerNameXname(string memory _nameString, bytes32 _affCode, bool _all) - isHuman() - public - payable - { - bytes32 _name = _nameString.nameFilter(); - address _addr = msg.sender; - uint256 _paid = msg.value; - (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXnameFromDapp{value:msg.value}(msg.sender, _name, _affCode, _all); - - uint256 _pID = pIDxAddr_[_addr]; - - // fire event - emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, block.timestamp); - } - //============================================================================== - // _ _ _|__|_ _ _ _ . - // (_|(/_ | | (/_| _\ . (for UI & viewing things on etherscan) - //=====_|======================================================================= - /** - * @dev return the price buyer will pay for next 1 individual key. - * -functionhash- 0x018a25e8 - * @return price for next key bought (in wei format) - */ - function getBuyPrice() - public - view - returns (uint256) - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = block.timestamp; - - // are we in a round? - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - return ((round_[_rID].keys.add(1000000000000000000)).ethRec(1000000000000000000)); - else // rounds over. need price for new round - return (75000000000000); - // init - } - - /** - * @dev returns time left. dont spam this, you'll ddos yourself from your node - * provider - * -functionhash- 0xc7e284b8 - * @return time left in seconds - */ - function getTimeLeft() - public - view - returns (uint256) - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = block.timestamp; - - if (_now < round_[_rID].end) - if (_now > round_[_rID].strt + rndGap_) - return ((round_[_rID].end).sub(_now)); - else - return ((round_[_rID].strt + rndGap_).sub(_now)); - else - return (0); - } - - /** - * @dev returns player earnings per vaults - * -functionhash- 0x63066434 - * @return winnings vault - * @return general vault - * @return affiliate vault - */ - function getPlayerVaults(uint256 _pID) - public - view - returns (uint256, uint256, uint256) - { - // setup local rID - uint256 _rID = rID_; - - // if round has ended. but round end has not been run (so contract has not distributed winnings) - if (block.timestamp > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) - { - // if player is winner - if (round_[_rID].plyr == _pID) - { - return - ( - (plyr_[_pID].win).add(((round_[_rID].pot).mul(48)) / 100), - (plyr_[_pID].gen).add(getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask)), - plyr_[_pID].aff - ); - // if player is not the winner - } else { - return - ( - plyr_[_pID].win, - (plyr_[_pID].gen).add(getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask)), - plyr_[_pID].aff - ); - } - - // if round is still going on, or round has ended and round end has been ran - } else { - return - ( - plyr_[_pID].win, - (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), - plyr_[_pID].aff - ); - } - } - - /** - * solidity hates stack limits. this lets us avoid that hate - */ - function getPlayerVaultsHelper(uint256 _pID, uint256 _rID) - private - view - returns (uint256) - { - return (((((round_[_rID].mask).add(((((round_[_rID].pot).mul(potSplit_[round_[_rID].team].gen)) / 100).mul(1000000000000000000)) / (round_[_rID].keys))).mul(plyrRnds_[_pID][_rID].keys)) / 1000000000000000000)); - } - - /** - * @dev returns all current round info needed for front end - * -functionhash- 0x747dff42 - * @return eth invested during ICO phase - * @return round id - * @return total keys for round - * @return time round ends - * @return time round started - * @return current pot - * @return current team ID & player ID in lead - * @return current player in leads address - * @return current player in leads name - * @return whales eth in for round - * @return bears eth in for round - * @return sneks eth in for round - * @return bulls eth in for round - * @return airdrop tracker # & airdrop pot - */ - function getCurrentRoundInfo() - public - view - returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256, address, bytes32, uint256, uint256, uint256, uint256, uint256) - { - // setup local rID - uint256 _rID = rID_; - - return - ( - round_[_rID].ico, //0 - _rID, //1 - round_[_rID].keys, //2 - round_[_rID].end, //3 - round_[_rID].strt, //4 - round_[_rID].pot, //5 - (round_[_rID].team + (round_[_rID].plyr * 10)), //6 - plyr_[round_[_rID].plyr].addr, //7 - plyr_[round_[_rID].plyr].name, //8 - rndTmEth_[_rID][0], //9 - rndTmEth_[_rID][1], //10 - rndTmEth_[_rID][2], //11 - rndTmEth_[_rID][3], //12 - airDropTracker_ + (airDropPot_ * 1000) //13 - ); - } - - /** - * @dev returns player info based on address. if no address is given, it will - * use msg.sender - * -functionhash- 0xee0b5d8b - * @param _addr address of the player you want to lookup - * @return player ID - * @return player name - * @return keys owned (current round) - * @return winnings vault - * @return general vault - * @return affiliate vault - * @return player round eth - */ - function getPlayerInfoByAddress(address _addr) - public - view - returns (uint256, bytes32, uint256, uint256, uint256, uint256, uint256) - { - // setup local rID - uint256 _rID = rID_; - - if (_addr == address(0)) - { - _addr == msg.sender; - } - uint256 _pID = pIDxAddr_[_addr]; - - return - ( - _pID, //0 - plyr_[_pID].name, //1 - plyrRnds_[_pID][_rID].keys, //2 - plyr_[_pID].win, //3 - (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), //4 - plyr_[_pID].aff, //5 - plyrRnds_[_pID][_rID].eth //6 - ); - } - - //============================================================================== - // _ _ _ _ | _ _ . _ . - // (_(_)| (/_ |(_)(_||(_ . (this + tools + calcs + modules = our softwares engine) - //=====================_|======================================================= - /** - * @dev logic runs whenever a buy order is executed. determines how to handle - * incoming eth depending on if we are in an active round or not - */ - function buyCore(uint256 _pID, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) - private - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = block.timestamp; - - // if round is active - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - { - // call core - core(_rID, _pID, msg.value, _affID, _team, _eventData_); - - // if round is not active - } else { - // check to see if end round needs to be ran - if (_now > round_[_rID].end && round_[_rID].ended == false) - { - // end the round (distributes pot) & start new round - round_[_rID].ended = true; - _eventData_ = endRound(_eventData_); - - // build event data - _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; - - // fire buy and distribute event - emit F3Devents.onBuyAndDistribute - ( - msg.sender, - plyr_[_pID].name, - msg.value, - _eventData_.compressedData, - _eventData_.compressedIDs, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount - ); - } - - // put eth in players vault - plyr_[_pID].gen = plyr_[_pID].gen.add(msg.value); - } - } - - /** - * @dev logic runs whenever a reload order is executed. determines how to handle - * incoming eth depending on if we are in an active round or not - */ - function reLoadCore(uint256 _pID, uint256 _affID, uint256 _team, uint256 _eth, F3Ddatasets.EventReturns memory _eventData_) - private - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = block.timestamp; - - // if round is active - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - { - // get earnings from all vaults and return unused to gen vault - // because we use a custom safemath library. this will throw if player - // tried to spend more eth than they have. - plyr_[_pID].gen = withdrawEarnings(_pID).sub(_eth); - - // call core - core(_rID, _pID, _eth, _affID, _team, _eventData_); - - // if round is not active and end round needs to be ran - } else if (_now > round_[_rID].end && round_[_rID].ended == false) { - // end the round (distributes pot) & start new round - round_[_rID].ended = true; - _eventData_ = endRound(_eventData_); - - // build event data - _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; - - // fire buy and distribute event - emit F3Devents.onReLoadAndDistribute - ( - msg.sender, - plyr_[_pID].name, - _eventData_.compressedData, - _eventData_.compressedIDs, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount - ); - } - } - - /** - * @dev this is the core logic for any buy/reload that happens while a round - * is live. - */ - function core(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) - private - { - // if player is new to round - if (plyrRnds_[_pID][_rID].keys == 0) - _eventData_ = managePlayer(_pID, _eventData_); - - // early round eth limiter - if (round_[_rID].eth < 100000000000000000000 && plyrRnds_[_pID][_rID].eth.add(_eth) > 1000000000000000000) - { - uint256 _availableLimit = (1000000000000000000).sub(plyrRnds_[_pID][_rID].eth); - uint256 _refund = _eth.sub(_availableLimit); - plyr_[_pID].gen = plyr_[_pID].gen.add(_refund); - _eth = _availableLimit; - } - - // if eth left is greater than min eth allowed (sorry no pocket lint) - if (_eth > 1000000000) - { - - // mint the new keys - uint256 _keys = (round_[_rID].eth).keysRec(_eth); - - // if they bought at least 1 whole key - if (_keys >= 1000000000000000000) - { - updateTimer(_keys, _rID); - - // set new leaders - if (round_[_rID].plyr != _pID) - round_[_rID].plyr = _pID; - if (round_[_rID].team != _team) - round_[_rID].team = _team; - - // set the new leader bool to true - _eventData_.compressedData = _eventData_.compressedData + 100; - } - - // manage airdrops - if (_eth >= 100000000000000000) - { - airDropTracker_++; - if (airdrop() == true) - { - // gib muni - uint256 _prize; - if (_eth >= 10000000000000000000) - { - // calculate prize and give it to winner - _prize = ((airDropPot_).mul(75)) / 100; - plyr_[_pID].win = (plyr_[_pID].win).add(_prize); - - // adjust airDropPot - airDropPot_ = (airDropPot_).sub(_prize); - - // let event know a tier 3 prize was won - _eventData_.compressedData += 300000000000000000000000000000000; - } else if (_eth >= 1000000000000000000 && _eth < 10000000000000000000) { - // calculate prize and give it to winner - _prize = ((airDropPot_).mul(50)) / 100; - plyr_[_pID].win = (plyr_[_pID].win).add(_prize); - - // adjust airDropPot - airDropPot_ = (airDropPot_).sub(_prize); - - // let event know a tier 2 prize was won - _eventData_.compressedData += 200000000000000000000000000000000; - } else if (_eth >= 100000000000000000 && _eth < 1000000000000000000) { - // calculate prize and give it to winner - _prize = ((airDropPot_).mul(25)) / 100; - plyr_[_pID].win = (plyr_[_pID].win).add(_prize); - - // adjust airDropPot - airDropPot_ = (airDropPot_).sub(_prize); - - // let event know a tier 3 prize was won - _eventData_.compressedData += 300000000000000000000000000000000; - } - // set airdrop happened bool to true - _eventData_.compressedData += 10000000000000000000000000000000; - // let event know how much was won - _eventData_.compressedData += _prize * 1000000000000000000000000000000000; - - // reset air drop tracker - airDropTracker_ = 0; - } - } - - // store the air drop tracker number (number of buys since last airdrop) - _eventData_.compressedData = _eventData_.compressedData + (airDropTracker_ * 1000); - - // update player - plyrRnds_[_pID][_rID].keys = _keys.add(plyrRnds_[_pID][_rID].keys); - plyrRnds_[_pID][_rID].eth = _eth.add(plyrRnds_[_pID][_rID].eth); - - // update round - round_[_rID].keys = _keys.add(round_[_rID].keys); - round_[_rID].eth = _eth.add(round_[_rID].eth); - rndTmEth_[_rID][_team] = _eth.add(rndTmEth_[_rID][_team]); - - // distribute eth - _eventData_ = distributeExternal(_rID, _pID, _eth, _affID, _team, _eventData_); - _eventData_ = distributeInternal(_rID, _pID, _eth, _team, _keys, _eventData_); - - // call end tx function to fire end tx event. - endTx(_pID, _team, _eth, _keys, _eventData_); - } - } - //============================================================================== - // _ _ | _ | _ _|_ _ _ _ . - // (_(_||(_|_||(_| | (_)| _\ . - //============================================================================== - /** - * @dev calculates unmasked earnings (just calculates, does not update mask) - * @return earnings in wei format - */ - function calcUnMaskedEarnings(uint256 _pID, uint256 _rIDlast) - private - view - returns (uint256) - { - return ((((round_[_rIDlast].mask).mul(plyrRnds_[_pID][_rIDlast].keys)) / (1000000000000000000)).sub(plyrRnds_[_pID][_rIDlast].mask)); - } - - /** - * @dev returns the amount of keys you would get given an amount of eth. - * -functionhash- 0xce89c80c - * @param _rID round ID you want price for - * @param _eth amount of eth sent in - * @return keys received - */ - function calcKeysReceived(uint256 _rID, uint256 _eth) - public - view - returns (uint256) - { - // grab time - uint256 _now = block.timestamp; - - // are we in a round? - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - return ((round_[_rID].eth).keysRec(_eth)); - else // rounds over. need keys for new round - return ((_eth).keys()); - } - - /** - * @dev returns current eth price for X keys. - * -functionhash- 0xcf808000 - * @param _keys number of keys desired (in 18 decimal format) - * @return amount of eth needed to send - */ - function iWantXKeys(uint256 _keys) - public - view - returns (uint256) - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = block.timestamp; - - // are we in a round? - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - return ((round_[_rID].keys.add(_keys)).ethRec(_keys)); - else // rounds over. need price for new round - return ((_keys).eth()); - } - //============================================================================== - // _|_ _ _ | _ . - // | (_)(_)|_\ . - //============================================================================== - /** - * @dev receives name/player info from names contract - */ - function receivePlayerInfo(uint256 _pID, address payable _addr, bytes32 _name, uint256 _laff) - external - { - require(msg.sender == address(playerBook), "your not playerNames contract... hmmm.."); - if (pIDxAddr_[_addr] != _pID) - pIDxAddr_[_addr] = _pID; - if (pIDxName_[_name] != _pID) - pIDxName_[_name] = _pID; - if (plyr_[_pID].addr != _addr) - plyr_[_pID].addr = _addr; - if (plyr_[_pID].name != _name) - plyr_[_pID].name = _name; - if (plyr_[_pID].laff != _laff) - plyr_[_pID].laff = _laff; - if (plyrNames_[_pID][_name] == false) - plyrNames_[_pID][_name] = true; - } - - /** - * @dev receives entire player name list - */ - function receivePlayerNameList(uint256 _pID, bytes32 _name) - external - { - require(msg.sender == address(playerBook), "your not playerNames contract... hmmm.."); - if (plyrNames_[_pID][_name] == false) - plyrNames_[_pID][_name] = true; - } - - /** - * @dev gets existing or registers new pID. use this when a player may be new - * @return pID - */ - function determinePID(F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - uint256 _pID = pIDxAddr_[msg.sender]; - // if player is new to this version of fomo3d - if (_pID == 0) - { - // grab their player ID, name and last aff ID, from player names contract - _pID = playerBook.getPlayerID(msg.sender); - bytes32 _name = playerBook.getPlayerName(_pID); - uint256 _laff = playerBook.getPlayerLAff(_pID); - - // set up player account - pIDxAddr_[msg.sender] = _pID; - plyr_[_pID].addr = payable(msg.sender); - - if (_name != "") - { - pIDxName_[_name] = _pID; - plyr_[_pID].name = _name; - plyrNames_[_pID][_name] = true; - } - - if (_laff != 0 && _laff != _pID) - plyr_[_pID].laff = _laff; - - // set the new player bool to true - _eventData_.compressedData = _eventData_.compressedData + 1; - } - return (_eventData_); - } - - /** - * @dev checks to make sure user picked a valid team. if not sets team - * to default (sneks) - */ - function verifyTeam(uint256 _team) - private - pure - returns (uint256) - { - if (_team < 0 || _team > 3) - return (2); - else - return (_team); - } - - /** - * @dev decides if round end needs to be run & new round started. and if - * player unmasked earnings from previously played rounds need to be moved. - */ - function managePlayer(uint256 _pID, F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - // if player has played a previous round, move their unmasked earnings - // from that round to gen vault. - if (plyr_[_pID].lrnd != 0) - updateGenVault(_pID, plyr_[_pID].lrnd); - - // update player's last round played - plyr_[_pID].lrnd = rID_; - - // set the joined round bool to true - _eventData_.compressedData = _eventData_.compressedData + 10; - - return (_eventData_); - } - - /** - * @dev ends the round. manages paying out winner/splitting up pot - */ - function endRound(F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - // setup local rID - uint256 _rID = rID_; - - // grab our winning player and team id's - uint256 _winPID = round_[_rID].plyr; - uint256 _winTID = round_[_rID].team; - - // grab our pot amount - uint256 _pot = round_[_rID].pot; - - // calculate our winner share, community rewards, gen share, - // p3d share, and amount reserved for next pot - uint256 _win = (_pot.mul(48)) / 100; - uint256 _com = (_pot / 50); - uint256 _gen = (_pot.mul(potSplit_[_winTID].gen)) / 100; - uint256 _p3d = (_pot.mul(potSplit_[_winTID].p3d)) / 100; - uint256 _res = (((_pot.sub(_win)).sub(_com)).sub(_gen)).sub(_p3d); - - // calculate ppt for round mask - uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); - uint256 _dust = _gen.sub((_ppt.mul(round_[_rID].keys)) / 1000000000000000000); - if (_dust > 0) - { - _gen = _gen.sub(_dust); - _res = _res.add(_dust); - } - - // pay our winner - plyr_[_winPID].win = _win.add(plyr_[_winPID].win); - - // community rewards - address payable add = payable(address(uint160(Jekyll_Island_Inc))); - if (!add.send(_com)) - { - // This ensures Team Just cannot influence the outcome of FoMo3D with - // bank migrations by breaking outgoing transactions. - // Something we would never do. But that's not the point. - // We spent 2000$ in eth re-deploying just to patch this, we hold the - // highest belief that everything we create should be trustless. - // Team JUST, The name you shouldn't have to trust. - _p3d = _p3d.add(_com); - _com = 0; - } - - // distribute gen portion to key holders - round_[_rID].mask = _ppt.add(round_[_rID].mask); - - // send share for p3d to divies - if (_p3d > 0){ - address payable addr = payable(address(uint160(Divies))); - addr.transfer(_p3d); - } - // prepare event data - _eventData_.compressedData = _eventData_.compressedData + (round_[_rID].end * 1000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + (_winPID * 100000000000000000000000000) + (_winTID * 100000000000000000); - _eventData_.winnerAddr = plyr_[_winPID].addr; - _eventData_.winnerName = plyr_[_winPID].name; - _eventData_.amountWon = _win; - _eventData_.genAmount = _gen; - _eventData_.P3DAmount = _p3d; - _eventData_.newPot = _res; - - // start next round - rID_++; - _rID++; - round_[_rID].strt = block.timestamp; - round_[_rID].end = block.timestamp.add(rndInit_).add(rndGap_); - round_[_rID].pot = _res; - - return (_eventData_); - } - - /** - * @dev moves any unmasked earnings to gen vault. updates earnings mask - */ - function updateGenVault(uint256 _pID, uint256 _rIDlast) - private - { - uint256 _earnings = calcUnMaskedEarnings(_pID, _rIDlast); - if (_earnings > 0) - { - // put in gen vault - plyr_[_pID].gen = _earnings.add(plyr_[_pID].gen); - // zero out their earnings by updating mask - plyrRnds_[_pID][_rIDlast].mask = _earnings.add(plyrRnds_[_pID][_rIDlast].mask); - } - } - - /** - * @dev updates round timer based on number of whole keys bought. - */ - function updateTimer(uint256 _keys, uint256 _rID) - private - { - // grab time - uint256 _now = block.timestamp; - - // calculate time based on number of keys bought - uint256 _newTime; - if (_now > round_[_rID].end && round_[_rID].plyr == 0) - _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(_now); - else - _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(round_[_rID].end); - - // compare to max and set new end time - if (_newTime < (rndMax_).add(_now)) - round_[_rID].end = _newTime; - else - round_[_rID].end = rndMax_.add(_now); - } - - /** - * @dev generates a random number between 0-99 and checks to see if thats - * resulted in an airdrop win - * @return do we have a winner? - */ - function airdrop() - private - view - returns (bool) - { - uint256 seed = uint256(keccak256(abi.encodePacked( - - (block.timestamp).add - (block.difficulty).add - ((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (block.timestamp)).add - (block.gaslimit).add - ((uint256(keccak256(abi.encodePacked(msg.sender)))) / (block.timestamp)).add - (block.number) - - ))); - if ((seed - ((seed / 1000) * 1000)) < airDropTracker_) - return (true); - else - return (false); - } - - /** - * @dev distributes eth based on fees to com, aff, and p3d - */ - function distributeExternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - // pay 2% out to community rewards - uint256 _com = _eth / 50; - uint256 _p3d; - address payable addr = payable(address(uint160(Jekyll_Island_Inc))); - if (!addr.send(_com)) - { - // This ensures Team Just cannot influence the outcome of FoMo3D with - // bank migrations by breaking outgoing transactions. - // Something we would never do. But that's not the point. - // We spent 2000$ in eth re-deploying just to patch this, we hold the - // highest belief that everything we create should be trustless. - // Team JUST, The name you shouldn't have to trust. - _p3d = _com; - _com = 0; - } - - // pay 1% out to FoMo3D short - _com = _eth / 100; - address payable add = payable(address(uint160(otherF3D_))); - add.transfer(_com); - - // distribute share to affiliate - _com = _eth / 10; - - // decide what to do with affiliate share of fees - // affiliate must not be self, and must have a name registered - if (_affID != _pID && plyr_[_affID].name != '') { - plyr_[_affID].aff = _com.add(plyr_[_affID].aff); - emit F3Devents.onAffiliatePayout(_affID, plyr_[_affID].addr, plyr_[_affID].name, _rID, _pID, _com, block.timestamp); - } else { - _p3d = _com; - } - - // pay out p3d - _p3d = _p3d.add((_eth.mul(fees_[_team].p3d)) / (100)); - if (_p3d > 0) - { - // deposit to divies contract - address payable add = payable(address(uint160(Divies))); - add.transfer(_p3d); - - // set up event data - _eventData_.P3DAmount = _p3d.add(_eventData_.P3DAmount); - } - - return (_eventData_); - } - - function potSwap() - external - payable - { - // setup local rID - uint256 _rID = rID_ + 1; - - round_[_rID].pot = round_[_rID].pot.add(msg.value); - emit F3Devents.onPotSwapDeposit(_rID, msg.value); - } - - /** - * @dev distributes eth based on fees to gen and pot - */ - function distributeInternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _team, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - // calculate gen share - uint256 _gen = (_eth.mul(fees_[_team].gen)) / 100; - - // toss 1% into airdrop pot - uint256 _air = (_eth / 100); - airDropPot_ = airDropPot_.add(_air); - - // update eth balance (eth = eth - (com share + pot swap share + aff share + p3d share + airdrop pot share)) - _eth = _eth.sub(((_eth.mul(14)) / 100).add((_eth.mul(fees_[_team].p3d)) / 100)); - - // calculate pot - uint256 _pot = _eth.sub(_gen); - - // distribute gen share (thats what updateMasks() does) and adjust - // balances for dust. - uint256 _dust = updateMasks(_rID, _pID, _gen, _keys); - if (_dust > 0) - _gen = _gen.sub(_dust); - - // add eth to pot - round_[_rID].pot = _pot.add(_dust).add(round_[_rID].pot); - - // set up event data - _eventData_.genAmount = _gen.add(_eventData_.genAmount); - _eventData_.potAmount = _pot; - - return (_eventData_); - } - - /** - * @dev updates masks for round and player when keys are bought - * @return dust left over - */ - function updateMasks(uint256 _rID, uint256 _pID, uint256 _gen, uint256 _keys) - private - returns (uint256) - { - /* MASKING NOTES - earnings masks are a tricky thing for people to wrap their minds around. - the basic thing to understand here. is were going to have a global - tracker based on profit per share for each round, that increases in - relevant proportion to the increase in share supply. - - the player will have an additional mask that basically says "based - on the rounds mask, my shares, and how much i've already withdrawn, - how much is still owed to me?" - */ - - // calc profit per key & round mask based on this buy: (dust goes to pot) - uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); - round_[_rID].mask = _ppt.add(round_[_rID].mask); - - // calculate player earning from their own buy (only based on the keys - // they just bought). & update player earnings mask - uint256 _pearn = (_ppt.mul(_keys)) / (1000000000000000000); - plyrRnds_[_pID][_rID].mask = (((round_[_rID].mask.mul(_keys)) / (1000000000000000000)).sub(_pearn)).add(plyrRnds_[_pID][_rID].mask); - - // calculate & return dust - return (_gen.sub((_ppt.mul(round_[_rID].keys)) / (1000000000000000000))); - } - - /** - * @dev adds up unmasked earnings, & vault earnings, sets them all to 0 - * @return earnings in wei format - */ - function withdrawEarnings(uint256 _pID) - private - returns (uint256) - { - // update gen vault - updateGenVault(_pID, plyr_[_pID].lrnd); - - // from vaults - uint256 _earnings = (plyr_[_pID].win).add(plyr_[_pID].gen).add(plyr_[_pID].aff); - if (_earnings > 0) - { - plyr_[_pID].win = 0; - plyr_[_pID].gen = 0; - plyr_[_pID].aff = 0; - } - - return (_earnings); - } - - /** - * @dev prepares compression data and fires event for buy or reload tx's - */ - function endTx(uint256 _pID, uint256 _team, uint256 _eth, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) - private - { - _eventData_.compressedData = _eventData_.compressedData + (block.timestamp * 1000000000000000000) + (_team * 100000000000000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID + (rID_ * 10000000000000000000000000000000000000000000000000000); - - emit F3Devents.onEndTx - ( - _eventData_.compressedData, - _eventData_.compressedIDs, - plyr_[_pID].name, - msg.sender, - _eth, - _keys, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount, - _eventData_.potAmount, - airDropPot_ - ); - } - //============================================================================== - // (~ _ _ _._|_ . - // _)(/_(_|_|| | | \/ . - //====================/========================================================= - /** upon contract deploy, it will be deactivated. this is a one time - * use function that will activate the contract. we do this so devs - * have time to set things up on the web end **/ - bool public activated_ = false; - - function activate() - public - onlyDevs - { - - // can only be ran once - require(activated_ == false, "fomo3d already activated"); - - // activate the contract - activated_ = true; - - otherF3D_ = msg.sender; - Divies = msg.sender; - Jekyll_Island_Inc = msg.sender; - - // lets start first round - rID_ = 1; - round_[1].strt = block.timestamp + rndExtra_ - rndGap_; - round_[1].end = block.timestamp + rndInit_ + rndExtra_; - } - - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractScenario007.sol b/framework/src/test/resources/soliditycode/contractScenario007.sol deleted file mode 100644 index a6fa095860f..00000000000 --- a/framework/src/test/resources/soliditycode/contractScenario007.sol +++ /dev/null @@ -1,1432 +0,0 @@ - -/** - * @title ERC165 - * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md - */ -interface ERC165 { - - /** - * @notice Query if a contract implements an interface - * @param _interfaceId The interface identifier, as specified in ERC-165 - * @dev Interface identification is specified in ERC-165. This function - * uses less than 30,000 gas. - */ - function supportsInterface(bytes4 _interfaceId) external view returns (bool); - -} - -contract ERC721Basic is ERC165 { - - event Transfer( - address indexed _from, - address indexed _to, - uint256 indexed _tokenId - ); - event Approval( - address indexed _owner, - address indexed _approved, - uint256 indexed _tokenId - ); - event ApprovalForAll( - address indexed _owner, - address indexed _operator, - bool _approved - ); - - function balanceOf(address _owner) public view returns (uint256 _balance); - function ownerOf(uint256 _tokenId) public view returns (address _owner); - function exists(uint256 _tokenId) public view returns (bool _exists); - - function approve(address _to, uint256 _tokenId) public; - function getApproved(uint256 _tokenId) - public view returns (address _operator); - - function setApprovalForAll(address _operator, bool _approved) public; - function isApprovedForAll(address _owner, address _operator) - public view returns (bool); - - function transferFrom(address _from, address _to, uint256 _tokenId) public; - function safeTransferFrom(address _from, address _to, uint256 _tokenId) - public; - - function safeTransferFrom( - address _from, - address _to, - uint256 _tokenId, - bytes memory _data - ) - public; -} - - -/** - * @title SupportsInterfaceWithLookup - * @author Matt Condon (@shrugs) - * @dev Implements ERC165 using a lookup table. - */ -contract SupportsInterfaceWithLookup is ERC165 { - bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7; - /** - * 0x01ffc9a7 === - * bytes4(keccak256('supportsInterface(bytes4)')) - */ - - /** - * @dev a mapping of interface id to whether or not it's supported - */ - mapping(bytes4 => bool) internal supportedInterfaces; - - /** - * @dev A contract implementing SupportsInterfaceWithLookup - * implement ERC165 itself - */ - constructor() public { - _registerInterface(InterfaceId_ERC165); - } - - /** - * @dev implement supportsInterface(bytes4) using a lookup table - */ - function supportsInterface(bytes4 _interfaceId) external view returns (bool) { - return supportedInterfaces[_interfaceId]; - } - - /** - * @dev private method for registering an interface - */ - function _registerInterface(bytes4 _interfaceId) internal { - require(_interfaceId != 0xffffffff); - supportedInterfaces[_interfaceId] = true; - } -} - -contract Governable { - - event Pause(); - event Unpause(); - - address public governor; - bool public paused = false; - - constructor() public { - governor = msg.sender; - } - - function setGovernor(address _gov) public onlyGovernor { - governor = _gov; - } - - modifier onlyGovernor { - require(msg.sender == governor); - _; - } - - /** - * @dev Modifier to make a function callable only when the contract is not paused. - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev Modifier to make a function callable only when the contract is paused. - */ - modifier whenPaused() { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyGovernor whenNotPaused public { - paused = true; - emit Pause(); - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyGovernor whenPaused public { - paused = false; - emit Unpause(); - } - -} - -contract CardBase is Governable { - - struct Card { - uint16 proto; - uint16 purity; - } - - function getCard(uint id) public view returns (uint16 proto, uint16 purity) { - Card memory card = cards[id]; - return (card.proto, card.purity); - } - - function getShine(uint16 purity) public pure returns (uint8) { - return uint8(purity / 1000); - } - - Card[] public cards; - -} - -contract CardProto is CardBase { - - event NewProtoCard( - uint16 id, uint8 season, uint8 god, - Rarity rarity, uint8 mana, uint8 attack, - uint8 health, uint8 cardType, uint8 tribe, bool packable - ); - - struct Limit { - uint64 limit; - bool exists; - } - - // limits for mythic cards - mapping(uint16 => Limit) public limits; - - // can only set limits once - function setLimit(uint16 id, uint64 limit) public onlyGovernor { - Limit memory l = limits[id]; - require(!l.exists); - limits[id] = Limit({ - limit: limit, - exists: true - }); - } - - function getLimit(uint16 id) public view returns (uint64 limit, bool set) { - Limit memory l = limits[id]; - return (l.limit, l.exists); - } - - // could make these arrays to save gas - // not really necessary - will be update a very limited no of times - mapping(uint8 => bool) public seasonTradable; - mapping(uint8 => bool) public seasonTradabilityLocked; - uint8 public currentSeason; - - function makeTradable(uint8 season) public onlyGovernor { - seasonTradable[season] = true; - } - - function makeUntradable(uint8 season) public onlyGovernor { - require(!seasonTradabilityLocked[season]); - seasonTradable[season] = false; - } - - function makePermanantlyTradable(uint8 season) public onlyGovernor { - require(seasonTradable[season]); - seasonTradabilityLocked[season] = true; - } - - function isTradable(uint16 proto) public view returns (bool) { - return seasonTradable[protos[proto].season]; - } - - function nextSeason() public onlyGovernor { - //Seasons shouldn't go to 0 if there is more than the uint8 should hold, the governor should know this ¯\_(ツ)_/¯ -M - require(currentSeason <= 255); - - currentSeason++; - mythic.length = 0; - legendary.length = 0; - epic.length = 0; - rare.length = 0; - common.length = 0; - } - - enum Rarity { - Common, - Rare, - Epic, - Legendary, - Mythic - } - - uint8 constant SPELL = 1; - uint8 constant MINION = 2; - uint8 constant WEAPON = 3; - uint8 constant HERO = 4; - - struct ProtoCard { - bool exists; - uint8 god; - uint8 season; - uint8 cardType; - Rarity rarity; - uint8 mana; - uint8 attack; - uint8 health; - uint8 tribe; - } - - // there is a particular design decision driving this: - // need to be able to iterate over mythics only for card generation - // don't store 5 different arrays: have to use 2 ids - // better to bear this cost (2 bytes per proto card) - // rather than 1 byte per instance - - uint16 public protoCount; - - mapping(uint16 => ProtoCard) protos; - - uint16[] public mythic; - uint16[] public legendary; - uint16[] public epic; - uint16[] public rare; - uint16[] public common; - - function addProtos( - uint16[] memory externalIDs, uint8[] memory gods, Rarity[] memory rarities, uint8[] memory manas, uint8[] memory attacks, - uint8[] memory healths, uint8[] memory cardTypes, uint8[] memory tribes, bool[] memory packable - ) public onlyGovernor returns(uint16) { - - for (uint i = 0; i < externalIDs.length; i++) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: gods[i], - season: currentSeason, - cardType: cardTypes[i], - rarity: rarities[i], - mana: manas[i], - attack: attacks[i], - health: healths[i], - tribe: tribes[i] - }); - - _addProto(externalIDs[i], card, packable[i]); - } - - } - - function addProto( - uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 cardType, uint8 tribe, bool packable - ) public onlyGovernor returns(uint16) { - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: cardType, - rarity: rarity, - mana: mana, - attack: attack, - health: health, - tribe: tribe - }); - - _addProto(externalID, card, packable); - } - - function addWeapon( - uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 durability, bool packable - ) public onlyGovernor returns(uint16) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: WEAPON, - rarity: rarity, - mana: mana, - attack: attack, - health: durability, - tribe: 0 - }); - - _addProto(externalID, card, packable); - } - - function addSpell(uint16 externalID, uint8 god, Rarity rarity, uint8 mana, bool packable) public onlyGovernor returns(uint16) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: SPELL, - rarity: rarity, - mana: mana, - attack: 0, - health: 0, - tribe: 0 - }); - - _addProto(externalID, card, packable); - } - - function addMinion( - uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 tribe, bool packable - ) public onlyGovernor returns(uint16) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: MINION, - rarity: rarity, - mana: mana, - attack: attack, - health: health, - tribe: tribe - }); - - _addProto(externalID, card, packable); - } - - function _addProto(uint16 externalID, ProtoCard memory card, bool packable) internal { - - require(!protos[externalID].exists); - - card.exists = true; - - protos[externalID] = card; - - protoCount++; - - emit NewProtoCard( - externalID, currentSeason, card.god, - card.rarity, card.mana, card.attack, - card.health, card.cardType, card.tribe, packable - ); - - if (packable) { - Rarity rarity = card.rarity; - if (rarity == Rarity.Common) { - common.push(externalID); - } else if (rarity == Rarity.Rare) { - rare.push(externalID); - } else if (rarity == Rarity.Epic) { - epic.push(externalID); - } else if (rarity == Rarity.Legendary) { - legendary.push(externalID); - } else if (rarity == Rarity.Mythic) { - mythic.push(externalID); - } else { - require(false); - } - } - } - - function getProto(uint16 id) public view returns( - bool exists, uint8 god, uint8 season, uint8 cardType, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 tribe - ) { - ProtoCard memory proto = protos[id]; - return ( - proto.exists, - proto.god, - proto.season, - proto.cardType, - proto.rarity, - proto.mana, - proto.attack, - proto.health, - proto.tribe - ); - } - - function getRandomCard(Rarity rarity, uint16 random) public view returns (uint16) { - // modulo bias is fine - creates rarity tiers etc - // will obviously revert is there are no cards of that type: this is expected - should never happen - if (rarity == Rarity.Common) { - return common[random % common.length]; - } else if (rarity == Rarity.Rare) { - return rare[random % rare.length]; - } else if (rarity == Rarity.Epic) { - return epic[random % epic.length]; - } else if (rarity == Rarity.Legendary) { - return legendary[random % legendary.length]; - } else if (rarity == Rarity.Mythic) { - // make sure a mythic is available - uint16 id; - uint64 limit; - bool set; - for (uint i = 0; i < mythic.length; i++) { - id = mythic[(random + i) % mythic.length]; - (limit, set) = getLimit(id); - if (set && limit > 0){ - return id; - } - } - // if not, they get a legendary :( - return legendary[random % legendary.length]; - } - require(false); - return 0; - } - - // can never adjust tradable cards - // each season gets a 'balancing beta' - // totally immutable: season, rarity - function replaceProto( - uint16 index, uint8 god, uint8 cardType, uint8 mana, uint8 attack, uint8 health, uint8 tribe - ) public onlyGovernor { - ProtoCard memory pc = protos[index]; - require(!seasonTradable[pc.season]); - protos[index] = ProtoCard({ - exists: true, - god: god, - season: pc.season, - cardType: cardType, - rarity: pc.rarity, - mana: mana, - attack: attack, - health: health, - tribe: tribe - }); - } - -} - -contract ERC721Receiver { - /** - * @dev Magic value to be returned upon successful reception of an NFT - * Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`, - * which can be also obtained as `ERC721Receiver(0).onERC721Received.selector` - */ - bytes4 internal constant ERC721_RECEIVED = 0x150b7a02; - - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a `safetransfer`. This function MAY throw to revert and reject the - * transfer. Return of other than the magic value MUST result in the - * transaction being reverted. - * Note: the contract address is always the message sender. - * @param _operator The address which called `safeTransferFrom` function - * @param _from The address which previously owned the token - * @param _tokenId The NFT identifier which is being transfered - * @param _data Additional data with no specified format - * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - */ - function onERC721Received( - address _operator, - address _from, - uint256 _tokenId, - bytes memory _data - ) - public - returns(bytes4); -} - -library AddressUtils { - - /** - * Returns whether the target address is a contract - * @dev This function will return false if invoked during the constructor of a contract, - * as the code is not actually created until after the constructor finishes. - * @param addr address to check - * @return whether the target address is a contract - */ - function isContract1(address addr) internal view returns (bool) { - uint256 size; - // XXX Currently there is no better way to check if there is a contract in an address - // than to check the size of the code at that address. - // See https://ethereum.stackexchange.com/a/14016/36603 - // for more details about how this works. - // TODO Check this again before the Serenity release, because all addresses will be - // contracts then. - // solium-disable-next-line security/no-inline-assembly - assembly { size := extcodesize(addr) } - return size > 0; - } - -} - -library SafeMath { - - /** - * @dev Multiplies two numbers, throws on overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { - // Gas optimization: this is cheaper than asserting 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - c = a * b; - assert(c / a == b); - return c; - } - - /** - * @dev Integer division of two numbers, truncating the quotient. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // assert(b > 0); // Solidity automatically throws when dividing by 0 - // uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - return a / b; - } - - /** - * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - assert(b <= a); - return a - b; - } - - /** - * @dev Adds two numbers, throws on overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256 c) { - c = a + b; - assert(c >= a); - return c; - } -} - -contract ERC721BasicToken is CardProto, SupportsInterfaceWithLookup, ERC721Basic { - - bytes4 private constant InterfaceId_ERC721 = 0x80ac58cd; - /* - * 0x80ac58cd === - * bytes4(keccak256('balanceOf(address)')) ^ - * bytes4(keccak256('ownerOf(uint256)')) ^ - * bytes4(keccak256('approve(address,uint256)')) ^ - * bytes4(keccak256('getApproved(uint256)')) ^ - * bytes4(keccak256('setApprovalForAll(address,bool)')) ^ - * bytes4(keccak256('isApprovedForAll(address,address)')) ^ - * bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^ - * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) - */ - - bytes4 private constant InterfaceId_ERC721Exists = 0x4f558e79; - /* - * 0x4f558e79 === - * bytes4(keccak256('exists(uint256)')) - */ - - using SafeMath for uint256; - using AddressUtils for address; - - // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - // which can be also obtained as `ERC721Receiver(0).onERC721Received.selector` - bytes4 private constant ERC721_RECEIVED = 0x150b7a02; - - // Mapping from token ID to owner - mapping (uint256 => address) internal tokenOwner; - - // Mapping from token ID to approved address - mapping (uint256 => address) internal tokenApprovals; - - // Mapping from owner to number of owned token - // mapping (address => uint256) internal ownedTokensCount; - - // Mapping from owner to operator approvals - mapping (address => mapping (address => bool)) internal operatorApprovals; - - /** - * @dev Guarantees msg.sender is owner of the given token - * @param _tokenId uint256 ID of the token to validate its ownership belongs to msg.sender - */ - modifier onlyOwnerOf(uint256 _tokenId) { - require(ownerOf(_tokenId) == msg.sender); - _; - } - - /** - * @dev Checks msg.sender can transfer a token, by being owner, approved, or operator - * @param _tokenId uint256 ID of the token to validate - */ - modifier canTransfer(uint256 _tokenId) { - require(isApprovedOrOwner(msg.sender, _tokenId)); - _; - } - - constructor() - public - { - // register the supported interfaces to conform to ERC721 via ERC165 - _registerInterface(InterfaceId_ERC721); - _registerInterface(InterfaceId_ERC721Exists); - } - - /** - * @dev Gets the balance of the specified address - * @param _owner address to query the balance of - * @return uint256 representing the amount owned by the passed address - */ - function balanceOf(address _owner) public view returns (uint256); - - /** - * @dev Gets the owner of the specified token ID - * @param _tokenId uint256 ID of the token to query the owner of - * @return owner address currently marked as the owner of the given token ID - */ - function ownerOf(uint256 _tokenId) public view returns (address) { - address owner = tokenOwner[_tokenId]; - require(owner != address(0)); - return owner; - } - - /** - * @dev Returns whether the specified token exists - * @param _tokenId uint256 ID of the token to query the existence of - * @return whether the token exists - */ - function exists(uint256 _tokenId) public view returns (bool) { - address owner = tokenOwner[_tokenId]; - return owner != address(0); - } - - /** - * @dev Approves another address to transfer the given token ID - * The zero address indicates there is no approved address. - * There can only be one approved address per token at a given time. - * Can only be called by the token owner or an approved operator. - * @param _to address to be approved for the given token ID - * @param _tokenId uint256 ID of the token to be approved - */ - function approve(address _to, uint256 _tokenId) public { - address owner = ownerOf(_tokenId); - require(_to != owner); - require(msg.sender == owner || isApprovedForAll(owner, msg.sender)); - - tokenApprovals[_tokenId] = _to; - emit Approval(owner, _to, _tokenId); - } - - /** - * @dev Gets the approved address for a token ID, or zero if no address set - * @param _tokenId uint256 ID of the token to query the approval of - * @return address currently approved for the given token ID - */ - function getApproved(uint256 _tokenId) public view returns (address) { - return tokenApprovals[_tokenId]; - } - - /** - * @dev Sets or unsets the approval of a given operator - * An operator is allowed to transfer all tokens of the sender on their behalf - * @param _to operator address to set the approval - * @param _approved representing the status of the approval to be set - */ - function setApprovalForAll(address _to, bool _approved) public { - require(_to != msg.sender); - operatorApprovals[msg.sender][_to] = _approved; - emit ApprovalForAll(msg.sender, _to, _approved); - } - - /** - * @dev Tells whether an operator is approved by a given owner - * @param _owner owner address which you want to query the approval of - * @param _operator operator address which you want to query the approval of - * @return bool whether the given operator is approved by the given owner - */ - function isApprovedForAll( - address _owner, - address _operator - ) - public - view - returns (bool) - { - return operatorApprovals[_owner][_operator]; - } - - /** - * @dev Transfers the ownership of a given token ID to another address - * Usage of this method is discouraged, use `safeTransferFrom` whenever possible - * Requires the msg sender to be the owner, approved, or operator - * @param _from current owner of the token - * @param _to address to receive the ownership of the given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - public - canTransfer(_tokenId) - { - require(_from != address(0)); - require(_to != address(0)); - - clearApproval(_from, _tokenId); - removeTokenFrom(_from, _tokenId); - addTokenTo(_to, _tokenId); - - emit Transfer(_from, _to, _tokenId); - } - - /** - * @dev Safely transfers the ownership of a given token ID to another address - * If the target address is a contract, it must implement `onERC721Received`, - * which is called upon a safe transfer, and return the magic value - * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, - * the transfer is reverted. - * - * Requires the msg sender to be the owner, approved, or operator - * @param _from current owner of the token - * @param _to address to receive the ownership of the given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function safeTransferFrom( - address _from, - address _to, - uint256 _tokenId - ) - public - canTransfer(_tokenId) - { - // solium-disable-next-line arg-overflow - safeTransferFrom(_from, _to, _tokenId, ""); - } - - /** - * @dev Safely transfers the ownership of a given token ID to another address - * If the target address is a contract, it must implement `onERC721Received`, - * which is called upon a safe transfer, and return the magic value - * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, - * the transfer is reverted. - * Requires the msg sender to be the owner, approved, or operator - * @param _from current owner of the token - * @param _to address to receive the ownership of the given token ID - * @param _tokenId uint256 ID of the token to be transferred - * @param _data bytes data to send along with a safe transfer check - */ - function safeTransferFrom( - address _from, - address _to, - uint256 _tokenId, - bytes memory _data - ) - public - canTransfer(_tokenId) - { - transferFrom(_from, _to, _tokenId); - // solium-disable-next-line arg-overflow - require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data)); - } - - /** - * @dev Returns whether the given spender can transfer a given token ID - * @param _spender address of the spender to query - * @param _tokenId uint256 ID of the token to be transferred - * @return bool whether the msg.sender is approved for the given token ID, - * is an operator of the owner, or is the owner of the token - */ - function isApprovedOrOwner( - address _spender, - uint256 _tokenId - ) - internal - view - returns (bool) - { - address owner = ownerOf(_tokenId); - // Disable solium check because of - // https://github.com/duaraghav8/Solium/issues/175 - // solium-disable-next-line operator-whitespace - return ( - _spender == owner || - getApproved(_tokenId) == _spender || - isApprovedForAll(owner, _spender) - ); - } - - /** - * @dev Internal function to clear current approval of a given token ID - * Reverts if the given address is not indeed the owner of the token - * @param _owner owner of the token - * @param _tokenId uint256 ID of the token to be transferred - */ - function clearApproval(address _owner, uint256 _tokenId) internal { - require(ownerOf(_tokenId) == _owner); - if (tokenApprovals[_tokenId] != address(0)) { - tokenApprovals[_tokenId] = address(0); - } - } - - /** - * @dev Internal function to mint a new token - * Reverts if the given token ID already exists - * @param _to The address that will own the minted token - * @param _tokenId uint256 ID of the token to be minted by the msg.sender - */ - function _mint(address _to, uint256 _tokenId) internal { - require(_to != address(0)); - addNewTokenTo(_to, _tokenId); - emit Transfer(address(0), _to, _tokenId); - } - - - /** - * @dev Internal function to burn a specific token - * Reverts if the token does not exist - * @param _tokenId uint256 ID of the token being burned by the msg.sender - */ - function _burn(address _owner, uint256 _tokenId) internal { - clearApproval(_owner, _tokenId); - removeTokenFrom(_owner, _tokenId); - emit Transfer(_owner, address(0), _tokenId); - } - - function addNewTokenTo(address _to, uint256 _tokenId) internal { - require(tokenOwner[_tokenId] == address(0)); - tokenOwner[_tokenId] = _to; - } - - /** - * @dev Internal function to add a token ID to the list of a given address - * @param _to address representing the new owner of the given token ID - * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address - */ - function addTokenTo(address _to, uint256 _tokenId) internal { - require(tokenOwner[_tokenId] == address(0)); - tokenOwner[_tokenId] = _to; - // ownedTokensCount[_to] = ownedTokensCount[_to].add(1); - } - - /** - * @dev Internal function to remove a token ID from the list of a given address - * @param _from address representing the previous owner of the given token ID - * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address - */ - function removeTokenFrom(address _from, uint256 _tokenId) internal { - require(ownerOf(_tokenId) == _from); - // ownedTokensCount[_from] = ownedTokensCount[_from].sub(1); - tokenOwner[_tokenId] = address(0); - } - - /** - * @dev Internal function to invoke `onERC721Received` on a target address - * The call is not executed if the target address is not a contract - * @param _from address representing the previous owner of the given token ID - * @param _to target address that will receive the tokens - * @param _tokenId uint256 ID of the token to be transferred - * @param _data bytes optional data to send along with the call - * @return whether the call correctly returned the expected magic value - */ - function checkAndCallSafeTransfer( - address _from, - address _to, - uint256 _tokenId, - bytes memory _data - ) - internal - returns (bool) - { - if (!_to.isContract1()) { - return true; - } - bytes4 retval = ERC721Receiver(_to).onERC721Received( - msg.sender, _from, _tokenId, _data); - return (retval == ERC721_RECEIVED); - } - -} - - - -contract ERC721Enumerable is ERC721Basic { - function totalSupply() public view returns (uint256); - function tokenOfOwnerByIndex( - address _owner, - uint256 _index - ) - public - view - returns (uint256 _tokenId); - - function tokenByIndex(uint256 _index) public view returns (uint256); -} - -contract ERC721Metadata is ERC721Basic { - function name() external view returns (string memory _name); - function symbol() external view returns (string memory _symbol); - function tokenURI(uint256 _tokenId) public view returns (string memory); -} - -contract ERC721 is ERC721Basic, ERC721Enumerable, ERC721Metadata { - -} - - - - -library Strings { - - // via https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol - function strConcat(string memory _a, string memory _b, string memory _c, string memory _d, string memory _e) internal pure returns (string memory ) { - bytes memory _ba = bytes(_a); - bytes memory _bb = bytes(_b); - bytes memory _bc = bytes(_c); - bytes memory _bd = bytes(_d); - bytes memory _be = bytes(_e); - string memory abcde = new string(_ba.length + _bb.length + _bc.length + _bd.length + _be.length); - bytes memory babcde = bytes(abcde); - uint k = 0; - for (uint i = 0; i < _ba.length; i++) babcde[k++] = _ba[i]; - for (uint i = 0; i < _bb.length; i++) babcde[k++] = _bb[i]; - for (uint i = 0; i < _bc.length; i++) babcde[k++] = _bc[i]; - for (uint i = 0; i < _bd.length; i++) babcde[k++] = _bd[i]; - for (uint i = 0; i < _be.length; i++) babcde[k++] = _be[i]; - return string(babcde); - } - - function strConcat(string memory _a, string memory _b, string memory _c, string memory _d) internal pure returns (string memory ) { - return strConcat(_a, _b, _c, _d, ""); - } - - function strConcat(string memory _a, string memory _b, string memory _c) internal pure returns (string memory ) { - return strConcat(_a, _b, _c, "", ""); - } - - function strConcat(string memory _a, string memory _b) internal pure returns (string memory ) { - return strConcat(_a, _b, "", "", ""); - } - - function uint2str(uint i) internal pure returns (string memory ) { - if (i == 0) return "0"; - uint j = i; - uint len; - while (j != 0){ - len++; - j /= 10; - } - bytes memory bstr = new bytes(len); - uint k = len - 1; - while (i != 0){ - bstr[k--] = byte(uint8(48 + i % 10)); - i /= 10; - } - return string(bstr); - } -} - -contract ERC721Token is SupportsInterfaceWithLookup, ERC721BasicToken, ERC721 { - - using Strings for string; - - bytes4 private constant InterfaceId_ERC721Enumerable = 0x780e9d63; - /** - * 0x780e9d63 === - * bytes4(keccak256('totalSupply()')) ^ - * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ - * bytes4(keccak256('tokenByIndex(uint256)')) - */ - - bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f; - /** - * 0x5b5e139f === - * bytes4(keccak256('name()')) ^ - * bytes4(keccak256('symbol()')) ^ - * bytes4(keccak256('tokenURI(uint256)')) - */ - - /*** Constants ***/ - // Configure these for your own deployment - string public constant NAME = "Gods Unchained"; - string public constant SYMBOL = "GODS"; - string public tokenMetadataBaseURI = "https://api.godsunchained.com/card/"; - - // Mapping from owner to list of owned token IDs - // EDITED: limit to 2^40 (around 1T) - mapping(address => uint40[]) internal ownedTokens; - - uint32[] ownedTokensIndex; - - /** - * @dev Constructor function - */ - constructor() public { - - // register the supported interfaces to conform to ERC721 via ERC165 - _registerInterface(InterfaceId_ERC721Enumerable); - _registerInterface(InterfaceId_ERC721Metadata); - } - - /** - * @dev Gets the token name - * @return string representing the token name - */ - function name() external view returns (string memory) { - return NAME; - } - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory) { - return SYMBOL; - } - - /** - * @dev Returns an URI for a given token ID - * Throws if the token ID does not exist. May return an empty string. - * @param _tokenId uint256 ID of the token to query - */ - function tokenURI(uint256 _tokenId) public view returns (string memory) { - return Strings.strConcat( - tokenMetadataBaseURI, - Strings.uint2str(_tokenId) - ); - } - - /** - * @dev Gets the token ID at a given index of the tokens list of the requested owner - * @param _owner address owning the tokens list to be accessed - * @param _index uint256 representing the index to be accessed of the requested tokens list - * @return uint256 token ID at the given index of the tokens list owned by the requested address - */ - function tokenOfOwnerByIndex( - address _owner, - uint256 _index - ) - public - view - returns (uint256) - { - require(_index < balanceOf(_owner)); - return ownedTokens[_owner][_index]; - } - - /** - * @dev Gets the total amount of tokens stored by the contract - * @return uint256 representing the total amount of tokens - */ - function totalSupply() public view returns (uint256) { - return cards.length; - } - - /** - * @dev Gets the token ID at a given index of all the tokens in this contract - * Reverts if the index is greater or equal to the total number of tokens - * @param _index uint256 representing the index to be accessed of the tokens list - * @return uint256 token ID at the given index of the tokens list - */ - function tokenByIndex(uint256 _index) public view returns (uint256) { - require(_index < totalSupply()); - return _index; - } - - /** - * @dev Internal function to add a token ID to the list of a given address - * @param _to address representing the new owner of the given token ID - * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address - */ - function addTokenTo(address _to, uint256 _tokenId) internal { - super.addTokenTo(_to, _tokenId); - uint256 length = ownedTokens[_to].length; - // EDITED: prevent overflow - require(length == uint32(length)); - ownedTokens[_to].push(uint40(_tokenId)); - - ownedTokensIndex[_tokenId] = uint32(length); - } - - // EDITED - // have to have in order to use array rather than mapping - function addNewTokenTo(address _to, uint256 _tokenId) internal { - super.addNewTokenTo(_to, _tokenId); - uint256 length = ownedTokens[_to].length; - // EDITED: prevent overflow - require(length == uint32(length)); - ownedTokens[_to].push(uint40(_tokenId)); - ownedTokensIndex.push(uint32(length)); - } - - /** - * @dev Internal function to remove a token ID from the list of a given address - * @param _from address representing the previous owner of the given token ID - * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address - */ - function removeTokenFrom(address _from, uint256 _tokenId) internal { - super.removeTokenFrom(_from, _tokenId); - - uint32 tokenIndex = ownedTokensIndex[_tokenId]; - uint256 lastTokenIndex = ownedTokens[_from].length.sub(1); - uint40 lastToken = ownedTokens[_from][lastTokenIndex]; - - ownedTokens[_from][tokenIndex] = lastToken; - ownedTokens[_from][lastTokenIndex] = 0; - // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to - // be zero. Then we can make sure that we will remove _tokenId from the ownedTokens list since we are first swapping - // the lastToken to the first position, and then dropping the element placed in the last position of the list - - ownedTokens[_from].length--; - ownedTokensIndex[_tokenId] = 0; - ownedTokensIndex[lastToken] = tokenIndex; - } - - /** - * @dev Gets the balance of the specified address - overrriden from previous to save gas - * @param _owner address to query the balance of - * @return uint256 representing the amount owned by the passed address - */ - function balanceOf(address _owner) public view returns (uint256) { - return ownedTokens[_owner].length; - } - -} - -contract CardOwnershipTwo is ERC721Token { - - uint public burnCount; - - function getActiveCards() public view returns (uint) { - return totalSupply() - burnCount; - } - - /** - * @param to : the address to which the card will be transferred - * @param id : the id of the card to be transferred - */ - function transfer(address to, uint id) public payable onlyOwnerOf(id) { - require(isTradable(cards[id].proto)); - require(to != address(0)); - - _transfer(msg.sender, to, id); - } - - function _transfer(address from, address to, uint id) internal { - - clearApproval(from, id); - - removeTokenFrom(from, id); - - addTokenTo(to, id); - - emit Transfer(from, to, id); - } - - /** - * @param to : the address to which the cards will be transferred - * @param ids : the ids of the cards to be transferred - */ - function transferAll(address to, uint[] memory ids) public payable { - for (uint i = 0; i < ids.length; i++) { - transfer(to, ids[i]); - } - } - - /** - * @param proposed : the claimed owner of the cards - * @param ids : the ids of the cards to check - * @return whether proposed owns all of the cards - */ - function ownsAll(address proposed, uint[] memory ids) public view returns (bool) { - require(ids.length > 0); - for (uint i = 0; i < ids.length; i++) { - if (!owns(proposed, ids[i])) { - return false; - } - } - return true; - } - - /** - * @param proposed : the claimed owner of the card - * @param id : the id of the card to check - * @return whether proposed owns the card - */ - function owns(address proposed, uint id) public view returns (bool) { - return ownerOf(id) == proposed; - } - - function burn(uint id) public onlyOwnerOf(id) { - burnCount++; - _burn(msg.sender, id); - } - - /** - * @param ids : the indices of the tokens to burn - */ - function burnAll(uint[] memory ids) public { - for (uint i = 0; i < ids.length; i++){ - burn(ids[i]); - } - } - - /** - * @param to : the address to approve for transfer - * @param id : the index of the card to be approved - */ - function approve(address to, uint id) public { - require(isTradable(cards[id].proto)); - super.approve(to, id); - } - - /** - * @param to : the address to approve for transfer - * @param ids : the indices of the cards to be approved - */ - function approveAll(address to, uint[] memory ids) public { - for (uint i = 0; i < ids.length; i++) { - approve(to, ids[i]); - } - } - - /** - * @param to : the address to which the token should be transferred - * @param id : the index of the token to transfer - */ - function transferFrom(address from, address to, uint id) public { - require(isTradable(cards[id].proto)); - super.transferFrom(from, to, id); - } - - /** - * @param to : the address to which the tokens should be transferred - * @param ids : the indices of the tokens to transfer - */ - function transferAllFrom(address from, address to, uint[] memory ids) public { - for (uint i = 0; i < ids.length; i++) { - transferFrom(from, to, ids[i]); - } - } - - /** - * @return the number of cards which have been burned - */ - function getBurnCount() public view returns (uint) { - return burnCount; - } - -} - -contract CardIntegrationTwo is CardOwnershipTwo { - - address[] public packs; - - event CardCreated(uint indexed id, uint16 proto, uint16 purity, address owner); - - function addPack(address approved) public onlyGovernor { - packs.push(approved); - } - - modifier onlyApprovedPacks { - require(_isApprovedPack()); - _; - } - - function _isApprovedPack() private view returns (bool) { - for (uint i = 0; i < packs.length; i++) { - if (msg.sender == address(packs[i])) { - return true; - } - } - return false; - } - - function createCard(address owner, uint16 proto, uint16 purity) public whenNotPaused onlyApprovedPacks returns (uint) { - ProtoCard memory card = protos[proto]; - require(card.season == currentSeason); - if (card.rarity == Rarity.Mythic) { - uint64 limit; - bool exists; - (limit, exists) = getLimit(proto); - require(!exists || limit > 0); - limits[proto].limit--; - } - return _createCard(owner, proto, purity); - } - - function _createCard(address owner, uint16 proto, uint16 purity) internal returns (uint) { - Card memory card = Card({ - proto: proto, - purity: purity - }); - - uint id = cards.push(card) - 1; - - _mint(owner, id); - - emit CardCreated(id, proto, purity, owner); - - return id; - } - - /*function combineCards(uint[] ids) public whenNotPaused { - require(ids.length == 5); - require(ownsAll(msg.sender, ids)); - Card memory first = cards[ids[0]]; - uint16 proto = first.proto; - uint8 shine = _getShine(first.purity); - require(shine < shineLimit); - uint16 puritySum = first.purity - (shine * 1000); - burn(ids[0]); - for (uint i = 1; i < ids.length; i++) { - Card memory next = cards[ids[i]]; - require(next.proto == proto); - require(_getShine(next.purity) == shine); - puritySum += (next.purity - (shine * 1000)); - burn(ids[i]); - } - uint16 newPurity = uint16(((shine + 1) * 1000) + (puritySum / ids.length)); - _createCard(msg.sender, proto, newPurity); - }*/ - - - // PURITY NOTES - // currently, we only - // however, to protect rarity, you'll never be abl - // this is enforced by the restriction in the create-card function - // no cards above this point can be found in packs - - - -} - -contract PreviousInterface { - - function ownerOf(uint id) public view returns (address); - - function getCard(uint id) public view returns (uint16, uint16); - - function totalSupply() public view returns (uint); - - function burnCount() public view returns (uint); - -} - -contract CardMigration is CardIntegrationTwo { - - constructor(PreviousInterface previous) public { - old = previous; - } - - // use interface to lower deployment cost - PreviousInterface old; - - mapping(uint => bool) public migrated; - - function migrate(uint id) public { - - require(!migrated[id]); - - migrated[id] = true; - - address owner = old.ownerOf(id); - - uint16 proto; - uint16 purity; - - (proto, purity) = old.getCard(id); - - _createCard(owner, proto, purity); - } - - function migrateAll(uint[] memory ids) public { - - for (uint i = 0; i < ids.length; i++){ - migrate(ids[i]); - } - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractScenario008.sol b/framework/src/test/resources/soliditycode/contractScenario008.sol deleted file mode 100644 index 0dbed350e4c..00000000000 --- a/framework/src/test/resources/soliditycode/contractScenario008.sol +++ /dev/null @@ -1,2061 +0,0 @@ - - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() public { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address payable public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address payable _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() virtual public onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer1(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - emit Transfer1(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(block.timestamp), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - kitties.push(_kitty); - uint256 newKittenId = kitties.length - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - emit Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(address(0), _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -abstract contract ERC721 { - // Required methods - function totalSupply() virtual public view returns (uint256 total); - function balanceOf(address _owner) virtual public view returns (uint256 balance); - function ownerOf(uint256 _tokenId) virtual external view returns (address owner); - function approve(address _to, uint256 _tokenId) virtual external; - function transfer(address _to, uint256 _tokenId) virtual external; - function transferFrom(address _from, address _to, uint256 _tokenId) virtual external; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) virtual external view returns (bool); -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is ERC721, KittyBase { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external override view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public override view returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - override - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - override - external - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - emit Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - override - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() override public view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - override - external - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { - string memory outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { - require( address(erc721Metadata) != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - payable(msg.sender).transfer(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, address(saleAuction)); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - payable(msg.sender) - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, address(siringAuction)); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - payable(msg.sender) - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid{value:(msg.value - autoBirthFee)}(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, address(saleAuction)); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - payable(address(uint160(address(this)))) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - constructor() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(int256(-1)), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - emit ContractUpgrade(_v2Address); - } - -/// @notice No tipping! -/// @dev Reject all Ether from being sent here, unless it's from one of the -/// two auction contracts. (Hopefully, we can prevent user accidents.) -fallback() external payable { -require( -msg.sender == address(saleAuction) || -msg.sender == address(siringAuction) -); -} - -/// @notice Returns all the relevant information about a specific kitty. -/// @param _id The ID of the kitty of interest. -function getKitty(uint256 _id) -external -view -returns ( -bool isGestating, -bool isReady, -uint256 cooldownIndex, -uint256 nextActionAt, -uint256 siringWithId, -uint256 birthTime, -uint256 matronId, -uint256 sireId, -uint256 generation, -uint256 genes -) { -Kitty storage kit = kitties[_id]; - -// if this variable is 0 then it's not gestating -isGestating = (kit.siringWithId != 0); -isReady = (kit.cooldownEndBlock <= block.number); -cooldownIndex = uint256(kit.cooldownIndex); -nextActionAt = uint256(kit.cooldownEndBlock); -siringWithId = uint256(kit.siringWithId); -birthTime = uint256(kit.birthTime); -matronId = uint256(kit.matronId); -sireId = uint256(kit.sireId); -generation = uint256(kit.generation); -genes = kit.genes; -} - -/// @dev Override unpause so it requires all external contract addresses -/// to be set before contract can be unpaused. Also, we can't have -/// newContractAddress set either, because then the contract was upgraded. -/// @notice This is public rather than external so we can call super.unpause -/// without using an expensive CALL. - -function unpause() override public onlyCEO whenPaused { -require(address(saleAuction) != address(0)); -require(address(siringAuction) != address(0)); -require(address(geneScience) != address(0)); -require(newContractAddress == address(0)); - -// Actually unpause the contract. -super.unpause(); -} - -// @dev Allows the CFO to capture the balance available to the contract. -function withdrawBalance() external onlyCFO { -uint256 balance = address(this).balance; -// Subtract all the currently pregnant kittens we have, plus 1 of margin. -uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - -if (balance > subtractFees) { -cfoAddress.transfer(balance - subtractFees); -} -} -} - - - - - - - - - - - - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - -function isGeneScience() public pure returns (bool){ -return true; -} - -/// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor -/// @param genes1 genes of mom -/// @param genes2 genes of sire -/// @return the genes that are supposed to be passed down the child -function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - -return (genes1+genes2+targetBlock)/2; - - -} -} - - - - - - - - - - - - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { -/// @dev Given a token Id, returns a byte array that is supposed to be converted into string. -function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { -if (_tokenId == 1) { -buffer[0] = "Hello World! :D"; -count = 15; -} else if (_tokenId == 2) { -buffer[0] = "I would definitely choose a medi"; -buffer[1] = "um length string."; -count = 49; -} else if (_tokenId == 3) { -buffer[0] = "Lorem ipsum dolor sit amet, mi e"; -buffer[1] = "st accumsan dapibus augue lorem,"; -buffer[2] = " tristique vestibulum id, libero"; -buffer[3] = " suscipit varius sapien aliquam."; -count = 128; -} -} -} - - - - - - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - -// Represents an auction on an NFT -struct Auction { -// Current owner of NFT -address payable seller; -// Price (in wei) at beginning of auction -uint128 startingPrice; -// Price (in wei) at end of auction -uint128 endingPrice; -// Duration (in seconds) of auction -uint64 duration; -// Time when auction started -// NOTE: 0 if this auction has been concluded -uint64 startedAt; -} - -// Reference to contract tracking NFT ownership -ERC721 public nonFungibleContract; - -// Cut owner takes on each auction, measured in basis points (1/100 of a percent). -// Values 0-10,000 map to 0%-100% -uint256 public ownerCut; - -// Map from token ID to their corresponding auction. -mapping (uint256 => Auction) tokenIdToAuction; - -event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); -event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); -event AuctionCancelled(uint256 tokenId); - -/// @dev Returns true if the claimant owns the token. -/// @param _claimant - Address claiming to own the token. -/// @param _tokenId - ID of token whose ownership to verify. -function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { -return (nonFungibleContract.ownerOf(_tokenId) == _claimant); -} - -/// @dev Escrows the NFT, assigning ownership to this contract. -/// Throws if the escrow fails. -/// @param _owner - Current owner address of token to escrow. -/// @param _tokenId - ID of token whose approval to verify. -function _escrow(address _owner, uint256 _tokenId) internal { -// it will throw if transfer fails -nonFungibleContract.transferFrom(_owner, address(this), _tokenId); -} - -/// @dev Transfers an NFT owned by this contract to another address. -/// Returns true if the transfer succeeds. -/// @param _receiver - Address to transfer NFT to. -/// @param _tokenId - ID of token to transfer. -function _transfer(address _receiver, uint256 _tokenId) internal { -// it will throw if transfer fails -nonFungibleContract.transfer(_receiver, _tokenId); -} - -/// @dev Adds an auction to the list of open auctions. Also fires the -/// AuctionCreated event. -/// @param _tokenId The ID of the token to be put on auction. -/// @param _auction Auction to add. -function _addAuction(uint256 _tokenId, Auction memory _auction) internal { -// Require that all auctions have a duration of -// at least one minute. (Keeps our math from getting hairy!) -require(_auction.duration >= 1 minutes); - -tokenIdToAuction[_tokenId] = _auction; - -emit AuctionCreated( -uint256(_tokenId), -uint256(_auction.startingPrice), -uint256(_auction.endingPrice), -uint256(_auction.duration) -); -} - -/// @dev Cancels an auction unconditionally. -function _cancelAuction(uint256 _tokenId, address _seller) internal { -_removeAuction(_tokenId); -_transfer(_seller, _tokenId); -emit AuctionCancelled(_tokenId); -} - -/// @dev Computes the price and transfers winnings. -/// Does NOT transfer ownership of token. -function _bid(uint256 _tokenId, uint256 _bidAmount) -internal -returns (uint256) -{ -// Get a reference to the auction struct -Auction storage auction = tokenIdToAuction[_tokenId]; - -// Explicitly check that this auction is currently live. -// (Because of how Ethereum mappings work, we can't just count -// on the lookup above failing. An invalid _tokenId will just -// return an auction object that is all zeros.) -require(_isOnAuction(auction)); - -// Check that the bid is greater than or equal to the current price -uint256 price = _currentPrice(auction); -require(_bidAmount >= price); - -// Grab a reference to the seller before the auction struct -// gets deleted. -address payable seller = auction.seller; - -// The bid is good! Remove the auction before sending the fees -// to the sender so we can't have a reentrancy attack. -_removeAuction(_tokenId); - -// Transfer proceeds to seller (if there are any!) -if (price > 0) { -// Calculate the auctioneer's cut. -// (NOTE: _computeCut() is guaranteed to return a -// value <= price, so this subtraction can't go negative.) -uint256 auctioneerCut = _computeCut(price); -uint256 sellerProceeds = price - auctioneerCut; - -// NOTE: Doing a transfer() in the middle of a complex -// method like this is generally discouraged because of -// reentrancy attacks and DoS attacks if the seller is -// a contract with an invalid fallback function. We explicitly -// guard against reentrancy attacks by removing the auction -// before calling transfer(), and the only thing the seller -// can DoS is the sale of their own asset! (And if it's an -// accident, they can call cancelAuction(). ) -seller.transfer(sellerProceeds); -} - -// Calculate any excess funds included with the bid. If the excess -// is anything worth worrying about, transfer it back to bidder. -// NOTE: We checked above that the bid amount is greater than or -// equal to the price so this cannot underflow. -uint256 bidExcess = _bidAmount - price; - -// Return the funds. Similar to the previous transfer, this is -// not susceptible to a re-entry attack because the auction is -// removed before any transfers occur. - payable(msg.sender).transfer(bidExcess); - -// Tell the world! -emit AuctionSuccessful(_tokenId, price, msg.sender); - -return price; -} - -/// @dev Removes an auction from the list of open auctions. -/// @param _tokenId - ID of NFT on auction. -function _removeAuction(uint256 _tokenId) internal { -delete tokenIdToAuction[_tokenId]; -} - -/// @dev Returns true if the NFT is on auction. -/// @param _auction - Auction to check. -function _isOnAuction(Auction storage _auction) internal view returns (bool) { -return (_auction.startedAt > 0); -} - -/// @dev Returns current price of an NFT on auction. Broken into two -/// functions (this one, that computes the duration from the auction -/// structure, and the other that does the price computation) so we -/// can easily test that the price computation works correctly. -function _currentPrice(Auction storage _auction) -internal -view -returns (uint256) -{ -uint256 secondsPassed = 0; - -// A bit of insurance against negative values (or wraparound). -// Probably not necessary (since Ethereum guarnatees that the -// now variable doesn't ever go backwards). -if (block.timestamp > _auction.startedAt) { -secondsPassed = block.timestamp - _auction.startedAt; -} - -return _computeCurrentPrice( -_auction.startingPrice, -_auction.endingPrice, -_auction.duration, -secondsPassed -); -} - -/// @dev Computes the current price of an auction. Factored out -/// from _currentPrice so we can run extensive unit tests. -/// When testing, make this function public and turn on -/// `Current price computation` test suite. -function _computeCurrentPrice( -uint256 _startingPrice, -uint256 _endingPrice, -uint256 _duration, -uint256 _secondsPassed -) -internal -pure -returns (uint256) -{ -// NOTE: We don't use SafeMath (or similar) in this function because -// all of our public functions carefully cap the maximum values for -// time (at 64-bits) and currency (at 128-bits). _duration is -// also known to be non-zero (see the require() statement in -// _addAuction()) -if (_secondsPassed >= _duration) { -// We've reached the end of the dynamic pricing portion -// of the auction, just return the end price. -return _endingPrice; -} else { -// Starting price can be higher than ending price (and often is!), so -// this delta can be negative. -int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - -// This multiplication can't overflow, _secondsPassed will easily fit within -// 64-bits, and totalPriceChange will easily fit within 128-bits, their product -// will always fit within 256-bits. -int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - -// currentPriceChange can be negative, but if so, will have a magnitude -// less that _startingPrice. Thus, this result will always end up positive. -int256 currentPrice = int256(_startingPrice) + currentPriceChange; - -return uint256(currentPrice); -} -} - -/// @dev Computes owner's cut of a sale. -/// @param _price - Sale price of NFT. -function _computeCut(uint256 _price) internal view returns (uint256) { -// NOTE: We don't use SafeMath (or similar) in this function because -// all of our entry functions carefully cap the maximum values for -// currency (at 128-bits), and ownerCut <= 10000 (see the require() -// statement in the ClockAuction constructor). The result of this -// function is always guaranteed to be <= _price. -return _price * ownerCut / 10000; -} - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { -event Pause(); -event Unpause(); - -bool public paused = false; - - -/** - * @dev modifier to allow actions only when the contract IS paused - */ -modifier whenNotPaused() { -require(!paused); -_; -} - -/** - * @dev modifier to allow actions only when the contract IS NOT paused - */ -modifier whenPaused { -require(paused); -_; -} - -/** - * @dev called by the owner to pause, triggers stopped state - */ -function pause() onlyOwner whenNotPaused public returns (bool) { -paused = true; -emit Pause(); -return true; -} - -/** - * @dev called by the owner to unpause, returns to normal state - */ -function unpause() onlyOwner whenPaused public returns (bool) { -paused = false; -emit Unpause(); -return true; -} -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - -/// @dev The ERC-165 interface signature for ERC-721. -/// Ref: https://github.com/ethereum/EIPs/issues/165 -/// Ref: https://github.com/ethereum/EIPs/issues/721 -bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - -/// @dev Constructor creates a reference to the NFT ownership contract -/// and verifies the owner cut is in the valid range. -/// @param _nftAddress - address of a deployed contract implementing -/// the Nonfungible Interface. -/// @param _cut - percent cut the owner takes on each auction, must be -/// between 0-10,000. -constructor(address _nftAddress, uint256 _cut) public { -require(_cut <= 10000); -ownerCut = _cut; - -ERC721 candidateContract = ERC721(_nftAddress); -require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); -nonFungibleContract = candidateContract; -} - -/// @dev Remove all Ether from the contract, which is the owner's cuts -/// as well as any Ether sent directly to the contract address. -/// Always transfers to the NFT contract, but can be called either by -/// the owner or the NFT contract. -function withdrawBalance() external { -address payable nftAddress = payable(address(uint160(address(nonFungibleContract)))); - -require( -msg.sender == owner || -msg.sender == nftAddress -); -// We are using this boolean method to make sure that even if one fails it will still work -bool res = nftAddress.send(address(this).balance); -} - -/// @dev Creates and begins a new auction. -/// @param _tokenId - ID of token to auction, sender must be owner. -/// @param _startingPrice - Price of item (in wei) at beginning of auction. -/// @param _endingPrice - Price of item (in wei) at end of auction. -/// @param _duration - Length of time to move between starting -/// price and ending price (in seconds). -/// @param _seller - Seller, if not the message sender -function createAuction( -uint256 _tokenId, -uint256 _startingPrice, -uint256 _endingPrice, -uint256 _duration, -address payable _seller -) -virtual -external -whenNotPaused -{ -// Sanity check that no inputs overflow how many bits we've allocated -// to store them in the auction struct. -require(_startingPrice == uint256(uint128(_startingPrice))); -require(_endingPrice == uint256(uint128(_endingPrice))); -require(_duration == uint256(uint64(_duration))); - -require(_owns(msg.sender, _tokenId)); -_escrow(msg.sender, _tokenId); -Auction memory auction = Auction( -_seller, -uint128(_startingPrice), -uint128(_endingPrice), -uint64(_duration), -uint64(block.timestamp) -); -_addAuction(_tokenId, auction); -} - -/// @dev Bids on an open auction, completing the auction and transferring -/// ownership of the NFT if enough Ether is supplied. -/// @param _tokenId - ID of token to bid on. -function bid(uint256 _tokenId) -external -payable -whenNotPaused -virtual -{ -// _bid will throw if the bid or funds transfer fails -_bid(_tokenId, msg.value); -_transfer(msg.sender, _tokenId); -} - -/// @dev Cancels an auction that hasn't been won yet. -/// Returns the NFT to original owner. -/// @notice This is a state-modifying function that can -/// be called while the contract is paused. -/// @param _tokenId - ID of token on auction -function cancelAuction(uint256 _tokenId) -external -{ -Auction storage auction = tokenIdToAuction[_tokenId]; -require(_isOnAuction(auction)); -address seller = auction.seller; -require(msg.sender == seller); -_cancelAuction(_tokenId, seller); -} - -/// @dev Cancels an auction when the contract is paused. -/// Only the owner may do this, and NFTs are returned to -/// the seller. This should only be used in emergencies. -/// @param _tokenId - ID of the NFT on auction to cancel. -function cancelAuctionWhenPaused(uint256 _tokenId) -whenPaused -onlyOwner -external -{ -Auction storage auction = tokenIdToAuction[_tokenId]; -require(_isOnAuction(auction)); -_cancelAuction(_tokenId, auction.seller); -} - -/// @dev Returns auction info for an NFT on auction. -/// @param _tokenId - ID of NFT on auction. -function getAuction(uint256 _tokenId) -external -view -returns -( -address seller, -uint256 startingPrice, -uint256 endingPrice, -uint256 duration, -uint256 startedAt -) { -Auction storage auction = tokenIdToAuction[_tokenId]; -require(_isOnAuction(auction)); -return ( -auction.seller, -auction.startingPrice, -auction.endingPrice, -auction.duration, -auction.startedAt -); -} - -/// @dev Returns the current price of an auction. -/// @param _tokenId - ID of the token price we are checking. -function getCurrentPrice(uint256 _tokenId) -external -view -returns (uint256) -{ -Auction storage auction = tokenIdToAuction[_tokenId]; -require(_isOnAuction(auction)); -return _currentPrice(auction); -} - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - -// @dev Sanity check that allows us to ensure that we are pointing to the -// right auction in our setSiringAuctionAddress() call. -bool public isSiringClockAuction = true; - -// Delegate constructor -constructor(address _nftAddr, uint256 _cut) public -ClockAuction(_nftAddr, _cut) {} - -/// @dev Creates and begins a new auction. Since this function is wrapped, -/// require sender to be KittyCore contract. -/// @param _tokenId - ID of token to auction, sender must be owner. -/// @param _startingPrice - Price of item (in wei) at beginning of auction. -/// @param _endingPrice - Price of item (in wei) at end of auction. -/// @param _duration - Length of auction (in seconds). -/// @param _seller - Seller, if not the message sender -function createAuction( -uint256 _tokenId, -uint256 _startingPrice, -uint256 _endingPrice, -uint256 _duration, -address payable _seller -) -override -external -{ -// Sanity check that no inputs overflow how many bits we've allocated -// to store them in the auction struct. -require(_startingPrice == uint256(uint128(_startingPrice))); -require(_endingPrice == uint256(uint128(_endingPrice))); -require(_duration == uint256(uint64(_duration))); - -require(msg.sender == address(nonFungibleContract)); -_escrow(_seller, _tokenId); -Auction memory auction = Auction( -_seller, -uint128(_startingPrice), -uint128(_endingPrice), -uint64(_duration), -uint64(block.timestamp) -); -_addAuction(_tokenId, auction); -} - -/// @dev Places a bid for siring. Requires the sender -/// is the KittyCore contract because all bid methods -/// should be wrapped. Also returns the kitty to the -/// seller rather than the winner. -function bid(uint256 _tokenId) -external -payable -override -{ -require(msg.sender == address(nonFungibleContract)); -address seller = tokenIdToAuction[_tokenId].seller; -// _bid checks that token ID is valid and will throw if bid fails -_bid(_tokenId, msg.value); -// We transfer the kitty back to the seller, the winner will get -// the offspring -_transfer(seller, _tokenId); -} - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - -// @dev Sanity check that allows us to ensure that we are pointing to the -// right auction in our setSaleAuctionAddress() call. -bool public isSaleClockAuction = true; - -// Tracks last 5 sale price of gen0 kitty sales -uint256 public gen0SaleCount; -uint256[5] public lastGen0SalePrices; - -// Delegate constructor -constructor(address _nftAddr, uint256 _cut) public -ClockAuction(_nftAddr, _cut) {} - -/// @dev Creates and begins a new auction. -/// @param _tokenId - ID of token to auction, sender must be owner. -/// @param _startingPrice - Price of item (in wei) at beginning of auction. -/// @param _endingPrice - Price of item (in wei) at end of auction. -/// @param _duration - Length of auction (in seconds). -/// @param _seller - Seller, if not the message sender -function createAuction( -uint256 _tokenId, -uint256 _startingPrice, -uint256 _endingPrice, -uint256 _duration, -address payable _seller -) -override -external -{ -// Sanity check that no inputs overflow how many bits we've allocated -// to store them in the auction struct. -require(_startingPrice == uint256(uint128(_startingPrice))); -require(_endingPrice == uint256(uint128(_endingPrice))); -require(_duration == uint256(uint64(_duration))); - -require(msg.sender == address(nonFungibleContract)); -_escrow(_seller, _tokenId); -Auction memory auction = Auction( -_seller, -uint128(_startingPrice), -uint128(_endingPrice), -uint64(_duration), -uint64(block.timestamp) -); -_addAuction(_tokenId, auction); -} - -/// @dev Updates lastSalePrice if seller is the nft contract -/// Otherwise, works the same as default bid method. -function bid(uint256 _tokenId) -external -override -payable -{ -// _bid verifies token ID size -address seller = tokenIdToAuction[_tokenId].seller; -uint256 price = _bid(_tokenId, msg.value); -_transfer(msg.sender, _tokenId); - -// If not a gen0 auction, exit -if (seller == address(nonFungibleContract)) { -// Track gen0 sale prices -lastGen0SalePrices[gen0SaleCount % 5] = price; -gen0SaleCount++; -} -} - -function averageGen0SalePrice() external view returns (uint256) { -uint256 sum = 0; -for (uint256 i = 0; i < 5; i++) { -sum += lastGen0SalePrices[i]; -} -return sum / 5; -} - -} - - - - - - - diff --git a/framework/src/test/resources/soliditycode/contractScenario009.sol b/framework/src/test/resources/soliditycode/contractScenario009.sol deleted file mode 100644 index 52fa63e90ac..00000000000 --- a/framework/src/test/resources/soliditycode/contractScenario009.sol +++ /dev/null @@ -1,51 +0,0 @@ - - -library Set { - // We define a new struct datatype that will be used to - // hold its data in the calling contract. - struct Data { mapping(uint => bool) flags; } - - // Note that the first parameter is of type "storage - // reference" and thus only its storage address and not - // its contents is passed as part of the call. This is a - // special feature of library functions. It is idiomatic - // to call the first parameter 'self', if the function can - // be seen as a method of that object. - function insert (Data storage self, uint value) public - returns (bool) - { - if (self.flags[value]) - return false; // already there - self.flags[value] = true; - return true; - } - - function remove(Data storage self, uint value) public - returns (bool) - { - if (!self.flags[value]) - return false; // not there - self.flags[value] = false; - return true; - } - - function contains(Data storage self, uint value) public - returns (bool) - { - return self.flags[value]; - } -} - - -contract C { - Set.Data knownValues; - - function register(uint value) public { - // The library functions can be called without a - // specific instance of the library, since the - // "instance" will be the current contract. - if (!Set.insert(knownValues, value)) - revert(); - } - // In this contract, we can also directly access knownValues.flags, if we want. -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractScenario010.sol b/framework/src/test/resources/soliditycode/contractScenario010.sol deleted file mode 100644 index 4e299efecad..00000000000 --- a/framework/src/test/resources/soliditycode/contractScenario010.sol +++ /dev/null @@ -1,107 +0,0 @@ - - -contract TRON_ERC721 { - //name - function name() view public returns (string memory name){ - return "Tron ERC721 Token"; - } - //symbol - function symbol() view public returns (string memory symbol){ - return "T721T"; - } - - //totalSupply - - function totalSupply() view public returns (uint256 supply){ - uint256 totalSupply = 1000000000000; - return totalSupply; - } - - mapping(address => uint) private balances; - function balanceOf(address _owner) view public returns (uint balance) - { - return balances[_owner]; - } - - - mapping(uint256 => address) private tokenOwners; - mapping(uint256 => bool) private tokenExists; - function ownerOf(uint256 _tokenId) view public returns (address owner) { - require(tokenExists[_tokenId]); - return tokenOwners[_tokenId]; - } - - - mapping(address => mapping (address => uint256)) allowed; - function approve(address _to, uint256 _tokenId) public{ - require(msg.sender == ownerOf(_tokenId)); - require(msg.sender != _to); - allowed[msg.sender][_to] = _tokenId; - emit Approval(msg.sender, _to, _tokenId); - } - - - function takeOwnership(uint256 _tokenId) public { - require(tokenExists[_tokenId]); - address oldOwner = ownerOf(_tokenId); - address newOwner = msg.sender; - require(newOwner != oldOwner); - require(allowed[oldOwner][newOwner] == _tokenId); - balances[oldOwner] -= 1; - tokenOwners[_tokenId] = newOwner; - balances[newOwner] += 1; - emit Transfer(oldOwner, newOwner, _tokenId); - } - - - mapping(address => mapping(uint256 => uint256)) private ownerTokens; - function removeFromTokenList(address owner, uint256 _tokenId) private { - for(uint256 i = 0;ownerTokens[owner][i] != _tokenId;i++){ - ownerTokens[owner][i] = 0; - } - } - - function transfer(address _to, uint256 _tokenId) public{ - address currentOwner = msg.sender; - address newOwner = _to; - require(tokenExists[_tokenId]); - require(currentOwner == ownerOf(_tokenId)); - require(currentOwner != newOwner); - require(newOwner != address(0)); - address oldOwner =currentOwner; - removeFromTokenList(oldOwner,_tokenId); - balances[oldOwner] -= 1; - tokenOwners[_tokenId] = newOwner; - balances[newOwner] += 1; - emit Transfer(oldOwner, newOwner, _tokenId); - } - - function transferFrom(address _from,address _to, uint256 _tokenId) public{ - address currentOwner = _from; - address newOwner = _to; - require(tokenExists[_tokenId]); - require(currentOwner == ownerOf(_tokenId)); - require(currentOwner != newOwner); - require(newOwner != address(0)); - address oldOwner =currentOwner; - removeFromTokenList(oldOwner,_tokenId); - balances[oldOwner] -= 1; - tokenOwners[_tokenId] = newOwner; - balances[newOwner] += 1; - emit Transfer(oldOwner, newOwner, _tokenId); - } - - - function tokenOfOwnerByIndex(address _owner, uint256 _index) view public returns (uint tokenId){ - return ownerTokens[_owner][_index]; - } - - - mapping(uint256 => string) tokenLinks; - function tokenMetadata(uint256 _tokenId) view public returns (string memory infoUrl) { - return tokenLinks[_tokenId]; - } - // Events - event Transfer(address indexed _from, address indexed _to, uint256 _tokenId); - event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId); -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractScenario011.sol b/framework/src/test/resources/soliditycode/contractScenario011.sol deleted file mode 100644 index c0d30e8ebab..00000000000 --- a/framework/src/test/resources/soliditycode/contractScenario011.sol +++ /dev/null @@ -1,2060 +0,0 @@ - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() public { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address payable public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address payable _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() public virtual onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer1(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - emit Transfer1(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(block.timestamp), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - kitties.push(_kitty); - uint256 newKittenId = kitties.length - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - emit Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(address(0), _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -abstract contract ERC721 { - // Required methods - function totalSupply() public virtual view returns (uint256 total); - function balanceOf(address _owner) public virtual view returns (uint256 balance); - function ownerOf(uint256 _tokenId) external virtual view returns (address owner); - function approve(address _to, uint256 _tokenId) external virtual; - function transfer(address _to, uint256 _tokenId) external virtual; - function transferFrom(address _from, address _to, uint256 _tokenId) external virtual; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) external virtual view returns (bool); -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is ERC721, KittyBase { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external override view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public view override returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - override - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - external - override - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - emit Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - external - override - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() public override view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - external - override - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { - string memory outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { - require( address(erc721Metadata) != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2 ; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - payable(msg.sender).transfer(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, address(saleAuction)); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - payable(msg.sender) - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, address(siringAuction)); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - payable(msg.sender) - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid{value : (msg.value - autoBirthFee)}(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10 ; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, address(saleAuction)); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - payable(address(uint160(address(this)))) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - constructor() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(int256(-1)), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - emit ContractUpgrade(_v2Address); - } - - /// @notice No tipping! - /// @dev Reject all Ether from being sent here, unless it's from one of the - /// two auction contracts. (Hopefully, we can prevent user accidents.) - fallback() external payable { - require( - msg.sender == address(saleAuction) || - msg.sender == address(siringAuction) - ); - } - - /// @notice Returns all the relevant information about a specific kitty. - /// @param _id The ID of the kitty of interest. - function getKitty(uint256 _id) - external - view - returns ( - bool isGestating, - bool isReady, - uint256 cooldownIndex, - uint256 nextActionAt, - uint256 siringWithId, - uint256 birthTime, - uint256 matronId, - uint256 sireId, - uint256 generation, - uint256 genes - ) { - Kitty storage kit = kitties[_id]; - - // if this variable is 0 then it's not gestating - isGestating = (kit.siringWithId != 0); - isReady = (kit.cooldownEndBlock <= block.number); - cooldownIndex = uint256(kit.cooldownIndex); - nextActionAt = uint256(kit.cooldownEndBlock); - siringWithId = uint256(kit.siringWithId); - birthTime = uint256(kit.birthTime); - matronId = uint256(kit.matronId); - sireId = uint256(kit.sireId); - generation = uint256(kit.generation); - genes = kit.genes; - } - - /// @dev Override unpause so it requires all external contract addresses - /// to be set before contract can be unpaused. Also, we can't have - /// newContractAddress set either, because then the contract was upgraded. - /// @notice This is public rather than external so we can call super.unpause - /// without using an expensive CALL. - - function unpause() public override onlyCEO whenPaused { - require(address(saleAuction) != address(0)); - require(address(siringAuction) != address(0)); - require(address(geneScience) != address(0)); - require(newContractAddress == address(0)); - - // Actually unpause the contract. - super.unpause(); - } - - // @dev Allows the CFO to capture the balance available to the contract. - function withdrawBalance() external onlyCFO { - uint256 balance = address(this).balance; - // Subtract all the currently pregnant kittens we have, plus 1 of margin. - uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - - if (balance > subtractFees) { - cfoAddress.transfer(balance - subtractFees); - } - } -} - - - - - - - - - - - - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - - function isGeneScience() public pure returns (bool){ - return true; - } - - /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor - /// @param genes1 genes of mom - /// @param genes2 genes of sire - /// @return the genes that are supposed to be passed down the child - function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - - return (genes1+genes2+targetBlock)/2; - - - } -} - - - - - - - - - - - - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { - /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. - function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { - if (_tokenId == 1) { - buffer[0] = "Hello World! :D"; - count = 15; - } else if (_tokenId == 2) { - buffer[0] = "I would definitely choose a medi"; - buffer[1] = "um length string."; - count = 49; - } else if (_tokenId == 3) { - buffer[0] = "Lorem ipsum dolor sit amet, mi e"; - buffer[1] = "st accumsan dapibus augue lorem,"; - buffer[2] = " tristique vestibulum id, libero"; - buffer[3] = " suscipit varius sapien aliquam."; - count = 128; - } - } -} - - - - - - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - - // Represents an auction on an NFT - struct Auction { - // Current owner of NFT - address payable seller; - // Price (in wei) at beginning of auction - uint128 startingPrice; - // Price (in wei) at end of auction - uint128 endingPrice; - // Duration (in seconds) of auction - uint64 duration; - // Time when auction started - // NOTE: 0 if this auction has been concluded - uint64 startedAt; - } - - // Reference to contract tracking NFT ownership - ERC721 public nonFungibleContract; - - // Cut owner takes on each auction, measured in basis points (1/100 of a percent). - // Values 0-10,000 map to 0%-100% - uint256 public ownerCut; - - // Map from token ID to their corresponding auction. - mapping (uint256 => Auction) tokenIdToAuction; - - event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); - event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); - event AuctionCancelled(uint256 tokenId); - - /// @dev Returns true if the claimant owns the token. - /// @param _claimant - Address claiming to own the token. - /// @param _tokenId - ID of token whose ownership to verify. - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return (nonFungibleContract.ownerOf(_tokenId) == _claimant); - } - - /// @dev Escrows the NFT, assigning ownership to this contract. - /// Throws if the escrow fails. - /// @param _owner - Current owner address of token to escrow. - /// @param _tokenId - ID of token whose approval to verify. - function _escrow(address _owner, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transferFrom(_owner, address(this), _tokenId); - } - - /// @dev Transfers an NFT owned by this contract to another address. - /// Returns true if the transfer succeeds. - /// @param _receiver - Address to transfer NFT to. - /// @param _tokenId - ID of token to transfer. - function _transfer(address _receiver, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transfer(_receiver, _tokenId); - } - - /// @dev Adds an auction to the list of open auctions. Also fires the - /// AuctionCreated event. - /// @param _tokenId The ID of the token to be put on auction. - /// @param _auction Auction to add. - function _addAuction(uint256 _tokenId, Auction memory _auction) internal { - // Require that all auctions have a duration of - // at least one minute. (Keeps our math from getting hairy!) - require(_auction.duration >= 1 minutes); - - tokenIdToAuction[_tokenId] = _auction; - - emit AuctionCreated( - uint256(_tokenId), - uint256(_auction.startingPrice), - uint256(_auction.endingPrice), - uint256(_auction.duration) - ); - } - - /// @dev Cancels an auction unconditionally. - function _cancelAuction(uint256 _tokenId, address _seller) internal { - _removeAuction(_tokenId); - _transfer(_seller, _tokenId); - emit AuctionCancelled(_tokenId); - } - - /// @dev Computes the price and transfers winnings. - /// Does NOT transfer ownership of token. - function _bid(uint256 _tokenId, uint256 _bidAmount) - internal - returns (uint256) - { - // Get a reference to the auction struct - Auction storage auction = tokenIdToAuction[_tokenId]; - - // Explicitly check that this auction is currently live. - // (Because of how Ethereum mappings work, we can't just count - // on the lookup above failing. An invalid _tokenId will just - // return an auction object that is all zeros.) - require(_isOnAuction(auction)); - - // Check that the bid is greater than or equal to the current price - uint256 price = _currentPrice(auction); - require(_bidAmount >= price); - - // Grab a reference to the seller before the auction struct - // gets deleted. - address payable seller = auction.seller; - - // The bid is good! Remove the auction before sending the fees - // to the sender so we can't have a reentrancy attack. - _removeAuction(_tokenId); - - // Transfer proceeds to seller (if there are any!) - if (price > 0) { - // Calculate the auctioneer's cut. - // (NOTE: _computeCut() is guaranteed to return a - // value <= price, so this subtraction can't go negative.) - uint256 auctioneerCut = _computeCut(price); - uint256 sellerProceeds = price - auctioneerCut; - - // NOTE: Doing a transfer() in the middle of a complex - // method like this is generally discouraged because of - // reentrancy attacks and DoS attacks if the seller is - // a contract with an invalid fallback function. We explicitly - // guard against reentrancy attacks by removing the auction - // before calling transfer(), and the only thing the seller - // can DoS is the sale of their own asset! (And if it's an - // accident, they can call cancelAuction(). ) - seller.transfer(sellerProceeds); - } - - // Calculate any excess funds included with the bid. If the excess - // is anything worth worrying about, transfer it back to bidder. - // NOTE: We checked above that the bid amount is greater than or - // equal to the price so this cannot underflow. - uint256 bidExcess = _bidAmount - price; - - // Return the funds. Similar to the previous transfer, this is - // not susceptible to a re-entry attack because the auction is - // removed before any transfers occur. - payable(msg.sender).transfer(bidExcess); - - // Tell the world! - emit AuctionSuccessful(_tokenId, price, msg.sender); - - return price; - } - - /// @dev Removes an auction from the list of open auctions. - /// @param _tokenId - ID of NFT on auction. - function _removeAuction(uint256 _tokenId) internal { - delete tokenIdToAuction[_tokenId]; - } - - /// @dev Returns true if the NFT is on auction. - /// @param _auction - Auction to check. - function _isOnAuction(Auction storage _auction) internal view returns (bool) { - return (_auction.startedAt > 0); - } - - /// @dev Returns current price of an NFT on auction. Broken into two - /// functions (this one, that computes the duration from the auction - /// structure, and the other that does the price computation) so we - /// can easily test that the price computation works correctly. - function _currentPrice(Auction storage _auction) - internal - view - returns (uint256) - { - uint256 secondsPassed = 0; - - // A bit of insurance against negative values (or wraparound). - // Probably not necessary (since Ethereum guarnatees that the - // now variable doesn't ever go backwards). - if (block.timestamp > _auction.startedAt) { - secondsPassed = block.timestamp - _auction.startedAt; - } - - return _computeCurrentPrice( - _auction.startingPrice, - _auction.endingPrice, - _auction.duration, - secondsPassed - ); - } - - /// @dev Computes the current price of an auction. Factored out - /// from _currentPrice so we can run extensive unit tests. - /// When testing, make this function public and turn on - /// `Current price computation` test suite. - function _computeCurrentPrice( - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - uint256 _secondsPassed - ) - internal - pure - returns (uint256) - { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our public functions carefully cap the maximum values for - // time (at 64-bits) and currency (at 128-bits). _duration is - // also known to be non-zero (see the require() statement in - // _addAuction()) - if (_secondsPassed >= _duration) { - // We've reached the end of the dynamic pricing portion - // of the auction, just return the end price. - return _endingPrice; - } else { - // Starting price can be higher than ending price (and often is!), so - // this delta can be negative. - int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - - // This multiplication can't overflow, _secondsPassed will easily fit within - // 64-bits, and totalPriceChange will easily fit within 128-bits, their product - // will always fit within 256-bits. - int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - - // currentPriceChange can be negative, but if so, will have a magnitude - // less that _startingPrice. Thus, this result will always end up positive. - int256 currentPrice = int256(_startingPrice) + currentPriceChange; - - return uint256(currentPrice); - } - } - - /// @dev Computes owner's cut of a sale. - /// @param _price - Sale price of NFT. - function _computeCut(uint256 _price) internal view returns (uint256) { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our entry functions carefully cap the maximum values for - // currency (at 128-bits), and ownerCut <= 10000 (see the require() - // statement in the ClockAuction constructor). The result of this - // function is always guaranteed to be <= _price. - return _price * ownerCut / 10000; - } - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { - event Pause(); - event Unpause(); - - bool public paused = false; - - - /** - * @dev modifier to allow actions only when the contract IS paused - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev modifier to allow actions only when the contract IS NOT paused - */ - modifier whenPaused { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyOwner whenNotPaused public returns (bool) { - paused = true; - emit Pause(); - return true; - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyOwner whenPaused public returns (bool) { - paused = false; - emit Unpause(); - return true; - } -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - - /// @dev The ERC-165 interface signature for ERC-721. - /// Ref: https://github.com/ethereum/EIPs/issues/165 - /// Ref: https://github.com/ethereum/EIPs/issues/721 - bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - - /// @dev Constructor creates a reference to the NFT ownership contract - /// and verifies the owner cut is in the valid range. - /// @param _nftAddress - address of a deployed contract implementing - /// the Nonfungible Interface. - /// @param _cut - percent cut the owner takes on each auction, must be - /// between 0-10,000. - constructor(address _nftAddress, uint256 _cut) public { - require(_cut <= 10000); - ownerCut = _cut; - - ERC721 candidateContract = ERC721(_nftAddress); - require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); - nonFungibleContract = candidateContract; - } - - /// @dev Remove all Ether from the contract, which is the owner's cuts - /// as well as any Ether sent directly to the contract address. - /// Always transfers to the NFT contract, but can be called either by - /// the owner or the NFT contract. - function withdrawBalance() external { - address payable nftAddress = payable(address(uint160(address(nonFungibleContract)))); - - require( - msg.sender == owner || - msg.sender == nftAddress - ); - // We are using this boolean method to make sure that even if one fails it will still work - bool res = nftAddress.send(address(this).balance); - } - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of time to move between starting - /// price and ending price (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - virtual - whenNotPaused - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(_owns(msg.sender, _tokenId)); - _escrow(msg.sender, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(block.timestamp) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Bids on an open auction, completing the auction and transferring - /// ownership of the NFT if enough Ether is supplied. - /// @param _tokenId - ID of token to bid on. - function bid(uint256 _tokenId) - external - payable - virtual - whenNotPaused - { - // _bid will throw if the bid or funds transfer fails - _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - } - - /// @dev Cancels an auction that hasn't been won yet. - /// Returns the NFT to original owner. - /// @notice This is a state-modifying function that can - /// be called while the contract is paused. - /// @param _tokenId - ID of token on auction - function cancelAuction(uint256 _tokenId) - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - address seller = auction.seller; - require(msg.sender == seller); - _cancelAuction(_tokenId, seller); - } - - /// @dev Cancels an auction when the contract is paused. - /// Only the owner may do this, and NFTs are returned to - /// the seller. This should only be used in emergencies. - /// @param _tokenId - ID of the NFT on auction to cancel. - function cancelAuctionWhenPaused(uint256 _tokenId) - whenPaused - onlyOwner - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - _cancelAuction(_tokenId, auction.seller); - } - - /// @dev Returns auction info for an NFT on auction. - /// @param _tokenId - ID of NFT on auction. - function getAuction(uint256 _tokenId) - external - view - returns - ( - address seller, - uint256 startingPrice, - uint256 endingPrice, - uint256 duration, - uint256 startedAt - ) { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return ( - auction.seller, - auction.startingPrice, - auction.endingPrice, - auction.duration, - auction.startedAt - ); - } - - /// @dev Returns the current price of an auction. - /// @param _tokenId - ID of the token price we are checking. - function getCurrentPrice(uint256 _tokenId) - external - view - returns (uint256) - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return _currentPrice(auction); - } - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSiringAuctionAddress() call. - bool public isSiringClockAuction = true; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. Since this function is wrapped, - /// require sender to be KittyCore contract. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - override - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(block.timestamp) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Places a bid for siring. Requires the sender - /// is the KittyCore contract because all bid methods - /// should be wrapped. Also returns the kitty to the - /// seller rather than the winner. - function bid(uint256 _tokenId) - external - payable - override - { - require(msg.sender == address(nonFungibleContract)); - address seller = tokenIdToAuction[_tokenId].seller; - // _bid checks that token ID is valid and will throw if bid fails - _bid(_tokenId, msg.value); - // We transfer the kitty back to the seller, the winner will get - // the offspring - _transfer(seller, _tokenId); - } - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSaleAuctionAddress() call. - bool public isSaleClockAuction = true; - - // Tracks last 5 sale price of gen0 kitty sales - uint256 public gen0SaleCount; - uint256[5] public lastGen0SalePrices; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - override - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(block.timestamp) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Updates lastSalePrice if seller is the nft contract - /// Otherwise, works the same as default bid method. - function bid(uint256 _tokenId) - external - payable - override - { - // _bid verifies token ID size - address seller = tokenIdToAuction[_tokenId].seller; - uint256 price = _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - - // If not a gen0 auction, exit - if (seller == address(nonFungibleContract)) { - // Track gen0 sale prices - lastGen0SalePrices[gen0SaleCount % 5] = price; - gen0SaleCount++; - } - } - - function averageGen0SalePrice() external view returns (uint256) { - uint256 sum = 0; - for (uint256 i = 0; i < 5; i++) { - sum += lastGen0SalePrices[i]; - } - return sum / 5; - } - -} - - - - - - - diff --git a/framework/src/test/resources/soliditycode/contractScenario012.sol b/framework/src/test/resources/soliditycode/contractScenario012.sol deleted file mode 100644 index ae6882685a8..00000000000 --- a/framework/src/test/resources/soliditycode/contractScenario012.sol +++ /dev/null @@ -1,57 +0,0 @@ - -contract PayTest { - -uint256 public n; -constructor() payable public{ -n = 0; -} - -function nPlusOne() public{ -n = n+1; -} - -//get current contract balance -function getBalance() payable public returns (uint) { -return address(this).balance; -} - -function getSenderBalance() public view returns(address, uint) { -return (msg.sender, msg.sender.balance); -} - -address public user; - -//deposit 1 coin to msg.sender -function depositOneCoin() payable public returns(bool success){ -return payable(msg.sender).send(1); -} - -// function transferOneCoin() payable public returns(){ -// address(msg.sender).transfer(1); -// } - -// function depositOneCoin() payable public returns(address addr, uint amount, bool success){ -// return (msg.sender, msg.value, msg.sender.send(1)); -// } - -//deposit coin to msg.sender -function deposit(uint256 money) payable public returns(bool success){ -return payable(msg.sender).send(money); -} -// function deposit(uint money) payable public returns(address addr, uint amount, bool success){ -// return (msg.sender, msg.value, msg.sender.send(money)); -// } - -// fallback() payable { -// msg.sender.send(1); -// } - -function sendToAddress(address payable _receiver) payable public{ -_receiver.transfer(msg.value); -} - -function sendToAddress2(address payable _receiver) payable public{ -_receiver.transfer(5); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractScenario013.sol b/framework/src/test/resources/soliditycode/contractScenario013.sol deleted file mode 100644 index 93b7905679b..00000000000 --- a/framework/src/test/resources/soliditycode/contractScenario013.sol +++ /dev/null @@ -1,8 +0,0 @@ - -contract timetest { - -function time() public{ -require(1 trx == 1000000 sun); - -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractScenario014.sol b/framework/src/test/resources/soliditycode/contractScenario014.sol deleted file mode 100644 index 9f423d1b1ab..00000000000 --- a/framework/src/test/resources/soliditycode/contractScenario014.sol +++ /dev/null @@ -1,34 +0,0 @@ - -contract Contract1 { - constructor() public payable{} - function send5SunToReceiver(address payable _receiver) payable public{ - _receiver.transfer(5); - } -} -contract contract2 { - address public payContract; - - constructor(address _add) payable public{ - payContract = _add; - } - - function triggerContract1(address _receiver) payable public{ - payContract.call(abi.encodeWithSignature("send5SunToReceiver(address)",_receiver)); - } - - function triggerContract1ButRevert(address _receiver) payable public{ - payContract.call(abi.encodeWithSignature("send5SunToReceiver(address)",_receiver)); - require(1 == 2); - } - -} -contract contract3 { - address public payContract; - constructor(address _add) payable public{ - payContract = _add; - } - - function triggerContract2(address _receiver) payable public{ - payContract.call(abi.encodeWithSignature("triggerContract1(address)",_receiver)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTest.sol b/framework/src/test/resources/soliditycode/contractTest.sol deleted file mode 100644 index 9a72b4a53b4..00000000000 --- a/framework/src/test/resources/soliditycode/contractTest.sol +++ /dev/null @@ -1,19 +0,0 @@ - - -contract Test{ - -function a() public returns (uint){ - -uint256 count = 0; - -for (uint256 i = 1; i > 0; i++) { - -count++; - -} - -return count; - -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractToMathedFeed.sol b/framework/src/test/resources/soliditycode/contractToMathedFeed.sol deleted file mode 100644 index d9df9d9c10d..00000000000 --- a/framework/src/test/resources/soliditycode/contractToMathedFeed.sol +++ /dev/null @@ -1,21 +0,0 @@ - - -contract ToMathedFeed { - uint public i=1; - function ToMathed (uint value) public { - i=value; - } -} - -contract ToMathedUseINContract { - function ToMathedIUseNR(address a,uint256 n) public returns(bool){ - address payContract=a; - (bool success, bytes memory data) = payContract.call(abi.encodeWithSignature("ToMathedNot(uint256)",n)); - return success; - } - function ToMathedIUseNRE(address a,uint256 value) public returns(bool){ - address payContract=a; - (bool success, bytes memory data) = payContract.call(abi.encodeWithSignature("ToMathed(uint256)",value)); - return success; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTransferToken001.sol b/framework/src/test/resources/soliditycode/contractTransferToken001.sol deleted file mode 100644 index 0edbbfbb44a..00000000000 --- a/framework/src/test/resources/soliditycode/contractTransferToken001.sol +++ /dev/null @@ -1,22 +0,0 @@ -contract A { - address public a; - constructor() public payable{} - function kill(address payable toAddress) payable public{ - selfdestruct(toAddress); - } - function newB() public payable returns(address){ - B bAddress=new B(); - a= address(bAddress); - return a; - - } - - } - -contract B{ - constructor() public payable {} - fallback() external payable {} - function kill(address payable toAddress) payable public{ - selfdestruct(toAddress); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrc1155.sol b/framework/src/test/resources/soliditycode/contractTrc1155.sol deleted file mode 100644 index c33d07b3dfc..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrc1155.sol +++ /dev/null @@ -1,612 +0,0 @@ -pragma solidity ^0.8.0; - -interface IERC165 { - - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - - - -abstract contract ERC165 is IERC165 { - - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} - -interface IERC1155 is IERC165 { - - event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); - - - event TransferBatch( - address indexed operator, - address indexed from, - address indexed to, - uint256[] ids, - uint256[] values - ); - - - event ApprovalForAll(address indexed account, address indexed operator, bool approved); - - - event URI(string value, uint256 indexed id); - - - function balanceOf(address account, uint256 id) external view returns (uint256); - - - function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) - external - view - returns (uint256[] memory); - - - function setApprovalForAll(address operator, bool approved) external; - - - function isApprovedForAll(address account, address operator) external view returns (bool); - - - function safeTransferFrom( - address from, - address to, - uint256 id, - uint256 amount, - bytes calldata data - ) external; - - function safeBatchTransferFrom( - address from, - address to, - uint256[] calldata ids, - uint256[] calldata amounts, - bytes calldata data - ) external; -} - - -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -library Address { - - - function isAContract(address account) internal view returns (bool) { - // This method relies on extcodesize, which returns 0 for contracts in - // construction, since the code is only stored at the end of the - // constructor execution. - - uint256 size; - assembly { - size := extcodesize(account) - } - return size > 0; - } - - - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isAContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isAContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isAContract(target), "Address: delegate call to non-contract"); - - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - - -interface IERC1155MetadataURI is IERC1155 { - - function uri(uint256 id) external view returns (string memory); -} - - - - -interface IERC1155Receiver is IERC165 { - - function onERC1155Received( - address operator, - address from, - uint256 id, - uint256 value, - bytes calldata data - ) external returns (bytes4); - - - function onERC1155BatchReceived( - address operator, - address from, - uint256[] calldata ids, - uint256[] calldata values, - bytes calldata data - ) external returns (bytes4); -} - - -contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { - using Address for address; - - // Mapping from token ID to account balances - mapping(uint256 => mapping(address => uint256)) private _balances; - - // Mapping from account to operator approvals - mapping(address => mapping(address => bool)) private _operatorApprovals; - - // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json - string private _uri; - - /** - * @dev See {_setURI}. - */ - constructor(string memory uri_) { - _setURI(uri_); - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { - return - interfaceId == type(IERC1155).interfaceId || - interfaceId == type(IERC1155MetadataURI).interfaceId || - super.supportsInterface(interfaceId); - } - - - function uri(uint256 id) public view virtual override returns (string memory) { - return _uri; - } - - function balanceOf(address account, uint256 id) public view virtual override returns (uint256) { - require(account != address(0), "ERC1155: balance query for the zero address"); - return _balances[id][account]; - } - - - function balanceOfBatch(address[] memory accounts, uint256[] memory ids) - public - view - virtual - override - returns (uint256[] memory) - { - require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch"); - - uint256[] memory batchBalances = new uint256[](accounts.length); - - for (uint256 i = 0; i < accounts.length; ++i) { - batchBalances[i] = balanceOf(accounts[i], ids[i]); - } - - return batchBalances; - } - - - function setApprovalForAll(address operator, bool approved) public virtual override { - _setApprovalForAll(_msgSender(), operator, approved); - } - - - function isApprovedForAll(address account, address operator) public view virtual override returns (bool) { - return _operatorApprovals[account][operator]; - } - - - function safeTransferFrom( - address from, - address to, - uint256 id, - uint256 amount, - bytes memory data - ) public virtual override { - require( - from == _msgSender() || isApprovedForAll(from, _msgSender()), - "ERC1155: caller is not owner nor approved" - ); - _safeTransferFrom(from, to, id, amount, data); - } - - - function safeBatchTransferFrom( - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) public virtual override { - require( - from == _msgSender() || isApprovedForAll(from, _msgSender()), - "ERC1155: transfer caller is not owner nor approved" - ); - _safeBatchTransferFrom(from, to, ids, amounts, data); - } - - - function _safeTransferFrom( - address from, - address to, - uint256 id, - uint256 amount, - bytes memory data - ) internal virtual { - require(to != address(0), "ERC1155: transfer to the zero address"); - - address operator = _msgSender(); - - _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data); - - uint256 fromBalance = _balances[id][from]; - require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); - unchecked { - _balances[id][from] = fromBalance - amount; - } - _balances[id][to] += amount; - - emit TransferSingle(operator, from, to, id, amount); - - _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); - } - - - function _safeBatchTransferFrom( - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) internal virtual { - require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); - require(to != address(0), "ERC1155: transfer to the zero address"); - - address operator = _msgSender(); - - _beforeTokenTransfer(operator, from, to, ids, amounts, data); - - for (uint256 i = 0; i < ids.length; ++i) { - uint256 id = ids[i]; - uint256 amount = amounts[i]; - - uint256 fromBalance = _balances[id][from]; - require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); - unchecked { - _balances[id][from] = fromBalance - amount; - } - _balances[id][to] += amount; - } - - emit TransferBatch(operator, from, to, ids, amounts); - - _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data); - } - - - function _setURI(string memory newuri) internal virtual { - _uri = newuri; - } - - - function _mint( - address to, - uint256 id, - uint256 amount, - bytes memory data - ) internal virtual { - require(to != address(0), "ERC1155: mint to the zero address"); - - address operator = _msgSender(); - - _beforeTokenTransfer(operator, address(0), to, _asSingletonArray(id), _asSingletonArray(amount), data); - - _balances[id][to] += amount; - emit TransferSingle(operator, address(0), to, id, amount); - - _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data); - } - - - function _mintBatch( - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) internal virtual { - require(to != address(0), "ERC1155: mint to the zero address"); - require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); - - address operator = _msgSender(); - - _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); - - for (uint256 i = 0; i < ids.length; i++) { - _balances[ids[i]][to] += amounts[i]; - } - - emit TransferBatch(operator, address(0), to, ids, amounts); - - _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data); - } - - - function _burn( - address from, - uint256 id, - uint256 amount - ) internal virtual { - require(from != address(0), "ERC1155: burn from the zero address"); - - address operator = _msgSender(); - - _beforeTokenTransfer(operator, from, address(0), _asSingletonArray(id), _asSingletonArray(amount), ""); - - uint256 fromBalance = _balances[id][from]; - require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); - unchecked { - _balances[id][from] = fromBalance - amount; - } - - emit TransferSingle(operator, from, address(0), id, amount); - } - - - function _burnBatch( - address from, - uint256[] memory ids, - uint256[] memory amounts - ) internal virtual { - require(from != address(0), "ERC1155: burn from the zero address"); - require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); - - address operator = _msgSender(); - - _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); - - for (uint256 i = 0; i < ids.length; i++) { - uint256 id = ids[i]; - uint256 amount = amounts[i]; - - uint256 fromBalance = _balances[id][from]; - require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); - unchecked { - _balances[id][from] = fromBalance - amount; - } - } - - emit TransferBatch(operator, from, address(0), ids, amounts); - } - - - function _setApprovalForAll( - address owner, - address operator, - bool approved - ) internal virtual { - require(owner != operator, "ERC1155: setting approval status for self"); - _operatorApprovals[owner][operator] = approved; - emit ApprovalForAll(owner, operator, approved); - } - - - function _beforeTokenTransfer( - address operator, - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) internal virtual {} - - function _doSafeTransferAcceptanceCheck( - address operator, - address from, - address to, - uint256 id, - uint256 amount, - bytes memory data - ) private { - if (to.isAContract()) { - try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) { - if (response != IERC1155Receiver.onERC1155Received.selector) { - revert("ERC1155: ERC1155Receiver rejected tokens"); - } - } catch Error(string memory reason) { - revert(reason); - } catch { - revert("ERC1155: transfer to non ERC1155Receiver implementer"); - } - } - } - - function _doSafeBatchTransferAcceptanceCheck( - address operator, - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) private { - if (to.isAContract()) { - try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns ( - bytes4 response - ) { - if (response != IERC1155Receiver.onERC1155BatchReceived.selector) { - revert("ERC1155: ERC1155Receiver rejected tokens"); - } - } catch Error(string memory reason) { - revert(reason); - } catch { - revert("ERC1155: transfer to non ERC1155Receiver implementer"); - } - } - } - - function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) { - uint256[] memory array = new uint256[](1); - array[0] = element; - - return array; - } - - -} - - -contract TronCoins is ERC1155 { - uint256 public constant TRX = 0; - uint256 public constant BTT = 1; - uint256 public constant WIN = 2; - uint256 public constant SUN = 3; - uint256 public constant APENFT = 4; - uint256 public constant APENFT1 = 5; - - constructor() public ERC1155("https://game.example/api/item/%7Bid%7D.json") { - _mint(msg.sender, TRX, 10**3, ""); - _mint(msg.sender, BTT, 10**2, ""); - _mint(msg.sender, WIN, 10**5, ""); - _mint(msg.sender, SUN, 10**4, ""); - _mint(msg.sender, APENFT, 1, ""); - _mint(msg.sender, APENFT1, 1, ""); - } -} - - -abstract contract ERC1155Receiver is ERC165, IERC1155Receiver { - /** - * @dev See {IERC165-supportsInterface} - */ - function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { - return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId); - } -} - - -contract ERC1155Holder is ERC1155Receiver { - function onERC1155Received( - address, - address, - uint256, - uint256, - bytes memory - ) public virtual override returns (bytes4) { - return this.onERC1155Received.selector; - } - - function onERC1155BatchReceived( - address, - address, - uint256[] memory, - uint256[] memory, - bytes memory - ) public virtual override returns (bytes4) { - return this.onERC1155BatchReceived.selector; - } -} - - -contract MyContractCanReceiver is ERC1155Holder { -} - - - -contract MyContractCanNotReceiver { -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken001.sol b/framework/src/test/resources/soliditycode/contractTrcToken001.sol deleted file mode 100644 index 4bd83e30229..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken001.sol +++ /dev/null @@ -1,41 +0,0 @@ - - - contract tokenTest{ - - uint pos0; - mapping(address => uint) pos1; - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - Storage(); - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - - - function Storage() public { - pos0 = 1234; - pos1[msg.sender] = 5678; - } - - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken002.sol b/framework/src/test/resources/soliditycode/contractTrcToken002.sol deleted file mode 100644 index ea28f4a62b6..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken002.sol +++ /dev/null @@ -1,30 +0,0 @@ - - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken003.sol b/framework/src/test/resources/soliditycode/contractTrcToken003.sol deleted file mode 100644 index 863429fc4f8..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken003.sol +++ /dev/null @@ -1,16 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken005.sol b/framework/src/test/resources/soliditycode/contractTrcToken005.sol deleted file mode 100644 index 863429fc4f8..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken005.sol +++ /dev/null @@ -1,16 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken011.sol b/framework/src/test/resources/soliditycode/contractTrcToken011.sol deleted file mode 100644 index 43e4010ec3f..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken011.sol +++ /dev/null @@ -1,35 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - fallback() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken012.sol b/framework/src/test/resources/soliditycode/contractTrcToken012.sol deleted file mode 100644 index ab0c19767e7..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken012.sol +++ /dev/null @@ -1,26 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken014.sol b/framework/src/test/resources/soliditycode/contractTrcToken014.sol deleted file mode 100644 index 589406c47c6..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken014.sol +++ /dev/null @@ -1,34 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - fallback() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken018.sol b/framework/src/test/resources/soliditycode/contractTrcToken018.sol deleted file mode 100644 index ab0c19767e7..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken018.sol +++ /dev/null @@ -1,26 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken023.sol b/framework/src/test/resources/soliditycode/contractTrcToken023.sol deleted file mode 100644 index 070acb201ff..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken023.sol +++ /dev/null @@ -1,26 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - toAddress.transferToken(amount,id); - } - } - -contract B{ - uint256 public flag = 0; - constructor() public payable {} - fallback() external { - flag = 1; -} - -} - -contract C{ - uint256 public flag = 0; - constructor() public payable {} - fallback() external payable { - //flag = 1; -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken026.sol b/framework/src/test/resources/soliditycode/contractTrcToken026.sol deleted file mode 100644 index 5464265d81f..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken026.sol +++ /dev/null @@ -1,31 +0,0 @@ - - -contract token{ - constructor() payable public{} - fallback() payable external{} - function testInCall(address callBAddress,address callCAddress, address toAddress ,uint256 amount,trcToken id) payable public{ - //callBAddress.call(bytes4(keccak256("transC(address,address,uint256,trcToken)")),callCAddress,toAddress,amount,id); - callBAddress.call(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callCAddress,toAddress,amount,id)); - } - function testIndelegateCall(address callBddress,address callAddressC, address toAddress,uint256 amount, trcToken id) payable public{ - callBddress.delegatecall(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callAddressC,toAddress,amount,id)); - } - } - - - -contract B{ - constructor() public payable{} - fallback() external payable{} - function transC(address payable callCAddress,address payable toAddress,uint256 amount, trcToken id) payable public{ - callCAddress.call(abi.encodeWithSignature("trans(address,uint256,trcToken)",toAddress,amount,id)); - } -} -contract C{ - constructor() payable public{} - fallback() payable external{} - function trans(address payable toAddress,uint256 amount, trcToken id) payable public{ - toAddress.transferToken(amount,id); - } - -} diff --git a/framework/src/test/resources/soliditycode/contractTrcToken027.sol b/framework/src/test/resources/soliditycode/contractTrcToken027.sol deleted file mode 100644 index e7d6ee768f3..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken027.sol +++ /dev/null @@ -1,30 +0,0 @@ - - -contract token{ - constructor() payable public{} - fallback() payable external{} - function testInCall(address callBAddress,address callCAddress, address toAddress ,uint256 amount,trcToken id) payable public{ - callBAddress.call(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callCAddress,toAddress,amount,id)); - } - function testIndelegateCall(address callBddress,address callAddressC, address toAddress,uint256 amount, trcToken id) payable public{ - callBddress.delegatecall(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callAddressC,toAddress,amount,id)); - } - } - - - -contract B{ - constructor() public payable{} - fallback() external payable{} - function transC(address callCAddress,address toAddress,uint256 amount, trcToken id) payable public{ - callCAddress.call(abi.encodeWithSignature("trans(address,uint256,trcToken)",toAddress,amount,id)); - } -} -contract C{ - constructor() payable public{} - fallback() payable external{} - function trans(address payable toAddress,uint256 amount, trcToken id) payable public{ - toAddress.transferToken(amount,id); - } - -} diff --git a/framework/src/test/resources/soliditycode/contractTrcToken028.sol b/framework/src/test/resources/soliditycode/contractTrcToken028.sol deleted file mode 100644 index 0f27d89c819..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken028.sol +++ /dev/null @@ -1,25 +0,0 @@ - - -contract token{ - uint256 public a=1; - constructor() public payable{} - function tokenBalanceWithSameName(trcToken id) public payable{ - B b= new B(); - a= b.tokenBalance(id); - } - function getA() public returns(uint256){ - return a; - } -} - - -contract B{ - uint256 public flag =0; - constructor() public payable{} - fallback() external payable{} - function tokenBalance(trcToken id) payable public returns(uint256){ - flag =9; - return flag; - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken029.sol b/framework/src/test/resources/soliditycode/contractTrcToken029.sol deleted file mode 100644 index 8480cf6f19d..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken029.sol +++ /dev/null @@ -1,24 +0,0 @@ - - -contract token{ - address public a; - constructor() public payable{} - function transferTokenWithSameName(trcToken id,uint256 amount) public payable{ - B b= new B(); - b.transferToken(amount,id); - a= address(b); - } -} - - -contract B{ - uint256 public flag =0; - constructor() public payable{} - fallback() external payable{} - function transferToken(uint256 amount, trcToken id) payable public returns(bool){ - flag =9; - } - function getFlag() public view returns (uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken030.sol b/framework/src/test/resources/soliditycode/contractTrcToken030.sol deleted file mode 100644 index 06b8201979c..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken030.sol +++ /dev/null @@ -1,17 +0,0 @@ - - contract token{ - constructor() public payable{} - - // 4)suicide也会转移token - // 所有token,trx均被转移到toAddress, - // 若toAddress为合约地址本身,则所有token,trx均被烧掉进黑洞 - function kill(address payable toAddress) payable public{ - selfdestruct(toAddress); - } - - } - -contract B{ - constructor() public payable {} - fallback() external payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken031.sol b/framework/src/test/resources/soliditycode/contractTrcToken031.sol deleted file mode 100644 index 65ec394e8da..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken031.sol +++ /dev/null @@ -1,18 +0,0 @@ - - - contract token{ - constructor() public payable{} - - // 4)suicide也会转移token - // 所有token,trx均被转移到toAddress, - // 若toAddress为合约地址本身,则所有token,trx均被烧掉进黑洞 - function kill(address payable toAddress) payable public{ - selfdestruct(toAddress); - } - - } - -contract B{ - constructor() public payable {} - fallback() external payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken034.sol b/framework/src/test/resources/soliditycode/contractTrcToken034.sol deleted file mode 100644 index 32c55f8c84b..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken034.sol +++ /dev/null @@ -1,25 +0,0 @@ - - - contract token{ - - constructor() public payable {} - - // 2. 异常测试 - // 1)revert, 金额回退 - function failTransferTokenRevert(address payable toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - require(1==2); - } - - // 2)Error, 金额回退, fee limit 扣光 - function failTransferTokenError(address payable toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - assert(1==2); - } - - } - contract B{ - uint256 public flag = 0; - constructor() public payable {} - fallback() external payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken035.sol b/framework/src/test/resources/soliditycode/contractTrcToken035.sol deleted file mode 100644 index ca45dde790d..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken035.sol +++ /dev/null @@ -1,24 +0,0 @@ - - - contract token{ - constructor() public payable {} - - // 2. 异常测试 - // 1)revert, 金额回退 - function failTransferTokenRevert(address payable toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - require(1==2); - } - - // 2)Error, 金额回退, fee limit 扣光 - function failTransferTokenError(address payable toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - assert(1==2); - } - - } - contract B{ - uint256 public flag = 0; - constructor() public payable {} - fallback() external payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken036.sol b/framework/src/test/resources/soliditycode/contractTrcToken036.sol deleted file mode 100644 index c1da2f7555e..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken036.sol +++ /dev/null @@ -1,52 +0,0 @@ - -contract IllegalDecorate { -constructor() payable public{} -fallback() payable external{} -event log(uint256); -function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public payable { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate1 { -constructor() payable public{} -fallback() payable external{} -event log(uint256); -function transferTokenWithConstant(address payable toAddress, uint256 tokenValue) public payable { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate2 { -constructor() payable public{} -fallback() payable external{} -event log(uint256); -function transferTokenWithView(address payable toAddress, uint256 tokenValue) public payable { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate3 { -event log(uint256); -constructor() payable public{} -fallback() payable external{} -function transferTokenWithOutPayable(address payable toAddress, uint256 tokenValue) public { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken036_1.sol b/framework/src/test/resources/soliditycode/contractTrcToken036_1.sol deleted file mode 100644 index 327ab5a756e..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken036_1.sol +++ /dev/null @@ -1,13 +0,0 @@ - -contract IllegalDecorate { -constructor() payable public{} -fallback() payable external{} -event log(uint256); -function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public pure { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} diff --git a/framework/src/test/resources/soliditycode/contractTrcToken036_2.sol b/framework/src/test/resources/soliditycode/contractTrcToken036_2.sol deleted file mode 100644 index 817a96e3c80..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken036_2.sol +++ /dev/null @@ -1,13 +0,0 @@ - -contract IllegalDecorate { -constructor() payable public{} -fallback() payable external{} -event log(uint256); -function transferTokenWithConstant(address toAddress, uint256 tokenValue) public constant { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken036_3.sol b/framework/src/test/resources/soliditycode/contractTrcToken036_3.sol deleted file mode 100644 index 67400c2e8ad..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken036_3.sol +++ /dev/null @@ -1,13 +0,0 @@ - -contract IllegalDecorate { -constructor() payable public{} -fallback() payable external{} -event log(uint256); -function transferTokenWithView(address payable toAddress, uint256 tokenValue) public view { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken036_4.sol b/framework/src/test/resources/soliditycode/contractTrcToken036_4.sol deleted file mode 100644 index cbaca0d4b38..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken036_4.sol +++ /dev/null @@ -1,13 +0,0 @@ - -contract IllegalDecorate { -event log(uint256); -constructor() payable public{} -fallback() payable external{} -function transferTokenWithOutPayable(address payable toAddress, uint256 tokenValue) public { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken036_old.sol b/framework/src/test/resources/soliditycode/contractTrcToken036_old.sol deleted file mode 100644 index 1f03afb7636..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken036_old.sol +++ /dev/null @@ -1,41 +0,0 @@ - - - -contract IllegalDecorate1 { -constructor() payable public{} -fallback() payable public{} -event log(uint256); -function transferTokenWithConstant(address toAddress, uint256 tokenValue) public constant { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate2 { -constructor() payable public{} -fallback() payable public{} -event log(uint256); -function transferTokenWithView(address toAddress, uint256 tokenValue) public view { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate3 { -event log(uint256); -constructor() payable public{} -fallback() payable public{} -function transferTokenWithOutPayable(address toAddress, uint256 tokenValue) public { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken037.sol b/framework/src/test/resources/soliditycode/contractTrcToken037.sol deleted file mode 100644 index 7cdd91702e8..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken037.sol +++ /dev/null @@ -1,24 +0,0 @@ - - -contract transferTrc10 { - function receive(address payable rec) public payable { - uint256 aamount=address(this).tokenBalance(msg.tokenid); - uint256 bamount=rec.tokenBalance(msg.tokenid); - require(msg.tokenvalue==aamount); - require(aamount==msg.tokenvalue); - rec.transferToken(aamount,msg.tokenid); - require(0==address(this).tokenBalance(msg.tokenid)); - require(bamount+aamount==rec.tokenBalance(msg.tokenid)); - (bool success, bytes memory data) =rec.call(abi.encodeWithSignature("checkTrc10(uint256,trcToken,uint256)",bamount+aamount,msg.tokenid,0)); - require(success); - - } -} - -contract receiveTrc10 { - fallback() external payable {} - function checkTrc10(uint256 amount,trcToken tid,uint256 meamount) public{ - require(amount==address(this).tokenBalance(tid)); - require(meamount==msg.sender.tokenBalance(tid)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken038.sol b/framework/src/test/resources/soliditycode/contractTrcToken038.sol deleted file mode 100644 index eeb5ae744cf..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken038.sol +++ /dev/null @@ -1,24 +0,0 @@ - - -contract transferTrc10 { - function receive(address payable rec) public payable { - uint256 aamount=address(this).tokenBalance(msg.tokenid); - uint256 bamount=rec.tokenBalance(msg.tokenid); - require(msg.tokenvalue==aamount); - require(aamount==msg.tokenvalue); - rec.transferToken(aamount,msg.tokenid); - //require(rec.call(abi.encode(bytes4(keccak256("AssertError()"))))); - (bool suc, bytes memory data) = rec.call(abi.encodeWithSignature("AssertError()")); - require(suc); - require(aamount==address(this).tokenBalance(msg.tokenid)); - require(bamount==rec.tokenBalance(msg.tokenid)); - } -} - -contract receiveTrc10 { - fallback() external payable { - } - function AssertError() public{ - assert(1==2); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken039.sol b/framework/src/test/resources/soliditycode/contractTrcToken039.sol deleted file mode 100644 index ebf6fb932ed..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken039.sol +++ /dev/null @@ -1,44 +0,0 @@ - -/* - * 1. caller账户issue一个token - * 2. caller部署proxy, 传入1000 token,1000 trx - * 3. caller部署A - * 4. caller部署B - * 5. caller调用proxy中upgradetTo函数,传入A的地址 - * 6. caller调用proxy中不存在的trans(uint256,address,trcToken)函数,注意这时trcToken是无意义的,但也带上tokenid。address是任意另外某账户的地址 - * 7. 可以看到目标地址trx增长5,caller账户trx减少5 - * 8. caller调用proxy中upgradeTo函数,传入B的地址 - * 9. caller调用proxy中不存在的trans(uint256,address,trcToken)函数。 - * 10. 可以看到目标地址token增长5,caller账户token减少5 -*/ -contract Proxy { - constructor() payable public{} - address public implementation; - function upgradeTo(address _address) public { - implementation = _address; - } - fallback() payable external{ - address addr = implementation; - require(addr != address(0)); - assembly { - let freememstart := mload(0x40) - calldatacopy(freememstart, 0, calldatasize()) - let success := delegatecall(not(0), addr, freememstart, calldatasize(), freememstart, 0) - returndatacopy(freememstart, 0, returndatasize()) - switch success - case 0 { revert(freememstart, returndatasize()) } - default { return(freememstart, returndatasize()) } - } - } -} - -contract A { - function trans(uint256 amount, address payable toAddress, trcToken id) payable public { - toAddress.transfer(amount); - } -} -contract B{ - function trans(uint256 amount, address payable toAddress, trcToken id) payable public { - toAddress.transferToken(amount,id); - } -} diff --git a/framework/src/test/resources/soliditycode/contractTrcToken041.sol b/framework/src/test/resources/soliditycode/contractTrcToken041.sol deleted file mode 100644 index 6284253d1d5..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken041.sol +++ /dev/null @@ -1,20 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } - -contract B{ - uint256 public flag = 0; - constructor() public payable {} - fallback() external payable {} - - function setFlag() public payable{ - flag = 1; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken043.sol b/framework/src/test/resources/soliditycode/contractTrcToken043.sol deleted file mode 100644 index 43e4010ec3f..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken043.sol +++ /dev/null @@ -1,35 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - fallback() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken048.sol b/framework/src/test/resources/soliditycode/contractTrcToken048.sol deleted file mode 100644 index e705f696c1d..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken048.sol +++ /dev/null @@ -1,14 +0,0 @@ - - - contract Test { - event log(uint256); - function testMsgTokenValue() payable public returns(uint256 value) { - emit log(msg.tokenvalue); - return msg.tokenvalue; - } - - function testMsgValue() payable public returns(uint256 value) { - emit log(msg.value); - return msg.value; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken049.sol b/framework/src/test/resources/soliditycode/contractTrcToken049.sol deleted file mode 100644 index d40480720df..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken049.sol +++ /dev/null @@ -1,9 +0,0 @@ - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken050.sol b/framework/src/test/resources/soliditycode/contractTrcToken050.sol deleted file mode 100644 index 6bc6d956898..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken050.sol +++ /dev/null @@ -1,10 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken051.sol b/framework/src/test/resources/soliditycode/contractTrcToken051.sol deleted file mode 100644 index 493016b777f..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken051.sol +++ /dev/null @@ -1,11 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - fallback() external payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken052.sol b/framework/src/test/resources/soliditycode/contractTrcToken052.sol deleted file mode 100644 index 6bc6d956898..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken052.sol +++ /dev/null @@ -1,10 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken054.sol b/framework/src/test/resources/soliditycode/contractTrcToken054.sol deleted file mode 100644 index 863429fc4f8..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken054.sol +++ /dev/null @@ -1,16 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken055.sol b/framework/src/test/resources/soliditycode/contractTrcToken055.sol deleted file mode 100644 index 863429fc4f8..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken055.sol +++ /dev/null @@ -1,16 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken060.sol b/framework/src/test/resources/soliditycode/contractTrcToken060.sol deleted file mode 100644 index ea28f4a62b6..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken060.sol +++ /dev/null @@ -1,30 +0,0 @@ - - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken061.sol b/framework/src/test/resources/soliditycode/contractTrcToken061.sol deleted file mode 100644 index ea28f4a62b6..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken061.sol +++ /dev/null @@ -1,30 +0,0 @@ - - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken064.sol b/framework/src/test/resources/soliditycode/contractTrcToken064.sol deleted file mode 100644 index 43e0da8a510..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken064.sol +++ /dev/null @@ -1,49 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } - function transferTokenTestValueMaxBigInteger(address payable toAddress) payable public { - toAddress.transferToken(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0); - } - function transferTokenTestValueOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(9223372036854775808, 1000001); - } - function transferTokenTestValueMaxLong(address payable toAddress) payable public { - toAddress.transferToken(9223372036854775807, 1000001); - } - function transferTokenTestValue0IdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(0, 9223372036854775809); - } -} - - - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - fallback() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken066.sol b/framework/src/test/resources/soliditycode/contractTrcToken066.sol deleted file mode 100644 index 43e4010ec3f..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken066.sol +++ /dev/null @@ -1,35 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - fallback() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken067.sol b/framework/src/test/resources/soliditycode/contractTrcToken067.sol deleted file mode 100644 index 43e4010ec3f..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken067.sol +++ /dev/null @@ -1,35 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - fallback() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken073.sol b/framework/src/test/resources/soliditycode/contractTrcToken073.sol deleted file mode 100644 index a9ee8ea412b..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken073.sol +++ /dev/null @@ -1,16 +0,0 @@ - -contract Dest { - event logFallback(uint256 indexed, uint256 indexed, uint256 indexed); - event logGetToken(uint256 indexed, uint256 indexed, uint256 indexed, uint256); - - - constructor() payable public {} - - function getToken(trcToken tokenId) payable public{ - emit logGetToken(msg.sender.tokenBalance(tokenId), msg.tokenid, msg.tokenvalue, msg.value); - } - - fallback() payable external{ - emit logFallback(msg.tokenid, msg.tokenvalue, msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken075.sol b/framework/src/test/resources/soliditycode/contractTrcToken075.sol deleted file mode 100644 index c90f8dcbee3..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken075.sol +++ /dev/null @@ -1,26 +0,0 @@ - - -contract Dest { - event logFallback(uint256 indexed, uint256 indexed, uint256 indexed); - event logGetToken(uint256 indexed, uint256 indexed, uint256 indexed, uint256); - - constructor() payable public {} - - function getToken(trcToken tokenId) payable public{ - emit logGetToken(msg.sender.tokenBalance(tokenId), msg.tokenid, msg.tokenvalue, msg.value); - } - - function getTokenLongMin() payable public{ - // long.min - 1000020 - emit logGetToken(msg.sender.tokenBalance(trcToken(uint256(int256(-9223372036855775828)))), msg.tokenid, msg.tokenvalue, msg.value); - } - - function getTokenLongMax() payable public{ - // long.max + 1000020 - emit logGetToken(msg.sender.tokenBalance(trcToken(9223372036855775827)), msg.tokenid, msg.tokenvalue, msg.value); - } - - fallback() payable external{ - emit logFallback(msg.tokenid, msg.tokenvalue, msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken076.sol b/framework/src/test/resources/soliditycode/contractTrcToken076.sol deleted file mode 100644 index a9decbee320..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken076.sol +++ /dev/null @@ -1,19 +0,0 @@ - -contract Test { - address public origin; - address public sender; - bool public result1; - bool public result2; - function test() external { - origin = tx.origin; - sender = msg.sender; - result1 = msg.sender == tx.origin; // true - result2 = origin == sender; // true - } -function getResult1() public returns(bool){ - return result1; -} -function getResult2() public returns(bool){ - return result2; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken077.sol b/framework/src/test/resources/soliditycode/contractTrcToken077.sol deleted file mode 100644 index aeecf9cb9a5..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken077.sol +++ /dev/null @@ -1,11 +0,0 @@ - - -contract trcToken077 { -function addressTest() public returns(bytes32 addressValue) { - assembly{ - let x := mload(0x40) //Find empty storage location using "free memory pointer" - mstore(x,address) //Place current contract address - addressValue := mload(x) - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken078.sol b/framework/src/test/resources/soliditycode/contractTrcToken078.sol deleted file mode 100644 index 8d10d25312d..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken078.sol +++ /dev/null @@ -1,35 +0,0 @@ - -contract callerContract { - constructor() public payable{} - fallback() external payable{} - function sendToB(address called_address, address c) public payable{ - called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); - } - function sendToB2(address called_address,address c) public payable{ - called_address.call(abi.encodeWithSignature("transferTo(address)",c)); - } - function sendToB3(address called_address,address c) public payable{ - called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); - } -} - contract calledContract { - fallback() external payable{} - constructor() public payable {} - function transferTo(address payable toAddress)public payable{ - toAddress.transfer(5); - } - - function setIinC(address c) public payable{ - c.call{value:5}(abi.encode(bytes4(keccak256("setI()")))); - } - - } - contract c{ - address public origin; - address public sender; - constructor() public payable{} - event log(address,address); - fallback() payable external{ - emit log(tx.origin,msg.sender); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken079.sol b/framework/src/test/resources/soliditycode/contractTrcToken079.sol deleted file mode 100644 index 863429fc4f8..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken079.sol +++ /dev/null @@ -1,16 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken080.sol b/framework/src/test/resources/soliditycode/contractTrcToken080.sol deleted file mode 100644 index 2d2688b74a4..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken080.sol +++ /dev/null @@ -1,30 +0,0 @@ - - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - fallback() external payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcToken081.sol b/framework/src/test/resources/soliditycode/contractTrcToken081.sol deleted file mode 100644 index b69ecde68b2..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcToken081.sol +++ /dev/null @@ -1,51 +0,0 @@ -contract TokenSender { - constructor() payable public{} - function sendTRC10(address target) public payable { - trcToken tokenId = msg.tokenid; - bytes memory callData = abi.encodeWithSignature("receiveTRC10(address,uint256,trcToken)", msg.sender, 1, tokenId); - assembly { - let ret := calltoken( - gas(), - target, - 1, - tokenId, - add(callData, 0x20), - mload(callData), - 0, - 0) - if iszero(ret) { - revert(0, 0) - } - } - } - - function sendTRC10NoMethod(address target) public payable { - trcToken tokenId = msg.tokenid; - bytes4 sig = bytes4(keccak256("()")); // function signature - assembly { - let x := mload(0x40) // get empty storage location - mstore(x,sig) - let ret := calltoken( - gas(), - target, - 1, //token value - tokenId, //token id - x, // input - 0x04, // input size = 4 bytes - x, // output stored at input location, save space - 0x04) - if iszero(ret) { - revert(0, 0) - } - } - } -} - -contract TokenReceiver { - constructor() payable public{} - event Received(address, address, uint256, trcToken); - - function receiveTRC10(address origin, uint256 value, trcToken id) external payable { - emit Received(msg.sender, origin, value, id); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractTrcTokenToOther.sol b/framework/src/test/resources/soliditycode/contractTrcTokenToOther.sol deleted file mode 100644 index 6a18fac311a..00000000000 --- a/framework/src/test/resources/soliditycode/contractTrcTokenToOther.sol +++ /dev/null @@ -1,44 +0,0 @@ - - -contract ConvertType { - -constructor() payable public{} - -fallback() payable external{} - -//function trcTokenOnStorage(trcToken storage token) internal { // ERROR: Data location can only be specified for array, struct or mapping types, but "storage" was given. -//} - -function trcTokenToString(trcToken token) public pure returns(string memory s){ -// s = token; // ERROR -// s = string(token); // ERROR -} - -function trcTokenToUint256(trcToken token) public pure returns(uint256 r){ -uint256 u = token; // OK -uint256 u2 = uint256(token); // OK -r = u2; -} - -function trcTokenToAddress(trcToken token) public pure returns(address r){ -//r = token; // ERROR -token = 1000001; -address a2 = address(uint160(token)); // OK -r = a2; -} - -function trcTokenToBytes(trcToken token) public pure returns(bytes memory r){ -//r = token; // ERROR -// r = bytes(token); // ERROR -} - -function trcTokenToBytes32(trcToken token) public pure returns(bytes32 r){ -// r = token; // ERROR -bytes32 b2 = bytes32(token); // OK -r = b2; -} - -function trcTokenToArray(trcToken token) public pure returns(uint[] memory r){ -//r = token; // ERROR -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/contractUnknownException.sol b/framework/src/test/resources/soliditycode/contractUnknownException.sol deleted file mode 100644 index d2d37364a0e..00000000000 --- a/framework/src/test/resources/soliditycode/contractUnknownException.sol +++ /dev/null @@ -1,64 +0,0 @@ - -contract testA { - constructor() public payable { - A a = (new A){value:10}(); - a.fun(); - } -} - -contract testB { - constructor() public payable { - B b = (new B){value:10}(); - b.fun(); - } -} - - -contract testC { - constructor() public payable{ - C c = (new C){value:10}(); - c.fun(); - } -} - -contract testD { - constructor() public payable{ - D d = (new D){value:10}(); - d.fun(); - } -} - - -contract A { - constructor() public payable{ - selfdestruct(payable(msg.sender)); - } - function fun() public { - } - -} - -contract B { - constructor() public payable { - revert(); - } - function fun() public { - } -} - - -contract C { - constructor() public payable { - assert(1==2); - } - function fun() public { - } -} - -contract D { - constructor() public payable { - require(1==2); - } - function fun() public { - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/create2CallContract.sol b/framework/src/test/resources/soliditycode/create2CallContract.sol deleted file mode 100644 index 046706ebd9e..00000000000 --- a/framework/src/test/resources/soliditycode/create2CallContract.sol +++ /dev/null @@ -1,37 +0,0 @@ -contract callerContract { - constructor() payable public{} - fallback() payable external{} - function delegateCallCreate2(address called_address, bytes memory code, uint256 salt) public { - called_address.delegatecall(abi.encodeWithSignature("deploy(bytes,uint256)",code,salt)); - } - function callCreate2(address called_address,bytes memory code, uint256 salt) public returns(bool,bytes memory){ - return called_address.call(abi.encodeWithSignature("deploy(bytes,uint256)",code,salt)); - } -} - - -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - -contract TestConstract { - uint public i; - constructor () public { - } - function plusOne() public returns(uint){ - i++; - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/create2Istanbul.sol b/framework/src/test/resources/soliditycode/create2Istanbul.sol deleted file mode 100644 index c2ef8f3236b..00000000000 --- a/framework/src/test/resources/soliditycode/create2Istanbul.sol +++ /dev/null @@ -1,28 +0,0 @@ - - -contract create2Istanbul { - function deploy(bytes memory code, uint256 salt) public returns(address) { - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - - } - return addr; - } - - // prefix in main net is 0x41, testnet config is 0xa0 - function get(bytes1 prefix, bytes calldata code, uint256 salt) external view returns(address) { - //bytes32 hash = keccak256(abi.encodePacked(bytes1(0x41),address(this), salt, keccak256(code))); - bytes32 hash = keccak256(abi.encodePacked(prefix,address(this), salt, keccak256(code))); - address addr = address(uint160(uint256(hash))); - return addr; - } - -} - -contract B { - constructor() public payable{} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/create2contract.sol b/framework/src/test/resources/soliditycode/create2contract.sol deleted file mode 100644 index 0171f4d5486..00000000000 --- a/framework/src/test/resources/soliditycode/create2contract.sol +++ /dev/null @@ -1,52 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } - - event Deployed(address addr, bytes32 salt, address sender); - function deploy(bytes memory code, bytes32 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - -contract FactoryBytes { - event Deployed(address addr, bytes32 salt, address sender); - function deploy(bytes memory code, bytes32 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - -contract TestConstract { - uint public i; - constructor () public { - } - function plusOne() public returns(uint){ - i++; - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/create2contract22.sol b/framework/src/test/resources/soliditycode/create2contract22.sol deleted file mode 100644 index cfad7c815fb..00000000000 --- a/framework/src/test/resources/soliditycode/create2contract22.sol +++ /dev/null @@ -1,109 +0,0 @@ -contract Factory { - event Deployed(address addr, trcToken salt, address sender); - event Deployed1(address addr, uint256 salt, address sender); - event Deployed2(address addr, address salt, address sender); - event Deployed3(address addr, string salt, address sender); - - - function deploy(bytes memory code, trcToken salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } - - function deploy1(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed1(addr, salt, msg.sender); - return addr; - } - - function deploy2(bytes memory code, address salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed2(addr, salt, msg.sender); - return addr; - } - - function deploy3(bytes memory code, string memory salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed3(addr, salt, msg.sender); - return addr; - } - -} - - -contract TestConstract { - uint public i=1; - function testTransfer(uint256 i) payable public{ - payable(msg.sender).transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - payable(msg.sender).transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} - -contract TestConstract1 { - uint public i=2; - function testTransfer(uint256 i) payable public{ - payable(msg.sender).transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - payable(msg.sender).transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} - -contract TestConstract2 { - uint public i=3; - function testTransfer(uint256 i) payable public{ - payable(msg.sender).transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - payable(msg.sender).transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} - -contract TestConstract3 { - uint public i=4; - function testTransfer(uint256 i) payable public{ - payable(msg.sender).transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - payable(msg.sender).transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/create2contractn.sol b/framework/src/test/resources/soliditycode/create2contractn.sol deleted file mode 100644 index 4ecf7bc16b4..00000000000 --- a/framework/src/test/resources/soliditycode/create2contractn.sol +++ /dev/null @@ -1,29 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract TestConstract { - uint public i=1; - function testTransfer(uint256 i) payable public{ - payable(msg.sender).transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - payable(msg.sender).transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/create2contractn2.sol b/framework/src/test/resources/soliditycode/create2contractn2.sol deleted file mode 100644 index 626988c4e04..00000000000 --- a/framework/src/test/resources/soliditycode/create2contractn2.sol +++ /dev/null @@ -1,26 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract TestConstract { - uint public i=1; - function set() payable public { - i=5; - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/demo.sol b/framework/src/test/resources/soliditycode/demo.sol deleted file mode 100644 index 06bf15387fc..00000000000 --- a/framework/src/test/resources/soliditycode/demo.sol +++ /dev/null @@ -1,73 +0,0 @@ - - - contract tokenTest{ - uint256 codesize; - constructor() payable public{ - uint256 m; - address addr = address(this); - assembly { - m := extcodesize(addr) - } - codesize = m; - } - - // positive case - function pulsone() public payable{ - uint256 j = 0; - uint i = 100; - for (; i < i; i++) { - j++; - } - } - - - function getCodeSize() public returns (uint256){ - return codesize; - } - - } - - contract confirmTest{ - - uint256 codesize; - constructor() payable public{ - uint256 m; - address addr = address(this); - assembly { - m := extcodesize(addr) - - } - codesize = m; - } - - function getCodeSize() public returns (uint256){ - return codesize; - } - - function confirm(address addr) public returns (uint256){ - uint256 j; - assembly { - j := extcodesize(addr) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - return j; - } - - function at(address _addr) public returns (bytes memory o_code) { - assembly { - // retrieve the size of the code, this needs assembly - let size := extcodesize(_addr) - // allocate output byte array - this could also be done without assembly - // by using o_code = new bytes(size) - o_code := mload(0x40) - // new "memory end" including padding - mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) - // store length in memory - mstore(o_code, size) - // actually retrieve the code, this needs assembly - extcodecopy(_addr, add(o_code, 0x20), 0, size) - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/enumAndStruct.sol b/framework/src/test/resources/soliditycode/enumAndStruct.sol deleted file mode 100644 index 836a4ac850e..00000000000 --- a/framework/src/test/resources/soliditycode/enumAndStruct.sol +++ /dev/null @@ -1,43 +0,0 @@ - - -struct S_out { -uint x; -} - -enum ErrorType { -Revert_Error, //0 -RevertWithMsg_Error, //1 -Require_Error, //2 -RequirewithMsg_Error, //3 -Assert_Error, //4 -Tansfer_Error, //5 -Send_Error, //6 -Math_Error, //7 -ArrayOverFlow_Error //8 -} - -contract enumAndStructTest { - -struct S_inner { -int x; -} - -enum ErrorType_inner { -Revert_Error, //0 -RevertWithMsg_Error, //1 -Require_Error, //2 -RequirewithMsg_Error, //3 -Assert_Error, //4 -Tansfer_Error, //5 -Send_Error, //6 -Math_Error, //7 -ArrayOverFlow_Error //8 -} - -function getvalue() public returns(uint) { - require(ErrorType.Require_Error == ErrorType(2)); - S_out memory s = S_out(1); - return s.x; -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/event001.sol b/framework/src/test/resources/soliditycode/event001.sol deleted file mode 100644 index 7662df3a5c6..00000000000 --- a/framework/src/test/resources/soliditycode/event001.sol +++ /dev/null @@ -1,10 +0,0 @@ -contract Event { - event xixi(uint256 id) ; - event log2(uint256,uint256,uint256); - constructor() public payable{} - function messageI() payable public returns (uint ret) { - //emit log2(1,2,3); - emit xixi(1); - return 1; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/event002.sol b/framework/src/test/resources/soliditycode/event002.sol deleted file mode 100644 index a61f834e1b5..00000000000 --- a/framework/src/test/resources/soliditycode/event002.sol +++ /dev/null @@ -1,52 +0,0 @@ - - -contract Event { - - event _0(); - event a_0() anonymous; - event a_4i(uint256 indexed x1, uint256 indexed x2 , uint256 indexed x3, uint256 indexed x4, uint256 x5)anonymous ; - event _3i(uint256 x1, uint256 indexed x2 , uint256 indexed x3, uint256 x4, uint256 x5) ; - event _1i(uint256 indexed x1, uint256, uint256 indexed, uint256 x4) ; - event a_1i(uint256) anonymous; - event _ai(uint8[2], uint8) ; - event a_ai(uint8[2], uint8) anonymous; - event _a1i(uint8[2] indexed, uint8) ; - event a_a1i(uint8[2] indexed, uint8) anonymous; - - constructor () public { - // emit a_0(); - // emit a_1i(123); - // emit a_4i(1,2,3,5,16); - // emit _0(); - emit _3i(1,2,3,5,16); - // emit _1i(1,2,3,5); - // emit _ai([1,2], 3); - // emit a_ai([3,4], 5); - // emit _a1i([1,2], 3); - // emit a_a1i([3,4], 5); - } - - function e() public { - emit _1i(1,2,3,4); - } - - function l() public { - emit a_1i(1); - } - - function k() public{ - emit a_4i(2,3,4,5,17); - emit _3i(2,3,4,5,16); - emit _1i(2,3,4,5); - emit a_1i(128); - emit _0(); - emit a_0(); - //selfdestruct(msg.sender); - //emit a_4i(1,2,3,5,16); - //emit _3i(1,2,3,5,16); - //emit _1i(1,2,3,5); - //emit a_1i(123); - //emit _0(); - //emit a_0(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/eventLog2.sol b/framework/src/test/resources/soliditycode/eventLog2.sol deleted file mode 100644 index 0ad82f6dd1f..00000000000 --- a/framework/src/test/resources/soliditycode/eventLog2.sol +++ /dev/null @@ -1,8 +0,0 @@ -contract Event { - event log2(uint256,uint256,uint256); - constructor() public payable{} - function messageI() payable public returns (uint ret) { - emit log2(1,1,1); - return 1; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/extCodeHash.sol b/framework/src/test/resources/soliditycode/extCodeHash.sol deleted file mode 100644 index d6209770682..00000000000 --- a/framework/src/test/resources/soliditycode/extCodeHash.sol +++ /dev/null @@ -1,13 +0,0 @@ -contract TestExtCodeHash { - - function getCodeHashByAddr(address _addr) public returns (bytes32 _hash) { - assembly { - _hash := extcodehash(_addr) - } - } - function getCodeHashByUint(uint256 _addr) public returns (bytes32 _hash) { - assembly { - _hash := extcodehash(_addr) - } - } -} diff --git a/framework/src/test/resources/soliditycode/extCodeHash11.sol b/framework/src/test/resources/soliditycode/extCodeHash11.sol deleted file mode 100644 index 961941c7d20..00000000000 --- a/framework/src/test/resources/soliditycode/extCodeHash11.sol +++ /dev/null @@ -1,103 +0,0 @@ -contract Counter { -uint count = 0; -address payable owner; -event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); -constructor() public{ -owner = payable(msg.sender); -} -function getCodeHashByAddr() public returns (bytes32 _hashBefore, bytes32 _hashAfter) { -address addr = address(this); -assembly { -_hashBefore := extcodehash(addr) -} -if (owner == msg.sender) { -selfdestruct(owner); -} -assembly { -_hashAfter := extcodehash(addr) -} -revert(); -emit LogResult(_hashBefore, _hashAfter); -} -} - -contract Counter1 { -uint count = 0; -address payable owner; -event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); -constructor() public{ -owner = payable(msg.sender); -} -function getCodeHashByAddr() public returns (bytes32 _hashBefore, bytes32 _hashAfter) { -address addr = address(this); -assembly { -_hashBefore := extcodehash(addr) -} -if (owner == msg.sender) { -selfdestruct(owner); -} -assembly { -_hashAfter := extcodehash(addr) -} - -emit LogResult(_hashBefore, _hashAfter); -} -} - - -contract Counter2 { -uint count = 0; -address payable owner; -event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); -constructor() public{ -owner = payable(msg.sender); -} -function getCodeHashByAddr(address c) public returns (bytes32 _hashBefore, bytes32 _hashAfter) { - TestConstract t=new TestConstract(); -address addr = address(t); -assembly { -_hashBefore := extcodehash(addr) -} - addr.call(abi.encodeWithSignature("testSuicideNonexistentTarget(address)",c)); - - -assembly { -_hashAfter := extcodehash(addr) -} - -emit LogResult(_hashBefore, _hashAfter); -} -} - - -contract Counter3 { -uint count = 0; -address payable owner; -event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); -constructor() public{ -owner = payable(msg.sender); -} -function getCodeHashByAddr(address c) public returns (bytes32 _hashBefore, bytes32 _hashAfter) { - TestConstract t=new TestConstract(); -address addr = address(t); -assembly { -_hashBefore := extcodehash(addr) -} -if (owner == msg.sender) { -selfdestruct(owner); -} - -assembly { -_hashAfter := extcodehash(addr) -} - -emit LogResult(_hashBefore, _hashAfter); -} -} - -contract TestConstract { - uint public i=1; - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/extCodeHashConstruct.sol b/framework/src/test/resources/soliditycode/extCodeHashConstruct.sol deleted file mode 100644 index 6d640ad7a23..00000000000 --- a/framework/src/test/resources/soliditycode/extCodeHashConstruct.sol +++ /dev/null @@ -1,14 +0,0 @@ -contract CounterConstruct { - uint count = 0; - address payable owner; - event LogResult(bytes32 _hashBefore); - constructor() public{ - owner = payable(msg.sender); - address addr = address(this); - bytes32 _hashBefore; - assembly { - _hashBefore := extcodehash(addr) - } - emit LogResult(_hashBefore); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/extCodeHashStress.sol b/framework/src/test/resources/soliditycode/extCodeHashStress.sol deleted file mode 100644 index cf41f3c8106..00000000000 --- a/framework/src/test/resources/soliditycode/extCodeHashStress.sol +++ /dev/null @@ -1,45 +0,0 @@ -contract Trigger { - function test(address addr) public returns(uint i) { - bytes32 hash; - while (gasleft() > 1000) { - assembly { - hash := extcodehash(addr) - } - i++; - } - } - - function test(address[] memory addrs) public returns(uint i) { - bytes32 hash; - uint i = 0; - for (; i < addrs.length; i++) { - address addr = addrs[i]; - assembly { - hash := extcodehash(addr) - } - } - return i; - } - } - - - - contract TriggerNormal { - function test(address addr) public returns(uint i) { - i = 0; - while (gasleft() > 100000) { - i++; - } - } - } - - contract TriggerNormal1 { - function test(address[] memory addrs) public returns(uint i) { - bytes32 hash; - uint i = 0; - for (; i < addrs.length; i++) { - address addr = addrs[i]; - addr.balance; - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/extCodeHashTestNoPayable.sol b/framework/src/test/resources/soliditycode/extCodeHashTestNoPayable.sol deleted file mode 100644 index c3a2ad8c6ae..00000000000 --- a/framework/src/test/resources/soliditycode/extCodeHashTestNoPayable.sol +++ /dev/null @@ -1,8 +0,0 @@ -contract testConstantContract{ -uint256 public i; -function testNoPayable() public returns (uint256 z) { -i=1; -z=i; -return z; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/fallbackUpgrade.sol b/framework/src/test/resources/soliditycode/fallbackUpgrade.sol deleted file mode 100644 index 6751858c65e..00000000000 --- a/framework/src/test/resources/soliditycode/fallbackUpgrade.sol +++ /dev/null @@ -1,83 +0,0 @@ -contract Test0{ - event FuncCalled(bytes data,uint a); -} - -contract Test1 { - - event FuncCalled(string a); - fallback() external { - x = "fallback"; - emit FuncCalled(x); - } - string x; -} -//含有payable的fallback,无receice -contract Test2 { - - event FuncCalled(string data); - fallback() external payable{ - x = "fallback"; - emit FuncCalled(x); - } - string x; -} - -contract TestPayable { - event FuncCalled(string a); - - fallback() external payable { - x = "fallback"; - emit FuncCalled(x); - } - - receive() external payable { - x = "receive"; - emit FuncCalled(x); - } - string x; -} - -contract Caller { - function callTest0(Test0 test) public{ - (bool success,) = address(test).call(abi.encodeWithSignature("nonExistingFunction()")); - require(success); - } - function callTest1(address test) public returns (bool) { - (bool success,) = test.call(abi.encodeWithSignature("nonExistingFunction()")); - require(success); - (success,) = address(test).call(""); - require(success); - return true; - } - function callTest2(address test) public payable returns (bool) { - (bool success,) = test.call{value:1000}(abi.encodeWithSignature("nonExistingFunction()")); - require(success); - return true; - } - function callTestPayable1(TestPayable test) public payable returns (bool) { - (bool success,) = address(test).call(abi.encodeWithSignature("nonExistingFunction()")); - require(success); - (success,) = address(test).call(""); - require(success); - return true; - } -} - - -//contract Test0 { -// event FallbackCall(string data,bytes msg); -// //event FuncCalled(string a,bytes data); -// function() external payable{ -// x = "fallback"; -// emit FallbackCall(x,msg.data); -// } -// string x; -//} -//contract Caller{ -// function call(Test0 test) public payable returns(bool){ -// (bool success,) = address(test).call(abi.encodeWithSignature("nonExistingFunction()")); -// require(success); -// return true; -// } -//} - diff --git a/framework/src/test/resources/soliditycode/freezeContract001.sol b/framework/src/test/resources/soliditycode/freezeContract001.sol deleted file mode 100644 index f8522c4166e..00000000000 --- a/framework/src/test/resources/soliditycode/freezeContract001.sol +++ /dev/null @@ -1,63 +0,0 @@ - -contract TestFreeze { - constructor() public payable {} - - function freeze(address payable receiver, uint amount, uint res) external payable{ - receiver.freeze(amount, res); - } - - function unfreeze(address payable receiver, uint res) external { - receiver.unfreeze(res); - } - - function destroy(address payable inheritor) external { - selfdestruct(inheritor); - } - - function send(address payable A) external { - A.transfer(10); - } - - function send(address payable A, uint256 value) external { - A.transfer(value); - } - - function getExpireTime(address payable target, uint res) external view returns(uint) { - return target.freezeExpireTime(res); - } - - function deploy(uint256 salt) public returns(address){ - address addr; - bytes memory code = type(C).creationCode; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } - - function freezeAndSend(address payable receiver, uint amount, uint res) external { - receiver.transfer(amount); - receiver.freeze(amount, res); - } - - -} - - -contract C { - constructor() public payable {} - - function destroy(address payable inheritor) external { - selfdestruct(inheritor); - } -} - -contract D { - constructor() public payable { - payable(msg.sender).freeze(msg.value, 1); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/function_type_array_to_storage.sol b/framework/src/test/resources/soliditycode/function_type_array_to_storage.sol deleted file mode 100644 index a2093023d6a..00000000000 --- a/framework/src/test/resources/soliditycode/function_type_array_to_storage.sol +++ /dev/null @@ -1,45 +0,0 @@ -contract C { - constructor() public payable{} - function () external returns(uint)[1] externalDefaultArray; - function () external view returns(uint)[1] externalViewArray; - function () external pure returns(uint)[1] externalPureArray; - - function () internal returns(uint)[1] internalDefaultArray; - function () internal view returns(uint)[1] internalViewArray; - function () internal pure returns(uint)[1] internalPureArray; - - function externalDefault() external returns(uint) { return 11; } - function externalView() external view returns(uint) { return 12; } - function externalPure() external pure returns(uint) { return 13; } - - function internalDefault() internal returns(uint) { return 21; } - function internalView() internal view returns(uint) { return 22; } - function internalPure() internal pure returns(uint) { return 23; } - - function testViewToDefault() public returns (uint, uint) { - externalDefaultArray = [this.externalView]; - internalDefaultArray = [internalView]; - - return (externalDefaultArray[0](), internalDefaultArray[0]()); - } - - function testPureToDefault() public returns (uint, uint) { - externalDefaultArray = [this.externalPure]; - internalDefaultArray = [internalPure]; - - return (externalDefaultArray[0](), internalDefaultArray[0]()); - } - - function testPureToView() public returns (uint, uint) { - externalViewArray = [this.externalPure]; - internalViewArray = [internalPure]; - - return (externalViewArray[0](), internalViewArray[0]()); - } -} -// ==== -// compileViaYul: also -// ---- -// testViewToDefault() -> 12, 22 -// testPureToDefault() -> 13, 23 -// testPureToView() -> 13, 23 diff --git a/framework/src/test/resources/soliditycode/getAddressChange.sol b/framework/src/test/resources/soliditycode/getAddressChange.sol deleted file mode 100644 index 2796da68770..00000000000 --- a/framework/src/test/resources/soliditycode/getAddressChange.sol +++ /dev/null @@ -1,12 +0,0 @@ -contract getAddressChange { - constructor() public payable {} - // testaddress1函数新增了一个address属性。0.6.0之前 external函数可以通过address(x)来转化为地址,6.0将其禁止,可以通过函数address属性直接获取 - function testaddress1() public view returns(address) { - //return address(this.getamount); //0.6.0之前可以使用 - return this.getamount.address; //0.6.0 - - } - function getamount(address) external view returns(uint256) { - return address(this).balance; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/isSRCandidate.sol b/framework/src/test/resources/soliditycode/isSRCandidate.sol deleted file mode 100644 index e8e9b692dec..00000000000 --- a/framework/src/test/resources/soliditycode/isSRCandidate.sol +++ /dev/null @@ -1,35 +0,0 @@ - - - -contract ContractB{ - address others; -} - -contract TestIsSRCandidate{ - - ContractB contractB = new ContractB(); - - function isSRCandidateTest(address addr) public view returns (bool) { - return address(addr).isSRCandidate; - } - - function zeroAddressTest() public view returns (bool) { - return address(0x0).isSRCandidate; - } - - function localContractAddrTest() public view returns (bool) { - return address(this).isSRCandidate; - } - - function otherContractAddrTest() public view returns (bool) { - return address(contractB).isSRCandidate; - } - - function nonpayableAddrTest(address addr) public view returns (bool) { - return addr.isSRCandidate; - } - - function payableAddrTest(address payable addr) public returns (bool) { - return addr.isSRCandidate; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/mappingGetter.sol b/framework/src/test/resources/soliditycode/mappingGetter.sol deleted file mode 100644 index dbd473717cb..00000000000 --- a/framework/src/test/resources/soliditycode/mappingGetter.sol +++ /dev/null @@ -1,4 +0,0 @@ -contract mappingGetter { - mapping(bytes => uint256) public balances1; - mapping(string => uint256) public balances2; -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/multiValiSignPerformance01.sol b/framework/src/test/resources/soliditycode/multiValiSignPerformance01.sol deleted file mode 100644 index 74baa963366..00000000000 --- a/framework/src/test/resources/soliditycode/multiValiSignPerformance01.sol +++ /dev/null @@ -1,37 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract ecrecoverValidateSign { - - using ECVerify for bytes32; - - function validateSign(bytes32 hash,bytes[] memory sig,address[] memory signer) public returns (bool) { - for(uint256 i=0;i=0.5.0 <0.7.0; - -contract A { - uint public x; - function setValue(uint _x) public { - x = _x; - } -} -contract B is A {} -contract C is A {} -// No explicit override required -contract D is B, C {} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/override003.sol b/framework/src/test/resources/soliditycode/override003.sol deleted file mode 100644 index 0ca6a2663d1..00000000000 --- a/framework/src/test/resources/soliditycode/override003.sol +++ /dev/null @@ -1,20 +0,0 @@ -//pragma solidity ^0.6.0; -contract A { - uint public x; - function setValue(uint _x) public virtual { - x = _x; - } -} - -contract B { - uint public y; - function setValue(uint _y) public virtual { - y = _y; - } -} - -contract C is A, B { - function setValue(uint _x) public override(B,A) { - A.setValue(_x); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/override004.sol b/framework/src/test/resources/soliditycode/override004.sol deleted file mode 100644 index d0cf20525d5..00000000000 --- a/framework/src/test/resources/soliditycode/override004.sol +++ /dev/null @@ -1,25 +0,0 @@ -//pragma solidity >=0.5.0 <0.7.0; - -contract A { - uint public x = 4; - function setValue(uint _x) public notZero { - x = _x; - } - modifier notZero() virtual { - require(x >= 5,"x must >= 5"); - _; - } -} - -contract B is A { - function setValue2(uint _x) public { - x = _x; - } -} - -contract C is A,B { - modifier notZero override { - require(x >= 6,"x must >= 6"); - _; - } -} diff --git a/framework/src/test/resources/soliditycode/override005.sol b/framework/src/test/resources/soliditycode/override005.sol deleted file mode 100644 index 0ea485ae0a2..00000000000 --- a/framework/src/test/resources/soliditycode/override005.sol +++ /dev/null @@ -1,39 +0,0 @@ -pragma solidity >= 0.6.0; - -contract Base { - enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } - ActionChoices public choice2 = ActionChoices.GoRight; - - function stopped() virtual external view returns (bool) { - return true; - } - function i() virtual external view returns (int) { - return 32482980; - } - function i2() virtual external view returns (int) { - return -32482980; - } - function ui() virtual external view returns (uint) { - return 23487820; - } - function origin() virtual external view returns (address) { - return 0x3b0E4a6EdEE231CE0c3433F00F1bbc5FeD409c0B; - } - function b32() virtual external view returns (bytes32) { - return 0xb55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd231050; - } - function choice() virtual external returns (ActionChoices) { - return choice2; - } -} - -contract Test is Base { - - bool override public stopped = false; - int override public i = 32482989; - int override public i2 = -32482989; - uint override public ui = 23487823; - address override public origin = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; - bytes32 override public b32 = 0xb55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105c; - ActionChoices override public choice = ActionChoices.SitStill; -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/overridePrivateFunction.sol b/framework/src/test/resources/soliditycode/overridePrivateFunction.sol deleted file mode 100644 index b0b4d679620..00000000000 --- a/framework/src/test/resources/soliditycode/overridePrivateFunction.sol +++ /dev/null @@ -1,22 +0,0 @@ -pragma solidity ^0.5.17; - -contract A { - - function test() private pure returns(uint) { - return 1; - } - -} - -contract B is A { - - function basic() private pure returns(uint) { - return 2; - } - function testOverridePrivate() external payable returns(uint) { - return basic(); - } - - constructor() public payable {} -} - diff --git a/framework/src/test/resources/soliditycode/payable001.sol b/framework/src/test/resources/soliditycode/payable001.sol deleted file mode 100644 index 4fe7b20921f..00000000000 --- a/framework/src/test/resources/soliditycode/payable001.sol +++ /dev/null @@ -1,31 +0,0 @@ - - - -contract A { - constructor() public payable{ - } - - fallback() external payable { - } -} - -contract PayableTest { - -address payable a1; -function receiveMoneyTransfer(address a, uint256 _x) public { -a1 = payable(a); -a1.transfer(_x); -} - -function receiveMoneySend(address a, uint256 x) public { -address payable a2 = payable(a); -a2.send(x); -} - -function receiveMoneyTransferWithContract(A PayableTest, uint256 x) public { -payable(address(PayableTest)).transfer(x); -} - -constructor() public payable{ -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/pedersenHash001.sol b/framework/src/test/resources/soliditycode/pedersenHash001.sol deleted file mode 100644 index 6cad7cb9855..00000000000 --- a/framework/src/test/resources/soliditycode/pedersenHash001.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract pedersenHashTest { - - function test1() public returns (bool, bytes memory){ - bytes memory empty = ""; - return address(0x1000004).delegatecall(empty); - } - - function test2(bytes memory data) public returns (bool, bytes memory){ - return address(0x1000004).delegatecall(data); - } - - function test3(uint32 hash, bytes32 left, bytes32 right) public returns (bytes32){ - return pedersenHash(hash, left, right); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/pedersenHash002.sol b/framework/src/test/resources/soliditycode/pedersenHash002.sol deleted file mode 100644 index b0a78973ef2..00000000000 --- a/framework/src/test/resources/soliditycode/pedersenHash002.sol +++ /dev/null @@ -1,320 +0,0 @@ -pragma experimental ABIEncoderV2; - -import "./SafeMath.sol"; - -abstract contract TokenTRC20 { - function transfer(address _to, uint256 _value) public virtual returns (bool success); - - function transferFrom(address _from, address _to, uint256 _value) public virtual returns (bool success); -} - -contract ShieldedTRC20 { - using SafeMath for uint256; - - uint256 public scalingFactor; // used when decimals of TRC20 token is too large. - uint256 public leafCount; - uint256 constant INT64_MAX = 2 ** 63 - 1; - bytes32 public latestRoot; - mapping(bytes32 => bytes32) public nullifiers; // store nullifiers of spent commitments - mapping(bytes32 => bytes32) public roots; // store history root - mapping(uint256 => bytes32) public tree; - mapping(bytes32 => bytes32) public noteCommitment; - bytes32[33] frontier; - bytes32[32] zeroes = [bytes32(0x0100000000000000000000000000000000000000000000000000000000000000), bytes32(0x817de36ab2d57feb077634bca77819c8e0bd298c04f6fed0e6a83cc1356ca155), bytes32(0xffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e34), bytes32(0xd8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c), bytes32(0xe110de65c907b9dea4ae0bd83a4b0a51bea175646a64c12b4c9f931b2cb31b49), bytes32(0x912d82b2c2bca231f71efcf61737fbf0a08befa0416215aeef53e8bb6d23390a), bytes32(0x8ac9cf9c391e3fd42891d27238a81a8a5c1d3a72b1bcbea8cf44a58ce7389613), bytes32(0xd6c639ac24b46bd19341c91b13fdcab31581ddaf7f1411336a271f3d0aa52813), bytes32(0x7b99abdc3730991cc9274727d7d82d28cb794edbc7034b4f0053ff7c4b680444), bytes32(0x43ff5457f13b926b61df552d4e402ee6dc1463f99a535f9a713439264d5b616b), bytes32(0xba49b659fbd0b7334211ea6a9d9df185c757e70aa81da562fb912b84f49bce72), bytes32(0x4777c8776a3b1e69b73a62fa701fa4f7a6282d9aee2c7a6b82e7937d7081c23c), bytes32(0xec677114c27206f5debc1c1ed66f95e2b1885da5b7be3d736b1de98579473048), bytes32(0x1b77dac4d24fb7258c3c528704c59430b630718bec486421837021cf75dab651), bytes32(0xbd74b25aacb92378a871bf27d225cfc26baca344a1ea35fdd94510f3d157082c), bytes32(0xd6acdedf95f608e09fa53fb43dcd0990475726c5131210c9e5caeab97f0e642f), bytes32(0x1ea6675f9551eeb9dfaaa9247bc9858270d3d3a4c5afa7177a984d5ed1be2451), bytes32(0x6edb16d01907b759977d7650dad7e3ec049af1a3d875380b697c862c9ec5d51c), bytes32(0xcd1c8dbf6e3acc7a80439bc4962cf25b9dce7c896f3a5bd70803fc5a0e33cf00), bytes32(0x6aca8448d8263e547d5ff2950e2ed3839e998d31cbc6ac9fd57bc6002b159216), bytes32(0x8d5fa43e5a10d11605ac7430ba1f5d81fb1b68d29a640405767749e841527673), bytes32(0x08eeab0c13abd6069e6310197bf80f9c1ea6de78fd19cbae24d4a520e6cf3023), bytes32(0x0769557bc682b1bf308646fd0b22e648e8b9e98f57e29f5af40f6edb833e2c49), bytes32(0x4c6937d78f42685f84b43ad3b7b00f81285662f85c6a68ef11d62ad1a3ee0850), bytes32(0xfee0e52802cb0c46b1eb4d376c62697f4759f6c8917fa352571202fd778fd712), bytes32(0x16d6252968971a83da8521d65382e61f0176646d771c91528e3276ee45383e4a), bytes32(0xd2e1642c9a462229289e5b0e3b7f9008e0301cbb93385ee0e21da2545073cb58), bytes32(0xa5122c08ff9c161d9ca6fc462073396c7d7d38e8ee48cdb3bea7e2230134ed6a), bytes32(0x28e7b841dcbc47cceb69d7cb8d94245fb7cb2ba3a7a6bc18f13f945f7dbd6e2a), bytes32(0xe1f34b034d4a3cd28557e2907ebf990c918f64ecb50a94f01d6fda5ca5c7ef72), bytes32(0x12935f14b676509b81eb49ef25f39269ed72309238b4c145803544b646dca62d), bytes32(0xb2eed031d4d6a4f02a097f80b54cc1541d4163c6b6f5971f88b6e41d35c53814)]; - address owner; - TokenTRC20 trc20Token; - - event MintNewLeaf(uint256 position, bytes32 cm, bytes32 cv, bytes32 epk, bytes32[21] c); - event TransferNewLeaf(uint256 position, bytes32 cm, bytes32 cv, bytes32 epk, bytes32[21] c); - event BurnNewLeaf(uint256 position, bytes32 cm, bytes32 cv, bytes32 epk, bytes32[21] c); - event TokenMint(address from, uint256 value); - event TokenBurn(address to, uint256 value, bytes32[3] ciphertext); - event NoteSpent(bytes32 nf); - - constructor (address trc20ContractAddress, uint256 scalingFactorExponent) public { - require(scalingFactorExponent < 77, "The scalingFactorExponent is out of range!"); - scalingFactor = 10 ** scalingFactorExponent; - owner = msg.sender; - trc20Token = TokenTRC20(trc20ContractAddress); - } - // output: cm, cv, epk, proof - function mint(uint256 rawValue, bytes32[9] calldata output, bytes32[2] calldata bindingSignature, bytes32[21] calldata c) external { - address sender = msg.sender; - // transfer the trc20Token from the sender to this contract - bool transferResult = trc20Token.transferFrom(sender, address(this), rawValue); - require(transferResult, "TransferFrom failed!"); - - require(noteCommitment[output[0]] == 0, "Duplicate noteCommitments!"); - uint64 value = rawValueToValue(rawValue); - bytes32 signHash = sha256(abi.encodePacked(address(this), value, output, c)); - (bytes32[] memory ret) = verifyMintProof(output, bindingSignature, value, signHash, frontier, leafCount); - uint256 result = uint256(ret[0]); - require(result == 1, "The proof and signature have not been verified by the contract!"); - - uint256 slot = uint256(ret[1]); - uint256 nodeIndex = leafCount + 2 ** 32 - 1; - tree[nodeIndex] = output[0]; - if (slot == 0) { - frontier[0] = output[0]; - } - for (uint256 i = 1; i < slot + 1; i++) { - nodeIndex = (nodeIndex - 1) / 2; - tree[nodeIndex] = ret[i + 1]; - if (i == slot) { - frontier[slot] = tree[nodeIndex]; - } - } - latestRoot = ret[slot + 2]; - roots[latestRoot] = latestRoot; - noteCommitment[output[0]] = output[0]; - leafCount ++; - - emit MintNewLeaf(leafCount - 1, output[0], output[1], output[2], c); - emit TokenMint(sender, rawValue); - } - //input: nf, anchor, cv, rk, proof - //output: cm, cv, epk, proof - function transfer(bytes32[10][] calldata input, bytes32[2][] calldata spendAuthoritySignature, bytes32[9][] calldata output, bytes32[2] calldata bindingSignature, bytes32[21][] calldata c) external { - require(input.length >= 1 && input.length <= 2, "Input number must be 1 or 2!"); - require(input.length == spendAuthoritySignature.length, "Input number must be equal to spendAuthoritySignature number!"); - require(output.length >= 1 && output.length <= 2, "Output number must be 1 or 2!"); - require(output.length == c.length, "Output number must be equal to c number!"); - - for (uint256 i = 0; i < input.length; i++) { - require(nullifiers[input[i][0]] == 0, "The note has already been spent!"); - require(roots[input[i][1]] != 0, "The anchor must exist!"); - } - for (uint256 i = 0; i < output.length; i++) { - require(noteCommitment[output[i][0]] == 0, "Duplicate noteCommitment!"); - } - - bytes32 signHash = sha256(abi.encodePacked(address(this), input, output, c)); - (bytes32[] memory ret) = verifyTransferProof(input, spendAuthoritySignature, output, bindingSignature, signHash, 0, frontier, leafCount); - uint256 result = uint256(ret[0]); - require(result == 1, "The proof and signature have not been verified by the contract!"); - - uint256 offset = 1; - //ret offset - for (uint256 i = 0; i < output.length; i++) { - uint256 slot = uint256(ret[offset++]); - uint256 nodeIndex = leafCount + 2 ** 32 - 1; - tree[nodeIndex] = output[i][0]; - if (slot == 0) { - frontier[0] = output[i][0]; - } - for (uint256 k = 1; k < slot + 1; k++) { - nodeIndex = (nodeIndex - 1) / 2; - tree[nodeIndex] = ret[offset++]; - if (k == slot) { - frontier[slot] = tree[nodeIndex]; - } - } - leafCount++; - } - latestRoot = ret[offset]; - roots[latestRoot] = latestRoot; - for (uint256 i = 0; i < input.length; i++) { - bytes32 nf = input[i][0]; - nullifiers[nf] = nf; - emit NoteSpent(nf); - } - for (uint256 i = 0; i < output.length; i++) { - noteCommitment[output[i][0]] = output[i][0]; - emit TransferNewLeaf(leafCount - (output.length - i), output[i][0], output[i][1], output[i][2], c[i]); - } - } - //input: nf, anchor, cv, rk, proof - //output: cm, cv, epk, proof - function burn(bytes32[10] calldata input, bytes32[2] calldata spendAuthoritySignature, uint256 rawValue, bytes32[2] calldata bindingSignature, address payTo, bytes32[3] calldata burnCipher, bytes32[9][] calldata output, bytes32[21][] calldata c) external { - uint64 value = rawValueToValue(rawValue); - bytes32 signHash = sha256(abi.encodePacked(address(this), input, output, c, payTo, value)); - - bytes32 nf = input[0]; - bytes32 anchor = input[1]; - require(nullifiers[nf] == 0, "The note has already been spent!"); - require(roots[anchor] != 0, "The anchor must exist!"); - - require(output.length <= 1, "Output number cannot exceed 1!"); - require(output.length == c.length, "Output number must be equal to length of c!"); - - // bytes32 signHash = sha256(abi.encodePacked(address(this), input, payTo, value, output, c)); - if (output.length == 0) { - (bool result) = verifyBurnProof(input, spendAuthoritySignature, value, bindingSignature, signHash); - require(result, "The proof and signature have not been verified by the contract!"); - } else { - transferInBurn(input, spendAuthoritySignature, value, bindingSignature, signHash, output, c); - } - - nullifiers[nf] = nf; - emit NoteSpent(nf); - //Finally, transfer trc20Token from this contract to the nominated address - bool transferResult = trc20Token.transfer(payTo, rawValue); - require(transferResult, "Transfer failed!"); - - emit TokenBurn(payTo, rawValue, burnCipher); - } - - function transferInBurn(bytes32[10] memory input, bytes32[2] memory spendAuthoritySignature, uint64 value, bytes32[2] memory bindingSignature, bytes32 signHash, bytes32[9][] memory output, bytes32[21][] memory c) private { - bytes32 cm = output[0][0]; - require(noteCommitment[cm] == 0, "Duplicate noteCommitment!"); - bytes32[10][] memory inputs = new bytes32[10][](1); - inputs[0] = input; - bytes32[2][] memory spendAuthoritySignatures = new bytes32[2][](1); - spendAuthoritySignatures[0] = spendAuthoritySignature; - (bytes32[] memory ret) = verifyTransferProof(inputs, spendAuthoritySignatures, output, bindingSignature, signHash, value, frontier, leafCount); - uint256 result = uint256(ret[0]); - require(result == 1, "The proof and signature have not been verified by the contract!"); - - uint256 slot = uint256(ret[1]); - uint256 nodeIndex = leafCount + 2 ** 32 - 1; - tree[nodeIndex] = cm; - if (slot == 0) { - frontier[0] = cm; - } - for (uint256 i = 1; i < slot + 1; i++) { - nodeIndex = (nodeIndex - 1) / 2; - tree[nodeIndex] = ret[i + 1]; - if (i == slot) { - frontier[slot] = tree[nodeIndex]; - } - } - latestRoot = ret[slot + 2]; - roots[latestRoot] = latestRoot; - noteCommitment[cm] = cm; - leafCount ++; - - emit BurnNewLeaf(leafCount - 1, cm, output[0][1], output[0][2], c[0]); - } - - //position: index of leafnode, start from 0 - function getPath(uint256 position) public view returns (bytes32, bytes32[32] memory) { - require(position >= 0, "Position should be non-negative!"); - require(position < leafCount, "Position should be smaller than leafCount!"); - uint256 index = position + 2 ** 32 - 1; - bytes32[32] memory path; - uint32 level = ancestorLevel(position); - bytes32 targetNodeValue = getTargetNodeValue(position, level); - for (uint32 i = 0; i < 32; i++) { - if (i == level) { - path[31 - i] = targetNodeValue; - } else { - if (index % 2 == 0) { - path[31 - i] = tree[index - 1]; - } else { - path[31 - i] = tree[index + 1] == 0 ? zeroes[i] : tree[index + 1]; - } - } - index = (index - 1) / 2; - } - return (latestRoot, path); - } - - //position: index of leafnode, start from 0 - function getPathByValueIsZero(uint256 position) public view returns (bytes32, bytes32[32] memory) { - require(position >= 0, "Position should be non-negative!"); - require(position < leafCount, "Position should be smaller than leafCount!"); - uint256 index = position + 2 ** 32 - 1; - bytes32[32] memory path; - uint32 level = ancestorLevel(position); - bytes32 targetNodeValue = getTargetNodeValueByValueIsZero(position, level); - for (uint32 i = 0; i < 32; i++) { - if (i == level) { - path[31 - i] = targetNodeValue; - } else { - if (index % 2 == 0) { - path[31 - i] = tree[index - 1]; - } else { - path[31 - i] = tree[index + 1] == 0 ? zeroes[i] : tree[index + 1]; - } - } - index = (index - 1) / 2; - } - return (latestRoot, path); - } - - function ancestorLevel(uint256 leafIndex) private view returns (uint32) { - uint256 nodeIndex1 = leafIndex + 2 ** 32 - 1; - uint256 nodeIndex2 = leafCount + 2 ** 32 - 2; - uint32 level = 0; - while (((nodeIndex1 - 1) / 2) != ((nodeIndex2 - 1) / 2)) { - nodeIndex1 = (nodeIndex1 - 1) / 2; - nodeIndex2 = (nodeIndex2 - 1) / 2; - level = level + 1; - } - return level; - } - - function getTargetNodeValue(uint256 leafIndex, uint32 level) private view returns (bytes32) { - bytes32 left; - bytes32 right; - uint256 index = leafIndex + 2 ** 32 - 1; - uint256 nodeIndex = leafCount + 2 ** 32 - 2; - bytes32 nodeValue = tree[nodeIndex]; - if (level == 0) { - if (index < nodeIndex) { - return nodeValue; - } - if (index == nodeIndex) { - if (index % 2 == 0) { - return tree[index - 1]; - } else { - return zeroes[0]; - } - } - } - for (uint32 i = 0; i < level; i++) { - if (nodeIndex % 2 == 0) { - left = tree[nodeIndex - 1]; - right = nodeValue; - } else { - left = nodeValue; - right = zeroes[i]; - } - nodeValue = pedersenHash(i, left, right); - nodeIndex = (nodeIndex - 1) / 2; - } - return nodeValue; - } - - function getTargetNodeValueByValueIsZero(uint256 leafIndex, uint32 level) private view returns (bytes32) { - bytes32 left; - bytes32 right; - uint256 index = leafIndex + 2 ** 32 - 1; - uint256 nodeIndex = leafCount + 2 ** 32 - 2; - bytes32 nodeValue = tree[nodeIndex]; - if (level == 0) { - if (index < nodeIndex) { - return nodeValue; - } - if (index == nodeIndex) { - if (index % 2 == 0) { - return tree[index - 1]; - } else { - return zeroes[0]; - } - } - } - for (uint32 i = 0; i < level; i++) { - if (nodeIndex % 2 == 0) { - left = tree[nodeIndex - 1]; - right = nodeValue; - } else { - left = nodeValue; - right = zeroes[i]; - } - left = bytes32(0x0); - right = bytes32(0x0); - nodeValue = pedersenHash(i, left, right); - nodeIndex = (nodeIndex - 1) / 2; - } - return nodeValue; - } - - function rawValueToValue(uint256 rawValue) private view returns (uint64) { - require(rawValue > 0, "Value must be positive!"); - require(rawValue.mod(scalingFactor) == 0, "Value must be integer multiples of scalingFactor!"); - uint256 value = rawValue.div(scalingFactor); - require(value < INT64_MAX); - return uint64(value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/requireExceptiontest1TestRequireContract.sol b/framework/src/test/resources/soliditycode/requireExceptiontest1TestRequireContract.sol deleted file mode 100644 index 16d01911d35..00000000000 --- a/framework/src/test/resources/soliditycode/requireExceptiontest1TestRequireContract.sol +++ /dev/null @@ -1,15 +0,0 @@ - -contract TestThrowsContract{ - function testAssert() public { - assert(1==2); - } - function testRequire() public { - require(2==1); - } - function testRevert() public { - revert(); - } - //function testThrow(){ - // throw; - //} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/requireExceptiontest2TestThrowsContract.sol b/framework/src/test/resources/soliditycode/requireExceptiontest2TestThrowsContract.sol deleted file mode 100644 index 1ff73ad6460..00000000000 --- a/framework/src/test/resources/soliditycode/requireExceptiontest2TestThrowsContract.sol +++ /dev/null @@ -1,15 +0,0 @@ - -contract TestThrowsContract{ - function testAssert() public { - assert(1==2); - } - function testRequire() public { - require(2==1); - } - function testRevert() public { - revert(); - } - // function testThrow() public { - // throw; - //} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/requireExceptiontest3TestRevertContract.sol b/framework/src/test/resources/soliditycode/requireExceptiontest3TestRevertContract.sol deleted file mode 100644 index b42a8c3fb23..00000000000 --- a/framework/src/test/resources/soliditycode/requireExceptiontest3TestRevertContract.sol +++ /dev/null @@ -1,15 +0,0 @@ - -contract TestThrowsContract{ - function testAssert() public { - assert(1==2); - } - function testRequire() public { - require(2==1); - } - function testRevert() public { - revert(); - } - // function testThrow(){ - // throw; - // } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/requireExceptiontest4noPayableContract.sol b/framework/src/test/resources/soliditycode/requireExceptiontest4noPayableContract.sol deleted file mode 100644 index 35f89631e7d..00000000000 --- a/framework/src/test/resources/soliditycode/requireExceptiontest4noPayableContract.sol +++ /dev/null @@ -1,8 +0,0 @@ - - -contract noPayableContract { - -function noPayable() public payable returns (uint){ -return msg.value; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/requireExceptiontest4noPayableContract_1.sol b/framework/src/test/resources/soliditycode/requireExceptiontest4noPayableContract_1.sol deleted file mode 100644 index 35f89631e7d..00000000000 --- a/framework/src/test/resources/soliditycode/requireExceptiontest4noPayableContract_1.sol +++ /dev/null @@ -1,8 +0,0 @@ - - -contract noPayableContract { - -function noPayable() public payable returns (uint){ -return msg.value; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/requireExceptiontest5noPayableConstructor.sol b/framework/src/test/resources/soliditycode/requireExceptiontest5noPayableConstructor.sol deleted file mode 100644 index 097594ab7c9..00000000000 --- a/framework/src/test/resources/soliditycode/requireExceptiontest5noPayableConstructor.sol +++ /dev/null @@ -1,11 +0,0 @@ - - -contract MyContract { - uint money; - - //function MyContract(uint _money) { - constructor(uint _money) public payable{ - require(msg.value >= _money); - money = _money; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/requireExceptiontest5noPayableConstructor_1.sol b/framework/src/test/resources/soliditycode/requireExceptiontest5noPayableConstructor_1.sol deleted file mode 100644 index 5008ec5c9bf..00000000000 --- a/framework/src/test/resources/soliditycode/requireExceptiontest5noPayableConstructor_1.sol +++ /dev/null @@ -1,11 +0,0 @@ - - -contract MyContract { - uint money; - - //function MyContract(uint _money) { - constructor(uint _money) public { - require(msg.value >= _money); - money = _money; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/requireExceptiontest6transferTestContract.sol b/framework/src/test/resources/soliditycode/requireExceptiontest6transferTestContract.sol deleted file mode 100644 index 4f171aebb9a..00000000000 --- a/framework/src/test/resources/soliditycode/requireExceptiontest6transferTestContract.sol +++ /dev/null @@ -1,8 +0,0 @@ - - -contract transferTestContract { - function tranferTest(address payable addr) public payable{ - addr.transfer(10); - - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/requireExceptiontest7payableFallbakContract.sol b/framework/src/test/resources/soliditycode/requireExceptiontest7payableFallbakContract.sol deleted file mode 100644 index 534726cb1b4..00000000000 --- a/framework/src/test/resources/soliditycode/requireExceptiontest7payableFallbakContract.sol +++ /dev/null @@ -1,14 +0,0 @@ - - -contract Test { - fallback() external { x = 1; } - uint x; -} - - -contract Caller { - function callTest(Test test) public { - //test.call(0xabcdef01); // hash does not exist - address(test).call(abi.encode(0xabcdef01)); // hash does not exist - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/requireExceptiontest8newContractGasNoenough.sol b/framework/src/test/resources/soliditycode/requireExceptiontest8newContractGasNoenough.sol deleted file mode 100644 index b8743e8231a..00000000000 --- a/framework/src/test/resources/soliditycode/requireExceptiontest8newContractGasNoenough.sol +++ /dev/null @@ -1,19 +0,0 @@ - - -contract Account{ - uint256 public accId; - - // function Account(uint accountId) payable{ - constructor(uint accountId) payable public { - accId = accountId; - } -} - -contract Initialize{ - // Account public account = new Account(10); - - function newAccount() public { - Account account = new Account(1); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/requireExceptiontest9MessageUsedErrorFeed.sol b/framework/src/test/resources/soliditycode/requireExceptiontest9MessageUsedErrorFeed.sol deleted file mode 100644 index 18142d20ee8..00000000000 --- a/framework/src/test/resources/soliditycode/requireExceptiontest9MessageUsedErrorFeed.sol +++ /dev/null @@ -1,18 +0,0 @@ - - -contract MathedFeed { - - function divideMathed() public returns (uint ret) { - uint x=1; - uint y=0; - return x/y; - } -} - - -contract MathedUseContract { - - function MathedUse(address addr) public returns (uint) { - return MathedFeed(addr).divideMathed(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/requireExceptiontestFunctionUsedErrorFeed.sol b/framework/src/test/resources/soliditycode/requireExceptiontestFunctionUsedErrorFeed.sol deleted file mode 100644 index 64243dffd7c..00000000000 --- a/framework/src/test/resources/soliditycode/requireExceptiontestFunctionUsedErrorFeed.sol +++ /dev/null @@ -1,17 +0,0 @@ - - -contract MessageFeed { - - function mValue() payable public returns (uint ret) { - return msg.value; - } -} - -contract MessageUseContract { - function inputValue() payable public returns (uint){ - return msg.value; - } - function messageUse(address addr) payable public returns (uint) { - return MessageFeed(addr).mValue{value:1}(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/selector.sol b/framework/src/test/resources/soliditycode/selector.sol deleted file mode 100644 index 5805a6e8d22..00000000000 --- a/framework/src/test/resources/soliditycode/selector.sol +++ /dev/null @@ -1,21 +0,0 @@ - - -library A { - function getBalance(address) public view returns (uint256) { - return address(this).balance; - } - - function getamount(address) external view returns (uint256) { - return address(this).balance; - } -} - -contract testSelector { - using A for address; - - - function getselector2() public view returns (bytes4, bytes4) { - return (A.getBalance.selector, A.getamount.selector); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/slotAndOffsetNewGrammer.sol b/framework/src/test/resources/soliditycode/slotAndOffsetNewGrammer.sol deleted file mode 100644 index b4c2b0ed516..00000000000 --- a/framework/src/test/resources/soliditycode/slotAndOffsetNewGrammer.sol +++ /dev/null @@ -1,32 +0,0 @@ -contract A { - uint b; - uint a; - uint c; - uint d; - uint e; - - function getA() external returns(uint,uint) { - uint slot; - uint offset; - assembly { -// old grammer -// slot := a_slot -// offset := a_offset - slot := a.slot - offset := a.offset - } - return (slot, offset); - } - - function getE() external returns(uint,uint) { - uint slot; - uint offset; - assembly { -// slot := e_slot -// offset := e_offset - slot := e.slot - offset := e.offset - } - return (slot, offset); - } -} diff --git a/framework/src/test/resources/soliditycode/stackContract001.sol b/framework/src/test/resources/soliditycode/stackContract001.sol deleted file mode 100644 index c2e8f2f7611..00000000000 --- a/framework/src/test/resources/soliditycode/stackContract001.sol +++ /dev/null @@ -1,61 +0,0 @@ - - -contract A{ - event log(uint256); - constructor() payable public{ - emit log(withdrawreward()); - emit log(address(this).rewardbalance); - } - function withdrawRewardTest() public returns (uint256){ - return withdrawreward(); - } - - function test() public{ - emit log(123); - } -} - -contract B{ - event log(uint256); - constructor() payable public{ - emit log(withdrawreward()); - emit log(address(this).rewardbalance); - } - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - function UnStake() public returns (bool result){ - return unstake(); - } - function SelfdestructTest(address payable target) public{ - selfdestruct(target); - } - function rewardBalance(address addr) public view returns (uint256){ - return addr.rewardbalance; - } - - function nullAddressTest() public view returns (uint256) { - return address(0x0).rewardbalance; - } - - function localContractAddrTest() public view returns (uint256) { - address payable localContract = address(uint160(address(this))); - return localContract.rewardbalance; - } - - function withdrawRewardTest() public returns (uint256){ - return withdrawreward(); - } - - function contractBWithdrawRewardTest(address contractB) public returns (uint) { - return B(contractB).withdrawRewardTest(); - } - - function createA() public returns (address){ - return address(new A()); - } - - function callA(address Addr) public{ - A(Addr).test(); - } -} diff --git a/framework/src/test/resources/soliditycode/stackSuicide001.sol b/framework/src/test/resources/soliditycode/stackSuicide001.sol deleted file mode 100644 index d1fc520ddb2..00000000000 --- a/framework/src/test/resources/soliditycode/stackSuicide001.sol +++ /dev/null @@ -1,84 +0,0 @@ - -contract testStakeSuicide{ - B b; - constructor() payable public{} - function deployB() payable public returns (B addrB){ - b = (new B).value(1000000000)(); - return b; - } - function SelfdestructTest(address payable target) public{ - selfdestruct(target); - } - function SelfdestructTest2(address sr, uint256 amount, address payable target) public{ - stake(sr, amount); - selfdestruct(target); - } - function Stake(address sr, uint256 amount) public payable returns (bool result){ - return stake(sr, amount); - } - function Stake2(address sr, uint256 amount) public returns (bool result){ - stake(sr, amount); - return stake(sr, amount); - } - function UnStake() public returns (bool result){ - return unstake(); - } - function UnStake2() public returns (bool result){ - unstake(); - return unstake(); - } - function WithdrawReward() public { - withdrawreward(); - } - function RewardBalance(address addr) view public returns (uint256 balance) { - return addr.rewardbalance; - } - function revertTest1(address sr, uint256 amount, address payable transferAddr) public{ - transferAddr.transfer(1000000); - stake(sr, amount); - transferAddr.transfer(2000000); - stake(sr, 1000000000000000);//stake more than balance to fail - transferAddr.transfer(4000000); - } - function revertTest2(address payable transferAddr) public{ - transferAddr.transfer(1000000); - unstake(); - transferAddr.transfer(2000000); - unstake();//unstake twice to fail - transferAddr.transfer(4000000); - } - - function BStake(address sr, uint256 amount) public returns (bool result){ - return b.Stake(sr, amount); - } - function BUnStake() public returns (bool result){ - return b.UnStake(); - } - function transfer(address payable add,uint256 num) public { - return add.transfer(num); - } -} - -contract B{ - constructor() payable public{} - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - function UnStake() public returns (bool result){ - return unstake(); - } - function SelfdestructTest(address payable target) public{ - selfdestruct(target); - } - - function deploy(bytes memory code, uint256 salt) public returns(address) { - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - return addr; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/stateVariableShadowing.sol b/framework/src/test/resources/soliditycode/stateVariableShadowing.sol deleted file mode 100644 index a9109ee296c..00000000000 --- a/framework/src/test/resources/soliditycode/stateVariableShadowing.sol +++ /dev/null @@ -1,21 +0,0 @@ -contract test { -// uint public x; -// function setValue1(uint _x) public returns (uint){ -// x = _x; -// return x; -// } - uint public y; - function setValue3(uint _x) public returns (uint){ - y = _x; - return y; - } -} - -contract stateVariableShadowing is test { - uint public x; - function setValue2(uint _x) public returns (uint){ - x = _x; - return x; - } -} - diff --git a/framework/src/test/resources/soliditycode/stringSplit.sol b/framework/src/test/resources/soliditycode/stringSplit.sol deleted file mode 100644 index 84231f2d1fe..00000000000 --- a/framework/src/test/resources/soliditycode/stringSplit.sol +++ /dev/null @@ -1,45 +0,0 @@ - - -contract testStringSplit { -string s1 = "s""1""2"",./"; -string s2 = "s123?\\'."; -string s3 = hex"41"hex"42"; -string s4 = hex"4142"; - -function getS1() public view returns (string memory) { -return s1; -} - -function getS1N1() public pure returns (string memory) { -string memory n1 = "s""1""2"",./"; -return n1; -} - -function getS2() public view returns (string memory) { -return s2; -} - -function getS2N2() public pure returns (string memory) { -string memory n2 = "s123?\'."; -return n2; -} - -function getS3() public view returns (string memory) { -return s3; -} - -function getS3N3() public pure returns (string memory) { -string memory n3 = hex"41"hex"42"; -return n3; -} - -function getS4() public view returns (string memory) { -return s4; -} - -function getS4N4() public pure returns (string memory) { -string memory n4 = hex"4142"; -return n4; -} - -} diff --git a/framework/src/test/resources/soliditycode/suicide001.sol b/framework/src/test/resources/soliditycode/suicide001.sol deleted file mode 100644 index cb4690e1043..00000000000 --- a/framework/src/test/resources/soliditycode/suicide001.sol +++ /dev/null @@ -1,32 +0,0 @@ -contract factory { - constructor() payable public { - } - - function create1() payable public returns (address){ - Caller add = (new Caller){value:0}(); - return address(add); - } - - function kill() payable public{ - selfdestruct(payable(msg.sender)); - } - - function create2(bytes memory code, uint256 salt) public returns(address){ - Caller addr; - Caller addr1; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - return address(addr); - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/suicide002.sol b/framework/src/test/resources/soliditycode/suicide002.sol deleted file mode 100644 index bb845f8e0d6..00000000000 --- a/framework/src/test/resources/soliditycode/suicide002.sol +++ /dev/null @@ -1,43 +0,0 @@ -contract Factory { - uint256 public num; - event Deployed(address addr, uint256 salt, address sender); - constructor() public { - } - function deploy(bytes memory code, uint256 salt) public returns(address){ - TestConstract addr; - TestConstract addr1; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - - addr.testSuicideNonexistentTarget(payable(msg.sender)); - addr.set(); - - assembly { - addr1 := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(address(addr), salt, msg.sender); - return address(addr); - } -} - - - -contract TestConstract { - uint public i=1; - constructor () public { - } - - function set() public{ - i=9; - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/super_skip_unimplemented_in_abstract_contract.sol b/framework/src/test/resources/soliditycode/super_skip_unimplemented_in_abstract_contract.sol deleted file mode 100644 index 82dc5d513f7..00000000000 --- a/framework/src/test/resources/soliditycode/super_skip_unimplemented_in_abstract_contract.sol +++ /dev/null @@ -1,22 +0,0 @@ -contract A { - function f() public virtual returns (uint) { - return 42; - } -} - -abstract contract I { - function f() external virtual returns (uint); -} - -contract B is A, I { - function f() override(A, I) public returns (uint) { - // I.f() is before A.f() in the C3 linearized order - // but it has no implementation. - return super.f(); - } -} -// ==== -// compileToEwasm: also -// compileViaYul: also -// ---- -// f() -> 42 diff --git a/framework/src/test/resources/soliditycode/testGetFilterChange.sol b/framework/src/test/resources/soliditycode/testGetFilterChange.sol deleted file mode 100644 index 8a922031c2f..00000000000 --- a/framework/src/test/resources/soliditycode/testGetFilterChange.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma solidity ^0.8.0; -contract SolidityTest { - event Deployed(address sender, uint256 a, uint256 num); - function getResult(uint256 num) public payable returns(uint256) { - uint256 a=0; - for(a=0;a1); - } else if (ErrorType(errorType) == ErrorType.RequirewithMsg_Error) { - require(0>1,"Require Msg."); - } else if (ErrorType(errorType) == ErrorType.Assert_Error) { - assert(1<0); - } else if (ErrorType(errorType) == ErrorType.Tansfer_Error) { - payable(msg.sender).transfer(1); - } else if (ErrorType(errorType) == ErrorType.Send_Error) { - payable(msg.sender).send(1); - } else if (ErrorType(errorType) == ErrorType.Math_Error) { - uint256 a = 1; - uint256 b = 0; - uint256 n = a / b; - } else if (ErrorType(errorType) == ErrorType.ArrayOverFlow_Error) { - arraryUint.pop(); - } - return "success"; - - } - - function callFun(string memory functionStr, string memory argsStr) public{ - address(this).call(abi.encodeWithSignature(functionStr, argsStr)); - } - -} - -contract NewContract { - uint256[] arraryUint ; - - constructor(uint256 errorType) public payable{ - if (ErrorType(errorType) == ErrorType.Revert_Error){ - revert(); - } else if (ErrorType(errorType) == ErrorType.RevertWithMsg_Error){ - revert("Revert Msg."); - } else if (ErrorType(errorType) == ErrorType.Require_Error) { - require(0>1); - } else if (ErrorType(errorType) == ErrorType.RequirewithMsg_Error) { - require(0>1,"Require Msg."); - } else if (ErrorType(errorType) == ErrorType.Assert_Error) { - assert(1<0); - } else if (ErrorType(errorType) == ErrorType.Tansfer_Error) { - payable(msg.sender).transfer(1); - } else if (ErrorType(errorType) == ErrorType.Send_Error) { - payable(msg.sender).send(1); - } else if (ErrorType(errorType) == ErrorType.Math_Error) { - uint256 a = 1; - uint256 b = 0; - uint256 n = a / b; - } else if (ErrorType(errorType) == ErrorType.ArrayOverFlow_Error) { - arraryUint.pop(); - } - } -} - -contract tryTest { - function getData(errorContract inter, string memory functionStr, string memory argsStr) public payable returns(string memory) { - try inter.callFun(functionStr,argsStr) { - return "123"; - } catch Error(string memory errorMsg/* 出错原因 */) { - return errorMsg; - } catch (bytes memory) { - return "3"; - } - } - - function getErrorSwitch(errorContract add, uint256 errorType ) public payable returns(string memory) { - try add.errorSwitch(errorType) returns (string memory Msg) { - return Msg; - } catch Error(string memory errorMsg/* 出错原因 */) { - return errorMsg; - } catch (bytes memory) { - return "NoErrorMsg"; - } - } - - function catchNewErrorSwitch(uint256 errorType) public returns (address nc){ - try new NewContract(errorType) returns (NewContract nc){ - return address(nc); - }catch { - return address(0x00); - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/tvmAssetIssue001.sol b/framework/src/test/resources/soliditycode/tvmAssetIssue001.sol deleted file mode 100644 index 5388ed68473..00000000000 --- a/framework/src/test/resources/soliditycode/tvmAssetIssue001.sol +++ /dev/null @@ -1,25 +0,0 @@ - -contract tvmAssetIssue001 { - constructor() payable public{} - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - return assetissue(name, abbr, totalSupply, precision); - } - - function updateAsset(trcToken tokenId, string memory url, string memory desc) public returns (bool) { - return updateasset(tokenId, bytes(url), bytes(desc)); - } - - function updateOtherAccountAsset(string memory url, string memory desc) public returns (bool) { - trcToken tokenId = trcToken(1000004); - return updateasset(tokenId, bytes(url), bytes(desc)); - } - - function updateAssetOnBytes(trcToken tokenId, bytes memory url, bytes memory desc) public returns (bool) { - return updateasset(tokenId, url, desc); - } - - function transferToken(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/tvmAssetIssue002.sol b/framework/src/test/resources/soliditycode/tvmAssetIssue002.sol deleted file mode 100644 index 87c1206b778..00000000000 --- a/framework/src/test/resources/soliditycode/tvmAssetIssue002.sol +++ /dev/null @@ -1,15 +0,0 @@ - - -contract tvmAssetIssue002 { - constructor() payable public{} - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - assetissue(name, abbr, totalSupply, precision); - return assetissue(name, abbr, totalSupply, precision); - } - - function updateAsset(trcToken tokenId, string memory url1, string memory desc1, string memory url2, string memory desc2) public returns (bool) { - updateasset(tokenId, bytes(url1), bytes(desc1)); - return updateasset(tokenId, bytes(url2), bytes(desc2)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/tvmAssetIssue003.sol b/framework/src/test/resources/soliditycode/tvmAssetIssue003.sol deleted file mode 100644 index f5ce5e0dc3e..00000000000 --- a/framework/src/test/resources/soliditycode/tvmAssetIssue003.sol +++ /dev/null @@ -1,23 +0,0 @@ - - -contract tvmAssetIssue003 { - constructor() payable public{} - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - return assetissue(name, abbr, totalSupply, precision); - } - - function tokenIssueAndTransfer(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision, address addr) public { - address payable newaddress = address(uint160(addr)); - newaddress.transfer(100000000); - assetissue(name, abbr, totalSupply, precision); - newaddress.transfer(100000000); - } - - function updateAssetAndTransfer(trcToken tokenId, string memory url, string memory desc, address addr) public { - address payable newaddress = address(uint160(addr)); - newaddress.transfer(100000000); - updateasset(tokenId, bytes(url), bytes(desc)); - newaddress.transfer(100000000); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/tvmAssetIssue004.sol b/framework/src/test/resources/soliditycode/tvmAssetIssue004.sol deleted file mode 100644 index c8332de8f45..00000000000 --- a/framework/src/test/resources/soliditycode/tvmAssetIssue004.sol +++ /dev/null @@ -1,39 +0,0 @@ - - -contract A { - - constructor() payable public{} - fallback() payable external {} - - function tokenIssueA(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint){ - return assetissue(name, abbr, totalSupply, precision); - } - - function updateAssetA(trcToken tokenId, string memory url, string memory desc) public returns (bool) { - return updateasset(tokenId, bytes(url), bytes(desc)); - } - - function transferToken(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } -} - -contract tvmAssetIssue004 { - - A a; - - constructor() payable public{} - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - return a.tokenIssueA(name, abbr, totalSupply, precision); - } - - function updateAsset(trcToken tokenId, string memory url, string memory desc) public returns (bool) { - return a.updateAssetA(tokenId, url, desc); - } - - function getContractAddress() public payable returns (address) { - a = (new A).value(1024000000)(); - return address(a); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/tvmAssetIssue005.sol b/framework/src/test/resources/soliditycode/tvmAssetIssue005.sol deleted file mode 100644 index 8c36d050ff8..00000000000 --- a/framework/src/test/resources/soliditycode/tvmAssetIssue005.sol +++ /dev/null @@ -1,45 +0,0 @@ - - -contract tvmAssetIssue005 { - constructor() payable public{} - - fallback() external payable { - } - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - return assetissue(name, abbr, totalSupply, precision); - } - - function updateAsset(trcToken tokenId, string memory url, string memory desc) public returns (bool) { - return updateasset(tokenId, bytes(url), bytes(desc)); - } - - function updateAssetOnBytes(trcToken tokenId, bytes memory url, bytes memory desc) public returns (bool) { - return updateasset(tokenId, url, desc); - } - - function transferToken(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - - function SelfdestructTest(address payable target) public { - selfdestruct(target); - } -} - -contract B { - event Deployed(address addr, uint256 salt); - - function deploy(uint256 salt) public returns (address) { - address addr; - bytes memory code = type(tvmAssetIssue005).creationCode; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt); - return addr; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/tvmVote.sol b/framework/src/test/resources/soliditycode/tvmVote.sol deleted file mode 100644 index 214c7c6b10c..00000000000 --- a/framework/src/test/resources/soliditycode/tvmVote.sol +++ /dev/null @@ -1,89 +0,0 @@ -contract TestVote { - - /** - * @dev Contract can accept value while creating. - */ - constructor() public payable {} - - /** - * @dev Freeze `amount` balance of contract to get resource for `receiver` - * which type is `res` (0 for bandwidth, 1 for energy). - */ - function freeze(address payable receiver, uint amount, uint res) external { - receiver.freeze(amount, res); - } - - /** - * @dev Unfreeze specific balance to get corresponding balance.You can use - * `receiver' and 'res' (0 for bandwidth, 1 for energy) parameters to - * unfreeze specific balance. - */ - function unfreeze(address payable receiver, uint res) external { - receiver.unfreeze(res); - } - - /** - * @dev Vote witness in `srList` array and every witness will get correspond - * tron power in `tpList` array. - */ - function voteWitness(address[] calldata srList, uint[] calldata tpList) external { - vote(srList, tpList); - } - - /** - * @dev Withdraw all allowance and reward to contract balance. Return actually withdraw amount. - */ - function withdrawReward() external returns(uint) { - return withdrawreward(); - } - - /** - * @dev query all allowance and reward of contract account. Return contract's all allowance. - */ - function queryRewardBalance() external view returns(uint) { - return rewardBalance(); - } - - /** - * @dev Judge whether the address is a candidate address.If the address is a candidate address, - * return `true`, or return `false`. - */ - function isWitness(address sr) external view returns(bool) { - return isSrCandidate(sr); - } - - /** - * @dev Query vote count of `from` votes for `to`. Return corresponding vote count. - */ - function queryVoteCount(address from, address to) external view returns(uint) { - return voteCount(from, to); - } - - /** - * @dev Query total vote count of `owner`. Return owner's total vote count. - */ - function queryTotalVoteCount(address owner) external view returns(uint) { - return totalVoteCount(owner); - } - - /** - * @dev Query `owner` recevied vote count. Return owner's received vote count. - */ - function queryReceivedVoteCount(address owner) external view returns(uint) { - return receivedVoteCount(owner); - } - - /** - * @dev Query `owner` used vote count. Return owner's used vote count. - */ - function queryUsedVoteCount(address owner) external view returns(uint) { - return usedVoteCount(owner); - } - - /** - * @dev Execute self destruct and transfer all balance and asset of contract to target address. - */ - function killme(address payable target) external { - selfdestruct(target); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/typeName.sol b/framework/src/test/resources/soliditycode/typeName.sol deleted file mode 100644 index 5b44abd1bbb..00000000000 --- a/framework/src/test/resources/soliditycode/typeName.sol +++ /dev/null @@ -1,5 +0,0 @@ -contract TypeName { - function testTypeName() public returns (string memory){ - return type(TypeName).name; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/unStake001.sol b/framework/src/test/resources/soliditycode/unStake001.sol deleted file mode 100644 index 03734fecfa5..00000000000 --- a/framework/src/test/resources/soliditycode/unStake001.sol +++ /dev/null @@ -1,90 +0,0 @@ - - -contract unStakeTest { - B b; - constructor() payable public{} - function deployB() payable public returns (B addrB){ - b = (new B).value(1000000000)(); - return b; - } - - function selfdestructTest(address payable target) public { - selfdestruct(target); - } - - function selfdestructTest2(address sr, uint256 amount, address payable target) public { - stake(sr, amount); - selfdestruct(target); - } - - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - - function stake2(address sr, uint256 amount) public returns (bool result){ - stake(sr, amount); - return stake(sr, amount); - } - - function unStake() public returns (bool result){ - return unstake(); - } - - function unStake2() public returns (bool result){ - unstake(); - return unstake(); - } - - function withdrawReward() public returns (uint256 amount) { - return withdrawreward(); - } - - function rewardBalance(address addr) view public returns (uint256 balance) { - return addr.rewardbalance; - } - - function revertTest1(address sr, uint256 amount, address payable transferAddr) public { - transferAddr.transfer(1000000); - stake(sr, amount); - transferAddr.transfer(2000000); - stake(sr, 1000000000000000); - //stake more than balance to fail - transferAddr.transfer(4000000); - } - - function revertTest2(address payable transferAddr) public { - transferAddr.transfer(1000000); - unstake(); - transferAddr.transfer(2000000); - unstake(); - //unstake twice to fail - transferAddr.transfer(4000000); - } - - function BStake(address sr, uint256 amount) public returns (bool result){ - return b.Stake(sr, amount); - } - - function BUnStake() public returns (bool result){ - return b.UnStake(); - } - - function BSelfdestructTest(address payable target) public { - b.SelfdestructTest(target); - } -} - -contract B { - constructor() payable public{} - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - - function UnStake() public returns (bool result){ - return unstake(); - } - - function SelfdestructTest(address payable target) public { - selfdestruct(target); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/validatemultisign001.sol b/framework/src/test/resources/soliditycode/validatemultisign001.sol deleted file mode 100644 index cc0a742d0c5..00000000000 --- a/framework/src/test/resources/soliditycode/validatemultisign001.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract validatemultisignTest { - function testmulti(address a, uint256 perid, bytes32 hash, bytes[] memory signatures) public returns (bool){ - return validatemultisign(a, perid, hash, signatures); - } - - function testbatch(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public returns (bytes32){ - return batchvalidatesign(hash, signatures, addresses); - } - - function testMultiPrecompileContract(bytes memory data) public returns(bool, bytes memory){ - return address(0xa).delegatecall(data); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/verifyTransferProof001.sol b/framework/src/test/resources/soliditycode/verifyTransferProof001.sol deleted file mode 100644 index 587b4defd10..00000000000 --- a/framework/src/test/resources/soliditycode/verifyTransferProof001.sol +++ /dev/null @@ -1,15 +0,0 @@ -contract verifyTransferProofTest { - - function test1() public returns (bool, bytes memory){ - bytes memory empty = ""; - return address(0x1000002).delegatecall(empty); - } - - function test2(bytes memory data) public returns (bool, bytes memory){ - return address(0x1000002).delegatecall(data); - } - - function test3(bytes32[10][] memory input, bytes32[2][] memory spendAuthoritySignature, bytes32[9][] memory output, bytes32[2] memory bindingSignature, bytes32 signHash, uint64 valueBalance, bytes32[33] memory frontier, uint256 leafCount) public returns (bytes32[] memory){ - return verifyTransferProof(input, spendAuthoritySignature, output, bindingSignature, signHash, valueBalance, frontier, leafCount); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode/virtual001.sol b/framework/src/test/resources/soliditycode/virtual001.sol deleted file mode 100644 index f7967626764..00000000000 --- a/framework/src/test/resources/soliditycode/virtual001.sol +++ /dev/null @@ -1,19 +0,0 @@ -//pragma solidity ^0.6.0; -interface X { - function setValue(uint _x) external; -} -abstract contract Y { - function setBool(bool _y) external virtual ; -} -contract Y2 { - string public z; - function setString(string calldata _z) external virtual { z = "123"; } -} - -contract Z is X,Y,Y2 { - uint public x; - bool public y; - function setValue(uint _x) external override { x = _x; } - function setBool(bool _y) external override { y = _y; } - function setString(string calldata _z) external override { z = _z; } -} diff --git a/framework/src/test/resources/soliditycode/walletTestMutiSign004.sol b/framework/src/test/resources/soliditycode/walletTestMutiSign004.sol deleted file mode 100644 index 7b943aee5c1..00000000000 --- a/framework/src/test/resources/soliditycode/walletTestMutiSign004.sol +++ /dev/null @@ -1,51 +0,0 @@ -contract timeoutTest { - string public iarray1; - // cpu - function oneCpu() public { - require(1==1); - } - - function storage8Char() public { - iarray1 = "12345678"; - } - - function testUseCpu(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - } - return count; - } - - - uint256[] public iarray; - uint public calculatedFibNumber; - mapping(address=>mapping(address=>uint256)) public m; - - function testUseStorage(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - iarray.push(i); - } - return count; - } - - // stack - //uint n = 0; - uint yy = 0; - function test() public { - //n += 1; - yy += 1; - test(); - } - - function setFibonacci(uint n) public returns (uint256){ - calculatedFibNumber = fibonacci(n); - return calculatedFibNumber; - } - - function fibonacci(uint n) internal returns (uint) { - return fibonacci(n - 1) + fibonacci(n - 2); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/AssertException002.sol b/framework/src/test/resources/soliditycode_0.5.15/AssertException002.sol deleted file mode 100644 index 2bff1dcec3e..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/AssertException002.sol +++ /dev/null @@ -1,17 +0,0 @@ -//pragma solidity ^0.4.0; - -contract AssertException{ - function divideIHaveArgsReturn(int x,int y) public returns (int z) { - return x / y; - } - function testAssert() public { - require(2==1); - } -} -contract C { - constructor() public payable { - assert(1==2); - } - function fun() public { - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/AssignToExternal.sol b/framework/src/test/resources/soliditycode_0.5.15/AssignToExternal.sol deleted file mode 100644 index d4f09590a36..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/AssignToExternal.sol +++ /dev/null @@ -1,30 +0,0 @@ -contract AssignToExternal { - // Not allow: - // function f(uint256[] calldata x, uint256[] calldata y) external pure { - // x = y; - // } - - // allow: - - function f(uint256 a) external returns (uint){ - a = a + 1; - return a; - } - - function StringSet(string calldata a) external returns (string memory){ - return a; - } - - function ByteSet(bytes32 a) external returns (bytes32){ - return a; - } - - function UintArraySet(uint256[2] calldata a) external returns (uint256[2] memory){ - return a; - } - - function AddSet(address a) external returns (address){ - return a; - } - -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/BlockHash.sol b/framework/src/test/resources/soliditycode_0.5.15/BlockHash.sol deleted file mode 100644 index 6603da65e44..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/BlockHash.sol +++ /dev/null @@ -1,38 +0,0 @@ -contract TestBlockHash { - - function testOR1(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = blockhash(block.number - 1) | bytes32(value); - return (b1, c, blockhash(block.number - 1)); - } - - function testOR2(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = bytes32(value) | blockhash(block.number - 1); - return (b1, c, blockhash(block.number - 1)); - } - - function testAND1(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = blockhash(block.number - 1) & bytes32(value); - return (b1, c, blockhash(block.number - 1)); - } - - function testAND2(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = bytes32(value) & blockhash(block.number - 1); - return (b1, c, blockhash(block.number - 1)); - } - - function testXOR1(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = blockhash(block.number - 1) ^ bytes32(value); - return (b1, c, blockhash(block.number - 1)); - } - - function testXOR2(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = bytes32(value) ^ blockhash(block.number - 1); - return (b1, c, blockhash(block.number - 1)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/ClearAbi001.sol b/framework/src/test/resources/soliditycode_0.5.15/ClearAbi001.sol deleted file mode 100644 index fccc59e14be..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/ClearAbi001.sol +++ /dev/null @@ -1,7 +0,0 @@ -//pragma solidity ^0.4.0; - -contract testConstantContract{ -function testPayable() public view returns (int z) { -return 1; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/ClearAbi005.sol b/framework/src/test/resources/soliditycode_0.5.15/ClearAbi005.sol deleted file mode 100644 index a3115398386..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/ClearAbi005.sol +++ /dev/null @@ -1,26 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract TestConstract { - uint public i=0; - constructor () public { - } - function plusOne() public returns(uint){ - i++; - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/ConstructorDefaults.sol b/framework/src/test/resources/soliditycode_0.5.15/ConstructorDefaults.sol deleted file mode 100644 index 4b6186ccb95..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/ConstructorDefaults.sol +++ /dev/null @@ -1,9 +0,0 @@ -contract testIsContract{ - bool result; - constructor (bool a) public { - result = a; - } -function test( address a) public returns (bool) { -return result; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/Create2Test023.sol b/framework/src/test/resources/soliditycode_0.5.15/Create2Test023.sol deleted file mode 100644 index 4c3f8af9f2b..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/Create2Test023.sol +++ /dev/null @@ -1,31 +0,0 @@ -contract factory { - constructor() payable public { - } - - function deploy(bytes memory code, uint256 salt) public returns(address){ - Caller addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - return address(addr); - } - - function testCreate() payable public returns (address){ - Caller add = (new Caller).value(0)(); - return address(add); - } - - function kill( ) payable public{ - selfdestruct(msg.sender); - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/Create2Test024.sol b/framework/src/test/resources/soliditycode_0.5.15/Create2Test024.sol deleted file mode 100644 index f5a9d032cff..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/Create2Test024.sol +++ /dev/null @@ -1,56 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - TestConstract addr; - TestConstract addr1; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - - addr.testSuicideNonexistentTarget(msg.sender); - addr.set(); - emit Deployed(address(addr), salt, msg.sender); - return address(addr); - } - - function deploy2(bytes memory code, uint256 salt) public returns(address){ - TestConstract addr; - TestConstract addr1; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - - //addr.testSuicideNonexistentTarget(msg.sender); - //addr.set(); - - assembly { - addr1 := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(address(addr), salt, msg.sender); - return address(addr); - } -} - - - -contract TestConstract { - uint public i=1; - constructor () public { - } - - function set() public{ - i=9; - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/Create2Test025.sol b/framework/src/test/resources/soliditycode_0.5.15/Create2Test025.sol deleted file mode 100644 index 895dc43e56f..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/Create2Test025.sol +++ /dev/null @@ -1,34 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - constructor() public { - } - - function create2(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } - - function get(bytes1 prefix, bytes calldata code, uint256 salt) external view returns(address) { - //bytes32 hash = keccak256(abi.encodePacked(bytes1(0x41),address(this), salt, keccak256(code))); - bytes32 hash = keccak256(abi.encodePacked(prefix,address(this), salt, keccak256(code))); - address addr = address(uint160(uint256(hash))); - return addr; - } -} - -contract TestContract{ - uint256 public num; - constructor(uint256 j) public{ - num = j; - } - function getNum() public returns (uint256){ - return num; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/ExtCodeHashTest010.sol b/framework/src/test/resources/soliditycode_0.5.15/ExtCodeHashTest010.sol deleted file mode 100644 index bfa8a7fa0d8..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/ExtCodeHashTest010.sol +++ /dev/null @@ -1,46 +0,0 @@ -contract Counter { - uint count = 0; - address payable owner; - event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); - constructor() public{ - owner = msg.sender; - } - function getCodeHashSuicide(address addr) public returns (bytes32 _hashBefore){ - assembly{ - _hashBefore := extcodehash(addr) - } - selfdestruct(owner); - return _hashBefore; - } - - function getCodeHashRevert() public returns (bytes32 _hashBefore, bytes32 _hashAfter) { - address addr = address(this); - assembly { - _hashBefore := extcodehash(addr) - } - if (owner == msg.sender) { - selfdestruct(owner); - } - assembly { - _hashAfter := extcodehash(addr) - } - revert(); - emit LogResult(_hashBefore, _hashAfter); - } - - function getCodeHashCreate() public returns (bytes32 _hashBefore){ - TestContract A = (new TestContract).value(0)(); - address addr = address(A); - assembly{ - _hashBefore := extcodehash(addr) - } - revert(); - return _hashBefore; - } -} - -contract TestContract{ - uint256 count = 1; - constructor() public payable{ - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/ParentTypeBug.sol b/framework/src/test/resources/soliditycode_0.5.15/ParentTypeBug.sol deleted file mode 100644 index 897c843ae24..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/ParentTypeBug.sol +++ /dev/null @@ -1,13 +0,0 @@ -contract Parent { - uint256 public m_aMember; - address public m_bMember; -} -contract Child is Parent { - function foo() public view returns (uint256) { return Parent.m_aMember; } - function bar() public view returns (address) { return Parent.m_bMember; } - - // complie failed - // function foo() public pure returns (uint256) { return Parent.m_aMember; } - // function bar() public pure returns (address) { return Parent.m_bMember; } - -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/SafeMath.sol b/framework/src/test/resources/soliditycode_0.5.15/SafeMath.sol deleted file mode 100644 index b154b8b81b5..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/SafeMath.sol +++ /dev/null @@ -1,149 +0,0 @@ -pragma solidity ^0.5.8; - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/ShiftCommand001.sol b/framework/src/test/resources/soliditycode_0.5.15/ShiftCommand001.sol deleted file mode 100644 index 574ee2b571b..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/ShiftCommand001.sol +++ /dev/null @@ -1,18 +0,0 @@ -contract TestBitwiseShift { - - function shlTest(uint256 num, uint256 input) public returns (bytes32 out) { - assembly { - out := shl(num, input) - } - } - function shrTest(uint256 num, uint256 input) public returns (bytes32 out) { - assembly { - out := shr(num, input) - } - } - function sarTest(uint256 num, uint256 input) public returns (bytes32 out) { - assembly { - out := sar(num, input) - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/SolidityMappingFix.sol b/framework/src/test/resources/soliditycode_0.5.15/SolidityMappingFix.sol deleted file mode 100644 index 67692d3b4ae..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/SolidityMappingFix.sol +++ /dev/null @@ -1,9 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Tests { - mapping(address => uint) public balances; - function update(uint256 amount) public returns (address addr) - { - balances[msg.sender] = amount; - return msg.sender; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/TestMappings_array_pop.sol b/framework/src/test/resources/soliditycode_0.5.15/TestMappings_array_pop.sol deleted file mode 100644 index 3ceac916049..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TestMappings_array_pop.sol +++ /dev/null @@ -1,19 +0,0 @@ -contract C { - mapping (uint256 => uint256)[] a; - - function n1(uint256 key, uint256 value) public { - a.length++; - a[a.length - 1][key] = value; - } - - - - function map(uint256 key) public view returns (uint) { - return a[a.length - 1][key]; - } - - function p() public { - a.pop(); - } -} - diff --git a/framework/src/test/resources/soliditycode_0.5.15/TransferFailed001.sol b/framework/src/test/resources/soliditycode_0.5.15/TransferFailed001.sol deleted file mode 100644 index dba043edcb3..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TransferFailed001.sol +++ /dev/null @@ -1,147 +0,0 @@ -contract EnergyOfTransferFailedTest { - constructor() payable public { - - } - - function testTransferTokenCompiledLongMax() payable public{ - address(0x1).transferToken(1,9223372036855775827); - } - - function testTransferTokenCompiled() payable public{ - address(0x1).transferToken(1,1); - } - - function testTransferTokenCompiledLongMin() payable public{ - //address(0x1).transferToken(1,-9223372036855775828); - } - - function testTransferTokenCompiledLongMin1() payable public returns(uint256){ - return address(0x2).tokenBalance(trcToken(-9223372036855775828)); - } - - function testTransferTokenCompiled1() payable public returns(uint256){ - return address(0x1).tokenBalance(trcToken(1)); - } - - function testTransferTokenCompiledLongMax1() payable public returns(uint256){ - return address(0x2).tokenBalance(trcToken(9223372036855775827)); - } - - function testTransferTokenCompiledTokenId(uint256 tokenid) payable public returns(uint256){ - return address(0x1).tokenBalance(trcToken(tokenid)); - } - - function testTransferTokenTest(address addr ,uint256 tokenid) payable public returns(uint256){ - return addr.tokenBalance(trcToken(tokenid)); - } - - // InsufficientBalance - function testTransferTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.transfer(i); - } - - function testSendTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.send(i); - } - - function testTransferTokenInsufficientBalance(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - - function testCallTrxInsufficientBalance(uint256 i,address payable caller) public { - caller.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testCreateTrxInsufficientBalance(uint256 i) payable public { - (new Caller).value(i)(); - } - - // NonexistentTarget - - function testSendTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - nonexistentTarget.send(i); - } - - function testSendTrxRevert(uint256 i,address payable nonexistentTarget) payable public { - nonexistentTarget.send(i); - revert(); - } - - function testTransferTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - nonexistentTarget.transfer(i); - } - - function testTransferTrxrevert(uint256 i,address payable nonexistentTarget) payable public{ - nonexistentTarget.transfer(i); - revert(); - } - - function testTransferTokenNonexistentTarget(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - nonexistentTarget.transferToken(i, tokenId); - } - - function testTransferTokenRevert(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - nonexistentTarget.transferToken(i, tokenId); - revert(); - } - - function testCallTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - nonexistentTarget.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } - - function testSuicideRevert(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - revert(); - } - - // target is self - function testTransferTrxSelf(uint256 i) payable public{ - address payable self = address(uint160(address(this))); - self.transfer(i); - } - - function testSendTrxSelf(uint256 i) payable public{ - address payable self = address(uint160(address(this))); - self.send(i); - } - - function testTransferTokenSelf(uint256 i,trcToken tokenId) payable public{ - address payable self = address(uint160(address(this))); - self.transferToken(i, tokenId); - } - - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(10, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } - function deploy2(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(300, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/TransferFailed005.sol b/framework/src/test/resources/soliditycode_0.5.15/TransferFailed005.sol deleted file mode 100644 index aa39aafa152..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TransferFailed005.sol +++ /dev/null @@ -1,90 +0,0 @@ -contract EnergyOfTransferFailedTest { - constructor() payable public { - - } - // InsufficientBalance - function testTransferTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.transfer(i); - } - - function testSendTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.send(i); - } - - function testTransferTokenInsufficientBalance(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - - function testCallTrxInsufficientBalance(uint256 i,address payable caller) public returns (bool,bytes memory){ - return caller.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testCreateTrxInsufficientBalance(uint256 i) payable public { - (new Caller).value(i)(); - } - - // NonexistentTarget - - function testSendTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.send(i); - } - - function testTransferTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.transfer(i); - } - - function testTransferTokenNonexistentTarget(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - require(address(this).balance >= i); - nonexistentTarget.transferToken(i, tokenId); - } - - function testCallTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } - - // target is self - function testTransferTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.transfer(i); - } - - function testSendTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.send(i); - } - - function testTransferTokenSelf(uint256 i,trcToken tokenId) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.transferToken(i, tokenId); - } - - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(10, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256 ){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/TransferFailed006.sol b/framework/src/test/resources/soliditycode_0.5.15/TransferFailed006.sol deleted file mode 100644 index aa39aafa152..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TransferFailed006.sol +++ /dev/null @@ -1,90 +0,0 @@ -contract EnergyOfTransferFailedTest { - constructor() payable public { - - } - // InsufficientBalance - function testTransferTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.transfer(i); - } - - function testSendTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.send(i); - } - - function testTransferTokenInsufficientBalance(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - - function testCallTrxInsufficientBalance(uint256 i,address payable caller) public returns (bool,bytes memory){ - return caller.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testCreateTrxInsufficientBalance(uint256 i) payable public { - (new Caller).value(i)(); - } - - // NonexistentTarget - - function testSendTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.send(i); - } - - function testTransferTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.transfer(i); - } - - function testTransferTokenNonexistentTarget(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - require(address(this).balance >= i); - nonexistentTarget.transferToken(i, tokenId); - } - - function testCallTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } - - // target is self - function testTransferTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.transfer(i); - } - - function testSendTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.send(i); - } - - function testTransferTokenSelf(uint256 i,trcToken tokenId) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.transferToken(i, tokenId); - } - - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(10, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256 ){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/TransferFailed007.sol b/framework/src/test/resources/soliditycode_0.5.15/TransferFailed007.sol deleted file mode 100644 index aa39aafa152..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TransferFailed007.sol +++ /dev/null @@ -1,90 +0,0 @@ -contract EnergyOfTransferFailedTest { - constructor() payable public { - - } - // InsufficientBalance - function testTransferTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.transfer(i); - } - - function testSendTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.send(i); - } - - function testTransferTokenInsufficientBalance(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - - function testCallTrxInsufficientBalance(uint256 i,address payable caller) public returns (bool,bytes memory){ - return caller.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testCreateTrxInsufficientBalance(uint256 i) payable public { - (new Caller).value(i)(); - } - - // NonexistentTarget - - function testSendTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.send(i); - } - - function testTransferTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.transfer(i); - } - - function testTransferTokenNonexistentTarget(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - require(address(this).balance >= i); - nonexistentTarget.transferToken(i, tokenId); - } - - function testCallTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } - - // target is self - function testTransferTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.transfer(i); - } - - function testSendTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.send(i); - } - - function testTransferTokenSelf(uint256 i,trcToken tokenId) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.transferToken(i, tokenId); - } - - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(10, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256 ){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/TriggerConstant001.sol b/framework/src/test/resources/soliditycode_0.5.15/TriggerConstant001.sol deleted file mode 100644 index 515b9e07724..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TriggerConstant001.sol +++ /dev/null @@ -1,28 +0,0 @@ -//pragma solidity ^0.4.0; - -contract testConstantContract{ - uint256 public i; - function testPayable() public payable returns (uint256 z) { - i=1; - z=i; - return z; - } - function testNoPayable() public returns (uint256 z) { - i=1; - z=i; - return z; - } - function testView() public view returns (uint256 z) { - uint256 i=1; - return i; - } - function testPure() public pure returns (uint256 z) { - uint256 i=1; - return i; - } - function testView2() public view returns (uint256 z) { - uint256 i=1; - revert(); - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/TriggerConstant002.sol b/framework/src/test/resources/soliditycode_0.5.15/TriggerConstant002.sol deleted file mode 100644 index 44332e58c51..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TriggerConstant002.sol +++ /dev/null @@ -1,10 +0,0 @@ -//pragma solidity ^0.4.0; - -contract testConstantContract{ - uint256 public i; - function testNoPayable() public returns (uint256 z) { - i=1; - z=i; - return z; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/TriggerConstant003.sol b/framework/src/test/resources/soliditycode_0.5.15/TriggerConstant003.sol deleted file mode 100644 index 03e29fb76b6..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TriggerConstant003.sol +++ /dev/null @@ -1,18 +0,0 @@ -//pragma solidity ^0.4.0; - -contract testConstantContract{ - function testView() public view returns (uint256 z) { - uint256 i=1; - return i; - } - - function testPure() public pure returns (uint256 z) { - uint256 i=1; - return i; - } - - function testPayable() public payable returns (uint256 z) { - uint256 i=1; - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/TriggerConstant004.sol b/framework/src/test/resources/soliditycode_0.5.15/TriggerConstant004.sol deleted file mode 100644 index fce77178ca7..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TriggerConstant004.sol +++ /dev/null @@ -1,8 +0,0 @@ -//pragma solidity ^0.4.0; - -contract testConstantContract{ -function testPure() public pure returns (uint256 z) { -uint256 i=1; -return i; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/TriggerConstant015.sol b/framework/src/test/resources/soliditycode_0.5.15/TriggerConstant015.sol deleted file mode 100644 index d926c43c824..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TriggerConstant015.sol +++ /dev/null @@ -1,24 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract TestConstract { - constructor () public { - } - function plusOne() public returns(uint){ - return 1; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/TriggerConstant024.sol b/framework/src/test/resources/soliditycode_0.5.15/TriggerConstant024.sol deleted file mode 100644 index 287b0fc9782..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TriggerConstant024.sol +++ /dev/null @@ -1,9 +0,0 @@ -//pragma solidity ^0.4.0; - -contract testConstantContract{ -function testView() public view returns (uint256 z) { -uint256 i=1; -revert(); -return i; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/TvmIsContract.sol b/framework/src/test/resources/soliditycode_0.5.15/TvmIsContract.sol deleted file mode 100644 index 4266b9e92ca..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TvmIsContract.sol +++ /dev/null @@ -1,15 +0,0 @@ -contract testIsContract{ -bool public isContrct; -constructor () public { - isContrct = address(this).isContract; -} -function testIsContractCommand(address a) public returns (bool) { -return (a.isContract); -} -function selfdestructContract(address payable a) public { - selfdestruct(a); -} -function testConstructor() public returns(bool){ - return isContrct; -} -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/TvmIsContract001.sol b/framework/src/test/resources/soliditycode_0.5.15/TvmIsContract001.sol deleted file mode 100644 index 77aae930b59..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TvmIsContract001.sol +++ /dev/null @@ -1,24 +0,0 @@ -contract testIsContract{ -bool public isContrct; -constructor () public { - isContrct = address(this).isContract; -} -function testIsContractCommand(address a) public returns (bool) { -return (a.isContract); -} - -function testIsContractView(address a) view public returns (bool) { -return (a.isContract); -} - -function selfdestructContract(address payable a) public { - selfdestruct(a); -} -function testConstructor() public returns(bool){ - return isContrct; -} - -function testConstructorView() public view returns(bool){ - return isContrct; -} -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/TvmIsContract002.sol b/framework/src/test/resources/soliditycode_0.5.15/TvmIsContract002.sol deleted file mode 100644 index 2fe474fd98c..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TvmIsContract002.sol +++ /dev/null @@ -1,5 +0,0 @@ -contract testIsContract{ -function testIsContractCommand(address a) public returns (bool) { -return (a.isContract); -} -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand043.sol b/framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand043.sol deleted file mode 100644 index 04d9f7dde28..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand043.sol +++ /dev/null @@ -1,18 +0,0 @@ -contract TestBitwiseShift { - - function shlTest(int256 num, int256 input) public returns (bytes32 out) { - assembly { - out := shl(num, input) - } - } - function shrTest(int256 num, int256 input) public returns (bytes32 out) { - assembly { - out := shr(num, input) - } - } - function sarTest(int256 num, int256 input) public returns (bytes32 out) { - assembly { - out := sar(num, input) - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand103.sol b/framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand103.sol deleted file mode 100644 index 7ad130c87c6..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand103.sol +++ /dev/null @@ -1,8 +0,0 @@ -//pragma solidity ^0.4.0; - -contract testConstantContract{ -function testView() public constant returns (uint256 z) { -uint256 i=1; -return i; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand107.sol b/framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand107.sol deleted file mode 100644 index 4dcd33ad7b0..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand107.sol +++ /dev/null @@ -1,9 +0,0 @@ -//pragma solidity ^0.4.0; - - contract testConstantContract{ - int256 public i; - function testPayable() public returns (int z) { - z=1+1; - return z; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand108.sol b/framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand108.sol deleted file mode 100644 index b44d5c82731..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand108.sol +++ /dev/null @@ -1,7 +0,0 @@ -//pragma solidity ^0.4.0; - - contract testConstantContract{ - function test() pure public returns (int z) { - return 1; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand109.sol b/framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand109.sol deleted file mode 100644 index 864f01f7fb4..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TvmNewCommand109.sol +++ /dev/null @@ -1,7 +0,0 @@ -//pragma solidity ^0.4.0; - - contract testConstantContract{ - function test() view public returns (int z) { - return 1; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/TvmOldCommand001.sol b/framework/src/test/resources/soliditycode_0.5.15/TvmOldCommand001.sol deleted file mode 100644 index 9f3cf079ea1..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/TvmOldCommand001.sol +++ /dev/null @@ -1,11 +0,0 @@ -//pragma solidity ^0.4.0; - -contract binaryRightContract{ - function binaryMoveR(int i)public returns (int z) { - return z = 5 >> i; - } - function binaryLiftR(int i)public returns (int z) { - return z = 5 << i; - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/VerifyBurnProof001.sol b/framework/src/test/resources/soliditycode_0.5.15/VerifyBurnProof001.sol deleted file mode 100644 index 4173e84de23..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/VerifyBurnProof001.sol +++ /dev/null @@ -1,20 +0,0 @@ - -contract VerifyBurnProof001Test { - // verifyBurnProof(bytes32[10],bytes32[2],uint64,bytes32[2],bytes32) - // size = 512 - // - - function VerifyBurnProofSize001(bytes32[10] memory output, bytes32[2] memory spendAuthoritySignature, uint64 value, bytes32[2] memory bindingSignature,bytes32 signHash) public returns (bool){ - return verifyBurnProof(output, spendAuthoritySignature, value, bindingSignature, signHash); - } - - function VerifyBurnProofSize002(bytes memory data) public returns (bool, bytes memory){ - // bytes memory empty = ""; - return address(0x1000003).delegatecall(data); - } - - function VerifyBurnProofSize003() public returns (bool, bytes memory){ - bytes memory empty = ""; - return address(0x1000003).delegatecall(empty); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/VerifyMintProof001.sol b/framework/src/test/resources/soliditycode_0.5.15/VerifyMintProof001.sol deleted file mode 100644 index cb0812c2ef5..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/VerifyMintProof001.sol +++ /dev/null @@ -1,33 +0,0 @@ - -contract VerifyMintProof001Test { - // verifyMintProof(bytes32[9],bytes32[2],uint64,bytes32,bytes32[33],uint256) - - function VerifyMintProofSize001(bytes32[9] memory output, bytes32[2] memory bindingSignature, uint64 value, bytes32 signHash, bytes32[33] memory frontier,uint256 leafCount) public returns (bytes32[] memory){ - return verifyMintProof(output, bindingSignature, value, signHash, frontier, leafCount); - } - - function VerifyMintProofSize002(bytes memory data) public returns (bool, bytes memory){ -// address verifyMint = address (0x1000001); -// -// assembly { -// let succeeded := delegatecall(sub(gas, 5000), verifyMint, add(data, 0x20), mload(data), 0, 0) -// let size := returndatasize -// let response := mload(0x40) -// mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f)))) -// mstore(response, size) -// returndatacopy(add(response, 0x20), 0, size) -// switch iszero(succeeded) -// case 1 { -// // throw if delegatecall failed -// revert(add(response, 0x20), size) -// } -// } - - return address(0x1000001).delegatecall(data); - } - - function VerifyMintProofSize003() public returns (bool, bytes memory){ - bytes memory empty = ""; - return address(0x1000001).call(empty); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/abiencode.sol b/framework/src/test/resources/soliditycode_0.5.15/abiencode.sol deleted file mode 100644 index 38fad3454d6..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/abiencode.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma experimental ABIEncoderV2; - -// tests encoding from storage arrays - -contract AbiEncode { - int256[2][] tmp_h; - function h(int256[2][] calldata s) external returns (bytes memory) { - tmp_h = s; - return abi.encode(tmp_h); - } - int256[2][2] tmp_i; - function i(int256[2][2] calldata s) external returns (bytes memory) { - tmp_i = s; - return abi.encode(tmp_i); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/addMsg001Nonpayable.sol b/framework/src/test/resources/soliditycode_0.5.15/addMsg001Nonpayable.sol deleted file mode 100644 index d1294f2336a..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/addMsg001Nonpayable.sol +++ /dev/null @@ -1,20 +0,0 @@ -//pragma solidity ^0.4.24; - -contract IllegalDecorate { - -event log(uint256); -constructor() payable public{} - -function() payable external{} - -function transferTokenWithOutPayable(address payable toAddress, uint256 tokenValue)public { -// function transferTokenWithValue(address toAddress, uint256 tokenValue) payable public { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); - -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/addMsg002View.sol b/framework/src/test/resources/soliditycode_0.5.15/addMsg002View.sol deleted file mode 100644 index 423bb68e3ed..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/addMsg002View.sol +++ /dev/null @@ -1,20 +0,0 @@ -//pragma solidity ^0.4.24; - -contract IllegalDecorate { - -constructor() payable public{} - -function() payable external{} - -event log(uint256); - -function transferTokenWithView(address payable toAddress, uint256 tokenValue) public view{ -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} - diff --git a/framework/src/test/resources/soliditycode_0.5.15/addMsg003Constant.sol b/framework/src/test/resources/soliditycode_0.5.15/addMsg003Constant.sol deleted file mode 100644 index 0f0ab7553e0..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/addMsg003Constant.sol +++ /dev/null @@ -1,19 +0,0 @@ -//pragma solidity ^0.4.24; - -contract IllegalDecorate { - -constructor() payable public{} - -function() payable external{} - -event log(uint256); - -function transferTokenWithConstant(address payable toAddress, uint256 tokenValue) public constant{ -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/addMsg004Pure.sol b/framework/src/test/resources/soliditycode_0.5.15/addMsg004Pure.sol deleted file mode 100644 index b5d3a4e4aee..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/addMsg004Pure.sol +++ /dev/null @@ -1,19 +0,0 @@ -//pragma solidity ^0.4.24; - -contract IllegalDecorate { - -constructor() payable public{} - -function() payable external{} - -event log(uint256); - -function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public pure{ -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/addTransferToken001Nonpayable.sol b/framework/src/test/resources/soliditycode_0.5.15/addTransferToken001Nonpayable.sol deleted file mode 100644 index c8d0dcc7560..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/addTransferToken001Nonpayable.sol +++ /dev/null @@ -1,13 +0,0 @@ -//pragma solidity ^0.4.24; - - contract IllegalDecorate { - - constructor() payable public{} - - function() payable external{} - - function transferTokenWithOutPayable(address payable toAddress,trcToken id, uint256 tokenValue)public { - - toAddress.transferToken(tokenValue, id); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/addTransferToken001payable.sol b/framework/src/test/resources/soliditycode_0.5.15/addTransferToken001payable.sol deleted file mode 100644 index 803d66ad75e..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/addTransferToken001payable.sol +++ /dev/null @@ -1,13 +0,0 @@ -//pragma solidity ^0.4.24; - - contract IllegalDecorate { - - constructor() payable public{} - - function() payable external{} - - function transferTokenWithOutPayable(address payable toAddress,trcToken id, uint256 tokenValue) public payable{ - - toAddress.transferToken(tokenValue, id); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/addTransferToken002View.sol b/framework/src/test/resources/soliditycode_0.5.15/addTransferToken002View.sol deleted file mode 100644 index 109f46386ce..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/addTransferToken002View.sol +++ /dev/null @@ -1,15 +0,0 @@ -//pragma solidity ^0.4.24; - -contract IllegalDecorate { - - constructor() payable public{} - - function() payable external{} - - function transferTokenWithView(address payable toAddress,trcToken id, uint256 tokenValue) public view{ - - toAddress.transferToken(tokenValue, id); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/addTransferToken003Constant.sol b/framework/src/test/resources/soliditycode_0.5.15/addTransferToken003Constant.sol deleted file mode 100644 index fb1a2cbbbb4..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/addTransferToken003Constant.sol +++ /dev/null @@ -1,15 +0,0 @@ -//pragma solidity ^0.4.24; - -contract IllegalDecorate { - - constructor() payable public{} - - function() payable external{} - - function transferTokenWithConstant(address payable toAddress, uint256 tokenValue) public constant{ - - toAddress.transferToken(tokenValue, 0x6e6d62); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/addTransferToken004Pure.sol b/framework/src/test/resources/soliditycode_0.5.15/addTransferToken004Pure.sol deleted file mode 100644 index 7ea2bf0a40b..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/addTransferToken004Pure.sol +++ /dev/null @@ -1,15 +0,0 @@ -//pragma solidity ^0.4.24; - -contract IllegalDecorate { - - constructor() payable public{} - - function() payable external{} - - function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public pure{ - - toAddress.transferToken(tokenValue, 0x6e6d62); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/addTrcToken001Assemble.sol b/framework/src/test/resources/soliditycode_0.5.15/addTrcToken001Assemble.sol deleted file mode 100644 index a93d9046a3f..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/addTrcToken001Assemble.sol +++ /dev/null @@ -1,62 +0,0 @@ -//pragma solidity ^0.4.24; - -contract InAssemble { - -mapping(trcToken => uint256) tokenCnt; -mapping(uint256 => mapping(trcToken => trcToken)) cntTokenToken; -constructor () payable public {} -function getBalance (address addr) view public returns(uint256 r) { -assembly{ -r := balance(addr) -} -} - -function getTokenBalanceConstant (address addr, trcToken tokenId) view public returns(uint256 r) { -assembly{ -r := tokenbalance(tokenId, addr) -} -} - -function getTokenBalance (address addr, trcToken tokenId) public returns(uint256 r) { -assembly{ -r := tokenbalance(tokenId, addr) -} -} - -function transferTokenInAssembly(address addr, trcToken tokenId, uint256 tokenValue) public payable { -bytes4 sig = bytes4(keccak256("()")); // function signature - -assembly { -let x := mload(0x40) // get empty storage location -mstore(x,sig) // 4 bytes - place signature in empty storage - -let ret := calltoken(gas, addr, tokenValue, tokenId, -x, // input -0x04, // input size = 4 bytes -x, // output stored at input location, save space -0x0 // output size = 0 bytes -) - -// let ret := calltoken(gas, addr, tokenValue, -// x, // input -// 0x04, // input size = 4 bytes -// x, // output stored at input location, save space -// 0x0 // output size = 0 bytes -// ) // ERROR - - -mstore(0x40, add(x,0x20)) // update free memory pointer -} - -} - -function trcTokenInMap(trcToken tokenId, uint256 tokenValue) public returns(uint256 r) { -tokenCnt[tokenId] += tokenValue; -r = tokenCnt[tokenId]; -} - -function cntTokenTokenInMap(trcToken tokenId1, trcToken tokenId2, uint256 tokenValue) public returns(trcToken r) { -cntTokenToken[tokenValue][tokenId1] = tokenId2; -r = cntTokenToken[tokenValue][tokenId1]; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/addTrcToken002Cat.sol b/framework/src/test/resources/soliditycode_0.5.15/addTrcToken002Cat.sol deleted file mode 100644 index 6d9c169330d..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/addTrcToken002Cat.sol +++ /dev/null @@ -1,2051 +0,0 @@ -//pragma solidity ^0.4.11; - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() public { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address payable public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address payable _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() public onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - emit Transfer(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(now), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - uint256 newKittenId = kitties.push(_kitty) - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - emit Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(address(0), _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -contract ERC721 { - // Required methods - function totalSupply() public view returns (uint256 total); - function balanceOf(address _owner) public view returns (uint256 balance); - function ownerOf(uint256 _tokenId) external view returns (address owner); - function approve(address _to, uint256 _tokenId) external; - function transfer(address _to, uint256 _tokenId) external; - function transferFrom(address _from, address _to, uint256 _tokenId) external; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) external view returns (bool); -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is ERC721, KittyBase { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public view returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - emit Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() public view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - external - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { - string memory outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { - require( address(erc721Metadata) != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2 sun; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - msg.sender.transfer(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, address(saleAuction)); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, address(siringAuction)); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10 sun; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, address(saleAuction)); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - address(uint160(address(this))) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - constructor() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(-1), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - emit ContractUpgrade(_v2Address); - } - - /// @notice No tipping! - /// @dev Reject all Ether from being sent here, unless it's from one of the - /// two auction contracts. (Hopefully, we can prevent user accidents.) - function() external payable { - require( - msg.sender == address(saleAuction) || - msg.sender == address(siringAuction) - ); - } - - /// @notice Returns all the relevant information about a specific kitty. - /// @param _id The ID of the kitty of interest. - function getKitty(uint256 _id) - external - view - returns ( - bool isGestating, - bool isReady, - uint256 cooldownIndex, - uint256 nextActionAt, - uint256 siringWithId, - uint256 birthTime, - uint256 matronId, - uint256 sireId, - uint256 generation, - uint256 genes - ) { - Kitty storage kit = kitties[_id]; - - // if this variable is 0 then it's not gestating - isGestating = (kit.siringWithId != 0); - isReady = (kit.cooldownEndBlock <= block.number); - cooldownIndex = uint256(kit.cooldownIndex); - nextActionAt = uint256(kit.cooldownEndBlock); - siringWithId = uint256(kit.siringWithId); - birthTime = uint256(kit.birthTime); - matronId = uint256(kit.matronId); - sireId = uint256(kit.sireId); - generation = uint256(kit.generation); - genes = kit.genes; - } - - /// @dev Override unpause so it requires all external contract addresses - /// to be set before contract can be unpaused. Also, we can't have - /// newContractAddress set either, because then the contract was upgraded. - /// @notice This is public rather than external so we can call super.unpause - /// without using an expensive CALL. - - function unpause(address payable toAddress, uint256 tokenValue, trcToken tokenId) public onlyCEO whenPaused returns (uint256 r) { - require(address(saleAuction) != address(0)); - require(address(siringAuction) != address(0)); - require(address(geneScience) != address(0)); - require(address(newContractAddress) == address(0)); - toAddress.transferToken(tokenValue, tokenId); - r = address(this).tokenBalance(tokenId); - // Actually unpause the contract. - super.unpause(); - } - - // @dev Allows the CFO to capture the balance available to the contract. - function withdrawBalance() external onlyCFO { - uint256 balance = address(this).balance; - // Subtract all the currently pregnant kittens we have, plus 1 of margin. - uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - - if (balance > subtractFees) { - cfoAddress.transfer(balance - subtractFees); - } - } -} - - - - - - - - - - - - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - - function isGeneScience() public pure returns (bool){ - return true; - } - - /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor - /// @param genes1 genes of mom - /// @param genes2 genes of sire - /// @return the genes that are supposed to be passed down the child - function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - - return (genes1+genes2+targetBlock)/2; - - -} -} - - - - - - - - - - - - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { - /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. - function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { - if (_tokenId == 1) { - buffer[0] = "Hello World! :D"; - count = 15; - } else if (_tokenId == 2) { - buffer[0] = "I would definitely choose a medi"; - buffer[1] = "um length string."; - count = 49; - } else if (_tokenId == 3) { - buffer[0] = "Lorem ipsum dolor sit amet, mi e"; - buffer[1] = "st accumsan dapibus augue lorem,"; - buffer[2] = " tristique vestibulum id, libero"; - buffer[3] = " suscipit varius sapien aliquam."; - count = 128; - } - } -} - - - - - - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - - // Represents an auction on an NFT - struct Auction { - // Current owner of NFT - address payable seller; - // Price (in wei) at beginning of auction - uint128 startingPrice; - // Price (in wei) at end of auction - uint128 endingPrice; - // Duration (in seconds) of auction - uint64 duration; - // Time when auction started - // NOTE: 0 if this auction has been concluded - uint64 startedAt; - } - - // Reference to contract tracking NFT ownership - ERC721 public nonFungibleContract; - - // Cut owner takes on each auction, measured in basis points (1/100 of a percent). - // Values 0-10,000 map to 0%-100% - uint256 public ownerCut; - - // Map from token ID to their corresponding auction. - mapping (uint256 => Auction) tokenIdToAuction; - - event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); - event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); - event AuctionCancelled(uint256 tokenId); - - /// @dev Returns true if the claimant owns the token. - /// @param _claimant - Address claiming to own the token. - /// @param _tokenId - ID of token whose ownership to verify. - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return (nonFungibleContract.ownerOf(_tokenId) == _claimant); - } - - /// @dev Escrows the NFT, assigning ownership to this contract. - /// Throws if the escrow fails. - /// @param _owner - Current owner address of token to escrow. - /// @param _tokenId - ID of token whose approval to verify. - function _escrow(address _owner, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transferFrom(_owner, address(this), _tokenId); - } - - /// @dev Transfers an NFT owned by this contract to another address. - /// Returns true if the transfer succeeds. - /// @param _receiver - Address to transfer NFT to. - /// @param _tokenId - ID of token to transfer. - function _transfer(address _receiver, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transfer(_receiver, _tokenId); - } - - /// @dev Adds an auction to the list of open auctions. Also fires the - /// AuctionCreated event. - /// @param _tokenId The ID of the token to be put on auction. - /// @param _auction Auction to add. - function _addAuction(uint256 _tokenId, Auction memory _auction) internal { - // Require that all auctions have a duration of - // at least one minute. (Keeps our math from getting hairy!) - require(_auction.duration >= 1 minutes); - - tokenIdToAuction[_tokenId] = _auction; - - emit AuctionCreated( - uint256(_tokenId), - uint256(_auction.startingPrice), - uint256(_auction.endingPrice), - uint256(_auction.duration) - ); - } - - /// @dev Cancels an auction unconditionally. - function _cancelAuction(uint256 _tokenId, address _seller) internal { - _removeAuction(_tokenId); - _transfer(_seller, _tokenId); - emit AuctionCancelled(_tokenId); - } - - /// @dev Computes the price and transfers winnings. - /// Does NOT transfer ownership of token. - function _bid(uint256 _tokenId, uint256 _bidAmount) - internal - returns (uint256) - { - // Get a reference to the auction struct - Auction storage auction = tokenIdToAuction[_tokenId]; - - // Explicitly check that this auction is currently live. - // (Because of how Ethereum mappings work, we can't just count - // on the lookup above failing. An invalid _tokenId will just - // return an auction object that is all zeros.) - require(_isOnAuction(auction)); - - // Check that the bid is greater than or equal to the current price - uint256 price = _currentPrice(auction); - require(_bidAmount >= price); - - // Grab a reference to the seller before the auction struct - // gets deleted. - address payable seller = auction.seller; - - // The bid is good! Remove the auction before sending the fees - // to the sender so we can't have a reentrancy attack. - _removeAuction(_tokenId); - - // Transfer proceeds to seller (if there are any!) - if (price > 0) { - // Calculate the auctioneer's cut. - // (NOTE: _computeCut() is guaranteed to return a - // value <= price, so this subtraction can't go negative.) - uint256 auctioneerCut = _computeCut(price); - uint256 sellerProceeds = price - auctioneerCut; - - // NOTE: Doing a transfer() in the middle of a complex - // method like this is generally discouraged because of - // reentrancy attacks and DoS attacks if the seller is - // a contract with an invalid fallback function. We explicitly - // guard against reentrancy attacks by removing the auction - // before calling transfer(), and the only thing the seller - // can DoS is the sale of their own asset! (And if it's an - // accident, they can call cancelAuction(). ) - seller.transfer(sellerProceeds); - } - - // Calculate any excess funds included with the bid. If the excess - // is anything worth worrying about, transfer it back to bidder. - // NOTE: We checked above that the bid amount is greater than or - // equal to the price so this cannot underflow. - uint256 bidExcess = _bidAmount - price; - - // Return the funds. Similar to the previous transfer, this is - // not susceptible to a re-entry attack because the auction is - // removed before any transfers occur. - msg.sender.transfer(bidExcess); - - // Tell the world! - emit AuctionSuccessful(_tokenId, price, msg.sender); - - return price; - } - - /// @dev Removes an auction from the list of open auctions. - /// @param _tokenId - ID of NFT on auction. - function _removeAuction(uint256 _tokenId) internal { - delete tokenIdToAuction[_tokenId]; - } - - /// @dev Returns true if the NFT is on auction. - /// @param _auction - Auction to check. - function _isOnAuction(Auction storage _auction) internal view returns (bool) { - return (_auction.startedAt > 0); - } - - /// @dev Returns current price of an NFT on auction. Broken into two - /// functions (this one, that computes the duration from the auction - /// structure, and the other that does the price computation) so we - /// can easily test that the price computation works correctly. - function _currentPrice(Auction storage _auction) - internal - view - returns (uint256) - { - uint256 secondsPassed = 0; - - // A bit of insurance against negative values (or wraparound). - // Probably not necessary (since Ethereum guarnatees that the - // now variable doesn't ever go backwards). - if (now > _auction.startedAt) { - secondsPassed = now - _auction.startedAt; - } - - return _computeCurrentPrice( - _auction.startingPrice, - _auction.endingPrice, - _auction.duration, - secondsPassed - ); - } - - /// @dev Computes the current price of an auction. Factored out - /// from _currentPrice so we can run extensive unit tests. - /// When testing, make this function public and turn on - /// `Current price computation` test suite. - function _computeCurrentPrice( - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - uint256 _secondsPassed - ) - internal - pure - returns (uint256) - { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our public functions carefully cap the maximum values for - // time (at 64-bits) and currency (at 128-bits). _duration is - // also known to be non-zero (see the require() statement in - // _addAuction()) - if (_secondsPassed >= _duration) { - // We've reached the end of the dynamic pricing portion - // of the auction, just return the end price. - return _endingPrice; - } else { - // Starting price can be higher than ending price (and often is!), so - // this delta can be negative. - int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - - // This multiplication can't overflow, _secondsPassed will easily fit within - // 64-bits, and totalPriceChange will easily fit within 128-bits, their product - // will always fit within 256-bits. - int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - - // currentPriceChange can be negative, but if so, will have a magnitude - // less that _startingPrice. Thus, this result will always end up positive. - int256 currentPrice = int256(_startingPrice) + currentPriceChange; - - return uint256(currentPrice); - } - } - - /// @dev Computes owner's cut of a sale. - /// @param _price - Sale price of NFT. - function _computeCut(uint256 _price) internal view returns (uint256) { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our entry functions carefully cap the maximum values for - // currency (at 128-bits), and ownerCut <= 10000 (see the require() - // statement in the ClockAuction constructor). The result of this - // function is always guaranteed to be <= _price. - return _price * ownerCut / 10000; - } - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { - event Pause(); - event Unpause(); - - bool public paused = false; - - - /** - * @dev modifier to allow actions only when the contract IS paused - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev modifier to allow actions only when the contract IS NOT paused - */ - modifier whenPaused { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyOwner whenNotPaused public returns (bool) { - paused = true; - emit Pause(); - return true; - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyOwner whenPaused public returns (bool) { - paused = false; - emit Unpause(); - return true; - } -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - - /// @dev The ERC-165 interface signature for ERC-721. - /// Ref: https://github.com/ethereum/EIPs/issues/165 - /// Ref: https://github.com/ethereum/EIPs/issues/721 - bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - - /// @dev Constructor creates a reference to the NFT ownership contract - /// and verifies the owner cut is in the valid range. - /// @param _nftAddress - address of a deployed contract implementing - /// the Nonfungible Interface. - /// @param _cut - percent cut the owner takes on each auction, must be - /// between 0-10,000. - constructor(address _nftAddress, uint256 _cut) public { - require(_cut <= 10000); - ownerCut = _cut; - - ERC721 candidateContract = ERC721(_nftAddress); - require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); - nonFungibleContract = candidateContract; - } - - /// @dev Remove all Ether from the contract, which is the owner's cuts - /// as well as any Ether sent directly to the contract address. - /// Always transfers to the NFT contract, but can be called either by - /// the owner or the NFT contract. - function withdrawBalance() external { - address payable nftAddress = address(uint160(address(nonFungibleContract))); - - require( - msg.sender == owner || - msg.sender == nftAddress - ); - // We are using this boolean method to make sure that even if one fails it will still work - bool res = nftAddress.send(address(this).balance); - } - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of time to move between starting - /// price and ending price (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - whenNotPaused - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(_owns(msg.sender, _tokenId)); - _escrow(msg.sender, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Bids on an open auction, completing the auction and transferring - /// ownership of the NFT if enough Ether is supplied. - /// @param _tokenId - ID of token to bid on. - function bid(uint256 _tokenId) - external - payable - whenNotPaused - { - // _bid will throw if the bid or funds transfer fails - _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - } - - /// @dev Cancels an auction that hasn't been won yet. - /// Returns the NFT to original owner. - /// @notice This is a state-modifying function that can - /// be called while the contract is paused. - /// @param _tokenId - ID of token on auction - function cancelAuction(uint256 _tokenId) - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - address seller = auction.seller; - require(msg.sender == seller); - _cancelAuction(_tokenId, seller); - } - - /// @dev Cancels an auction when the contract is paused. - /// Only the owner may do this, and NFTs are returned to - /// the seller. This should only be used in emergencies. - /// @param _tokenId - ID of the NFT on auction to cancel. - function cancelAuctionWhenPaused(uint256 _tokenId) - whenPaused - onlyOwner - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - _cancelAuction(_tokenId, auction.seller); - } - - /// @dev Returns auction info for an NFT on auction. - /// @param _tokenId - ID of NFT on auction. - function getAuction(uint256 _tokenId) - external - view - returns - ( - address seller, - uint256 startingPrice, - uint256 endingPrice, - uint256 duration, - uint256 startedAt - ) { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return ( - auction.seller, - auction.startingPrice, - auction.endingPrice, - auction.duration, - auction.startedAt - ); - } - - /// @dev Returns the current price of an auction. - /// @param _tokenId - ID of the token price we are checking. - function getCurrentPrice(uint256 _tokenId) - external - view - returns (uint256) - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return _currentPrice(auction); - } - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSiringAuctionAddress() call. - bool public isSiringClockAuction = true; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. Since this function is wrapped, - /// require sender to be KittyCore contract. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Places a bid for siring. Requires the sender - /// is the KittyCore contract because all bid methods - /// should be wrapped. Also returns the kitty to the - /// seller rather than the winner. - function bid(uint256 _tokenId) - external - payable - { - require(msg.sender == address(nonFungibleContract)); - address seller = tokenIdToAuction[_tokenId].seller; - // _bid checks that token ID is valid and will throw if bid fails - _bid(_tokenId, msg.value); - // We transfer the kitty back to the seller, the winner will get - // the offspring - _transfer(seller, _tokenId); - } - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSaleAuctionAddress() call. - bool public isSaleClockAuction = true; - - // Tracks last 5 sale price of gen0 kitty sales - uint256 public gen0SaleCount; - uint256[5] public lastGen0SalePrices; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Updates lastSalePrice if seller is the nft contract - /// Otherwise, works the same as default bid method. - function bid(uint256 _tokenId) - external - payable - { - // _bid verifies token ID size - address seller = tokenIdToAuction[_tokenId].seller; - uint256 price = _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - - // If not a gen0 auction, exit - if (seller == address(nonFungibleContract)) { - // Track gen0 sale prices - lastGen0SalePrices[gen0SaleCount % 5] = price; - gen0SaleCount++; - } - } - - function averageGen0SalePrice() external view returns (uint256) { - uint256 sum = 0; - for (uint256 i = 0; i < 5; i++) { - sum += lastGen0SalePrices[i]; - } - return sum / 5; - } - -} - - - - - - - diff --git a/framework/src/test/resources/soliditycode_0.5.15/addTrcToken002Cat_withFinny.sol b/framework/src/test/resources/soliditycode_0.5.15/addTrcToken002Cat_withFinny.sol deleted file mode 100644 index 2acebceddda..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/addTrcToken002Cat_withFinny.sol +++ /dev/null @@ -1,2051 +0,0 @@ -//pragma solidity ^0.4.11; - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() public { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address payable public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address payable _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() public onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - emit Transfer(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(now), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - uint256 newKittenId = kitties.push(_kitty) - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - emit Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(address(0), _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -contract ERC721 { - // Required methods - function totalSupply() public view returns (uint256 total); - function balanceOf(address _owner) public view returns (uint256 balance); - function ownerOf(uint256 _tokenId) external view returns (address owner); - function approve(address _to, uint256 _tokenId) external; - function transfer(address _to, uint256 _tokenId) external; - function transferFrom(address _from, address _to, uint256 _tokenId) external; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) external view returns (bool); -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is ERC721, KittyBase { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public view returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - emit Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() public view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - external - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { - string memory outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { - require( address(erc721Metadata) != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2 finney; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - msg.sender.transfer(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, address(saleAuction)); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, address(siringAuction)); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10 finney; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, address(saleAuction)); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - address(uint160(address(this))) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - constructor() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(-1), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - emit ContractUpgrade(_v2Address); - } - - /// @notice No tipping! - /// @dev Reject all Ether from being sent here, unless it's from one of the - /// two auction contracts. (Hopefully, we can prevent user accidents.) - function() external payable { - require( - msg.sender == address(saleAuction) || - msg.sender == address(siringAuction) - ); - } - - /// @notice Returns all the relevant information about a specific kitty. - /// @param _id The ID of the kitty of interest. - function getKitty(uint256 _id) - external - view - returns ( - bool isGestating, - bool isReady, - uint256 cooldownIndex, - uint256 nextActionAt, - uint256 siringWithId, - uint256 birthTime, - uint256 matronId, - uint256 sireId, - uint256 generation, - uint256 genes - ) { - Kitty storage kit = kitties[_id]; - - // if this variable is 0 then it's not gestating - isGestating = (kit.siringWithId != 0); - isReady = (kit.cooldownEndBlock <= block.number); - cooldownIndex = uint256(kit.cooldownIndex); - nextActionAt = uint256(kit.cooldownEndBlock); - siringWithId = uint256(kit.siringWithId); - birthTime = uint256(kit.birthTime); - matronId = uint256(kit.matronId); - sireId = uint256(kit.sireId); - generation = uint256(kit.generation); - genes = kit.genes; - } - - /// @dev Override unpause so it requires all external contract addresses - /// to be set before contract can be unpaused. Also, we can't have - /// newContractAddress set either, because then the contract was upgraded. - /// @notice This is public rather than external so we can call super.unpause - /// without using an expensive CALL. - - function unpause(address payable toAddress, uint256 tokenValue, trcToken tokenId) public onlyCEO whenPaused returns (uint256 r) { - require(address(saleAuction) != address(0)); - require(address(siringAuction) != address(0)); - require(address(geneScience) != address(0)); - require(address(newContractAddress) == address(0)); - toAddress.transferToken(tokenValue, tokenId); - r = address(this).tokenBalance(tokenId); - // Actually unpause the contract. - super.unpause(); - } - - // @dev Allows the CFO to capture the balance available to the contract. - function withdrawBalance() external onlyCFO { - uint256 balance = address(this).balance; - // Subtract all the currently pregnant kittens we have, plus 1 of margin. - uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - - if (balance > subtractFees) { - cfoAddress.transfer(balance - subtractFees); - } - } -} - - - - - - - - - - - - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - - function isGeneScience() public pure returns (bool){ - return true; - } - - /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor - /// @param genes1 genes of mom - /// @param genes2 genes of sire - /// @return the genes that are supposed to be passed down the child - function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - - return (genes1+genes2+targetBlock)/2; - - -} -} - - - - - - - - - - - - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { - /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. - function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { - if (_tokenId == 1) { - buffer[0] = "Hello World! :D"; - count = 15; - } else if (_tokenId == 2) { - buffer[0] = "I would definitely choose a medi"; - buffer[1] = "um length string."; - count = 49; - } else if (_tokenId == 3) { - buffer[0] = "Lorem ipsum dolor sit amet, mi e"; - buffer[1] = "st accumsan dapibus augue lorem,"; - buffer[2] = " tristique vestibulum id, libero"; - buffer[3] = " suscipit varius sapien aliquam."; - count = 128; - } - } -} - - - - - - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - - // Represents an auction on an NFT - struct Auction { - // Current owner of NFT - address payable seller; - // Price (in wei) at beginning of auction - uint128 startingPrice; - // Price (in wei) at end of auction - uint128 endingPrice; - // Duration (in seconds) of auction - uint64 duration; - // Time when auction started - // NOTE: 0 if this auction has been concluded - uint64 startedAt; - } - - // Reference to contract tracking NFT ownership - ERC721 public nonFungibleContract; - - // Cut owner takes on each auction, measured in basis points (1/100 of a percent). - // Values 0-10,000 map to 0%-100% - uint256 public ownerCut; - - // Map from token ID to their corresponding auction. - mapping (uint256 => Auction) tokenIdToAuction; - - event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); - event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); - event AuctionCancelled(uint256 tokenId); - - /// @dev Returns true if the claimant owns the token. - /// @param _claimant - Address claiming to own the token. - /// @param _tokenId - ID of token whose ownership to verify. - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return (nonFungibleContract.ownerOf(_tokenId) == _claimant); - } - - /// @dev Escrows the NFT, assigning ownership to this contract. - /// Throws if the escrow fails. - /// @param _owner - Current owner address of token to escrow. - /// @param _tokenId - ID of token whose approval to verify. - function _escrow(address _owner, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transferFrom(_owner, address(this), _tokenId); - } - - /// @dev Transfers an NFT owned by this contract to another address. - /// Returns true if the transfer succeeds. - /// @param _receiver - Address to transfer NFT to. - /// @param _tokenId - ID of token to transfer. - function _transfer(address _receiver, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transfer(_receiver, _tokenId); - } - - /// @dev Adds an auction to the list of open auctions. Also fires the - /// AuctionCreated event. - /// @param _tokenId The ID of the token to be put on auction. - /// @param _auction Auction to add. - function _addAuction(uint256 _tokenId, Auction memory _auction) internal { - // Require that all auctions have a duration of - // at least one minute. (Keeps our math from getting hairy!) - require(_auction.duration >= 1 minutes); - - tokenIdToAuction[_tokenId] = _auction; - - emit AuctionCreated( - uint256(_tokenId), - uint256(_auction.startingPrice), - uint256(_auction.endingPrice), - uint256(_auction.duration) - ); - } - - /// @dev Cancels an auction unconditionally. - function _cancelAuction(uint256 _tokenId, address _seller) internal { - _removeAuction(_tokenId); - _transfer(_seller, _tokenId); - emit AuctionCancelled(_tokenId); - } - - /// @dev Computes the price and transfers winnings. - /// Does NOT transfer ownership of token. - function _bid(uint256 _tokenId, uint256 _bidAmount) - internal - returns (uint256) - { - // Get a reference to the auction struct - Auction storage auction = tokenIdToAuction[_tokenId]; - - // Explicitly check that this auction is currently live. - // (Because of how Ethereum mappings work, we can't just count - // on the lookup above failing. An invalid _tokenId will just - // return an auction object that is all zeros.) - require(_isOnAuction(auction)); - - // Check that the bid is greater than or equal to the current price - uint256 price = _currentPrice(auction); - require(_bidAmount >= price); - - // Grab a reference to the seller before the auction struct - // gets deleted. - address payable seller = auction.seller; - - // The bid is good! Remove the auction before sending the fees - // to the sender so we can't have a reentrancy attack. - _removeAuction(_tokenId); - - // Transfer proceeds to seller (if there are any!) - if (price > 0) { - // Calculate the auctioneer's cut. - // (NOTE: _computeCut() is guaranteed to return a - // value <= price, so this subtraction can't go negative.) - uint256 auctioneerCut = _computeCut(price); - uint256 sellerProceeds = price - auctioneerCut; - - // NOTE: Doing a transfer() in the middle of a complex - // method like this is generally discouraged because of - // reentrancy attacks and DoS attacks if the seller is - // a contract with an invalid fallback function. We explicitly - // guard against reentrancy attacks by removing the auction - // before calling transfer(), and the only thing the seller - // can DoS is the sale of their own asset! (And if it's an - // accident, they can call cancelAuction(). ) - seller.transfer(sellerProceeds); - } - - // Calculate any excess funds included with the bid. If the excess - // is anything worth worrying about, transfer it back to bidder. - // NOTE: We checked above that the bid amount is greater than or - // equal to the price so this cannot underflow. - uint256 bidExcess = _bidAmount - price; - - // Return the funds. Similar to the previous transfer, this is - // not susceptible to a re-entry attack because the auction is - // removed before any transfers occur. - msg.sender.transfer(bidExcess); - - // Tell the world! - emit AuctionSuccessful(_tokenId, price, msg.sender); - - return price; - } - - /// @dev Removes an auction from the list of open auctions. - /// @param _tokenId - ID of NFT on auction. - function _removeAuction(uint256 _tokenId) internal { - delete tokenIdToAuction[_tokenId]; - } - - /// @dev Returns true if the NFT is on auction. - /// @param _auction - Auction to check. - function _isOnAuction(Auction storage _auction) internal view returns (bool) { - return (_auction.startedAt > 0); - } - - /// @dev Returns current price of an NFT on auction. Broken into two - /// functions (this one, that computes the duration from the auction - /// structure, and the other that does the price computation) so we - /// can easily test that the price computation works correctly. - function _currentPrice(Auction storage _auction) - internal - view - returns (uint256) - { - uint256 secondsPassed = 0; - - // A bit of insurance against negative values (or wraparound). - // Probably not necessary (since Ethereum guarnatees that the - // now variable doesn't ever go backwards). - if (now > _auction.startedAt) { - secondsPassed = now - _auction.startedAt; - } - - return _computeCurrentPrice( - _auction.startingPrice, - _auction.endingPrice, - _auction.duration, - secondsPassed - ); - } - - /// @dev Computes the current price of an auction. Factored out - /// from _currentPrice so we can run extensive unit tests. - /// When testing, make this function public and turn on - /// `Current price computation` test suite. - function _computeCurrentPrice( - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - uint256 _secondsPassed - ) - internal - pure - returns (uint256) - { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our public functions carefully cap the maximum values for - // time (at 64-bits) and currency (at 128-bits). _duration is - // also known to be non-zero (see the require() statement in - // _addAuction()) - if (_secondsPassed >= _duration) { - // We've reached the end of the dynamic pricing portion - // of the auction, just return the end price. - return _endingPrice; - } else { - // Starting price can be higher than ending price (and often is!), so - // this delta can be negative. - int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - - // This multiplication can't overflow, _secondsPassed will easily fit within - // 64-bits, and totalPriceChange will easily fit within 128-bits, their product - // will always fit within 256-bits. - int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - - // currentPriceChange can be negative, but if so, will have a magnitude - // less that _startingPrice. Thus, this result will always end up positive. - int256 currentPrice = int256(_startingPrice) + currentPriceChange; - - return uint256(currentPrice); - } - } - - /// @dev Computes owner's cut of a sale. - /// @param _price - Sale price of NFT. - function _computeCut(uint256 _price) internal view returns (uint256) { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our entry functions carefully cap the maximum values for - // currency (at 128-bits), and ownerCut <= 10000 (see the require() - // statement in the ClockAuction constructor). The result of this - // function is always guaranteed to be <= _price. - return _price * ownerCut / 10000; - } - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { - event Pause(); - event Unpause(); - - bool public paused = false; - - - /** - * @dev modifier to allow actions only when the contract IS paused - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev modifier to allow actions only when the contract IS NOT paused - */ - modifier whenPaused { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyOwner whenNotPaused public returns (bool) { - paused = true; - emit Pause(); - return true; - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyOwner whenPaused public returns (bool) { - paused = false; - emit Unpause(); - return true; - } -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - - /// @dev The ERC-165 interface signature for ERC-721. - /// Ref: https://github.com/ethereum/EIPs/issues/165 - /// Ref: https://github.com/ethereum/EIPs/issues/721 - bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - - /// @dev Constructor creates a reference to the NFT ownership contract - /// and verifies the owner cut is in the valid range. - /// @param _nftAddress - address of a deployed contract implementing - /// the Nonfungible Interface. - /// @param _cut - percent cut the owner takes on each auction, must be - /// between 0-10,000. - constructor(address _nftAddress, uint256 _cut) public { - require(_cut <= 10000); - ownerCut = _cut; - - ERC721 candidateContract = ERC721(_nftAddress); - require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); - nonFungibleContract = candidateContract; - } - - /// @dev Remove all Ether from the contract, which is the owner's cuts - /// as well as any Ether sent directly to the contract address. - /// Always transfers to the NFT contract, but can be called either by - /// the owner or the NFT contract. - function withdrawBalance() external { - address payable nftAddress = address(uint160(address(nonFungibleContract))); - - require( - msg.sender == owner || - msg.sender == nftAddress - ); - // We are using this boolean method to make sure that even if one fails it will still work - bool res = nftAddress.send(address(this).balance); - } - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of time to move between starting - /// price and ending price (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - whenNotPaused - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(_owns(msg.sender, _tokenId)); - _escrow(msg.sender, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Bids on an open auction, completing the auction and transferring - /// ownership of the NFT if enough Ether is supplied. - /// @param _tokenId - ID of token to bid on. - function bid(uint256 _tokenId) - external - payable - whenNotPaused - { - // _bid will throw if the bid or funds transfer fails - _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - } - - /// @dev Cancels an auction that hasn't been won yet. - /// Returns the NFT to original owner. - /// @notice This is a state-modifying function that can - /// be called while the contract is paused. - /// @param _tokenId - ID of token on auction - function cancelAuction(uint256 _tokenId) - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - address seller = auction.seller; - require(msg.sender == seller); - _cancelAuction(_tokenId, seller); - } - - /// @dev Cancels an auction when the contract is paused. - /// Only the owner may do this, and NFTs are returned to - /// the seller. This should only be used in emergencies. - /// @param _tokenId - ID of the NFT on auction to cancel. - function cancelAuctionWhenPaused(uint256 _tokenId) - whenPaused - onlyOwner - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - _cancelAuction(_tokenId, auction.seller); - } - - /// @dev Returns auction info for an NFT on auction. - /// @param _tokenId - ID of NFT on auction. - function getAuction(uint256 _tokenId) - external - view - returns - ( - address seller, - uint256 startingPrice, - uint256 endingPrice, - uint256 duration, - uint256 startedAt - ) { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return ( - auction.seller, - auction.startingPrice, - auction.endingPrice, - auction.duration, - auction.startedAt - ); - } - - /// @dev Returns the current price of an auction. - /// @param _tokenId - ID of the token price we are checking. - function getCurrentPrice(uint256 _tokenId) - external - view - returns (uint256) - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return _currentPrice(auction); - } - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSiringAuctionAddress() call. - bool public isSiringClockAuction = true; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. Since this function is wrapped, - /// require sender to be KittyCore contract. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Places a bid for siring. Requires the sender - /// is the KittyCore contract because all bid methods - /// should be wrapped. Also returns the kitty to the - /// seller rather than the winner. - function bid(uint256 _tokenId) - external - payable - { - require(msg.sender == address(nonFungibleContract)); - address seller = tokenIdToAuction[_tokenId].seller; - // _bid checks that token ID is valid and will throw if bid fails - _bid(_tokenId, msg.value); - // We transfer the kitty back to the seller, the winner will get - // the offspring - _transfer(seller, _tokenId); - } - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSaleAuctionAddress() call. - bool public isSaleClockAuction = true; - - // Tracks last 5 sale price of gen0 kitty sales - uint256 public gen0SaleCount; - uint256[5] public lastGen0SalePrices; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Updates lastSalePrice if seller is the nft contract - /// Otherwise, works the same as default bid method. - function bid(uint256 _tokenId) - external - payable - { - // _bid verifies token ID size - address seller = tokenIdToAuction[_tokenId].seller; - uint256 price = _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - - // If not a gen0 auction, exit - if (seller == address(nonFungibleContract)) { - // Track gen0 sale prices - lastGen0SalePrices[gen0SaleCount % 5] = price; - gen0SaleCount++; - } - } - - function averageGen0SalePrice() external view returns (uint256) { - uint256 sum = 0; - for (uint256 i = 0; i < 5; i++) { - sum += lastGen0SalePrices[i]; - } - return sum / 5; - } - -} - - - - - - - diff --git a/framework/src/test/resources/soliditycode_0.5.15/addressCheckNew.sol b/framework/src/test/resources/soliditycode_0.5.15/addressCheckNew.sol deleted file mode 100644 index 3c10b8c680d..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/addressCheckNew.sol +++ /dev/null @@ -1,9 +0,0 @@ -pragma experimental ABIEncoderV2; -contract testIsContract{ - function checkAddress(address addr) public returns (address){ - return addr; - } - function checkAddress2(address addr) pure public returns(address){ - return addr; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/addressCheckOld.sol b/framework/src/test/resources/soliditycode_0.5.15/addressCheckOld.sol deleted file mode 100644 index 6c6b15d1736..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/addressCheckOld.sol +++ /dev/null @@ -1,8 +0,0 @@ -contract testIsContract{ - function checkAddress(address addr) public returns (address){ - return addr; - } - function checkAddress2(address addr) pure public returns (address){ - return addr; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/altbn.sol b/framework/src/test/resources/soliditycode_0.5.15/altbn.sol deleted file mode 100644 index ee6ca1a98c9..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/altbn.sol +++ /dev/null @@ -1,63 +0,0 @@ -pragma solidity ^0.5.12; - -contract AltBn128 { - constructor() public payable {} - function callBn256Add(bytes32 ax, bytes32 ay, bytes32 bx, bytes32 by) public returns (bytes32[2] memory result) { - bytes32[4] memory input; - input[0] = ax; - input[1] = ay; - input[2] = bx; - input[3] = by; - assembly { - let success := call(gas, 0x06, 0, input, 0x80, result, 0x40) - } - - } - - function callBn256AddNoValue(bytes32 ax, bytes32 ay, bytes32 bx, bytes32 by) public returns - (bytes32[2] memory result) { - bytes32[4] memory input; - input[0] = ax; - input[1] = ay; - input[2] = bx; - input[3] = by; - assembly { - let success := call(gas, 0xac, 0, input, 0x80, result, 0x40) - } - } - - function callBn256ScalarMul(bytes32 x, bytes32 y, bytes32 scalar) public returns (bytes32[2] memory result) { - bytes32[3] memory input; - input[0] = x; - input[1] = y; - input[2] = scalar; - assembly { - let success := call(gas, 0x07, 0, input, 0x60, result, 0x40) - switch success - case 0 { - revert(0,0) - } - } - } - - function callBn256Pairing(bytes memory input) public returns (bytes32 result) { - // input is a serialized bytes stream of (a1, b1, a2, b2, ..., ak, bk) from (G_1 x G_2)^k - uint256 len = input.length; - require(len % 192 == 0); - assembly { - let memPtr := mload(0x40) - let success := call(gas, 0x08, 0, add(input, 0x20), len, memPtr, 0x20) - switch success - case 0 { - revert(0,0) - } default { - result := mload(memPtr) - } - } - } - - function convert(uint256 num) public view returns(bytes32) { - return bytes32(num); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/arrayLength001.sol b/framework/src/test/resources/soliditycode_0.5.15/arrayLength001.sol deleted file mode 100644 index 1c7e4e9dac2..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/arrayLength001.sol +++ /dev/null @@ -1,16 +0,0 @@ - -contract Test { - byte[] a; - - function ChangeSize() external returns(byte[] memory) { - a.push(0x01); - a.length = 3; - - a.length ++; - a.length --; - a.length --; - - a.pop(); - return a; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/assemblyTest.sol b/framework/src/test/resources/soliditycode_0.5.15/assemblyTest.sol deleted file mode 100644 index 6da31ff7b6f..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/assemblyTest.sol +++ /dev/null @@ -1,62 +0,0 @@ -pragma solidity ^0.5.12; - -contract assemblyTest { - - uint constant x = 1; - uint constant y = x; - function getZuint() public view returns (uint) { - uint z = y + 1; - assembly { - z := y - } - return z; - } - - function getZuint2() public returns (uint) { - uint z = y + 1; - assembly { - z := y - } - return z; - } - - bool constant bool1 = true; - bool constant bool2 = bool1; - function getZbool() public view returns (bool) { - bool z; - assembly { - z := bool2 - } - return z; - } - - function getZbool2() public returns (bool) { - bool z; - assembly { - z := bool2 - } - return z; - } - - -// string constant string1 = "abc"; -// string constant string2 = string1; -// function getZstring() public view returns (string memory) { -// string memory z; -// assembly { -// z := string2 -// } -// return z; -// } - - -// address origin1 = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; -// address origin2 = origin1; -// function getZaddress() public view returns (address) { -// address z; -// assembly { -// z := origin2 -// } -// return z; -// } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest1DivideInt.sol b/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest1DivideInt.sol deleted file mode 100644 index ca38896acee..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest1DivideInt.sol +++ /dev/null @@ -1,7 +0,0 @@ -//pragma solidity ^0.4.0; - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest2FindArgsContractMinTest.sol b/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest2FindArgsContractMinTest.sol deleted file mode 100644 index b8565d2578e..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest2FindArgsContractMinTest.sol +++ /dev/null @@ -1,10 +0,0 @@ -//pragma solidity ^0.4.0; -contract findArgsIContract{ -function findArgsByIndex1(uint i) public returns (uint z) { -uint[] memory a = new uint[](3); -a[0]=1; -a[1]=2; -a[2]=3; -return a[i]; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest3ByteMinContract.sol b/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest3ByteMinContract.sol deleted file mode 100644 index 6d846fad7f4..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest3ByteMinContract.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma solidity >0.5.0; -contract byteContract{ -bytes b; -function testBytesGet(uint i) public returns (bytes1){ -b = new bytes(3); -b[0]=0x0b; -b[1]=0x0c; -b[2]=0x0d; -return b[i]; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest4Enum.sol b/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest4Enum.sol deleted file mode 100644 index 4a740d4a089..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest4Enum.sol +++ /dev/null @@ -1,13 +0,0 @@ -//pragma solidity ^0.4.4; - -contract enumContract { - enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } - ActionChoices _choice; - function setGoStraight(ActionChoices choice) public { - _choice = choice; - } - - function getChoice() public returns (ActionChoices) { - return _choice; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest5MoveRight.sol b/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest5MoveRight.sol deleted file mode 100644 index 7194520fb09..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest5MoveRight.sol +++ /dev/null @@ -1,7 +0,0 @@ -//pragma solidity ^0.4.0; - -contract binaryRightContract{ - function binaryMoveR(int i)public returns (int z) { - return z = 5 >> i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest6UninitializedContract.sol b/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest6UninitializedContract.sol deleted file mode 100644 index 1ff2215abdb..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest6UninitializedContract.sol +++ /dev/null @@ -1,27 +0,0 @@ -//pragma solidity ^0.4.0; -contract uni { -function b(int x, int y) internal returns (int) -{ - return x * y; -} - -function test1() external returns (int) -{ - // Variable containing a function pointer - function (int, int) internal returns (int) funcPtr; - - funcPtr = b; - - // This call to funcPtr will succeed - return funcPtr(4, 5); -} - -function test2() external returns (int) -{ - // Variable containing a function pointer - function (int, int) internal returns (int) funcPtr; - - // This call will fail because funcPtr is still a zero-initialized function pointer - return funcPtr(4, 5); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest7TestAssertContract.sol b/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest7TestAssertContract.sol deleted file mode 100644 index 0bfd6fbd04e..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/assertExceptiontest7TestAssertContract.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity >0.5.0; -contract TestThrowsContract{ - function testAssert() public{ - assert(1==2); - } - function testRequire() public{ - require(2==1); - } - function testRevert() public{ - revert(); - } - function testThrow() public{ - revert(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign.sol b/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign.sol deleted file mode 100644 index 9e1c1b289b5..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - - function testArray2(bytes memory data) public returns(bool, bytes memory){ - return address(0x9).delegatecall(data); - } - - function testArray4(bytes memory data) public { - //address(0x1).delegatecall(data); - } - //function testArray3(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public { - //address(0x9).delegatecall(hash,signatures,addresses); - //} -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign001.sol b/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign001.sol deleted file mode 100644 index 57e051ce415..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign001.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - function testPure(bytes32 hash, bytes[] memory signatures, address[] memory addresses) pure public returns(bytes32){ - return batchvalidatesign(hash, signatures, addresses); - } - - function testArray(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public returns(bytes32){ - return batchvalidatesign(hash, signatures, addresses); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign002.sol b/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign002.sol deleted file mode 100644 index 375cec3a2a2..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign002.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - function testArray(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public returns(bytes32){ - - return batchvalidatesign(hash, signatures, addresses); - - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign003.sol b/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign003.sol deleted file mode 100644 index c43536af499..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign003.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract Demo { -bytes32 public result; -constructor (bytes32 hash, bytes[] memory signatures, address[] memory addresses) public { - result = batchvalidatesign(hash, signatures, addresses); -} -function testConstructor() public returns(bytes32){ - return result; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign005.sol b/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign005.sol deleted file mode 100644 index 3a6ca362973..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign005.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - - function testArray2(bytes memory data) public returns(bool, bytes memory){ - return address(0x9).delegatecall(data); - } - - function testArray4(bytes memory data) public { - //address(0x1).delegatecall(data); - } - function testArray3(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public { - //address(0x9).delegatecall(hash,signatures,addresses); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign007.sol b/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign007.sol deleted file mode 100644 index 974ffb34efe..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign007.sol +++ /dev/null @@ -1,17 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract Demo { - bytes32 public result; - - constructor (bytes32 hash, bytes[] memory signatures, address[] memory addresses) public { - result = batchvalidatesign(hash, signatures, addresses); - } - - function testConstructor() public returns(bytes32){ - return result; - } - - function testConstructorPure() public view returns(bytes32){ - return result; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign02.sol b/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign02.sol deleted file mode 100644 index 375cec3a2a2..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/batchvalidatesign02.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - function testArray(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public returns(bytes32){ - - return batchvalidatesign(hash, signatures, addresses); - - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/callValueGasPure.sol b/framework/src/test/resources/soliditycode_0.5.15/callValueGasPure.sol deleted file mode 100644 index ed4877e1ce4..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/callValueGasPure.sol +++ /dev/null @@ -1,8 +0,0 @@ - -contract C { -function check(address a) external pure returns (bool success) { - a.call.value(42).gas(42); - a.call.gas(42); - //a.call.value(1).gas(42)("fwefewf"); -} -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/calldata.sol b/framework/src/test/resources/soliditycode_0.5.15/calldata.sol deleted file mode 100644 index 6e877ac1b2f..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/calldata.sol +++ /dev/null @@ -1,33 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract C { - struct S { uint256 a; } - - function f(S calldata s) external returns (bytes memory) { - return abi.encode(s); - } - - function g(S calldata s) external returns (bytes memory) { - return this.f(s); - } - - function m(uint256[] calldata) external pure returns (bytes memory) { - return msg.data; - } - function h(uint8[] calldata s) external pure returns (bytes memory) { - return abi.encode(s); - } - function i(uint8[][2] calldata s, uint256 which) external view returns (bytes memory) { - return this.h(s[which]); - } - function j(bytes calldata s) external pure returns (bytes memory) { - return abi.encode(s); - } - function k(bytes[2] calldata s, uint256 which) external view returns (bytes memory) { - return this.j(s[which]); - } - function l(function() external returns (uint)[] calldata s) external returns (uint, uint, uint) { - assert(s.length == 3); - return (s[0](), s[1](), s[2]()); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/callvalue.sol b/framework/src/test/resources/soliditycode_0.5.15/callvalue.sol deleted file mode 100644 index ee2a30342c5..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/callvalue.sol +++ /dev/null @@ -1,9 +0,0 @@ -contract Callvalue { -function check() public payable returns(uint) { - uint256 wad; - assembly { - wad := callvalue - } - return wad; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/chainid001.sol b/framework/src/test/resources/soliditycode_0.5.15/chainid001.sol deleted file mode 100644 index c057a83b325..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/chainid001.sol +++ /dev/null @@ -1,20 +0,0 @@ -pragma solidity ^0.5.12; - -contract IstanbulTest { - constructor() public payable {} - function getId() public view returns(uint256){ - uint256 id; - assembly { - id := chainid() - } - return id; - } - - function getBalance(address src) public view returns(uint256){ - return address(src).balance; - } - - function getBalance() public view returns(uint256){ - return address(this).balance; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/codeSaftySupport.sol b/framework/src/test/resources/soliditycode_0.5.15/codeSaftySupport.sol deleted file mode 100644 index 45a4beee384..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/codeSaftySupport.sol +++ /dev/null @@ -1,19 +0,0 @@ -//pragma solidity ^0.4.24; - -contract IllegalDecorate { - -constructor() payable public{} - -function() payable external{} - -event log(uint256); - -function transferToken(address payable toAddress, uint256 tokenValue) public payable { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/codeSaftyUnsupport.sol b/framework/src/test/resources/soliditycode_0.5.15/codeSaftyUnsupport.sol deleted file mode 100644 index 220d66b2257..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/codeSaftyUnsupport.sol +++ /dev/null @@ -1,56 +0,0 @@ -//pragma solidity ^0.4.24; - -contract SubC { - -event log(string); - -function () payable external{} - -function receiveToken() payable public{} - -function getBalance() view public returns (uint256 r) { -r = address(this).balance; -} -} - -contract UseDot { -constructor() payable public{} -function() payable external{} -mapping(address => mapping(trcToken => uint256)) sender_tokens; - -function trigger1(address payable addr, trcToken tokenInputId) payable public { - //address(SubC(addr)).call.value(1000).tokenId(tokenInputId)(abi.encodeWithSignature("receiveToken()")); // ERROR -} - -function trigger2(address payable addr) payable public { -// addr.transferToken.value(10)(10, 0x6e6d62); // ERROR -} - -function trigger3(address payable addr) payable public { - // address(SubC(addr)).receiveToken.tokenvalue(10)(); // ERROR -} - -function trigger4(address payable addr) payable public { - //SubC(addr).receiveToken.tokenId(0x6e6d62)(); // ERROR -} - -function trigger5(address payable addr) payable public { - SubC(addr).receiveToken.value(10)(); -} - -function trigger6(address payable addr, trcToken tokenId) payable public { -address(SubC(addr)).call.value(1000)(abi.encodeWithSignature("transferToken(uint256, trcToken)", 10, tokenId)); -} - -function trigger7(address addr) payable public { - //sender_tokens[msg.sender][msg.tokenid] += msg.tokenvalue; // compile success, no necessary to trigger -} - -function trigger8(address addr) public payable returns(bytes memory r){ -// r = msg.data; // compile success, no necessary to trigger -} - -function getBalance() public returns (uint256 r){ -r = address(this).balance; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/constantCallStorage001.sol b/framework/src/test/resources/soliditycode_0.5.15/constantCallStorage001.sol deleted file mode 100644 index 1f584923a55..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/constantCallStorage001.sol +++ /dev/null @@ -1,159 +0,0 @@ -contract NotView { - uint256 public num = 123; - function setnum() public returns(uint256){ - num = num + 15; - return num; - } -} -contract NotViewInterface{ - function setnum() public returns(uint256); -} -contract UseNotView { - function setnumuseproxy(address contractAddress) public returns(uint256){ - NotViewInterface inter = NotViewInterface(contractAddress); - return inter.setnum(); - } -} -contract viewCall { - bool stopped = false; - int i = 32482989; - int i2 = -32482989; - uint ui = 23487823; - address origin = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; - bytes32 b32 = bytes32(uint256(0xdCad3a6d3569DF655070DEd0)); - bytes bs = new bytes(3); - string s = "123qwe"; - enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } - ActionChoices choice = ActionChoices.GoRight; - int64[] b = [-1, 2, -3]; - int32[2][] tmp_h = [[1,2],[3,4],[5,6]]; - int256[2][2] tmp_i = [[11,22],[33,44]]; - mapping (address => uint256) public mapa; - constructor() payable public{ - mapa[address(0x00)] = 34; - } - event log(int); - event log(uint); - event log(bool); - event log(address); - event log(bytes32); - event log(bytes); - event log(string); - event log(ActionChoices); - event log(int64[]); - event log(int32[2][]); - event log(int256[2][2]); - function changeBool(bool param) public returns (bool){ - stopped = param; - emit log(stopped); - return stopped; - } - function getBool() public returns (bool){ - emit log(stopped); - return stopped; - } - function changeInt(int param) public returns (int){ - i = param; - emit log(i); - return i; - } - function getInt() public returns (int){ - emit log(i); - return i; - } - function changeNegativeInt(int param) public returns (int){ - i2 = param; - emit log(i2); - return i2; - } - function getNegativeInt() public returns (int){ - emit log(i2); - return i2; - } - function changeUint(uint param) public returns (uint){ - ui = param; - emit log(ui); - return ui; - } - function getUint() public returns (uint){ - emit log(ui); - return ui; - } - function changeAddress(address param) public returns (address){ - origin = param; - emit log(origin); - return origin; - } - function getAddress() public returns (address){ - emit log(origin); - return origin; - } - function changeBytes32(bytes32 param) public returns (bytes32){ - b32 = param; - emit log(b32); - return b32; - } - function getBytes32() public returns (bytes32){ - emit log(b32); - return b32; - } - function changeBytes(bytes memory param) public returns (bytes memory){ - bs = param; - emit log(bs); - return bs; - } - function getBytes() public returns (bytes memory){ - emit log(bs); - return bs; - } - function changeString(string memory param) public returns (string memory){ - s = param; - emit log(s); - return s; - } - function getString() public returns (string memory){ - emit log(s); - return s; - } - function changeActionChoices(ActionChoices param) public returns (ActionChoices){ - choice = param; - emit log(choice); - return choice; - } - function getActionChoices() public returns (ActionChoices){ - emit log(choice); - return choice; - } - function changeInt64NegativeArray(int64[] memory param) public returns (int64[] memory){ - b = param; - emit log(b); - return b; - } - function getInt64NegativeArray() public returns (int64[] memory){ - emit log(b); - return b; - } - function changeInt32Array(int32[2][] memory param) public returns (int32[2][] memory){ - tmp_h = param; - emit log(tmp_h); - return tmp_h; - } - function getInt32Array() public returns (int32[2][] memory){ - emit log(tmp_h); - return tmp_h; - } - function changeInt256Array(int256[2][2] memory param) public returns (int256[2][2] memory){ - tmp_i = param; - emit log(tmp_i); - return tmp_i; - } - function getInt256Array() public returns (int256[2][2] memory){ - emit log(tmp_i); - return tmp_i; - } - function setMapping(uint256 param) public returns (uint256){ - mapa[msg.sender] = param; - return mapa[msg.sender]; - - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/constantCallStorage002.sol b/framework/src/test/resources/soliditycode_0.5.15/constantCallStorage002.sol deleted file mode 100644 index 1ceba5e87d2..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/constantCallStorage002.sol +++ /dev/null @@ -1,16 +0,0 @@ -contract NotView { - uint256 public num = 123; - function setnum() public returns(uint256){ - num = num + 15; - return num; - } -} -contract NotViewInterface{ - function setnum() public view returns(uint256); -} -contract UseNotView { - function setnumuseproxy(address contractAddress) public view returns(uint256){ - NotViewInterface inter = NotViewInterface(contractAddress); - return inter.setnum(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/constantCallStorage0425.sol b/framework/src/test/resources/soliditycode_0.5.15/constantCallStorage0425.sol deleted file mode 100644 index 8ecf771626d..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/constantCallStorage0425.sol +++ /dev/null @@ -1,156 +0,0 @@ -contract constantCall { - bool stopped = false; - int i = 32482989; - int i2 = -32482989; - uint ui = 23487823; - address origin = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; - bytes32 b32 = 0xb55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105c; - bytes bs = new bytes(9); - string s = "123qwe"; - enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } - ActionChoices choice = ActionChoices.SitStill; - int64[] b = [91, 2, 333]; - int32[2][] tmp_h = [[1,2],[3,4],[5,6]]; - int256[2][2] tmp_i = [[11,22],[33,44]]; - mapping (address => uint256) public mapa; - - constructor() payable public{ - mapa[address(0x00)] = 88; - } - event log(int); - event log(uint); - event log(bool); - event log(address); - event log(bytes32); - event log(bytes); - event log(string); - event log(ActionChoices); - event log(int64[]); - event log(int32[2][]); - event log(int256[2][2]); - - function changeBool(bool param) public constant returns (bool){ - stopped = param; - log(stopped); - return stopped; - } - function getBool() public constant returns (bool){ - log(stopped); - return stopped; - } - - function changeInt(int param) public returns (int){ - i = param; - log(i); - return i; - } - function getInt() public returns (int){ - log(i); - return i; - } - - function changeNegativeInt(int param) public constant returns (int){ - i2 = param; - log(i2); - return i2; - } - function getNegativeInt() public constant returns (int){ - log(i2); - return i2; - } - - function changeUint(uint param) public returns (uint){ - ui = param; - log(ui); - return ui; - } - function getUint() public returns (uint){ - log(ui); - return ui; - } - - function changeAddress(address param) public constant returns (address){ - origin = param; - log(origin); - return origin; - } - function getAddress() public constant returns (address){ - log(origin); - return origin; - } - - function changeBytes32(bytes32 param) public constant returns (bytes32){ - b32 = param; - log(b32); - return b32; - } - function getBytes32() public returns (bytes32){ - log(b32); - return b32; - } - - function changeBytes(bytes param) public constant returns (bytes){ - bs = param; - log(bs); - return bs; - } - function getBytes() public constant returns (bytes){ - log(bs); - return bs; - } - - function changeString(string param) public constant returns (string){ - s = param; - log(s); - return s; - } - function getString() public returns (string){ - log(s); - return s; - } - - function changeActionChoices(ActionChoices param) public constant returns (ActionChoices){ - choice = param; - log(choice); - return choice; - } - function getActionChoices() public constant returns (ActionChoices){ - log(choice); - return choice; - } - - function changeInt64NegativeArray(int64[] param) public constant returns (int64[]){ - b = param; - log(b); - return b; - } - function getInt64NegativeArray() public constant returns (int64[]){ - log(b); - return b; - } - - function changeInt32Array(int32[2][] param) public returns (int32[2][]){ - tmp_h = param; - log(tmp_h); - return tmp_h; - } - function getInt32Array() public constant returns (int32[2][]){ - log(tmp_h); - return tmp_h; - } - - function changeInt256Array(int256[2][2] param) public returns (int256[2][2]){ - tmp_i = param; - log(tmp_i); - return tmp_i; - } - function getInt256Array() public constant returns (int256[2][2]){ - log(tmp_i); - return tmp_i; - } - function setMapping(uint256 param) public returns (uint256){ - mapa[msg.sender] = param; - return mapa[msg.sender]; - - } -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/constantContract001.sol b/framework/src/test/resources/soliditycode_0.5.15/constantContract001.sol deleted file mode 100644 index ab97b450235..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/constantContract001.sol +++ /dev/null @@ -1,8 +0,0 @@ -//pragma solidity ^0.4.0; - -contract testConstantContract{ -function testPure(uint256 x,uint256 y) public pure returns (uint256 z) { -uint256 i=1; -return i + x + y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGetterContract.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGetterContract.sol deleted file mode 100644 index ba090f061dd..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGetterContract.sol +++ /dev/null @@ -1,17 +0,0 @@ -//pragma solidity ^0.4.0; - - -contract getterContract { - -constructor() public payable{} -function() external payable{} - -uint public c = msg.value; - -function getDataUsingAccessor() public payable returns (uint){ - -return c; - -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test1Grammar001.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test1Grammar001.sol deleted file mode 100644 index 1d0ad6e3d3f..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test1Grammar001.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma solidity >0.5.0; -contract FunctionSelector { - function select(bool useB, uint x) public returns (uint z) { - //var f = a; - //if (useB) f = b; - //return f(x); - if (useB) - return b(x); - else - return a(x); - } -function a(uint x) public returns (uint z) { - return x * x; - } -function b(uint x) public returns (uint z) { - return 2 * x; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test2Grammar002.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test2Grammar002.sol deleted file mode 100644 index df9d5c88839..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test2Grammar002.sol +++ /dev/null @@ -1,44 +0,0 @@ -//pragma solidity ^0.4.16; -library Set { - // We define a new struct datatype that will be used to - // hold its data in the calling contract. - struct Data { mapping(uint => bool) flags; } - - // Note that the first parameter is of type "storage - // reference" and thus only its storage address and not - // its contents is passed as part of the call. This is a - // special feature of library functions. It is idiomatic - // to call the first parameter 'self', if the function can - // be seen as a method of that object. - function insert(Data storage self, uint value) public returns (bool) { - if (self.flags[value]) - return false; // already there - self.flags[value] = true; - return true; - } - - function remove(Data storage self, uint value) public returns (bool) { - if (!self.flags[value]) - return false; // not there - self.flags[value] = false; - return true; - } - - function contains(Data storage self, uint value) public returns (bool) { - return self.flags[value]; - } -} - - -contract C { - Set.Data knownValues; - - function register (uint value) public{ - // The library functions can be called without a - // specific instance of the library, since the - // "instance" will be the current contract. - if (!Set.insert(knownValues, value)) - revert(); - } - // In this contract, we can also directly access knownValues.flags, if we want. -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test3Grammar003.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test3Grammar003.sol deleted file mode 100644 index ce56f5c9912..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test3Grammar003.sol +++ /dev/null @@ -1,44 +0,0 @@ -//pragma solidity ^0.4.11; - -library Set { - struct Data { mapping(uint => bool) flags; } - - function insert(Data storage self, uint value) public - returns (bool) - { - if (self.flags[value]) - return false; // already there - self.flags[value] = true; - return true; - } - - function remove(Data storage self, uint value) public - returns (bool) - { - if (!self.flags[value]) - return false; // not there - self.flags[value] = false; - return true; - } - - function contains(Data storage self, uint value) public - returns (bool) - { - return self.flags[value]; - } -} - - -contract C { - using Set for Set.Data; // this is the crucial change - Set.Data knownValues; - - function register(uint value) public{ - // Here, all variables of type Set.Data have - // corresponding member functions. - // The following function call is identical to - // Set.insert(knownValues, value) - if (!knownValues.insert(value)) - revert(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test4Grammar004.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test4Grammar004.sol deleted file mode 100644 index b36d171a912..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test4Grammar004.sol +++ /dev/null @@ -1,31 +0,0 @@ -//pragma solidity ^0.4.0; - -library Search { - function indexOf(uint[] storage self, uint value) public returns (uint) { - for (uint i = 0; i < self.length; i++) - if (self[i] == value) return i; - return uint(-1); - } -} - - -contract C { - using Search for uint[]; - uint[] public data; - - function append(uint value) public{ - data.push(value); - } - - function replace(uint _old, uint _new) public{ - // This performs the library function call - uint index = data.indexOf(_old); - if (index == uint(-1)) - data.push(_new); - else - data[index] = _new; - } - function getData(uint256 index) public returns(uint256){ - return data[index]; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test5Grammar006.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test5Grammar006.sol deleted file mode 100644 index 805476a9e4a..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar001test5Grammar006.sol +++ /dev/null @@ -1,38 +0,0 @@ -// pragma solidity ^0.4.0; -contract InfoFeed { -function d1(uint x) public{ - assembly{ - function f(x) -> y { switch x case 0 { y := 1 } default { y := mul(x, f(sub(x, 1))) } } - } - } - function d2(uint x) public{ - assembly { x := mul(1, add(2, 3))} - } - function f(uint x) public{ - assembly { x := sub(x, 1) } - - } - function d(uint x) public{ - assembly{ - let x := add(2, 3) let y := mload(0x40) x := add(x, y) - } - } - function d4(uint x) public{ - // Error: The labels 'repeat' is disallowed. Please use "if", "switch", "for" or function calls instead - //assembly{let x := 10 repeat: x := sub(x, 1) jumpi(repeat, eq(x, 0)) - x = x; - //} - } - function d5(uint x) public{ - assembly{ - function f(x) -> y { switch x case 0 { y := mul(x, 2) } default { y := 0 } } - - } - } - - function d6(uint x) public{ - assembly{ - function f(x) -> y { for { let i := 0 } lt(i, x) { i := add(i, 1) } { y := mul(2, y) } } - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test1Grammar007_1.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test1Grammar007_1.sol deleted file mode 100644 index 6e3ac0bfd1e..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test1Grammar007_1.sol +++ /dev/null @@ -1,60 +0,0 @@ -//pragma solidity ^0.4.19; -contract Doug{ - mapping (bytes32 => uint) public contracts; - constructor() public{ - contracts['hww'] = 1; - contracts['brian'] = 2; - contracts['zzy'] = 7; - } - - function getDougName(string memory _name) public view returns(string memory) { - return _name; - } - - function getDougAge(uint _age) public pure returns(uint) { - return 3 ** _age; - } -} - -contract DogInterface { - function getDougAge(uint _age) public returns (uint); - function contracts(bytes32 name) public returns (uint); -} -contract main{ - - event FetchContract(address dogInterfaceAddress, address sender, bytes32 name); - - address public DOUG; - - address dogInterfaceAddress; - DogInterface dogContract ; - - function setDOUG(address _doug) public { - DOUG = _doug; - } - - constructor(address addr) public{ - dogInterfaceAddress = addr; - dogContract = DogInterface(dogInterfaceAddress); - } - - function dougOfage(uint _age) public returns(uint) { - - uint num = dogContract.getDougAge(_age); - return _age+num; - // return num; - } - - function uintOfName(bytes32 _name) public returns (uint) { - - dogContract.contracts(_name); - emit FetchContract(dogInterfaceAddress, msg.sender, _name); - - } - - // function getTest(string _name) public view returns(string) { - // string memory newName = _name ; - // DogInterface(DOUG).getDougName(newName); - // return newName; - // } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test1Grammar007_2.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test1Grammar007_2.sol deleted file mode 100644 index 6e3ac0bfd1e..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test1Grammar007_2.sol +++ /dev/null @@ -1,60 +0,0 @@ -//pragma solidity ^0.4.19; -contract Doug{ - mapping (bytes32 => uint) public contracts; - constructor() public{ - contracts['hww'] = 1; - contracts['brian'] = 2; - contracts['zzy'] = 7; - } - - function getDougName(string memory _name) public view returns(string memory) { - return _name; - } - - function getDougAge(uint _age) public pure returns(uint) { - return 3 ** _age; - } -} - -contract DogInterface { - function getDougAge(uint _age) public returns (uint); - function contracts(bytes32 name) public returns (uint); -} -contract main{ - - event FetchContract(address dogInterfaceAddress, address sender, bytes32 name); - - address public DOUG; - - address dogInterfaceAddress; - DogInterface dogContract ; - - function setDOUG(address _doug) public { - DOUG = _doug; - } - - constructor(address addr) public{ - dogInterfaceAddress = addr; - dogContract = DogInterface(dogInterfaceAddress); - } - - function dougOfage(uint _age) public returns(uint) { - - uint num = dogContract.getDougAge(_age); - return _age+num; - // return num; - } - - function uintOfName(bytes32 _name) public returns (uint) { - - dogContract.contracts(_name); - emit FetchContract(dogInterfaceAddress, msg.sender, _name); - - } - - // function getTest(string _name) public view returns(string) { - // string memory newName = _name ; - // DogInterface(DOUG).getDougName(newName); - // return newName; - // } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test2Grammar008.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test2Grammar008.sol deleted file mode 100644 index c9c5d614d2d..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test2Grammar008.sol +++ /dev/null @@ -1,14 +0,0 @@ -//pragma solidity ^0.4.19; -contract Feline { - function utterance() public returns (bytes32); - - function getContractName() public returns (string memory){ - return "Feline"; - } -} - - -contract Cat is Feline { - function utterance() public returns (bytes32) { return "miaow"; } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test3Grammar010.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test3Grammar010.sol deleted file mode 100644 index a7749dfcc71..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test3Grammar010.sol +++ /dev/null @@ -1,10 +0,0 @@ -//pragma solidity ^0.4.0; -contract InfoFeed { -function info() public payable returns (uint ret) { return 42; } -} -contract Consumer { -constructor() payable public{} -InfoFeed feed; -function setFeed(address addr) public { feed = InfoFeed(addr); } -function callFeed() public payable { feed.info.value(10).gas(800)(); } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test4Grammar011.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test4Grammar011.sol deleted file mode 100644 index 921b52a6080..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test4Grammar011.sol +++ /dev/null @@ -1,11 +0,0 @@ -//pragma solidity ^0.4.0; -contract C { -function f(uint key, uint value) public returns(uint) { -return key; -// do something -} -function g() public { -// named arguments -f({value: 2, key: 3}); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test4Grammar012.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test4Grammar012.sol deleted file mode 100644 index 45e6d3aaf6e..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test4Grammar012.sol +++ /dev/null @@ -1,24 +0,0 @@ -//pragma solidity ^0.4.24; -contract rTest { -function info() public payable returns (uint,address,bytes4,uint,uint,uint,address,uint) { -//function info() public payable returns (address ,uint,uint,uint,bytes32,uint,bytes,uint,address,bytes4,uint,uint,uint,address,uint) { -//var a = block.coinbase ; -//var b = block.difficulty; -//var c = block.gaslimit; -//var d = block.number; -//var e = block.blockhash(0); -//var e = d; -//var f = block.timestamp; -//bytes memory g = msg.data; -uint256 h = gasleft(); -address payable i = msg.sender; -bytes4 j = msg.sig; -uint256 k = msg.value; -uint256 l = now; -uint256 m = tx.gasprice; -address payable n = tx.origin; -uint256 o = address(this).balance; -return (h,i,j,k,l,m,n,o); -//return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test6Grammar013.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test6Grammar013.sol deleted file mode 100644 index 56f97191ea0..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar002test6Grammar013.sol +++ /dev/null @@ -1,24 +0,0 @@ -//pragma solidity ^0.4.4; -contract Counter { -uint count = 0; -address payable owner; -//function Counter() public{ -constructor() public{ -owner = msg.sender; -} -function increment() public { -uint step = 10; -if (owner == msg.sender) { -count = count + step; -} -} -function getCount() public returns (uint){ -return count; -} -function kill() public{ -if (owner == msg.sender) { -selfdestruct(owner); -//selfdestruct(address(owner)); -} -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test1Grammar014.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test1Grammar014.sol deleted file mode 100644 index 9190e902056..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test1Grammar014.sol +++ /dev/null @@ -1,68 +0,0 @@ -//pragma solidity ^0.4.4; -contract A { -uint256 public numberForB; -address public senderForB; -function callTest(address bAddress, uint256 _number) public{ - -//bAddress.call(bytes4(sha3("setValue(uint256)")), _number); // B's storage is set, A is not modified -bAddress.call(abi.encodeWithSignature("setValue(uint256)",_number)); // B's storage is set, A is not modified -} -function callcodeTest(address bAddress, uint256 _number) public{ -//bAddress.callcode(bytes4(sha3("setValue(uint256)")), _number); // A's storage is set, B is not modified -bAddress.delegatecall(abi.encodeWithSignature("setValue(uint256)", _number)); // A's storage is set, B is not modified -} -function delegatecallTest(address bAddress, uint256 _number) public{ -//bAddress.delegatecall(bytes4(sha3("setValue(uint256)")), _number); // A's storage is set, B is not modified -bAddress.delegatecall(abi.encodeWithSignature("setValue(uint256)", _number)); // A's storage is set, B is not modified -} - -function callAddTest(address bAddress) public{ -//bAddress.call(bytes4(sha3("add()"))); // B's storage is set, A is not modified -bAddress.call(abi.encodeWithSignature("add()")); // B's storage is set, A is not modified -//bAddress.call(bytes4(sha3("add()"))); // B's storage is set, A is not modified -bAddress.call(abi.encodeWithSignature("add()")); // B's storage is set, A is not modified -} -function getnumberForB() public returns(uint256){ - return numberForB; - } - function getsenderForB() public returns(address){ - return senderForB; - } -} -contract B { -uint256 public numberForB; -address public senderForB; -address public addr11; -mapping(uint256=>address) public addr1; -mapping(uint256=>address) public addr2; -event ssss(uint256); -function setValue(uint256 _number) public{ - -emit ssss(_number); -numberForB = _number; -senderForB = msg.sender; -// senderForB is A if invoked by A's callTest. B's storage will be updated -// senderForB is A if invoked by A's callcodeTest. None of B's storage is updated -// senderForB is OWNER if invoked by A's delegatecallTest. None of B's storage is updated -} - -function add() public{ -numberForB=numberForB+1; -C c1 = new C(); -addr1[numberForB]=c1.getAddress(); -addr11 = c1.getAddress(); -C c2 = new C(); -addr2[numberForB] = c2.getAddress(); -} -function getnumberForB() public returns(uint256){ - return numberForB; - } - function getsenderForB() public returns(address){ - return senderForB; - } -} -contract C { -function getAddress() public view returns(address){ -return address(this); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test2Grammar015.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test2Grammar015.sol deleted file mode 100644 index 51aa0843890..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test2Grammar015.sol +++ /dev/null @@ -1,39 +0,0 @@ -//pragma solidity ^0.4.0; - -contract ExecuteFallback{ - - //回退事件,会把调用的数据打印出来 - event FallbackCalled(bytes data); - //fallback函数,注意是没有名字的,没有参数,没有返回值的 - function() external{ - emit FallbackCalled(msg.data); - } - - //调用已存在函数的事件,会把调用的原始数据,请求参数打印出来 - event ExistFuncCalled(bytes data, uint256 para); - //一个存在的函数 - function existFunc(uint256 para) public{ - emit ExistFuncCalled(msg.data, para); - } - - // 模拟从外部对一个存在的函数发起一个调用,将直接调用函数 - function callExistFunc() public{ - bytes4 funcIdentifier = bytes4(keccak256("existFunc(uint256)")); - //this.call(funcIdentifier, uint256(1)); - address(this).call(abi.encode(funcIdentifier, uint256(1))); - } - - //模拟从外部对一个不存在的函数发起一个调用,由于匹配不到函数,将调用回退函数 - function callNonExistFunc() public{ - bytes4 funcIdentifier = bytes4(keccak256("functionNotExist()")); - //this.call(funcIdentifier); - address(this).call(abi.encode(funcIdentifier)); - } - - function ExistFuncCalledTopic() view public returns(bytes32){ - return keccak256("ExistFuncCalled(bytes,uint256)"); - } - function FallbackCalledTopic() view public returns(bytes32){ - return keccak256("FallbackCalled(bytes)"); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test3Grammar016.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test3Grammar016.sol deleted file mode 100644 index 11eb8f9cc70..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test3Grammar016.sol +++ /dev/null @@ -1,23 +0,0 @@ -//pragma solidity ^0.4.0; -contract C { -uint private data; -function f(uint a) private returns(uint b) { return a + 1; } -function setData(uint a) public { data = a; } -function getData() public returns(uint) { return data; } -function compute(uint a, uint b) internal returns (uint) { return a+b; } -} -contract D { -function readData() public{ -C c = new C(); -//uint local = c.f(7); // error: member "f" is not visible -c.setData(3); -uint local = c.getData(); -// local = c.compute(3, 5); // error: member "compute" is not visible -} -} -contract E is C { -function g() public { -C c = new C(); -uint val = compute(3, 5); // access to internal member (from derived to parent contract) -} -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test4Grammar017.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test4Grammar017.sol deleted file mode 100644 index 23fcdec76f0..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test4Grammar017.sol +++ /dev/null @@ -1,50 +0,0 @@ -//pragma solidity ^0.4.0; -contract CrowdFunding{ -struct Funder{ -address addr; -uint amount; -} - -struct Campaign{ -address payable beneficiary; -uint goal; -uint amount; -uint funderNum; -mapping(uint => Funder) funders; -} - -uint compaingnID; -mapping (uint => Campaign) campaigns; - -function candidate(address payable beneficiary, uint goal) public payable returns (uint compaingnID){ -// initialize -campaigns[compaingnID++] = Campaign(beneficiary, goal, 0, 0); -} - -function vote(uint compaingnID) payable public { -Campaign storage c = campaigns[compaingnID]; - -//another way to initialize -c.funders[c.funderNum++] = Funder({addr: msg.sender, amount: msg.value}); -c.amount += msg.value; -} - -function check(uint comapingnId) public payable returns (bool){ - Campaign memory c = campaigns[comapingnId]; - - if(c.amount < c.goal){ - return false; - } - - uint amount = c.amount; - // incase send much more - c.amount = 0; - // address payable addr = address(uint160(c.beneficiary)); - //if(! addr.send(amount)){ - - if (! c.beneficiary.send(amount)){ - revert(); - } - return true; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test5Grammar018.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test5Grammar018.sol deleted file mode 100644 index ddd6deb040f..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test5Grammar018.sol +++ /dev/null @@ -1,37 +0,0 @@ -//pragma solidity ^0.4.0; - - -contract Grammar18{ - function testAddmod() public returns (uint z) { - //计算(x + y)%k,其中以任意精度执行加法,并且不在2 ** 256处围绕 - z=addmod(2, 2, 3); - return z; - } - function testMulmod() public returns (uint z) { -//计算(x * y)%k,其中乘法以任意精度执行,并且不会在2 ** 256处循环。 - z=mulmod(2, 3, 4); - return z; - } - - function testKeccak256() public returns(bytes32){ - //计算的(紧凑)参数的Ethereum-SHA-3(Keccak-256)的散列 - return keccak256("11"); - } - - function testSha256() public returns(bytes32){ - //计算(紧密包装)参数的SHA-256散列 - return sha256("11"); - } - function testSha3() public returns(bytes32){ - //计算(紧密包装)参数的SHA-256散列 - //return sha3("11"); - return keccak256("11"); - } - - function testRipemd160() public returns(bytes32){ - //计算(紧密包装)参数的RIPEMD-160哈希值 - return ripemd160("11"); - } - - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test6Grammar019.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test6Grammar019.sol deleted file mode 100644 index 30418539865..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test6Grammar019.sol +++ /dev/null @@ -1,12 +0,0 @@ -//pragma solidity ^0.4.0; -contract timetest { - -constructor() public { -require( 1 == 1 seconds); -require(1 minutes == 60 seconds); -require(1 hours == 60 minutes); -require(1 days == 24 hours); -require(1 weeks == 7 days); -//require(1 years == 365 days); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test7Grammar020.sol b/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test7Grammar020.sol deleted file mode 100644 index 1b960e6e313..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractGrammar003test7Grammar020.sol +++ /dev/null @@ -1,8 +0,0 @@ -//pragma solidity ^0.4.0; -contract trxtest { - -function test() public { -require(1 trx == 1000000 sun); - -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInnerContract.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInnerContract.sol deleted file mode 100644 index bc183931c88..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInnerContract.sol +++ /dev/null @@ -1,32 +0,0 @@ -//pragma solidity ^0.4.0; - - - -contract InnerContract { - - constructor() public payable{} - function() external payable{} - - function messageI() payable public returns (uint ret) { - - - - } - -} - - - -contract OuterContract { - - - constructor() public payable{} - function() external payable{} - - function callInner(address payable addr) payable public returns (uint) { - - return InnerContract(addr).messageI.value(1)(); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction001.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction001.sol deleted file mode 100644 index 8baba262e87..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction001.sol +++ /dev/null @@ -1,42 +0,0 @@ -//pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable external{} - function test1(address payable cAddr) public payable{ - B b1 = (new B).value(10)();//1.1 - B b2 = new B();//1.2 - address(b2).transfer(5);//1.3 - b2.callCGetZero(cAddr, 1);//1.4 - b2.callCGetZero(cAddr,2);//1.6 - } - function test2(address payable cAddress,uint256 amount) public payable{ - cAddress.call.value(amount)(abi.encodeWithSignature("newBAndTransfer()"));//2.1 - cAddress.call.value(amount + 1)(abi.encodeWithSignature("newBAndTransfer()"));//2.6 - } -} - -contract B{ - constructor() payable public{} - function() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero(address payable cAddress,uint256 amount) public{ - cAddress.call.value(amount)(abi.encodeWithSignature("getZero()"));//1.5,1.7 - } -} - -contract C{ - constructor() payable public{} - function() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - B b1 = (new B).value(7)();//2.2,2.7 - b1.getOne();//2.3,2.8 - B b2 = (new B).value(3)();//2.4,2.9 - b2.getOne();//2.5,2.10 - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction002.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction002.sol deleted file mode 100644 index 42231b7c960..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction002.sol +++ /dev/null @@ -1,21 +0,0 @@ -//pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable external{} - - function test2(address cAddress,uint256 amount) public payable{ - //cAddress.call.value(amount)();//2.1 - cAddress.call.value(amount)("");//2.1 - } -} - - -contract C{ - constructor() payable public{} - function() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction003.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction003.sol deleted file mode 100644 index 0910a0c4a2b..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction003.sol +++ /dev/null @@ -1,31 +0,0 @@ -//pragma solidity ^0.4.24; - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer() payable public{ - B b = (new B).value(10)();//1 - - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable public returns(bool) { - return true; - } - constructor() public payable {} - function payC(address payable c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - function () payable external{} - } - diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction004.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction004.sol deleted file mode 100644 index c7866dddb58..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction004.sol +++ /dev/null @@ -1,25 +0,0 @@ -//pragma solidity ^0.4.24; - -contract A{ - constructor () payable public{} - function test(address payable toAddress) public payable{ - selfdestruct(toAddress); - } - function () payable external{} - function getBalance() public view returns(uint256){ - return address(this).balance; - } -} -contract B{ - function() external payable{} - function kill(address contractAddres, address toAddress) payable public { - contractAddres.call(abi.encodeWithSignature("test(address)",address(this))); - } - function kill2() public{ - A a = new A(); - a.test(address(this)); - } - function getBalance() public view returns(uint256){ - return address(this).balance; - } -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction005.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction005.sol deleted file mode 100644 index 6e83c423b38..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction005.sol +++ /dev/null @@ -1,54 +0,0 @@ -//pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable external{} - function test1() public payable{ - B b1 = (new B).value(10)();//1.1 - b1.callCGetZero(false); - b1.callCGetZero(true);//1.4 - } - function test2() public payable{ - C c1 = (new C).value(10)();//1.1 - c1.newBAndTransfer(false); - c1.newBAndTransfer(true);//1.4 - - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract B{ - constructor() payable public{} - function() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero(bool success) public payable{ - if(!success){ - assert(1==2); - } - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract C{ - uint256 public flag=0; - constructor() payable public{} - function() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer(bool success) payable public returns(uint256){ - flag = 1; - if(!success){ - require(2==1); - } - } - function getFlag() public returns(uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction006.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction006.sol deleted file mode 100644 index 6bc548690a5..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction001testInternalTransaction006.sol +++ /dev/null @@ -1,54 +0,0 @@ -//pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable external{} - function test1() public payable{ - B b1 = (new B).value(10)();//1.1 - b1.callCGetZero(true);//1.4 - b1.callCGetZero(false); - } - function test2() public payable{ - C c1 = (new C).value(10)();//1.1 - c1.newBAndTransfer(true);//1.4 - c1.newBAndTransfer(false); - - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract B{ - constructor() payable public{} - function() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero(bool success) public payable{ - if(!success){ - assert(1==2); - } - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract C{ - uint256 public flag=0; - constructor() payable public{} - function() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer(bool success) payable public returns(uint256){ - flag = 1; - if(!success){ - require(2==1); - } - } - function getFlag() public returns(uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test1InternalTransaction007.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test1InternalTransaction007.sol deleted file mode 100644 index 229bf82fa2d..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test1InternalTransaction007.sol +++ /dev/null @@ -1,38 +0,0 @@ -//pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable external{} - function test1(address cAddr) public payable{ - B b1 = (new B).value(10)();//1.1 - B b2 = new B();//1.2 - address(b2).transfer(5);//1.3 - b2.callCGetZero();//1.4 - } - function test2(address cAddress,uint256 amount) public payable{ - cAddress.call.value(amount)(abi.encodeWithSignature("newBAndTransfer()"));//2.1 - } -} - -contract B{ - constructor() payable public{} - function() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero() public{ - assert(1==2); - - } -} - -contract C{ - constructor() payable public{} - function() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test2InternalTransaction008.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test2InternalTransaction008.sol deleted file mode 100644 index a75fba4f14b..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test2InternalTransaction008.sol +++ /dev/null @@ -1,60 +0,0 @@ -//pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable external{} - - function testAssert(address bAddress,uint256 amount) public payable{ - bAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("callCGetZero(bool)",false));//2.1 - bAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("callCGetZero(bool)",true)); - } - function testRequire(address cAddress,uint256 amount) public payable{ - cAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("newBAndTransfer(bool)",false));//2.1 - cAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("newBAndTransfer(bool)",true)); - } - function testAssert1(address bAddress,uint256 amount) public payable{ - bAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("callCGetZero(bool)",true)); - bAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("callCGetZero(bool)",false));//2.1 - } - function testtRequire2(address cAddress,uint256 amount) public payable{ - cAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("newBAndTransfer(bool)",true)); - cAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("newBAndTransfer(bool)",false));//2.1 - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract B{ - constructor() payable public{} - function() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero(bool success) payable public{ - if(!success){ - assert(1==2); - } - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract C{ - uint256 public flag=0; - constructor() payable public{} - function() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer(bool success) payable public returns(uint256){ - flag = 1; - if(!success){ - require(2==1); - } - } - function getFlag() public returns(uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test3InternalTransaction009.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test3InternalTransaction009.sol deleted file mode 100644 index 1a7df822511..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test3InternalTransaction009.sol +++ /dev/null @@ -1,47 +0,0 @@ -//pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable external{} - function test1(address cAddr,address dcontract,address baddress) public payable{ - B b1 = (new B).value(10)();//1.1 - address(b1).transfer(5);//1.3 - b1.callCGetZero(cAddr, 1);//1.4 - b1.getOne(dcontract,baddress); - } -} - -contract B{ - constructor() payable public{} - function() payable external{} - function getOne(address contractAddres, address toAddress) payable public{ - contractAddres.call(abi.encodeWithSignature("suicide1(address)",address(this))); - - } - function callCGetZero(address cAddress,uint256 amount) public{ - cAddress.call.value(amount)(abi.encodeWithSignature("getZero()"));//1.5,1.7 - } -} - -contract C{ - constructor() payable public{} - function() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public{ - B b1 = (new B).value(7)();//2.2,2.7 - B b2 = (new B).value(3)();//2.4,2.9 - } -} - -contract D{ - constructor () payable public{} - function suicide1(address payable toAddress) public payable{ - selfdestruct(toAddress); - } - function () payable external{} - function getBalance() public view returns(uint256){ - return address(this).balance; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test4InternalTransaction010.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test4InternalTransaction010.sol deleted file mode 100644 index 7f34b2bfe08..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test4InternalTransaction010.sol +++ /dev/null @@ -1,186 +0,0 @@ -//pragma solidity ^0.4.24; - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - - } - function transfer2() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - - } - function getBalance() public returns(uint256) { - return address(this).balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable public returns(bool) { - return true; - } - constructor() public payable {} - function payC(address payable c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - function () payable external{} - } - diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test4InternalTransaction010_1.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test4InternalTransaction010_1.sol deleted file mode 100644 index c77fe76f5fa..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test4InternalTransaction010_1.sol +++ /dev/null @@ -1,210 +0,0 @@ -pragma solidity ^0.4.24; - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - } - function transfer2() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - - } - function getBalance() returns(uint256){ - return this.balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable returns(bool) { - return true; - } - constructor() public payable {} - function payC(address c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() returns(uint256){ - return this.balance; - } - function () payable{} - } - - \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test5InternalTransaction012.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test5InternalTransaction012.sol deleted file mode 100644 index ce2798888fe..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction002test5InternalTransaction012.sol +++ /dev/null @@ -1,51 +0,0 @@ -//pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable external{} - function test1(address bAddr,address eAddr) public payable{ - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - } - -} - -contract B{ - constructor() payable public{} - function() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function testNN(address eAddress) public payable{ - D d1=(new D).value(1000)(); - d1.getOne(eAddress); - } -} - -contract C{ - constructor() payable public{} - function() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - function() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract D{ - constructor() payable public{} - function() payable external{} - function getOne(address eAddress) payable public returns(uint256){ - eAddress.call.value(1)(abi.encodeWithSignature("getZero()"));//2.1 - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction013.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction013.sol deleted file mode 100644 index bc1d3dbe6cd..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction013.sol +++ /dev/null @@ -1,56 +0,0 @@ -//pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable external{} - function test1(address dAddr) public payable{ - B b1 = (new B).value(10)();//1.1 - b1.testNN(dAddr,2);//1.6 - // C c1 = (new C).value(1000000000000)();//1.2 - // E e1 = (new E).value(1)();//1.2 - } - function test2(address cAddress,uint256 amount) public payable{ - cAddress.call.value(amount)(abi.encodeWithSignature("newBAndTransfer()"));//2.1 - } -} - -contract B{ - constructor() payable public{} - function() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function testNN(address dAddress,uint256 amount) public payable{ - // D d1=(new D)(); - dAddress.call.value(amount)(abi.encodeWithSignature("getOne()"));//2.1 - } -} - -contract C{ - constructor() payable public{} - function() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - function() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract D{ - constructor() payable public{} - function() payable external{} - function getOne() payable public returns(uint256){ - E e = (new E).value(5)(); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction014.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction014.sol deleted file mode 100644 index b3bbfc9a7db..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction014.sol +++ /dev/null @@ -1,38 +0,0 @@ -contract callerContract { - constructor() payable public{} - function() payable external{} - function sendToB(address called_address,address c) public payable{ - called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); - } - function sendToB2(address called_address,address c) public payable{ - called_address.call(abi.encodeWithSignature("transferTo(address)",c)); - } - function sendToB3(address called_address,address c) public payable{ - called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); - } -} - - contract calledContract { - function() payable external {} - constructor() payable public{} - function transferTo(address payable toAddress)public payable{ - toAddress.transfer(5); - } - - function setIinC(address c) public payable{ - c.call.value(5)(abi.encodeWithSignature("setI()")); - } - - } - - contract c{ - uint256 public i=0; - constructor() public payable{} - function getBalance() public view returns(uint256){ - return address(this).balance; - } - function setI() payable public{ - i=5; - } - function() payable external{} - } diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction015.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction015.sol deleted file mode 100644 index 0426d650da4..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction015.sol +++ /dev/null @@ -1,60 +0,0 @@ -//pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable external{} - function test1(address dAddr,address eAddr) public payable{ - B b1 = (new B).value(10)();//1.1 - b1.testNN(dAddr,2,eAddr);//1.6 - // C c1 = (new C).value(1000000000000)();//1.2 - // E e1 = (new E).value(1)();//1.2 - } - function test2(address cAddress,uint256 amount) public payable{ - cAddress.call.value(amount)(abi.encodeWithSignature("newBAndTransfer()"));//2.1 - } -} - -contract B{ - constructor() payable public{} - function() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function testNN(address dAddress,uint256 amount,address eAddress) public payable{ - // D d1=(new D)(); - dAddress.call.value(amount)(abi.encodeWithSignature("getOne(address)",address(this)));//2.1 - } -} - -contract C{ - constructor() payable public{} - function() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - function() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } - function suicide(address payable toAddress) public payable{ - selfdestruct(toAddress); - } -} -contract D{ - constructor() payable public{} - function() payable external{} - function getOne(address payable eAddress) payable public{ - E e = (new E).value(5)(); - e.suicide(eAddress); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction016.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction016.sol deleted file mode 100644 index f97217fe169..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction016.sol +++ /dev/null @@ -1,174 +0,0 @@ -//pragma solidity ^0.4.24; - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function () payable external{} - function transfer() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - B b1=(new B).value(1)();//1 - address payable aaa=address(this); - b1.suicide1(aaa); - } - function transfer2() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - B b1=(new B).value(1)();//1 - address payable aaa=address(this); - b1.suicide1(aaa); - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable public returns(bool) { - return true; - } - constructor() public payable {} - function payC(address payable c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - function () payable external{} - function suicide1(address payable toAddress) public payable{ - selfdestruct(toAddress); - } - } - diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction017.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction017.sol deleted file mode 100644 index ebe570fd8af..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction017.sol +++ /dev/null @@ -1,199 +0,0 @@ -//pragma solidity ^0.4.24; - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer(address payable Address) payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - - B b=(new B).value(1)();//1 - selfdestruct(Address); - } - function transfer2() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable public returns(bool) { - return true; - } - constructor() public payable {} - function payC(address payable c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - function () payable external{} - } - diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction018.sol b/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction018.sol deleted file mode 100644 index a59c587b233..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractInternalTransaction003testInternalTransaction018.sol +++ /dev/null @@ -1,97 +0,0 @@ -//pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable external{} - function test1(address payable bAddr,address eAddr) public payable{ - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - - } - -} - -contract B{ - constructor() payable public{} - function() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function testNN(address eAddress) public payable { - D d1=(new D).value(100)(); - d1.getOne(eAddress); - } -} - -contract C{ - constructor() payable public{} - function() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - function() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract D{ - constructor() payable public{} - function() payable external{} - function getOne(address eAddress) payable public returns(uint256){ - eAddress.call.value(1)(abi.encodeWithSignature("getZero()"));//2.1 - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractLinkage001.sol b/framework/src/test/resources/soliditycode_0.5.15/contractLinkage001.sol deleted file mode 100644 index 4c04cf5c6fb..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractLinkage001.sol +++ /dev/null @@ -1,9 +0,0 @@ -//pragma solidity ^0.4.0; - -contract divideIHaveArgsReturnStorage{ -constructor() payable public{} -function() payable external{} -function divideIHaveArgsReturn(int x,int y) public payable returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractLinkage002.sol b/framework/src/test/resources/soliditycode_0.5.15/contractLinkage002.sol deleted file mode 100644 index ca38896acee..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractLinkage002.sol +++ /dev/null @@ -1,7 +0,0 @@ -//pragma solidity ^0.4.0; - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractLinkage003.sol b/framework/src/test/resources/soliditycode_0.5.15/contractLinkage003.sol deleted file mode 100644 index ca38896acee..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractLinkage003.sol +++ /dev/null @@ -1,7 +0,0 @@ -//pragma solidity ^0.4.0; - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractLinkage004.sol b/framework/src/test/resources/soliditycode_0.5.15/contractLinkage004.sol deleted file mode 100644 index ca38896acee..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractLinkage004.sol +++ /dev/null @@ -1,7 +0,0 @@ -//pragma solidity ^0.4.0; - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractLinkage005.sol b/framework/src/test/resources/soliditycode_0.5.15/contractLinkage005.sol deleted file mode 100644 index 7b943aee5c1..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractLinkage005.sol +++ /dev/null @@ -1,51 +0,0 @@ -contract timeoutTest { - string public iarray1; - // cpu - function oneCpu() public { - require(1==1); - } - - function storage8Char() public { - iarray1 = "12345678"; - } - - function testUseCpu(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - } - return count; - } - - - uint256[] public iarray; - uint public calculatedFibNumber; - mapping(address=>mapping(address=>uint256)) public m; - - function testUseStorage(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - iarray.push(i); - } - return count; - } - - // stack - //uint n = 0; - uint yy = 0; - function test() public { - //n += 1; - yy += 1; - test(); - } - - function setFibonacci(uint n) public returns (uint256){ - calculatedFibNumber = fibonacci(n); - return calculatedFibNumber; - } - - function fibonacci(uint n) internal returns (uint) { - return fibonacci(n - 1) + fibonacci(n - 2); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractLinkage006.sol b/framework/src/test/resources/soliditycode_0.5.15/contractLinkage006.sol deleted file mode 100644 index 9c20c82dc02..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractLinkage006.sol +++ /dev/null @@ -1,18 +0,0 @@ -//pragma solidity ^0.4.0; -contract AA{ - uint256 public count=0; - constructor () payable public{} - function init(address payable addr, uint256 max) payable public { - count =0; - this.hack(addr,max); - } - function hack(address payable addr, uint256 max) payable public { - while (count < max) { - count = count +1; - this.hack(addr,max); - } - if (count == max) { - addr.send(20); - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractOriginEnergyLimit001.sol b/framework/src/test/resources/soliditycode_0.5.15/contractOriginEnergyLimit001.sol deleted file mode 100644 index 212614935f6..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractOriginEnergyLimit001.sol +++ /dev/null @@ -1,11 +0,0 @@ -//pragma solidity ^0.4.0; - -contract findArgsContractTest{ - function findArgsByIndexTest(uint i) public returns (uint z) { - uint[] memory a = new uint[](3); - a[0]=1; - a[1]=2; - a[2]=3; - return a[i]; - } -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractOriginEnergyLimit004.sol b/framework/src/test/resources/soliditycode_0.5.15/contractOriginEnergyLimit004.sol deleted file mode 100644 index 212614935f6..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractOriginEnergyLimit004.sol +++ /dev/null @@ -1,11 +0,0 @@ -//pragma solidity ^0.4.0; - -contract findArgsContractTest{ - function findArgsByIndexTest(uint i) public returns (uint z) { - uint[] memory a = new uint[](3); - a[0]=1; - a[1]=2; - a[2]=3; - return a[i]; - } -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractOtherToTrcToken.sol b/framework/src/test/resources/soliditycode_0.5.15/contractOtherToTrcToken.sol deleted file mode 100644 index 74afd5d0e54..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractOtherToTrcToken.sol +++ /dev/null @@ -1,41 +0,0 @@ -//pragma solidity ^0.4.24; - -contract ConvertType { - -constructor() payable public{} - -function() payable external{} - -//function stringToTrctoken(address payable toAddress, string memory tokenStr, uint256 tokenValue) public { -// trcToken t = trcToken(tokenStr); // ERROR -// toAddress.transferToken(tokenValue, tokenStr); // ERROR -//} - -function uint256ToTrctoken(address payable toAddress, uint256 tokenValue, uint256 tokenInt) public { - trcToken t = trcToken(tokenInt); // OK - toAddress.transferToken(tokenValue, t); // OK - toAddress.transferToken(tokenValue, tokenInt); // OK -} - -function addressToTrctoken(address payable toAddress, uint256 tokenValue, address adr) public { - trcToken t = trcToken(adr); // OK - toAddress.transferToken(tokenValue, t); // OK -//toAddress.transferToken(tokenValue, adr); // ERROR -} - -//function bytesToTrctoken(address payable toAddress, bytes memory b, uint256 tokenValue) public { - // trcToken t = trcToken(b); // ERROR - // toAddress.transferToken(tokenValue, b); // ERROR -//} - -function bytes32ToTrctoken(address payable toAddress, uint256 tokenValue, bytes32 b32) public { - trcToken t = trcToken(b32); // OK - toAddress.transferToken(tokenValue, t); // OK -// toAddress.transferToken(tokenValue, b32); // ERROR -} - -//function arrayToTrctoken(address payable toAddress, uint256[] memory arr, uint256 tokenValue) public { -//trcToken t = trcToken(arr); // ERROR -// toAddress.transferToken(tokenValue, arr); // ERROR -//} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractScenario001.sol b/framework/src/test/resources/soliditycode_0.5.15/contractScenario001.sol deleted file mode 100644 index ca38896acee..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractScenario001.sol +++ /dev/null @@ -1,7 +0,0 @@ -//pragma solidity ^0.4.0; - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractScenario002.sol b/framework/src/test/resources/soliditycode_0.5.15/contractScenario002.sol deleted file mode 100644 index aa9deda79ef..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractScenario002.sol +++ /dev/null @@ -1,53 +0,0 @@ -//pragma solidity ^0.4.0; -contract TronNative{ - - address public voteContractAddress= address(0x10001); - address public freezeBalanceAddress = address(0x10002); - address public unFreezeBalanceAddress = address(0x10003); - address public withdrawBalanceAddress = address(0x10004); - address public approveProposalAddress = address(0x10005); - address public createProposalAddress = address(0x10006); - address public deleteProposalAddress = address(0x10007); - constructor () payable public {} - - function voteForSingleWitness (address payable witnessAddr, uint256 voteValue) public{ - // method 1: - voteContractAddress.delegatecall(abi.encode(witnessAddr,voteValue)); - } - - function voteUsingAssembly (address witnessAddr, uint256 voteValue) public{ - // method 2: - assembly{ - mstore(0x80,witnessAddr) - mstore(0xa0,voteValue) - // gas, address, in, size, out, size - if iszero(delegatecall(0, 0x10001, 0x80, 0x40, 0x80, 0x0)) { - revert(0, 0) - } - } - } - - function freezeBalance(uint256 frozen_Balance,uint256 frozen_Duration) public { - freezeBalanceAddress.delegatecall(abi.encode(frozen_Balance,frozen_Duration)); - } - - function unFreezeBalance() public { - unFreezeBalanceAddress.delegatecall(""); - } - - function withdrawBalance() public { - withdrawBalanceAddress.delegatecall(""); - } - - function approveProposal(uint256 id, bool isApprove) public { - approveProposalAddress.delegatecall(abi.encode(id,isApprove)); - } - - function createProposal(bytes32 [] memory data) public { - createProposalAddress.delegatecall(abi.encode(data)); - } - - function deleteProposal(uint256 id) public{ - deleteProposalAddress.delegatecall(abi.encode(id)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractScenario003.sol b/framework/src/test/resources/soliditycode_0.5.15/contractScenario003.sol deleted file mode 100644 index ca38896acee..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractScenario003.sol +++ /dev/null @@ -1,7 +0,0 @@ -//pragma solidity ^0.4.0; - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractScenario004.sol b/framework/src/test/resources/soliditycode_0.5.15/contractScenario004.sol deleted file mode 100644 index b3ca2687b4c..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractScenario004.sol +++ /dev/null @@ -1,88 +0,0 @@ -//pragma solidity ^0.4.11; - -contract TronToken { - - string public name = "Tronix"; // token name - string public symbol = "TRX"; // token symbol - uint256 public decimals = 6; // token digit - - mapping (address => uint256) public balanceOf; - mapping (address => mapping (address => uint256)) public allowance; - - uint256 public totalSupply = 0; - bool public stopped = false; - - uint256 constant valueFounder = 100000000000000000; - address owner = address(0x0); - - modifier isOwner { - assert(owner == msg.sender); - _; - } - - modifier isRunning { - assert (!stopped); - _; - } - - modifier validAddress { - assert(address(0x0) != msg.sender); - _; - } - - constructor(address _addressFounder) public { - owner = msg.sender; - totalSupply = valueFounder; - balanceOf[_addressFounder] = valueFounder; - emit Transfer(address(0x0), _addressFounder, valueFounder); - } - - function transfer(address _to, uint256 _value) isRunning validAddress public returns (bool success) { - require(balanceOf[msg.sender] >= _value); - require(balanceOf[_to] + _value >= balanceOf[_to]); - balanceOf[msg.sender] -= _value; - balanceOf[_to] += _value; - emit Transfer(msg.sender, _to, _value); - return true; - } - - function transferFrom(address _from, address _to, uint256 _value) isRunning validAddress public returns (bool success) { - require(balanceOf[_from] >= _value); - require(balanceOf[_to] + _value >= balanceOf[_to]); - require(allowance[_from][msg.sender] >= _value); - balanceOf[_to] += _value; - balanceOf[_from] -= _value; - allowance[_from][msg.sender] -= _value; - emit Transfer(_from, _to, _value); - return true; - } - - function approve(address _spender, uint256 _value) isRunning validAddress public returns (bool success) { - require(_value == 0 || allowance[msg.sender][_spender] == 0); - allowance[msg.sender][_spender] = _value; - emit Approval(msg.sender, _spender, _value); - return true; - } - - function stop() isOwner public { - stopped = true; - } - - function start() isOwner public { - stopped = false; - } - - function setName(string memory _name) isOwner public { - name = _name; - } - - function burn(uint256 _value) public { - require(balanceOf[msg.sender] >= _value); - balanceOf[msg.sender] -= _value; - balanceOf[address(0x0)] += _value; - emit Transfer(msg.sender, address(0x0), _value); - } - - event Transfer(address indexed _from, address indexed _to, uint256 _value); - event Approval(address indexed _owner, address indexed _spender, uint256 _value); -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractScenario005.sol b/framework/src/test/resources/soliditycode_0.5.15/contractScenario005.sol deleted file mode 100644 index d46098cd410..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractScenario005.sol +++ /dev/null @@ -1,103 +0,0 @@ -//pragma solidity ^0.4.16; - -interface token { - function transfer(address receiver, uint amount) external; -} - -contract Crowdsale { - address payable public beneficiary = 0x1b228F5D9f934c7bb18Aaa86F90418932888E7b4; // 募资成功后的收款方 - uint public fundingGoal = 10000000; // 募资额度 - uint public amountRaised = 1000000; // 参与数量 - uint public deadline; // 募资截止期 - - uint public price; // token 与以太坊的汇率 , token卖多少钱 - token public tokenReward; // 要卖的token - - mapping(address => uint256) public balanceOf; - - bool fundingGoalReached = false; // 众筹是否达到目标 - bool crowdsaleClosed = false; // 众筹是否结束 - - /** - * 事件可以用来跟踪信息 - **/ - event GoalReached(address recipient, uint totalAmountRaised); - event FundTransfer(address backer, uint amount, bool isContribution); - - /** - * 构造函数, 设置相关属性 - */ - constructor( - address payable ifSuccessfulSendTo, - uint fundingGoalInEthers, - uint durationInMinutes, - uint finneyCostOfEachToken, - address addressOfTokenUsedAsReward) public{ - beneficiary = ifSuccessfulSendTo; - fundingGoal = fundingGoalInEthers * 1 sun; - deadline = now + durationInMinutes * 1 minutes; - price = finneyCostOfEachToken * 1 trx; - tokenReward = token(addressOfTokenUsedAsReward); // 传入已发布的 token 合约的地址来创建实例 - } - - /** - * 无函数名的Fallback函数, - * 在向合约转账时,这个函数会被调用 - */ - function () payable external{ - require(!crowdsaleClosed); - uint amount = msg.value; - balanceOf[msg.sender] += amount; - amountRaised += amount; - tokenReward.transfer(msg.sender, amount / price); - emit FundTransfer(msg.sender, amount, true); - } - - /** - * 定义函数修改器modifier(作用和Python的装饰器很相似) - * 用于在函数执行前检查某种前置条件(判断通过之后才会继续执行该方法) - * _ 表示继续执行之后的代码 - **/ - modifier afterDeadline() { if (now >= deadline) _; } - - /** - * 判断众筹是否完成融资目标, 这个方法使用了afterDeadline函数修改器 - * - */ - function checkGoalReached() afterDeadline public{ - if (amountRaised >= fundingGoal) { - fundingGoalReached = true; - emit GoalReached(beneficiary, amountRaised); - } - crowdsaleClosed = true; - } - - - /** - * 完成融资目标时,融资款发送到收款方 - * 未完成融资目标时,执行退款 - * - */ - function safeWithdrawal() afterDeadline public{ - if (!fundingGoalReached) { - uint amount = balanceOf[msg.sender]; - balanceOf[msg.sender] = 0; - if (amount > 0) { - if (msg.sender.send(amount)) { - emit FundTransfer(msg.sender, amount, false); - } else { - balanceOf[msg.sender] = amount; - } - } - } - - if (fundingGoalReached && beneficiary == msg.sender) { - if (address(beneficiary).send(amountRaised)) { - emit FundTransfer(beneficiary, amountRaised, false); - } else { - //If we fail to send the funds to beneficiary, unlock funders balance - fundingGoalReached = false; - } - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractScenario006.sol b/framework/src/test/resources/soliditycode_0.5.15/contractScenario006.sol deleted file mode 100644 index 397c62096e0..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractScenario006.sol +++ /dev/null @@ -1,1963 +0,0 @@ -//pragma solidity ^0.4.24; - -interface PlayerBookInterface { - function getPlayerID(address _addr) external returns (uint256); - function getPlayerName(uint256 _pID) external view returns (bytes32); - function getPlayerLAff(uint256 _pID) external view returns (uint256); - function getPlayerAddr(uint256 _pID) external view returns (address); - function getNameFee() external view returns (uint256); - function registerNameXIDFromDapp(address _addr, bytes32 _name, uint256 _affCode, bool _all) external payable returns(bool, uint256); - function registerNameXaddrFromDapp(address _addr, bytes32 _name, address _affCode, bool _all) external payable returns(bool, uint256); - function registerNameXnameFromDapp(address _addr, bytes32 _name, bytes32 _affCode, bool _all) external payable returns(bool, uint256); - function isDev(address _who) external view returns(bool); -} - - -/** -* @title -Name Filter- v0.1.9 -* ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ -* │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ -* ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ -* _____ _____ -* (, / /) /) /) (, / /) /) -* ┌─┐ / _ (/_ // // / _ // _ __ _(/ -* ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ -* ┴ ┴ / / .-/ _____ (__ / -* (__ / (_/ (, / /)™ -* / __ __ __ __ _ __ __ _ _/_ _ _(/ -* ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ -* ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 -* ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ -* _ __ _ ____ ____ _ _ _____ ____ ___ -*=============| |\ | / /\ | |\/| | |_ =====| |_ | | | | | | | |_ | |_)==============* -*=============|_| \| /_/--\ |_| | |_|__=====|_| |_| |_|__ |_| |_|__ |_| \==============* -* -* ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ -* ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ -* ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ -*/ - -library NameFilter { - /** - * @dev filters name strings - * -converts uppercase to lower case. - * -makes sure it does not start/end with a space - * -makes sure it does not contain multiple spaces in a row - * -cannot be only numbers - * -cannot start with 0x - * -restricts characters to A-Z, a-z, 0-9, and space. - * @return reprocessed string in bytes32 format - */ - function nameFilter(string memory _input) - internal - pure - returns(bytes32) - { - bytes memory _temp = bytes(_input); - uint256 _length = _temp.length; - - //sorry limited to 32 characters - require (_length <= 32 && _length > 0, "string must be between 1 and 32 characters"); - // make sure it doesnt start with or end with space - require(_temp[0] != 0x20 && _temp[_length-1] != 0x20, "string cannot start or end with space"); - // make sure first two characters are not 0x - if (_temp[0] == 0x30) - { - require(_temp[1] != 0x78, "string cannot start with 0x"); - require(_temp[1] != 0x58, "string cannot start with 0X"); - } - - // create a bool to track if we have a non number character - bool _hasNonNumber; - - // convert & check - for (uint256 i = 0; i < _length; i++) - { - // if its uppercase A-Z - if (_temp[i] > 0x40 && _temp[i] < 0x5b) - { - // convert to lower case a-z - _temp[i] = byte(uint8(_temp[i]) + 32); - - // we have a non number - if (_hasNonNumber == false) - _hasNonNumber = true; - } else { - require - ( - // require character is a space - _temp[i] == 0x20 || - // OR lowercase a-z - (_temp[i] > 0x60 && _temp[i] < 0x7b) || - // or 0-9 - (_temp[i] > 0x2f && _temp[i] < 0x3a), - "string contains invalid characters" - ); - // make sure theres not 2x spaces in a row - if (_temp[i] == 0x20) - require( _temp[i+1] != 0x20, "string cannot contain consecutive spaces"); - - // see if we have a character other than a number - if (_hasNonNumber == false && (_temp[i] < 0x30 || _temp[i] > 0x39)) - _hasNonNumber = true; - } - } - - require(_hasNonNumber == true, "string cannot be only numbers"); - - bytes32 _ret; - assembly { - _ret := mload(add(_temp, 32)) - } - return (_ret); - } -} - - -library SafeMath { - - /** - * @dev Multiplies two numbers, throws on overflow. - */ - function mul(uint256 a, uint256 b) - internal - pure - returns (uint256 c) - { - if (a == 0) { - return 0; - } - c = a * b; - require(c / a == b, "SafeMath mul failed"); - return c; - } - - /** - * @dev Integer division of two numbers, truncating the quotient. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // assert(b > 0); // Solidity automatically throws when dividing by 0 - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - return c; - } - - /** - * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 a, uint256 b) - internal - pure - returns (uint256) - { - require(b <= a, "SafeMath sub failed"); - return a - b; - } - - /** - * @dev Adds two numbers, throws on overflow. - */ - function add(uint256 a, uint256 b) - internal - pure - returns (uint256 c) - { - c = a + b; - require(c >= a, "SafeMath add failed"); - return c; - } - - /** - * @dev gives square root of given x. - */ - function sqrt(uint256 x) - internal - pure - returns (uint256 y) - { - uint256 z = ((add(x,1)) / 2); - y = x; - while (z < y) - { - y = z; - z = ((add((x / z),z)) / 2); - } - } - - /** - * @dev gives square. multiplies x by x - */ - function sq(uint256 x) - internal - pure - returns (uint256) - { - return (mul(x,x)); - } - - /** - * @dev x to the power of y - */ - function pwr(uint256 x, uint256 y) - internal - pure - returns (uint256) - { - if (x==0) - return (0); - else if (y==0) - return (1); - else - { - uint256 z = x; - for (uint256 i=1; i < y; i++) - z = mul(z,x); - return (z); - } - } -} - -//============================================================================== -// | _ _ _ | _ . -// |<(/_\/ (_(_||(_ . -//=======/====================================================================== -library F3DKeysCalcLong { - using SafeMath for *; - /** - * @dev calculates number of keys received given X eth - * @param _curEth current amount of eth in contract - * @param _newEth eth being spent - * @return amount of ticket purchased - */ - function keysRec(uint256 _curEth, uint256 _newEth) - internal - pure - returns (uint256) - { - return(keys((_curEth).add(_newEth)).sub(keys(_curEth))); - } - - /** - * @dev calculates amount of eth received if you sold X keys - * @param _curKeys current amount of keys that exist - * @param _sellKeys amount of keys you wish to sell - * @return amount of eth received - */ - function ethRec(uint256 _curKeys, uint256 _sellKeys) - internal - pure - returns (uint256) - { - return((eth(_curKeys)).sub(eth(_curKeys.sub(_sellKeys)))); - } - - /** - * @dev calculates how many keys would exist with given an amount of eth - * @param _eth eth "in contract" - * @return number of keys that would exist - */ - function keys(uint256 _eth) - internal - pure - returns(uint256) - { - return ((((((_eth).mul(1000000000000000000)).mul(312500000000000000000000000)).add(5624988281256103515625000000000000000000000000000000000000000000)).sqrt()).sub(74999921875000000000000000000000)) / (156250000); - } - - /** - * @dev calculates how much eth would be in contract given a number of keys - * @param _keys number of keys "in contract" - * @return eth that would exists - */ - function eth(uint256 _keys) - internal - pure - returns(uint256) - { - return ((78125000).mul(_keys.sq()).add(((149999843750000).mul(_keys.mul(1000000000000000000))) / (2))) / ((1000000000000000000).sq()); - } -} - -library F3Ddatasets { - //compressedData key - // [76-33][32][31][30][29][28-18][17][16-6][5-3][2][1][0] - // 0 - new player (bool) - // 1 - joined round (bool) - // 2 - new leader (bool) - // 3-5 - air drop tracker (uint 0-999) - // 6-16 - round end time - // 17 - winnerTeam - // 18 - 28 timestamp - // 29 - team - // 30 - 0 = reinvest (round), 1 = buy (round), 2 = buy (ico), 3 = reinvest (ico) - // 31 - airdrop happened bool - // 32 - airdrop tier - // 33 - airdrop amount won - //compressedIDs key - // [77-52][51-26][25-0] - // 0-25 - pID - // 26-51 - winPID - // 52-77 - rID - struct EventReturns { - uint256 compressedData; - uint256 compressedIDs; - address winnerAddr; // winner address - bytes32 winnerName; // winner name - uint256 amountWon; // amount won - uint256 newPot; // amount in new pot - uint256 P3DAmount; // amount distributed to p3d - uint256 genAmount; // amount distributed to gen - uint256 potAmount; // amount added to pot - } - struct Player { - address payable addr; // player address - bytes32 name; // player name - uint256 win; // winnings vault - uint256 gen; // general vault - uint256 aff; // affiliate vault - uint256 lrnd; // last round played - uint256 laff; // last affiliate id used - } - struct PlayerRounds { - uint256 eth; // eth player has added to round (used for eth limiter) - uint256 keys; // keys - uint256 mask; // player mask - uint256 ico; // ICO phase investment - } - struct Round { - uint256 plyr; // pID of player in lead - uint256 team; // tID of team in lead - uint256 end; // time ends/ended - bool ended; // has round end function been ran - uint256 strt; // time round started - uint256 keys; // keys - uint256 eth; // total eth in - uint256 pot; // eth to pot (during round) / final amount paid to winner (after round ends) - uint256 mask; // global mask - uint256 ico; // total eth sent in during ICO phase - uint256 icoGen; // total eth for gen during ICO phase - uint256 icoAvg; // average key price for ICO phase - } - struct TeamFee { - uint256 gen; // % of buy in thats paid to key holders of current round - uint256 p3d; // % of buy in thats paid to p3d holders - } - struct PotSplit { - uint256 gen; // % of pot thats paid to key holders of current round - uint256 p3d; // % of pot thats paid to p3d holders - } -} - -contract F3Devents { - // fired whenever a player registers a name - event onNewName - ( - uint256 indexed playerID, - address indexed playerAddress, - bytes32 indexed playerName, - bool isNewPlayer, - uint256 affiliateID, - address affiliateAddress, - bytes32 affiliateName, - uint256 amountPaid, - uint256 timeStamp - ); - - // fired at end of buy or reload - event onEndTx - ( - uint256 compressedData, - uint256 compressedIDs, - bytes32 playerName, - address playerAddress, - uint256 ethIn, - uint256 keysBought, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount, - uint256 potAmount, - uint256 airDropPot - ); - - // fired whenever theres a withdraw - event onWithdraw - ( - uint256 indexed playerID, - address playerAddress, - bytes32 playerName, - uint256 ethOut, - uint256 timeStamp - ); - - // fired whenever a withdraw forces end round to be ran - event onWithdrawAndDistribute - ( - address playerAddress, - bytes32 playerName, - uint256 ethOut, - uint256 compressedData, - uint256 compressedIDs, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount - ); - - // (fomo3d long only) fired whenever a player tries a buy after round timer - // hit zero, and causes end round to be ran. - event onBuyAndDistribute - ( - address playerAddress, - bytes32 playerName, - uint256 ethIn, - uint256 compressedData, - uint256 compressedIDs, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount - ); - - // (fomo3d long only) fired whenever a player tries a reload after round timer - // hit zero, and causes end round to be ran. - event onReLoadAndDistribute - ( - address playerAddress, - bytes32 playerName, - uint256 compressedData, - uint256 compressedIDs, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount - ); - - // fired whenever an affiliate is paid - event onAffiliatePayout - ( - uint256 indexed affiliateID, - address affiliateAddress, - bytes32 affiliateName, - uint256 indexed roundID, - uint256 indexed buyerID, - uint256 amount, - uint256 timeStamp - ); - - // received pot swap deposit - event onPotSwapDeposit - ( - uint256 roundID, - uint256 amountAddedToPot - ); -} - - - -contract FoMo3Dlong is F3Devents { - using SafeMath for *; - using NameFilter for string; - using F3DKeysCalcLong for uint256; - - address public otherF3D_; - address public Divies; - address public Jekyll_Island_Inc; - PlayerBookInterface public playerBook;// =PlayerBookInterface(0x0dcd2f752394c41875e259e00bb44fd505297caf);//new PlayerBook();// - // TeamJustInterface constant private teamJust = TeamJustInterface(0x3a5f8140b9213a0f733a6a639857c9df43ee3f5a);// new TeamJust();// - - //============================================================================== - // _ _ _ |`. _ _ _ |_ | _ _ . - // (_(_)| |~|~|(_||_|| (_||_)|(/__\ . (game settings) - //=================_|=========================================================== - string constant public name = "FoMo3D Long Official"; - string constant public symbol = "F3D"; - uint256 private rndExtra_ = 30;//extSettings.getLongExtra(); // length of the very first ICO - uint256 private rndGap_ = 30; //extSettings.getLongGap(); // length of ICO phase, set to 1 year for EOS. - uint256 constant private rndInit_ = 1 hours; // round timer starts at this - uint256 constant private rndInc_ = 30 seconds; // every full key purchased adds this much to the timer - uint256 constant private rndMax_ = 24 hours; // max length a round timer can be - //============================================================================== - // _| _ _|_ _ _ _ _|_ _ . - // (_|(_| | (_| _\(/_ | |_||_) . (data used to store game info that changes) - //=============================|================================================ - uint256 public airDropPot_; // person who gets the airdrop wins part of this pot - uint256 public airDropTracker_ = 0; // incremented each time a "qualified" tx occurs. used to determine winning air drop - uint256 public rID_; // round id number / total rounds that have happened - //**************** - // PLAYER DATA - //**************** - mapping(address => uint256) public pIDxAddr_; // (addr => pID) returns player id by address - mapping(bytes32 => uint256) public pIDxName_; // (name => pID) returns player id by name - mapping(uint256 => F3Ddatasets.Player) public plyr_; // (pID => data) player data - mapping(uint256 => mapping(uint256 => F3Ddatasets.PlayerRounds)) public plyrRnds_; // (pID => rID => data) player round data by player id & round id - mapping(uint256 => mapping(bytes32 => bool)) public plyrNames_; // (pID => name => bool) list of names a player owns. (used so you can change your display name amongst any name you own) - //**************** - // ROUND DATA - //**************** - mapping(uint256 => F3Ddatasets.Round) public round_; // (rID => data) round data - mapping(uint256 => mapping(uint256 => uint256)) public rndTmEth_; // (rID => tID => data) eth in per team, by round id and team id - //**************** - // TEAM FEE DATA - //**************** - mapping(uint256 => F3Ddatasets.TeamFee) public fees_; // (team => fees) fee distribution by team - mapping(uint256 => F3Ddatasets.PotSplit) public potSplit_; // (team => fees) pot split distribution by team - - function setPlayerBook(address _playerBook) external { - require(msg.sender == owner, 'only dev!'); - require(address(playerBook) == address(0), 'already set!'); - playerBook = PlayerBookInterface(_playerBook); - } - - address public owner; - - //============================================================================== - // _ _ _ __|_ _ __|_ _ _ . - // (_(_)| |_\ | | |_|(_ | (_)| . (initial data setup upon contract deploy) - //============================================================================== - constructor() - public - { - owner = msg.sender; - // Team allocation structures - // 0 = whales - // 1 = bears - // 2 = sneks - // 3 = bulls - - // Team allocation percentages - // (F3D, P3D) + (Pot , Referrals, Community) - // Referrals / Community rewards are mathematically designed to come from the winner's share of the pot. - fees_[0] = F3Ddatasets.TeamFee(30, 6); - //50% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - fees_[1] = F3Ddatasets.TeamFee(43, 0); - //43% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - fees_[2] = F3Ddatasets.TeamFee(56, 10); - //20% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - fees_[3] = F3Ddatasets.TeamFee(43, 8); - //35% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - - // how to split up the final pot based on which team was picked - // (F3D, P3D) - potSplit_[0] = F3Ddatasets.PotSplit(15, 10); - //48% to winner, 25% to next round, 2% to com - potSplit_[1] = F3Ddatasets.PotSplit(25, 0); - //48% to winner, 25% to next round, 2% to com - potSplit_[2] = F3Ddatasets.PotSplit(20, 20); - //48% to winner, 10% to next round, 2% to com - potSplit_[3] = F3Ddatasets.PotSplit(30, 10); - //48% to winner, 10% to next round, 2% to com - } - //============================================================================== - // _ _ _ _|. |`. _ _ _ . - // | | |(_)(_||~|~|(/_| _\ . (these are safety checks) - //============================================================================== - /** - * @dev used to make sure no one can interact with contract until it has - * been activated. - */ - modifier isActivated() { - require(activated_ == true, "its not ready yet. check ?eta in discord"); - _; - } - - /** - * @dev prevents contracts from interacting with fomo3d - */ - modifier isHuman() { - address _addr = msg.sender; - uint256 _codeLength; - - assembly {_codeLength := extcodesize(_addr)} - require(_codeLength == 0, "sorry humans only"); - _; - } - - modifier onlyDevs() - { - require(playerBook.isDev(msg.sender) == true, "msg sender is not a dev"); - _; - } - - /** - * @dev sets boundaries for incoming tx - */ - modifier isWithinLimits(uint256 _eth) { - require(_eth >= 1000000000, "pocket lint: not a valid currency"); - require(_eth <= 100000000000000000000000, "no vitalik, no"); - _; - } - - //============================================================================== - // _ |_ |. _ |` _ __|_. _ _ _ . - // |_)|_||_)||(_ ~|~|_|| |(_ | |(_)| |_\ . (use these to interact with contract) - //====|========================================================================= - /** - * @dev emergency buy uses last stored affiliate ID and team snek - */ - function() - isActivated() - isHuman() - isWithinLimits(msg.value) - external - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_ ; - _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // buy core - buyCore(_pID, plyr_[_pID].laff, 2, _eventData_); - } - - /** - * @dev converts all incoming ethereum to keys. - * -functionhash- 0x8f38f309 (using ID for affiliate) - * -functionhash- 0x98a0871d (using address for affiliate) - * -functionhash- 0xa65b37a1 (using name for affiliate) - * @param _affCode the ID/address/name of the player who gets the affiliate fee - * @param _team what team is the player playing for? - */ - function buyXid(uint256 _affCode, uint256 _team) - isActivated() - isHuman() - isWithinLimits(msg.value) - public - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_; - _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == 0 || _affCode == _pID) - { - // use last stored affiliate code - _affCode = plyr_[_pID].laff; - - // if affiliate code was given & its not the same as previously stored - } else if (_affCode != plyr_[_pID].laff) { - // update last affiliate - plyr_[_pID].laff = _affCode; - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // buy core - buyCore(_pID, _affCode, _team, _eventData_); - } - - function buyXaddr(address _affCode, uint256 _team) - isActivated() - isHuman() - isWithinLimits(msg.value) - public - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_; - _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == address(0) || _affCode == msg.sender) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxAddr_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // buy core - buyCore(_pID, _affID, _team, _eventData_); - } - - function buyXname(bytes32 _affCode, uint256 _team) - isActivated() - isHuman() - isWithinLimits(msg.value) - public - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_ ; - _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == '' || _affCode == plyr_[_pID].name) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxName_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // buy core - buyCore(_pID, _affID, _team, _eventData_); - } - - /** - * @dev essentially the same as buy, but instead of you sending ether - * from your wallet, it uses your unwithdrawn earnings. - * -functionhash- 0x349cdcac (using ID for affiliate) - * -functionhash- 0x82bfc739 (using address for affiliate) - * -functionhash- 0x079ce327 (using name for affiliate) - * @param _affCode the ID/address/name of the player who gets the affiliate fee - * @param _team what team is the player playing for? - * @param _eth amount of earnings to use (remainder returned to gen vault) - */ - function reLoadXid(uint256 _affCode, uint256 _team, uint256 _eth) - isActivated() - isHuman() - isWithinLimits(_eth) - public - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == 0 || _affCode == _pID) - { - // use last stored affiliate code - _affCode = plyr_[_pID].laff; - - // if affiliate code was given & its not the same as previously stored - } else if (_affCode != plyr_[_pID].laff) { - // update last affiliate - plyr_[_pID].laff = _affCode; - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // reload core - reLoadCore(_pID, _affCode, _team, _eth, _eventData_); - } - - function reLoadXaddr(address _affCode, uint256 _team, uint256 _eth) - isActivated() - isHuman() - isWithinLimits(_eth) - public - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == address(0) || _affCode == msg.sender) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxAddr_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // reload core - reLoadCore(_pID, _affID, _team, _eth, _eventData_); - } - - function reLoadXname(bytes32 _affCode, uint256 _team, uint256 _eth) - isActivated() - isHuman() - isWithinLimits(_eth) - public - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == '' || _affCode == plyr_[_pID].name) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxName_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // reload core - reLoadCore(_pID, _affID, _team, _eth, _eventData_); - } - - /** - * @dev withdraws all of your earnings. - * -functionhash- 0x3ccfd60b - */ - function withdraw() - isActivated() - isHuman() - public - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = now; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // setup temp var for player eth - uint256 _eth; - - // check to see if round has ended and no one has run round end yet - if (_now > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // end the round (distributes pot) - round_[_rID].ended = true; - _eventData_ = endRound(_eventData_); - - // get their earnings - _eth = withdrawEarnings(_pID); - - // gib moni - if (_eth > 0) - plyr_[_pID].addr.transfer(_eth); - - // build event data - _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; - - // fire withdraw and distribute event - emit F3Devents.onWithdrawAndDistribute - ( - msg.sender, - plyr_[_pID].name, - _eth, - _eventData_.compressedData, - _eventData_.compressedIDs, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount - ); - - // in any other situation - } else { - // get their earnings - _eth = withdrawEarnings(_pID); - - // gib moni - if (_eth > 0) - plyr_[_pID].addr.transfer(_eth); - - // fire withdraw event - emit F3Devents.onWithdraw(_pID, msg.sender, plyr_[_pID].name, _eth, _now); - } - } - - /** - * @dev use these to register names. they are just wrappers that will send the - * registration requests to the PlayerBook contract. So registering here is the - * same as registering there. UI will always display the last name you registered. - * but you will still own all previously registered names to use as affiliate - * links. - * - must pay a registration fee. - * - name must be unique - * - names will be converted to lowercase - * - name cannot start or end with a space - * - cannot have more than 1 space in a row - * - cannot be only numbers - * - cannot start with 0x - * - name must be at least 1 char - * - max length of 32 characters long - * - allowed characters: a-z, 0-9, and space - * -functionhash- 0x921dec21 (using ID for affiliate) - * -functionhash- 0x3ddd4698 (using address for affiliate) - * -functionhash- 0x685ffd83 (using name for affiliate) - * @param _nameString players desired name - * @param _affCode affiliate ID, address, or name of who referred you - * @param _all set to true if you want this to push your info to all games - * (this might cost a lot of gas) - */ - function registerNameXID(string memory _nameString, uint256 _affCode, bool _all) - isHuman() - public - payable - { - bytes32 _name = _nameString.nameFilter(); - address _addr = msg.sender; - uint256 _paid = msg.value; - (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXIDFromDapp.value(_paid)(_addr, _name, _affCode, _all); - - uint256 _pID = pIDxAddr_[_addr]; - - // fire event - emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); - } - - function registerNameXaddr(string memory _nameString, address _affCode, bool _all) - isHuman() - public - payable - { - bytes32 _name = _nameString.nameFilter(); - address _addr = msg.sender; - uint256 _paid = msg.value; - (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXaddrFromDapp.value(msg.value)(msg.sender, _name, _affCode, _all); - - uint256 _pID = pIDxAddr_[_addr]; - - // fire event - emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); - } - - function registerNameXname(string memory _nameString, bytes32 _affCode, bool _all) - isHuman() - public - payable - { - bytes32 _name = _nameString.nameFilter(); - address _addr = msg.sender; - uint256 _paid = msg.value; - (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXnameFromDapp.value(msg.value)(msg.sender, _name, _affCode, _all); - - uint256 _pID = pIDxAddr_[_addr]; - - // fire event - emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); - } - //============================================================================== - // _ _ _|__|_ _ _ _ . - // (_|(/_ | | (/_| _\ . (for UI & viewing things on etherscan) - //=====_|======================================================================= - /** - * @dev return the price buyer will pay for next 1 individual key. - * -functionhash- 0x018a25e8 - * @return price for next key bought (in wei format) - */ - function getBuyPrice() - public - view - returns (uint256) - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = now; - - // are we in a round? - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - return ((round_[_rID].keys.add(1000000000000000000)).ethRec(1000000000000000000)); - else // rounds over. need price for new round - return (75000000000000); - // init - } - - /** - * @dev returns time left. dont spam this, you'll ddos yourself from your node - * provider - * -functionhash- 0xc7e284b8 - * @return time left in seconds - */ - function getTimeLeft() - public - view - returns (uint256) - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = now; - - if (_now < round_[_rID].end) - if (_now > round_[_rID].strt + rndGap_) - return ((round_[_rID].end).sub(_now)); - else - return ((round_[_rID].strt + rndGap_).sub(_now)); - else - return (0); - } - - /** - * @dev returns player earnings per vaults - * -functionhash- 0x63066434 - * @return winnings vault - * @return general vault - * @return affiliate vault - */ - function getPlayerVaults(uint256 _pID) - public - view - returns (uint256, uint256, uint256) - { - // setup local rID - uint256 _rID = rID_; - - // if round has ended. but round end has not been run (so contract has not distributed winnings) - if (now > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) - { - // if player is winner - if (round_[_rID].plyr == _pID) - { - return - ( - (plyr_[_pID].win).add(((round_[_rID].pot).mul(48)) / 100), - (plyr_[_pID].gen).add(getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask)), - plyr_[_pID].aff - ); - // if player is not the winner - } else { - return - ( - plyr_[_pID].win, - (plyr_[_pID].gen).add(getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask)), - plyr_[_pID].aff - ); - } - - // if round is still going on, or round has ended and round end has been ran - } else { - return - ( - plyr_[_pID].win, - (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), - plyr_[_pID].aff - ); - } - } - - /** - * solidity hates stack limits. this lets us avoid that hate - */ - function getPlayerVaultsHelper(uint256 _pID, uint256 _rID) - private - view - returns (uint256) - { - return (((((round_[_rID].mask).add(((((round_[_rID].pot).mul(potSplit_[round_[_rID].team].gen)) / 100).mul(1000000000000000000)) / (round_[_rID].keys))).mul(plyrRnds_[_pID][_rID].keys)) / 1000000000000000000)); - } - - /** - * @dev returns all current round info needed for front end - * -functionhash- 0x747dff42 - * @return eth invested during ICO phase - * @return round id - * @return total keys for round - * @return time round ends - * @return time round started - * @return current pot - * @return current team ID & player ID in lead - * @return current player in leads address - * @return current player in leads name - * @return whales eth in for round - * @return bears eth in for round - * @return sneks eth in for round - * @return bulls eth in for round - * @return airdrop tracker # & airdrop pot - */ - function getCurrentRoundInfo() - public - view - returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256, address, bytes32, uint256, uint256, uint256, uint256, uint256) - { - // setup local rID - uint256 _rID = rID_; - - return - ( - round_[_rID].ico, //0 - _rID, //1 - round_[_rID].keys, //2 - round_[_rID].end, //3 - round_[_rID].strt, //4 - round_[_rID].pot, //5 - (round_[_rID].team + (round_[_rID].plyr * 10)), //6 - plyr_[round_[_rID].plyr].addr, //7 - plyr_[round_[_rID].plyr].name, //8 - rndTmEth_[_rID][0], //9 - rndTmEth_[_rID][1], //10 - rndTmEth_[_rID][2], //11 - rndTmEth_[_rID][3], //12 - airDropTracker_ + (airDropPot_ * 1000) //13 - ); - } - - /** - * @dev returns player info based on address. if no address is given, it will - * use msg.sender - * -functionhash- 0xee0b5d8b - * @param _addr address of the player you want to lookup - * @return player ID - * @return player name - * @return keys owned (current round) - * @return winnings vault - * @return general vault - * @return affiliate vault - * @return player round eth - */ - function getPlayerInfoByAddress(address _addr) - public - view - returns (uint256, bytes32, uint256, uint256, uint256, uint256, uint256) - { - // setup local rID - uint256 _rID = rID_; - - if (_addr == address(0)) - { - _addr == msg.sender; - } - uint256 _pID = pIDxAddr_[_addr]; - - return - ( - _pID, //0 - plyr_[_pID].name, //1 - plyrRnds_[_pID][_rID].keys, //2 - plyr_[_pID].win, //3 - (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), //4 - plyr_[_pID].aff, //5 - plyrRnds_[_pID][_rID].eth //6 - ); - } - - //============================================================================== - // _ _ _ _ | _ _ . _ . - // (_(_)| (/_ |(_)(_||(_ . (this + tools + calcs + modules = our softwares engine) - //=====================_|======================================================= - /** - * @dev logic runs whenever a buy order is executed. determines how to handle - * incoming eth depending on if we are in an active round or not - */ - function buyCore(uint256 _pID, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) - private - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = now; - - // if round is active - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - { - // call core - core(_rID, _pID, msg.value, _affID, _team, _eventData_); - - // if round is not active - } else { - // check to see if end round needs to be ran - if (_now > round_[_rID].end && round_[_rID].ended == false) - { - // end the round (distributes pot) & start new round - round_[_rID].ended = true; - _eventData_ = endRound(_eventData_); - - // build event data - _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; - - // fire buy and distribute event - emit F3Devents.onBuyAndDistribute - ( - msg.sender, - plyr_[_pID].name, - msg.value, - _eventData_.compressedData, - _eventData_.compressedIDs, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount - ); - } - - // put eth in players vault - plyr_[_pID].gen = plyr_[_pID].gen.add(msg.value); - } - } - - /** - * @dev logic runs whenever a reload order is executed. determines how to handle - * incoming eth depending on if we are in an active round or not - */ - function reLoadCore(uint256 _pID, uint256 _affID, uint256 _team, uint256 _eth, F3Ddatasets.EventReturns memory _eventData_) - private - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = now; - - // if round is active - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - { - // get earnings from all vaults and return unused to gen vault - // because we use a custom safemath library. this will throw if player - // tried to spend more eth than they have. - plyr_[_pID].gen = withdrawEarnings(_pID).sub(_eth); - - // call core - core(_rID, _pID, _eth, _affID, _team, _eventData_); - - // if round is not active and end round needs to be ran - } else if (_now > round_[_rID].end && round_[_rID].ended == false) { - // end the round (distributes pot) & start new round - round_[_rID].ended = true; - _eventData_ = endRound(_eventData_); - - // build event data - _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; - - // fire buy and distribute event - emit F3Devents.onReLoadAndDistribute - ( - msg.sender, - plyr_[_pID].name, - _eventData_.compressedData, - _eventData_.compressedIDs, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount - ); - } - } - - /** - * @dev this is the core logic for any buy/reload that happens while a round - * is live. - */ - function core(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) - private - { - // if player is new to round - if (plyrRnds_[_pID][_rID].keys == 0) - _eventData_ = managePlayer(_pID, _eventData_); - - // early round eth limiter - if (round_[_rID].eth < 100000000000000000000 && plyrRnds_[_pID][_rID].eth.add(_eth) > 1000000000000000000) - { - uint256 _availableLimit = (1000000000000000000).sub(plyrRnds_[_pID][_rID].eth); - uint256 _refund = _eth.sub(_availableLimit); - plyr_[_pID].gen = plyr_[_pID].gen.add(_refund); - _eth = _availableLimit; - } - - // if eth left is greater than min eth allowed (sorry no pocket lint) - if (_eth > 1000000000) - { - - // mint the new keys - uint256 _keys = (round_[_rID].eth).keysRec(_eth); - - // if they bought at least 1 whole key - if (_keys >= 1000000000000000000) - { - updateTimer(_keys, _rID); - - // set new leaders - if (round_[_rID].plyr != _pID) - round_[_rID].plyr = _pID; - if (round_[_rID].team != _team) - round_[_rID].team = _team; - - // set the new leader bool to true - _eventData_.compressedData = _eventData_.compressedData + 100; - } - - // manage airdrops - if (_eth >= 100000000000000000) - { - airDropTracker_++; - if (airdrop() == true) - { - // gib muni - uint256 _prize; - if (_eth >= 10000000000000000000) - { - // calculate prize and give it to winner - _prize = ((airDropPot_).mul(75)) / 100; - plyr_[_pID].win = (plyr_[_pID].win).add(_prize); - - // adjust airDropPot - airDropPot_ = (airDropPot_).sub(_prize); - - // let event know a tier 3 prize was won - _eventData_.compressedData += 300000000000000000000000000000000; - } else if (_eth >= 1000000000000000000 && _eth < 10000000000000000000) { - // calculate prize and give it to winner - _prize = ((airDropPot_).mul(50)) / 100; - plyr_[_pID].win = (plyr_[_pID].win).add(_prize); - - // adjust airDropPot - airDropPot_ = (airDropPot_).sub(_prize); - - // let event know a tier 2 prize was won - _eventData_.compressedData += 200000000000000000000000000000000; - } else if (_eth >= 100000000000000000 && _eth < 1000000000000000000) { - // calculate prize and give it to winner - _prize = ((airDropPot_).mul(25)) / 100; - plyr_[_pID].win = (plyr_[_pID].win).add(_prize); - - // adjust airDropPot - airDropPot_ = (airDropPot_).sub(_prize); - - // let event know a tier 3 prize was won - _eventData_.compressedData += 300000000000000000000000000000000; - } - // set airdrop happened bool to true - _eventData_.compressedData += 10000000000000000000000000000000; - // let event know how much was won - _eventData_.compressedData += _prize * 1000000000000000000000000000000000; - - // reset air drop tracker - airDropTracker_ = 0; - } - } - - // store the air drop tracker number (number of buys since last airdrop) - _eventData_.compressedData = _eventData_.compressedData + (airDropTracker_ * 1000); - - // update player - plyrRnds_[_pID][_rID].keys = _keys.add(plyrRnds_[_pID][_rID].keys); - plyrRnds_[_pID][_rID].eth = _eth.add(plyrRnds_[_pID][_rID].eth); - - // update round - round_[_rID].keys = _keys.add(round_[_rID].keys); - round_[_rID].eth = _eth.add(round_[_rID].eth); - rndTmEth_[_rID][_team] = _eth.add(rndTmEth_[_rID][_team]); - - // distribute eth - _eventData_ = distributeExternal(_rID, _pID, _eth, _affID, _team, _eventData_); - _eventData_ = distributeInternal(_rID, _pID, _eth, _team, _keys, _eventData_); - - // call end tx function to fire end tx event. - endTx(_pID, _team, _eth, _keys, _eventData_); - } - } - //============================================================================== - // _ _ | _ | _ _|_ _ _ _ . - // (_(_||(_|_||(_| | (_)| _\ . - //============================================================================== - /** - * @dev calculates unmasked earnings (just calculates, does not update mask) - * @return earnings in wei format - */ - function calcUnMaskedEarnings(uint256 _pID, uint256 _rIDlast) - private - view - returns (uint256) - { - return ((((round_[_rIDlast].mask).mul(plyrRnds_[_pID][_rIDlast].keys)) / (1000000000000000000)).sub(plyrRnds_[_pID][_rIDlast].mask)); - } - - /** - * @dev returns the amount of keys you would get given an amount of eth. - * -functionhash- 0xce89c80c - * @param _rID round ID you want price for - * @param _eth amount of eth sent in - * @return keys received - */ - function calcKeysReceived(uint256 _rID, uint256 _eth) - public - view - returns (uint256) - { - // grab time - uint256 _now = now; - - // are we in a round? - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - return ((round_[_rID].eth).keysRec(_eth)); - else // rounds over. need keys for new round - return ((_eth).keys()); - } - - /** - * @dev returns current eth price for X keys. - * -functionhash- 0xcf808000 - * @param _keys number of keys desired (in 18 decimal format) - * @return amount of eth needed to send - */ - function iWantXKeys(uint256 _keys) - public - view - returns (uint256) - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = now; - - // are we in a round? - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - return ((round_[_rID].keys.add(_keys)).ethRec(_keys)); - else // rounds over. need price for new round - return ((_keys).eth()); - } - //============================================================================== - // _|_ _ _ | _ . - // | (_)(_)|_\ . - //============================================================================== - /** - * @dev receives name/player info from names contract - */ - function receivePlayerInfo(uint256 _pID, address payable _addr, bytes32 _name, uint256 _laff) - external - { - require(msg.sender == address(playerBook), "your not playerNames contract... hmmm.."); - if (pIDxAddr_[_addr] != _pID) - pIDxAddr_[_addr] = _pID; - if (pIDxName_[_name] != _pID) - pIDxName_[_name] = _pID; - if (plyr_[_pID].addr != _addr) - plyr_[_pID].addr = _addr; - if (plyr_[_pID].name != _name) - plyr_[_pID].name = _name; - if (plyr_[_pID].laff != _laff) - plyr_[_pID].laff = _laff; - if (plyrNames_[_pID][_name] == false) - plyrNames_[_pID][_name] = true; - } - - /** - * @dev receives entire player name list - */ - function receivePlayerNameList(uint256 _pID, bytes32 _name) - external - { - require(msg.sender == address(playerBook), "your not playerNames contract... hmmm.."); - if (plyrNames_[_pID][_name] == false) - plyrNames_[_pID][_name] = true; - } - - /** - * @dev gets existing or registers new pID. use this when a player may be new - * @return pID - */ - function determinePID(F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - uint256 _pID = pIDxAddr_[msg.sender]; - // if player is new to this version of fomo3d - if (_pID == 0) - { - // grab their player ID, name and last aff ID, from player names contract - _pID = playerBook.getPlayerID(msg.sender); - bytes32 _name = playerBook.getPlayerName(_pID); - uint256 _laff = playerBook.getPlayerLAff(_pID); - - // set up player account - pIDxAddr_[msg.sender] = _pID; - plyr_[_pID].addr = msg.sender; - - if (_name != "") - { - pIDxName_[_name] = _pID; - plyr_[_pID].name = _name; - plyrNames_[_pID][_name] = true; - } - - if (_laff != 0 && _laff != _pID) - plyr_[_pID].laff = _laff; - - // set the new player bool to true - _eventData_.compressedData = _eventData_.compressedData + 1; - } - return (_eventData_); - } - - /** - * @dev checks to make sure user picked a valid team. if not sets team - * to default (sneks) - */ - function verifyTeam(uint256 _team) - private - pure - returns (uint256) - { - if (_team < 0 || _team > 3) - return (2); - else - return (_team); - } - - /** - * @dev decides if round end needs to be run & new round started. and if - * player unmasked earnings from previously played rounds need to be moved. - */ - function managePlayer(uint256 _pID, F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - // if player has played a previous round, move their unmasked earnings - // from that round to gen vault. - if (plyr_[_pID].lrnd != 0) - updateGenVault(_pID, plyr_[_pID].lrnd); - - // update player's last round played - plyr_[_pID].lrnd = rID_; - - // set the joined round bool to true - _eventData_.compressedData = _eventData_.compressedData + 10; - - return (_eventData_); - } - - /** - * @dev ends the round. manages paying out winner/splitting up pot - */ - function endRound(F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - // setup local rID - uint256 _rID = rID_; - - // grab our winning player and team id's - uint256 _winPID = round_[_rID].plyr; - uint256 _winTID = round_[_rID].team; - - // grab our pot amount - uint256 _pot = round_[_rID].pot; - - // calculate our winner share, community rewards, gen share, - // p3d share, and amount reserved for next pot - uint256 _win = (_pot.mul(48)) / 100; - uint256 _com = (_pot / 50); - uint256 _gen = (_pot.mul(potSplit_[_winTID].gen)) / 100; - uint256 _p3d = (_pot.mul(potSplit_[_winTID].p3d)) / 100; - uint256 _res = (((_pot.sub(_win)).sub(_com)).sub(_gen)).sub(_p3d); - - // calculate ppt for round mask - uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); - uint256 _dust = _gen.sub((_ppt.mul(round_[_rID].keys)) / 1000000000000000000); - if (_dust > 0) - { - _gen = _gen.sub(_dust); - _res = _res.add(_dust); - } - - // pay our winner - plyr_[_winPID].win = _win.add(plyr_[_winPID].win); - - // community rewards - address payable add = address(uint160(Jekyll_Island_Inc)); - if (!add.send(_com)) - { - // This ensures Team Just cannot influence the outcome of FoMo3D with - // bank migrations by breaking outgoing transactions. - // Something we would never do. But that's not the point. - // We spent 2000$ in eth re-deploying just to patch this, we hold the - // highest belief that everything we create should be trustless. - // Team JUST, The name you shouldn't have to trust. - _p3d = _p3d.add(_com); - _com = 0; - } - - // distribute gen portion to key holders - round_[_rID].mask = _ppt.add(round_[_rID].mask); - - // send share for p3d to divies - if (_p3d > 0){ - address payable addr = address(uint160(Divies)); - addr.transfer(_p3d); - } - // prepare event data - _eventData_.compressedData = _eventData_.compressedData + (round_[_rID].end * 1000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + (_winPID * 100000000000000000000000000) + (_winTID * 100000000000000000); - _eventData_.winnerAddr = plyr_[_winPID].addr; - _eventData_.winnerName = plyr_[_winPID].name; - _eventData_.amountWon = _win; - _eventData_.genAmount = _gen; - _eventData_.P3DAmount = _p3d; - _eventData_.newPot = _res; - - // start next round - rID_++; - _rID++; - round_[_rID].strt = now; - round_[_rID].end = now.add(rndInit_).add(rndGap_); - round_[_rID].pot = _res; - - return (_eventData_); - } - - /** - * @dev moves any unmasked earnings to gen vault. updates earnings mask - */ - function updateGenVault(uint256 _pID, uint256 _rIDlast) - private - { - uint256 _earnings = calcUnMaskedEarnings(_pID, _rIDlast); - if (_earnings > 0) - { - // put in gen vault - plyr_[_pID].gen = _earnings.add(plyr_[_pID].gen); - // zero out their earnings by updating mask - plyrRnds_[_pID][_rIDlast].mask = _earnings.add(plyrRnds_[_pID][_rIDlast].mask); - } - } - - /** - * @dev updates round timer based on number of whole keys bought. - */ - function updateTimer(uint256 _keys, uint256 _rID) - private - { - // grab time - uint256 _now = now; - - // calculate time based on number of keys bought - uint256 _newTime; - if (_now > round_[_rID].end && round_[_rID].plyr == 0) - _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(_now); - else - _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(round_[_rID].end); - - // compare to max and set new end time - if (_newTime < (rndMax_).add(_now)) - round_[_rID].end = _newTime; - else - round_[_rID].end = rndMax_.add(_now); - } - - /** - * @dev generates a random number between 0-99 and checks to see if thats - * resulted in an airdrop win - * @return do we have a winner? - */ - function airdrop() - private - view - returns (bool) - { - uint256 seed = uint256(keccak256(abi.encodePacked( - - (block.timestamp).add - (block.difficulty).add - ((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)).add - (block.gaslimit).add - ((uint256(keccak256(abi.encodePacked(msg.sender)))) / (now)).add - (block.number) - - ))); - if ((seed - ((seed / 1000) * 1000)) < airDropTracker_) - return (true); - else - return (false); - } - - /** - * @dev distributes eth based on fees to com, aff, and p3d - */ - function distributeExternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - // pay 2% out to community rewards - uint256 _com = _eth / 50; - uint256 _p3d; - address payable addr = address(uint160(Jekyll_Island_Inc)); - if (!addr.send(_com)) - { - // This ensures Team Just cannot influence the outcome of FoMo3D with - // bank migrations by breaking outgoing transactions. - // Something we would never do. But that's not the point. - // We spent 2000$ in eth re-deploying just to patch this, we hold the - // highest belief that everything we create should be trustless. - // Team JUST, The name you shouldn't have to trust. - _p3d = _com; - _com = 0; - } - - // pay 1% out to FoMo3D short - _com = _eth / 100; - address payable add = address(uint160(otherF3D_)); - add.transfer(_com); - - // distribute share to affiliate - _com = _eth / 10; - - // decide what to do with affiliate share of fees - // affiliate must not be self, and must have a name registered - if (_affID != _pID && plyr_[_affID].name != '') { - plyr_[_affID].aff = _com.add(plyr_[_affID].aff); - emit F3Devents.onAffiliatePayout(_affID, plyr_[_affID].addr, plyr_[_affID].name, _rID, _pID, _com, now); - } else { - _p3d = _com; - } - - // pay out p3d - _p3d = _p3d.add((_eth.mul(fees_[_team].p3d)) / (100)); - if (_p3d > 0) - { - // deposit to divies contract - address payable add = address(uint160(Divies)); - add.transfer(_p3d); - - // set up event data - _eventData_.P3DAmount = _p3d.add(_eventData_.P3DAmount); - } - - return (_eventData_); - } - - function potSwap() - external - payable - { - // setup local rID - uint256 _rID = rID_ + 1; - - round_[_rID].pot = round_[_rID].pot.add(msg.value); - emit F3Devents.onPotSwapDeposit(_rID, msg.value); - } - - /** - * @dev distributes eth based on fees to gen and pot - */ - function distributeInternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _team, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - // calculate gen share - uint256 _gen = (_eth.mul(fees_[_team].gen)) / 100; - - // toss 1% into airdrop pot - uint256 _air = (_eth / 100); - airDropPot_ = airDropPot_.add(_air); - - // update eth balance (eth = eth - (com share + pot swap share + aff share + p3d share + airdrop pot share)) - _eth = _eth.sub(((_eth.mul(14)) / 100).add((_eth.mul(fees_[_team].p3d)) / 100)); - - // calculate pot - uint256 _pot = _eth.sub(_gen); - - // distribute gen share (thats what updateMasks() does) and adjust - // balances for dust. - uint256 _dust = updateMasks(_rID, _pID, _gen, _keys); - if (_dust > 0) - _gen = _gen.sub(_dust); - - // add eth to pot - round_[_rID].pot = _pot.add(_dust).add(round_[_rID].pot); - - // set up event data - _eventData_.genAmount = _gen.add(_eventData_.genAmount); - _eventData_.potAmount = _pot; - - return (_eventData_); - } - - /** - * @dev updates masks for round and player when keys are bought - * @return dust left over - */ - function updateMasks(uint256 _rID, uint256 _pID, uint256 _gen, uint256 _keys) - private - returns (uint256) - { - /* MASKING NOTES - earnings masks are a tricky thing for people to wrap their minds around. - the basic thing to understand here. is were going to have a global - tracker based on profit per share for each round, that increases in - relevant proportion to the increase in share supply. - - the player will have an additional mask that basically says "based - on the rounds mask, my shares, and how much i've already withdrawn, - how much is still owed to me?" - */ - - // calc profit per key & round mask based on this buy: (dust goes to pot) - uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); - round_[_rID].mask = _ppt.add(round_[_rID].mask); - - // calculate player earning from their own buy (only based on the keys - // they just bought). & update player earnings mask - uint256 _pearn = (_ppt.mul(_keys)) / (1000000000000000000); - plyrRnds_[_pID][_rID].mask = (((round_[_rID].mask.mul(_keys)) / (1000000000000000000)).sub(_pearn)).add(plyrRnds_[_pID][_rID].mask); - - // calculate & return dust - return (_gen.sub((_ppt.mul(round_[_rID].keys)) / (1000000000000000000))); - } - - /** - * @dev adds up unmasked earnings, & vault earnings, sets them all to 0 - * @return earnings in wei format - */ - function withdrawEarnings(uint256 _pID) - private - returns (uint256) - { - // update gen vault - updateGenVault(_pID, plyr_[_pID].lrnd); - - // from vaults - uint256 _earnings = (plyr_[_pID].win).add(plyr_[_pID].gen).add(plyr_[_pID].aff); - if (_earnings > 0) - { - plyr_[_pID].win = 0; - plyr_[_pID].gen = 0; - plyr_[_pID].aff = 0; - } - - return (_earnings); - } - - /** - * @dev prepares compression data and fires event for buy or reload tx's - */ - function endTx(uint256 _pID, uint256 _team, uint256 _eth, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) - private - { - _eventData_.compressedData = _eventData_.compressedData + (now * 1000000000000000000) + (_team * 100000000000000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID + (rID_ * 10000000000000000000000000000000000000000000000000000); - - emit F3Devents.onEndTx - ( - _eventData_.compressedData, - _eventData_.compressedIDs, - plyr_[_pID].name, - msg.sender, - _eth, - _keys, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount, - _eventData_.potAmount, - airDropPot_ - ); - } - //============================================================================== - // (~ _ _ _._|_ . - // _)(/_(_|_|| | | \/ . - //====================/========================================================= - /** upon contract deploy, it will be deactivated. this is a one time - * use function that will activate the contract. we do this so devs - * have time to set things up on the web end **/ - bool public activated_ = false; - - function activate() - public - onlyDevs - { - - // can only be ran once - require(activated_ == false, "fomo3d already activated"); - - // activate the contract - activated_ = true; - - otherF3D_ = msg.sender; - Divies = msg.sender; - Jekyll_Island_Inc = msg.sender; - - // lets start first round - rID_ = 1; - round_[1].strt = now + rndExtra_ - rndGap_; - round_[1].end = now + rndInit_ + rndExtra_; - } - - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractScenario007.sol b/framework/src/test/resources/soliditycode_0.5.15/contractScenario007.sol deleted file mode 100644 index 1e6ff5d7250..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractScenario007.sol +++ /dev/null @@ -1,1433 +0,0 @@ -//pragma solidity 0.4.24; - -/** - * @title ERC165 - * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md - */ -interface ERC165 { - - /** - * @notice Query if a contract implements an interface - * @param _interfaceId The interface identifier, as specified in ERC-165 - * @dev Interface identification is specified in ERC-165. This function - * uses less than 30,000 gas. - */ - function supportsInterface(bytes4 _interfaceId) external view returns (bool); - -} - -contract ERC721Basic is ERC165 { - - event Transfer( - address indexed _from, - address indexed _to, - uint256 indexed _tokenId - ); - event Approval( - address indexed _owner, - address indexed _approved, - uint256 indexed _tokenId - ); - event ApprovalForAll( - address indexed _owner, - address indexed _operator, - bool _approved - ); - - function balanceOf(address _owner) public view returns (uint256 _balance); - function ownerOf(uint256 _tokenId) public view returns (address _owner); - function exists(uint256 _tokenId) public view returns (bool _exists); - - function approve(address _to, uint256 _tokenId) public; - function getApproved(uint256 _tokenId) - public view returns (address _operator); - - function setApprovalForAll(address _operator, bool _approved) public; - function isApprovedForAll(address _owner, address _operator) - public view returns (bool); - - function transferFrom(address _from, address _to, uint256 _tokenId) public; - function safeTransferFrom(address _from, address _to, uint256 _tokenId) - public; - - function safeTransferFrom( - address _from, - address _to, - uint256 _tokenId, - bytes memory _data - ) - public; -} - - -/** - * @title SupportsInterfaceWithLookup - * @author Matt Condon (@shrugs) - * @dev Implements ERC165 using a lookup table. - */ -contract SupportsInterfaceWithLookup is ERC165 { - bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7; - /** - * 0x01ffc9a7 === - * bytes4(keccak256('supportsInterface(bytes4)')) - */ - - /** - * @dev a mapping of interface id to whether or not it's supported - */ - mapping(bytes4 => bool) internal supportedInterfaces; - - /** - * @dev A contract implementing SupportsInterfaceWithLookup - * implement ERC165 itself - */ - constructor() public { - _registerInterface(InterfaceId_ERC165); - } - - /** - * @dev implement supportsInterface(bytes4) using a lookup table - */ - function supportsInterface(bytes4 _interfaceId) external view returns (bool) { - return supportedInterfaces[_interfaceId]; - } - - /** - * @dev private method for registering an interface - */ - function _registerInterface(bytes4 _interfaceId) internal { - require(_interfaceId != 0xffffffff); - supportedInterfaces[_interfaceId] = true; - } -} - -contract Governable { - - event Pause(); - event Unpause(); - - address public governor; - bool public paused = false; - - constructor() public { - governor = msg.sender; - } - - function setGovernor(address _gov) public onlyGovernor { - governor = _gov; - } - - modifier onlyGovernor { - require(msg.sender == governor); - _; - } - - /** - * @dev Modifier to make a function callable only when the contract is not paused. - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev Modifier to make a function callable only when the contract is paused. - */ - modifier whenPaused() { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyGovernor whenNotPaused public { - paused = true; - emit Pause(); - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyGovernor whenPaused public { - paused = false; - emit Unpause(); - } - -} - -contract CardBase is Governable { - - struct Card { - uint16 proto; - uint16 purity; - } - - function getCard(uint id) public view returns (uint16 proto, uint16 purity) { - Card memory card = cards[id]; - return (card.proto, card.purity); - } - - function getShine(uint16 purity) public pure returns (uint8) { - return uint8(purity / 1000); - } - - Card[] public cards; - -} - -contract CardProto is CardBase { - - event NewProtoCard( - uint16 id, uint8 season, uint8 god, - Rarity rarity, uint8 mana, uint8 attack, - uint8 health, uint8 cardType, uint8 tribe, bool packable - ); - - struct Limit { - uint64 limit; - bool exists; - } - - // limits for mythic cards - mapping(uint16 => Limit) public limits; - - // can only set limits once - function setLimit(uint16 id, uint64 limit) public onlyGovernor { - Limit memory l = limits[id]; - require(!l.exists); - limits[id] = Limit({ - limit: limit, - exists: true - }); - } - - function getLimit(uint16 id) public view returns (uint64 limit, bool set) { - Limit memory l = limits[id]; - return (l.limit, l.exists); - } - - // could make these arrays to save gas - // not really necessary - will be update a very limited no of times - mapping(uint8 => bool) public seasonTradable; - mapping(uint8 => bool) public seasonTradabilityLocked; - uint8 public currentSeason; - - function makeTradable(uint8 season) public onlyGovernor { - seasonTradable[season] = true; - } - - function makeUntradable(uint8 season) public onlyGovernor { - require(!seasonTradabilityLocked[season]); - seasonTradable[season] = false; - } - - function makePermanantlyTradable(uint8 season) public onlyGovernor { - require(seasonTradable[season]); - seasonTradabilityLocked[season] = true; - } - - function isTradable(uint16 proto) public view returns (bool) { - return seasonTradable[protos[proto].season]; - } - - function nextSeason() public onlyGovernor { - //Seasons shouldn't go to 0 if there is more than the uint8 should hold, the governor should know this ¯\_(ツ)_/¯ -M - require(currentSeason <= 255); - - currentSeason++; - mythic.length = 0; - legendary.length = 0; - epic.length = 0; - rare.length = 0; - common.length = 0; - } - - enum Rarity { - Common, - Rare, - Epic, - Legendary, - Mythic - } - - uint8 constant SPELL = 1; - uint8 constant MINION = 2; - uint8 constant WEAPON = 3; - uint8 constant HERO = 4; - - struct ProtoCard { - bool exists; - uint8 god; - uint8 season; - uint8 cardType; - Rarity rarity; - uint8 mana; - uint8 attack; - uint8 health; - uint8 tribe; - } - - // there is a particular design decision driving this: - // need to be able to iterate over mythics only for card generation - // don't store 5 different arrays: have to use 2 ids - // better to bear this cost (2 bytes per proto card) - // rather than 1 byte per instance - - uint16 public protoCount; - - mapping(uint16 => ProtoCard) protos; - - uint16[] public mythic; - uint16[] public legendary; - uint16[] public epic; - uint16[] public rare; - uint16[] public common; - - function addProtos( - uint16[] memory externalIDs, uint8[] memory gods, Rarity[] memory rarities, uint8[] memory manas, uint8[] memory attacks, - uint8[] memory healths, uint8[] memory cardTypes, uint8[] memory tribes, bool[] memory packable - ) public onlyGovernor returns(uint16) { - - for (uint i = 0; i < externalIDs.length; i++) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: gods[i], - season: currentSeason, - cardType: cardTypes[i], - rarity: rarities[i], - mana: manas[i], - attack: attacks[i], - health: healths[i], - tribe: tribes[i] - }); - - _addProto(externalIDs[i], card, packable[i]); - } - - } - - function addProto( - uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 cardType, uint8 tribe, bool packable - ) public onlyGovernor returns(uint16) { - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: cardType, - rarity: rarity, - mana: mana, - attack: attack, - health: health, - tribe: tribe - }); - - _addProto(externalID, card, packable); - } - - function addWeapon( - uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 durability, bool packable - ) public onlyGovernor returns(uint16) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: WEAPON, - rarity: rarity, - mana: mana, - attack: attack, - health: durability, - tribe: 0 - }); - - _addProto(externalID, card, packable); - } - - function addSpell(uint16 externalID, uint8 god, Rarity rarity, uint8 mana, bool packable) public onlyGovernor returns(uint16) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: SPELL, - rarity: rarity, - mana: mana, - attack: 0, - health: 0, - tribe: 0 - }); - - _addProto(externalID, card, packable); - } - - function addMinion( - uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 tribe, bool packable - ) public onlyGovernor returns(uint16) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: MINION, - rarity: rarity, - mana: mana, - attack: attack, - health: health, - tribe: tribe - }); - - _addProto(externalID, card, packable); - } - - function _addProto(uint16 externalID, ProtoCard memory card, bool packable) internal { - - require(!protos[externalID].exists); - - card.exists = true; - - protos[externalID] = card; - - protoCount++; - - emit NewProtoCard( - externalID, currentSeason, card.god, - card.rarity, card.mana, card.attack, - card.health, card.cardType, card.tribe, packable - ); - - if (packable) { - Rarity rarity = card.rarity; - if (rarity == Rarity.Common) { - common.push(externalID); - } else if (rarity == Rarity.Rare) { - rare.push(externalID); - } else if (rarity == Rarity.Epic) { - epic.push(externalID); - } else if (rarity == Rarity.Legendary) { - legendary.push(externalID); - } else if (rarity == Rarity.Mythic) { - mythic.push(externalID); - } else { - require(false); - } - } - } - - function getProto(uint16 id) public view returns( - bool exists, uint8 god, uint8 season, uint8 cardType, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 tribe - ) { - ProtoCard memory proto = protos[id]; - return ( - proto.exists, - proto.god, - proto.season, - proto.cardType, - proto.rarity, - proto.mana, - proto.attack, - proto.health, - proto.tribe - ); - } - - function getRandomCard(Rarity rarity, uint16 random) public view returns (uint16) { - // modulo bias is fine - creates rarity tiers etc - // will obviously revert is there are no cards of that type: this is expected - should never happen - if (rarity == Rarity.Common) { - return common[random % common.length]; - } else if (rarity == Rarity.Rare) { - return rare[random % rare.length]; - } else if (rarity == Rarity.Epic) { - return epic[random % epic.length]; - } else if (rarity == Rarity.Legendary) { - return legendary[random % legendary.length]; - } else if (rarity == Rarity.Mythic) { - // make sure a mythic is available - uint16 id; - uint64 limit; - bool set; - for (uint i = 0; i < mythic.length; i++) { - id = mythic[(random + i) % mythic.length]; - (limit, set) = getLimit(id); - if (set && limit > 0){ - return id; - } - } - // if not, they get a legendary :( - return legendary[random % legendary.length]; - } - require(false); - return 0; - } - - // can never adjust tradable cards - // each season gets a 'balancing beta' - // totally immutable: season, rarity - function replaceProto( - uint16 index, uint8 god, uint8 cardType, uint8 mana, uint8 attack, uint8 health, uint8 tribe - ) public onlyGovernor { - ProtoCard memory pc = protos[index]; - require(!seasonTradable[pc.season]); - protos[index] = ProtoCard({ - exists: true, - god: god, - season: pc.season, - cardType: cardType, - rarity: pc.rarity, - mana: mana, - attack: attack, - health: health, - tribe: tribe - }); - } - -} - -contract ERC721Receiver { - /** - * @dev Magic value to be returned upon successful reception of an NFT - * Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`, - * which can be also obtained as `ERC721Receiver(0).onERC721Received.selector` - */ - bytes4 internal constant ERC721_RECEIVED = 0x150b7a02; - - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a `safetransfer`. This function MAY throw to revert and reject the - * transfer. Return of other than the magic value MUST result in the - * transaction being reverted. - * Note: the contract address is always the message sender. - * @param _operator The address which called `safeTransferFrom` function - * @param _from The address which previously owned the token - * @param _tokenId The NFT identifier which is being transfered - * @param _data Additional data with no specified format - * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - */ - function onERC721Received( - address _operator, - address _from, - uint256 _tokenId, - bytes memory _data - ) - public - returns(bytes4); -} - -library AddressUtils { - - /** - * Returns whether the target address is a contract - * @dev This function will return false if invoked during the constructor of a contract, - * as the code is not actually created until after the constructor finishes. - * @param addr address to check - * @return whether the target address is a contract - */ - function isContract1(address addr) internal view returns (bool) { - uint256 size; - // XXX Currently there is no better way to check if there is a contract in an address - // than to check the size of the code at that address. - // See https://ethereum.stackexchange.com/a/14016/36603 - // for more details about how this works. - // TODO Check this again before the Serenity release, because all addresses will be - // contracts then. - // solium-disable-next-line security/no-inline-assembly - assembly { size := extcodesize(addr) } - return size > 0; - } - -} - -library SafeMath { - - /** - * @dev Multiplies two numbers, throws on overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { - // Gas optimization: this is cheaper than asserting 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - c = a * b; - assert(c / a == b); - return c; - } - - /** - * @dev Integer division of two numbers, truncating the quotient. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // assert(b > 0); // Solidity automatically throws when dividing by 0 - // uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - return a / b; - } - - /** - * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - assert(b <= a); - return a - b; - } - - /** - * @dev Adds two numbers, throws on overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256 c) { - c = a + b; - assert(c >= a); - return c; - } -} - -contract ERC721BasicToken is CardProto, SupportsInterfaceWithLookup, ERC721Basic { - - bytes4 private constant InterfaceId_ERC721 = 0x80ac58cd; - /* - * 0x80ac58cd === - * bytes4(keccak256('balanceOf(address)')) ^ - * bytes4(keccak256('ownerOf(uint256)')) ^ - * bytes4(keccak256('approve(address,uint256)')) ^ - * bytes4(keccak256('getApproved(uint256)')) ^ - * bytes4(keccak256('setApprovalForAll(address,bool)')) ^ - * bytes4(keccak256('isApprovedForAll(address,address)')) ^ - * bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^ - * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) - */ - - bytes4 private constant InterfaceId_ERC721Exists = 0x4f558e79; - /* - * 0x4f558e79 === - * bytes4(keccak256('exists(uint256)')) - */ - - using SafeMath for uint256; - using AddressUtils for address; - - // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - // which can be also obtained as `ERC721Receiver(0).onERC721Received.selector` - bytes4 private constant ERC721_RECEIVED = 0x150b7a02; - - // Mapping from token ID to owner - mapping (uint256 => address) internal tokenOwner; - - // Mapping from token ID to approved address - mapping (uint256 => address) internal tokenApprovals; - - // Mapping from owner to number of owned token - // mapping (address => uint256) internal ownedTokensCount; - - // Mapping from owner to operator approvals - mapping (address => mapping (address => bool)) internal operatorApprovals; - - /** - * @dev Guarantees msg.sender is owner of the given token - * @param _tokenId uint256 ID of the token to validate its ownership belongs to msg.sender - */ - modifier onlyOwnerOf(uint256 _tokenId) { - require(ownerOf(_tokenId) == msg.sender); - _; - } - - /** - * @dev Checks msg.sender can transfer a token, by being owner, approved, or operator - * @param _tokenId uint256 ID of the token to validate - */ - modifier canTransfer(uint256 _tokenId) { - require(isApprovedOrOwner(msg.sender, _tokenId)); - _; - } - - constructor() - public - { - // register the supported interfaces to conform to ERC721 via ERC165 - _registerInterface(InterfaceId_ERC721); - _registerInterface(InterfaceId_ERC721Exists); - } - - /** - * @dev Gets the balance of the specified address - * @param _owner address to query the balance of - * @return uint256 representing the amount owned by the passed address - */ - function balanceOf(address _owner) public view returns (uint256); - - /** - * @dev Gets the owner of the specified token ID - * @param _tokenId uint256 ID of the token to query the owner of - * @return owner address currently marked as the owner of the given token ID - */ - function ownerOf(uint256 _tokenId) public view returns (address) { - address owner = tokenOwner[_tokenId]; - require(owner != address(0)); - return owner; - } - - /** - * @dev Returns whether the specified token exists - * @param _tokenId uint256 ID of the token to query the existence of - * @return whether the token exists - */ - function exists(uint256 _tokenId) public view returns (bool) { - address owner = tokenOwner[_tokenId]; - return owner != address(0); - } - - /** - * @dev Approves another address to transfer the given token ID - * The zero address indicates there is no approved address. - * There can only be one approved address per token at a given time. - * Can only be called by the token owner or an approved operator. - * @param _to address to be approved for the given token ID - * @param _tokenId uint256 ID of the token to be approved - */ - function approve(address _to, uint256 _tokenId) public { - address owner = ownerOf(_tokenId); - require(_to != owner); - require(msg.sender == owner || isApprovedForAll(owner, msg.sender)); - - tokenApprovals[_tokenId] = _to; - emit Approval(owner, _to, _tokenId); - } - - /** - * @dev Gets the approved address for a token ID, or zero if no address set - * @param _tokenId uint256 ID of the token to query the approval of - * @return address currently approved for the given token ID - */ - function getApproved(uint256 _tokenId) public view returns (address) { - return tokenApprovals[_tokenId]; - } - - /** - * @dev Sets or unsets the approval of a given operator - * An operator is allowed to transfer all tokens of the sender on their behalf - * @param _to operator address to set the approval - * @param _approved representing the status of the approval to be set - */ - function setApprovalForAll(address _to, bool _approved) public { - require(_to != msg.sender); - operatorApprovals[msg.sender][_to] = _approved; - emit ApprovalForAll(msg.sender, _to, _approved); - } - - /** - * @dev Tells whether an operator is approved by a given owner - * @param _owner owner address which you want to query the approval of - * @param _operator operator address which you want to query the approval of - * @return bool whether the given operator is approved by the given owner - */ - function isApprovedForAll( - address _owner, - address _operator - ) - public - view - returns (bool) - { - return operatorApprovals[_owner][_operator]; - } - - /** - * @dev Transfers the ownership of a given token ID to another address - * Usage of this method is discouraged, use `safeTransferFrom` whenever possible - * Requires the msg sender to be the owner, approved, or operator - * @param _from current owner of the token - * @param _to address to receive the ownership of the given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - public - canTransfer(_tokenId) - { - require(_from != address(0)); - require(_to != address(0)); - - clearApproval(_from, _tokenId); - removeTokenFrom(_from, _tokenId); - addTokenTo(_to, _tokenId); - - emit Transfer(_from, _to, _tokenId); - } - - /** - * @dev Safely transfers the ownership of a given token ID to another address - * If the target address is a contract, it must implement `onERC721Received`, - * which is called upon a safe transfer, and return the magic value - * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, - * the transfer is reverted. - * - * Requires the msg sender to be the owner, approved, or operator - * @param _from current owner of the token - * @param _to address to receive the ownership of the given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function safeTransferFrom( - address _from, - address _to, - uint256 _tokenId - ) - public - canTransfer(_tokenId) - { - // solium-disable-next-line arg-overflow - safeTransferFrom(_from, _to, _tokenId, ""); - } - - /** - * @dev Safely transfers the ownership of a given token ID to another address - * If the target address is a contract, it must implement `onERC721Received`, - * which is called upon a safe transfer, and return the magic value - * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, - * the transfer is reverted. - * Requires the msg sender to be the owner, approved, or operator - * @param _from current owner of the token - * @param _to address to receive the ownership of the given token ID - * @param _tokenId uint256 ID of the token to be transferred - * @param _data bytes data to send along with a safe transfer check - */ - function safeTransferFrom( - address _from, - address _to, - uint256 _tokenId, - bytes memory _data - ) - public - canTransfer(_tokenId) - { - transferFrom(_from, _to, _tokenId); - // solium-disable-next-line arg-overflow - require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data)); - } - - /** - * @dev Returns whether the given spender can transfer a given token ID - * @param _spender address of the spender to query - * @param _tokenId uint256 ID of the token to be transferred - * @return bool whether the msg.sender is approved for the given token ID, - * is an operator of the owner, or is the owner of the token - */ - function isApprovedOrOwner( - address _spender, - uint256 _tokenId - ) - internal - view - returns (bool) - { - address owner = ownerOf(_tokenId); - // Disable solium check because of - // https://github.com/duaraghav8/Solium/issues/175 - // solium-disable-next-line operator-whitespace - return ( - _spender == owner || - getApproved(_tokenId) == _spender || - isApprovedForAll(owner, _spender) - ); - } - - /** - * @dev Internal function to clear current approval of a given token ID - * Reverts if the given address is not indeed the owner of the token - * @param _owner owner of the token - * @param _tokenId uint256 ID of the token to be transferred - */ - function clearApproval(address _owner, uint256 _tokenId) internal { - require(ownerOf(_tokenId) == _owner); - if (tokenApprovals[_tokenId] != address(0)) { - tokenApprovals[_tokenId] = address(0); - } - } - - /** - * @dev Internal function to mint a new token - * Reverts if the given token ID already exists - * @param _to The address that will own the minted token - * @param _tokenId uint256 ID of the token to be minted by the msg.sender - */ - function _mint(address _to, uint256 _tokenId) internal { - require(_to != address(0)); - addNewTokenTo(_to, _tokenId); - emit Transfer(address(0), _to, _tokenId); - } - - - /** - * @dev Internal function to burn a specific token - * Reverts if the token does not exist - * @param _tokenId uint256 ID of the token being burned by the msg.sender - */ - function _burn(address _owner, uint256 _tokenId) internal { - clearApproval(_owner, _tokenId); - removeTokenFrom(_owner, _tokenId); - emit Transfer(_owner, address(0), _tokenId); - } - - function addNewTokenTo(address _to, uint256 _tokenId) internal { - require(tokenOwner[_tokenId] == address(0)); - tokenOwner[_tokenId] = _to; - } - - /** - * @dev Internal function to add a token ID to the list of a given address - * @param _to address representing the new owner of the given token ID - * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address - */ - function addTokenTo(address _to, uint256 _tokenId) internal { - require(tokenOwner[_tokenId] == address(0)); - tokenOwner[_tokenId] = _to; - // ownedTokensCount[_to] = ownedTokensCount[_to].add(1); - } - - /** - * @dev Internal function to remove a token ID from the list of a given address - * @param _from address representing the previous owner of the given token ID - * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address - */ - function removeTokenFrom(address _from, uint256 _tokenId) internal { - require(ownerOf(_tokenId) == _from); - // ownedTokensCount[_from] = ownedTokensCount[_from].sub(1); - tokenOwner[_tokenId] = address(0); - } - - /** - * @dev Internal function to invoke `onERC721Received` on a target address - * The call is not executed if the target address is not a contract - * @param _from address representing the previous owner of the given token ID - * @param _to target address that will receive the tokens - * @param _tokenId uint256 ID of the token to be transferred - * @param _data bytes optional data to send along with the call - * @return whether the call correctly returned the expected magic value - */ - function checkAndCallSafeTransfer( - address _from, - address _to, - uint256 _tokenId, - bytes memory _data - ) - internal - returns (bool) - { - if (!_to.isContract1()) { - return true; - } - bytes4 retval = ERC721Receiver(_to).onERC721Received( - msg.sender, _from, _tokenId, _data); - return (retval == ERC721_RECEIVED); - } - -} - - - -contract ERC721Enumerable is ERC721Basic { - function totalSupply() public view returns (uint256); - function tokenOfOwnerByIndex( - address _owner, - uint256 _index - ) - public - view - returns (uint256 _tokenId); - - function tokenByIndex(uint256 _index) public view returns (uint256); -} - -contract ERC721Metadata is ERC721Basic { - function name() external view returns (string memory _name); - function symbol() external view returns (string memory _symbol); - function tokenURI(uint256 _tokenId) public view returns (string memory); -} - -contract ERC721 is ERC721Basic, ERC721Enumerable, ERC721Metadata { - -} - - - - -library Strings { - - // via https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol - function strConcat(string memory _a, string memory _b, string memory _c, string memory _d, string memory _e) internal pure returns (string memory ) { - bytes memory _ba = bytes(_a); - bytes memory _bb = bytes(_b); - bytes memory _bc = bytes(_c); - bytes memory _bd = bytes(_d); - bytes memory _be = bytes(_e); - string memory abcde = new string(_ba.length + _bb.length + _bc.length + _bd.length + _be.length); - bytes memory babcde = bytes(abcde); - uint k = 0; - for (uint i = 0; i < _ba.length; i++) babcde[k++] = _ba[i]; - for (uint i = 0; i < _bb.length; i++) babcde[k++] = _bb[i]; - for (uint i = 0; i < _bc.length; i++) babcde[k++] = _bc[i]; - for (uint i = 0; i < _bd.length; i++) babcde[k++] = _bd[i]; - for (uint i = 0; i < _be.length; i++) babcde[k++] = _be[i]; - return string(babcde); - } - - function strConcat(string memory _a, string memory _b, string memory _c, string memory _d) internal pure returns (string memory ) { - return strConcat(_a, _b, _c, _d, ""); - } - - function strConcat(string memory _a, string memory _b, string memory _c) internal pure returns (string memory ) { - return strConcat(_a, _b, _c, "", ""); - } - - function strConcat(string memory _a, string memory _b) internal pure returns (string memory ) { - return strConcat(_a, _b, "", "", ""); - } - - function uint2str(uint i) internal pure returns (string memory ) { - if (i == 0) return "0"; - uint j = i; - uint len; - while (j != 0){ - len++; - j /= 10; - } - bytes memory bstr = new bytes(len); - uint k = len - 1; - while (i != 0){ - bstr[k--] = byte(uint8(48 + i % 10)); - i /= 10; - } - return string(bstr); - } -} - -contract ERC721Token is SupportsInterfaceWithLookup, ERC721BasicToken, ERC721 { - - using Strings for string; - - bytes4 private constant InterfaceId_ERC721Enumerable = 0x780e9d63; - /** - * 0x780e9d63 === - * bytes4(keccak256('totalSupply()')) ^ - * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ - * bytes4(keccak256('tokenByIndex(uint256)')) - */ - - bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f; - /** - * 0x5b5e139f === - * bytes4(keccak256('name()')) ^ - * bytes4(keccak256('symbol()')) ^ - * bytes4(keccak256('tokenURI(uint256)')) - */ - - /*** Constants ***/ - // Configure these for your own deployment - string public constant NAME = "Gods Unchained"; - string public constant SYMBOL = "GODS"; - string public tokenMetadataBaseURI = "https://api.godsunchained.com/card/"; - - // Mapping from owner to list of owned token IDs - // EDITED: limit to 2^40 (around 1T) - mapping(address => uint40[]) internal ownedTokens; - - uint32[] ownedTokensIndex; - - /** - * @dev Constructor function - */ - constructor() public { - - // register the supported interfaces to conform to ERC721 via ERC165 - _registerInterface(InterfaceId_ERC721Enumerable); - _registerInterface(InterfaceId_ERC721Metadata); - } - - /** - * @dev Gets the token name - * @return string representing the token name - */ - function name() external view returns (string memory) { - return NAME; - } - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory) { - return SYMBOL; - } - - /** - * @dev Returns an URI for a given token ID - * Throws if the token ID does not exist. May return an empty string. - * @param _tokenId uint256 ID of the token to query - */ - function tokenURI(uint256 _tokenId) public view returns (string memory) { - return Strings.strConcat( - tokenMetadataBaseURI, - Strings.uint2str(_tokenId) - ); - } - - /** - * @dev Gets the token ID at a given index of the tokens list of the requested owner - * @param _owner address owning the tokens list to be accessed - * @param _index uint256 representing the index to be accessed of the requested tokens list - * @return uint256 token ID at the given index of the tokens list owned by the requested address - */ - function tokenOfOwnerByIndex( - address _owner, - uint256 _index - ) - public - view - returns (uint256) - { - require(_index < balanceOf(_owner)); - return ownedTokens[_owner][_index]; - } - - /** - * @dev Gets the total amount of tokens stored by the contract - * @return uint256 representing the total amount of tokens - */ - function totalSupply() public view returns (uint256) { - return cards.length; - } - - /** - * @dev Gets the token ID at a given index of all the tokens in this contract - * Reverts if the index is greater or equal to the total number of tokens - * @param _index uint256 representing the index to be accessed of the tokens list - * @return uint256 token ID at the given index of the tokens list - */ - function tokenByIndex(uint256 _index) public view returns (uint256) { - require(_index < totalSupply()); - return _index; - } - - /** - * @dev Internal function to add a token ID to the list of a given address - * @param _to address representing the new owner of the given token ID - * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address - */ - function addTokenTo(address _to, uint256 _tokenId) internal { - super.addTokenTo(_to, _tokenId); - uint256 length = ownedTokens[_to].length; - // EDITED: prevent overflow - require(length == uint32(length)); - ownedTokens[_to].push(uint40(_tokenId)); - - ownedTokensIndex[_tokenId] = uint32(length); - } - - // EDITED - // have to have in order to use array rather than mapping - function addNewTokenTo(address _to, uint256 _tokenId) internal { - super.addNewTokenTo(_to, _tokenId); - uint256 length = ownedTokens[_to].length; - // EDITED: prevent overflow - require(length == uint32(length)); - ownedTokens[_to].push(uint40(_tokenId)); - ownedTokensIndex.push(uint32(length)); - } - - /** - * @dev Internal function to remove a token ID from the list of a given address - * @param _from address representing the previous owner of the given token ID - * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address - */ - function removeTokenFrom(address _from, uint256 _tokenId) internal { - super.removeTokenFrom(_from, _tokenId); - - uint32 tokenIndex = ownedTokensIndex[_tokenId]; - uint256 lastTokenIndex = ownedTokens[_from].length.sub(1); - uint40 lastToken = ownedTokens[_from][lastTokenIndex]; - - ownedTokens[_from][tokenIndex] = lastToken; - ownedTokens[_from][lastTokenIndex] = 0; - // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to - // be zero. Then we can make sure that we will remove _tokenId from the ownedTokens list since we are first swapping - // the lastToken to the first position, and then dropping the element placed in the last position of the list - - ownedTokens[_from].length--; - ownedTokensIndex[_tokenId] = 0; - ownedTokensIndex[lastToken] = tokenIndex; - } - - /** - * @dev Gets the balance of the specified address - overrriden from previous to save gas - * @param _owner address to query the balance of - * @return uint256 representing the amount owned by the passed address - */ - function balanceOf(address _owner) public view returns (uint256) { - return ownedTokens[_owner].length; - } - -} - -contract CardOwnershipTwo is ERC721Token { - - uint public burnCount; - - function getActiveCards() public view returns (uint) { - return totalSupply() - burnCount; - } - - /** - * @param to : the address to which the card will be transferred - * @param id : the id of the card to be transferred - */ - function transfer(address to, uint id) public payable onlyOwnerOf(id) { - require(isTradable(cards[id].proto)); - require(to != address(0)); - - _transfer(msg.sender, to, id); - } - - function _transfer(address from, address to, uint id) internal { - - clearApproval(from, id); - - removeTokenFrom(from, id); - - addTokenTo(to, id); - - emit Transfer(from, to, id); - } - - /** - * @param to : the address to which the cards will be transferred - * @param ids : the ids of the cards to be transferred - */ - function transferAll(address to, uint[] memory ids) public payable { - for (uint i = 0; i < ids.length; i++) { - transfer(to, ids[i]); - } - } - - /** - * @param proposed : the claimed owner of the cards - * @param ids : the ids of the cards to check - * @return whether proposed owns all of the cards - */ - function ownsAll(address proposed, uint[] memory ids) public view returns (bool) { - require(ids.length > 0); - for (uint i = 0; i < ids.length; i++) { - if (!owns(proposed, ids[i])) { - return false; - } - } - return true; - } - - /** - * @param proposed : the claimed owner of the card - * @param id : the id of the card to check - * @return whether proposed owns the card - */ - function owns(address proposed, uint id) public view returns (bool) { - return ownerOf(id) == proposed; - } - - function burn(uint id) public onlyOwnerOf(id) { - burnCount++; - _burn(msg.sender, id); - } - - /** - * @param ids : the indices of the tokens to burn - */ - function burnAll(uint[] memory ids) public { - for (uint i = 0; i < ids.length; i++){ - burn(ids[i]); - } - } - - /** - * @param to : the address to approve for transfer - * @param id : the index of the card to be approved - */ - function approve(address to, uint id) public { - require(isTradable(cards[id].proto)); - super.approve(to, id); - } - - /** - * @param to : the address to approve for transfer - * @param ids : the indices of the cards to be approved - */ - function approveAll(address to, uint[] memory ids) public { - for (uint i = 0; i < ids.length; i++) { - approve(to, ids[i]); - } - } - - /** - * @param to : the address to which the token should be transferred - * @param id : the index of the token to transfer - */ - function transferFrom(address from, address to, uint id) public { - require(isTradable(cards[id].proto)); - super.transferFrom(from, to, id); - } - - /** - * @param to : the address to which the tokens should be transferred - * @param ids : the indices of the tokens to transfer - */ - function transferAllFrom(address from, address to, uint[] memory ids) public { - for (uint i = 0; i < ids.length; i++) { - transferFrom(from, to, ids[i]); - } - } - - /** - * @return the number of cards which have been burned - */ - function getBurnCount() public view returns (uint) { - return burnCount; - } - -} - -contract CardIntegrationTwo is CardOwnershipTwo { - - address[] public packs; - - event CardCreated(uint indexed id, uint16 proto, uint16 purity, address owner); - - function addPack(address approved) public onlyGovernor { - packs.push(approved); - } - - modifier onlyApprovedPacks { - require(_isApprovedPack()); - _; - } - - function _isApprovedPack() private view returns (bool) { - for (uint i = 0; i < packs.length; i++) { - if (msg.sender == address(packs[i])) { - return true; - } - } - return false; - } - - function createCard(address owner, uint16 proto, uint16 purity) public whenNotPaused onlyApprovedPacks returns (uint) { - ProtoCard memory card = protos[proto]; - require(card.season == currentSeason); - if (card.rarity == Rarity.Mythic) { - uint64 limit; - bool exists; - (limit, exists) = getLimit(proto); - require(!exists || limit > 0); - limits[proto].limit--; - } - return _createCard(owner, proto, purity); - } - - function _createCard(address owner, uint16 proto, uint16 purity) internal returns (uint) { - Card memory card = Card({ - proto: proto, - purity: purity - }); - - uint id = cards.push(card) - 1; - - _mint(owner, id); - - emit CardCreated(id, proto, purity, owner); - - return id; - } - - /*function combineCards(uint[] ids) public whenNotPaused { - require(ids.length == 5); - require(ownsAll(msg.sender, ids)); - Card memory first = cards[ids[0]]; - uint16 proto = first.proto; - uint8 shine = _getShine(first.purity); - require(shine < shineLimit); - uint16 puritySum = first.purity - (shine * 1000); - burn(ids[0]); - for (uint i = 1; i < ids.length; i++) { - Card memory next = cards[ids[i]]; - require(next.proto == proto); - require(_getShine(next.purity) == shine); - puritySum += (next.purity - (shine * 1000)); - burn(ids[i]); - } - uint16 newPurity = uint16(((shine + 1) * 1000) + (puritySum / ids.length)); - _createCard(msg.sender, proto, newPurity); - }*/ - - - // PURITY NOTES - // currently, we only - // however, to protect rarity, you'll never be abl - // this is enforced by the restriction in the create-card function - // no cards above this point can be found in packs - - - -} - -contract PreviousInterface { - - function ownerOf(uint id) public view returns (address); - - function getCard(uint id) public view returns (uint16, uint16); - - function totalSupply() public view returns (uint); - - function burnCount() public view returns (uint); - -} - -contract CardMigration is CardIntegrationTwo { - - constructor(PreviousInterface previous) public { - old = previous; - } - - // use interface to lower deployment cost - PreviousInterface old; - - mapping(uint => bool) public migrated; - - function migrate(uint id) public { - - require(!migrated[id]); - - migrated[id] = true; - - address owner = old.ownerOf(id); - - uint16 proto; - uint16 purity; - - (proto, purity) = old.getCard(id); - - _createCard(owner, proto, purity); - } - - function migrateAll(uint[] memory ids) public { - - for (uint i = 0; i < ids.length; i++){ - migrate(ids[i]); - } - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractScenario008.sol b/framework/src/test/resources/soliditycode_0.5.15/contractScenario008.sol deleted file mode 100644 index 251b41bc6a2..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractScenario008.sol +++ /dev/null @@ -1,2050 +0,0 @@ -//pragma solidity ^0.4.11; - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() public { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address payable public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address payable _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() public onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - emit Transfer(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(now), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - uint256 newKittenId = kitties.push(_kitty) - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - emit Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(address(0), _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -contract ERC721 { - // Required methods - function totalSupply() public view returns (uint256 total); - function balanceOf(address _owner) public view returns (uint256 balance); - function ownerOf(uint256 _tokenId) external view returns (address owner); - function approve(address _to, uint256 _tokenId) external; - function transfer(address _to, uint256 _tokenId) external; - function transferFrom(address _from, address _to, uint256 _tokenId) external; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) external view returns (bool); -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is ERC721, KittyBase { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public view returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - emit Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() public view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - external - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { - string memory outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { - require( address(erc721Metadata) != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2 sun; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - msg.sender.transfer(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, address(saleAuction)); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, address(siringAuction)); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10 sun; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, address(saleAuction)); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - address(uint160(address(this))) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - constructor() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(-1), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - emit ContractUpgrade(_v2Address); - } - - /// @notice No tipping! - /// @dev Reject all Ether from being sent here, unless it's from one of the - /// two auction contracts. (Hopefully, we can prevent user accidents.) - function() external payable { - require( - msg.sender == address(saleAuction) || - msg.sender == address(siringAuction) - ); - } - - /// @notice Returns all the relevant information about a specific kitty. - /// @param _id The ID of the kitty of interest. - function getKitty(uint256 _id) - external - view - returns ( - bool isGestating, - bool isReady, - uint256 cooldownIndex, - uint256 nextActionAt, - uint256 siringWithId, - uint256 birthTime, - uint256 matronId, - uint256 sireId, - uint256 generation, - uint256 genes - ) { - Kitty storage kit = kitties[_id]; - - // if this variable is 0 then it's not gestating - isGestating = (kit.siringWithId != 0); - isReady = (kit.cooldownEndBlock <= block.number); - cooldownIndex = uint256(kit.cooldownIndex); - nextActionAt = uint256(kit.cooldownEndBlock); - siringWithId = uint256(kit.siringWithId); - birthTime = uint256(kit.birthTime); - matronId = uint256(kit.matronId); - sireId = uint256(kit.sireId); - generation = uint256(kit.generation); - genes = kit.genes; - } - - /// @dev Override unpause so it requires all external contract addresses - /// to be set before contract can be unpaused. Also, we can't have - /// newContractAddress set either, because then the contract was upgraded. - /// @notice This is public rather than external so we can call super.unpause - /// without using an expensive CALL. - - function unpause() public onlyCEO whenPaused { - require(address(saleAuction) != address(0)); - require(address(siringAuction) != address(0)); - require(address(geneScience) != address(0)); - require(newContractAddress == address(0)); - - // Actually unpause the contract. - super.unpause(); - } - - // @dev Allows the CFO to capture the balance available to the contract. - function withdrawBalance() external onlyCFO { - uint256 balance = address(this).balance; - // Subtract all the currently pregnant kittens we have, plus 1 of margin. - uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - - if (balance > subtractFees) { - cfoAddress.transfer(balance - subtractFees); - } - } -} - - - - - - - - - - - - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - - function isGeneScience() public pure returns (bool){ - return true; - } - - /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor - /// @param genes1 genes of mom - /// @param genes2 genes of sire - /// @return the genes that are supposed to be passed down the child - function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - - return (genes1+genes2+targetBlock)/2; - - -} -} - - - - - - - - - - - - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { - /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. - function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { - if (_tokenId == 1) { - buffer[0] = "Hello World! :D"; - count = 15; - } else if (_tokenId == 2) { - buffer[0] = "I would definitely choose a medi"; - buffer[1] = "um length string."; - count = 49; - } else if (_tokenId == 3) { - buffer[0] = "Lorem ipsum dolor sit amet, mi e"; - buffer[1] = "st accumsan dapibus augue lorem,"; - buffer[2] = " tristique vestibulum id, libero"; - buffer[3] = " suscipit varius sapien aliquam."; - count = 128; - } - } -} - - - - - - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - - // Represents an auction on an NFT - struct Auction { - // Current owner of NFT - address payable seller; - // Price (in wei) at beginning of auction - uint128 startingPrice; - // Price (in wei) at end of auction - uint128 endingPrice; - // Duration (in seconds) of auction - uint64 duration; - // Time when auction started - // NOTE: 0 if this auction has been concluded - uint64 startedAt; - } - - // Reference to contract tracking NFT ownership - ERC721 public nonFungibleContract; - - // Cut owner takes on each auction, measured in basis points (1/100 of a percent). - // Values 0-10,000 map to 0%-100% - uint256 public ownerCut; - - // Map from token ID to their corresponding auction. - mapping (uint256 => Auction) tokenIdToAuction; - - event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); - event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); - event AuctionCancelled(uint256 tokenId); - - /// @dev Returns true if the claimant owns the token. - /// @param _claimant - Address claiming to own the token. - /// @param _tokenId - ID of token whose ownership to verify. - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return (nonFungibleContract.ownerOf(_tokenId) == _claimant); - } - - /// @dev Escrows the NFT, assigning ownership to this contract. - /// Throws if the escrow fails. - /// @param _owner - Current owner address of token to escrow. - /// @param _tokenId - ID of token whose approval to verify. - function _escrow(address _owner, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transferFrom(_owner, address(this), _tokenId); - } - - /// @dev Transfers an NFT owned by this contract to another address. - /// Returns true if the transfer succeeds. - /// @param _receiver - Address to transfer NFT to. - /// @param _tokenId - ID of token to transfer. - function _transfer(address _receiver, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transfer(_receiver, _tokenId); - } - - /// @dev Adds an auction to the list of open auctions. Also fires the - /// AuctionCreated event. - /// @param _tokenId The ID of the token to be put on auction. - /// @param _auction Auction to add. - function _addAuction(uint256 _tokenId, Auction memory _auction) internal { - // Require that all auctions have a duration of - // at least one minute. (Keeps our math from getting hairy!) - require(_auction.duration >= 1 minutes); - - tokenIdToAuction[_tokenId] = _auction; - - emit AuctionCreated( - uint256(_tokenId), - uint256(_auction.startingPrice), - uint256(_auction.endingPrice), - uint256(_auction.duration) - ); - } - - /// @dev Cancels an auction unconditionally. - function _cancelAuction(uint256 _tokenId, address _seller) internal { - _removeAuction(_tokenId); - _transfer(_seller, _tokenId); - emit AuctionCancelled(_tokenId); - } - - /// @dev Computes the price and transfers winnings. - /// Does NOT transfer ownership of token. - function _bid(uint256 _tokenId, uint256 _bidAmount) - internal - returns (uint256) - { - // Get a reference to the auction struct - Auction storage auction = tokenIdToAuction[_tokenId]; - - // Explicitly check that this auction is currently live. - // (Because of how Ethereum mappings work, we can't just count - // on the lookup above failing. An invalid _tokenId will just - // return an auction object that is all zeros.) - require(_isOnAuction(auction)); - - // Check that the bid is greater than or equal to the current price - uint256 price = _currentPrice(auction); - require(_bidAmount >= price); - - // Grab a reference to the seller before the auction struct - // gets deleted. - address payable seller = auction.seller; - - // The bid is good! Remove the auction before sending the fees - // to the sender so we can't have a reentrancy attack. - _removeAuction(_tokenId); - - // Transfer proceeds to seller (if there are any!) - if (price > 0) { - // Calculate the auctioneer's cut. - // (NOTE: _computeCut() is guaranteed to return a - // value <= price, so this subtraction can't go negative.) - uint256 auctioneerCut = _computeCut(price); - uint256 sellerProceeds = price - auctioneerCut; - - // NOTE: Doing a transfer() in the middle of a complex - // method like this is generally discouraged because of - // reentrancy attacks and DoS attacks if the seller is - // a contract with an invalid fallback function. We explicitly - // guard against reentrancy attacks by removing the auction - // before calling transfer(), and the only thing the seller - // can DoS is the sale of their own asset! (And if it's an - // accident, they can call cancelAuction(). ) - seller.transfer(sellerProceeds); - } - - // Calculate any excess funds included with the bid. If the excess - // is anything worth worrying about, transfer it back to bidder. - // NOTE: We checked above that the bid amount is greater than or - // equal to the price so this cannot underflow. - uint256 bidExcess = _bidAmount - price; - - // Return the funds. Similar to the previous transfer, this is - // not susceptible to a re-entry attack because the auction is - // removed before any transfers occur. - msg.sender.transfer(bidExcess); - - // Tell the world! - emit AuctionSuccessful(_tokenId, price, msg.sender); - - return price; - } - - /// @dev Removes an auction from the list of open auctions. - /// @param _tokenId - ID of NFT on auction. - function _removeAuction(uint256 _tokenId) internal { - delete tokenIdToAuction[_tokenId]; - } - - /// @dev Returns true if the NFT is on auction. - /// @param _auction - Auction to check. - function _isOnAuction(Auction storage _auction) internal view returns (bool) { - return (_auction.startedAt > 0); - } - - /// @dev Returns current price of an NFT on auction. Broken into two - /// functions (this one, that computes the duration from the auction - /// structure, and the other that does the price computation) so we - /// can easily test that the price computation works correctly. - function _currentPrice(Auction storage _auction) - internal - view - returns (uint256) - { - uint256 secondsPassed = 0; - - // A bit of insurance against negative values (or wraparound). - // Probably not necessary (since Ethereum guarnatees that the - // now variable doesn't ever go backwards). - if (now > _auction.startedAt) { - secondsPassed = now - _auction.startedAt; - } - - return _computeCurrentPrice( - _auction.startingPrice, - _auction.endingPrice, - _auction.duration, - secondsPassed - ); - } - - /// @dev Computes the current price of an auction. Factored out - /// from _currentPrice so we can run extensive unit tests. - /// When testing, make this function public and turn on - /// `Current price computation` test suite. - function _computeCurrentPrice( - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - uint256 _secondsPassed - ) - internal - pure - returns (uint256) - { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our public functions carefully cap the maximum values for - // time (at 64-bits) and currency (at 128-bits). _duration is - // also known to be non-zero (see the require() statement in - // _addAuction()) - if (_secondsPassed >= _duration) { - // We've reached the end of the dynamic pricing portion - // of the auction, just return the end price. - return _endingPrice; - } else { - // Starting price can be higher than ending price (and often is!), so - // this delta can be negative. - int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - - // This multiplication can't overflow, _secondsPassed will easily fit within - // 64-bits, and totalPriceChange will easily fit within 128-bits, their product - // will always fit within 256-bits. - int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - - // currentPriceChange can be negative, but if so, will have a magnitude - // less that _startingPrice. Thus, this result will always end up positive. - int256 currentPrice = int256(_startingPrice) + currentPriceChange; - - return uint256(currentPrice); - } - } - - /// @dev Computes owner's cut of a sale. - /// @param _price - Sale price of NFT. - function _computeCut(uint256 _price) internal view returns (uint256) { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our entry functions carefully cap the maximum values for - // currency (at 128-bits), and ownerCut <= 10000 (see the require() - // statement in the ClockAuction constructor). The result of this - // function is always guaranteed to be <= _price. - return _price * ownerCut / 10000; - } - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { - event Pause(); - event Unpause(); - - bool public paused = false; - - - /** - * @dev modifier to allow actions only when the contract IS paused - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev modifier to allow actions only when the contract IS NOT paused - */ - modifier whenPaused { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyOwner whenNotPaused public returns (bool) { - paused = true; - emit Pause(); - return true; - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyOwner whenPaused public returns (bool) { - paused = false; - emit Unpause(); - return true; - } -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - - /// @dev The ERC-165 interface signature for ERC-721. - /// Ref: https://github.com/ethereum/EIPs/issues/165 - /// Ref: https://github.com/ethereum/EIPs/issues/721 - bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - - /// @dev Constructor creates a reference to the NFT ownership contract - /// and verifies the owner cut is in the valid range. - /// @param _nftAddress - address of a deployed contract implementing - /// the Nonfungible Interface. - /// @param _cut - percent cut the owner takes on each auction, must be - /// between 0-10,000. - constructor(address _nftAddress, uint256 _cut) public { - require(_cut <= 10000); - ownerCut = _cut; - - ERC721 candidateContract = ERC721(_nftAddress); - require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); - nonFungibleContract = candidateContract; - } - - /// @dev Remove all Ether from the contract, which is the owner's cuts - /// as well as any Ether sent directly to the contract address. - /// Always transfers to the NFT contract, but can be called either by - /// the owner or the NFT contract. - function withdrawBalance() external { - address payable nftAddress = address(uint160(address(nonFungibleContract))); - - require( - msg.sender == owner || - msg.sender == nftAddress - ); - // We are using this boolean method to make sure that even if one fails it will still work - bool res = nftAddress.send(address(this).balance); - } - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of time to move between starting - /// price and ending price (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - whenNotPaused - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(_owns(msg.sender, _tokenId)); - _escrow(msg.sender, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Bids on an open auction, completing the auction and transferring - /// ownership of the NFT if enough Ether is supplied. - /// @param _tokenId - ID of token to bid on. - function bid(uint256 _tokenId) - external - payable - whenNotPaused - { - // _bid will throw if the bid or funds transfer fails - _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - } - - /// @dev Cancels an auction that hasn't been won yet. - /// Returns the NFT to original owner. - /// @notice This is a state-modifying function that can - /// be called while the contract is paused. - /// @param _tokenId - ID of token on auction - function cancelAuction(uint256 _tokenId) - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - address seller = auction.seller; - require(msg.sender == seller); - _cancelAuction(_tokenId, seller); - } - - /// @dev Cancels an auction when the contract is paused. - /// Only the owner may do this, and NFTs are returned to - /// the seller. This should only be used in emergencies. - /// @param _tokenId - ID of the NFT on auction to cancel. - function cancelAuctionWhenPaused(uint256 _tokenId) - whenPaused - onlyOwner - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - _cancelAuction(_tokenId, auction.seller); - } - - /// @dev Returns auction info for an NFT on auction. - /// @param _tokenId - ID of NFT on auction. - function getAuction(uint256 _tokenId) - external - view - returns - ( - address seller, - uint256 startingPrice, - uint256 endingPrice, - uint256 duration, - uint256 startedAt - ) { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return ( - auction.seller, - auction.startingPrice, - auction.endingPrice, - auction.duration, - auction.startedAt - ); - } - - /// @dev Returns the current price of an auction. - /// @param _tokenId - ID of the token price we are checking. - function getCurrentPrice(uint256 _tokenId) - external - view - returns (uint256) - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return _currentPrice(auction); - } - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSiringAuctionAddress() call. - bool public isSiringClockAuction = true; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. Since this function is wrapped, - /// require sender to be KittyCore contract. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Places a bid for siring. Requires the sender - /// is the KittyCore contract because all bid methods - /// should be wrapped. Also returns the kitty to the - /// seller rather than the winner. - function bid(uint256 _tokenId) - external - payable - { - require(msg.sender == address(nonFungibleContract)); - address seller = tokenIdToAuction[_tokenId].seller; - // _bid checks that token ID is valid and will throw if bid fails - _bid(_tokenId, msg.value); - // We transfer the kitty back to the seller, the winner will get - // the offspring - _transfer(seller, _tokenId); - } - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSaleAuctionAddress() call. - bool public isSaleClockAuction = true; - - // Tracks last 5 sale price of gen0 kitty sales - uint256 public gen0SaleCount; - uint256[5] public lastGen0SalePrices; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Updates lastSalePrice if seller is the nft contract - /// Otherwise, works the same as default bid method. - function bid(uint256 _tokenId) - external - payable - { - // _bid verifies token ID size - address seller = tokenIdToAuction[_tokenId].seller; - uint256 price = _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - - // If not a gen0 auction, exit - if (seller == address(nonFungibleContract)) { - // Track gen0 sale prices - lastGen0SalePrices[gen0SaleCount % 5] = price; - gen0SaleCount++; - } - } - - function averageGen0SalePrice() external view returns (uint256) { - uint256 sum = 0; - for (uint256 i = 0; i < 5; i++) { - sum += lastGen0SalePrices[i]; - } - return sum / 5; - } - -} - - - - - - - diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractScenario009.sol b/framework/src/test/resources/soliditycode_0.5.15/contractScenario009.sol deleted file mode 100644 index fb0b76db240..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractScenario009.sol +++ /dev/null @@ -1,51 +0,0 @@ -//pragma solidity ^0.4.0; - -library Set { - // We define a new struct datatype that will be used to - // hold its data in the calling contract. - struct Data { mapping(uint => bool) flags; } - - // Note that the first parameter is of type "storage - // reference" and thus only its storage address and not - // its contents is passed as part of the call. This is a - // special feature of library functions. It is idiomatic - // to call the first parameter 'self', if the function can - // be seen as a method of that object. - function insert (Data storage self, uint value) public - returns (bool) - { - if (self.flags[value]) - return false; // already there - self.flags[value] = true; - return true; - } - - function remove(Data storage self, uint value) public - returns (bool) - { - if (!self.flags[value]) - return false; // not there - self.flags[value] = false; - return true; - } - - function contains(Data storage self, uint value) public - returns (bool) - { - return self.flags[value]; - } -} - - -contract C { - Set.Data knownValues; - - function register(uint value) public { - // The library functions can be called without a - // specific instance of the library, since the - // "instance" will be the current contract. - if (!Set.insert(knownValues, value)) - revert(); - } - // In this contract, we can also directly access knownValues.flags, if we want. -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractScenario010.sol b/framework/src/test/resources/soliditycode_0.5.15/contractScenario010.sol deleted file mode 100644 index f665ea9686e..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractScenario010.sol +++ /dev/null @@ -1,107 +0,0 @@ -//pragma solidity ^0.4.11; - -contract TRON_ERC721 { - //name - function name() view public returns (string memory name){ - return "Tron ERC721 Token"; - } - //symbol - function symbol() view public returns (string memory symbol){ - return "T721T"; - } - - //totalSupply - - function totalSupply() view public returns (uint256 supply){ - uint256 totalSupply = 1000000000000; - return totalSupply; - } - - mapping(address => uint) private balances; - function balanceOf(address _owner) view public returns (uint balance) - { - return balances[_owner]; - } - - - mapping(uint256 => address) private tokenOwners; - mapping(uint256 => bool) private tokenExists; - function ownerOf(uint256 _tokenId) view public returns (address owner) { - require(tokenExists[_tokenId]); - return tokenOwners[_tokenId]; - } - - - mapping(address => mapping (address => uint256)) allowed; - function approve(address _to, uint256 _tokenId) public{ - require(msg.sender == ownerOf(_tokenId)); - require(msg.sender != _to); - allowed[msg.sender][_to] = _tokenId; - emit Approval(msg.sender, _to, _tokenId); - } - - - function takeOwnership(uint256 _tokenId) public { - require(tokenExists[_tokenId]); - address oldOwner = ownerOf(_tokenId); - address newOwner = msg.sender; - require(newOwner != oldOwner); - require(allowed[oldOwner][newOwner] == _tokenId); - balances[oldOwner] -= 1; - tokenOwners[_tokenId] = newOwner; - balances[newOwner] += 1; - emit Transfer(oldOwner, newOwner, _tokenId); - } - - - mapping(address => mapping(uint256 => uint256)) private ownerTokens; - function removeFromTokenList(address owner, uint256 _tokenId) private { - for(uint256 i = 0;ownerTokens[owner][i] != _tokenId;i++){ - ownerTokens[owner][i] = 0; - } - } - - function transfer(address _to, uint256 _tokenId) public{ - address currentOwner = msg.sender; - address newOwner = _to; - require(tokenExists[_tokenId]); - require(currentOwner == ownerOf(_tokenId)); - require(currentOwner != newOwner); - require(newOwner != address(0)); - address oldOwner =currentOwner; - removeFromTokenList(oldOwner,_tokenId); - balances[oldOwner] -= 1; - tokenOwners[_tokenId] = newOwner; - balances[newOwner] += 1; - emit Transfer(oldOwner, newOwner, _tokenId); - } - - function transferFrom(address _from,address _to, uint256 _tokenId) public{ - address currentOwner = _from; - address newOwner = _to; - require(tokenExists[_tokenId]); - require(currentOwner == ownerOf(_tokenId)); - require(currentOwner != newOwner); - require(newOwner != address(0)); - address oldOwner =currentOwner; - removeFromTokenList(oldOwner,_tokenId); - balances[oldOwner] -= 1; - tokenOwners[_tokenId] = newOwner; - balances[newOwner] += 1; - emit Transfer(oldOwner, newOwner, _tokenId); - } - - - function tokenOfOwnerByIndex(address _owner, uint256 _index) view public returns (uint tokenId){ - return ownerTokens[_owner][_index]; - } - - - mapping(uint256 => string) tokenLinks; - function tokenMetadata(uint256 _tokenId) view public returns (string memory infoUrl) { - return tokenLinks[_tokenId]; - } - // Events - event Transfer(address indexed _from, address indexed _to, uint256 _tokenId); - event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId); -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractScenario011.sol b/framework/src/test/resources/soliditycode_0.5.15/contractScenario011.sol deleted file mode 100644 index 74fe819be31..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractScenario011.sol +++ /dev/null @@ -1,2050 +0,0 @@ -//pragma solidity ^0.4.11; - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() public { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address payable public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address payable _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() public onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - emit Transfer(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(now), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - uint256 newKittenId = kitties.push(_kitty) - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - emit Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(address(0), _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -contract ERC721 { - // Required methods - function totalSupply() public view returns (uint256 total); - function balanceOf(address _owner) public view returns (uint256 balance); - function ownerOf(uint256 _tokenId) external view returns (address owner); - function approve(address _to, uint256 _tokenId) external; - function transfer(address _to, uint256 _tokenId) external; - function transferFrom(address _from, address _to, uint256 _tokenId) external; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) external view returns (bool); -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is ERC721, KittyBase { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public view returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - emit Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() public view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - external - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { - string memory outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { - require( address(erc721Metadata) != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2 sun; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - msg.sender.transfer(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, address(saleAuction)); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, address(siringAuction)); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10 sun; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, address(saleAuction)); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - address(uint160(address(this))) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - constructor() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(-1), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - emit ContractUpgrade(_v2Address); - } - - /// @notice No tipping! - /// @dev Reject all Ether from being sent here, unless it's from one of the - /// two auction contracts. (Hopefully, we can prevent user accidents.) - function() external payable { - require( - msg.sender == address(saleAuction) || - msg.sender == address(siringAuction) - ); - } - - /// @notice Returns all the relevant information about a specific kitty. - /// @param _id The ID of the kitty of interest. - function getKitty(uint256 _id) - external - view - returns ( - bool isGestating, - bool isReady, - uint256 cooldownIndex, - uint256 nextActionAt, - uint256 siringWithId, - uint256 birthTime, - uint256 matronId, - uint256 sireId, - uint256 generation, - uint256 genes - ) { - Kitty storage kit = kitties[_id]; - - // if this variable is 0 then it's not gestating - isGestating = (kit.siringWithId != 0); - isReady = (kit.cooldownEndBlock <= block.number); - cooldownIndex = uint256(kit.cooldownIndex); - nextActionAt = uint256(kit.cooldownEndBlock); - siringWithId = uint256(kit.siringWithId); - birthTime = uint256(kit.birthTime); - matronId = uint256(kit.matronId); - sireId = uint256(kit.sireId); - generation = uint256(kit.generation); - genes = kit.genes; - } - - /// @dev Override unpause so it requires all external contract addresses - /// to be set before contract can be unpaused. Also, we can't have - /// newContractAddress set either, because then the contract was upgraded. - /// @notice This is public rather than external so we can call super.unpause - /// without using an expensive CALL. - - function unpause() public onlyCEO whenPaused { - require(address(saleAuction) != address(0)); - require(address(siringAuction) != address(0)); - require(address(geneScience) != address(0)); - require(newContractAddress == address(0)); - - // Actually unpause the contract. - super.unpause(); - } - - // @dev Allows the CFO to capture the balance available to the contract. - function withdrawBalance() external onlyCFO { - uint256 balance = address(this).balance; - // Subtract all the currently pregnant kittens we have, plus 1 of margin. - uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - - if (balance > subtractFees) { - cfoAddress.transfer(balance - subtractFees); - } - } -} - - - - - - - - - - - - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - - function isGeneScience() public pure returns (bool){ - return true; - } - - /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor - /// @param genes1 genes of mom - /// @param genes2 genes of sire - /// @return the genes that are supposed to be passed down the child - function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - - return (genes1+genes2+targetBlock)/2; - - -} -} - - - - - - - - - - - - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { - /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. - function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { - if (_tokenId == 1) { - buffer[0] = "Hello World! :D"; - count = 15; - } else if (_tokenId == 2) { - buffer[0] = "I would definitely choose a medi"; - buffer[1] = "um length string."; - count = 49; - } else if (_tokenId == 3) { - buffer[0] = "Lorem ipsum dolor sit amet, mi e"; - buffer[1] = "st accumsan dapibus augue lorem,"; - buffer[2] = " tristique vestibulum id, libero"; - buffer[3] = " suscipit varius sapien aliquam."; - count = 128; - } - } -} - - - - - - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - - // Represents an auction on an NFT - struct Auction { - // Current owner of NFT - address payable seller; - // Price (in wei) at beginning of auction - uint128 startingPrice; - // Price (in wei) at end of auction - uint128 endingPrice; - // Duration (in seconds) of auction - uint64 duration; - // Time when auction started - // NOTE: 0 if this auction has been concluded - uint64 startedAt; - } - - // Reference to contract tracking NFT ownership - ERC721 public nonFungibleContract; - - // Cut owner takes on each auction, measured in basis points (1/100 of a percent). - // Values 0-10,000 map to 0%-100% - uint256 public ownerCut; - - // Map from token ID to their corresponding auction. - mapping (uint256 => Auction) tokenIdToAuction; - - event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); - event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); - event AuctionCancelled(uint256 tokenId); - - /// @dev Returns true if the claimant owns the token. - /// @param _claimant - Address claiming to own the token. - /// @param _tokenId - ID of token whose ownership to verify. - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return (nonFungibleContract.ownerOf(_tokenId) == _claimant); - } - - /// @dev Escrows the NFT, assigning ownership to this contract. - /// Throws if the escrow fails. - /// @param _owner - Current owner address of token to escrow. - /// @param _tokenId - ID of token whose approval to verify. - function _escrow(address _owner, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transferFrom(_owner, address(this), _tokenId); - } - - /// @dev Transfers an NFT owned by this contract to another address. - /// Returns true if the transfer succeeds. - /// @param _receiver - Address to transfer NFT to. - /// @param _tokenId - ID of token to transfer. - function _transfer(address _receiver, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transfer(_receiver, _tokenId); - } - - /// @dev Adds an auction to the list of open auctions. Also fires the - /// AuctionCreated event. - /// @param _tokenId The ID of the token to be put on auction. - /// @param _auction Auction to add. - function _addAuction(uint256 _tokenId, Auction memory _auction) internal { - // Require that all auctions have a duration of - // at least one minute. (Keeps our math from getting hairy!) - require(_auction.duration >= 1 minutes); - - tokenIdToAuction[_tokenId] = _auction; - - emit AuctionCreated( - uint256(_tokenId), - uint256(_auction.startingPrice), - uint256(_auction.endingPrice), - uint256(_auction.duration) - ); - } - - /// @dev Cancels an auction unconditionally. - function _cancelAuction(uint256 _tokenId, address _seller) internal { - _removeAuction(_tokenId); - _transfer(_seller, _tokenId); - emit AuctionCancelled(_tokenId); - } - - /// @dev Computes the price and transfers winnings. - /// Does NOT transfer ownership of token. - function _bid(uint256 _tokenId, uint256 _bidAmount) - internal - returns (uint256) - { - // Get a reference to the auction struct - Auction storage auction = tokenIdToAuction[_tokenId]; - - // Explicitly check that this auction is currently live. - // (Because of how Ethereum mappings work, we can't just count - // on the lookup above failing. An invalid _tokenId will just - // return an auction object that is all zeros.) - require(_isOnAuction(auction)); - - // Check that the bid is greater than or equal to the current price - uint256 price = _currentPrice(auction); - require(_bidAmount >= price); - - // Grab a reference to the seller before the auction struct - // gets deleted. - address payable seller = auction.seller; - - // The bid is good! Remove the auction before sending the fees - // to the sender so we can't have a reentrancy attack. - _removeAuction(_tokenId); - - // Transfer proceeds to seller (if there are any!) - if (price > 0) { - // Calculate the auctioneer's cut. - // (NOTE: _computeCut() is guaranteed to return a - // value <= price, so this subtraction can't go negative.) - uint256 auctioneerCut = _computeCut(price); - uint256 sellerProceeds = price - auctioneerCut; - - // NOTE: Doing a transfer() in the middle of a complex - // method like this is generally discouraged because of - // reentrancy attacks and DoS attacks if the seller is - // a contract with an invalid fallback function. We explicitly - // guard against reentrancy attacks by removing the auction - // before calling transfer(), and the only thing the seller - // can DoS is the sale of their own asset! (And if it's an - // accident, they can call cancelAuction(). ) - seller.transfer(sellerProceeds); - } - - // Calculate any excess funds included with the bid. If the excess - // is anything worth worrying about, transfer it back to bidder. - // NOTE: We checked above that the bid amount is greater than or - // equal to the price so this cannot underflow. - uint256 bidExcess = _bidAmount - price; - - // Return the funds. Similar to the previous transfer, this is - // not susceptible to a re-entry attack because the auction is - // removed before any transfers occur. - msg.sender.transfer(bidExcess); - - // Tell the world! - emit AuctionSuccessful(_tokenId, price, msg.sender); - - return price; - } - - /// @dev Removes an auction from the list of open auctions. - /// @param _tokenId - ID of NFT on auction. - function _removeAuction(uint256 _tokenId) internal { - delete tokenIdToAuction[_tokenId]; - } - - /// @dev Returns true if the NFT is on auction. - /// @param _auction - Auction to check. - function _isOnAuction(Auction storage _auction) internal view returns (bool) { - return (_auction.startedAt > 0); - } - - /// @dev Returns current price of an NFT on auction. Broken into two - /// functions (this one, that computes the duration from the auction - /// structure, and the other that does the price computation) so we - /// can easily test that the price computation works correctly. - function _currentPrice(Auction storage _auction) - internal - view - returns (uint256) - { - uint256 secondsPassed = 0; - - // A bit of insurance against negative values (or wraparound). - // Probably not necessary (since Ethereum guarnatees that the - // now variable doesn't ever go backwards). - if (now > _auction.startedAt) { - secondsPassed = now - _auction.startedAt; - } - - return _computeCurrentPrice( - _auction.startingPrice, - _auction.endingPrice, - _auction.duration, - secondsPassed - ); - } - - /// @dev Computes the current price of an auction. Factored out - /// from _currentPrice so we can run extensive unit tests. - /// When testing, make this function public and turn on - /// `Current price computation` test suite. - function _computeCurrentPrice( - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - uint256 _secondsPassed - ) - internal - pure - returns (uint256) - { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our public functions carefully cap the maximum values for - // time (at 64-bits) and currency (at 128-bits). _duration is - // also known to be non-zero (see the require() statement in - // _addAuction()) - if (_secondsPassed >= _duration) { - // We've reached the end of the dynamic pricing portion - // of the auction, just return the end price. - return _endingPrice; - } else { - // Starting price can be higher than ending price (and often is!), so - // this delta can be negative. - int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - - // This multiplication can't overflow, _secondsPassed will easily fit within - // 64-bits, and totalPriceChange will easily fit within 128-bits, their product - // will always fit within 256-bits. - int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - - // currentPriceChange can be negative, but if so, will have a magnitude - // less that _startingPrice. Thus, this result will always end up positive. - int256 currentPrice = int256(_startingPrice) + currentPriceChange; - - return uint256(currentPrice); - } - } - - /// @dev Computes owner's cut of a sale. - /// @param _price - Sale price of NFT. - function _computeCut(uint256 _price) internal view returns (uint256) { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our entry functions carefully cap the maximum values for - // currency (at 128-bits), and ownerCut <= 10000 (see the require() - // statement in the ClockAuction constructor). The result of this - // function is always guaranteed to be <= _price. - return _price * ownerCut / 10000; - } - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { - event Pause(); - event Unpause(); - - bool public paused = false; - - - /** - * @dev modifier to allow actions only when the contract IS paused - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev modifier to allow actions only when the contract IS NOT paused - */ - modifier whenPaused { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyOwner whenNotPaused public returns (bool) { - paused = true; - emit Pause(); - return true; - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyOwner whenPaused public returns (bool) { - paused = false; - emit Unpause(); - return true; - } -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - - /// @dev The ERC-165 interface signature for ERC-721. - /// Ref: https://github.com/ethereum/EIPs/issues/165 - /// Ref: https://github.com/ethereum/EIPs/issues/721 - bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - - /// @dev Constructor creates a reference to the NFT ownership contract - /// and verifies the owner cut is in the valid range. - /// @param _nftAddress - address of a deployed contract implementing - /// the Nonfungible Interface. - /// @param _cut - percent cut the owner takes on each auction, must be - /// between 0-10,000. - constructor(address _nftAddress, uint256 _cut) public { - require(_cut <= 10000); - ownerCut = _cut; - - ERC721 candidateContract = ERC721(_nftAddress); - require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); - nonFungibleContract = candidateContract; - } - - /// @dev Remove all Ether from the contract, which is the owner's cuts - /// as well as any Ether sent directly to the contract address. - /// Always transfers to the NFT contract, but can be called either by - /// the owner or the NFT contract. - function withdrawBalance() external { - address payable nftAddress = address(uint160(address(nonFungibleContract))); - - require( - msg.sender == owner || - msg.sender == nftAddress - ); - // We are using this boolean method to make sure that even if one fails it will still work - bool res = nftAddress.send(address(this).balance); - } - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of time to move between starting - /// price and ending price (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - whenNotPaused - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(_owns(msg.sender, _tokenId)); - _escrow(msg.sender, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Bids on an open auction, completing the auction and transferring - /// ownership of the NFT if enough Ether is supplied. - /// @param _tokenId - ID of token to bid on. - function bid(uint256 _tokenId) - external - payable - whenNotPaused - { - // _bid will throw if the bid or funds transfer fails - _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - } - - /// @dev Cancels an auction that hasn't been won yet. - /// Returns the NFT to original owner. - /// @notice This is a state-modifying function that can - /// be called while the contract is paused. - /// @param _tokenId - ID of token on auction - function cancelAuction(uint256 _tokenId) - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - address seller = auction.seller; - require(msg.sender == seller); - _cancelAuction(_tokenId, seller); - } - - /// @dev Cancels an auction when the contract is paused. - /// Only the owner may do this, and NFTs are returned to - /// the seller. This should only be used in emergencies. - /// @param _tokenId - ID of the NFT on auction to cancel. - function cancelAuctionWhenPaused(uint256 _tokenId) - whenPaused - onlyOwner - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - _cancelAuction(_tokenId, auction.seller); - } - - /// @dev Returns auction info for an NFT on auction. - /// @param _tokenId - ID of NFT on auction. - function getAuction(uint256 _tokenId) - external - view - returns - ( - address seller, - uint256 startingPrice, - uint256 endingPrice, - uint256 duration, - uint256 startedAt - ) { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return ( - auction.seller, - auction.startingPrice, - auction.endingPrice, - auction.duration, - auction.startedAt - ); - } - - /// @dev Returns the current price of an auction. - /// @param _tokenId - ID of the token price we are checking. - function getCurrentPrice(uint256 _tokenId) - external - view - returns (uint256) - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return _currentPrice(auction); - } - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSiringAuctionAddress() call. - bool public isSiringClockAuction = true; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. Since this function is wrapped, - /// require sender to be KittyCore contract. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Places a bid for siring. Requires the sender - /// is the KittyCore contract because all bid methods - /// should be wrapped. Also returns the kitty to the - /// seller rather than the winner. - function bid(uint256 _tokenId) - external - payable - { - require(msg.sender == address(nonFungibleContract)); - address seller = tokenIdToAuction[_tokenId].seller; - // _bid checks that token ID is valid and will throw if bid fails - _bid(_tokenId, msg.value); - // We transfer the kitty back to the seller, the winner will get - // the offspring - _transfer(seller, _tokenId); - } - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSaleAuctionAddress() call. - bool public isSaleClockAuction = true; - - // Tracks last 5 sale price of gen0 kitty sales - uint256 public gen0SaleCount; - uint256[5] public lastGen0SalePrices; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Updates lastSalePrice if seller is the nft contract - /// Otherwise, works the same as default bid method. - function bid(uint256 _tokenId) - external - payable - { - // _bid verifies token ID size - address seller = tokenIdToAuction[_tokenId].seller; - uint256 price = _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - - // If not a gen0 auction, exit - if (seller == address(nonFungibleContract)) { - // Track gen0 sale prices - lastGen0SalePrices[gen0SaleCount % 5] = price; - gen0SaleCount++; - } - } - - function averageGen0SalePrice() external view returns (uint256) { - uint256 sum = 0; - for (uint256 i = 0; i < 5; i++) { - sum += lastGen0SalePrices[i]; - } - return sum / 5; - } - -} - - - - - - - diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractScenario012.sol b/framework/src/test/resources/soliditycode_0.5.15/contractScenario012.sol deleted file mode 100644 index 7bed08dd111..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractScenario012.sol +++ /dev/null @@ -1,57 +0,0 @@ -//pragma solidity ^0.4.0; -contract PayTest { - -uint256 public n; -constructor() payable public{ -n = 0; -} - -function nPlusOne() public{ -n = n+1; -} - -//get current contract balance -function getBalance() payable public returns (uint) { -return address(this).balance; -} - -function getSenderBalance() public view returns(address, uint) { -return (msg.sender, msg.sender.balance); -} - -address public user; - -//deposit 1 coin to msg.sender -function depositOneCoin() payable public returns(bool success){ -return msg.sender.send(1); -} - -// function transferOneCoin() payable public returns(){ -// address(msg.sender).transfer(1); -// } - -// function depositOneCoin() payable public returns(address addr, uint amount, bool success){ -// return (msg.sender, msg.value, msg.sender.send(1)); -// } - -//deposit coin to msg.sender -function deposit(uint256 money) payable public returns(bool success){ -return msg.sender.send(money); -} -// function deposit(uint money) payable public returns(address addr, uint amount, bool success){ -// return (msg.sender, msg.value, msg.sender.send(money)); -// } - -// function () payable { -// msg.sender.send(1); -// } - -function sendToAddress(address payable _receiver) payable public{ -_receiver.transfer(msg.value); -} - -function sendToAddress2(address payable _receiver) payable public{ -_receiver.transfer(5); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractScenario013.sol b/framework/src/test/resources/soliditycode_0.5.15/contractScenario013.sol deleted file mode 100644 index b91085d018e..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractScenario013.sol +++ /dev/null @@ -1,8 +0,0 @@ -//pragma solidity ^0.4.0; -contract timetest { - -function time() public{ -require(1 trx == 1000000 sun); - -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractScenario014.sol b/framework/src/test/resources/soliditycode_0.5.15/contractScenario014.sol deleted file mode 100644 index 41ea739e231..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractScenario014.sol +++ /dev/null @@ -1,34 +0,0 @@ -//pragma solidity ^0.4.0; -contract Contract1 { - constructor() public payable{} - function send5SunToReceiver(address payable _receiver) payable public{ - _receiver.transfer(5); - } -} -contract contract2 { - address public payContract; - - constructor(address _add) payable public{ - payContract = _add; - } - - function triggerContract1(address _receiver) payable public{ - payContract.call(abi.encodeWithSignature("send5SunToReceiver(address)",_receiver)); - } - - function triggerContract1ButRevert(address _receiver) payable public{ - payContract.call(abi.encodeWithSignature("send5SunToReceiver(address)",_receiver)); - require(1 == 2); - } - -} -contract contract3 { - address public payContract; - constructor(address _add) payable public{ - payContract = _add; - } - - function triggerContract2(address _receiver) payable public{ - payContract.call(abi.encodeWithSignature("triggerContract1(address)",_receiver)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTest.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTest.sol deleted file mode 100644 index 409545eaabb..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTest.sol +++ /dev/null @@ -1,19 +0,0 @@ -//pragma solidity ^0.4.4; - -contract Test{ - -function a() public returns (uint){ - -uint256 count = 0; - -for (uint256 i = 1; i > 0; i++) { - -count++; - -} - -return count; - -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractToMathedFeed.sol b/framework/src/test/resources/soliditycode_0.5.15/contractToMathedFeed.sol deleted file mode 100644 index a5d181ad927..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractToMathedFeed.sol +++ /dev/null @@ -1,21 +0,0 @@ -//pragma solidity ^0.4.0; - -contract ToMathedFeed { - uint public i=1; - function ToMathed (uint value) public { - i=value; - } -} - -contract ToMathedUseINContract { - function ToMathedIUseNR(address a,uint256 n) public returns(bool){ - address payContract=a; - (bool success, bytes memory data) = payContract.call(abi.encodeWithSignature("ToMathedNot(uint256)",n)); - return success; - } - function ToMathedIUseNRE(address a,uint256 value) public returns(bool){ - address payContract=a; - (bool success, bytes memory data) = payContract.call(abi.encodeWithSignature("ToMathed(uint256)",value)); - return success; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTransferToken001.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTransferToken001.sol deleted file mode 100644 index e91c0d7bf0f..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTransferToken001.sol +++ /dev/null @@ -1,22 +0,0 @@ -contract A { - address public a; - constructor() public payable{} - function kill(address payable toAddress) payable public{ - selfdestruct(toAddress); - } - function newB() public payable returns(address){ - B bAddress=new B(); - a= address(bAddress); - return a; - - } - - } - -contract B{ - constructor() public payable {} - function() external payable {} - function kill(address payable toAddress) payable public{ - selfdestruct(toAddress); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken001.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken001.sol deleted file mode 100644 index 0db64f36336..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken001.sol +++ /dev/null @@ -1,30 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken002.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken002.sol deleted file mode 100644 index 0db64f36336..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken002.sol +++ /dev/null @@ -1,30 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken003.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken003.sol deleted file mode 100644 index 48205199eec..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken003.sol +++ /dev/null @@ -1,16 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken005.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken005.sol deleted file mode 100644 index 48205199eec..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken005.sol +++ /dev/null @@ -1,16 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken011.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken011.sol deleted file mode 100644 index f815c26b136..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken011.sol +++ /dev/null @@ -1,35 +0,0 @@ -//pragma solidity ^0.4.24; -contract transferTokenContract { - constructor() payable public{} - function() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - function() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken012.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken012.sol deleted file mode 100644 index 668f67ae205..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken012.sol +++ /dev/null @@ -1,26 +0,0 @@ -//pragma solidity ^0.4.24; -contract transferTokenContract { - constructor() payable public{} - function() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken014.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken014.sol deleted file mode 100644 index 3753770398a..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken014.sol +++ /dev/null @@ -1,34 +0,0 @@ -//pragma solidity ^0.4.24; -contract transferTokenContract { - constructor() payable public{} - function() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - function() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken018.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken018.sol deleted file mode 100644 index 668f67ae205..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken018.sol +++ /dev/null @@ -1,26 +0,0 @@ -//pragma solidity ^0.4.24; -contract transferTokenContract { - constructor() payable public{} - function() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken023.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken023.sol deleted file mode 100644 index 99b19beb107..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken023.sol +++ /dev/null @@ -1,26 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - toAddress.transferToken(amount,id); - } - } - -contract B{ - uint256 public flag = 0; - constructor() public payable {} - function() external { - flag = 1; -} - -} -//pragma solidity ^0.4.24; -contract C{ - uint256 public flag = 0; - constructor() public payable {} - function() external payable { - //flag = 1; -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken026.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken026.sol deleted file mode 100644 index 66635521150..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken026.sol +++ /dev/null @@ -1,31 +0,0 @@ -//pragma solidity ^0.4.24; - -contract token{ - constructor() payable public{} - function() payable external{} - function testInCall(address callBAddress,address callCAddress, address toAddress ,uint256 amount,trcToken id) payable public{ - //callBAddress.call(bytes4(keccak256("transC(address,address,uint256,trcToken)")),callCAddress,toAddress,amount,id); - callBAddress.call(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callCAddress,toAddress,amount,id)); - } - function testIndelegateCall(address callBddress,address callAddressC, address toAddress,uint256 amount, trcToken id) payable public{ - callBddress.delegatecall(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callAddressC,toAddress,amount,id)); - } - } - - - -contract B{ - constructor() public payable{} - function() external payable{} - function transC(address payable callCAddress,address payable toAddress,uint256 amount, trcToken id) payable public{ - callCAddress.call(abi.encodeWithSignature("trans(address,uint256,trcToken)",toAddress,amount,id)); - } -} -contract C{ - constructor() payable public{} - function() payable external{} - function trans(address payable toAddress,uint256 amount, trcToken id) payable public{ - toAddress.transferToken(amount,id); - } - -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken027.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken027.sol deleted file mode 100644 index ee9c1d3eb46..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken027.sol +++ /dev/null @@ -1,30 +0,0 @@ -//pragma solidity ^0.4.24; - -contract token{ - constructor() payable public{} - function() payable external{} - function testInCall(address callBAddress,address callCAddress, address toAddress ,uint256 amount,trcToken id) payable public{ - callBAddress.call(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callCAddress,toAddress,amount,id)); - } - function testIndelegateCall(address callBddress,address callAddressC, address toAddress,uint256 amount, trcToken id) payable public{ - callBddress.delegatecall(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callAddressC,toAddress,amount,id)); - } - } - - - -contract B{ - constructor() public payable{} - function() external payable{} - function transC(address callCAddress,address toAddress,uint256 amount, trcToken id) payable public{ - callCAddress.call(abi.encodeWithSignature("trans(address,uint256,trcToken)",toAddress,amount,id)); - } -} -contract C{ - constructor() payable public{} - function() payable external{} - function trans(address payable toAddress,uint256 amount, trcToken id) payable public{ - toAddress.transferToken(amount,id); - } - -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken028.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken028.sol deleted file mode 100644 index 957f1c3c60d..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken028.sol +++ /dev/null @@ -1,25 +0,0 @@ -//pragma solidity ^0.4.24; - -contract token{ - uint256 public a=1; - constructor() public payable{} - function tokenBalanceWithSameName(trcToken id) public payable{ - B b= new B(); - a= b.tokenBalance(id); - } - function getA() public returns(uint256){ - return a; - } -} - - -contract B{ - uint256 public flag =0; - constructor() public payable{} - function() external payable{} - function tokenBalance(trcToken id) payable public returns(uint256){ - flag =9; - return flag; - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken029.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken029.sol deleted file mode 100644 index e8f5cbc0988..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken029.sol +++ /dev/null @@ -1,24 +0,0 @@ -//pragma solidity ^0.4.24; - -contract token{ - address public a; - constructor() public payable{} - function transferTokenWithSameName(trcToken id,uint256 amount) public payable{ - B b= new B(); - b.transferToken(amount,id); - a= address(b); - } -} - - -contract B{ - uint256 public flag =0; - constructor() public payable{} - function() external payable{} - function transferToken(uint256 amount, trcToken id) payable public returns(bool){ - flag =9; - } - function getFlag() public view returns (uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken030.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken030.sol deleted file mode 100644 index 5693292d127..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken030.sol +++ /dev/null @@ -1,18 +0,0 @@ -//pragma solidity ^0.4.24; - - contract token{ - constructor() public payable{} - - // 4)suicide也会转移token - // 所有token,trx均被转移到toAddress, - // 若toAddress为合约地址本身,则所有token,trx均被烧掉进黑洞 - function kill(address payable toAddress) payable public{ - selfdestruct(toAddress); - } - - } - -contract B{ - constructor() public payable {} - function() external payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken031.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken031.sol deleted file mode 100644 index 5693292d127..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken031.sol +++ /dev/null @@ -1,18 +0,0 @@ -//pragma solidity ^0.4.24; - - contract token{ - constructor() public payable{} - - // 4)suicide也会转移token - // 所有token,trx均被转移到toAddress, - // 若toAddress为合约地址本身,则所有token,trx均被烧掉进黑洞 - function kill(address payable toAddress) payable public{ - selfdestruct(toAddress); - } - - } - -contract B{ - constructor() public payable {} - function() external payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken034.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken034.sol deleted file mode 100644 index 2a3d9e1fa3a..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken034.sol +++ /dev/null @@ -1,25 +0,0 @@ -//pragma solidity ^0.4.24; - - contract token{ - - constructor() public payable {} - - // 2. 异常测试 - // 1)revert, 金额回退 - function failTransferTokenRevert(address payable toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - require(1==2); - } - - // 2)Error, 金额回退, fee limit 扣光 - function failTransferTokenError(address payable toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - assert(1==2); - } - - } - contract B{ - uint256 public flag = 0; - constructor() public payable {} - function() external payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken035.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken035.sol deleted file mode 100644 index ab53daa704a..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken035.sol +++ /dev/null @@ -1,24 +0,0 @@ -//pragma solidity ^0.4.24; - - contract token{ - constructor() public payable {} - - // 2. 异常测试 - // 1)revert, 金额回退 - function failTransferTokenRevert(address payable toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - require(1==2); - } - - // 2)Error, 金额回退, fee limit 扣光 - function failTransferTokenError(address payable toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - assert(1==2); - } - - } - contract B{ - uint256 public flag = 0; - constructor() public payable {} - function() external payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036.sol deleted file mode 100644 index 6a4c61d1e07..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036.sol +++ /dev/null @@ -1,52 +0,0 @@ -//pragma solidity ^0.4.24; -contract IllegalDecorate { -constructor() payable public{} -function() payable external{} -event log(uint256); -function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public payable { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate1 { -constructor() payable public{} -function() payable external{} -event log(uint256); -function transferTokenWithConstant(address payable toAddress, uint256 tokenValue) public payable { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate2 { -constructor() payable public{} -function() payable external{} -event log(uint256); -function transferTokenWithView(address payable toAddress, uint256 tokenValue) public payable { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate3 { -event log(uint256); -constructor() payable public{} -function() payable external{} -function transferTokenWithOutPayable(address payable toAddress, uint256 tokenValue) public { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_1.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_1.sol deleted file mode 100644 index cd039f3e39d..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_1.sol +++ /dev/null @@ -1,13 +0,0 @@ -//pragma solidity ^0.4.24; -contract IllegalDecorate { -constructor() payable public{} -function() payable external{} -event log(uint256); -function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public pure { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_2.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_2.sol deleted file mode 100644 index 0b4d56e086b..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_2.sol +++ /dev/null @@ -1,13 +0,0 @@ -//pragma solidity ^0.4.24; -contract IllegalDecorate { -constructor() payable public{} -function() payable external{} -event log(uint256); -function transferTokenWithConstant(address toAddress, uint256 tokenValue) public constant { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_3.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_3.sol deleted file mode 100644 index b8c7d750514..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_3.sol +++ /dev/null @@ -1,13 +0,0 @@ -//pragma solidity ^0.4.24; -contract IllegalDecorate { -constructor() payable public{} -function() payable external{} -event log(uint256); -function transferTokenWithView(address payable toAddress, uint256 tokenValue) public view { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_4.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_4.sol deleted file mode 100644 index 29c1990962b..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_4.sol +++ /dev/null @@ -1,13 +0,0 @@ -//pragma solidity ^0.4.24; -contract IllegalDecorate { -event log(uint256); -constructor() payable public{} -function() payable external{} -function transferTokenWithOutPayable(address payable toAddress, uint256 tokenValue) public { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_old.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_old.sol deleted file mode 100644 index 7ea2561a1e1..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken036_old.sol +++ /dev/null @@ -1,41 +0,0 @@ -//pragma solidity ^0.4.24; - - -contract IllegalDecorate1 { -constructor() payable public{} -function() payable public{} -event log(uint256); -function transferTokenWithConstant(address toAddress, uint256 tokenValue) public constant { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate2 { -constructor() payable public{} -function() payable public{} -event log(uint256); -function transferTokenWithView(address toAddress, uint256 tokenValue) public view { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate3 { -event log(uint256); -constructor() payable public{} -function() payable public{} -function transferTokenWithOutPayable(address toAddress, uint256 tokenValue) public { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken037.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken037.sol deleted file mode 100644 index 5e3fbcb8270..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken037.sol +++ /dev/null @@ -1,24 +0,0 @@ -//pragma solidity ^0.4.24; - -contract transferTrc10 { - function receive(address payable rec) public payable { - uint256 aamount=address(this).tokenBalance(msg.tokenid); - uint256 bamount=rec.tokenBalance(msg.tokenid); - require(msg.tokenvalue==aamount); - require(aamount==msg.tokenvalue); - rec.transferToken(aamount,msg.tokenid); - require(0==address(this).tokenBalance(msg.tokenid)); - require(bamount+aamount==rec.tokenBalance(msg.tokenid)); - (bool success, bytes memory data) =rec.call(abi.encodeWithSignature("checkTrc10(uint256,trcToken,uint256)",bamount+aamount,msg.tokenid,0)); - require(success); - - } -} - -contract receiveTrc10 { - function() external payable {} - function checkTrc10(uint256 amount,trcToken tid,uint256 meamount) public{ - require(amount==address(this).tokenBalance(tid)); - require(meamount==msg.sender.tokenBalance(tid)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken038.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken038.sol deleted file mode 100644 index 713d7661e84..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken038.sol +++ /dev/null @@ -1,24 +0,0 @@ -//pragma solidity ^0.4.24; - -contract transferTrc10 { - function receive(address payable rec) public payable { - uint256 aamount=address(this).tokenBalance(msg.tokenid); - uint256 bamount=rec.tokenBalance(msg.tokenid); - require(msg.tokenvalue==aamount); - require(aamount==msg.tokenvalue); - rec.transferToken(aamount,msg.tokenid); - //require(rec.call(abi.encode(bytes4(keccak256("AssertError()"))))); - (bool suc, bytes memory data) = rec.call(abi.encodeWithSignature("AssertError()")); - require(suc); - require(aamount==address(this).tokenBalance(msg.tokenid)); - require(bamount==rec.tokenBalance(msg.tokenid)); - } -} - -contract receiveTrc10 { - function() external payable { - } - function AssertError() public{ - assert(1==2); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken039.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken039.sol deleted file mode 100644 index e60b3285652..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken039.sol +++ /dev/null @@ -1,44 +0,0 @@ -//pragma solidity ^0.4.24; -/* - * 1. caller账户issue一个token - * 2. caller部署proxy, 传入1000 token,1000 trx - * 3. caller部署A - * 4. caller部署B - * 5. caller调用proxy中upgradetTo函数,传入A的地址 - * 6. caller调用proxy中不存在的trans(uint256,address,trcToken)函数,注意这时trcToken是无意义的,但也带上tokenid。address是任意另外某账户的地址 - * 7. 可以看到目标地址trx增长5,caller账户trx减少5 - * 8. caller调用proxy中upgradeTo函数,传入B的地址 - * 9. caller调用proxy中不存在的trans(uint256,address,trcToken)函数。 - * 10. 可以看到目标地址token增长5,caller账户token减少5 -*/ -contract Proxy { - constructor() payable public{} - address public implementation; - function upgradeTo(address _address) public { - implementation = _address; - } - function() payable external{ - address addr = implementation; - require(addr != address(0)); - assembly { - let freememstart := mload(0x40) - calldatacopy(freememstart, 0, calldatasize()) - let success := delegatecall(not(0), addr, freememstart, calldatasize(), freememstart, 0) - returndatacopy(freememstart, 0, returndatasize()) - switch success - case 0 { revert(freememstart, returndatasize()) } - default { return(freememstart, returndatasize()) } - } - } -} - -contract A { - function trans(uint256 amount, address payable toAddress, trcToken id) payable public { - toAddress.transfer(amount); - } -} -contract B{ - function trans(uint256 amount, address payable toAddress, trcToken id) payable public { - toAddress.transferToken(amount,id); - } -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken041.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken041.sol deleted file mode 100644 index a6272bc813d..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken041.sol +++ /dev/null @@ -1,20 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } - -contract B{ - uint256 public flag = 0; - constructor() public payable {} - function() external payable {} - - function setFlag() public payable{ - flag = 1; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken043.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken043.sol deleted file mode 100644 index f815c26b136..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken043.sol +++ /dev/null @@ -1,35 +0,0 @@ -//pragma solidity ^0.4.24; -contract transferTokenContract { - constructor() payable public{} - function() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - function() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken048.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken048.sol deleted file mode 100644 index de2844608c0..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken048.sol +++ /dev/null @@ -1,14 +0,0 @@ -//pragma solidity ^0.4.24; - - contract Test { - event log(uint256); - function testMsgTokenValue() payable public returns(uint256 value) { - emit log(msg.tokenvalue); - return msg.tokenvalue; - } - - function testMsgValue() payable public returns(uint256 value) { - emit log(msg.value); - return msg.value; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken049.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken049.sol deleted file mode 100644 index 3fd502c89fd..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken049.sol +++ /dev/null @@ -1,10 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken050.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken050.sol deleted file mode 100644 index 3fd502c89fd..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken050.sol +++ /dev/null @@ -1,10 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken051.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken051.sol deleted file mode 100644 index b5b9efd4817..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken051.sol +++ /dev/null @@ -1,11 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - function() external payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken052.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken052.sol deleted file mode 100644 index 3fd502c89fd..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken052.sol +++ /dev/null @@ -1,10 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken054.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken054.sol deleted file mode 100644 index 48205199eec..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken054.sol +++ /dev/null @@ -1,16 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken055.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken055.sol deleted file mode 100644 index 48205199eec..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken055.sol +++ /dev/null @@ -1,16 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken060.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken060.sol deleted file mode 100644 index 0db64f36336..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken060.sol +++ /dev/null @@ -1,30 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken061.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken061.sol deleted file mode 100644 index 0db64f36336..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken061.sol +++ /dev/null @@ -1,30 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken064.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken064.sol deleted file mode 100644 index cf2a6fe8097..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken064.sol +++ /dev/null @@ -1,49 +0,0 @@ -//pragma solidity ^0.4.24; -contract transferTokenContract { - constructor() payable public{} - function() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } - function transferTokenTestValueMaxBigInteger(address payable toAddress) payable public { - toAddress.transferToken(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0); - } - function transferTokenTestValueOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(9223372036854775808, 1000001); - } - function transferTokenTestValueMaxLong(address payable toAddress) payable public { - toAddress.transferToken(9223372036854775807, 1000001); - } - function transferTokenTestValue0IdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(0, 9223372036854775809); - } -} - - - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - function() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken066.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken066.sol deleted file mode 100644 index f815c26b136..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken066.sol +++ /dev/null @@ -1,35 +0,0 @@ -//pragma solidity ^0.4.24; -contract transferTokenContract { - constructor() payable public{} - function() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - function() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken067.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken067.sol deleted file mode 100644 index f815c26b136..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken067.sol +++ /dev/null @@ -1,35 +0,0 @@ -//pragma solidity ^0.4.24; -contract transferTokenContract { - constructor() payable public{} - function() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - function() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken073.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken073.sol deleted file mode 100644 index 9cb13ec7268..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken073.sol +++ /dev/null @@ -1,17 +0,0 @@ -//pragma solidity ^0.4.0; - -contract Dest { - event logFallback(uint256 indexed, uint256 indexed, uint256 indexed); - event logGetToken(uint256 indexed, uint256 indexed, uint256 indexed, uint256); - - - constructor() payable public {} - - function getToken(trcToken tokenId) payable public{ - emit logGetToken(msg.sender.tokenBalance(tokenId), msg.tokenid, msg.tokenvalue, msg.value); - } - - function () payable external{ - emit logFallback(msg.tokenid, msg.tokenvalue, msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken075.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken075.sol deleted file mode 100644 index 2a32fd7e8d3..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken075.sol +++ /dev/null @@ -1,26 +0,0 @@ -//pragma solidity ^0.4.0; - -contract Dest { - event logFallback(uint256 indexed, uint256 indexed, uint256 indexed); - event logGetToken(uint256 indexed, uint256 indexed, uint256 indexed, uint256); - - constructor() payable public {} - - function getToken(trcToken tokenId) payable public{ - emit logGetToken(msg.sender.tokenBalance(tokenId), msg.tokenid, msg.tokenvalue, msg.value); - } - - function getTokenLongMin() payable public{ - // long.min - 1000020 - emit logGetToken(msg.sender.tokenBalance(trcToken(-9223372036855775828)), msg.tokenid, msg.tokenvalue, msg.value); - } - - function getTokenLongMax() payable public{ - // long.max + 1000020 - emit logGetToken(msg.sender.tokenBalance(trcToken(9223372036855775827)), msg.tokenid, msg.tokenvalue, msg.value); - } - - function () payable external{ - emit logFallback(msg.tokenid, msg.tokenvalue, msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken076.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken076.sol deleted file mode 100644 index 9de79a327c3..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken076.sol +++ /dev/null @@ -1,19 +0,0 @@ -//pragma solidity ^0.4.24; -contract Test { - address public origin; - address public sender; - bool public result1; - bool public result2; - function test() external { - origin = tx.origin; - sender = msg.sender; - result1 = msg.sender == tx.origin; // true - result2 = origin == sender; // true - } -function getResult1() public returns(bool){ - return result1; -} -function getResult2() public returns(bool){ - return result2; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken077.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken077.sol deleted file mode 100644 index e110f24e2fc..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken077.sol +++ /dev/null @@ -1,11 +0,0 @@ -//pragma solidity ^0.4.24; - -contract trcToken077 { -function addressTest() public returns(bytes32 addressValue) { - assembly{ - let x := mload(0x40) //Find empty storage location using "free memory pointer" - mstore(x,address) //Place current contract address - addressValue := mload(x) - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken078.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken078.sol deleted file mode 100644 index f7504ea55aa..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken078.sol +++ /dev/null @@ -1,35 +0,0 @@ -//pragma solidity ^0.4.24; -contract callerContract { - constructor() public payable{} - function() external payable{} - function sendToB(address called_address, address c) public payable{ - called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); - } - function sendToB2(address called_address,address c) public payable{ - called_address.call(abi.encodeWithSignature("transferTo(address)",c)); - } - function sendToB3(address called_address,address c) public payable{ - called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); - } -} - contract calledContract { - function() external payable{} - constructor() public payable {} - function transferTo(address payable toAddress)public payable{ - toAddress.transfer(5); - } - - function setIinC(address c) public payable{ - c.call.value(5)(abi.encode(bytes4(keccak256("setI()")))); - } - - } - contract c{ - address public origin; - address public sender; - constructor() public payable{} - event log(address,address); - function() payable external{ - emit log(tx.origin,msg.sender); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken079.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken079.sol deleted file mode 100644 index 48205199eec..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken079.sol +++ /dev/null @@ -1,16 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken080.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken080.sol deleted file mode 100644 index 27529ce48e8..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcToken080.sol +++ /dev/null @@ -1,30 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - function() external payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractTrcTokenToOther.sol b/framework/src/test/resources/soliditycode_0.5.15/contractTrcTokenToOther.sol deleted file mode 100644 index 22456df9e8e..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractTrcTokenToOther.sol +++ /dev/null @@ -1,44 +0,0 @@ -//pragma solidity ^0.4.24; - -contract ConvertType { - -constructor() payable public{} - -function() payable external{} - -//function trcTokenOnStorage(trcToken storage token) internal { // ERROR: Data location can only be specified for array, struct or mapping types, but "storage" was given. -//} - -function trcTokenToString(trcToken token) public pure returns(string memory s){ -// s = token; // ERROR -// s = string(token); // ERROR -} - -function trcTokenToUint256(trcToken token) public pure returns(uint256 r){ -uint256 u = token; // OK -uint256 u2 = uint256(token); // OK -r = u2; -} - -function trcTokenToAddress(trcToken token) public pure returns(address r){ -//r = token; // ERROR -token = 0x1234567812345678123456781234567812345678123456781234567812345678; -address a2 = address(token); // OK -r = a2; -} - -function trcTokenToBytes(trcToken token) public pure returns(bytes memory r){ -//r = token; // ERROR -// r = bytes(token); // ERROR -} - -function trcTokenToBytes32(trcToken token) public pure returns(bytes32 r){ -// r = token; // ERROR -bytes32 b2 = bytes32(token); // OK -r = b2; -} - -function trcTokenToArray(trcToken token) public pure returns(uint[] memory r){ -//r = token; // ERROR -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/contractUnknownException.sol b/framework/src/test/resources/soliditycode_0.5.15/contractUnknownException.sol deleted file mode 100644 index 37c28468be1..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/contractUnknownException.sol +++ /dev/null @@ -1,65 +0,0 @@ -// pragma solidity ^0.4.24; - -contract testA { - constructor() public payable { - A a = (new A).value(10)(); - a.fun(); - } -} - -contract testB { - constructor() public payable { - B b = (new B).value(10)(); - b.fun(); - } -} - - -contract testC { - constructor() public payable{ - C c = (new C).value(10)(); - c.fun(); - } -} - -contract testD { - constructor() public payable{ - D d = (new D).value(10)(); - d.fun(); - } -} - - -contract A { - constructor() public payable{ - selfdestruct(msg.sender); - } - function fun() public { - } - -} - -contract B { - constructor() public payable { - revert(); - } - function fun() public { - } -} - - -contract C { - constructor() public payable { - assert(1==2); - } - function fun() public { - } -} - -contract D { - constructor() public payable { - require(1==2); - } - function fun() public { - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/create2CallContract.sol b/framework/src/test/resources/soliditycode_0.5.15/create2CallContract.sol deleted file mode 100644 index f2de1c7ee13..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/create2CallContract.sol +++ /dev/null @@ -1,37 +0,0 @@ -contract callerContract { - constructor() payable public{} - function() payable external{} - function delegateCallCreate2(address called_address, bytes memory code, uint256 salt) public { - called_address.delegatecall(abi.encodeWithSignature("deploy(bytes,uint256)",code,salt)); - } - function callCreate2(address called_address,bytes memory code, uint256 salt) public returns(bool,bytes memory){ - return called_address.call(abi.encodeWithSignature("deploy(bytes,uint256)",code,salt)); - } -} - - -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - -contract TestConstract { - uint public i; - constructor () public { - } - function plusOne() public returns(uint){ - i++; - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/create2Istanbul.sol b/framework/src/test/resources/soliditycode_0.5.15/create2Istanbul.sol deleted file mode 100644 index b79db6e4639..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/create2Istanbul.sol +++ /dev/null @@ -1,28 +0,0 @@ -pragma solidity ^0.5.12; - -contract create2Istanbul { - function deploy(bytes memory code, uint256 salt) public returns(address) { - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - - } - return addr; - } - - // prefix in main net is 0x41, testnet config is 0xa0 - function get(bytes1 prefix, bytes calldata code, uint256 salt) external view returns(address) { - //bytes32 hash = keccak256(abi.encodePacked(bytes1(0x41),address(this), salt, keccak256(code))); - bytes32 hash = keccak256(abi.encodePacked(prefix,address(this), salt, keccak256(code))); - address addr = address(uint160(uint256(hash))); - return addr; - } - -} - -contract B { - constructor() public payable{} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/create2contract.sol b/framework/src/test/resources/soliditycode_0.5.15/create2contract.sol deleted file mode 100644 index 0171f4d5486..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/create2contract.sol +++ /dev/null @@ -1,52 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } - - event Deployed(address addr, bytes32 salt, address sender); - function deploy(bytes memory code, bytes32 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - -contract FactoryBytes { - event Deployed(address addr, bytes32 salt, address sender); - function deploy(bytes memory code, bytes32 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - -contract TestConstract { - uint public i; - constructor () public { - } - function plusOne() public returns(uint){ - i++; - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/create2contract22.sol b/framework/src/test/resources/soliditycode_0.5.15/create2contract22.sol deleted file mode 100644 index c33cb08edc3..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/create2contract22.sol +++ /dev/null @@ -1,109 +0,0 @@ -contract Factory { - event Deployed(address addr, trcToken salt, address sender); - event Deployed1(address addr, uint8 salt, address sender); - event Deployed2(address addr, address salt, address sender); - event Deployed3(address addr, string salt, address sender); - - - function deploy(bytes memory code, trcToken salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } - - function deploy1(bytes memory code, uint8 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed1(addr, salt, msg.sender); - return addr; - } - - function deploy2(bytes memory code, address salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed2(addr, salt, msg.sender); - return addr; - } - - function deploy3(bytes memory code, string memory salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed3(addr, salt, msg.sender); - return addr; - } - -} - - -contract TestConstract { - uint public i=1; - function testTransfer(uint256 i) payable public{ - msg.sender.transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} - -contract TestConstract1 { - uint public i=2; - function testTransfer(uint256 i) payable public{ - msg.sender.transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} - -contract TestConstract2 { - uint public i=3; - function testTransfer(uint256 i) payable public{ - msg.sender.transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} - -contract TestConstract3 { - uint public i=4; - function testTransfer(uint256 i) payable public{ - msg.sender.transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/create2contractn.sol b/framework/src/test/resources/soliditycode_0.5.15/create2contractn.sol deleted file mode 100644 index e0e3ae64c16..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/create2contractn.sol +++ /dev/null @@ -1,29 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract TestConstract { - uint public i=1; - function testTransfer(uint256 i) payable public{ - msg.sender.transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/create2contractn2.sol b/framework/src/test/resources/soliditycode_0.5.15/create2contractn2.sol deleted file mode 100644 index 626988c4e04..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/create2contractn2.sol +++ /dev/null @@ -1,26 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract TestConstract { - uint public i=1; - function set() payable public { - i=5; - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/demo.sol b/framework/src/test/resources/soliditycode_0.5.15/demo.sol deleted file mode 100644 index c7f6d0d4da9..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/demo.sol +++ /dev/null @@ -1,73 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - uint256 codesize; - constructor() payable public{ - uint256 m; - address addr = address(this); - assembly { - m := extcodesize(addr) - } - codesize = m; - } - - // positive case - function pulsone() public payable{ - uint256 j = 0; - uint i = 100; - for (; i < i; i++) { - j++; - } - } - - - function getCodeSize() public returns (uint256){ - return codesize; - } - - } - - contract confirmTest{ - - uint256 codesize; - constructor() payable public{ - uint256 m; - address addr = address(this); - assembly { - m := extcodesize(addr) - - } - codesize = m; - } - - function getCodeSize() public returns (uint256){ - return codesize; - } - - function confirm(address addr) public returns (uint256){ - uint256 j; - assembly { - j := extcodesize(addr) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - return j; - } - - function at(address _addr) public returns (bytes memory o_code) { - assembly { - // retrieve the size of the code, this needs assembly - let size := extcodesize(_addr) - // allocate output byte array - this could also be done without assembly - // by using o_code = new bytes(size) - o_code := mload(0x40) - // new "memory end" including padding - mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) - // store length in memory - mstore(o_code, size) - // actually retrieve the code, this needs assembly - extcodecopy(_addr, add(o_code, 0x20), 0, size) - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/event001.sol b/framework/src/test/resources/soliditycode_0.5.15/event001.sol deleted file mode 100644 index 7662df3a5c6..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/event001.sol +++ /dev/null @@ -1,10 +0,0 @@ -contract Event { - event xixi(uint256 id) ; - event log2(uint256,uint256,uint256); - constructor() public payable{} - function messageI() payable public returns (uint ret) { - //emit log2(1,2,3); - emit xixi(1); - return 1; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/event002.sol b/framework/src/test/resources/soliditycode_0.5.15/event002.sol deleted file mode 100644 index 70a5275521c..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/event002.sol +++ /dev/null @@ -1,52 +0,0 @@ -pragma solidity >=0.4.0 <0.7.0; - -contract Event { - - event _0(); - event a_0() anonymous; - event a_4i(uint256 indexed x1, uint256 indexed x2 , uint256 indexed x3, uint256 indexed x4, uint256 x5)anonymous ; - event _3i(uint256 x1, uint256 indexed x2 , uint256 indexed x3, uint256 x4, uint256 x5) ; - event _1i(uint256 indexed x1, uint256, uint256 indexed, uint256 x4) ; - event a_1i(uint256) anonymous; - event _ai(uint8[2], uint8) ; - event a_ai(uint8[2], uint8) anonymous; - event _a1i(uint8[2] indexed, uint8) ; - event a_a1i(uint8[2] indexed, uint8) anonymous; - - constructor () public { - // emit a_0(); - // emit a_1i(123); - // emit a_4i(1,2,3,5,16); - // emit _0(); - emit _3i(1,2,3,5,16); - // emit _1i(1,2,3,5); - // emit _ai([1,2], 3); - // emit a_ai([3,4], 5); - // emit _a1i([1,2], 3); - // emit a_a1i([3,4], 5); - } - - function e() public { - emit _1i(1,2,3,4); - } - - function l() public { - emit a_1i(1); - } - - function k() public{ - emit a_4i(2,3,4,5,17); - emit _3i(2,3,4,5,16); - emit _1i(2,3,4,5); - emit a_1i(128); - emit _0(); - emit a_0(); - //selfdestruct(msg.sender); - //emit a_4i(1,2,3,5,16); - //emit _3i(1,2,3,5,16); - //emit _1i(1,2,3,5); - //emit a_1i(123); - //emit _0(); - //emit a_0(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/extCodeHash.sol b/framework/src/test/resources/soliditycode_0.5.15/extCodeHash.sol deleted file mode 100644 index d6209770682..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/extCodeHash.sol +++ /dev/null @@ -1,13 +0,0 @@ -contract TestExtCodeHash { - - function getCodeHashByAddr(address _addr) public returns (bytes32 _hash) { - assembly { - _hash := extcodehash(_addr) - } - } - function getCodeHashByUint(uint256 _addr) public returns (bytes32 _hash) { - assembly { - _hash := extcodehash(_addr) - } - } -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/extCodeHash11.sol b/framework/src/test/resources/soliditycode_0.5.15/extCodeHash11.sol deleted file mode 100644 index ad59f6cce1c..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/extCodeHash11.sol +++ /dev/null @@ -1,103 +0,0 @@ -contract Counter { -uint count = 0; -address payable owner; -event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); -constructor() public{ -owner = msg.sender; -} -function getCodeHashByAddr() public returns (bytes32 _hashBefore, bytes32 _hashAfter) { -address addr = address(this); -assembly { -_hashBefore := extcodehash(addr) -} -if (owner == msg.sender) { -selfdestruct(owner); -} -assembly { -_hashAfter := extcodehash(addr) -} -revert(); -emit LogResult(_hashBefore, _hashAfter); -} -} - -contract Counter1 { -uint count = 0; -address payable owner; -event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); -constructor() public{ -owner = msg.sender; -} -function getCodeHashByAddr() public returns (bytes32 _hashBefore, bytes32 _hashAfter) { -address addr = address(this); -assembly { -_hashBefore := extcodehash(addr) -} -if (owner == msg.sender) { -selfdestruct(owner); -} -assembly { -_hashAfter := extcodehash(addr) -} - -emit LogResult(_hashBefore, _hashAfter); -} -} - - -contract Counter2 { -uint count = 0; -address payable owner; -event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); -constructor() public{ -owner = msg.sender; -} -function getCodeHashByAddr(address c) public returns (bytes32 _hashBefore, bytes32 _hashAfter) { - TestConstract t=new TestConstract(); -address addr = address(t); -assembly { -_hashBefore := extcodehash(addr) -} - addr.call(abi.encodeWithSignature("testSuicideNonexistentTarget(address)",c)); - - -assembly { -_hashAfter := extcodehash(addr) -} - -emit LogResult(_hashBefore, _hashAfter); -} -} - - -contract Counter3 { -uint count = 0; -address payable owner; -event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); -constructor() public{ -owner = msg.sender; -} -function getCodeHashByAddr(address c) public returns (bytes32 _hashBefore, bytes32 _hashAfter) { - TestConstract t=new TestConstract(); -address addr = address(t); -assembly { -_hashBefore := extcodehash(addr) -} -if (owner == msg.sender) { -selfdestruct(owner); -} - -assembly { -_hashAfter := extcodehash(addr) -} - -emit LogResult(_hashBefore, _hashAfter); -} -} - -contract TestConstract { - uint public i=1; - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/extCodeHashConstruct.sol b/framework/src/test/resources/soliditycode_0.5.15/extCodeHashConstruct.sol deleted file mode 100644 index 6bb91b3d3b1..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/extCodeHashConstruct.sol +++ /dev/null @@ -1,14 +0,0 @@ -contract CounterConstruct { - uint count = 0; - address payable owner; - event LogResult(bytes32 _hashBefore); - constructor() public{ - owner = msg.sender; - address addr = address(this); - bytes32 _hashBefore; - assembly { - _hashBefore := extcodehash(addr) - } - emit LogResult(_hashBefore); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/extCodeHashStress.sol b/framework/src/test/resources/soliditycode_0.5.15/extCodeHashStress.sol deleted file mode 100644 index cf41f3c8106..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/extCodeHashStress.sol +++ /dev/null @@ -1,45 +0,0 @@ -contract Trigger { - function test(address addr) public returns(uint i) { - bytes32 hash; - while (gasleft() > 1000) { - assembly { - hash := extcodehash(addr) - } - i++; - } - } - - function test(address[] memory addrs) public returns(uint i) { - bytes32 hash; - uint i = 0; - for (; i < addrs.length; i++) { - address addr = addrs[i]; - assembly { - hash := extcodehash(addr) - } - } - return i; - } - } - - - - contract TriggerNormal { - function test(address addr) public returns(uint i) { - i = 0; - while (gasleft() > 100000) { - i++; - } - } - } - - contract TriggerNormal1 { - function test(address[] memory addrs) public returns(uint i) { - bytes32 hash; - uint i = 0; - for (; i < addrs.length; i++) { - address addr = addrs[i]; - addr.balance; - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/extCodeHashTestNoPayable.sol b/framework/src/test/resources/soliditycode_0.5.15/extCodeHashTestNoPayable.sol deleted file mode 100644 index c3a2ad8c6ae..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/extCodeHashTestNoPayable.sol +++ /dev/null @@ -1,8 +0,0 @@ -contract testConstantContract{ -uint256 public i; -function testNoPayable() public returns (uint256 z) { -i=1; -z=i; -return z; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/isSRCandidate.sol b/framework/src/test/resources/soliditycode_0.5.15/isSRCandidate.sol deleted file mode 100644 index 723e6d0e93a..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/isSRCandidate.sol +++ /dev/null @@ -1,35 +0,0 @@ - -pragma solidity ^0.5.0; - -contract ContractB{ - address others; -} - -contract TestIsSRCandidate{ - - ContractB contractB = new ContractB(); - - function isSRCandidateTest(address addr) public view returns (bool) { - return address(addr).isSRCandidate; - } - - function zeroAddressTest() public view returns (bool) { - return address(0x0).isSRCandidate; - } - - function localContractAddrTest() public view returns (bool) { - return address(this).isSRCandidate; - } - - function otherContractAddrTest() public view returns (bool) { - return address(contractB).isSRCandidate; - } - - function nonpayableAddrTest(address addr) public view returns (bool) { - return addr.isSRCandidate; - } - - function payableAddrTest(address payable addr) public returns (bool) { - return addr.isSRCandidate; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/mappingGetter.sol b/framework/src/test/resources/soliditycode_0.5.15/mappingGetter.sol deleted file mode 100644 index dbd473717cb..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/mappingGetter.sol +++ /dev/null @@ -1,4 +0,0 @@ -contract mappingGetter { - mapping(bytes => uint256) public balances1; - mapping(string => uint256) public balances2; -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/multiValiSignPerformance01.sol b/framework/src/test/resources/soliditycode_0.5.15/multiValiSignPerformance01.sol deleted file mode 100644 index 74baa963366..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/multiValiSignPerformance01.sol +++ /dev/null @@ -1,37 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract ecrecoverValidateSign { - - using ECVerify for bytes32; - - function validateSign(bytes32 hash,bytes[] memory sig,address[] memory signer) public returns (bool) { - for(uint256 i=0;i bytes32) public nullifiers; // store nullifiers of spent commitments - mapping(bytes32 => bytes32) public roots; // store history root - mapping(uint256 => bytes32) public tree; - mapping(bytes32 => bytes32) public noteCommitment; - bytes32[33] frontier; - bytes32[32] zeroes = [bytes32(0x0100000000000000000000000000000000000000000000000000000000000000), bytes32(0x817de36ab2d57feb077634bca77819c8e0bd298c04f6fed0e6a83cc1356ca155), bytes32(0xffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e34), bytes32(0xd8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c), bytes32(0xe110de65c907b9dea4ae0bd83a4b0a51bea175646a64c12b4c9f931b2cb31b49), bytes32(0x912d82b2c2bca231f71efcf61737fbf0a08befa0416215aeef53e8bb6d23390a), bytes32(0x8ac9cf9c391e3fd42891d27238a81a8a5c1d3a72b1bcbea8cf44a58ce7389613), bytes32(0xd6c639ac24b46bd19341c91b13fdcab31581ddaf7f1411336a271f3d0aa52813), bytes32(0x7b99abdc3730991cc9274727d7d82d28cb794edbc7034b4f0053ff7c4b680444), bytes32(0x43ff5457f13b926b61df552d4e402ee6dc1463f99a535f9a713439264d5b616b), bytes32(0xba49b659fbd0b7334211ea6a9d9df185c757e70aa81da562fb912b84f49bce72), bytes32(0x4777c8776a3b1e69b73a62fa701fa4f7a6282d9aee2c7a6b82e7937d7081c23c), bytes32(0xec677114c27206f5debc1c1ed66f95e2b1885da5b7be3d736b1de98579473048), bytes32(0x1b77dac4d24fb7258c3c528704c59430b630718bec486421837021cf75dab651), bytes32(0xbd74b25aacb92378a871bf27d225cfc26baca344a1ea35fdd94510f3d157082c), bytes32(0xd6acdedf95f608e09fa53fb43dcd0990475726c5131210c9e5caeab97f0e642f), bytes32(0x1ea6675f9551eeb9dfaaa9247bc9858270d3d3a4c5afa7177a984d5ed1be2451), bytes32(0x6edb16d01907b759977d7650dad7e3ec049af1a3d875380b697c862c9ec5d51c), bytes32(0xcd1c8dbf6e3acc7a80439bc4962cf25b9dce7c896f3a5bd70803fc5a0e33cf00), bytes32(0x6aca8448d8263e547d5ff2950e2ed3839e998d31cbc6ac9fd57bc6002b159216), bytes32(0x8d5fa43e5a10d11605ac7430ba1f5d81fb1b68d29a640405767749e841527673), bytes32(0x08eeab0c13abd6069e6310197bf80f9c1ea6de78fd19cbae24d4a520e6cf3023), bytes32(0x0769557bc682b1bf308646fd0b22e648e8b9e98f57e29f5af40f6edb833e2c49), bytes32(0x4c6937d78f42685f84b43ad3b7b00f81285662f85c6a68ef11d62ad1a3ee0850), bytes32(0xfee0e52802cb0c46b1eb4d376c62697f4759f6c8917fa352571202fd778fd712), bytes32(0x16d6252968971a83da8521d65382e61f0176646d771c91528e3276ee45383e4a), bytes32(0xd2e1642c9a462229289e5b0e3b7f9008e0301cbb93385ee0e21da2545073cb58), bytes32(0xa5122c08ff9c161d9ca6fc462073396c7d7d38e8ee48cdb3bea7e2230134ed6a), bytes32(0x28e7b841dcbc47cceb69d7cb8d94245fb7cb2ba3a7a6bc18f13f945f7dbd6e2a), bytes32(0xe1f34b034d4a3cd28557e2907ebf990c918f64ecb50a94f01d6fda5ca5c7ef72), bytes32(0x12935f14b676509b81eb49ef25f39269ed72309238b4c145803544b646dca62d), bytes32(0xb2eed031d4d6a4f02a097f80b54cc1541d4163c6b6f5971f88b6e41d35c53814)]; - address owner; - TokenTRC20 trc20Token; - - event MintNewLeaf(uint256 position, bytes32 cm, bytes32 cv, bytes32 epk, bytes32[21] c); - event TransferNewLeaf(uint256 position, bytes32 cm, bytes32 cv, bytes32 epk, bytes32[21] c); - event BurnNewLeaf(uint256 position, bytes32 cm, bytes32 cv, bytes32 epk, bytes32[21] c); - event TokenMint(address from, uint256 value); - event TokenBurn(address to, uint256 value, bytes32[3] ciphertext); - event NoteSpent(bytes32 nf); - - constructor (address trc20ContractAddress, uint256 scalingFactorExponent) public { - require(scalingFactorExponent < 77, "The scalingFactorExponent is out of range!"); - scalingFactor = 10 ** scalingFactorExponent; - owner = msg.sender; - trc20Token = TokenTRC20(trc20ContractAddress); - } - // output: cm, cv, epk, proof - function mint(uint256 rawValue, bytes32[9] calldata output, bytes32[2] calldata bindingSignature, bytes32[21] calldata c) external { - address sender = msg.sender; - // transfer the trc20Token from the sender to this contract - bool transferResult = trc20Token.transferFrom(sender, address(this), rawValue); - require(transferResult, "TransferFrom failed!"); - - require(noteCommitment[output[0]] == 0, "Duplicate noteCommitments!"); - uint64 value = rawValueToValue(rawValue); - bytes32 signHash = sha256(abi.encodePacked(address(this), value, output, c)); - (bytes32[] memory ret) = verifyMintProof(output, bindingSignature, value, signHash, frontier, leafCount); - uint256 result = uint256(ret[0]); - require(result == 1, "The proof and signature have not been verified by the contract!"); - - uint256 slot = uint256(ret[1]); - uint256 nodeIndex = leafCount + 2 ** 32 - 1; - tree[nodeIndex] = output[0]; - if (slot == 0) { - frontier[0] = output[0]; - } - for (uint256 i = 1; i < slot + 1; i++) { - nodeIndex = (nodeIndex - 1) / 2; - tree[nodeIndex] = ret[i + 1]; - if (i == slot) { - frontier[slot] = tree[nodeIndex]; - } - } - latestRoot = ret[slot + 2]; - roots[latestRoot] = latestRoot; - noteCommitment[output[0]] = output[0]; - leafCount ++; - - emit MintNewLeaf(leafCount - 1, output[0], output[1], output[2], c); - emit TokenMint(sender, rawValue); - } - //input: nf, anchor, cv, rk, proof - //output: cm, cv, epk, proof - function transfer(bytes32[10][] calldata input, bytes32[2][] calldata spendAuthoritySignature, bytes32[9][] calldata output, bytes32[2] calldata bindingSignature, bytes32[21][] calldata c) external { - require(input.length >= 1 && input.length <= 2, "Input number must be 1 or 2!"); - require(input.length == spendAuthoritySignature.length, "Input number must be equal to spendAuthoritySignature number!"); - require(output.length >= 1 && output.length <= 2, "Output number must be 1 or 2!"); - require(output.length == c.length, "Output number must be equal to c number!"); - - for (uint256 i = 0; i < input.length; i++) { - require(nullifiers[input[i][0]] == 0, "The note has already been spent!"); - require(roots[input[i][1]] != 0, "The anchor must exist!"); - } - for (uint256 i = 0; i < output.length; i++) { - require(noteCommitment[output[i][0]] == 0, "Duplicate noteCommitment!"); - } - - bytes32 signHash = sha256(abi.encodePacked(address(this), input, output, c)); - (bytes32[] memory ret) = verifyTransferProof(input, spendAuthoritySignature, output, bindingSignature, signHash, 0, frontier, leafCount); - uint256 result = uint256(ret[0]); - require(result == 1, "The proof and signature have not been verified by the contract!"); - - uint256 offset = 1; - //ret offset - for (uint256 i = 0; i < output.length; i++) { - uint256 slot = uint256(ret[offset++]); - uint256 nodeIndex = leafCount + 2 ** 32 - 1; - tree[nodeIndex] = output[i][0]; - if (slot == 0) { - frontier[0] = output[i][0]; - } - for (uint256 k = 1; k < slot + 1; k++) { - nodeIndex = (nodeIndex - 1) / 2; - tree[nodeIndex] = ret[offset++]; - if (k == slot) { - frontier[slot] = tree[nodeIndex]; - } - } - leafCount++; - } - latestRoot = ret[offset]; - roots[latestRoot] = latestRoot; - for (uint256 i = 0; i < input.length; i++) { - bytes32 nf = input[i][0]; - nullifiers[nf] = nf; - emit NoteSpent(nf); - } - for (uint256 i = 0; i < output.length; i++) { - noteCommitment[output[i][0]] = output[i][0]; - emit TransferNewLeaf(leafCount - (output.length - i), output[i][0], output[i][1], output[i][2], c[i]); - } - } - //input: nf, anchor, cv, rk, proof - //output: cm, cv, epk, proof - function burn(bytes32[10] calldata input, bytes32[2] calldata spendAuthoritySignature, uint256 rawValue, bytes32[2] calldata bindingSignature, address payTo, bytes32[3] calldata burnCipher, bytes32[9][] calldata output, bytes32[21][] calldata c) external { - uint64 value = rawValueToValue(rawValue); - bytes32 signHash = sha256(abi.encodePacked(address(this), input, output, c, payTo, value)); - - bytes32 nf = input[0]; - bytes32 anchor = input[1]; - require(nullifiers[nf] == 0, "The note has already been spent!"); - require(roots[anchor] != 0, "The anchor must exist!"); - - require(output.length <= 1, "Output number cannot exceed 1!"); - require(output.length == c.length, "Output number must be equal to length of c!"); - - // bytes32 signHash = sha256(abi.encodePacked(address(this), input, payTo, value, output, c)); - if (output.length == 0) { - (bool result) = verifyBurnProof(input, spendAuthoritySignature, value, bindingSignature, signHash); - require(result, "The proof and signature have not been verified by the contract!"); - } else { - transferInBurn(input, spendAuthoritySignature, value, bindingSignature, signHash, output, c); - } - - nullifiers[nf] = nf; - emit NoteSpent(nf); - //Finally, transfer trc20Token from this contract to the nominated address - bool transferResult = trc20Token.transfer(payTo, rawValue); - require(transferResult, "Transfer failed!"); - - emit TokenBurn(payTo, rawValue, burnCipher); - } - - function transferInBurn(bytes32[10] memory input, bytes32[2] memory spendAuthoritySignature, uint64 value, bytes32[2] memory bindingSignature, bytes32 signHash, bytes32[9][] memory output, bytes32[21][] memory c) private { - bytes32 cm = output[0][0]; - require(noteCommitment[cm] == 0, "Duplicate noteCommitment!"); - bytes32[10][] memory inputs = new bytes32[10][](1); - inputs[0] = input; - bytes32[2][] memory spendAuthoritySignatures = new bytes32[2][](1); - spendAuthoritySignatures[0] = spendAuthoritySignature; - (bytes32[] memory ret) = verifyTransferProof(inputs, spendAuthoritySignatures, output, bindingSignature, signHash, value, frontier, leafCount); - uint256 result = uint256(ret[0]); - require(result == 1, "The proof and signature have not been verified by the contract!"); - - uint256 slot = uint256(ret[1]); - uint256 nodeIndex = leafCount + 2 ** 32 - 1; - tree[nodeIndex] = cm; - if (slot == 0) { - frontier[0] = cm; - } - for (uint256 i = 1; i < slot + 1; i++) { - nodeIndex = (nodeIndex - 1) / 2; - tree[nodeIndex] = ret[i + 1]; - if (i == slot) { - frontier[slot] = tree[nodeIndex]; - } - } - latestRoot = ret[slot + 2]; - roots[latestRoot] = latestRoot; - noteCommitment[cm] = cm; - leafCount ++; - - emit BurnNewLeaf(leafCount - 1, cm, output[0][1], output[0][2], c[0]); - } - - //position: index of leafnode, start from 0 - function getPath(uint256 position) public view returns (bytes32, bytes32[32] memory) { - require(position >= 0, "Position should be non-negative!"); - require(position < leafCount, "Position should be smaller than leafCount!"); - uint256 index = position + 2 ** 32 - 1; - bytes32[32] memory path; - uint32 level = ancestorLevel(position); - bytes32 targetNodeValue = getTargetNodeValue(position, level); - for (uint32 i = 0; i < 32; i++) { - if (i == level) { - path[31 - i] = targetNodeValue; - } else { - if (index % 2 == 0) { - path[31 - i] = tree[index - 1]; - } else { - path[31 - i] = tree[index + 1] == 0 ? zeroes[i] : tree[index + 1]; - } - } - index = (index - 1) / 2; - } - return (latestRoot, path); - } - - //position: index of leafnode, start from 0 - function getPathByValueIsZero(uint256 position) public view returns (bytes32, bytes32[32] memory) { - require(position >= 0, "Position should be non-negative!"); - require(position < leafCount, "Position should be smaller than leafCount!"); - uint256 index = position + 2 ** 32 - 1; - bytes32[32] memory path; - uint32 level = ancestorLevel(position); - bytes32 targetNodeValue = getTargetNodeValueByValueIsZero(position, level); - for (uint32 i = 0; i < 32; i++) { - if (i == level) { - path[31 - i] = targetNodeValue; - } else { - if (index % 2 == 0) { - path[31 - i] = tree[index - 1]; - } else { - path[31 - i] = tree[index + 1] == 0 ? zeroes[i] : tree[index + 1]; - } - } - index = (index - 1) / 2; - } - return (latestRoot, path); - } - - function ancestorLevel(uint256 leafIndex) private view returns (uint32) { - uint256 nodeIndex1 = leafIndex + 2 ** 32 - 1; - uint256 nodeIndex2 = leafCount + 2 ** 32 - 2; - uint32 level = 0; - while (((nodeIndex1 - 1) / 2) != ((nodeIndex2 - 1) / 2)) { - nodeIndex1 = (nodeIndex1 - 1) / 2; - nodeIndex2 = (nodeIndex2 - 1) / 2; - level = level + 1; - } - return level; - } - - function getTargetNodeValue(uint256 leafIndex, uint32 level) private view returns (bytes32) { - bytes32 left; - bytes32 right; - uint256 index = leafIndex + 2 ** 32 - 1; - uint256 nodeIndex = leafCount + 2 ** 32 - 2; - bytes32 nodeValue = tree[nodeIndex]; - if (level == 0) { - if (index < nodeIndex) { - return nodeValue; - } - if (index == nodeIndex) { - if (index % 2 == 0) { - return tree[index - 1]; - } else { - return zeroes[0]; - } - } - } - for (uint32 i = 0; i < level; i++) { - if (nodeIndex % 2 == 0) { - left = tree[nodeIndex - 1]; - right = nodeValue; - } else { - left = nodeValue; - right = zeroes[i]; - } - nodeValue = pedersenHash(i, left, right); - nodeIndex = (nodeIndex - 1) / 2; - } - return nodeValue; - } - - function getTargetNodeValueByValueIsZero(uint256 leafIndex, uint32 level) private view returns (bytes32) { - bytes32 left; - bytes32 right; - uint256 index = leafIndex + 2 ** 32 - 1; - uint256 nodeIndex = leafCount + 2 ** 32 - 2; - bytes32 nodeValue = tree[nodeIndex]; - if (level == 0) { - if (index < nodeIndex) { - return nodeValue; - } - if (index == nodeIndex) { - if (index % 2 == 0) { - return tree[index - 1]; - } else { - return zeroes[0]; - } - } - } - for (uint32 i = 0; i < level; i++) { - if (nodeIndex % 2 == 0) { - left = tree[nodeIndex - 1]; - right = nodeValue; - } else { - left = nodeValue; - right = zeroes[i]; - } - left = bytes32(0x0); - right = bytes32(0x0); - nodeValue = pedersenHash(i, left, right); - nodeIndex = (nodeIndex - 1) / 2; - } - return nodeValue; - } - - function rawValueToValue(uint256 rawValue) private view returns (uint64) { - require(rawValue > 0, "Value must be positive!"); - require(rawValue.mod(scalingFactor) == 0, "Value must be integer multiples of scalingFactor!"); - uint256 value = rawValue.div(scalingFactor); - require(value < INT64_MAX); - return uint64(value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest1TestRequireContract.sol b/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest1TestRequireContract.sol deleted file mode 100644 index dbb97ab4f04..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest1TestRequireContract.sol +++ /dev/null @@ -1,15 +0,0 @@ -//pragma solidity ^0.4.0; -contract TestThrowsContract{ - function testAssert() public { - assert(1==2); - } - function testRequire() public { - require(2==1); - } - function testRevert() public { - revert(); - } - //function testThrow(){ - // throw; - //} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest2TestThrowsContract.sol b/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest2TestThrowsContract.sol deleted file mode 100644 index abcc2d84ca2..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest2TestThrowsContract.sol +++ /dev/null @@ -1,15 +0,0 @@ -//pragma solidity ^0.4.0; -contract TestThrowsContract{ - function testAssert() public { - assert(1==2); - } - function testRequire() public { - require(2==1); - } - function testRevert() public { - revert(); - } - // function testThrow() public { - // throw; - //} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest3TestRevertContract.sol b/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest3TestRevertContract.sol deleted file mode 100644 index 229fa6a74b0..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest3TestRevertContract.sol +++ /dev/null @@ -1,15 +0,0 @@ -//pragma solidity ^0.4.0; -contract TestThrowsContract{ - function testAssert() public { - assert(1==2); - } - function testRequire() public { - require(2==1); - } - function testRevert() public { - revert(); - } - // function testThrow(){ - // throw; - // } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest4noPayableContract.sol b/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest4noPayableContract.sol deleted file mode 100644 index aa043ad9c3b..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest4noPayableContract.sol +++ /dev/null @@ -1,8 +0,0 @@ -//pragma solidity ^0.4.0; - -contract noPayableContract { - -function noPayable() public payable returns (uint){ -return msg.value; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest4noPayableContract_1.sol b/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest4noPayableContract_1.sol deleted file mode 100644 index fe7ba275736..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest4noPayableContract_1.sol +++ /dev/null @@ -1,8 +0,0 @@ -//pragma solidity ^0.4.0; - -contract noPayableContract { - -function noPayable() public returns (uint){ -return msg.value; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest5noPayableConstructor.sol b/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest5noPayableConstructor.sol deleted file mode 100644 index e1733b0562b..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest5noPayableConstructor.sol +++ /dev/null @@ -1,11 +0,0 @@ -//pragma solidity ^0.4.0; - -contract MyContract { - uint money; - - //function MyContract(uint _money) { - constructor(uint _money) public payable{ - require(msg.value >= _money); - money = _money; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest5noPayableConstructor_1.sol b/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest5noPayableConstructor_1.sol deleted file mode 100644 index 793b468d4c2..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest5noPayableConstructor_1.sol +++ /dev/null @@ -1,11 +0,0 @@ -//pragma solidity ^0.4.0; - -contract MyContract { - uint money; - - //function MyContract(uint _money) { - constructor(uint _money) public { - require(msg.value >= _money); - money = _money; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest6transferTestContract.sol b/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest6transferTestContract.sol deleted file mode 100644 index 8c64ff740cd..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest6transferTestContract.sol +++ /dev/null @@ -1,8 +0,0 @@ -//pragma solidity ^0.4.0; - -contract transferTestContract { - function tranferTest(address payable addr) public payable{ - addr.transfer(10); - - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest7payableFallbakContract.sol b/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest7payableFallbakContract.sol deleted file mode 100644 index 85cf454e08e..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest7payableFallbakContract.sol +++ /dev/null @@ -1,14 +0,0 @@ -//pragma solidity ^0.4.0; - -contract Test { - function() external { x = 1; } - uint x; -} - - -contract Caller { - function callTest(Test test) public { - //test.call(0xabcdef01); // hash does not exist - address(test).call(abi.encode(0xabcdef01)); // hash does not exist - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest8newContractGasNoenough.sol b/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest8newContractGasNoenough.sol deleted file mode 100644 index b322ac68591..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest8newContractGasNoenough.sol +++ /dev/null @@ -1,19 +0,0 @@ -//pragma solidity ^0.4.0; - -contract Account{ - uint256 public accId; - - // function Account(uint accountId) payable{ - constructor(uint accountId) payable public { - accId = accountId; - } -} - -contract Initialize{ - // Account public account = new Account(10); - - function newAccount() public { - Account account = new Account(1); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest9MessageUsedErrorFeed.sol b/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest9MessageUsedErrorFeed.sol deleted file mode 100644 index 05448bfd0ac..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontest9MessageUsedErrorFeed.sol +++ /dev/null @@ -1,18 +0,0 @@ -//pragma solidity ^0.4.0; - -contract MathedFeed { - - function divideMathed() public returns (uint ret) { - uint x=1; - uint y=0; - return x/y; - } -} - - -contract MathedUseContract { - - function MathedUse(address addr) public returns (uint) { - return MathedFeed(addr).divideMathed(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontestFunctionUsedErrorFeed.sol b/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontestFunctionUsedErrorFeed.sol deleted file mode 100644 index b7f5244954d..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/requireExceptiontestFunctionUsedErrorFeed.sol +++ /dev/null @@ -1,17 +0,0 @@ -//pragma solidity ^0.4.0; - -contract MessageFeed { - - function mValue() payable public returns (uint ret) { - return msg.value; - } -} - -contract MessageUseContract { - function inputValue() payable public returns (uint){ - return msg.value; - } - function messageUse(address addr) payable public returns (uint) { - return MessageFeed(addr).mValue.value(1)(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/selector.sol b/framework/src/test/resources/soliditycode_0.5.15/selector.sol deleted file mode 100644 index 411e36b0b8e..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/selector.sol +++ /dev/null @@ -1,21 +0,0 @@ -pragma solidity ^0; - -library A { - function getBalance(address) public view returns (uint256) { - return address(this).balance; - } - - function getamount(address) external view returns (uint256) { - return address(this).balance; - } -} - -contract testSelector { - using A for address; - - - function getselector2() public view returns (bytes4, bytes4) { - return (A.getBalance.selector, A.getamount.selector); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/stackContract001.sol b/framework/src/test/resources/soliditycode_0.5.15/stackContract001.sol deleted file mode 100644 index 19041b1e405..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/stackContract001.sol +++ /dev/null @@ -1,61 +0,0 @@ -pragma solidity ^0.5.0; - -contract A{ - event log(uint256); - constructor() payable public{ - emit log(withdrawreward()); - emit log(address(this).rewardbalance); - } - function withdrawRewardTest() public returns (uint256){ - return withdrawreward(); - } - - function test() public{ - emit log(123); - } -} - -contract B{ - event log(uint256); - constructor() payable public{ - emit log(withdrawreward()); - emit log(address(this).rewardbalance); - } - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - function UnStake() public returns (bool result){ - return unstake(); - } - function SelfdestructTest(address payable target) public{ - selfdestruct(target); - } - function rewardBalance(address addr) public view returns (uint256){ - return addr.rewardbalance; - } - - function nullAddressTest() public view returns (uint256) { - return address(0x0).rewardbalance; - } - - function localContractAddrTest() public view returns (uint256) { - address payable localContract = address(uint160(address(this))); - return localContract.rewardbalance; - } - - function withdrawRewardTest() public returns (uint256){ - return withdrawreward(); - } - - function contractBWithdrawRewardTest(address contractB) public returns (uint) { - return B(contractB).withdrawRewardTest(); - } - - function createA() public returns (address){ - return address(new A()); - } - - function callA(address Addr) public{ - A(Addr).test(); - } -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/stackSuicide001.sol b/framework/src/test/resources/soliditycode_0.5.15/stackSuicide001.sol deleted file mode 100644 index a71816ddabd..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/stackSuicide001.sol +++ /dev/null @@ -1,84 +0,0 @@ -pragma solidity ^0.5.0; -contract testStakeSuicide{ - B b; - constructor() payable public{} - function deployB() payable public returns (B addrB){ - b = (new B).value(1000000000)(); - return b; - } - function SelfdestructTest(address payable target) public{ - selfdestruct(target); - } - function SelfdestructTest2(address sr, uint256 amount, address payable target) public{ - stake(sr, amount); - selfdestruct(target); - } - function Stake(address sr, uint256 amount) public payable returns (bool result){ - return stake(sr, amount); - } - function Stake2(address sr, uint256 amount) public returns (bool result){ - stake(sr, amount); - return stake(sr, amount); - } - function UnStake() public returns (bool result){ - return unstake(); - } - function UnStake2() public returns (bool result){ - unstake(); - return unstake(); - } - function WithdrawReward() public { - withdrawreward(); - } - function RewardBalance(address addr) view public returns (uint256 balance) { - return addr.rewardbalance; - } - function revertTest1(address sr, uint256 amount, address payable transferAddr) public{ - transferAddr.transfer(1000000); - stake(sr, amount); - transferAddr.transfer(2000000); - stake(sr, 1000000000000000);//stake more than balance to fail - transferAddr.transfer(4000000); - } - function revertTest2(address payable transferAddr) public{ - transferAddr.transfer(1000000); - unstake(); - transferAddr.transfer(2000000); - unstake();//unstake twice to fail - transferAddr.transfer(4000000); - } - - function BStake(address sr, uint256 amount) public returns (bool result){ - return b.Stake(sr, amount); - } - function BUnStake() public returns (bool result){ - return b.UnStake(); - } - function transfer(address payable add,uint256 num) public { - return add.transfer(num); - } -} - -contract B{ - constructor() payable public{} - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - function UnStake() public returns (bool result){ - return unstake(); - } - function SelfdestructTest(address payable target) public{ - selfdestruct(target); - } - - function deploy(bytes memory code, uint256 salt) public returns(address) { - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - return addr; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/stringSplit.sol b/framework/src/test/resources/soliditycode_0.5.15/stringSplit.sol deleted file mode 100644 index 5a7f5bdd4c9..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/stringSplit.sol +++ /dev/null @@ -1,45 +0,0 @@ -pragma solidity ^0; - -contract testStringSplit { -string s1 = "s""1""2"",./"; -string s2 = "s123?\\'."; -string s3 = hex"41"hex"42"; -string s4 = hex"4142"; - -function getS1() public view returns (string memory) { -return s1; -} - -function getS1N1() public pure returns (string memory) { -string memory n1 = "s""1""2"",./"; -return n1; -} - -function getS2() public view returns (string memory) { -return s2; -} - -function getS2N2() public pure returns (string memory) { -string memory n2 = "s123?\'."; -return n2; -} - -function getS3() public view returns (string memory) { -return s3; -} - -function getS3N3() public pure returns (string memory) { -string memory n3 = hex"41"hex"42"; -return n3; -} - -function getS4() public view returns (string memory) { -return s4; -} - -function getS4N4() public pure returns (string memory) { -string memory n4 = hex"4142"; -return n4; -} - -} diff --git a/framework/src/test/resources/soliditycode_0.5.15/suicide001.sol b/framework/src/test/resources/soliditycode_0.5.15/suicide001.sol deleted file mode 100644 index 3544f8bf84a..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/suicide001.sol +++ /dev/null @@ -1,32 +0,0 @@ -contract factory { - constructor() payable public { - } - - function create1() payable public returns (address){ - Caller add = (new Caller).value(0)(); - return address(add); - } - - function kill() payable public{ - selfdestruct(msg.sender); - } - - function create2(bytes memory code, uint256 salt) public returns(address){ - Caller addr; - Caller addr1; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - return address(addr); - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/suicide002.sol b/framework/src/test/resources/soliditycode_0.5.15/suicide002.sol deleted file mode 100644 index 160ab64f320..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/suicide002.sol +++ /dev/null @@ -1,43 +0,0 @@ -contract Factory { - uint256 public num; - event Deployed(address addr, uint256 salt, address sender); - constructor() public { - } - function deploy(bytes memory code, uint256 salt) public returns(address){ - TestConstract addr; - TestConstract addr1; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - - addr.testSuicideNonexistentTarget(msg.sender); - addr.set(); - - assembly { - addr1 := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(address(addr), salt, msg.sender); - return address(addr); - } -} - - - -contract TestConstract { - uint public i=1; - constructor () public { - } - - function set() public{ - i=9; - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/testOutOfMem.sol b/framework/src/test/resources/soliditycode_0.5.15/testOutOfMem.sol deleted file mode 100644 index 8d285b28b7d..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/testOutOfMem.sol +++ /dev/null @@ -1,7 +0,0 @@ -contract Test { - function testOutOfMem(uint256 x) public returns(bytes32 r) { - uint[] memory memVar; - memVar = new uint[](x); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/testStakeSuicide.sol b/framework/src/test/resources/soliditycode_0.5.15/testStakeSuicide.sol deleted file mode 100644 index 6f8ddfe0e3e..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/testStakeSuicide.sol +++ /dev/null @@ -1,71 +0,0 @@ -pragma solidity ^0.5.0; -contract testStakeSuicide{ - B b; - constructor() payable public{} - function deployB() payable public returns (B addrB){ - b = (new B).value(1000000000)(); - return b; - } - function SelfdestructTest(address payable target) public{ - selfdestruct(target); - } - function SelfdestructTest2(address sr, uint256 amount, address payable target) public{ - stake(sr, amount); - selfdestruct(target); - } - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - function Stake2(address sr, uint256 amount) public returns (bool result){ - stake(sr, amount); - return stake(sr, amount); - } - function UnStake() public returns (bool result){ - return unstake(); - } - function UnStake2() public returns (bool result){ - unstake(); - return unstake(); - } - function WithdrawReward() public { - withdrawreward(); - } - function RewardBalance(address addr) view public returns (uint256 balance) { - return addr.rewardbalance; - } - function revertTest1(address sr, uint256 amount, address payable transferAddr) public{ - transferAddr.transfer(1000000); - stake(sr, amount); - transferAddr.transfer(2000000); - stake(sr, 1000000000000000);//stake more than balance to fail - transferAddr.transfer(4000000); - } - function revertTest2(address payable transferAddr) public{ - transferAddr.transfer(1000000); - unstake(); - transferAddr.transfer(2000000); - unstake();//unstake twice to fail - transferAddr.transfer(4000000); - } - function BStake(address sr, uint256 amount) public returns (bool result){ - return b.Stake(sr, amount); - } - function BUnStake() public returns (bool result){ - return b.UnStake(); - } - function BSelfdestructTest(address payable target) public{ - b.SelfdestructTest(target); - } -} -contract B{ - constructor() payable public{} - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - function UnStake() public returns (bool result){ - return unstake(); - } - function SelfdestructTest(address payable target) public{ - selfdestruct(target); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/tryCatch001.sol b/framework/src/test/resources/soliditycode_0.5.15/tryCatch001.sol deleted file mode 100644 index 5692fe84540..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/tryCatch001.sol +++ /dev/null @@ -1,105 +0,0 @@ -pragma solidity ^0.6.0; - -enum ErrorType { - Revert_Error, //0 - RevertWithMsg_Error, //1 - Require_Error, //2 - RequirewithMsg_Error, //3 - Assert_Error, //4 - Tansfer_Error, //5 - Send_Error, //6 - Math_Error, //7 - ArrayOverFlow_Error //8 -} -contract errorContract { - uint256[] arraryUint ; - - function errorSwitch(uint256 errorType) public returns(string memory) { - if (ErrorType(errorType) == ErrorType.Revert_Error){ - revert(); - } else if (ErrorType(errorType) == ErrorType.RevertWithMsg_Error){ - revert("Revert Msg."); - } else if (ErrorType(errorType) == ErrorType.Require_Error) { - require(0>1); - } else if (ErrorType(errorType) == ErrorType.RequirewithMsg_Error) { - require(0>1,"Require Msg."); - } else if (ErrorType(errorType) == ErrorType.Assert_Error) { - assert(1<0); - } else if (ErrorType(errorType) == ErrorType.Tansfer_Error) { - payable(msg.sender).transfer(1); - } else if (ErrorType(errorType) == ErrorType.Send_Error) { - payable(msg.sender).send(1); - } else if (ErrorType(errorType) == ErrorType.Math_Error) { - uint256 a = 1; - uint256 b = 0; - uint256 n = a / b; - } else if (ErrorType(errorType) == ErrorType.ArrayOverFlow_Error) { - arraryUint.pop(); - } - return "success"; - - } - - function callFun(string memory functionStr, string memory argsStr) public{ - address(this).call(abi.encodeWithSignature(functionStr, argsStr)); - } - -} - -contract NewContract { - uint256[] arraryUint ; - - constructor(uint256 errorType) public payable{ - if (ErrorType(errorType) == ErrorType.Revert_Error){ - revert(); - } else if (ErrorType(errorType) == ErrorType.RevertWithMsg_Error){ - revert("Revert Msg."); - } else if (ErrorType(errorType) == ErrorType.Require_Error) { - require(0>1); - } else if (ErrorType(errorType) == ErrorType.RequirewithMsg_Error) { - require(0>1,"Require Msg."); - } else if (ErrorType(errorType) == ErrorType.Assert_Error) { - assert(1<0); - } else if (ErrorType(errorType) == ErrorType.Tansfer_Error) { - payable(msg.sender).transfer(1); - } else if (ErrorType(errorType) == ErrorType.Send_Error) { - payable(msg.sender).send(1); - } else if (ErrorType(errorType) == ErrorType.Math_Error) { - uint256 a = 1; - uint256 b = 0; - uint256 n = a / b; - } else if (ErrorType(errorType) == ErrorType.ArrayOverFlow_Error) { - arraryUint.pop(); - } - } -} - -contract tryTest { - function getData(errorContract inter, string memory functionStr, string memory argsStr) public payable returns(string memory) { - try inter.callFun(functionStr,argsStr) { - return "123"; - } catch Error(string memory errorMsg/* 出错原因 */) { - return errorMsg; - } catch (bytes memory) { - return "3"; - } - } - - function getErrorSwitch(errorContract add, uint256 errorType ) public payable returns(string memory) { - try add.errorSwitch(errorType) returns (string memory Msg) { - return Msg; - } catch Error(string memory errorMsg/* 出错原因 */) { - return errorMsg; - } catch (bytes memory) { - return "NoErrorMsg"; - } - } - - function catchNewErrorSwitch(uint256 errorType) public returns (address nc){ - try new NewContract(errorType) returns (NewContract nc){ - return address(nc); - }catch { - return address(0x00); - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue001.sol b/framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue001.sol deleted file mode 100644 index fd3c817421b..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue001.sol +++ /dev/null @@ -1,26 +0,0 @@ -pragma solidity ^0.5.12; - -contract tvmAssetIssue001 { - constructor() payable public{} - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - return assetissue(name, abbr, totalSupply, precision); - } - - function updateAsset(trcToken tokenId, string memory url, string memory desc) public returns (bool) { - return updateasset(tokenId, bytes(url), bytes(desc)); - } - - function updateOtherAccountAsset(string memory url, string memory desc) public returns (bool) { - trcToken tokenId = trcToken(1000004); - return updateasset(tokenId, bytes(url), bytes(desc)); - } - - function updateAssetOnBytes(trcToken tokenId, bytes memory url, bytes memory desc) public returns (bool) { - return updateasset(tokenId, url, desc); - } - - function transferToken(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue002.sol b/framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue002.sol deleted file mode 100644 index b158faf6720..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue002.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity ^0.5.12; - -contract tvmAssetIssue002 { - constructor() payable public{} - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - assetissue(name, abbr, totalSupply, precision); - return assetissue(name, abbr, totalSupply, precision); - } - - function updateAsset(trcToken tokenId, string memory url1, string memory desc1, string memory url2, string memory desc2) public returns (bool) { - updateasset(tokenId, bytes(url1), bytes(desc1)); - return updateasset(tokenId, bytes(url2), bytes(desc2)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue003.sol b/framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue003.sol deleted file mode 100644 index 40390238d8f..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue003.sol +++ /dev/null @@ -1,23 +0,0 @@ -pragma solidity ^0.5.12; - -contract tvmAssetIssue003 { - constructor() payable public{} - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - return assetissue(name, abbr, totalSupply, precision); - } - - function tokenIssueAndTransfer(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision, address addr) public { - address payable newaddress = address(uint160(addr)); - newaddress.transfer(100000000); - assetissue(name, abbr, totalSupply, precision); - newaddress.transfer(100000000); - } - - function updateAssetAndTransfer(trcToken tokenId, string memory url, string memory desc, address addr) public { - address payable newaddress = address(uint160(addr)); - newaddress.transfer(100000000); - updateasset(tokenId, bytes(url), bytes(desc)); - newaddress.transfer(100000000); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue004.sol b/framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue004.sol deleted file mode 100644 index fbebdb26e68..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue004.sol +++ /dev/null @@ -1,39 +0,0 @@ -pragma solidity ^0.5.12; - -contract A { - - constructor() payable public{} - function() payable external {} - - function tokenIssueA(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint){ - return assetissue(name, abbr, totalSupply, precision); - } - - function updateAssetA(trcToken tokenId, string memory url, string memory desc) public returns (bool) { - return updateasset(tokenId, bytes(url), bytes(desc)); - } - - function transferToken(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } -} - -contract tvmAssetIssue004 { - - A a; - - constructor() payable public{} - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - return a.tokenIssueA(name, abbr, totalSupply, precision); - } - - function updateAsset(trcToken tokenId, string memory url, string memory desc) public returns (bool) { - return a.updateAssetA(tokenId, url, desc); - } - - function getContractAddress() public payable returns (address) { - a = (new A).value(1024000000)(); - return address(a); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue005.sol b/framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue005.sol deleted file mode 100644 index 20fd14944c2..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/tvmAssetIssue005.sol +++ /dev/null @@ -1,45 +0,0 @@ -pragma solidity ^0.5.12; - -contract tvmAssetIssue005 { - constructor() payable public{} - - function() external payable { - } - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - return assetissue(name, abbr, totalSupply, precision); - } - - function updateAsset(trcToken tokenId, string memory url, string memory desc) public returns (bool) { - return updateasset(tokenId, bytes(url), bytes(desc)); - } - - function updateAssetOnBytes(trcToken tokenId, bytes memory url, bytes memory desc) public returns (bool) { - return updateasset(tokenId, url, desc); - } - - function transferToken(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - - function SelfdestructTest(address payable target) public { - selfdestruct(target); - } -} - -contract B { - event Deployed(address addr, uint256 salt); - - function deploy(uint256 salt) public returns (address) { - address addr; - bytes memory code = type(tvmAssetIssue005).creationCode; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt); - return addr; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/typeName.sol b/framework/src/test/resources/soliditycode_0.5.15/typeName.sol deleted file mode 100644 index 5b44abd1bbb..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/typeName.sol +++ /dev/null @@ -1,5 +0,0 @@ -contract TypeName { - function testTypeName() public returns (string memory){ - return type(TypeName).name; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/unStake001.sol b/framework/src/test/resources/soliditycode_0.5.15/unStake001.sol deleted file mode 100644 index 54a9829cd40..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/unStake001.sol +++ /dev/null @@ -1,90 +0,0 @@ -pragma solidity ^0.5.0; - -contract unStakeTest { - B b; - constructor() payable public{} - function deployB() payable public returns (B addrB){ - b = (new B).value(1000000000)(); - return b; - } - - function selfdestructTest(address payable target) public { - selfdestruct(target); - } - - function selfdestructTest2(address sr, uint256 amount, address payable target) public { - stake(sr, amount); - selfdestruct(target); - } - - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - - function stake2(address sr, uint256 amount) public returns (bool result){ - stake(sr, amount); - return stake(sr, amount); - } - - function unStake() public returns (bool result){ - return unstake(); - } - - function unStake2() public returns (bool result){ - unstake(); - return unstake(); - } - - function withdrawReward() public returns (uint256 amount) { - return withdrawreward(); - } - - function rewardBalance(address addr) view public returns (uint256 balance) { - return addr.rewardbalance; - } - - function revertTest1(address sr, uint256 amount, address payable transferAddr) public { - transferAddr.transfer(1000000); - stake(sr, amount); - transferAddr.transfer(2000000); - stake(sr, 1000000000000000); - //stake more than balance to fail - transferAddr.transfer(4000000); - } - - function revertTest2(address payable transferAddr) public { - transferAddr.transfer(1000000); - unstake(); - transferAddr.transfer(2000000); - unstake(); - //unstake twice to fail - transferAddr.transfer(4000000); - } - - function BStake(address sr, uint256 amount) public returns (bool result){ - return b.Stake(sr, amount); - } - - function BUnStake() public returns (bool result){ - return b.UnStake(); - } - - function BSelfdestructTest(address payable target) public { - b.SelfdestructTest(target); - } -} - -contract B { - constructor() payable public{} - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - - function UnStake() public returns (bool result){ - return unstake(); - } - - function SelfdestructTest(address payable target) public { - selfdestruct(target); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/validatemultisign001.sol b/framework/src/test/resources/soliditycode_0.5.15/validatemultisign001.sol deleted file mode 100644 index cc0a742d0c5..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/validatemultisign001.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract validatemultisignTest { - function testmulti(address a, uint256 perid, bytes32 hash, bytes[] memory signatures) public returns (bool){ - return validatemultisign(a, perid, hash, signatures); - } - - function testbatch(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public returns (bytes32){ - return batchvalidatesign(hash, signatures, addresses); - } - - function testMultiPrecompileContract(bytes memory data) public returns(bool, bytes memory){ - return address(0xa).delegatecall(data); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/verifyTransferProof001.sol b/framework/src/test/resources/soliditycode_0.5.15/verifyTransferProof001.sol deleted file mode 100644 index 587b4defd10..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/verifyTransferProof001.sol +++ /dev/null @@ -1,15 +0,0 @@ -contract verifyTransferProofTest { - - function test1() public returns (bool, bytes memory){ - bytes memory empty = ""; - return address(0x1000002).delegatecall(empty); - } - - function test2(bytes memory data) public returns (bool, bytes memory){ - return address(0x1000002).delegatecall(data); - } - - function test3(bytes32[10][] memory input, bytes32[2][] memory spendAuthoritySignature, bytes32[9][] memory output, bytes32[2] memory bindingSignature, bytes32 signHash, uint64 valueBalance, bytes32[33] memory frontier, uint256 leafCount) public returns (bytes32[] memory){ - return verifyTransferProof(input, spendAuthoritySignature, output, bindingSignature, signHash, valueBalance, frontier, leafCount); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.5.15/walletTestMutiSign004.sol b/framework/src/test/resources/soliditycode_0.5.15/walletTestMutiSign004.sol deleted file mode 100644 index 7b943aee5c1..00000000000 --- a/framework/src/test/resources/soliditycode_0.5.15/walletTestMutiSign004.sol +++ /dev/null @@ -1,51 +0,0 @@ -contract timeoutTest { - string public iarray1; - // cpu - function oneCpu() public { - require(1==1); - } - - function storage8Char() public { - iarray1 = "12345678"; - } - - function testUseCpu(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - } - return count; - } - - - uint256[] public iarray; - uint public calculatedFibNumber; - mapping(address=>mapping(address=>uint256)) public m; - - function testUseStorage(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - iarray.push(i); - } - return count; - } - - // stack - //uint n = 0; - uint yy = 0; - function test() public { - //n += 1; - yy += 1; - test(); - } - - function setFibonacci(uint n) public returns (uint256){ - calculatedFibNumber = fibonacci(n); - return calculatedFibNumber; - } - - function fibonacci(uint n) internal returns (uint) { - return fibonacci(n - 1) + fibonacci(n - 2); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/AssertException002.sol b/framework/src/test/resources/soliditycode_0.6.12/AssertException002.sol deleted file mode 100644 index 15cc07ff984..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/AssertException002.sol +++ /dev/null @@ -1,17 +0,0 @@ - - -contract AssertException{ - function divideIHaveArgsReturn(int x,int y) public returns (int z) { - return x / y; - } - function testAssert() public { - require(2==1); - } -} -contract C { - constructor() public payable { - assert(1==2); - } - function fun() public { - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/AssignToExternal.sol b/framework/src/test/resources/soliditycode_0.6.12/AssignToExternal.sol deleted file mode 100644 index d4f09590a36..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/AssignToExternal.sol +++ /dev/null @@ -1,30 +0,0 @@ -contract AssignToExternal { - // Not allow: - // function f(uint256[] calldata x, uint256[] calldata y) external pure { - // x = y; - // } - - // allow: - - function f(uint256 a) external returns (uint){ - a = a + 1; - return a; - } - - function StringSet(string calldata a) external returns (string memory){ - return a; - } - - function ByteSet(bytes32 a) external returns (bytes32){ - return a; - } - - function UintArraySet(uint256[2] calldata a) external returns (uint256[2] memory){ - return a; - } - - function AddSet(address a) external returns (address){ - return a; - } - -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/BlockHash.sol b/framework/src/test/resources/soliditycode_0.6.12/BlockHash.sol deleted file mode 100644 index 6603da65e44..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/BlockHash.sol +++ /dev/null @@ -1,38 +0,0 @@ -contract TestBlockHash { - - function testOR1(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = blockhash(block.number - 1) | bytes32(value); - return (b1, c, blockhash(block.number - 1)); - } - - function testOR2(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = bytes32(value) | blockhash(block.number - 1); - return (b1, c, blockhash(block.number - 1)); - } - - function testAND1(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = blockhash(block.number - 1) & bytes32(value); - return (b1, c, blockhash(block.number - 1)); - } - - function testAND2(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = bytes32(value) & blockhash(block.number - 1); - return (b1, c, blockhash(block.number - 1)); - } - - function testXOR1(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = blockhash(block.number - 1) ^ bytes32(value); - return (b1, c, blockhash(block.number - 1)); - } - - function testXOR2(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = bytes32(value) ^ blockhash(block.number - 1); - return (b1, c, blockhash(block.number - 1)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/ClearAbi001.sol b/framework/src/test/resources/soliditycode_0.6.12/ClearAbi001.sol deleted file mode 100644 index 39a8e8cf005..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/ClearAbi001.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract testConstantContract{ -function testPayable() public view returns (int z) { -return 1; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/ClearAbi005.sol b/framework/src/test/resources/soliditycode_0.6.12/ClearAbi005.sol deleted file mode 100644 index a3115398386..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/ClearAbi005.sol +++ /dev/null @@ -1,26 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract TestConstract { - uint public i=0; - constructor () public { - } - function plusOne() public returns(uint){ - i++; - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/ConstructorDefaults.sol b/framework/src/test/resources/soliditycode_0.6.12/ConstructorDefaults.sol deleted file mode 100644 index 4b6186ccb95..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/ConstructorDefaults.sol +++ /dev/null @@ -1,9 +0,0 @@ -contract testIsContract{ - bool result; - constructor (bool a) public { - result = a; - } -function test( address a) public returns (bool) { -return result; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/Create2Test023.sol b/framework/src/test/resources/soliditycode_0.6.12/Create2Test023.sol deleted file mode 100644 index 4c3f8af9f2b..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/Create2Test023.sol +++ /dev/null @@ -1,31 +0,0 @@ -contract factory { - constructor() payable public { - } - - function deploy(bytes memory code, uint256 salt) public returns(address){ - Caller addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - return address(addr); - } - - function testCreate() payable public returns (address){ - Caller add = (new Caller).value(0)(); - return address(add); - } - - function kill( ) payable public{ - selfdestruct(msg.sender); - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/Create2Test024.sol b/framework/src/test/resources/soliditycode_0.6.12/Create2Test024.sol deleted file mode 100644 index f5a9d032cff..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/Create2Test024.sol +++ /dev/null @@ -1,56 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - TestConstract addr; - TestConstract addr1; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - - addr.testSuicideNonexistentTarget(msg.sender); - addr.set(); - emit Deployed(address(addr), salt, msg.sender); - return address(addr); - } - - function deploy2(bytes memory code, uint256 salt) public returns(address){ - TestConstract addr; - TestConstract addr1; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - - //addr.testSuicideNonexistentTarget(msg.sender); - //addr.set(); - - assembly { - addr1 := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(address(addr), salt, msg.sender); - return address(addr); - } -} - - - -contract TestConstract { - uint public i=1; - constructor () public { - } - - function set() public{ - i=9; - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/Create2Test025.sol b/framework/src/test/resources/soliditycode_0.6.12/Create2Test025.sol deleted file mode 100644 index 895dc43e56f..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/Create2Test025.sol +++ /dev/null @@ -1,34 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - constructor() public { - } - - function create2(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } - - function get(bytes1 prefix, bytes calldata code, uint256 salt) external view returns(address) { - //bytes32 hash = keccak256(abi.encodePacked(bytes1(0x41),address(this), salt, keccak256(code))); - bytes32 hash = keccak256(abi.encodePacked(prefix,address(this), salt, keccak256(code))); - address addr = address(uint160(uint256(hash))); - return addr; - } -} - -contract TestContract{ - uint256 public num; - constructor(uint256 j) public{ - num = j; - } - function getNum() public returns (uint256){ - return num; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/ExtCodeHashTest010.sol b/framework/src/test/resources/soliditycode_0.6.12/ExtCodeHashTest010.sol deleted file mode 100644 index bfa8a7fa0d8..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/ExtCodeHashTest010.sol +++ /dev/null @@ -1,46 +0,0 @@ -contract Counter { - uint count = 0; - address payable owner; - event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); - constructor() public{ - owner = msg.sender; - } - function getCodeHashSuicide(address addr) public returns (bytes32 _hashBefore){ - assembly{ - _hashBefore := extcodehash(addr) - } - selfdestruct(owner); - return _hashBefore; - } - - function getCodeHashRevert() public returns (bytes32 _hashBefore, bytes32 _hashAfter) { - address addr = address(this); - assembly { - _hashBefore := extcodehash(addr) - } - if (owner == msg.sender) { - selfdestruct(owner); - } - assembly { - _hashAfter := extcodehash(addr) - } - revert(); - emit LogResult(_hashBefore, _hashAfter); - } - - function getCodeHashCreate() public returns (bytes32 _hashBefore){ - TestContract A = (new TestContract).value(0)(); - address addr = address(A); - assembly{ - _hashBefore := extcodehash(addr) - } - revert(); - return _hashBefore; - } -} - -contract TestContract{ - uint256 count = 1; - constructor() public payable{ - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/ExternalSelector.sol b/framework/src/test/resources/soliditycode_0.6.12/ExternalSelector.sol deleted file mode 100644 index 0359813e275..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/ExternalSelector.sol +++ /dev/null @@ -1,92 +0,0 @@ -pragma solidity ^0.6.0; - -contract selectorContract { - function testSelectorNoParam() external pure returns(uint) { - return 11; - } - - function testSelectorWithParam(uint x) external pure returns(uint) { - return 22; - } -} - -interface interfaceSelector { - function getSelector() external pure returns(uint); -} - -interface B is interfaceSelector { - // interface现在可以继承自其他interface - function testImplemention() external pure returns(uint); -} - -contract implementContract is B{ - function getSelector() external override pure returns(uint) { - return 66; - } - - function testImplemention() external override pure returns(uint) { - return 77; - } - - constructor() public payable {} -} - -contract basicContract{ - function testNewUse() external payable returns(uint) { - return 345; - } - - constructor() public payable {} -} - -contract TestGasValue{ - constructor() public payable {} - - function testNewUse() external payable returns(uint) { - return 123; - } - basicContract bc = new basicContract(); - // external方法在调用时可以采用c.f{gas: 10000, value: 4 trx}()的形式 - function callWithGasAndValue(uint x,uint y) external returns(uint) { - return bc.testNewUse{gas:x, value:y}(); - } - - function callThisNoGasAnd1Value() external returns(uint) { - return this.testNewUse{gas:0, value:1}(); - } - - // inline assembly中允许true和false字面量 - function testAssemblyTrue() public pure returns(uint x) { - assembly { - x := true - } - } - - // inline assembly中允许true和false字面量 - function testAssemblyFalse() public pure returns(uint x) { - assembly { - x := false - } - } - - // create2的high-level用法new C{salt: 0x1234, value: 1 ether}(arg1, arg2) - function testCreate2() public returns(address) { - basicContract c = new basicContract{salt: bytes32(bytes1(0x01)), value: 1 trx}(); - return address(c); - } - - - function getContractSelectorNoParam() public pure returns(bytes4) { - return selectorContract.testSelectorNoParam.selector; - } - - function getContractSelectorWithParam() public pure returns(bytes4) { - return selectorContract.testSelectorWithParam.selector; - } - - function getInterfaceSelectorNoParam() public pure returns(bytes4) { - return interfaceSelector.getSelector.selector; - } - -} - diff --git a/framework/src/test/resources/soliditycode_0.6.12/NewFeature068.sol b/framework/src/test/resources/soliditycode_0.6.12/NewFeature068.sol deleted file mode 100644 index f5c19435f7c..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/NewFeature068.sol +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.6.8; - -abstract contract testModifier { - modifier isOwner() virtual; -} - -abstract contract testInterfaceId { - function getValue() external view virtual returns(uint); - function getOwner() external view virtual returns(uint); - -} - -interface a { - function getValue() external view returns(uint); - function getOwner() external view returns(uint); -} - -contract testMapKey is testModifier{ - - enum size{ - SMALL, - LARGE - } - - mapping(size => uint) public enums; - - mapping(testMapKey => uint) public contracts; - - function setEnumValue(uint value) public { - enums[size.SMALL] = value; - } - - function getEnumValue() public view returns(uint) { - return enums[size.SMALL]; - } - - function setContractValue() public { - contracts[this] = 2; - } - - function getContractValue() public view returns(uint) { - return contracts[this]; - } - - bytes4 constant functionSelector = this.getEnumValue.selector; - - function getfunctionSelector() public pure returns(bytes4) { - return functionSelector; - } - - uint immutable x; - address immutable owner = msg.sender; - - constructor() public { - x = 5; - } - - string b = "test"; - - function testStorage() public view returns(string memory) { - string storage aa; - aa = b; - return aa; - - } - - function getImmutableVal() public view returns(uint) { - return x; - } - - function getOwner() public view returns(address) { - return owner; - } - - function getInterfaceId() public pure returns(bytes4,bytes4) { - return (type(a).interfaceId, type(testInterfaceId).interfaceId); - } - - modifier isOwner() override { - require(msg.sender == owner); - _; - } - - function requireOwner() public view isOwner returns(uint) { - return 6; - } - - - function getUint256MinAndMax() public pure returns(uint, uint) { - return (type(uint).min, type(uint).max); - } - - - function getUint8MinAndMax() public pure returns(uint8, uint8) { - return (type(uint8).min, type(uint8).max); - } - -} - - -abstract contract base { - function abstractfun() virtual public returns(uint); -} - -abstract contract callEmptyFunction is base { - function callfun() public returns(uint) { - return abstractfun(); - } -} - - - - - - - - - - - - - - - - diff --git a/framework/src/test/resources/soliditycode_0.6.12/ParentTypeBug.sol b/framework/src/test/resources/soliditycode_0.6.12/ParentTypeBug.sol deleted file mode 100644 index 897c843ae24..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/ParentTypeBug.sol +++ /dev/null @@ -1,13 +0,0 @@ -contract Parent { - uint256 public m_aMember; - address public m_bMember; -} -contract Child is Parent { - function foo() public view returns (uint256) { return Parent.m_aMember; } - function bar() public view returns (address) { return Parent.m_bMember; } - - // complie failed - // function foo() public pure returns (uint256) { return Parent.m_aMember; } - // function bar() public pure returns (address) { return Parent.m_bMember; } - -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/SafeMath.sol b/framework/src/test/resources/soliditycode_0.6.12/SafeMath.sol deleted file mode 100644 index 1a7f1be2b8e..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/SafeMath.sol +++ /dev/null @@ -1,149 +0,0 @@ - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/ShiftCommand001.sol b/framework/src/test/resources/soliditycode_0.6.12/ShiftCommand001.sol deleted file mode 100644 index 574ee2b571b..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/ShiftCommand001.sol +++ /dev/null @@ -1,18 +0,0 @@ -contract TestBitwiseShift { - - function shlTest(uint256 num, uint256 input) public returns (bytes32 out) { - assembly { - out := shl(num, input) - } - } - function shrTest(uint256 num, uint256 input) public returns (bytes32 out) { - assembly { - out := shr(num, input) - } - } - function sarTest(uint256 num, uint256 input) public returns (bytes32 out) { - assembly { - out := sar(num, input) - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/SolidityMappingFix.sol b/framework/src/test/resources/soliditycode_0.6.12/SolidityMappingFix.sol deleted file mode 100644 index 67692d3b4ae..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/SolidityMappingFix.sol +++ /dev/null @@ -1,9 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Tests { - mapping(address => uint) public balances; - function update(uint256 amount) public returns (address addr) - { - balances[msg.sender] = amount; - return msg.sender; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/TestMappings_array_pop.sol b/framework/src/test/resources/soliditycode_0.6.12/TestMappings_array_pop.sol deleted file mode 100644 index 0d5c4bb7013..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TestMappings_array_pop.sol +++ /dev/null @@ -1,19 +0,0 @@ -contract C { - mapping (uint256 => uint256)[] a; - - function n1(uint256 key, uint256 value) public { - a.push(); - a[a.length - 1][key] = value; - } - - - - function map(uint256 key) public view returns (uint) { - return a[a.length - 1][key]; - } - - function p() public { - a.pop(); - } -} - diff --git a/framework/src/test/resources/soliditycode_0.6.12/TransferFailed001.sol b/framework/src/test/resources/soliditycode_0.6.12/TransferFailed001.sol deleted file mode 100644 index dba043edcb3..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TransferFailed001.sol +++ /dev/null @@ -1,147 +0,0 @@ -contract EnergyOfTransferFailedTest { - constructor() payable public { - - } - - function testTransferTokenCompiledLongMax() payable public{ - address(0x1).transferToken(1,9223372036855775827); - } - - function testTransferTokenCompiled() payable public{ - address(0x1).transferToken(1,1); - } - - function testTransferTokenCompiledLongMin() payable public{ - //address(0x1).transferToken(1,-9223372036855775828); - } - - function testTransferTokenCompiledLongMin1() payable public returns(uint256){ - return address(0x2).tokenBalance(trcToken(-9223372036855775828)); - } - - function testTransferTokenCompiled1() payable public returns(uint256){ - return address(0x1).tokenBalance(trcToken(1)); - } - - function testTransferTokenCompiledLongMax1() payable public returns(uint256){ - return address(0x2).tokenBalance(trcToken(9223372036855775827)); - } - - function testTransferTokenCompiledTokenId(uint256 tokenid) payable public returns(uint256){ - return address(0x1).tokenBalance(trcToken(tokenid)); - } - - function testTransferTokenTest(address addr ,uint256 tokenid) payable public returns(uint256){ - return addr.tokenBalance(trcToken(tokenid)); - } - - // InsufficientBalance - function testTransferTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.transfer(i); - } - - function testSendTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.send(i); - } - - function testTransferTokenInsufficientBalance(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - - function testCallTrxInsufficientBalance(uint256 i,address payable caller) public { - caller.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testCreateTrxInsufficientBalance(uint256 i) payable public { - (new Caller).value(i)(); - } - - // NonexistentTarget - - function testSendTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - nonexistentTarget.send(i); - } - - function testSendTrxRevert(uint256 i,address payable nonexistentTarget) payable public { - nonexistentTarget.send(i); - revert(); - } - - function testTransferTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - nonexistentTarget.transfer(i); - } - - function testTransferTrxrevert(uint256 i,address payable nonexistentTarget) payable public{ - nonexistentTarget.transfer(i); - revert(); - } - - function testTransferTokenNonexistentTarget(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - nonexistentTarget.transferToken(i, tokenId); - } - - function testTransferTokenRevert(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - nonexistentTarget.transferToken(i, tokenId); - revert(); - } - - function testCallTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - nonexistentTarget.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } - - function testSuicideRevert(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - revert(); - } - - // target is self - function testTransferTrxSelf(uint256 i) payable public{ - address payable self = address(uint160(address(this))); - self.transfer(i); - } - - function testSendTrxSelf(uint256 i) payable public{ - address payable self = address(uint160(address(this))); - self.send(i); - } - - function testTransferTokenSelf(uint256 i,trcToken tokenId) payable public{ - address payable self = address(uint160(address(this))); - self.transferToken(i, tokenId); - } - - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(10, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } - function deploy2(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(300, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/TransferFailed005.sol b/framework/src/test/resources/soliditycode_0.6.12/TransferFailed005.sol deleted file mode 100644 index aa39aafa152..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TransferFailed005.sol +++ /dev/null @@ -1,90 +0,0 @@ -contract EnergyOfTransferFailedTest { - constructor() payable public { - - } - // InsufficientBalance - function testTransferTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.transfer(i); - } - - function testSendTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.send(i); - } - - function testTransferTokenInsufficientBalance(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - - function testCallTrxInsufficientBalance(uint256 i,address payable caller) public returns (bool,bytes memory){ - return caller.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testCreateTrxInsufficientBalance(uint256 i) payable public { - (new Caller).value(i)(); - } - - // NonexistentTarget - - function testSendTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.send(i); - } - - function testTransferTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.transfer(i); - } - - function testTransferTokenNonexistentTarget(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - require(address(this).balance >= i); - nonexistentTarget.transferToken(i, tokenId); - } - - function testCallTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } - - // target is self - function testTransferTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.transfer(i); - } - - function testSendTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.send(i); - } - - function testTransferTokenSelf(uint256 i,trcToken tokenId) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.transferToken(i, tokenId); - } - - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(10, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256 ){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/TransferFailed006.sol b/framework/src/test/resources/soliditycode_0.6.12/TransferFailed006.sol deleted file mode 100644 index aa39aafa152..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TransferFailed006.sol +++ /dev/null @@ -1,90 +0,0 @@ -contract EnergyOfTransferFailedTest { - constructor() payable public { - - } - // InsufficientBalance - function testTransferTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.transfer(i); - } - - function testSendTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.send(i); - } - - function testTransferTokenInsufficientBalance(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - - function testCallTrxInsufficientBalance(uint256 i,address payable caller) public returns (bool,bytes memory){ - return caller.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testCreateTrxInsufficientBalance(uint256 i) payable public { - (new Caller).value(i)(); - } - - // NonexistentTarget - - function testSendTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.send(i); - } - - function testTransferTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.transfer(i); - } - - function testTransferTokenNonexistentTarget(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - require(address(this).balance >= i); - nonexistentTarget.transferToken(i, tokenId); - } - - function testCallTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } - - // target is self - function testTransferTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.transfer(i); - } - - function testSendTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.send(i); - } - - function testTransferTokenSelf(uint256 i,trcToken tokenId) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.transferToken(i, tokenId); - } - - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(10, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256 ){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/TransferFailed007.sol b/framework/src/test/resources/soliditycode_0.6.12/TransferFailed007.sol deleted file mode 100644 index aa39aafa152..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TransferFailed007.sol +++ /dev/null @@ -1,90 +0,0 @@ -contract EnergyOfTransferFailedTest { - constructor() payable public { - - } - // InsufficientBalance - function testTransferTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.transfer(i); - } - - function testSendTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.send(i); - } - - function testTransferTokenInsufficientBalance(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - - function testCallTrxInsufficientBalance(uint256 i,address payable caller) public returns (bool,bytes memory){ - return caller.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testCreateTrxInsufficientBalance(uint256 i) payable public { - (new Caller).value(i)(); - } - - // NonexistentTarget - - function testSendTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.send(i); - } - - function testTransferTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.transfer(i); - } - - function testTransferTokenNonexistentTarget(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - require(address(this).balance >= i); - nonexistentTarget.transferToken(i, tokenId); - } - - function testCallTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } - - // target is self - function testTransferTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.transfer(i); - } - - function testSendTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.send(i); - } - - function testTransferTokenSelf(uint256 i,trcToken tokenId) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.transferToken(i, tokenId); - } - - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(10, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256 ){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/TriggerConstant001.sol b/framework/src/test/resources/soliditycode_0.6.12/TriggerConstant001.sol deleted file mode 100644 index b385850577d..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TriggerConstant001.sol +++ /dev/null @@ -1,28 +0,0 @@ - - -contract testConstantContract{ - uint256 public i; - function testPayable() public payable returns (uint256 z) { - i=1; - z=i; - return z; - } - function testNoPayable() public returns (uint256 z) { - i=1; - z=i; - return z; - } - function testView() public view returns (uint256 z) { - uint256 i=1; - return i; - } - function testPure() public pure returns (uint256 z) { - uint256 i=1; - return i; - } - function testView2() public view returns (uint256 z) { - uint256 i=1; - revert(); - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/TriggerConstant002.sol b/framework/src/test/resources/soliditycode_0.6.12/TriggerConstant002.sol deleted file mode 100644 index 7708d81792a..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TriggerConstant002.sol +++ /dev/null @@ -1,10 +0,0 @@ - - -contract testConstantContract{ - uint256 public i; - function testNoPayable() public returns (uint256 z) { - i=1; - z=i; - return z; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/TriggerConstant003.sol b/framework/src/test/resources/soliditycode_0.6.12/TriggerConstant003.sol deleted file mode 100644 index 947b3f610e6..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TriggerConstant003.sol +++ /dev/null @@ -1,18 +0,0 @@ - - -contract testConstantContract{ - function testView() public view returns (uint256 z) { - uint256 i=1; - return i; - } - - function testPure() public pure returns (uint256 z) { - uint256 i=1; - return i; - } - - function testPayable() public payable returns (uint256 z) { - uint256 i=1; - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/TriggerConstant004.sol b/framework/src/test/resources/soliditycode_0.6.12/TriggerConstant004.sol deleted file mode 100644 index 7fcb44950e7..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TriggerConstant004.sol +++ /dev/null @@ -1,8 +0,0 @@ - - -contract testConstantContract{ -function testPure() public pure returns (uint256 z) { -uint256 i=1; -return i; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/TriggerConstant015.sol b/framework/src/test/resources/soliditycode_0.6.12/TriggerConstant015.sol deleted file mode 100644 index d926c43c824..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TriggerConstant015.sol +++ /dev/null @@ -1,24 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract TestConstract { - constructor () public { - } - function plusOne() public returns(uint){ - return 1; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/TriggerConstant024.sol b/framework/src/test/resources/soliditycode_0.6.12/TriggerConstant024.sol deleted file mode 100644 index 69ad3a2d5b5..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TriggerConstant024.sol +++ /dev/null @@ -1,9 +0,0 @@ - - -contract testConstantContract{ -function testView() public view returns (uint256 z) { -uint256 i=1; -revert(); -return i; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/TvmIsContract.sol b/framework/src/test/resources/soliditycode_0.6.12/TvmIsContract.sol deleted file mode 100644 index 4266b9e92ca..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TvmIsContract.sol +++ /dev/null @@ -1,15 +0,0 @@ -contract testIsContract{ -bool public isContrct; -constructor () public { - isContrct = address(this).isContract; -} -function testIsContractCommand(address a) public returns (bool) { -return (a.isContract); -} -function selfdestructContract(address payable a) public { - selfdestruct(a); -} -function testConstructor() public returns(bool){ - return isContrct; -} -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/TvmIsContract001.sol b/framework/src/test/resources/soliditycode_0.6.12/TvmIsContract001.sol deleted file mode 100644 index 77aae930b59..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TvmIsContract001.sol +++ /dev/null @@ -1,24 +0,0 @@ -contract testIsContract{ -bool public isContrct; -constructor () public { - isContrct = address(this).isContract; -} -function testIsContractCommand(address a) public returns (bool) { -return (a.isContract); -} - -function testIsContractView(address a) view public returns (bool) { -return (a.isContract); -} - -function selfdestructContract(address payable a) public { - selfdestruct(a); -} -function testConstructor() public returns(bool){ - return isContrct; -} - -function testConstructorView() public view returns(bool){ - return isContrct; -} -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/TvmIsContract002.sol b/framework/src/test/resources/soliditycode_0.6.12/TvmIsContract002.sol deleted file mode 100644 index 2fe474fd98c..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TvmIsContract002.sol +++ /dev/null @@ -1,5 +0,0 @@ -contract testIsContract{ -function testIsContractCommand(address a) public returns (bool) { -return (a.isContract); -} -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand043.sol b/framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand043.sol deleted file mode 100644 index 04d9f7dde28..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand043.sol +++ /dev/null @@ -1,18 +0,0 @@ -contract TestBitwiseShift { - - function shlTest(int256 num, int256 input) public returns (bytes32 out) { - assembly { - out := shl(num, input) - } - } - function shrTest(int256 num, int256 input) public returns (bytes32 out) { - assembly { - out := shr(num, input) - } - } - function sarTest(int256 num, int256 input) public returns (bytes32 out) { - assembly { - out := sar(num, input) - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand103.sol b/framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand103.sol deleted file mode 100644 index dbc7fd0f0f4..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand103.sol +++ /dev/null @@ -1,8 +0,0 @@ - - -contract testConstantContract{ -function testView() public constant returns (uint256 z) { -uint256 i=1; -return i; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand107.sol b/framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand107.sol deleted file mode 100644 index 5b51cd1842c..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand107.sol +++ /dev/null @@ -1,9 +0,0 @@ - - - contract testConstantContract{ - int256 public i; - function testPayable() public returns (int z) { - z=1+1; - return z; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand108.sol b/framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand108.sol deleted file mode 100644 index 0088054faf9..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand108.sol +++ /dev/null @@ -1,7 +0,0 @@ - - - contract testConstantContract{ - function test() pure public returns (int z) { - return 1; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand109.sol b/framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand109.sol deleted file mode 100644 index dc8dd1e8399..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TvmNewCommand109.sol +++ /dev/null @@ -1,7 +0,0 @@ - - - contract testConstantContract{ - function test() view public returns (int z) { - return 1; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/TvmOldCommand001.sol b/framework/src/test/resources/soliditycode_0.6.12/TvmOldCommand001.sol deleted file mode 100644 index 1ee046babe0..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/TvmOldCommand001.sol +++ /dev/null @@ -1,11 +0,0 @@ - - -contract binaryRightContract{ - function binaryMoveR(int i)public returns (int z) { - return z = 5 >> i; - } - function binaryLiftR(int i)public returns (int z) { - return z = 5 << i; - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/VerifyBurnProof001.sol b/framework/src/test/resources/soliditycode_0.6.12/VerifyBurnProof001.sol deleted file mode 100644 index 4173e84de23..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/VerifyBurnProof001.sol +++ /dev/null @@ -1,20 +0,0 @@ - -contract VerifyBurnProof001Test { - // verifyBurnProof(bytes32[10],bytes32[2],uint64,bytes32[2],bytes32) - // size = 512 - // - - function VerifyBurnProofSize001(bytes32[10] memory output, bytes32[2] memory spendAuthoritySignature, uint64 value, bytes32[2] memory bindingSignature,bytes32 signHash) public returns (bool){ - return verifyBurnProof(output, spendAuthoritySignature, value, bindingSignature, signHash); - } - - function VerifyBurnProofSize002(bytes memory data) public returns (bool, bytes memory){ - // bytes memory empty = ""; - return address(0x1000003).delegatecall(data); - } - - function VerifyBurnProofSize003() public returns (bool, bytes memory){ - bytes memory empty = ""; - return address(0x1000003).delegatecall(empty); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/VerifyMintProof001.sol b/framework/src/test/resources/soliditycode_0.6.12/VerifyMintProof001.sol deleted file mode 100644 index cb0812c2ef5..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/VerifyMintProof001.sol +++ /dev/null @@ -1,33 +0,0 @@ - -contract VerifyMintProof001Test { - // verifyMintProof(bytes32[9],bytes32[2],uint64,bytes32,bytes32[33],uint256) - - function VerifyMintProofSize001(bytes32[9] memory output, bytes32[2] memory bindingSignature, uint64 value, bytes32 signHash, bytes32[33] memory frontier,uint256 leafCount) public returns (bytes32[] memory){ - return verifyMintProof(output, bindingSignature, value, signHash, frontier, leafCount); - } - - function VerifyMintProofSize002(bytes memory data) public returns (bool, bytes memory){ -// address verifyMint = address (0x1000001); -// -// assembly { -// let succeeded := delegatecall(sub(gas, 5000), verifyMint, add(data, 0x20), mload(data), 0, 0) -// let size := returndatasize -// let response := mload(0x40) -// mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f)))) -// mstore(response, size) -// returndatacopy(add(response, 0x20), 0, size) -// switch iszero(succeeded) -// case 1 { -// // throw if delegatecall failed -// revert(add(response, 0x20), size) -// } -// } - - return address(0x1000001).delegatecall(data); - } - - function VerifyMintProofSize003() public returns (bool, bytes memory){ - bytes memory empty = ""; - return address(0x1000001).call(empty); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/abiencode.sol b/framework/src/test/resources/soliditycode_0.6.12/abiencode.sol deleted file mode 100644 index 38fad3454d6..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/abiencode.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma experimental ABIEncoderV2; - -// tests encoding from storage arrays - -contract AbiEncode { - int256[2][] tmp_h; - function h(int256[2][] calldata s) external returns (bytes memory) { - tmp_h = s; - return abi.encode(tmp_h); - } - int256[2][2] tmp_i; - function i(int256[2][2] calldata s) external returns (bytes memory) { - tmp_i = s; - return abi.encode(tmp_i); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/abstract001.sol b/framework/src/test/resources/soliditycode_0.6.12/abstract001.sol deleted file mode 100644 index 56bdc38eef4..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/abstract001.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma solidity ^0.6.0; - -interface X { - function setValue(uint _x) external; - function setBalance(uint _x) external; -} - -abstract contract abstract001 is X { - uint x; - function setX(uint _x) public { x = _x; } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/abstract002.sol b/framework/src/test/resources/soliditycode_0.6.12/abstract002.sol deleted file mode 100644 index 98bcf879f60..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/abstract002.sol +++ /dev/null @@ -1,13 +0,0 @@ -pragma solidity ^0.6.0; - -interface X { - function setValue(uint _x) external; - function setBalance(uint _x) external; -} - -abstract contract abstract002 is X { - uint x; - function setX(uint _x) public { x = _x; } - function setValue(uint _x) external override{ x = _x; } - function setBalance(uint _x) external override{ x = _x; } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/accountAssert.sol b/framework/src/test/resources/soliditycode_0.6.12/accountAssert.sol deleted file mode 100644 index 6d370f56080..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/accountAssert.sol +++ /dev/null @@ -1,94 +0,0 @@ -pragma solidity ^0.6.0; - -contract transferTokenTestA { - - // transfer trc10 to a new address or exist address in constructor - constructor(address payable toAddress, uint256 tokenValue, trcToken id) payable public{ - toAddress.transferToken(tokenValue, id); - require(toAddress.tokenBalance(id) > 0, "tokenBalance should not be 0"); - } - - fallback() payable external{} - - function transferTest(address payable toAddress, uint256 tokenValue) payable public { - toAddress.transfer(tokenValue); - } - - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - - // suicide to a new address - function selfdestructTest(address payable toAddress) payable public{ - selfdestruct(toAddress); - } - - // transfer to a new contract - function createContractTest(uint256 tokenValue, trcToken id) payable public returns(address){ - Simple s = new Simple(); - require(address(s).tokenBalance(id)==0, "tokenBalance should be 0"); - address(s).transferToken(tokenValue, id); - require(address(s).tokenBalance(id)==tokenValue, "tokenBalance should not be 0"); - return address(s); - } - - // revert transfer to a new contract - function revertCreateContractTest(uint256 tokenValue, trcToken id) payable public { - Simple s = new Simple(); - address(s).transferToken(tokenValue, id); - revert(); - } -} - -contract transferTokenTestB { - - constructor() payable public{ - } - - fallback() payable external{} - - function transferTest(address payable toAddress, uint256 tokenValue) payable public { - toAddress.transfer(tokenValue); - } - - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - - // suicide to a new address - function selfdestructTest(address payable toAddress) payable public{ - selfdestruct(toAddress); - } - - // transfer to a new contract - function createContractTest(uint256 tokenValue, trcToken id) payable public returns(address){ - Simple s = new Simple(); - require(address(s).tokenBalance(id)==0, "tokenBalance should be 0"); - address(s).transferToken(tokenValue, id); - require(address(s).tokenBalance(id)==tokenValue, "tokenBalance should not be 0"); - return address(s); - } - - // revert transfer to a new contract - function revertCreateContractTest(uint256 tokenValue, trcToken id) payable public { - Simple s = new Simple(); - address(s).transferToken(tokenValue, id); - revert(); - } -} - -contract transferTokenTestC { - Simple public s; - - // transfer to a new address in constructor - constructor(trcToken id) payable public{ - s = new Simple(); - require(address(s).tokenBalance(id)==0, "new contract tokenBalance should be 0"); - require(address(this).tokenBalance(id)==0, "this.tokenBalance should be 0"); - } -} - -contract Simple { - constructor() payable public{} - fallback() payable external{} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/addMsg001Nonpayable.sol b/framework/src/test/resources/soliditycode_0.6.12/addMsg001Nonpayable.sol deleted file mode 100644 index fcd40cdb521..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/addMsg001Nonpayable.sol +++ /dev/null @@ -1,20 +0,0 @@ - - -contract IllegalDecorate { - -event log(uint256); -constructor() payable public{} - -fallback() payable external{} - -function transferTokenWithOutPayable(address payable toAddress, uint256 tokenValue)public { -// function transferTokenWithValue(address toAddress, uint256 tokenValue) payable public { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); - -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/addMsg002View.sol b/framework/src/test/resources/soliditycode_0.6.12/addMsg002View.sol deleted file mode 100644 index 0c04b5c0b8a..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/addMsg002View.sol +++ /dev/null @@ -1,20 +0,0 @@ - - -contract IllegalDecorate { - -constructor() payable public{} - -fallback() payable external{} - -event log(uint256); - -function transferTokenWithView(address payable toAddress, uint256 tokenValue) public view{ -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} - diff --git a/framework/src/test/resources/soliditycode_0.6.12/addMsg003Constant.sol b/framework/src/test/resources/soliditycode_0.6.12/addMsg003Constant.sol deleted file mode 100644 index 2065802bed1..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/addMsg003Constant.sol +++ /dev/null @@ -1,19 +0,0 @@ - - -contract IllegalDecorate { - -constructor() payable public{} - -fallback() payable external{} - -event log(uint256); - -function transferTokenWithConstant(address payable toAddress, uint256 tokenValue) public constant{ -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/addMsg004Pure.sol b/framework/src/test/resources/soliditycode_0.6.12/addMsg004Pure.sol deleted file mode 100644 index 25f1a36d8b7..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/addMsg004Pure.sol +++ /dev/null @@ -1,19 +0,0 @@ - - -contract IllegalDecorate { - -constructor() payable public{} - -fallback() payable external{} - -event log(uint256); - -function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public pure{ -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/addTransferToken001Nonpayable.sol b/framework/src/test/resources/soliditycode_0.6.12/addTransferToken001Nonpayable.sol deleted file mode 100644 index 039b341b6ac..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/addTransferToken001Nonpayable.sol +++ /dev/null @@ -1,13 +0,0 @@ - - - contract IllegalDecorate { - - constructor() payable public{} - - fallback() payable external{} - - function transferTokenWithOutPayable(address payable toAddress,trcToken id, uint256 tokenValue)public { - - toAddress.transferToken(tokenValue, id); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/addTransferToken001payable.sol b/framework/src/test/resources/soliditycode_0.6.12/addTransferToken001payable.sol deleted file mode 100644 index 17078e30189..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/addTransferToken001payable.sol +++ /dev/null @@ -1,13 +0,0 @@ - - - contract IllegalDecorate { - - constructor() payable public{} - - fallback() payable external{} - - function transferTokenWithOutPayable(address payable toAddress,trcToken id, uint256 tokenValue) public payable{ - - toAddress.transferToken(tokenValue, id); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/addTransferToken002View.sol b/framework/src/test/resources/soliditycode_0.6.12/addTransferToken002View.sol deleted file mode 100644 index c50a16390f5..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/addTransferToken002View.sol +++ /dev/null @@ -1,15 +0,0 @@ - - -contract IllegalDecorate { - - constructor() payable public{} - - fallback() payable external{} - - function transferTokenWithView(address payable toAddress,trcToken id, uint256 tokenValue) public view{ - - toAddress.transferToken(tokenValue, id); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/addTransferToken003Constant.sol b/framework/src/test/resources/soliditycode_0.6.12/addTransferToken003Constant.sol deleted file mode 100644 index 18721d9b94c..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/addTransferToken003Constant.sol +++ /dev/null @@ -1,14 +0,0 @@ - -contract IllegalDecorate { - - constructor() payable public{} - - fallback() payable external{} - - function transferTokenWithConstant(address payable toAddress, uint256 tokenValue) public constant{ - - toAddress.transferToken(tokenValue, 0x6e6d62); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/addTransferToken004Pure.sol b/framework/src/test/resources/soliditycode_0.6.12/addTransferToken004Pure.sol deleted file mode 100644 index f7716ee3874..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/addTransferToken004Pure.sol +++ /dev/null @@ -1,15 +0,0 @@ - - -contract IllegalDecorate { - - constructor() payable public{} - - fallback() payable external{} - - function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public pure{ - - toAddress.transferToken(tokenValue, 0x6e6d62); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/addTrcToken001Assemble.sol b/framework/src/test/resources/soliditycode_0.6.12/addTrcToken001Assemble.sol deleted file mode 100644 index fe7a7f4cef8..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/addTrcToken001Assemble.sol +++ /dev/null @@ -1,62 +0,0 @@ - - -contract InAssemble { - -mapping(trcToken => uint256) tokenCnt; -mapping(uint256 => mapping(trcToken => trcToken)) cntTokenToken; -constructor () payable public {} -function getBalance (address addr) view public returns(uint256 r) { -assembly{ -r := balance(addr) -} -} - -function getTokenBalanceConstant (address addr, trcToken tokenId) view public returns(uint256 r) { -assembly{ -r := tokenbalance(tokenId, addr) -} -} - -function getTokenBalance (address addr, trcToken tokenId) public returns(uint256 r) { -assembly{ -r := tokenbalance(tokenId, addr) -} -} - -function transferTokenInAssembly(address addr, trcToken tokenId, uint256 tokenValue) public payable { -bytes4 sig = bytes4(keccak256("()")); // function signature - -assembly { -let x := mload(0x40) // get empty storage location -mstore(x,sig) // 4 bytes - place signature in empty storage - -let ret := calltoken(gas, addr, tokenValue, tokenId, -x, // input -0x04, // input size = 4 bytes -x, // output stored at input location, save space -0x0 // output size = 0 bytes -) - -// let ret := calltoken(gas, addr, tokenValue, -// x, // input -// 0x04, // input size = 4 bytes -// x, // output stored at input location, save space -// 0x0 // output size = 0 bytes -// ) // ERROR - - -mstore(0x40, add(x,0x20)) // update free memory pointer -} - -} - -function trcTokenInMap(trcToken tokenId, uint256 tokenValue) public returns(uint256 r) { -tokenCnt[tokenId] += tokenValue; -r = tokenCnt[tokenId]; -} - -function cntTokenTokenInMap(trcToken tokenId1, trcToken tokenId2, uint256 tokenValue) public returns(trcToken r) { -cntTokenToken[tokenValue][tokenId1] = tokenId2; -r = cntTokenToken[tokenValue][tokenId1]; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/addTrcToken002Cat.sol b/framework/src/test/resources/soliditycode_0.6.12/addTrcToken002Cat.sol deleted file mode 100644 index 0cd407079ba..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/addTrcToken002Cat.sol +++ /dev/null @@ -1,2051 +0,0 @@ - - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() public { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address payable public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address payable _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() public onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - emit Transfer(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(now), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - uint256 newKittenId = kitties.push(_kitty) - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - emit Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(address(0), _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -contract ERC721 { - // Required methods - function totalSupply() public view returns (uint256 total); - function balanceOf(address _owner) public view returns (uint256 balance); - function ownerOf(uint256 _tokenId) external view returns (address owner); - function approve(address _to, uint256 _tokenId) external; - function transfer(address _to, uint256 _tokenId) external; - function transferFrom(address _from, address _to, uint256 _tokenId) external; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) external view returns (bool); -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is ERC721, KittyBase { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public view returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - emit Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() public view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - external - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { - string memory outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { - require( address(erc721Metadata) != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2 sun; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - msg.sender.transfer(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, address(saleAuction)); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, address(siringAuction)); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10 sun; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, address(saleAuction)); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - address(uint160(address(this))) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - constructor() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(-1), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - emit ContractUpgrade(_v2Address); - } - - /// @notice No tipping! - /// @dev Reject all Ether from being sent here, unless it's from one of the - /// two auction contracts. (Hopefully, we can prevent user accidents.) - fallback() external payable { - require( - msg.sender == address(saleAuction) || - msg.sender == address(siringAuction) - ); - } - - /// @notice Returns all the relevant information about a specific kitty. - /// @param _id The ID of the kitty of interest. - function getKitty(uint256 _id) - external - view - returns ( - bool isGestating, - bool isReady, - uint256 cooldownIndex, - uint256 nextActionAt, - uint256 siringWithId, - uint256 birthTime, - uint256 matronId, - uint256 sireId, - uint256 generation, - uint256 genes - ) { - Kitty storage kit = kitties[_id]; - - // if this variable is 0 then it's not gestating - isGestating = (kit.siringWithId != 0); - isReady = (kit.cooldownEndBlock <= block.number); - cooldownIndex = uint256(kit.cooldownIndex); - nextActionAt = uint256(kit.cooldownEndBlock); - siringWithId = uint256(kit.siringWithId); - birthTime = uint256(kit.birthTime); - matronId = uint256(kit.matronId); - sireId = uint256(kit.sireId); - generation = uint256(kit.generation); - genes = kit.genes; - } - - /// @dev Override unpause so it requires all external contract addresses - /// to be set before contract can be unpaused. Also, we can't have - /// newContractAddress set either, because then the contract was upgraded. - /// @notice This is public rather than external so we can call super.unpause - /// without using an expensive CALL. - - function unpause(address payable toAddress, uint256 tokenValue, trcToken tokenId) public onlyCEO whenPaused returns (uint256 r) { - require(address(saleAuction) != address(0)); - require(address(siringAuction) != address(0)); - require(address(geneScience) != address(0)); - require(address(newContractAddress) == address(0)); - toAddress.transferToken(tokenValue, tokenId); - r = address(this).tokenBalance(tokenId); - // Actually unpause the contract. - super.unpause(); - } - - // @dev Allows the CFO to capture the balance available to the contract. - function withdrawBalance() external onlyCFO { - uint256 balance = address(this).balance; - // Subtract all the currently pregnant kittens we have, plus 1 of margin. - uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - - if (balance > subtractFees) { - cfoAddress.transfer(balance - subtractFees); - } - } -} - - - - - - - - - - - - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - - function isGeneScience() public pure returns (bool){ - return true; - } - - /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor - /// @param genes1 genes of mom - /// @param genes2 genes of sire - /// @return the genes that are supposed to be passed down the child - function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - - return (genes1+genes2+targetBlock)/2; - - -} -} - - - - - - - - - - - - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { - /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. - function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { - if (_tokenId == 1) { - buffer[0] = "Hello World! :D"; - count = 15; - } else if (_tokenId == 2) { - buffer[0] = "I would definitely choose a medi"; - buffer[1] = "um length string."; - count = 49; - } else if (_tokenId == 3) { - buffer[0] = "Lorem ipsum dolor sit amet, mi e"; - buffer[1] = "st accumsan dapibus augue lorem,"; - buffer[2] = " tristique vestibulum id, libero"; - buffer[3] = " suscipit varius sapien aliquam."; - count = 128; - } - } -} - - - - - - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - - // Represents an auction on an NFT - struct Auction { - // Current owner of NFT - address payable seller; - // Price (in wei) at beginning of auction - uint128 startingPrice; - // Price (in wei) at end of auction - uint128 endingPrice; - // Duration (in seconds) of auction - uint64 duration; - // Time when auction started - // NOTE: 0 if this auction has been concluded - uint64 startedAt; - } - - // Reference to contract tracking NFT ownership - ERC721 public nonFungibleContract; - - // Cut owner takes on each auction, measured in basis points (1/100 of a percent). - // Values 0-10,000 map to 0%-100% - uint256 public ownerCut; - - // Map from token ID to their corresponding auction. - mapping (uint256 => Auction) tokenIdToAuction; - - event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); - event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); - event AuctionCancelled(uint256 tokenId); - - /// @dev Returns true if the claimant owns the token. - /// @param _claimant - Address claiming to own the token. - /// @param _tokenId - ID of token whose ownership to verify. - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return (nonFungibleContract.ownerOf(_tokenId) == _claimant); - } - - /// @dev Escrows the NFT, assigning ownership to this contract. - /// Throws if the escrow fails. - /// @param _owner - Current owner address of token to escrow. - /// @param _tokenId - ID of token whose approval to verify. - function _escrow(address _owner, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transferFrom(_owner, address(this), _tokenId); - } - - /// @dev Transfers an NFT owned by this contract to another address. - /// Returns true if the transfer succeeds. - /// @param _receiver - Address to transfer NFT to. - /// @param _tokenId - ID of token to transfer. - function _transfer(address _receiver, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transfer(_receiver, _tokenId); - } - - /// @dev Adds an auction to the list of open auctions. Also fires the - /// AuctionCreated event. - /// @param _tokenId The ID of the token to be put on auction. - /// @param _auction Auction to add. - function _addAuction(uint256 _tokenId, Auction memory _auction) internal { - // Require that all auctions have a duration of - // at least one minute. (Keeps our math from getting hairy!) - require(_auction.duration >= 1 minutes); - - tokenIdToAuction[_tokenId] = _auction; - - emit AuctionCreated( - uint256(_tokenId), - uint256(_auction.startingPrice), - uint256(_auction.endingPrice), - uint256(_auction.duration) - ); - } - - /// @dev Cancels an auction unconditionally. - function _cancelAuction(uint256 _tokenId, address _seller) internal { - _removeAuction(_tokenId); - _transfer(_seller, _tokenId); - emit AuctionCancelled(_tokenId); - } - - /// @dev Computes the price and transfers winnings. - /// Does NOT transfer ownership of token. - function _bid(uint256 _tokenId, uint256 _bidAmount) - internal - returns (uint256) - { - // Get a reference to the auction struct - Auction storage auction = tokenIdToAuction[_tokenId]; - - // Explicitly check that this auction is currently live. - // (Because of how Ethereum mappings work, we can't just count - // on the lookup above failing. An invalid _tokenId will just - // return an auction object that is all zeros.) - require(_isOnAuction(auction)); - - // Check that the bid is greater than or equal to the current price - uint256 price = _currentPrice(auction); - require(_bidAmount >= price); - - // Grab a reference to the seller before the auction struct - // gets deleted. - address payable seller = auction.seller; - - // The bid is good! Remove the auction before sending the fees - // to the sender so we can't have a reentrancy attack. - _removeAuction(_tokenId); - - // Transfer proceeds to seller (if there are any!) - if (price > 0) { - // Calculate the auctioneer's cut. - // (NOTE: _computeCut() is guaranteed to return a - // value <= price, so this subtraction can't go negative.) - uint256 auctioneerCut = _computeCut(price); - uint256 sellerProceeds = price - auctioneerCut; - - // NOTE: Doing a transfer() in the middle of a complex - // method like this is generally discouraged because of - // reentrancy attacks and DoS attacks if the seller is - // a contract with an invalid fallback function. We explicitly - // guard against reentrancy attacks by removing the auction - // before calling transfer(), and the only thing the seller - // can DoS is the sale of their own asset! (And if it's an - // accident, they can call cancelAuction(). ) - seller.transfer(sellerProceeds); - } - - // Calculate any excess funds included with the bid. If the excess - // is anything worth worrying about, transfer it back to bidder. - // NOTE: We checked above that the bid amount is greater than or - // equal to the price so this cannot underflow. - uint256 bidExcess = _bidAmount - price; - - // Return the funds. Similar to the previous transfer, this is - // not susceptible to a re-entry attack because the auction is - // removed before any transfers occur. - msg.sender.transfer(bidExcess); - - // Tell the world! - emit AuctionSuccessful(_tokenId, price, msg.sender); - - return price; - } - - /// @dev Removes an auction from the list of open auctions. - /// @param _tokenId - ID of NFT on auction. - function _removeAuction(uint256 _tokenId) internal { - delete tokenIdToAuction[_tokenId]; - } - - /// @dev Returns true if the NFT is on auction. - /// @param _auction - Auction to check. - function _isOnAuction(Auction storage _auction) internal view returns (bool) { - return (_auction.startedAt > 0); - } - - /// @dev Returns current price of an NFT on auction. Broken into two - /// functions (this one, that computes the duration from the auction - /// structure, and the other that does the price computation) so we - /// can easily test that the price computation works correctly. - function _currentPrice(Auction storage _auction) - internal - view - returns (uint256) - { - uint256 secondsPassed = 0; - - // A bit of insurance against negative values (or wraparound). - // Probably not necessary (since Ethereum guarnatees that the - // now variable doesn't ever go backwards). - if (now > _auction.startedAt) { - secondsPassed = now - _auction.startedAt; - } - - return _computeCurrentPrice( - _auction.startingPrice, - _auction.endingPrice, - _auction.duration, - secondsPassed - ); - } - - /// @dev Computes the current price of an auction. Factored out - /// from _currentPrice so we can run extensive unit tests. - /// When testing, make this function public and turn on - /// `Current price computation` test suite. - function _computeCurrentPrice( - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - uint256 _secondsPassed - ) - internal - pure - returns (uint256) - { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our public functions carefully cap the maximum values for - // time (at 64-bits) and currency (at 128-bits). _duration is - // also known to be non-zero (see the require() statement in - // _addAuction()) - if (_secondsPassed >= _duration) { - // We've reached the end of the dynamic pricing portion - // of the auction, just return the end price. - return _endingPrice; - } else { - // Starting price can be higher than ending price (and often is!), so - // this delta can be negative. - int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - - // This multiplication can't overflow, _secondsPassed will easily fit within - // 64-bits, and totalPriceChange will easily fit within 128-bits, their product - // will always fit within 256-bits. - int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - - // currentPriceChange can be negative, but if so, will have a magnitude - // less that _startingPrice. Thus, this result will always end up positive. - int256 currentPrice = int256(_startingPrice) + currentPriceChange; - - return uint256(currentPrice); - } - } - - /// @dev Computes owner's cut of a sale. - /// @param _price - Sale price of NFT. - function _computeCut(uint256 _price) internal view returns (uint256) { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our entry functions carefully cap the maximum values for - // currency (at 128-bits), and ownerCut <= 10000 (see the require() - // statement in the ClockAuction constructor). The result of this - // function is always guaranteed to be <= _price. - return _price * ownerCut / 10000; - } - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { - event Pause(); - event Unpause(); - - bool public paused = false; - - - /** - * @dev modifier to allow actions only when the contract IS paused - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev modifier to allow actions only when the contract IS NOT paused - */ - modifier whenPaused { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyOwner whenNotPaused public returns (bool) { - paused = true; - emit Pause(); - return true; - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyOwner whenPaused public returns (bool) { - paused = false; - emit Unpause(); - return true; - } -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - - /// @dev The ERC-165 interface signature for ERC-721. - /// Ref: https://github.com/ethereum/EIPs/issues/165 - /// Ref: https://github.com/ethereum/EIPs/issues/721 - bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - - /// @dev Constructor creates a reference to the NFT ownership contract - /// and verifies the owner cut is in the valid range. - /// @param _nftAddress - address of a deployed contract implementing - /// the Nonfungible Interface. - /// @param _cut - percent cut the owner takes on each auction, must be - /// between 0-10,000. - constructor(address _nftAddress, uint256 _cut) public { - require(_cut <= 10000); - ownerCut = _cut; - - ERC721 candidateContract = ERC721(_nftAddress); - require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); - nonFungibleContract = candidateContract; - } - - /// @dev Remove all Ether from the contract, which is the owner's cuts - /// as well as any Ether sent directly to the contract address. - /// Always transfers to the NFT contract, but can be called either by - /// the owner or the NFT contract. - function withdrawBalance() external { - address payable nftAddress = address(uint160(address(nonFungibleContract))); - - require( - msg.sender == owner || - msg.sender == nftAddress - ); - // We are using this boolean method to make sure that even if one fails it will still work - bool res = nftAddress.send(address(this).balance); - } - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of time to move between starting - /// price and ending price (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - whenNotPaused - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(_owns(msg.sender, _tokenId)); - _escrow(msg.sender, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Bids on an open auction, completing the auction and transferring - /// ownership of the NFT if enough Ether is supplied. - /// @param _tokenId - ID of token to bid on. - function bid(uint256 _tokenId) - external - payable - whenNotPaused - { - // _bid will throw if the bid or funds transfer fails - _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - } - - /// @dev Cancels an auction that hasn't been won yet. - /// Returns the NFT to original owner. - /// @notice This is a state-modifying function that can - /// be called while the contract is paused. - /// @param _tokenId - ID of token on auction - function cancelAuction(uint256 _tokenId) - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - address seller = auction.seller; - require(msg.sender == seller); - _cancelAuction(_tokenId, seller); - } - - /// @dev Cancels an auction when the contract is paused. - /// Only the owner may do this, and NFTs are returned to - /// the seller. This should only be used in emergencies. - /// @param _tokenId - ID of the NFT on auction to cancel. - function cancelAuctionWhenPaused(uint256 _tokenId) - whenPaused - onlyOwner - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - _cancelAuction(_tokenId, auction.seller); - } - - /// @dev Returns auction info for an NFT on auction. - /// @param _tokenId - ID of NFT on auction. - function getAuction(uint256 _tokenId) - external - view - returns - ( - address seller, - uint256 startingPrice, - uint256 endingPrice, - uint256 duration, - uint256 startedAt - ) { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return ( - auction.seller, - auction.startingPrice, - auction.endingPrice, - auction.duration, - auction.startedAt - ); - } - - /// @dev Returns the current price of an auction. - /// @param _tokenId - ID of the token price we are checking. - function getCurrentPrice(uint256 _tokenId) - external - view - returns (uint256) - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return _currentPrice(auction); - } - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSiringAuctionAddress() call. - bool public isSiringClockAuction = true; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. Since this function is wrapped, - /// require sender to be KittyCore contract. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Places a bid for siring. Requires the sender - /// is the KittyCore contract because all bid methods - /// should be wrapped. Also returns the kitty to the - /// seller rather than the winner. - function bid(uint256 _tokenId) - external - payable - { - require(msg.sender == address(nonFungibleContract)); - address seller = tokenIdToAuction[_tokenId].seller; - // _bid checks that token ID is valid and will throw if bid fails - _bid(_tokenId, msg.value); - // We transfer the kitty back to the seller, the winner will get - // the offspring - _transfer(seller, _tokenId); - } - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSaleAuctionAddress() call. - bool public isSaleClockAuction = true; - - // Tracks last 5 sale price of gen0 kitty sales - uint256 public gen0SaleCount; - uint256[5] public lastGen0SalePrices; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Updates lastSalePrice if seller is the nft contract - /// Otherwise, works the same as default bid method. - function bid(uint256 _tokenId) - external - payable - { - // _bid verifies token ID size - address seller = tokenIdToAuction[_tokenId].seller; - uint256 price = _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - - // If not a gen0 auction, exit - if (seller == address(nonFungibleContract)) { - // Track gen0 sale prices - lastGen0SalePrices[gen0SaleCount % 5] = price; - gen0SaleCount++; - } - } - - function averageGen0SalePrice() external view returns (uint256) { - uint256 sum = 0; - for (uint256 i = 0; i < 5; i++) { - sum += lastGen0SalePrices[i]; - } - return sum / 5; - } - -} - - - - - - - diff --git a/framework/src/test/resources/soliditycode_0.6.12/addTrcToken002Cat_withFinny.sol b/framework/src/test/resources/soliditycode_0.6.12/addTrcToken002Cat_withFinny.sol deleted file mode 100644 index 24117bc5e6b..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/addTrcToken002Cat_withFinny.sol +++ /dev/null @@ -1,2051 +0,0 @@ - - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() public { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address payable public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address payable _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() public onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - emit Transfer(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(now), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - uint256 newKittenId = kitties.push(_kitty) - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - emit Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(address(0), _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -contract ERC721 { - // Required methods - function totalSupply() public view returns (uint256 total); - function balanceOf(address _owner) public view returns (uint256 balance); - function ownerOf(uint256 _tokenId) external view returns (address owner); - function approve(address _to, uint256 _tokenId) external; - function transfer(address _to, uint256 _tokenId) external; - function transferFrom(address _from, address _to, uint256 _tokenId) external; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) external view returns (bool); -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is ERC721, KittyBase { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public view returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - emit Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() public view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - external - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { - string memory outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { - require( address(erc721Metadata) != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2 finney; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - msg.sender.transfer(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, address(saleAuction)); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, address(siringAuction)); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10 finney; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, address(saleAuction)); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - address(uint160(address(this))) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - constructor() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(-1), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - emit ContractUpgrade(_v2Address); - } - - /// @notice No tipping! - /// @dev Reject all Ether from being sent here, unless it's from one of the - /// two auction contracts. (Hopefully, we can prevent user accidents.) - fallback() external payable { - require( - msg.sender == address(saleAuction) || - msg.sender == address(siringAuction) - ); - } - - /// @notice Returns all the relevant information about a specific kitty. - /// @param _id The ID of the kitty of interest. - function getKitty(uint256 _id) - external - view - returns ( - bool isGestating, - bool isReady, - uint256 cooldownIndex, - uint256 nextActionAt, - uint256 siringWithId, - uint256 birthTime, - uint256 matronId, - uint256 sireId, - uint256 generation, - uint256 genes - ) { - Kitty storage kit = kitties[_id]; - - // if this variable is 0 then it's not gestating - isGestating = (kit.siringWithId != 0); - isReady = (kit.cooldownEndBlock <= block.number); - cooldownIndex = uint256(kit.cooldownIndex); - nextActionAt = uint256(kit.cooldownEndBlock); - siringWithId = uint256(kit.siringWithId); - birthTime = uint256(kit.birthTime); - matronId = uint256(kit.matronId); - sireId = uint256(kit.sireId); - generation = uint256(kit.generation); - genes = kit.genes; - } - - /// @dev Override unpause so it requires all external contract addresses - /// to be set before contract can be unpaused. Also, we can't have - /// newContractAddress set either, because then the contract was upgraded. - /// @notice This is public rather than external so we can call super.unpause - /// without using an expensive CALL. - - function unpause(address payable toAddress, uint256 tokenValue, trcToken tokenId) public onlyCEO whenPaused returns (uint256 r) { - require(address(saleAuction) != address(0)); - require(address(siringAuction) != address(0)); - require(address(geneScience) != address(0)); - require(address(newContractAddress) == address(0)); - toAddress.transferToken(tokenValue, tokenId); - r = address(this).tokenBalance(tokenId); - // Actually unpause the contract. - super.unpause(); - } - - // @dev Allows the CFO to capture the balance available to the contract. - function withdrawBalance() external onlyCFO { - uint256 balance = address(this).balance; - // Subtract all the currently pregnant kittens we have, plus 1 of margin. - uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - - if (balance > subtractFees) { - cfoAddress.transfer(balance - subtractFees); - } - } -} - - - - - - - - - - - - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - - function isGeneScience() public pure returns (bool){ - return true; - } - - /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor - /// @param genes1 genes of mom - /// @param genes2 genes of sire - /// @return the genes that are supposed to be passed down the child - function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - - return (genes1+genes2+targetBlock)/2; - - -} -} - - - - - - - - - - - - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { - /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. - function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { - if (_tokenId == 1) { - buffer[0] = "Hello World! :D"; - count = 15; - } else if (_tokenId == 2) { - buffer[0] = "I would definitely choose a medi"; - buffer[1] = "um length string."; - count = 49; - } else if (_tokenId == 3) { - buffer[0] = "Lorem ipsum dolor sit amet, mi e"; - buffer[1] = "st accumsan dapibus augue lorem,"; - buffer[2] = " tristique vestibulum id, libero"; - buffer[3] = " suscipit varius sapien aliquam."; - count = 128; - } - } -} - - - - - - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - - // Represents an auction on an NFT - struct Auction { - // Current owner of NFT - address payable seller; - // Price (in wei) at beginning of auction - uint128 startingPrice; - // Price (in wei) at end of auction - uint128 endingPrice; - // Duration (in seconds) of auction - uint64 duration; - // Time when auction started - // NOTE: 0 if this auction has been concluded - uint64 startedAt; - } - - // Reference to contract tracking NFT ownership - ERC721 public nonFungibleContract; - - // Cut owner takes on each auction, measured in basis points (1/100 of a percent). - // Values 0-10,000 map to 0%-100% - uint256 public ownerCut; - - // Map from token ID to their corresponding auction. - mapping (uint256 => Auction) tokenIdToAuction; - - event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); - event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); - event AuctionCancelled(uint256 tokenId); - - /// @dev Returns true if the claimant owns the token. - /// @param _claimant - Address claiming to own the token. - /// @param _tokenId - ID of token whose ownership to verify. - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return (nonFungibleContract.ownerOf(_tokenId) == _claimant); - } - - /// @dev Escrows the NFT, assigning ownership to this contract. - /// Throws if the escrow fails. - /// @param _owner - Current owner address of token to escrow. - /// @param _tokenId - ID of token whose approval to verify. - function _escrow(address _owner, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transferFrom(_owner, address(this), _tokenId); - } - - /// @dev Transfers an NFT owned by this contract to another address. - /// Returns true if the transfer succeeds. - /// @param _receiver - Address to transfer NFT to. - /// @param _tokenId - ID of token to transfer. - function _transfer(address _receiver, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transfer(_receiver, _tokenId); - } - - /// @dev Adds an auction to the list of open auctions. Also fires the - /// AuctionCreated event. - /// @param _tokenId The ID of the token to be put on auction. - /// @param _auction Auction to add. - function _addAuction(uint256 _tokenId, Auction memory _auction) internal { - // Require that all auctions have a duration of - // at least one minute. (Keeps our math from getting hairy!) - require(_auction.duration >= 1 minutes); - - tokenIdToAuction[_tokenId] = _auction; - - emit AuctionCreated( - uint256(_tokenId), - uint256(_auction.startingPrice), - uint256(_auction.endingPrice), - uint256(_auction.duration) - ); - } - - /// @dev Cancels an auction unconditionally. - function _cancelAuction(uint256 _tokenId, address _seller) internal { - _removeAuction(_tokenId); - _transfer(_seller, _tokenId); - emit AuctionCancelled(_tokenId); - } - - /// @dev Computes the price and transfers winnings. - /// Does NOT transfer ownership of token. - function _bid(uint256 _tokenId, uint256 _bidAmount) - internal - returns (uint256) - { - // Get a reference to the auction struct - Auction storage auction = tokenIdToAuction[_tokenId]; - - // Explicitly check that this auction is currently live. - // (Because of how Ethereum mappings work, we can't just count - // on the lookup above failing. An invalid _tokenId will just - // return an auction object that is all zeros.) - require(_isOnAuction(auction)); - - // Check that the bid is greater than or equal to the current price - uint256 price = _currentPrice(auction); - require(_bidAmount >= price); - - // Grab a reference to the seller before the auction struct - // gets deleted. - address payable seller = auction.seller; - - // The bid is good! Remove the auction before sending the fees - // to the sender so we can't have a reentrancy attack. - _removeAuction(_tokenId); - - // Transfer proceeds to seller (if there are any!) - if (price > 0) { - // Calculate the auctioneer's cut. - // (NOTE: _computeCut() is guaranteed to return a - // value <= price, so this subtraction can't go negative.) - uint256 auctioneerCut = _computeCut(price); - uint256 sellerProceeds = price - auctioneerCut; - - // NOTE: Doing a transfer() in the middle of a complex - // method like this is generally discouraged because of - // reentrancy attacks and DoS attacks if the seller is - // a contract with an invalid fallback function. We explicitly - // guard against reentrancy attacks by removing the auction - // before calling transfer(), and the only thing the seller - // can DoS is the sale of their own asset! (And if it's an - // accident, they can call cancelAuction(). ) - seller.transfer(sellerProceeds); - } - - // Calculate any excess funds included with the bid. If the excess - // is anything worth worrying about, transfer it back to bidder. - // NOTE: We checked above that the bid amount is greater than or - // equal to the price so this cannot underflow. - uint256 bidExcess = _bidAmount - price; - - // Return the funds. Similar to the previous transfer, this is - // not susceptible to a re-entry attack because the auction is - // removed before any transfers occur. - msg.sender.transfer(bidExcess); - - // Tell the world! - emit AuctionSuccessful(_tokenId, price, msg.sender); - - return price; - } - - /// @dev Removes an auction from the list of open auctions. - /// @param _tokenId - ID of NFT on auction. - function _removeAuction(uint256 _tokenId) internal { - delete tokenIdToAuction[_tokenId]; - } - - /// @dev Returns true if the NFT is on auction. - /// @param _auction - Auction to check. - function _isOnAuction(Auction storage _auction) internal view returns (bool) { - return (_auction.startedAt > 0); - } - - /// @dev Returns current price of an NFT on auction. Broken into two - /// functions (this one, that computes the duration from the auction - /// structure, and the other that does the price computation) so we - /// can easily test that the price computation works correctly. - function _currentPrice(Auction storage _auction) - internal - view - returns (uint256) - { - uint256 secondsPassed = 0; - - // A bit of insurance against negative values (or wraparound). - // Probably not necessary (since Ethereum guarnatees that the - // now variable doesn't ever go backwards). - if (now > _auction.startedAt) { - secondsPassed = now - _auction.startedAt; - } - - return _computeCurrentPrice( - _auction.startingPrice, - _auction.endingPrice, - _auction.duration, - secondsPassed - ); - } - - /// @dev Computes the current price of an auction. Factored out - /// from _currentPrice so we can run extensive unit tests. - /// When testing, make this function public and turn on - /// `Current price computation` test suite. - function _computeCurrentPrice( - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - uint256 _secondsPassed - ) - internal - pure - returns (uint256) - { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our public functions carefully cap the maximum values for - // time (at 64-bits) and currency (at 128-bits). _duration is - // also known to be non-zero (see the require() statement in - // _addAuction()) - if (_secondsPassed >= _duration) { - // We've reached the end of the dynamic pricing portion - // of the auction, just return the end price. - return _endingPrice; - } else { - // Starting price can be higher than ending price (and often is!), so - // this delta can be negative. - int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - - // This multiplication can't overflow, _secondsPassed will easily fit within - // 64-bits, and totalPriceChange will easily fit within 128-bits, their product - // will always fit within 256-bits. - int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - - // currentPriceChange can be negative, but if so, will have a magnitude - // less that _startingPrice. Thus, this result will always end up positive. - int256 currentPrice = int256(_startingPrice) + currentPriceChange; - - return uint256(currentPrice); - } - } - - /// @dev Computes owner's cut of a sale. - /// @param _price - Sale price of NFT. - function _computeCut(uint256 _price) internal view returns (uint256) { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our entry functions carefully cap the maximum values for - // currency (at 128-bits), and ownerCut <= 10000 (see the require() - // statement in the ClockAuction constructor). The result of this - // function is always guaranteed to be <= _price. - return _price * ownerCut / 10000; - } - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { - event Pause(); - event Unpause(); - - bool public paused = false; - - - /** - * @dev modifier to allow actions only when the contract IS paused - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev modifier to allow actions only when the contract IS NOT paused - */ - modifier whenPaused { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyOwner whenNotPaused public returns (bool) { - paused = true; - emit Pause(); - return true; - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyOwner whenPaused public returns (bool) { - paused = false; - emit Unpause(); - return true; - } -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - - /// @dev The ERC-165 interface signature for ERC-721. - /// Ref: https://github.com/ethereum/EIPs/issues/165 - /// Ref: https://github.com/ethereum/EIPs/issues/721 - bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - - /// @dev Constructor creates a reference to the NFT ownership contract - /// and verifies the owner cut is in the valid range. - /// @param _nftAddress - address of a deployed contract implementing - /// the Nonfungible Interface. - /// @param _cut - percent cut the owner takes on each auction, must be - /// between 0-10,000. - constructor(address _nftAddress, uint256 _cut) public { - require(_cut <= 10000); - ownerCut = _cut; - - ERC721 candidateContract = ERC721(_nftAddress); - require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); - nonFungibleContract = candidateContract; - } - - /// @dev Remove all Ether from the contract, which is the owner's cuts - /// as well as any Ether sent directly to the contract address. - /// Always transfers to the NFT contract, but can be called either by - /// the owner or the NFT contract. - function withdrawBalance() external { - address payable nftAddress = address(uint160(address(nonFungibleContract))); - - require( - msg.sender == owner || - msg.sender == nftAddress - ); - // We are using this boolean method to make sure that even if one fails it will still work - bool res = nftAddress.send(address(this).balance); - } - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of time to move between starting - /// price and ending price (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - whenNotPaused - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(_owns(msg.sender, _tokenId)); - _escrow(msg.sender, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Bids on an open auction, completing the auction and transferring - /// ownership of the NFT if enough Ether is supplied. - /// @param _tokenId - ID of token to bid on. - function bid(uint256 _tokenId) - external - payable - whenNotPaused - { - // _bid will throw if the bid or funds transfer fails - _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - } - - /// @dev Cancels an auction that hasn't been won yet. - /// Returns the NFT to original owner. - /// @notice This is a state-modifying function that can - /// be called while the contract is paused. - /// @param _tokenId - ID of token on auction - function cancelAuction(uint256 _tokenId) - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - address seller = auction.seller; - require(msg.sender == seller); - _cancelAuction(_tokenId, seller); - } - - /// @dev Cancels an auction when the contract is paused. - /// Only the owner may do this, and NFTs are returned to - /// the seller. This should only be used in emergencies. - /// @param _tokenId - ID of the NFT on auction to cancel. - function cancelAuctionWhenPaused(uint256 _tokenId) - whenPaused - onlyOwner - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - _cancelAuction(_tokenId, auction.seller); - } - - /// @dev Returns auction info for an NFT on auction. - /// @param _tokenId - ID of NFT on auction. - function getAuction(uint256 _tokenId) - external - view - returns - ( - address seller, - uint256 startingPrice, - uint256 endingPrice, - uint256 duration, - uint256 startedAt - ) { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return ( - auction.seller, - auction.startingPrice, - auction.endingPrice, - auction.duration, - auction.startedAt - ); - } - - /// @dev Returns the current price of an auction. - /// @param _tokenId - ID of the token price we are checking. - function getCurrentPrice(uint256 _tokenId) - external - view - returns (uint256) - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return _currentPrice(auction); - } - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSiringAuctionAddress() call. - bool public isSiringClockAuction = true; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. Since this function is wrapped, - /// require sender to be KittyCore contract. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Places a bid for siring. Requires the sender - /// is the KittyCore contract because all bid methods - /// should be wrapped. Also returns the kitty to the - /// seller rather than the winner. - function bid(uint256 _tokenId) - external - payable - { - require(msg.sender == address(nonFungibleContract)); - address seller = tokenIdToAuction[_tokenId].seller; - // _bid checks that token ID is valid and will throw if bid fails - _bid(_tokenId, msg.value); - // We transfer the kitty back to the seller, the winner will get - // the offspring - _transfer(seller, _tokenId); - } - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSaleAuctionAddress() call. - bool public isSaleClockAuction = true; - - // Tracks last 5 sale price of gen0 kitty sales - uint256 public gen0SaleCount; - uint256[5] public lastGen0SalePrices; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Updates lastSalePrice if seller is the nft contract - /// Otherwise, works the same as default bid method. - function bid(uint256 _tokenId) - external - payable - { - // _bid verifies token ID size - address seller = tokenIdToAuction[_tokenId].seller; - uint256 price = _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - - // If not a gen0 auction, exit - if (seller == address(nonFungibleContract)) { - // Track gen0 sale prices - lastGen0SalePrices[gen0SaleCount % 5] = price; - gen0SaleCount++; - } - } - - function averageGen0SalePrice() external view returns (uint256) { - uint256 sum = 0; - for (uint256 i = 0; i < 5; i++) { - sum += lastGen0SalePrices[i]; - } - return sum / 5; - } - -} - - - - - - - diff --git a/framework/src/test/resources/soliditycode_0.6.12/addressCheckNew.sol b/framework/src/test/resources/soliditycode_0.6.12/addressCheckNew.sol deleted file mode 100644 index 3c10b8c680d..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/addressCheckNew.sol +++ /dev/null @@ -1,9 +0,0 @@ -pragma experimental ABIEncoderV2; -contract testIsContract{ - function checkAddress(address addr) public returns (address){ - return addr; - } - function checkAddress2(address addr) pure public returns(address){ - return addr; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/addressCheckOld.sol b/framework/src/test/resources/soliditycode_0.6.12/addressCheckOld.sol deleted file mode 100644 index 6c6b15d1736..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/addressCheckOld.sol +++ /dev/null @@ -1,8 +0,0 @@ -contract testIsContract{ - function checkAddress(address addr) public returns (address){ - return addr; - } - function checkAddress2(address addr) pure public returns (address){ - return addr; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/altbn.sol b/framework/src/test/resources/soliditycode_0.6.12/altbn.sol deleted file mode 100644 index c3cfcdbe2b9..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/altbn.sol +++ /dev/null @@ -1,61 +0,0 @@ -contract AltBn128 { - constructor() public payable {} - function callBn256Add(bytes32 ax, bytes32 ay, bytes32 bx, bytes32 by) public returns (bytes32[2] memory result) { - bytes32[4] memory input; - input[0] = ax; - input[1] = ay; - input[2] = bx; - input[3] = by; - assembly { - let success := call(gas(), 0x06, 0, input, 0x80, result, 0x40) - } - - } - - function callBn256AddNoValue(bytes32 ax, bytes32 ay, bytes32 bx, bytes32 by) public returns - (bytes32[2] memory result) { - bytes32[4] memory input; - input[0] = ax; - input[1] = ay; - input[2] = bx; - input[3] = by; - assembly { - let success := call(gas(), 0xac, 0, input, 0x80, result, 0x40) - } - } - - function callBn256ScalarMul(bytes32 x, bytes32 y, bytes32 scalar) public returns (bytes32[2] memory result) { - bytes32[3] memory input; - input[0] = x; - input[1] = y; - input[2] = scalar; - assembly { - let success := call(gas(), 0x07, 0, input, 0x60, result, 0x40) - switch success - case 0 { - revert(0,0) - } - } - } - - function callBn256Pairing(bytes memory input) public returns (bytes32 result) { - // input is a serialized bytes stream of (a1, b1, a2, b2, ..., ak, bk) from (G_1 x G_2)^k - uint256 len = input.length; - require(len % 192 == 0); - assembly { - let memPtr := mload(0x40) - let success := call(gas(), 0x08, 0, add(input, 0x20), len, memPtr, 0x20) - switch success - case 0 { - revert(0,0) - } default { - result := mload(memPtr) - } - } - } - - function convert(uint256 num) public view returns(bytes32) { - return bytes32(num); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/arrayLength001.sol b/framework/src/test/resources/soliditycode_0.6.12/arrayLength001.sol deleted file mode 100644 index 46b2405a97e..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/arrayLength001.sol +++ /dev/null @@ -1,64 +0,0 @@ - - -contract arrayLength { - byte[] a; - uint256[] IntergerArray; - bytes bs; - - // arrary length - function arrayPushValue() public returns (byte[] memory){ - a = new byte[](1); - a.push(0x01); - return a; - } - - function arrayPush() public returns(byte[] memory){ - a = new byte[](1); - a.push(); - return a; - } - - function arrayPop() public returns(byte[] memory){ - a = new byte[](1); - a.pop(); - return a; - } - - // arrary push/pop return Value - function arrayPushValueReturn() public { - a = new byte[](1); - return a.push(0x01); - } - - function arrayPushReturn() public returns (bytes1){ - a = new byte[](1); - return a.push(); - } - - function arrayPopReturn() public{ - a = new byte[](1); - return a.pop(); - } - - function uint256ArrayPushValue() public returns (byte[] memory){ - IntergerArray = [1,2,3]; - IntergerArray.push(); - return a; - } - - - // bytes - function bytesPushValue() public { - - return bs.push(0x01); - } - - function bytesPush() public returns (bytes1){ - return bs.push(); - } - - function bytesPop() public { - return bs.pop(); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/assemblyTest.sol b/framework/src/test/resources/soliditycode_0.6.12/assemblyTest.sol deleted file mode 100644 index 519a5a85fa3..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/assemblyTest.sol +++ /dev/null @@ -1,61 +0,0 @@ - -contract assemblyTest { - - uint constant x = 1; - uint constant y = x; - function getZuint() public view returns (uint) { - uint z = y + 1; - assembly { - z := y - } - return z; - } - - function getZuint2() public returns (uint) { - uint z = y + 1; - assembly { - z := y - } - return z; - } - - bool constant bool1 = true; - bool constant bool2 = bool1; - function getZbool() public view returns (bool) { - bool z; - assembly { - z := bool2 - } - return z; - } - - function getZbool2() public returns (bool) { - bool z; - assembly { - z := bool2 - } - return z; - } - - -// string constant string1 = "abc"; -// string constant string2 = string1; -// function getZstring() public view returns (string memory) { -// string memory z; -// assembly { -// z := string2 -// } -// return z; -// } - - -// address origin1 = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; -// address origin2 = origin1; -// function getZaddress() public view returns (address) { -// address z; -// assembly { -// z := origin2 -// } -// return z; -// } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest1DivideInt.sol b/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest1DivideInt.sol deleted file mode 100644 index 92778e42bc9..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest1DivideInt.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest2FindArgsContractMinTest.sol b/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest2FindArgsContractMinTest.sol deleted file mode 100644 index 75436287805..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest2FindArgsContractMinTest.sol +++ /dev/null @@ -1,10 +0,0 @@ - -contract findArgsIContract{ -function findArgsByIndex1(uint i) public returns (uint z) { -uint[] memory a = new uint[](3); -a[0]=1; -a[1]=2; -a[2]=3; -return a[i]; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest3ByteMinContract.sol b/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest3ByteMinContract.sol deleted file mode 100644 index c8a2e5e363b..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest3ByteMinContract.sol +++ /dev/null @@ -1,11 +0,0 @@ - -contract byteContract{ -bytes b; -function testBytesGet(uint i) public returns (bytes1){ -b = new bytes(3); -b[0]=0x0b; -b[1]=0x0c; -b[2]=0x0d; -return b[i]; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest4Enum.sol b/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest4Enum.sol deleted file mode 100644 index 6bd2ade2eea..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest4Enum.sol +++ /dev/null @@ -1,13 +0,0 @@ - - -contract enumContract { - enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } - ActionChoices _choice; - function setGoStraight(ActionChoices choice) public { - _choice = choice; - } - - function getChoice() public returns (ActionChoices) { - return _choice; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest5MoveRight.sol b/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest5MoveRight.sol deleted file mode 100644 index b83168d5ddc..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest5MoveRight.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract binaryRightContract{ - function binaryMoveR(int i)public returns (int z) { - return z = 5 >> i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest6UninitializedContract.sol b/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest6UninitializedContract.sol deleted file mode 100644 index c82e0f5806c..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest6UninitializedContract.sol +++ /dev/null @@ -1,27 +0,0 @@ - -contract uni { -function b(int x, int y) internal returns (int) -{ - return x * y; -} - -function test1() external returns (int) -{ - // Variable containing a function pointer - function (int, int) internal returns (int) funcPtr; - - funcPtr = b; - - // This call to funcPtr will succeed - return funcPtr(4, 5); -} - -function test2() external returns (int) -{ - // Variable containing a function pointer - function (int, int) internal returns (int) funcPtr; - - // This call will fail because funcPtr is still a zero-initialized function pointer - return funcPtr(4, 5); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest7TestAssertContract.sol b/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest7TestAssertContract.sol deleted file mode 100644 index 05b592e0682..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/assertExceptiontest7TestAssertContract.sol +++ /dev/null @@ -1,14 +0,0 @@ -contract TestThrowsContract{ - function testAssert() public{ - assert(1==2); - } - function testRequire() public{ - require(2==1); - } - function testRevert() public{ - revert(); - } - function testThrow() public{ - revert(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign.sol b/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign.sol deleted file mode 100644 index 9e1c1b289b5..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - - function testArray2(bytes memory data) public returns(bool, bytes memory){ - return address(0x9).delegatecall(data); - } - - function testArray4(bytes memory data) public { - //address(0x1).delegatecall(data); - } - //function testArray3(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public { - //address(0x9).delegatecall(hash,signatures,addresses); - //} -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign001.sol b/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign001.sol deleted file mode 100644 index 57e051ce415..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign001.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - function testPure(bytes32 hash, bytes[] memory signatures, address[] memory addresses) pure public returns(bytes32){ - return batchvalidatesign(hash, signatures, addresses); - } - - function testArray(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public returns(bytes32){ - return batchvalidatesign(hash, signatures, addresses); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign002.sol b/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign002.sol deleted file mode 100644 index 375cec3a2a2..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign002.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - function testArray(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public returns(bytes32){ - - return batchvalidatesign(hash, signatures, addresses); - - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign003.sol b/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign003.sol deleted file mode 100644 index c43536af499..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign003.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract Demo { -bytes32 public result; -constructor (bytes32 hash, bytes[] memory signatures, address[] memory addresses) public { - result = batchvalidatesign(hash, signatures, addresses); -} -function testConstructor() public returns(bytes32){ - return result; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign005.sol b/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign005.sol deleted file mode 100644 index 3a6ca362973..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign005.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - - function testArray2(bytes memory data) public returns(bool, bytes memory){ - return address(0x9).delegatecall(data); - } - - function testArray4(bytes memory data) public { - //address(0x1).delegatecall(data); - } - function testArray3(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public { - //address(0x9).delegatecall(hash,signatures,addresses); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign007.sol b/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign007.sol deleted file mode 100644 index 974ffb34efe..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign007.sol +++ /dev/null @@ -1,17 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract Demo { - bytes32 public result; - - constructor (bytes32 hash, bytes[] memory signatures, address[] memory addresses) public { - result = batchvalidatesign(hash, signatures, addresses); - } - - function testConstructor() public returns(bytes32){ - return result; - } - - function testConstructorPure() public view returns(bytes32){ - return result; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign02.sol b/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign02.sol deleted file mode 100644 index 375cec3a2a2..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/batchvalidatesign02.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - function testArray(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public returns(bytes32){ - - return batchvalidatesign(hash, signatures, addresses); - - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/callValueGasPure.sol b/framework/src/test/resources/soliditycode_0.6.12/callValueGasPure.sol deleted file mode 100644 index ed4877e1ce4..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/callValueGasPure.sol +++ /dev/null @@ -1,8 +0,0 @@ - -contract C { -function check(address a) external pure returns (bool success) { - a.call.value(42).gas(42); - a.call.gas(42); - //a.call.value(1).gas(42)("fwefewf"); -} -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/calldata.sol b/framework/src/test/resources/soliditycode_0.6.12/calldata.sol deleted file mode 100644 index 6e877ac1b2f..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/calldata.sol +++ /dev/null @@ -1,33 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract C { - struct S { uint256 a; } - - function f(S calldata s) external returns (bytes memory) { - return abi.encode(s); - } - - function g(S calldata s) external returns (bytes memory) { - return this.f(s); - } - - function m(uint256[] calldata) external pure returns (bytes memory) { - return msg.data; - } - function h(uint8[] calldata s) external pure returns (bytes memory) { - return abi.encode(s); - } - function i(uint8[][2] calldata s, uint256 which) external view returns (bytes memory) { - return this.h(s[which]); - } - function j(bytes calldata s) external pure returns (bytes memory) { - return abi.encode(s); - } - function k(bytes[2] calldata s, uint256 which) external view returns (bytes memory) { - return this.j(s[which]); - } - function l(function() external returns (uint)[] calldata s) external returns (uint, uint, uint) { - assert(s.length == 3); - return (s[0](), s[1](), s[2]()); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/callvalue.sol b/framework/src/test/resources/soliditycode_0.6.12/callvalue.sol deleted file mode 100644 index f01dcf2b52f..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/callvalue.sol +++ /dev/null @@ -1,9 +0,0 @@ -contract Callvalue { -function check() public payable returns(uint) { - uint256 wad; - assembly { - wad := callvalue() - } - return wad; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/chainid001.sol b/framework/src/test/resources/soliditycode_0.6.12/chainid001.sol deleted file mode 100644 index 9cf24077dfb..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/chainid001.sol +++ /dev/null @@ -1,19 +0,0 @@ - -contract IstanbulTest { - constructor() public payable {} - function getId() public view returns(uint256){ - uint256 id; - assembly { - id := chainid() - } - return id; - } - - function getBalance(address src) public view returns(uint256){ - return address(src).balance; - } - - function getBalance() public view returns(uint256){ - return address(this).balance; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/codeSaftySupport.sol b/framework/src/test/resources/soliditycode_0.6.12/codeSaftySupport.sol deleted file mode 100644 index 1cee8e4646c..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/codeSaftySupport.sol +++ /dev/null @@ -1,19 +0,0 @@ - - -contract IllegalDecorate { - -constructor() payable public{} - -fallback() payable external{} - -event log(uint256); - -function transferToken(address payable toAddress, uint256 tokenValue) public payable { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/codeSaftyUnsupport.sol b/framework/src/test/resources/soliditycode_0.6.12/codeSaftyUnsupport.sol deleted file mode 100644 index d448f49d706..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/codeSaftyUnsupport.sol +++ /dev/null @@ -1,56 +0,0 @@ - - -contract SubC { - -event log(string); - -fallback() payable external{} - -function receiveToken() payable public{} - -function getBalance() view public returns (uint256 r) { -r = address(this).balance; -} -} - -contract UseDot { -constructor() payable public{} -fallback() payable external{} -mapping(address => mapping(trcToken => uint256)) sender_tokens; - -function trigger1(address payable addr, trcToken tokenInputId) payable public { - //address(SubC(addr)).call.value(1000).tokenId(tokenInputId)(abi.encodeWithSignature("receiveToken()")); // ERROR -} - -function trigger2(address payable addr) payable public { -// addr.transferToken.value(10)(10, 0x6e6d62); // ERROR -} - -function trigger3(address payable addr) payable public { - // address(SubC(addr)).receiveToken.tokenvalue(10)(); // ERROR -} - -function trigger4(address payable addr) payable public { - //SubC(addr).receiveToken.tokenId(0x6e6d62)(); // ERROR -} - -function trigger5(address payable addr) payable public { - SubC(addr).receiveToken.value(10)(); -} - -function trigger6(address payable addr, trcToken tokenId) payable public { -address(SubC(addr)).call.value(1000)(abi.encodeWithSignature("transferToken(uint256, trcToken)", 10, tokenId)); -} - -function trigger7(address addr) payable public { - //sender_tokens[msg.sender][msg.tokenid] += msg.tokenvalue; // compile success, no necessary to trigger -} - -function trigger8(address addr) public payable returns(bytes memory r){ -// r = msg.data; // compile success, no necessary to trigger -} - -function getBalance() public returns (uint256 r){ -r = address(this).balance; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/constantCallStorage001.sol b/framework/src/test/resources/soliditycode_0.6.12/constantCallStorage001.sol deleted file mode 100644 index 1f584923a55..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/constantCallStorage001.sol +++ /dev/null @@ -1,159 +0,0 @@ -contract NotView { - uint256 public num = 123; - function setnum() public returns(uint256){ - num = num + 15; - return num; - } -} -contract NotViewInterface{ - function setnum() public returns(uint256); -} -contract UseNotView { - function setnumuseproxy(address contractAddress) public returns(uint256){ - NotViewInterface inter = NotViewInterface(contractAddress); - return inter.setnum(); - } -} -contract viewCall { - bool stopped = false; - int i = 32482989; - int i2 = -32482989; - uint ui = 23487823; - address origin = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; - bytes32 b32 = bytes32(uint256(0xdCad3a6d3569DF655070DEd0)); - bytes bs = new bytes(3); - string s = "123qwe"; - enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } - ActionChoices choice = ActionChoices.GoRight; - int64[] b = [-1, 2, -3]; - int32[2][] tmp_h = [[1,2],[3,4],[5,6]]; - int256[2][2] tmp_i = [[11,22],[33,44]]; - mapping (address => uint256) public mapa; - constructor() payable public{ - mapa[address(0x00)] = 34; - } - event log(int); - event log(uint); - event log(bool); - event log(address); - event log(bytes32); - event log(bytes); - event log(string); - event log(ActionChoices); - event log(int64[]); - event log(int32[2][]); - event log(int256[2][2]); - function changeBool(bool param) public returns (bool){ - stopped = param; - emit log(stopped); - return stopped; - } - function getBool() public returns (bool){ - emit log(stopped); - return stopped; - } - function changeInt(int param) public returns (int){ - i = param; - emit log(i); - return i; - } - function getInt() public returns (int){ - emit log(i); - return i; - } - function changeNegativeInt(int param) public returns (int){ - i2 = param; - emit log(i2); - return i2; - } - function getNegativeInt() public returns (int){ - emit log(i2); - return i2; - } - function changeUint(uint param) public returns (uint){ - ui = param; - emit log(ui); - return ui; - } - function getUint() public returns (uint){ - emit log(ui); - return ui; - } - function changeAddress(address param) public returns (address){ - origin = param; - emit log(origin); - return origin; - } - function getAddress() public returns (address){ - emit log(origin); - return origin; - } - function changeBytes32(bytes32 param) public returns (bytes32){ - b32 = param; - emit log(b32); - return b32; - } - function getBytes32() public returns (bytes32){ - emit log(b32); - return b32; - } - function changeBytes(bytes memory param) public returns (bytes memory){ - bs = param; - emit log(bs); - return bs; - } - function getBytes() public returns (bytes memory){ - emit log(bs); - return bs; - } - function changeString(string memory param) public returns (string memory){ - s = param; - emit log(s); - return s; - } - function getString() public returns (string memory){ - emit log(s); - return s; - } - function changeActionChoices(ActionChoices param) public returns (ActionChoices){ - choice = param; - emit log(choice); - return choice; - } - function getActionChoices() public returns (ActionChoices){ - emit log(choice); - return choice; - } - function changeInt64NegativeArray(int64[] memory param) public returns (int64[] memory){ - b = param; - emit log(b); - return b; - } - function getInt64NegativeArray() public returns (int64[] memory){ - emit log(b); - return b; - } - function changeInt32Array(int32[2][] memory param) public returns (int32[2][] memory){ - tmp_h = param; - emit log(tmp_h); - return tmp_h; - } - function getInt32Array() public returns (int32[2][] memory){ - emit log(tmp_h); - return tmp_h; - } - function changeInt256Array(int256[2][2] memory param) public returns (int256[2][2] memory){ - tmp_i = param; - emit log(tmp_i); - return tmp_i; - } - function getInt256Array() public returns (int256[2][2] memory){ - emit log(tmp_i); - return tmp_i; - } - function setMapping(uint256 param) public returns (uint256){ - mapa[msg.sender] = param; - return mapa[msg.sender]; - - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/constantCallStorage002.sol b/framework/src/test/resources/soliditycode_0.6.12/constantCallStorage002.sol deleted file mode 100644 index 1ceba5e87d2..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/constantCallStorage002.sol +++ /dev/null @@ -1,16 +0,0 @@ -contract NotView { - uint256 public num = 123; - function setnum() public returns(uint256){ - num = num + 15; - return num; - } -} -contract NotViewInterface{ - function setnum() public view returns(uint256); -} -contract UseNotView { - function setnumuseproxy(address contractAddress) public view returns(uint256){ - NotViewInterface inter = NotViewInterface(contractAddress); - return inter.setnum(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/constantCallStorage0425.sol b/framework/src/test/resources/soliditycode_0.6.12/constantCallStorage0425.sol deleted file mode 100644 index 8ecf771626d..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/constantCallStorage0425.sol +++ /dev/null @@ -1,156 +0,0 @@ -contract constantCall { - bool stopped = false; - int i = 32482989; - int i2 = -32482989; - uint ui = 23487823; - address origin = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; - bytes32 b32 = 0xb55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105c; - bytes bs = new bytes(9); - string s = "123qwe"; - enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } - ActionChoices choice = ActionChoices.SitStill; - int64[] b = [91, 2, 333]; - int32[2][] tmp_h = [[1,2],[3,4],[5,6]]; - int256[2][2] tmp_i = [[11,22],[33,44]]; - mapping (address => uint256) public mapa; - - constructor() payable public{ - mapa[address(0x00)] = 88; - } - event log(int); - event log(uint); - event log(bool); - event log(address); - event log(bytes32); - event log(bytes); - event log(string); - event log(ActionChoices); - event log(int64[]); - event log(int32[2][]); - event log(int256[2][2]); - - function changeBool(bool param) public constant returns (bool){ - stopped = param; - log(stopped); - return stopped; - } - function getBool() public constant returns (bool){ - log(stopped); - return stopped; - } - - function changeInt(int param) public returns (int){ - i = param; - log(i); - return i; - } - function getInt() public returns (int){ - log(i); - return i; - } - - function changeNegativeInt(int param) public constant returns (int){ - i2 = param; - log(i2); - return i2; - } - function getNegativeInt() public constant returns (int){ - log(i2); - return i2; - } - - function changeUint(uint param) public returns (uint){ - ui = param; - log(ui); - return ui; - } - function getUint() public returns (uint){ - log(ui); - return ui; - } - - function changeAddress(address param) public constant returns (address){ - origin = param; - log(origin); - return origin; - } - function getAddress() public constant returns (address){ - log(origin); - return origin; - } - - function changeBytes32(bytes32 param) public constant returns (bytes32){ - b32 = param; - log(b32); - return b32; - } - function getBytes32() public returns (bytes32){ - log(b32); - return b32; - } - - function changeBytes(bytes param) public constant returns (bytes){ - bs = param; - log(bs); - return bs; - } - function getBytes() public constant returns (bytes){ - log(bs); - return bs; - } - - function changeString(string param) public constant returns (string){ - s = param; - log(s); - return s; - } - function getString() public returns (string){ - log(s); - return s; - } - - function changeActionChoices(ActionChoices param) public constant returns (ActionChoices){ - choice = param; - log(choice); - return choice; - } - function getActionChoices() public constant returns (ActionChoices){ - log(choice); - return choice; - } - - function changeInt64NegativeArray(int64[] param) public constant returns (int64[]){ - b = param; - log(b); - return b; - } - function getInt64NegativeArray() public constant returns (int64[]){ - log(b); - return b; - } - - function changeInt32Array(int32[2][] param) public returns (int32[2][]){ - tmp_h = param; - log(tmp_h); - return tmp_h; - } - function getInt32Array() public constant returns (int32[2][]){ - log(tmp_h); - return tmp_h; - } - - function changeInt256Array(int256[2][2] param) public returns (int256[2][2]){ - tmp_i = param; - log(tmp_i); - return tmp_i; - } - function getInt256Array() public constant returns (int256[2][2]){ - log(tmp_i); - return tmp_i; - } - function setMapping(uint256 param) public returns (uint256){ - mapa[msg.sender] = param; - return mapa[msg.sender]; - - } -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/constantContract001.sol b/framework/src/test/resources/soliditycode_0.6.12/constantContract001.sol deleted file mode 100644 index 7d574c5a008..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/constantContract001.sol +++ /dev/null @@ -1,8 +0,0 @@ - - -contract testConstantContract{ -function testPure(uint256 x,uint256 y) public pure returns (uint256 z) { -uint256 i=1; -return i + x + y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGetterContract.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGetterContract.sol deleted file mode 100644 index 365b53ebf1a..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGetterContract.sol +++ /dev/null @@ -1,17 +0,0 @@ - - - -contract getterContract { - -constructor() public payable{} -fallback() external payable{} - -uint public c = msg.value; - -function getDataUsingAccessor() public payable returns (uint){ - -return c; - -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test1Grammar001.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test1Grammar001.sol deleted file mode 100644 index 659e56c9150..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test1Grammar001.sol +++ /dev/null @@ -1,18 +0,0 @@ - -contract FunctionSelector { - function select(bool useB, uint x) public returns (uint z) { - //var f = a; - //if (useB) f = b; - //return f(x); - if (useB) - return b(x); - else - return a(x); - } -function a(uint x) public returns (uint z) { - return x * x; - } -function b(uint x) public returns (uint z) { - return 2 * x; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test2Grammar002.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test2Grammar002.sol deleted file mode 100644 index 744b17e9585..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test2Grammar002.sol +++ /dev/null @@ -1,44 +0,0 @@ - -library Set { - // We define a new struct datatype that will be used to - // hold its data in the calling contract. - struct Data { mapping(uint => bool) flags; } - - // Note that the first parameter is of type "storage - // reference" and thus only its storage address and not - // its contents is passed as part of the call. This is a - // special feature of library functions. It is idiomatic - // to call the first parameter 'self', if the function can - // be seen as a method of that object. - function insert(Data storage self, uint value) public returns (bool) { - if (self.flags[value]) - return false; // already there - self.flags[value] = true; - return true; - } - - function remove(Data storage self, uint value) public returns (bool) { - if (!self.flags[value]) - return false; // not there - self.flags[value] = false; - return true; - } - - function contains(Data storage self, uint value) public returns (bool) { - return self.flags[value]; - } -} - - -contract C { - Set.Data knownValues; - - function register (uint value) public{ - // The library functions can be called without a - // specific instance of the library, since the - // "instance" will be the current contract. - if (!Set.insert(knownValues, value)) - revert(); - } - // In this contract, we can also directly access knownValues.flags, if we want. -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test3Grammar003.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test3Grammar003.sol deleted file mode 100644 index 140ba2a8f56..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test3Grammar003.sol +++ /dev/null @@ -1,44 +0,0 @@ - - -library Set { - struct Data { mapping(uint => bool) flags; } - - function insert(Data storage self, uint value) public - returns (bool) - { - if (self.flags[value]) - return false; // already there - self.flags[value] = true; - return true; - } - - function remove(Data storage self, uint value) public - returns (bool) - { - if (!self.flags[value]) - return false; // not there - self.flags[value] = false; - return true; - } - - function contains(Data storage self, uint value) public - returns (bool) - { - return self.flags[value]; - } -} - - -contract C { - using Set for Set.Data; // this is the crucial change - Set.Data knownValues; - - function register(uint value) public{ - // Here, all variables of type Set.Data have - // corresponding member functions. - // The following function call is identical to - // Set.insert(knownValues, value) - if (!knownValues.insert(value)) - revert(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test4Grammar004.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test4Grammar004.sol deleted file mode 100644 index 772691cebc5..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test4Grammar004.sol +++ /dev/null @@ -1,31 +0,0 @@ - - -library Search { - function indexOf(uint[] storage self, uint value) public returns (uint) { - for (uint i = 0; i < self.length; i++) - if (self[i] == value) return i; - return uint(-1); - } -} - - -contract C { - using Search for uint[]; - uint[] public data; - - function append(uint value) public{ - data.push(value); - } - - function replace(uint _old, uint _new) public{ - // This performs the library function call - uint index = data.indexOf(_old); - if (index == uint(-1)) - data.push(_new); - else - data[index] = _new; - } - function getData(uint256 index) public returns(uint256){ - return data[index]; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test5Grammar006.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test5Grammar006.sol deleted file mode 100644 index 275d42d1e71..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar001test5Grammar006.sol +++ /dev/null @@ -1,45 +0,0 @@ -contract InfoFeed { -function d1(uint x1) public{ - - assembly{ - function f(x) -> y { switch x case 0 { y := 1 } default { y := mul(x, f(sub(x, 1))) } } - } - } - function d2(uint x1) public{ - assembly { - let x:=1 - x := mul(1, add(2, 3))} - } - function f(uint x) public{ - assembly { x := sub(x, 1) } - - } - // 0.6.0 Variable declarations cannot shadow declarations outside the assembly block. - function d(uint x1) public returns(uint256){ - uint256 x; - assembly{ - x := add(2, 3) - let y := mload(0x40) - x := add(x, y) - } - return x; - } - function d4(uint x) public{ - // Error: The labels 'repeat' is disallowed. Please use "if", "switch", "for" or function calls instead - //assembly{let x := 10 repeat: x := sub(x, 1) jumpi(repeat, eq(x, 0)) - x = x; - //} - } - function d5(uint x1) public{ - assembly{ - function f(x) -> y { switch x case 0 { y := mul(x, 2) } default { y := 0 } } - - } - } - - function d6(uint x1) public{ - assembly{ - function f(x) -> y { for { let i := 0 } lt(i, x) { i := add(i, 1) } { y := mul(2, y) } } - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test1Grammar007_1.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test1Grammar007_1.sol deleted file mode 100644 index 020c2a38ca4..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test1Grammar007_1.sol +++ /dev/null @@ -1,60 +0,0 @@ -contract Doug{ - mapping (bytes32 => uint) public contracts; - constructor() public{ - contracts['hww'] = 1; - contracts['brian'] = 2; - contracts['zzy'] = 7; - } - - function getDougName(string memory _name) public view returns(string memory) { - return _name; - } - - function getDougAge(uint _age) public pure returns(uint) { - return 3 ** _age; - } -} - -// -abstract contract DogInterface { - function getDougAge(uint _age) public virtual returns (uint); - function contracts(bytes32 name) public virtual returns (uint); -} -contract main{ - - event FetchContract(address dogInterfaceAddress, address sender, bytes32 name); - - address public DOUG; - - address dogInterfaceAddress; - DogInterface dogContract ; - - function setDOUG(address _doug) public { - DOUG = _doug; - } - - constructor(address addr) public{ - dogInterfaceAddress = addr; - dogContract = DogInterface(dogInterfaceAddress); - } - - function dougOfage(uint _age) public returns(uint) { - - uint num = dogContract.getDougAge(_age); - return _age+num; - // return num; - } - - function uintOfName(bytes32 _name) public returns (uint) { - - dogContract.contracts(_name); - emit FetchContract(dogInterfaceAddress, msg.sender, _name); - - } - - // function getTest(string _name) public view returns(string) { - // string memory newName = _name ; - // DogInterface(DOUG).getDougName(newName); - // return newName; - // } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test1Grammar007_2.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test1Grammar007_2.sol deleted file mode 100644 index 8945b566543..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test1Grammar007_2.sol +++ /dev/null @@ -1,60 +0,0 @@ - -contract Doug{ - mapping (bytes32 => uint) public contracts; - constructor() public{ - contracts['hww'] = 1; - contracts['brian'] = 2; - contracts['zzy'] = 7; - } - - function getDougName(string memory _name) public view returns(string memory) { - return _name; - } - - function getDougAge(uint _age) public pure returns(uint) { - return 3 ** _age; - } -} - -abstract contract DogInterface { - function getDougAge(uint _age) public virtual returns (uint); - function contracts(bytes32 name) public virtual returns (uint); -} -contract main{ - - event FetchContract(address dogInterfaceAddress, address sender, bytes32 name); - - address public DOUG; - - address dogInterfaceAddress; - DogInterface dogContract ; - - function setDOUG(address _doug) public { - DOUG = _doug; - } - - constructor(address addr) public{ - dogInterfaceAddress = addr; - dogContract = DogInterface(dogInterfaceAddress); - } - - function dougOfage(uint _age) public returns(uint) { - - uint num = dogContract.getDougAge(_age); - return _age+num; - // return num; - } - - function uintOfName(bytes32 _name) public returns (uint) { - - dogContract.contracts(_name); - emit FetchContract(dogInterfaceAddress, msg.sender, _name); - - } - - // function getTest(string _name) public view returns(string) { - // string memory newName = _name ; - // DogInterface(DOUG).getDougName(newName); - // return newName; - // } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test2Grammar008.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test2Grammar008.sol deleted file mode 100644 index 956623c3103..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test2Grammar008.sol +++ /dev/null @@ -1,18 +0,0 @@ - - -// version 0.6.0 change -// add abstract and override -abstract contract Feline { - - function utterance() public virtual returns (bytes32); - - function getContractName() public returns (string memory){ - return "Feline"; - } -} - - -contract Cat is Feline { - function utterance() public override returns (bytes32) { return "miaow"; } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test3Grammar010.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test3Grammar010.sol deleted file mode 100644 index d6845d2e336..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test3Grammar010.sol +++ /dev/null @@ -1,10 +0,0 @@ - -contract InfoFeed { -function info() public payable returns (uint ret) { return 42; } -} -contract Consumer { -constructor() payable public{} -InfoFeed feed; -function setFeed(address addr) public { feed = InfoFeed(addr); } -function callFeed() public payable { feed.info.value(10).gas(800)(); } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test4Grammar011.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test4Grammar011.sol deleted file mode 100644 index fcd18f438ef..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test4Grammar011.sol +++ /dev/null @@ -1,11 +0,0 @@ - -contract C { -function f(uint key, uint value) public returns(uint) { -return key; -// do something -} -function g() public { -// named arguments -f({value: 2, key: 3}); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test4Grammar012.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test4Grammar012.sol deleted file mode 100644 index 8fb3c750298..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test4Grammar012.sol +++ /dev/null @@ -1,24 +0,0 @@ - -contract rTest { -function info() public payable returns (uint,address,bytes4,uint,uint,uint,address,uint) { -//function info() public payable returns (address ,uint,uint,uint,bytes32,uint,bytes,uint,address,bytes4,uint,uint,uint,address,uint) { -//var a = block.coinbase ; -//var b = block.difficulty; -//var c = block.gaslimit; -//var d = block.number; -//var e = block.blockhash(0); -//var e = d; -//var f = block.timestamp; -//bytes memory g = msg.data; -uint256 h = gasleft(); -address payable i = msg.sender; -bytes4 j = msg.sig; -uint256 k = msg.value; -uint256 l = now; -uint256 m = tx.gasprice; -address payable n = tx.origin; -uint256 o = address(this).balance; -return (h,i,j,k,l,m,n,o); -//return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test6Grammar013.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test6Grammar013.sol deleted file mode 100644 index 53de5def6bc..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar002test6Grammar013.sol +++ /dev/null @@ -1,24 +0,0 @@ - -contract Counter { -uint count = 0; -address payable owner; -//function Counter() public{ -constructor() public{ -owner = msg.sender; -} -function increment() public { -uint step = 10; -if (owner == msg.sender) { -count = count + step; -} -} -function getCount() public returns (uint){ -return count; -} -function kill() public{ -if (owner == msg.sender) { -selfdestruct(owner); -//selfdestruct(address(owner)); -} -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test1Grammar014.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test1Grammar014.sol deleted file mode 100644 index b2d70b3741c..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test1Grammar014.sol +++ /dev/null @@ -1,67 +0,0 @@ -contract A { -uint256 public numberForB; -address public senderForB; -function callTest(address bAddress, uint256 _number) public{ - -//bAddress.call(bytes4(sha3("setValue(uint256)")), _number); // B's storage is set, A is not modified -bAddress.call(abi.encodeWithSignature("setValue(uint256)",_number)); // B's storage is set, A is not modified -} -function callcodeTest(address bAddress, uint256 _number) public{ -//bAddress.callcode(bytes4(sha3("setValue(uint256)")), _number); // A's storage is set, B is not modified -bAddress.delegatecall(abi.encodeWithSignature("setValue(uint256)", _number)); // A's storage is set, B is not modified -} -function delegatecallTest(address bAddress, uint256 _number) public{ -//bAddress.delegatecall(bytes4(sha3("setValue(uint256)")), _number); // A's storage is set, B is not modified -bAddress.delegatecall(abi.encodeWithSignature("setValue(uint256)", _number)); // A's storage is set, B is not modified -} - -function callAddTest(address bAddress) public{ -//bAddress.call(bytes4(sha3("add()"))); // B's storage is set, A is not modified -bAddress.call(abi.encodeWithSignature("add()")); // B's storage is set, A is not modified -//bAddress.call(bytes4(sha3("add()"))); // B's storage is set, A is not modified -bAddress.call(abi.encodeWithSignature("add()")); // B's storage is set, A is not modified -} -function getnumberForB() public returns(uint256){ - return numberForB; - } - function getsenderForB() public returns(address){ - return senderForB; - } -} -contract B { -uint256 public numberForB; -address public senderForB; -address public addr11; -mapping(uint256=>address) public addr1; -mapping(uint256=>address) public addr2; -event ssss(uint256); -function setValue(uint256 _number) public{ - -emit ssss(_number); -numberForB = _number; -senderForB = msg.sender; -// senderForB is A if invoked by A's callTest. B's storage will be updated -// senderForB is A if invoked by A's callcodeTest. None of B's storage is updated -// senderForB is OWNER if invoked by A's delegatecallTest. None of B's storage is updated -} - -function add() public{ -numberForB=numberForB+1; -C c1 = new C(); -addr1[numberForB]=c1.getAddress(); -addr11 = c1.getAddress(); -C c2 = new C(); -addr2[numberForB] = c2.getAddress(); -} -function getnumberForB() public returns(uint256){ - return numberForB; - } - function getsenderForB() public returns(address){ - return senderForB; - } -} -contract C { -function getAddress() public view returns(address){ -return address(this); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test2Grammar015.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test2Grammar015.sol deleted file mode 100644 index 0aa93e5e94f..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test2Grammar015.sol +++ /dev/null @@ -1,40 +0,0 @@ - - -contract ExecuteFallback{ - - //回退事件,会把调用的数据打印出来 - event FallbackCalled(bytes data); - //fallback函数,注意是没有名字的,没有参数,没有返回值的 - // 0.6.0 Split unnamed fallback functions into two cases defined using fallback() and receive() - fallback() external{ - emit FallbackCalled(msg.data); - } - - //调用已存在函数的事件,会把调用的原始数据,请求参数打印出来 - event ExistFuncCalled(bytes data, uint256 para); - //一个存在的函数 - function existFunc(uint256 para) public{ - emit ExistFuncCalled(msg.data, para); - } - - // 模拟从外部对一个存在的函数发起一个调用,将直接调用函数 - function callExistFunc() public{ - bytes4 funcIdentifier = bytes4(keccak256("existFunc(uint256)")); - //this.call(funcIdentifier, uint256(1)); - address(this).call(abi.encode(funcIdentifier, uint256(1))); - } - - //模拟从外部对一个不存在的函数发起一个调用,由于匹配不到函数,将调用回退函数 - function callNonExistFunc() public{ - bytes4 funcIdentifier = bytes4(keccak256("functionNotExist()")); - //this.call(funcIdentifier); - address(this).call(abi.encode(funcIdentifier)); - } - - function ExistFuncCalledTopic() view public returns(bytes32){ - return keccak256("ExistFuncCalled(bytes,uint256)"); - } - function FallbackCalledTopic() view public returns(bytes32){ - return keccak256("FallbackCalled(bytes)"); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test3Grammar016.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test3Grammar016.sol deleted file mode 100644 index 6a73d7a8d7e..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test3Grammar016.sol +++ /dev/null @@ -1,23 +0,0 @@ - -contract C { -uint private data; -function f(uint a) private returns(uint b) { return a + 1; } -function setData(uint a) public { data = a; } -function getData() public returns(uint) { return data; } -function compute(uint a, uint b) internal returns (uint) { return a+b; } -} -contract D { -function readData() public{ -C c = new C(); -//uint local = c.f(7); // error: member "f" is not visible -c.setData(3); -uint local = c.getData(); -// local = c.compute(3, 5); // error: member "compute" is not visible -} -} -contract E is C { -function g() public { -C c = new C(); -uint val = compute(3, 5); // access to internal member (from derived to parent contract) -} -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test4Grammar017.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test4Grammar017.sol deleted file mode 100644 index fb81b6e529c..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test4Grammar017.sol +++ /dev/null @@ -1,50 +0,0 @@ - -contract CrowdFunding{ -struct Funder{ -address addr; -uint amount; -} - -struct Campaign{ -address payable beneficiary; -uint goal; -uint amount; -uint funderNum; -mapping(uint => Funder) funders; -} - -uint compaingnID; -mapping (uint => Campaign) campaigns; - -function candidate(address payable beneficiary, uint goal) public payable returns (uint compaingnID){ -// initialize -campaigns[compaingnID++] = Campaign(beneficiary, goal, 0, 0); -} - -function vote(uint compaingnID) payable public { -Campaign storage c = campaigns[compaingnID]; - -//another way to initialize -c.funders[c.funderNum++] = Funder({addr: msg.sender, amount: msg.value}); -c.amount += msg.value; -} - -function check(uint comapingnId) public payable returns (bool){ - Campaign memory c = campaigns[comapingnId]; - - if(c.amount < c.goal){ - return false; - } - - uint amount = c.amount; - // incase send much more - c.amount = 0; - // address payable addr = address(uint160(c.beneficiary)); - //if(! addr.send(amount)){ - - if (! c.beneficiary.send(amount)){ - revert(); - } - return true; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test5Grammar018.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test5Grammar018.sol deleted file mode 100644 index ec241f3eae9..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test5Grammar018.sol +++ /dev/null @@ -1,37 +0,0 @@ - - - -contract Grammar18{ - function testAddmod() public returns (uint z) { - //计算(x + y)%k,其中以任意精度执行加法,并且不在2 ** 256处围绕 - z=addmod(2, 2, 3); - return z; - } - function testMulmod() public returns (uint z) { -//计算(x * y)%k,其中乘法以任意精度执行,并且不会在2 ** 256处循环。 - z=mulmod(2, 3, 4); - return z; - } - - function testKeccak256() public returns(bytes32){ - //计算的(紧凑)参数的Ethereum-SHA-3(Keccak-256)的散列 - return keccak256("11"); - } - - function testSha256() public returns(bytes32){ - //计算(紧密包装)参数的SHA-256散列 - return sha256("11"); - } - function testSha3() public returns(bytes32){ - //计算(紧密包装)参数的SHA-256散列 - //return sha3("11"); - return keccak256("11"); - } - - function testRipemd160() public returns(bytes32){ - //计算(紧密包装)参数的RIPEMD-160哈希值 - return ripemd160("11"); - } - - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test6Grammar019.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test6Grammar019.sol deleted file mode 100644 index 727ef7091e7..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test6Grammar019.sol +++ /dev/null @@ -1,12 +0,0 @@ - -contract timetest { - -constructor() public { -require( 1 == 1 seconds); -require(1 minutes == 60 seconds); -require(1 hours == 60 minutes); -require(1 days == 24 hours); -require(1 weeks == 7 days); -//require(1 years == 365 days); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test7Grammar020.sol b/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test7Grammar020.sol deleted file mode 100644 index 39a7fddcb7e..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractGrammar003test7Grammar020.sol +++ /dev/null @@ -1,8 +0,0 @@ - -contract trxtest { - -function test() public { -require(1 trx == 1000000 sun); - -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInnerContract.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInnerContract.sol deleted file mode 100644 index 0de68bbf7da..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInnerContract.sol +++ /dev/null @@ -1,32 +0,0 @@ - - - - -contract InnerContract { - - constructor() public payable{} - fallback() external payable{} - - function messageI() payable public returns (uint ret) { - - - - } - -} - - - -contract OuterContract { - - - constructor() public payable{} - fallback() external payable{} - - function callInner(address payable addr) payable public returns (uint) { - - return InnerContract(addr).messageI.value(1)(); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction001.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction001.sol deleted file mode 100644 index 02fa51949c3..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction001.sol +++ /dev/null @@ -1,41 +0,0 @@ - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address payable cAddr) public payable{ - B b1 = (new B).value(10)();//1.1 - B b2 = new B();//1.2 - payable(address(b2)).transfer(5);//1.3 - b2.callCGetZero(cAddr, 1);//1.4 - b2.callCGetZero(cAddr,2);//1.6 - } - function test2(address payable cAddress,uint256 amount) public payable{ - cAddress.call.value(amount)(abi.encodeWithSignature("newBAndTransfer()"));//2.1 - cAddress.call.value(amount + 1)(abi.encodeWithSignature("newBAndTransfer()"));//2.6 - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero(address payable cAddress,uint256 amount) public{ - cAddress.call.value(amount)(abi.encodeWithSignature("getZero()"));//1.5,1.7 - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - B b1 = (new B).value(7)();//2.2,2.7 - b1.getOne();//2.3,2.8 - B b2 = (new B).value(3)();//2.4,2.9 - b2.getOne();//2.5,2.10 - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction002.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction002.sol deleted file mode 100644 index 92edfeb1157..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction002.sol +++ /dev/null @@ -1,20 +0,0 @@ - -contract A{ - constructor() payable public{} - fallback() payable external{} - - function test2(address cAddress,uint256 amount) public payable{ - //cAddress.call.value(amount)();//2.1 - cAddress.call.value(amount)("");//2.1 - } -} - - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction003.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction003.sol deleted file mode 100644 index 2e17d6dbc02..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction003.sol +++ /dev/null @@ -1,30 +0,0 @@ - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer() payable public{ - B b = (new B).value(10)();//1 - - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable public returns(bool) { - return true; - } - constructor() public payable {} - function payC(address payable c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - fallback() payable external{} - } - diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction004.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction004.sol deleted file mode 100644 index e8f32d7bfd9..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction004.sol +++ /dev/null @@ -1,24 +0,0 @@ - -contract A{ - constructor () payable public{} - function test(address payable toAddress) public payable{ - selfdestruct(toAddress); - } - fallback() payable external{} - function getBalance() public view returns(uint256){ - return address(this).balance; - } -} -contract B{ - fallback() external payable{} - function kill(address contractAddres, address toAddress) payable public { - contractAddres.call(abi.encodeWithSignature("test(address)",address(this))); - } - function kill2() public{ - A a = new A(); - a.test(payable(address(this))); - } - function getBalance() public view returns(uint256){ - return address(this).balance; - } -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction005.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction005.sol deleted file mode 100644 index b198d260e4d..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction005.sol +++ /dev/null @@ -1,53 +0,0 @@ - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1() public payable{ - B b1 = (new B).value(10)();//1.1 - b1.callCGetZero(false); - b1.callCGetZero(true);//1.4 - } - function test2() public payable{ - C c1 = (new C).value(10)();//1.1 - c1.newBAndTransfer(false); - c1.newBAndTransfer(true);//1.4 - - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero(bool success) public payable{ - if(!success){ - assert(1==2); - } - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract C{ - uint256 public flag=0; - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer(bool success) payable public returns(uint256){ - flag = 1; - if(!success){ - require(2==1); - } - } - function getFlag() public returns(uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction006.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction006.sol deleted file mode 100644 index ca51fda2021..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction001testInternalTransaction006.sol +++ /dev/null @@ -1,54 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1() public payable{ - B b1 = (new B).value(10)();//1.1 - b1.callCGetZero(true);//1.4 - b1.callCGetZero(false); - } - function test2() public payable{ - C c1 = (new C).value(10)();//1.1 - c1.newBAndTransfer(true);//1.4 - c1.newBAndTransfer(false); - - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero(bool success) public payable{ - if(!success){ - assert(1==2); - } - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract C{ - uint256 public flag=0; - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer(bool success) payable public returns(uint256){ - flag = 1; - if(!success){ - require(2==1); - } - } - function getFlag() public returns(uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test1InternalTransaction007.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test1InternalTransaction007.sol deleted file mode 100644 index 528fb9fa8a8..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test1InternalTransaction007.sol +++ /dev/null @@ -1,38 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address cAddr) public payable{ - B b1 = (new B).value(10)();//1.1 - B b2 = new B();//1.2 - payable(address(b2)).transfer(5);//1.3 - b2.callCGetZero();//1.4 - } - function test2(address cAddress,uint256 amount) public payable{ - cAddress.call.value(amount)(abi.encodeWithSignature("newBAndTransfer()"));//2.1 - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero() public{ - assert(1==2); - - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test2InternalTransaction008.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test2InternalTransaction008.sol deleted file mode 100644 index c1e9ea0596f..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test2InternalTransaction008.sol +++ /dev/null @@ -1,60 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - - function testAssert(address bAddress,uint256 amount) public payable{ - bAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("callCGetZero(bool)",false));//2.1 - bAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("callCGetZero(bool)",true)); - } - function testRequire(address cAddress,uint256 amount) public payable{ - cAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("newBAndTransfer(bool)",false));//2.1 - cAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("newBAndTransfer(bool)",true)); - } - function testAssert1(address bAddress,uint256 amount) public payable{ - bAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("callCGetZero(bool)",true)); - bAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("callCGetZero(bool)",false));//2.1 - } - function testtRequire2(address cAddress,uint256 amount) public payable{ - cAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("newBAndTransfer(bool)",true)); - cAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("newBAndTransfer(bool)",false));//2.1 - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero(bool success) payable public{ - if(!success){ - assert(1==2); - } - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract C{ - uint256 public flag=0; - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer(bool success) payable public returns(uint256){ - flag = 1; - if(!success){ - require(2==1); - } - } - function getFlag() public returns(uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test3InternalTransaction009.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test3InternalTransaction009.sol deleted file mode 100644 index 7c8a1f8c879..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test3InternalTransaction009.sol +++ /dev/null @@ -1,47 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address cAddr,address dcontract,address baddress) public payable{ - B b1 = (new B).value(10)();//1.1 - payable(address(b1)).transfer(5);//1.3 - b1.callCGetZero(cAddr, 1);//1.4 - b1.getOne(dcontract,baddress); - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne(address contractAddres, address toAddress) payable public{ - contractAddres.call(abi.encodeWithSignature("suicide1(address)",address(this))); - - } - function callCGetZero(address cAddress,uint256 amount) public{ - cAddress.call.value(amount)(abi.encodeWithSignature("getZero()"));//1.5,1.7 - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public{ - B b1 = (new B).value(7)();//2.2,2.7 - B b2 = (new B).value(3)();//2.4,2.9 - } -} - -contract D{ - constructor () payable public{} - function suicide1(address payable toAddress) public payable{ - selfdestruct(toAddress); - } - fallback() payable external{} - function getBalance() public view returns(uint256){ - return address(this).balance; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test4InternalTransaction010.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test4InternalTransaction010.sol deleted file mode 100644 index af2b54af172..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test4InternalTransaction010.sol +++ /dev/null @@ -1,186 +0,0 @@ - - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - - } - function transfer2() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - - } - function getBalance() public returns(uint256) { - return address(this).balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable public returns(bool) { - return true; - } - constructor() public payable {} - function payC(address payable c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - fallback() payable external{} - } - diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test4InternalTransaction010_1.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test4InternalTransaction010_1.sol deleted file mode 100644 index d0c80d14ffb..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test4InternalTransaction010_1.sol +++ /dev/null @@ -1,210 +0,0 @@ - - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - } - function transfer2() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - - } - function getBalance() returns(uint256){ - return this.balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable returns(bool) { - return true; - } - constructor() public payable {} - function payC(address c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() returns(uint256){ - return this.balance; - } - fallback() payable{} - } - - \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test5InternalTransaction012.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test5InternalTransaction012.sol deleted file mode 100644 index e9bc38b58d4..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction002test5InternalTransaction012.sol +++ /dev/null @@ -1,51 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address bAddr,address eAddr) public payable{ - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - } - -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function testNN(address eAddress) public payable{ - D d1=(new D).value(1000)(); - d1.getOne(eAddress); - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract D{ - constructor() payable public{} - fallback() payable external{} - function getOne(address eAddress) payable public returns(uint256){ - eAddress.call.value(1)(abi.encodeWithSignature("getZero()"));//2.1 - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction013.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction013.sol deleted file mode 100644 index 3ef9264ee70..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction013.sol +++ /dev/null @@ -1,56 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address dAddr) public payable{ - B b1 = (new B).value(10)();//1.1 - b1.testNN(dAddr,2);//1.6 - // C c1 = (new C).value(1000000000000)();//1.2 - // E e1 = (new E).value(1)();//1.2 - } - function test2(address cAddress,uint256 amount) public payable{ - cAddress.call.value(amount)(abi.encodeWithSignature("newBAndTransfer()"));//2.1 - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function testNN(address dAddress,uint256 amount) public payable{ - // D d1=(new D)(); - dAddress.call.value(amount)(abi.encodeWithSignature("getOne()"));//2.1 - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract D{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - E e = (new E).value(5)(); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction014.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction014.sol deleted file mode 100644 index 5647048bab3..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction014.sol +++ /dev/null @@ -1,38 +0,0 @@ -contract callerContract { - constructor() payable public{} - fallback() payable external{} - function sendToB(address called_address,address c) public payable{ - called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); - } - function sendToB2(address called_address,address c) public payable{ - called_address.call(abi.encodeWithSignature("transferTo(address)",c)); - } - function sendToB3(address called_address,address c) public payable{ - called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); - } -} - - contract calledContract { - fallback() payable external {} - constructor() payable public{} - function transferTo(address payable toAddress)public payable{ - toAddress.transfer(5); - } - - function setIinC(address c) public payable{ - c.call.value(5)(abi.encodeWithSignature("setI()")); - } - - } - - contract c{ - uint256 public i=0; - constructor() public payable{} - function getBalance() public view returns(uint256){ - return address(this).balance; - } - function setI() payable public{ - i=5; - } - fallback() payable external{} - } diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction015.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction015.sol deleted file mode 100644 index 229f79f3c96..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction015.sol +++ /dev/null @@ -1,60 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address dAddr,address eAddr) public payable{ - B b1 = (new B).value(10)();//1.1 - b1.testNN(dAddr,2,eAddr);//1.6 - // C c1 = (new C).value(1000000000000)();//1.2 - // E e1 = (new E).value(1)();//1.2 - } - function test2(address cAddress,uint256 amount) public payable{ - cAddress.call.value(amount)(abi.encodeWithSignature("newBAndTransfer()"));//2.1 - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function testNN(address dAddress,uint256 amount,address eAddress) public payable{ - // D d1=(new D)(); - dAddress.call.value(amount)(abi.encodeWithSignature("getOne(address)",address(this)));//2.1 - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } - function suicide(address payable toAddress) public payable{ - selfdestruct(toAddress); - } -} -contract D{ - constructor() payable public{} - fallback() payable external{} - function getOne(address payable eAddress) payable public{ - E e = (new E).value(5)(); - e.suicide(eAddress); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction016.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction016.sol deleted file mode 100644 index f5cbdc2f1fa..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction016.sol +++ /dev/null @@ -1,174 +0,0 @@ - - - contract A{ - uint256 public num = 0; - constructor() public payable{} - fallback() payable external{} - function transfer() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - B b1=(new B).value(1)();//1 - address payable aaa=address(this); - b1.suicide1(aaa); - } - function transfer2() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - B b1=(new B).value(1)();//1 - address payable aaa=address(this); - b1.suicide1(aaa); - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable public returns(bool) { - return true; - } - constructor() public payable {} - function payC(address payable c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - fallback() payable external{} - function suicide1(address payable toAddress) public payable{ - selfdestruct(toAddress); - } - } - diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction017.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction017.sol deleted file mode 100644 index 6847eebc546..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction017.sol +++ /dev/null @@ -1,199 +0,0 @@ - - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer(address payable Address) payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - - B b=(new B).value(1)();//1 - selfdestruct(Address); - } - function transfer2() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable public returns(bool) { - return true; - } - constructor() public payable {} - function payC(address payable c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - fallback() payable external{} - } - diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction018.sol b/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction018.sol deleted file mode 100644 index 80705ffd5e9..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractInternalTransaction003testInternalTransaction018.sol +++ /dev/null @@ -1,97 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address payable bAddr,address eAddr) public payable{ - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - - } - -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function testNN(address eAddress) public payable { - D d1=(new D).value(100)(); - d1.getOne(eAddress); - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract D{ - constructor() payable public{} - fallback() payable external{} - function getOne(address eAddress) payable public returns(uint256){ - eAddress.call.value(1)(abi.encodeWithSignature("getZero()"));//2.1 - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractLinkage001.sol b/framework/src/test/resources/soliditycode_0.6.12/contractLinkage001.sol deleted file mode 100644 index 8d441fba2da..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractLinkage001.sol +++ /dev/null @@ -1,9 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -constructor() payable public{} -fallback() payable external{} -function divideIHaveArgsReturn(int x,int y) public payable returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractLinkage002.sol b/framework/src/test/resources/soliditycode_0.6.12/contractLinkage002.sol deleted file mode 100644 index 92778e42bc9..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractLinkage002.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractLinkage003.sol b/framework/src/test/resources/soliditycode_0.6.12/contractLinkage003.sol deleted file mode 100644 index 92778e42bc9..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractLinkage003.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractLinkage004.sol b/framework/src/test/resources/soliditycode_0.6.12/contractLinkage004.sol deleted file mode 100644 index 92778e42bc9..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractLinkage004.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractLinkage005.sol b/framework/src/test/resources/soliditycode_0.6.12/contractLinkage005.sol deleted file mode 100644 index 7b943aee5c1..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractLinkage005.sol +++ /dev/null @@ -1,51 +0,0 @@ -contract timeoutTest { - string public iarray1; - // cpu - function oneCpu() public { - require(1==1); - } - - function storage8Char() public { - iarray1 = "12345678"; - } - - function testUseCpu(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - } - return count; - } - - - uint256[] public iarray; - uint public calculatedFibNumber; - mapping(address=>mapping(address=>uint256)) public m; - - function testUseStorage(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - iarray.push(i); - } - return count; - } - - // stack - //uint n = 0; - uint yy = 0; - function test() public { - //n += 1; - yy += 1; - test(); - } - - function setFibonacci(uint n) public returns (uint256){ - calculatedFibNumber = fibonacci(n); - return calculatedFibNumber; - } - - function fibonacci(uint n) internal returns (uint) { - return fibonacci(n - 1) + fibonacci(n - 2); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractLinkage006.sol b/framework/src/test/resources/soliditycode_0.6.12/contractLinkage006.sol deleted file mode 100644 index 53449f61ce2..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractLinkage006.sol +++ /dev/null @@ -1,18 +0,0 @@ - -contract AA{ - uint256 public count=0; - constructor () payable public{} - function init(address payable addr, uint256 max) payable public { - count =0; - this.hack(addr,max); - } - function hack(address payable addr, uint256 max) payable public { - while (count < max) { - count = count +1; - this.hack(addr,max); - } - if (count == max) { - addr.send(20); - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractOriginEnergyLimit001.sol b/framework/src/test/resources/soliditycode_0.6.12/contractOriginEnergyLimit001.sol deleted file mode 100644 index 6feb7fff3b8..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractOriginEnergyLimit001.sol +++ /dev/null @@ -1,11 +0,0 @@ - - -contract findArgsContractTest{ - function findArgsByIndexTest(uint i) public returns (uint z) { - uint[] memory a = new uint[](3); - a[0]=1; - a[1]=2; - a[2]=3; - return a[i]; - } -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractOriginEnergyLimit004.sol b/framework/src/test/resources/soliditycode_0.6.12/contractOriginEnergyLimit004.sol deleted file mode 100644 index 6feb7fff3b8..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractOriginEnergyLimit004.sol +++ /dev/null @@ -1,11 +0,0 @@ - - -contract findArgsContractTest{ - function findArgsByIndexTest(uint i) public returns (uint z) { - uint[] memory a = new uint[](3); - a[0]=1; - a[1]=2; - a[2]=3; - return a[i]; - } -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractOtherToTrcToken.sol b/framework/src/test/resources/soliditycode_0.6.12/contractOtherToTrcToken.sol deleted file mode 100644 index 933358e128b..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractOtherToTrcToken.sol +++ /dev/null @@ -1,41 +0,0 @@ - - -contract ConvertType { - -constructor() payable public{} - -fallback() payable external{} - -//function stringToTrctoken(address payable toAddress, string memory tokenStr, uint256 tokenValue) public { -// trcToken t = trcToken(tokenStr); // ERROR -// toAddress.transferToken(tokenValue, tokenStr); // ERROR -//} - -function uint256ToTrctoken(address payable toAddress, uint256 tokenValue, uint256 tokenInt) public { - trcToken t = trcToken(tokenInt); // OK - toAddress.transferToken(tokenValue, t); // OK - toAddress.transferToken(tokenValue, tokenInt); // OK -} - -function addressToTrctoken(address payable toAddress, uint256 tokenValue, address adr) public { - trcToken t = trcToken(adr); // OK - toAddress.transferToken(tokenValue, t); // OK -//toAddress.transferToken(tokenValue, adr); // ERROR -} - -//function bytesToTrctoken(address payable toAddress, bytes memory b, uint256 tokenValue) public { - // trcToken t = trcToken(b); // ERROR - // toAddress.transferToken(tokenValue, b); // ERROR -//} - -function bytes32ToTrctoken(address payable toAddress, uint256 tokenValue, bytes32 b32) public { - trcToken t = trcToken(b32); // OK - toAddress.transferToken(tokenValue, t); // OK -// toAddress.transferToken(tokenValue, b32); // ERROR -} - -//function arrayToTrctoken(address payable toAddress, uint256[] memory arr, uint256 tokenValue) public { -//trcToken t = trcToken(arr); // ERROR -// toAddress.transferToken(tokenValue, arr); // ERROR -//} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractScenario001.sol b/framework/src/test/resources/soliditycode_0.6.12/contractScenario001.sol deleted file mode 100644 index 92778e42bc9..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractScenario001.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractScenario002.sol b/framework/src/test/resources/soliditycode_0.6.12/contractScenario002.sol deleted file mode 100644 index 5b990fe36e8..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractScenario002.sol +++ /dev/null @@ -1,53 +0,0 @@ - -contract TronNative{ - - address public voteContractAddress= address(0x10001); - address public freezeBalanceAddress = address(0x10002); - address public unFreezeBalanceAddress = address(0x10003); - address public withdrawBalanceAddress = address(0x10004); - address public approveProposalAddress = address(0x10005); - address public createProposalAddress = address(0x10006); - address public deleteProposalAddress = address(0x10007); - constructor () payable public {} - - function voteForSingleWitness (address payable witnessAddr, uint256 voteValue) public{ - // method 1: - voteContractAddress.delegatecall(abi.encode(witnessAddr,voteValue)); - } - - function voteUsingAssembly (address witnessAddr, uint256 voteValue) public{ - // method 2: - assembly{ - mstore(0x80,witnessAddr) - mstore(0xa0,voteValue) - // gas, address, in, size, out, size - if iszero(delegatecall(0, 0x10001, 0x80, 0x40, 0x80, 0x0)) { - revert(0, 0) - } - } - } - - function freezeBalance(uint256 frozen_Balance,uint256 frozen_Duration) public { - freezeBalanceAddress.delegatecall(abi.encode(frozen_Balance,frozen_Duration)); - } - - function unFreezeBalance() public { - unFreezeBalanceAddress.delegatecall(""); - } - - function withdrawBalance() public { - withdrawBalanceAddress.delegatecall(""); - } - - function approveProposal(uint256 id, bool isApprove) public { - approveProposalAddress.delegatecall(abi.encode(id,isApprove)); - } - - function createProposal(bytes32 [] memory data) public { - createProposalAddress.delegatecall(abi.encode(data)); - } - - function deleteProposal(uint256 id) public{ - deleteProposalAddress.delegatecall(abi.encode(id)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractScenario003.sol b/framework/src/test/resources/soliditycode_0.6.12/contractScenario003.sol deleted file mode 100644 index 92778e42bc9..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractScenario003.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractScenario004.sol b/framework/src/test/resources/soliditycode_0.6.12/contractScenario004.sol deleted file mode 100644 index f6919502914..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractScenario004.sol +++ /dev/null @@ -1,88 +0,0 @@ - - -contract TronToken { - - string public name = "Tronix"; // token name - string public symbol = "TRX"; // token symbol - uint256 public decimals = 6; // token digit - - mapping (address => uint256) public balanceOf; - mapping (address => mapping (address => uint256)) public allowance; - - uint256 public totalSupply = 0; - bool public stopped = false; - - uint256 constant valueFounder = 100000000000000000; - address owner = address(0x0); - - modifier isOwner { - assert(owner == msg.sender); - _; - } - - modifier isRunning { - assert (!stopped); - _; - } - - modifier validAddress { - assert(address(0x0) != msg.sender); - _; - } - - constructor(address _addressFounder) public { - owner = msg.sender; - totalSupply = valueFounder; - balanceOf[_addressFounder] = valueFounder; - emit Transfer(address(0x0), _addressFounder, valueFounder); - } - - function transfer(address _to, uint256 _value) isRunning validAddress public returns (bool success) { - require(balanceOf[msg.sender] >= _value); - require(balanceOf[_to] + _value >= balanceOf[_to]); - balanceOf[msg.sender] -= _value; - balanceOf[_to] += _value; - emit Transfer(msg.sender, _to, _value); - return true; - } - - function transferFrom(address _from, address _to, uint256 _value) isRunning validAddress public returns (bool success) { - require(balanceOf[_from] >= _value); - require(balanceOf[_to] + _value >= balanceOf[_to]); - require(allowance[_from][msg.sender] >= _value); - balanceOf[_to] += _value; - balanceOf[_from] -= _value; - allowance[_from][msg.sender] -= _value; - emit Transfer(_from, _to, _value); - return true; - } - - function approve(address _spender, uint256 _value) isRunning validAddress public returns (bool success) { - require(_value == 0 || allowance[msg.sender][_spender] == 0); - allowance[msg.sender][_spender] = _value; - emit Approval(msg.sender, _spender, _value); - return true; - } - - function stop() isOwner public { - stopped = true; - } - - function start() isOwner public { - stopped = false; - } - - function setName(string memory _name) isOwner public { - name = _name; - } - - function burn(uint256 _value) public { - require(balanceOf[msg.sender] >= _value); - balanceOf[msg.sender] -= _value; - balanceOf[address(0x0)] += _value; - emit Transfer(msg.sender, address(0x0), _value); - } - - event Transfer(address indexed _from, address indexed _to, uint256 _value); - event Approval(address indexed _owner, address indexed _spender, uint256 _value); -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractScenario005.sol b/framework/src/test/resources/soliditycode_0.6.12/contractScenario005.sol deleted file mode 100644 index c377af7da97..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractScenario005.sol +++ /dev/null @@ -1,103 +0,0 @@ - - -interface token { - function transfer(address receiver, uint amount) external; -} - -contract Crowdsale { - address payable public beneficiary = 0x1b228F5D9f934c7bb18Aaa86F90418932888E7b4; // 募资成功后的收款方 - uint public fundingGoal = 10000000; // 募资额度 - uint public amountRaised = 1000000; // 参与数量 - uint public deadline; // 募资截止期 - - uint public price; // token 与以太坊的汇率 , token卖多少钱 - token public tokenReward; // 要卖的token - - mapping(address => uint256) public balanceOf; - - bool fundingGoalReached = false; // 众筹是否达到目标 - bool crowdsaleClosed = false; // 众筹是否结束 - - /** - * 事件可以用来跟踪信息 - **/ - event GoalReached(address recipient, uint totalAmountRaised); - event FundTransfer(address backer, uint amount, bool isContribution); - - /** - * 构造函数, 设置相关属性 - */ - constructor( - address payable ifSuccessfulSendTo, - uint fundingGoalInEthers, - uint durationInMinutes, - uint finneyCostOfEachToken, - address addressOfTokenUsedAsReward) public{ - beneficiary = ifSuccessfulSendTo; - fundingGoal = fundingGoalInEthers * 1 sun; - deadline = now + durationInMinutes * 1 minutes; - price = finneyCostOfEachToken * 1 trx; - tokenReward = token(addressOfTokenUsedAsReward); // 传入已发布的 token 合约的地址来创建实例 - } - - /** - * 无函数名的Fallback函数, - * 在向合约转账时,这个函数会被调用 - */ - fallback() payable external{ - require(!crowdsaleClosed); - uint amount = msg.value; - balanceOf[msg.sender] += amount; - amountRaised += amount; - tokenReward.transfer(msg.sender, amount / price); - emit FundTransfer(msg.sender, amount, true); - } - - /** - * 定义函数修改器modifier(作用和Python的装饰器很相似) - * 用于在函数执行前检查某种前置条件(判断通过之后才会继续执行该方法) - * _ 表示继续执行之后的代码 - **/ - modifier afterDeadline() { if (now >= deadline) _; } - - /** - * 判断众筹是否完成融资目标, 这个方法使用了afterDeadline函数修改器 - * - */ - function checkGoalReached() afterDeadline public{ - if (amountRaised >= fundingGoal) { - fundingGoalReached = true; - emit GoalReached(beneficiary, amountRaised); - } - crowdsaleClosed = true; - } - - - /** - * 完成融资目标时,融资款发送到收款方 - * 未完成融资目标时,执行退款 - * - */ - function safeWithdrawal() afterDeadline public{ - if (!fundingGoalReached) { - uint amount = balanceOf[msg.sender]; - balanceOf[msg.sender] = 0; - if (amount > 0) { - if (msg.sender.send(amount)) { - emit FundTransfer(msg.sender, amount, false); - } else { - balanceOf[msg.sender] = amount; - } - } - } - - if (fundingGoalReached && beneficiary == msg.sender) { - if (payable(beneficiary).send(amountRaised)) { - emit FundTransfer(beneficiary, amountRaised, false); - } else { - //If we fail to send the funds to beneficiary, unlock funders balance - fundingGoalReached = false; - } - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractScenario006.sol b/framework/src/test/resources/soliditycode_0.6.12/contractScenario006.sol deleted file mode 100644 index 6d6feeb8188..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractScenario006.sol +++ /dev/null @@ -1,1963 +0,0 @@ - - -interface PlayerBookInterface { - function getPlayerID(address _addr) external returns (uint256); - function getPlayerName(uint256 _pID) external view returns (bytes32); - function getPlayerLAff(uint256 _pID) external view returns (uint256); - function getPlayerAddr(uint256 _pID) external view returns (address); - function getNameFee() external view returns (uint256); - function registerNameXIDFromDapp(address _addr, bytes32 _name, uint256 _affCode, bool _all) external payable returns(bool, uint256); - function registerNameXaddrFromDapp(address _addr, bytes32 _name, address _affCode, bool _all) external payable returns(bool, uint256); - function registerNameXnameFromDapp(address _addr, bytes32 _name, bytes32 _affCode, bool _all) external payable returns(bool, uint256); - function isDev(address _who) external view returns(bool); -} - - -/** -* @title -Name Filter- v0.1.9 -* ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ -* │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ -* ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ -* _____ _____ -* (, / /) /) /) (, / /) /) -* ┌─┐ / _ (/_ // // / _ // _ __ _(/ -* ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ -* ┴ ┴ / / .-/ _____ (__ / -* (__ / (_/ (, / /)™ -* / __ __ __ __ _ __ __ _ _/_ _ _(/ -* ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ -* ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 -* ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ -* _ __ _ ____ ____ _ _ _____ ____ ___ -*=============| |\ | / /\ | |\/| | |_ =====| |_ | | | | | | | |_ | |_)==============* -*=============|_| \| /_/--\ |_| | |_|__=====|_| |_| |_|__ |_| |_|__ |_| \==============* -* -* ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ -* ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ -* ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ -*/ - -library NameFilter { - /** - * @dev filters name strings - * -converts uppercase to lower case. - * -makes sure it does not start/end with a space - * -makes sure it does not contain multiple spaces in a row - * -cannot be only numbers - * -cannot start with 0x - * -restricts characters to A-Z, a-z, 0-9, and space. - * @return reprocessed string in bytes32 format - */ - function nameFilter(string memory _input) - internal - pure - returns(bytes32) - { - bytes memory _temp = bytes(_input); - uint256 _length = _temp.length; - - //sorry limited to 32 characters - require (_length <= 32 && _length > 0, "string must be between 1 and 32 characters"); - // make sure it doesnt start with or end with space - require(_temp[0] != 0x20 && _temp[_length-1] != 0x20, "string cannot start or end with space"); - // make sure first two characters are not 0x - if (_temp[0] == 0x30) - { - require(_temp[1] != 0x78, "string cannot start with 0x"); - require(_temp[1] != 0x58, "string cannot start with 0X"); - } - - // create a bool to track if we have a non number character - bool _hasNonNumber; - - // convert & check - for (uint256 i = 0; i < _length; i++) - { - // if its uppercase A-Z - if (_temp[i] > 0x40 && _temp[i] < 0x5b) - { - // convert to lower case a-z - _temp[i] = byte(uint8(_temp[i]) + 32); - - // we have a non number - if (_hasNonNumber == false) - _hasNonNumber = true; - } else { - require - ( - // require character is a space - _temp[i] == 0x20 || - // OR lowercase a-z - (_temp[i] > 0x60 && _temp[i] < 0x7b) || - // or 0-9 - (_temp[i] > 0x2f && _temp[i] < 0x3a), - "string contains invalid characters" - ); - // make sure theres not 2x spaces in a row - if (_temp[i] == 0x20) - require( _temp[i+1] != 0x20, "string cannot contain consecutive spaces"); - - // see if we have a character other than a number - if (_hasNonNumber == false && (_temp[i] < 0x30 || _temp[i] > 0x39)) - _hasNonNumber = true; - } - } - - require(_hasNonNumber == true, "string cannot be only numbers"); - - bytes32 _ret; - assembly { - _ret := mload(add(_temp, 32)) - } - return (_ret); - } -} - - -library SafeMath { - - /** - * @dev Multiplies two numbers, throws on overflow. - */ - function mul(uint256 a, uint256 b) - internal - pure - returns (uint256 c) - { - if (a == 0) { - return 0; - } - c = a * b; - require(c / a == b, "SafeMath mul failed"); - return c; - } - - /** - * @dev Integer division of two numbers, truncating the quotient. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // assert(b > 0); // Solidity automatically throws when dividing by 0 - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - return c; - } - - /** - * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 a, uint256 b) - internal - pure - returns (uint256) - { - require(b <= a, "SafeMath sub failed"); - return a - b; - } - - /** - * @dev Adds two numbers, throws on overflow. - */ - function add(uint256 a, uint256 b) - internal - pure - returns (uint256 c) - { - c = a + b; - require(c >= a, "SafeMath add failed"); - return c; - } - - /** - * @dev gives square root of given x. - */ - function sqrt(uint256 x) - internal - pure - returns (uint256 y) - { - uint256 z = ((add(x,1)) / 2); - y = x; - while (z < y) - { - y = z; - z = ((add((x / z),z)) / 2); - } - } - - /** - * @dev gives square. multiplies x by x - */ - function sq(uint256 x) - internal - pure - returns (uint256) - { - return (mul(x,x)); - } - - /** - * @dev x to the power of y - */ - function pwr(uint256 x, uint256 y) - internal - pure - returns (uint256) - { - if (x==0) - return (0); - else if (y==0) - return (1); - else - { - uint256 z = x; - for (uint256 i=1; i < y; i++) - z = mul(z,x); - return (z); - } - } -} - -//============================================================================== -// | _ _ _ | _ . -// |<(/_\/ (_(_||(_ . -//=======/====================================================================== -library F3DKeysCalcLong { - using SafeMath for *; - /** - * @dev calculates number of keys received given X eth - * @param _curEth current amount of eth in contract - * @param _newEth eth being spent - * @return amount of ticket purchased - */ - function keysRec(uint256 _curEth, uint256 _newEth) - internal - pure - returns (uint256) - { - return(keys((_curEth).add(_newEth)).sub(keys(_curEth))); - } - - /** - * @dev calculates amount of eth received if you sold X keys - * @param _curKeys current amount of keys that exist - * @param _sellKeys amount of keys you wish to sell - * @return amount of eth received - */ - function ethRec(uint256 _curKeys, uint256 _sellKeys) - internal - pure - returns (uint256) - { - return((eth(_curKeys)).sub(eth(_curKeys.sub(_sellKeys)))); - } - - /** - * @dev calculates how many keys would exist with given an amount of eth - * @param _eth eth "in contract" - * @return number of keys that would exist - */ - function keys(uint256 _eth) - internal - pure - returns(uint256) - { - return ((((((_eth).mul(1000000000000000000)).mul(312500000000000000000000000)).add(5624988281256103515625000000000000000000000000000000000000000000)).sqrt()).sub(74999921875000000000000000000000)) / (156250000); - } - - /** - * @dev calculates how much eth would be in contract given a number of keys - * @param _keys number of keys "in contract" - * @return eth that would exists - */ - function eth(uint256 _keys) - internal - pure - returns(uint256) - { - return ((78125000).mul(_keys.sq()).add(((149999843750000).mul(_keys.mul(1000000000000000000))) / (2))) / ((1000000000000000000).sq()); - } -} - -library F3Ddatasets { - //compressedData key - // [76-33][32][31][30][29][28-18][17][16-6][5-3][2][1][0] - // 0 - new player (bool) - // 1 - joined round (bool) - // 2 - new leader (bool) - // 3-5 - air drop tracker (uint 0-999) - // 6-16 - round end time - // 17 - winnerTeam - // 18 - 28 timestamp - // 29 - team - // 30 - 0 = reinvest (round), 1 = buy (round), 2 = buy (ico), 3 = reinvest (ico) - // 31 - airdrop happened bool - // 32 - airdrop tier - // 33 - airdrop amount won - //compressedIDs key - // [77-52][51-26][25-0] - // 0-25 - pID - // 26-51 - winPID - // 52-77 - rID - struct EventReturns { - uint256 compressedData; - uint256 compressedIDs; - address winnerAddr; // winner address - bytes32 winnerName; // winner name - uint256 amountWon; // amount won - uint256 newPot; // amount in new pot - uint256 P3DAmount; // amount distributed to p3d - uint256 genAmount; // amount distributed to gen - uint256 potAmount; // amount added to pot - } - struct Player { - address payable addr; // player address - bytes32 name; // player name - uint256 win; // winnings vault - uint256 gen; // general vault - uint256 aff; // affiliate vault - uint256 lrnd; // last round played - uint256 laff; // last affiliate id used - } - struct PlayerRounds { - uint256 eth; // eth player has added to round (used for eth limiter) - uint256 keys; // keys - uint256 mask; // player mask - uint256 ico; // ICO phase investment - } - struct Round { - uint256 plyr; // pID of player in lead - uint256 team; // tID of team in lead - uint256 end; // time ends/ended - bool ended; // has round end function been ran - uint256 strt; // time round started - uint256 keys; // keys - uint256 eth; // total eth in - uint256 pot; // eth to pot (during round) / final amount paid to winner (after round ends) - uint256 mask; // global mask - uint256 ico; // total eth sent in during ICO phase - uint256 icoGen; // total eth for gen during ICO phase - uint256 icoAvg; // average key price for ICO phase - } - struct TeamFee { - uint256 gen; // % of buy in thats paid to key holders of current round - uint256 p3d; // % of buy in thats paid to p3d holders - } - struct PotSplit { - uint256 gen; // % of pot thats paid to key holders of current round - uint256 p3d; // % of pot thats paid to p3d holders - } -} - -contract F3Devents { - // fired whenever a player registers a name - event onNewName - ( - uint256 indexed playerID, - address indexed playerAddress, - bytes32 indexed playerName, - bool isNewPlayer, - uint256 affiliateID, - address affiliateAddress, - bytes32 affiliateName, - uint256 amountPaid, - uint256 timeStamp - ); - - // fired at end of buy or reload - event onEndTx - ( - uint256 compressedData, - uint256 compressedIDs, - bytes32 playerName, - address playerAddress, - uint256 ethIn, - uint256 keysBought, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount, - uint256 potAmount, - uint256 airDropPot - ); - - // fired whenever theres a withdraw - event onWithdraw - ( - uint256 indexed playerID, - address playerAddress, - bytes32 playerName, - uint256 ethOut, - uint256 timeStamp - ); - - // fired whenever a withdraw forces end round to be ran - event onWithdrawAndDistribute - ( - address playerAddress, - bytes32 playerName, - uint256 ethOut, - uint256 compressedData, - uint256 compressedIDs, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount - ); - - // (fomo3d long only) fired whenever a player tries a buy after round timer - // hit zero, and causes end round to be ran. - event onBuyAndDistribute - ( - address playerAddress, - bytes32 playerName, - uint256 ethIn, - uint256 compressedData, - uint256 compressedIDs, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount - ); - - // (fomo3d long only) fired whenever a player tries a reload after round timer - // hit zero, and causes end round to be ran. - event onReLoadAndDistribute - ( - address playerAddress, - bytes32 playerName, - uint256 compressedData, - uint256 compressedIDs, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount - ); - - // fired whenever an affiliate is paid - event onAffiliatePayout - ( - uint256 indexed affiliateID, - address affiliateAddress, - bytes32 affiliateName, - uint256 indexed roundID, - uint256 indexed buyerID, - uint256 amount, - uint256 timeStamp - ); - - // received pot swap deposit - event onPotSwapDeposit - ( - uint256 roundID, - uint256 amountAddedToPot - ); -} - - - -contract FoMo3Dlong is F3Devents { - using SafeMath for *; - using NameFilter for string; - using F3DKeysCalcLong for uint256; - - address public otherF3D_; - address public Divies; - address public Jekyll_Island_Inc; - PlayerBookInterface public playerBook;// =PlayerBookInterface(0x0dcd2f752394c41875e259e00bb44fd505297caf);//new PlayerBook();// - // TeamJustInterface constant private teamJust = TeamJustInterface(0x3a5f8140b9213a0f733a6a639857c9df43ee3f5a);// new TeamJust();// - - //============================================================================== - // _ _ _ |`. _ _ _ |_ | _ _ . - // (_(_)| |~|~|(_||_|| (_||_)|(/__\ . (game settings) - //=================_|=========================================================== - string constant public name = "FoMo3D Long Official"; - string constant public symbol = "F3D"; - uint256 private rndExtra_ = 30;//extSettings.getLongExtra(); // length of the very first ICO - uint256 private rndGap_ = 30; //extSettings.getLongGap(); // length of ICO phase, set to 1 year for EOS. - uint256 constant private rndInit_ = 1 hours; // round timer starts at this - uint256 constant private rndInc_ = 30 seconds; // every full key purchased adds this much to the timer - uint256 constant private rndMax_ = 24 hours; // max length a round timer can be - //============================================================================== - // _| _ _|_ _ _ _ _|_ _ . - // (_|(_| | (_| _\(/_ | |_||_) . (data used to store game info that changes) - //=============================|================================================ - uint256 public airDropPot_; // person who gets the airdrop wins part of this pot - uint256 public airDropTracker_ = 0; // incremented each time a "qualified" tx occurs. used to determine winning air drop - uint256 public rID_; // round id number / total rounds that have happened - //**************** - // PLAYER DATA - //**************** - mapping(address => uint256) public pIDxAddr_; // (addr => pID) returns player id by address - mapping(bytes32 => uint256) public pIDxName_; // (name => pID) returns player id by name - mapping(uint256 => F3Ddatasets.Player) public plyr_; // (pID => data) player data - mapping(uint256 => mapping(uint256 => F3Ddatasets.PlayerRounds)) public plyrRnds_; // (pID => rID => data) player round data by player id & round id - mapping(uint256 => mapping(bytes32 => bool)) public plyrNames_; // (pID => name => bool) list of names a player owns. (used so you can change your display name amongst any name you own) - //**************** - // ROUND DATA - //**************** - mapping(uint256 => F3Ddatasets.Round) public round_; // (rID => data) round data - mapping(uint256 => mapping(uint256 => uint256)) public rndTmEth_; // (rID => tID => data) eth in per team, by round id and team id - //**************** - // TEAM FEE DATA - //**************** - mapping(uint256 => F3Ddatasets.TeamFee) public fees_; // (team => fees) fee distribution by team - mapping(uint256 => F3Ddatasets.PotSplit) public potSplit_; // (team => fees) pot split distribution by team - - function setPlayerBook(address _playerBook) external { - require(msg.sender == owner, 'only dev!'); - require(address(playerBook) == address(0), 'already set!'); - playerBook = PlayerBookInterface(_playerBook); - } - - address public owner; - - //============================================================================== - // _ _ _ __|_ _ __|_ _ _ . - // (_(_)| |_\ | | |_|(_ | (_)| . (initial data setup upon contract deploy) - //============================================================================== - constructor() - public - { - owner = msg.sender; - // Team allocation structures - // 0 = whales - // 1 = bears - // 2 = sneks - // 3 = bulls - - // Team allocation percentages - // (F3D, P3D) + (Pot , Referrals, Community) - // Referrals / Community rewards are mathematically designed to come from the winner's share of the pot. - fees_[0] = F3Ddatasets.TeamFee(30, 6); - //50% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - fees_[1] = F3Ddatasets.TeamFee(43, 0); - //43% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - fees_[2] = F3Ddatasets.TeamFee(56, 10); - //20% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - fees_[3] = F3Ddatasets.TeamFee(43, 8); - //35% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - - // how to split up the final pot based on which team was picked - // (F3D, P3D) - potSplit_[0] = F3Ddatasets.PotSplit(15, 10); - //48% to winner, 25% to next round, 2% to com - potSplit_[1] = F3Ddatasets.PotSplit(25, 0); - //48% to winner, 25% to next round, 2% to com - potSplit_[2] = F3Ddatasets.PotSplit(20, 20); - //48% to winner, 10% to next round, 2% to com - potSplit_[3] = F3Ddatasets.PotSplit(30, 10); - //48% to winner, 10% to next round, 2% to com - } - //============================================================================== - // _ _ _ _|. |`. _ _ _ . - // | | |(_)(_||~|~|(/_| _\ . (these are safety checks) - //============================================================================== - /** - * @dev used to make sure no one can interact with contract until it has - * been activated. - */ - modifier isActivated() { - require(activated_ == true, "its not ready yet. check ?eta in discord"); - _; - } - - /** - * @dev prevents contracts from interacting with fomo3d - */ - modifier isHuman() { - address _addr = msg.sender; - uint256 _codeLength; - - assembly {_codeLength := extcodesize(_addr)} - require(_codeLength == 0, "sorry humans only"); - _; - } - - modifier onlyDevs() - { - require(playerBook.isDev(msg.sender) == true, "msg sender is not a dev"); - _; - } - - /** - * @dev sets boundaries for incoming tx - */ - modifier isWithinLimits(uint256 _eth) { - require(_eth >= 1000000000, "pocket lint: not a valid currency"); - require(_eth <= 100000000000000000000000, "no vitalik, no"); - _; - } - - //============================================================================== - // _ |_ |. _ |` _ __|_. _ _ _ . - // |_)|_||_)||(_ ~|~|_|| |(_ | |(_)| |_\ . (use these to interact with contract) - //====|========================================================================= - /** - * @dev emergency buy uses last stored affiliate ID and team snek - */ - fallback() - isActivated() - isHuman() - isWithinLimits(msg.value) - external - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_ ; - _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // buy core - buyCore(_pID, plyr_[_pID].laff, 2, _eventData_); - } - - /** - * @dev converts all incoming ethereum to keys. - * -functionhash- 0x8f38f309 (using ID for affiliate) - * -functionhash- 0x98a0871d (using address for affiliate) - * -functionhash- 0xa65b37a1 (using name for affiliate) - * @param _affCode the ID/address/name of the player who gets the affiliate fee - * @param _team what team is the player playing for? - */ - function buyXid(uint256 _affCode, uint256 _team) - isActivated() - isHuman() - isWithinLimits(msg.value) - public - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_; - _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == 0 || _affCode == _pID) - { - // use last stored affiliate code - _affCode = plyr_[_pID].laff; - - // if affiliate code was given & its not the same as previously stored - } else if (_affCode != plyr_[_pID].laff) { - // update last affiliate - plyr_[_pID].laff = _affCode; - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // buy core - buyCore(_pID, _affCode, _team, _eventData_); - } - - function buyXaddr(address _affCode, uint256 _team) - isActivated() - isHuman() - isWithinLimits(msg.value) - public - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_; - _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == address(0) || _affCode == msg.sender) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxAddr_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // buy core - buyCore(_pID, _affID, _team, _eventData_); - } - - function buyXname(bytes32 _affCode, uint256 _team) - isActivated() - isHuman() - isWithinLimits(msg.value) - public - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_ ; - _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == '' || _affCode == plyr_[_pID].name) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxName_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // buy core - buyCore(_pID, _affID, _team, _eventData_); - } - - /** - * @dev essentially the same as buy, but instead of you sending ether - * from your wallet, it uses your unwithdrawn earnings. - * -functionhash- 0x349cdcac (using ID for affiliate) - * -functionhash- 0x82bfc739 (using address for affiliate) - * -functionhash- 0x079ce327 (using name for affiliate) - * @param _affCode the ID/address/name of the player who gets the affiliate fee - * @param _team what team is the player playing for? - * @param _eth amount of earnings to use (remainder returned to gen vault) - */ - function reLoadXid(uint256 _affCode, uint256 _team, uint256 _eth) - isActivated() - isHuman() - isWithinLimits(_eth) - public - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == 0 || _affCode == _pID) - { - // use last stored affiliate code - _affCode = plyr_[_pID].laff; - - // if affiliate code was given & its not the same as previously stored - } else if (_affCode != plyr_[_pID].laff) { - // update last affiliate - plyr_[_pID].laff = _affCode; - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // reload core - reLoadCore(_pID, _affCode, _team, _eth, _eventData_); - } - - function reLoadXaddr(address _affCode, uint256 _team, uint256 _eth) - isActivated() - isHuman() - isWithinLimits(_eth) - public - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == address(0) || _affCode == msg.sender) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxAddr_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // reload core - reLoadCore(_pID, _affID, _team, _eth, _eventData_); - } - - function reLoadXname(bytes32 _affCode, uint256 _team, uint256 _eth) - isActivated() - isHuman() - isWithinLimits(_eth) - public - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == '' || _affCode == plyr_[_pID].name) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxName_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // reload core - reLoadCore(_pID, _affID, _team, _eth, _eventData_); - } - - /** - * @dev withdraws all of your earnings. - * -functionhash- 0x3ccfd60b - */ - function withdraw() - isActivated() - isHuman() - public - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = now; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // setup temp var for player eth - uint256 _eth; - - // check to see if round has ended and no one has run round end yet - if (_now > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // end the round (distributes pot) - round_[_rID].ended = true; - _eventData_ = endRound(_eventData_); - - // get their earnings - _eth = withdrawEarnings(_pID); - - // gib moni - if (_eth > 0) - plyr_[_pID].addr.transfer(_eth); - - // build event data - _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; - - // fire withdraw and distribute event - emit F3Devents.onWithdrawAndDistribute - ( - msg.sender, - plyr_[_pID].name, - _eth, - _eventData_.compressedData, - _eventData_.compressedIDs, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount - ); - - // in any other situation - } else { - // get their earnings - _eth = withdrawEarnings(_pID); - - // gib moni - if (_eth > 0) - plyr_[_pID].addr.transfer(_eth); - - // fire withdraw event - emit F3Devents.onWithdraw(_pID, msg.sender, plyr_[_pID].name, _eth, _now); - } - } - - /** - * @dev use these to register names. they are just wrappers that will send the - * registration requests to the PlayerBook contract. So registering here is the - * same as registering there. UI will always display the last name you registered. - * but you will still own all previously registered names to use as affiliate - * links. - * - must pay a registration fee. - * - name must be unique - * - names will be converted to lowercase - * - name cannot start or end with a space - * - cannot have more than 1 space in a row - * - cannot be only numbers - * - cannot start with 0x - * - name must be at least 1 char - * - max length of 32 characters long - * - allowed characters: a-z, 0-9, and space - * -functionhash- 0x921dec21 (using ID for affiliate) - * -functionhash- 0x3ddd4698 (using address for affiliate) - * -functionhash- 0x685ffd83 (using name for affiliate) - * @param _nameString players desired name - * @param _affCode affiliate ID, address, or name of who referred you - * @param _all set to true if you want this to push your info to all games - * (this might cost a lot of gas) - */ - function registerNameXID(string memory _nameString, uint256 _affCode, bool _all) - isHuman() - public - payable - { - bytes32 _name = _nameString.nameFilter(); - address _addr = msg.sender; - uint256 _paid = msg.value; - (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXIDFromDapp.value(_paid)(_addr, _name, _affCode, _all); - - uint256 _pID = pIDxAddr_[_addr]; - - // fire event - emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); - } - - function registerNameXaddr(string memory _nameString, address _affCode, bool _all) - isHuman() - public - payable - { - bytes32 _name = _nameString.nameFilter(); - address _addr = msg.sender; - uint256 _paid = msg.value; - (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXaddrFromDapp.value(msg.value)(msg.sender, _name, _affCode, _all); - - uint256 _pID = pIDxAddr_[_addr]; - - // fire event - emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); - } - - function registerNameXname(string memory _nameString, bytes32 _affCode, bool _all) - isHuman() - public - payable - { - bytes32 _name = _nameString.nameFilter(); - address _addr = msg.sender; - uint256 _paid = msg.value; - (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXnameFromDapp.value(msg.value)(msg.sender, _name, _affCode, _all); - - uint256 _pID = pIDxAddr_[_addr]; - - // fire event - emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); - } - //============================================================================== - // _ _ _|__|_ _ _ _ . - // (_|(/_ | | (/_| _\ . (for UI & viewing things on etherscan) - //=====_|======================================================================= - /** - * @dev return the price buyer will pay for next 1 individual key. - * -functionhash- 0x018a25e8 - * @return price for next key bought (in wei format) - */ - function getBuyPrice() - public - view - returns (uint256) - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = now; - - // are we in a round? - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - return ((round_[_rID].keys.add(1000000000000000000)).ethRec(1000000000000000000)); - else // rounds over. need price for new round - return (75000000000000); - // init - } - - /** - * @dev returns time left. dont spam this, you'll ddos yourself from your node - * provider - * -functionhash- 0xc7e284b8 - * @return time left in seconds - */ - function getTimeLeft() - public - view - returns (uint256) - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = now; - - if (_now < round_[_rID].end) - if (_now > round_[_rID].strt + rndGap_) - return ((round_[_rID].end).sub(_now)); - else - return ((round_[_rID].strt + rndGap_).sub(_now)); - else - return (0); - } - - /** - * @dev returns player earnings per vaults - * -functionhash- 0x63066434 - * @return winnings vault - * @return general vault - * @return affiliate vault - */ - function getPlayerVaults(uint256 _pID) - public - view - returns (uint256, uint256, uint256) - { - // setup local rID - uint256 _rID = rID_; - - // if round has ended. but round end has not been run (so contract has not distributed winnings) - if (now > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) - { - // if player is winner - if (round_[_rID].plyr == _pID) - { - return - ( - (plyr_[_pID].win).add(((round_[_rID].pot).mul(48)) / 100), - (plyr_[_pID].gen).add(getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask)), - plyr_[_pID].aff - ); - // if player is not the winner - } else { - return - ( - plyr_[_pID].win, - (plyr_[_pID].gen).add(getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask)), - plyr_[_pID].aff - ); - } - - // if round is still going on, or round has ended and round end has been ran - } else { - return - ( - plyr_[_pID].win, - (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), - plyr_[_pID].aff - ); - } - } - - /** - * solidity hates stack limits. this lets us avoid that hate - */ - function getPlayerVaultsHelper(uint256 _pID, uint256 _rID) - private - view - returns (uint256) - { - return (((((round_[_rID].mask).add(((((round_[_rID].pot).mul(potSplit_[round_[_rID].team].gen)) / 100).mul(1000000000000000000)) / (round_[_rID].keys))).mul(plyrRnds_[_pID][_rID].keys)) / 1000000000000000000)); - } - - /** - * @dev returns all current round info needed for front end - * -functionhash- 0x747dff42 - * @return eth invested during ICO phase - * @return round id - * @return total keys for round - * @return time round ends - * @return time round started - * @return current pot - * @return current team ID & player ID in lead - * @return current player in leads address - * @return current player in leads name - * @return whales eth in for round - * @return bears eth in for round - * @return sneks eth in for round - * @return bulls eth in for round - * @return airdrop tracker # & airdrop pot - */ - function getCurrentRoundInfo() - public - view - returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256, address, bytes32, uint256, uint256, uint256, uint256, uint256) - { - // setup local rID - uint256 _rID = rID_; - - return - ( - round_[_rID].ico, //0 - _rID, //1 - round_[_rID].keys, //2 - round_[_rID].end, //3 - round_[_rID].strt, //4 - round_[_rID].pot, //5 - (round_[_rID].team + (round_[_rID].plyr * 10)), //6 - plyr_[round_[_rID].plyr].addr, //7 - plyr_[round_[_rID].plyr].name, //8 - rndTmEth_[_rID][0], //9 - rndTmEth_[_rID][1], //10 - rndTmEth_[_rID][2], //11 - rndTmEth_[_rID][3], //12 - airDropTracker_ + (airDropPot_ * 1000) //13 - ); - } - - /** - * @dev returns player info based on address. if no address is given, it will - * use msg.sender - * -functionhash- 0xee0b5d8b - * @param _addr address of the player you want to lookup - * @return player ID - * @return player name - * @return keys owned (current round) - * @return winnings vault - * @return general vault - * @return affiliate vault - * @return player round eth - */ - function getPlayerInfoByAddress(address _addr) - public - view - returns (uint256, bytes32, uint256, uint256, uint256, uint256, uint256) - { - // setup local rID - uint256 _rID = rID_; - - if (_addr == address(0)) - { - _addr == msg.sender; - } - uint256 _pID = pIDxAddr_[_addr]; - - return - ( - _pID, //0 - plyr_[_pID].name, //1 - plyrRnds_[_pID][_rID].keys, //2 - plyr_[_pID].win, //3 - (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), //4 - plyr_[_pID].aff, //5 - plyrRnds_[_pID][_rID].eth //6 - ); - } - - //============================================================================== - // _ _ _ _ | _ _ . _ . - // (_(_)| (/_ |(_)(_||(_ . (this + tools + calcs + modules = our softwares engine) - //=====================_|======================================================= - /** - * @dev logic runs whenever a buy order is executed. determines how to handle - * incoming eth depending on if we are in an active round or not - */ - function buyCore(uint256 _pID, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) - private - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = now; - - // if round is active - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - { - // call core - core(_rID, _pID, msg.value, _affID, _team, _eventData_); - - // if round is not active - } else { - // check to see if end round needs to be ran - if (_now > round_[_rID].end && round_[_rID].ended == false) - { - // end the round (distributes pot) & start new round - round_[_rID].ended = true; - _eventData_ = endRound(_eventData_); - - // build event data - _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; - - // fire buy and distribute event - emit F3Devents.onBuyAndDistribute - ( - msg.sender, - plyr_[_pID].name, - msg.value, - _eventData_.compressedData, - _eventData_.compressedIDs, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount - ); - } - - // put eth in players vault - plyr_[_pID].gen = plyr_[_pID].gen.add(msg.value); - } - } - - /** - * @dev logic runs whenever a reload order is executed. determines how to handle - * incoming eth depending on if we are in an active round or not - */ - function reLoadCore(uint256 _pID, uint256 _affID, uint256 _team, uint256 _eth, F3Ddatasets.EventReturns memory _eventData_) - private - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = now; - - // if round is active - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - { - // get earnings from all vaults and return unused to gen vault - // because we use a custom safemath library. this will throw if player - // tried to spend more eth than they have. - plyr_[_pID].gen = withdrawEarnings(_pID).sub(_eth); - - // call core - core(_rID, _pID, _eth, _affID, _team, _eventData_); - - // if round is not active and end round needs to be ran - } else if (_now > round_[_rID].end && round_[_rID].ended == false) { - // end the round (distributes pot) & start new round - round_[_rID].ended = true; - _eventData_ = endRound(_eventData_); - - // build event data - _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; - - // fire buy and distribute event - emit F3Devents.onReLoadAndDistribute - ( - msg.sender, - plyr_[_pID].name, - _eventData_.compressedData, - _eventData_.compressedIDs, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount - ); - } - } - - /** - * @dev this is the core logic for any buy/reload that happens while a round - * is live. - */ - function core(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) - private - { - // if player is new to round - if (plyrRnds_[_pID][_rID].keys == 0) - _eventData_ = managePlayer(_pID, _eventData_); - - // early round eth limiter - if (round_[_rID].eth < 100000000000000000000 && plyrRnds_[_pID][_rID].eth.add(_eth) > 1000000000000000000) - { - uint256 _availableLimit = (1000000000000000000).sub(plyrRnds_[_pID][_rID].eth); - uint256 _refund = _eth.sub(_availableLimit); - plyr_[_pID].gen = plyr_[_pID].gen.add(_refund); - _eth = _availableLimit; - } - - // if eth left is greater than min eth allowed (sorry no pocket lint) - if (_eth > 1000000000) - { - - // mint the new keys - uint256 _keys = (round_[_rID].eth).keysRec(_eth); - - // if they bought at least 1 whole key - if (_keys >= 1000000000000000000) - { - updateTimer(_keys, _rID); - - // set new leaders - if (round_[_rID].plyr != _pID) - round_[_rID].plyr = _pID; - if (round_[_rID].team != _team) - round_[_rID].team = _team; - - // set the new leader bool to true - _eventData_.compressedData = _eventData_.compressedData + 100; - } - - // manage airdrops - if (_eth >= 100000000000000000) - { - airDropTracker_++; - if (airdrop() == true) - { - // gib muni - uint256 _prize; - if (_eth >= 10000000000000000000) - { - // calculate prize and give it to winner - _prize = ((airDropPot_).mul(75)) / 100; - plyr_[_pID].win = (plyr_[_pID].win).add(_prize); - - // adjust airDropPot - airDropPot_ = (airDropPot_).sub(_prize); - - // let event know a tier 3 prize was won - _eventData_.compressedData += 300000000000000000000000000000000; - } else if (_eth >= 1000000000000000000 && _eth < 10000000000000000000) { - // calculate prize and give it to winner - _prize = ((airDropPot_).mul(50)) / 100; - plyr_[_pID].win = (plyr_[_pID].win).add(_prize); - - // adjust airDropPot - airDropPot_ = (airDropPot_).sub(_prize); - - // let event know a tier 2 prize was won - _eventData_.compressedData += 200000000000000000000000000000000; - } else if (_eth >= 100000000000000000 && _eth < 1000000000000000000) { - // calculate prize and give it to winner - _prize = ((airDropPot_).mul(25)) / 100; - plyr_[_pID].win = (plyr_[_pID].win).add(_prize); - - // adjust airDropPot - airDropPot_ = (airDropPot_).sub(_prize); - - // let event know a tier 3 prize was won - _eventData_.compressedData += 300000000000000000000000000000000; - } - // set airdrop happened bool to true - _eventData_.compressedData += 10000000000000000000000000000000; - // let event know how much was won - _eventData_.compressedData += _prize * 1000000000000000000000000000000000; - - // reset air drop tracker - airDropTracker_ = 0; - } - } - - // store the air drop tracker number (number of buys since last airdrop) - _eventData_.compressedData = _eventData_.compressedData + (airDropTracker_ * 1000); - - // update player - plyrRnds_[_pID][_rID].keys = _keys.add(plyrRnds_[_pID][_rID].keys); - plyrRnds_[_pID][_rID].eth = _eth.add(plyrRnds_[_pID][_rID].eth); - - // update round - round_[_rID].keys = _keys.add(round_[_rID].keys); - round_[_rID].eth = _eth.add(round_[_rID].eth); - rndTmEth_[_rID][_team] = _eth.add(rndTmEth_[_rID][_team]); - - // distribute eth - _eventData_ = distributeExternal(_rID, _pID, _eth, _affID, _team, _eventData_); - _eventData_ = distributeInternal(_rID, _pID, _eth, _team, _keys, _eventData_); - - // call end tx function to fire end tx event. - endTx(_pID, _team, _eth, _keys, _eventData_); - } - } - //============================================================================== - // _ _ | _ | _ _|_ _ _ _ . - // (_(_||(_|_||(_| | (_)| _\ . - //============================================================================== - /** - * @dev calculates unmasked earnings (just calculates, does not update mask) - * @return earnings in wei format - */ - function calcUnMaskedEarnings(uint256 _pID, uint256 _rIDlast) - private - view - returns (uint256) - { - return ((((round_[_rIDlast].mask).mul(plyrRnds_[_pID][_rIDlast].keys)) / (1000000000000000000)).sub(plyrRnds_[_pID][_rIDlast].mask)); - } - - /** - * @dev returns the amount of keys you would get given an amount of eth. - * -functionhash- 0xce89c80c - * @param _rID round ID you want price for - * @param _eth amount of eth sent in - * @return keys received - */ - function calcKeysReceived(uint256 _rID, uint256 _eth) - public - view - returns (uint256) - { - // grab time - uint256 _now = now; - - // are we in a round? - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - return ((round_[_rID].eth).keysRec(_eth)); - else // rounds over. need keys for new round - return ((_eth).keys()); - } - - /** - * @dev returns current eth price for X keys. - * -functionhash- 0xcf808000 - * @param _keys number of keys desired (in 18 decimal format) - * @return amount of eth needed to send - */ - function iWantXKeys(uint256 _keys) - public - view - returns (uint256) - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = now; - - // are we in a round? - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - return ((round_[_rID].keys.add(_keys)).ethRec(_keys)); - else // rounds over. need price for new round - return ((_keys).eth()); - } - //============================================================================== - // _|_ _ _ | _ . - // | (_)(_)|_\ . - //============================================================================== - /** - * @dev receives name/player info from names contract - */ - function receivePlayerInfo(uint256 _pID, address payable _addr, bytes32 _name, uint256 _laff) - external - { - require(msg.sender == address(playerBook), "your not playerNames contract... hmmm.."); - if (pIDxAddr_[_addr] != _pID) - pIDxAddr_[_addr] = _pID; - if (pIDxName_[_name] != _pID) - pIDxName_[_name] = _pID; - if (plyr_[_pID].addr != _addr) - plyr_[_pID].addr = _addr; - if (plyr_[_pID].name != _name) - plyr_[_pID].name = _name; - if (plyr_[_pID].laff != _laff) - plyr_[_pID].laff = _laff; - if (plyrNames_[_pID][_name] == false) - plyrNames_[_pID][_name] = true; - } - - /** - * @dev receives entire player name list - */ - function receivePlayerNameList(uint256 _pID, bytes32 _name) - external - { - require(msg.sender == address(playerBook), "your not playerNames contract... hmmm.."); - if (plyrNames_[_pID][_name] == false) - plyrNames_[_pID][_name] = true; - } - - /** - * @dev gets existing or registers new pID. use this when a player may be new - * @return pID - */ - function determinePID(F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - uint256 _pID = pIDxAddr_[msg.sender]; - // if player is new to this version of fomo3d - if (_pID == 0) - { - // grab their player ID, name and last aff ID, from player names contract - _pID = playerBook.getPlayerID(msg.sender); - bytes32 _name = playerBook.getPlayerName(_pID); - uint256 _laff = playerBook.getPlayerLAff(_pID); - - // set up player account - pIDxAddr_[msg.sender] = _pID; - plyr_[_pID].addr = msg.sender; - - if (_name != "") - { - pIDxName_[_name] = _pID; - plyr_[_pID].name = _name; - plyrNames_[_pID][_name] = true; - } - - if (_laff != 0 && _laff != _pID) - plyr_[_pID].laff = _laff; - - // set the new player bool to true - _eventData_.compressedData = _eventData_.compressedData + 1; - } - return (_eventData_); - } - - /** - * @dev checks to make sure user picked a valid team. if not sets team - * to default (sneks) - */ - function verifyTeam(uint256 _team) - private - pure - returns (uint256) - { - if (_team < 0 || _team > 3) - return (2); - else - return (_team); - } - - /** - * @dev decides if round end needs to be run & new round started. and if - * player unmasked earnings from previously played rounds need to be moved. - */ - function managePlayer(uint256 _pID, F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - // if player has played a previous round, move their unmasked earnings - // from that round to gen vault. - if (plyr_[_pID].lrnd != 0) - updateGenVault(_pID, plyr_[_pID].lrnd); - - // update player's last round played - plyr_[_pID].lrnd = rID_; - - // set the joined round bool to true - _eventData_.compressedData = _eventData_.compressedData + 10; - - return (_eventData_); - } - - /** - * @dev ends the round. manages paying out winner/splitting up pot - */ - function endRound(F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - // setup local rID - uint256 _rID = rID_; - - // grab our winning player and team id's - uint256 _winPID = round_[_rID].plyr; - uint256 _winTID = round_[_rID].team; - - // grab our pot amount - uint256 _pot = round_[_rID].pot; - - // calculate our winner share, community rewards, gen share, - // p3d share, and amount reserved for next pot - uint256 _win = (_pot.mul(48)) / 100; - uint256 _com = (_pot / 50); - uint256 _gen = (_pot.mul(potSplit_[_winTID].gen)) / 100; - uint256 _p3d = (_pot.mul(potSplit_[_winTID].p3d)) / 100; - uint256 _res = (((_pot.sub(_win)).sub(_com)).sub(_gen)).sub(_p3d); - - // calculate ppt for round mask - uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); - uint256 _dust = _gen.sub((_ppt.mul(round_[_rID].keys)) / 1000000000000000000); - if (_dust > 0) - { - _gen = _gen.sub(_dust); - _res = _res.add(_dust); - } - - // pay our winner - plyr_[_winPID].win = _win.add(plyr_[_winPID].win); - - // community rewards - address payable add = address(uint160(Jekyll_Island_Inc)); - if (!add.send(_com)) - { - // This ensures Team Just cannot influence the outcome of FoMo3D with - // bank migrations by breaking outgoing transactions. - // Something we would never do. But that's not the point. - // We spent 2000$ in eth re-deploying just to patch this, we hold the - // highest belief that everything we create should be trustless. - // Team JUST, The name you shouldn't have to trust. - _p3d = _p3d.add(_com); - _com = 0; - } - - // distribute gen portion to key holders - round_[_rID].mask = _ppt.add(round_[_rID].mask); - - // send share for p3d to divies - if (_p3d > 0){ - address payable addr = address(uint160(Divies)); - addr.transfer(_p3d); - } - // prepare event data - _eventData_.compressedData = _eventData_.compressedData + (round_[_rID].end * 1000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + (_winPID * 100000000000000000000000000) + (_winTID * 100000000000000000); - _eventData_.winnerAddr = plyr_[_winPID].addr; - _eventData_.winnerName = plyr_[_winPID].name; - _eventData_.amountWon = _win; - _eventData_.genAmount = _gen; - _eventData_.P3DAmount = _p3d; - _eventData_.newPot = _res; - - // start next round - rID_++; - _rID++; - round_[_rID].strt = now; - round_[_rID].end = now.add(rndInit_).add(rndGap_); - round_[_rID].pot = _res; - - return (_eventData_); - } - - /** - * @dev moves any unmasked earnings to gen vault. updates earnings mask - */ - function updateGenVault(uint256 _pID, uint256 _rIDlast) - private - { - uint256 _earnings = calcUnMaskedEarnings(_pID, _rIDlast); - if (_earnings > 0) - { - // put in gen vault - plyr_[_pID].gen = _earnings.add(plyr_[_pID].gen); - // zero out their earnings by updating mask - plyrRnds_[_pID][_rIDlast].mask = _earnings.add(plyrRnds_[_pID][_rIDlast].mask); - } - } - - /** - * @dev updates round timer based on number of whole keys bought. - */ - function updateTimer(uint256 _keys, uint256 _rID) - private - { - // grab time - uint256 _now = now; - - // calculate time based on number of keys bought - uint256 _newTime; - if (_now > round_[_rID].end && round_[_rID].plyr == 0) - _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(_now); - else - _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(round_[_rID].end); - - // compare to max and set new end time - if (_newTime < (rndMax_).add(_now)) - round_[_rID].end = _newTime; - else - round_[_rID].end = rndMax_.add(_now); - } - - /** - * @dev generates a random number between 0-99 and checks to see if thats - * resulted in an airdrop win - * @return do we have a winner? - */ - function airdrop() - private - view - returns (bool) - { - uint256 seed = uint256(keccak256(abi.encodePacked( - - (block.timestamp).add - (block.difficulty).add - ((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)).add - (block.gaslimit).add - ((uint256(keccak256(abi.encodePacked(msg.sender)))) / (now)).add - (block.number) - - ))); - if ((seed - ((seed / 1000) * 1000)) < airDropTracker_) - return (true); - else - return (false); - } - - /** - * @dev distributes eth based on fees to com, aff, and p3d - */ - function distributeExternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - // pay 2% out to community rewards - uint256 _com = _eth / 50; - uint256 _p3d; - address payable addr = address(uint160(Jekyll_Island_Inc)); - if (!addr.send(_com)) - { - // This ensures Team Just cannot influence the outcome of FoMo3D with - // bank migrations by breaking outgoing transactions. - // Something we would never do. But that's not the point. - // We spent 2000$ in eth re-deploying just to patch this, we hold the - // highest belief that everything we create should be trustless. - // Team JUST, The name you shouldn't have to trust. - _p3d = _com; - _com = 0; - } - - // pay 1% out to FoMo3D short - _com = _eth / 100; - address payable add = address(uint160(otherF3D_)); - add.transfer(_com); - - // distribute share to affiliate - _com = _eth / 10; - - // decide what to do with affiliate share of fees - // affiliate must not be self, and must have a name registered - if (_affID != _pID && plyr_[_affID].name != '') { - plyr_[_affID].aff = _com.add(plyr_[_affID].aff); - emit F3Devents.onAffiliatePayout(_affID, plyr_[_affID].addr, plyr_[_affID].name, _rID, _pID, _com, now); - } else { - _p3d = _com; - } - - // pay out p3d - _p3d = _p3d.add((_eth.mul(fees_[_team].p3d)) / (100)); - if (_p3d > 0) - { - // deposit to divies contract - address payable add = address(uint160(Divies)); - add.transfer(_p3d); - - // set up event data - _eventData_.P3DAmount = _p3d.add(_eventData_.P3DAmount); - } - - return (_eventData_); - } - - function potSwap() - external - payable - { - // setup local rID - uint256 _rID = rID_ + 1; - - round_[_rID].pot = round_[_rID].pot.add(msg.value); - emit F3Devents.onPotSwapDeposit(_rID, msg.value); - } - - /** - * @dev distributes eth based on fees to gen and pot - */ - function distributeInternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _team, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - // calculate gen share - uint256 _gen = (_eth.mul(fees_[_team].gen)) / 100; - - // toss 1% into airdrop pot - uint256 _air = (_eth / 100); - airDropPot_ = airDropPot_.add(_air); - - // update eth balance (eth = eth - (com share + pot swap share + aff share + p3d share + airdrop pot share)) - _eth = _eth.sub(((_eth.mul(14)) / 100).add((_eth.mul(fees_[_team].p3d)) / 100)); - - // calculate pot - uint256 _pot = _eth.sub(_gen); - - // distribute gen share (thats what updateMasks() does) and adjust - // balances for dust. - uint256 _dust = updateMasks(_rID, _pID, _gen, _keys); - if (_dust > 0) - _gen = _gen.sub(_dust); - - // add eth to pot - round_[_rID].pot = _pot.add(_dust).add(round_[_rID].pot); - - // set up event data - _eventData_.genAmount = _gen.add(_eventData_.genAmount); - _eventData_.potAmount = _pot; - - return (_eventData_); - } - - /** - * @dev updates masks for round and player when keys are bought - * @return dust left over - */ - function updateMasks(uint256 _rID, uint256 _pID, uint256 _gen, uint256 _keys) - private - returns (uint256) - { - /* MASKING NOTES - earnings masks are a tricky thing for people to wrap their minds around. - the basic thing to understand here. is were going to have a global - tracker based on profit per share for each round, that increases in - relevant proportion to the increase in share supply. - - the player will have an additional mask that basically says "based - on the rounds mask, my shares, and how much i've already withdrawn, - how much is still owed to me?" - */ - - // calc profit per key & round mask based on this buy: (dust goes to pot) - uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); - round_[_rID].mask = _ppt.add(round_[_rID].mask); - - // calculate player earning from their own buy (only based on the keys - // they just bought). & update player earnings mask - uint256 _pearn = (_ppt.mul(_keys)) / (1000000000000000000); - plyrRnds_[_pID][_rID].mask = (((round_[_rID].mask.mul(_keys)) / (1000000000000000000)).sub(_pearn)).add(plyrRnds_[_pID][_rID].mask); - - // calculate & return dust - return (_gen.sub((_ppt.mul(round_[_rID].keys)) / (1000000000000000000))); - } - - /** - * @dev adds up unmasked earnings, & vault earnings, sets them all to 0 - * @return earnings in wei format - */ - function withdrawEarnings(uint256 _pID) - private - returns (uint256) - { - // update gen vault - updateGenVault(_pID, plyr_[_pID].lrnd); - - // from vaults - uint256 _earnings = (plyr_[_pID].win).add(plyr_[_pID].gen).add(plyr_[_pID].aff); - if (_earnings > 0) - { - plyr_[_pID].win = 0; - plyr_[_pID].gen = 0; - plyr_[_pID].aff = 0; - } - - return (_earnings); - } - - /** - * @dev prepares compression data and fires event for buy or reload tx's - */ - function endTx(uint256 _pID, uint256 _team, uint256 _eth, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) - private - { - _eventData_.compressedData = _eventData_.compressedData + (now * 1000000000000000000) + (_team * 100000000000000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID + (rID_ * 10000000000000000000000000000000000000000000000000000); - - emit F3Devents.onEndTx - ( - _eventData_.compressedData, - _eventData_.compressedIDs, - plyr_[_pID].name, - msg.sender, - _eth, - _keys, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount, - _eventData_.potAmount, - airDropPot_ - ); - } - //============================================================================== - // (~ _ _ _._|_ . - // _)(/_(_|_|| | | \/ . - //====================/========================================================= - /** upon contract deploy, it will be deactivated. this is a one time - * use function that will activate the contract. we do this so devs - * have time to set things up on the web end **/ - bool public activated_ = false; - - function activate() - public - onlyDevs - { - - // can only be ran once - require(activated_ == false, "fomo3d already activated"); - - // activate the contract - activated_ = true; - - otherF3D_ = msg.sender; - Divies = msg.sender; - Jekyll_Island_Inc = msg.sender; - - // lets start first round - rID_ = 1; - round_[1].strt = now + rndExtra_ - rndGap_; - round_[1].end = now + rndInit_ + rndExtra_; - } - - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractScenario007.sol b/framework/src/test/resources/soliditycode_0.6.12/contractScenario007.sol deleted file mode 100644 index a6fa095860f..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractScenario007.sol +++ /dev/null @@ -1,1432 +0,0 @@ - -/** - * @title ERC165 - * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md - */ -interface ERC165 { - - /** - * @notice Query if a contract implements an interface - * @param _interfaceId The interface identifier, as specified in ERC-165 - * @dev Interface identification is specified in ERC-165. This function - * uses less than 30,000 gas. - */ - function supportsInterface(bytes4 _interfaceId) external view returns (bool); - -} - -contract ERC721Basic is ERC165 { - - event Transfer( - address indexed _from, - address indexed _to, - uint256 indexed _tokenId - ); - event Approval( - address indexed _owner, - address indexed _approved, - uint256 indexed _tokenId - ); - event ApprovalForAll( - address indexed _owner, - address indexed _operator, - bool _approved - ); - - function balanceOf(address _owner) public view returns (uint256 _balance); - function ownerOf(uint256 _tokenId) public view returns (address _owner); - function exists(uint256 _tokenId) public view returns (bool _exists); - - function approve(address _to, uint256 _tokenId) public; - function getApproved(uint256 _tokenId) - public view returns (address _operator); - - function setApprovalForAll(address _operator, bool _approved) public; - function isApprovedForAll(address _owner, address _operator) - public view returns (bool); - - function transferFrom(address _from, address _to, uint256 _tokenId) public; - function safeTransferFrom(address _from, address _to, uint256 _tokenId) - public; - - function safeTransferFrom( - address _from, - address _to, - uint256 _tokenId, - bytes memory _data - ) - public; -} - - -/** - * @title SupportsInterfaceWithLookup - * @author Matt Condon (@shrugs) - * @dev Implements ERC165 using a lookup table. - */ -contract SupportsInterfaceWithLookup is ERC165 { - bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7; - /** - * 0x01ffc9a7 === - * bytes4(keccak256('supportsInterface(bytes4)')) - */ - - /** - * @dev a mapping of interface id to whether or not it's supported - */ - mapping(bytes4 => bool) internal supportedInterfaces; - - /** - * @dev A contract implementing SupportsInterfaceWithLookup - * implement ERC165 itself - */ - constructor() public { - _registerInterface(InterfaceId_ERC165); - } - - /** - * @dev implement supportsInterface(bytes4) using a lookup table - */ - function supportsInterface(bytes4 _interfaceId) external view returns (bool) { - return supportedInterfaces[_interfaceId]; - } - - /** - * @dev private method for registering an interface - */ - function _registerInterface(bytes4 _interfaceId) internal { - require(_interfaceId != 0xffffffff); - supportedInterfaces[_interfaceId] = true; - } -} - -contract Governable { - - event Pause(); - event Unpause(); - - address public governor; - bool public paused = false; - - constructor() public { - governor = msg.sender; - } - - function setGovernor(address _gov) public onlyGovernor { - governor = _gov; - } - - modifier onlyGovernor { - require(msg.sender == governor); - _; - } - - /** - * @dev Modifier to make a function callable only when the contract is not paused. - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev Modifier to make a function callable only when the contract is paused. - */ - modifier whenPaused() { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyGovernor whenNotPaused public { - paused = true; - emit Pause(); - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyGovernor whenPaused public { - paused = false; - emit Unpause(); - } - -} - -contract CardBase is Governable { - - struct Card { - uint16 proto; - uint16 purity; - } - - function getCard(uint id) public view returns (uint16 proto, uint16 purity) { - Card memory card = cards[id]; - return (card.proto, card.purity); - } - - function getShine(uint16 purity) public pure returns (uint8) { - return uint8(purity / 1000); - } - - Card[] public cards; - -} - -contract CardProto is CardBase { - - event NewProtoCard( - uint16 id, uint8 season, uint8 god, - Rarity rarity, uint8 mana, uint8 attack, - uint8 health, uint8 cardType, uint8 tribe, bool packable - ); - - struct Limit { - uint64 limit; - bool exists; - } - - // limits for mythic cards - mapping(uint16 => Limit) public limits; - - // can only set limits once - function setLimit(uint16 id, uint64 limit) public onlyGovernor { - Limit memory l = limits[id]; - require(!l.exists); - limits[id] = Limit({ - limit: limit, - exists: true - }); - } - - function getLimit(uint16 id) public view returns (uint64 limit, bool set) { - Limit memory l = limits[id]; - return (l.limit, l.exists); - } - - // could make these arrays to save gas - // not really necessary - will be update a very limited no of times - mapping(uint8 => bool) public seasonTradable; - mapping(uint8 => bool) public seasonTradabilityLocked; - uint8 public currentSeason; - - function makeTradable(uint8 season) public onlyGovernor { - seasonTradable[season] = true; - } - - function makeUntradable(uint8 season) public onlyGovernor { - require(!seasonTradabilityLocked[season]); - seasonTradable[season] = false; - } - - function makePermanantlyTradable(uint8 season) public onlyGovernor { - require(seasonTradable[season]); - seasonTradabilityLocked[season] = true; - } - - function isTradable(uint16 proto) public view returns (bool) { - return seasonTradable[protos[proto].season]; - } - - function nextSeason() public onlyGovernor { - //Seasons shouldn't go to 0 if there is more than the uint8 should hold, the governor should know this ¯\_(ツ)_/¯ -M - require(currentSeason <= 255); - - currentSeason++; - mythic.length = 0; - legendary.length = 0; - epic.length = 0; - rare.length = 0; - common.length = 0; - } - - enum Rarity { - Common, - Rare, - Epic, - Legendary, - Mythic - } - - uint8 constant SPELL = 1; - uint8 constant MINION = 2; - uint8 constant WEAPON = 3; - uint8 constant HERO = 4; - - struct ProtoCard { - bool exists; - uint8 god; - uint8 season; - uint8 cardType; - Rarity rarity; - uint8 mana; - uint8 attack; - uint8 health; - uint8 tribe; - } - - // there is a particular design decision driving this: - // need to be able to iterate over mythics only for card generation - // don't store 5 different arrays: have to use 2 ids - // better to bear this cost (2 bytes per proto card) - // rather than 1 byte per instance - - uint16 public protoCount; - - mapping(uint16 => ProtoCard) protos; - - uint16[] public mythic; - uint16[] public legendary; - uint16[] public epic; - uint16[] public rare; - uint16[] public common; - - function addProtos( - uint16[] memory externalIDs, uint8[] memory gods, Rarity[] memory rarities, uint8[] memory manas, uint8[] memory attacks, - uint8[] memory healths, uint8[] memory cardTypes, uint8[] memory tribes, bool[] memory packable - ) public onlyGovernor returns(uint16) { - - for (uint i = 0; i < externalIDs.length; i++) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: gods[i], - season: currentSeason, - cardType: cardTypes[i], - rarity: rarities[i], - mana: manas[i], - attack: attacks[i], - health: healths[i], - tribe: tribes[i] - }); - - _addProto(externalIDs[i], card, packable[i]); - } - - } - - function addProto( - uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 cardType, uint8 tribe, bool packable - ) public onlyGovernor returns(uint16) { - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: cardType, - rarity: rarity, - mana: mana, - attack: attack, - health: health, - tribe: tribe - }); - - _addProto(externalID, card, packable); - } - - function addWeapon( - uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 durability, bool packable - ) public onlyGovernor returns(uint16) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: WEAPON, - rarity: rarity, - mana: mana, - attack: attack, - health: durability, - tribe: 0 - }); - - _addProto(externalID, card, packable); - } - - function addSpell(uint16 externalID, uint8 god, Rarity rarity, uint8 mana, bool packable) public onlyGovernor returns(uint16) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: SPELL, - rarity: rarity, - mana: mana, - attack: 0, - health: 0, - tribe: 0 - }); - - _addProto(externalID, card, packable); - } - - function addMinion( - uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 tribe, bool packable - ) public onlyGovernor returns(uint16) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: MINION, - rarity: rarity, - mana: mana, - attack: attack, - health: health, - tribe: tribe - }); - - _addProto(externalID, card, packable); - } - - function _addProto(uint16 externalID, ProtoCard memory card, bool packable) internal { - - require(!protos[externalID].exists); - - card.exists = true; - - protos[externalID] = card; - - protoCount++; - - emit NewProtoCard( - externalID, currentSeason, card.god, - card.rarity, card.mana, card.attack, - card.health, card.cardType, card.tribe, packable - ); - - if (packable) { - Rarity rarity = card.rarity; - if (rarity == Rarity.Common) { - common.push(externalID); - } else if (rarity == Rarity.Rare) { - rare.push(externalID); - } else if (rarity == Rarity.Epic) { - epic.push(externalID); - } else if (rarity == Rarity.Legendary) { - legendary.push(externalID); - } else if (rarity == Rarity.Mythic) { - mythic.push(externalID); - } else { - require(false); - } - } - } - - function getProto(uint16 id) public view returns( - bool exists, uint8 god, uint8 season, uint8 cardType, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 tribe - ) { - ProtoCard memory proto = protos[id]; - return ( - proto.exists, - proto.god, - proto.season, - proto.cardType, - proto.rarity, - proto.mana, - proto.attack, - proto.health, - proto.tribe - ); - } - - function getRandomCard(Rarity rarity, uint16 random) public view returns (uint16) { - // modulo bias is fine - creates rarity tiers etc - // will obviously revert is there are no cards of that type: this is expected - should never happen - if (rarity == Rarity.Common) { - return common[random % common.length]; - } else if (rarity == Rarity.Rare) { - return rare[random % rare.length]; - } else if (rarity == Rarity.Epic) { - return epic[random % epic.length]; - } else if (rarity == Rarity.Legendary) { - return legendary[random % legendary.length]; - } else if (rarity == Rarity.Mythic) { - // make sure a mythic is available - uint16 id; - uint64 limit; - bool set; - for (uint i = 0; i < mythic.length; i++) { - id = mythic[(random + i) % mythic.length]; - (limit, set) = getLimit(id); - if (set && limit > 0){ - return id; - } - } - // if not, they get a legendary :( - return legendary[random % legendary.length]; - } - require(false); - return 0; - } - - // can never adjust tradable cards - // each season gets a 'balancing beta' - // totally immutable: season, rarity - function replaceProto( - uint16 index, uint8 god, uint8 cardType, uint8 mana, uint8 attack, uint8 health, uint8 tribe - ) public onlyGovernor { - ProtoCard memory pc = protos[index]; - require(!seasonTradable[pc.season]); - protos[index] = ProtoCard({ - exists: true, - god: god, - season: pc.season, - cardType: cardType, - rarity: pc.rarity, - mana: mana, - attack: attack, - health: health, - tribe: tribe - }); - } - -} - -contract ERC721Receiver { - /** - * @dev Magic value to be returned upon successful reception of an NFT - * Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`, - * which can be also obtained as `ERC721Receiver(0).onERC721Received.selector` - */ - bytes4 internal constant ERC721_RECEIVED = 0x150b7a02; - - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a `safetransfer`. This function MAY throw to revert and reject the - * transfer. Return of other than the magic value MUST result in the - * transaction being reverted. - * Note: the contract address is always the message sender. - * @param _operator The address which called `safeTransferFrom` function - * @param _from The address which previously owned the token - * @param _tokenId The NFT identifier which is being transfered - * @param _data Additional data with no specified format - * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - */ - function onERC721Received( - address _operator, - address _from, - uint256 _tokenId, - bytes memory _data - ) - public - returns(bytes4); -} - -library AddressUtils { - - /** - * Returns whether the target address is a contract - * @dev This function will return false if invoked during the constructor of a contract, - * as the code is not actually created until after the constructor finishes. - * @param addr address to check - * @return whether the target address is a contract - */ - function isContract1(address addr) internal view returns (bool) { - uint256 size; - // XXX Currently there is no better way to check if there is a contract in an address - // than to check the size of the code at that address. - // See https://ethereum.stackexchange.com/a/14016/36603 - // for more details about how this works. - // TODO Check this again before the Serenity release, because all addresses will be - // contracts then. - // solium-disable-next-line security/no-inline-assembly - assembly { size := extcodesize(addr) } - return size > 0; - } - -} - -library SafeMath { - - /** - * @dev Multiplies two numbers, throws on overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { - // Gas optimization: this is cheaper than asserting 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - c = a * b; - assert(c / a == b); - return c; - } - - /** - * @dev Integer division of two numbers, truncating the quotient. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // assert(b > 0); // Solidity automatically throws when dividing by 0 - // uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - return a / b; - } - - /** - * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - assert(b <= a); - return a - b; - } - - /** - * @dev Adds two numbers, throws on overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256 c) { - c = a + b; - assert(c >= a); - return c; - } -} - -contract ERC721BasicToken is CardProto, SupportsInterfaceWithLookup, ERC721Basic { - - bytes4 private constant InterfaceId_ERC721 = 0x80ac58cd; - /* - * 0x80ac58cd === - * bytes4(keccak256('balanceOf(address)')) ^ - * bytes4(keccak256('ownerOf(uint256)')) ^ - * bytes4(keccak256('approve(address,uint256)')) ^ - * bytes4(keccak256('getApproved(uint256)')) ^ - * bytes4(keccak256('setApprovalForAll(address,bool)')) ^ - * bytes4(keccak256('isApprovedForAll(address,address)')) ^ - * bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^ - * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) - */ - - bytes4 private constant InterfaceId_ERC721Exists = 0x4f558e79; - /* - * 0x4f558e79 === - * bytes4(keccak256('exists(uint256)')) - */ - - using SafeMath for uint256; - using AddressUtils for address; - - // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - // which can be also obtained as `ERC721Receiver(0).onERC721Received.selector` - bytes4 private constant ERC721_RECEIVED = 0x150b7a02; - - // Mapping from token ID to owner - mapping (uint256 => address) internal tokenOwner; - - // Mapping from token ID to approved address - mapping (uint256 => address) internal tokenApprovals; - - // Mapping from owner to number of owned token - // mapping (address => uint256) internal ownedTokensCount; - - // Mapping from owner to operator approvals - mapping (address => mapping (address => bool)) internal operatorApprovals; - - /** - * @dev Guarantees msg.sender is owner of the given token - * @param _tokenId uint256 ID of the token to validate its ownership belongs to msg.sender - */ - modifier onlyOwnerOf(uint256 _tokenId) { - require(ownerOf(_tokenId) == msg.sender); - _; - } - - /** - * @dev Checks msg.sender can transfer a token, by being owner, approved, or operator - * @param _tokenId uint256 ID of the token to validate - */ - modifier canTransfer(uint256 _tokenId) { - require(isApprovedOrOwner(msg.sender, _tokenId)); - _; - } - - constructor() - public - { - // register the supported interfaces to conform to ERC721 via ERC165 - _registerInterface(InterfaceId_ERC721); - _registerInterface(InterfaceId_ERC721Exists); - } - - /** - * @dev Gets the balance of the specified address - * @param _owner address to query the balance of - * @return uint256 representing the amount owned by the passed address - */ - function balanceOf(address _owner) public view returns (uint256); - - /** - * @dev Gets the owner of the specified token ID - * @param _tokenId uint256 ID of the token to query the owner of - * @return owner address currently marked as the owner of the given token ID - */ - function ownerOf(uint256 _tokenId) public view returns (address) { - address owner = tokenOwner[_tokenId]; - require(owner != address(0)); - return owner; - } - - /** - * @dev Returns whether the specified token exists - * @param _tokenId uint256 ID of the token to query the existence of - * @return whether the token exists - */ - function exists(uint256 _tokenId) public view returns (bool) { - address owner = tokenOwner[_tokenId]; - return owner != address(0); - } - - /** - * @dev Approves another address to transfer the given token ID - * The zero address indicates there is no approved address. - * There can only be one approved address per token at a given time. - * Can only be called by the token owner or an approved operator. - * @param _to address to be approved for the given token ID - * @param _tokenId uint256 ID of the token to be approved - */ - function approve(address _to, uint256 _tokenId) public { - address owner = ownerOf(_tokenId); - require(_to != owner); - require(msg.sender == owner || isApprovedForAll(owner, msg.sender)); - - tokenApprovals[_tokenId] = _to; - emit Approval(owner, _to, _tokenId); - } - - /** - * @dev Gets the approved address for a token ID, or zero if no address set - * @param _tokenId uint256 ID of the token to query the approval of - * @return address currently approved for the given token ID - */ - function getApproved(uint256 _tokenId) public view returns (address) { - return tokenApprovals[_tokenId]; - } - - /** - * @dev Sets or unsets the approval of a given operator - * An operator is allowed to transfer all tokens of the sender on their behalf - * @param _to operator address to set the approval - * @param _approved representing the status of the approval to be set - */ - function setApprovalForAll(address _to, bool _approved) public { - require(_to != msg.sender); - operatorApprovals[msg.sender][_to] = _approved; - emit ApprovalForAll(msg.sender, _to, _approved); - } - - /** - * @dev Tells whether an operator is approved by a given owner - * @param _owner owner address which you want to query the approval of - * @param _operator operator address which you want to query the approval of - * @return bool whether the given operator is approved by the given owner - */ - function isApprovedForAll( - address _owner, - address _operator - ) - public - view - returns (bool) - { - return operatorApprovals[_owner][_operator]; - } - - /** - * @dev Transfers the ownership of a given token ID to another address - * Usage of this method is discouraged, use `safeTransferFrom` whenever possible - * Requires the msg sender to be the owner, approved, or operator - * @param _from current owner of the token - * @param _to address to receive the ownership of the given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - public - canTransfer(_tokenId) - { - require(_from != address(0)); - require(_to != address(0)); - - clearApproval(_from, _tokenId); - removeTokenFrom(_from, _tokenId); - addTokenTo(_to, _tokenId); - - emit Transfer(_from, _to, _tokenId); - } - - /** - * @dev Safely transfers the ownership of a given token ID to another address - * If the target address is a contract, it must implement `onERC721Received`, - * which is called upon a safe transfer, and return the magic value - * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, - * the transfer is reverted. - * - * Requires the msg sender to be the owner, approved, or operator - * @param _from current owner of the token - * @param _to address to receive the ownership of the given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function safeTransferFrom( - address _from, - address _to, - uint256 _tokenId - ) - public - canTransfer(_tokenId) - { - // solium-disable-next-line arg-overflow - safeTransferFrom(_from, _to, _tokenId, ""); - } - - /** - * @dev Safely transfers the ownership of a given token ID to another address - * If the target address is a contract, it must implement `onERC721Received`, - * which is called upon a safe transfer, and return the magic value - * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, - * the transfer is reverted. - * Requires the msg sender to be the owner, approved, or operator - * @param _from current owner of the token - * @param _to address to receive the ownership of the given token ID - * @param _tokenId uint256 ID of the token to be transferred - * @param _data bytes data to send along with a safe transfer check - */ - function safeTransferFrom( - address _from, - address _to, - uint256 _tokenId, - bytes memory _data - ) - public - canTransfer(_tokenId) - { - transferFrom(_from, _to, _tokenId); - // solium-disable-next-line arg-overflow - require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data)); - } - - /** - * @dev Returns whether the given spender can transfer a given token ID - * @param _spender address of the spender to query - * @param _tokenId uint256 ID of the token to be transferred - * @return bool whether the msg.sender is approved for the given token ID, - * is an operator of the owner, or is the owner of the token - */ - function isApprovedOrOwner( - address _spender, - uint256 _tokenId - ) - internal - view - returns (bool) - { - address owner = ownerOf(_tokenId); - // Disable solium check because of - // https://github.com/duaraghav8/Solium/issues/175 - // solium-disable-next-line operator-whitespace - return ( - _spender == owner || - getApproved(_tokenId) == _spender || - isApprovedForAll(owner, _spender) - ); - } - - /** - * @dev Internal function to clear current approval of a given token ID - * Reverts if the given address is not indeed the owner of the token - * @param _owner owner of the token - * @param _tokenId uint256 ID of the token to be transferred - */ - function clearApproval(address _owner, uint256 _tokenId) internal { - require(ownerOf(_tokenId) == _owner); - if (tokenApprovals[_tokenId] != address(0)) { - tokenApprovals[_tokenId] = address(0); - } - } - - /** - * @dev Internal function to mint a new token - * Reverts if the given token ID already exists - * @param _to The address that will own the minted token - * @param _tokenId uint256 ID of the token to be minted by the msg.sender - */ - function _mint(address _to, uint256 _tokenId) internal { - require(_to != address(0)); - addNewTokenTo(_to, _tokenId); - emit Transfer(address(0), _to, _tokenId); - } - - - /** - * @dev Internal function to burn a specific token - * Reverts if the token does not exist - * @param _tokenId uint256 ID of the token being burned by the msg.sender - */ - function _burn(address _owner, uint256 _tokenId) internal { - clearApproval(_owner, _tokenId); - removeTokenFrom(_owner, _tokenId); - emit Transfer(_owner, address(0), _tokenId); - } - - function addNewTokenTo(address _to, uint256 _tokenId) internal { - require(tokenOwner[_tokenId] == address(0)); - tokenOwner[_tokenId] = _to; - } - - /** - * @dev Internal function to add a token ID to the list of a given address - * @param _to address representing the new owner of the given token ID - * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address - */ - function addTokenTo(address _to, uint256 _tokenId) internal { - require(tokenOwner[_tokenId] == address(0)); - tokenOwner[_tokenId] = _to; - // ownedTokensCount[_to] = ownedTokensCount[_to].add(1); - } - - /** - * @dev Internal function to remove a token ID from the list of a given address - * @param _from address representing the previous owner of the given token ID - * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address - */ - function removeTokenFrom(address _from, uint256 _tokenId) internal { - require(ownerOf(_tokenId) == _from); - // ownedTokensCount[_from] = ownedTokensCount[_from].sub(1); - tokenOwner[_tokenId] = address(0); - } - - /** - * @dev Internal function to invoke `onERC721Received` on a target address - * The call is not executed if the target address is not a contract - * @param _from address representing the previous owner of the given token ID - * @param _to target address that will receive the tokens - * @param _tokenId uint256 ID of the token to be transferred - * @param _data bytes optional data to send along with the call - * @return whether the call correctly returned the expected magic value - */ - function checkAndCallSafeTransfer( - address _from, - address _to, - uint256 _tokenId, - bytes memory _data - ) - internal - returns (bool) - { - if (!_to.isContract1()) { - return true; - } - bytes4 retval = ERC721Receiver(_to).onERC721Received( - msg.sender, _from, _tokenId, _data); - return (retval == ERC721_RECEIVED); - } - -} - - - -contract ERC721Enumerable is ERC721Basic { - function totalSupply() public view returns (uint256); - function tokenOfOwnerByIndex( - address _owner, - uint256 _index - ) - public - view - returns (uint256 _tokenId); - - function tokenByIndex(uint256 _index) public view returns (uint256); -} - -contract ERC721Metadata is ERC721Basic { - function name() external view returns (string memory _name); - function symbol() external view returns (string memory _symbol); - function tokenURI(uint256 _tokenId) public view returns (string memory); -} - -contract ERC721 is ERC721Basic, ERC721Enumerable, ERC721Metadata { - -} - - - - -library Strings { - - // via https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol - function strConcat(string memory _a, string memory _b, string memory _c, string memory _d, string memory _e) internal pure returns (string memory ) { - bytes memory _ba = bytes(_a); - bytes memory _bb = bytes(_b); - bytes memory _bc = bytes(_c); - bytes memory _bd = bytes(_d); - bytes memory _be = bytes(_e); - string memory abcde = new string(_ba.length + _bb.length + _bc.length + _bd.length + _be.length); - bytes memory babcde = bytes(abcde); - uint k = 0; - for (uint i = 0; i < _ba.length; i++) babcde[k++] = _ba[i]; - for (uint i = 0; i < _bb.length; i++) babcde[k++] = _bb[i]; - for (uint i = 0; i < _bc.length; i++) babcde[k++] = _bc[i]; - for (uint i = 0; i < _bd.length; i++) babcde[k++] = _bd[i]; - for (uint i = 0; i < _be.length; i++) babcde[k++] = _be[i]; - return string(babcde); - } - - function strConcat(string memory _a, string memory _b, string memory _c, string memory _d) internal pure returns (string memory ) { - return strConcat(_a, _b, _c, _d, ""); - } - - function strConcat(string memory _a, string memory _b, string memory _c) internal pure returns (string memory ) { - return strConcat(_a, _b, _c, "", ""); - } - - function strConcat(string memory _a, string memory _b) internal pure returns (string memory ) { - return strConcat(_a, _b, "", "", ""); - } - - function uint2str(uint i) internal pure returns (string memory ) { - if (i == 0) return "0"; - uint j = i; - uint len; - while (j != 0){ - len++; - j /= 10; - } - bytes memory bstr = new bytes(len); - uint k = len - 1; - while (i != 0){ - bstr[k--] = byte(uint8(48 + i % 10)); - i /= 10; - } - return string(bstr); - } -} - -contract ERC721Token is SupportsInterfaceWithLookup, ERC721BasicToken, ERC721 { - - using Strings for string; - - bytes4 private constant InterfaceId_ERC721Enumerable = 0x780e9d63; - /** - * 0x780e9d63 === - * bytes4(keccak256('totalSupply()')) ^ - * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ - * bytes4(keccak256('tokenByIndex(uint256)')) - */ - - bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f; - /** - * 0x5b5e139f === - * bytes4(keccak256('name()')) ^ - * bytes4(keccak256('symbol()')) ^ - * bytes4(keccak256('tokenURI(uint256)')) - */ - - /*** Constants ***/ - // Configure these for your own deployment - string public constant NAME = "Gods Unchained"; - string public constant SYMBOL = "GODS"; - string public tokenMetadataBaseURI = "https://api.godsunchained.com/card/"; - - // Mapping from owner to list of owned token IDs - // EDITED: limit to 2^40 (around 1T) - mapping(address => uint40[]) internal ownedTokens; - - uint32[] ownedTokensIndex; - - /** - * @dev Constructor function - */ - constructor() public { - - // register the supported interfaces to conform to ERC721 via ERC165 - _registerInterface(InterfaceId_ERC721Enumerable); - _registerInterface(InterfaceId_ERC721Metadata); - } - - /** - * @dev Gets the token name - * @return string representing the token name - */ - function name() external view returns (string memory) { - return NAME; - } - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory) { - return SYMBOL; - } - - /** - * @dev Returns an URI for a given token ID - * Throws if the token ID does not exist. May return an empty string. - * @param _tokenId uint256 ID of the token to query - */ - function tokenURI(uint256 _tokenId) public view returns (string memory) { - return Strings.strConcat( - tokenMetadataBaseURI, - Strings.uint2str(_tokenId) - ); - } - - /** - * @dev Gets the token ID at a given index of the tokens list of the requested owner - * @param _owner address owning the tokens list to be accessed - * @param _index uint256 representing the index to be accessed of the requested tokens list - * @return uint256 token ID at the given index of the tokens list owned by the requested address - */ - function tokenOfOwnerByIndex( - address _owner, - uint256 _index - ) - public - view - returns (uint256) - { - require(_index < balanceOf(_owner)); - return ownedTokens[_owner][_index]; - } - - /** - * @dev Gets the total amount of tokens stored by the contract - * @return uint256 representing the total amount of tokens - */ - function totalSupply() public view returns (uint256) { - return cards.length; - } - - /** - * @dev Gets the token ID at a given index of all the tokens in this contract - * Reverts if the index is greater or equal to the total number of tokens - * @param _index uint256 representing the index to be accessed of the tokens list - * @return uint256 token ID at the given index of the tokens list - */ - function tokenByIndex(uint256 _index) public view returns (uint256) { - require(_index < totalSupply()); - return _index; - } - - /** - * @dev Internal function to add a token ID to the list of a given address - * @param _to address representing the new owner of the given token ID - * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address - */ - function addTokenTo(address _to, uint256 _tokenId) internal { - super.addTokenTo(_to, _tokenId); - uint256 length = ownedTokens[_to].length; - // EDITED: prevent overflow - require(length == uint32(length)); - ownedTokens[_to].push(uint40(_tokenId)); - - ownedTokensIndex[_tokenId] = uint32(length); - } - - // EDITED - // have to have in order to use array rather than mapping - function addNewTokenTo(address _to, uint256 _tokenId) internal { - super.addNewTokenTo(_to, _tokenId); - uint256 length = ownedTokens[_to].length; - // EDITED: prevent overflow - require(length == uint32(length)); - ownedTokens[_to].push(uint40(_tokenId)); - ownedTokensIndex.push(uint32(length)); - } - - /** - * @dev Internal function to remove a token ID from the list of a given address - * @param _from address representing the previous owner of the given token ID - * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address - */ - function removeTokenFrom(address _from, uint256 _tokenId) internal { - super.removeTokenFrom(_from, _tokenId); - - uint32 tokenIndex = ownedTokensIndex[_tokenId]; - uint256 lastTokenIndex = ownedTokens[_from].length.sub(1); - uint40 lastToken = ownedTokens[_from][lastTokenIndex]; - - ownedTokens[_from][tokenIndex] = lastToken; - ownedTokens[_from][lastTokenIndex] = 0; - // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to - // be zero. Then we can make sure that we will remove _tokenId from the ownedTokens list since we are first swapping - // the lastToken to the first position, and then dropping the element placed in the last position of the list - - ownedTokens[_from].length--; - ownedTokensIndex[_tokenId] = 0; - ownedTokensIndex[lastToken] = tokenIndex; - } - - /** - * @dev Gets the balance of the specified address - overrriden from previous to save gas - * @param _owner address to query the balance of - * @return uint256 representing the amount owned by the passed address - */ - function balanceOf(address _owner) public view returns (uint256) { - return ownedTokens[_owner].length; - } - -} - -contract CardOwnershipTwo is ERC721Token { - - uint public burnCount; - - function getActiveCards() public view returns (uint) { - return totalSupply() - burnCount; - } - - /** - * @param to : the address to which the card will be transferred - * @param id : the id of the card to be transferred - */ - function transfer(address to, uint id) public payable onlyOwnerOf(id) { - require(isTradable(cards[id].proto)); - require(to != address(0)); - - _transfer(msg.sender, to, id); - } - - function _transfer(address from, address to, uint id) internal { - - clearApproval(from, id); - - removeTokenFrom(from, id); - - addTokenTo(to, id); - - emit Transfer(from, to, id); - } - - /** - * @param to : the address to which the cards will be transferred - * @param ids : the ids of the cards to be transferred - */ - function transferAll(address to, uint[] memory ids) public payable { - for (uint i = 0; i < ids.length; i++) { - transfer(to, ids[i]); - } - } - - /** - * @param proposed : the claimed owner of the cards - * @param ids : the ids of the cards to check - * @return whether proposed owns all of the cards - */ - function ownsAll(address proposed, uint[] memory ids) public view returns (bool) { - require(ids.length > 0); - for (uint i = 0; i < ids.length; i++) { - if (!owns(proposed, ids[i])) { - return false; - } - } - return true; - } - - /** - * @param proposed : the claimed owner of the card - * @param id : the id of the card to check - * @return whether proposed owns the card - */ - function owns(address proposed, uint id) public view returns (bool) { - return ownerOf(id) == proposed; - } - - function burn(uint id) public onlyOwnerOf(id) { - burnCount++; - _burn(msg.sender, id); - } - - /** - * @param ids : the indices of the tokens to burn - */ - function burnAll(uint[] memory ids) public { - for (uint i = 0; i < ids.length; i++){ - burn(ids[i]); - } - } - - /** - * @param to : the address to approve for transfer - * @param id : the index of the card to be approved - */ - function approve(address to, uint id) public { - require(isTradable(cards[id].proto)); - super.approve(to, id); - } - - /** - * @param to : the address to approve for transfer - * @param ids : the indices of the cards to be approved - */ - function approveAll(address to, uint[] memory ids) public { - for (uint i = 0; i < ids.length; i++) { - approve(to, ids[i]); - } - } - - /** - * @param to : the address to which the token should be transferred - * @param id : the index of the token to transfer - */ - function transferFrom(address from, address to, uint id) public { - require(isTradable(cards[id].proto)); - super.transferFrom(from, to, id); - } - - /** - * @param to : the address to which the tokens should be transferred - * @param ids : the indices of the tokens to transfer - */ - function transferAllFrom(address from, address to, uint[] memory ids) public { - for (uint i = 0; i < ids.length; i++) { - transferFrom(from, to, ids[i]); - } - } - - /** - * @return the number of cards which have been burned - */ - function getBurnCount() public view returns (uint) { - return burnCount; - } - -} - -contract CardIntegrationTwo is CardOwnershipTwo { - - address[] public packs; - - event CardCreated(uint indexed id, uint16 proto, uint16 purity, address owner); - - function addPack(address approved) public onlyGovernor { - packs.push(approved); - } - - modifier onlyApprovedPacks { - require(_isApprovedPack()); - _; - } - - function _isApprovedPack() private view returns (bool) { - for (uint i = 0; i < packs.length; i++) { - if (msg.sender == address(packs[i])) { - return true; - } - } - return false; - } - - function createCard(address owner, uint16 proto, uint16 purity) public whenNotPaused onlyApprovedPacks returns (uint) { - ProtoCard memory card = protos[proto]; - require(card.season == currentSeason); - if (card.rarity == Rarity.Mythic) { - uint64 limit; - bool exists; - (limit, exists) = getLimit(proto); - require(!exists || limit > 0); - limits[proto].limit--; - } - return _createCard(owner, proto, purity); - } - - function _createCard(address owner, uint16 proto, uint16 purity) internal returns (uint) { - Card memory card = Card({ - proto: proto, - purity: purity - }); - - uint id = cards.push(card) - 1; - - _mint(owner, id); - - emit CardCreated(id, proto, purity, owner); - - return id; - } - - /*function combineCards(uint[] ids) public whenNotPaused { - require(ids.length == 5); - require(ownsAll(msg.sender, ids)); - Card memory first = cards[ids[0]]; - uint16 proto = first.proto; - uint8 shine = _getShine(first.purity); - require(shine < shineLimit); - uint16 puritySum = first.purity - (shine * 1000); - burn(ids[0]); - for (uint i = 1; i < ids.length; i++) { - Card memory next = cards[ids[i]]; - require(next.proto == proto); - require(_getShine(next.purity) == shine); - puritySum += (next.purity - (shine * 1000)); - burn(ids[i]); - } - uint16 newPurity = uint16(((shine + 1) * 1000) + (puritySum / ids.length)); - _createCard(msg.sender, proto, newPurity); - }*/ - - - // PURITY NOTES - // currently, we only - // however, to protect rarity, you'll never be abl - // this is enforced by the restriction in the create-card function - // no cards above this point can be found in packs - - - -} - -contract PreviousInterface { - - function ownerOf(uint id) public view returns (address); - - function getCard(uint id) public view returns (uint16, uint16); - - function totalSupply() public view returns (uint); - - function burnCount() public view returns (uint); - -} - -contract CardMigration is CardIntegrationTwo { - - constructor(PreviousInterface previous) public { - old = previous; - } - - // use interface to lower deployment cost - PreviousInterface old; - - mapping(uint => bool) public migrated; - - function migrate(uint id) public { - - require(!migrated[id]); - - migrated[id] = true; - - address owner = old.ownerOf(id); - - uint16 proto; - uint16 purity; - - (proto, purity) = old.getCard(id); - - _createCard(owner, proto, purity); - } - - function migrateAll(uint[] memory ids) public { - - for (uint i = 0; i < ids.length; i++){ - migrate(ids[i]); - } - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractScenario008.sol b/framework/src/test/resources/soliditycode_0.6.12/contractScenario008.sol deleted file mode 100644 index d039f7393d2..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractScenario008.sol +++ /dev/null @@ -1,2061 +0,0 @@ - - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() public { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address payable public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address payable _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() virtual public onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - emit Transfer(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(now), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - kitties.push(_kitty); - uint256 newKittenId = kitties.length - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - emit Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(address(0), _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -abstract contract ERC721 { - // Required methods - function totalSupply() virtual public view returns (uint256 total); - function balanceOf(address _owner) virtual public view returns (uint256 balance); - function ownerOf(uint256 _tokenId) virtual external view returns (address owner); - function approve(address _to, uint256 _tokenId) virtual external; - function transfer(address _to, uint256 _tokenId) virtual external; - function transferFrom(address _from, address _to, uint256 _tokenId) virtual external; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) virtual external view returns (bool); -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is ERC721, KittyBase { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external override view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public override view returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - override - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - override - external - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - emit Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - override - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() override public view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - override - external - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { - string memory outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { - require( address(erc721Metadata) != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - msg.sender.transfer(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, address(saleAuction)); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, address(siringAuction)); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, address(saleAuction)); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - address(uint160(address(this))) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - constructor() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(-1), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - emit ContractUpgrade(_v2Address); - } - -/// @notice No tipping! -/// @dev Reject all Ether from being sent here, unless it's from one of the -/// two auction contracts. (Hopefully, we can prevent user accidents.) -fallback() external payable { -require( -msg.sender == address(saleAuction) || -msg.sender == address(siringAuction) -); -} - -/// @notice Returns all the relevant information about a specific kitty. -/// @param _id The ID of the kitty of interest. -function getKitty(uint256 _id) -external -view -returns ( -bool isGestating, -bool isReady, -uint256 cooldownIndex, -uint256 nextActionAt, -uint256 siringWithId, -uint256 birthTime, -uint256 matronId, -uint256 sireId, -uint256 generation, -uint256 genes -) { -Kitty storage kit = kitties[_id]; - -// if this variable is 0 then it's not gestating -isGestating = (kit.siringWithId != 0); -isReady = (kit.cooldownEndBlock <= block.number); -cooldownIndex = uint256(kit.cooldownIndex); -nextActionAt = uint256(kit.cooldownEndBlock); -siringWithId = uint256(kit.siringWithId); -birthTime = uint256(kit.birthTime); -matronId = uint256(kit.matronId); -sireId = uint256(kit.sireId); -generation = uint256(kit.generation); -genes = kit.genes; -} - -/// @dev Override unpause so it requires all external contract addresses -/// to be set before contract can be unpaused. Also, we can't have -/// newContractAddress set either, because then the contract was upgraded. -/// @notice This is public rather than external so we can call super.unpause -/// without using an expensive CALL. - -function unpause() override public onlyCEO whenPaused { -require(address(saleAuction) != address(0)); -require(address(siringAuction) != address(0)); -require(address(geneScience) != address(0)); -require(newContractAddress == address(0)); - -// Actually unpause the contract. -super.unpause(); -} - -// @dev Allows the CFO to capture the balance available to the contract. -function withdrawBalance() external onlyCFO { -uint256 balance = address(this).balance; -// Subtract all the currently pregnant kittens we have, plus 1 of margin. -uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - -if (balance > subtractFees) { -cfoAddress.transfer(balance - subtractFees); -} -} -} - - - - - - - - - - - - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - -function isGeneScience() public pure returns (bool){ -return true; -} - -/// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor -/// @param genes1 genes of mom -/// @param genes2 genes of sire -/// @return the genes that are supposed to be passed down the child -function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - -return (genes1+genes2+targetBlock)/2; - - -} -} - - - - - - - - - - - - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { -/// @dev Given a token Id, returns a byte array that is supposed to be converted into string. -function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { -if (_tokenId == 1) { -buffer[0] = "Hello World! :D"; -count = 15; -} else if (_tokenId == 2) { -buffer[0] = "I would definitely choose a medi"; -buffer[1] = "um length string."; -count = 49; -} else if (_tokenId == 3) { -buffer[0] = "Lorem ipsum dolor sit amet, mi e"; -buffer[1] = "st accumsan dapibus augue lorem,"; -buffer[2] = " tristique vestibulum id, libero"; -buffer[3] = " suscipit varius sapien aliquam."; -count = 128; -} -} -} - - - - - - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - -// Represents an auction on an NFT -struct Auction { -// Current owner of NFT -address payable seller; -// Price (in wei) at beginning of auction -uint128 startingPrice; -// Price (in wei) at end of auction -uint128 endingPrice; -// Duration (in seconds) of auction -uint64 duration; -// Time when auction started -// NOTE: 0 if this auction has been concluded -uint64 startedAt; -} - -// Reference to contract tracking NFT ownership -ERC721 public nonFungibleContract; - -// Cut owner takes on each auction, measured in basis points (1/100 of a percent). -// Values 0-10,000 map to 0%-100% -uint256 public ownerCut; - -// Map from token ID to their corresponding auction. -mapping (uint256 => Auction) tokenIdToAuction; - -event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); -event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); -event AuctionCancelled(uint256 tokenId); - -/// @dev Returns true if the claimant owns the token. -/// @param _claimant - Address claiming to own the token. -/// @param _tokenId - ID of token whose ownership to verify. -function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { -return (nonFungibleContract.ownerOf(_tokenId) == _claimant); -} - -/// @dev Escrows the NFT, assigning ownership to this contract. -/// Throws if the escrow fails. -/// @param _owner - Current owner address of token to escrow. -/// @param _tokenId - ID of token whose approval to verify. -function _escrow(address _owner, uint256 _tokenId) internal { -// it will throw if transfer fails -nonFungibleContract.transferFrom(_owner, address(this), _tokenId); -} - -/// @dev Transfers an NFT owned by this contract to another address. -/// Returns true if the transfer succeeds. -/// @param _receiver - Address to transfer NFT to. -/// @param _tokenId - ID of token to transfer. -function _transfer(address _receiver, uint256 _tokenId) internal { -// it will throw if transfer fails -nonFungibleContract.transfer(_receiver, _tokenId); -} - -/// @dev Adds an auction to the list of open auctions. Also fires the -/// AuctionCreated event. -/// @param _tokenId The ID of the token to be put on auction. -/// @param _auction Auction to add. -function _addAuction(uint256 _tokenId, Auction memory _auction) internal { -// Require that all auctions have a duration of -// at least one minute. (Keeps our math from getting hairy!) -require(_auction.duration >= 1 minutes); - -tokenIdToAuction[_tokenId] = _auction; - -emit AuctionCreated( -uint256(_tokenId), -uint256(_auction.startingPrice), -uint256(_auction.endingPrice), -uint256(_auction.duration) -); -} - -/// @dev Cancels an auction unconditionally. -function _cancelAuction(uint256 _tokenId, address _seller) internal { -_removeAuction(_tokenId); -_transfer(_seller, _tokenId); -emit AuctionCancelled(_tokenId); -} - -/// @dev Computes the price and transfers winnings. -/// Does NOT transfer ownership of token. -function _bid(uint256 _tokenId, uint256 _bidAmount) -internal -returns (uint256) -{ -// Get a reference to the auction struct -Auction storage auction = tokenIdToAuction[_tokenId]; - -// Explicitly check that this auction is currently live. -// (Because of how Ethereum mappings work, we can't just count -// on the lookup above failing. An invalid _tokenId will just -// return an auction object that is all zeros.) -require(_isOnAuction(auction)); - -// Check that the bid is greater than or equal to the current price -uint256 price = _currentPrice(auction); -require(_bidAmount >= price); - -// Grab a reference to the seller before the auction struct -// gets deleted. -address payable seller = auction.seller; - -// The bid is good! Remove the auction before sending the fees -// to the sender so we can't have a reentrancy attack. -_removeAuction(_tokenId); - -// Transfer proceeds to seller (if there are any!) -if (price > 0) { -// Calculate the auctioneer's cut. -// (NOTE: _computeCut() is guaranteed to return a -// value <= price, so this subtraction can't go negative.) -uint256 auctioneerCut = _computeCut(price); -uint256 sellerProceeds = price - auctioneerCut; - -// NOTE: Doing a transfer() in the middle of a complex -// method like this is generally discouraged because of -// reentrancy attacks and DoS attacks if the seller is -// a contract with an invalid fallback function. We explicitly -// guard against reentrancy attacks by removing the auction -// before calling transfer(), and the only thing the seller -// can DoS is the sale of their own asset! (And if it's an -// accident, they can call cancelAuction(). ) -seller.transfer(sellerProceeds); -} - -// Calculate any excess funds included with the bid. If the excess -// is anything worth worrying about, transfer it back to bidder. -// NOTE: We checked above that the bid amount is greater than or -// equal to the price so this cannot underflow. -uint256 bidExcess = _bidAmount - price; - -// Return the funds. Similar to the previous transfer, this is -// not susceptible to a re-entry attack because the auction is -// removed before any transfers occur. -msg.sender.transfer(bidExcess); - -// Tell the world! -emit AuctionSuccessful(_tokenId, price, msg.sender); - -return price; -} - -/// @dev Removes an auction from the list of open auctions. -/// @param _tokenId - ID of NFT on auction. -function _removeAuction(uint256 _tokenId) internal { -delete tokenIdToAuction[_tokenId]; -} - -/// @dev Returns true if the NFT is on auction. -/// @param _auction - Auction to check. -function _isOnAuction(Auction storage _auction) internal view returns (bool) { -return (_auction.startedAt > 0); -} - -/// @dev Returns current price of an NFT on auction. Broken into two -/// functions (this one, that computes the duration from the auction -/// structure, and the other that does the price computation) so we -/// can easily test that the price computation works correctly. -function _currentPrice(Auction storage _auction) -internal -view -returns (uint256) -{ -uint256 secondsPassed = 0; - -// A bit of insurance against negative values (or wraparound). -// Probably not necessary (since Ethereum guarnatees that the -// now variable doesn't ever go backwards). -if (now > _auction.startedAt) { -secondsPassed = now - _auction.startedAt; -} - -return _computeCurrentPrice( -_auction.startingPrice, -_auction.endingPrice, -_auction.duration, -secondsPassed -); -} - -/// @dev Computes the current price of an auction. Factored out -/// from _currentPrice so we can run extensive unit tests. -/// When testing, make this function public and turn on -/// `Current price computation` test suite. -function _computeCurrentPrice( -uint256 _startingPrice, -uint256 _endingPrice, -uint256 _duration, -uint256 _secondsPassed -) -internal -pure -returns (uint256) -{ -// NOTE: We don't use SafeMath (or similar) in this function because -// all of our public functions carefully cap the maximum values for -// time (at 64-bits) and currency (at 128-bits). _duration is -// also known to be non-zero (see the require() statement in -// _addAuction()) -if (_secondsPassed >= _duration) { -// We've reached the end of the dynamic pricing portion -// of the auction, just return the end price. -return _endingPrice; -} else { -// Starting price can be higher than ending price (and often is!), so -// this delta can be negative. -int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - -// This multiplication can't overflow, _secondsPassed will easily fit within -// 64-bits, and totalPriceChange will easily fit within 128-bits, their product -// will always fit within 256-bits. -int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - -// currentPriceChange can be negative, but if so, will have a magnitude -// less that _startingPrice. Thus, this result will always end up positive. -int256 currentPrice = int256(_startingPrice) + currentPriceChange; - -return uint256(currentPrice); -} -} - -/// @dev Computes owner's cut of a sale. -/// @param _price - Sale price of NFT. -function _computeCut(uint256 _price) internal view returns (uint256) { -// NOTE: We don't use SafeMath (or similar) in this function because -// all of our entry functions carefully cap the maximum values for -// currency (at 128-bits), and ownerCut <= 10000 (see the require() -// statement in the ClockAuction constructor). The result of this -// function is always guaranteed to be <= _price. -return _price * ownerCut / 10000; -} - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { -event Pause(); -event Unpause(); - -bool public paused = false; - - -/** - * @dev modifier to allow actions only when the contract IS paused - */ -modifier whenNotPaused() { -require(!paused); -_; -} - -/** - * @dev modifier to allow actions only when the contract IS NOT paused - */ -modifier whenPaused { -require(paused); -_; -} - -/** - * @dev called by the owner to pause, triggers stopped state - */ -function pause() onlyOwner whenNotPaused public returns (bool) { -paused = true; -emit Pause(); -return true; -} - -/** - * @dev called by the owner to unpause, returns to normal state - */ -function unpause() onlyOwner whenPaused public returns (bool) { -paused = false; -emit Unpause(); -return true; -} -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - -/// @dev The ERC-165 interface signature for ERC-721. -/// Ref: https://github.com/ethereum/EIPs/issues/165 -/// Ref: https://github.com/ethereum/EIPs/issues/721 -bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - -/// @dev Constructor creates a reference to the NFT ownership contract -/// and verifies the owner cut is in the valid range. -/// @param _nftAddress - address of a deployed contract implementing -/// the Nonfungible Interface. -/// @param _cut - percent cut the owner takes on each auction, must be -/// between 0-10,000. -constructor(address _nftAddress, uint256 _cut) public { -require(_cut <= 10000); -ownerCut = _cut; - -ERC721 candidateContract = ERC721(_nftAddress); -require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); -nonFungibleContract = candidateContract; -} - -/// @dev Remove all Ether from the contract, which is the owner's cuts -/// as well as any Ether sent directly to the contract address. -/// Always transfers to the NFT contract, but can be called either by -/// the owner or the NFT contract. -function withdrawBalance() external { -address payable nftAddress = address(uint160(address(nonFungibleContract))); - -require( -msg.sender == owner || -msg.sender == nftAddress -); -// We are using this boolean method to make sure that even if one fails it will still work -bool res = nftAddress.send(address(this).balance); -} - -/// @dev Creates and begins a new auction. -/// @param _tokenId - ID of token to auction, sender must be owner. -/// @param _startingPrice - Price of item (in wei) at beginning of auction. -/// @param _endingPrice - Price of item (in wei) at end of auction. -/// @param _duration - Length of time to move between starting -/// price and ending price (in seconds). -/// @param _seller - Seller, if not the message sender -function createAuction( -uint256 _tokenId, -uint256 _startingPrice, -uint256 _endingPrice, -uint256 _duration, -address payable _seller -) -virtual -external -whenNotPaused -{ -// Sanity check that no inputs overflow how many bits we've allocated -// to store them in the auction struct. -require(_startingPrice == uint256(uint128(_startingPrice))); -require(_endingPrice == uint256(uint128(_endingPrice))); -require(_duration == uint256(uint64(_duration))); - -require(_owns(msg.sender, _tokenId)); -_escrow(msg.sender, _tokenId); -Auction memory auction = Auction( -_seller, -uint128(_startingPrice), -uint128(_endingPrice), -uint64(_duration), -uint64(now) -); -_addAuction(_tokenId, auction); -} - -/// @dev Bids on an open auction, completing the auction and transferring -/// ownership of the NFT if enough Ether is supplied. -/// @param _tokenId - ID of token to bid on. -function bid(uint256 _tokenId) -external -payable -whenNotPaused -virtual -{ -// _bid will throw if the bid or funds transfer fails -_bid(_tokenId, msg.value); -_transfer(msg.sender, _tokenId); -} - -/// @dev Cancels an auction that hasn't been won yet. -/// Returns the NFT to original owner. -/// @notice This is a state-modifying function that can -/// be called while the contract is paused. -/// @param _tokenId - ID of token on auction -function cancelAuction(uint256 _tokenId) -external -{ -Auction storage auction = tokenIdToAuction[_tokenId]; -require(_isOnAuction(auction)); -address seller = auction.seller; -require(msg.sender == seller); -_cancelAuction(_tokenId, seller); -} - -/// @dev Cancels an auction when the contract is paused. -/// Only the owner may do this, and NFTs are returned to -/// the seller. This should only be used in emergencies. -/// @param _tokenId - ID of the NFT on auction to cancel. -function cancelAuctionWhenPaused(uint256 _tokenId) -whenPaused -onlyOwner -external -{ -Auction storage auction = tokenIdToAuction[_tokenId]; -require(_isOnAuction(auction)); -_cancelAuction(_tokenId, auction.seller); -} - -/// @dev Returns auction info for an NFT on auction. -/// @param _tokenId - ID of NFT on auction. -function getAuction(uint256 _tokenId) -external -view -returns -( -address seller, -uint256 startingPrice, -uint256 endingPrice, -uint256 duration, -uint256 startedAt -) { -Auction storage auction = tokenIdToAuction[_tokenId]; -require(_isOnAuction(auction)); -return ( -auction.seller, -auction.startingPrice, -auction.endingPrice, -auction.duration, -auction.startedAt -); -} - -/// @dev Returns the current price of an auction. -/// @param _tokenId - ID of the token price we are checking. -function getCurrentPrice(uint256 _tokenId) -external -view -returns (uint256) -{ -Auction storage auction = tokenIdToAuction[_tokenId]; -require(_isOnAuction(auction)); -return _currentPrice(auction); -} - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - -// @dev Sanity check that allows us to ensure that we are pointing to the -// right auction in our setSiringAuctionAddress() call. -bool public isSiringClockAuction = true; - -// Delegate constructor -constructor(address _nftAddr, uint256 _cut) public -ClockAuction(_nftAddr, _cut) {} - -/// @dev Creates and begins a new auction. Since this function is wrapped, -/// require sender to be KittyCore contract. -/// @param _tokenId - ID of token to auction, sender must be owner. -/// @param _startingPrice - Price of item (in wei) at beginning of auction. -/// @param _endingPrice - Price of item (in wei) at end of auction. -/// @param _duration - Length of auction (in seconds). -/// @param _seller - Seller, if not the message sender -function createAuction( -uint256 _tokenId, -uint256 _startingPrice, -uint256 _endingPrice, -uint256 _duration, -address payable _seller -) -override -external -{ -// Sanity check that no inputs overflow how many bits we've allocated -// to store them in the auction struct. -require(_startingPrice == uint256(uint128(_startingPrice))); -require(_endingPrice == uint256(uint128(_endingPrice))); -require(_duration == uint256(uint64(_duration))); - -require(msg.sender == address(nonFungibleContract)); -_escrow(_seller, _tokenId); -Auction memory auction = Auction( -_seller, -uint128(_startingPrice), -uint128(_endingPrice), -uint64(_duration), -uint64(now) -); -_addAuction(_tokenId, auction); -} - -/// @dev Places a bid for siring. Requires the sender -/// is the KittyCore contract because all bid methods -/// should be wrapped. Also returns the kitty to the -/// seller rather than the winner. -function bid(uint256 _tokenId) -external -payable -override -{ -require(msg.sender == address(nonFungibleContract)); -address seller = tokenIdToAuction[_tokenId].seller; -// _bid checks that token ID is valid and will throw if bid fails -_bid(_tokenId, msg.value); -// We transfer the kitty back to the seller, the winner will get -// the offspring -_transfer(seller, _tokenId); -} - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - -// @dev Sanity check that allows us to ensure that we are pointing to the -// right auction in our setSaleAuctionAddress() call. -bool public isSaleClockAuction = true; - -// Tracks last 5 sale price of gen0 kitty sales -uint256 public gen0SaleCount; -uint256[5] public lastGen0SalePrices; - -// Delegate constructor -constructor(address _nftAddr, uint256 _cut) public -ClockAuction(_nftAddr, _cut) {} - -/// @dev Creates and begins a new auction. -/// @param _tokenId - ID of token to auction, sender must be owner. -/// @param _startingPrice - Price of item (in wei) at beginning of auction. -/// @param _endingPrice - Price of item (in wei) at end of auction. -/// @param _duration - Length of auction (in seconds). -/// @param _seller - Seller, if not the message sender -function createAuction( -uint256 _tokenId, -uint256 _startingPrice, -uint256 _endingPrice, -uint256 _duration, -address payable _seller -) -override -external -{ -// Sanity check that no inputs overflow how many bits we've allocated -// to store them in the auction struct. -require(_startingPrice == uint256(uint128(_startingPrice))); -require(_endingPrice == uint256(uint128(_endingPrice))); -require(_duration == uint256(uint64(_duration))); - -require(msg.sender == address(nonFungibleContract)); -_escrow(_seller, _tokenId); -Auction memory auction = Auction( -_seller, -uint128(_startingPrice), -uint128(_endingPrice), -uint64(_duration), -uint64(now) -); -_addAuction(_tokenId, auction); -} - -/// @dev Updates lastSalePrice if seller is the nft contract -/// Otherwise, works the same as default bid method. -function bid(uint256 _tokenId) -external -override -payable -{ -// _bid verifies token ID size -address seller = tokenIdToAuction[_tokenId].seller; -uint256 price = _bid(_tokenId, msg.value); -_transfer(msg.sender, _tokenId); - -// If not a gen0 auction, exit -if (seller == address(nonFungibleContract)) { -// Track gen0 sale prices -lastGen0SalePrices[gen0SaleCount % 5] = price; -gen0SaleCount++; -} -} - -function averageGen0SalePrice() external view returns (uint256) { -uint256 sum = 0; -for (uint256 i = 0; i < 5; i++) { -sum += lastGen0SalePrices[i]; -} -return sum / 5; -} - -} - - - - - - - diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractScenario009.sol b/framework/src/test/resources/soliditycode_0.6.12/contractScenario009.sol deleted file mode 100644 index 52fa63e90ac..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractScenario009.sol +++ /dev/null @@ -1,51 +0,0 @@ - - -library Set { - // We define a new struct datatype that will be used to - // hold its data in the calling contract. - struct Data { mapping(uint => bool) flags; } - - // Note that the first parameter is of type "storage - // reference" and thus only its storage address and not - // its contents is passed as part of the call. This is a - // special feature of library functions. It is idiomatic - // to call the first parameter 'self', if the function can - // be seen as a method of that object. - function insert (Data storage self, uint value) public - returns (bool) - { - if (self.flags[value]) - return false; // already there - self.flags[value] = true; - return true; - } - - function remove(Data storage self, uint value) public - returns (bool) - { - if (!self.flags[value]) - return false; // not there - self.flags[value] = false; - return true; - } - - function contains(Data storage self, uint value) public - returns (bool) - { - return self.flags[value]; - } -} - - -contract C { - Set.Data knownValues; - - function register(uint value) public { - // The library functions can be called without a - // specific instance of the library, since the - // "instance" will be the current contract. - if (!Set.insert(knownValues, value)) - revert(); - } - // In this contract, we can also directly access knownValues.flags, if we want. -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractScenario010.sol b/framework/src/test/resources/soliditycode_0.6.12/contractScenario010.sol deleted file mode 100644 index 4e299efecad..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractScenario010.sol +++ /dev/null @@ -1,107 +0,0 @@ - - -contract TRON_ERC721 { - //name - function name() view public returns (string memory name){ - return "Tron ERC721 Token"; - } - //symbol - function symbol() view public returns (string memory symbol){ - return "T721T"; - } - - //totalSupply - - function totalSupply() view public returns (uint256 supply){ - uint256 totalSupply = 1000000000000; - return totalSupply; - } - - mapping(address => uint) private balances; - function balanceOf(address _owner) view public returns (uint balance) - { - return balances[_owner]; - } - - - mapping(uint256 => address) private tokenOwners; - mapping(uint256 => bool) private tokenExists; - function ownerOf(uint256 _tokenId) view public returns (address owner) { - require(tokenExists[_tokenId]); - return tokenOwners[_tokenId]; - } - - - mapping(address => mapping (address => uint256)) allowed; - function approve(address _to, uint256 _tokenId) public{ - require(msg.sender == ownerOf(_tokenId)); - require(msg.sender != _to); - allowed[msg.sender][_to] = _tokenId; - emit Approval(msg.sender, _to, _tokenId); - } - - - function takeOwnership(uint256 _tokenId) public { - require(tokenExists[_tokenId]); - address oldOwner = ownerOf(_tokenId); - address newOwner = msg.sender; - require(newOwner != oldOwner); - require(allowed[oldOwner][newOwner] == _tokenId); - balances[oldOwner] -= 1; - tokenOwners[_tokenId] = newOwner; - balances[newOwner] += 1; - emit Transfer(oldOwner, newOwner, _tokenId); - } - - - mapping(address => mapping(uint256 => uint256)) private ownerTokens; - function removeFromTokenList(address owner, uint256 _tokenId) private { - for(uint256 i = 0;ownerTokens[owner][i] != _tokenId;i++){ - ownerTokens[owner][i] = 0; - } - } - - function transfer(address _to, uint256 _tokenId) public{ - address currentOwner = msg.sender; - address newOwner = _to; - require(tokenExists[_tokenId]); - require(currentOwner == ownerOf(_tokenId)); - require(currentOwner != newOwner); - require(newOwner != address(0)); - address oldOwner =currentOwner; - removeFromTokenList(oldOwner,_tokenId); - balances[oldOwner] -= 1; - tokenOwners[_tokenId] = newOwner; - balances[newOwner] += 1; - emit Transfer(oldOwner, newOwner, _tokenId); - } - - function transferFrom(address _from,address _to, uint256 _tokenId) public{ - address currentOwner = _from; - address newOwner = _to; - require(tokenExists[_tokenId]); - require(currentOwner == ownerOf(_tokenId)); - require(currentOwner != newOwner); - require(newOwner != address(0)); - address oldOwner =currentOwner; - removeFromTokenList(oldOwner,_tokenId); - balances[oldOwner] -= 1; - tokenOwners[_tokenId] = newOwner; - balances[newOwner] += 1; - emit Transfer(oldOwner, newOwner, _tokenId); - } - - - function tokenOfOwnerByIndex(address _owner, uint256 _index) view public returns (uint tokenId){ - return ownerTokens[_owner][_index]; - } - - - mapping(uint256 => string) tokenLinks; - function tokenMetadata(uint256 _tokenId) view public returns (string memory infoUrl) { - return tokenLinks[_tokenId]; - } - // Events - event Transfer(address indexed _from, address indexed _to, uint256 _tokenId); - event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId); -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractScenario011.sol b/framework/src/test/resources/soliditycode_0.6.12/contractScenario011.sol deleted file mode 100644 index 041d298cf32..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractScenario011.sol +++ /dev/null @@ -1,2060 +0,0 @@ - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() public { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address payable public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address payable _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() public virtual onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - emit Transfer(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(now), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - kitties.push(_kitty); - uint256 newKittenId = kitties.length - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - emit Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(address(0), _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -abstract contract ERC721 { - // Required methods - function totalSupply() public virtual view returns (uint256 total); - function balanceOf(address _owner) public virtual view returns (uint256 balance); - function ownerOf(uint256 _tokenId) external virtual view returns (address owner); - function approve(address _to, uint256 _tokenId) external virtual; - function transfer(address _to, uint256 _tokenId) external virtual; - function transferFrom(address _from, address _to, uint256 _tokenId) external virtual; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) external virtual view returns (bool); -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is ERC721, KittyBase { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external override view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public view override returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - override - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - external - override - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - emit Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - external - override - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() public override view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - external - override - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { - string memory outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { - require( address(erc721Metadata) != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2 ; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - msg.sender.transfer(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, address(saleAuction)); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, address(siringAuction)); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10 ; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, address(saleAuction)); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - address(uint160(address(this))) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - constructor() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(-1), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - emit ContractUpgrade(_v2Address); - } - - /// @notice No tipping! - /// @dev Reject all Ether from being sent here, unless it's from one of the - /// two auction contracts. (Hopefully, we can prevent user accidents.) - fallback() external payable { - require( - msg.sender == address(saleAuction) || - msg.sender == address(siringAuction) - ); - } - - /// @notice Returns all the relevant information about a specific kitty. - /// @param _id The ID of the kitty of interest. - function getKitty(uint256 _id) - external - view - returns ( - bool isGestating, - bool isReady, - uint256 cooldownIndex, - uint256 nextActionAt, - uint256 siringWithId, - uint256 birthTime, - uint256 matronId, - uint256 sireId, - uint256 generation, - uint256 genes - ) { - Kitty storage kit = kitties[_id]; - - // if this variable is 0 then it's not gestating - isGestating = (kit.siringWithId != 0); - isReady = (kit.cooldownEndBlock <= block.number); - cooldownIndex = uint256(kit.cooldownIndex); - nextActionAt = uint256(kit.cooldownEndBlock); - siringWithId = uint256(kit.siringWithId); - birthTime = uint256(kit.birthTime); - matronId = uint256(kit.matronId); - sireId = uint256(kit.sireId); - generation = uint256(kit.generation); - genes = kit.genes; - } - - /// @dev Override unpause so it requires all external contract addresses - /// to be set before contract can be unpaused. Also, we can't have - /// newContractAddress set either, because then the contract was upgraded. - /// @notice This is public rather than external so we can call super.unpause - /// without using an expensive CALL. - - function unpause() public override onlyCEO whenPaused { - require(address(saleAuction) != address(0)); - require(address(siringAuction) != address(0)); - require(address(geneScience) != address(0)); - require(newContractAddress == address(0)); - - // Actually unpause the contract. - super.unpause(); - } - - // @dev Allows the CFO to capture the balance available to the contract. - function withdrawBalance() external onlyCFO { - uint256 balance = address(this).balance; - // Subtract all the currently pregnant kittens we have, plus 1 of margin. - uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - - if (balance > subtractFees) { - cfoAddress.transfer(balance - subtractFees); - } - } -} - - - - - - - - - - - - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - - function isGeneScience() public pure returns (bool){ - return true; - } - - /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor - /// @param genes1 genes of mom - /// @param genes2 genes of sire - /// @return the genes that are supposed to be passed down the child - function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - - return (genes1+genes2+targetBlock)/2; - - - } -} - - - - - - - - - - - - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { - /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. - function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { - if (_tokenId == 1) { - buffer[0] = "Hello World! :D"; - count = 15; - } else if (_tokenId == 2) { - buffer[0] = "I would definitely choose a medi"; - buffer[1] = "um length string."; - count = 49; - } else if (_tokenId == 3) { - buffer[0] = "Lorem ipsum dolor sit amet, mi e"; - buffer[1] = "st accumsan dapibus augue lorem,"; - buffer[2] = " tristique vestibulum id, libero"; - buffer[3] = " suscipit varius sapien aliquam."; - count = 128; - } - } -} - - - - - - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - - // Represents an auction on an NFT - struct Auction { - // Current owner of NFT - address payable seller; - // Price (in wei) at beginning of auction - uint128 startingPrice; - // Price (in wei) at end of auction - uint128 endingPrice; - // Duration (in seconds) of auction - uint64 duration; - // Time when auction started - // NOTE: 0 if this auction has been concluded - uint64 startedAt; - } - - // Reference to contract tracking NFT ownership - ERC721 public nonFungibleContract; - - // Cut owner takes on each auction, measured in basis points (1/100 of a percent). - // Values 0-10,000 map to 0%-100% - uint256 public ownerCut; - - // Map from token ID to their corresponding auction. - mapping (uint256 => Auction) tokenIdToAuction; - - event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); - event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); - event AuctionCancelled(uint256 tokenId); - - /// @dev Returns true if the claimant owns the token. - /// @param _claimant - Address claiming to own the token. - /// @param _tokenId - ID of token whose ownership to verify. - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return (nonFungibleContract.ownerOf(_tokenId) == _claimant); - } - - /// @dev Escrows the NFT, assigning ownership to this contract. - /// Throws if the escrow fails. - /// @param _owner - Current owner address of token to escrow. - /// @param _tokenId - ID of token whose approval to verify. - function _escrow(address _owner, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transferFrom(_owner, address(this), _tokenId); - } - - /// @dev Transfers an NFT owned by this contract to another address. - /// Returns true if the transfer succeeds. - /// @param _receiver - Address to transfer NFT to. - /// @param _tokenId - ID of token to transfer. - function _transfer(address _receiver, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transfer(_receiver, _tokenId); - } - - /// @dev Adds an auction to the list of open auctions. Also fires the - /// AuctionCreated event. - /// @param _tokenId The ID of the token to be put on auction. - /// @param _auction Auction to add. - function _addAuction(uint256 _tokenId, Auction memory _auction) internal { - // Require that all auctions have a duration of - // at least one minute. (Keeps our math from getting hairy!) - require(_auction.duration >= 1 minutes); - - tokenIdToAuction[_tokenId] = _auction; - - emit AuctionCreated( - uint256(_tokenId), - uint256(_auction.startingPrice), - uint256(_auction.endingPrice), - uint256(_auction.duration) - ); - } - - /// @dev Cancels an auction unconditionally. - function _cancelAuction(uint256 _tokenId, address _seller) internal { - _removeAuction(_tokenId); - _transfer(_seller, _tokenId); - emit AuctionCancelled(_tokenId); - } - - /// @dev Computes the price and transfers winnings. - /// Does NOT transfer ownership of token. - function _bid(uint256 _tokenId, uint256 _bidAmount) - internal - returns (uint256) - { - // Get a reference to the auction struct - Auction storage auction = tokenIdToAuction[_tokenId]; - - // Explicitly check that this auction is currently live. - // (Because of how Ethereum mappings work, we can't just count - // on the lookup above failing. An invalid _tokenId will just - // return an auction object that is all zeros.) - require(_isOnAuction(auction)); - - // Check that the bid is greater than or equal to the current price - uint256 price = _currentPrice(auction); - require(_bidAmount >= price); - - // Grab a reference to the seller before the auction struct - // gets deleted. - address payable seller = auction.seller; - - // The bid is good! Remove the auction before sending the fees - // to the sender so we can't have a reentrancy attack. - _removeAuction(_tokenId); - - // Transfer proceeds to seller (if there are any!) - if (price > 0) { - // Calculate the auctioneer's cut. - // (NOTE: _computeCut() is guaranteed to return a - // value <= price, so this subtraction can't go negative.) - uint256 auctioneerCut = _computeCut(price); - uint256 sellerProceeds = price - auctioneerCut; - - // NOTE: Doing a transfer() in the middle of a complex - // method like this is generally discouraged because of - // reentrancy attacks and DoS attacks if the seller is - // a contract with an invalid fallback function. We explicitly - // guard against reentrancy attacks by removing the auction - // before calling transfer(), and the only thing the seller - // can DoS is the sale of their own asset! (And if it's an - // accident, they can call cancelAuction(). ) - seller.transfer(sellerProceeds); - } - - // Calculate any excess funds included with the bid. If the excess - // is anything worth worrying about, transfer it back to bidder. - // NOTE: We checked above that the bid amount is greater than or - // equal to the price so this cannot underflow. - uint256 bidExcess = _bidAmount - price; - - // Return the funds. Similar to the previous transfer, this is - // not susceptible to a re-entry attack because the auction is - // removed before any transfers occur. - msg.sender.transfer(bidExcess); - - // Tell the world! - emit AuctionSuccessful(_tokenId, price, msg.sender); - - return price; - } - - /// @dev Removes an auction from the list of open auctions. - /// @param _tokenId - ID of NFT on auction. - function _removeAuction(uint256 _tokenId) internal { - delete tokenIdToAuction[_tokenId]; - } - - /// @dev Returns true if the NFT is on auction. - /// @param _auction - Auction to check. - function _isOnAuction(Auction storage _auction) internal view returns (bool) { - return (_auction.startedAt > 0); - } - - /// @dev Returns current price of an NFT on auction. Broken into two - /// functions (this one, that computes the duration from the auction - /// structure, and the other that does the price computation) so we - /// can easily test that the price computation works correctly. - function _currentPrice(Auction storage _auction) - internal - view - returns (uint256) - { - uint256 secondsPassed = 0; - - // A bit of insurance against negative values (or wraparound). - // Probably not necessary (since Ethereum guarnatees that the - // now variable doesn't ever go backwards). - if (now > _auction.startedAt) { - secondsPassed = now - _auction.startedAt; - } - - return _computeCurrentPrice( - _auction.startingPrice, - _auction.endingPrice, - _auction.duration, - secondsPassed - ); - } - - /// @dev Computes the current price of an auction. Factored out - /// from _currentPrice so we can run extensive unit tests. - /// When testing, make this function public and turn on - /// `Current price computation` test suite. - function _computeCurrentPrice( - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - uint256 _secondsPassed - ) - internal - pure - returns (uint256) - { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our public functions carefully cap the maximum values for - // time (at 64-bits) and currency (at 128-bits). _duration is - // also known to be non-zero (see the require() statement in - // _addAuction()) - if (_secondsPassed >= _duration) { - // We've reached the end of the dynamic pricing portion - // of the auction, just return the end price. - return _endingPrice; - } else { - // Starting price can be higher than ending price (and often is!), so - // this delta can be negative. - int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - - // This multiplication can't overflow, _secondsPassed will easily fit within - // 64-bits, and totalPriceChange will easily fit within 128-bits, their product - // will always fit within 256-bits. - int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - - // currentPriceChange can be negative, but if so, will have a magnitude - // less that _startingPrice. Thus, this result will always end up positive. - int256 currentPrice = int256(_startingPrice) + currentPriceChange; - - return uint256(currentPrice); - } - } - - /// @dev Computes owner's cut of a sale. - /// @param _price - Sale price of NFT. - function _computeCut(uint256 _price) internal view returns (uint256) { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our entry functions carefully cap the maximum values for - // currency (at 128-bits), and ownerCut <= 10000 (see the require() - // statement in the ClockAuction constructor). The result of this - // function is always guaranteed to be <= _price. - return _price * ownerCut / 10000; - } - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { - event Pause(); - event Unpause(); - - bool public paused = false; - - - /** - * @dev modifier to allow actions only when the contract IS paused - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev modifier to allow actions only when the contract IS NOT paused - */ - modifier whenPaused { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyOwner whenNotPaused public returns (bool) { - paused = true; - emit Pause(); - return true; - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyOwner whenPaused public returns (bool) { - paused = false; - emit Unpause(); - return true; - } -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - - /// @dev The ERC-165 interface signature for ERC-721. - /// Ref: https://github.com/ethereum/EIPs/issues/165 - /// Ref: https://github.com/ethereum/EIPs/issues/721 - bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - - /// @dev Constructor creates a reference to the NFT ownership contract - /// and verifies the owner cut is in the valid range. - /// @param _nftAddress - address of a deployed contract implementing - /// the Nonfungible Interface. - /// @param _cut - percent cut the owner takes on each auction, must be - /// between 0-10,000. - constructor(address _nftAddress, uint256 _cut) public { - require(_cut <= 10000); - ownerCut = _cut; - - ERC721 candidateContract = ERC721(_nftAddress); - require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); - nonFungibleContract = candidateContract; - } - - /// @dev Remove all Ether from the contract, which is the owner's cuts - /// as well as any Ether sent directly to the contract address. - /// Always transfers to the NFT contract, but can be called either by - /// the owner or the NFT contract. - function withdrawBalance() external { - address payable nftAddress = address(uint160(address(nonFungibleContract))); - - require( - msg.sender == owner || - msg.sender == nftAddress - ); - // We are using this boolean method to make sure that even if one fails it will still work - bool res = nftAddress.send(address(this).balance); - } - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of time to move between starting - /// price and ending price (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - virtual - whenNotPaused - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(_owns(msg.sender, _tokenId)); - _escrow(msg.sender, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Bids on an open auction, completing the auction and transferring - /// ownership of the NFT if enough Ether is supplied. - /// @param _tokenId - ID of token to bid on. - function bid(uint256 _tokenId) - external - payable - virtual - whenNotPaused - { - // _bid will throw if the bid or funds transfer fails - _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - } - - /// @dev Cancels an auction that hasn't been won yet. - /// Returns the NFT to original owner. - /// @notice This is a state-modifying function that can - /// be called while the contract is paused. - /// @param _tokenId - ID of token on auction - function cancelAuction(uint256 _tokenId) - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - address seller = auction.seller; - require(msg.sender == seller); - _cancelAuction(_tokenId, seller); - } - - /// @dev Cancels an auction when the contract is paused. - /// Only the owner may do this, and NFTs are returned to - /// the seller. This should only be used in emergencies. - /// @param _tokenId - ID of the NFT on auction to cancel. - function cancelAuctionWhenPaused(uint256 _tokenId) - whenPaused - onlyOwner - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - _cancelAuction(_tokenId, auction.seller); - } - - /// @dev Returns auction info for an NFT on auction. - /// @param _tokenId - ID of NFT on auction. - function getAuction(uint256 _tokenId) - external - view - returns - ( - address seller, - uint256 startingPrice, - uint256 endingPrice, - uint256 duration, - uint256 startedAt - ) { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return ( - auction.seller, - auction.startingPrice, - auction.endingPrice, - auction.duration, - auction.startedAt - ); - } - - /// @dev Returns the current price of an auction. - /// @param _tokenId - ID of the token price we are checking. - function getCurrentPrice(uint256 _tokenId) - external - view - returns (uint256) - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return _currentPrice(auction); - } - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSiringAuctionAddress() call. - bool public isSiringClockAuction = true; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. Since this function is wrapped, - /// require sender to be KittyCore contract. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - override - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Places a bid for siring. Requires the sender - /// is the KittyCore contract because all bid methods - /// should be wrapped. Also returns the kitty to the - /// seller rather than the winner. - function bid(uint256 _tokenId) - external - payable - override - { - require(msg.sender == address(nonFungibleContract)); - address seller = tokenIdToAuction[_tokenId].seller; - // _bid checks that token ID is valid and will throw if bid fails - _bid(_tokenId, msg.value); - // We transfer the kitty back to the seller, the winner will get - // the offspring - _transfer(seller, _tokenId); - } - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSaleAuctionAddress() call. - bool public isSaleClockAuction = true; - - // Tracks last 5 sale price of gen0 kitty sales - uint256 public gen0SaleCount; - uint256[5] public lastGen0SalePrices; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - override - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Updates lastSalePrice if seller is the nft contract - /// Otherwise, works the same as default bid method. - function bid(uint256 _tokenId) - external - payable - override - { - // _bid verifies token ID size - address seller = tokenIdToAuction[_tokenId].seller; - uint256 price = _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - - // If not a gen0 auction, exit - if (seller == address(nonFungibleContract)) { - // Track gen0 sale prices - lastGen0SalePrices[gen0SaleCount % 5] = price; - gen0SaleCount++; - } - } - - function averageGen0SalePrice() external view returns (uint256) { - uint256 sum = 0; - for (uint256 i = 0; i < 5; i++) { - sum += lastGen0SalePrices[i]; - } - return sum / 5; - } - -} - - - - - - - diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractScenario012.sol b/framework/src/test/resources/soliditycode_0.6.12/contractScenario012.sol deleted file mode 100644 index 7fea2b1ccf1..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractScenario012.sol +++ /dev/null @@ -1,57 +0,0 @@ - -contract PayTest { - -uint256 public n; -constructor() payable public{ -n = 0; -} - -function nPlusOne() public{ -n = n+1; -} - -//get current contract balance -function getBalance() payable public returns (uint) { -return address(this).balance; -} - -function getSenderBalance() public view returns(address, uint) { -return (msg.sender, msg.sender.balance); -} - -address public user; - -//deposit 1 coin to msg.sender -function depositOneCoin() payable public returns(bool success){ -return msg.sender.send(1); -} - -// function transferOneCoin() payable public returns(){ -// address(msg.sender).transfer(1); -// } - -// function depositOneCoin() payable public returns(address addr, uint amount, bool success){ -// return (msg.sender, msg.value, msg.sender.send(1)); -// } - -//deposit coin to msg.sender -function deposit(uint256 money) payable public returns(bool success){ -return msg.sender.send(money); -} -// function deposit(uint money) payable public returns(address addr, uint amount, bool success){ -// return (msg.sender, msg.value, msg.sender.send(money)); -// } - -// fallback() payable { -// msg.sender.send(1); -// } - -function sendToAddress(address payable _receiver) payable public{ -_receiver.transfer(msg.value); -} - -function sendToAddress2(address payable _receiver) payable public{ -_receiver.transfer(5); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractScenario013.sol b/framework/src/test/resources/soliditycode_0.6.12/contractScenario013.sol deleted file mode 100644 index 93b7905679b..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractScenario013.sol +++ /dev/null @@ -1,8 +0,0 @@ - -contract timetest { - -function time() public{ -require(1 trx == 1000000 sun); - -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractScenario014.sol b/framework/src/test/resources/soliditycode_0.6.12/contractScenario014.sol deleted file mode 100644 index 9f423d1b1ab..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractScenario014.sol +++ /dev/null @@ -1,34 +0,0 @@ - -contract Contract1 { - constructor() public payable{} - function send5SunToReceiver(address payable _receiver) payable public{ - _receiver.transfer(5); - } -} -contract contract2 { - address public payContract; - - constructor(address _add) payable public{ - payContract = _add; - } - - function triggerContract1(address _receiver) payable public{ - payContract.call(abi.encodeWithSignature("send5SunToReceiver(address)",_receiver)); - } - - function triggerContract1ButRevert(address _receiver) payable public{ - payContract.call(abi.encodeWithSignature("send5SunToReceiver(address)",_receiver)); - require(1 == 2); - } - -} -contract contract3 { - address public payContract; - constructor(address _add) payable public{ - payContract = _add; - } - - function triggerContract2(address _receiver) payable public{ - payContract.call(abi.encodeWithSignature("triggerContract1(address)",_receiver)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTest.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTest.sol deleted file mode 100644 index 9a72b4a53b4..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTest.sol +++ /dev/null @@ -1,19 +0,0 @@ - - -contract Test{ - -function a() public returns (uint){ - -uint256 count = 0; - -for (uint256 i = 1; i > 0; i++) { - -count++; - -} - -return count; - -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractToMathedFeed.sol b/framework/src/test/resources/soliditycode_0.6.12/contractToMathedFeed.sol deleted file mode 100644 index d9df9d9c10d..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractToMathedFeed.sol +++ /dev/null @@ -1,21 +0,0 @@ - - -contract ToMathedFeed { - uint public i=1; - function ToMathed (uint value) public { - i=value; - } -} - -contract ToMathedUseINContract { - function ToMathedIUseNR(address a,uint256 n) public returns(bool){ - address payContract=a; - (bool success, bytes memory data) = payContract.call(abi.encodeWithSignature("ToMathedNot(uint256)",n)); - return success; - } - function ToMathedIUseNRE(address a,uint256 value) public returns(bool){ - address payContract=a; - (bool success, bytes memory data) = payContract.call(abi.encodeWithSignature("ToMathed(uint256)",value)); - return success; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTransferToken001.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTransferToken001.sol deleted file mode 100644 index 0edbbfbb44a..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTransferToken001.sol +++ /dev/null @@ -1,22 +0,0 @@ -contract A { - address public a; - constructor() public payable{} - function kill(address payable toAddress) payable public{ - selfdestruct(toAddress); - } - function newB() public payable returns(address){ - B bAddress=new B(); - a= address(bAddress); - return a; - - } - - } - -contract B{ - constructor() public payable {} - fallback() external payable {} - function kill(address payable toAddress) payable public{ - selfdestruct(toAddress); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken001.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken001.sol deleted file mode 100644 index ea28f4a62b6..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken001.sol +++ /dev/null @@ -1,30 +0,0 @@ - - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken002.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken002.sol deleted file mode 100644 index ea28f4a62b6..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken002.sol +++ /dev/null @@ -1,30 +0,0 @@ - - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken003.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken003.sol deleted file mode 100644 index 863429fc4f8..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken003.sol +++ /dev/null @@ -1,16 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken005.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken005.sol deleted file mode 100644 index 863429fc4f8..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken005.sol +++ /dev/null @@ -1,16 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken011.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken011.sol deleted file mode 100644 index 43e4010ec3f..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken011.sol +++ /dev/null @@ -1,35 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - fallback() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken012.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken012.sol deleted file mode 100644 index ab0c19767e7..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken012.sol +++ /dev/null @@ -1,26 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken014.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken014.sol deleted file mode 100644 index 589406c47c6..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken014.sol +++ /dev/null @@ -1,34 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - fallback() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken018.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken018.sol deleted file mode 100644 index ab0c19767e7..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken018.sol +++ /dev/null @@ -1,26 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken023.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken023.sol deleted file mode 100644 index 070acb201ff..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken023.sol +++ /dev/null @@ -1,26 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - toAddress.transferToken(amount,id); - } - } - -contract B{ - uint256 public flag = 0; - constructor() public payable {} - fallback() external { - flag = 1; -} - -} - -contract C{ - uint256 public flag = 0; - constructor() public payable {} - fallback() external payable { - //flag = 1; -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken026.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken026.sol deleted file mode 100644 index 5464265d81f..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken026.sol +++ /dev/null @@ -1,31 +0,0 @@ - - -contract token{ - constructor() payable public{} - fallback() payable external{} - function testInCall(address callBAddress,address callCAddress, address toAddress ,uint256 amount,trcToken id) payable public{ - //callBAddress.call(bytes4(keccak256("transC(address,address,uint256,trcToken)")),callCAddress,toAddress,amount,id); - callBAddress.call(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callCAddress,toAddress,amount,id)); - } - function testIndelegateCall(address callBddress,address callAddressC, address toAddress,uint256 amount, trcToken id) payable public{ - callBddress.delegatecall(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callAddressC,toAddress,amount,id)); - } - } - - - -contract B{ - constructor() public payable{} - fallback() external payable{} - function transC(address payable callCAddress,address payable toAddress,uint256 amount, trcToken id) payable public{ - callCAddress.call(abi.encodeWithSignature("trans(address,uint256,trcToken)",toAddress,amount,id)); - } -} -contract C{ - constructor() payable public{} - fallback() payable external{} - function trans(address payable toAddress,uint256 amount, trcToken id) payable public{ - toAddress.transferToken(amount,id); - } - -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken027.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken027.sol deleted file mode 100644 index e7d6ee768f3..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken027.sol +++ /dev/null @@ -1,30 +0,0 @@ - - -contract token{ - constructor() payable public{} - fallback() payable external{} - function testInCall(address callBAddress,address callCAddress, address toAddress ,uint256 amount,trcToken id) payable public{ - callBAddress.call(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callCAddress,toAddress,amount,id)); - } - function testIndelegateCall(address callBddress,address callAddressC, address toAddress,uint256 amount, trcToken id) payable public{ - callBddress.delegatecall(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callAddressC,toAddress,amount,id)); - } - } - - - -contract B{ - constructor() public payable{} - fallback() external payable{} - function transC(address callCAddress,address toAddress,uint256 amount, trcToken id) payable public{ - callCAddress.call(abi.encodeWithSignature("trans(address,uint256,trcToken)",toAddress,amount,id)); - } -} -contract C{ - constructor() payable public{} - fallback() payable external{} - function trans(address payable toAddress,uint256 amount, trcToken id) payable public{ - toAddress.transferToken(amount,id); - } - -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken028.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken028.sol deleted file mode 100644 index 0f27d89c819..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken028.sol +++ /dev/null @@ -1,25 +0,0 @@ - - -contract token{ - uint256 public a=1; - constructor() public payable{} - function tokenBalanceWithSameName(trcToken id) public payable{ - B b= new B(); - a= b.tokenBalance(id); - } - function getA() public returns(uint256){ - return a; - } -} - - -contract B{ - uint256 public flag =0; - constructor() public payable{} - fallback() external payable{} - function tokenBalance(trcToken id) payable public returns(uint256){ - flag =9; - return flag; - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken029.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken029.sol deleted file mode 100644 index 8480cf6f19d..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken029.sol +++ /dev/null @@ -1,24 +0,0 @@ - - -contract token{ - address public a; - constructor() public payable{} - function transferTokenWithSameName(trcToken id,uint256 amount) public payable{ - B b= new B(); - b.transferToken(amount,id); - a= address(b); - } -} - - -contract B{ - uint256 public flag =0; - constructor() public payable{} - fallback() external payable{} - function transferToken(uint256 amount, trcToken id) payable public returns(bool){ - flag =9; - } - function getFlag() public view returns (uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken030.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken030.sol deleted file mode 100644 index 06b8201979c..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken030.sol +++ /dev/null @@ -1,17 +0,0 @@ - - contract token{ - constructor() public payable{} - - // 4)suicide也会转移token - // 所有token,trx均被转移到toAddress, - // 若toAddress为合约地址本身,则所有token,trx均被烧掉进黑洞 - function kill(address payable toAddress) payable public{ - selfdestruct(toAddress); - } - - } - -contract B{ - constructor() public payable {} - fallback() external payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken031.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken031.sol deleted file mode 100644 index 65ec394e8da..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken031.sol +++ /dev/null @@ -1,18 +0,0 @@ - - - contract token{ - constructor() public payable{} - - // 4)suicide也会转移token - // 所有token,trx均被转移到toAddress, - // 若toAddress为合约地址本身,则所有token,trx均被烧掉进黑洞 - function kill(address payable toAddress) payable public{ - selfdestruct(toAddress); - } - - } - -contract B{ - constructor() public payable {} - fallback() external payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken034.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken034.sol deleted file mode 100644 index 32c55f8c84b..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken034.sol +++ /dev/null @@ -1,25 +0,0 @@ - - - contract token{ - - constructor() public payable {} - - // 2. 异常测试 - // 1)revert, 金额回退 - function failTransferTokenRevert(address payable toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - require(1==2); - } - - // 2)Error, 金额回退, fee limit 扣光 - function failTransferTokenError(address payable toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - assert(1==2); - } - - } - contract B{ - uint256 public flag = 0; - constructor() public payable {} - fallback() external payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken035.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken035.sol deleted file mode 100644 index ca45dde790d..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken035.sol +++ /dev/null @@ -1,24 +0,0 @@ - - - contract token{ - constructor() public payable {} - - // 2. 异常测试 - // 1)revert, 金额回退 - function failTransferTokenRevert(address payable toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - require(1==2); - } - - // 2)Error, 金额回退, fee limit 扣光 - function failTransferTokenError(address payable toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - assert(1==2); - } - - } - contract B{ - uint256 public flag = 0; - constructor() public payable {} - fallback() external payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036.sol deleted file mode 100644 index c1da2f7555e..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036.sol +++ /dev/null @@ -1,52 +0,0 @@ - -contract IllegalDecorate { -constructor() payable public{} -fallback() payable external{} -event log(uint256); -function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public payable { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate1 { -constructor() payable public{} -fallback() payable external{} -event log(uint256); -function transferTokenWithConstant(address payable toAddress, uint256 tokenValue) public payable { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate2 { -constructor() payable public{} -fallback() payable external{} -event log(uint256); -function transferTokenWithView(address payable toAddress, uint256 tokenValue) public payable { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate3 { -event log(uint256); -constructor() payable public{} -fallback() payable external{} -function transferTokenWithOutPayable(address payable toAddress, uint256 tokenValue) public { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_1.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_1.sol deleted file mode 100644 index 327ab5a756e..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_1.sol +++ /dev/null @@ -1,13 +0,0 @@ - -contract IllegalDecorate { -constructor() payable public{} -fallback() payable external{} -event log(uint256); -function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public pure { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_2.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_2.sol deleted file mode 100644 index 817a96e3c80..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_2.sol +++ /dev/null @@ -1,13 +0,0 @@ - -contract IllegalDecorate { -constructor() payable public{} -fallback() payable external{} -event log(uint256); -function transferTokenWithConstant(address toAddress, uint256 tokenValue) public constant { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_3.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_3.sol deleted file mode 100644 index 67400c2e8ad..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_3.sol +++ /dev/null @@ -1,13 +0,0 @@ - -contract IllegalDecorate { -constructor() payable public{} -fallback() payable external{} -event log(uint256); -function transferTokenWithView(address payable toAddress, uint256 tokenValue) public view { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_4.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_4.sol deleted file mode 100644 index cbaca0d4b38..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_4.sol +++ /dev/null @@ -1,13 +0,0 @@ - -contract IllegalDecorate { -event log(uint256); -constructor() payable public{} -fallback() payable external{} -function transferTokenWithOutPayable(address payable toAddress, uint256 tokenValue) public { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_old.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_old.sol deleted file mode 100644 index 1f03afb7636..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken036_old.sol +++ /dev/null @@ -1,41 +0,0 @@ - - - -contract IllegalDecorate1 { -constructor() payable public{} -fallback() payable public{} -event log(uint256); -function transferTokenWithConstant(address toAddress, uint256 tokenValue) public constant { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate2 { -constructor() payable public{} -fallback() payable public{} -event log(uint256); -function transferTokenWithView(address toAddress, uint256 tokenValue) public view { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate3 { -event log(uint256); -constructor() payable public{} -fallback() payable public{} -function transferTokenWithOutPayable(address toAddress, uint256 tokenValue) public { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken037.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken037.sol deleted file mode 100644 index 7cdd91702e8..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken037.sol +++ /dev/null @@ -1,24 +0,0 @@ - - -contract transferTrc10 { - function receive(address payable rec) public payable { - uint256 aamount=address(this).tokenBalance(msg.tokenid); - uint256 bamount=rec.tokenBalance(msg.tokenid); - require(msg.tokenvalue==aamount); - require(aamount==msg.tokenvalue); - rec.transferToken(aamount,msg.tokenid); - require(0==address(this).tokenBalance(msg.tokenid)); - require(bamount+aamount==rec.tokenBalance(msg.tokenid)); - (bool success, bytes memory data) =rec.call(abi.encodeWithSignature("checkTrc10(uint256,trcToken,uint256)",bamount+aamount,msg.tokenid,0)); - require(success); - - } -} - -contract receiveTrc10 { - fallback() external payable {} - function checkTrc10(uint256 amount,trcToken tid,uint256 meamount) public{ - require(amount==address(this).tokenBalance(tid)); - require(meamount==msg.sender.tokenBalance(tid)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken038.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken038.sol deleted file mode 100644 index eeb5ae744cf..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken038.sol +++ /dev/null @@ -1,24 +0,0 @@ - - -contract transferTrc10 { - function receive(address payable rec) public payable { - uint256 aamount=address(this).tokenBalance(msg.tokenid); - uint256 bamount=rec.tokenBalance(msg.tokenid); - require(msg.tokenvalue==aamount); - require(aamount==msg.tokenvalue); - rec.transferToken(aamount,msg.tokenid); - //require(rec.call(abi.encode(bytes4(keccak256("AssertError()"))))); - (bool suc, bytes memory data) = rec.call(abi.encodeWithSignature("AssertError()")); - require(suc); - require(aamount==address(this).tokenBalance(msg.tokenid)); - require(bamount==rec.tokenBalance(msg.tokenid)); - } -} - -contract receiveTrc10 { - fallback() external payable { - } - function AssertError() public{ - assert(1==2); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken039.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken039.sol deleted file mode 100644 index ebf6fb932ed..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken039.sol +++ /dev/null @@ -1,44 +0,0 @@ - -/* - * 1. caller账户issue一个token - * 2. caller部署proxy, 传入1000 token,1000 trx - * 3. caller部署A - * 4. caller部署B - * 5. caller调用proxy中upgradetTo函数,传入A的地址 - * 6. caller调用proxy中不存在的trans(uint256,address,trcToken)函数,注意这时trcToken是无意义的,但也带上tokenid。address是任意另外某账户的地址 - * 7. 可以看到目标地址trx增长5,caller账户trx减少5 - * 8. caller调用proxy中upgradeTo函数,传入B的地址 - * 9. caller调用proxy中不存在的trans(uint256,address,trcToken)函数。 - * 10. 可以看到目标地址token增长5,caller账户token减少5 -*/ -contract Proxy { - constructor() payable public{} - address public implementation; - function upgradeTo(address _address) public { - implementation = _address; - } - fallback() payable external{ - address addr = implementation; - require(addr != address(0)); - assembly { - let freememstart := mload(0x40) - calldatacopy(freememstart, 0, calldatasize()) - let success := delegatecall(not(0), addr, freememstart, calldatasize(), freememstart, 0) - returndatacopy(freememstart, 0, returndatasize()) - switch success - case 0 { revert(freememstart, returndatasize()) } - default { return(freememstart, returndatasize()) } - } - } -} - -contract A { - function trans(uint256 amount, address payable toAddress, trcToken id) payable public { - toAddress.transfer(amount); - } -} -contract B{ - function trans(uint256 amount, address payable toAddress, trcToken id) payable public { - toAddress.transferToken(amount,id); - } -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken041.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken041.sol deleted file mode 100644 index 6284253d1d5..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken041.sol +++ /dev/null @@ -1,20 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } - -contract B{ - uint256 public flag = 0; - constructor() public payable {} - fallback() external payable {} - - function setFlag() public payable{ - flag = 1; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken043.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken043.sol deleted file mode 100644 index 43e4010ec3f..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken043.sol +++ /dev/null @@ -1,35 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - fallback() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken048.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken048.sol deleted file mode 100644 index e705f696c1d..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken048.sol +++ /dev/null @@ -1,14 +0,0 @@ - - - contract Test { - event log(uint256); - function testMsgTokenValue() payable public returns(uint256 value) { - emit log(msg.tokenvalue); - return msg.tokenvalue; - } - - function testMsgValue() payable public returns(uint256 value) { - emit log(msg.value); - return msg.value; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken049.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken049.sol deleted file mode 100644 index d40480720df..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken049.sol +++ /dev/null @@ -1,9 +0,0 @@ - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken050.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken050.sol deleted file mode 100644 index 6bc6d956898..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken050.sol +++ /dev/null @@ -1,10 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken051.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken051.sol deleted file mode 100644 index 493016b777f..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken051.sol +++ /dev/null @@ -1,11 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - fallback() external payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken052.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken052.sol deleted file mode 100644 index 6bc6d956898..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken052.sol +++ /dev/null @@ -1,10 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken054.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken054.sol deleted file mode 100644 index 863429fc4f8..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken054.sol +++ /dev/null @@ -1,16 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken055.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken055.sol deleted file mode 100644 index 863429fc4f8..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken055.sol +++ /dev/null @@ -1,16 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken060.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken060.sol deleted file mode 100644 index ea28f4a62b6..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken060.sol +++ /dev/null @@ -1,30 +0,0 @@ - - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken061.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken061.sol deleted file mode 100644 index ea28f4a62b6..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken061.sol +++ /dev/null @@ -1,30 +0,0 @@ - - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken064.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken064.sol deleted file mode 100644 index 43e0da8a510..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken064.sol +++ /dev/null @@ -1,49 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } - function transferTokenTestValueMaxBigInteger(address payable toAddress) payable public { - toAddress.transferToken(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0); - } - function transferTokenTestValueOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(9223372036854775808, 1000001); - } - function transferTokenTestValueMaxLong(address payable toAddress) payable public { - toAddress.transferToken(9223372036854775807, 1000001); - } - function transferTokenTestValue0IdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(0, 9223372036854775809); - } -} - - - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - fallback() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken066.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken066.sol deleted file mode 100644 index 43e4010ec3f..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken066.sol +++ /dev/null @@ -1,35 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - fallback() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken067.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken067.sol deleted file mode 100644 index 43e4010ec3f..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken067.sol +++ /dev/null @@ -1,35 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - fallback() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken073.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken073.sol deleted file mode 100644 index a9ee8ea412b..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken073.sol +++ /dev/null @@ -1,16 +0,0 @@ - -contract Dest { - event logFallback(uint256 indexed, uint256 indexed, uint256 indexed); - event logGetToken(uint256 indexed, uint256 indexed, uint256 indexed, uint256); - - - constructor() payable public {} - - function getToken(trcToken tokenId) payable public{ - emit logGetToken(msg.sender.tokenBalance(tokenId), msg.tokenid, msg.tokenvalue, msg.value); - } - - fallback() payable external{ - emit logFallback(msg.tokenid, msg.tokenvalue, msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken075.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken075.sol deleted file mode 100644 index 9f201900295..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken075.sol +++ /dev/null @@ -1,26 +0,0 @@ - - -contract Dest { - event logFallback(uint256 indexed, uint256 indexed, uint256 indexed); - event logGetToken(uint256 indexed, uint256 indexed, uint256 indexed, uint256); - - constructor() payable public {} - - function getToken(trcToken tokenId) payable public{ - emit logGetToken(msg.sender.tokenBalance(tokenId), msg.tokenid, msg.tokenvalue, msg.value); - } - - function getTokenLongMin() payable public{ - // long.min - 1000020 - emit logGetToken(msg.sender.tokenBalance(trcToken(-9223372036855775828)), msg.tokenid, msg.tokenvalue, msg.value); - } - - function getTokenLongMax() payable public{ - // long.max + 1000020 - emit logGetToken(msg.sender.tokenBalance(trcToken(9223372036855775827)), msg.tokenid, msg.tokenvalue, msg.value); - } - - fallback() payable external{ - emit logFallback(msg.tokenid, msg.tokenvalue, msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken076.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken076.sol deleted file mode 100644 index a9decbee320..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken076.sol +++ /dev/null @@ -1,19 +0,0 @@ - -contract Test { - address public origin; - address public sender; - bool public result1; - bool public result2; - function test() external { - origin = tx.origin; - sender = msg.sender; - result1 = msg.sender == tx.origin; // true - result2 = origin == sender; // true - } -function getResult1() public returns(bool){ - return result1; -} -function getResult2() public returns(bool){ - return result2; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken077.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken077.sol deleted file mode 100644 index aeecf9cb9a5..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken077.sol +++ /dev/null @@ -1,11 +0,0 @@ - - -contract trcToken077 { -function addressTest() public returns(bytes32 addressValue) { - assembly{ - let x := mload(0x40) //Find empty storage location using "free memory pointer" - mstore(x,address) //Place current contract address - addressValue := mload(x) - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken078.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken078.sol deleted file mode 100644 index 02ba4a79699..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken078.sol +++ /dev/null @@ -1,35 +0,0 @@ - -contract callerContract { - constructor() public payable{} - fallback() external payable{} - function sendToB(address called_address, address c) public payable{ - called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); - } - function sendToB2(address called_address,address c) public payable{ - called_address.call(abi.encodeWithSignature("transferTo(address)",c)); - } - function sendToB3(address called_address,address c) public payable{ - called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); - } -} - contract calledContract { - fallback() external payable{} - constructor() public payable {} - function transferTo(address payable toAddress)public payable{ - toAddress.transfer(5); - } - - function setIinC(address c) public payable{ - c.call.value(5)(abi.encode(bytes4(keccak256("setI()")))); - } - - } - contract c{ - address public origin; - address public sender; - constructor() public payable{} - event log(address,address); - fallback() payable external{ - emit log(tx.origin,msg.sender); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken079.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken079.sol deleted file mode 100644 index 863429fc4f8..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken079.sol +++ /dev/null @@ -1,16 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken080.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken080.sol deleted file mode 100644 index 2d2688b74a4..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcToken080.sol +++ /dev/null @@ -1,30 +0,0 @@ - - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - fallback() external payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractTrcTokenToOther.sol b/framework/src/test/resources/soliditycode_0.6.12/contractTrcTokenToOther.sol deleted file mode 100644 index 8e926d3ba17..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractTrcTokenToOther.sol +++ /dev/null @@ -1,44 +0,0 @@ - - -contract ConvertType { - -constructor() payable public{} - -fallback() payable external{} - -//function trcTokenOnStorage(trcToken storage token) internal { // ERROR: Data location can only be specified for array, struct or mapping types, but "storage" was given. -//} - -function trcTokenToString(trcToken token) public pure returns(string memory s){ -// s = token; // ERROR -// s = string(token); // ERROR -} - -function trcTokenToUint256(trcToken token) public pure returns(uint256 r){ -uint256 u = token; // OK -uint256 u2 = uint256(token); // OK -r = u2; -} - -function trcTokenToAddress(trcToken token) public pure returns(address r){ -//r = token; // ERROR -token = 0x1234567812345678123456781234567812345678123456781234567812345678; -address a2 = address(token); // OK -r = a2; -} - -function trcTokenToBytes(trcToken token) public pure returns(bytes memory r){ -//r = token; // ERROR -// r = bytes(token); // ERROR -} - -function trcTokenToBytes32(trcToken token) public pure returns(bytes32 r){ -// r = token; // ERROR -bytes32 b2 = bytes32(token); // OK -r = b2; -} - -function trcTokenToArray(trcToken token) public pure returns(uint[] memory r){ -//r = token; // ERROR -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/contractUnknownException.sol b/framework/src/test/resources/soliditycode_0.6.12/contractUnknownException.sol deleted file mode 100644 index 4fd9c64be72..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/contractUnknownException.sol +++ /dev/null @@ -1,64 +0,0 @@ - -contract testA { - constructor() public payable { - A a = (new A).value(10)(); - a.fun(); - } -} - -contract testB { - constructor() public payable { - B b = (new B).value(10)(); - b.fun(); - } -} - - -contract testC { - constructor() public payable{ - C c = (new C).value(10)(); - c.fun(); - } -} - -contract testD { - constructor() public payable{ - D d = (new D).value(10)(); - d.fun(); - } -} - - -contract A { - constructor() public payable{ - selfdestruct(msg.sender); - } - function fun() public { - } - -} - -contract B { - constructor() public payable { - revert(); - } - function fun() public { - } -} - - -contract C { - constructor() public payable { - assert(1==2); - } - function fun() public { - } -} - -contract D { - constructor() public payable { - require(1==2); - } - function fun() public { - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/create2CallContract.sol b/framework/src/test/resources/soliditycode_0.6.12/create2CallContract.sol deleted file mode 100644 index 046706ebd9e..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/create2CallContract.sol +++ /dev/null @@ -1,37 +0,0 @@ -contract callerContract { - constructor() payable public{} - fallback() payable external{} - function delegateCallCreate2(address called_address, bytes memory code, uint256 salt) public { - called_address.delegatecall(abi.encodeWithSignature("deploy(bytes,uint256)",code,salt)); - } - function callCreate2(address called_address,bytes memory code, uint256 salt) public returns(bool,bytes memory){ - return called_address.call(abi.encodeWithSignature("deploy(bytes,uint256)",code,salt)); - } -} - - -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - -contract TestConstract { - uint public i; - constructor () public { - } - function plusOne() public returns(uint){ - i++; - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/create2Istanbul.sol b/framework/src/test/resources/soliditycode_0.6.12/create2Istanbul.sol deleted file mode 100644 index c2ef8f3236b..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/create2Istanbul.sol +++ /dev/null @@ -1,28 +0,0 @@ - - -contract create2Istanbul { - function deploy(bytes memory code, uint256 salt) public returns(address) { - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - - } - return addr; - } - - // prefix in main net is 0x41, testnet config is 0xa0 - function get(bytes1 prefix, bytes calldata code, uint256 salt) external view returns(address) { - //bytes32 hash = keccak256(abi.encodePacked(bytes1(0x41),address(this), salt, keccak256(code))); - bytes32 hash = keccak256(abi.encodePacked(prefix,address(this), salt, keccak256(code))); - address addr = address(uint160(uint256(hash))); - return addr; - } - -} - -contract B { - constructor() public payable{} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/create2contract.sol b/framework/src/test/resources/soliditycode_0.6.12/create2contract.sol deleted file mode 100644 index 0171f4d5486..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/create2contract.sol +++ /dev/null @@ -1,52 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } - - event Deployed(address addr, bytes32 salt, address sender); - function deploy(bytes memory code, bytes32 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - -contract FactoryBytes { - event Deployed(address addr, bytes32 salt, address sender); - function deploy(bytes memory code, bytes32 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - -contract TestConstract { - uint public i; - constructor () public { - } - function plusOne() public returns(uint){ - i++; - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/create2contract22.sol b/framework/src/test/resources/soliditycode_0.6.12/create2contract22.sol deleted file mode 100644 index c33cb08edc3..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/create2contract22.sol +++ /dev/null @@ -1,109 +0,0 @@ -contract Factory { - event Deployed(address addr, trcToken salt, address sender); - event Deployed1(address addr, uint8 salt, address sender); - event Deployed2(address addr, address salt, address sender); - event Deployed3(address addr, string salt, address sender); - - - function deploy(bytes memory code, trcToken salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } - - function deploy1(bytes memory code, uint8 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed1(addr, salt, msg.sender); - return addr; - } - - function deploy2(bytes memory code, address salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed2(addr, salt, msg.sender); - return addr; - } - - function deploy3(bytes memory code, string memory salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed3(addr, salt, msg.sender); - return addr; - } - -} - - -contract TestConstract { - uint public i=1; - function testTransfer(uint256 i) payable public{ - msg.sender.transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} - -contract TestConstract1 { - uint public i=2; - function testTransfer(uint256 i) payable public{ - msg.sender.transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} - -contract TestConstract2 { - uint public i=3; - function testTransfer(uint256 i) payable public{ - msg.sender.transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} - -contract TestConstract3 { - uint public i=4; - function testTransfer(uint256 i) payable public{ - msg.sender.transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/create2contractn.sol b/framework/src/test/resources/soliditycode_0.6.12/create2contractn.sol deleted file mode 100644 index e0e3ae64c16..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/create2contractn.sol +++ /dev/null @@ -1,29 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract TestConstract { - uint public i=1; - function testTransfer(uint256 i) payable public{ - msg.sender.transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/create2contractn2.sol b/framework/src/test/resources/soliditycode_0.6.12/create2contractn2.sol deleted file mode 100644 index 626988c4e04..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/create2contractn2.sol +++ /dev/null @@ -1,26 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract TestConstract { - uint public i=1; - function set() payable public { - i=5; - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/demo.sol b/framework/src/test/resources/soliditycode_0.6.12/demo.sol deleted file mode 100644 index 06bf15387fc..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/demo.sol +++ /dev/null @@ -1,73 +0,0 @@ - - - contract tokenTest{ - uint256 codesize; - constructor() payable public{ - uint256 m; - address addr = address(this); - assembly { - m := extcodesize(addr) - } - codesize = m; - } - - // positive case - function pulsone() public payable{ - uint256 j = 0; - uint i = 100; - for (; i < i; i++) { - j++; - } - } - - - function getCodeSize() public returns (uint256){ - return codesize; - } - - } - - contract confirmTest{ - - uint256 codesize; - constructor() payable public{ - uint256 m; - address addr = address(this); - assembly { - m := extcodesize(addr) - - } - codesize = m; - } - - function getCodeSize() public returns (uint256){ - return codesize; - } - - function confirm(address addr) public returns (uint256){ - uint256 j; - assembly { - j := extcodesize(addr) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - return j; - } - - function at(address _addr) public returns (bytes memory o_code) { - assembly { - // retrieve the size of the code, this needs assembly - let size := extcodesize(_addr) - // allocate output byte array - this could also be done without assembly - // by using o_code = new bytes(size) - o_code := mload(0x40) - // new "memory end" including padding - mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) - // store length in memory - mstore(o_code, size) - // actually retrieve the code, this needs assembly - extcodecopy(_addr, add(o_code, 0x20), 0, size) - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/enumAndStruct.sol b/framework/src/test/resources/soliditycode_0.6.12/enumAndStruct.sol deleted file mode 100644 index 836a4ac850e..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/enumAndStruct.sol +++ /dev/null @@ -1,43 +0,0 @@ - - -struct S_out { -uint x; -} - -enum ErrorType { -Revert_Error, //0 -RevertWithMsg_Error, //1 -Require_Error, //2 -RequirewithMsg_Error, //3 -Assert_Error, //4 -Tansfer_Error, //5 -Send_Error, //6 -Math_Error, //7 -ArrayOverFlow_Error //8 -} - -contract enumAndStructTest { - -struct S_inner { -int x; -} - -enum ErrorType_inner { -Revert_Error, //0 -RevertWithMsg_Error, //1 -Require_Error, //2 -RequirewithMsg_Error, //3 -Assert_Error, //4 -Tansfer_Error, //5 -Send_Error, //6 -Math_Error, //7 -ArrayOverFlow_Error //8 -} - -function getvalue() public returns(uint) { - require(ErrorType.Require_Error == ErrorType(2)); - S_out memory s = S_out(1); - return s.x; -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/event001.sol b/framework/src/test/resources/soliditycode_0.6.12/event001.sol deleted file mode 100644 index 7662df3a5c6..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/event001.sol +++ /dev/null @@ -1,10 +0,0 @@ -contract Event { - event xixi(uint256 id) ; - event log2(uint256,uint256,uint256); - constructor() public payable{} - function messageI() payable public returns (uint ret) { - //emit log2(1,2,3); - emit xixi(1); - return 1; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/event002.sol b/framework/src/test/resources/soliditycode_0.6.12/event002.sol deleted file mode 100644 index a61f834e1b5..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/event002.sol +++ /dev/null @@ -1,52 +0,0 @@ - - -contract Event { - - event _0(); - event a_0() anonymous; - event a_4i(uint256 indexed x1, uint256 indexed x2 , uint256 indexed x3, uint256 indexed x4, uint256 x5)anonymous ; - event _3i(uint256 x1, uint256 indexed x2 , uint256 indexed x3, uint256 x4, uint256 x5) ; - event _1i(uint256 indexed x1, uint256, uint256 indexed, uint256 x4) ; - event a_1i(uint256) anonymous; - event _ai(uint8[2], uint8) ; - event a_ai(uint8[2], uint8) anonymous; - event _a1i(uint8[2] indexed, uint8) ; - event a_a1i(uint8[2] indexed, uint8) anonymous; - - constructor () public { - // emit a_0(); - // emit a_1i(123); - // emit a_4i(1,2,3,5,16); - // emit _0(); - emit _3i(1,2,3,5,16); - // emit _1i(1,2,3,5); - // emit _ai([1,2], 3); - // emit a_ai([3,4], 5); - // emit _a1i([1,2], 3); - // emit a_a1i([3,4], 5); - } - - function e() public { - emit _1i(1,2,3,4); - } - - function l() public { - emit a_1i(1); - } - - function k() public{ - emit a_4i(2,3,4,5,17); - emit _3i(2,3,4,5,16); - emit _1i(2,3,4,5); - emit a_1i(128); - emit _0(); - emit a_0(); - //selfdestruct(msg.sender); - //emit a_4i(1,2,3,5,16); - //emit _3i(1,2,3,5,16); - //emit _1i(1,2,3,5); - //emit a_1i(123); - //emit _0(); - //emit a_0(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/extCodeHash.sol b/framework/src/test/resources/soliditycode_0.6.12/extCodeHash.sol deleted file mode 100644 index d6209770682..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/extCodeHash.sol +++ /dev/null @@ -1,13 +0,0 @@ -contract TestExtCodeHash { - - function getCodeHashByAddr(address _addr) public returns (bytes32 _hash) { - assembly { - _hash := extcodehash(_addr) - } - } - function getCodeHashByUint(uint256 _addr) public returns (bytes32 _hash) { - assembly { - _hash := extcodehash(_addr) - } - } -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/extCodeHash11.sol b/framework/src/test/resources/soliditycode_0.6.12/extCodeHash11.sol deleted file mode 100644 index ad59f6cce1c..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/extCodeHash11.sol +++ /dev/null @@ -1,103 +0,0 @@ -contract Counter { -uint count = 0; -address payable owner; -event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); -constructor() public{ -owner = msg.sender; -} -function getCodeHashByAddr() public returns (bytes32 _hashBefore, bytes32 _hashAfter) { -address addr = address(this); -assembly { -_hashBefore := extcodehash(addr) -} -if (owner == msg.sender) { -selfdestruct(owner); -} -assembly { -_hashAfter := extcodehash(addr) -} -revert(); -emit LogResult(_hashBefore, _hashAfter); -} -} - -contract Counter1 { -uint count = 0; -address payable owner; -event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); -constructor() public{ -owner = msg.sender; -} -function getCodeHashByAddr() public returns (bytes32 _hashBefore, bytes32 _hashAfter) { -address addr = address(this); -assembly { -_hashBefore := extcodehash(addr) -} -if (owner == msg.sender) { -selfdestruct(owner); -} -assembly { -_hashAfter := extcodehash(addr) -} - -emit LogResult(_hashBefore, _hashAfter); -} -} - - -contract Counter2 { -uint count = 0; -address payable owner; -event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); -constructor() public{ -owner = msg.sender; -} -function getCodeHashByAddr(address c) public returns (bytes32 _hashBefore, bytes32 _hashAfter) { - TestConstract t=new TestConstract(); -address addr = address(t); -assembly { -_hashBefore := extcodehash(addr) -} - addr.call(abi.encodeWithSignature("testSuicideNonexistentTarget(address)",c)); - - -assembly { -_hashAfter := extcodehash(addr) -} - -emit LogResult(_hashBefore, _hashAfter); -} -} - - -contract Counter3 { -uint count = 0; -address payable owner; -event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); -constructor() public{ -owner = msg.sender; -} -function getCodeHashByAddr(address c) public returns (bytes32 _hashBefore, bytes32 _hashAfter) { - TestConstract t=new TestConstract(); -address addr = address(t); -assembly { -_hashBefore := extcodehash(addr) -} -if (owner == msg.sender) { -selfdestruct(owner); -} - -assembly { -_hashAfter := extcodehash(addr) -} - -emit LogResult(_hashBefore, _hashAfter); -} -} - -contract TestConstract { - uint public i=1; - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/extCodeHashConstruct.sol b/framework/src/test/resources/soliditycode_0.6.12/extCodeHashConstruct.sol deleted file mode 100644 index 6bb91b3d3b1..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/extCodeHashConstruct.sol +++ /dev/null @@ -1,14 +0,0 @@ -contract CounterConstruct { - uint count = 0; - address payable owner; - event LogResult(bytes32 _hashBefore); - constructor() public{ - owner = msg.sender; - address addr = address(this); - bytes32 _hashBefore; - assembly { - _hashBefore := extcodehash(addr) - } - emit LogResult(_hashBefore); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/extCodeHashStress.sol b/framework/src/test/resources/soliditycode_0.6.12/extCodeHashStress.sol deleted file mode 100644 index cf41f3c8106..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/extCodeHashStress.sol +++ /dev/null @@ -1,45 +0,0 @@ -contract Trigger { - function test(address addr) public returns(uint i) { - bytes32 hash; - while (gasleft() > 1000) { - assembly { - hash := extcodehash(addr) - } - i++; - } - } - - function test(address[] memory addrs) public returns(uint i) { - bytes32 hash; - uint i = 0; - for (; i < addrs.length; i++) { - address addr = addrs[i]; - assembly { - hash := extcodehash(addr) - } - } - return i; - } - } - - - - contract TriggerNormal { - function test(address addr) public returns(uint i) { - i = 0; - while (gasleft() > 100000) { - i++; - } - } - } - - contract TriggerNormal1 { - function test(address[] memory addrs) public returns(uint i) { - bytes32 hash; - uint i = 0; - for (; i < addrs.length; i++) { - address addr = addrs[i]; - addr.balance; - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/extCodeHashTestNoPayable.sol b/framework/src/test/resources/soliditycode_0.6.12/extCodeHashTestNoPayable.sol deleted file mode 100644 index c3a2ad8c6ae..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/extCodeHashTestNoPayable.sol +++ /dev/null @@ -1,8 +0,0 @@ -contract testConstantContract{ -uint256 public i; -function testNoPayable() public returns (uint256 z) { -i=1; -z=i; -return z; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/fallbackUpgrade.sol b/framework/src/test/resources/soliditycode_0.6.12/fallbackUpgrade.sol deleted file mode 100644 index f73140ad245..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/fallbackUpgrade.sol +++ /dev/null @@ -1,83 +0,0 @@ -contract Test0{ - event FuncCalled(bytes data,uint a); -} - -contract Test1 { - - event FuncCalled(string a); - fallback() external { - x = "fallback"; - emit FuncCalled(x); - } - string x; -} -//含有payable的fallback,无receice -contract Test2 { - - event FuncCalled(string data); - fallback() external payable{ - x = "fallback"; - emit FuncCalled(x); - } - string x; -} - -contract TestPayable { - event FuncCalled(string a); - - fallback() external payable { - x = "fallback"; - emit FuncCalled(x); - } - - receive() external payable { - x = "receive"; - emit FuncCalled(x); - } - string x; -} - -contract Caller { - function callTest0(Test0 test) public{ - (bool success,) = address(test).call(abi.encodeWithSignature("nonExistingFunction()")); - require(success); - } - function callTest1(address test) public returns (bool) { - (bool success,) = test.call(abi.encodeWithSignature("nonExistingFunction()")); - require(success); - (success,) = address(test).call(""); - require(success); - return true; - } - function callTest2(address test) public payable returns (bool) { - (bool success,) = test.call.value(1000)(abi.encodeWithSignature("nonExistingFunction()")); - require(success); - return true; - } - function callTestPayable1(TestPayable test) public payable returns (bool) { - (bool success,) = address(test).call(abi.encodeWithSignature("nonExistingFunction()")); - require(success); - (success,) = address(test).call(""); - require(success); - return true; - } -} - - -//contract Test0 { -// event FallbackCall(string data,bytes msg); -// //event FuncCalled(string a,bytes data); -// function() external payable{ -// x = "fallback"; -// emit FallbackCall(x,msg.data); -// } -// string x; -//} -//contract Caller{ -// function call(Test0 test) public payable returns(bool){ -// (bool success,) = address(test).call(abi.encodeWithSignature("nonExistingFunction()")); -// require(success); -// return true; -// } -//} - diff --git a/framework/src/test/resources/soliditycode_0.6.12/freezeContract001.sol b/framework/src/test/resources/soliditycode_0.6.12/freezeContract001.sol deleted file mode 100644 index 0ad8ed9f460..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/freezeContract001.sol +++ /dev/null @@ -1,63 +0,0 @@ - -contract TestFreeze { - constructor() public payable {} - - function freeze(address payable receiver, uint amount, uint res) external payable{ - receiver.freeze(amount, res); - } - - function unfreeze(address payable receiver, uint res) external { - receiver.unfreeze(res); - } - - function destroy(address payable inheritor) external { - selfdestruct(inheritor); - } - - function send(address payable A) external { - A.transfer(10); - } - - function send(address payable A, uint256 value) external { - A.transfer(value); - } - - function getExpireTime(address payable target, uint res) external view returns(uint) { - return target.freezeExpireTime(res); - } - - function deploy(uint256 salt) public returns(address){ - address addr; - bytes memory code = type(C).creationCode; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } - - function freezeAndSend(address payable receiver, uint amount, uint res) external { - receiver.transfer(amount); - receiver.freeze(amount, res); - } - - -} - - -contract C { - constructor() public payable {} - - function destroy(address payable inheritor) external { - selfdestruct(inheritor); - } -} - -contract D { - constructor() public payable { - msg.sender.freeze(msg.value, 1); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/getAddressChange.sol b/framework/src/test/resources/soliditycode_0.6.12/getAddressChange.sol deleted file mode 100644 index 2796da68770..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/getAddressChange.sol +++ /dev/null @@ -1,12 +0,0 @@ -contract getAddressChange { - constructor() public payable {} - // testaddress1函数新增了一个address属性。0.6.0之前 external函数可以通过address(x)来转化为地址,6.0将其禁止,可以通过函数address属性直接获取 - function testaddress1() public view returns(address) { - //return address(this.getamount); //0.6.0之前可以使用 - return this.getamount.address; //0.6.0 - - } - function getamount(address) external view returns(uint256) { - return address(this).balance; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/isSRCandidate.sol b/framework/src/test/resources/soliditycode_0.6.12/isSRCandidate.sol deleted file mode 100644 index e8e9b692dec..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/isSRCandidate.sol +++ /dev/null @@ -1,35 +0,0 @@ - - - -contract ContractB{ - address others; -} - -contract TestIsSRCandidate{ - - ContractB contractB = new ContractB(); - - function isSRCandidateTest(address addr) public view returns (bool) { - return address(addr).isSRCandidate; - } - - function zeroAddressTest() public view returns (bool) { - return address(0x0).isSRCandidate; - } - - function localContractAddrTest() public view returns (bool) { - return address(this).isSRCandidate; - } - - function otherContractAddrTest() public view returns (bool) { - return address(contractB).isSRCandidate; - } - - function nonpayableAddrTest(address addr) public view returns (bool) { - return addr.isSRCandidate; - } - - function payableAddrTest(address payable addr) public returns (bool) { - return addr.isSRCandidate; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/mappingGetter.sol b/framework/src/test/resources/soliditycode_0.6.12/mappingGetter.sol deleted file mode 100644 index dbd473717cb..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/mappingGetter.sol +++ /dev/null @@ -1,4 +0,0 @@ -contract mappingGetter { - mapping(bytes => uint256) public balances1; - mapping(string => uint256) public balances2; -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/multiValiSignPerformance01.sol b/framework/src/test/resources/soliditycode_0.6.12/multiValiSignPerformance01.sol deleted file mode 100644 index 74baa963366..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/multiValiSignPerformance01.sol +++ /dev/null @@ -1,37 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract ecrecoverValidateSign { - - using ECVerify for bytes32; - - function validateSign(bytes32 hash,bytes[] memory sig,address[] memory signer) public returns (bool) { - for(uint256 i=0;i=0.5.0 <0.7.0; - -contract A { - uint public x; - function setValue(uint _x) public { - x = _x; - } -} -contract B is A {} -contract C is A {} -// No explicit override required -contract D is B, C {} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/override003.sol b/framework/src/test/resources/soliditycode_0.6.12/override003.sol deleted file mode 100644 index 103133fc53c..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/override003.sol +++ /dev/null @@ -1,20 +0,0 @@ -pragma solidity ^0.6.0; -contract A { - uint public x; - function setValue(uint _x) public virtual { - x = _x; - } -} - -contract B { - uint public y; - function setValue(uint _y) public virtual { - y = _y; - } -} - -contract C is A, B { - function setValue(uint _x) public override(B,A) { - A.setValue(_x); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/override004.sol b/framework/src/test/resources/soliditycode_0.6.12/override004.sol deleted file mode 100644 index 1549d49b53f..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/override004.sol +++ /dev/null @@ -1,25 +0,0 @@ -pragma solidity >=0.5.0 <0.7.0; - -contract A { - uint public x = 4; - function setValue(uint _x) public notZero { - x = _x; - } - modifier notZero() virtual { - require(x >= 5,"x must >= 5"); - _; - } -} - -contract B is A { - function setValue2(uint _x) public { - x = _x; - } -} - -contract C is A,B { - modifier notZero override { - require(x >= 6,"x must >= 6"); - _; - } -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/override005.sol b/framework/src/test/resources/soliditycode_0.6.12/override005.sol deleted file mode 100644 index a8e44399ece..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/override005.sol +++ /dev/null @@ -1,39 +0,0 @@ -pragma solidity >= 0.6.0; - -contract Base { - enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } - ActionChoices public choice2 = ActionChoices.GoRight; - - function stopped() virtual external pure returns (bool) { - return true; - } - function i() virtual external pure returns (int) { - return 32482980; - } - function i2() virtual external pure returns (int) { - return -32482980; - } - function ui() virtual external pure returns (uint) { - return 23487820; - } - function origin() virtual external pure returns (address) { - return 0x3b0E4a6EdEE231CE0c3433F00F1bbc5FeD409c0B; - } - function b32() virtual external pure returns (bytes32) { - return 0xb55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd231050; - } - function choice() virtual external returns (ActionChoices) { - return choice2; - } -} - -contract Test is Base { - - bool override public stopped = false; - int override public i = 32482989; - int override public i2 = -32482989; - uint override public ui = 23487823; - address override public origin = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; - bytes32 override public b32 = 0xb55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105c; - ActionChoices override public choice = ActionChoices.SitStill; -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/overridePrivateFunction.sol b/framework/src/test/resources/soliditycode_0.6.12/overridePrivateFunction.sol deleted file mode 100644 index b0b4d679620..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/overridePrivateFunction.sol +++ /dev/null @@ -1,22 +0,0 @@ -pragma solidity ^0.5.17; - -contract A { - - function test() private pure returns(uint) { - return 1; - } - -} - -contract B is A { - - function basic() private pure returns(uint) { - return 2; - } - function testOverridePrivate() external payable returns(uint) { - return basic(); - } - - constructor() public payable {} -} - diff --git a/framework/src/test/resources/soliditycode_0.6.12/payable001.sol b/framework/src/test/resources/soliditycode_0.6.12/payable001.sol deleted file mode 100644 index 4fe7b20921f..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/payable001.sol +++ /dev/null @@ -1,31 +0,0 @@ - - - -contract A { - constructor() public payable{ - } - - fallback() external payable { - } -} - -contract PayableTest { - -address payable a1; -function receiveMoneyTransfer(address a, uint256 _x) public { -a1 = payable(a); -a1.transfer(_x); -} - -function receiveMoneySend(address a, uint256 x) public { -address payable a2 = payable(a); -a2.send(x); -} - -function receiveMoneyTransferWithContract(A PayableTest, uint256 x) public { -payable(address(PayableTest)).transfer(x); -} - -constructor() public payable{ -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/pedersenHash001.sol b/framework/src/test/resources/soliditycode_0.6.12/pedersenHash001.sol deleted file mode 100644 index 6cad7cb9855..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/pedersenHash001.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract pedersenHashTest { - - function test1() public returns (bool, bytes memory){ - bytes memory empty = ""; - return address(0x1000004).delegatecall(empty); - } - - function test2(bytes memory data) public returns (bool, bytes memory){ - return address(0x1000004).delegatecall(data); - } - - function test3(uint32 hash, bytes32 left, bytes32 right) public returns (bytes32){ - return pedersenHash(hash, left, right); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/pedersenHash002.sol b/framework/src/test/resources/soliditycode_0.6.12/pedersenHash002.sol deleted file mode 100644 index b0a78973ef2..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/pedersenHash002.sol +++ /dev/null @@ -1,320 +0,0 @@ -pragma experimental ABIEncoderV2; - -import "./SafeMath.sol"; - -abstract contract TokenTRC20 { - function transfer(address _to, uint256 _value) public virtual returns (bool success); - - function transferFrom(address _from, address _to, uint256 _value) public virtual returns (bool success); -} - -contract ShieldedTRC20 { - using SafeMath for uint256; - - uint256 public scalingFactor; // used when decimals of TRC20 token is too large. - uint256 public leafCount; - uint256 constant INT64_MAX = 2 ** 63 - 1; - bytes32 public latestRoot; - mapping(bytes32 => bytes32) public nullifiers; // store nullifiers of spent commitments - mapping(bytes32 => bytes32) public roots; // store history root - mapping(uint256 => bytes32) public tree; - mapping(bytes32 => bytes32) public noteCommitment; - bytes32[33] frontier; - bytes32[32] zeroes = [bytes32(0x0100000000000000000000000000000000000000000000000000000000000000), bytes32(0x817de36ab2d57feb077634bca77819c8e0bd298c04f6fed0e6a83cc1356ca155), bytes32(0xffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e34), bytes32(0xd8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c), bytes32(0xe110de65c907b9dea4ae0bd83a4b0a51bea175646a64c12b4c9f931b2cb31b49), bytes32(0x912d82b2c2bca231f71efcf61737fbf0a08befa0416215aeef53e8bb6d23390a), bytes32(0x8ac9cf9c391e3fd42891d27238a81a8a5c1d3a72b1bcbea8cf44a58ce7389613), bytes32(0xd6c639ac24b46bd19341c91b13fdcab31581ddaf7f1411336a271f3d0aa52813), bytes32(0x7b99abdc3730991cc9274727d7d82d28cb794edbc7034b4f0053ff7c4b680444), bytes32(0x43ff5457f13b926b61df552d4e402ee6dc1463f99a535f9a713439264d5b616b), bytes32(0xba49b659fbd0b7334211ea6a9d9df185c757e70aa81da562fb912b84f49bce72), bytes32(0x4777c8776a3b1e69b73a62fa701fa4f7a6282d9aee2c7a6b82e7937d7081c23c), bytes32(0xec677114c27206f5debc1c1ed66f95e2b1885da5b7be3d736b1de98579473048), bytes32(0x1b77dac4d24fb7258c3c528704c59430b630718bec486421837021cf75dab651), bytes32(0xbd74b25aacb92378a871bf27d225cfc26baca344a1ea35fdd94510f3d157082c), bytes32(0xd6acdedf95f608e09fa53fb43dcd0990475726c5131210c9e5caeab97f0e642f), bytes32(0x1ea6675f9551eeb9dfaaa9247bc9858270d3d3a4c5afa7177a984d5ed1be2451), bytes32(0x6edb16d01907b759977d7650dad7e3ec049af1a3d875380b697c862c9ec5d51c), bytes32(0xcd1c8dbf6e3acc7a80439bc4962cf25b9dce7c896f3a5bd70803fc5a0e33cf00), bytes32(0x6aca8448d8263e547d5ff2950e2ed3839e998d31cbc6ac9fd57bc6002b159216), bytes32(0x8d5fa43e5a10d11605ac7430ba1f5d81fb1b68d29a640405767749e841527673), bytes32(0x08eeab0c13abd6069e6310197bf80f9c1ea6de78fd19cbae24d4a520e6cf3023), bytes32(0x0769557bc682b1bf308646fd0b22e648e8b9e98f57e29f5af40f6edb833e2c49), bytes32(0x4c6937d78f42685f84b43ad3b7b00f81285662f85c6a68ef11d62ad1a3ee0850), bytes32(0xfee0e52802cb0c46b1eb4d376c62697f4759f6c8917fa352571202fd778fd712), bytes32(0x16d6252968971a83da8521d65382e61f0176646d771c91528e3276ee45383e4a), bytes32(0xd2e1642c9a462229289e5b0e3b7f9008e0301cbb93385ee0e21da2545073cb58), bytes32(0xa5122c08ff9c161d9ca6fc462073396c7d7d38e8ee48cdb3bea7e2230134ed6a), bytes32(0x28e7b841dcbc47cceb69d7cb8d94245fb7cb2ba3a7a6bc18f13f945f7dbd6e2a), bytes32(0xe1f34b034d4a3cd28557e2907ebf990c918f64ecb50a94f01d6fda5ca5c7ef72), bytes32(0x12935f14b676509b81eb49ef25f39269ed72309238b4c145803544b646dca62d), bytes32(0xb2eed031d4d6a4f02a097f80b54cc1541d4163c6b6f5971f88b6e41d35c53814)]; - address owner; - TokenTRC20 trc20Token; - - event MintNewLeaf(uint256 position, bytes32 cm, bytes32 cv, bytes32 epk, bytes32[21] c); - event TransferNewLeaf(uint256 position, bytes32 cm, bytes32 cv, bytes32 epk, bytes32[21] c); - event BurnNewLeaf(uint256 position, bytes32 cm, bytes32 cv, bytes32 epk, bytes32[21] c); - event TokenMint(address from, uint256 value); - event TokenBurn(address to, uint256 value, bytes32[3] ciphertext); - event NoteSpent(bytes32 nf); - - constructor (address trc20ContractAddress, uint256 scalingFactorExponent) public { - require(scalingFactorExponent < 77, "The scalingFactorExponent is out of range!"); - scalingFactor = 10 ** scalingFactorExponent; - owner = msg.sender; - trc20Token = TokenTRC20(trc20ContractAddress); - } - // output: cm, cv, epk, proof - function mint(uint256 rawValue, bytes32[9] calldata output, bytes32[2] calldata bindingSignature, bytes32[21] calldata c) external { - address sender = msg.sender; - // transfer the trc20Token from the sender to this contract - bool transferResult = trc20Token.transferFrom(sender, address(this), rawValue); - require(transferResult, "TransferFrom failed!"); - - require(noteCommitment[output[0]] == 0, "Duplicate noteCommitments!"); - uint64 value = rawValueToValue(rawValue); - bytes32 signHash = sha256(abi.encodePacked(address(this), value, output, c)); - (bytes32[] memory ret) = verifyMintProof(output, bindingSignature, value, signHash, frontier, leafCount); - uint256 result = uint256(ret[0]); - require(result == 1, "The proof and signature have not been verified by the contract!"); - - uint256 slot = uint256(ret[1]); - uint256 nodeIndex = leafCount + 2 ** 32 - 1; - tree[nodeIndex] = output[0]; - if (slot == 0) { - frontier[0] = output[0]; - } - for (uint256 i = 1; i < slot + 1; i++) { - nodeIndex = (nodeIndex - 1) / 2; - tree[nodeIndex] = ret[i + 1]; - if (i == slot) { - frontier[slot] = tree[nodeIndex]; - } - } - latestRoot = ret[slot + 2]; - roots[latestRoot] = latestRoot; - noteCommitment[output[0]] = output[0]; - leafCount ++; - - emit MintNewLeaf(leafCount - 1, output[0], output[1], output[2], c); - emit TokenMint(sender, rawValue); - } - //input: nf, anchor, cv, rk, proof - //output: cm, cv, epk, proof - function transfer(bytes32[10][] calldata input, bytes32[2][] calldata spendAuthoritySignature, bytes32[9][] calldata output, bytes32[2] calldata bindingSignature, bytes32[21][] calldata c) external { - require(input.length >= 1 && input.length <= 2, "Input number must be 1 or 2!"); - require(input.length == spendAuthoritySignature.length, "Input number must be equal to spendAuthoritySignature number!"); - require(output.length >= 1 && output.length <= 2, "Output number must be 1 or 2!"); - require(output.length == c.length, "Output number must be equal to c number!"); - - for (uint256 i = 0; i < input.length; i++) { - require(nullifiers[input[i][0]] == 0, "The note has already been spent!"); - require(roots[input[i][1]] != 0, "The anchor must exist!"); - } - for (uint256 i = 0; i < output.length; i++) { - require(noteCommitment[output[i][0]] == 0, "Duplicate noteCommitment!"); - } - - bytes32 signHash = sha256(abi.encodePacked(address(this), input, output, c)); - (bytes32[] memory ret) = verifyTransferProof(input, spendAuthoritySignature, output, bindingSignature, signHash, 0, frontier, leafCount); - uint256 result = uint256(ret[0]); - require(result == 1, "The proof and signature have not been verified by the contract!"); - - uint256 offset = 1; - //ret offset - for (uint256 i = 0; i < output.length; i++) { - uint256 slot = uint256(ret[offset++]); - uint256 nodeIndex = leafCount + 2 ** 32 - 1; - tree[nodeIndex] = output[i][0]; - if (slot == 0) { - frontier[0] = output[i][0]; - } - for (uint256 k = 1; k < slot + 1; k++) { - nodeIndex = (nodeIndex - 1) / 2; - tree[nodeIndex] = ret[offset++]; - if (k == slot) { - frontier[slot] = tree[nodeIndex]; - } - } - leafCount++; - } - latestRoot = ret[offset]; - roots[latestRoot] = latestRoot; - for (uint256 i = 0; i < input.length; i++) { - bytes32 nf = input[i][0]; - nullifiers[nf] = nf; - emit NoteSpent(nf); - } - for (uint256 i = 0; i < output.length; i++) { - noteCommitment[output[i][0]] = output[i][0]; - emit TransferNewLeaf(leafCount - (output.length - i), output[i][0], output[i][1], output[i][2], c[i]); - } - } - //input: nf, anchor, cv, rk, proof - //output: cm, cv, epk, proof - function burn(bytes32[10] calldata input, bytes32[2] calldata spendAuthoritySignature, uint256 rawValue, bytes32[2] calldata bindingSignature, address payTo, bytes32[3] calldata burnCipher, bytes32[9][] calldata output, bytes32[21][] calldata c) external { - uint64 value = rawValueToValue(rawValue); - bytes32 signHash = sha256(abi.encodePacked(address(this), input, output, c, payTo, value)); - - bytes32 nf = input[0]; - bytes32 anchor = input[1]; - require(nullifiers[nf] == 0, "The note has already been spent!"); - require(roots[anchor] != 0, "The anchor must exist!"); - - require(output.length <= 1, "Output number cannot exceed 1!"); - require(output.length == c.length, "Output number must be equal to length of c!"); - - // bytes32 signHash = sha256(abi.encodePacked(address(this), input, payTo, value, output, c)); - if (output.length == 0) { - (bool result) = verifyBurnProof(input, spendAuthoritySignature, value, bindingSignature, signHash); - require(result, "The proof and signature have not been verified by the contract!"); - } else { - transferInBurn(input, spendAuthoritySignature, value, bindingSignature, signHash, output, c); - } - - nullifiers[nf] = nf; - emit NoteSpent(nf); - //Finally, transfer trc20Token from this contract to the nominated address - bool transferResult = trc20Token.transfer(payTo, rawValue); - require(transferResult, "Transfer failed!"); - - emit TokenBurn(payTo, rawValue, burnCipher); - } - - function transferInBurn(bytes32[10] memory input, bytes32[2] memory spendAuthoritySignature, uint64 value, bytes32[2] memory bindingSignature, bytes32 signHash, bytes32[9][] memory output, bytes32[21][] memory c) private { - bytes32 cm = output[0][0]; - require(noteCommitment[cm] == 0, "Duplicate noteCommitment!"); - bytes32[10][] memory inputs = new bytes32[10][](1); - inputs[0] = input; - bytes32[2][] memory spendAuthoritySignatures = new bytes32[2][](1); - spendAuthoritySignatures[0] = spendAuthoritySignature; - (bytes32[] memory ret) = verifyTransferProof(inputs, spendAuthoritySignatures, output, bindingSignature, signHash, value, frontier, leafCount); - uint256 result = uint256(ret[0]); - require(result == 1, "The proof and signature have not been verified by the contract!"); - - uint256 slot = uint256(ret[1]); - uint256 nodeIndex = leafCount + 2 ** 32 - 1; - tree[nodeIndex] = cm; - if (slot == 0) { - frontier[0] = cm; - } - for (uint256 i = 1; i < slot + 1; i++) { - nodeIndex = (nodeIndex - 1) / 2; - tree[nodeIndex] = ret[i + 1]; - if (i == slot) { - frontier[slot] = tree[nodeIndex]; - } - } - latestRoot = ret[slot + 2]; - roots[latestRoot] = latestRoot; - noteCommitment[cm] = cm; - leafCount ++; - - emit BurnNewLeaf(leafCount - 1, cm, output[0][1], output[0][2], c[0]); - } - - //position: index of leafnode, start from 0 - function getPath(uint256 position) public view returns (bytes32, bytes32[32] memory) { - require(position >= 0, "Position should be non-negative!"); - require(position < leafCount, "Position should be smaller than leafCount!"); - uint256 index = position + 2 ** 32 - 1; - bytes32[32] memory path; - uint32 level = ancestorLevel(position); - bytes32 targetNodeValue = getTargetNodeValue(position, level); - for (uint32 i = 0; i < 32; i++) { - if (i == level) { - path[31 - i] = targetNodeValue; - } else { - if (index % 2 == 0) { - path[31 - i] = tree[index - 1]; - } else { - path[31 - i] = tree[index + 1] == 0 ? zeroes[i] : tree[index + 1]; - } - } - index = (index - 1) / 2; - } - return (latestRoot, path); - } - - //position: index of leafnode, start from 0 - function getPathByValueIsZero(uint256 position) public view returns (bytes32, bytes32[32] memory) { - require(position >= 0, "Position should be non-negative!"); - require(position < leafCount, "Position should be smaller than leafCount!"); - uint256 index = position + 2 ** 32 - 1; - bytes32[32] memory path; - uint32 level = ancestorLevel(position); - bytes32 targetNodeValue = getTargetNodeValueByValueIsZero(position, level); - for (uint32 i = 0; i < 32; i++) { - if (i == level) { - path[31 - i] = targetNodeValue; - } else { - if (index % 2 == 0) { - path[31 - i] = tree[index - 1]; - } else { - path[31 - i] = tree[index + 1] == 0 ? zeroes[i] : tree[index + 1]; - } - } - index = (index - 1) / 2; - } - return (latestRoot, path); - } - - function ancestorLevel(uint256 leafIndex) private view returns (uint32) { - uint256 nodeIndex1 = leafIndex + 2 ** 32 - 1; - uint256 nodeIndex2 = leafCount + 2 ** 32 - 2; - uint32 level = 0; - while (((nodeIndex1 - 1) / 2) != ((nodeIndex2 - 1) / 2)) { - nodeIndex1 = (nodeIndex1 - 1) / 2; - nodeIndex2 = (nodeIndex2 - 1) / 2; - level = level + 1; - } - return level; - } - - function getTargetNodeValue(uint256 leafIndex, uint32 level) private view returns (bytes32) { - bytes32 left; - bytes32 right; - uint256 index = leafIndex + 2 ** 32 - 1; - uint256 nodeIndex = leafCount + 2 ** 32 - 2; - bytes32 nodeValue = tree[nodeIndex]; - if (level == 0) { - if (index < nodeIndex) { - return nodeValue; - } - if (index == nodeIndex) { - if (index % 2 == 0) { - return tree[index - 1]; - } else { - return zeroes[0]; - } - } - } - for (uint32 i = 0; i < level; i++) { - if (nodeIndex % 2 == 0) { - left = tree[nodeIndex - 1]; - right = nodeValue; - } else { - left = nodeValue; - right = zeroes[i]; - } - nodeValue = pedersenHash(i, left, right); - nodeIndex = (nodeIndex - 1) / 2; - } - return nodeValue; - } - - function getTargetNodeValueByValueIsZero(uint256 leafIndex, uint32 level) private view returns (bytes32) { - bytes32 left; - bytes32 right; - uint256 index = leafIndex + 2 ** 32 - 1; - uint256 nodeIndex = leafCount + 2 ** 32 - 2; - bytes32 nodeValue = tree[nodeIndex]; - if (level == 0) { - if (index < nodeIndex) { - return nodeValue; - } - if (index == nodeIndex) { - if (index % 2 == 0) { - return tree[index - 1]; - } else { - return zeroes[0]; - } - } - } - for (uint32 i = 0; i < level; i++) { - if (nodeIndex % 2 == 0) { - left = tree[nodeIndex - 1]; - right = nodeValue; - } else { - left = nodeValue; - right = zeroes[i]; - } - left = bytes32(0x0); - right = bytes32(0x0); - nodeValue = pedersenHash(i, left, right); - nodeIndex = (nodeIndex - 1) / 2; - } - return nodeValue; - } - - function rawValueToValue(uint256 rawValue) private view returns (uint64) { - require(rawValue > 0, "Value must be positive!"); - require(rawValue.mod(scalingFactor) == 0, "Value must be integer multiples of scalingFactor!"); - uint256 value = rawValue.div(scalingFactor); - require(value < INT64_MAX); - return uint64(value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest1TestRequireContract.sol b/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest1TestRequireContract.sol deleted file mode 100644 index 16d01911d35..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest1TestRequireContract.sol +++ /dev/null @@ -1,15 +0,0 @@ - -contract TestThrowsContract{ - function testAssert() public { - assert(1==2); - } - function testRequire() public { - require(2==1); - } - function testRevert() public { - revert(); - } - //function testThrow(){ - // throw; - //} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest2TestThrowsContract.sol b/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest2TestThrowsContract.sol deleted file mode 100644 index 1ff73ad6460..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest2TestThrowsContract.sol +++ /dev/null @@ -1,15 +0,0 @@ - -contract TestThrowsContract{ - function testAssert() public { - assert(1==2); - } - function testRequire() public { - require(2==1); - } - function testRevert() public { - revert(); - } - // function testThrow() public { - // throw; - //} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest3TestRevertContract.sol b/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest3TestRevertContract.sol deleted file mode 100644 index b42a8c3fb23..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest3TestRevertContract.sol +++ /dev/null @@ -1,15 +0,0 @@ - -contract TestThrowsContract{ - function testAssert() public { - assert(1==2); - } - function testRequire() public { - require(2==1); - } - function testRevert() public { - revert(); - } - // function testThrow(){ - // throw; - // } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest4noPayableContract.sol b/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest4noPayableContract.sol deleted file mode 100644 index 35f89631e7d..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest4noPayableContract.sol +++ /dev/null @@ -1,8 +0,0 @@ - - -contract noPayableContract { - -function noPayable() public payable returns (uint){ -return msg.value; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest4noPayableContract_1.sol b/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest4noPayableContract_1.sol deleted file mode 100644 index 5b6dd509f6f..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest4noPayableContract_1.sol +++ /dev/null @@ -1,8 +0,0 @@ - - -contract noPayableContract { - -function noPayable() public returns (uint){ -return msg.value; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest5noPayableConstructor.sol b/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest5noPayableConstructor.sol deleted file mode 100644 index 097594ab7c9..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest5noPayableConstructor.sol +++ /dev/null @@ -1,11 +0,0 @@ - - -contract MyContract { - uint money; - - //function MyContract(uint _money) { - constructor(uint _money) public payable{ - require(msg.value >= _money); - money = _money; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest5noPayableConstructor_1.sol b/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest5noPayableConstructor_1.sol deleted file mode 100644 index 5008ec5c9bf..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest5noPayableConstructor_1.sol +++ /dev/null @@ -1,11 +0,0 @@ - - -contract MyContract { - uint money; - - //function MyContract(uint _money) { - constructor(uint _money) public { - require(msg.value >= _money); - money = _money; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest6transferTestContract.sol b/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest6transferTestContract.sol deleted file mode 100644 index 4f171aebb9a..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest6transferTestContract.sol +++ /dev/null @@ -1,8 +0,0 @@ - - -contract transferTestContract { - function tranferTest(address payable addr) public payable{ - addr.transfer(10); - - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest7payableFallbakContract.sol b/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest7payableFallbakContract.sol deleted file mode 100644 index 534726cb1b4..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest7payableFallbakContract.sol +++ /dev/null @@ -1,14 +0,0 @@ - - -contract Test { - fallback() external { x = 1; } - uint x; -} - - -contract Caller { - function callTest(Test test) public { - //test.call(0xabcdef01); // hash does not exist - address(test).call(abi.encode(0xabcdef01)); // hash does not exist - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest8newContractGasNoenough.sol b/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest8newContractGasNoenough.sol deleted file mode 100644 index b8743e8231a..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest8newContractGasNoenough.sol +++ /dev/null @@ -1,19 +0,0 @@ - - -contract Account{ - uint256 public accId; - - // function Account(uint accountId) payable{ - constructor(uint accountId) payable public { - accId = accountId; - } -} - -contract Initialize{ - // Account public account = new Account(10); - - function newAccount() public { - Account account = new Account(1); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest9MessageUsedErrorFeed.sol b/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest9MessageUsedErrorFeed.sol deleted file mode 100644 index 18142d20ee8..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontest9MessageUsedErrorFeed.sol +++ /dev/null @@ -1,18 +0,0 @@ - - -contract MathedFeed { - - function divideMathed() public returns (uint ret) { - uint x=1; - uint y=0; - return x/y; - } -} - - -contract MathedUseContract { - - function MathedUse(address addr) public returns (uint) { - return MathedFeed(addr).divideMathed(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontestFunctionUsedErrorFeed.sol b/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontestFunctionUsedErrorFeed.sol deleted file mode 100644 index ad90faa6dab..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/requireExceptiontestFunctionUsedErrorFeed.sol +++ /dev/null @@ -1,17 +0,0 @@ - - -contract MessageFeed { - - function mValue() payable public returns (uint ret) { - return msg.value; - } -} - -contract MessageUseContract { - function inputValue() payable public returns (uint){ - return msg.value; - } - function messageUse(address addr) payable public returns (uint) { - return MessageFeed(addr).mValue.value(1)(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/selector.sol b/framework/src/test/resources/soliditycode_0.6.12/selector.sol deleted file mode 100644 index 5805a6e8d22..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/selector.sol +++ /dev/null @@ -1,21 +0,0 @@ - - -library A { - function getBalance(address) public view returns (uint256) { - return address(this).balance; - } - - function getamount(address) external view returns (uint256) { - return address(this).balance; - } -} - -contract testSelector { - using A for address; - - - function getselector2() public view returns (bytes4, bytes4) { - return (A.getBalance.selector, A.getamount.selector); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/stackContract001.sol b/framework/src/test/resources/soliditycode_0.6.12/stackContract001.sol deleted file mode 100644 index c2e8f2f7611..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/stackContract001.sol +++ /dev/null @@ -1,61 +0,0 @@ - - -contract A{ - event log(uint256); - constructor() payable public{ - emit log(withdrawreward()); - emit log(address(this).rewardbalance); - } - function withdrawRewardTest() public returns (uint256){ - return withdrawreward(); - } - - function test() public{ - emit log(123); - } -} - -contract B{ - event log(uint256); - constructor() payable public{ - emit log(withdrawreward()); - emit log(address(this).rewardbalance); - } - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - function UnStake() public returns (bool result){ - return unstake(); - } - function SelfdestructTest(address payable target) public{ - selfdestruct(target); - } - function rewardBalance(address addr) public view returns (uint256){ - return addr.rewardbalance; - } - - function nullAddressTest() public view returns (uint256) { - return address(0x0).rewardbalance; - } - - function localContractAddrTest() public view returns (uint256) { - address payable localContract = address(uint160(address(this))); - return localContract.rewardbalance; - } - - function withdrawRewardTest() public returns (uint256){ - return withdrawreward(); - } - - function contractBWithdrawRewardTest(address contractB) public returns (uint) { - return B(contractB).withdrawRewardTest(); - } - - function createA() public returns (address){ - return address(new A()); - } - - function callA(address Addr) public{ - A(Addr).test(); - } -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/stackSuicide001.sol b/framework/src/test/resources/soliditycode_0.6.12/stackSuicide001.sol deleted file mode 100644 index d1fc520ddb2..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/stackSuicide001.sol +++ /dev/null @@ -1,84 +0,0 @@ - -contract testStakeSuicide{ - B b; - constructor() payable public{} - function deployB() payable public returns (B addrB){ - b = (new B).value(1000000000)(); - return b; - } - function SelfdestructTest(address payable target) public{ - selfdestruct(target); - } - function SelfdestructTest2(address sr, uint256 amount, address payable target) public{ - stake(sr, amount); - selfdestruct(target); - } - function Stake(address sr, uint256 amount) public payable returns (bool result){ - return stake(sr, amount); - } - function Stake2(address sr, uint256 amount) public returns (bool result){ - stake(sr, amount); - return stake(sr, amount); - } - function UnStake() public returns (bool result){ - return unstake(); - } - function UnStake2() public returns (bool result){ - unstake(); - return unstake(); - } - function WithdrawReward() public { - withdrawreward(); - } - function RewardBalance(address addr) view public returns (uint256 balance) { - return addr.rewardbalance; - } - function revertTest1(address sr, uint256 amount, address payable transferAddr) public{ - transferAddr.transfer(1000000); - stake(sr, amount); - transferAddr.transfer(2000000); - stake(sr, 1000000000000000);//stake more than balance to fail - transferAddr.transfer(4000000); - } - function revertTest2(address payable transferAddr) public{ - transferAddr.transfer(1000000); - unstake(); - transferAddr.transfer(2000000); - unstake();//unstake twice to fail - transferAddr.transfer(4000000); - } - - function BStake(address sr, uint256 amount) public returns (bool result){ - return b.Stake(sr, amount); - } - function BUnStake() public returns (bool result){ - return b.UnStake(); - } - function transfer(address payable add,uint256 num) public { - return add.transfer(num); - } -} - -contract B{ - constructor() payable public{} - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - function UnStake() public returns (bool result){ - return unstake(); - } - function SelfdestructTest(address payable target) public{ - selfdestruct(target); - } - - function deploy(bytes memory code, uint256 salt) public returns(address) { - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - return addr; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/stateVariableShadowing.sol b/framework/src/test/resources/soliditycode_0.6.12/stateVariableShadowing.sol deleted file mode 100644 index a9109ee296c..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/stateVariableShadowing.sol +++ /dev/null @@ -1,21 +0,0 @@ -contract test { -// uint public x; -// function setValue1(uint _x) public returns (uint){ -// x = _x; -// return x; -// } - uint public y; - function setValue3(uint _x) public returns (uint){ - y = _x; - return y; - } -} - -contract stateVariableShadowing is test { - uint public x; - function setValue2(uint _x) public returns (uint){ - x = _x; - return x; - } -} - diff --git a/framework/src/test/resources/soliditycode_0.6.12/stringSplit.sol b/framework/src/test/resources/soliditycode_0.6.12/stringSplit.sol deleted file mode 100644 index 84231f2d1fe..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/stringSplit.sol +++ /dev/null @@ -1,45 +0,0 @@ - - -contract testStringSplit { -string s1 = "s""1""2"",./"; -string s2 = "s123?\\'."; -string s3 = hex"41"hex"42"; -string s4 = hex"4142"; - -function getS1() public view returns (string memory) { -return s1; -} - -function getS1N1() public pure returns (string memory) { -string memory n1 = "s""1""2"",./"; -return n1; -} - -function getS2() public view returns (string memory) { -return s2; -} - -function getS2N2() public pure returns (string memory) { -string memory n2 = "s123?\'."; -return n2; -} - -function getS3() public view returns (string memory) { -return s3; -} - -function getS3N3() public pure returns (string memory) { -string memory n3 = hex"41"hex"42"; -return n3; -} - -function getS4() public view returns (string memory) { -return s4; -} - -function getS4N4() public pure returns (string memory) { -string memory n4 = hex"4142"; -return n4; -} - -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/suicide001.sol b/framework/src/test/resources/soliditycode_0.6.12/suicide001.sol deleted file mode 100644 index 3544f8bf84a..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/suicide001.sol +++ /dev/null @@ -1,32 +0,0 @@ -contract factory { - constructor() payable public { - } - - function create1() payable public returns (address){ - Caller add = (new Caller).value(0)(); - return address(add); - } - - function kill() payable public{ - selfdestruct(msg.sender); - } - - function create2(bytes memory code, uint256 salt) public returns(address){ - Caller addr; - Caller addr1; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - return address(addr); - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/suicide002.sol b/framework/src/test/resources/soliditycode_0.6.12/suicide002.sol deleted file mode 100644 index 160ab64f320..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/suicide002.sol +++ /dev/null @@ -1,43 +0,0 @@ -contract Factory { - uint256 public num; - event Deployed(address addr, uint256 salt, address sender); - constructor() public { - } - function deploy(bytes memory code, uint256 salt) public returns(address){ - TestConstract addr; - TestConstract addr1; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - - addr.testSuicideNonexistentTarget(msg.sender); - addr.set(); - - assembly { - addr1 := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(address(addr), salt, msg.sender); - return address(addr); - } -} - - - -contract TestConstract { - uint public i=1; - constructor () public { - } - - function set() public{ - i=9; - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/testOutOfMem.sol b/framework/src/test/resources/soliditycode_0.6.12/testOutOfMem.sol deleted file mode 100644 index 8d285b28b7d..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/testOutOfMem.sol +++ /dev/null @@ -1,7 +0,0 @@ -contract Test { - function testOutOfMem(uint256 x) public returns(bytes32 r) { - uint[] memory memVar; - memVar = new uint[](x); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/testStakeSuicide.sol b/framework/src/test/resources/soliditycode_0.6.12/testStakeSuicide.sol deleted file mode 100644 index 3342a5607f7..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/testStakeSuicide.sol +++ /dev/null @@ -1,71 +0,0 @@ - -contract testStakeSuicide{ - B b; - constructor() payable public{} - function deployB() payable public returns (B addrB){ - b = (new B).value(1000000000)(); - return b; - } - function SelfdestructTest(address payable target) public{ - selfdestruct(target); - } - function SelfdestructTest2(address sr, uint256 amount, address payable target) public{ - stake(sr, amount); - selfdestruct(target); - } - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - function Stake2(address sr, uint256 amount) public returns (bool result){ - stake(sr, amount); - return stake(sr, amount); - } - function UnStake() public returns (bool result){ - return unstake(); - } - function UnStake2() public returns (bool result){ - unstake(); - return unstake(); - } - function WithdrawReward() public { - withdrawreward(); - } - function RewardBalance(address addr) view public returns (uint256 balance) { - return addr.rewardbalance; - } - function revertTest1(address sr, uint256 amount, address payable transferAddr) public{ - transferAddr.transfer(1000000); - stake(sr, amount); - transferAddr.transfer(2000000); - stake(sr, 1000000000000000);//stake more than balance to fail - transferAddr.transfer(4000000); - } - function revertTest2(address payable transferAddr) public{ - transferAddr.transfer(1000000); - unstake(); - transferAddr.transfer(2000000); - unstake();//unstake twice to fail - transferAddr.transfer(4000000); - } - function BStake(address sr, uint256 amount) public returns (bool result){ - return b.Stake(sr, amount); - } - function BUnStake() public returns (bool result){ - return b.UnStake(); - } - function BSelfdestructTest(address payable target) public{ - b.SelfdestructTest(target); - } -} -contract B{ - constructor() payable public{} - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - function UnStake() public returns (bool result){ - return unstake(); - } - function SelfdestructTest(address payable target) public{ - selfdestruct(target); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/tryCatch001.sol b/framework/src/test/resources/soliditycode_0.6.12/tryCatch001.sol deleted file mode 100644 index 283db92e159..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/tryCatch001.sol +++ /dev/null @@ -1,105 +0,0 @@ - - -enum ErrorType { - Revert_Error, //0 - RevertWithMsg_Error, //1 - Require_Error, //2 - RequirewithMsg_Error, //3 - Assert_Error, //4 - Tansfer_Error, //5 - Send_Error, //6 - Math_Error, //7 - ArrayOverFlow_Error //8 -} -contract errorContract { - uint256[] arraryUint ; - - function errorSwitch(uint256 errorType) public returns(string memory) { - if (ErrorType(errorType) == ErrorType.Revert_Error){ - revert(); - } else if (ErrorType(errorType) == ErrorType.RevertWithMsg_Error){ - revert("Revert Msg."); - } else if (ErrorType(errorType) == ErrorType.Require_Error) { - require(0>1); - } else if (ErrorType(errorType) == ErrorType.RequirewithMsg_Error) { - require(0>1,"Require Msg."); - } else if (ErrorType(errorType) == ErrorType.Assert_Error) { - assert(1<0); - } else if (ErrorType(errorType) == ErrorType.Tansfer_Error) { - payable(msg.sender).transfer(1); - } else if (ErrorType(errorType) == ErrorType.Send_Error) { - payable(msg.sender).send(1); - } else if (ErrorType(errorType) == ErrorType.Math_Error) { - uint256 a = 1; - uint256 b = 0; - uint256 n = a / b; - } else if (ErrorType(errorType) == ErrorType.ArrayOverFlow_Error) { - arraryUint.pop(); - } - return "success"; - - } - - function callFun(string memory functionStr, string memory argsStr) public{ - address(this).call(abi.encodeWithSignature(functionStr, argsStr)); - } - -} - -contract NewContract { - uint256[] arraryUint ; - - constructor(uint256 errorType) public payable{ - if (ErrorType(errorType) == ErrorType.Revert_Error){ - revert(); - } else if (ErrorType(errorType) == ErrorType.RevertWithMsg_Error){ - revert("Revert Msg."); - } else if (ErrorType(errorType) == ErrorType.Require_Error) { - require(0>1); - } else if (ErrorType(errorType) == ErrorType.RequirewithMsg_Error) { - require(0>1,"Require Msg."); - } else if (ErrorType(errorType) == ErrorType.Assert_Error) { - assert(1<0); - } else if (ErrorType(errorType) == ErrorType.Tansfer_Error) { - payable(msg.sender).transfer(1); - } else if (ErrorType(errorType) == ErrorType.Send_Error) { - payable(msg.sender).send(1); - } else if (ErrorType(errorType) == ErrorType.Math_Error) { - uint256 a = 1; - uint256 b = 0; - uint256 n = a / b; - } else if (ErrorType(errorType) == ErrorType.ArrayOverFlow_Error) { - arraryUint.pop(); - } - } -} - -contract tryTest { - function getData(errorContract inter, string memory functionStr, string memory argsStr) public payable returns(string memory) { - try inter.callFun(functionStr,argsStr) { - return "123"; - } catch Error(string memory errorMsg/* 出错原因 */) { - return errorMsg; - } catch (bytes memory) { - return "3"; - } - } - - function getErrorSwitch(errorContract add, uint256 errorType ) public payable returns(string memory) { - try add.errorSwitch(errorType) returns (string memory Msg) { - return Msg; - } catch Error(string memory errorMsg/* 出错原因 */) { - return errorMsg; - } catch (bytes memory) { - return "NoErrorMsg"; - } - } - - function catchNewErrorSwitch(uint256 errorType) public returns (address nc){ - try new NewContract(errorType) returns (NewContract nc){ - return address(nc); - }catch { - return address(0x00); - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue001.sol b/framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue001.sol deleted file mode 100644 index 5388ed68473..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue001.sol +++ /dev/null @@ -1,25 +0,0 @@ - -contract tvmAssetIssue001 { - constructor() payable public{} - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - return assetissue(name, abbr, totalSupply, precision); - } - - function updateAsset(trcToken tokenId, string memory url, string memory desc) public returns (bool) { - return updateasset(tokenId, bytes(url), bytes(desc)); - } - - function updateOtherAccountAsset(string memory url, string memory desc) public returns (bool) { - trcToken tokenId = trcToken(1000004); - return updateasset(tokenId, bytes(url), bytes(desc)); - } - - function updateAssetOnBytes(trcToken tokenId, bytes memory url, bytes memory desc) public returns (bool) { - return updateasset(tokenId, url, desc); - } - - function transferToken(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue002.sol b/framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue002.sol deleted file mode 100644 index 87c1206b778..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue002.sol +++ /dev/null @@ -1,15 +0,0 @@ - - -contract tvmAssetIssue002 { - constructor() payable public{} - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - assetissue(name, abbr, totalSupply, precision); - return assetissue(name, abbr, totalSupply, precision); - } - - function updateAsset(trcToken tokenId, string memory url1, string memory desc1, string memory url2, string memory desc2) public returns (bool) { - updateasset(tokenId, bytes(url1), bytes(desc1)); - return updateasset(tokenId, bytes(url2), bytes(desc2)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue003.sol b/framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue003.sol deleted file mode 100644 index f5ce5e0dc3e..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue003.sol +++ /dev/null @@ -1,23 +0,0 @@ - - -contract tvmAssetIssue003 { - constructor() payable public{} - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - return assetissue(name, abbr, totalSupply, precision); - } - - function tokenIssueAndTransfer(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision, address addr) public { - address payable newaddress = address(uint160(addr)); - newaddress.transfer(100000000); - assetissue(name, abbr, totalSupply, precision); - newaddress.transfer(100000000); - } - - function updateAssetAndTransfer(trcToken tokenId, string memory url, string memory desc, address addr) public { - address payable newaddress = address(uint160(addr)); - newaddress.transfer(100000000); - updateasset(tokenId, bytes(url), bytes(desc)); - newaddress.transfer(100000000); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue004.sol b/framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue004.sol deleted file mode 100644 index c8332de8f45..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue004.sol +++ /dev/null @@ -1,39 +0,0 @@ - - -contract A { - - constructor() payable public{} - fallback() payable external {} - - function tokenIssueA(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint){ - return assetissue(name, abbr, totalSupply, precision); - } - - function updateAssetA(trcToken tokenId, string memory url, string memory desc) public returns (bool) { - return updateasset(tokenId, bytes(url), bytes(desc)); - } - - function transferToken(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } -} - -contract tvmAssetIssue004 { - - A a; - - constructor() payable public{} - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - return a.tokenIssueA(name, abbr, totalSupply, precision); - } - - function updateAsset(trcToken tokenId, string memory url, string memory desc) public returns (bool) { - return a.updateAssetA(tokenId, url, desc); - } - - function getContractAddress() public payable returns (address) { - a = (new A).value(1024000000)(); - return address(a); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue005.sol b/framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue005.sol deleted file mode 100644 index 8c36d050ff8..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/tvmAssetIssue005.sol +++ /dev/null @@ -1,45 +0,0 @@ - - -contract tvmAssetIssue005 { - constructor() payable public{} - - fallback() external payable { - } - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - return assetissue(name, abbr, totalSupply, precision); - } - - function updateAsset(trcToken tokenId, string memory url, string memory desc) public returns (bool) { - return updateasset(tokenId, bytes(url), bytes(desc)); - } - - function updateAssetOnBytes(trcToken tokenId, bytes memory url, bytes memory desc) public returns (bool) { - return updateasset(tokenId, url, desc); - } - - function transferToken(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - - function SelfdestructTest(address payable target) public { - selfdestruct(target); - } -} - -contract B { - event Deployed(address addr, uint256 salt); - - function deploy(uint256 salt) public returns (address) { - address addr; - bytes memory code = type(tvmAssetIssue005).creationCode; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt); - return addr; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/typeName.sol b/framework/src/test/resources/soliditycode_0.6.12/typeName.sol deleted file mode 100644 index 5b44abd1bbb..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/typeName.sol +++ /dev/null @@ -1,5 +0,0 @@ -contract TypeName { - function testTypeName() public returns (string memory){ - return type(TypeName).name; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/unStake001.sol b/framework/src/test/resources/soliditycode_0.6.12/unStake001.sol deleted file mode 100644 index 03734fecfa5..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/unStake001.sol +++ /dev/null @@ -1,90 +0,0 @@ - - -contract unStakeTest { - B b; - constructor() payable public{} - function deployB() payable public returns (B addrB){ - b = (new B).value(1000000000)(); - return b; - } - - function selfdestructTest(address payable target) public { - selfdestruct(target); - } - - function selfdestructTest2(address sr, uint256 amount, address payable target) public { - stake(sr, amount); - selfdestruct(target); - } - - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - - function stake2(address sr, uint256 amount) public returns (bool result){ - stake(sr, amount); - return stake(sr, amount); - } - - function unStake() public returns (bool result){ - return unstake(); - } - - function unStake2() public returns (bool result){ - unstake(); - return unstake(); - } - - function withdrawReward() public returns (uint256 amount) { - return withdrawreward(); - } - - function rewardBalance(address addr) view public returns (uint256 balance) { - return addr.rewardbalance; - } - - function revertTest1(address sr, uint256 amount, address payable transferAddr) public { - transferAddr.transfer(1000000); - stake(sr, amount); - transferAddr.transfer(2000000); - stake(sr, 1000000000000000); - //stake more than balance to fail - transferAddr.transfer(4000000); - } - - function revertTest2(address payable transferAddr) public { - transferAddr.transfer(1000000); - unstake(); - transferAddr.transfer(2000000); - unstake(); - //unstake twice to fail - transferAddr.transfer(4000000); - } - - function BStake(address sr, uint256 amount) public returns (bool result){ - return b.Stake(sr, amount); - } - - function BUnStake() public returns (bool result){ - return b.UnStake(); - } - - function BSelfdestructTest(address payable target) public { - b.SelfdestructTest(target); - } -} - -contract B { - constructor() payable public{} - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - - function UnStake() public returns (bool result){ - return unstake(); - } - - function SelfdestructTest(address payable target) public { - selfdestruct(target); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/validatemultisign001.sol b/framework/src/test/resources/soliditycode_0.6.12/validatemultisign001.sol deleted file mode 100644 index cc0a742d0c5..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/validatemultisign001.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract validatemultisignTest { - function testmulti(address a, uint256 perid, bytes32 hash, bytes[] memory signatures) public returns (bool){ - return validatemultisign(a, perid, hash, signatures); - } - - function testbatch(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public returns (bytes32){ - return batchvalidatesign(hash, signatures, addresses); - } - - function testMultiPrecompileContract(bytes memory data) public returns(bool, bytes memory){ - return address(0xa).delegatecall(data); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/verifyTransferProof001.sol b/framework/src/test/resources/soliditycode_0.6.12/verifyTransferProof001.sol deleted file mode 100644 index 587b4defd10..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/verifyTransferProof001.sol +++ /dev/null @@ -1,15 +0,0 @@ -contract verifyTransferProofTest { - - function test1() public returns (bool, bytes memory){ - bytes memory empty = ""; - return address(0x1000002).delegatecall(empty); - } - - function test2(bytes memory data) public returns (bool, bytes memory){ - return address(0x1000002).delegatecall(data); - } - - function test3(bytes32[10][] memory input, bytes32[2][] memory spendAuthoritySignature, bytes32[9][] memory output, bytes32[2] memory bindingSignature, bytes32 signHash, uint64 valueBalance, bytes32[33] memory frontier, uint256 leafCount) public returns (bytes32[] memory){ - return verifyTransferProof(input, spendAuthoritySignature, output, bindingSignature, signHash, valueBalance, frontier, leafCount); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.6.12/virtual001.sol b/framework/src/test/resources/soliditycode_0.6.12/virtual001.sol deleted file mode 100644 index 6dddac07ef4..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/virtual001.sol +++ /dev/null @@ -1,19 +0,0 @@ -pragma solidity ^0.6.0; -interface X { - function setValue(uint _x) external; -} -abstract contract Y { - function setBool(bool _y) external virtual ; -} -contract Y2 { - string public z; - function setString(string calldata _z) external virtual { z = "123"; } -} - -contract Z is X,Y,Y2 { - uint public x; - bool public y; - function setValue(uint _x) external override { x = _x; } - function setBool(bool _y) external override { y = _y; } - function setString(string calldata _z) external override { z = _z; } -} diff --git a/framework/src/test/resources/soliditycode_0.6.12/walletTestMutiSign004.sol b/framework/src/test/resources/soliditycode_0.6.12/walletTestMutiSign004.sol deleted file mode 100644 index 7b943aee5c1..00000000000 --- a/framework/src/test/resources/soliditycode_0.6.12/walletTestMutiSign004.sol +++ /dev/null @@ -1,51 +0,0 @@ -contract timeoutTest { - string public iarray1; - // cpu - function oneCpu() public { - require(1==1); - } - - function storage8Char() public { - iarray1 = "12345678"; - } - - function testUseCpu(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - } - return count; - } - - - uint256[] public iarray; - uint public calculatedFibNumber; - mapping(address=>mapping(address=>uint256)) public m; - - function testUseStorage(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - iarray.push(i); - } - return count; - } - - // stack - //uint n = 0; - uint yy = 0; - function test() public { - //n += 1; - yy += 1; - test(); - } - - function setFibonacci(uint n) public returns (uint256){ - calculatedFibNumber = fibonacci(n); - return calculatedFibNumber; - } - - function fibonacci(uint n) internal returns (uint) { - return fibonacci(n - 1) + fibonacci(n - 2); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/AssertException002.sol b/framework/src/test/resources/soliditycode_0.7.6/AssertException002.sol deleted file mode 100644 index 15cc07ff984..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/AssertException002.sol +++ /dev/null @@ -1,17 +0,0 @@ - - -contract AssertException{ - function divideIHaveArgsReturn(int x,int y) public returns (int z) { - return x / y; - } - function testAssert() public { - require(2==1); - } -} -contract C { - constructor() public payable { - assert(1==2); - } - function fun() public { - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/AssignToExternal.sol b/framework/src/test/resources/soliditycode_0.7.6/AssignToExternal.sol deleted file mode 100644 index d4f09590a36..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/AssignToExternal.sol +++ /dev/null @@ -1,30 +0,0 @@ -contract AssignToExternal { - // Not allow: - // function f(uint256[] calldata x, uint256[] calldata y) external pure { - // x = y; - // } - - // allow: - - function f(uint256 a) external returns (uint){ - a = a + 1; - return a; - } - - function StringSet(string calldata a) external returns (string memory){ - return a; - } - - function ByteSet(bytes32 a) external returns (bytes32){ - return a; - } - - function UintArraySet(uint256[2] calldata a) external returns (uint256[2] memory){ - return a; - } - - function AddSet(address a) external returns (address){ - return a; - } - -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/BlockHash.sol b/framework/src/test/resources/soliditycode_0.7.6/BlockHash.sol deleted file mode 100644 index 6603da65e44..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/BlockHash.sol +++ /dev/null @@ -1,38 +0,0 @@ -contract TestBlockHash { - - function testOR1(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = blockhash(block.number - 1) | bytes32(value); - return (b1, c, blockhash(block.number - 1)); - } - - function testOR2(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = bytes32(value) | blockhash(block.number - 1); - return (b1, c, blockhash(block.number - 1)); - } - - function testAND1(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = blockhash(block.number - 1) & bytes32(value); - return (b1, c, blockhash(block.number - 1)); - } - - function testAND2(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = bytes32(value) & blockhash(block.number - 1); - return (b1, c, blockhash(block.number - 1)); - } - - function testXOR1(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = blockhash(block.number - 1) ^ bytes32(value); - return (b1, c, blockhash(block.number - 1)); - } - - function testXOR2(bytes32 value) public returns(bytes32, bytes32, bytes32) { - bytes32 b1 = blockhash(block.number - 1); - bytes32 c = bytes32(value) ^ blockhash(block.number - 1); - return (b1, c, blockhash(block.number - 1)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/ClearAbi001.sol b/framework/src/test/resources/soliditycode_0.7.6/ClearAbi001.sol deleted file mode 100644 index 39a8e8cf005..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/ClearAbi001.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract testConstantContract{ -function testPayable() public view returns (int z) { -return 1; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/ClearAbi005.sol b/framework/src/test/resources/soliditycode_0.7.6/ClearAbi005.sol deleted file mode 100644 index a3115398386..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/ClearAbi005.sol +++ /dev/null @@ -1,26 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract TestConstract { - uint public i=0; - constructor () public { - } - function plusOne() public returns(uint){ - i++; - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/ConstructorDefaults.sol b/framework/src/test/resources/soliditycode_0.7.6/ConstructorDefaults.sol deleted file mode 100644 index 4b6186ccb95..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/ConstructorDefaults.sol +++ /dev/null @@ -1,9 +0,0 @@ -contract testIsContract{ - bool result; - constructor (bool a) public { - result = a; - } -function test( address a) public returns (bool) { -return result; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/Create2Test023.sol b/framework/src/test/resources/soliditycode_0.7.6/Create2Test023.sol deleted file mode 100644 index ba48645ae3f..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/Create2Test023.sol +++ /dev/null @@ -1,31 +0,0 @@ -contract factory { - constructor() payable public { - } - - function deploy(bytes memory code, uint256 salt) public returns(address){ - Caller addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - return address(addr); - } - - function testCreate() payable public returns (address){ - Caller add = (new Caller){value:0}(); - return address(add); - } - - function kill( ) payable public{ - selfdestruct(msg.sender); - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/Create2Test024.sol b/framework/src/test/resources/soliditycode_0.7.6/Create2Test024.sol deleted file mode 100644 index f5a9d032cff..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/Create2Test024.sol +++ /dev/null @@ -1,56 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - TestConstract addr; - TestConstract addr1; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - - addr.testSuicideNonexistentTarget(msg.sender); - addr.set(); - emit Deployed(address(addr), salt, msg.sender); - return address(addr); - } - - function deploy2(bytes memory code, uint256 salt) public returns(address){ - TestConstract addr; - TestConstract addr1; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - - //addr.testSuicideNonexistentTarget(msg.sender); - //addr.set(); - - assembly { - addr1 := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(address(addr), salt, msg.sender); - return address(addr); - } -} - - - -contract TestConstract { - uint public i=1; - constructor () public { - } - - function set() public{ - i=9; - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/Create2Test025.sol b/framework/src/test/resources/soliditycode_0.7.6/Create2Test025.sol deleted file mode 100644 index 895dc43e56f..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/Create2Test025.sol +++ /dev/null @@ -1,34 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - constructor() public { - } - - function create2(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } - - function get(bytes1 prefix, bytes calldata code, uint256 salt) external view returns(address) { - //bytes32 hash = keccak256(abi.encodePacked(bytes1(0x41),address(this), salt, keccak256(code))); - bytes32 hash = keccak256(abi.encodePacked(prefix,address(this), salt, keccak256(code))); - address addr = address(uint160(uint256(hash))); - return addr; - } -} - -contract TestContract{ - uint256 public num; - constructor(uint256 j) public{ - num = j; - } - function getNum() public returns (uint256){ - return num; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/ExtCodeHashTest010.sol b/framework/src/test/resources/soliditycode_0.7.6/ExtCodeHashTest010.sol deleted file mode 100644 index 6feaa923f4b..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/ExtCodeHashTest010.sol +++ /dev/null @@ -1,46 +0,0 @@ -contract Counter { - uint count = 0; - address payable owner; - event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); - constructor() public{ - owner = msg.sender; - } - function getCodeHashSuicide(address addr) public returns (bytes32 _hashBefore){ - assembly{ - _hashBefore := extcodehash(addr) - } - selfdestruct(owner); - return _hashBefore; - } - - function getCodeHashRevert() public returns (bytes32 _hashBefore, bytes32 _hashAfter) { - address addr = address(this); - assembly { - _hashBefore := extcodehash(addr) - } - if (owner == msg.sender) { - selfdestruct(owner); - } - assembly { - _hashAfter := extcodehash(addr) - } - revert(); - emit LogResult(_hashBefore, _hashAfter); - } - - function getCodeHashCreate() public returns (bytes32 _hashBefore){ - TestContract A = (new TestContract){value:0}(); - address addr = address(A); - assembly{ - _hashBefore := extcodehash(addr) - } - revert(); - return _hashBefore; - } -} - -contract TestContract{ - uint256 count = 1; - constructor() public payable{ - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/ExternalSelector.sol b/framework/src/test/resources/soliditycode_0.7.6/ExternalSelector.sol deleted file mode 100644 index 01fddac9e2e..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/ExternalSelector.sol +++ /dev/null @@ -1,92 +0,0 @@ -//pragma solidity ^0.6.0; - -contract selectorContract { - function testSelectorNoParam() external pure returns(uint) { - return 11; - } - - function testSelectorWithParam(uint x) external pure returns(uint) { - return 22; - } -} - -interface interfaceSelector { - function getSelector() external pure returns(uint); -} - -interface B is interfaceSelector { - // interface现在可以继承自其他interface - function testImplemention() external pure returns(uint); -} - -contract implementContract is B{ - function getSelector() external override pure returns(uint) { - return 66; - } - - function testImplemention() external override pure returns(uint) { - return 77; - } - - constructor() public payable {} -} - -contract basicContract{ - function testNewUse() external payable returns(uint) { - return 345; - } - - constructor() public payable {} -} - -contract TestGasValue{ - constructor() public payable {} - - function testNewUse() external payable returns(uint) { - return 123; - } - basicContract bc = new basicContract(); - // external方法在调用时可以采用c.f{gas: 10000, value: 4 trx}()的形式 - function callWithGasAndValue(uint x,uint y) external returns(uint) { - return bc.testNewUse{gas:x, value:y}(); - } - - function callThisNoGasAnd1Value() external returns(uint) { - return this.testNewUse{gas:0, value:1}(); - } - - // inline assembly中允许true和false字面量 - function testAssemblyTrue() public pure returns(uint x) { - assembly { - x := true - } - } - - // inline assembly中允许true和false字面量 - function testAssemblyFalse() public pure returns(uint x) { - assembly { - x := false - } - } - - // create2的high-level用法new C{salt: 0x1234, value: 1 ether}(arg1, arg2) - function testCreate2() public returns(address) { - basicContract c = new basicContract{salt: bytes32(bytes1(0x01)), value: 1 trx}(); - return address(c); - } - - - function getContractSelectorNoParam() public pure returns(bytes4) { - return selectorContract.testSelectorNoParam.selector; - } - - function getContractSelectorWithParam() public pure returns(bytes4) { - return selectorContract.testSelectorWithParam.selector; - } - - function getInterfaceSelectorNoParam() public pure returns(bytes4) { - return interfaceSelector.getSelector.selector; - } - -} - diff --git a/framework/src/test/resources/soliditycode_0.7.6/NewFeature068.sol b/framework/src/test/resources/soliditycode_0.7.6/NewFeature068.sol deleted file mode 100644 index be4ee209e15..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/NewFeature068.sol +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -//pragma solidity ^0.6.8; - -abstract contract testModifier { - modifier isOwner() virtual; -} - -abstract contract testInterfaceId { - function getValue() external view virtual returns(uint); - function getOwner() external view virtual returns(uint); - -} - -interface a { - function getValue() external view returns(uint); - function getOwner() external view returns(uint); -} - -contract testMapKey is testModifier{ - - enum size{ - SMALL, - LARGE - } - - mapping(size => uint) public enums; - - mapping(testMapKey => uint) public contracts; - - function setEnumValue(uint value) public { - enums[size.SMALL] = value; - } - - function getEnumValue() public view returns(uint) { - return enums[size.SMALL]; - } - - function setContractValue() public { - contracts[this] = 2; - } - - function getContractValue() public view returns(uint) { - return contracts[this]; - } - - bytes4 constant functionSelector = this.getEnumValue.selector; - - function getfunctionSelector() public pure returns(bytes4) { - return functionSelector; - } - - uint immutable x; - address immutable owner = msg.sender; - - constructor() public { - x = 5; - } - - string b = "test"; - - function testStorage() public view returns(string memory) { - string storage aa; - aa = b; - return aa; - - } - - function getImmutableVal() public view returns(uint) { - return x; - } - - function getOwner() public view returns(address) { - return owner; - } - - function getInterfaceId() public pure returns(bytes4,bytes4) { - return (type(a).interfaceId, type(testInterfaceId).interfaceId); - } - - modifier isOwner() override { - require(msg.sender == owner); - _; - } - - function requireOwner() public view isOwner returns(uint) { - return 6; - } - - - function getUint256MinAndMax() public pure returns(uint, uint) { - return (type(uint).min, type(uint).max); - } - - - function getUint8MinAndMax() public pure returns(uint8, uint8) { - return (type(uint8).min, type(uint8).max); - } - -} - - -abstract contract base { - function abstractfun() virtual public returns(uint); -} - -abstract contract callEmptyFunction is base { - function callfun() public returns(uint) { - return abstractfun(); - } -} - - - - - - - - - - - - - - - - diff --git a/framework/src/test/resources/soliditycode_0.7.6/NewFeature076.sol b/framework/src/test/resources/soliditycode_0.7.6/NewFeature076.sol deleted file mode 100644 index 3191acb8f1d..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/NewFeature076.sol +++ /dev/null @@ -1,21 +0,0 @@ -function a() returns (uint) { - return 1; -} -abstract contract abvd { - -} -interface qwer { - function getValue() external view returns(uint); - function getOwner() external view returns(uint); -} -contract C { - function getOutsideMethod() external returns (uint) { - return a(); - } - function getAbstractName() public returns(string memory) { - return type(abvd).name; - } - function getInterfaceName() public returns(string memory) { - return type(qwer).name; - } -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/ParentTypeBug.sol b/framework/src/test/resources/soliditycode_0.7.6/ParentTypeBug.sol deleted file mode 100644 index 897c843ae24..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/ParentTypeBug.sol +++ /dev/null @@ -1,13 +0,0 @@ -contract Parent { - uint256 public m_aMember; - address public m_bMember; -} -contract Child is Parent { - function foo() public view returns (uint256) { return Parent.m_aMember; } - function bar() public view returns (address) { return Parent.m_bMember; } - - // complie failed - // function foo() public pure returns (uint256) { return Parent.m_aMember; } - // function bar() public pure returns (address) { return Parent.m_bMember; } - -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/SafeMath.sol b/framework/src/test/resources/soliditycode_0.7.6/SafeMath.sol deleted file mode 100644 index 1a7f1be2b8e..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/SafeMath.sol +++ /dev/null @@ -1,149 +0,0 @@ - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/ShiftCommand001.sol b/framework/src/test/resources/soliditycode_0.7.6/ShiftCommand001.sol deleted file mode 100644 index 574ee2b571b..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/ShiftCommand001.sol +++ /dev/null @@ -1,18 +0,0 @@ -contract TestBitwiseShift { - - function shlTest(uint256 num, uint256 input) public returns (bytes32 out) { - assembly { - out := shl(num, input) - } - } - function shrTest(uint256 num, uint256 input) public returns (bytes32 out) { - assembly { - out := shr(num, input) - } - } - function sarTest(uint256 num, uint256 input) public returns (bytes32 out) { - assembly { - out := sar(num, input) - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/SolidityMappingFix.sol b/framework/src/test/resources/soliditycode_0.7.6/SolidityMappingFix.sol deleted file mode 100644 index 67692d3b4ae..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/SolidityMappingFix.sol +++ /dev/null @@ -1,9 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Tests { - mapping(address => uint) public balances; - function update(uint256 amount) public returns (address addr) - { - balances[msg.sender] = amount; - return msg.sender; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/TestMappings_array_pop.sol b/framework/src/test/resources/soliditycode_0.7.6/TestMappings_array_pop.sol deleted file mode 100644 index 0d5c4bb7013..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TestMappings_array_pop.sol +++ /dev/null @@ -1,19 +0,0 @@ -contract C { - mapping (uint256 => uint256)[] a; - - function n1(uint256 key, uint256 value) public { - a.push(); - a[a.length - 1][key] = value; - } - - - - function map(uint256 key) public view returns (uint) { - return a[a.length - 1][key]; - } - - function p() public { - a.pop(); - } -} - diff --git a/framework/src/test/resources/soliditycode_0.7.6/TransferFailed001.sol b/framework/src/test/resources/soliditycode_0.7.6/TransferFailed001.sol deleted file mode 100644 index e35cd04f590..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TransferFailed001.sol +++ /dev/null @@ -1,147 +0,0 @@ -contract EnergyOfTransferFailedTest { - constructor() payable public { - - } - - function testTransferTokenCompiledLongMax() payable public{ - address(0x1).transferToken(1,9223372036855775827); - } - - function testTransferTokenCompiled() payable public{ - address(0x1).transferToken(1,1); - } - - function testTransferTokenCompiledLongMin() payable public{ - //address(0x1).transferToken(1,-9223372036855775828); - } - - function testTransferTokenCompiledLongMin1() payable public returns(uint256){ - return address(0x2).tokenBalance(trcToken(-9223372036855775828)); - } - - function testTransferTokenCompiled1() payable public returns(uint256){ - return address(0x1).tokenBalance(trcToken(1)); - } - - function testTransferTokenCompiledLongMax1() payable public returns(uint256){ - return address(0x2).tokenBalance(trcToken(9223372036855775827)); - } - - function testTransferTokenCompiledTokenId(uint256 tokenid) payable public returns(uint256){ - return address(0x1).tokenBalance(trcToken(tokenid)); - } - - function testTransferTokenTest(address addr ,uint256 tokenid) payable public returns(uint256){ - return addr.tokenBalance(trcToken(tokenid)); - } - - // InsufficientBalance - function testTransferTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.transfer(i); - } - - function testSendTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.send(i); - } - - function testTransferTokenInsufficientBalance(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - - function testCallTrxInsufficientBalance(uint256 i,address payable caller) public { - caller.call{value:i}(abi.encodeWithSignature("test()")); - } - - function testCreateTrxInsufficientBalance(uint256 i) payable public { - (new Caller){value:i}(); - } - - // NonexistentTarget - - function testSendTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - nonexistentTarget.send(i); - } - - function testSendTrxRevert(uint256 i,address payable nonexistentTarget) payable public { - nonexistentTarget.send(i); - revert(); - } - - function testTransferTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - nonexistentTarget.transfer(i); - } - - function testTransferTrxrevert(uint256 i,address payable nonexistentTarget) payable public{ - nonexistentTarget.transfer(i); - revert(); - } - - function testTransferTokenNonexistentTarget(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - nonexistentTarget.transferToken(i, tokenId); - } - - function testTransferTokenRevert(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - nonexistentTarget.transferToken(i, tokenId); - revert(); - } - - function testCallTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - nonexistentTarget.call{value:i}(abi.encodeWithSignature("test()")); - } - - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } - - function testSuicideRevert(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - revert(); - } - - // target is self - function testTransferTrxSelf(uint256 i) payable public{ - address payable self = address(uint160(address(this))); - self.transfer(i); - } - - function testSendTrxSelf(uint256 i) payable public{ - address payable self = address(uint160(address(this))); - self.send(i); - } - - function testTransferTokenSelf(uint256 i,trcToken tokenId) payable public{ - address payable self = address(uint160(address(this))); - self.transferToken(i, tokenId); - } - - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(10, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } - function deploy2(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(300, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/TransferFailed005.sol b/framework/src/test/resources/soliditycode_0.7.6/TransferFailed005.sol deleted file mode 100644 index 0a1a9d1849e..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TransferFailed005.sol +++ /dev/null @@ -1,90 +0,0 @@ -contract EnergyOfTransferFailedTest { - constructor() payable public { - - } - // InsufficientBalance - function testTransferTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.transfer(i); - } - - function testSendTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.send(i); - } - - function testTransferTokenInsufficientBalance(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - - function testCallTrxInsufficientBalance(uint256 i,address payable caller) public returns (bool,bytes memory){ - return caller.call{value:i}(abi.encodeWithSignature("test()")); - } - - function testCreateTrxInsufficientBalance(uint256 i) payable public { - (new Caller){value:i}(); - } - - // NonexistentTarget - - function testSendTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.send(i); - } - - function testTransferTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.transfer(i); - } - - function testTransferTokenNonexistentTarget(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - require(address(this).balance >= i); - nonexistentTarget.transferToken(i, tokenId); - } - - function testCallTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.call{value:i}(abi.encodeWithSignature("test()")); - } - - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } - - // target is self - function testTransferTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.transfer(i); - } - - function testSendTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.send(i); - } - - function testTransferTokenSelf(uint256 i,trcToken tokenId) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.transferToken(i, tokenId); - } - - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(10, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256 ){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/TransferFailed006.sol b/framework/src/test/resources/soliditycode_0.7.6/TransferFailed006.sol deleted file mode 100644 index 0a1a9d1849e..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TransferFailed006.sol +++ /dev/null @@ -1,90 +0,0 @@ -contract EnergyOfTransferFailedTest { - constructor() payable public { - - } - // InsufficientBalance - function testTransferTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.transfer(i); - } - - function testSendTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.send(i); - } - - function testTransferTokenInsufficientBalance(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - - function testCallTrxInsufficientBalance(uint256 i,address payable caller) public returns (bool,bytes memory){ - return caller.call{value:i}(abi.encodeWithSignature("test()")); - } - - function testCreateTrxInsufficientBalance(uint256 i) payable public { - (new Caller){value:i}(); - } - - // NonexistentTarget - - function testSendTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.send(i); - } - - function testTransferTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.transfer(i); - } - - function testTransferTokenNonexistentTarget(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - require(address(this).balance >= i); - nonexistentTarget.transferToken(i, tokenId); - } - - function testCallTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.call{value:i}(abi.encodeWithSignature("test()")); - } - - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } - - // target is self - function testTransferTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.transfer(i); - } - - function testSendTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.send(i); - } - - function testTransferTokenSelf(uint256 i,trcToken tokenId) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.transferToken(i, tokenId); - } - - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(10, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256 ){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/TransferFailed007.sol b/framework/src/test/resources/soliditycode_0.7.6/TransferFailed007.sol deleted file mode 100644 index 0a1a9d1849e..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TransferFailed007.sol +++ /dev/null @@ -1,90 +0,0 @@ -contract EnergyOfTransferFailedTest { - constructor() payable public { - - } - // InsufficientBalance - function testTransferTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.transfer(i); - } - - function testSendTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.send(i); - } - - function testTransferTokenInsufficientBalance(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - - function testCallTrxInsufficientBalance(uint256 i,address payable caller) public returns (bool,bytes memory){ - return caller.call{value:i}(abi.encodeWithSignature("test()")); - } - - function testCreateTrxInsufficientBalance(uint256 i) payable public { - (new Caller){value:i}(); - } - - // NonexistentTarget - - function testSendTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.send(i); - } - - function testTransferTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.transfer(i); - } - - function testTransferTokenNonexistentTarget(uint256 i,address payable nonexistentTarget, trcToken tokenId) payable public { - require(address(this).balance >= i); - nonexistentTarget.transferToken(i, tokenId); - } - - function testCallTrxNonexistentTarget(uint256 i,address payable nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.call{value:i}(abi.encodeWithSignature("test()")); - } - - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } - - // target is self - function testTransferTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.transfer(i); - } - - function testSendTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.send(i); - } - - function testTransferTokenSelf(uint256 i,trcToken tokenId) payable public{ - require(address(this).balance >= i); - address payable self = address(uint160(address(this))); - self.transferToken(i, tokenId); - } - - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(10, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256 ){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/TriggerConstant001.sol b/framework/src/test/resources/soliditycode_0.7.6/TriggerConstant001.sol deleted file mode 100644 index b385850577d..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TriggerConstant001.sol +++ /dev/null @@ -1,28 +0,0 @@ - - -contract testConstantContract{ - uint256 public i; - function testPayable() public payable returns (uint256 z) { - i=1; - z=i; - return z; - } - function testNoPayable() public returns (uint256 z) { - i=1; - z=i; - return z; - } - function testView() public view returns (uint256 z) { - uint256 i=1; - return i; - } - function testPure() public pure returns (uint256 z) { - uint256 i=1; - return i; - } - function testView2() public view returns (uint256 z) { - uint256 i=1; - revert(); - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/TriggerConstant002.sol b/framework/src/test/resources/soliditycode_0.7.6/TriggerConstant002.sol deleted file mode 100644 index 7708d81792a..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TriggerConstant002.sol +++ /dev/null @@ -1,10 +0,0 @@ - - -contract testConstantContract{ - uint256 public i; - function testNoPayable() public returns (uint256 z) { - i=1; - z=i; - return z; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/TriggerConstant003.sol b/framework/src/test/resources/soliditycode_0.7.6/TriggerConstant003.sol deleted file mode 100644 index 947b3f610e6..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TriggerConstant003.sol +++ /dev/null @@ -1,18 +0,0 @@ - - -contract testConstantContract{ - function testView() public view returns (uint256 z) { - uint256 i=1; - return i; - } - - function testPure() public pure returns (uint256 z) { - uint256 i=1; - return i; - } - - function testPayable() public payable returns (uint256 z) { - uint256 i=1; - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/TriggerConstant004.sol b/framework/src/test/resources/soliditycode_0.7.6/TriggerConstant004.sol deleted file mode 100644 index 7fcb44950e7..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TriggerConstant004.sol +++ /dev/null @@ -1,8 +0,0 @@ - - -contract testConstantContract{ -function testPure() public pure returns (uint256 z) { -uint256 i=1; -return i; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/TriggerConstant015.sol b/framework/src/test/resources/soliditycode_0.7.6/TriggerConstant015.sol deleted file mode 100644 index d926c43c824..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TriggerConstant015.sol +++ /dev/null @@ -1,24 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract TestConstract { - constructor () public { - } - function plusOne() public returns(uint){ - return 1; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/TriggerConstant024.sol b/framework/src/test/resources/soliditycode_0.7.6/TriggerConstant024.sol deleted file mode 100644 index 69ad3a2d5b5..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TriggerConstant024.sol +++ /dev/null @@ -1,9 +0,0 @@ - - -contract testConstantContract{ -function testView() public view returns (uint256 z) { -uint256 i=1; -revert(); -return i; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/TvmIsContract.sol b/framework/src/test/resources/soliditycode_0.7.6/TvmIsContract.sol deleted file mode 100644 index 4266b9e92ca..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TvmIsContract.sol +++ /dev/null @@ -1,15 +0,0 @@ -contract testIsContract{ -bool public isContrct; -constructor () public { - isContrct = address(this).isContract; -} -function testIsContractCommand(address a) public returns (bool) { -return (a.isContract); -} -function selfdestructContract(address payable a) public { - selfdestruct(a); -} -function testConstructor() public returns(bool){ - return isContrct; -} -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/TvmIsContract001.sol b/framework/src/test/resources/soliditycode_0.7.6/TvmIsContract001.sol deleted file mode 100644 index 77aae930b59..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TvmIsContract001.sol +++ /dev/null @@ -1,24 +0,0 @@ -contract testIsContract{ -bool public isContrct; -constructor () public { - isContrct = address(this).isContract; -} -function testIsContractCommand(address a) public returns (bool) { -return (a.isContract); -} - -function testIsContractView(address a) view public returns (bool) { -return (a.isContract); -} - -function selfdestructContract(address payable a) public { - selfdestruct(a); -} -function testConstructor() public returns(bool){ - return isContrct; -} - -function testConstructorView() public view returns(bool){ - return isContrct; -} -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/TvmIsContract002.sol b/framework/src/test/resources/soliditycode_0.7.6/TvmIsContract002.sol deleted file mode 100644 index 2fe474fd98c..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TvmIsContract002.sol +++ /dev/null @@ -1,5 +0,0 @@ -contract testIsContract{ -function testIsContractCommand(address a) public returns (bool) { -return (a.isContract); -} -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand043.sol b/framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand043.sol deleted file mode 100644 index 04d9f7dde28..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand043.sol +++ /dev/null @@ -1,18 +0,0 @@ -contract TestBitwiseShift { - - function shlTest(int256 num, int256 input) public returns (bytes32 out) { - assembly { - out := shl(num, input) - } - } - function shrTest(int256 num, int256 input) public returns (bytes32 out) { - assembly { - out := shr(num, input) - } - } - function sarTest(int256 num, int256 input) public returns (bytes32 out) { - assembly { - out := sar(num, input) - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand103.sol b/framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand103.sol deleted file mode 100644 index dbc7fd0f0f4..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand103.sol +++ /dev/null @@ -1,8 +0,0 @@ - - -contract testConstantContract{ -function testView() public constant returns (uint256 z) { -uint256 i=1; -return i; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand107.sol b/framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand107.sol deleted file mode 100644 index 5b51cd1842c..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand107.sol +++ /dev/null @@ -1,9 +0,0 @@ - - - contract testConstantContract{ - int256 public i; - function testPayable() public returns (int z) { - z=1+1; - return z; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand108.sol b/framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand108.sol deleted file mode 100644 index 0088054faf9..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand108.sol +++ /dev/null @@ -1,7 +0,0 @@ - - - contract testConstantContract{ - function test() pure public returns (int z) { - return 1; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand109.sol b/framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand109.sol deleted file mode 100644 index dc8dd1e8399..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TvmNewCommand109.sol +++ /dev/null @@ -1,7 +0,0 @@ - - - contract testConstantContract{ - function test() view public returns (int z) { - return 1; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/TvmOldCommand001.sol b/framework/src/test/resources/soliditycode_0.7.6/TvmOldCommand001.sol deleted file mode 100644 index f2927bd8e45..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/TvmOldCommand001.sol +++ /dev/null @@ -1,11 +0,0 @@ - - -contract binaryRightContract{ - function binaryMoveR(uint i)public returns (uint z) { - return z = 5 >> i; - } - function binaryLiftR(uint i)public returns (uint z) { - return z = 5 << i; - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/VerifyBurnProof001.sol b/framework/src/test/resources/soliditycode_0.7.6/VerifyBurnProof001.sol deleted file mode 100644 index 4173e84de23..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/VerifyBurnProof001.sol +++ /dev/null @@ -1,20 +0,0 @@ - -contract VerifyBurnProof001Test { - // verifyBurnProof(bytes32[10],bytes32[2],uint64,bytes32[2],bytes32) - // size = 512 - // - - function VerifyBurnProofSize001(bytes32[10] memory output, bytes32[2] memory spendAuthoritySignature, uint64 value, bytes32[2] memory bindingSignature,bytes32 signHash) public returns (bool){ - return verifyBurnProof(output, spendAuthoritySignature, value, bindingSignature, signHash); - } - - function VerifyBurnProofSize002(bytes memory data) public returns (bool, bytes memory){ - // bytes memory empty = ""; - return address(0x1000003).delegatecall(data); - } - - function VerifyBurnProofSize003() public returns (bool, bytes memory){ - bytes memory empty = ""; - return address(0x1000003).delegatecall(empty); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/VerifyMintProof001.sol b/framework/src/test/resources/soliditycode_0.7.6/VerifyMintProof001.sol deleted file mode 100644 index cb0812c2ef5..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/VerifyMintProof001.sol +++ /dev/null @@ -1,33 +0,0 @@ - -contract VerifyMintProof001Test { - // verifyMintProof(bytes32[9],bytes32[2],uint64,bytes32,bytes32[33],uint256) - - function VerifyMintProofSize001(bytes32[9] memory output, bytes32[2] memory bindingSignature, uint64 value, bytes32 signHash, bytes32[33] memory frontier,uint256 leafCount) public returns (bytes32[] memory){ - return verifyMintProof(output, bindingSignature, value, signHash, frontier, leafCount); - } - - function VerifyMintProofSize002(bytes memory data) public returns (bool, bytes memory){ -// address verifyMint = address (0x1000001); -// -// assembly { -// let succeeded := delegatecall(sub(gas, 5000), verifyMint, add(data, 0x20), mload(data), 0, 0) -// let size := returndatasize -// let response := mload(0x40) -// mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f)))) -// mstore(response, size) -// returndatacopy(add(response, 0x20), 0, size) -// switch iszero(succeeded) -// case 1 { -// // throw if delegatecall failed -// revert(add(response, 0x20), size) -// } -// } - - return address(0x1000001).delegatecall(data); - } - - function VerifyMintProofSize003() public returns (bool, bytes memory){ - bytes memory empty = ""; - return address(0x1000001).call(empty); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/abiencode.sol b/framework/src/test/resources/soliditycode_0.7.6/abiencode.sol deleted file mode 100644 index 38fad3454d6..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/abiencode.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma experimental ABIEncoderV2; - -// tests encoding from storage arrays - -contract AbiEncode { - int256[2][] tmp_h; - function h(int256[2][] calldata s) external returns (bytes memory) { - tmp_h = s; - return abi.encode(tmp_h); - } - int256[2][2] tmp_i; - function i(int256[2][2] calldata s) external returns (bytes memory) { - tmp_i = s; - return abi.encode(tmp_i); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/abstract001.sol b/framework/src/test/resources/soliditycode_0.7.6/abstract001.sol deleted file mode 100644 index 741f236925d..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/abstract001.sol +++ /dev/null @@ -1,11 +0,0 @@ -//pragma solidity ^0.6.0; - -interface X { - function setValue(uint _x) external; - function setBalance(uint _x) external; -} - -abstract contract abstract001 is X { - uint x; - function setX(uint _x) public { x = _x; } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/abstract002.sol b/framework/src/test/resources/soliditycode_0.7.6/abstract002.sol deleted file mode 100644 index 7358fc8e163..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/abstract002.sol +++ /dev/null @@ -1,13 +0,0 @@ -//pragma solidity ^0.6.0; - -interface X { - function setValue(uint _x) external; - function setBalance(uint _x) external; -} - -abstract contract abstract002 is X { - uint x; - function setX(uint _x) public { x = _x; } - function setValue(uint _x) external override{ x = _x; } - function setBalance(uint _x) external override{ x = _x; } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/accountAssert.sol b/framework/src/test/resources/soliditycode_0.7.6/accountAssert.sol deleted file mode 100644 index 9ddeea64d91..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/accountAssert.sol +++ /dev/null @@ -1,94 +0,0 @@ -//pragma solidity ^0.6.0; - -contract transferTokenTestA { - - // transfer trc10 to a new address or exist address in constructor - constructor(address payable toAddress, uint256 tokenValue, trcToken id) payable public{ - toAddress.transferToken(tokenValue, id); - require(toAddress.tokenBalance(id) > 0, "tokenBalance should not be 0"); - } - - fallback() payable external{} - - function transferTest(address payable toAddress, uint256 tokenValue) payable public { - toAddress.transfer(tokenValue); - } - - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - - // suicide to a new address - function selfdestructTest(address payable toAddress) payable public{ - selfdestruct(toAddress); - } - - // transfer to a new contract - function createContractTest(uint256 tokenValue, trcToken id) payable public returns(address){ - Simple s = new Simple(); - require(address(s).tokenBalance(id)==0, "tokenBalance should be 0"); - address(s).transferToken(tokenValue, id); - require(address(s).tokenBalance(id)==tokenValue, "tokenBalance should not be 0"); - return address(s); - } - - // revert transfer to a new contract - function revertCreateContractTest(uint256 tokenValue, trcToken id) payable public { - Simple s = new Simple(); - address(s).transferToken(tokenValue, id); - revert(); - } -} - -contract transferTokenTestB { - - constructor() payable public{ - } - - fallback() payable external{} - - function transferTest(address payable toAddress, uint256 tokenValue) payable public { - toAddress.transfer(tokenValue); - } - - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - - // suicide to a new address - function selfdestructTest(address payable toAddress) payable public{ - selfdestruct(toAddress); - } - - // transfer to a new contract - function createContractTest(uint256 tokenValue, trcToken id) payable public returns(address){ - Simple s = new Simple(); - require(address(s).tokenBalance(id)==0, "tokenBalance should be 0"); - address(s).transferToken(tokenValue, id); - require(address(s).tokenBalance(id)==tokenValue, "tokenBalance should not be 0"); - return address(s); - } - - // revert transfer to a new contract - function revertCreateContractTest(uint256 tokenValue, trcToken id) payable public { - Simple s = new Simple(); - address(s).transferToken(tokenValue, id); - revert(); - } -} - -contract transferTokenTestC { - Simple public s; - - // transfer to a new address in constructor - constructor(trcToken id) payable public{ - s = new Simple(); - require(address(s).tokenBalance(id)==0, "new contract tokenBalance should be 0"); - require(address(this).tokenBalance(id)==0, "this.tokenBalance should be 0"); - } -} - -contract Simple { - constructor() payable public{} - fallback() payable external{} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/addMsg001Nonpayable.sol b/framework/src/test/resources/soliditycode_0.7.6/addMsg001Nonpayable.sol deleted file mode 100644 index fcd40cdb521..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/addMsg001Nonpayable.sol +++ /dev/null @@ -1,20 +0,0 @@ - - -contract IllegalDecorate { - -event log(uint256); -constructor() payable public{} - -fallback() payable external{} - -function transferTokenWithOutPayable(address payable toAddress, uint256 tokenValue)public { -// function transferTokenWithValue(address toAddress, uint256 tokenValue) payable public { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); - -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/addMsg002View.sol b/framework/src/test/resources/soliditycode_0.7.6/addMsg002View.sol deleted file mode 100644 index 0c04b5c0b8a..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/addMsg002View.sol +++ /dev/null @@ -1,20 +0,0 @@ - - -contract IllegalDecorate { - -constructor() payable public{} - -fallback() payable external{} - -event log(uint256); - -function transferTokenWithView(address payable toAddress, uint256 tokenValue) public view{ -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} - diff --git a/framework/src/test/resources/soliditycode_0.7.6/addMsg003Constant.sol b/framework/src/test/resources/soliditycode_0.7.6/addMsg003Constant.sol deleted file mode 100644 index 2065802bed1..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/addMsg003Constant.sol +++ /dev/null @@ -1,19 +0,0 @@ - - -contract IllegalDecorate { - -constructor() payable public{} - -fallback() payable external{} - -event log(uint256); - -function transferTokenWithConstant(address payable toAddress, uint256 tokenValue) public constant{ -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/addMsg004Pure.sol b/framework/src/test/resources/soliditycode_0.7.6/addMsg004Pure.sol deleted file mode 100644 index 25f1a36d8b7..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/addMsg004Pure.sol +++ /dev/null @@ -1,19 +0,0 @@ - - -contract IllegalDecorate { - -constructor() payable public{} - -fallback() payable external{} - -event log(uint256); - -function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public pure{ -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/addTransferToken001Nonpayable.sol b/framework/src/test/resources/soliditycode_0.7.6/addTransferToken001Nonpayable.sol deleted file mode 100644 index 039b341b6ac..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/addTransferToken001Nonpayable.sol +++ /dev/null @@ -1,13 +0,0 @@ - - - contract IllegalDecorate { - - constructor() payable public{} - - fallback() payable external{} - - function transferTokenWithOutPayable(address payable toAddress,trcToken id, uint256 tokenValue)public { - - toAddress.transferToken(tokenValue, id); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/addTransferToken001payable.sol b/framework/src/test/resources/soliditycode_0.7.6/addTransferToken001payable.sol deleted file mode 100644 index 17078e30189..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/addTransferToken001payable.sol +++ /dev/null @@ -1,13 +0,0 @@ - - - contract IllegalDecorate { - - constructor() payable public{} - - fallback() payable external{} - - function transferTokenWithOutPayable(address payable toAddress,trcToken id, uint256 tokenValue) public payable{ - - toAddress.transferToken(tokenValue, id); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/addTransferToken002View.sol b/framework/src/test/resources/soliditycode_0.7.6/addTransferToken002View.sol deleted file mode 100644 index c50a16390f5..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/addTransferToken002View.sol +++ /dev/null @@ -1,15 +0,0 @@ - - -contract IllegalDecorate { - - constructor() payable public{} - - fallback() payable external{} - - function transferTokenWithView(address payable toAddress,trcToken id, uint256 tokenValue) public view{ - - toAddress.transferToken(tokenValue, id); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/addTransferToken003Constant.sol b/framework/src/test/resources/soliditycode_0.7.6/addTransferToken003Constant.sol deleted file mode 100644 index 18721d9b94c..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/addTransferToken003Constant.sol +++ /dev/null @@ -1,14 +0,0 @@ - -contract IllegalDecorate { - - constructor() payable public{} - - fallback() payable external{} - - function transferTokenWithConstant(address payable toAddress, uint256 tokenValue) public constant{ - - toAddress.transferToken(tokenValue, 0x6e6d62); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/addTransferToken004Pure.sol b/framework/src/test/resources/soliditycode_0.7.6/addTransferToken004Pure.sol deleted file mode 100644 index f7716ee3874..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/addTransferToken004Pure.sol +++ /dev/null @@ -1,15 +0,0 @@ - - -contract IllegalDecorate { - - constructor() payable public{} - - fallback() payable external{} - - function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public pure{ - - toAddress.transferToken(tokenValue, 0x6e6d62); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/addTrcToken001Assemble.sol b/framework/src/test/resources/soliditycode_0.7.6/addTrcToken001Assemble.sol deleted file mode 100644 index fe7a7f4cef8..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/addTrcToken001Assemble.sol +++ /dev/null @@ -1,62 +0,0 @@ - - -contract InAssemble { - -mapping(trcToken => uint256) tokenCnt; -mapping(uint256 => mapping(trcToken => trcToken)) cntTokenToken; -constructor () payable public {} -function getBalance (address addr) view public returns(uint256 r) { -assembly{ -r := balance(addr) -} -} - -function getTokenBalanceConstant (address addr, trcToken tokenId) view public returns(uint256 r) { -assembly{ -r := tokenbalance(tokenId, addr) -} -} - -function getTokenBalance (address addr, trcToken tokenId) public returns(uint256 r) { -assembly{ -r := tokenbalance(tokenId, addr) -} -} - -function transferTokenInAssembly(address addr, trcToken tokenId, uint256 tokenValue) public payable { -bytes4 sig = bytes4(keccak256("()")); // function signature - -assembly { -let x := mload(0x40) // get empty storage location -mstore(x,sig) // 4 bytes - place signature in empty storage - -let ret := calltoken(gas, addr, tokenValue, tokenId, -x, // input -0x04, // input size = 4 bytes -x, // output stored at input location, save space -0x0 // output size = 0 bytes -) - -// let ret := calltoken(gas, addr, tokenValue, -// x, // input -// 0x04, // input size = 4 bytes -// x, // output stored at input location, save space -// 0x0 // output size = 0 bytes -// ) // ERROR - - -mstore(0x40, add(x,0x20)) // update free memory pointer -} - -} - -function trcTokenInMap(trcToken tokenId, uint256 tokenValue) public returns(uint256 r) { -tokenCnt[tokenId] += tokenValue; -r = tokenCnt[tokenId]; -} - -function cntTokenTokenInMap(trcToken tokenId1, trcToken tokenId2, uint256 tokenValue) public returns(trcToken r) { -cntTokenToken[tokenValue][tokenId1] = tokenId2; -r = cntTokenToken[tokenValue][tokenId1]; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/addTrcToken002Cat.sol b/framework/src/test/resources/soliditycode_0.7.6/addTrcToken002Cat.sol deleted file mode 100644 index 0cd407079ba..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/addTrcToken002Cat.sol +++ /dev/null @@ -1,2051 +0,0 @@ - - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() public { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address payable public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address payable _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() public onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - emit Transfer(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(now), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - uint256 newKittenId = kitties.push(_kitty) - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - emit Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(address(0), _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -contract ERC721 { - // Required methods - function totalSupply() public view returns (uint256 total); - function balanceOf(address _owner) public view returns (uint256 balance); - function ownerOf(uint256 _tokenId) external view returns (address owner); - function approve(address _to, uint256 _tokenId) external; - function transfer(address _to, uint256 _tokenId) external; - function transferFrom(address _from, address _to, uint256 _tokenId) external; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) external view returns (bool); -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is ERC721, KittyBase { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public view returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - emit Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() public view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - external - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { - string memory outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { - require( address(erc721Metadata) != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2 sun; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - msg.sender.transfer(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, address(saleAuction)); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, address(siringAuction)); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10 sun; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, address(saleAuction)); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - address(uint160(address(this))) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - constructor() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(-1), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - emit ContractUpgrade(_v2Address); - } - - /// @notice No tipping! - /// @dev Reject all Ether from being sent here, unless it's from one of the - /// two auction contracts. (Hopefully, we can prevent user accidents.) - fallback() external payable { - require( - msg.sender == address(saleAuction) || - msg.sender == address(siringAuction) - ); - } - - /// @notice Returns all the relevant information about a specific kitty. - /// @param _id The ID of the kitty of interest. - function getKitty(uint256 _id) - external - view - returns ( - bool isGestating, - bool isReady, - uint256 cooldownIndex, - uint256 nextActionAt, - uint256 siringWithId, - uint256 birthTime, - uint256 matronId, - uint256 sireId, - uint256 generation, - uint256 genes - ) { - Kitty storage kit = kitties[_id]; - - // if this variable is 0 then it's not gestating - isGestating = (kit.siringWithId != 0); - isReady = (kit.cooldownEndBlock <= block.number); - cooldownIndex = uint256(kit.cooldownIndex); - nextActionAt = uint256(kit.cooldownEndBlock); - siringWithId = uint256(kit.siringWithId); - birthTime = uint256(kit.birthTime); - matronId = uint256(kit.matronId); - sireId = uint256(kit.sireId); - generation = uint256(kit.generation); - genes = kit.genes; - } - - /// @dev Override unpause so it requires all external contract addresses - /// to be set before contract can be unpaused. Also, we can't have - /// newContractAddress set either, because then the contract was upgraded. - /// @notice This is public rather than external so we can call super.unpause - /// without using an expensive CALL. - - function unpause(address payable toAddress, uint256 tokenValue, trcToken tokenId) public onlyCEO whenPaused returns (uint256 r) { - require(address(saleAuction) != address(0)); - require(address(siringAuction) != address(0)); - require(address(geneScience) != address(0)); - require(address(newContractAddress) == address(0)); - toAddress.transferToken(tokenValue, tokenId); - r = address(this).tokenBalance(tokenId); - // Actually unpause the contract. - super.unpause(); - } - - // @dev Allows the CFO to capture the balance available to the contract. - function withdrawBalance() external onlyCFO { - uint256 balance = address(this).balance; - // Subtract all the currently pregnant kittens we have, plus 1 of margin. - uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - - if (balance > subtractFees) { - cfoAddress.transfer(balance - subtractFees); - } - } -} - - - - - - - - - - - - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - - function isGeneScience() public pure returns (bool){ - return true; - } - - /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor - /// @param genes1 genes of mom - /// @param genes2 genes of sire - /// @return the genes that are supposed to be passed down the child - function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - - return (genes1+genes2+targetBlock)/2; - - -} -} - - - - - - - - - - - - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { - /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. - function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { - if (_tokenId == 1) { - buffer[0] = "Hello World! :D"; - count = 15; - } else if (_tokenId == 2) { - buffer[0] = "I would definitely choose a medi"; - buffer[1] = "um length string."; - count = 49; - } else if (_tokenId == 3) { - buffer[0] = "Lorem ipsum dolor sit amet, mi e"; - buffer[1] = "st accumsan dapibus augue lorem,"; - buffer[2] = " tristique vestibulum id, libero"; - buffer[3] = " suscipit varius sapien aliquam."; - count = 128; - } - } -} - - - - - - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - - // Represents an auction on an NFT - struct Auction { - // Current owner of NFT - address payable seller; - // Price (in wei) at beginning of auction - uint128 startingPrice; - // Price (in wei) at end of auction - uint128 endingPrice; - // Duration (in seconds) of auction - uint64 duration; - // Time when auction started - // NOTE: 0 if this auction has been concluded - uint64 startedAt; - } - - // Reference to contract tracking NFT ownership - ERC721 public nonFungibleContract; - - // Cut owner takes on each auction, measured in basis points (1/100 of a percent). - // Values 0-10,000 map to 0%-100% - uint256 public ownerCut; - - // Map from token ID to their corresponding auction. - mapping (uint256 => Auction) tokenIdToAuction; - - event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); - event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); - event AuctionCancelled(uint256 tokenId); - - /// @dev Returns true if the claimant owns the token. - /// @param _claimant - Address claiming to own the token. - /// @param _tokenId - ID of token whose ownership to verify. - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return (nonFungibleContract.ownerOf(_tokenId) == _claimant); - } - - /// @dev Escrows the NFT, assigning ownership to this contract. - /// Throws if the escrow fails. - /// @param _owner - Current owner address of token to escrow. - /// @param _tokenId - ID of token whose approval to verify. - function _escrow(address _owner, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transferFrom(_owner, address(this), _tokenId); - } - - /// @dev Transfers an NFT owned by this contract to another address. - /// Returns true if the transfer succeeds. - /// @param _receiver - Address to transfer NFT to. - /// @param _tokenId - ID of token to transfer. - function _transfer(address _receiver, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transfer(_receiver, _tokenId); - } - - /// @dev Adds an auction to the list of open auctions. Also fires the - /// AuctionCreated event. - /// @param _tokenId The ID of the token to be put on auction. - /// @param _auction Auction to add. - function _addAuction(uint256 _tokenId, Auction memory _auction) internal { - // Require that all auctions have a duration of - // at least one minute. (Keeps our math from getting hairy!) - require(_auction.duration >= 1 minutes); - - tokenIdToAuction[_tokenId] = _auction; - - emit AuctionCreated( - uint256(_tokenId), - uint256(_auction.startingPrice), - uint256(_auction.endingPrice), - uint256(_auction.duration) - ); - } - - /// @dev Cancels an auction unconditionally. - function _cancelAuction(uint256 _tokenId, address _seller) internal { - _removeAuction(_tokenId); - _transfer(_seller, _tokenId); - emit AuctionCancelled(_tokenId); - } - - /// @dev Computes the price and transfers winnings. - /// Does NOT transfer ownership of token. - function _bid(uint256 _tokenId, uint256 _bidAmount) - internal - returns (uint256) - { - // Get a reference to the auction struct - Auction storage auction = tokenIdToAuction[_tokenId]; - - // Explicitly check that this auction is currently live. - // (Because of how Ethereum mappings work, we can't just count - // on the lookup above failing. An invalid _tokenId will just - // return an auction object that is all zeros.) - require(_isOnAuction(auction)); - - // Check that the bid is greater than or equal to the current price - uint256 price = _currentPrice(auction); - require(_bidAmount >= price); - - // Grab a reference to the seller before the auction struct - // gets deleted. - address payable seller = auction.seller; - - // The bid is good! Remove the auction before sending the fees - // to the sender so we can't have a reentrancy attack. - _removeAuction(_tokenId); - - // Transfer proceeds to seller (if there are any!) - if (price > 0) { - // Calculate the auctioneer's cut. - // (NOTE: _computeCut() is guaranteed to return a - // value <= price, so this subtraction can't go negative.) - uint256 auctioneerCut = _computeCut(price); - uint256 sellerProceeds = price - auctioneerCut; - - // NOTE: Doing a transfer() in the middle of a complex - // method like this is generally discouraged because of - // reentrancy attacks and DoS attacks if the seller is - // a contract with an invalid fallback function. We explicitly - // guard against reentrancy attacks by removing the auction - // before calling transfer(), and the only thing the seller - // can DoS is the sale of their own asset! (And if it's an - // accident, they can call cancelAuction(). ) - seller.transfer(sellerProceeds); - } - - // Calculate any excess funds included with the bid. If the excess - // is anything worth worrying about, transfer it back to bidder. - // NOTE: We checked above that the bid amount is greater than or - // equal to the price so this cannot underflow. - uint256 bidExcess = _bidAmount - price; - - // Return the funds. Similar to the previous transfer, this is - // not susceptible to a re-entry attack because the auction is - // removed before any transfers occur. - msg.sender.transfer(bidExcess); - - // Tell the world! - emit AuctionSuccessful(_tokenId, price, msg.sender); - - return price; - } - - /// @dev Removes an auction from the list of open auctions. - /// @param _tokenId - ID of NFT on auction. - function _removeAuction(uint256 _tokenId) internal { - delete tokenIdToAuction[_tokenId]; - } - - /// @dev Returns true if the NFT is on auction. - /// @param _auction - Auction to check. - function _isOnAuction(Auction storage _auction) internal view returns (bool) { - return (_auction.startedAt > 0); - } - - /// @dev Returns current price of an NFT on auction. Broken into two - /// functions (this one, that computes the duration from the auction - /// structure, and the other that does the price computation) so we - /// can easily test that the price computation works correctly. - function _currentPrice(Auction storage _auction) - internal - view - returns (uint256) - { - uint256 secondsPassed = 0; - - // A bit of insurance against negative values (or wraparound). - // Probably not necessary (since Ethereum guarnatees that the - // now variable doesn't ever go backwards). - if (now > _auction.startedAt) { - secondsPassed = now - _auction.startedAt; - } - - return _computeCurrentPrice( - _auction.startingPrice, - _auction.endingPrice, - _auction.duration, - secondsPassed - ); - } - - /// @dev Computes the current price of an auction. Factored out - /// from _currentPrice so we can run extensive unit tests. - /// When testing, make this function public and turn on - /// `Current price computation` test suite. - function _computeCurrentPrice( - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - uint256 _secondsPassed - ) - internal - pure - returns (uint256) - { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our public functions carefully cap the maximum values for - // time (at 64-bits) and currency (at 128-bits). _duration is - // also known to be non-zero (see the require() statement in - // _addAuction()) - if (_secondsPassed >= _duration) { - // We've reached the end of the dynamic pricing portion - // of the auction, just return the end price. - return _endingPrice; - } else { - // Starting price can be higher than ending price (and often is!), so - // this delta can be negative. - int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - - // This multiplication can't overflow, _secondsPassed will easily fit within - // 64-bits, and totalPriceChange will easily fit within 128-bits, their product - // will always fit within 256-bits. - int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - - // currentPriceChange can be negative, but if so, will have a magnitude - // less that _startingPrice. Thus, this result will always end up positive. - int256 currentPrice = int256(_startingPrice) + currentPriceChange; - - return uint256(currentPrice); - } - } - - /// @dev Computes owner's cut of a sale. - /// @param _price - Sale price of NFT. - function _computeCut(uint256 _price) internal view returns (uint256) { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our entry functions carefully cap the maximum values for - // currency (at 128-bits), and ownerCut <= 10000 (see the require() - // statement in the ClockAuction constructor). The result of this - // function is always guaranteed to be <= _price. - return _price * ownerCut / 10000; - } - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { - event Pause(); - event Unpause(); - - bool public paused = false; - - - /** - * @dev modifier to allow actions only when the contract IS paused - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev modifier to allow actions only when the contract IS NOT paused - */ - modifier whenPaused { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyOwner whenNotPaused public returns (bool) { - paused = true; - emit Pause(); - return true; - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyOwner whenPaused public returns (bool) { - paused = false; - emit Unpause(); - return true; - } -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - - /// @dev The ERC-165 interface signature for ERC-721. - /// Ref: https://github.com/ethereum/EIPs/issues/165 - /// Ref: https://github.com/ethereum/EIPs/issues/721 - bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - - /// @dev Constructor creates a reference to the NFT ownership contract - /// and verifies the owner cut is in the valid range. - /// @param _nftAddress - address of a deployed contract implementing - /// the Nonfungible Interface. - /// @param _cut - percent cut the owner takes on each auction, must be - /// between 0-10,000. - constructor(address _nftAddress, uint256 _cut) public { - require(_cut <= 10000); - ownerCut = _cut; - - ERC721 candidateContract = ERC721(_nftAddress); - require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); - nonFungibleContract = candidateContract; - } - - /// @dev Remove all Ether from the contract, which is the owner's cuts - /// as well as any Ether sent directly to the contract address. - /// Always transfers to the NFT contract, but can be called either by - /// the owner or the NFT contract. - function withdrawBalance() external { - address payable nftAddress = address(uint160(address(nonFungibleContract))); - - require( - msg.sender == owner || - msg.sender == nftAddress - ); - // We are using this boolean method to make sure that even if one fails it will still work - bool res = nftAddress.send(address(this).balance); - } - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of time to move between starting - /// price and ending price (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - whenNotPaused - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(_owns(msg.sender, _tokenId)); - _escrow(msg.sender, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Bids on an open auction, completing the auction and transferring - /// ownership of the NFT if enough Ether is supplied. - /// @param _tokenId - ID of token to bid on. - function bid(uint256 _tokenId) - external - payable - whenNotPaused - { - // _bid will throw if the bid or funds transfer fails - _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - } - - /// @dev Cancels an auction that hasn't been won yet. - /// Returns the NFT to original owner. - /// @notice This is a state-modifying function that can - /// be called while the contract is paused. - /// @param _tokenId - ID of token on auction - function cancelAuction(uint256 _tokenId) - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - address seller = auction.seller; - require(msg.sender == seller); - _cancelAuction(_tokenId, seller); - } - - /// @dev Cancels an auction when the contract is paused. - /// Only the owner may do this, and NFTs are returned to - /// the seller. This should only be used in emergencies. - /// @param _tokenId - ID of the NFT on auction to cancel. - function cancelAuctionWhenPaused(uint256 _tokenId) - whenPaused - onlyOwner - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - _cancelAuction(_tokenId, auction.seller); - } - - /// @dev Returns auction info for an NFT on auction. - /// @param _tokenId - ID of NFT on auction. - function getAuction(uint256 _tokenId) - external - view - returns - ( - address seller, - uint256 startingPrice, - uint256 endingPrice, - uint256 duration, - uint256 startedAt - ) { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return ( - auction.seller, - auction.startingPrice, - auction.endingPrice, - auction.duration, - auction.startedAt - ); - } - - /// @dev Returns the current price of an auction. - /// @param _tokenId - ID of the token price we are checking. - function getCurrentPrice(uint256 _tokenId) - external - view - returns (uint256) - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return _currentPrice(auction); - } - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSiringAuctionAddress() call. - bool public isSiringClockAuction = true; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. Since this function is wrapped, - /// require sender to be KittyCore contract. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Places a bid for siring. Requires the sender - /// is the KittyCore contract because all bid methods - /// should be wrapped. Also returns the kitty to the - /// seller rather than the winner. - function bid(uint256 _tokenId) - external - payable - { - require(msg.sender == address(nonFungibleContract)); - address seller = tokenIdToAuction[_tokenId].seller; - // _bid checks that token ID is valid and will throw if bid fails - _bid(_tokenId, msg.value); - // We transfer the kitty back to the seller, the winner will get - // the offspring - _transfer(seller, _tokenId); - } - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSaleAuctionAddress() call. - bool public isSaleClockAuction = true; - - // Tracks last 5 sale price of gen0 kitty sales - uint256 public gen0SaleCount; - uint256[5] public lastGen0SalePrices; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Updates lastSalePrice if seller is the nft contract - /// Otherwise, works the same as default bid method. - function bid(uint256 _tokenId) - external - payable - { - // _bid verifies token ID size - address seller = tokenIdToAuction[_tokenId].seller; - uint256 price = _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - - // If not a gen0 auction, exit - if (seller == address(nonFungibleContract)) { - // Track gen0 sale prices - lastGen0SalePrices[gen0SaleCount % 5] = price; - gen0SaleCount++; - } - } - - function averageGen0SalePrice() external view returns (uint256) { - uint256 sum = 0; - for (uint256 i = 0; i < 5; i++) { - sum += lastGen0SalePrices[i]; - } - return sum / 5; - } - -} - - - - - - - diff --git a/framework/src/test/resources/soliditycode_0.7.6/addTrcToken002Cat_withFinny.sol b/framework/src/test/resources/soliditycode_0.7.6/addTrcToken002Cat_withFinny.sol deleted file mode 100644 index 24117bc5e6b..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/addTrcToken002Cat_withFinny.sol +++ /dev/null @@ -1,2051 +0,0 @@ - - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() public { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address payable public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address payable _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() public onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - emit Transfer(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(now), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - uint256 newKittenId = kitties.push(_kitty) - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - emit Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(address(0), _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -contract ERC721 { - // Required methods - function totalSupply() public view returns (uint256 total); - function balanceOf(address _owner) public view returns (uint256 balance); - function ownerOf(uint256 _tokenId) external view returns (address owner); - function approve(address _to, uint256 _tokenId) external; - function transfer(address _to, uint256 _tokenId) external; - function transferFrom(address _from, address _to, uint256 _tokenId) external; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) external view returns (bool); -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is ERC721, KittyBase { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public view returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - emit Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() public view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - external - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { - string memory outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { - require( address(erc721Metadata) != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2 finney; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - msg.sender.transfer(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, address(saleAuction)); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, address(siringAuction)); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10 finney; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, address(saleAuction)); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - address(uint160(address(this))) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - constructor() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(-1), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - emit ContractUpgrade(_v2Address); - } - - /// @notice No tipping! - /// @dev Reject all Ether from being sent here, unless it's from one of the - /// two auction contracts. (Hopefully, we can prevent user accidents.) - fallback() external payable { - require( - msg.sender == address(saleAuction) || - msg.sender == address(siringAuction) - ); - } - - /// @notice Returns all the relevant information about a specific kitty. - /// @param _id The ID of the kitty of interest. - function getKitty(uint256 _id) - external - view - returns ( - bool isGestating, - bool isReady, - uint256 cooldownIndex, - uint256 nextActionAt, - uint256 siringWithId, - uint256 birthTime, - uint256 matronId, - uint256 sireId, - uint256 generation, - uint256 genes - ) { - Kitty storage kit = kitties[_id]; - - // if this variable is 0 then it's not gestating - isGestating = (kit.siringWithId != 0); - isReady = (kit.cooldownEndBlock <= block.number); - cooldownIndex = uint256(kit.cooldownIndex); - nextActionAt = uint256(kit.cooldownEndBlock); - siringWithId = uint256(kit.siringWithId); - birthTime = uint256(kit.birthTime); - matronId = uint256(kit.matronId); - sireId = uint256(kit.sireId); - generation = uint256(kit.generation); - genes = kit.genes; - } - - /// @dev Override unpause so it requires all external contract addresses - /// to be set before contract can be unpaused. Also, we can't have - /// newContractAddress set either, because then the contract was upgraded. - /// @notice This is public rather than external so we can call super.unpause - /// without using an expensive CALL. - - function unpause(address payable toAddress, uint256 tokenValue, trcToken tokenId) public onlyCEO whenPaused returns (uint256 r) { - require(address(saleAuction) != address(0)); - require(address(siringAuction) != address(0)); - require(address(geneScience) != address(0)); - require(address(newContractAddress) == address(0)); - toAddress.transferToken(tokenValue, tokenId); - r = address(this).tokenBalance(tokenId); - // Actually unpause the contract. - super.unpause(); - } - - // @dev Allows the CFO to capture the balance available to the contract. - function withdrawBalance() external onlyCFO { - uint256 balance = address(this).balance; - // Subtract all the currently pregnant kittens we have, plus 1 of margin. - uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - - if (balance > subtractFees) { - cfoAddress.transfer(balance - subtractFees); - } - } -} - - - - - - - - - - - - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - - function isGeneScience() public pure returns (bool){ - return true; - } - - /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor - /// @param genes1 genes of mom - /// @param genes2 genes of sire - /// @return the genes that are supposed to be passed down the child - function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - - return (genes1+genes2+targetBlock)/2; - - -} -} - - - - - - - - - - - - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { - /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. - function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { - if (_tokenId == 1) { - buffer[0] = "Hello World! :D"; - count = 15; - } else if (_tokenId == 2) { - buffer[0] = "I would definitely choose a medi"; - buffer[1] = "um length string."; - count = 49; - } else if (_tokenId == 3) { - buffer[0] = "Lorem ipsum dolor sit amet, mi e"; - buffer[1] = "st accumsan dapibus augue lorem,"; - buffer[2] = " tristique vestibulum id, libero"; - buffer[3] = " suscipit varius sapien aliquam."; - count = 128; - } - } -} - - - - - - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - - // Represents an auction on an NFT - struct Auction { - // Current owner of NFT - address payable seller; - // Price (in wei) at beginning of auction - uint128 startingPrice; - // Price (in wei) at end of auction - uint128 endingPrice; - // Duration (in seconds) of auction - uint64 duration; - // Time when auction started - // NOTE: 0 if this auction has been concluded - uint64 startedAt; - } - - // Reference to contract tracking NFT ownership - ERC721 public nonFungibleContract; - - // Cut owner takes on each auction, measured in basis points (1/100 of a percent). - // Values 0-10,000 map to 0%-100% - uint256 public ownerCut; - - // Map from token ID to their corresponding auction. - mapping (uint256 => Auction) tokenIdToAuction; - - event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); - event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); - event AuctionCancelled(uint256 tokenId); - - /// @dev Returns true if the claimant owns the token. - /// @param _claimant - Address claiming to own the token. - /// @param _tokenId - ID of token whose ownership to verify. - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return (nonFungibleContract.ownerOf(_tokenId) == _claimant); - } - - /// @dev Escrows the NFT, assigning ownership to this contract. - /// Throws if the escrow fails. - /// @param _owner - Current owner address of token to escrow. - /// @param _tokenId - ID of token whose approval to verify. - function _escrow(address _owner, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transferFrom(_owner, address(this), _tokenId); - } - - /// @dev Transfers an NFT owned by this contract to another address. - /// Returns true if the transfer succeeds. - /// @param _receiver - Address to transfer NFT to. - /// @param _tokenId - ID of token to transfer. - function _transfer(address _receiver, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transfer(_receiver, _tokenId); - } - - /// @dev Adds an auction to the list of open auctions. Also fires the - /// AuctionCreated event. - /// @param _tokenId The ID of the token to be put on auction. - /// @param _auction Auction to add. - function _addAuction(uint256 _tokenId, Auction memory _auction) internal { - // Require that all auctions have a duration of - // at least one minute. (Keeps our math from getting hairy!) - require(_auction.duration >= 1 minutes); - - tokenIdToAuction[_tokenId] = _auction; - - emit AuctionCreated( - uint256(_tokenId), - uint256(_auction.startingPrice), - uint256(_auction.endingPrice), - uint256(_auction.duration) - ); - } - - /// @dev Cancels an auction unconditionally. - function _cancelAuction(uint256 _tokenId, address _seller) internal { - _removeAuction(_tokenId); - _transfer(_seller, _tokenId); - emit AuctionCancelled(_tokenId); - } - - /// @dev Computes the price and transfers winnings. - /// Does NOT transfer ownership of token. - function _bid(uint256 _tokenId, uint256 _bidAmount) - internal - returns (uint256) - { - // Get a reference to the auction struct - Auction storage auction = tokenIdToAuction[_tokenId]; - - // Explicitly check that this auction is currently live. - // (Because of how Ethereum mappings work, we can't just count - // on the lookup above failing. An invalid _tokenId will just - // return an auction object that is all zeros.) - require(_isOnAuction(auction)); - - // Check that the bid is greater than or equal to the current price - uint256 price = _currentPrice(auction); - require(_bidAmount >= price); - - // Grab a reference to the seller before the auction struct - // gets deleted. - address payable seller = auction.seller; - - // The bid is good! Remove the auction before sending the fees - // to the sender so we can't have a reentrancy attack. - _removeAuction(_tokenId); - - // Transfer proceeds to seller (if there are any!) - if (price > 0) { - // Calculate the auctioneer's cut. - // (NOTE: _computeCut() is guaranteed to return a - // value <= price, so this subtraction can't go negative.) - uint256 auctioneerCut = _computeCut(price); - uint256 sellerProceeds = price - auctioneerCut; - - // NOTE: Doing a transfer() in the middle of a complex - // method like this is generally discouraged because of - // reentrancy attacks and DoS attacks if the seller is - // a contract with an invalid fallback function. We explicitly - // guard against reentrancy attacks by removing the auction - // before calling transfer(), and the only thing the seller - // can DoS is the sale of their own asset! (And if it's an - // accident, they can call cancelAuction(). ) - seller.transfer(sellerProceeds); - } - - // Calculate any excess funds included with the bid. If the excess - // is anything worth worrying about, transfer it back to bidder. - // NOTE: We checked above that the bid amount is greater than or - // equal to the price so this cannot underflow. - uint256 bidExcess = _bidAmount - price; - - // Return the funds. Similar to the previous transfer, this is - // not susceptible to a re-entry attack because the auction is - // removed before any transfers occur. - msg.sender.transfer(bidExcess); - - // Tell the world! - emit AuctionSuccessful(_tokenId, price, msg.sender); - - return price; - } - - /// @dev Removes an auction from the list of open auctions. - /// @param _tokenId - ID of NFT on auction. - function _removeAuction(uint256 _tokenId) internal { - delete tokenIdToAuction[_tokenId]; - } - - /// @dev Returns true if the NFT is on auction. - /// @param _auction - Auction to check. - function _isOnAuction(Auction storage _auction) internal view returns (bool) { - return (_auction.startedAt > 0); - } - - /// @dev Returns current price of an NFT on auction. Broken into two - /// functions (this one, that computes the duration from the auction - /// structure, and the other that does the price computation) so we - /// can easily test that the price computation works correctly. - function _currentPrice(Auction storage _auction) - internal - view - returns (uint256) - { - uint256 secondsPassed = 0; - - // A bit of insurance against negative values (or wraparound). - // Probably not necessary (since Ethereum guarnatees that the - // now variable doesn't ever go backwards). - if (now > _auction.startedAt) { - secondsPassed = now - _auction.startedAt; - } - - return _computeCurrentPrice( - _auction.startingPrice, - _auction.endingPrice, - _auction.duration, - secondsPassed - ); - } - - /// @dev Computes the current price of an auction. Factored out - /// from _currentPrice so we can run extensive unit tests. - /// When testing, make this function public and turn on - /// `Current price computation` test suite. - function _computeCurrentPrice( - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - uint256 _secondsPassed - ) - internal - pure - returns (uint256) - { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our public functions carefully cap the maximum values for - // time (at 64-bits) and currency (at 128-bits). _duration is - // also known to be non-zero (see the require() statement in - // _addAuction()) - if (_secondsPassed >= _duration) { - // We've reached the end of the dynamic pricing portion - // of the auction, just return the end price. - return _endingPrice; - } else { - // Starting price can be higher than ending price (and often is!), so - // this delta can be negative. - int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - - // This multiplication can't overflow, _secondsPassed will easily fit within - // 64-bits, and totalPriceChange will easily fit within 128-bits, their product - // will always fit within 256-bits. - int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - - // currentPriceChange can be negative, but if so, will have a magnitude - // less that _startingPrice. Thus, this result will always end up positive. - int256 currentPrice = int256(_startingPrice) + currentPriceChange; - - return uint256(currentPrice); - } - } - - /// @dev Computes owner's cut of a sale. - /// @param _price - Sale price of NFT. - function _computeCut(uint256 _price) internal view returns (uint256) { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our entry functions carefully cap the maximum values for - // currency (at 128-bits), and ownerCut <= 10000 (see the require() - // statement in the ClockAuction constructor). The result of this - // function is always guaranteed to be <= _price. - return _price * ownerCut / 10000; - } - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { - event Pause(); - event Unpause(); - - bool public paused = false; - - - /** - * @dev modifier to allow actions only when the contract IS paused - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev modifier to allow actions only when the contract IS NOT paused - */ - modifier whenPaused { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyOwner whenNotPaused public returns (bool) { - paused = true; - emit Pause(); - return true; - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyOwner whenPaused public returns (bool) { - paused = false; - emit Unpause(); - return true; - } -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - - /// @dev The ERC-165 interface signature for ERC-721. - /// Ref: https://github.com/ethereum/EIPs/issues/165 - /// Ref: https://github.com/ethereum/EIPs/issues/721 - bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - - /// @dev Constructor creates a reference to the NFT ownership contract - /// and verifies the owner cut is in the valid range. - /// @param _nftAddress - address of a deployed contract implementing - /// the Nonfungible Interface. - /// @param _cut - percent cut the owner takes on each auction, must be - /// between 0-10,000. - constructor(address _nftAddress, uint256 _cut) public { - require(_cut <= 10000); - ownerCut = _cut; - - ERC721 candidateContract = ERC721(_nftAddress); - require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); - nonFungibleContract = candidateContract; - } - - /// @dev Remove all Ether from the contract, which is the owner's cuts - /// as well as any Ether sent directly to the contract address. - /// Always transfers to the NFT contract, but can be called either by - /// the owner or the NFT contract. - function withdrawBalance() external { - address payable nftAddress = address(uint160(address(nonFungibleContract))); - - require( - msg.sender == owner || - msg.sender == nftAddress - ); - // We are using this boolean method to make sure that even if one fails it will still work - bool res = nftAddress.send(address(this).balance); - } - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of time to move between starting - /// price and ending price (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - whenNotPaused - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(_owns(msg.sender, _tokenId)); - _escrow(msg.sender, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Bids on an open auction, completing the auction and transferring - /// ownership of the NFT if enough Ether is supplied. - /// @param _tokenId - ID of token to bid on. - function bid(uint256 _tokenId) - external - payable - whenNotPaused - { - // _bid will throw if the bid or funds transfer fails - _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - } - - /// @dev Cancels an auction that hasn't been won yet. - /// Returns the NFT to original owner. - /// @notice This is a state-modifying function that can - /// be called while the contract is paused. - /// @param _tokenId - ID of token on auction - function cancelAuction(uint256 _tokenId) - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - address seller = auction.seller; - require(msg.sender == seller); - _cancelAuction(_tokenId, seller); - } - - /// @dev Cancels an auction when the contract is paused. - /// Only the owner may do this, and NFTs are returned to - /// the seller. This should only be used in emergencies. - /// @param _tokenId - ID of the NFT on auction to cancel. - function cancelAuctionWhenPaused(uint256 _tokenId) - whenPaused - onlyOwner - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - _cancelAuction(_tokenId, auction.seller); - } - - /// @dev Returns auction info for an NFT on auction. - /// @param _tokenId - ID of NFT on auction. - function getAuction(uint256 _tokenId) - external - view - returns - ( - address seller, - uint256 startingPrice, - uint256 endingPrice, - uint256 duration, - uint256 startedAt - ) { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return ( - auction.seller, - auction.startingPrice, - auction.endingPrice, - auction.duration, - auction.startedAt - ); - } - - /// @dev Returns the current price of an auction. - /// @param _tokenId - ID of the token price we are checking. - function getCurrentPrice(uint256 _tokenId) - external - view - returns (uint256) - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return _currentPrice(auction); - } - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSiringAuctionAddress() call. - bool public isSiringClockAuction = true; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. Since this function is wrapped, - /// require sender to be KittyCore contract. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Places a bid for siring. Requires the sender - /// is the KittyCore contract because all bid methods - /// should be wrapped. Also returns the kitty to the - /// seller rather than the winner. - function bid(uint256 _tokenId) - external - payable - { - require(msg.sender == address(nonFungibleContract)); - address seller = tokenIdToAuction[_tokenId].seller; - // _bid checks that token ID is valid and will throw if bid fails - _bid(_tokenId, msg.value); - // We transfer the kitty back to the seller, the winner will get - // the offspring - _transfer(seller, _tokenId); - } - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSaleAuctionAddress() call. - bool public isSaleClockAuction = true; - - // Tracks last 5 sale price of gen0 kitty sales - uint256 public gen0SaleCount; - uint256[5] public lastGen0SalePrices; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Updates lastSalePrice if seller is the nft contract - /// Otherwise, works the same as default bid method. - function bid(uint256 _tokenId) - external - payable - { - // _bid verifies token ID size - address seller = tokenIdToAuction[_tokenId].seller; - uint256 price = _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - - // If not a gen0 auction, exit - if (seller == address(nonFungibleContract)) { - // Track gen0 sale prices - lastGen0SalePrices[gen0SaleCount % 5] = price; - gen0SaleCount++; - } - } - - function averageGen0SalePrice() external view returns (uint256) { - uint256 sum = 0; - for (uint256 i = 0; i < 5; i++) { - sum += lastGen0SalePrices[i]; - } - return sum / 5; - } - -} - - - - - - - diff --git a/framework/src/test/resources/soliditycode_0.7.6/addressCheckNew.sol b/framework/src/test/resources/soliditycode_0.7.6/addressCheckNew.sol deleted file mode 100644 index 3c10b8c680d..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/addressCheckNew.sol +++ /dev/null @@ -1,9 +0,0 @@ -pragma experimental ABIEncoderV2; -contract testIsContract{ - function checkAddress(address addr) public returns (address){ - return addr; - } - function checkAddress2(address addr) pure public returns(address){ - return addr; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/addressCheckOld.sol b/framework/src/test/resources/soliditycode_0.7.6/addressCheckOld.sol deleted file mode 100644 index 6c6b15d1736..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/addressCheckOld.sol +++ /dev/null @@ -1,8 +0,0 @@ -contract testIsContract{ - function checkAddress(address addr) public returns (address){ - return addr; - } - function checkAddress2(address addr) pure public returns (address){ - return addr; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/altbn.sol b/framework/src/test/resources/soliditycode_0.7.6/altbn.sol deleted file mode 100644 index c3cfcdbe2b9..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/altbn.sol +++ /dev/null @@ -1,61 +0,0 @@ -contract AltBn128 { - constructor() public payable {} - function callBn256Add(bytes32 ax, bytes32 ay, bytes32 bx, bytes32 by) public returns (bytes32[2] memory result) { - bytes32[4] memory input; - input[0] = ax; - input[1] = ay; - input[2] = bx; - input[3] = by; - assembly { - let success := call(gas(), 0x06, 0, input, 0x80, result, 0x40) - } - - } - - function callBn256AddNoValue(bytes32 ax, bytes32 ay, bytes32 bx, bytes32 by) public returns - (bytes32[2] memory result) { - bytes32[4] memory input; - input[0] = ax; - input[1] = ay; - input[2] = bx; - input[3] = by; - assembly { - let success := call(gas(), 0xac, 0, input, 0x80, result, 0x40) - } - } - - function callBn256ScalarMul(bytes32 x, bytes32 y, bytes32 scalar) public returns (bytes32[2] memory result) { - bytes32[3] memory input; - input[0] = x; - input[1] = y; - input[2] = scalar; - assembly { - let success := call(gas(), 0x07, 0, input, 0x60, result, 0x40) - switch success - case 0 { - revert(0,0) - } - } - } - - function callBn256Pairing(bytes memory input) public returns (bytes32 result) { - // input is a serialized bytes stream of (a1, b1, a2, b2, ..., ak, bk) from (G_1 x G_2)^k - uint256 len = input.length; - require(len % 192 == 0); - assembly { - let memPtr := mload(0x40) - let success := call(gas(), 0x08, 0, add(input, 0x20), len, memPtr, 0x20) - switch success - case 0 { - revert(0,0) - } default { - result := mload(memPtr) - } - } - } - - function convert(uint256 num) public view returns(bytes32) { - return bytes32(num); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/arrayLength001.sol b/framework/src/test/resources/soliditycode_0.7.6/arrayLength001.sol deleted file mode 100644 index 46b2405a97e..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/arrayLength001.sol +++ /dev/null @@ -1,64 +0,0 @@ - - -contract arrayLength { - byte[] a; - uint256[] IntergerArray; - bytes bs; - - // arrary length - function arrayPushValue() public returns (byte[] memory){ - a = new byte[](1); - a.push(0x01); - return a; - } - - function arrayPush() public returns(byte[] memory){ - a = new byte[](1); - a.push(); - return a; - } - - function arrayPop() public returns(byte[] memory){ - a = new byte[](1); - a.pop(); - return a; - } - - // arrary push/pop return Value - function arrayPushValueReturn() public { - a = new byte[](1); - return a.push(0x01); - } - - function arrayPushReturn() public returns (bytes1){ - a = new byte[](1); - return a.push(); - } - - function arrayPopReturn() public{ - a = new byte[](1); - return a.pop(); - } - - function uint256ArrayPushValue() public returns (byte[] memory){ - IntergerArray = [1,2,3]; - IntergerArray.push(); - return a; - } - - - // bytes - function bytesPushValue() public { - - return bs.push(0x01); - } - - function bytesPush() public returns (bytes1){ - return bs.push(); - } - - function bytesPop() public { - return bs.pop(); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/assemblyTest.sol b/framework/src/test/resources/soliditycode_0.7.6/assemblyTest.sol deleted file mode 100644 index 519a5a85fa3..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/assemblyTest.sol +++ /dev/null @@ -1,61 +0,0 @@ - -contract assemblyTest { - - uint constant x = 1; - uint constant y = x; - function getZuint() public view returns (uint) { - uint z = y + 1; - assembly { - z := y - } - return z; - } - - function getZuint2() public returns (uint) { - uint z = y + 1; - assembly { - z := y - } - return z; - } - - bool constant bool1 = true; - bool constant bool2 = bool1; - function getZbool() public view returns (bool) { - bool z; - assembly { - z := bool2 - } - return z; - } - - function getZbool2() public returns (bool) { - bool z; - assembly { - z := bool2 - } - return z; - } - - -// string constant string1 = "abc"; -// string constant string2 = string1; -// function getZstring() public view returns (string memory) { -// string memory z; -// assembly { -// z := string2 -// } -// return z; -// } - - -// address origin1 = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; -// address origin2 = origin1; -// function getZaddress() public view returns (address) { -// address z; -// assembly { -// z := origin2 -// } -// return z; -// } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest1DivideInt.sol b/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest1DivideInt.sol deleted file mode 100644 index 92778e42bc9..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest1DivideInt.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest2FindArgsContractMinTest.sol b/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest2FindArgsContractMinTest.sol deleted file mode 100644 index 75436287805..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest2FindArgsContractMinTest.sol +++ /dev/null @@ -1,10 +0,0 @@ - -contract findArgsIContract{ -function findArgsByIndex1(uint i) public returns (uint z) { -uint[] memory a = new uint[](3); -a[0]=1; -a[1]=2; -a[2]=3; -return a[i]; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest3ByteMinContract.sol b/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest3ByteMinContract.sol deleted file mode 100644 index c8a2e5e363b..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest3ByteMinContract.sol +++ /dev/null @@ -1,11 +0,0 @@ - -contract byteContract{ -bytes b; -function testBytesGet(uint i) public returns (bytes1){ -b = new bytes(3); -b[0]=0x0b; -b[1]=0x0c; -b[2]=0x0d; -return b[i]; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest4Enum.sol b/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest4Enum.sol deleted file mode 100644 index 6bd2ade2eea..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest4Enum.sol +++ /dev/null @@ -1,13 +0,0 @@ - - -contract enumContract { - enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } - ActionChoices _choice; - function setGoStraight(ActionChoices choice) public { - _choice = choice; - } - - function getChoice() public returns (ActionChoices) { - return _choice; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest5MoveRight.sol b/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest5MoveRight.sol deleted file mode 100644 index ad8f6f0f173..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest5MoveRight.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract binaryRightContract{ - function binaryMoveR(uint i)public returns (uint z) { - return z = 5 >> i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest6UninitializedContract.sol b/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest6UninitializedContract.sol deleted file mode 100644 index c82e0f5806c..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest6UninitializedContract.sol +++ /dev/null @@ -1,27 +0,0 @@ - -contract uni { -function b(int x, int y) internal returns (int) -{ - return x * y; -} - -function test1() external returns (int) -{ - // Variable containing a function pointer - function (int, int) internal returns (int) funcPtr; - - funcPtr = b; - - // This call to funcPtr will succeed - return funcPtr(4, 5); -} - -function test2() external returns (int) -{ - // Variable containing a function pointer - function (int, int) internal returns (int) funcPtr; - - // This call will fail because funcPtr is still a zero-initialized function pointer - return funcPtr(4, 5); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest7TestAssertContract.sol b/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest7TestAssertContract.sol deleted file mode 100644 index 05b592e0682..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/assertExceptiontest7TestAssertContract.sol +++ /dev/null @@ -1,14 +0,0 @@ -contract TestThrowsContract{ - function testAssert() public{ - assert(1==2); - } - function testRequire() public{ - require(2==1); - } - function testRevert() public{ - revert(); - } - function testThrow() public{ - revert(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign.sol b/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign.sol deleted file mode 100644 index 9e1c1b289b5..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - - function testArray2(bytes memory data) public returns(bool, bytes memory){ - return address(0x9).delegatecall(data); - } - - function testArray4(bytes memory data) public { - //address(0x1).delegatecall(data); - } - //function testArray3(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public { - //address(0x9).delegatecall(hash,signatures,addresses); - //} -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign001.sol b/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign001.sol deleted file mode 100644 index 57e051ce415..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign001.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - function testPure(bytes32 hash, bytes[] memory signatures, address[] memory addresses) pure public returns(bytes32){ - return batchvalidatesign(hash, signatures, addresses); - } - - function testArray(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public returns(bytes32){ - return batchvalidatesign(hash, signatures, addresses); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign002.sol b/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign002.sol deleted file mode 100644 index 375cec3a2a2..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign002.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - function testArray(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public returns(bytes32){ - - return batchvalidatesign(hash, signatures, addresses); - - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign003.sol b/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign003.sol deleted file mode 100644 index c43536af499..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign003.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract Demo { -bytes32 public result; -constructor (bytes32 hash, bytes[] memory signatures, address[] memory addresses) public { - result = batchvalidatesign(hash, signatures, addresses); -} -function testConstructor() public returns(bytes32){ - return result; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign005.sol b/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign005.sol deleted file mode 100644 index 3a6ca362973..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign005.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - - function testArray2(bytes memory data) public returns(bool, bytes memory){ - return address(0x9).delegatecall(data); - } - - function testArray4(bytes memory data) public { - //address(0x1).delegatecall(data); - } - function testArray3(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public { - //address(0x9).delegatecall(hash,signatures,addresses); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign007.sol b/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign007.sol deleted file mode 100644 index 974ffb34efe..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign007.sol +++ /dev/null @@ -1,17 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract Demo { - bytes32 public result; - - constructor (bytes32 hash, bytes[] memory signatures, address[] memory addresses) public { - result = batchvalidatesign(hash, signatures, addresses); - } - - function testConstructor() public returns(bytes32){ - return result; - } - - function testConstructorPure() public view returns(bytes32){ - return result; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign02.sol b/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign02.sol deleted file mode 100644 index 375cec3a2a2..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/batchvalidatesign02.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma experimental ABIEncoderV2; -contract Demo { - function testArray(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public returns(bytes32){ - - return batchvalidatesign(hash, signatures, addresses); - - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/callValueGasPure.sol b/framework/src/test/resources/soliditycode_0.7.6/callValueGasPure.sol deleted file mode 100644 index 6aab49bab84..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/callValueGasPure.sol +++ /dev/null @@ -1,8 +0,0 @@ - -contract C { -function check(address a) external pure returns (bool success) { - a.call{value:42,gas:42}; - a.call{gas:42}; - //a.call.value(1).gas(42)("fwefewf"); -} -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/calldata.sol b/framework/src/test/resources/soliditycode_0.7.6/calldata.sol deleted file mode 100644 index 6e877ac1b2f..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/calldata.sol +++ /dev/null @@ -1,33 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract C { - struct S { uint256 a; } - - function f(S calldata s) external returns (bytes memory) { - return abi.encode(s); - } - - function g(S calldata s) external returns (bytes memory) { - return this.f(s); - } - - function m(uint256[] calldata) external pure returns (bytes memory) { - return msg.data; - } - function h(uint8[] calldata s) external pure returns (bytes memory) { - return abi.encode(s); - } - function i(uint8[][2] calldata s, uint256 which) external view returns (bytes memory) { - return this.h(s[which]); - } - function j(bytes calldata s) external pure returns (bytes memory) { - return abi.encode(s); - } - function k(bytes[2] calldata s, uint256 which) external view returns (bytes memory) { - return this.j(s[which]); - } - function l(function() external returns (uint)[] calldata s) external returns (uint, uint, uint) { - assert(s.length == 3); - return (s[0](), s[1](), s[2]()); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/callvalue.sol b/framework/src/test/resources/soliditycode_0.7.6/callvalue.sol deleted file mode 100644 index f01dcf2b52f..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/callvalue.sol +++ /dev/null @@ -1,9 +0,0 @@ -contract Callvalue { -function check() public payable returns(uint) { - uint256 wad; - assembly { - wad := callvalue() - } - return wad; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/chainid001.sol b/framework/src/test/resources/soliditycode_0.7.6/chainid001.sol deleted file mode 100644 index 9cf24077dfb..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/chainid001.sol +++ /dev/null @@ -1,19 +0,0 @@ - -contract IstanbulTest { - constructor() public payable {} - function getId() public view returns(uint256){ - uint256 id; - assembly { - id := chainid() - } - return id; - } - - function getBalance(address src) public view returns(uint256){ - return address(src).balance; - } - - function getBalance() public view returns(uint256){ - return address(this).balance; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/codeSaftySupport.sol b/framework/src/test/resources/soliditycode_0.7.6/codeSaftySupport.sol deleted file mode 100644 index 1cee8e4646c..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/codeSaftySupport.sol +++ /dev/null @@ -1,19 +0,0 @@ - - -contract IllegalDecorate { - -constructor() payable public{} - -fallback() payable external{} - -event log(uint256); - -function transferToken(address payable toAddress, uint256 tokenValue) public payable { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/codeSaftyUnsupport.sol b/framework/src/test/resources/soliditycode_0.7.6/codeSaftyUnsupport.sol deleted file mode 100644 index fa65a134001..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/codeSaftyUnsupport.sol +++ /dev/null @@ -1,56 +0,0 @@ - - -contract SubC { - -event log(string); - -fallback() payable external{} - -function receiveToken() payable public{} - -function getBalance() view public returns (uint256 r) { -r = address(this).balance; -} -} - -contract UseDot { -constructor() payable public{} -fallback() payable external{} -mapping(address => mapping(trcToken => uint256)) sender_tokens; - -function trigger1(address payable addr, trcToken tokenInputId) payable public { - //address(SubC(addr)).call.value(1000).tokenId(tokenInputId)(abi.encodeWithSignature("receiveToken()")); // ERROR -} - -function trigger2(address payable addr) payable public { -// addr.transferToken.value(10)(10, 0x6e6d62); // ERROR -} - -function trigger3(address payable addr) payable public { - // address(SubC(addr)).receiveToken.tokenvalue(10)(); // ERROR -} - -function trigger4(address payable addr) payable public { - //SubC(addr).receiveToken.tokenId(0x6e6d62)(); // ERROR -} - -function trigger5(address payable addr) payable public { - SubC(addr).receiveToken{value:10}(); -} - -function trigger6(address payable addr, trcToken tokenId) payable public { -address(SubC(addr)).call{value:1000}(abi.encodeWithSignature("transferToken(uint256, trcToken)", 10, tokenId)); -} - -function trigger7(address addr) payable public { - //sender_tokens[msg.sender][msg.tokenid] += msg.tokenvalue; // compile success, no necessary to trigger -} - -function trigger8(address addr) public payable returns(bytes memory r){ -// r = msg.data; // compile success, no necessary to trigger -} - -function getBalance() public returns (uint256 r){ -r = address(this).balance; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/constantCallStorage001.sol b/framework/src/test/resources/soliditycode_0.7.6/constantCallStorage001.sol deleted file mode 100644 index 1f584923a55..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/constantCallStorage001.sol +++ /dev/null @@ -1,159 +0,0 @@ -contract NotView { - uint256 public num = 123; - function setnum() public returns(uint256){ - num = num + 15; - return num; - } -} -contract NotViewInterface{ - function setnum() public returns(uint256); -} -contract UseNotView { - function setnumuseproxy(address contractAddress) public returns(uint256){ - NotViewInterface inter = NotViewInterface(contractAddress); - return inter.setnum(); - } -} -contract viewCall { - bool stopped = false; - int i = 32482989; - int i2 = -32482989; - uint ui = 23487823; - address origin = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; - bytes32 b32 = bytes32(uint256(0xdCad3a6d3569DF655070DEd0)); - bytes bs = new bytes(3); - string s = "123qwe"; - enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } - ActionChoices choice = ActionChoices.GoRight; - int64[] b = [-1, 2, -3]; - int32[2][] tmp_h = [[1,2],[3,4],[5,6]]; - int256[2][2] tmp_i = [[11,22],[33,44]]; - mapping (address => uint256) public mapa; - constructor() payable public{ - mapa[address(0x00)] = 34; - } - event log(int); - event log(uint); - event log(bool); - event log(address); - event log(bytes32); - event log(bytes); - event log(string); - event log(ActionChoices); - event log(int64[]); - event log(int32[2][]); - event log(int256[2][2]); - function changeBool(bool param) public returns (bool){ - stopped = param; - emit log(stopped); - return stopped; - } - function getBool() public returns (bool){ - emit log(stopped); - return stopped; - } - function changeInt(int param) public returns (int){ - i = param; - emit log(i); - return i; - } - function getInt() public returns (int){ - emit log(i); - return i; - } - function changeNegativeInt(int param) public returns (int){ - i2 = param; - emit log(i2); - return i2; - } - function getNegativeInt() public returns (int){ - emit log(i2); - return i2; - } - function changeUint(uint param) public returns (uint){ - ui = param; - emit log(ui); - return ui; - } - function getUint() public returns (uint){ - emit log(ui); - return ui; - } - function changeAddress(address param) public returns (address){ - origin = param; - emit log(origin); - return origin; - } - function getAddress() public returns (address){ - emit log(origin); - return origin; - } - function changeBytes32(bytes32 param) public returns (bytes32){ - b32 = param; - emit log(b32); - return b32; - } - function getBytes32() public returns (bytes32){ - emit log(b32); - return b32; - } - function changeBytes(bytes memory param) public returns (bytes memory){ - bs = param; - emit log(bs); - return bs; - } - function getBytes() public returns (bytes memory){ - emit log(bs); - return bs; - } - function changeString(string memory param) public returns (string memory){ - s = param; - emit log(s); - return s; - } - function getString() public returns (string memory){ - emit log(s); - return s; - } - function changeActionChoices(ActionChoices param) public returns (ActionChoices){ - choice = param; - emit log(choice); - return choice; - } - function getActionChoices() public returns (ActionChoices){ - emit log(choice); - return choice; - } - function changeInt64NegativeArray(int64[] memory param) public returns (int64[] memory){ - b = param; - emit log(b); - return b; - } - function getInt64NegativeArray() public returns (int64[] memory){ - emit log(b); - return b; - } - function changeInt32Array(int32[2][] memory param) public returns (int32[2][] memory){ - tmp_h = param; - emit log(tmp_h); - return tmp_h; - } - function getInt32Array() public returns (int32[2][] memory){ - emit log(tmp_h); - return tmp_h; - } - function changeInt256Array(int256[2][2] memory param) public returns (int256[2][2] memory){ - tmp_i = param; - emit log(tmp_i); - return tmp_i; - } - function getInt256Array() public returns (int256[2][2] memory){ - emit log(tmp_i); - return tmp_i; - } - function setMapping(uint256 param) public returns (uint256){ - mapa[msg.sender] = param; - return mapa[msg.sender]; - - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/constantCallStorage002.sol b/framework/src/test/resources/soliditycode_0.7.6/constantCallStorage002.sol deleted file mode 100644 index 1ceba5e87d2..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/constantCallStorage002.sol +++ /dev/null @@ -1,16 +0,0 @@ -contract NotView { - uint256 public num = 123; - function setnum() public returns(uint256){ - num = num + 15; - return num; - } -} -contract NotViewInterface{ - function setnum() public view returns(uint256); -} -contract UseNotView { - function setnumuseproxy(address contractAddress) public view returns(uint256){ - NotViewInterface inter = NotViewInterface(contractAddress); - return inter.setnum(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/constantCallStorage0425.sol b/framework/src/test/resources/soliditycode_0.7.6/constantCallStorage0425.sol deleted file mode 100644 index 8ecf771626d..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/constantCallStorage0425.sol +++ /dev/null @@ -1,156 +0,0 @@ -contract constantCall { - bool stopped = false; - int i = 32482989; - int i2 = -32482989; - uint ui = 23487823; - address origin = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; - bytes32 b32 = 0xb55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105c; - bytes bs = new bytes(9); - string s = "123qwe"; - enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } - ActionChoices choice = ActionChoices.SitStill; - int64[] b = [91, 2, 333]; - int32[2][] tmp_h = [[1,2],[3,4],[5,6]]; - int256[2][2] tmp_i = [[11,22],[33,44]]; - mapping (address => uint256) public mapa; - - constructor() payable public{ - mapa[address(0x00)] = 88; - } - event log(int); - event log(uint); - event log(bool); - event log(address); - event log(bytes32); - event log(bytes); - event log(string); - event log(ActionChoices); - event log(int64[]); - event log(int32[2][]); - event log(int256[2][2]); - - function changeBool(bool param) public constant returns (bool){ - stopped = param; - log(stopped); - return stopped; - } - function getBool() public constant returns (bool){ - log(stopped); - return stopped; - } - - function changeInt(int param) public returns (int){ - i = param; - log(i); - return i; - } - function getInt() public returns (int){ - log(i); - return i; - } - - function changeNegativeInt(int param) public constant returns (int){ - i2 = param; - log(i2); - return i2; - } - function getNegativeInt() public constant returns (int){ - log(i2); - return i2; - } - - function changeUint(uint param) public returns (uint){ - ui = param; - log(ui); - return ui; - } - function getUint() public returns (uint){ - log(ui); - return ui; - } - - function changeAddress(address param) public constant returns (address){ - origin = param; - log(origin); - return origin; - } - function getAddress() public constant returns (address){ - log(origin); - return origin; - } - - function changeBytes32(bytes32 param) public constant returns (bytes32){ - b32 = param; - log(b32); - return b32; - } - function getBytes32() public returns (bytes32){ - log(b32); - return b32; - } - - function changeBytes(bytes param) public constant returns (bytes){ - bs = param; - log(bs); - return bs; - } - function getBytes() public constant returns (bytes){ - log(bs); - return bs; - } - - function changeString(string param) public constant returns (string){ - s = param; - log(s); - return s; - } - function getString() public returns (string){ - log(s); - return s; - } - - function changeActionChoices(ActionChoices param) public constant returns (ActionChoices){ - choice = param; - log(choice); - return choice; - } - function getActionChoices() public constant returns (ActionChoices){ - log(choice); - return choice; - } - - function changeInt64NegativeArray(int64[] param) public constant returns (int64[]){ - b = param; - log(b); - return b; - } - function getInt64NegativeArray() public constant returns (int64[]){ - log(b); - return b; - } - - function changeInt32Array(int32[2][] param) public returns (int32[2][]){ - tmp_h = param; - log(tmp_h); - return tmp_h; - } - function getInt32Array() public constant returns (int32[2][]){ - log(tmp_h); - return tmp_h; - } - - function changeInt256Array(int256[2][2] param) public returns (int256[2][2]){ - tmp_i = param; - log(tmp_i); - return tmp_i; - } - function getInt256Array() public constant returns (int256[2][2]){ - log(tmp_i); - return tmp_i; - } - function setMapping(uint256 param) public returns (uint256){ - mapa[msg.sender] = param; - return mapa[msg.sender]; - - } -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/constantContract001.sol b/framework/src/test/resources/soliditycode_0.7.6/constantContract001.sol deleted file mode 100644 index 7d574c5a008..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/constantContract001.sol +++ /dev/null @@ -1,8 +0,0 @@ - - -contract testConstantContract{ -function testPure(uint256 x,uint256 y) public pure returns (uint256 z) { -uint256 i=1; -return i + x + y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGetterContract.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGetterContract.sol deleted file mode 100644 index 365b53ebf1a..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGetterContract.sol +++ /dev/null @@ -1,17 +0,0 @@ - - - -contract getterContract { - -constructor() public payable{} -fallback() external payable{} - -uint public c = msg.value; - -function getDataUsingAccessor() public payable returns (uint){ - -return c; - -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test1Grammar001.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test1Grammar001.sol deleted file mode 100644 index 659e56c9150..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test1Grammar001.sol +++ /dev/null @@ -1,18 +0,0 @@ - -contract FunctionSelector { - function select(bool useB, uint x) public returns (uint z) { - //var f = a; - //if (useB) f = b; - //return f(x); - if (useB) - return b(x); - else - return a(x); - } -function a(uint x) public returns (uint z) { - return x * x; - } -function b(uint x) public returns (uint z) { - return 2 * x; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test2Grammar002.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test2Grammar002.sol deleted file mode 100644 index 744b17e9585..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test2Grammar002.sol +++ /dev/null @@ -1,44 +0,0 @@ - -library Set { - // We define a new struct datatype that will be used to - // hold its data in the calling contract. - struct Data { mapping(uint => bool) flags; } - - // Note that the first parameter is of type "storage - // reference" and thus only its storage address and not - // its contents is passed as part of the call. This is a - // special feature of library functions. It is idiomatic - // to call the first parameter 'self', if the function can - // be seen as a method of that object. - function insert(Data storage self, uint value) public returns (bool) { - if (self.flags[value]) - return false; // already there - self.flags[value] = true; - return true; - } - - function remove(Data storage self, uint value) public returns (bool) { - if (!self.flags[value]) - return false; // not there - self.flags[value] = false; - return true; - } - - function contains(Data storage self, uint value) public returns (bool) { - return self.flags[value]; - } -} - - -contract C { - Set.Data knownValues; - - function register (uint value) public{ - // The library functions can be called without a - // specific instance of the library, since the - // "instance" will be the current contract. - if (!Set.insert(knownValues, value)) - revert(); - } - // In this contract, we can also directly access knownValues.flags, if we want. -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test3Grammar003.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test3Grammar003.sol deleted file mode 100644 index 140ba2a8f56..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test3Grammar003.sol +++ /dev/null @@ -1,44 +0,0 @@ - - -library Set { - struct Data { mapping(uint => bool) flags; } - - function insert(Data storage self, uint value) public - returns (bool) - { - if (self.flags[value]) - return false; // already there - self.flags[value] = true; - return true; - } - - function remove(Data storage self, uint value) public - returns (bool) - { - if (!self.flags[value]) - return false; // not there - self.flags[value] = false; - return true; - } - - function contains(Data storage self, uint value) public - returns (bool) - { - return self.flags[value]; - } -} - - -contract C { - using Set for Set.Data; // this is the crucial change - Set.Data knownValues; - - function register(uint value) public{ - // Here, all variables of type Set.Data have - // corresponding member functions. - // The following function call is identical to - // Set.insert(knownValues, value) - if (!knownValues.insert(value)) - revert(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test4Grammar004.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test4Grammar004.sol deleted file mode 100644 index 772691cebc5..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test4Grammar004.sol +++ /dev/null @@ -1,31 +0,0 @@ - - -library Search { - function indexOf(uint[] storage self, uint value) public returns (uint) { - for (uint i = 0; i < self.length; i++) - if (self[i] == value) return i; - return uint(-1); - } -} - - -contract C { - using Search for uint[]; - uint[] public data; - - function append(uint value) public{ - data.push(value); - } - - function replace(uint _old, uint _new) public{ - // This performs the library function call - uint index = data.indexOf(_old); - if (index == uint(-1)) - data.push(_new); - else - data[index] = _new; - } - function getData(uint256 index) public returns(uint256){ - return data[index]; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test5Grammar006.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test5Grammar006.sol deleted file mode 100644 index 275d42d1e71..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar001test5Grammar006.sol +++ /dev/null @@ -1,45 +0,0 @@ -contract InfoFeed { -function d1(uint x1) public{ - - assembly{ - function f(x) -> y { switch x case 0 { y := 1 } default { y := mul(x, f(sub(x, 1))) } } - } - } - function d2(uint x1) public{ - assembly { - let x:=1 - x := mul(1, add(2, 3))} - } - function f(uint x) public{ - assembly { x := sub(x, 1) } - - } - // 0.6.0 Variable declarations cannot shadow declarations outside the assembly block. - function d(uint x1) public returns(uint256){ - uint256 x; - assembly{ - x := add(2, 3) - let y := mload(0x40) - x := add(x, y) - } - return x; - } - function d4(uint x) public{ - // Error: The labels 'repeat' is disallowed. Please use "if", "switch", "for" or function calls instead - //assembly{let x := 10 repeat: x := sub(x, 1) jumpi(repeat, eq(x, 0)) - x = x; - //} - } - function d5(uint x1) public{ - assembly{ - function f(x) -> y { switch x case 0 { y := mul(x, 2) } default { y := 0 } } - - } - } - - function d6(uint x1) public{ - assembly{ - function f(x) -> y { for { let i := 0 } lt(i, x) { i := add(i, 1) } { y := mul(2, y) } } - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test1Grammar007_1.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test1Grammar007_1.sol deleted file mode 100644 index 020c2a38ca4..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test1Grammar007_1.sol +++ /dev/null @@ -1,60 +0,0 @@ -contract Doug{ - mapping (bytes32 => uint) public contracts; - constructor() public{ - contracts['hww'] = 1; - contracts['brian'] = 2; - contracts['zzy'] = 7; - } - - function getDougName(string memory _name) public view returns(string memory) { - return _name; - } - - function getDougAge(uint _age) public pure returns(uint) { - return 3 ** _age; - } -} - -// -abstract contract DogInterface { - function getDougAge(uint _age) public virtual returns (uint); - function contracts(bytes32 name) public virtual returns (uint); -} -contract main{ - - event FetchContract(address dogInterfaceAddress, address sender, bytes32 name); - - address public DOUG; - - address dogInterfaceAddress; - DogInterface dogContract ; - - function setDOUG(address _doug) public { - DOUG = _doug; - } - - constructor(address addr) public{ - dogInterfaceAddress = addr; - dogContract = DogInterface(dogInterfaceAddress); - } - - function dougOfage(uint _age) public returns(uint) { - - uint num = dogContract.getDougAge(_age); - return _age+num; - // return num; - } - - function uintOfName(bytes32 _name) public returns (uint) { - - dogContract.contracts(_name); - emit FetchContract(dogInterfaceAddress, msg.sender, _name); - - } - - // function getTest(string _name) public view returns(string) { - // string memory newName = _name ; - // DogInterface(DOUG).getDougName(newName); - // return newName; - // } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test1Grammar007_2.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test1Grammar007_2.sol deleted file mode 100644 index 8945b566543..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test1Grammar007_2.sol +++ /dev/null @@ -1,60 +0,0 @@ - -contract Doug{ - mapping (bytes32 => uint) public contracts; - constructor() public{ - contracts['hww'] = 1; - contracts['brian'] = 2; - contracts['zzy'] = 7; - } - - function getDougName(string memory _name) public view returns(string memory) { - return _name; - } - - function getDougAge(uint _age) public pure returns(uint) { - return 3 ** _age; - } -} - -abstract contract DogInterface { - function getDougAge(uint _age) public virtual returns (uint); - function contracts(bytes32 name) public virtual returns (uint); -} -contract main{ - - event FetchContract(address dogInterfaceAddress, address sender, bytes32 name); - - address public DOUG; - - address dogInterfaceAddress; - DogInterface dogContract ; - - function setDOUG(address _doug) public { - DOUG = _doug; - } - - constructor(address addr) public{ - dogInterfaceAddress = addr; - dogContract = DogInterface(dogInterfaceAddress); - } - - function dougOfage(uint _age) public returns(uint) { - - uint num = dogContract.getDougAge(_age); - return _age+num; - // return num; - } - - function uintOfName(bytes32 _name) public returns (uint) { - - dogContract.contracts(_name); - emit FetchContract(dogInterfaceAddress, msg.sender, _name); - - } - - // function getTest(string _name) public view returns(string) { - // string memory newName = _name ; - // DogInterface(DOUG).getDougName(newName); - // return newName; - // } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test2Grammar008.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test2Grammar008.sol deleted file mode 100644 index 956623c3103..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test2Grammar008.sol +++ /dev/null @@ -1,18 +0,0 @@ - - -// version 0.6.0 change -// add abstract and override -abstract contract Feline { - - function utterance() public virtual returns (bytes32); - - function getContractName() public returns (string memory){ - return "Feline"; - } -} - - -contract Cat is Feline { - function utterance() public override returns (bytes32) { return "miaow"; } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test3Grammar010.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test3Grammar010.sol deleted file mode 100644 index 617f96cb4e5..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test3Grammar010.sol +++ /dev/null @@ -1,10 +0,0 @@ - -contract InfoFeed { -function info() public payable returns (uint ret) { return 42; } -} -contract Consumer { -constructor() payable public{} -InfoFeed feed; -function setFeed(address addr) public { feed = InfoFeed(addr); } -function callFeed() public payable { feed.info{value:10,gas:800}(); } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test4Grammar011.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test4Grammar011.sol deleted file mode 100644 index fcd18f438ef..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test4Grammar011.sol +++ /dev/null @@ -1,11 +0,0 @@ - -contract C { -function f(uint key, uint value) public returns(uint) { -return key; -// do something -} -function g() public { -// named arguments -f({value: 2, key: 3}); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test4Grammar012.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test4Grammar012.sol deleted file mode 100644 index 293b5e2ba9d..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test4Grammar012.sol +++ /dev/null @@ -1,24 +0,0 @@ - -contract rTest { -function info() public payable returns (uint,address,bytes4,uint,uint,uint,address,uint) { -//function info() public payable returns (address ,uint,uint,uint,bytes32,uint,bytes,uint,address,bytes4,uint,uint,uint,address,uint) { -//var a = block.coinbase ; -//var b = block.difficulty; -//var c = block.gaslimit; -//var d = block.number; -//var e = block.blockhash(0); -//var e = d; -//var f = block.timestamp; -//bytes memory g = msg.data; -uint256 h = gasleft(); -address payable i = msg.sender; -bytes4 j = msg.sig; -uint256 k = msg.value; -uint256 l = block.timestamp; -uint256 m = tx.gasprice; -address payable n = tx.origin; -uint256 o = address(this).balance; -return (h,i,j,k,l,m,n,o); -//return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test6Grammar013.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test6Grammar013.sol deleted file mode 100644 index 53de5def6bc..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar002test6Grammar013.sol +++ /dev/null @@ -1,24 +0,0 @@ - -contract Counter { -uint count = 0; -address payable owner; -//function Counter() public{ -constructor() public{ -owner = msg.sender; -} -function increment() public { -uint step = 10; -if (owner == msg.sender) { -count = count + step; -} -} -function getCount() public returns (uint){ -return count; -} -function kill() public{ -if (owner == msg.sender) { -selfdestruct(owner); -//selfdestruct(address(owner)); -} -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test1Grammar014.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test1Grammar014.sol deleted file mode 100644 index b2d70b3741c..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test1Grammar014.sol +++ /dev/null @@ -1,67 +0,0 @@ -contract A { -uint256 public numberForB; -address public senderForB; -function callTest(address bAddress, uint256 _number) public{ - -//bAddress.call(bytes4(sha3("setValue(uint256)")), _number); // B's storage is set, A is not modified -bAddress.call(abi.encodeWithSignature("setValue(uint256)",_number)); // B's storage is set, A is not modified -} -function callcodeTest(address bAddress, uint256 _number) public{ -//bAddress.callcode(bytes4(sha3("setValue(uint256)")), _number); // A's storage is set, B is not modified -bAddress.delegatecall(abi.encodeWithSignature("setValue(uint256)", _number)); // A's storage is set, B is not modified -} -function delegatecallTest(address bAddress, uint256 _number) public{ -//bAddress.delegatecall(bytes4(sha3("setValue(uint256)")), _number); // A's storage is set, B is not modified -bAddress.delegatecall(abi.encodeWithSignature("setValue(uint256)", _number)); // A's storage is set, B is not modified -} - -function callAddTest(address bAddress) public{ -//bAddress.call(bytes4(sha3("add()"))); // B's storage is set, A is not modified -bAddress.call(abi.encodeWithSignature("add()")); // B's storage is set, A is not modified -//bAddress.call(bytes4(sha3("add()"))); // B's storage is set, A is not modified -bAddress.call(abi.encodeWithSignature("add()")); // B's storage is set, A is not modified -} -function getnumberForB() public returns(uint256){ - return numberForB; - } - function getsenderForB() public returns(address){ - return senderForB; - } -} -contract B { -uint256 public numberForB; -address public senderForB; -address public addr11; -mapping(uint256=>address) public addr1; -mapping(uint256=>address) public addr2; -event ssss(uint256); -function setValue(uint256 _number) public{ - -emit ssss(_number); -numberForB = _number; -senderForB = msg.sender; -// senderForB is A if invoked by A's callTest. B's storage will be updated -// senderForB is A if invoked by A's callcodeTest. None of B's storage is updated -// senderForB is OWNER if invoked by A's delegatecallTest. None of B's storage is updated -} - -function add() public{ -numberForB=numberForB+1; -C c1 = new C(); -addr1[numberForB]=c1.getAddress(); -addr11 = c1.getAddress(); -C c2 = new C(); -addr2[numberForB] = c2.getAddress(); -} -function getnumberForB() public returns(uint256){ - return numberForB; - } - function getsenderForB() public returns(address){ - return senderForB; - } -} -contract C { -function getAddress() public view returns(address){ -return address(this); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test2Grammar015.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test2Grammar015.sol deleted file mode 100644 index 0aa93e5e94f..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test2Grammar015.sol +++ /dev/null @@ -1,40 +0,0 @@ - - -contract ExecuteFallback{ - - //回退事件,会把调用的数据打印出来 - event FallbackCalled(bytes data); - //fallback函数,注意是没有名字的,没有参数,没有返回值的 - // 0.6.0 Split unnamed fallback functions into two cases defined using fallback() and receive() - fallback() external{ - emit FallbackCalled(msg.data); - } - - //调用已存在函数的事件,会把调用的原始数据,请求参数打印出来 - event ExistFuncCalled(bytes data, uint256 para); - //一个存在的函数 - function existFunc(uint256 para) public{ - emit ExistFuncCalled(msg.data, para); - } - - // 模拟从外部对一个存在的函数发起一个调用,将直接调用函数 - function callExistFunc() public{ - bytes4 funcIdentifier = bytes4(keccak256("existFunc(uint256)")); - //this.call(funcIdentifier, uint256(1)); - address(this).call(abi.encode(funcIdentifier, uint256(1))); - } - - //模拟从外部对一个不存在的函数发起一个调用,由于匹配不到函数,将调用回退函数 - function callNonExistFunc() public{ - bytes4 funcIdentifier = bytes4(keccak256("functionNotExist()")); - //this.call(funcIdentifier); - address(this).call(abi.encode(funcIdentifier)); - } - - function ExistFuncCalledTopic() view public returns(bytes32){ - return keccak256("ExistFuncCalled(bytes,uint256)"); - } - function FallbackCalledTopic() view public returns(bytes32){ - return keccak256("FallbackCalled(bytes)"); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test3Grammar016.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test3Grammar016.sol deleted file mode 100644 index 6a73d7a8d7e..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test3Grammar016.sol +++ /dev/null @@ -1,23 +0,0 @@ - -contract C { -uint private data; -function f(uint a) private returns(uint b) { return a + 1; } -function setData(uint a) public { data = a; } -function getData() public returns(uint) { return data; } -function compute(uint a, uint b) internal returns (uint) { return a+b; } -} -contract D { -function readData() public{ -C c = new C(); -//uint local = c.f(7); // error: member "f" is not visible -c.setData(3); -uint local = c.getData(); -// local = c.compute(3, 5); // error: member "compute" is not visible -} -} -contract E is C { -function g() public { -C c = new C(); -uint val = compute(3, 5); // access to internal member (from derived to parent contract) -} -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test4Grammar017.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test4Grammar017.sol deleted file mode 100644 index 38746d90734..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test4Grammar017.sol +++ /dev/null @@ -1,51 +0,0 @@ -contract CrowdFunding{ - struct Funder{ - address addr; - uint amount; - } - - struct Campaign{ - address payable beneficiary; - uint goal; - uint amount; - uint funderNum; - mapping(uint => Funder) funders; - } - - uint compaingnID; - mapping (uint => Campaign) campaigns; - - function candidate(address payable beneficiary, uint goal) public payable returns (uint compaingnID){ - // initialize - Campaign storage c = campaigns[compaingnID++]; - c.beneficiary = beneficiary; - c.goal = goal; - } - - function vote(uint compaingnID) payable public { - Campaign storage c = campaigns[compaingnID]; - - //another way to initialize - c.funders[c.funderNum++] = Funder({addr: msg.sender, amount: msg.value}); - c.amount += msg.value; - } - - function check(uint comapingnId) public payable returns (bool){ - Campaign storage c = campaigns[comapingnId]; - - if(c.amount < c.goal){ - return false; - } - - uint amount = c.amount; - // incase send much more - c.amount = 0; - // address payable addr = address(uint160(c.beneficiary)); - //if(! addr.send(amount)){ - - if (! c.beneficiary.send(amount)){ - revert(); - } - return true; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test5Grammar018.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test5Grammar018.sol deleted file mode 100644 index ec241f3eae9..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test5Grammar018.sol +++ /dev/null @@ -1,37 +0,0 @@ - - - -contract Grammar18{ - function testAddmod() public returns (uint z) { - //计算(x + y)%k,其中以任意精度执行加法,并且不在2 ** 256处围绕 - z=addmod(2, 2, 3); - return z; - } - function testMulmod() public returns (uint z) { -//计算(x * y)%k,其中乘法以任意精度执行,并且不会在2 ** 256处循环。 - z=mulmod(2, 3, 4); - return z; - } - - function testKeccak256() public returns(bytes32){ - //计算的(紧凑)参数的Ethereum-SHA-3(Keccak-256)的散列 - return keccak256("11"); - } - - function testSha256() public returns(bytes32){ - //计算(紧密包装)参数的SHA-256散列 - return sha256("11"); - } - function testSha3() public returns(bytes32){ - //计算(紧密包装)参数的SHA-256散列 - //return sha3("11"); - return keccak256("11"); - } - - function testRipemd160() public returns(bytes32){ - //计算(紧密包装)参数的RIPEMD-160哈希值 - return ripemd160("11"); - } - - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test6Grammar019.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test6Grammar019.sol deleted file mode 100644 index 727ef7091e7..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test6Grammar019.sol +++ /dev/null @@ -1,12 +0,0 @@ - -contract timetest { - -constructor() public { -require( 1 == 1 seconds); -require(1 minutes == 60 seconds); -require(1 hours == 60 minutes); -require(1 days == 24 hours); -require(1 weeks == 7 days); -//require(1 years == 365 days); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test7Grammar020.sol b/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test7Grammar020.sol deleted file mode 100644 index 39a7fddcb7e..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractGrammar003test7Grammar020.sol +++ /dev/null @@ -1,8 +0,0 @@ - -contract trxtest { - -function test() public { -require(1 trx == 1000000 sun); - -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInnerContract.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInnerContract.sol deleted file mode 100644 index 5e6addef105..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInnerContract.sol +++ /dev/null @@ -1,32 +0,0 @@ - - - - -contract InnerContract { - - constructor() public payable{} - fallback() external payable{} - - function messageI() payable public returns (uint ret) { - - - - } - -} - - - -contract OuterContract { - - - constructor() public payable{} - fallback() external payable{} - - function callInner(address payable addr) payable public returns (uint) { - - return InnerContract(addr).messageI{value:1}(); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction001.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction001.sol deleted file mode 100644 index 52dcfb16fc3..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction001.sol +++ /dev/null @@ -1,41 +0,0 @@ - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address payable cAddr) public payable{ - B b1 = (new B){value:10}();//1.1 - B b2 = new B();//1.2 - payable(address(b2)).transfer(5);//1.3 - b2.callCGetZero(cAddr, 1);//1.4 - b2.callCGetZero(cAddr,2);//1.6 - } - function test2(address payable cAddress,uint256 amount) public payable{ - cAddress.call{value:amount}(abi.encodeWithSignature("newBAndTransfer()"));//2.1 - cAddress.call{value:amount + 1}(abi.encodeWithSignature("newBAndTransfer()"));//2.6 - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero(address payable cAddress,uint256 amount) public{ - cAddress.call{value:amount}(abi.encodeWithSignature("getZero()"));//1.5,1.7 - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - B b1 = (new B){value:7}();//2.2,2.7 - b1.getOne();//2.3,2.8 - B b2 = (new B){value:3}();//2.4,2.9 - b2.getOne();//2.5,2.10 - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction002.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction002.sol deleted file mode 100644 index 502e42d0c7b..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction002.sol +++ /dev/null @@ -1,20 +0,0 @@ - -contract A{ - constructor() payable public{} - fallback() payable external{} - - function test2(address cAddress,uint256 amount) public payable{ - //cAddress.call.value(amount)();//2.1 - cAddress.call{value:amount}("");//2.1 - } -} - - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction003.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction003.sol deleted file mode 100644 index 9d3e38affbd..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction003.sol +++ /dev/null @@ -1,30 +0,0 @@ - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer() payable public{ - B b = (new B){value:10}();//1 - - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable public returns(bool) { - return true; - } - constructor() public payable {} - function payC(address payable c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - fallback() payable external{} - } - diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction004.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction004.sol deleted file mode 100644 index e8f32d7bfd9..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction004.sol +++ /dev/null @@ -1,24 +0,0 @@ - -contract A{ - constructor () payable public{} - function test(address payable toAddress) public payable{ - selfdestruct(toAddress); - } - fallback() payable external{} - function getBalance() public view returns(uint256){ - return address(this).balance; - } -} -contract B{ - fallback() external payable{} - function kill(address contractAddres, address toAddress) payable public { - contractAddres.call(abi.encodeWithSignature("test(address)",address(this))); - } - function kill2() public{ - A a = new A(); - a.test(payable(address(this))); - } - function getBalance() public view returns(uint256){ - return address(this).balance; - } -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction005.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction005.sol deleted file mode 100644 index f6bdf294a99..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction005.sol +++ /dev/null @@ -1,53 +0,0 @@ - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1() public payable{ - B b1 = (new B){value:10}();//1.1 - b1.callCGetZero(false); - b1.callCGetZero(true);//1.4 - } - function test2() public payable{ - C c1 = (new C){value:10}();//1.1 - c1.newBAndTransfer(false); - c1.newBAndTransfer(true);//1.4 - - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero(bool success) public payable{ - if(!success){ - assert(1==2); - } - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract C{ - uint256 public flag=0; - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer(bool success) payable public returns(uint256){ - flag = 1; - if(!success){ - require(2==1); - } - } - function getFlag() public returns(uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction006.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction006.sol deleted file mode 100644 index ec574998b29..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction001testInternalTransaction006.sol +++ /dev/null @@ -1,54 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1() public payable{ - B b1 = (new B){value:10}();//1.1 - b1.callCGetZero(true);//1.4 - b1.callCGetZero(false); - } - function test2() public payable{ - C c1 = (new C){value:10}();//1.1 - c1.newBAndTransfer(true);//1.4 - c1.newBAndTransfer(false); - - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero(bool success) public payable{ - if(!success){ - assert(1==2); - } - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract C{ - uint256 public flag=0; - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer(bool success) payable public returns(uint256){ - flag = 1; - if(!success){ - require(2==1); - } - } - function getFlag() public returns(uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test1InternalTransaction007.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test1InternalTransaction007.sol deleted file mode 100644 index d14c3d8aa16..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test1InternalTransaction007.sol +++ /dev/null @@ -1,38 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address cAddr) public payable{ - B b1 = (new B){value:10}();//1.1 - B b2 = new B();//1.2 - payable(address(b2)).transfer(5);//1.3 - b2.callCGetZero();//1.4 - } - function test2(address cAddress,uint256 amount) public payable{ - cAddress.call{value:amount}(abi.encodeWithSignature("newBAndTransfer()"));//2.1 - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero() public{ - assert(1==2); - - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test2InternalTransaction008.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test2InternalTransaction008.sol deleted file mode 100644 index 2e57a0e635c..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test2InternalTransaction008.sol +++ /dev/null @@ -1,60 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - - function testAssert(address bAddress,uint256 amount) public payable{ - bAddress.call{value:amount,gas:1000000}(abi.encodeWithSignature("callCGetZero(bool)",false));//2.1 - bAddress.call{value:amount,gas:1000000}(abi.encodeWithSignature("callCGetZero(bool)",true)); - } - function testRequire(address cAddress,uint256 amount) public payable{ - cAddress.call{value:amount,gas:1000000}(abi.encodeWithSignature("newBAndTransfer(bool)",false));//2.1 - cAddress.call{value:amount,gas:1000000}(abi.encodeWithSignature("newBAndTransfer(bool)",true)); - } - function testAssert1(address bAddress,uint256 amount) public payable{ - bAddress.call{value:amount,gas:1000000}(abi.encodeWithSignature("callCGetZero(bool)",true)); - bAddress.call{value:amount,gas:1000000}(abi.encodeWithSignature("callCGetZero(bool)",false));//2.1 - } - function testtRequire2(address cAddress,uint256 amount) public payable{ - cAddress.call{value:amount,gas:1000000}(abi.encodeWithSignature("newBAndTransfer(bool)",true)); - cAddress.call{value:amount,gas:1000000}(abi.encodeWithSignature("newBAndTransfer(bool)",false));//2.1 - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function callCGetZero(bool success) payable public{ - if(!success){ - assert(1==2); - } - } - function getBalance() view public returns(uint256){ - return address(this).balance; - } -} - -contract C{ - uint256 public flag=0; - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer(bool success) payable public returns(uint256){ - flag = 1; - if(!success){ - require(2==1); - } - } - function getFlag() public returns(uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test3InternalTransaction009.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test3InternalTransaction009.sol deleted file mode 100644 index d750df65ea4..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test3InternalTransaction009.sol +++ /dev/null @@ -1,47 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address cAddr,address dcontract,address baddress) public payable{ - B b1 = (new B){value:10}();//1.1 - payable(address(b1)).transfer(5);//1.3 - b1.callCGetZero(cAddr, 1);//1.4 - b1.getOne(dcontract,baddress); - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne(address contractAddres, address toAddress) payable public{ - contractAddres.call(abi.encodeWithSignature("suicide1(address)",address(this))); - - } - function callCGetZero(address cAddress,uint256 amount) public{ - cAddress.call{value:amount}(abi.encodeWithSignature("getZero()"));//1.5,1.7 - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public{ - B b1 = (new B){value:7}();//2.2,2.7 - B b2 = (new B){value:3}();//2.4,2.9 - } -} - -contract D{ - constructor () payable public{} - function suicide1(address payable toAddress) public payable{ - selfdestruct(toAddress); - } - fallback() payable external{} - function getBalance() public view returns(uint256){ - return address(this).balance; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test4InternalTransaction010.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test4InternalTransaction010.sol deleted file mode 100644 index ff5817ea173..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test4InternalTransaction010.sol +++ /dev/null @@ -1,186 +0,0 @@ - - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer() payable public{ - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - - } - function transfer2() payable public{ - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - - } - function getBalance() public returns(uint256) { - return address(this).balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable public returns(bool) { - return true; - } - constructor() public payable {} - function payC(address payable c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - fallback() payable external{} - } - diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test4InternalTransaction010_1.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test4InternalTransaction010_1.sol deleted file mode 100644 index d0c80d14ffb..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test4InternalTransaction010_1.sol +++ /dev/null @@ -1,210 +0,0 @@ - - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - } - function transfer2() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - - } - function getBalance() returns(uint256){ - return this.balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable returns(bool) { - return true; - } - constructor() public payable {} - function payC(address c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() returns(uint256){ - return this.balance; - } - fallback() payable{} - } - - \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test5InternalTransaction012.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test5InternalTransaction012.sol deleted file mode 100644 index 59ffe9f0fe9..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction002test5InternalTransaction012.sol +++ /dev/null @@ -1,51 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address bAddr,address eAddr) public payable{ - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - } - -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function testNN(address eAddress) public payable{ - D d1=(new D){value:1000}(); - d1.getOne(eAddress); - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract D{ - constructor() payable public{} - fallback() payable external{} - function getOne(address eAddress) payable public returns(uint256){ - eAddress.call{value:1}(abi.encodeWithSignature("getZero()"));//2.1 - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction013.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction013.sol deleted file mode 100644 index 1dae0beb03c..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction013.sol +++ /dev/null @@ -1,56 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address dAddr) public payable{ - B b1 = (new B){value:10}();//1.1 - b1.testNN(dAddr,2);//1.6 - // C c1 = (new C).value(1000000000000)();//1.2 - // E e1 = (new E).value(1)();//1.2 - } - function test2(address cAddress,uint256 amount) public payable{ - cAddress.call{value:amount}(abi.encodeWithSignature("newBAndTransfer()"));//2.1 - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function testNN(address dAddress,uint256 amount) public payable{ - // D d1=(new D)(); - dAddress.call{value:amount}(abi.encodeWithSignature("getOne()"));//2.1 - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract D{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - E e = (new E){value:5}(); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction014.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction014.sol deleted file mode 100644 index 0346cec669b..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction014.sol +++ /dev/null @@ -1,38 +0,0 @@ -contract callerContract { - constructor() payable public{} - fallback() payable external{} - function sendToB(address called_address,address c) public payable{ - called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); - } - function sendToB2(address called_address,address c) public payable{ - called_address.call(abi.encodeWithSignature("transferTo(address)",c)); - } - function sendToB3(address called_address,address c) public payable{ - called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); - } -} - - contract calledContract { - fallback() payable external {} - constructor() payable public{} - function transferTo(address payable toAddress)public payable{ - toAddress.transfer(5); - } - - function setIinC(address c) public payable{ - c.call{value:5}(abi.encodeWithSignature("setI()")); - } - - } - - contract c{ - uint256 public i=0; - constructor() public payable{} - function getBalance() public view returns(uint256){ - return address(this).balance; - } - function setI() payable public{ - i=5; - } - fallback() payable external{} - } diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction015.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction015.sol deleted file mode 100644 index edeb9488454..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction015.sol +++ /dev/null @@ -1,60 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address dAddr,address eAddr) public payable{ - B b1 = (new B){value:10}();//1.1 - b1.testNN(dAddr,2,eAddr);//1.6 - // C c1 = (new C).value(1000000000000)();//1.2 - // E e1 = (new E).value(1)();//1.2 - } - function test2(address cAddress,uint256 amount) public payable{ - cAddress.call{value:amount}(abi.encodeWithSignature("newBAndTransfer()"));//2.1 - } -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function testNN(address dAddress,uint256 amount,address eAddress) public payable{ - // D d1=(new D)(); - dAddress.call{value:amount}(abi.encodeWithSignature("getOne(address)",address(this)));//2.1 - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } - function suicide(address payable toAddress) public payable{ - selfdestruct(toAddress); - } -} -contract D{ - constructor() payable public{} - fallback() payable external{} - function getOne(address payable eAddress) payable public{ - E e = (new E){value:5}(); - e.suicide(eAddress); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction016.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction016.sol deleted file mode 100644 index 418d4d09ac0..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction016.sol +++ /dev/null @@ -1,174 +0,0 @@ - - - contract A{ - uint256 public num = 0; - constructor() public payable{} - fallback() payable external{} - function transfer() payable public{ - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - B b1=(new B){value:1}();//1 - address payable aaa=address(this); - b1.suicide1(aaa); - } - function transfer2() payable public{ - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - B b1=(new B){value:1}();//1 - address payable aaa=address(this); - b1.suicide1(aaa); - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable public returns(bool) { - return true; - } - constructor() public payable {} - function payC(address payable c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - fallback() payable external{} - function suicide1(address payable toAddress) public payable{ - selfdestruct(toAddress); - } - } - diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction017.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction017.sol deleted file mode 100644 index 32cf9f2a04d..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction017.sol +++ /dev/null @@ -1,199 +0,0 @@ - - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer(address payable Address) payable public{ - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - - B b=(new B){value:1}();//1 - selfdestruct(Address); - } - function transfer2() payable public{ - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - (new B){value:1}();//1 - - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable public returns(bool) { - return true; - } - constructor() public payable {} - function payC(address payable c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() public returns(uint256){ - return address(this).balance; - } - fallback() payable external{} - } - diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction018.sol b/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction018.sol deleted file mode 100644 index fadb5f84b51..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractInternalTransaction003testInternalTransaction018.sol +++ /dev/null @@ -1,97 +0,0 @@ - - -contract A{ - constructor() payable public{} - fallback() payable external{} - function test1(address payable bAddr,address eAddr) public payable{ - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - bAddr.call{value:1}(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 - - } - -} - -contract B{ - constructor() payable public{} - fallback() payable external{} - function getOne() payable public returns(uint256){ - return 1; - } - function testNN(address eAddress) public payable { - D d1=(new D){value:100}(); - d1.getOne(eAddress); - } -} - -contract C{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - fallback() payable external{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract D{ - constructor() payable public{} - fallback() payable external{} - function getOne(address eAddress) payable public returns(uint256){ - eAddress.call{value:1}(abi.encodeWithSignature("getZero()"));//2.1 - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractLinkage001.sol b/framework/src/test/resources/soliditycode_0.7.6/contractLinkage001.sol deleted file mode 100644 index 8d441fba2da..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractLinkage001.sol +++ /dev/null @@ -1,9 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -constructor() payable public{} -fallback() payable external{} -function divideIHaveArgsReturn(int x,int y) public payable returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractLinkage002.sol b/framework/src/test/resources/soliditycode_0.7.6/contractLinkage002.sol deleted file mode 100644 index 92778e42bc9..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractLinkage002.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractLinkage003.sol b/framework/src/test/resources/soliditycode_0.7.6/contractLinkage003.sol deleted file mode 100644 index 92778e42bc9..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractLinkage003.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractLinkage004.sol b/framework/src/test/resources/soliditycode_0.7.6/contractLinkage004.sol deleted file mode 100644 index 92778e42bc9..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractLinkage004.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractLinkage005.sol b/framework/src/test/resources/soliditycode_0.7.6/contractLinkage005.sol deleted file mode 100644 index 7b943aee5c1..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractLinkage005.sol +++ /dev/null @@ -1,51 +0,0 @@ -contract timeoutTest { - string public iarray1; - // cpu - function oneCpu() public { - require(1==1); - } - - function storage8Char() public { - iarray1 = "12345678"; - } - - function testUseCpu(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - } - return count; - } - - - uint256[] public iarray; - uint public calculatedFibNumber; - mapping(address=>mapping(address=>uint256)) public m; - - function testUseStorage(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - iarray.push(i); - } - return count; - } - - // stack - //uint n = 0; - uint yy = 0; - function test() public { - //n += 1; - yy += 1; - test(); - } - - function setFibonacci(uint n) public returns (uint256){ - calculatedFibNumber = fibonacci(n); - return calculatedFibNumber; - } - - function fibonacci(uint n) internal returns (uint) { - return fibonacci(n - 1) + fibonacci(n - 2); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractLinkage006.sol b/framework/src/test/resources/soliditycode_0.7.6/contractLinkage006.sol deleted file mode 100644 index 53449f61ce2..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractLinkage006.sol +++ /dev/null @@ -1,18 +0,0 @@ - -contract AA{ - uint256 public count=0; - constructor () payable public{} - function init(address payable addr, uint256 max) payable public { - count =0; - this.hack(addr,max); - } - function hack(address payable addr, uint256 max) payable public { - while (count < max) { - count = count +1; - this.hack(addr,max); - } - if (count == max) { - addr.send(20); - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractOriginEnergyLimit001.sol b/framework/src/test/resources/soliditycode_0.7.6/contractOriginEnergyLimit001.sol deleted file mode 100644 index 6feb7fff3b8..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractOriginEnergyLimit001.sol +++ /dev/null @@ -1,11 +0,0 @@ - - -contract findArgsContractTest{ - function findArgsByIndexTest(uint i) public returns (uint z) { - uint[] memory a = new uint[](3); - a[0]=1; - a[1]=2; - a[2]=3; - return a[i]; - } -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractOriginEnergyLimit004.sol b/framework/src/test/resources/soliditycode_0.7.6/contractOriginEnergyLimit004.sol deleted file mode 100644 index 6feb7fff3b8..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractOriginEnergyLimit004.sol +++ /dev/null @@ -1,11 +0,0 @@ - - -contract findArgsContractTest{ - function findArgsByIndexTest(uint i) public returns (uint z) { - uint[] memory a = new uint[](3); - a[0]=1; - a[1]=2; - a[2]=3; - return a[i]; - } -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractOtherToTrcToken.sol b/framework/src/test/resources/soliditycode_0.7.6/contractOtherToTrcToken.sol deleted file mode 100644 index 933358e128b..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractOtherToTrcToken.sol +++ /dev/null @@ -1,41 +0,0 @@ - - -contract ConvertType { - -constructor() payable public{} - -fallback() payable external{} - -//function stringToTrctoken(address payable toAddress, string memory tokenStr, uint256 tokenValue) public { -// trcToken t = trcToken(tokenStr); // ERROR -// toAddress.transferToken(tokenValue, tokenStr); // ERROR -//} - -function uint256ToTrctoken(address payable toAddress, uint256 tokenValue, uint256 tokenInt) public { - trcToken t = trcToken(tokenInt); // OK - toAddress.transferToken(tokenValue, t); // OK - toAddress.transferToken(tokenValue, tokenInt); // OK -} - -function addressToTrctoken(address payable toAddress, uint256 tokenValue, address adr) public { - trcToken t = trcToken(adr); // OK - toAddress.transferToken(tokenValue, t); // OK -//toAddress.transferToken(tokenValue, adr); // ERROR -} - -//function bytesToTrctoken(address payable toAddress, bytes memory b, uint256 tokenValue) public { - // trcToken t = trcToken(b); // ERROR - // toAddress.transferToken(tokenValue, b); // ERROR -//} - -function bytes32ToTrctoken(address payable toAddress, uint256 tokenValue, bytes32 b32) public { - trcToken t = trcToken(b32); // OK - toAddress.transferToken(tokenValue, t); // OK -// toAddress.transferToken(tokenValue, b32); // ERROR -} - -//function arrayToTrctoken(address payable toAddress, uint256[] memory arr, uint256 tokenValue) public { -//trcToken t = trcToken(arr); // ERROR -// toAddress.transferToken(tokenValue, arr); // ERROR -//} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractScenario001.sol b/framework/src/test/resources/soliditycode_0.7.6/contractScenario001.sol deleted file mode 100644 index 92778e42bc9..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractScenario001.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractScenario002.sol b/framework/src/test/resources/soliditycode_0.7.6/contractScenario002.sol deleted file mode 100644 index 5b990fe36e8..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractScenario002.sol +++ /dev/null @@ -1,53 +0,0 @@ - -contract TronNative{ - - address public voteContractAddress= address(0x10001); - address public freezeBalanceAddress = address(0x10002); - address public unFreezeBalanceAddress = address(0x10003); - address public withdrawBalanceAddress = address(0x10004); - address public approveProposalAddress = address(0x10005); - address public createProposalAddress = address(0x10006); - address public deleteProposalAddress = address(0x10007); - constructor () payable public {} - - function voteForSingleWitness (address payable witnessAddr, uint256 voteValue) public{ - // method 1: - voteContractAddress.delegatecall(abi.encode(witnessAddr,voteValue)); - } - - function voteUsingAssembly (address witnessAddr, uint256 voteValue) public{ - // method 2: - assembly{ - mstore(0x80,witnessAddr) - mstore(0xa0,voteValue) - // gas, address, in, size, out, size - if iszero(delegatecall(0, 0x10001, 0x80, 0x40, 0x80, 0x0)) { - revert(0, 0) - } - } - } - - function freezeBalance(uint256 frozen_Balance,uint256 frozen_Duration) public { - freezeBalanceAddress.delegatecall(abi.encode(frozen_Balance,frozen_Duration)); - } - - function unFreezeBalance() public { - unFreezeBalanceAddress.delegatecall(""); - } - - function withdrawBalance() public { - withdrawBalanceAddress.delegatecall(""); - } - - function approveProposal(uint256 id, bool isApprove) public { - approveProposalAddress.delegatecall(abi.encode(id,isApprove)); - } - - function createProposal(bytes32 [] memory data) public { - createProposalAddress.delegatecall(abi.encode(data)); - } - - function deleteProposal(uint256 id) public{ - deleteProposalAddress.delegatecall(abi.encode(id)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractScenario003.sol b/framework/src/test/resources/soliditycode_0.7.6/contractScenario003.sol deleted file mode 100644 index 92778e42bc9..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractScenario003.sol +++ /dev/null @@ -1,7 +0,0 @@ - - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractScenario004.sol b/framework/src/test/resources/soliditycode_0.7.6/contractScenario004.sol deleted file mode 100644 index f6919502914..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractScenario004.sol +++ /dev/null @@ -1,88 +0,0 @@ - - -contract TronToken { - - string public name = "Tronix"; // token name - string public symbol = "TRX"; // token symbol - uint256 public decimals = 6; // token digit - - mapping (address => uint256) public balanceOf; - mapping (address => mapping (address => uint256)) public allowance; - - uint256 public totalSupply = 0; - bool public stopped = false; - - uint256 constant valueFounder = 100000000000000000; - address owner = address(0x0); - - modifier isOwner { - assert(owner == msg.sender); - _; - } - - modifier isRunning { - assert (!stopped); - _; - } - - modifier validAddress { - assert(address(0x0) != msg.sender); - _; - } - - constructor(address _addressFounder) public { - owner = msg.sender; - totalSupply = valueFounder; - balanceOf[_addressFounder] = valueFounder; - emit Transfer(address(0x0), _addressFounder, valueFounder); - } - - function transfer(address _to, uint256 _value) isRunning validAddress public returns (bool success) { - require(balanceOf[msg.sender] >= _value); - require(balanceOf[_to] + _value >= balanceOf[_to]); - balanceOf[msg.sender] -= _value; - balanceOf[_to] += _value; - emit Transfer(msg.sender, _to, _value); - return true; - } - - function transferFrom(address _from, address _to, uint256 _value) isRunning validAddress public returns (bool success) { - require(balanceOf[_from] >= _value); - require(balanceOf[_to] + _value >= balanceOf[_to]); - require(allowance[_from][msg.sender] >= _value); - balanceOf[_to] += _value; - balanceOf[_from] -= _value; - allowance[_from][msg.sender] -= _value; - emit Transfer(_from, _to, _value); - return true; - } - - function approve(address _spender, uint256 _value) isRunning validAddress public returns (bool success) { - require(_value == 0 || allowance[msg.sender][_spender] == 0); - allowance[msg.sender][_spender] = _value; - emit Approval(msg.sender, _spender, _value); - return true; - } - - function stop() isOwner public { - stopped = true; - } - - function start() isOwner public { - stopped = false; - } - - function setName(string memory _name) isOwner public { - name = _name; - } - - function burn(uint256 _value) public { - require(balanceOf[msg.sender] >= _value); - balanceOf[msg.sender] -= _value; - balanceOf[address(0x0)] += _value; - emit Transfer(msg.sender, address(0x0), _value); - } - - event Transfer(address indexed _from, address indexed _to, uint256 _value); - event Approval(address indexed _owner, address indexed _spender, uint256 _value); -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractScenario005.sol b/framework/src/test/resources/soliditycode_0.7.6/contractScenario005.sol deleted file mode 100644 index 39fe4665559..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractScenario005.sol +++ /dev/null @@ -1,103 +0,0 @@ - - -interface token { - function transfer(address receiver, uint amount) external; -} - -contract Crowdsale { - address payable public beneficiary = 0x1b228F5D9f934c7bb18Aaa86F90418932888E7b4; // 募资成功后的收款方 - uint public fundingGoal = 10000000; // 募资额度 - uint public amountRaised = 1000000; // 参与数量 - uint public deadline; // 募资截止期 - - uint public price; // token 与以太坊的汇率 , token卖多少钱 - token public tokenReward; // 要卖的token - - mapping(address => uint256) public balanceOf; - - bool fundingGoalReached = false; // 众筹是否达到目标 - bool crowdsaleClosed = false; // 众筹是否结束 - - /** - * 事件可以用来跟踪信息 - **/ - event GoalReached(address recipient, uint totalAmountRaised); - event FundTransfer(address backer, uint amount, bool isContribution); - - /** - * 构造函数, 设置相关属性 - */ - constructor( - address payable ifSuccessfulSendTo, - uint fundingGoalInEthers, - uint durationInMinutes, - uint finneyCostOfEachToken, - address addressOfTokenUsedAsReward) public{ - beneficiary = ifSuccessfulSendTo; - fundingGoal = fundingGoalInEthers * 1 sun; - deadline = block.timestamp + durationInMinutes * 1 minutes; - price = finneyCostOfEachToken * 1 trx; - tokenReward = token(addressOfTokenUsedAsReward); // 传入已发布的 token 合约的地址来创建实例 - } - - /** - * 无函数名的Fallback函数, - * 在向合约转账时,这个函数会被调用 - */ - fallback() payable external{ - require(!crowdsaleClosed); - uint amount = msg.value; - balanceOf[msg.sender] += amount; - amountRaised += amount; - tokenReward.transfer(msg.sender, amount / price); - emit FundTransfer(msg.sender, amount, true); - } - - /** - * 定义函数修改器modifier(作用和Python的装饰器很相似) - * 用于在函数执行前检查某种前置条件(判断通过之后才会继续执行该方法) - * _ 表示继续执行之后的代码 - **/ - modifier afterDeadline() { if (block.timestamp >= deadline) _; } - - /** - * 判断众筹是否完成融资目标, 这个方法使用了afterDeadline函数修改器 - * - */ - function checkGoalReached() afterDeadline public{ - if (amountRaised >= fundingGoal) { - fundingGoalReached = true; - emit GoalReached(beneficiary, amountRaised); - } - crowdsaleClosed = true; - } - - - /** - * 完成融资目标时,融资款发送到收款方 - * 未完成融资目标时,执行退款 - * - */ - function safeWithdrawal() afterDeadline public{ - if (!fundingGoalReached) { - uint amount = balanceOf[msg.sender]; - balanceOf[msg.sender] = 0; - if (amount > 0) { - if (msg.sender.send(amount)) { - emit FundTransfer(msg.sender, amount, false); - } else { - balanceOf[msg.sender] = amount; - } - } - } - - if (fundingGoalReached && beneficiary == msg.sender) { - if (payable(beneficiary).send(amountRaised)) { - emit FundTransfer(beneficiary, amountRaised, false); - } else { - //If we fail to send the funds to beneficiary, unlock funders balance - fundingGoalReached = false; - } - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractScenario006.sol b/framework/src/test/resources/soliditycode_0.7.6/contractScenario006.sol deleted file mode 100644 index 7b8e2270e23..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractScenario006.sol +++ /dev/null @@ -1,1963 +0,0 @@ - - -interface PlayerBookInterface { - function getPlayerID(address _addr) external returns (uint256); - function getPlayerName(uint256 _pID) external view returns (bytes32); - function getPlayerLAff(uint256 _pID) external view returns (uint256); - function getPlayerAddr(uint256 _pID) external view returns (address); - function getNameFee() external view returns (uint256); - function registerNameXIDFromDapp(address _addr, bytes32 _name, uint256 _affCode, bool _all) external payable returns(bool, uint256); - function registerNameXaddrFromDapp(address _addr, bytes32 _name, address _affCode, bool _all) external payable returns(bool, uint256); - function registerNameXnameFromDapp(address _addr, bytes32 _name, bytes32 _affCode, bool _all) external payable returns(bool, uint256); - function isDev(address _who) external view returns(bool); -} - - -/** -* @title -Name Filter- v0.1.9 -* ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ -* │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ -* ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ -* _____ _____ -* (, / /) /) /) (, / /) /) -* ┌─┐ / _ (/_ // // / _ // _ __ _(/ -* ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ -* ┴ ┴ / / .-/ _____ (__ / -* (__ / (_/ (, / /)™ -* / __ __ __ __ _ __ __ _ _/_ _ _(/ -* ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ -* ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 -* ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ -* _ __ _ ____ ____ _ _ _____ ____ ___ -*=============| |\ | / /\ | |\/| | |_ =====| |_ | | | | | | | |_ | |_)==============* -*=============|_| \| /_/--\ |_| | |_|__=====|_| |_| |_|__ |_| |_|__ |_| \==============* -* -* ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ -* ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ -* ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ -*/ - -library NameFilter { - /** - * @dev filters name strings - * -converts uppercase to lower case. - * -makes sure it does not start/end with a space - * -makes sure it does not contain multiple spaces in a row - * -cannot be only numbers - * -cannot start with 0x - * -restricts characters to A-Z, a-z, 0-9, and space. - * @return reprocessed string in bytes32 format - */ - function nameFilter(string memory _input) - internal - pure - returns(bytes32) - { - bytes memory _temp = bytes(_input); - uint256 _length = _temp.length; - - //sorry limited to 32 characters - require (_length <= 32 && _length > 0, "string must be between 1 and 32 characters"); - // make sure it doesnt start with or end with space - require(_temp[0] != 0x20 && _temp[_length-1] != 0x20, "string cannot start or end with space"); - // make sure first two characters are not 0x - if (_temp[0] == 0x30) - { - require(_temp[1] != 0x78, "string cannot start with 0x"); - require(_temp[1] != 0x58, "string cannot start with 0X"); - } - - // create a bool to track if we have a non number character - bool _hasNonNumber; - - // convert & check - for (uint256 i = 0; i < _length; i++) - { - // if its uppercase A-Z - if (_temp[i] > 0x40 && _temp[i] < 0x5b) - { - // convert to lower case a-z - _temp[i] = byte(uint8(_temp[i]) + 32); - - // we have a non number - if (_hasNonNumber == false) - _hasNonNumber = true; - } else { - require - ( - // require character is a space - _temp[i] == 0x20 || - // OR lowercase a-z - (_temp[i] > 0x60 && _temp[i] < 0x7b) || - // or 0-9 - (_temp[i] > 0x2f && _temp[i] < 0x3a), - "string contains invalid characters" - ); - // make sure theres not 2x spaces in a row - if (_temp[i] == 0x20) - require( _temp[i+1] != 0x20, "string cannot contain consecutive spaces"); - - // see if we have a character other than a number - if (_hasNonNumber == false && (_temp[i] < 0x30 || _temp[i] > 0x39)) - _hasNonNumber = true; - } - } - - require(_hasNonNumber == true, "string cannot be only numbers"); - - bytes32 _ret; - assembly { - _ret := mload(add(_temp, 32)) - } - return (_ret); - } -} - - -library SafeMath { - - /** - * @dev Multiplies two numbers, throws on overflow. - */ - function mul(uint256 a, uint256 b) - internal - pure - returns (uint256 c) - { - if (a == 0) { - return 0; - } - c = a * b; - require(c / a == b, "SafeMath mul failed"); - return c; - } - - /** - * @dev Integer division of two numbers, truncating the quotient. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // assert(b > 0); // Solidity automatically throws when dividing by 0 - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - return c; - } - - /** - * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 a, uint256 b) - internal - pure - returns (uint256) - { - require(b <= a, "SafeMath sub failed"); - return a - b; - } - - /** - * @dev Adds two numbers, throws on overflow. - */ - function add(uint256 a, uint256 b) - internal - pure - returns (uint256 c) - { - c = a + b; - require(c >= a, "SafeMath add failed"); - return c; - } - - /** - * @dev gives square root of given x. - */ - function sqrt(uint256 x) - internal - pure - returns (uint256 y) - { - uint256 z = ((add(x,1)) / 2); - y = x; - while (z < y) - { - y = z; - z = ((add((x / z),z)) / 2); - } - } - - /** - * @dev gives square. multiplies x by x - */ - function sq(uint256 x) - internal - pure - returns (uint256) - { - return (mul(x,x)); - } - - /** - * @dev x to the power of y - */ - function pwr(uint256 x, uint256 y) - internal - pure - returns (uint256) - { - if (x==0) - return (0); - else if (y==0) - return (1); - else - { - uint256 z = x; - for (uint256 i=1; i < y; i++) - z = mul(z,x); - return (z); - } - } -} - -//============================================================================== -// | _ _ _ | _ . -// |<(/_\/ (_(_||(_ . -//=======/====================================================================== -library F3DKeysCalcLong { - using SafeMath for *; - /** - * @dev calculates number of keys received given X eth - * @param _curEth current amount of eth in contract - * @param _newEth eth being spent - * @return amount of ticket purchased - */ - function keysRec(uint256 _curEth, uint256 _newEth) - internal - pure - returns (uint256) - { - return(keys((_curEth).add(_newEth)).sub(keys(_curEth))); - } - - /** - * @dev calculates amount of eth received if you sold X keys - * @param _curKeys current amount of keys that exist - * @param _sellKeys amount of keys you wish to sell - * @return amount of eth received - */ - function ethRec(uint256 _curKeys, uint256 _sellKeys) - internal - pure - returns (uint256) - { - return((eth(_curKeys)).sub(eth(_curKeys.sub(_sellKeys)))); - } - - /** - * @dev calculates how many keys would exist with given an amount of eth - * @param _eth eth "in contract" - * @return number of keys that would exist - */ - function keys(uint256 _eth) - internal - pure - returns(uint256) - { - return ((((((_eth).mul(1000000000000000000)).mul(312500000000000000000000000)).add(5624988281256103515625000000000000000000000000000000000000000000)).sqrt()).sub(74999921875000000000000000000000)) / (156250000); - } - - /** - * @dev calculates how much eth would be in contract given a number of keys - * @param _keys number of keys "in contract" - * @return eth that would exists - */ - function eth(uint256 _keys) - internal - pure - returns(uint256) - { - return ((78125000).mul(_keys.sq()).add(((149999843750000).mul(_keys.mul(1000000000000000000))) / (2))) / ((1000000000000000000).sq()); - } -} - -library F3Ddatasets { - //compressedData key - // [76-33][32][31][30][29][28-18][17][16-6][5-3][2][1][0] - // 0 - new player (bool) - // 1 - joined round (bool) - // 2 - new leader (bool) - // 3-5 - air drop tracker (uint 0-999) - // 6-16 - round end time - // 17 - winnerTeam - // 18 - 28 timestamp - // 29 - team - // 30 - 0 = reinvest (round), 1 = buy (round), 2 = buy (ico), 3 = reinvest (ico) - // 31 - airdrop happened bool - // 32 - airdrop tier - // 33 - airdrop amount won - //compressedIDs key - // [77-52][51-26][25-0] - // 0-25 - pID - // 26-51 - winPID - // 52-77 - rID - struct EventReturns { - uint256 compressedData; - uint256 compressedIDs; - address winnerAddr; // winner address - bytes32 winnerName; // winner name - uint256 amountWon; // amount won - uint256 newPot; // amount in new pot - uint256 P3DAmount; // amount distributed to p3d - uint256 genAmount; // amount distributed to gen - uint256 potAmount; // amount added to pot - } - struct Player { - address payable addr; // player address - bytes32 name; // player name - uint256 win; // winnings vault - uint256 gen; // general vault - uint256 aff; // affiliate vault - uint256 lrnd; // last round played - uint256 laff; // last affiliate id used - } - struct PlayerRounds { - uint256 eth; // eth player has added to round (used for eth limiter) - uint256 keys; // keys - uint256 mask; // player mask - uint256 ico; // ICO phase investment - } - struct Round { - uint256 plyr; // pID of player in lead - uint256 team; // tID of team in lead - uint256 end; // time ends/ended - bool ended; // has round end function been ran - uint256 strt; // time round started - uint256 keys; // keys - uint256 eth; // total eth in - uint256 pot; // eth to pot (during round) / final amount paid to winner (after round ends) - uint256 mask; // global mask - uint256 ico; // total eth sent in during ICO phase - uint256 icoGen; // total eth for gen during ICO phase - uint256 icoAvg; // average key price for ICO phase - } - struct TeamFee { - uint256 gen; // % of buy in thats paid to key holders of current round - uint256 p3d; // % of buy in thats paid to p3d holders - } - struct PotSplit { - uint256 gen; // % of pot thats paid to key holders of current round - uint256 p3d; // % of pot thats paid to p3d holders - } -} - -contract F3Devents { - // fired whenever a player registers a name - event onNewName - ( - uint256 indexed playerID, - address indexed playerAddress, - bytes32 indexed playerName, - bool isNewPlayer, - uint256 affiliateID, - address affiliateAddress, - bytes32 affiliateName, - uint256 amountPaid, - uint256 timeStamp - ); - - // fired at end of buy or reload - event onEndTx - ( - uint256 compressedData, - uint256 compressedIDs, - bytes32 playerName, - address playerAddress, - uint256 ethIn, - uint256 keysBought, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount, - uint256 potAmount, - uint256 airDropPot - ); - - // fired whenever theres a withdraw - event onWithdraw - ( - uint256 indexed playerID, - address playerAddress, - bytes32 playerName, - uint256 ethOut, - uint256 timeStamp - ); - - // fired whenever a withdraw forces end round to be ran - event onWithdrawAndDistribute - ( - address playerAddress, - bytes32 playerName, - uint256 ethOut, - uint256 compressedData, - uint256 compressedIDs, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount - ); - - // (fomo3d long only) fired whenever a player tries a buy after round timer - // hit zero, and causes end round to be ran. - event onBuyAndDistribute - ( - address playerAddress, - bytes32 playerName, - uint256 ethIn, - uint256 compressedData, - uint256 compressedIDs, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount - ); - - // (fomo3d long only) fired whenever a player tries a reload after round timer - // hit zero, and causes end round to be ran. - event onReLoadAndDistribute - ( - address playerAddress, - bytes32 playerName, - uint256 compressedData, - uint256 compressedIDs, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount - ); - - // fired whenever an affiliate is paid - event onAffiliatePayout - ( - uint256 indexed affiliateID, - address affiliateAddress, - bytes32 affiliateName, - uint256 indexed roundID, - uint256 indexed buyerID, - uint256 amount, - uint256 timeStamp - ); - - // received pot swap deposit - event onPotSwapDeposit - ( - uint256 roundID, - uint256 amountAddedToPot - ); -} - - - -contract FoMo3Dlong is F3Devents { - using SafeMath for *; - using NameFilter for string; - using F3DKeysCalcLong for uint256; - - address public otherF3D_; - address public Divies; - address public Jekyll_Island_Inc; - PlayerBookInterface public playerBook;// =PlayerBookInterface(0x0dcd2f752394c41875e259e00bb44fd505297caf);//new PlayerBook();// - // TeamJustInterface constant private teamJust = TeamJustInterface(0x3a5f8140b9213a0f733a6a639857c9df43ee3f5a);// new TeamJust();// - - //============================================================================== - // _ _ _ |`. _ _ _ |_ | _ _ . - // (_(_)| |~|~|(_||_|| (_||_)|(/__\ . (game settings) - //=================_|=========================================================== - string constant public name = "FoMo3D Long Official"; - string constant public symbol = "F3D"; - uint256 private rndExtra_ = 30;//extSettings.getLongExtra(); // length of the very first ICO - uint256 private rndGap_ = 30; //extSettings.getLongGap(); // length of ICO phase, set to 1 year for EOS. - uint256 constant private rndInit_ = 1 hours; // round timer starts at this - uint256 constant private rndInc_ = 30 seconds; // every full key purchased adds this much to the timer - uint256 constant private rndMax_ = 24 hours; // max length a round timer can be - //============================================================================== - // _| _ _|_ _ _ _ _|_ _ . - // (_|(_| | (_| _\(/_ | |_||_) . (data used to store game info that changes) - //=============================|================================================ - uint256 public airDropPot_; // person who gets the airdrop wins part of this pot - uint256 public airDropTracker_ = 0; // incremented each time a "qualified" tx occurs. used to determine winning air drop - uint256 public rID_; // round id number / total rounds that have happened - //**************** - // PLAYER DATA - //**************** - mapping(address => uint256) public pIDxAddr_; // (addr => pID) returns player id by address - mapping(bytes32 => uint256) public pIDxName_; // (name => pID) returns player id by name - mapping(uint256 => F3Ddatasets.Player) public plyr_; // (pID => data) player data - mapping(uint256 => mapping(uint256 => F3Ddatasets.PlayerRounds)) public plyrRnds_; // (pID => rID => data) player round data by player id & round id - mapping(uint256 => mapping(bytes32 => bool)) public plyrNames_; // (pID => name => bool) list of names a player owns. (used so you can change your display name amongst any name you own) - //**************** - // ROUND DATA - //**************** - mapping(uint256 => F3Ddatasets.Round) public round_; // (rID => data) round data - mapping(uint256 => mapping(uint256 => uint256)) public rndTmEth_; // (rID => tID => data) eth in per team, by round id and team id - //**************** - // TEAM FEE DATA - //**************** - mapping(uint256 => F3Ddatasets.TeamFee) public fees_; // (team => fees) fee distribution by team - mapping(uint256 => F3Ddatasets.PotSplit) public potSplit_; // (team => fees) pot split distribution by team - - function setPlayerBook(address _playerBook) external { - require(msg.sender == owner, 'only dev!'); - require(address(playerBook) == address(0), 'already set!'); - playerBook = PlayerBookInterface(_playerBook); - } - - address public owner; - - //============================================================================== - // _ _ _ __|_ _ __|_ _ _ . - // (_(_)| |_\ | | |_|(_ | (_)| . (initial data setup upon contract deploy) - //============================================================================== - constructor() - public - { - owner = msg.sender; - // Team allocation structures - // 0 = whales - // 1 = bears - // 2 = sneks - // 3 = bulls - - // Team allocation percentages - // (F3D, P3D) + (Pot , Referrals, Community) - // Referrals / Community rewards are mathematically designed to come from the winner's share of the pot. - fees_[0] = F3Ddatasets.TeamFee(30, 6); - //50% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - fees_[1] = F3Ddatasets.TeamFee(43, 0); - //43% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - fees_[2] = F3Ddatasets.TeamFee(56, 10); - //20% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - fees_[3] = F3Ddatasets.TeamFee(43, 8); - //35% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - - // how to split up the final pot based on which team was picked - // (F3D, P3D) - potSplit_[0] = F3Ddatasets.PotSplit(15, 10); - //48% to winner, 25% to next round, 2% to com - potSplit_[1] = F3Ddatasets.PotSplit(25, 0); - //48% to winner, 25% to next round, 2% to com - potSplit_[2] = F3Ddatasets.PotSplit(20, 20); - //48% to winner, 10% to next round, 2% to com - potSplit_[3] = F3Ddatasets.PotSplit(30, 10); - //48% to winner, 10% to next round, 2% to com - } - //============================================================================== - // _ _ _ _|. |`. _ _ _ . - // | | |(_)(_||~|~|(/_| _\ . (these are safety checks) - //============================================================================== - /** - * @dev used to make sure no one can interact with contract until it has - * been activated. - */ - modifier isActivated() { - require(activated_ == true, "its not ready yet. check ?eta in discord"); - _; - } - - /** - * @dev prevents contracts from interacting with fomo3d - */ - modifier isHuman() { - address _addr = msg.sender; - uint256 _codeLength; - - assembly {_codeLength := extcodesize(_addr)} - require(_codeLength == 0, "sorry humans only"); - _; - } - - modifier onlyDevs() - { - require(playerBook.isDev(msg.sender) == true, "msg sender is not a dev"); - _; - } - - /** - * @dev sets boundaries for incoming tx - */ - modifier isWithinLimits(uint256 _eth) { - require(_eth >= 1000000000, "pocket lint: not a valid currency"); - require(_eth <= 100000000000000000000000, "no vitalik, no"); - _; - } - - //============================================================================== - // _ |_ |. _ |` _ __|_. _ _ _ . - // |_)|_||_)||(_ ~|~|_|| |(_ | |(_)| |_\ . (use these to interact with contract) - //====|========================================================================= - /** - * @dev emergency buy uses last stored affiliate ID and team snek - */ - fallback() - isActivated() - isHuman() - isWithinLimits(msg.value) - external - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_ ; - _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // buy core - buyCore(_pID, plyr_[_pID].laff, 2, _eventData_); - } - - /** - * @dev converts all incoming ethereum to keys. - * -functionhash- 0x8f38f309 (using ID for affiliate) - * -functionhash- 0x98a0871d (using address for affiliate) - * -functionhash- 0xa65b37a1 (using name for affiliate) - * @param _affCode the ID/address/name of the player who gets the affiliate fee - * @param _team what team is the player playing for? - */ - function buyXid(uint256 _affCode, uint256 _team) - isActivated() - isHuman() - isWithinLimits(msg.value) - public - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_; - _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == 0 || _affCode == _pID) - { - // use last stored affiliate code - _affCode = plyr_[_pID].laff; - - // if affiliate code was given & its not the same as previously stored - } else if (_affCode != plyr_[_pID].laff) { - // update last affiliate - plyr_[_pID].laff = _affCode; - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // buy core - buyCore(_pID, _affCode, _team, _eventData_); - } - - function buyXaddr(address _affCode, uint256 _team) - isActivated() - isHuman() - isWithinLimits(msg.value) - public - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_; - _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == address(0) || _affCode == msg.sender) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxAddr_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // buy core - buyCore(_pID, _affID, _team, _eventData_); - } - - function buyXname(bytes32 _affCode, uint256 _team) - isActivated() - isHuman() - isWithinLimits(msg.value) - public - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_ ; - _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == '' || _affCode == plyr_[_pID].name) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxName_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // buy core - buyCore(_pID, _affID, _team, _eventData_); - } - - /** - * @dev essentially the same as buy, but instead of you sending ether - * from your wallet, it uses your unwithdrawn earnings. - * -functionhash- 0x349cdcac (using ID for affiliate) - * -functionhash- 0x82bfc739 (using address for affiliate) - * -functionhash- 0x079ce327 (using name for affiliate) - * @param _affCode the ID/address/name of the player who gets the affiliate fee - * @param _team what team is the player playing for? - * @param _eth amount of earnings to use (remainder returned to gen vault) - */ - function reLoadXid(uint256 _affCode, uint256 _team, uint256 _eth) - isActivated() - isHuman() - isWithinLimits(_eth) - public - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == 0 || _affCode == _pID) - { - // use last stored affiliate code - _affCode = plyr_[_pID].laff; - - // if affiliate code was given & its not the same as previously stored - } else if (_affCode != plyr_[_pID].laff) { - // update last affiliate - plyr_[_pID].laff = _affCode; - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // reload core - reLoadCore(_pID, _affCode, _team, _eth, _eventData_); - } - - function reLoadXaddr(address _affCode, uint256 _team, uint256 _eth) - isActivated() - isHuman() - isWithinLimits(_eth) - public - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == address(0) || _affCode == msg.sender) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxAddr_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // reload core - reLoadCore(_pID, _affID, _team, _eth, _eventData_); - } - - function reLoadXname(bytes32 _affCode, uint256 _team, uint256 _eth) - isActivated() - isHuman() - isWithinLimits(_eth) - public - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == '' || _affCode == plyr_[_pID].name) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxName_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // reload core - reLoadCore(_pID, _affID, _team, _eth, _eventData_); - } - - /** - * @dev withdraws all of your earnings. - * -functionhash- 0x3ccfd60b - */ - function withdraw() - isActivated() - isHuman() - public - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = block.timestamp; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // setup temp var for player eth - uint256 _eth; - - // check to see if round has ended and no one has run round end yet - if (_now > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // end the round (distributes pot) - round_[_rID].ended = true; - _eventData_ = endRound(_eventData_); - - // get their earnings - _eth = withdrawEarnings(_pID); - - // gib moni - if (_eth > 0) - plyr_[_pID].addr.transfer(_eth); - - // build event data - _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; - - // fire withdraw and distribute event - emit F3Devents.onWithdrawAndDistribute - ( - msg.sender, - plyr_[_pID].name, - _eth, - _eventData_.compressedData, - _eventData_.compressedIDs, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount - ); - - // in any other situation - } else { - // get their earnings - _eth = withdrawEarnings(_pID); - - // gib moni - if (_eth > 0) - plyr_[_pID].addr.transfer(_eth); - - // fire withdraw event - emit F3Devents.onWithdraw(_pID, msg.sender, plyr_[_pID].name, _eth, _now); - } - } - - /** - * @dev use these to register names. they are just wrappers that will send the - * registration requests to the PlayerBook contract. So registering here is the - * same as registering there. UI will always display the last name you registered. - * but you will still own all previously registered names to use as affiliate - * links. - * - must pay a registration fee. - * - name must be unique - * - names will be converted to lowercase - * - name cannot start or end with a space - * - cannot have more than 1 space in a row - * - cannot be only numbers - * - cannot start with 0x - * - name must be at least 1 char - * - max length of 32 characters long - * - allowed characters: a-z, 0-9, and space - * -functionhash- 0x921dec21 (using ID for affiliate) - * -functionhash- 0x3ddd4698 (using address for affiliate) - * -functionhash- 0x685ffd83 (using name for affiliate) - * @param _nameString players desired name - * @param _affCode affiliate ID, address, or name of who referred you - * @param _all set to true if you want this to push your info to all games - * (this might cost a lot of gas) - */ - function registerNameXID(string memory _nameString, uint256 _affCode, bool _all) - isHuman() - public - payable - { - bytes32 _name = _nameString.nameFilter(); - address _addr = msg.sender; - uint256 _paid = msg.value; - (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXIDFromDapp{value:_paid}(_addr, _name, _affCode, _all); - - uint256 _pID = pIDxAddr_[_addr]; - - // fire event - emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, block.timestamp); - } - - function registerNameXaddr(string memory _nameString, address _affCode, bool _all) - isHuman() - public - payable - { - bytes32 _name = _nameString.nameFilter(); - address _addr = msg.sender; - uint256 _paid = msg.value; - (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXaddrFromDapp{value:msg.value}(msg.sender, _name, _affCode, _all); - - uint256 _pID = pIDxAddr_[_addr]; - - // fire event - emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, block.timestamp); - } - - function registerNameXname(string memory _nameString, bytes32 _affCode, bool _all) - isHuman() - public - payable - { - bytes32 _name = _nameString.nameFilter(); - address _addr = msg.sender; - uint256 _paid = msg.value; - (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXnameFromDapp{value:msg.value}(msg.sender, _name, _affCode, _all); - - uint256 _pID = pIDxAddr_[_addr]; - - // fire event - emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, block.timestamp); - } - //============================================================================== - // _ _ _|__|_ _ _ _ . - // (_|(/_ | | (/_| _\ . (for UI & viewing things on etherscan) - //=====_|======================================================================= - /** - * @dev return the price buyer will pay for next 1 individual key. - * -functionhash- 0x018a25e8 - * @return price for next key bought (in wei format) - */ - function getBuyPrice() - public - view - returns (uint256) - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = block.timestamp; - - // are we in a round? - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - return ((round_[_rID].keys.add(1000000000000000000)).ethRec(1000000000000000000)); - else // rounds over. need price for new round - return (75000000000000); - // init - } - - /** - * @dev returns time left. dont spam this, you'll ddos yourself from your node - * provider - * -functionhash- 0xc7e284b8 - * @return time left in seconds - */ - function getTimeLeft() - public - view - returns (uint256) - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = block.timestamp; - - if (_now < round_[_rID].end) - if (_now > round_[_rID].strt + rndGap_) - return ((round_[_rID].end).sub(_now)); - else - return ((round_[_rID].strt + rndGap_).sub(_now)); - else - return (0); - } - - /** - * @dev returns player earnings per vaults - * -functionhash- 0x63066434 - * @return winnings vault - * @return general vault - * @return affiliate vault - */ - function getPlayerVaults(uint256 _pID) - public - view - returns (uint256, uint256, uint256) - { - // setup local rID - uint256 _rID = rID_; - - // if round has ended. but round end has not been run (so contract has not distributed winnings) - if (block.timestamp > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) - { - // if player is winner - if (round_[_rID].plyr == _pID) - { - return - ( - (plyr_[_pID].win).add(((round_[_rID].pot).mul(48)) / 100), - (plyr_[_pID].gen).add(getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask)), - plyr_[_pID].aff - ); - // if player is not the winner - } else { - return - ( - plyr_[_pID].win, - (plyr_[_pID].gen).add(getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask)), - plyr_[_pID].aff - ); - } - - // if round is still going on, or round has ended and round end has been ran - } else { - return - ( - plyr_[_pID].win, - (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), - plyr_[_pID].aff - ); - } - } - - /** - * solidity hates stack limits. this lets us avoid that hate - */ - function getPlayerVaultsHelper(uint256 _pID, uint256 _rID) - private - view - returns (uint256) - { - return (((((round_[_rID].mask).add(((((round_[_rID].pot).mul(potSplit_[round_[_rID].team].gen)) / 100).mul(1000000000000000000)) / (round_[_rID].keys))).mul(plyrRnds_[_pID][_rID].keys)) / 1000000000000000000)); - } - - /** - * @dev returns all current round info needed for front end - * -functionhash- 0x747dff42 - * @return eth invested during ICO phase - * @return round id - * @return total keys for round - * @return time round ends - * @return time round started - * @return current pot - * @return current team ID & player ID in lead - * @return current player in leads address - * @return current player in leads name - * @return whales eth in for round - * @return bears eth in for round - * @return sneks eth in for round - * @return bulls eth in for round - * @return airdrop tracker # & airdrop pot - */ - function getCurrentRoundInfo() - public - view - returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256, address, bytes32, uint256, uint256, uint256, uint256, uint256) - { - // setup local rID - uint256 _rID = rID_; - - return - ( - round_[_rID].ico, //0 - _rID, //1 - round_[_rID].keys, //2 - round_[_rID].end, //3 - round_[_rID].strt, //4 - round_[_rID].pot, //5 - (round_[_rID].team + (round_[_rID].plyr * 10)), //6 - plyr_[round_[_rID].plyr].addr, //7 - plyr_[round_[_rID].plyr].name, //8 - rndTmEth_[_rID][0], //9 - rndTmEth_[_rID][1], //10 - rndTmEth_[_rID][2], //11 - rndTmEth_[_rID][3], //12 - airDropTracker_ + (airDropPot_ * 1000) //13 - ); - } - - /** - * @dev returns player info based on address. if no address is given, it will - * use msg.sender - * -functionhash- 0xee0b5d8b - * @param _addr address of the player you want to lookup - * @return player ID - * @return player name - * @return keys owned (current round) - * @return winnings vault - * @return general vault - * @return affiliate vault - * @return player round eth - */ - function getPlayerInfoByAddress(address _addr) - public - view - returns (uint256, bytes32, uint256, uint256, uint256, uint256, uint256) - { - // setup local rID - uint256 _rID = rID_; - - if (_addr == address(0)) - { - _addr == msg.sender; - } - uint256 _pID = pIDxAddr_[_addr]; - - return - ( - _pID, //0 - plyr_[_pID].name, //1 - plyrRnds_[_pID][_rID].keys, //2 - plyr_[_pID].win, //3 - (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), //4 - plyr_[_pID].aff, //5 - plyrRnds_[_pID][_rID].eth //6 - ); - } - - //============================================================================== - // _ _ _ _ | _ _ . _ . - // (_(_)| (/_ |(_)(_||(_ . (this + tools + calcs + modules = our softwares engine) - //=====================_|======================================================= - /** - * @dev logic runs whenever a buy order is executed. determines how to handle - * incoming eth depending on if we are in an active round or not - */ - function buyCore(uint256 _pID, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) - private - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = block.timestamp; - - // if round is active - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - { - // call core - core(_rID, _pID, msg.value, _affID, _team, _eventData_); - - // if round is not active - } else { - // check to see if end round needs to be ran - if (_now > round_[_rID].end && round_[_rID].ended == false) - { - // end the round (distributes pot) & start new round - round_[_rID].ended = true; - _eventData_ = endRound(_eventData_); - - // build event data - _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; - - // fire buy and distribute event - emit F3Devents.onBuyAndDistribute - ( - msg.sender, - plyr_[_pID].name, - msg.value, - _eventData_.compressedData, - _eventData_.compressedIDs, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount - ); - } - - // put eth in players vault - plyr_[_pID].gen = plyr_[_pID].gen.add(msg.value); - } - } - - /** - * @dev logic runs whenever a reload order is executed. determines how to handle - * incoming eth depending on if we are in an active round or not - */ - function reLoadCore(uint256 _pID, uint256 _affID, uint256 _team, uint256 _eth, F3Ddatasets.EventReturns memory _eventData_) - private - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = block.timestamp; - - // if round is active - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - { - // get earnings from all vaults and return unused to gen vault - // because we use a custom safemath library. this will throw if player - // tried to spend more eth than they have. - plyr_[_pID].gen = withdrawEarnings(_pID).sub(_eth); - - // call core - core(_rID, _pID, _eth, _affID, _team, _eventData_); - - // if round is not active and end round needs to be ran - } else if (_now > round_[_rID].end && round_[_rID].ended == false) { - // end the round (distributes pot) & start new round - round_[_rID].ended = true; - _eventData_ = endRound(_eventData_); - - // build event data - _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; - - // fire buy and distribute event - emit F3Devents.onReLoadAndDistribute - ( - msg.sender, - plyr_[_pID].name, - _eventData_.compressedData, - _eventData_.compressedIDs, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount - ); - } - } - - /** - * @dev this is the core logic for any buy/reload that happens while a round - * is live. - */ - function core(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) - private - { - // if player is new to round - if (plyrRnds_[_pID][_rID].keys == 0) - _eventData_ = managePlayer(_pID, _eventData_); - - // early round eth limiter - if (round_[_rID].eth < 100000000000000000000 && plyrRnds_[_pID][_rID].eth.add(_eth) > 1000000000000000000) - { - uint256 _availableLimit = (1000000000000000000).sub(plyrRnds_[_pID][_rID].eth); - uint256 _refund = _eth.sub(_availableLimit); - plyr_[_pID].gen = plyr_[_pID].gen.add(_refund); - _eth = _availableLimit; - } - - // if eth left is greater than min eth allowed (sorry no pocket lint) - if (_eth > 1000000000) - { - - // mint the new keys - uint256 _keys = (round_[_rID].eth).keysRec(_eth); - - // if they bought at least 1 whole key - if (_keys >= 1000000000000000000) - { - updateTimer(_keys, _rID); - - // set new leaders - if (round_[_rID].plyr != _pID) - round_[_rID].plyr = _pID; - if (round_[_rID].team != _team) - round_[_rID].team = _team; - - // set the new leader bool to true - _eventData_.compressedData = _eventData_.compressedData + 100; - } - - // manage airdrops - if (_eth >= 100000000000000000) - { - airDropTracker_++; - if (airdrop() == true) - { - // gib muni - uint256 _prize; - if (_eth >= 10000000000000000000) - { - // calculate prize and give it to winner - _prize = ((airDropPot_).mul(75)) / 100; - plyr_[_pID].win = (plyr_[_pID].win).add(_prize); - - // adjust airDropPot - airDropPot_ = (airDropPot_).sub(_prize); - - // let event know a tier 3 prize was won - _eventData_.compressedData += 300000000000000000000000000000000; - } else if (_eth >= 1000000000000000000 && _eth < 10000000000000000000) { - // calculate prize and give it to winner - _prize = ((airDropPot_).mul(50)) / 100; - plyr_[_pID].win = (plyr_[_pID].win).add(_prize); - - // adjust airDropPot - airDropPot_ = (airDropPot_).sub(_prize); - - // let event know a tier 2 prize was won - _eventData_.compressedData += 200000000000000000000000000000000; - } else if (_eth >= 100000000000000000 && _eth < 1000000000000000000) { - // calculate prize and give it to winner - _prize = ((airDropPot_).mul(25)) / 100; - plyr_[_pID].win = (plyr_[_pID].win).add(_prize); - - // adjust airDropPot - airDropPot_ = (airDropPot_).sub(_prize); - - // let event know a tier 3 prize was won - _eventData_.compressedData += 300000000000000000000000000000000; - } - // set airdrop happened bool to true - _eventData_.compressedData += 10000000000000000000000000000000; - // let event know how much was won - _eventData_.compressedData += _prize * 1000000000000000000000000000000000; - - // reset air drop tracker - airDropTracker_ = 0; - } - } - - // store the air drop tracker number (number of buys since last airdrop) - _eventData_.compressedData = _eventData_.compressedData + (airDropTracker_ * 1000); - - // update player - plyrRnds_[_pID][_rID].keys = _keys.add(plyrRnds_[_pID][_rID].keys); - plyrRnds_[_pID][_rID].eth = _eth.add(plyrRnds_[_pID][_rID].eth); - - // update round - round_[_rID].keys = _keys.add(round_[_rID].keys); - round_[_rID].eth = _eth.add(round_[_rID].eth); - rndTmEth_[_rID][_team] = _eth.add(rndTmEth_[_rID][_team]); - - // distribute eth - _eventData_ = distributeExternal(_rID, _pID, _eth, _affID, _team, _eventData_); - _eventData_ = distributeInternal(_rID, _pID, _eth, _team, _keys, _eventData_); - - // call end tx function to fire end tx event. - endTx(_pID, _team, _eth, _keys, _eventData_); - } - } - //============================================================================== - // _ _ | _ | _ _|_ _ _ _ . - // (_(_||(_|_||(_| | (_)| _\ . - //============================================================================== - /** - * @dev calculates unmasked earnings (just calculates, does not update mask) - * @return earnings in wei format - */ - function calcUnMaskedEarnings(uint256 _pID, uint256 _rIDlast) - private - view - returns (uint256) - { - return ((((round_[_rIDlast].mask).mul(plyrRnds_[_pID][_rIDlast].keys)) / (1000000000000000000)).sub(plyrRnds_[_pID][_rIDlast].mask)); - } - - /** - * @dev returns the amount of keys you would get given an amount of eth. - * -functionhash- 0xce89c80c - * @param _rID round ID you want price for - * @param _eth amount of eth sent in - * @return keys received - */ - function calcKeysReceived(uint256 _rID, uint256 _eth) - public - view - returns (uint256) - { - // grab time - uint256 _now = block.timestamp; - - // are we in a round? - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - return ((round_[_rID].eth).keysRec(_eth)); - else // rounds over. need keys for new round - return ((_eth).keys()); - } - - /** - * @dev returns current eth price for X keys. - * -functionhash- 0xcf808000 - * @param _keys number of keys desired (in 18 decimal format) - * @return amount of eth needed to send - */ - function iWantXKeys(uint256 _keys) - public - view - returns (uint256) - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = block.timestamp; - - // are we in a round? - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - return ((round_[_rID].keys.add(_keys)).ethRec(_keys)); - else // rounds over. need price for new round - return ((_keys).eth()); - } - //============================================================================== - // _|_ _ _ | _ . - // | (_)(_)|_\ . - //============================================================================== - /** - * @dev receives name/player info from names contract - */ - function receivePlayerInfo(uint256 _pID, address payable _addr, bytes32 _name, uint256 _laff) - external - { - require(msg.sender == address(playerBook), "your not playerNames contract... hmmm.."); - if (pIDxAddr_[_addr] != _pID) - pIDxAddr_[_addr] = _pID; - if (pIDxName_[_name] != _pID) - pIDxName_[_name] = _pID; - if (plyr_[_pID].addr != _addr) - plyr_[_pID].addr = _addr; - if (plyr_[_pID].name != _name) - plyr_[_pID].name = _name; - if (plyr_[_pID].laff != _laff) - plyr_[_pID].laff = _laff; - if (plyrNames_[_pID][_name] == false) - plyrNames_[_pID][_name] = true; - } - - /** - * @dev receives entire player name list - */ - function receivePlayerNameList(uint256 _pID, bytes32 _name) - external - { - require(msg.sender == address(playerBook), "your not playerNames contract... hmmm.."); - if (plyrNames_[_pID][_name] == false) - plyrNames_[_pID][_name] = true; - } - - /** - * @dev gets existing or registers new pID. use this when a player may be new - * @return pID - */ - function determinePID(F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - uint256 _pID = pIDxAddr_[msg.sender]; - // if player is new to this version of fomo3d - if (_pID == 0) - { - // grab their player ID, name and last aff ID, from player names contract - _pID = playerBook.getPlayerID(msg.sender); - bytes32 _name = playerBook.getPlayerName(_pID); - uint256 _laff = playerBook.getPlayerLAff(_pID); - - // set up player account - pIDxAddr_[msg.sender] = _pID; - plyr_[_pID].addr = msg.sender; - - if (_name != "") - { - pIDxName_[_name] = _pID; - plyr_[_pID].name = _name; - plyrNames_[_pID][_name] = true; - } - - if (_laff != 0 && _laff != _pID) - plyr_[_pID].laff = _laff; - - // set the new player bool to true - _eventData_.compressedData = _eventData_.compressedData + 1; - } - return (_eventData_); - } - - /** - * @dev checks to make sure user picked a valid team. if not sets team - * to default (sneks) - */ - function verifyTeam(uint256 _team) - private - pure - returns (uint256) - { - if (_team < 0 || _team > 3) - return (2); - else - return (_team); - } - - /** - * @dev decides if round end needs to be run & new round started. and if - * player unmasked earnings from previously played rounds need to be moved. - */ - function managePlayer(uint256 _pID, F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - // if player has played a previous round, move their unmasked earnings - // from that round to gen vault. - if (plyr_[_pID].lrnd != 0) - updateGenVault(_pID, plyr_[_pID].lrnd); - - // update player's last round played - plyr_[_pID].lrnd = rID_; - - // set the joined round bool to true - _eventData_.compressedData = _eventData_.compressedData + 10; - - return (_eventData_); - } - - /** - * @dev ends the round. manages paying out winner/splitting up pot - */ - function endRound(F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - // setup local rID - uint256 _rID = rID_; - - // grab our winning player and team id's - uint256 _winPID = round_[_rID].plyr; - uint256 _winTID = round_[_rID].team; - - // grab our pot amount - uint256 _pot = round_[_rID].pot; - - // calculate our winner share, community rewards, gen share, - // p3d share, and amount reserved for next pot - uint256 _win = (_pot.mul(48)) / 100; - uint256 _com = (_pot / 50); - uint256 _gen = (_pot.mul(potSplit_[_winTID].gen)) / 100; - uint256 _p3d = (_pot.mul(potSplit_[_winTID].p3d)) / 100; - uint256 _res = (((_pot.sub(_win)).sub(_com)).sub(_gen)).sub(_p3d); - - // calculate ppt for round mask - uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); - uint256 _dust = _gen.sub((_ppt.mul(round_[_rID].keys)) / 1000000000000000000); - if (_dust > 0) - { - _gen = _gen.sub(_dust); - _res = _res.add(_dust); - } - - // pay our winner - plyr_[_winPID].win = _win.add(plyr_[_winPID].win); - - // community rewards - address payable add = address(uint160(Jekyll_Island_Inc)); - if (!add.send(_com)) - { - // This ensures Team Just cannot influence the outcome of FoMo3D with - // bank migrations by breaking outgoing transactions. - // Something we would never do. But that's not the point. - // We spent 2000$ in eth re-deploying just to patch this, we hold the - // highest belief that everything we create should be trustless. - // Team JUST, The name you shouldn't have to trust. - _p3d = _p3d.add(_com); - _com = 0; - } - - // distribute gen portion to key holders - round_[_rID].mask = _ppt.add(round_[_rID].mask); - - // send share for p3d to divies - if (_p3d > 0){ - address payable addr = address(uint160(Divies)); - addr.transfer(_p3d); - } - // prepare event data - _eventData_.compressedData = _eventData_.compressedData + (round_[_rID].end * 1000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + (_winPID * 100000000000000000000000000) + (_winTID * 100000000000000000); - _eventData_.winnerAddr = plyr_[_winPID].addr; - _eventData_.winnerName = plyr_[_winPID].name; - _eventData_.amountWon = _win; - _eventData_.genAmount = _gen; - _eventData_.P3DAmount = _p3d; - _eventData_.newPot = _res; - - // start next round - rID_++; - _rID++; - round_[_rID].strt = block.timestamp; - round_[_rID].end = block.timestamp.add(rndInit_).add(rndGap_); - round_[_rID].pot = _res; - - return (_eventData_); - } - - /** - * @dev moves any unmasked earnings to gen vault. updates earnings mask - */ - function updateGenVault(uint256 _pID, uint256 _rIDlast) - private - { - uint256 _earnings = calcUnMaskedEarnings(_pID, _rIDlast); - if (_earnings > 0) - { - // put in gen vault - plyr_[_pID].gen = _earnings.add(plyr_[_pID].gen); - // zero out their earnings by updating mask - plyrRnds_[_pID][_rIDlast].mask = _earnings.add(plyrRnds_[_pID][_rIDlast].mask); - } - } - - /** - * @dev updates round timer based on number of whole keys bought. - */ - function updateTimer(uint256 _keys, uint256 _rID) - private - { - // grab time - uint256 _now = block.timestamp; - - // calculate time based on number of keys bought - uint256 _newTime; - if (_now > round_[_rID].end && round_[_rID].plyr == 0) - _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(_now); - else - _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(round_[_rID].end); - - // compare to max and set new end time - if (_newTime < (rndMax_).add(_now)) - round_[_rID].end = _newTime; - else - round_[_rID].end = rndMax_.add(_now); - } - - /** - * @dev generates a random number between 0-99 and checks to see if thats - * resulted in an airdrop win - * @return do we have a winner? - */ - function airdrop() - private - view - returns (bool) - { - uint256 seed = uint256(keccak256(abi.encodePacked( - - (block.timestamp).add - (block.difficulty).add - ((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (block.timestamp)).add - (block.gaslimit).add - ((uint256(keccak256(abi.encodePacked(msg.sender)))) / (block.timestamp)).add - (block.number) - - ))); - if ((seed - ((seed / 1000) * 1000)) < airDropTracker_) - return (true); - else - return (false); - } - - /** - * @dev distributes eth based on fees to com, aff, and p3d - */ - function distributeExternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - // pay 2% out to community rewards - uint256 _com = _eth / 50; - uint256 _p3d; - address payable addr = address(uint160(Jekyll_Island_Inc)); - if (!addr.send(_com)) - { - // This ensures Team Just cannot influence the outcome of FoMo3D with - // bank migrations by breaking outgoing transactions. - // Something we would never do. But that's not the point. - // We spent 2000$ in eth re-deploying just to patch this, we hold the - // highest belief that everything we create should be trustless. - // Team JUST, The name you shouldn't have to trust. - _p3d = _com; - _com = 0; - } - - // pay 1% out to FoMo3D short - _com = _eth / 100; - address payable add = address(uint160(otherF3D_)); - add.transfer(_com); - - // distribute share to affiliate - _com = _eth / 10; - - // decide what to do with affiliate share of fees - // affiliate must not be self, and must have a name registered - if (_affID != _pID && plyr_[_affID].name != '') { - plyr_[_affID].aff = _com.add(plyr_[_affID].aff); - emit F3Devents.onAffiliatePayout(_affID, plyr_[_affID].addr, plyr_[_affID].name, _rID, _pID, _com, block.timestamp); - } else { - _p3d = _com; - } - - // pay out p3d - _p3d = _p3d.add((_eth.mul(fees_[_team].p3d)) / (100)); - if (_p3d > 0) - { - // deposit to divies contract - address payable add = address(uint160(Divies)); - add.transfer(_p3d); - - // set up event data - _eventData_.P3DAmount = _p3d.add(_eventData_.P3DAmount); - } - - return (_eventData_); - } - - function potSwap() - external - payable - { - // setup local rID - uint256 _rID = rID_ + 1; - - round_[_rID].pot = round_[_rID].pot.add(msg.value); - emit F3Devents.onPotSwapDeposit(_rID, msg.value); - } - - /** - * @dev distributes eth based on fees to gen and pot - */ - function distributeInternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _team, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns memory) - { - // calculate gen share - uint256 _gen = (_eth.mul(fees_[_team].gen)) / 100; - - // toss 1% into airdrop pot - uint256 _air = (_eth / 100); - airDropPot_ = airDropPot_.add(_air); - - // update eth balance (eth = eth - (com share + pot swap share + aff share + p3d share + airdrop pot share)) - _eth = _eth.sub(((_eth.mul(14)) / 100).add((_eth.mul(fees_[_team].p3d)) / 100)); - - // calculate pot - uint256 _pot = _eth.sub(_gen); - - // distribute gen share (thats what updateMasks() does) and adjust - // balances for dust. - uint256 _dust = updateMasks(_rID, _pID, _gen, _keys); - if (_dust > 0) - _gen = _gen.sub(_dust); - - // add eth to pot - round_[_rID].pot = _pot.add(_dust).add(round_[_rID].pot); - - // set up event data - _eventData_.genAmount = _gen.add(_eventData_.genAmount); - _eventData_.potAmount = _pot; - - return (_eventData_); - } - - /** - * @dev updates masks for round and player when keys are bought - * @return dust left over - */ - function updateMasks(uint256 _rID, uint256 _pID, uint256 _gen, uint256 _keys) - private - returns (uint256) - { - /* MASKING NOTES - earnings masks are a tricky thing for people to wrap their minds around. - the basic thing to understand here. is were going to have a global - tracker based on profit per share for each round, that increases in - relevant proportion to the increase in share supply. - - the player will have an additional mask that basically says "based - on the rounds mask, my shares, and how much i've already withdrawn, - how much is still owed to me?" - */ - - // calc profit per key & round mask based on this buy: (dust goes to pot) - uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); - round_[_rID].mask = _ppt.add(round_[_rID].mask); - - // calculate player earning from their own buy (only based on the keys - // they just bought). & update player earnings mask - uint256 _pearn = (_ppt.mul(_keys)) / (1000000000000000000); - plyrRnds_[_pID][_rID].mask = (((round_[_rID].mask.mul(_keys)) / (1000000000000000000)).sub(_pearn)).add(plyrRnds_[_pID][_rID].mask); - - // calculate & return dust - return (_gen.sub((_ppt.mul(round_[_rID].keys)) / (1000000000000000000))); - } - - /** - * @dev adds up unmasked earnings, & vault earnings, sets them all to 0 - * @return earnings in wei format - */ - function withdrawEarnings(uint256 _pID) - private - returns (uint256) - { - // update gen vault - updateGenVault(_pID, plyr_[_pID].lrnd); - - // from vaults - uint256 _earnings = (plyr_[_pID].win).add(plyr_[_pID].gen).add(plyr_[_pID].aff); - if (_earnings > 0) - { - plyr_[_pID].win = 0; - plyr_[_pID].gen = 0; - plyr_[_pID].aff = 0; - } - - return (_earnings); - } - - /** - * @dev prepares compression data and fires event for buy or reload tx's - */ - function endTx(uint256 _pID, uint256 _team, uint256 _eth, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) - private - { - _eventData_.compressedData = _eventData_.compressedData + (block.timestamp * 1000000000000000000) + (_team * 100000000000000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID + (rID_ * 10000000000000000000000000000000000000000000000000000); - - emit F3Devents.onEndTx - ( - _eventData_.compressedData, - _eventData_.compressedIDs, - plyr_[_pID].name, - msg.sender, - _eth, - _keys, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount, - _eventData_.potAmount, - airDropPot_ - ); - } - //============================================================================== - // (~ _ _ _._|_ . - // _)(/_(_|_|| | | \/ . - //====================/========================================================= - /** upon contract deploy, it will be deactivated. this is a one time - * use function that will activate the contract. we do this so devs - * have time to set things up on the web end **/ - bool public activated_ = false; - - function activate() - public - onlyDevs - { - - // can only be ran once - require(activated_ == false, "fomo3d already activated"); - - // activate the contract - activated_ = true; - - otherF3D_ = msg.sender; - Divies = msg.sender; - Jekyll_Island_Inc = msg.sender; - - // lets start first round - rID_ = 1; - round_[1].strt = block.timestamp + rndExtra_ - rndGap_; - round_[1].end = block.timestamp + rndInit_ + rndExtra_; - } - - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractScenario007.sol b/framework/src/test/resources/soliditycode_0.7.6/contractScenario007.sol deleted file mode 100644 index a6fa095860f..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractScenario007.sol +++ /dev/null @@ -1,1432 +0,0 @@ - -/** - * @title ERC165 - * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md - */ -interface ERC165 { - - /** - * @notice Query if a contract implements an interface - * @param _interfaceId The interface identifier, as specified in ERC-165 - * @dev Interface identification is specified in ERC-165. This function - * uses less than 30,000 gas. - */ - function supportsInterface(bytes4 _interfaceId) external view returns (bool); - -} - -contract ERC721Basic is ERC165 { - - event Transfer( - address indexed _from, - address indexed _to, - uint256 indexed _tokenId - ); - event Approval( - address indexed _owner, - address indexed _approved, - uint256 indexed _tokenId - ); - event ApprovalForAll( - address indexed _owner, - address indexed _operator, - bool _approved - ); - - function balanceOf(address _owner) public view returns (uint256 _balance); - function ownerOf(uint256 _tokenId) public view returns (address _owner); - function exists(uint256 _tokenId) public view returns (bool _exists); - - function approve(address _to, uint256 _tokenId) public; - function getApproved(uint256 _tokenId) - public view returns (address _operator); - - function setApprovalForAll(address _operator, bool _approved) public; - function isApprovedForAll(address _owner, address _operator) - public view returns (bool); - - function transferFrom(address _from, address _to, uint256 _tokenId) public; - function safeTransferFrom(address _from, address _to, uint256 _tokenId) - public; - - function safeTransferFrom( - address _from, - address _to, - uint256 _tokenId, - bytes memory _data - ) - public; -} - - -/** - * @title SupportsInterfaceWithLookup - * @author Matt Condon (@shrugs) - * @dev Implements ERC165 using a lookup table. - */ -contract SupportsInterfaceWithLookup is ERC165 { - bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7; - /** - * 0x01ffc9a7 === - * bytes4(keccak256('supportsInterface(bytes4)')) - */ - - /** - * @dev a mapping of interface id to whether or not it's supported - */ - mapping(bytes4 => bool) internal supportedInterfaces; - - /** - * @dev A contract implementing SupportsInterfaceWithLookup - * implement ERC165 itself - */ - constructor() public { - _registerInterface(InterfaceId_ERC165); - } - - /** - * @dev implement supportsInterface(bytes4) using a lookup table - */ - function supportsInterface(bytes4 _interfaceId) external view returns (bool) { - return supportedInterfaces[_interfaceId]; - } - - /** - * @dev private method for registering an interface - */ - function _registerInterface(bytes4 _interfaceId) internal { - require(_interfaceId != 0xffffffff); - supportedInterfaces[_interfaceId] = true; - } -} - -contract Governable { - - event Pause(); - event Unpause(); - - address public governor; - bool public paused = false; - - constructor() public { - governor = msg.sender; - } - - function setGovernor(address _gov) public onlyGovernor { - governor = _gov; - } - - modifier onlyGovernor { - require(msg.sender == governor); - _; - } - - /** - * @dev Modifier to make a function callable only when the contract is not paused. - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev Modifier to make a function callable only when the contract is paused. - */ - modifier whenPaused() { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyGovernor whenNotPaused public { - paused = true; - emit Pause(); - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyGovernor whenPaused public { - paused = false; - emit Unpause(); - } - -} - -contract CardBase is Governable { - - struct Card { - uint16 proto; - uint16 purity; - } - - function getCard(uint id) public view returns (uint16 proto, uint16 purity) { - Card memory card = cards[id]; - return (card.proto, card.purity); - } - - function getShine(uint16 purity) public pure returns (uint8) { - return uint8(purity / 1000); - } - - Card[] public cards; - -} - -contract CardProto is CardBase { - - event NewProtoCard( - uint16 id, uint8 season, uint8 god, - Rarity rarity, uint8 mana, uint8 attack, - uint8 health, uint8 cardType, uint8 tribe, bool packable - ); - - struct Limit { - uint64 limit; - bool exists; - } - - // limits for mythic cards - mapping(uint16 => Limit) public limits; - - // can only set limits once - function setLimit(uint16 id, uint64 limit) public onlyGovernor { - Limit memory l = limits[id]; - require(!l.exists); - limits[id] = Limit({ - limit: limit, - exists: true - }); - } - - function getLimit(uint16 id) public view returns (uint64 limit, bool set) { - Limit memory l = limits[id]; - return (l.limit, l.exists); - } - - // could make these arrays to save gas - // not really necessary - will be update a very limited no of times - mapping(uint8 => bool) public seasonTradable; - mapping(uint8 => bool) public seasonTradabilityLocked; - uint8 public currentSeason; - - function makeTradable(uint8 season) public onlyGovernor { - seasonTradable[season] = true; - } - - function makeUntradable(uint8 season) public onlyGovernor { - require(!seasonTradabilityLocked[season]); - seasonTradable[season] = false; - } - - function makePermanantlyTradable(uint8 season) public onlyGovernor { - require(seasonTradable[season]); - seasonTradabilityLocked[season] = true; - } - - function isTradable(uint16 proto) public view returns (bool) { - return seasonTradable[protos[proto].season]; - } - - function nextSeason() public onlyGovernor { - //Seasons shouldn't go to 0 if there is more than the uint8 should hold, the governor should know this ¯\_(ツ)_/¯ -M - require(currentSeason <= 255); - - currentSeason++; - mythic.length = 0; - legendary.length = 0; - epic.length = 0; - rare.length = 0; - common.length = 0; - } - - enum Rarity { - Common, - Rare, - Epic, - Legendary, - Mythic - } - - uint8 constant SPELL = 1; - uint8 constant MINION = 2; - uint8 constant WEAPON = 3; - uint8 constant HERO = 4; - - struct ProtoCard { - bool exists; - uint8 god; - uint8 season; - uint8 cardType; - Rarity rarity; - uint8 mana; - uint8 attack; - uint8 health; - uint8 tribe; - } - - // there is a particular design decision driving this: - // need to be able to iterate over mythics only for card generation - // don't store 5 different arrays: have to use 2 ids - // better to bear this cost (2 bytes per proto card) - // rather than 1 byte per instance - - uint16 public protoCount; - - mapping(uint16 => ProtoCard) protos; - - uint16[] public mythic; - uint16[] public legendary; - uint16[] public epic; - uint16[] public rare; - uint16[] public common; - - function addProtos( - uint16[] memory externalIDs, uint8[] memory gods, Rarity[] memory rarities, uint8[] memory manas, uint8[] memory attacks, - uint8[] memory healths, uint8[] memory cardTypes, uint8[] memory tribes, bool[] memory packable - ) public onlyGovernor returns(uint16) { - - for (uint i = 0; i < externalIDs.length; i++) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: gods[i], - season: currentSeason, - cardType: cardTypes[i], - rarity: rarities[i], - mana: manas[i], - attack: attacks[i], - health: healths[i], - tribe: tribes[i] - }); - - _addProto(externalIDs[i], card, packable[i]); - } - - } - - function addProto( - uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 cardType, uint8 tribe, bool packable - ) public onlyGovernor returns(uint16) { - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: cardType, - rarity: rarity, - mana: mana, - attack: attack, - health: health, - tribe: tribe - }); - - _addProto(externalID, card, packable); - } - - function addWeapon( - uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 durability, bool packable - ) public onlyGovernor returns(uint16) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: WEAPON, - rarity: rarity, - mana: mana, - attack: attack, - health: durability, - tribe: 0 - }); - - _addProto(externalID, card, packable); - } - - function addSpell(uint16 externalID, uint8 god, Rarity rarity, uint8 mana, bool packable) public onlyGovernor returns(uint16) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: SPELL, - rarity: rarity, - mana: mana, - attack: 0, - health: 0, - tribe: 0 - }); - - _addProto(externalID, card, packable); - } - - function addMinion( - uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 tribe, bool packable - ) public onlyGovernor returns(uint16) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: MINION, - rarity: rarity, - mana: mana, - attack: attack, - health: health, - tribe: tribe - }); - - _addProto(externalID, card, packable); - } - - function _addProto(uint16 externalID, ProtoCard memory card, bool packable) internal { - - require(!protos[externalID].exists); - - card.exists = true; - - protos[externalID] = card; - - protoCount++; - - emit NewProtoCard( - externalID, currentSeason, card.god, - card.rarity, card.mana, card.attack, - card.health, card.cardType, card.tribe, packable - ); - - if (packable) { - Rarity rarity = card.rarity; - if (rarity == Rarity.Common) { - common.push(externalID); - } else if (rarity == Rarity.Rare) { - rare.push(externalID); - } else if (rarity == Rarity.Epic) { - epic.push(externalID); - } else if (rarity == Rarity.Legendary) { - legendary.push(externalID); - } else if (rarity == Rarity.Mythic) { - mythic.push(externalID); - } else { - require(false); - } - } - } - - function getProto(uint16 id) public view returns( - bool exists, uint8 god, uint8 season, uint8 cardType, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 tribe - ) { - ProtoCard memory proto = protos[id]; - return ( - proto.exists, - proto.god, - proto.season, - proto.cardType, - proto.rarity, - proto.mana, - proto.attack, - proto.health, - proto.tribe - ); - } - - function getRandomCard(Rarity rarity, uint16 random) public view returns (uint16) { - // modulo bias is fine - creates rarity tiers etc - // will obviously revert is there are no cards of that type: this is expected - should never happen - if (rarity == Rarity.Common) { - return common[random % common.length]; - } else if (rarity == Rarity.Rare) { - return rare[random % rare.length]; - } else if (rarity == Rarity.Epic) { - return epic[random % epic.length]; - } else if (rarity == Rarity.Legendary) { - return legendary[random % legendary.length]; - } else if (rarity == Rarity.Mythic) { - // make sure a mythic is available - uint16 id; - uint64 limit; - bool set; - for (uint i = 0; i < mythic.length; i++) { - id = mythic[(random + i) % mythic.length]; - (limit, set) = getLimit(id); - if (set && limit > 0){ - return id; - } - } - // if not, they get a legendary :( - return legendary[random % legendary.length]; - } - require(false); - return 0; - } - - // can never adjust tradable cards - // each season gets a 'balancing beta' - // totally immutable: season, rarity - function replaceProto( - uint16 index, uint8 god, uint8 cardType, uint8 mana, uint8 attack, uint8 health, uint8 tribe - ) public onlyGovernor { - ProtoCard memory pc = protos[index]; - require(!seasonTradable[pc.season]); - protos[index] = ProtoCard({ - exists: true, - god: god, - season: pc.season, - cardType: cardType, - rarity: pc.rarity, - mana: mana, - attack: attack, - health: health, - tribe: tribe - }); - } - -} - -contract ERC721Receiver { - /** - * @dev Magic value to be returned upon successful reception of an NFT - * Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`, - * which can be also obtained as `ERC721Receiver(0).onERC721Received.selector` - */ - bytes4 internal constant ERC721_RECEIVED = 0x150b7a02; - - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a `safetransfer`. This function MAY throw to revert and reject the - * transfer. Return of other than the magic value MUST result in the - * transaction being reverted. - * Note: the contract address is always the message sender. - * @param _operator The address which called `safeTransferFrom` function - * @param _from The address which previously owned the token - * @param _tokenId The NFT identifier which is being transfered - * @param _data Additional data with no specified format - * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - */ - function onERC721Received( - address _operator, - address _from, - uint256 _tokenId, - bytes memory _data - ) - public - returns(bytes4); -} - -library AddressUtils { - - /** - * Returns whether the target address is a contract - * @dev This function will return false if invoked during the constructor of a contract, - * as the code is not actually created until after the constructor finishes. - * @param addr address to check - * @return whether the target address is a contract - */ - function isContract1(address addr) internal view returns (bool) { - uint256 size; - // XXX Currently there is no better way to check if there is a contract in an address - // than to check the size of the code at that address. - // See https://ethereum.stackexchange.com/a/14016/36603 - // for more details about how this works. - // TODO Check this again before the Serenity release, because all addresses will be - // contracts then. - // solium-disable-next-line security/no-inline-assembly - assembly { size := extcodesize(addr) } - return size > 0; - } - -} - -library SafeMath { - - /** - * @dev Multiplies two numbers, throws on overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { - // Gas optimization: this is cheaper than asserting 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - c = a * b; - assert(c / a == b); - return c; - } - - /** - * @dev Integer division of two numbers, truncating the quotient. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // assert(b > 0); // Solidity automatically throws when dividing by 0 - // uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - return a / b; - } - - /** - * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - assert(b <= a); - return a - b; - } - - /** - * @dev Adds two numbers, throws on overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256 c) { - c = a + b; - assert(c >= a); - return c; - } -} - -contract ERC721BasicToken is CardProto, SupportsInterfaceWithLookup, ERC721Basic { - - bytes4 private constant InterfaceId_ERC721 = 0x80ac58cd; - /* - * 0x80ac58cd === - * bytes4(keccak256('balanceOf(address)')) ^ - * bytes4(keccak256('ownerOf(uint256)')) ^ - * bytes4(keccak256('approve(address,uint256)')) ^ - * bytes4(keccak256('getApproved(uint256)')) ^ - * bytes4(keccak256('setApprovalForAll(address,bool)')) ^ - * bytes4(keccak256('isApprovedForAll(address,address)')) ^ - * bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^ - * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) - */ - - bytes4 private constant InterfaceId_ERC721Exists = 0x4f558e79; - /* - * 0x4f558e79 === - * bytes4(keccak256('exists(uint256)')) - */ - - using SafeMath for uint256; - using AddressUtils for address; - - // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - // which can be also obtained as `ERC721Receiver(0).onERC721Received.selector` - bytes4 private constant ERC721_RECEIVED = 0x150b7a02; - - // Mapping from token ID to owner - mapping (uint256 => address) internal tokenOwner; - - // Mapping from token ID to approved address - mapping (uint256 => address) internal tokenApprovals; - - // Mapping from owner to number of owned token - // mapping (address => uint256) internal ownedTokensCount; - - // Mapping from owner to operator approvals - mapping (address => mapping (address => bool)) internal operatorApprovals; - - /** - * @dev Guarantees msg.sender is owner of the given token - * @param _tokenId uint256 ID of the token to validate its ownership belongs to msg.sender - */ - modifier onlyOwnerOf(uint256 _tokenId) { - require(ownerOf(_tokenId) == msg.sender); - _; - } - - /** - * @dev Checks msg.sender can transfer a token, by being owner, approved, or operator - * @param _tokenId uint256 ID of the token to validate - */ - modifier canTransfer(uint256 _tokenId) { - require(isApprovedOrOwner(msg.sender, _tokenId)); - _; - } - - constructor() - public - { - // register the supported interfaces to conform to ERC721 via ERC165 - _registerInterface(InterfaceId_ERC721); - _registerInterface(InterfaceId_ERC721Exists); - } - - /** - * @dev Gets the balance of the specified address - * @param _owner address to query the balance of - * @return uint256 representing the amount owned by the passed address - */ - function balanceOf(address _owner) public view returns (uint256); - - /** - * @dev Gets the owner of the specified token ID - * @param _tokenId uint256 ID of the token to query the owner of - * @return owner address currently marked as the owner of the given token ID - */ - function ownerOf(uint256 _tokenId) public view returns (address) { - address owner = tokenOwner[_tokenId]; - require(owner != address(0)); - return owner; - } - - /** - * @dev Returns whether the specified token exists - * @param _tokenId uint256 ID of the token to query the existence of - * @return whether the token exists - */ - function exists(uint256 _tokenId) public view returns (bool) { - address owner = tokenOwner[_tokenId]; - return owner != address(0); - } - - /** - * @dev Approves another address to transfer the given token ID - * The zero address indicates there is no approved address. - * There can only be one approved address per token at a given time. - * Can only be called by the token owner or an approved operator. - * @param _to address to be approved for the given token ID - * @param _tokenId uint256 ID of the token to be approved - */ - function approve(address _to, uint256 _tokenId) public { - address owner = ownerOf(_tokenId); - require(_to != owner); - require(msg.sender == owner || isApprovedForAll(owner, msg.sender)); - - tokenApprovals[_tokenId] = _to; - emit Approval(owner, _to, _tokenId); - } - - /** - * @dev Gets the approved address for a token ID, or zero if no address set - * @param _tokenId uint256 ID of the token to query the approval of - * @return address currently approved for the given token ID - */ - function getApproved(uint256 _tokenId) public view returns (address) { - return tokenApprovals[_tokenId]; - } - - /** - * @dev Sets or unsets the approval of a given operator - * An operator is allowed to transfer all tokens of the sender on their behalf - * @param _to operator address to set the approval - * @param _approved representing the status of the approval to be set - */ - function setApprovalForAll(address _to, bool _approved) public { - require(_to != msg.sender); - operatorApprovals[msg.sender][_to] = _approved; - emit ApprovalForAll(msg.sender, _to, _approved); - } - - /** - * @dev Tells whether an operator is approved by a given owner - * @param _owner owner address which you want to query the approval of - * @param _operator operator address which you want to query the approval of - * @return bool whether the given operator is approved by the given owner - */ - function isApprovedForAll( - address _owner, - address _operator - ) - public - view - returns (bool) - { - return operatorApprovals[_owner][_operator]; - } - - /** - * @dev Transfers the ownership of a given token ID to another address - * Usage of this method is discouraged, use `safeTransferFrom` whenever possible - * Requires the msg sender to be the owner, approved, or operator - * @param _from current owner of the token - * @param _to address to receive the ownership of the given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - public - canTransfer(_tokenId) - { - require(_from != address(0)); - require(_to != address(0)); - - clearApproval(_from, _tokenId); - removeTokenFrom(_from, _tokenId); - addTokenTo(_to, _tokenId); - - emit Transfer(_from, _to, _tokenId); - } - - /** - * @dev Safely transfers the ownership of a given token ID to another address - * If the target address is a contract, it must implement `onERC721Received`, - * which is called upon a safe transfer, and return the magic value - * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, - * the transfer is reverted. - * - * Requires the msg sender to be the owner, approved, or operator - * @param _from current owner of the token - * @param _to address to receive the ownership of the given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function safeTransferFrom( - address _from, - address _to, - uint256 _tokenId - ) - public - canTransfer(_tokenId) - { - // solium-disable-next-line arg-overflow - safeTransferFrom(_from, _to, _tokenId, ""); - } - - /** - * @dev Safely transfers the ownership of a given token ID to another address - * If the target address is a contract, it must implement `onERC721Received`, - * which is called upon a safe transfer, and return the magic value - * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, - * the transfer is reverted. - * Requires the msg sender to be the owner, approved, or operator - * @param _from current owner of the token - * @param _to address to receive the ownership of the given token ID - * @param _tokenId uint256 ID of the token to be transferred - * @param _data bytes data to send along with a safe transfer check - */ - function safeTransferFrom( - address _from, - address _to, - uint256 _tokenId, - bytes memory _data - ) - public - canTransfer(_tokenId) - { - transferFrom(_from, _to, _tokenId); - // solium-disable-next-line arg-overflow - require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data)); - } - - /** - * @dev Returns whether the given spender can transfer a given token ID - * @param _spender address of the spender to query - * @param _tokenId uint256 ID of the token to be transferred - * @return bool whether the msg.sender is approved for the given token ID, - * is an operator of the owner, or is the owner of the token - */ - function isApprovedOrOwner( - address _spender, - uint256 _tokenId - ) - internal - view - returns (bool) - { - address owner = ownerOf(_tokenId); - // Disable solium check because of - // https://github.com/duaraghav8/Solium/issues/175 - // solium-disable-next-line operator-whitespace - return ( - _spender == owner || - getApproved(_tokenId) == _spender || - isApprovedForAll(owner, _spender) - ); - } - - /** - * @dev Internal function to clear current approval of a given token ID - * Reverts if the given address is not indeed the owner of the token - * @param _owner owner of the token - * @param _tokenId uint256 ID of the token to be transferred - */ - function clearApproval(address _owner, uint256 _tokenId) internal { - require(ownerOf(_tokenId) == _owner); - if (tokenApprovals[_tokenId] != address(0)) { - tokenApprovals[_tokenId] = address(0); - } - } - - /** - * @dev Internal function to mint a new token - * Reverts if the given token ID already exists - * @param _to The address that will own the minted token - * @param _tokenId uint256 ID of the token to be minted by the msg.sender - */ - function _mint(address _to, uint256 _tokenId) internal { - require(_to != address(0)); - addNewTokenTo(_to, _tokenId); - emit Transfer(address(0), _to, _tokenId); - } - - - /** - * @dev Internal function to burn a specific token - * Reverts if the token does not exist - * @param _tokenId uint256 ID of the token being burned by the msg.sender - */ - function _burn(address _owner, uint256 _tokenId) internal { - clearApproval(_owner, _tokenId); - removeTokenFrom(_owner, _tokenId); - emit Transfer(_owner, address(0), _tokenId); - } - - function addNewTokenTo(address _to, uint256 _tokenId) internal { - require(tokenOwner[_tokenId] == address(0)); - tokenOwner[_tokenId] = _to; - } - - /** - * @dev Internal function to add a token ID to the list of a given address - * @param _to address representing the new owner of the given token ID - * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address - */ - function addTokenTo(address _to, uint256 _tokenId) internal { - require(tokenOwner[_tokenId] == address(0)); - tokenOwner[_tokenId] = _to; - // ownedTokensCount[_to] = ownedTokensCount[_to].add(1); - } - - /** - * @dev Internal function to remove a token ID from the list of a given address - * @param _from address representing the previous owner of the given token ID - * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address - */ - function removeTokenFrom(address _from, uint256 _tokenId) internal { - require(ownerOf(_tokenId) == _from); - // ownedTokensCount[_from] = ownedTokensCount[_from].sub(1); - tokenOwner[_tokenId] = address(0); - } - - /** - * @dev Internal function to invoke `onERC721Received` on a target address - * The call is not executed if the target address is not a contract - * @param _from address representing the previous owner of the given token ID - * @param _to target address that will receive the tokens - * @param _tokenId uint256 ID of the token to be transferred - * @param _data bytes optional data to send along with the call - * @return whether the call correctly returned the expected magic value - */ - function checkAndCallSafeTransfer( - address _from, - address _to, - uint256 _tokenId, - bytes memory _data - ) - internal - returns (bool) - { - if (!_to.isContract1()) { - return true; - } - bytes4 retval = ERC721Receiver(_to).onERC721Received( - msg.sender, _from, _tokenId, _data); - return (retval == ERC721_RECEIVED); - } - -} - - - -contract ERC721Enumerable is ERC721Basic { - function totalSupply() public view returns (uint256); - function tokenOfOwnerByIndex( - address _owner, - uint256 _index - ) - public - view - returns (uint256 _tokenId); - - function tokenByIndex(uint256 _index) public view returns (uint256); -} - -contract ERC721Metadata is ERC721Basic { - function name() external view returns (string memory _name); - function symbol() external view returns (string memory _symbol); - function tokenURI(uint256 _tokenId) public view returns (string memory); -} - -contract ERC721 is ERC721Basic, ERC721Enumerable, ERC721Metadata { - -} - - - - -library Strings { - - // via https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol - function strConcat(string memory _a, string memory _b, string memory _c, string memory _d, string memory _e) internal pure returns (string memory ) { - bytes memory _ba = bytes(_a); - bytes memory _bb = bytes(_b); - bytes memory _bc = bytes(_c); - bytes memory _bd = bytes(_d); - bytes memory _be = bytes(_e); - string memory abcde = new string(_ba.length + _bb.length + _bc.length + _bd.length + _be.length); - bytes memory babcde = bytes(abcde); - uint k = 0; - for (uint i = 0; i < _ba.length; i++) babcde[k++] = _ba[i]; - for (uint i = 0; i < _bb.length; i++) babcde[k++] = _bb[i]; - for (uint i = 0; i < _bc.length; i++) babcde[k++] = _bc[i]; - for (uint i = 0; i < _bd.length; i++) babcde[k++] = _bd[i]; - for (uint i = 0; i < _be.length; i++) babcde[k++] = _be[i]; - return string(babcde); - } - - function strConcat(string memory _a, string memory _b, string memory _c, string memory _d) internal pure returns (string memory ) { - return strConcat(_a, _b, _c, _d, ""); - } - - function strConcat(string memory _a, string memory _b, string memory _c) internal pure returns (string memory ) { - return strConcat(_a, _b, _c, "", ""); - } - - function strConcat(string memory _a, string memory _b) internal pure returns (string memory ) { - return strConcat(_a, _b, "", "", ""); - } - - function uint2str(uint i) internal pure returns (string memory ) { - if (i == 0) return "0"; - uint j = i; - uint len; - while (j != 0){ - len++; - j /= 10; - } - bytes memory bstr = new bytes(len); - uint k = len - 1; - while (i != 0){ - bstr[k--] = byte(uint8(48 + i % 10)); - i /= 10; - } - return string(bstr); - } -} - -contract ERC721Token is SupportsInterfaceWithLookup, ERC721BasicToken, ERC721 { - - using Strings for string; - - bytes4 private constant InterfaceId_ERC721Enumerable = 0x780e9d63; - /** - * 0x780e9d63 === - * bytes4(keccak256('totalSupply()')) ^ - * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ - * bytes4(keccak256('tokenByIndex(uint256)')) - */ - - bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f; - /** - * 0x5b5e139f === - * bytes4(keccak256('name()')) ^ - * bytes4(keccak256('symbol()')) ^ - * bytes4(keccak256('tokenURI(uint256)')) - */ - - /*** Constants ***/ - // Configure these for your own deployment - string public constant NAME = "Gods Unchained"; - string public constant SYMBOL = "GODS"; - string public tokenMetadataBaseURI = "https://api.godsunchained.com/card/"; - - // Mapping from owner to list of owned token IDs - // EDITED: limit to 2^40 (around 1T) - mapping(address => uint40[]) internal ownedTokens; - - uint32[] ownedTokensIndex; - - /** - * @dev Constructor function - */ - constructor() public { - - // register the supported interfaces to conform to ERC721 via ERC165 - _registerInterface(InterfaceId_ERC721Enumerable); - _registerInterface(InterfaceId_ERC721Metadata); - } - - /** - * @dev Gets the token name - * @return string representing the token name - */ - function name() external view returns (string memory) { - return NAME; - } - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory) { - return SYMBOL; - } - - /** - * @dev Returns an URI for a given token ID - * Throws if the token ID does not exist. May return an empty string. - * @param _tokenId uint256 ID of the token to query - */ - function tokenURI(uint256 _tokenId) public view returns (string memory) { - return Strings.strConcat( - tokenMetadataBaseURI, - Strings.uint2str(_tokenId) - ); - } - - /** - * @dev Gets the token ID at a given index of the tokens list of the requested owner - * @param _owner address owning the tokens list to be accessed - * @param _index uint256 representing the index to be accessed of the requested tokens list - * @return uint256 token ID at the given index of the tokens list owned by the requested address - */ - function tokenOfOwnerByIndex( - address _owner, - uint256 _index - ) - public - view - returns (uint256) - { - require(_index < balanceOf(_owner)); - return ownedTokens[_owner][_index]; - } - - /** - * @dev Gets the total amount of tokens stored by the contract - * @return uint256 representing the total amount of tokens - */ - function totalSupply() public view returns (uint256) { - return cards.length; - } - - /** - * @dev Gets the token ID at a given index of all the tokens in this contract - * Reverts if the index is greater or equal to the total number of tokens - * @param _index uint256 representing the index to be accessed of the tokens list - * @return uint256 token ID at the given index of the tokens list - */ - function tokenByIndex(uint256 _index) public view returns (uint256) { - require(_index < totalSupply()); - return _index; - } - - /** - * @dev Internal function to add a token ID to the list of a given address - * @param _to address representing the new owner of the given token ID - * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address - */ - function addTokenTo(address _to, uint256 _tokenId) internal { - super.addTokenTo(_to, _tokenId); - uint256 length = ownedTokens[_to].length; - // EDITED: prevent overflow - require(length == uint32(length)); - ownedTokens[_to].push(uint40(_tokenId)); - - ownedTokensIndex[_tokenId] = uint32(length); - } - - // EDITED - // have to have in order to use array rather than mapping - function addNewTokenTo(address _to, uint256 _tokenId) internal { - super.addNewTokenTo(_to, _tokenId); - uint256 length = ownedTokens[_to].length; - // EDITED: prevent overflow - require(length == uint32(length)); - ownedTokens[_to].push(uint40(_tokenId)); - ownedTokensIndex.push(uint32(length)); - } - - /** - * @dev Internal function to remove a token ID from the list of a given address - * @param _from address representing the previous owner of the given token ID - * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address - */ - function removeTokenFrom(address _from, uint256 _tokenId) internal { - super.removeTokenFrom(_from, _tokenId); - - uint32 tokenIndex = ownedTokensIndex[_tokenId]; - uint256 lastTokenIndex = ownedTokens[_from].length.sub(1); - uint40 lastToken = ownedTokens[_from][lastTokenIndex]; - - ownedTokens[_from][tokenIndex] = lastToken; - ownedTokens[_from][lastTokenIndex] = 0; - // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to - // be zero. Then we can make sure that we will remove _tokenId from the ownedTokens list since we are first swapping - // the lastToken to the first position, and then dropping the element placed in the last position of the list - - ownedTokens[_from].length--; - ownedTokensIndex[_tokenId] = 0; - ownedTokensIndex[lastToken] = tokenIndex; - } - - /** - * @dev Gets the balance of the specified address - overrriden from previous to save gas - * @param _owner address to query the balance of - * @return uint256 representing the amount owned by the passed address - */ - function balanceOf(address _owner) public view returns (uint256) { - return ownedTokens[_owner].length; - } - -} - -contract CardOwnershipTwo is ERC721Token { - - uint public burnCount; - - function getActiveCards() public view returns (uint) { - return totalSupply() - burnCount; - } - - /** - * @param to : the address to which the card will be transferred - * @param id : the id of the card to be transferred - */ - function transfer(address to, uint id) public payable onlyOwnerOf(id) { - require(isTradable(cards[id].proto)); - require(to != address(0)); - - _transfer(msg.sender, to, id); - } - - function _transfer(address from, address to, uint id) internal { - - clearApproval(from, id); - - removeTokenFrom(from, id); - - addTokenTo(to, id); - - emit Transfer(from, to, id); - } - - /** - * @param to : the address to which the cards will be transferred - * @param ids : the ids of the cards to be transferred - */ - function transferAll(address to, uint[] memory ids) public payable { - for (uint i = 0; i < ids.length; i++) { - transfer(to, ids[i]); - } - } - - /** - * @param proposed : the claimed owner of the cards - * @param ids : the ids of the cards to check - * @return whether proposed owns all of the cards - */ - function ownsAll(address proposed, uint[] memory ids) public view returns (bool) { - require(ids.length > 0); - for (uint i = 0; i < ids.length; i++) { - if (!owns(proposed, ids[i])) { - return false; - } - } - return true; - } - - /** - * @param proposed : the claimed owner of the card - * @param id : the id of the card to check - * @return whether proposed owns the card - */ - function owns(address proposed, uint id) public view returns (bool) { - return ownerOf(id) == proposed; - } - - function burn(uint id) public onlyOwnerOf(id) { - burnCount++; - _burn(msg.sender, id); - } - - /** - * @param ids : the indices of the tokens to burn - */ - function burnAll(uint[] memory ids) public { - for (uint i = 0; i < ids.length; i++){ - burn(ids[i]); - } - } - - /** - * @param to : the address to approve for transfer - * @param id : the index of the card to be approved - */ - function approve(address to, uint id) public { - require(isTradable(cards[id].proto)); - super.approve(to, id); - } - - /** - * @param to : the address to approve for transfer - * @param ids : the indices of the cards to be approved - */ - function approveAll(address to, uint[] memory ids) public { - for (uint i = 0; i < ids.length; i++) { - approve(to, ids[i]); - } - } - - /** - * @param to : the address to which the token should be transferred - * @param id : the index of the token to transfer - */ - function transferFrom(address from, address to, uint id) public { - require(isTradable(cards[id].proto)); - super.transferFrom(from, to, id); - } - - /** - * @param to : the address to which the tokens should be transferred - * @param ids : the indices of the tokens to transfer - */ - function transferAllFrom(address from, address to, uint[] memory ids) public { - for (uint i = 0; i < ids.length; i++) { - transferFrom(from, to, ids[i]); - } - } - - /** - * @return the number of cards which have been burned - */ - function getBurnCount() public view returns (uint) { - return burnCount; - } - -} - -contract CardIntegrationTwo is CardOwnershipTwo { - - address[] public packs; - - event CardCreated(uint indexed id, uint16 proto, uint16 purity, address owner); - - function addPack(address approved) public onlyGovernor { - packs.push(approved); - } - - modifier onlyApprovedPacks { - require(_isApprovedPack()); - _; - } - - function _isApprovedPack() private view returns (bool) { - for (uint i = 0; i < packs.length; i++) { - if (msg.sender == address(packs[i])) { - return true; - } - } - return false; - } - - function createCard(address owner, uint16 proto, uint16 purity) public whenNotPaused onlyApprovedPacks returns (uint) { - ProtoCard memory card = protos[proto]; - require(card.season == currentSeason); - if (card.rarity == Rarity.Mythic) { - uint64 limit; - bool exists; - (limit, exists) = getLimit(proto); - require(!exists || limit > 0); - limits[proto].limit--; - } - return _createCard(owner, proto, purity); - } - - function _createCard(address owner, uint16 proto, uint16 purity) internal returns (uint) { - Card memory card = Card({ - proto: proto, - purity: purity - }); - - uint id = cards.push(card) - 1; - - _mint(owner, id); - - emit CardCreated(id, proto, purity, owner); - - return id; - } - - /*function combineCards(uint[] ids) public whenNotPaused { - require(ids.length == 5); - require(ownsAll(msg.sender, ids)); - Card memory first = cards[ids[0]]; - uint16 proto = first.proto; - uint8 shine = _getShine(first.purity); - require(shine < shineLimit); - uint16 puritySum = first.purity - (shine * 1000); - burn(ids[0]); - for (uint i = 1; i < ids.length; i++) { - Card memory next = cards[ids[i]]; - require(next.proto == proto); - require(_getShine(next.purity) == shine); - puritySum += (next.purity - (shine * 1000)); - burn(ids[i]); - } - uint16 newPurity = uint16(((shine + 1) * 1000) + (puritySum / ids.length)); - _createCard(msg.sender, proto, newPurity); - }*/ - - - // PURITY NOTES - // currently, we only - // however, to protect rarity, you'll never be abl - // this is enforced by the restriction in the create-card function - // no cards above this point can be found in packs - - - -} - -contract PreviousInterface { - - function ownerOf(uint id) public view returns (address); - - function getCard(uint id) public view returns (uint16, uint16); - - function totalSupply() public view returns (uint); - - function burnCount() public view returns (uint); - -} - -contract CardMigration is CardIntegrationTwo { - - constructor(PreviousInterface previous) public { - old = previous; - } - - // use interface to lower deployment cost - PreviousInterface old; - - mapping(uint => bool) public migrated; - - function migrate(uint id) public { - - require(!migrated[id]); - - migrated[id] = true; - - address owner = old.ownerOf(id); - - uint16 proto; - uint16 purity; - - (proto, purity) = old.getCard(id); - - _createCard(owner, proto, purity); - } - - function migrateAll(uint[] memory ids) public { - - for (uint i = 0; i < ids.length; i++){ - migrate(ids[i]); - } - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractScenario008.sol b/framework/src/test/resources/soliditycode_0.7.6/contractScenario008.sol deleted file mode 100644 index 9881507fab7..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractScenario008.sol +++ /dev/null @@ -1,2061 +0,0 @@ - - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() public { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address payable public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address payable _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() virtual public onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer1(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - emit Transfer1(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(block.timestamp), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - kitties.push(_kitty); - uint256 newKittenId = kitties.length - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - emit Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(address(0), _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -abstract contract ERC721 { - // Required methods - function totalSupply() virtual public view returns (uint256 total); - function balanceOf(address _owner) virtual public view returns (uint256 balance); - function ownerOf(uint256 _tokenId) virtual external view returns (address owner); - function approve(address _to, uint256 _tokenId) virtual external; - function transfer(address _to, uint256 _tokenId) virtual external; - function transferFrom(address _from, address _to, uint256 _tokenId) virtual external; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) virtual external view returns (bool); -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is ERC721, KittyBase { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external override view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public override view returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - override - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - override - external - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - emit Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - override - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() override public view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - override - external - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { - string memory outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { - require( address(erc721Metadata) != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - msg.sender.transfer(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, address(saleAuction)); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, address(siringAuction)); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid{value:(msg.value - autoBirthFee)}(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, address(saleAuction)); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - address(uint160(address(this))) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - constructor() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(-1), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - emit ContractUpgrade(_v2Address); - } - -/// @notice No tipping! -/// @dev Reject all Ether from being sent here, unless it's from one of the -/// two auction contracts. (Hopefully, we can prevent user accidents.) -fallback() external payable { -require( -msg.sender == address(saleAuction) || -msg.sender == address(siringAuction) -); -} - -/// @notice Returns all the relevant information about a specific kitty. -/// @param _id The ID of the kitty of interest. -function getKitty(uint256 _id) -external -view -returns ( -bool isGestating, -bool isReady, -uint256 cooldownIndex, -uint256 nextActionAt, -uint256 siringWithId, -uint256 birthTime, -uint256 matronId, -uint256 sireId, -uint256 generation, -uint256 genes -) { -Kitty storage kit = kitties[_id]; - -// if this variable is 0 then it's not gestating -isGestating = (kit.siringWithId != 0); -isReady = (kit.cooldownEndBlock <= block.number); -cooldownIndex = uint256(kit.cooldownIndex); -nextActionAt = uint256(kit.cooldownEndBlock); -siringWithId = uint256(kit.siringWithId); -birthTime = uint256(kit.birthTime); -matronId = uint256(kit.matronId); -sireId = uint256(kit.sireId); -generation = uint256(kit.generation); -genes = kit.genes; -} - -/// @dev Override unpause so it requires all external contract addresses -/// to be set before contract can be unpaused. Also, we can't have -/// newContractAddress set either, because then the contract was upgraded. -/// @notice This is public rather than external so we can call super.unpause -/// without using an expensive CALL. - -function unpause() override public onlyCEO whenPaused { -require(address(saleAuction) != address(0)); -require(address(siringAuction) != address(0)); -require(address(geneScience) != address(0)); -require(newContractAddress == address(0)); - -// Actually unpause the contract. -super.unpause(); -} - -// @dev Allows the CFO to capture the balance available to the contract. -function withdrawBalance() external onlyCFO { -uint256 balance = address(this).balance; -// Subtract all the currently pregnant kittens we have, plus 1 of margin. -uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - -if (balance > subtractFees) { -cfoAddress.transfer(balance - subtractFees); -} -} -} - - - - - - - - - - - - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - -function isGeneScience() public pure returns (bool){ -return true; -} - -/// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor -/// @param genes1 genes of mom -/// @param genes2 genes of sire -/// @return the genes that are supposed to be passed down the child -function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - -return (genes1+genes2+targetBlock)/2; - - -} -} - - - - - - - - - - - - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { -/// @dev Given a token Id, returns a byte array that is supposed to be converted into string. -function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { -if (_tokenId == 1) { -buffer[0] = "Hello World! :D"; -count = 15; -} else if (_tokenId == 2) { -buffer[0] = "I would definitely choose a medi"; -buffer[1] = "um length string."; -count = 49; -} else if (_tokenId == 3) { -buffer[0] = "Lorem ipsum dolor sit amet, mi e"; -buffer[1] = "st accumsan dapibus augue lorem,"; -buffer[2] = " tristique vestibulum id, libero"; -buffer[3] = " suscipit varius sapien aliquam."; -count = 128; -} -} -} - - - - - - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - -// Represents an auction on an NFT -struct Auction { -// Current owner of NFT -address payable seller; -// Price (in wei) at beginning of auction -uint128 startingPrice; -// Price (in wei) at end of auction -uint128 endingPrice; -// Duration (in seconds) of auction -uint64 duration; -// Time when auction started -// NOTE: 0 if this auction has been concluded -uint64 startedAt; -} - -// Reference to contract tracking NFT ownership -ERC721 public nonFungibleContract; - -// Cut owner takes on each auction, measured in basis points (1/100 of a percent). -// Values 0-10,000 map to 0%-100% -uint256 public ownerCut; - -// Map from token ID to their corresponding auction. -mapping (uint256 => Auction) tokenIdToAuction; - -event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); -event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); -event AuctionCancelled(uint256 tokenId); - -/// @dev Returns true if the claimant owns the token. -/// @param _claimant - Address claiming to own the token. -/// @param _tokenId - ID of token whose ownership to verify. -function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { -return (nonFungibleContract.ownerOf(_tokenId) == _claimant); -} - -/// @dev Escrows the NFT, assigning ownership to this contract. -/// Throws if the escrow fails. -/// @param _owner - Current owner address of token to escrow. -/// @param _tokenId - ID of token whose approval to verify. -function _escrow(address _owner, uint256 _tokenId) internal { -// it will throw if transfer fails -nonFungibleContract.transferFrom(_owner, address(this), _tokenId); -} - -/// @dev Transfers an NFT owned by this contract to another address. -/// Returns true if the transfer succeeds. -/// @param _receiver - Address to transfer NFT to. -/// @param _tokenId - ID of token to transfer. -function _transfer(address _receiver, uint256 _tokenId) internal { -// it will throw if transfer fails -nonFungibleContract.transfer(_receiver, _tokenId); -} - -/// @dev Adds an auction to the list of open auctions. Also fires the -/// AuctionCreated event. -/// @param _tokenId The ID of the token to be put on auction. -/// @param _auction Auction to add. -function _addAuction(uint256 _tokenId, Auction memory _auction) internal { -// Require that all auctions have a duration of -// at least one minute. (Keeps our math from getting hairy!) -require(_auction.duration >= 1 minutes); - -tokenIdToAuction[_tokenId] = _auction; - -emit AuctionCreated( -uint256(_tokenId), -uint256(_auction.startingPrice), -uint256(_auction.endingPrice), -uint256(_auction.duration) -); -} - -/// @dev Cancels an auction unconditionally. -function _cancelAuction(uint256 _tokenId, address _seller) internal { -_removeAuction(_tokenId); -_transfer(_seller, _tokenId); -emit AuctionCancelled(_tokenId); -} - -/// @dev Computes the price and transfers winnings. -/// Does NOT transfer ownership of token. -function _bid(uint256 _tokenId, uint256 _bidAmount) -internal -returns (uint256) -{ -// Get a reference to the auction struct -Auction storage auction = tokenIdToAuction[_tokenId]; - -// Explicitly check that this auction is currently live. -// (Because of how Ethereum mappings work, we can't just count -// on the lookup above failing. An invalid _tokenId will just -// return an auction object that is all zeros.) -require(_isOnAuction(auction)); - -// Check that the bid is greater than or equal to the current price -uint256 price = _currentPrice(auction); -require(_bidAmount >= price); - -// Grab a reference to the seller before the auction struct -// gets deleted. -address payable seller = auction.seller; - -// The bid is good! Remove the auction before sending the fees -// to the sender so we can't have a reentrancy attack. -_removeAuction(_tokenId); - -// Transfer proceeds to seller (if there are any!) -if (price > 0) { -// Calculate the auctioneer's cut. -// (NOTE: _computeCut() is guaranteed to return a -// value <= price, so this subtraction can't go negative.) -uint256 auctioneerCut = _computeCut(price); -uint256 sellerProceeds = price - auctioneerCut; - -// NOTE: Doing a transfer() in the middle of a complex -// method like this is generally discouraged because of -// reentrancy attacks and DoS attacks if the seller is -// a contract with an invalid fallback function. We explicitly -// guard against reentrancy attacks by removing the auction -// before calling transfer(), and the only thing the seller -// can DoS is the sale of their own asset! (And if it's an -// accident, they can call cancelAuction(). ) -seller.transfer(sellerProceeds); -} - -// Calculate any excess funds included with the bid. If the excess -// is anything worth worrying about, transfer it back to bidder. -// NOTE: We checked above that the bid amount is greater than or -// equal to the price so this cannot underflow. -uint256 bidExcess = _bidAmount - price; - -// Return the funds. Similar to the previous transfer, this is -// not susceptible to a re-entry attack because the auction is -// removed before any transfers occur. -msg.sender.transfer(bidExcess); - -// Tell the world! -emit AuctionSuccessful(_tokenId, price, msg.sender); - -return price; -} - -/// @dev Removes an auction from the list of open auctions. -/// @param _tokenId - ID of NFT on auction. -function _removeAuction(uint256 _tokenId) internal { -delete tokenIdToAuction[_tokenId]; -} - -/// @dev Returns true if the NFT is on auction. -/// @param _auction - Auction to check. -function _isOnAuction(Auction storage _auction) internal view returns (bool) { -return (_auction.startedAt > 0); -} - -/// @dev Returns current price of an NFT on auction. Broken into two -/// functions (this one, that computes the duration from the auction -/// structure, and the other that does the price computation) so we -/// can easily test that the price computation works correctly. -function _currentPrice(Auction storage _auction) -internal -view -returns (uint256) -{ -uint256 secondsPassed = 0; - -// A bit of insurance against negative values (or wraparound). -// Probably not necessary (since Ethereum guarnatees that the -// now variable doesn't ever go backwards). -if (block.timestamp > _auction.startedAt) { -secondsPassed = block.timestamp - _auction.startedAt; -} - -return _computeCurrentPrice( -_auction.startingPrice, -_auction.endingPrice, -_auction.duration, -secondsPassed -); -} - -/// @dev Computes the current price of an auction. Factored out -/// from _currentPrice so we can run extensive unit tests. -/// When testing, make this function public and turn on -/// `Current price computation` test suite. -function _computeCurrentPrice( -uint256 _startingPrice, -uint256 _endingPrice, -uint256 _duration, -uint256 _secondsPassed -) -internal -pure -returns (uint256) -{ -// NOTE: We don't use SafeMath (or similar) in this function because -// all of our public functions carefully cap the maximum values for -// time (at 64-bits) and currency (at 128-bits). _duration is -// also known to be non-zero (see the require() statement in -// _addAuction()) -if (_secondsPassed >= _duration) { -// We've reached the end of the dynamic pricing portion -// of the auction, just return the end price. -return _endingPrice; -} else { -// Starting price can be higher than ending price (and often is!), so -// this delta can be negative. -int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - -// This multiplication can't overflow, _secondsPassed will easily fit within -// 64-bits, and totalPriceChange will easily fit within 128-bits, their product -// will always fit within 256-bits. -int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - -// currentPriceChange can be negative, but if so, will have a magnitude -// less that _startingPrice. Thus, this result will always end up positive. -int256 currentPrice = int256(_startingPrice) + currentPriceChange; - -return uint256(currentPrice); -} -} - -/// @dev Computes owner's cut of a sale. -/// @param _price - Sale price of NFT. -function _computeCut(uint256 _price) internal view returns (uint256) { -// NOTE: We don't use SafeMath (or similar) in this function because -// all of our entry functions carefully cap the maximum values for -// currency (at 128-bits), and ownerCut <= 10000 (see the require() -// statement in the ClockAuction constructor). The result of this -// function is always guaranteed to be <= _price. -return _price * ownerCut / 10000; -} - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { -event Pause(); -event Unpause(); - -bool public paused = false; - - -/** - * @dev modifier to allow actions only when the contract IS paused - */ -modifier whenNotPaused() { -require(!paused); -_; -} - -/** - * @dev modifier to allow actions only when the contract IS NOT paused - */ -modifier whenPaused { -require(paused); -_; -} - -/** - * @dev called by the owner to pause, triggers stopped state - */ -function pause() onlyOwner whenNotPaused public returns (bool) { -paused = true; -emit Pause(); -return true; -} - -/** - * @dev called by the owner to unpause, returns to normal state - */ -function unpause() onlyOwner whenPaused public returns (bool) { -paused = false; -emit Unpause(); -return true; -} -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - -/// @dev The ERC-165 interface signature for ERC-721. -/// Ref: https://github.com/ethereum/EIPs/issues/165 -/// Ref: https://github.com/ethereum/EIPs/issues/721 -bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - -/// @dev Constructor creates a reference to the NFT ownership contract -/// and verifies the owner cut is in the valid range. -/// @param _nftAddress - address of a deployed contract implementing -/// the Nonfungible Interface. -/// @param _cut - percent cut the owner takes on each auction, must be -/// between 0-10,000. -constructor(address _nftAddress, uint256 _cut) public { -require(_cut <= 10000); -ownerCut = _cut; - -ERC721 candidateContract = ERC721(_nftAddress); -require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); -nonFungibleContract = candidateContract; -} - -/// @dev Remove all Ether from the contract, which is the owner's cuts -/// as well as any Ether sent directly to the contract address. -/// Always transfers to the NFT contract, but can be called either by -/// the owner or the NFT contract. -function withdrawBalance() external { -address payable nftAddress = address(uint160(address(nonFungibleContract))); - -require( -msg.sender == owner || -msg.sender == nftAddress -); -// We are using this boolean method to make sure that even if one fails it will still work -bool res = nftAddress.send(address(this).balance); -} - -/// @dev Creates and begins a new auction. -/// @param _tokenId - ID of token to auction, sender must be owner. -/// @param _startingPrice - Price of item (in wei) at beginning of auction. -/// @param _endingPrice - Price of item (in wei) at end of auction. -/// @param _duration - Length of time to move between starting -/// price and ending price (in seconds). -/// @param _seller - Seller, if not the message sender -function createAuction( -uint256 _tokenId, -uint256 _startingPrice, -uint256 _endingPrice, -uint256 _duration, -address payable _seller -) -virtual -external -whenNotPaused -{ -// Sanity check that no inputs overflow how many bits we've allocated -// to store them in the auction struct. -require(_startingPrice == uint256(uint128(_startingPrice))); -require(_endingPrice == uint256(uint128(_endingPrice))); -require(_duration == uint256(uint64(_duration))); - -require(_owns(msg.sender, _tokenId)); -_escrow(msg.sender, _tokenId); -Auction memory auction = Auction( -_seller, -uint128(_startingPrice), -uint128(_endingPrice), -uint64(_duration), -uint64(block.timestamp) -); -_addAuction(_tokenId, auction); -} - -/// @dev Bids on an open auction, completing the auction and transferring -/// ownership of the NFT if enough Ether is supplied. -/// @param _tokenId - ID of token to bid on. -function bid(uint256 _tokenId) -external -payable -whenNotPaused -virtual -{ -// _bid will throw if the bid or funds transfer fails -_bid(_tokenId, msg.value); -_transfer(msg.sender, _tokenId); -} - -/// @dev Cancels an auction that hasn't been won yet. -/// Returns the NFT to original owner. -/// @notice This is a state-modifying function that can -/// be called while the contract is paused. -/// @param _tokenId - ID of token on auction -function cancelAuction(uint256 _tokenId) -external -{ -Auction storage auction = tokenIdToAuction[_tokenId]; -require(_isOnAuction(auction)); -address seller = auction.seller; -require(msg.sender == seller); -_cancelAuction(_tokenId, seller); -} - -/// @dev Cancels an auction when the contract is paused. -/// Only the owner may do this, and NFTs are returned to -/// the seller. This should only be used in emergencies. -/// @param _tokenId - ID of the NFT on auction to cancel. -function cancelAuctionWhenPaused(uint256 _tokenId) -whenPaused -onlyOwner -external -{ -Auction storage auction = tokenIdToAuction[_tokenId]; -require(_isOnAuction(auction)); -_cancelAuction(_tokenId, auction.seller); -} - -/// @dev Returns auction info for an NFT on auction. -/// @param _tokenId - ID of NFT on auction. -function getAuction(uint256 _tokenId) -external -view -returns -( -address seller, -uint256 startingPrice, -uint256 endingPrice, -uint256 duration, -uint256 startedAt -) { -Auction storage auction = tokenIdToAuction[_tokenId]; -require(_isOnAuction(auction)); -return ( -auction.seller, -auction.startingPrice, -auction.endingPrice, -auction.duration, -auction.startedAt -); -} - -/// @dev Returns the current price of an auction. -/// @param _tokenId - ID of the token price we are checking. -function getCurrentPrice(uint256 _tokenId) -external -view -returns (uint256) -{ -Auction storage auction = tokenIdToAuction[_tokenId]; -require(_isOnAuction(auction)); -return _currentPrice(auction); -} - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - -// @dev Sanity check that allows us to ensure that we are pointing to the -// right auction in our setSiringAuctionAddress() call. -bool public isSiringClockAuction = true; - -// Delegate constructor -constructor(address _nftAddr, uint256 _cut) public -ClockAuction(_nftAddr, _cut) {} - -/// @dev Creates and begins a new auction. Since this function is wrapped, -/// require sender to be KittyCore contract. -/// @param _tokenId - ID of token to auction, sender must be owner. -/// @param _startingPrice - Price of item (in wei) at beginning of auction. -/// @param _endingPrice - Price of item (in wei) at end of auction. -/// @param _duration - Length of auction (in seconds). -/// @param _seller - Seller, if not the message sender -function createAuction( -uint256 _tokenId, -uint256 _startingPrice, -uint256 _endingPrice, -uint256 _duration, -address payable _seller -) -override -external -{ -// Sanity check that no inputs overflow how many bits we've allocated -// to store them in the auction struct. -require(_startingPrice == uint256(uint128(_startingPrice))); -require(_endingPrice == uint256(uint128(_endingPrice))); -require(_duration == uint256(uint64(_duration))); - -require(msg.sender == address(nonFungibleContract)); -_escrow(_seller, _tokenId); -Auction memory auction = Auction( -_seller, -uint128(_startingPrice), -uint128(_endingPrice), -uint64(_duration), -uint64(block.timestamp) -); -_addAuction(_tokenId, auction); -} - -/// @dev Places a bid for siring. Requires the sender -/// is the KittyCore contract because all bid methods -/// should be wrapped. Also returns the kitty to the -/// seller rather than the winner. -function bid(uint256 _tokenId) -external -payable -override -{ -require(msg.sender == address(nonFungibleContract)); -address seller = tokenIdToAuction[_tokenId].seller; -// _bid checks that token ID is valid and will throw if bid fails -_bid(_tokenId, msg.value); -// We transfer the kitty back to the seller, the winner will get -// the offspring -_transfer(seller, _tokenId); -} - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - -// @dev Sanity check that allows us to ensure that we are pointing to the -// right auction in our setSaleAuctionAddress() call. -bool public isSaleClockAuction = true; - -// Tracks last 5 sale price of gen0 kitty sales -uint256 public gen0SaleCount; -uint256[5] public lastGen0SalePrices; - -// Delegate constructor -constructor(address _nftAddr, uint256 _cut) public -ClockAuction(_nftAddr, _cut) {} - -/// @dev Creates and begins a new auction. -/// @param _tokenId - ID of token to auction, sender must be owner. -/// @param _startingPrice - Price of item (in wei) at beginning of auction. -/// @param _endingPrice - Price of item (in wei) at end of auction. -/// @param _duration - Length of auction (in seconds). -/// @param _seller - Seller, if not the message sender -function createAuction( -uint256 _tokenId, -uint256 _startingPrice, -uint256 _endingPrice, -uint256 _duration, -address payable _seller -) -override -external -{ -// Sanity check that no inputs overflow how many bits we've allocated -// to store them in the auction struct. -require(_startingPrice == uint256(uint128(_startingPrice))); -require(_endingPrice == uint256(uint128(_endingPrice))); -require(_duration == uint256(uint64(_duration))); - -require(msg.sender == address(nonFungibleContract)); -_escrow(_seller, _tokenId); -Auction memory auction = Auction( -_seller, -uint128(_startingPrice), -uint128(_endingPrice), -uint64(_duration), -uint64(block.timestamp) -); -_addAuction(_tokenId, auction); -} - -/// @dev Updates lastSalePrice if seller is the nft contract -/// Otherwise, works the same as default bid method. -function bid(uint256 _tokenId) -external -override -payable -{ -// _bid verifies token ID size -address seller = tokenIdToAuction[_tokenId].seller; -uint256 price = _bid(_tokenId, msg.value); -_transfer(msg.sender, _tokenId); - -// If not a gen0 auction, exit -if (seller == address(nonFungibleContract)) { -// Track gen0 sale prices -lastGen0SalePrices[gen0SaleCount % 5] = price; -gen0SaleCount++; -} -} - -function averageGen0SalePrice() external view returns (uint256) { -uint256 sum = 0; -for (uint256 i = 0; i < 5; i++) { -sum += lastGen0SalePrices[i]; -} -return sum / 5; -} - -} - - - - - - - diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractScenario009.sol b/framework/src/test/resources/soliditycode_0.7.6/contractScenario009.sol deleted file mode 100644 index 52fa63e90ac..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractScenario009.sol +++ /dev/null @@ -1,51 +0,0 @@ - - -library Set { - // We define a new struct datatype that will be used to - // hold its data in the calling contract. - struct Data { mapping(uint => bool) flags; } - - // Note that the first parameter is of type "storage - // reference" and thus only its storage address and not - // its contents is passed as part of the call. This is a - // special feature of library functions. It is idiomatic - // to call the first parameter 'self', if the function can - // be seen as a method of that object. - function insert (Data storage self, uint value) public - returns (bool) - { - if (self.flags[value]) - return false; // already there - self.flags[value] = true; - return true; - } - - function remove(Data storage self, uint value) public - returns (bool) - { - if (!self.flags[value]) - return false; // not there - self.flags[value] = false; - return true; - } - - function contains(Data storage self, uint value) public - returns (bool) - { - return self.flags[value]; - } -} - - -contract C { - Set.Data knownValues; - - function register(uint value) public { - // The library functions can be called without a - // specific instance of the library, since the - // "instance" will be the current contract. - if (!Set.insert(knownValues, value)) - revert(); - } - // In this contract, we can also directly access knownValues.flags, if we want. -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractScenario010.sol b/framework/src/test/resources/soliditycode_0.7.6/contractScenario010.sol deleted file mode 100644 index 4e299efecad..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractScenario010.sol +++ /dev/null @@ -1,107 +0,0 @@ - - -contract TRON_ERC721 { - //name - function name() view public returns (string memory name){ - return "Tron ERC721 Token"; - } - //symbol - function symbol() view public returns (string memory symbol){ - return "T721T"; - } - - //totalSupply - - function totalSupply() view public returns (uint256 supply){ - uint256 totalSupply = 1000000000000; - return totalSupply; - } - - mapping(address => uint) private balances; - function balanceOf(address _owner) view public returns (uint balance) - { - return balances[_owner]; - } - - - mapping(uint256 => address) private tokenOwners; - mapping(uint256 => bool) private tokenExists; - function ownerOf(uint256 _tokenId) view public returns (address owner) { - require(tokenExists[_tokenId]); - return tokenOwners[_tokenId]; - } - - - mapping(address => mapping (address => uint256)) allowed; - function approve(address _to, uint256 _tokenId) public{ - require(msg.sender == ownerOf(_tokenId)); - require(msg.sender != _to); - allowed[msg.sender][_to] = _tokenId; - emit Approval(msg.sender, _to, _tokenId); - } - - - function takeOwnership(uint256 _tokenId) public { - require(tokenExists[_tokenId]); - address oldOwner = ownerOf(_tokenId); - address newOwner = msg.sender; - require(newOwner != oldOwner); - require(allowed[oldOwner][newOwner] == _tokenId); - balances[oldOwner] -= 1; - tokenOwners[_tokenId] = newOwner; - balances[newOwner] += 1; - emit Transfer(oldOwner, newOwner, _tokenId); - } - - - mapping(address => mapping(uint256 => uint256)) private ownerTokens; - function removeFromTokenList(address owner, uint256 _tokenId) private { - for(uint256 i = 0;ownerTokens[owner][i] != _tokenId;i++){ - ownerTokens[owner][i] = 0; - } - } - - function transfer(address _to, uint256 _tokenId) public{ - address currentOwner = msg.sender; - address newOwner = _to; - require(tokenExists[_tokenId]); - require(currentOwner == ownerOf(_tokenId)); - require(currentOwner != newOwner); - require(newOwner != address(0)); - address oldOwner =currentOwner; - removeFromTokenList(oldOwner,_tokenId); - balances[oldOwner] -= 1; - tokenOwners[_tokenId] = newOwner; - balances[newOwner] += 1; - emit Transfer(oldOwner, newOwner, _tokenId); - } - - function transferFrom(address _from,address _to, uint256 _tokenId) public{ - address currentOwner = _from; - address newOwner = _to; - require(tokenExists[_tokenId]); - require(currentOwner == ownerOf(_tokenId)); - require(currentOwner != newOwner); - require(newOwner != address(0)); - address oldOwner =currentOwner; - removeFromTokenList(oldOwner,_tokenId); - balances[oldOwner] -= 1; - tokenOwners[_tokenId] = newOwner; - balances[newOwner] += 1; - emit Transfer(oldOwner, newOwner, _tokenId); - } - - - function tokenOfOwnerByIndex(address _owner, uint256 _index) view public returns (uint tokenId){ - return ownerTokens[_owner][_index]; - } - - - mapping(uint256 => string) tokenLinks; - function tokenMetadata(uint256 _tokenId) view public returns (string memory infoUrl) { - return tokenLinks[_tokenId]; - } - // Events - event Transfer(address indexed _from, address indexed _to, uint256 _tokenId); - event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId); -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractScenario011.sol b/framework/src/test/resources/soliditycode_0.7.6/contractScenario011.sol deleted file mode 100644 index 6b213fa0f28..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractScenario011.sol +++ /dev/null @@ -1,2060 +0,0 @@ - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() public { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address payable public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address payable _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() public virtual onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer1(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - emit Transfer1(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(block.timestamp), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - kitties.push(_kitty); - uint256 newKittenId = kitties.length - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - emit Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(address(0), _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -abstract contract ERC721 { - // Required methods - function totalSupply() public virtual view returns (uint256 total); - function balanceOf(address _owner) public virtual view returns (uint256 balance); - function ownerOf(uint256 _tokenId) external virtual view returns (address owner); - function approve(address _to, uint256 _tokenId) external virtual; - function transfer(address _to, uint256 _tokenId) external virtual; - function transferFrom(address _from, address _to, uint256 _tokenId) external virtual; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) external virtual view returns (bool); -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is ERC721, KittyBase { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external override view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public view override returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - override - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - external - override - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - emit Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - external - override - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() public override view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - external - override - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { - string memory outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { - require( address(erc721Metadata) != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2 ; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - msg.sender.transfer(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, address(saleAuction)); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, address(siringAuction)); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid{value : (msg.value - autoBirthFee)}(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10 ; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, address(saleAuction)); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - address(uint160(address(this))) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - constructor() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(-1), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - emit ContractUpgrade(_v2Address); - } - - /// @notice No tipping! - /// @dev Reject all Ether from being sent here, unless it's from one of the - /// two auction contracts. (Hopefully, we can prevent user accidents.) - fallback() external payable { - require( - msg.sender == address(saleAuction) || - msg.sender == address(siringAuction) - ); - } - - /// @notice Returns all the relevant information about a specific kitty. - /// @param _id The ID of the kitty of interest. - function getKitty(uint256 _id) - external - view - returns ( - bool isGestating, - bool isReady, - uint256 cooldownIndex, - uint256 nextActionAt, - uint256 siringWithId, - uint256 birthTime, - uint256 matronId, - uint256 sireId, - uint256 generation, - uint256 genes - ) { - Kitty storage kit = kitties[_id]; - - // if this variable is 0 then it's not gestating - isGestating = (kit.siringWithId != 0); - isReady = (kit.cooldownEndBlock <= block.number); - cooldownIndex = uint256(kit.cooldownIndex); - nextActionAt = uint256(kit.cooldownEndBlock); - siringWithId = uint256(kit.siringWithId); - birthTime = uint256(kit.birthTime); - matronId = uint256(kit.matronId); - sireId = uint256(kit.sireId); - generation = uint256(kit.generation); - genes = kit.genes; - } - - /// @dev Override unpause so it requires all external contract addresses - /// to be set before contract can be unpaused. Also, we can't have - /// newContractAddress set either, because then the contract was upgraded. - /// @notice This is public rather than external so we can call super.unpause - /// without using an expensive CALL. - - function unpause() public override onlyCEO whenPaused { - require(address(saleAuction) != address(0)); - require(address(siringAuction) != address(0)); - require(address(geneScience) != address(0)); - require(newContractAddress == address(0)); - - // Actually unpause the contract. - super.unpause(); - } - - // @dev Allows the CFO to capture the balance available to the contract. - function withdrawBalance() external onlyCFO { - uint256 balance = address(this).balance; - // Subtract all the currently pregnant kittens we have, plus 1 of margin. - uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - - if (balance > subtractFees) { - cfoAddress.transfer(balance - subtractFees); - } - } -} - - - - - - - - - - - - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - - function isGeneScience() public pure returns (bool){ - return true; - } - - /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor - /// @param genes1 genes of mom - /// @param genes2 genes of sire - /// @return the genes that are supposed to be passed down the child - function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - - return (genes1+genes2+targetBlock)/2; - - - } -} - - - - - - - - - - - - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { - /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. - function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { - if (_tokenId == 1) { - buffer[0] = "Hello World! :D"; - count = 15; - } else if (_tokenId == 2) { - buffer[0] = "I would definitely choose a medi"; - buffer[1] = "um length string."; - count = 49; - } else if (_tokenId == 3) { - buffer[0] = "Lorem ipsum dolor sit amet, mi e"; - buffer[1] = "st accumsan dapibus augue lorem,"; - buffer[2] = " tristique vestibulum id, libero"; - buffer[3] = " suscipit varius sapien aliquam."; - count = 128; - } - } -} - - - - - - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - - // Represents an auction on an NFT - struct Auction { - // Current owner of NFT - address payable seller; - // Price (in wei) at beginning of auction - uint128 startingPrice; - // Price (in wei) at end of auction - uint128 endingPrice; - // Duration (in seconds) of auction - uint64 duration; - // Time when auction started - // NOTE: 0 if this auction has been concluded - uint64 startedAt; - } - - // Reference to contract tracking NFT ownership - ERC721 public nonFungibleContract; - - // Cut owner takes on each auction, measured in basis points (1/100 of a percent). - // Values 0-10,000 map to 0%-100% - uint256 public ownerCut; - - // Map from token ID to their corresponding auction. - mapping (uint256 => Auction) tokenIdToAuction; - - event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); - event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); - event AuctionCancelled(uint256 tokenId); - - /// @dev Returns true if the claimant owns the token. - /// @param _claimant - Address claiming to own the token. - /// @param _tokenId - ID of token whose ownership to verify. - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return (nonFungibleContract.ownerOf(_tokenId) == _claimant); - } - - /// @dev Escrows the NFT, assigning ownership to this contract. - /// Throws if the escrow fails. - /// @param _owner - Current owner address of token to escrow. - /// @param _tokenId - ID of token whose approval to verify. - function _escrow(address _owner, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transferFrom(_owner, address(this), _tokenId); - } - - /// @dev Transfers an NFT owned by this contract to another address. - /// Returns true if the transfer succeeds. - /// @param _receiver - Address to transfer NFT to. - /// @param _tokenId - ID of token to transfer. - function _transfer(address _receiver, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transfer(_receiver, _tokenId); - } - - /// @dev Adds an auction to the list of open auctions. Also fires the - /// AuctionCreated event. - /// @param _tokenId The ID of the token to be put on auction. - /// @param _auction Auction to add. - function _addAuction(uint256 _tokenId, Auction memory _auction) internal { - // Require that all auctions have a duration of - // at least one minute. (Keeps our math from getting hairy!) - require(_auction.duration >= 1 minutes); - - tokenIdToAuction[_tokenId] = _auction; - - emit AuctionCreated( - uint256(_tokenId), - uint256(_auction.startingPrice), - uint256(_auction.endingPrice), - uint256(_auction.duration) - ); - } - - /// @dev Cancels an auction unconditionally. - function _cancelAuction(uint256 _tokenId, address _seller) internal { - _removeAuction(_tokenId); - _transfer(_seller, _tokenId); - emit AuctionCancelled(_tokenId); - } - - /// @dev Computes the price and transfers winnings. - /// Does NOT transfer ownership of token. - function _bid(uint256 _tokenId, uint256 _bidAmount) - internal - returns (uint256) - { - // Get a reference to the auction struct - Auction storage auction = tokenIdToAuction[_tokenId]; - - // Explicitly check that this auction is currently live. - // (Because of how Ethereum mappings work, we can't just count - // on the lookup above failing. An invalid _tokenId will just - // return an auction object that is all zeros.) - require(_isOnAuction(auction)); - - // Check that the bid is greater than or equal to the current price - uint256 price = _currentPrice(auction); - require(_bidAmount >= price); - - // Grab a reference to the seller before the auction struct - // gets deleted. - address payable seller = auction.seller; - - // The bid is good! Remove the auction before sending the fees - // to the sender so we can't have a reentrancy attack. - _removeAuction(_tokenId); - - // Transfer proceeds to seller (if there are any!) - if (price > 0) { - // Calculate the auctioneer's cut. - // (NOTE: _computeCut() is guaranteed to return a - // value <= price, so this subtraction can't go negative.) - uint256 auctioneerCut = _computeCut(price); - uint256 sellerProceeds = price - auctioneerCut; - - // NOTE: Doing a transfer() in the middle of a complex - // method like this is generally discouraged because of - // reentrancy attacks and DoS attacks if the seller is - // a contract with an invalid fallback function. We explicitly - // guard against reentrancy attacks by removing the auction - // before calling transfer(), and the only thing the seller - // can DoS is the sale of their own asset! (And if it's an - // accident, they can call cancelAuction(). ) - seller.transfer(sellerProceeds); - } - - // Calculate any excess funds included with the bid. If the excess - // is anything worth worrying about, transfer it back to bidder. - // NOTE: We checked above that the bid amount is greater than or - // equal to the price so this cannot underflow. - uint256 bidExcess = _bidAmount - price; - - // Return the funds. Similar to the previous transfer, this is - // not susceptible to a re-entry attack because the auction is - // removed before any transfers occur. - msg.sender.transfer(bidExcess); - - // Tell the world! - emit AuctionSuccessful(_tokenId, price, msg.sender); - - return price; - } - - /// @dev Removes an auction from the list of open auctions. - /// @param _tokenId - ID of NFT on auction. - function _removeAuction(uint256 _tokenId) internal { - delete tokenIdToAuction[_tokenId]; - } - - /// @dev Returns true if the NFT is on auction. - /// @param _auction - Auction to check. - function _isOnAuction(Auction storage _auction) internal view returns (bool) { - return (_auction.startedAt > 0); - } - - /// @dev Returns current price of an NFT on auction. Broken into two - /// functions (this one, that computes the duration from the auction - /// structure, and the other that does the price computation) so we - /// can easily test that the price computation works correctly. - function _currentPrice(Auction storage _auction) - internal - view - returns (uint256) - { - uint256 secondsPassed = 0; - - // A bit of insurance against negative values (or wraparound). - // Probably not necessary (since Ethereum guarnatees that the - // now variable doesn't ever go backwards). - if (block.timestamp > _auction.startedAt) { - secondsPassed = block.timestamp - _auction.startedAt; - } - - return _computeCurrentPrice( - _auction.startingPrice, - _auction.endingPrice, - _auction.duration, - secondsPassed - ); - } - - /// @dev Computes the current price of an auction. Factored out - /// from _currentPrice so we can run extensive unit tests. - /// When testing, make this function public and turn on - /// `Current price computation` test suite. - function _computeCurrentPrice( - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - uint256 _secondsPassed - ) - internal - pure - returns (uint256) - { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our public functions carefully cap the maximum values for - // time (at 64-bits) and currency (at 128-bits). _duration is - // also known to be non-zero (see the require() statement in - // _addAuction()) - if (_secondsPassed >= _duration) { - // We've reached the end of the dynamic pricing portion - // of the auction, just return the end price. - return _endingPrice; - } else { - // Starting price can be higher than ending price (and often is!), so - // this delta can be negative. - int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - - // This multiplication can't overflow, _secondsPassed will easily fit within - // 64-bits, and totalPriceChange will easily fit within 128-bits, their product - // will always fit within 256-bits. - int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - - // currentPriceChange can be negative, but if so, will have a magnitude - // less that _startingPrice. Thus, this result will always end up positive. - int256 currentPrice = int256(_startingPrice) + currentPriceChange; - - return uint256(currentPrice); - } - } - - /// @dev Computes owner's cut of a sale. - /// @param _price - Sale price of NFT. - function _computeCut(uint256 _price) internal view returns (uint256) { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our entry functions carefully cap the maximum values for - // currency (at 128-bits), and ownerCut <= 10000 (see the require() - // statement in the ClockAuction constructor). The result of this - // function is always guaranteed to be <= _price. - return _price * ownerCut / 10000; - } - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { - event Pause(); - event Unpause(); - - bool public paused = false; - - - /** - * @dev modifier to allow actions only when the contract IS paused - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev modifier to allow actions only when the contract IS NOT paused - */ - modifier whenPaused { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyOwner whenNotPaused public returns (bool) { - paused = true; - emit Pause(); - return true; - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyOwner whenPaused public returns (bool) { - paused = false; - emit Unpause(); - return true; - } -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - - /// @dev The ERC-165 interface signature for ERC-721. - /// Ref: https://github.com/ethereum/EIPs/issues/165 - /// Ref: https://github.com/ethereum/EIPs/issues/721 - bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - - /// @dev Constructor creates a reference to the NFT ownership contract - /// and verifies the owner cut is in the valid range. - /// @param _nftAddress - address of a deployed contract implementing - /// the Nonfungible Interface. - /// @param _cut - percent cut the owner takes on each auction, must be - /// between 0-10,000. - constructor(address _nftAddress, uint256 _cut) public { - require(_cut <= 10000); - ownerCut = _cut; - - ERC721 candidateContract = ERC721(_nftAddress); - require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); - nonFungibleContract = candidateContract; - } - - /// @dev Remove all Ether from the contract, which is the owner's cuts - /// as well as any Ether sent directly to the contract address. - /// Always transfers to the NFT contract, but can be called either by - /// the owner or the NFT contract. - function withdrawBalance() external { - address payable nftAddress = address(uint160(address(nonFungibleContract))); - - require( - msg.sender == owner || - msg.sender == nftAddress - ); - // We are using this boolean method to make sure that even if one fails it will still work - bool res = nftAddress.send(address(this).balance); - } - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of time to move between starting - /// price and ending price (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - virtual - whenNotPaused - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(_owns(msg.sender, _tokenId)); - _escrow(msg.sender, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(block.timestamp) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Bids on an open auction, completing the auction and transferring - /// ownership of the NFT if enough Ether is supplied. - /// @param _tokenId - ID of token to bid on. - function bid(uint256 _tokenId) - external - payable - virtual - whenNotPaused - { - // _bid will throw if the bid or funds transfer fails - _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - } - - /// @dev Cancels an auction that hasn't been won yet. - /// Returns the NFT to original owner. - /// @notice This is a state-modifying function that can - /// be called while the contract is paused. - /// @param _tokenId - ID of token on auction - function cancelAuction(uint256 _tokenId) - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - address seller = auction.seller; - require(msg.sender == seller); - _cancelAuction(_tokenId, seller); - } - - /// @dev Cancels an auction when the contract is paused. - /// Only the owner may do this, and NFTs are returned to - /// the seller. This should only be used in emergencies. - /// @param _tokenId - ID of the NFT on auction to cancel. - function cancelAuctionWhenPaused(uint256 _tokenId) - whenPaused - onlyOwner - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - _cancelAuction(_tokenId, auction.seller); - } - - /// @dev Returns auction info for an NFT on auction. - /// @param _tokenId - ID of NFT on auction. - function getAuction(uint256 _tokenId) - external - view - returns - ( - address seller, - uint256 startingPrice, - uint256 endingPrice, - uint256 duration, - uint256 startedAt - ) { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return ( - auction.seller, - auction.startingPrice, - auction.endingPrice, - auction.duration, - auction.startedAt - ); - } - - /// @dev Returns the current price of an auction. - /// @param _tokenId - ID of the token price we are checking. - function getCurrentPrice(uint256 _tokenId) - external - view - returns (uint256) - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return _currentPrice(auction); - } - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSiringAuctionAddress() call. - bool public isSiringClockAuction = true; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. Since this function is wrapped, - /// require sender to be KittyCore contract. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - override - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(block.timestamp) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Places a bid for siring. Requires the sender - /// is the KittyCore contract because all bid methods - /// should be wrapped. Also returns the kitty to the - /// seller rather than the winner. - function bid(uint256 _tokenId) - external - payable - override - { - require(msg.sender == address(nonFungibleContract)); - address seller = tokenIdToAuction[_tokenId].seller; - // _bid checks that token ID is valid and will throw if bid fails - _bid(_tokenId, msg.value); - // We transfer the kitty back to the seller, the winner will get - // the offspring - _transfer(seller, _tokenId); - } - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSaleAuctionAddress() call. - bool public isSaleClockAuction = true; - - // Tracks last 5 sale price of gen0 kitty sales - uint256 public gen0SaleCount; - uint256[5] public lastGen0SalePrices; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address payable _seller - ) - external - override - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(block.timestamp) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Updates lastSalePrice if seller is the nft contract - /// Otherwise, works the same as default bid method. - function bid(uint256 _tokenId) - external - payable - override - { - // _bid verifies token ID size - address seller = tokenIdToAuction[_tokenId].seller; - uint256 price = _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - - // If not a gen0 auction, exit - if (seller == address(nonFungibleContract)) { - // Track gen0 sale prices - lastGen0SalePrices[gen0SaleCount % 5] = price; - gen0SaleCount++; - } - } - - function averageGen0SalePrice() external view returns (uint256) { - uint256 sum = 0; - for (uint256 i = 0; i < 5; i++) { - sum += lastGen0SalePrices[i]; - } - return sum / 5; - } - -} - - - - - - - diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractScenario012.sol b/framework/src/test/resources/soliditycode_0.7.6/contractScenario012.sol deleted file mode 100644 index 7fea2b1ccf1..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractScenario012.sol +++ /dev/null @@ -1,57 +0,0 @@ - -contract PayTest { - -uint256 public n; -constructor() payable public{ -n = 0; -} - -function nPlusOne() public{ -n = n+1; -} - -//get current contract balance -function getBalance() payable public returns (uint) { -return address(this).balance; -} - -function getSenderBalance() public view returns(address, uint) { -return (msg.sender, msg.sender.balance); -} - -address public user; - -//deposit 1 coin to msg.sender -function depositOneCoin() payable public returns(bool success){ -return msg.sender.send(1); -} - -// function transferOneCoin() payable public returns(){ -// address(msg.sender).transfer(1); -// } - -// function depositOneCoin() payable public returns(address addr, uint amount, bool success){ -// return (msg.sender, msg.value, msg.sender.send(1)); -// } - -//deposit coin to msg.sender -function deposit(uint256 money) payable public returns(bool success){ -return msg.sender.send(money); -} -// function deposit(uint money) payable public returns(address addr, uint amount, bool success){ -// return (msg.sender, msg.value, msg.sender.send(money)); -// } - -// fallback() payable { -// msg.sender.send(1); -// } - -function sendToAddress(address payable _receiver) payable public{ -_receiver.transfer(msg.value); -} - -function sendToAddress2(address payable _receiver) payable public{ -_receiver.transfer(5); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractScenario013.sol b/framework/src/test/resources/soliditycode_0.7.6/contractScenario013.sol deleted file mode 100644 index 93b7905679b..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractScenario013.sol +++ /dev/null @@ -1,8 +0,0 @@ - -contract timetest { - -function time() public{ -require(1 trx == 1000000 sun); - -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractScenario014.sol b/framework/src/test/resources/soliditycode_0.7.6/contractScenario014.sol deleted file mode 100644 index 9f423d1b1ab..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractScenario014.sol +++ /dev/null @@ -1,34 +0,0 @@ - -contract Contract1 { - constructor() public payable{} - function send5SunToReceiver(address payable _receiver) payable public{ - _receiver.transfer(5); - } -} -contract contract2 { - address public payContract; - - constructor(address _add) payable public{ - payContract = _add; - } - - function triggerContract1(address _receiver) payable public{ - payContract.call(abi.encodeWithSignature("send5SunToReceiver(address)",_receiver)); - } - - function triggerContract1ButRevert(address _receiver) payable public{ - payContract.call(abi.encodeWithSignature("send5SunToReceiver(address)",_receiver)); - require(1 == 2); - } - -} -contract contract3 { - address public payContract; - constructor(address _add) payable public{ - payContract = _add; - } - - function triggerContract2(address _receiver) payable public{ - payContract.call(abi.encodeWithSignature("triggerContract1(address)",_receiver)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTest.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTest.sol deleted file mode 100644 index 9a72b4a53b4..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTest.sol +++ /dev/null @@ -1,19 +0,0 @@ - - -contract Test{ - -function a() public returns (uint){ - -uint256 count = 0; - -for (uint256 i = 1; i > 0; i++) { - -count++; - -} - -return count; - -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractToMathedFeed.sol b/framework/src/test/resources/soliditycode_0.7.6/contractToMathedFeed.sol deleted file mode 100644 index d9df9d9c10d..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractToMathedFeed.sol +++ /dev/null @@ -1,21 +0,0 @@ - - -contract ToMathedFeed { - uint public i=1; - function ToMathed (uint value) public { - i=value; - } -} - -contract ToMathedUseINContract { - function ToMathedIUseNR(address a,uint256 n) public returns(bool){ - address payContract=a; - (bool success, bytes memory data) = payContract.call(abi.encodeWithSignature("ToMathedNot(uint256)",n)); - return success; - } - function ToMathedIUseNRE(address a,uint256 value) public returns(bool){ - address payContract=a; - (bool success, bytes memory data) = payContract.call(abi.encodeWithSignature("ToMathed(uint256)",value)); - return success; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTransferToken001.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTransferToken001.sol deleted file mode 100644 index 0edbbfbb44a..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTransferToken001.sol +++ /dev/null @@ -1,22 +0,0 @@ -contract A { - address public a; - constructor() public payable{} - function kill(address payable toAddress) payable public{ - selfdestruct(toAddress); - } - function newB() public payable returns(address){ - B bAddress=new B(); - a= address(bAddress); - return a; - - } - - } - -contract B{ - constructor() public payable {} - fallback() external payable {} - function kill(address payable toAddress) payable public{ - selfdestruct(toAddress); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken001.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken001.sol deleted file mode 100644 index ea28f4a62b6..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken001.sol +++ /dev/null @@ -1,30 +0,0 @@ - - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken002.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken002.sol deleted file mode 100644 index ea28f4a62b6..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken002.sol +++ /dev/null @@ -1,30 +0,0 @@ - - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken003.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken003.sol deleted file mode 100644 index 863429fc4f8..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken003.sol +++ /dev/null @@ -1,16 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken005.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken005.sol deleted file mode 100644 index 863429fc4f8..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken005.sol +++ /dev/null @@ -1,16 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken011.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken011.sol deleted file mode 100644 index 43e4010ec3f..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken011.sol +++ /dev/null @@ -1,35 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - fallback() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken012.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken012.sol deleted file mode 100644 index ab0c19767e7..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken012.sol +++ /dev/null @@ -1,26 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken014.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken014.sol deleted file mode 100644 index 589406c47c6..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken014.sol +++ /dev/null @@ -1,34 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - fallback() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken018.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken018.sol deleted file mode 100644 index ab0c19767e7..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken018.sol +++ /dev/null @@ -1,26 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken023.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken023.sol deleted file mode 100644 index 070acb201ff..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken023.sol +++ /dev/null @@ -1,26 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - toAddress.transferToken(amount,id); - } - } - -contract B{ - uint256 public flag = 0; - constructor() public payable {} - fallback() external { - flag = 1; -} - -} - -contract C{ - uint256 public flag = 0; - constructor() public payable {} - fallback() external payable { - //flag = 1; -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken026.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken026.sol deleted file mode 100644 index 5464265d81f..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken026.sol +++ /dev/null @@ -1,31 +0,0 @@ - - -contract token{ - constructor() payable public{} - fallback() payable external{} - function testInCall(address callBAddress,address callCAddress, address toAddress ,uint256 amount,trcToken id) payable public{ - //callBAddress.call(bytes4(keccak256("transC(address,address,uint256,trcToken)")),callCAddress,toAddress,amount,id); - callBAddress.call(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callCAddress,toAddress,amount,id)); - } - function testIndelegateCall(address callBddress,address callAddressC, address toAddress,uint256 amount, trcToken id) payable public{ - callBddress.delegatecall(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callAddressC,toAddress,amount,id)); - } - } - - - -contract B{ - constructor() public payable{} - fallback() external payable{} - function transC(address payable callCAddress,address payable toAddress,uint256 amount, trcToken id) payable public{ - callCAddress.call(abi.encodeWithSignature("trans(address,uint256,trcToken)",toAddress,amount,id)); - } -} -contract C{ - constructor() payable public{} - fallback() payable external{} - function trans(address payable toAddress,uint256 amount, trcToken id) payable public{ - toAddress.transferToken(amount,id); - } - -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken027.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken027.sol deleted file mode 100644 index e7d6ee768f3..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken027.sol +++ /dev/null @@ -1,30 +0,0 @@ - - -contract token{ - constructor() payable public{} - fallback() payable external{} - function testInCall(address callBAddress,address callCAddress, address toAddress ,uint256 amount,trcToken id) payable public{ - callBAddress.call(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callCAddress,toAddress,amount,id)); - } - function testIndelegateCall(address callBddress,address callAddressC, address toAddress,uint256 amount, trcToken id) payable public{ - callBddress.delegatecall(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callAddressC,toAddress,amount,id)); - } - } - - - -contract B{ - constructor() public payable{} - fallback() external payable{} - function transC(address callCAddress,address toAddress,uint256 amount, trcToken id) payable public{ - callCAddress.call(abi.encodeWithSignature("trans(address,uint256,trcToken)",toAddress,amount,id)); - } -} -contract C{ - constructor() payable public{} - fallback() payable external{} - function trans(address payable toAddress,uint256 amount, trcToken id) payable public{ - toAddress.transferToken(amount,id); - } - -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken028.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken028.sol deleted file mode 100644 index 0f27d89c819..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken028.sol +++ /dev/null @@ -1,25 +0,0 @@ - - -contract token{ - uint256 public a=1; - constructor() public payable{} - function tokenBalanceWithSameName(trcToken id) public payable{ - B b= new B(); - a= b.tokenBalance(id); - } - function getA() public returns(uint256){ - return a; - } -} - - -contract B{ - uint256 public flag =0; - constructor() public payable{} - fallback() external payable{} - function tokenBalance(trcToken id) payable public returns(uint256){ - flag =9; - return flag; - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken029.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken029.sol deleted file mode 100644 index 8480cf6f19d..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken029.sol +++ /dev/null @@ -1,24 +0,0 @@ - - -contract token{ - address public a; - constructor() public payable{} - function transferTokenWithSameName(trcToken id,uint256 amount) public payable{ - B b= new B(); - b.transferToken(amount,id); - a= address(b); - } -} - - -contract B{ - uint256 public flag =0; - constructor() public payable{} - fallback() external payable{} - function transferToken(uint256 amount, trcToken id) payable public returns(bool){ - flag =9; - } - function getFlag() public view returns (uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken030.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken030.sol deleted file mode 100644 index 06b8201979c..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken030.sol +++ /dev/null @@ -1,17 +0,0 @@ - - contract token{ - constructor() public payable{} - - // 4)suicide也会转移token - // 所有token,trx均被转移到toAddress, - // 若toAddress为合约地址本身,则所有token,trx均被烧掉进黑洞 - function kill(address payable toAddress) payable public{ - selfdestruct(toAddress); - } - - } - -contract B{ - constructor() public payable {} - fallback() external payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken031.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken031.sol deleted file mode 100644 index 65ec394e8da..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken031.sol +++ /dev/null @@ -1,18 +0,0 @@ - - - contract token{ - constructor() public payable{} - - // 4)suicide也会转移token - // 所有token,trx均被转移到toAddress, - // 若toAddress为合约地址本身,则所有token,trx均被烧掉进黑洞 - function kill(address payable toAddress) payable public{ - selfdestruct(toAddress); - } - - } - -contract B{ - constructor() public payable {} - fallback() external payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken034.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken034.sol deleted file mode 100644 index 32c55f8c84b..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken034.sol +++ /dev/null @@ -1,25 +0,0 @@ - - - contract token{ - - constructor() public payable {} - - // 2. 异常测试 - // 1)revert, 金额回退 - function failTransferTokenRevert(address payable toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - require(1==2); - } - - // 2)Error, 金额回退, fee limit 扣光 - function failTransferTokenError(address payable toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - assert(1==2); - } - - } - contract B{ - uint256 public flag = 0; - constructor() public payable {} - fallback() external payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken035.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken035.sol deleted file mode 100644 index ca45dde790d..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken035.sol +++ /dev/null @@ -1,24 +0,0 @@ - - - contract token{ - constructor() public payable {} - - // 2. 异常测试 - // 1)revert, 金额回退 - function failTransferTokenRevert(address payable toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - require(1==2); - } - - // 2)Error, 金额回退, fee limit 扣光 - function failTransferTokenError(address payable toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - assert(1==2); - } - - } - contract B{ - uint256 public flag = 0; - constructor() public payable {} - fallback() external payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036.sol deleted file mode 100644 index c1da2f7555e..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036.sol +++ /dev/null @@ -1,52 +0,0 @@ - -contract IllegalDecorate { -constructor() payable public{} -fallback() payable external{} -event log(uint256); -function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public payable { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate1 { -constructor() payable public{} -fallback() payable external{} -event log(uint256); -function transferTokenWithConstant(address payable toAddress, uint256 tokenValue) public payable { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate2 { -constructor() payable public{} -fallback() payable external{} -event log(uint256); -function transferTokenWithView(address payable toAddress, uint256 tokenValue) public payable { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate3 { -event log(uint256); -constructor() payable public{} -fallback() payable external{} -function transferTokenWithOutPayable(address payable toAddress, uint256 tokenValue) public { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_1.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_1.sol deleted file mode 100644 index 327ab5a756e..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_1.sol +++ /dev/null @@ -1,13 +0,0 @@ - -contract IllegalDecorate { -constructor() payable public{} -fallback() payable external{} -event log(uint256); -function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public pure { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_2.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_2.sol deleted file mode 100644 index 817a96e3c80..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_2.sol +++ /dev/null @@ -1,13 +0,0 @@ - -contract IllegalDecorate { -constructor() payable public{} -fallback() payable external{} -event log(uint256); -function transferTokenWithConstant(address toAddress, uint256 tokenValue) public constant { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_3.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_3.sol deleted file mode 100644 index 67400c2e8ad..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_3.sol +++ /dev/null @@ -1,13 +0,0 @@ - -contract IllegalDecorate { -constructor() payable public{} -fallback() payable external{} -event log(uint256); -function transferTokenWithView(address payable toAddress, uint256 tokenValue) public view { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_4.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_4.sol deleted file mode 100644 index cbaca0d4b38..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_4.sol +++ /dev/null @@ -1,13 +0,0 @@ - -contract IllegalDecorate { -event log(uint256); -constructor() payable public{} -fallback() payable external{} -function transferTokenWithOutPayable(address payable toAddress, uint256 tokenValue) public { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_old.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_old.sol deleted file mode 100644 index 1f03afb7636..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken036_old.sol +++ /dev/null @@ -1,41 +0,0 @@ - - - -contract IllegalDecorate1 { -constructor() payable public{} -fallback() payable public{} -event log(uint256); -function transferTokenWithConstant(address toAddress, uint256 tokenValue) public constant { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate2 { -constructor() payable public{} -fallback() payable public{} -event log(uint256); -function transferTokenWithView(address toAddress, uint256 tokenValue) public view { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate3 { -event log(uint256); -constructor() payable public{} -fallback() payable public{} -function transferTokenWithOutPayable(address toAddress, uint256 tokenValue) public { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken037.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken037.sol deleted file mode 100644 index 7cdd91702e8..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken037.sol +++ /dev/null @@ -1,24 +0,0 @@ - - -contract transferTrc10 { - function receive(address payable rec) public payable { - uint256 aamount=address(this).tokenBalance(msg.tokenid); - uint256 bamount=rec.tokenBalance(msg.tokenid); - require(msg.tokenvalue==aamount); - require(aamount==msg.tokenvalue); - rec.transferToken(aamount,msg.tokenid); - require(0==address(this).tokenBalance(msg.tokenid)); - require(bamount+aamount==rec.tokenBalance(msg.tokenid)); - (bool success, bytes memory data) =rec.call(abi.encodeWithSignature("checkTrc10(uint256,trcToken,uint256)",bamount+aamount,msg.tokenid,0)); - require(success); - - } -} - -contract receiveTrc10 { - fallback() external payable {} - function checkTrc10(uint256 amount,trcToken tid,uint256 meamount) public{ - require(amount==address(this).tokenBalance(tid)); - require(meamount==msg.sender.tokenBalance(tid)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken038.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken038.sol deleted file mode 100644 index eeb5ae744cf..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken038.sol +++ /dev/null @@ -1,24 +0,0 @@ - - -contract transferTrc10 { - function receive(address payable rec) public payable { - uint256 aamount=address(this).tokenBalance(msg.tokenid); - uint256 bamount=rec.tokenBalance(msg.tokenid); - require(msg.tokenvalue==aamount); - require(aamount==msg.tokenvalue); - rec.transferToken(aamount,msg.tokenid); - //require(rec.call(abi.encode(bytes4(keccak256("AssertError()"))))); - (bool suc, bytes memory data) = rec.call(abi.encodeWithSignature("AssertError()")); - require(suc); - require(aamount==address(this).tokenBalance(msg.tokenid)); - require(bamount==rec.tokenBalance(msg.tokenid)); - } -} - -contract receiveTrc10 { - fallback() external payable { - } - function AssertError() public{ - assert(1==2); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken039.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken039.sol deleted file mode 100644 index ebf6fb932ed..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken039.sol +++ /dev/null @@ -1,44 +0,0 @@ - -/* - * 1. caller账户issue一个token - * 2. caller部署proxy, 传入1000 token,1000 trx - * 3. caller部署A - * 4. caller部署B - * 5. caller调用proxy中upgradetTo函数,传入A的地址 - * 6. caller调用proxy中不存在的trans(uint256,address,trcToken)函数,注意这时trcToken是无意义的,但也带上tokenid。address是任意另外某账户的地址 - * 7. 可以看到目标地址trx增长5,caller账户trx减少5 - * 8. caller调用proxy中upgradeTo函数,传入B的地址 - * 9. caller调用proxy中不存在的trans(uint256,address,trcToken)函数。 - * 10. 可以看到目标地址token增长5,caller账户token减少5 -*/ -contract Proxy { - constructor() payable public{} - address public implementation; - function upgradeTo(address _address) public { - implementation = _address; - } - fallback() payable external{ - address addr = implementation; - require(addr != address(0)); - assembly { - let freememstart := mload(0x40) - calldatacopy(freememstart, 0, calldatasize()) - let success := delegatecall(not(0), addr, freememstart, calldatasize(), freememstart, 0) - returndatacopy(freememstart, 0, returndatasize()) - switch success - case 0 { revert(freememstart, returndatasize()) } - default { return(freememstart, returndatasize()) } - } - } -} - -contract A { - function trans(uint256 amount, address payable toAddress, trcToken id) payable public { - toAddress.transfer(amount); - } -} -contract B{ - function trans(uint256 amount, address payable toAddress, trcToken id) payable public { - toAddress.transferToken(amount,id); - } -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken041.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken041.sol deleted file mode 100644 index 6284253d1d5..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken041.sol +++ /dev/null @@ -1,20 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } - -contract B{ - uint256 public flag = 0; - constructor() public payable {} - fallback() external payable {} - - function setFlag() public payable{ - flag = 1; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken043.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken043.sol deleted file mode 100644 index 43e4010ec3f..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken043.sol +++ /dev/null @@ -1,35 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - fallback() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken048.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken048.sol deleted file mode 100644 index e705f696c1d..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken048.sol +++ /dev/null @@ -1,14 +0,0 @@ - - - contract Test { - event log(uint256); - function testMsgTokenValue() payable public returns(uint256 value) { - emit log(msg.tokenvalue); - return msg.tokenvalue; - } - - function testMsgValue() payable public returns(uint256 value) { - emit log(msg.value); - return msg.value; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken049.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken049.sol deleted file mode 100644 index d40480720df..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken049.sol +++ /dev/null @@ -1,9 +0,0 @@ - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken050.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken050.sol deleted file mode 100644 index 6bc6d956898..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken050.sol +++ /dev/null @@ -1,10 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken051.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken051.sol deleted file mode 100644 index 493016b777f..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken051.sol +++ /dev/null @@ -1,11 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - fallback() external payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken052.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken052.sol deleted file mode 100644 index 6bc6d956898..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken052.sol +++ /dev/null @@ -1,10 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken054.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken054.sol deleted file mode 100644 index 863429fc4f8..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken054.sol +++ /dev/null @@ -1,16 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken055.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken055.sol deleted file mode 100644 index 863429fc4f8..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken055.sol +++ /dev/null @@ -1,16 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken060.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken060.sol deleted file mode 100644 index ea28f4a62b6..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken060.sol +++ /dev/null @@ -1,30 +0,0 @@ - - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken061.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken061.sol deleted file mode 100644 index ea28f4a62b6..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken061.sol +++ /dev/null @@ -1,30 +0,0 @@ - - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken064.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken064.sol deleted file mode 100644 index 43e0da8a510..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken064.sol +++ /dev/null @@ -1,49 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } - function transferTokenTestValueMaxBigInteger(address payable toAddress) payable public { - toAddress.transferToken(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0); - } - function transferTokenTestValueOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(9223372036854775808, 1000001); - } - function transferTokenTestValueMaxLong(address payable toAddress) payable public { - toAddress.transferToken(9223372036854775807, 1000001); - } - function transferTokenTestValue0IdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(0, 9223372036854775809); - } -} - - - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - fallback() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken066.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken066.sol deleted file mode 100644 index 43e4010ec3f..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken066.sol +++ /dev/null @@ -1,35 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - fallback() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken067.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken067.sol deleted file mode 100644 index 43e4010ec3f..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken067.sol +++ /dev/null @@ -1,35 +0,0 @@ - -contract transferTokenContract { - constructor() payable public{} - fallback() payable external{} - function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - fallback() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken073.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken073.sol deleted file mode 100644 index a9ee8ea412b..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken073.sol +++ /dev/null @@ -1,16 +0,0 @@ - -contract Dest { - event logFallback(uint256 indexed, uint256 indexed, uint256 indexed); - event logGetToken(uint256 indexed, uint256 indexed, uint256 indexed, uint256); - - - constructor() payable public {} - - function getToken(trcToken tokenId) payable public{ - emit logGetToken(msg.sender.tokenBalance(tokenId), msg.tokenid, msg.tokenvalue, msg.value); - } - - fallback() payable external{ - emit logFallback(msg.tokenid, msg.tokenvalue, msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken075.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken075.sol deleted file mode 100644 index 9f201900295..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken075.sol +++ /dev/null @@ -1,26 +0,0 @@ - - -contract Dest { - event logFallback(uint256 indexed, uint256 indexed, uint256 indexed); - event logGetToken(uint256 indexed, uint256 indexed, uint256 indexed, uint256); - - constructor() payable public {} - - function getToken(trcToken tokenId) payable public{ - emit logGetToken(msg.sender.tokenBalance(tokenId), msg.tokenid, msg.tokenvalue, msg.value); - } - - function getTokenLongMin() payable public{ - // long.min - 1000020 - emit logGetToken(msg.sender.tokenBalance(trcToken(-9223372036855775828)), msg.tokenid, msg.tokenvalue, msg.value); - } - - function getTokenLongMax() payable public{ - // long.max + 1000020 - emit logGetToken(msg.sender.tokenBalance(trcToken(9223372036855775827)), msg.tokenid, msg.tokenvalue, msg.value); - } - - fallback() payable external{ - emit logFallback(msg.tokenid, msg.tokenvalue, msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken076.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken076.sol deleted file mode 100644 index a9decbee320..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken076.sol +++ /dev/null @@ -1,19 +0,0 @@ - -contract Test { - address public origin; - address public sender; - bool public result1; - bool public result2; - function test() external { - origin = tx.origin; - sender = msg.sender; - result1 = msg.sender == tx.origin; // true - result2 = origin == sender; // true - } -function getResult1() public returns(bool){ - return result1; -} -function getResult2() public returns(bool){ - return result2; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken077.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken077.sol deleted file mode 100644 index aeecf9cb9a5..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken077.sol +++ /dev/null @@ -1,11 +0,0 @@ - - -contract trcToken077 { -function addressTest() public returns(bytes32 addressValue) { - assembly{ - let x := mload(0x40) //Find empty storage location using "free memory pointer" - mstore(x,address) //Place current contract address - addressValue := mload(x) - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken078.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken078.sol deleted file mode 100644 index 8d10d25312d..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken078.sol +++ /dev/null @@ -1,35 +0,0 @@ - -contract callerContract { - constructor() public payable{} - fallback() external payable{} - function sendToB(address called_address, address c) public payable{ - called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); - } - function sendToB2(address called_address,address c) public payable{ - called_address.call(abi.encodeWithSignature("transferTo(address)",c)); - } - function sendToB3(address called_address,address c) public payable{ - called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); - } -} - contract calledContract { - fallback() external payable{} - constructor() public payable {} - function transferTo(address payable toAddress)public payable{ - toAddress.transfer(5); - } - - function setIinC(address c) public payable{ - c.call{value:5}(abi.encode(bytes4(keccak256("setI()")))); - } - - } - contract c{ - address public origin; - address public sender; - constructor() public payable{} - event log(address,address); - fallback() payable external{ - emit log(tx.origin,msg.sender); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken079.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken079.sol deleted file mode 100644 index 863429fc4f8..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken079.sol +++ /dev/null @@ -1,16 +0,0 @@ - - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken080.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken080.sol deleted file mode 100644 index 2d2688b74a4..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcToken080.sol +++ /dev/null @@ -1,30 +0,0 @@ - - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - fallback() external payable{} - // positive case - function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractTrcTokenToOther.sol b/framework/src/test/resources/soliditycode_0.7.6/contractTrcTokenToOther.sol deleted file mode 100644 index 8e926d3ba17..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractTrcTokenToOther.sol +++ /dev/null @@ -1,44 +0,0 @@ - - -contract ConvertType { - -constructor() payable public{} - -fallback() payable external{} - -//function trcTokenOnStorage(trcToken storage token) internal { // ERROR: Data location can only be specified for array, struct or mapping types, but "storage" was given. -//} - -function trcTokenToString(trcToken token) public pure returns(string memory s){ -// s = token; // ERROR -// s = string(token); // ERROR -} - -function trcTokenToUint256(trcToken token) public pure returns(uint256 r){ -uint256 u = token; // OK -uint256 u2 = uint256(token); // OK -r = u2; -} - -function trcTokenToAddress(trcToken token) public pure returns(address r){ -//r = token; // ERROR -token = 0x1234567812345678123456781234567812345678123456781234567812345678; -address a2 = address(token); // OK -r = a2; -} - -function trcTokenToBytes(trcToken token) public pure returns(bytes memory r){ -//r = token; // ERROR -// r = bytes(token); // ERROR -} - -function trcTokenToBytes32(trcToken token) public pure returns(bytes32 r){ -// r = token; // ERROR -bytes32 b2 = bytes32(token); // OK -r = b2; -} - -function trcTokenToArray(trcToken token) public pure returns(uint[] memory r){ -//r = token; // ERROR -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/contractUnknownException.sol b/framework/src/test/resources/soliditycode_0.7.6/contractUnknownException.sol deleted file mode 100644 index 0aca7badde8..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/contractUnknownException.sol +++ /dev/null @@ -1,64 +0,0 @@ - -contract testA { - constructor() public payable { - A a = (new A){value:10}(); - a.fun(); - } -} - -contract testB { - constructor() public payable { - B b = (new B){value:10}(); - b.fun(); - } -} - - -contract testC { - constructor() public payable{ - C c = (new C){value:10}(); - c.fun(); - } -} - -contract testD { - constructor() public payable{ - D d = (new D){value:10}(); - d.fun(); - } -} - - -contract A { - constructor() public payable{ - selfdestruct(msg.sender); - } - function fun() public { - } - -} - -contract B { - constructor() public payable { - revert(); - } - function fun() public { - } -} - - -contract C { - constructor() public payable { - assert(1==2); - } - function fun() public { - } -} - -contract D { - constructor() public payable { - require(1==2); - } - function fun() public { - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/create2CallContract.sol b/framework/src/test/resources/soliditycode_0.7.6/create2CallContract.sol deleted file mode 100644 index 046706ebd9e..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/create2CallContract.sol +++ /dev/null @@ -1,37 +0,0 @@ -contract callerContract { - constructor() payable public{} - fallback() payable external{} - function delegateCallCreate2(address called_address, bytes memory code, uint256 salt) public { - called_address.delegatecall(abi.encodeWithSignature("deploy(bytes,uint256)",code,salt)); - } - function callCreate2(address called_address,bytes memory code, uint256 salt) public returns(bool,bytes memory){ - return called_address.call(abi.encodeWithSignature("deploy(bytes,uint256)",code,salt)); - } -} - - -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - -contract TestConstract { - uint public i; - constructor () public { - } - function plusOne() public returns(uint){ - i++; - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/create2Istanbul.sol b/framework/src/test/resources/soliditycode_0.7.6/create2Istanbul.sol deleted file mode 100644 index c2ef8f3236b..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/create2Istanbul.sol +++ /dev/null @@ -1,28 +0,0 @@ - - -contract create2Istanbul { - function deploy(bytes memory code, uint256 salt) public returns(address) { - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - - } - return addr; - } - - // prefix in main net is 0x41, testnet config is 0xa0 - function get(bytes1 prefix, bytes calldata code, uint256 salt) external view returns(address) { - //bytes32 hash = keccak256(abi.encodePacked(bytes1(0x41),address(this), salt, keccak256(code))); - bytes32 hash = keccak256(abi.encodePacked(prefix,address(this), salt, keccak256(code))); - address addr = address(uint160(uint256(hash))); - return addr; - } - -} - -contract B { - constructor() public payable{} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/create2contract.sol b/framework/src/test/resources/soliditycode_0.7.6/create2contract.sol deleted file mode 100644 index 0171f4d5486..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/create2contract.sol +++ /dev/null @@ -1,52 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } - - event Deployed(address addr, bytes32 salt, address sender); - function deploy(bytes memory code, bytes32 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - -contract FactoryBytes { - event Deployed(address addr, bytes32 salt, address sender); - function deploy(bytes memory code, bytes32 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - -contract TestConstract { - uint public i; - constructor () public { - } - function plusOne() public returns(uint){ - i++; - return i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/create2contract22.sol b/framework/src/test/resources/soliditycode_0.7.6/create2contract22.sol deleted file mode 100644 index c33cb08edc3..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/create2contract22.sol +++ /dev/null @@ -1,109 +0,0 @@ -contract Factory { - event Deployed(address addr, trcToken salt, address sender); - event Deployed1(address addr, uint8 salt, address sender); - event Deployed2(address addr, address salt, address sender); - event Deployed3(address addr, string salt, address sender); - - - function deploy(bytes memory code, trcToken salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } - - function deploy1(bytes memory code, uint8 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed1(addr, salt, msg.sender); - return addr; - } - - function deploy2(bytes memory code, address salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed2(addr, salt, msg.sender); - return addr; - } - - function deploy3(bytes memory code, string memory salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed3(addr, salt, msg.sender); - return addr; - } - -} - - -contract TestConstract { - uint public i=1; - function testTransfer(uint256 i) payable public{ - msg.sender.transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} - -contract TestConstract1 { - uint public i=2; - function testTransfer(uint256 i) payable public{ - msg.sender.transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} - -contract TestConstract2 { - uint public i=3; - function testTransfer(uint256 i) payable public{ - msg.sender.transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} - -contract TestConstract3 { - uint public i=4; - function testTransfer(uint256 i) payable public{ - msg.sender.transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/create2contractn.sol b/framework/src/test/resources/soliditycode_0.7.6/create2contractn.sol deleted file mode 100644 index e0e3ae64c16..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/create2contractn.sol +++ /dev/null @@ -1,29 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract TestConstract { - uint public i=1; - function testTransfer(uint256 i) payable public{ - msg.sender.transfer(i); - } - function testTransferToken(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/create2contractn2.sol b/framework/src/test/resources/soliditycode_0.7.6/create2contractn2.sol deleted file mode 100644 index 626988c4e04..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/create2contractn2.sol +++ /dev/null @@ -1,26 +0,0 @@ -contract Factory { - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract TestConstract { - uint public i=1; - function set() payable public { - i=5; - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/demo.sol b/framework/src/test/resources/soliditycode_0.7.6/demo.sol deleted file mode 100644 index 06bf15387fc..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/demo.sol +++ /dev/null @@ -1,73 +0,0 @@ - - - contract tokenTest{ - uint256 codesize; - constructor() payable public{ - uint256 m; - address addr = address(this); - assembly { - m := extcodesize(addr) - } - codesize = m; - } - - // positive case - function pulsone() public payable{ - uint256 j = 0; - uint i = 100; - for (; i < i; i++) { - j++; - } - } - - - function getCodeSize() public returns (uint256){ - return codesize; - } - - } - - contract confirmTest{ - - uint256 codesize; - constructor() payable public{ - uint256 m; - address addr = address(this); - assembly { - m := extcodesize(addr) - - } - codesize = m; - } - - function getCodeSize() public returns (uint256){ - return codesize; - } - - function confirm(address addr) public returns (uint256){ - uint256 j; - assembly { - j := extcodesize(addr) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - return j; - } - - function at(address _addr) public returns (bytes memory o_code) { - assembly { - // retrieve the size of the code, this needs assembly - let size := extcodesize(_addr) - // allocate output byte array - this could also be done without assembly - // by using o_code = new bytes(size) - o_code := mload(0x40) - // new "memory end" including padding - mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) - // store length in memory - mstore(o_code, size) - // actually retrieve the code, this needs assembly - extcodecopy(_addr, add(o_code, 0x20), 0, size) - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/enumAndStruct.sol b/framework/src/test/resources/soliditycode_0.7.6/enumAndStruct.sol deleted file mode 100644 index 836a4ac850e..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/enumAndStruct.sol +++ /dev/null @@ -1,43 +0,0 @@ - - -struct S_out { -uint x; -} - -enum ErrorType { -Revert_Error, //0 -RevertWithMsg_Error, //1 -Require_Error, //2 -RequirewithMsg_Error, //3 -Assert_Error, //4 -Tansfer_Error, //5 -Send_Error, //6 -Math_Error, //7 -ArrayOverFlow_Error //8 -} - -contract enumAndStructTest { - -struct S_inner { -int x; -} - -enum ErrorType_inner { -Revert_Error, //0 -RevertWithMsg_Error, //1 -Require_Error, //2 -RequirewithMsg_Error, //3 -Assert_Error, //4 -Tansfer_Error, //5 -Send_Error, //6 -Math_Error, //7 -ArrayOverFlow_Error //8 -} - -function getvalue() public returns(uint) { - require(ErrorType.Require_Error == ErrorType(2)); - S_out memory s = S_out(1); - return s.x; -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/event001.sol b/framework/src/test/resources/soliditycode_0.7.6/event001.sol deleted file mode 100644 index 7662df3a5c6..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/event001.sol +++ /dev/null @@ -1,10 +0,0 @@ -contract Event { - event xixi(uint256 id) ; - event log2(uint256,uint256,uint256); - constructor() public payable{} - function messageI() payable public returns (uint ret) { - //emit log2(1,2,3); - emit xixi(1); - return 1; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/event002.sol b/framework/src/test/resources/soliditycode_0.7.6/event002.sol deleted file mode 100644 index a61f834e1b5..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/event002.sol +++ /dev/null @@ -1,52 +0,0 @@ - - -contract Event { - - event _0(); - event a_0() anonymous; - event a_4i(uint256 indexed x1, uint256 indexed x2 , uint256 indexed x3, uint256 indexed x4, uint256 x5)anonymous ; - event _3i(uint256 x1, uint256 indexed x2 , uint256 indexed x3, uint256 x4, uint256 x5) ; - event _1i(uint256 indexed x1, uint256, uint256 indexed, uint256 x4) ; - event a_1i(uint256) anonymous; - event _ai(uint8[2], uint8) ; - event a_ai(uint8[2], uint8) anonymous; - event _a1i(uint8[2] indexed, uint8) ; - event a_a1i(uint8[2] indexed, uint8) anonymous; - - constructor () public { - // emit a_0(); - // emit a_1i(123); - // emit a_4i(1,2,3,5,16); - // emit _0(); - emit _3i(1,2,3,5,16); - // emit _1i(1,2,3,5); - // emit _ai([1,2], 3); - // emit a_ai([3,4], 5); - // emit _a1i([1,2], 3); - // emit a_a1i([3,4], 5); - } - - function e() public { - emit _1i(1,2,3,4); - } - - function l() public { - emit a_1i(1); - } - - function k() public{ - emit a_4i(2,3,4,5,17); - emit _3i(2,3,4,5,16); - emit _1i(2,3,4,5); - emit a_1i(128); - emit _0(); - emit a_0(); - //selfdestruct(msg.sender); - //emit a_4i(1,2,3,5,16); - //emit _3i(1,2,3,5,16); - //emit _1i(1,2,3,5); - //emit a_1i(123); - //emit _0(); - //emit a_0(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/extCodeHash.sol b/framework/src/test/resources/soliditycode_0.7.6/extCodeHash.sol deleted file mode 100644 index d6209770682..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/extCodeHash.sol +++ /dev/null @@ -1,13 +0,0 @@ -contract TestExtCodeHash { - - function getCodeHashByAddr(address _addr) public returns (bytes32 _hash) { - assembly { - _hash := extcodehash(_addr) - } - } - function getCodeHashByUint(uint256 _addr) public returns (bytes32 _hash) { - assembly { - _hash := extcodehash(_addr) - } - } -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/extCodeHash11.sol b/framework/src/test/resources/soliditycode_0.7.6/extCodeHash11.sol deleted file mode 100644 index ad59f6cce1c..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/extCodeHash11.sol +++ /dev/null @@ -1,103 +0,0 @@ -contract Counter { -uint count = 0; -address payable owner; -event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); -constructor() public{ -owner = msg.sender; -} -function getCodeHashByAddr() public returns (bytes32 _hashBefore, bytes32 _hashAfter) { -address addr = address(this); -assembly { -_hashBefore := extcodehash(addr) -} -if (owner == msg.sender) { -selfdestruct(owner); -} -assembly { -_hashAfter := extcodehash(addr) -} -revert(); -emit LogResult(_hashBefore, _hashAfter); -} -} - -contract Counter1 { -uint count = 0; -address payable owner; -event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); -constructor() public{ -owner = msg.sender; -} -function getCodeHashByAddr() public returns (bytes32 _hashBefore, bytes32 _hashAfter) { -address addr = address(this); -assembly { -_hashBefore := extcodehash(addr) -} -if (owner == msg.sender) { -selfdestruct(owner); -} -assembly { -_hashAfter := extcodehash(addr) -} - -emit LogResult(_hashBefore, _hashAfter); -} -} - - -contract Counter2 { -uint count = 0; -address payable owner; -event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); -constructor() public{ -owner = msg.sender; -} -function getCodeHashByAddr(address c) public returns (bytes32 _hashBefore, bytes32 _hashAfter) { - TestConstract t=new TestConstract(); -address addr = address(t); -assembly { -_hashBefore := extcodehash(addr) -} - addr.call(abi.encodeWithSignature("testSuicideNonexistentTarget(address)",c)); - - -assembly { -_hashAfter := extcodehash(addr) -} - -emit LogResult(_hashBefore, _hashAfter); -} -} - - -contract Counter3 { -uint count = 0; -address payable owner; -event LogResult(bytes32 _hashBefore, bytes32 _hashAfter); -constructor() public{ -owner = msg.sender; -} -function getCodeHashByAddr(address c) public returns (bytes32 _hashBefore, bytes32 _hashAfter) { - TestConstract t=new TestConstract(); -address addr = address(t); -assembly { -_hashBefore := extcodehash(addr) -} -if (owner == msg.sender) { -selfdestruct(owner); -} - -assembly { -_hashAfter := extcodehash(addr) -} - -emit LogResult(_hashBefore, _hashAfter); -} -} - -contract TestConstract { - uint public i=1; - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/extCodeHashConstruct.sol b/framework/src/test/resources/soliditycode_0.7.6/extCodeHashConstruct.sol deleted file mode 100644 index 6bb91b3d3b1..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/extCodeHashConstruct.sol +++ /dev/null @@ -1,14 +0,0 @@ -contract CounterConstruct { - uint count = 0; - address payable owner; - event LogResult(bytes32 _hashBefore); - constructor() public{ - owner = msg.sender; - address addr = address(this); - bytes32 _hashBefore; - assembly { - _hashBefore := extcodehash(addr) - } - emit LogResult(_hashBefore); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/extCodeHashStress.sol b/framework/src/test/resources/soliditycode_0.7.6/extCodeHashStress.sol deleted file mode 100644 index cf41f3c8106..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/extCodeHashStress.sol +++ /dev/null @@ -1,45 +0,0 @@ -contract Trigger { - function test(address addr) public returns(uint i) { - bytes32 hash; - while (gasleft() > 1000) { - assembly { - hash := extcodehash(addr) - } - i++; - } - } - - function test(address[] memory addrs) public returns(uint i) { - bytes32 hash; - uint i = 0; - for (; i < addrs.length; i++) { - address addr = addrs[i]; - assembly { - hash := extcodehash(addr) - } - } - return i; - } - } - - - - contract TriggerNormal { - function test(address addr) public returns(uint i) { - i = 0; - while (gasleft() > 100000) { - i++; - } - } - } - - contract TriggerNormal1 { - function test(address[] memory addrs) public returns(uint i) { - bytes32 hash; - uint i = 0; - for (; i < addrs.length; i++) { - address addr = addrs[i]; - addr.balance; - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/extCodeHashTestNoPayable.sol b/framework/src/test/resources/soliditycode_0.7.6/extCodeHashTestNoPayable.sol deleted file mode 100644 index c3a2ad8c6ae..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/extCodeHashTestNoPayable.sol +++ /dev/null @@ -1,8 +0,0 @@ -contract testConstantContract{ -uint256 public i; -function testNoPayable() public returns (uint256 z) { -i=1; -z=i; -return z; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/fallbackUpgrade.sol b/framework/src/test/resources/soliditycode_0.7.6/fallbackUpgrade.sol deleted file mode 100644 index 6751858c65e..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/fallbackUpgrade.sol +++ /dev/null @@ -1,83 +0,0 @@ -contract Test0{ - event FuncCalled(bytes data,uint a); -} - -contract Test1 { - - event FuncCalled(string a); - fallback() external { - x = "fallback"; - emit FuncCalled(x); - } - string x; -} -//含有payable的fallback,无receice -contract Test2 { - - event FuncCalled(string data); - fallback() external payable{ - x = "fallback"; - emit FuncCalled(x); - } - string x; -} - -contract TestPayable { - event FuncCalled(string a); - - fallback() external payable { - x = "fallback"; - emit FuncCalled(x); - } - - receive() external payable { - x = "receive"; - emit FuncCalled(x); - } - string x; -} - -contract Caller { - function callTest0(Test0 test) public{ - (bool success,) = address(test).call(abi.encodeWithSignature("nonExistingFunction()")); - require(success); - } - function callTest1(address test) public returns (bool) { - (bool success,) = test.call(abi.encodeWithSignature("nonExistingFunction()")); - require(success); - (success,) = address(test).call(""); - require(success); - return true; - } - function callTest2(address test) public payable returns (bool) { - (bool success,) = test.call{value:1000}(abi.encodeWithSignature("nonExistingFunction()")); - require(success); - return true; - } - function callTestPayable1(TestPayable test) public payable returns (bool) { - (bool success,) = address(test).call(abi.encodeWithSignature("nonExistingFunction()")); - require(success); - (success,) = address(test).call(""); - require(success); - return true; - } -} - - -//contract Test0 { -// event FallbackCall(string data,bytes msg); -// //event FuncCalled(string a,bytes data); -// function() external payable{ -// x = "fallback"; -// emit FallbackCall(x,msg.data); -// } -// string x; -//} -//contract Caller{ -// function call(Test0 test) public payable returns(bool){ -// (bool success,) = address(test).call(abi.encodeWithSignature("nonExistingFunction()")); -// require(success); -// return true; -// } -//} - diff --git a/framework/src/test/resources/soliditycode_0.7.6/freezeContract001.sol b/framework/src/test/resources/soliditycode_0.7.6/freezeContract001.sol deleted file mode 100644 index 0ad8ed9f460..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/freezeContract001.sol +++ /dev/null @@ -1,63 +0,0 @@ - -contract TestFreeze { - constructor() public payable {} - - function freeze(address payable receiver, uint amount, uint res) external payable{ - receiver.freeze(amount, res); - } - - function unfreeze(address payable receiver, uint res) external { - receiver.unfreeze(res); - } - - function destroy(address payable inheritor) external { - selfdestruct(inheritor); - } - - function send(address payable A) external { - A.transfer(10); - } - - function send(address payable A, uint256 value) external { - A.transfer(value); - } - - function getExpireTime(address payable target, uint res) external view returns(uint) { - return target.freezeExpireTime(res); - } - - function deploy(uint256 salt) public returns(address){ - address addr; - bytes memory code = type(C).creationCode; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } - - function freezeAndSend(address payable receiver, uint amount, uint res) external { - receiver.transfer(amount); - receiver.freeze(amount, res); - } - - -} - - -contract C { - constructor() public payable {} - - function destroy(address payable inheritor) external { - selfdestruct(inheritor); - } -} - -contract D { - constructor() public payable { - msg.sender.freeze(msg.value, 1); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/getAddressChange.sol b/framework/src/test/resources/soliditycode_0.7.6/getAddressChange.sol deleted file mode 100644 index 2796da68770..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/getAddressChange.sol +++ /dev/null @@ -1,12 +0,0 @@ -contract getAddressChange { - constructor() public payable {} - // testaddress1函数新增了一个address属性。0.6.0之前 external函数可以通过address(x)来转化为地址,6.0将其禁止,可以通过函数address属性直接获取 - function testaddress1() public view returns(address) { - //return address(this.getamount); //0.6.0之前可以使用 - return this.getamount.address; //0.6.0 - - } - function getamount(address) external view returns(uint256) { - return address(this).balance; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/isSRCandidate.sol b/framework/src/test/resources/soliditycode_0.7.6/isSRCandidate.sol deleted file mode 100644 index e8e9b692dec..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/isSRCandidate.sol +++ /dev/null @@ -1,35 +0,0 @@ - - - -contract ContractB{ - address others; -} - -contract TestIsSRCandidate{ - - ContractB contractB = new ContractB(); - - function isSRCandidateTest(address addr) public view returns (bool) { - return address(addr).isSRCandidate; - } - - function zeroAddressTest() public view returns (bool) { - return address(0x0).isSRCandidate; - } - - function localContractAddrTest() public view returns (bool) { - return address(this).isSRCandidate; - } - - function otherContractAddrTest() public view returns (bool) { - return address(contractB).isSRCandidate; - } - - function nonpayableAddrTest(address addr) public view returns (bool) { - return addr.isSRCandidate; - } - - function payableAddrTest(address payable addr) public returns (bool) { - return addr.isSRCandidate; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/mappingGetter.sol b/framework/src/test/resources/soliditycode_0.7.6/mappingGetter.sol deleted file mode 100644 index dbd473717cb..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/mappingGetter.sol +++ /dev/null @@ -1,4 +0,0 @@ -contract mappingGetter { - mapping(bytes => uint256) public balances1; - mapping(string => uint256) public balances2; -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/multiValiSignPerformance01.sol b/framework/src/test/resources/soliditycode_0.7.6/multiValiSignPerformance01.sol deleted file mode 100644 index 74baa963366..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/multiValiSignPerformance01.sol +++ /dev/null @@ -1,37 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract ecrecoverValidateSign { - - using ECVerify for bytes32; - - function validateSign(bytes32 hash,bytes[] memory sig,address[] memory signer) public returns (bool) { - for(uint256 i=0;i=0.5.0 <0.7.0; - -contract A { - uint public x; - function setValue(uint _x) public { - x = _x; - } -} -contract B is A {} -contract C is A {} -// No explicit override required -contract D is B, C {} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/override003.sol b/framework/src/test/resources/soliditycode_0.7.6/override003.sol deleted file mode 100644 index 0ca6a2663d1..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/override003.sol +++ /dev/null @@ -1,20 +0,0 @@ -//pragma solidity ^0.6.0; -contract A { - uint public x; - function setValue(uint _x) public virtual { - x = _x; - } -} - -contract B { - uint public y; - function setValue(uint _y) public virtual { - y = _y; - } -} - -contract C is A, B { - function setValue(uint _x) public override(B,A) { - A.setValue(_x); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/override004.sol b/framework/src/test/resources/soliditycode_0.7.6/override004.sol deleted file mode 100644 index d0cf20525d5..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/override004.sol +++ /dev/null @@ -1,25 +0,0 @@ -//pragma solidity >=0.5.0 <0.7.0; - -contract A { - uint public x = 4; - function setValue(uint _x) public notZero { - x = _x; - } - modifier notZero() virtual { - require(x >= 5,"x must >= 5"); - _; - } -} - -contract B is A { - function setValue2(uint _x) public { - x = _x; - } -} - -contract C is A,B { - modifier notZero override { - require(x >= 6,"x must >= 6"); - _; - } -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/override005.sol b/framework/src/test/resources/soliditycode_0.7.6/override005.sol deleted file mode 100644 index 0ea485ae0a2..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/override005.sol +++ /dev/null @@ -1,39 +0,0 @@ -pragma solidity >= 0.6.0; - -contract Base { - enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } - ActionChoices public choice2 = ActionChoices.GoRight; - - function stopped() virtual external view returns (bool) { - return true; - } - function i() virtual external view returns (int) { - return 32482980; - } - function i2() virtual external view returns (int) { - return -32482980; - } - function ui() virtual external view returns (uint) { - return 23487820; - } - function origin() virtual external view returns (address) { - return 0x3b0E4a6EdEE231CE0c3433F00F1bbc5FeD409c0B; - } - function b32() virtual external view returns (bytes32) { - return 0xb55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd231050; - } - function choice() virtual external returns (ActionChoices) { - return choice2; - } -} - -contract Test is Base { - - bool override public stopped = false; - int override public i = 32482989; - int override public i2 = -32482989; - uint override public ui = 23487823; - address override public origin = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; - bytes32 override public b32 = 0xb55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105c; - ActionChoices override public choice = ActionChoices.SitStill; -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/overridePrivateFunction.sol b/framework/src/test/resources/soliditycode_0.7.6/overridePrivateFunction.sol deleted file mode 100644 index b0b4d679620..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/overridePrivateFunction.sol +++ /dev/null @@ -1,22 +0,0 @@ -pragma solidity ^0.5.17; - -contract A { - - function test() private pure returns(uint) { - return 1; - } - -} - -contract B is A { - - function basic() private pure returns(uint) { - return 2; - } - function testOverridePrivate() external payable returns(uint) { - return basic(); - } - - constructor() public payable {} -} - diff --git a/framework/src/test/resources/soliditycode_0.7.6/payable001.sol b/framework/src/test/resources/soliditycode_0.7.6/payable001.sol deleted file mode 100644 index 4fe7b20921f..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/payable001.sol +++ /dev/null @@ -1,31 +0,0 @@ - - - -contract A { - constructor() public payable{ - } - - fallback() external payable { - } -} - -contract PayableTest { - -address payable a1; -function receiveMoneyTransfer(address a, uint256 _x) public { -a1 = payable(a); -a1.transfer(_x); -} - -function receiveMoneySend(address a, uint256 x) public { -address payable a2 = payable(a); -a2.send(x); -} - -function receiveMoneyTransferWithContract(A PayableTest, uint256 x) public { -payable(address(PayableTest)).transfer(x); -} - -constructor() public payable{ -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/pedersenHash001.sol b/framework/src/test/resources/soliditycode_0.7.6/pedersenHash001.sol deleted file mode 100644 index 6cad7cb9855..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/pedersenHash001.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract pedersenHashTest { - - function test1() public returns (bool, bytes memory){ - bytes memory empty = ""; - return address(0x1000004).delegatecall(empty); - } - - function test2(bytes memory data) public returns (bool, bytes memory){ - return address(0x1000004).delegatecall(data); - } - - function test3(uint32 hash, bytes32 left, bytes32 right) public returns (bytes32){ - return pedersenHash(hash, left, right); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/pedersenHash002.sol b/framework/src/test/resources/soliditycode_0.7.6/pedersenHash002.sol deleted file mode 100644 index b0a78973ef2..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/pedersenHash002.sol +++ /dev/null @@ -1,320 +0,0 @@ -pragma experimental ABIEncoderV2; - -import "./SafeMath.sol"; - -abstract contract TokenTRC20 { - function transfer(address _to, uint256 _value) public virtual returns (bool success); - - function transferFrom(address _from, address _to, uint256 _value) public virtual returns (bool success); -} - -contract ShieldedTRC20 { - using SafeMath for uint256; - - uint256 public scalingFactor; // used when decimals of TRC20 token is too large. - uint256 public leafCount; - uint256 constant INT64_MAX = 2 ** 63 - 1; - bytes32 public latestRoot; - mapping(bytes32 => bytes32) public nullifiers; // store nullifiers of spent commitments - mapping(bytes32 => bytes32) public roots; // store history root - mapping(uint256 => bytes32) public tree; - mapping(bytes32 => bytes32) public noteCommitment; - bytes32[33] frontier; - bytes32[32] zeroes = [bytes32(0x0100000000000000000000000000000000000000000000000000000000000000), bytes32(0x817de36ab2d57feb077634bca77819c8e0bd298c04f6fed0e6a83cc1356ca155), bytes32(0xffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e34), bytes32(0xd8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c), bytes32(0xe110de65c907b9dea4ae0bd83a4b0a51bea175646a64c12b4c9f931b2cb31b49), bytes32(0x912d82b2c2bca231f71efcf61737fbf0a08befa0416215aeef53e8bb6d23390a), bytes32(0x8ac9cf9c391e3fd42891d27238a81a8a5c1d3a72b1bcbea8cf44a58ce7389613), bytes32(0xd6c639ac24b46bd19341c91b13fdcab31581ddaf7f1411336a271f3d0aa52813), bytes32(0x7b99abdc3730991cc9274727d7d82d28cb794edbc7034b4f0053ff7c4b680444), bytes32(0x43ff5457f13b926b61df552d4e402ee6dc1463f99a535f9a713439264d5b616b), bytes32(0xba49b659fbd0b7334211ea6a9d9df185c757e70aa81da562fb912b84f49bce72), bytes32(0x4777c8776a3b1e69b73a62fa701fa4f7a6282d9aee2c7a6b82e7937d7081c23c), bytes32(0xec677114c27206f5debc1c1ed66f95e2b1885da5b7be3d736b1de98579473048), bytes32(0x1b77dac4d24fb7258c3c528704c59430b630718bec486421837021cf75dab651), bytes32(0xbd74b25aacb92378a871bf27d225cfc26baca344a1ea35fdd94510f3d157082c), bytes32(0xd6acdedf95f608e09fa53fb43dcd0990475726c5131210c9e5caeab97f0e642f), bytes32(0x1ea6675f9551eeb9dfaaa9247bc9858270d3d3a4c5afa7177a984d5ed1be2451), bytes32(0x6edb16d01907b759977d7650dad7e3ec049af1a3d875380b697c862c9ec5d51c), bytes32(0xcd1c8dbf6e3acc7a80439bc4962cf25b9dce7c896f3a5bd70803fc5a0e33cf00), bytes32(0x6aca8448d8263e547d5ff2950e2ed3839e998d31cbc6ac9fd57bc6002b159216), bytes32(0x8d5fa43e5a10d11605ac7430ba1f5d81fb1b68d29a640405767749e841527673), bytes32(0x08eeab0c13abd6069e6310197bf80f9c1ea6de78fd19cbae24d4a520e6cf3023), bytes32(0x0769557bc682b1bf308646fd0b22e648e8b9e98f57e29f5af40f6edb833e2c49), bytes32(0x4c6937d78f42685f84b43ad3b7b00f81285662f85c6a68ef11d62ad1a3ee0850), bytes32(0xfee0e52802cb0c46b1eb4d376c62697f4759f6c8917fa352571202fd778fd712), bytes32(0x16d6252968971a83da8521d65382e61f0176646d771c91528e3276ee45383e4a), bytes32(0xd2e1642c9a462229289e5b0e3b7f9008e0301cbb93385ee0e21da2545073cb58), bytes32(0xa5122c08ff9c161d9ca6fc462073396c7d7d38e8ee48cdb3bea7e2230134ed6a), bytes32(0x28e7b841dcbc47cceb69d7cb8d94245fb7cb2ba3a7a6bc18f13f945f7dbd6e2a), bytes32(0xe1f34b034d4a3cd28557e2907ebf990c918f64ecb50a94f01d6fda5ca5c7ef72), bytes32(0x12935f14b676509b81eb49ef25f39269ed72309238b4c145803544b646dca62d), bytes32(0xb2eed031d4d6a4f02a097f80b54cc1541d4163c6b6f5971f88b6e41d35c53814)]; - address owner; - TokenTRC20 trc20Token; - - event MintNewLeaf(uint256 position, bytes32 cm, bytes32 cv, bytes32 epk, bytes32[21] c); - event TransferNewLeaf(uint256 position, bytes32 cm, bytes32 cv, bytes32 epk, bytes32[21] c); - event BurnNewLeaf(uint256 position, bytes32 cm, bytes32 cv, bytes32 epk, bytes32[21] c); - event TokenMint(address from, uint256 value); - event TokenBurn(address to, uint256 value, bytes32[3] ciphertext); - event NoteSpent(bytes32 nf); - - constructor (address trc20ContractAddress, uint256 scalingFactorExponent) public { - require(scalingFactorExponent < 77, "The scalingFactorExponent is out of range!"); - scalingFactor = 10 ** scalingFactorExponent; - owner = msg.sender; - trc20Token = TokenTRC20(trc20ContractAddress); - } - // output: cm, cv, epk, proof - function mint(uint256 rawValue, bytes32[9] calldata output, bytes32[2] calldata bindingSignature, bytes32[21] calldata c) external { - address sender = msg.sender; - // transfer the trc20Token from the sender to this contract - bool transferResult = trc20Token.transferFrom(sender, address(this), rawValue); - require(transferResult, "TransferFrom failed!"); - - require(noteCommitment[output[0]] == 0, "Duplicate noteCommitments!"); - uint64 value = rawValueToValue(rawValue); - bytes32 signHash = sha256(abi.encodePacked(address(this), value, output, c)); - (bytes32[] memory ret) = verifyMintProof(output, bindingSignature, value, signHash, frontier, leafCount); - uint256 result = uint256(ret[0]); - require(result == 1, "The proof and signature have not been verified by the contract!"); - - uint256 slot = uint256(ret[1]); - uint256 nodeIndex = leafCount + 2 ** 32 - 1; - tree[nodeIndex] = output[0]; - if (slot == 0) { - frontier[0] = output[0]; - } - for (uint256 i = 1; i < slot + 1; i++) { - nodeIndex = (nodeIndex - 1) / 2; - tree[nodeIndex] = ret[i + 1]; - if (i == slot) { - frontier[slot] = tree[nodeIndex]; - } - } - latestRoot = ret[slot + 2]; - roots[latestRoot] = latestRoot; - noteCommitment[output[0]] = output[0]; - leafCount ++; - - emit MintNewLeaf(leafCount - 1, output[0], output[1], output[2], c); - emit TokenMint(sender, rawValue); - } - //input: nf, anchor, cv, rk, proof - //output: cm, cv, epk, proof - function transfer(bytes32[10][] calldata input, bytes32[2][] calldata spendAuthoritySignature, bytes32[9][] calldata output, bytes32[2] calldata bindingSignature, bytes32[21][] calldata c) external { - require(input.length >= 1 && input.length <= 2, "Input number must be 1 or 2!"); - require(input.length == spendAuthoritySignature.length, "Input number must be equal to spendAuthoritySignature number!"); - require(output.length >= 1 && output.length <= 2, "Output number must be 1 or 2!"); - require(output.length == c.length, "Output number must be equal to c number!"); - - for (uint256 i = 0; i < input.length; i++) { - require(nullifiers[input[i][0]] == 0, "The note has already been spent!"); - require(roots[input[i][1]] != 0, "The anchor must exist!"); - } - for (uint256 i = 0; i < output.length; i++) { - require(noteCommitment[output[i][0]] == 0, "Duplicate noteCommitment!"); - } - - bytes32 signHash = sha256(abi.encodePacked(address(this), input, output, c)); - (bytes32[] memory ret) = verifyTransferProof(input, spendAuthoritySignature, output, bindingSignature, signHash, 0, frontier, leafCount); - uint256 result = uint256(ret[0]); - require(result == 1, "The proof and signature have not been verified by the contract!"); - - uint256 offset = 1; - //ret offset - for (uint256 i = 0; i < output.length; i++) { - uint256 slot = uint256(ret[offset++]); - uint256 nodeIndex = leafCount + 2 ** 32 - 1; - tree[nodeIndex] = output[i][0]; - if (slot == 0) { - frontier[0] = output[i][0]; - } - for (uint256 k = 1; k < slot + 1; k++) { - nodeIndex = (nodeIndex - 1) / 2; - tree[nodeIndex] = ret[offset++]; - if (k == slot) { - frontier[slot] = tree[nodeIndex]; - } - } - leafCount++; - } - latestRoot = ret[offset]; - roots[latestRoot] = latestRoot; - for (uint256 i = 0; i < input.length; i++) { - bytes32 nf = input[i][0]; - nullifiers[nf] = nf; - emit NoteSpent(nf); - } - for (uint256 i = 0; i < output.length; i++) { - noteCommitment[output[i][0]] = output[i][0]; - emit TransferNewLeaf(leafCount - (output.length - i), output[i][0], output[i][1], output[i][2], c[i]); - } - } - //input: nf, anchor, cv, rk, proof - //output: cm, cv, epk, proof - function burn(bytes32[10] calldata input, bytes32[2] calldata spendAuthoritySignature, uint256 rawValue, bytes32[2] calldata bindingSignature, address payTo, bytes32[3] calldata burnCipher, bytes32[9][] calldata output, bytes32[21][] calldata c) external { - uint64 value = rawValueToValue(rawValue); - bytes32 signHash = sha256(abi.encodePacked(address(this), input, output, c, payTo, value)); - - bytes32 nf = input[0]; - bytes32 anchor = input[1]; - require(nullifiers[nf] == 0, "The note has already been spent!"); - require(roots[anchor] != 0, "The anchor must exist!"); - - require(output.length <= 1, "Output number cannot exceed 1!"); - require(output.length == c.length, "Output number must be equal to length of c!"); - - // bytes32 signHash = sha256(abi.encodePacked(address(this), input, payTo, value, output, c)); - if (output.length == 0) { - (bool result) = verifyBurnProof(input, spendAuthoritySignature, value, bindingSignature, signHash); - require(result, "The proof and signature have not been verified by the contract!"); - } else { - transferInBurn(input, spendAuthoritySignature, value, bindingSignature, signHash, output, c); - } - - nullifiers[nf] = nf; - emit NoteSpent(nf); - //Finally, transfer trc20Token from this contract to the nominated address - bool transferResult = trc20Token.transfer(payTo, rawValue); - require(transferResult, "Transfer failed!"); - - emit TokenBurn(payTo, rawValue, burnCipher); - } - - function transferInBurn(bytes32[10] memory input, bytes32[2] memory spendAuthoritySignature, uint64 value, bytes32[2] memory bindingSignature, bytes32 signHash, bytes32[9][] memory output, bytes32[21][] memory c) private { - bytes32 cm = output[0][0]; - require(noteCommitment[cm] == 0, "Duplicate noteCommitment!"); - bytes32[10][] memory inputs = new bytes32[10][](1); - inputs[0] = input; - bytes32[2][] memory spendAuthoritySignatures = new bytes32[2][](1); - spendAuthoritySignatures[0] = spendAuthoritySignature; - (bytes32[] memory ret) = verifyTransferProof(inputs, spendAuthoritySignatures, output, bindingSignature, signHash, value, frontier, leafCount); - uint256 result = uint256(ret[0]); - require(result == 1, "The proof and signature have not been verified by the contract!"); - - uint256 slot = uint256(ret[1]); - uint256 nodeIndex = leafCount + 2 ** 32 - 1; - tree[nodeIndex] = cm; - if (slot == 0) { - frontier[0] = cm; - } - for (uint256 i = 1; i < slot + 1; i++) { - nodeIndex = (nodeIndex - 1) / 2; - tree[nodeIndex] = ret[i + 1]; - if (i == slot) { - frontier[slot] = tree[nodeIndex]; - } - } - latestRoot = ret[slot + 2]; - roots[latestRoot] = latestRoot; - noteCommitment[cm] = cm; - leafCount ++; - - emit BurnNewLeaf(leafCount - 1, cm, output[0][1], output[0][2], c[0]); - } - - //position: index of leafnode, start from 0 - function getPath(uint256 position) public view returns (bytes32, bytes32[32] memory) { - require(position >= 0, "Position should be non-negative!"); - require(position < leafCount, "Position should be smaller than leafCount!"); - uint256 index = position + 2 ** 32 - 1; - bytes32[32] memory path; - uint32 level = ancestorLevel(position); - bytes32 targetNodeValue = getTargetNodeValue(position, level); - for (uint32 i = 0; i < 32; i++) { - if (i == level) { - path[31 - i] = targetNodeValue; - } else { - if (index % 2 == 0) { - path[31 - i] = tree[index - 1]; - } else { - path[31 - i] = tree[index + 1] == 0 ? zeroes[i] : tree[index + 1]; - } - } - index = (index - 1) / 2; - } - return (latestRoot, path); - } - - //position: index of leafnode, start from 0 - function getPathByValueIsZero(uint256 position) public view returns (bytes32, bytes32[32] memory) { - require(position >= 0, "Position should be non-negative!"); - require(position < leafCount, "Position should be smaller than leafCount!"); - uint256 index = position + 2 ** 32 - 1; - bytes32[32] memory path; - uint32 level = ancestorLevel(position); - bytes32 targetNodeValue = getTargetNodeValueByValueIsZero(position, level); - for (uint32 i = 0; i < 32; i++) { - if (i == level) { - path[31 - i] = targetNodeValue; - } else { - if (index % 2 == 0) { - path[31 - i] = tree[index - 1]; - } else { - path[31 - i] = tree[index + 1] == 0 ? zeroes[i] : tree[index + 1]; - } - } - index = (index - 1) / 2; - } - return (latestRoot, path); - } - - function ancestorLevel(uint256 leafIndex) private view returns (uint32) { - uint256 nodeIndex1 = leafIndex + 2 ** 32 - 1; - uint256 nodeIndex2 = leafCount + 2 ** 32 - 2; - uint32 level = 0; - while (((nodeIndex1 - 1) / 2) != ((nodeIndex2 - 1) / 2)) { - nodeIndex1 = (nodeIndex1 - 1) / 2; - nodeIndex2 = (nodeIndex2 - 1) / 2; - level = level + 1; - } - return level; - } - - function getTargetNodeValue(uint256 leafIndex, uint32 level) private view returns (bytes32) { - bytes32 left; - bytes32 right; - uint256 index = leafIndex + 2 ** 32 - 1; - uint256 nodeIndex = leafCount + 2 ** 32 - 2; - bytes32 nodeValue = tree[nodeIndex]; - if (level == 0) { - if (index < nodeIndex) { - return nodeValue; - } - if (index == nodeIndex) { - if (index % 2 == 0) { - return tree[index - 1]; - } else { - return zeroes[0]; - } - } - } - for (uint32 i = 0; i < level; i++) { - if (nodeIndex % 2 == 0) { - left = tree[nodeIndex - 1]; - right = nodeValue; - } else { - left = nodeValue; - right = zeroes[i]; - } - nodeValue = pedersenHash(i, left, right); - nodeIndex = (nodeIndex - 1) / 2; - } - return nodeValue; - } - - function getTargetNodeValueByValueIsZero(uint256 leafIndex, uint32 level) private view returns (bytes32) { - bytes32 left; - bytes32 right; - uint256 index = leafIndex + 2 ** 32 - 1; - uint256 nodeIndex = leafCount + 2 ** 32 - 2; - bytes32 nodeValue = tree[nodeIndex]; - if (level == 0) { - if (index < nodeIndex) { - return nodeValue; - } - if (index == nodeIndex) { - if (index % 2 == 0) { - return tree[index - 1]; - } else { - return zeroes[0]; - } - } - } - for (uint32 i = 0; i < level; i++) { - if (nodeIndex % 2 == 0) { - left = tree[nodeIndex - 1]; - right = nodeValue; - } else { - left = nodeValue; - right = zeroes[i]; - } - left = bytes32(0x0); - right = bytes32(0x0); - nodeValue = pedersenHash(i, left, right); - nodeIndex = (nodeIndex - 1) / 2; - } - return nodeValue; - } - - function rawValueToValue(uint256 rawValue) private view returns (uint64) { - require(rawValue > 0, "Value must be positive!"); - require(rawValue.mod(scalingFactor) == 0, "Value must be integer multiples of scalingFactor!"); - uint256 value = rawValue.div(scalingFactor); - require(value < INT64_MAX); - return uint64(value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest1TestRequireContract.sol b/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest1TestRequireContract.sol deleted file mode 100644 index 16d01911d35..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest1TestRequireContract.sol +++ /dev/null @@ -1,15 +0,0 @@ - -contract TestThrowsContract{ - function testAssert() public { - assert(1==2); - } - function testRequire() public { - require(2==1); - } - function testRevert() public { - revert(); - } - //function testThrow(){ - // throw; - //} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest2TestThrowsContract.sol b/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest2TestThrowsContract.sol deleted file mode 100644 index 1ff73ad6460..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest2TestThrowsContract.sol +++ /dev/null @@ -1,15 +0,0 @@ - -contract TestThrowsContract{ - function testAssert() public { - assert(1==2); - } - function testRequire() public { - require(2==1); - } - function testRevert() public { - revert(); - } - // function testThrow() public { - // throw; - //} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest3TestRevertContract.sol b/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest3TestRevertContract.sol deleted file mode 100644 index b42a8c3fb23..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest3TestRevertContract.sol +++ /dev/null @@ -1,15 +0,0 @@ - -contract TestThrowsContract{ - function testAssert() public { - assert(1==2); - } - function testRequire() public { - require(2==1); - } - function testRevert() public { - revert(); - } - // function testThrow(){ - // throw; - // } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest4noPayableContract.sol b/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest4noPayableContract.sol deleted file mode 100644 index 35f89631e7d..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest4noPayableContract.sol +++ /dev/null @@ -1,8 +0,0 @@ - - -contract noPayableContract { - -function noPayable() public payable returns (uint){ -return msg.value; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest4noPayableContract_1.sol b/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest4noPayableContract_1.sol deleted file mode 100644 index 5b6dd509f6f..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest4noPayableContract_1.sol +++ /dev/null @@ -1,8 +0,0 @@ - - -contract noPayableContract { - -function noPayable() public returns (uint){ -return msg.value; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest5noPayableConstructor.sol b/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest5noPayableConstructor.sol deleted file mode 100644 index 097594ab7c9..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest5noPayableConstructor.sol +++ /dev/null @@ -1,11 +0,0 @@ - - -contract MyContract { - uint money; - - //function MyContract(uint _money) { - constructor(uint _money) public payable{ - require(msg.value >= _money); - money = _money; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest5noPayableConstructor_1.sol b/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest5noPayableConstructor_1.sol deleted file mode 100644 index 5008ec5c9bf..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest5noPayableConstructor_1.sol +++ /dev/null @@ -1,11 +0,0 @@ - - -contract MyContract { - uint money; - - //function MyContract(uint _money) { - constructor(uint _money) public { - require(msg.value >= _money); - money = _money; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest6transferTestContract.sol b/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest6transferTestContract.sol deleted file mode 100644 index 4f171aebb9a..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest6transferTestContract.sol +++ /dev/null @@ -1,8 +0,0 @@ - - -contract transferTestContract { - function tranferTest(address payable addr) public payable{ - addr.transfer(10); - - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest7payableFallbakContract.sol b/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest7payableFallbakContract.sol deleted file mode 100644 index 534726cb1b4..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest7payableFallbakContract.sol +++ /dev/null @@ -1,14 +0,0 @@ - - -contract Test { - fallback() external { x = 1; } - uint x; -} - - -contract Caller { - function callTest(Test test) public { - //test.call(0xabcdef01); // hash does not exist - address(test).call(abi.encode(0xabcdef01)); // hash does not exist - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest8newContractGasNoenough.sol b/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest8newContractGasNoenough.sol deleted file mode 100644 index b8743e8231a..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest8newContractGasNoenough.sol +++ /dev/null @@ -1,19 +0,0 @@ - - -contract Account{ - uint256 public accId; - - // function Account(uint accountId) payable{ - constructor(uint accountId) payable public { - accId = accountId; - } -} - -contract Initialize{ - // Account public account = new Account(10); - - function newAccount() public { - Account account = new Account(1); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest9MessageUsedErrorFeed.sol b/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest9MessageUsedErrorFeed.sol deleted file mode 100644 index 18142d20ee8..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontest9MessageUsedErrorFeed.sol +++ /dev/null @@ -1,18 +0,0 @@ - - -contract MathedFeed { - - function divideMathed() public returns (uint ret) { - uint x=1; - uint y=0; - return x/y; - } -} - - -contract MathedUseContract { - - function MathedUse(address addr) public returns (uint) { - return MathedFeed(addr).divideMathed(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontestFunctionUsedErrorFeed.sol b/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontestFunctionUsedErrorFeed.sol deleted file mode 100644 index 64243dffd7c..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/requireExceptiontestFunctionUsedErrorFeed.sol +++ /dev/null @@ -1,17 +0,0 @@ - - -contract MessageFeed { - - function mValue() payable public returns (uint ret) { - return msg.value; - } -} - -contract MessageUseContract { - function inputValue() payable public returns (uint){ - return msg.value; - } - function messageUse(address addr) payable public returns (uint) { - return MessageFeed(addr).mValue{value:1}(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/selector.sol b/framework/src/test/resources/soliditycode_0.7.6/selector.sol deleted file mode 100644 index 5805a6e8d22..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/selector.sol +++ /dev/null @@ -1,21 +0,0 @@ - - -library A { - function getBalance(address) public view returns (uint256) { - return address(this).balance; - } - - function getamount(address) external view returns (uint256) { - return address(this).balance; - } -} - -contract testSelector { - using A for address; - - - function getselector2() public view returns (bytes4, bytes4) { - return (A.getBalance.selector, A.getamount.selector); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/slotAndOffsetNewGrammer.sol b/framework/src/test/resources/soliditycode_0.7.6/slotAndOffsetNewGrammer.sol deleted file mode 100644 index b4c2b0ed516..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/slotAndOffsetNewGrammer.sol +++ /dev/null @@ -1,32 +0,0 @@ -contract A { - uint b; - uint a; - uint c; - uint d; - uint e; - - function getA() external returns(uint,uint) { - uint slot; - uint offset; - assembly { -// old grammer -// slot := a_slot -// offset := a_offset - slot := a.slot - offset := a.offset - } - return (slot, offset); - } - - function getE() external returns(uint,uint) { - uint slot; - uint offset; - assembly { -// slot := e_slot -// offset := e_offset - slot := e.slot - offset := e.offset - } - return (slot, offset); - } -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/stackContract001.sol b/framework/src/test/resources/soliditycode_0.7.6/stackContract001.sol deleted file mode 100644 index c2e8f2f7611..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/stackContract001.sol +++ /dev/null @@ -1,61 +0,0 @@ - - -contract A{ - event log(uint256); - constructor() payable public{ - emit log(withdrawreward()); - emit log(address(this).rewardbalance); - } - function withdrawRewardTest() public returns (uint256){ - return withdrawreward(); - } - - function test() public{ - emit log(123); - } -} - -contract B{ - event log(uint256); - constructor() payable public{ - emit log(withdrawreward()); - emit log(address(this).rewardbalance); - } - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - function UnStake() public returns (bool result){ - return unstake(); - } - function SelfdestructTest(address payable target) public{ - selfdestruct(target); - } - function rewardBalance(address addr) public view returns (uint256){ - return addr.rewardbalance; - } - - function nullAddressTest() public view returns (uint256) { - return address(0x0).rewardbalance; - } - - function localContractAddrTest() public view returns (uint256) { - address payable localContract = address(uint160(address(this))); - return localContract.rewardbalance; - } - - function withdrawRewardTest() public returns (uint256){ - return withdrawreward(); - } - - function contractBWithdrawRewardTest(address contractB) public returns (uint) { - return B(contractB).withdrawRewardTest(); - } - - function createA() public returns (address){ - return address(new A()); - } - - function callA(address Addr) public{ - A(Addr).test(); - } -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/stackSuicide001.sol b/framework/src/test/resources/soliditycode_0.7.6/stackSuicide001.sol deleted file mode 100644 index d1fc520ddb2..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/stackSuicide001.sol +++ /dev/null @@ -1,84 +0,0 @@ - -contract testStakeSuicide{ - B b; - constructor() payable public{} - function deployB() payable public returns (B addrB){ - b = (new B).value(1000000000)(); - return b; - } - function SelfdestructTest(address payable target) public{ - selfdestruct(target); - } - function SelfdestructTest2(address sr, uint256 amount, address payable target) public{ - stake(sr, amount); - selfdestruct(target); - } - function Stake(address sr, uint256 amount) public payable returns (bool result){ - return stake(sr, amount); - } - function Stake2(address sr, uint256 amount) public returns (bool result){ - stake(sr, amount); - return stake(sr, amount); - } - function UnStake() public returns (bool result){ - return unstake(); - } - function UnStake2() public returns (bool result){ - unstake(); - return unstake(); - } - function WithdrawReward() public { - withdrawreward(); - } - function RewardBalance(address addr) view public returns (uint256 balance) { - return addr.rewardbalance; - } - function revertTest1(address sr, uint256 amount, address payable transferAddr) public{ - transferAddr.transfer(1000000); - stake(sr, amount); - transferAddr.transfer(2000000); - stake(sr, 1000000000000000);//stake more than balance to fail - transferAddr.transfer(4000000); - } - function revertTest2(address payable transferAddr) public{ - transferAddr.transfer(1000000); - unstake(); - transferAddr.transfer(2000000); - unstake();//unstake twice to fail - transferAddr.transfer(4000000); - } - - function BStake(address sr, uint256 amount) public returns (bool result){ - return b.Stake(sr, amount); - } - function BUnStake() public returns (bool result){ - return b.UnStake(); - } - function transfer(address payable add,uint256 num) public { - return add.transfer(num); - } -} - -contract B{ - constructor() payable public{} - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - function UnStake() public returns (bool result){ - return unstake(); - } - function SelfdestructTest(address payable target) public{ - selfdestruct(target); - } - - function deploy(bytes memory code, uint256 salt) public returns(address) { - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - return addr; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/stateVariableShadowing.sol b/framework/src/test/resources/soliditycode_0.7.6/stateVariableShadowing.sol deleted file mode 100644 index a9109ee296c..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/stateVariableShadowing.sol +++ /dev/null @@ -1,21 +0,0 @@ -contract test { -// uint public x; -// function setValue1(uint _x) public returns (uint){ -// x = _x; -// return x; -// } - uint public y; - function setValue3(uint _x) public returns (uint){ - y = _x; - return y; - } -} - -contract stateVariableShadowing is test { - uint public x; - function setValue2(uint _x) public returns (uint){ - x = _x; - return x; - } -} - diff --git a/framework/src/test/resources/soliditycode_0.7.6/stringSplit.sol b/framework/src/test/resources/soliditycode_0.7.6/stringSplit.sol deleted file mode 100644 index 84231f2d1fe..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/stringSplit.sol +++ /dev/null @@ -1,45 +0,0 @@ - - -contract testStringSplit { -string s1 = "s""1""2"",./"; -string s2 = "s123?\\'."; -string s3 = hex"41"hex"42"; -string s4 = hex"4142"; - -function getS1() public view returns (string memory) { -return s1; -} - -function getS1N1() public pure returns (string memory) { -string memory n1 = "s""1""2"",./"; -return n1; -} - -function getS2() public view returns (string memory) { -return s2; -} - -function getS2N2() public pure returns (string memory) { -string memory n2 = "s123?\'."; -return n2; -} - -function getS3() public view returns (string memory) { -return s3; -} - -function getS3N3() public pure returns (string memory) { -string memory n3 = hex"41"hex"42"; -return n3; -} - -function getS4() public view returns (string memory) { -return s4; -} - -function getS4N4() public pure returns (string memory) { -string memory n4 = hex"4142"; -return n4; -} - -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/suicide001.sol b/framework/src/test/resources/soliditycode_0.7.6/suicide001.sol deleted file mode 100644 index 241a406d6a2..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/suicide001.sol +++ /dev/null @@ -1,32 +0,0 @@ -contract factory { - constructor() payable public { - } - - function create1() payable public returns (address){ - Caller add = (new Caller){value:0}(); - return address(add); - } - - function kill() payable public{ - selfdestruct(msg.sender); - } - - function create2(bytes memory code, uint256 salt) public returns(address){ - Caller addr; - Caller addr1; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - return address(addr); - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/suicide002.sol b/framework/src/test/resources/soliditycode_0.7.6/suicide002.sol deleted file mode 100644 index 160ab64f320..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/suicide002.sol +++ /dev/null @@ -1,43 +0,0 @@ -contract Factory { - uint256 public num; - event Deployed(address addr, uint256 salt, address sender); - constructor() public { - } - function deploy(bytes memory code, uint256 salt) public returns(address){ - TestConstract addr; - TestConstract addr1; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - - addr.testSuicideNonexistentTarget(msg.sender); - addr.set(); - - assembly { - addr1 := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(address(addr), salt, msg.sender); - return address(addr); - } -} - - - -contract TestConstract { - uint public i=1; - constructor () public { - } - - function set() public{ - i=9; - } - function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/testOutOfMem.sol b/framework/src/test/resources/soliditycode_0.7.6/testOutOfMem.sol deleted file mode 100644 index 8d285b28b7d..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/testOutOfMem.sol +++ /dev/null @@ -1,7 +0,0 @@ -contract Test { - function testOutOfMem(uint256 x) public returns(bytes32 r) { - uint[] memory memVar; - memVar = new uint[](x); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/testStakeSuicide.sol b/framework/src/test/resources/soliditycode_0.7.6/testStakeSuicide.sol deleted file mode 100644 index 3342a5607f7..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/testStakeSuicide.sol +++ /dev/null @@ -1,71 +0,0 @@ - -contract testStakeSuicide{ - B b; - constructor() payable public{} - function deployB() payable public returns (B addrB){ - b = (new B).value(1000000000)(); - return b; - } - function SelfdestructTest(address payable target) public{ - selfdestruct(target); - } - function SelfdestructTest2(address sr, uint256 amount, address payable target) public{ - stake(sr, amount); - selfdestruct(target); - } - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - function Stake2(address sr, uint256 amount) public returns (bool result){ - stake(sr, amount); - return stake(sr, amount); - } - function UnStake() public returns (bool result){ - return unstake(); - } - function UnStake2() public returns (bool result){ - unstake(); - return unstake(); - } - function WithdrawReward() public { - withdrawreward(); - } - function RewardBalance(address addr) view public returns (uint256 balance) { - return addr.rewardbalance; - } - function revertTest1(address sr, uint256 amount, address payable transferAddr) public{ - transferAddr.transfer(1000000); - stake(sr, amount); - transferAddr.transfer(2000000); - stake(sr, 1000000000000000);//stake more than balance to fail - transferAddr.transfer(4000000); - } - function revertTest2(address payable transferAddr) public{ - transferAddr.transfer(1000000); - unstake(); - transferAddr.transfer(2000000); - unstake();//unstake twice to fail - transferAddr.transfer(4000000); - } - function BStake(address sr, uint256 amount) public returns (bool result){ - return b.Stake(sr, amount); - } - function BUnStake() public returns (bool result){ - return b.UnStake(); - } - function BSelfdestructTest(address payable target) public{ - b.SelfdestructTest(target); - } -} -contract B{ - constructor() payable public{} - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - function UnStake() public returns (bool result){ - return unstake(); - } - function SelfdestructTest(address payable target) public{ - selfdestruct(target); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/tryCatch001.sol b/framework/src/test/resources/soliditycode_0.7.6/tryCatch001.sol deleted file mode 100644 index 283db92e159..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/tryCatch001.sol +++ /dev/null @@ -1,105 +0,0 @@ - - -enum ErrorType { - Revert_Error, //0 - RevertWithMsg_Error, //1 - Require_Error, //2 - RequirewithMsg_Error, //3 - Assert_Error, //4 - Tansfer_Error, //5 - Send_Error, //6 - Math_Error, //7 - ArrayOverFlow_Error //8 -} -contract errorContract { - uint256[] arraryUint ; - - function errorSwitch(uint256 errorType) public returns(string memory) { - if (ErrorType(errorType) == ErrorType.Revert_Error){ - revert(); - } else if (ErrorType(errorType) == ErrorType.RevertWithMsg_Error){ - revert("Revert Msg."); - } else if (ErrorType(errorType) == ErrorType.Require_Error) { - require(0>1); - } else if (ErrorType(errorType) == ErrorType.RequirewithMsg_Error) { - require(0>1,"Require Msg."); - } else if (ErrorType(errorType) == ErrorType.Assert_Error) { - assert(1<0); - } else if (ErrorType(errorType) == ErrorType.Tansfer_Error) { - payable(msg.sender).transfer(1); - } else if (ErrorType(errorType) == ErrorType.Send_Error) { - payable(msg.sender).send(1); - } else if (ErrorType(errorType) == ErrorType.Math_Error) { - uint256 a = 1; - uint256 b = 0; - uint256 n = a / b; - } else if (ErrorType(errorType) == ErrorType.ArrayOverFlow_Error) { - arraryUint.pop(); - } - return "success"; - - } - - function callFun(string memory functionStr, string memory argsStr) public{ - address(this).call(abi.encodeWithSignature(functionStr, argsStr)); - } - -} - -contract NewContract { - uint256[] arraryUint ; - - constructor(uint256 errorType) public payable{ - if (ErrorType(errorType) == ErrorType.Revert_Error){ - revert(); - } else if (ErrorType(errorType) == ErrorType.RevertWithMsg_Error){ - revert("Revert Msg."); - } else if (ErrorType(errorType) == ErrorType.Require_Error) { - require(0>1); - } else if (ErrorType(errorType) == ErrorType.RequirewithMsg_Error) { - require(0>1,"Require Msg."); - } else if (ErrorType(errorType) == ErrorType.Assert_Error) { - assert(1<0); - } else if (ErrorType(errorType) == ErrorType.Tansfer_Error) { - payable(msg.sender).transfer(1); - } else if (ErrorType(errorType) == ErrorType.Send_Error) { - payable(msg.sender).send(1); - } else if (ErrorType(errorType) == ErrorType.Math_Error) { - uint256 a = 1; - uint256 b = 0; - uint256 n = a / b; - } else if (ErrorType(errorType) == ErrorType.ArrayOverFlow_Error) { - arraryUint.pop(); - } - } -} - -contract tryTest { - function getData(errorContract inter, string memory functionStr, string memory argsStr) public payable returns(string memory) { - try inter.callFun(functionStr,argsStr) { - return "123"; - } catch Error(string memory errorMsg/* 出错原因 */) { - return errorMsg; - } catch (bytes memory) { - return "3"; - } - } - - function getErrorSwitch(errorContract add, uint256 errorType ) public payable returns(string memory) { - try add.errorSwitch(errorType) returns (string memory Msg) { - return Msg; - } catch Error(string memory errorMsg/* 出错原因 */) { - return errorMsg; - } catch (bytes memory) { - return "NoErrorMsg"; - } - } - - function catchNewErrorSwitch(uint256 errorType) public returns (address nc){ - try new NewContract(errorType) returns (NewContract nc){ - return address(nc); - }catch { - return address(0x00); - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue001.sol b/framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue001.sol deleted file mode 100644 index 5388ed68473..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue001.sol +++ /dev/null @@ -1,25 +0,0 @@ - -contract tvmAssetIssue001 { - constructor() payable public{} - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - return assetissue(name, abbr, totalSupply, precision); - } - - function updateAsset(trcToken tokenId, string memory url, string memory desc) public returns (bool) { - return updateasset(tokenId, bytes(url), bytes(desc)); - } - - function updateOtherAccountAsset(string memory url, string memory desc) public returns (bool) { - trcToken tokenId = trcToken(1000004); - return updateasset(tokenId, bytes(url), bytes(desc)); - } - - function updateAssetOnBytes(trcToken tokenId, bytes memory url, bytes memory desc) public returns (bool) { - return updateasset(tokenId, url, desc); - } - - function transferToken(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue002.sol b/framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue002.sol deleted file mode 100644 index 87c1206b778..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue002.sol +++ /dev/null @@ -1,15 +0,0 @@ - - -contract tvmAssetIssue002 { - constructor() payable public{} - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - assetissue(name, abbr, totalSupply, precision); - return assetissue(name, abbr, totalSupply, precision); - } - - function updateAsset(trcToken tokenId, string memory url1, string memory desc1, string memory url2, string memory desc2) public returns (bool) { - updateasset(tokenId, bytes(url1), bytes(desc1)); - return updateasset(tokenId, bytes(url2), bytes(desc2)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue003.sol b/framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue003.sol deleted file mode 100644 index f5ce5e0dc3e..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue003.sol +++ /dev/null @@ -1,23 +0,0 @@ - - -contract tvmAssetIssue003 { - constructor() payable public{} - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - return assetissue(name, abbr, totalSupply, precision); - } - - function tokenIssueAndTransfer(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision, address addr) public { - address payable newaddress = address(uint160(addr)); - newaddress.transfer(100000000); - assetissue(name, abbr, totalSupply, precision); - newaddress.transfer(100000000); - } - - function updateAssetAndTransfer(trcToken tokenId, string memory url, string memory desc, address addr) public { - address payable newaddress = address(uint160(addr)); - newaddress.transfer(100000000); - updateasset(tokenId, bytes(url), bytes(desc)); - newaddress.transfer(100000000); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue004.sol b/framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue004.sol deleted file mode 100644 index c8332de8f45..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue004.sol +++ /dev/null @@ -1,39 +0,0 @@ - - -contract A { - - constructor() payable public{} - fallback() payable external {} - - function tokenIssueA(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint){ - return assetissue(name, abbr, totalSupply, precision); - } - - function updateAssetA(trcToken tokenId, string memory url, string memory desc) public returns (bool) { - return updateasset(tokenId, bytes(url), bytes(desc)); - } - - function transferToken(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } -} - -contract tvmAssetIssue004 { - - A a; - - constructor() payable public{} - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - return a.tokenIssueA(name, abbr, totalSupply, precision); - } - - function updateAsset(trcToken tokenId, string memory url, string memory desc) public returns (bool) { - return a.updateAssetA(tokenId, url, desc); - } - - function getContractAddress() public payable returns (address) { - a = (new A).value(1024000000)(); - return address(a); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue005.sol b/framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue005.sol deleted file mode 100644 index 8c36d050ff8..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/tvmAssetIssue005.sol +++ /dev/null @@ -1,45 +0,0 @@ - - -contract tvmAssetIssue005 { - constructor() payable public{} - - fallback() external payable { - } - - function tokenIssue(bytes32 name, bytes32 abbr, uint64 totalSupply, uint8 precision) public returns (uint) { - return assetissue(name, abbr, totalSupply, precision); - } - - function updateAsset(trcToken tokenId, string memory url, string memory desc) public returns (bool) { - return updateasset(tokenId, bytes(url), bytes(desc)); - } - - function updateAssetOnBytes(trcToken tokenId, bytes memory url, bytes memory desc) public returns (bool) { - return updateasset(tokenId, url, desc); - } - - function transferToken(address payable toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - - function SelfdestructTest(address payable target) public { - selfdestruct(target); - } -} - -contract B { - event Deployed(address addr, uint256 salt); - - function deploy(uint256 salt) public returns (address) { - address addr; - bytes memory code = type(tvmAssetIssue005).creationCode; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt); - return addr; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/typeName.sol b/framework/src/test/resources/soliditycode_0.7.6/typeName.sol deleted file mode 100644 index 5b44abd1bbb..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/typeName.sol +++ /dev/null @@ -1,5 +0,0 @@ -contract TypeName { - function testTypeName() public returns (string memory){ - return type(TypeName).name; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/unStake001.sol b/framework/src/test/resources/soliditycode_0.7.6/unStake001.sol deleted file mode 100644 index 03734fecfa5..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/unStake001.sol +++ /dev/null @@ -1,90 +0,0 @@ - - -contract unStakeTest { - B b; - constructor() payable public{} - function deployB() payable public returns (B addrB){ - b = (new B).value(1000000000)(); - return b; - } - - function selfdestructTest(address payable target) public { - selfdestruct(target); - } - - function selfdestructTest2(address sr, uint256 amount, address payable target) public { - stake(sr, amount); - selfdestruct(target); - } - - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - - function stake2(address sr, uint256 amount) public returns (bool result){ - stake(sr, amount); - return stake(sr, amount); - } - - function unStake() public returns (bool result){ - return unstake(); - } - - function unStake2() public returns (bool result){ - unstake(); - return unstake(); - } - - function withdrawReward() public returns (uint256 amount) { - return withdrawreward(); - } - - function rewardBalance(address addr) view public returns (uint256 balance) { - return addr.rewardbalance; - } - - function revertTest1(address sr, uint256 amount, address payable transferAddr) public { - transferAddr.transfer(1000000); - stake(sr, amount); - transferAddr.transfer(2000000); - stake(sr, 1000000000000000); - //stake more than balance to fail - transferAddr.transfer(4000000); - } - - function revertTest2(address payable transferAddr) public { - transferAddr.transfer(1000000); - unstake(); - transferAddr.transfer(2000000); - unstake(); - //unstake twice to fail - transferAddr.transfer(4000000); - } - - function BStake(address sr, uint256 amount) public returns (bool result){ - return b.Stake(sr, amount); - } - - function BUnStake() public returns (bool result){ - return b.UnStake(); - } - - function BSelfdestructTest(address payable target) public { - b.SelfdestructTest(target); - } -} - -contract B { - constructor() payable public{} - function Stake(address sr, uint256 amount) public returns (bool result){ - return stake(sr, amount); - } - - function UnStake() public returns (bool result){ - return unstake(); - } - - function SelfdestructTest(address payable target) public { - selfdestruct(target); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/validatemultisign001.sol b/framework/src/test/resources/soliditycode_0.7.6/validatemultisign001.sol deleted file mode 100644 index cc0a742d0c5..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/validatemultisign001.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma experimental ABIEncoderV2; - -contract validatemultisignTest { - function testmulti(address a, uint256 perid, bytes32 hash, bytes[] memory signatures) public returns (bool){ - return validatemultisign(a, perid, hash, signatures); - } - - function testbatch(bytes32 hash, bytes[] memory signatures, address[] memory addresses) public returns (bytes32){ - return batchvalidatesign(hash, signatures, addresses); - } - - function testMultiPrecompileContract(bytes memory data) public returns(bool, bytes memory){ - return address(0xa).delegatecall(data); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/verifyTransferProof001.sol b/framework/src/test/resources/soliditycode_0.7.6/verifyTransferProof001.sol deleted file mode 100644 index 587b4defd10..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/verifyTransferProof001.sol +++ /dev/null @@ -1,15 +0,0 @@ -contract verifyTransferProofTest { - - function test1() public returns (bool, bytes memory){ - bytes memory empty = ""; - return address(0x1000002).delegatecall(empty); - } - - function test2(bytes memory data) public returns (bool, bytes memory){ - return address(0x1000002).delegatecall(data); - } - - function test3(bytes32[10][] memory input, bytes32[2][] memory spendAuthoritySignature, bytes32[9][] memory output, bytes32[2] memory bindingSignature, bytes32 signHash, uint64 valueBalance, bytes32[33] memory frontier, uint256 leafCount) public returns (bytes32[] memory){ - return verifyTransferProof(input, spendAuthoritySignature, output, bindingSignature, signHash, valueBalance, frontier, leafCount); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_0.7.6/virtual001.sol b/framework/src/test/resources/soliditycode_0.7.6/virtual001.sol deleted file mode 100644 index f7967626764..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/virtual001.sol +++ /dev/null @@ -1,19 +0,0 @@ -//pragma solidity ^0.6.0; -interface X { - function setValue(uint _x) external; -} -abstract contract Y { - function setBool(bool _y) external virtual ; -} -contract Y2 { - string public z; - function setString(string calldata _z) external virtual { z = "123"; } -} - -contract Z is X,Y,Y2 { - uint public x; - bool public y; - function setValue(uint _x) external override { x = _x; } - function setBool(bool _y) external override { y = _y; } - function setString(string calldata _z) external override { z = _z; } -} diff --git a/framework/src/test/resources/soliditycode_0.7.6/walletTestMutiSign004.sol b/framework/src/test/resources/soliditycode_0.7.6/walletTestMutiSign004.sol deleted file mode 100644 index 7b943aee5c1..00000000000 --- a/framework/src/test/resources/soliditycode_0.7.6/walletTestMutiSign004.sol +++ /dev/null @@ -1,51 +0,0 @@ -contract timeoutTest { - string public iarray1; - // cpu - function oneCpu() public { - require(1==1); - } - - function storage8Char() public { - iarray1 = "12345678"; - } - - function testUseCpu(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - } - return count; - } - - - uint256[] public iarray; - uint public calculatedFibNumber; - mapping(address=>mapping(address=>uint256)) public m; - - function testUseStorage(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - iarray.push(i); - } - return count; - } - - // stack - //uint n = 0; - uint yy = 0; - function test() public { - //n += 1; - yy += 1; - test(); - } - - function setFibonacci(uint n) public returns (uint256){ - calculatedFibNumber = fibonacci(n); - return calculatedFibNumber; - } - - function fibonacci(uint n) internal returns (uint) { - return fibonacci(n - 1) + fibonacci(n - 2); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/TransferFailed001.sol b/framework/src/test/resources/soliditycode_v0.4.25/TransferFailed001.sol deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/framework/src/test/resources/soliditycode_v0.4.25/TransferFailed005.sol b/framework/src/test/resources/soliditycode_v0.4.25/TransferFailed005.sol deleted file mode 100644 index d3179a30191..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/TransferFailed005.sol +++ /dev/null @@ -1,106 +0,0 @@ -contract EnergyOfTransferFailedTest { - constructor() payable public { - - } - function testTransferTokenCompiledLongMax() payable public{ - address(0x1).transferToken(1,9223372036855775827); - } - - function testTransferTokenCompiledLongMin() payable public{ - //address(0x1).transferToken(1,-9223372036855775828); - } - - function testTransferTokenCompiledLongMin1() payable public{ - address(0x1).tokenBalance(trcToken(-9223372036855775828)); - } - - function testTransferTokenCompiledLongMax1() payable public{ - address(0x1).tokenBalance(trcToken(9223372036855775827)); - } - - // InsufficientBalance - function testTransferTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.transfer(i); - } - - function testSendTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.send(i); - } - - function testTransferTokenInsufficientBalance(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - - function testCallTrxInsufficientBalance(uint256 i,address caller) public returns (bool){ - return caller.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testCreateTrxInsufficientBalance(uint256 i) payable public { - (new Caller).value(i)(); - } - - // NonexistentTarget - - function testSendTrxNonexistentTarget(uint256 i,address nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.send(i); - } - - function testTransferTrxNonexistentTarget(uint256 i,address nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.transfer(i); - } - - function testTransferTokenNonexistentTarget(uint256 i,address nonexistentTarget, trcToken tokenId) payable public { - require(address(this).balance >= i); - nonexistentTarget.transferToken(i, tokenId); - } - - function testCallTrxNonexistentTarget(uint256 i,address nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testSuicideNonexistentTarget(address nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } - - // target is self - function testTransferTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address self = address(uint160(address(this))); - self.transfer(i); - } - - function testSendTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address self = address(uint160(address(this))); - self.send(i); - } - - function testTransferTokenSelf(uint256 i,trcToken tokenId) payable public{ - require(address(this).balance >= i); - address self = address(uint160(address(this))); - self.transferToken(i, tokenId); - } - - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(10, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256 ){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/TransferFailed007.sol b/framework/src/test/resources/soliditycode_v0.4.25/TransferFailed007.sol deleted file mode 100644 index ffd6f10c486..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/TransferFailed007.sol +++ /dev/null @@ -1,90 +0,0 @@ -contract EnergyOfTransferFailedTest { - constructor() payable public { - - } - // InsufficientBalance - function testTransferTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.transfer(i); - } - - function testSendTrxInsufficientBalance(uint256 i) payable public{ - msg.sender.send(i); - } - - function testTransferTokenInsufficientBalance(uint256 i,trcToken tokenId) payable public{ - msg.sender.transferToken(i, tokenId); - } - - function testCallTrxInsufficientBalance(uint256 i,address caller) public returns (bool){ - return caller.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testCreateTrxInsufficientBalance(uint256 i) payable public { - (new Caller).value(i)(); - } - - // NonexistentTarget - - function testSendTrxNonexistentTarget(uint256 i,address nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.send(i); - } - - function testTransferTrxNonexistentTarget(uint256 i,address nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.transfer(i); - } - - function testTransferTokenNonexistentTarget(uint256 i,address nonexistentTarget, trcToken tokenId) payable public { - require(address(this).balance >= i); - nonexistentTarget.transferToken(i, tokenId); - } - - function testCallTrxNonexistentTarget(uint256 i,address nonexistentTarget) payable public { - require(address(this).balance >= i); - nonexistentTarget.call.value(i)(abi.encodeWithSignature("test()")); - } - - function testSuicideNonexistentTarget(address nonexistentTarget) payable public { - selfdestruct(nonexistentTarget); - } - - // target is self - function testTransferTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address self = address(uint160(address(this))); - self.transfer(i); - } - - function testSendTrxSelf(uint256 i) payable public{ - require(address(this).balance >= i); - address self = address(uint160(address(this))); - self.send(i); - } - - function testTransferTokenSelf(uint256 i,trcToken tokenId) payable public{ - require(address(this).balance >= i); - address self = address(uint160(address(this))); - self.transferToken(i, tokenId); - } - - event Deployed(address addr, uint256 salt, address sender); - function deploy(bytes memory code, uint256 salt) public returns(address){ - address addr; - assembly { - addr := create2(10, add(code, 0x20), mload(code), salt) - //if iszero(extcodesize(addr)) { - // revert(0, 0) - //} - } - //emit Deployed(addr, salt, msg.sender); - return addr; - } -} - - - -contract Caller { - constructor() payable public {} - function test() payable public returns (uint256 ){return 1;} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/addMsg001Nonpayable.sol b/framework/src/test/resources/soliditycode_v0.4.25/addMsg001Nonpayable.sol deleted file mode 100644 index 7b124f0e870..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/addMsg001Nonpayable.sol +++ /dev/null @@ -1,20 +0,0 @@ -//pragma solidity ^0.4.24; - -contract IllegalDecorate { - -event log(uint256); -constructor() payable public{} - -function() payable public{} - -function transferTokenWithOutPayable(address toAddress, uint256 tokenValue) public { -// function transferTokenWithValue(address toAddress, uint256 tokenValue) payable public { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); - -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/addMsg002View.sol b/framework/src/test/resources/soliditycode_v0.4.25/addMsg002View.sol deleted file mode 100644 index 97c07ace501..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/addMsg002View.sol +++ /dev/null @@ -1,20 +0,0 @@ -//pragma solidity ^0.4.24; - -contract IllegalDecorate { - -constructor() payable public{} - -function() payable public{} - -event log(uint256); - -function transferTokenWithView(address toAddress, uint256 tokenValue) public view { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} - diff --git a/framework/src/test/resources/soliditycode_v0.4.25/addMsg003Constant.sol b/framework/src/test/resources/soliditycode_v0.4.25/addMsg003Constant.sol deleted file mode 100644 index 4cc69e05c90..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/addMsg003Constant.sol +++ /dev/null @@ -1,19 +0,0 @@ -//pragma solidity ^0.4.24; - -contract IllegalDecorate { - -constructor() payable public{} - -function() payable public{} - -event log(uint256); - -function transferTokenWithConstant(address toAddress, uint256 tokenValue) public constant { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/addMsg004Pure.sol b/framework/src/test/resources/soliditycode_v0.4.25/addMsg004Pure.sol deleted file mode 100644 index 886e5d2ea0f..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/addMsg004Pure.sol +++ /dev/null @@ -1,19 +0,0 @@ -//pragma solidity ^0.4.24; - -contract IllegalDecorate { - -constructor() payable public{} - -function() payable public{} - -event log(uint256); - -function transferTokenWithPure(address toAddress, uint256 tokenValue) public pure { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/addTransferToken001Nonpayable.sol b/framework/src/test/resources/soliditycode_v0.4.25/addTransferToken001Nonpayable.sol deleted file mode 100644 index b6c69fca887..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/addTransferToken001Nonpayable.sol +++ /dev/null @@ -1,15 +0,0 @@ -//pragma solidity ^0.4.24; - - contract IllegalDecorate { - - constructor() payable public{} - - function() payable public{} - - function transferTokenWithOutPayable(address toAddress, uint256 tokenValue)public { - - toAddress.transferToken(tokenValue, 0x6e6d62); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/addTransferToken002View.sol b/framework/src/test/resources/soliditycode_v0.4.25/addTransferToken002View.sol deleted file mode 100644 index fc390f12b53..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/addTransferToken002View.sol +++ /dev/null @@ -1,15 +0,0 @@ -//pragma solidity ^0.4.24; - -contract IllegalDecorate { - - constructor() payable public{} - - function() payable public{} - - function transferTokenWithView(address toAddress, uint256 tokenValue) public view { - - toAddress.transferToken(tokenValue, 0x6e6d62); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/addTransferToken003Constant.sol b/framework/src/test/resources/soliditycode_v0.4.25/addTransferToken003Constant.sol deleted file mode 100644 index 38c034f6bfb..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/addTransferToken003Constant.sol +++ /dev/null @@ -1,15 +0,0 @@ -//pragma solidity ^0.4.24; - -contract IllegalDecorate { - - constructor() payable public{} - - function() payable public{} - - function transferTokenWithConstant(address toAddress, uint256 tokenValue)public constant { - - toAddress.transferToken(tokenValue, 0x6e6d62); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/addTransferToken004Pure.sol b/framework/src/test/resources/soliditycode_v0.4.25/addTransferToken004Pure.sol deleted file mode 100644 index 085fd1bbbdb..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/addTransferToken004Pure.sol +++ /dev/null @@ -1,15 +0,0 @@ -//pragma solidity ^0.4.24; - -contract IllegalDecorate { - - constructor() payable public{} - - function() payable public{} - - function transferTokenWithPure(address toAddress, uint256 tokenValue) public pure { - - toAddress.transferToken(tokenValue, 0x6e6d62); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/addTrcToken001Assemble.sol b/framework/src/test/resources/soliditycode_v0.4.25/addTrcToken001Assemble.sol deleted file mode 100644 index a0015c9e75b..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/addTrcToken001Assemble.sol +++ /dev/null @@ -1,81 +0,0 @@ -//pragma solidity ^0.4.24; - -contract InAssemble { - -mapping(trcToken => uint256) tokenCnt; -mapping(uint256 => mapping(trcToken => trcToken)) cntTokenToken; -constructor () payable {} -function getBalance(address addr) constant returns(uint256 r) { -assembly{ -r := balance(addr) -} -} - -function getTokenBalanceConstant(address addr, trcToken tokenId) constant returns(uint256 r) { -assembly{ -r := tokenbalance(tokenId, addr) -} -} - -function getTokenBalance(address addr, trcToken tokenId) returns(uint256 r) { -assembly{ -r := tokenbalance(tokenId, addr) -} -} - -function transferTokenInAssembly(address addr, trcToken tokenId, uint256 tokenValue) payable { -bytes4 sig = bytes4(keccak256("()")); // function signature - -assembly { -let x := mload(0x40) // get empty storage location -mstore(x,sig) // 4 bytes - place signature in empty storage - -let ret := calltoken(gas, addr, tokenValue, tokenId, -x, // input -0x04, // input size = 4 bytes -x, // output stored at input location, save space -0x0 // output size = 0 bytes -) - -// let ret := calltoken(gas, addr, tokenValue, -// x, // input -// 0x04, // input size = 4 bytes -// x, // output stored at input location, save space -// 0x0 // output size = 0 bytes -// ) // ERROR - - -mstore(0x40, add(x,0x20)) // update free memory pointer -} - -// assembly { -// let x := mload(0x40) //Find empty storage location using "free memory pointer" -// mstore(x,sig) //Place signature at begining of empty storage -// mstore(add(x,0x04),a) //Place first argument directly next to signature -// mstore(add(x,0x24),b) //Place second argument next to first, padded to 32 bytes - -// let success := call( //This is the critical change (Pop the top stack value) -// 5000, //5k gas -// addr, //To addr -// 0, //No value -// x, /Inputs are stored at location x -// 0x44, //Inputs are 68 bytes long -// x, //Store output over input (saves space) -// 0x20) //Outputs are 32 bytes long - -// c := mload(x) //Assign output value to c -// mstore(0x40,add(x,0x44)) // Set storage pointer to empty space -// } - -} - -function trcTokenInMap(trcToken tokenId, uint256 tokenValue) returns(uint256 r) { -tokenCnt[tokenId] += tokenValue; -r = tokenCnt[tokenId]; -} - -function cntTokenTokenInMap(trcToken tokenId1, trcToken tokenId2, uint256 tokenValue) returns(trcToken r) { -cntTokenToken[tokenValue][tokenId1] = tokenId2; -r = cntTokenToken[tokenValue][tokenId1]; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/addTrcToken002Cat.sol b/framework/src/test/resources/soliditycode_v0.4.25/addTrcToken002Cat.sol deleted file mode 100644 index 0858c6442fb..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/addTrcToken002Cat.sol +++ /dev/null @@ -1,2017 +0,0 @@ -//pragma solidity ^0.4.11; - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - function Ownable() { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -contract ERC721 { - // Required methods - function totalSupply() public view returns (uint256 total); - function balanceOf(address _owner) public view returns (uint256 balance); - function ownerOf(uint256 _tokenId) external view returns (address owner); - function approve(address _to, uint256 _tokenId) external; - function transfer(address _to, uint256 _tokenId) external; - function transferFrom(address _from, address _to, uint256 _tokenId) external; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) external view returns (bool); -} - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - - function isGeneScience() public pure returns (bool){ - return true; - } - - /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor - /// @param genes1 genes of mom - /// @param genes2 genes of sire - /// @return the genes that are supposed to be passed down the child - function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - - return (genes1+genes2+targetBlock)/2; - - -} -} - - - - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() public onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - Transfer(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(now), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - uint256 newKittenId = kitties.push(_kitty) - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(0, _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { - /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. - function getMetadata(uint256 _tokenId, string) public view returns (bytes32[4] buffer, uint256 count) { - if (_tokenId == 1) { - buffer[0] = "Hello World! :D"; - count = 15; - } else if (_tokenId == 2) { - buffer[0] = "I would definitely choose a medi"; - buffer[1] = "um length string."; - count = 49; - } else if (_tokenId == 3) { - buffer[0] = "Lorem ipsum dolor sit amet, mi e"; - buffer[1] = "st accumsan dapibus augue lorem,"; - buffer[2] = " tristique vestibulum id, libero"; - buffer[3] = " suscipit varius sapien aliquam."; - count = 128; - } - } -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is KittyBase, ERC721 { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public view returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() public view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - external - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] _rawBytes, uint256 _stringLength) private view returns (string) { - var outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string _preferredTransport) external view returns (string infoUrl) { - require(erc721Metadata != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2 sun; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - msg.sender.send(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - - // Represents an auction on an NFT - struct Auction { - // Current owner of NFT - address seller; - // Price (in wei) at beginning of auction - uint128 startingPrice; - // Price (in wei) at end of auction - uint128 endingPrice; - // Duration (in seconds) of auction - uint64 duration; - // Time when auction started - // NOTE: 0 if this auction has been concluded - uint64 startedAt; - } - - // Reference to contract tracking NFT ownership - ERC721 public nonFungibleContract; - - // Cut owner takes on each auction, measured in basis points (1/100 of a percent). - // Values 0-10,000 map to 0%-100% - uint256 public ownerCut; - - // Map from token ID to their corresponding auction. - mapping (uint256 => Auction) tokenIdToAuction; - - event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); - event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); - event AuctionCancelled(uint256 tokenId); - - /// @dev Returns true if the claimant owns the token. - /// @param _claimant - Address claiming to own the token. - /// @param _tokenId - ID of token whose ownership to verify. - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return (nonFungibleContract.ownerOf(_tokenId) == _claimant); - } - - /// @dev Escrows the NFT, assigning ownership to this contract. - /// Throws if the escrow fails. - /// @param _owner - Current owner address of token to escrow. - /// @param _tokenId - ID of token whose approval to verify. - function _escrow(address _owner, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transferFrom(_owner, this, _tokenId); - } - - /// @dev Transfers an NFT owned by this contract to another address. - /// Returns true if the transfer succeeds. - /// @param _receiver - Address to transfer NFT to. - /// @param _tokenId - ID of token to transfer. - function _transfer(address _receiver, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transfer(_receiver, _tokenId); - } - - /// @dev Adds an auction to the list of open auctions. Also fires the - /// AuctionCreated event. - /// @param _tokenId The ID of the token to be put on auction. - /// @param _auction Auction to add. - function _addAuction(uint256 _tokenId, Auction _auction) internal { - // Require that all auctions have a duration of - // at least one minute. (Keeps our math from getting hairy!) - require(_auction.duration >= 1 minutes); - - tokenIdToAuction[_tokenId] = _auction; - - AuctionCreated( - uint256(_tokenId), - uint256(_auction.startingPrice), - uint256(_auction.endingPrice), - uint256(_auction.duration) - ); - } - - /// @dev Cancels an auction unconditionally. - function _cancelAuction(uint256 _tokenId, address _seller) internal { - _removeAuction(_tokenId); - _transfer(_seller, _tokenId); - AuctionCancelled(_tokenId); - } - - /// @dev Computes the price and transfers winnings. - /// Does NOT transfer ownership of token. - function _bid(uint256 _tokenId, uint256 _bidAmount) - internal - returns (uint256) - { - // Get a reference to the auction struct - Auction storage auction = tokenIdToAuction[_tokenId]; - - // Explicitly check that this auction is currently live. - // (Because of how Ethereum mappings work, we can't just count - // on the lookup above failing. An invalid _tokenId will just - // return an auction object that is all zeros.) - require(_isOnAuction(auction)); - - // Check that the bid is greater than or equal to the current price - uint256 price = _currentPrice(auction); - require(_bidAmount >= price); - - // Grab a reference to the seller before the auction struct - // gets deleted. - address seller = auction.seller; - - // The bid is good! Remove the auction before sending the fees - // to the sender so we can't have a reentrancy attack. - _removeAuction(_tokenId); - - // Transfer proceeds to seller (if there are any!) - if (price > 0) { - // Calculate the auctioneer's cut. - // (NOTE: _computeCut() is guaranteed to return a - // value <= price, so this subtraction can't go negative.) - uint256 auctioneerCut = _computeCut(price); - uint256 sellerProceeds = price - auctioneerCut; - - // NOTE: Doing a transfer() in the middle of a complex - // method like this is generally discouraged because of - // reentrancy attacks and DoS attacks if the seller is - // a contract with an invalid fallback function. We explicitly - // guard against reentrancy attacks by removing the auction - // before calling transfer(), and the only thing the seller - // can DoS is the sale of their own asset! (And if it's an - // accident, they can call cancelAuction(). ) - seller.transfer(sellerProceeds); - } - - // Calculate any excess funds included with the bid. If the excess - // is anything worth worrying about, transfer it back to bidder. - // NOTE: We checked above that the bid amount is greater than or - // equal to the price so this cannot underflow. - uint256 bidExcess = _bidAmount - price; - - // Return the funds. Similar to the previous transfer, this is - // not susceptible to a re-entry attack because the auction is - // removed before any transfers occur. - msg.sender.transfer(bidExcess); - - // Tell the world! - AuctionSuccessful(_tokenId, price, msg.sender); - - return price; - } - - /// @dev Removes an auction from the list of open auctions. - /// @param _tokenId - ID of NFT on auction. - function _removeAuction(uint256 _tokenId) internal { - delete tokenIdToAuction[_tokenId]; - } - - /// @dev Returns true if the NFT is on auction. - /// @param _auction - Auction to check. - function _isOnAuction(Auction storage _auction) internal view returns (bool) { - return (_auction.startedAt > 0); - } - - /// @dev Returns current price of an NFT on auction. Broken into two - /// functions (this one, that computes the duration from the auction - /// structure, and the other that does the price computation) so we - /// can easily test that the price computation works correctly. - function _currentPrice(Auction storage _auction) - internal - view - returns (uint256) - { - uint256 secondsPassed = 0; - - // A bit of insurance against negative values (or wraparound). - // Probably not necessary (since Ethereum guarnatees that the - // now variable doesn't ever go backwards). - if (now > _auction.startedAt) { - secondsPassed = now - _auction.startedAt; - } - - return _computeCurrentPrice( - _auction.startingPrice, - _auction.endingPrice, - _auction.duration, - secondsPassed - ); - } - - /// @dev Computes the current price of an auction. Factored out - /// from _currentPrice so we can run extensive unit tests. - /// When testing, make this function public and turn on - /// `Current price computation` test suite. - function _computeCurrentPrice( - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - uint256 _secondsPassed - ) - internal - pure - returns (uint256) - { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our public functions carefully cap the maximum values for - // time (at 64-bits) and currency (at 128-bits). _duration is - // also known to be non-zero (see the require() statement in - // _addAuction()) - if (_secondsPassed >= _duration) { - // We've reached the end of the dynamic pricing portion - // of the auction, just return the end price. - return _endingPrice; - } else { - // Starting price can be higher than ending price (and often is!), so - // this delta can be negative. - int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - - // This multiplication can't overflow, _secondsPassed will easily fit within - // 64-bits, and totalPriceChange will easily fit within 128-bits, their product - // will always fit within 256-bits. - int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - - // currentPriceChange can be negative, but if so, will have a magnitude - // less that _startingPrice. Thus, this result will always end up positive. - int256 currentPrice = int256(_startingPrice) + currentPriceChange; - - return uint256(currentPrice); - } - } - - /// @dev Computes owner's cut of a sale. - /// @param _price - Sale price of NFT. - function _computeCut(uint256 _price) internal view returns (uint256) { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our entry functions carefully cap the maximum values for - // currency (at 128-bits), and ownerCut <= 10000 (see the require() - // statement in the ClockAuction constructor). The result of this - // function is always guaranteed to be <= _price. - return _price * ownerCut / 10000; - } - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { - event Pause(); - event Unpause(); - - bool public paused = false; - - - /** - * @dev modifier to allow actions only when the contract IS paused - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev modifier to allow actions only when the contract IS NOT paused - */ - modifier whenPaused { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyOwner whenNotPaused returns (bool) { - paused = true; - Pause(); - return true; - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyOwner whenPaused returns (bool) { - paused = false; - Unpause(); - return true; - } -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - - /// @dev The ERC-165 interface signature for ERC-721. - /// Ref: https://github.com/ethereum/EIPs/issues/165 - /// Ref: https://github.com/ethereum/EIPs/issues/721 - bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - - /// @dev Constructor creates a reference to the NFT ownership contract - /// and verifies the owner cut is in the valid range. - /// @param _nftAddress - address of a deployed contract implementing - /// the Nonfungible Interface. - /// @param _cut - percent cut the owner takes on each auction, must be - /// between 0-10,000. - function ClockAuction(address _nftAddress, uint256 _cut) public { - require(_cut <= 10000); - ownerCut = _cut; - - ERC721 candidateContract = ERC721(_nftAddress); - require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); - nonFungibleContract = candidateContract; - } - - /// @dev Remove all Ether from the contract, which is the owner's cuts - /// as well as any Ether sent directly to the contract address. - /// Always transfers to the NFT contract, but can be called either by - /// the owner or the NFT contract. - function withdrawBalance() external { - address nftAddress = address(nonFungibleContract); - - require( - msg.sender == owner || - msg.sender == nftAddress - ); - // We are using this boolean method to make sure that even if one fails it will still work - bool res = nftAddress.send(this.balance); - } - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of time to move between starting - /// price and ending price (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address _seller - ) - external - whenNotPaused - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(_owns(msg.sender, _tokenId)); - _escrow(msg.sender, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Bids on an open auction, completing the auction and transferring - /// ownership of the NFT if enough Ether is supplied. - /// @param _tokenId - ID of token to bid on. - function bid(uint256 _tokenId) - external - payable - whenNotPaused - { - // _bid will throw if the bid or funds transfer fails - _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - } - - /// @dev Cancels an auction that hasn't been won yet. - /// Returns the NFT to original owner. - /// @notice This is a state-modifying function that can - /// be called while the contract is paused. - /// @param _tokenId - ID of token on auction - function cancelAuction(uint256 _tokenId) - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - address seller = auction.seller; - require(msg.sender == seller); - _cancelAuction(_tokenId, seller); - } - - /// @dev Cancels an auction when the contract is paused. - /// Only the owner may do this, and NFTs are returned to - /// the seller. This should only be used in emergencies. - /// @param _tokenId - ID of the NFT on auction to cancel. - function cancelAuctionWhenPaused(uint256 _tokenId) - whenPaused - onlyOwner - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - _cancelAuction(_tokenId, auction.seller); - } - - /// @dev Returns auction info for an NFT on auction. - /// @param _tokenId - ID of NFT on auction. - function getAuction(uint256 _tokenId) - external - view - returns - ( - address seller, - uint256 startingPrice, - uint256 endingPrice, - uint256 duration, - uint256 startedAt - ) { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return ( - auction.seller, - auction.startingPrice, - auction.endingPrice, - auction.duration, - auction.startedAt - ); - } - - /// @dev Returns the current price of an auction. - /// @param _tokenId - ID of the token price we are checking. - function getCurrentPrice(uint256 _tokenId) - external - view - returns (uint256) - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return _currentPrice(auction); - } - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSiringAuctionAddress() call. - bool public isSiringClockAuction = true; - - // Delegate constructor - function SiringClockAuction(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. Since this function is wrapped, - /// require sender to be KittyCore contract. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Places a bid for siring. Requires the sender - /// is the KittyCore contract because all bid methods - /// should be wrapped. Also returns the kitty to the - /// seller rather than the winner. - function bid(uint256 _tokenId) - external - payable - { - require(msg.sender == address(nonFungibleContract)); - address seller = tokenIdToAuction[_tokenId].seller; - // _bid checks that token ID is valid and will throw if bid fails - _bid(_tokenId, msg.value); - // We transfer the kitty back to the seller, the winner will get - // the offspring - _transfer(seller, _tokenId); - } - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSaleAuctionAddress() call. - bool public isSaleClockAuction = true; - - // Tracks last 5 sale price of gen0 kitty sales - uint256 public gen0SaleCount; - uint256[5] public lastGen0SalePrices; - - // Delegate constructor - function SaleClockAuction(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Updates lastSalePrice if seller is the nft contract - /// Otherwise, works the same as default bid method. - function bid(uint256 _tokenId) - external - payable - { - // _bid verifies token ID size - address seller = tokenIdToAuction[_tokenId].seller; - uint256 price = _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - - // If not a gen0 auction, exit - if (seller == address(nonFungibleContract)) { - // Track gen0 sale prices - lastGen0SalePrices[gen0SaleCount % 5] = price; - gen0SaleCount++; - } - } - - function averageGen0SalePrice() external view returns (uint256) { - uint256 sum = 0; - for (uint256 i = 0; i < 5; i++) { - sum += lastGen0SalePrices[i]; - } - return sum / 5; - } - -} - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, saleAuction); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, siringAuction); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10 sun; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, saleAuction); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - address(this) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - function KittyCore() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(-1), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - ContractUpgrade(_v2Address); - } - - /// @notice No tipping! - /// @dev Reject all Ether from being sent here, unless it's from one of the - /// two auction contracts. (Hopefully, we can prevent user accidents.) - function() external payable { - require( - msg.sender == address(saleAuction) || - msg.sender == address(siringAuction) - ); - } - - /// @notice Returns all the relevant information about a specific kitty. - /// @param _id The ID of the kitty of interest. - function getKitty(uint256 _id) - external - view - returns ( - bool isGestating, - bool isReady, - uint256 cooldownIndex, - uint256 nextActionAt, - uint256 siringWithId, - uint256 birthTime, - uint256 matronId, - uint256 sireId, - uint256 generation, - uint256 genes - ) { - Kitty storage kit = kitties[_id]; - - // if this variable is 0 then it's not gestating - isGestating = (kit.siringWithId != 0); - isReady = (kit.cooldownEndBlock <= block.number); - cooldownIndex = uint256(kit.cooldownIndex); - nextActionAt = uint256(kit.cooldownEndBlock); - siringWithId = uint256(kit.siringWithId); - birthTime = uint256(kit.birthTime); - matronId = uint256(kit.matronId); - sireId = uint256(kit.sireId); - generation = uint256(kit.generation); - genes = kit.genes; - } - - /// @dev Override unpause so it requires all external contract addresses - /// to be set before contract can be unpaused. Also, we can't have - /// newContractAddress set either, because then the contract was upgraded. - /// @notice This is public rather than external so we can call super.unpause - /// without using an expensive CALL. - function unpause(address toAddress, uint256 tokenValue, trcToken tokenId) public onlyCEO whenPaused returns (uint256 r) { - require(saleAuction != address(0)); - require(siringAuction != address(0)); - require(geneScience != address(0)); - require(newContractAddress == address(0)); - toAddress.transferToken(tokenValue, tokenId); - r = address(this).tokenBalance(tokenId); - // Actually unpause the contract. - super.unpause(); - } - - // @dev Allows the CFO to capture the balance available to the contract. - function withdrawBalance() external onlyCFO { - uint256 balance = this.balance; - // Subtract all the currently pregnant kittens we have, plus 1 of margin. - uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - - if (balance > subtractFees) { - cfoAddress.send(balance - subtractFees); - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/addTrcToken002Cat_withFinny.sol b/framework/src/test/resources/soliditycode_v0.4.25/addTrcToken002Cat_withFinny.sol deleted file mode 100644 index 5839b983a32..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/addTrcToken002Cat_withFinny.sol +++ /dev/null @@ -1,2017 +0,0 @@ -//pragma solidity ^0.4.11; - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - function Ownable() { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -contract ERC721 { - // Required methods - function totalSupply() public view returns (uint256 total); - function balanceOf(address _owner) public view returns (uint256 balance); - function ownerOf(uint256 _tokenId) external view returns (address owner); - function approve(address _to, uint256 _tokenId) external; - function transfer(address _to, uint256 _tokenId) external; - function transferFrom(address _from, address _to, uint256 _tokenId) external; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) external view returns (bool); -} - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - - function isGeneScience() public pure returns (bool){ - return true; - } - - /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor - /// @param genes1 genes of mom - /// @param genes2 genes of sire - /// @return the genes that are supposed to be passed down the child - function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - - return (genes1+genes2+targetBlock)/2; - - -} -} - - - - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() public onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - Transfer(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(now), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - uint256 newKittenId = kitties.push(_kitty) - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(0, _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { - /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. - function getMetadata(uint256 _tokenId, string) public view returns (bytes32[4] buffer, uint256 count) { - if (_tokenId == 1) { - buffer[0] = "Hello World! :D"; - count = 15; - } else if (_tokenId == 2) { - buffer[0] = "I would definitely choose a medi"; - buffer[1] = "um length string."; - count = 49; - } else if (_tokenId == 3) { - buffer[0] = "Lorem ipsum dolor sit amet, mi e"; - buffer[1] = "st accumsan dapibus augue lorem,"; - buffer[2] = " tristique vestibulum id, libero"; - buffer[3] = " suscipit varius sapien aliquam."; - count = 128; - } - } -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is KittyBase, ERC721 { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public view returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() public view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - external - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] _rawBytes, uint256 _stringLength) private view returns (string) { - var outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string _preferredTransport) external view returns (string infoUrl) { - require(erc721Metadata != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2 finny; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - msg.sender.send(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - - // Represents an auction on an NFT - struct Auction { - // Current owner of NFT - address seller; - // Price (in wei) at beginning of auction - uint128 startingPrice; - // Price (in wei) at end of auction - uint128 endingPrice; - // Duration (in seconds) of auction - uint64 duration; - // Time when auction started - // NOTE: 0 if this auction has been concluded - uint64 startedAt; - } - - // Reference to contract tracking NFT ownership - ERC721 public nonFungibleContract; - - // Cut owner takes on each auction, measured in basis points (1/100 of a percent). - // Values 0-10,000 map to 0%-100% - uint256 public ownerCut; - - // Map from token ID to their corresponding auction. - mapping (uint256 => Auction) tokenIdToAuction; - - event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); - event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); - event AuctionCancelled(uint256 tokenId); - - /// @dev Returns true if the claimant owns the token. - /// @param _claimant - Address claiming to own the token. - /// @param _tokenId - ID of token whose ownership to verify. - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return (nonFungibleContract.ownerOf(_tokenId) == _claimant); - } - - /// @dev Escrows the NFT, assigning ownership to this contract. - /// Throws if the escrow fails. - /// @param _owner - Current owner address of token to escrow. - /// @param _tokenId - ID of token whose approval to verify. - function _escrow(address _owner, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transferFrom(_owner, this, _tokenId); - } - - /// @dev Transfers an NFT owned by this contract to another address. - /// Returns true if the transfer succeeds. - /// @param _receiver - Address to transfer NFT to. - /// @param _tokenId - ID of token to transfer. - function _transfer(address _receiver, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transfer(_receiver, _tokenId); - } - - /// @dev Adds an auction to the list of open auctions. Also fires the - /// AuctionCreated event. - /// @param _tokenId The ID of the token to be put on auction. - /// @param _auction Auction to add. - function _addAuction(uint256 _tokenId, Auction _auction) internal { - // Require that all auctions have a duration of - // at least one minute. (Keeps our math from getting hairy!) - require(_auction.duration >= 1 minutes); - - tokenIdToAuction[_tokenId] = _auction; - - AuctionCreated( - uint256(_tokenId), - uint256(_auction.startingPrice), - uint256(_auction.endingPrice), - uint256(_auction.duration) - ); - } - - /// @dev Cancels an auction unconditionally. - function _cancelAuction(uint256 _tokenId, address _seller) internal { - _removeAuction(_tokenId); - _transfer(_seller, _tokenId); - AuctionCancelled(_tokenId); - } - - /// @dev Computes the price and transfers winnings. - /// Does NOT transfer ownership of token. - function _bid(uint256 _tokenId, uint256 _bidAmount) - internal - returns (uint256) - { - // Get a reference to the auction struct - Auction storage auction = tokenIdToAuction[_tokenId]; - - // Explicitly check that this auction is currently live. - // (Because of how Ethereum mappings work, we can't just count - // on the lookup above failing. An invalid _tokenId will just - // return an auction object that is all zeros.) - require(_isOnAuction(auction)); - - // Check that the bid is greater than or equal to the current price - uint256 price = _currentPrice(auction); - require(_bidAmount >= price); - - // Grab a reference to the seller before the auction struct - // gets deleted. - address seller = auction.seller; - - // The bid is good! Remove the auction before sending the fees - // to the sender so we can't have a reentrancy attack. - _removeAuction(_tokenId); - - // Transfer proceeds to seller (if there are any!) - if (price > 0) { - // Calculate the auctioneer's cut. - // (NOTE: _computeCut() is guaranteed to return a - // value <= price, so this subtraction can't go negative.) - uint256 auctioneerCut = _computeCut(price); - uint256 sellerProceeds = price - auctioneerCut; - - // NOTE: Doing a transfer() in the middle of a complex - // method like this is generally discouraged because of - // reentrancy attacks and DoS attacks if the seller is - // a contract with an invalid fallback function. We explicitly - // guard against reentrancy attacks by removing the auction - // before calling transfer(), and the only thing the seller - // can DoS is the sale of their own asset! (And if it's an - // accident, they can call cancelAuction(). ) - seller.transfer(sellerProceeds); - } - - // Calculate any excess funds included with the bid. If the excess - // is anything worth worrying about, transfer it back to bidder. - // NOTE: We checked above that the bid amount is greater than or - // equal to the price so this cannot underflow. - uint256 bidExcess = _bidAmount - price; - - // Return the funds. Similar to the previous transfer, this is - // not susceptible to a re-entry attack because the auction is - // removed before any transfers occur. - msg.sender.transfer(bidExcess); - - // Tell the world! - AuctionSuccessful(_tokenId, price, msg.sender); - - return price; - } - - /// @dev Removes an auction from the list of open auctions. - /// @param _tokenId - ID of NFT on auction. - function _removeAuction(uint256 _tokenId) internal { - delete tokenIdToAuction[_tokenId]; - } - - /// @dev Returns true if the NFT is on auction. - /// @param _auction - Auction to check. - function _isOnAuction(Auction storage _auction) internal view returns (bool) { - return (_auction.startedAt > 0); - } - - /// @dev Returns current price of an NFT on auction. Broken into two - /// functions (this one, that computes the duration from the auction - /// structure, and the other that does the price computation) so we - /// can easily test that the price computation works correctly. - function _currentPrice(Auction storage _auction) - internal - view - returns (uint256) - { - uint256 secondsPassed = 0; - - // A bit of insurance against negative values (or wraparound). - // Probably not necessary (since Ethereum guarnatees that the - // now variable doesn't ever go backwards). - if (now > _auction.startedAt) { - secondsPassed = now - _auction.startedAt; - } - - return _computeCurrentPrice( - _auction.startingPrice, - _auction.endingPrice, - _auction.duration, - secondsPassed - ); - } - - /// @dev Computes the current price of an auction. Factored out - /// from _currentPrice so we can run extensive unit tests. - /// When testing, make this function public and turn on - /// `Current price computation` test suite. - function _computeCurrentPrice( - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - uint256 _secondsPassed - ) - internal - pure - returns (uint256) - { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our public functions carefully cap the maximum values for - // time (at 64-bits) and currency (at 128-bits). _duration is - // also known to be non-zero (see the require() statement in - // _addAuction()) - if (_secondsPassed >= _duration) { - // We've reached the end of the dynamic pricing portion - // of the auction, just return the end price. - return _endingPrice; - } else { - // Starting price can be higher than ending price (and often is!), so - // this delta can be negative. - int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - - // This multiplication can't overflow, _secondsPassed will easily fit within - // 64-bits, and totalPriceChange will easily fit within 128-bits, their product - // will always fit within 256-bits. - int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - - // currentPriceChange can be negative, but if so, will have a magnitude - // less that _startingPrice. Thus, this result will always end up positive. - int256 currentPrice = int256(_startingPrice) + currentPriceChange; - - return uint256(currentPrice); - } - } - - /// @dev Computes owner's cut of a sale. - /// @param _price - Sale price of NFT. - function _computeCut(uint256 _price) internal view returns (uint256) { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our entry functions carefully cap the maximum values for - // currency (at 128-bits), and ownerCut <= 10000 (see the require() - // statement in the ClockAuction constructor). The result of this - // function is always guaranteed to be <= _price. - return _price * ownerCut / 10000; - } - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { - event Pause(); - event Unpause(); - - bool public paused = false; - - - /** - * @dev modifier to allow actions only when the contract IS paused - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev modifier to allow actions only when the contract IS NOT paused - */ - modifier whenPaused { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyOwner whenNotPaused returns (bool) { - paused = true; - Pause(); - return true; - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyOwner whenPaused returns (bool) { - paused = false; - Unpause(); - return true; - } -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - - /// @dev The ERC-165 interface signature for ERC-721. - /// Ref: https://github.com/ethereum/EIPs/issues/165 - /// Ref: https://github.com/ethereum/EIPs/issues/721 - bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - - /// @dev Constructor creates a reference to the NFT ownership contract - /// and verifies the owner cut is in the valid range. - /// @param _nftAddress - address of a deployed contract implementing - /// the Nonfungible Interface. - /// @param _cut - percent cut the owner takes on each auction, must be - /// between 0-10,000. - function ClockAuction(address _nftAddress, uint256 _cut) public { - require(_cut <= 10000); - ownerCut = _cut; - - ERC721 candidateContract = ERC721(_nftAddress); - require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); - nonFungibleContract = candidateContract; - } - - /// @dev Remove all Ether from the contract, which is the owner's cuts - /// as well as any Ether sent directly to the contract address. - /// Always transfers to the NFT contract, but can be called either by - /// the owner or the NFT contract. - function withdrawBalance() external { - address nftAddress = address(nonFungibleContract); - - require( - msg.sender == owner || - msg.sender == nftAddress - ); - // We are using this boolean method to make sure that even if one fails it will still work - bool res = nftAddress.send(this.balance); - } - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of time to move between starting - /// price and ending price (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address _seller - ) - external - whenNotPaused - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(_owns(msg.sender, _tokenId)); - _escrow(msg.sender, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Bids on an open auction, completing the auction and transferring - /// ownership of the NFT if enough Ether is supplied. - /// @param _tokenId - ID of token to bid on. - function bid(uint256 _tokenId) - external - payable - whenNotPaused - { - // _bid will throw if the bid or funds transfer fails - _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - } - - /// @dev Cancels an auction that hasn't been won yet. - /// Returns the NFT to original owner. - /// @notice This is a state-modifying function that can - /// be called while the contract is paused. - /// @param _tokenId - ID of token on auction - function cancelAuction(uint256 _tokenId) - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - address seller = auction.seller; - require(msg.sender == seller); - _cancelAuction(_tokenId, seller); - } - - /// @dev Cancels an auction when the contract is paused. - /// Only the owner may do this, and NFTs are returned to - /// the seller. This should only be used in emergencies. - /// @param _tokenId - ID of the NFT on auction to cancel. - function cancelAuctionWhenPaused(uint256 _tokenId) - whenPaused - onlyOwner - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - _cancelAuction(_tokenId, auction.seller); - } - - /// @dev Returns auction info for an NFT on auction. - /// @param _tokenId - ID of NFT on auction. - function getAuction(uint256 _tokenId) - external - view - returns - ( - address seller, - uint256 startingPrice, - uint256 endingPrice, - uint256 duration, - uint256 startedAt - ) { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return ( - auction.seller, - auction.startingPrice, - auction.endingPrice, - auction.duration, - auction.startedAt - ); - } - - /// @dev Returns the current price of an auction. - /// @param _tokenId - ID of the token price we are checking. - function getCurrentPrice(uint256 _tokenId) - external - view - returns (uint256) - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return _currentPrice(auction); - } - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSiringAuctionAddress() call. - bool public isSiringClockAuction = true; - - // Delegate constructor - function SiringClockAuction(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. Since this function is wrapped, - /// require sender to be KittyCore contract. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Places a bid for siring. Requires the sender - /// is the KittyCore contract because all bid methods - /// should be wrapped. Also returns the kitty to the - /// seller rather than the winner. - function bid(uint256 _tokenId) - external - payable - { - require(msg.sender == address(nonFungibleContract)); - address seller = tokenIdToAuction[_tokenId].seller; - // _bid checks that token ID is valid and will throw if bid fails - _bid(_tokenId, msg.value); - // We transfer the kitty back to the seller, the winner will get - // the offspring - _transfer(seller, _tokenId); - } - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSaleAuctionAddress() call. - bool public isSaleClockAuction = true; - - // Tracks last 5 sale price of gen0 kitty sales - uint256 public gen0SaleCount; - uint256[5] public lastGen0SalePrices; - - // Delegate constructor - function SaleClockAuction(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Updates lastSalePrice if seller is the nft contract - /// Otherwise, works the same as default bid method. - function bid(uint256 _tokenId) - external - payable - { - // _bid verifies token ID size - address seller = tokenIdToAuction[_tokenId].seller; - uint256 price = _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - - // If not a gen0 auction, exit - if (seller == address(nonFungibleContract)) { - // Track gen0 sale prices - lastGen0SalePrices[gen0SaleCount % 5] = price; - gen0SaleCount++; - } - } - - function averageGen0SalePrice() external view returns (uint256) { - uint256 sum = 0; - for (uint256 i = 0; i < 5; i++) { - sum += lastGen0SalePrices[i]; - } - return sum / 5; - } - -} - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, saleAuction); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, siringAuction); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10 finny; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, saleAuction); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - address(this) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - function KittyCore() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(-1), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - ContractUpgrade(_v2Address); - } - - /// @notice No tipping! - /// @dev Reject all Ether from being sent here, unless it's from one of the - /// two auction contracts. (Hopefully, we can prevent user accidents.) - function() external payable { - require( - msg.sender == address(saleAuction) || - msg.sender == address(siringAuction) - ); - } - - /// @notice Returns all the relevant information about a specific kitty. - /// @param _id The ID of the kitty of interest. - function getKitty(uint256 _id) - external - view - returns ( - bool isGestating, - bool isReady, - uint256 cooldownIndex, - uint256 nextActionAt, - uint256 siringWithId, - uint256 birthTime, - uint256 matronId, - uint256 sireId, - uint256 generation, - uint256 genes - ) { - Kitty storage kit = kitties[_id]; - - // if this variable is 0 then it's not gestating - isGestating = (kit.siringWithId != 0); - isReady = (kit.cooldownEndBlock <= block.number); - cooldownIndex = uint256(kit.cooldownIndex); - nextActionAt = uint256(kit.cooldownEndBlock); - siringWithId = uint256(kit.siringWithId); - birthTime = uint256(kit.birthTime); - matronId = uint256(kit.matronId); - sireId = uint256(kit.sireId); - generation = uint256(kit.generation); - genes = kit.genes; - } - - /// @dev Override unpause so it requires all external contract addresses - /// to be set before contract can be unpaused. Also, we can't have - /// newContractAddress set either, because then the contract was upgraded. - /// @notice This is public rather than external so we can call super.unpause - /// without using an expensive CALL. - function unpause(address toAddress, uint256 tokenValue, trcToken tokenId) public onlyCEO whenPaused returns (uint256 r) { - require(saleAuction != address(0)); - require(siringAuction != address(0)); - require(geneScience != address(0)); - require(newContractAddress == address(0)); - toAddress.transferToken(tokenValue, tokenId); - r = address(this).tokenBalance(tokenId); - // Actually unpause the contract. - super.unpause(); - } - - // @dev Allows the CFO to capture the balance available to the contract. - function withdrawBalance() external onlyCFO { - uint256 balance = this.balance; - // Subtract all the currently pregnant kittens we have, plus 1 of margin. - uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - - if (balance > subtractFees) { - cfoAddress.send(balance - subtractFees); - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest1DivideInt.sol b/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest1DivideInt.sol deleted file mode 100644 index 8ed20cd1cab..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest1DivideInt.sol +++ /dev/null @@ -1,7 +0,0 @@ -pragma solidity ^0.4.0; - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest2FindArgsContractMinTest.sol b/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest2FindArgsContractMinTest.sol deleted file mode 100644 index af54558bc98..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest2FindArgsContractMinTest.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma solidity ^0.4.0; -contract findArgsIContract{ -function findArgsByIndex1(uint i)public returns (uint z) { -uint[] memory a = new uint[](3); -a[0]=1; -a[1]=2; -a[2]=3; -return a[i]; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest3ByteMinContract.sol b/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest3ByteMinContract.sol deleted file mode 100644 index d2e8637612d..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest3ByteMinContract.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma solidity ^0.4.0; -contract byteContract { -bytes b; -function testBytesGet(uint i) returns (bytes1){ -b = new bytes(3); -b[0]=12; -b[1]=13; -b[2]=14; -return b[i]; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest4Enum.sol b/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest4Enum.sol deleted file mode 100644 index 5d7164d27d1..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest4Enum.sol +++ /dev/null @@ -1,13 +0,0 @@ -pragma solidity ^0.4.4; - -contract enumContract { - enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } - ActionChoices _choice; - function setGoStraight(ActionChoices choice) public { - _choice = choice; - } - - function getChoice() public returns (ActionChoices) { - return _choice; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest5MoveRight.sol b/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest5MoveRight.sol deleted file mode 100644 index c0d15a7aa09..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest5MoveRight.sol +++ /dev/null @@ -1,7 +0,0 @@ -pragma solidity ^0.4.0; - -contract binaryRightContract{ - function binaryMoveR(int i)public returns (int z) { - return z = 5 >> i; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest6UninitializedContract.sol b/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest6UninitializedContract.sol deleted file mode 100644 index dbfa3e01bc0..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest6UninitializedContract.sol +++ /dev/null @@ -1,27 +0,0 @@ -pragma solidity ^0.4.0; -contract uni { -function b(int x, int y) internal returns (int) -{ - return x * y; -} - -function test1() external returns (int) -{ - // Variable containing a function pointer - function (int, int) internal returns (int) funcPtr; - - funcPtr = b; - - // This call to funcPtr will succeed - return funcPtr(4, 5); -} - -function test2() external returns (int) -{ - // Variable containing a function pointer - function (int, int) internal returns (int) funcPtr; - - // This call will fail because funcPtr is still a zero-initialized function pointer - return funcPtr(4, 5); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest7TestAssertContract.sol b/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest7TestAssertContract.sol deleted file mode 100644 index 842b8c174e5..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/assertExceptiontest7TestAssertContract.sol +++ /dev/null @@ -1,17 +0,0 @@ -pragma solidity ^0.4.0; - - -contract TestThrowsContract{ - function testAssert(){ - assert(1==2); - } - function testRequire(){ - require(2==1); - } - function testRevert(){ - revert(); - } - function testThrow(){ - throw; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/codeSaftySupport.sol b/framework/src/test/resources/soliditycode_v0.4.25/codeSaftySupport.sol deleted file mode 100644 index 7ae081877b6..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/codeSaftySupport.sol +++ /dev/null @@ -1,19 +0,0 @@ -pragma solidity ^0.4.24; - -contract IllegalDecorate { - -constructor() payable public{} - -function() payable external{} - -event log(uint256); - -function transferToken(address toAddress, uint256 tokenValue) public payable { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/codeSaftyUnsupport.sol b/framework/src/test/resources/soliditycode_v0.4.25/codeSaftyUnsupport.sol deleted file mode 100644 index ff561614780..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/codeSaftyUnsupport.sol +++ /dev/null @@ -1,50 +0,0 @@ - pragma solidity ^0.4.24; -contract SubC { -event log(string); - -function () payable {} - -function receiveToken() payable {} - -function getBalance() constant public returns (uint256 r){ -r = address(this).balance; -} -} -contract UseDot { -constructor() payable public{} -function() payable public{} -mapping(address => mapping(trcToken => uint256)) sender_tokens; - -function trigger1(address addr) payable public { - //SubC(addr).call.value(1000).tokenId(0x6e6d62)(bytes4(sha3("receiveToken()"))); // ERROR -} - -function trigger2(address addr) payable public { - //addr.transferToken.value(10)(10, 0x6e6d62); // ERROR -} - -function trigger3(address addr) payable public { -// SubC(addr).receiveToken.tokenvalue(10)(); // ERROR -} - -function trigger4(address addr) payable public { -// SubC(addr).receiveToken.tokenId(0x6e6d62)(); // ERROR -} - -function trigger5(address addr) payable public { -SubC(addr).receiveToken.value(10)(); -} -function trigger6(address addr, trcToken tokenId) payable public { -SubC(addr).call.value(1000)(bytes4(sha3("transferToken(uint256, trcToken)")), 10, tokenId); -} - -function trigger7(address addr) payable public { - //sender_tokens[msg.sender][msg.tokenid] += msg.tokenvalue; // compile success, no necessary to trigger -} -function trigger8(address addr) public payable returns(bytes r){ - //r = msg.data; // compile success, no necessary to trigger -} -function getBalance() public returns (uint256 r){ -r = address(this).balance; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGetterContract.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGetterContract.sol deleted file mode 100644 index deed0aeabd2..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGetterContract.sol +++ /dev/null @@ -1,17 +0,0 @@ -//pragma solidity ^0.4.0; - - -contract getterContract{ - -constructor() public payable{} -function() external payable{} - -uint public c = msg.value; - -function getDataUsingAccessor() returns (uint){ - -return c; - -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test1Grammar001.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test1Grammar001.sol deleted file mode 100644 index f433ed3585f..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test1Grammar001.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.4.16; -contract FunctionSelector { - function select(bool useB, uint x) public returns (uint z) { - var f = a; - if (useB) f = b; - return f(x); - } -function a(uint x) public returns (uint z) { - return x * x; - } -function b(uint x) public returns (uint z) { - return 2 * x; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test2Grammar002.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test2Grammar002.sol deleted file mode 100644 index da9ff8caa56..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test2Grammar002.sol +++ /dev/null @@ -1,44 +0,0 @@ -pragma solidity ^0.4.16; -library Set { - // We define a new struct datatype that will be used to - // hold its data in the calling contract. - struct Data { mapping(uint => bool) flags; } - - // Note that the first parameter is of type "storage - // reference" and thus only its storage address and not - // its contents is passed as part of the call. This is a - // special feature of library functions. It is idiomatic - // to call the first parameter 'self', if the function can - // be seen as a method of that object. - function insert(Data storage self, uint value) public returns (bool) { - if (self.flags[value]) - return false; // already there - self.flags[value] = true; - return true; - } - - function remove(Data storage self, uint value) public returns (bool) { - if (!self.flags[value]) - return false; // not there - self.flags[value] = false; - return true; - } - - function contains(Data storage self, uint value) public returns (bool) { - return self.flags[value]; - } -} - - -contract C { - Set.Data knownValues; - - function register(uint value) { - // The library functions can be called without a - // specific instance of the library, since the - // "instance" will be the current contract. - if (!Set.insert(knownValues, value)) - throw; - } - // In this contract, we can also directly access knownValues.flags, if we want. -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test3Grammar003.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test3Grammar003.sol deleted file mode 100644 index 4d3f87ebe3e..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test3Grammar003.sol +++ /dev/null @@ -1,44 +0,0 @@ -pragma solidity ^0.4.11; - -library Set { - struct Data { mapping(uint => bool) flags; } - - function insert(Data storage self, uint value) public - returns (bool) - { - if (self.flags[value]) - return false; // already there - self.flags[value] = true; - return true; - } - - function remove(Data storage self, uint value) public - returns (bool) - { - if (!self.flags[value]) - return false; // not there - self.flags[value] = false; - return true; - } - - function contains(Data storage self, uint value) public - returns (bool) - { - return self.flags[value]; - } -} - - -contract C { - using Set for Set.Data; // this is the crucial change - Set.Data knownValues; - - function register(uint value) { - // Here, all variables of type Set.Data have - // corresponding member functions. - // The following function call is identical to - // Set.insert(knownValues, value) - if (!knownValues.insert(value)) - throw; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test4Grammar004.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test4Grammar004.sol deleted file mode 100644 index 78bc620c81f..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test4Grammar004.sol +++ /dev/null @@ -1,31 +0,0 @@ -pragma solidity ^0.4.0; - -library Search { - function indexOf(uint[] storage self, uint value) public returns (uint) { - for (uint i = 0; i < self.length; i++) - if (self[i] == value) return i; - return uint(-1); - } -} - - -contract C { - using Search for uint[]; - uint[] public data; - - function append(uint value) { - data.push(value); - } - - function replace(uint _old, uint _new) { - // This performs the library function call - uint index = data.indexOf(_old); - if (index == uint(-1)) - data.push(_new); - else - data[index] = _new; - } - function getData(uint256 index) public returns(uint256){ - return data[index]; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test5Grammar006.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test5Grammar006.sol deleted file mode 100644 index 5bba3d4bba0..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar001test5Grammar006.sol +++ /dev/null @@ -1,36 +0,0 @@ - pragma solidity ^0.4.0; -contract InfoFeed { -function d1(uint x){ - assembly{ - function f(x) -> y { switch x case 0 { y := 1 } default { y := mul(x, f(sub(x, 1))) } } - } - } - function d2(uint x){ - assembly { x := mul(1, add(2, 3))} - } - function f(uint x) { - assembly { x := sub(x, 1) } - - } - function d(uint x){ - assembly{ - let x := add(2, 3) let y := mload(0x40) x := add(x, y) - } - } - function d4(uint x){ - assembly{let x := 10 repeat: x := sub(x, 1) jumpi(repeat, eq(x, 0)) - } - } - function d5(uint x){ - assembly{ - function f(x) -> y { switch x case 0 { y := mul(x, 2) } default { y := 0 } } - - } - } - - function d6(uint x){ - assembly{ - function f(x) -> y { for { let i := 0 } lt(i, x) { i := add(i, 1) } { y := mul(2, y) } } - } - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test1Grammar007_1.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test1Grammar007_1.sol deleted file mode 100644 index 752d3613be2..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test1Grammar007_1.sol +++ /dev/null @@ -1,60 +0,0 @@ -pragma solidity ^0.4.19; -contract Doug{ - mapping (bytes32 => uint) public contracts; - function Doug() { - contracts['hww'] = 1; - contracts['brian'] = 2; - contracts['zzy'] = 7; - } - - function getDougName(string _name) public view returns(string) { - return _name; - } - - function getDougAge(uint _age) public pure returns(uint) { - return 3 ** _age; - } -} - -contract DogInterface { - function getDougAge(uint _age) returns (uint); - function contracts(bytes32 name) returns (uint); -} -contract main{ - - event FetchContract(address dogInterfaceAddress, address sender, bytes32 name); - - address public DOUG; - - address dogInterfaceAddress; - DogInterface dogContract ; - - function setDOUG(address _doug) { - DOUG = _doug; - } - - constructor(address addr) public{ - dogInterfaceAddress = addr; - dogContract = DogInterface(dogInterfaceAddress); - } - - function dougOfage(uint _age) public view returns(uint) { - - uint num = dogContract.getDougAge(_age); - return _age+num; - // return num; - } - - function uintOfName(bytes32 _name) returns (uint) { - - dogContract.contracts(_name); - FetchContract(dogInterfaceAddress, msg.sender, _name); - - } - - // function getTest(string _name) public view returns(string) { - // string memory newName = _name ; - // DogInterface(DOUG).getDougName(newName); - // return newName; - // } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test1Grammar007_2.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test1Grammar007_2.sol deleted file mode 100644 index 8078507e7b2..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test1Grammar007_2.sol +++ /dev/null @@ -1,60 +0,0 @@ -pragma solidity ^0.4.19; -contract Doug{ - mapping (bytes32 => uint) public contracts; - function Doug() { - contracts['hww'] = 1; - contracts['brian'] = 2; - contracts['zzy'] = 7; - } - - function getDougName(string _name) public view returns(string) { - return _name; - } - - function getDougAge(uint _age) public pure returns(uint) { - return 3 ** _age; - } -} - -contract DogInterface { - function getDougAge(uint _age) returns (uint); - function contracts(bytes32 name) returns (uint); -} -contract main{ - - event FetchContract(address dogInterfaceAddress, address sender, bytes32 name); - - address public DOUG; - - address dogInterfaceAddress; - DogInterface dogContract ; - - function setDOUG(address _doug) { - DOUG = _doug; - } - - constructor(address addr) public{ - dogInterfaceAddress = addr; - dogContract = DogInterface(dogInterfaceAddress); - } - - function dougOfage(uint _age) public view returns(uint) { - - uint num = dogContract.getDougAge(_age); - return _age+num; - // return num; - } - - function uintOfName(bytes32 _name) returns (uint) { - - dogContract.contracts(_name); - FetchContract(dogInterfaceAddress, msg.sender, _name); - - } - - // function getTest(string _name) public view returns(string) { - // string memory newName = _name ; - // DogInterface(DOUG).getDougName(newName); - // return newName; - // } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test2Grammar008.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test2Grammar008.sol deleted file mode 100644 index fb4338de0d8..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test2Grammar008.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.4.19; -contract Feline { - function utterance() public returns (bytes32); - - function getContractName() public returns (string){ - return "Feline"; - } -} - - -contract Cat is Feline { - function utterance() public returns (bytes32) { return "miaow"; } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test3Grammar010.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test3Grammar010.sol deleted file mode 100644 index 43ff2e0aef3..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test3Grammar010.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma solidity ^0.4.0; -contract InfoFeed { -function info() public payable returns (uint ret) { return 42; } -} -contract Consumer { -constructor() payable public{} -InfoFeed feed; -function setFeed(address addr) public { feed = InfoFeed(addr); } -function callFeed() public payable{ feed.info.value(10).gas(800)(); } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test4Grammar011.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test4Grammar011.sol deleted file mode 100644 index 0b673512248..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test4Grammar011.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma solidity ^0.4.0; -contract C { -function f(uint key, uint value) public returns(uint) { -return key; -// do something -} -function g() public { -// named arguments -f({value: 2, key: 3}); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test4Grammar012.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test4Grammar012.sol deleted file mode 100644 index 3c72e608e24..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test4Grammar012.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.4.24; -contract rTest { -function info() public payable returns (uint,address,bytes4,uint,uint,uint,address,uint) { -//function info() public payable returns (address ,uint,uint,uint,bytes32,uint,bytes,uint,address,bytes4,uint,uint,uint,address,uint) { -//var a = block.coinbase ; -//var b = block.difficulty; -//var c = block.gaslimit; -//var d = block.number; -//var e = block.blockhash(0); -//var e = d; -//var f = block.timestamp; -//bytes memory g = msg.data; -var h = msg.gas; -var i = msg.sender; -var j = msg.sig; -var k = msg.value; -var l = now; -var m = tx.gasprice; -var n = tx.origin; -var o = this.balance; -return (h,i,j,k,l,m,n,o); -//return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test6Grammar013.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test6Grammar013.sol deleted file mode 100644 index f29197bccc3..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar002test6Grammar013.sol +++ /dev/null @@ -1,22 +0,0 @@ -pragma solidity ^0.4.4; -contract Counter { -uint count = 0; -address owner; -function Counter() { -owner = msg.sender; -} -function increment() public { -uint step = 10; -if (owner == msg.sender) { -count = count + step; -} -} -function getCount() public returns (uint) { -return count; -} -function kill() { -if (owner == msg.sender) { -selfdestruct(owner); -} -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test1Grammar014.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test1Grammar014.sol deleted file mode 100644 index c55b5b391a3..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test1Grammar014.sol +++ /dev/null @@ -1,59 +0,0 @@ -pragma solidity ^0.4.4; -contract A { -uint256 public numberForB; -address public senderForB; -function callTest(address bAddress, uint256 _number) { -bAddress.call(bytes4(sha3("setValue(uint256)")), _number); // B's storage is set, A is not modified -} -function callcodeTest(address bAddress, uint256 _number) { -bAddress.callcode(bytes4(sha3("setValue(uint256)")), _number); // A's storage is set, B is not modified -} -function delegatecallTest(address bAddress, uint256 _number) { -bAddress.delegatecall(bytes4(sha3("setValue(uint256)")), _number); // A's storage is set, B is not modified -} - -function callAddTest(address bAddress) { -bAddress.call(bytes4(sha3("add()"))); // B's storage is set, A is not modified -bAddress.call(bytes4(sha3("add()"))); // B's storage is set, A is not modified -} -function getnumberForB() public returns(uint256){ - return numberForB; - } - function getsenderForB() public returns(address){ - return senderForB; - } -} -contract B { -uint256 public numberForB; -address public senderForB; -address public addr11; -mapping(uint256=>address) public addr1; -mapping(uint256=>address) public addr2; -function setValue(uint256 _number) { -numberForB = _number; -senderForB = msg.sender; -// senderForB is A if invoked by A's callTest. B's storage will be updated -// senderForB is A if invoked by A's callcodeTest. None of B's storage is updated -// senderForB is OWNER if invoked by A's delegatecallTest. None of B's storage is updated -} - -function add() public{ -numberForB=numberForB+1; -C c1 = new C(); -addr1[numberForB]=c1.getAddress(); -addr11 = c1.getAddress(); -C c2 = new C(); -addr2[numberForB] = c2.getAddress(); -} -function getnumberForB() public returns(uint256){ - return numberForB; - } - function getsenderForB() public returns(address){ - return senderForB; - } -} -contract C { -function getAddress() public view returns(address){ -return address(this); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test2Grammar015.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test2Grammar015.sol deleted file mode 100644 index 4e704628f4b..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test2Grammar015.sol +++ /dev/null @@ -1,37 +0,0 @@ -pragma solidity ^0.4.0; - -contract ExecuteFallback{ - - //回退事件,会把调用的数据打印出来 - event FallbackCalled(bytes data); - //fallback函数,注意是没有名字的,没有参数,没有返回值的 - function(){ - FallbackCalled(msg.data); - } - - //调用已存在函数的事件,会把调用的原始数据,请求参数打印出来 - event ExistFuncCalled(bytes data, uint256 para); - //一个存在的函数 - function existFunc(uint256 para){ - ExistFuncCalled(msg.data, para); - } - - // 模拟从外部对一个存在的函数发起一个调用,将直接调用函数 - function callExistFunc(){ - bytes4 funcIdentifier = bytes4(keccak256("existFunc(uint256)")); - this.call(funcIdentifier, uint256(1)); - } - - //模拟从外部对一个不存在的函数发起一个调用,由于匹配不到函数,将调用回退函数 - function callNonExistFunc(){ - bytes4 funcIdentifier = bytes4(keccak256("functionNotExist()")); - this.call(funcIdentifier); - } - - function ExistFuncCalledTopic() view returns(bytes32){ - return keccak256("ExistFuncCalled(bytes,uint256)"); - } - function FallbackCalledTopic() view returns(bytes32){ - return keccak256("FallbackCalled(bytes)"); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test3Grammar016.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test3Grammar016.sol deleted file mode 100644 index a39a0a08d96..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test3Grammar016.sol +++ /dev/null @@ -1,23 +0,0 @@ -pragma solidity ^0.4.0; -contract C { -uint private data; -function f(uint a) private returns(uint b) { return a + 1; } -function setData(uint a) public { data = a; } -function getData() public returns(uint) { return data; } -function compute(uint a, uint b) internal returns (uint) { return a+b; } -} -contract D { -function readData() public{ -C c = new C(); -//uint local = c.f(7); // error: member "f" is not visible -c.setData(3); -uint local = c.getData(); -// local = c.compute(3, 5); // error: member "compute" is not visible -} -} -contract E is C { -function g() public { -C c = new C(); -uint val = compute(3, 5); // access to internal member (from derived to parent contract) -} -} diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test4Grammar017.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test4Grammar017.sol deleted file mode 100644 index 3387a9c30bd..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test4Grammar017.sol +++ /dev/null @@ -1,47 +0,0 @@ -pragma solidity ^0.4.0; -contract CrowdFunding{ -struct Funder{ -address addr; -uint amount; -} - -struct Campaign{ -address beneficiary; -uint goal; -uint amount; -uint funderNum; -mapping(uint => Funder) funders; -} - -uint compaingnID; -mapping (uint => Campaign) campaigns; - -function candidate(address beneficiary, uint goal) returns (uint compaingnID){ -// initialize -campaigns[compaingnID++] = Campaign(beneficiary, goal, 0, 0); -} - -function vote(uint compaingnID) payable { -Campaign c = campaigns[compaingnID]; - -//another way to initialize -c.funders[c.funderNum++] = Funder({addr: msg.sender, amount: msg.value}); -c.amount += msg.value; -} - -function check(uint comapingnId) returns (bool){ -Campaign c = campaigns[comapingnId]; - -if(c.amount < c.goal){ -return false; -} - -uint amount = c.amount; -// incase send much more -c.amount = 0; -if(!c.beneficiary.send(amount)){ -throw; -} -return true; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test5Grammar018.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test5Grammar018.sol deleted file mode 100644 index 4fdaf52a29f..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test5Grammar018.sol +++ /dev/null @@ -1,36 +0,0 @@ -pragma solidity ^0.4.0; - - -contract Grammar18{ - function testAddmod() public returns (uint z) { - //计算(x + y)%k,其中以任意精度执行加法,并且不在2 ** 256处围绕 - z=addmod(2, 2, 3); - return z; - } - function testMulmod() public returns (uint z) { -//计算(x * y)%k,其中乘法以任意精度执行,并且不会在2 ** 256处循环。 - z=mulmod(2, 3, 4); - return z; - } - - function testKeccak256() public returns(bytes32){ - //计算的(紧凑)参数的Ethereum-SHA-3(Keccak-256)的散列 - return keccak256("11"); - } - - function testSha256() public returns(bytes32){ - //计算(紧密包装)参数的SHA-256散列 - return sha256("11"); - } - function testSha3() public returns(bytes32){ - //计算(紧密包装)参数的SHA-256散列 - return sha3("11"); - } - - function testRipemd160() public returns(bytes32){ - //计算(紧密包装)参数的RIPEMD-160哈希值 - return ripemd160("11"); - } - - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test6Grammar019.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test6Grammar019.sol deleted file mode 100644 index 3b2d5f2263c..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test6Grammar019.sol +++ /dev/null @@ -1,12 +0,0 @@ -pragma solidity ^0.4.0; -contract timetest { - -function timetest() public { -require( 1 == 1 seconds); -require(1 minutes == 60 seconds); -require(1 hours == 60 minutes); -require(1 days == 24 hours); -require(1 weeks == 7 days); -require(1 years == 365 days); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test7Grammar020.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test7Grammar020.sol deleted file mode 100644 index d5157c18c47..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractGrammar003test7Grammar020.sol +++ /dev/null @@ -1,7 +0,0 @@ -pragma solidity ^0.4.0; -contract trxtest { - -function test() public { -require(1 trx == 1000000 sun); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractInnerContract.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractInnerContract.sol deleted file mode 100644 index 02402acd217..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractInnerContract.sol +++ /dev/null @@ -1,31 +0,0 @@ -//pragma solidity ^0.4.0; - - - -contract InnerContract { - - - constructor() public payable{} - function() external payable{} - function messageI() payable returns (uint ret) { - - - - } - -} - - - -contract OuterContract { - - constructor() public payable{} - function() external payable{} - - function callInner(address addr) payable returns (uint) { - - return InnerContract(addr).messageI.value(1)(); - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction001.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction001.sol deleted file mode 100644 index 1f13e067773..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction001.sol +++ /dev/null @@ -1,42 +0,0 @@ -pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable public{} - function test1(address cAddr) public payable{ - B b1 = (new B).value(10)();//1.1 - B b2 = new B();//1.2 - b2.transfer(5);//1.3 - b2.callCGetZero(cAddr, 1);//1.4 - b2.callCGetZero(cAddr,2);//1.6 - } - function test2(address cAddress,uint256 amount) public payable{ - cAddress.call.value(amount)(bytes4(keccak256("newBAndTransfer()")));//2.1 - cAddress.call.value(amount + 1)(bytes4(keccak256("newBAndTransfer()")));//2.6 - } -} - -contract B{ - constructor() payable public{} - function() payable public{} - function getOne() payable returns(uint256){ - return 1; - } - function callCGetZero(address cAddress,uint256 amount){ - cAddress.call.value(amount)(bytes4(keccak256("getZero()")));//1.5,1.7 - } -} - -contract C{ - constructor() payable public{} - function() payable public{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - B b1 = (new B).value(7)();//2.2,2.7 - b1.getOne();//2.3,2.8 - B b2 = (new B).value(3)();//2.4,2.9 - b2.getOne();//2.5,2.10 - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction002.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction002.sol deleted file mode 100644 index b5fd94f5a0e..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction002.sol +++ /dev/null @@ -1,20 +0,0 @@ -pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable public{} - - function test2(address cAddress,uint256 amount) public payable{ - cAddress.call.value(amount)();//2.1 - } -} - - -contract C{ - constructor() payable public{} - function() payable public{} - function getZero() payable public returns(uint256){ - return 0; - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction003.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction003.sol deleted file mode 100644 index ab8841419e7..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction003.sol +++ /dev/null @@ -1,31 +0,0 @@ -pragma solidity ^0.4.24; - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer() payable public{ - B b = (new B).value(10)();//1 - - } - function getBalance() returns(uint256){ - return this.balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable returns(bool) { - return true; - } - constructor() public payable {} - function payC(address c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() public returns(uint256){ - return this.balance; - } - function () payable{} - } - diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction004.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction004.sol deleted file mode 100644 index 8a03691b172..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction004.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.4.24; - -contract A{ - constructor () payable public{} - function suicide(address toAddress) public payable{ - selfdestruct(toAddress); - } - function () payable public{} - function getBalance() public view returns(uint256){ - return this.balance; - } -} -contract B{ - function kill(address contractAddres, address toAddress) payable public { - contractAddres.call(bytes4(keccak256("suicide(address)")),address(this)); - } - function kill2(){ - A a = new A(); - a.suicide(this); - } - function getBalance() public view returns(uint256){ - return this.balance; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction005.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction005.sol deleted file mode 100644 index d4042dba94a..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction005.sol +++ /dev/null @@ -1,54 +0,0 @@ -pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable public{} - function test1() public payable{ - B b1 = (new B).value(10)();//1.1 - b1.callCGetZero(false); - b1.callCGetZero(true);//1.4 - } - function test2() public payable{ - C c1 = (new C).value(10)();//1.1 - c1.newBAndTransfer(false); - c1.newBAndTransfer(true);//1.4 - - } - function getBalance() view public returns(uint256){ - return this.balance; - } -} - -contract B{ - constructor() payable public{} - function() payable public{} - function getOne() payable returns(uint256){ - return 1; - } - function callCGetZero(bool success) payable{ - if(!success){ - assert(1==2); - } - } - function getBalance() view public returns(uint256){ - return this.balance; - } -} - -contract C{ - uint256 public flag=0; - constructor() payable public{} - function() payable public{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer(bool success) payable public returns(uint256){ - flag = 1; - if(!success){ - require(2==1); - } - } - function getFlag() public returns(uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction006.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction006.sol deleted file mode 100644 index 885966df74f..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction006.sol +++ /dev/null @@ -1,54 +0,0 @@ -pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable public{} - function test1() public payable{ - B b1 = (new B).value(10)();//1.1 - b1.callCGetZero(true);//1.4 - b1.callCGetZero(false); - } - function test2() public payable{ - C c1 = (new C).value(10)();//1.1 - c1.newBAndTransfer(true);//1.4 - c1.newBAndTransfer(false); - - } - function getBalance() view public returns(uint256){ - return this.balance; - } -} - -contract B{ - constructor() payable public{} - function() payable public{} - function getOne() payable returns(uint256){ - return 1; - } - function callCGetZero(bool success) payable{ - if(!success){ - assert(1==2); - } - } - function getBalance() view public returns(uint256){ - return this.balance; - } -} - -contract C{ - uint256 public flag=0; - constructor() payable public{} - function() payable public{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer(bool success) payable public returns(uint256){ - flag = 1; - if(!success){ - require(2==1); - } - } - function getFlag() public returns(uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test1InternalTransaction007.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test1InternalTransaction007.sol deleted file mode 100644 index fc1eb39c36e..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test1InternalTransaction007.sol +++ /dev/null @@ -1,38 +0,0 @@ -pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable public{} - function test1(address cAddr) public payable{ - B b1 = (new B).value(10)();//1.1 - B b2 = new B();//1.2 - b2.transfer(5);//1.3 - b2.callCGetZero();//1.4 - } - function test2(address cAddress,uint256 amount) public payable{ - cAddress.call.value(amount)(bytes4(keccak256("newBAndTransfer()")));//2.1 - } -} - -contract B{ - constructor() payable public{} - function() payable public{} - function getOne() payable returns(uint256){ - return 1; - } - function callCGetZero(){ - assert(1==2); - - } -} - -contract C{ - constructor() payable public{} - function() payable public{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test2InternalTransaction008.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test2InternalTransaction008.sol deleted file mode 100644 index f728c2a8bf6..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test2InternalTransaction008.sol +++ /dev/null @@ -1,60 +0,0 @@ -pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable public{} - - function testAssert(address bAddress,uint256 amount) public payable{ - bAddress.call.value(amount).gas(1000000)(bytes4(keccak256("callCGetZero(bool)")),false);//2.1 - bAddress.call.value(amount).gas(1000000)(bytes4(keccak256("callCGetZero(bool)")),true); - } - function testRequire(address cAddress,uint256 amount) public payable{ - cAddress.call.value(amount).gas(1000000)(bytes4(keccak256("newBAndTransfer(bool)")),false);//2.1 - cAddress.call.value(amount).gas(1000000)(bytes4(keccak256("newBAndTransfer(bool)")),true); - } - function testAssert1(address bAddress,uint256 amount) public payable{ - bAddress.call.value(amount).gas(1000000)(bytes4(keccak256("callCGetZero(bool)")),true); - bAddress.call.value(amount).gas(1000000)(bytes4(keccak256("callCGetZero(bool)")),false);//2.1 - } - function testtRequire2(address cAddress,uint256 amount) public payable{ - cAddress.call.value(amount).gas(1000000)(bytes4(keccak256("newBAndTransfer(bool)")),true); - cAddress.call.value(amount).gas(1000000)(bytes4(keccak256("newBAndTransfer(bool)")),false);//2.1 - } - function getBalance() view public returns(uint256){ - return this.balance; - } -} - -contract B{ - constructor() payable public{} - function() payable public{} - function getOne() payable returns(uint256){ - return 1; - } - function callCGetZero(bool success) payable{ - if(!success){ - assert(1==2); - } - } - function getBalance() view public returns(uint256){ - return this.balance; - } -} - -contract C{ - uint256 public flag=0; - constructor() payable public{} - function() payable public{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer(bool success) payable public returns(uint256){ - flag = 1; - if(!success){ - require(2==1); - } - } - function getFlag() public returns(uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test3InternalTransaction009.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test3InternalTransaction009.sol deleted file mode 100644 index 199c0884182..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test3InternalTransaction009.sol +++ /dev/null @@ -1,47 +0,0 @@ -pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable public{} - function test1(address cAddr,address dcontract,address baddress) public payable{ - B b1 = (new B).value(10)();//1.1 - b1.transfer(5);//1.3 - b1.callCGetZero(cAddr, 1);//1.4 - b1.getOne(dcontract,baddress); - } -} - -contract B{ - constructor() payable public{} - function() payable public{} - function getOne(address contractAddres, address toAddress) payable public{ - contractAddres.call(bytes4(keccak256("suicide1(address)")),address(this)); - - } - function callCGetZero(address cAddress,uint256 amount){ - cAddress.call.value(amount)(bytes4(keccak256("getZero()")));//1.5,1.7 - } -} - -contract C{ - constructor() payable public{} - function() payable public{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public{ - B b1 = (new B).value(7)();//2.2,2.7 - B b2 = (new B).value(3)();//2.4,2.9 - } -} - -contract D{ - constructor () payable public{} - function suicide1(address toAddress) public payable{ - selfdestruct(toAddress); - } - function () payable public{} - function getBalance() public view returns(uint256){ - return this.balance; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test4InternalTransaction010.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test4InternalTransaction010.sol deleted file mode 100644 index 7c10d407461..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test4InternalTransaction010.sol +++ /dev/null @@ -1,188 +0,0 @@ -pragma solidity ^0.4.24; - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - - } - function transfer2() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - - } - function getBalance() returns(uint256){ - return this.balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable returns(bool) { - return true; - } - constructor() public payable {} - function payC(address c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() returns(uint256){ - return this.balance; - } - function () payable{} - } - diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test5InternalTransaction012.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test5InternalTransaction012.sol deleted file mode 100644 index 3dd0c1b2cae..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test5InternalTransaction012.sol +++ /dev/null @@ -1,51 +0,0 @@ -pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable public{} - function test1(address bAddr,address eAddr) public payable{ - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - } - -} - -contract B{ - constructor() payable public{} - function() payable public{} - function getOne() payable returns(uint256){ - return 1; - } - function testNN(address eAddress) public payable{ - D d1=(new D).value(1000)(); - d1.getOne(eAddress); - } -} - -contract C{ - constructor() payable public{} - function() payable public{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - function() payable public{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract D{ - constructor() payable public{} - function() payable public{} - function getOne(address eAddress) payable returns(uint256){ - eAddress.call.value(1)(bytes4(keccak256("getZero()")));//2.1 - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction013.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction013.sol deleted file mode 100644 index 4e48646270f..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction013.sol +++ /dev/null @@ -1,56 +0,0 @@ -pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable public{} - function test1(address dAddr) public payable{ - B b1 = (new B).value(10)();//1.1 - b1.testNN(dAddr,2);//1.6 - // C c1 = (new C).value(1000000000000)();//1.2 - // E e1 = (new E).value(1)();//1.2 - } - function test2(address cAddress,uint256 amount) public payable{ - cAddress.call.value(amount)(bytes4(keccak256("newBAndTransfer()")));//2.1 - } -} - -contract B{ - constructor() payable public{} - function() payable public{} - function getOne() payable returns(uint256){ - return 1; - } - function testNN(address dAddress,uint256 amount) public payable{ - // D d1=(new D)(); - dAddress.call.value(amount)(bytes4(keccak256("getOne()")));//2.1 - } -} - -contract C{ - constructor() payable public{} - function() payable public{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - function() payable public{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract D{ - constructor() payable public{} - function() payable public{} - function getOne() payable returns(uint256){ - E e = (new E).value(5)(); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction014.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction014.sol deleted file mode 100644 index 46e1f8e0eed..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction014.sol +++ /dev/null @@ -1,40 +0,0 @@ -pragma solidity ^0.4.24; - -contract callerContract { - constructor() payable{} - function() payable{} - function sendToB(address called_address,address c) public payable{ - called_address.delegatecall(bytes4(keccak256("transferTo(address)")),c); - } - function sendToB2(address called_address,address c) public payable{ - called_address.call(bytes4(keccak256("transferTo(address)")),c); - } - function sendToB3(address called_address,address c) public payable{ - called_address.callcode(bytes4(keccak256("transferTo(address)")),c); - } -} - - contract calledContract { - function() payable{} - constructor() payable {} - function transferTo(address toAddress)public payable{ - toAddress.transfer(5); - } - - function setIinC(address c) public payable{ - c.call.value(5)(bytes4(keccak256("setI()"))); - } - - } - - contract c{ - uint256 public i=0; - constructor() public payable{} - function getBalance() public view returns(uint256){ - return this.balance; - } - function setI() payable{ - i=5; - } - function() payable{} - } diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction015.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction015.sol deleted file mode 100644 index 61666b44892..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction015.sol +++ /dev/null @@ -1,60 +0,0 @@ -pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable public{} - function test1(address dAddr,address eAddr) public payable{ - B b1 = (new B).value(10)();//1.1 - b1.testNN(dAddr,2,eAddr);//1.6 - // C c1 = (new C).value(1000000000000)();//1.2 - // E e1 = (new E).value(1)();//1.2 - } - function test2(address cAddress,uint256 amount) public payable{ - cAddress.call.value(amount)(bytes4(keccak256("newBAndTransfer()")));//2.1 - } -} - -contract B{ - constructor() payable public{} - function() payable public{} - function getOne() payable returns(uint256){ - return 1; - } - function testNN(address dAddress,uint256 amount,address eAddress) public payable{ - // D d1=(new D)(); - dAddress.call.value(amount)(bytes4(keccak256("getOne(address)")),address(this));//2.1 - } -} - -contract C{ - constructor() payable public{} - function() payable public{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - function() payable public{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } - function suicide(address toAddress) public payable{ - selfdestruct(toAddress); - } -} -contract D{ - constructor() payable public{} - function() payable public{} - function getOne(address eAddress) payable public{ - E e = (new E).value(5)(); - e.suicide(eAddress); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction016.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction016.sol deleted file mode 100644 index b0cbe16af4d..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction016.sol +++ /dev/null @@ -1,184 +0,0 @@ -pragma solidity ^0.4.24; - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - - B b1=(new B).value(1)();//1 - b1.suicide(this); - } - function transfer2() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - B b1=(new B).value(1)();//1 - b1.suicide(this); - } - function getBalance() returns(uint256){ - return this.balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable returns(bool) { - return true; - } - constructor() public payable {} - function payC(address c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() returns(uint256){ - return this.balance; - } - function () payable{} - function suicide(address toAddress) public payable{ - selfdestruct(toAddress); - } - } - diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction017.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction017.sol deleted file mode 100644 index 2352e61b733..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction017.sol +++ /dev/null @@ -1,194 +0,0 @@ -pragma solidity ^0.4.24; - - contract A{ - uint256 public num = 0; - constructor() public payable{} - function transfer(address Address) payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - - B b=(new B).value(1)();//1 - selfdestruct(Address); - } - function transfer2() payable public{ - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - (new B).value(1)();//1 - - } - function getBalance() public returns(uint256){ - return this.balance; - } - } - contract B{ - uint256 public num = 0; - function f() payable returns(bool) { - return true; - } - constructor() public payable {} - function payC(address c, bool isRevert) public{ - c.transfer(1);//4 - if (isRevert) { - revert(); - } - } - function getBalance() returns(uint256){ - return this.balance; - } - function () payable{} - } - diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction018.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction018.sol deleted file mode 100644 index 6341ee61b06..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction018.sol +++ /dev/null @@ -1,149 +0,0 @@ -pragma solidity ^0.4.24; - -contract A{ - constructor() payable public{} - function() payable public{} - function test1(address bAddr,address eAddr) public payable{ - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 - - - } - -} - -contract B{ - constructor() payable public{} - function() payable public{} - function getOne() payable returns(uint256){ - return 1; - } - function testNN(address eAddress) public payable{ - D d1=(new D).value(100)(); - d1.getOne(eAddress); - } -} - -contract C{ - constructor() payable public{} - function() payable public{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract E{ - constructor() payable public{} - function() payable public{} - function getZero() payable public returns(uint256){ - return 0; - } - function newBAndTransfer() payable public returns(uint256){ - require(2==1); - } -} -contract D{ - constructor() payable public{} - function() payable public{} - function getOne(address eAddress) payable returns(uint256){ - eAddress.call.value(1)(bytes4(keccak256("getZero()")));//2.1 - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractLinkage001.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractLinkage001.sol deleted file mode 100644 index 4c04cf5c6fb..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractLinkage001.sol +++ /dev/null @@ -1,9 +0,0 @@ -//pragma solidity ^0.4.0; - -contract divideIHaveArgsReturnStorage{ -constructor() payable public{} -function() payable external{} -function divideIHaveArgsReturn(int x,int y) public payable returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractLinkage002.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractLinkage002.sol deleted file mode 100644 index ca38896acee..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractLinkage002.sol +++ /dev/null @@ -1,7 +0,0 @@ -//pragma solidity ^0.4.0; - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractLinkage003.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractLinkage003.sol deleted file mode 100644 index ca38896acee..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractLinkage003.sol +++ /dev/null @@ -1,7 +0,0 @@ -//pragma solidity ^0.4.0; - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractLinkage004.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractLinkage004.sol deleted file mode 100644 index ca38896acee..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractLinkage004.sol +++ /dev/null @@ -1,7 +0,0 @@ -//pragma solidity ^0.4.0; - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractLinkage005.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractLinkage005.sol deleted file mode 100644 index 7b943aee5c1..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractLinkage005.sol +++ /dev/null @@ -1,51 +0,0 @@ -contract timeoutTest { - string public iarray1; - // cpu - function oneCpu() public { - require(1==1); - } - - function storage8Char() public { - iarray1 = "12345678"; - } - - function testUseCpu(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - } - return count; - } - - - uint256[] public iarray; - uint public calculatedFibNumber; - mapping(address=>mapping(address=>uint256)) public m; - - function testUseStorage(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - iarray.push(i); - } - return count; - } - - // stack - //uint n = 0; - uint yy = 0; - function test() public { - //n += 1; - yy += 1; - test(); - } - - function setFibonacci(uint n) public returns (uint256){ - calculatedFibNumber = fibonacci(n); - return calculatedFibNumber; - } - - function fibonacci(uint n) internal returns (uint) { - return fibonacci(n - 1) + fibonacci(n - 2); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractLinkage006.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractLinkage006.sol deleted file mode 100644 index 9b16ff63368..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractLinkage006.sol +++ /dev/null @@ -1,18 +0,0 @@ -//pragma solidity ^0.4.0; -contract AA{ - uint256 public count=0; - constructor () payable public{} - function init(address addr, uint256 max) payable public { - count =0; - this.hack(addr,max); - } - function hack(address addr, uint256 max) payable public { - while (count < max) { - count = count +1; - this.hack(addr,max); - } - if (count == max) { - addr.send(20); - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractOriginEnergyLimit001.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractOriginEnergyLimit001.sol deleted file mode 100644 index af80b15cc8b..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractOriginEnergyLimit001.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma solidity ^0.4.0; - -contract findArgsContractTest{ - function findArgsByIndexTest(uint i) public returns (uint z) { - uint[] memory a = new uint[](3); - a[0]=1; - a[1]=2; - a[2]=3; - return a[i]; - } -} diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractOriginEnergyLimit004.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractOriginEnergyLimit004.sol deleted file mode 100644 index af80b15cc8b..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractOriginEnergyLimit004.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma solidity ^0.4.0; - -contract findArgsContractTest{ - function findArgsByIndexTest(uint i) public returns (uint z) { - uint[] memory a = new uint[](3); - a[0]=1; - a[1]=2; - a[2]=3; - return a[i]; - } -} diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractOtherToTrcToken.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractOtherToTrcToken.sol deleted file mode 100644 index 1fcff0c039f..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractOtherToTrcToken.sol +++ /dev/null @@ -1,40 +0,0 @@ -pragma solidity ^0.4.24; -contract ConvertType { - -constructor() payable public{} - -function() payable external{} - -//function stringToTrctoken(address payable toAddress, string memory tokenStr, uint256 tokenValue) public { -// trcToken t = trcToken(tokenStr); // ERROR -// toAddress.transferToken(tokenValue, tokenStr); // ERROR -//} - -function uint256ToTrctoken(address toAddress,uint256 tokenValue, uint256 tokenInt) public { - trcToken t = trcToken(tokenInt); // OK - toAddress.transferToken(tokenValue, t); // OK - toAddress.transferToken(tokenValue, tokenInt); // OK -} - -function addressToTrctoken(address toAddress, uint256 tokenValue, address adr) public { - trcToken t = trcToken(adr); // OK - toAddress.transferToken(tokenValue, t); // OK -//toAddress.transferToken(tokenValue, adr); // ERROR -} - -//function bytesToTrctoken(address payable toAddress, bytes memory b, uint256 tokenValue) public { - // trcToken t = trcToken(b); // ERROR - // toAddress.transferToken(tokenValue, b); // ERROR -//} - -function bytes32ToTrctoken(address toAddress, uint256 tokenValue, bytes32 b32) public { - trcToken t = trcToken(b32); // OK - toAddress.transferToken(tokenValue, t); // OK -// toAddress.transferToken(tokenValue, b32); // ERROR -} - -//function arrayToTrctoken(address payable toAddress, uint256[] memory arr, uint256 tokenValue) public { -//trcToken t = trcToken(arr); // ERROR -// toAddress.transferToken(tokenValue, arr); // ERROR -//} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario001.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractScenario001.sol deleted file mode 100644 index ca38896acee..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario001.sol +++ /dev/null @@ -1,7 +0,0 @@ -//pragma solidity ^0.4.0; - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario002.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractScenario002.sol deleted file mode 100644 index c096bbff619..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario002.sol +++ /dev/null @@ -1,53 +0,0 @@ -//pragma solidity ^0.4.0; -contract TronNative{ - - address public voteContractAddress= address(0x10001); - address public freezeBalanceAddress = address(0x10002); - address public unFreezeBalanceAddress = address(0x10003); - address public withdrawBalanceAddress = address(0x10004); - address public approveProposalAddress = address(0x10005); - address public createProposalAddress = address(0x10006); - address public deleteProposalAddress = address(0x10007); - constructor () payable public {} - - function voteForSingleWitness (address witnessAddr, uint256 voteValue) public{ - // method 1: - voteContractAddress.delegatecall(abi.encode(witnessAddr,voteValue)); - } - - function voteUsingAssembly (address witnessAddr, uint256 voteValue) public{ - // method 2: - assembly{ - mstore(0x80,witnessAddr) - mstore(0xa0,voteValue) - // gas, address, in, size, out, size - if iszero(delegatecall(0, 0x10001, 0x80, 0x40, 0x80, 0x0)) { - revert(0, 0) - } - } - } - - function freezeBalance(uint256 frozen_Balance,uint256 frozen_Duration) public { - freezeBalanceAddress.delegatecall(abi.encode(frozen_Balance,frozen_Duration)); - } - - function unFreezeBalance() public { - unFreezeBalanceAddress.delegatecall(""); - } - - function withdrawBalance() public { - withdrawBalanceAddress.delegatecall(""); - } - - function approveProposal(uint256 id, bool isApprove) public { - approveProposalAddress.delegatecall(abi.encode(id,isApprove)); - } - - function createProposal(bytes32 [] memory data) public { - createProposalAddress.delegatecall(abi.encode(data)); - } - - function deleteProposal(uint256 id) public{ - deleteProposalAddress.delegatecall(abi.encode(id)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario003.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractScenario003.sol deleted file mode 100644 index ca38896acee..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario003.sol +++ /dev/null @@ -1,7 +0,0 @@ -//pragma solidity ^0.4.0; - -contract divideIHaveArgsReturnStorage{ -function divideIHaveArgsReturn(int x,int y) public returns (int z) { -return z = x / y; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario004.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractScenario004.sol deleted file mode 100644 index b3ca2687b4c..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario004.sol +++ /dev/null @@ -1,88 +0,0 @@ -//pragma solidity ^0.4.11; - -contract TronToken { - - string public name = "Tronix"; // token name - string public symbol = "TRX"; // token symbol - uint256 public decimals = 6; // token digit - - mapping (address => uint256) public balanceOf; - mapping (address => mapping (address => uint256)) public allowance; - - uint256 public totalSupply = 0; - bool public stopped = false; - - uint256 constant valueFounder = 100000000000000000; - address owner = address(0x0); - - modifier isOwner { - assert(owner == msg.sender); - _; - } - - modifier isRunning { - assert (!stopped); - _; - } - - modifier validAddress { - assert(address(0x0) != msg.sender); - _; - } - - constructor(address _addressFounder) public { - owner = msg.sender; - totalSupply = valueFounder; - balanceOf[_addressFounder] = valueFounder; - emit Transfer(address(0x0), _addressFounder, valueFounder); - } - - function transfer(address _to, uint256 _value) isRunning validAddress public returns (bool success) { - require(balanceOf[msg.sender] >= _value); - require(balanceOf[_to] + _value >= balanceOf[_to]); - balanceOf[msg.sender] -= _value; - balanceOf[_to] += _value; - emit Transfer(msg.sender, _to, _value); - return true; - } - - function transferFrom(address _from, address _to, uint256 _value) isRunning validAddress public returns (bool success) { - require(balanceOf[_from] >= _value); - require(balanceOf[_to] + _value >= balanceOf[_to]); - require(allowance[_from][msg.sender] >= _value); - balanceOf[_to] += _value; - balanceOf[_from] -= _value; - allowance[_from][msg.sender] -= _value; - emit Transfer(_from, _to, _value); - return true; - } - - function approve(address _spender, uint256 _value) isRunning validAddress public returns (bool success) { - require(_value == 0 || allowance[msg.sender][_spender] == 0); - allowance[msg.sender][_spender] = _value; - emit Approval(msg.sender, _spender, _value); - return true; - } - - function stop() isOwner public { - stopped = true; - } - - function start() isOwner public { - stopped = false; - } - - function setName(string memory _name) isOwner public { - name = _name; - } - - function burn(uint256 _value) public { - require(balanceOf[msg.sender] >= _value); - balanceOf[msg.sender] -= _value; - balanceOf[address(0x0)] += _value; - emit Transfer(msg.sender, address(0x0), _value); - } - - event Transfer(address indexed _from, address indexed _to, uint256 _value); - event Approval(address indexed _owner, address indexed _spender, uint256 _value); -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario005.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractScenario005.sol deleted file mode 100644 index f4bec71761c..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario005.sol +++ /dev/null @@ -1,103 +0,0 @@ -//pragma solidity ^0.4.16; - -interface token { - function transfer(address receiver, uint amount); -} - -contract Crowdsale { - address public beneficiary = 0x1B228F5D9F934C7BB18AAA86F90418932888E7B4; // 募资成功后的收款方 - uint public fundingGoal = 10000000; // 募资额度 - uint public amountRaised = 1000000; // 参与数量 - uint public deadline; // 募资截止期 - - uint public price; // token 与以太坊的汇率 , token卖多少钱 - token public tokenReward; // 要卖的token - - mapping(address => uint256) public balanceOf; - - bool fundingGoalReached = false; // 众筹是否达到目标 - bool crowdsaleClosed = false; // 众筹是否结束 - - /** - * 事件可以用来跟踪信息 - **/ - event GoalReached(address recipient, uint totalAmountRaised); - event FundTransfer(address backer, uint amount, bool isContribution); - - /** - * 构造函数, 设置相关属性 - */ - function Crowdsale( - address ifSuccessfulSendTo, - uint fundingGoalInEthers, - uint durationInMinutes, - uint finneyCostOfEachToken, - address addressOfTokenUsedAsReward) { - beneficiary = ifSuccessfulSendTo; - fundingGoal = fundingGoalInEthers * 1 sun; - deadline = now + durationInMinutes * 1 minutes; - price = finneyCostOfEachToken * 1 sun; - tokenReward = token(addressOfTokenUsedAsReward); // 传入已发布的 token 合约的地址来创建实例 - } - - /** - * 无函数名的Fallback函数, - * 在向合约转账时,这个函数会被调用 - */ - function () payable { - require(!crowdsaleClosed); - uint amount = msg.value; - balanceOf[msg.sender] += amount; - amountRaised += amount; - tokenReward.transfer(msg.sender, amount / price); - FundTransfer(msg.sender, amount, true); - } - - /** - * 定义函数修改器modifier(作用和Python的装饰器很相似) - * 用于在函数执行前检查某种前置条件(判断通过之后才会继续执行该方法) - * _ 表示继续执行之后的代码 - **/ - modifier afterDeadline() { if (now >= deadline) _; } - - /** - * 判断众筹是否完成融资目标, 这个方法使用了afterDeadline函数修改器 - * - */ - function checkGoalReached() afterDeadline { - if (amountRaised >= fundingGoal) { - fundingGoalReached = true; - GoalReached(beneficiary, amountRaised); - } - crowdsaleClosed = true; - } - - - /** - * 完成融资目标时,融资款发送到收款方 - * 未完成融资目标时,执行退款 - * - */ - function safeWithdrawal() afterDeadline { - if (!fundingGoalReached) { - uint amount = balanceOf[msg.sender]; - balanceOf[msg.sender] = 0; - if (amount > 0) { - if (msg.sender.send(amount)) { - FundTransfer(msg.sender, amount, false); - } else { - balanceOf[msg.sender] = amount; - } - } - } - - if (fundingGoalReached && beneficiary == msg.sender) { - if (beneficiary.send(amountRaised)) { - FundTransfer(beneficiary, amountRaised, false); - } else { - //If we fail to send the funds to beneficiary, unlock funders balance - fundingGoalReached = false; - } - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario006.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractScenario006.sol deleted file mode 100644 index af55371cb6e..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario006.sol +++ /dev/null @@ -1,1954 +0,0 @@ -//pragma solidity ^0.4.24; - -interface PlayerBookInterface { - function getPlayerID(address _addr) external returns (uint256); - function getPlayerName(uint256 _pID) external view returns (bytes32); - function getPlayerLAff(uint256 _pID) external view returns (uint256); - function getPlayerAddr(uint256 _pID) external view returns (address); - function getNameFee() external view returns (uint256); - function registerNameXIDFromDapp(address _addr, bytes32 _name, uint256 _affCode, bool _all) external payable returns(bool, uint256); - function registerNameXaddrFromDapp(address _addr, bytes32 _name, address _affCode, bool _all) external payable returns(bool, uint256); - function registerNameXnameFromDapp(address _addr, bytes32 _name, bytes32 _affCode, bool _all) external payable returns(bool, uint256); - function isDev(address _who) external view returns(bool); -} - - -/** -* @title -Name Filter- v0.1.9 -* ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ -* │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ -* ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ -* _____ _____ -* (, / /) /) /) (, / /) /) -* ┌─┐ / _ (/_ // // / _ // _ __ _(/ -* ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ -* ┴ ┴ / / .-/ _____ (__ / -* (__ / (_/ (, / /)™ -* / __ __ __ __ _ __ __ _ _/_ _ _(/ -* ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ -* ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 -* ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ -* _ __ _ ____ ____ _ _ _____ ____ ___ -*=============| |\ | / /\ | |\/| | |_ =====| |_ | | | | | | | |_ | |_)==============* -*=============|_| \| /_/--\ |_| | |_|__=====|_| |_| |_|__ |_| |_|__ |_| \==============* -* -* ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ -* ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ -* ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ -*/ - -library NameFilter { - /** - * @dev filters name strings - * -converts uppercase to lower case. - * -makes sure it does not start/end with a space - * -makes sure it does not contain multiple spaces in a row - * -cannot be only numbers - * -cannot start with 0x - * -restricts characters to A-Z, a-z, 0-9, and space. - * @return reprocessed string in bytes32 format - */ - function nameFilter(string _input) - internal - pure - returns(bytes32) - { - bytes memory _temp = bytes(_input); - uint256 _length = _temp.length; - - //sorry limited to 32 characters - require (_length <= 32 && _length > 0, "string must be between 1 and 32 characters"); - // make sure it doesnt start with or end with space - require(_temp[0] != 0x20 && _temp[_length-1] != 0x20, "string cannot start or end with space"); - // make sure first two characters are not 0x - if (_temp[0] == 0x30) - { - require(_temp[1] != 0x78, "string cannot start with 0x"); - require(_temp[1] != 0x58, "string cannot start with 0X"); - } - - // create a bool to track if we have a non number character - bool _hasNonNumber; - - // convert & check - for (uint256 i = 0; i < _length; i++) - { - // if its uppercase A-Z - if (_temp[i] > 0x40 && _temp[i] < 0x5b) - { - // convert to lower case a-z - _temp[i] = byte(uint(_temp[i]) + 32); - - // we have a non number - if (_hasNonNumber == false) - _hasNonNumber = true; - } else { - require - ( - // require character is a space - _temp[i] == 0x20 || - // OR lowercase a-z - (_temp[i] > 0x60 && _temp[i] < 0x7b) || - // or 0-9 - (_temp[i] > 0x2f && _temp[i] < 0x3a), - "string contains invalid characters" - ); - // make sure theres not 2x spaces in a row - if (_temp[i] == 0x20) - require( _temp[i+1] != 0x20, "string cannot contain consecutive spaces"); - - // see if we have a character other than a number - if (_hasNonNumber == false && (_temp[i] < 0x30 || _temp[i] > 0x39)) - _hasNonNumber = true; - } - } - - require(_hasNonNumber == true, "string cannot be only numbers"); - - bytes32 _ret; - assembly { - _ret := mload(add(_temp, 32)) - } - return (_ret); - } -} - - -library SafeMath { - - /** - * @dev Multiplies two numbers, throws on overflow. - */ - function mul(uint256 a, uint256 b) - internal - pure - returns (uint256 c) - { - if (a == 0) { - return 0; - } - c = a * b; - require(c / a == b, "SafeMath mul failed"); - return c; - } - - /** - * @dev Integer division of two numbers, truncating the quotient. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // assert(b > 0); // Solidity automatically throws when dividing by 0 - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - return c; - } - - /** - * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 a, uint256 b) - internal - pure - returns (uint256) - { - require(b <= a, "SafeMath sub failed"); - return a - b; - } - - /** - * @dev Adds two numbers, throws on overflow. - */ - function add(uint256 a, uint256 b) - internal - pure - returns (uint256 c) - { - c = a + b; - require(c >= a, "SafeMath add failed"); - return c; - } - - /** - * @dev gives square root of given x. - */ - function sqrt(uint256 x) - internal - pure - returns (uint256 y) - { - uint256 z = ((add(x,1)) / 2); - y = x; - while (z < y) - { - y = z; - z = ((add((x / z),z)) / 2); - } - } - - /** - * @dev gives square. multiplies x by x - */ - function sq(uint256 x) - internal - pure - returns (uint256) - { - return (mul(x,x)); - } - - /** - * @dev x to the power of y - */ - function pwr(uint256 x, uint256 y) - internal - pure - returns (uint256) - { - if (x==0) - return (0); - else if (y==0) - return (1); - else - { - uint256 z = x; - for (uint256 i=1; i < y; i++) - z = mul(z,x); - return (z); - } - } -} - -//============================================================================== -// | _ _ _ | _ . -// |<(/_\/ (_(_||(_ . -//=======/====================================================================== -library F3DKeysCalcLong { - using SafeMath for *; - /** - * @dev calculates number of keys received given X eth - * @param _curEth current amount of eth in contract - * @param _newEth eth being spent - * @return amount of ticket purchased - */ - function keysRec(uint256 _curEth, uint256 _newEth) - internal - pure - returns (uint256) - { - return(keys((_curEth).add(_newEth)).sub(keys(_curEth))); - } - - /** - * @dev calculates amount of eth received if you sold X keys - * @param _curKeys current amount of keys that exist - * @param _sellKeys amount of keys you wish to sell - * @return amount of eth received - */ - function ethRec(uint256 _curKeys, uint256 _sellKeys) - internal - pure - returns (uint256) - { - return((eth(_curKeys)).sub(eth(_curKeys.sub(_sellKeys)))); - } - - /** - * @dev calculates how many keys would exist with given an amount of eth - * @param _eth eth "in contract" - * @return number of keys that would exist - */ - function keys(uint256 _eth) - internal - pure - returns(uint256) - { - return ((((((_eth).mul(1000000000000000000)).mul(312500000000000000000000000)).add(5624988281256103515625000000000000000000000000000000000000000000)).sqrt()).sub(74999921875000000000000000000000)) / (156250000); - } - - /** - * @dev calculates how much eth would be in contract given a number of keys - * @param _keys number of keys "in contract" - * @return eth that would exists - */ - function eth(uint256 _keys) - internal - pure - returns(uint256) - { - return ((78125000).mul(_keys.sq()).add(((149999843750000).mul(_keys.mul(1000000000000000000))) / (2))) / ((1000000000000000000).sq()); - } -} - -library F3Ddatasets { - //compressedData key - // [76-33][32][31][30][29][28-18][17][16-6][5-3][2][1][0] - // 0 - new player (bool) - // 1 - joined round (bool) - // 2 - new leader (bool) - // 3-5 - air drop tracker (uint 0-999) - // 6-16 - round end time - // 17 - winnerTeam - // 18 - 28 timestamp - // 29 - team - // 30 - 0 = reinvest (round), 1 = buy (round), 2 = buy (ico), 3 = reinvest (ico) - // 31 - airdrop happened bool - // 32 - airdrop tier - // 33 - airdrop amount won - //compressedIDs key - // [77-52][51-26][25-0] - // 0-25 - pID - // 26-51 - winPID - // 52-77 - rID - struct EventReturns { - uint256 compressedData; - uint256 compressedIDs; - address winnerAddr; // winner address - bytes32 winnerName; // winner name - uint256 amountWon; // amount won - uint256 newPot; // amount in new pot - uint256 P3DAmount; // amount distributed to p3d - uint256 genAmount; // amount distributed to gen - uint256 potAmount; // amount added to pot - } - struct Player { - address addr; // player address - bytes32 name; // player name - uint256 win; // winnings vault - uint256 gen; // general vault - uint256 aff; // affiliate vault - uint256 lrnd; // last round played - uint256 laff; // last affiliate id used - } - struct PlayerRounds { - uint256 eth; // eth player has added to round (used for eth limiter) - uint256 keys; // keys - uint256 mask; // player mask - uint256 ico; // ICO phase investment - } - struct Round { - uint256 plyr; // pID of player in lead - uint256 team; // tID of team in lead - uint256 end; // time ends/ended - bool ended; // has round end function been ran - uint256 strt; // time round started - uint256 keys; // keys - uint256 eth; // total eth in - uint256 pot; // eth to pot (during round) / final amount paid to winner (after round ends) - uint256 mask; // global mask - uint256 ico; // total eth sent in during ICO phase - uint256 icoGen; // total eth for gen during ICO phase - uint256 icoAvg; // average key price for ICO phase - } - struct TeamFee { - uint256 gen; // % of buy in thats paid to key holders of current round - uint256 p3d; // % of buy in thats paid to p3d holders - } - struct PotSplit { - uint256 gen; // % of pot thats paid to key holders of current round - uint256 p3d; // % of pot thats paid to p3d holders - } -} - -contract F3Devents { - // fired whenever a player registers a name - event onNewName - ( - uint256 indexed playerID, - address indexed playerAddress, - bytes32 indexed playerName, - bool isNewPlayer, - uint256 affiliateID, - address affiliateAddress, - bytes32 affiliateName, - uint256 amountPaid, - uint256 timeStamp - ); - - // fired at end of buy or reload - event onEndTx - ( - uint256 compressedData, - uint256 compressedIDs, - bytes32 playerName, - address playerAddress, - uint256 ethIn, - uint256 keysBought, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount, - uint256 potAmount, - uint256 airDropPot - ); - - // fired whenever theres a withdraw - event onWithdraw - ( - uint256 indexed playerID, - address playerAddress, - bytes32 playerName, - uint256 ethOut, - uint256 timeStamp - ); - - // fired whenever a withdraw forces end round to be ran - event onWithdrawAndDistribute - ( - address playerAddress, - bytes32 playerName, - uint256 ethOut, - uint256 compressedData, - uint256 compressedIDs, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount - ); - - // (fomo3d long only) fired whenever a player tries a buy after round timer - // hit zero, and causes end round to be ran. - event onBuyAndDistribute - ( - address playerAddress, - bytes32 playerName, - uint256 ethIn, - uint256 compressedData, - uint256 compressedIDs, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount - ); - - // (fomo3d long only) fired whenever a player tries a reload after round timer - // hit zero, and causes end round to be ran. - event onReLoadAndDistribute - ( - address playerAddress, - bytes32 playerName, - uint256 compressedData, - uint256 compressedIDs, - address winnerAddr, - bytes32 winnerName, - uint256 amountWon, - uint256 newPot, - uint256 P3DAmount, - uint256 genAmount - ); - - // fired whenever an affiliate is paid - event onAffiliatePayout - ( - uint256 indexed affiliateID, - address affiliateAddress, - bytes32 affiliateName, - uint256 indexed roundID, - uint256 indexed buyerID, - uint256 amount, - uint256 timeStamp - ); - - // received pot swap deposit - event onPotSwapDeposit - ( - uint256 roundID, - uint256 amountAddedToPot - ); -} - - - -contract FoMo3Dlong is F3Devents { - using SafeMath for *; - using NameFilter for string; - using F3DKeysCalcLong for uint256; - - address public otherF3D_; - address public Divies; - address public Jekyll_Island_Inc; - PlayerBookInterface public playerBook;// =PlayerBookInterface(0x0dcd2f752394c41875e259e00bb44fd505297caf);//new PlayerBook();// - // TeamJustInterface constant private teamJust = TeamJustInterface(0x3a5f8140b9213a0f733a6a639857c9df43ee3f5a);// new TeamJust();// - - //============================================================================== - // _ _ _ |`. _ _ _ |_ | _ _ . - // (_(_)| |~|~|(_||_|| (_||_)|(/__\ . (game settings) - //=================_|=========================================================== - string constant public name = "FoMo3D Long Official"; - string constant public symbol = "F3D"; - uint256 private rndExtra_ = 30;//extSettings.getLongExtra(); // length of the very first ICO - uint256 private rndGap_ = 30; //extSettings.getLongGap(); // length of ICO phase, set to 1 year for EOS. - uint256 constant private rndInit_ = 1 hours; // round timer starts at this - uint256 constant private rndInc_ = 30 seconds; // every full key purchased adds this much to the timer - uint256 constant private rndMax_ = 24 hours; // max length a round timer can be - //============================================================================== - // _| _ _|_ _ _ _ _|_ _ . - // (_|(_| | (_| _\(/_ | |_||_) . (data used to store game info that changes) - //=============================|================================================ - uint256 public airDropPot_; // person who gets the airdrop wins part of this pot - uint256 public airDropTracker_ = 0; // incremented each time a "qualified" tx occurs. used to determine winning air drop - uint256 public rID_; // round id number / total rounds that have happened - //**************** - // PLAYER DATA - //**************** - mapping(address => uint256) public pIDxAddr_; // (addr => pID) returns player id by address - mapping(bytes32 => uint256) public pIDxName_; // (name => pID) returns player id by name - mapping(uint256 => F3Ddatasets.Player) public plyr_; // (pID => data) player data - mapping(uint256 => mapping(uint256 => F3Ddatasets.PlayerRounds)) public plyrRnds_; // (pID => rID => data) player round data by player id & round id - mapping(uint256 => mapping(bytes32 => bool)) public plyrNames_; // (pID => name => bool) list of names a player owns. (used so you can change your display name amongst any name you own) - //**************** - // ROUND DATA - //**************** - mapping(uint256 => F3Ddatasets.Round) public round_; // (rID => data) round data - mapping(uint256 => mapping(uint256 => uint256)) public rndTmEth_; // (rID => tID => data) eth in per team, by round id and team id - //**************** - // TEAM FEE DATA - //**************** - mapping(uint256 => F3Ddatasets.TeamFee) public fees_; // (team => fees) fee distribution by team - mapping(uint256 => F3Ddatasets.PotSplit) public potSplit_; // (team => fees) pot split distribution by team - - function setPlayerBook(address _playerBook) external { - require(msg.sender == owner, 'only dev!'); - require(address(playerBook) == address(0), 'already set!'); - playerBook = PlayerBookInterface(_playerBook); - } - - address public owner; - - //============================================================================== - // _ _ _ __|_ _ __|_ _ _ . - // (_(_)| |_\ | | |_|(_ | (_)| . (initial data setup upon contract deploy) - //============================================================================== - constructor() - public - { - owner = msg.sender; - // Team allocation structures - // 0 = whales - // 1 = bears - // 2 = sneks - // 3 = bulls - - // Team allocation percentages - // (F3D, P3D) + (Pot , Referrals, Community) - // Referrals / Community rewards are mathematically designed to come from the winner's share of the pot. - fees_[0] = F3Ddatasets.TeamFee(30, 6); - //50% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - fees_[1] = F3Ddatasets.TeamFee(43, 0); - //43% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - fees_[2] = F3Ddatasets.TeamFee(56, 10); - //20% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - fees_[3] = F3Ddatasets.TeamFee(43, 8); - //35% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot - - // how to split up the final pot based on which team was picked - // (F3D, P3D) - potSplit_[0] = F3Ddatasets.PotSplit(15, 10); - //48% to winner, 25% to next round, 2% to com - potSplit_[1] = F3Ddatasets.PotSplit(25, 0); - //48% to winner, 25% to next round, 2% to com - potSplit_[2] = F3Ddatasets.PotSplit(20, 20); - //48% to winner, 10% to next round, 2% to com - potSplit_[3] = F3Ddatasets.PotSplit(30, 10); - //48% to winner, 10% to next round, 2% to com - } - //============================================================================== - // _ _ _ _|. |`. _ _ _ . - // | | |(_)(_||~|~|(/_| _\ . (these are safety checks) - //============================================================================== - /** - * @dev used to make sure no one can interact with contract until it has - * been activated. - */ - modifier isActivated() { - require(activated_ == true, "its not ready yet. check ?eta in discord"); - _; - } - - /** - * @dev prevents contracts from interacting with fomo3d - */ - modifier isHuman() { - address _addr = msg.sender; - uint256 _codeLength; - - assembly {_codeLength := extcodesize(_addr)} - require(_codeLength == 0, "sorry humans only"); - _; - } - - modifier onlyDevs() - { - require(playerBook.isDev(msg.sender) == true, "msg sender is not a dev"); - _; - } - - /** - * @dev sets boundaries for incoming tx - */ - modifier isWithinLimits(uint256 _eth) { - require(_eth >= 1000000000, "pocket lint: not a valid currency"); - require(_eth <= 100000000000000000000000, "no vitalik, no"); - _; - } - - //============================================================================== - // _ |_ |. _ |` _ __|_. _ _ _ . - // |_)|_||_)||(_ ~|~|_|| |(_ | |(_)| |_\ . (use these to interact with contract) - //====|========================================================================= - /** - * @dev emergency buy uses last stored affiliate ID and team snek - */ - function() - isActivated() - isHuman() - isWithinLimits(msg.value) - public - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // buy core - buyCore(_pID, plyr_[_pID].laff, 2, _eventData_); - } - - /** - * @dev converts all incoming ethereum to keys. - * -functionhash- 0x8f38f309 (using ID for affiliate) - * -functionhash- 0x98a0871d (using address for affiliate) - * -functionhash- 0xa65b37a1 (using name for affiliate) - * @param _affCode the ID/address/name of the player who gets the affiliate fee - * @param _team what team is the player playing for? - */ - function buyXid(uint256 _affCode, uint256 _team) - isActivated() - isHuman() - isWithinLimits(msg.value) - public - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == 0 || _affCode == _pID) - { - // use last stored affiliate code - _affCode = plyr_[_pID].laff; - - // if affiliate code was given & its not the same as previously stored - } else if (_affCode != plyr_[_pID].laff) { - // update last affiliate - plyr_[_pID].laff = _affCode; - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // buy core - buyCore(_pID, _affCode, _team, _eventData_); - } - - function buyXaddr(address _affCode, uint256 _team) - isActivated() - isHuman() - isWithinLimits(msg.value) - public - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == address(0) || _affCode == msg.sender) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxAddr_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // buy core - buyCore(_pID, _affID, _team, _eventData_); - } - - function buyXname(bytes32 _affCode, uint256 _team) - isActivated() - isHuman() - isWithinLimits(msg.value) - public - payable - { - // set up our tx event data and determine if player is new or not - F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); - - // fetch player id - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == '' || _affCode == plyr_[_pID].name) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxName_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // buy core - buyCore(_pID, _affID, _team, _eventData_); - } - - /** - * @dev essentially the same as buy, but instead of you sending ether - * from your wallet, it uses your unwithdrawn earnings. - * -functionhash- 0x349cdcac (using ID for affiliate) - * -functionhash- 0x82bfc739 (using address for affiliate) - * -functionhash- 0x079ce327 (using name for affiliate) - * @param _affCode the ID/address/name of the player who gets the affiliate fee - * @param _team what team is the player playing for? - * @param _eth amount of earnings to use (remainder returned to gen vault) - */ - function reLoadXid(uint256 _affCode, uint256 _team, uint256 _eth) - isActivated() - isHuman() - isWithinLimits(_eth) - public - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == 0 || _affCode == _pID) - { - // use last stored affiliate code - _affCode = plyr_[_pID].laff; - - // if affiliate code was given & its not the same as previously stored - } else if (_affCode != plyr_[_pID].laff) { - // update last affiliate - plyr_[_pID].laff = _affCode; - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // reload core - reLoadCore(_pID, _affCode, _team, _eth, _eventData_); - } - - function reLoadXaddr(address _affCode, uint256 _team, uint256 _eth) - isActivated() - isHuman() - isWithinLimits(_eth) - public - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == address(0) || _affCode == msg.sender) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxAddr_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // reload core - reLoadCore(_pID, _affID, _team, _eth, _eventData_); - } - - function reLoadXname(bytes32 _affCode, uint256 _team, uint256 _eth) - isActivated() - isHuman() - isWithinLimits(_eth) - public - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // manage affiliate residuals - uint256 _affID; - // if no affiliate code was given or player tried to use their own, lolz - if (_affCode == '' || _affCode == plyr_[_pID].name) - { - // use last stored affiliate code - _affID = plyr_[_pID].laff; - - // if affiliate code was given - } else { - // get affiliate ID from aff Code - _affID = pIDxName_[_affCode]; - - // if affID is not the same as previously stored - if (_affID != plyr_[_pID].laff) - { - // update last affiliate - plyr_[_pID].laff = _affID; - } - } - - // verify a valid team was selected - _team = verifyTeam(_team); - - // reload core - reLoadCore(_pID, _affID, _team, _eth, _eventData_); - } - - /** - * @dev withdraws all of your earnings. - * -functionhash- 0x3ccfd60b - */ - function withdraw() - isActivated() - isHuman() - public - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = now; - - // fetch player ID - uint256 _pID = pIDxAddr_[msg.sender]; - - // setup temp var for player eth - uint256 _eth; - - // check to see if round has ended and no one has run round end yet - if (_now > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) - { - // set up our tx event data - F3Ddatasets.EventReturns memory _eventData_; - - // end the round (distributes pot) - round_[_rID].ended = true; - _eventData_ = endRound(_eventData_); - - // get their earnings - _eth = withdrawEarnings(_pID); - - // gib moni - if (_eth > 0) - plyr_[_pID].addr.transfer(_eth); - - // build event data - _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; - - // fire withdraw and distribute event - emit F3Devents.onWithdrawAndDistribute - ( - msg.sender, - plyr_[_pID].name, - _eth, - _eventData_.compressedData, - _eventData_.compressedIDs, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount - ); - - // in any other situation - } else { - // get their earnings - _eth = withdrawEarnings(_pID); - - // gib moni - if (_eth > 0) - plyr_[_pID].addr.transfer(_eth); - - // fire withdraw event - emit F3Devents.onWithdraw(_pID, msg.sender, plyr_[_pID].name, _eth, _now); - } - } - - /** - * @dev use these to register names. they are just wrappers that will send the - * registration requests to the PlayerBook contract. So registering here is the - * same as registering there. UI will always display the last name you registered. - * but you will still own all previously registered names to use as affiliate - * links. - * - must pay a registration fee. - * - name must be unique - * - names will be converted to lowercase - * - name cannot start or end with a space - * - cannot have more than 1 space in a row - * - cannot be only numbers - * - cannot start with 0x - * - name must be at least 1 char - * - max length of 32 characters long - * - allowed characters: a-z, 0-9, and space - * -functionhash- 0x921dec21 (using ID for affiliate) - * -functionhash- 0x3ddd4698 (using address for affiliate) - * -functionhash- 0x685ffd83 (using name for affiliate) - * @param _nameString players desired name - * @param _affCode affiliate ID, address, or name of who referred you - * @param _all set to true if you want this to push your info to all games - * (this might cost a lot of gas) - */ - function registerNameXID(string _nameString, uint256 _affCode, bool _all) - isHuman() - public - payable - { - bytes32 _name = _nameString.nameFilter(); - address _addr = msg.sender; - uint256 _paid = msg.value; - (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXIDFromDapp.value(_paid)(_addr, _name, _affCode, _all); - - uint256 _pID = pIDxAddr_[_addr]; - - // fire event - emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); - } - - function registerNameXaddr(string _nameString, address _affCode, bool _all) - isHuman() - public - payable - { - bytes32 _name = _nameString.nameFilter(); - address _addr = msg.sender; - uint256 _paid = msg.value; - (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXaddrFromDapp.value(msg.value)(msg.sender, _name, _affCode, _all); - - uint256 _pID = pIDxAddr_[_addr]; - - // fire event - emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); - } - - function registerNameXname(string _nameString, bytes32 _affCode, bool _all) - isHuman() - public - payable - { - bytes32 _name = _nameString.nameFilter(); - address _addr = msg.sender; - uint256 _paid = msg.value; - (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXnameFromDapp.value(msg.value)(msg.sender, _name, _affCode, _all); - - uint256 _pID = pIDxAddr_[_addr]; - - // fire event - emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); - } - //============================================================================== - // _ _ _|__|_ _ _ _ . - // (_|(/_ | | (/_| _\ . (for UI & viewing things on etherscan) - //=====_|======================================================================= - /** - * @dev return the price buyer will pay for next 1 individual key. - * -functionhash- 0x018a25e8 - * @return price for next key bought (in wei format) - */ - function getBuyPrice() - public - view - returns (uint256) - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = now; - - // are we in a round? - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - return ((round_[_rID].keys.add(1000000000000000000)).ethRec(1000000000000000000)); - else // rounds over. need price for new round - return (75000000000000); - // init - } - - /** - * @dev returns time left. dont spam this, you'll ddos yourself from your node - * provider - * -functionhash- 0xc7e284b8 - * @return time left in seconds - */ - function getTimeLeft() - public - view - returns (uint256) - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = now; - - if (_now < round_[_rID].end) - if (_now > round_[_rID].strt + rndGap_) - return ((round_[_rID].end).sub(_now)); - else - return ((round_[_rID].strt + rndGap_).sub(_now)); - else - return (0); - } - - /** - * @dev returns player earnings per vaults - * -functionhash- 0x63066434 - * @return winnings vault - * @return general vault - * @return affiliate vault - */ - function getPlayerVaults(uint256 _pID) - public - view - returns (uint256, uint256, uint256) - { - // setup local rID - uint256 _rID = rID_; - - // if round has ended. but round end has not been run (so contract has not distributed winnings) - if (now > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) - { - // if player is winner - if (round_[_rID].plyr == _pID) - { - return - ( - (plyr_[_pID].win).add(((round_[_rID].pot).mul(48)) / 100), - (plyr_[_pID].gen).add(getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask)), - plyr_[_pID].aff - ); - // if player is not the winner - } else { - return - ( - plyr_[_pID].win, - (plyr_[_pID].gen).add(getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask)), - plyr_[_pID].aff - ); - } - - // if round is still going on, or round has ended and round end has been ran - } else { - return - ( - plyr_[_pID].win, - (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), - plyr_[_pID].aff - ); - } - } - - /** - * solidity hates stack limits. this lets us avoid that hate - */ - function getPlayerVaultsHelper(uint256 _pID, uint256 _rID) - private - view - returns (uint256) - { - return (((((round_[_rID].mask).add(((((round_[_rID].pot).mul(potSplit_[round_[_rID].team].gen)) / 100).mul(1000000000000000000)) / (round_[_rID].keys))).mul(plyrRnds_[_pID][_rID].keys)) / 1000000000000000000)); - } - - /** - * @dev returns all current round info needed for front end - * -functionhash- 0x747dff42 - * @return eth invested during ICO phase - * @return round id - * @return total keys for round - * @return time round ends - * @return time round started - * @return current pot - * @return current team ID & player ID in lead - * @return current player in leads address - * @return current player in leads name - * @return whales eth in for round - * @return bears eth in for round - * @return sneks eth in for round - * @return bulls eth in for round - * @return airdrop tracker # & airdrop pot - */ - function getCurrentRoundInfo() - public - view - returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256, address, bytes32, uint256, uint256, uint256, uint256, uint256) - { - // setup local rID - uint256 _rID = rID_; - - return - ( - round_[_rID].ico, //0 - _rID, //1 - round_[_rID].keys, //2 - round_[_rID].end, //3 - round_[_rID].strt, //4 - round_[_rID].pot, //5 - (round_[_rID].team + (round_[_rID].plyr * 10)), //6 - plyr_[round_[_rID].plyr].addr, //7 - plyr_[round_[_rID].plyr].name, //8 - rndTmEth_[_rID][0], //9 - rndTmEth_[_rID][1], //10 - rndTmEth_[_rID][2], //11 - rndTmEth_[_rID][3], //12 - airDropTracker_ + (airDropPot_ * 1000) //13 - ); - } - - /** - * @dev returns player info based on address. if no address is given, it will - * use msg.sender - * -functionhash- 0xee0b5d8b - * @param _addr address of the player you want to lookup - * @return player ID - * @return player name - * @return keys owned (current round) - * @return winnings vault - * @return general vault - * @return affiliate vault - * @return player round eth - */ - function getPlayerInfoByAddress(address _addr) - public - view - returns (uint256, bytes32, uint256, uint256, uint256, uint256, uint256) - { - // setup local rID - uint256 _rID = rID_; - - if (_addr == address(0)) - { - _addr == msg.sender; - } - uint256 _pID = pIDxAddr_[_addr]; - - return - ( - _pID, //0 - plyr_[_pID].name, //1 - plyrRnds_[_pID][_rID].keys, //2 - plyr_[_pID].win, //3 - (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), //4 - plyr_[_pID].aff, //5 - plyrRnds_[_pID][_rID].eth //6 - ); - } - - //============================================================================== - // _ _ _ _ | _ _ . _ . - // (_(_)| (/_ |(_)(_||(_ . (this + tools + calcs + modules = our softwares engine) - //=====================_|======================================================= - /** - * @dev logic runs whenever a buy order is executed. determines how to handle - * incoming eth depending on if we are in an active round or not - */ - function buyCore(uint256 _pID, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) - private - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = now; - - // if round is active - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - { - // call core - core(_rID, _pID, msg.value, _affID, _team, _eventData_); - - // if round is not active - } else { - // check to see if end round needs to be ran - if (_now > round_[_rID].end && round_[_rID].ended == false) - { - // end the round (distributes pot) & start new round - round_[_rID].ended = true; - _eventData_ = endRound(_eventData_); - - // build event data - _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; - - // fire buy and distribute event - emit F3Devents.onBuyAndDistribute - ( - msg.sender, - plyr_[_pID].name, - msg.value, - _eventData_.compressedData, - _eventData_.compressedIDs, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount - ); - } - - // put eth in players vault - plyr_[_pID].gen = plyr_[_pID].gen.add(msg.value); - } - } - - /** - * @dev logic runs whenever a reload order is executed. determines how to handle - * incoming eth depending on if we are in an active round or not - */ - function reLoadCore(uint256 _pID, uint256 _affID, uint256 _team, uint256 _eth, F3Ddatasets.EventReturns memory _eventData_) - private - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = now; - - // if round is active - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - { - // get earnings from all vaults and return unused to gen vault - // because we use a custom safemath library. this will throw if player - // tried to spend more eth than they have. - plyr_[_pID].gen = withdrawEarnings(_pID).sub(_eth); - - // call core - core(_rID, _pID, _eth, _affID, _team, _eventData_); - - // if round is not active and end round needs to be ran - } else if (_now > round_[_rID].end && round_[_rID].ended == false) { - // end the round (distributes pot) & start new round - round_[_rID].ended = true; - _eventData_ = endRound(_eventData_); - - // build event data - _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; - - // fire buy and distribute event - emit F3Devents.onReLoadAndDistribute - ( - msg.sender, - plyr_[_pID].name, - _eventData_.compressedData, - _eventData_.compressedIDs, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount - ); - } - } - - /** - * @dev this is the core logic for any buy/reload that happens while a round - * is live. - */ - function core(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) - private - { - // if player is new to round - if (plyrRnds_[_pID][_rID].keys == 0) - _eventData_ = managePlayer(_pID, _eventData_); - - // early round eth limiter - if (round_[_rID].eth < 100000000000000000000 && plyrRnds_[_pID][_rID].eth.add(_eth) > 1000000000000000000) - { - uint256 _availableLimit = (1000000000000000000).sub(plyrRnds_[_pID][_rID].eth); - uint256 _refund = _eth.sub(_availableLimit); - plyr_[_pID].gen = plyr_[_pID].gen.add(_refund); - _eth = _availableLimit; - } - - // if eth left is greater than min eth allowed (sorry no pocket lint) - if (_eth > 1000000000) - { - - // mint the new keys - uint256 _keys = (round_[_rID].eth).keysRec(_eth); - - // if they bought at least 1 whole key - if (_keys >= 1000000000000000000) - { - updateTimer(_keys, _rID); - - // set new leaders - if (round_[_rID].plyr != _pID) - round_[_rID].plyr = _pID; - if (round_[_rID].team != _team) - round_[_rID].team = _team; - - // set the new leader bool to true - _eventData_.compressedData = _eventData_.compressedData + 100; - } - - // manage airdrops - if (_eth >= 100000000000000000) - { - airDropTracker_++; - if (airdrop() == true) - { - // gib muni - uint256 _prize; - if (_eth >= 10000000000000000000) - { - // calculate prize and give it to winner - _prize = ((airDropPot_).mul(75)) / 100; - plyr_[_pID].win = (plyr_[_pID].win).add(_prize); - - // adjust airDropPot - airDropPot_ = (airDropPot_).sub(_prize); - - // let event know a tier 3 prize was won - _eventData_.compressedData += 300000000000000000000000000000000; - } else if (_eth >= 1000000000000000000 && _eth < 10000000000000000000) { - // calculate prize and give it to winner - _prize = ((airDropPot_).mul(50)) / 100; - plyr_[_pID].win = (plyr_[_pID].win).add(_prize); - - // adjust airDropPot - airDropPot_ = (airDropPot_).sub(_prize); - - // let event know a tier 2 prize was won - _eventData_.compressedData += 200000000000000000000000000000000; - } else if (_eth >= 100000000000000000 && _eth < 1000000000000000000) { - // calculate prize and give it to winner - _prize = ((airDropPot_).mul(25)) / 100; - plyr_[_pID].win = (plyr_[_pID].win).add(_prize); - - // adjust airDropPot - airDropPot_ = (airDropPot_).sub(_prize); - - // let event know a tier 3 prize was won - _eventData_.compressedData += 300000000000000000000000000000000; - } - // set airdrop happened bool to true - _eventData_.compressedData += 10000000000000000000000000000000; - // let event know how much was won - _eventData_.compressedData += _prize * 1000000000000000000000000000000000; - - // reset air drop tracker - airDropTracker_ = 0; - } - } - - // store the air drop tracker number (number of buys since last airdrop) - _eventData_.compressedData = _eventData_.compressedData + (airDropTracker_ * 1000); - - // update player - plyrRnds_[_pID][_rID].keys = _keys.add(plyrRnds_[_pID][_rID].keys); - plyrRnds_[_pID][_rID].eth = _eth.add(plyrRnds_[_pID][_rID].eth); - - // update round - round_[_rID].keys = _keys.add(round_[_rID].keys); - round_[_rID].eth = _eth.add(round_[_rID].eth); - rndTmEth_[_rID][_team] = _eth.add(rndTmEth_[_rID][_team]); - - // distribute eth - _eventData_ = distributeExternal(_rID, _pID, _eth, _affID, _team, _eventData_); - _eventData_ = distributeInternal(_rID, _pID, _eth, _team, _keys, _eventData_); - - // call end tx function to fire end tx event. - endTx(_pID, _team, _eth, _keys, _eventData_); - } - } - //============================================================================== - // _ _ | _ | _ _|_ _ _ _ . - // (_(_||(_|_||(_| | (_)| _\ . - //============================================================================== - /** - * @dev calculates unmasked earnings (just calculates, does not update mask) - * @return earnings in wei format - */ - function calcUnMaskedEarnings(uint256 _pID, uint256 _rIDlast) - private - view - returns (uint256) - { - return ((((round_[_rIDlast].mask).mul(plyrRnds_[_pID][_rIDlast].keys)) / (1000000000000000000)).sub(plyrRnds_[_pID][_rIDlast].mask)); - } - - /** - * @dev returns the amount of keys you would get given an amount of eth. - * -functionhash- 0xce89c80c - * @param _rID round ID you want price for - * @param _eth amount of eth sent in - * @return keys received - */ - function calcKeysReceived(uint256 _rID, uint256 _eth) - public - view - returns (uint256) - { - // grab time - uint256 _now = now; - - // are we in a round? - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - return ((round_[_rID].eth).keysRec(_eth)); - else // rounds over. need keys for new round - return ((_eth).keys()); - } - - /** - * @dev returns current eth price for X keys. - * -functionhash- 0xcf808000 - * @param _keys number of keys desired (in 18 decimal format) - * @return amount of eth needed to send - */ - function iWantXKeys(uint256 _keys) - public - view - returns (uint256) - { - // setup local rID - uint256 _rID = rID_; - - // grab time - uint256 _now = now; - - // are we in a round? - if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) - return ((round_[_rID].keys.add(_keys)).ethRec(_keys)); - else // rounds over. need price for new round - return ((_keys).eth()); - } - //============================================================================== - // _|_ _ _ | _ . - // | (_)(_)|_\ . - //============================================================================== - /** - * @dev receives name/player info from names contract - */ - function receivePlayerInfo(uint256 _pID, address _addr, bytes32 _name, uint256 _laff) - external - { - require(msg.sender == address(playerBook), "your not playerNames contract... hmmm.."); - if (pIDxAddr_[_addr] != _pID) - pIDxAddr_[_addr] = _pID; - if (pIDxName_[_name] != _pID) - pIDxName_[_name] = _pID; - if (plyr_[_pID].addr != _addr) - plyr_[_pID].addr = _addr; - if (plyr_[_pID].name != _name) - plyr_[_pID].name = _name; - if (plyr_[_pID].laff != _laff) - plyr_[_pID].laff = _laff; - if (plyrNames_[_pID][_name] == false) - plyrNames_[_pID][_name] = true; - } - - /** - * @dev receives entire player name list - */ - function receivePlayerNameList(uint256 _pID, bytes32 _name) - external - { - require(msg.sender == address(playerBook), "your not playerNames contract... hmmm.."); - if (plyrNames_[_pID][_name] == false) - plyrNames_[_pID][_name] = true; - } - - /** - * @dev gets existing or registers new pID. use this when a player may be new - * @return pID - */ - function determinePID(F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns) - { - uint256 _pID = pIDxAddr_[msg.sender]; - // if player is new to this version of fomo3d - if (_pID == 0) - { - // grab their player ID, name and last aff ID, from player names contract - _pID = playerBook.getPlayerID(msg.sender); - bytes32 _name = playerBook.getPlayerName(_pID); - uint256 _laff = playerBook.getPlayerLAff(_pID); - - // set up player account - pIDxAddr_[msg.sender] = _pID; - plyr_[_pID].addr = msg.sender; - - if (_name != "") - { - pIDxName_[_name] = _pID; - plyr_[_pID].name = _name; - plyrNames_[_pID][_name] = true; - } - - if (_laff != 0 && _laff != _pID) - plyr_[_pID].laff = _laff; - - // set the new player bool to true - _eventData_.compressedData = _eventData_.compressedData + 1; - } - return (_eventData_); - } - - /** - * @dev checks to make sure user picked a valid team. if not sets team - * to default (sneks) - */ - function verifyTeam(uint256 _team) - private - pure - returns (uint256) - { - if (_team < 0 || _team > 3) - return (2); - else - return (_team); - } - - /** - * @dev decides if round end needs to be run & new round started. and if - * player unmasked earnings from previously played rounds need to be moved. - */ - function managePlayer(uint256 _pID, F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns) - { - // if player has played a previous round, move their unmasked earnings - // from that round to gen vault. - if (plyr_[_pID].lrnd != 0) - updateGenVault(_pID, plyr_[_pID].lrnd); - - // update player's last round played - plyr_[_pID].lrnd = rID_; - - // set the joined round bool to true - _eventData_.compressedData = _eventData_.compressedData + 10; - - return (_eventData_); - } - - /** - * @dev ends the round. manages paying out winner/splitting up pot - */ - function endRound(F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns) - { - // setup local rID - uint256 _rID = rID_; - - // grab our winning player and team id's - uint256 _winPID = round_[_rID].plyr; - uint256 _winTID = round_[_rID].team; - - // grab our pot amount - uint256 _pot = round_[_rID].pot; - - // calculate our winner share, community rewards, gen share, - // p3d share, and amount reserved for next pot - uint256 _win = (_pot.mul(48)) / 100; - uint256 _com = (_pot / 50); - uint256 _gen = (_pot.mul(potSplit_[_winTID].gen)) / 100; - uint256 _p3d = (_pot.mul(potSplit_[_winTID].p3d)) / 100; - uint256 _res = (((_pot.sub(_win)).sub(_com)).sub(_gen)).sub(_p3d); - - // calculate ppt for round mask - uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); - uint256 _dust = _gen.sub((_ppt.mul(round_[_rID].keys)) / 1000000000000000000); - if (_dust > 0) - { - _gen = _gen.sub(_dust); - _res = _res.add(_dust); - } - - // pay our winner - plyr_[_winPID].win = _win.add(plyr_[_winPID].win); - - // community rewards - if (!address(Jekyll_Island_Inc).send(_com)) - { - // This ensures Team Just cannot influence the outcome of FoMo3D with - // bank migrations by breaking outgoing transactions. - // Something we would never do. But that's not the point. - // We spent 2000$ in eth re-deploying just to patch this, we hold the - // highest belief that everything we create should be trustless. - // Team JUST, The name you shouldn't have to trust. - _p3d = _p3d.add(_com); - _com = 0; - } - - // distribute gen portion to key holders - round_[_rID].mask = _ppt.add(round_[_rID].mask); - - // send share for p3d to divies - if (_p3d > 0) - Divies.transfer(_p3d); - - // prepare event data - _eventData_.compressedData = _eventData_.compressedData + (round_[_rID].end * 1000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + (_winPID * 100000000000000000000000000) + (_winTID * 100000000000000000); - _eventData_.winnerAddr = plyr_[_winPID].addr; - _eventData_.winnerName = plyr_[_winPID].name; - _eventData_.amountWon = _win; - _eventData_.genAmount = _gen; - _eventData_.P3DAmount = _p3d; - _eventData_.newPot = _res; - - // start next round - rID_++; - _rID++; - round_[_rID].strt = now; - round_[_rID].end = now.add(rndInit_).add(rndGap_); - round_[_rID].pot = _res; - - return (_eventData_); - } - - /** - * @dev moves any unmasked earnings to gen vault. updates earnings mask - */ - function updateGenVault(uint256 _pID, uint256 _rIDlast) - private - { - uint256 _earnings = calcUnMaskedEarnings(_pID, _rIDlast); - if (_earnings > 0) - { - // put in gen vault - plyr_[_pID].gen = _earnings.add(plyr_[_pID].gen); - // zero out their earnings by updating mask - plyrRnds_[_pID][_rIDlast].mask = _earnings.add(plyrRnds_[_pID][_rIDlast].mask); - } - } - - /** - * @dev updates round timer based on number of whole keys bought. - */ - function updateTimer(uint256 _keys, uint256 _rID) - private - { - // grab time - uint256 _now = now; - - // calculate time based on number of keys bought - uint256 _newTime; - if (_now > round_[_rID].end && round_[_rID].plyr == 0) - _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(_now); - else - _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(round_[_rID].end); - - // compare to max and set new end time - if (_newTime < (rndMax_).add(_now)) - round_[_rID].end = _newTime; - else - round_[_rID].end = rndMax_.add(_now); - } - - /** - * @dev generates a random number between 0-99 and checks to see if thats - * resulted in an airdrop win - * @return do we have a winner? - */ - function airdrop() - private - view - returns (bool) - { - uint256 seed = uint256(keccak256(abi.encodePacked( - - (block.timestamp).add - (block.difficulty).add - ((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)).add - (block.gaslimit).add - ((uint256(keccak256(abi.encodePacked(msg.sender)))) / (now)).add - (block.number) - - ))); - if ((seed - ((seed / 1000) * 1000)) < airDropTracker_) - return (true); - else - return (false); - } - - /** - * @dev distributes eth based on fees to com, aff, and p3d - */ - function distributeExternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns) - { - // pay 2% out to community rewards - uint256 _com = _eth / 50; - uint256 _p3d; - if (!address(Jekyll_Island_Inc).send(_com)) - { - // This ensures Team Just cannot influence the outcome of FoMo3D with - // bank migrations by breaking outgoing transactions. - // Something we would never do. But that's not the point. - // We spent 2000$ in eth re-deploying just to patch this, we hold the - // highest belief that everything we create should be trustless. - // Team JUST, The name you shouldn't have to trust. - _p3d = _com; - _com = 0; - } - - // pay 1% out to FoMo3D short - uint256 _long = _eth / 100; - otherF3D_.transfer(_long); - - // distribute share to affiliate - uint256 _aff = _eth / 10; - - // decide what to do with affiliate share of fees - // affiliate must not be self, and must have a name registered - if (_affID != _pID && plyr_[_affID].name != '') { - plyr_[_affID].aff = _aff.add(plyr_[_affID].aff); - emit F3Devents.onAffiliatePayout(_affID, plyr_[_affID].addr, plyr_[_affID].name, _rID, _pID, _aff, now); - } else { - _p3d = _aff; - } - - // pay out p3d - _p3d = _p3d.add((_eth.mul(fees_[_team].p3d)) / (100)); - if (_p3d > 0) - { - // deposit to divies contract - Divies.transfer(_p3d); - - // set up event data - _eventData_.P3DAmount = _p3d.add(_eventData_.P3DAmount); - } - - return (_eventData_); - } - - function potSwap() - external - payable - { - // setup local rID - uint256 _rID = rID_ + 1; - - round_[_rID].pot = round_[_rID].pot.add(msg.value); - emit F3Devents.onPotSwapDeposit(_rID, msg.value); - } - - /** - * @dev distributes eth based on fees to gen and pot - */ - function distributeInternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _team, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) - private - returns (F3Ddatasets.EventReturns) - { - // calculate gen share - uint256 _gen = (_eth.mul(fees_[_team].gen)) / 100; - - // toss 1% into airdrop pot - uint256 _air = (_eth / 100); - airDropPot_ = airDropPot_.add(_air); - - // update eth balance (eth = eth - (com share + pot swap share + aff share + p3d share + airdrop pot share)) - _eth = _eth.sub(((_eth.mul(14)) / 100).add((_eth.mul(fees_[_team].p3d)) / 100)); - - // calculate pot - uint256 _pot = _eth.sub(_gen); - - // distribute gen share (thats what updateMasks() does) and adjust - // balances for dust. - uint256 _dust = updateMasks(_rID, _pID, _gen, _keys); - if (_dust > 0) - _gen = _gen.sub(_dust); - - // add eth to pot - round_[_rID].pot = _pot.add(_dust).add(round_[_rID].pot); - - // set up event data - _eventData_.genAmount = _gen.add(_eventData_.genAmount); - _eventData_.potAmount = _pot; - - return (_eventData_); - } - - /** - * @dev updates masks for round and player when keys are bought - * @return dust left over - */ - function updateMasks(uint256 _rID, uint256 _pID, uint256 _gen, uint256 _keys) - private - returns (uint256) - { - /* MASKING NOTES - earnings masks are a tricky thing for people to wrap their minds around. - the basic thing to understand here. is were going to have a global - tracker based on profit per share for each round, that increases in - relevant proportion to the increase in share supply. - - the player will have an additional mask that basically says "based - on the rounds mask, my shares, and how much i've already withdrawn, - how much is still owed to me?" - */ - - // calc profit per key & round mask based on this buy: (dust goes to pot) - uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); - round_[_rID].mask = _ppt.add(round_[_rID].mask); - - // calculate player earning from their own buy (only based on the keys - // they just bought). & update player earnings mask - uint256 _pearn = (_ppt.mul(_keys)) / (1000000000000000000); - plyrRnds_[_pID][_rID].mask = (((round_[_rID].mask.mul(_keys)) / (1000000000000000000)).sub(_pearn)).add(plyrRnds_[_pID][_rID].mask); - - // calculate & return dust - return (_gen.sub((_ppt.mul(round_[_rID].keys)) / (1000000000000000000))); - } - - /** - * @dev adds up unmasked earnings, & vault earnings, sets them all to 0 - * @return earnings in wei format - */ - function withdrawEarnings(uint256 _pID) - private - returns (uint256) - { - // update gen vault - updateGenVault(_pID, plyr_[_pID].lrnd); - - // from vaults - uint256 _earnings = (plyr_[_pID].win).add(plyr_[_pID].gen).add(plyr_[_pID].aff); - if (_earnings > 0) - { - plyr_[_pID].win = 0; - plyr_[_pID].gen = 0; - plyr_[_pID].aff = 0; - } - - return (_earnings); - } - - /** - * @dev prepares compression data and fires event for buy or reload tx's - */ - function endTx(uint256 _pID, uint256 _team, uint256 _eth, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) - private - { - _eventData_.compressedData = _eventData_.compressedData + (now * 1000000000000000000) + (_team * 100000000000000000000000000000); - _eventData_.compressedIDs = _eventData_.compressedIDs + _pID + (rID_ * 10000000000000000000000000000000000000000000000000000); - - emit F3Devents.onEndTx - ( - _eventData_.compressedData, - _eventData_.compressedIDs, - plyr_[_pID].name, - msg.sender, - _eth, - _keys, - _eventData_.winnerAddr, - _eventData_.winnerName, - _eventData_.amountWon, - _eventData_.newPot, - _eventData_.P3DAmount, - _eventData_.genAmount, - _eventData_.potAmount, - airDropPot_ - ); - } - //============================================================================== - // (~ _ _ _._|_ . - // _)(/_(_|_|| | | \/ . - //====================/========================================================= - /** upon contract deploy, it will be deactivated. this is a one time - * use function that will activate the contract. we do this so devs - * have time to set things up on the web end **/ - bool public activated_ = false; - - function activate() - public - onlyDevs - { - - // can only be ran once - require(activated_ == false, "fomo3d already activated"); - - // activate the contract - activated_ = true; - - otherF3D_ = msg.sender; - Divies = msg.sender; - Jekyll_Island_Inc = msg.sender; - - // lets start first round - rID_ = 1; - round_[1].strt = now + rndExtra_ - rndGap_; - round_[1].end = now + rndInit_ + rndExtra_; - } - - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario007.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractScenario007.sol deleted file mode 100644 index 44aae1a5e32..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario007.sol +++ /dev/null @@ -1,1433 +0,0 @@ -//pragma solidity 0.4.24; - -/** - * @title ERC165 - * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md - */ -interface ERC165 { - - /** - * @notice Query if a contract implements an interface - * @param _interfaceId The interface identifier, as specified in ERC-165 - * @dev Interface identification is specified in ERC-165. This function - * uses less than 30,000 gas. - */ - function supportsInterface(bytes4 _interfaceId) external view returns (bool); - -} - -contract ERC721Basic is ERC165 { - - event Transfer( - address indexed _from, - address indexed _to, - uint256 indexed _tokenId - ); - event Approval( - address indexed _owner, - address indexed _approved, - uint256 indexed _tokenId - ); - event ApprovalForAll( - address indexed _owner, - address indexed _operator, - bool _approved - ); - - function balanceOf(address _owner) public view returns (uint256 _balance); - function ownerOf(uint256 _tokenId) public view returns (address _owner); - function exists(uint256 _tokenId) public view returns (bool _exists); - - function approve(address _to, uint256 _tokenId) public; - function getApproved(uint256 _tokenId) - public view returns (address _operator); - - function setApprovalForAll(address _operator, bool _approved) public; - function isApprovedForAll(address _owner, address _operator) - public view returns (bool); - - function transferFrom(address _from, address _to, uint256 _tokenId) public; - function safeTransferFrom(address _from, address _to, uint256 _tokenId) - public; - - function safeTransferFrom( - address _from, - address _to, - uint256 _tokenId, - bytes memory _data - ) - public; -} - - -/** - * @title SupportsInterfaceWithLookup - * @author Matt Condon (@shrugs) - * @dev Implements ERC165 using a lookup table. - */ -contract SupportsInterfaceWithLookup is ERC165 { - bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7; - /** - * 0x01ffc9a7 === - * bytes4(keccak256('supportsInterface(bytes4)')) - */ - - /** - * @dev a mapping of interface id to whether or not it's supported - */ - mapping(bytes4 => bool) internal supportedInterfaces; - - /** - * @dev A contract implementing SupportsInterfaceWithLookup - * implement ERC165 itself - */ - constructor() public { - _registerInterface(InterfaceId_ERC165); - } - - /** - * @dev implement supportsInterface(bytes4) using a lookup table - */ - function supportsInterface(bytes4 _interfaceId) external view returns (bool) { - return supportedInterfaces[_interfaceId]; - } - - /** - * @dev private method for registering an interface - */ - function _registerInterface(bytes4 _interfaceId) internal { - require(_interfaceId != 0xffffffff); - supportedInterfaces[_interfaceId] = true; - } -} - -contract Governable { - - event Pause(); - event Unpause(); - - address public governor; - bool public paused = false; - - constructor() public { - governor = msg.sender; - } - - function setGovernor(address _gov) public onlyGovernor { - governor = _gov; - } - - modifier onlyGovernor { - require(msg.sender == governor); - _; - } - - /** - * @dev Modifier to make a function callable only when the contract is not paused. - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev Modifier to make a function callable only when the contract is paused. - */ - modifier whenPaused() { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyGovernor whenNotPaused public { - paused = true; - emit Pause(); - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyGovernor whenPaused public { - paused = false; - emit Unpause(); - } - -} - -contract CardBase is Governable { - - struct Card { - uint16 proto; - uint16 purity; - } - - function getCard(uint id) public view returns (uint16 proto, uint16 purity) { - Card memory card = cards[id]; - return (card.proto, card.purity); - } - - function getShine(uint16 purity) public pure returns (uint8) { - return uint8(purity / 1000); - } - - Card[] public cards; - -} - -contract CardProto is CardBase { - - event NewProtoCard( - uint16 id, uint8 season, uint8 god, - Rarity rarity, uint8 mana, uint8 attack, - uint8 health, uint8 cardType, uint8 tribe, bool packable - ); - - struct Limit { - uint64 limit; - bool exists; - } - - // limits for mythic cards - mapping(uint16 => Limit) public limits; - - // can only set limits once - function setLimit(uint16 id, uint64 limit) public onlyGovernor { - Limit memory l = limits[id]; - require(!l.exists); - limits[id] = Limit({ - limit: limit, - exists: true - }); - } - - function getLimit(uint16 id) public view returns (uint64 limit, bool set) { - Limit memory l = limits[id]; - return (l.limit, l.exists); - } - - // could make these arrays to save gas - // not really necessary - will be update a very limited no of times - mapping(uint8 => bool) public seasonTradable; - mapping(uint8 => bool) public seasonTradabilityLocked; - uint8 public currentSeason; - - function makeTradable(uint8 season) public onlyGovernor { - seasonTradable[season] = true; - } - - function makeUntradable(uint8 season) public onlyGovernor { - require(!seasonTradabilityLocked[season]); - seasonTradable[season] = false; - } - - function makePermanantlyTradable(uint8 season) public onlyGovernor { - require(seasonTradable[season]); - seasonTradabilityLocked[season] = true; - } - - function isTradable(uint16 proto) public view returns (bool) { - return seasonTradable[protos[proto].season]; - } - - function nextSeason() public onlyGovernor { - //Seasons shouldn't go to 0 if there is more than the uint8 should hold, the governor should know this ¯\_(ツ)_/¯ -M - require(currentSeason <= 255); - - currentSeason++; - mythic.length = 0; - legendary.length = 0; - epic.length = 0; - rare.length = 0; - common.length = 0; - } - - enum Rarity { - Common, - Rare, - Epic, - Legendary, - Mythic - } - - uint8 constant SPELL = 1; - uint8 constant MINION = 2; - uint8 constant WEAPON = 3; - uint8 constant HERO = 4; - - struct ProtoCard { - bool exists; - uint8 god; - uint8 season; - uint8 cardType; - Rarity rarity; - uint8 mana; - uint8 attack; - uint8 health; - uint8 tribe; - } - - // there is a particular design decision driving this: - // need to be able to iterate over mythics only for card generation - // don't store 5 different arrays: have to use 2 ids - // better to bear this cost (2 bytes per proto card) - // rather than 1 byte per instance - - uint16 public protoCount; - - mapping(uint16 => ProtoCard) protos; - - uint16[] public mythic; - uint16[] public legendary; - uint16[] public epic; - uint16[] public rare; - uint16[] public common; - - function addProtos( - uint16[] memory externalIDs, uint8[] memory gods, Rarity[] memory rarities, uint8[] memory manas, uint8[] memory attacks, - uint8[] memory healths, uint8[] memory cardTypes, uint8[] memory tribes, bool[] memory packable - ) public onlyGovernor returns(uint16) { - - for (uint i = 0; i < externalIDs.length; i++) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: gods[i], - season: currentSeason, - cardType: cardTypes[i], - rarity: rarities[i], - mana: manas[i], - attack: attacks[i], - health: healths[i], - tribe: tribes[i] - }); - - _addProto(externalIDs[i], card, packable[i]); - } - - } - - function addProto( - uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 cardType, uint8 tribe, bool packable - ) public onlyGovernor returns(uint16) { - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: cardType, - rarity: rarity, - mana: mana, - attack: attack, - health: health, - tribe: tribe - }); - - _addProto(externalID, card, packable); - } - - function addWeapon( - uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 durability, bool packable - ) public onlyGovernor returns(uint16) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: WEAPON, - rarity: rarity, - mana: mana, - attack: attack, - health: durability, - tribe: 0 - }); - - _addProto(externalID, card, packable); - } - - function addSpell(uint16 externalID, uint8 god, Rarity rarity, uint8 mana, bool packable) public onlyGovernor returns(uint16) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: SPELL, - rarity: rarity, - mana: mana, - attack: 0, - health: 0, - tribe: 0 - }); - - _addProto(externalID, card, packable); - } - - function addMinion( - uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 tribe, bool packable - ) public onlyGovernor returns(uint16) { - - ProtoCard memory card = ProtoCard({ - exists: true, - god: god, - season: currentSeason, - cardType: MINION, - rarity: rarity, - mana: mana, - attack: attack, - health: health, - tribe: tribe - }); - - _addProto(externalID, card, packable); - } - - function _addProto(uint16 externalID, ProtoCard memory card, bool packable) internal { - - require(!protos[externalID].exists); - - card.exists = true; - - protos[externalID] = card; - - protoCount++; - - emit NewProtoCard( - externalID, currentSeason, card.god, - card.rarity, card.mana, card.attack, - card.health, card.cardType, card.tribe, packable - ); - - if (packable) { - Rarity rarity = card.rarity; - if (rarity == Rarity.Common) { - common.push(externalID); - } else if (rarity == Rarity.Rare) { - rare.push(externalID); - } else if (rarity == Rarity.Epic) { - epic.push(externalID); - } else if (rarity == Rarity.Legendary) { - legendary.push(externalID); - } else if (rarity == Rarity.Mythic) { - mythic.push(externalID); - } else { - require(false); - } - } - } - - function getProto(uint16 id) public view returns( - bool exists, uint8 god, uint8 season, uint8 cardType, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 tribe - ) { - ProtoCard memory proto = protos[id]; - return ( - proto.exists, - proto.god, - proto.season, - proto.cardType, - proto.rarity, - proto.mana, - proto.attack, - proto.health, - proto.tribe - ); - } - - function getRandomCard(Rarity rarity, uint16 random) public view returns (uint16) { - // modulo bias is fine - creates rarity tiers etc - // will obviously revert is there are no cards of that type: this is expected - should never happen - if (rarity == Rarity.Common) { - return common[random % common.length]; - } else if (rarity == Rarity.Rare) { - return rare[random % rare.length]; - } else if (rarity == Rarity.Epic) { - return epic[random % epic.length]; - } else if (rarity == Rarity.Legendary) { - return legendary[random % legendary.length]; - } else if (rarity == Rarity.Mythic) { - // make sure a mythic is available - uint16 id; - uint64 limit; - bool set; - for (uint i = 0; i < mythic.length; i++) { - id = mythic[(random + i) % mythic.length]; - (limit, set) = getLimit(id); - if (set && limit > 0){ - return id; - } - } - // if not, they get a legendary :( - return legendary[random % legendary.length]; - } - require(false); - return 0; - } - - // can never adjust tradable cards - // each season gets a 'balancing beta' - // totally immutable: season, rarity - function replaceProto( - uint16 index, uint8 god, uint8 cardType, uint8 mana, uint8 attack, uint8 health, uint8 tribe - ) public onlyGovernor { - ProtoCard memory pc = protos[index]; - require(!seasonTradable[pc.season]); - protos[index] = ProtoCard({ - exists: true, - god: god, - season: pc.season, - cardType: cardType, - rarity: pc.rarity, - mana: mana, - attack: attack, - health: health, - tribe: tribe - }); - } - -} - -contract ERC721Receiver { - /** - * @dev Magic value to be returned upon successful reception of an NFT - * Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`, - * which can be also obtained as `ERC721Receiver(0).onERC721Received.selector` - */ - bytes4 internal constant ERC721_RECEIVED = 0x150b7a02; - - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a `safetransfer`. This function MAY throw to revert and reject the - * transfer. Return of other than the magic value MUST result in the - * transaction being reverted. - * Note: the contract address is always the message sender. - * @param _operator The address which called `safeTransferFrom` function - * @param _from The address which previously owned the token - * @param _tokenId The NFT identifier which is being transfered - * @param _data Additional data with no specified format - * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - */ - function onERC721Received( - address _operator, - address _from, - uint256 _tokenId, - bytes memory _data - ) - public - returns(bytes4); -} - -library AddressUtils { - - /** - * Returns whether the target address is a contract - * @dev This function will return false if invoked during the constructor of a contract, - * as the code is not actually created until after the constructor finishes. - * @param addr address to check - * @return whether the target address is a contract - */ - function isContract(address addr) internal view returns (bool) { - uint256 size; - // XXX Currently there is no better way to check if there is a contract in an address - // than to check the size of the code at that address. - // See https://ethereum.stackexchange.com/a/14016/36603 - // for more details about how this works. - // TODO Check this again before the Serenity release, because all addresses will be - // contracts then. - // solium-disable-next-line security/no-inline-assembly - assembly { size := extcodesize(addr) } - return size > 0; - } - -} - -library SafeMath { - - /** - * @dev Multiplies two numbers, throws on overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { - // Gas optimization: this is cheaper than asserting 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - c = a * b; - assert(c / a == b); - return c; - } - - /** - * @dev Integer division of two numbers, truncating the quotient. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // assert(b > 0); // Solidity automatically throws when dividing by 0 - // uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - return a / b; - } - - /** - * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - assert(b <= a); - return a - b; - } - - /** - * @dev Adds two numbers, throws on overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256 c) { - c = a + b; - assert(c >= a); - return c; - } -} - -contract ERC721BasicToken is CardProto, SupportsInterfaceWithLookup, ERC721Basic { - - bytes4 private constant InterfaceId_ERC721 = 0x80ac58cd; - /* - * 0x80ac58cd === - * bytes4(keccak256('balanceOf(address)')) ^ - * bytes4(keccak256('ownerOf(uint256)')) ^ - * bytes4(keccak256('approve(address,uint256)')) ^ - * bytes4(keccak256('getApproved(uint256)')) ^ - * bytes4(keccak256('setApprovalForAll(address,bool)')) ^ - * bytes4(keccak256('isApprovedForAll(address,address)')) ^ - * bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^ - * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) - */ - - bytes4 private constant InterfaceId_ERC721Exists = 0x4f558e79; - /* - * 0x4f558e79 === - * bytes4(keccak256('exists(uint256)')) - */ - - using SafeMath for uint256; - using AddressUtils for address; - - // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - // which can be also obtained as `ERC721Receiver(0).onERC721Received.selector` - bytes4 private constant ERC721_RECEIVED = 0x150b7a02; - - // Mapping from token ID to owner - mapping (uint256 => address) internal tokenOwner; - - // Mapping from token ID to approved address - mapping (uint256 => address) internal tokenApprovals; - - // Mapping from owner to number of owned token - // mapping (address => uint256) internal ownedTokensCount; - - // Mapping from owner to operator approvals - mapping (address => mapping (address => bool)) internal operatorApprovals; - - /** - * @dev Guarantees msg.sender is owner of the given token - * @param _tokenId uint256 ID of the token to validate its ownership belongs to msg.sender - */ - modifier onlyOwnerOf(uint256 _tokenId) { - require(ownerOf(_tokenId) == msg.sender); - _; - } - - /** - * @dev Checks msg.sender can transfer a token, by being owner, approved, or operator - * @param _tokenId uint256 ID of the token to validate - */ - modifier canTransfer(uint256 _tokenId) { - require(isApprovedOrOwner(msg.sender, _tokenId)); - _; - } - - constructor() - public - { - // register the supported interfaces to conform to ERC721 via ERC165 - _registerInterface(InterfaceId_ERC721); - _registerInterface(InterfaceId_ERC721Exists); - } - - /** - * @dev Gets the balance of the specified address - * @param _owner address to query the balance of - * @return uint256 representing the amount owned by the passed address - */ - function balanceOf(address _owner) public view returns (uint256); - - /** - * @dev Gets the owner of the specified token ID - * @param _tokenId uint256 ID of the token to query the owner of - * @return owner address currently marked as the owner of the given token ID - */ - function ownerOf(uint256 _tokenId) public view returns (address) { - address owner = tokenOwner[_tokenId]; - require(owner != address(0)); - return owner; - } - - /** - * @dev Returns whether the specified token exists - * @param _tokenId uint256 ID of the token to query the existence of - * @return whether the token exists - */ - function exists(uint256 _tokenId) public view returns (bool) { - address owner = tokenOwner[_tokenId]; - return owner != address(0); - } - - /** - * @dev Approves another address to transfer the given token ID - * The zero address indicates there is no approved address. - * There can only be one approved address per token at a given time. - * Can only be called by the token owner or an approved operator. - * @param _to address to be approved for the given token ID - * @param _tokenId uint256 ID of the token to be approved - */ - function approve(address _to, uint256 _tokenId) public { - address owner = ownerOf(_tokenId); - require(_to != owner); - require(msg.sender == owner || isApprovedForAll(owner, msg.sender)); - - tokenApprovals[_tokenId] = _to; - emit Approval(owner, _to, _tokenId); - } - - /** - * @dev Gets the approved address for a token ID, or zero if no address set - * @param _tokenId uint256 ID of the token to query the approval of - * @return address currently approved for the given token ID - */ - function getApproved(uint256 _tokenId) public view returns (address) { - return tokenApprovals[_tokenId]; - } - - /** - * @dev Sets or unsets the approval of a given operator - * An operator is allowed to transfer all tokens of the sender on their behalf - * @param _to operator address to set the approval - * @param _approved representing the status of the approval to be set - */ - function setApprovalForAll(address _to, bool _approved) public { - require(_to != msg.sender); - operatorApprovals[msg.sender][_to] = _approved; - emit ApprovalForAll(msg.sender, _to, _approved); - } - - /** - * @dev Tells whether an operator is approved by a given owner - * @param _owner owner address which you want to query the approval of - * @param _operator operator address which you want to query the approval of - * @return bool whether the given operator is approved by the given owner - */ - function isApprovedForAll( - address _owner, - address _operator - ) - public - view - returns (bool) - { - return operatorApprovals[_owner][_operator]; - } - - /** - * @dev Transfers the ownership of a given token ID to another address - * Usage of this method is discouraged, use `safeTransferFrom` whenever possible - * Requires the msg sender to be the owner, approved, or operator - * @param _from current owner of the token - * @param _to address to receive the ownership of the given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - public - canTransfer(_tokenId) - { - require(_from != address(0)); - require(_to != address(0)); - - clearApproval(_from, _tokenId); - removeTokenFrom(_from, _tokenId); - addTokenTo(_to, _tokenId); - - emit Transfer(_from, _to, _tokenId); - } - - /** - * @dev Safely transfers the ownership of a given token ID to another address - * If the target address is a contract, it must implement `onERC721Received`, - * which is called upon a safe transfer, and return the magic value - * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, - * the transfer is reverted. - * - * Requires the msg sender to be the owner, approved, or operator - * @param _from current owner of the token - * @param _to address to receive the ownership of the given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function safeTransferFrom( - address _from, - address _to, - uint256 _tokenId - ) - public - canTransfer(_tokenId) - { - // solium-disable-next-line arg-overflow - safeTransferFrom(_from, _to, _tokenId, ""); - } - - /** - * @dev Safely transfers the ownership of a given token ID to another address - * If the target address is a contract, it must implement `onERC721Received`, - * which is called upon a safe transfer, and return the magic value - * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, - * the transfer is reverted. - * Requires the msg sender to be the owner, approved, or operator - * @param _from current owner of the token - * @param _to address to receive the ownership of the given token ID - * @param _tokenId uint256 ID of the token to be transferred - * @param _data bytes data to send along with a safe transfer check - */ - function safeTransferFrom( - address _from, - address _to, - uint256 _tokenId, - bytes memory _data - ) - public - canTransfer(_tokenId) - { - transferFrom(_from, _to, _tokenId); - // solium-disable-next-line arg-overflow - require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data)); - } - - /** - * @dev Returns whether the given spender can transfer a given token ID - * @param _spender address of the spender to query - * @param _tokenId uint256 ID of the token to be transferred - * @return bool whether the msg.sender is approved for the given token ID, - * is an operator of the owner, or is the owner of the token - */ - function isApprovedOrOwner( - address _spender, - uint256 _tokenId - ) - internal - view - returns (bool) - { - address owner = ownerOf(_tokenId); - // Disable solium check because of - // https://github.com/duaraghav8/Solium/issues/175 - // solium-disable-next-line operator-whitespace - return ( - _spender == owner || - getApproved(_tokenId) == _spender || - isApprovedForAll(owner, _spender) - ); - } - - /** - * @dev Internal function to clear current approval of a given token ID - * Reverts if the given address is not indeed the owner of the token - * @param _owner owner of the token - * @param _tokenId uint256 ID of the token to be transferred - */ - function clearApproval(address _owner, uint256 _tokenId) internal { - require(ownerOf(_tokenId) == _owner); - if (tokenApprovals[_tokenId] != address(0)) { - tokenApprovals[_tokenId] = address(0); - } - } - - /** - * @dev Internal function to mint a new token - * Reverts if the given token ID already exists - * @param _to The address that will own the minted token - * @param _tokenId uint256 ID of the token to be minted by the msg.sender - */ - function _mint(address _to, uint256 _tokenId) internal { - require(_to != address(0)); - addNewTokenTo(_to, _tokenId); - emit Transfer(address(0), _to, _tokenId); - } - - - /** - * @dev Internal function to burn a specific token - * Reverts if the token does not exist - * @param _tokenId uint256 ID of the token being burned by the msg.sender - */ - function _burn(address _owner, uint256 _tokenId) internal { - clearApproval(_owner, _tokenId); - removeTokenFrom(_owner, _tokenId); - emit Transfer(_owner, address(0), _tokenId); - } - - function addNewTokenTo(address _to, uint256 _tokenId) internal { - require(tokenOwner[_tokenId] == address(0)); - tokenOwner[_tokenId] = _to; - } - - /** - * @dev Internal function to add a token ID to the list of a given address - * @param _to address representing the new owner of the given token ID - * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address - */ - function addTokenTo(address _to, uint256 _tokenId) internal { - require(tokenOwner[_tokenId] == address(0)); - tokenOwner[_tokenId] = _to; - // ownedTokensCount[_to] = ownedTokensCount[_to].add(1); - } - - /** - * @dev Internal function to remove a token ID from the list of a given address - * @param _from address representing the previous owner of the given token ID - * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address - */ - function removeTokenFrom(address _from, uint256 _tokenId) internal { - require(ownerOf(_tokenId) == _from); - // ownedTokensCount[_from] = ownedTokensCount[_from].sub(1); - tokenOwner[_tokenId] = address(0); - } - - /** - * @dev Internal function to invoke `onERC721Received` on a target address - * The call is not executed if the target address is not a contract - * @param _from address representing the previous owner of the given token ID - * @param _to target address that will receive the tokens - * @param _tokenId uint256 ID of the token to be transferred - * @param _data bytes optional data to send along with the call - * @return whether the call correctly returned the expected magic value - */ - function checkAndCallSafeTransfer( - address _from, - address _to, - uint256 _tokenId, - bytes memory _data - ) - internal - returns (bool) - { - if (!_to.isContract()) { - return true; - } - bytes4 retval = ERC721Receiver(_to).onERC721Received( - msg.sender, _from, _tokenId, _data); - return (retval == ERC721_RECEIVED); - } - -} - - - -contract ERC721Enumerable is ERC721Basic { - function totalSupply() public view returns (uint256); - function tokenOfOwnerByIndex( - address _owner, - uint256 _index - ) - public - view - returns (uint256 _tokenId); - - function tokenByIndex(uint256 _index) public view returns (uint256); -} - -contract ERC721Metadata is ERC721Basic { - function name() external view returns (string memory _name); - function symbol() external view returns (string memory _symbol); - function tokenURI(uint256 _tokenId) public view returns (string memory); -} - -contract ERC721 is ERC721Basic, ERC721Enumerable, ERC721Metadata { - -} - - - - -library Strings { - - // via https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol - function strConcat(string memory _a, string memory _b, string memory _c, string memory _d, string memory _e) internal pure returns (string memory ) { - bytes memory _ba = bytes(_a); - bytes memory _bb = bytes(_b); - bytes memory _bc = bytes(_c); - bytes memory _bd = bytes(_d); - bytes memory _be = bytes(_e); - string memory abcde = new string(_ba.length + _bb.length + _bc.length + _bd.length + _be.length); - bytes memory babcde = bytes(abcde); - uint k = 0; - for (uint i = 0; i < _ba.length; i++) babcde[k++] = _ba[i]; - for ( i = 0; i < _bb.length; i++) babcde[k++] = _bb[i]; - for ( i = 0; i < _bc.length; i++) babcde[k++] = _bc[i]; - for ( i = 0; i < _bd.length; i++) babcde[k++] = _bd[i]; - for ( i = 0; i < _be.length; i++) babcde[k++] = _be[i]; - return string(babcde); - } - - function strConcat(string memory _a, string memory _b, string memory _c, string memory _d) internal pure returns (string memory ) { - return strConcat(_a, _b, _c, _d, ""); - } - - function strConcat(string memory _a, string memory _b, string memory _c) internal pure returns (string memory ) { - return strConcat(_a, _b, _c, "", ""); - } - - function strConcat(string memory _a, string memory _b) internal pure returns (string memory ) { - return strConcat(_a, _b, "", "", ""); - } - - function uint2str(uint i) internal pure returns (string memory ) { - if (i == 0) return "0"; - uint j = i; - uint len; - while (j != 0){ - len++; - j /= 10; - } - bytes memory bstr = new bytes(len); - uint k = len - 1; - while (i != 0){ - bstr[k--] = byte(uint8(48 + i % 10)); - i /= 10; - } - return string(bstr); - } -} - -contract ERC721Token is SupportsInterfaceWithLookup, ERC721BasicToken, ERC721 { - - using Strings for string; - - bytes4 private constant InterfaceId_ERC721Enumerable = 0x780e9d63; - /** - * 0x780e9d63 === - * bytes4(keccak256('totalSupply()')) ^ - * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ - * bytes4(keccak256('tokenByIndex(uint256)')) - */ - - bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f; - /** - * 0x5b5e139f === - * bytes4(keccak256('name()')) ^ - * bytes4(keccak256('symbol()')) ^ - * bytes4(keccak256('tokenURI(uint256)')) - */ - - /*** Constants ***/ - // Configure these for your own deployment - string public constant NAME = "Gods Unchained"; - string public constant SYMBOL = "GODS"; - string public tokenMetadataBaseURI = "https://api.godsunchained.com/card/"; - - // Mapping from owner to list of owned token IDs - // EDITED: limit to 2^40 (around 1T) - mapping(address => uint40[]) internal ownedTokens; - - uint32[] ownedTokensIndex; - - /** - * @dev Constructor function - */ - constructor() public { - - // register the supported interfaces to conform to ERC721 via ERC165 - _registerInterface(InterfaceId_ERC721Enumerable); - _registerInterface(InterfaceId_ERC721Metadata); - } - - /** - * @dev Gets the token name - * @return string representing the token name - */ - function name() external view returns (string memory) { - return NAME; - } - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory) { - return SYMBOL; - } - - /** - * @dev Returns an URI for a given token ID - * Throws if the token ID does not exist. May return an empty string. - * @param _tokenId uint256 ID of the token to query - */ - function tokenURI(uint256 _tokenId) public view returns (string memory) { - return Strings.strConcat( - tokenMetadataBaseURI, - Strings.uint2str(_tokenId) - ); - } - - /** - * @dev Gets the token ID at a given index of the tokens list of the requested owner - * @param _owner address owning the tokens list to be accessed - * @param _index uint256 representing the index to be accessed of the requested tokens list - * @return uint256 token ID at the given index of the tokens list owned by the requested address - */ - function tokenOfOwnerByIndex( - address _owner, - uint256 _index - ) - public - view - returns (uint256) - { - require(_index < balanceOf(_owner)); - return ownedTokens[_owner][_index]; - } - - /** - * @dev Gets the total amount of tokens stored by the contract - * @return uint256 representing the total amount of tokens - */ - function totalSupply() public view returns (uint256) { - return cards.length; - } - - /** - * @dev Gets the token ID at a given index of all the tokens in this contract - * Reverts if the index is greater or equal to the total number of tokens - * @param _index uint256 representing the index to be accessed of the tokens list - * @return uint256 token ID at the given index of the tokens list - */ - function tokenByIndex(uint256 _index) public view returns (uint256) { - require(_index < totalSupply()); - return _index; - } - - /** - * @dev Internal function to add a token ID to the list of a given address - * @param _to address representing the new owner of the given token ID - * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address - */ - function addTokenTo(address _to, uint256 _tokenId) internal { - super.addTokenTo(_to, _tokenId); - uint256 length = ownedTokens[_to].length; - // EDITED: prevent overflow - require(length == uint32(length)); - ownedTokens[_to].push(uint40(_tokenId)); - - ownedTokensIndex[_tokenId] = uint32(length); - } - - // EDITED - // have to have in order to use array rather than mapping - function addNewTokenTo(address _to, uint256 _tokenId) internal { - super.addNewTokenTo(_to, _tokenId); - uint256 length = ownedTokens[_to].length; - // EDITED: prevent overflow - require(length == uint32(length)); - ownedTokens[_to].push(uint40(_tokenId)); - ownedTokensIndex.push(uint32(length)); - } - - /** - * @dev Internal function to remove a token ID from the list of a given address - * @param _from address representing the previous owner of the given token ID - * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address - */ - function removeTokenFrom(address _from, uint256 _tokenId) internal { - super.removeTokenFrom(_from, _tokenId); - - uint32 tokenIndex = ownedTokensIndex[_tokenId]; - uint256 lastTokenIndex = ownedTokens[_from].length.sub(1); - uint40 lastToken = ownedTokens[_from][lastTokenIndex]; - - ownedTokens[_from][tokenIndex] = lastToken; - ownedTokens[_from][lastTokenIndex] = 0; - // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to - // be zero. Then we can make sure that we will remove _tokenId from the ownedTokens list since we are first swapping - // the lastToken to the first position, and then dropping the element placed in the last position of the list - - ownedTokens[_from].length--; - ownedTokensIndex[_tokenId] = 0; - ownedTokensIndex[lastToken] = tokenIndex; - } - - /** - * @dev Gets the balance of the specified address - overrriden from previous to save gas - * @param _owner address to query the balance of - * @return uint256 representing the amount owned by the passed address - */ - function balanceOf(address _owner) public view returns (uint256) { - return ownedTokens[_owner].length; - } - -} - -contract CardOwnershipTwo is ERC721Token { - - uint public burnCount; - - function getActiveCards() public view returns (uint) { - return totalSupply() - burnCount; - } - - /** - * @param to : the address to which the card will be transferred - * @param id : the id of the card to be transferred - */ - function transfer(address to, uint id) public payable onlyOwnerOf(id) { - require(isTradable(cards[id].proto)); - require(to != address(0)); - - _transfer(msg.sender, to, id); - } - - function _transfer(address from, address to, uint id) internal { - - clearApproval(from, id); - - removeTokenFrom(from, id); - - addTokenTo(to, id); - - emit Transfer(from, to, id); - } - - /** - * @param to : the address to which the cards will be transferred - * @param ids : the ids of the cards to be transferred - */ - function transferAll(address to, uint[] memory ids) public payable { - for (uint i = 0; i < ids.length; i++) { - transfer(to, ids[i]); - } - } - - /** - * @param proposed : the claimed owner of the cards - * @param ids : the ids of the cards to check - * @return whether proposed owns all of the cards - */ - function ownsAll(address proposed, uint[] memory ids) public view returns (bool) { - require(ids.length > 0); - for (uint i = 0; i < ids.length; i++) { - if (!owns(proposed, ids[i])) { - return false; - } - } - return true; - } - - /** - * @param proposed : the claimed owner of the card - * @param id : the id of the card to check - * @return whether proposed owns the card - */ - function owns(address proposed, uint id) public view returns (bool) { - return ownerOf(id) == proposed; - } - - function burn(uint id) public onlyOwnerOf(id) { - burnCount++; - _burn(msg.sender, id); - } - - /** - * @param ids : the indices of the tokens to burn - */ - function burnAll(uint[] memory ids) public { - for (uint i = 0; i < ids.length; i++){ - burn(ids[i]); - } - } - - /** - * @param to : the address to approve for transfer - * @param id : the index of the card to be approved - */ - function approve(address to, uint id) public { - require(isTradable(cards[id].proto)); - super.approve(to, id); - } - - /** - * @param to : the address to approve for transfer - * @param ids : the indices of the cards to be approved - */ - function approveAll(address to, uint[] memory ids) public { - for (uint i = 0; i < ids.length; i++) { - approve(to, ids[i]); - } - } - - /** - * @param to : the address to which the token should be transferred - * @param id : the index of the token to transfer - */ - function transferFrom(address from, address to, uint id) public { - require(isTradable(cards[id].proto)); - super.transferFrom(from, to, id); - } - - /** - * @param to : the address to which the tokens should be transferred - * @param ids : the indices of the tokens to transfer - */ - function transferAllFrom(address from, address to, uint[] memory ids) public { - for (uint i = 0; i < ids.length; i++) { - transferFrom(from, to, ids[i]); - } - } - - /** - * @return the number of cards which have been burned - */ - function getBurnCount() public view returns (uint) { - return burnCount; - } - -} - -contract CardIntegrationTwo is CardOwnershipTwo { - - address[] public packs; - - event CardCreated(uint indexed id, uint16 proto, uint16 purity, address owner); - - function addPack(address approved) public onlyGovernor { - packs.push(approved); - } - - modifier onlyApprovedPacks { - require(_isApprovedPack()); - _; - } - - function _isApprovedPack() private view returns (bool) { - for (uint i = 0; i < packs.length; i++) { - if (msg.sender == address(packs[i])) { - return true; - } - } - return false; - } - - function createCard(address owner, uint16 proto, uint16 purity) public whenNotPaused onlyApprovedPacks returns (uint) { - ProtoCard memory card = protos[proto]; - require(card.season == currentSeason); - if (card.rarity == Rarity.Mythic) { - uint64 limit; - bool exists; - (limit, exists) = getLimit(proto); - require(!exists || limit > 0); - limits[proto].limit--; - } - return _createCard(owner, proto, purity); - } - - function _createCard(address owner, uint16 proto, uint16 purity) internal returns (uint) { - Card memory card = Card({ - proto: proto, - purity: purity - }); - - uint id = cards.push(card) - 1; - - _mint(owner, id); - - emit CardCreated(id, proto, purity, owner); - - return id; - } - - /*function combineCards(uint[] ids) public whenNotPaused { - require(ids.length == 5); - require(ownsAll(msg.sender, ids)); - Card memory first = cards[ids[0]]; - uint16 proto = first.proto; - uint8 shine = _getShine(first.purity); - require(shine < shineLimit); - uint16 puritySum = first.purity - (shine * 1000); - burn(ids[0]); - for (uint i = 1; i < ids.length; i++) { - Card memory next = cards[ids[i]]; - require(next.proto == proto); - require(_getShine(next.purity) == shine); - puritySum += (next.purity - (shine * 1000)); - burn(ids[i]); - } - uint16 newPurity = uint16(((shine + 1) * 1000) + (puritySum / ids.length)); - _createCard(msg.sender, proto, newPurity); - }*/ - - - // PURITY NOTES - // currently, we only - // however, to protect rarity, you'll never be abl - // this is enforced by the restriction in the create-card function - // no cards above this point can be found in packs - - - -} - -contract PreviousInterface { - - function ownerOf(uint id) public view returns (address); - - function getCard(uint id) public view returns (uint16, uint16); - - function totalSupply() public view returns (uint); - - function burnCount() public view returns (uint); - -} - -contract CardMigration is CardIntegrationTwo { - - constructor(PreviousInterface previous) public { - old = previous; - } - - // use interface to lower deployment cost - PreviousInterface old; - - mapping(uint => bool) public migrated; - - function migrate(uint id) public { - - require(!migrated[id]); - - migrated[id] = true; - - address owner = old.ownerOf(id); - - uint16 proto; - uint16 purity; - - (proto, purity) = old.getCard(id); - - _createCard(owner, proto, purity); - } - - function migrateAll(uint[] memory ids) public { - - for (uint i = 0; i < ids.length; i++){ - migrate(ids[i]); - } - - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario008.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractScenario008.sol deleted file mode 100644 index 7336976e2b6..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario008.sol +++ /dev/null @@ -1,2016 +0,0 @@ -//pragma solidity ^0.4.11; - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - function Ownable() { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -contract ERC721 { - // Required methods - function totalSupply() public view returns (uint256 total); - function balanceOf(address _owner) public view returns (uint256 balance); - function ownerOf(uint256 _tokenId) external view returns (address owner); - function approve(address _to, uint256 _tokenId) external; - function transfer(address _to, uint256 _tokenId) external; - function transferFrom(address _from, address _to, uint256 _tokenId) external; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) external view returns (bool); -} - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - - function isGeneScience() public pure returns (bool){ - return true; - } - - /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor - /// @param genes1 genes of mom - /// @param genes2 genes of sire - /// @return the genes that are supposed to be passed down the child - function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - - return (genes1+genes2+targetBlock)/2; - - -} -} - - - - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() public onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - Transfer(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(now), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - uint256 newKittenId = kitties.push(_kitty) - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(0, _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { - /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. - function getMetadata(uint256 _tokenId, string) public view returns (bytes32[4] buffer, uint256 count) { - if (_tokenId == 1) { - buffer[0] = "Hello World! :D"; - count = 15; - } else if (_tokenId == 2) { - buffer[0] = "I would definitely choose a medi"; - buffer[1] = "um length string."; - count = 49; - } else if (_tokenId == 3) { - buffer[0] = "Lorem ipsum dolor sit amet, mi e"; - buffer[1] = "st accumsan dapibus augue lorem,"; - buffer[2] = " tristique vestibulum id, libero"; - buffer[3] = " suscipit varius sapien aliquam."; - count = 128; - } - } -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is KittyBase, ERC721 { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public view returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() public view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - external - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] _rawBytes, uint256 _stringLength) private view returns (string) { - var outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string _preferredTransport) external view returns (string infoUrl) { - require(erc721Metadata != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2 sun; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - msg.sender.send(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - - // Represents an auction on an NFT - struct Auction { - // Current owner of NFT - address seller; - // Price (in wei) at beginning of auction - uint128 startingPrice; - // Price (in wei) at end of auction - uint128 endingPrice; - // Duration (in seconds) of auction - uint64 duration; - // Time when auction started - // NOTE: 0 if this auction has been concluded - uint64 startedAt; - } - - // Reference to contract tracking NFT ownership - ERC721 public nonFungibleContract; - - // Cut owner takes on each auction, measured in basis points (1/100 of a percent). - // Values 0-10,000 map to 0%-100% - uint256 public ownerCut; - - // Map from token ID to their corresponding auction. - mapping (uint256 => Auction) tokenIdToAuction; - - event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); - event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); - event AuctionCancelled(uint256 tokenId); - - /// @dev Returns true if the claimant owns the token. - /// @param _claimant - Address claiming to own the token. - /// @param _tokenId - ID of token whose ownership to verify. - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return (nonFungibleContract.ownerOf(_tokenId) == _claimant); - } - - /// @dev Escrows the NFT, assigning ownership to this contract. - /// Throws if the escrow fails. - /// @param _owner - Current owner address of token to escrow. - /// @param _tokenId - ID of token whose approval to verify. - function _escrow(address _owner, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transferFrom(_owner, this, _tokenId); - } - - /// @dev Transfers an NFT owned by this contract to another address. - /// Returns true if the transfer succeeds. - /// @param _receiver - Address to transfer NFT to. - /// @param _tokenId - ID of token to transfer. - function _transfer(address _receiver, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transfer(_receiver, _tokenId); - } - - /// @dev Adds an auction to the list of open auctions. Also fires the - /// AuctionCreated event. - /// @param _tokenId The ID of the token to be put on auction. - /// @param _auction Auction to add. - function _addAuction(uint256 _tokenId, Auction _auction) internal { - // Require that all auctions have a duration of - // at least one minute. (Keeps our math from getting hairy!) - require(_auction.duration >= 1 minutes); - - tokenIdToAuction[_tokenId] = _auction; - - AuctionCreated( - uint256(_tokenId), - uint256(_auction.startingPrice), - uint256(_auction.endingPrice), - uint256(_auction.duration) - ); - } - - /// @dev Cancels an auction unconditionally. - function _cancelAuction(uint256 _tokenId, address _seller) internal { - _removeAuction(_tokenId); - _transfer(_seller, _tokenId); - AuctionCancelled(_tokenId); - } - - /// @dev Computes the price and transfers winnings. - /// Does NOT transfer ownership of token. - function _bid(uint256 _tokenId, uint256 _bidAmount) - internal - returns (uint256) - { - // Get a reference to the auction struct - Auction storage auction = tokenIdToAuction[_tokenId]; - - // Explicitly check that this auction is currently live. - // (Because of how Ethereum mappings work, we can't just count - // on the lookup above failing. An invalid _tokenId will just - // return an auction object that is all zeros.) - require(_isOnAuction(auction)); - - // Check that the bid is greater than or equal to the current price - uint256 price = _currentPrice(auction); - require(_bidAmount >= price); - - // Grab a reference to the seller before the auction struct - // gets deleted. - address seller = auction.seller; - - // The bid is good! Remove the auction before sending the fees - // to the sender so we can't have a reentrancy attack. - _removeAuction(_tokenId); - - // Transfer proceeds to seller (if there are any!) - if (price > 0) { - // Calculate the auctioneer's cut. - // (NOTE: _computeCut() is guaranteed to return a - // value <= price, so this subtraction can't go negative.) - uint256 auctioneerCut = _computeCut(price); - uint256 sellerProceeds = price - auctioneerCut; - - // NOTE: Doing a transfer() in the middle of a complex - // method like this is generally discouraged because of - // reentrancy attacks and DoS attacks if the seller is - // a contract with an invalid fallback function. We explicitly - // guard against reentrancy attacks by removing the auction - // before calling transfer(), and the only thing the seller - // can DoS is the sale of their own asset! (And if it's an - // accident, they can call cancelAuction(). ) - seller.transfer(sellerProceeds); - } - - // Calculate any excess funds included with the bid. If the excess - // is anything worth worrying about, transfer it back to bidder. - // NOTE: We checked above that the bid amount is greater than or - // equal to the price so this cannot underflow. - uint256 bidExcess = _bidAmount - price; - - // Return the funds. Similar to the previous transfer, this is - // not susceptible to a re-entry attack because the auction is - // removed before any transfers occur. - msg.sender.transfer(bidExcess); - - // Tell the world! - AuctionSuccessful(_tokenId, price, msg.sender); - - return price; - } - - /// @dev Removes an auction from the list of open auctions. - /// @param _tokenId - ID of NFT on auction. - function _removeAuction(uint256 _tokenId) internal { - delete tokenIdToAuction[_tokenId]; - } - - /// @dev Returns true if the NFT is on auction. - /// @param _auction - Auction to check. - function _isOnAuction(Auction storage _auction) internal view returns (bool) { - return (_auction.startedAt > 0); - } - - /// @dev Returns current price of an NFT on auction. Broken into two - /// functions (this one, that computes the duration from the auction - /// structure, and the other that does the price computation) so we - /// can easily test that the price computation works correctly. - function _currentPrice(Auction storage _auction) - internal - view - returns (uint256) - { - uint256 secondsPassed = 0; - - // A bit of insurance against negative values (or wraparound). - // Probably not necessary (since Ethereum guarnatees that the - // now variable doesn't ever go backwards). - if (now > _auction.startedAt) { - secondsPassed = now - _auction.startedAt; - } - - return _computeCurrentPrice( - _auction.startingPrice, - _auction.endingPrice, - _auction.duration, - secondsPassed - ); - } - - /// @dev Computes the current price of an auction. Factored out - /// from _currentPrice so we can run extensive unit tests. - /// When testing, make this function public and turn on - /// `Current price computation` test suite. - function _computeCurrentPrice( - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - uint256 _secondsPassed - ) - internal - pure - returns (uint256) - { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our public functions carefully cap the maximum values for - // time (at 64-bits) and currency (at 128-bits). _duration is - // also known to be non-zero (see the require() statement in - // _addAuction()) - if (_secondsPassed >= _duration) { - // We've reached the end of the dynamic pricing portion - // of the auction, just return the end price. - return _endingPrice; - } else { - // Starting price can be higher than ending price (and often is!), so - // this delta can be negative. - int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - - // This multiplication can't overflow, _secondsPassed will easily fit within - // 64-bits, and totalPriceChange will easily fit within 128-bits, their product - // will always fit within 256-bits. - int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - - // currentPriceChange can be negative, but if so, will have a magnitude - // less that _startingPrice. Thus, this result will always end up positive. - int256 currentPrice = int256(_startingPrice) + currentPriceChange; - - return uint256(currentPrice); - } - } - - /// @dev Computes owner's cut of a sale. - /// @param _price - Sale price of NFT. - function _computeCut(uint256 _price) internal view returns (uint256) { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our entry functions carefully cap the maximum values for - // currency (at 128-bits), and ownerCut <= 10000 (see the require() - // statement in the ClockAuction constructor). The result of this - // function is always guaranteed to be <= _price. - return _price * ownerCut / 10000; - } - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { - event Pause(); - event Unpause(); - - bool public paused = false; - - - /** - * @dev modifier to allow actions only when the contract IS paused - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev modifier to allow actions only when the contract IS NOT paused - */ - modifier whenPaused { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyOwner whenNotPaused returns (bool) { - paused = true; - Pause(); - return true; - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyOwner whenPaused returns (bool) { - paused = false; - Unpause(); - return true; - } -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - - /// @dev The ERC-165 interface signature for ERC-721. - /// Ref: https://github.com/ethereum/EIPs/issues/165 - /// Ref: https://github.com/ethereum/EIPs/issues/721 - bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - - /// @dev Constructor creates a reference to the NFT ownership contract - /// and verifies the owner cut is in the valid range. - /// @param _nftAddress - address of a deployed contract implementing - /// the Nonfungible Interface. - /// @param _cut - percent cut the owner takes on each auction, must be - /// between 0-10,000. - function ClockAuction(address _nftAddress, uint256 _cut) public { - require(_cut <= 10000); - ownerCut = _cut; - - ERC721 candidateContract = ERC721(_nftAddress); - require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); - nonFungibleContract = candidateContract; - } - - /// @dev Remove all Ether from the contract, which is the owner's cuts - /// as well as any Ether sent directly to the contract address. - /// Always transfers to the NFT contract, but can be called either by - /// the owner or the NFT contract. - function withdrawBalance() external { - address nftAddress = address(nonFungibleContract); - - require( - msg.sender == owner || - msg.sender == nftAddress - ); - // We are using this boolean method to make sure that even if one fails it will still work - bool res = nftAddress.send(this.balance); - } - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of time to move between starting - /// price and ending price (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address _seller - ) - external - whenNotPaused - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(_owns(msg.sender, _tokenId)); - _escrow(msg.sender, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Bids on an open auction, completing the auction and transferring - /// ownership of the NFT if enough Ether is supplied. - /// @param _tokenId - ID of token to bid on. - function bid(uint256 _tokenId) - external - payable - whenNotPaused - { - // _bid will throw if the bid or funds transfer fails - _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - } - - /// @dev Cancels an auction that hasn't been won yet. - /// Returns the NFT to original owner. - /// @notice This is a state-modifying function that can - /// be called while the contract is paused. - /// @param _tokenId - ID of token on auction - function cancelAuction(uint256 _tokenId) - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - address seller = auction.seller; - require(msg.sender == seller); - _cancelAuction(_tokenId, seller); - } - - /// @dev Cancels an auction when the contract is paused. - /// Only the owner may do this, and NFTs are returned to - /// the seller. This should only be used in emergencies. - /// @param _tokenId - ID of the NFT on auction to cancel. - function cancelAuctionWhenPaused(uint256 _tokenId) - whenPaused - onlyOwner - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - _cancelAuction(_tokenId, auction.seller); - } - - /// @dev Returns auction info for an NFT on auction. - /// @param _tokenId - ID of NFT on auction. - function getAuction(uint256 _tokenId) - external - view - returns - ( - address seller, - uint256 startingPrice, - uint256 endingPrice, - uint256 duration, - uint256 startedAt - ) { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return ( - auction.seller, - auction.startingPrice, - auction.endingPrice, - auction.duration, - auction.startedAt - ); - } - - /// @dev Returns the current price of an auction. - /// @param _tokenId - ID of the token price we are checking. - function getCurrentPrice(uint256 _tokenId) - external - view - returns (uint256) - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return _currentPrice(auction); - } - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSiringAuctionAddress() call. - bool public isSiringClockAuction = true; - - // Delegate constructor - function SiringClockAuction(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. Since this function is wrapped, - /// require sender to be KittyCore contract. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Places a bid for siring. Requires the sender - /// is the KittyCore contract because all bid methods - /// should be wrapped. Also returns the kitty to the - /// seller rather than the winner. - function bid(uint256 _tokenId) - external - payable - { - require(msg.sender == address(nonFungibleContract)); - address seller = tokenIdToAuction[_tokenId].seller; - // _bid checks that token ID is valid and will throw if bid fails - _bid(_tokenId, msg.value); - // We transfer the kitty back to the seller, the winner will get - // the offspring - _transfer(seller, _tokenId); - } - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSaleAuctionAddress() call. - bool public isSaleClockAuction = true; - - // Tracks last 5 sale price of gen0 kitty sales - uint256 public gen0SaleCount; - uint256[5] public lastGen0SalePrices; - - // Delegate constructor - function SaleClockAuction(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Updates lastSalePrice if seller is the nft contract - /// Otherwise, works the same as default bid method. - function bid(uint256 _tokenId) - external - payable - { - // _bid verifies token ID size - address seller = tokenIdToAuction[_tokenId].seller; - uint256 price = _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - - // If not a gen0 auction, exit - if (seller == address(nonFungibleContract)) { - // Track gen0 sale prices - lastGen0SalePrices[gen0SaleCount % 5] = price; - gen0SaleCount++; - } - } - - function averageGen0SalePrice() external view returns (uint256) { - uint256 sum = 0; - for (uint256 i = 0; i < 5; i++) { - sum += lastGen0SalePrices[i]; - } - return sum / 5; - } - -} - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, saleAuction); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, siringAuction); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10 sun; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, saleAuction); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - address(this) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - function KittyCore() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(-1), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - ContractUpgrade(_v2Address); - } - - /// @notice No tipping! - /// @dev Reject all Ether from being sent here, unless it's from one of the - /// two auction contracts. (Hopefully, we can prevent user accidents.) - function() external payable { - require( - msg.sender == address(saleAuction) || - msg.sender == address(siringAuction) - ); - } - - /// @notice Returns all the relevant information about a specific kitty. - /// @param _id The ID of the kitty of interest. - function getKitty(uint256 _id) - external - view - returns ( - bool isGestating, - bool isReady, - uint256 cooldownIndex, - uint256 nextActionAt, - uint256 siringWithId, - uint256 birthTime, - uint256 matronId, - uint256 sireId, - uint256 generation, - uint256 genes - ) { - Kitty storage kit = kitties[_id]; - - // if this variable is 0 then it's not gestating - isGestating = (kit.siringWithId != 0); - isReady = (kit.cooldownEndBlock <= block.number); - cooldownIndex = uint256(kit.cooldownIndex); - nextActionAt = uint256(kit.cooldownEndBlock); - siringWithId = uint256(kit.siringWithId); - birthTime = uint256(kit.birthTime); - matronId = uint256(kit.matronId); - sireId = uint256(kit.sireId); - generation = uint256(kit.generation); - genes = kit.genes; - } - - /// @dev Override unpause so it requires all external contract addresses - /// to be set before contract can be unpaused. Also, we can't have - /// newContractAddress set either, because then the contract was upgraded. - /// @notice This is public rather than external so we can call super.unpause - /// without using an expensive CALL. - function unpause() public onlyCEO whenPaused { - require(saleAuction != address(0)); - require(siringAuction != address(0)); - require(geneScience != address(0)); - require(newContractAddress == address(0)); - - // Actually unpause the contract. - super.unpause(); - } - - // @dev Allows the CFO to capture the balance available to the contract. - function withdrawBalance() external onlyCFO { - uint256 balance = this.balance; - // Subtract all the currently pregnant kittens we have, plus 1 of margin. - uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - - if (balance > subtractFees) { - cfoAddress.send(balance - subtractFees); - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario009.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractScenario009.sol deleted file mode 100644 index 215c671848e..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario009.sol +++ /dev/null @@ -1,51 +0,0 @@ -//pragma solidity ^0.4.0; - -library Set { - // We define a new struct datatype that will be used to - // hold its data in the calling contract. - struct Data { mapping(uint => bool) flags; } - - // Note that the first parameter is of type "storage - // reference" and thus only its storage address and not - // its contents is passed as part of the call. This is a - // special feature of library functions. It is idiomatic - // to call the first parameter 'self', if the function can - // be seen as a method of that object. - function insert(Data storage self, uint value) - returns (bool) - { - if (self.flags[value]) - return false; // already there - self.flags[value] = true; - return true; - } - - function remove(Data storage self, uint value) - returns (bool) - { - if (!self.flags[value]) - return false; // not there - self.flags[value] = false; - return true; - } - - function contains(Data storage self, uint value) - returns (bool) - { - return self.flags[value]; - } -} - - -contract C { - Set.Data knownValues; - - function register(uint value) { - // The library functions can be called without a - // specific instance of the library, since the - // "instance" will be the current contract. - if (!Set.insert(knownValues, value)) - throw; - } - // In this contract, we can also directly access knownValues.flags, if we want. -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario010.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractScenario010.sol deleted file mode 100644 index f665ea9686e..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario010.sol +++ /dev/null @@ -1,107 +0,0 @@ -//pragma solidity ^0.4.11; - -contract TRON_ERC721 { - //name - function name() view public returns (string memory name){ - return "Tron ERC721 Token"; - } - //symbol - function symbol() view public returns (string memory symbol){ - return "T721T"; - } - - //totalSupply - - function totalSupply() view public returns (uint256 supply){ - uint256 totalSupply = 1000000000000; - return totalSupply; - } - - mapping(address => uint) private balances; - function balanceOf(address _owner) view public returns (uint balance) - { - return balances[_owner]; - } - - - mapping(uint256 => address) private tokenOwners; - mapping(uint256 => bool) private tokenExists; - function ownerOf(uint256 _tokenId) view public returns (address owner) { - require(tokenExists[_tokenId]); - return tokenOwners[_tokenId]; - } - - - mapping(address => mapping (address => uint256)) allowed; - function approve(address _to, uint256 _tokenId) public{ - require(msg.sender == ownerOf(_tokenId)); - require(msg.sender != _to); - allowed[msg.sender][_to] = _tokenId; - emit Approval(msg.sender, _to, _tokenId); - } - - - function takeOwnership(uint256 _tokenId) public { - require(tokenExists[_tokenId]); - address oldOwner = ownerOf(_tokenId); - address newOwner = msg.sender; - require(newOwner != oldOwner); - require(allowed[oldOwner][newOwner] == _tokenId); - balances[oldOwner] -= 1; - tokenOwners[_tokenId] = newOwner; - balances[newOwner] += 1; - emit Transfer(oldOwner, newOwner, _tokenId); - } - - - mapping(address => mapping(uint256 => uint256)) private ownerTokens; - function removeFromTokenList(address owner, uint256 _tokenId) private { - for(uint256 i = 0;ownerTokens[owner][i] != _tokenId;i++){ - ownerTokens[owner][i] = 0; - } - } - - function transfer(address _to, uint256 _tokenId) public{ - address currentOwner = msg.sender; - address newOwner = _to; - require(tokenExists[_tokenId]); - require(currentOwner == ownerOf(_tokenId)); - require(currentOwner != newOwner); - require(newOwner != address(0)); - address oldOwner =currentOwner; - removeFromTokenList(oldOwner,_tokenId); - balances[oldOwner] -= 1; - tokenOwners[_tokenId] = newOwner; - balances[newOwner] += 1; - emit Transfer(oldOwner, newOwner, _tokenId); - } - - function transferFrom(address _from,address _to, uint256 _tokenId) public{ - address currentOwner = _from; - address newOwner = _to; - require(tokenExists[_tokenId]); - require(currentOwner == ownerOf(_tokenId)); - require(currentOwner != newOwner); - require(newOwner != address(0)); - address oldOwner =currentOwner; - removeFromTokenList(oldOwner,_tokenId); - balances[oldOwner] -= 1; - tokenOwners[_tokenId] = newOwner; - balances[newOwner] += 1; - emit Transfer(oldOwner, newOwner, _tokenId); - } - - - function tokenOfOwnerByIndex(address _owner, uint256 _index) view public returns (uint tokenId){ - return ownerTokens[_owner][_index]; - } - - - mapping(uint256 => string) tokenLinks; - function tokenMetadata(uint256 _tokenId) view public returns (string memory infoUrl) { - return tokenLinks[_tokenId]; - } - // Events - event Transfer(address indexed _from, address indexed _to, uint256 _tokenId); - event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId); -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario011.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractScenario011.sol deleted file mode 100644 index 4d1e9c1ba12..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario011.sol +++ /dev/null @@ -1,2050 +0,0 @@ -//pragma solidity ^0.4.11; - - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() public { - owner = msg.sender; - } - - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } - -} - - - - -/// @title A facet of KittyCore that manages special access privileges. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyAccessControl { - // This facet controls access control for CryptoKitties. There are four roles managed here: - // - // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart - // contracts. It is also the only role that can unpause the smart contract. It is initially - // set to the address that created the smart contract in the KittyCore constructor. - // - // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. - // - // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. - // - // It should be noted that these roles are distinct without overlap in their access abilities, the - // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any - // address to any role, the CEO address itself doesn't have the ability to act in those roles. This - // restriction is intentional so that we aren't tempted to use the CEO address frequently out of - // convenience. The less we use an address, the less likely it is that we somehow compromise the - // account. - - /// @dev Emited when contract is upgraded - See README.md for updgrade plan - event ContractUpgrade(address newContract); - - // The addresses of the accounts (or contracts) that can execute actions within each roles. - address public ceoAddress; - address public cfoAddress; - address public cooAddress; - - // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked - bool public paused = false; - - /// @dev Access modifier for CEO-only functionality - modifier onlyCEO() { - require(msg.sender == ceoAddress); - _; - } - - /// @dev Access modifier for CFO-only functionality - modifier onlyCFO() { - require(msg.sender == cfoAddress); - _; - } - - /// @dev Access modifier for COO-only functionality - modifier onlyCOO() { - require(msg.sender == cooAddress); - _; - } - - modifier onlyCLevel() { - require( - msg.sender == cooAddress || - msg.sender == ceoAddress || - msg.sender == cfoAddress - ); - _; - } - - /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. - /// @param _newCEO The address of the new CEO - function setCEO(address _newCEO) external onlyCEO { - require(_newCEO != address(0)); - - ceoAddress = _newCEO; - } - - /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. - /// @param _newCFO The address of the new CFO - function setCFO(address _newCFO) external onlyCEO { - require(_newCFO != address(0)); - - cfoAddress = _newCFO; - } - - /// @dev Assigns a new address to act as the COO. Only available to the current CEO. - /// @param _newCOO The address of the new COO - function setCOO(address _newCOO) external onlyCEO { - require(_newCOO != address(0)); - - cooAddress = _newCOO; - } - - /*** Pausable functionality adapted from OpenZeppelin ***/ - - /// @dev Modifier to allow actions only when the contract IS NOT paused - modifier whenNotPaused() { - require(!paused); - _; - } - - /// @dev Modifier to allow actions only when the contract IS paused - modifier whenPaused { - require(paused); - _; - } - - /// @dev Called by any "C-level" role to pause the contract. Used only when - /// a bug or exploit is detected and we need to limit damage. - function pause() external onlyCLevel whenNotPaused { - paused = true; - } - - /// @dev Unpauses the smart contract. Can only be called by the CEO, since - /// one reason we may pause the contract is when CFO or COO accounts are - /// compromised. - /// @notice This is public rather than external so it can be called by - /// derived contracts. - function unpause() public onlyCEO whenPaused { - // can't unpause if contract was upgraded - paused = false; - } -} - - - - -/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBase is KittyAccessControl { - /*** EVENTS ***/ - - /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously - /// includes any time a cat is created through the giveBirth method, but it is also called - /// when a new gen0 cat is created. - event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); - - /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten - /// ownership is assigned, including births. - event Transfer(address from, address to, uint256 tokenId); - - /*** DATA TYPES ***/ - - /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy - /// of this structure, so great care was taken to ensure that it fits neatly into - /// exactly two 256-bit words. Note that the order of the members in this structure - /// is important because of the byte-packing rules used by Ethereum. - /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html - struct Kitty { - // The Kitty's genetic code is packed into these 256-bits, the format is - // sooper-sekret! A cat's genes never change. - uint256 genes; - - // The timestamp from the block when this cat came into existence. - uint64 birthTime; - - // The minimum timestamp after which this cat can engage in breeding - // activities again. This same timestamp is used for the pregnancy - // timer (for matrons) as well as the siring cooldown. - uint64 cooldownEndBlock; - - // The ID of the parents of this kitty, set to 0 for gen0 cats. - // Note that using 32-bit unsigned integers limits us to a "mere" - // 4 billion cats. This number might seem small until you realize - // that Ethereum currently has a limit of about 500 million - // transactions per year! So, this definitely won't be a problem - // for several years (even as Ethereum learns to scale). - uint32 matronId; - uint32 sireId; - - // Set to the ID of the sire cat for matrons that are pregnant, - // zero otherwise. A non-zero value here is how we know a cat - // is pregnant. Used to retrieve the genetic material for the new - // kitten when the birth transpires. - uint32 siringWithId; - - // Set to the index in the cooldown array (see below) that represents - // the current cooldown duration for this Kitty. This starts at zero - // for gen0 cats, and is initialized to floor(generation/2) for others. - // Incremented by one for each successful breeding action, regardless - // of whether this cat is acting as matron or sire. - uint16 cooldownIndex; - - // The "generation number" of this cat. Cats minted by the CK contract - // for sale are called "gen0" and have a generation number of 0. The - // generation number of all other cats is the larger of the two generation - // numbers of their parents, plus one. - // (i.e. max(matron.generation, sire.generation) + 1) - uint16 generation; - } - - /*** CONSTANTS ***/ - - /// @dev A lookup table indicating the cooldown duration after any successful - /// breeding action, called "pregnancy time" for matrons and "siring cooldown" - /// for sires. Designed such that the cooldown roughly doubles each time a cat - /// is bred, encouraging owners not to just keep breeding the same cat over - /// and over again. Caps out at one week (a cat can breed an unbounded number - /// of times, and the maximum cooldown is always seven days). - uint32[14] public cooldowns = [ - uint32(1 minutes), - uint32(2 minutes), - uint32(5 minutes), - uint32(10 minutes), - uint32(30 minutes), - uint32(1 hours), - uint32(2 hours), - uint32(4 hours), - uint32(8 hours), - uint32(16 hours), - uint32(1 days), - uint32(2 days), - uint32(4 days), - uint32(7 days) - ]; - - // An approximation of currently how many seconds are in between blocks. - uint256 public secondsPerBlock = 15; - - /*** STORAGE ***/ - - /// @dev An array containing the Kitty struct for all Kitties in existence. The ID - /// of each cat is actually an index into this array. Note that ID 0 is a negacat, - /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre - /// creature that is both matron and sire... to itself! Has an invalid genetic code. - /// In other words, cat ID 0 is invalid... ;-) - Kitty[] kitties; - - /// @dev A mapping from cat IDs to the address that owns them. All cats have - /// some valid owner address, even gen0 cats are created with a non-zero owner. - mapping (uint256 => address) public kittyIndexToOwner; - - // @dev A mapping from owner address to count of tokens that address owns. - // Used internally inside balanceOf() to resolve ownership count. - mapping (address => uint256) ownershipTokenCount; - - /// @dev A mapping from KittyIDs to an address that has been approved to call - /// transferFrom(). Each Kitty can only have one approved address for transfer - /// at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public kittyIndexToApproved; - - /// @dev A mapping from KittyIDs to an address that has been approved to use - /// this Kitty for siring via breedWith(). Each Kitty can only have one approved - /// address for siring at any time. A zero value means no approval is outstanding. - mapping (uint256 => address) public sireAllowedToAddress; - - /// @dev The address of the ClockAuction contract that handles sales of Kitties. This - /// same contract handles both peer-to-peer sales as well as the gen0 sales which are - /// initiated every 15 minutes. - SaleClockAuction public saleAuction; - - /// @dev The address of a custom ClockAuction subclassed contract that handles siring - /// auctions. Needs to be separate from saleAuction because the actions taken on success - /// after a sales and siring auction are quite different. - SiringClockAuction public siringAuction; - - /// @dev Assigns ownership of a specific Kitty to an address. - function _transfer(address _from, address _to, uint256 _tokenId) internal { - // Since the number of kittens is capped to 2^32 we can't overflow this - ownershipTokenCount[_to]++; - // transfer ownership - kittyIndexToOwner[_tokenId] = _to; - // When creating new kittens _from is 0x0, but we can't account that address. - if (_from != address(0)) { - ownershipTokenCount[_from]--; - // once the kitten is transferred also clear sire allowances - delete sireAllowedToAddress[_tokenId]; - // clear any previously approved ownership exchange - delete kittyIndexToApproved[_tokenId]; - } - // Emit the transfer event. - emit Transfer(_from, _to, _tokenId); - } - - /// @dev An internal method that creates a new kitty and stores it. This - /// method doesn't do any checking and should only be called when the - /// input data is known to be valid. Will generate both a Birth event - /// and a Transfer event. - /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) - /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) - /// @param _generation The generation number of this cat, must be computed by caller. - /// @param _genes The kitty's genetic code. - /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) - function _createKitty( - uint256 _matronId, - uint256 _sireId, - uint256 _generation, - uint256 _genes, - address _owner - ) - internal - returns (uint) - { - // These requires are not strictly necessary, our calling code should make - // sure that these conditions are never broken. However! _createKitty() is already - // an expensive call (for storage), and it doesn't hurt to be especially careful - // to ensure our data structures are always valid. - require(_matronId == uint256(uint32(_matronId))); - require(_sireId == uint256(uint32(_sireId))); - require(_generation == uint256(uint16(_generation))); - - // New kitty starts with the same cooldown as parent gen/2 - uint16 cooldownIndex = uint16(_generation / 2); - if (cooldownIndex > 13) { - cooldownIndex = 13; - } - - Kitty memory _kitty = Kitty({ - genes: _genes, - birthTime: uint64(now), - cooldownEndBlock: 0, - matronId: uint32(_matronId), - sireId: uint32(_sireId), - siringWithId: 0, - cooldownIndex: cooldownIndex, - generation: uint16(_generation) - }); - uint256 newKittenId = kitties.push(_kitty) - 1; - - // It's probably never going to happen, 4 billion cats is A LOT, but - // let's just be 100% sure we never let this happen. - require(newKittenId == uint256(uint32(newKittenId))); - - // emit the birth event - emit Birth( - _owner, - newKittenId, - uint256(_kitty.matronId), - uint256(_kitty.sireId), - _kitty.genes - ); - - // This will assign ownership, and also emit the Transfer event as - // per ERC721 draft - _transfer(address(0), _owner, newKittenId); - - return newKittenId; - } - - // Any C-level can fix how many seconds per blocks are currently observed. - function setSecondsPerBlock(uint256 secs) external onlyCLevel { - require(secs < cooldowns[0]); - secondsPerBlock = secs; - } -} - - -/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens -/// @author Dieter Shirley (https://github.com/dete) -contract ERC721 { - // Required methods - function totalSupply() public view returns (uint256 total); - function balanceOf(address _owner) public view returns (uint256 balance); - function ownerOf(uint256 _tokenId) external view returns (address owner); - function approve(address _to, uint256 _tokenId) external; - function transfer(address _to, uint256 _tokenId) external; - function transferFrom(address _from, address _to, uint256 _tokenId) external; - - // Events - event Transfer(address from, address to, uint256 tokenId); - event Approval(address owner, address approved, uint256 tokenId); - - // Optional - // function name() public view returns (string name); - // function symbol() public view returns (string symbol); - // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); - // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); - - // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) - function supportsInterface(bytes4 _interfaceID) external view returns (bool); -} - - -/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 -/// See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyOwnership is ERC721, KittyBase { - - /// @notice Name and symbol of the non fungible token, as defined in ERC721. - string public constant name = "CryptoKitties"; - string public constant symbol = "CK"; - - // The contract that will return kitty metadata - ERC721Metadata public erc721Metadata; - - bytes4 constant InterfaceSignature_ERC165 = - bytes4(keccak256('supportsInterface(bytes4)')); - - bytes4 constant InterfaceSignature_ERC721 = - bytes4(keccak256('name()')) ^ - bytes4(keccak256('symbol()')) ^ - bytes4(keccak256('totalSupply()')) ^ - bytes4(keccak256('balanceOf(address)')) ^ - bytes4(keccak256('ownerOf(uint256)')) ^ - bytes4(keccak256('approve(address,uint256)')) ^ - bytes4(keccak256('transfer(address,uint256)')) ^ - bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - bytes4(keccak256('tokensOfOwner(address)')) ^ - bytes4(keccak256('tokenMetadata(uint256,string)')); - - /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). - /// Returns true for any standardized interfaces implemented by this contract. We implement - /// ERC-165 (obviously!) and ERC-721. - function supportsInterface(bytes4 _interfaceID) external view returns (bool) - { - // DEBUG ONLY - //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); - - return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); - } - - /// @dev Set the address of the sibling contract that tracks metadata. - /// CEO only. - function setMetadataAddress(address _contractAddress) public onlyCEO { - erc721Metadata = ERC721Metadata(_contractAddress); - } - - // Internal utility functions: These functions all assume that their input arguments - // are valid. We leave it to public methods to sanitize their inputs and follow - // the required logic. - - /// @dev Checks if a given address is the current owner of a particular Kitty. - /// @param _claimant the address we are validating against. - /// @param _tokenId kitten id, only valid when > 0 - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToOwner[_tokenId] == _claimant; - } - - /// @dev Checks if a given address currently has transferApproval for a particular Kitty. - /// @param _claimant the address we are confirming kitten is approved for. - /// @param _tokenId kitten id, only valid when > 0 - function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { - return kittyIndexToApproved[_tokenId] == _claimant; - } - - /// @dev Marks an address as being approved for transferFrom(), overwriting any previous - /// approval. Setting _approved to address(0) clears all transfer approval. - /// NOTE: _approve() does NOT send the Approval event. This is intentional because - /// _approve() and transferFrom() are used together for putting Kitties on auction, and - /// there is no value in spamming the log with Approval events in that case. - function _approve(uint256 _tokenId, address _approved) internal { - kittyIndexToApproved[_tokenId] = _approved; - } - - /// @notice Returns the number of Kitties owned by a specific address. - /// @param _owner The owner address to check. - /// @dev Required for ERC-721 compliance - function balanceOf(address _owner) public view returns (uint256 count) { - return ownershipTokenCount[_owner]; - } - - /// @notice Transfers a Kitty to another address. If transferring to a smart - /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or - /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. - /// @param _to The address of the recipient, can be a user or contract. - /// @param _tokenId The ID of the Kitty to transfer. - /// @dev Required for ERC-721 compliance. - function transfer( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Disallow transfers to the auction contracts to prevent accidental - // misuse. Auction contracts should only take ownership of kitties - // through the allow + transferFrom flow. - require(_to != address(saleAuction)); - require(_to != address(siringAuction)); - - // You can only send your own cat. - require(_owns(msg.sender, _tokenId)); - - // Reassign ownership, clear pending approvals, emit Transfer event. - _transfer(msg.sender, _to, _tokenId); - } - - /// @notice Grant another address the right to transfer a specific Kitty via - /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. - /// @param _to The address to be granted transfer approval. Pass address(0) to - /// clear all approvals. - /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. - /// @dev Required for ERC-721 compliance. - function approve( - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Only an owner can grant transfer approval. - require(_owns(msg.sender, _tokenId)); - - // Register the approval (replacing any previous approval). - _approve(_tokenId, _to); - - // Emit approval event. - emit Approval(msg.sender, _to, _tokenId); - } - - /// @notice Transfer a Kitty owned by another address, for which the calling address - /// has previously been granted transfer approval by the owner. - /// @param _from The address that owns the Kitty to be transfered. - /// @param _to The address that should take ownership of the Kitty. Can be any address, - /// including the caller. - /// @param _tokenId The ID of the Kitty to be transferred. - /// @dev Required for ERC-721 compliance. - function transferFrom( - address _from, - address _to, - uint256 _tokenId - ) - external - whenNotPaused - { - // Safety check to prevent against an unexpected 0x0 default. - require(_to != address(0)); - // Disallow transfers to this contract to prevent accidental misuse. - // The contract should never own any kitties (except very briefly - // after a gen0 cat is created and before it goes on auction). - require(_to != address(this)); - // Check for approval and valid ownership - require(_approvedFor(msg.sender, _tokenId)); - require(_owns(_from, _tokenId)); - - // Reassign ownership (also clears pending approvals and emits Transfer event). - _transfer(_from, _to, _tokenId); - } - - /// @notice Returns the total number of Kitties currently in existence. - /// @dev Required for ERC-721 compliance. - function totalSupply() public view returns (uint) { - return kitties.length - 1; - } - - /// @notice Returns the address currently assigned ownership of a given Kitty. - /// @dev Required for ERC-721 compliance. - function ownerOf(uint256 _tokenId) - external - view - returns (address owner) - { - owner = kittyIndexToOwner[_tokenId]; - - require(owner != address(0)); - } - - /// @notice Returns a list of all Kitty IDs assigned to an address. - /// @param _owner The owner whose Kitties we are interested in. - /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly - /// expensive (it walks the entire Kitty array looking for cats belonging to owner), - /// but it also returns a dynamic array, which is only supported for web3 calls, and - /// not contract-to-contract calls. - function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { - uint256 tokenCount = balanceOf(_owner); - - if (tokenCount == 0) { - // Return an empty array - return new uint256[](0); - } else { - uint256[] memory result = new uint256[](tokenCount); - uint256 totalCats = totalSupply(); - uint256 resultIndex = 0; - - // We count on the fact that all cats have IDs starting at 1 and increasing - // sequentially up to the totalCat count. - uint256 catId; - - for (catId = 1; catId <= totalCats; catId++) { - if (kittyIndexToOwner[catId] == _owner) { - result[resultIndex] = catId; - resultIndex++; - } - } - - return result; - } - } - - /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _memcpy(uint _dest, uint _src, uint _len) private view { - // Copy word-length chunks while possible - for(; _len >= 32; _len -= 32) { - assembly { - mstore(_dest, mload(_src)) - } - _dest += 32; - _src += 32; - } - - // Copy remaining bytes - uint256 mask = 256 ** (32 - _len) - 1; - assembly { - let srcpart := and(mload(_src), not(mask)) - let destpart := and(mload(_dest), mask) - mstore(_dest, or(destpart, srcpart)) - } - } - - /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) - /// This method is licenced under the Apache License. - /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol - function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { - string memory outputString = new string(_stringLength); - uint256 outputPtr; - uint256 bytesPtr; - - assembly { - outputPtr := add(outputString, 32) - bytesPtr := _rawBytes - } - - _memcpy(outputPtr, bytesPtr, _stringLength); - - return outputString; - } - - /// @notice Returns a URI pointing to a metadata package for this token conforming to - /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) - /// @param _tokenId The ID number of the Kitty whose metadata should be returned. - function tokenMetadata(uint256 _tokenId, string _preferredTransport) external view returns (string infoUrl) { - require( address(erc721Metadata) != address(0)); - bytes32[4] memory buffer; - uint256 count; - (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); - - return _toString(buffer, count); - } -} - - - - -/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. -contract KittyBreeding is KittyOwnership { - - /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy - /// timer begins for the matron. - event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); - - /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards - /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by - /// the COO role as the gas price changes. - uint256 public autoBirthFee = 2 sun; - - // Keeps track of number of pregnant kitties. - uint256 public pregnantKitties; - - /// @dev The address of the sibling contract that is used to implement the sooper-sekret - /// genetic combination algorithm. - GeneScienceInterface public geneScience; - - /// @dev Update the address of the genetic contract, can only be called by the CEO. - /// @param _address An address of a GeneScience contract instance to be used from this point forward. - function setGeneScienceAddress(address _address) external onlyCEO { - GeneScienceInterface candidateContract = GeneScienceInterface(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isGeneScience()); - - // Set the new contract address - geneScience = candidateContract; - } - - /// @dev Checks that a given kitten is able to breed. Requires that the - /// current cooldown is finished (for sires) and also checks that there is - /// no pending pregnancy. - function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { - // In addition to checking the cooldownEndBlock, we also need to check to see if - // the cat has a pending birth; there can be some period of time between the end - // of the pregnacy timer and the birth event. - return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); - } - - /// @dev Check if a sire has authorized breeding with this matron. True if both sire - /// and matron have the same owner, or if the sire has given siring permission to - /// the matron's owner (via approveSiring()). - function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { - address matronOwner = kittyIndexToOwner[_matronId]; - address sireOwner = kittyIndexToOwner[_sireId]; - - // Siring is okay if they have same owner, or if the matron's owner was given - // permission to breed with this sire. - return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); - } - - /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. - /// Also increments the cooldownIndex (unless it has hit the cap). - /// @param _kitten A reference to the Kitty in storage which needs its timer started. - function _triggerCooldown(Kitty storage _kitten) internal { - // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). - _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); - - // Increment the breeding count, clamping it at 13, which is the length of the - // cooldowns array. We could check the array size dynamically, but hard-coding - // this as a constant saves gas. Yay, Solidity! - if (_kitten.cooldownIndex < 13) { - _kitten.cooldownIndex += 1; - } - } - - /// @notice Grants approval to another user to sire with one of your Kitties. - /// @param _addr The address that will be able to sire with your Kitty. Set to - /// address(0) to clear all siring approvals for this Kitty. - /// @param _sireId A Kitty that you own that _addr will now be able to sire with. - function approveSiring(address _addr, uint256 _sireId) - external - whenNotPaused - { - require(_owns(msg.sender, _sireId)); - sireAllowedToAddress[_sireId] = _addr; - } - - /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only - /// be called by the COO address. (This fee is used to offset the gas cost incurred - /// by the autobirth daemon). - function setAutoBirthFee(uint256 val) external onlyCOO { - autoBirthFee = val; - } - - /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation - /// period has passed. - function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { - return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); - } - - /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or - /// in the middle of a siring cooldown). - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isReadyToBreed(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - Kitty storage kit = kitties[_kittyId]; - return _isReadyToBreed(kit); - } - - /// @dev Checks whether a kitty is currently pregnant. - /// @param _kittyId reference the id of the kitten, any user can inquire about it - function isPregnant(uint256 _kittyId) - public - view - returns (bool) - { - require(_kittyId > 0); - // A kitty is pregnant if and only if this field is set - return kitties[_kittyId].siringWithId != 0; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT - /// check ownership permissions (that is up to the caller). - /// @param _matron A reference to the Kitty struct of the potential matron. - /// @param _matronId The matron's ID. - /// @param _sire A reference to the Kitty struct of the potential sire. - /// @param _sireId The sire's ID - function _isValidMatingPair( - Kitty storage _matron, - uint256 _matronId, - Kitty storage _sire, - uint256 _sireId - ) - private - view - returns(bool) - { - // A Kitty can't breed with itself! - if (_matronId == _sireId) { - return false; - } - - // Kitties can't breed with their parents. - if (_matron.matronId == _sireId || _matron.sireId == _sireId) { - return false; - } - if (_sire.matronId == _matronId || _sire.sireId == _matronId) { - return false; - } - - // We can short circuit the sibling check (below) if either cat is - // gen zero (has a matron ID of zero). - if (_sire.matronId == 0 || _matron.matronId == 0) { - return true; - } - - // Kitties can't breed with full or half siblings. - if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { - return false; - } - if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { - return false; - } - - // Everything seems cool! Let's get DTF. - return true; - } - - /// @dev Internal check to see if a given sire and matron are a valid mating pair for - /// breeding via auction (i.e. skips ownership and siring approval checks). - function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) - internal - view - returns (bool) - { - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId); - } - - /// @notice Checks to see if two cats can breed together, including checks for - /// ownership and siring approvals. Does NOT check that both cats are ready for - /// breeding (i.e. breedWith could still fail until the cooldowns are finished). - /// TODO: Shouldn't this check pregnancy and cooldowns?!? - /// @param _matronId The ID of the proposed matron. - /// @param _sireId The ID of the proposed sire. - function canBreedWith(uint256 _matronId, uint256 _sireId) - external - view - returns(bool) - { - require(_matronId > 0); - require(_sireId > 0); - Kitty storage matron = kitties[_matronId]; - Kitty storage sire = kitties[_sireId]; - return _isValidMatingPair(matron, _matronId, sire, _sireId) && - _isSiringPermitted(_sireId, _matronId); - } - - /// @dev Internal utility function to initiate breeding, assumes that all breeding - /// requirements have been checked. - function _breedWith(uint256 _matronId, uint256 _sireId) internal { - // Grab a reference to the Kitties from storage. - Kitty storage sire = kitties[_sireId]; - Kitty storage matron = kitties[_matronId]; - - // Mark the matron as pregnant, keeping track of who the sire is. - matron.siringWithId = uint32(_sireId); - - // Trigger the cooldown for both parents. - _triggerCooldown(sire); - _triggerCooldown(matron); - - // Clear siring permission for both parents. This may not be strictly necessary - // but it's likely to avoid confusion! - delete sireAllowedToAddress[_matronId]; - delete sireAllowedToAddress[_sireId]; - - // Every time a kitty gets pregnant, counter is incremented. - pregnantKitties++; - - // Emit the pregnancy event. - emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); - } - - /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you - /// have previously been given Siring approval. Will either make your cat pregnant, or will - /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() - /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) - /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) - function breedWithAuto(uint256 _matronId, uint256 _sireId) - external - payable - whenNotPaused - { - // Checks for payment. - require(msg.value >= autoBirthFee); - - // Caller must own the matron. - require(_owns(msg.sender, _matronId)); - - // Neither sire nor matron are allowed to be on auction during a normal - // breeding operation, but we don't need to check that explicitly. - // For matron: The caller of this function can't be the owner of the matron - // because the owner of a Kitty on auction is the auction house, and the - // auction house will never call breedWith(). - // For sire: Similarly, a sire on auction will be owned by the auction house - // and the act of transferring ownership will have cleared any oustanding - // siring approval. - // Thus we don't need to spend gas explicitly checking to see if either cat - // is on auction. - - // Check that matron and sire are both owned by caller, or that the sire - // has given siring permission to caller (i.e. matron's owner). - // Will fail for _sireId = 0 - require(_isSiringPermitted(_sireId, _matronId)); - - // Grab a reference to the potential matron - Kitty storage matron = kitties[_matronId]; - - // Make sure matron isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(matron)); - - // Grab a reference to the potential sire - Kitty storage sire = kitties[_sireId]; - - // Make sure sire isn't pregnant, or in the middle of a siring cooldown - require(_isReadyToBreed(sire)); - - // Test that these cats are a valid mating pair. - require(_isValidMatingPair( - matron, - _matronId, - sire, - _sireId - )); - - // All checks passed, kitty gets pregnant! - _breedWith(_matronId, _sireId); - } - - /// @notice Have a pregnant Kitty give birth! - /// @param _matronId A Kitty ready to give birth. - /// @return The Kitty ID of the new kitten. - /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, - /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned - /// to the current owner of the matron. Upon successful completion, both the matron and the - /// new kitten will be ready to breed again. Note that anyone can call this function (if they - /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. - function giveBirth(uint256 _matronId) - external - whenNotPaused - returns(uint256) - { - // Grab a reference to the matron in storage. - Kitty storage matron = kitties[_matronId]; - - // Check that the matron is a valid cat. - require(matron.birthTime != 0); - - // Check that the matron is pregnant, and that its time has come! - require(_isReadyToGiveBirth(matron)); - - // Grab a reference to the sire in storage. - uint256 sireId = matron.siringWithId; - Kitty storage sire = kitties[sireId]; - - // Determine the higher generation number of the two parents - uint16 parentGen = matron.generation; - if (sire.generation > matron.generation) { - parentGen = sire.generation; - } - - // Call the sooper-sekret gene mixing operation. - uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); - - // Make the new kitten! - address owner = kittyIndexToOwner[_matronId]; - uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); - - // Clear the reference to sire from the matron (REQUIRED! Having siringWithId - // set is what marks a matron as being pregnant.) - delete matron.siringWithId; - - // Every time a kitty gives birth counter is decremented. - pregnantKitties--; - - // Send the balance fee to the person who made birth happen. - msg.sender.transfer(autoBirthFee); - - // return the new kitten's ID - return kittenId; - } -} - - - -/// @title Handles creating auctions for sale and siring of kitties. -/// This wrapper of ReverseAuction exists only so that users can create -/// auctions with only one transaction. -contract KittyAuction is KittyBreeding { - - // @notice The auction contract variables are defined in KittyBase to allow - // us to refer to them in KittyOwnership to prevent accidental transfers. - // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. - // `siringAuction` refers to the auction for siring rights of kitties. - - /// @dev Sets the reference to the sale auction. - /// @param _address - Address of sale contract. - function setSaleAuctionAddress(address _address) external onlyCEO { - SaleClockAuction candidateContract = SaleClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSaleClockAuction()); - - // Set the new contract address - saleAuction = candidateContract; - } - - /// @dev Sets the reference to the siring auction. - /// @param _address - Address of siring contract. - function setSiringAuctionAddress(address _address) external onlyCEO { - SiringClockAuction candidateContract = SiringClockAuction(_address); - - // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 - require(candidateContract.isSiringClockAuction()); - - // Set the new contract address - siringAuction = candidateContract; - } - - /// @dev Put a kitty up for auction. - /// Does some ownership trickery to create auctions in one tx. - function createSaleAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - // Ensure the kitty is not pregnant to prevent the auction - // contract accidentally receiving ownership of the child. - // NOTE: the kitty IS allowed to be in a cooldown. - require(!isPregnant(_kittyId)); - _approve(_kittyId, address(saleAuction)); - // Sale auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - saleAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Put a kitty up for auction to be sire. - /// Performs checks to ensure the kitty can be sired, then - /// delegates to reverse auction. - function createSiringAuction( - uint256 _kittyId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration - ) - external - whenNotPaused - { - // Auction contract checks input sizes - // If kitty is already on any auction, this will throw - // because it will be owned by the auction contract. - require(_owns(msg.sender, _kittyId)); - require(isReadyToBreed(_kittyId)); - _approve(_kittyId, address(siringAuction)); - // Siring auction throws if inputs are invalid and clears - // transfer and sire approval after escrowing the kitty. - siringAuction.createAuction( - _kittyId, - _startingPrice, - _endingPrice, - _duration, - msg.sender - ); - } - - /// @dev Completes a siring auction by bidding. - /// Immediately breeds the winning matron with the sire on auction. - /// @param _sireId - ID of the sire on auction. - /// @param _matronId - ID of the matron owned by the bidder. - function bidOnSiringAuction( - uint256 _sireId, - uint256 _matronId - ) - external - payable - whenNotPaused - { - // Auction contract checks input sizes - require(_owns(msg.sender, _matronId)); - require(isReadyToBreed(_matronId)); - require(_canBreedWithViaAuction(_matronId, _sireId)); - - // Define the current price of the auction. - uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); - require(msg.value >= currentPrice + autoBirthFee); - - // Siring auction will throw if the bid fails. - siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); - _breedWith(uint32(_matronId), uint32(_sireId)); - } - - /// @dev Transfers the balance of the sale auction contract - /// to the KittyCore contract. We use two-step withdrawal to - /// prevent two transfer calls in the auction bid function. - function withdrawAuctionBalances() external onlyCLevel { - saleAuction.withdrawBalance(); - siringAuction.withdrawBalance(); - } -} - - -/// @title all functions related to creating kittens -contract KittyMinting is KittyAuction { - - // Limits the number of cats the contract owner can ever create. - uint256 public constant PROMO_CREATION_LIMIT = 5000; - uint256 public constant GEN0_CREATION_LIMIT = 45000; - - // Constants for gen0 auctions. - uint256 public constant GEN0_STARTING_PRICE = 10 sun; - uint256 public constant GEN0_AUCTION_DURATION = 1 days; - - // Counts the number of cats the contract owner has created. - uint256 public promoCreatedCount; - uint256 public gen0CreatedCount; - - /// @dev we can create promo kittens, up to a limit. Only callable by COO - /// @param _genes the encoded genes of the kitten to be created, any value is accepted - /// @param _owner the future owner of the created kittens. Default to contract COO - function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { - address kittyOwner = _owner; - if (kittyOwner == address(0)) { - kittyOwner = cooAddress; - } - require(promoCreatedCount < PROMO_CREATION_LIMIT); - - promoCreatedCount++; - _createKitty(0, 0, 0, _genes, kittyOwner); - } - - /// @dev Creates a new gen0 kitty with the given genes and - /// creates an auction for it. - function createGen0Auction(uint256 _genes) external onlyCOO { - require(gen0CreatedCount < GEN0_CREATION_LIMIT); - - uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); - _approve(kittyId, address(saleAuction)); - - saleAuction.createAuction( - kittyId, - _computeNextGen0Price(), - 0, - GEN0_AUCTION_DURATION, - address(uint160(address(this))) - ); - - gen0CreatedCount++; - } - - /// @dev Computes the next gen0 auction starting price, given - /// the average of the past 5 prices + 50%. - function _computeNextGen0Price() internal view returns (uint256) { - uint256 avePrice = saleAuction.averageGen0SalePrice(); - - // Sanity check to ensure we don't overflow arithmetic - require(avePrice == uint256(uint128(avePrice))); - - uint256 nextPrice = avePrice + (avePrice / 2); - - // We never auction for less than starting price - if (nextPrice < GEN0_STARTING_PRICE) { - nextPrice = GEN0_STARTING_PRICE; - } - - return nextPrice; - } -} - - - -/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. -/// @author Axiom Zen (https://www.axiomzen.co) -/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. -contract KittyCore is KittyMinting { - - // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, - // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts - // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are - // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping - // them in their own contracts, we can upgrade them without disrupting the main contract that tracks - // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of - // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. - // Don't worry, I'm sure someone will reverse engineer it soon enough! - // - // Secondly, we break the core contract into multiple files using inheritence, one for each major - // facet of functionality of CK. This allows us to keep related code bundled together while still - // avoiding a single giant file with everything in it. The breakdown is as follows: - // - // - KittyBase: This is where we define the most fundamental code shared throughout the core - // functionality. This includes our main data storage, constants and data types, plus - // internal functions for managing these items. - // - // - KittyAccessControl: This contract manages the various addresses and constraints for operations - // that can be executed only by specific roles. Namely CEO, CFO and COO. - // - // - KittyOwnership: This provides the methods required for basic non-fungible token - // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). - // - // - KittyBreeding: This file contains the methods necessary to breed cats together, including - // keeping track of siring offers, and relies on an external genetic combination contract. - // - // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring - // services. The actual auction functionality is handled in two sibling contracts (one - // for sales and one for siring), while auction creation and bidding is mostly mediated - // through this facet of the core contract. - // - // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. - // We can make up to 5000 "promo" cats that can be given away (especially important when - // the community is new), and all others can only be created and then immediately put up - // for auction via an algorithmically determined starting price. Regardless of how they - // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the - // community to breed, breed, breed! - - // Set in case the core contract is broken and an upgrade is required - address public newContractAddress; - - /// @notice Creates the main CryptoKitties smart contract instance. - constructor() public { - // Starts paused. - paused = true; - - // the creator of the contract is the initial CEO - ceoAddress = msg.sender; - - // the creator of the contract is also the initial COO - cooAddress = msg.sender; - - // start with the mythical kitten 0 - so we don't have generation-0 parent issues - _createKitty(0, 0, 0, uint256(-1), address(0)); - } - - /// @dev Used to mark the smart contract as upgraded, in case there is a serious - /// breaking bug. This method does nothing but keep track of the new contract and - /// emit a message indicating that the new address is set. It's up to clients of this - /// contract to update to the new contract address in that case. (This contract will - /// be paused indefinitely if such an upgrade takes place.) - /// @param _v2Address new address - function setNewAddress(address _v2Address) external onlyCEO whenPaused { - // See README.md for updgrade plan - newContractAddress = _v2Address; - emit ContractUpgrade(_v2Address); - } - - /// @notice No tipping! - /// @dev Reject all Ether from being sent here, unless it's from one of the - /// two auction contracts. (Hopefully, we can prevent user accidents.) - function() external payable { - require( - msg.sender == address(saleAuction) || - msg.sender == address(siringAuction) - ); - } - - /// @notice Returns all the relevant information about a specific kitty. - /// @param _id The ID of the kitty of interest. - function getKitty(uint256 _id) - external - view - returns ( - bool isGestating, - bool isReady, - uint256 cooldownIndex, - uint256 nextActionAt, - uint256 siringWithId, - uint256 birthTime, - uint256 matronId, - uint256 sireId, - uint256 generation, - uint256 genes - ) { - Kitty storage kit = kitties[_id]; - - // if this variable is 0 then it's not gestating - isGestating = (kit.siringWithId != 0); - isReady = (kit.cooldownEndBlock <= block.number); - cooldownIndex = uint256(kit.cooldownIndex); - nextActionAt = uint256(kit.cooldownEndBlock); - siringWithId = uint256(kit.siringWithId); - birthTime = uint256(kit.birthTime); - matronId = uint256(kit.matronId); - sireId = uint256(kit.sireId); - generation = uint256(kit.generation); - genes = kit.genes; - } - - /// @dev Override unpause so it requires all external contract addresses - /// to be set before contract can be unpaused. Also, we can't have - /// newContractAddress set either, because then the contract was upgraded. - /// @notice This is public rather than external so we can call super.unpause - /// without using an expensive CALL. - - function unpause() public onlyCEO whenPaused { - require(address(saleAuction) != address(0)); - require(address(siringAuction) != address(0)); - require(address(geneScience) != address(0)); - require(newContractAddress == address(0)); - - // Actually unpause the contract. - super.unpause(); - } - - // @dev Allows the CFO to capture the balance available to the contract. - function withdrawBalance() external onlyCFO { - uint256 balance = address(this).balance; - // Subtract all the currently pregnant kittens we have, plus 1 of margin. - uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; - - if (balance > subtractFees) { - cfoAddress.transfer(balance - subtractFees); - } - } -} - - - - - - - - - - - - - -// // Auction wrapper functions - - -// Auction wrapper functions - - - - - - - -/// @title SEKRETOOOO -contract GeneScienceInterface { - - function isGeneScience() public pure returns (bool){ - return true; - } - - /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor - /// @param genes1 genes of mom - /// @param genes2 genes of sire - /// @return the genes that are supposed to be passed down the child - function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ - - return (genes1+genes2+targetBlock)/2; - - -} -} - - - - - - - - - - - - - - - - -/// @title The external contract that is responsible for generating metadata for the kitties, -/// it has one function that will return the data as bytes. -contract ERC721Metadata { - /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. - function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { - if (_tokenId == 1) { - buffer[0] = "Hello World! :D"; - count = 15; - } else if (_tokenId == 2) { - buffer[0] = "I would definitely choose a medi"; - buffer[1] = "um length string."; - count = 49; - } else if (_tokenId == 3) { - buffer[0] = "Lorem ipsum dolor sit amet, mi e"; - buffer[1] = "st accumsan dapibus augue lorem,"; - buffer[2] = " tristique vestibulum id, libero"; - buffer[3] = " suscipit varius sapien aliquam."; - count = 128; - } - } -} - - - - - - - - - - - - - - - -/// @title Auction Core -/// @dev Contains models, variables, and internal methods for the auction. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuctionBase { - - // Represents an auction on an NFT - struct Auction { - // Current owner of NFT - address seller; - // Price (in wei) at beginning of auction - uint128 startingPrice; - // Price (in wei) at end of auction - uint128 endingPrice; - // Duration (in seconds) of auction - uint64 duration; - // Time when auction started - // NOTE: 0 if this auction has been concluded - uint64 startedAt; - } - - // Reference to contract tracking NFT ownership - ERC721 public nonFungibleContract; - - // Cut owner takes on each auction, measured in basis points (1/100 of a percent). - // Values 0-10,000 map to 0%-100% - uint256 public ownerCut; - - // Map from token ID to their corresponding auction. - mapping (uint256 => Auction) tokenIdToAuction; - - event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); - event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); - event AuctionCancelled(uint256 tokenId); - - /// @dev Returns true if the claimant owns the token. - /// @param _claimant - Address claiming to own the token. - /// @param _tokenId - ID of token whose ownership to verify. - function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { - return (nonFungibleContract.ownerOf(_tokenId) == _claimant); - } - - /// @dev Escrows the NFT, assigning ownership to this contract. - /// Throws if the escrow fails. - /// @param _owner - Current owner address of token to escrow. - /// @param _tokenId - ID of token whose approval to verify. - function _escrow(address _owner, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transferFrom(_owner, address(this), _tokenId); - } - - /// @dev Transfers an NFT owned by this contract to another address. - /// Returns true if the transfer succeeds. - /// @param _receiver - Address to transfer NFT to. - /// @param _tokenId - ID of token to transfer. - function _transfer(address _receiver, uint256 _tokenId) internal { - // it will throw if transfer fails - nonFungibleContract.transfer(_receiver, _tokenId); - } - - /// @dev Adds an auction to the list of open auctions. Also fires the - /// AuctionCreated event. - /// @param _tokenId The ID of the token to be put on auction. - /// @param _auction Auction to add. - function _addAuction(uint256 _tokenId, Auction memory _auction) internal { - // Require that all auctions have a duration of - // at least one minute. (Keeps our math from getting hairy!) - require(_auction.duration >= 1 minutes); - - tokenIdToAuction[_tokenId] = _auction; - - emit AuctionCreated( - uint256(_tokenId), - uint256(_auction.startingPrice), - uint256(_auction.endingPrice), - uint256(_auction.duration) - ); - } - - /// @dev Cancels an auction unconditionally. - function _cancelAuction(uint256 _tokenId, address _seller) internal { - _removeAuction(_tokenId); - _transfer(_seller, _tokenId); - emit AuctionCancelled(_tokenId); - } - - /// @dev Computes the price and transfers winnings. - /// Does NOT transfer ownership of token. - function _bid(uint256 _tokenId, uint256 _bidAmount) - internal - returns (uint256) - { - // Get a reference to the auction struct - Auction storage auction = tokenIdToAuction[_tokenId]; - - // Explicitly check that this auction is currently live. - // (Because of how Ethereum mappings work, we can't just count - // on the lookup above failing. An invalid _tokenId will just - // return an auction object that is all zeros.) - require(_isOnAuction(auction)); - - // Check that the bid is greater than or equal to the current price - uint256 price = _currentPrice(auction); - require(_bidAmount >= price); - - // Grab a reference to the seller before the auction struct - // gets deleted. - address seller = auction.seller; - - // The bid is good! Remove the auction before sending the fees - // to the sender so we can't have a reentrancy attack. - _removeAuction(_tokenId); - - // Transfer proceeds to seller (if there are any!) - if (price > 0) { - // Calculate the auctioneer's cut. - // (NOTE: _computeCut() is guaranteed to return a - // value <= price, so this subtraction can't go negative.) - uint256 auctioneerCut = _computeCut(price); - uint256 sellerProceeds = price - auctioneerCut; - - // NOTE: Doing a transfer() in the middle of a complex - // method like this is generally discouraged because of - // reentrancy attacks and DoS attacks if the seller is - // a contract with an invalid fallback function. We explicitly - // guard against reentrancy attacks by removing the auction - // before calling transfer(), and the only thing the seller - // can DoS is the sale of their own asset! (And if it's an - // accident, they can call cancelAuction(). ) - seller.transfer(sellerProceeds); - } - - // Calculate any excess funds included with the bid. If the excess - // is anything worth worrying about, transfer it back to bidder. - // NOTE: We checked above that the bid amount is greater than or - // equal to the price so this cannot underflow. - uint256 bidExcess = _bidAmount - price; - - // Return the funds. Similar to the previous transfer, this is - // not susceptible to a re-entry attack because the auction is - // removed before any transfers occur. - msg.sender.transfer(bidExcess); - - // Tell the world! - emit AuctionSuccessful(_tokenId, price, msg.sender); - - return price; - } - - /// @dev Removes an auction from the list of open auctions. - /// @param _tokenId - ID of NFT on auction. - function _removeAuction(uint256 _tokenId) internal { - delete tokenIdToAuction[_tokenId]; - } - - /// @dev Returns true if the NFT is on auction. - /// @param _auction - Auction to check. - function _isOnAuction(Auction storage _auction) internal view returns (bool) { - return (_auction.startedAt > 0); - } - - /// @dev Returns current price of an NFT on auction. Broken into two - /// functions (this one, that computes the duration from the auction - /// structure, and the other that does the price computation) so we - /// can easily test that the price computation works correctly. - function _currentPrice(Auction storage _auction) - internal - view - returns (uint256) - { - uint256 secondsPassed = 0; - - // A bit of insurance against negative values (or wraparound). - // Probably not necessary (since Ethereum guarnatees that the - // now variable doesn't ever go backwards). - if (now > _auction.startedAt) { - secondsPassed = now - _auction.startedAt; - } - - return _computeCurrentPrice( - _auction.startingPrice, - _auction.endingPrice, - _auction.duration, - secondsPassed - ); - } - - /// @dev Computes the current price of an auction. Factored out - /// from _currentPrice so we can run extensive unit tests. - /// When testing, make this function public and turn on - /// `Current price computation` test suite. - function _computeCurrentPrice( - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - uint256 _secondsPassed - ) - internal - pure - returns (uint256) - { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our public functions carefully cap the maximum values for - // time (at 64-bits) and currency (at 128-bits). _duration is - // also known to be non-zero (see the require() statement in - // _addAuction()) - if (_secondsPassed >= _duration) { - // We've reached the end of the dynamic pricing portion - // of the auction, just return the end price. - return _endingPrice; - } else { - // Starting price can be higher than ending price (and often is!), so - // this delta can be negative. - int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); - - // This multiplication can't overflow, _secondsPassed will easily fit within - // 64-bits, and totalPriceChange will easily fit within 128-bits, their product - // will always fit within 256-bits. - int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); - - // currentPriceChange can be negative, but if so, will have a magnitude - // less that _startingPrice. Thus, this result will always end up positive. - int256 currentPrice = int256(_startingPrice) + currentPriceChange; - - return uint256(currentPrice); - } - } - - /// @dev Computes owner's cut of a sale. - /// @param _price - Sale price of NFT. - function _computeCut(uint256 _price) internal view returns (uint256) { - // NOTE: We don't use SafeMath (or similar) in this function because - // all of our entry functions carefully cap the maximum values for - // currency (at 128-bits), and ownerCut <= 10000 (see the require() - // statement in the ClockAuction constructor). The result of this - // function is always guaranteed to be <= _price. - return _price * ownerCut / 10000; - } - -} - - - - - - - -/** - * @title Pausable - * @dev Base contract which allows children to implement an emergency stop mechanism. - */ -contract Pausable is Ownable { - event Pause(); - event Unpause(); - - bool public paused = false; - - - /** - * @dev modifier to allow actions only when the contract IS paused - */ - modifier whenNotPaused() { - require(!paused); - _; - } - - /** - * @dev modifier to allow actions only when the contract IS NOT paused - */ - modifier whenPaused { - require(paused); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() onlyOwner whenNotPaused public returns (bool) { - paused = true; - emit Pause(); - return true; - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() onlyOwner whenPaused public returns (bool) { - paused = false; - emit Unpause(); - return true; - } -} - - -/// @title Clock auction for non-fungible tokens. -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract ClockAuction is Pausable, ClockAuctionBase { - - /// @dev The ERC-165 interface signature for ERC-721. - /// Ref: https://github.com/ethereum/EIPs/issues/165 - /// Ref: https://github.com/ethereum/EIPs/issues/721 - bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); - - /// @dev Constructor creates a reference to the NFT ownership contract - /// and verifies the owner cut is in the valid range. - /// @param _nftAddress - address of a deployed contract implementing - /// the Nonfungible Interface. - /// @param _cut - percent cut the owner takes on each auction, must be - /// between 0-10,000. - constructor(address _nftAddress, uint256 _cut) public { - require(_cut <= 10000); - ownerCut = _cut; - - ERC721 candidateContract = ERC721(_nftAddress); - require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); - nonFungibleContract = candidateContract; - } - - /// @dev Remove all Ether from the contract, which is the owner's cuts - /// as well as any Ether sent directly to the contract address. - /// Always transfers to the NFT contract, but can be called either by - /// the owner or the NFT contract. - function withdrawBalance() external { - address nftAddress = address(uint160(address(nonFungibleContract))); - - require( - msg.sender == owner || - msg.sender == nftAddress - ); - // We are using this boolean method to make sure that even if one fails it will still work - bool res = nftAddress.send(address(this).balance); - } - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of time to move between starting - /// price and ending price (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address _seller - ) - external - whenNotPaused - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(_owns(msg.sender, _tokenId)); - _escrow(msg.sender, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Bids on an open auction, completing the auction and transferring - /// ownership of the NFT if enough Ether is supplied. - /// @param _tokenId - ID of token to bid on. - function bid(uint256 _tokenId) - external - payable - whenNotPaused - { - // _bid will throw if the bid or funds transfer fails - _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - } - - /// @dev Cancels an auction that hasn't been won yet. - /// Returns the NFT to original owner. - /// @notice This is a state-modifying function that can - /// be called while the contract is paused. - /// @param _tokenId - ID of token on auction - function cancelAuction(uint256 _tokenId) - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - address seller = auction.seller; - require(msg.sender == seller); - _cancelAuction(_tokenId, seller); - } - - /// @dev Cancels an auction when the contract is paused. - /// Only the owner may do this, and NFTs are returned to - /// the seller. This should only be used in emergencies. - /// @param _tokenId - ID of the NFT on auction to cancel. - function cancelAuctionWhenPaused(uint256 _tokenId) - whenPaused - onlyOwner - external - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - _cancelAuction(_tokenId, auction.seller); - } - - /// @dev Returns auction info for an NFT on auction. - /// @param _tokenId - ID of NFT on auction. - function getAuction(uint256 _tokenId) - external - view - returns - ( - address seller, - uint256 startingPrice, - uint256 endingPrice, - uint256 duration, - uint256 startedAt - ) { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return ( - auction.seller, - auction.startingPrice, - auction.endingPrice, - auction.duration, - auction.startedAt - ); - } - - /// @dev Returns the current price of an auction. - /// @param _tokenId - ID of the token price we are checking. - function getCurrentPrice(uint256 _tokenId) - external - view - returns (uint256) - { - Auction storage auction = tokenIdToAuction[_tokenId]; - require(_isOnAuction(auction)); - return _currentPrice(auction); - } - -} - - -/// @title Reverse auction modified for siring -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SiringClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSiringAuctionAddress() call. - bool public isSiringClockAuction = true; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. Since this function is wrapped, - /// require sender to be KittyCore contract. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Places a bid for siring. Requires the sender - /// is the KittyCore contract because all bid methods - /// should be wrapped. Also returns the kitty to the - /// seller rather than the winner. - function bid(uint256 _tokenId) - external - payable - { - require(msg.sender == address(nonFungibleContract)); - address seller = tokenIdToAuction[_tokenId].seller; - // _bid checks that token ID is valid and will throw if bid fails - _bid(_tokenId, msg.value); - // We transfer the kitty back to the seller, the winner will get - // the offspring - _transfer(seller, _tokenId); - } - -} - - - - - -/// @title Clock auction modified for sale of kitties -/// @notice We omit a fallback function to prevent accidental sends to this contract. -contract SaleClockAuction is ClockAuction { - - // @dev Sanity check that allows us to ensure that we are pointing to the - // right auction in our setSaleAuctionAddress() call. - bool public isSaleClockAuction = true; - - // Tracks last 5 sale price of gen0 kitty sales - uint256 public gen0SaleCount; - uint256[5] public lastGen0SalePrices; - - // Delegate constructor - constructor(address _nftAddr, uint256 _cut) public - ClockAuction(_nftAddr, _cut) {} - - /// @dev Creates and begins a new auction. - /// @param _tokenId - ID of token to auction, sender must be owner. - /// @param _startingPrice - Price of item (in wei) at beginning of auction. - /// @param _endingPrice - Price of item (in wei) at end of auction. - /// @param _duration - Length of auction (in seconds). - /// @param _seller - Seller, if not the message sender - function createAuction( - uint256 _tokenId, - uint256 _startingPrice, - uint256 _endingPrice, - uint256 _duration, - address _seller - ) - external - { - // Sanity check that no inputs overflow how many bits we've allocated - // to store them in the auction struct. - require(_startingPrice == uint256(uint128(_startingPrice))); - require(_endingPrice == uint256(uint128(_endingPrice))); - require(_duration == uint256(uint64(_duration))); - - require(msg.sender == address(nonFungibleContract)); - _escrow(_seller, _tokenId); - Auction memory auction = Auction( - _seller, - uint128(_startingPrice), - uint128(_endingPrice), - uint64(_duration), - uint64(now) - ); - _addAuction(_tokenId, auction); - } - - /// @dev Updates lastSalePrice if seller is the nft contract - /// Otherwise, works the same as default bid method. - function bid(uint256 _tokenId) - external - payable - { - // _bid verifies token ID size - address seller = tokenIdToAuction[_tokenId].seller; - uint256 price = _bid(_tokenId, msg.value); - _transfer(msg.sender, _tokenId); - - // If not a gen0 auction, exit - if (seller == address(nonFungibleContract)) { - // Track gen0 sale prices - lastGen0SalePrices[gen0SaleCount % 5] = price; - gen0SaleCount++; - } - } - - function averageGen0SalePrice() external view returns (uint256) { - uint256 sum = 0; - for (uint256 i = 0; i < 5; i++) { - sum += lastGen0SalePrices[i]; - } - return sum / 5; - } - -} - - - - - - - diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario012.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractScenario012.sol deleted file mode 100644 index 81f64134298..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario012.sol +++ /dev/null @@ -1,57 +0,0 @@ -//pragma solidity ^0.4.0; -contract PayTest { - -uint256 public n; -constructor() payable public{ -n = 0; -} - -function nPlusOne() public{ -n = n+1; -} - -//get current contract balance -function getBalance() payable public returns (uint) { -return address(this).balance; -} - -function getSenderBalance() public view returns(address, uint) { -return (msg.sender, msg.sender.balance); -} - -address public user; - -//deposit 1 coin to msg.sender -function depositOneCoin() payable public returns(bool success){ -return msg.sender.send(1); -} - -// function transferOneCoin() payable public returns(){ -// address(msg.sender).transfer(1); -// } - -// function depositOneCoin() payable public returns(address addr, uint amount, bool success){ -// return (msg.sender, msg.value, msg.sender.send(1)); -// } - -//deposit coin to msg.sender -function deposit(uint256 money) payable public returns(bool success){ -return msg.sender.send(money); -} -// function deposit(uint money) payable public returns(address addr, uint amount, bool success){ -// return (msg.sender, msg.value, msg.sender.send(money)); -// } - -// function () payable { -// msg.sender.send(1); -// } - -function sendToAddress(address _receiver) payable public{ -_receiver.transfer(msg.value); -} - -function sendToAddress2(address _receiver) payable public{ -_receiver.transfer(5); -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario013.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractScenario013.sol deleted file mode 100644 index b91085d018e..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario013.sol +++ /dev/null @@ -1,8 +0,0 @@ -//pragma solidity ^0.4.0; -contract timetest { - -function time() public{ -require(1 trx == 1000000 sun); - -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario014.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractScenario014.sol deleted file mode 100644 index 0e00a8f7f9b..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractScenario014.sol +++ /dev/null @@ -1,34 +0,0 @@ -//pragma solidity ^0.4.0; -contract Contract1 { - constructor() public payable{} - function send5SunToReceiver(address _receiver) payable public{ - _receiver.transfer(5); - } -} -contract contract2 { - address public payContract; - - constructor(address _add) payable public{ - payContract = _add; - } - - function triggerContract1(address _receiver) payable public{ - payContract.call(abi.encodeWithSignature("send5SunToReceiver(address)",_receiver)); - } - - function triggerContract1ButRevert(address _receiver) payable public{ - payContract.call(abi.encodeWithSignature("send5SunToReceiver(address)",_receiver)); - require(1 == 2); - } - -} -contract contract3 { - address public payContract; - constructor(address _add) payable public{ - payContract = _add; - } - - function triggerContract2(address _receiver) payable public{ - payContract.call(abi.encodeWithSignature("triggerContract1(address)",_receiver)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTest.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTest.sol deleted file mode 100644 index d6c5f34af2d..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTest.sol +++ /dev/null @@ -1,19 +0,0 @@ -//pragma solidity ^0.4.4; - -contract Test{ - -function a() returns (uint){ - -uint256 count = 0; - -for (uint256 i = 1; i > 0; i++) { - -count++; - -} - -return count; - -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractToMathedFeed.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractToMathedFeed.sol deleted file mode 100644 index 7cbfddfc657..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractToMathedFeed.sol +++ /dev/null @@ -1,19 +0,0 @@ -//pragma solidity ^0.4.0; - -contract ToMathedFeed { - uint public i=1; - function ToMathed(uint value) { - i=value; - } -} - -contract ToMathedUseINContract { - function ToMathedIUseNR(address a,uint256 n) returns(bool){ - address payContract=a; - return payContract.call(bytes4(keccak256("ToMathedNot(uint256)")),n); - } - function ToMathedIUseNRE(address a,uint256 value) returns(bool){ - address payContract=a; - return payContract.call(bytes4(keccak256("ToMathed(uint256)")),value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken001.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken001.sol deleted file mode 100644 index a7649149263..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken001.sol +++ /dev/null @@ -1,30 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken002.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken002.sol deleted file mode 100644 index a7649149263..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken002.sol +++ /dev/null @@ -1,30 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken003.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken003.sol deleted file mode 100644 index 924513518ea..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken003.sol +++ /dev/null @@ -1,16 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken005.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken005.sol deleted file mode 100644 index 924513518ea..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken005.sol +++ /dev/null @@ -1,16 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken011.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken011.sol deleted file mode 100644 index eee0510ccc3..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken011.sol +++ /dev/null @@ -1,35 +0,0 @@ -//pragma solidity ^0.4.24; -contract transferTokenContract { - constructor() payable public{} - function() payable public{} - function transferTokenTest(address toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - function() payable public{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken012.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken012.sol deleted file mode 100644 index 99bb82c48f2..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken012.sol +++ /dev/null @@ -1,26 +0,0 @@ -//pragma solidity ^0.4.24; -contract transferTokenContract { - constructor() payable public{} - function() payable public{} - function transferTokenTest(address toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken014.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken014.sol deleted file mode 100644 index ada9432a02e..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken014.sol +++ /dev/null @@ -1,34 +0,0 @@ -//pragma solidity ^0.4.24; -contract transferTokenContract { - constructor() payable public{} - function() payable public{} - function transferTokenTest(address toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - function() payable external{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken018.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken018.sol deleted file mode 100644 index 99bb82c48f2..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken018.sol +++ /dev/null @@ -1,26 +0,0 @@ -//pragma solidity ^0.4.24; -contract transferTokenContract { - constructor() payable public{} - function() payable public{} - function transferTokenTest(address toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken023.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken023.sol deleted file mode 100644 index 16551e2f177..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken023.sol +++ /dev/null @@ -1,26 +0,0 @@ -pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ - toAddress.transferToken(amount,id); - } - } - -contract B{ - uint256 public flag = 0; - constructor() public payable {} - function() public payable { - flag = 1; -} - -} -pragma solidity ^0.4.24; -contract C{ - uint256 public flag = 0; - constructor() public payable {} - function() public payable { - //flag = 1; -} - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken026.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken026.sol deleted file mode 100644 index a45d885bbb4..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken026.sol +++ /dev/null @@ -1,30 +0,0 @@ -pragma solidity ^0.4.24; - -contract token{ - constructor() payable public{} - function() payable public{} - function testInCall(address callBAddress,address callCAddress, address toAddress ,uint256 amount,trcToken id) payable public{ - callBAddress.call(bytes4(keccak256("transC(address,address,uint256,trcToken)")),callCAddress,toAddress,amount,id); - } - function testIndelegateCall(address callBddress,address callAddressC, address toAddress,uint256 amount, trcToken id) payable public{ - callBddress.delegatecall(bytes4(keccak256("transC(address,address,uint256,trcToken)")),callAddressC,toAddress,amount,id); - } - } - - - -contract B{ - constructor() public payable{} - function() public payable{} - function transC(address callCAddress,address toAddress,uint256 amount, trcToken id) payable public{ - callCAddress.call(bytes4(keccak256("trans(address,uint256,trcToken)")),toAddress,amount,id); - } -} -contract C{ - constructor() payable public{} - function() payable public{} - function trans(address toAddress,uint256 amount, trcToken id) payable public{ - toAddress.transferToken(amount,id); - } - -} diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken027.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken027.sol deleted file mode 100644 index a45d885bbb4..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken027.sol +++ /dev/null @@ -1,30 +0,0 @@ -pragma solidity ^0.4.24; - -contract token{ - constructor() payable public{} - function() payable public{} - function testInCall(address callBAddress,address callCAddress, address toAddress ,uint256 amount,trcToken id) payable public{ - callBAddress.call(bytes4(keccak256("transC(address,address,uint256,trcToken)")),callCAddress,toAddress,amount,id); - } - function testIndelegateCall(address callBddress,address callAddressC, address toAddress,uint256 amount, trcToken id) payable public{ - callBddress.delegatecall(bytes4(keccak256("transC(address,address,uint256,trcToken)")),callAddressC,toAddress,amount,id); - } - } - - - -contract B{ - constructor() public payable{} - function() public payable{} - function transC(address callCAddress,address toAddress,uint256 amount, trcToken id) payable public{ - callCAddress.call(bytes4(keccak256("trans(address,uint256,trcToken)")),toAddress,amount,id); - } -} -contract C{ - constructor() payable public{} - function() payable public{} - function trans(address toAddress,uint256 amount, trcToken id) payable public{ - toAddress.transferToken(amount,id); - } - -} diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken028.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken028.sol deleted file mode 100644 index 36dad7847a2..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken028.sol +++ /dev/null @@ -1,25 +0,0 @@ -pragma solidity ^0.4.24; - -contract token{ - uint256 public a=1; - constructor() public payable{} - function tokenBalanceWithSameName(trcToken id) public payable{ - B b= new B(); - a= b.tokenBalance(id); - } - function getA() public returns(uint256){ - return a; - } -} - - -contract B{ - uint256 public flag =0; - constructor() public payable{} - function() public payable{} - function tokenBalance(trcToken id) payable public returns(uint256){ - flag =9; - return flag; - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken029.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken029.sol deleted file mode 100644 index 93a79a6f774..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken029.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.4.24; - -contract token{ - address public a; - constructor() public payable{} - function transferTokenWithSameName(trcToken id,uint256 amount) public payable{ - B b= new B(); - b.transferToken(amount,id); - a= address(b); - } -} - - -contract B{ - uint256 public flag =0; - constructor() public payable{} - function() public payable{} - function transferToken(uint256 amount, trcToken id) payable public returns(bool){ - flag =9; - } - function getFlag() public view returns (uint256){ - return flag; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken030.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken030.sol deleted file mode 100644 index d82c6ab6928..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken030.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma solidity ^0.4.24; - - contract token{ - constructor() public payable{} - - // 4)suicide也会转移token - // 所有token,trx均被转移到toAddress, - // 若toAddress为合约地址本身,则所有token,trx均被烧掉进黑洞 - function kill(address toAddress) payable public{ - selfdestruct(toAddress); - } - - } - -contract B{ - constructor() public payable {} - function() public payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken031.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken031.sol deleted file mode 100644 index d82c6ab6928..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken031.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma solidity ^0.4.24; - - contract token{ - constructor() public payable{} - - // 4)suicide也会转移token - // 所有token,trx均被转移到toAddress, - // 若toAddress为合约地址本身,则所有token,trx均被烧掉进黑洞 - function kill(address toAddress) payable public{ - selfdestruct(toAddress); - } - - } - -contract B{ - constructor() public payable {} - function() public payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken034.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken034.sol deleted file mode 100644 index 03afab38850..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken034.sol +++ /dev/null @@ -1,23 +0,0 @@ -pragma solidity ^0.4.24; - - contract token{ - - // 2. 异常测试 - // 1)revert, 金额回退 - function failTransferTokenRevert(address toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - require(1==2); - } - - // 2)Error, 金额回退, fee limit 扣光 - function failTransferTokenError(address toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - assert(1==2); - } - - } - contract B{ - uint256 public flag = 0; - constructor() public payable {} - function() public payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken035.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken035.sol deleted file mode 100644 index 03afab38850..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken035.sol +++ /dev/null @@ -1,23 +0,0 @@ -pragma solidity ^0.4.24; - - contract token{ - - // 2. 异常测试 - // 1)revert, 金额回退 - function failTransferTokenRevert(address toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - require(1==2); - } - - // 2)Error, 金额回退, fee limit 扣光 - function failTransferTokenError(address toAddress,uint256 amount, trcToken id) public payable{ - toAddress.transferToken(amount,id); - assert(1==2); - } - - } - contract B{ - uint256 public flag = 0; - constructor() public payable {} - function() public payable {} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken036.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken036.sol deleted file mode 100644 index b9c81f8cd59..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken036.sol +++ /dev/null @@ -1,65 +0,0 @@ -pragma solidity ^0.4.24; -contract IllegalDecorate { -constructor() payable public{} -function() payable public{} -event log(uint256); -function transferTokenWithPure(address toAddress, uint256 tokenValue) public payable { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate1 { -constructor() payable public{} -function() payable public{} -event log(uint256); -function transferTokenWithConstant(address toAddress, uint256 tokenValue) public constant { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate2 { -constructor() payable public{} -function() payable public{} -event log(uint256); -function transferTokenWithView(address toAddress, uint256 tokenValue) public view { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate3 { -event log(uint256); -constructor() payable public{} -function() payable public{} -function transferTokenWithOutPayable(address toAddress, uint256 tokenValue) public { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} - -contract IllegalDecorate4 { -constructor() payable public{} -function() payable public{} -event log(uint256); -function transferTokenWithPure(address toAddress, uint256 tokenValue) public pure { -emit log(msg.value); -emit log(msg.tokenvalue); -emit log(msg.tokenid); -toAddress.transferToken(msg.tokenvalue, msg.tokenid); -toAddress.transfer(msg.value); -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken037.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken037.sol deleted file mode 100644 index ad19db9a3a6..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken037.sol +++ /dev/null @@ -1,23 +0,0 @@ -pragma solidity ^0.4.24; - -contract transferTrc10 { - function receive(address rec) public payable { - uint256 aamount=address(this).tokenBalance(msg.tokenid); - uint256 bamount=rec.tokenBalance(msg.tokenid); - require(msg.tokenvalue==aamount); - require(aamount==msg.tokenvalue); - rec.transferToken(aamount,msg.tokenid); - require(0==address(this).tokenBalance(msg.tokenid)); - require(bamount+aamount==rec.tokenBalance(msg.tokenid)); - require(rec.call(bytes4(keccak256("checkTrc10(uint256,trcToken,uint256)")),bamount+aamount,msg.tokenid,0)); - } -} - -contract receiveTrc10 { - function() public payable { - } - function checkTrc10(uint256 amount,trcToken tid,uint256 meamount) public{ - require(amount==address(this).tokenBalance(tid)); - require(meamount==msg.sender.tokenBalance(tid)); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken038.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken038.sol deleted file mode 100644 index 5b1a0babe8b..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken038.sol +++ /dev/null @@ -1,22 +0,0 @@ -pragma solidity ^0.4.24; - -contract transferTrc10 { - function receive(address rec) public payable { - uint256 aamount=address(this).tokenBalance(msg.tokenid); - uint256 bamount=rec.tokenBalance(msg.tokenid); - require(msg.tokenvalue==aamount); - require(aamount==msg.tokenvalue); - rec.transferToken(aamount,msg.tokenid); - require(rec.call(bytes4(keccak256("AssertError()")))); - require(aamount==address(this).tokenBalance(msg.tokenid)); - require(bamount==rec.tokenBalance(msg.tokenid)); - } -} - -contract receiveTrc10 { - function() public payable { - } - function AssertError() public{ - assert(1==2); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken039.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken039.sol deleted file mode 100644 index 7229e3aaa9a..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken039.sol +++ /dev/null @@ -1,44 +0,0 @@ -pragma solidity ^0.4.24; -/* - * 1. caller账户issue一个token - * 2. caller部署proxy, 传入1000 token,1000 trx - * 3. caller部署A - * 4. caller部署B - * 5. caller调用proxy中upgradetTo函数,传入A的地址 - * 6. caller调用proxy中不存在的trans(uint256,address,trcToken)函数,注意这时trcToken是无意义的,但也带上tokenid。address是任意另外某账户的地址 - * 7. 可以看到目标地址trx增长5,caller账户trx减少5 - * 8. caller调用proxy中upgradeTo函数,传入B的地址 - * 9. caller调用proxy中不存在的trans(uint256,address,trcToken)函数。 - * 10. 可以看到目标地址token增长5,caller账户token减少5 -*/ -contract Proxy { - constructor() payable public{} - address public implementation; - function upgradeTo(address _address) public { - implementation = _address; - } - function() payable public{ - address addr = implementation; - require(addr != address(0)); - assembly { - let freememstart := mload(0x40) - calldatacopy(freememstart, 0, calldatasize()) - let success := delegatecall(not(0), addr, freememstart, calldatasize(), freememstart, 0) - returndatacopy(freememstart, 0, returndatasize()) - switch success - case 0 { revert(freememstart, returndatasize()) } - default { return(freememstart, returndatasize()) } - } - } -} - -contract A { - function trans(uint256 amount, address toAddress, trcToken id) payable public { - toAddress.transfer(amount); - } -} -contract B{ - function trans(uint256 amount, address toAddress, trcToken id) payable public { - toAddress.transferToken(amount,id); - } -} diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken041.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken041.sol deleted file mode 100644 index f70ab112afe..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken041.sol +++ /dev/null @@ -1,20 +0,0 @@ -pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } - -contract B{ - uint256 public flag = 0; - constructor() public payable {} - function() public payable {} - - function setFlag() public payable{ - flag = 1; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken043.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken043.sol deleted file mode 100644 index eee0510ccc3..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken043.sol +++ /dev/null @@ -1,35 +0,0 @@ -//pragma solidity ^0.4.24; -contract transferTokenContract { - constructor() payable public{} - function() payable public{} - function transferTokenTest(address toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - function() payable public{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken048.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken048.sol deleted file mode 100644 index de2844608c0..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken048.sol +++ /dev/null @@ -1,14 +0,0 @@ -//pragma solidity ^0.4.24; - - contract Test { - event log(uint256); - function testMsgTokenValue() payable public returns(uint256 value) { - emit log(msg.tokenvalue); - return msg.tokenvalue; - } - - function testMsgValue() payable public returns(uint256 value) { - emit log(msg.value); - return msg.value; - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken049.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken049.sol deleted file mode 100644 index 25b31a4ffd6..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken049.sol +++ /dev/null @@ -1,10 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken050.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken050.sol deleted file mode 100644 index 25b31a4ffd6..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken050.sol +++ /dev/null @@ -1,10 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken051.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken051.sol deleted file mode 100644 index 25b31a4ffd6..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken051.sol +++ /dev/null @@ -1,10 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken052.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken052.sol deleted file mode 100644 index 25b31a4ffd6..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken052.sol +++ /dev/null @@ -1,10 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken054.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken054.sol deleted file mode 100644 index 924513518ea..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken054.sol +++ /dev/null @@ -1,16 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken055.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken055.sol deleted file mode 100644 index 924513518ea..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken055.sol +++ /dev/null @@ -1,16 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken060.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken060.sol deleted file mode 100644 index a7649149263..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken060.sol +++ /dev/null @@ -1,30 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken061.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken061.sol deleted file mode 100644 index a7649149263..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken061.sol +++ /dev/null @@ -1,30 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken064.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken064.sol deleted file mode 100644 index 0378fd90cc1..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken064.sol +++ /dev/null @@ -1,49 +0,0 @@ -//pragma solidity ^0.4.24; -contract transferTokenContract { - constructor() payable public{} - function() payable public{} - function transferTokenTest(address toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } - function transferTokenTestValueMaxBigInteger(address toAddress) payable public { - toAddress.transferToken(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0); - } - function transferTokenTestValueOverBigInteger(address toAddress) payable public { - toAddress.transferToken(9223372036854775808, 1000001); - } - function transferTokenTestValueMaxLong(address toAddress) payable public { - toAddress.transferToken(9223372036854775807, 1000001); - } - function transferTokenTestValue0IdBigInteger(address toAddress) payable public { - toAddress.transferToken(0, 9223372036854775809); - } -} - - - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - function() payable public{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken066.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken066.sol deleted file mode 100644 index eee0510ccc3..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken066.sol +++ /dev/null @@ -1,35 +0,0 @@ -//pragma solidity ^0.4.24; -contract transferTokenContract { - constructor() payable public{} - function() payable public{} - function transferTokenTest(address toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - function() payable public{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken067.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken067.sol deleted file mode 100644 index eee0510ccc3..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken067.sol +++ /dev/null @@ -1,35 +0,0 @@ -//pragma solidity ^0.4.24; -contract transferTokenContract { - constructor() payable public{} - function() payable public{} - function transferTokenTest(address toAddress, uint256 tokenValue, trcToken id) payable public { - toAddress.transferToken(tokenValue, id); - } - function transferTokenTestIDOverBigInteger(address toAddress) payable public { - toAddress.transferToken(1, 9223372036854775809); - } - function transferTokenTestValueRandomIdBigInteger(address toAddress) payable public { - toAddress.transferToken(1, 36893488147420103233); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ - trcToken id = msg.tokenid; - uint256 value = msg.tokenvalue; - return (id, value); - } - function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ - trcToken id = 1000001; - return accountAddress.tokenBalance(id); - } - function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ - return toAddress.tokenBalance(tokenId); - } -} - - -contract Result { - event log(uint256,uint256,uint256); - constructor() payable public{} - function() payable public{ - emit log(msg.tokenid,msg.tokenvalue,msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken073.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken073.sol deleted file mode 100644 index b5b6d149565..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken073.sol +++ /dev/null @@ -1,17 +0,0 @@ -//pragma solidity ^0.4.0; - -contract Dest { - event logFallback(uint256 indexed, uint256 indexed, uint256 indexed); - event logGetToken(uint256 indexed, uint256 indexed, uint256 indexed, uint256); - - - function Dest() payable public {} - - function getToken(trcToken tokenId) payable { - logGetToken(msg.sender.tokenBalance(tokenId), msg.tokenid, msg.tokenvalue, msg.value); - } - - function () payable { - logFallback(msg.tokenid, msg.tokenvalue, msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken075.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken075.sol deleted file mode 100644 index dfcaf8c2a52..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken075.sol +++ /dev/null @@ -1,26 +0,0 @@ -//pragma solidity ^0.4.0; - -contract Dest { - event logFallback(uint256 indexed, uint256 indexed, uint256 indexed); - event logGetToken(uint256 indexed, uint256 indexed, uint256 indexed, uint256); - - function Dest() payable public {} - - function getToken(trcToken tokenId) payable { - logGetToken(msg.sender.tokenBalance(tokenId), msg.tokenid, msg.tokenvalue, msg.value); - } - - function getTokenLongMin() payable { - // long.min - 1000020 - logGetToken(msg.sender.tokenBalance(trcToken(-9223372036855775828)), msg.tokenid, msg.tokenvalue, msg.value); - } - - function getTokenLongMax() payable { - // long.max + 1000020 - logGetToken(msg.sender.tokenBalance(trcToken(9223372036855775827)), msg.tokenid, msg.tokenvalue, msg.value); - } - - function () payable { - logFallback(msg.tokenid, msg.tokenvalue, msg.value); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken076.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken076.sol deleted file mode 100644 index 9de79a327c3..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken076.sol +++ /dev/null @@ -1,19 +0,0 @@ -//pragma solidity ^0.4.24; -contract Test { - address public origin; - address public sender; - bool public result1; - bool public result2; - function test() external { - origin = tx.origin; - sender = msg.sender; - result1 = msg.sender == tx.origin; // true - result2 = origin == sender; // true - } -function getResult1() public returns(bool){ - return result1; -} -function getResult2() public returns(bool){ - return result2; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken077.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken077.sol deleted file mode 100644 index e110f24e2fc..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken077.sol +++ /dev/null @@ -1,11 +0,0 @@ -//pragma solidity ^0.4.24; - -contract trcToken077 { -function addressTest() public returns(bytes32 addressValue) { - assembly{ - let x := mload(0x40) //Find empty storage location using "free memory pointer" - mstore(x,address) //Place current contract address - addressValue := mload(x) - } - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken078.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken078.sol deleted file mode 100644 index 4d51a365e14..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken078.sol +++ /dev/null @@ -1,35 +0,0 @@ -//pragma solidity ^0.4.24; -contract callerContract { - constructor() payable{} - function() payable{} - function sendToB(address called_address,address c) public payable{ - called_address.delegatecall(bytes4(keccak256("transferTo(address)")),c); - } - function sendToB2(address called_address,address c) public payable{ - called_address.call(bytes4(keccak256("transferTo(address)")),c); - } - function sendToB3(address called_address,address c) public payable{ - called_address.callcode(bytes4(keccak256("transferTo(address)")),c); - } -} - contract calledContract { - function() payable{} - constructor() payable {} - function transferTo(address toAddress)public payable{ - toAddress.transfer(5); - } - - function setIinC(address c) public payable{ - c.call.value(5)(bytes4(keccak256("setI()"))); - } - - } - contract c{ - address public origin; - address public sender; - constructor() public payable{} - event log(address,address); - function() payable public{ - emit log(tx.origin,msg.sender); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken079.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken079.sol deleted file mode 100644 index 924513518ea..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken079.sol +++ /dev/null @@ -1,16 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - constructor() public payable{} - // positive case - function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken080.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken080.sol deleted file mode 100644 index a7649149263..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcToken080.sol +++ /dev/null @@ -1,30 +0,0 @@ -//pragma solidity ^0.4.24; - - contract tokenTest{ - trcToken idCon = 0; - uint256 tokenValueCon=0; - uint256 callValueCon = 0; - - // positive case - function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ - //trcToken id = 0x74657374546f6b656e; - toAddress.transferToken(amount,id); - } - - function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ - trcToken id = msg.tokenid; - uint256 tokenValue = msg.tokenvalue; - uint256 callValue = msg.value; - return (id, tokenValue, callValue); - } - - constructor() public payable { - idCon = msg.tokenid; - tokenValueCon = msg.tokenvalue; - callValueCon = msg.value; - } - - function getResultInCon() public payable returns(trcToken, uint256, uint256) { - return (idCon, tokenValueCon, callValueCon); - } - } \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcTokenToOther.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractTrcTokenToOther.sol deleted file mode 100644 index e9ebd0ae865..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractTrcTokenToOther.sol +++ /dev/null @@ -1,44 +0,0 @@ -//pragma solidity ^0.4.24; - -contract ConvertType { - -constructor() payable public{} - -function() payable public{} - -// function trcTokenOnStorage(trcToken storage token) internal { // ERROR Storage location can only be given for array or struct types -// } - -function trcTokenToString(trcToken token) public constant returns(string r){ -// string s = token; // ERROR -// string s2 = string(token); // ERROR -} - -function trcTokenToUint256(trcToken token) public constant returns(uint256 r){ -uint256 u = token; // OK -uint256 u2 = uint256(token); // OK -r = u2; -} - -function trcTokenToAddress(trcToken token) public constant returns(address r){ -// address a = token; // ERROR -token = 0x1234567812345678123456781234567812345678123456781234567812345678; -address a2 = address(token); // OK -r = a2; -} - -function trcTokenToBytes(trcToken token) public constant returns(bytes r){ -// bytes b = token; // ERROR -// bytes b2 = bytes(token); // ERROR -} - -function trcTokenToBytes32(trcToken token) public constant returns(bytes32 r){ -// bytes32 b = token; // ERROR -bytes32 b2 = bytes32(token); // OK -r = b2; -} - -function trcTokenToArray(trcToken token) public constant returns(uint[] r){ -// uint[] a = token; // ERROR -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/contractUnknownException.sol b/framework/src/test/resources/soliditycode_v0.4.25/contractUnknownException.sol deleted file mode 100644 index be8af8f7451..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/contractUnknownException.sol +++ /dev/null @@ -1,65 +0,0 @@ - pragma solidity ^0.4.24; - -contract testA { - constructor() public payable { - A a = (new A).value(10)(); - a.fun(); - } -} - -contract testB { - constructor() public payable { - B b = (new B).value(10)(); - b.fun(); - } -} - - -contract testC { - constructor() public payable{ - C c = (new C).value(10)(); - c.fun(); - } -} - -contract testD { - constructor() public payable{ - D d = (new D).value(10)(); - d.fun(); - } -} - - -contract A { - constructor() public payable{ - selfdestruct(msg.sender); - } - function fun() { - } - -} - -contract B { - constructor() public payable { - revert(); - } - function fun() { - } -} - - -contract C { - constructor() public payable { - assert(1==2); - } - function fun() { - } -} - -contract D { - constructor() public payable { - require(1==2); - } - function fun() { - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest1TestRequireContract.sol b/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest1TestRequireContract.sol deleted file mode 100644 index a7c874ebd92..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest1TestRequireContract.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity ^0.4.0; -contract TestThrowsContract{ - function testAssert(){ - assert(1==2); - } - function testRequire(){ - require(2==1); - } - function testRevert(){ - revert(); - } - function testThrow(){ - throw; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest2TestThrowsContract.sol b/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest2TestThrowsContract.sol deleted file mode 100644 index a7c874ebd92..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest2TestThrowsContract.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity ^0.4.0; -contract TestThrowsContract{ - function testAssert(){ - assert(1==2); - } - function testRequire(){ - require(2==1); - } - function testRevert(){ - revert(); - } - function testThrow(){ - throw; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest3TestRevertContract.sol b/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest3TestRevertContract.sol deleted file mode 100644 index a7c874ebd92..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest3TestRevertContract.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity ^0.4.0; -contract TestThrowsContract{ - function testAssert(){ - assert(1==2); - } - function testRequire(){ - require(2==1); - } - function testRevert(){ - revert(); - } - function testThrow(){ - throw; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest4noPayableContract.sol b/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest4noPayableContract.sol deleted file mode 100644 index 59c15a1b1ab..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest4noPayableContract.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.4.0; - -contract noPayableContract { - -function noPayable() public returns (uint){ -return msg.value; -} -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest5noPayableConstructor.sol b/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest5noPayableConstructor.sol deleted file mode 100644 index c1138704b8b..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest5noPayableConstructor.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma solidity ^0.4.0; - -contract MyContract { - uint money; - - function MyContract(uint _money) { - require(msg.value >= _money); - money = _money; - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest6transferTestContract.sol b/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest6transferTestContract.sol deleted file mode 100644 index b0d93d238cf..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest6transferTestContract.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.4.0; - -contract transferTestContract { - function tranferTest(address addr) public payable{ - addr.transfer(10); - - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest7payableFallbakContract.sol b/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest7payableFallbakContract.sol deleted file mode 100644 index af290a06804..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest7payableFallbakContract.sol +++ /dev/null @@ -1,13 +0,0 @@ -pragma solidity ^0.4.0; - -contract Test { - function() { x = 1; } - uint x; -} - - -contract Caller { - function callTest(Test test) { - test.call(0xabcdef01); // hash does not exist - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest8newContractGasNoenough.sol b/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest8newContractGasNoenough.sol deleted file mode 100644 index 79066c2bfc8..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest8newContractGasNoenough.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma solidity ^0.4.0; - -contract Account{ - uint256 public accId; - - function Account(uint accountId) payable{ - accId = accountId; - } -} - -contract Initialize{ - // Account public account = new Account(10); - - function newAccount(){ - Account account = new Account(1); - } - -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest9MessageUsedErrorFeed.sol b/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest9MessageUsedErrorFeed.sol deleted file mode 100644 index f6187a6c3d1..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontest9MessageUsedErrorFeed.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma solidity ^0.4.0; - -contract MathedFeed { - - function divideMathed() public returns (uint ret) { - uint x=1; - uint y=0; - return x/y; - } -} - - -contract MathedUseContract { - - function MathedUse(address addr) public returns (uint) { - return MathedFeed(addr).divideMathed(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontestFunctionUsedErrorFeed.sol b/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontestFunctionUsedErrorFeed.sol deleted file mode 100644 index cc1e8c88306..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/requireExceptiontestFunctionUsedErrorFeed.sol +++ /dev/null @@ -1,17 +0,0 @@ -pragma solidity ^0.4.0; - -contract MessageFeed { - - function mValue() payable returns (uint ret) { - return msg.value; - } -} - -contract MessageUseContract { - function inputValue() payable returns (uint){ - return msg.value; - } - function messageUse(address addr) payable returns (uint) { - return MessageFeed(addr).mValue.value(1)(); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/soliditycode_v0.4.25/walletTestMutiSign004.sol b/framework/src/test/resources/soliditycode_v0.4.25/walletTestMutiSign004.sol deleted file mode 100644 index 7de52e9f155..00000000000 --- a/framework/src/test/resources/soliditycode_v0.4.25/walletTestMutiSign004.sol +++ /dev/null @@ -1,52 +0,0 @@ -//pragma solidity ^0.4.0; - -contract timeoutTest { - string public iarray1; - // cpu - function oneCpu() { - require(1==1); - } - - function storage8Char() { - iarray1 = "12345678"; - - } - - function testUseCpu(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - } - return count; - } - - - uint256[] public iarray; - uint public calculatedFibNumber; - mapping(address=>mapping(address=>uint256)) public m; - - function testUseStorage(uint256 a) public returns (uint256){ - uint256 count = 0; - for (uint256 i = 0; i < a; i++) { - count++; - iarray.push(i); - } - return count; - } - - // stack - uint n = 0; - function test() { - n += 1; - test(); - } - - function setFibonacci(uint n) public returns (uint256){ - calculatedFibNumber = fibonacci(n); - return calculatedFibNumber; - } - - function fibonacci(uint n) internal returns (uint) { - return fibonacci(n - 1) + fibonacci(n - 2); - } -} \ No newline at end of file diff --git a/framework/src/test/resources/testng.xml b/framework/src/test/resources/testng.xml deleted file mode 100644 index 6856338d3b8..00000000000 --- a/framework/src/test/resources/testng.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From acd2cb5a53a5c189e5609d5679e318b38720c78b Mon Sep 17 00:00:00 2001 From: yuekun Date: Wed, 21 Jun 2023 10:37:43 +0800 Subject: [PATCH 0819/1197] fix(freezeV2): optimize resource usage recovery logic --- .../org/tron/core/actuator/VMActuator.java | 16 ++-- .../org/tron/core/capsule/AccountCapsule.java | 61 ++++++++++++- .../org/tron/core/capsule/ReceiptCapsule.java | 8 ++ .../org/tron/core/db/ResourceProcessor.java | 91 +++++++++++++++++-- .../org/tron/core/db/TransactionTrace.java | 38 ++++++-- .../java/org/tron/core/config/Parameter.java | 1 + .../org/tron/core/EnergyProcessorTest.java | 57 ++++++++++++ .../UnDelegateResourceActuatorTest.java | 74 +++++++++++++++ .../tron/core/db/TransactionTraceTest.java | 65 +++++++++++++ protocol/src/main/protos/core/Tron.proto | 2 + 10 files changed, 389 insertions(+), 24 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index a32e81a33a4..326e2472757 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -4,6 +4,7 @@ import static java.lang.Math.min; import static org.apache.commons.lang3.ArrayUtils.getLength; import static org.apache.commons.lang3.ArrayUtils.isNotEmpty; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import com.google.protobuf.ByteString; import java.math.BigInteger; @@ -58,7 +59,6 @@ import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.contract.Common; import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; import org.tron.protos.contract.SmartContractOuterClass.SmartContract; import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; @@ -568,12 +568,13 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi energyProcessor.updateUsage(account); account.setLatestConsumeTimeForEnergy(now); receipt.setCallerEnergyUsage(account.getEnergyUsage()); - receipt.setCallerEnergyWindowSize(account.getWindowSize(Common.ResourceCode.ENERGY)); + receipt.setCallerEnergyWindowSize(account.getWindowSize(ENERGY)); + receipt.setCallerEnergyWindowSizeV2(account.getWindowSizeV2(ENERGY)); account.setEnergyUsage( - energyProcessor.increase(account, Common.ResourceCode.ENERGY, + energyProcessor.increase(account, ENERGY, account.getEnergyUsage(), min(leftFrozenEnergy, energyFromFeeLimit), now, now)); receipt.setCallerEnergyMergedUsage(account.getEnergyUsage()); - receipt.setCallerEnergyMergedWindowSize(account.getWindowSize(Common.ResourceCode.ENERGY)); + receipt.setCallerEnergyMergedWindowSize(account.getWindowSize(ENERGY)); rootRepository.updateAccount(account.createDbKey(), account); } return min(availableEnergy, energyFromFeeLimit); @@ -730,12 +731,13 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu energyProcessor.updateUsage(creator); creator.setLatestConsumeTimeForEnergy(now); receipt.setOriginEnergyUsage(creator.getEnergyUsage()); - receipt.setOriginEnergyWindowSize(creator.getWindowSize(Common.ResourceCode.ENERGY)); + receipt.setOriginEnergyWindowSize(creator.getWindowSize(ENERGY)); + receipt.setOriginEnergyWindowSizeV2(creator.getWindowSizeV2(ENERGY)); creator.setEnergyUsage( - energyProcessor.increase(creator, Common.ResourceCode.ENERGY, + energyProcessor.increase(creator, ENERGY, creator.getEnergyUsage(), creatorEnergyLimit, now, now)); receipt.setOriginEnergyMergedUsage(creator.getEnergyUsage()); - receipt.setOriginEnergyMergedWindowSize(creator.getWindowSize(Common.ResourceCode.ENERGY)); + receipt.setOriginEnergyMergedWindowSize(creator.getWindowSize(ENERGY)); rootRepository.updateAccount(creator.createDbKey(), creator); } return Math.addExact(callerEnergyLimit, creatorEnergyLimit); diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index 48593f5d36c..13f3cf576f1 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -42,8 +42,10 @@ import java.util.Map; import java.util.Objects; +import static java.lang.Math.ceil; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_MS; +import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_PRECISION; import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; @@ -1369,12 +1371,62 @@ public void setNewWindowSize(ResourceCode resourceCode, long newWindowSize) { public long getWindowSize(ResourceCode resourceCode) { long windowSize; + boolean windowOptimized; if (resourceCode == BANDWIDTH) { windowSize = this.account.getNetWindowSize(); + windowOptimized = this.account.getNetWindowOptimized(); } else { windowSize = this.account.getAccountResource().getEnergyWindowSize(); + windowOptimized = this.account.getAccountResource().getEnergyWindowOptimized(); + } + if (windowSize == 0) { + return WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL; + } + if (windowOptimized) { + return windowSize < WINDOW_SIZE_PRECISION ? WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL : + windowSize / WINDOW_SIZE_PRECISION; + } else { + return windowSize; + } + } + + public long getWindowSizeV2(ResourceCode resourceCode) { + long windowSize; + boolean windowOptimized; + if (resourceCode == BANDWIDTH) { + windowSize = this.account.getNetWindowSize(); + windowOptimized = this.account.getNetWindowOptimized(); + } else { + windowSize = this.account.getAccountResource().getEnergyWindowSize(); + windowOptimized = this.account.getAccountResource().getEnergyWindowOptimized(); + } + if (windowSize == 0) { + return WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL * WINDOW_SIZE_PRECISION; + } + if (windowOptimized) { + return windowSize; + } else { + return windowSize * WINDOW_SIZE_PRECISION; + } + } + + public boolean getWindowOptimized(ResourceCode resourceCode) { + boolean windowOptimized; + if (resourceCode == BANDWIDTH) { + windowOptimized = this.account.getNetWindowOptimized(); + } else { + windowOptimized = this.account.getAccountResource().getEnergyWindowOptimized(); + } + return windowOptimized; + } + + public void setWindowOptimized(ResourceCode resourceCode, boolean windowOptimized) { + if (resourceCode == BANDWIDTH) { + this.account = this.account.toBuilder().setNetWindowOptimized(windowOptimized).build(); + } else { + this.account = this.account.toBuilder().setAccountResource(this.account.getAccountResource() + .toBuilder().setEnergyWindowOptimized(windowOptimized).build()).build(); } - return windowSize == 0 ? WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL : windowSize; } public long getLastConsumeTime(ResourceCode resourceCode) { @@ -1393,4 +1445,11 @@ public long getFrozenV2BalanceWithDelegated(ResourceCode resourceCode) { } } + public void setNewWindowSizeV2( ResourceCode resourceCode, long newWindowSize) { + this.setNewWindowSize(resourceCode, newWindowSize); + if (!this.getWindowOptimized(resourceCode)) { + this.setWindowOptimized(resourceCode, true); + } + } + } diff --git a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index 2cef21e7617..7d003b6b0e4 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -69,6 +69,10 @@ public class ReceiptCapsule { @Setter private long callerEnergyWindowSize; + @Getter + @Setter + private long callerEnergyWindowSizeV2; + /** * Window size of caller after merging frozen energy */ @@ -83,6 +87,10 @@ public class ReceiptCapsule { @Setter private long originEnergyWindowSize; + @Getter + @Setter + private long originEnergyWindowSizeV2; + /** * Window size of origin after merging frozen energy */ diff --git a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java index 7603a25313a..87472b6212f 100644 --- a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java @@ -1,6 +1,9 @@ package org.tron.core.db; +import static java.lang.Math.ceil; +import static java.lang.Math.round; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; +import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_PRECISION; import org.tron.common.utils.Commons; import org.tron.core.capsule.AccountCapsule; @@ -59,13 +62,16 @@ protected long increase(long lastUsage, long usage, long lastTime, long now, lon } public long recovery(AccountCapsule accountCapsule, ResourceCode resourceCode, - long lastUsage, long lastTime, long now) { + long lastUsage, long lastTime, long now) { long oldWindowSize = accountCapsule.getWindowSize(resourceCode); return increase(lastUsage, 0, lastTime, now, oldWindowSize); } public long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, - long lastUsage, long usage, long lastTime, long now) { + long lastUsage, long usage, long lastTime, long now) { + if (dynamicPropertiesStore.supportAllowCancelAllUnfreezeV2()) { + return increaseV2(accountCapsule, resourceCode, lastUsage, usage, lastTime, now); + } long oldWindowSize = accountCapsule.getWindowSize(resourceCode); long averageLastUsage = divideCeil(lastUsage * this.precision, oldWindowSize); long averageUsage = divideCeil(usage * this.precision, this.windowSize); @@ -88,15 +94,50 @@ public long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, return newUsage; } long remainWindowSize = oldWindowSize - (now - lastTime); - long newWindowSize = (remainWindowSize * remainUsage + this.windowSize * usage) - / newUsage; + long newWindowSize = getNewWindowSize(remainUsage, remainWindowSize, usage, + windowSize, newUsage); accountCapsule.setNewWindowSize(resourceCode, newWindowSize); } return newUsage; } + public long increaseV2(AccountCapsule accountCapsule, ResourceCode resourceCode, + long lastUsage, long usage, long lastTime, long now) { + long oldWindowSizeV2 = accountCapsule.getWindowSizeV2(resourceCode); + long oldWindowSize = accountCapsule.getWindowSize(resourceCode); + long averageLastUsage = divideCeil(lastUsage * this.precision, oldWindowSize); + long averageUsage = divideCeil(usage * this.precision, this.windowSize); + + if (lastTime != now) { + if (lastTime + oldWindowSize > now) { + long delta = now - lastTime; + double decay = (oldWindowSize - delta) / (double) oldWindowSize; + averageLastUsage = Math.round(averageLastUsage * decay); + } else { + averageLastUsage = 0; + } + } + + long newUsage = getUsage(averageLastUsage, oldWindowSize, averageUsage, this.windowSize); + long remainUsage = getUsage(averageLastUsage, oldWindowSize); + if (remainUsage == 0) { + accountCapsule.setNewWindowSizeV2(resourceCode, this.windowSize * WINDOW_SIZE_PRECISION); + return newUsage; + } + + long remainWindowSize = oldWindowSizeV2 - (now - lastTime) * WINDOW_SIZE_PRECISION; + long newWindowSize = divideCeil( + remainUsage * remainWindowSize + usage * this.windowSize * WINDOW_SIZE_PRECISION, newUsage); + newWindowSize = Math.min(newWindowSize, this.windowSize * WINDOW_SIZE_PRECISION); + accountCapsule.setNewWindowSizeV2(resourceCode, newWindowSize); + return newUsage; + } + public long unDelegateIncrease(AccountCapsule owner, final AccountCapsule receiver, - long transferUsage, ResourceCode resourceCode, long now) { + long transferUsage, ResourceCode resourceCode, long now) { + if (dynamicPropertiesStore.supportAllowCancelAllUnfreezeV2()) { + return unDelegateIncreaseV2(owner, receiver, transferUsage, resourceCode, now); + } long lastOwnerTime = owner.getLastConsumeTime(resourceCode); long ownerUsage = owner.getUsage(resourceCode); // Update itself first @@ -110,17 +151,49 @@ public long unDelegateIncrease(AccountCapsule owner, final AccountCapsule receiv long newOwnerUsage = ownerUsage + transferUsage; // mean ownerUsage == 0 and transferUsage == 0 if (newOwnerUsage == 0) { - owner.setNewWindowSize(resourceCode, this.windowSize); + owner.setNewWindowSize(resourceCode, this.windowSize); return newOwnerUsage; } // calculate new windowSize - long newOwnerWindowSize = (ownerUsage * remainOwnerWindowSize + - transferUsage * remainReceiverWindowSize) - / newOwnerUsage; + long newOwnerWindowSize = getNewWindowSize(ownerUsage, remainOwnerWindowSize, transferUsage, + remainReceiverWindowSize, newOwnerUsage); owner.setNewWindowSize(resourceCode, newOwnerWindowSize); return newOwnerUsage; } + public long unDelegateIncreaseV2(AccountCapsule owner, final AccountCapsule receiver, + long transferUsage, ResourceCode resourceCode, long now) { + long lastOwnerTime = owner.getLastConsumeTime(resourceCode); + long ownerUsage = owner.getUsage(resourceCode); + // Update itself first + ownerUsage = increase(owner, resourceCode, ownerUsage, 0, lastOwnerTime, now); + long newOwnerUsage = ownerUsage + transferUsage; + // mean ownerUsage == 0 and transferUsage == 0 + if (newOwnerUsage == 0) { + owner.setNewWindowSizeV2(resourceCode, this.windowSize * WINDOW_SIZE_PRECISION); + return newOwnerUsage; + } + + long remainOwnerWindowSizeV2 = owner.getWindowSizeV2(resourceCode); + long remainReceiverWindowSizeV2 = receiver.getWindowSizeV2(resourceCode); + remainOwnerWindowSizeV2 = remainOwnerWindowSizeV2 < 0 ? 0 : remainOwnerWindowSizeV2; + remainReceiverWindowSizeV2 = remainReceiverWindowSizeV2 < 0 ? 0 : remainReceiverWindowSizeV2; + + // calculate new windowSize + long newOwnerWindowSize = + divideCeil( + ownerUsage * remainOwnerWindowSizeV2 + transferUsage * remainReceiverWindowSizeV2, + newOwnerUsage); + newOwnerWindowSize = Math.min(newOwnerWindowSize, this.windowSize * WINDOW_SIZE_PRECISION); + owner.setNewWindowSizeV2(resourceCode, newOwnerWindowSize); + return newOwnerUsage; + } + + private long getNewWindowSize(long lastUsage, long lastWindowSize, long usage, + long windowSize, long newUsage) { + return (lastUsage * lastWindowSize + usage * windowSize) / newUsage; + } + private long divideCeil(long numerator, long denominator) { return (numerator / denominator) + ((numerator % denominator) > 0 ? 1 : 0); } diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java index c239639f019..e9c4feb7e18 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java @@ -2,6 +2,8 @@ import static org.tron.common.runtime.InternalTransaction.TrxType.TRX_CONTRACT_CALL_TYPE; import static org.tron.common.runtime.InternalTransaction.TrxType.TRX_CONTRACT_CREATION_TYPE; +import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import java.util.Objects; import lombok.Getter; @@ -263,14 +265,16 @@ && getRuntimeResult().getException() == null && !getRuntimeResult().isRevert()) receipt.getOriginEnergyUsage(), receipt.getOriginEnergyWindowSize(), receipt.getOriginEnergyMergedUsage(), - receipt.getOriginEnergyMergedWindowSize()); + receipt.getOriginEnergyMergedWindowSize(), + receipt.getOriginEnergyWindowSizeV2()); } resetAccountUsage(caller, receipt.getCallerEnergyUsage(), receipt.getCallerEnergyWindowSize(), receipt.getCallerEnergyMergedUsage(), - receipt.getCallerEnergyMergedWindowSize()); + receipt.getCallerEnergyMergedWindowSize(), + receipt.getCallerEnergyWindowSizeV2()); } receipt.payEnergyBill( dynamicPropertiesStore, accountStore, forkController, @@ -282,8 +286,12 @@ && getRuntimeResult().getException() == null && !getRuntimeResult().isRevert()) } private void resetAccountUsage(AccountCapsule accountCap, - long usage, long size, long mergedUsage, long mergedSize) { - long currentSize = accountCap.getWindowSize(Common.ResourceCode.ENERGY); + long usage, long size, long mergedUsage, long mergedSize, long size2) { + if (dynamicPropertiesStore.supportAllowCancelAllUnfreezeV2()) { + resetAccountUsageV2(accountCap, usage, size, mergedUsage, mergedSize, size2); + return; + } + long currentSize = accountCap.getWindowSize(ENERGY); long currentUsage = accountCap.getEnergyUsage(); // Drop the pre consumed frozen energy long newArea = currentUsage * currentSize @@ -294,8 +302,24 @@ private void resetAccountUsage(AccountCapsule accountCap, long newUsage = Long.max(0, newArea / newSize); // Reset account usage and window size accountCap.setEnergyUsage(newUsage); - accountCap.setNewWindowSize(Common.ResourceCode.ENERGY, - newUsage == 0 ? 0L : newSize); + accountCap.setNewWindowSize(ENERGY, newUsage == 0 ? 0L : newSize); + } + + private void resetAccountUsageV2(AccountCapsule accountCap, + long usage, long size, long mergedUsage, long mergedSize, long size2) { + long currentSize = accountCap.getWindowSize(ENERGY); + long currentSize2 = accountCap.getWindowSizeV2(ENERGY); + long currentUsage = accountCap.getEnergyUsage(); + // Drop the pre consumed frozen energy + long newArea = currentUsage * currentSize - (mergedUsage * mergedSize - usage * size); + // If area merging happened during suicide, use the current window size + long newSize = mergedSize == currentSize ? size : currentSize; + long newSize2 = mergedSize == currentSize ? size2 : currentSize2; + // Calc new usage by fixed x-axes + long newUsage = Long.max(0, newArea / newSize); + // Reset account usage and window size + accountCap.setEnergyUsage(newUsage); + accountCap.setNewWindowSizeV2(ENERGY, newUsage == 0 ? 0L : newSize2); } public boolean checkNeedRetry() { @@ -354,7 +378,7 @@ public void deleteContract(byte[] address) { public static byte[] convertToTronAddress(byte[] address) { if (address.length == 20) { byte[] newAddress = new byte[21]; - byte[] temp = new byte[]{DecodeUtil.addressPreFixByte}; + byte[] temp = new byte[] {DecodeUtil.addressPreFixByte}; System.arraycopy(temp, 0, newAddress, 0, temp.length); System.arraycopy(address, 0, newAddress, temp.length, address.length); address = newAddress; diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index 5a170577b99..6bbc66846bd 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -76,6 +76,7 @@ public class ChainConstant { public static final long DELEGATE_PERIOD = 3 * 86_400_000L; public static final long TRX_PRECISION = 1000_000L; public static final long DELEGATE_COST_BASE_SIZE = 275L; + public static final long WINDOW_SIZE_PRECISION = 1000L; } public class NodeConstant { diff --git a/framework/src/test/java/org/tron/core/EnergyProcessorTest.java b/framework/src/test/java/org/tron/core/EnergyProcessorTest.java index f4311930bb2..da0493e2026 100755 --- a/framework/src/test/java/org/tron/core/EnergyProcessorTest.java +++ b/framework/src/test/java/org/tron/core/EnergyProcessorTest.java @@ -14,6 +14,7 @@ import org.tron.core.db.EnergyProcessor; import org.tron.protos.Protocol.AccountType; import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; +import org.tron.protos.contract.Common; @Slf4j public class EnergyProcessorTest extends BaseTest { @@ -97,7 +98,63 @@ public void testUseContractCreatorEnergy() throws Exception { Assert.assertEquals(1526647838000L, ownerCapsuleNew.getAccountResource().getLatestConsumeTimeForEnergy()); Assert.assertEquals(10000L, ownerCapsuleNew.getAccountResource().getEnergyUsage()); + } + @Test + public void testUseEnergyInWindowSizeV2() throws Exception { + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(10000L); + dbManager.getDynamicPropertiesStore().saveTotalEnergyWeight(2849288700L); + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(14); + + AccountCapsule ownerCapsule = + dbManager.getAccountStore().get(ByteArray.fromHexString(CONTRACT_PROVIDER_ADDRESS)); + ownerCapsule.setNewWindowSize(Common.ResourceCode.ENERGY, 300); + ownerCapsule.setWindowOptimized(Common.ResourceCode.ENERGY, false); + ownerCapsule.setLatestConsumeTimeForEnergy(9999L); + ownerCapsule.setEnergyUsage(70021176L); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + + EnergyProcessor processor = + new EnergyProcessor(dbManager.getDynamicPropertiesStore(), dbManager.getAccountStore()); + long energy = 2345L; + long now = 9999L; + for (int i = 0; i < 1000; i++) { + processor.useEnergy(ownerCapsule, energy, now); + } + processor.useEnergy(ownerCapsule, energy, now); + Assert.assertEquals(72368521, ownerCapsule.getEnergyUsage()); + Assert.assertEquals(300, ownerCapsule.getWindowSize(Common.ResourceCode.ENERGY)); + Assert.assertFalse(ownerCapsule.getWindowOptimized(Common.ResourceCode.ENERGY)); + + dbManager.getDynamicPropertiesStore().saveAllowCancelAllUnfreezeV2(1); + ownerCapsule.setNewWindowSize(Common.ResourceCode.ENERGY, 300); + ownerCapsule.setWindowOptimized(Common.ResourceCode.ENERGY, false); + ownerCapsule.setLatestConsumeTimeForEnergy(9999L); + ownerCapsule.setEnergyUsage(70021176L); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + + for (int i = 0; i < 1000; i++) { + processor.useEnergy(ownerCapsule, energy, now); + } + processor.useEnergy(ownerCapsule, energy, now); + + Assert.assertEquals(72368521L, ownerCapsule.getEnergyUsage()); + Assert.assertEquals(1224, ownerCapsule.getWindowSize(Common.ResourceCode.ENERGY)); + Assert.assertEquals(1224919, ownerCapsule.getWindowSizeV2(Common.ResourceCode.ENERGY)); + Assert.assertTrue(ownerCapsule.getWindowOptimized(Common.ResourceCode.ENERGY)); + + ownerCapsule.setNewWindowSize(Common.ResourceCode.ENERGY, 300); + ownerCapsule.setWindowOptimized(Common.ResourceCode.ENERGY, false); + ownerCapsule.setLatestConsumeTimeForEnergy(9999L); + ownerCapsule.setEnergyUsage(70021176L); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + for (int i = 0; i < 1000; i++) { + processor.useEnergy(ownerCapsule, energy, now); + now++; + } + Assert.assertEquals(15844971L, ownerCapsule.getEnergyUsage()); + Assert.assertEquals(2086, ownerCapsule.getWindowSize(Common.ResourceCode.ENERGY)); + Assert.assertEquals(2086556, ownerCapsule.getWindowSizeV2(Common.ResourceCode.ENERGY)); } @Test diff --git a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java index e825364be39..82ed6865fb8 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java @@ -368,6 +368,80 @@ public void testLockedAndUnlockUnDelegateForBandwidth() { } } + + @Test + public void testLockedAndUnlockUnDelegateForBandwidthUsingWindowSizeV2() { + delegateLockedBandwidthForOwner(Long.MAX_VALUE); + delegateBandwidthForOwner(); + dbManager.getDynamicPropertiesStore().saveAllowCancelAllUnfreezeV2(1); + + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + byte[] receiver = ByteArray.fromHexString(RECEIVER_ADDRESS); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiver); + receiverCapsule.setNetUsage(1_000_000_000); + long nowSlot = dbManager.getChainBaseManager().getHeadSlot(); + receiverCapsule.setLatestConsumeTime(nowSlot - 14400); + dbManager.getAccountStore().put(receiver, receiverCapsule); + AccountCapsule ownerCapsule = dbManager.getAccountStore().get(owner); + ownerCapsule.setNetUsage(1_000_000_000); + ownerCapsule.setLatestConsumeTime(nowSlot - 14400); + dbManager.getAccountStore().put(owner, ownerCapsule); + + UnDelegateResourceActuator actuator = new UnDelegateResourceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegatedContractForBandwidth(OWNER_ADDRESS, delegateBalance)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(2 * delegateBalance, + receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(2 * delegateBalance, + ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(0, ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(2 * delegateBalance, ownerCapsule.getTronPower()); + Assert.assertEquals(1_000_000_000, ownerCapsule.getNetUsage()); + Assert.assertEquals(1_000_000_000, receiverCapsule.getNetUsage()); + DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule.createDbKeyV2(owner, receiver, false)); + DelegatedResourceCapsule lockedResourceCapsule = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule.createDbKeyV2(owner, receiver, true)); + Assert.assertNotNull(delegatedResourceCapsule); + Assert.assertNotNull(lockedResourceCapsule); + + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); + + // check DelegatedResource + DelegatedResourceCapsule delegatedResourceCapsule1 = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule.createDbKeyV2(owner, receiver, false)); + DelegatedResourceCapsule lockedResourceCapsule1 = dbManager.getDelegatedResourceStore() + .get(DelegatedResourceCapsule.createDbKeyV2(owner, receiver, true)); + Assert.assertNull(delegatedResourceCapsule1); + Assert.assertNotNull(lockedResourceCapsule1); + // check owner + ownerCapsule = dbManager.getAccountStore().get(owner); + Assert.assertEquals(1000000000, ownerCapsule.getDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(delegateBalance, ownerCapsule.getFrozenV2BalanceForBandwidth()); + Assert.assertEquals(2 * delegateBalance, ownerCapsule.getTronPower()); + Assert.assertEquals(750000000, ownerCapsule.getNetUsage()); + Assert.assertEquals(nowSlot, ownerCapsule.getLatestConsumeTime()); + + // check receiver + receiverCapsule = dbManager.getAccountStore().get(receiver); + Assert.assertEquals(1000000000, + receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth()); + Assert.assertEquals(250000000, receiverCapsule.getNetUsage()); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(e.getMessage()); + } + dbManager.getDynamicPropertiesStore().saveAllowCancelAllUnfreezeV2(0); + } + @Test public void testLockedUnDelegateBalanceForBandwidthInsufficient() { delegateLockedBandwidthForOwner(Long.MAX_VALUE); diff --git a/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java b/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java index 94da7dc27c4..3e02032dac0 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java @@ -383,4 +383,69 @@ public void testPay() throws BalanceInsufficientException { transactionTrace.pay(); AccountCapsule accountCapsule1 = dbManager.getAccountStore().get(ownerAddress.toByteArray()); } + + + @Test + public void testTriggerUseUsageInWindowSizeV2() throws VMIllegalException, ContractExeException, + ContractValidateException, BalanceInsufficientException { + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(14); + dbManager.getDynamicPropertiesStore().saveAllowCancelAllUnfreezeV2(1); + + String contractName = "tracetestContract"; + String code = "608060405234801561001057600080fd5b5060005b6103e88110156100375760008181526020819" + + "05260409020819055600a01610014565b5061010f806100476000396000f300608060405260043610605257" + + "63ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634903b" + + "0d181146057578063da31158814607e578063fe4ba936146093575b600080fd5b348015606257600080fd5b" + + "50606c60043560ad565b60408051918252519081900360200190f35b348015608957600080fd5b50606c600" + + "43560bf565b348015609e57600080fd5b5060ab60043560243560d1565b005b600060208190529081526040" + + "90205481565b60009081526020819052604090205490565b600091825260208290526040909120555600a16" + + "5627a7a723058200596e6c0a5371c2c533eb97ba4c1c19b0521750a5624cb5d2e93249c8b7219d20029"; + String abi = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":" + + "\"balances\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"st" + + "ateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name" + + "\":\"account\",\"type\":\"uint256\"}],\"name\":\"getCoin\",\"outputs\":[{\"name\":\"\"" + + ",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"func" + + "tion\"},{\"constant\":false,\"inputs\":[{\"name\":\"receiver\",\"type\":\"uint256\"},{" + + "\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"setCoin\",\"outputs\":[],\"payab" + + "le\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"" + + "payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]"; + CreateSmartContract smartContract = TvmTestUtils.createSmartContract( + Commons.decodeFromBase58Check(OwnerAddress), contractName, abi, code, 0, + 100); + Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( + Contract.newBuilder().setParameter(Any.pack(smartContract)) + .setType(ContractType.CreateSmartContract)).setFeeLimit(1000000000) + .setTimestamp(System.currentTimeMillis())) + .build(); + + byte[] contractAddress = deployInit(transaction); + AccountCapsule accountCapsule = new AccountCapsule(ByteString.copyFrom("owner".getBytes()), + ByteString.copyFrom(Commons.decodeFromBase58Check(TriggerOwnerAddress)), + AccountType.Normal, + totalBalance); + + accountCapsule.setFrozenForEnergy(10_000_000L, 0L); + dbManager.getAccountStore() + .put(Commons.decodeFromBase58Check(TriggerOwnerAddress), accountCapsule); + TriggerSmartContract triggerContract = TvmTestUtils.createTriggerContract(contractAddress, + "setCoin(uint256,uint256)", "133,133", false, + 0, Commons.decodeFromBase58Check(TriggerOwnerAddress)); + Transaction transaction2 = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( + Contract.newBuilder().setParameter(Any.pack(triggerContract)) + .setType(ContractType.TriggerSmartContract)).setFeeLimit(1000000000L)).build(); + TransactionCapsule transactionCapsule = new TransactionCapsule(transaction2); + TransactionTrace trace = new TransactionTrace(transactionCapsule, StoreFactory + .getInstance(), new RuntimeImpl()); + trace.init(null); + trace.exec(); + trace.pay(); + Assert.assertEquals(0, trace.getReceipt().getEnergyUsage()); + Assert.assertEquals(2025200, trace.getReceipt().getEnergyFee()); + accountCapsule = dbManager.getAccountStore().get(accountCapsule.getAddress().toByteArray()); + Assert.assertEquals(totalBalance, + accountCapsule.getBalance() + trace.getReceipt().getEnergyFee()); + + dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(0); + dbManager.getDynamicPropertiesStore().saveAllowCancelAllUnfreezeV2(0); + } } diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 05f8b990cb7..aa6a96ba1b3 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -193,6 +193,7 @@ message Account { bytes account_id = 23; int64 net_window_size = 24; + bool net_window_optimized = 25; message AccountResource { // energy resource, get from frozen @@ -215,6 +216,7 @@ message Account { int64 delegated_frozenV2_balance_for_energy = 10; int64 acquired_delegated_frozenV2_balance_for_energy = 11; + bool energy_window_optimized = 12; } AccountResource account_resource = 26; bytes codeHash = 30; From 199d4735cb3dcc6e5d533201753fa2efd7f85ff6 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Mon, 26 Jun 2023 11:51:39 +0800 Subject: [PATCH 0820/1197] fix(freezeV2): optimize unit test format --- .../tron/core/db/TransactionTraceTest.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java b/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java index 3e02032dac0..553eb46a725 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java @@ -393,28 +393,28 @@ public void testTriggerUseUsageInWindowSizeV2() throws VMIllegalException, Contr String contractName = "tracetestContract"; String code = "608060405234801561001057600080fd5b5060005b6103e88110156100375760008181526020819" - + "05260409020819055600a01610014565b5061010f806100476000396000f300608060405260043610605257" - + "63ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634903b" - + "0d181146057578063da31158814607e578063fe4ba936146093575b600080fd5b348015606257600080fd5b" - + "50606c60043560ad565b60408051918252519081900360200190f35b348015608957600080fd5b50606c600" - + "43560bf565b348015609e57600080fd5b5060ab60043560243560d1565b005b600060208190529081526040" - + "90205481565b60009081526020819052604090205490565b600091825260208290526040909120555600a16" - + "5627a7a723058200596e6c0a5371c2c533eb97ba4c1c19b0521750a5624cb5d2e93249c8b7219d20029"; + + "05260409020819055600a01610014565b5061010f806100476000396000f300608060405260043610605257" + + "63ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634903b" + + "0d181146057578063da31158814607e578063fe4ba936146093575b600080fd5b348015606257600080fd5b" + + "50606c60043560ad565b60408051918252519081900360200190f35b348015608957600080fd5b50606c600" + + "43560bf565b348015609e57600080fd5b5060ab60043560243560d1565b005b600060208190529081526040" + + "90205481565b60009081526020819052604090205490565b600091825260208290526040909120555600a16" + + "5627a7a723058200596e6c0a5371c2c533eb97ba4c1c19b0521750a5624cb5d2e93249c8b7219d20029"; String abi = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":" - + "\"balances\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"st" - + "ateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name" - + "\":\"account\",\"type\":\"uint256\"}],\"name\":\"getCoin\",\"outputs\":[{\"name\":\"\"" - + ",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"func" - + "tion\"},{\"constant\":false,\"inputs\":[{\"name\":\"receiver\",\"type\":\"uint256\"},{" - + "\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"setCoin\",\"outputs\":[],\"payab" - + "le\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"" - + "payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]"; + + "\"balances\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"st" + + "ateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name" + + "\":\"account\",\"type\":\"uint256\"}],\"name\":\"getCoin\",\"outputs\":[{\"name\":\"\"" + + ",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"func" + + "tion\"},{\"constant\":false,\"inputs\":[{\"name\":\"receiver\",\"type\":\"uint256\"},{" + + "\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"setCoin\",\"outputs\":[],\"payab" + + "le\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"" + + "payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]"; CreateSmartContract smartContract = TvmTestUtils.createSmartContract( Commons.decodeFromBase58Check(OwnerAddress), contractName, abi, code, 0, 100); Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( - Contract.newBuilder().setParameter(Any.pack(smartContract)) - .setType(ContractType.CreateSmartContract)).setFeeLimit(1000000000) + Contract.newBuilder().setParameter(Any.pack(smartContract)) + .setType(ContractType.CreateSmartContract)).setFeeLimit(1000000000) .setTimestamp(System.currentTimeMillis())) .build(); From 5c9ca49c8a745b82c2e5e799dfbd1b86437278db Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 26 Jun 2023 17:09:06 +0800 Subject: [PATCH 0821/1197] feat(monitor): Optimize http interface monitoring --- .../core/services/filter/HttpInterceptor.java | 34 +++++++------------ 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java index 51b4d60f856..d912e42aee9 100644 --- a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java +++ b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java @@ -38,30 +38,20 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha HttpServletResponse resp = (HttpServletResponse) response; - if (resp.getStatus() != HTTP_NOT_FOUND) { // correct endpoint - String endpointQPS = MetricsKey.NET_API_DETAIL_QPS + endpoint; - MetricsUtil.meterMark(MetricsKey.NET_API_QPS); - MetricsUtil.meterMark(endpointQPS); - - int reposeContentSize = responseWrapper.getByteSize(); - String endpointOutTraffic = MetricsKey.NET_API_DETAIL_OUT_TRAFFIC + endpoint; - MetricsUtil.meterMark(MetricsKey.NET_API_OUT_TRAFFIC, - reposeContentSize); - MetricsUtil.meterMark(endpointOutTraffic, reposeContentSize); - - if (resp.getStatus() != HTTP_SUCCESS) { //http fail - String endpointFailQPS = MetricsKey.NET_API_DETAIL_FAIL_QPS + endpoint; - MetricsUtil.meterMark(MetricsKey.NET_API_FAIL_QPS); - MetricsUtil.meterMark(endpointFailQPS); - } - } else { // wrong endpoint - MetricsUtil.meterMark(MetricsKey.NET_API_QPS); + int size = responseWrapper.getByteSize(); + MetricsUtil.meterMark(MetricsKey.NET_API_OUT_TRAFFIC, size); + MetricsUtil.meterMark(MetricsKey.NET_API_QPS); + + if (resp.getStatus() == HTTP_SUCCESS) { + MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_OUT_TRAFFIC + endpoint, size); + MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_QPS + endpoint); + Metrics.histogramObserve(MetricKeys.Histogram.HTTP_BYTES, + responseWrapper.getByteSize(), + Strings.isNullOrEmpty(endpoint) ? MetricLabels.UNDEFINED : endpoint, + String.valueOf(responseWrapper.getStatus())); + } else { MetricsUtil.meterMark(MetricsKey.NET_API_FAIL_QPS); } - Metrics.histogramObserve(MetricKeys.Histogram.HTTP_BYTES, - responseWrapper.getByteSize(), - Strings.isNullOrEmpty(endpoint) ? MetricLabels.UNDEFINED : endpoint, - String.valueOf(responseWrapper.getStatus())); } else { chain.doFilter(request, response); } From a9d968a6ff72429ec096cc4f5c9a324ef3b145b5 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 29 Jun 2023 15:01:49 +0800 Subject: [PATCH 0822/1197] feat(net):update libp2p version to v1.2.0 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index a184cab4b74..0ed13763a1e 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'io.github.tronprotocol', name: 'libp2p', version: '2.0.0',{ + compile group: 'io.github.tronprotocol', name: 'libp2p', version: '1.2.0',{ exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' From aad0df3cd230b4c1cc2224368e428f72e0f803d8 Mon Sep 17 00:00:00 2001 From: forfreeday Date: Sat, 1 Jul 2023 12:48:17 +0800 Subject: [PATCH 0823/1197] update a new version. version name:GreatVoyage-v4.7.1.1-343-g959e0199de,version code:18031 --- framework/src/main/java/org/tron/program/Version.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 20ceb88f708..b0837871d5d 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,8 +2,8 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.7.1-11-ge5e347de7"; - public static final String VERSION_CODE = "17686"; + public static final String VERSION_NAME = "GreatVoyage-v4.7.1.1-343-g959e0199de"; + public static final String VERSION_CODE = "18031"; private static final String VERSION = "4.7.2"; public static String getVersion() { From 6ed9db403bc6d49ba5a4b2048177ed133b5fe60a Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 3 Jul 2023 16:16:07 +0800 Subject: [PATCH 0824/1197] feat(test): optimize NodeInfoServiceTest --- .../core/services/NodeInfoServiceTest.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java b/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java index d442a5826f7..848014a27d3 100644 --- a/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java @@ -1,10 +1,14 @@ package org.tron.core.services; +import static org.mockito.Mockito.mock; + import com.alibaba.fastjson.JSON; import com.google.protobuf.ByteString; import io.grpc.ManagedChannelBuilder; +import java.net.InetSocketAddress; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; +import org.mockito.Mockito; import org.tron.api.GrpcAPI.EmptyMessage; import org.tron.api.WalletGrpc; import org.tron.api.WalletGrpc.WalletBlockingStub; @@ -13,6 +17,9 @@ import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.client.Configuration; import org.tron.core.capsule.BlockCapsule; +import org.tron.core.net.P2pEventHandlerImpl; +import org.tron.core.net.peer.PeerManager; +import org.tron.p2p.connection.Channel; import org.tron.program.Version; @@ -21,12 +28,14 @@ public class NodeInfoServiceTest { private NodeInfoService nodeInfoService; private WitnessProductBlockService witnessProductBlockService; + private P2pEventHandlerImpl p2pEventHandler; private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") .get(0); public NodeInfoServiceTest(TronApplicationContext context) { nodeInfoService = context.getBean("nodeInfoService", NodeInfoService.class); witnessProductBlockService = context.getBean(WitnessProductBlockService.class); + p2pEventHandler = context.getBean(P2pEventHandlerImpl.class); } public void test() { @@ -36,6 +45,16 @@ public void test() { 200, ByteString.EMPTY); witnessProductBlockService.validWitnessProductTwoBlock(blockCapsule1); witnessProductBlockService.validWitnessProductTwoBlock(blockCapsule2); + + //add peer + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); + Channel c1 = mock(Channel.class); + Mockito.when(c1.getInetSocketAddress()).thenReturn(a1); + Mockito.when(c1.getInetAddress()).thenReturn(a1.getAddress()); + p2pEventHandler.onConnect(c1); + Assert.assertEquals(1, PeerManager.getPeers().size()); + + //test setConnectInfo NodeInfo nodeInfo = nodeInfoService.getNodeInfo(); Assert.assertEquals(nodeInfo.getConfigNodeInfo().getCodeVersion(), Version.getVersion()); Assert.assertEquals(nodeInfo.getCheatWitnessInfoMap().size(), 1); From e1b9a0b9d7310f057275e1022c97be67405cba61 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 3 Jul 2023 16:33:12 +0800 Subject: [PATCH 0825/1197] feat(monitor): remove unused filed --- .../main/java/org/tron/core/services/filter/HttpInterceptor.java | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java index d912e42aee9..5f0ef8bb20c 100644 --- a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java +++ b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java @@ -19,7 +19,6 @@ public class HttpInterceptor implements Filter { private String endpoint; - private final int HTTP_NOT_FOUND = 404; private final int HTTP_SUCCESS = 200; @Override From 0b67b1a3262bd86f1309447300d090d4f90c9291 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 3 Jul 2023 16:47:55 +0800 Subject: [PATCH 0826/1197] feat(test):optimize NodeInfoServiceTest --- .../test/java/org/tron/core/services/NodeInfoServiceTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java b/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java index 848014a27d3..19d0540e5e6 100644 --- a/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java @@ -52,7 +52,6 @@ public void test() { Mockito.when(c1.getInetSocketAddress()).thenReturn(a1); Mockito.when(c1.getInetAddress()).thenReturn(a1.getAddress()); p2pEventHandler.onConnect(c1); - Assert.assertEquals(1, PeerManager.getPeers().size()); //test setConnectInfo NodeInfo nodeInfo = nodeInfoService.getNodeInfo(); From 1a665224a70763c6616cc5f74ddf0e6e358b211b Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 4 Jul 2023 11:35:13 +0800 Subject: [PATCH 0827/1197] feat(monitor): optimize http interface monitor --- .../java/org/tron/core/services/filter/HttpInterceptor.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java index 5f0ef8bb20c..b67637f4558 100644 --- a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java +++ b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java @@ -45,11 +45,11 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_OUT_TRAFFIC + endpoint, size); MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_QPS + endpoint); Metrics.histogramObserve(MetricKeys.Histogram.HTTP_BYTES, - responseWrapper.getByteSize(), - Strings.isNullOrEmpty(endpoint) ? MetricLabels.UNDEFINED : endpoint, - String.valueOf(responseWrapper.getStatus())); + size, endpoint, String.valueOf(responseWrapper.getStatus())); } else { MetricsUtil.meterMark(MetricsKey.NET_API_FAIL_QPS); + Metrics.histogramObserve(MetricKeys.Histogram.HTTP_BYTES, + size, MetricLabels.UNDEFINED, String.valueOf(responseWrapper.getStatus())); } } else { chain.doFilter(request, response); From c43370a06fa55991c8433007c054dc6e9c854b67 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 4 Jul 2023 14:20:06 +0800 Subject: [PATCH 0828/1197] feat(monitor): optimize monitoring logic for different http code --- .../core/services/filter/HttpInterceptor.java | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java index b67637f4558..9116df377f7 100644 --- a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java +++ b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java @@ -20,6 +20,8 @@ public class HttpInterceptor implements Filter { private String endpoint; private final int HTTP_SUCCESS = 200; + private final int HTTP_BAD_REQUEST = 400; + private final int HTTP_NOT_ACCEPTABLE = 406; @Override public void init(FilterConfig filterConfig) { @@ -36,44 +38,44 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha chain.doFilter(request, responseWrapper); HttpServletResponse resp = (HttpServletResponse) response; - int size = responseWrapper.getByteSize(); + MetricsUtil.meterMark(MetricsKey.NET_API_OUT_TRAFFIC, size); MetricsUtil.meterMark(MetricsKey.NET_API_QPS); + if (resp.getStatus() >= HTTP_BAD_REQUEST && resp.getStatus() <= HTTP_NOT_ACCEPTABLE) { + MetricsUtil.meterMark(MetricsKey.NET_API_FAIL_QPS); + Metrics.histogramObserve(MetricKeys.Histogram.HTTP_BYTES, + size, MetricLabels.UNDEFINED, String.valueOf(responseWrapper.getStatus())); + return; + } + if (resp.getStatus() == HTTP_SUCCESS) { - MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_OUT_TRAFFIC + endpoint, size); MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_QPS + endpoint); - Metrics.histogramObserve(MetricKeys.Histogram.HTTP_BYTES, - size, endpoint, String.valueOf(responseWrapper.getStatus())); } else { MetricsUtil.meterMark(MetricsKey.NET_API_FAIL_QPS); - Metrics.histogramObserve(MetricKeys.Histogram.HTTP_BYTES, - size, MetricLabels.UNDEFINED, String.valueOf(responseWrapper.getStatus())); + MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_FAIL_QPS + endpoint); } + + MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_OUT_TRAFFIC + endpoint, size); + Metrics.histogramObserve(MetricKeys.Histogram.HTTP_BYTES, + size, endpoint, String.valueOf(responseWrapper.getStatus())); } else { chain.doFilter(request, response); } - } catch (Exception e) { - - if (MetricsUtil.getMeters(MetricsKey.NET_API_DETAIL_QPS).containsKey( - MetricsKey.NET_API_DETAIL_QPS + endpoint)) { // correct endpoint - MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_FAIL_QPS - + endpoint, 1); - MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_QPS - + endpoint, 1); + String key = MetricsKey.NET_API_DETAIL_QPS + endpoint; + if (MetricsUtil.getMeters(MetricsKey.NET_API_DETAIL_QPS).containsKey(key)) { + MetricsUtil.meterMark(key, 1); + MetricsUtil.meterMark(key, 1); } MetricsUtil.meterMark(MetricsKey.NET_API_QPS, 1); MetricsUtil.meterMark(MetricsKey.NET_API_FAIL_QPS, 1); - } - } @Override public void destroy() { - } } From 353587d6839888fba81af59e4d283ede9468e5e3 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 4 Jul 2023 14:23:45 +0800 Subject: [PATCH 0829/1197] feat(monitor): optimize monitoring logic for http interface --- .../tron/core/services/filter/HttpInterceptor.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java index 9116df377f7..8f30c9554d6 100644 --- a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java +++ b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java @@ -56,7 +56,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha MetricsUtil.meterMark(MetricsKey.NET_API_FAIL_QPS); MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_FAIL_QPS + endpoint); } - + MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_OUT_TRAFFIC + endpoint, size); Metrics.histogramObserve(MetricKeys.Histogram.HTTP_BYTES, size, endpoint, String.valueOf(responseWrapper.getStatus())); @@ -64,10 +64,12 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha chain.doFilter(request, response); } } catch (Exception e) { - String key = MetricsKey.NET_API_DETAIL_QPS + endpoint; - if (MetricsUtil.getMeters(MetricsKey.NET_API_DETAIL_QPS).containsKey(key)) { - MetricsUtil.meterMark(key, 1); - MetricsUtil.meterMark(key, 1); + if (MetricsUtil.getMeters(MetricsKey.NET_API_DETAIL_QPS).containsKey( + MetricsKey.NET_API_DETAIL_QPS + endpoint)) { + MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_FAIL_QPS + + endpoint, 1); + MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_QPS + + endpoint, 1); } MetricsUtil.meterMark(MetricsKey.NET_API_QPS, 1); MetricsUtil.meterMark(MetricsKey.NET_API_FAIL_QPS, 1); From e8a921f33b605aa9151be9378d09d000f3cd90fc Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 4 Jul 2023 15:08:03 +0800 Subject: [PATCH 0830/1197] feat(monitor): optimize code --- .../core/services/filter/HttpInterceptor.java | 65 ++++++++----------- 1 file changed, 28 insertions(+), 37 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java index 8f30c9554d6..071174ad499 100644 --- a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java +++ b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java @@ -30,46 +30,38 @@ public void init(FilterConfig filterConfig) { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { try { - if (request instanceof HttpServletRequest) { - endpoint = ((HttpServletRequest) request).getRequestURI(); - - CharResponseWrapper responseWrapper = new CharResponseWrapper( - (HttpServletResponse) response); - chain.doFilter(request, responseWrapper); - - HttpServletResponse resp = (HttpServletResponse) response; - int size = responseWrapper.getByteSize(); - - MetricsUtil.meterMark(MetricsKey.NET_API_OUT_TRAFFIC, size); - MetricsUtil.meterMark(MetricsKey.NET_API_QPS); - - if (resp.getStatus() >= HTTP_BAD_REQUEST && resp.getStatus() <= HTTP_NOT_ACCEPTABLE) { - MetricsUtil.meterMark(MetricsKey.NET_API_FAIL_QPS); - Metrics.histogramObserve(MetricKeys.Histogram.HTTP_BYTES, - size, MetricLabels.UNDEFINED, String.valueOf(responseWrapper.getStatus())); - return; - } - - if (resp.getStatus() == HTTP_SUCCESS) { - MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_QPS + endpoint); - } else { - MetricsUtil.meterMark(MetricsKey.NET_API_FAIL_QPS); - MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_FAIL_QPS + endpoint); - } - - MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_OUT_TRAFFIC + endpoint, size); + if (!(request instanceof HttpServletRequest)) { + chain.doFilter(request, response); + return; + } + endpoint = ((HttpServletRequest) request).getRequestURI(); + CharResponseWrapper responseWrapper = new CharResponseWrapper( + (HttpServletResponse) response); + chain.doFilter(request, responseWrapper); + HttpServletResponse resp = (HttpServletResponse) response; + int size = responseWrapper.getByteSize(); + MetricsUtil.meterMark(MetricsKey.NET_API_OUT_TRAFFIC, size); + MetricsUtil.meterMark(MetricsKey.NET_API_QPS); + if (resp.getStatus() >= HTTP_BAD_REQUEST && resp.getStatus() <= HTTP_NOT_ACCEPTABLE) { + MetricsUtil.meterMark(MetricsKey.NET_API_FAIL_QPS); Metrics.histogramObserve(MetricKeys.Histogram.HTTP_BYTES, - size, endpoint, String.valueOf(responseWrapper.getStatus())); + size, MetricLabels.UNDEFINED, String.valueOf(responseWrapper.getStatus())); + return; + } + if (resp.getStatus() == HTTP_SUCCESS) { + MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_QPS + endpoint); } else { - chain.doFilter(request, response); + MetricsUtil.meterMark(MetricsKey.NET_API_FAIL_QPS); + MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_FAIL_QPS + endpoint); } + MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_OUT_TRAFFIC + endpoint, size); + Metrics.histogramObserve(MetricKeys.Histogram.HTTP_BYTES, + size, endpoint, String.valueOf(responseWrapper.getStatus())); } catch (Exception e) { - if (MetricsUtil.getMeters(MetricsKey.NET_API_DETAIL_QPS).containsKey( - MetricsKey.NET_API_DETAIL_QPS + endpoint)) { - MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_FAIL_QPS - + endpoint, 1); - MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_QPS - + endpoint, 1); + String key = MetricsKey.NET_API_DETAIL_QPS + endpoint; + if (MetricsUtil.getMeters(MetricsKey.NET_API_DETAIL_QPS).containsKey(key)) { + MetricsUtil.meterMark(key, 1); + MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_QPS + endpoint, 1); } MetricsUtil.meterMark(MetricsKey.NET_API_QPS, 1); MetricsUtil.meterMark(MetricsKey.NET_API_FAIL_QPS, 1); @@ -79,7 +71,6 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha @Override public void destroy() { } - } From 5a515c11477a5537074a614f3d7db67009d0ee59 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Tue, 4 Jul 2023 16:25:24 +0800 Subject: [PATCH 0831/1197] fix(readme): update description of JDK 1.8 version in use --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 916ba25a329..3e51097916f 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ TRON is a project dedicated to building the infrastructure for a truly decentral TRON enables large-scale development and engagement. With over 2000 transactions per second (TPS), high concurrency, low latency, and massive data transmission. It is ideal for building decentralized entertainment applications. Free features and incentive systems allow developers to create premium app experiences for users. # Building the source -Building java-tron requires `git` and `Oracle JDK 1.8` to be installed, other JDK versions are not supported yet. Make sure you operate on `Linux` and `MacOS` operating systems. +Building java-tron requires `git` and 64-bit version of `Oracle JDK 1.8` to be installed, other JDK versions are not supported yet. Make sure you operate on `Linux` and `MacOS` operating systems. Clone the repo and switch to the `master` branch @@ -79,7 +79,7 @@ $ ./gradlew clean build -x test # Running java-tron -Running java-tron requires `Oracle JDK 1.8` to be installed, other JDK versions are not supported yet. Make sure you operate on `Linux` and `MacOS` operating systems. +Running java-tron requires 64-bit version of `Oracle JDK 1.8` to be installed, other JDK versions are not supported yet. Make sure you operate on `Linux` and `MacOS` operating systems. Get the mainnet configuration file: [main_net_config.conf](https://github.com/tronprotocol/tron-deployment/blob/master/main_net_config.conf), other network configuration files can be find [here](https://github.com/tronprotocol/tron-deployment). ## Hardware Requirements From 757c15c33ca7f3ca4ea74b550773190c3c68284d Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 4 Jul 2023 19:11:19 +0800 Subject: [PATCH 0832/1197] feat(monitor): modify monitoring key --- .../java/org/tron/core/services/filter/HttpInterceptor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java index 071174ad499..2cce8272dd5 100644 --- a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java +++ b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java @@ -61,7 +61,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha String key = MetricsKey.NET_API_DETAIL_QPS + endpoint; if (MetricsUtil.getMeters(MetricsKey.NET_API_DETAIL_QPS).containsKey(key)) { MetricsUtil.meterMark(key, 1); - MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_QPS + endpoint, 1); + MetricsUtil.meterMark(MetricsKey.NET_API_DETAIL_FAIL_QPS + endpoint, 1); } MetricsUtil.meterMark(MetricsKey.NET_API_QPS, 1); MetricsUtil.meterMark(MetricsKey.NET_API_FAIL_QPS, 1); From 291d9fc8673effd058b1099842ec5d4fdc609ac7 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 5 Jul 2023 12:27:39 +0800 Subject: [PATCH 0833/1197] feat(unit): optimize AdvServiceTest --- .../core/net/services/AdvServiceTest.java | 81 +++++++++++-------- 1 file changed, 49 insertions(+), 32 deletions(-) diff --git a/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java b/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java index 78db0398755..870dc9eef8e 100644 --- a/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java @@ -1,42 +1,58 @@ package org.tron.core.net.services; -import com.google.common.collect.Lists; -import java.util.List; -import javax.annotation.Resource; +import static org.mockito.Mockito.mock; + +import java.io.File; +import java.net.InetSocketAddress; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.BaseTest; +import org.mockito.Mockito; +import org.springframework.context.ApplicationContext; +import org.tron.common.application.TronApplicationContext; import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.FileUtil; import org.tron.common.utils.ReflectUtils; import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; +import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; +import org.tron.core.net.P2pEventHandlerImpl; import org.tron.core.net.message.adv.BlockMessage; import org.tron.core.net.message.adv.TransactionMessage; import org.tron.core.net.peer.Item; import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.peer.PeerManager; import org.tron.core.net.service.adv.AdvService; -import org.tron.p2p.P2pEventHandler; +import org.tron.p2p.connection.Channel; import org.tron.protos.Protocol; import org.tron.protos.Protocol.Inventory.InventoryType; -public class AdvServiceTest extends BaseTest { - - @Resource - private AdvService service; - @Resource - private PeerConnection peer; +public class AdvServiceTest { + private static String dbPath = "output-adv-service-test1"; + private static TronApplicationContext context; + private static AdvService service; + private static P2pEventHandlerImpl p2pEventHandler; + private static ApplicationContext ctx; - /** - * init context. - */ @BeforeClass public static void init() { dbPath = "output-adv-service-test"; Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, - Constant.TEST_CONF); + Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + service = context.getBean(AdvService.class); + p2pEventHandler = context.getBean(P2pEventHandlerImpl.class); + ctx = (ApplicationContext) ReflectUtils.getFieldObject(p2pEventHandler, "ctx"); + } + + @AfterClass + public static void after() { + Args.clearParam(); + context.destroy(); + FileUtil.deleteDir(new File(dbPath)); } @Test @@ -66,25 +82,26 @@ private void testAddInv() { } private void testBroadcast() { + InetSocketAddress inetSocketAddress = + new InetSocketAddress("127.0.0.2", 10001); - try { - List peers = Lists.newArrayList(); - peers.add(peer); - ReflectUtils.setFieldValue(P2pEventHandler.class, "peers", peers); - BlockCapsule blockCapsule = new BlockCapsule(1, Sha256Hash.ZERO_HASH, - System.currentTimeMillis(), Sha256Hash.ZERO_HASH.getByteString()); - BlockMessage msg = new BlockMessage(blockCapsule); - service.broadcast(msg); - Item item = new Item(blockCapsule.getBlockId(), InventoryType.BLOCK); - Assert.assertNotNull(service.getMessage(item)); - peer.checkAndPutAdvInvRequest(item, System.currentTimeMillis()); - boolean res = peer.checkAndPutAdvInvRequest(item, System.currentTimeMillis()); - Assert.assertFalse(res); - } catch (NullPointerException e) { - System.out.println(e); - } - } + Channel c1 = mock(Channel.class); + Mockito.when(c1.getInetSocketAddress()).thenReturn(inetSocketAddress); + Mockito.when(c1.getInetAddress()).thenReturn(inetSocketAddress.getAddress()); + PeerConnection peer = PeerManager.add(ctx, c1); + peer.setChannel(c1); + peer.setNeedSyncFromUs(false); + peer.setNeedSyncFromPeer(false); + + BlockCapsule blockCapsule = new BlockCapsule(1, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), Sha256Hash.ZERO_HASH.getByteString()); + BlockMessage msg = new BlockMessage(blockCapsule); + service.broadcast(msg); + Item item = new Item(blockCapsule.getBlockId(), InventoryType.BLOCK); + Assert.assertNotNull(service.getMessage(item)); + Assert.assertNotNull(peer.getAdvInvSpread().getIfPresent(item)); + } private void testTrxBroadcast() { Protocol.Transaction trx = Protocol.Transaction.newBuilder().build(); From 043265e93c5a69ee213d1424f26e335e54814049 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Wed, 12 Jul 2023 18:45:29 +0800 Subject: [PATCH 0834/1197] docs(plugins/read_me): fix examples for db lite (#5347) --- plugins/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/README.md b/plugins/README.md index e2458b7e9a6..6807bfbb409 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -91,7 +91,7 @@ DB lite provides lite database, parameters are compatible with previous `LiteFul #split and get a history dataset java -jar Toolkit.jar db lite -o split -t history --fn-data-path output-directory/database --dataset-path /tmp #merge history dataset and snapshot dataset - java -jar Toolkit.jar db lite -o split -t history --fn-data-path /tmp/snapshot --dataset-path /tmp/history + java -jar Toolkit.jar db lite -o merge --fn-data-path /tmp/snapshot --dataset-path /tmp/history ``` ## DB Move From 586601f929d4fa95a62531356ef0954d860d3ff4 Mon Sep 17 00:00:00 2001 From: Jorge <46056498+jorgectf@users.noreply.github.com> Date: Wed, 19 Jul 2023 08:00:26 +0200 Subject: [PATCH 0835/1197] CI:Add CodeQL workflow (#5331) * Add CodeQL workflow * Clean `on.push.branches` --- .github/workflows/codeql.yml | 64 ++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000000..4ab98d5cf3c --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,64 @@ +name: "CodeQL" + +on: + push: + branches: [ 'develop', 'master', 'release_**' ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ 'develop' ] + schedule: + - cron: '6 10 * * 0' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'java' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Use only 'java' to analyze code written in Java, Kotlin or both + # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" From 040ea41b9aa866740ac0118bdaebfdfbae7b49f5 Mon Sep 17 00:00:00 2001 From: Kayle Date: Wed, 19 Jul 2023 14:05:00 +0800 Subject: [PATCH 0836/1197] feat(issue): Add labels to issue templates (#5358) --- .github/ISSUE_TEMPLATE/ask-a-question.md | 2 +- .github/ISSUE_TEMPLATE/report-a-bug.md | 2 +- .github/ISSUE_TEMPLATE/request-a-feature.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/ask-a-question.md b/.github/ISSUE_TEMPLATE/ask-a-question.md index a92239b39eb..96d3d783684 100644 --- a/.github/ISSUE_TEMPLATE/ask-a-question.md +++ b/.github/ISSUE_TEMPLATE/ask-a-question.md @@ -2,7 +2,7 @@ name: Ask a question about: Something is unclear title: '' -labels: '' +labels: 'type:docs' assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/report-a-bug.md b/.github/ISSUE_TEMPLATE/report-a-bug.md index 649d7e97ed1..cfadd364c21 100644 --- a/.github/ISSUE_TEMPLATE/report-a-bug.md +++ b/.github/ISSUE_TEMPLATE/report-a-bug.md @@ -2,7 +2,7 @@ name: Report a bug about: Create a report to help us improve title: '' -labels: '' +labels: 'type:bug' assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/request-a-feature.md b/.github/ISSUE_TEMPLATE/request-a-feature.md index 9047b7e6a87..5099a72008b 100644 --- a/.github/ISSUE_TEMPLATE/request-a-feature.md +++ b/.github/ISSUE_TEMPLATE/request-a-feature.md @@ -2,7 +2,7 @@ name: Request a feature about: Suggest an idea for this project title: '' -labels: '' +labels: 'type:feature' assignees: '' --- From a1968e5ac474bdc71e0447285154fd7284e47cb5 Mon Sep 17 00:00:00 2001 From: Kayle Date: Thu, 20 Jul 2023 12:16:47 +0800 Subject: [PATCH 0837/1197] feat(issue): Optimize ask-a-question.md (#5361) 1. Updates imported to social apps for communication 2. Update the description, choose one of the two social apps --- .github/ISSUE_TEMPLATE/ask-a-question.md | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/ask-a-question.md b/.github/ISSUE_TEMPLATE/ask-a-question.md index 96d3d783684..14bf73d9de8 100644 --- a/.github/ISSUE_TEMPLATE/ask-a-question.md +++ b/.github/ISSUE_TEMPLATE/ask-a-question.md @@ -6,23 +6,5 @@ labels: 'type:docs' assignees: '' --- - - - -### System information - -java-tron version: `java -jar FullNode.jar -v` -OS & Version: Windows/Linux/OSX - - -### 1. What did you do? - - - -### 2. What did you expect to see? - - - -### 3. What did you see instead? - +This should only be used in very rare cases e.g. if you are not 100% sure if something is a bug or asking a question that leads to improving the documentation. For general questions please use [discord](https://discord.gg/5gyhdvG9) or [Telegram](https://t.me/TronOfficialDevelopersGroupEn). From 3ad08d17fbf1bc769037041c28e2fcff7cd8f8f6 Mon Sep 17 00:00:00 2001 From: Kayle Date: Thu, 20 Jul 2023 14:15:29 +0800 Subject: [PATCH 0838/1197] feat(config): Update seed node ip list in config.conf (#5360) --- framework/src/main/resources/config.conf | 37 ++++++++++++------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 67aa374eec3..c049bbbebc7 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -16,7 +16,7 @@ storage { # block_KDB, peers, properties, recent-block, trans, # utxo, votes, witness, witness_schedule. - # Otherwise, db configs will remain defualt and data will be stored in + # Otherwise, db configs will remain default and data will be stored in # the path of "output-directory" or which is set by "-d" ("--output-directory"). # setting can impove leveldb performance .... start @@ -359,23 +359,24 @@ seed.node = { "34.220.77.106:18888", "13.127.47.162:18888", "13.124.62.58:18888", - "13.229.128.108:18888", - "35.182.37.246:18888", - "34.200.228.125:18888", - "18.220.232.201:18888", - "13.57.30.186:18888", - "35.165.103.105:18888", - "18.184.238.21:18888", - "34.250.140.143:18888", - "35.176.192.130:18888", - "52.47.197.188:18888", - "52.62.210.100:18888", - "13.231.4.243:18888", - "18.231.76.29:18888", - "35.154.90.144:18888", - "13.125.210.234:18888", - "13.250.40.82:18888", - "35.183.101.48:18888" + "54.151.226.240:18888", + "35.174.93.198:18888", + "18.210.241.149:18888", + "54.177.115.127:18888", + "54.254.131.82:18888", + "18.167.171.167:18888", + "54.167.11.177:18888", + "35.74.7.196:18888", + "52.196.244.176:18888", + "54.248.129.19:18888", + "43.198.142.160:18888", + "3.0.214.7:18888", + "54.153.59.116:18888", + "54.153.94.160:18888", + "54.82.161.39:18888", + "54.179.207.68:18888", + "18.142.82.44:18888", + "18.163.230.203:18888" ] } From f15b2d94820841f9df688874ee2f42c2e91554ae Mon Sep 17 00:00:00 2001 From: Kayle Date: Thu, 20 Jul 2023 16:09:47 +0800 Subject: [PATCH 0839/1197] feat(issue): Add SECURITY.md (#5363) --- SECURITY.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000000..b3125ce6af1 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,7 @@ +## Supported Versions +Please see [Releases](https://github.com/tronprotocol/java-tron/releases). We recommend using the [most recently released version](https://github.com/tronprotocol/java-tron/releases/latest). + +## Reporting a Vulnerability +**Please do not file a public ticket** mentioning the vulnerability. +To find out how to report a vulnerability in TRON, visit [https://hackerone.com/tron_dao](https://hackerone.com/tron_dao?type=team) or email [bounty@tron.network](mailto:bounty@tron.network). +Please read the [disclosure policy](https://www.hackerone.com/disclosure-guidelines) for more information about publicly disclosed security vulnerabilities. From 57d118596cd76ab3ba83b0e8a43f7241b0cac3a9 Mon Sep 17 00:00:00 2001 From: Kayle Date: Thu, 20 Jul 2023 17:02:19 +0800 Subject: [PATCH 0840/1197] fix(docs): fix doc links for README (#5364) --- README.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 3e51097916f..2e0050ad84c 100644 --- a/README.md +++ b/README.md @@ -42,15 +42,14 @@

## Table of Contents -- [What’s TRON?](#What’s-TRON) -- [Building the Source Code](#Building-the-source) - - [Getting the Source Code](#Getting-the-Source-Code) - - [Build](#Build) -- [Running java-tron](#Running-java-tron) -- [Community](#Community) -- [Contribution](#Contribution) -- [Resources](#Resources) -- [License](#License) +- [What’s TRON?](#whats-tron) +- [Building the Source Code](#building-the-source) +- [Running java-tron](#running-java-tron) +- [Community](#community) +- [Contribution](#contribution) +- [Resources](#resources) +- [Integrity Check](#integrity-Check) +- [License](#license) ## What's TRON? From 9a65bb648022e85ea78bffb8bd5c6a78253e3952 Mon Sep 17 00:00:00 2001 From: Kayle Date: Thu, 20 Jul 2023 18:25:05 +0800 Subject: [PATCH 0841/1197] docs(README.md): fix catalogue links (#5365) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2e0050ad84c..4d1d7b0b3b6 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ - [Community](#community) - [Contribution](#contribution) - [Resources](#resources) -- [Integrity Check](#integrity-Check) +- [Integrity Check](#integrity-check) - [License](#license) ## What's TRON? From 10223ccf44124b0ac2429354fc693b6d0d5f9563 Mon Sep 17 00:00:00 2001 From: Jake151987 <127825539+Jake151987@users.noreply.github.com> Date: Tue, 1 Aug 2023 14:29:26 +0800 Subject: [PATCH 0842/1197] docs(ISSUE_TEMPLATE): fix invitation URL for Discord (#5387) --- .github/ISSUE_TEMPLATE/ask-a-question.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/ask-a-question.md b/.github/ISSUE_TEMPLATE/ask-a-question.md index 14bf73d9de8..e503998b477 100644 --- a/.github/ISSUE_TEMPLATE/ask-a-question.md +++ b/.github/ISSUE_TEMPLATE/ask-a-question.md @@ -6,5 +6,5 @@ labels: 'type:docs' assignees: '' --- -This should only be used in very rare cases e.g. if you are not 100% sure if something is a bug or asking a question that leads to improving the documentation. For general questions please use [discord](https://discord.gg/5gyhdvG9) or [Telegram](https://t.me/TronOfficialDevelopersGroupEn). +This should only be used in very rare cases e.g. if you are not 100% sure if something is a bug or asking a question that leads to improving the documentation. For general questions please use [Discord](https://discord.gg/cGKSsRVCGm) or [Telegram](https://t.me/TronOfficialDevelopersGroupEn). From 5ce3ff04af90310e665039beb3e5e8c5187e9faa Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 8 Aug 2023 11:37:26 +0800 Subject: [PATCH 0843/1197] fix(db): fix getHeadBlockId abnormal return problem --- chainbase/src/main/java/org/tron/core/ChainBaseManager.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java index adf66527499..dad76041777 100644 --- a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java +++ b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java @@ -316,9 +316,7 @@ public BlockCapsule getHead() throws HeaderNotFound { } public synchronized BlockId getHeadBlockId() { - return new BlockId( - dynamicPropertiesStore.getLatestBlockHeaderHash(), - dynamicPropertiesStore.getLatestBlockHeaderNumber()); + return new BlockId(dynamicPropertiesStore.getLatestBlockHeaderHash()); } public long getHeadBlockNum() { From 56efc4ee5c7eb3eab3619971fdf6dd21b6899391 Mon Sep 17 00:00:00 2001 From: lurais <107600021+lurais@users.noreply.github.com> Date: Wed, 9 Aug 2023 12:46:01 +0800 Subject: [PATCH 0844/1197] feat(log): optimize checkpointV2 check tips (#5383) --- .../src/main/java/org/tron/core/db2/core/SnapshotManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java index 230a812e093..4eed2c06733 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java @@ -493,7 +493,9 @@ public void check() { if (!isV2Open()) { List cpList = getCheckpointList(); if (cpList != null && cpList.size() != 0) { - logger.error("checkpoint check failed, can't convert checkpoint from v2 to v1"); + logger.error("checkpoint check failed, the checkpoint version of database not match your " + + "config file, please set storage.checkpoint.version = 2 in your config file " + + "and restart the node."); System.exit(-1); } checkV1(); From 2bbc0fddb77e5d0df53990db704fe5b37f8a3298 Mon Sep 17 00:00:00 2001 From: lurais <107600021+lurais@users.noreply.github.com> Date: Wed, 9 Aug 2023 12:49:58 +0800 Subject: [PATCH 0845/1197] feat(sign): optimize default signature verification efficiency (#5396) --- framework/src/main/java/org/tron/core/config/args/Args.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 50e4dacf6a9..040a06c6a02 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -824,7 +824,7 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.validateSignThreadNum = config.hasPath(Constant.NODE_VALIDATE_SIGN_THREAD_NUM) ? config .getInt(Constant.NODE_VALIDATE_SIGN_THREAD_NUM) - : (Runtime.getRuntime().availableProcessors() + 1) / 2; + : Runtime.getRuntime().availableProcessors(); PARAMETER.walletExtensionApi = config.hasPath(Constant.NODE_WALLET_EXTENSION_API) From 1a33965c569c3b9ba568410270fbda79dd9fff76 Mon Sep 17 00:00:00 2001 From: lurais <107600021+lurais@users.noreply.github.com> Date: Wed, 9 Aug 2023 16:38:34 +0800 Subject: [PATCH 0846/1197] feat(log): optimize error log output for Wallet.java (#5366) --- framework/src/main/java/org/tron/core/Wallet.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index b866ab54001..3560a7032bc 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -2058,7 +2058,7 @@ public IncrementalMerkleTree getMerkleTreeOfBlock(long blockNum) throws ZksnarkE .parseFrom(chainBaseManager.getMerkleTreeIndexStore().get(blockNum)); } } catch (Exception ex) { - logger.error(ex.getMessage()); + logger.error("GetMerkleTreeOfBlock failed, blockNum:{}", blockNum, ex); } return null; @@ -4304,7 +4304,7 @@ public long getEnergyFee(long timestamp) { return energyFee; } catch (Exception e) { - logger.error("getEnergyFee timestamp={} failed, error is {}", timestamp, e.getMessage()); + logger.error("GetEnergyFee timestamp={} failed", timestamp, e); return getEnergyFee(); } } @@ -4313,7 +4313,7 @@ public String getEnergyPrices() { try { return chainBaseManager.getDynamicPropertiesStore().getEnergyPriceHistory(); } catch (Exception e) { - logger.error("getEnergyPrices failed, error is {}", e.getMessage()); + logger.error("GetEnergyPrices failed", e); } return null; @@ -4323,7 +4323,7 @@ public String getBandwidthPrices() { try { return chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistory(); } catch (Exception e) { - logger.error("getBandwidthPrices failed, error is {}", e.getMessage()); + logger.error("GetBandwidthPrices failed", e); } return null; @@ -4444,7 +4444,7 @@ public String getMemoFeePrices() { try { return chainBaseManager.getDynamicPropertiesStore().getMemoFeeHistory(); } catch (Exception e) { - logger.error("getMemoFeePrices failed, error is {}", e.getMessage()); + logger.error("GetMemoFeePrices failed", e); } return null; } From 61c61773a97979ec2967eeaa9b580338d320f492 Mon Sep 17 00:00:00 2001 From: lurais <107600021+lurais@users.noreply.github.com> Date: Thu, 10 Aug 2023 14:27:27 +0800 Subject: [PATCH 0847/1197] feat(log): optimize error tips for db open(#5385) --- .../leveldb/LevelDbDataSourceImpl.java | 21 ++++++++++++---- .../rocksdb/RocksDbDataSourceImpl.java | 10 ++++++-- framework/build.gradle | 1 + .../leveldb/LevelDbDataSourceImplTest.java | 25 +++++++++++++++++++ .../leveldb/RocksDbDataSourceImplTest.java | 24 ++++++++++++++++++ 5 files changed, 74 insertions(+), 7 deletions(-) diff --git a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java index 2292f974c4b..43a24ff4416 100644 --- a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java @@ -142,11 +142,22 @@ private void openDatabase(Options dbOptions) throws IOException { if (!Files.isSymbolicLink(dbPath.getParent())) { Files.createDirectories(dbPath.getParent()); } - database = factory.open(dbPath.toFile(), dbOptions); - if (!this.getDBName().startsWith("checkpoint")) { - logger.info("DB {} open success with writeBufferSize {} M, cacheSize {} M, maxOpenFiles {}.", - this.getDBName(), dbOptions.writeBufferSize() / 1024 / 1024, - dbOptions.cacheSize() / 1024 / 1024, dbOptions.maxOpenFiles()); + try { + database = factory.open(dbPath.toFile(), dbOptions); + if (!this.getDBName().startsWith("checkpoint")) { + logger + .info("DB {} open success with writeBufferSize {} M, cacheSize {} M, maxOpenFiles {}.", + this.getDBName(), dbOptions.writeBufferSize() / 1024 / 1024, + dbOptions.cacheSize() / 1024 / 1024, dbOptions.maxOpenFiles()); + } + } catch (IOException e) { + if (e.getMessage().contains("Corruption:")) { + logger.error("Database {} corrupted, please delete database directory({}) and restart.", + dataBaseName, parentPath, e); + } else { + logger.error("Open Database {} failed", dataBaseName, e); + } + System.exit(1); } } diff --git a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java index a561ed1fa11..6c5d8018487 100644 --- a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java @@ -32,6 +32,7 @@ import org.rocksdb.RocksDBException; import org.rocksdb.RocksIterator; import org.rocksdb.Statistics; +import org.rocksdb.Status; import org.rocksdb.WriteBatch; import org.rocksdb.WriteOptions; import org.slf4j.LoggerFactory; @@ -265,8 +266,13 @@ protected void log(InfoLogLevel infoLogLevel, String logMsg) { try { database = RocksDB.open(options, dbPath.toString()); } catch (RocksDBException e) { - throw new RuntimeException( - String.format("failed to open database: %s", dataBaseName), e); + if (Objects.equals(e.getStatus().getCode(), Status.Code.Corruption)) { + logger.error("Database {} corrupted, please delete database directory({}) " + + "and restart.", dataBaseName, parentPath, e); + } else { + logger.error("Open Database {} failed", dataBaseName, e); + } + System.exit(1); } alive = true; diff --git a/framework/build.gradle b/framework/build.gradle index d3e13ac0a7e..063d320d477 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -43,6 +43,7 @@ dependencies { testCompile group: 'junit', name: 'junit', version: '4.13.2' testCompile group: 'org.mockito', name: 'mockito-core', version: '2.13.0' testCompile group: 'org.hamcrest', name: 'hamcrest-junit', version: '1.0.0.1' + testCompile group: 'com.github.stefanbirkner', name: 'system-rules', version: '1.16.0' compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java index eed995f12b5..b4ac2b4aebf 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java @@ -37,7 +37,9 @@ import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.contrib.java.lang.system.ExpectedSystemExit; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; import org.tron.common.utils.PublicMethod; @@ -65,6 +67,9 @@ public class LevelDbDataSourceImplTest { private byte[] key5 = "00000005aa".getBytes(); private byte[] key6 = "00000006aa".getBytes(); + @Rule + public final ExpectedSystemExit exit = ExpectedSystemExit.none(); + /** * Release resources. */ @@ -332,4 +337,24 @@ public void prefixQueryTest() { dataSource.resetDb(); dataSource.closeDB(); } + + @Test + public void initDbTest() { + exit.expectSystemExitWithStatus(1); + makeExceptionDb("test_initDb"); + LevelDbDataSourceImpl dataSource = new LevelDbDataSourceImpl( + Args.getInstance().getOutputDirectory(), "test_initDb"); + dataSource.initDB(); + dataSource.closeDB(); + } + + private void makeExceptionDb(String dbName) { + LevelDbDataSourceImpl dataSource = new LevelDbDataSourceImpl( + Args.getInstance().getOutputDirectory(), "test_initDb"); + dataSource.initDB(); + dataSource.closeDB(); + FileUtil.saveData(dataSource.getDbPath().toString() + "/CURRENT", + "...", Boolean.FALSE); + } + } diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java index f0ceb7fcac4..62630014b23 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java @@ -20,7 +20,9 @@ import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Rule; import org.junit.Test; +import org.junit.contrib.java.lang.system.ExpectedSystemExit; import org.tron.common.storage.rocksdb.RocksDbDataSourceImpl; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; @@ -48,6 +50,9 @@ public class RocksDbDataSourceImplTest { private byte[] key5 = "00000005aa".getBytes(); private byte[] key6 = "00000006aa".getBytes(); + @Rule + public final ExpectedSystemExit exit = ExpectedSystemExit.none(); + /** * Release resources. */ @@ -382,4 +387,23 @@ public void prefixQueryTest() { dataSource.resetDb(); dataSource.closeDB(); } + + @Test + public void initDbTest() { + exit.expectSystemExitWithStatus(1); + makeExceptionDb("test_initDb"); + RocksDbDataSourceImpl dataSource = new RocksDbDataSourceImpl( + Args.getInstance().getOutputDirectory(), "test_initDb"); + dataSource.initDB(); + dataSource.closeDB(); + } + + private void makeExceptionDb(String dbName) { + RocksDbDataSourceImpl dataSource = new RocksDbDataSourceImpl( + Args.getInstance().getOutputDirectory(), "test_initDb"); + dataSource.initDB(); + dataSource.closeDB(); + FileUtil.saveData(dataSource.getDbPath().toString() + "/CURRENT", + "...", Boolean.FALSE); + } } From a9c4f4324c895f2f3c74eb7d7fb13add719419fe Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Tue, 15 Aug 2023 11:23:32 +0800 Subject: [PATCH 0848/1197] feat(all): tune single Thread into SingleThreadExecutor (#5410) --- .../common/es/ExecutorServiceManager.java | 55 +++++++++++++++++++ .../org/tron/consensus/dpos/DposTask.java | 20 +++---- .../common/backup/socket/BackupServer.java | 12 +++- .../tron/core/config/TronLogShutdownHook.java | 4 +- .../main/java/org/tron/core/db/Manager.java | 25 ++++++--- .../nodepersist/NodePersistService.java | 30 ++++------ .../tron/common/backup/BackupServerTest.java | 44 +++++++++++++++ 7 files changed, 150 insertions(+), 40 deletions(-) create mode 100644 common/src/main/java/org/tron/common/es/ExecutorServiceManager.java create mode 100644 framework/src/test/java/org/tron/common/backup/BackupServerTest.java diff --git a/common/src/main/java/org/tron/common/es/ExecutorServiceManager.java b/common/src/main/java/org/tron/common/es/ExecutorServiceManager.java new file mode 100644 index 00000000000..f1e60fdcfbc --- /dev/null +++ b/common/src/main/java/org/tron/common/es/ExecutorServiceManager.java @@ -0,0 +1,55 @@ +package org.tron.common.es; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import lombok.extern.slf4j.Slf4j; + +@Slf4j(topic = "common") +public class ExecutorServiceManager { + + public static ExecutorService newSingleThreadExecutor(String name) { + return newSingleThreadExecutor(name, false); + } + + public static ExecutorService newSingleThreadExecutor(String name, boolean isDaemon) { + return Executors.newSingleThreadExecutor( + new ThreadFactoryBuilder().setNameFormat(name).setDaemon(isDaemon).build()); + } + + + public static ScheduledExecutorService newSingleThreadScheduledExecutor(String name) { + return newSingleThreadScheduledExecutor(name, false); + } + + public static ScheduledExecutorService newSingleThreadScheduledExecutor(String name, + boolean isDaemon) { + return Executors.newSingleThreadScheduledExecutor( + new ThreadFactoryBuilder().setNameFormat(name).setDaemon(isDaemon).build()); + } + + public static void shutdownAndAwaitTermination(ExecutorService pool, String name) { + if (pool == null) { + return; + } + logger.info("Pool {} shutdown...", name); + pool.shutdown(); // Disable new tasks from being submitted + try { + // Wait a while for existing tasks to terminate + if (!pool.awaitTermination(60, java.util.concurrent.TimeUnit.SECONDS)) { + pool.shutdownNow(); // Cancel currently executing tasks + // Wait a while for tasks to respond to being cancelled + if (!pool.awaitTermination(60, java.util.concurrent.TimeUnit.SECONDS)) { + logger.warn("Pool {} did not terminate", name); + } + } + } catch (InterruptedException ie) { + // (Re-)Cancel if current thread also interrupted + pool.shutdownNow(); + // Preserve interrupt status + Thread.currentThread().interrupt(); + } + logger.info("Pool {} shutdown done", name); + } +} diff --git a/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java b/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java index dcfa85ca5f3..537fe49ae65 100644 --- a/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java +++ b/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java @@ -3,12 +3,14 @@ import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import com.google.protobuf.ByteString; +import java.util.concurrent.ExecutorService; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.joda.time.DateTime; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; +import org.springframework.util.ObjectUtils; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; @@ -34,16 +36,18 @@ public class DposTask { @Setter private DposService dposService; - private Thread produceThread; + private ExecutorService produceExecutor; + + private final String name = "DPosMiner"; private volatile boolean isRunning = true; public void init() { - if (!dposService.isEnable() || StringUtils.isEmpty(dposService.getMiners())) { + if (!dposService.isEnable() || ObjectUtils.isEmpty(dposService.getMiners())) { return; } - + produceExecutor = ExecutorServiceManager.newSingleThreadExecutor(name); Runnable runnable = () -> { while (isRunning) { try { @@ -67,17 +71,13 @@ public void init() { } } }; - produceThread = new Thread(runnable, "DPosMiner"); - produceThread.start(); + produceExecutor.submit(runnable); logger.info("DPoS task started."); } public void stop() { isRunning = false; - if (produceThread != null) { - produceThread.interrupt(); - } - logger.info("DPoS task stopped."); + ExecutorServiceManager.shutdownAndAwaitTermination(produceExecutor, name); } private State produceBlock() { diff --git a/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java b/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java index e3b1de31736..fa2c0947852 100644 --- a/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java +++ b/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java @@ -7,11 +7,13 @@ import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder; import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; +import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.common.backup.BackupManager; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; import org.tron.p2p.stats.TrafficStats; @@ -29,6 +31,9 @@ public class BackupServer { private volatile boolean shutdown = false; + private final String name = "BackupServer"; + private ExecutorService executor; + @Autowired public BackupServer(final BackupManager backupManager) { this.backupManager = backupManager; @@ -36,13 +41,14 @@ public BackupServer(final BackupManager backupManager) { public void initServer() { if (port > 0 && commonParameter.getBackupMembers().size() > 0) { - new Thread(() -> { + executor = ExecutorServiceManager.newSingleThreadExecutor(name); + executor.submit(() -> { try { start(); } catch (Exception e) { logger.error("Start backup server failed, {}", e); } - }, "BackupServer").start(); + }); } } @@ -88,6 +94,7 @@ public void initChannel(NioDatagramChannel ch) public void close() { logger.info("Closing backup server..."); shutdown = true; + ExecutorServiceManager.shutdownAndAwaitTermination(executor, name); if (channel != null) { try { channel.close().await(10, TimeUnit.SECONDS); @@ -95,5 +102,6 @@ public void close() { logger.warn("Closing backup server failed.", e); } } + logger.info("Backup server closed."); } } diff --git a/framework/src/main/java/org/tron/core/config/TronLogShutdownHook.java b/framework/src/main/java/org/tron/core/config/TronLogShutdownHook.java index 880aa7e3090..f873b88ca44 100644 --- a/framework/src/main/java/org/tron/core/config/TronLogShutdownHook.java +++ b/framework/src/main/java/org/tron/core/config/TronLogShutdownHook.java @@ -16,9 +16,9 @@ public class TronLogShutdownHook extends ShutdownHookBase { private static final Duration CHECK_SHUTDOWN_DELAY = Duration.buildByMilliseconds(100); /** - * The check times before shutdown. default is 50 + * The check times before shutdown. default is 60000/100 = 600 times. */ - private Integer check_times = 50; + private final long check_times = 60 * 1000 / CHECK_SHUTDOWN_DELAY.getMilliseconds(); public TronLogShutdownHook() { } diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 3928f657e44..3a18dce32a9 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -49,6 +49,7 @@ import org.tron.api.GrpcAPI.TransactionInfoList; import org.tron.common.args.GenesisBlock; import org.tron.common.bloom.Bloom; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.logsfilter.EventPluginLoader; import org.tron.common.logsfilter.FilterQuery; import org.tron.common.logsfilter.capsule.BlockFilterCapsule; @@ -253,6 +254,13 @@ public class Manager { private AtomicInteger blockWaitLock = new AtomicInteger(0); private Object transactionLock = new Object(); + private ExecutorService rePushEs; + private static final String rePushEsName = "repush"; + private ExecutorService triggerEs; + private static final String triggerEsName = "event-trigger"; + private ExecutorService filterEs; + private static final String filterEsName = "filter"; + /** * Cycle thread to rePush Transactions */ @@ -429,14 +437,17 @@ public BlockingQueue getRePushTransactions() { public void stopRePushThread() { isRunRePushThread = false; + ExecutorServiceManager.shutdownAndAwaitTermination(rePushEs, rePushEsName); } public void stopRePushTriggerThread() { isRunTriggerCapsuleProcessThread = false; + ExecutorServiceManager.shutdownAndAwaitTermination(triggerEs, triggerEsName); } public void stopFilterProcessThread() { isRunFilterProcessThread = false; + ExecutorServiceManager.shutdownAndAwaitTermination(filterEs, filterEsName); } @PostConstruct @@ -524,21 +535,19 @@ public void init() { revokingStore.enable(); validateSignService = Executors .newFixedThreadPool(Args.getInstance().getValidateSignThreadNum()); - Thread rePushThread = new Thread(rePushLoop); - rePushThread.setDaemon(true); - rePushThread.start(); + rePushEs = ExecutorServiceManager.newSingleThreadExecutor(rePushEsName, true); + rePushEs.submit(rePushLoop); // add contract event listener for subscribing if (Args.getInstance().isEventSubscribe()) { startEventSubscribing(); - Thread triggerCapsuleProcessThread = new Thread(triggerCapsuleProcessLoop); - triggerCapsuleProcessThread.setDaemon(true); - triggerCapsuleProcessThread.start(); + triggerEs = ExecutorServiceManager.newSingleThreadExecutor(triggerEsName, true); + triggerEs.submit(triggerCapsuleProcessLoop); } // start json rpc filter process if (CommonParameter.getInstance().isJsonRpcFilterEnabled()) { - Thread filterProcessThread = new Thread(filterProcessLoop); - filterProcessThread.start(); + filterEs = ExecutorServiceManager.newSingleThreadExecutor(filterEsName); + filterEs.submit(filterProcessLoop); } //initStoreFactory diff --git a/framework/src/main/java/org/tron/core/net/service/nodepersist/NodePersistService.java b/framework/src/main/java/org/tron/core/net/service/nodepersist/NodePersistService.java index 457fe7c55cb..2445a7d64e5 100644 --- a/framework/src/main/java/org/tron/core/net/service/nodepersist/NodePersistService.java +++ b/framework/src/main/java/org/tron/core/net/service/nodepersist/NodePersistService.java @@ -4,12 +4,12 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.List; -import java.util.Objects; -import java.util.Timer; -import java.util.TimerTask; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.JsonUtil; @@ -27,28 +27,22 @@ public class NodePersistService { private final boolean isNodePersist = CommonParameter.getInstance().isNodeDiscoveryPersist(); @Autowired private CommonStore commonStore; - private Timer nodePersistTaskTimer; + + private ScheduledExecutorService nodePersistExecutor; + + private final String name = "NodePersistTask"; public void init() { if (isNodePersist) { - nodePersistTaskTimer = new Timer("NodePersistTaskTimer"); - nodePersistTaskTimer.scheduleAtFixedRate(new TimerTask() { - @Override - public void run() { - dbWrite(); - } - }, DB_COMMIT_RATE, DB_COMMIT_RATE); + nodePersistExecutor = ExecutorServiceManager.newSingleThreadScheduledExecutor(name); + nodePersistExecutor.scheduleAtFixedRate(this::dbWrite, DB_COMMIT_RATE, DB_COMMIT_RATE, + TimeUnit.MILLISECONDS); } } public void close() { - if (Objects.isNull(nodePersistTaskTimer)) { - return; - } - try { - nodePersistTaskTimer.cancel(); - } catch (Exception e) { - logger.error("Close nodePersistTaskTimer failed", e); + if (isNodePersist) { + ExecutorServiceManager.shutdownAndAwaitTermination(nodePersistExecutor, name); } } diff --git a/framework/src/test/java/org/tron/common/backup/BackupServerTest.java b/framework/src/test/java/org/tron/common/backup/BackupServerTest.java new file mode 100644 index 00000000000..34b17ec186f --- /dev/null +++ b/framework/src/test/java/org/tron/common/backup/BackupServerTest.java @@ -0,0 +1,44 @@ +package org.tron.common.backup; + +import java.util.ArrayList; +import java.util.List; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.tron.common.backup.socket.BackupServer; +import org.tron.common.parameter.CommonParameter; +import org.tron.core.Constant; +import org.tron.core.config.args.Args; + + +public class BackupServerTest { + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + private BackupServer backupServer; + + @Before + public void setUp() throws Exception { + Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + CommonParameter.getInstance().setBackupPort(80); + List members = new ArrayList<>(); + members.add("127.0.0.2"); + CommonParameter.getInstance().setBackupMembers(members); + BackupManager backupManager = new BackupManager(); + backupManager.init(); + backupServer = new BackupServer(backupManager); + } + + @After + public void tearDown() { + backupServer.close(); + Args.clearParam(); + } + + @Test + public void test() throws InterruptedException { + backupServer.initServer(); + } +} From 83151aaf4d66911533347b6250bb135a6c0883a9 Mon Sep 17 00:00:00 2001 From: chengtx01 <56535423+chengtx01@users.noreply.github.com> Date: Thu, 17 Aug 2023 19:09:51 +0800 Subject: [PATCH 0849/1197] feat(net):improve chain inventory generating logic (#5393) --- .../SyncBlockChainMsgHandler.java | 20 +++++++++++++++++-- .../SyncBlockChainMsgHandlerTest.java | 16 +++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java index 9027034ccc7..3c83bc51e47 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java @@ -87,6 +87,18 @@ private boolean check(PeerConnection peer, SyncBlockChainMessage msg) throws P2p private LinkedList getLostBlockIds(List blockIds) throws P2pException { + BlockId unForkId = getUnForkId(blockIds); + LinkedList ids = getBlockIds(unForkId.getNum()); + + if (ids.isEmpty() || !unForkId.equals(ids.peekFirst())) { + unForkId = getUnForkId(blockIds); + ids = getBlockIds(unForkId.getNum()); + } + + return ids; + } + + private BlockId getUnForkId(List blockIds) throws P2pException { BlockId unForkId = null; for (int i = blockIds.size() - 1; i >= 0; i--) { if (tronNetDelegate.containBlockInMainChain(blockIds.get(i))) { @@ -99,13 +111,17 @@ private LinkedList getLostBlockIds(List blockIds) throws P2pEx throw new P2pException(TypeEnum.SYNC_FAILED, "unForkId is null"); } + return unForkId; + } + + private LinkedList getBlockIds(Long unForkNum) throws P2pException { BlockId headID = tronNetDelegate.getHeadBlockId(); long headNum = headID.getNum(); - long len = Math.min(headNum, unForkId.getNum() + NetConstants.SYNC_FETCH_BATCH_NUM); + long len = Math.min(headNum, unForkNum + NetConstants.SYNC_FETCH_BATCH_NUM); LinkedList ids = new LinkedList<>(); - for (long i = unForkId.getNum(); i <= len; i++) { + for (long i = unForkNum; i <= len; i++) { if (i == headNum) { ids.add(headID); } else { diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java index 2dbad09c655..53375ec7815 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java @@ -2,6 +2,7 @@ import java.io.File; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.InetSocketAddress; import java.util.ArrayList; @@ -64,6 +65,21 @@ public void testProcessMessage() throws Exception { method.setAccessible(true); boolean f = (boolean)method.invoke(handler, peer, message); Assert.assertTrue(!f); + + Method method1 = handler.getClass().getDeclaredMethod( + "getLostBlockIds", List.class); + method1.setAccessible(true); + try { + method1.invoke(handler, blockIds); + } catch (InvocationTargetException e) { + Assert.assertEquals("unForkId is null", e.getTargetException().getMessage()); + } + + Method method2 = handler.getClass().getDeclaredMethod( + "getBlockIds", Long.class); + method2.setAccessible(true); + List list = (List) method2.invoke(handler, 0L); + Assert.assertEquals(1, list.size()); } @After From f18864c710f373fc6069ca0ca70dee026c02896a Mon Sep 17 00:00:00 2001 From: Kayle Date: Fri, 18 Aug 2023 13:56:07 +0800 Subject: [PATCH 0850/1197] feat(http): optimize getAddress method (#5367) --- framework/build.gradle | 1 + .../org/tron/core/services/http/Util.java | 59 +++++++-- .../http/GetBrokerageServletTest.java | 91 +++++++++++++ .../services/http/GetRewardServletTest.java | 120 ++++++++++++++++++ 4 files changed, 260 insertions(+), 11 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/services/http/GetBrokerageServletTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/GetRewardServletTest.java diff --git a/framework/build.gradle b/framework/build.gradle index 063d320d477..9bc93cacf33 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -86,6 +86,7 @@ dependencies { compile group: 'org.pf4j', name: 'pf4j', version: '2.5.0' testImplementation group: 'org.springframework', name: 'spring-test', version: '5.2.0.RELEASE' + testImplementation group: 'org.springframework', name: 'spring-web', version: '5.2.0.RELEASE' compile group: 'org.zeromq', name: 'jeromq', version: '0.5.3' compile project(":chainbase") diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 2cbf5d2e718..06c4f8ef26a 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -11,19 +11,22 @@ import com.google.protobuf.GeneratedMessageV3; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; + +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStreamReader; import java.lang.reflect.Constructor; import java.math.BigDecimal; import java.nio.charset.Charset; import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.bouncycastle.util.encoders.Hex; +import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.util.StringUtil; import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.BlockList; @@ -70,6 +73,8 @@ public class Util { public static final String FUNCTION_SELECTOR = "function_selector"; public static final String FUNCTION_PARAMETER = "parameter"; public static final String CALL_DATA = "data"; + public static final String APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded"; + public static final String APPLICATION_JSON = "application/json"; public static String printTransactionFee(String transactionFee) { JSONObject jsonObject = new JSONObject(); @@ -498,16 +503,7 @@ public static void printAccount(Account reply, HttpServletResponse response, Boo public static byte[] getAddress(HttpServletRequest request) throws Exception { byte[] address = null; String addressParam = "address"; - String addressStr = request.getParameter(addressParam); - if (StringUtils.isBlank(addressStr)) { - String input = request.getReader().lines() - .collect(Collectors.joining(System.lineSeparator())); - Util.checkBodySize(input); - JSONObject jsonObject = JSON.parseObject(input); - if (jsonObject != null) { - addressStr = jsonObject.getString(addressParam); - } - } + String addressStr = checkGetParam(request, addressParam); if (StringUtils.isNotBlank(addressStr)) { if (StringUtils.startsWith(addressStr, Constant.ADD_PRE_FIX_STRING_MAINNET)) { address = Hex.decode(addressStr); @@ -518,6 +514,47 @@ public static byte[] getAddress(HttpServletRequest request) throws Exception { return address; } + private static String checkGetParam(HttpServletRequest request, String key) throws Exception { + String method = request.getMethod(); + String value = null; + + if (HttpMethod.GET.toString().toUpperCase().equalsIgnoreCase(method)) { + return request.getParameter(key); + } + if (HttpMethod.POST.toString().toUpperCase().equals(method)) { + String contentType = request.getContentType(); + if (StringUtils.isBlank(contentType)) { + return null; + } + if (APPLICATION_JSON.toLowerCase().contains(contentType)) { + value = getRequestValue(request); + if (StringUtils.isBlank(value)) { + return null; + } + + JSONObject jsonObject = JSON.parseObject(value); + if (jsonObject != null) { + return jsonObject.getString(key); + } + } else if (APPLICATION_FORM_URLENCODED.toLowerCase().contains(contentType)) { + return request.getParameter(key); + } else { + return null; + } + } + return value; + } + + public static String getRequestValue(HttpServletRequest request) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream())); + String line; + StringBuilder sb = new StringBuilder(); + while ((line = reader.readLine()) != null) { + sb.append(line); + } + return sb.toString(); + } + public static List convertLogAddressToTronAddress(TransactionInfo transactionInfo) { List newLogList = new ArrayList<>(); diff --git a/framework/src/test/java/org/tron/core/services/http/GetBrokerageServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetBrokerageServletTest.java new file mode 100644 index 00000000000..898108d0dcd --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/GetBrokerageServletTest.java @@ -0,0 +1,91 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; + +import java.io.UnsupportedEncodingException; +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 GetBrokerageServletTest extends BaseTest { + + @Resource + private GetBrokerageServlet getBrokerageServlet; + + static { + dbPath = "db_GetBrokerageServlet_test"; + Args.setParam( + new String[]{ + "--output-directory", dbPath, + }, Constant.TEST_CONF + ); + } + + public MockHttpServletRequest createRequest(String contentType) { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setMethod("POST"); + request.setContentType(contentType); + request.setCharacterEncoding("UTF-8"); + return request; + } + + @Test + public void getBrokerageValueByJsonTest() { + int expect = 20; + String jsonParam = "{\"address\": \"27VZHn9PFZwNh7o2EporxmLkpe157iWZVkh\"}"; + MockHttpServletRequest request = createRequest("application/json"); + request.setContent(jsonParam.getBytes()); + MockHttpServletResponse response = new MockHttpServletResponse(); + getBrokerageServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + int brokerage = (int)result.get("brokerage"); + Assert.assertEquals(expect, brokerage); + } catch (UnsupportedEncodingException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void getBrokerageValueTest() { + int expect = 20; + MockHttpServletRequest request = createRequest("application/x-www-form-urlencoded"); + request.addParameter("address", "27VZHn9PFZwNh7o2EporxmLkpe157iWZVkh"); + MockHttpServletResponse response = new MockHttpServletResponse(); + getBrokerageServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + int brokerage = (int)result.get("brokerage"); + Assert.assertEquals(expect, brokerage); + } catch (UnsupportedEncodingException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void getByBlankParamTest() { + int expect = 0; + MockHttpServletRequest request = createRequest("application/x-www-form-urlencoded"); + request.addParameter("address", ""); + MockHttpServletResponse response = new MockHttpServletResponse(); + getBrokerageServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + int brokerage = (int)result.get("brokerage"); + Assert.assertEquals(expect, brokerage); + String content = (String) result.get("Error"); + Assert.assertNull(content); + } catch (UnsupportedEncodingException e) { + Assert.fail(e.getMessage()); + } + } +} diff --git a/framework/src/test/java/org/tron/core/services/http/GetRewardServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetRewardServletTest.java new file mode 100644 index 00000000000..47e563f01f9 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/GetRewardServletTest.java @@ -0,0 +1,120 @@ +package org.tron.core.services.http; + +import static org.tron.common.utils.Commons.decodeFromBase58Check; + +import com.alibaba.fastjson.JSONObject; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; + +import org.apache.commons.lang3.StringUtils; +import org.junit.After; +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.FileUtil; +import org.tron.core.Constant; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.service.MortgageService; +import org.tron.core.store.DelegationStore; + +public class GetRewardServletTest extends BaseTest { + + @Resource + private Manager manager; + + @Resource + private MortgageService mortgageService; + + @Resource + private DelegationStore delegationStore; + + @Resource + GetRewardServlet getRewardServlet; + + static { + dbPath = "db_GetRewardServlet_test"; + Args.setParam( + new String[]{ + "--output-directory", dbPath, + }, Constant.TEST_CONF + ); + } + + public MockHttpServletRequest createRequest(String contentType) { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setMethod("POST"); + request.setContentType(contentType); + request.setCharacterEncoding("UTF-8"); + return request; + } + + public void init() { + manager.getDynamicPropertiesStore().saveChangeDelegation(1); + byte[] sr = decodeFromBase58Check("27VZHn9PFZwNh7o2EporxmLkpe157iWZVkh"); + delegationStore.setBrokerage(0, sr, 10); + delegationStore.setWitnessVote(0, sr, 100000000); + } + + @Test + public void getRewardValueByJsonTest() { + init(); + int expect = 138181; + String jsonParam = "{\"address\": \"27VZHn9PFZwNh7o2EporxmLkpe157iWZVkh\"}"; + MockHttpServletRequest request = createRequest("application/json"); + MockHttpServletResponse response = new MockHttpServletResponse(); + request.setContent(jsonParam.getBytes()); + try { + getRewardServlet.doPost(request, response); + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + int reward = (int)result.get("reward"); + Assert.assertEquals(expect, reward); + } catch (UnsupportedEncodingException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void getRewardValueTest() { + init(); + int expect = 138181; + MockHttpServletRequest request = createRequest("application/x-www-form-urlencoded"); + MockHttpServletResponse response = new MockHttpServletResponse(); + mortgageService.payStandbyWitness(); + request.addParameter("address", "27VZHn9PFZwNh7o2EporxmLkpe157iWZVkh"); + getRewardServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + int reward = (int)result.get("reward"); + Assert.assertEquals(expect, reward); + } catch (UnsupportedEncodingException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void getByBlankParamTest() { + MockHttpServletRequest request = createRequest("application/x-www-form-urlencoded"); + MockHttpServletResponse response = new MockHttpServletResponse(); + request.addParameter("address", ""); + GetRewardServlet getRewardServlet = new GetRewardServlet(); + getRewardServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + int reward = (int)result.get("reward"); + Assert.assertEquals(0, reward); + String content = (String) result.get("Error"); + Assert.assertNull(content); + } catch (UnsupportedEncodingException e) { + Assert.fail(e.getMessage()); + } + } + +} From f20e11b893f5735ae5256c92bf9793224387c9e2 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Mon, 21 Aug 2023 18:53:22 +0800 Subject: [PATCH 0851/1197] feat(db): optimize for bloomFilter initialization (#5394) --- .../java/org/tron/core/ChainBaseManager.java | 5 + .../org/tron/core/db/TransactionCache.java | 0 .../org/tron/core/db2/common/TxCacheDB.java | 149 +++++++++++++++++- .../org/tron/core/db/TxCacheDBInitTest.java | 90 +++++++++++ 4 files changed, 241 insertions(+), 3 deletions(-) rename {framework => chainbase}/src/main/java/org/tron/core/db/TransactionCache.java (100%) create mode 100644 framework/src/test/java/org/tron/core/db/TxCacheDBInitTest.java diff --git a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java index dad76041777..939d95dc584 100644 --- a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java +++ b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java @@ -28,6 +28,7 @@ import org.tron.core.db.PbftSignDataStore; import org.tron.core.db.RecentBlockStore; import org.tron.core.db.RecentTransactionStore; +import org.tron.core.db.TransactionCache; import org.tron.core.db.TransactionStore; import org.tron.core.db2.core.ITronChainBase; import org.tron.core.exception.BadItemException; @@ -237,6 +238,9 @@ public class ChainBaseManager { @Autowired private DbStatService dbStatService; + @Autowired + private TransactionCache transactionCache; + @Getter @Setter private NodeType nodeType; @@ -291,6 +295,7 @@ public void closeAllStore() { closeOneStore(pbftSignDataStore); closeOneStore(sectionBloomStore); closeOneStore(accountAssetStore); + closeOneStore(transactionCache); } // for test only diff --git a/framework/src/main/java/org/tron/core/db/TransactionCache.java b/chainbase/src/main/java/org/tron/core/db/TransactionCache.java similarity index 100% rename from framework/src/main/java/org/tron/core/db/TransactionCache.java rename to chainbase/src/main/java/org/tron/core/db/TransactionCache.java diff --git a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java index 71cf361b06a..9923a876cad 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java @@ -3,10 +3,24 @@ import com.google.common.hash.BloomFilter; import com.google.common.hash.Funnels; import com.google.common.primitives.Longs; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; +import java.util.Properties; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicBoolean; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.bouncycastle.util.encoders.Hex; @@ -17,6 +31,7 @@ import org.tron.common.storage.leveldb.LevelDbDataSourceImpl; import org.tron.common.storage.rocksdb.RocksDbDataSourceImpl; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; import org.tron.common.utils.JsonUtil; import org.tron.common.utils.StorageUtils; import org.tron.core.capsule.BytesCapsule; @@ -42,6 +57,7 @@ public class TxCacheDB implements DB, Flusher { private BloomFilter[] bloomFilters = new BloomFilter[2]; // filterStartBlock record the start block of the active filter private volatile long filterStartBlock = INVALID_BLOCK; + private volatile long currentBlockNum = INVALID_BLOCK; // currentFilterIndex records the index of the active filter private volatile int currentFilterIndex = 0; @@ -57,6 +73,12 @@ public class TxCacheDB implements DB, Flusher { // replace persistentStore and optimizes startup performance private RecentTransactionStore recentTransactionStore; + private final Path cacheFile0; + private final Path cacheFile1; + private final Path cacheProperties; + private final Path cacheDir; + private AtomicBoolean isValid = new AtomicBoolean(false); + public TxCacheDB(String name, RecentTransactionStore recentTransactionStore) { this.name = name; this.TRANSACTION_COUNT = @@ -85,6 +107,10 @@ public TxCacheDB(String name, RecentTransactionStore recentTransactionStore) { MAX_BLOCK_SIZE * TRANSACTION_COUNT); this.bloomFilters[1] = BloomFilter.create(Funnels.byteArrayFunnel(), MAX_BLOCK_SIZE * TRANSACTION_COUNT); + cacheDir = Paths.get(CommonParameter.getInstance().getOutputDirectory(), ".cache"); + this.cacheFile0 = Paths.get(cacheDir.toString(), "bloomFilters_0"); + this.cacheFile1 = Paths.get(cacheDir.toString(), "bloomFilters_1"); + this.cacheProperties = Paths.get(cacheDir.toString(), "txCache.properties"); } @@ -110,6 +136,10 @@ private void initCache() { } public void init() { + if (recovery()) { + isValid.set(true); + return; + } long size = recentTransactionStore.size(); if (size != MAX_BLOCK_SIZE) { // 0. load from persistentStore @@ -129,6 +159,7 @@ public void init() { logger.info("Load cache from recentTransactionStore, filter: {}, filter-fpp: {}, cost: {} ms.", bloomFilters[1].approximateElementCount(), bloomFilters[1].expectedFpp(), System.currentTimeMillis() - start); + isValid.set(true); } @Override @@ -172,7 +203,7 @@ public void put(byte[] key, byte[] value) { MAX_BLOCK_SIZE * TRANSACTION_COUNT); } bloomFilters[currentFilterIndex].put(key); - + currentBlockNum = blockNum; if (lastMetricBlock != blockNum) { lastMetricBlock = blockNum; Metrics.gaugeSet(MetricKeys.Gauge.TX_CACHE, @@ -208,13 +239,15 @@ public Iterator> iterator() { } @Override - public void flush(Map batch) { + public synchronized void flush(Map batch) { + isValid.set(false); batch.forEach((k, v) -> this.put(k.getBytes(), v.getBytes())); + isValid.set(true); } @Override public void close() { - reset(); + dump(); bloomFilters[0] = null; bloomFilters[1] = null; persistentStore.close(); @@ -224,6 +257,116 @@ public void close() { public void reset() { } + private boolean recovery() { + FileUtil.createDirIfNotExists(this.cacheDir.toString()); + logger.info("recovery bloomFilters start."); + CompletableFuture loadProperties = CompletableFuture.supplyAsync(this::loadProperties); + CompletableFuture tk0 = loadProperties.thenApplyAsync( + v -> recovery(0, this.cacheFile0)); + CompletableFuture tk1 = loadProperties.thenApplyAsync( + v -> recovery(1, this.cacheFile1)); + + return CompletableFuture.allOf(tk0, tk1).thenApply(v -> { + logger.info("recovery bloomFilters success."); + return true; + }).exceptionally(this::handleException).join(); + } + + private boolean recovery(int index, Path file) { + try (InputStream in = new BufferedInputStream(Files.newInputStream(file, + StandardOpenOption.READ, StandardOpenOption.DELETE_ON_CLOSE))) { + logger.info("recovery bloomFilter[{}] from file.", index); + long start = System.currentTimeMillis(); + bloomFilters[index] = BloomFilter.readFrom(in, Funnels.byteArrayFunnel()); + logger.info("recovery bloomFilter[{}] from file done,filter: {}, filter-fpp: {}, cost {} ms.", + index, bloomFilters[index].approximateElementCount(), bloomFilters[index].expectedFpp(), + System.currentTimeMillis() - start); + return true; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private boolean handleException(Throwable e) { + bloomFilters[0] = BloomFilter.create(Funnels.byteArrayFunnel(), + MAX_BLOCK_SIZE * TRANSACTION_COUNT); + bloomFilters[1] = BloomFilter.create(Funnels.byteArrayFunnel(), + MAX_BLOCK_SIZE * TRANSACTION_COUNT); + try { + Files.deleteIfExists(this.cacheFile0); + Files.deleteIfExists(this.cacheFile1); + } catch (Exception ignored) { + + } + logger.info("recovery bloomFilters failed. {}", e.getMessage()); + logger.info("rollback to previous mode."); + return false; + } + + private void dump() { + if (!isValid.get()) { + logger.info("bloomFilters is not valid."); + } + FileUtil.createDirIfNotExists(this.cacheDir.toString()); + logger.info("dump bloomFilters start."); + CompletableFuture task0 = CompletableFuture.runAsync( + () -> dump(0, this.cacheFile0)); + CompletableFuture task1 = CompletableFuture.runAsync( + () -> dump(1, this.cacheFile1)); + CompletableFuture.allOf(task0, task1).thenRun(() -> { + writeProperties(); + logger.info("dump bloomFilters done."); + + }).exceptionally(e -> { + logger.info("dump bloomFilters to file failed. {}", e.getMessage()); + return null; + }).join(); + } + + private void dump(int index, Path file) { + try (OutputStream out = new BufferedOutputStream(Files.newOutputStream(file))) { + logger.info("dump bloomFilters[{}] to file.", index); + long start = System.currentTimeMillis(); + bloomFilters[index].writeTo(out); + logger.info("dump bloomFilters[{}] to file done,filter: {}, filter-fpp: {}, cost {} ms.", + index, bloomFilters[index].approximateElementCount(), bloomFilters[index].expectedFpp(), + System.currentTimeMillis() - start); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private boolean loadProperties() { + try (Reader r = new InputStreamReader(new BufferedInputStream(Files.newInputStream( + this.cacheProperties, StandardOpenOption.READ, StandardOpenOption.DELETE_ON_CLOSE)), + StandardCharsets.UTF_8)) { + Properties properties = new Properties(); + properties.load(r); + filterStartBlock = Long.parseLong(properties.getProperty("filterStartBlock")); + currentBlockNum = Long.parseLong(properties.getProperty("currentBlockNum")); + currentFilterIndex = Integer.parseInt(properties.getProperty("currentFilterIndex")); + logger.info("filterStartBlock: {}, currentBlockNum: {}, currentFilterIndex: {}, load done.", + filterStartBlock, currentBlockNum, currentFilterIndex); + return true; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private void writeProperties() { + try (Writer w = Files.newBufferedWriter(this.cacheProperties, StandardCharsets.UTF_8)) { + Properties properties = new Properties(); + properties.setProperty("filterStartBlock", String.valueOf(filterStartBlock)); + properties.setProperty("currentBlockNum", String.valueOf(currentBlockNum)); + properties.setProperty("currentFilterIndex", String.valueOf(currentFilterIndex)); + properties.store(w, "Generated by the application. PLEASE DO NOT EDIT! "); + logger.info("filterStartBlock: {}, currentBlockNum: {}, currentFilterIndex: {}, write done.", + filterStartBlock, currentBlockNum, currentFilterIndex); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + @Override public TxCacheDB newInstance() { return new TxCacheDB(name, recentTransactionStore); diff --git a/framework/src/test/java/org/tron/core/db/TxCacheDBInitTest.java b/framework/src/test/java/org/tron/core/db/TxCacheDBInitTest.java new file mode 100644 index 00000000000..c3cb7cb2eb6 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/TxCacheDBInitTest.java @@ -0,0 +1,90 @@ +package org.tron.core.db; + +import java.io.IOException; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.ByteArray; +import org.tron.core.Constant; +import org.tron.core.capsule.BytesCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.keystore.Wallet; + +@Slf4j +public class TxCacheDBInitTest { + + private static TronApplicationContext context; + + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); + + private final byte[][] hash = new byte[140000][64]; + + @AfterClass + public static void destroy() { + context.destroy(); + Args.clearParam(); + } + + /** + * Init data. + */ + @BeforeClass + public static void init() throws IOException { + Args.setParam(new String[]{"--output-directory", temporaryFolder.newFolder().toString(), + "--p2p-disable", "true"}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + } + + @Test + public void reload() { + TransactionCache db = context.getBean(TransactionCache.class); + db.initCache(); + putTransaction(); + DefaultListableBeanFactory defaultListableBeanFactory = + (DefaultListableBeanFactory) context.getAutowireCapableBeanFactory(); + queryTransaction(); + defaultListableBeanFactory.destroySingleton("transactionCache"); + TransactionCache transactionCache = new TransactionCache("transactionCache", + context.getBean(RecentTransactionStore.class)); + transactionCache.initCache(); + defaultListableBeanFactory.registerSingleton("transactionCache",transactionCache); + queryTransaction(); + } + + private void putTransaction() { + TransactionCache db = context.getBean(TransactionCache.class); + for (int i = 1; i < 140000; i++) { + hash[i] = Wallet.generateRandomBytes(64); + db.put(hash[i], new BytesCapsule(ByteArray.fromLong(i))); + } + } + + private void queryTransaction() { + TransactionCache db = context.getBean(TransactionCache.class); + // [1,65537] are expired + for (int i = 1; i < 65538; i++) { + try { + Assert.assertFalse("index = " + i, db.has(hash[i])); + } catch (Exception e) { + Assert.fail("transaction should be expired index = " + i); + } + } + // [65538,140000] are in cache + for (int i = 65538; i < 140000; i++) { + try { + Assert.assertTrue("index = " + i, db.has(hash[i])); + } catch (Exception e) { + Assert.fail("transaction should not be expired index = " + i); + } + } + } + +} \ No newline at end of file From 563af93196ecb8f4452300ce3b604d09ff738199 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 22 Aug 2023 13:25:39 +0800 Subject: [PATCH 0852/1197] feat(net): optimize transaction execution logic --- .../TransactionsMsgHandler.java | 5 +++-- .../tron/core/net/peer/PeerConnection.java | 4 ++++ .../core/net/peer/PeerConnectionTest.java | 19 +++++++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java index 5f8b3fcef16..a0109c06060 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java @@ -116,8 +116,8 @@ private void handleSmartContract() { } private void handleTransaction(PeerConnection peer, TransactionMessage trx) { - if (peer.isDisconnect()) { - logger.warn("Drop trx {} from {}, peer is disconnect", trx.getMessageId(), + if (peer.isBadPeer()) { + logger.warn("Drop trx {} from {}, peer is bad peer", trx.getMessageId(), peer.getInetAddress()); return; } @@ -133,6 +133,7 @@ private void handleTransaction(PeerConnection peer, TransactionMessage trx) { logger.warn("Trx {} from peer {} process failed. type: {}, reason: {}", trx.getMessageId(), peer.getInetAddress(), e.getType(), e.getMessage()); if (e.getType().equals(TypeEnum.BAD_TRX)) { + peer.setBadPeer(true); peer.disconnect(ReasonCode.BAD_TX); } } catch (Exception e) { diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index 0499fb4f818..666c99208ba 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -71,6 +71,10 @@ public class PeerConnection { @Getter private volatile boolean fetchAble; + @Setter + @Getter + private volatile boolean isBadPeer; + @Getter @Setter private ByteString address; diff --git a/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java b/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java new file mode 100644 index 00000000000..565f2c2b817 --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java @@ -0,0 +1,19 @@ +package org.tron.core.net.peer; + +import org.junit.Assert; +import org.junit.Test; + +public class PeerConnectionTest { + + @Test + public void testVariableDefaultValue() { + PeerConnection peerConnection = new PeerConnection(); + Assert.assertTrue(!peerConnection.isBadPeer()); + Assert.assertTrue(!peerConnection.isFetchAble()); + Assert.assertTrue(peerConnection.isIdle()); + Assert.assertTrue(!peerConnection.isRelayPeer()); + Assert.assertTrue(peerConnection.isNeedSyncFromPeer()); + Assert.assertTrue(peerConnection.isNeedSyncFromUs()); + Assert.assertTrue(!peerConnection.isSyncFinish()); + } +} From 6a1e001ea34ae5f993c7fc66e75cd3ec53fe1dbc Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 22 Aug 2023 14:45:16 +0800 Subject: [PATCH 0853/1197] delete four unused paramaters in Args --- .../common/parameter/CommonParameter.java | 27 ++++++++++--------- .../src/main/java/org/tron/core/Constant.java | 4 +-- .../java/org/tron/core/config/args/Args.java | 27 ++++++++++--------- .../org/tron/common/config/args/ArgsTest.java | 5 ++-- 4 files changed, 33 insertions(+), 30 deletions(-) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 0c8e6f74ee3..e89c512eb5e 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -18,6 +18,7 @@ import org.tron.core.config.args.Overlay; import org.tron.core.config.args.SeedNode; import org.tron.core.config.args.Storage; +import org.tron.p2p.P2pConfig; import org.tron.p2p.dns.update.PublishConfig; public class CommonParameter { @@ -169,6 +170,8 @@ public class CommonParameter { @Setter public int minParticipationRate; @Getter + public P2pConfig p2pConfig; + @Getter @Setter public int nodeListenPort; @Getter @@ -177,21 +180,21 @@ public class CommonParameter { @Getter @Setter public String nodeExternalIp; - @Getter - @Setter - public boolean nodeDiscoveryPublicHomeNode; - @Getter - @Setter - public long nodeDiscoveryPingTimeout; - @Getter - @Setter - public long nodeP2pPingInterval; +// @Getter +// @Setter +// public boolean nodeDiscoveryPublicHomeNode; +// @Getter +// @Setter +// public long nodeDiscoveryPingTimeout; +// @Getter +// @Setter +// public long nodeP2pPingInterval; @Getter @Setter public int nodeP2pVersion; - @Getter - @Setter - public String p2pNodeId; +// @Getter +// @Setter +// public String p2pNodeId; @Getter @Setter public boolean nodeEnableIpv6 = false; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index dea5a2534b9..4987c070218 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -101,8 +101,8 @@ public class Constant { public static final String NODE_MAX_CONNECTIONS_WITH_SAME_IP = "node.maxConnectionsWithSameIp"; public static final String NODE_MIN_PARTICIPATION_RATE = "node.minParticipationRate"; public static final String NODE_LISTEN_PORT = "node.listen.port"; - public static final String NODE_DISCOVERY_PUBLIC_HOME_NODE = "node.discovery.public.home.node"; - public static final String NODE_DISCOVERY_PING_TIMEOUT = "node.discovery.ping.timeout"; + //public static final String NODE_DISCOVERY_PUBLIC_HOME_NODE = "node.discovery.public.home.node"; + //public static final String NODE_DISCOVERY_PING_TIMEOUT = "node.discovery.ping.timeout"; public static final String NODE_P2P_PING_INTERVAL = "node.p2p.pingInterval"; public static final String NODE_P2P_VERSION = "node.p2p.version"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 040a06c6a02..5af82f132a4 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -73,6 +73,7 @@ import org.tron.core.store.AccountStore; import org.tron.keystore.Credentials; import org.tron.keystore.WalletUtils; +import org.tron.p2p.P2pConfig; import org.tron.p2p.dns.update.DnsType; import org.tron.p2p.dns.update.PublishConfig; import org.tron.p2p.utils.NetUtil; @@ -140,9 +141,9 @@ public static void clearParam() { PARAMETER.nodeListenPort = 0; PARAMETER.nodeDiscoveryBindIp = ""; PARAMETER.nodeExternalIp = ""; - PARAMETER.nodeDiscoveryPublicHomeNode = false; - PARAMETER.nodeDiscoveryPingTimeout = 15000; - PARAMETER.nodeP2pPingInterval = 0L; + // PARAMETER.nodeDiscoveryPublicHomeNode = false; + // PARAMETER.nodeDiscoveryPingTimeout = 15000; + // PARAMETER.nodeP2pPingInterval = 0L; PARAMETER.nodeP2pVersion = 0; PARAMETER.nodeEnableIpv6 = false; PARAMETER.dnsTreeUrls = new ArrayList<>(); @@ -170,7 +171,7 @@ public static void clearParam() { PARAMETER.forbidTransferToContract = 0; PARAMETER.tcpNettyWorkThreadNum = 0; PARAMETER.udpNettyWorkThreadNum = 0; - PARAMETER.p2pNodeId = ""; + // PARAMETER.p2pNodeId = ""; PARAMETER.solidityNode = false; PARAMETER.trustNodeAddr = ""; PARAMETER.walletExtensionApi = false; @@ -639,17 +640,17 @@ public static void setParam(final String[] args, final String confFileName) { bindIp(config); externalIp(config); - PARAMETER.nodeDiscoveryPublicHomeNode = - config.hasPath(Constant.NODE_DISCOVERY_PUBLIC_HOME_NODE) && config - .getBoolean(Constant.NODE_DISCOVERY_PUBLIC_HOME_NODE); + //PARAMETER.nodeDiscoveryPublicHomeNode = + // config.hasPath(Constant.NODE_DISCOVERY_PUBLIC_HOME_NODE) && config + // .getBoolean(Constant.NODE_DISCOVERY_PUBLIC_HOME_NODE); - PARAMETER.nodeDiscoveryPingTimeout = - config.hasPath(Constant.NODE_DISCOVERY_PING_TIMEOUT) - ? config.getLong(Constant.NODE_DISCOVERY_PING_TIMEOUT) : 15000; + //PARAMETER.nodeDiscoveryPingTimeout = + // config.hasPath(Constant.NODE_DISCOVERY_PING_TIMEOUT) + // ? config.getLong(Constant.NODE_DISCOVERY_PING_TIMEOUT) : 15000; - PARAMETER.nodeP2pPingInterval = - config.hasPath(Constant.NODE_P2P_PING_INTERVAL) - ? config.getLong(Constant.NODE_P2P_PING_INTERVAL) : 0; + //PARAMETER.nodeP2pPingInterval = + // config.hasPath(Constant.NODE_P2P_PING_INTERVAL) + // ? config.getLong(Constant.NODE_P2P_PING_INTERVAL) : 0; PARAMETER.nodeP2pVersion = config.hasPath(Constant.NODE_P2P_VERSION) diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index 7ad8069db06..17a04421d2d 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -11,14 +11,13 @@ import org.tron.core.config.args.Args; - public class ArgsTest { private static final String dbPath = "output_arg_test"; @Before public void init() { - Args.setParam(new String[]{"--output-directory", dbPath, "--p2p-disable", "true", + Args.setParam(new String[] {"--output-directory", dbPath, "--p2p-disable", "true", "--debug"}, Constant.TEST_CONF); } @@ -32,7 +31,7 @@ public void destroy() { public void testConfig() { Assert.assertEquals(Args.getInstance().getMaxTransactionPendingSize(), 2000); Assert.assertEquals(Args.getInstance().getPendingTransactionTimeout(), 60_000); - Assert.assertEquals(Args.getInstance().getNodeDiscoveryPingTimeout(), 15_000); + //Assert.assertEquals(Args.getInstance().getNodeDiscoveryPingTimeout(), 15_000); Assert.assertEquals(Args.getInstance().getMaxFastForwardNum(), 3); Assert.assertEquals(Args.getInstance().getBlockCacheTimeout(), 60); Assert.assertEquals(Args.getInstance().isNodeDetectEnable(), false); From ac90c45be4aa5f177184c742ab2b01f963ca6e8e Mon Sep 17 00:00:00 2001 From: lxcmyf Date: Tue, 22 Aug 2023 15:48:58 +0800 Subject: [PATCH 0854/1197] feat(api): optimize compatibility (#5408) --- .../tron/core/capsule/TransactionCapsule.java | 4 + .../http/GetAssetIssueListServlet.java | 33 +++++-- .../GetAvailableUnfreezeCountServlet.java | 3 + .../services/http/GetBlockByNumServlet.java | 9 +- .../http/GetCanDelegatedMaxSizeServlet.java | 8 +- .../GetCanWithdrawUnfreezeAmountServlet.java | 14 ++- .../services/http/GetNowBlockServlet.java | 36 ++++++-- .../core/services/http/ListNodesServlet.java | 33 +++++-- .../services/http/ListProposalsServlet.java | 33 +++++-- .../tron/core/services/http/PostParams.java | 6 ++ .../org/tron/core/services/http/Util.java | 30 ++++++- .../http/GetAssetIssueListServletTest.java | 83 ++++++++++++++++++ .../services/http/GetNowBlockServletTest.java | 86 +++++++++++++++++++ .../services/http/ListNodesServletTest.java | 83 ++++++++++++++++++ .../http/ListProposalsServletTest.java | 83 ++++++++++++++++++ 15 files changed, 504 insertions(+), 40 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/services/http/GetAssetIssueListServletTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/GetNowBlockServletTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/ListNodesServletTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/ListProposalsServletTest.java diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java index a33f445c15f..1edb5b114fb 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -346,6 +346,10 @@ public static byte[] getOwner(Transaction.Contract contract) { } } return owner.toByteArray(); + } catch (InvalidProtocolBufferException invalidProtocolBufferException) { + logger.warn("InvalidProtocolBufferException occurred because {}, please verify the interface " + + "input parameters", invalidProtocolBufferException.getMessage()); + return new byte[0]; } catch (Exception ex) { logger.error(ex.getMessage()); return new byte[0]; diff --git a/framework/src/main/java/org/tron/core/services/http/GetAssetIssueListServlet.java b/framework/src/main/java/org/tron/core/services/http/GetAssetIssueListServlet.java index 7757ecd8722..01ec00dbef3 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetAssetIssueListServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetAssetIssueListServlet.java @@ -1,5 +1,8 @@ package org.tron.core.services.http; +import static org.tron.core.services.http.Util.existVisible; + +import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; @@ -8,7 +11,6 @@ import org.tron.api.GrpcAPI.AssetIssueList; import org.tron.core.Wallet; - @Component @Slf4j(topic = "API") public class GetAssetIssueListServlet extends RateLimiterServlet { @@ -16,21 +18,36 @@ public class GetAssetIssueListServlet extends RateLimiterServlet { @Autowired private Wallet wallet; + @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { boolean visible = Util.getVisible(request); - AssetIssueList reply = wallet.getAssetIssueList(); - if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply, visible)); - } else { - response.getWriter().println("{}"); - } + response(response, visible); } catch (Exception e) { Util.processError(e, response); } } + @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { - doGet(request, response); + try { + PostParams params = PostParams.getPostParams(request); + boolean visible = Util.getVisible(request); + if (!existVisible(request)) { + visible = params.isVisible(); + } + response(response, visible); + } catch (Exception e) { + Util.processError(e, response); + } + } + + private void response(HttpServletResponse response, boolean visible) throws IOException { + AssetIssueList reply = wallet.getAssetIssueList(); + if (reply != null) { + response.getWriter().println(JsonFormat.printToString(reply, visible)); + } else { + response.getWriter().println("{}"); + } } } diff --git a/framework/src/main/java/org/tron/core/services/http/GetAvailableUnfreezeCountServlet.java b/framework/src/main/java/org/tron/core/services/http/GetAvailableUnfreezeCountServlet.java index 28fec9f3ee3..51f78fc4390 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetAvailableUnfreezeCountServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetAvailableUnfreezeCountServlet.java @@ -23,6 +23,9 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { boolean visible = Util.getVisible(request); String ownerAddress = request.getParameter("ownerAddress"); + if (ownerAddress == null) { + ownerAddress = request.getParameter("owner_address"); + } if (visible) { ownerAddress = Util.getHexAddress(ownerAddress); } diff --git a/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java index 44babc69551..800b421ace0 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java @@ -18,14 +18,21 @@ public class GetBlockByNumServlet extends RateLimiterServlet { @Autowired private Wallet wallet; + @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - fillResponse(Util.getVisible(request), Long.parseLong(request.getParameter("num")), response); + long num = 0; + String numStr = request.getParameter("num"); + if (numStr != null) { + num = Long.parseLong(numStr); + } + fillResponse(Util.getVisible(request), num, response); } catch (Exception e) { Util.processError(e, response); } } + @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { try { PostParams params = PostParams.getPostParams(request); diff --git a/framework/src/main/java/org/tron/core/services/http/GetCanDelegatedMaxSizeServlet.java b/framework/src/main/java/org/tron/core/services/http/GetCanDelegatedMaxSizeServlet.java index 81dd52400b5..924306a6a3f 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetCanDelegatedMaxSizeServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetCanDelegatedMaxSizeServlet.java @@ -18,10 +18,15 @@ public class GetCanDelegatedMaxSizeServlet extends RateLimiterServlet { @Autowired private Wallet wallet; + @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { boolean visible = Util.getVisible(request); - int type = Integer.parseInt(request.getParameter("type")); + int type = 0; + String typeStr = request.getParameter("type"); + if (typeStr != null) { + type = Integer.parseInt(typeStr); + } String ownerAddress = request.getParameter("owner_address"); if (visible) { ownerAddress = Util.getHexAddress(ownerAddress); @@ -34,6 +39,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { } } + @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { try { PostParams params = PostParams.getPostParams(request); diff --git a/framework/src/main/java/org/tron/core/services/http/GetCanWithdrawUnfreezeAmountServlet.java b/framework/src/main/java/org/tron/core/services/http/GetCanWithdrawUnfreezeAmountServlet.java index 4c1bbaf4f99..435cca9e5fb 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetCanWithdrawUnfreezeAmountServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetCanWithdrawUnfreezeAmountServlet.java @@ -18,23 +18,29 @@ public class GetCanWithdrawUnfreezeAmountServlet extends RateLimiterServlet { @Autowired private Wallet wallet; + @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { boolean visible = Util.getVisible(request); String ownerAddress = request.getParameter("owner_address"); - long timestamp = Long.valueOf(request.getParameter("timestamp")); + long timestamp = 0; + String timestampStr = request.getParameter("timestamp"); + if (timestampStr != null) { + timestamp = Long.parseLong(timestampStr); + } if (visible) { ownerAddress = Util.getHexAddress(ownerAddress); } fillResponse(visible, - ByteString.copyFrom(ByteArray.fromHexString(ownerAddress)), - timestamp, - response); + ByteString.copyFrom(ByteArray.fromHexString(ownerAddress)), + timestamp, + response); } catch (Exception e) { Util.processError(e, response); } } + @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { try { PostParams params = PostParams.getPostParams(request); diff --git a/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java b/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java index f7d9700aeb9..78e7178cfe3 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java @@ -1,5 +1,9 @@ package org.tron.core.services.http; +import static org.tron.core.services.http.Util.existVisible; +import static org.tron.core.services.http.Util.getVisible; + +import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; @@ -8,7 +12,6 @@ import org.tron.core.Wallet; import org.tron.protos.Protocol.Block; - @Component @Slf4j(topic = "API") public class GetNowBlockServlet extends RateLimiterServlet { @@ -16,21 +19,36 @@ public class GetNowBlockServlet extends RateLimiterServlet { @Autowired private Wallet wallet; + @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - boolean visible = Util.getVisible(request); - Block reply = wallet.getNowBlock(); - if (reply != null) { - response.getWriter().println(Util.printBlock(reply, visible)); - } else { - response.getWriter().println("{}"); - } + boolean visible = getVisible(request); + response(response, visible); } catch (Exception e) { Util.processError(e, response); } } + @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { - doGet(request, response); + try { + PostParams params = PostParams.getPostParams(request); + boolean visible = getVisible(request); + if (!existVisible(request)) { + visible = params.isVisible(); + } + response(response, visible); + } catch (Exception e) { + Util.processError(e, response); + } + } + + private void response(HttpServletResponse response, boolean visible) throws IOException { + Block reply = wallet.getNowBlock(); + if (reply != null) { + response.getWriter().println(Util.printBlock(reply, visible)); + } else { + response.getWriter().println("{}"); + } } } \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/services/http/ListNodesServlet.java b/framework/src/main/java/org/tron/core/services/http/ListNodesServlet.java index 94fd568a3f4..fb0b877832b 100644 --- a/framework/src/main/java/org/tron/core/services/http/ListNodesServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/ListNodesServlet.java @@ -1,5 +1,8 @@ package org.tron.core.services.http; +import static org.tron.core.services.http.Util.existVisible; + +import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; @@ -8,7 +11,6 @@ import org.tron.api.GrpcAPI.NodeList; import org.tron.core.Wallet; - @Component @Slf4j(topic = "API") public class ListNodesServlet extends RateLimiterServlet { @@ -16,21 +18,36 @@ public class ListNodesServlet extends RateLimiterServlet { @Autowired private Wallet wallet; + @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { boolean visible = Util.getVisible(request); - NodeList reply = wallet.listNodes(); - if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply, visible)); - } else { - response.getWriter().println("{}"); - } + response(response, visible); } catch (Exception e) { Util.processError(e, response); } } + @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { - doGet(request, response); + try { + PostParams params = PostParams.getPostParams(request); + boolean visible = Util.getVisible(request); + if (!existVisible(request)) { + visible = params.isVisible(); + } + response(response, visible); + } catch (Exception e) { + Util.processError(e, response); + } + } + + private void response(HttpServletResponse response, boolean visible) throws IOException { + NodeList reply = wallet.listNodes(); + if (reply != null) { + response.getWriter().println(JsonFormat.printToString(reply, visible)); + } else { + response.getWriter().println("{}"); + } } } diff --git a/framework/src/main/java/org/tron/core/services/http/ListProposalsServlet.java b/framework/src/main/java/org/tron/core/services/http/ListProposalsServlet.java index f8c67395b1b..e309963edda 100644 --- a/framework/src/main/java/org/tron/core/services/http/ListProposalsServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/ListProposalsServlet.java @@ -1,5 +1,8 @@ package org.tron.core.services.http; +import static org.tron.core.services.http.Util.existVisible; + +import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; @@ -8,7 +11,6 @@ import org.tron.api.GrpcAPI.ProposalList; import org.tron.core.Wallet; - @Component @Slf4j(topic = "API") public class ListProposalsServlet extends RateLimiterServlet { @@ -16,21 +18,36 @@ public class ListProposalsServlet extends RateLimiterServlet { @Autowired private Wallet wallet; + @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { boolean visible = Util.getVisible(request); - ProposalList reply = wallet.getProposalList(); - if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply, visible)); - } else { - response.getWriter().println("{}"); - } + response(response, visible); } catch (Exception e) { Util.processError(e, response); } } + @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { - doGet(request, response); + try { + PostParams params = PostParams.getPostParams(request); + boolean visible = Util.getVisible(request); + if (!existVisible(request)) { + visible = params.isVisible(); + } + response(response, visible); + } catch (Exception e) { + Util.processError(e, response); + } + } + + private void response(HttpServletResponse response, boolean visible) throws IOException { + ProposalList reply = wallet.getProposalList(); + if (reply != null) { + response.getWriter().println(JsonFormat.printToString(reply, visible)); + } else { + response.getWriter().println("{}"); + } } } diff --git a/framework/src/main/java/org/tron/core/services/http/PostParams.java b/framework/src/main/java/org/tron/core/services/http/PostParams.java index a2077fb3c78..7dcb0be6ae3 100644 --- a/framework/src/main/java/org/tron/core/services/http/PostParams.java +++ b/framework/src/main/java/org/tron/core/services/http/PostParams.java @@ -1,5 +1,8 @@ package org.tron.core.services.http; +import static org.apache.http.entity.ContentType.APPLICATION_FORM_URLENCODED; +import static org.tron.core.services.http.Util.getJsonString; + import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; import lombok.Getter; @@ -21,6 +24,9 @@ public PostParams(String params, boolean visible) { public static PostParams getPostParams(HttpServletRequest request) throws Exception { String input = request.getReader().lines().collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + if (APPLICATION_FORM_URLENCODED.getMimeType().equals(request.getContentType())) { + input = getJsonString(input); + } boolean visible = Util.getVisiblePost(input); return new PostParams(input, visible); } diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 06c4f8ef26a..186f77cf3e8 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import static org.apache.commons.lang3.StringUtils.EMPTY; import static org.tron.common.utils.Commons.decodeFromBase58Check; import com.alibaba.fastjson.JSON; @@ -21,13 +22,17 @@ import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.Objects; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.bouncycastle.util.encoders.Hex; import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.util.MultiMap; import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.util.UrlEncoded; import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.BlockList; import org.tron.api.GrpcAPI.TransactionApprovedList; @@ -338,12 +343,16 @@ public static boolean getVisible(final HttpServletRequest request) { return visible; } + public static boolean existVisible(final HttpServletRequest request) { + return Objects.nonNull(request.getParameter(VISIBLE)); + } + public static boolean getVisiblePost(final String input) { boolean visible = false; if (StringUtil.isNotBlank(input)) { JSONObject jsonObject = JSON.parseObject(input); if (jsonObject.containsKey(VISIBLE)) { - visible = jsonObject.getBoolean(VISIBLE); + visible = Boolean.parseBoolean(jsonObject.getString(VISIBLE)); } } @@ -606,4 +615,23 @@ public static void validateParameter(String contract) throws InvalidParameterExc } } + public static String getJsonString(String str) { + if (StringUtils.isEmpty(str)) { + return EMPTY; + } + MultiMap params = new MultiMap<>(); + UrlEncoded.decodeUtf8To(str, params); + JSONObject json = new JSONObject(); + for (Map.Entry> entry : params.entrySet()) { + String key = entry.getKey(); + List values = entry.getValue(); + if (values.size() == 1) { + json.put(key, values.get(0)); + } else { + json.put(key, values); + } + } + return json.toString(); + } + } diff --git a/framework/src/test/java/org/tron/core/services/http/GetAssetIssueListServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetAssetIssueListServletTest.java new file mode 100644 index 00000000000..141c349e252 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/GetAssetIssueListServletTest.java @@ -0,0 +1,83 @@ +package org.tron.core.services.http; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.Assert.fail; + +import com.alibaba.fastjson.JSONObject; +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; +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 GetAssetIssueListServletTest extends BaseTest { + + @Resource + private GetAssetIssueListServlet getAssetIssueListServlet; + + static { + dbPath = "db_GetNowBlockServlet_test"; + Args.setParam( + new String[]{ + "--output-directory", dbPath, + }, Constant.TEST_CONF + ); + } + + public MockHttpServletRequest createRequest(String contentType) { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setMethod("POST"); + request.setContentType(contentType); + request.setCharacterEncoding("UTF-8"); + return request; + } + + @Test + public void testGetAssetIssueListByJson() { + String jsonParam = "{\"visible\": true}"; + MockHttpServletRequest request = createRequest("application/json"); + request.setContent(jsonParam.getBytes()); + MockHttpServletResponse response = new MockHttpServletResponse(); + getAssetIssueListServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + JSONObject.parseObject(contentAsString); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + + @Test + public void testGetAssetIssueListValue() { + MockHttpServletRequest request = createRequest("application/x-www-form-urlencoded"); + try { + String params = "visible=true"; + request.setContent(params.getBytes(UTF_8)); + MockHttpServletResponse response = new MockHttpServletResponse(); + getAssetIssueListServlet.doPost(request, response); + String contentAsString = response.getContentAsString(); + JSONObject.parseObject(contentAsString); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + + @Test + public void testGetAssetIssueListEmptyParam() { + MockHttpServletRequest request = createRequest("application/x-www-form-urlencoded"); + String params = "visible="; + request.setContent(params.getBytes(UTF_8)); + MockHttpServletResponse response = new MockHttpServletResponse(); + getAssetIssueListServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + JSONObject.parseObject(contentAsString); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + +} diff --git a/framework/src/test/java/org/tron/core/services/http/GetNowBlockServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetNowBlockServletTest.java new file mode 100644 index 00000000000..682f780b249 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/GetNowBlockServletTest.java @@ -0,0 +1,86 @@ +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 com.alibaba.fastjson.JSONObject; +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; +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 GetNowBlockServletTest extends BaseTest { + + @Resource + private GetNowBlockServlet getNowBlockServlet; + + static { + dbPath = "db_GetNowBlockServlet_test"; + Args.setParam( + new String[]{ + "--output-directory", dbPath, + }, Constant.TEST_CONF + ); + } + + public MockHttpServletRequest createRequest(String contentType) { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setMethod("POST"); + request.setContentType(contentType); + request.setCharacterEncoding("UTF-8"); + return request; + } + + @Test + public void testGetNowBlockByJson() { + String jsonParam = "{\"visible\": true}"; + MockHttpServletRequest request = createRequest("application/json"); + request.setContent(jsonParam.getBytes()); + MockHttpServletResponse response = new MockHttpServletResponse(); + getNowBlockServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + assertTrue(result.containsKey("blockID")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + + @Test + public void testGetNowBlockValue() { + MockHttpServletRequest request = createRequest("application/x-www-form-urlencoded"); + try { + String params = "visible=true"; + request.setContent(params.getBytes(UTF_8)); + MockHttpServletResponse response = new MockHttpServletResponse(); + getNowBlockServlet.doPost(request, response); + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + assertTrue(result.containsKey("blockID")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + + @Test + public void testGetNowBlockEmptyParam() { + MockHttpServletRequest request = createRequest("application/x-www-form-urlencoded"); + String params = "visible="; + request.setContent(params.getBytes(UTF_8)); + MockHttpServletResponse response = new MockHttpServletResponse(); + getNowBlockServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + assertTrue(result.containsKey("blockID")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } +} diff --git a/framework/src/test/java/org/tron/core/services/http/ListNodesServletTest.java b/framework/src/test/java/org/tron/core/services/http/ListNodesServletTest.java new file mode 100644 index 00000000000..e2b8e7e9b6e --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/ListNodesServletTest.java @@ -0,0 +1,83 @@ +package org.tron.core.services.http; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; +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 ListNodesServletTest extends BaseTest { + + @Resource + private ListNodesServlet listNodesServlet; + + static { + dbPath = "db_GetNowBlockServlet_test"; + Args.setParam( + new String[]{ + "--output-directory", dbPath, + }, Constant.TEST_CONF + ); + } + + public MockHttpServletRequest createRequest(String contentType) { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setMethod("POST"); + request.setContentType(contentType); + request.setCharacterEncoding("UTF-8"); + return request; + } + + @Test + public void testListNodesByJson() { + String jsonParam = "{\"visible\": true}"; + MockHttpServletRequest request = createRequest("application/json"); + request.setContent(jsonParam.getBytes()); + MockHttpServletResponse response = new MockHttpServletResponse(); + listNodesServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + assertNotNull(contentAsString); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + + @Test + public void testListNodesValue() { + MockHttpServletRequest request = createRequest("application/x-www-form-urlencoded"); + try { + String params = "visible=true"; + request.setContent(params.getBytes(UTF_8)); + MockHttpServletResponse response = new MockHttpServletResponse(); + listNodesServlet.doPost(request, response); + String contentAsString = response.getContentAsString(); + assertNotNull(contentAsString); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + + @Test + public void testListNodesEmptyParam() { + MockHttpServletRequest request = createRequest("application/x-www-form-urlencoded"); + String params = "visible="; + request.setContent(params.getBytes(UTF_8)); + MockHttpServletResponse response = new MockHttpServletResponse(); + listNodesServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + assertNotNull(contentAsString); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + +} diff --git a/framework/src/test/java/org/tron/core/services/http/ListProposalsServletTest.java b/framework/src/test/java/org/tron/core/services/http/ListProposalsServletTest.java new file mode 100644 index 00000000000..0879d02004b --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/ListProposalsServletTest.java @@ -0,0 +1,83 @@ +package org.tron.core.services.http; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.Assert.fail; + +import com.alibaba.fastjson.JSONObject; +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; +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 ListProposalsServletTest extends BaseTest { + + @Resource + private ListProposalsServlet listProposalsServlet; + + static { + dbPath = "db_GetNowBlockServlet_test"; + Args.setParam( + new String[]{ + "--output-directory", dbPath, + }, Constant.TEST_CONF + ); + } + + public MockHttpServletRequest createRequest(String contentType) { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setMethod("POST"); + request.setContentType(contentType); + request.setCharacterEncoding("UTF-8"); + return request; + } + + @Test + public void testListProposalsByJson() { + String jsonParam = "{\"visible\": true}"; + MockHttpServletRequest request = createRequest("application/json"); + request.setContent(jsonParam.getBytes()); + MockHttpServletResponse response = new MockHttpServletResponse(); + listProposalsServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + JSONObject.parseObject(contentAsString); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + + @Test + public void testListProposalsValue() { + MockHttpServletRequest request = createRequest("application/x-www-form-urlencoded"); + try { + String params = "visible=true"; + request.setContent(params.getBytes(UTF_8)); + MockHttpServletResponse response = new MockHttpServletResponse(); + listProposalsServlet.doPost(request, response); + String contentAsString = response.getContentAsString(); + JSONObject.parseObject(contentAsString); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + + @Test + public void testListProposalsEmptyParam() { + MockHttpServletRequest request = createRequest("application/x-www-form-urlencoded"); + String params = "visible="; + request.setContent(params.getBytes(UTF_8)); + MockHttpServletResponse response = new MockHttpServletResponse(); + listProposalsServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + JSONObject.parseObject(contentAsString); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + +} From e1d096be16bd8dcda1673cbfc9cab7f8490573e9 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Wed, 23 Aug 2023 10:57:05 +0800 Subject: [PATCH 0855/1197] feat(all):make @PreDestroy work (#5421) --- .../common/application/ApplicationImpl.java | 3 - .../application/TronApplicationContext.java | 19 ++-- .../main/java/org/tron/program/FullNode.java | 7 +- .../java/org/tron/program/SolidityNode.java | 5 +- .../LiteFnQueryGrpcInterceptorTest.java | 91 ++++++++++--------- .../filter/RpcApiAccessInterceptorTest.java | 23 ++--- .../tron/program/LiteFullNodeToolTest.java | 5 +- 7 files changed, 69 insertions(+), 84 deletions(-) diff --git a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java index 0e38e97baaf..26200abec2d 100644 --- a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java +++ b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java @@ -12,8 +12,6 @@ import org.tron.core.db.Manager; import org.tron.core.metrics.MetricsUtil; import org.tron.core.net.TronNetService; -import org.tron.program.FullNode; -import org.tron.program.SolidityNode; @Slf4j(topic = "app") @Component @@ -87,7 +85,6 @@ public void shutdown() { dbManager.stopFilterProcessThread(); dynamicArgs.close(); logger.info("******** end to shutdown ********"); - FullNode.shutDownSign = true; } @Override diff --git a/framework/src/main/java/org/tron/common/application/TronApplicationContext.java b/framework/src/main/java/org/tron/common/application/TronApplicationContext.java index 7f0aea813a3..482e9e6219d 100644 --- a/framework/src/main/java/org/tron/common/application/TronApplicationContext.java +++ b/framework/src/main/java/org/tron/common/application/TronApplicationContext.java @@ -2,8 +2,7 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.tron.core.db.Manager; -import org.tron.core.net.TronNetService; +import org.tron.program.FullNode; public class TronApplicationContext extends AnnotationConfigApplicationContext { @@ -23,19 +22,13 @@ public TronApplicationContext(String... basePackages) { } @Override - public void destroy() { - + public void doClose() { + logger.info("******** start to close ********"); Application appT = ApplicationFactory.create(this); appT.shutdownServices(); appT.shutdown(); - - TronNetService tronNetService = getBean(TronNetService.class); - tronNetService.close(); - - Manager dbManager = getBean(Manager.class); - dbManager.stopRePushThread(); - dbManager.stopRePushTriggerThread(); - dbManager.stopFilterProcessThread(); - super.destroy(); + super.doClose(); + logger.info("******** close end ********"); + FullNode.shutDownSign = true; } } diff --git a/framework/src/main/java/org/tron/program/FullNode.java b/framework/src/main/java/org/tron/program/FullNode.java index 62732dd5e60..5ebf70e0d7a 100644 --- a/framework/src/main/java/org/tron/program/FullNode.java +++ b/framework/src/main/java/org/tron/program/FullNode.java @@ -81,7 +81,7 @@ public static void main(String[] args) { context.register(DefaultConfig.class); context.refresh(); Application appT = ApplicationFactory.create(context); - shutdown(appT); + context.registerShutdownHook(); // grpc api server RpcApiService rpcApiService = context.getBean(RpcApiService.class); @@ -138,9 +138,4 @@ public static void main(String[] args) { rpcApiService.blockUntilShutdown(); } - - public static void shutdown(final Application app) { - logger.info("********register application shutdown hook********"); - Runtime.getRuntime().addShutdownHook(new Thread(app::shutdown)); - } } diff --git a/framework/src/main/java/org/tron/program/SolidityNode.java b/framework/src/main/java/org/tron/program/SolidityNode.java index 0ca001da7bb..6101db8068c 100644 --- a/framework/src/main/java/org/tron/program/SolidityNode.java +++ b/framework/src/main/java/org/tron/program/SolidityNode.java @@ -71,7 +71,8 @@ public static void main(String[] args) { } parameter.setSolidityNode(true); - ApplicationContext context = new TronApplicationContext(DefaultConfig.class); + TronApplicationContext context = new TronApplicationContext(DefaultConfig.class); + context.registerShutdownHook(); if (parameter.isHelp()) { logger.info("Here is the help message."); @@ -81,8 +82,6 @@ public static void main(String[] args) { Metrics.init(); Application appT = ApplicationFactory.create(context); - FullNode.shutdown(appT); - RpcApiService rpcApiService = context.getBean(RpcApiService.class); appT.addService(rpcApiService); //http diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java index 4ee8fd051d0..439bf1f718f 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java @@ -3,23 +3,23 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import io.grpc.StatusRuntimeException; -import java.io.File; +import java.io.IOException; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; - -import org.junit.After; +import org.junit.AfterClass; import org.junit.Assert; -import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; import org.tron.api.GrpcAPI; import org.tron.api.WalletGrpc; import org.tron.api.WalletSolidityGrpc; import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.PublicMethod; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; @@ -32,54 +32,58 @@ @Slf4j public class LiteFnQueryGrpcInterceptorTest { - private TronApplicationContext context; - private ManagedChannel channelFull = null; - private ManagedChannel channelpBFT = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; - private WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubpBFT = null; - private RpcApiService rpcApiService; - private RpcApiServiceOnSolidity rpcApiServiceOnSolidity; - private RpcApiServiceOnPBFT rpcApiServiceOnPBFT; - private Application appTest; - private ChainBaseManager chainBaseManager; - - private String dbPath = "output_grpc_interceptor_test"; + private static TronApplicationContext context; + private static ManagedChannel channelFull = null; + private static ManagedChannel channelSolidity = null; + private static ManagedChannel channelpBFT = null; + private static WalletGrpc.WalletBlockingStub blockingStubFull = null; + private static WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; + private static WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubpBFT = null; + private static ChainBaseManager chainBaseManager; + private static final String ERROR_MSG = + "UNAVAILABLE: this API is closed because this node is a lite fullnode"; @Rule public ExpectedException thrown = ExpectedException.none(); + @ClassRule + public static TemporaryFolder temporaryFolder = new TemporaryFolder(); + /** * init logic. */ - @Before - public void init() { - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + @BeforeClass + public static void init() throws IOException { + Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); Args.getInstance().setRpcPort(PublicMethod.chooseRandomPort()); Args.getInstance().setRpcOnSolidityPort(PublicMethod.chooseRandomPort()); Args.getInstance().setRpcOnPBFTPort(PublicMethod.chooseRandomPort()); String fullnode = String.format("%s:%d", Args.getInstance().getNodeDiscoveryBindIp(), Args.getInstance().getRpcPort()); + String solidityNode = String.format("%s:%d", Args.getInstance().getNodeDiscoveryBindIp(), + Args.getInstance().getRpcOnSolidityPort()); String pBFTNode = String.format("%s:%d", Args.getInstance().getNodeDiscoveryBindIp(), - Args.getInstance().getRpcOnPBFTPort()); + Args.getInstance().getRpcOnPBFTPort()); channelFull = ManagedChannelBuilder.forTarget(fullnode) .usePlaintext() .build(); + channelSolidity = ManagedChannelBuilder.forTarget(solidityNode) + .usePlaintext() + .build(); channelpBFT = ManagedChannelBuilder.forTarget(pBFTNode) .usePlaintext() .build(); context = new TronApplicationContext(DefaultConfig.class); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelFull); + blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); blockingStubpBFT = WalletSolidityGrpc.newBlockingStub(channelpBFT); - blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelFull); - rpcApiService = context.getBean(RpcApiService.class); - rpcApiServiceOnSolidity = context.getBean(RpcApiServiceOnSolidity.class); - rpcApiServiceOnPBFT = context.getBean(RpcApiServiceOnPBFT.class); + RpcApiService rpcApiService = context.getBean(RpcApiService.class); + RpcApiServiceOnSolidity rpcOnSolidity = context.getBean(RpcApiServiceOnSolidity.class); + RpcApiServiceOnPBFT rpcApiServiceOnPBFT = context.getBean(RpcApiServiceOnPBFT.class); chainBaseManager = context.getBean(ChainBaseManager.class); - appTest = ApplicationFactory.create(context); + Application appTest = ApplicationFactory.create(context); appTest.addService(rpcApiService); - appTest.addService(rpcApiServiceOnSolidity); + appTest.addService(rpcOnSolidity); appTest.addService(rpcApiServiceOnPBFT); appTest.initServices(Args.getInstance()); appTest.startServices(); @@ -89,23 +93,19 @@ public void init() { /** * destroy the context. */ - @After - public void destroy() throws InterruptedException { + @AfterClass + public static void destroy() throws InterruptedException { if (channelFull != null) { channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); } + if (channelSolidity != null) { + channelSolidity.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } if (channelpBFT != null) { channelpBFT.shutdown().awaitTermination(5, TimeUnit.SECONDS); } + context.close(); Args.clearParam(); - appTest.shutdownServices(); - appTest.shutdown(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } @Test @@ -113,16 +113,25 @@ public void testGrpcApiThrowStatusRuntimeException() { final GrpcAPI.NumberMessage message = GrpcAPI.NumberMessage.newBuilder().setNum(0).build(); chainBaseManager.setNodeType(ChainBaseManager.NodeType.LITE); thrown.expect(StatusRuntimeException.class); - thrown.expectMessage("UNAVAILABLE: this API is closed because this node is a lite fullnode"); + thrown.expectMessage(ERROR_MSG); blockingStubFull.getBlockByNum(message); } + @Test + public void testGrpcSolidityThrowStatusRuntimeException() { + final GrpcAPI.NumberMessage message = GrpcAPI.NumberMessage.newBuilder().setNum(0).build(); + chainBaseManager.setNodeType(ChainBaseManager.NodeType.LITE); + thrown.expect(StatusRuntimeException.class); + thrown.expectMessage(ERROR_MSG); + blockingStubSolidity.getBlockByNum(message); + } + @Test public void testpBFTGrpcApiThrowStatusRuntimeException() { final GrpcAPI.NumberMessage message = GrpcAPI.NumberMessage.newBuilder().setNum(0).build(); chainBaseManager.setNodeType(ChainBaseManager.NodeType.LITE); thrown.expect(StatusRuntimeException.class); - thrown.expectMessage("UNAVAILABLE: this API is closed because this node is a lite fullnode"); + thrown.expectMessage(ERROR_MSG); blockingStubpBFT.getBlockByNum(message); } diff --git a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java index edd15fc19de..ac1f21f6160 100644 --- a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java @@ -4,7 +4,7 @@ import io.grpc.ManagedChannelBuilder; import io.grpc.StatusRuntimeException; import io.grpc.stub.ServerCallStreamObserver; -import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -13,16 +13,17 @@ import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; import org.tron.api.GrpcAPI; import org.tron.api.WalletGrpc; import org.tron.api.WalletSolidityGrpc; import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.PublicMethod; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; @@ -41,17 +42,18 @@ public class RpcApiAccessInterceptorTest { private static WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPBFT = null; private static Application appTest; - private static String dbPath = "output_rpc_api_access_interceptor_test"; - @Rule public ExpectedException thrown = ExpectedException.none(); + @ClassRule + public static TemporaryFolder temporaryFolder = new TemporaryFolder(); + /** * init logic. */ @BeforeClass - public static void init() { - Args.setParam(new String[] {"-d", dbPath}, Constant.TEST_CONF); + public static void init() throws IOException { + Args.setParam(new String[] {"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); Args.getInstance().setRpcPort(PublicMethod.chooseRandomPort()); Args.getInstance().setRpcOnSolidityPort(PublicMethod.chooseRandomPort()); Args.getInstance().setRpcOnPBFTPort(PublicMethod.chooseRandomPort()); @@ -97,15 +99,8 @@ public static void init() { */ @AfterClass public static void destroy() { + context.close(); Args.clearParam(); - appTest.shutdownServices(); - appTest.shutdown(); - context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } @Test diff --git a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java index e7e164e8e3b..205b2fbd30d 100644 --- a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java +++ b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java @@ -5,7 +5,6 @@ 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; @@ -76,9 +75,7 @@ public void shutdown() throws InterruptedException { if (channelFull != null) { channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); } - appTest.shutdownServices(); - appTest.shutdown(); - context.destroy(); + context.close(); } public void init() { From a4100b6ac250071c50c7ce5e0067a6016c283d05 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Wed, 23 Aug 2023 11:07:29 +0800 Subject: [PATCH 0856/1197] feat(db):tune the databases closure (#5429) --- .../java/org/tron/core/ChainBaseManager.java | 58 +--------- .../java/org/tron/core/db/TronDatabase.java | 9 +- .../tron/core/db/TronStoreWithRevoking.java | 9 +- .../org/tron/core/db2/common/TxCacheDB.java | 12 +++ .../tron/core/db2/core/SnapshotManager.java | 4 - .../common/application/ApplicationImpl.java | 7 +- .../main/java/org/tron/core/db/Manager.java | 23 +--- .../org/tron/core/db/TronDatabaseTest.java | 101 ++++++++++++++++++ .../org/tron/core/db/TxCacheDBInitTest.java | 1 + 9 files changed, 140 insertions(+), 84 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/db/TronDatabaseTest.java diff --git a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java index 939d95dc584..e43d442534a 100644 --- a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java +++ b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java @@ -28,9 +28,7 @@ import org.tron.core.db.PbftSignDataStore; import org.tron.core.db.RecentBlockStore; import org.tron.core.db.RecentTransactionStore; -import org.tron.core.db.TransactionCache; import org.tron.core.db.TransactionStore; -import org.tron.core.db2.core.ITronChainBase; import org.tron.core.exception.BadItemException; import org.tron.core.exception.HeaderNotFound; import org.tron.core.exception.ItemNotFoundException; @@ -238,9 +236,6 @@ public class ChainBaseManager { @Autowired private DbStatService dbStatService; - @Autowired - private TransactionCache transactionCache; - @Getter @Setter private NodeType nodeType; @@ -249,55 +244,6 @@ public class ChainBaseManager { @Setter private long lowestBlockNum = -1; // except num = 0. - public void closeOneStore(ITronChainBase database) { - logger.info("******** Begin to close {}. ********", database.getName()); - try { - database.close(); - } catch (Exception e) { - logger.info("Failed to close {}.", database.getName(), e); - } finally { - logger.info("******** End to close {}. ********", database.getName()); - } - } - - public void closeAllStore() { - dbStatService.shutdown(); - closeOneStore(transactionRetStore); - closeOneStore(recentBlockStore); - closeOneStore(transactionHistoryStore); - closeOneStore(transactionStore); - closeOneStore(accountStore); - closeOneStore(blockStore); - closeOneStore(blockIndexStore); - closeOneStore(accountIdIndexStore); - closeOneStore(accountIndexStore); - closeOneStore(witnessScheduleStore); - closeOneStore(assetIssueStore); - closeOneStore(dynamicPropertiesStore); - closeOneStore(abiStore); - closeOneStore(codeStore); - closeOneStore(contractStore); - closeOneStore(contractStateStore); - closeOneStore(storageRowStore); - closeOneStore(exchangeStore); - closeOneStore(proposalStore); - closeOneStore(votesStore); - closeOneStore(delegatedResourceStore); - closeOneStore(delegatedResourceAccountIndexStore); - closeOneStore(assetIssueV2Store); - closeOneStore(exchangeV2Store); - closeOneStore(nullifierStore); - closeOneStore(merkleTreeStore); - closeOneStore(delegationStore); - closeOneStore(proofStore); - closeOneStore(commonStore); - closeOneStore(commonDataBase); - closeOneStore(pbftSignDataStore); - closeOneStore(sectionBloomStore); - closeOneStore(accountAssetStore); - closeOneStore(transactionCache); - } - // for test only public List getWitnesses() { return witnessScheduleStore.getActiveWitnesses(); @@ -437,6 +383,10 @@ private void init() { this.nodeType = getLowestBlockNum() > 1 ? NodeType.LITE : NodeType.FULL; } + public void shutdown() { + dbStatService.shutdown(); + } + public boolean isLiteNode() { return getNodeType() == NodeType.LITE; } diff --git a/chainbase/src/main/java/org/tron/core/db/TronDatabase.java b/chainbase/src/main/java/org/tron/core/db/TronDatabase.java index b96d7543302..d791e189eb4 100644 --- a/chainbase/src/main/java/org/tron/core/db/TronDatabase.java +++ b/chainbase/src/main/java/org/tron/core/db/TronDatabase.java @@ -94,7 +94,14 @@ public void reset() { */ @Override public void close() { - dbSource.closeDB(); + logger.info("******** Begin to close {}. ********", getName()); + try { + dbSource.closeDB(); + } catch (Exception e) { + logger.warn("Failed to close {}.", getName(), e); + } finally { + logger.info("******** End to close {}. ********", getName()); + } } public abstract void put(byte[] key, T item); diff --git a/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java b/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java index c1da54d84f4..4b75ddee3a4 100644 --- a/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java +++ b/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java @@ -182,7 +182,14 @@ public String getName() { @Override public void close() { - revokingDB.close(); + logger.info("******** Begin to close {}. ********", getName()); + try { + revokingDB.close(); + } catch (Exception e) { + logger.warn("Failed to close {}.", getName(), e); + } finally { + logger.info("******** End to close {}. ********", getName()); + } } @Override diff --git a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java index 9923a876cad..34f6720a3a1 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java @@ -21,6 +21,8 @@ import java.util.Properties; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; +import lombok.Getter; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.bouncycastle.util.encoders.Hex; @@ -79,6 +81,10 @@ public class TxCacheDB implements DB, Flusher { private final Path cacheDir; private AtomicBoolean isValid = new AtomicBoolean(false); + @Getter + @Setter + private volatile boolean alive; + public TxCacheDB(String name, RecentTransactionStore recentTransactionStore) { this.name = name; this.TRANSACTION_COUNT = @@ -138,6 +144,7 @@ private void initCache() { public void init() { if (recovery()) { isValid.set(true); + setAlive(true); return; } long size = recentTransactionStore.size(); @@ -160,6 +167,7 @@ public void init() { bloomFilters[1].approximateElementCount(), bloomFilters[1].expectedFpp(), System.currentTimeMillis() - start); isValid.set(true); + setAlive(true); } @Override @@ -247,10 +255,14 @@ public synchronized void flush(Map batch) { @Override public void close() { + if (!isAlive()) { + return; + } dump(); bloomFilters[0] = null; bloomFilters[1] = null; persistentStore.close(); + setAlive(false); } @Override diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java index 4eed2c06733..96796b3c460 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java @@ -284,10 +284,6 @@ public synchronized void disable() { @Override public void shutdown() { - logger.info("******** Begin to pop revokingDb. ********"); - logger.info("******** Before revokingDb size: {}.", size); - checkTmpStore.close(); - logger.info("******** End to pop revokingDb. ********"); if (pruneCheckpointThread != null) { pruneCheckpointThread.shutdown(); } diff --git a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java index 26200abec2d..b6bcd670a03 100644 --- a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java +++ b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java @@ -77,12 +77,13 @@ public void shutdown() { synchronized (dbManager.getRevokingStore()) { dbManager.getSession().reset(); closeRevokingStore(); - closeAllStore(); } dbManager.stopRePushThread(); dbManager.stopRePushTriggerThread(); EventPluginLoader.getInstance().stopPlugin(); dbManager.stopFilterProcessThread(); + dbManager.stopValidateSignThread(); + getChainBaseManager().shutdown(); dynamicArgs.close(); logger.info("******** end to shutdown ********"); } @@ -112,8 +113,4 @@ private void closeRevokingStore() { dbManager.getRevokingStore().shutdown(); } - private void closeAllStore() { - dbManager.closeAllStore(); - } - } diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 3a18dce32a9..c50e8c900a1 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -105,7 +105,6 @@ import org.tron.core.db.api.MoveAbiHelper; import org.tron.core.db2.ISession; import org.tron.core.db2.core.Chainbase; -import org.tron.core.db2.core.ITronChainBase; import org.tron.core.db2.core.SnapshotManager; import org.tron.core.exception.AccountResourceInsufficientException; import org.tron.core.exception.BadBlockException; @@ -450,6 +449,10 @@ public void stopFilterProcessThread() { ExecutorServiceManager.shutdownAndAwaitTermination(filterEs, filterEsName); } + public void stopValidateSignThread() { + ExecutorServiceManager.shutdownAndAwaitTermination(validateSignService, "validate-sign"); + } + @PostConstruct public void init() { ChainBaseManager.init(chainBaseManager); @@ -1926,24 +1929,6 @@ public NullifierStore getNullifierStore() { return chainBaseManager.getNullifierStore(); } - public void closeAllStore() { - logger.info("******** Begin to close db. ********"); - chainBaseManager.closeAllStore(); - validateSignService.shutdown(); - logger.info("******** End to close db. ********"); - } - - public void closeOneStore(ITronChainBase database) { - logger.info("******** Begin to close {}. ********", database.getName()); - try { - database.close(); - } catch (Exception e) { - logger.info("Failed to close {}.", database.getName(), e); - } finally { - logger.info("******** End to close {}. ********", database.getName()); - } - } - public boolean isTooManyPending() { return getPendingTransactions().size() + getRePushTransactions().size() > maxTransactionPendingSize; diff --git a/framework/src/test/java/org/tron/core/db/TronDatabaseTest.java b/framework/src/test/java/org/tron/core/db/TronDatabaseTest.java new file mode 100644 index 00000000000..f38f55df64d --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/TronDatabaseTest.java @@ -0,0 +1,101 @@ +package org.tron.core.db; + +import com.google.protobuf.InvalidProtocolBufferException; +import java.io.IOException; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; +import org.rocksdb.RocksDB; +import org.tron.core.Constant; +import org.tron.core.config.args.Args; +import org.tron.core.exception.BadItemException; +import org.tron.core.exception.ItemNotFoundException; + +public class TronDatabaseTest extends TronDatabase { + + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); + + static { + RocksDB.loadLibrary(); + } + + @BeforeClass + public static void initArgs() throws IOException { + Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + } + + @AfterClass + public static void destroy() { + Args.clearParam(); + } + + @Override + public void put(byte[] key, String item) { + + } + + @Override + public void delete(byte[] key) { + + } + + @Override + public String get(byte[] key) { + return "test"; + } + + @Override + public boolean has(byte[] key) { + return false; + } + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void TestInit() { + TronDatabaseTest db = new TronDatabaseTest(); + Assert.assertNull(db.getDbSource()); + Assert.assertNull(db.getDbName()); + } + + @Test + public void TestIterator() { + TronDatabaseTest db = new TronDatabaseTest(); + thrown.expect(UnsupportedOperationException.class); + db.iterator(); + } + + @Test + public void TestIsNotEmpty() { + TronDatabaseTest db = new TronDatabaseTest(); + thrown.expect(UnsupportedOperationException.class); + db.isNotEmpty(); + } + + @Test + public void TestGetUnchecked() { + TronDatabaseTest db = new TronDatabaseTest(); + Assert.assertNull(db.getUnchecked("test".getBytes())); + } + + @Test + public void TestClose() { + TronDatabaseTest db = new TronDatabaseTest(); + db.close(); + } + + @Test + public void TestGetFromRoot() throws + InvalidProtocolBufferException, BadItemException, ItemNotFoundException { + TronDatabaseTest db = new TronDatabaseTest(); + Assert.assertEquals(db.getFromRoot("test".getBytes()), + "test"); + } +} diff --git a/framework/src/test/java/org/tron/core/db/TxCacheDBInitTest.java b/framework/src/test/java/org/tron/core/db/TxCacheDBInitTest.java index c3cb7cb2eb6..e415476d739 100644 --- a/framework/src/test/java/org/tron/core/db/TxCacheDBInitTest.java +++ b/framework/src/test/java/org/tron/core/db/TxCacheDBInitTest.java @@ -51,6 +51,7 @@ public void reload() { DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) context.getAutowireCapableBeanFactory(); queryTransaction(); + db.close(); defaultListableBeanFactory.destroySingleton("transactionCache"); TransactionCache transactionCache = new TransactionCache("transactionCache", context.getBean(RecentTransactionStore.class)); From 45cbda0258d08c665189f73ad5d3ecfa05881dab Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 23 Aug 2023 18:11:38 +0800 Subject: [PATCH 0857/1197] feat(net):optimzie code --- common/src/main/java/org/tron/core/Constant.java | 4 ++-- framework/src/test/java/org/tron/core/WalletTest.java | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 4987c070218..afe967285ee 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -103,8 +103,8 @@ public class Constant { public static final String NODE_LISTEN_PORT = "node.listen.port"; //public static final String NODE_DISCOVERY_PUBLIC_HOME_NODE = "node.discovery.public.home.node"; //public static final String NODE_DISCOVERY_PING_TIMEOUT = "node.discovery.ping.timeout"; - - public static final String NODE_P2P_PING_INTERVAL = "node.p2p.pingInterval"; + + //public static final String NODE_P2P_PING_INTERVAL = "node.p2p.pingInterval"; public static final String NODE_P2P_VERSION = "node.p2p.version"; public static final String NODE_ENABLE_IPV6 = "node.enableIpv6"; public static final String NODE_DNS_TREE_URLS = "node.dns.treeUrls"; diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 15b51f51edf..25500f13bbe 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -42,6 +42,7 @@ import org.tron.api.GrpcAPI.AssetIssueList; import org.tron.api.GrpcAPI.BlockList; import org.tron.api.GrpcAPI.ExchangeList; +import org.tron.api.GrpcAPI.NumberMessage; import org.tron.api.GrpcAPI.ProposalList; import org.tron.common.BaseTest; import org.tron.common.crypto.ECKey; @@ -567,6 +568,12 @@ public void getBlock() { assertEquals(block, wallet.getBlock(req)); } + @Test + public void testGetNextMaintenanceTime() { + NumberMessage numberMessage = wallet.getNextMaintenanceTime(); + Assert.assertEquals(0, numberMessage.getNum()); + } + //@Test public void testChainParameters() { From 3b2b60eb8bd9f9b29efb21a552a58d450ae89baa Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 23 Aug 2023 18:13:29 +0800 Subject: [PATCH 0858/1197] feat(net):optimzie code --- .../main/java/org/tron/common/parameter/CommonParameter.java | 3 --- common/src/main/java/org/tron/core/Constant.java | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index e89c512eb5e..a8c4991a782 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -18,7 +18,6 @@ import org.tron.core.config.args.Overlay; import org.tron.core.config.args.SeedNode; import org.tron.core.config.args.Storage; -import org.tron.p2p.P2pConfig; import org.tron.p2p.dns.update.PublishConfig; public class CommonParameter { @@ -170,8 +169,6 @@ public class CommonParameter { @Setter public int minParticipationRate; @Getter - public P2pConfig p2pConfig; - @Getter @Setter public int nodeListenPort; @Getter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index afe967285ee..7a56b7990b6 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -103,7 +103,7 @@ public class Constant { public static final String NODE_LISTEN_PORT = "node.listen.port"; //public static final String NODE_DISCOVERY_PUBLIC_HOME_NODE = "node.discovery.public.home.node"; //public static final String NODE_DISCOVERY_PING_TIMEOUT = "node.discovery.ping.timeout"; - + //public static final String NODE_P2P_PING_INTERVAL = "node.p2p.pingInterval"; public static final String NODE_P2P_VERSION = "node.p2p.version"; public static final String NODE_ENABLE_IPV6 = "node.enableIpv6"; From a02fbb0aaae73687923cc45ed81c4a8901a0c1d6 Mon Sep 17 00:00:00 2001 From: lxcmyf Date: Wed, 23 Aug 2023 20:40:47 +0800 Subject: [PATCH 0859/1197] feat(freezeV2): optimize Stake2.0 code (#5426) --------- Co-authored-by: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Co-authored-by: chaozhu --- .../actuator/CancelAllUnfreezeV2Actuator.java | 5 + .../actuator/DelegateResourceActuator.java | 56 ++-- .../core/actuator/FreezeBalanceActuator.java | 4 +- .../actuator/FreezeBalanceV2Actuator.java | 6 +- .../actuator/UnDelegateResourceActuator.java | 12 +- .../actuator/UnfreezeBalanceV2Actuator.java | 16 +- .../WithdrawExpireUnfreezeActuator.java | 4 +- .../org/tron/core/utils/ProposalUtil.java | 6 +- .../org/tron/core/utils/TransactionUtil.java | 57 +--- .../DelegateResourceProcessor.java | 26 +- .../FreezeBalanceProcessor.java | 4 +- .../FreezeBalanceV2Processor.java | 5 +- .../UnDelegateResourceProcessor.java | 16 +- .../WithdrawExpireUnfreezeProcessor.java | 4 +- .../org/tron/core/vm/program/Program.java | 44 ++- .../org/tron/core/vm/utils/FreezeV2Util.java | 40 +-- .../org/tron/core/capsule/AccountCapsule.java | 16 + .../org/tron/core/db/ResourceProcessor.java | 25 +- .../core/store/DynamicPropertiesStore.java | 6 +- .../java/org/tron/core/config/Parameter.java | 1 + .../src/main/java/org/tron/core/Wallet.java | 50 ++-- .../tron/common/runtime/vm/FreezeV2Test.java | 30 +- .../DelegateResourceActuatorTest.java | 26 +- .../actuator/FreezeBalanceActuatorTest.java | 130 ++++---- .../actuator/FreezeBalanceV2ActuatorTest.java | 75 ++--- .../actuator/UnfreezeBalanceActuatorTest.java | 187 +++++------- .../UnfreezeBalanceV2ActuatorTest.java | 3 +- .../actuator/utils/TransactionUtilTest.java | 277 +++++++++++++++++- 28 files changed, 633 insertions(+), 498 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/CancelAllUnfreezeV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/CancelAllUnfreezeV2Actuator.java index 527c88115ac..048f703e9f7 100755 --- a/actuator/src/main/java/org/tron/core/actuator/CancelAllUnfreezeV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/CancelAllUnfreezeV2Actuator.java @@ -58,6 +58,11 @@ public boolean execute(Object result) throws ContractExeException { List unfrozenV2List = ownerCapsule.getUnfrozenV2List(); long now = dynamicStore.getLatestBlockHeaderTimestamp(); AtomicLong atomicWithdrawExpireBalance = new AtomicLong(0L); + /* The triple object is defined by resource type, with left representing the pair object + corresponding to bandwidth, middle representing the pair object corresponding to energy, and + right representing the pair object corresponding to tron power. The pair object for each + resource type, left represents resource weight, and right represents the number of unfreeze + resources for that resource type. */ Triple, Pair, Pair> triple = Triple.of( Pair.of(new AtomicLong(0L), new AtomicLong(0L)), diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index c54c00b5697..6725bc349b9 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -1,11 +1,14 @@ package org.tron.core.actuator; import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; +import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import static org.tron.protos.contract.Common.ResourceCode; import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; import static org.tron.protos.contract.Common.ResourceCode.ENERGY; +import static org.tron.core.vm.utils.FreezeV2Util.getV2EnergyUsage; +import static org.tron.core.vm.utils.FreezeV2Util.getV2NetUsage; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; @@ -64,7 +67,8 @@ public boolean execute(Object result) throws ContractExeException { DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore(); long delegateBalance = delegateResourceContract.getBalance(); boolean lock = delegateResourceContract.getLock(); - long lockPeriod = getLockPeriod(dynamicStore, delegateResourceContract); + long lockPeriod = getLockPeriod(dynamicStore.supportMaxDelegateLockPeriod(), + delegateResourceContract); byte[] receiverAddress = delegateResourceContract.getReceiverAddress().toByteArray(); // delegate resource to receiver @@ -143,7 +147,7 @@ public boolean validate() throws ContractValidateException { long delegateBalance = delegateResourceContract.getBalance(); if (delegateBalance < TRX_PRECISION) { - throw new ContractValidateException("delegateBalance must be more than 1TRX"); + throw new ContractValidateException("delegateBalance must be greater than or equal to 1 TRX"); } switch (delegateResourceContract.getResource()) { @@ -153,22 +157,15 @@ public boolean validate() throws ContractValidateException { long accountNetUsage = ownerCapsule.getNetUsage(); if (null != this.getTx() && this.getTx().isTransactionCreate()) { - accountNetUsage += TransactionUtil.estimateConsumeBandWidthSize(ownerCapsule, - chainBaseManager); + accountNetUsage += TransactionUtil.estimateConsumeBandWidthSize(dynamicStore, + ownerCapsule.getBalance()); } long netUsage = (long) (accountNetUsage * TRX_PRECISION * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); - - long remainNetUsage = netUsage - - ownerCapsule.getFrozenBalance() - - ownerCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() - - ownerCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth(); - - remainNetUsage = Math.max(0, remainNetUsage); - - if (ownerCapsule.getFrozenV2BalanceForBandwidth() - remainNetUsage < delegateBalance) { + long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage); + if (ownerCapsule.getFrozenV2BalanceForBandwidth() - v2NetUsage < delegateBalance) { throw new ContractValidateException( - "delegateBalance must be less than available FreezeBandwidthV2 balance"); + "delegateBalance must be less than or equal to available FreezeBandwidthV2 balance"); } } break; @@ -178,17 +175,10 @@ public boolean validate() throws ContractValidateException { long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); - - long remainEnergyUsage = energyUsage - - ownerCapsule.getEnergyFrozenBalance() - - ownerCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() - - ownerCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy(); - - remainEnergyUsage = Math.max(0, remainEnergyUsage); - - if (ownerCapsule.getFrozenV2BalanceForEnergy() - remainEnergyUsage < delegateBalance) { + long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage); + if (ownerCapsule.getFrozenV2BalanceForEnergy() - v2EnergyUsage < delegateBalance) { throw new ContractValidateException( - "delegateBalance must be less than available FreezeEnergyV2 balance"); + "delegateBalance must be less than or equal to available FreezeEnergyV2 balance"); } } break; @@ -219,7 +209,7 @@ public boolean validate() throws ContractValidateException { boolean lock = delegateResourceContract.getLock(); if (lock && dynamicStore.supportMaxDelegateLockPeriod()) { - long lockPeriod = getLockPeriod(dynamicStore, delegateResourceContract); + long lockPeriod = getLockPeriod(true, delegateResourceContract); long maxDelegateLockPeriod = dynamicStore.getMaxDelegateLockPeriod(); if (lockPeriod < 0 || lockPeriod > maxDelegateLockPeriod) { throw new ContractValidateException( @@ -257,20 +247,20 @@ public boolean validate() throws ContractValidateException { return true; } - private long getLockPeriod(DynamicPropertiesStore dynamicStore, + private long getLockPeriod(boolean supportMaxDelegateLockPeriod, DelegateResourceContract delegateResourceContract) { long lockPeriod = delegateResourceContract.getLockPeriod(); - if (dynamicStore.supportMaxDelegateLockPeriod()) { - return lockPeriod == 0 ? DELEGATE_PERIOD / 3000 : lockPeriod; + if (supportMaxDelegateLockPeriod) { + return lockPeriod == 0 ? DELEGATE_PERIOD / BLOCK_PRODUCED_INTERVAL : lockPeriod; } else { - return 0; + return DELEGATE_PERIOD / BLOCK_PRODUCED_INTERVAL; } } private void validRemainTime(ResourceCode resourceCode, long lockPeriod, long expireTime, long now) throws ContractValidateException { long remainTime = expireTime - now; - if (lockPeriod * 3 * 1000 < remainTime) { + if (lockPeriod * BLOCK_PRODUCED_INTERVAL < remainTime) { throw new ContractValidateException( "The lock period for " + resourceCode.name() + " this time cannot be less than the " + "remaining time[" + remainTime + "ms] of the last lock period for " @@ -303,11 +293,7 @@ private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boole //modify DelegatedResourceStore long expireTime = 0; if (lock) { - if (dynamicPropertiesStore.supportMaxDelegateLockPeriod()) { - expireTime = now + lockPeriod * 3 * 1000; - } else { - expireTime = now + DELEGATE_PERIOD; - } + expireTime = now + lockPeriod * BLOCK_PRODUCED_INTERVAL; } byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, lock); DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore.get(key); diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java index 0cfd981217f..421b4e3013a 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java @@ -189,7 +189,7 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("frozenBalance must be positive"); } if (frozenBalance < TRX_PRECISION) { - throw new ContractValidateException("frozenBalance must be more than 1TRX"); + throw new ContractValidateException("frozenBalance must be greater than or equal to 1 TRX"); } int frozenCount = accountCapsule.getFrozenCount(); @@ -197,7 +197,7 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("frozenCount must be 0 or 1"); } if (frozenBalance > accountCapsule.getBalance()) { - throw new ContractValidateException("frozenBalance must be less than accountBalance"); + throw new ContractValidateException("frozenBalance must be less than or equal to accountBalance"); } long frozenDuration = freezeBalanceContract.getFrozenDuration(); diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java index 90b03e43e1a..f0e5505be9c 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceV2Actuator.java @@ -54,8 +54,8 @@ public boolean execute(Object result) throws ContractExeException { accountCapsule.initializeOldTronPower(); } - long newBalance = accountCapsule.getBalance() - freezeBalanceV2Contract.getFrozenBalance(); long frozenBalance = freezeBalanceV2Contract.getFrozenBalance(); + long newBalance = accountCapsule.getBalance() - frozenBalance; switch (freezeBalanceV2Contract.getResource()) { case BANDWIDTH: @@ -133,11 +133,11 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("frozenBalance must be positive"); } if (frozenBalance < TRX_PRECISION) { - throw new ContractValidateException("frozenBalance must be more than 1TRX"); + throw new ContractValidateException("frozenBalance must be greater than or equal to 1 TRX"); } if (frozenBalance > accountCapsule.getBalance()) { - throw new ContractValidateException("frozenBalance must be less than accountBalance"); + throw new ContractValidateException("frozenBalance must be less than or equal to accountBalance"); } switch (freezeBalanceV2Contract.getResource()) { diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index a99d462b61c..79a09664180 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -10,7 +10,6 @@ import java.util.Arrays; import java.util.Objects; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.ArrayUtils; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; @@ -144,9 +143,8 @@ public boolean execute(Object result) throws ContractExeException { long now = chainBaseManager.getHeadSlot(); if (Objects.nonNull(receiverCapsule) && transferUsage > 0) { - ownerCapsule.setNetUsage(processor.unDelegateIncrease(ownerCapsule, receiverCapsule, - transferUsage, BANDWIDTH, now)); - ownerCapsule.setLatestConsumeTime(now); + processor.unDelegateIncrease(ownerCapsule, receiverCapsule, + transferUsage, BANDWIDTH, now); } } break; @@ -160,9 +158,7 @@ public boolean execute(Object result) throws ContractExeException { long now = chainBaseManager.getHeadSlot(); if (Objects.nonNull(receiverCapsule) && transferUsage > 0) { - ownerCapsule.setEnergyUsage(processor.unDelegateIncrease(ownerCapsule, receiverCapsule, - transferUsage, ENERGY, now)); - ownerCapsule.setLatestConsumeTimeForEnergy(now); + processor.unDelegateIncrease(ownerCapsule, receiverCapsule, transferUsage, ENERGY, now); } } break; @@ -240,7 +236,7 @@ public boolean validate() throws ContractValidateException { } byte[] receiverAddress = unDelegateResourceContract.getReceiverAddress().toByteArray(); - if (ArrayUtils.isEmpty(receiverAddress) || !DecodeUtil.addressValid(receiverAddress)) { + if (!DecodeUtil.addressValid(receiverAddress)) { throw new ContractValidateException("Invalid receiverAddress"); } if (Arrays.equals(receiverAddress, ownerAddress)) { diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java index 45b05ec8bec..fb41c97f7ed 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java @@ -11,6 +11,8 @@ import com.google.common.collect.Lists; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; + +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Objects; @@ -365,19 +367,23 @@ private void updateVote(AccountCapsule accountCapsule, } // Update Owner Voting - votesCapsule.clearNewVotes(); + List addVotes = new ArrayList<>(); for (Vote vote : accountCapsule.getVotesList()) { long newVoteCount = (long) ((double) vote.getVoteCount() / totalVote * ownedTronPower / TRX_PRECISION); if (newVoteCount > 0) { - votesCapsule.addNewVotes(vote.getVoteAddress(), newVoteCount); + Vote newVote = Vote.newBuilder() + .setVoteAddress(vote.getVoteAddress()) + .setVoteCount(newVoteCount) + .build(); + addVotes.add(newVote); } } + votesCapsule.clearNewVotes(); + votesCapsule.addAllNewVotes(addVotes); votesStore.put(ownerAddress, votesCapsule); accountCapsule.clearVotes(); - for (Vote vote : votesCapsule.getNewVotes()) { - accountCapsule.addVotes(vote.getVoteAddress(), vote.getVoteCount()); - } + accountCapsule.addAllVotes(addVotes); } } \ No newline at end of file diff --git a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java index 0c547d2b5a3..fd71ebf1404 100755 --- a/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuator.java @@ -125,8 +125,8 @@ private long getTotalWithdrawUnfreeze(List unfrozenV2List, long now) } private List getTotalWithdrawList(List unfrozenV2List, long now) { - return unfrozenV2List.stream().filter(unfrozenV2 -> (unfrozenV2.getUnfreezeAmount() > 0 - && unfrozenV2.getUnfreezeExpireTime() <= now)).collect(Collectors.toList()); + return unfrozenV2List.stream().filter(unfrozenV2 -> unfrozenV2.getUnfreezeExpireTime() <= now) + .collect(Collectors.toList()); } private List getRemainWithdrawList(List unfrozenV2List, long now) { diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 0e0cc81446c..0f55bbae9b7 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -2,6 +2,7 @@ import static org.tron.core.Constant.DYNAMIC_ENERGY_INCREASE_FACTOR_RANGE; import static org.tron.core.Constant.DYNAMIC_ENERGY_MAX_FACTOR_RANGE; +import static org.tron.core.config.Parameter.ChainConstant.ONE_YEAR_BLOCK_NUMBERS; import org.tron.common.utils.ForkController; import org.tron.core.config.Parameter.ForkBlockVersionConsts; @@ -714,10 +715,11 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, "Bad chain parameter id [MAX_DELEGATE_LOCK_PERIOD]"); } long maxDelegateLockPeriod = dynamicPropertiesStore.getMaxDelegateLockPeriod(); - if (value <= maxDelegateLockPeriod || value > 10512000L) { + if (value <= maxDelegateLockPeriod || value > ONE_YEAR_BLOCK_NUMBERS) { throw new ContractValidateException( "This value[MAX_DELEGATE_LOCK_PERIOD] is only allowed to be greater than " - + maxDelegateLockPeriod + " and less than or equal to 10512000 !"); + + maxDelegateLockPeriod + " and less than or equal to " + ONE_YEAR_BLOCK_NUMBERS + + " !"); } if (dynamicPropertiesStore.getUnfreezeDelayDays() == 0) { throw new ContractValidateException( diff --git a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java index 462a80fa600..7044564b1e1 100644 --- a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java @@ -44,6 +44,7 @@ import org.tron.core.capsule.TransactionCapsule; import org.tron.core.exception.PermissionException; import org.tron.core.exception.SignatureFormatException; +import org.tron.core.store.DynamicPropertiesStore; import org.tron.protos.Protocol.Permission; import org.tron.protos.Protocol.Permission.PermissionType; import org.tron.protos.Protocol.Transaction; @@ -222,7 +223,7 @@ public TransactionSignWeight getTransactionSignWeight(Transaction trx) { } tswBuilder.setPermission(permission); if (trx.getSignatureCount() > 0) { - List approveList = new ArrayList(); + List approveList = new ArrayList<>(); long currentWeight = TransactionCapsule.checkWeight(permission, trx.getSignatureList(), Sha256Hash.hash(CommonParameter.getInstance() .isECKeyCryptoEngine(), trx.getRawData().toByteArray()), approveList); @@ -253,56 +254,24 @@ public TransactionSignWeight getTransactionSignWeight(Transaction trx) { return tswBuilder.build(); } - public static long consumeBandWidthSize( - final TransactionCapsule transactionCapsule, - ChainBaseManager chainBaseManager) { - long bytesSize; - - boolean supportVM = chainBaseManager.getDynamicPropertiesStore().supportVM(); - if (supportVM) { - bytesSize = transactionCapsule.getInstance().toBuilder().clearRet().build().getSerializedSize(); - } else { - bytesSize = transactionCapsule.getSerializedSize(); - } - - List contracts = transactionCapsule.getInstance().getRawData().getContractList(); - for (Transaction.Contract contract : contracts) { - if (contract.getType() == Contract.ContractType.ShieldedTransferContract) { - continue; - } - if (supportVM) { - bytesSize += Constant.MAX_RESULT_SIZE_IN_TX; - } - } - - return bytesSize; - } - - public static long estimateConsumeBandWidthSize(final AccountCapsule ownerCapsule, - ChainBaseManager chainBaseManager) { + public static long estimateConsumeBandWidthSize(DynamicPropertiesStore dps, long balance) { DelegateResourceContract.Builder builder; - if (chainBaseManager.getDynamicPropertiesStore().supportMaxDelegateLockPeriod()) { + if (dps.supportMaxDelegateLockPeriod()) { builder = DelegateResourceContract.newBuilder() - .setLock(true) - .setLockPeriod(chainBaseManager.getDynamicPropertiesStore().getMaxDelegateLockPeriod()) - .setBalance(ownerCapsule.getFrozenV2BalanceForBandwidth()); + .setLock(true) + .setLockPeriod(dps.getMaxDelegateLockPeriod()) + .setBalance(balance); } else { builder = DelegateResourceContract.newBuilder() - .setLock(true) - .setBalance(ownerCapsule.getFrozenV2BalanceForBandwidth()); + .setLock(true) + .setBalance(balance); } - TransactionCapsule fakeTransactionCapsule = new TransactionCapsule(builder.build() - , ContractType.DelegateResourceContract); - long size1 = consumeBandWidthSize(fakeTransactionCapsule, chainBaseManager); - + long builderSize = builder.build().getSerializedSize(); DelegateResourceContract.Builder builder2 = DelegateResourceContract.newBuilder() - .setBalance(TRX_PRECISION); - TransactionCapsule fakeTransactionCapsule2 = new TransactionCapsule(builder2.build() - , ContractType.DelegateResourceContract); - long size2 = consumeBandWidthSize(fakeTransactionCapsule2, chainBaseManager); - long addSize = Math.max(size1 - size2, 0L); + .setBalance(TRX_PRECISION); + long builder2Size = builder2.build().getSerializedSize(); + long addSize = Math.max(builderSize - builder2Size, 0L); return DELEGATE_COST_BASE_SIZE + addSize; } - } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index 18eb543097b..b3772970248 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -3,6 +3,8 @@ import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.core.vm.utils.FreezeV2Util.getV2EnergyUsage; +import static org.tron.core.vm.utils.FreezeV2Util.getV2NetUsage; import com.google.common.primitives.Bytes; import com.google.protobuf.ByteString; @@ -49,7 +51,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra } long delegateBalance = param.getDelegateBalance(); if (delegateBalance < TRX_PRECISION) { - throw new ContractValidateException("delegateBalance must be more than 1TRX"); + throw new ContractValidateException("delegateBalance must be greater than or equal to 1 TRX"); } switch (param.getResourceType()) { @@ -60,16 +62,11 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra long netUsage = (long) (ownerCapsule.getNetUsage() * TRX_PRECISION * ((double) (repo.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); - long remainNetUsage = netUsage - - ownerCapsule.getFrozenBalance() - - ownerCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() - - ownerCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth(); + long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage); - remainNetUsage = Math.max(0, remainNetUsage); - - if (ownerCapsule.getFrozenV2BalanceForBandwidth() - remainNetUsage < delegateBalance) { + if (ownerCapsule.getFrozenV2BalanceForBandwidth() - v2NetUsage < delegateBalance) { throw new ContractValidateException( - "delegateBalance must be less than available FreezeBandwidthV2 balance"); + "delegateBalance must be less than or equal to available FreezeBandwidthV2 balance"); } } break; @@ -81,16 +78,11 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) (repo.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); - long remainEnergyUsage = energyUsage - - ownerCapsule.getEnergyFrozenBalance() - - ownerCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() - - ownerCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy(); - - remainEnergyUsage = Math.max(0, remainEnergyUsage); + long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage); - if (ownerCapsule.getFrozenV2BalanceForEnergy() - remainEnergyUsage < delegateBalance) { + if (ownerCapsule.getFrozenV2BalanceForEnergy() - v2EnergyUsage < delegateBalance) { throw new ContractValidateException( - "delegateBalance must be less than available FreezeEnergyV2 balance"); + "delegateBalance must be less than or equal to available FreezeEnergyV2 balance"); } } break; diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceProcessor.java index c5c8fa91344..3088527ace6 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceProcessor.java @@ -30,9 +30,9 @@ public void validate(FreezeBalanceParam param, Repository repo) throws ContractV if (frozenBalance <= 0) { throw new ContractValidateException("FrozenBalance must be positive"); } else if (frozenBalance < TRX_PRECISION) { - throw new ContractValidateException("FrozenBalance must be more than 1TRX"); + throw new ContractValidateException("FrozenBalance must be greater than or equal to 1 TRX"); } else if (frozenBalance > ownerCapsule.getBalance()) { - throw new ContractValidateException("FrozenBalance must be less than accountBalance"); + throw new ContractValidateException("FrozenBalance must be less than or equal to accountBalance"); } // validate frozen count of owner account diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java index b3dd258ae59..e7e932194ed 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/FreezeBalanceV2Processor.java @@ -37,9 +37,10 @@ public void validate(FreezeBalanceV2Param param, Repository repo) throws Contrac if (frozenBalance <= 0) { throw new ContractValidateException("FrozenBalance must be positive"); } else if (frozenBalance < TRX_PRECISION) { - throw new ContractValidateException("FrozenBalance must be more than 1TRX"); + throw new ContractValidateException("FrozenBalance must be greater than or equal to 1 TRX"); } else if (frozenBalance > ownerCapsule.getBalance()) { - throw new ContractValidateException("FrozenBalance must be less than accountBalance"); + throw new ContractValidateException( + "FrozenBalance must be less than or equal to accountBalance"); } // validate arg @resourceType diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index d4cc2fcb8ce..d521e596e3e 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -10,7 +10,6 @@ import java.util.Arrays; import java.util.Objects; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.ArrayUtils; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.ChainBaseManager; @@ -49,7 +48,7 @@ public void validate(UnDelegateResourceParam param, Repository repo) throws Cont } byte[] receiverAddress = param.getReceiverAddress(); - if (ArrayUtils.isEmpty(receiverAddress) || !DecodeUtil.addressValid(receiverAddress)) { + if (!DecodeUtil.addressValid(receiverAddress)) { throw new ContractValidateException("Invalid receiverAddress"); } if (Arrays.equals(receiverAddress, ownerAddress)) { @@ -103,7 +102,9 @@ public void execute(UnDelegateResourceParam param, Repository repo) { case BANDWIDTH: BandwidthProcessor bandwidthProcessor = new BandwidthProcessor(ChainBaseManager.getInstance()); bandwidthProcessor.updateUsageForDelegated(receiverCapsule); - + /* For example, in a scenario where a regular account can be upgraded to a contract + account through an interface, the account information will be cleared after the + contract suicide, and this account will be converted to a regular account in the future */ if (receiverCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth() < unDelegateBalance) { // A TVM contract suicide, re-create will produce this situation @@ -166,9 +167,8 @@ public void execute(UnDelegateResourceParam param, Repository repo) { BandwidthProcessor processor = new BandwidthProcessor(ChainBaseManager.getInstance()); if (Objects.nonNull(receiverCapsule) && transferUsage > 0) { - ownerCapsule.setNetUsage(processor.unDelegateIncrease(ownerCapsule, receiverCapsule, - transferUsage, BANDWIDTH, now)); - ownerCapsule.setLatestConsumeTime(now); + processor.unDelegateIncrease(ownerCapsule, receiverCapsule, + transferUsage, BANDWIDTH, now); } } break; @@ -181,9 +181,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { EnergyProcessor processor = new EnergyProcessor(dynamicStore, ChainBaseManager.getInstance().getAccountStore()); if (Objects.nonNull(receiverCapsule) && transferUsage > 0) { - ownerCapsule.setEnergyUsage(processor.unDelegateIncrease(ownerCapsule, receiverCapsule, - transferUsage, ENERGY, now)); - ownerCapsule.setLatestConsumeTimeForEnergy(now); + processor.unDelegateIncrease(ownerCapsule, receiverCapsule, transferUsage, ENERGY, now); } } break; diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java index da08a002677..0bcdb10d46f 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/WithdrawExpireUnfreezeProcessor.java @@ -60,8 +60,8 @@ private long getTotalWithdrawUnfreeze(List unfrozen } private List getTotalWithdrawList(List unfrozenV2List, long now) { - return unfrozenV2List.stream().filter(unfrozenV2 -> (unfrozenV2.getUnfreezeAmount() > 0 - && unfrozenV2.getUnfreezeExpireTime() <= now)).collect(Collectors.toList()); + return unfrozenV2List.stream().filter(unfrozenV2 -> unfrozenV2.getUnfreezeExpireTime() <= now) + .collect(Collectors.toList()); } public long execute(WithdrawExpireUnfreezeParam param, Repository repo) throws ContractExeException { diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 90a59f53a36..e02ba225c6b 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -9,6 +9,10 @@ import static org.apache.commons.lang3.ArrayUtils.nullToEmpty; import static org.tron.common.utils.ByteUtil.stripLeadingZeroes; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; +import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; +import static org.tron.protos.contract.Common.ResourceCode.UNRECOGNIZED; import com.google.protobuf.ByteString; import java.math.BigInteger; @@ -556,15 +560,8 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit bandwidthProcessor.updateUsageForDelegated(ownerCapsule); ownerCapsule.setLatestConsumeTime(now); if (ownerCapsule.getNetUsage() > 0) { - long newNetUsage = - bandwidthProcessor.unDelegateIncrease( - inheritorCapsule, - ownerCapsule, - ownerCapsule.getNetUsage(), - Common.ResourceCode.BANDWIDTH, - now); - inheritorCapsule.setNetUsage(newNetUsage); - inheritorCapsule.setLatestConsumeTime(now); + bandwidthProcessor.unDelegateIncrease(inheritorCapsule, ownerCapsule, + ownerCapsule.getNetUsage(), BANDWIDTH, now); } EnergyProcessor energyProcessor = @@ -573,15 +570,8 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit energyProcessor.updateUsage(ownerCapsule); ownerCapsule.setLatestConsumeTimeForEnergy(now); if (ownerCapsule.getEnergyUsage() > 0) { - long newEnergyUsage = - energyProcessor.unDelegateIncrease( - inheritorCapsule, - ownerCapsule, - ownerCapsule.getEnergyUsage(), - Common.ResourceCode.ENERGY, - now); - inheritorCapsule.setEnergyUsage(newEnergyUsage); - inheritorCapsule.setLatestConsumeTimeForEnergy(now); + energyProcessor.unDelegateIncrease(inheritorCapsule, ownerCapsule, + ownerCapsule.getEnergyUsage(), ENERGY, now); } // withdraw expire unfrozen balance @@ -608,9 +598,9 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit private void clearOwnerFreezeV2(AccountCapsule ownerCapsule) { ownerCapsule.clearFrozenV2(); ownerCapsule.setNetUsage(0); - ownerCapsule.setNewWindowSize(Common.ResourceCode.BANDWIDTH, 0); + ownerCapsule.setNewWindowSize(BANDWIDTH, 0); ownerCapsule.setEnergyUsage(0); - ownerCapsule.setNewWindowSize(Common.ResourceCode.ENERGY, 0); + ownerCapsule.setNewWindowSize(ENERGY, 0); ownerCapsule.clearUnfrozenV2(); } @@ -2091,11 +2081,11 @@ public boolean unDelegateResource( private Common.ResourceCode parseResourceCode(DataWord resourceType) { switch (resourceType.intValue()) { case 0: - return Common.ResourceCode.BANDWIDTH; + return BANDWIDTH; case 1: - return Common.ResourceCode.ENERGY; + return ENERGY; default: - return Common.ResourceCode.UNRECOGNIZED; + return UNRECOGNIZED; } } @@ -2104,13 +2094,13 @@ private Common.ResourceCode parseResourceCodeV2(DataWord resourceType) { byte type = resourceType.sValue().byteValueExact(); switch (type) { case 0: - return Common.ResourceCode.BANDWIDTH; + return BANDWIDTH; case 1: - return Common.ResourceCode.ENERGY; + return ENERGY; case 2: - return Common.ResourceCode.TRON_POWER; + return TRON_POWER; default: - return Common.ResourceCode.UNRECOGNIZED; + return UNRECOGNIZED; } } catch (ArithmeticException e) { logger.warn("TVM ParseResourceCodeV2: invalid resource code: {}", resourceType.sValue()); diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index 9a22f796228..7bc760f9edf 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -12,8 +12,6 @@ import org.tron.core.vm.repository.Repository; import org.tron.protos.Protocol; -import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; - public class FreezeV2Util { private FreezeV2Util() { @@ -163,13 +161,8 @@ public static long queryDelegatableResource(byte[] address, long type, Repositor return frozenV2Resource; } - long remainNetUsage = usage - - accountCapsule.getFrozenBalance() - - accountCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() - - accountCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth(); - - remainNetUsage = Math.max(0, remainNetUsage); - return Math.max(0L, frozenV2Resource - remainNetUsage); + long v2NetUsage = getV2NetUsage(accountCapsule, usage); + return Math.max(0L, frozenV2Resource - v2NetUsage); } if (type == 1) { @@ -188,13 +181,8 @@ public static long queryDelegatableResource(byte[] address, long type, Repositor return frozenV2Resource; } - long remainEnergyUsage = usage - - accountCapsule.getEnergyFrozenBalance() - - accountCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() - - accountCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy(); - - remainEnergyUsage = Math.max(0, remainEnergyUsage); - return Math.max(0L, frozenV2Resource - remainEnergyUsage); + long v2EnergyUsage = getV2EnergyUsage(accountCapsule, usage); + return Math.max(0L, frozenV2Resource - v2EnergyUsage); } return 0L; @@ -246,8 +234,24 @@ private static long getTotalWithdrawUnfreeze(List u } private static List getTotalWithdrawList(List unfrozenV2List, long now) { - return unfrozenV2List.stream().filter(unfrozenV2 -> (unfrozenV2.getUnfreezeAmount() > 0 - && unfrozenV2.getUnfreezeExpireTime() <= now)).collect(Collectors.toList()); + return unfrozenV2List.stream().filter(unfrozenV2 -> unfrozenV2.getUnfreezeExpireTime() <= now) + .collect(Collectors.toList()); + } + + public static long getV2NetUsage(AccountCapsule ownerCapsule, long netUsage) { + long v2NetUsage= netUsage + - ownerCapsule.getFrozenBalance() + - ownerCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() + - ownerCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth(); + return Math.max(0, v2NetUsage); + } + + public static long getV2EnergyUsage(AccountCapsule ownerCapsule, long energyUsage) { + long v2EnergyUsage= energyUsage + - ownerCapsule.getEnergyFrozenBalance() + - ownerCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() + - ownerCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy(); + return Math.max(0, v2EnergyUsage); } } diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index 13f3cf576f1..b60fed63cda 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -1452,4 +1452,20 @@ public void setNewWindowSizeV2( ResourceCode resourceCode, long newWindowSize) { } } + public void setUsage(ResourceCode resourceCode, long usage) { + if (resourceCode == BANDWIDTH) { + setNetUsage(usage); + } else { + setEnergyUsage(usage); + } + } + + public void setLatestTime(ResourceCode resourceCode, long time) { + if (resourceCode == BANDWIDTH) { + setLatestConsumeTime(time); + } else { + setLatestConsumeTimeForEnergy(time); + } + } + } diff --git a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java index 87472b6212f..a7a22390958 100644 --- a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java @@ -1,7 +1,5 @@ package org.tron.core.db; -import static java.lang.Math.ceil; -import static java.lang.Math.round; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_PRECISION; @@ -127,16 +125,17 @@ public long increaseV2(AccountCapsule accountCapsule, ResourceCode resourceCode, long remainWindowSize = oldWindowSizeV2 - (now - lastTime) * WINDOW_SIZE_PRECISION; long newWindowSize = divideCeil( - remainUsage * remainWindowSize + usage * this.windowSize * WINDOW_SIZE_PRECISION, newUsage); + remainUsage * remainWindowSize + usage * this.windowSize * WINDOW_SIZE_PRECISION, newUsage); newWindowSize = Math.min(newWindowSize, this.windowSize * WINDOW_SIZE_PRECISION); accountCapsule.setNewWindowSizeV2(resourceCode, newWindowSize); return newUsage; } - public long unDelegateIncrease(AccountCapsule owner, final AccountCapsule receiver, + public void unDelegateIncrease(AccountCapsule owner, final AccountCapsule receiver, long transferUsage, ResourceCode resourceCode, long now) { if (dynamicPropertiesStore.supportAllowCancelAllUnfreezeV2()) { - return unDelegateIncreaseV2(owner, receiver, transferUsage, resourceCode, now); + unDelegateIncreaseV2(owner, receiver, transferUsage, resourceCode, now); + return; } long lastOwnerTime = owner.getLastConsumeTime(resourceCode); long ownerUsage = owner.getUsage(resourceCode); @@ -152,16 +151,19 @@ public long unDelegateIncrease(AccountCapsule owner, final AccountCapsule receiv // mean ownerUsage == 0 and transferUsage == 0 if (newOwnerUsage == 0) { owner.setNewWindowSize(resourceCode, this.windowSize); - return newOwnerUsage; + owner.setUsage(resourceCode, 0); + owner.setLatestTime(resourceCode, now); + return; } // calculate new windowSize long newOwnerWindowSize = getNewWindowSize(ownerUsage, remainOwnerWindowSize, transferUsage, remainReceiverWindowSize, newOwnerUsage); owner.setNewWindowSize(resourceCode, newOwnerWindowSize); - return newOwnerUsage; + owner.setUsage(resourceCode, newOwnerUsage); + owner.setLatestTime(resourceCode, now); } - public long unDelegateIncreaseV2(AccountCapsule owner, final AccountCapsule receiver, + public void unDelegateIncreaseV2(AccountCapsule owner, final AccountCapsule receiver, long transferUsage, ResourceCode resourceCode, long now) { long lastOwnerTime = owner.getLastConsumeTime(resourceCode); long ownerUsage = owner.getUsage(resourceCode); @@ -171,7 +173,9 @@ public long unDelegateIncreaseV2(AccountCapsule owner, final AccountCapsule rece // mean ownerUsage == 0 and transferUsage == 0 if (newOwnerUsage == 0) { owner.setNewWindowSizeV2(resourceCode, this.windowSize * WINDOW_SIZE_PRECISION); - return newOwnerUsage; + owner.setUsage(resourceCode, 0); + owner.setLatestTime(resourceCode, now); + return; } long remainOwnerWindowSizeV2 = owner.getWindowSizeV2(resourceCode); @@ -186,7 +190,8 @@ public long unDelegateIncreaseV2(AccountCapsule owner, final AccountCapsule rece newOwnerUsage); newOwnerWindowSize = Math.min(newOwnerWindowSize, this.windowSize * WINDOW_SIZE_PRECISION); owner.setNewWindowSizeV2(resourceCode, newOwnerWindowSize); - return newOwnerUsage; + owner.setUsage(resourceCode, newOwnerUsage); + owner.setLatestTime(resourceCode, now); } private long getNewWindowSize(long lastUsage, long lastWindowSize, long usage, diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 5f8c9ff89fc..f3059d31558 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -1,5 +1,6 @@ package org.tron.core.store; +import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; import com.google.protobuf.ByteString; @@ -2824,11 +2825,12 @@ public long getMaxDelegateLockPeriod() { return Optional.ofNullable(getUnchecked(MAX_DELEGATE_LOCK_PERIOD)) .map(BytesCapsule::getData) .map(ByteArray::toLong) - .orElse(DELEGATE_PERIOD / 3000); + .orElse(DELEGATE_PERIOD / BLOCK_PRODUCED_INTERVAL); } public boolean supportMaxDelegateLockPeriod() { - return (getMaxDelegateLockPeriod() > DELEGATE_PERIOD / 3000) && getUnfreezeDelayDays() > 0; + return (getMaxDelegateLockPeriod() > DELEGATE_PERIOD / BLOCK_PRODUCED_INTERVAL) && + getUnfreezeDelayDays() > 0; } private static class DynamicResourceProperties { diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index 6bbc66846bd..b1a948e9fdf 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -77,6 +77,7 @@ public class ChainConstant { public static final long TRX_PRECISION = 1000_000L; public static final long DELEGATE_COST_BASE_SIZE = 275L; public static final long WINDOW_SIZE_PRECISION = 1000L; + public static final long ONE_YEAR_BLOCK_NUMBERS = 10512000L; } public class NodeConstant { diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 3560a7032bc..1ddc57fdc8c 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -21,6 +21,7 @@ import static org.tron.common.utils.Commons.getAssetIssueStoreFinal; import static org.tron.common.utils.Commons.getExchangeStoreFinal; import static org.tron.common.utils.WalletUtil.isConstant; +import static org.tron.core.capsule.utils.TransactionUtil.buildInternalTransaction; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import static org.tron.core.config.Parameter.DatabaseConstants.EXCHANGE_COUNT_LIMIT_MAX; @@ -28,6 +29,8 @@ import static org.tron.core.config.Parameter.DatabaseConstants.PROPOSAL_COUNT_LIMIT_MAX; import static org.tron.core.services.jsonrpc.JsonRpcApiUtil.parseEnergyFee; import static org.tron.core.services.jsonrpc.TronJsonRpcImpl.EARLIEST_STR; +import static org.tron.core.vm.utils.FreezeV2Util.getV2EnergyUsage; +import static org.tron.core.vm.utils.FreezeV2Util.getV2NetUsage; import static org.tron.protos.contract.Common.ResourceCode; import com.google.common.collect.ContiguousSet; @@ -152,7 +155,6 @@ import org.tron.core.capsule.TransactionRetCapsule; import org.tron.core.capsule.WitnessCapsule; import org.tron.core.capsule.utils.MarketUtils; -import org.tron.core.capsule.utils.TransactionUtil; import org.tron.core.config.args.Args; import org.tron.core.db.BandwidthProcessor; import org.tron.core.db.BlockIndexStore; @@ -191,6 +193,7 @@ import org.tron.core.store.MarketPairPriceToOrderStore; import org.tron.core.store.MarketPairToPriceStore; import org.tron.core.store.StoreFactory; +import org.tron.core.utils.TransactionUtil; import org.tron.core.vm.program.Program; import org.tron.core.zen.ShieldedTRC20ParametersBuilder; import org.tron.core.zen.ShieldedTRC20ParametersBuilder.ShieldedTRC20ParametersType; @@ -782,6 +785,10 @@ public GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage getCanWithdrawUnfreezeAm ByteString ownerAddress, long timestamp) { GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage.Builder builder = GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage.newBuilder(); + if (timestamp < 0) { + return builder.build(); + } + long canWithdrawUnfreezeAmount; AccountStore accountStore = chainBaseManager.getAccountStore(); @@ -799,13 +806,8 @@ public GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage getCanWithdrawUnfreezeAm long finalTimestamp = timestamp; canWithdrawUnfreezeAmount = unfrozenV2List - .stream() - .filter(unfrozenV2 -> - (unfrozenV2.getUnfreezeAmount() > 0 - && unfrozenV2.getUnfreezeExpireTime() <= finalTimestamp)) - .mapToLong(UnFreezeV2::getUnfreezeAmount) - .sum(); - + .stream().filter(unfrozenV2 -> unfrozenV2.getUnfreezeExpireTime() <= finalTimestamp) + .mapToLong(UnFreezeV2::getUnfreezeAmount).sum(); builder.setAmount(canWithdrawUnfreezeAmount); return builder.build(); @@ -844,13 +846,7 @@ public GrpcAPI.GetAvailableUnfreezeCountResponseMessage getAvailableUnfreezeCoun } long now = dynamicStore.getLatestBlockHeaderTimestamp(); - List unfrozenV2List = accountCapsule.getInstance().getUnfrozenV2List(); - long getUsedUnfreezeCount = unfrozenV2List - .stream() - .filter(unfrozenV2 -> - (unfrozenV2.getUnfreezeAmount() > 0 - && unfrozenV2.getUnfreezeExpireTime() > now)) - .count(); + long getUsedUnfreezeCount = accountCapsule.getUnfreezingV2Count(now); getAvailableUnfreezeCount = UnfreezeBalanceV2Actuator.getUNFREEZE_MAX_TIMES() - getUsedUnfreezeCount; builder.setCount(getAvailableUnfreezeCount); @@ -870,20 +866,15 @@ public long calcCanDelegatedBandWidthMaxSize( processor.updateUsage(ownerCapsule); long accountNetUsage = ownerCapsule.getNetUsage(); - accountNetUsage += org.tron.core.utils.TransactionUtil.estimateConsumeBandWidthSize( - ownerCapsule, chainBaseManager); + accountNetUsage += TransactionUtil.estimateConsumeBandWidthSize(dynamicStore, + ownerCapsule.getBalance()); long netUsage = (long) (accountNetUsage * TRX_PRECISION * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); - long remainNetUsage = netUsage - - ownerCapsule.getFrozenBalance() - - ownerCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() - - ownerCapsule.getAcquiredDelegatedFrozenV2BalanceForBandwidth(); + long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage); - remainNetUsage = Math.max(0, remainNetUsage); - - long maxSize = ownerCapsule.getFrozenV2BalanceForBandwidth() - remainNetUsage; + long maxSize = ownerCapsule.getFrozenV2BalanceForBandwidth() - v2NetUsage; return Math.max(0, maxSize); } @@ -901,14 +892,9 @@ public long calcCanDelegatedEnergyMaxSize(ByteString ownerAddress) { long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); - long remainEnergyUsage = energyUsage - - ownerCapsule.getEnergyFrozenBalance() - - ownerCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() - - ownerCapsule.getAcquiredDelegatedFrozenV2BalanceForEnergy(); - - remainEnergyUsage = Math.max(0, remainEnergyUsage); + long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage); - long maxSize = ownerCapsule.getFrozenV2BalanceForEnergy() - remainEnergyUsage; + long maxSize = ownerCapsule.getFrozenV2BalanceForEnergy() - v2EnergyUsage; return Math.max(0, maxSize); } @@ -3058,7 +3044,7 @@ public Transaction callConstantContract(TransactionCapsule trxCap, result.getLogInfoList().forEach(logInfo -> builder.addLogs(LogInfo.buildLog(logInfo))); result.getInternalTransactions().forEach(it -> - builder.addInternalTransactions(TransactionUtil.buildInternalTransaction(it))); + builder.addInternalTransactions(buildInternalTransaction(it))); ret.setStatus(0, code.SUCESS); if (StringUtils.isNoneEmpty(result.getRuntimeError())) { ret.setStatus(0, code.FAILED); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java index 78096564e48..59df7021249 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -842,20 +842,20 @@ private TVMTestResult unDelegateResource( acquiredBalance = res == 0 ? oldReceiver.getAcquiredDelegatedFrozenV2BalanceForBandwidth() : oldReceiver.getAcquiredDelegatedFrozenV2BalanceForEnergy(); + long unDelegateMaxUsage; if (res == 0) { - long unDelegateMaxUsage = (long) (amount / TRX_PRECISION + unDelegateMaxUsage = (long) (amount / TRX_PRECISION * ((double) (dynamicStore.getTotalNetLimit()) / dynamicStore.getTotalNetWeight())); transferUsage = (long) (oldReceiver.getNetUsage() * ((double) (amount) / oldReceiver.getAllFrozenBalanceForBandwidth())); - transferUsage = Math.min(unDelegateMaxUsage, transferUsage); } else { - long unDelegateMaxUsage = (long) (amount / TRX_PRECISION + unDelegateMaxUsage = (long) (amount / TRX_PRECISION * ((double) (dynamicStore.getTotalEnergyCurrentLimit()) / dynamicStore.getTotalEnergyWeight())); transferUsage = (long) (oldReceiver.getEnergyUsage() * ((double) (amount) / oldReceiver.getAllFrozenBalanceForEnergy())); - transferUsage = Math.min(unDelegateMaxUsage, transferUsage); } + transferUsage = Math.min(unDelegateMaxUsage, transferUsage); } DelegatedResourceStore delegatedResourceStore = manager.getDelegatedResourceStore(); @@ -1002,28 +1002,18 @@ private TVMTestResult suicide(byte[] callerAddr, byte[] contractAddr, byte[] inh newInheritor.getFrozenBalance() - oldInheritorFrozenBalance); if (oldInheritor != null) { if (oldContract.getNetUsage() > 0) { - long expectedNewNetUsage = - bandwidthProcessor.unDelegateIncrease( - oldInheritor, - oldContract, - oldContract.getNetUsage(), - Common.ResourceCode.BANDWIDTH, - now); + bandwidthProcessor.unDelegateIncrease(oldInheritor, oldContract, oldContract.getNetUsage(), + Common.ResourceCode.BANDWIDTH, now); Assert.assertEquals( - expectedNewNetUsage, newInheritor.getNetUsage() - oldInheritorBandwidthUsage); + oldInheritor.getNetUsage(), newInheritor.getNetUsage() - oldInheritorBandwidthUsage); Assert.assertEquals( ChainBaseManager.getInstance().getHeadSlot(), newInheritor.getLatestConsumeTime()); } if (oldContract.getEnergyUsage() > 0) { - long expectedNewEnergyUsage = - energyProcessor.unDelegateIncrease( - oldInheritor, - oldContract, - oldContract.getEnergyUsage(), - Common.ResourceCode.ENERGY, - now); + energyProcessor.unDelegateIncrease(oldInheritor, oldContract, + oldContract.getEnergyUsage(), Common.ResourceCode.ENERGY, now); Assert.assertEquals( - expectedNewEnergyUsage, newInheritor.getEnergyUsage() - oldInheritorEnergyUsage); + oldInheritor.getEnergyUsage(), newInheritor.getEnergyUsage() - oldInheritorEnergyUsage); Assert.assertEquals( ChainBaseManager.getInstance().getHeadSlot(), newInheritor.getLatestConsumeTimeForEnergy()); diff --git a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java index b20d55fd983..f49f39baabd 100644 --- a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java @@ -1,6 +1,9 @@ package org.tron.core.actuator; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -13,7 +16,6 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.tron.common.BaseTest; @@ -179,7 +181,8 @@ public void testDelegateResourceWithNoFreeze() { actuator.execute(ret); fail("cannot run here."); } catch (ContractValidateException e) { - assertEquals("delegateBalance must be less than available FreezeBandwidthV2 balance", + assertEquals( + "delegateBalance must be less than or equal to available FreezeBandwidthV2 balance", e.getMessage()); } catch (ContractExeException e) { fail(); @@ -193,7 +196,7 @@ public void testDelegateResourceWithNoFreeze() { fail("cannot run here."); } catch (ContractValidateException e) { assertEquals( - "delegateBalance must be less than available FreezeEnergyV2 balance", + "delegateBalance must be less than or equal to available FreezeEnergyV2 balance", e.getMessage()); } catch (ContractExeException e) { fail(e.getMessage()); @@ -222,7 +225,8 @@ public void testDelegateBandwidthWithUsage() { actuator.execute(ret); fail("cannot run here."); } catch (ContractValidateException e) { - assertEquals("delegateBalance must be less than available FreezeBandwidthV2 balance", + assertEquals( + "delegateBalance must be less than or equal to available FreezeBandwidthV2 balance", e.getMessage()); } catch (ContractExeException e) { fail(e.getMessage()); @@ -252,7 +256,7 @@ public void testDelegateCpuWithUsage() { fail("cannot run here."); } catch (ContractValidateException e) { assertEquals( - "delegateBalance must be less than available FreezeEnergyV2 balance", + "delegateBalance must be less than or equal to available FreezeEnergyV2 balance", e.getMessage()); } catch (ContractExeException e) { fail(e.getMessage()); @@ -407,9 +411,9 @@ public void testLockedDelegateResourceForBandwidth() { .get(DelegatedResourceCapsule .createDbKeyV2(ByteArray.fromHexString(OWNER_ADDRESS), ByteArray.fromHexString(RECEIVER_ADDRESS), true)); - Assert.assertNull(delegatedResourceCapsule); - Assert.assertNotNull(lockedResourceCapsule); - Assert.assertNotEquals(0, lockedResourceCapsule.getExpireTimeForBandwidth()); + assertNull(delegatedResourceCapsule); + assertNotNull(lockedResourceCapsule); + assertNotEquals(0, lockedResourceCapsule.getExpireTimeForBandwidth()); assertEquals(delegateBalance, lockedResourceCapsule.getFrozenBalanceForBandwidth()); long totalNetWeightAfter = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); assertEquals(totalNetWeightBefore, totalNetWeightAfter); @@ -662,7 +666,8 @@ public void delegateLessThanZero() { actuator.execute(ret); fail("cannot run here."); } catch (ContractValidateException e) { - assertEquals("delegateBalance must be more than 1TRX", e.getMessage()); + assertEquals("delegateBalance must be greater than or equal to 1 TRX", + e.getMessage()); } catch (ContractExeException e) { fail(e.getMessage()); } @@ -700,7 +705,8 @@ public void delegateMoreThanBalance() { actuator.execute(ret); fail("cannot run here."); } catch (ContractValidateException e) { - assertEquals("delegateBalance must be less than available FreezeBandwidthV2 balance", + assertEquals( + "delegateBalance must be less than or equal to available FreezeBandwidthV2 balance", e.getMessage()); } catch (ContractExeException e) { fail(e.getMessage()); diff --git a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java index abcaf538e93..c66a86fe58c 100644 --- a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java @@ -137,7 +137,7 @@ public void testFreezeBalanceForBandwidth() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule owner = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); @@ -145,10 +145,8 @@ public void testFreezeBalanceForBandwidth() { - TRANSFER_FEE); Assert.assertEquals(owner.getFrozenBalance(), frozenBalance); Assert.assertEquals(frozenBalance, owner.getTronPower()); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -164,7 +162,7 @@ public void testFreezeBalanceForEnergy() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule owner = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); @@ -173,10 +171,8 @@ public void testFreezeBalanceForEnergy() { Assert.assertEquals(0L, owner.getFrozenBalance()); Assert.assertEquals(frozenBalance, owner.getEnergyFrozenBalance()); Assert.assertEquals(frozenBalance, owner.getTronPower()); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -206,9 +202,9 @@ public void testFreezeDelegatedBalanceForBandwidthWithContractAddress() { actuator.validate(); actuator.execute(ret); } catch (ContractValidateException e) { - Assert.assertEquals(e.getMessage(), "Do not allow delegate resources to contract addresses"); + Assert.assertEquals("Do not allow delegate resources to contract addresses", e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } } @@ -227,7 +223,7 @@ public void testFreezeDelegatedBalanceForBandwidth() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule owner = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); @@ -258,9 +254,8 @@ public void testFreezeDelegatedBalanceForBandwidth() { Assert .assertEquals(0, delegatedResourceAccountIndexCapsuleOwner.getFromAccountsList().size()); Assert.assertEquals(1, delegatedResourceAccountIndexCapsuleOwner.getToAccountsList().size()); - Assert.assertEquals(true, - delegatedResourceAccountIndexCapsuleOwner.getToAccountsList() - .contains(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)))); + Assert.assertTrue(delegatedResourceAccountIndexCapsuleOwner.getToAccountsList() + .contains(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)))); DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsuleReceiver = dbManager .getDelegatedResourceAccountIndexStore().get(ByteArray.fromHexString(RECEIVER_ADDRESS)); @@ -269,15 +264,12 @@ public void testFreezeDelegatedBalanceForBandwidth() { Assert .assertEquals(1, delegatedResourceAccountIndexCapsuleReceiver.getFromAccountsList().size()); - Assert.assertEquals(true, - delegatedResourceAccountIndexCapsuleReceiver.getFromAccountsList() - .contains(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)))); + Assert.assertTrue(delegatedResourceAccountIndexCapsuleReceiver.getFromAccountsList() + .contains(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)))); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -359,7 +351,7 @@ public void testFreezeDelegatedBalanceForCpuSameNameTokenActive() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule owner = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); @@ -394,9 +386,8 @@ public void testFreezeDelegatedBalanceForCpuSameNameTokenActive() { Assert .assertEquals(0, delegatedResourceAccountIndexCapsuleOwner.getFromAccountsList().size()); Assert.assertEquals(1, delegatedResourceAccountIndexCapsuleOwner.getToAccountsList().size()); - Assert.assertEquals(true, - delegatedResourceAccountIndexCapsuleOwner.getToAccountsList() - .contains(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)))); + Assert.assertTrue(delegatedResourceAccountIndexCapsuleOwner.getToAccountsList() + .contains(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)))); DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsuleReceiver = dbManager .getDelegatedResourceAccountIndexStore().get(ByteArray.fromHexString(RECEIVER_ADDRESS)); @@ -405,14 +396,11 @@ public void testFreezeDelegatedBalanceForCpuSameNameTokenActive() { Assert .assertEquals(1, delegatedResourceAccountIndexCapsuleReceiver.getFromAccountsList().size()); - Assert.assertEquals(true, - delegatedResourceAccountIndexCapsuleReceiver.getFromAccountsList() - .contains(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)))); + Assert.assertTrue(delegatedResourceAccountIndexCapsuleReceiver.getFromAccountsList() + .contains(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)))); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -430,7 +418,7 @@ public void testFreezeDelegatedBalanceForCpuSameNameTokenClose() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule owner = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); Assert.assertEquals(owner.getBalance(), initBalance - frozenBalance @@ -450,10 +438,8 @@ public void testFreezeDelegatedBalanceForCpuSameNameTokenClose() { Assert.assertEquals(totalEnergyWeightBefore + frozenBalance / 1000_000L, totalEnergyWeightAfter); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -471,10 +457,9 @@ public void freezeLessThanZero() { fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("frozenBalance must be positive", e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } } @@ -492,10 +477,10 @@ public void freezeMoreThanBalance() { actuator.execute(ret); fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); - Assert.assertEquals("frozenBalance must be less than accountBalance", e.getMessage()); + Assert.assertEquals( + "frozenBalance must be less than or equal to accountBalance", e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } } @@ -514,12 +499,9 @@ public void invalidOwnerAddress() { fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); - Assert.assertEquals("Invalid address", e.getMessage()); - } catch (ContractExeException e) { - Assert.assertTrue(e instanceof ContractExeException); + Assert.fail(); } } @@ -538,11 +520,10 @@ public void invalidOwnerAccount() { actuator.execute(ret); fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Account[" + OWNER_ACCOUNT_INVALID + "] not exists", e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } } @@ -563,11 +544,10 @@ public void durationLessThanMin() { } catch (ContractValidateException e) { long minFrozenTime = dbManager.getDynamicPropertiesStore().getMinFrozenTime(); long maxFrozenTime = dbManager.getDynamicPropertiesStore().getMaxFrozenTime(); - Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("frozenDuration must be less than " + maxFrozenTime + " days " + "and more than " + minFrozenTime + " days", e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } } @@ -587,11 +567,10 @@ public void durationMoreThanMax() { } catch (ContractValidateException e) { long minFrozenTime = dbManager.getDynamicPropertiesStore().getMinFrozenTime(); long maxFrozenTime = dbManager.getDynamicPropertiesStore().getMaxFrozenTime(); - Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("frozenDuration must be less than " + maxFrozenTime + " days " + "and more than " + minFrozenTime + " days", e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } } @@ -609,10 +588,10 @@ public void lessThan1TrxTest() { actuator.execute(ret); fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); - Assert.assertEquals("frozenBalance must be more than 1TRX", e.getMessage()); + Assert.assertEquals("frozenBalance must be greater than or equal to 1 TRX", + e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } } @@ -636,10 +615,9 @@ public void frozenNumTest() { actuator.execute(ret); fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("frozenCount must be 0 or 1", e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } } @@ -655,10 +633,8 @@ public void moreThanFrozenNumber() { try { actuator.validate(); actuator.execute(ret); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } try { actuator.validate(); @@ -666,11 +642,10 @@ public void moreThanFrozenNumber() { fail("cannot run here."); } catch (ContractValidateException e) { long maxFrozenNumber = ChainConstant.MAX_FROZEN_NUMBER; - Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("max frozen number is: " + maxFrozenNumber, e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } } @@ -711,16 +686,14 @@ public void testFreezeBalanceForEnergyWithoutOldTronPowerAfterNewResourceModel() try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule owner = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); Assert.assertEquals(-1L, owner.getInstance().getOldTronPower()); Assert.assertEquals(0L, owner.getAllTronPower()); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -744,16 +717,14 @@ public void testFreezeBalanceForEnergyWithOldTronPowerAfterNewResourceModel() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); owner = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); Assert.assertEquals(100L, owner.getInstance().getOldTronPower()); Assert.assertEquals(100L, owner.getAllTronPower()); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -777,18 +748,15 @@ public void testFreezeBalanceForTronPowerWithOldTronPowerAfterNewResourceModel() try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); owner = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); Assert.assertEquals(100L, owner.getInstance().getOldTronPower()); Assert.assertEquals(frozenBalance + 100L, owner.getAllTronPower()); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } - } diff --git a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java index 082338df753..1e6039c3e69 100644 --- a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java @@ -129,7 +129,7 @@ public void testFreezeBalanceForBandwidth() { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule owner = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); @@ -137,10 +137,8 @@ public void testFreezeBalanceForBandwidth() { - TRANSFER_FEE); Assert.assertEquals(owner.getFrozenV2BalanceForBandwidth(), frozenBalance); Assert.assertEquals(frozenBalance, owner.getTronPower()); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -155,7 +153,7 @@ public void testFreezeBalanceForEnergy() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule owner = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); @@ -164,10 +162,8 @@ public void testFreezeBalanceForEnergy() { Assert.assertEquals(0L, owner.getAllFrozenBalanceForBandwidth()); Assert.assertEquals(frozenBalance, owner.getAllFrozenBalanceForEnergy()); Assert.assertEquals(frozenBalance, owner.getTronPower()); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -185,10 +181,9 @@ public void freezeLessThanZero() { fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("frozenBalance must be positive", e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } } @@ -205,10 +200,10 @@ public void freezeMoreThanBalance() { actuator.execute(ret); fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); - Assert.assertEquals("frozenBalance must be less than accountBalance", e.getMessage()); + Assert.assertEquals("frozenBalance must be less than or equal to accountBalance", + e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } } @@ -226,12 +221,9 @@ public void invalidOwnerAddress() { fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); - Assert.assertEquals("Invalid address", e.getMessage()); - } catch (ContractExeException e) { - Assert.assertTrue(e instanceof ContractExeException); + Assert.fail(); } } @@ -249,11 +241,10 @@ public void invalidOwnerAccount() { actuator.execute(ret); fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Account[" + OWNER_ACCOUNT_INVALID + "] not exists", e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } } @@ -270,10 +261,10 @@ public void lessThan1TrxTest() { actuator.execute(ret); fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); - Assert.assertEquals("frozenBalance must be more than 1TRX", e.getMessage()); + Assert.assertEquals("frozenBalance must be greater than or equal to 1 TRX", + e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } } @@ -288,10 +279,8 @@ public void moreThanFrozenNumber() { try { actuator.validate(); actuator.execute(ret); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } try { actuator.validate(); @@ -299,11 +288,9 @@ public void moreThanFrozenNumber() { fail("cannot run here."); } catch (ContractValidateException e) { long maxFrozenNumber = ChainConstant.MAX_FROZEN_NUMBER; - Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("max frozen number is: " + maxFrozenNumber, e.getMessage()); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } } @@ -343,16 +330,14 @@ public void testFreezeBalanceForEnergyWithoutOldTronPowerAfterNewResourceModel() try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule owner = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); Assert.assertEquals(-1L, owner.getInstance().getOldTronPower()); Assert.assertEquals(0L, owner.getAllTronPower()); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -360,7 +345,6 @@ public void testFreezeBalanceForEnergyWithoutOldTronPowerAfterNewResourceModel() @Test public void testFreezeBalanceForEnergyWithOldTronPowerAfterNewResourceModel() { long frozenBalance = 1_000_000_000L; - long duration = 3; FreezeBalanceV2Actuator actuator = new FreezeBalanceV2Actuator(); ChainBaseManager chainBaseManager = dbManager.getChainBaseManager(); chainBaseManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); @@ -377,16 +361,14 @@ public void testFreezeBalanceForEnergyWithOldTronPowerAfterNewResourceModel() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); owner = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); Assert.assertEquals(100L, owner.getInstance().getOldTronPower()); Assert.assertEquals(100L, owner.getAllTronPower()); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -409,19 +391,16 @@ public void testFreezeBalanceForTronPowerWithOldTronPowerAfterNewResourceModel() try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); owner = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); Assert.assertEquals(100L, owner.getInstance().getOldTronPower()); Assert.assertEquals(100L, owner.getTronPower()); Assert.assertEquals(frozenBalance + 100, owner.getAllTronPower()); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } - } diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java index 3f9b999228c..77e70f6762e 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java @@ -110,8 +110,8 @@ public void testUnfreezeBalanceForBandwidth() { AccountCapsule accountCapsule = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); accountCapsule.setFrozen(frozenBalance, now); - Assert.assertEquals(accountCapsule.getFrozenBalance(), frozenBalance); - Assert.assertEquals(accountCapsule.getTronPower(), frozenBalance); + Assert.assertEquals(frozenBalance, accountCapsule.getFrozenBalance()); + Assert.assertEquals(frozenBalance, accountCapsule.getTronPower()); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); UnfreezeBalanceActuator actuator = new UnfreezeBalanceActuator(); @@ -124,22 +124,20 @@ public void testUnfreezeBalanceForBandwidth() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule owner = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); Assert.assertEquals(owner.getBalance(), initBalance + frozenBalance); - Assert.assertEquals(owner.getFrozenBalance(), 0); - Assert.assertEquals(owner.getTronPower(), 0L); + Assert.assertEquals(0, owner.getFrozenBalance()); + Assert.assertEquals(0L, owner.getTronPower()); long totalNetWeightAfter = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); Assert.assertEquals(totalNetWeightBefore, totalNetWeightAfter + frozenBalance / 1000_000L); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -204,12 +202,12 @@ public void testUnfreezeSelfAndOthersForBandwidth() { actuator1.execute(ret1); long afterWeight1 = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); Assert.assertEquals(1, afterWeight1); - Assert.assertEquals(ret1.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret1.getInstance().getRet()); } catch (ContractValidateException e) { logger.error("ContractValidateException", e); - Assert.assertFalse(e instanceof ContractValidateException); + Assert.fail(); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } UnfreezeBalanceActuator actuator = new UnfreezeBalanceActuator(); @@ -222,11 +220,9 @@ public void testUnfreezeSelfAndOthersForBandwidth() { actuator.execute(ret); long afterWeight = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); Assert.assertEquals(0, afterWeight); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } dbManager.getDynamicPropertiesStore().saveAllowNewReward(0); } @@ -240,8 +236,8 @@ public void testUnfreezeBalanceForEnergy() { AccountCapsule accountCapsule = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); accountCapsule.setFrozenForEnergy(frozenBalance, now); - Assert.assertEquals(accountCapsule.getAllFrozenBalanceForEnergy(), frozenBalance); - Assert.assertEquals(accountCapsule.getTronPower(), frozenBalance); + Assert.assertEquals(frozenBalance, accountCapsule.getAllFrozenBalanceForEnergy()); + Assert.assertEquals(frozenBalance, accountCapsule.getTronPower()); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); UnfreezeBalanceActuator actuator = new UnfreezeBalanceActuator(); @@ -253,20 +249,18 @@ public void testUnfreezeBalanceForEnergy() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule owner = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); Assert.assertEquals(owner.getBalance(), initBalance + frozenBalance); - Assert.assertEquals(owner.getEnergyFrozenBalance(), 0); - Assert.assertEquals(owner.getTronPower(), 0L); + Assert.assertEquals(0, owner.getEnergyFrozenBalance()); + Assert.assertEquals(0L, owner.getTronPower()); long totalEnergyWeightAfter = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); Assert.assertEquals(totalEnergyWeightBefore, totalEnergyWeightAfter + frozenBalance / 1000_000L); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -325,7 +319,7 @@ public void testUnfreezeDelegatedBalanceForBandwidth() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule ownerResult = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); @@ -352,10 +346,8 @@ public void testUnfreezeDelegatedBalanceForBandwidth() { Assert.assertEquals(0, delegatedResourceAccountIndexCapsuleReceiver.getFromAccountsList().size()); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -419,17 +411,18 @@ public void testUnfreezeDelegatedBalanceForBandwidthWithDeletedReceiver() { actuator.execute(ret); Assert.fail(); } catch (ContractValidateException e) { - Assert.assertEquals(e.getMessage(), - "Receiver Account[a0abd4b9367799eaa3197fecb144eb71de1e049150] does not exist"); + Assert.assertEquals( + "Receiver Account[a0abd4b9367799eaa3197fecb144eb71de1e049150] does not exist", + e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } dbManager.getDynamicPropertiesStore().saveAllowTvmConstantinople(1); try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule ownerResult = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); @@ -453,11 +446,8 @@ public void testUnfreezeDelegatedBalanceForBandwidthWithDeletedReceiver() { Assert.assertEquals(0, delegatedResourceAccountIndexCapsuleReceiver.getFromAccountsList().size()); - } catch (ContractValidateException e) { - logger.error("", e); - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -532,10 +522,11 @@ public void testUnfreezeDelegatedBalanceForBandwidthWithRecreatedReceiver() { actuator.execute(ret); Assert.fail(); } catch (ContractValidateException e) { - Assert.assertEquals(e.getMessage(), - "AcquiredDelegatedFrozenBalanceForBandwidth[10] < delegatedBandwidth[1000000000]"); + Assert.assertEquals( + "AcquiredDelegatedFrozenBalanceForBandwidth[10] < delegatedBandwidth[1000000000]", + e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } dbManager.getDynamicPropertiesStore().saveAllowShieldedTransaction(1); @@ -543,7 +534,7 @@ public void testUnfreezeDelegatedBalanceForBandwidthWithRecreatedReceiver() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule ownerResult = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); @@ -638,10 +629,9 @@ public void testUnfreezeDelegatedBalanceForBandwidthSameTokenNameClose() { actuator.execute(ret); fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("no frozenBalance(BANDWIDTH)", e.getMessage()); } catch (ContractExeException e) { - Assert.assertTrue(e instanceof ContractExeException); + Assert.fail(); } } @@ -678,7 +668,7 @@ public void testUnfreezeDelegatedBalanceForCpu() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule ownerResult = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); @@ -689,11 +679,8 @@ public void testUnfreezeDelegatedBalanceForCpu() { Assert.assertEquals(0L, ownerResult.getTronPower()); Assert.assertEquals(0L, ownerResult.getDelegatedFrozenBalanceForEnergy()); Assert.assertEquals(0L, receiverResult.getAllFrozenBalanceForEnergy()); - } catch (ContractValidateException e) { - logger.error("", e); - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -734,10 +721,11 @@ public void testUnfreezeDelegatedBalanceForCpuWithDeletedReceiver() { actuator.execute(ret); Assert.fail(); } catch (ContractValidateException e) { - Assert.assertEquals(e.getMessage(), - "Receiver Account[a0abd4b9367799eaa3197fecb144eb71de1e049150] does not exist"); + Assert.assertEquals( + "Receiver Account[a0abd4b9367799eaa3197fecb144eb71de1e049150] does not exist", + e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } dbManager.getDynamicPropertiesStore().saveAllowTvmConstantinople(1); @@ -745,17 +733,15 @@ public void testUnfreezeDelegatedBalanceForCpuWithDeletedReceiver() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule ownerResult = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); Assert.assertEquals(initBalance + frozenBalance, ownerResult.getBalance()); Assert.assertEquals(0L, ownerResult.getTronPower()); Assert.assertEquals(0L, ownerResult.getDelegatedFrozenBalanceForEnergy()); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -809,10 +795,11 @@ public void testUnfreezeDelegatedBalanceForCpuWithRecreatedReceiver() { actuator.execute(ret); Assert.fail(); } catch (ContractValidateException e) { - Assert.assertEquals(e.getMessage(), - "AcquiredDelegatedFrozenBalanceForEnergy[10] < delegatedEnergy[1000000000]"); + Assert.assertEquals( + "AcquiredDelegatedFrozenBalanceForEnergy[10] < delegatedEnergy[1000000000]", + e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } dbManager.getDynamicPropertiesStore().saveAllowShieldedTransaction(1); @@ -821,7 +808,7 @@ public void testUnfreezeDelegatedBalanceForCpuWithRecreatedReceiver() { try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule ownerResult = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); @@ -830,9 +817,7 @@ public void testUnfreezeDelegatedBalanceForCpuWithRecreatedReceiver() { Assert.assertEquals(0L, ownerResult.getDelegatedFrozenBalanceForEnergy()); receiver = dbManager.getAccountStore().get(receiver.createDbKey()); Assert.assertEquals(0, receiver.getAcquiredDelegatedFrozenBalanceForEnergy()); - } catch (ContractValidateException e) { - Assert.fail(); - } catch (ContractExeException e) { + } catch (ContractValidateException | ContractExeException e) { Assert.fail(); } } @@ -856,12 +841,9 @@ public void invalidOwnerAddress() { fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); - Assert.assertEquals("Invalid address", e.getMessage()); - } catch (ContractExeException e) { - Assert.assertTrue(e instanceof ContractExeException); + Assert.fail(); } } @@ -884,11 +866,10 @@ public void invalidOwnerAccount() { actuator.execute(ret); fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Account[" + OWNER_ACCOUNT_INVALID + "] does not exist", e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } } @@ -904,10 +885,9 @@ public void noFrozenBalance() { fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("no frozenBalance(BANDWIDTH)", e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } } @@ -930,17 +910,15 @@ public void notTimeToUnfreeze() { fail("cannot run here."); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("It's not time to unfreeze(BANDWIDTH).", e.getMessage()); } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + Assert.fail(); } } @Test public void testClearVotes() { byte[] ownerAddressBytes = ByteArray.fromHexString(OWNER_ADDRESS); - ByteString ownerAddress = ByteString.copyFrom(ownerAddressBytes); long now = System.currentTimeMillis(); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); @@ -960,14 +938,12 @@ public void testClearVotes() { VotesCapsule votesCapsule = dbManager.getVotesStore().get(ownerAddressBytes); Assert.assertNotNull(votesCapsule); Assert.assertEquals(0, votesCapsule.getNewVotes().size()); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } // if had votes - List oldVotes = new ArrayList(); + List oldVotes = new ArrayList<>(); VotesCapsule votesCapsule = new VotesCapsule( ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), oldVotes); votesCapsule.addNewVotes(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), @@ -981,10 +957,8 @@ public void testClearVotes() { votesCapsule = dbManager.getVotesStore().get(ownerAddressBytes); Assert.assertNotNull(votesCapsule); Assert.assertEquals(0, votesCapsule.getNewVotes().size()); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -1063,8 +1037,8 @@ public void commonErrorCheck() { AccountCapsule accountCapsule = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); accountCapsule.setFrozen(frozenBalance, now); - Assert.assertEquals(accountCapsule.getFrozenBalance(), frozenBalance); - Assert.assertEquals(accountCapsule.getTronPower(), frozenBalance); + Assert.assertEquals(frozenBalance, accountCapsule.getFrozenBalance()); + Assert.assertEquals(frozenBalance, accountCapsule.getTronPower()); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); @@ -1087,7 +1061,7 @@ public void testUnfreezeBalanceForEnergyWithOldTronPowerAfterNewResourceModel() accountCapsule.setFrozenForEnergy(frozenBalance, now); accountCapsule.setOldTronPower(frozenBalance); accountCapsule.addVotes(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), 100L); - Assert.assertEquals(accountCapsule.getAllFrozenBalanceForEnergy(), frozenBalance); + Assert.assertEquals(frozenBalance, accountCapsule.getAllFrozenBalanceForEnergy()); dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); UnfreezeBalanceActuator actuator = new UnfreezeBalanceActuator(); @@ -1098,16 +1072,14 @@ public void testUnfreezeBalanceForEnergyWithOldTronPowerAfterNewResourceModel() try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule owner = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); - Assert.assertEquals(owner.getVotesList().size(), 0L); + Assert.assertEquals(0L, owner.getVotesList().size()); Assert.assertEquals(owner.getInstance().getOldTronPower(), -1L); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -1133,16 +1105,14 @@ public void testUnfreezeBalanceForEnergyWithoutOldTronPowerAfterNewResourceModel try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule owner = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); - Assert.assertEquals(owner.getVotesList().size(), 1L); + Assert.assertEquals(1L, owner.getVotesList().size()); Assert.assertEquals(owner.getInstance().getOldTronPower(), -1L); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -1168,16 +1138,14 @@ public void testUnfreezeBalanceForTronPowerWithOldTronPowerAfterNewResourceModel try { actuator.validate(); actuator.execute(ret); - Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + Assert.assertEquals(code.SUCESS, ret.getInstance().getRet()); AccountCapsule owner = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); - Assert.assertEquals(owner.getVotesList().size(), 0L); + Assert.assertEquals(0L, owner.getVotesList().size()); Assert.assertEquals(owner.getInstance().getOldTronPower(), -1L); - } catch (ContractValidateException e) { - Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail(); } } @@ -1198,13 +1166,12 @@ public void testUnfreezeBalanceForTronPowerWithOldTronPowerAfterNewResourceModel UnfreezeBalanceActuator actuator = new UnfreezeBalanceActuator(); actuator.setChainBaseManager(dbManager.getChainBaseManager()) .setAny(getContractForTronPower(OWNER_ADDRESS)); - TransactionResultCapsule ret = new TransactionResultCapsule(); try { actuator.validate(); Assert.fail(); } catch (ContractValidateException e) { - Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("It's not time to unfreeze(TronPower).", e.getMessage()); } } diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java index 14a6de98606..db2a78b1623 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java @@ -629,8 +629,7 @@ public void testUnfreezeBalanceCalcUnfreezeExpireTime() { .build(); long ret = actuator.calcUnfreezeExpireTime(now); - - Assert.assertTrue(true); + Assert.assertTrue(ret > 0); } @Test diff --git a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java index 0baaad7c962..7d737870e58 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java @@ -4,7 +4,9 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.tron.core.capsule.utils.TransactionUtil.isNumber; +import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_COST_BASE_SIZE; import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import static org.tron.core.utils.TransactionUtil.validAccountId; import static org.tron.core.utils.TransactionUtil.validAccountName; import static org.tron.core.utils.TransactionUtil.validAssetName; @@ -12,19 +14,27 @@ import com.google.protobuf.ByteString; import java.nio.charset.StandardCharsets; +import java.util.List; import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; +import org.tron.core.ChainBaseManager; 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.core.store.DynamicPropertiesStore; import org.tron.core.utils.TransactionUtil; +import org.tron.protos.Protocol; import org.tron.protos.Protocol.AccountType; - +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.contract.BalanceContract.DelegateResourceContract; @Slf4j(topic = "capsule") public class TransactionUtilTest extends BaseTest { @@ -39,7 +49,6 @@ public static void init() { dbPath = "output_transactionUtil_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; - } @Before @@ -55,6 +64,82 @@ public void setUp() { dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); } + // only for testing + public static long consumeBandWidthSize( + final TransactionCapsule transactionCapsule, + ChainBaseManager chainBaseManager) { + long bs; + + boolean supportVM = chainBaseManager.getDynamicPropertiesStore().supportVM(); + if (supportVM) { + bs = transactionCapsule.getInstance().toBuilder().clearRet().build().getSerializedSize(); + } else { + bs = transactionCapsule.getSerializedSize(); + } + + List contracts = transactionCapsule.getInstance().getRawData() + .getContractList(); + for (Transaction.Contract contract : contracts) { + if (contract.getType() == Transaction.Contract.ContractType.ShieldedTransferContract) { + continue; + } + if (supportVM) { + bs += Constant.MAX_RESULT_SIZE_IN_TX; + } + } + + return bs; + } + + // only for testing + public static long estimateConsumeBandWidthSize(final AccountCapsule ownerCapsule, + ChainBaseManager chainBaseManager) { + DelegateResourceContract.Builder builder; + if (chainBaseManager.getDynamicPropertiesStore().supportMaxDelegateLockPeriod()) { + builder = DelegateResourceContract.newBuilder() + .setLock(true) + .setLockPeriod(chainBaseManager.getDynamicPropertiesStore().getMaxDelegateLockPeriod()) + .setBalance(ownerCapsule.getFrozenV2BalanceForBandwidth()); + } else { + builder = DelegateResourceContract.newBuilder() + .setLock(true) + .setBalance(ownerCapsule.getFrozenV2BalanceForBandwidth()); + } + TransactionCapsule fakeTransactionCapsule = new TransactionCapsule(builder.build(), + ContractType.DelegateResourceContract); + long size1 = consumeBandWidthSize(fakeTransactionCapsule, chainBaseManager); + + DelegateResourceContract.Builder builder2 = DelegateResourceContract.newBuilder() + .setBalance(TRX_PRECISION); + TransactionCapsule fakeTransactionCapsule2 = new TransactionCapsule(builder2.build(), + ContractType.DelegateResourceContract); + long size2 = consumeBandWidthSize(fakeTransactionCapsule2, chainBaseManager); + long addSize = Math.max(size1 - size2, 0L); + + return DELEGATE_COST_BASE_SIZE + addSize; + } + + // only for testing + public static long estimateConsumeBandWidthSizeOld( + final AccountCapsule ownerCapsule, + ChainBaseManager chainBaseManager) { + DelegateResourceContract.Builder builder = DelegateResourceContract.newBuilder() + .setLock(true) + .setBalance(ownerCapsule.getFrozenV2BalanceForBandwidth()); + TransactionCapsule fakeTransactionCapsule = new TransactionCapsule(builder.build(), + ContractType.DelegateResourceContract); + long size1 = consumeBandWidthSize(fakeTransactionCapsule, chainBaseManager); + + DelegateResourceContract.Builder builder2 = DelegateResourceContract.newBuilder() + .setBalance(TRX_PRECISION); + TransactionCapsule fakeTransactionCapsule2 = new TransactionCapsule(builder2.build(), + ContractType.DelegateResourceContract); + long size2 = consumeBandWidthSize(fakeTransactionCapsule2, chainBaseManager); + long addSize = Math.max(size1 - size2, 0L); + + return DELEGATE_COST_BASE_SIZE + addSize; + } + @Test public void validAccountNameCheck() { StringBuilder account = new StringBuilder(); @@ -65,7 +150,6 @@ public void validAccountNameCheck() { assertTrue(validAccountName(account.toString().getBytes(StandardCharsets.UTF_8))); account.append('z'); assertFalse(validAccountName(account.toString().getBytes(StandardCharsets.UTF_8))); - } @Test @@ -147,7 +231,7 @@ public void isNumberCheck() { public void testEstimateConsumeBandWidthSize() { AccountCapsule ownerCapsule = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); - long estimateConsumeBandWidthSize = TransactionUtil.estimateConsumeBandWidthSize(ownerCapsule, + long estimateConsumeBandWidthSize = estimateConsumeBandWidthSize(ownerCapsule, dbManager.getChainBaseManager()); assertEquals(275L, estimateConsumeBandWidthSize); chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(DELEGATE_PERIOD / 3000); @@ -159,10 +243,193 @@ public void testEstimateConsumeBandWidthSize2() { chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(864000L); AccountCapsule ownerCapsule = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); - long estimateConsumeBandWidthSize = TransactionUtil.estimateConsumeBandWidthSize(ownerCapsule, + long estimateConsumeBandWidthSize = estimateConsumeBandWidthSize(ownerCapsule, dbManager.getChainBaseManager()); assertEquals(277L, estimateConsumeBandWidthSize); chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(DELEGATE_PERIOD / 3000); } + + @Test + public void testEstimateConsumeBandWidthSizeOld() { + dbManager.getDynamicPropertiesStore().saveAllowCreationOfContracts(1L); + ChainBaseManager chainBaseManager = dbManager.getChainBaseManager(); + long balance = 1000_000L; + + AccountCapsule ownerCapsule = new AccountCapsule(ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), Protocol.AccountType.Normal, + balance); + ownerCapsule.addFrozenBalanceForBandwidthV2(balance); + dbManager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); + ownerCapsule = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + long estimateConsumeBandWidthSize1 = estimateConsumeBandWidthSizeOld( + ownerCapsule, chainBaseManager); + Assert.assertEquals(277, estimateConsumeBandWidthSize1); + + balance = 1000_000_000L; + ownerCapsule = new AccountCapsule(ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), Protocol.AccountType.Normal, + balance); + ownerCapsule.addFrozenBalanceForBandwidthV2(balance); + dbManager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); + long estimateConsumeBandWidthSize2 = estimateConsumeBandWidthSizeOld( + ownerCapsule, chainBaseManager); + Assert.assertEquals(279, estimateConsumeBandWidthSize2); + + balance = 1000_000_000_000L; + ownerCapsule = new AccountCapsule(ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), Protocol.AccountType.Normal, + balance); + ownerCapsule.addFrozenBalanceForBandwidthV2(balance); + dbManager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); + long estimateConsumeBandWidthSize3 = estimateConsumeBandWidthSizeOld( + ownerCapsule, chainBaseManager); + Assert.assertEquals(280, estimateConsumeBandWidthSize3); + + balance = 1000_000_000_000_000L; + ownerCapsule = new AccountCapsule(ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), Protocol.AccountType.Normal, + balance); + ownerCapsule.addFrozenBalanceForBandwidthV2(balance); + dbManager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); + long estimateConsumeBandWidthSize4 = estimateConsumeBandWidthSizeOld( + ownerCapsule, chainBaseManager); + Assert.assertEquals(282, estimateConsumeBandWidthSize4); + } + + + @Test + public void testEstimateConsumeBandWidthSizeNew() { + long balance = 1000_000L; + DynamicPropertiesStore dps = chainBaseManager.getDynamicPropertiesStore(); + long estimateConsumeBandWidthSize1 = TransactionUtil.estimateConsumeBandWidthSize(dps, balance); + Assert.assertEquals(277, estimateConsumeBandWidthSize1); + + balance = 1000_000_000L; + long estimateConsumeBandWidthSize2 = TransactionUtil.estimateConsumeBandWidthSize(dps, balance); + Assert.assertEquals(279, estimateConsumeBandWidthSize2); + + balance = 1000_000_000_000L; + long estimateConsumeBandWidthSize3 = TransactionUtil.estimateConsumeBandWidthSize(dps, balance); + Assert.assertEquals(280, estimateConsumeBandWidthSize3); + + balance = 1000_000_000_000_000L; + long estimateConsumeBandWidthSize4 = TransactionUtil.estimateConsumeBandWidthSize(dps, balance); + Assert.assertEquals(282, estimateConsumeBandWidthSize4); + } + + + @Test + public void testEstimateConsumeBandWidthSize3() { + dbManager.getDynamicPropertiesStore().saveAllowCreationOfContracts(1L); + ChainBaseManager chainBaseManager = dbManager.getChainBaseManager(); + DynamicPropertiesStore dps = chainBaseManager.getDynamicPropertiesStore(); + long balance = 1000_000L; + + AccountCapsule ownerCapsule; + long estimateConsumeBandWidthSizeOld; + long estimateConsumeBandWidthSizeNew; + + for (int i = 0; i < 100; i++) { + // old value is + ownerCapsule = new AccountCapsule(ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), Protocol.AccountType.Normal, + balance); + ownerCapsule.addFrozenBalanceForBandwidthV2(balance); + dbManager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); + estimateConsumeBandWidthSizeOld = estimateConsumeBandWidthSizeOld( + ownerCapsule, chainBaseManager); + + // new value is + estimateConsumeBandWidthSizeNew = TransactionUtil.estimateConsumeBandWidthSize(dps, balance); + + System.out.println("balance:" + + balance + + ", estimateConsumeBandWidthSizeOld:" + + estimateConsumeBandWidthSizeOld + + ", estimateConsumeBandWidthSizeNew:" + + estimateConsumeBandWidthSizeNew); + // new value assert equal to old value + Assert.assertEquals(estimateConsumeBandWidthSizeOld, estimateConsumeBandWidthSizeNew); + + // balance accumulated + balance = balance * 10; + if (balance < 0) { + break; + } + } + + } + + @Test + public void estimateConsumeBandWidthSizePositive() { + DynamicPropertiesStore dps = chainBaseManager.getDynamicPropertiesStore(); + long balance = 100; + DelegateResourceContract.Builder builder = + DelegateResourceContract.newBuilder() + .setLock(true) + .setBalance(balance); + DelegateResourceContract.Builder builder2 = + DelegateResourceContract.newBuilder() + .setBalance(TRX_PRECISION); + + long expected = DELEGATE_COST_BASE_SIZE + Math.max( + builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L); + long actual = TransactionUtil.estimateConsumeBandWidthSize(dps, balance); + Assert.assertEquals(expected, actual); + } + + @Test + public void estimateConsumeBandWidthSizeBoundary() { + DynamicPropertiesStore dps = chainBaseManager.getDynamicPropertiesStore(); + long balance = TRX_PRECISION; + DelegateResourceContract.Builder builder = + DelegateResourceContract.newBuilder() + .setLock(true) + .setBalance(balance); + DelegateResourceContract.Builder builder2 = + DelegateResourceContract.newBuilder() + .setBalance(TRX_PRECISION); + + long expected = DELEGATE_COST_BASE_SIZE + Math.max( + builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L); + long actual = TransactionUtil.estimateConsumeBandWidthSize(dps, balance); + Assert.assertEquals(expected, actual); + } + + @Test + public void estimateConsumeBandWidthSizeEdge() { + DynamicPropertiesStore dps = chainBaseManager.getDynamicPropertiesStore(); + long balance = TRX_PRECISION + 1; + DelegateResourceContract.Builder builder = + DelegateResourceContract.newBuilder() + .setLock(true) + .setBalance(balance); + DelegateResourceContract.Builder builder2 = + DelegateResourceContract.newBuilder() + .setBalance(TRX_PRECISION); + + long expected = DELEGATE_COST_BASE_SIZE + Math.max( + builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L); + long actual = TransactionUtil.estimateConsumeBandWidthSize(dps, balance); + Assert.assertEquals(expected, actual); + } + + @Test + public void estimateConsumeBandWidthSizeCorner() { + DynamicPropertiesStore dps = chainBaseManager.getDynamicPropertiesStore(); + long balance = Long.MAX_VALUE; + DelegateResourceContract.Builder builder = + DelegateResourceContract.newBuilder() + .setLock(true) + .setBalance(balance); + DelegateResourceContract.Builder builder2 = + DelegateResourceContract.newBuilder() + .setBalance(TRX_PRECISION); + + long expected = DELEGATE_COST_BASE_SIZE + Math.max( + builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L); + long actual = TransactionUtil.estimateConsumeBandWidthSize(dps, balance); + Assert.assertEquals(expected, actual); + } } From 1e1cd579c2d646454cf1c5dc314a7ae816e5a108 Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 24 Aug 2023 11:33:50 +0800 Subject: [PATCH 0860/1197] feat(shell): optimize startup scripts --- start.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/start.sh b/start.sh index 6c579a97478..89f13cf25a7 100644 --- a/start.sh +++ b/start.sh @@ -22,7 +22,7 @@ FULL_NODE_DIR="FullNode" FULL_NODE_CONFIG_DIR="config" # config file FULL_NODE_CONFIG_MAIN_NET="main_net_config.conf" -FULL_NODE_CONFIG_TEST_NET="test_net_config.conf.conf" +FULL_NODE_CONFIG_TEST_NET="test_net_config.conf" FULL_NODE_CONFIG_PRIVATE_NET="private_net_config.conf" DEFAULT_FULL_NODE_CONFIG='config.conf' JAR_NAME="FullNode.jar" From e70ef1bca7a722e32cd3ab1c8580cff112197f66 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 24 Aug 2023 17:56:42 +0800 Subject: [PATCH 0861/1197] feat(*):delelte some unuseful code --- .../tron/common/parameter/CommonParameter.java | 12 ------------ common/src/main/java/org/tron/core/Constant.java | 4 ---- .../java/org/tron/core/config/args/Args.java | 16 ---------------- .../org/tron/common/config/args/ArgsTest.java | 1 - 4 files changed, 33 deletions(-) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index a8c4991a782..3ba55f9b47f 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -177,21 +177,9 @@ public class CommonParameter { @Getter @Setter public String nodeExternalIp; -// @Getter -// @Setter -// public boolean nodeDiscoveryPublicHomeNode; -// @Getter -// @Setter -// public long nodeDiscoveryPingTimeout; -// @Getter -// @Setter -// public long nodeP2pPingInterval; @Getter @Setter public int nodeP2pVersion; -// @Getter -// @Setter -// public String p2pNodeId; @Getter @Setter public boolean nodeEnableIpv6 = false; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 7a56b7990b6..57db2d59639 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -101,10 +101,6 @@ public class Constant { public static final String NODE_MAX_CONNECTIONS_WITH_SAME_IP = "node.maxConnectionsWithSameIp"; public static final String NODE_MIN_PARTICIPATION_RATE = "node.minParticipationRate"; public static final String NODE_LISTEN_PORT = "node.listen.port"; - //public static final String NODE_DISCOVERY_PUBLIC_HOME_NODE = "node.discovery.public.home.node"; - //public static final String NODE_DISCOVERY_PING_TIMEOUT = "node.discovery.ping.timeout"; - - //public static final String NODE_P2P_PING_INTERVAL = "node.p2p.pingInterval"; public static final String NODE_P2P_VERSION = "node.p2p.version"; public static final String NODE_ENABLE_IPV6 = "node.enableIpv6"; public static final String NODE_DNS_TREE_URLS = "node.dns.treeUrls"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 5af82f132a4..e19cf5c95d7 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -141,9 +141,6 @@ public static void clearParam() { PARAMETER.nodeListenPort = 0; PARAMETER.nodeDiscoveryBindIp = ""; PARAMETER.nodeExternalIp = ""; - // PARAMETER.nodeDiscoveryPublicHomeNode = false; - // PARAMETER.nodeDiscoveryPingTimeout = 15000; - // PARAMETER.nodeP2pPingInterval = 0L; PARAMETER.nodeP2pVersion = 0; PARAMETER.nodeEnableIpv6 = false; PARAMETER.dnsTreeUrls = new ArrayList<>(); @@ -171,7 +168,6 @@ public static void clearParam() { PARAMETER.forbidTransferToContract = 0; PARAMETER.tcpNettyWorkThreadNum = 0; PARAMETER.udpNettyWorkThreadNum = 0; - // PARAMETER.p2pNodeId = ""; PARAMETER.solidityNode = false; PARAMETER.trustNodeAddr = ""; PARAMETER.walletExtensionApi = false; @@ -640,18 +636,6 @@ public static void setParam(final String[] args, final String confFileName) { bindIp(config); externalIp(config); - //PARAMETER.nodeDiscoveryPublicHomeNode = - // config.hasPath(Constant.NODE_DISCOVERY_PUBLIC_HOME_NODE) && config - // .getBoolean(Constant.NODE_DISCOVERY_PUBLIC_HOME_NODE); - - //PARAMETER.nodeDiscoveryPingTimeout = - // config.hasPath(Constant.NODE_DISCOVERY_PING_TIMEOUT) - // ? config.getLong(Constant.NODE_DISCOVERY_PING_TIMEOUT) : 15000; - - //PARAMETER.nodeP2pPingInterval = - // config.hasPath(Constant.NODE_P2P_PING_INTERVAL) - // ? config.getLong(Constant.NODE_P2P_PING_INTERVAL) : 0; - PARAMETER.nodeP2pVersion = config.hasPath(Constant.NODE_P2P_VERSION) ? config.getInt(Constant.NODE_P2P_VERSION) : 0; diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index 17a04421d2d..1c47599b61a 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -31,7 +31,6 @@ public void destroy() { public void testConfig() { Assert.assertEquals(Args.getInstance().getMaxTransactionPendingSize(), 2000); Assert.assertEquals(Args.getInstance().getPendingTransactionTimeout(), 60_000); - //Assert.assertEquals(Args.getInstance().getNodeDiscoveryPingTimeout(), 15_000); Assert.assertEquals(Args.getInstance().getMaxFastForwardNum(), 3); Assert.assertEquals(Args.getInstance().getBlockCacheTimeout(), 60); Assert.assertEquals(Args.getInstance().isNodeDetectEnable(), false); From 0bf4bbc3d1deb2a1c7ca613c2b8df04b54e43d3e Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Thu, 10 Aug 2023 15:25:27 +0800 Subject: [PATCH 0862/1197] feat(api): add gRPC implementation for certain interfaces --- .../src/main/java/org/tron/core/Wallet.java | 15 +++-- .../org/tron/core/services/RpcApiService.java | 45 ++++++++++++++ .../http/GetBandwidthPricesServlet.java | 15 ++--- .../services/http/GetEnergyPricesServlet.java | 15 ++--- .../interfaceOnPBFT/RpcApiServiceOnPBFT.java | 18 +++++- .../RpcApiServiceOnSolidity.java | 19 ++++-- .../common/utils/client/utils/HttpMethed.java | 8 +++ .../filter/RpcApiAccessInterceptorTest.java | 49 ++++++++++----- .../http/GetBandwidthPricesServletTest.java | 62 +++++++++++++++++++ .../http/GetEnergyPricesServletTest.java | 62 +++++++++++++++++++ protocol/src/main/protos/api/api.proto | 15 +++++ 11 files changed, 275 insertions(+), 48 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/services/http/GetBandwidthPricesServletTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/GetEnergyPricesServletTest.java diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 3560a7032bc..c7110556b7b 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -87,6 +87,7 @@ import org.tron.api.GrpcAPI.PrivateShieldedTRC20ParametersWithoutAsk; import org.tron.api.GrpcAPI.ProposalList; import org.tron.api.GrpcAPI.ReceiveNote; +import org.tron.api.GrpcAPI.ResourcePricesResponseMessage; import org.tron.api.GrpcAPI.Return; import org.tron.api.GrpcAPI.Return.response_code; import org.tron.api.GrpcAPI.ShieldedAddressInfo; @@ -4309,23 +4310,25 @@ public long getEnergyFee(long timestamp) { } } - public String getEnergyPrices() { + public ResourcePricesResponseMessage getEnergyPrices() { + ResourcePricesResponseMessage.Builder builder = ResourcePricesResponseMessage.newBuilder(); try { - return chainBaseManager.getDynamicPropertiesStore().getEnergyPriceHistory(); + builder.setPrices(chainBaseManager.getDynamicPropertiesStore().getEnergyPriceHistory()); + return builder.build(); } catch (Exception e) { logger.error("GetEnergyPrices failed", e); } - return null; } - public String getBandwidthPrices() { + public ResourcePricesResponseMessage getBandwidthPrices() { + ResourcePricesResponseMessage.Builder builder = ResourcePricesResponseMessage.newBuilder(); try { - return chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistory(); + builder.setPrices(chainBaseManager.getDynamicPropertiesStore().getBandwidthPriceHistory()); + return builder.build(); } catch (Exception e) { logger.error("GetBandwidthPrices failed", e); } - return null; } diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 2a4ebca95b4..3087f153c3c 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -55,6 +55,7 @@ import org.tron.api.GrpcAPI.PrivateShieldedTRC20Parameters; import org.tron.api.GrpcAPI.PrivateShieldedTRC20ParametersWithoutAsk; import org.tron.api.GrpcAPI.ProposalList; +import org.tron.api.GrpcAPI.ResourcePricesResponseMessage; import org.tron.api.GrpcAPI.Return; import org.tron.api.GrpcAPI.Return.response_code; import org.tron.api.GrpcAPI.ShieldedAddressInfo; @@ -994,6 +995,28 @@ public void getBlock(GrpcAPI.BlockReq request, StreamObserver responseObserver) { getBlockCommon(request, responseObserver); } + + @Override + public void getBandwidthPrices(EmptyMessage request, + StreamObserver responseObserver) { + try { + responseObserver.onNext(wallet.getBandwidthPrices()); + } catch (Exception e) { + responseObserver.onError(getRunTimeException(e)); + } + responseObserver.onCompleted(); + } + + @Override + public void getEnergyPrices(EmptyMessage request, + StreamObserver responseObserver) { + try { + responseObserver.onNext(wallet.getEnergyPrices()); + } catch (Exception e) { + responseObserver.onError(getRunTimeException(e)); + } + responseObserver.onCompleted(); + } } /** @@ -2027,6 +2050,28 @@ public void getCanWithdrawUnfreezeAmount(CanWithdrawUnfreezeAmountRequestMessage responseObserver.onCompleted(); } + @Override + public void getBandwidthPrices(EmptyMessage request, + StreamObserver responseObserver) { + try { + responseObserver.onNext(wallet.getBandwidthPrices()); + } catch (Exception e) { + responseObserver.onError(getRunTimeException(e)); + } + responseObserver.onCompleted(); + } + + @Override + public void getEnergyPrices(EmptyMessage request, + StreamObserver responseObserver) { + try { + responseObserver.onNext(wallet.getEnergyPrices()); + } catch (Exception e) { + responseObserver.onError(getRunTimeException(e)); + } + responseObserver.onCompleted(); + } + @Override public void getPaginatedProposalList(PaginatedMessage request, StreamObserver responseObserver) { diff --git a/framework/src/main/java/org/tron/core/services/http/GetBandwidthPricesServlet.java b/framework/src/main/java/org/tron/core/services/http/GetBandwidthPricesServlet.java index ea4b535af39..b4350412930 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetBandwidthPricesServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetBandwidthPricesServlet.java @@ -1,14 +1,13 @@ package org.tron.core.services.http; -import com.alibaba.fastjson.JSONObject; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.api.GrpcAPI.ResourcePricesResponseMessage; import org.tron.core.Wallet; - @Component @Slf4j(topic = "API") public class GetBandwidthPricesServlet extends RateLimiterServlet { @@ -16,21 +15,17 @@ public class GetBandwidthPricesServlet extends RateLimiterServlet { @Autowired private Wallet wallet; + @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - String reply = wallet.getBandwidthPrices(); - if (reply != null) { - JSONObject jsonObject = new JSONObject(); - jsonObject.put("prices", reply); - response.getWriter().println(jsonObject); - } else { - response.getWriter().println("{}"); - } + ResourcePricesResponseMessage reply = wallet.getBandwidthPrices(); + response.getWriter().println(reply == null ? "{}" : JsonFormat.printToString(reply)); } catch (Exception e) { Util.processError(e, response); } } + @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { doGet(request, response); } diff --git a/framework/src/main/java/org/tron/core/services/http/GetEnergyPricesServlet.java b/framework/src/main/java/org/tron/core/services/http/GetEnergyPricesServlet.java index 36129d8ffdb..3f0a4fa8177 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetEnergyPricesServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetEnergyPricesServlet.java @@ -1,14 +1,13 @@ package org.tron.core.services.http; -import com.alibaba.fastjson.JSONObject; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.api.GrpcAPI.ResourcePricesResponseMessage; import org.tron.core.Wallet; - @Component @Slf4j(topic = "API") public class GetEnergyPricesServlet extends RateLimiterServlet { @@ -16,21 +15,17 @@ public class GetEnergyPricesServlet extends RateLimiterServlet { @Autowired private Wallet wallet; + @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - String reply = wallet.getEnergyPrices(); - if (reply != null) { - JSONObject jsonObject = new JSONObject(); - jsonObject.put("prices", reply); - response.getWriter().println(jsonObject); - } else { - response.getWriter().println("{}"); - } + ResourcePricesResponseMessage reply = wallet.getEnergyPrices(); + response.getWriter().println(reply == null ? "{}" : JsonFormat.printToString(reply)); } catch (Exception e) { Util.processError(e, response); } } + @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { doGet(request, response); } diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java index c003f9d3994..73aef934dbf 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java @@ -32,15 +32,13 @@ import org.tron.api.GrpcAPI.NumberMessage; import org.tron.api.GrpcAPI.OvkDecryptTRC20Parameters; import org.tron.api.GrpcAPI.PaginatedMessage; +import org.tron.api.GrpcAPI.ResourcePricesResponseMessage; import org.tron.api.GrpcAPI.SpendResult; import org.tron.api.GrpcAPI.TransactionExtention; import org.tron.api.GrpcAPI.WitnessList; import org.tron.api.WalletSolidityGrpc.WalletSolidityImplBase; import org.tron.common.application.Service; -import org.tron.common.crypto.ECKey; import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; import org.tron.core.config.args.Args; import org.tron.core.services.RpcApiService; import org.tron.core.services.filter.LiteFnQueryGrpcInterceptor; @@ -554,5 +552,19 @@ public void getBlock(GrpcAPI.BlockReq request, () -> rpcApiService.getWalletSolidityApi().getBlock(request, responseObserver)); } + @Override + public void getBandwidthPrices(EmptyMessage request, + StreamObserver responseObserver) { + walletOnPBFT.futureGet( + () -> rpcApiService.getWalletSolidityApi().getBandwidthPrices(request, responseObserver)); + } + + @Override + public void getEnergyPrices(EmptyMessage request, + StreamObserver responseObserver) { + walletOnPBFT.futureGet( + () -> rpcApiService.getWalletSolidityApi().getEnergyPrices(request, responseObserver)); + } + } } diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java index 3f4bfeda731..bb29814ac8d 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java @@ -28,6 +28,7 @@ import org.tron.api.GrpcAPI.NoteParameters; import org.tron.api.GrpcAPI.NumberMessage; import org.tron.api.GrpcAPI.PaginatedMessage; +import org.tron.api.GrpcAPI.ResourcePricesResponseMessage; import org.tron.api.GrpcAPI.Return; import org.tron.api.GrpcAPI.Return.response_code; import org.tron.api.GrpcAPI.SpendResult; @@ -36,12 +37,8 @@ import org.tron.api.GrpcAPI.WitnessList; import org.tron.api.WalletSolidityGrpc.WalletSolidityImplBase; import org.tron.common.application.Service; -import org.tron.common.crypto.SignInterface; -import org.tron.common.crypto.SignUtils; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.Sha256Hash; -import org.tron.common.utils.StringUtil; -import org.tron.common.utils.Utils; import org.tron.core.capsule.BlockCapsule; import org.tron.core.config.args.Args; import org.tron.core.services.RpcApiService; @@ -537,5 +534,19 @@ public void getBlock(GrpcAPI.BlockReq request, () -> rpcApiService.getWalletSolidityApi().getBlock(request, responseObserver)); } + @Override + public void getBandwidthPrices(EmptyMessage request, + StreamObserver responseObserver) { + walletOnSolidity.futureGet( + () -> rpcApiService.getWalletSolidityApi().getBandwidthPrices(request, responseObserver)); + } + + @Override + public void getEnergyPrices(EmptyMessage request, + StreamObserver responseObserver) { + walletOnSolidity.futureGet( + () -> rpcApiService.getWalletSolidityApi().getEnergyPrices(request, responseObserver)); + } + } } diff --git a/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java b/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java index 6839de47434..ee872be6330 100644 --- a/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java @@ -23,6 +23,7 @@ import org.apache.http.params.CoreConnectionPNames; import org.apache.http.util.EntityUtils; import org.junit.Assert; +import org.springframework.mock.web.MockHttpServletRequest; import org.tron.api.GrpcAPI; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; @@ -4876,4 +4877,11 @@ public static HttpResponse getTransactionFromPending(String httpNode, String txi } return response; } + + public static MockHttpServletRequest createRequest(String method) { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setMethod(method); + request.setCharacterEncoding("UTF-8"); + return request; + } } diff --git a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java index edd15fc19de..33f9437028b 100644 --- a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java @@ -16,7 +16,10 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.tron.api.GrpcAPI; +import org.tron.api.GrpcAPI.BlockReq; +import org.tron.api.GrpcAPI.BytesMessage; +import org.tron.api.GrpcAPI.EmptyMessage; +import org.tron.api.GrpcAPI.NumberMessage; import org.tron.api.WalletGrpc; import org.tron.api.WalletSolidityGrpc; import org.tron.common.application.Application; @@ -41,7 +44,7 @@ public class RpcApiAccessInterceptorTest { private static WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPBFT = null; private static Application appTest; - private static String dbPath = "output_rpc_api_access_interceptor_test"; + private static final String dbPath = "output_rpc_api_access_interceptor_test"; @Rule public ExpectedException thrown = ExpectedException.none(); @@ -115,7 +118,7 @@ public void testAccessDisabledFullNode() { disabledApiList.add("getblockbynum"); Args.getInstance().setDisabledApiList(disabledApiList); - final GrpcAPI.NumberMessage message = GrpcAPI.NumberMessage.newBuilder().setNum(0).build(); + final NumberMessage message = NumberMessage.newBuilder().setNum(0).build(); thrown.expect(StatusRuntimeException.class); thrown.expectMessage("this API is unavailable due to config"); blockingStubFull.getBlockByNum(message); @@ -125,42 +128,42 @@ public void testAccessDisabledFullNode() { public void testRpcApiService() { RpcApiService rpcApiService = context.getBean(RpcApiService.class); ServerCallStreamObserverTest serverCallStreamObserverTest = new ServerCallStreamObserverTest(); - rpcApiService.getBlockCommon(GrpcAPI.BlockReq.getDefaultInstance(), + rpcApiService.getBlockCommon(BlockReq.getDefaultInstance(), serverCallStreamObserverTest); Assert.assertTrue("Get block Common failed!", serverCallStreamObserverTest.isReady()); serverCallStreamObserverTest.isCancelled(); - rpcApiService.getBrokerageInfoCommon(GrpcAPI.BytesMessage.newBuilder().build(), + rpcApiService.getBrokerageInfoCommon(BytesMessage.newBuilder().build(), serverCallStreamObserverTest); Assert.assertTrue("Get brokerage info Common failed!", serverCallStreamObserverTest.isReady()); serverCallStreamObserverTest.isCancelled(); - rpcApiService.getBurnTrxCommon(GrpcAPI.EmptyMessage.newBuilder().build(), + rpcApiService.getBurnTrxCommon(EmptyMessage.newBuilder().build(), serverCallStreamObserverTest); Assert.assertTrue("Get burn trx common failed!", serverCallStreamObserverTest.isReady()); serverCallStreamObserverTest.isCancelled(); - rpcApiService.getPendingSizeCommon(GrpcAPI.EmptyMessage.getDefaultInstance(), + rpcApiService.getPendingSizeCommon(EmptyMessage.getDefaultInstance(), serverCallStreamObserverTest); Assert.assertTrue("Get pending size common failed!", serverCallStreamObserverTest.isReady()); serverCallStreamObserverTest.isCancelled(); - rpcApiService.getRewardInfoCommon(GrpcAPI.BytesMessage.newBuilder().build(), + rpcApiService.getRewardInfoCommon(BytesMessage.newBuilder().build(), serverCallStreamObserverTest); Assert.assertTrue("Get reward info common failed!", serverCallStreamObserverTest.isReady()); serverCallStreamObserverTest.isCancelled(); rpcApiService.getTransactionCountByBlockNumCommon( - GrpcAPI.NumberMessage.newBuilder().getDefaultInstanceForType(), + NumberMessage.newBuilder().getDefaultInstanceForType(), serverCallStreamObserverTest); Assert.assertTrue("Get transaction count by block num failed!", serverCallStreamObserverTest.isReady()); serverCallStreamObserverTest.isCancelled(); - rpcApiService.getTransactionFromPendingCommon(GrpcAPI.BytesMessage.newBuilder().build(), + rpcApiService.getTransactionFromPendingCommon(BytesMessage.newBuilder().build(), serverCallStreamObserverTest); Assert.assertTrue("Get transaction from pending failed!", serverCallStreamObserverTest.isReady() == false); serverCallStreamObserverTest.isCancelled(); - rpcApiService.getTransactionListFromPendingCommon(GrpcAPI.EmptyMessage.newBuilder() + rpcApiService.getTransactionListFromPendingCommon(EmptyMessage.newBuilder() .getDefaultInstanceForType(), serverCallStreamObserverTest); Assert.assertTrue("Get transaction list from pending failed!", serverCallStreamObserverTest.isReady()); @@ -228,7 +231,7 @@ public void testAccessDisabledSolidityNode() { disabledApiList.add("getblockbynum"); Args.getInstance().setDisabledApiList(disabledApiList); - final GrpcAPI.NumberMessage message = GrpcAPI.NumberMessage.newBuilder().setNum(0).build(); + final NumberMessage message = NumberMessage.newBuilder().setNum(0).build(); thrown.expect(StatusRuntimeException.class); thrown.expectMessage("this API is unavailable due to config"); blockingStubSolidity.getBlockByNum(message); @@ -241,7 +244,7 @@ public void testAccessDisabledPBFTNode() { disabledApiList.add("getblockbynum"); Args.getInstance().setDisabledApiList(disabledApiList); - final GrpcAPI.NumberMessage message = GrpcAPI.NumberMessage.newBuilder().setNum(0).build(); + final NumberMessage message = NumberMessage.newBuilder().setNum(0).build(); thrown.expect(StatusRuntimeException.class); thrown.expectMessage("this API is unavailable due to config"); blockingStubPBFT.getBlockByNum(message); @@ -251,7 +254,7 @@ public void testAccessDisabledPBFTNode() { public void testAccessNoDisabled() { Args.getInstance().setDisabledApiList(Collections.emptyList()); - final GrpcAPI.NumberMessage message = GrpcAPI.NumberMessage.newBuilder().setNum(0).build(); + final NumberMessage message = NumberMessage.newBuilder().setNum(0).build(); Assert.assertNotNull(blockingStubFull.getBlockByNum(message)); Assert.assertNotNull(blockingStubSolidity.getBlockByNum(message)); Assert.assertNotNull(blockingStubPBFT.getBlockByNum(message)); @@ -263,11 +266,27 @@ public void testAccessDisabledNotIncluded() { disabledApiList.add("getaccount"); Args.getInstance().setDisabledApiList(disabledApiList); - final GrpcAPI.NumberMessage message = GrpcAPI.NumberMessage.newBuilder().setNum(0).build(); + final NumberMessage message = NumberMessage.newBuilder().setNum(0).build(); Assert.assertNotNull(blockingStubFull.getBlockByNum(message)); Assert.assertNotNull(blockingStubSolidity.getBlockByNum(message)); Assert.assertNotNull(blockingStubPBFT.getBlockByNum(message)); } + @Test + public void testGetBandwidthPrices() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + Assert.assertNotNull(blockingStubFull.getBandwidthPrices(message)); + Assert.assertNotNull(blockingStubSolidity.getBandwidthPrices(message)); + Assert.assertNotNull(blockingStubPBFT.getBandwidthPrices(message)); + } + + @Test + public void testGetEnergyPrices() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + Assert.assertNotNull(blockingStubFull.getEnergyPrices(message)); + Assert.assertNotNull(blockingStubSolidity.getEnergyPrices(message)); + Assert.assertNotNull(blockingStubPBFT.getEnergyPrices(message)); + } + } diff --git a/framework/src/test/java/org/tron/core/services/http/GetBandwidthPricesServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetBandwidthPricesServletTest.java new file mode 100644 index 00000000000..90d2794be9a --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/GetBandwidthPricesServletTest.java @@ -0,0 +1,62 @@ +package org.tron.core.services.http; + +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 java.io.IOException; +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +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 GetBandwidthPricesServletTest extends BaseTest { + + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); + @Resource + private GetBandwidthPricesServlet getBandwidthPricesServlet; + + @BeforeClass + public static void init() throws IOException { + Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + } + + @Test + public void testGet() { + MockHttpServletRequest request = createRequest(HttpGet.METHOD_NAME); + MockHttpServletResponse response = new MockHttpServletResponse(); + getBandwidthPricesServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + assertTrue(result.containsKey("prices")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + + @Test + public void testPost() { + MockHttpServletRequest request = createRequest(HttpPost.METHOD_NAME); + try { + MockHttpServletResponse response = new MockHttpServletResponse(); + getBandwidthPricesServlet.doPost(request, response); + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + assertTrue(result.containsKey("prices")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } +} diff --git a/framework/src/test/java/org/tron/core/services/http/GetEnergyPricesServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetEnergyPricesServletTest.java new file mode 100644 index 00000000000..391f2c2d4a7 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/GetEnergyPricesServletTest.java @@ -0,0 +1,62 @@ +package org.tron.core.services.http; + +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 java.io.IOException; +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +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 GetEnergyPricesServletTest extends BaseTest { + + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); + @Resource + private GetEnergyPricesServlet getEnergyPricesServlet; + + @BeforeClass + public static void init() throws IOException { + Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + } + + @Test + public void testGet() { + MockHttpServletRequest request = createRequest(HttpGet.METHOD_NAME); + MockHttpServletResponse response = new MockHttpServletResponse(); + getEnergyPricesServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + assertTrue(result.containsKey("prices")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + + @Test + public void testPost() { + MockHttpServletRequest request = createRequest(HttpPost.METHOD_NAME); + try { + MockHttpServletResponse response = new MockHttpServletResponse(); + getEnergyPricesServlet.doPost(request, response); + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + assertTrue(result.containsKey("prices")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } +} diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index d23d6e01729..e9dc851dcd8 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -767,6 +767,12 @@ service Wallet { rpc GetBlock (BlockReq) returns (BlockExtention) { } + + rpc GetBandwidthPrices (EmptyMessage) returns (ResourcePricesResponseMessage) { + } + + rpc GetEnergyPrices (EmptyMessage) returns (ResourcePricesResponseMessage) { + } }; service WalletSolidity { @@ -963,6 +969,11 @@ service WalletSolidity { } rpc GetBlock (BlockReq) returns (BlockExtention) { } + rpc GetBandwidthPrices (EmptyMessage) returns (ResourcePricesResponseMessage) { + } + + rpc GetEnergyPrices (EmptyMessage) returns (ResourcePricesResponseMessage) { + } }; service WalletExtension { @@ -1107,6 +1118,10 @@ message CanWithdrawUnfreezeAmountResponseMessage { int64 amount = 1; } +message ResourcePricesResponseMessage { + string prices = 1; +} + // Gossip node list message NodeList { repeated Node nodes = 1; From 93454a29bf3c5dff3606ced77f022b9546927957 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Fri, 25 Aug 2023 11:58:31 +0800 Subject: [PATCH 0863/1197] chore(gitignore): ignore .cache (#5448) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6309bbd79a5..3917bb44679 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,4 @@ Wallet /vm_trace/ /framework/propPath +.cache From 300524661735d347cd3c8e550c5d0eff82ca05ab Mon Sep 17 00:00:00 2001 From: lxcmyf Date: Mon, 28 Aug 2023 14:40:43 +0800 Subject: [PATCH 0864/1197] feat(api): add resource price for solidity and PBFT (#5451) --- .../http/GetBandwidthPricesOnPBFTServlet.java | 27 ++++++++ .../http/GetEnergyPricesOnPBFTServlet.java | 3 +- .../http/PBFT/HttpApiOnPBFTService.java | 5 ++ .../GetBandwidthPricesOnSolidityServlet.java | 28 +++++++++ .../GetEnergyPricesOnSolidityServlet.java | 3 +- .../solidity/HttpApiOnSolidityService.java | 5 ++ .../test/java/org/tron/common/BaseTest.java | 10 +-- .../common/utils/client/utils/HttpMethed.java | 8 +++ .../GetBandwidthPricesOnPBFTServletTest.java | 62 +++++++++++++++++++ .../GetEnergyPricesOnPBFTServletTest.java | 62 +++++++++++++++++++ ...tBandwidthPricesOnSolidityServletTest.java | 62 +++++++++++++++++++ .../GetEnergyPricesOnSolidityServletTest.java | 62 +++++++++++++++++++ 12 files changed, 331 insertions(+), 6 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetBandwidthPricesOnPBFTServlet.java create mode 100644 framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetBandwidthPricesOnSolidityServlet.java create mode 100644 framework/src/test/java/org/tron/core/services/interfaceOnPBFT/http/GetBandwidthPricesOnPBFTServletTest.java create mode 100644 framework/src/test/java/org/tron/core/services/interfaceOnPBFT/http/GetEnergyPricesOnPBFTServletTest.java create mode 100644 framework/src/test/java/org/tron/core/services/interfaceOnSolidity/http/GetBandwidthPricesOnSolidityServletTest.java create mode 100644 framework/src/test/java/org/tron/core/services/interfaceOnSolidity/http/GetEnergyPricesOnSolidityServletTest.java diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetBandwidthPricesOnPBFTServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetBandwidthPricesOnPBFTServlet.java new file mode 100644 index 00000000000..c89bc5f9646 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetBandwidthPricesOnPBFTServlet.java @@ -0,0 +1,27 @@ +package org.tron.core.services.interfaceOnPBFT.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetBandwidthPricesServlet; +import org.tron.core.services.interfaceOnPBFT.WalletOnPBFT; + +@Component +@Slf4j(topic = "API") +public class GetBandwidthPricesOnPBFTServlet extends GetBandwidthPricesServlet { + + @Autowired + private WalletOnPBFT walletOnPBFT; + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doGet(request, response)); + } + + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetEnergyPricesOnPBFTServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetEnergyPricesOnPBFTServlet.java index 4cf8ad06b27..11c1dcaa0e8 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetEnergyPricesOnPBFTServlet.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetEnergyPricesOnPBFTServlet.java @@ -8,7 +8,6 @@ import org.tron.core.services.http.GetEnergyPricesServlet; import org.tron.core.services.interfaceOnPBFT.WalletOnPBFT; - @Component @Slf4j(topic = "API") public class GetEnergyPricesOnPBFTServlet extends GetEnergyPricesServlet { @@ -16,10 +15,12 @@ public class GetEnergyPricesOnPBFTServlet extends GetEnergyPricesServlet { @Autowired private WalletOnPBFT walletOnPBFT; + @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { walletOnPBFT.futureGet(() -> super.doGet(request, response)); } + @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { walletOnPBFT.futureGet(() -> super.doPost(request, response)); } diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java index 33da1414bbe..9b72f11e2bf 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java @@ -22,6 +22,7 @@ import org.tron.core.services.interfaceOnPBFT.http.GetAssetIssueListByNameOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetAssetIssueListOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetAvailableUnfreezeCountOnPBFTServlet; +import org.tron.core.services.interfaceOnPBFT.http.GetBandwidthPricesOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetBlockByIdOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetBlockByLatestNumOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetBlockByLimitNextOnPBFTServlet; @@ -156,6 +157,8 @@ public class HttpApiOnPBFTService implements Service { @Autowired private GetBurnTrxOnPBFTServlet getBurnTrxOnPBFTServlet; @Autowired + private GetBandwidthPricesOnPBFTServlet getBandwidthPricesOnPBFTServlet; + @Autowired private GetEnergyPricesOnPBFTServlet getEnergyPricesOnPBFTServlet; @Autowired @@ -258,6 +261,8 @@ public void start() { "/isshieldedtrc20contractnotespent"); context.addServlet(new ServletHolder(getBurnTrxOnPBFTServlet), "/getburntrx"); + context.addServlet(new ServletHolder(getBandwidthPricesOnPBFTServlet), + "/getbandwidthprices"); context.addServlet(new ServletHolder(getEnergyPricesOnPBFTServlet), "/getenergyprices"); context.addServlet(new ServletHolder(getBlockOnPBFTServlet), diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetBandwidthPricesOnSolidityServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetBandwidthPricesOnSolidityServlet.java new file mode 100644 index 00000000000..bb2fca37a97 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetBandwidthPricesOnSolidityServlet.java @@ -0,0 +1,28 @@ +package org.tron.core.services.interfaceOnSolidity.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetBandwidthPricesServlet; +import org.tron.core.services.interfaceOnSolidity.WalletOnSolidity; + +@Component +@Slf4j(topic = "API") +public class GetBandwidthPricesOnSolidityServlet extends GetBandwidthPricesServlet { + + @Autowired + private WalletOnSolidity walletOnSolidity; + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doGet(request, response)); + } + + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doPost(request, response)); + } +} + diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetEnergyPricesOnSolidityServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetEnergyPricesOnSolidityServlet.java index b9d4fb765f6..a867fc3596a 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetEnergyPricesOnSolidityServlet.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetEnergyPricesOnSolidityServlet.java @@ -8,7 +8,6 @@ import org.tron.core.services.http.GetEnergyPricesServlet; import org.tron.core.services.interfaceOnSolidity.WalletOnSolidity; - @Component @Slf4j(topic = "API") public class GetEnergyPricesOnSolidityServlet extends GetEnergyPricesServlet { @@ -16,10 +15,12 @@ public class GetEnergyPricesOnSolidityServlet extends GetEnergyPricesServlet { @Autowired private WalletOnSolidity walletOnSolidity; + @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { walletOnSolidity.futureGet(() -> super.doGet(request, response)); } + @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { walletOnSolidity.futureGet(() -> super.doPost(request, response)); } diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java index bddec04d6a6..ba5ab49ef7a 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java @@ -22,6 +22,7 @@ import org.tron.core.services.interfaceOnSolidity.http.GetAssetIssueListByNameOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetAssetIssueListOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetAvailableUnfreezeCountOnSolidityServlet; +import org.tron.core.services.interfaceOnSolidity.http.GetBandwidthPricesOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetBlockByIdOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetBlockByLatestNumOnSolidityServlet; import org.tron.core.services.interfaceOnSolidity.http.GetBlockByLimitNextOnSolidityServlet; @@ -168,6 +169,8 @@ public class HttpApiOnSolidityService implements Service { @Autowired private GetMarketPairListOnSolidityServlet getMarketPairListOnSolidityServlet; @Autowired + private GetBandwidthPricesOnSolidityServlet getBandwidthPricesOnSolidityServlet; + @Autowired private GetEnergyPricesOnSolidityServlet getEnergyPricesOnSolidityServlet; @Autowired @@ -290,6 +293,8 @@ public void start() { context.addServlet(new ServletHolder(getRewardServlet), "/walletsolidity/getReward"); context .addServlet(new ServletHolder(getBurnTrxOnSolidityServlet), "/walletsolidity/getburntrx"); + context.addServlet(new ServletHolder(getBandwidthPricesOnSolidityServlet), + "/walletsolidity/getbandwidthprices"); context.addServlet(new ServletHolder(getEnergyPricesOnSolidityServlet), "/walletsolidity/getenergyprices"); diff --git a/framework/src/test/java/org/tron/common/BaseTest.java b/framework/src/test/java/org/tron/common/BaseTest.java index 1826dddea64..1dfbf702eff 100644 --- a/framework/src/test/java/org/tron/common/BaseTest.java +++ b/framework/src/test/java/org/tron/common/BaseTest.java @@ -37,10 +37,12 @@ public abstract class BaseTest { @AfterClass public static void destroy() { Args.clearParam(); - if (StringUtils.isNotEmpty(dbPath) && FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); + if (StringUtils.isNotEmpty(dbPath)) { + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.info("Release resources failure."); + } } } diff --git a/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java b/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java index 6839de47434..ee872be6330 100644 --- a/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java @@ -23,6 +23,7 @@ import org.apache.http.params.CoreConnectionPNames; import org.apache.http.util.EntityUtils; import org.junit.Assert; +import org.springframework.mock.web.MockHttpServletRequest; import org.tron.api.GrpcAPI; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; @@ -4876,4 +4877,11 @@ public static HttpResponse getTransactionFromPending(String httpNode, String txi } return response; } + + public static MockHttpServletRequest createRequest(String method) { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setMethod(method); + request.setCharacterEncoding("UTF-8"); + return request; + } } diff --git a/framework/src/test/java/org/tron/core/services/interfaceOnPBFT/http/GetBandwidthPricesOnPBFTServletTest.java b/framework/src/test/java/org/tron/core/services/interfaceOnPBFT/http/GetBandwidthPricesOnPBFTServletTest.java new file mode 100644 index 00000000000..06d552f1ede --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/interfaceOnPBFT/http/GetBandwidthPricesOnPBFTServletTest.java @@ -0,0 +1,62 @@ +package org.tron.core.services.interfaceOnPBFT.http; + +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 java.io.IOException; +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +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 GetBandwidthPricesOnPBFTServletTest extends BaseTest { + + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); + @Resource + private GetBandwidthPricesOnPBFTServlet getBandwidthPricesOnPBFTServlet; + + @BeforeClass + public static void init() throws IOException { + Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + } + + @Test + public void testGet() { + MockHttpServletRequest request = createRequest(HttpGet.METHOD_NAME); + MockHttpServletResponse response = new MockHttpServletResponse(); + getBandwidthPricesOnPBFTServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + assertTrue(result.containsKey("prices")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + + @Test + public void testPost() { + MockHttpServletRequest request = createRequest(HttpPost.METHOD_NAME); + try { + MockHttpServletResponse response = new MockHttpServletResponse(); + getBandwidthPricesOnPBFTServlet.doPost(request, response); + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + assertTrue(result.containsKey("prices")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } +} diff --git a/framework/src/test/java/org/tron/core/services/interfaceOnPBFT/http/GetEnergyPricesOnPBFTServletTest.java b/framework/src/test/java/org/tron/core/services/interfaceOnPBFT/http/GetEnergyPricesOnPBFTServletTest.java new file mode 100644 index 00000000000..ec2ce818da0 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/interfaceOnPBFT/http/GetEnergyPricesOnPBFTServletTest.java @@ -0,0 +1,62 @@ +package org.tron.core.services.interfaceOnPBFT.http; + +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 java.io.IOException; +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +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 GetEnergyPricesOnPBFTServletTest extends BaseTest { + + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); + @Resource + private GetEnergyPricesOnPBFTServlet getEnergyPricesOnPBFTServlet; + + @BeforeClass + public static void init() throws IOException { + Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + } + + @Test + public void testGet() { + MockHttpServletRequest request = createRequest(HttpGet.METHOD_NAME); + MockHttpServletResponse response = new MockHttpServletResponse(); + getEnergyPricesOnPBFTServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + assertTrue(result.containsKey("prices")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + + @Test + public void testPost() { + MockHttpServletRequest request = createRequest(HttpPost.METHOD_NAME); + try { + MockHttpServletResponse response = new MockHttpServletResponse(); + getEnergyPricesOnPBFTServlet.doPost(request, response); + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + assertTrue(result.containsKey("prices")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } +} diff --git a/framework/src/test/java/org/tron/core/services/interfaceOnSolidity/http/GetBandwidthPricesOnSolidityServletTest.java b/framework/src/test/java/org/tron/core/services/interfaceOnSolidity/http/GetBandwidthPricesOnSolidityServletTest.java new file mode 100644 index 00000000000..6eb27113b99 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/interfaceOnSolidity/http/GetBandwidthPricesOnSolidityServletTest.java @@ -0,0 +1,62 @@ +package org.tron.core.services.interfaceOnSolidity.http; + +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 java.io.IOException; +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +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 GetBandwidthPricesOnSolidityServletTest extends BaseTest { + + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); + @Resource + private GetBandwidthPricesOnSolidityServlet getBandwidthPricesOnSolidityServlet; + + @BeforeClass + public static void init() throws IOException { + Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + } + + @Test + public void testGet() { + MockHttpServletRequest request = createRequest(HttpGet.METHOD_NAME); + MockHttpServletResponse response = new MockHttpServletResponse(); + getBandwidthPricesOnSolidityServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + assertTrue(result.containsKey("prices")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + + @Test + public void testPost() { + MockHttpServletRequest request = createRequest(HttpPost.METHOD_NAME); + try { + MockHttpServletResponse response = new MockHttpServletResponse(); + getBandwidthPricesOnSolidityServlet.doPost(request, response); + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + assertTrue(result.containsKey("prices")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } +} diff --git a/framework/src/test/java/org/tron/core/services/interfaceOnSolidity/http/GetEnergyPricesOnSolidityServletTest.java b/framework/src/test/java/org/tron/core/services/interfaceOnSolidity/http/GetEnergyPricesOnSolidityServletTest.java new file mode 100644 index 00000000000..174175918c1 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/interfaceOnSolidity/http/GetEnergyPricesOnSolidityServletTest.java @@ -0,0 +1,62 @@ +package org.tron.core.services.interfaceOnSolidity.http; + +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 java.io.IOException; +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +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 GetEnergyPricesOnSolidityServletTest extends BaseTest { + + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); + @Resource + private GetEnergyPricesOnSolidityServlet getEnergyPricesOnSolidityServlet; + + @BeforeClass + public static void init() throws IOException { + Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + } + + @Test + public void testGet() { + MockHttpServletRequest request = createRequest(HttpGet.METHOD_NAME); + MockHttpServletResponse response = new MockHttpServletResponse(); + getEnergyPricesOnSolidityServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + assertTrue(result.containsKey("prices")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + + @Test + public void testPost() { + MockHttpServletRequest request = createRequest(HttpPost.METHOD_NAME); + try { + MockHttpServletResponse response = new MockHttpServletResponse(); + getEnergyPricesOnSolidityServlet.doPost(request, response); + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + assertTrue(result.containsKey("prices")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } +} From 8efbd8750486cb8bf98a5b9f2fd9e4a194e9a455 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 28 Aug 2023 14:43:15 +0800 Subject: [PATCH 0865/1197] add test case of WalletTest --- .../src/main/java/org/tron/core/config/args/Args.java | 1 - framework/src/test/java/org/tron/core/WalletTest.java | 10 ++++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index e19cf5c95d7..69dc8d52423 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -73,7 +73,6 @@ import org.tron.core.store.AccountStore; import org.tron.keystore.Credentials; import org.tron.keystore.WalletUtils; -import org.tron.p2p.P2pConfig; import org.tron.p2p.dns.update.DnsType; import org.tron.p2p.dns.update.PublishConfig; import org.tron.p2p.utils.NetUtil; diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 25500f13bbe..802591d8daa 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -532,6 +532,16 @@ public void getPaginatedProposalList() { } + @Test + public void testGetProposalById() { + buildProposal(); + // + Proposal proposal = wallet.getProposalById(ByteString.copyFrom(ByteArray.fromLong(1L))); + Assert.assertNotNull(proposal); + proposal = wallet.getProposalById(ByteString.copyFrom(ByteArray.fromLong(3L))); + Assert.assertNull(proposal); + } + @Test public void getPaginatedExchangeList() { buildExchange(); From 703cf87407c2c7eb24cc3bd3ff7648e5cc457555 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 29 Aug 2023 16:07:17 +0800 Subject: [PATCH 0866/1197] add test case of WalletTest --- .../test/java/org/tron/core/WalletTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 802591d8daa..e1ba2cbee5f 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -552,6 +552,24 @@ public void getPaginatedExchangeList() { exchangeList.getExchangesList().get(1).getCreatorAddress().toStringUtf8()); } + @Test + public void testGetExchangeById() { + buildExchange(); + // + Exchange exchange = wallet.getExchangeById(ByteString.copyFrom(ByteArray.fromLong(1L))); + Assert.assertNotNull(exchange); + exchange = wallet.getExchangeById(ByteString.copyFrom(ByteArray.fromLong(3L))); + Assert.assertNull(exchange); + } + + @Test + public void testGetExchangeList() { + buildExchange(); + // + ExchangeList exchangeList = wallet.getExchangeList(); + Assert.assertEquals(2, exchangeList.getExchangesCount()); + } + @Test public void getBlock() { GrpcAPI.BlockReq req = GrpcAPI.BlockReq.getDefaultInstance(); From 4ada90e5238cd627ca14001bebfe1c74956a92fb Mon Sep 17 00:00:00 2001 From: lurais <107600021+lurais@users.noreply.github.com> Date: Wed, 30 Aug 2023 17:36:30 +0800 Subject: [PATCH 0867/1197] feat(sign): optimize sign exception log (#5446) Co-authored-by: morgan.peng --- .../java/org/tron/common/crypto/SignUtils.java | 10 +++++++--- .../tron/common/crypto/BouncyCastleTest.java | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/crypto/src/main/java/org/tron/common/crypto/SignUtils.java b/crypto/src/main/java/org/tron/common/crypto/SignUtils.java index 87a55ffe655..b921d548e8b 100644 --- a/crypto/src/main/java/org/tron/common/crypto/SignUtils.java +++ b/crypto/src/main/java/org/tron/common/crypto/SignUtils.java @@ -26,10 +26,14 @@ public static SignInterface fromPrivate(byte[] privKeyBytes, boolean isECKeyCryp public static byte[] signatureToAddress( byte[] messageHash, String signatureBase64, boolean isECKeyCryptoEngine) throws SignatureException { - if (isECKeyCryptoEngine) { - return ECKey.signatureToAddress(messageHash, signatureBase64); + try { + if (isECKeyCryptoEngine) { + return ECKey.signatureToAddress(messageHash, signatureBase64); + } + return SM2.signatureToAddress(messageHash, signatureBase64); + } catch (Exception e) { + throw new SignatureException(e); } - return SM2.signatureToAddress(messageHash, signatureBase64); } public static SignatureInterface fromComponents( diff --git a/framework/src/test/java/org/tron/common/crypto/BouncyCastleTest.java b/framework/src/test/java/org/tron/common/crypto/BouncyCastleTest.java index 4e3a78461f2..880a6623a38 100644 --- a/framework/src/test/java/org/tron/common/crypto/BouncyCastleTest.java +++ b/framework/src/test/java/org/tron/common/crypto/BouncyCastleTest.java @@ -8,6 +8,7 @@ import java.util.Arrays; import org.bouncycastle.crypto.digests.SM3Digest; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Test; import org.tron.common.crypto.sm2.SM2; import org.tron.common.utils.Sha256Hash; @@ -131,4 +132,21 @@ public void testSM2SpongySignature() throws SignatureException { byte[] address = SignUtils.signatureToAddress(hash, spongySig, false); assertEquals(spongyAddress, Hex.toHexString(Arrays.copyOfRange(address, 1, 21))); } + + @Test + public void testSignToAddress() { + String messageHash = "818e0e76976123b9b78b6076cc2b5d53e61b49ff9cf78304de688a860ce7cb95"; + String base64Sign = "G1y76mVO6TRpFwp3qOiLVzHA8uFsrDiOL7hbC2uN9qTHHiLypaW4vnQkfkoUygjo5qBd" + + "+NlYQ/mAPVWKu6K00co="; + try { + SignUtils.signatureToAddress(Hex.decode(messageHash), base64Sign, Boolean.TRUE); + } catch (Exception e) { + Assert.assertTrue(e instanceof SignatureException); + } + try { + SignUtils.signatureToAddress(Hex.decode(messageHash), base64Sign, Boolean.FALSE); + } catch (Exception e) { + Assert.assertTrue(e instanceof SignatureException); + } + } } From 4d5f05a22d801062f89b3f5ed7e673188068b744 Mon Sep 17 00:00:00 2001 From: Simon <107106002+CarlChaoCarl@users.noreply.github.com> Date: Wed, 30 Aug 2023 17:40:40 +0800 Subject: [PATCH 0868/1197] fix(freezeV2): fix estimateConsumeBandWidthSize (#5450) --- .../actuator/DelegateResourceActuator.java | 2 +- .../src/main/java/org/tron/core/Wallet.java | 2 +- .../test/java/org/tron/core/WalletTest.java | 43 +++++++++++++ .../DelegateResourceActuatorTest.java | 62 ++++++++++++++++++- 4 files changed, 106 insertions(+), 3 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 6725bc349b9..776bd952711 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -158,7 +158,7 @@ public boolean validate() throws ContractValidateException { long accountNetUsage = ownerCapsule.getNetUsage(); if (null != this.getTx() && this.getTx().isTransactionCreate()) { accountNetUsage += TransactionUtil.estimateConsumeBandWidthSize(dynamicStore, - ownerCapsule.getBalance()); + ownerCapsule.getFrozenV2BalanceForBandwidth()); } long netUsage = (long) (accountNetUsage * TRX_PRECISION * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 1ddc57fdc8c..c7d1a3f50aa 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -867,7 +867,7 @@ public long calcCanDelegatedBandWidthMaxSize( long accountNetUsage = ownerCapsule.getNetUsage(); accountNetUsage += TransactionUtil.estimateConsumeBandWidthSize(dynamicStore, - ownerCapsule.getBalance()); + ownerCapsule.getFrozenV2BalanceForBandwidth()); long netUsage = (long) (accountNetUsage * TRX_PRECISION * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index e1ba2cbee5f..92bbebb8b37 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -1107,5 +1107,48 @@ public void testListNodes() { GrpcAPI.NodeList nodeList = wallet.listNodes(); assertEquals(0, nodeList.getNodesList().size()); } + + /** + * We calculate the size of the structure and conclude that + * delegate_balance = 1000_000L; => 277 + * delegate_balance = 1000_000_000L; => 279 + * delegate_balance = 1000_000_000_000L => 280 + * + * We initialize account information as follows + * account balance = 1000_000_000_000L + * account frozen_balance = 1000_000_000L + * + * then estimateConsumeBandWidthSize cost 279 + * + * so we have following result: + * TransactionUtil.estimateConsumeBandWidthSize( + * dynamicStore,ownerCapsule.getBalance()) ===> false + * TransactionUtil.estimateConsumeBandWidthSize( + * dynamicStore,ownerCapsule.getFrozenV2BalanceForBandwidth()) ===> true + * + * This test case is used to verify the above conclusions + */ + @Test + public void testGetCanDelegatedMaxSizeBandWidth123() { + long frozenBalance = 1000_000_000L; + AccountCapsule ownerCapsule = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + ownerCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + ownerCapsule.setNetUsage(0L); + ownerCapsule.setEnergyUsage(0L); + dbManager.getDynamicPropertiesStore().saveTotalNetWeight(0L); + dbManager.getDynamicPropertiesStore().saveTotalEnergyWeight(0L); + dbManager.getDynamicPropertiesStore().addTotalNetWeight( + frozenBalance / TRX_PRECISION + 43100000000L); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + + GrpcAPI.CanDelegatedMaxSizeResponseMessage message = wallet.getCanDelegatedMaxSize( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + BANDWIDTH.getNumber()); + Assert.assertEquals(frozenBalance / TRX_PRECISION - 279, + message.getMaxSize() / TRX_PRECISION); + chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(DELEGATE_PERIOD / 3000); + } + } diff --git a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java index f49f39baabd..b2ecae06177 100644 --- a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java @@ -16,6 +16,7 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.tron.common.BaseTest; @@ -25,11 +26,13 @@ import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; import org.tron.core.capsule.DelegatedResourceCapsule; +import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.config.args.Args; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.Protocol; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.contract.AssetIssueContractOuterClass; @@ -43,7 +46,7 @@ public class DelegateResourceActuatorTest extends BaseTest { private static final String RECEIVER_ADDRESS; private static final String OWNER_ADDRESS_INVALID = "aaaa"; private static final String OWNER_ACCOUNT_INVALID; - private static final long initBalance = 10_000_000_000L; + private static final long initBalance = 1000_000_000_000L; static { dbPath = "output_delegate_resource_test"; @@ -59,6 +62,7 @@ public class DelegateResourceActuatorTest extends BaseTest { */ @Before public void createAccountCapsule() { + dbManager.getDynamicPropertiesStore().saveTotalNetWeight(0L); dbManager.getDynamicPropertiesStore().saveUnfreezeDelayDays(1L); dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1L); @@ -828,4 +832,60 @@ private Any getErrorContract() { ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))).build() ); } + + + /** + * We calculate the size of the structure and conclude that + * delegate_balance = 1000_000L; => 277 + * delegate_balance = 1000_000_000L; => 279 + * delegate_balance = 1000_000_000_000L => 280 + * + * We initialize account information as follows + * account balance = 1000_000_000_000L + * account frozen_balance = 1000_000_000L + * + * then estimateConsumeBandWidthSize cost 279 + * + * so we have following result: + * TransactionUtil.estimateConsumeBandWidthSize( + * dynamicStore,ownerCapsule.getBalance()) ===> false + * TransactionUtil.estimateConsumeBandWidthSize( + * dynamicStore,ownerCapsule.getFrozenV2BalanceForBandwidth()) ===> true + * + * This test case is used to verify the above conclusions + */ + @Test + public void testDelegateResourceNoFreeze123() { + long frozenBalance = 1000_000_000L; + AccountCapsule ownerCapsule = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + ownerCapsule.addFrozenBalanceForBandwidthV2(frozenBalance); + dbManager.getDynamicPropertiesStore().addTotalNetWeight( + frozenBalance / TRX_PRECISION + 43100000000L); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + + long delegateBalance = frozenBalance - 279 * TRX_PRECISION; + //long delegateBalance = initBalance; + DelegateResourceActuator actuator = new DelegateResourceActuator(); + TransactionCapsule transactionCapsule = new TransactionCapsule( + getDelegateContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance), + Protocol.Transaction.Contract.ContractType.DelegateResourceContract + ); + transactionCapsule.setTransactionCreate(true); + actuator.setChainBaseManager(dbManager.getChainBaseManager()).setAny( + getDelegateContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, delegateBalance)); + actuator.setTx(transactionCapsule); + + boolean bSuccess = true; + try { + actuator.validate(); + } catch (ContractValidateException e) { + assertEquals( + "delegateBalance must be less than or equal to available FreezeBandwidthV2 balance", + e.getMessage()); + bSuccess = false; + } + Assert.assertEquals(true, bSuccess); + } + } From f9c42d6cb5d1667ffb3c6468633021b5056eb07e Mon Sep 17 00:00:00 2001 From: Brown Jiang <317787106@qq.com> Date: Wed, 30 Aug 2023 18:17:08 +0800 Subject: [PATCH 0869/1197] feat(net): get external IPv4 from libp2p (#5407) * get external ip from libp2p * add test case testIpFromLibP2p --- .../common/parameter/CommonParameter.java | 3 ++ .../src/main/java/org/tron/core/Constant.java | 1 - .../java/org/tron/core/config/args/Args.java | 37 +++------------ .../org/tron/core/net/TronNetService.java | 2 +- .../org/tron/core/config/args/ArgsTest.java | 45 ++++++++++++++++++- 5 files changed, 52 insertions(+), 36 deletions(-) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 3ba55f9b47f..aa9f4e40f14 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -18,6 +18,7 @@ import org.tron.core.config.args.Overlay; import org.tron.core.config.args.SeedNode; import org.tron.core.config.args.Storage; +import org.tron.p2p.P2pConfig; import org.tron.p2p.dns.update.PublishConfig; public class CommonParameter { @@ -169,6 +170,8 @@ public class CommonParameter { @Setter public int minParticipationRate; @Getter + public P2pConfig p2pConfig; + @Getter @Setter public int nodeListenPort; @Getter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 57db2d59639..3e859f6fd96 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -280,7 +280,6 @@ public class Constant { public static final String NODE_DISCOVERY_BIND_IP = "node.discovery.bind.ip"; public static final String NODE_DISCOVERY_EXTERNAL_IP = "node.discovery.external.ip"; - public static final String AMAZONAWS_URL = "http://checkip.amazonaws.com/"; public static final String NODE_BACKUP_PRIORITY = "node.backup.priority"; public static final String NODE_BACKUP_PORT = "node.backup.port"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 69dc8d52423..74a755aca7f 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -15,15 +15,12 @@ import com.typesafe.config.ConfigObject; import io.grpc.internal.GrpcUtil; import io.grpc.netty.NettyServerBuilder; -import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; -import java.net.URL; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; @@ -73,6 +70,7 @@ import org.tron.core.store.AccountStore; import org.tron.keystore.Credentials; import org.tron.keystore.WalletUtils; +import org.tron.p2p.P2pConfig; import org.tron.p2p.dns.update.DnsType; import org.tron.p2p.dns.update.PublishConfig; import org.tron.p2p.utils.NetUtil; @@ -628,6 +626,7 @@ public static void setParam(final String[] args, final String confFileName) { ? config.getInt(Constant.NODE_MIN_PARTICIPATION_RATE) : 0; + PARAMETER.p2pConfig = new P2pConfig(); PARAMETER.nodeListenPort = config.hasPath(Constant.NODE_LISTEN_PORT) ? config.getInt(Constant.NODE_LISTEN_PORT) : 0; @@ -1533,36 +1532,10 @@ private static void externalIp(final com.typesafe.config.Config config) { if (!config.hasPath(Constant.NODE_DISCOVERY_EXTERNAL_IP) || config .getString(Constant.NODE_DISCOVERY_EXTERNAL_IP).trim().isEmpty()) { if (PARAMETER.nodeExternalIp == null) { - logger.info("External IP wasn't set, using checkip.amazonaws.com to identify it..."); - BufferedReader in = null; - try { - in = new BufferedReader(new InputStreamReader( - new URL(Constant.AMAZONAWS_URL).openStream())); - PARAMETER.nodeExternalIp = in.readLine(); - if (PARAMETER.nodeExternalIp == null || PARAMETER.nodeExternalIp.trim().isEmpty()) { - throw new IOException("Invalid address: '" + PARAMETER.nodeExternalIp + "'"); - } - try { - InetAddress.getByName(PARAMETER.nodeExternalIp); - } catch (Exception e) { - throw new IOException("Invalid address: '" + PARAMETER.nodeExternalIp + "'"); - } - logger.info("External address identified: {}", PARAMETER.nodeExternalIp); - } catch (IOException e) { + logger.info("External IP wasn't set, using ipv4 from libp2p"); + PARAMETER.nodeExternalIp = PARAMETER.p2pConfig.getIp(); + if (StringUtils.isEmpty(PARAMETER.nodeExternalIp)) { PARAMETER.nodeExternalIp = PARAMETER.nodeDiscoveryBindIp; - logger.warn( - "Can't get external IP. Fall back to peer.bind.ip: " - + PARAMETER.nodeExternalIp + " :" - + e); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - //ignore - } - } - } } } else { diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 87d878be8c9..03becf5d4e9 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -148,7 +148,7 @@ public static boolean hasIpv4Stack(Set ipSet) { } private P2pConfig getConfig() { - P2pConfig config = new P2pConfig(); + P2pConfig config = parameter.getP2pConfig(); return updateConfig(config); } diff --git a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java index 143e10706aa..13e272d1e13 100644 --- a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java @@ -16,8 +16,16 @@ package org.tron.core.config.args; import com.google.common.collect.Lists; +import com.typesafe.config.Config; +import com.typesafe.config.ConfigMergeable; +import com.typesafe.config.ConfigOrigin; +import com.typesafe.config.ConfigRenderOptions; +import com.typesafe.config.ConfigValue; +import com.typesafe.config.ConfigValueType; import io.grpc.internal.GrpcUtil; import io.grpc.netty.NettyServerBuilder; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.junit.After; @@ -28,7 +36,10 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.LocalWitnesses; import org.tron.common.utils.PublicMethod; +import org.tron.common.utils.ReflectUtils; import org.tron.core.Constant; +import org.tron.core.config.Configuration; +import org.tron.core.net.peer.PeerManager; @Slf4j public class ArgsTest { @@ -44,7 +55,7 @@ public void destroy() { @Test public void get() { - Args.setParam(new String[]{"-w"}, Constant.TEST_CONF); + Args.setParam(new String[] {"-w"}, Constant.TEST_CONF); CommonParameter parameter = Args.getInstance(); @@ -55,7 +66,7 @@ public void get() { localWitnesses.initWitnessAccountAddress(true); Args.setLocalWitnesses(localWitnesses); address = ByteArray.toHexString(Args.getLocalWitnesses() - .getWitnessAccountAddress(CommonParameter.getInstance().isECKeyCryptoEngine())); + .getWitnessAccountAddress(CommonParameter.getInstance().isECKeyCryptoEngine())); Assert.assertEquals(0, parameter.getBackupPriority()); @@ -112,5 +123,35 @@ public void get() { ByteArray.toHexString(Args.getLocalWitnesses() .getWitnessAccountAddress(CommonParameter.getInstance().isECKeyCryptoEngine()))); } + + @Test + public void testIpFromLibP2p() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Args.setParam(new String[] {"-w"}, Constant.TEST_CONF); + CommonParameter parameter = Args.getInstance(); + + String configuredBindIp = parameter.getNodeDiscoveryBindIp(); + String configuredExternalIp = parameter.getNodeExternalIp(); + Assert.assertEquals("127.0.0.1", configuredBindIp); + Assert.assertEquals("46.168.1.1", configuredExternalIp); + + Config config = Configuration.getByFileName(null, Constant.TEST_CONF); + Config config2 = config.withoutPath(Constant.NODE_DISCOVERY_BIND_IP); + Config config3 = config2.withoutPath(Constant.NODE_DISCOVERY_EXTERNAL_IP); + + CommonParameter.getInstance().setNodeDiscoveryBindIp(null); + CommonParameter.getInstance().setNodeExternalIp(null); + + Method method1 = Args.class.getDeclaredMethod("bindIp", Config.class); + method1.setAccessible(true); + method1.invoke(Args.class, config3); + + Method method2 = Args.class.getDeclaredMethod("externalIp", Config.class); + method2.setAccessible(true); + method2.invoke(Args.class, config3); + + Assert.assertNotEquals(configuredBindIp, parameter.getNodeDiscoveryBindIp()); + Assert.assertNotEquals(configuredExternalIp, parameter.getNodeExternalIp()); + } } From 03e903e7db2f34a3f70e47615975c89d88bebe1f Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Wed, 30 Aug 2023 21:49:54 +0800 Subject: [PATCH 0870/1197] feat(all):name thread pools (#5425) --- .../tron/core/vm/PrecompiledContracts.java | 12 ++++--- .../common/storage/metric/DbStatService.java | 16 +++------ .../tron/core/capsule/TransactionCapsule.java | 7 ++-- .../tron/core/db2/core/SnapshotManager.java | 33 ++++++++----------- .../common/es/ExecutorServiceManager.java | 30 ++++++++++++++++- .../org/tron/consensus/pbft/PbftManager.java | 14 +++++--- .../org/tron/common/backup/BackupManager.java | 11 +++++-- .../common/backup/socket/BackupServer.java | 4 ++- .../tron/core/config/args/DynamicArgs.java | 12 +++---- .../main/java/org/tron/core/db/Manager.java | 6 ++-- .../messagehandler/PbftDataSyncHandler.java | 16 ++++++--- .../TransactionsMsgHandler.java | 21 ++++++------ .../org/tron/core/net/peer/PeerManager.java | 9 +++-- .../tron/core/net/peer/PeerStatusCheck.java | 10 +++--- .../tron/core/net/service/adv/AdvService.java | 16 +++++---- .../effective/EffectiveCheckService.java | 16 +++------ .../service/fetchblock/FetchBlockService.java | 12 +++---- .../core/net/service/relay/RelayService.java | 8 +++-- .../service/statistics/TronStatsManager.java | 13 ++++---- .../core/net/service/sync/SyncService.java | 15 +++++---- .../org/tron/core/services/RpcApiService.java | 7 ++-- .../interfaceOnPBFT/RpcApiServiceOnPBFT.java | 7 ++-- .../RpcApiServiceOnSolidity.java | 7 ++-- .../core/services/jsonrpc/JsonRpcServlet.java | 9 ++--- .../services/jsonrpc/TronJsonRpcImpl.java | 21 +++++++++--- .../java/org/tron/core/trie/TrieImpl.java | 6 ++-- 26 files changed, 201 insertions(+), 137 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 9d4aef2bf36..be7b9423f5c 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -26,7 +26,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import lombok.AllArgsConstructor; @@ -46,6 +45,7 @@ import org.tron.common.crypto.zksnark.BN128G2; import org.tron.common.crypto.zksnark.Fp; import org.tron.common.crypto.zksnark.PairingCheck; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.runtime.ProgramResult; import org.tron.common.runtime.vm.DataWord; @@ -983,11 +983,13 @@ public Pair execute(byte[] rawData) { public static class BatchValidateSign extends PrecompiledContract { private static final ExecutorService workers; + private static final String workersName = "validate-sign-contract"; private static final int ENGERYPERSIGN = 1500; private static final int MAX_SIZE = 16; static { - workers = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() / 2 + 1); + workers = ExecutorServiceManager.newFixedThreadPool(workersName, + Runtime.getRuntime().availableProcessors() / 2 + 1); } @Override @@ -1290,10 +1292,12 @@ public static class VerifyTransferProof extends VerifyProof { private static final Integer[] SIZE = {2080, 2368, 2464, 2752}; private static final ExecutorService workersInConstantCall; private static final ExecutorService workersInNonConstantCall; + private static final String constantCallName = "verify-transfer-constant-call"; + private static final String nonConstantCallName = "verify-transfer-non-constant-call"; static { - workersInConstantCall = Executors.newFixedThreadPool(5); - workersInNonConstantCall = Executors.newFixedThreadPool(5); + workersInConstantCall = ExecutorServiceManager.newFixedThreadPool(constantCallName, 5); + workersInNonConstantCall = ExecutorServiceManager.newFixedThreadPool(nonConstantCallName, 5); } @Override diff --git a/chainbase/src/main/java/org/tron/common/storage/metric/DbStatService.java b/chainbase/src/main/java/org/tron/common/storage/metric/DbStatService.java index 402ab087808..b6fa25d5901 100644 --- a/chainbase/src/main/java/org/tron/common/storage/metric/DbStatService.java +++ b/chainbase/src/main/java/org/tron/common/storage/metric/DbStatService.java @@ -1,11 +1,10 @@ package org.tron.common.storage.metric; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.prometheus.Metrics; import org.tron.core.db.common.DbSourceInter; import org.tron.core.db2.common.DB; @@ -13,10 +12,9 @@ @Slf4j(topic = "metrics") @Component public class DbStatService { - private static final ScheduledExecutorService statExecutor = - Executors.newSingleThreadScheduledExecutor( - new ThreadFactoryBuilder().setNameFormat("db-stats-thread-%d").build()); - + private final String esName = "db-stats"; + private final ScheduledExecutorService statExecutor = + ExecutorServiceManager.newSingleThreadScheduledExecutor(esName); public void register(DB db) { if (Metrics.enabled()) { @@ -32,11 +30,7 @@ public void register(DbSourceInter db) { public void shutdown() { if (Metrics.enabled()) { - try { - statExecutor.shutdown(); - } catch (Exception e) { - logger.error("{}", e.getMessage()); - } + ExecutorServiceManager.shutdownAndAwaitTermination(statExecutor, esName); } } } diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java index 1edb5b114fb..9598fd99a6b 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -33,7 +33,6 @@ import java.util.HashMap; import java.util.List; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicInteger; import lombok.Getter; @@ -43,6 +42,7 @@ import org.tron.common.crypto.ECKey.ECDSASignature; import org.tron.common.crypto.SignInterface; import org.tron.common.crypto.SignUtils; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.overlay.message.Message; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; @@ -86,8 +86,9 @@ @Slf4j(topic = "capsule") public class TransactionCapsule implements ProtoCapsule { - private static final ExecutorService executorService = Executors - .newFixedThreadPool(CommonParameter.getInstance() + private static final String esName = "valid-contract-proto"; + private static final ExecutorService executorService = ExecutorServiceManager + .newFixedThreadPool(esName, CommonParameter.getInstance() .getValidContractProtoThreadNum()); private static final String OWNER_ADDRESS = "ownerAddress_"; diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java index 96796b3c460..f5de96e5587 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java @@ -16,8 +16,6 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -25,12 +23,12 @@ import java.util.concurrent.locks.LockSupport; import java.util.stream.Collectors; import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.tron.common.error.TronDBException; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.storage.WriteOptionsWrapper; import org.tron.common.utils.FileUtil; @@ -76,6 +74,7 @@ public class SnapshotManager implements RevokingDatabase { private Map flushServices = new HashMap<>(); private ScheduledExecutorService pruneCheckpointThread = null; + private final String pruneName = "checkpoint-prune"; @Autowired @Setter @@ -95,7 +94,7 @@ public void init() { checkpointVersion = CommonParameter.getInstance().getStorage().getCheckpointVersion(); // prune checkpoint if (isV2Open()) { - pruneCheckpointThread = Executors.newSingleThreadScheduledExecutor(); + pruneCheckpointThread = ExecutorServiceManager.newSingleThreadScheduledExecutor(pruneName); pruneCheckpointThread.scheduleWithFixedDelay(() -> { try { if (!unChecked) { @@ -117,18 +116,6 @@ public void init() { exitThread.start(); } - @PreDestroy - public void close() { - try { - exitThread.interrupt(); - // help GC - exitThread = null; - flushServices.values().forEach(ExecutorService::shutdown); - } catch (Exception e) { - logger.warn("exitThread interrupt error", e); - } - } - public static String simpleDecode(byte[] bytes) { byte[] lengthBytes = Arrays.copyOf(bytes, 4); int length = Ints.fromByteArray(lengthBytes); @@ -177,7 +164,8 @@ public void add(IRevokingDB db) { Chainbase revokingDB = (Chainbase) db; dbs.add(revokingDB); flushServices.put(revokingDB.getDbName(), - MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor())); + MoreExecutors.listeningDecorator(ExecutorServiceManager.newSingleThreadExecutor( + "flush-service-" + revokingDB.getDbName()))); } private void advance() { @@ -284,8 +272,15 @@ public synchronized void disable() { @Override public void shutdown() { - if (pruneCheckpointThread != null) { - pruneCheckpointThread.shutdown(); + ExecutorServiceManager.shutdownAndAwaitTermination(pruneCheckpointThread, pruneName); + flushServices.forEach((key, value) -> ExecutorServiceManager.shutdownAndAwaitTermination(value, + "flush-service-" + key)); + try { + exitThread.interrupt(); + // help GC + exitThread = null; + } catch (Exception e) { + logger.warn("exitThread interrupt error", e); } } diff --git a/common/src/main/java/org/tron/common/es/ExecutorServiceManager.java b/common/src/main/java/org/tron/common/es/ExecutorServiceManager.java index f1e60fdcfbc..196d44ba722 100644 --- a/common/src/main/java/org/tron/common/es/ExecutorServiceManager.java +++ b/common/src/main/java/org/tron/common/es/ExecutorServiceManager.java @@ -1,12 +1,15 @@ package org.tron.common.es; import com.google.common.util.concurrent.ThreadFactoryBuilder; +import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; -@Slf4j(topic = "common") +@Slf4j(topic = "common-executor") public class ExecutorServiceManager { public static ExecutorService newSingleThreadExecutor(String name) { @@ -29,6 +32,31 @@ public static ScheduledExecutorService newSingleThreadScheduledExecutor(String n new ThreadFactoryBuilder().setNameFormat(name).setDaemon(isDaemon).build()); } + public static ExecutorService newFixedThreadPool(String name, int fixThreads) { + return newFixedThreadPool(name, fixThreads, false); + } + + public static ExecutorService newFixedThreadPool(String name, int fixThreads, boolean isDaemon) { + return Executors.newFixedThreadPool(fixThreads, + new ThreadFactoryBuilder().setNameFormat(name + "-%d").setDaemon(isDaemon).build()); + } + + public static ExecutorService newThreadPoolExecutor(int corePoolSize, int maximumPoolSize, + long keepAliveTime, TimeUnit unit, + BlockingQueue workQueue, + String name) { + return newThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, + name, false); + } + + public static ExecutorService newThreadPoolExecutor(int corePoolSize, int maximumPoolSize, + long keepAliveTime, TimeUnit unit, + BlockingQueue workQueue, + String name, boolean isDaemon) { + return new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, + new ThreadFactoryBuilder().setNameFormat(name + "-%d").setDaemon(isDaemon).build()); + } + public static void shutdownAndAwaitTermination(ExecutorService pool, String name) { if (pool == null) { return; diff --git a/consensus/src/main/java/org/tron/consensus/pbft/PbftManager.java b/consensus/src/main/java/org/tron/consensus/pbft/PbftManager.java index 2f42524e03e..9be925bdbc6 100644 --- a/consensus/src/main/java/org/tron/consensus/pbft/PbftManager.java +++ b/consensus/src/main/java/org/tron/consensus/pbft/PbftManager.java @@ -1,13 +1,14 @@ package org.tron.consensus.pbft; import com.google.protobuf.ByteString; +import java.io.Closeable; import java.util.List; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import javax.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.common.es.ExecutorServiceManager; import org.tron.consensus.base.Param; import org.tron.consensus.base.Param.Miner; import org.tron.consensus.dpos.MaintenanceManager; @@ -18,7 +19,7 @@ @Slf4j(topic = "pbft") @Component -public class PbftManager { +public class PbftManager implements Closeable { @Autowired private PbftMessageHandle pbftMessageHandle; @@ -29,8 +30,8 @@ public class PbftManager { @Autowired private ChainBaseManager chainBaseManager; - private ExecutorService executorService = Executors.newFixedThreadPool(10, - r -> new Thread(r, "Pbft")); + private final String esName = "pbft-msg-manager"; + private ExecutorService executorService = ExecutorServiceManager.newFixedThreadPool(esName, 10); @PostConstruct public void init() { @@ -111,4 +112,9 @@ public boolean verifyMsg(PbftBaseMessage msg) { return witnessList.contains(ByteString.copyFrom(msg.getPublicKey())); } + @Override + public void close() { + ExecutorServiceManager.shutdownAndAwaitTermination(executorService, esName); + } + } \ No newline at end of file diff --git a/framework/src/main/java/org/tron/common/backup/BackupManager.java b/framework/src/main/java/org/tron/common/backup/BackupManager.java index ef304164f1a..0c4a3e60dfd 100644 --- a/framework/src/main/java/org/tron/common/backup/BackupManager.java +++ b/framework/src/main/java/org/tron/common/backup/BackupManager.java @@ -9,7 +9,6 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.Set; -import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -19,6 +18,7 @@ import org.tron.common.backup.socket.EventHandler; import org.tron.common.backup.socket.MessageHandler; import org.tron.common.backup.socket.UdpEvent; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; @Slf4j(topic = "backup") @@ -39,7 +39,10 @@ public class BackupManager implements EventHandler { private Set members = new ConcurrentSet<>(); - private ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); + private final String esName = "backup-manager"; + + private ScheduledExecutorService executorService = + ExecutorServiceManager.newSingleThreadScheduledExecutor(esName); private MessageHandler messageHandler; @@ -144,6 +147,10 @@ public void handleEvent(UdpEvent udpEvent) { } } + public void stop() { + ExecutorServiceManager.shutdownAndAwaitTermination(executorService, esName); + } + @Override public void channelActivated() { init(); diff --git a/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java b/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java index fa2c0947852..2acf1e12633 100644 --- a/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java +++ b/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java @@ -19,7 +19,7 @@ @Slf4j(topic = "backup") @Component -public class BackupServer { +public class BackupServer implements AutoCloseable { private CommonParameter commonParameter = CommonParameter.getInstance(); @@ -91,10 +91,12 @@ public void initChannel(NioDatagramChannel ch) } } + @Override public void close() { logger.info("Closing backup server..."); shutdown = true; ExecutorServiceManager.shutdownAndAwaitTermination(executor, name); + backupManager.stop(); if (channel != null) { try { channel.close().await(10, TimeUnit.SECONDS); diff --git a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java index cbf167cb955..674ea0f74c6 100644 --- a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java +++ b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java @@ -7,12 +7,11 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.List; -import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; - import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; import org.tron.core.Constant; import org.tron.core.config.Configuration; @@ -26,10 +25,12 @@ public class DynamicArgs { private long lastModified = 0; - private ScheduledExecutorService reloadExecutor = Executors.newSingleThreadScheduledExecutor(); + private ScheduledExecutorService reloadExecutor; + private final String esName = "dynamic-reload"; public void init() { if (parameter.isDynamicConfigEnable()) { + reloadExecutor = ExecutorServiceManager.newSingleThreadScheduledExecutor(esName); logger.info("Start the dynamic loading configuration service"); long checkInterval = parameter.getDynamicConfigCheckInterval(); File config = getConfigFile(); @@ -108,7 +109,6 @@ private void updateTrustNodes(Config config) { } public void close() { - logger.info("Closing the dynamic loading configuration service"); - reloadExecutor.shutdown(); + ExecutorServiceManager.shutdownAndAwaitTermination(reloadExecutor, esName); } -} \ No newline at end of file +} diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index c50e8c900a1..de515fefc90 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -29,7 +29,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.PriorityBlockingQueue; @@ -206,6 +205,7 @@ public class Manager { @Setter private MerkleContainer merkleContainer; private ExecutorService validateSignService; + private String validateSignName = "validate-sign"; private boolean isRunRePushThread = true; private boolean isRunTriggerCapsuleProcessThread = true; private BlockingQueue pushTransactionQueue = new LinkedBlockingQueue<>(); @@ -536,8 +536,8 @@ public void init() { logger.info("Lite node lowestNum: {}", chainBaseManager.getLowestBlockNum()); } revokingStore.enable(); - validateSignService = Executors - .newFixedThreadPool(Args.getInstance().getValidateSignThreadNum()); + validateSignService = ExecutorServiceManager + .newFixedThreadPool(validateSignName, Args.getInstance().getValidateSignThreadNum()); rePushEs = ExecutorServiceManager.newSingleThreadExecutor(rePushEsName, true); rePushEs.submit(rePushLoop); // add contract event listener for subscribing diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java index 238d131abe8..60f614632a4 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java @@ -4,6 +4,7 @@ import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import io.netty.util.internal.ConcurrentSet; +import java.io.Closeable; import java.security.SignatureException; import java.util.ArrayList; import java.util.List; @@ -12,12 +13,12 @@ import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.Future; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.tron.common.crypto.ECKey; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; import org.tron.consensus.base.Param; @@ -34,12 +35,14 @@ @Slf4j(topic = "pbft-data-sync") @Service -public class PbftDataSyncHandler implements TronMsgHandler { +public class PbftDataSyncHandler implements TronMsgHandler, Closeable { private Map pbftCommitMessageCache = new ConcurrentHashMap<>(); - private ExecutorService executorService = Executors.newFixedThreadPool(19, - r -> new Thread(r, "valid-header-pbft-sign")); + private final String esName = "valid-header-pbft-sign"; + + private ExecutorService executorService = ExecutorServiceManager.newFixedThreadPool( + esName, 19); @Autowired private ChainBaseManager chainBaseManager; @@ -81,6 +84,11 @@ public void processPBFTCommitData(BlockCapsule block) { } } + @Override + public void close() { + ExecutorServiceManager.shutdownAndAwaitTermination(executorService, esName); + } + private void processPBFTCommitMessage(PbftCommitMessage pbftCommitMessage) { try { PbftSignDataStore pbftSignDataStore = chainBaseManager.getPbftSignDataStore(); diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java index a0109c06060..665381b31a8 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java @@ -2,15 +2,14 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.common.es.ExecutorServiceManager; import org.tron.core.config.args.Args; import org.tron.core.exception.P2pException; import org.tron.core.exception.P2pException.TypeEnum; @@ -42,19 +41,21 @@ public class TransactionsMsgHandler implements TronMsgHandler { private BlockingQueue queue = new LinkedBlockingQueue(); private int threadNum = Args.getInstance().getValidateSignThreadNum(); - private ExecutorService trxHandlePool = new ThreadPoolExecutor(threadNum, threadNum, 0L, - TimeUnit.MILLISECONDS, queue); - - private ScheduledExecutorService smartContractExecutor = Executors - .newSingleThreadScheduledExecutor(); + private final String trxEsName = "trx-msg-handler"; + private ExecutorService trxHandlePool = ExecutorServiceManager.newThreadPoolExecutor( + threadNum, threadNum, 0L, + TimeUnit.MILLISECONDS, queue, trxEsName); + private final String smartEsName = "contract-msg-handler"; + private final ScheduledExecutorService smartContractExecutor = ExecutorServiceManager + .newSingleThreadScheduledExecutor(smartEsName); public void init() { handleSmartContract(); } public void close() { - trxHandlePool.shutdown(); - smartContractExecutor.shutdown(); + ExecutorServiceManager.shutdownAndAwaitTermination(trxHandlePool, trxEsName); + ExecutorServiceManager.shutdownAndAwaitTermination(smartContractExecutor, smartEsName); } public boolean isBusy() { @@ -102,7 +103,7 @@ private void check(PeerConnection peer, TransactionsMessage msg) throws P2pExcep private void handleSmartContract() { smartContractExecutor.scheduleWithFixedDelay(() -> { try { - while (queue.size() < MAX_SMART_CONTRACT_SUBMIT_SIZE) { + while (queue.size() < MAX_SMART_CONTRACT_SUBMIT_SIZE && smartContractQueue.size() > 0) { TrxEvent event = smartContractQueue.take(); trxHandlePool.submit(() -> handleTransaction(event.getPeer(), event.getMsg())); } diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java index 6817720dff5..a80101d4f3a 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java @@ -5,13 +5,13 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; -import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationContext; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.prometheus.MetricKeys; import org.tron.common.prometheus.MetricLabels; import org.tron.common.prometheus.Metrics; @@ -25,8 +25,11 @@ public class PeerManager { private static AtomicInteger passivePeersCount = new AtomicInteger(0); @Getter private static AtomicInteger activePeersCount = new AtomicInteger(0); + private static final String esName = "peer-manager"; + + private static ScheduledExecutorService executor = + ExecutorServiceManager.newSingleThreadScheduledExecutor(esName); - private static ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); private static long DISCONNECTION_TIME_OUT = 60_000; @@ -48,7 +51,7 @@ public static void close() { p.getChannel().close(); } } - executor.shutdownNow(); + ExecutorServiceManager.shutdownAndAwaitTermination(executor, esName); } catch (Exception e) { logger.error("Peer manager shutdown failed", e); } diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java b/framework/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java index 84cf59b9bd7..6ccbf6427a7 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java @@ -1,11 +1,11 @@ package org.tron.core.net.peer; -import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.common.es.ExecutorServiceManager; import org.tron.core.config.Parameter.NetConstants; import org.tron.core.net.TronNetDelegate; import org.tron.protos.Protocol.ReasonCode; @@ -17,8 +17,10 @@ public class PeerStatusCheck { @Autowired private TronNetDelegate tronNetDelegate; - private ScheduledExecutorService peerStatusCheckExecutor = Executors - .newSingleThreadScheduledExecutor(); + private final String name = "peer-status-check"; + + private ScheduledExecutorService peerStatusCheckExecutor = ExecutorServiceManager + .newSingleThreadScheduledExecutor(name); private int blockUpdateTimeout = 30_000; @@ -33,7 +35,7 @@ public void init() { } public void close() { - peerStatusCheckExecutor.shutdown(); + ExecutorServiceManager.shutdownAndAwaitTermination(peerStatusCheckExecutor, name); } public void statusCheck() { diff --git a/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java b/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java index 03668d01837..59477e5d6f7 100644 --- a/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java +++ b/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java @@ -6,7 +6,6 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; - import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; @@ -15,15 +14,14 @@ import java.util.List; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; - import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.overlay.message.Message; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.Time; @@ -73,9 +71,13 @@ public class AdvService { .maximumSize(MAX_BLOCK_CACHE_SIZE).expireAfterWrite(1, TimeUnit.MINUTES) .recordStats().build(); - private ScheduledExecutorService spreadExecutor = Executors.newSingleThreadScheduledExecutor(); + private final String spreadName = "adv-spread"; + private final String fetchName = "adv-fetch"; + private final ScheduledExecutorService spreadExecutor = ExecutorServiceManager + .newSingleThreadScheduledExecutor(spreadName); - private ScheduledExecutorService fetchExecutor = Executors.newSingleThreadScheduledExecutor(); + private final ScheduledExecutorService fetchExecutor = ExecutorServiceManager + .newSingleThreadScheduledExecutor(fetchName); @Getter private MessageCount trxCount = new MessageCount(); @@ -102,8 +104,8 @@ public void init() { } public void close() { - spreadExecutor.shutdown(); - fetchExecutor.shutdown(); + ExecutorServiceManager.shutdownAndAwaitTermination(spreadExecutor, spreadName); + ExecutorServiceManager.shutdownAndAwaitTermination(fetchExecutor, fetchName); } public synchronized void addInvToCache(Item item) { diff --git a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java index 44fdc56f938..a4e89412bae 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/EffectiveCheckService.java @@ -2,14 +2,12 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; -import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.net.InetSocketAddress; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; -import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @@ -18,6 +16,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.common.es.ExecutorServiceManager; import org.tron.core.config.args.Args; import org.tron.core.net.TronNetDelegate; import org.tron.core.net.TronNetService; @@ -42,12 +41,13 @@ public class EffectiveCheckService { @Setter private volatile InetSocketAddress cur; private final AtomicInteger count = new AtomicInteger(0); - private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor( - new ThreadFactoryBuilder().setNameFormat("effective-thread-%d").build()); + private final String esName = "effective-check"; + private ScheduledExecutorService executor; private long MAX_HANDSHAKE_TIME = 60_000; public void init() { if (isEffectiveCheck) { + executor = ExecutorServiceManager.newSingleThreadScheduledExecutor(esName); executor.scheduleWithFixedDelay(() -> { try { findEffectiveNode(); @@ -69,13 +69,7 @@ public void triggerNext() { } public void close() { - if (executor != null) { - try { - executor.shutdown(); - } catch (Exception e) { - logger.error("Exception in shutdown effective service worker, {}", e.getMessage()); - } - } + ExecutorServiceManager.shutdownAndAwaitTermination(executor, esName); } public boolean isIsolateLand() { diff --git a/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java b/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java index 6a5b120a896..889f6f6e132 100644 --- a/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java +++ b/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java @@ -5,20 +5,17 @@ import java.util.List; import java.util.Optional; import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.concurrent.BasicThreadFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; - +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.Sha256Hash; import org.tron.core.ChainBaseManager; import org.tron.core.capsule.BlockCapsule; -import org.tron.core.config.Parameter; import org.tron.core.metrics.MetricsKey; import org.tron.core.metrics.MetricsUtil; import org.tron.core.net.TronNetDelegate; @@ -43,9 +40,10 @@ public class FetchBlockService { private static final double BLOCK_FETCH_LEFT_TIME_PERCENT = 0.5; + private final String esName = "fetch-block"; + private final ScheduledExecutorService fetchBlockWorkerExecutor = - new ScheduledThreadPoolExecutor(1, - new BasicThreadFactory.Builder().namingPattern("FetchBlockWorkerSchedule-").build()); + ExecutorServiceManager.newSingleThreadScheduledExecutor(esName); public void init() { fetchBlockWorkerExecutor.scheduleWithFixedDelay(() -> { @@ -58,7 +56,7 @@ public void init() { } public void close() { - fetchBlockWorkerExecutor.shutdown(); + ExecutorServiceManager.shutdownAndAwaitTermination(fetchBlockWorkerExecutor, esName); } public void fetchBlock(List sha256HashList, PeerConnection peer) { diff --git a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java index 665255a6594..9f1b2ef3c37 100644 --- a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java @@ -6,7 +6,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -18,6 +17,7 @@ import org.tron.common.backup.BackupManager.BackupStatusEnum; import org.tron.common.crypto.SignInterface; import org.tron.common.crypto.SignUtils; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; @@ -53,8 +53,10 @@ public class RelayService { private WitnessScheduleStore witnessScheduleStore; private BackupManager backupManager; + private final String esName = "relay-service"; - private ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); + private ScheduledExecutorService executorService = ExecutorServiceManager + .newSingleThreadScheduledExecutor(esName); private CommonParameter parameter = Args.getInstance(); @@ -95,7 +97,7 @@ public void init() { } public void close() { - executorService.shutdown(); + ExecutorServiceManager.shutdownAndAwaitTermination(executorService, esName); } public void fillHelloMessage(HelloMessage message, Channel channel) { diff --git a/framework/src/main/java/org/tron/core/net/service/statistics/TronStatsManager.java b/framework/src/main/java/org/tron/core/net/service/statistics/TronStatsManager.java index da9b4b0f2d3..caac3f7f325 100644 --- a/framework/src/main/java/org/tron/core/net/service/statistics/TronStatsManager.java +++ b/framework/src/main/java/org/tron/core/net/service/statistics/TronStatsManager.java @@ -3,11 +3,11 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import java.net.InetAddress; -import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.prometheus.MetricKeys; import org.tron.common.prometheus.MetricLabels; import org.tron.common.prometheus.Metrics; @@ -27,7 +27,10 @@ public class TronStatsManager { private static Cache cache = CacheBuilder.newBuilder() .maximumSize(3000).recordStats().build(); - private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + private final String esName = "net-traffic-collector"; + + private ScheduledExecutorService executor = + ExecutorServiceManager.newSingleThreadScheduledExecutor(esName); public static NodeStatistics getNodeStatistics(InetAddress inetAddress) { NodeStatistics nodeStatistics = cache.getIfPresent(inetAddress); @@ -49,11 +52,7 @@ public void init() { } public void close() { - try { - executor.shutdownNow(); - } catch (Exception e) { - logger.error("Exception in shutdown traffic stats worker, {}", e.getMessage()); - } + ExecutorServiceManager.shutdownAndAwaitTermination(executor, esName); } private void work() { diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index eae134758cd..1e3e18441b9 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -11,13 +11,13 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.utils.Pair; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.BlockCapsule.BlockId; @@ -54,10 +54,13 @@ public class SyncService { .expireAfterWrite(blockCacheTimeout, TimeUnit.MINUTES).initialCapacity(10_000) .recordStats().build(); - private ScheduledExecutorService fetchExecutor = Executors.newSingleThreadScheduledExecutor(); + private final String fetchEsName = "sync-fetch-block"; + private final String handleEsName = "sync-handle-block"; + private final ScheduledExecutorService fetchExecutor = ExecutorServiceManager + .newSingleThreadScheduledExecutor(fetchEsName); - private ScheduledExecutorService blockHandleExecutor = Executors - .newSingleThreadScheduledExecutor(); + private final ScheduledExecutorService blockHandleExecutor = ExecutorServiceManager + .newSingleThreadScheduledExecutor(handleEsName); private volatile boolean handleFlag = false; @@ -91,8 +94,8 @@ public void init() { } public void close() { - fetchExecutor.shutdown(); - blockHandleExecutor.shutdown(); + ExecutorServiceManager.shutdownAndAwaitTermination(fetchExecutor, fetchEsName); + ExecutorServiceManager.shutdownAndAwaitTermination(blockHandleExecutor, handleEsName); } public void startSync(PeerConnection peer) { diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 2a4ebca95b4..26861523311 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -12,7 +12,6 @@ import io.grpc.stub.StreamObserver; import java.io.IOException; import java.util.Objects; -import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -76,6 +75,7 @@ import org.tron.api.WalletGrpc.WalletImplBase; import org.tron.api.WalletSolidityGrpc.WalletSolidityImplBase; import org.tron.common.application.Service; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; @@ -204,6 +204,8 @@ public class RpcApiService implements Service { @Getter private MonitorApi monitorApi = new MonitorApi(); + private final String executorName = "rpc-full-executor"; + @Override public void init() { @@ -221,7 +223,8 @@ public void start() { if (parameter.getRpcThreadNum() > 0) { serverBuilder = serverBuilder - .executor(Executors.newFixedThreadPool(parameter.getRpcThreadNum())); + .executor(ExecutorServiceManager.newFixedThreadPool( + executorName, parameter.getRpcThreadNum())); } if (parameter.isSolidityNode()) { diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java index c003f9d3994..2457e5fc891 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java @@ -4,7 +4,6 @@ import io.grpc.netty.NettyServerBuilder; import io.grpc.stub.StreamObserver; import java.io.IOException; -import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -38,6 +37,7 @@ import org.tron.api.WalletSolidityGrpc.WalletSolidityImplBase; import org.tron.common.application.Service; import org.tron.common.crypto.ECKey; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.StringUtil; import org.tron.common.utils.Utils; @@ -85,6 +85,8 @@ public class RpcApiServiceOnPBFT implements Service { @Autowired private RpcApiAccessInterceptor apiAccessInterceptor; + private final String executorName = "rpc-pbft-executor"; + @Override public void init() { } @@ -104,7 +106,8 @@ public void start() { if (args.getRpcThreadNum() > 0) { serverBuilder = serverBuilder - .executor(Executors.newFixedThreadPool(args.getRpcThreadNum())); + .executor(ExecutorServiceManager.newFixedThreadPool( + executorName, args.getRpcThreadNum())); } serverBuilder = serverBuilder.addService(new WalletPBFTApi()); diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java index 3f4bfeda731..5bf6f1846e5 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java @@ -5,7 +5,6 @@ import io.grpc.netty.NettyServerBuilder; import io.grpc.stub.StreamObserver; import java.io.IOException; -import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -38,6 +37,7 @@ import org.tron.common.application.Service; import org.tron.common.crypto.SignInterface; import org.tron.common.crypto.SignUtils; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.StringUtil; @@ -87,6 +87,8 @@ public class RpcApiServiceOnSolidity implements Service { @Autowired private RpcApiAccessInterceptor apiAccessInterceptor; + private final String executorName = "rpc-solidity-executor"; + @Override public void init() { } @@ -105,7 +107,8 @@ public void start() { if (parameter.getRpcThreadNum() > 0) { serverBuilder = serverBuilder - .executor(Executors.newFixedThreadPool(parameter.getRpcThreadNum())); + .executor(ExecutorServiceManager.newFixedThreadPool( + executorName, parameter.getRpcThreadNum())); } serverBuilder = serverBuilder.addService(new WalletSolidityApi()); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcServlet.java b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcServlet.java index 61d163a3e8a..878b71d86b5 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcServlet.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcServlet.java @@ -26,11 +26,7 @@ public class JsonRpcServlet extends RateLimiterServlet { private JsonRpcServer rpcServer = null; @Autowired - private NodeInfoService nodeInfoService; - @Autowired - private Wallet wallet; - @Autowired - private Manager manager; + private TronJsonRpc tronJsonRpc; @Autowired private JsonRpcInterceptor interceptor; @@ -40,10 +36,9 @@ public void init(ServletConfig config) throws ServletException { super.init(config); ClassLoader cl = Thread.currentThread().getContextClassLoader(); - TronJsonRpcImpl jsonRpcImpl = new TronJsonRpcImpl(nodeInfoService, wallet, manager); Object compositeService = ProxyUtil.createCompositeServiceProxy( cl, - new Object[] {jsonRpcImpl}, + new Object[] {tronJsonRpc}, new Class[] {TronJsonRpc.class}, true); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 9b9dbbdfe70..0ca57a3b98c 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -13,6 +13,8 @@ import com.alibaba.fastjson.JSON; import com.google.protobuf.ByteString; import com.google.protobuf.GeneratedMessageV3; +import java.io.Closeable; +import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; @@ -22,7 +24,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.regex.Matcher; import java.util.regex.Pattern; import lombok.Getter; @@ -30,12 +31,15 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.bouncycastle.util.encoders.Hex; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; import org.tron.api.GrpcAPI.BytesMessage; import org.tron.api.GrpcAPI.EstimateEnergyMessage; import org.tron.api.GrpcAPI.Return; import org.tron.api.GrpcAPI.Return.response_code; import org.tron.api.GrpcAPI.TransactionExtention; import org.tron.common.crypto.Hash; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.logsfilter.ContractEventParser; import org.tron.common.logsfilter.capsule.BlockFilterCapsule; import org.tron.common.logsfilter.capsule.LogsFilterCapsule; @@ -91,7 +95,8 @@ import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; @Slf4j(topic = "API") -public class TronJsonRpcImpl implements TronJsonRpc { +@Component +public class TronJsonRpcImpl implements TronJsonRpc, Closeable { public enum RequestSource { FULLNODE, @@ -148,12 +153,15 @@ public enum RequestSource { private final NodeInfoService nodeInfoService; private final Wallet wallet; private final Manager manager; + private final String esName = "query-section"; - public TronJsonRpcImpl(NodeInfoService nodeInfoService, Wallet wallet, Manager manager) { + @Autowired + public TronJsonRpcImpl(@Autowired NodeInfoService nodeInfoService, @Autowired Wallet wallet, + @Autowired Manager manager) { this.nodeInfoService = nodeInfoService; this.wallet = wallet; this.manager = manager; - this.sectionExecutor = Executors.newFixedThreadPool(5); + this.sectionExecutor = ExecutorServiceManager.newFixedThreadPool(esName, 5); } public static void handleBLockFilter(BlockFilterCapsule blockFilterCapsule) { @@ -1370,4 +1378,9 @@ public static Object[] getFilterResult(String filterId, Map cache, byte[] root) { public static ExecutorService getExecutor() { if (executor == null) { - executor = Executors.newFixedThreadPool(4, - new ThreadFactoryBuilder().setNameFormat("trie-calc-thread-%d").build()); + executor = ExecutorServiceManager.newFixedThreadPool("trie-calc", 4); } return executor; } From 91b6f333c5c601c1173fd6ab399aab0295938dab Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 31 Aug 2023 12:03:38 +0800 Subject: [PATCH 0871/1197] test(net):add message handler test --- .../FetchInvDataMsgHandlerTest.java | 60 +++++++++ .../PbftDataSyncHandlerTest.java | 51 ++++++++ .../messagehandler/PbftMsgHandlerTest.java | 119 ++++++++++++++++++ .../TransactionsMsgHandlerTest.java | 87 +++++++++++++ 4 files changed, 317 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/net/messagehandler/PbftDataSyncHandlerTest.java create mode 100644 framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java create mode 100644 framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandlerTest.java index e885741c29c..f3258deace2 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandlerTest.java @@ -1,5 +1,65 @@ package org.tron.core.net.messagehandler; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import java.lang.reflect.Field; +import java.util.concurrent.TimeUnit; +import java.util.LinkedList; +import java.util.List; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; +import org.tron.common.utils.ReflectUtils; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.config.Parameter; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.message.adv.BlockMessage; +import org.tron.core.net.message.adv.FetchInvDataMessage; +import org.tron.core.net.peer.Item; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.service.adv.AdvService; +import org.tron.protos.Protocol; + + + public class FetchInvDataMsgHandlerTest { + @Test + public void testProcessMessage() throws Exception { + FetchInvDataMsgHandler fetchInvDataMsgHandler = new FetchInvDataMsgHandler(); + PeerConnection peer = Mockito.mock(PeerConnection.class); + TronNetDelegate tronNetDelegate = Mockito.mock(TronNetDelegate.class); + AdvService advService = Mockito.mock(AdvService.class); + + Field field = FetchInvDataMsgHandler.class.getDeclaredField("tronNetDelegate"); + field.setAccessible(true); + field.set(fetchInvDataMsgHandler, tronNetDelegate); + + Mockito.when(tronNetDelegate.allowPBFT()).thenReturn(false); + + BlockCapsule.BlockId blockId = new BlockCapsule.BlockId(); + List blockIds = new LinkedList<>(); + blockIds.add(blockId); + + Cache advInvSpread = CacheBuilder.newBuilder().maximumSize(20000) + .expireAfterWrite(1, TimeUnit.HOURS).recordStats().build(); + Mockito.when(peer.getAdvInvSpread()).thenReturn(advInvSpread); + Mockito.when(peer.isNeedSyncFromUs()).thenReturn(true); + Mockito.when(peer.isSyncFinish()).thenReturn(false); + Mockito.when(peer.getBlockBothHave()).thenReturn(blockId); + Cache syncBlockIdCache = CacheBuilder.newBuilder() + .maximumSize(2 * Parameter.NetConstants.SYNC_FETCH_BATCH_NUM).recordStats().build(); + Mockito.when(peer.getSyncBlockIdCache()).thenReturn(syncBlockIdCache); + Mockito.when(peer.getLastSyncBlockId()).thenReturn(blockId); + BlockCapsule blockCapsule = new BlockCapsule(1, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), Sha256Hash.ZERO_HASH.getByteString()); + Mockito.when(advService.getMessage(new Item(blockId, Protocol.Inventory.InventoryType.BLOCK))) + .thenReturn(new BlockMessage(blockCapsule)); + ReflectUtils.setFieldValue(fetchInvDataMsgHandler, "advService", advService); + + fetchInvDataMsgHandler.processMessage(peer, + new FetchInvDataMessage(blockIds, Protocol.Inventory.InventoryType.BLOCK)); + Assert.assertNotNull(syncBlockIdCache.getIfPresent(blockId)); + } } diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/PbftDataSyncHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/PbftDataSyncHandlerTest.java new file mode 100644 index 00000000000..37911cb1b53 --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/messagehandler/PbftDataSyncHandlerTest.java @@ -0,0 +1,51 @@ +package org.tron.core.net.messagehandler; + +import com.google.protobuf.ByteString; +import java.lang.reflect.Field; +import java.util.ArrayList; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.ChainBaseManager; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.PbftSignCapsule; +import org.tron.core.db.PbftSignDataStore; +import org.tron.core.net.message.pbft.PbftCommitMessage; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.Protocol; + +public class PbftDataSyncHandlerTest { + @Test + public void testProcessMessage() throws Exception { + PbftDataSyncHandler pbftDataSyncHandler = new PbftDataSyncHandler(); + BlockCapsule blockCapsule = new BlockCapsule(1, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), ByteString.EMPTY); + Protocol.PBFTMessage.Raw.Builder rawBuilder = Protocol.PBFTMessage.Raw.newBuilder(); + rawBuilder.setViewN(blockCapsule.getNum()) + .setEpoch(0) + .setDataType(Protocol.PBFTMessage.DataType.BLOCK) + .setMsgType(Protocol.PBFTMessage.MsgType.PREPREPARE) + .setData(blockCapsule.getBlockId().getByteString()); + Protocol.PBFTMessage.Raw raw = rawBuilder.build(); + PbftSignCapsule pbftSignCapsule = new PbftSignCapsule(raw.toByteString(), new ArrayList<>()); + PbftCommitMessage pbftCommitMessage = new PbftCommitMessage(pbftSignCapsule); + pbftDataSyncHandler.processMessage(null, pbftCommitMessage); + Assert.assertEquals(Protocol.PBFTMessage.Raw.parseFrom( + pbftCommitMessage.getPBFTCommitResult().getData()).getViewN(), 1); + + DynamicPropertiesStore dynamicPropertiesStore = Mockito.mock(DynamicPropertiesStore.class); + PbftSignDataStore pbftSignDataStore = Mockito.mock(PbftSignDataStore.class); + ChainBaseManager chainBaseManager = Mockito.mock(ChainBaseManager.class); + Mockito.when(chainBaseManager.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStore); + Mockito.when(dynamicPropertiesStore.allowPBFT()).thenReturn(true); + Mockito.when(dynamicPropertiesStore.getMaintenanceTimeInterval()).thenReturn(600L); + Mockito.when(chainBaseManager.getPbftSignDataStore()).thenReturn(pbftSignDataStore); + + Field field = PbftDataSyncHandler.class.getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(pbftDataSyncHandler, chainBaseManager); + + pbftDataSyncHandler.processPBFTCommitData(blockCapsule); + } +} diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java new file mode 100644 index 00000000000..bb1a915cd52 --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java @@ -0,0 +1,119 @@ +package org.tron.core.net.messagehandler; + +import com.google.protobuf.ByteString; +import java.io.File; +import java.lang.reflect.Field; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Collections; +import org.bouncycastle.util.encoders.Hex; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.Mockito; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.crypto.SignInterface; +import org.tron.common.crypto.SignUtils; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.PublicMethod; +import org.tron.common.utils.ReflectUtils; +import org.tron.common.utils.Sha256Hash; +import org.tron.consensus.base.Param; +import org.tron.consensus.pbft.message.PbftMessage; +import org.tron.core.Constant; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.consensus.PbftBaseImpl; +import org.tron.core.exception.P2pException; +import org.tron.core.net.TronNetService; +import org.tron.core.net.message.MessageTypes; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.peer.PeerManager; +import org.tron.p2p.P2pConfig; +import org.tron.p2p.base.Parameter; +import org.tron.p2p.connection.Channel; +import org.tron.protos.Protocol; +import static org.mockito.Mockito.mock; + +public class PbftMsgHandlerTest { + private static TronApplicationContext context; + private PeerConnection peer; + private static String dbPath = "output-pbft-message-handler-test"; + + + @BeforeClass + public static void init() { + Args.setParam(new String[] {"--output-directory", dbPath, "--debug"}, + Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + + TronNetService tronNetService = context.getBean(TronNetService.class); + Parameter.p2pConfig = new P2pConfig(); + ReflectUtils.setFieldValue(tronNetService, "p2pConfig", Parameter.p2pConfig); + } + + @AfterClass + public static void destroy() { + Args.clearParam(); + context.destroy(); + FileUtil.deleteDir(new File(dbPath)); + } + + @Before + public void clearPeers() { + try { + Field field = PeerManager.class.getDeclaredField("peers"); + field.setAccessible(true); + field.set(PeerManager.class, Collections.synchronizedList(new ArrayList<>())); + } catch (NoSuchFieldException | IllegalAccessException e) { + //ignore + } + } + + @Test + public void testPbft() throws Exception { + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); + Channel c1 = mock(Channel.class); + Mockito.when(c1.getInetSocketAddress()).thenReturn(a1); + Mockito.when(c1.getInetAddress()).thenReturn(a1.getAddress()); + PeerManager.add(context, c1); + Assert.assertEquals(1, PeerManager.getPeers().size()); + Assert.assertFalse(c1.isDisconnect()); + + peer = PeerManager.getPeers().get(0); + BlockCapsule blockCapsule = new BlockCapsule(1, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), ByteString.EMPTY); + PbftMessage pbftMessage = new PbftMessage(); + Protocol.PBFTMessage.Raw.Builder rawBuilder = Protocol.PBFTMessage.Raw.newBuilder(); + Protocol.PBFTMessage.Builder builder = Protocol.PBFTMessage.newBuilder(); + rawBuilder.setViewN(blockCapsule.getNum()) + .setEpoch(0) + .setDataType(Protocol.PBFTMessage.DataType.BLOCK) + .setMsgType(Protocol.PBFTMessage.MsgType.PREPREPARE) + .setData(blockCapsule.getBlockId().getByteString()); + Protocol.PBFTMessage.Raw raw = rawBuilder.build(); + builder.setRawData(raw); + SignInterface sign = SignUtils.fromPrivate(Hex.decode(PublicMethod.getRandomPrivateKey()), + true); + builder.setSignature(ByteString.copyFrom(sign.Base64toBytes(sign.signHash( + Sha256Hash.hash(true, raw.toByteArray()))))); + Protocol.PBFTMessage message = builder.build(); + pbftMessage.setType(MessageTypes.PBFT_MSG.asByte()); + pbftMessage.setPbftMessage(message); + pbftMessage.setData(message.toByteArray()); + pbftMessage.setSwitch(blockCapsule.isSwitch()); + Param.getInstance().setPbftInterface(context.getBean(PbftBaseImpl.class)); + peer.setNeedSyncFromPeer(false); + //Mockito.doNothing().when(pbftMessage).analyzeSignature(); + try { + context.getBean(PbftMsgHandler.class).processMessage(peer, pbftMessage); + } catch (P2pException e) { + Assert.assertEquals(P2pException.TypeEnum.BAD_MESSAGE, e.getType()); + } + + Assert.assertEquals(1, PeerManager.getPeers().size()); + } +} diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java new file mode 100644 index 00000000000..2a5cacbe0cc --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java @@ -0,0 +1,87 @@ +package org.tron.core.net.messagehandler; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import lombok.extern.slf4j.Slf4j; +import org.joda.time.DateTime; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.Mockito; +import org.tron.common.BaseTest; +import org.tron.common.utils.ByteArray; +import org.tron.core.Constant; +import org.tron.core.config.args.Args; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.message.adv.TransactionMessage; +import org.tron.core.net.message.adv.TransactionsMessage; +import org.tron.core.net.peer.Item; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.service.adv.AdvService; +import org.tron.protos.Protocol; +import org.tron.protos.contract.BalanceContract; + +@Slf4j +public class TransactionsMsgHandlerTest extends BaseTest { + @BeforeClass + public static void init() { + dbPath = "output_trxmsghandler_test"; + Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, + Constant.TEST_CONF); + + } + + @Test + public void testProcessMessage() { + TransactionsMsgHandler transactionsMsgHandler = new TransactionsMsgHandler(); + try { + Assert.assertFalse(transactionsMsgHandler.isBusy()); + + transactionsMsgHandler.init(); + + PeerConnection peer = Mockito.mock(PeerConnection.class); + TronNetDelegate tronNetDelegate = Mockito.mock(TronNetDelegate.class); + AdvService advService = Mockito.mock(AdvService.class); + + Field field = TransactionsMsgHandler.class.getDeclaredField("tronNetDelegate"); + field.setAccessible(true); + field.set(transactionsMsgHandler, tronNetDelegate); + + BalanceContract.TransferContract transferContract = BalanceContract.TransferContract + .newBuilder() + .setAmount(10) + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString("121212a9cf"))) + .setToAddress(ByteString.copyFrom(ByteArray.fromHexString("232323a9cf"))).build(); + + long transactionTimestamp = DateTime.now().minusDays(4).getMillis(); + Protocol.Transaction trx = Protocol.Transaction.newBuilder().setRawData( + Protocol.Transaction.raw.newBuilder().setTimestamp(transactionTimestamp) + .setRefBlockNum(1) + .addContract( + Protocol.Transaction.Contract.newBuilder() + .setType(Protocol.Transaction.Contract.ContractType.TransferContract) + .setParameter(Any.pack(transferContract)).build()).build()) + .build(); + Map advInvRequest = new ConcurrentHashMap<>(); + Item item = new Item(new TransactionMessage(trx).getMessageId(), + Protocol.Inventory.InventoryType.TRX); + advInvRequest.put(item, 0L); + Mockito.when(peer.getAdvInvRequest()).thenReturn(advInvRequest); + + List transactionList = new ArrayList<>(); + transactionList.add(trx); + transactionsMsgHandler.processMessage(peer, new TransactionsMessage(transactionList)); + Assert.assertNull(advInvRequest.get(item)); + //Thread.sleep(10); + } catch (Exception e) { + logger.error("error", e); + } finally { + transactionsMsgHandler.close(); + } + } +} From 04b182682c09b95155fcdc8b26a0de0af03f814b Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 31 Aug 2023 14:38:15 +0800 Subject: [PATCH 0872/1197] test(net):fix checkstyle issues --- .../org/tron/core/net/messagehandler/PbftMsgHandlerTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java index bb1a915cd52..3fec10fc163 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java @@ -1,5 +1,7 @@ package org.tron.core.net.messagehandler; +import static org.mockito.Mockito.mock; + import com.google.protobuf.ByteString; import java.io.File; import java.lang.reflect.Field; @@ -36,7 +38,7 @@ import org.tron.p2p.base.Parameter; import org.tron.p2p.connection.Channel; import org.tron.protos.Protocol; -import static org.mockito.Mockito.mock; + public class PbftMsgHandlerTest { private static TronApplicationContext context; From 868faec56880327605d3b87761afdcf7ea409700 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 31 Aug 2023 14:41:38 +0800 Subject: [PATCH 0873/1197] Revert "test(net):fix checkstyle issues" This reverts commit 04b18268 --- .../org/tron/core/net/messagehandler/PbftMsgHandlerTest.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java index 3fec10fc163..bb1a915cd52 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java @@ -1,7 +1,5 @@ package org.tron.core.net.messagehandler; -import static org.mockito.Mockito.mock; - import com.google.protobuf.ByteString; import java.io.File; import java.lang.reflect.Field; @@ -38,7 +36,7 @@ import org.tron.p2p.base.Parameter; import org.tron.p2p.connection.Channel; import org.tron.protos.Protocol; - +import static org.mockito.Mockito.mock; public class PbftMsgHandlerTest { private static TronApplicationContext context; From 6fdfd0173b8535b64b00b3f31bd5229f292ee425 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 31 Aug 2023 14:42:27 +0800 Subject: [PATCH 0874/1197] test(net):fix checkstyle issues --- .../core/net/messagehandler/FetchInvDataMsgHandlerTest.java | 2 +- .../org/tron/core/net/messagehandler/PbftMsgHandlerTest.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandlerTest.java index f3258deace2..404d275276a 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandlerTest.java @@ -3,9 +3,9 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import java.lang.reflect.Field; -import java.util.concurrent.TimeUnit; import java.util.LinkedList; import java.util.List; +import java.util.concurrent.TimeUnit; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java index bb1a915cd52..3fec10fc163 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java @@ -1,5 +1,7 @@ package org.tron.core.net.messagehandler; +import static org.mockito.Mockito.mock; + import com.google.protobuf.ByteString; import java.io.File; import java.lang.reflect.Field; @@ -36,7 +38,7 @@ import org.tron.p2p.base.Parameter; import org.tron.p2p.connection.Channel; import org.tron.protos.Protocol; -import static org.mockito.Mockito.mock; + public class PbftMsgHandlerTest { private static TronApplicationContext context; From e2fd6640f7d884f7acd25a846ed4d1979dba5fbe Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 31 Aug 2023 15:41:51 +0800 Subject: [PATCH 0875/1197] feat(net): fix failure to process FETCH_INV_DATA message --- .../tron/core/net/service/adv/AdvService.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java b/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java index 59477e5d6f7..28725b8737e 100644 --- a/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java +++ b/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java @@ -41,11 +41,11 @@ @Slf4j(topic = "net") @Component public class AdvService { - private final int MAX_INV_TO_FETCH_CACHE_SIZE = 100_000; private final int MAX_TRX_CACHE_SIZE = 50_000; private final int MAX_BLOCK_CACHE_SIZE = 10; private final int MAX_SPREAD_SIZE = 1_000; + private final long TIMEOUT = MSG_CACHE_DURATION_IN_BLOCKS * BLOCK_PRODUCED_INTERVAL; @Autowired private TronNetDelegate tronNetDelegate; @@ -264,13 +264,12 @@ private void consumerInvToFetch() { Collection peers = tronNetDelegate.getActivePeer().stream() .filter(peer -> peer.isIdle()) .collect(Collectors.toList()); - InvSender invSender = new InvSender(); - long now = System.currentTimeMillis(); synchronized (this) { if (invToFetch.isEmpty() || peers.isEmpty()) { return; } + long now = System.currentTimeMillis(); invToFetch.forEach((item, time) -> { if (time < now - MSG_CACHE_DURATION_IN_BLOCKS * BLOCK_PRODUCED_INTERVAL) { logger.info("This obj is too late to fetch, type: {} hash: {}", item.getType(), @@ -279,15 +278,16 @@ private void consumerInvToFetch() { invToFetchCache.invalidate(item); return; } - peers.stream().filter(peer -> peer.getAdvInvReceive().getIfPresent(item) != null - && invSender.getSize(peer) < MAX_TRX_FETCH_PER_PEER) - .sorted(Comparator.comparingInt(peer -> invSender.getSize(peer))) - .findFirst().ifPresent(peer -> { - if (peer.checkAndPutAdvInvRequest(item, now)) { - invSender.add(item, peer); - } - invToFetch.remove(item); - }); + peers.stream().filter(peer -> { + Long t = peer.getAdvInvReceive().getIfPresent(item); + return t != null && now - t < TIMEOUT && invSender.getSize(peer) < MAX_TRX_FETCH_PER_PEER; + }).sorted(Comparator.comparingInt(peer -> invSender.getSize(peer))) + .findFirst().ifPresent(peer -> { + if (peer.checkAndPutAdvInvRequest(item, now)) { + invSender.add(item, peer); + } + invToFetch.remove(item); + }); }); } From ad728fa64ef34857efecee59307cd6483558a025 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Thu, 31 Aug 2023 16:08:09 +0800 Subject: [PATCH 0876/1197] feat(all):tune the sequence of resources closure (#5447) --- .../tron/common/application/Application.java | 4 + .../common/application/ApplicationImpl.java | 35 +++----- .../tron/common/application/HttpService.java | 81 ++++++++++++++++++ .../tron/common/application/RpcService.java | 85 +++++++++++++++++++ .../org/tron/common/application/Service.java | 7 ++ .../common/application/ServiceContainer.java | 33 ++++--- .../application/TronApplicationContext.java | 11 ++- .../org/tron/core/config/DefaultConfig.java | 2 +- .../tron/core/config/TronLogShutdownHook.java | 5 +- .../tron/core/config/args/DynamicArgs.java | 4 + .../main/java/org/tron/core/db/Manager.java | 11 +++ .../org/tron/core/services/RpcApiService.java | 43 ++-------- .../services/http/FullNodeHttpApiService.java | 75 ++-------------- .../solidity/SolidityNodeHttpApiService.java | 29 ++----- .../JsonRpcServiceOnPBFT.java | 26 ++---- .../JsonRpcServiceOnSolidity.java | 27 ++---- .../interfaceOnPBFT/RpcApiServiceOnPBFT.java | 33 ++----- .../http/PBFT/HttpApiOnPBFTService.java | 27 ++---- .../RpcApiServiceOnSolidity.java | 32 ++----- .../solidity/HttpApiOnSolidityService.java | 27 ++---- .../jsonrpc/FullNodeJsonRpcHttpService.java | 26 ++---- .../org/tron/core/zen/ZksnarkInitService.java | 62 ++++++++++++++ .../main/java/org/tron/program/FullNode.java | 8 +- .../java/org/tron/program/SolidityNode.java | 8 +- .../PrecompiledContractsVerifyProofTest.java | 4 +- .../tron/core/ShieldedTRC20BuilderTest.java | 4 +- .../ShieldedTransferActuatorTest.java | 4 +- .../tron/core/jsonrpc/JsonrpcServiceTest.java | 24 ++++++ .../core/metrics/MetricsApiServiceTest.java | 2 - .../test/java/org/tron/core/net/BaseNet.java | 4 +- .../java/org/tron/core/pbft/PbftApiTest.java | 1 + .../org/tron/core/services/WalletApiTest.java | 2 - .../filter/HttpApiAccessFilterTest.java | 2 - .../LiteFnQueryGrpcInterceptorTest.java | 3 +- .../filter/LiteFnQueryHttpFilterTest.java | 2 - .../filter/RpcApiAccessInterceptorTest.java | 2 - .../http/TriggerSmartContractServletTest.java | 2 - .../tron/core/zksnark/LibrustzcashTest.java | 4 +- .../tron/core/zksnark/SaplingNoteTest.java | 4 +- .../tron/core/zksnark/SendCoinShieldTest.java | 4 +- .../core/zksnark/ShieldedReceiveTest.java | 4 +- .../tron/program/LiteFullNodeToolTest.java | 2 - .../org/tron/program/SolidityNodeTest.java | 1 + 43 files changed, 408 insertions(+), 368 deletions(-) create mode 100644 framework/src/main/java/org/tron/common/application/HttpService.java create mode 100644 framework/src/main/java/org/tron/common/application/RpcService.java create mode 100644 framework/src/main/java/org/tron/core/zen/ZksnarkInitService.java diff --git a/framework/src/main/java/org/tron/common/application/Application.java b/framework/src/main/java/org/tron/common/application/Application.java index fdc0abc19e0..3d7e7a10864 100644 --- a/framework/src/main/java/org/tron/common/application/Application.java +++ b/framework/src/main/java/org/tron/common/application/Application.java @@ -34,6 +34,10 @@ public interface Application { void startServices(); + // DO NOT USE THIS METHOD IN TEST CASES MAIN-THREAD + default void blockUntilShutdown() { + } + void shutdownServices(); void addService(Service service); diff --git a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java index b6bcd670a03..9133fddf434 100644 --- a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java +++ b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java @@ -3,11 +3,9 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.common.logsfilter.EventPluginLoader; import org.tron.common.parameter.CommonParameter; import org.tron.core.ChainBaseManager; import org.tron.core.config.args.Args; -import org.tron.core.config.args.DynamicArgs; import org.tron.core.consensus.ConsensusService; import org.tron.core.db.Manager; import org.tron.core.metrics.MetricsUtil; @@ -31,9 +29,6 @@ public class ApplicationImpl implements Application { @Autowired private ConsensusService consensusService; - @Autowired - private DynamicArgs dynamicArgs; - @Override public void setOptions(Args args) { // not used @@ -64,28 +59,18 @@ public void startup() { } consensusService.start(); MetricsUtil.init(); - dynamicArgs.init(); + this.initServices(Args.getInstance()); + this.startServices(); } @Override public void shutdown() { - logger.info("******** start to shutdown ********"); + this.shutdownServices(); + consensusService.stop(); if (!Args.getInstance().isSolidityNode() && (!Args.getInstance().p2pDisable)) { tronNetService.close(); } - consensusService.stop(); - synchronized (dbManager.getRevokingStore()) { - dbManager.getSession().reset(); - closeRevokingStore(); - } - dbManager.stopRePushThread(); - dbManager.stopRePushTriggerThread(); - EventPluginLoader.getInstance().stopPlugin(); - dbManager.stopFilterProcessThread(); - dbManager.stopValidateSignThread(); - getChainBaseManager().shutdown(); - dynamicArgs.close(); - logger.info("******** end to shutdown ********"); + dbManager.close(); } @Override @@ -93,6 +78,11 @@ public void startServices() { services.start(); } + @Override + public void blockUntilShutdown() { + services.blockUntilShutdown(); + } + @Override public void shutdownServices() { services.stop(); @@ -108,9 +98,4 @@ public ChainBaseManager getChainBaseManager() { return chainBaseManager; } - private void closeRevokingStore() { - logger.info("******** start to closeRevokingStore ********"); - dbManager.getRevokingStore().shutdown(); - } - } diff --git a/framework/src/main/java/org/tron/common/application/HttpService.java b/framework/src/main/java/org/tron/common/application/HttpService.java new file mode 100644 index 00000000000..76f8e74d65c --- /dev/null +++ b/framework/src/main/java/org/tron/common/application/HttpService.java @@ -0,0 +1,81 @@ +/* + * java-tron is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * java-tron is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.tron.common.application; + +import com.google.common.base.Objects; +import lombok.extern.slf4j.Slf4j; +import org.eclipse.jetty.server.Server; + +@Slf4j(topic = "rpc") +public abstract class HttpService implements Service { + + protected Server apiServer; + protected int port; + + @Override + public void blockUntilShutdown() { + if (apiServer != null) { + try { + apiServer.join(); + } catch (InterruptedException e) { + logger.warn("{}", e.getMessage()); + Thread.currentThread().interrupt(); + } + } + } + + @Override + public void start() { + if (apiServer != null) { + try { + apiServer.start(); + logger.info("{} started, listening on {}", this.getClass().getSimpleName(), port); + } catch (Exception e) { + logger.error("{}", this.getClass().getSimpleName(), e); + } + } + } + + @Override + public void stop() { + if (apiServer != null) { + logger.info("{} shutdown...", this.getClass().getSimpleName()); + try { + apiServer.stop(); + } catch (Exception e) { + logger.warn("{}", this.getClass().getSimpleName(), e); + } + logger.info("{} shutdown complete", this.getClass().getSimpleName()); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + HttpService that = (HttpService) o; + return port == that.port; + } + + @Override + public int hashCode() { + return Objects.hashCode(getClass().getSimpleName(), port); + } +} diff --git a/framework/src/main/java/org/tron/common/application/RpcService.java b/framework/src/main/java/org/tron/common/application/RpcService.java new file mode 100644 index 00000000000..cb89441174a --- /dev/null +++ b/framework/src/main/java/org/tron/common/application/RpcService.java @@ -0,0 +1,85 @@ +/* + * java-tron is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * java-tron is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.tron.common.application; + +import com.google.common.base.Objects; +import io.grpc.Server; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; + +@Slf4j(topic = "rpc") +public abstract class RpcService implements Service { + + protected Server apiServer; + protected int port; + + @Override + public void blockUntilShutdown() { + if (apiServer != null) { + try { + apiServer.awaitTermination(); + } catch (InterruptedException e) { + logger.warn("{}", e.getMessage()); + Thread.currentThread().interrupt(); + } + } + } + + @Override + public void start() { + if (apiServer != null) { + try { + apiServer.start(); + logger.info("{} started, listening on {}", this.getClass().getSimpleName(), port); + } catch (IOException e) { + logger.error("{}", this.getClass().getSimpleName(), e); + } + } + } + + @Override + public void stop() { + if (apiServer != null) { + logger.info("{} shutdown...", this.getClass().getSimpleName()); + try { + apiServer.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + logger.warn("{}", this.getClass().getSimpleName(), e); + } + logger.info("{} shutdown complete", this.getClass().getSimpleName()); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RpcService that = (RpcService) o; + return port == that.port; + } + + @Override + public int hashCode() { + return Objects.hashCode(getClass().getSimpleName(), port); + } + +} diff --git a/framework/src/main/java/org/tron/common/application/Service.java b/framework/src/main/java/org/tron/common/application/Service.java index 72cfad9bcc8..67b4e3ce9ae 100644 --- a/framework/src/main/java/org/tron/common/application/Service.java +++ b/framework/src/main/java/org/tron/common/application/Service.java @@ -23,7 +23,14 @@ public interface Service { void init(CommonParameter parameter); + /** + * Start the service. + * {@link Service#init(CommonParameter parameter) init(CommonParameter parameter)} must be called + * before this method. + */ void start(); void stop(); + + void blockUntilShutdown(); } diff --git a/framework/src/main/java/org/tron/common/application/ServiceContainer.java b/framework/src/main/java/org/tron/common/application/ServiceContainer.java index d194360c5ea..2951596add7 100644 --- a/framework/src/main/java/org/tron/common/application/ServiceContainer.java +++ b/framework/src/main/java/org/tron/common/application/ServiceContainer.java @@ -15,17 +15,19 @@ package org.tron.common.application; -import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; import lombok.extern.slf4j.Slf4j; import org.tron.common.parameter.CommonParameter; @Slf4j(topic = "app") public class ServiceContainer { - private ArrayList services; + private final Set services; public ServiceContainer() { - this.services = new ArrayList<>(); + this.services = Collections.synchronizedSet(new LinkedHashSet<>()); } public void add(Service service) { @@ -34,31 +36,38 @@ public void add(Service service) { public void init() { - for (Service service : this.services) { + this.services.forEach(service -> { logger.debug("Initing {}.", service.getClass().getSimpleName()); service.init(); - } + }); } public void init(CommonParameter parameter) { - for (Service service : this.services) { + this.services.forEach(service -> { logger.debug("Initing {}.", service.getClass().getSimpleName()); service.init(parameter); - } + }); } public void start() { - logger.debug("Starting services."); - for (Service service : this.services) { + logger.info("Starting api services."); + this.services.forEach(service -> { logger.debug("Starting {}.", service.getClass().getSimpleName()); service.start(); - } + }); + logger.info("All api services started."); } public void stop() { - for (Service service : this.services) { + logger.info("Stopping api services."); + this.services.forEach(service -> { logger.debug("Stopping {}.", service.getClass().getSimpleName()); service.stop(); - } + }); + logger.info("All api services stopped."); + } + + public void blockUntilShutdown() { + this.services.stream().findFirst().ifPresent(Service::blockUntilShutdown); } } diff --git a/framework/src/main/java/org/tron/common/application/TronApplicationContext.java b/framework/src/main/java/org/tron/common/application/TronApplicationContext.java index 482e9e6219d..64edec77c9c 100644 --- a/framework/src/main/java/org/tron/common/application/TronApplicationContext.java +++ b/framework/src/main/java/org/tron/common/application/TronApplicationContext.java @@ -2,7 +2,7 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.tron.program.FullNode; +import org.tron.core.config.TronLogShutdownHook; public class TronApplicationContext extends AnnotationConfigApplicationContext { @@ -25,10 +25,15 @@ public TronApplicationContext(String... basePackages) { public void doClose() { logger.info("******** start to close ********"); Application appT = ApplicationFactory.create(this); - appT.shutdownServices(); appT.shutdown(); super.doClose(); logger.info("******** close end ********"); - FullNode.shutDownSign = true; + TronLogShutdownHook.shutDown = true; + } + + @Override + public void registerShutdownHook() { + super.registerShutdownHook(); + TronLogShutdownHook.shutDown = false; } } diff --git a/framework/src/main/java/org/tron/core/config/DefaultConfig.java b/framework/src/main/java/org/tron/core/config/DefaultConfig.java index 6c6a0e2c566..2c4c2a8717e 100755 --- a/framework/src/main/java/org/tron/core/config/DefaultConfig.java +++ b/framework/src/main/java/org/tron/core/config/DefaultConfig.java @@ -42,7 +42,7 @@ public DefaultConfig() { Thread.setDefaultUncaughtExceptionHandler((t, e) -> logger.error("Uncaught exception", e)); } - @Bean + @Bean(destroyMethod = "") public RevokingDatabase revokingDatabase() { try { return new SnapshotManager( diff --git a/framework/src/main/java/org/tron/core/config/TronLogShutdownHook.java b/framework/src/main/java/org/tron/core/config/TronLogShutdownHook.java index f873b88ca44..f497b9a85d8 100644 --- a/framework/src/main/java/org/tron/core/config/TronLogShutdownHook.java +++ b/framework/src/main/java/org/tron/core/config/TronLogShutdownHook.java @@ -20,6 +20,9 @@ public class TronLogShutdownHook extends ShutdownHookBase { */ private final long check_times = 60 * 1000 / CHECK_SHUTDOWN_DELAY.getMilliseconds(); + // if true, shutdown hook will be executed , for example, 'java -jar FullNode.jar -[v|h]'. + public static volatile boolean shutDown = true; + public TronLogShutdownHook() { } @@ -27,7 +30,7 @@ public TronLogShutdownHook() { public void run() { try { for (int i = 0; i < check_times; i++) { - if (FullNode.shutDownSign) { + if (shutDown) { break; } addInfo("Sleeping for " + CHECK_SHUTDOWN_DELAY); diff --git a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java index 674ea0f74c6..557b8f1211b 100644 --- a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java +++ b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java @@ -9,6 +9,8 @@ import java.util.List; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.tron.common.es.ExecutorServiceManager; @@ -28,6 +30,7 @@ public class DynamicArgs { private ScheduledExecutorService reloadExecutor; private final String esName = "dynamic-reload"; + @PostConstruct public void init() { if (parameter.isDynamicConfigEnable()) { reloadExecutor = ExecutorServiceManager.newSingleThreadScheduledExecutor(esName); @@ -108,6 +111,7 @@ private void updateTrustNodes(Config config) { TronNetService.getP2pConfig().getTrustNodes().toString()); } + @PreDestroy public void close() { ExecutorServiceManager.shutdownAndAwaitTermination(reloadExecutor, esName); } diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index de515fefc90..9a2f53dd69a 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -2416,6 +2416,17 @@ private boolean isBlockWaitingLock() { return blockWaitLock.get() > NO_BLOCK_WAITING_LOCK; } + public void close() { + stopRePushThread(); + stopRePushTriggerThread(); + EventPluginLoader.getInstance().stopPlugin(); + stopFilterProcessThread(); + stopValidateSignThread(); + chainBaseManager.shutdown(); + revokingStore.shutdown(); + session.reset(); + } + private static class ValidateSignTask implements Callable { private TransactionCapsule trx; diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index ec2eebb8826..94d5b97decd 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -5,12 +5,10 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; import com.google.protobuf.ProtocolStringList; -import io.grpc.Server; import io.grpc.Status; import io.grpc.StatusRuntimeException; import io.grpc.netty.NettyServerBuilder; import io.grpc.stub.StreamObserver; -import java.io.IOException; import java.util.Objects; import java.util.concurrent.TimeUnit; import lombok.Getter; @@ -75,7 +73,7 @@ import org.tron.api.WalletExtensionGrpc; import org.tron.api.WalletGrpc.WalletImplBase; import org.tron.api.WalletSolidityGrpc.WalletSolidityImplBase; -import org.tron.common.application.Service; +import org.tron.common.application.RpcService; import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; @@ -164,15 +162,13 @@ @Component @Slf4j(topic = "API") -public class RpcApiService implements Service { +public class RpcApiService extends RpcService { public static final String CONTRACT_VALIDATE_EXCEPTION = "ContractValidateException: {}"; private static final String EXCEPTION_CAUGHT = "exception caught"; private static final String UNKNOWN_EXCEPTION_CAUGHT = "unknown exception caught: "; private static final long BLOCK_LIMIT_NUM = 100; private static final long TRANSACTION_LIMIT_NUM = 1000; - private int port = Args.getInstance().getRpcPort(); - private Server apiServer; @Autowired private Manager dbManager; @Autowired @@ -208,6 +204,7 @@ public void init() { @Override public void init(CommonParameter args) { + port = Args.getInstance().getRpcPort(); } @Override @@ -255,19 +252,10 @@ public void start() { apiServer = serverBuilder.build(); rateLimiterInterceptor.init(apiServer); - - apiServer.start(); - } catch (IOException e) { + super.start(); + } catch (Exception e) { logger.debug(e.getMessage(), e); } - - logger.info("RpcApiService has started, listening on " + port); - - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - System.err.println("*** shutting down gRPC server since JVM is shutting down"); - //server.this.stop(); - System.err.println("*** server is shutdown"); - })); } @@ -366,27 +354,6 @@ private void checkSupportShieldedTRC20Transaction() throws ZksnarkException { } } - @Override - public void stop() { - if (apiServer != null) { - apiServer.shutdown(); - } - } - - /** - * ... - */ - public void blockUntilShutdown() { - if (apiServer != null) { - try { - apiServer.awaitTermination(); - } catch (InterruptedException e) { - logger.warn("{}", e); - Thread.currentThread().interrupt(); - } - } - } - /** * DatabaseApi. */ diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index 082307fe629..55e6e07b5ec 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -1,13 +1,9 @@ package org.tron.core.services.http; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; import java.util.EnumSet; import javax.servlet.DispatcherType; import javax.servlet.Filter; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.io.FileUtils; import org.eclipse.jetty.server.ConnectionLimit; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.FilterHolder; @@ -16,24 +12,17 @@ import org.eclipse.jetty.servlet.ServletHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.common.application.Service; +import org.tron.common.application.HttpService; import org.tron.common.parameter.CommonParameter; -import org.tron.common.zksnark.JLibrustzcash; -import org.tron.common.zksnark.LibrustzcashParam.InitZksnarkParams; import org.tron.core.config.args.Args; -import org.tron.core.exception.ZksnarkException; import org.tron.core.services.filter.HttpApiAccessFilter; import org.tron.core.services.filter.HttpInterceptor; import org.tron.core.services.filter.LiteFnQueryHttpFilter; -@Component +@Component("fullNodeHttpApiService") @Slf4j(topic = "API") -public class FullNodeHttpApiService implements Service { - - private int port = Args.getInstance().getFullNodeHttpPort(); - - private Server server; +public class FullNodeHttpApiService extends HttpService { @Autowired private GetAccountServlet getAccountServlet; @@ -305,60 +294,22 @@ public class FullNodeHttpApiService implements Service { @Autowired private CancelAllUnfreezeV2Servlet cancelAllUnfreezeV2Servlet; - private static String getParamsFile(String fileName) { - InputStream in = Thread.currentThread().getContextClassLoader() - .getResourceAsStream("params" + File.separator + fileName); - File fileOut = new File(System.getProperty("java.io.tmpdir") - + File.separator + fileName + "." + System.currentTimeMillis()); - try { - FileUtils.copyToFile(in, fileOut); - } catch (IOException e) { - logger.error(e.getMessage(), e); - } - return fileOut.getAbsolutePath(); - } - - public static void librustzcashInitZksnarkParams() { - logger.info("init zk param begin"); - - if (!JLibrustzcash.isOpenZen()) { - logger.info("zen switch is off, zen will not start."); - return; - } - - String spendPath = getParamsFile("sapling-spend.params"); - String spendHash = "25fd9a0d1c1be0526c14662947ae95b758fe9f3d7fb7f55e9b4437830dcc6215a7ce3ea465" - + "914b157715b7a4d681389ea4aa84438190e185d5e4c93574d3a19a"; - - String outputPath = getParamsFile("sapling-output.params"); - String outputHash = "a1cb23b93256adce5bce2cb09cefbc96a1d16572675ceb691e9a3626ec15b5b546926ff1c" - + "536cfe3a9df07d796b32fdfc3e5d99d65567257bf286cd2858d71a6"; - - try { - JLibrustzcash.librustzcashInitZksnarkParams( - new InitZksnarkParams(spendPath, spendHash, outputPath, outputHash)); - } catch (ZksnarkException e) { - logger.error("librustzcashInitZksnarkParams fail!", e); - } - logger.info("init zk param done"); - } - @Override public void init() { } @Override public void init(CommonParameter args) { - librustzcashInitZksnarkParams(); + port = Args.getInstance().getFullNodeHttpPort(); } @Override public void start() { try { - server = new Server(port); + apiServer = new Server(port); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); - server.setHandler(context); + apiServer.setHandler(context); context.addServlet(new ServletHolder(getAccountServlet), "/wallet/getaccount"); context.addServlet(new ServletHolder(transferServlet), "/wallet/createtransaction"); @@ -571,7 +522,7 @@ public void start() { int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { - server.addBean(new ConnectionLimit(maxHttpConnectNumber, server)); + apiServer.addBean(new ConnectionLimit(maxHttpConnectNumber, apiServer)); } // filters the specified APIs @@ -595,17 +546,7 @@ public void start() { .addFilterWithMapping((Class) HttpInterceptor.class, "/*", EnumSet.of(DispatcherType.REQUEST)); context.addFilter(fh, "/*", EnumSet.of(DispatcherType.REQUEST)); - - server.start(); - } catch (Exception e) { - logger.debug("IOException: {}", e.getMessage()); - } - } - - @Override - public void stop() { - try { - server.stop(); + super.start(); } catch (Exception e) { logger.debug("IOException: {}", e.getMessage()); } diff --git a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java index 534bc504c82..a1808b4fa86 100644 --- a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java @@ -10,12 +10,11 @@ import org.eclipse.jetty.servlet.ServletHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.common.application.Service; +import org.tron.common.application.HttpService; import org.tron.common.parameter.CommonParameter; import org.tron.core.config.args.Args; import org.tron.core.services.filter.HttpApiAccessFilter; import org.tron.core.services.http.EstimateEnergyServlet; -import org.tron.core.services.http.FullNodeHttpApiService; import org.tron.core.services.http.GetAccountByIdServlet; import org.tron.core.services.http.GetAccountServlet; import org.tron.core.services.http.GetAssetIssueByIdServlet; @@ -63,11 +62,7 @@ @Component @Slf4j(topic = "API") -public class SolidityNodeHttpApiService implements Service { - - private int port = Args.getInstance().getSolidityHttpPort(); - - private Server server; +public class SolidityNodeHttpApiService extends HttpService { @Autowired private GetAccountServlet getAccountServlet; @@ -176,16 +171,16 @@ public void init() { @Override public void init(CommonParameter args) { - FullNodeHttpApiService.librustzcashInitZksnarkParams(); + port = Args.getInstance().getSolidityHttpPort(); } @Override public void start() { try { - server = new Server(port); + apiServer = new Server(port); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); - server.setHandler(context); + apiServer.setHandler(context); // same as FullNode context.addServlet(new ServletHolder(getAccountServlet), "/walletsolidity/getaccount"); @@ -294,22 +289,12 @@ public void start() { int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { - server.addBean(new ConnectionLimit(maxHttpConnectNumber, server)); + apiServer.addBean(new ConnectionLimit(maxHttpConnectNumber, apiServer)); } - server.start(); + super.start(); } catch (Exception e) { logger.debug("IOException: {}", e.getMessage()); } } - - @Override - public void stop() { - try { - server.stop(); - } catch (Exception e) { - logger.debug("Exception: {}", e.getMessage()); - } - } - } diff --git a/framework/src/main/java/org/tron/core/services/interfaceJsonRpcOnPBFT/JsonRpcServiceOnPBFT.java b/framework/src/main/java/org/tron/core/services/interfaceJsonRpcOnPBFT/JsonRpcServiceOnPBFT.java index 96da1515610..1893a46045a 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceJsonRpcOnPBFT/JsonRpcServiceOnPBFT.java +++ b/framework/src/main/java/org/tron/core/services/interfaceJsonRpcOnPBFT/JsonRpcServiceOnPBFT.java @@ -7,16 +7,12 @@ import org.eclipse.jetty.servlet.ServletHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.common.application.Service; +import org.tron.common.application.HttpService; import org.tron.common.parameter.CommonParameter; @Component @Slf4j(topic = "API") -public class JsonRpcServiceOnPBFT implements Service { - - private int port = CommonParameter.getInstance().getJsonRpcHttpPBFTPort(); - - private Server server; +public class JsonRpcServiceOnPBFT extends HttpService { @Autowired private JsonRpcOnPBFTServlet jsonRpcOnPBFTServlet; @@ -27,36 +23,28 @@ public void init() { @Override public void init(CommonParameter args) { + port = CommonParameter.getInstance().getJsonRpcHttpPBFTPort(); } @Override public void start() { try { - server = new Server(port); + apiServer = new Server(port); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); - server.setHandler(context); + apiServer.setHandler(context); context.addServlet(new ServletHolder(jsonRpcOnPBFTServlet), "/jsonrpc"); int maxHttpConnectNumber = CommonParameter.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { - server.addBean(new ConnectionLimit(maxHttpConnectNumber, server)); + apiServer.addBean(new ConnectionLimit(maxHttpConnectNumber, apiServer)); } - server.start(); + super.start(); } catch (Exception e) { logger.debug("IOException: {}", e.getMessage()); } } - - @Override - public void stop() { - try { - server.stop(); - } catch (Exception e) { - logger.debug("IOException: {}", e.getMessage()); - } - } } diff --git a/framework/src/main/java/org/tron/core/services/interfaceJsonRpcOnSolidity/JsonRpcServiceOnSolidity.java b/framework/src/main/java/org/tron/core/services/interfaceJsonRpcOnSolidity/JsonRpcServiceOnSolidity.java index 41357c13dc2..52f5b761ae2 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceJsonRpcOnSolidity/JsonRpcServiceOnSolidity.java +++ b/framework/src/main/java/org/tron/core/services/interfaceJsonRpcOnSolidity/JsonRpcServiceOnSolidity.java @@ -7,16 +7,12 @@ import org.eclipse.jetty.servlet.ServletHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.common.application.Service; +import org.tron.common.application.HttpService; import org.tron.common.parameter.CommonParameter; @Component @Slf4j(topic = "API") -public class JsonRpcServiceOnSolidity implements Service { - - private int port = CommonParameter.getInstance().getJsonRpcHttpSolidityPort(); - - private Server server; +public class JsonRpcServiceOnSolidity extends HttpService { @Autowired private JsonRpcOnSolidityServlet jsonRpcOnSolidityServlet; @@ -27,34 +23,25 @@ public void init() { @Override public void init(CommonParameter args) { + port = CommonParameter.getInstance().getJsonRpcHttpSolidityPort(); } @Override public void start() { try { - server = new Server(port); + apiServer = new Server(port); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); - server.setHandler(context); + apiServer.setHandler(context); context.addServlet(new ServletHolder(jsonRpcOnSolidityServlet), "/jsonrpc"); int maxHttpConnectNumber = CommonParameter.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { - server.addBean(new ConnectionLimit(maxHttpConnectNumber, server)); + apiServer.addBean(new ConnectionLimit(maxHttpConnectNumber, apiServer)); } + super.start(); - server.start(); - - } catch (Exception e) { - logger.debug("IOException: {}", e.getMessage()); - } - } - - @Override - public void stop() { - try { - server.stop(); } catch (Exception e) { logger.debug("IOException: {}", e.getMessage()); } diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java index 7eea053592e..2f7b1dcc15c 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java @@ -1,9 +1,7 @@ package org.tron.core.services.interfaceOnPBFT; -import io.grpc.Server; import io.grpc.netty.NettyServerBuilder; import io.grpc.stub.StreamObserver; -import java.io.IOException; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -36,8 +34,7 @@ import org.tron.api.GrpcAPI.TransactionExtention; import org.tron.api.GrpcAPI.WitnessList; import org.tron.api.WalletSolidityGrpc.WalletSolidityImplBase; -import org.tron.common.application.Service; -import org.tron.common.crypto.ECKey; +import org.tron.common.application.RpcService; import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; import org.tron.core.config.args.Args; @@ -64,10 +61,7 @@ @Slf4j(topic = "API") -public class RpcApiServiceOnPBFT implements Service { - - private int port = Args.getInstance().getRpcOnPBFTPort(); - private Server apiServer; +public class RpcApiServiceOnPBFT extends RpcService { @Autowired private WalletOnPBFT walletOnPBFT; @@ -92,7 +86,7 @@ public void init() { @Override public void init(CommonParameter parameter) { - + port = Args.getInstance().getRpcOnPBFTPort(); } @Override @@ -131,27 +125,10 @@ public void start() { apiServer = serverBuilder.build(); rateLimiterInterceptor.init(apiServer); - - apiServer.start(); - - } catch (IOException e) { + super.start(); + } catch (Exception e) { logger.debug(e.getMessage(), e); } - - logger.info("RpcApiServiceOnPBFT started, listening on " + port); - - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - System.err.println("*** shutting down gRPC server on PBFT since JVM is shutting down"); - //server.this.stop(); - System.err.println("*** server on PBFT shut down"); - })); - } - - @Override - public void stop() { - if (apiServer != null) { - apiServer.shutdown(); - } } /** diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java index 9b72f11e2bf..7a5fd0cbcde 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java @@ -9,7 +9,7 @@ import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.springframework.beans.factory.annotation.Autowired; -import org.tron.common.application.Service; +import org.tron.common.application.HttpService; import org.tron.common.parameter.CommonParameter; import org.tron.core.config.args.Args; import org.tron.core.services.filter.HttpApiAccessFilter; @@ -60,11 +60,7 @@ import org.tron.core.services.interfaceOnPBFT.http.TriggerConstantContractOnPBFTServlet; @Slf4j(topic = "API") -public class HttpApiOnPBFTService implements Service { - - private int port = Args.getInstance().getPBFTHttpPort(); - - private Server server; +public class HttpApiOnPBFTService extends HttpService { @Autowired private GetAccountOnPBFTServlet accountOnPBFTServlet; @@ -183,16 +179,16 @@ public void init() { @Override public void init(CommonParameter parameter) { - + port = Args.getInstance().getPBFTHttpPort(); } @Override public void start() { try { - server = new Server(port); + apiServer = new Server(port); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/walletpbft/"); - server.setHandler(context); + apiServer.setHandler(context); // same as FullNode context.addServlet(new ServletHolder(accountOnPBFTServlet), "/getaccount"); @@ -281,7 +277,7 @@ public void start() { int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { - server.addBean(new ConnectionLimit(maxHttpConnectNumber, server)); + apiServer.addBean(new ConnectionLimit(maxHttpConnectNumber, apiServer)); } // filters the specified APIs @@ -293,18 +289,9 @@ public void start() { context.addFilter(new FilterHolder(httpApiAccessFilter), "/*", EnumSet.allOf(DispatcherType.class)); - server.start(); + super.start(); } catch (Exception e) { logger.debug("IOException: {}", e.getMessage()); } } - - @Override - public void stop() { - try { - server.stop(); - } catch (Exception e) { - logger.debug("Exception: {}", e.getMessage()); - } - } } diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java index 75538cb5cdf..68ec79175fa 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java @@ -1,10 +1,8 @@ package org.tron.core.services.interfaceOnSolidity; import com.google.protobuf.ByteString; -import io.grpc.Server; import io.grpc.netty.NettyServerBuilder; import io.grpc.stub.StreamObserver; -import java.io.IOException; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -35,9 +33,7 @@ import org.tron.api.GrpcAPI.TransactionInfoList; import org.tron.api.GrpcAPI.WitnessList; import org.tron.api.WalletSolidityGrpc.WalletSolidityImplBase; -import org.tron.common.application.Service; -import org.tron.common.crypto.SignInterface; -import org.tron.common.crypto.SignUtils; +import org.tron.common.application.RpcService; import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.Sha256Hash; @@ -66,10 +62,8 @@ @Slf4j(topic = "API") -public class RpcApiServiceOnSolidity implements Service { +public class RpcApiServiceOnSolidity extends RpcService { - private int port = Args.getInstance().getRpcOnSolidityPort(); - private Server apiServer; @Autowired private WalletOnSolidity walletOnSolidity; @@ -94,6 +88,7 @@ public void init() { @Override public void init(CommonParameter args) { + port = Args.getInstance().getRpcOnSolidityPort(); } @Override @@ -131,20 +126,10 @@ public void start() { apiServer = serverBuilder.build(); rateLimiterInterceptor.init(apiServer); - - apiServer.start(); - - } catch (IOException e) { + super.start(); + } catch (Exception e) { logger.debug(e.getMessage(), e); } - - logger.info("RpcApiServiceOnSolidity started, listening on " + port); - - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - System.err.println("*** shutting down gRPC server on solidity since JVM is shutting down"); - //server.this.stop(); - System.err.println("*** server on solidity shut down"); - })); } private TransactionExtention transaction2Extention(Transaction transaction) { @@ -176,13 +161,6 @@ private BlockExtention block2Extention(Block block) { return builder.build(); } - @Override - public void stop() { - if (apiServer != null) { - apiServer.shutdown(); - } - } - /** * DatabaseApi. */ diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java index ba5ab49ef7a..f89be80c71b 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java @@ -9,7 +9,7 @@ import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.springframework.beans.factory.annotation.Autowired; -import org.tron.common.application.Service; +import org.tron.common.application.HttpService; import org.tron.common.parameter.CommonParameter; import org.tron.core.config.args.Args; import org.tron.core.services.filter.HttpApiAccessFilter; @@ -63,11 +63,7 @@ @Slf4j(topic = "API") -public class HttpApiOnSolidityService implements Service { - - private int port = Args.getInstance().getSolidityHttpPort(); - - private Server server; +public class HttpApiOnSolidityService extends HttpService { @Autowired private GetAccountOnSolidityServlet accountOnSolidityServlet; @@ -189,16 +185,16 @@ public void init() { @Override public void init(CommonParameter args) { - + port = Args.getInstance().getSolidityHttpPort(); } @Override public void start() { try { - server = new Server(port); + apiServer = new Server(port); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); - server.setHandler(context); + apiServer.setHandler(context); // same as FullNode context.addServlet(new ServletHolder(accountOnSolidityServlet), "/walletsolidity/getaccount"); @@ -315,20 +311,11 @@ public void start() { int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { - server.addBean(new ConnectionLimit(maxHttpConnectNumber, server)); + apiServer.addBean(new ConnectionLimit(maxHttpConnectNumber, apiServer)); } - server.start(); + super.start(); } catch (Exception e) { logger.debug("IOException: {}", e.getMessage()); } } - - @Override - public void stop() { - try { - server.stop(); - } catch (Exception e) { - logger.debug("Exception: {}", e.getMessage()); - } - } } diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/FullNodeJsonRpcHttpService.java b/framework/src/main/java/org/tron/core/services/jsonrpc/FullNodeJsonRpcHttpService.java index c38b9b198c0..ff017f9562e 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/FullNodeJsonRpcHttpService.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/FullNodeJsonRpcHttpService.java @@ -11,17 +11,13 @@ import org.eclipse.jetty.servlet.ServletHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.common.application.Service; +import org.tron.common.application.HttpService; import org.tron.common.parameter.CommonParameter; import org.tron.core.services.filter.HttpInterceptor; @Component @Slf4j(topic = "API") -public class FullNodeJsonRpcHttpService implements Service { - - private final int port = CommonParameter.getInstance().getJsonRpcHttpFullNodePort(); - - private Server server; +public class FullNodeJsonRpcHttpService extends HttpService { @Autowired private JsonRpcServlet jsonRpcServlet; @@ -32,21 +28,22 @@ public void init() { @Override public void init(CommonParameter args) { + port = CommonParameter.getInstance().getJsonRpcHttpFullNodePort(); } @Override public void start() { try { - server = new Server(port); + apiServer = new Server(port); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); - server.setHandler(context); + apiServer.setHandler(context); context.addServlet(new ServletHolder(jsonRpcServlet), "/jsonrpc"); int maxHttpConnectNumber = CommonParameter.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { - server.addBean(new ConnectionLimit(maxHttpConnectNumber, server)); + apiServer.addBean(new ConnectionLimit(maxHttpConnectNumber, apiServer)); } // filter @@ -56,19 +53,10 @@ public void start() { EnumSet.of(DispatcherType.REQUEST)); context.addFilter(fh, "/*", EnumSet.of(DispatcherType.REQUEST)); - server.start(); + super.start(); } catch (Exception e) { logger.debug("IOException: {}", e.getMessage()); } } - - @Override - public void stop() { - try { - server.stop(); - } catch (Exception e) { - logger.debug("IOException: {}", e.getMessage()); - } - } } diff --git a/framework/src/main/java/org/tron/core/zen/ZksnarkInitService.java b/framework/src/main/java/org/tron/core/zen/ZksnarkInitService.java new file mode 100644 index 00000000000..2811b50397d --- /dev/null +++ b/framework/src/main/java/org/tron/core/zen/ZksnarkInitService.java @@ -0,0 +1,62 @@ +package org.tron.core.zen; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import javax.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.FileUtils; +import org.springframework.context.annotation.DependsOn; +import org.springframework.stereotype.Component; +import org.tron.common.zksnark.JLibrustzcash; +import org.tron.common.zksnark.LibrustzcashParam; +import org.tron.core.exception.ZksnarkException; + +@Slf4j(topic = "API") +@Component +@DependsOn("fullNodeHttpApiService") +public class ZksnarkInitService { + + @PostConstruct + private void init() { + librustzcashInitZksnarkParams(); + } + + public static void librustzcashInitZksnarkParams() { + logger.info("init zk param begin"); + + if (!JLibrustzcash.isOpenZen()) { + logger.info("zen switch is off, zen will not start."); + return; + } + + String spendPath = getParamsFile("sapling-spend.params"); + String spendHash = "25fd9a0d1c1be0526c14662947ae95b758fe9f3d7fb7f55e9b4437830dcc6215a7ce3ea465" + + "914b157715b7a4d681389ea4aa84438190e185d5e4c93574d3a19a"; + + String outputPath = getParamsFile("sapling-output.params"); + String outputHash = "a1cb23b93256adce5bce2cb09cefbc96a1d16572675ceb691e9a3626ec15b5b546926ff1c" + + "536cfe3a9df07d796b32fdfc3e5d99d65567257bf286cd2858d71a6"; + + try { + JLibrustzcash.librustzcashInitZksnarkParams( + new LibrustzcashParam.InitZksnarkParams(spendPath, spendHash, outputPath, outputHash)); + } catch (ZksnarkException e) { + logger.error("librustzcashInitZksnarkParams fail!", e); + } + logger.info("init zk param done"); + } + + private static String getParamsFile(String fileName) { + InputStream in = Thread.currentThread().getContextClassLoader() + .getResourceAsStream("params" + File.separator + fileName); + File fileOut = new File(System.getProperty("java.io.tmpdir") + + File.separator + fileName + "." + System.currentTimeMillis()); + try { + FileUtils.copyToFile(in, fileOut); + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + return fileOut.getAbsolutePath(); + } +} \ No newline at end of file diff --git a/framework/src/main/java/org/tron/program/FullNode.java b/framework/src/main/java/org/tron/program/FullNode.java index 5ebf70e0d7a..0fd87eb5de0 100644 --- a/framework/src/main/java/org/tron/program/FullNode.java +++ b/framework/src/main/java/org/tron/program/FullNode.java @@ -30,8 +30,6 @@ public class FullNode { - public static volatile boolean shutDownSign = false; - public static void load(String path) { try { File file = new File(path); @@ -131,11 +129,7 @@ public static void main(String[] args) { JsonRpcServiceOnPBFT jsonRpcServiceOnPBFT = context.getBean(JsonRpcServiceOnPBFT.class); appT.addService(jsonRpcServiceOnPBFT); } - - appT.initServices(parameter); - appT.startServices(); appT.startup(); - - rpcApiService.blockUntilShutdown(); + appT.blockUntilShutdown(); } } diff --git a/framework/src/main/java/org/tron/program/SolidityNode.java b/framework/src/main/java/org/tron/program/SolidityNode.java index 6101db8068c..4cf71177803 100644 --- a/framework/src/main/java/org/tron/program/SolidityNode.java +++ b/framework/src/main/java/org/tron/program/SolidityNode.java @@ -90,14 +90,10 @@ public static void main(String[] args) { appT.addService(httpApiService); } - appT.initServices(parameter); - appT.startServices(); - appT.startup(); - SolidityNode node = new SolidityNode(appT.getDbManager()); node.start(); - - rpcApiService.blockUntilShutdown(); + appT.startup(); + appT.blockUntilShutdown(); } private void start() { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java index d97be9581b7..08ce6be57a0 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java @@ -25,13 +25,13 @@ import org.tron.core.capsule.PedersenHashCapsule; import org.tron.core.config.args.Args; import org.tron.core.exception.ZksnarkException; -import org.tron.core.services.http.FullNodeHttpApiService; import org.tron.core.vm.PrecompiledContracts.MerkleHash; import org.tron.core.vm.PrecompiledContracts.VerifyBurnProof; import org.tron.core.vm.PrecompiledContracts.VerifyMintProof; import org.tron.core.vm.PrecompiledContracts.VerifyTransferProof; import org.tron.core.zen.ShieldedTRC20ParametersBuilder; import org.tron.core.zen.ShieldedTRC20ParametersBuilder.ShieldedTRC20ParametersType; +import org.tron.core.zen.ZksnarkInitService; import org.tron.core.zen.address.DiversifierT; import org.tron.core.zen.address.ExpandedSpendingKey; import org.tron.core.zen.address.FullViewingKey; @@ -64,7 +64,7 @@ public static void init() { .fromHexString("030c8c2bc59fb3eb8afb047a8ea4b028743d23e7d38c6fa30908358431e2314d"); SHIELDED_CONTRACT_ADDRESS = WalletClient.decodeFromBase58Check(SHIELDED_CONTRACT_ADDRESS_STR); PUBLIC_TO_ADDRESS = WalletClient.decodeFromBase58Check(PUBLIC_TO_ADDRESS_STR); - FullNodeHttpApiService.librustzcashInitZksnarkParams(); + ZksnarkInitService.librustzcashInitZksnarkParams(); } @Test diff --git a/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java b/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java index e7fefd5e121..db62b04e6b0 100644 --- a/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java +++ b/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java @@ -37,10 +37,10 @@ import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ZksnarkException; -import org.tron.core.services.http.FullNodeHttpApiService; import org.tron.core.vm.PrecompiledContracts.VerifyBurnProof; import org.tron.core.vm.PrecompiledContracts.VerifyMintProof; import org.tron.core.vm.PrecompiledContracts.VerifyTransferProof; +import org.tron.core.zen.ZksnarkInitService; import org.tron.core.zen.address.DiversifierT; import org.tron.core.zen.address.ExpandedSpendingKey; import org.tron.core.zen.address.FullViewingKey; @@ -69,7 +69,7 @@ public class ShieldedTRC20BuilderTest extends BaseTest { SHIELDED_CONTRACT_ADDRESS = WalletClient.decodeFromBase58Check(SHIELDED_CONTRACT_ADDRESS_STR); DEFAULT_OVK = ByteArray .fromHexString("030c8c2bc59fb3eb8afb047a8ea4b028743d23e7d38c6fa30908358431e2314d"); - FullNodeHttpApiService.librustzcashInitZksnarkParams(); + ZksnarkInitService.librustzcashInitZksnarkParams(); PUBLIC_TO_ADDRESS = WalletClient.decodeFromBase58Check(PUBLIC_TO_ADDRESS_STR); } diff --git a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java index 5e7d33832b4..f84610cc551 100755 --- a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java @@ -27,8 +27,8 @@ import org.tron.core.exception.PermissionException; import org.tron.core.exception.ValidateSignatureException; import org.tron.core.exception.ZksnarkException; -import org.tron.core.services.http.FullNodeHttpApiService; import org.tron.core.zen.ZenTransactionBuilder; +import org.tron.core.zen.ZksnarkInitService; import org.tron.core.zen.address.DiversifierT; import org.tron.core.zen.address.ExpandedSpendingKey; import org.tron.core.zen.address.FullViewingKey; @@ -91,7 +91,7 @@ public static void init() throws ZksnarkException { } private static void librustzcashInitZksnarkParams() { - FullNodeHttpApiService.librustzcashInitZksnarkParams(); + ZksnarkInitService.librustzcashInitZksnarkParams(); } /** diff --git a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java index f3ad69d09a1..94f9d5e15f2 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java @@ -29,6 +29,8 @@ import org.tron.core.capsule.TransactionCapsule; import org.tron.core.config.args.Args; import org.tron.core.services.NodeInfoService; +import org.tron.core.services.interfaceJsonRpcOnPBFT.JsonRpcServiceOnPBFT; +import org.tron.core.services.interfaceJsonRpcOnSolidity.JsonRpcServiceOnSolidity; import org.tron.core.services.jsonrpc.FullNodeJsonRpcHttpService; import org.tron.core.services.jsonrpc.TronJsonRpcImpl; import org.tron.core.services.jsonrpc.types.BlockResult; @@ -55,10 +57,18 @@ public class JsonrpcServiceTest extends BaseTest { @Resource private FullNodeJsonRpcHttpService fullNodeJsonRpcHttpService; + @Resource + private JsonRpcServiceOnPBFT jsonRpcServiceOnPBFT; + + @Resource + private JsonRpcServiceOnSolidity jsonRpcServiceOnSolidity; + static { dbPath = "output_jsonrpc_service_test"; Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); CommonParameter.getInstance().setJsonRpcHttpFullNodeEnable(true); + CommonParameter.getInstance().setJsonRpcHttpPBFTNodeEnable(true); + CommonParameter.getInstance().setJsonRpcHttpSolidityNodeEnable(true); CommonParameter.getInstance().setMetricsPrometheusEnable(true); Metrics.init(); @@ -256,6 +266,7 @@ public void testGetTransactionByHash() { @Test public void testGetBlockByNumber2() { + fullNodeJsonRpcHttpService.init(Args.getInstance()); fullNodeJsonRpcHttpService.start(); JsonArray params = new JsonArray(); params.add(ByteArray.toJsonHex(blockCapsule.getNum())); @@ -290,4 +301,17 @@ public void testGetBlockByNumber2() { } } + @Test + public void testServicesInit() { + try { + jsonRpcServiceOnPBFT.init(Args.getInstance()); + jsonRpcServiceOnPBFT.start(); + jsonRpcServiceOnSolidity.init(Args.getInstance()); + jsonRpcServiceOnSolidity.start(); + } finally { + jsonRpcServiceOnPBFT.stop(); + jsonRpcServiceOnSolidity.stop(); + } + } + } diff --git a/framework/src/test/java/org/tron/core/metrics/MetricsApiServiceTest.java b/framework/src/test/java/org/tron/core/metrics/MetricsApiServiceTest.java index 714faea05d9..d906ba20d63 100644 --- a/framework/src/test/java/org/tron/core/metrics/MetricsApiServiceTest.java +++ b/framework/src/test/java/org/tron/core/metrics/MetricsApiServiceTest.java @@ -52,8 +52,6 @@ public void init() { rpcApiService = context.getBean(RpcApiService.class); metricsApiService = context.getBean(MetricsApiService.class); appT.addService(rpcApiService); - appT.initServices(parameter); - appT.startServices(); appT.startup(); } diff --git a/framework/src/test/java/org/tron/core/net/BaseNet.java b/framework/src/test/java/org/tron/core/net/BaseNet.java index 805f8aa76a4..1eab04fe106 100644 --- a/framework/src/test/java/org/tron/core/net/BaseNet.java +++ b/framework/src/test/java/org/tron/core/net/BaseNet.java @@ -93,8 +93,6 @@ public static void init() throws Exception { appT = ApplicationFactory.create(context); rpcApiService = context.getBean(RpcApiService.class); appT.addService(rpcApiService); - appT.initServices(parameter); - appT.startServices(); appT.startup(); try { Thread.sleep(2000); @@ -102,7 +100,7 @@ public static void init() throws Exception { //ignore } tronNetDelegate = context.getBean(TronNetDelegate.class); - rpcApiService.blockUntilShutdown(); + appT.blockUntilShutdown(); }); int tryTimes = 0; do { diff --git a/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java b/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java index 61ce5ec3625..8363e6028bc 100755 --- a/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java +++ b/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java @@ -59,6 +59,7 @@ public void pbftapi() throws IOException { Assert.assertTrue(dynamicPropertiesStore.getLatestBlockHeaderNumber() >= 10); commonDataBase.saveLatestPbftBlockNum(6); + httpApiOnPBFTService.init(Args.getInstance()); httpApiOnPBFTService.start(); CloseableHttpResponse response; try (CloseableHttpClient httpClient = HttpClients.createDefault()) { diff --git a/framework/src/test/java/org/tron/core/services/WalletApiTest.java b/framework/src/test/java/org/tron/core/services/WalletApiTest.java index 3e8316666e6..5c3ef49d67c 100644 --- a/framework/src/test/java/org/tron/core/services/WalletApiTest.java +++ b/framework/src/test/java/org/tron/core/services/WalletApiTest.java @@ -36,8 +36,6 @@ public void init() { appT = ApplicationFactory.create(context); rpcApiService = context.getBean(RpcApiService.class); appT.addService(rpcApiService); - appT.initServices(Args.getInstance()); - appT.startServices(); appT.startup(); } diff --git a/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java b/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java index 46449aab9c4..0be61682b08 100644 --- a/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java @@ -53,8 +53,6 @@ public void init() { appTest.addService(httpApiService); appTest.addService(httpApiOnSolidityService); appTest.addService(httpApiOnPBFTService); - appTest.initServices(Args.getInstance()); - appTest.startServices(); appTest.startup(); } diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java index 439bf1f718f..999b37d8fd6 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java @@ -74,6 +74,7 @@ public static void init() throws IOException { .usePlaintext() .build(); context = new TronApplicationContext(DefaultConfig.class); + context.registerShutdownHook(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); blockingStubpBFT = WalletSolidityGrpc.newBlockingStub(channelpBFT); @@ -85,8 +86,6 @@ public static void init() throws IOException { appTest.addService(rpcApiService); appTest.addService(rpcOnSolidity); appTest.addService(rpcApiServiceOnPBFT); - appTest.initServices(Args.getInstance()); - appTest.startServices(); appTest.startup(); } diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java index 5c4b955667f..5522c56075d 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java @@ -55,8 +55,6 @@ public void init() { appTest.addService(httpApiService); appTest.addService(httpApiOnSolidityService); appTest.addService(httpApiOnPBFTService); - appTest.initServices(Args.getInstance()); - appTest.startServices(); appTest.startup(); } diff --git a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java index d9f1081a285..59c4509c441 100644 --- a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java @@ -91,8 +91,6 @@ public static void init() throws IOException { appTest.addService(rpcApiService); appTest.addService(rpcApiServiceOnSolidity); appTest.addService(rpcApiServiceOnPBFT); - appTest.initServices(Args.getInstance()); - appTest.startServices(); appTest.startup(); } diff --git a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java index 8adae9b8c3d..0525ec6e9d0 100644 --- a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java @@ -55,8 +55,6 @@ public void before() { appT.addService(httpApiService); // start services - appT.initServices(Args.getInstance()); - appT.startServices(); appT.startup(); // create contract for testing diff --git a/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java b/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java index 55223bccb0c..38fdce334b2 100644 --- a/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java @@ -50,9 +50,9 @@ import org.tron.core.config.args.Args; import org.tron.core.exception.BadItemException; import org.tron.core.exception.ZksnarkException; -import org.tron.core.services.http.FullNodeHttpApiService; import org.tron.core.zen.ZenTransactionBuilder; import org.tron.core.zen.ZenTransactionBuilder.SpendDescriptionInfo; +import org.tron.core.zen.ZksnarkInitService; import org.tron.core.zen.address.DiversifierT; import org.tron.core.zen.address.ExpandedSpendingKey; import org.tron.core.zen.address.FullViewingKey; @@ -116,7 +116,7 @@ public static void test(byte[] K, byte[] ovk, byte[] cv, byte[] cm, byte[] epk) } public static void librustzcashInitZksnarkParams() { - FullNodeHttpApiService.librustzcashInitZksnarkParams(); + ZksnarkInitService.librustzcashInitZksnarkParams(); } @Test diff --git a/framework/src/test/java/org/tron/core/zksnark/SaplingNoteTest.java b/framework/src/test/java/org/tron/core/zksnark/SaplingNoteTest.java index 776e94adc3c..60f6c8c0826 100644 --- a/framework/src/test/java/org/tron/core/zksnark/SaplingNoteTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/SaplingNoteTest.java @@ -8,7 +8,7 @@ import org.tron.core.config.args.Args; import org.tron.core.exception.BadItemException; import org.tron.core.exception.ZksnarkException; -import org.tron.core.services.http.FullNodeHttpApiService; +import org.tron.core.zen.ZksnarkInitService; import org.tron.core.zen.address.DiversifierT; import org.tron.core.zen.address.PaymentAddress; import org.tron.core.zen.address.SpendingKey; @@ -21,7 +21,7 @@ public class SaplingNoteTest { public static void init() { Args.setFullNodeAllowShieldedTransaction(true); // Args.getInstance().setAllowShieldedTransaction(1); - FullNodeHttpApiService.librustzcashInitZksnarkParams(); + ZksnarkInitService.librustzcashInitZksnarkParams(); } @AfterClass diff --git a/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java b/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java index 5b480cd0274..5fafe0724dc 100644 --- a/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java @@ -64,9 +64,9 @@ import org.tron.core.exception.VMIllegalException; import org.tron.core.exception.ValidateSignatureException; import org.tron.core.exception.ZksnarkException; -import org.tron.core.services.http.FullNodeHttpApiService; import org.tron.core.zen.ZenTransactionBuilder; import org.tron.core.zen.ZenTransactionBuilder.SpendDescriptionInfo; +import org.tron.core.zen.ZksnarkInitService; import org.tron.core.zen.address.DiversifierT; import org.tron.core.zen.address.ExpandedSpendingKey; import org.tron.core.zen.address.FullViewingKey; @@ -221,7 +221,7 @@ private IncrementalMerkleVoucherContainer createSimpleMerkleVoucherContainer(byt } private void librustzcashInitZksnarkParams() { - FullNodeHttpApiService.librustzcashInitZksnarkParams(); + ZksnarkInitService.librustzcashInitZksnarkParams(); } @Test diff --git a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java index 514a5dfab76..e52021986fc 100755 --- a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java @@ -66,11 +66,11 @@ import org.tron.core.exception.VMIllegalException; import org.tron.core.exception.ValidateSignatureException; import org.tron.core.exception.ZksnarkException; -import org.tron.core.services.http.FullNodeHttpApiService; import org.tron.core.utils.TransactionUtil; import org.tron.core.zen.ZenTransactionBuilder; import org.tron.core.zen.ZenTransactionBuilder.ReceiveDescriptionInfo; import org.tron.core.zen.ZenTransactionBuilder.SpendDescriptionInfo; +import org.tron.core.zen.ZksnarkInitService; import org.tron.core.zen.address.DiversifierT; import org.tron.core.zen.address.ExpandedSpendingKey; import org.tron.core.zen.address.FullViewingKey; @@ -142,7 +142,7 @@ public void init() { } private static void librustzcashInitZksnarkParams() { - FullNodeHttpApiService.librustzcashInitZksnarkParams(); + ZksnarkInitService.librustzcashInitZksnarkParams(); } private static byte[] randomUint256() { diff --git a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java index 205b2fbd30d..c23ab213006 100644 --- a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java +++ b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java @@ -42,8 +42,6 @@ public void startApp() { appTest = ApplicationFactory.create(context); appTest.addService(context.getBean(RpcApiService.class)); appTest.addService(context.getBean(RpcApiServiceOnSolidity.class)); - appTest.initServices(Args.getInstance()); - appTest.startServices(); appTest.startup(); String fullNode = String.format("%s:%d", "127.0.0.1", diff --git a/framework/src/test/java/org/tron/program/SolidityNodeTest.java b/framework/src/test/java/org/tron/program/SolidityNodeTest.java index 422ec5e6876..4d151cda7f0 100755 --- a/framework/src/test/java/org/tron/program/SolidityNodeTest.java +++ b/framework/src/test/java/org/tron/program/SolidityNodeTest.java @@ -35,6 +35,7 @@ public class SolidityNodeTest { */ @BeforeClass public static void init() { + rpcApiService.init(Args.getInstance()); rpcApiService.start(); } From c175194f6481c457eb87f53e54b73f0a25b5a0d4 Mon Sep 17 00:00:00 2001 From: liukai Date: Mon, 28 Aug 2023 16:18:47 +0800 Subject: [PATCH 0877/1197] test(case): fix code style --- .../tron/core/db/AccountAssetStoreTest.java | 139 ++++++++++++++++++ .../org/tron/core/db/AssetIssueStoreTest.java | 91 ++++++++++++ .../tron/core/db/AssetIssueV2StoreTest.java | 92 ++++++++++++ .../org/tron/core/db/ContractStoreTest.java | 102 +++++++++++++ .../core/db/DelegatedResourceStoreTest.java | 72 +++++++++ .../org/tron/core/db/DelegationStoreTest.java | 72 +++++++++ 6 files changed, 568 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/db/AccountAssetStoreTest.java create mode 100644 framework/src/test/java/org/tron/core/db/AssetIssueStoreTest.java create mode 100644 framework/src/test/java/org/tron/core/db/AssetIssueV2StoreTest.java create mode 100644 framework/src/test/java/org/tron/core/db/ContractStoreTest.java create mode 100644 framework/src/test/java/org/tron/core/db/DelegatedResourceStoreTest.java create mode 100644 framework/src/test/java/org/tron/core/db/DelegationStoreTest.java diff --git a/framework/src/test/java/org/tron/core/db/AccountAssetStoreTest.java b/framework/src/test/java/org/tron/core/db/AccountAssetStoreTest.java new file mode 100644 index 00000000000..df670fb55ad --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/AccountAssetStoreTest.java @@ -0,0 +1,139 @@ +package org.tron.core.db; + +import com.google.common.primitives.Longs; +import com.google.protobuf.ByteString; + +import java.util.Map; +import javax.annotation.Resource; + +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.AssetIssueCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.store.AccountAssetStore; +import org.tron.core.store.AccountStore; +import org.tron.protos.Protocol; +import org.tron.protos.contract.AssetIssueContractOuterClass; + +public class AccountAssetStoreTest extends BaseTest { + + private static final byte[] ASSET_KEY = "20000".getBytes(); + private static AccountCapsule ownerCapsule; + + private static String OWNER_ADDRESS = Wallet.getAddressPreFixString() + + "abd4b9367799eaa3197fecb144eb71de1e049abc"; + private static final long TOTAL_SUPPLY = 1000_000_000L; + private static final int TRX_NUM = 10; + private static final int NUM = 1; + private static final long START_TIME = 1; + private static final long END_TIME = 2; + private static final int VOTE_SCORE = 2; + private static final String DESCRIPTION = "TRX"; + private static final String URL = "https://tron.network/"; + + @Resource + private AccountAssetStore accountAssetStore; + + @Resource + private AccountStore accountStore; + + static { + dbPath = "db_AccountAssetStore_test"; + Args.setParam( + new String[]{ + "--output-directory", dbPath, + }, + Constant.TEST_CONF + ); + } + + @Before + public void init() { + accountAssetStore.put(ASSET_KEY, Longs.toByteArray(200L)); + + ownerCapsule = + new AccountCapsule( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + ByteString.copyFromUtf8("owner"), + Protocol.AccountType.AssetIssue); + } + + + private long createAsset(String tokenName) { + long id = chainBaseManager.getDynamicPropertiesStore().getTokenIdNum() + 1; + chainBaseManager.getDynamicPropertiesStore().saveTokenIdNum(id); + AssetIssueContractOuterClass.AssetIssueContract assetIssueContract = + AssetIssueContractOuterClass.AssetIssueContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setName(ByteString.copyFrom(ByteArray.fromString(tokenName))) + .setId(Long.toString(id)) + .setTotalSupply(TOTAL_SUPPLY) + .setTrxNum(TRX_NUM) + .setNum(NUM) + .setStartTime(START_TIME) + .setEndTime(END_TIME) + .setVoteScore(VOTE_SCORE) + .setDescription(ByteString.copyFrom(ByteArray.fromString(DESCRIPTION))) + .setUrl(ByteString.copyFrom(ByteArray.fromString(URL))) + .build(); + AssetIssueCapsule assetIssueCapsule = new AssetIssueCapsule(assetIssueContract); + chainBaseManager.getAssetIssueV2Store() + .put(assetIssueCapsule.createDbV2Key(), assetIssueCapsule); + try { + ownerCapsule.addAssetV2(ByteArray.fromString(String.valueOf(id)), TOTAL_SUPPLY); + } catch (Exception e) { + e.printStackTrace(); + } + accountStore.put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + return id; + } + + @Test + public void testPut() { + byte[] key = "10000".getBytes(); + accountAssetStore.put(key, Longs.toByteArray(100L)); + byte[] bytes = accountAssetStore.get(key); + Assert.assertEquals(100L, Longs.fromByteArray(bytes)); + } + + @Test + public void testGet() { + byte[] bytes = accountAssetStore.get(ASSET_KEY); + Assert.assertEquals(200L, Longs.fromByteArray(bytes)); + } + + @Test + public void testGetAccountAssets() { + long assetKey = createAsset("testToken1"); + AccountCapsule accountCapsule = accountStore.get(ownerCapsule.getAddress().toByteArray()); + long assetValue = accountCapsule.getAssetV2(String.valueOf(assetKey)); + Assert.assertEquals(assetValue, TOTAL_SUPPLY); + } + + @Test + public void testGetAllAssets() { + long assetKey1 = createAsset("testToken1"); + long assetKey2 = createAsset("testToken2"); + AccountCapsule accountCapsule = accountStore.get(ownerCapsule.getAddress().toByteArray()); + + Map allAssets = accountAssetStore.getAllAssets(accountCapsule.getInstance()); + Long assetValue1 = allAssets.get(String.valueOf(assetKey1)); + Assert.assertNotNull(assetValue1); + + Long assetV1 = accountCapsule.getAssetV2(String.valueOf(assetKey1)); + Assert.assertEquals(assetValue1, assetV1); + + Long assetValue2 = allAssets.get(String.valueOf(assetKey2)); + Assert.assertNotNull(assetValue2); + + Long assetV2 = accountCapsule.getAssetV2(String.valueOf(assetKey2)); + Assert.assertEquals(assetValue1, assetV2); + } + +} diff --git a/framework/src/test/java/org/tron/core/db/AssetIssueStoreTest.java b/framework/src/test/java/org/tron/core/db/AssetIssueStoreTest.java new file mode 100644 index 00000000000..8e448c246e2 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/AssetIssueStoreTest.java @@ -0,0 +1,91 @@ +package org.tron.core.db; + +import com.google.protobuf.ByteString; +import javax.annotation.Resource; +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.capsule.AssetIssueCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.store.AssetIssueStore; +import org.tron.protos.contract.AssetIssueContractOuterClass; + +public class AssetIssueStoreTest extends BaseTest { + + private static final String NAME = "test-asset"; + private static final long TOTAL_SUPPLY = 10000L; + private static final int TRX_NUM = 10000; + private static final int NUM = 100000; + private static final String DESCRIPTION = "myCoin"; + private static final String URL = "tron.network"; + + @Resource + private AssetIssueStore assetIssueStore; + + static { + dbPath = "db_AssetIssueStoreTest_test"; + Args.setParam( + new String[]{ + "--output-directory", dbPath, + }, + Constant.TEST_CONF + ); + } + + @Before + public void init() { + long id = dbManager.getDynamicPropertiesStore().getTokenIdNum() + 1; + AssetIssueCapsule assetIssueCapsule = createAssetIssue(id, NAME); + assetIssueStore.put(assetIssueCapsule.createDbKey(), assetIssueCapsule); + } + + private AssetIssueCapsule createAssetIssue(long id, String name) { + dbManager.getDynamicPropertiesStore().saveTokenIdNum(id); + AssetIssueContractOuterClass.AssetIssueContract assetIssueContract = + AssetIssueContractOuterClass.AssetIssueContract.newBuilder() + .setName(ByteString.copyFrom(ByteArray.fromString(name))).setId(Long.toString(id)) + .setTotalSupply(TOTAL_SUPPLY) + .setTrxNum(TRX_NUM).setNum(NUM).setStartTime(1).setEndTime(100).setVoteScore(2) + .setDescription(ByteString.copyFrom(ByteArray.fromString(DESCRIPTION))) + .setUrl(ByteString.copyFrom(ByteArray.fromString(URL))).build(); + AssetIssueCapsule assetIssueCapsule = new AssetIssueCapsule(assetIssueContract); + return assetIssueCapsule; + } + + @Test + public void testPut() { + long id = dbManager.getDynamicPropertiesStore().getTokenIdNum() + 1; + String issueName = "test-asset2"; + AssetIssueCapsule assetIssueCapsule = createAssetIssue(id, issueName); + assetIssueStore.put(assetIssueCapsule.createDbKey(), assetIssueCapsule); + AssetIssueCapsule assetIssueCapsule1 = assetIssueStore.get(ByteArray.fromString(issueName)); + + Assert.assertNotNull(assetIssueCapsule1); + Assert.assertEquals(issueName, new String(assetIssueCapsule1.getName().toByteArray())); + } + + @Test + public void testGet() { + AssetIssueCapsule assetIssueCapsule = assetIssueStore.get(ByteArray.fromString(NAME)); + Assert.assertNotNull(assetIssueCapsule); + Assert.assertEquals(NAME, new String(assetIssueCapsule.getName().toByteArray())); + Assert.assertEquals(TOTAL_SUPPLY, assetIssueCapsule.getInstance().getTotalSupply()); + } + + @Test + public void testDelete() { + long id = dbManager.getDynamicPropertiesStore().getTokenIdNum() + 1; + String issueName = "test-asset-delete"; + AssetIssueCapsule assetIssueCapsule = createAssetIssue(id, issueName); + assetIssueStore.put(assetIssueCapsule.createDbKey(), assetIssueCapsule); + AssetIssueCapsule assetIssueCapsule1 = assetIssueStore.get(ByteArray.fromString(issueName)); + Assert.assertNotNull(assetIssueCapsule1); + assetIssueStore.delete(assetIssueCapsule1.createDbKey()); + AssetIssueCapsule assetIssueCapsule2 = assetIssueStore.get(ByteArray.fromString(issueName)); + Assert.assertNull(assetIssueCapsule2); + + } +} diff --git a/framework/src/test/java/org/tron/core/db/AssetIssueV2StoreTest.java b/framework/src/test/java/org/tron/core/db/AssetIssueV2StoreTest.java new file mode 100644 index 00000000000..c24706fcc40 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/AssetIssueV2StoreTest.java @@ -0,0 +1,92 @@ +package org.tron.core.db; + +import com.google.protobuf.ByteString; +import javax.annotation.Resource; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.BaseTest; +import org.tron.core.Constant; +import org.tron.core.capsule.AssetIssueCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.store.AssetIssueV2Store; +import org.tron.protos.contract.AssetIssueContractOuterClass; + + +public class AssetIssueV2StoreTest extends BaseTest { + + static { + dbPath = "db_AssetIssueV2StoreTest_test"; + Args.setParam( + new String[]{ + "--output-directory", dbPath, + }, + Constant.TEST_CONF + ); + } + + private AssetIssueCapsule assetIssueCapsule; + + @Resource + private AssetIssueV2Store assetIssueV2Store; + + @Before + public void init() { + String firstTokenId = "abc"; + assetIssueCapsule = + new AssetIssueCapsule( + AssetIssueContractOuterClass.AssetIssueContract.newBuilder() + .setName(ByteString.copyFrom(firstTokenId.getBytes())) + .build()); + assetIssueCapsule.setId(String.valueOf(1L)); + assetIssueV2Store + .put(assetIssueCapsule.createDbV2Key(), assetIssueCapsule); + } + + @Test + public void testPut() { + String firstTokenId = "efg"; + assetIssueCapsule = + new AssetIssueCapsule( + AssetIssueContractOuterClass.AssetIssueContract.newBuilder() + .setName(ByteString.copyFrom(firstTokenId.getBytes())) + .build()); + assetIssueCapsule.setId(String.valueOf(2L)); + assetIssueV2Store + .put(assetIssueCapsule.createDbV2Key(), assetIssueCapsule); + AssetIssueCapsule assetIssueCapsule = + assetIssueV2Store.get(this.assetIssueCapsule.createDbV2Key()); + Assert.assertNotNull(assetIssueCapsule); + String assetName = new String(assetIssueCapsule.getName().toByteArray()); + Assert.assertEquals(firstTokenId, assetName); + } + + @Test + public void testGet() { + AssetIssueCapsule assetIssueCapsule1 = assetIssueV2Store.get(assetIssueCapsule.createDbV2Key()); + Assert.assertNotNull(assetIssueCapsule1); + String assetName = new String(assetIssueCapsule1.getName().toByteArray()); + Assert.assertEquals("abc", assetName); + } + + @Test + public void testDelete() { + String firstTokenId = "hij"; + assetIssueCapsule = + new AssetIssueCapsule( + AssetIssueContractOuterClass.AssetIssueContract.newBuilder() + .setName(ByteString.copyFrom(firstTokenId.getBytes())) + .build()); + assetIssueCapsule.setId(String.valueOf(2L)); + assetIssueV2Store + .put(assetIssueCapsule.createDbV2Key(), assetIssueCapsule); + AssetIssueCapsule assetIssueCapsule = + assetIssueV2Store.get(this.assetIssueCapsule.createDbV2Key()); + Assert.assertNotNull(assetIssueCapsule); + + assetIssueV2Store.delete(assetIssueCapsule.createDbV2Key()); + AssetIssueCapsule assetIssueCapsule1 = + assetIssueV2Store.get(this.assetIssueCapsule.createDbV2Key()); + Assert.assertNull(assetIssueCapsule1); + } +} diff --git a/framework/src/test/java/org/tron/core/db/ContractStoreTest.java b/framework/src/test/java/org/tron/core/db/ContractStoreTest.java new file mode 100644 index 00000000000..6b461c02bfe --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/ContractStoreTest.java @@ -0,0 +1,102 @@ +package org.tron.core.db; + +import com.google.protobuf.ByteString; +import javax.annotation.Resource; +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.ContractCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.store.ContractStore; +import org.tron.protos.contract.SmartContractOuterClass; + +public class ContractStoreTest extends BaseTest { + + private static final String SMART_CONTRACT_NAME = "smart_contract_test"; + private static final String CONTRACT_ADDRESS = "111111"; + private static final long SOURCE_ENERGY_LIMIT = 10L; + private static String OWNER_ADDRESS; + + static { + dbPath = "db_ContractStoreTest_test"; + Args.setParam( + new String[]{ + "--output-directory", dbPath, + }, + Constant.TEST_CONF + ); + } + + @Resource + private ContractStore contractStore; + + @Before + public void init() { + SmartContractOuterClass.SmartContract.Builder contract = + createContract(CONTRACT_ADDRESS, SMART_CONTRACT_NAME); + contractStore.put( + ByteArray.fromHexString(CONTRACT_ADDRESS), + new ContractCapsule(contract.build())); + } + + private SmartContractOuterClass.SmartContract.Builder createContract( + String contractAddress, String contractName) { + OWNER_ADDRESS = + Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; + 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 testGet() { + ContractCapsule contractCapsule = contractStore.get(ByteArray.fromHexString(CONTRACT_ADDRESS)); + byte[] originAddressByte = contractCapsule.getOriginAddress(); + String address = ByteArray.toHexString(originAddressByte); + Assert.assertEquals(OWNER_ADDRESS, address); + } + + @Test + public void testPut() { + String contractAddress = "22222222"; + String contractName = "test_contract_name"; + SmartContractOuterClass.SmartContract.Builder contract = + createContract(contractAddress, contractName); + + contractStore.put( + ByteArray.fromHexString(contractAddress), + new ContractCapsule(contract.build())); + + ContractCapsule contractCapsule = contractStore.get(ByteArray.fromHexString(contractAddress)); + Assert.assertNotNull(contractCapsule); + String name = contractCapsule.getInstance().getName(); + Assert.assertEquals(contractName, name); + } + + @Test + public void testDelete() { + String contractAddress = "3333333"; + String contractName = "test_contract_name3333"; + SmartContractOuterClass.SmartContract.Builder contract = + createContract(contractAddress, contractName); + contractStore.put( + ByteArray.fromHexString(contractAddress), + new ContractCapsule(contract.build())); + ContractCapsule contractCapsule = contractStore.get(ByteArray.fromHexString(contractAddress)); + Assert.assertNotNull(contractCapsule); + String name = contractCapsule.getInstance().getName(); + Assert.assertEquals(contractName, name); + + contractStore.delete(ByteArray.fromHexString(contractAddress)); + ContractCapsule contractCapsule2 = contractStore.get(ByteArray.fromHexString(contractAddress)); + Assert.assertNull(contractCapsule2); + } +} diff --git a/framework/src/test/java/org/tron/core/db/DelegatedResourceStoreTest.java b/framework/src/test/java/org/tron/core/db/DelegatedResourceStoreTest.java new file mode 100644 index 00000000000..e10838b12dd --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/DelegatedResourceStoreTest.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.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.capsule.DelegatedResourceCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.store.DelegatedResourceStore; + +public class DelegatedResourceStoreTest extends BaseTest { + private static final long BALANCE = 1_000_000; + private static final long EXPIRE_TIME = 1000L; + private static final String OWNER_ADDRESS = "111111111111"; + private static final String RECEIVER_ADDRESS = "222222222222"; + private static DelegatedResourceCapsule delegatedResourceCapsule; + + @Resource + private DelegatedResourceStore delegatedResourceStore; + + static { + dbPath = "db_DelegatedResourceStore_test"; + Args.setParam( + new String[]{ + "--output-directory", dbPath, + }, + Constant.TEST_CONF + ); + } + + @Before + public void init() { + delegatedResourceCapsule = create(OWNER_ADDRESS); + delegatedResourceStore.put(delegatedResourceCapsule.createDbKey(), + delegatedResourceCapsule); + } + + @Test + public void testGet() { + DelegatedResourceCapsule delegatedResource = delegatedResourceStore + .get(delegatedResourceCapsule.createDbKey()); + Assert.assertNotNull(delegatedResource); + Assert.assertEquals(delegatedResourceCapsule.getFrom(), delegatedResource.getFrom()); + } + + @Test + public void testPut() { + DelegatedResourceCapsule delegatedResourceCapsule = create("333333333333"); + byte[] key = delegatedResourceCapsule.createDbKey(); + delegatedResourceStore.put(key, delegatedResourceCapsule); + + DelegatedResourceCapsule delegatedResourceCapsule1 = delegatedResourceStore.get(key); + Assert.assertNotNull(delegatedResourceCapsule1); + Assert.assertEquals(BALANCE, delegatedResourceCapsule1.getFrozenBalanceForEnergy()); + } + + public DelegatedResourceCapsule create(String address) { + byte[] ownerAddress = ByteArray.fromHexString(address); + byte[] receiverAddress = ByteArray.fromHexString(RECEIVER_ADDRESS); + DelegatedResourceCapsule delegatedResourceCapsule = new DelegatedResourceCapsule( + ByteString.copyFrom(ownerAddress), + ByteString.copyFrom(receiverAddress)); + + delegatedResourceCapsule.setFrozenBalanceForEnergy(BALANCE, EXPIRE_TIME); + return delegatedResourceCapsule; + } + +} diff --git a/framework/src/test/java/org/tron/core/db/DelegationStoreTest.java b/framework/src/test/java/org/tron/core/db/DelegationStoreTest.java new file mode 100644 index 00000000000..1bfbbb33660 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/DelegationStoreTest.java @@ -0,0 +1,72 @@ +package org.tron.core.db; + +import javax.annotation.Resource; +import org.bouncycastle.util.encoders.Hex; +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.capsule.BytesCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.store.DelegationStore; + + +public class DelegationStoreTest extends BaseTest { + + private static final String OWNER_ADDRESS = "11111111111"; + private static final long CYCLE = 100; + private static final long VALUE = 10_000_000; + + @Resource + private DelegationStore delegationStore; + + static { + dbPath = "db_DelegationStore_test"; + Args.setParam( + new String[]{ + "--output-directory", dbPath, + }, + Constant.TEST_CONF + ); + } + + @Before + public void init() { + create(); + } + + public void create() { + byte[] key = buildRewardKey(CYCLE, ByteArray.fromHexString(OWNER_ADDRESS)); + delegationStore.put(key, new BytesCapsule(ByteArray + .fromLong(VALUE))); + } + + private byte[] buildRewardKey(long cycle, byte[] address) { + return (cycle + "-" + Hex.toHexString(address) + "-reward").getBytes(); + } + + @Test + public void testGet() { + byte[] key = buildRewardKey(CYCLE, ByteArray.fromHexString(OWNER_ADDRESS)); + BytesCapsule bytesCapsule = delegationStore.get(key); + Assert.assertNotNull(bytesCapsule); + long actualValue = ByteArray.toLong(bytesCapsule.getData()); + Assert.assertEquals(VALUE, actualValue); + } + + @Test + public void testPut() { + long value = 20_000_000; + byte[] key = buildRewardKey(CYCLE, ByteArray.fromHexString("2222222222222")); + 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); + } + +} From 068764b8349a60430d18a1b6e7527e159ed20f64 Mon Sep 17 00:00:00 2001 From: Simon <107106002+CarlChaoCarl@users.noreply.github.com> Date: Mon, 4 Sep 2023 13:16:04 +0800 Subject: [PATCH 0878/1197] feature(db): optimize properties query (#5378) --- .../tron/core/db2/core/AbstractSnapshot.java | 7 + .../java/org/tron/core/db2/core/Snapshot.java | 4 + .../org/tron/core/db2/core/SnapshotImpl.java | 23 ++ .../tron/core/db2/core/SnapshotManager.java | 6 + .../org/tron/core/db2/core/SnapshotRoot.java | 4 + .../org/tron/core/db2/SnapshotImplTest.java | 201 ++++++++++++++++++ 6 files changed, 245 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/db2/SnapshotImplTest.java diff --git a/chainbase/src/main/java/org/tron/core/db2/core/AbstractSnapshot.java b/chainbase/src/main/java/org/tron/core/db2/core/AbstractSnapshot.java index 496a0fd09ac..ba6c77d43a2 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/AbstractSnapshot.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/AbstractSnapshot.java @@ -15,6 +15,8 @@ public abstract class AbstractSnapshot implements Snapshot { protected WeakReference next; + protected boolean isOptimized; + @Override public Snapshot advance() { return new SnapshotImpl(this); @@ -34,4 +36,9 @@ public void setNext(Snapshot next) { public String getDbName() { return db.getDbName(); } + + @Override + public boolean isOptimized(){ + return isOptimized; + } } diff --git a/chainbase/src/main/java/org/tron/core/db2/core/Snapshot.java b/chainbase/src/main/java/org/tron/core/db2/core/Snapshot.java index e1ca149b207..75545dc29b4 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/Snapshot.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/Snapshot.java @@ -46,4 +46,8 @@ static boolean isImpl(Snapshot snapshot) { void updateSolidity(); String getDbName(); + + boolean isOptimized(); + + void reloadToMem(); } diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotImpl.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotImpl.java index ae8073f668b..bc31b406b30 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotImpl.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotImpl.java @@ -30,6 +30,10 @@ public class SnapshotImpl extends AbstractSnapshot { } previous = snapshot; snapshot.setNext(this); + isOptimized = snapshot.isOptimized(); + if (isOptimized && root == previous) { + Streams.stream(root.iterator()).forEach( e -> put(e.getKey(),e.getValue())); + } } @Override @@ -40,6 +44,7 @@ public byte[] get(byte[] key) { private byte[] get(Snapshot head, byte[] key) { Snapshot snapshot = head; Value value; + while (Snapshot.isImpl(snapshot)) { if ((value = ((SnapshotImpl) snapshot).db.get(Key.of(key))) != null) { return value.getBytes(); @@ -83,6 +88,19 @@ public void merge(Snapshot from) { Streams.stream(fromImpl.db).forEach(e -> db.put(e.getKey(), e.getValue())); } + public void mergeAhead(Snapshot from) { + if (from instanceof SnapshotRoot) { + return ; + } + SnapshotImpl fromImpl = (SnapshotImpl) from; + Streams.stream(fromImpl.db).forEach(e -> { + if (db.get(e.getKey()) == null) { + db.put(e.getKey(), e.getValue()); + } + } + ); + } + @Override public Snapshot retreat() { return previous; @@ -177,4 +195,9 @@ public String getDbName() { public Snapshot newInstance() { return new SnapshotImpl(this); } + + @Override + public void reloadToMem() { + mergeAhead(previous); + } } diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java index f5de96e5587..f0f169ae340 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java @@ -221,6 +221,12 @@ public synchronized void commit() { } --activeSession; + + dbs.forEach(db -> { + if (db.getHead().isOptimized()) { + db.getHead().reloadToMem(); + } + }); } public synchronized void pop() { diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java index 709e2ae1b62..f95cf68dafe 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java @@ -38,6 +38,7 @@ public SnapshotRoot(DB db) { if (CACHE_DBS.contains(this.db.getDbName())) { this.cache = CacheManager.allocate(CacheType.findByType(this.db.getDbName())); } + isOptimized = "properties".equalsIgnoreCase(db.getDbName()); } private boolean needOptAsset() { @@ -221,4 +222,7 @@ public String getDbName() { public Snapshot newInstance() { return new SnapshotRoot(db.newInstance()); } + + @Override + public void reloadToMem() { } } diff --git a/framework/src/test/java/org/tron/core/db2/SnapshotImplTest.java b/framework/src/test/java/org/tron/core/db2/SnapshotImplTest.java new file mode 100644 index 00000000000..aab6f656b1f --- /dev/null +++ b/framework/src/test/java/org/tron/core/db2/SnapshotImplTest.java @@ -0,0 +1,201 @@ +package org.tron.core.db2; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.io.File; +import java.lang.reflect.Constructor; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.application.Application; +import org.tron.common.application.ApplicationFactory; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.FileUtil; +import org.tron.core.Constant; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.db2.core.Snapshot; +import org.tron.core.db2.core.SnapshotImpl; +import org.tron.core.db2.core.SnapshotManager; +import org.tron.core.db2.core.SnapshotRoot; + +public class SnapshotImplTest { + private RevokingDbWithCacheNewValueTest.TestRevokingTronStore tronDatabase; + private TronApplicationContext context; + private Application appT; + private SnapshotManager revokingDatabase; + + @Before + public void init() { + Args.setParam(new String[]{"-d", "output_revokingStore_test"}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + appT = ApplicationFactory.create(context); + + tronDatabase = new RevokingDbWithCacheNewValueTest.TestRevokingTronStore( + "testSnapshotRoot-testMerge"); + revokingDatabase = context.getBean(SnapshotManager.class); + revokingDatabase.enable(); + revokingDatabase.add(tronDatabase.getRevokingDB()); + } + + @After + public void removeDb() { + Args.clearParam(); + context.destroy(); + FileUtil.deleteDir(new File("output_revokingStore_test")); + + tronDatabase.close(); + revokingDatabase.shutdown(); + } + + /** + * linklist is: from -> root + * root:key1=>value1, key2=>value2 + * from:key3=>value3, key4=>value4 + * after construct, getSnapshotImplIns(root); + * from: key1=>value1, key2=>value2, key3=>value3, key4=>value4 + * from: get key1 or key2, traverse 0 times + */ + @Test + public void testMergeRoot() { + // linklist is: from -> root + SnapshotRoot root = new SnapshotRoot(tronDatabase.getDb()); + //root.setOptimized(true); + + root.put("key1".getBytes(), "value1".getBytes()); + root.put("key2".getBytes(), "value2".getBytes()); + SnapshotImpl from = getSnapshotImplIns(root); + from.put("key3".getBytes(), "value3".getBytes()); + from.put("key4".getBytes(), "value4".getBytes()); + + byte[] s1 = from.get("key1".getBytes()); + assertEquals(new String("value1".getBytes()), new String(s1)); + byte[] s2 = from.get("key2".getBytes()); + assertEquals(new String("value2".getBytes()), new String(s2)); + } + + /** + * linklist is: from2 -> from -> root + * root: + * from:key1=>value1, key2=>value2 + * from2:key3=>value3,key4=>value4 + * before merge: from2.mergeAhead(from); + * from2: get key1 or key2, traverse 1 times + * after merge + * from2:key1=>value1, key2=>value2, value3=>value3,key4=>value4 + * from2: get key1 or key2, traverse 0 times + * + */ + @Test + public void testMergeAhead() { + + // linklist is: from2 -> from -> root + SnapshotRoot root = new SnapshotRoot(tronDatabase.getDb()); + SnapshotImpl from = getSnapshotImplIns(root); + from.put("key1".getBytes(), "value1".getBytes()); + from.put("key2".getBytes(), "value2".getBytes()); + + SnapshotImpl from2 = getSnapshotImplIns(from); + from2.put("key3".getBytes(), "value3".getBytes()); + from2.put("key4".getBytes(), "value4".getBytes()); + + /* + // before merge get data in from is success,traverse 0 times + byte[] s1 = from.get("key1".getBytes()); + assertEquals(new String("value1".getBytes()), new String(s1)); + byte[] s2 = from.get("key2".getBytes()); + assertEquals(new String("value2".getBytes()), new String(s2)); + // before merge get data in from2 is success, traverse 0 times + byte[] s3 = from2.get("key3".getBytes()); + assertEquals(new String("value3".getBytes()), new String(s3)); + byte[] s4 = from2.get("key4".getBytes()); + assertEquals(new String("value4".getBytes()), new String(s4)); + */ + + // before merge from2 get data is success, traverse 1 times + byte[] s11 = from2.get("key1".getBytes()); + assertEquals(new String("value1".getBytes()), new String(s11)); + byte[] s12 = from2.get("key2".getBytes()); + assertEquals(new String("value2".getBytes()), new String(s12)); + // this can not get key3 and key4 + assertNull(from.get("key3".getBytes())); + assertNull(from.get("key4".getBytes())); + + // do mergeAhead + from2.mergeAhead(from); + /* + // after merge get data in from is success, traverse 0 times + s1 = from.get("key1".getBytes()); + assertEquals(new String("value1".getBytes()), new String(s1)); + s2 = from.get("key2".getBytes()); + assertEquals(new String("value2".getBytes()), new String(s2)); + + // after merge get data in from2 is success, traverse 0 times + s3 = from2.get("key3".getBytes()); + assertEquals(new String("value3".getBytes()), new String(s3)); + s4 = from2.get("key4".getBytes()); + assertEquals(new String("value4".getBytes()), new String(s4)); + */ + + // after merge from2 get data is success, traverse 0 times + byte[] s1 = from2.get("key1".getBytes()); + assertEquals(new String("value1".getBytes()), new String(s1)); + byte[] s2 = from2.get("key2".getBytes()); + assertEquals(new String("value2".getBytes()), new String(s2)); + + // this can not get key3 and key4 + assertNull(from.get("key3".getBytes())); + assertNull(from.get("key4".getBytes())); + } + + /** + * from: key1=>value1, key2=>value2, key3=>value31 + * from2: key3=>value32,key4=>value4 + * after merge: from2.mergeAhead(from); + * from2: key1=>value1, key2=>value2, key3=>value32, key4=>value4 + */ + @Test + public void testMergeOverride() { + // linklist is: from2 -> from -> root + SnapshotRoot root = new SnapshotRoot(tronDatabase.getDb()); + SnapshotImpl from = getSnapshotImplIns(root); + from.put("key1".getBytes(), "value1".getBytes()); + from.put("key2".getBytes(), "value2".getBytes()); + from.put("key3".getBytes(), "value31".getBytes()); + + SnapshotImpl from2 = getSnapshotImplIns(from); + from2.put("key3".getBytes(), "value32".getBytes()); + from2.put("key4".getBytes(), "value4".getBytes()); + // do mergeAhead + from2.mergeAhead(from); + + // after merge from2 get data is success, traverse 0 times + byte[] s1 = from2.get("key1".getBytes()); + assertEquals(new String("value1".getBytes()), new String(s1)); + byte[] s2 = from2.get("key2".getBytes()); + assertEquals(new String("value2".getBytes()), new String(s2)); + byte[] s3 = from2.get("key3".getBytes()); + assertEquals(new String("value32".getBytes()), new String(s3)); + byte[] s4 = from2.get("key4".getBytes()); + assertEquals(new String("value4".getBytes()), new String(s4)); + } + + /** + * The constructor of SnapshotImpl is not public + * so reflection is used to construct the object here. + */ + private SnapshotImpl getSnapshotImplIns(Snapshot snapshot) { + Class clazz = SnapshotImpl.class; + try { + Constructor constructor = clazz.getDeclaredConstructor(Snapshot.class); + constructor.setAccessible(true); + return (SnapshotImpl) constructor.newInstance(snapshot); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + +} From d6ff7339f5f96c21e2c888e06a46b372107e19e6 Mon Sep 17 00:00:00 2001 From: Simon <107106002+CarlChaoCarl@users.noreply.github.com> Date: Mon, 4 Sep 2023 13:21:46 +0800 Subject: [PATCH 0879/1197] feat(mechanism): add stake info for log trigger (#5419) --- .../trigger/TransactionLogTrigger.java | 6 + .../capsule/TransactionLogTriggerCapsule.java | 85 ++++++++++ .../TransactionLogTriggerCapsuleTest.java | 159 ++++++++++++++++++ 3 files changed, 250 insertions(+) create mode 100644 framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java diff --git a/common/src/main/java/org/tron/common/logsfilter/trigger/TransactionLogTrigger.java b/common/src/main/java/org/tron/common/logsfilter/trigger/TransactionLogTrigger.java index dec4170efb8..a4fb1fddb79 100644 --- a/common/src/main/java/org/tron/common/logsfilter/trigger/TransactionLogTrigger.java +++ b/common/src/main/java/org/tron/common/logsfilter/trigger/TransactionLogTrigger.java @@ -1,6 +1,8 @@ package org.tron.common.logsfilter.trigger; import java.util.List; +import java.util.Map; + import lombok.Getter; import lombok.Setter; @@ -91,6 +93,10 @@ public class TransactionLogTrigger extends Trigger { @Setter private long energyUnitPrice; + @Getter + @Setter + private Map extMap; + public TransactionLogTrigger() { setTriggerName(Trigger.TRANSACTION_TRIGGER_NAME); } diff --git a/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java b/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java index 8600cb6ef8c..ab6ea018cf8 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java +++ b/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java @@ -1,6 +1,7 @@ package org.tron.common.logsfilter.capsule; import static org.tron.protos.Protocol.Transaction.Contract.ContractType.CreateSmartContract; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import com.google.protobuf.Any; import com.google.protobuf.ByteString; @@ -26,7 +27,14 @@ import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.TransactionInfo; import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; +import org.tron.protos.contract.BalanceContract.CancelAllUnfreezeV2Contract; +import org.tron.protos.contract.BalanceContract.DelegateResourceContract; +import org.tron.protos.contract.BalanceContract.FreezeBalanceV2Contract; import org.tron.protos.contract.BalanceContract.TransferContract; +import org.tron.protos.contract.BalanceContract.UnDelegateResourceContract; +import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; +import org.tron.protos.contract.BalanceContract.UnfreezeBalanceV2Contract; +import org.tron.protos.contract.BalanceContract.WithdrawExpireUnfreezeContract; import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; @@ -156,6 +164,82 @@ public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule StringUtil.encode58Check(createSmartContract.getOwnerAddress().toByteArray())); } break; + case UnfreezeBalanceContract: + UnfreezeBalanceContract unfreezeBalanceContract = contractParameter + .unpack(UnfreezeBalanceContract.class); + + transactionLogTrigger.setFromAddress(StringUtil + .encode58Check(unfreezeBalanceContract.getOwnerAddress().toByteArray())); + if (!ByteString.EMPTY.equals(unfreezeBalanceContract.getReceiverAddress())) { + transactionLogTrigger.setToAddress(StringUtil + .encode58Check(unfreezeBalanceContract.getReceiverAddress().toByteArray())); + } + transactionLogTrigger.setAssetName("trx"); + transactionLogTrigger.setAssetAmount( + transactionInfo.getUnfreezeAmount()); + break; + case FreezeBalanceV2Contract: + FreezeBalanceV2Contract freezeBalanceV2Contract = contractParameter + .unpack(FreezeBalanceV2Contract.class); + + transactionLogTrigger.setFromAddress(StringUtil + .encode58Check(freezeBalanceV2Contract.getOwnerAddress().toByteArray())); + transactionLogTrigger.setAssetName("trx"); + transactionLogTrigger.setAssetAmount(freezeBalanceV2Contract.getFrozenBalance()); + break; + case UnfreezeBalanceV2Contract: + UnfreezeBalanceV2Contract unfreezeBalanceV2Contract = contractParameter + .unpack(UnfreezeBalanceV2Contract.class); + + transactionLogTrigger.setFromAddress(StringUtil + .encode58Check(unfreezeBalanceV2Contract.getOwnerAddress().toByteArray())); + transactionLogTrigger.setAssetName("trx"); + transactionLogTrigger.setAssetAmount( + unfreezeBalanceV2Contract.getUnfreezeBalance()); + break; + case WithdrawExpireUnfreezeContract: + WithdrawExpireUnfreezeContract withdrawExpireUnfreezeContract = contractParameter + .unpack(WithdrawExpireUnfreezeContract.class); + + transactionLogTrigger.setFromAddress(StringUtil.encode58Check( + withdrawExpireUnfreezeContract.getOwnerAddress().toByteArray())); + transactionLogTrigger.setAssetName("trx"); + transactionLogTrigger.setAssetAmount(transactionInfo.getWithdrawExpireAmount()); + break; + case DelegateResourceContract: + DelegateResourceContract delegateResourceContract = contractParameter + .unpack(DelegateResourceContract.class); + + transactionLogTrigger.setFromAddress(StringUtil + .encode58Check(delegateResourceContract.getOwnerAddress().toByteArray())); + transactionLogTrigger.setToAddress(StringUtil + .encode58Check(delegateResourceContract.getReceiverAddress().toByteArray())); + transactionLogTrigger.setAssetName("trx"); + transactionLogTrigger.setAssetAmount( + delegateResourceContract.getBalance()); + break; + case UnDelegateResourceContract: + UnDelegateResourceContract unDelegateResourceContract = contractParameter + .unpack(UnDelegateResourceContract.class); + + transactionLogTrigger.setFromAddress(StringUtil + .encode58Check(unDelegateResourceContract.getOwnerAddress().toByteArray())); + transactionLogTrigger.setToAddress(StringUtil.encode58Check( + unDelegateResourceContract.getReceiverAddress().toByteArray())); + + transactionLogTrigger.setAssetName("trx"); + transactionLogTrigger.setAssetAmount( + unDelegateResourceContract.getBalance()); + break; + case CancelAllUnfreezeV2Contract: + CancelAllUnfreezeV2Contract cancelAllUnfreezeV2Contract = contractParameter + .unpack(CancelAllUnfreezeV2Contract.class); + + transactionLogTrigger.setFromAddress(StringUtil + .encode58Check(cancelAllUnfreezeV2Contract.getOwnerAddress().toByteArray())); + transactionLogTrigger.setAssetName("trx"); + transactionLogTrigger.setExtMap(transactionInfo.getCancelUnfreezeV2AmountMap()); + break; default: break; } @@ -269,4 +353,5 @@ private List getInternalTransactionList( public void processTrigger() { EventPluginLoader.getInstance().postTransactionTrigger(transactionLogTrigger); } + } diff --git a/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java new file mode 100644 index 00000000000..d8da2cc540d --- /dev/null +++ b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java @@ -0,0 +1,159 @@ +package org.tron.common.logsfilter; + +import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; + +import com.google.protobuf.ByteString; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.logsfilter.capsule.TransactionLogTriggerCapsule; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.p2p.utils.ByteArray; +import org.tron.protos.Protocol; +import org.tron.protos.contract.BalanceContract; +import org.tron.protos.contract.Common; + +public class TransactionLogTriggerCapsuleTest { + + private static final String OWNER_ADDRESS = "41548794500882809695a8a687866e76d4271a1abc"; + private static final String RECEIVER_ADDRESS = "41abd4b9367799eaa3197fecb144eb71de1e049150"; + + public TransactionCapsule transactionCapsule; + public BlockCapsule blockCapsule; + + @Before + public void setup() { + blockCapsule = new BlockCapsule(1, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), Sha256Hash.ZERO_HASH.getByteString()); + } + + @Test + public void testConstructorWithUnfreezeBalanceTrxCapsule() { + BalanceContract.UnfreezeBalanceContract.Builder builder2 = + BalanceContract.UnfreezeBalanceContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); + transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.UnfreezeBalanceContract); + + TransactionLogTriggerCapsule triggerCapsule = + new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getToAddress()); + } + + + @Test + public void testConstructorWithFreezeBalanceV2TrxCapsule() { + BalanceContract.FreezeBalanceV2Contract.Builder builder2 = + BalanceContract.FreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setFrozenBalance(TRX_PRECISION + 100000) + .setResource(Common.ResourceCode.BANDWIDTH); + transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.FreezeBalanceV2Contract); + + TransactionLogTriggerCapsule triggerCapsule = + new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); + Assert.assertEquals("trx", triggerCapsule.getTransactionLogTrigger().getAssetName()); + Assert.assertEquals(TRX_PRECISION + 100000, + triggerCapsule.getTransactionLogTrigger().getAssetAmount()); + } + + @Test + public void testConstructorWithUnfreezeBalanceV2TrxCapsule() { + BalanceContract.UnfreezeBalanceV2Contract.Builder builder2 = + BalanceContract.UnfreezeBalanceV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setUnfreezeBalance(TRX_PRECISION + 4000) + .setResource(Common.ResourceCode.BANDWIDTH); + transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.UnfreezeBalanceV2Contract); + + TransactionLogTriggerCapsule triggerCapsule = + new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); + Assert.assertEquals("trx", triggerCapsule.getTransactionLogTrigger().getAssetName()); + Assert.assertEquals(TRX_PRECISION + 4000, + triggerCapsule.getTransactionLogTrigger().getAssetAmount()); + } + + + @Test + public void testConstructorWithWithdrawExpireTrxCapsule() { + BalanceContract.WithdrawExpireUnfreezeContract.Builder builder2 = + BalanceContract.WithdrawExpireUnfreezeContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); + transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.WithdrawExpireUnfreezeContract); + + TransactionLogTriggerCapsule triggerCapsule = + new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); + Assert.assertEquals("trx", triggerCapsule.getTransactionLogTrigger().getAssetName()); + Assert.assertEquals(0L, triggerCapsule.getTransactionLogTrigger().getAssetAmount()); + } + + + @Test + public void testConstructorWithDelegateResourceTrxCapsule() { + BalanceContract.DelegateResourceContract.Builder builder2 = + BalanceContract.DelegateResourceContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))) + .setBalance(TRX_PRECISION + 2000); + transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.DelegateResourceContract); + + TransactionLogTriggerCapsule triggerCapsule = + new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getToAddress()); + Assert.assertEquals("trx", triggerCapsule.getTransactionLogTrigger().getAssetName()); + Assert.assertEquals(TRX_PRECISION + 2000, + triggerCapsule.getTransactionLogTrigger().getAssetAmount()); + } + + @Test + public void testConstructorWithUnDelegateResourceTrxCapsule() { + BalanceContract.UnDelegateResourceContract.Builder builder2 = + BalanceContract.UnDelegateResourceContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))) + .setBalance(TRX_PRECISION + 10000); + transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.UnDelegateResourceContract); + + TransactionLogTriggerCapsule triggerCapsule = + new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getToAddress()); + Assert.assertEquals("trx", triggerCapsule.getTransactionLogTrigger().getAssetName()); + Assert.assertEquals(TRX_PRECISION + 10000, + triggerCapsule.getTransactionLogTrigger().getAssetAmount()); + } + + @Test + public void testConstructorWithCancelAllUnfreezeTrxCapsule() { + BalanceContract.CancelAllUnfreezeV2Contract.Builder builder2 = + BalanceContract.CancelAllUnfreezeV2Contract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); + transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.CancelAllUnfreezeV2Contract); + + TransactionLogTriggerCapsule triggerCapsule = + new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); + } + +} \ No newline at end of file From b9ab07aae89d6e66c31ba371250a9cbbcc7d241d Mon Sep 17 00:00:00 2001 From: Brown Jiang <317787106@qq.com> Date: Tue, 5 Sep 2023 10:01:04 +0800 Subject: [PATCH 0880/1197] feat(net):supplement disconnect reasons (#5392) * feat(net):supplement disconnect reasons * add ReasonCode NO_SUCH_MESSAGE --- .../src/main/java/org/tron/core/net/P2pEventHandlerImpl.java | 4 +++- .../org/tron/core/net/message/sync/ChainInventoryMessage.java | 1 + .../src/main/java/org/tron/core/net/peer/PeerManager.java | 2 ++ .../java/org/tron/core/net/service/relay/RelayService.java | 2 ++ protocol/src/main/protos/core/Tron.proto | 2 ++ 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java index 10615b70ce3..7518b1347a7 100644 --- a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java +++ b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java @@ -38,6 +38,7 @@ import org.tron.p2p.P2pEventHandler; import org.tron.p2p.connection.Channel; import org.tron.protos.Protocol; +import org.tron.protos.Protocol.ReasonCode; @Slf4j(topic = "net") @Component @@ -232,7 +233,8 @@ private void processException(PeerConnection peer, TronMessage msg, Exception ex code = Protocol.ReasonCode.BAD_BLOCK; break; case NO_SUCH_MESSAGE: - case MESSAGE_WITH_WRONG_LENGTH: + code = Protocol.ReasonCode.NO_SUCH_MESSAGE; + break; case BAD_MESSAGE: code = Protocol.ReasonCode.BAD_PROTOCOL; break; diff --git a/framework/src/main/java/org/tron/core/net/message/sync/ChainInventoryMessage.java b/framework/src/main/java/org/tron/core/net/message/sync/ChainInventoryMessage.java index 4179544ebf7..610a5ff2f11 100644 --- a/framework/src/main/java/org/tron/core/net/message/sync/ChainInventoryMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/sync/ChainInventoryMessage.java @@ -73,6 +73,7 @@ public String toString() { sb.append(", end blockId: ").append(blockIdWeGet.peekLast().getString()); } } + sb.append(", remain_num: ").append(chainInventory.getRemainNum()); return sb.toString(); } } diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java index a80101d4f3a..537f2083691 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java @@ -16,6 +16,7 @@ import org.tron.common.prometheus.MetricLabels; import org.tron.common.prometheus.Metrics; import org.tron.p2p.connection.Channel; +import org.tron.protos.Protocol.ReasonCode; @Slf4j(topic = "net") public class PeerManager { @@ -48,6 +49,7 @@ public static void close() { try { for (PeerConnection p : new ArrayList<>(peers)) { if (!p.isDisconnect()) { + p.disconnect(ReasonCode.PEER_QUITING); p.getChannel().close(); } } diff --git a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java index 9f1b2ef3c37..dfc5f2e89da 100644 --- a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java @@ -34,6 +34,7 @@ import org.tron.core.store.WitnessScheduleStore; import org.tron.p2p.connection.Channel; import org.tron.protos.Protocol; +import org.tron.protos.Protocol.ReasonCode; @Slf4j(topic = "net") @Component @@ -184,6 +185,7 @@ private void disconnect() { TronNetService.getP2pConfig().getActiveNodes().remove(address); TronNetService.getPeers().forEach(peer -> { if (peer.getInetAddress().equals(address.getAddress())) { + peer.disconnect(ReasonCode.NOT_WITNESS); peer.getChannel().close(); } }); diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index aa6a96ba1b3..2fc08901e93 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -601,6 +601,8 @@ enum ReasonCode { TOO_MANY_PEERS_WITH_SAME_IP = 0x22; LIGHT_NODE_SYNC_FAIL = 0x23; BELOW_THAN_ME = 0X24; + NOT_WITNESS = 0x25; + NO_SUCH_MESSAGE = 0x26; UNKNOWN = 0xFF; } From cec13b2f6e747b99509668b3e4f9c855a28c3c65 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Tue, 5 Sep 2023 14:15:42 +0800 Subject: [PATCH 0881/1197] feat(zksnark): delete sapling tmp file on exit (#5467) --- .../src/main/java/org/tron/core/zen/ZksnarkInitService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/framework/src/main/java/org/tron/core/zen/ZksnarkInitService.java b/framework/src/main/java/org/tron/core/zen/ZksnarkInitService.java index 2811b50397d..8b9aafe4715 100644 --- a/framework/src/main/java/org/tron/core/zen/ZksnarkInitService.java +++ b/framework/src/main/java/org/tron/core/zen/ZksnarkInitService.java @@ -57,6 +57,9 @@ private static String getParamsFile(String fileName) { } catch (IOException e) { logger.error(e.getMessage(), e); } + if (fileOut.exists()) { + fileOut.deleteOnExit(); + } return fileOut.getAbsolutePath(); } } \ No newline at end of file From 437c12e1fc6f12593bd6fdf7d159eb6461d8a3e8 Mon Sep 17 00:00:00 2001 From: lxcmyf Date: Wed, 6 Sep 2023 11:25:38 +0800 Subject: [PATCH 0882/1197] test(rpc): add test for RPC (#5471) --- .../core/services/RpcApiServicesTest.java | 1213 +++++++++++++++++ .../org/tron/core/services/http/UtilTest.java | 60 + .../org/tron/keystore/WalletFileTest.java | 61 +- 3 files changed, 1327 insertions(+), 7 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java diff --git a/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java b/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java new file mode 100644 index 00000000000..8b45b871af7 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java @@ -0,0 +1,1213 @@ +package org.tron.core.services; + +import static org.junit.Assert.assertNotNull; +import static org.tron.common.parameter.CommonParameter.getInstance; +import static org.tron.common.utils.client.WalletClient.decodeFromBase58Check; +import static org.tron.protos.Protocol.Transaction.Contract.ContractType.TransferContract; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import java.io.IOException; +import java.util.Objects; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.junit.runners.MethodSorters; +import org.tron.api.DatabaseGrpc; +import org.tron.api.DatabaseGrpc.DatabaseBlockingStub; +import org.tron.api.GrpcAPI.BlockLimit; +import org.tron.api.GrpcAPI.BlockReq; +import org.tron.api.GrpcAPI.BytesMessage; +import org.tron.api.GrpcAPI.CanDelegatedMaxSizeRequestMessage; +import org.tron.api.GrpcAPI.CanWithdrawUnfreezeAmountRequestMessage; +import org.tron.api.GrpcAPI.DelegatedResourceMessage; +import org.tron.api.GrpcAPI.DiversifierMessage; +import org.tron.api.GrpcAPI.EmptyMessage; +import org.tron.api.GrpcAPI.ExpandedSpendingKeyMessage; +import org.tron.api.GrpcAPI.GetAvailableUnfreezeCountRequestMessage; +import org.tron.api.GrpcAPI.IncomingViewingKeyDiversifierMessage; +import org.tron.api.GrpcAPI.IncomingViewingKeyMessage; +import org.tron.api.GrpcAPI.IvkDecryptAndMarkParameters; +import org.tron.api.GrpcAPI.IvkDecryptParameters; +import org.tron.api.GrpcAPI.IvkDecryptTRC20Parameters; +import org.tron.api.GrpcAPI.NumberMessage; +import org.tron.api.GrpcAPI.OvkDecryptParameters; +import org.tron.api.GrpcAPI.OvkDecryptTRC20Parameters; +import org.tron.api.GrpcAPI.PaginatedMessage; +import org.tron.api.GrpcAPI.PrivateParameters; +import org.tron.api.GrpcAPI.PrivateParametersWithoutAsk; +import org.tron.api.GrpcAPI.ViewingKeyMessage; +import org.tron.api.WalletGrpc; +import org.tron.api.WalletGrpc.WalletBlockingStub; +import org.tron.api.WalletSolidityGrpc; +import org.tron.api.WalletSolidityGrpc.WalletSolidityBlockingStub; +import org.tron.common.application.Application; +import org.tron.common.application.ApplicationFactory; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.PublicMethod; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.services.interfaceOnPBFT.RpcApiServiceOnPBFT; +import org.tron.core.services.interfaceOnSolidity.RpcApiServiceOnSolidity; +import org.tron.protos.Protocol; +import org.tron.protos.Protocol.Account; +import org.tron.protos.Protocol.Block; +import org.tron.protos.Protocol.BlockHeader.raw; +import org.tron.protos.Protocol.MarketOrderPair; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.contract.AccountContract.AccountCreateContract; +import org.tron.protos.contract.AccountContract.AccountPermissionUpdateContract; +import org.tron.protos.contract.AccountContract.AccountUpdateContract; +import org.tron.protos.contract.AccountContract.SetAccountIdContract; +import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; +import org.tron.protos.contract.AssetIssueContractOuterClass.ParticipateAssetIssueContract; +import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; +import org.tron.protos.contract.AssetIssueContractOuterClass.UnfreezeAssetContract; +import org.tron.protos.contract.AssetIssueContractOuterClass.UpdateAssetContract; +import org.tron.protos.contract.BalanceContract; +import org.tron.protos.contract.BalanceContract.AccountBalanceRequest; +import org.tron.protos.contract.BalanceContract.AccountIdentifier; +import org.tron.protos.contract.BalanceContract.BlockBalanceTrace.BlockIdentifier; +import org.tron.protos.contract.BalanceContract.CancelAllUnfreezeV2Contract; +import org.tron.protos.contract.BalanceContract.DelegateResourceContract; +import org.tron.protos.contract.BalanceContract.FreezeBalanceContract; +import org.tron.protos.contract.BalanceContract.FreezeBalanceV2Contract; +import org.tron.protos.contract.BalanceContract.UnDelegateResourceContract; +import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; +import org.tron.protos.contract.BalanceContract.UnfreezeBalanceV2Contract; +import org.tron.protos.contract.BalanceContract.WithdrawBalanceContract; +import org.tron.protos.contract.BalanceContract.WithdrawExpireUnfreezeContract; +import org.tron.protos.contract.ExchangeContract.ExchangeCreateContract; +import org.tron.protos.contract.ExchangeContract.ExchangeInjectContract; +import org.tron.protos.contract.ExchangeContract.ExchangeTransactionContract; +import org.tron.protos.contract.ExchangeContract.ExchangeWithdrawContract; +import org.tron.protos.contract.MarketContract.MarketCancelOrderContract; +import org.tron.protos.contract.MarketContract.MarketSellAssetContract; +import org.tron.protos.contract.ProposalContract.ProposalApproveContract; +import org.tron.protos.contract.ProposalContract.ProposalCreateContract; +import org.tron.protos.contract.ProposalContract.ProposalDeleteContract; +import org.tron.protos.contract.SmartContractOuterClass.ClearABIContract; +import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; +import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; +import org.tron.protos.contract.SmartContractOuterClass.UpdateEnergyLimitContract; +import org.tron.protos.contract.SmartContractOuterClass.UpdateSettingContract; +import org.tron.protos.contract.StorageContract.UpdateBrokerageContract; +import org.tron.protos.contract.WitnessContract.VoteWitnessContract; +import org.tron.protos.contract.WitnessContract.WitnessCreateContract; +import org.tron.protos.contract.WitnessContract.WitnessUpdateContract; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class RpcApiServicesTest { + private static TronApplicationContext context; + private static DatabaseBlockingStub databaseBlockingStubFull = null; + private static DatabaseBlockingStub databaseBlockingStubSolidity = null; + private static DatabaseBlockingStub databaseBlockingStubPBFT = null; + private static WalletBlockingStub blockingStubFull = null; + private static WalletSolidityBlockingStub blockingStubSolidity = null; + private static WalletSolidityBlockingStub blockingStubPBFT = null; + @ClassRule + public static TemporaryFolder temporaryFolder = new TemporaryFolder(); + private static ByteString ownerAddress; + private static ByteString sk; + private static ByteString ask; + private static ByteString nsk; + private static ByteString ovk; + private static ByteString ak; + private static ByteString nk; + private static ByteString ivk; + private static ByteString d; + + @BeforeClass + public static void init() throws IOException { + Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + String OWNER_ADDRESS = Wallet.getAddressPreFixString() + + "548794500882809695a8a687866e76d4271a1abc"; + getInstance().setRpcPort(PublicMethod.chooseRandomPort()); + getInstance().setRpcOnSolidityPort(PublicMethod.chooseRandomPort()); + getInstance().setRpcOnPBFTPort(PublicMethod.chooseRandomPort()); + String fullNode = String.format("%s:%d", getInstance().getNodeDiscoveryBindIp(), + getInstance().getRpcPort()); + String solidityNode = String.format("%s:%d", getInstance().getNodeDiscoveryBindIp(), + getInstance().getRpcOnSolidityPort()); + String pBFTNode = String.format("%s:%d", getInstance().getNodeDiscoveryBindIp(), + getInstance().getRpcOnPBFTPort()); + + ManagedChannel channelFull = ManagedChannelBuilder.forTarget(fullNode) + .usePlaintext() + .build(); + ManagedChannel channelPBFT = ManagedChannelBuilder.forTarget(pBFTNode) + .usePlaintext() + .build(); + ManagedChannel channelSolidity = ManagedChannelBuilder.forTarget(solidityNode) + .usePlaintext() + .build(); + context = new TronApplicationContext(DefaultConfig.class); + databaseBlockingStubFull = DatabaseGrpc.newBlockingStub(channelFull); + databaseBlockingStubSolidity = DatabaseGrpc.newBlockingStub(channelSolidity); + databaseBlockingStubPBFT = DatabaseGrpc.newBlockingStub(channelPBFT); + blockingStubFull = WalletGrpc.newBlockingStub(channelFull); + blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); + blockingStubPBFT = WalletSolidityGrpc.newBlockingStub(channelPBFT); + + RpcApiService rpcApiService = context.getBean(RpcApiService.class); + RpcApiServiceOnSolidity rpcApiServiceOnSolidity = + context.getBean(RpcApiServiceOnSolidity.class); + RpcApiServiceOnPBFT rpcApiServiceOnPBFT = context.getBean(RpcApiServiceOnPBFT.class); + + Manager manager = context.getBean(Manager.class); + + ownerAddress = ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)); + AccountCapsule ownerCapsule = new AccountCapsule(ByteString.copyFromUtf8("owner"), + ownerAddress, Protocol.AccountType.Normal, 10_000_000_000L); + manager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); + manager.getDynamicPropertiesStore().saveAllowShieldedTransaction(1); + manager.getDynamicPropertiesStore().saveAllowShieldedTRC20Transaction(1); + Application appTest = ApplicationFactory.create(context); + appTest.addService(rpcApiService); + appTest.addService(rpcApiServiceOnSolidity); + appTest.addService(rpcApiServiceOnPBFT); + appTest.startup(); + } + + @AfterClass + public static void destroy() { + context.close(); + Args.clearParam(); + } + + @Test + public void testGetBlockByNum() { + NumberMessage message = NumberMessage.newBuilder().setNum(0).build(); + assertNotNull(databaseBlockingStubFull.getBlockByNum(message)); + assertNotNull(databaseBlockingStubSolidity.getBlockByNum(message)); + assertNotNull(databaseBlockingStubPBFT.getBlockByNum(message)); + assertNotNull(blockingStubFull.getBlockByNum(message)); + assertNotNull(blockingStubSolidity.getBlockByNum(message)); + assertNotNull(blockingStubPBFT.getBlockByNum(message)); + + assertNotNull(blockingStubFull.getBlockByNum2(message)); + assertNotNull(blockingStubSolidity.getBlockByNum2(message)); + assertNotNull(blockingStubPBFT.getBlockByNum2(message)); + } + + @Test + public void testGetDynamicProperties() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(databaseBlockingStubFull.getDynamicProperties(message)); + assertNotNull(databaseBlockingStubSolidity.getDynamicProperties(message)); + assertNotNull(databaseBlockingStubPBFT.getDynamicProperties(message)); + } + + @Test + public void testGetAccount() { + Account account = Account.newBuilder().setAddress(ownerAddress).build(); + assertNotNull(blockingStubFull.getAccount(account)); + assertNotNull(blockingStubSolidity.getAccount(account)); + assertNotNull(blockingStubPBFT.getAccount(account)); + } + + @Test + public void testGetAccountById() { + Account account = Account.newBuilder().setAccountId(ownerAddress).build(); + assertNotNull(blockingStubFull.getAccountById(account)); + assertNotNull(blockingStubSolidity.getAccountById(account)); + assertNotNull(blockingStubPBFT.getAccountById(account)); + } + + @Test + public void testListWitnesses() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(blockingStubFull.listWitnesses(message)); + assertNotNull(blockingStubSolidity.listWitnesses(message)); + assertNotNull(blockingStubPBFT.listWitnesses(message)); + } + + @Test + public void testGetAssetIssueList() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getAssetIssueList(message)); + assertNotNull(blockingStubSolidity.getAssetIssueList(message)); + assertNotNull(blockingStubPBFT.getAssetIssueList(message)); + } + + @Test + public void testGetPaginatedAssetIssueList() { + PaginatedMessage paginatedMessage = PaginatedMessage.newBuilder() + .setOffset(0).setLimit(5).build(); + assertNotNull(blockingStubFull.getPaginatedAssetIssueList(paginatedMessage)); + assertNotNull(blockingStubSolidity.getPaginatedAssetIssueList(paginatedMessage)); + assertNotNull(blockingStubPBFT.getPaginatedAssetIssueList(paginatedMessage)); + } + + @Test + public void testGetAssetIssueByName() { + BytesMessage message = BytesMessage.newBuilder().setValue(ownerAddress).build(); + assertNotNull(blockingStubFull.getAssetIssueByName(message)); + assertNotNull(blockingStubSolidity.getAssetIssueByName(message)); + assertNotNull(blockingStubPBFT.getAssetIssueByName(message)); + } + + @Test + public void testGetAssetIssueListByName() { + BytesMessage message = BytesMessage.newBuilder().setValue(ownerAddress).build(); + assertNotNull(blockingStubFull.getAssetIssueListByName(message)); + assertNotNull(blockingStubSolidity.getAssetIssueListByName(message)); + assertNotNull(blockingStubPBFT.getAssetIssueListByName(message)); + } + + @Test + public void testGetAssetIssueById() { + BytesMessage message = BytesMessage.newBuilder().setValue(ownerAddress).build(); + assertNotNull(blockingStubFull.getAssetIssueById(message)); + assertNotNull(blockingStubSolidity.getAssetIssueById(message)); + assertNotNull(blockingStubPBFT.getAssetIssueById(message)); + } + + @Test + public void testGetBlockReference() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(databaseBlockingStubFull.getBlockReference(message)); + assertNotNull(databaseBlockingStubSolidity.getBlockReference(message)); + assertNotNull(databaseBlockingStubPBFT.getBlockReference(message)); + } + + @Test + public void testGetNowBlock() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(databaseBlockingStubFull.getNowBlock(message)); + assertNotNull(databaseBlockingStubSolidity.getNowBlock(message)); + assertNotNull(databaseBlockingStubPBFT.getNowBlock(message)); + assertNotNull(blockingStubFull.getNowBlock(message)); + assertNotNull(blockingStubSolidity.getNowBlock(message)); + assertNotNull(blockingStubPBFT.getNowBlock(message)); + + assertNotNull(blockingStubFull.getNowBlock2(message)); + assertNotNull(blockingStubSolidity.getNowBlock2(message)); + assertNotNull(blockingStubPBFT.getNowBlock2(message)); + } + + @Test + public void testGetDelegatedResource() { + DelegatedResourceMessage message = DelegatedResourceMessage.newBuilder() + .setFromAddress(ownerAddress) + .setToAddress(ownerAddress).build(); + assertNotNull(blockingStubFull.getDelegatedResource(message)); + assertNotNull(blockingStubSolidity.getDelegatedResource(message)); + assertNotNull(blockingStubPBFT.getDelegatedResource(message)); + + assertNotNull(blockingStubFull.getDelegatedResourceV2(message)); + assertNotNull(blockingStubSolidity.getDelegatedResourceV2(message)); + assertNotNull(blockingStubPBFT.getDelegatedResourceV2(message)); + } + + @Test + public void testGetDelegatedResourceAccountIndex() { + BytesMessage message = BytesMessage.newBuilder().setValue(ownerAddress).build(); + assertNotNull(blockingStubFull.getDelegatedResourceAccountIndex(message)); + assertNotNull(blockingStubSolidity.getDelegatedResourceAccountIndex(message)); + assertNotNull(blockingStubPBFT.getDelegatedResourceAccountIndex(message)); + + assertNotNull(blockingStubFull.getDelegatedResourceAccountIndexV2(message)); + assertNotNull(blockingStubSolidity.getDelegatedResourceAccountIndexV2(message)); + assertNotNull(blockingStubPBFT.getDelegatedResourceAccountIndexV2(message)); + } + + @Test + public void testGetCanDelegatedMaxSize() { + CanDelegatedMaxSizeRequestMessage message = CanDelegatedMaxSizeRequestMessage.newBuilder() + .setType(0).setOwnerAddress(ownerAddress).build(); + assertNotNull(blockingStubFull.getCanDelegatedMaxSize(message)); + assertNotNull(blockingStubSolidity.getCanDelegatedMaxSize(message)); + assertNotNull(blockingStubPBFT.getCanDelegatedMaxSize(message)); + } + + @Test + public void testGetAvailableUnfreezeCount() { + GetAvailableUnfreezeCountRequestMessage message = GetAvailableUnfreezeCountRequestMessage + .newBuilder().setOwnerAddress(ownerAddress).build(); + assertNotNull(blockingStubFull.getAvailableUnfreezeCount(message)); + assertNotNull(blockingStubSolidity.getAvailableUnfreezeCount(message)); + assertNotNull(blockingStubPBFT.getAvailableUnfreezeCount(message)); + } + + @Test + public void testGetCanWithdrawUnfreezeAmount() { + CanWithdrawUnfreezeAmountRequestMessage message = CanWithdrawUnfreezeAmountRequestMessage + .newBuilder().setOwnerAddress(ownerAddress).setTimestamp(0).build(); + assertNotNull(blockingStubFull.getCanWithdrawUnfreezeAmount(message)); + assertNotNull(blockingStubSolidity.getCanWithdrawUnfreezeAmount(message)); + assertNotNull(blockingStubPBFT.getCanWithdrawUnfreezeAmount(message)); + } + + @Test + public void testGetExchangeById() { + BytesMessage message = BytesMessage.newBuilder().setValue(ownerAddress).build(); + assertNotNull(blockingStubFull.getExchangeById(message)); + assertNotNull(blockingStubSolidity.getExchangeById(message)); + assertNotNull(blockingStubPBFT.getExchangeById(message)); + } + + @Test + public void testListExchanges() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(blockingStubFull.listExchanges(message)); + assertNotNull(blockingStubSolidity.listExchanges(message)); + assertNotNull(blockingStubPBFT.listExchanges(message)); + } + + @Test + public void testGetTransactionCountByBlockNum() { + NumberMessage message = NumberMessage.newBuilder().setNum(0).build(); + assertNotNull(blockingStubFull.getTransactionCountByBlockNum(message)); + assertNotNull(blockingStubSolidity.getTransactionCountByBlockNum(message)); + assertNotNull(blockingStubPBFT.getTransactionCountByBlockNum(message)); + } + + @Test + public void testListNodes() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(blockingStubFull.listNodes(message)); + } + + @Test + public void testGetTransactionById() { + BytesMessage message = BytesMessage.newBuilder().setValue(ownerAddress).build(); + assertNotNull(blockingStubFull.getTransactionById(message)); + assertNotNull(blockingStubSolidity.getTransactionById(message)); + assertNotNull(blockingStubPBFT.getTransactionById(message)); + } + + @Test + public void testGetTransactionInfoById() { + BytesMessage message = BytesMessage.newBuilder().setValue(ownerAddress).build(); + assertNotNull(blockingStubFull.getTransactionInfoById(message)); + assertNotNull(blockingStubSolidity.getTransactionInfoById(message)); + assertNotNull(blockingStubPBFT.getTransactionInfoById(message)); + } + + @Test + public void testGetRewardInfo() { + BytesMessage message = BytesMessage.newBuilder().setValue(ownerAddress).build(); + assertNotNull(blockingStubFull.getRewardInfo(message)); + assertNotNull(blockingStubSolidity.getRewardInfo(message)); + assertNotNull(blockingStubPBFT.getRewardInfo(message)); + } + + @Test + public void testGetBrokerageInfo() { + BytesMessage message = BytesMessage.newBuilder().setValue(ownerAddress).build(); + assertNotNull(blockingStubFull.getBrokerageInfo(message)); + assertNotNull(blockingStubSolidity.getBrokerageInfo(message)); + assertNotNull(blockingStubPBFT.getBrokerageInfo(message)); + } + + @Test + public void testGetBurnTrx() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getBurnTrx(message)); + assertNotNull(blockingStubSolidity.getBurnTrx(message)); + assertNotNull(blockingStubPBFT.getBurnTrx(message)); + } + + // @Test + // public void testGetMerkleTreeVoucherInfo() { + // OutputPoint outputPoint = OutputPoint.newBuilder().build(); + // OutputPointInfo message = OutputPointInfo.newBuilder() + // .addOutPoints(outputPoint).setBlockNum(0).build(); + // assertNotNull(blockingStubFull.getMerkleTreeVoucherInfo(message)); + // assertNotNull(blockingStubSolidity.getMerkleTreeVoucherInfo(message)); + // assertNotNull(blockingStubPBFT.getMerkleTreeVoucherInfo(message)); + // } + + @Test + public void testScanNoteByIvk() { + IvkDecryptParameters message = IvkDecryptParameters.newBuilder() + .setStartBlockIndex(0) + .setEndBlockIndex(1) + .build(); + assertNotNull(blockingStubFull.scanNoteByIvk(message)); + assertNotNull(blockingStubSolidity.scanNoteByIvk(message)); + assertNotNull(blockingStubPBFT.scanNoteByIvk(message)); + } + + @Test + public void testScanAndMarkNoteByIvk() { + IvkDecryptAndMarkParameters message = IvkDecryptAndMarkParameters.newBuilder() + .setStartBlockIndex(0) + .setEndBlockIndex(1) + .build(); + assertNotNull(blockingStubFull.scanAndMarkNoteByIvk(message)); + assertNotNull(blockingStubSolidity.scanAndMarkNoteByIvk(message)); + assertNotNull(blockingStubPBFT.scanAndMarkNoteByIvk(message)); + } + + @Test + public void test08ScanNoteByOvk() { + OvkDecryptParameters message = OvkDecryptParameters.newBuilder() + .setStartBlockIndex(0) + .setEndBlockIndex(1) + .setOvk(ovk) + .build(); + assertNotNull(blockingStubFull.scanNoteByOvk(message)); + assertNotNull(blockingStubSolidity.scanNoteByOvk(message)); + assertNotNull(blockingStubPBFT.scanNoteByOvk(message)); + } + + // @Test + // public void testIsSpend() { + // NoteParameters message = NoteParameters.newBuilder() + // .build(); + // assertNotNull(blockingStubFull.isSpend(message)); + // assertNotNull(blockingStubSolidity.isSpend(message)); + // assertNotNull(blockingStubPBFT.isSpend(message)); + // } + + @Test + public void testScanShieldedTRC20NotesByIvk() { + IvkDecryptTRC20Parameters message = IvkDecryptTRC20Parameters.newBuilder() + .setStartBlockIndex(1) + .setEndBlockIndex(10) + .build(); + assertNotNull(blockingStubFull.scanShieldedTRC20NotesByIvk(message)); + assertNotNull(blockingStubSolidity.scanShieldedTRC20NotesByIvk(message)); + assertNotNull(blockingStubPBFT.scanShieldedTRC20NotesByIvk(message)); + } + + @Test + public void testScanShieldedTRC20NotesByOvk() { + OvkDecryptTRC20Parameters message = OvkDecryptTRC20Parameters.newBuilder() + .setStartBlockIndex(1) + .setEndBlockIndex(10) + .build(); + assertNotNull(blockingStubFull.scanShieldedTRC20NotesByOvk(message)); + assertNotNull(blockingStubSolidity.scanShieldedTRC20NotesByOvk(message)); + assertNotNull(blockingStubPBFT.scanShieldedTRC20NotesByOvk(message)); + } + + // @Test + // public void testIsShieldedTRC20ContractNoteSpent() { + // NfTRC20Parameters message = NfTRC20Parameters.newBuilder().build(); + // assertNotNull(blockingStubFull.isShieldedTRC20ContractNoteSpent(message)); + // assertNotNull(blockingStubSolidity.isShieldedTRC20ContractNoteSpent(message)); + // assertNotNull(blockingStubPBFT.isShieldedTRC20ContractNoteSpent(message)); + // } + + // @Test + // public void testGetTriggerInputForShieldedTRC20Contract() { + // ShieldedTRC20TriggerContractParameters message = + // ShieldedTRC20TriggerContractParameters.newBuilder() + // .setAmount("1000") + // .build(); + // assertNotNull(blockingStubFull.getTriggerInputForShieldedTRC20Contract(message)); + // } + + @Test + public void testUpdateBrokerage() { + UpdateBrokerageContract message = UpdateBrokerageContract.newBuilder() + .setOwnerAddress(ownerAddress).setBrokerage(1).build(); + assertNotNull(blockingStubFull.updateBrokerage(message)); + } + + @Test + public void testCreateCommonTransaction() { + UpdateBrokerageContract.Builder updateBrokerageContract = UpdateBrokerageContract.newBuilder(); + updateBrokerageContract.setOwnerAddress( + ByteString.copyFrom(Objects + .requireNonNull(decodeFromBase58Check("TN3zfjYUmMFK3ZsHSsrdJoNRtGkQmZLBLz")))) + .setBrokerage(10); + Transaction.Builder transaction = Transaction.newBuilder(); + Transaction.raw.Builder raw = Transaction.raw.newBuilder(); + Transaction.Contract.Builder contract = Transaction.Contract.newBuilder(); + contract.setType(Transaction.Contract.ContractType.UpdateBrokerageContract) + .setParameter(Any.pack(updateBrokerageContract.build())); + raw.addContract(contract.build()); + transaction.setRawData(raw.build()); + assertNotNull(blockingStubFull.createCommonTransaction(transaction.build())); + } + + @Test + public void testGetTransactionInfoByBlockNum() { + NumberMessage message = NumberMessage.newBuilder().setNum(1).build(); + assertNotNull(blockingStubFull.getTransactionInfoByBlockNum(message)); + assertNotNull(blockingStubSolidity.getTransactionInfoByBlockNum(message)); + } + + @Test + public void testMarketSellAsset() { + String sellTokenId = "123"; + long sellTokenQuant = 100000000L; + String buyTokenId = "456"; + long buyTokenQuant = 200000000L; + MarketSellAssetContract message = MarketSellAssetContract.newBuilder() + .setOwnerAddress(ownerAddress) + .setBuyTokenQuantity(buyTokenQuant) + .setBuyTokenId(ByteString.copyFrom(buyTokenId.getBytes())) + .setSellTokenQuantity(sellTokenQuant) + .setSellTokenId(ByteString.copyFrom(sellTokenId.getBytes())) + .build(); + assertNotNull(blockingStubFull.marketSellAsset(message)); + } + + @Test + public void testMarketCancelOrder() { + MarketCancelOrderContract message = MarketCancelOrderContract.newBuilder() + .setOwnerAddress(ownerAddress) + .setOrderId(ByteString.copyFromUtf8("123")) + .build(); + assertNotNull(blockingStubFull.marketCancelOrder(message)); + } + + @Test + public void testGetMarketOrderByAccount() { + BytesMessage message = BytesMessage.newBuilder().setValue(ownerAddress).build(); + assertNotNull(blockingStubFull.getMarketOrderByAccount(message)); + assertNotNull(blockingStubSolidity.getMarketOrderByAccount(message)); + assertNotNull(blockingStubPBFT.getMarketOrderByAccount(message)); + } + + // @Test + // public void testGetMarketOrderById() { + // BytesMessage message = BytesMessage.newBuilder().setValue(ownerAddress).build(); + // assertNotNull(blockingStubFull.getMarketOrderById(message)); + // assertNotNull(blockingStubSolidity.getMarketOrderById(message)); + // assertNotNull(blockingStubPBFT.getMarketOrderById(message)); + // } + + @Test + public void testGetMarketPriceByPair() { + MarketOrderPair marketOrderPair = getMarketOrderPair(); + assertNotNull(blockingStubFull.getMarketPriceByPair(marketOrderPair)); + assertNotNull(blockingStubSolidity.getMarketPriceByPair(marketOrderPair)); + assertNotNull(blockingStubPBFT.getMarketPriceByPair(marketOrderPair)); + } + + @Test + public void testGetMarketOrderListByPair() { + MarketOrderPair marketOrderPair = getMarketOrderPair(); + assertNotNull(blockingStubFull.getMarketOrderListByPair(marketOrderPair)); + assertNotNull(blockingStubSolidity.getMarketOrderListByPair(marketOrderPair)); + assertNotNull(blockingStubPBFT.getMarketOrderListByPair(marketOrderPair)); + } + + private static MarketOrderPair getMarketOrderPair() { + ByteString buyTokenId = ByteString.copyFrom(Objects + .requireNonNull(ByteArray.fromString("_"))); + ByteString sellTokenId = ByteString.copyFrom(Objects + .requireNonNull(ByteArray.fromString("_"))); + return MarketOrderPair.newBuilder() + .setBuyTokenId(buyTokenId) + .setSellTokenId(sellTokenId).build(); + } + + @Test + public void testGetMarketPairList() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getMarketPairList(message)); + assertNotNull(blockingStubSolidity.getMarketPairList(message)); + assertNotNull(blockingStubPBFT.getMarketPairList(message)); + } + + @Test + public void testGetTransactionFromPending() { + BalanceContract.TransferContract tc = + BalanceContract.TransferContract.newBuilder() + .setAmount(10) + .setOwnerAddress(ByteString.copyFromUtf8("aaa")) + .setToAddress(ByteString.copyFromUtf8("bbb")) + .build(); + TransactionCapsule trx = new TransactionCapsule(tc, TransferContract); + BytesMessage message = BytesMessage.newBuilder() + .setValue(trx.getTransactionId().getByteString()).build(); + assertNotNull(blockingStubFull.getTransactionFromPending(message)); + } + + @Test + public void testGetTransactionListFromPending() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getTransactionListFromPending(message)); + } + + @Test + public void testGetPendingSize() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getPendingSize(message)); + } + + @Test + public void testGetBlock() { + BlockReq message = BlockReq.newBuilder().setIdOrNum("0").build(); + assertNotNull(blockingStubFull.getBlock(message)); + assertNotNull(blockingStubSolidity.getBlock(message)); + assertNotNull(blockingStubPBFT.getBlock(message)); + } + + @Test + public void testGetAccountBalance() { + AccountIdentifier accountIdentifier = AccountIdentifier.newBuilder() + .setAddress(ownerAddress).build(); + BlockIdentifier blockIdentifier = getBlockIdentifier(); + AccountBalanceRequest message = AccountBalanceRequest.newBuilder() + .setAccountIdentifier(accountIdentifier) + .setBlockIdentifier(blockIdentifier) + .build(); + assertNotNull(blockingStubFull.getAccountBalance(message)); + } + + @Test + public void testGetBlockBalanceTrace() { + BlockIdentifier blockIdentifier = getBlockIdentifier(); + assertNotNull(blockingStubFull.getBlockBalanceTrace(blockIdentifier)); + } + + private static BlockIdentifier getBlockIdentifier() { + Block nowBlock = blockingStubFull.getNowBlock(EmptyMessage.newBuilder().build()); + raw rawData = nowBlock.getBlockHeader().getRawData(); + BlockCapsule.BlockId blockId = + new BlockCapsule.BlockId(Sha256Hash.of(getInstance().isECKeyCryptoEngine(), + rawData.toByteArray()), + rawData.getNumber()); + return BlockIdentifier.newBuilder() + .setNumber(rawData.getNumber()) + .setHash(blockId.getByteString()) + .build(); + } + + @Test + public void testCreateTransaction() { + BalanceContract.TransferContract transferContract = BalanceContract.TransferContract + .newBuilder() + .setOwnerAddress(ownerAddress) + .setToAddress(ownerAddress) + .setAmount(1000) + .build(); + assertNotNull(blockingStubFull.createTransaction(transferContract)); + assertNotNull(blockingStubFull.createTransaction2(transferContract)); + } + + @Test + public void testGetTransactionSignWeight() { + UpdateBrokerageContract.Builder updateBrokerageContract = UpdateBrokerageContract.newBuilder(); + updateBrokerageContract.setOwnerAddress( + ByteString.copyFrom(Objects + .requireNonNull(decodeFromBase58Check("TN3zfjYUmMFK3ZsHSsrdJoNRtGkQmZLBLz")))) + .setBrokerage(10); + Transaction.Builder transaction = Transaction.newBuilder(); + Transaction.raw.Builder raw = Transaction.raw.newBuilder(); + Transaction.Contract.Builder contract = Transaction.Contract.newBuilder(); + contract.setType(Transaction.Contract.ContractType.UpdateBrokerageContract) + .setParameter(Any.pack(updateBrokerageContract.build())); + raw.addContract(contract.build()); + transaction.setRawData(raw.build()); + assertNotNull(blockingStubFull.getTransactionSignWeight(transaction.build())); + } + + @Test + public void testGetTransactionApprovedList() { + UpdateBrokerageContract.Builder updateBrokerageContract = UpdateBrokerageContract.newBuilder(); + updateBrokerageContract.setOwnerAddress( + ByteString.copyFrom(Objects + .requireNonNull(decodeFromBase58Check("TN3zfjYUmMFK3ZsHSsrdJoNRtGkQmZLBLz")))) + .setBrokerage(10); + Transaction.Builder transaction = Transaction.newBuilder(); + Transaction.raw.Builder raw = Transaction.raw.newBuilder(); + Transaction.Contract.Builder contract = Transaction.Contract.newBuilder(); + contract.setType(Transaction.Contract.ContractType.UpdateBrokerageContract) + .setParameter(Any.pack(updateBrokerageContract.build())); + raw.addContract(contract.build()); + transaction.setRawData(raw.build()); + assertNotNull(blockingStubFull.getTransactionApprovedList(transaction.build())); + } + + @Test + public void testCreateAssetIssue() { + AssetIssueContract assetIssueContract = AssetIssueContract.newBuilder() + .build(); + assertNotNull(blockingStubFull.createAssetIssue(assetIssueContract)); + assertNotNull(blockingStubFull.createAssetIssue2(assetIssueContract)); + } + + @Test + public void testUnfreezeAsset() { + UnfreezeAssetContract message = UnfreezeAssetContract.newBuilder().build(); + assertNotNull(blockingStubFull.unfreezeAsset(message)); + assertNotNull(blockingStubFull.unfreezeAsset2(message)); + } + + @Test + public void testVoteWitnessAccount() { + VoteWitnessContract message = VoteWitnessContract.newBuilder().build(); + assertNotNull(blockingStubFull.voteWitnessAccount(message)); + assertNotNull(blockingStubFull.voteWitnessAccount2(message)); + } + + @Test + public void testUpdateSetting() { + UpdateSettingContract message = UpdateSettingContract.newBuilder().build(); + assertNotNull(blockingStubFull.updateSetting(message)); + } + + @Test + public void testUpdateEnergyLimit() { + UpdateEnergyLimitContract message = UpdateEnergyLimitContract.newBuilder().build(); + assertNotNull(blockingStubFull.updateEnergyLimit(message)); + } + + @Test + public void testClearContractABI() { + ClearABIContract message = ClearABIContract.newBuilder().build(); + assertNotNull(blockingStubFull.clearContractABI(message)); + } + + @Test + public void testCreateWitness() { + WitnessCreateContract message = WitnessCreateContract.newBuilder().build(); + assertNotNull(blockingStubFull.createWitness(message)); + assertNotNull(blockingStubFull.createWitness2(message)); + } + + @Test + public void testCreateAccount() { + AccountCreateContract message = AccountCreateContract.newBuilder().build(); + assertNotNull(blockingStubFull.createAccount(message)); + assertNotNull(blockingStubFull.createAccount2(message)); + } + + @Test + public void testUpdateWitness() { + WitnessUpdateContract message = WitnessUpdateContract.newBuilder().build(); + assertNotNull(blockingStubFull.updateWitness(message)); + assertNotNull(blockingStubFull.updateWitness2(message)); + } + + @Test + public void testUpdateAccount() { + AccountUpdateContract message = AccountUpdateContract.newBuilder().build(); + assertNotNull(blockingStubFull.updateAccount(message)); + assertNotNull(blockingStubFull.updateAccount2(message)); + } + + @Test + public void testSetAccountId() { + SetAccountIdContract message = SetAccountIdContract.newBuilder().build(); + assertNotNull(blockingStubFull.setAccountId(message)); + } + + @Test + public void testUpdateAsset() { + UpdateAssetContract message = UpdateAssetContract.newBuilder().build(); + assertNotNull(blockingStubFull.updateAsset(message)); + assertNotNull(blockingStubFull.updateAsset2(message)); + } + + @Test + public void testFreezeBalance2() { + FreezeBalanceContract message = FreezeBalanceContract.newBuilder().build(); + assertNotNull(blockingStubFull.freezeBalance(message)); + assertNotNull(blockingStubFull.freezeBalance2(message)); + } + + @Test + public void testFreezeBalanceV2() { + FreezeBalanceV2Contract message = FreezeBalanceV2Contract.newBuilder().build(); + assertNotNull(blockingStubFull.freezeBalanceV2(message)); + } + + @Test + public void testUnfreezeBalance() { + UnfreezeBalanceContract message = UnfreezeBalanceContract.newBuilder().build(); + assertNotNull(blockingStubFull.unfreezeBalance(message)); + assertNotNull(blockingStubFull.unfreezeBalance2(message)); + } + + @Test + public void testUnfreezeBalanceV2() { + UnfreezeBalanceV2Contract message = UnfreezeBalanceV2Contract.newBuilder().build(); + assertNotNull(blockingStubFull.unfreezeBalanceV2(message)); + } + + @Test + public void testWithdrawBalance() { + WithdrawBalanceContract message = WithdrawBalanceContract.newBuilder().build(); + assertNotNull(blockingStubFull.withdrawBalance(message)); + assertNotNull(blockingStubFull.withdrawBalance2(message)); + } + + @Test + public void testWithdrawExpireUnfreeze() { + WithdrawExpireUnfreezeContract message = WithdrawExpireUnfreezeContract.newBuilder().build(); + assertNotNull(blockingStubFull.withdrawExpireUnfreeze(message)); + } + + @Test + public void testDelegateResource() { + DelegateResourceContract message = DelegateResourceContract.newBuilder().build(); + assertNotNull(blockingStubFull.delegateResource(message)); + } + + @Test + public void testUnDelegateResource() { + UnDelegateResourceContract message = UnDelegateResourceContract.newBuilder().build(); + assertNotNull(blockingStubFull.unDelegateResource(message)); + } + + @Test + public void testCancelAllUnfreezeV2() { + CancelAllUnfreezeV2Contract message = CancelAllUnfreezeV2Contract.newBuilder().build(); + assertNotNull(blockingStubFull.cancelAllUnfreezeV2(message)); + } + + @Test + public void testProposalCreate() { + ProposalCreateContract message = ProposalCreateContract.newBuilder().build(); + assertNotNull(blockingStubFull.proposalCreate(message)); + } + + @Test + public void testProposalApprove() { + ProposalApproveContract message = ProposalApproveContract.newBuilder().build(); + assertNotNull(blockingStubFull.proposalApprove(message)); + } + + @Test + public void testProposalDelete() { + ProposalDeleteContract message = ProposalDeleteContract.newBuilder().build(); + assertNotNull(blockingStubFull.proposalDelete(message)); + } + + @Test + public void testExchangeCreate() { + ExchangeCreateContract message = ExchangeCreateContract.newBuilder().build(); + assertNotNull(blockingStubFull.exchangeCreate(message)); + } + + @Test + public void testExchangeInject() { + ExchangeInjectContract message = ExchangeInjectContract.newBuilder().build(); + assertNotNull(blockingStubFull.exchangeInject(message)); + } + + @Test + public void testExchangeWithdraw() { + ExchangeWithdrawContract message = ExchangeWithdrawContract.newBuilder().build(); + assertNotNull(blockingStubFull.exchangeWithdraw(message)); + } + + @Test + public void testExchangeTransaction() { + ExchangeTransactionContract message = ExchangeTransactionContract.newBuilder().build(); + assertNotNull(blockingStubFull.exchangeTransaction(message)); + } + + @Test + public void testTransferAsset() { + TransferAssetContract message = TransferAssetContract.newBuilder().build(); + assertNotNull(blockingStubFull.transferAsset(message)); + assertNotNull(blockingStubFull.transferAsset2(message)); + } + + @Test + public void testParticipateAssetIssue() { + ParticipateAssetIssueContract message = ParticipateAssetIssueContract.newBuilder().build(); + assertNotNull(blockingStubFull.participateAssetIssue(message)); + assertNotNull(blockingStubFull.participateAssetIssue2(message)); + } + + @Test + public void testGetAssetIssueByAccount() { + Account message = Account.newBuilder().build(); + assertNotNull(blockingStubFull.getAssetIssueByAccount(message)); + } + + @Test + public void testGetAccountNet() { + Account message = Account.newBuilder().build(); + assertNotNull(blockingStubFull.getAccountNet(message)); + } + + @Test + public void testGetAccountResource() { + Account message = Account.newBuilder().build(); + assertNotNull(blockingStubFull.getAccountResource(message)); + } + + @Test + public void testGetBlockById() { + BytesMessage message = BytesMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getBlockById(message)); + } + + @Test + public void testGetProposalById() { + BytesMessage message = BytesMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getProposalById(message)); + } + + @Test + public void testGetBlockByLimitNext() { + BlockLimit message = BlockLimit.newBuilder().build(); + assertNotNull(blockingStubFull.getBlockByLimitNext(message)); + assertNotNull(blockingStubFull.getBlockByLimitNext2(message)); + } + + @Test + public void testGetBlockByLatestNum() { + NumberMessage message = NumberMessage.newBuilder().setNum(0).build(); + assertNotNull(blockingStubFull.getBlockByLatestNum(message)); + assertNotNull(blockingStubFull.getBlockByLatestNum2(message)); + } + + @Test + public void testDeployContract() { + CreateSmartContract message = CreateSmartContract.newBuilder().build(); + assertNotNull(blockingStubFull.deployContract(message)); + } + + @Test + public void testTotalTransaction() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(blockingStubFull.totalTransaction(message)); + } + + @Test + public void testGetNextMaintenanceTime() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getNextMaintenanceTime(message)); + } + + @Test + public void testTriggerContract() { + TriggerSmartContract message = TriggerSmartContract.newBuilder().build(); + assertNotNull(blockingStubFull.estimateEnergy(message)); + assertNotNull(blockingStubSolidity.estimateEnergy(message)); + assertNotNull(blockingStubPBFT.estimateEnergy(message)); + } + + @Test + public void testEstimateEnergy() { + TriggerSmartContract message = TriggerSmartContract.newBuilder().build(); + assertNotNull(blockingStubFull.estimateEnergy(message)); + } + + @Test + public void testTriggerConstantContract() { + TriggerSmartContract message = TriggerSmartContract.newBuilder().build(); + assertNotNull(blockingStubFull.triggerConstantContract(message)); + } + + @Test + public void testGetContract() { + BytesMessage message = BytesMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getContract(message)); + } + + @Test + public void testGetContractInfo() { + BytesMessage message = BytesMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getContractInfo(message)); + } + + @Test + public void testListProposals() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(blockingStubFull.listProposals(message)); + } + + @Test + public void testGetBandwidthPrices() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getBandwidthPrices(message)); + assertNotNull(blockingStubSolidity.getBandwidthPrices(message)); + assertNotNull(blockingStubPBFT.getBandwidthPrices(message)); + } + + @Test + public void testGetEnergyPrices() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getEnergyPrices(message)); + assertNotNull(blockingStubSolidity.getEnergyPrices(message)); + assertNotNull(blockingStubPBFT.getEnergyPrices(message)); + } + + @Test + public void testGetMemoFee() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getMemoFee(message)); + } + + @Test + public void testGetPaginatedProposalList() { + PaginatedMessage message = PaginatedMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getPaginatedProposalList(message)); + } + + @Test + public void testGetPaginatedExchangeList() { + PaginatedMessage message = PaginatedMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getPaginatedExchangeList(message)); + } + + @Test + public void testGetChainParameters() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getChainParameters(message)); + } + + @Test + public void testGetNodeInfo() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getNodeInfo(message)); + } + + @Test + public void testAccountPermissionUpdate() { + AccountPermissionUpdateContract message = AccountPermissionUpdateContract.newBuilder().build(); + assertNotNull(blockingStubFull.accountPermissionUpdate(message)); + } + + @Test + public void testCreateShieldedTransaction() { + PrivateParameters message = PrivateParameters.newBuilder().build(); + assertNotNull(blockingStubFull.createShieldedTransaction(message)); + } + + @Test + public void testCreateShieldedTransactionWithoutSpendAuthSig() { + PrivateParametersWithoutAsk message = PrivateParametersWithoutAsk.newBuilder().build(); + assertNotNull(blockingStubFull.createShieldedTransactionWithoutSpendAuthSig(message)); + } + + @Test + public void testGetNewShieldedAddress() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getNewShieldedAddress(message)); + } + + @Test + public void test01GetSpendingKey() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + BytesMessage spendingKey = blockingStubFull.getSpendingKey(message); + assertNotNull(spendingKey); + sk = spendingKey.getValue(); + } + + @Test + public void testGetRcm() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + assertNotNull(blockingStubFull.getRcm(message)); + } + + @Test + public void test02GetExpandedSpendingKey() { + BytesMessage message = BytesMessage.newBuilder().setValue(sk).build(); + ExpandedSpendingKeyMessage eskMessage = blockingStubFull.getExpandedSpendingKey(message); + assertNotNull(eskMessage); + ask = eskMessage.getAsk(); + nsk = eskMessage.getNsk(); + ovk = eskMessage.getOvk(); + } + + @Test + public void test03GetAkFromAsk() { + BytesMessage message = BytesMessage.newBuilder().setValue(ask).build(); + BytesMessage akMessage = blockingStubFull.getAkFromAsk(message); + assertNotNull(akMessage); + ak = akMessage.getValue(); + } + + @Test + public void test04GetNkFromNsk() { + BytesMessage message = BytesMessage.newBuilder().setValue(nsk).build(); + BytesMessage nkFromNsk = blockingStubFull.getNkFromNsk(message); + assertNotNull(nkFromNsk); + nk = nkFromNsk.getValue(); + } + + @Test + public void test05GetIncomingViewingKey() { + ViewingKeyMessage viewingKeyMessage = ViewingKeyMessage.newBuilder() + .setAk(ak) + .setNk(nk) + .build(); + IncomingViewingKeyMessage incomingViewingKey = blockingStubFull + .getIncomingViewingKey(viewingKeyMessage); + assertNotNull(incomingViewingKey); + ivk = incomingViewingKey.getIvk(); + } + + @Test + public void test06GetDiversifier() { + EmptyMessage message = EmptyMessage.newBuilder().build(); + DiversifierMessage diversifier = blockingStubFull.getDiversifier(message); + assertNotNull(diversifier); + d = diversifier.getD(); + } + + @Test + public void test07GetZenPaymentAddress() { + DiversifierMessage diversifierMessage = DiversifierMessage.newBuilder().setD(d).build(); + IncomingViewingKeyMessage incomingViewingKey = IncomingViewingKeyMessage.newBuilder() + .setIvk(ivk).build(); + IncomingViewingKeyDiversifierMessage message = IncomingViewingKeyDiversifierMessage + .newBuilder() + .setD(diversifierMessage) + .setIvk(incomingViewingKey) + .build(); + assertNotNull(blockingStubFull.getZenPaymentAddress(message)); + } + + // @Test + // public void testCreateShieldNullifier() { + // NfParameters message = NfParameters + // .newBuilder().build(); + // assertNotNull(blockingStubFull.createShieldNullifier(message)); + // } + + // @Test + // public void testCreateSpendAuthSig() { + // SpendAuthSigParameters message = SpendAuthSigParameters + // .newBuilder().build(); + // assertNotNull(blockingStubFull.createSpendAuthSig(message)); + // } + + // @Test + // public void testGetShieldTransactionHash() { + // Transaction message = Transaction + // .newBuilder().build(); + // assertNotNull(blockingStubFull.getShieldTransactionHash(message)); + // } + + // @Test + // public void testCreateShieldedContractParameters() { + // PrivateShieldedTRC20Parameters message = PrivateShieldedTRC20Parameters + // .newBuilder().build(); + // assertNotNull(blockingStubFull.createShieldedContractParameters(message)); + // } + + // @Test + // public void testCreateShieldedContractParametersWithoutAsk() throws ZksnarkException { + // SpendingKey sk = SpendingKey.random(); + // ExpandedSpendingKey expsk = sk.expandedSpendingKey(); + // byte[] ovk = expsk.getOvk(); + // PrivateShieldedTRC20ParametersWithoutAsk message = PrivateShieldedTRC20ParametersWithoutAsk + // .newBuilder() + // .setOvk(ByteString.copyFrom(ovk)) + // .setFromAmount(BigInteger.valueOf(50).toString()) + // .setShieldedTRC20ContractAddress(ownerAddress) + // .build(); + // assertNotNull(blockingStubFull + // .createShieldedContractParametersWithoutAsk(message)); + // } +} diff --git a/framework/src/test/java/org/tron/core/services/http/UtilTest.java b/framework/src/test/java/org/tron/core/services/http/UtilTest.java index 1f698796ba7..2fd69a4b8e2 100644 --- a/framework/src/test/java/org/tron/core/services/http/UtilTest.java +++ b/framework/src/test/java/org/tron/core/services/http/UtilTest.java @@ -1,19 +1,27 @@ package org.tron.core.services.http; +import com.google.protobuf.ByteString; import javax.annotation.Resource; + import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.tron.api.GrpcAPI.TransactionApprovedList; import org.tron.api.GrpcAPI.TransactionSignWeight; 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.config.args.Args; import org.tron.core.utils.TransactionUtil; +import org.tron.protos.Protocol; import org.tron.protos.Protocol.Transaction; public class UtilTest extends BaseTest { + private static final String OWNER_ADDRESS; + @Resource private Wallet wallet; @Resource @@ -21,9 +29,23 @@ public class UtilTest extends BaseTest { static { dbPath = "output_util_test"; + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "c076305e35aea1fe45a772fcaaab8a36e87bdb55"; Args.setParam(new String[] {"-d", dbPath}, Constant.TEST_CONF); } + @Before + public void setUp() { + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + AccountCapsule ownerCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(owner), + Protocol.AccountType.Normal, + 10_000_000_000L); + ownerCapsule.setFrozenForBandwidth(1000000L, 1000000L); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + } + @Test public void testPackTransactionWithInvalidType() { @@ -108,4 +130,42 @@ public void testPackTransactionWithInvalidType() { Assert.assertEquals("Invalid transaction: no valid contract", txSignWeight.getResult().getMessage()); } + + @Test + public void testPackTransaction() { + String strTransaction = "{\n" + + " \"visible\": false,\n" + + " \"signature\": [\n" + + " \"5c23bddabccd3e4e5ebdf7d2f21dc58af9f88e0b99620374c5354e0dd9efb3a436167d95b70d2" + + "d825180bf90bc84525acb13a203f209afd5d397316f6b2c387c01\"\n" + + " ],\n" + + " \"txID\": \"fc33817936b06e50d4b6f1797e62f52d69af6c0da580a607241a9c03a48e390e\",\n" + + " \"raw_data\": {\n" + + " \"contract\": [\n" + + " {\n" + + " \"parameter\": {\n" + + " \"value\": {\n" + + " \"amount\": 10,\n" + + " \"owner_address\":\"41c076305e35aea1fe45a772fcaaab8a36e87bdb55\"," + + " \"to_address\": \"415624c12e308b03a1a6b21d9b86e3942fac1ab92b\"\n" + + " },\n" + + " \"type_url\": \"type.googleapis.com/protocol.TransferContract\"\n" + + " },\n" + + " \"type\": \"TransferContract\"\n" + + " }\n" + + " ],\n" + + " \"ref_block_bytes\": \"d8ed\",\n" + + " \"ref_block_hash\": \"2e066c3259e756f5\",\n" + + " \"expiration\": 1651906644000,\n" + + " \"timestamp\": 1651906586162\n" + + " },\n" + + " \"raw_data_hex\": \"0a02d8ed22082e066c3259e756f540a090bcea89305a65080112610a2d747970" + + "652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e74726163741230" + + "0a1541c076305e35aea1fe45a772fcaaab8a36e87bdb551215415624c12e308b03a1a6b21d9b86e3942fac1a" + + "b92b180a70b2ccb8ea8930\"\n" + + "}"; + Transaction transaction = Util.packTransaction(strTransaction, false); + TransactionSignWeight txSignWeight = transactionUtil.getTransactionSignWeight(transaction); + Assert.assertNotNull(txSignWeight); + } } diff --git a/framework/src/test/java/org/tron/keystore/WalletFileTest.java b/framework/src/test/java/org/tron/keystore/WalletFileTest.java index 7d584b3d8e2..c24647be322 100644 --- a/framework/src/test/java/org/tron/keystore/WalletFileTest.java +++ b/framework/src/test/java/org/tron/keystore/WalletFileTest.java @@ -2,7 +2,6 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; -import junit.framework.TestCase; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; import org.junit.Test; @@ -10,8 +9,7 @@ import org.tron.core.exception.CipherException; @Slf4j -public class WalletFileTest extends TestCase { - +public class WalletFileTest { @Test public void testGetAddress() throws NoSuchAlgorithmException, CipherException { @@ -19,10 +17,59 @@ public void testGetAddress() throws NoSuchAlgorithmException, CipherException { SecureRandom.getInstance("NativePRNG"),true)); WalletFile walletFile2 = Wallet.createStandard("", SignUtils.getGeneratedRandomSign( SecureRandom.getInstance("NativePRNG"),true)); - Assert.assertTrue(!walletFile1.getAddress().equals(walletFile2.getAddress())); - Assert.assertTrue(!walletFile1.getCrypto().equals(walletFile2.getCrypto())); - Assert.assertTrue(!walletFile1.getId().equals(walletFile2.getId())); - Assert.assertTrue(walletFile1.getVersion() == walletFile2.getVersion()); + WalletFile walletFile3 = (WalletFile) getSame(walletFile1); + Assert.assertNotEquals(walletFile1.getAddress(), walletFile2.getAddress()); + Assert.assertNotEquals(walletFile1.getCrypto(), walletFile2.getCrypto()); + Assert.assertNotEquals(walletFile1.getId(), walletFile2.getId()); + Assert.assertEquals(walletFile1.getVersion(), walletFile2.getVersion()); + Assert.assertNotEquals(walletFile1, walletFile2); + Assert.assertEquals(walletFile1, walletFile3); + Assert.assertNotEquals(walletFile1, null); + Assert.assertNotEquals(walletFile2, new Object()); + Assert.assertNotEquals(0, walletFile1.hashCode()); + + WalletFile.CipherParams cipherParams = new WalletFile.CipherParams(); + WalletFile.CipherParams cipherParams1 = new WalletFile.CipherParams(); + WalletFile.CipherParams cipherParams2 = (WalletFile.CipherParams) getSame(cipherParams); + Assert.assertEquals(cipherParams, cipherParams1); + Assert.assertEquals(cipherParams, cipherParams2); + Assert.assertNotEquals(cipherParams, null); + Assert.assertNotEquals(cipherParams, new Object()); + Assert.assertEquals(0, cipherParams.hashCode()); + + WalletFile.Aes128CtrKdfParams aes128CtrKdfParams = new WalletFile.Aes128CtrKdfParams(); + WalletFile.Aes128CtrKdfParams aes128CtrKdfParams1 = new WalletFile.Aes128CtrKdfParams(); + WalletFile.Aes128CtrKdfParams aes128CtrKdfParams2 = (WalletFile.Aes128CtrKdfParams) + getSame(aes128CtrKdfParams); + Assert.assertEquals(aes128CtrKdfParams, aes128CtrKdfParams1); + Assert.assertEquals(aes128CtrKdfParams, aes128CtrKdfParams2); + Assert.assertNotEquals(aes128CtrKdfParams, null); + Assert.assertNotEquals(aes128CtrKdfParams, new Object()); + Assert.assertEquals(0, aes128CtrKdfParams.hashCode()); + + WalletFile.ScryptKdfParams scryptKdfParams = new WalletFile.ScryptKdfParams(); + WalletFile.ScryptKdfParams scryptKdfParams1 = new WalletFile.ScryptKdfParams(); + WalletFile.ScryptKdfParams scryptKdfParams2 = (WalletFile.ScryptKdfParams) + getSame(scryptKdfParams); + Assert.assertEquals(scryptKdfParams, scryptKdfParams1); + Assert.assertEquals(scryptKdfParams, scryptKdfParams2); + Assert.assertNotEquals(scryptKdfParams, null); + Assert.assertNotEquals(scryptKdfParams, new Object()); + Assert.assertEquals(0, scryptKdfParams.hashCode()); + + WalletFile.Crypto crypto = new WalletFile.Crypto(); + WalletFile.Crypto crypto1 = new WalletFile.Crypto(); + WalletFile.Crypto crypto2 = (WalletFile.Crypto) getSame(crypto); + Assert.assertEquals(crypto, crypto1); + Assert.assertEquals(crypto, crypto2); + Assert.assertNotEquals(crypto, null); + Assert.assertNotEquals(crypto, new Object()); + Assert.assertEquals(0, crypto.hashCode()); + + } + + private Object getSame(Object obj) { + return obj; } } \ No newline at end of file From 6748bcef39d63418648598b49176c1af03313b68 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 7 Sep 2023 15:03:13 +0800 Subject: [PATCH 0883/1197] test(net):optimize test code --- .../core/net/messagehandler/PbftDataSyncHandlerTest.java | 6 ++++++ .../core/net/messagehandler/TransactionsMsgHandlerTest.java | 4 +--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/PbftDataSyncHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/PbftDataSyncHandlerTest.java index 37911cb1b53..d1fdfaa5d90 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/PbftDataSyncHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/PbftDataSyncHandlerTest.java @@ -1,8 +1,10 @@ package org.tron.core.net.messagehandler; +import com.alibaba.fastjson.JSON; import com.google.protobuf.ByteString; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Map; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; @@ -47,5 +49,9 @@ public void testProcessMessage() throws Exception { field.set(pbftDataSyncHandler, chainBaseManager); pbftDataSyncHandler.processPBFTCommitData(blockCapsule); + Field field1 = PbftDataSyncHandler.class.getDeclaredField("pbftCommitMessageCache"); + field1.setAccessible(true); + Map map = JSON.parseObject(JSON.toJSONString(field1.get(pbftDataSyncHandler)), Map.class); + Assert.assertFalse(map.containsKey(0)); } } diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java index 2a5cacbe0cc..fe58928e3bc 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java @@ -7,7 +7,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import lombok.extern.slf4j.Slf4j; import org.joda.time.DateTime; import org.junit.Assert; import org.junit.BeforeClass; @@ -26,7 +25,6 @@ import org.tron.protos.Protocol; import org.tron.protos.contract.BalanceContract; -@Slf4j public class TransactionsMsgHandlerTest extends BaseTest { @BeforeClass public static void init() { @@ -79,7 +77,7 @@ public void testProcessMessage() { Assert.assertNull(advInvRequest.get(item)); //Thread.sleep(10); } catch (Exception e) { - logger.error("error", e); + Assert.fail(); } finally { transactionsMsgHandler.close(); } From 1e500f080b9e55f6bda8e1ea95f7c816d2ec29df Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 7 Sep 2023 17:19:29 +0800 Subject: [PATCH 0884/1197] feat(config): update jacoco config --- actuator/build.gradle | 2 +- chainbase/build.gradle | 2 +- common/build.gradle | 2 +- consensus/build.gradle | 2 +- crypto/build.gradle | 13 +++++++++++++ framework/build.gradle | 2 +- plugins/build.gradle | 4 ++-- 7 files changed, 20 insertions(+), 7 deletions(-) diff --git a/actuator/build.gradle b/actuator/build.gradle index 15f661be9bd..a0ce72b0ee6 100644 --- a/actuator/build.gradle +++ b/actuator/build.gradle @@ -52,7 +52,7 @@ jacocoTestReport { xml.enabled = true html.enabled = true } - executionData.from = '../framework/build/jacoco/jacocoTest.exec' + getExecutionData().setFrom(fileTree('../framework/build/jacoco').include("**.exec")) afterEvaluate { classDirectories.from = classDirectories.files.collect { fileTree(dir: it,) diff --git a/chainbase/build.gradle b/chainbase/build.gradle index fb1778d2fc6..a2868aa78b4 100644 --- a/chainbase/build.gradle +++ b/chainbase/build.gradle @@ -80,7 +80,7 @@ jacocoTestReport { xml.enabled = true html.enabled = true } - executionData.from = '../framework/build/jacoco/jacocoTest.exec' + getExecutionData().setFrom(fileTree('../framework/build/jacoco').include("**.exec")) afterEvaluate { classDirectories.from = classDirectories.files.collect { fileTree(dir: it,) diff --git a/common/build.gradle b/common/build.gradle index 0ed13763a1e..641ac4d07cf 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -68,7 +68,7 @@ jacocoTestReport { xml.enabled = true html.enabled = true } - executionData.from = '../framework/build/jacoco/jacocoTest.exec' + getExecutionData().setFrom(fileTree('../framework/build/jacoco').include("**.exec")) afterEvaluate { classDirectories.from = classDirectories.files.collect { fileTree(dir: it,) diff --git a/consensus/build.gradle b/consensus/build.gradle index c12662446f1..78f60bd7530 100644 --- a/consensus/build.gradle +++ b/consensus/build.gradle @@ -48,7 +48,7 @@ jacocoTestReport { xml.enabled = true html.enabled = true } - executionData.from = '../framework/build/jacoco/jacocoTest.exec' + getExecutionData().setFrom(fileTree('../framework/build/jacoco').include("**.exec")) afterEvaluate { classDirectories.from = classDirectories.files.collect { fileTree(dir: it,) diff --git a/crypto/build.gradle b/crypto/build.gradle index 19ae8e805fe..5bbfc630c45 100644 --- a/crypto/build.gradle +++ b/crypto/build.gradle @@ -15,3 +15,16 @@ dependencies { compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' compile project(":common") } + +jacocoTestReport { + reports { + xml.enabled = true + html.enabled = true + } + getExecutionData().setFrom(fileTree('../framework/build/jacoco').include("**.exec")) + afterEvaluate { + classDirectories.from = classDirectories.files.collect { + fileTree(dir: it,) + } + } +} diff --git a/framework/build.gradle b/framework/build.gradle index 9bc93cacf33..c894ae1e03d 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -165,7 +165,7 @@ jacocoTestReport { csv.enabled false html.destination file("${buildDir}/jacocoHtml") } - executionData.from = 'build/jacoco/jacocoTest.exec' + getExecutionData().setFrom(fileTree('../framework/build/jacoco').include("**.exec")) } def binaryRelease(taskName, jarName, mainClass) { diff --git a/plugins/build.gradle b/plugins/build.gradle index 9f4cb3ef59b..eca66dca27d 100644 --- a/plugins/build.gradle +++ b/plugins/build.gradle @@ -76,7 +76,7 @@ test { exceptionFormat = 'full' } jacoco { - destinationFile = file("$buildDir/jacoco/jacocoTest.exec") + destinationFile = file("../framework/build/jacoco/jacocoTest1.exec") classDumpDir = file("$buildDir/jacoco/classpathdumps") } } @@ -87,7 +87,7 @@ jacocoTestReport { csv.enabled false html.destination file("${buildDir}/jacocoHtml") } - executionData.from = 'build/jacoco/jacocoTest.exec' + getExecutionData().setFrom(fileTree('../framework/build/jacoco').include("**.exec")) } def binaryRelease(taskName, jarName, mainClass) { From 17558c54ed1891cd293fdf17858ddcd2d96db2a9 Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 7 Sep 2023 21:32:02 +0800 Subject: [PATCH 0885/1197] test(case): add WitnessScheduleStoreTest test case --- .../core/db/WitnessScheduleStoreTest.java | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/db/WitnessScheduleStoreTest.java diff --git a/framework/src/test/java/org/tron/core/db/WitnessScheduleStoreTest.java b/framework/src/test/java/org/tron/core/db/WitnessScheduleStoreTest.java new file mode 100644 index 00000000000..c12e5fdc413 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/WitnessScheduleStoreTest.java @@ -0,0 +1,106 @@ +package org.tron.core.db; + +import com.google.protobuf.ByteString; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; + +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.config.args.Args; +import org.tron.core.store.WitnessScheduleStore; + +public class WitnessScheduleStoreTest extends BaseTest { + + @Resource + private WitnessScheduleStore witnessScheduleStore; + private static final String KEY1 = "41f08012b4881c320eb40b80f1228731898824e09d"; + private static final String KEY2 = "41df309fef25b311e7895562bd9e11aab2a58816d2"; + private static final String KEY3 = "41F8C7ACC4C08CF36CA08FC2A61B1F5A7C8DEA7BEC"; + + private static final String CURRENT_KEY1 = "411D7ABA13EA199A63D1647E58E39C16A9BB9DA689"; + private static final String CURRENT_KEY2 = "410694981B116304ED21E05896FB16A6BC2E91C92C"; + private static final String CURRENT_KEY3 = "411155D10415FAC16A8F4CB2F382CE0E0F0A7E64CC"; + + private static List witnessAddresses; + private static List currentShuffledWitnesses; + + + static { + dbPath = "output-WitnessScheduleStore-test"; + Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + } + + @Before + public void init() { + witnessAddresses = Arrays.asList( + getByteString(KEY1), + getByteString(KEY2), + getByteString(KEY3) + ); + + currentShuffledWitnesses = Arrays.asList( + getByteString(CURRENT_KEY1), + getByteString(CURRENT_KEY2), + getByteString(CURRENT_KEY3) + ); + } + + private ByteString getByteString(String address) { + return ByteString.copyFrom( + ByteArray.fromHexString(address)); + } + + @Test + public void tetSaveActiveWitnesses() { + witnessScheduleStore.saveActiveWitnesses(witnessAddresses); + List activeWitnesses = witnessScheduleStore.getActiveWitnesses(); + Assert.assertNotNull(activeWitnesses); + Assert.assertEquals(3, activeWitnesses.size()); + ByteString firstWitness = activeWitnesses.get(0); + Assert.assertEquals(getByteString(KEY1), firstWitness); + } + + @Test + public void testGetActiveWitnesses() { + witnessScheduleStore.saveActiveWitnesses(witnessAddresses); + List activeWitnesses = witnessScheduleStore.getActiveWitnesses(); + Assert.assertNotNull(activeWitnesses); + Assert.assertEquals(3, activeWitnesses.size()); + ByteString firstWitness = activeWitnesses.get(0); + ByteString secondWitness = activeWitnesses.get(1); + ByteString thirdWitness = activeWitnesses.get(2); + Assert.assertEquals(getByteString(KEY1), firstWitness); + Assert.assertEquals(getByteString(KEY2), secondWitness); + Assert.assertEquals(getByteString(KEY3), thirdWitness); + } + + @Test + public void testSaveCurrentShuffledWitnesses() { + witnessScheduleStore.saveCurrentShuffledWitnesses(currentShuffledWitnesses); + List currentWitnesses = witnessScheduleStore.getCurrentShuffledWitnesses(); + Assert.assertNotNull(currentWitnesses); + Assert.assertEquals(3, currentWitnesses.size()); + ByteString firstWitness = currentWitnesses.get(0); + Assert.assertEquals(getByteString(CURRENT_KEY1), firstWitness); + } + + @Test + public void GetCurrentShuffledWitnesses() { + witnessScheduleStore.saveCurrentShuffledWitnesses(currentShuffledWitnesses); + List currentWitnesses = witnessScheduleStore.getCurrentShuffledWitnesses(); + Assert.assertNotNull(currentWitnesses); + Assert.assertEquals(3, currentWitnesses.size()); + ByteString firstWitness = currentWitnesses.get(0); + ByteString secondWitness = currentWitnesses.get(1); + ByteString thirdWitness = currentWitnesses.get(2); + Assert.assertEquals(getByteString(CURRENT_KEY1), firstWitness); + Assert.assertEquals(getByteString(CURRENT_KEY2), secondWitness); + Assert.assertEquals(getByteString(CURRENT_KEY3), thirdWitness); + } + +} From b54912a339104a5ba9e6dac664c78e835354bcfb Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Tue, 12 Sep 2023 12:14:07 +0800 Subject: [PATCH 0886/1197] test(plugins): add test for plugins (#5482) --- plugins/build.gradle | 3 + .../java/org/tron/plugins/DbConvertTest.java | 92 ++------- .../java/org/tron/plugins/DbCopyTest.java | 53 ++++++ .../org/tron/plugins/DbLiteLevelDbTest.java | 13 ++ .../org/tron/plugins/DbLiteLevelDbV2Test.java | 12 ++ .../org/tron/plugins/DbLiteRocksDbTest.java | 12 ++ .../java/org/tron/plugins/DbLiteTest.java | 176 ++++++++++++++++++ .../test/java/org/tron/plugins/DbTest.java | 89 +++++++++ 8 files changed, 372 insertions(+), 78 deletions(-) create mode 100644 plugins/src/test/java/org/tron/plugins/DbCopyTest.java create mode 100644 plugins/src/test/java/org/tron/plugins/DbLiteLevelDbTest.java create mode 100644 plugins/src/test/java/org/tron/plugins/DbLiteLevelDbV2Test.java create mode 100644 plugins/src/test/java/org/tron/plugins/DbLiteRocksDbTest.java create mode 100644 plugins/src/test/java/org/tron/plugins/DbLiteTest.java create mode 100644 plugins/src/test/java/org/tron/plugins/DbTest.java diff --git a/plugins/build.gradle b/plugins/build.gradle index 9f4cb3ef59b..d8578f576b0 100644 --- a/plugins/build.gradle +++ b/plugins/build.gradle @@ -29,6 +29,8 @@ dependencies { testCompile group: 'junit', name: 'junit', version: '4.13.2' testCompile group: 'org.mockito', name: 'mockito-core', version: '2.13.0' testCompile group: 'org.hamcrest', name: 'hamcrest-junit', version: '1.0.0.1' + testCompile project(":framework") + testCompile project(":framework").sourceSets.test.output compile group: 'info.picocli', name: 'picocli', version: '4.6.3' compile group: 'com.typesafe', name: 'config', version: '1.3.2' compile group: 'me.tongfei', name: 'progressbar', version: '0.9.3' @@ -75,6 +77,7 @@ test { testLogging { exceptionFormat = 'full' } + maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 jacoco { destinationFile = file("$buildDir/jacoco/jacocoTest.exec") classDumpDir = file("$buildDir/jacoco/classpathdumps") diff --git a/plugins/src/test/java/org/tron/plugins/DbConvertTest.java b/plugins/src/test/java/org/tron/plugins/DbConvertTest.java index 91996815c01..150e47c9f65 100644 --- a/plugins/src/test/java/org/tron/plugins/DbConvertTest.java +++ b/plugins/src/test/java/org/tron/plugins/DbConvertTest.java @@ -1,85 +1,24 @@ package org.tron.plugins; -import java.io.File; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.util.UUID; -import org.iq80.leveldb.DB; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.BeforeClass; import org.junit.Test; -import org.tron.plugins.utils.ByteArray; -import org.tron.plugins.utils.DBUtils; -import org.tron.plugins.utils.FileUtils; -import org.tron.plugins.utils.MarketUtils; import picocli.CommandLine; -public class DbConvertTest { +public class DbConvertTest extends DbTest { - - private static final String INPUT_DIRECTORY = "output-directory/convert-database/"; - private static final String OUTPUT_DIRECTORY = "output-directory/convert-database-dest/"; - private static final String ACCOUNT = "account"; - private static final String MARKET = DBUtils.MARKET_PAIR_PRICE_TO_ORDER; - CommandLine cli = new CommandLine(new Toolkit()); - - - @BeforeClass - public static void init() throws IOException { - if (new File(INPUT_DIRECTORY).mkdirs()) { - initDB(new File(INPUT_DIRECTORY,ACCOUNT)); - initDB(new File(INPUT_DIRECTORY,MARKET)); - } - } - - private static void initDB(File file) throws IOException { - try (DB db = DBUtils.newLevelDb(file.toPath())) { - if (MARKET.equalsIgnoreCase(file.getName())) { - byte[] sellTokenID1 = ByteArray.fromString("100"); - byte[] buyTokenID1 = ByteArray.fromString("200"); - byte[] pairPriceKey1 = MarketUtils.createPairPriceKey( - sellTokenID1, - buyTokenID1, - 1000L, - 2001L - ); - byte[] pairPriceKey2 = MarketUtils.createPairPriceKey( - sellTokenID1, - buyTokenID1, - 1000L, - 2002L - ); - byte[] pairPriceKey3 = MarketUtils.createPairPriceKey( - sellTokenID1, - buyTokenID1, - 1000L, - 2003L - ); - - - //Use out-of-order insertion,key in store should be 1,2,3 - db.put(pairPriceKey1, "1".getBytes(StandardCharsets.UTF_8)); - db.put(pairPriceKey2, "2".getBytes(StandardCharsets.UTF_8)); - db.put(pairPriceKey3, "3".getBytes(StandardCharsets.UTF_8)); - } else { - for (int i = 0; i < 100; i++) { - byte[] bytes = UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8); - db.put(bytes, bytes); - } - } - } - } - - @AfterClass - public static void destroy() { - FileUtils.deleteDir(new File(INPUT_DIRECTORY)); - FileUtils.deleteDir(new File(OUTPUT_DIRECTORY)); + @Test + public void testRun() throws IOException { + String[] args = new String[] { "db", "convert", INPUT_DIRECTORY, + temporaryFolder.newFolder().toString() }; + Assert.assertEquals(0, cli.execute(args)); } @Test - public void testRun() { - String[] args = new String[] { "db", "convert", INPUT_DIRECTORY, OUTPUT_DIRECTORY }; + public void testRunWithSafe() throws IOException { + String[] args = new String[] { "db", "convert", INPUT_DIRECTORY, + temporaryFolder.newFolder().toString(),"--safe" }; Assert.assertEquals(0, cli.execute(args)); } @@ -92,18 +31,15 @@ public void testHelp() { @Test public void testNotExist() { - String[] args = new String[] {"db", "convert", - OUTPUT_DIRECTORY + File.separator + UUID.randomUUID(), - OUTPUT_DIRECTORY}; + String[] args = new String[] {"db", "convert", UUID.randomUUID().toString(), + UUID.randomUUID().toString()}; Assert.assertEquals(404, cli.execute(args)); } @Test - public void testEmpty() { - File file = new File(OUTPUT_DIRECTORY + File.separator + UUID.randomUUID()); - file.mkdirs(); - file.deleteOnExit(); - String[] args = new String[] {"db", "convert", file.toString(), OUTPUT_DIRECTORY}; + public void testEmpty() throws IOException { + String[] args = new String[] {"db", "convert", temporaryFolder.newFolder().toString(), + temporaryFolder.newFolder().toString()}; Assert.assertEquals(0, cli.execute(args)); } diff --git a/plugins/src/test/java/org/tron/plugins/DbCopyTest.java b/plugins/src/test/java/org/tron/plugins/DbCopyTest.java new file mode 100644 index 00000000000..c5cc8f2bb31 --- /dev/null +++ b/plugins/src/test/java/org/tron/plugins/DbCopyTest.java @@ -0,0 +1,53 @@ +package org.tron.plugins; + +import java.io.IOException; +import java.util.UUID; +import org.junit.Assert; +import org.junit.Test; +import picocli.CommandLine; + +public class DbCopyTest extends DbTest { + + @Test + public void testRun() { + String[] args = new String[] { "db", "cp", INPUT_DIRECTORY, + tmpDir + UUID.randomUUID()}; + Assert.assertEquals(0, cli.execute(args)); + } + + @Test + public void testHelp() { + String[] args = new String[] {"db", "cp", "-h"}; + CommandLine cli = new CommandLine(new Toolkit()); + Assert.assertEquals(0, cli.execute(args)); + } + + @Test + public void testNotExist() { + String[] args = new String[] {"db", "cp", UUID.randomUUID().toString(), + UUID.randomUUID().toString()}; + Assert.assertEquals(404, cli.execute(args)); + } + + @Test + public void testEmpty() throws IOException { + String[] args = new String[] {"db", "cp", temporaryFolder.newFolder().toString(), + tmpDir + UUID.randomUUID()}; + Assert.assertEquals(0, cli.execute(args)); + } + + @Test + public void testDestIsExist() throws IOException { + String[] args = new String[] {"db", "cp", temporaryFolder.newFile().toString(), + temporaryFolder.newFolder().toString()}; + Assert.assertEquals(402, cli.execute(args)); + } + + @Test + public void testSrcIsFile() throws IOException { + String[] args = new String[] {"db", "cp", temporaryFolder.newFile().toString(), + tmpDir + UUID.randomUUID()}; + Assert.assertEquals(403, cli.execute(args)); + } + +} diff --git a/plugins/src/test/java/org/tron/plugins/DbLiteLevelDbTest.java b/plugins/src/test/java/org/tron/plugins/DbLiteLevelDbTest.java new file mode 100644 index 00000000000..792f93ad197 --- /dev/null +++ b/plugins/src/test/java/org/tron/plugins/DbLiteLevelDbTest.java @@ -0,0 +1,13 @@ +package org.tron.plugins; + +import java.io.IOException; +import org.junit.Test; + + +public class DbLiteLevelDbTest extends DbLiteTest { + + @Test + public void testToolsWithLevelDB() throws InterruptedException, IOException { + testTools("LEVELDB", 1); + } +} diff --git a/plugins/src/test/java/org/tron/plugins/DbLiteLevelDbV2Test.java b/plugins/src/test/java/org/tron/plugins/DbLiteLevelDbV2Test.java new file mode 100644 index 00000000000..ae48e1d66e9 --- /dev/null +++ b/plugins/src/test/java/org/tron/plugins/DbLiteLevelDbV2Test.java @@ -0,0 +1,12 @@ +package org.tron.plugins; + +import java.io.IOException; +import org.junit.Test; + +public class DbLiteLevelDbV2Test extends DbLiteTest { + + @Test + public void testToolsWithLevelDBV2() throws InterruptedException, IOException { + testTools("LEVELDB", 2); + } +} diff --git a/plugins/src/test/java/org/tron/plugins/DbLiteRocksDbTest.java b/plugins/src/test/java/org/tron/plugins/DbLiteRocksDbTest.java new file mode 100644 index 00000000000..e6910b1103a --- /dev/null +++ b/plugins/src/test/java/org/tron/plugins/DbLiteRocksDbTest.java @@ -0,0 +1,12 @@ +package org.tron.plugins; + +import java.io.IOException; +import org.junit.Test; + +public class DbLiteRocksDbTest extends DbLiteTest { + + @Test + public void testToolsWithRocksDB() throws InterruptedException, IOException { + testTools("ROCKSDB", 1); + } +} diff --git a/plugins/src/test/java/org/tron/plugins/DbLiteTest.java b/plugins/src/test/java/org/tron/plugins/DbLiteTest.java new file mode 100644 index 00000000000..8baf48b0b48 --- /dev/null +++ b/plugins/src/test/java/org/tron/plugins/DbLiteTest.java @@ -0,0 +1,176 @@ +package org.tron.plugins; + +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.junit.After; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; +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 picocli.CommandLine; + +@Slf4j +public class DbLiteTest { + + private TronApplicationContext context; + private WalletGrpc.WalletBlockingStub blockingStubFull = null; + private ManagedChannel channelFull; + private Application appTest; + private String databaseDir; + + @Rule + public final TemporaryFolder folder = new TemporaryFolder(); + + private String dbPath; + CommandLine cli = new CommandLine(new DbLite()); + + /** + * 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); + } + + /** + * shutdown the fullNode. + */ + public void shutdown() throws InterruptedException { + if (channelFull != null) { + channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + context.close(); + } + + public void init() throws IOException { + dbPath = folder.newFolder().toString(); + Args.setParam(new String[]{"-d", dbPath, "-w", "--p2p-disable", "true"}, + "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() { + Args.clearParam(); + } + + void testTools(String dbType, int checkpointVersion) + throws InterruptedException, IOException { + logger.info("dbType {}, checkpointVersion {}", dbType, checkpointVersion); + 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); + DbLite.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 + cli.execute(argsForSnapshot); + // start fullNode + startApp(); + // produce transactions for 6 seconds + generateSomeTransactions(6); + // stop the node + shutdown(); + // generate history + cli.execute(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 + cli.execute(argsForMerge); + // start and validate + startApp(); + generateSomeTransactions(6); + shutdown(); + DbLite.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/src/test/java/org/tron/plugins/DbTest.java b/plugins/src/test/java/org/tron/plugins/DbTest.java new file mode 100644 index 00000000000..8a5f9de4a67 --- /dev/null +++ b/plugins/src/test/java/org/tron/plugins/DbTest.java @@ -0,0 +1,89 @@ +package org.tron.plugins; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Paths; +import java.util.UUID; +import org.iq80.leveldb.DB; +import org.junit.Before; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; +import org.tron.plugins.utils.ByteArray; +import org.tron.plugins.utils.DBUtils; +import org.tron.plugins.utils.MarketUtils; +import picocli.CommandLine; + +public class DbTest { + + String INPUT_DIRECTORY; + private static final String ACCOUNT = "account"; + private static final String MARKET = DBUtils.MARKET_PAIR_PRICE_TO_ORDER; + CommandLine cli = new CommandLine(new Toolkit()); + String tmpDir = System.getProperty("java.io.tmpdir"); + + @Rule + public final TemporaryFolder temporaryFolder = new TemporaryFolder(); + + + @Before + public void init() throws IOException { + INPUT_DIRECTORY = temporaryFolder.newFolder().toString(); + initDB(new File(INPUT_DIRECTORY, ACCOUNT)); + initDB(new File(INPUT_DIRECTORY, MARKET)); + initDB(new File(INPUT_DIRECTORY, DBUtils.CHECKPOINT_DB_V2)); + } + + private static void initDB(File file) throws IOException { + if (DBUtils.CHECKPOINT_DB_V2.equalsIgnoreCase(file.getName())) { + File dbFile = new File(file, DBUtils.CHECKPOINT_DB_V2); + if (dbFile.mkdirs()) { + for (int i = 0; i < 3; i++) { + try (DB db = DBUtils.newLevelDb(Paths.get(dbFile.getPath(), + System.currentTimeMillis() + ""))) { + for (int j = 0; j < 100; j++) { + byte[] bytes = UUID.randomUUID().toString().getBytes(); + db.put(bytes, bytes); + } + } + } + } + return; + } + try (DB db = DBUtils.newLevelDb(file.toPath())) { + if (MARKET.equalsIgnoreCase(file.getName())) { + byte[] sellTokenID1 = ByteArray.fromString("100"); + byte[] buyTokenID1 = ByteArray.fromString("200"); + byte[] pairPriceKey1 = MarketUtils.createPairPriceKey( + sellTokenID1, + buyTokenID1, + 1000L, + 2001L + ); + byte[] pairPriceKey2 = MarketUtils.createPairPriceKey( + sellTokenID1, + buyTokenID1, + 1000L, + 2002L + ); + byte[] pairPriceKey3 = MarketUtils.createPairPriceKey( + sellTokenID1, + buyTokenID1, + 1000L, + 2003L + ); + + + //Use out-of-order insertion,key in store should be 1,2,3 + db.put(pairPriceKey1, "1".getBytes(StandardCharsets.UTF_8)); + db.put(pairPriceKey2, "2".getBytes(StandardCharsets.UTF_8)); + db.put(pairPriceKey3, "3".getBytes(StandardCharsets.UTF_8)); + } else { + for (int i = 0; i < 100; i++) { + byte[] bytes = UUID.randomUUID().toString().getBytes(); + db.put(bytes, bytes); + } + } + } + } +} From 0fbbc7aba3b869660f9ad230aecefc8fe6b8dfea Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Tue, 12 Sep 2023 14:17:49 +0800 Subject: [PATCH 0887/1197] test(refactor): create folders with temporaryFolder (#5477) --- .../test/java/org/tron/common/BaseTest.java | 28 +++++++++------ .../org/tron/common/config/args/ArgsTest.java | 14 ++++---- .../tron/common/runtime/InheritanceTest.java | 3 +- .../InternalTransactionComplexTest.java | 3 +- .../common/runtime/ProgramResultTest.java | 3 +- .../tron/common/runtime/RuntimeImplTest.java | 3 +- .../runtime/RuntimeTransferComplexTest.java | 3 +- .../vm/BandWidthRuntimeOutOfTimeTest.java | 3 +- ...andWidthRuntimeOutOfTimeWithCheckTest.java | 3 +- .../runtime/vm/BandWidthRuntimeTest.java | 3 +- .../vm/BandWidthRuntimeWithCheckTest.java | 3 +- .../tron/common/runtime/vm/BatchSendTest.java | 3 +- .../tron/common/runtime/vm/ChargeTest.java | 3 +- .../runtime/vm/EnergyWhenAssertStyleTest.java | 3 +- .../vm/EnergyWhenRequireStyleTest.java | 3 +- .../vm/EnergyWhenSendAndTransferTest.java | 3 +- .../vm/EnergyWhenTimeoutStyleTest.java | 3 +- .../tron/common/runtime/vm/FreezeTest.java | 16 ++++----- .../tron/common/runtime/vm/FreezeV2Test.java | 16 ++++----- .../vm/InternalTransactionCallTest.java | 19 +++++------ .../common/runtime/vm/OperationsTest.java | 6 +--- .../runtime/vm/PrecompiledContractsTest.java | 3 +- .../PrecompiledContractsVerifyProofTest.java | 3 +- .../common/runtime/vm/RepositoryTest.java | 3 +- .../common/runtime/vm/TimeBenchmarkTest.java | 3 +- .../runtime/vm/TransferToAccountTest.java | 3 +- .../common/runtime/vm/TransferTokenTest.java | 3 +- .../common/runtime/vm/VMContractTestBase.java | 20 +++++------ .../tron/common/runtime/vm/VMTestBase.java | 21 ++++++------ .../vm/ValidateMultiSignContractTest.java | 3 +- .../org/tron/common/runtime/vm/VoteTest.java | 14 ++++---- .../leveldb/LevelDbDataSourceImplTest.java | 19 ++++++----- .../leveldb/RocksDbDataSourceImplTest.java | 27 ++++++--------- .../org/tron/core/BandwidthProcessorTest.java | 3 +- .../org/tron/core/EnergyProcessorTest.java | 3 +- .../org/tron/core/ForkControllerTest.java | 15 ++++---- .../tron/core/ShieldedTRC20BuilderTest.java | 3 +- .../java/org/tron/core/StorageMarketTest.java | 3 +- .../test/java/org/tron/core/WalletTest.java | 3 +- .../AccountPermissionUpdateActuatorTest.java | 3 +- .../core/actuator/ActuatorConstantTest.java | 3 +- .../core/actuator/AssetIssueActuatorTest.java | 3 +- .../CancelAllUnfreezeV2ActuatorTest.java | 3 +- .../ClearABIContractActuatorTest.java | 3 +- .../actuator/CreateAccountActuatorTest.java | 3 +- .../DelegateResourceActuatorTest.java | 3 +- .../actuator/ExchangeCreateActuatorTest.java | 3 +- .../actuator/ExchangeInjectActuatorTest.java | 3 +- .../ExchangeTransactionActuatorTest.java | 3 +- .../ExchangeWithdrawActuatorTest.java | 3 +- .../actuator/FreezeBalanceActuatorTest.java | 3 +- .../actuator/FreezeBalanceV2ActuatorTest.java | 3 +- .../MarketCancelOrderActuatorTest.java | 3 +- .../actuator/MarketSellAssetActuatorTest.java | 3 +- .../ParticipateAssetIssueActuatorTest.java | 3 +- .../actuator/ProposalApproveActuatorTest.java | 3 +- .../actuator/ProposalCreateActuatorTest.java | 3 +- .../actuator/ProposalDeleteActuatorTest.java | 3 +- .../actuator/SetAccountIdActuatorTest.java | 3 +- .../ShieldedTransferActuatorTest.java | 3 +- .../core/actuator/TransferActuatorTest.java | 3 +- .../actuator/TransferAssetActuatorTest.java | 3 +- .../UnDelegateResourceActuatorTest.java | 3 +- .../actuator/UnfreezeAssetActuatorTest.java | 3 +- .../actuator/UnfreezeBalanceActuatorTest.java | 3 +- .../UnfreezeBalanceV2ActuatorTest.java | 3 +- .../actuator/UpdateAccountActuatorTest.java | 3 +- .../actuator/UpdateAssetActuatorTest.java | 3 +- .../actuator/UpdateBrokerageActuatorTest.java | 3 +- ...UpdateEnergyLimitContractActuatorTest.java | 3 +- .../UpdateSettingContractActuatorTest.java | 3 +- .../actuator/VoteWitnessActuatorTest.java | 3 +- .../actuator/WithdrawBalanceActuatorTest.java | 3 +- .../WithdrawExpireUnfreezeActuatorTest.java | 3 +- .../actuator/WitnessCreateActuatorTest.java | 3 +- .../actuator/WitnessUpdateActuatorTest.java | 3 +- .../core/actuator/utils/ProposalUtilTest.java | 3 +- .../actuator/utils/TransactionUtilTest.java | 3 +- .../actuator/vm/ProgramTraceListenerTest.java | 14 ++++---- .../core/actuator/vm/ProgramTraceTest.java | 15 ++++---- .../tron/core/capsule/AccountCapsuleTest.java | 3 +- .../tron/core/capsule/BlockCapsuleTest.java | 14 ++++---- .../core/capsule/ExchangeCapsuleTest.java | 3 +- .../core/capsule/TransactionCapsuleTest.java | 3 +- .../tron/core/capsule/VotesCapsuleTest.java | 14 ++++---- .../core/capsule/utils/AssetUtilTest.java | 3 +- .../capsule/utils/ExchangeProcessorTest.java | 3 +- .../core/config/args/DynamicArgsTest.java | 12 ++++--- .../tron/core/db/AccountIdIndexStoreTest.java | 3 +- .../tron/core/db/AccountIndexStoreTest.java | 3 +- .../org/tron/core/db/AccountStoreTest.java | 3 +- .../db/BandwidthPriceHistoryLoaderTest.java | 18 +++++----- .../java/org/tron/core/db/BlockStoreTest.java | 3 +- .../core/db/EnergyPriceHistoryLoaderTest.java | 3 +- .../org/tron/core/db/KhaosDatabaseTest.java | 8 +---- .../java/org/tron/core/db/ManagerTest.java | 14 ++++---- .../db/MarketPairPriceToOrderStoreTest.java | 3 +- .../org/tron/core/db/NullifierStoreTest.java | 3 +- .../tron/core/db/TransactionExpireTest.java | 24 +++++-------- .../tron/core/db/TransactionHistoryTest.java | 3 +- .../tron/core/db/TransactionRetStoreTest.java | 4 +-- .../tron/core/db/TransactionStoreTest.java | 4 +-- .../tron/core/db/TransactionTraceTest.java | 3 +- .../java/org/tron/core/db/TxCacheDBTest.java | 3 +- .../java/org/tron/core/db/VotesStoreTest.java | 3 +- .../org/tron/core/db/WitnessStoreTest.java | 3 +- .../core/db/api/AssetUpdateHelperTest.java | 3 +- .../tron/core/db/backup/BackupDbUtilTest.java | 4 ++- .../java/org/tron/core/db2/ChainbaseTest.java | 18 +++++----- .../core/jsonrpc/BuildTransactionTest.java | 3 +- .../tron/core/jsonrpc/JsonrpcServiceTest.java | 3 +- .../core/jsonrpc/SectionBloomStoreTest.java | 3 +- .../tron/core/jsonrpc/WalletCursorTest.java | 3 +- .../core/metrics/MetricsApiServiceTest.java | 12 ++++--- .../prometheus/PrometheusApiServiceTest.java | 3 +- .../test/java/org/tron/core/net/BaseNet.java | 28 +++++++++------ .../messagehandler/BlockMsgHandlerTest.java | 3 +- .../messagehandler/MessageHandlerTest.java | 13 +++---- .../SyncBlockChainMsgHandlerTest.java | 12 +++---- .../core/net/services/AdvServiceTest.java | 17 +++++----- .../services/EffectiveCheckServiceTest.java | 16 +++++---- .../net/services/HandShakeServiceTest.java | 16 ++++----- .../core/net/services/RelayServiceTest.java | 3 +- .../core/net/services/SyncServiceTest.java | 12 +++---- .../java/org/tron/core/pbft/PbftApiTest.java | 3 +- .../core/services/ProposalServiceTest.java | 3 +- .../org/tron/core/services/WalletApiTest.java | 15 ++++---- .../filter/HttpApiAccessFilterTest.java | 3 +- .../LiteFnQueryGrpcInterceptorTest.java | 2 +- .../filter/LiteFnQueryHttpFilterTest.java | 3 +- .../filter/RpcApiAccessInterceptorTest.java | 2 +- .../http/GetAssetIssueListServletTest.java | 3 +- .../http/GetBandwidthPricesServletTest.java | 9 ++--- .../http/GetBrokerageServletTest.java | 3 +- .../http/GetEnergyPricesServletTest.java | 9 ++--- .../http/GetMemoFeePricesServletTest.java | 9 ++--- .../services/http/GetNowBlockServletTest.java | 3 +- .../services/http/GetRewardServletTest.java | 3 +- .../services/http/ListNodesServletTest.java | 3 +- .../http/ListProposalsServletTest.java | 3 +- .../http/TriggerSmartContractServletTest.java | 3 +- .../org/tron/core/services/http/UtilTest.java | 4 +-- .../GetBandwidthPricesOnPBFTServletTest.java | 9 ++--- .../GetEnergyPricesOnPBFTServletTest.java | 9 ++--- ...tBandwidthPricesOnSolidityServletTest.java | 9 ++--- .../GetEnergyPricesOnSolidityServletTest.java | 9 ++--- .../services/stop/BlockHeightStopTest.java | 6 ---- .../services/stop/BlockSyncCountStopTest.java | 6 ---- .../core/services/stop/BlockTimeStopTest.java | 6 ---- .../services/stop/ConditionallyStopTest.java | 11 ++++-- .../core/witness/ProposalControllerTest.java | 3 +- .../core/witness/WitnessControllerTest.java | 3 +- .../tron/core/zksnark/LibrustzcashTest.java | 3 +- .../core/zksnark/MerkleContainerTest.java | 3 +- .../org/tron/core/zksnark/MerkleTreeTest.java | 3 +- .../tron/core/zksnark/NoteEncDecryTest.java | 3 +- .../tron/core/zksnark/SendCoinShieldTest.java | 3 +- .../core/zksnark/ShieldedReceiveTest.java | 3 +- .../tron/program/AccountVoteWitnessTest.java | 3 +- .../org/tron/program/SolidityNodeTest.java | 34 ++++++++----------- .../java/org/tron/program/SupplementTest.java | 13 +++++-- 161 files changed, 413 insertions(+), 586 deletions(-) diff --git a/framework/src/test/java/org/tron/common/BaseTest.java b/framework/src/test/java/org/tron/common/BaseTest.java index 1dfbf702eff..c17d10d6ae4 100644 --- a/framework/src/test/java/org/tron/common/BaseTest.java +++ b/framework/src/test/java/org/tron/common/BaseTest.java @@ -1,18 +1,19 @@ package org.tron.common; import com.google.protobuf.ByteString; -import java.io.File; +import java.io.IOException; import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.ClassRule; +import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.tron.common.crypto.ECKey; import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.Sha256Hash; import org.tron.consensus.base.Param; import org.tron.core.ChainBaseManager; @@ -28,22 +29,27 @@ @DirtiesContext public abstract class BaseTest { - protected static String dbPath; + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); + @Resource protected Manager dbManager; @Resource protected ChainBaseManager chainBaseManager; + + public static String dbPath() { + try { + return temporaryFolder.newFolder().toString(); + } catch (IOException e) { + Assert.fail("create temp folder failed"); + } + return null; + } + @AfterClass public static void destroy() { Args.clearParam(); - if (StringUtils.isNotEmpty(dbPath)) { - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } } public Protocol.Block getSignedBlock(ByteString witness, long time, byte[] privateKey) { diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index 1c47599b61a..2e29b38824f 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -1,30 +1,32 @@ package org.tron.common.config.args; -import java.io.File; +import java.io.IOException; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.tron.common.parameter.RateLimiterInitialization; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.config.args.Args; public class ArgsTest { - private static final String dbPath = "output_arg_test"; + @Rule + public final TemporaryFolder temporaryFolder = new TemporaryFolder(); @Before - public void init() { - Args.setParam(new String[] {"--output-directory", dbPath, "--p2p-disable", "true", + public void init() throws IOException { + Args.setParam(new String[] {"--output-directory", + temporaryFolder.newFolder().toString(), "--p2p-disable", "true", "--debug"}, Constant.TEST_CONF); } @After public void destroy() { Args.clearParam(); - FileUtil.deleteDir(new File(dbPath)); } @Test diff --git a/framework/src/test/java/org/tron/common/runtime/InheritanceTest.java b/framework/src/test/java/org/tron/common/runtime/InheritanceTest.java index 4121407fe35..4b57bc880d7 100644 --- a/framework/src/test/java/org/tron/common/runtime/InheritanceTest.java +++ b/framework/src/test/java/org/tron/common/runtime/InheritanceTest.java @@ -25,8 +25,7 @@ public class InheritanceTest extends BaseTest { private static boolean init; static { - dbPath = "output_InheritanceTest"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; } diff --git a/framework/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java b/framework/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java index 923f2386605..172ef40afa7 100644 --- a/framework/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java +++ b/framework/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java @@ -27,8 +27,7 @@ public class InternalTransactionComplexTest extends BaseTest { private static boolean init; static { - dbPath = "output_InternalTransactionComplexTest"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug", "--support-constant"}, + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug", "--support-constant"}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; } diff --git a/framework/src/test/java/org/tron/common/runtime/ProgramResultTest.java b/framework/src/test/java/org/tron/common/runtime/ProgramResultTest.java index d083b2c729c..a2e53dd8711 100644 --- a/framework/src/test/java/org/tron/common/runtime/ProgramResultTest.java +++ b/framework/src/test/java/org/tron/common/runtime/ProgramResultTest.java @@ -44,8 +44,7 @@ public class ProgramResultTest extends BaseTest { private static boolean init; static { - dbPath = "output_InternalTransactionComplexTest"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug", "--support-constant"}, + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug", "--support-constant"}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; TRANSFER_TO = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; diff --git a/framework/src/test/java/org/tron/common/runtime/RuntimeImplTest.java b/framework/src/test/java/org/tron/common/runtime/RuntimeImplTest.java index 585a625668a..0b7721a325d 100644 --- a/framework/src/test/java/org/tron/common/runtime/RuntimeImplTest.java +++ b/framework/src/test/java/org/tron/common/runtime/RuntimeImplTest.java @@ -40,8 +40,7 @@ public class RuntimeImplTest extends BaseTest { private final long creatorTotalBalance = 3_000_000_000L; static { - dbPath = "output_RuntimeImplTest"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); callerAddress = Hex .decode(Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"); creatorAddress = Hex diff --git a/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java b/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java index 366c631ea6e..c9d61db9270 100644 --- a/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java +++ b/framework/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java @@ -32,8 +32,7 @@ public class RuntimeTransferComplexTest extends BaseTest { private static boolean init; static { - dbPath = "output_RuntimeTransferComplexTest"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; TRANSFER_TO = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java index a0c87da01c6..afac8cd7d22 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java @@ -67,10 +67,9 @@ public class BandWidthRuntimeOutOfTimeTest extends BaseTest { private static boolean init; static { - dbPath = "output_bandwidth_runtime_out_of_time_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory, "-w", diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java index 37167988f34..7203388f815 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java @@ -68,10 +68,9 @@ public class BandWidthRuntimeOutOfTimeWithCheckTest extends BaseTest { private static boolean init; static { - dbPath = "output_bandwidth_runtime_out_of_time_with_check_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory, "-w", diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java index 20e8e11535a..40c5908c2dd 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java @@ -59,10 +59,9 @@ public class BandWidthRuntimeTest extends BaseTest { @BeforeClass public static void init() { - dbPath = "output_bandwidth_runtime_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory, "-w" diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java index 0e7f79eb42f..e359e7eab1a 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java @@ -70,10 +70,9 @@ public class BandWidthRuntimeWithCheckTest extends BaseTest { private static boolean init; static { - dbPath = "output_bandwidth_runtime_with_check_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory, "-w" diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java index a5c397e54c2..5ada5612fce 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java @@ -39,8 +39,7 @@ public class BatchSendTest extends BaseTest { private static final AccountCapsule ownerCapsule; static { - dbPath = "output_BatchSendTest"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; TRANSFER_TO = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/ChargeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/ChargeTest.java index 78d5fc9e330..c158b2e400f 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/ChargeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/ChargeTest.java @@ -27,8 +27,7 @@ public class ChargeTest extends BaseTest { private long totalBalance = 100_000_000_000_000L; static { - dbPath = "output_ChargeTest"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java index 20abd7467aa..8b985d4bb1d 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java @@ -32,8 +32,7 @@ public class EnergyWhenAssertStyleTest extends BaseTest { private long totalBalance = 30_000_000_000_000L; static { - dbPath = "output_EnergyWhenAssertStyleTest"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java index 125d5220f07..19231b225f1 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java @@ -28,8 +28,7 @@ public class EnergyWhenRequireStyleTest extends BaseTest { private long totalBalance = 30_000_000_000_000L; static { - dbPath = "output_EnergyWhenRequireStyleTest"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java index 4db1b6a2033..009b332324b 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java @@ -27,8 +27,7 @@ public class EnergyWhenSendAndTransferTest extends BaseTest { private long totalBalance = 30_000_000_000_000L; static { - dbPath = "output_EnergyWhenSendAndTransferTest"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java index 6e99d55b668..2559b43a020 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java @@ -29,8 +29,7 @@ public class EnergyWhenTimeoutStyleTest extends BaseTest { private long totalBalance = 30_000_000_000_000L; static { - dbPath = "output_CPUTimeTest"; - Args.setParam(new String[]{"--output-directory", dbPath}, + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java index 600000e6535..e1459637e19 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java @@ -7,7 +7,6 @@ import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import com.google.protobuf.ByteString; -import java.io.File; import java.util.Arrays; import java.util.function.Consumer; import lombok.extern.slf4j.Slf4j; @@ -15,7 +14,9 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.RuntimeImpl; @@ -23,7 +24,6 @@ import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.Commons; import org.tron.common.utils.FastByteComparisons; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.common.utils.WalletUtil; import org.tron.common.utils.client.utils.AbiUtil; @@ -121,7 +121,8 @@ public class FreezeTest { private static final String userCStr = "27juXSbMvL6pb8VgmKRgW6ByCfw5RqZjUuo"; private static final byte[] userC = Commons.decode58Check(userCStr); - private static String dbPath; + @Rule + public final TemporaryFolder temporaryFolder = new TemporaryFolder(); private static TronApplicationContext context; private static Manager manager; private static byte[] owner; @@ -129,8 +130,8 @@ public class FreezeTest { @Before public void init() throws Exception { - dbPath = "output_" + FreezeTest.class.getName(); - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", + temporaryFolder.newFolder().toString(), "--debug"}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); manager = context.getBean(Manager.class); owner = Hex.decode(Wallet.getAddressPreFixString() @@ -1042,10 +1043,5 @@ public void destroy() { VMConfig.initVmHardFork(false); Args.clearParam(); context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.error("Release resources failure."); - } } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java index 59df7021249..9558c701109 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -9,7 +9,6 @@ import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import com.google.protobuf.ByteString; -import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -19,7 +18,9 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.RuntimeImpl; @@ -27,7 +28,6 @@ import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.Commons; import org.tron.common.utils.FastByteComparisons; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.common.utils.WalletUtil; import org.tron.common.utils.client.utils.AbiUtil; @@ -156,7 +156,8 @@ public class FreezeV2Test { private static final String userCStr = "27juXSbMvL6pb8VgmKRgW6ByCfw5RqZjUuo"; private static final byte[] userC = Commons.decode58Check(userCStr); - private static String dbPath; + @Rule + public final TemporaryFolder temporaryFolder = new TemporaryFolder(); private static TronApplicationContext context; private static Manager manager; private static byte[] owner; @@ -164,8 +165,8 @@ public class FreezeV2Test { @Before public void init() throws Exception { - dbPath = "output_" + FreezeV2Test.class.getName(); - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", + temporaryFolder.newFolder().toString(), "--debug"}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); manager = context.getBean(Manager.class); owner = Hex.decode(Wallet.getAddressPreFixString() @@ -1044,10 +1045,5 @@ public void destroy() { VMConfig.initVmHardFork(false); Args.clearParam(); context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.error("Release resources failure."); - } } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/InternalTransactionCallTest.java b/framework/src/test/java/org/tron/common/runtime/vm/InternalTransactionCallTest.java index 7f7bfd69ca4..75a8f32186c 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/InternalTransactionCallTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/InternalTransactionCallTest.java @@ -1,18 +1,19 @@ package org.tron.common.runtime.vm; -import java.io.File; +import java.io.IOException; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.TvmTestUtils; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.config.DefaultConfig; @@ -33,7 +34,8 @@ public class InternalTransactionCallTest { private Manager dbManager; private TronApplicationContext context; private RepositoryImpl repository; - private String dbPath = "output_InternalTransactionCallTest"; + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); private String OWNER_ADDRESS; private Application AppT; @@ -41,9 +43,10 @@ public class InternalTransactionCallTest { * Init data. */ @Before - public void init() { + public void init() throws IOException { Args.clearParam(); - Args.setParam(new String[]{"--output-directory", dbPath, "--support-constant", "--debug"}, + Args.setParam(new String[]{"--output-directory", + temporaryFolder.newFolder().toString(), "--support-constant", "--debug"}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); @@ -356,11 +359,5 @@ public byte[] deployBContractAndGetItsAddress() public void destroy() { context.destroy(); Args.clearParam(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.warn("Release resources failure."); - } - } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java index 965c7e0ce1a..be031d7c00b 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java @@ -2,7 +2,6 @@ import static org.junit.Assert.assertEquals; -import java.io.File; import java.util.List; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -16,7 +15,6 @@ import org.tron.common.BaseTest; import org.tron.common.parameter.CommonParameter; import org.tron.common.runtime.InternalTransaction; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.config.args.Args; import org.tron.core.exception.ContractValidateException; @@ -42,8 +40,7 @@ public class OperationsTest extends BaseTest { @BeforeClass public static void init() { - dbPath = "output_operations_test"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); CommonParameter.getInstance().setDebug(true); VMConfig.initAllowTvmTransferTrc10(1); VMConfig.initAllowTvmConstantinople(1); @@ -58,7 +55,6 @@ public static void destroy() { ConfigLoader.disable = false; VMConfig.initVmHardFork(false); Args.clearParam(); - FileUtil.deleteDir(new File(dbPath)); VMConfig.initAllowTvmTransferTrc10(0); VMConfig.initAllowTvmConstantinople(0); VMConfig.initAllowTvmSolidity059(0); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index b4365f02338..dce2cc7d105 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -106,8 +106,7 @@ public class PrecompiledContractsTest extends BaseTest { private static final long latestTimestamp = 1_000_000L; static { - dbPath = "output_PrecompiledContracts_test"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; WITNESS_ADDRESS = Wallet.getAddressPreFixString() + WITNESS_ADDRESS_BASE; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java index 08ce6be57a0..833ed6b0ac3 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java @@ -58,8 +58,7 @@ public class PrecompiledContractsVerifyProofTest extends BaseTest { @BeforeClass public static void init() { - dbPath = "output_PrecompiledContracts_VerifyProof_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, "config-test.conf"); + Args.setParam(new String[]{"--output-directory", dbPath()}, "config-test.conf"); DEFAULT_OVK = ByteArray .fromHexString("030c8c2bc59fb3eb8afb047a8ea4b028743d23e7d38c6fa30908358431e2314d"); SHIELDED_CONTRACT_ADDRESS = WalletClient.decodeFromBase58Check(SHIELDED_CONTRACT_ADDRESS_STR); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/RepositoryTest.java b/framework/src/test/java/org/tron/common/runtime/vm/RepositoryTest.java index 1e92c67a834..5c38ed90a3c 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/RepositoryTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/RepositoryTest.java @@ -34,8 +34,7 @@ public class RepositoryTest extends BaseTest { private Repository rootRepository; static { - dbPath = "output_DepostitTest"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java b/framework/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java index cc79d5f7ad6..8104a689cfa 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java @@ -29,8 +29,7 @@ public class TimeBenchmarkTest extends BaseTest { private long totalBalance = 30_000_000_000_000L; static { - dbPath = "output_TimeBenchmarkTest"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java b/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java index 13f01847c81..ede47555f3f 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/TransferToAccountTest.java @@ -54,8 +54,7 @@ public class TransferToAccountTest extends BaseTest { private static AccountCapsule ownerCapsule; static { - dbPath = "output_TransferToAccountTest"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; TRANSFER_TO = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java b/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java index 87ff59a785b..0509cad1dc7 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java @@ -44,8 +44,7 @@ public class TransferTokenTest extends BaseTest { static { - dbPath = "output_TransferTokenTest"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; TRANSFER_TO = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/VMContractTestBase.java b/framework/src/test/java/org/tron/common/runtime/vm/VMContractTestBase.java index 777166a0bc0..ee49bdca7f6 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/VMContractTestBase.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/VMContractTestBase.java @@ -1,13 +1,14 @@ package org.tron.common.runtime.vm; -import java.io.File; +import java.io.IOException; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.junit.After; import org.junit.Before; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.Runtime; -import org.tron.common.utils.FileUtil; import org.tron.consensus.dpos.DposSlot; import org.tron.consensus.dpos.MaintenanceManager; import org.tron.core.ChainBaseManager; @@ -26,8 +27,8 @@ @Slf4j public class VMContractTestBase { - - protected String dbPath; + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); protected Runtime runtime; protected Manager manager; protected Repository rootRepository; @@ -50,9 +51,9 @@ public class VMContractTestBase { } @Before - public void init() { - dbPath = "output_" + this.getClass().getName(); - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + public void init() throws IOException { + Args.setParam(new String[]{"--output-directory", + temporaryFolder.newFolder().toString(), "--debug"}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); // TRdmP9bYvML7dGUX9Rbw2kZrE2TayPZmZX - 41abd4b9367799eaa3197fecb144eb71de1e049abc @@ -77,10 +78,5 @@ public void init() { public void destroy() { Args.clearParam(); context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.error("Release resources failure."); - } } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/VMTestBase.java b/framework/src/test/java/org/tron/common/runtime/vm/VMTestBase.java index 1ceee84d634..18209543f62 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/VMTestBase.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/VMTestBase.java @@ -1,13 +1,15 @@ package org.tron.common.runtime.vm; -import java.io.File; +import java.io.IOException; + import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.junit.After; import org.junit.Before; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.Runtime; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.config.DefaultConfig; @@ -23,15 +25,17 @@ public class VMTestBase { protected Manager manager; protected TronApplicationContext context; - protected String dbPath; protected Repository rootRepository; protected String OWNER_ADDRESS; protected Runtime runtime; + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + @Before - public void init() { - dbPath = "output_" + this.getClass().getName(); - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + public void init() throws IOException { + Args.setParam(new String[]{"--output-directory", + temporaryFolder.newFolder().toString(), "--debug"}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; manager = context.getBean(Manager.class); @@ -45,11 +49,6 @@ public void init() { public void destroy() { Args.clearParam(); context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.error("Release resources failure."); - } } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java b/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java index 765a80f3d5f..a688f5f9a29 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java @@ -37,8 +37,7 @@ public class ValidateMultiSignContractTest extends BaseTest { private static final byte[] longData; static { - dbPath = "output_ValidateMultiSignContract_test"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); longData = new byte[1000000]; Arrays.fill(longData, (byte) 2); } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java b/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java index 22a33993589..1d85e9a7eab 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java @@ -19,7 +19,9 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; import org.tron.common.parameter.CommonParameter; import org.tron.common.runtime.Runtime; @@ -264,7 +266,8 @@ private static Consumer getSmallerConsumer(long expected) { return getConsumer("<", expected); } - private static String dbPath; + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); private static TronApplicationContext context; private static Manager manager; private static MaintenanceManager maintenanceManager; @@ -275,8 +278,8 @@ private static Consumer getSmallerConsumer(long expected) { @Before public void init() throws Exception { - dbPath = "output_" + VoteTest.class.getName(); - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", + temporaryFolder.newFolder().toString(), "--debug"}, Constant.TEST_CONF); CommonParameter.getInstance().setCheckFrozenTime(0); context = new TronApplicationContext(DefaultConfig.class); manager = context.getBean(Manager.class); @@ -310,11 +313,6 @@ public void destroy() { VMConfig.initVmHardFork(false); Args.clearParam(); context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.error("Release resources failure."); - } } private byte[] deployContract(String contractName, String abi, String code) throws Exception { diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java index b4ac2b4aebf..c774d10c172 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java @@ -26,6 +26,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import java.io.File; +import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -37,9 +38,11 @@ import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.ExpectedSystemExit; +import org.junit.rules.TemporaryFolder; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; import org.tron.common.utils.PublicMethod; @@ -50,7 +53,8 @@ @Slf4j public class LevelDbDataSourceImplTest { - private static final String dbPath = "output-levelDb-test"; + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); private static LevelDbDataSourceImpl dataSourceTest; private byte[] value1 = "10000".getBytes(); @@ -76,17 +80,14 @@ public class LevelDbDataSourceImplTest { @AfterClass public static void destroy() { Args.clearParam(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } @Before - public void initDb() { - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); - dataSourceTest = new LevelDbDataSourceImpl(dbPath + File.separator, "test_levelDb"); + public void initDb() throws IOException { + Args.setParam(new String[]{"--output-directory", + temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + dataSourceTest = new LevelDbDataSourceImpl( + Args.getInstance().getOutputDirectory() + File.separator, "test_levelDb"); } @Test diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java index 62630014b23..51a5ddc96ee 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java @@ -8,6 +8,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import java.io.File; +import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -18,11 +19,12 @@ import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; import org.junit.Assert; -import org.junit.Before; import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.ExpectedSystemExit; +import org.junit.rules.TemporaryFolder; import org.tron.common.storage.rocksdb.RocksDbDataSourceImpl; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; @@ -34,7 +36,8 @@ @Slf4j public class RocksDbDataSourceImplTest { - private static final String dbPath = "output-Rocks-test"; + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); private static RocksDbDataSourceImpl dataSourceTest; private byte[] value1 = "10000".getBytes(); @@ -58,25 +61,15 @@ public class RocksDbDataSourceImplTest { */ @AfterClass public static void destroy() { - String directory = Args.getInstance().getStorage().getDbDirectory(); Args.clearParam(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - - if (FileUtil.deleteDir(new File(dbPath + directory))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } @BeforeClass - public static void initDb() { - Args.setParam(new String[]{"--output-directory", dbPath}, "config-test-dbbackup.conf"); - dataSourceTest = new RocksDbDataSourceImpl(dbPath + File.separator, "test_rocksDb"); + public static void initDb() throws IOException { + Args.setParam(new String[]{"--output-directory", + temporaryFolder.newFolder().toString()}, "config-test-dbbackup.conf"); + dataSourceTest = new RocksDbDataSourceImpl( + Args.getInstance().getOutputDirectory() + File.separator, "test_rocksDb"); } @Test diff --git a/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java b/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java index 69501c4e393..300c202e11a 100755 --- a/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java +++ b/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java @@ -47,8 +47,7 @@ public class BandwidthProcessorTest extends BaseTest { static { - dbPath = "output_bandwidth_processor_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); ASSET_NAME = "test_token"; ASSET_NAME_V2 = "2"; OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; diff --git a/framework/src/test/java/org/tron/core/EnergyProcessorTest.java b/framework/src/test/java/org/tron/core/EnergyProcessorTest.java index da0493e2026..1e9064cb998 100755 --- a/framework/src/test/java/org/tron/core/EnergyProcessorTest.java +++ b/framework/src/test/java/org/tron/core/EnergyProcessorTest.java @@ -24,8 +24,7 @@ public class EnergyProcessorTest extends BaseTest { private static final String USER_ADDRESS; static { - dbPath = "energy_processor_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); ASSET_NAME = "test_token"; CONTRACT_PROVIDER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; diff --git a/framework/src/test/java/org/tron/core/ForkControllerTest.java b/framework/src/test/java/org/tron/core/ForkControllerTest.java index 20a28f9b619..74e651b3c1d 100644 --- a/framework/src/test/java/org/tron/core/ForkControllerTest.java +++ b/framework/src/test/java/org/tron/core/ForkControllerTest.java @@ -1,16 +1,16 @@ package org.tron.core; import com.google.protobuf.ByteString; -import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.List; - import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.ForkController; import org.tron.core.capsule.BlockCapsule; import org.tron.core.config.DefaultConfig; @@ -24,12 +24,14 @@ public class ForkControllerTest { private static DynamicPropertiesStore dynamicPropertiesStore; private static final ForkController forkController = ForkController.instance(); private static TronApplicationContext context; - private static final String dbPath = "output_fork_test"; + @Rule + public final TemporaryFolder temporaryFolder = new TemporaryFolder(); private static long ENERGY_LIMIT_BLOCK_NUM = 4727890L; @Before - public void init() { - Args.setParam(new String[]{"-d", dbPath, "-w"}, Constant.TEST_CONF); + public void init() throws IOException { + Args.setParam(new String[]{"-d", + temporaryFolder.newFolder().toString(), "-w"}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); dynamicPropertiesStore = context.getBean(DynamicPropertiesStore.class); chainBaseManager = context.getBean(ChainBaseManager.class); @@ -255,7 +257,6 @@ private byte[] getBytes(int i) { public void removeDb() { Args.clearParam(); context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } } diff --git a/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java b/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java index db62b04e6b0..ff30537ee7a 100644 --- a/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java +++ b/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java @@ -64,8 +64,7 @@ public class ShieldedTRC20BuilderTest extends BaseTest { private static final byte[] PUBLIC_TO_ADDRESS; static { - dbPath = "output_Shielded_TRC20_Api_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, "config-test-mainnet.conf"); + Args.setParam(new String[]{"--output-directory", dbPath()}, "config-test-mainnet.conf"); SHIELDED_CONTRACT_ADDRESS = WalletClient.decodeFromBase58Check(SHIELDED_CONTRACT_ADDRESS_STR); DEFAULT_OVK = ByteArray .fromHexString("030c8c2bc59fb3eb8afb047a8ea4b028743d23e7d38c6fa30908358431e2314d"); diff --git a/framework/src/test/java/org/tron/core/StorageMarketTest.java b/framework/src/test/java/org/tron/core/StorageMarketTest.java index 1c471032861..8b6e90e1c67 100644 --- a/framework/src/test/java/org/tron/core/StorageMarketTest.java +++ b/framework/src/test/java/org/tron/core/StorageMarketTest.java @@ -24,8 +24,7 @@ public class StorageMarketTest extends BaseTest { private static StorageMarket storageMarket; static { - dbPath = "output_storage_market_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; } diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 712a708f822..7461ff44c08 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -137,8 +137,7 @@ public class WalletTest extends BaseTest { private static boolean init; static { - dbPath = "output_wallet_test"; - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; } diff --git a/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java index d46545c5e16..69bac08c3e6 100644 --- a/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java @@ -52,8 +52,7 @@ public class AccountPermissionUpdateActuatorTest extends BaseTest { private static final String KEY_ADDRESS_INVALID = "bbbb"; static { - dbPath = "output_account_permission_update_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; WITNESS_ADDRESS = Wallet.getAddressPreFixString() + "8CFC572CC20CA18B636BDD93B4FB15EA84CC2B4E"; KEY_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; diff --git a/framework/src/test/java/org/tron/core/actuator/ActuatorConstantTest.java b/framework/src/test/java/org/tron/core/actuator/ActuatorConstantTest.java index 3ad6aa1d6dd..b8c2bd4fef9 100644 --- a/framework/src/test/java/org/tron/core/actuator/ActuatorConstantTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ActuatorConstantTest.java @@ -17,8 +17,7 @@ public class ActuatorConstantTest extends BaseTest { */ @BeforeClass public static void init() { - dbPath = "output_actuatorConstant_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); } @Test diff --git a/framework/src/test/java/org/tron/core/actuator/AssetIssueActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/AssetIssueActuatorTest.java index 58e3ae8ed29..77c24c28797 100755 --- a/framework/src/test/java/org/tron/core/actuator/AssetIssueActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/AssetIssueActuatorTest.java @@ -47,8 +47,7 @@ public class AssetIssueActuatorTest extends BaseTest { private static long endTime = 0; static { - dbPath = "output_assetIssue_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; OWNER_ADDRESS_SECOND = Wallet .getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; diff --git a/framework/src/test/java/org/tron/core/actuator/CancelAllUnfreezeV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/CancelAllUnfreezeV2ActuatorTest.java index fcc545a0fc2..fc2dad88420 100644 --- a/framework/src/test/java/org/tron/core/actuator/CancelAllUnfreezeV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/CancelAllUnfreezeV2ActuatorTest.java @@ -35,8 +35,7 @@ public class CancelAllUnfreezeV2ActuatorTest extends BaseTest { private static final long initBalance = 10_000_000_000L; static { - dbPath = "output_cancel_all_unfreeze_v2_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; OWNER_ACCOUNT_INVALID = diff --git a/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java index 1f6571e8868..3a23151f6bc 100644 --- a/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java @@ -43,8 +43,7 @@ public class ClearABIContractActuatorTest extends BaseTest { private static final ABI TARGET_ABI = ABI.getDefaultInstance(); static { - dbPath = "output_clearabicontract_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_NOTEXIST = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; diff --git a/framework/src/test/java/org/tron/core/actuator/CreateAccountActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/CreateAccountActuatorTest.java index d53b0332f64..f756f3dd087 100755 --- a/framework/src/test/java/org/tron/core/actuator/CreateAccountActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/CreateAccountActuatorTest.java @@ -32,8 +32,7 @@ public class CreateAccountActuatorTest extends BaseTest { private static final String INVALID_ACCOUNT_ADDRESS; static { - dbPath = "output_CreateAccount_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = diff --git a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java index b2ecae06177..95577f46e50 100644 --- a/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/DelegateResourceActuatorTest.java @@ -49,8 +49,7 @@ public class DelegateResourceActuatorTest extends BaseTest { private static final long initBalance = 1000_000_000_000L; static { - dbPath = "output_delegate_resource_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; OWNER_ACCOUNT_INVALID = diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java index f8e4a27bda1..807d0e1be02 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java @@ -40,8 +40,7 @@ public class ExchangeCreateActuatorTest extends BaseTest { private static final String OWNER_ADDRESS_NOACCOUNT; static { - dbPath = "output_ExchangeCreate_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java index 553108d5490..6268c226c7e 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java @@ -41,8 +41,7 @@ public class ExchangeInjectActuatorTest extends BaseTest { private static final String OWNER_ADDRESS_NOACCOUNT; static { - dbPath = "output_ExchangeInject_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java index 5d728a61ff5..02107427cad 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java @@ -42,8 +42,7 @@ public class ExchangeTransactionActuatorTest extends BaseTest { private static final String OWNER_ADDRESS_NOACCOUNT; static { - dbPath = "output_ExchangeTransaction_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java index 85ea81ed932..6844925288e 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java @@ -42,8 +42,7 @@ public class ExchangeWithdrawActuatorTest extends BaseTest { private static final String OWNER_ADDRESS_NOACCOUNT; static { - dbPath = "output_ExchangeWithdraw_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = diff --git a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java index c66a86fe58c..18eef50c36f 100644 --- a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java @@ -41,8 +41,7 @@ public class FreezeBalanceActuatorTest extends BaseTest { private static final long initBalance = 10_000_000_000L; static { - dbPath = "output_freeze_balance_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; OWNER_ACCOUNT_INVALID = diff --git a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java index 1e6039c3e69..86b0e3143ab 100644 --- a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceV2ActuatorTest.java @@ -36,8 +36,7 @@ public class FreezeBalanceV2ActuatorTest extends BaseTest { private static final long initBalance = 10_000_000_000L; static { - dbPath = "output_freeze_balance_v2_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; OWNER_ACCOUNT_INVALID = diff --git a/framework/src/test/java/org/tron/core/actuator/MarketCancelOrderActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/MarketCancelOrderActuatorTest.java index 51b20ceab02..b5c3427f529 100644 --- a/framework/src/test/java/org/tron/core/actuator/MarketCancelOrderActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/MarketCancelOrderActuatorTest.java @@ -51,8 +51,7 @@ public class MarketCancelOrderActuatorTest extends BaseTest { private static final String TRX = "_"; static { - dbPath = "output_MarketCancelOrder_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = diff --git a/framework/src/test/java/org/tron/core/actuator/MarketSellAssetActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/MarketSellAssetActuatorTest.java index a2a7cea259e..0e938cdb025 100644 --- a/framework/src/test/java/org/tron/core/actuator/MarketSellAssetActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/MarketSellAssetActuatorTest.java @@ -53,8 +53,7 @@ public class MarketSellAssetActuatorTest extends BaseTest { private static final String TRX = "_"; static { - dbPath = "output_MarketSellAsset_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = diff --git a/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java index 0bcfbc8820f..52e5f554374 100755 --- a/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java @@ -41,8 +41,7 @@ public class ParticipateAssetIssueActuatorTest extends BaseTest { private static long AMOUNT = TOTAL_SUPPLY - (1000L) / TRX_NUM * NUM; static { - dbPath = "output_participateAsset_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1234"; TO_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; TO_ADDRESS_2 = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e048892"; diff --git a/framework/src/test/java/org/tron/core/actuator/ProposalApproveActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ProposalApproveActuatorTest.java index 484c6666941..2e8e78306a9 100644 --- a/framework/src/test/java/org/tron/core/actuator/ProposalApproveActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ProposalApproveActuatorTest.java @@ -40,8 +40,7 @@ public class ProposalApproveActuatorTest extends BaseTest { private static final String OWNER_ADDRESS_NOACCOUNT; static { - dbPath = "output_ProposalApprove_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = diff --git a/framework/src/test/java/org/tron/core/actuator/ProposalCreateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ProposalCreateActuatorTest.java index 1e95911884c..a42a4ffbe5a 100644 --- a/framework/src/test/java/org/tron/core/actuator/ProposalCreateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ProposalCreateActuatorTest.java @@ -38,8 +38,7 @@ public class ProposalCreateActuatorTest extends BaseTest { private static final String OWNER_ADDRESS_NOACCOUNT; static { - dbPath = "output_ProposalCreate_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = diff --git a/framework/src/test/java/org/tron/core/actuator/ProposalDeleteActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ProposalDeleteActuatorTest.java index 63e5758a907..dfd34cb620e 100644 --- a/framework/src/test/java/org/tron/core/actuator/ProposalDeleteActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ProposalDeleteActuatorTest.java @@ -40,8 +40,7 @@ public class ProposalDeleteActuatorTest extends BaseTest { private static final String OWNER_ADDRESS_NOACCOUNT; static { - dbPath = "output_ProposalDelete_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = diff --git a/framework/src/test/java/org/tron/core/actuator/SetAccountIdActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/SetAccountIdActuatorTest.java index 0b4311ca46f..e93d9ecf333 100644 --- a/framework/src/test/java/org/tron/core/actuator/SetAccountIdActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/SetAccountIdActuatorTest.java @@ -30,8 +30,7 @@ public class SetAccountIdActuatorTest extends BaseTest { private static final String OWNER_ADDRESS_INVALID = "aaaa"; static { - dbPath = "output_setaccountid_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; OWNER_ADDRESS_1 = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; } diff --git a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java index f84610cc551..b71ba432018 100755 --- a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java @@ -68,8 +68,7 @@ public class ShieldedTransferActuatorTest extends BaseTest { private Wallet wallet; static { - dbPath = "output_shield_transfer_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); ADDRESS_ONE_PRIVATE_KEY = PublicMethod.getRandomPrivateKey(); PUBLIC_ADDRESS_ONE = PublicMethod.getHexAddressByPrivateKey(ADDRESS_ONE_PRIVATE_KEY); diff --git a/framework/src/test/java/org/tron/core/actuator/TransferActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/TransferActuatorTest.java index 05aea41e7c7..12df9031ca8 100644 --- a/framework/src/test/java/org/tron/core/actuator/TransferActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/TransferActuatorTest.java @@ -46,8 +46,7 @@ public class TransferActuatorTest extends BaseTest { private static final String To_ACCOUNT_INVALID; static { - dbPath = "output_transfer_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; TO_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ACCOUNT_INVALID = diff --git a/framework/src/test/java/org/tron/core/actuator/TransferAssetActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/TransferAssetActuatorTest.java index 07bb8415068..8c936f16dc5 100755 --- a/framework/src/test/java/org/tron/core/actuator/TransferAssetActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/TransferAssetActuatorTest.java @@ -72,8 +72,7 @@ public class TransferAssetActuatorTest extends BaseTest { private static final String URL = "https://tron.network/"; static { - dbPath = "output_transferasset_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; TO_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a146a"; NOT_EXIT_ADDRESS = Wallet.getAddressPreFixString() + "B56446E617E924805E4D6CA021D341FEF6E2013B"; diff --git a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java index 82ed6865fb8..eea1a0bf9b7 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnDelegateResourceActuatorTest.java @@ -38,8 +38,7 @@ public class UnDelegateResourceActuatorTest extends BaseTest { private static final long delegateBalance = 1_000_000_000L; static { - dbPath = "output_unDelegate_resource_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; OWNER_ACCOUNT_INVALID = diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeAssetActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeAssetActuatorTest.java index 0a624faf113..7471e9ba20f 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeAssetActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeAssetActuatorTest.java @@ -36,8 +36,7 @@ public class UnfreezeAssetActuatorTest extends BaseTest { private static final String assetName = "testCoin"; static { - dbPath = "output_unfreeze_asset_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; OWNER_ACCOUNT_INVALID = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java index 77e70f6762e..e9f1d934e5a 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java @@ -40,8 +40,7 @@ public class UnfreezeBalanceActuatorTest extends BaseTest { private static final long frozenBalance = 1_000_000_000L; static { - dbPath = "output_unfreeze_balance_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; OWNER_ACCOUNT_INVALID = diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java index db2a78b1623..749052736e5 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java @@ -38,8 +38,7 @@ public class UnfreezeBalanceV2ActuatorTest extends BaseTest { private static final long frozenBalance = 1_000_000_000L; static { - dbPath = "output_unfreeze_balance_v2_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; OWNER_ACCOUNT_INVALID = diff --git a/framework/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java index acbb9fb4d0b..0e385347836 100755 --- a/framework/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java @@ -32,8 +32,7 @@ public class UpdateAccountActuatorTest extends BaseTest { private static final String OWNER_ADDRESS_INVALID = "aaaa"; static { - dbPath = "output_updateaccount_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; OWNER_ADDRESS_1 = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; } diff --git a/framework/src/test/java/org/tron/core/actuator/UpdateAssetActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UpdateAssetActuatorTest.java index b7583bc335b..3bdba2055af 100644 --- a/framework/src/test/java/org/tron/core/actuator/UpdateAssetActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UpdateAssetActuatorTest.java @@ -39,8 +39,7 @@ public class UpdateAssetActuatorTest extends BaseTest { private static final String URL = "tron-my.com"; static { - dbPath = "output_updateAsset_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_NOTEXIST = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; diff --git a/framework/src/test/java/org/tron/core/actuator/UpdateBrokerageActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UpdateBrokerageActuatorTest.java index 034415e0ef1..efd090b4b3a 100644 --- a/framework/src/test/java/org/tron/core/actuator/UpdateBrokerageActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UpdateBrokerageActuatorTest.java @@ -34,8 +34,7 @@ public class UpdateBrokerageActuatorTest extends BaseTest { private static final int BROKEN_AGE = 10; static { - dbPath = "output_updatebrokerageactuator_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_NOTEXIST = Wallet.getAddressPreFixString() + "1234b9367799eaa3197fecb144eb71de1e049123"; diff --git a/framework/src/test/java/org/tron/core/actuator/UpdateEnergyLimitContractActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UpdateEnergyLimitContractActuatorTest.java index 3703dc74e87..60f52b541b9 100644 --- a/framework/src/test/java/org/tron/core/actuator/UpdateEnergyLimitContractActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UpdateEnergyLimitContractActuatorTest.java @@ -47,8 +47,7 @@ public class UpdateEnergyLimitContractActuatorTest extends BaseTest { private static String OWNER_ADDRESS_NOTEXIST; static { - dbPath = "output_updateEnergyLimitContractActuator_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); } /** diff --git a/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java index 0445f893983..508cee731f0 100644 --- a/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java @@ -41,8 +41,7 @@ public class UpdateSettingContractActuatorTest extends BaseTest { private static final long INVALID_PERCENT = 200L; static { - dbPath = "output_updatesettingcontract_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_NOTEXIST = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; diff --git a/framework/src/test/java/org/tron/core/actuator/VoteWitnessActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/VoteWitnessActuatorTest.java index cedd147dbaa..1a152555931 100644 --- a/framework/src/test/java/org/tron/core/actuator/VoteWitnessActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/VoteWitnessActuatorTest.java @@ -51,8 +51,7 @@ public class VoteWitnessActuatorTest extends BaseTest { private static boolean consensusStart; static { - dbPath = "output_VoteWitness_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; WITNESS_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; WITNESS_ADDRESS_NOACCOUNT = diff --git a/framework/src/test/java/org/tron/core/actuator/WithdrawBalanceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/WithdrawBalanceActuatorTest.java index 7010b10657a..22a4acbb838 100644 --- a/framework/src/test/java/org/tron/core/actuator/WithdrawBalanceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/WithdrawBalanceActuatorTest.java @@ -36,8 +36,7 @@ public class WithdrawBalanceActuatorTest extends BaseTest { private static final long allowance = 32_000_000L; static { - dbPath = "output_withdraw_balance_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; OWNER_ACCOUNT_INVALID = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; diff --git a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java index 1544e546854..34ac0d9bbeb 100644 --- a/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/WithdrawExpireUnfreezeActuatorTest.java @@ -39,8 +39,7 @@ public class WithdrawExpireUnfreezeActuatorTest extends BaseTest { private static final long allowance = 32_000_000L; static { - dbPath = "output_withdraw_expire_unfreeze_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; OWNER_ACCOUNT_INVALID = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; diff --git a/framework/src/test/java/org/tron/core/actuator/WitnessCreateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/WitnessCreateActuatorTest.java index 721d88af2b6..0809ed2993e 100644 --- a/framework/src/test/java/org/tron/core/actuator/WitnessCreateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/WitnessCreateActuatorTest.java @@ -36,8 +36,7 @@ public class WitnessCreateActuatorTest extends BaseTest { private static final String OWNER_ADDRESS_BALANCENOTSUFFIENT; static { - dbPath = "output_WitnessCreate_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS_FIRST = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_SECOND = diff --git a/framework/src/test/java/org/tron/core/actuator/WitnessUpdateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/WitnessUpdateActuatorTest.java index 31ac6a3cf88..6ad6e381c5e 100644 --- a/framework/src/test/java/org/tron/core/actuator/WitnessUpdateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/WitnessUpdateActuatorTest.java @@ -36,8 +36,7 @@ public class WitnessUpdateActuatorTest extends BaseTest { private static final String OWNER_ADDRESS_INVALID = "aaaa"; static { - dbPath = "output_WitnessUpdate_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ADDRESS_NOTEXIST = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; diff --git a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java index 5de7771dfe2..6f4df3cba8f 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java @@ -32,8 +32,7 @@ public class ProposalUtilTest extends BaseTest { */ @BeforeClass public static void init() { - dbPath = "output_ProposalUtil_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); } @Test diff --git a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java index 7d737870e58..9d56876a4da 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java @@ -46,8 +46,7 @@ public class TransactionUtilTest extends BaseTest { */ @BeforeClass public static void init() { - dbPath = "output_transactionUtil_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; } diff --git a/framework/src/test/java/org/tron/core/actuator/vm/ProgramTraceListenerTest.java b/framework/src/test/java/org/tron/core/actuator/vm/ProgramTraceListenerTest.java index 7cd1b41f5a5..089711219f8 100644 --- a/framework/src/test/java/org/tron/core/actuator/vm/ProgramTraceListenerTest.java +++ b/framework/src/test/java/org/tron/core/actuator/vm/ProgramTraceListenerTest.java @@ -1,6 +1,6 @@ package org.tron.core.actuator.vm; -import java.io.File; +import java.io.IOException; import java.lang.reflect.Field; import java.util.List; import java.util.Map; @@ -8,9 +8,10 @@ import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.tron.common.runtime.vm.DataWord; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.config.args.Args; import org.tron.core.db.TransactionStoreTest; @@ -20,7 +21,8 @@ @Slf4j(topic = "VM") public class ProgramTraceListenerTest { - private static final String dbPath = "output_programTraceListener_test"; + @ClassRule + public static TemporaryFolder temporaryFolder = new TemporaryFolder(); private static final int WORD_SIZE = 32; private ProgramTraceListener traceListener; @@ -30,15 +32,15 @@ public class ProgramTraceListenerTest { private DataWord storageWordValue = new DataWord(3); @BeforeClass - public static void init() { - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + public static void init() throws IOException { + Args.setParam(new String[]{"--output-directory", + temporaryFolder.newFolder().toString(), "--debug"}, Constant.TEST_CONF); } @AfterClass public static void destroy() { Args.clearParam(); - FileUtil.deleteDir(new File(dbPath)); } private void invokeProgramTraceListener(ProgramTraceListener traceListener) { diff --git a/framework/src/test/java/org/tron/core/actuator/vm/ProgramTraceTest.java b/framework/src/test/java/org/tron/core/actuator/vm/ProgramTraceTest.java index c9c4966e208..46be28deed0 100644 --- a/framework/src/test/java/org/tron/core/actuator/vm/ProgramTraceTest.java +++ b/framework/src/test/java/org/tron/core/actuator/vm/ProgramTraceTest.java @@ -1,14 +1,15 @@ package org.tron.core.actuator.vm; -import java.io.File; +import java.io.IOException; import java.math.BigInteger; import java.util.List; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.tron.common.runtime.vm.DataWord; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.config.args.Args; import org.tron.core.vm.trace.Op; @@ -16,17 +17,19 @@ import org.tron.core.vm.trace.ProgramTrace; public class ProgramTraceTest { - private static final String dbPath = "output_programTrace_test"; + + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); @BeforeClass - public static void init() { - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + public static void init() throws IOException { + Args.setParam(new String[]{"--output-directory", + temporaryFolder.newFolder().toString(), "--debug"}, Constant.TEST_CONF); } @AfterClass public static void destroy() { Args.clearParam(); - FileUtil.deleteDir(new File(dbPath)); } @Test diff --git a/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java index 65aab3e9e7a..de72b4be276 100644 --- a/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java @@ -36,8 +36,7 @@ public class AccountCapsuleTest extends BaseTest { static AccountCapsule accountCapsule; static { - dbPath = "output_accountCapsule_test"; - Args.setParam(new String[]{"-d", dbPath, "-w"}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath(), "-w"}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "a06a17a49648a8ad32055c06f60fa14ae46df91234"; } diff --git a/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java index 88d67c3a632..0dd078dedb0 100644 --- a/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java @@ -1,16 +1,16 @@ package org.tron.core.capsule; import com.google.protobuf.ByteString; -import java.io.File; +import java.io.IOException; import java.util.Arrays; - import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.LocalWitnesses; import org.tron.common.utils.PublicMethod; import org.tron.common.utils.Sha256Hash; @@ -33,18 +33,18 @@ public class BlockCapsuleTest { .fromHexString("9938a342238077182498b464ac0292229938a342238077182498b464ac029222"))), 1234, ByteString.copyFrom("1234567".getBytes())); - private static String dbPath = "output_bloackcapsule_test"; + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); @BeforeClass - public static void init() { - Args.setParam(new String[]{"-d", dbPath}, + public static void init() throws IOException { + Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); } @AfterClass public static void removeDb() { Args.clearParam(); - FileUtil.deleteDir(new File(dbPath)); } @Test diff --git a/framework/src/test/java/org/tron/core/capsule/ExchangeCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/ExchangeCapsuleTest.java index 48479287eab..791767a952f 100644 --- a/framework/src/test/java/org/tron/core/capsule/ExchangeCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/ExchangeCapsuleTest.java @@ -15,8 +15,7 @@ public class ExchangeCapsuleTest extends BaseTest { static { - dbPath = "output_exchange_capsule_test_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); } /** diff --git a/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java index 28f7bf0e4f5..fcb2a4fbfd5 100644 --- a/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java @@ -46,8 +46,7 @@ public class TransactionCapsuleTest extends BaseTest { @BeforeClass public static void init() { - dbPath = "output_transactioncapsule_test"; - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "03702350064AD5C1A8AA6B4D74B051199CFF8EA7"; /*TO_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; OWNER_ACCOUNT_NOT_Exist = diff --git a/framework/src/test/java/org/tron/core/capsule/VotesCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/VotesCapsuleTest.java index d2e4483cdf0..64bb660ab9a 100644 --- a/framework/src/test/java/org/tron/core/capsule/VotesCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/VotesCapsuleTest.java @@ -1,15 +1,16 @@ package org.tron.core.capsule; import com.google.protobuf.ByteString; -import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Test; -import org.tron.common.utils.FileUtil; +import org.junit.rules.TemporaryFolder; import org.tron.common.utils.StringUtil; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -21,7 +22,8 @@ @Slf4j public class VotesCapsuleTest { - private static String dbPath = "output_votesCapsule_test"; + @ClassRule + public static TemporaryFolder temporaryFolder = new TemporaryFolder(); private static final String OWNER_ADDRESS; private static List oldVotes; @@ -31,15 +33,15 @@ public class VotesCapsuleTest { } @BeforeClass - public static void init() { - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); + public static void init() throws IOException { + Args.setParam(new String[]{"--output-directory", + temporaryFolder.newFolder().toString(), "--debug"}, Constant.TEST_CONF); } @AfterClass public static void destroy() { Args.clearParam(); - FileUtil.deleteDir(new File(dbPath)); } @Test diff --git a/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java b/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java index 8d56c1a5f21..2b07d7d7952 100644 --- a/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java +++ b/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java @@ -24,8 +24,7 @@ public class AssetUtilTest extends BaseTest { static { - dbPath = "output_AssetUtil_test"; - Args.setParam(new String[] {"-d", dbPath, "-w"}, Constant.TEST_CONF); + Args.setParam(new String[] {"-d", dbPath(), "-w"}, Constant.TEST_CONF); } public static byte[] randomBytes(int length) { diff --git a/framework/src/test/java/org/tron/core/capsule/utils/ExchangeProcessorTest.java b/framework/src/test/java/org/tron/core/capsule/utils/ExchangeProcessorTest.java index 3d30dabf031..3437eb0ea42 100644 --- a/framework/src/test/java/org/tron/core/capsule/utils/ExchangeProcessorTest.java +++ b/framework/src/test/java/org/tron/core/capsule/utils/ExchangeProcessorTest.java @@ -15,8 +15,7 @@ public class ExchangeProcessorTest extends BaseTest { private static ExchangeProcessor processor; static { - dbPath = "output_buy_exchange_processor_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); } /** diff --git a/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java index 2ca95239ad7..2a3af9c440e 100644 --- a/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java @@ -1,13 +1,15 @@ package org.tron.core.config.args; import java.io.File; +import java.io.IOException; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.ReflectUtils; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; @@ -17,11 +19,12 @@ public class DynamicArgsTest { protected TronApplicationContext context; private DynamicArgs dynamicArgs; - private String dbPath = "output-dynamic-config-test"; + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); @Before - public void init() { - Args.setParam(new String[]{"--output-directory", dbPath}, + public void init() throws IOException { + Args.setParam(new String[]{"--output-directory", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); dynamicArgs = context.getBean(DynamicArgs.class); @@ -32,7 +35,6 @@ public void init() { public void destroy() { Args.clearParam(); context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } @Test diff --git a/framework/src/test/java/org/tron/core/db/AccountIdIndexStoreTest.java b/framework/src/test/java/org/tron/core/db/AccountIdIndexStoreTest.java index fa31b2fd451..9033e90481c 100644 --- a/framework/src/test/java/org/tron/core/db/AccountIdIndexStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/AccountIdIndexStoreTest.java @@ -34,8 +34,7 @@ public class AccountIdIndexStoreTest extends BaseTest { private static AccountCapsule accountCapsule4; static { - dbPath = "output_AccountIndexStore_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); } diff --git a/framework/src/test/java/org/tron/core/db/AccountIndexStoreTest.java b/framework/src/test/java/org/tron/core/db/AccountIndexStoreTest.java index 0b449addc41..a4dc848b749 100755 --- a/framework/src/test/java/org/tron/core/db/AccountIndexStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/AccountIndexStoreTest.java @@ -23,10 +23,9 @@ public class AccountIndexStoreTest extends BaseTest { private static byte[] accountName = TransactionStoreTest.randomBytes(32); static { - dbPath = "output_AccountIndexStore_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory }, diff --git a/framework/src/test/java/org/tron/core/db/AccountStoreTest.java b/framework/src/test/java/org/tron/core/db/AccountStoreTest.java index f199b371f9d..9249a3358dc 100755 --- a/framework/src/test/java/org/tron/core/db/AccountStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/AccountStoreTest.java @@ -36,10 +36,9 @@ public class AccountStoreTest extends BaseTest { private static boolean init; static { - dbPath = "output_AccountStore_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory }, diff --git a/framework/src/test/java/org/tron/core/db/BandwidthPriceHistoryLoaderTest.java b/framework/src/test/java/org/tron/core/db/BandwidthPriceHistoryLoaderTest.java index 4c7af2b31fe..298b9f40235 100644 --- a/framework/src/test/java/org/tron/core/db/BandwidthPriceHistoryLoaderTest.java +++ b/framework/src/test/java/org/tron/core/db/BandwidthPriceHistoryLoaderTest.java @@ -11,16 +11,17 @@ import static org.tron.core.utils.ProposalUtil.ProposalType.TRANSACTION_FEE; import static org.tron.core.utils.ProposalUtil.ProposalType.WITNESS_127_PAY_PER_BLOCK; -import java.io.File; +import java.io.IOException; import java.util.HashMap; import java.util.Map; import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.ProposalCapsule; @@ -36,7 +37,8 @@ public class BandwidthPriceHistoryLoaderTest { private static ChainBaseManager chainBaseManager; private static TronApplicationContext context; - private static final String dbPath = "output-BandwidthPriceHistoryLoaderTest-test"; + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); private static long t1; private static long price1; private static long t2; @@ -47,8 +49,9 @@ public class BandwidthPriceHistoryLoaderTest { // Note, here use @Before and @After instead of @BeforeClass and @AfterClass, // because it needs to initialize DB before the single test every time @Before - public void init() { - Args.setParam(new String[] {"--output-directory", dbPath}, Constant.TEST_CONF); + public void init() throws IOException { + Args.setParam(new String[] {"--output-directory", + temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); chainBaseManager = context.getBean(ChainBaseManager.class); } @@ -57,11 +60,6 @@ public void init() { public void destroy() { Args.clearParam(); context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } public void initDB() { 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 cdf8dbcc29c..4f706a97dcf 100644 --- a/framework/src/test/java/org/tron/core/db/BlockStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/BlockStoreTest.java @@ -11,8 +11,7 @@ public class BlockStoreTest extends BaseTest { static { - dbPath = "output-blockStore-test"; - Args.setParam(new String[]{"--output-directory", dbPath}, + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); } diff --git a/framework/src/test/java/org/tron/core/db/EnergyPriceHistoryLoaderTest.java b/framework/src/test/java/org/tron/core/db/EnergyPriceHistoryLoaderTest.java index ca115bed2bd..995d9e01ecb 100644 --- a/framework/src/test/java/org/tron/core/db/EnergyPriceHistoryLoaderTest.java +++ b/framework/src/test/java/org/tron/core/db/EnergyPriceHistoryLoaderTest.java @@ -36,8 +36,7 @@ public class EnergyPriceHistoryLoaderTest extends BaseTest { private static long price5 = 140L; static { - dbPath = "output-EnergyPriceHistoryLoaderTest-test"; - Args.setParam(new String[] {"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[] {"--output-directory", dbPath()}, Constant.TEST_CONF); } public void initDB() { diff --git a/framework/src/test/java/org/tron/core/db/KhaosDatabaseTest.java b/framework/src/test/java/org/tron/core/db/KhaosDatabaseTest.java index de895abb4b4..72214c6743e 100644 --- a/framework/src/test/java/org/tron/core/db/KhaosDatabaseTest.java +++ b/framework/src/test/java/org/tron/core/db/KhaosDatabaseTest.java @@ -8,7 +8,6 @@ import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; -import org.junit.BeforeClass; import org.junit.Test; import org.tron.common.BaseTest; import org.tron.common.parameter.CommonParameter; @@ -32,14 +31,9 @@ public class KhaosDatabaseTest extends BaseTest { private KhaosDatabase khaosDatabase; static { - dbPath = "output-khaosDatabase-test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); } - @BeforeClass - public static void init() { - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - } @Test public void testStartBlock() { diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index 020805c93fa..e25faf536f7 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -9,7 +9,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.protobuf.ByteString; -import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -22,12 +22,13 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; import org.tron.common.crypto.ECKey; import org.tron.common.runtime.RuntimeImpl; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.JsonUtil; import org.tron.common.utils.LocalWitnesses; import org.tron.common.utils.PublicMethod; @@ -100,7 +101,8 @@ public class ManagerTest extends BlockGenerate { private static DposSlot dposSlot; private static TronApplicationContext context; private static BlockCapsule blockCapsule2; - private static String dbPath = "output_manager_test"; + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); private static AtomicInteger port = new AtomicInteger(0); private static String accountAddress = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; @@ -108,8 +110,9 @@ public class ManagerTest extends BlockGenerate { private LocalWitnesses localWitnesses; @Before - public void init() { - Args.setParam(new String[]{"-d", dbPath, "-w"}, Constant.TEST_CONF); + public void init() throws IOException { + Args.setParam(new String[]{"-d", + temporaryFolder.newFolder().toString(), "-w"}, Constant.TEST_CONF); Args.getInstance().setNodeListenPort(10000 + port.incrementAndGet()); context = new TronApplicationContext(DefaultConfig.class); @@ -157,7 +160,6 @@ public void init() { public void removeDb() { Args.clearParam(); context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } @Test diff --git a/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreTest.java b/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreTest.java index f90b5712c56..1f453cb9b41 100755 --- a/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreTest.java @@ -23,8 +23,7 @@ public class MarketPairPriceToOrderStoreTest extends BaseTest { static { - dbPath = "output-MarketPairPriceToOrderStore-test"; - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); } @After diff --git a/framework/src/test/java/org/tron/core/db/NullifierStoreTest.java b/framework/src/test/java/org/tron/core/db/NullifierStoreTest.java index 5ed2f967a15..96b2fc1a74d 100644 --- a/framework/src/test/java/org/tron/core/db/NullifierStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/NullifierStoreTest.java @@ -29,8 +29,7 @@ public class NullifierStoreTest extends BaseTest { private static BytesCapsule nullifier2New; static { - dbPath = "output_NullifierStore_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); } diff --git a/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java b/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java index f9b1a6c44e0..843e54d38a8 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java @@ -1,50 +1,47 @@ package org.tron.core.db; import com.google.protobuf.ByteString; -import java.io.File; -import java.lang.reflect.Array; +import java.io.IOException; import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.Return.response_code; import org.tron.common.application.TronApplicationContext; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.LocalWitnesses; import org.tron.common.utils.PublicMethod; import org.tron.common.utils.Sha256Hash; -import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.store.WitnessScheduleStore; -import org.tron.protos.Protocol; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.contract.BalanceContract.TransferContract; @Slf4j public class TransactionExpireTest { - private String dbPath = "output_expire_test"; + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); private TronApplicationContext context; private Wallet wallet; private Manager dbManager; private BlockCapsule blockCapsule; @Before - public void init() { - Args.setParam(new String[] {"--output-directory", dbPath}, Constant.TEST_CONF); + public void init() throws IOException { + Args.setParam(new String[] {"--output-directory", + temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); CommonParameter.PARAMETER.setMinEffectiveConnection(0); context = new TronApplicationContext(DefaultConfig.class); @@ -77,11 +74,6 @@ private void initLocalWitness() { public void removeDb() { Args.clearParam(); context.destroy(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } @Test 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 812f19922ca..eef168938b2 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionHistoryTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionHistoryTest.java @@ -24,10 +24,9 @@ public class TransactionHistoryTest extends BaseTest { private static TransactionInfoCapsule transactionInfoCapsule; static { - dbPath = "output_TransactionHistoryStore_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory }, diff --git a/framework/src/test/java/org/tron/core/db/TransactionRetStoreTest.java b/framework/src/test/java/org/tron/core/db/TransactionRetStoreTest.java index 04478f2c261..b8aebe00aac 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionRetStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionRetStoreTest.java @@ -32,8 +32,8 @@ public class TransactionRetStoreTest extends BaseTest { private static TransactionRetCapsule transactionRetCapsule; static { - dbPath = "output_TransactionRetStore_test"; - Args.setParam(new String[]{"--output-directory", dbPath, "--storage-db-directory", dbDirectory, + Args.setParam(new String[]{"--output-directory", dbPath(), + "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory}, Constant.TEST_CONF); } diff --git a/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java b/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java index f51a8744c74..1edc4aca756 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java @@ -50,9 +50,7 @@ public class TransactionStoreTest extends BaseTest { */ @BeforeClass public static void init() { - dbPath = "output_TransactionStore_test"; - Args.setParam(new String[]{"--output-directory", dbPath, "--storage-db-directory", - dbDirectory, "--storage-index-directory", indexDirectory, "-w"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath(), "-w"}, Constant.TEST_CONF); } /** diff --git a/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java b/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java index 553eb46a725..161fbea9569 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java @@ -60,10 +60,9 @@ public class TransactionTraceTest extends BaseTest { private static boolean init; static { - dbPath = "output_TransactionTrace_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory, "-w", diff --git a/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java b/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java index 8b1724248a0..1b49228a968 100644 --- a/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java +++ b/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java @@ -23,8 +23,7 @@ public class TxCacheDBTest extends BaseTest { public static void init() { String dbDirectory = "db_TransactionCache_test"; String indexDirectory = "index_TransactionCache_test"; - dbPath = "output_TransactionCache_test"; - Args.setParam(new String[]{"--output-directory", dbPath, "--storage-db-directory", + Args.setParam(new String[]{"--output-directory", dbPath(), "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory, "-w"}, Constant.TEST_CONF); } diff --git a/framework/src/test/java/org/tron/core/db/VotesStoreTest.java b/framework/src/test/java/org/tron/core/db/VotesStoreTest.java index 9e5cd7c0098..48d4d1324db 100755 --- a/framework/src/test/java/org/tron/core/db/VotesStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/VotesStoreTest.java @@ -19,8 +19,7 @@ public class VotesStoreTest extends BaseTest { static { - dbPath = "output-votesStore-test"; - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); } @Resource diff --git a/framework/src/test/java/org/tron/core/db/WitnessStoreTest.java b/framework/src/test/java/org/tron/core/db/WitnessStoreTest.java index fd91e7da72a..3190e226689 100755 --- a/framework/src/test/java/org/tron/core/db/WitnessStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/WitnessStoreTest.java @@ -15,8 +15,7 @@ public class WitnessStoreTest extends BaseTest { static { - dbPath = "output-witnessStore-test"; - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); } @Resource diff --git a/framework/src/test/java/org/tron/core/db/api/AssetUpdateHelperTest.java b/framework/src/test/java/org/tron/core/db/api/AssetUpdateHelperTest.java index 714198bde51..ed18b1be97d 100644 --- a/framework/src/test/java/org/tron/core/db/api/AssetUpdateHelperTest.java +++ b/framework/src/test/java/org/tron/core/db/api/AssetUpdateHelperTest.java @@ -27,8 +27,7 @@ public class AssetUpdateHelperTest extends BaseTest { private static boolean init; static { - dbPath = "output_AssetUpdateHelperTest_test"; - Args.setParam(new String[]{"-d", dbPath, "-w"}, "config-test-index.conf"); + Args.setParam(new String[]{"-d", dbPath(), "-w"}, "config-test-index.conf"); Args.getInstance().setSolidityNode(true); } diff --git a/framework/src/test/java/org/tron/core/db/backup/BackupDbUtilTest.java b/framework/src/test/java/org/tron/core/db/backup/BackupDbUtilTest.java index 4ddbd88d338..0153faeab71 100644 --- a/framework/src/test/java/org/tron/core/db/backup/BackupDbUtilTest.java +++ b/framework/src/test/java/org/tron/core/db/backup/BackupDbUtilTest.java @@ -34,8 +34,10 @@ public class BackupDbUtilTest extends BaseTest { String bak2Path; int frequency; + private static final String dbPath; + static { - dbPath = "output-BackupDbUtilTest"; + dbPath = dbPath(); Args.setParam( new String[]{ "--output-directory", dbPath, diff --git a/framework/src/test/java/org/tron/core/db2/ChainbaseTest.java b/framework/src/test/java/org/tron/core/db2/ChainbaseTest.java index 86e3bfefe6b..ee9813be633 100644 --- a/framework/src/test/java/org/tron/core/db2/ChainbaseTest.java +++ b/framework/src/test/java/org/tron/core/db2/ChainbaseTest.java @@ -1,18 +1,19 @@ package org.tron.core.db2; -import java.io.File; +import java.io.IOException; import java.util.HashMap; import java.util.Map; import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.rocksdb.RocksDB; import org.tron.common.storage.leveldb.LevelDbDataSourceImpl; import org.tron.common.storage.rocksdb.RocksDbDataSourceImpl; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.config.args.Args; import org.tron.core.db.common.DbSourceInter; @@ -24,7 +25,8 @@ @Slf4j public class ChainbaseTest { - private static final String dbPath = "output-chainbase-test"; + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); private Chainbase chainbase = null; private final byte[] value0 = "00000".getBytes(); @@ -61,17 +63,13 @@ public class ChainbaseTest { @AfterClass public static void destroy() { Args.clearParam(); - if (FileUtil.deleteDir(new File(dbPath))) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } @Before - public void initDb() { + public void initDb() throws IOException { RocksDB.loadLibrary(); - Args.setParam(new String[] {"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[] {"--output-directory", + temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); } @Test diff --git a/framework/src/test/java/org/tron/core/jsonrpc/BuildTransactionTest.java b/framework/src/test/java/org/tron/core/jsonrpc/BuildTransactionTest.java index 55d7c106458..578d5869e31 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/BuildTransactionTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/BuildTransactionTest.java @@ -32,8 +32,7 @@ public class BuildTransactionTest extends BaseTest { private Wallet wallet; static { - dbPath = "output_build_transaction_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; diff --git a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java index 94f9d5e15f2..b3ed26b591f 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java @@ -64,8 +64,7 @@ public class JsonrpcServiceTest extends BaseTest { private JsonRpcServiceOnSolidity jsonRpcServiceOnSolidity; static { - dbPath = "output_jsonrpc_service_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); CommonParameter.getInstance().setJsonRpcHttpFullNodeEnable(true); CommonParameter.getInstance().setJsonRpcHttpPBFTNodeEnable(true); CommonParameter.getInstance().setJsonRpcHttpSolidityNodeEnable(true); diff --git a/framework/src/test/java/org/tron/core/jsonrpc/SectionBloomStoreTest.java b/framework/src/test/java/org/tron/core/jsonrpc/SectionBloomStoreTest.java index 9b107792d86..6e350a38999 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/SectionBloomStoreTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/SectionBloomStoreTest.java @@ -29,8 +29,7 @@ public class SectionBloomStoreTest extends BaseTest { SectionBloomStore sectionBloomStore; static { - dbPath = "output-sectionBloomStore-test"; - Args.setParam(new String[] {"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[] {"--output-directory", dbPath()}, Constant.TEST_CONF); } @Test diff --git a/framework/src/test/java/org/tron/core/jsonrpc/WalletCursorTest.java b/framework/src/test/java/org/tron/core/jsonrpc/WalletCursorTest.java index 05d27832e1d..d460440184c 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/WalletCursorTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/WalletCursorTest.java @@ -30,8 +30,7 @@ public class WalletCursorTest extends BaseTest { private static boolean init; static { - dbPath = "output_wallet_cursor_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; diff --git a/framework/src/test/java/org/tron/core/metrics/MetricsApiServiceTest.java b/framework/src/test/java/org/tron/core/metrics/MetricsApiServiceTest.java index d906ba20d63..51a46b09388 100644 --- a/framework/src/test/java/org/tron/core/metrics/MetricsApiServiceTest.java +++ b/framework/src/test/java/org/tron/core/metrics/MetricsApiServiceTest.java @@ -1,16 +1,17 @@ package org.tron.core.metrics; -import java.io.File; +import java.io.IOException; import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; @@ -21,7 +22,8 @@ @Slf4j public class MetricsApiServiceTest { - private static String dbPath = "output-metrics"; + @ClassRule + public static TemporaryFolder temporaryFolder = new TemporaryFolder(); private static String dbDirectory = "metrics-database"; private static String indexDirectory = "metrics-index"; private static int port = 10001; @@ -32,7 +34,8 @@ public class MetricsApiServiceTest { @Before - public void init() { + public void init() throws IOException { + String dbPath = temporaryFolder.newFolder().toString(); Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); Args.setParam( @@ -103,6 +106,5 @@ public void testProcessMessage() { @After public void destroy() { context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } } diff --git a/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java b/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java index a2a812ef30b..1c6e56cbbbe 100644 --- a/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java +++ b/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java @@ -55,8 +55,7 @@ public class PrometheusApiServiceTest extends BaseTest { private ChainBaseManager chainManager; static { - dbPath = "output-prometheus-metric"; - Args.setParam(new String[] {"-d", dbPath, "-w"}, Constant.TEST_CONF); + Args.setParam(new String[] {"-d", dbPath(), "-w"}, Constant.TEST_CONF); Args.getInstance().setNodeListenPort(10000 + port.incrementAndGet()); initParameter(Args.getInstance()); Metrics.init(); diff --git a/framework/src/test/java/org/tron/core/net/BaseNet.java b/framework/src/test/java/org/tron/core/net/BaseNet.java index 1eab04fe106..7ae8b355168 100644 --- a/framework/src/test/java/org/tron/core/net/BaseNet.java +++ b/framework/src/test/java/org/tron/core/net/BaseNet.java @@ -14,13 +14,17 @@ import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.handler.timeout.WriteTimeoutHandler; import java.io.File; +import java.io.IOException; import java.util.Collection; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.rules.TemporaryFolder; import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; @@ -36,7 +40,8 @@ @Slf4j public class BaseNet { - private static String dbPath = "output-net"; + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); private static String dbDirectory = "net-database"; private static String indexDirectory = "net-index"; private static int port = 10000; @@ -77,14 +82,18 @@ protected void initChannel(Channel ch) throws Exception { public static void init() throws Exception { executorService.execute(() -> { logger.info("Full node running."); - Args.setParam( - new String[]{ - "--output-directory", dbPath, - "--storage-db-directory", dbDirectory, - "--storage-index-directory", indexDirectory - }, - "config.conf" - ); + try { + Args.setParam( + new String[]{ + "--output-directory", temporaryFolder.newFolder().toString(), + "--storage-db-directory", dbDirectory, + "--storage-index-directory", indexDirectory + }, + "config.conf" + ); + } catch (IOException e) { + Assert.fail("create temp db directory failed"); + } CommonParameter parameter = Args.getInstance(); parameter.setNodeListenPort(port); parameter.getSeedNode().getAddressList().clear(); @@ -117,6 +126,5 @@ public static void destroy() { } Args.clearParam(); context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } } diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java index 57c27bc2382..8154d01aded 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java @@ -41,8 +41,7 @@ public class BlockMsgHandlerTest extends BaseTest { */ @BeforeClass public static void init() { - dbPath = "output_blockmsghandler_test"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); } diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java index 215b5f495ad..7ff29b54bb7 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/MessageHandlerTest.java @@ -3,7 +3,6 @@ import static org.mockito.Mockito.mock; import com.google.protobuf.ByteString; -import java.io.File; import java.lang.reflect.Field; import java.net.InetSocketAddress; import java.util.ArrayList; @@ -12,11 +11,12 @@ import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.mockito.Mockito; import org.springframework.context.ApplicationContext; import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.ReflectUtils; import org.tron.common.utils.Sha256Hash; import org.tron.consensus.pbft.message.PbftMessage; @@ -39,13 +39,15 @@ public class MessageHandlerTest { private PeerConnection peer; private static P2pEventHandlerImpl p2pEventHandler; private static ApplicationContext ctx; - private static String dbPath = "output-message-handler-test"; + + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); @BeforeClass public static void init() throws Exception { - Args.setParam(new String[] {"--output-directory", dbPath, "--debug"}, - Constant.TEST_CONF); + Args.setParam(new String[] {"--output-directory", + temporaryFolder.newFolder().toString(), "--debug"}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); p2pEventHandler = context.getBean(P2pEventHandlerImpl.class); ctx = (ApplicationContext) ReflectUtils.getFieldObject(p2pEventHandler, "ctx"); @@ -59,7 +61,6 @@ public static void init() throws Exception { public static void destroy() { Args.clearParam(); context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } @Before diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java index 53375ec7815..25108e19b70 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java @@ -1,6 +1,5 @@ package org.tron.core.net.messagehandler; -import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -10,9 +9,10 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; import org.tron.core.config.DefaultConfig; @@ -27,12 +27,13 @@ public class SyncBlockChainMsgHandlerTest { private TronApplicationContext context; private SyncBlockChainMsgHandler handler; private PeerConnection peer; - private String dbPath = "output-sync-chain-test"; + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); @Before public void init() throws Exception { - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, - Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", + temporaryFolder.newFolder().toString(), "--debug"}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); handler = context.getBean(SyncBlockChainMsgHandler.class); peer = context.getBean(PeerConnection.class); @@ -85,7 +86,6 @@ public void testProcessMessage() throws Exception { @After public void destroy() { Args.clearParam(); - FileUtil.deleteDir(new File(dbPath)); } } diff --git a/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java b/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java index 870dc9eef8e..d79b54f6f45 100644 --- a/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java @@ -2,17 +2,18 @@ import static org.mockito.Mockito.mock; -import java.io.File; +import java.io.IOException; import java.net.InetSocketAddress; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.mockito.Mockito; import org.springframework.context.ApplicationContext; import org.tron.common.application.TronApplicationContext; import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.ReflectUtils; import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; @@ -31,17 +32,18 @@ import org.tron.protos.Protocol.Inventory.InventoryType; public class AdvServiceTest { - private static String dbPath = "output-adv-service-test1"; private static TronApplicationContext context; private static AdvService service; private static P2pEventHandlerImpl p2pEventHandler; private static ApplicationContext ctx; + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); + @BeforeClass - public static void init() { - dbPath = "output-adv-service-test"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, - Constant.TEST_CONF); + public static void init() throws IOException { + Args.setParam(new String[]{"--output-directory", + temporaryFolder.newFolder().toString(), "--debug"}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); service = context.getBean(AdvService.class); p2pEventHandler = context.getBean(P2pEventHandlerImpl.class); @@ -52,7 +54,6 @@ public static void init() { public static void after() { Args.clearParam(); context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } @Test diff --git a/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java b/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java index aa42e0fcb89..9104b087d26 100644 --- a/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/EffectiveCheckServiceTest.java @@ -1,14 +1,15 @@ package org.tron.core.net.services; -import java.io.File; +import java.io.IOException; import java.lang.reflect.Method; import java.net.InetSocketAddress; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.ReflectUtils; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; @@ -21,12 +22,14 @@ public class EffectiveCheckServiceTest { protected TronApplicationContext context; private EffectiveCheckService service; - private String dbPath = "output-effective-service-test"; + + @Rule + public final TemporaryFolder temporaryFolder = new TemporaryFolder(); @Before - public void init() { - Args.setParam(new String[] {"--output-directory", dbPath, "--debug"}, - Constant.TEST_CONF); + public void init() throws IOException { + Args.setParam(new String[] {"--output-directory", + temporaryFolder.newFolder().toString(), "--debug"}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); service = context.getBean(EffectiveCheckService.class); } @@ -35,7 +38,6 @@ public void init() { public void destroy() { Args.clearParam(); context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } @Test diff --git a/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java b/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java index 4f074b2c825..e027749458f 100644 --- a/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java @@ -4,7 +4,6 @@ import static org.tron.core.net.message.handshake.HelloMessage.getEndpointFromNode; import com.google.protobuf.ByteString; -import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -16,15 +15,14 @@ import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.mockito.Mockito; import org.springframework.context.ApplicationContext; import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.ReflectUtils; import org.tron.common.utils.Sha256Hash; -import org.tron.consensus.pbft.message.PbftMessage; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; @@ -33,7 +31,6 @@ import org.tron.core.net.P2pEventHandlerImpl; import org.tron.core.net.TronNetService; import org.tron.core.net.message.handshake.HelloMessage; -import org.tron.core.net.message.keepalive.PingMessage; import org.tron.core.net.peer.PeerConnection; import org.tron.core.net.peer.PeerManager; import org.tron.p2p.P2pConfig; @@ -51,13 +48,13 @@ public class HandShakeServiceTest { private PeerConnection peer; private static P2pEventHandlerImpl p2pEventHandler; private static ApplicationContext ctx; - private static String dbPath = "output-message-handler-test"; - + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); @BeforeClass public static void init() throws Exception { - Args.setParam(new String[] {"--output-directory", dbPath, "--debug"}, - Constant.TEST_CONF); + Args.setParam(new String[] {"--output-directory", + temporaryFolder.newFolder().toString(), "--debug"}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); p2pEventHandler = context.getBean(P2pEventHandlerImpl.class); ctx = (ApplicationContext) ReflectUtils.getFieldObject(p2pEventHandler, "ctx"); @@ -71,7 +68,6 @@ public static void init() throws Exception { public static void destroy() { Args.clearParam(); context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } @Before diff --git a/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java b/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java index a5b676d0144..777472bdc35 100644 --- a/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java @@ -40,8 +40,7 @@ public class RelayServiceTest extends BaseTest { */ @BeforeClass public static void init() { - dbPath = "output-relay-service-test"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); } diff --git a/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java b/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java index e51ec564886..89c081eaab5 100644 --- a/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java @@ -3,7 +3,6 @@ import static org.mockito.Mockito.mock; import com.google.common.cache.Cache; -import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.InetSocketAddress; @@ -13,11 +12,12 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.mockito.Mockito; import org.springframework.context.ApplicationContext; import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.ReflectUtils; import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; @@ -38,7 +38,8 @@ public class SyncServiceTest { private PeerConnection peer; private P2pEventHandlerImpl p2pEventHandler; private ApplicationContext ctx; - private String dbPath = "output-sync-service-test"; + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); private InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.2", 10001); @@ -50,8 +51,8 @@ public SyncServiceTest() { */ @Before public void init() throws Exception { - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, - Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", + temporaryFolder.newFolder().toString(), "--debug"}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); service = context.getBean(SyncService.class); p2pEventHandler = context.getBean(P2pEventHandlerImpl.class); @@ -65,7 +66,6 @@ public void init() throws Exception { public void destroy() { Args.clearParam(); context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } @Test diff --git a/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java b/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java index 8363e6028bc..9bc942d6684 100755 --- a/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java +++ b/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java @@ -35,8 +35,7 @@ public class PbftApiTest extends BaseTest { @BeforeClass public static void init() { - dbPath = "output_pbftAPI_test"; - Args.setParam(new String[]{"-d", dbPath, "-w"}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath(), "-w"}, Constant.TEST_CONF); } @Test diff --git a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java index 53c97f07b2a..0ba32b27f2e 100644 --- a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java @@ -26,8 +26,7 @@ public class ProposalServiceTest extends BaseTest { @BeforeClass public static void init() { - dbPath = "output_proposal_test"; - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); } diff --git a/framework/src/test/java/org/tron/core/services/WalletApiTest.java b/framework/src/test/java/org/tron/core/services/WalletApiTest.java index 5c3ef49d67c..0a87c348fdb 100644 --- a/framework/src/test/java/org/tron/core/services/WalletApiTest.java +++ b/framework/src/test/java/org/tron/core/services/WalletApiTest.java @@ -1,18 +1,19 @@ package org.tron.core.services; import io.grpc.ManagedChannelBuilder; -import java.io.File; +import java.io.IOException; import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.tron.api.GrpcAPI.EmptyMessage; 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.utils.FileUtil; import org.tron.common.utils.client.Configuration; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; @@ -22,16 +23,19 @@ @Slf4j public class WalletApiTest { + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + private static TronApplicationContext context; - private static String dbPath = "output_wallet_api_test"; private String fullnode = Configuration.getByPath("testng.conf") .getStringList("fullnode.ip.list").get(0); private RpcApiService rpcApiService; private Application appT; @Before - public void init() { - Args.setParam(new String[]{ "-d", dbPath, "--p2p-disable", "true"}, Constant.TEST_CONF); + public void init() throws IOException { + Args.setParam(new String[]{ "-d", temporaryFolder.newFolder().toString(), + "--p2p-disable", "true"}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); appT = ApplicationFactory.create(context); rpcApiService = context.getBean(RpcApiService.class); @@ -53,7 +57,6 @@ public void listNodesTest() { public void destroy() { Args.clearParam(); context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } } diff --git a/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java b/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java index 0be61682b08..6423252560b 100644 --- a/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java @@ -40,8 +40,7 @@ public class HttpApiAccessFilterTest extends BaseTest { private static final CloseableHttpClient httpClient = HttpClients.createDefault(); static { - dbPath = "output_http_api_access_filter_test"; - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); Args.getInstance().setFullNodeAllowShieldedTransactionArgs(false); } diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java index 999b37d8fd6..00f2c2fc086 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java @@ -47,7 +47,7 @@ public class LiteFnQueryGrpcInterceptorTest { public ExpectedException thrown = ExpectedException.none(); @ClassRule - public static TemporaryFolder temporaryFolder = new TemporaryFolder(); + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); /** * init logic. diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java index 5522c56075d..38e0b054c2b 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java @@ -42,8 +42,7 @@ public class LiteFnQueryHttpFilterTest extends BaseTest { private final CloseableHttpClient httpClient = HttpClients.createDefault(); static { - dbPath = "output_http_filter_test"; - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); Args.getInstance().setFullNodeAllowShieldedTransactionArgs(false); } diff --git a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java index 59c4509c441..7d95c0c368a 100644 --- a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java @@ -48,7 +48,7 @@ public class RpcApiAccessInterceptorTest { private static WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubSolidity = null; private static WalletSolidityGrpc.WalletSolidityBlockingStub blockingStubPBFT = null; @ClassRule - public static TemporaryFolder temporaryFolder = new TemporaryFolder(); + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); /** * init logic. diff --git a/framework/src/test/java/org/tron/core/services/http/GetAssetIssueListServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetAssetIssueListServletTest.java index 141c349e252..71a2d4fa5d5 100644 --- a/framework/src/test/java/org/tron/core/services/http/GetAssetIssueListServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/GetAssetIssueListServletTest.java @@ -19,10 +19,9 @@ public class GetAssetIssueListServletTest extends BaseTest { private GetAssetIssueListServlet getAssetIssueListServlet; static { - dbPath = "db_GetNowBlockServlet_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), }, Constant.TEST_CONF ); } diff --git a/framework/src/test/java/org/tron/core/services/http/GetBandwidthPricesServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetBandwidthPricesServletTest.java index 90d2794be9a..40ef8ad068f 100644 --- a/framework/src/test/java/org/tron/core/services/http/GetBandwidthPricesServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/GetBandwidthPricesServletTest.java @@ -5,15 +5,12 @@ import static org.tron.common.utils.client.utils.HttpMethed.createRequest; import com.alibaba.fastjson.JSONObject; -import java.io.IOException; import java.io.UnsupportedEncodingException; import javax.annotation.Resource; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.junit.BeforeClass; -import org.junit.ClassRule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.tron.common.BaseTest; @@ -22,14 +19,12 @@ public class GetBandwidthPricesServletTest extends BaseTest { - @ClassRule - public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); @Resource private GetBandwidthPricesServlet getBandwidthPricesServlet; @BeforeClass - public static void init() throws IOException { - Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + public static void init() { + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); } @Test diff --git a/framework/src/test/java/org/tron/core/services/http/GetBrokerageServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetBrokerageServletTest.java index 898108d0dcd..c7fa8f7fc58 100644 --- a/framework/src/test/java/org/tron/core/services/http/GetBrokerageServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/GetBrokerageServletTest.java @@ -19,10 +19,9 @@ public class GetBrokerageServletTest extends BaseTest { private GetBrokerageServlet getBrokerageServlet; static { - dbPath = "db_GetBrokerageServlet_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), }, Constant.TEST_CONF ); } diff --git a/framework/src/test/java/org/tron/core/services/http/GetEnergyPricesServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetEnergyPricesServletTest.java index 391f2c2d4a7..34e93c557f5 100644 --- a/framework/src/test/java/org/tron/core/services/http/GetEnergyPricesServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/GetEnergyPricesServletTest.java @@ -5,15 +5,12 @@ import static org.tron.common.utils.client.utils.HttpMethed.createRequest; import com.alibaba.fastjson.JSONObject; -import java.io.IOException; import java.io.UnsupportedEncodingException; import javax.annotation.Resource; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.junit.BeforeClass; -import org.junit.ClassRule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.tron.common.BaseTest; @@ -22,14 +19,12 @@ public class GetEnergyPricesServletTest extends BaseTest { - @ClassRule - public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); @Resource private GetEnergyPricesServlet getEnergyPricesServlet; @BeforeClass - public static void init() throws IOException { - Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + public static void init() { + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); } @Test diff --git a/framework/src/test/java/org/tron/core/services/http/GetMemoFeePricesServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetMemoFeePricesServletTest.java index cdfb32cb411..a954f4f4f8f 100644 --- a/framework/src/test/java/org/tron/core/services/http/GetMemoFeePricesServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/GetMemoFeePricesServletTest.java @@ -5,15 +5,12 @@ import static org.tron.common.utils.client.utils.HttpMethed.createRequest; import com.alibaba.fastjson.JSONObject; -import java.io.IOException; import java.io.UnsupportedEncodingException; import javax.annotation.Resource; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.junit.BeforeClass; -import org.junit.ClassRule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.tron.common.BaseTest; @@ -22,14 +19,12 @@ public class GetMemoFeePricesServletTest extends BaseTest { - @ClassRule - public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); @Resource private GetMemoFeePricesServlet getMemoFeePricesServlet; @BeforeClass - public static void init() throws IOException { - Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + public static void init() { + Args.setParam(new String[]{"-d",dbPath()}, Constant.TEST_CONF); } @Test diff --git a/framework/src/test/java/org/tron/core/services/http/GetNowBlockServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetNowBlockServletTest.java index 682f780b249..0406d7b89cb 100644 --- a/framework/src/test/java/org/tron/core/services/http/GetNowBlockServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/GetNowBlockServletTest.java @@ -20,10 +20,9 @@ public class GetNowBlockServletTest extends BaseTest { private GetNowBlockServlet getNowBlockServlet; static { - dbPath = "db_GetNowBlockServlet_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), }, Constant.TEST_CONF ); } diff --git a/framework/src/test/java/org/tron/core/services/http/GetRewardServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetRewardServletTest.java index 47e563f01f9..c8ae67a4a79 100644 --- a/framework/src/test/java/org/tron/core/services/http/GetRewardServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/GetRewardServletTest.java @@ -37,10 +37,9 @@ public class GetRewardServletTest extends BaseTest { GetRewardServlet getRewardServlet; static { - dbPath = "db_GetRewardServlet_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), }, Constant.TEST_CONF ); } diff --git a/framework/src/test/java/org/tron/core/services/http/ListNodesServletTest.java b/framework/src/test/java/org/tron/core/services/http/ListNodesServletTest.java index e2b8e7e9b6e..1f491ca11db 100644 --- a/framework/src/test/java/org/tron/core/services/http/ListNodesServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/ListNodesServletTest.java @@ -19,10 +19,9 @@ public class ListNodesServletTest extends BaseTest { private ListNodesServlet listNodesServlet; static { - dbPath = "db_GetNowBlockServlet_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), }, Constant.TEST_CONF ); } diff --git a/framework/src/test/java/org/tron/core/services/http/ListProposalsServletTest.java b/framework/src/test/java/org/tron/core/services/http/ListProposalsServletTest.java index 0879d02004b..aa3a1817a3e 100644 --- a/framework/src/test/java/org/tron/core/services/http/ListProposalsServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/ListProposalsServletTest.java @@ -19,10 +19,9 @@ public class ListProposalsServletTest extends BaseTest { private ListProposalsServlet listProposalsServlet; static { - dbPath = "db_GetNowBlockServlet_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), }, Constant.TEST_CONF ); } diff --git a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java index 0525ec6e9d0..384c0cada6c 100644 --- a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java @@ -40,9 +40,8 @@ public class TriggerSmartContractServletTest extends BaseTest { @BeforeClass public static void init() throws Exception { - dbPath = "output_" + TriggerSmartContractServletTest.class.getName(); Args.setParam( - new String[]{"--output-directory", dbPath, "--debug", "--witness"}, Constant.TEST_CONF); + new String[]{"--output-directory", dbPath(), "--debug", "--witness"}, Constant.TEST_CONF); Args.getInstance().needSyncCheck = false; // build app context diff --git a/framework/src/test/java/org/tron/core/services/http/UtilTest.java b/framework/src/test/java/org/tron/core/services/http/UtilTest.java index 2fd69a4b8e2..5d9d8092b22 100644 --- a/framework/src/test/java/org/tron/core/services/http/UtilTest.java +++ b/framework/src/test/java/org/tron/core/services/http/UtilTest.java @@ -2,7 +2,6 @@ import com.google.protobuf.ByteString; import javax.annotation.Resource; - import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -28,9 +27,8 @@ public class UtilTest extends BaseTest { private TransactionUtil transactionUtil; static { - dbPath = "output_util_test"; OWNER_ADDRESS = Wallet.getAddressPreFixString() + "c076305e35aea1fe45a772fcaaab8a36e87bdb55"; - Args.setParam(new String[] {"-d", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[] {"-d", dbPath()}, Constant.TEST_CONF); } @Before diff --git a/framework/src/test/java/org/tron/core/services/interfaceOnPBFT/http/GetBandwidthPricesOnPBFTServletTest.java b/framework/src/test/java/org/tron/core/services/interfaceOnPBFT/http/GetBandwidthPricesOnPBFTServletTest.java index 06d552f1ede..a8e07b743c5 100644 --- a/framework/src/test/java/org/tron/core/services/interfaceOnPBFT/http/GetBandwidthPricesOnPBFTServletTest.java +++ b/framework/src/test/java/org/tron/core/services/interfaceOnPBFT/http/GetBandwidthPricesOnPBFTServletTest.java @@ -5,15 +5,12 @@ import static org.tron.common.utils.client.utils.HttpMethed.createRequest; import com.alibaba.fastjson.JSONObject; -import java.io.IOException; import java.io.UnsupportedEncodingException; import javax.annotation.Resource; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.junit.BeforeClass; -import org.junit.ClassRule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.tron.common.BaseTest; @@ -22,14 +19,12 @@ public class GetBandwidthPricesOnPBFTServletTest extends BaseTest { - @ClassRule - public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); @Resource private GetBandwidthPricesOnPBFTServlet getBandwidthPricesOnPBFTServlet; @BeforeClass - public static void init() throws IOException { - Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + public static void init() { + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); } @Test diff --git a/framework/src/test/java/org/tron/core/services/interfaceOnPBFT/http/GetEnergyPricesOnPBFTServletTest.java b/framework/src/test/java/org/tron/core/services/interfaceOnPBFT/http/GetEnergyPricesOnPBFTServletTest.java index ec2ce818da0..8785618bdbe 100644 --- a/framework/src/test/java/org/tron/core/services/interfaceOnPBFT/http/GetEnergyPricesOnPBFTServletTest.java +++ b/framework/src/test/java/org/tron/core/services/interfaceOnPBFT/http/GetEnergyPricesOnPBFTServletTest.java @@ -5,15 +5,12 @@ import static org.tron.common.utils.client.utils.HttpMethed.createRequest; import com.alibaba.fastjson.JSONObject; -import java.io.IOException; import java.io.UnsupportedEncodingException; import javax.annotation.Resource; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.junit.BeforeClass; -import org.junit.ClassRule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.tron.common.BaseTest; @@ -22,14 +19,12 @@ public class GetEnergyPricesOnPBFTServletTest extends BaseTest { - @ClassRule - public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); @Resource private GetEnergyPricesOnPBFTServlet getEnergyPricesOnPBFTServlet; @BeforeClass - public static void init() throws IOException { - Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + public static void init() { + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); } @Test diff --git a/framework/src/test/java/org/tron/core/services/interfaceOnSolidity/http/GetBandwidthPricesOnSolidityServletTest.java b/framework/src/test/java/org/tron/core/services/interfaceOnSolidity/http/GetBandwidthPricesOnSolidityServletTest.java index 6eb27113b99..4b1ace08970 100644 --- a/framework/src/test/java/org/tron/core/services/interfaceOnSolidity/http/GetBandwidthPricesOnSolidityServletTest.java +++ b/framework/src/test/java/org/tron/core/services/interfaceOnSolidity/http/GetBandwidthPricesOnSolidityServletTest.java @@ -5,15 +5,12 @@ import static org.tron.common.utils.client.utils.HttpMethed.createRequest; import com.alibaba.fastjson.JSONObject; -import java.io.IOException; import java.io.UnsupportedEncodingException; import javax.annotation.Resource; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.junit.BeforeClass; -import org.junit.ClassRule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.tron.common.BaseTest; @@ -22,14 +19,12 @@ public class GetBandwidthPricesOnSolidityServletTest extends BaseTest { - @ClassRule - public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); @Resource private GetBandwidthPricesOnSolidityServlet getBandwidthPricesOnSolidityServlet; @BeforeClass - public static void init() throws IOException { - Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + public static void init() { + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); } @Test diff --git a/framework/src/test/java/org/tron/core/services/interfaceOnSolidity/http/GetEnergyPricesOnSolidityServletTest.java b/framework/src/test/java/org/tron/core/services/interfaceOnSolidity/http/GetEnergyPricesOnSolidityServletTest.java index 174175918c1..6a26f9bc861 100644 --- a/framework/src/test/java/org/tron/core/services/interfaceOnSolidity/http/GetEnergyPricesOnSolidityServletTest.java +++ b/framework/src/test/java/org/tron/core/services/interfaceOnSolidity/http/GetEnergyPricesOnSolidityServletTest.java @@ -5,15 +5,12 @@ import static org.tron.common.utils.client.utils.HttpMethed.createRequest; import com.alibaba.fastjson.JSONObject; -import java.io.IOException; import java.io.UnsupportedEncodingException; import javax.annotation.Resource; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.junit.BeforeClass; -import org.junit.ClassRule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.tron.common.BaseTest; @@ -22,14 +19,12 @@ public class GetEnergyPricesOnSolidityServletTest extends BaseTest { - @ClassRule - public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); @Resource private GetEnergyPricesOnSolidityServlet getEnergyPricesOnSolidityServlet; @BeforeClass - public static void init() throws IOException { - Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + public static void init() { + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); } @Test diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java index a05cc64aad4..66a827fc55e 100644 --- a/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java @@ -18,10 +18,4 @@ protected void check() throws Exception { Assert.assertEquals(height, dbManager.getDynamicPropertiesStore() .getLatestBlockHeaderNumberFromDB()); } - - @Override - protected void initDbPath() { - dbPath = "output-height-stop"; - } - } diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java index f974a8a4272..0ac9b93f2dc 100644 --- a/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java @@ -19,10 +19,4 @@ protected void check() throws Exception { Assert.assertEquals(sync + currentHeader, dbManager .getDynamicPropertiesStore().getLatestBlockHeaderNumberFromDB()); } - - @Override - protected void initDbPath() { - dbPath = "output-sync-stop"; - } - } diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java index 2d3fde1afdb..86c32e66507 100644 --- a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java @@ -37,10 +37,4 @@ protected void check() throws Exception { Assert.assertTrue(cronExpression.isSatisfiedBy(new Date(chainManager .getBlockById(chainManager.getBlockIdByNum(height)).getTimeStamp()))); } - - @Override - protected void initDbPath() { - dbPath = "output-time-stop"; - } - } diff --git a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java index 617e824c58f..dc3d02e7ced 100644 --- a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java @@ -3,6 +3,7 @@ import com.google.common.collect.Maps; import com.google.protobuf.ByteString; import java.io.File; +import java.io.IOException; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; @@ -17,7 +18,9 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; import org.tron.common.crypto.ECKey; import org.tron.common.parameter.CommonParameter; @@ -44,6 +47,8 @@ @Slf4j public abstract class ConditionallyStopTest extends BlockGenerate { + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); static ChainBaseManager chainManager; private static DposSlot dposSlot; @@ -67,14 +72,15 @@ public abstract class ConditionallyStopTest extends BlockGenerate { protected abstract void check() throws Exception; - protected abstract void initDbPath(); + protected void initDbPath() throws IOException { + dbPath = temporaryFolder.newFolder().toString(); + } @Before public void init() throws Exception { initDbPath(); - FileUtil.deleteDir(new File(dbPath)); logger.info("Full node running."); Args.setParam(new String[] {"-d", dbPath, "-w"}, Constant.TEST_CONF); Args.getInstance().setNodeListenPort(10000 + port.incrementAndGet()); @@ -108,7 +114,6 @@ public void init() throws Exception { public void destroy() { Args.clearParam(); context.destroy(); - FileUtil.deleteDir(new File(dbPath)); } private void generateBlock(Map witnessAndAccount) throws Exception { diff --git a/framework/src/test/java/org/tron/core/witness/ProposalControllerTest.java b/framework/src/test/java/org/tron/core/witness/ProposalControllerTest.java index 769b09770c2..c7b55ed4417 100644 --- a/framework/src/test/java/org/tron/core/witness/ProposalControllerTest.java +++ b/framework/src/test/java/org/tron/core/witness/ProposalControllerTest.java @@ -29,8 +29,7 @@ public class ProposalControllerTest extends BaseTest { private static boolean init; static { - dbPath = "output_proposal_controller_test"; - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); } @Before diff --git a/framework/src/test/java/org/tron/core/witness/WitnessControllerTest.java b/framework/src/test/java/org/tron/core/witness/WitnessControllerTest.java index dcca6e4bc65..26e46ac138c 100644 --- a/framework/src/test/java/org/tron/core/witness/WitnessControllerTest.java +++ b/framework/src/test/java/org/tron/core/witness/WitnessControllerTest.java @@ -20,8 +20,7 @@ public class WitnessControllerTest extends BaseTest { static { - dbPath = "output_witness_controller_test"; - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); } @Test diff --git a/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java b/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java index 38fdce334b2..67353eb24b1 100644 --- a/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java @@ -73,10 +73,9 @@ public class LibrustzcashTest extends BaseTest { @BeforeClass public static void init() { - dbPath = "output_Librustzcash_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory, "-w", diff --git a/framework/src/test/java/org/tron/core/zksnark/MerkleContainerTest.java b/framework/src/test/java/org/tron/core/zksnark/MerkleContainerTest.java index 678eb137df0..6216ab41f3f 100644 --- a/framework/src/test/java/org/tron/core/zksnark/MerkleContainerTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/MerkleContainerTest.java @@ -38,8 +38,7 @@ public class MerkleContainerTest extends BaseTest { static { - dbPath = "MerkleContainerTest"; - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); } /*@Before diff --git a/framework/src/test/java/org/tron/core/zksnark/MerkleTreeTest.java b/framework/src/test/java/org/tron/core/zksnark/MerkleTreeTest.java index a3048a14375..cb70adb35a2 100644 --- a/framework/src/test/java/org/tron/core/zksnark/MerkleTreeTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/MerkleTreeTest.java @@ -31,10 +31,9 @@ public class MerkleTreeTest extends BaseTest { private static boolean init; static { - dbPath = "output_ShieldedTransaction_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory, "-w", diff --git a/framework/src/test/java/org/tron/core/zksnark/NoteEncDecryTest.java b/framework/src/test/java/org/tron/core/zksnark/NoteEncDecryTest.java index e2b8ef43306..e59060540e9 100644 --- a/framework/src/test/java/org/tron/core/zksnark/NoteEncDecryTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/NoteEncDecryTest.java @@ -22,7 +22,6 @@ @Slf4j public class NoteEncDecryTest extends BaseTest { - private static final String dbPath = "note_encdec_test"; private static final String FROM_ADDRESS; private static final String ADDRESS_ONE_PRIVATE_KEY; private static final long OWNER_BALANCE = 100_000_000; @@ -41,7 +40,7 @@ public class NoteEncDecryTest extends BaseTest { private Wallet wallet; static { - Args.setParam(new String[]{"--output-directory", dbPath}, "config-localtest.conf"); + Args.setParam(new String[]{"--output-directory", dbPath()}, "config-localtest.conf"); FROM_ADDRESS = Wallet.getAddressPreFixString() + "a7d8a35b260395c14aa456297662092ba3b76fc0"; ADDRESS_ONE_PRIVATE_KEY = "7f7f701e94d4f1dd60ee5205e7ea8ee31121427210417b608a6b2e96433549a7"; } diff --git a/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java b/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java index 5fafe0724dc..4a844c49c3c 100644 --- a/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java @@ -110,8 +110,7 @@ public class SendCoinShieldTest extends BaseTest { private static boolean init; static { - dbPath = "output_ShieldedTransaction_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, "config-test-mainnet.conf"); + Args.setParam(new String[]{"--output-directory", dbPath()}, "config-test-mainnet.conf"); Args.getInstance().setZenTokenId(String.valueOf(tokenId)); PUBLIC_ADDRESS_ONE = Wallet.getAddressPreFixString() + "a7d8a35b260395c14aa456297662092ba3b76fc0"; diff --git a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java index e52021986fc..819bfede557 100755 --- a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java @@ -122,8 +122,7 @@ public class ShieldedReceiveTest extends BaseTest { private static boolean init; static { - dbPath = "receive_description_test"; - Args.setParam(new String[]{"--output-directory", dbPath}, "config-localtest.conf"); + Args.setParam(new String[]{"--output-directory", dbPath()}, "config-localtest.conf"); FROM_ADDRESS = Wallet.getAddressPreFixString() + "a7d8a35b260395c14aa456297662092ba3b76fc0"; ADDRESS_ONE_PRIVATE_KEY = "7f7f701e94d4f1dd60ee5205e7ea8ee31121427210417b608a6b2e96433549a7"; } diff --git a/framework/src/test/java/org/tron/program/AccountVoteWitnessTest.java b/framework/src/test/java/org/tron/program/AccountVoteWitnessTest.java index 9f61d91a938..decdbff5e25 100755 --- a/framework/src/test/java/org/tron/program/AccountVoteWitnessTest.java +++ b/framework/src/test/java/org/tron/program/AccountVoteWitnessTest.java @@ -22,8 +22,7 @@ public class AccountVoteWitnessTest extends BaseTest { private MaintenanceManager maintenanceManager; static { - dbPath = "output_witness_test"; - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); } private static Boolean deleteFolder(File index) { diff --git a/framework/src/test/java/org/tron/program/SolidityNodeTest.java b/framework/src/test/java/org/tron/program/SolidityNodeTest.java index 4d151cda7f0..3ec8959e821 100755 --- a/framework/src/test/java/org/tron/program/SolidityNodeTest.java +++ b/framework/src/test/java/org/tron/program/SolidityNodeTest.java @@ -1,33 +1,34 @@ package org.tron.program; import java.io.File; +import java.io.IOException; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.tron.common.application.TronApplicationContext; +import org.tron.common.BaseTest; import org.tron.common.client.DatabaseGrpcClient; import org.tron.core.Constant; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.services.RpcApiService; import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.DynamicProperties; @Slf4j -public class SolidityNodeTest { +public class SolidityNodeTest extends BaseTest { - private static TronApplicationContext context; - - private static RpcApiService rpcApiService; - private static String dbPath = "output_sn_test"; + @Resource + RpcApiService rpcApiService; static { - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); + try { + Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + } catch (IOException e) { + Assert.fail("create temp directory failed."); + } Args.getInstance().setSolidityNode(true); - rpcApiService = context.getBean(RpcApiService.class); } /** @@ -35,8 +36,6 @@ public class SolidityNodeTest { */ @BeforeClass public static void init() { - rpcApiService.init(Args.getInstance()); - rpcApiService.start(); } /** @@ -45,14 +44,6 @@ public static void init() { @AfterClass public static void removeDb() { Args.clearParam(); - rpcApiService.stop(); - context.destroy(); - File dbFolder = new File(dbPath); - if (deleteFolder(dbFolder)) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } } private static Boolean deleteFolder(File index) { @@ -75,6 +66,8 @@ public void testSolidityArgs() { @Test public void testSolidityGrpcCall() { + rpcApiService.init(Args.getInstance()); + rpcApiService.start(); DatabaseGrpcClient databaseGrpcClient = null; String address = Args.getInstance().getTrustNodeAddr(); try { @@ -98,6 +91,7 @@ public void testSolidityGrpcCall() { logger.error("Failed to create database grpc client {}", address); } databaseGrpcClient.shutdown(); + rpcApiService.stop(); } } diff --git a/framework/src/test/java/org/tron/program/SupplementTest.java b/framework/src/test/java/org/tron/program/SupplementTest.java index 5655ee4a098..f370a871006 100644 --- a/framework/src/test/java/org/tron/program/SupplementTest.java +++ b/framework/src/test/java/org/tron/program/SupplementTest.java @@ -5,12 +5,15 @@ import static org.junit.Assert.assertTrue; import java.io.File; +import java.io.IOException; import java.math.BigInteger; import javax.annotation.Resource; import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; @@ -34,7 +37,9 @@ @ContextConfiguration(classes = {DefaultConfig.class}) public class SupplementTest { - private static final String dbPath = "output_coverage_test"; + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); + private static String dbPath; @Resource private StorageRowStore storageRowStore; @@ -43,7 +48,8 @@ public class SupplementTest { public ExpectedException thrown = ExpectedException.none(); @BeforeClass - public static void init() { + public static void init() throws IOException { + dbPath = temporaryFolder.newFolder().toString(); Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); } @@ -53,7 +59,8 @@ public void testGet() throws Exception { assertNotNull(storageRowCapsule); DbBackupConfig dbBackupConfig = new DbBackupConfig(); - dbBackupConfig.initArgs(true, "propPath", "bak1path/", "bak2path/", 1); + String p = dbPath + File.separator; + dbBackupConfig.initArgs(true, p + "propPath", p + "bak1path/", p + "bak2path/", 1); WalletUtils.generateFullNewWalletFile("123456", new File(dbPath)); WalletUtils.generateLightNewWalletFile("123456", new File(dbPath)); From 7b6dfe4f0ebcabc1efb69dd7222c6f3a43be2cbf Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Wed, 13 Sep 2023 14:23:01 +0800 Subject: [PATCH 0888/1197] feat(net):update libp2p version to test-v2.0.2 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 0ed13763a1e..32cca29bcb3 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'io.github.tronprotocol', name: 'libp2p', version: '1.2.0',{ + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v2.0.2',{ exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' From 9d089e7ac7f1b9d213b0044725270a9f2a76d5eb Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Wed, 13 Sep 2023 17:28:49 +0800 Subject: [PATCH 0889/1197] test(net):create folder with temporaryFolder --- .../core/net/messagehandler/TransactionsMsgHandlerTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java index fe58928e3bc..47ffde30ac3 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java @@ -28,8 +28,7 @@ public class TransactionsMsgHandlerTest extends BaseTest { @BeforeClass public static void init() { - dbPath = "output_trxmsghandler_test"; - Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, + Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); } From 326b7828f2262880a322393df011a03ddfa5df42 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Wed, 13 Sep 2023 19:05:17 +0800 Subject: [PATCH 0890/1197] fix(db):avoid dumping a wrong cached data (#5491) --- chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java | 1 + 1 file changed, 1 insertion(+) diff --git a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java index 34f6720a3a1..cefe014959e 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java @@ -318,6 +318,7 @@ private boolean handleException(Throwable e) { private void dump() { if (!isValid.get()) { logger.info("bloomFilters is not valid."); + return; } FileUtil.createDirIfNotExists(this.cacheDir.toString()); logger.info("dump bloomFilters start."); From 47099a229f3686d2228dbb4a29eba24e009c4245 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 14 Sep 2023 09:57:42 +0800 Subject: [PATCH 0891/1197] test(net): add unit test for peer connection --- .../tron/core/net/peer/PeerConnection.java | 1 - .../core/net/peer/PeerConnectionTest.java | 260 ++++++++++++++++++ .../tron/core/net/peer/PeerManagerTest.java | 138 ++++++++++ .../net/services/TronStatsManagerTest.java | 27 ++ 4 files changed, 425 insertions(+), 1 deletion(-) create mode 100644 framework/src/test/java/org/tron/core/net/peer/PeerManagerTest.java create mode 100644 framework/src/test/java/org/tron/core/net/services/TronStatsManagerTest.java diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index 666c99208ba..6743f00421d 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -204,7 +204,6 @@ public void onDisconnect() { syncBlockToFetch.clear(); syncBlockRequested.clear(); syncBlockInProcess.clear(); - syncBlockInProcess.clear(); } public String log() { diff --git a/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java b/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java index 565f2c2b817..c0d81ca2763 100644 --- a/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java +++ b/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java @@ -1,7 +1,28 @@ package org.tron.core.net.peer; +import static org.mockito.Mockito.mock; + +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + import org.junit.Assert; import org.junit.Test; +import org.mockito.Mockito; +import org.tron.common.overlay.message.Message; +import org.tron.common.utils.Pair; +import org.tron.common.utils.ReflectUtils; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.net.message.adv.InventoryMessage; +import org.tron.core.net.message.handshake.HelloMessage; +import org.tron.core.net.message.keepalive.PingMessage; +import org.tron.core.net.message.keepalive.PongMessage; +import org.tron.core.net.service.adv.AdvService; +import org.tron.core.net.service.sync.SyncService; +import org.tron.p2p.connection.Channel; +import org.tron.protos.Protocol; public class PeerConnectionTest { @@ -16,4 +37,243 @@ public void testVariableDefaultValue() { Assert.assertTrue(peerConnection.isNeedSyncFromUs()); Assert.assertTrue(!peerConnection.isSyncFinish()); } + + @Test + public void testOnDisconnect() { + PeerConnection peerConnection = new PeerConnection(); + + SyncService syncService = mock(SyncService.class); + ReflectUtils.setFieldValue(peerConnection, "syncService", syncService); + + AdvService advService = mock(AdvService.class); + ReflectUtils.setFieldValue(peerConnection, "advService", advService); + + Item item = new Item(Sha256Hash.ZERO_HASH, Protocol.Inventory.InventoryType.TRX); + Long time = System.currentTimeMillis(); + BlockCapsule.BlockId blockId = new BlockCapsule.BlockId(); + peerConnection.getAdvInvReceive().put(item, time); + peerConnection.getAdvInvSpread().put(item, time); + peerConnection.getSyncBlockIdCache().put(item.getHash(), time); + peerConnection.getSyncBlockToFetch().add(blockId); + peerConnection.getSyncBlockRequested().put(blockId, time); + peerConnection.getSyncBlockInProcess().add(blockId); + + peerConnection.onDisconnect(); + + //Assert.assertEquals(0, peerConnection.getAdvInvReceive().size()); + //Assert.assertEquals(0, peerConnection.getAdvInvSpread().size()); + //Assert.assertEquals(0, peerConnection.getSyncBlockIdCache().size()); + Assert.assertEquals(0, peerConnection.getSyncBlockToFetch().size()); + Assert.assertEquals(0, peerConnection.getSyncBlockRequested().size()); + Assert.assertEquals(0, peerConnection.getSyncBlockInProcess().size()); + } + + @Test + public void testIsIdle() { + PeerConnection peerConnection = new PeerConnection(); + boolean f = peerConnection.isIdle(); + Assert.assertTrue(f); + + Item item = new Item(Sha256Hash.ZERO_HASH, Protocol.Inventory.InventoryType.TRX); + Long time = System.currentTimeMillis(); + peerConnection.getAdvInvRequest().put(item, time); + f = peerConnection.isIdle(); + Assert.assertTrue(!f); + + peerConnection.getAdvInvRequest().clear(); + f = peerConnection.isIdle(); + Assert.assertTrue(f); + + BlockCapsule.BlockId blockId = new BlockCapsule.BlockId(); + peerConnection.getSyncBlockRequested().put(blockId, time); + f = peerConnection.isIdle(); + Assert.assertTrue(!f); + + peerConnection.getSyncBlockRequested().clear(); + f = peerConnection.isIdle(); + Assert.assertTrue(f); + + peerConnection.setSyncChainRequested(new Pair<>(new LinkedList<>(), time)); + f = peerConnection.isIdle(); + Assert.assertTrue(!f); + } + + @Test + public void testOnConnect() { + PeerConnection peerConnection = new PeerConnection(); + SyncService syncService = mock(SyncService.class); + ReflectUtils.setFieldValue(peerConnection, "syncService", syncService); + + HelloMessage m1 = mock(HelloMessage.class); + BlockCapsule.BlockId b1 = new BlockCapsule.BlockId(Sha256Hash.ZERO_HASH, 1); + Mockito.when(m1.getHeadBlockId()).thenReturn(b1); + + HelloMessage m2 = mock(HelloMessage.class); + BlockCapsule.BlockId b2 = new BlockCapsule.BlockId(Sha256Hash.ZERO_HASH, 2); + Mockito.when(m2.getHeadBlockId()).thenReturn(b2); + + Assert.assertTrue(peerConnection.isNeedSyncFromUs()); + Assert.assertTrue(peerConnection.isNeedSyncFromPeer()); + + ReflectUtils.setFieldValue(peerConnection, "helloMessageReceive", m1); + ReflectUtils.setFieldValue(peerConnection, "helloMessageSend", m2); + peerConnection.onConnect(); + Assert.assertTrue(peerConnection.isNeedSyncFromUs()); + Assert.assertTrue(!peerConnection.isNeedSyncFromPeer()); + + peerConnection.setNeedSyncFromPeer(true); + peerConnection.setNeedSyncFromUs(true); + ReflectUtils.setFieldValue(peerConnection, "helloMessageReceive", m2); + ReflectUtils.setFieldValue(peerConnection, "helloMessageSend", m1); + peerConnection.onConnect(); + Assert.assertTrue(!peerConnection.isNeedSyncFromUs()); + Assert.assertTrue(peerConnection.isNeedSyncFromPeer()); + + peerConnection.setNeedSyncFromPeer(true); + peerConnection.setNeedSyncFromUs(true); + ReflectUtils.setFieldValue(peerConnection, "helloMessageReceive", m1); + ReflectUtils.setFieldValue(peerConnection, "helloMessageSend", m1); + peerConnection.onConnect(); + Assert.assertTrue(!peerConnection.isNeedSyncFromUs()); + Assert.assertTrue(!peerConnection.isNeedSyncFromPeer()); + } + + @Test + public void testSetChannel() { + PeerConnection peerConnection = new PeerConnection(); + + InetSocketAddress inetSocketAddress = + new InetSocketAddress("127.0.0.2", 10001); + Channel c1 = new Channel(); + ReflectUtils.setFieldValue(c1, "inetSocketAddress", inetSocketAddress); + ReflectUtils.setFieldValue(c1, "inetAddress", inetSocketAddress.getAddress()); + + List relayNodes = new ArrayList<>(); + ReflectUtils.setFieldValue(peerConnection, "relayNodes", relayNodes); + + peerConnection.setChannel(c1); + Assert.assertTrue(!peerConnection.isRelayPeer()); + + relayNodes.add(inetSocketAddress); + peerConnection.setChannel(c1); + Assert.assertTrue(peerConnection.isRelayPeer()); + } + + @Test + public void testIsSyncFinish() { + PeerConnection peerConnection = new PeerConnection(); + boolean f = peerConnection.isSyncFinish(); + Assert.assertTrue(!f); + + peerConnection.setNeedSyncFromUs(false); + f = peerConnection.isSyncFinish(); + Assert.assertTrue(!f); + + peerConnection.setNeedSyncFromPeer(false); + f = peerConnection.isSyncFinish(); + Assert.assertTrue(f); + } + + @Test + public void testCheckAndPutAdvInvRequest() { + PeerConnection peerConnection = new PeerConnection(); + Item item = new Item(Sha256Hash.ZERO_HASH, Protocol.Inventory.InventoryType.TRX); + Long time = System.currentTimeMillis(); + boolean f = peerConnection.checkAndPutAdvInvRequest(item, time); + Assert.assertTrue(f); + + f = peerConnection.checkAndPutAdvInvRequest(item, time); + Assert.assertTrue(!f); + } + + @Test + public void testEquals() { + List relayNodes = new ArrayList<>(); + + PeerConnection p1 = new PeerConnection(); + InetSocketAddress inetSocketAddress1 = + new InetSocketAddress("127.0.0.2", 10001); + Channel c1 = new Channel(); + ReflectUtils.setFieldValue(c1, "inetSocketAddress", inetSocketAddress1); + ReflectUtils.setFieldValue(c1, "inetAddress", inetSocketAddress1.getAddress()); + ReflectUtils.setFieldValue(p1, "relayNodes", relayNodes); + p1.setChannel(c1); + + PeerConnection p2 = new PeerConnection(); + InetSocketAddress inetSocketAddress2 = + new InetSocketAddress("127.0.0.2", 10002); + Channel c2 = new Channel(); + ReflectUtils.setFieldValue(c2, "inetSocketAddress", inetSocketAddress2); + ReflectUtils.setFieldValue(c2, "inetAddress", inetSocketAddress2.getAddress()); + ReflectUtils.setFieldValue(p2, "relayNodes", relayNodes); + p2.setChannel(c2); + + PeerConnection p3 = new PeerConnection(); + InetSocketAddress inetSocketAddress3 = + new InetSocketAddress("127.0.0.2", 10002); + Channel c3 = new Channel(); + ReflectUtils.setFieldValue(c3, "inetSocketAddress", inetSocketAddress3); + ReflectUtils.setFieldValue(c3, "inetAddress", inetSocketAddress3.getAddress()); + ReflectUtils.setFieldValue(p3, "relayNodes", relayNodes); + p3.setChannel(c3); + + Assert.assertTrue(p1.equals(p1)); + Assert.assertTrue(!p1.equals(p2)); + Assert.assertTrue(p2.equals(p3)); + } + + @Test + public void testHashCode() { + List relayNodes = new ArrayList<>(); + + PeerConnection p1 = new PeerConnection(); + InetSocketAddress inetSocketAddress1 = + new InetSocketAddress("127.0.0.2", 10001); + Channel c1 = new Channel(); + ReflectUtils.setFieldValue(c1, "inetSocketAddress", inetSocketAddress1); + ReflectUtils.setFieldValue(c1, "inetAddress", inetSocketAddress1.getAddress()); + ReflectUtils.setFieldValue(p1, "relayNodes", relayNodes); + p1.setChannel(c1); + + PeerConnection p2 = new PeerConnection(); + InetSocketAddress inetSocketAddress2 = + new InetSocketAddress("127.0.0.2", 10002); + Channel c2 = new Channel(); + ReflectUtils.setFieldValue(c2, "inetSocketAddress", inetSocketAddress2); + ReflectUtils.setFieldValue(c2, "inetAddress", inetSocketAddress2.getAddress()); + ReflectUtils.setFieldValue(p2, "relayNodes", relayNodes); + p2.setChannel(c2); + + PeerConnection p3 = new PeerConnection(); + InetSocketAddress inetSocketAddress3 = + new InetSocketAddress("127.0.0.2", 10002); + Channel c3 = new Channel(); + ReflectUtils.setFieldValue(c3, "inetSocketAddress", inetSocketAddress3); + ReflectUtils.setFieldValue(c3, "inetAddress", inetSocketAddress3.getAddress()); + ReflectUtils.setFieldValue(p3, "relayNodes", relayNodes); + p3.setChannel(c3); + + Assert.assertTrue(p1.hashCode() != p2.hashCode()); + Assert.assertTrue(p2.hashCode() == p3.hashCode()); + } + + @Test + public void testNeedToLog() throws Exception { + Message msg = new PingMessage(); + boolean f = PeerConnection.needToLog(msg); + Assert.assertTrue(!f); + + msg = new PongMessage(); + f = PeerConnection.needToLog(msg); + Assert.assertTrue(!f); + + msg = new InventoryMessage(new ArrayList<>(), Protocol.Inventory.InventoryType.TRX); + f = PeerConnection.needToLog(msg); + Assert.assertTrue(!f); + + msg = new InventoryMessage(new ArrayList<>(), Protocol.Inventory.InventoryType.BLOCK); + f = PeerConnection.needToLog(msg); + Assert.assertTrue(f); + } + } diff --git a/framework/src/test/java/org/tron/core/net/peer/PeerManagerTest.java b/framework/src/test/java/org/tron/core/net/peer/PeerManagerTest.java new file mode 100644 index 00000000000..a6151da6d1c --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/peer/PeerManagerTest.java @@ -0,0 +1,138 @@ +package org.tron.core.net.peer; + +import static org.mockito.Mockito.mock; + +import java.lang.reflect.Field; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.context.ApplicationContext; +import org.tron.common.utils.ReflectUtils; +import org.tron.p2p.connection.Channel; + +public class PeerManagerTest { + List relayNodes = new ArrayList<>(); + + @Test + public void testAdd() throws Exception { + Field field = PeerManager.class.getDeclaredField("peers"); + field.setAccessible(true); + field.set(PeerManager.class, Collections.synchronizedList(new ArrayList<>())); + + PeerConnection p1 = new PeerConnection(); + InetSocketAddress inetSocketAddress1 = + new InetSocketAddress("127.0.0.2", 10001); + Channel c1 = new Channel(); + ReflectUtils.setFieldValue(c1, "inetSocketAddress", inetSocketAddress1); + ReflectUtils.setFieldValue(c1, "inetAddress", inetSocketAddress1.getAddress()); + ReflectUtils.setFieldValue(p1, "relayNodes", relayNodes); + p1.setChannel(c1); + + ApplicationContext ctx = mock(ApplicationContext.class); + Mockito.when(ctx.getBean(PeerConnection.class)).thenReturn(p1); + + PeerConnection p = PeerManager.add(ctx, c1); + Assert.assertTrue(p != null); + + p = PeerManager.add(ctx, c1); + Assert.assertTrue(p == null); + } + + @Test + public void testRemove() throws Exception { + Field field = PeerManager.class.getDeclaredField("peers"); + field.setAccessible(true); + field.set(PeerManager.class, Collections.synchronizedList(new ArrayList<>())); + + PeerConnection p1 = new PeerConnection(); + InetSocketAddress inetSocketAddress1 = + new InetSocketAddress("127.0.0.2", 10001); + Channel c1 = new Channel(); + ReflectUtils.setFieldValue(c1, "inetSocketAddress", inetSocketAddress1); + ReflectUtils.setFieldValue(c1, "inetAddress", inetSocketAddress1.getAddress()); + ReflectUtils.setFieldValue(p1, "relayNodes", relayNodes); + p1.setChannel(c1); + + ApplicationContext ctx = mock(ApplicationContext.class); + Mockito.when(ctx.getBean(PeerConnection.class)).thenReturn(p1); + + PeerConnection p = PeerManager.remove(c1); + Assert.assertTrue(p == null); + + PeerManager.add(ctx, c1); + p = PeerManager.remove(c1); + Assert.assertTrue(p != null); + } + + @Test + public void testGetPeerConnection() throws Exception { + Field field = PeerManager.class.getDeclaredField("peers"); + field.setAccessible(true); + field.set(PeerManager.class, Collections.synchronizedList(new ArrayList<>())); + + PeerConnection p1 = new PeerConnection(); + InetSocketAddress inetSocketAddress1 = + new InetSocketAddress("127.0.0.2", 10001); + Channel c1 = new Channel(); + ReflectUtils.setFieldValue(c1, "inetSocketAddress", inetSocketAddress1); + ReflectUtils.setFieldValue(c1, "inetAddress", inetSocketAddress1.getAddress()); + ReflectUtils.setFieldValue(p1, "relayNodes", relayNodes); + p1.setChannel(c1); + + ApplicationContext ctx = mock(ApplicationContext.class); + Mockito.when(ctx.getBean(PeerConnection.class)).thenReturn(p1); + + PeerManager.add(ctx, c1); + PeerConnection p = PeerManager.getPeerConnection(c1); + Assert.assertTrue(p != null); + } + + @Test + public void testGetPeers() throws Exception { + Field field = PeerManager.class.getDeclaredField("peers"); + field.setAccessible(true); + field.set(PeerManager.class, Collections.synchronizedList(new ArrayList<>())); + + PeerConnection p1 = new PeerConnection(); + InetSocketAddress inetSocketAddress1 = + new InetSocketAddress("127.0.0.1", 10001); + Channel c1 = new Channel(); + ReflectUtils.setFieldValue(c1, "inetSocketAddress", inetSocketAddress1); + ReflectUtils.setFieldValue(c1, "inetAddress", inetSocketAddress1.getAddress()); + ReflectUtils.setFieldValue(p1, "relayNodes", relayNodes); + p1.setChannel(c1); + + ApplicationContext ctx = mock(ApplicationContext.class); + Mockito.when(ctx.getBean(PeerConnection.class)).thenReturn(p1); + + PeerConnection p = PeerManager.add(ctx, c1); + Assert.assertTrue(p != null); + + List peers = PeerManager.getPeers(); + Assert.assertEquals(1, peers.size()); + + PeerConnection p2 = new PeerConnection(); + InetSocketAddress inetSocketAddress2 = + new InetSocketAddress("127.0.0.2", 10001); + Channel c2 = new Channel(); + ReflectUtils.setFieldValue(c2, "inetSocketAddress", inetSocketAddress2); + ReflectUtils.setFieldValue(c2, "inetAddress", inetSocketAddress2.getAddress()); + ReflectUtils.setFieldValue(p2, "relayNodes", relayNodes); + p2.setChannel(c2); + + ApplicationContext ctx2 = mock(ApplicationContext.class); + Mockito.when(ctx2.getBean(PeerConnection.class)).thenReturn(p2); + + p = PeerManager.add(ctx2, c2); + Assert.assertTrue(p != null); + + peers = PeerManager.getPeers(); + Assert.assertEquals(2, peers.size()); + } + +} diff --git a/framework/src/test/java/org/tron/core/net/services/TronStatsManagerTest.java b/framework/src/test/java/org/tron/core/net/services/TronStatsManagerTest.java new file mode 100644 index 00000000000..369955f4e7f --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/services/TronStatsManagerTest.java @@ -0,0 +1,27 @@ +package org.tron.core.net.services; + +import java.net.InetAddress; +import java.net.InetSocketAddress; + +import org.junit.Assert; +import org.junit.Test; +import org.tron.core.net.service.statistics.NodeStatistics; +import org.tron.core.net.service.statistics.TronStatsManager; +import org.tron.protos.Protocol; + +public class TronStatsManagerTest { + + @Test + public void testOnDisconnect() { + InetSocketAddress inetSocketAddress = + new InetSocketAddress("127.0.0.2", 10001); + + InetAddress inetAddress = inetSocketAddress.getAddress(); + + NodeStatistics statistics = TronStatsManager.getNodeStatistics(inetAddress); + + Assert.assertTrue(null != statistics); + Assert.assertEquals(Protocol.ReasonCode.UNKNOWN, statistics.getDisconnectReason()); + } + +} From 99bef82403951b40d952fb08f4858df8484c71bc Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Thu, 14 Sep 2023 17:05:15 +0800 Subject: [PATCH 0892/1197] feat(api): change log level from error to warn for url parsing (#5496) --- .../java/org/tron/core/services/filter/HttpApiAccessFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/filter/HttpApiAccessFilter.java b/framework/src/main/java/org/tron/core/services/filter/HttpApiAccessFilter.java index ae7ab75a473..0405165ff99 100644 --- a/framework/src/main/java/org/tron/core/services/filter/HttpApiAccessFilter.java +++ b/framework/src/main/java/org/tron/core/services/filter/HttpApiAccessFilter.java @@ -65,7 +65,7 @@ private boolean isDisabled(String endpoint) { disabled = disabledApiList.contains(endpoint.split("/")[2].toLowerCase()); } } catch (Exception e) { - logger.error("check isDisabled except, endpoint={}, error is {}", endpoint, e.getMessage()); + logger.warn("check isDisabled except, endpoint={}, {}", endpoint, e.getMessage()); } return disabled; From b81a63efa971150f0162e2d40c2c147c9fe53c93 Mon Sep 17 00:00:00 2001 From: Kayle Date: Thu, 14 Sep 2023 17:23:00 +0800 Subject: [PATCH 0893/1197] feat(http): optimize parameter parsing (#5483) --------- Co-authored-by: liukai --- .../org/tron/core/services/http/Util.java | 15 +++++------- .../http/GetBrokerageServletTest.java | 19 +++++++++++++++ .../services/http/GetRewardServletTest.java | 24 +++++++++++++++++-- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 186f77cf3e8..6874ec875d0 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -30,6 +30,7 @@ import org.apache.commons.lang3.StringUtils; import org.bouncycastle.util.encoders.Hex; import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.util.MultiMap; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.UrlEncoded; @@ -78,8 +79,6 @@ public class Util { public static final String FUNCTION_SELECTOR = "function_selector"; public static final String FUNCTION_PARAMETER = "parameter"; public static final String CALL_DATA = "data"; - public static final String APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded"; - public static final String APPLICATION_JSON = "application/json"; public static String printTransactionFee(String transactionFee) { JSONObject jsonObject = new JSONObject(); @@ -525,7 +524,6 @@ public static byte[] getAddress(HttpServletRequest request) throws Exception { private static String checkGetParam(HttpServletRequest request, String key) throws Exception { String method = request.getMethod(); - String value = null; if (HttpMethod.GET.toString().toUpperCase().equalsIgnoreCase(method)) { return request.getParameter(key); @@ -535,8 +533,10 @@ private static String checkGetParam(HttpServletRequest request, String key) thro if (StringUtils.isBlank(contentType)) { return null; } - if (APPLICATION_JSON.toLowerCase().contains(contentType)) { - value = getRequestValue(request); + if (contentType.contains(MimeTypes.Type.FORM_ENCODED.asString())) { + return request.getParameter(key); + } else { + String value = getRequestValue(request); if (StringUtils.isBlank(value)) { return null; } @@ -545,13 +545,10 @@ private static String checkGetParam(HttpServletRequest request, String key) thro if (jsonObject != null) { return jsonObject.getString(key); } - } else if (APPLICATION_FORM_URLENCODED.toLowerCase().contains(contentType)) { - return request.getParameter(key); - } else { return null; } } - return value; + return null; } public static String getRequestValue(HttpServletRequest request) throws IOException { diff --git a/framework/src/test/java/org/tron/core/services/http/GetBrokerageServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetBrokerageServletTest.java index c7fa8f7fc58..ffe8cc6c22e 100644 --- a/framework/src/test/java/org/tron/core/services/http/GetBrokerageServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/GetBrokerageServletTest.java @@ -52,6 +52,25 @@ public void getBrokerageValueByJsonTest() { } } + + @Test + public void getBrokerageByJsonUTF8Test() { + int expect = 20; + String jsonParam = "{\"address\": \"27VZHn9PFZwNh7o2EporxmLkpe157iWZVkh\"}"; + MockHttpServletRequest request = createRequest("application/json; charset=utf-8"); + request.setContent(jsonParam.getBytes()); + MockHttpServletResponse response = new MockHttpServletResponse(); + getBrokerageServlet.doPost(request, response); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + int brokerage = (int)result.get("brokerage"); + Assert.assertEquals(expect, brokerage); + } catch (UnsupportedEncodingException e) { + Assert.fail(e.getMessage()); + } + } + @Test public void getBrokerageValueTest() { int expect = 20; diff --git a/framework/src/test/java/org/tron/core/services/http/GetRewardServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetRewardServletTest.java index c8ae67a4a79..404e154a4c3 100644 --- a/framework/src/test/java/org/tron/core/services/http/GetRewardServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/GetRewardServletTest.java @@ -8,9 +8,11 @@ import java.io.UnsupportedEncodingException; import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.junit.After; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; @@ -22,6 +24,7 @@ import org.tron.core.service.MortgageService; import org.tron.core.store.DelegationStore; +@Slf4j public class GetRewardServletTest extends BaseTest { @Resource @@ -52,6 +55,7 @@ public MockHttpServletRequest createRequest(String contentType) { return request; } + @Before public void init() { manager.getDynamicPropertiesStore().saveChangeDelegation(1); byte[] sr = decodeFromBase58Check("27VZHn9PFZwNh7o2EporxmLkpe157iWZVkh"); @@ -61,7 +65,6 @@ public void init() { @Test public void getRewardValueByJsonTest() { - init(); int expect = 138181; String jsonParam = "{\"address\": \"27VZHn9PFZwNh7o2EporxmLkpe157iWZVkh\"}"; MockHttpServletRequest request = createRequest("application/json"); @@ -78,9 +81,26 @@ public void getRewardValueByJsonTest() { } } + @Test + public void getRewardByJsonUTF8Test() { + int expect = 138181; + String jsonParam = "{\"address\": \"27VZHn9PFZwNh7o2EporxmLkpe157iWZVkh\"}"; + MockHttpServletRequest request = createRequest("application/json; charset=utf-8"); + MockHttpServletResponse response = new MockHttpServletResponse(); + request.setContent(jsonParam.getBytes()); + try { + getRewardServlet.doPost(request, response); + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + int reward = (int)result.get("reward"); + Assert.assertEquals(expect, reward); + } catch (UnsupportedEncodingException e) { + Assert.fail(e.getMessage()); + } + } + @Test public void getRewardValueTest() { - init(); int expect = 138181; MockHttpServletRequest request = createRequest("application/x-www-form-urlencoded"); MockHttpServletResponse response = new MockHttpServletResponse(); From 47fe70240192e0a60c261dcc0c3d525f383b6d70 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Mon, 18 Sep 2023 14:42:58 +0800 Subject: [PATCH 0894/1197] feat(db/checkPointV2Store): change log level from info to debug for close (#5499) --- .../org/tron/core/store/CheckPointV2Store.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/chainbase/src/main/java/org/tron/core/store/CheckPointV2Store.java b/chainbase/src/main/java/org/tron/core/store/CheckPointV2Store.java index 046df7f6643..2f952e6b82a 100644 --- a/chainbase/src/main/java/org/tron/core/store/CheckPointV2Store.java +++ b/chainbase/src/main/java/org/tron/core/store/CheckPointV2Store.java @@ -1,6 +1,7 @@ package org.tron.core.store; import com.google.protobuf.InvalidProtocolBufferException; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.tron.core.db.TronDatabase; import org.tron.core.exception.BadItemException; @@ -9,6 +10,7 @@ import java.util.Spliterator; import java.util.function.Consumer; +@Slf4j(topic = "DB") public class CheckPointV2Store extends TronDatabase { @Autowired @@ -50,4 +52,19 @@ public Spliterator spliterator() { protected void init() { } + /** + * close the database. + */ + @Override + public void close() { + logger.debug("******** Begin to close {}. ********", getName()); + try { + dbSource.closeDB(); + } catch (Exception e) { + logger.warn("Failed to close {}.", getName(), e); + } finally { + logger.debug("******** End to close {}. ********", getName()); + } + } + } From c97617c0f6ba5d2df9efc20fb8157ab3e6854f33 Mon Sep 17 00:00:00 2001 From: Kayle Date: Tue, 19 Sep 2023 09:24:13 +0800 Subject: [PATCH 0895/1197] fix(test\db): fix wrong output path (#5501) Co-authored-by: liukai --- .../src/test/java/org/tron/core/db/AccountAssetStoreTest.java | 3 +-- .../src/test/java/org/tron/core/db/AssetIssueStoreTest.java | 3 +-- .../src/test/java/org/tron/core/db/AssetIssueV2StoreTest.java | 3 +-- .../src/test/java/org/tron/core/db/ContractStoreTest.java | 3 +-- .../test/java/org/tron/core/db/DelegatedResourceStoreTest.java | 3 +-- .../src/test/java/org/tron/core/db/DelegationStoreTest.java | 3 +-- .../test/java/org/tron/core/db/WitnessScheduleStoreTest.java | 3 +-- 7 files changed, 7 insertions(+), 14 deletions(-) diff --git a/framework/src/test/java/org/tron/core/db/AccountAssetStoreTest.java b/framework/src/test/java/org/tron/core/db/AccountAssetStoreTest.java index df670fb55ad..48c24d98af1 100644 --- a/framework/src/test/java/org/tron/core/db/AccountAssetStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/AccountAssetStoreTest.java @@ -44,10 +44,9 @@ public class AccountAssetStoreTest extends BaseTest { private AccountStore accountStore; static { - dbPath = "db_AccountAssetStore_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), }, Constant.TEST_CONF ); diff --git a/framework/src/test/java/org/tron/core/db/AssetIssueStoreTest.java b/framework/src/test/java/org/tron/core/db/AssetIssueStoreTest.java index 8e448c246e2..34a4a8507d6 100644 --- a/framework/src/test/java/org/tron/core/db/AssetIssueStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/AssetIssueStoreTest.java @@ -26,10 +26,9 @@ public class AssetIssueStoreTest extends BaseTest { private AssetIssueStore assetIssueStore; static { - dbPath = "db_AssetIssueStoreTest_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), }, Constant.TEST_CONF ); diff --git a/framework/src/test/java/org/tron/core/db/AssetIssueV2StoreTest.java b/framework/src/test/java/org/tron/core/db/AssetIssueV2StoreTest.java index c24706fcc40..e92027e3a28 100644 --- a/framework/src/test/java/org/tron/core/db/AssetIssueV2StoreTest.java +++ b/framework/src/test/java/org/tron/core/db/AssetIssueV2StoreTest.java @@ -16,10 +16,9 @@ public class AssetIssueV2StoreTest extends BaseTest { static { - dbPath = "db_AssetIssueV2StoreTest_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), }, Constant.TEST_CONF ); diff --git a/framework/src/test/java/org/tron/core/db/ContractStoreTest.java b/framework/src/test/java/org/tron/core/db/ContractStoreTest.java index 6b461c02bfe..391a2013636 100644 --- a/framework/src/test/java/org/tron/core/db/ContractStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/ContractStoreTest.java @@ -22,10 +22,9 @@ public class ContractStoreTest extends BaseTest { private static String OWNER_ADDRESS; static { - dbPath = "db_ContractStoreTest_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), }, Constant.TEST_CONF ); 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 e10838b12dd..8878ff0dcf3 100644 --- a/framework/src/test/java/org/tron/core/db/DelegatedResourceStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/DelegatedResourceStoreTest.java @@ -23,10 +23,9 @@ public class DelegatedResourceStoreTest extends BaseTest { private DelegatedResourceStore delegatedResourceStore; static { - dbPath = "db_DelegatedResourceStore_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), }, Constant.TEST_CONF ); 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 1bfbbb33660..d63015ae064 100644 --- a/framework/src/test/java/org/tron/core/db/DelegationStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/DelegationStoreTest.java @@ -23,10 +23,9 @@ public class DelegationStoreTest extends BaseTest { private DelegationStore delegationStore; static { - dbPath = "db_DelegationStore_test"; Args.setParam( new String[]{ - "--output-directory", dbPath, + "--output-directory", dbPath(), }, Constant.TEST_CONF ); diff --git a/framework/src/test/java/org/tron/core/db/WitnessScheduleStoreTest.java b/framework/src/test/java/org/tron/core/db/WitnessScheduleStoreTest.java index c12e5fdc413..7588b1c7add 100644 --- a/framework/src/test/java/org/tron/core/db/WitnessScheduleStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/WitnessScheduleStoreTest.java @@ -31,8 +31,7 @@ public class WitnessScheduleStoreTest extends BaseTest { static { - dbPath = "output-WitnessScheduleStore-test"; - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); } @Before From 6703d13e1c129948158993435b182cf9e12f2e91 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Tue, 19 Sep 2023 10:41:21 +0800 Subject: [PATCH 0896/1197] feat(api): add http/grpc interface rate limit --- .../org/tron/common/parameter/CommonParameter.java | 3 +++ common/src/main/java/org/tron/core/Constant.java | 2 ++ .../src/main/java/org/tron/core/config/args/Args.java | 6 ++++++ .../tron/core/services/http/RateLimiterServlet.java | 5 +++-- .../services/ratelimiter/RateLimiterInterceptor.java | 4 +++- .../services/ratelimiter/strategy/QpsStrategy.java | 3 ++- .../java/org/tron/common/config/args/ArgsTest.java | 10 ++++++++++ framework/src/test/resources/config-test.conf | 1 + 8 files changed, 30 insertions(+), 4 deletions(-) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index aa9f4e40f14..94d398c4b86 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -415,6 +415,9 @@ public class CommonParameter { @Setter public int rateLimiterGlobalIpQps; @Getter + @Setter + public int rateLimiterGlobalApiQps; + @Getter public DbBackupConfig dbBackupConfig; @Getter public RocksDbSettings rocksDBCustomSettings; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 3e859f6fd96..54ff30d9e65 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -256,6 +256,8 @@ public class Constant { public static final String RATE_LIMITER_GLOBAL_IP_QPS = "rate.limiter.global.ip.qps"; + public static final String RATE_LIMITER_GLOBAL_API_QPS = "rate.limiter.global.api.qps"; + public static final String COMMITTEE_CHANGED_DELEGATION = "committee.changedDelegation"; public static final String CRYPTO_ENGINE = "crypto.engine"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 74a755aca7f..b3a6821f3b2 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -224,6 +224,7 @@ public static void clearParam() { PARAMETER.memoFee = 0; PARAMETER.rateLimiterGlobalQps = 50000; PARAMETER.rateLimiterGlobalIpQps = 10000; + PARAMETER.rateLimiterGlobalApiQps = 1000; PARAMETER.p2pDisable = false; PARAMETER.dynamicConfigEnable = false; PARAMETER.dynamicConfigCheckInterval = 600; @@ -957,6 +958,10 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.RATE_LIMITER_GLOBAL_IP_QPS) ? config .getInt(Constant.RATE_LIMITER_GLOBAL_IP_QPS) : 10000; + PARAMETER.rateLimiterGlobalApiQps = + config.hasPath(Constant.RATE_LIMITER_GLOBAL_API_QPS) ? config + .getInt(Constant.RATE_LIMITER_GLOBAL_API_QPS) : 1000; + PARAMETER.rateLimiterInitialization = getRateLimiterFromConfig(config); PARAMETER.changedDelegation = @@ -1627,6 +1632,7 @@ public static void logConfig() { logger.info("Node effective check enable: {}", parameter.isNodeEffectiveCheckEnable()); logger.info("Rate limiter global qps: {}", parameter.getRateLimiterGlobalQps()); logger.info("Rate limiter global ip qps: {}", parameter.getRateLimiterGlobalIpQps()); + logger.info("Rate limiter global api qps: {}", parameter.getRateLimiterGlobalApiQps()); logger.info("************************ Backup config ************************"); logger.info("Backup priority: {}", parameter.getBackupPriority()); logger.info("Backup listen port: {}", parameter.getBackupPort()); diff --git a/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java b/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java index eb8b7b86257..062750f914e 100644 --- a/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java @@ -31,6 +31,7 @@ public abstract class RateLimiterServlet extends HttpServlet { private static final String KEY_PREFIX_HTTP = "http_"; private static final String ADAPTER_PREFIX = "org.tron.core.services.ratelimiter.adapter."; + private static final int QPS = Args.getInstance().getRateLimiterGlobalApiQps(); @Autowired private RateLimiterContainer container; @@ -62,7 +63,7 @@ private void addRateContainer() { } else { constructor = c.getConstructor(); - obj = constructor.newInstance(); + obj = constructor.newInstance("qps=" + QPS); container.add(KEY_PREFIX_HTTP, getClass().getSimpleName(), (IRateLimiter) obj); } success = true; @@ -78,7 +79,7 @@ private void addRateContainer() { // if the specific rate limiter strategy of servlet is not defined or fail to add, // then add a default Strategy. try { - IRateLimiter rateLimiter = new DefaultBaseQqsAdapter("qps=1000"); + IRateLimiter rateLimiter = new DefaultBaseQqsAdapter("qps=" + QPS); container.add(KEY_PREFIX_HTTP, getClass().getSimpleName(), rateLimiter); } catch (Exception e) { logger.warn( diff --git a/framework/src/main/java/org/tron/core/services/ratelimiter/RateLimiterInterceptor.java b/framework/src/main/java/org/tron/core/services/ratelimiter/RateLimiterInterceptor.java index d629ae05abd..d6803dc76d7 100644 --- a/framework/src/main/java/org/tron/core/services/ratelimiter/RateLimiterInterceptor.java +++ b/framework/src/main/java/org/tron/core/services/ratelimiter/RateLimiterInterceptor.java @@ -31,6 +31,8 @@ public class RateLimiterInterceptor implements ServerInterceptor { private static final String KEY_PREFIX_RPC = "rpc_"; + private static final int QPS = Args.getInstance().getRateLimiterGlobalApiQps(); + @Autowired private RateLimiterContainer container; @@ -41,7 +43,7 @@ public void init(Server server) { for (ServerServiceDefinition service : server.getServices()) { for (ServerMethodDefinition method : service.getMethods()) { container.add(KEY_PREFIX_RPC, method.getMethodDescriptor().getFullMethodName(), - new DefaultBaseQqsAdapter("qps=1000")); + new DefaultBaseQqsAdapter("qps=" + QPS)); } } diff --git a/framework/src/main/java/org/tron/core/services/ratelimiter/strategy/QpsStrategy.java b/framework/src/main/java/org/tron/core/services/ratelimiter/strategy/QpsStrategy.java index a4d56af8ba2..8c18af34da9 100644 --- a/framework/src/main/java/org/tron/core/services/ratelimiter/strategy/QpsStrategy.java +++ b/framework/src/main/java/org/tron/core/services/ratelimiter/strategy/QpsStrategy.java @@ -4,12 +4,13 @@ import java.util.HashMap; import java.util.Map; import lombok.extern.slf4j.Slf4j; +import org.tron.core.config.args.Args; @Slf4j public class QpsStrategy extends Strategy { public static final String STRATEGY_PARAM_QPS = "qps"; - public static final Double DEFAULT_QPS = 100D; + public static final int DEFAULT_QPS = Args.getInstance().getRateLimiterGlobalApiQps(); private RateLimiter rateLimiter; public QpsStrategy(String paramString) { diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index 2e29b38824f..aa9ac14964d 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -1,13 +1,21 @@ package org.tron.common.config.args; +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; + import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; +import org.tron.common.client.WalletGrpcClient; import org.tron.common.parameter.RateLimiterInitialization; +import org.tron.common.utils.client.GrpcClient; +import org.tron.common.utils.client.WalletClient; import org.tron.core.Constant; import org.tron.core.config.args.Args; @@ -31,6 +39,7 @@ public void destroy() { @Test public void testConfig() { + Args.logConfig(); Assert.assertEquals(Args.getInstance().getMaxTransactionPendingSize(), 2000); Assert.assertEquals(Args.getInstance().getPendingTransactionTimeout(), 60_000); Assert.assertEquals(Args.getInstance().getMaxFastForwardNum(), 3); @@ -39,6 +48,7 @@ public void testConfig() { Assert.assertFalse(Args.getInstance().isNodeEffectiveCheckEnable()); Assert.assertEquals(Args.getInstance().getRateLimiterGlobalQps(), 1000); Assert.assertEquals(Args.getInstance().getRateLimiterGlobalIpQps(), 1000); + Assert.assertEquals(Args.getInstance().getRateLimiterGlobalApiQps(), 100); Assert.assertEquals(Args.getInstance().p2pDisable, true); Assert.assertEquals(Args.getInstance().getMaxTps(), 1000); RateLimiterInitialization rateLimiter = Args.getInstance().getRateLimiterInitialization(); diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index d506521965f..236502d3360 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -348,6 +348,7 @@ committee = { rate.limiter.global.qps = 1000 rate.limiter.global.ip.qps = 1000 +rate.limiter.global.api.qps = 100 rate.limiter.http = [ { component = "GetNowBlockServlet", From 290753a6da719324c959e9ba1ae076fb650409c0 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Tue, 19 Sep 2023 19:10:19 +0800 Subject: [PATCH 0897/1197] fix(api): optimize API call compatibility --- .../main/java/org/tron/core/services/http/Util.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 6874ec875d0..6eac3d6cf94 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -613,6 +613,9 @@ public static void validateParameter(String contract) throws InvalidParameterExc } public static String getJsonString(String str) { + if (isValidJson(str)) { + return str; + } if (StringUtils.isEmpty(str)) { return EMPTY; } @@ -631,4 +634,12 @@ public static String getJsonString(String str) { return json.toString(); } + public static boolean isValidJson(String json) { + try { + JSON.parse(json); + return true; + } catch (Exception e) { + return false; + } + } } From 7ffd2fcb1ec10cd58893362b9e50623ca59c1673 Mon Sep 17 00:00:00 2001 From: Simon <107106002+CarlChaoCarl@users.noreply.github.com> Date: Tue, 19 Sep 2023 19:58:41 +0800 Subject: [PATCH 0898/1197] fix(event/mechanism): fix NPE in TransactionLogTriggerCapsule (#5500) --- .../capsule/TransactionLogTriggerCapsule.java | 14 +++++--- .../TransactionLogTriggerCapsuleTest.java | 33 +++++++++++++++---- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java b/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java index ab6ea018cf8..f5d457f541d 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java +++ b/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java @@ -175,8 +175,10 @@ public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule .encode58Check(unfreezeBalanceContract.getReceiverAddress().toByteArray())); } transactionLogTrigger.setAssetName("trx"); - transactionLogTrigger.setAssetAmount( - transactionInfo.getUnfreezeAmount()); + if (Objects.nonNull(transactionInfo)) { + transactionLogTrigger.setAssetAmount( + transactionInfo.getUnfreezeAmount()); + } break; case FreezeBalanceV2Contract: FreezeBalanceV2Contract freezeBalanceV2Contract = contractParameter @@ -204,7 +206,9 @@ public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule transactionLogTrigger.setFromAddress(StringUtil.encode58Check( withdrawExpireUnfreezeContract.getOwnerAddress().toByteArray())); transactionLogTrigger.setAssetName("trx"); - transactionLogTrigger.setAssetAmount(transactionInfo.getWithdrawExpireAmount()); + if (Objects.nonNull(transactionInfo)) { + transactionLogTrigger.setAssetAmount(transactionInfo.getWithdrawExpireAmount()); + } break; case DelegateResourceContract: DelegateResourceContract delegateResourceContract = contractParameter @@ -238,7 +242,9 @@ public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule transactionLogTrigger.setFromAddress(StringUtil .encode58Check(cancelAllUnfreezeV2Contract.getOwnerAddress().toByteArray())); transactionLogTrigger.setAssetName("trx"); - transactionLogTrigger.setExtMap(transactionInfo.getCancelUnfreezeV2AmountMap()); + if (Objects.nonNull(transactionInfo)) { + transactionLogTrigger.setExtMap(transactionInfo.getCancelUnfreezeV2AmountMap()); + } break; default: break; diff --git a/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java index d8da2cc540d..76dd6e99158 100644 --- a/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java +++ b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java @@ -1,6 +1,7 @@ package org.tron.common.logsfilter; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; import com.google.protobuf.ByteString; import org.junit.Assert; @@ -37,12 +38,18 @@ public void testConstructorWithUnfreezeBalanceTrxCapsule() { .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); transactionCapsule = new TransactionCapsule(builder2.build(), Protocol.Transaction.Contract.ContractType.UnfreezeBalanceContract); + Protocol.TransactionInfo.Builder builder = Protocol.TransactionInfo.newBuilder(); + builder.setUnfreezeAmount(TRX_PRECISION + 1000); - TransactionLogTriggerCapsule triggerCapsule = - new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + + TransactionLogTriggerCapsule triggerCapsule = new TransactionLogTriggerCapsule( + transactionCapsule, blockCapsule,0,0,0, + builder.build(),0); Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getToAddress()); + Assert.assertEquals(TRX_PRECISION + 1000, + triggerCapsule.getTransactionLogTrigger().getAssetAmount()); } @@ -93,12 +100,17 @@ public void testConstructorWithWithdrawExpireTrxCapsule() { transactionCapsule = new TransactionCapsule(builder2.build(), Protocol.Transaction.Contract.ContractType.WithdrawExpireUnfreezeContract); - TransactionLogTriggerCapsule triggerCapsule = - new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + Protocol.TransactionInfo.Builder builder = Protocol.TransactionInfo.newBuilder(); + builder.setWithdrawExpireAmount(TRX_PRECISION + 1000); + + TransactionLogTriggerCapsule triggerCapsule = new TransactionLogTriggerCapsule( + transactionCapsule, blockCapsule,0,0,0, + builder.build(),0); Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); Assert.assertEquals("trx", triggerCapsule.getTransactionLogTrigger().getAssetName()); - Assert.assertEquals(0L, triggerCapsule.getTransactionLogTrigger().getAssetAmount()); + Assert.assertEquals(TRX_PRECISION + 1000, + triggerCapsule.getTransactionLogTrigger().getAssetAmount()); } @@ -150,10 +162,17 @@ public void testConstructorWithCancelAllUnfreezeTrxCapsule() { transactionCapsule = new TransactionCapsule(builder2.build(), Protocol.Transaction.Contract.ContractType.CancelAllUnfreezeV2Contract); - TransactionLogTriggerCapsule triggerCapsule = - new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + Protocol.TransactionInfo.Builder builder = Protocol.TransactionInfo.newBuilder(); + builder.clearCancelUnfreezeV2Amount().putCancelUnfreezeV2Amount( + BANDWIDTH.name(), TRX_PRECISION + 2000); + + TransactionLogTriggerCapsule triggerCapsule = new TransactionLogTriggerCapsule( + transactionCapsule, blockCapsule,0,0,0, + builder.build(),0); Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); + Assert.assertEquals(TRX_PRECISION + 2000, + triggerCapsule.getTransactionLogTrigger().getExtMap().get(BANDWIDTH.name()).longValue()); } } \ No newline at end of file From 703a8663315c55515129b48ff86aa84ea0e7da57 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Wed, 20 Sep 2023 18:42:41 +0800 Subject: [PATCH 0899/1197] fix(db/trans-cache): avoid recovering a wrong cached data (#5505) --- .../org/tron/core/db/TransactionCache.java | 8 ++++++-- .../org/tron/core/db2/common/TxCacheDB.java | 20 ++++++++++++++----- .../org/tron/core/config/DefaultConfig.java | 7 ------- .../main/java/org/tron/core/db/Manager.java | 2 +- .../org/tron/core/db/TxCacheDBInitTest.java | 20 +++++++++++++++---- 5 files changed, 38 insertions(+), 19 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionCache.java b/chainbase/src/main/java/org/tron/core/db/TransactionCache.java index 70b42ca7226..58ed9be9145 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionCache.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionCache.java @@ -3,16 +3,20 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; import org.tron.core.capsule.BytesCapsule; import org.tron.core.db2.common.TxCacheDB; +import org.tron.core.store.DynamicPropertiesStore; @Slf4j +@Component public class TransactionCache extends TronStoreWithRevoking { @Autowired public TransactionCache(@Value("trans-cache") String dbName, - RecentTransactionStore recentTransactionStore) { - super(new TxCacheDB(dbName, recentTransactionStore)); + @Autowired RecentTransactionStore recentTransactionStore, + @Autowired DynamicPropertiesStore dynamicPropertiesStore) { + super(new TxCacheDB(dbName, recentTransactionStore, dynamicPropertiesStore)); } public void initCache() { diff --git a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java index cefe014959e..8e5a2ee6787 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java @@ -40,6 +40,7 @@ import org.tron.core.db.RecentTransactionItem; import org.tron.core.db.RecentTransactionStore; import org.tron.core.db.common.iterator.DBIterator; +import org.tron.core.store.DynamicPropertiesStore; @Slf4j(topic = "DB") public class TxCacheDB implements DB, Flusher { @@ -59,7 +60,6 @@ public class TxCacheDB implements DB, Flusher { private BloomFilter[] bloomFilters = new BloomFilter[2]; // filterStartBlock record the start block of the active filter private volatile long filterStartBlock = INVALID_BLOCK; - private volatile long currentBlockNum = INVALID_BLOCK; // currentFilterIndex records the index of the active filter private volatile int currentFilterIndex = 0; @@ -75,6 +75,8 @@ public class TxCacheDB implements DB, Flusher { // replace persistentStore and optimizes startup performance private RecentTransactionStore recentTransactionStore; + private DynamicPropertiesStore dynamicPropertiesStore; + private final Path cacheFile0; private final Path cacheFile1; private final Path cacheProperties; @@ -85,11 +87,13 @@ public class TxCacheDB implements DB, Flusher { @Setter private volatile boolean alive; - public TxCacheDB(String name, RecentTransactionStore recentTransactionStore) { + public TxCacheDB(String name, RecentTransactionStore recentTransactionStore, + DynamicPropertiesStore dynamicPropertiesStore) { this.name = name; this.TRANSACTION_COUNT = CommonParameter.getInstance().getStorage().getEstimatedBlockTransactions(); this.recentTransactionStore = recentTransactionStore; + this.dynamicPropertiesStore = dynamicPropertiesStore; String dbEngine = CommonParameter.getInstance().getStorage().getDbEngine(); if ("LEVELDB".equals(dbEngine.toUpperCase())) { this.persistentStore = new LevelDB( @@ -211,7 +215,6 @@ public void put(byte[] key, byte[] value) { MAX_BLOCK_SIZE * TRANSACTION_COUNT); } bloomFilters[currentFilterIndex].put(key); - currentBlockNum = blockNum; if (lastMetricBlock != blockNum) { lastMetricBlock = blockNum; Metrics.gaugeSet(MetricKeys.Gauge.TX_CACHE, @@ -356,8 +359,14 @@ private boolean loadProperties() { Properties properties = new Properties(); properties.load(r); filterStartBlock = Long.parseLong(properties.getProperty("filterStartBlock")); - currentBlockNum = Long.parseLong(properties.getProperty("currentBlockNum")); + long currentBlockNum = Long.parseLong(properties.getProperty("currentBlockNum")); + long currentBlockNumFromDB = dynamicPropertiesStore.getLatestBlockHeaderNumberFromDB(); currentFilterIndex = Integer.parseInt(properties.getProperty("currentFilterIndex")); + if (currentBlockNum != currentBlockNumFromDB) { + throw new IllegalStateException( + String.format("currentBlockNum not match. filter: %d, db: %d", + currentBlockNum, currentBlockNumFromDB)); + } logger.info("filterStartBlock: {}, currentBlockNum: {}, currentFilterIndex: {}, load done.", filterStartBlock, currentBlockNum, currentFilterIndex); return true; @@ -369,6 +378,7 @@ private boolean loadProperties() { private void writeProperties() { try (Writer w = Files.newBufferedWriter(this.cacheProperties, StandardCharsets.UTF_8)) { Properties properties = new Properties(); + long currentBlockNum = dynamicPropertiesStore.getLatestBlockHeaderNumberFromDB(); properties.setProperty("filterStartBlock", String.valueOf(filterStartBlock)); properties.setProperty("currentBlockNum", String.valueOf(currentBlockNum)); properties.setProperty("currentFilterIndex", String.valueOf(currentFilterIndex)); @@ -382,7 +392,7 @@ private void writeProperties() { @Override public TxCacheDB newInstance() { - return new TxCacheDB(name, recentTransactionStore); + return new TxCacheDB(name, recentTransactionStore, dynamicPropertiesStore); } @Override diff --git a/framework/src/main/java/org/tron/core/config/DefaultConfig.java b/framework/src/main/java/org/tron/core/config/DefaultConfig.java index 2c4c2a8717e..7cc32d9a581 100755 --- a/framework/src/main/java/org/tron/core/config/DefaultConfig.java +++ b/framework/src/main/java/org/tron/core/config/DefaultConfig.java @@ -11,9 +11,7 @@ import org.springframework.context.annotation.Import; import org.tron.common.utils.StorageUtils; import org.tron.core.config.args.Args; -import org.tron.core.db.RecentTransactionStore; import org.tron.core.db.RevokingDatabase; -import org.tron.core.db.TransactionCache; import org.tron.core.db.backup.BackupRocksDBAspect; import org.tron.core.db.backup.NeedBeanCondition; import org.tron.core.db2.core.SnapshotManager; @@ -93,11 +91,6 @@ public HttpApiOnPBFTService getHttpApiOnPBFTService() { return null; } - @Bean - public TransactionCache transactionCache() { - return new TransactionCache("trans-cache", appCtx.getBean(RecentTransactionStore.class)); - } - @Bean @Conditional(NeedBeanCondition.class) public BackupRocksDBAspect backupRocksDBAspect() { diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 9a2f53dd69a..b0d902eb84a 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -179,8 +179,8 @@ public class Manager { @Setter public boolean eventPluginLoaded = false; private int maxTransactionPendingSize = Args.getInstance().getMaxTransactionPendingSize(); - @Autowired(required = false) @Getter + @Autowired private TransactionCache transactionCache; @Autowired private KhaosDatabase khaosDb; diff --git a/framework/src/test/java/org/tron/core/db/TxCacheDBInitTest.java b/framework/src/test/java/org/tron/core/db/TxCacheDBInitTest.java index e415476d739..b976cf5f2da 100644 --- a/framework/src/test/java/org/tron/core/db/TxCacheDBInitTest.java +++ b/framework/src/test/java/org/tron/core/db/TxCacheDBInitTest.java @@ -15,6 +15,7 @@ import org.tron.core.capsule.BytesCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; +import org.tron.core.store.DynamicPropertiesStore; import org.tron.keystore.Wallet; @Slf4j @@ -53,11 +54,22 @@ public void reload() { queryTransaction(); db.close(); defaultListableBeanFactory.destroySingleton("transactionCache"); - TransactionCache transactionCache = new TransactionCache("transactionCache", - context.getBean(RecentTransactionStore.class)); - transactionCache.initCache(); - defaultListableBeanFactory.registerSingleton("transactionCache",transactionCache); + db = new TransactionCache("transactionCache", + context.getBean(RecentTransactionStore.class), + context.getBean(DynamicPropertiesStore.class)); + db.initCache(); + defaultListableBeanFactory.registerSingleton("transactionCache",db); queryTransaction(); + db.close(); + defaultListableBeanFactory.destroySingleton("transactionCache"); + db = new TransactionCache("transactionCache", + context.getBean(RecentTransactionStore.class), + context.getBean(DynamicPropertiesStore.class)); + DynamicPropertiesStore dynamicPropertiesStore = context.getBean(DynamicPropertiesStore.class); + dynamicPropertiesStore.saveLatestBlockHeaderNumber(1); + defaultListableBeanFactory.registerSingleton("transactionCache",db); + db.initCache(); + Assert.assertFalse(db.has(hash[65538])); } private void putTransaction() { From 9842b3ff1416c26b27d0296c334b03e4c483e68e Mon Sep 17 00:00:00 2001 From: lxcmyf Date: Thu, 21 Sep 2023 18:36:31 +0800 Subject: [PATCH 0900/1197] fix(freezeV2): remove duplicate judgments (#5508) --- .../java/org/tron/core/actuator/DelegateResourceActuator.java | 2 +- .../tron/core/vm/nativecontract/DelegateResourceProcessor.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 776bd952711..161f22cfb17 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -189,7 +189,7 @@ public boolean validate() throws ContractValidateException { byte[] receiverAddress = delegateResourceContract.getReceiverAddress().toByteArray(); - if (ArrayUtils.isEmpty(receiverAddress) || !DecodeUtil.addressValid(receiverAddress)) { + if (!DecodeUtil.addressValid(receiverAddress)) { throw new ContractValidateException("Invalid receiverAddress"); } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index b3772970248..bb0d4e8297c 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -93,7 +93,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra byte[] receiverAddress = param.getReceiverAddress(); - if (ArrayUtils.isEmpty(receiverAddress) || !DecodeUtil.addressValid(receiverAddress)) { + if (!DecodeUtil.addressValid(receiverAddress)) { throw new ContractValidateException("Invalid receiverAddress"); } if (Arrays.equals(receiverAddress, ownerAddress)) { From 6802f34064627fec15dcb20ed7c2a503fa7951c0 Mon Sep 17 00:00:00 2001 From: lurais <107600021+lurais@users.noreply.github.com> Date: Fri, 22 Sep 2023 14:26:55 +0800 Subject: [PATCH 0901/1197] feat(test): add db test (#5461) Co-authored-by: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Co-authored-by: morgan.peng --- .../leveldb/LevelDbDataSourceImplTest.java | 9 ++ .../leveldb/RocksDbDataSourceImplTest.java | 9 ++ .../java/org/tron/core/db/AbiStoreTest.java | 61 +++++++ .../tron/core/db/AccountTraceStoreTest.java | 57 +++++++ .../tron/core/db/BalanceTraceStoreTest.java | 131 +++++++++++++++ .../java/org/tron/core/db/CodeStoreTest.java | 74 +++++++++ ...elegatedResourceAccountIndexStoreTest.java | 150 ++++++++++++++++++ 7 files changed, 491 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/db/AbiStoreTest.java create mode 100644 framework/src/test/java/org/tron/core/db/AccountTraceStoreTest.java create mode 100644 framework/src/test/java/org/tron/core/db/BalanceTraceStoreTest.java create mode 100644 framework/src/test/java/org/tron/core/db/CodeStoreTest.java create mode 100644 framework/src/test/java/org/tron/core/db/DelegatedResourceAccountIndexStoreTest.java diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java index c774d10c172..50a55d24a0f 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java @@ -27,7 +27,9 @@ import com.google.common.collect.Sets; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -113,6 +115,13 @@ public void testReset() { Args.getInstance().getOutputDirectory(), "test_reset"); dataSource.resetDb(); assertEquals(0, dataSource.allKeys().size()); + assertEquals("LEVELDB", dataSource.getEngine()); + assertEquals("test_reset", dataSource.getName()); + assertEquals(Sets.newHashSet(), dataSource.getlatestValues(0)); + assertEquals(Collections.emptyMap(), dataSource.getNext(key1, 0)); + assertEquals(new ArrayList<>(), dataSource.getKeysNext(key1, 0)); + assertEquals(Sets.newHashSet(), dataSource.getValuesNext(key1, 0)); + assertEquals(Sets.newHashSet(), dataSource.getlatestValues(0)); dataSource.closeDB(); } diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java index 51a5ddc96ee..ed37c1e4bcd 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java @@ -9,7 +9,9 @@ import com.google.common.collect.Sets; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -95,6 +97,13 @@ public void testReset() { Args.getInstance().getOutputDirectory(), "test_reset"); dataSource.resetDb(); assertEquals(0, dataSource.allKeys().size()); + assertEquals("ROCKSDB", dataSource.getEngine()); + assertEquals("test_reset", dataSource.getName()); + assertEquals(Sets.newHashSet(), dataSource.getlatestValues(0)); + assertEquals(Collections.emptyMap(), dataSource.getNext(key1, 0)); + assertEquals(new ArrayList<>(), dataSource.getKeysNext(key1, 0)); + assertEquals(Sets.newHashSet(), dataSource.getValuesNext(key1, 0)); + assertEquals(Sets.newHashSet(), dataSource.getlatestValues(0)); dataSource.closeDB(); } diff --git a/framework/src/test/java/org/tron/core/db/AbiStoreTest.java b/framework/src/test/java/org/tron/core/db/AbiStoreTest.java new file mode 100644 index 00000000000..0cb134c50ce --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/AbiStoreTest.java @@ -0,0 +1,61 @@ +package org.tron.core.db; + +import static org.tron.common.utils.PublicMethod.jsonStr2Abi; + +import com.google.protobuf.ByteString; +import javax.annotation.Resource; +import org.bouncycastle.util.encoders.Hex; +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.capsule.AbiCapsule; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.store.AbiStore; +import org.tron.core.store.AccountIndexStore; +import org.tron.protos.Protocol.AccountType; +import org.tron.protos.contract.SmartContractOuterClass; + +public class AbiStoreTest extends BaseTest { + + @Resource + private AbiStore abiStore; + + private static final byte[] contractAddr = Hex.decode( + "41000000000000000000000000000000000000dEaD"); + + private static final SmartContractOuterClass.SmartContract.ABI SOURCE_ABI = jsonStr2Abi( + "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\"" + + ":\"constructor\"}]"); + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath() + }, + Constant.TEST_CONF + ); + } + + @Test + public void testPut() { + abiStore.put(contractAddr, new AbiCapsule(SOURCE_ABI)); + Assert.assertEquals(abiStore.has(contractAddr), Boolean.TRUE); + } + + @Test + public void testGet() { + abiStore.put(contractAddr, new AbiCapsule(SOURCE_ABI)); + AbiCapsule abiCapsule = abiStore.get(contractAddr); + Assert.assertEquals(abiCapsule.getInstance(), SOURCE_ABI); + } + + @Test + public void testGetTotalAbi() { + abiStore.put(contractAddr, new AbiCapsule(SOURCE_ABI)); + Assert.assertEquals(abiStore.getTotalABIs(), 1); + } +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/db/AccountTraceStoreTest.java b/framework/src/test/java/org/tron/core/db/AccountTraceStoreTest.java new file mode 100644 index 00000000000..aa87f903ad3 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/AccountTraceStoreTest.java @@ -0,0 +1,57 @@ +package org.tron.core.db; + +import com.google.common.primitives.Bytes; +import com.google.common.primitives.Longs; +import com.google.protobuf.ByteString; +import javax.annotation.Resource; +import org.apache.commons.lang3.tuple.Pair; +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.capsule.AccountCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.exception.BadItemException; +import org.tron.core.exception.ItemNotFoundException; +import org.tron.core.store.AccountIndexStore; +import org.tron.core.store.AccountTraceStore; +import org.tron.protos.Protocol.AccountType; + +public class AccountTraceStoreTest extends BaseTest { + + @Resource + private AccountTraceStore accountTraceStore; + private static byte[] address = TransactionStoreTest.randomBytes(32); + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath() + }, + Constant.TEST_CONF + ); + } + + + @Test + public void testRecordBalanceWithBlock() throws BadItemException, ItemNotFoundException { + accountTraceStore.recordBalanceWithBlock(address,1,9999); + Assert.assertNotNull(accountTraceStore.get(Bytes.concat(address, + Longs.toByteArray(1L ^ Long.MAX_VALUE)))); + } + + @Test + public void testGetPrevBalance() { + accountTraceStore.recordBalanceWithBlock(address,2,9999); + Pair pair = accountTraceStore.getPrevBalance(address,2); + Assert.assertEquals((long)pair.getKey(),2L); + Assert.assertEquals((long)pair.getValue(), 0L); + byte[] address2 = TransactionStoreTest.randomBytes(21); + accountTraceStore.recordBalanceWithBlock(address2,3,99); + Pair pair2 = accountTraceStore.getPrevBalance(address2, 3); + Assert.assertEquals((long)pair2.getKey(),3L); + Assert.assertEquals((long)pair2.getValue(), 99L); + } +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/db/BalanceTraceStoreTest.java b/framework/src/test/java/org/tron/core/db/BalanceTraceStoreTest.java new file mode 100644 index 00000000000..82547a997da --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/BalanceTraceStoreTest.java @@ -0,0 +1,131 @@ +package org.tron.core.db; + +import static org.junit.Assert.assertEquals; +import static org.tron.protos.Protocol.Transaction.Contract.ContractType.TransferContract; +import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS; + +import com.google.protobuf.ByteString; +import java.util.Arrays; +import javax.annotation.Resource; +import org.bouncycastle.util.encoders.Hex; +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.capsule.BlockBalanceTraceCapsule; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.store.BalanceTraceStore; +import org.tron.protos.Protocol; +import org.tron.protos.contract.BalanceContract; + + +public class BalanceTraceStoreTest extends BaseTest { + + @Resource + private BalanceTraceStore balanceTraceStoreUnderTest; + + private static final byte[] contractAddr = Hex.decode( + "41000000000000000000000000000000000000dEaD"); + + BlockCapsule blockCapsule = new BlockCapsule(Protocol.Block.newBuilder().setBlockHeader( + Protocol.BlockHeader.newBuilder().setRawData(Protocol.BlockHeader.raw.newBuilder() + .setParentHash(ByteString.copyFrom(ByteArray.fromHexString( + "0304f784e4e7bae517bcab94c3e0c9214fb4ac7ff9d7d5a937d1f40031f87b81"))))).build()); + final TransactionCapsule transactionCapsule = + new TransactionCapsule(Protocol.Transaction.newBuilder().build()); + BalanceContract.TransactionBalanceTrace transactionBalanceTrace = + BalanceContract.TransactionBalanceTrace.newBuilder() + .setTransactionIdentifier(transactionCapsule.getTransactionId().getByteString()) + .setType(TransferContract.name()) + .setStatus(SUCCESS.name()) + .build(); + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath() + }, + Constant.TEST_CONF + ); + } + + @Before + public void clear() { + balanceTraceStoreUnderTest.resetCurrentTransactionTrace(); + balanceTraceStoreUnderTest.resetCurrentBlockTrace(); + } + + + @Test + public void testSetCurrentTransactionId() throws Exception { + balanceTraceStoreUnderTest.setCurrentBlockId(blockCapsule); + balanceTraceStoreUnderTest.setCurrentTransactionId(transactionCapsule); + Assert.assertEquals(balanceTraceStoreUnderTest.getCurrentTransactionId(), + transactionCapsule.getTransactionId()); + } + + @Test + public void testSetCurrentBlockId() { + balanceTraceStoreUnderTest.setCurrentBlockId(blockCapsule); + Assert.assertEquals(blockCapsule.getBlockId(), balanceTraceStoreUnderTest.getCurrentBlockId()); + } + + @Test + public void testResetCurrentTransactionTrace() { + balanceTraceStoreUnderTest.setCurrentBlockId(blockCapsule); + balanceTraceStoreUnderTest.setCurrentTransactionId(transactionCapsule); + balanceTraceStoreUnderTest.resetCurrentTransactionTrace(); + balanceTraceStoreUnderTest.resetCurrentBlockTrace(); + Assert.assertNotNull(balanceTraceStoreUnderTest.getCurrentTransactionId()); + Assert.assertNull(balanceTraceStoreUnderTest.getCurrentTransactionBalanceTrace()); + } + + @Test + public void testInitCurrentBlockBalanceTrace() { + balanceTraceStoreUnderTest.initCurrentBlockBalanceTrace(blockCapsule); + Assert.assertNull(balanceTraceStoreUnderTest.getCurrentBlockId()); + } + + @Test + public void testInitCurrentTransactionBalanceTrace() { + balanceTraceStoreUnderTest.setCurrentBlockId(blockCapsule); + balanceTraceStoreUnderTest.initCurrentTransactionBalanceTrace(transactionCapsule); + Assert.assertEquals(blockCapsule.getBlockId(), balanceTraceStoreUnderTest.getCurrentBlockId()); + Assert.assertNull(balanceTraceStoreUnderTest.getCurrentTransactionId()); + } + + @Test + public void testUpdateCurrentTransactionStatus() { + balanceTraceStoreUnderTest.setCurrentBlockId(blockCapsule); + balanceTraceStoreUnderTest.updateCurrentTransactionStatus(""); + Assert.assertNull(balanceTraceStoreUnderTest.getCurrentTransactionBalanceTrace()); + } + + @Test + public void testGetBlockBalanceTrace() throws Exception { + BlockBalanceTraceCapsule blockBalanceTraceCapsule = new BlockBalanceTraceCapsule(blockCapsule); + balanceTraceStoreUnderTest.put(ByteArray.fromLong(blockCapsule.getNum()), + blockBalanceTraceCapsule); + final BlockBalanceTraceCapsule result = + balanceTraceStoreUnderTest.getBlockBalanceTrace(blockCapsule.getBlockId()); + assertEquals(Arrays.toString(result.getData()), + Arrays.toString(blockBalanceTraceCapsule.getData())); + } + + @Test + public void testGetTransactionBalanceTrace() throws Exception { + BlockBalanceTraceCapsule blockBalanceTraceCapsule = new BlockBalanceTraceCapsule(blockCapsule); + blockBalanceTraceCapsule.addTransactionBalanceTrace(transactionBalanceTrace); + balanceTraceStoreUnderTest.put(ByteArray.fromLong(blockCapsule.getNum()), + blockBalanceTraceCapsule); + final BalanceContract.TransactionBalanceTrace result = + balanceTraceStoreUnderTest.getTransactionBalanceTrace(blockCapsule.getBlockId(), + transactionCapsule.getTransactionId()); + Assert.assertEquals(result.getStatus(),"SUCCESS"); + } + +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/db/CodeStoreTest.java b/framework/src/test/java/org/tron/core/db/CodeStoreTest.java new file mode 100644 index 00000000000..59bfba2236a --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/CodeStoreTest.java @@ -0,0 +1,74 @@ +package org.tron.core.db; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import javax.annotation.Resource; +import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; +import org.junit.BeforeClass; +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.CodeCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.store.CodeStore; + +public class CodeStoreTest extends BaseTest { + + private static final byte[] contractAddr1 = Hex.decode( + "41000000000000000000000000000000000000dEaD"); + private static final byte[] contractAddr2 = Hex.decode( + "41000000000000000000000000000000000000dEbD"); + private static final byte[] contractAddr3 = Hex.decode( + "41000000000000000000000000000000000000dEcD"); + + private static String codeString = + "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d28015" + + "61002a57600080fd5b50600436106100495760003560e01c806385bb7d69146100555761004a565b5b61" + + "0052610073565b50005b61005d610073565b60405161006a91906100b9565b60405180910390f35b6000" + + "80600090505b60028110156100a657808261009091906100d4565b915060018161009f91906100d4565b" + + "905061007b565b5090565b6100b38161012a565b82525050565b60006020820190506100ce6000830184" + + "6100aa565b92915050565b60006100df8261012a565b91506100ea8361012a565b9250827fffffffffff" + + "ffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561011f5761011e61013456" + + "5b5b828201905092915050565b6000819050919050565b7f4e487b710000000000000000000000000000" + + "0000000000000000000000000000600052601160045260246000fdfea26474726f6e58221220f3d01983" + + "23c67293b97323c101e294e6d2cac7fb29555292675277e11c275a4b64736f6c63430008060033"; + private static final CodeCapsule codeCapsule = new CodeCapsule(ByteArray + .fromHexString(codeString)); + + @Resource + private CodeStore codeStore; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath() + }, + Constant.TEST_CONF + ); + } + + @Test + public void testGet() { + codeStore.put(contractAddr1, codeCapsule); + final CodeCapsule result = codeStore.get(contractAddr1); + assertEquals(result.toString(), Arrays.toString(ByteArray.fromHexString(codeString))); + } + + @Test + public void testGetTotalCodes() throws Exception { + codeStore.put(contractAddr1, codeCapsule); + codeStore.put(codeCapsule.getCodeHash().getBytes(), codeCapsule); + final long result = codeStore.getTotalCodes(); + assertEquals(2L, result); + } + + @Test + public void testFindCodeByHash() { + codeStore.put(codeCapsule.getCodeHash().getBytes(), codeCapsule); + final byte[] result = codeStore.findCodeByHash(codeCapsule.getCodeHash().getBytes()); + assertEquals(Arrays.toString(result), Arrays.toString(ByteArray.fromHexString(codeString))); + } +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/db/DelegatedResourceAccountIndexStoreTest.java b/framework/src/test/java/org/tron/core/db/DelegatedResourceAccountIndexStoreTest.java new file mode 100644 index 00000000000..fd5932603e3 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/DelegatedResourceAccountIndexStoreTest.java @@ -0,0 +1,150 @@ +package org.tron.core.db; + +import com.google.common.primitives.Bytes; +import com.google.protobuf.ByteString; +import java.util.Collections; +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.DecodeUtil; +import org.tron.core.Constant; +import org.tron.core.capsule.DelegatedResourceAccountIndexCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.store.DelegatedResourceAccountIndexStore; + + +public class DelegatedResourceAccountIndexStoreTest extends BaseTest { + + @Resource + private DelegatedResourceAccountIndexStore delegatedResourceAccountIndexStore; + + String owner1 = DecodeUtil.addressPreFixString + "548794500882809695a8a687866e76d4271a1abc"; + private static final byte[] FROM_PREFIX = {0x01}; + private static final byte[] TO_PREFIX = {0x02}; + private static final byte[] V2_FROM_PREFIX = {0x03}; + private static final byte[] V2_TO_PREFIX = {0x04}; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath() + }, + Constant.TEST_CONF + ); + } + + @Test + public void testGet() { + delegatedResourceAccountIndexStore.put(ByteArray.fromHexString(owner1), + new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom("testGet".getBytes()))); + final DelegatedResourceAccountIndexCapsule result = + delegatedResourceAccountIndexStore.get(ByteArray.fromHexString(owner1)); + Assert.assertNotNull(result); + Assert.assertEquals(result.getAccount(), ByteString.copyFrom("testGet".getBytes())); + } + + @Test + public void testConvert() { + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = + new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom("testConvert".getBytes())); + delegatedResourceAccountIndexCapsule.setAllFromAccounts( + Collections.singletonList(ByteString.copyFrom("testConvertFrom".getBytes()))); + delegatedResourceAccountIndexCapsule.setAllToAccounts( + Collections.singletonList(ByteString.copyFrom("testConvertTo".getBytes()))); + delegatedResourceAccountIndexStore.put(ByteArray.fromHexString(owner1), + delegatedResourceAccountIndexCapsule); + delegatedResourceAccountIndexStore.convert(ByteArray.fromHexString(owner1)); + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule1 = + delegatedResourceAccountIndexStore.get(Bytes.concat(FROM_PREFIX, + ByteArray.fromHexString(owner1), "testConvertTo".getBytes())); + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule2 = + delegatedResourceAccountIndexStore.get(Bytes.concat(TO_PREFIX, + "testConvertTo".getBytes(), ByteArray.fromHexString(owner1))); + Assert.assertNotNull(delegatedResourceAccountIndexCapsule1); + Assert.assertNotNull(delegatedResourceAccountIndexCapsule2); + } + + @Test + public void testDelegate() throws Exception { + delegatedResourceAccountIndexStore.delegate("testDelegateFrom".getBytes(), + "testDelegateTo".getBytes(),1L); + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule1 = + delegatedResourceAccountIndexStore.get(Bytes.concat(FROM_PREFIX, + "testDelegateFrom".getBytes(), "testDelegateTo".getBytes())); + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule2 = + delegatedResourceAccountIndexStore.get(Bytes.concat(TO_PREFIX, "testDelegateTo".getBytes(), + "testDelegateFrom".getBytes())); + Assert.assertNotNull(delegatedResourceAccountIndexCapsule1); + Assert.assertEquals(delegatedResourceAccountIndexCapsule1.getTimestamp(),1); + Assert.assertNotNull(delegatedResourceAccountIndexCapsule2); + Assert.assertEquals(delegatedResourceAccountIndexCapsule2.getTimestamp(),1); + } + + @Test + public void testDelegateV2() { + delegatedResourceAccountIndexStore.delegateV2("testDelegatev2From".getBytes(), + "testDelegatev2To".getBytes(),2L); + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule1 = + delegatedResourceAccountIndexStore.get(Bytes.concat(V2_FROM_PREFIX, + "testDelegatev2From".getBytes(), "testDelegatev2To".getBytes())); + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule2 = + delegatedResourceAccountIndexStore.get(Bytes.concat(V2_TO_PREFIX, + "testDelegatev2To".getBytes(), "testDelegatev2From".getBytes())); + Assert.assertNotNull(delegatedResourceAccountIndexCapsule1); + Assert.assertEquals(delegatedResourceAccountIndexCapsule1.getTimestamp(),2); + Assert.assertNotNull(delegatedResourceAccountIndexCapsule2); + Assert.assertEquals(delegatedResourceAccountIndexCapsule2.getTimestamp(),2); + } + + @Test + public void testUnDelegate() throws Exception { + delegatedResourceAccountIndexStore.delegate("testDelegateFrom".getBytes(), + "testDelegateTo".getBytes(),1L); + delegatedResourceAccountIndexStore.unDelegate("testDelegateFrom".getBytes(), + "testDelegateTo".getBytes()); + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule1 = + delegatedResourceAccountIndexStore.get(Bytes.concat(FROM_PREFIX, + "testDelegateFrom".getBytes(), "testDelegateTo".getBytes())); + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule2 = + delegatedResourceAccountIndexStore.get(Bytes.concat(TO_PREFIX, + "testDelegateTo".getBytes(), "testDelegateFrom".getBytes())); + Assert.assertNull(delegatedResourceAccountIndexCapsule1); + Assert.assertNull(delegatedResourceAccountIndexCapsule2); + } + + @Test + public void testUnDelegateV2() { + delegatedResourceAccountIndexStore.delegateV2("testDelegateFrom".getBytes(), + "testDelegateTo".getBytes(),1L); + delegatedResourceAccountIndexStore.unDelegateV2("testDelegateFrom".getBytes(), + "testDelegateTo".getBytes()); + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule1 = + delegatedResourceAccountIndexStore.get(Bytes.concat(V2_FROM_PREFIX, + "testDelegateFrom".getBytes(), "testDelegateTo".getBytes())); + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule2 = + delegatedResourceAccountIndexStore.get(Bytes.concat(V2_TO_PREFIX, + "testDelegateTo".getBytes(), "testDelegateFrom".getBytes())); + Assert.assertNull(delegatedResourceAccountIndexCapsule1); + Assert.assertNull(delegatedResourceAccountIndexCapsule2); + } + + @Test + public void testGetIndex() throws Exception { + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = + delegatedResourceAccountIndexStore.getIndex("testGetIndex".getBytes()); + Assert.assertNotNull(delegatedResourceAccountIndexCapsule); + Assert.assertNotNull(delegatedResourceAccountIndexCapsule.getFromAccountsList()); + Assert.assertNotNull(delegatedResourceAccountIndexCapsule.getToAccountsList()); + } + + @Test + public void testGetV2Index() { + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = + delegatedResourceAccountIndexStore.getV2Index("testGetV2Index".getBytes()); + Assert.assertNotNull(delegatedResourceAccountIndexCapsule); + Assert.assertNotNull(delegatedResourceAccountIndexCapsule.getFromAccountsList()); + Assert.assertNotNull(delegatedResourceAccountIndexCapsule.getToAccountsList()); + } +} \ No newline at end of file From c78c42e77a8db0fcbd3ece5fe1e83cefc71debbd Mon Sep 17 00:00:00 2001 From: lurais <107600021+lurais@users.noreply.github.com> Date: Fri, 22 Sep 2023 17:02:41 +0800 Subject: [PATCH 0902/1197] test(db): add test case (#5503) Co-authored-by: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Co-authored-by: morgan.peng --- .../org/tron/core/db/ExchangeStoreTest.java | 62 ++++++++++++++ .../org/tron/core/db/ExchangeV2StoreTest.java | 44 ++++++++++ .../db/IncrementalMerkleTreeStoreTest.java | 51 ++++++++++++ .../tron/core/db/MarketAccountStoreTest.java | 37 +++++++++ .../tron/core/db/MarketOrderStoreTest.java | 47 +++++++++++ .../core/db/MarketPairToPriceStoreTest.java | 83 +++++++++++++++++++ .../org/tron/core/db/ProposalStoreTest.java | 72 ++++++++++++++++ .../tron/core/db/TreeBlockIndexStoreTest.java | 52 ++++++++++++ 8 files changed, 448 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/db/ExchangeStoreTest.java create mode 100644 framework/src/test/java/org/tron/core/db/ExchangeV2StoreTest.java create mode 100644 framework/src/test/java/org/tron/core/db/IncrementalMerkleTreeStoreTest.java create mode 100644 framework/src/test/java/org/tron/core/db/MarketAccountStoreTest.java create mode 100644 framework/src/test/java/org/tron/core/db/MarketOrderStoreTest.java create mode 100644 framework/src/test/java/org/tron/core/db/MarketPairToPriceStoreTest.java create mode 100644 framework/src/test/java/org/tron/core/db/ProposalStoreTest.java create mode 100644 framework/src/test/java/org/tron/core/db/TreeBlockIndexStoreTest.java diff --git a/framework/src/test/java/org/tron/core/db/ExchangeStoreTest.java b/framework/src/test/java/org/tron/core/db/ExchangeStoreTest.java new file mode 100644 index 00000000000..f48ac11301d --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/ExchangeStoreTest.java @@ -0,0 +1,62 @@ +package org.tron.core.db; + +import com.google.protobuf.ByteString; +import java.util.List; +import javax.annotation.Resource; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.BaseTest; +import org.tron.core.Constant; +import org.tron.core.capsule.ExchangeCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.store.ExchangeStore; +import org.tron.protos.Protocol; + +public class ExchangeStoreTest extends BaseTest { + + @Resource + private ExchangeStore exchangeStore; + private byte[] exchangeKey1; + private byte[] exchangeKey2; + + static { + Args.setParam( + new String[] { + "--output-directory", dbPath() + }, + Constant.TEST_CONF + ); + } + + @Before + public void init() { + 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); + builder.setExchangeId(2L).setCreatorAddress(ByteString.copyFromUtf8("Address2")); + exchangeCapsule = new ExchangeCapsule(builder.build()); + exchangeKey2 = exchangeCapsule.createDbKey(); + chainBaseManager.getExchangeStore().put(exchangeKey2, exchangeCapsule); + } + + + @Test + public void testGet() throws Exception { + final ExchangeCapsule result = exchangeStore.get(exchangeKey1); + Assert.assertNotNull(result); + Assert.assertEquals(result.getID(), 1); + } + + @Test + public void testGetAllExchanges() { + List exchangeCapsuleList = exchangeStore.getAllExchanges(); + ExchangeCapsule exchangeCapsule1 = exchangeCapsuleList.get(0); + ExchangeCapsule exchangeCapsule2 = exchangeCapsuleList.get(1); + Assert.assertEquals(exchangeCapsuleList.size(), 2); + Assert.assertEquals(exchangeCapsule1.getCreatorAddress(), ByteString.copyFromUtf8("Address1")); + Assert.assertEquals(exchangeCapsule2.getCreatorAddress(), ByteString.copyFromUtf8("Address2")); + } +} diff --git a/framework/src/test/java/org/tron/core/db/ExchangeV2StoreTest.java b/framework/src/test/java/org/tron/core/db/ExchangeV2StoreTest.java new file mode 100644 index 00000000000..2b1e2ea31ea --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/ExchangeV2StoreTest.java @@ -0,0 +1,44 @@ +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.core.Constant; +import org.tron.core.capsule.ExchangeCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.store.ExchangeV2Store; +import org.tron.protos.Protocol; + +public class ExchangeV2StoreTest extends BaseTest { + + @Resource + private ExchangeV2Store exchangeV2Store; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath() + }, + Constant.TEST_CONF + ); + } + + @Test + public void testGet() throws Exception { + byte[] key = putToExchangeV2(); + final ExchangeCapsule result = exchangeV2Store.get(key); + Assert.assertNotNull(result); + Assert.assertEquals(result.getID(), 1); + } + + private byte[] putToExchangeV2() { + Protocol.Exchange.Builder builder = Protocol.Exchange.newBuilder().setExchangeId(1L) + .setCreatorAddress(ByteString.copyFromUtf8("Address1")); + ExchangeCapsule exchangeCapsule = new ExchangeCapsule(builder.build()); + byte[] exchangeKey1 = exchangeCapsule.createDbKey(); + exchangeV2Store.put(exchangeKey1, exchangeCapsule); + return exchangeKey1; + } +} diff --git a/framework/src/test/java/org/tron/core/db/IncrementalMerkleTreeStoreTest.java b/framework/src/test/java/org/tron/core/db/IncrementalMerkleTreeStoreTest.java new file mode 100644 index 00000000000..643f86d3fe5 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/IncrementalMerkleTreeStoreTest.java @@ -0,0 +1,51 @@ +package org.tron.core.db; + +import javax.annotation.Resource; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.BaseTest; +import org.tron.core.Constant; +import org.tron.core.capsule.IncrementalMerkleTreeCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.store.IncrementalMerkleTreeStore; + +public class IncrementalMerkleTreeStoreTest extends BaseTest { + + private static final byte[] incrementalMerkleTreeData = {10, 0}; + + @Resource + private IncrementalMerkleTreeStore incrementalMerkleTreeStore; + + static { + Args.setParam( + new String[] { + "--output-directory", dbPath() + }, + Constant.TEST_CONF + ); + } + + @Before + public void init() { + incrementalMerkleTreeStore.put("Address1".getBytes(), new IncrementalMerkleTreeCapsule( + incrementalMerkleTreeData)); + } + + @Test + public void testGet() throws Exception { + final IncrementalMerkleTreeCapsule result = + incrementalMerkleTreeStore.get("Address1".getBytes()); + Assert.assertNotNull(result); + Assert.assertEquals(result.getInstance(), new IncrementalMerkleTreeCapsule( + incrementalMerkleTreeData).getInstance()); + } + + @Test + public void testContain() throws Exception { + final boolean result1 = incrementalMerkleTreeStore.contain("Address1".getBytes()); + final boolean result2 = incrementalMerkleTreeStore.contain("Address2".getBytes()); + Assert.assertTrue(result1); + Assert.assertFalse(result2); + } +} diff --git a/framework/src/test/java/org/tron/core/db/MarketAccountStoreTest.java b/framework/src/test/java/org/tron/core/db/MarketAccountStoreTest.java new file mode 100644 index 00000000000..51bf1c5d7fc --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/MarketAccountStoreTest.java @@ -0,0 +1,37 @@ +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.core.Constant; +import org.tron.core.capsule.MarketAccountOrderCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.store.MarketAccountStore; + +public class MarketAccountStoreTest extends BaseTest { + + @Resource + private MarketAccountStore marketAccountStore; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath() + }, + Constant.TEST_CONF + ); + } + + @Test + public void testGet() throws Exception { + 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 new file mode 100644 index 00000000000..33126783e9a --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/MarketOrderStoreTest.java @@ -0,0 +1,47 @@ +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.core.Constant; +import org.tron.core.capsule.MarketOrderCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.store.MarketOrderStore; +import org.tron.protos.Protocol; + +public class MarketOrderStoreTest extends BaseTest { + + @Resource + private MarketOrderStore marketOrderStore; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath() + }, + Constant.TEST_CONF + ); + } + + @Test + public void testGet() throws Exception { + byte[] orderId = "testGet".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())); + final MarketOrderCapsule result = marketOrderStore.get(orderId); + Assert.assertNotNull(result); + Assert.assertEquals(new String(result.getSellTokenId()), "addr1"); + Assert.assertEquals(result.getSellTokenQuantity(), 200L); + Assert.assertEquals(new String(result.getBuyTokenId()), "addr2"); + Assert.assertEquals(result.getBuyTokenQuantity(), 100L); + } + +} diff --git a/framework/src/test/java/org/tron/core/db/MarketPairToPriceStoreTest.java b/framework/src/test/java/org/tron/core/db/MarketPairToPriceStoreTest.java new file mode 100644 index 00000000000..adf315bb92e --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/MarketPairToPriceStoreTest.java @@ -0,0 +1,83 @@ +package org.tron.core.db; + +import static org.junit.Assert.assertEquals; + +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.config.args.Args; +import org.tron.core.store.MarketPairPriceToOrderStore; +import org.tron.core.store.MarketPairToPriceStore; + +public class MarketPairToPriceStoreTest extends BaseTest { + + @Resource + private MarketPairToPriceStore marketPairToPriceStore; + + @Resource + private MarketPairPriceToOrderStore marketPairPriceToOrderStore; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath() + }, + Constant.TEST_CONF + ); + } + + @Test + public void testGet() throws Exception { + marketPairToPriceStore.put("testGet".getBytes(), new BytesCapsule( + ByteArray.fromString("11.0"))); + final BytesCapsule result = marketPairToPriceStore.get("testGet".getBytes()); + Assert.assertNotNull(result); + Assert.assertEquals(new String(result.getData()), "11.0"); + } + + @Test + public void testGetPriceNum() { + marketPairToPriceStore.put("testGetPriceNum".getBytes(), new BytesCapsule( + ByteArray.fromLong(100))); + final long result = marketPairToPriceStore.getPriceNum("testGetPriceNum".getBytes()); + assertEquals(100L, result); + assertEquals(0L, marketPairToPriceStore.getPriceNum("testGetPriceNum1".getBytes())); + } + + @Test + public void testGetPriceNumByTokenId() { + marketPairToPriceStore.setPriceNum("tokenId1".getBytes(), "tokenId2".getBytes(),99); + final long result = + marketPairToPriceStore.getPriceNum("tokenId1".getBytes(), "tokenId2".getBytes()); + assertEquals(99L, result); + assertEquals(0L, marketPairToPriceStore.getPriceNum("tokenId2".getBytes(), + "tokenId1".getBytes())); + } + + @Test + public void testSetPriceNum() { + marketPairToPriceStore.setPriceNum("testSetPriceNum1".getBytes(), 98L); + long result = marketPairToPriceStore.getPriceNum("testSetPriceNum1".getBytes()); + assertEquals(result, 98); + } + + @Test + public void testSetPriceNumByToken() { + marketPairToPriceStore.setPriceNum("token3".getBytes(), "token4".getBytes(), 97L); + long result = marketPairToPriceStore.getPriceNum("token3".getBytes(), "token4".getBytes()); + assertEquals(result, 97); + } + + @Test + public void testAddNewPriceKey() { + marketPairToPriceStore + .addNewPriceKey("token5".getBytes(), "token6".getBytes(), marketPairPriceToOrderStore); + long result = marketPairToPriceStore.getPriceNum("token5".getBytes(), "token6".getBytes()); + assertEquals(1, result); + } + +} diff --git a/framework/src/test/java/org/tron/core/db/ProposalStoreTest.java b/framework/src/test/java/org/tron/core/db/ProposalStoreTest.java new file mode 100644 index 00000000000..b08402d33a0 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/ProposalStoreTest.java @@ -0,0 +1,72 @@ +package org.tron.core.db; + +import static org.junit.Assert.assertThrows; + +import com.google.protobuf.ByteString; +import java.util.List; + +import javax.annotation.Resource; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.BaseTest; +import org.tron.core.Constant; +import org.tron.core.capsule.ProposalCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.exception.ItemNotFoundException; +import org.tron.core.store.ProposalStore; +import org.tron.protos.Protocol; + +public class ProposalStoreTest extends BaseTest { + + @Resource + private ProposalStore proposalStore; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath() + }, + Constant.TEST_CONF + ); + } + + @Before + public void init() { + Protocol.Proposal.Builder builder = Protocol.Proposal.newBuilder() + .setProposalId(1L).putParameters(1,99).setState(Protocol.Proposal.State.PENDING) + .setProposerAddress(ByteString.copyFromUtf8("Address1")); + proposalStore.put("1".getBytes(), new ProposalCapsule(builder.build())); + builder.setProposalId(2L).setState(Protocol.Proposal.State.APPROVED).setProposerAddress( + ByteString.copyFromUtf8("Address2")); + proposalStore.put("2".getBytes(), new ProposalCapsule(builder.build())); + } + + @Test + public void testGet() throws Exception { + final ProposalCapsule result = proposalStore.get("1".getBytes()); + Assert.assertNotNull(result); + Assert.assertEquals(result.getID(),1); + Assert.assertEquals(result.getProposalAddress(), ByteString.copyFromUtf8("Address1")); + assertThrows(ItemNotFoundException.class, + () -> proposalStore.get("testGet1".getBytes())); + } + + @Test + public void testGetAllProposals() { + final List result = proposalStore.getAllProposals(); + Assert.assertEquals(result.size(), 2); + Assert.assertEquals(result.get(0).getID(), 1); + Assert.assertEquals(result.get(0).getProposalAddress(), ByteString.copyFromUtf8("Address1")); + } + + @Test + public void testGetSpecifiedProposals() { + final List result = + proposalStore.getSpecifiedProposals(Protocol.Proposal.State.PENDING, 1); + Assert.assertEquals(result.size(), 1); + Assert.assertEquals(result.get(0).getID(), 1); + Assert.assertEquals(result.get(0).getProposalAddress(), ByteString.copyFromUtf8("Address1")); + } + +} diff --git a/framework/src/test/java/org/tron/core/db/TreeBlockIndexStoreTest.java b/framework/src/test/java/org/tron/core/db/TreeBlockIndexStoreTest.java new file mode 100644 index 00000000000..19d1329e580 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/TreeBlockIndexStoreTest.java @@ -0,0 +1,52 @@ +package org.tron.core.db; + +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.config.args.Args; +import org.tron.core.exception.ItemNotFoundException; +import org.tron.core.store.TreeBlockIndexStore; + +public class TreeBlockIndexStoreTest extends BaseTest { + + @Resource + private TreeBlockIndexStore treeBlockIndexStore; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath() + }, + Constant.TEST_CONF + ); + } + + @Test + public void testPut() throws ItemNotFoundException { + treeBlockIndexStore.put(1L, "testPut".getBytes()); + byte[] result = treeBlockIndexStore.get(1L); + Assert.assertEquals(new String(result),"testPut"); + } + + @Test + public void testGetByNum() throws Exception { + treeBlockIndexStore.put(2L, "testGetByNum".getBytes()); + byte[] result = treeBlockIndexStore.get(2L); + Assert.assertEquals(new String(result),"testGetByNum"); + Assert.assertThrows(ItemNotFoundException.class, () -> treeBlockIndexStore.get(0L)); + } + + @Test + public void testGet() throws Exception { + treeBlockIndexStore.put(3L, "testGet".getBytes()); + final BytesCapsule result = treeBlockIndexStore.get(ByteArray.fromLong(3L)); + Assert.assertEquals(new String(result.getData()),"testGet"); + Assert.assertThrows(ItemNotFoundException.class, () -> treeBlockIndexStore + .get(ByteArray.fromLong(0L))); + } + +} From 9406d24b5665088de0c9e8652385b49d2351d74c Mon Sep 17 00:00:00 2001 From: lxcmyf Date: Mon, 25 Sep 2023 16:00:23 +0800 Subject: [PATCH 0903/1197] fix(api): add resource price query API for soliditynode (#5516) --- .../http/solidity/SolidityNodeHttpApiService.java | 15 ++++++++++----- .../java/org/tron/program/SolidityNodeTest.java | 10 ++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java index a1808b4fa86..0c66b220e09 100644 --- a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java @@ -22,6 +22,7 @@ import org.tron.core.services.http.GetAssetIssueListByNameServlet; import org.tron.core.services.http.GetAssetIssueListServlet; import org.tron.core.services.http.GetAvailableUnfreezeCountServlet; +import org.tron.core.services.http.GetBandwidthPricesServlet; import org.tron.core.services.http.GetBlockByIdServlet; import org.tron.core.services.http.GetBlockByLatestNumServlet; import org.tron.core.services.http.GetBlockByLimitNextServlet; @@ -35,6 +36,7 @@ import org.tron.core.services.http.GetDelegatedResourceAccountIndexV2Servlet; import org.tron.core.services.http.GetDelegatedResourceServlet; import org.tron.core.services.http.GetDelegatedResourceV2Servlet; +import org.tron.core.services.http.GetEnergyPricesServlet; import org.tron.core.services.http.GetExchangeByIdServlet; import org.tron.core.services.http.GetMarketOrderByAccountServlet; import org.tron.core.services.http.GetMarketOrderByIdServlet; @@ -66,7 +68,6 @@ public class SolidityNodeHttpApiService extends HttpService { @Autowired private GetAccountServlet getAccountServlet; - @Autowired private GetTransactionByIdSolidityServlet getTransactionByIdServlet; @Autowired @@ -91,7 +92,6 @@ public class SolidityNodeHttpApiService extends HttpService { private GetExchangeByIdServlet getExchangeByIdServlet; @Autowired private ListExchangesServlet listExchangesServlet; - @Autowired private ListWitnessesServlet listWitnessesServlet; @Autowired @@ -154,15 +154,16 @@ public class SolidityNodeHttpApiService extends HttpService { private TriggerConstantContractServlet triggerConstantContractServlet; @Autowired private EstimateEnergyServlet estimateEnergyServlet; - @Autowired private GetTransactionInfoByBlockNumServlet getTransactionInfoByBlockNumServlet; - @Autowired private HttpApiAccessFilter httpApiAccessFilter; - @Autowired private GetBlockServlet getBlockServlet; + @Autowired + private GetBandwidthPricesServlet getBandwidthPricesServlet; + @Autowired + private GetEnergyPricesServlet getEnergyPricesServlet; @Override @@ -279,6 +280,10 @@ public void start() { context.addServlet(new ServletHolder(getRewardServlet), "/walletsolidity/getReward"); context.addServlet(new ServletHolder(getBurnTrxServlet), "/walletsolidity/getburntrx"); context.addServlet(new ServletHolder(getBlockServlet), "/walletsolidity/getblock"); + context.addServlet(new ServletHolder(getBandwidthPricesServlet), + "/walletsolidity/getbandwidthprices"); + context.addServlet(new ServletHolder(getEnergyPricesServlet), + "/walletsolidity/getenergyprices"); // http access filter context.addFilter(new FilterHolder(httpApiAccessFilter), "/walletsolidity/*", diff --git a/framework/src/test/java/org/tron/program/SolidityNodeTest.java b/framework/src/test/java/org/tron/program/SolidityNodeTest.java index 3ec8959e821..a77fa2fa8c6 100755 --- a/framework/src/test/java/org/tron/program/SolidityNodeTest.java +++ b/framework/src/test/java/org/tron/program/SolidityNodeTest.java @@ -13,6 +13,7 @@ import org.tron.core.Constant; import org.tron.core.config.args.Args; import org.tron.core.services.RpcApiService; +import org.tron.core.services.http.solidity.SolidityNodeHttpApiService; import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.DynamicProperties; @@ -21,6 +22,8 @@ public class SolidityNodeTest extends BaseTest { @Resource RpcApiService rpcApiService; + @Resource + SolidityNodeHttpApiService solidityNodeHttpApiService; static { try { @@ -94,4 +97,11 @@ public void testSolidityGrpcCall() { rpcApiService.stop(); } + @Test + public void testSolidityNodeHttpApiService() { + solidityNodeHttpApiService.init(Args.getInstance()); + solidityNodeHttpApiService.start(); + solidityNodeHttpApiService.stop(); + Assert.assertTrue(true); + } } From 962a3dbe97a67c2399faac6d57a2fae974905c94 Mon Sep 17 00:00:00 2001 From: Brown Jiang <317787106@qq.com> Date: Tue, 26 Sep 2023 10:33:12 +0800 Subject: [PATCH 0904/1197] feat(net):update libp2p (#5517) --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index fc95dd385b7..8cca0853dc5 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v2.0.2',{ + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v2.0.3',{ exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' From fe7715de604212de80e712cd8533a345a91ae2a2 Mon Sep 17 00:00:00 2001 From: Kayle Date: Sat, 7 Oct 2023 10:17:02 +0800 Subject: [PATCH 0905/1197] feat(LiteFullNodeTool): mark LiteFullNodeTool as deprecated (#5509) --------- Co-authored-by: liukai --- .../main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java | 3 +++ .../src/test/java/org/tron/program/LiteFullNodeToolTest.java | 1 + 2 files changed, 4 insertions(+) diff --git a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java index f2535c7caa5..40c371c58e0 100644 --- a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java +++ b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java @@ -39,6 +39,7 @@ import org.tron.tool.litefullnode.iterator.DBIterator; @Slf4j(topic = "tool") +@Deprecated public class LiteFullNodeTool { private static final long START_TIME = System.currentTimeMillis() / 1000; @@ -556,6 +557,8 @@ private void run(Args argv) { * 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(); diff --git a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java index c23ab213006..d1da0bf00d8 100644 --- a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java +++ b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java @@ -24,6 +24,7 @@ import org.tron.tool.litefullnode.LiteFullNodeTool; @Slf4j +@Deprecated public class LiteFullNodeToolTest { private TronApplicationContext context; From c6239406be14e775dc3a0e1e08c7ad29a44dd30a Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Sun, 8 Oct 2023 19:53:39 +0800 Subject: [PATCH 0906/1197] feat(db/trans-cache): verify cached files with crc32c (#5523) --- .../org/tron/core/db2/common/TxCacheDB.java | 86 +++++++++++++++---- 1 file changed, 70 insertions(+), 16 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java index 8e5a2ee6787..3da6cd9475a 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java @@ -2,9 +2,13 @@ import com.google.common.hash.BloomFilter; import com.google.common.hash.Funnels; +import com.google.common.hash.HashCode; +import com.google.common.hash.Hashing; +import com.google.common.io.ByteSource; import com.google.common.primitives.Longs; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; @@ -18,6 +22,7 @@ import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.Properties; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; @@ -79,6 +84,8 @@ public class TxCacheDB implements DB, Flusher { private final Path cacheFile0; private final Path cacheFile1; + private String crc32c0; + private String crc32c1; private final Path cacheProperties; private final Path cacheDir; private AtomicBoolean isValid = new AtomicBoolean(false); @@ -281,13 +288,18 @@ private boolean recovery() { CompletableFuture tk1 = loadProperties.thenApplyAsync( v -> recovery(1, this.cacheFile1)); - return CompletableFuture.allOf(tk0, tk1).thenApply(v -> { - logger.info("recovery bloomFilters success."); - return true; - }).exceptionally(this::handleException).join(); + try { + return CompletableFuture.allOf(tk0, tk1).thenApply(v -> { + logger.info("recovery bloomFilters success."); + return true; + }).exceptionally(this::handleException).join(); + } finally { + clearCrc32c(); + } } private boolean recovery(int index, Path file) { + checkCrc32c(index, file); try (InputStream in = new BufferedInputStream(Files.newInputStream(file, StandardOpenOption.READ, StandardOpenOption.DELETE_ON_CLOSE))) { logger.info("recovery bloomFilter[{}] from file.", index); @@ -329,24 +341,38 @@ private void dump() { () -> dump(0, this.cacheFile0)); CompletableFuture task1 = CompletableFuture.runAsync( () -> dump(1, this.cacheFile1)); - CompletableFuture.allOf(task0, task1).thenRun(() -> { - writeProperties(); - logger.info("dump bloomFilters done."); - - }).exceptionally(e -> { - logger.info("dump bloomFilters to file failed. {}", e.getMessage()); - return null; - }).join(); + try { + CompletableFuture.allOf(task0, task1).thenRun(() -> { + writeProperties(); + logger.info("dump bloomFilters done."); + }).exceptionally(e -> { + logger.info("dump bloomFilters to file failed. {}", e.getMessage()); + return null; + }).join(); + } finally { + clearCrc32c(); + } } private void dump(int index, Path file) { + logger.info("dump bloomFilters[{}] to file.", index); + long start = System.currentTimeMillis(); try (OutputStream out = new BufferedOutputStream(Files.newOutputStream(file))) { - logger.info("dump bloomFilters[{}] to file.", index); - long start = System.currentTimeMillis(); bloomFilters[index].writeTo(out); - logger.info("dump bloomFilters[{}] to file done,filter: {}, filter-fpp: {}, cost {} ms.", + } catch (Exception e) { + throw new RuntimeException(e); + } + try { + String crc32c = getCrc32c(file); + if (index == 0) { + this.crc32c0 = crc32c; + } else { + this.crc32c1 = crc32c; + } + logger.info("dump bloomFilters[{}] to file done,filter: {}, filter-fpp: {}, " + + "crc32c: {}, cost {} ms.", index, bloomFilters[index].approximateElementCount(), bloomFilters[index].expectedFpp(), - System.currentTimeMillis() - start); + crc32c, System.currentTimeMillis() - start); } catch (Exception e) { throw new RuntimeException(e); } @@ -367,6 +393,8 @@ private boolean loadProperties() { String.format("currentBlockNum not match. filter: %d, db: %d", currentBlockNum, currentBlockNumFromDB)); } + this.crc32c0 = properties.getProperty("crc32c0"); + this.crc32c1 = properties.getProperty("crc32c1"); logger.info("filterStartBlock: {}, currentBlockNum: {}, currentFilterIndex: {}, load done.", filterStartBlock, currentBlockNum, currentFilterIndex); return true; @@ -382,6 +410,8 @@ private void writeProperties() { properties.setProperty("filterStartBlock", String.valueOf(filterStartBlock)); properties.setProperty("currentBlockNum", String.valueOf(currentBlockNum)); properties.setProperty("currentFilterIndex", String.valueOf(currentFilterIndex)); + properties.setProperty("crc32c0", this.crc32c0); + properties.setProperty("crc32c1", this.crc32c1); properties.store(w, "Generated by the application. PLEASE DO NOT EDIT! "); logger.info("filterStartBlock: {}, currentBlockNum: {}, currentFilterIndex: {}, write done.", filterStartBlock, currentBlockNum, currentFilterIndex); @@ -390,6 +420,30 @@ private void writeProperties() { } } + private String getCrc32c(Path file) throws IOException { + ByteSource byteSource = com.google.common.io.Files.asByteSource(file.toFile()); + HashCode hc = byteSource.hash(Hashing.crc32c()); + return hc.toString(); + } + + private void checkCrc32c(int index, Path file) { + try { + String actual = getCrc32c(file); + String expect = index == 0 ? this.crc32c0 : this.crc32c1; + if (!Objects.equals(actual, expect)) { + throw new IllegalStateException("crc32c not match. index: " + index + ", expect: " + expect + + ", actual: " + actual); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private void clearCrc32c() { + this.crc32c0 = null; + this.crc32c1 = null; + } + @Override public TxCacheDB newInstance() { return new TxCacheDB(name, recentTransactionStore, dynamicPropertiesStore); From 94e1a8488261c46215b9089808d216c6c042efc7 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Wed, 11 Oct 2023 10:21:00 +0800 Subject: [PATCH 0907/1197] test(db): fix org.iq80.leveldb.DBException: Closed (#5528) --- .../src/test/java/org/tron/common/BaseTest.java | 13 +++++++++++++ .../org/tron/core/db/NullifierStoreTest.java | 3 --- .../java/org/tron/core/db/TxCacheDBTest.java | 4 ---- .../filter/HttpApiAccessFilterTest.java | 11 ++++------- .../filter/LiteFnQueryHttpFilterTest.java | 11 ++++------- .../http/TriggerSmartContractServletTest.java | 3 --- .../java/org/tron/program/SupplementTest.java | 17 +++-------------- 7 files changed, 24 insertions(+), 38 deletions(-) diff --git a/framework/src/test/java/org/tron/common/BaseTest.java b/framework/src/test/java/org/tron/common/BaseTest.java index c17d10d6ae4..959a746a141 100644 --- a/framework/src/test/java/org/tron/common/BaseTest.java +++ b/framework/src/test/java/org/tron/common/BaseTest.java @@ -2,6 +2,7 @@ import com.google.protobuf.ByteString; import java.io.IOException; +import javax.annotation.PostConstruct; import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; @@ -12,6 +13,7 @@ import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.tron.common.application.Application; import org.tron.common.crypto.ECKey; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.Sha256Hash; @@ -37,6 +39,16 @@ public abstract class BaseTest { @Resource protected ChainBaseManager chainBaseManager; + @Resource + protected Application appT; + + private static Application appT1; + + + @PostConstruct + private void prepare() { + appT1 = appT; + } public static String dbPath() { try { @@ -49,6 +61,7 @@ public static String dbPath() { @AfterClass public static void destroy() { + appT1.shutdown(); Args.clearParam(); } diff --git a/framework/src/test/java/org/tron/core/db/NullifierStoreTest.java b/framework/src/test/java/org/tron/core/db/NullifierStoreTest.java index 96b2fc1a74d..6070182a5c1 100644 --- a/framework/src/test/java/org/tron/core/db/NullifierStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/NullifierStoreTest.java @@ -7,7 +7,6 @@ import org.junit.BeforeClass; import org.junit.Test; import org.tron.common.BaseTest; -import org.tron.common.application.Application; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.BytesCapsule; @@ -21,8 +20,6 @@ public class NullifierStoreTest extends BaseTest { private static final byte[] TRX_TWO = randomBytes(32); private static final byte[] TRX_TWO_NEW = randomBytes(32); @Resource - public Application AppT; - @Resource private NullifierStore nullifierStore; private static BytesCapsule nullifier1; private static BytesCapsule nullifier2; diff --git a/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java b/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java index 1b49228a968..55557cf51b5 100644 --- a/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java +++ b/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java @@ -1,11 +1,9 @@ package org.tron.core.db; -import javax.annotation.Resource; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.tron.common.BaseTest; -import org.tron.common.application.Application; import org.tron.common.utils.ByteArray; import org.tron.core.Constant; import org.tron.core.capsule.BytesCapsule; @@ -13,8 +11,6 @@ import org.tron.keystore.Wallet; public class TxCacheDBTest extends BaseTest { - @Resource - private Application appT; /** * Init data. diff --git a/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java b/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java index 6423252560b..5f883fc8c07 100644 --- a/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java @@ -17,7 +17,6 @@ import org.junit.Before; import org.junit.Test; import org.tron.common.BaseTest; -import org.tron.common.application.Application; import org.tron.common.parameter.CommonParameter; import org.tron.core.Constant; import org.tron.core.config.args.Args; @@ -27,8 +26,6 @@ public class HttpApiAccessFilterTest extends BaseTest { - @Resource - private Application appTest; @Resource private FullNodeHttpApiService httpApiService; @Resource @@ -49,10 +46,10 @@ public class HttpApiAccessFilterTest extends BaseTest { */ @Before public void init() { - appTest.addService(httpApiService); - appTest.addService(httpApiOnSolidityService); - appTest.addService(httpApiOnPBFTService); - appTest.startup(); + appT.addService(httpApiService); + appT.addService(httpApiOnSolidityService); + appT.addService(httpApiOnPBFTService); + appT.startup(); } @Test diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java index 38e0b054c2b..5fd4711273e 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java @@ -19,7 +19,6 @@ import org.junit.Before; import org.junit.Test; import org.tron.common.BaseTest; -import org.tron.common.application.Application; import org.tron.core.Constant; import org.tron.core.config.args.Args; import org.tron.core.services.http.FullNodeHttpApiService; @@ -32,8 +31,6 @@ public class LiteFnQueryHttpFilterTest extends BaseTest { private final String ip = "127.0.0.1"; private int fullHttpPort; @Resource - private Application appTest; - @Resource private FullNodeHttpApiService httpApiService; @Resource private HttpApiOnSolidityService httpApiOnSolidityService; @@ -51,10 +48,10 @@ public class LiteFnQueryHttpFilterTest extends BaseTest { */ @Before public void init() { - appTest.addService(httpApiService); - appTest.addService(httpApiOnSolidityService); - appTest.addService(httpApiOnPBFTService); - appTest.startup(); + appT.addService(httpApiService); + appT.addService(httpApiOnSolidityService); + appT.addService(httpApiOnPBFTService); + appT.startup(); } @Test diff --git a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java index 384c0cada6c..f363b7fbefc 100644 --- a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java @@ -11,7 +11,6 @@ import org.junit.Test; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.tron.common.BaseTest; -import org.tron.common.application.Application; import org.tron.common.utils.ByteArray; import org.tron.common.utils.client.Configuration; import org.tron.common.utils.client.utils.HttpMethed; @@ -35,8 +34,6 @@ public class TriggerSmartContractServletTest extends BaseTest { @Resource private FullNodeHttpApiService httpApiService; - @Resource - private Application appT; @BeforeClass public static void init() throws Exception { diff --git a/framework/src/test/java/org/tron/program/SupplementTest.java b/framework/src/test/java/org/tron/program/SupplementTest.java index f370a871006..ffa6b14f46b 100644 --- a/framework/src/test/java/org/tron/program/SupplementTest.java +++ b/framework/src/test/java/org/tron/program/SupplementTest.java @@ -9,15 +9,10 @@ import java.math.BigInteger; import javax.annotation.Resource; import org.junit.BeforeClass; -import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.junit.runner.RunWith; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.tron.common.BaseTest; import org.tron.common.config.DbBackupConfig; import org.tron.common.entity.PeerInfo; import org.tron.common.utils.CompactEncoder; @@ -26,19 +21,13 @@ import org.tron.core.Constant; import org.tron.core.capsule.StorageRowCapsule; import org.tron.core.capsule.utils.RLP; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.services.http.HttpSelfFormatFieldName; import org.tron.core.store.StorageRowStore; import org.tron.keystore.WalletUtils; -@RunWith(SpringJUnit4ClassRunner.class) -@DirtiesContext -@ContextConfiguration(classes = {DefaultConfig.class}) -public class SupplementTest { +public class SupplementTest extends BaseTest { - @ClassRule - public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); private static String dbPath; @Resource @@ -49,7 +38,7 @@ public class SupplementTest { @BeforeClass public static void init() throws IOException { - dbPath = temporaryFolder.newFolder().toString(); + dbPath = dbPath(); Args.setParam(new String[]{"--output-directory", dbPath, "--debug"}, Constant.TEST_CONF); } From 283230aa9c4426c5b8ea2d5853e80e121a1eb155 Mon Sep 17 00:00:00 2001 From: Brown Jiang <317787106@qq.com> Date: Wed, 11 Oct 2023 15:20:54 +0800 Subject: [PATCH 0908/1197] test(api): add test cases of Wallet (#5442) * add wallet test --- .../src/main/java/org/tron/core/Wallet.java | 2 +- .../org/tron/common/config/args/ArgsTest.java | 17 + .../java/org/tron/core/ShieldWalletTest.java | 383 ++++++++++++++++++ .../test/java/org/tron/core/WalletTest.java | 92 ++++- .../tron/core/db/TransactionExpireTest.java | 49 ++- .../core/zksnark/MerkleContainerTest.java | 1 + .../core/zksnark/ShieldedReceiveTest.java | 16 +- 7 files changed, 537 insertions(+), 23 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/ShieldWalletTest.java diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index fdea2a555a8..0865e202974 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -4100,7 +4100,7 @@ private void checkBigIntegerRange(BigInteger in) throws ContractValidateExceptio } } - private byte[] getShieldedContractScalingFactor(byte[] contractAddress) + public byte[] getShieldedContractScalingFactor(byte[] contractAddress) throws ContractExeException { String methodSign = "scalingFactor()"; byte[] selector = new byte[4]; diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index 8e2e1accb4a..b95d47bfa39 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -1,6 +1,9 @@ package org.tron.common.config.args; +import com.beust.jcommander.JCommander; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -46,4 +49,18 @@ public void testConfig() { Assert.assertEquals(rateLimiter.getHttpMap().size(), 1); Assert.assertEquals(rateLimiter.getRpcMap().size(), 0); } + + @Test + public void testHelpMessage() { + JCommander jCommander = JCommander.newBuilder().addObject(Args.PARAMETER).build(); + Method method; + try { + method = Args.class.getDeclaredMethod("printVersion"); + method.setAccessible(true); + method.invoke(Args.class); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + Assert.fail(); + } + Args.printHelp(jCommander); + } } diff --git a/framework/src/test/java/org/tron/core/ShieldWalletTest.java b/framework/src/test/java/org/tron/core/ShieldWalletTest.java new file mode 100644 index 00000000000..5bc2a31c9d0 --- /dev/null +++ b/framework/src/test/java/org/tron/core/ShieldWalletTest.java @@ -0,0 +1,383 @@ +package org.tron.core; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.tron.core.zen.ZksnarkInitService.librustzcashInitZksnarkParams; + +import java.math.BigInteger; +import javax.annotation.Resource; +import org.junit.Assert; +import org.junit.Test; +import org.tron.api.GrpcAPI.PrivateParameters; +import org.tron.api.GrpcAPI.PrivateParametersWithoutAsk; +import org.tron.api.GrpcAPI.PrivateShieldedTRC20Parameters; +import org.tron.api.GrpcAPI.PrivateShieldedTRC20ParametersWithoutAsk; +import org.tron.api.GrpcAPI.ShieldedAddressInfo; +import org.tron.api.GrpcAPI.ShieldedTRC20Parameters; +import org.tron.common.BaseTest; +import org.tron.common.utils.ByteArray; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.exception.ContractExeException; +import org.tron.core.services.http.JsonFormat; +import org.tron.core.services.http.JsonFormat.ParseException; + + +public class ShieldWalletTest extends BaseTest { + + @Resource + private Wallet wallet; + + static { + Args.setParam(new String[] {"-d", dbPath()}, Constant.TEST_CONF); + } + + @Test + public void testCreateShieldedTransaction1() { + librustzcashInitZksnarkParams(); + String transactionStr1 = new String(ByteArray.fromHexString( + "0x7b0a20202020227472616e73706172656e745f66726f6d5f61646472657373223a202234433930413" + + "73241433344414546324536383932343545463430303839443634314345414337373433323433414233" + + "31333136303030222c0a202020202266726f6d5f616d6f756e74223a203130303030303030302c0a202" + + "02020226f766b223a223566643165636466643637396232616461333337623235306231303234373138" + + "6633316439636237316361653664666363396131613637626134373033643863222c0a2020202022736" + + "869656c6465645f7265636569766573223a205b0a20202020202020207b0a2020202020202020202020" + + "20226e6f7465223a207b0a202020202020202020202020202020202276616c7565223a2039303030303" + + "030302c0a20202020202020202020202020202020227061796d656e745f61646472657373223a20227a" + + "74726f6e3179616d336a723270746d79706c707030747978387974707a36736a64786364657a306a333" + + "36673636d656a76376e6863346171336d766b687275726772777671653932636a6c68356b3367222c0a" + + "202020202020202020202020202020202272636d223a202237323330353362636266656364663564613" + + "63663313861623033373634373665663330386336316237616265383931623263303165393033626362" + + "3837633065222c0a20202020202020202020202020202020226d656d6f223a20223232323232220a202" + + "0202020202020202020207d0a20202020202020207d0a202020205d0a7d")); + PrivateParameters.Builder builder1 = PrivateParameters.newBuilder(); + try { + JsonFormat.merge(transactionStr1, builder1, false); + } catch (ParseException e) { + Assert.fail(); + } + + try { + TransactionCapsule transactionCapsule = wallet.createShieldedTransaction(builder1.build()); + Assert.assertNotNull(transactionCapsule); + } catch (Exception e) { + Assert.fail(); + } + } + + @Test + public void testCreateShieldedTransaction2() { + librustzcashInitZksnarkParams(); + String transactionStr2 = new String(ByteArray.fromHexString( + "7b0a202020202261736b223a20223938666430333136376632333437623534643737323338343137663" + + "6373038643537323939643938376362613838353564653037626532346236316464653064222c0a2020" + + "2020226e736b223a2022643063623330653764306634653435333535363134333463303462616339316" + + "63039643230653664366234363361623031626534663531386230363839653039222c0a20202020226f" + + "766b223a202235666431656364666436373962326164613333376232353062313032343731386633316" + + "439636237316361653664666363396131613637626134373033643863222c0a2020202022736869656c" + + "6465645f7370656e6473223a205b0a20202020202020207b200a090909226e6f7465223a207b0a20202" + + "0202020202020202020202020202276616c7565223a2039303030303030302c0a202020202020202020" + + "20202020202020227061796d656e745f61646472657373223a20227a74726f6e3179616d336a7232707" + + "46d79706c707030747978387974707a36736a64786364657a306a33336673636d656a76376e68633461" + + "71336d766b687275726772777671653932636a6c68356b3367222c0a202020202020202020202020202" + + "020202272636d223a202237323330353362636266656364663564613636633138616230333736343736" + + "656633303863363162376162653839316232633031653930336263623837633065222c0a20202020202" + + "020202020202020202020226d656d6f223a20223232323232220a2020202020202020202020207d2c0a" + + "20202020202020202020202022616c706861223a2022323936656531633532633933663734306433616" + + "23162373265366463663561626231643666343965643865646236663334656633666462366537366335" + + "353063222c0a20202020202020202020202022766f7563686572223a207b0a202020202020202020202" + + "0202274726565223a207b0a20202020202020202020202020202020226c656674223a207b0a20202020" + + "2020202020202020202020202020202022636f6e74656e74223a2022346565653236313963343862613" + + "26264303235303235363330636430313362616361663337653961323162323965333938393735623763" + + "653864363436613265220a202020202020202020202020202020207d2c0a20202020202020202020202" + + "020202020227269676874223a207b0a202020202020202020202020202020202020202022636f6e7465" + + "6e74223a202235333863326139313537313333356334666138383866396234336239666164643931633" + + "334666366326265666130333931353932613564366535343539623537220a2020202020202020202020" + + "20202020207d0a2020202020202020202020207d2c0a202020202020202020202020227274223a20226" + + "33539376436633235663131623938613638303034343838393138386638613934616237393265353432" + + "32313461386636346632363334616535346535353531220a20202020202020207d2c0a2020202020202" + + "020202020202270617468223a2022323032306232656564303331643464366134663032613039376638" + + "30623534636331353431643431363363366236663539373166383862366534316433356335333831343" + + "23031323933356631346236373635303962383165623439656632356633393236396564373233303932" + + "33386234633134353830333534346236343664636136326432306531663334623033346434613363643" + + "23835353765323930376562663939306339313866363465636235306139346630316436666461356361" + + "35633765663732323032386537623834316463626334376363656236396437636238643934323435666" + + "23763623262613361376136626331386631336639343566376462643665326132306135313232633038" + + "66663963313631643963613666633436323037333339366337643764333865386565343863646233626" + + "56137653232333031333465643661323064326531363432633961343632323239323839653562306533" + + "62376639303038653033303163626239333338356565306532316461323534353037336362353832303" + + "13664363235323936383937316138336461383532316436353338326536316630313736363436643737" + + "31633931353238653332373665653435333833653461323066656530653532383032636230633436623" + + "16562346433373663363236393766343735396636633839313766613335323537313230326664373738" + + "66643731323230346336393337643738663432363835663834623433616433623762303066383132383" + + "53636326638356336613638656631316436326164316133656530383530323030373639353537626336" + + "38326231626633303836343666643062323265363438653862396539386635376532396635616634306" + + "63665646238333365326334393230303865656162306331336162643630363965363331303139376266" + + "38306639633165613664653738666431396362616532346434613532306536636633303233323038643" + + "56661343365356131306431313630356163373433306261316635643831666231623638643239613634" + + "30343035373637373439653834313532373637333230366163613834343864383236336535343764356" + + "66632393530653265643338333965393938643331636263366163396664353762633630303262313539" + + "32313632306364316338646266366533616363376138303433396263343936326366323562396463653" + + "76338393666336135626437303830336663356130653333636630303230366564623136643031393037" + + "62373539393737643736353064616437653365633034396166316133643837353338306236393763383" + + "63263396563356435316332303165613636373566393535316565623964666161613932343762633938" + + "35383237306433643361346335616661373137376139383464356564316265323435313230643661636" + + "46564663935663630386530396661353366623433646364303939303437353732366335313331323130" + + "63396535636165616239376630653634326632306264373462323561616362393233373861383731626" + + "63237643232356366633236626163613334346131656133356664643934353130663364313537303832" + + "63323031623737646163346432346662373235386333633532383730346335393433306236333037313" + + "86265633438363432313833373032316366373564616236353132306563363737313134633237323036" + + "66356465626331633165643636663935653262313838356461356237626533643733366231646539383" + + "53739343733303438323034373737633837373661336231653639623733613632666137303166613466" + + "37613632383264396165653263376136623832653739333764373038316332336332306261343962363" + + "53966626430623733333432313165613661396439646631383563373537653730616138316461353632" + + "66623931326238346634396263653732323034336666353435376631336239323662363164663535326" + + "43465343032656536646331343633663939613533356639613731333433393236346435623631366232" + + "30376239396162646333373330393931636339323734373237643764383264323863623739346564626" + + "33730333462346630303533666637633462363830343434323064366336333961633234623436626431" + + "39333431633931623133666463616233313538316464616637663134313133333661323731663364306" + + "16135323831333230386163396366396333393165336664343238393164323732333861383161386135" + + "63316433613732623162636265613863663434613538636537333839363133323039313264383262326" + + "33262636132333166373165666366363137333766626630613038626566613034313632313561656566" + + "35336538626236643233333930613230653131306465363563393037623964656134616530626438336" + + "13462306135316265613137353634366136346331326234633966393331623263623331623439323064" + + "38323833333836656632656630376562646262343338336331326137333961393533613464366530643" + + "66662313133396134303336643639336266626236633230666665396663303366313862313736633939" + + "38383036343339666630626238616431393361666462323762326363626338383835363931366464383" + + "03465333432303831376465333661623264353766656230373736333462636137373831396338653062" + + "64323938633034663666656430653661383363633133353663613135353230346565653236313963343" + + "86261326264303235303235363330636430313362616361663337653961323162323965333938393735" + + "62376365386436343661326530313030303030303030303030303030220a20202020202020207d0a202" + + "020205d2c0a2020202022736869656c6465645f7265636569766573223a205b0a20202020202020207b" + + "0a202020202020202020202020226e6f7465223a207b0a2020202020202020202020202020202022766" + + "16c7565223a2038303030303030302c0a20202020202020202020202020202020227061796d656e745f" + + "61646472657373223a20227a74726f6e31356b657a70736d71303568336d616a6e6c7a6834306772796" + + "a6d676d3630783265686a7967633771387336376d6c753835376375747177613334386e76706765706e" + + "35786b336735727278222c0a202020202020202020202020202020202272636d223a202237323330353" + + "36263626665636466356461363663313861623033373634373665663330386336316237616265383931" + + "6232633031653930336263623837633065222c0a20202020202020202020202020202020226d656d6f2" + + "23a2022313131313131313131220a2020202020202020202020207d0a20202020202020207d0a202020" + + "205d2c0a202020202276697369626c6522203a20747275650a7d")); + PrivateParameters.Builder builder2 = PrivateParameters.newBuilder(); + try { + JsonFormat.merge(transactionStr2, builder2, true); + } catch (ParseException e) { + Assert.fail(); + } + + try { + TransactionCapsule transactionCapsule = wallet.createShieldedTransaction(builder2.build()); + Assert.assertNotNull(transactionCapsule); + } catch (Exception e) { + Assert.fail(); + } + } + + @Test + public void testCreateShieldedTransactionWithoutSpendAuthSig() { + librustzcashInitZksnarkParams(); + String transactionStr3 = new String(ByteArray.fromHexString( + "7b0a2020202022616b223a2022373161643638633466353035373464356164333735343863626538363" + + "63031663732393662393161306362303535353733313462373830383437323730326465222c0a202020" + + "20226e736b223a202264306362333065376430663465343533353536313433346330346261633931663" + + "039643230653664366234363361623031626534663531386230363839653039222c0a20202020226f76" + + "6b223a20223566643165636466643637396232616461333337623235306231303234373138663331643" + + "9636237316361653664666363396131613637626134373033643863222c0a2020202022736869656c64" + + "65645f7370656e6473223a205b0a20202020202020207b0a202020202020202020202020226e6f74652" + + "23a207b0a202020202020202020202020202020202276616c7565223a2039303030303030302c0a2020" + + "2020202020202020202020202020227061796d656e745f61646472657373223a20227a74726f6e31796" + + "16d336a723270746d79706c707030747978387974707a36736a64786364657a306a33336673636d656a" + + "76376e6863346171336d766b687275726772777671653932636a6c68356b3367222c0a2020202020202" + + "02020202020202020202272636d223a2022373233303533626362666563646635646136366331386162" + + "30333736343736656633303863363162376162653839316232633031653930336263623837633065222" + + "c0a20202020202020202020202020202020226d656d6f223a20223232323232220a2020202020202020" + + "202020207d2c0a20202020202020202020202022616c706861223a20223239366565316335326339336" + + "63734306433616231623732653664636635616262316436663439656438656462366633346566336664" + + "62366537366335353063222c0a20202020202020202020202022766f7563686572223a207b0a2020202" + + "02020202020202020202020202274726565223a207b0a20202020202020202020202020202020202020" + + "20226c656674223a207b0a20202020202020202020202020202020202020202020202022636f6e74656" + + "e74223a2022346565653236313963343862613262643032353032353633306364303133626163616633" + + "37653961323162323965333938393735623763653864363436613265220a20202020202020202020202" + + "020202020202020207d2c0a2020202020202020202020202020202020202020227269676874223a207b" + + "0a20202020202020202020202020202020202020202020202022636f6e74656e74223a2022353338633" + + "26139313537313333356334666138383866396234336239666164643931633334666366326265666130" + + "333931353932613564366535343539623537220a20202020202020202020202020202020202020207d0" + + "a202020202020202020202020202020207d2c0a20202020202020202020202020202020227274223a20" + + "22633539376436633235663131623938613638303034343838393138386638613934616237393265353" + + "43232313461386636346632363334616535346535353531220a2020202020202020202020207d2c0a20" + + "20202020202020202020202270617468223a20223230323062326565643033316434643661346630326" + + "13039376638306235346363313534316434313633633662366635393731663838623665343164333563" + + "35333831343230313239333566313462363736353039623831656234396566323566333932363965643" + + "73233303932333862346331343538303335343462363436646361363264323065316633346230333464" + + "34613363643238353537653239303765626639393063393138663634656362353061393466303164366" + + "66461356361356337656637323230323865376238343164636263343763636562363964376362386439" + + "34323435666237636232626133613761366263313866313366393435663764626436653261323061353" + + "13232633038666639633136316439636136666334363230373333393663376437643338653865653438" + + "63646233626561376532323330313334656436613230643265313634326339613436323232393238396" + + "53562306533623766393030386530333031636262393333383565653065323164613235343530373363" + + "62353832303136643632353239363839373161383364613835323164363533383265363166303137363" + + "63436643737316339313532386533323736656534353338336534613230666565306535323830326362" + + "30633436623165623464333736633632363937663437353966366338393137666133353235373132303" + + "26664373738666437313232303463363933376437386634323638356638346234336164336237623030" + + "66383132383536363266383563366136386566313164363261643161336565303835303230303736393" + + "53537626336383262316266333038363436666430623232653634386538623965393866353765323966" + + "35616634306636656462383333653263343932303038656561623063313361626436303639653633313" + + "03139376266383066396331656136646537386664313963626165323464346135323065366366333032" + + "33323038643566613433653561313064313136303561633734333062613166356438316662316236386" + + "43239613634303430353736373734396538343135323736373332303661636138343438643832363365" + + "35343764356666323935306532656433383339653939386433316362633661633966643537626336303" + + "03262313539323136323063643163386462663665336163633761383034333962633439363263663235" + + "62396463653763383936663361356264373038303366633561306533336366303032303665646231366" + + "43031393037623735393937376437363530646164376533656330343961663161336438373533383062" + + "36393763383632633965633564353163323031656136363735663935353165656239646661616139323" + + "43762633938353832373064336433613463356166613731373761393834643565643162653234353132" + + "30643661636465646639356636303865303966613533666234336463643039393034373537323663353" + + "13331323130633965356361656162393766306536343266323062643734623235616163623932333738" + + "61383731626632376432323563666332366261636133343461316561333566646439343531306633643" + + "13537303832633230316237376461633464323466623732353863336335323837303463353934333062" + + "36333037313862656334383634323138333730323163663735646162363531323065633637373131346" + + "33237323036663564656263316331656436366639356532623138383564613562376265336437333662" + + "31646539383537393437333034383230343737376338373736613362316536396237336136326661373" + + "03166613466376136323832643961656532633761366238326537393337643730383163323363323062" + + "61343962363539666264306237333334323131656136613964396466313835633735376537306161383" + + "16461353632666239313262383466343962636537323230343366663534353766313362393236623631" + + "64663535326434653430326565366463313436336639396135333566396137313334333932363464356" + + "23631366232303762393961626463333733303939316363393237343732376437643832643238636237" + + "39346564626337303334623466303035336666376334623638303434343230643663363339616332346" + + "23436626431393334316339316231336664636162333135383164646166376631343131333336613237" + + "31663364306161353238313332303861633963663963333931653366643432383931643237323338613" + + "83161386135633164336137326231626362656138636634346135386365373338393631333230393132" + + "64383262326332626361323331663731656663663631373337666266306130386265666130343136323" + + "13561656566353365386262366432333339306132306531313064653635633930376239646561346165" + + "30626438336134623061353162656131373536343661363463313262346339663933316232636233316" + + "23439323064383238333338366566326566303765626462623433383363313261373339613935336134" + + "64366530643666623131333961343033366436393362666262366332306666653966633033663138623" + + "13736633939383830363433396666306262386164313933616664623237623263636263383838353639" + + "31366464383034653334323038313764653336616232643537666562303737363334626361373738313" + + "96338653062643239386330346636666564306536613833636331333536636131353532303465656532" + + "36313963343862613262643032353032353633306364303133626163616633376539613231623239653" + + "3393839373562376365386436343661326530313030303030303030303030303030220a202020202020" + + "20207d0a202020205d2c0a2020202022736869656c6465645f7265636569766573223a205b0a2020202" + + "0202020207b0a202020202020202020202020226e6f7465223a207b0a20202020202020202020202020" + + "2020202276616c7565223a2038303030303030302c0a202020202020202020202020202020202270617" + + "96d656e745f61646472657373223a20227a74726f6e31356b657a70736d71303568336d616a6e6c7a68" + + "34306772796a6d676d3630783265686a7967633771387336376d6c753835376375747177613334386e7" + + "6706765706e35786b336735727278222c0a202020202020202020202020202020202272636d223a2022" + + "37323330353362636266656364663564613636633138616230333736343736656633303863363162376" + + "162653839316232633031653930336263623837633065222c0a20202020202020202020202020202020" + + "226d656d6f223a2022313131313131313131220a2020202020202020202020207d0a202020202020202" + + "07d0a202020205d2c0a202020202276697369626c65223a20747275650a7d")); + PrivateParametersWithoutAsk.Builder builder3 = PrivateParametersWithoutAsk.newBuilder(); + try { + JsonFormat.merge(transactionStr3, builder3, false); + } catch (ParseException e) { + Assert.fail(); + } + + try { + TransactionCapsule transactionCapsule = wallet.createShieldedTransactionWithoutSpendAuthSig( + builder3.build()); + Assert.assertNotNull(transactionCapsule); + } catch (Exception e) { + Assert.fail(); + } + } + + @Test + public void testGetNewShieldedAddress() { + librustzcashInitZksnarkParams(); + try { + ShieldedAddressInfo shieldedAddressInfo = wallet.getNewShieldedAddress(); + Assert.assertNotNull(shieldedAddressInfo); + } catch (Exception e) { + Assert.fail(); + } + } + + @Test + public void testCreateShieldedContractParameters() throws ContractExeException { + librustzcashInitZksnarkParams(); + Args.getInstance().setFullNodeAllowShieldedTransactionArgs(true); + Wallet wallet1 = spy(new Wallet()); + + doReturn(BigInteger.valueOf(1).toByteArray()) + .when(wallet1).getShieldedContractScalingFactor( + ByteArray.fromHexString("4144007979359ECAC395BBD3CEF8060D3DF2DC3F01")); + String parameter = new String(ByteArray.fromHexString( + "7b0a202020202261736b223a22633235313365396533303834393439333262643832653063653533363" + + "63264313734323164393062373261383437316130613132623835353261333336653032222c0a202020" + + "20226e736b223a223463366266336464346130363433643230623632386637653435393830633565313" + + "8376630376135316436663365383661616631616239313663303765623064222c0a20202020226f766b" + + "223a2231376135386439613530353864613665343263613132636432383964306136616131363962393" + + "236633138653139626361353138623864366638363734653433222c0a202020202266726f6d5f616d6f" + + "756e74223a22313030222c0a2020202022736869656c6465645f7265636569766573223a5b0a2020202" + + "0202020207b0a202020202020202020202020226e6f7465223a7b0a2020202020202020202020202020" + + "20202276616c7565223a3130302c0a20202020202020202020202020202020227061796d656e745f616" + + "46472657373223a227a74726f6e317939397536656a71656e757076666b70356736713679716b703061" + + "34346334386374613064643567656a7471613476323768716132636768667664786e6d6e65683671717" + + "1303366613735222c0a202020202020202020202020202020202272636d223a22313662366635653430" + + "34343461623765656162313161653636313363323766333531313739373165666138376237313536306" + + "235383133383239633933393064220a2020202020202020202020207d0a20202020202020207d0a2020" + + "20205d2c0a2020202022736869656c6465645f54524332305f636f6e74726163745f616464726573732" + + "23a22343134343030373937393335394543414333393542424433434546383036304433444632444333" + + "463031220a7d")); + PrivateShieldedTRC20Parameters.Builder builder = PrivateShieldedTRC20Parameters.newBuilder(); + try { + JsonFormat.merge(parameter, builder, false); + } catch (ParseException e) { + Assert.fail(); + } + + try { + ShieldedTRC20Parameters shieldedTRC20Parameters = wallet1.createShieldedContractParameters( + builder.build()); + Assert.assertNotNull(shieldedTRC20Parameters); + } catch (Exception e) { + Assert.fail(); + } + } + + @Test + public void testCreateShieldedContractParametersWithoutAsk() throws ContractExeException { + librustzcashInitZksnarkParams(); + Args.getInstance().setFullNodeAllowShieldedTransactionArgs(true); + + Wallet wallet1 = spy(new Wallet()); + doReturn(BigInteger.valueOf(1).toByteArray()) + .when(wallet1).getShieldedContractScalingFactor( + ByteArray.fromHexString("4144007979359ECAC395BBD3CEF8060D3DF2DC3F01")); + String parameter = new String(ByteArray.fromHexString( + "7b0a2020202022616b223a2230656261373361343865323934396561356461613133626365663466646" + + "633613561613966336232363830363763663831313233333938613833386665336363222c0a20202020" + + "226e736b223a22346336626633646434613036343364323062363238663765343539383063356531383" + + "76630376135316436663365383661616631616239313663303765623064222c0a20202020226f766b22" + + "3a223137613538643961353035386461366534326361313263643238396430613661613136396239323" + + "6633138653139626361353138623864366638363734653433222c0a202020202266726f6d5f616d6f75" + + "6e74223a22313030222c0a2020202022736869656c6465645f7265636569766573223a5b0a202020202" + + "02020207b0a202020202020202020202020226e6f7465223a7b0a202020202020202020202020202020" + + "202276616c7565223a3130302c0a20202020202020202020202020202020227061796d656e745f61646" + + "472657373223a227a74726f6e317939397536656a71656e757076666b70356736713679716b70306134" + + "346334386374613064643567656a7471613476323768716132636768667664786e6d6e6568367171713" + + "03366613735222c0a202020202020202020202020202020202272636d223a2231366236663565343034" + + "34346162376565616231316165363631336332376633353131373937316566613837623731353630623" + + "5383133383239633933393064220a2020202020202020202020207d0a20202020202020207d0a202020" + + "205d2c0a2020202022736869656c6465645f54524332305f636f6e74726163745f61646472657373223" + + "a2234313434303037393739333539454341433339354242443343454638303630443344463244433346" + + "3031220a7d")); + PrivateShieldedTRC20ParametersWithoutAsk.Builder builder = + PrivateShieldedTRC20ParametersWithoutAsk.newBuilder(); + try { + JsonFormat.merge(parameter, builder, false); + } catch (ParseException e) { + Assert.fail(); + } + + try { + ShieldedTRC20Parameters shieldedTRC20Parameters = + wallet1.createShieldedContractParametersWithoutAsk(builder.build()); + Assert.assertNotNull(shieldedTRC20Parameters); + } catch (Exception e) { + Assert.fail(); + } + } +} diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 7461ff44c08..357a2d2ca08 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -39,6 +39,7 @@ import org.junit.Ignore; import org.junit.Test; import org.tron.api.GrpcAPI; +import org.tron.api.GrpcAPI.AccountNetMessage; import org.tron.api.GrpcAPI.AssetIssueList; import org.tron.api.GrpcAPI.BlockList; import org.tron.api.GrpcAPI.ExchangeList; @@ -130,6 +131,7 @@ public class WalletTest extends BaseTest { private static Transaction transaction4; private static Transaction transaction5; private static AssetIssueCapsule Asset1; + private static AssetIssueCapsule Asset2; private static final String OWNER_ADDRESS; private static final String RECEIVER_ADDRESS; @@ -235,11 +237,11 @@ private void addTransactionInfoToStore(Transaction transaction) { private static Transaction getBuildTransaction( TransferContract transferContract, long transactionTimestamp, long refBlockNum) { return Transaction.newBuilder().setRawData( - Transaction.raw.newBuilder().setTimestamp(transactionTimestamp) - .setRefBlockNum(refBlockNum) - .addContract( - Contract.newBuilder().setType(ContractType.TransferContract) - .setParameter(Any.pack(transferContract)).build()).build()) + Transaction.raw.newBuilder().setTimestamp(transactionTimestamp) + .setRefBlockNum(refBlockNum) + .addContract( + Contract.newBuilder().setType(ContractType.TransferContract) + .setParameter(Any.pack(transferContract)).build()).build()) .build(); } @@ -288,18 +290,26 @@ private void addBlockToStore(Block block) { private static Block getBuildBlock(long timestamp, long num, long witnessId, String witnessAddress, Transaction transaction, Transaction transactionNext) { return Block.newBuilder().setBlockHeader(BlockHeader.newBuilder().setRawData( - raw.newBuilder().setTimestamp(timestamp).setNumber(num).setWitnessId(witnessId) - .setWitnessAddress(ByteString.copyFrom(ByteArray.fromHexString(witnessAddress))) - .build()).build()).addTransactions(transaction).addTransactions(transactionNext) + raw.newBuilder().setTimestamp(timestamp).setNumber(num).setWitnessId(witnessId) + .setWitnessAddress(ByteString.copyFrom(ByteArray.fromHexString(witnessAddress))) + .build()).build()).addTransactions(transaction).addTransactions(transactionNext) .build(); } private void buildAssetIssue() { AssetIssueContract.Builder builder = AssetIssueContract.newBuilder(); + builder.setOwnerAddress(ByteString.copyFromUtf8("Address1")); builder.setName(ByteString.copyFromUtf8("Asset1")); Asset1 = new AssetIssueCapsule(builder.build()); chainBaseManager.getAssetIssueStore().put(Asset1.createDbKey(), Asset1); + + AssetIssueContract.Builder builder2 = AssetIssueContract.newBuilder(); + builder2.setOwnerAddress(ByteString.copyFromUtf8("Address2")); + builder2.setName(ByteString.copyFromUtf8("Asset2")); + builder2.setId("id2"); + Asset2 = new AssetIssueCapsule(builder2.build()); + chainBaseManager.getAssetIssueV2Store().put(Asset2.getId().getBytes(), Asset2); } private void buildProposal() { @@ -499,6 +509,52 @@ public void getPaginatedAssetIssueList() { } } + @Test + public void testGetAssetIssueByAccount() { + buildAssetIssue(); + // + AssetIssueList assetIssueList = wallet.getAssetIssueByAccount( + ByteString.copyFromUtf8("Address1")); + Assert.assertEquals(1, assetIssueList.getAssetIssueCount()); + } + + @Test + public void testGetAssetIssueList() { + buildAssetIssue(); + // + AssetIssueList assetIssueList = wallet.getAssetIssueList(); + Assert.assertEquals(1, assetIssueList.getAssetIssueCount()); + } + + @Test + public void testGetAssetIssueListByName() { + buildAssetIssue(); + // + AssetIssueList assetIssueList = wallet.getAssetIssueListByName( + ByteString.copyFromUtf8("Asset1")); + Assert.assertEquals(1, assetIssueList.getAssetIssueCount()); + } + + @Test + public void testGetAssetIssueById() { + buildAssetIssue(); + // + AssetIssueContract assetIssueContract = wallet.getAssetIssueById("id2"); + Assert.assertNotNull(assetIssueContract); + } + + @Test + public void testGetAccountNet() { + ByteString addressByte = ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)); + AccountCapsule accountCapsule = + new AccountCapsule(Protocol.Account.newBuilder().setAddress(addressByte).build()); + accountCapsule.setBalance(1000_000_000L); + dbManager.getChainBaseManager().getAccountStore() + .put(accountCapsule.createDbKey(), accountCapsule); + AccountNetMessage accountNetMessage = wallet.getAccountNet(addressByte); + Assert.assertNotNull(accountNetMessage); + } + @Test public void getPaginatedProposalList() { buildProposal(); @@ -686,8 +742,8 @@ public void testGetDelegatedResourceAccountIndex() { } private Any getDelegatedContractForCpu(String ownerAddress, String receiverAddress, - long frozenBalance, - long duration) { + long frozenBalance, + long duration) { return Any.pack( BalanceContract.FreezeBalanceContract.newBuilder() .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) @@ -723,13 +779,13 @@ private void freezeCpuForOwner() { } private Any getDelegateContractForBandwidth(String ownerAddress, String receiveAddress, - long unfreezeBalance) { + long unfreezeBalance) { return getLockedDelegateContractForBandwidth(ownerAddress, receiveAddress, unfreezeBalance, false); } private Any getLockedDelegateContractForBandwidth(String ownerAddress, String receiveAddress, - long unfreezeBalance, boolean lock) { + long unfreezeBalance, boolean lock) { return Any.pack(BalanceContract.DelegateResourceContract.newBuilder() .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) .setReceiverAddress(ByteString.copyFrom(ByteArray.fromHexString(receiveAddress))) @@ -949,7 +1005,7 @@ public void testGetAccountById() { chainBaseManager.getAccountIdIndexStore().put(ownerCapsule); Protocol.Account account = wallet.getAccountById( Protocol.Account.newBuilder().setAccountId(ByteString.copyFromUtf8("1001")).build()); - Assert.assertEquals(ownerCapsule.getAddress(),account.getAddress()); + Assert.assertEquals(ownerCapsule.getAddress(), account.getAddress()); } @Test @@ -967,18 +1023,18 @@ public void testGetAssetIssueByName() { String assetName = "My_asset"; String id = "10001"; AssetIssueCapsule assetCapsule = new AssetIssueCapsule(ByteArray.fromHexString(OWNER_ADDRESS), - id,assetName,"abbr", 1_000_000_000_000L,6); + id, assetName, "abbr", 1_000_000_000_000L, 6); chainBaseManager.getAssetIssueStore().put(assetCapsule.createDbKey(), assetCapsule); chainBaseManager.getAssetIssueV2Store().put(assetCapsule.createDbV2Key(), assetCapsule); try { AssetIssueContract assetIssue = wallet.getAssetIssueByName(ByteString.copyFromUtf8(assetName)); - Assert.assertEquals(ByteString.copyFromUtf8(assetName),assetIssue.getName()); - Assert.assertEquals(id,assetIssue.getId()); + Assert.assertEquals(ByteString.copyFromUtf8(assetName), assetIssue.getName()); + Assert.assertEquals(id, assetIssue.getId()); chainBaseManager.getDynamicPropertiesStore().saveAllowSameTokenName(1); assetIssue = wallet.getAssetIssueByName(ByteString.copyFromUtf8(assetName)); - Assert.assertEquals(ByteString.copyFromUtf8(assetName),assetIssue.getName()); - Assert.assertEquals(id,assetIssue.getId()); + Assert.assertEquals(ByteString.copyFromUtf8(assetName), assetIssue.getName()); + Assert.assertEquals(id, assetIssue.getId()); } catch (NonUniqueObjectException e) { Assert.fail(e.getMessage()); } diff --git a/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java b/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java index 843e54d38a8..5243405b7e6 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java @@ -3,7 +3,6 @@ import com.google.protobuf.ByteString; import java.io.IOException; import java.util.Arrays; - import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; @@ -13,6 +12,7 @@ import org.junit.rules.TemporaryFolder; import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.Return.response_code; +import org.tron.api.GrpcAPI.TransactionApprovedList; import org.tron.common.application.TronApplicationContext; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; @@ -21,10 +21,13 @@ import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; +import org.tron.protos.Protocol; +import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.contract.BalanceContract.TransferContract; @@ -97,4 +100,48 @@ public void testExpireTransaction() { GrpcAPI.Return result = wallet.broadcastTransaction(transactionCapsule.getInstance()); Assert.assertEquals(response_code.TRANSACTION_EXPIRATION_ERROR, result.getCode()); } + + @Test + public void testTransactionApprovedList() { + byte[] address = Args.getLocalWitnesses() + .getWitnessAccountAddress(CommonParameter.getInstance().isECKeyCryptoEngine()); + TransferContract transferContract = TransferContract.newBuilder() + .setAmount(1L) + .setOwnerAddress(ByteString.copyFrom(address)) + .setToAddress(ByteString.copyFrom(ByteArray.fromHexString( + (Wallet.getAddressPreFixString() + "A389132D6639FBDA4FBC8B659264E6B7C90DB086")))) + .build(); + TransactionCapsule transactionCapsule = + new TransactionCapsule(transferContract, ContractType.TransferContract); + transactionCapsule.setReference(blockCapsule.getNum(), blockCapsule.getBlockId().getBytes()); + transactionCapsule.sign(ByteArray.fromHexString(Args.getLocalWitnesses().getPrivateKey())); + + TransactionApprovedList transactionApprovedList = wallet.getTransactionApprovedList( + transactionCapsule.getInstance()); + Assert.assertTrue( + transactionApprovedList.getResult().getMessage().contains("Account does not exist!")); + + ByteString addressByte = ByteString.copyFrom(address); + AccountCapsule accountCapsule = + new AccountCapsule(Protocol.Account.newBuilder().setAddress(addressByte).build()); + accountCapsule.setBalance(1000_000_000L); + dbManager.getChainBaseManager().getAccountStore() + .put(accountCapsule.createDbKey(), accountCapsule); + transactionApprovedList = wallet.getTransactionApprovedList(transactionCapsule.getInstance()); + Assert.assertEquals("", transactionApprovedList.getResult().getMessage()); + + byte[] randomSig = org.tron.keystore.Wallet.generateRandomBytes(64); + Transaction transaction = transactionCapsule.getInstance().toBuilder().clearSignature() + .addSignature(ByteString.copyFrom(randomSig)).build(); + transactionApprovedList = wallet.getTransactionApprovedList(transaction); + Assert.assertEquals(TransactionApprovedList.Result.response_code.SIGNATURE_FORMAT_ERROR, + transactionApprovedList.getResult().getCode()); + + randomSig = org.tron.keystore.Wallet.generateRandomBytes(65); + transaction = transactionCapsule.getInstance().toBuilder().clearSignature() + .addSignature(ByteString.copyFrom(randomSig)).build(); + transactionApprovedList = wallet.getTransactionApprovedList(transaction); + Assert.assertEquals(TransactionApprovedList.Result.response_code.COMPUTE_ADDRESS_ERROR, + transactionApprovedList.getResult().getCode()); + } } diff --git a/framework/src/test/java/org/tron/core/zksnark/MerkleContainerTest.java b/framework/src/test/java/org/tron/core/zksnark/MerkleContainerTest.java index 6216ab41f3f..183a504ee35 100644 --- a/framework/src/test/java/org/tron/core/zksnark/MerkleContainerTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/MerkleContainerTest.java @@ -23,6 +23,7 @@ import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.contract.ShieldContract.IncrementalMerkleTree; import org.tron.protos.contract.ShieldContract.IncrementalMerkleVoucherInfo; import org.tron.protos.contract.ShieldContract.OutputPoint; import org.tron.protos.contract.ShieldContract.OutputPointInfo; diff --git a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java index 819bfede557..c963a92bb9d 100755 --- a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java @@ -17,6 +17,7 @@ import org.junit.Test; import org.tron.api.GrpcAPI.BytesMessage; import org.tron.api.GrpcAPI.DecryptNotes; +import org.tron.api.GrpcAPI.DecryptNotesMarked; import org.tron.api.GrpcAPI.ReceiveNote; import org.tron.api.GrpcAPI.SpendAuthSigParameters; import org.tron.api.GrpcAPI.TransactionExtention; @@ -2377,8 +2378,8 @@ public void pushSameSkAndScanAndSpend() throws Exception { chainBaseManager.addWitness(ByteString.copyFrom(witnessAddress)); //sometimes generate block failed, try several times. - - Block block = getSignedBlock(witnessCapsule.getAddress(), 0, privateKey); + long time = System.currentTimeMillis(); + Block block = getSignedBlock(witnessCapsule.getAddress(), time, privateKey); dbManager.pushBlock(new BlockCapsule(block)); //create transactions @@ -2426,17 +2427,25 @@ public void pushSameSkAndScanAndSpend() throws Exception { Thread.sleep(500); //package transaction to block - block = getSignedBlock(witnessCapsule.getAddress(), 0, privateKey); + block = getSignedBlock(witnessCapsule.getAddress(), time + 3000, privateKey); dbManager.pushBlock(new BlockCapsule(block)); BlockCapsule blockCapsule3 = new BlockCapsule(wallet.getNowBlock()); Assert.assertEquals("blocknum != 2", 2, blockCapsule3.getNum()); + block = getSignedBlock(witnessCapsule.getAddress(), time + 6000, privateKey); + dbManager.pushBlock(new BlockCapsule(block)); + // scan note by ivk byte[] receiverIvk = incomingViewingKey.getValue(); DecryptNotes notes1 = wallet.scanNoteByIvk(0, 100, receiverIvk); Assert.assertEquals(2, notes1.getNoteTxsCount()); + // scan note by ivk and mark + DecryptNotesMarked notes3 = wallet.scanAndMarkNoteByIvk(0, 100, receiverIvk, + fullViewingKey.getAk(), fullViewingKey.getNk()); + Assert.assertEquals(2, notes3.getNoteTxsCount()); + // scan note by ovk DecryptNotes notes2 = wallet.scanNoteByOvk(0, 100, senderOvk); Assert.assertEquals(2, notes2.getNoteTxsCount()); @@ -2452,6 +2461,7 @@ public void pushSameSkAndScanAndSpend() throws Exception { outPointBuild.setIndex(i); request.addOutPoints(outPointBuild.build()); } + request.setBlockNum(1); IncrementalMerkleVoucherInfo merkleVoucherInfo = wallet .getMerkleTreeVoucherInfo(request.build()); From e987efb94812bfed6097ee102262711d0bd47eb6 Mon Sep 17 00:00:00 2001 From: Brown Jiang <317787106@qq.com> Date: Thu, 12 Oct 2023 16:55:44 +0800 Subject: [PATCH 0909/1197] feat(net): fix bug of getting head block concurrently (#5532) * fix bug of getting head block concurrently --- .../messagehandler/SyncBlockChainMsgHandler.java | 16 ++++++++-------- .../SyncBlockChainMsgHandlerTest.java | 9 +++++---- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java index 3c83bc51e47..958ebfe5561 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java @@ -37,8 +37,8 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep long remainNum = 0; List summaryChainIds = syncBlockChainMessage.getBlockIds(); - - LinkedList blockIds = getLostBlockIds(summaryChainIds); + BlockId headID = tronNetDelegate.getHeadBlockId(); + LinkedList blockIds = getLostBlockIds(summaryChainIds, headID); if (blockIds.size() == 0) { logger.warn("Can't get lost block Ids"); @@ -48,7 +48,7 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep peer.setNeedSyncFromUs(false); } else { peer.setNeedSyncFromUs(true); - remainNum = tronNetDelegate.getHeadBlockId().getNum() - blockIds.peekLast().getNum(); + remainNum = headID.getNum() - blockIds.peekLast().getNum(); } peer.setLastSyncBlockId(blockIds.peekLast()); @@ -85,14 +85,15 @@ private boolean check(PeerConnection peer, SyncBlockChainMessage msg) throws P2p return true; } - private LinkedList getLostBlockIds(List blockIds) throws P2pException { + private LinkedList getLostBlockIds(List blockIds, BlockId headID) + throws P2pException { BlockId unForkId = getUnForkId(blockIds); - LinkedList ids = getBlockIds(unForkId.getNum()); + LinkedList ids = getBlockIds(unForkId.getNum(), headID); if (ids.isEmpty() || !unForkId.equals(ids.peekFirst())) { unForkId = getUnForkId(blockIds); - ids = getBlockIds(unForkId.getNum()); + ids = getBlockIds(unForkId.getNum(), headID); } return ids; @@ -114,8 +115,7 @@ private BlockId getUnForkId(List blockIds) throws P2pException { return unForkId; } - private LinkedList getBlockIds(Long unForkNum) throws P2pException { - BlockId headID = tronNetDelegate.getHeadBlockId(); + private LinkedList getBlockIds(Long unForkNum, BlockId headID) throws P2pException { long headNum = headID.getNum(); long len = Math.min(headNum, unForkNum + NetConstants.SYNC_FETCH_BATCH_NUM); diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java index 25108e19b70..d4ad32dd34f 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java @@ -15,6 +15,7 @@ import org.tron.common.application.TronApplicationContext; import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.exception.P2pException; @@ -68,18 +69,18 @@ public void testProcessMessage() throws Exception { Assert.assertTrue(!f); Method method1 = handler.getClass().getDeclaredMethod( - "getLostBlockIds", List.class); + "getLostBlockIds", List.class, BlockId.class); method1.setAccessible(true); try { - method1.invoke(handler, blockIds); + method1.invoke(handler, blockIds, new BlockCapsule.BlockId()); } catch (InvocationTargetException e) { Assert.assertEquals("unForkId is null", e.getTargetException().getMessage()); } Method method2 = handler.getClass().getDeclaredMethod( - "getBlockIds", Long.class); + "getBlockIds", Long.class, BlockId.class); method2.setAccessible(true); - List list = (List) method2.invoke(handler, 0L); + List list = (List) method2.invoke(handler, 0L, new BlockCapsule.BlockId()); Assert.assertEquals(1, list.size()); } From 2ab26773fb1aa5de33e9f0f33ee10333833683f0 Mon Sep 17 00:00:00 2001 From: lxcmyf Date: Mon, 16 Oct 2023 11:50:04 +0800 Subject: [PATCH 0910/1197] fix(api):rollback due to insufficient compatibility (#5537) --- .../http/GetAssetIssueListServlet.java | 30 ++++------------- .../services/http/GetNowBlockServlet.java | 33 +++++-------------- .../core/services/http/ListNodesServlet.java | 30 ++++------------- .../services/http/ListProposalsServlet.java | 30 ++++------------- 4 files changed, 29 insertions(+), 94 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/http/GetAssetIssueListServlet.java b/framework/src/main/java/org/tron/core/services/http/GetAssetIssueListServlet.java index 01ec00dbef3..3968554a671 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetAssetIssueListServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetAssetIssueListServlet.java @@ -1,8 +1,5 @@ package org.tron.core.services.http; -import static org.tron.core.services.http.Util.existVisible; - -import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; @@ -22,7 +19,12 @@ public class GetAssetIssueListServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { boolean visible = Util.getVisible(request); - response(response, visible); + AssetIssueList reply = wallet.getAssetIssueList(); + if (reply != null) { + response.getWriter().println(JsonFormat.printToString(reply, visible)); + } else { + response.getWriter().println("{}"); + } } catch (Exception e) { Util.processError(e, response); } @@ -30,24 +32,6 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { - try { - PostParams params = PostParams.getPostParams(request); - boolean visible = Util.getVisible(request); - if (!existVisible(request)) { - visible = params.isVisible(); - } - response(response, visible); - } catch (Exception e) { - Util.processError(e, response); - } - } - - private void response(HttpServletResponse response, boolean visible) throws IOException { - AssetIssueList reply = wallet.getAssetIssueList(); - if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply, visible)); - } else { - response.getWriter().println("{}"); - } + doGet(request, response); } } diff --git a/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java b/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java index 78e7178cfe3..56e01d557f5 100644 --- a/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java @@ -1,9 +1,5 @@ package org.tron.core.services.http; -import static org.tron.core.services.http.Util.existVisible; -import static org.tron.core.services.http.Util.getVisible; - -import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; @@ -22,8 +18,13 @@ public class GetNowBlockServlet extends RateLimiterServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - boolean visible = getVisible(request); - response(response, visible); + boolean visible = Util.getVisible(request); + Block reply = wallet.getNowBlock(); + if (reply != null) { + response.getWriter().println(Util.printBlock(reply, visible)); + } else { + response.getWriter().println("{}"); + } } catch (Exception e) { Util.processError(e, response); } @@ -31,24 +32,6 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { - try { - PostParams params = PostParams.getPostParams(request); - boolean visible = getVisible(request); - if (!existVisible(request)) { - visible = params.isVisible(); - } - response(response, visible); - } catch (Exception e) { - Util.processError(e, response); - } - } - - private void response(HttpServletResponse response, boolean visible) throws IOException { - Block reply = wallet.getNowBlock(); - if (reply != null) { - response.getWriter().println(Util.printBlock(reply, visible)); - } else { - response.getWriter().println("{}"); - } + doGet(request, response); } } \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/services/http/ListNodesServlet.java b/framework/src/main/java/org/tron/core/services/http/ListNodesServlet.java index fb0b877832b..6b7b2b251a8 100644 --- a/framework/src/main/java/org/tron/core/services/http/ListNodesServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/ListNodesServlet.java @@ -1,8 +1,5 @@ package org.tron.core.services.http; -import static org.tron.core.services.http.Util.existVisible; - -import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; @@ -22,7 +19,12 @@ public class ListNodesServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { boolean visible = Util.getVisible(request); - response(response, visible); + NodeList reply = wallet.listNodes(); + if (reply != null) { + response.getWriter().println(JsonFormat.printToString(reply, visible)); + } else { + response.getWriter().println("{}"); + } } catch (Exception e) { Util.processError(e, response); } @@ -30,24 +32,6 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { - try { - PostParams params = PostParams.getPostParams(request); - boolean visible = Util.getVisible(request); - if (!existVisible(request)) { - visible = params.isVisible(); - } - response(response, visible); - } catch (Exception e) { - Util.processError(e, response); - } - } - - private void response(HttpServletResponse response, boolean visible) throws IOException { - NodeList reply = wallet.listNodes(); - if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply, visible)); - } else { - response.getWriter().println("{}"); - } + doGet(request, response); } } diff --git a/framework/src/main/java/org/tron/core/services/http/ListProposalsServlet.java b/framework/src/main/java/org/tron/core/services/http/ListProposalsServlet.java index e309963edda..a3b26d4afc6 100644 --- a/framework/src/main/java/org/tron/core/services/http/ListProposalsServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/ListProposalsServlet.java @@ -1,8 +1,5 @@ package org.tron.core.services.http; -import static org.tron.core.services.http.Util.existVisible; - -import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; @@ -22,7 +19,12 @@ public class ListProposalsServlet extends RateLimiterServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { boolean visible = Util.getVisible(request); - response(response, visible); + ProposalList reply = wallet.getProposalList(); + if (reply != null) { + response.getWriter().println(JsonFormat.printToString(reply, visible)); + } else { + response.getWriter().println("{}"); + } } catch (Exception e) { Util.processError(e, response); } @@ -30,24 +32,6 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { - try { - PostParams params = PostParams.getPostParams(request); - boolean visible = Util.getVisible(request); - if (!existVisible(request)) { - visible = params.isVisible(); - } - response(response, visible); - } catch (Exception e) { - Util.processError(e, response); - } - } - - private void response(HttpServletResponse response, boolean visible) throws IOException { - ProposalList reply = wallet.getProposalList(); - if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply, visible)); - } else { - response.getWriter().println("{}"); - } + doGet(request, response); } } From 1cb7f2cf7f8ac1086c3dd0824bbcaecf9d3339ea Mon Sep 17 00:00:00 2001 From: liukai Date: Mon, 16 Oct 2023 11:53:09 +0800 Subject: [PATCH 0911/1197] feat(version): update version --- framework/src/main/java/org/tron/program/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index b0837871d5d..54eb5d3de6e 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -4,7 +4,7 @@ public class Version { public static final String VERSION_NAME = "GreatVoyage-v4.7.1.1-343-g959e0199de"; public static final String VERSION_CODE = "18031"; - private static final String VERSION = "4.7.2"; + private static final String VERSION = "4.7.3"; public static String getVersion() { return VERSION; From 87db52abccb5288f1d18ec6be16a5685a1068044 Mon Sep 17 00:00:00 2001 From: Brown Jiang <317787106@qq.com> Date: Mon, 16 Oct 2023 18:36:57 +0800 Subject: [PATCH 0912/1197] update libp2p version to release 2.1.0 (#5539) --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 8cca0853dc5..0431316c009 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v2.0.3',{ + compile group: 'io.github.tronprotocol', name: 'libp2p', version: '2.1.0',{ exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' From d1f0ff3d3ce3bc0075899fed7f661500e759a117 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Wed, 18 Oct 2023 06:26:14 +0800 Subject: [PATCH 0913/1197] add switch for transaction cache initialization optimization (#5543) --- .../main/java/org/tron/core/db2/common/TxCacheDB.java | 9 +++++++++ .../main/java/org/tron/core/config/args/Storage.java | 10 ++++++++++ .../src/main/java/org/tron/core/config/args/Args.java | 2 ++ framework/src/main/resources/config.conf | 2 ++ framework/src/test/resources/config-test.conf | 2 ++ 5 files changed, 25 insertions(+) diff --git a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java index 3da6cd9475a..9d2409685c9 100644 --- a/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java +++ b/chainbase/src/main/java/org/tron/core/db2/common/TxCacheDB.java @@ -89,6 +89,7 @@ public class TxCacheDB implements DB, Flusher { private final Path cacheProperties; private final Path cacheDir; private AtomicBoolean isValid = new AtomicBoolean(false); + private boolean txCacheInitOptimization; @Getter @Setter @@ -128,6 +129,8 @@ public TxCacheDB(String name, RecentTransactionStore recentTransactionStore, this.cacheFile0 = Paths.get(cacheDir.toString(), "bloomFilters_0"); this.cacheFile1 = Paths.get(cacheDir.toString(), "bloomFilters_1"); this.cacheProperties = Paths.get(cacheDir.toString(), "txCache.properties"); + this.txCacheInitOptimization = CommonParameter.getInstance() + .getStorage().isTxCacheInitOptimization(); } @@ -280,6 +283,12 @@ public void reset() { } private boolean recovery() { + if (!txCacheInitOptimization) { + logger.info("txCache init optimization is disabled, skip fast recovery mode."); + logger.info("If you want fast recovery mode," + + " please set `storage.txCache.initOptimization = true` in config.conf."); + return false; + } FileUtil.createDirIfNotExists(this.cacheDir.toString()); logger.info("recovery bloomFilters start."); CompletableFuture loadProperties = CompletableFuture.supplyAsync(this::loadProperties); diff --git a/common/src/main/java/org/tron/core/config/args/Storage.java b/common/src/main/java/org/tron/core/config/args/Storage.java index 778d4d0141c..22dc239c167 100644 --- a/common/src/main/java/org/tron/core/config/args/Storage.java +++ b/common/src/main/java/org/tron/core/config/args/Storage.java @@ -77,6 +77,7 @@ public class Storage { private static final String CHECKPOINT_SYNC_KEY = "storage.checkpoint.sync"; private static final String CACHE_STRATEGIES = "storage.cache.strategies"; + public static final String TX_CACHE_INIT_OPTIMIZATION = "storage.txCache.initOptimization"; /** * Default values of directory @@ -145,6 +146,10 @@ public class Storage { @Setter private int estimatedBlockTransactions; + @Getter + @Setter + private boolean txCacheInitOptimization = false; + // second cache private final Map cacheStrategies = Maps.newConcurrentMap(); @@ -235,6 +240,11 @@ public static int getEstimatedTransactionsFromConfig(final Config config) { return estimatedTransactions; } + public static boolean getTxCacheInitOptimizationFromConfig(final Config config) { + return config.hasPath(TX_CACHE_INIT_OPTIMIZATION) + && config.getBoolean(TX_CACHE_INIT_OPTIMIZATION); + } + public void setCacheStrategies(Config config) { if (config.hasPath(CACHE_STRATEGIES)) { diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index b3a6821f3b2..5c2d76afbb1 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -520,6 +520,8 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.storage.setEstimatedBlockTransactions( Storage.getEstimatedTransactionsFromConfig(config)); + PARAMETER.storage.setTxCacheInitOptimization( + Storage.getTxCacheInitOptimizationFromConfig(config)); PARAMETER.storage.setMaxFlushCount(Storage.getSnapshotMaxFlushCountFromConfig(config)); PARAMETER.storage.setDefaultDbOptions(config); diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index c049bbbebc7..91f108b74a9 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -95,6 +95,8 @@ storage { # the estimated number of block transactions (default 1000, min 100, max 10000). # so the total number of cached transactions is 65536 * txCache.estimatedTransactions # txCache.estimatedTransactions = 1000 + # if true, transaction cache initialization will be faster. default false + # txCache.initOptimization = true } node.discovery = { diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index 236502d3360..cf7ca5e2f42 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -66,6 +66,8 @@ storage { # the estimated number of block transactions (default 1000, min 100, max 10000). # so the total number of cached transactions is 65536 * txCache.estimatedTransactions txCache.estimatedTransactions = 50 + # if true, transaction cache initialization will be faster. default false + txCache.initOptimization = true } From 5bafc0ce1f606e254568329f8157be64e47bc976 Mon Sep 17 00:00:00 2001 From: allen <56535423+jwrct@users.noreply.github.com> Date: Wed, 25 Oct 2023 02:47:06 -0500 Subject: [PATCH 0914/1197] Add block height check when processing PBFT messages (#5548) * fix(pbft): Add block height check when processing PBFT messages --- .../tron/common/parameter/CommonParameter.java | 3 +++ .../src/main/java/org/tron/core/Constant.java | 1 + .../java/org/tron/core/config/args/Args.java | 5 +++++ .../java/org/tron/core/net/TronNetDelegate.java | 8 ++++++++ .../core/net/messagehandler/PbftMsgHandler.java | 17 +++++++++++++++++ 5 files changed, 34 insertions(+) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 8c4cd23f09a..f8f6e6c5edb 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -518,6 +518,9 @@ public class CommonParameter { public int pBFTHttpPort; @Getter @Setter + public long pBFTExpireNum; + @Getter + @Setter public long oldSolidityBlockNum = -1; @Getter/**/ diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 54ff30d9e65..ba867793b41 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -303,6 +303,7 @@ public class Constant { public static final String SEED_NODE_IP_LIST = "seed.node.ip.list"; public static final String NODE_METRICS_ENABLE = "node.metricsEnable"; public static final String COMMITTEE_ALLOW_PBFT = "committee.allowPBFT"; + public static final String COMMITTEE_PBFT_EXPIRE_NUM = "committee.pBFTExpireNum"; public static final String NODE_AGREE_NODE_COUNT = "node.agreeNodeCount"; public static final String COMMITTEE_ALLOW_TRANSACTION_FEE_POOL = "committee.allowTransactionFeePool"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 5c2d76afbb1..75140dd5f54 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -149,6 +149,7 @@ public static void clearParam() { PARAMETER.fullNodeHttpPort = 0; PARAMETER.solidityHttpPort = 0; PARAMETER.pBFTHttpPort = 0; + PARAMETER.pBFTExpireNum = 20; PARAMETER.jsonRpcHttpFullNodePort = 0; PARAMETER.jsonRpcHttpSolidityPort = 0; PARAMETER.jsonRpcHttpPBFTPort = 0; @@ -974,6 +975,10 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.COMMITTEE_ALLOW_PBFT) ? config .getLong(Constant.COMMITTEE_ALLOW_PBFT) : 0; + PARAMETER.pBFTExpireNum = + config.hasPath(Constant.COMMITTEE_PBFT_EXPIRE_NUM) ? config + .getLong(Constant.COMMITTEE_PBFT_EXPIRE_NUM) : 20; + PARAMETER.agreeNodeCount = config.hasPath(Constant.NODE_AGREE_NODE_COUNT) ? config .getInt(Constant.NODE_AGREE_NODE_COUNT) : MAX_ACTIVE_WITNESS_NUM * 2 / 3 + 1; PARAMETER.agreeNodeCount = PARAMETER.agreeNodeCount > MAX_ACTIVE_WITNESS_NUM diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index 4d22f98d680..5d09e67908d 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -357,4 +357,12 @@ public Object getForkLock() { return dbManager.getForkLock(); } + public long getNextMaintenanceTime() { + return chainBaseManager.getDynamicPropertiesStore().getNextMaintenanceTime(); + } + + public long getMaintenanceTimeInterval() { + return chainBaseManager.getDynamicPropertiesStore().getMaintenanceTimeInterval(); + } + } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/PbftMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/PbftMsgHandler.java index 44eed8d1c2f..4e4cc858898 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/PbftMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/PbftMsgHandler.java @@ -11,9 +11,12 @@ import org.tron.consensus.pbft.PbftManager; import org.tron.consensus.pbft.message.PbftBaseMessage; import org.tron.consensus.pbft.message.PbftMessage; +import org.tron.core.config.args.Args; import org.tron.core.exception.P2pException; +import org.tron.core.net.TronNetDelegate; import org.tron.core.net.TronNetService; import org.tron.core.net.peer.PeerConnection; +import org.tron.protos.Protocol.PBFTMessage.DataType; @Component public class PbftMsgHandler { @@ -26,10 +29,24 @@ public class PbftMsgHandler { @Autowired private PbftManager pbftManager; + @Autowired + private TronNetDelegate tronNetDelegate; + public void processMessage(PeerConnection peer, PbftMessage msg) throws Exception { if (Param.getInstance().getPbftInterface().isSyncing()) { return; } + if (msg.getDataType().equals(DataType.BLOCK) + && tronNetDelegate.getHeadBlockId().getNum() - msg.getNumber() + > Args.getInstance().getPBFTExpireNum()) { + return; + } + long currentEpoch = tronNetDelegate.getNextMaintenanceTime(); + long expireEpoch = 2 * tronNetDelegate.getMaintenanceTimeInterval(); + if (msg.getDataType().equals(DataType.SRL) + && currentEpoch - msg.getEpoch() > expireEpoch) { + return; + } msg.analyzeSignature(); String key = buildKey(msg); Lock lock = striped.get(key); From 381c52c5830ab60db02dd7a94d6e8c0dbe0ffef5 Mon Sep 17 00:00:00 2001 From: liukai Date: Wed, 25 Oct 2023 19:31:35 +0800 Subject: [PATCH 0915/1197] update a new version. version name:GreatVoyage-v4.7.2-140-g9d13f9cb69,version code:18173 --- framework/src/main/java/org/tron/program/Version.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 54eb5d3de6e..4740daa9d5e 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,8 +2,8 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.7.1.1-343-g959e0199de"; - public static final String VERSION_CODE = "18031"; + public static final String VERSION_NAME = "GreatVoyage-v4.7.2-140-g9d13f9cb69"; + public static final String VERSION_CODE = "18173"; private static final String VERSION = "4.7.3"; public static String getVersion() { From 1ec48e1666c0977b7a39d611744086c414cd2b6c Mon Sep 17 00:00:00 2001 From: lurais <107600021+lurais@users.noreply.github.com> Date: Thu, 26 Oct 2023 15:54:38 +0800 Subject: [PATCH 0916/1197] feat(test): add unit tests of framework module (#5534) Co-authored-by: morgan.peng --- .../core/capsule/utils/DecodeResultTest.java | 28 +++++++ .../tron/core/capsule/utils/RLPListTest.java | 26 +++++++ .../services/jsonrpc/BlockResultTest.java | 46 ++++++++++++ .../services/jsonrpc/BuildArgumentsTest.java | 73 +++++++++++++++++++ .../services/jsonrpc/CallArgumentsTest.java | 47 ++++++++++++ .../jsonrpc/TransactionReceiptTest.java | 66 +++++++++++++++++ .../jsonrpc/TransactionResultTest.java | 59 +++++++++++++++ 7 files changed, 345 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/capsule/utils/DecodeResultTest.java create mode 100644 framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java create mode 100644 framework/src/test/java/org/tron/core/services/jsonrpc/BlockResultTest.java create mode 100644 framework/src/test/java/org/tron/core/services/jsonrpc/BuildArgumentsTest.java create mode 100644 framework/src/test/java/org/tron/core/services/jsonrpc/CallArgumentsTest.java create mode 100644 framework/src/test/java/org/tron/core/services/jsonrpc/TransactionReceiptTest.java create mode 100644 framework/src/test/java/org/tron/core/services/jsonrpc/TransactionResultTest.java diff --git a/framework/src/test/java/org/tron/core/capsule/utils/DecodeResultTest.java b/framework/src/test/java/org/tron/core/capsule/utils/DecodeResultTest.java new file mode 100644 index 00000000000..008224f98a1 --- /dev/null +++ b/framework/src/test/java/org/tron/core/capsule/utils/DecodeResultTest.java @@ -0,0 +1,28 @@ +package org.tron.core.capsule.utils; + +import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; +import org.junit.Test; +import org.tron.common.utils.ByteUtil; + +public class DecodeResultTest { + + @Test + public void testConstruct() { + DecodeResult decodeResult = new DecodeResult(0, "decoded"); + Assert.assertEquals(decodeResult.getPos(), 0); + Assert.assertEquals(decodeResult.getDecoded(), "decoded"); + Assert.assertEquals(decodeResult.toString(), "decoded"); + } + + @Test + public void testToString() { + DecodeResult decodeResult = new DecodeResult(0, "decoded"); + Assert.assertEquals(decodeResult.toString(), "decoded"); + decodeResult = new DecodeResult(0, ByteUtil.intToBytes(1000)); + Assert.assertEquals(Hex.toHexString(ByteUtil.intToBytes(1000)), decodeResult.toString()); + Object[] decodedData = {"aa","bb"}; + decodeResult = new DecodeResult(0, decodedData); + Assert.assertEquals("aabb", decodeResult.toString()); + } +} diff --git a/framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java b/framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java new file mode 100644 index 00000000000..7d903591966 --- /dev/null +++ b/framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java @@ -0,0 +1,26 @@ +package org.tron.core.capsule.utils; + +import org.junit.Assert; +import org.junit.Test; + +public class RLPListTest { + + @Test + public void testRecursivePrint() { + RLPItem element = new RLPItem("rlpItem".getBytes()); + Assert.assertEquals(new String(element.getRLPData()), "rlpItem"); + RLPList.recursivePrint(element); + RLPList rlpList = new RLPList(); + rlpList.add(new RLPItem("rlpItem0".getBytes())); + RLPList.recursivePrint(rlpList); + Assert.assertThrows(RuntimeException.class, () -> RLPList.recursivePrint(null)); + } + + @Test + public void testGetRLPData() { + RLPList rlpList = new RLPList(); + rlpList.setRLPData("rlpData".getBytes()); + Assert.assertEquals(new String(rlpList.getRLPData()), "rlpData"); + } + +} diff --git a/framework/src/test/java/org/tron/core/services/jsonrpc/BlockResultTest.java b/framework/src/test/java/org/tron/core/services/jsonrpc/BlockResultTest.java new file mode 100644 index 00000000000..2cd619a499a --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/jsonrpc/BlockResultTest.java @@ -0,0 +1,46 @@ +package org.tron.core.services.jsonrpc; + +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.Wallet; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.services.jsonrpc.types.BlockResult; +import org.tron.protos.Protocol; + +public class BlockResultTest extends BaseTest { + + @Resource + private Wallet wallet; + + static { + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); + } + + @Test + public void testBlockResult() { + Protocol.Transaction.raw.Builder raw = Protocol.Transaction.raw.newBuilder(); + Protocol.Transaction.Contract.Builder contract = Protocol.Transaction.Contract.newBuilder(); + contract.setType(Protocol.Transaction.Contract.ContractType.UpdateBrokerageContract); + raw.addContract(contract.build()); + + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().setRawData(raw).build(); + BlockCapsule blockCapsule = new BlockCapsule(Protocol.Block.newBuilder().setBlockHeader( + Protocol.BlockHeader.newBuilder().setRawData(Protocol.BlockHeader.raw.newBuilder() + .setParentHash(ByteString.copyFrom(ByteArray.fromHexString( + "0304f784e4e7bae517bcab94c3e0c9214fb4ac7ff9d7d5a937d1f40031f87b82"))) + .setNumber(0))).addTransactions(transaction).build()); + + BlockResult blockResult = new BlockResult(blockCapsule.getInstance(),true, wallet); + Assert.assertEquals(blockResult.getHash(), + "0x000000000000000036393ced0658419d3c251bc14ffab8d10c8b0898451054fa"); + Assert.assertEquals(blockResult.getTransactions().length, 1); + Assert.assertEquals(blockResult.getGasUsed(),"0x0"); + } + +} diff --git a/framework/src/test/java/org/tron/core/services/jsonrpc/BuildArgumentsTest.java b/framework/src/test/java/org/tron/core/services/jsonrpc/BuildArgumentsTest.java new file mode 100644 index 00000000000..f9e264c515f --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/jsonrpc/BuildArgumentsTest.java @@ -0,0 +1,73 @@ +package org.tron.core.services.jsonrpc; + +import javax.annotation.Resource; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.BaseTest; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.config.args.Args; +import org.tron.core.exception.JsonRpcInvalidParamsException; +import org.tron.core.exception.JsonRpcInvalidRequestException; +import org.tron.core.services.jsonrpc.types.BuildArguments; +import org.tron.core.services.jsonrpc.types.CallArguments; +import org.tron.protos.Protocol; + +public class BuildArgumentsTest extends BaseTest { + + @Resource + private Wallet wallet; + + private BuildArguments buildArguments; + + static { + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); + } + + @Before + public void initBuildArgs() { + buildArguments = new BuildArguments( + "0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000001","0x10","0.01","0x100", + "","0",9L,10000L,"",10L, + 2000L,"args",1,"",true); + } + + + @Test + public void testBuildArgument() { + CallArguments callArguments = new CallArguments( + "0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000001","0x10","0.01","0x100", + "","0"); + BuildArguments buildArguments = new BuildArguments(callArguments); + Assert.assertEquals(buildArguments.getFrom(), + "0x0000000000000000000000000000000000000000"); + Assert.assertEquals(buildArguments.getTo(), + "0x0000000000000000000000000000000000000001"); + Assert.assertEquals(buildArguments.getGas(), "0x10"); + Assert.assertEquals(buildArguments.getGasPrice(), "0.01"); + } + + @Test + public void testGetContractType() + throws JsonRpcInvalidRequestException, JsonRpcInvalidParamsException { + Protocol.Transaction.Contract.ContractType contractType = + buildArguments.getContractType(wallet); + Assert.assertEquals(contractType, Protocol.Transaction.Contract.ContractType.TransferContract); + } + + @Test + public void testParseValue() throws JsonRpcInvalidParamsException { + long value = buildArguments.parseValue(); + Assert.assertEquals(value, 256L); + } + + @Test + public void testParseGas() throws JsonRpcInvalidParamsException { + long gas = buildArguments.parseGas(); + Assert.assertEquals(gas, 16L); + } + +} diff --git a/framework/src/test/java/org/tron/core/services/jsonrpc/CallArgumentsTest.java b/framework/src/test/java/org/tron/core/services/jsonrpc/CallArgumentsTest.java new file mode 100644 index 00000000000..19dd76e5e07 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/jsonrpc/CallArgumentsTest.java @@ -0,0 +1,47 @@ +package org.tron.core.services.jsonrpc; + +import javax.annotation.Resource; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.BaseTest; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.config.args.Args; +import org.tron.core.exception.JsonRpcInvalidParamsException; +import org.tron.core.exception.JsonRpcInvalidRequestException; +import org.tron.core.services.jsonrpc.types.CallArguments; +import org.tron.protos.Protocol; + +public class CallArgumentsTest extends BaseTest { + + @Resource + private Wallet wallet; + + private CallArguments callArguments; + + static { + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); + } + + @Before + public void init() { + callArguments = new CallArguments("0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000001","0x10","0.01","0x100", + "","0"); + } + + @Test + public void testGetContractType() + throws JsonRpcInvalidRequestException, JsonRpcInvalidParamsException { + Protocol.Transaction.Contract.ContractType contractType = callArguments.getContractType(wallet); + Assert.assertEquals(Protocol.Transaction.Contract.ContractType.TransferContract, contractType); + } + + @Test + public void testParseValue() throws JsonRpcInvalidParamsException { + long value = callArguments.parseValue(); + Assert.assertEquals(256L, value); + } + +} diff --git a/framework/src/test/java/org/tron/core/services/jsonrpc/TransactionReceiptTest.java b/framework/src/test/java/org/tron/core/services/jsonrpc/TransactionReceiptTest.java new file mode 100644 index 00000000000..f10526e30a4 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/jsonrpc/TransactionReceiptTest.java @@ -0,0 +1,66 @@ +package org.tron.core.services.jsonrpc; + +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.Wallet; +import org.tron.core.capsule.TransactionRetCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.services.jsonrpc.types.TransactionReceipt; +import org.tron.core.store.TransactionRetStore; +import org.tron.protos.Protocol; + +public class TransactionReceiptTest extends BaseTest { + + @Resource + private Wallet wallet; + + @Resource + private TransactionRetStore transactionRetStore; + + static { + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); + } + + @Test + public void testTransactionReceipt() { + Protocol.TransactionInfo transactionInfo = Protocol.TransactionInfo.newBuilder() + .setId(ByteString.copyFrom("1".getBytes())) + .setContractAddress(ByteString.copyFrom("address1".getBytes())) + .setReceipt(Protocol.ResourceReceipt.newBuilder() + .setEnergyUsageTotal(0L) + .setResult(Protocol.Transaction.Result.contractResult.DEFAULT) + .build()) + .addLog(Protocol.TransactionInfo.Log.newBuilder() + .setAddress(ByteString.copyFrom("address1".getBytes())) + .setData(ByteString.copyFrom("data".getBytes())) + .build()) + .build(); + TransactionRetCapsule transactionRetCapsule = new TransactionRetCapsule(); + transactionRetCapsule.addTransactionInfo(transactionInfo); + transactionRetStore.put(ByteArray.fromLong(1), transactionRetCapsule); + + Protocol.Transaction.raw.Builder raw = Protocol.Transaction.raw.newBuilder(); + Protocol.Transaction.Contract.Builder contract = Protocol.Transaction.Contract.newBuilder(); + contract.setType(Protocol.Transaction.Contract.ContractType.UpdateBrokerageContract); + raw.addContract(contract.build()); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().setRawData(raw).build(); + + TransactionReceipt transactionReceipt = new TransactionReceipt( + Protocol.Block.newBuilder().setBlockHeader( + Protocol.BlockHeader.newBuilder().setRawData( + Protocol.BlockHeader.raw.newBuilder().setNumber(1))).addTransactions( + transaction).build(), transactionInfo, wallet); + + Assert.assertEquals(transactionReceipt.getBlockNumber(),"0x1"); + Assert.assertEquals(transactionReceipt.getTransactionIndex(),"0x0"); + Assert.assertEquals(transactionReceipt.getLogs().length,1); + Assert.assertEquals(transactionReceipt.getBlockHash(), + "0x0000000000000001464f071c8a336fd22eb5145dff1b245bda013ec89add8497"); + } + +} diff --git a/framework/src/test/java/org/tron/core/services/jsonrpc/TransactionResultTest.java b/framework/src/test/java/org/tron/core/services/jsonrpc/TransactionResultTest.java new file mode 100644 index 00000000000..a71441c73b4 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/jsonrpc/TransactionResultTest.java @@ -0,0 +1,59 @@ +package org.tron.core.services.jsonrpc; + +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.Wallet; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.services.jsonrpc.types.TransactionResult; +import org.tron.protos.Protocol; + +public class TransactionResultTest extends BaseTest { + + @Resource + private Wallet wallet; + + static { + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); + } + + @Test + public void testBuildTransactionResultWithBlock() { + Protocol.Transaction.raw.Builder raw = Protocol.Transaction.raw.newBuilder().addContract( + Protocol.Transaction.Contract.newBuilder().setType( + Protocol.Transaction.Contract.ContractType.TriggerSmartContract)); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().setRawData(raw).build(); + BlockCapsule blockCapsule = new BlockCapsule(Protocol.Block.newBuilder().setBlockHeader( + Protocol.BlockHeader.newBuilder().setRawData(Protocol.BlockHeader.raw.newBuilder() + .setParentHash(ByteString.copyFrom(ByteArray.fromHexString( + "0304f784e4e7bae517bcab94c3e0c9214fb4ac7ff9d7d5a937d1f40031f87b82"))) + .setNumber(9))).addTransactions(transaction).build()); + + TransactionResult transactionResult = new TransactionResult(blockCapsule,0, transaction, + 100,1, wallet); + Assert.assertEquals(transactionResult.getBlockNumber(), "0x9"); + Assert.assertEquals(transactionResult.getHash(), + "0xdebef90d0a8077620711b1b5af2b702665887ddcbf80868108026e1ab5e0bfb7"); + Assert.assertEquals(transactionResult.getGasPrice(), "0x1"); + Assert.assertEquals(transactionResult.getGas(), "0x64"); + } + + @Test + public void testBuildTransactionResult() { + Protocol.Transaction.raw.Builder raw = Protocol.Transaction.raw.newBuilder().addContract( + Protocol.Transaction.Contract.newBuilder().setType( + Protocol.Transaction.Contract.ContractType.TriggerSmartContract)); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().setRawData(raw).build(); + TransactionResult transactionResult = new TransactionResult(transaction, wallet); + Assert.assertEquals(transactionResult.getHash(), + "0xdebef90d0a8077620711b1b5af2b702665887ddcbf80868108026e1ab5e0bfb7"); + Assert.assertEquals(transactionResult.getGasPrice(), "0x"); + Assert.assertEquals(transactionResult.getNonce(), "0x0000000000000000"); + } + +} From 8de354f8e389dfc989d247818d11d884121d625e Mon Sep 17 00:00:00 2001 From: paladim Date: Thu, 26 Oct 2023 12:35:13 +0300 Subject: [PATCH 0917/1197] fix(event):synchronization of sending to zeromq (#5536) Co-authored-by: paladim --- .../common/logsfilter/nativequeue/NativeMessageQueue.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java b/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java index c0a115620c2..73dd1ee41d1 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java +++ b/framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java @@ -64,8 +64,10 @@ public void publishTrigger(String data, String topic) { } try { - publisher.sendMore(topic); - publisher.send(data); + synchronized (this) { + publisher.sendMore(topic); + publisher.send(data); + } } catch (RuntimeException e) { logger.error("write data to zeromq failed, data:{}, topic:{}, error:{}", data, topic, e.getMessage()); From df52667e48bb1aa6d0f6d6904f3eb1aea5e14e27 Mon Sep 17 00:00:00 2001 From: Kayle Date: Mon, 13 Nov 2023 14:08:53 +0800 Subject: [PATCH 0918/1197] feat(script): remove useless scripts (#5580) Co-authored-by: liukai --- script/checkStyle.sh | 26 ------------- script/codecov.sh | 5 --- script/querySonar.sh | 41 -------------------- script/sonar.sh | 89 -------------------------------------------- 4 files changed, 161 deletions(-) delete mode 100644 script/checkStyle.sh delete mode 100644 script/codecov.sh delete mode 100644 script/querySonar.sh delete mode 100644 script/sonar.sh diff --git a/script/checkStyle.sh b/script/checkStyle.sh deleted file mode 100644 index af3d5e7df1f..00000000000 --- a/script/checkStyle.sh +++ /dev/null @@ -1,26 +0,0 @@ -./gradlew clean build -x test > build.log 2>&1 -if [ $? != 0 ];then - echo "run ./gradlew build fail, Please check you code, Or just retry this test" - exit 1 -fi -echo "------------------------------ checkStyle check ------------------------------" -#echo $BUILDKITE_PULL_REQUEST_BASE_BRANCH -#if [[ x"$BUILDKITE_PULL_REQUEST_BASE_BRANCH" != x'develop' && x"$BUILDKITE_PULL_REQUEST_BASE_BRANCH" != x'master' ]];then -# echo "BUILDKITE_PULL_REQUEST_BASE_BRANCH isnot develop or master, SKIPED" -# exit 0 -#fi - -grep -v ":checkstyleMain\|:checkstyleTest\|:lint" build.log |grep "ant:checkstyle" > checkStyle.log 2>&1 -checkNum=`cat checkStyle.log | wc -l` -if [ ${checkNum} -gt 0 ];then - echo "please fix checkStyle problem," - echo "run [ ./gradlew clean build -x test ], and you can find checkStyle report in framework/build/reports/checkstyle/" - echo "!!!!! checkStyle Num ${checkNum} !!!!!" - cat checkStyle.log - - echo "checkStyle Failed, please fix checkStyle problem" - touch checkFailTag -else - echo "checkStyle problem zero" -fi -exit 0 diff --git a/script/codecov.sh b/script/codecov.sh deleted file mode 100644 index ba83a5a8ee2..00000000000 --- a/script/codecov.sh +++ /dev/null @@ -1,5 +0,0 @@ -bash <(curl -s https://codecov.io/bash) -t ee5ed39e-1cc4-49d1-bcf9-12bce10e5b3b -s ./common/build/reports/jacoco/test/ -s ./consensus/build/reports/jacoco/test/ -s ./chainbase/build/reports/jacoco/test/ -s ./actuator/build/reports/jacoco/test/ -s ./framework/build/reports/jacoco/test/ - -#bash <(curl -s https://codecov.io/bash) -t ee5ed39e-1cc4-49d1-bcf9-12bce10e5b3b -s ./common/build/reports/jacoco/test/jacocoTestReport.xml -s ./consensus/build/reports/jacoco/test/jacocoTestReport.xml -s ./chainbase/build/reports/jacoco/test/jacocoTestReport.xml -s ./actuator/build/reports/jacoco/test/jacocoTestReport.xml -s ./framework/build/reports/jacoco/test/jacocoTestReport.xml - -#bash <(curl -s https://codecov.io/bash) -t c2f718cbe2e84c62970a892cef614689 diff --git a/script/querySonar.sh b/script/querySonar.sh deleted file mode 100644 index 8c558634304..00000000000 --- a/script/querySonar.sh +++ /dev/null @@ -1,41 +0,0 @@ -echo "current branch is : "$BUILDKITE_BRANCH -if [ $BUILDKITE_PULL_REQUEST = "false" ]; then - SonarStatus_Url="https://sonarcloud.io/api/qualitygates/project_status?projectKey=java-tron&branch="$BUILDKITE_BRANCH - Status=`curl -s $SonarStatus_Url | jq '.projectStatus.status'` - echo "current branch sonarcloud status is : "$Status - if [ $Status = null ]; then - echo "wait for check finish, 5m ....." - sleep 300 - SonarStatus_Url="https://sonarcloud.io/api/qualitygates/project_status?projectKey=java-tron&branch="$BUILDKITE_BRANCH - Status=`curl -s $SonarStatus_Url | jq '.projectStatus.status'` - fi - - if [ x"$Status" = x'"OK"' ];then - echo "Sonar Check Pass" - exit 0 - else - echo "Sonar Check Failed" - echo "Please visit https://sonarcloud.io/dashboard?branch="$BUILDKITE_BRANCH"&id=java-tron for more details" - exit 1 - fi -else - echo "current PR number is : "$BUILDKITE_PULL_REQUEST - SonarStatus_Url="https://sonarcloud.io/api/qualitygates/project_status?projectKey=java-tron&pullRequest="$BUILDKITE_PULL_REQUEST - Status=`curl -s $SonarStatus_Url | jq '.projectStatus.status'` - if [ $Status = null ]; then - echo "wait for check finish, 5m ....." - sleep 300 - SonarStatus_Url="https://sonarcloud.io/api/qualitygates/project_status?projectKey=java-tron&pullRequest="$BUILDKITE_PULL_REQUEST - Status=`curl -s $SonarStatus_Url | jq '.projectStatus.status'` - fi - - echo "current pullRequest sonarcloud status is : "$Status - if [ x"$Status" = x'"OK"' ];then - echo "Sonar Check Pass" - exit 0 - else - echo "Sonar Check Failed" - echo "Please visit https://sonarcloud.io/dashboard?id=java-tron&pullRequest="$BUILDKITE_PULL_REQUEST" for more details" - exit 1 - fi -fi \ No newline at end of file diff --git a/script/sonar.sh b/script/sonar.sh deleted file mode 100644 index b3e2b5ccf28..00000000000 --- a/script/sonar.sh +++ /dev/null @@ -1,89 +0,0 @@ -echo "------------------------------ sonar check ------------------------------" -export SONAR_SCANNER_VERSION=4.2.0.1873 -export SONAR_SCANNER_HOME=/home/java-tron/sonar-scanner-4.1.0.1829-linux -export PATH=$SONAR_SCANNER_HOME/bin:$PATH -export SONAR_SCANNER_OPTS="-server" -#export PATH=$PATH:/home/java-tron/sonar-scanner-4.1.0.1829-linux/bin - -#BUILDKITE_BRANCH="MiraculousWang:develop" - -echo "current branch is : "$BUILDKITE_BRANCH -if [ $BUILDKITE_PULL_REQUEST = "false" ]; then - - sonar-scanner \ - -Dsonar.projectKey=java-tron \ - -Dsonar.organization=tron-zhaohong \ - -Dsonar.sources=./actuator/src,./framework/src/main,./consensus/src,./chainbase/src,./common/src,./crypto/src,./protocol/src \ - -Dsonar.java.binaries=./actuator/build/classes,./framework/build/classes,./consensus/build/classes,./chainbase/build/classes,./common/build/classes,./crypto/build/classes,./protocol/build/classes \ - -Dsonar.host.url=https://sonarcloud.io \ - -Dsonar.links.homepage=https://github.com/tronprotocol/java-tron \ - -Dsonar.links.scm=https://github.com/tronprotocol/java-tron \ - -Dsoanr.links.issue=https://github.com/tronprotocol/java-tron/issues \ - -Dsonar.branch.name=$BUILDKITE_BRANCH \ - -Dsonar.coverage.jacoco.xmlReportPaths=./common/build/reports/jacoco/test/jacocoTestReport.xml,./consensus/build/reports/jacoco/test/jacocoTestReport.xml,./chainbase/build/reports/jacoco/test/jacocoTestReport.xml,./actuator/build/reports/jacoco/test/jacocoTestReport.xml,./framework/build/reports/jacoco/test/jacocoTestReport.xml \ - -Dsonar.login=1717c3c748ec2e0ea61e501b05458de243c4abcc > /data/checkStyle/sonar.log - - sleep 100 - - - SonarStatus_Url="https://sonarcloud.io/api/qualitygates/project_status?projectKey=java-tron&branch="$BUILDKITE_BRANCH - Status=`curl -s $SonarStatus_Url | jq '.projectStatus.status'` - echo "current branch sonarcloud status is : "$Status - if [ $Status = null ]; then - echo "wait for check finish, 5m ....." - sleep 300 - SonarStatus_Url="https://sonarcloud.io/api/qualitygates/project_status?projectKey=java-tron&branch="$BUILDKITE_BRANCH - Status=`curl -s $SonarStatus_Url | jq '.projectStatus.status'` - fi - - if [ x"$Status" = x'"OK"' ];then - echo "Sonar Check Pass" - exit 0 - else - echo ">>>>>>>>>>>>>>>>>>>>>>>>>> Sonar Check Failed <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" - echo ">>>>>>>>>>>> Please visit https://sonarcloud.io/dashboard?branch="$BUILDKITE_BRANCH"&id=java-tron for more details <<<<<<<<<<<<<<<<<<" - touch checkFailTag - exit 0 - fi -else - echo "current PR number is : "$BUILDKITE_PULL_REQUEST - - sonar-scanner \ - -Dsonar.projectKey=java-tron \ - -Dsonar.organization=tron-zhaohong \ - -Dsonar.sources=./actuator/src,./framework/src/main,./consensus/src,./chainbase/src,./common/src,./crypto/src,./protocol/src \ - -Dsonar.java.binaries=./actuator/build/classes,./framework/build/classes,./consensus/build/classes,./chainbase/build/classes,./common/build/classes,./crypto/build/classes,./protocol/build/classes \ - -Dsonar.host.url=https://sonarcloud.io \ - -Dsonar.links.homepage=https://github.com/tronprotocol/java-tron \ - -Dsonar.links.scm=https://github.com/tronprotocol/java-tron \ - -Dsoanr.links.issue=https://github.com/tronprotocol/java-tron/issues \ - -Dsonar.pullrequest.key=$BUILDKITE_PULL_REQUEST \ - -Dsonar.pullrequest.branch=$BUILDKITE_BRANCH \ - -Dsonar.pullrequest.base=$BUILDKITE_PULL_REQUEST_BASE_BRANCH \ - -Dsonar.coverage.jacoco.xmlReportPaths=./common/build/reports/jacoco/test/jacocoTestReport.xml,./consensus/build/reports/jacoco/test/jacocoTestReport.xml,./chainbase/build/reports/jacoco/test/jacocoTestReport.xml,./actuator/build/reports/jacoco/test/jacocoTestReport.xml,./framework/build/reports/jacoco/test/jacocoTestReport.xml \ - -Dsonar.login=1717c3c748ec2e0ea61e501b05458de243c4abcc > /data/checkStyle/sonar.log - - sleep 100 - - SonarStatus_Url="https://sonarcloud.io/api/qualitygates/project_status?projectKey=java-tron&pullRequest="$BUILDKITE_PULL_REQUEST - Status=`curl -s $SonarStatus_Url | jq '.projectStatus.status'` - if [ $Status = null ]; then - echo "wait for check finish, 5m ....." - sleep 300 - SonarStatus_Url="https://sonarcloud.io/api/qualitygates/project_status?projectKey=java-tron&pullRequest="$BUILDKITE_PULL_REQUEST - Status=`curl -s $SonarStatus_Url | jq '.projectStatus.status'` - fi - - echo "current pullRequest sonarcloud status is : "$Status - if [ x"$Status" = x'"OK"' ];then - echo "Sonar Check Pass" - exit 0 - else - echo " -------------------------------- sonar check Failed ---------------------------------" - echo ">>>>>>>>>>>>>>> Please visit https://sonarcloud.io/dashboard?id=java-tron&pullRequest="$BUILDKITE_PULL_REQUEST" for more details <<<<<<<<<<<<<<<<<<" - echo "If this Sonar problem is not caused by your modification,Make sure you local branch is newest, And merge the newest tronprotocol/java-tron" - echo ">>>>>>>>>>>>>>>>>>>>>>>>>> Sonar Check Failed <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< " - touch checkFailTag - exit 0 - fi -fi From 4557c7270f71245a4667c544edbbd582a593dec9 Mon Sep 17 00:00:00 2001 From: Brown Jiang <317787106@qq.com> Date: Tue, 21 Nov 2023 10:52:37 +0800 Subject: [PATCH 0919/1197] modify default dns tree (#5585) --- framework/src/main/resources/config.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 91f108b74a9..e13973d4fb2 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -213,7 +213,7 @@ node { dns { # dns urls to get nodes, url format tree://{pubkey}@{domain}, default empty treeUrls = [ - #"tree://APFGGTFOBVE2ZNAB3CSMNNX6RRK3ODIRLP2AA5U4YFAA6MSYZUYTQ@nodes1.example.org", + #"tree://AKMQMNAJJBL73LXWPXDI4I5ZWWIZ4AWO34DWQ636QOBBXNFXH3LQS@main.trondisco.net", //offical dns tree ] } From 2d64668d1fa254a4893966564b809a588c738770 Mon Sep 17 00:00:00 2001 From: running-tomato <31307926+tomatoishealthy@users.noreply.github.com> Date: Thu, 23 Nov 2023 17:42:33 +0800 Subject: [PATCH 0920/1197] feat(grpc): add reflection service (#5583) --- .../main/java/org/tron/common/parameter/CommonParameter.java | 3 +++ common/src/main/java/org/tron/core/Constant.java | 2 ++ framework/src/main/java/org/tron/core/config/args/Args.java | 4 ++++ .../src/main/java/org/tron/core/services/RpcApiService.java | 5 +++++ .../core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java | 5 +++++ .../interfaceOnSolidity/RpcApiServiceOnSolidity.java | 5 +++++ framework/src/main/resources/config-localtest.conf | 3 +++ framework/src/main/resources/config.conf | 3 +++ .../src/test/java/org/tron/common/config/args/ArgsTest.java | 1 + framework/src/test/resources/config-localtest.conf | 3 +++ framework/src/test/resources/config-test.conf | 3 +++ protocol/build.gradle | 2 ++ 12 files changed, 39 insertions(+) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index f8f6e6c5edb..1ad50e1e359 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -255,6 +255,9 @@ public class CommonParameter { public int maxHeaderListSize; @Getter @Setter + public boolean isRpcReflectionServiceEnable; + @Getter + @Setter @Parameter(names = {"--validate-sign-thread"}, description = "Num of validate thread") public int validateSignThreadNum; @Getter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index ba867793b41..d7ec3b715c9 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -151,6 +151,8 @@ public class Constant { public static final String NODE_RPC_MAX_HEADER_LIST_SIZE = "node.rpc.maxHeaderListSize"; + public static final String NODE_RPC_REFLECTION_SERVICE = "node.rpc.reflectionService"; + public static final String NODE_OPEN_HISTORY_QUERY_WHEN_LITEFN = "node.openHistoryQueryWhenLiteFN"; public static final String BLOCK_MAINTENANCE_TIME_INTERVAL = "block.maintenanceTimeInterval"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 75140dd5f54..aff6708dfff 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -748,6 +748,10 @@ public static void setParam(final String[] args, final String confFileName) { ? config.getInt(Constant.NODE_RPC_MAX_HEADER_LIST_SIZE) : GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE; + PARAMETER.isRpcReflectionServiceEnable = + config.hasPath(Constant.NODE_RPC_REFLECTION_SERVICE) + && config.getBoolean(Constant.NODE_RPC_REFLECTION_SERVICE); + PARAMETER.maintenanceTimeInterval = config.hasPath(Constant.BLOCK_MAINTENANCE_TIME_INTERVAL) ? config .getInt(Constant.BLOCK_MAINTENANCE_TIME_INTERVAL) : 21600000L; diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 94d5b97decd..2e3994c3250 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -8,6 +8,7 @@ import io.grpc.Status; import io.grpc.StatusRuntimeException; import io.grpc.netty.NettyServerBuilder; +import io.grpc.protobuf.services.ProtoReflectionService; import io.grpc.stub.StreamObserver; import java.util.Objects; import java.util.concurrent.TimeUnit; @@ -250,6 +251,10 @@ public void start() { // add lite fullnode query interceptor serverBuilder.intercept(liteFnQueryGrpcInterceptor); + if (parameter.isRpcReflectionServiceEnable()) { + serverBuilder.addService(ProtoReflectionService.newInstance()); + } + apiServer = serverBuilder.build(); rateLimiterInterceptor.init(apiServer); super.start(); diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java index 2f7b1dcc15c..4d801f20e5c 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java @@ -1,6 +1,7 @@ package org.tron.core.services.interfaceOnPBFT; import io.grpc.netty.NettyServerBuilder; +import io.grpc.protobuf.services.ProtoReflectionService; import io.grpc.stub.StreamObserver; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -123,6 +124,10 @@ public void start() { // add lite fullnode query interceptor serverBuilder.intercept(liteFnQueryGrpcInterceptor); + if (args.isRpcReflectionServiceEnable()) { + serverBuilder.addService(ProtoReflectionService.newInstance()); + } + apiServer = serverBuilder.build(); rateLimiterInterceptor.init(apiServer); super.start(); diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java index 68ec79175fa..6bdfc824163 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java @@ -2,6 +2,7 @@ import com.google.protobuf.ByteString; import io.grpc.netty.NettyServerBuilder; +import io.grpc.protobuf.services.ProtoReflectionService; import io.grpc.stub.StreamObserver; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -124,6 +125,10 @@ public void start() { // add lite fullnode query interceptor serverBuilder.intercept(liteFnQueryGrpcInterceptor); + if (parameter.isRpcReflectionServiceEnable()) { + serverBuilder.addService(ProtoReflectionService.newInstance()); + } + apiServer = serverBuilder.build(); rateLimiterInterceptor.init(apiServer); super.start(); diff --git a/framework/src/main/resources/config-localtest.conf b/framework/src/main/resources/config-localtest.conf index 32f57481463..5ce30aeb1a4 100644 --- a/framework/src/main/resources/config-localtest.conf +++ b/framework/src/main/resources/config-localtest.conf @@ -149,6 +149,9 @@ node { # The maximum size of header list allowed to be received, default 8192 # maxHeaderListSize = + + # The switch of the reflection service, effective for all gRPC services + reflectionService = false } jsonrpc { diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index e13973d4fb2..019b6302911 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -284,6 +284,9 @@ node { # "getaccount", # "getnowblock2" # ] + + # The switch of the reflection service, effective for all gRPC services + # reflectionService = true } ## rate limiter config diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index b95d47bfa39..0b66064f663 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -48,6 +48,7 @@ public void testConfig() { RateLimiterInitialization rateLimiter = Args.getInstance().getRateLimiterInitialization(); Assert.assertEquals(rateLimiter.getHttpMap().size(), 1); Assert.assertEquals(rateLimiter.getRpcMap().size(), 0); + Assert.assertTrue(Args.getInstance().isRpcReflectionServiceEnable()); } @Test diff --git a/framework/src/test/resources/config-localtest.conf b/framework/src/test/resources/config-localtest.conf index c6ecaf28173..ff0fe8bf9d9 100644 --- a/framework/src/test/resources/config-localtest.conf +++ b/framework/src/test/resources/config-localtest.conf @@ -146,6 +146,9 @@ node { # The maximum size of header list allowed to be received, default 8192 # maxHeaderListSize = + + # The switch of the reflection service, effective for all gRPC services + reflectionService = true } jsonrpc { diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index cf7ca5e2f42..304ad125340 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -190,6 +190,9 @@ node { # The maximum size of header list allowed to be received, default 8192 # maxHeaderListSize = + + # The switch of the reflection service, effective for all gRPC services + reflectionService = true } } diff --git a/protocol/build.gradle b/protocol/build.gradle index e790e480fa0..922d6d19859 100644 --- a/protocol/build.gradle +++ b/protocol/build.gradle @@ -13,6 +13,8 @@ dependencies { compile group: 'io.grpc', name: 'grpc-netty', version: grpcVersion compile group: 'io.grpc', name: 'grpc-protobuf', version: grpcVersion compile group: 'io.grpc', name: 'grpc-stub', version: grpcVersion + compile group: 'io.grpc', name: 'grpc-services', version: grpcVersion + // end google grpc compile group: 'com.google.api.grpc', name: 'proto-google-common-protos', version: '2.15.0' From be07f5c91899cee0bfde517ac3a5e5f73c6fc957 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Fri, 24 Nov 2023 14:36:57 +0800 Subject: [PATCH 0921/1197] dependency(jetty): upgrade for security (#5571) --- framework/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/build.gradle b/framework/build.gradle index c894ae1e03d..1c817f545f0 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -70,8 +70,8 @@ dependencies { compile group: 'com.google.api.grpc', name: 'proto-google-common-protos', version: '2.15.0' // http - compile 'org.eclipse.jetty:jetty-server:9.4.49.v20220914' - compile 'org.eclipse.jetty:jetty-servlet:9.4.49.v20220914' + compile 'org.eclipse.jetty:jetty-server:9.4.53.v20231009' + compile 'org.eclipse.jetty:jetty-servlet:9.4.53.v20231009' compile 'com.alibaba:fastjson:1.2.83' compile group: 'org.apache.httpcomponents', name: 'httpasyncclient', version: '4.1.1' // end http From a66316c4aa632fd9237e6ed77a972b23b46271c7 Mon Sep 17 00:00:00 2001 From: lurais <107600021+lurais@users.noreply.github.com> Date: Wed, 29 Nov 2023 14:36:43 +0800 Subject: [PATCH 0922/1197] feat(test): add jetty test for CVE-2023-40167 (#5600) Co-authored-by: morgan.peng --- .../tron/common/jetty/JettyServerTest.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 framework/src/test/java/org/tron/common/jetty/JettyServerTest.java diff --git a/framework/src/test/java/org/tron/common/jetty/JettyServerTest.java b/framework/src/test/java/org/tron/common/jetty/JettyServerTest.java new file mode 100644 index 00000000000..fec29de0cb6 --- /dev/null +++ b/framework/src/test/java/org/tron/common/jetty/JettyServerTest.java @@ -0,0 +1,63 @@ +package org.tron.common.jetty; + +import java.net.URI; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.DefaultServlet; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +@Slf4j +public class JettyServerTest { + private static Server server; + private static URI serverUri; + + @BeforeClass + public static void startJetty() throws Exception { + server = new Server(); + ServerConnector connector = new ServerConnector(server); + connector.setPort(0); + server.addConnector(connector); + + ServletContextHandler context = new ServletContextHandler(); + ServletHolder defaultServ = new ServletHolder("default", DefaultServlet.class); + context.addServlet(defaultServ, "/"); + server.setHandler(context); + server.start(); + String host = connector.getHost(); + if (host == null) { + host = "localhost"; + } + int port = connector.getLocalPort(); + serverUri = new URI(String.format("http://%s:%d/", host, port)); + } + + @AfterClass + public static void stopJetty() { + try { + server.stop(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + public void testGet() throws Exception { + HttpClient client = new DefaultHttpClient(); + HttpGet request = new HttpGet(serverUri.resolve("/")); + request.setHeader("Content-Length", "+450"); + HttpResponse mockResponse = client.execute(request); + Assert.assertTrue(mockResponse.getStatusLine().toString().contains( + "400 Invalid Content-Length Value")); + } + +} From 3f3ffe9bc16b0e111f607e5ec3c9a0d042bb5a8e Mon Sep 17 00:00:00 2001 From: Kayle Date: Fri, 8 Dec 2023 15:31:09 +0800 Subject: [PATCH 0923/1197] docs(protobuf): change transaction data structure description (#5602) Co-authored-by: liukai --- Tron protobuf protocol document.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Tron protobuf protocol document.md b/Tron protobuf protocol document.md index 852ff313797..2ba2c3113a3 100644 --- a/Tron protobuf protocol document.md +++ b/Tron protobuf protocol document.md @@ -546,11 +546,11 @@ Transaction and transaction-related messages. message `raw` - `ref_block_bytes`: Deprecated. + `ref_block_bytes`: intercepted part of the now block bytes in transaction head. - `ref_block_num`: now block number in transaction head. + `ref_block_num`: Deprecated. - `ref_block_hash`: now block hash in transaction head. + `ref_block_hash`:intercepted part of the now block hash in transaction head.. `expiration`: the expiration time in transaction head. @@ -565,15 +565,15 @@ Transaction and transaction-related messages. ```java message raw { bytes ref_block_bytes = 1; - int64 ref_block_num = 3; + int64 ref_block_num = 3; bytes ref_block_hash = 4; - int64 expiration = 8; + int64 expiration = 8; repeated authority auths = 9; - bytes data = 10; + bytes data = 10; repeated Contract contract = 11; - bytes scripts = 12; + bytes scripts = 12; int64 timestamp = 14; - int64 fee_limit = 18; + int64 fee_limit = 18; } ``` From 581533769a817f6105360e0c333158a2320e455f Mon Sep 17 00:00:00 2001 From: Zoe Braiterman Date: Tue, 12 Dec 2023 22:47:56 -0500 Subject: [PATCH 0924/1197] fix(docs/readme): minor grammar fixes to the README file (#5606) --- README.md | 141 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 81 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index 4d1d7b0b3b6..05b820297ac 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,6 @@ Java implementation of the Tron Protocol -

@@ -42,6 +41,7 @@

## Table of Contents + - [What’s TRON?](#whats-tron) - [Building the Source Code](#building-the-source) - [Running java-tron](#running-java-tron) @@ -55,94 +55,109 @@ TRON is a project dedicated to building the infrastructure for a truly decentralized Internet. -* Tron Protocol, one of the largest blockchain-based operating systems in the world, offers scalable, high-availability and high-throughput support that underlies all the decentralized applications in the TRON ecosystem. +- Tron Protocol, one of the largest blockchain-based operating systems in the world, offers scalable, high-availability and high-throughput support that underlies all the decentralized applications in the TRON ecosystem. -* Tron Virtual Machine (TVM) allows anyone to develop decentralized applications (DAPPs) for themselves or their communities with smart contracts thereby making decentralized crowdfunding and token issuance easier than ever. +- Tron Virtual Machine (TVM) allows anyone to develop decentralized applications (DAPPs) for themselves or their communities with smart contracts thereby making decentralized crowdfunding and token issuance easier than ever. TRON enables large-scale development and engagement. With over 2000 transactions per second (TPS), high concurrency, low latency, and massive data transmission. It is ideal for building decentralized entertainment applications. Free features and incentive systems allow developers to create premium app experiences for users. # Building the source + Building java-tron requires `git` and 64-bit version of `Oracle JDK 1.8` to be installed, other JDK versions are not supported yet. Make sure you operate on `Linux` and `MacOS` operating systems. Clone the repo and switch to the `master` branch - ```bash - $ git clone https://github.com/tronprotocol/java-tron.git - $ cd java-tron - $ git checkout -t origin/master - ``` +```bash +$ git clone https://github.com/tronprotocol/java-tron.git +$ cd java-tron +$ git checkout -t origin/master +``` + then run the following command to build java-tron, the `FullNode.jar` file can be found in `java-tron/build/libs/` after build successful. + ```bash $ ./gradlew clean build -x test ``` - # Running java-tron + Running java-tron requires 64-bit version of `Oracle JDK 1.8` to be installed, other JDK versions are not supported yet. Make sure you operate on `Linux` and `MacOS` operating systems. -Get the mainnet configuration file: [main_net_config.conf](https://github.com/tronprotocol/tron-deployment/blob/master/main_net_config.conf), other network configuration files can be find [here](https://github.com/tronprotocol/tron-deployment). +Get the mainnet configuration file: [main_net_config.conf](https://github.com/tronprotocol/tron-deployment/blob/master/main_net_config.conf), other network configuration files can be found [here](https://github.com/tronprotocol/tron-deployment). + ## Hardware Requirements + Minimum: -* CPU with 8 cores -* 16GB RAM -* 2TB free storage space to sync the Mainnet + +- CPU with 8 cores +- 16GB RAM +- 2TB free storage space to sync the Mainnet Recommended: -* CPU with 16+ cores(32+ cores for a super representative) -* 32GB+ RAM(64GB+ for a super representative) -* High Performance SSD with at least 2.5TB free space -* 100+ MB/s download Internet service +- CPU with 16+ cores(32+ cores for a super representative) +- 32GB+ RAM(64GB+ for a super representative) +- High Performance SSD with at least 2.5TB free space +- 100+ MB/s download Internet service ## Running a full node for mainnet -Full node has full historical data, it is the entry point into the TRON network , it can be used by other processes as a gateway into the TRON network via HTTP and GRPC endpoints. You can interact with the TRON network through full node:transfer assets, deploy contracts, interact with contracts and so on. `-c ` parameter specifies a configuration file to run a full node: - ```bash - $ nohup java -Xms9G -Xmx9G -XX:ReservedCodeCacheSize=256m \ - -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m \ - -XX:MaxDirectMemorySize=1G -XX:+PrintGCDetails \ - -XX:+PrintGCDateStamps -Xloggc:gc.log \ - -XX:+UseConcMarkSweepGC -XX:NewRatio=2 \ - -XX:+CMSScavengeBeforeRemark -XX:+ParallelRefProcEnabled \ - -XX:+HeapDumpOnOutOfMemoryError \ - -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 \ - -jar FullNode.jar -c main_net_config.conf >> start.log 2>&1 & - ``` + +Full node has full historical data, it is the entry point into the TRON network , it can be used by other processes as a gateway into the TRON network via HTTP and GRPC endpoints. You can interact with the TRON network through full node:transfer assets, deploy contracts, interact with contracts and so on. `-c` parameter specifies a configuration file to run a full node: + +```bash +$ nohup java -Xms9G -Xmx9G -XX:ReservedCodeCacheSize=256m \ + -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m \ + -XX:MaxDirectMemorySize=1G -XX:+PrintGCDetails \ + -XX:+PrintGCDateStamps -Xloggc:gc.log \ + -XX:+UseConcMarkSweepGC -XX:NewRatio=2 \ + -XX:+CMSScavengeBeforeRemark -XX:+ParallelRefProcEnabled \ + -XX:+HeapDumpOnOutOfMemoryError \ + -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 \ + -jar FullNode.jar -c main_net_config.conf >> start.log 2>&1 & +``` + ## Running a super representative node for mainnet -Adding the `--witness` parameter to the startup command, full node will run as a super representative node. The super representative node supports all the functions of the full node and also supports block production. Before running, make sure you have a super representative account and get votes from others,once the number of obtained votes ranks in the top 27, your super representative node will participate in block production. -Fill in the private key of super representative address into the `localwitness` list in the `main_net_config.conf`, here is an example: - ``` - localwitness = [ - 650950B193DDDDB35B6E48912DD28F7AB0E7140C1BFDEFD493348F02295BD812 - ] - ``` +Adding the `--witness` parameter to the startup command, full node will run as a super representative node. The super representative node supports all the functions of the full node and also supports block production. Before running, make sure you have a super representative account and get votes from others. Once the number of obtained votes ranks in the top 27, your super representative node will participate in block production. + +Fill in the private key of super representative address into the `localwitness` list in the `main_net_config.conf`. Here is an example: + +``` + localwitness = [ + 650950B193DDDDB35B6E48912DD28F7AB0E7140C1BFDEFD493348F02295BD812 + ] +``` then run the following command to start the node: - ```bash - $ nohup java -Xms9G -Xmx9G -XX:ReservedCodeCacheSize=256m \ - -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m \ - -XX:MaxDirectMemorySize=1G -XX:+PrintGCDetails \ - -XX:+PrintGCDateStamps -Xloggc:gc.log \ - -XX:+UseConcMarkSweepGC -XX:NewRatio=2 \ - -XX:+CMSScavengeBeforeRemark -XX:+ParallelRefProcEnabled \ - -XX:+HeapDumpOnOutOfMemoryError \ - -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 \ - -jar FullNode.jar --witness -c main_net_config.conf >> start.log 2>&1 & - ``` + +```bash +$ nohup java -Xms9G -Xmx9G -XX:ReservedCodeCacheSize=256m \ + -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m \ + -XX:MaxDirectMemorySize=1G -XX:+PrintGCDetails \ + -XX:+PrintGCDateStamps -Xloggc:gc.log \ + -XX:+UseConcMarkSweepGC -XX:NewRatio=2 \ + -XX:+CMSScavengeBeforeRemark -XX:+ParallelRefProcEnabled \ + -XX:+HeapDumpOnOutOfMemoryError \ + -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 \ + -jar FullNode.jar --witness -c main_net_config.conf >> start.log 2>&1 & +``` ## Quick Start Tool -An easier way to build and run java-tron is to use `start.sh`, `start.sh` is a quick start script written in shell language, you can use it to build and run java-tron quickly and easily. + +An easier way to build and run java-tron is to use `start.sh`. `start.sh` is a quick start script written in the Shell language. You can use it to build and run java-tron quickly and easily. Here are some common use cases of the scripting tool -* Use `start.sh` to start a full node with the downloaded `FullNode.jar` -* Use `start.sh` to download the latest `FullNode.jar` and start a full node. -* Use `start.sh` to download the latest source code and compile a `FullNode.jar` and then start a full node. + +- Use `start.sh` to start a full node with the downloaded `FullNode.jar` +- Use `start.sh` to download the latest `FullNode.jar` and start a full node. +- Use `start.sh` to download the latest source code and compile a `FullNode.jar` and then start a full node. For more details, please refer to the tool [guide](./shell.md). ## Run inside Docker container One of the quickest ways to get `java-tron` up and running on your machine is by using Docker: + ```shell $ docker run -d --name="java-tron" \ -v /your_path/output-directory:/java-tron/output-directory \ @@ -155,6 +170,7 @@ $ docker run -d --name="java-tron" \ This will mount the `output-directory` and `logs` directories on the host, the docker.sh tool can also be used to simplify the use of docker, see more [here](docker/docker.md). # Community + [Tron Developers & SRs](https://discord.gg/hqKvyAM) is Tron's official Discord channel. Feel free to join this channel if you have any questions. [Core Devs Community](https://t.me/troncoredevscommunity) is the Telegram channel for java-tron community developers. If you want to contribute to java-tron, please join this channel. @@ -162,22 +178,27 @@ This will mount the `output-directory` and `logs` directories on the host, the d [tronprotocol/allcoredev](https://gitter.im/tronprotocol/allcoredev) is the official Gitter channel for developers. # Contribution -Thank you for considering to help out with the source code! If you'd like to contribute to java-tron, please see the [Contribution Guide](./CONTRIBUTING.md) for more details. +Thank you for considering to help out with the source code! If you'd like to contribute to java-tron, please see the [Contribution Guide](./CONTRIBUTING.md) for more details. # Resources -* [Medium](https://medium.com/@coredevs) java-tron's official technical articles are published there. -* [Documentation](https://tronprotocol.github.io/documentation-en/introduction/) java-tron's official technical documentation website. -* [Test network](http://nileex.io/) A stable test network of TRON contributed by TRON community. -* [Tronscan](https://tronscan.org/#/) TRON network blockchain browser. -* [Wallet-cli](https://github.com/tronprotocol/wallet-cli) TRON network wallet using command line. -* [TIP](https://github.com/tronprotocol/tips) TRON Improvement Proposal (TIP) describes standards for the TRON network. -* [TP](https://github.com/tronprotocol/tips/tree/master/tp) TRON Protocol (TP) describes standards already implemented in TRON network but not published as a TIP. + +- [Medium](https://medium.com/@coredevs) java-tron's official technical articles are published there. +- [Documentation](https://tronprotocol.github.io/documentation-en/introduction/) java-tron's official technical documentation website. +- [Test network](http://nileex.io/) A stable test network of TRON contributed by TRON community. +- [Tronscan](https://tronscan.org/#/) TRON network blockchain browser. +- [Wallet-cli](https://github.com/tronprotocol/wallet-cli) TRON network wallet using command line. +- [TIP](https://github.com/tronprotocol/tips) TRON Improvement Proposal (TIP) describes standards for the TRON network. +- [TP](https://github.com/tronprotocol/tips/tree/master/tp) TRON Protocol (TP) describes standards already implemented in TRON network but not published as a TIP. + # Integrity Check -* After January 3, 2023, releases are signed the gpg key: + +- After January 3, 2023, releases are signed the gpg key: ``` pub: 1254 F859 D2B1 BD9F 66E7 107D F859 BCB4 4A28 290B uid: build@tron.network ``` + # License + java-tron is released under the [LGPLv3 license](https://github.com/tronprotocol/java-tron/blob/master/LICENSE). From 30abf6cd8b2c44f2afed397e9d8a270559698009 Mon Sep 17 00:00:00 2001 From: lurais <107600021+lurais@users.noreply.github.com> Date: Tue, 19 Dec 2023 11:30:38 +0800 Subject: [PATCH 0925/1197] feat(checkStyle): use https for dtd links (#5623) Co-authored-by: morgan.peng --- config/checkstyle/checkStyle.xml | 2 +- config/checkstyle/checkStyleAll.xml | 2 +- framework/config/checkstyle/checkStyle.xml | 2 +- framework/config/checkstyle/checkStyleAll.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/checkstyle/checkStyle.xml b/config/checkstyle/checkStyle.xml index 16fda0fdc4f..9d09ca11bee 100644 --- a/config/checkstyle/checkStyle.xml +++ b/config/checkstyle/checkStyle.xml @@ -1,7 +1,7 @@ + "https://checkstyle.sourceforge.net/dtds/configuration_1_3.dtd"> - ``` [PM2] Spawning PM2 daemon with pm2_home=/root/.pm2 [PM2] PM2 Successfully daemonized @@ -166,25 +165,6 @@ If everything goes well, your terminal console output will look like following : (8) TYjQd4xrLZQGYMdLJqsTCuXVGapPqUp9ZX (10000 TRX) (9) THCw6hPZpFcLCWDcsZg3W77rXZ9rJQPncD (10000 TRX) - Private Keys - ================== - - (0) 2b2bddbeea87cecedcaf51eef55877b65725f709d2c0fcdfea0cb52d80acd52b - (1) f08759925316dc6344af538ebe3a619aeab836a0c254adca903cc764f87b0ee9 - (2) 1afc9f033cf9c6058db366b78a9f1b9c909b1b83397c9aed795afa05e9017511 - (3) f8f5bc70e91fc177eefea43b68c97b66536ac317a9300639e9d32a9db2f18a1f - (4) 031015272915917056c117d3cc2a03491a8f22ef450af83f6783efddf7064c59 - (5) 5eb25e2c1144f216aa99bbe2139d84bb6dedfb2c1ed72f3df6684a4c6d2cd96b - (6) f0b781da23992e6a3f536cb60917c3eb6a9c5434fcf441fcb8d7c58c01d6b70e - (7) 158f60a4379688a77d4a420e2f2a3e014ebf9ed0a1a093d7dc01ba23ebc5c970 - (8) e9342bb9108f46573804890a5301530c2834dce3703cd51ab77fba6161afec00 - (9) 2e9f0c507d2ea98dc4005a1afb1b743c629f7c145ccb55f38f75ae73cf8f605c - - HD Wallet - ================== - Mnemonic: border pulse twenty cruise grief shy need raw clean possible begin climb - Base HD Path: m/44'/60'/0'/0/{account_index} - ``` diff --git a/run.md b/run.md index 112478a4db5..c0ecbe4d91f 100644 --- a/run.md +++ b/run.md @@ -14,9 +14,9 @@ Use the [Testnet Config](https://github.com/tronprotocol/TronDeployment/blob/mas **Use the executable JAR(Recommended way):** ```bash -java -jar FullNode.jar -p your private key --witness -c your config.conf(Example:/data/java-tron/config.conf) +java -jar FullNode.jar -p --witness -c your config.conf(Example:/data/java-tron/config.conf) Example: -java -jar FullNode.jar -p 650950B193DDDDB35B6E48912DD28F7AB0E7140C1BFDEFD493348F02295BD812 --witness -c /data/java-tron/config.conf +java -jar FullNode.jar -p --witness -c /data/java-tron/config.conf ``` @@ -65,9 +65,9 @@ Then observe whether block synchronization success,If synchronization successf ```bash cd build/libs -java -jar FullNode.jar -p your private key --witness -c your config.conf (Example:/data/java-tron/config.conf) +java -jar FullNode.jar -p --witness -c your config.conf (Example:/data/java-tron/config.conf) Example: -java -jar FullNode.jar -p 650950B193DDDDB35B6E48912DD28F7AB0E7140C1BFDEFD493348F02295BD812 --witness -c /data/java-tron/config.conf +java -jar FullNode.jar -p --witness -c /data/java-tron/config.conf ``` @@ -81,7 +81,7 @@ java -jar FullNode.jar -p 650950B193DDDDB35B6E48912DD28F7AB0E7140C1BFDEFD493348F Using TaskInputs.file() with something that doesn't resolve to a File object has been deprecated and is scheduled to be removed in Gradle 5.0. Use TaskInputs.files() instead. > Task :run -20:39:22.749 INFO [o.t.c.c.a.Args] private.key = 63e62a71ed39e30bac7223097a173924aad5855959de517ff2987b0e0ec89f1a +20:39:22.749 INFO [o.t.c.c.a.Args] private.key = 63e62a71ed3... 20:39:22.816 WARN [o.t.c.c.a.Args] localwitness size must be one, get the first one 20:39:22.832 INFO [o.t.p.FullNode] Here is the help message.output-directory/ 三月 22, 2018 8:39:23 下午 org.tron.core.services.RpcApiService start From 20fc9b9b66730dba863ea04b84ad5a5fdccf563b Mon Sep 17 00:00:00 2001 From: running-tomato <31307926+tomatoishealthy@users.noreply.github.com> Date: Wed, 27 Dec 2023 11:34:00 +0800 Subject: [PATCH 0928/1197] feat(dependency): refactor gradle dependencies (#5625) --- actuator/build.gradle | 16 ---------------- build.gradle | 13 ++++++++----- chainbase/build.gradle | 34 ++-------------------------------- common/build.gradle | 7 ------- consensus/build.gradle | 13 ------------- crypto/build.gradle | 2 -- framework/build.gradle | 23 ----------------------- plugins/build.gradle | 3 --- 8 files changed, 10 insertions(+), 101 deletions(-) diff --git a/actuator/build.gradle b/actuator/build.gradle index a0ce72b0ee6..9b200064fb0 100644 --- a/actuator/build.gradle +++ b/actuator/build.gradle @@ -1,25 +1,9 @@ description = "actuator – a series of transactions for blockchain." -// Dependency versions -// --------------------------------------- - -def junitVersion = "4.13.2" -def mockitoVersion = "2.1.0" -def testNgVersion = "6.11" -def slf4jVersion = "1.7.25" -// -------------------------------------- - dependencies { compile project(":chainbase") compile project(":protocol") compile project(":crypto") - testImplementation "junit:junit:$junitVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - - compile "org.slf4j:jcl-over-slf4j:$slf4jVersion" - compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' - compile group: 'commons-codec', name: 'commons-codec', version: '1.11' - compile 'org.reflections:reflections:0.9.11' } test { diff --git a/build.gradle b/build.gradle index 8aad8910153..e3611a27a73 100644 --- a/build.gradle +++ b/build.gradle @@ -38,12 +38,7 @@ subprojects { dependencies { compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25' compile group: 'org.slf4j', name: 'jcl-over-slf4j', version: '1.7.25' - compile "org.slf4j:jcl-over-slf4j:1.7.25" compile group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.9' - compileOnly 'org.projectlombok:lombok:1.18.12' - annotationProcessor 'org.projectlombok:lombok:1.18.12' - testCompileOnly 'org.projectlombok:lombok:1.18.12' - testAnnotationProcessor 'org.projectlombok:lombok:1.18.12' compile group: 'com.google.guava', name: 'guava', version: '30.1-jre' compile "com.google.code.findbugs:jsr305:3.0.0" compile group: 'org.springframework', name: 'spring-context', version: '5.3.18' @@ -52,7 +47,15 @@ subprojects { compile group: 'org.apache.commons', name: 'commons-math', version: '2.2' compile "org.apache.commons:commons-collections4:4.1" compile group: 'joda-time', name: 'joda-time', version: '2.3' + compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' + + compileOnly 'org.projectlombok:lombok:1.18.12' + annotationProcessor 'org.projectlombok:lombok:1.18.12' + testCompileOnly 'org.projectlombok:lombok:1.18.12' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.12' + testImplementation group: 'junit', name: 'junit', version: '4.13.2' + testImplementation "org.mockito:mockito-core:2.1.0" } task sourcesJar(type: Jar, dependsOn: classes) { diff --git a/chainbase/build.gradle b/chainbase/build.gradle index a2868aa78b4..408fe56ba42 100644 --- a/chainbase/build.gradle +++ b/chainbase/build.gradle @@ -2,46 +2,16 @@ description = "chainbase – a decentralized database for blockchain." // Dependency versions // --------------------------------------- - -def junitVersion = "4.13.2" -def mockitoVersion = "2.1.0" -def testNgVersion = "6.11" def jacocoVersion = "0.8.0" -def leveldbVersion = "1.8" def jansiVersion = "1.16" // -------------------------------------- -static def isWindows() { - return org.gradle.internal.os.OperatingSystem.current().isWindows() -} - -if (isWindows()) { - ext { - leveldbGroup = "org.ethereum" - leveldbName = "leveldbjni-all" - leveldbVersion = "1.18.3" - } -} else { - ext { - leveldbGroup = "org.fusesource.leveldbjni" - leveldbName = "leveldbjni-all" - leveldbVersion = "1.8" - } -} - dependencies { - testImplementation "junit:junit:$junitVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - - compile group: leveldbGroup, name: leveldbName, version: leveldbVersion - compile "org.fusesource.jansi:jansi:$jansiVersion" - compile group: 'org.rocksdb', name: 'rocksdbjni', version: '5.15.10' - compile group: 'com.typesafe', name: 'config', version: '1.3.2' - compile 'io.github.tronprotocol:zksnark-java-sdk:1.0.0' - compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.8.5' compile project(":protocol") compile project(":common") compile project(":crypto") + compile "org.fusesource.jansi:jansi:$jansiVersion" + compile 'io.github.tronprotocol:zksnark-java-sdk:1.0.0' compile 'org.reflections:reflections:0.9.11' } diff --git a/common/build.gradle b/common/build.gradle index 0431316c009..2cf15ec6efd 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -8,7 +8,6 @@ sourceCompatibility = 1.8 // Dependency versions // --------------------------------------- - def leveldbVersion = "1.8" // -------------------------------------- @@ -30,13 +29,7 @@ if (isWindows()) { } } -repositories { - mavenCentral() -} - dependencies { - testCompile group: 'junit', name: 'junit', version: '4.13.2' - compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.13.4.1' compile "com.cedarsoftware:java-util:1.8.0" compile group: 'org.apache.httpcomponents', name: 'httpasyncclient', version: '4.1.1' diff --git a/consensus/build.gradle b/consensus/build.gradle index 78f60bd7530..4ecd7180d13 100644 --- a/consensus/build.gradle +++ b/consensus/build.gradle @@ -1,21 +1,8 @@ description = "consensus – a distributed consensus arithmetic for blockchain." -// Dependency versions -// --------------------------------------- -def junitVersion = "4.13.2" -def mockitoVersion = "2.1.0" -def testNgVersion = "6.11" -def slf4jVersion = "1.7.25" -// -------------------------------------- - dependencies { compile project(":chainbase") compile project(":protocol") - testImplementation "junit:junit:$junitVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - compile "org.slf4j:jcl-over-slf4j:$slf4jVersion" - compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' - compile group: 'commons-codec', name: 'commons-codec', version: '1.11' } test { diff --git a/crypto/build.gradle b/crypto/build.gradle index 5bbfc630c45..b551471bf49 100644 --- a/crypto/build.gradle +++ b/crypto/build.gradle @@ -11,8 +11,6 @@ repositories { } dependencies { - testCompile group: 'junit', name: 'junit', version: '4.13.2' - compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' compile project(":common") } diff --git a/framework/build.gradle b/framework/build.gradle index 1c817f545f0..877ed4e9073 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -40,40 +40,17 @@ dependencies { //local libraries compile fileTree(dir: 'libs', include: '*.jar') // end local libraries - testCompile group: 'junit', name: 'junit', version: '4.13.2' - testCompile group: 'org.mockito', name: 'mockito-core', version: '2.13.0' testCompile group: 'org.hamcrest', name: 'hamcrest-junit', version: '1.0.0.1' testCompile group: 'com.github.stefanbirkner', name: 'system-rules', version: '1.16.0' - compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' - - compile group: 'com.typesafe', name: 'config', version: '1.3.2' - - compile "com.cedarsoftware:java-util:1.8.0" - - compile group: 'com.beust', name: 'jcommander', version: '1.72' - - compile group: 'junit', name: 'junit', version: '4.13.2' - - compile group: 'net.jcip', name: 'jcip-annotations', version: '1.0' - compile group: 'com.google.inject', name: 'guice', version: '4.1.0' - - compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.8.5' - compile group: 'io.dropwizard.metrics', name: 'metrics-core', version: '3.1.2' compile group: 'com.github.davidb', name: 'metrics-influxdb', version: '0.8.2' - compile group: 'com.carrotsearch', name: 'java-sizeof', version: '0.0.5' - - //compile 'com.googlecode.cqengine:cqengine:2.12.4' - compile group: 'com.google.api.grpc', name: 'proto-google-common-protos', version: '2.15.0' - // http compile 'org.eclipse.jetty:jetty-server:9.4.53.v20231009' compile 'org.eclipse.jetty:jetty-servlet:9.4.53.v20231009' compile 'com.alibaba:fastjson:1.2.83' - compile group: 'org.apache.httpcomponents', name: 'httpasyncclient', version: '4.1.1' // end http // https://mvnrepository.com/artifact/com.github.briandilley.jsonrpc4j/jsonrpc4j diff --git a/plugins/build.gradle b/plugins/build.gradle index 3085bb24bdc..7f226d7099c 100644 --- a/plugins/build.gradle +++ b/plugins/build.gradle @@ -26,9 +26,6 @@ configurations.getByName('checkstyleConfig') { dependencies { //local libraries compile fileTree(dir: 'libs', include: '*.jar') - testCompile group: 'junit', name: 'junit', version: '4.13.2' - testCompile group: 'org.mockito', name: 'mockito-core', version: '2.13.0' - testCompile group: 'org.hamcrest', name: 'hamcrest-junit', version: '1.0.0.1' testCompile project(":framework") testCompile project(":framework").sourceSets.test.output compile group: 'info.picocli', name: 'picocli', version: '4.6.3' From acfaac819a3fdcad50611cdcae26d44a626ea473 Mon Sep 17 00:00:00 2001 From: Brown Jiang <317787106@qq.com> Date: Wed, 27 Dec 2023 11:55:14 +0800 Subject: [PATCH 0929/1197] feat(net):fix a concurrency issue for toString in BlockCapsule (#5594) --- .../org/tron/core/capsule/BlockCapsule.java | 3 +-- .../tron/core/capsule/BlockCapsuleTest.java | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java index 8baafcb5dd5..01ff7fb5365 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java @@ -56,7 +56,6 @@ public class BlockCapsule implements ProtoCapsule { private Block block; private List transactions = new ArrayList<>(); - private StringBuilder toStringBuff = new StringBuilder(); private boolean isSwitch; @Getter @Setter @@ -314,7 +313,7 @@ public boolean hasWitnessSignature() { @Override public String toString() { - toStringBuff.setLength(0); + StringBuilder toStringBuff = new StringBuilder(); toStringBuff.append("BlockCapsule \n[ "); toStringBuff.append("hash=").append(getBlockId()).append("\n"); diff --git a/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java index 0dd078dedb0..3c86d893895 100644 --- a/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java @@ -2,7 +2,9 @@ import com.google.protobuf.ByteString; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; import org.junit.Assert; @@ -146,4 +148,20 @@ public void testGetTimeStamp() { Assert.assertEquals(1234L, blockCapsule0.getTimeStamp()); } + @Test + public void testConcurrentToString() throws InterruptedException { + List threadList = new ArrayList<>(); + int n = 10; + for (int i = 0; i < n; i++) { + threadList.add(new Thread(() -> blockCapsule0.toString())); + } + for (int i = 0; i < n; i++) { + threadList.get(i).start(); + } + for (int i = 0; i < n; i++) { + threadList.get(i).join(); + } + Assert.assertTrue(true); + } + } From 565aef5d58121a3a25d12d999301c592be53440f Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Wed, 27 Dec 2023 12:01:47 +0800 Subject: [PATCH 0930/1197] feat(api): print more details for unexpected error (#5601) --- framework/src/main/java/org/tron/core/services/http/Util.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/http/Util.java b/framework/src/main/java/org/tron/core/services/http/Util.java index 8f27521495a..2b6b929d8a0 100644 --- a/framework/src/main/java/org/tron/core/services/http/Util.java +++ b/framework/src/main/java/org/tron/core/services/http/Util.java @@ -475,7 +475,7 @@ public static String getMemo(byte[] memo) { } public static void processError(Exception e, HttpServletResponse response) { - logger.debug("Exception: {}", e.getMessage()); + logger.debug(e.getMessage(), e); try { response.getWriter().println(Util.printErrorMsg(e)); } catch (IOException ioe) { From a76e17704e99dd8cbbb4d38979d07d2d7c0306ac Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Wed, 27 Dec 2023 12:11:49 +0800 Subject: [PATCH 0931/1197] test(plugins/dbLite): add test for merge function (#5603) --- plugins/src/test/java/org/tron/plugins/DbLiteTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/src/test/java/org/tron/plugins/DbLiteTest.java b/plugins/src/test/java/org/tron/plugins/DbLiteTest.java index 8baf48b0b48..5cb8c26c4bc 100644 --- a/plugins/src/test/java/org/tron/plugins/DbLiteTest.java +++ b/plugins/src/test/java/org/tron/plugins/DbLiteTest.java @@ -117,8 +117,8 @@ void testTools(String dbType, int checkpointVersion) cli.execute(argsForSnapshot); // start fullNode startApp(); - // produce transactions for 6 seconds - generateSomeTransactions(6); + // produce transactions + generateSomeTransactions(checkpointVersion == 1 ? 6 : 18); // stop the node shutdown(); // generate history @@ -139,7 +139,7 @@ void testTools(String dbType, int checkpointVersion) } // start and validate the snapshot startApp(); - generateSomeTransactions(6); + generateSomeTransactions(checkpointVersion == 1 ? 18 : 6); // stop the node shutdown(); // merge history From c4d7635200d3cac0f59cfd0c29b7a1324e65b3d2 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Wed, 27 Dec 2023 12:15:26 +0800 Subject: [PATCH 0932/1197] feat(log/api): separate unexpected and expected logs (#5624) --- .../java/org/tron/core/services/RpcApiService.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 2e3994c3250..c5077facf6f 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -2475,9 +2475,13 @@ public void createShieldedContractParameters( ShieldedTRC20Parameters shieldedTRC20Parameters = wallet .createShieldedContractParameters(request); responseObserver.onNext(shieldedTRC20Parameters); + } catch (ZksnarkException | ContractValidateException e) { + responseObserver.onError(getRunTimeException(e)); + logger.info("createShieldedContractParameters: {}", e.getMessage()); + return; } catch (Exception e) { responseObserver.onError(getRunTimeException(e)); - logger.info("createShieldedContractParameters exception caught: " + e.getMessage()); + logger.error("createShieldedContractParameters: ", e); return; } responseObserver.onCompleted(); @@ -2518,9 +2522,13 @@ public void scanShieldedTRC20NotesByIvk( request.getNk().toByteArray(), request.getEventsList()); responseObserver.onNext(decryptNotes); + } catch (BadItemException | ZksnarkException e) { + responseObserver.onError(getRunTimeException(e)); + logger.info("scanShieldedTRC20NotesByIvk: {}", e.getMessage()); + return; } catch (Exception e) { responseObserver.onError(getRunTimeException(e)); - logger.info("scanShieldedTRC20NotesByIvk exception caught: " + e.getMessage()); + logger.error("scanShieldedTRC20NotesByIvk:", e); return; } responseObserver.onCompleted(); From 989115a03f3d1c72a31486bba3f0e0846b3bbb6f Mon Sep 17 00:00:00 2001 From: Brown Jiang <317787106@qq.com> Date: Wed, 27 Dec 2023 12:22:04 +0800 Subject: [PATCH 0933/1197] feat(net): add codeVersion for HelloMessage (#5584) --- .../core/net/message/handshake/HelloMessage.java | 12 ++++++++++-- .../tron/core/net/services/HandShakeServiceTest.java | 4 ++++ protocol/src/main/protos/core/Tron.proto | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java b/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java index 9efb223fdb7..b98d0e173fb 100755 --- a/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java @@ -11,6 +11,7 @@ import org.tron.core.net.message.MessageTypes; import org.tron.core.net.message.TronMessage; import org.tron.p2p.discover.Node; +import org.tron.program.Version; import org.tron.protos.Discover.Endpoint; import org.tron.protos.Protocol; import org.tron.protos.Protocol.HelloMessage.Builder; @@ -61,6 +62,7 @@ public HelloMessage(Node from, long timestamp, ChainBaseManager chainBaseManager builder.setNodeType(chainBaseManager.getNodeType().getType()); builder.setLowestBlockNum(chainBaseManager.isLiteNode() ? chainBaseManager.getLowestBlockNum() : 0); + builder.setCodeVersion(ByteString.copyFrom(Version.getVersion().getBytes())); this.helloMessage = builder.build(); this.type = MessageTypes.P2P_HELLO.asByte(); @@ -127,17 +129,23 @@ public String toString() { .append("lowestBlockNum: ").append(helloMessage.getLowestBlockNum()).append("\n"); ByteString address = helloMessage.getAddress(); - if (address != null && !address.isEmpty()) { + if (!address.isEmpty()) { builder.append("address:") .append(StringUtil.encode58Check(address.toByteArray())).append("\n"); } ByteString signature = helloMessage.getSignature(); - if (signature != null && !signature.isEmpty()) { + if (!signature.isEmpty()) { builder.append("signature:") .append(signature.toByteArray().length).append("\n"); } + ByteString codeVersion = helloMessage.getCodeVersion(); + if (!codeVersion.isEmpty()) { + builder.append("codeVersion:") + .append(new String(codeVersion.toByteArray())).append("\n"); + } + return builder.toString(); } diff --git a/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java b/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java index e027749458f..ea2156ae713 100644 --- a/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java @@ -38,6 +38,7 @@ import org.tron.p2p.connection.Channel; import org.tron.p2p.discover.Node; import org.tron.p2p.utils.NetUtil; +import org.tron.program.Version; import org.tron.protos.Discover.Endpoint; import org.tron.protos.Protocol; import org.tron.protos.Protocol.HelloMessage.Builder; @@ -99,6 +100,9 @@ public void testOkHelloMessage() Node node = new Node(NetUtil.getNodeId(), a1.getAddress().getHostAddress(), null, a1.getPort()); HelloMessage helloMessage = new HelloMessage(node, System.currentTimeMillis(), ChainBaseManager.getChainBaseManager()); + + Assert.assertEquals(Version.getVersion(), + new String(helloMessage.getHelloMessage().getCodeVersion().toByteArray())); method.invoke(p2pEventHandler, peer, helloMessage.getSendBytes()); //dup hello message diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 2fc08901e93..41ef968d907 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -626,6 +626,7 @@ message HelloMessage { bytes signature = 8; int32 nodeType = 9; int64 lowestBlockNum = 10; + bytes codeVersion = 11; } message InternalTransaction { From 0d48db4870390f2afdb19bd4ca51a9baf7e4a334 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 28 Dec 2023 10:41:49 +0800 Subject: [PATCH 0934/1197] =?UTF-8?q?feat(net):=C2=A0stop=20broadcasting?= =?UTF-8?q?=20transactions=20when=20the=20block=20cannot=20be=20solidified?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/parameter/CommonParameter.java | 8 +++ .../src/main/java/org/tron/core/Constant.java | 4 ++ .../src/main/java/org/tron/core/Wallet.java | 7 +++ .../java/org/tron/core/config/args/Args.java | 10 ++++ .../org/tron/core/net/TronNetDelegate.java | 15 ++++++ .../messagehandler/InventoryMsgHandler.java | 7 +++ .../org/tron/core/config/args/ArgsTest.java | 2 + .../tron/core/net/TronNetDelegateTest.java | 51 +++++++++++++++++++ .../InventoryMsgHandlerTest.java | 22 +++++++- protocol/src/main/protos/api/api.proto | 2 + 10 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/net/TronNetDelegateTest.java diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index f8f6e6c5edb..319dd025c90 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -651,6 +651,14 @@ public class CommonParameter { @Setter public long allowCancelAllUnfreezeV2; + @Getter + @Setter + public boolean unsolidifiedBlockCheck; + + @Getter + @Setter + public int maxUnsolidifiedBlocks; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index ba867793b41..96e99b72079 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -371,4 +371,8 @@ public class Constant { public static final String DYNAMIC_CONFIG_CHECK_INTERVAL = "node.dynamicConfig.checkInterval"; public static final String COMMITTEE_ALLOW_TVM_SHANGHAI = "committee.allowTvmShangHai"; + + public static final String UNSOLIDIFIED_BLOCK_CHECK = "node.unsolidifiedBlockCheck"; + + public static final String MAX_UNSOLIDIFIED_BLOCKS = "node.maxUnsolidifiedBlocks"; } diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 0865e202974..a36ea5855ec 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -520,6 +520,13 @@ public GrpcAPI.Return broadcastTransaction(Transaction signedTransaction) { } } + if (tronNetDelegate.unsolidifiedBlockCheck()) { + logger.warn("Broadcast transaction {} has failed, block unsolidified.", txID); + return builder.setResult(false).setCode(response_code.BLOCK_UNSOLIDIFIED) + .setMessage(ByteString.copyFromUtf8("Bock unsolidified.")) + .build(); + } + if (dbManager.isTooManyPending()) { logger.warn("Broadcast transaction {} has failed, too many pending.", txID); return builder.setResult(false).setCode(response_code.SERVER_BUSY) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 75140dd5f54..0ca6b004fa7 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -230,6 +230,8 @@ public static void clearParam() { PARAMETER.dynamicConfigEnable = false; PARAMETER.dynamicConfigCheckInterval = 600; PARAMETER.allowTvmShangHai = 0; + PARAMETER.unsolidifiedBlockCheck = true; + PARAMETER.maxUnsolidifiedBlocks = 1000; } /** @@ -1178,6 +1180,14 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.COMMITTEE_ALLOW_TVM_SHANGHAI) ? config .getInt(Constant.COMMITTEE_ALLOW_TVM_SHANGHAI) : 0; + PARAMETER.unsolidifiedBlockCheck = + !config.hasPath(Constant.UNSOLIDIFIED_BLOCK_CHECK) + || config.getBoolean(Constant.UNSOLIDIFIED_BLOCK_CHECK); + + PARAMETER.maxUnsolidifiedBlocks = + config.hasPath(Constant.MAX_UNSOLIDIFIED_BLOCKS) ? config + .getInt(Constant.MAX_UNSOLIDIFIED_BLOCKS) : 1000; + logConfig(); } diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index 5d09e67908d..3aa06362cc9 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -29,6 +29,7 @@ import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.capsule.PbftSignCapsule; import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.config.args.Args; import org.tron.core.db.Manager; import org.tron.core.exception.AccountResourceInsufficientException; import org.tron.core.exception.BadBlockException; @@ -98,6 +99,11 @@ public class TronNetDelegate { @Setter private volatile boolean exit = true; + private int maxUnsolidifiedBlocks = Args.getInstance().getMaxUnsolidifiedBlocks(); + + private boolean unsolidifiedBlockCheck + = Args.getInstance().isUnsolidifiedBlockCheck(); + private Cache freshBlockId = CacheBuilder.newBuilder() .maximumSize(blockIdCacheSize).expireAfterWrite(1, TimeUnit.HOURS) .recordStats().build(); @@ -365,4 +371,13 @@ public long getMaintenanceTimeInterval() { return chainBaseManager.getDynamicPropertiesStore().getMaintenanceTimeInterval(); } + public boolean unsolidifiedBlockCheck() { + if (!unsolidifiedBlockCheck) { + return false; + } + long headNum = chainBaseManager.getHeadBlockNum(); + long solidNum = chainBaseManager.getSolidBlockId().getNum(); + return headNum - solidNum >= maxUnsolidifiedBlocks; + } + } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java index 02b04d73b32..40b0db33482 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java @@ -43,6 +43,7 @@ public void processMessage(PeerConnection peer, TronMessage msg) { } private boolean check(PeerConnection peer, InventoryMessage inventoryMessage) { + InventoryType type = inventoryMessage.getInventoryType(); int size = inventoryMessage.getHashList().size(); @@ -52,6 +53,12 @@ private boolean check(PeerConnection peer, InventoryMessage inventoryMessage) { return false; } + if (type.equals(InventoryType.TRX) && tronNetDelegate.unsolidifiedBlockCheck()) { + logger.warn("Drop inv: {} size: {} from Peer {}, block unsolidified", + type, size, peer.getInetAddress()); + return false; + } + if (type.equals(InventoryType.TRX) && transactionsMsgHandler.isBusy()) { logger.warn("Drop inv: {} size: {} from Peer {}, transactionsMsgHandler is busy", type, size, peer.getInetAddress()); diff --git a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java index 13e272d1e13..78d3ea0c6e6 100644 --- a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java @@ -102,6 +102,8 @@ public void get() { Assert.assertEquals(0, parameter.getActiveNodes().size()); Assert.assertEquals(30, parameter.getMaxConnections()); Assert.assertEquals(43, parameter.getNodeP2pVersion()); + Assert.assertEquals(1000, parameter.getMaxUnsolidifiedBlocks()); + Assert.assertEquals(true, parameter.isUnsolidifiedBlockCheck()); //Assert.assertEquals(30, args.getSyncNodeCount()); // gRPC network configs checking diff --git a/framework/src/test/java/org/tron/core/net/TronNetDelegateTest.java b/framework/src/test/java/org/tron/core/net/TronNetDelegateTest.java new file mode 100644 index 00000000000..674c13a73fe --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/TronNetDelegateTest.java @@ -0,0 +1,51 @@ +package org.tron.core.net; + +import static org.mockito.Mockito.mock; + +import java.lang.reflect.Field; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.ChainBaseManager; +import org.tron.core.Constant; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.config.args.Args; + +public class TronNetDelegateTest { + + @Test + public void test() throws Exception { + Args.setParam(new String[] {"-w"}, Constant.TEST_CONF); + CommonParameter parameter = Args.getInstance(); + Args.logConfig(); + + BlockCapsule.BlockId blockId = new BlockCapsule.BlockId(Sha256Hash.ZERO_HASH, 10000L); + + TronNetDelegate tronNetDelegate = new TronNetDelegate(); + + ChainBaseManager chainBaseManager = mock(ChainBaseManager.class); + Mockito.when(chainBaseManager.getHeadBlockNum()).thenReturn(10000L); + Mockito.when(chainBaseManager.getSolidBlockId()).thenReturn(blockId); + + Field field = tronNetDelegate.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(tronNetDelegate, chainBaseManager); + + Assert.assertTrue(!tronNetDelegate.unsolidifiedBlockCheck()); + + blockId = new BlockCapsule.BlockId(Sha256Hash.ZERO_HASH, 1L); + Mockito.when(chainBaseManager.getSolidBlockId()).thenReturn(blockId); + Assert.assertTrue(tronNetDelegate.unsolidifiedBlockCheck()); + + parameter.setUnsolidifiedBlockCheck(false); + tronNetDelegate = new TronNetDelegate(); + + field = tronNetDelegate.getClass().getDeclaredField("unsolidifiedBlockCheck"); + field.setAccessible(true); + field.set(tronNetDelegate, false); + + Assert.assertTrue(!tronNetDelegate.unsolidifiedBlockCheck()); + } +} diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/InventoryMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/InventoryMsgHandlerTest.java index 97db6207b2a..ee16d333193 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/InventoryMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/InventoryMsgHandlerTest.java @@ -1,10 +1,16 @@ package org.tron.core.net.messagehandler; +import static org.mockito.Mockito.mock; + import java.lang.reflect.Field; import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.ArrayList; import org.junit.Test; +import org.mockito.Mockito; +import org.tron.core.Constant; +import org.tron.core.config.args.Args; +import org.tron.core.net.TronNetDelegate; import org.tron.core.net.message.adv.InventoryMessage; import org.tron.core.net.peer.PeerConnection; import org.tron.p2p.connection.Channel; @@ -12,10 +18,12 @@ public class InventoryMsgHandlerTest { - private InventoryMsgHandler handler = new InventoryMsgHandler(); - @Test public void testProcessMessage() throws Exception { + InventoryMsgHandler handler = new InventoryMsgHandler(); + Args.setParam(new String[] {"-w"}, Constant.TEST_CONF); + Args.logConfig(); + InventoryMessage msg = new InventoryMessage(new ArrayList<>(), InventoryType.TRX); PeerConnection peer = new PeerConnection(); peer.setChannel(getChannel("1.0.0.3", 1000)); @@ -31,6 +39,16 @@ public void testProcessMessage() throws Exception { peer.setNeedSyncFromUs(true); handler.processMessage(peer, msg); + peer.setNeedSyncFromUs(false); + + TronNetDelegate tronNetDelegate = mock(TronNetDelegate.class); + Mockito.when(tronNetDelegate.unsolidifiedBlockCheck()).thenReturn(true); + + Field field = handler.getClass().getDeclaredField("tronNetDelegate"); + field.setAccessible(true); + field.set(handler, tronNetDelegate); + + handler.processMessage(peer, msg); } private Channel getChannel(String host, int port) throws Exception { diff --git a/protocol/src/main/protos/api/api.proto b/protocol/src/main/protos/api/api.proto index 9a7534cf6ce..2505fa48d6f 100644 --- a/protocol/src/main/protos/api/api.proto +++ b/protocol/src/main/protos/api/api.proto @@ -1051,6 +1051,8 @@ message Return { SERVER_BUSY = 9; NO_CONNECTION = 10; NOT_ENOUGH_EFFECTIVE_CONNECTION = 11; + BLOCK_UNSOLIDIFIED = 12; + OTHER_ERROR = 20; } From a0f431cfe3783c56cf32bfc6071dbe2bde0e4180 Mon Sep 17 00:00:00 2001 From: Brown Jiang <317787106@qq.com> Date: Fri, 29 Dec 2023 10:45:06 +0800 Subject: [PATCH 0935/1197] feat(net): delete config item node.discovery.bind.ip (#5597) * delete config item node.bind.ip * remove bindIp method from Args * get lan ip from libp2p --- common/build.gradle | 2 +- .../common/parameter/CommonParameter.java | 2 +- .../src/main/java/org/tron/core/Constant.java | 2 -- .../java/org/tron/core/config/args/Args.java | 30 ++++--------------- .../org/tron/core/config/args/ArgsTest.java | 19 +----------- .../core/services/RpcApiServicesTest.java | 6 ++-- .../LiteFnQueryGrpcInterceptorTest.java | 6 ++-- .../filter/RpcApiAccessInterceptorTest.java | 6 ++-- .../test/resources/config-test-mainnet.conf | 1 - .../resources/config-test-storagetest.conf | 1 - framework/src/test/resources/config-test.conf | 1 - 11 files changed, 17 insertions(+), 59 deletions(-) diff --git a/common/build.gradle b/common/build.gradle index 2cf15ec6efd..ba1c431e74c 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -46,7 +46,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'io.github.tronprotocol', name: 'libp2p', version: '2.1.0',{ + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v2.2.1',{ exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 1ad50e1e359..c42276e01bb 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -176,7 +176,7 @@ public class CommonParameter { public int nodeListenPort; @Getter @Setter - public String nodeDiscoveryBindIp; + public String nodeLanIp; @Getter @Setter public String nodeExternalIp; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index d7ec3b715c9..f739358156f 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -281,8 +281,6 @@ public class Constant { public static final String EVENT_SUBSCRIBE_CONTRACT_ADDRESS = "event.subscribe.filter.contractAddress"; public static final String EVENT_SUBSCRIBE_CONTRACT_TOPIC = "event.subscribe.filter.contractTopic"; - public static final String NODE_DISCOVERY_BIND_IP = "node.discovery.bind.ip"; - public static final String NODE_DISCOVERY_EXTERNAL_IP = "node.discovery.external.ip"; public static final String NODE_BACKUP_PRIORITY = "node.backup.priority"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index aff6708dfff..b5f7d97726e 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -20,7 +20,6 @@ import java.io.InputStream; import java.net.InetAddress; import java.net.InetSocketAddress; -import java.net.Socket; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; @@ -136,7 +135,7 @@ public static void clearParam() { PARAMETER.maxTps = 1000; PARAMETER.minParticipationRate = 0; PARAMETER.nodeListenPort = 0; - PARAMETER.nodeDiscoveryBindIp = ""; + PARAMETER.nodeLanIp = ""; PARAMETER.nodeExternalIp = ""; PARAMETER.nodeP2pVersion = 0; PARAMETER.nodeEnableIpv6 = false; @@ -635,7 +634,7 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.NODE_LISTEN_PORT) ? config.getInt(Constant.NODE_LISTEN_PORT) : 0; - bindIp(config); + PARAMETER.nodeLanIp = PARAMETER.p2pConfig.getLanIp(); externalIp(config); PARAMETER.nodeP2pVersion = @@ -1247,7 +1246,7 @@ public static List getInetSocketAddress( if (filter) { String ip = inetSocketAddress.getAddress().getHostAddress(); int port = inetSocketAddress.getPort(); - if (!(PARAMETER.nodeDiscoveryBindIp.equals(ip) + if (!(PARAMETER.nodeLanIp.equals(ip) || PARAMETER.nodeExternalIp.equals(ip) || Constant.LOCAL_HOST.equals(ip)) || PARAMETER.nodeListenPort != port) { @@ -1525,25 +1524,6 @@ private static FilterQuery getEventFilter(final com.typesafe.config.Config confi return filter; } - private static void bindIp(final com.typesafe.config.Config config) { - if (!config.hasPath(Constant.NODE_DISCOVERY_BIND_IP) - || config.getString(Constant.NODE_DISCOVERY_BIND_IP) - .trim().isEmpty()) { - if (PARAMETER.nodeDiscoveryBindIp == null) { - logger.info("Bind address wasn't set, Punching to identify it..."); - try (Socket s = new Socket("www.baidu.com", 80)) { - PARAMETER.nodeDiscoveryBindIp = s.getLocalAddress().getHostAddress(); - logger.info("UDP local bound to: {}", PARAMETER.nodeDiscoveryBindIp); - } catch (IOException e) { - logger.warn("Can't get bind IP. Fall back to 127.0.0.1: " + e); - PARAMETER.nodeDiscoveryBindIp = "127.0.0.1"; - } - } - } else { - PARAMETER.nodeDiscoveryBindIp = config.getString(Constant.NODE_DISCOVERY_BIND_IP).trim(); - } - } - private static void externalIp(final com.typesafe.config.Config config) { if (!config.hasPath(Constant.NODE_DISCOVERY_EXTERNAL_IP) || config .getString(Constant.NODE_DISCOVERY_EXTERNAL_IP).trim().isEmpty()) { @@ -1551,7 +1531,7 @@ private static void externalIp(final com.typesafe.config.Config config) { logger.info("External IP wasn't set, using ipv4 from libp2p"); PARAMETER.nodeExternalIp = PARAMETER.p2pConfig.getIp(); if (StringUtils.isEmpty(PARAMETER.nodeExternalIp)) { - PARAMETER.nodeExternalIp = PARAMETER.nodeDiscoveryBindIp; + PARAMETER.nodeExternalIp = PARAMETER.nodeLanIp; } } } else { @@ -1622,7 +1602,7 @@ public static void logConfig() { logger.info("\n"); logger.info("************************ Net config ************************"); logger.info("P2P version: {}", parameter.getNodeP2pVersion()); - logger.info("Bind IP: {}", parameter.getNodeDiscoveryBindIp()); + logger.info("LAN IP: {}", parameter.getNodeLanIp()); logger.info("External IP: {}", parameter.getNodeExternalIp()); logger.info("Listen port: {}", parameter.getNodeListenPort()); logger.info("Node ipv6 enable: {}", parameter.isNodeEnableIpv6()); diff --git a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java index 13e272d1e13..56e418be7c1 100644 --- a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java @@ -17,11 +17,6 @@ import com.google.common.collect.Lists; import com.typesafe.config.Config; -import com.typesafe.config.ConfigMergeable; -import com.typesafe.config.ConfigOrigin; -import com.typesafe.config.ConfigRenderOptions; -import com.typesafe.config.ConfigValue; -import com.typesafe.config.ConfigValueType; import io.grpc.internal.GrpcUtil; import io.grpc.netty.NettyServerBuilder; import java.lang.reflect.InvocationTargetException; @@ -36,10 +31,8 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.LocalWitnesses; import org.tron.common.utils.PublicMethod; -import org.tron.common.utils.ReflectUtils; import org.tron.core.Constant; import org.tron.core.config.Configuration; -import org.tron.core.net.peer.PeerManager; @Slf4j public class ArgsTest { @@ -95,7 +88,6 @@ public void get() { Assert.assertTrue(parameter.isNodeDiscoveryEnable()); Assert.assertTrue(parameter.isNodeDiscoveryPersist()); - Assert.assertEquals("127.0.0.1", parameter.getNodeDiscoveryBindIp()); Assert.assertEquals("46.168.1.1", parameter.getNodeExternalIp()); Assert.assertEquals(18888, parameter.getNodeListenPort()); Assert.assertEquals(2000, parameter.getNodeConnectionTimeout()); @@ -130,27 +122,18 @@ public void testIpFromLibP2p() Args.setParam(new String[] {"-w"}, Constant.TEST_CONF); CommonParameter parameter = Args.getInstance(); - String configuredBindIp = parameter.getNodeDiscoveryBindIp(); String configuredExternalIp = parameter.getNodeExternalIp(); - Assert.assertEquals("127.0.0.1", configuredBindIp); Assert.assertEquals("46.168.1.1", configuredExternalIp); Config config = Configuration.getByFileName(null, Constant.TEST_CONF); - Config config2 = config.withoutPath(Constant.NODE_DISCOVERY_BIND_IP); - Config config3 = config2.withoutPath(Constant.NODE_DISCOVERY_EXTERNAL_IP); + Config config3 = config.withoutPath(Constant.NODE_DISCOVERY_EXTERNAL_IP); - CommonParameter.getInstance().setNodeDiscoveryBindIp(null); CommonParameter.getInstance().setNodeExternalIp(null); - Method method1 = Args.class.getDeclaredMethod("bindIp", Config.class); - method1.setAccessible(true); - method1.invoke(Args.class, config3); - Method method2 = Args.class.getDeclaredMethod("externalIp", Config.class); method2.setAccessible(true); method2.invoke(Args.class, config3); - Assert.assertNotEquals(configuredBindIp, parameter.getNodeDiscoveryBindIp()); Assert.assertNotEquals(configuredExternalIp, parameter.getNodeExternalIp()); } } diff --git a/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java b/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java index 8b45b871af7..ebb9e0bb223 100644 --- a/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java +++ b/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java @@ -138,11 +138,11 @@ public static void init() throws IOException { getInstance().setRpcPort(PublicMethod.chooseRandomPort()); getInstance().setRpcOnSolidityPort(PublicMethod.chooseRandomPort()); getInstance().setRpcOnPBFTPort(PublicMethod.chooseRandomPort()); - String fullNode = String.format("%s:%d", getInstance().getNodeDiscoveryBindIp(), + String fullNode = String.format("%s:%d", getInstance().getNodeLanIp(), getInstance().getRpcPort()); - String solidityNode = String.format("%s:%d", getInstance().getNodeDiscoveryBindIp(), + String solidityNode = String.format("%s:%d", getInstance().getNodeLanIp(), getInstance().getRpcOnSolidityPort()); - String pBFTNode = String.format("%s:%d", getInstance().getNodeDiscoveryBindIp(), + String pBFTNode = String.format("%s:%d", getInstance().getNodeLanIp(), getInstance().getRpcOnPBFTPort()); ManagedChannel channelFull = ManagedChannelBuilder.forTarget(fullNode) diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java index 00f2c2fc086..081b5839f84 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java @@ -58,11 +58,11 @@ public static void init() throws IOException { Args.getInstance().setRpcPort(PublicMethod.chooseRandomPort()); Args.getInstance().setRpcOnSolidityPort(PublicMethod.chooseRandomPort()); Args.getInstance().setRpcOnPBFTPort(PublicMethod.chooseRandomPort()); - String fullnode = String.format("%s:%d", Args.getInstance().getNodeDiscoveryBindIp(), + String fullnode = String.format("%s:%d", Args.getInstance().getNodeLanIp(), Args.getInstance().getRpcPort()); - String solidityNode = String.format("%s:%d", Args.getInstance().getNodeDiscoveryBindIp(), + String solidityNode = String.format("%s:%d", Args.getInstance().getNodeLanIp(), Args.getInstance().getRpcOnSolidityPort()); - String pBFTNode = String.format("%s:%d", Args.getInstance().getNodeDiscoveryBindIp(), + String pBFTNode = String.format("%s:%d", Args.getInstance().getNodeLanIp(), Args.getInstance().getRpcOnPBFTPort()); channelFull = ManagedChannelBuilder.forTarget(fullnode) .usePlaintext() diff --git a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java index 7d95c0c368a..38af756f790 100644 --- a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java @@ -59,11 +59,11 @@ public static void init() throws IOException { Args.getInstance().setRpcPort(PublicMethod.chooseRandomPort()); Args.getInstance().setRpcOnSolidityPort(PublicMethod.chooseRandomPort()); Args.getInstance().setRpcOnPBFTPort(PublicMethod.chooseRandomPort()); - String fullNode = String.format("%s:%d", Args.getInstance().getNodeDiscoveryBindIp(), + String fullNode = String.format("%s:%d", Args.getInstance().getNodeLanIp(), Args.getInstance().getRpcPort()); - String solidityNode = String.format("%s:%d", Args.getInstance().getNodeDiscoveryBindIp(), + String solidityNode = String.format("%s:%d", Args.getInstance().getNodeLanIp(), Args.getInstance().getRpcOnSolidityPort()); - String pBFTNode = String.format("%s:%d", Args.getInstance().getNodeDiscoveryBindIp(), + String pBFTNode = String.format("%s:%d", Args.getInstance().getNodeLanIp(), Args.getInstance().getRpcOnPBFTPort()); ManagedChannel channelFull = ManagedChannelBuilder.forTarget(fullNode) diff --git a/framework/src/test/resources/config-test-mainnet.conf b/framework/src/test/resources/config-test-mainnet.conf index 43a01a0feb9..ad72d2afaaa 100644 --- a/framework/src/test/resources/config-test-mainnet.conf +++ b/framework/src/test/resources/config-test-mainnet.conf @@ -53,7 +53,6 @@ storage { node.discovery = { enable = true persist = true - bind.ip = "127.0.0.1" external.ip = "46.168.1.1" } diff --git a/framework/src/test/resources/config-test-storagetest.conf b/framework/src/test/resources/config-test-storagetest.conf index 5098e39b650..d2dc27b795a 100644 --- a/framework/src/test/resources/config-test-storagetest.conf +++ b/framework/src/test/resources/config-test-storagetest.conf @@ -76,7 +76,6 @@ storage { node.discovery = { enable = true persist = true - bind.ip = "127.0.0.1" external.ip = "46.168.1.1" } diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index 304ad125340..68a48ca64b2 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -74,7 +74,6 @@ storage { node.discovery = { enable = true persist = true - bind.ip = "127.0.0.1" external.ip = "46.168.1.1" } From d518512e32fdc3ca857c2ef8d44ef9ccb169cd57 Mon Sep 17 00:00:00 2001 From: liukai Date: Tue, 2 Jan 2024 14:34:04 +0800 Subject: [PATCH 0936/1197] feat(LiteFullNode): remove LiteFullNodeTool --- framework/build.gradle | 6 - .../org/tron/tool/litefullnode/DbTool.java | 199 ------ .../tool/litefullnode/LiteFullNodeTool.java | 637 ------------------ .../java/org/tron/tool/litefullnode/README.md | 109 --- .../java/org/tron/tool/litefullnode/Util.java | 62 -- .../tool/litefullnode/db/DBInterface.java | 21 - .../tool/litefullnode/db/LevelDBImpl.java | 46 -- .../tool/litefullnode/db/RocksDBImpl.java | 66 -- .../litefullnode/iterator/DBIterator.java | 18 - .../iterator/LevelDBIterator.java | 47 -- .../litefullnode/iterator/RockDBIterator.java | 48 -- .../tron/program/LiteFullNodeToolTest.java | 202 ------ plugins/README.md | 5 - 13 files changed, 1466 deletions(-) delete mode 100644 framework/src/main/java/org/tron/tool/litefullnode/DbTool.java delete mode 100644 framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java delete mode 100644 framework/src/main/java/org/tron/tool/litefullnode/README.md delete mode 100644 framework/src/main/java/org/tron/tool/litefullnode/Util.java delete mode 100644 framework/src/main/java/org/tron/tool/litefullnode/db/DBInterface.java delete mode 100644 framework/src/main/java/org/tron/tool/litefullnode/db/LevelDBImpl.java delete mode 100644 framework/src/main/java/org/tron/tool/litefullnode/db/RocksDBImpl.java delete mode 100644 framework/src/main/java/org/tron/tool/litefullnode/iterator/DBIterator.java delete mode 100644 framework/src/main/java/org/tron/tool/litefullnode/iterator/LevelDBIterator.java delete mode 100644 framework/src/main/java/org/tron/tool/litefullnode/iterator/RockDBIterator.java delete mode 100644 framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java diff --git a/framework/build.gradle b/framework/build.gradle index c894ae1e03d..08e2e88e826 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -239,13 +239,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 { @@ -264,10 +262,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/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..ed4235ea58e 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -66,11 +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`. - ### Available parameters: - `-o | --operate`: [split,merge], default: split. From c109b22fbc1530e5705cacf5d616ef8626161e53 Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 4 Jan 2024 14:54:47 +0800 Subject: [PATCH 0937/1197] feat(LiteFullNode): fix deleting titles --- plugins/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/README.md b/plugins/README.md index ed4235ea58e..19c952372c1 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -66,6 +66,10 @@ 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`. + ### Available parameters: - `-o | --operate`: [split,merge], default: split. From db9f3beb942f7519d168d84745cfe861367ce35f Mon Sep 17 00:00:00 2001 From: lurais <107600021+lurais@users.noreply.github.com> Date: Fri, 5 Jan 2024 14:25:25 +0800 Subject: [PATCH 0938/1197] feat(lite): optimize DbLite tool (#5647) --- .../main/java/org/tron/plugins/DbLite.java | 88 ++++--------------- 1 file changed, 15 insertions(+), 73 deletions(-) diff --git a/plugins/src/main/java/org/tron/plugins/DbLite.java b/plugins/src/main/java/org/tron/plugins/DbLite.java index ef7e73ec6d6..8804d6210b2 100644 --- a/plugins/src/main/java/org/tron/plugins/DbLite.java +++ b/plugins/src/main/java/org/tron/plugins/DbLite.java @@ -3,8 +3,6 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Lists; 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; @@ -155,10 +153,10 @@ public void generateSnapshot(String sourceDir, String snapshotDir) { long start = System.currentTimeMillis(); snapshotDir = Paths.get(snapshotDir, SNAPSHOT_DIR_NAME).toString(); try { + mergeCheckpoint(sourceDir); hasEnoughBlock(sourceDir); List snapshotDbs = getSnapshotDbs(sourceDir); split(sourceDir, snapshotDir, snapshotDbs); - mergeCheckpoint2Snapshot(sourceDir, snapshotDir); // write genesisBlock , latest recent blocks and trans fillSnapshotBlockAndTransDb(sourceDir, snapshotDir); // save min block to info @@ -192,9 +190,9 @@ public void generateHistory(String sourceDir, String historyDir) { throw new IllegalStateException( String.format("Unavailable sourceDir: %s is not fullNode data.", sourceDir)); } + mergeCheckpoint(sourceDir); hasEnoughBlock(sourceDir); split(sourceDir, historyDir, archiveDbs); - mergeCheckpoint2History(sourceDir, historyDir); // save max block to info generateInfoProperties(Paths.get(historyDir, INFO_FILE_NAME).toString(), getLatestBlockHeaderNum(sourceDir)); @@ -263,15 +261,6 @@ private List getSnapshotDbs(String sourceDir) { 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."); spec.commandLine().getOut().println("Begin to split the dbs."); @@ -289,7 +278,7 @@ private void split(String sourceDir, String destDir, List dbs) throws IO FileUtils.copyDatabases(Paths.get(sourceDir), Paths.get(destDir), dbs); } - private void mergeCheckpoint(String sourceDir, String destDir, List destDbs) { + private void mergeCheckpoint(String sourceDir) { logger.info("Begin to merge checkpoint to dataset."); spec.commandLine().getOut().println("Begin to merge checkpoint to dataset."); try { @@ -298,18 +287,18 @@ private void mergeCheckpoint(String sourceDir, String destDir, List dest for (String cp : cpList) { DBInterface checkpointDb = DbTool.getDB( sourceDir + "/" + DBUtils.CHECKPOINT_DB_V2, cp); - recover(checkpointDb, destDir, destDbs); + recover(checkpointDb, sourceDir); } } else if (Paths.get(sourceDir, CHECKPOINT_DB).toFile().exists()) { DBInterface tmpDb = DbTool.getDB(sourceDir, CHECKPOINT_DB); - recover(tmpDb, destDir, destDbs); + recover(tmpDb, sourceDir); } } catch (IOException | RocksDBException e) { throw new RuntimeException(e); } } - private void recover(DBInterface db, String destDir, List destDbs) + private void recover(DBInterface db, String destDir) throws IOException, RocksDBException { try (DBIterator iterator = db.iterator()) { for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) { @@ -323,17 +312,15 @@ private void recover(DBInterface db, String destDir, List destDbs) 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); + DBInterface destDb = DbTool.getDB(destDir, dbName); + if (realValue != null) { + destDb.put(realKey, realValue); + } else { + byte op = value[0]; + if (DBUtils.Operator.DELETE.getValue() == op) { + destDb.delete(realKey); } else { - byte op = value[0]; - if (DBUtils.Operator.DELETE.getValue() == op) { - destDb.delete(realKey); - } else { - destDb.put(realKey, new byte[0]); - } + destDb.put(realKey, new byte[0]); } } } @@ -353,23 +340,7 @@ private void generateInfoProperties(String propertyfile, long num) } 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; - if (cpList.size() > 0) { - String lastestCp = cpList.get(cpList.size() - 1); - checkpointDb = DbTool.getDB( - databaseDir + "/" + DBUtils.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) @@ -377,14 +348,6 @@ private long getLatestBlockHeaderNum(String databaseDir) throws IOException, Roc () -> 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. */ @@ -451,15 +414,6 @@ private byte[] getGenesisBlockHash(String parentDir) throws IOException, RocksDB 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 liteDir) throws IOException, RocksDBException { logger.info("Check the compatibility of this history."); @@ -531,7 +485,6 @@ private void trimExtraHistory(String liteDir, BlockNumInfo blockNumInfo) DBInterface transDb = DbTool.getDB(liteDir, TRANS_DB_NAME); DBInterface tranRetDb = DbTool.getDB(liteDir, TRANSACTION_RET_DB_NAME); - ProgressBar.wrap(LongStream.rangeClosed(start, end) .boxed() .sorted((a, b) -> Long.compare(b, a)), "trimHistory").forEach(n -> { @@ -566,7 +519,6 @@ private void mergeBak2Database(String liteDir, BlockNumInfo blockNumInfo) throws return; } - Path bakDir = Paths.get(liteDir, BACKUP_DIR_PREFIX + START_TIME); logger.info("Begin to merge {} to database, start {} end {}.", bakDir, start, end); spec.commandLine().getOut() @@ -593,17 +545,7 @@ private void mergeBak2Database(String liteDir, BlockNumInfo blockNumInfo) throws 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); - } + byte[] value = DbTool.getDB(sourceDir, dbName).get(key); if (isEmptyBytes(value)) { throw new RuntimeException(String.format("data not found in store, dbName: %s, key: %s", dbName, Arrays.toString(key))); From 52b33273b68441bf5b1bf3e97bdcb49ab1b2693c Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Fri, 5 Jan 2024 15:21:25 +0800 Subject: [PATCH 0939/1197] feat(db): optimize old rewards withdrawal (#5406) --- .../org/tron/core/utils/ProposalUtil.java | 23 +- .../core/db/common/iterator/DBIterator.java | 70 ++++- .../db/common/iterator/RockStoreIterator.java | 66 ++++- .../db/common/iterator/StoreIterator.java | 63 +++- .../tron/core/service/MortgageService.java | 45 ++- .../tron/core/service/RewardViCalService.java | 273 +++++++++++++++++ .../core/store/DynamicPropertiesStore.java | 32 ++ .../org/tron/core/store/RewardViStore.java | 43 +++ .../common/parameter/CommonParameter.java | 4 + .../tron/common/prometheus/MetricKeys.java | 2 + .../common/prometheus/MetricsHistogram.java | 2 + .../src/main/java/org/tron/core/Constant.java | 1 + .../java/org/tron/core/config/Parameter.java | 5 +- .../src/main/java/org/tron/core/Wallet.java | 4 + .../java/org/tron/core/config/args/Args.java | 5 + .../tron/core/consensus/ProposalService.java | 4 + .../db/common/iterator/AbstractIterator.java | 41 --- .../common/iterator/AssetIssueIterator.java | 17 -- .../core/db/common/iterator/DBIterator.java | 9 - .../common/iterator/TransactionIterator.java | 22 -- .../db/common/iterator/WitnessIterator.java | 17 -- .../java/org/tron/core/db/DBIteratorTest.java | 110 ++++--- .../tron/core/services/ComputeRewardTest.java | 277 ++++++++++++++++++ .../core/services/ProposalServiceTest.java | 9 + 24 files changed, 969 insertions(+), 175 deletions(-) create mode 100644 chainbase/src/main/java/org/tron/core/service/RewardViCalService.java create mode 100755 chainbase/src/main/java/org/tron/core/store/RewardViStore.java delete mode 100644 framework/src/main/java/org/tron/core/db/common/iterator/AbstractIterator.java delete mode 100644 framework/src/main/java/org/tron/core/db/common/iterator/AssetIssueIterator.java delete mode 100755 framework/src/main/java/org/tron/core/db/common/iterator/DBIterator.java delete mode 100644 framework/src/main/java/org/tron/core/db/common/iterator/TransactionIterator.java delete mode 100644 framework/src/main/java/org/tron/core/db/common/iterator/WitnessIterator.java create mode 100644 framework/src/test/java/org/tron/core/services/ComputeRewardTest.java diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 0f55bbae9b7..cf013266bd0 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -728,6 +728,26 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case ALLOW_OLD_REWARD_OPT: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7_4)) { + throw new ContractValidateException( + "Bad chain parameter id [ALLOW_OLD_REWARD_OPT]"); + } + if (value != 1) { + throw new ContractValidateException( + "This value[ALLOW_OLD_REWARD_OPT] is only allowed to be 1"); + } + if (!dynamicPropertiesStore.useNewRewardAlgorithm()) { + throw new ContractValidateException( + "[ALLOW_NEW_REWARD] proposal must be approved " + + "before [ALLOW_OLD_REWARD_OPT] can be proposed"); + } + if (dynamicPropertiesStore.useNewRewardAlgorithmFromStart()) { + throw new ContractValidateException( + "no need old reward opt, ALLOW_NEW_REWARD from start cycle 1"); + } + break; + } default: break; } @@ -803,7 +823,8 @@ public enum ProposalType { // current value, value range DYNAMIC_ENERGY_MAX_FACTOR(75), // 0, [0, 100_000] ALLOW_TVM_SHANGHAI(76), // 0, 1 ALLOW_CANCEL_ALL_UNFREEZE_V2(77), // 0, 1 - MAX_DELEGATE_LOCK_PERIOD(78); // (86400, 10512000] + MAX_DELEGATE_LOCK_PERIOD(78), // (86400, 10512000] + ALLOW_OLD_REWARD_OPT(79); // 0, 1 private long code; diff --git a/chainbase/src/main/java/org/tron/core/db/common/iterator/DBIterator.java b/chainbase/src/main/java/org/tron/core/db/common/iterator/DBIterator.java index f706623693f..ec8d7fd85be 100755 --- a/chainbase/src/main/java/org/tron/core/db/common/iterator/DBIterator.java +++ b/chainbase/src/main/java/org/tron/core/db/common/iterator/DBIterator.java @@ -1,9 +1,77 @@ package org.tron.core.db.common.iterator; +import com.google.common.collect.Iterators; +import com.google.common.collect.UnmodifiableIterator; +import com.google.common.primitives.Bytes; import java.io.Closeable; import java.util.Iterator; import java.util.Map.Entry; +import java.util.NoSuchElementException; -public interface DBIterator extends Iterator>, Closeable { +public interface DBIterator extends Iterator>, AutoCloseable, Closeable { + void seek(byte[] key); + + void seekToFirst(); + + void seekToLast(); + + default UnmodifiableIterator> prefixQueryAfterThat + (byte[] key, byte[] afterThat) { + this.seek(afterThat == null ? key : afterThat); + return Iterators.filter(this, entry -> Bytes.indexOf(entry.getKey(), key) == 0); + } + + /** + * An iterator is either positioned at a key/value pair, or + * not valid. This method returns true iff the iterator is valid. + * + * REQUIRES: iterator not closed + * + * @throws IllegalStateException if the iterator is closed. + * @return an iterator is either positioned at a key/value pair + */ + boolean valid(); + + /** + * The underlying storage for + * the returned slice is valid only until the next modification of + * the iterator. + * + * REQUIRES: valid() && !closed + * + * @throws IllegalStateException if the iterator is closed. + * @throws NoSuchElementException if the iterator is not valid. + * + * @return the key for the current entry + */ + byte[] getKey(); + + /** + * The underlying storage for + * the returned slice is valid only until the next modification of + * the iterator. + * + * REQUIRES: valid() && !closed + * + * @throws IllegalStateException if the iterator is closed. + * @throws NoSuchElementException if the iterator is not valid. + * + * @return the value for the current entry + */ + byte[] getValue(); + + /** + * @throws IllegalStateException if the iterator is closed. + */ + void checkState(); + + /** + * @throws NoSuchElementException if the iterator is not valid. + */ + default void checkValid() { + if (!valid()) { + throw new NoSuchElementException(); + } + } } diff --git a/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java b/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java index a8c4cff2066..1438b9247b5 100644 --- a/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java +++ b/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.util.Map.Entry; import java.util.NoSuchElementException; +import java.util.concurrent.atomic.AtomicBoolean; import lombok.extern.slf4j.Slf4j; import org.rocksdb.RocksIterator; @@ -13,7 +14,7 @@ public final class RockStoreIterator implements DBIterator { private final RocksIterator dbIterator; private boolean first = true; - private boolean valid = true; + private final AtomicBoolean close = new AtomicBoolean(false); public RockStoreIterator(RocksIterator dbIterator) { this.dbIterator = dbIterator; @@ -21,12 +22,14 @@ public RockStoreIterator(RocksIterator dbIterator) { @Override public void close() throws IOException { - dbIterator.close(); + if (close.compareAndSet(false, true)) { + dbIterator.close(); + } } @Override public boolean hasNext() { - if (!valid) { + if (close.get()) { return false; } boolean hasNext = false; @@ -37,13 +40,12 @@ public boolean hasNext() { first = false; } if (!(hasNext = dbIterator.isValid())) { // false is last item - dbIterator.close(); - valid = false; + close(); } } catch (Exception e) { logger.error(e.getMessage(), e); try { - dbIterator.close(); + close(); } catch (Exception e1) { logger.error(e.getMessage(), e); } @@ -53,7 +55,7 @@ public boolean hasNext() { @Override public Entry next() { - if (!valid) { + if (close.get()) { throw new NoSuchElementException(); } byte[] key = dbIterator.key(); @@ -76,4 +78,52 @@ public byte[] setValue(byte[] value) { } }; } -} \ No newline at end of file + + @Override + public void seek(byte[] key) { + checkState(); + dbIterator.seek(key); + this.first = false; + } + + @Override + public void seekToFirst() { + checkState(); + dbIterator.seekToFirst(); + this.first = false; + } + + @Override + public void seekToLast() { + checkState(); + dbIterator.seekToLast(); + this.first = false; + } + + @Override + public boolean valid() { + checkState(); + return dbIterator.isValid(); + } + + @Override + public byte[] getKey() { + checkState(); + checkValid(); + return dbIterator.key(); + } + + @Override + public byte[] getValue() { + checkState(); + checkValid(); + return dbIterator.value(); + } + + @Override + public void checkState() { + if (close.get()) { + throw new IllegalStateException("iterator has been closed"); + } + } +} diff --git a/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java b/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java index 292bb421e54..4c635660ea6 100755 --- a/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java +++ b/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.util.Map.Entry; import java.util.NoSuchElementException; +import java.util.concurrent.atomic.AtomicBoolean; import lombok.extern.slf4j.Slf4j; import org.iq80.leveldb.DBIterator; @@ -13,7 +14,7 @@ public final class StoreIterator implements org.tron.core.db.common.iterator.DBI private final DBIterator dbIterator; private boolean first = true; - private boolean valid = true; + private final AtomicBoolean close = new AtomicBoolean(false); public StoreIterator(DBIterator dbIterator) { this.dbIterator = dbIterator; @@ -21,12 +22,14 @@ public StoreIterator(DBIterator dbIterator) { @Override public void close() throws IOException { - dbIterator.close(); + if (close.compareAndSet(false, true)) { + dbIterator.close(); + } } @Override public boolean hasNext() { - if (!valid) { + if (close.get()) { return false; } @@ -39,8 +42,7 @@ public boolean hasNext() { } if (!(hasNext = dbIterator.hasNext())) { // false is last item - dbIterator.close(); - valid = false; + close(); } } catch (Exception e) { logger.error(e.getMessage(), e); @@ -51,7 +53,7 @@ public boolean hasNext() { @Override public Entry next() { - if (!valid) { + if (close.get()) { throw new NoSuchElementException(); } return dbIterator.next(); @@ -61,4 +63,53 @@ public Entry next() { public void remove() { throw new UnsupportedOperationException(); } + + @Override + public void seek(byte[] key) { + checkState(); + dbIterator.seek(key); + this.first = false; + } + + @Override + public void seekToFirst() { + checkState(); + dbIterator.seekToFirst(); + this.first = false; + } + + @Override + public void seekToLast() { + checkState(); + dbIterator.seekToLast(); + this.first = false; + } + + @Override + public boolean valid() { + checkState(); + return dbIterator.hasNext(); + } + + @Override + public byte[] getKey() { + checkState(); + checkValid(); + return dbIterator.peekNext().getKey(); + } + + @Override + public byte[] getValue() { + checkState(); + checkValid(); + return dbIterator.peekNext().getValue(); + } + + @Override + public void checkState() { + if (close.get()) { + throw new IllegalStateException("iterator has been closed"); + } + } } + diff --git a/chainbase/src/main/java/org/tron/core/service/MortgageService.java b/chainbase/src/main/java/org/tron/core/service/MortgageService.java index e9b00a38201..805245d53f2 100644 --- a/chainbase/src/main/java/org/tron/core/service/MortgageService.java +++ b/chainbase/src/main/java/org/tron/core/service/MortgageService.java @@ -4,12 +4,15 @@ import java.math.BigInteger; import java.util.Comparator; import java.util.List; +import java.util.stream.Collectors; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.bouncycastle.util.encoders.Hex; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tron.common.utils.Pair; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.WitnessCapsule; @@ -18,7 +21,6 @@ import org.tron.core.store.DelegationStore; import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.store.WitnessStore; -import org.tron.protos.Protocol.Vote; @Slf4j(topic = "mortgage") @Component @@ -37,6 +39,9 @@ public class MortgageService { @Setter private AccountStore accountStore; + @Autowired + private RewardViCalService rewardViCalService; + public void initStore(WitnessStore witnessStore, DelegationStore delegationStore, DynamicPropertiesStore dynamicPropertiesStore, AccountStore accountStore) { this.witnessStore = witnessStore; @@ -162,21 +167,21 @@ public long queryReward(byte[] address) { return reward + accountCapsule.getAllowance(); } - private long computeReward(long cycle, AccountCapsule accountCapsule) { + private long computeReward(long cycle, List> votes) { long reward = 0; - for (Vote vote : accountCapsule.getVotesList()) { - byte[] srAddress = vote.getVoteAddress().toByteArray(); + for (Pair vote : votes) { + byte[] srAddress = vote.getKey(); long totalReward = delegationStore.getReward(cycle, srAddress); + if (totalReward <= 0) { + continue; + } long totalVote = delegationStore.getWitnessVote(cycle, srAddress); if (totalVote == DelegationStore.REMARK || totalVote == 0) { continue; } - long userVote = vote.getVoteCount(); + long userVote = vote.getValue(); double voteRate = (double) userVote / totalVote; reward += voteRate * totalReward; - logger.debug("ComputeReward {}, {}, {}, {}, {}, {}, {}.", cycle, - Hex.toHexString(accountCapsule.getAddress().toByteArray()), Hex.toHexString(srAddress), - userVote, totalVote, totalReward, reward); } return reward; } @@ -197,23 +202,24 @@ private long computeReward(long beginCycle, long endCycle, AccountCapsule accoun long reward = 0; long newAlgorithmCycle = dynamicPropertiesStore.getNewRewardAlgorithmEffectiveCycle(); + List> srAddresses = accountCapsule.getVotesList().stream() + .map(vote -> new Pair<>(vote.getVoteAddress().toByteArray(), vote.getVoteCount())) + .collect(Collectors.toList()); if (beginCycle < newAlgorithmCycle) { long oldEndCycle = Math.min(endCycle, newAlgorithmCycle); - for (long cycle = beginCycle; cycle < oldEndCycle; cycle++) { - reward += computeReward(cycle, accountCapsule); - } + reward = getOldReward(beginCycle, oldEndCycle, srAddresses); beginCycle = oldEndCycle; } if (beginCycle < endCycle) { - for (Vote vote : accountCapsule.getVotesList()) { - byte[] srAddress = vote.getVoteAddress().toByteArray(); + for (Pair vote : srAddresses) { + byte[] srAddress = vote.getKey(); BigInteger beginVi = delegationStore.getWitnessVi(beginCycle - 1, srAddress); BigInteger endVi = delegationStore.getWitnessVi(endCycle - 1, srAddress); BigInteger deltaVi = endVi.subtract(beginVi); if (deltaVi.signum() <= 0) { continue; } - long userVote = vote.getVoteCount(); + long userVote = vote.getValue(); reward += deltaVi.multiply(BigInteger.valueOf(userVote)) .divide(DelegationStore.DECIMAL_OF_VI_REWARD).longValue(); } @@ -257,4 +263,15 @@ private void sortWitness(List list) { list.sort(Comparator.comparingLong((ByteString b) -> getWitnessByAddress(b).getVoteCount()) .reversed().thenComparing(Comparator.comparingInt(ByteString::hashCode).reversed())); } + + private long getOldReward(long begin, long end, List> votes) { + if (dynamicPropertiesStore.allowOldRewardOpt()) { + return rewardViCalService.getNewRewardAlgorithmReward(begin, end, votes); + } + long reward = 0; + for (long cycle = begin; cycle < end; cycle++) { + reward += computeReward(cycle, votes); + } + return reward; + } } diff --git a/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java b/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java new file mode 100644 index 00000000000..acb16142b3f --- /dev/null +++ b/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java @@ -0,0 +1,273 @@ +package org.tron.core.service; + +import static org.tron.core.store.DelegationStore.DECIMAL_OF_VI_REWARD; +import static org.tron.core.store.DelegationStore.REMARK; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Streams; +import com.google.common.primitives.Bytes; +import com.google.protobuf.ByteString; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.LongStream; +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.error.TronDBException; +import org.tron.common.es.ExecutorServiceManager; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Pair; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.utils.MerkleTree; +import org.tron.core.db.common.iterator.DBIterator; +import org.tron.core.db2.common.DB; +import org.tron.core.store.DelegationStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.store.RewardViStore; +import org.tron.core.store.WitnessStore; + +@Component +@Slf4j(topic = "rewardViCalService") +public class RewardViCalService { + + private final DB propertiesStore; + private final DB delegationStore; + private final DB witnessStore; + + @Autowired + private RewardViStore rewardViStore; + + private static final byte[] IS_DONE_KEY = new byte[]{0x00}; + private static final byte[] IS_DONE_VALUE = new byte[]{0x01}; + + private long newRewardCalStartCycle = Long.MAX_VALUE; + + private volatile long lastBlockNumber = -1; + + @VisibleForTesting + @Setter + private Sha256Hash rewardViRoot = Sha256Hash.wrap( + ByteString.fromHex("9debcb9924055500aaae98cdee10501c5c39d4daa75800a996f4bdda73dbccd8")); + + private final CountDownLatch lock = new CountDownLatch(1); + + private final ScheduledExecutorService es = ExecutorServiceManager + .newSingleThreadScheduledExecutor("rewardViCalService"); + + + @Autowired + public RewardViCalService(@Autowired DynamicPropertiesStore propertiesStore, + @Autowired DelegationStore delegationStore, @Autowired WitnessStore witnessStore) { + this.propertiesStore = propertiesStore.getDb(); + this.delegationStore = delegationStore.getDb(); + this.witnessStore = witnessStore.getDb(); + } + + @PostConstruct + private void init() { + es.scheduleWithFixedDelay(this::maybeRun, 0, 3, TimeUnit.SECONDS); + } + + private boolean enableNewRewardAlgorithm() { + this.newRewardCalStartCycle = this.getNewRewardAlgorithmEffectiveCycle(); + boolean ret = this.newRewardCalStartCycle != Long.MAX_VALUE; + if (ret && lastBlockNumber == -1) { + lastBlockNumber = this.getLatestBlockHeaderNumber(); + } + return ret; + } + + private boolean isDone() { + return rewardViStore.has(IS_DONE_KEY); + } + + private void maybeRun() { + if (enableNewRewardAlgorithm()) { + if (this.newRewardCalStartCycle > 1) { + if (isDone()) { + this.clearUp(true); + logger.info("rewardViCalService is already done"); + } else { + if (this.getLatestBlockHeaderNumber() > lastBlockNumber) { + // checkpoint is flushed to db, so we can start rewardViCalService + startRewardCal(); + clearUp(true); + } else { + logger.info("startRewardCal will run after checkpoint is flushed to db"); + } + } + } else { + clearUp(false); + logger.info("rewardViCalService is no need to run"); + } + } + } + + private void clearUp(boolean isDone) { + lock.countDown(); + if (isDone) { + calcMerkleRoot(); + } + es.shutdown(); + } + + @PreDestroy + private void destroy() { + es.shutdownNow(); + } + + + public long getNewRewardAlgorithmReward(long beginCycle, long endCycle, + List> votes) { + if (!rewardViStore.has(IS_DONE_KEY)) { + logger.warn("rewardViCalService is not done, wait for it"); + try { + lock.await(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new TronDBException(e); + } + } + + long reward = 0; + if (beginCycle < endCycle) { + for (Pair vote : votes) { + byte[] srAddress = vote.getKey(); + BigInteger beginVi = getWitnessVi(beginCycle - 1, srAddress); + BigInteger endVi = getWitnessVi(endCycle - 1, srAddress); + BigInteger deltaVi = endVi.subtract(beginVi); + if (deltaVi.signum() <= 0) { + continue; + } + long userVote = vote.getValue(); + reward += deltaVi.multiply(BigInteger.valueOf(userVote)) + .divide(DelegationStore.DECIMAL_OF_VI_REWARD).longValue(); + } + } + return reward; + + } + + private void calcMerkleRoot() { + logger.info("calcMerkleRoot start"); + DBIterator iterator = rewardViStore.iterator(); + iterator.seekToFirst(); + ArrayList ids = Streams.stream(iterator) + .map(this::getHash) + .collect(Collectors.toCollection(ArrayList::new)); + + Sha256Hash rewardViRootLocal = MerkleTree.getInstance().createTree(ids).getRoot().getHash(); + if (!Objects.equals(rewardViRoot, rewardViRootLocal)) { + logger.error("merkle root mismatch, expect: {}, actual: {}", + rewardViRoot, rewardViRootLocal); + } + logger.info("calcMerkleRoot: {}", rewardViRootLocal); + } + + private Sha256Hash getHash(Map.Entry entry) { + return Sha256Hash.of(CommonParameter.getInstance().isECKeyCryptoEngine(), + Bytes.concat(entry.getKey(), entry.getValue())); + } + + private void startRewardCal() { + logger.info("rewardViCalService start"); + rewardViStore.reset(); + DBIterator iterator = (DBIterator) witnessStore.iterator(); + iterator.seekToFirst(); + iterator.forEachRemaining(e -> accumulateWitnessReward(e.getKey())); + rewardViStore.put(IS_DONE_KEY, IS_DONE_VALUE); + logger.info("rewardViCalService is done"); + + } + + private void accumulateWitnessReward(byte[] witness) { + long startCycle = 1; + LongStream.range(startCycle, newRewardCalStartCycle) + .forEach(cycle -> accumulateWitnessVi(cycle, witness)); + } + + private void accumulateWitnessVi(long cycle, byte[] address) { + BigInteger preVi = getWitnessVi(cycle - 1, address); + long voteCount = getWitnessVote(cycle, address); + long reward = getReward(cycle, address); + if (reward == 0 || voteCount == 0) { // Just forward pre vi + if (!BigInteger.ZERO.equals(preVi)) { // Zero vi will not be record + setWitnessVi(cycle, address, preVi); + } + } else { // Accumulate delta vi + BigInteger deltaVi = BigInteger.valueOf(reward) + .multiply(DECIMAL_OF_VI_REWARD) + .divide(BigInteger.valueOf(voteCount)); + setWitnessVi(cycle, address, preVi.add(deltaVi)); + } + } + + private void setWitnessVi(long cycle, byte[] address, BigInteger value) { + byte[] k = buildViKey(cycle, address); + byte[] v = value.toByteArray(); + rewardViStore.put(k, v); + } + + private BigInteger getWitnessVi(long cycle, byte[] address) { + + byte[] v = rewardViStore.get(buildViKey(cycle, address)); + if (v == null) { + return BigInteger.ZERO; + } else { + return new BigInteger(v); + } + } + + private byte[] buildViKey(long cycle, byte[] address) { + return generateKey(cycle, address, "vi"); + } + + private long getReward(long cycle, byte[] address) { + byte[] value = this.delegationStore.get(generateKey(cycle, address, "reward")); + return value == null ? 0 : ByteArray.toLong(value); + } + + private long getWitnessVote(long cycle, byte[] address) { + byte[] value = this.delegationStore.get(generateKey(cycle, address, "vote")); + return value == null ? REMARK : ByteArray.toLong(value); + } + + private byte[] generateKey(long cycle, byte[] address, String suffix) { + return generateKey(cycle + "", address, suffix); + } + + private byte[] generateKey(String prefix, byte[] address, String suffix) { + StringBuilder sb = new StringBuilder(); + if (prefix != null) { + sb.append(prefix).append("-"); + } + sb.append(Hex.toHexString(address)); + if (suffix != null) { + sb.append("-").append(suffix); + } + return sb.toString().getBytes(); + } + + private long getNewRewardAlgorithmEffectiveCycle() { + byte[] value = this.propertiesStore.get("NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE".getBytes()); + return value == null ? Long.MAX_VALUE : ByteArray.toLong(value); + } + + private long getLatestBlockHeaderNumber() { + byte[] value = this.propertiesStore.get("latest_block_header_number".getBytes()); + return value == null ? 1 : ByteArray.toLong(value); + } +} + diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index f3059d31558..23693f9bab6 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -217,6 +217,8 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] MAX_DELEGATE_LOCK_PERIOD = "MAX_DELEGATE_LOCK_PERIOD".getBytes(); + private static final byte[] ALLOW_OLD_REWARD_OPT = "ALLOW_OLD_REWARD_OPT".getBytes(); + @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { super(dbName); @@ -2523,6 +2525,10 @@ public boolean useNewRewardAlgorithm() { return getNewRewardAlgorithmEffectiveCycle() != Long.MAX_VALUE; } + public boolean useNewRewardAlgorithmFromStart() { + return getNewRewardAlgorithmEffectiveCycle() == 1; + } + public void saveNewRewardAlgorithmEffectiveCycle() { if (getNewRewardAlgorithmEffectiveCycle() == Long.MAX_VALUE) { long currentCycle = getCurrentCycleNumber(); @@ -2833,6 +2839,32 @@ public boolean supportMaxDelegateLockPeriod() { getUnfreezeDelayDays() > 0; } + /** + * @require NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE != Long.MAX_VALUE + * @require NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE > 1 + */ + public void saveAllowOldRewardOpt(long allowOldRewardOpt) { + if (useNewRewardAlgorithm()) { + if (useNewRewardAlgorithmFromStart()) { + throw new IllegalStateException("no need old reward opt, ALLOW_NEW_REWARD from start"); + } + this.put(ALLOW_OLD_REWARD_OPT, new BytesCapsule(ByteArray.fromLong(allowOldRewardOpt))); + } else { + throw new IllegalStateException("not support old reward opt, ALLOW_NEW_REWARD not set"); + } + } + + public boolean allowOldRewardOpt() { + return getAllowOldRewardOpt() == 1L; + } + + public long getAllowOldRewardOpt() { + return Optional.ofNullable(getUnchecked(ALLOW_OLD_REWARD_OPT)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElse(CommonParameter.getInstance().getAllowOldRewardOpt()); + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/chainbase/src/main/java/org/tron/core/store/RewardViStore.java b/chainbase/src/main/java/org/tron/core/store/RewardViStore.java new file mode 100755 index 00000000000..f173cecc00f --- /dev/null +++ b/chainbase/src/main/java/org/tron/core/store/RewardViStore.java @@ -0,0 +1,43 @@ +package org.tron.core.store; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.tron.core.db.TronDatabase; +import org.tron.core.db.common.iterator.DBIterator; + +@Slf4j(topic = "DB") +@Component +public class RewardViStore extends TronDatabase { + + @Autowired + private RewardViStore(@Value("reward-vi") String dbName) { + super(dbName); + } + + @Override + public byte[] get(byte[] key) { + return dbSource.getData(key); + } + + @Override + public void put(byte[] key, byte[] item) { + dbSource.putData(key, item); + } + + @Override + public void delete(byte[] key) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean has(byte[] key) { + return dbSource.getData(key) != null; + } + + @Override + public DBIterator iterator() { + return ((DBIterator) dbSource.iterator()); + } +} diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index b75eb682932..95a1eb2d0ae 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -662,6 +662,10 @@ public class CommonParameter { @Setter public int maxUnsolidifiedBlocks; + @Getter + @Setter + public long allowOldRewardOpt; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/common/prometheus/MetricKeys.java b/common/src/main/java/org/tron/common/prometheus/MetricKeys.java index 87ab6fae0a3..7e85771000e 100644 --- a/common/src/main/java/org/tron/common/prometheus/MetricKeys.java +++ b/common/src/main/java/org/tron/common/prometheus/MetricKeys.java @@ -62,6 +62,8 @@ public static class Histogram { public static final String MESSAGE_PROCESS_LATENCY = "tron:message_process_latency_seconds"; public static final String BLOCK_FETCH_LATENCY = "tron:block_fetch_latency_seconds"; public static final String BLOCK_RECEIVE_DELAY = "tron:block_receive_delay_seconds"; + public static final String DO_REWARD_CAL_DELAY = "tron:do_reward_cal_seconds"; + private Histogram() { throw new IllegalStateException("Histogram"); diff --git a/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java b/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java index 556db10feb5..d776474c92e 100644 --- a/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java +++ b/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java @@ -48,6 +48,8 @@ public class MetricsHistogram { init(MetricKeys.Histogram.BLOCK_FETCH_LATENCY, "fetch block latency."); init(MetricKeys.Histogram.BLOCK_RECEIVE_DELAY, "receive block delay time, receiveTime - blockTime."); + init(MetricKeys.Histogram.DO_REWARD_CAL_DELAY, + "do reward cal delay time.", "depth"); } private MetricsHistogram() { diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 634d08b79a9..2cd9ea95f15 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -375,4 +375,5 @@ public class Constant { public static final String UNSOLIDIFIED_BLOCK_CHECK = "node.unsolidifiedBlockCheck"; public static final String MAX_UNSOLIDIFIED_BLOCKS = "node.maxUnsolidifiedBlocks"; + public static final String COMMITTEE_ALLOW_OLD_REWARD_OPT = "committee.allowOldRewardOpt"; } diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index b1a948e9fdf..247826af77a 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -22,7 +22,8 @@ public enum ForkBlockVersionEnum { VERSION_4_6(25, 1596780000000L, 80), VERSION_4_7(26, 1596780000000L, 80), VERSION_4_7_1(27, 1596780000000L, 80), - VERSION_4_7_2(28, 1596780000000L, 80); + VERSION_4_7_2(28, 1596780000000L, 80), + VERSION_4_7_4(29, 1596780000000L, 80); // if add a version, modify BLOCK_VERSION simultaneously @Getter @@ -71,7 +72,7 @@ public class ChainConstant { public static final int SINGLE_REPEAT = 1; public static final int BLOCK_FILLED_SLOTS_NUMBER = 128; public static final int MAX_FROZEN_NUMBER = 1; - public static final int BLOCK_VERSION = 28; + public static final int BLOCK_VERSION = 29; public static final long FROZEN_PERIOD = 86_400_000L; public static final long DELEGATE_PERIOD = 3 * 86_400_000L; public static final long TRX_PRECISION = 1000_000L; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index b14fcdb1167..cd2e26aa6f7 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1329,6 +1329,10 @@ public Protocol.ChainParameters getChainParameters() { .setKey("getMaxDelegateLockPeriod") .setValue(dbManager.getDynamicPropertiesStore().getMaxDelegateLockPeriod()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getAllowOldRewardOpt") + .setValue(dbManager.getDynamicPropertiesStore().getAllowOldRewardOpt()) + .build()); return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 4321ad464bc..9694668af01 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -231,6 +231,7 @@ public static void clearParam() { PARAMETER.allowTvmShangHai = 0; PARAMETER.unsolidifiedBlockCheck = true; PARAMETER.maxUnsolidifiedBlocks = 1000; + PARAMETER.allowOldRewardOpt = 0; } /** @@ -1191,6 +1192,10 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.MAX_UNSOLIDIFIED_BLOCKS) ? config .getInt(Constant.MAX_UNSOLIDIFIED_BLOCKS) : 1000; + PARAMETER.allowOldRewardOpt = + config.hasPath(Constant.COMMITTEE_ALLOW_OLD_REWARD_OPT) ? config + .getInt(Constant.COMMITTEE_ALLOW_OLD_REWARD_OPT) : 0; + logConfig(); } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 2cbf0c053d6..58da117cfc6 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -355,6 +355,10 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(entry.getValue()); break; } + case ALLOW_OLD_REWARD_OPT: { + manager.getDynamicPropertiesStore().saveAllowOldRewardOpt(entry.getValue()); + break; + } default: find = false; break; diff --git a/framework/src/main/java/org/tron/core/db/common/iterator/AbstractIterator.java b/framework/src/main/java/org/tron/core/db/common/iterator/AbstractIterator.java deleted file mode 100644 index ca3801619a8..00000000000 --- a/framework/src/main/java/org/tron/core/db/common/iterator/AbstractIterator.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.tron.core.db.common.iterator; - -import com.google.common.collect.Maps; -import com.google.common.reflect.TypeToken; -import java.lang.reflect.InvocationTargetException; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; - -public abstract class AbstractIterator implements Iterator> { - - protected Iterator> iterator; - private TypeToken typeToken = new TypeToken(getClass()) { - }; - - public AbstractIterator(Iterator> iterator) { - this.iterator = iterator; - } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - protected T of(byte[] value) { - try { - @SuppressWarnings("unchecked") - T t = (T) typeToken.getRawType().getConstructor(byte[].class).newInstance(value); - return t; - } catch (InstantiationException | NoSuchMethodException - | InvocationTargetException | IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - @Override - public Map.Entry next() { - Entry entry = iterator.next(); - return Maps.immutableEntry(entry.getKey(), of(entry.getValue())); - } -} diff --git a/framework/src/main/java/org/tron/core/db/common/iterator/AssetIssueIterator.java b/framework/src/main/java/org/tron/core/db/common/iterator/AssetIssueIterator.java deleted file mode 100644 index e52e5a93b46..00000000000 --- a/framework/src/main/java/org/tron/core/db/common/iterator/AssetIssueIterator.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.tron.core.db.common.iterator; - -import java.util.Iterator; -import java.util.Map.Entry; -import org.tron.core.capsule.AssetIssueCapsule; - -public class AssetIssueIterator extends AbstractIterator { - - public AssetIssueIterator(Iterator> iterator) { - super(iterator); - } - - @Override - protected AssetIssueCapsule of(byte[] value) { - return new AssetIssueCapsule(value); - } -} \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/db/common/iterator/DBIterator.java b/framework/src/main/java/org/tron/core/db/common/iterator/DBIterator.java deleted file mode 100755 index f706623693f..00000000000 --- a/framework/src/main/java/org/tron/core/db/common/iterator/DBIterator.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.tron.core.db.common.iterator; - -import java.io.Closeable; -import java.util.Iterator; -import java.util.Map.Entry; - -public interface DBIterator extends Iterator>, Closeable { - -} diff --git a/framework/src/main/java/org/tron/core/db/common/iterator/TransactionIterator.java b/framework/src/main/java/org/tron/core/db/common/iterator/TransactionIterator.java deleted file mode 100644 index eb61f38b4b3..00000000000 --- a/framework/src/main/java/org/tron/core/db/common/iterator/TransactionIterator.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.tron.core.db.common.iterator; - -import java.util.Iterator; -import java.util.Map.Entry; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.exception.BadItemException; - -public class TransactionIterator extends AbstractIterator { - - public TransactionIterator(Iterator> iterator) { - super(iterator); - } - - @Override - protected TransactionCapsule of(byte[] value) { - try { - return new TransactionCapsule(value); - } catch (BadItemException e) { - throw new RuntimeException(e); - } - } -} diff --git a/framework/src/main/java/org/tron/core/db/common/iterator/WitnessIterator.java b/framework/src/main/java/org/tron/core/db/common/iterator/WitnessIterator.java deleted file mode 100644 index 06837345141..00000000000 --- a/framework/src/main/java/org/tron/core/db/common/iterator/WitnessIterator.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.tron.core.db.common.iterator; - -import java.util.Iterator; -import java.util.Map.Entry; -import org.tron.core.capsule.WitnessCapsule; - -public class WitnessIterator extends AbstractIterator { - - public WitnessIterator(Iterator> iterator) { - super(iterator); - } - - @Override - protected WitnessCapsule of(byte[] value) { - return new WitnessCapsule(value); - } -} diff --git a/framework/src/test/java/org/tron/core/db/DBIteratorTest.java b/framework/src/test/java/org/tron/core/db/DBIteratorTest.java index a55d1b04d4d..b4f7ca424c0 100644 --- a/framework/src/test/java/org/tron/core/db/DBIteratorTest.java +++ b/framework/src/test/java/org/tron/core/db/DBIteratorTest.java @@ -5,86 +5,122 @@ import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.nio.file.Paths; import java.util.NoSuchElementException; import org.iq80.leveldb.DB; import org.iq80.leveldb.Options; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; import org.rocksdb.RocksDB; import org.rocksdb.RocksDBException; -import org.tron.common.utils.FileUtil; import org.tron.core.db.common.iterator.RockStoreIterator; import org.tron.core.db.common.iterator.StoreIterator; public class DBIteratorTest { - @BeforeClass - public static void init() { - File file = Paths.get("database-iterator").toFile(); - if (!file.exists()) { - file.mkdirs(); - } - } + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); - @AfterClass - public static void clear() { - File file = Paths.get("database-iterator").toFile(); - if (file.exists()) { - FileUtil.deleteDir(Paths.get("database-iterator").toFile()); - } - } + @Rule + public final ExpectedException thrown = ExpectedException.none(); @Test public void testLevelDb() throws IOException { - File file = new File("database-iterator/testLevelDb"); - try { - DB db = factory.open(file, new Options().createIfMissing(true)); + File file = temporaryFolder.newFolder(); + try (DB db = factory.open(file, new Options().createIfMissing(true))) { db.put("1".getBytes(StandardCharsets.UTF_8), "1".getBytes(StandardCharsets.UTF_8)); db.put("2".getBytes(StandardCharsets.UTF_8), "2".getBytes(StandardCharsets.UTF_8)); - StoreIterator iterator = new StoreIterator(db.iterator()); + StoreIterator iterator = new StoreIterator(db.iterator()); + iterator.seekToFirst(); + Assert.assertArrayEquals("1".getBytes(StandardCharsets.UTF_8), iterator.getKey()); + Assert.assertArrayEquals("1".getBytes(StandardCharsets.UTF_8), iterator.next().getValue()); + Assert.assertTrue(iterator.hasNext()); + + Assert.assertArrayEquals("2".getBytes(StandardCharsets.UTF_8), iterator.getValue()); + Assert.assertArrayEquals("2".getBytes(StandardCharsets.UTF_8), iterator.next().getKey()); + Assert.assertFalse(iterator.hasNext()); + + try { + iterator.seekToLast(); + } catch (Exception e) { + Assert.assertTrue(e instanceof IllegalStateException); + } + + iterator = new StoreIterator(db.iterator()); + iterator.seekToLast(); + Assert.assertArrayEquals("2".getBytes(StandardCharsets.UTF_8), iterator.getKey()); + Assert.assertArrayEquals("2".getBytes(StandardCharsets.UTF_8), iterator.getValue()); + iterator.seekToFirst(); while (iterator.hasNext()) { iterator.next(); } Assert.assertFalse(iterator.hasNext()); try { - iterator.next(); + iterator.getKey(); } catch (Exception e) { - Assert.assertTrue(e instanceof NoSuchElementException); + Assert.assertTrue(e instanceof IllegalStateException); } - db.close(); - } finally { - factory.destroy(file, new Options()); + try { + iterator.getValue(); + } catch (Exception e) { + Assert.assertTrue(e instanceof IllegalStateException); + } + thrown.expect(NoSuchElementException.class); + iterator.next(); } } @Test - public void testRocksDb() throws RocksDBException { - File file = new File("database-iterator/testRocksDb"); - try (org.rocksdb.Options options = new org.rocksdb.Options().setCreateIfMissing(true)) { - RocksDB db = RocksDB.open(options, file.toString()); + public void testRocksDb() throws RocksDBException, IOException { + File file = temporaryFolder.newFolder(); + try (org.rocksdb.Options options = new org.rocksdb.Options().setCreateIfMissing(true); + RocksDB db = RocksDB.open(options, file.toString())) { db.put("1".getBytes(StandardCharsets.UTF_8), "1".getBytes(StandardCharsets.UTF_8)); db.put("2".getBytes(StandardCharsets.UTF_8), "2".getBytes(StandardCharsets.UTF_8)); RockStoreIterator iterator = new RockStoreIterator(db.newIterator()); + iterator.seekToFirst(); + Assert.assertArrayEquals("1".getBytes(StandardCharsets.UTF_8), iterator.getKey()); + Assert.assertArrayEquals("1".getBytes(StandardCharsets.UTF_8), iterator.next().getValue()); + Assert.assertTrue(iterator.hasNext()); + + Assert.assertArrayEquals("2".getBytes(StandardCharsets.UTF_8), iterator.getValue()); + Assert.assertArrayEquals("2".getBytes(StandardCharsets.UTF_8), iterator.next().getKey()); + Assert.assertFalse(iterator.hasNext()); + + try { + iterator.seekToLast(); + } catch (Exception e) { + Assert.assertTrue(e instanceof IllegalStateException); + } + + iterator = new RockStoreIterator(db.newIterator()); + iterator.seekToLast(); + Assert.assertArrayEquals("2".getBytes(StandardCharsets.UTF_8), iterator.getKey()); + Assert.assertArrayEquals("2".getBytes(StandardCharsets.UTF_8), iterator.getValue()); + iterator.seekToFirst(); while (iterator.hasNext()) { iterator.next(); } Assert.assertFalse(iterator.hasNext()); try { - iterator.next(); + iterator.getKey(); + } catch (Exception e) { + Assert.assertTrue(e instanceof IllegalStateException); + } + try { + iterator.getValue(); } catch (Exception e) { - Assert.assertTrue(e instanceof NoSuchElementException); + Assert.assertTrue(e instanceof IllegalStateException); } - db.close(); - } finally { - RocksDB.destroyDB(file.toString(), new org.rocksdb.Options()); + thrown.expect(NoSuchElementException.class); + iterator.next(); } - } } diff --git a/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java b/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java new file mode 100644 index 00000000000..17b2526d6d0 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java @@ -0,0 +1,277 @@ +package org.tron.core.services; + +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.protobuf.ByteString; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.error.TronDBException; +import org.tron.common.es.ExecutorServiceManager; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.Constant; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.WitnessCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.service.MortgageService; +import org.tron.core.service.RewardViCalService; +import org.tron.core.store.AccountStore; +import org.tron.core.store.DelegationStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.store.WitnessStore; +import org.tron.protos.Protocol; + +public class ComputeRewardTest { + + private static final byte[] OWNER_ADDRESS = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1bf0"); + + private static final byte[] OWNER_ADDRESS_2 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1bf1"); + + private static final byte[] OWNER_ADDRESS_3 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1bf2"); + + private static final byte[] SR_ADDRESS_1 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c00"); + private static final byte[] SR_ADDRESS_2 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c01"); + private static final byte[] SR_ADDRESS_3 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c02"); + private static final byte[] SR_ADDRESS_4 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c03"); + private static final byte[] SR_ADDRESS_5 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c04"); + private static final byte[] SR_ADDRESS_6 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c05"); + private static final byte[] SR_ADDRESS_7 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c06"); + private static final byte[] SR_ADDRESS_8 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c07"); + private static final byte[] SR_ADDRESS_9 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c08"); + private static final byte[] SR_ADDRESS_10 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c09"); + private static final byte[] SR_ADDRESS_11 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c10"); + private static final byte[] SR_ADDRESS_12 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c11"); + private static final byte[] SR_ADDRESS_13 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c12"); + private static final byte[] SR_ADDRESS_14 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c13"); + private static final byte[] SR_ADDRESS_15 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c14"); + private static final byte[] SR_ADDRESS_16 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c15"); + private static final byte[] SR_ADDRESS_17 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c16"); + private static final byte[] SR_ADDRESS_18 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c17"); + private static final byte[] SR_ADDRESS_19 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c18"); + private static final byte[] SR_ADDRESS_20 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c19"); + private static final byte[] SR_ADDRESS_21 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c20"); + private static final byte[] SR_ADDRESS_22 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c21"); + private static final byte[] SR_ADDRESS_23 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c22"); + private static final byte[] SR_ADDRESS_24 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c23"); + private static final byte[] SR_ADDRESS_25 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c24"); + private static final byte[] SR_ADDRESS_26 = ByteArray.fromHexString( + "4105b9e8af8ee371cad87317f442d155b39fbd1c25"); + + private static TronApplicationContext context; + private static DynamicPropertiesStore propertiesStore; + private static DelegationStore delegationStore; + private static AccountStore accountStore; + private static RewardViCalService rewardViCalService; + private static WitnessStore witnessStore; + private static MortgageService mortgageService; + @Rule + public final TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @After + public void destroy() { + context.destroy(); + Args.clearParam(); + } + + /** + * Init data. + */ + @Before + public void init() throws IOException { + Args.setParam(new String[]{"--output-directory", temporaryFolder.newFolder().toString(), + "--p2p-disable", "true"}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + propertiesStore = context.getBean(DynamicPropertiesStore.class); + delegationStore = context.getBean(DelegationStore.class); + accountStore = context.getBean(AccountStore.class); + rewardViCalService = context.getBean(RewardViCalService.class); + witnessStore = context.getBean(WitnessStore.class); + mortgageService = context.getBean(MortgageService.class); + setUp(); + } + + private void setUp() { + // mock flush service + Map flushServices = new HashMap<>(); + flushServices.put("propertiesStore", MoreExecutors.listeningDecorator( + ExecutorServiceManager.newSingleThreadExecutor( + "flush-service-propertiesStore"))); + flushServices.put("delegationStore", MoreExecutors.listeningDecorator( + ExecutorServiceManager.newSingleThreadExecutor( + "flush-service-delegationStore"))); + flushServices.put("accountStore", MoreExecutors.listeningDecorator( + ExecutorServiceManager.newSingleThreadExecutor("flush-service-accountStore"))); + flushServices.put("witnessStore", MoreExecutors.listeningDecorator( + ExecutorServiceManager.newSingleThreadExecutor("flush-service-witnessStore"))); + + List> futures = new ArrayList<>(flushServices.size()); + + try { + flushServices.get("propertiesStore").submit(() -> { + propertiesStore.saveChangeDelegation(1); + propertiesStore.saveCurrentCycleNumber(4); + propertiesStore.saveNewRewardAlgorithmEffectiveCycle(); + propertiesStore.saveLatestBlockHeaderNumber(1); + }).get(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new TronDBException(e); + } catch (ExecutionException e) { + throw new TronDBException(e); + } + + try { + Thread.sleep(1000 * 6); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new TronDBException(e); + } + + List votes = new ArrayList<>(32); + votes.add(new Vote(46188095536L, 5, 1496122605L, SR_ADDRESS_1)); + votes.add(new Vote(48618386224L, 5, 1582867684L, SR_ADDRESS_2)); + votes.add(new Vote(13155856728L, 5, 586969566L, SR_ADDRESS_3)); + votes.add(new Vote(41883707392L, 5, 1342484905L, SR_ADDRESS_4)); + votes.add(new Vote(62017323832L, 5, 2061119522L, SR_ADDRESS_5)); + votes.add(new Vote(19227712L, 3, 722417L, SR_ADDRESS_6)); + votes.add(new Vote(46634987592L, 3, 1599681706L, SR_ADDRESS_7)); + votes.add(new Vote(49112700L, 3, 1753127L, SR_ADDRESS_8)); + votes.add(new Vote(40835355868L, 6, 1467015537L, SR_ADDRESS_9)); + votes.add(new Vote(10045616L, 5, 362326L, SR_ADDRESS_10)); + votes.add(new Vote(34534983616L, 5, 1217718846L, SR_ADDRESS_11)); + votes.add(new Vote(32387926028L, 5, 1292557190L, SR_ADDRESS_12)); + votes.add(new Vote(36516086396L, 5, 1295716573L, SR_ADDRESS_13)); + votes.add(new Vote(48411501224L, 5, 1575483226L, SR_ADDRESS_14)); + votes.add(new Vote(154785960L, 5, 6905922L, SR_ADDRESS_15)); + votes.add(new Vote(59057915168L, 6, 1956059729L, SR_ADDRESS_16)); + votes.add(new Vote(62921824L, 3, 2245904L, SR_ADDRESS_17)); + votes.add(new Vote(1180144L, 3, 42148L, SR_ADDRESS_18)); + votes.add(new Vote(104313216L, 5, 4654248L, SR_ADDRESS_19)); + votes.add(new Vote(20429168760L, 1, 759569195L, SR_ADDRESS_20)); + votes.add(new Vote(4706184L, 3, 168069L, SR_ADDRESS_21)); + votes.add(new Vote(55804071064L, 5, 1839919389L, SR_ADDRESS_22)); + votes.add(new Vote(6074042856L, 6, 216802459L, SR_ADDRESS_23)); + votes.add(new Vote(40729360L, 5, 1817205L, SR_ADDRESS_24)); + votes.add(new Vote(31250017036L, 5, 1242358644L, SR_ADDRESS_25)); + votes.add(new Vote(15003660L, 5, 669546L, SR_ADDRESS_26)); + + futures.add(flushServices.get("delegationStore").submit(() -> { + delegationStore.setBeginCycle(OWNER_ADDRESS, 2); + delegationStore.setEndCycle(OWNER_ADDRESS, 3); + delegationStore.setBeginCycle(OWNER_ADDRESS_2, 1); + delegationStore.setEndCycle(OWNER_ADDRESS_2, 2); + delegationStore.setBeginCycle(OWNER_ADDRESS_3, 5); + for (Vote vote : votes) { + delegationStore.addReward(3, vote.srAddress, vote.totalReward); + delegationStore.setWitnessVote(3, vote.srAddress, vote.totalVotes); + } + })); + + futures.add(flushServices.get("witnessStore").submit(() -> { + for (Vote vote : votes) { + witnessStore.put(vote.srAddress, new WitnessCapsule(Protocol.Witness.newBuilder() + .setAddress(ByteString.copyFrom(vote.srAddress)) + .setVoteCount(vote.totalVotes) + .build())); + } + })); + + futures.add(flushServices.get("accountStore").submit(() -> { + Protocol.Account.Builder accountBuilder = Protocol.Account.newBuilder(); + accountBuilder.setAddress(ByteString.copyFrom(OWNER_ADDRESS)); + for (Vote vote : votes) { + accountBuilder.addVotes(Protocol.Vote.newBuilder() + .setVoteAddress(ByteString.copyFrom(vote.srAddress)) + .setVoteCount(vote.userVotes)); + + } + accountStore.put(OWNER_ADDRESS, new AccountCapsule(accountBuilder.build())); + })); + Future future = Futures.allAsList(futures); + try { + future.get(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new TronDBException(e); + } catch (ExecutionException e) { + throw new TronDBException(e); + } + try { + flushServices.get("propertiesStore").submit(() -> { + propertiesStore.saveAllowOldRewardOpt(1); + propertiesStore.saveLatestBlockHeaderNumber(3); + propertiesStore.saveCurrentCycleNumber(5); + }).get(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new TronDBException(e); + } catch (ExecutionException e) { + throw new TronDBException(e); + } + + rewardViCalService.setRewardViRoot(Sha256Hash.wrap( + ByteString.fromHex("e0ebe2f3243391ed674dff816a07f589a3279420d6d88bc823b6a9d5778337ce"))); + } + + @Test + public void query() { + Assert.assertEquals(3189, mortgageService.queryReward(OWNER_ADDRESS)); + } + + static class Vote { + long totalVotes; + long userVotes; + long totalReward; + byte[] srAddress; + + public Vote(long totalReward, long userVotes, long totalVotes, byte[] srAddress) { + this.totalVotes = totalVotes; + this.userVotes = userVotes; + this.totalReward = totalReward; + this.srAddress = srAddress; + } + } +} diff --git a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java index 0ba32b27f2e..e248af647c3 100644 --- a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java @@ -1,5 +1,6 @@ package org.tron.core.services; +import static org.tron.core.utils.ProposalUtil.ProposalType.ALLOW_OLD_REWARD_OPT; import static org.tron.core.utils.ProposalUtil.ProposalType.ENERGY_FEE; import static org.tron.core.utils.ProposalUtil.ProposalType.TRANSACTION_FEE; import static org.tron.core.utils.ProposalUtil.ProposalType.WITNESS_127_PAY_PER_BLOCK; @@ -10,7 +11,9 @@ import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.tron.common.BaseTest; import org.tron.core.Constant; import org.tron.core.capsule.ProposalCapsule; @@ -22,6 +25,9 @@ @Slf4j public class ProposalServiceTest extends BaseTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private static boolean init; @BeforeClass @@ -63,6 +69,9 @@ public void test() { proposal = Proposal.newBuilder().putParameters(proposalType.getCode(), 1).build(); } proposalCapsule = new ProposalCapsule(proposal); + if (proposalType == ALLOW_OLD_REWARD_OPT) { + thrown.expect(IllegalStateException.class); + } result = ProposalService.process(dbManager, proposalCapsule); Assert.assertTrue(result); } From 62d780d314dca7b92b784ee7323faf2953634693 Mon Sep 17 00:00:00 2001 From: liukai Date: Fri, 5 Jan 2024 18:03:37 +0800 Subject: [PATCH 0940/1197] test(case): add test case --- .../tron/core/db/AccountTraceStoreTest.java | 13 +++++ .../java/org/tron/core/db/BlockStoreTest.java | 50 +++++++++++++++++++ .../tron/core/db/MarketOrderStoreTest.java | 17 +++++++ .../tron/core/db/TransactionHistoryTest.java | 7 +++ 4 files changed, 87 insertions(+) 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/BlockStoreTest.java b/framework/src/test/java/org/tron/core/db/BlockStoreTest.java index 4f706a97dcf..23ff8ab75b7 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,71 @@ package org.tron.core.db; +import com.google.protobuf.ByteString; import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; import org.junit.Test; import org.tron.common.BaseTest; +import org.tron.common.utils.JsonUtilTest; +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; + +import javax.annotation.Resource; @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(); + } + } + } 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/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 From ae1865ec3ed3678ba2c04e19c9aa8e0b17490786 Mon Sep 17 00:00:00 2001 From: liukai Date: Fri, 5 Jan 2024 19:52:47 +0800 Subject: [PATCH 0941/1197] test(case): fix import order --- framework/src/test/java/org/tron/core/db/BlockStoreTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 23ff8ab75b7..d1ec0ae4f88 100644 --- a/framework/src/test/java/org/tron/core/db/BlockStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/BlockStoreTest.java @@ -1,11 +1,11 @@ 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.JsonUtilTest; import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; @@ -13,7 +13,6 @@ import org.tron.core.exception.BadItemException; import org.tron.core.exception.ItemNotFoundException; -import javax.annotation.Resource; @Slf4j public class BlockStoreTest extends BaseTest { From f04616ac048af1b90ce3f22c5d1eae7334b09039 Mon Sep 17 00:00:00 2001 From: liukai Date: Sat, 6 Jan 2024 23:46:37 +0800 Subject: [PATCH 0942/1197] test(case): add case --- .../java/org/tron/core/db/BlockStoreTest.java | 20 ++++++++++++++ .../core/db/DelegatedResourceStoreTest.java | 15 +++++++++++ .../org/tron/core/db/DelegationStoreTest.java | 17 ++++++++++++ .../org/tron/core/db/ExchangeStoreTest.java | 25 ++++++++++++++++++ .../org/tron/core/db/ExchangeV2StoreTest.java | 26 +++++++++++++++++++ .../tron/core/db/MarketAccountStoreTest.java | 15 +++++++++++ 6 files changed, 118 insertions(+) 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 d1ec0ae4f88..937a102193f 100644 --- a/framework/src/test/java/org/tron/core/db/BlockStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/BlockStoreTest.java @@ -67,4 +67,24 @@ public void testGet() { } } + @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..87bd70b875a 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,10 @@ 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 +39,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())); + } + } From 8107586127ba19e6b05f51be1b93476cc0d8c522 Mon Sep 17 00:00:00 2001 From: liukai Date: Sun, 7 Jan 2024 15:04:14 +0800 Subject: [PATCH 0943/1197] test(case): add ZKProofStoreTest case --- .../tron/core/db/MarketAccountStoreTest.java | 3 +- .../org/tron/core/db/ZKProofStoreTest.java | 58 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 framework/src/test/java/org/tron/core/db/ZKProofStoreTest.java 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 87bd70b875a..ed94a64175d 100644 --- a/framework/src/test/java/org/tron/core/db/MarketAccountStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/MarketAccountStoreTest.java @@ -29,7 +29,8 @@ public class MarketAccountStoreTest extends BaseTest { public void testGet() throws Exception { String address = "Address1"; - MarketAccountOrderCapsule marketAccountOrderCapsule = marketAccountStore.getUnchecked(address.getBytes()); + MarketAccountOrderCapsule marketAccountOrderCapsule = + marketAccountStore.getUnchecked(address.getBytes()); Assert.assertNull(marketAccountOrderCapsule); marketAccountStore.put(address.getBytes(), 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); + } +} From 8721f800a224d34b55e882d7eeb4c744ff91aa60 Mon Sep 17 00:00:00 2001 From: liukai Date: Mon, 8 Jan 2024 17:45:36 +0800 Subject: [PATCH 0944/1197] test(case): add servlet case --- .../http/GetAccountByIdServletTest.java | 47 +++++++++++++++ .../http/GetBlockByIdServletTest.java | 49 ++++++++++++++++ .../http/GetBlockByNumServletTest.java | 58 +++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/services/http/GetAccountByIdServletTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/GetBlockByIdServletTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/GetBlockByNumServletTest.java 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..f283035ca1d --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/GetBlockByIdServletTest.java @@ -0,0 +1,49 @@ +package org.tron.core.services.http; + +import static java.nio.charset.StandardCharsets.UTF_8; +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 GetBlockByIdServletTest extends BaseTest { + + @Resource + private GetBlockByIdServlet getBlockByIdServlet; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + 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 testGetBlockById() { + String jsonParam = "{\"value\": " + + "\"0000000002951a2f65db6725c2d0583f1ab9bdb1520eeedece99d9c98f3\"}"; + MockHttpServletRequest request = createRequest("application/json"); + request.setContent(jsonParam.getBytes(UTF_8)); + MockHttpServletResponse response = new MockHttpServletResponse(); + getBlockByIdServlet.doPost(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..d3ffa735d8d --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/GetBlockByNumServletTest.java @@ -0,0 +1,58 @@ +package org.tron.core.services.http; + +import static org.apache.commons.lang3.StringUtils.isNotEmpty; +import static org.junit.Assert.assertTrue; + +import com.alibaba.fastjson.JSONObject; + +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; +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 + ); + } + + 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 testGetBlockByNum() { + 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(); + } + } + +} From 05e3f5553bbed6404351be3365c41e18e941b5f0 Mon Sep 17 00:00:00 2001 From: liukai Date: Tue, 9 Jan 2024 16:59:42 +0800 Subject: [PATCH 0945/1197] test(case): add some cases 1. add ClearABIServletTest 2. add CreateAccountServletTest 3. CreateAssetIssueServletTest --- .../services/http/ClearABIServletTest.java | 45 ++++++++++++++ .../http/CreateAccountServletTest.java | 46 ++++++++++++++ .../http/CreateAssetIssueServletTest.java | 61 +++++++++++++++++++ .../http/GetBlockByIdServletTest.java | 26 ++++---- .../http/GetBlockByNumServletTest.java | 29 ++++++--- 5 files changed, 186 insertions(+), 21 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/services/http/ClearABIServletTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/CreateAccountServletTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/CreateAssetIssueServletTest.java 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..27bc2a6eb34 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/ClearABIServletTest.java @@ -0,0 +1,45 @@ +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.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 ClearABIServletTest extends BaseTest { + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + @Resource + private ClearABIServlet clearABIServlet; + + @Test + public void testClear() { + String jsonParam = "{\n" + + " \"owner_address\": \"41a7d8a35b260395c14aa456297662092ba3b76fc0\",\n" + + " \"contract_address\": \"417bcb781f4743afaacf9f9528f3ea903b3782339f\"\n" + + "}"; + 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()); + } + +} 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..70a319e6040 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/CreateAccountServletTest.java @@ -0,0 +1,46 @@ +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.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 CreateAccountServletTest extends BaseTest { + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + @Resource + private CreateAccountServlet createAccountServlet; + + @Test + public void testCreate() { + String jsonParam = "{" + + "\"owner_address\": \"41d1e7a6bc354106cb410e65ff8b181c600ff14292\"," + + "\"account_address\": \"41e552f6487585c2b58bc2c9bb4492bc1f17132cd0\"" + + "}"; + 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()); + } +} 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..d9f9ccc412c --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/CreateAssetIssueServletTest.java @@ -0,0 +1,61 @@ +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.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 CreateAssetIssueServletTest extends BaseTest { + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + + @Resource + private CreateAssetIssueServlet createAssetIssueServlet; + + @Test + public void testCreate() { + String jsonParam = "{" + + " \"owner_address\": \"41e552f6487585c2b58bc2c9bb4492bc1f17132cd0\"," + + " \"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()); + + } + +} 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 index f283035ca1d..8b213e12640 100644 --- a/framework/src/test/java/org/tron/core/services/http/GetBlockByIdServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/GetBlockByIdServletTest.java @@ -1,10 +1,12 @@ package org.tron.core.services.http; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.apache.commons.lang3.StringUtils.isNotEmpty; +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; @@ -26,24 +28,24 @@ public class GetBlockByIdServletTest extends BaseTest { ); } - 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 testGetBlockById() { String jsonParam = "{\"value\": " + "\"0000000002951a2f65db6725c2d0583f1ab9bdb1520eeedece99d9c98f3\"}"; - MockHttpServletRequest request = createRequest("application/json"); + 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 index d3ffa735d8d..5ff84c54dbe 100644 --- a/framework/src/test/java/org/tron/core/services/http/GetBlockByNumServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/GetBlockByNumServletTest.java @@ -1,12 +1,14 @@ package org.tron.core.services.http; -import static org.apache.commons.lang3.StringUtils.isNotEmpty; 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; @@ -27,18 +29,27 @@ public class GetBlockByNumServletTest extends BaseTest { ); } - public MockHttpServletRequest createRequest(String contentType) { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setMethod("POST"); - if (isNotEmpty(contentType)) { - request.setContentType(contentType); + @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(); } - request.setCharacterEncoding("UTF-8"); - return request; } @Test - public void testGetBlockByNum() { + public void testGet() { String jsonParam = "{\"number\": 1}"; MockHttpServletRequest request = createRequest("application/json"); request.setContent(jsonParam.getBytes()); From bc701dec121baa5c8234a487a7ce7c92fc705ef1 Mon Sep 17 00:00:00 2001 From: liukai Date: Wed, 10 Jan 2024 15:30:52 +0800 Subject: [PATCH 0946/1197] test(case): add db test cases --- .../tron/core/db/RecentBlockStoreTest.java | 81 +++++++++++++++++ .../core/db/RecentTransactionStoreTest.java | 72 +++++++++++++++ .../AccountPermissionUpdateServletTest.java | 88 +++++++++++++++++++ .../http/UpdateAccountServletTest.java | 77 ++++++++++++++++ 4 files changed, 318 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/db/RecentBlockStoreTest.java create mode 100644 framework/src/test/java/org/tron/core/db/RecentTransactionStoreTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/AccountPermissionUpdateServletTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/UpdateAccountServletTest.java 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/services/http/AccountPermissionUpdateServletTest.java b/framework/src/test/java/org/tron/core/services/http/AccountPermissionUpdateServletTest.java new file mode 100644 index 00000000000..313a0a12a60 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/AccountPermissionUpdateServletTest.java @@ -0,0 +1,88 @@ +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 AccountPermissionUpdateServletTest extends BaseTest { + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + @Resource + private AccountPermissionUpdateServlet accountPermissionUpdateServlet; + + private String getParam() { + return "{" + + " \"owner_address\":\"TRGhNNfnmgLegT4zHNjEqDSADjgmnHvubJ\"," + + " \"owner\":{" + + " \"type\":0," + + " \"permission_name\":\"owner\"," + + " \"threshold\":1," + + " \"keys\":[" + + " {" + + " \"address\":\"TRGhNNfnmgLegT4zHNjEqDSADjgmnHvubJ\"," + + " \"weight\":1" + + " }" + + " ]" + + " }," + + " \"witness\":{" + + " \"type\":1," + + " \"permission_name\":\"witness\"," + + " \"threshold\":1," + + " \"keys\":[" + + " {" + + " \"address\":\"TRGhNNfnmgLegT4zHNjEqDSADjgmnHvubJ\"," + + " \"weight\":1" + + " }" + + " ]" + + " }," + + " \"actives\":[" + + " {" + + " \"type\":2," + + " \"permission_name\":\"active12323\"," + + " \"threshold\":2," + + " \"operations\":" + + "\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," + + " \"keys\":[" + + " {" + + " \"address\":\"TNhXo1GbRNCuorvYu5JFWN3m2NYr9QQpVR\"," + + " \"weight\":1" + + " }," + + " {" + + " \"address\":\"TKwhcDup8L2PH5r6hxp5CQvQzZqJLmKvZP\"," + + " \"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(); + + accountPermissionUpdateServlet.doPost(request, response); + Assert.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()); + } +} From d9107135c4a159bb52f226ded124b7d024e8cf89 Mon Sep 17 00:00:00 2001 From: o85372940 <155819557+o85372940@users.noreply.github.com> Date: Thu, 11 Jan 2024 09:52:19 +0800 Subject: [PATCH 0947/1197] feat(api):fix a concurrency issue for toString in BlockCapsule (#5657) --- .../org/tron/core/capsule/BlockCapsule.java | 3 +-- .../tron/core/capsule/BlockCapsuleTest.java | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java index 8baafcb5dd5..01ff7fb5365 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java @@ -56,7 +56,6 @@ public class BlockCapsule implements ProtoCapsule { private Block block; private List transactions = new ArrayList<>(); - private StringBuilder toStringBuff = new StringBuilder(); private boolean isSwitch; @Getter @Setter @@ -314,7 +313,7 @@ public boolean hasWitnessSignature() { @Override public String toString() { - toStringBuff.setLength(0); + StringBuilder toStringBuff = new StringBuilder(); toStringBuff.append("BlockCapsule \n[ "); toStringBuff.append("hash=").append(getBlockId()).append("\n"); diff --git a/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java index 0dd078dedb0..3c86d893895 100644 --- a/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java @@ -2,7 +2,9 @@ import com.google.protobuf.ByteString; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; import org.junit.Assert; @@ -146,4 +148,20 @@ public void testGetTimeStamp() { Assert.assertEquals(1234L, blockCapsule0.getTimeStamp()); } + @Test + public void testConcurrentToString() throws InterruptedException { + List threadList = new ArrayList<>(); + int n = 10; + for (int i = 0; i < n; i++) { + threadList.add(new Thread(() -> blockCapsule0.toString())); + } + for (int i = 0; i < n; i++) { + threadList.get(i).start(); + } + for (int i = 0; i < n; i++) { + threadList.get(i).join(); + } + Assert.assertTrue(true); + } + } From e14f3ddf2c4a08a0c4bf4229b289b38d60a2daa7 Mon Sep 17 00:00:00 2001 From: o85372940 <155819557+o85372940@users.noreply.github.com> Date: Thu, 11 Jan 2024 09:53:09 +0800 Subject: [PATCH 0948/1197] feat(db):optimize cache settings (#5659) --- .../org/tron/core/store/WitnessStore.java | 22 +------------------ .../org/tron/consensus/ConsensusDelegate.java | 4 ---- .../consensus/dpos/MaintenanceManager.java | 4 +--- .../tron/common/cache/CacheManagerTest.java | 14 ++++++++++++ .../java/org/tron/core/db/ManagerTest.java | 17 ++++++++++++-- 5 files changed, 31 insertions(+), 30 deletions(-) create mode 100644 framework/src/main/java/org/tron/common/cache/CacheManagerTest.java diff --git a/chainbase/src/main/java/org/tron/core/store/WitnessStore.java b/chainbase/src/main/java/org/tron/core/store/WitnessStore.java index e01680cfc74..d23a73f92f9 100644 --- a/chainbase/src/main/java/org/tron/core/store/WitnessStore.java +++ b/chainbase/src/main/java/org/tron/core/store/WitnessStore.java @@ -11,10 +11,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import org.tron.common.cache.CacheManager; -import org.tron.common.cache.CacheStrategies; -import org.tron.common.cache.CacheType; -import org.tron.common.cache.TronCache; import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.Parameter; import org.tron.core.db.TronStoreWithRevoking; @@ -22,14 +18,10 @@ @Slf4j(topic = "DB") @Component public class WitnessStore extends TronStoreWithRevoking { - // cache for 127 SR - private final TronCache> witnessStandbyCache; @Autowired protected WitnessStore(@Value("witness") String dbName) { super(dbName); - String strategy = String.format(CacheStrategies.PATTERNS, 1, 1, "30s", 1); - witnessStandbyCache = CacheManager.allocate(CacheType.witnessStandby, strategy); } /** @@ -48,19 +40,8 @@ public WitnessCapsule get(byte[] key) { } public List getWitnessStandby() { - List list = - witnessStandbyCache.getIfPresent(Parameter.ChainConstant.WITNESS_STANDBY_LENGTH); - if (list != null) { - return list; - } - return updateWitnessStandby(null); - } - - public List updateWitnessStandby(List all) { List ret; - if (all == null) { - all = getAllWitnesses(); - } + List all = getAllWitnesses(); all.sort(Comparator.comparingLong(WitnessCapsule::getVoteCount) .reversed().thenComparing(Comparator.comparingInt( (WitnessCapsule w) -> w.getAddress().hashCode()).reversed())); @@ -71,7 +52,6 @@ public List updateWitnessStandby(List all) { } // trim voteCount = 0 ret.removeIf(w -> w.getVoteCount() < 1); - witnessStandbyCache.put(Parameter.ChainConstant.WITNESS_STANDBY_LENGTH, ret); return ret; } diff --git a/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java b/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java index 4a98c933bd1..767463a6a5b 100644 --- a/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java +++ b/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java @@ -108,10 +108,6 @@ public List getAllWitnesses() { return witnessStore.getAllWitnesses(); } - public List updateWitnessStandby(List all) { - return witnessStore.updateWitnessStandby(all); - } - public void saveStateFlag(int flag) { dynamicPropertiesStore.saveStateFlag(flag); } diff --git a/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java b/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java index fc6cdd55c15..012169bdb87 100644 --- a/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java +++ b/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java @@ -151,13 +151,11 @@ public void doMaintenance() { if (dynamicPropertiesStore.allowChangeDelegation()) { long nextCycle = dynamicPropertiesStore.getCurrentCycleNumber() + 1; dynamicPropertiesStore.saveCurrentCycleNumber(nextCycle); - List all = consensusDelegate.getAllWitnesses(); - all.forEach(witness -> { + consensusDelegate.getAllWitnesses().forEach(witness -> { delegationStore.setBrokerage(nextCycle, witness.createDbKey(), delegationStore.getBrokerage(witness.createDbKey())); delegationStore.setWitnessVote(nextCycle, witness.createDbKey(), witness.getVoteCount()); }); - consensusDelegate.updateWitnessStandby(all); } } diff --git a/framework/src/main/java/org/tron/common/cache/CacheManagerTest.java b/framework/src/main/java/org/tron/common/cache/CacheManagerTest.java new file mode 100644 index 00000000000..b02b135552a --- /dev/null +++ b/framework/src/main/java/org/tron/common/cache/CacheManagerTest.java @@ -0,0 +1,14 @@ +package org.tron.common.cache; + +import org.junit.Assert; +import org.junit.Test; + +public class CacheManagerTest { + + @Test + public void allocate() { + String strategy = String.format(CacheStrategies.PATTERNS, 1, 1, "30s", 1); + TronCache cache = CacheManager.allocate(CacheType.witnessStandby, strategy); + Assert.assertNull(cache.getIfPresent("test")); + } +} diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index e25faf536f7..bd79f7d9776 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -581,14 +581,24 @@ public void pushSwitchFork() AccountResourceInsufficientException, EventBloomException { String key = "f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62"; + String key2 = "c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4"; byte[] privateKey = ByteArray.fromHexString(key); final ECKey ecKey = ECKey.fromPrivate(privateKey); byte[] address = ecKey.getAddress(); - + WitnessCapsule sr1 = new WitnessCapsule( + ByteString.copyFrom(address), "www.tron.net/first"); + sr1.setVoteCount(1000000000L); + byte[] privateKey2 = ByteArray.fromHexString(key2); + final ECKey ecKey2 = ECKey.fromPrivate(privateKey2); + byte[] address2 = ecKey2.getAddress(); + WitnessCapsule sr2 = new WitnessCapsule( + ByteString.copyFrom(address2), "www.tron.net/second"); + sr2.setVoteCount(100000L); + chainManager.getWitnessStore().put(address, sr1); WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address)); chainManager.getWitnessScheduleStore().saveActiveWitnesses(new ArrayList<>()); chainManager.addWitness(ByteString.copyFrom(address)); - + List witnessStandby1 = chainManager.getWitnessStore().getWitnessStandby(); Block block = getSignedBlock(witnessCapsule.getAddress(), 1533529947843L, privateKey); dbManager.pushBlock(new BlockCapsule(block)); @@ -625,6 +635,9 @@ public void pushSwitchFork() } catch (Exception e) { Assert.assertTrue(e instanceof Exception); } + chainManager.getWitnessStore().put(address, sr2); + List witnessStandby2 = chainManager.getWitnessStore().getWitnessStandby(); + Assert.assertNotEquals(witnessStandby1, witnessStandby2); } From 81fbe870ddcea78e7fcb789c1004b28e21860ed2 Mon Sep 17 00:00:00 2001 From: o85372940 <155819557+o85372940@users.noreply.github.com> Date: Thu, 11 Jan 2024 09:53:28 +0800 Subject: [PATCH 0949/1197] feat(lite):optimize DbLite tool (#5658) --- .../main/java/org/tron/plugins/DbLite.java | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/plugins/src/main/java/org/tron/plugins/DbLite.java b/plugins/src/main/java/org/tron/plugins/DbLite.java index ef7e73ec6d6..732d4913021 100644 --- a/plugins/src/main/java/org/tron/plugins/DbLite.java +++ b/plugins/src/main/java/org/tron/plugins/DbLite.java @@ -355,15 +355,7 @@ private void generateInfoProperties(String propertyfile, long num) 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; - if (cpList.size() > 0) { - String lastestCp = cpList.get(cpList.size() - 1); - checkpointDb = DbTool.getDB( - databaseDir + "/" + DBUtils.CHECKPOINT_DB_V2, lastestCp); - } else { - checkpointDb = DbTool.getDB(databaseDir, CHECKPOINT_DB); - } + DBInterface checkpointDb = getCheckpointDb(databaseDir); Long blockNumber = getLatestBlockHeaderNumFromCP(checkpointDb, latestBlockHeaderNumber.getBytes()); if (blockNumber != null) { @@ -594,7 +586,7 @@ private void mergeBak2Database(String liteDir, BlockNumInfo blockNumInfo) throws 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); + DBInterface checkpointDb = getCheckpointDb(sourceDir); // get data from tmp first. byte[] valueFromTmp = checkpointDb.get(Bytes.concat(simpleEncode(dbName), key)); byte[] value; @@ -672,6 +664,19 @@ private long getSecondBlock(String databaseDir) throws RocksDBException, IOExcep return num; } + private DBInterface getCheckpointDb(String sourceDir) throws IOException, RocksDBException { + List cpList = getCheckpointV2List(sourceDir); + DBInterface checkpointDb; + if (cpList.size() > 0) { + String latestCp = cpList.get(cpList.size() - 1); + checkpointDb = DbTool.getDB( + sourceDir + "/" + DBUtils.CHECKPOINT_DB_V2, latestCp); + } else { + checkpointDb = DbTool.getDB(sourceDir, CHECKPOINT_DB); + } + return checkpointDb; + } + @VisibleForTesting public static void setRecentBlks(long recentBlks) { RECENT_BLKS = recentBlks; From 259fa8501e70fe297e4a634183e74e9d448a1fe2 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Thu, 11 Jan 2024 11:47:34 +0800 Subject: [PATCH 0950/1197] feat(version): update version to 4.7.3.1 (#5661) --- framework/src/main/java/org/tron/program/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 4740daa9d5e..74400376acd 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -4,7 +4,7 @@ public class Version { public static final String VERSION_NAME = "GreatVoyage-v4.7.2-140-g9d13f9cb69"; public static final String VERSION_CODE = "18173"; - private static final String VERSION = "4.7.3"; + private static final String VERSION = "4.7.3.1"; public static String getVersion() { return VERSION; From f9bab7a39b496d52dcfcdbc694d398f7e7db71b1 Mon Sep 17 00:00:00 2001 From: Brown Jiang <317787106@qq.com> Date: Thu, 11 Jan 2024 17:32:09 +0800 Subject: [PATCH 0951/1197] feat(log): catch ContractExeException in createShieldedContractParameter (#5660) * feat(log): catch ContractExeException in createShieldedContractParameters --- .../src/main/java/org/tron/core/db/Manager.java | 1 + .../java/org/tron/core/services/RpcApiService.java | 3 ++- .../org/tron/core/capsule/utils/RLPListTest.java | 12 ++++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index b0d902eb84a..00af042beff 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1843,6 +1843,7 @@ private void postSolidityLogContractTrigger(Long blockNum, Long lastSolidityNum) triggerCapsule.setTriggerName(Trigger.SOLIDITYLOG_TRIGGER_NAME); EventPluginLoader.getInstance().postSolidityLogTrigger(triggerCapsule); } else { + // when switch fork, block will be post to triggerCapsuleQueue, transaction may be not found logger.error("PostSolidityLogContractTrigger txId = {} not contains transaction.", triggerCapsule.getTransactionId()); } diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index c5077facf6f..85ad2dd18dd 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -89,6 +89,7 @@ import org.tron.core.config.args.Args; import org.tron.core.db.Manager; import org.tron.core.exception.BadItemException; +import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ItemNotFoundException; import org.tron.core.exception.NonUniqueObjectException; @@ -2475,7 +2476,7 @@ public void createShieldedContractParameters( ShieldedTRC20Parameters shieldedTRC20Parameters = wallet .createShieldedContractParameters(request); responseObserver.onNext(shieldedTRC20Parameters); - } catch (ZksnarkException | ContractValidateException e) { + } catch (ZksnarkException | ContractValidateException | ContractExeException e) { responseObserver.onError(getRunTimeException(e)); logger.info("createShieldedContractParameters: {}", e.getMessage()); return; diff --git a/framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java b/framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java index 7d903591966..160ecd8f6dd 100644 --- a/framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java +++ b/framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java @@ -1,5 +1,7 @@ package org.tron.core.capsule.utils; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import org.junit.Assert; import org.junit.Test; @@ -23,4 +25,14 @@ public void testGetRLPData() { Assert.assertEquals(new String(rlpList.getRLPData()), "rlpData"); } + @Test + public void testToBytes() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Method method = RLP.class.getDeclaredMethod("toBytes", Object.class); + method.setAccessible(true); + + byte[] aBytes = new byte[10]; + byte[] bBytes = (byte[]) method.invoke(RLP.class, aBytes); + Assert.assertArrayEquals(aBytes, bBytes); + } } From 32f210dc7a0e94ca580c94af03d4c44dd209221f Mon Sep 17 00:00:00 2001 From: liukai Date: Thu, 11 Jan 2024 17:33:33 +0800 Subject: [PATCH 0952/1197] test(case): add transaction test cases --- .../org/tron/core/db/BlockIndexStoreTest.java | 64 +++++++++++++++++++ ...tTransactionInfoByBlockNumServletTest.java | 40 ++++++++++++ .../GetTransactionInfoByIdServletTest.java | 42 ++++++++++++ ...TransactionListFromPendingServletTest.java | 38 +++++++++++ 4 files changed, 184 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/db/BlockIndexStoreTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/GetTransactionInfoByBlockNumServletTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/GetTransactionInfoByIdServletTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/GetTransactionListFromPendingServletTest.java 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/services/http/GetTransactionInfoByBlockNumServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetTransactionInfoByBlockNumServletTest.java new file mode 100644 index 00000000000..5dde8b4abce --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/GetTransactionInfoByBlockNumServletTest.java @@ -0,0 +1,40 @@ +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.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 GetTransactionInfoByBlockNumServletTest extends BaseTest { + + @Resource + private GetTransactionInfoByBlockNumServlet getTransactionInfoByBlockNumServlet; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + @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()); + } +} 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..f2ff962c5a6 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/GetTransactionInfoByIdServletTest.java @@ -0,0 +1,42 @@ +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.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 GetTransactionInfoByIdServletTest extends BaseTest { + + @Resource + private GetTransactionInfoByIdServlet getTransactionInfoByIdServlet; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + @Test + public void testGetInfoById() { + String jsonParam = "{\"value\" : " + + "\"309b6fa3d01353e46f57dd8a8f276" + + "11f98e392b50d035cef213f2c55225a8bd2\"}"; + 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()); + } +} 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()); + } + +} From c2537256201a94d7405857697a468d2571ebb0c3 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 12 Jan 2024 12:09:55 +0800 Subject: [PATCH 0953/1197] update a new version. version name:GreatVoyage-v4.7.3-5-g788136ebe,version code:18180 --- framework/src/main/java/org/tron/program/Version.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 74400376acd..a01eb714297 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,8 +2,8 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.7.2-140-g9d13f9cb69"; - public static final String VERSION_CODE = "18173"; + public static final String VERSION_NAME = "GreatVoyage-v4.7.3-5-g788136ebe"; + public static final String VERSION_CODE = "18180"; private static final String VERSION = "4.7.3.1"; public static String getVersion() { From 5e7a40571f728b69667d9fb3bcc6aba656f0575c Mon Sep 17 00:00:00 2001 From: lurais <107600021+lurais@users.noreply.github.com> Date: Fri, 12 Jan 2024 19:47:38 +0800 Subject: [PATCH 0954/1197] Merge master into release_v4.7.4 branch (#5669) * feat(db):optimize cache settings (#5659) * feat(lite):optimize DbLite tool (#5658) --- .../org/tron/core/store/WitnessStore.java | 22 +---- .../org/tron/consensus/ConsensusDelegate.java | 4 - .../consensus/dpos/MaintenanceManager.java | 4 +- .../main/java/org/tron/program/Version.java | 6 +- .../java/org/tron/core/db/ManagerTest.java | 17 +++- .../main/java/org/tron/plugins/DbLite.java | 93 ++++++++++++++++--- 6 files changed, 98 insertions(+), 48 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/store/WitnessStore.java b/chainbase/src/main/java/org/tron/core/store/WitnessStore.java index e01680cfc74..d23a73f92f9 100644 --- a/chainbase/src/main/java/org/tron/core/store/WitnessStore.java +++ b/chainbase/src/main/java/org/tron/core/store/WitnessStore.java @@ -11,10 +11,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import org.tron.common.cache.CacheManager; -import org.tron.common.cache.CacheStrategies; -import org.tron.common.cache.CacheType; -import org.tron.common.cache.TronCache; import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.Parameter; import org.tron.core.db.TronStoreWithRevoking; @@ -22,14 +18,10 @@ @Slf4j(topic = "DB") @Component public class WitnessStore extends TronStoreWithRevoking { - // cache for 127 SR - private final TronCache> witnessStandbyCache; @Autowired protected WitnessStore(@Value("witness") String dbName) { super(dbName); - String strategy = String.format(CacheStrategies.PATTERNS, 1, 1, "30s", 1); - witnessStandbyCache = CacheManager.allocate(CacheType.witnessStandby, strategy); } /** @@ -48,19 +40,8 @@ public WitnessCapsule get(byte[] key) { } public List getWitnessStandby() { - List list = - witnessStandbyCache.getIfPresent(Parameter.ChainConstant.WITNESS_STANDBY_LENGTH); - if (list != null) { - return list; - } - return updateWitnessStandby(null); - } - - public List updateWitnessStandby(List all) { List ret; - if (all == null) { - all = getAllWitnesses(); - } + List all = getAllWitnesses(); all.sort(Comparator.comparingLong(WitnessCapsule::getVoteCount) .reversed().thenComparing(Comparator.comparingInt( (WitnessCapsule w) -> w.getAddress().hashCode()).reversed())); @@ -71,7 +52,6 @@ public List updateWitnessStandby(List all) { } // trim voteCount = 0 ret.removeIf(w -> w.getVoteCount() < 1); - witnessStandbyCache.put(Parameter.ChainConstant.WITNESS_STANDBY_LENGTH, ret); return ret; } diff --git a/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java b/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java index 4a98c933bd1..767463a6a5b 100644 --- a/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java +++ b/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java @@ -108,10 +108,6 @@ public List getAllWitnesses() { return witnessStore.getAllWitnesses(); } - public List updateWitnessStandby(List all) { - return witnessStore.updateWitnessStandby(all); - } - public void saveStateFlag(int flag) { dynamicPropertiesStore.saveStateFlag(flag); } diff --git a/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java b/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java index fc6cdd55c15..012169bdb87 100644 --- a/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java +++ b/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java @@ -151,13 +151,11 @@ public void doMaintenance() { if (dynamicPropertiesStore.allowChangeDelegation()) { long nextCycle = dynamicPropertiesStore.getCurrentCycleNumber() + 1; dynamicPropertiesStore.saveCurrentCycleNumber(nextCycle); - List all = consensusDelegate.getAllWitnesses(); - all.forEach(witness -> { + consensusDelegate.getAllWitnesses().forEach(witness -> { delegationStore.setBrokerage(nextCycle, witness.createDbKey(), delegationStore.getBrokerage(witness.createDbKey())); delegationStore.setWitnessVote(nextCycle, witness.createDbKey(), witness.getVoteCount()); }); - consensusDelegate.updateWitnessStandby(all); } } diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 4740daa9d5e..a01eb714297 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,9 +2,9 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.7.2-140-g9d13f9cb69"; - public static final String VERSION_CODE = "18173"; - private static final String VERSION = "4.7.3"; + public static final String VERSION_NAME = "GreatVoyage-v4.7.3-5-g788136ebe"; + public static final String VERSION_CODE = "18180"; + private static final String VERSION = "4.7.3.1"; public static String getVersion() { return VERSION; diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index e25faf536f7..bd79f7d9776 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -581,14 +581,24 @@ public void pushSwitchFork() AccountResourceInsufficientException, EventBloomException { String key = "f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62"; + String key2 = "c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4"; byte[] privateKey = ByteArray.fromHexString(key); final ECKey ecKey = ECKey.fromPrivate(privateKey); byte[] address = ecKey.getAddress(); - + WitnessCapsule sr1 = new WitnessCapsule( + ByteString.copyFrom(address), "www.tron.net/first"); + sr1.setVoteCount(1000000000L); + byte[] privateKey2 = ByteArray.fromHexString(key2); + final ECKey ecKey2 = ECKey.fromPrivate(privateKey2); + byte[] address2 = ecKey2.getAddress(); + WitnessCapsule sr2 = new WitnessCapsule( + ByteString.copyFrom(address2), "www.tron.net/second"); + sr2.setVoteCount(100000L); + chainManager.getWitnessStore().put(address, sr1); WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address)); chainManager.getWitnessScheduleStore().saveActiveWitnesses(new ArrayList<>()); chainManager.addWitness(ByteString.copyFrom(address)); - + List witnessStandby1 = chainManager.getWitnessStore().getWitnessStandby(); Block block = getSignedBlock(witnessCapsule.getAddress(), 1533529947843L, privateKey); dbManager.pushBlock(new BlockCapsule(block)); @@ -625,6 +635,9 @@ public void pushSwitchFork() } catch (Exception e) { Assert.assertTrue(e instanceof Exception); } + chainManager.getWitnessStore().put(address, sr2); + List witnessStandby2 = chainManager.getWitnessStore().getWitnessStandby(); + Assert.assertNotEquals(witnessStandby1, witnessStandby2); } diff --git a/plugins/src/main/java/org/tron/plugins/DbLite.java b/plugins/src/main/java/org/tron/plugins/DbLite.java index 8804d6210b2..732d4913021 100644 --- a/plugins/src/main/java/org/tron/plugins/DbLite.java +++ b/plugins/src/main/java/org/tron/plugins/DbLite.java @@ -3,6 +3,8 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Lists; 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; @@ -153,10 +155,10 @@ public void generateSnapshot(String sourceDir, String snapshotDir) { long start = System.currentTimeMillis(); snapshotDir = Paths.get(snapshotDir, SNAPSHOT_DIR_NAME).toString(); try { - mergeCheckpoint(sourceDir); hasEnoughBlock(sourceDir); List snapshotDbs = getSnapshotDbs(sourceDir); split(sourceDir, snapshotDir, snapshotDbs); + mergeCheckpoint2Snapshot(sourceDir, snapshotDir); // write genesisBlock , latest recent blocks and trans fillSnapshotBlockAndTransDb(sourceDir, snapshotDir); // save min block to info @@ -190,9 +192,9 @@ public void generateHistory(String sourceDir, String historyDir) { throw new IllegalStateException( String.format("Unavailable sourceDir: %s is not fullNode data.", sourceDir)); } - mergeCheckpoint(sourceDir); hasEnoughBlock(sourceDir); split(sourceDir, historyDir, archiveDbs); + mergeCheckpoint2History(sourceDir, historyDir); // save max block to info generateInfoProperties(Paths.get(historyDir, INFO_FILE_NAME).toString(), getLatestBlockHeaderNum(sourceDir)); @@ -261,6 +263,15 @@ private List getSnapshotDbs(String sourceDir) { 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."); spec.commandLine().getOut().println("Begin to split the dbs."); @@ -278,7 +289,7 @@ private void split(String sourceDir, String destDir, List dbs) throws IO FileUtils.copyDatabases(Paths.get(sourceDir), Paths.get(destDir), dbs); } - private void mergeCheckpoint(String sourceDir) { + private void mergeCheckpoint(String sourceDir, String destDir, List destDbs) { logger.info("Begin to merge checkpoint to dataset."); spec.commandLine().getOut().println("Begin to merge checkpoint to dataset."); try { @@ -287,18 +298,18 @@ private void mergeCheckpoint(String sourceDir) { for (String cp : cpList) { DBInterface checkpointDb = DbTool.getDB( sourceDir + "/" + DBUtils.CHECKPOINT_DB_V2, cp); - recover(checkpointDb, sourceDir); + recover(checkpointDb, destDir, destDbs); } } else if (Paths.get(sourceDir, CHECKPOINT_DB).toFile().exists()) { DBInterface tmpDb = DbTool.getDB(sourceDir, CHECKPOINT_DB); - recover(tmpDb, sourceDir); + recover(tmpDb, destDir, destDbs); } } catch (IOException | RocksDBException e) { throw new RuntimeException(e); } } - private void recover(DBInterface db, String destDir) + private void recover(DBInterface db, String destDir, List destDbs) throws IOException, RocksDBException { try (DBIterator iterator = db.iterator()) { for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) { @@ -312,15 +323,17 @@ private void recover(DBInterface db, String destDir) byte[] realKey = Arrays.copyOfRange(key, dbName.getBytes().length + 4, key.length); byte[] realValue = value.length == 1 ? null : Arrays.copyOfRange(value, 1, value.length); - DBInterface destDb = DbTool.getDB(destDir, dbName); - if (realValue != null) { - destDb.put(realKey, realValue); - } else { - byte op = value[0]; - if (DBUtils.Operator.DELETE.getValue() == op) { - destDb.delete(realKey); + if (destDbs != null && destDbs.contains(dbName)) { + DBInterface destDb = DbTool.getDB(destDir, dbName); + if (realValue != null) { + destDb.put(realKey, realValue); } else { - destDb.put(realKey, new byte[0]); + byte op = value[0]; + if (DBUtils.Operator.DELETE.getValue() == op) { + destDb.delete(realKey); + } else { + destDb.put(realKey, new byte[0]); + } } } } @@ -340,7 +353,15 @@ private void generateInfoProperties(String propertyfile, long num) } private long getLatestBlockHeaderNum(String databaseDir) throws IOException, RocksDBException { + // query latest_block_header_number from checkpoint first final String latestBlockHeaderNumber = "latest_block_header_number"; + DBInterface checkpointDb = getCheckpointDb(databaseDir); + 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) @@ -348,6 +369,14 @@ private long getLatestBlockHeaderNum(String databaseDir) throws IOException, Roc () -> 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. */ @@ -414,6 +443,15 @@ private byte[] getGenesisBlockHash(String parentDir) throws IOException, RocksDB 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 liteDir) throws IOException, RocksDBException { logger.info("Check the compatibility of this history."); @@ -485,6 +523,7 @@ private void trimExtraHistory(String liteDir, BlockNumInfo blockNumInfo) DBInterface transDb = DbTool.getDB(liteDir, TRANS_DB_NAME); DBInterface tranRetDb = DbTool.getDB(liteDir, TRANSACTION_RET_DB_NAME); + ProgressBar.wrap(LongStream.rangeClosed(start, end) .boxed() .sorted((a, b) -> Long.compare(b, a)), "trimHistory").forEach(n -> { @@ -519,6 +558,7 @@ private void mergeBak2Database(String liteDir, BlockNumInfo blockNumInfo) throws return; } + Path bakDir = Paths.get(liteDir, BACKUP_DIR_PREFIX + START_TIME); logger.info("Begin to merge {} to database, start {} end {}.", bakDir, start, end); spec.commandLine().getOut() @@ -545,7 +585,17 @@ private void mergeBak2Database(String liteDir, BlockNumInfo blockNumInfo) throws private byte[] getDataFromSourceDB(String sourceDir, String dbName, byte[] key) throws IOException, RocksDBException { - byte[] value = DbTool.getDB(sourceDir, dbName).get(key); + DBInterface sourceDb = DbTool.getDB(sourceDir, dbName); + DBInterface checkpointDb = getCheckpointDb(sourceDir); + // 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))); @@ -614,6 +664,19 @@ private long getSecondBlock(String databaseDir) throws RocksDBException, IOExcep return num; } + private DBInterface getCheckpointDb(String sourceDir) throws IOException, RocksDBException { + List cpList = getCheckpointV2List(sourceDir); + DBInterface checkpointDb; + if (cpList.size() > 0) { + String latestCp = cpList.get(cpList.size() - 1); + checkpointDb = DbTool.getDB( + sourceDir + "/" + DBUtils.CHECKPOINT_DB_V2, latestCp); + } else { + checkpointDb = DbTool.getDB(sourceDir, CHECKPOINT_DB); + } + return checkpointDb; + } + @VisibleForTesting public static void setRecentBlks(long recentBlks) { RECENT_BLKS = recentBlks; From 0f5a8defc65f5a8d5e61820cc6a03455c994b354 Mon Sep 17 00:00:00 2001 From: lurais <107600021+lurais@users.noreply.github.com> Date: Fri, 12 Jan 2024 19:48:27 +0800 Subject: [PATCH 0955/1197] Merge master into develop branch (#5668) * feat(api):fix a concurrency issue for toString in BlockCapsule (#5657) * feat(db):optimize cache settings (#5659) * feat(lite):optimize DbLite tool (#5658) --- .../org/tron/core/store/WitnessStore.java | 22 +---- .../org/tron/consensus/ConsensusDelegate.java | 4 - .../consensus/dpos/MaintenanceManager.java | 4 +- .../main/java/org/tron/program/Version.java | 6 +- .../java/org/tron/core/db/ManagerTest.java | 17 +++- .../main/java/org/tron/plugins/DbLite.java | 93 ++++++++++++++++--- 6 files changed, 98 insertions(+), 48 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/store/WitnessStore.java b/chainbase/src/main/java/org/tron/core/store/WitnessStore.java index e01680cfc74..d23a73f92f9 100644 --- a/chainbase/src/main/java/org/tron/core/store/WitnessStore.java +++ b/chainbase/src/main/java/org/tron/core/store/WitnessStore.java @@ -11,10 +11,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import org.tron.common.cache.CacheManager; -import org.tron.common.cache.CacheStrategies; -import org.tron.common.cache.CacheType; -import org.tron.common.cache.TronCache; import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.Parameter; import org.tron.core.db.TronStoreWithRevoking; @@ -22,14 +18,10 @@ @Slf4j(topic = "DB") @Component public class WitnessStore extends TronStoreWithRevoking { - // cache for 127 SR - private final TronCache> witnessStandbyCache; @Autowired protected WitnessStore(@Value("witness") String dbName) { super(dbName); - String strategy = String.format(CacheStrategies.PATTERNS, 1, 1, "30s", 1); - witnessStandbyCache = CacheManager.allocate(CacheType.witnessStandby, strategy); } /** @@ -48,19 +40,8 @@ public WitnessCapsule get(byte[] key) { } public List getWitnessStandby() { - List list = - witnessStandbyCache.getIfPresent(Parameter.ChainConstant.WITNESS_STANDBY_LENGTH); - if (list != null) { - return list; - } - return updateWitnessStandby(null); - } - - public List updateWitnessStandby(List all) { List ret; - if (all == null) { - all = getAllWitnesses(); - } + List all = getAllWitnesses(); all.sort(Comparator.comparingLong(WitnessCapsule::getVoteCount) .reversed().thenComparing(Comparator.comparingInt( (WitnessCapsule w) -> w.getAddress().hashCode()).reversed())); @@ -71,7 +52,6 @@ public List updateWitnessStandby(List all) { } // trim voteCount = 0 ret.removeIf(w -> w.getVoteCount() < 1); - witnessStandbyCache.put(Parameter.ChainConstant.WITNESS_STANDBY_LENGTH, ret); return ret; } diff --git a/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java b/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java index 4a98c933bd1..767463a6a5b 100644 --- a/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java +++ b/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java @@ -108,10 +108,6 @@ public List getAllWitnesses() { return witnessStore.getAllWitnesses(); } - public List updateWitnessStandby(List all) { - return witnessStore.updateWitnessStandby(all); - } - public void saveStateFlag(int flag) { dynamicPropertiesStore.saveStateFlag(flag); } diff --git a/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java b/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java index fc6cdd55c15..012169bdb87 100644 --- a/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java +++ b/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java @@ -151,13 +151,11 @@ public void doMaintenance() { if (dynamicPropertiesStore.allowChangeDelegation()) { long nextCycle = dynamicPropertiesStore.getCurrentCycleNumber() + 1; dynamicPropertiesStore.saveCurrentCycleNumber(nextCycle); - List all = consensusDelegate.getAllWitnesses(); - all.forEach(witness -> { + consensusDelegate.getAllWitnesses().forEach(witness -> { delegationStore.setBrokerage(nextCycle, witness.createDbKey(), delegationStore.getBrokerage(witness.createDbKey())); delegationStore.setWitnessVote(nextCycle, witness.createDbKey(), witness.getVoteCount()); }); - consensusDelegate.updateWitnessStandby(all); } } diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 4740daa9d5e..a01eb714297 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,9 +2,9 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.7.2-140-g9d13f9cb69"; - public static final String VERSION_CODE = "18173"; - private static final String VERSION = "4.7.3"; + public static final String VERSION_NAME = "GreatVoyage-v4.7.3-5-g788136ebe"; + public static final String VERSION_CODE = "18180"; + private static final String VERSION = "4.7.3.1"; public static String getVersion() { return VERSION; diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index e25faf536f7..bd79f7d9776 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -581,14 +581,24 @@ public void pushSwitchFork() AccountResourceInsufficientException, EventBloomException { String key = "f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62"; + String key2 = "c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4"; byte[] privateKey = ByteArray.fromHexString(key); final ECKey ecKey = ECKey.fromPrivate(privateKey); byte[] address = ecKey.getAddress(); - + WitnessCapsule sr1 = new WitnessCapsule( + ByteString.copyFrom(address), "www.tron.net/first"); + sr1.setVoteCount(1000000000L); + byte[] privateKey2 = ByteArray.fromHexString(key2); + final ECKey ecKey2 = ECKey.fromPrivate(privateKey2); + byte[] address2 = ecKey2.getAddress(); + WitnessCapsule sr2 = new WitnessCapsule( + ByteString.copyFrom(address2), "www.tron.net/second"); + sr2.setVoteCount(100000L); + chainManager.getWitnessStore().put(address, sr1); WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address)); chainManager.getWitnessScheduleStore().saveActiveWitnesses(new ArrayList<>()); chainManager.addWitness(ByteString.copyFrom(address)); - + List witnessStandby1 = chainManager.getWitnessStore().getWitnessStandby(); Block block = getSignedBlock(witnessCapsule.getAddress(), 1533529947843L, privateKey); dbManager.pushBlock(new BlockCapsule(block)); @@ -625,6 +635,9 @@ public void pushSwitchFork() } catch (Exception e) { Assert.assertTrue(e instanceof Exception); } + chainManager.getWitnessStore().put(address, sr2); + List witnessStandby2 = chainManager.getWitnessStore().getWitnessStandby(); + Assert.assertNotEquals(witnessStandby1, witnessStandby2); } diff --git a/plugins/src/main/java/org/tron/plugins/DbLite.java b/plugins/src/main/java/org/tron/plugins/DbLite.java index 8804d6210b2..732d4913021 100644 --- a/plugins/src/main/java/org/tron/plugins/DbLite.java +++ b/plugins/src/main/java/org/tron/plugins/DbLite.java @@ -3,6 +3,8 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Lists; 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; @@ -153,10 +155,10 @@ public void generateSnapshot(String sourceDir, String snapshotDir) { long start = System.currentTimeMillis(); snapshotDir = Paths.get(snapshotDir, SNAPSHOT_DIR_NAME).toString(); try { - mergeCheckpoint(sourceDir); hasEnoughBlock(sourceDir); List snapshotDbs = getSnapshotDbs(sourceDir); split(sourceDir, snapshotDir, snapshotDbs); + mergeCheckpoint2Snapshot(sourceDir, snapshotDir); // write genesisBlock , latest recent blocks and trans fillSnapshotBlockAndTransDb(sourceDir, snapshotDir); // save min block to info @@ -190,9 +192,9 @@ public void generateHistory(String sourceDir, String historyDir) { throw new IllegalStateException( String.format("Unavailable sourceDir: %s is not fullNode data.", sourceDir)); } - mergeCheckpoint(sourceDir); hasEnoughBlock(sourceDir); split(sourceDir, historyDir, archiveDbs); + mergeCheckpoint2History(sourceDir, historyDir); // save max block to info generateInfoProperties(Paths.get(historyDir, INFO_FILE_NAME).toString(), getLatestBlockHeaderNum(sourceDir)); @@ -261,6 +263,15 @@ private List getSnapshotDbs(String sourceDir) { 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."); spec.commandLine().getOut().println("Begin to split the dbs."); @@ -278,7 +289,7 @@ private void split(String sourceDir, String destDir, List dbs) throws IO FileUtils.copyDatabases(Paths.get(sourceDir), Paths.get(destDir), dbs); } - private void mergeCheckpoint(String sourceDir) { + private void mergeCheckpoint(String sourceDir, String destDir, List destDbs) { logger.info("Begin to merge checkpoint to dataset."); spec.commandLine().getOut().println("Begin to merge checkpoint to dataset."); try { @@ -287,18 +298,18 @@ private void mergeCheckpoint(String sourceDir) { for (String cp : cpList) { DBInterface checkpointDb = DbTool.getDB( sourceDir + "/" + DBUtils.CHECKPOINT_DB_V2, cp); - recover(checkpointDb, sourceDir); + recover(checkpointDb, destDir, destDbs); } } else if (Paths.get(sourceDir, CHECKPOINT_DB).toFile().exists()) { DBInterface tmpDb = DbTool.getDB(sourceDir, CHECKPOINT_DB); - recover(tmpDb, sourceDir); + recover(tmpDb, destDir, destDbs); } } catch (IOException | RocksDBException e) { throw new RuntimeException(e); } } - private void recover(DBInterface db, String destDir) + private void recover(DBInterface db, String destDir, List destDbs) throws IOException, RocksDBException { try (DBIterator iterator = db.iterator()) { for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) { @@ -312,15 +323,17 @@ private void recover(DBInterface db, String destDir) byte[] realKey = Arrays.copyOfRange(key, dbName.getBytes().length + 4, key.length); byte[] realValue = value.length == 1 ? null : Arrays.copyOfRange(value, 1, value.length); - DBInterface destDb = DbTool.getDB(destDir, dbName); - if (realValue != null) { - destDb.put(realKey, realValue); - } else { - byte op = value[0]; - if (DBUtils.Operator.DELETE.getValue() == op) { - destDb.delete(realKey); + if (destDbs != null && destDbs.contains(dbName)) { + DBInterface destDb = DbTool.getDB(destDir, dbName); + if (realValue != null) { + destDb.put(realKey, realValue); } else { - destDb.put(realKey, new byte[0]); + byte op = value[0]; + if (DBUtils.Operator.DELETE.getValue() == op) { + destDb.delete(realKey); + } else { + destDb.put(realKey, new byte[0]); + } } } } @@ -340,7 +353,15 @@ private void generateInfoProperties(String propertyfile, long num) } private long getLatestBlockHeaderNum(String databaseDir) throws IOException, RocksDBException { + // query latest_block_header_number from checkpoint first final String latestBlockHeaderNumber = "latest_block_header_number"; + DBInterface checkpointDb = getCheckpointDb(databaseDir); + 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) @@ -348,6 +369,14 @@ private long getLatestBlockHeaderNum(String databaseDir) throws IOException, Roc () -> 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. */ @@ -414,6 +443,15 @@ private byte[] getGenesisBlockHash(String parentDir) throws IOException, RocksDB 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 liteDir) throws IOException, RocksDBException { logger.info("Check the compatibility of this history."); @@ -485,6 +523,7 @@ private void trimExtraHistory(String liteDir, BlockNumInfo blockNumInfo) DBInterface transDb = DbTool.getDB(liteDir, TRANS_DB_NAME); DBInterface tranRetDb = DbTool.getDB(liteDir, TRANSACTION_RET_DB_NAME); + ProgressBar.wrap(LongStream.rangeClosed(start, end) .boxed() .sorted((a, b) -> Long.compare(b, a)), "trimHistory").forEach(n -> { @@ -519,6 +558,7 @@ private void mergeBak2Database(String liteDir, BlockNumInfo blockNumInfo) throws return; } + Path bakDir = Paths.get(liteDir, BACKUP_DIR_PREFIX + START_TIME); logger.info("Begin to merge {} to database, start {} end {}.", bakDir, start, end); spec.commandLine().getOut() @@ -545,7 +585,17 @@ private void mergeBak2Database(String liteDir, BlockNumInfo blockNumInfo) throws private byte[] getDataFromSourceDB(String sourceDir, String dbName, byte[] key) throws IOException, RocksDBException { - byte[] value = DbTool.getDB(sourceDir, dbName).get(key); + DBInterface sourceDb = DbTool.getDB(sourceDir, dbName); + DBInterface checkpointDb = getCheckpointDb(sourceDir); + // 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))); @@ -614,6 +664,19 @@ private long getSecondBlock(String databaseDir) throws RocksDBException, IOExcep return num; } + private DBInterface getCheckpointDb(String sourceDir) throws IOException, RocksDBException { + List cpList = getCheckpointV2List(sourceDir); + DBInterface checkpointDb; + if (cpList.size() > 0) { + String latestCp = cpList.get(cpList.size() - 1); + checkpointDb = DbTool.getDB( + sourceDir + "/" + DBUtils.CHECKPOINT_DB_V2, latestCp); + } else { + checkpointDb = DbTool.getDB(sourceDir, CHECKPOINT_DB); + } + return checkpointDb; + } + @VisibleForTesting public static void setRecentBlks(long recentBlks) { RECENT_BLKS = recentBlks; From 32e1e151a4c9ab748f3f31bd5a25a0b6c4db4909 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Mon, 15 Jan 2024 11:39:49 +0800 Subject: [PATCH 0956/1197] feat(db): optimize calculation services for reward when the node starts (#5654) * feat(db): optimize calculation services for reward when the service starts * feat(log): change log from error to warn for merkle root mismatch --- .../tron/core/service/RewardViCalService.java | 16 +++++++++++----- .../src/main/java/org/tron/core/db/Manager.java | 5 +++++ .../tron/core/services/ComputeRewardTest.java | 4 ---- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java b/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java index acb16142b3f..33e5233b551 100644 --- a/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java +++ b/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java @@ -17,7 +17,6 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.LongStream; -import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @@ -75,8 +74,14 @@ public RewardViCalService(@Autowired DynamicPropertiesStore propertiesStore, this.witnessStore = witnessStore.getDb(); } - @PostConstruct - private void init() { + public void init() { + // after init, we can get the latest block header number from db + this.newRewardCalStartCycle = this.getNewRewardAlgorithmEffectiveCycle(); + boolean ret = this.newRewardCalStartCycle != Long.MAX_VALUE; + if (ret) { + // checkpoint is flushed to db, we can start rewardViCalService immediately + lastBlockNumber = Long.MAX_VALUE; + } es.scheduleWithFixedDelay(this::maybeRun, 0, 3, TimeUnit.SECONDS); } @@ -100,7 +105,8 @@ private void maybeRun() { this.clearUp(true); logger.info("rewardViCalService is already done"); } else { - if (this.getLatestBlockHeaderNumber() > lastBlockNumber) { + if (lastBlockNumber == Long.MAX_VALUE // start rewardViCalService immediately + || this.getLatestBlockHeaderNumber() > lastBlockNumber) { // checkpoint is flushed to db, so we can start rewardViCalService startRewardCal(); clearUp(true); @@ -170,7 +176,7 @@ private void calcMerkleRoot() { Sha256Hash rewardViRootLocal = MerkleTree.getInstance().createTree(ids).getRoot().getHash(); if (!Objects.equals(rewardViRoot, rewardViRootLocal)) { - logger.error("merkle root mismatch, expect: {}, actual: {}", + logger.warn("merkle root mismatch, expect: {}, actual: {}", rewardViRoot, rewardViRootLocal); } logger.info("calcMerkleRoot: {}", rewardViRootLocal); diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 00af042beff..445c48fdd94 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -130,6 +130,7 @@ import org.tron.core.metrics.MetricsKey; import org.tron.core.metrics.MetricsUtil; import org.tron.core.service.MortgageService; +import org.tron.core.service.RewardViCalService; import org.tron.core.store.AccountAssetStore; import org.tron.core.store.AccountIdIndexStore; import org.tron.core.store.AccountIndexStore; @@ -260,6 +261,9 @@ public class Manager { private ExecutorService filterEs; private static final String filterEsName = "filter"; + @Autowired + private RewardViCalService rewardViCalService; + /** * Cycle thread to rePush Transactions */ @@ -465,6 +469,7 @@ public void init() { revokingStore.disable(); revokingStore.check(); transactionCache.initCache(); + rewardViCalService.init(); this.setProposalController(ProposalController.createInstance(this)); this.setMerkleContainer( merkleContainer.createInstance(chainBaseManager.getMerkleTreeStore(), diff --git a/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java b/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java index 17b2526d6d0..00e0799cf11 100644 --- a/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java +++ b/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java @@ -22,7 +22,6 @@ import org.tron.common.error.TronDBException; import org.tron.common.es.ExecutorServiceManager; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.WitnessCapsule; @@ -251,9 +250,6 @@ private void setUp() { } catch (ExecutionException e) { throw new TronDBException(e); } - - rewardViCalService.setRewardViRoot(Sha256Hash.wrap( - ByteString.fromHex("e0ebe2f3243391ed674dff816a07f589a3279420d6d88bc823b6a9d5778337ce"))); } @Test From 46454a24824bdb74a3d6063ef119cf2a8300eed9 Mon Sep 17 00:00:00 2001 From: Brown Jiang <317787106@qq.com> Date: Mon, 15 Jan 2024 12:39:42 +0800 Subject: [PATCH 0957/1197] feat(log):verify columns of hellomessage to avoid too long log (#5667) --- .../net/message/handshake/HelloMessage.java | 17 ++++++++ .../service/handshake/HandshakeService.java | 15 ++++--- .../net/services/HandShakeServiceTest.java | 41 +++++++++++++++++++ 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java b/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java index b98d0e173fb..867ced5dbff 100755 --- a/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java +++ b/framework/src/main/java/org/tron/core/net/message/handshake/HelloMessage.java @@ -4,6 +4,7 @@ import lombok.Getter; import org.apache.commons.lang3.StringUtils; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.ChainBaseManager; import org.tron.core.capsule.BlockCapsule; @@ -169,6 +170,22 @@ public boolean valid() { return false; } + int maxByteSize = 200; + ByteString address = this.helloMessage.getAddress(); + if (!address.isEmpty() && address.toByteArray().length > maxByteSize) { + return false; + } + + ByteString sig = this.helloMessage.getSignature(); + if (!sig.isEmpty() && sig.toByteArray().length > maxByteSize) { + return false; + } + + ByteString codeVersion = this.helloMessage.getCodeVersion(); + if (!codeVersion.isEmpty() && codeVersion.toByteArray().length > maxByteSize) { + return false; + } + return true; } diff --git a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java index aa6567d1cda..6cd117c83dd 100644 --- a/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java +++ b/framework/src/main/java/org/tron/core/net/service/handshake/HandshakeService.java @@ -48,12 +48,15 @@ public void processHelloMessage(PeerConnection peer, HelloMessage msg) { } if (!msg.valid()) { - logger.warn("Peer {} invalid hello message parameters, " - + "GenesisBlockId: {}, SolidBlockId: {}, HeadBlockId: {}", - peer.getInetSocketAddress(), - ByteArray.toHexString(msg.getInstance().getGenesisBlockId().getHash().toByteArray()), - ByteArray.toHexString(msg.getInstance().getSolidBlockId().getHash().toByteArray()), - ByteArray.toHexString(msg.getInstance().getHeadBlockId().getHash().toByteArray())); + logger.warn("Peer {} invalid hello message parameters, GenesisBlockId: {}, SolidBlockId: {}, " + + "HeadBlockId: {}, address: {}, sig: {}, codeVersion: {}", + peer.getInetSocketAddress(), + ByteArray.toHexString(msg.getInstance().getGenesisBlockId().getHash().toByteArray()), + ByteArray.toHexString(msg.getInstance().getSolidBlockId().getHash().toByteArray()), + ByteArray.toHexString(msg.getInstance().getHeadBlockId().getHash().toByteArray()), + msg.getInstance().getAddress().toByteArray().length, + msg.getInstance().getSignature().toByteArray().length, + msg.getInstance().getCodeVersion().toByteArray().length); peer.disconnect(ReasonCode.UNEXPECTED_IDENTITY); return; } diff --git a/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java b/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java index ea2156ae713..f4fabce5d64 100644 --- a/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/HandShakeServiceTest.java @@ -21,6 +21,7 @@ import org.mockito.Mockito; import org.springframework.context.ApplicationContext; import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.ByteArray; import org.tron.common.utils.ReflectUtils; import org.tron.common.utils.Sha256Hash; import org.tron.core.ChainBaseManager; @@ -137,6 +138,37 @@ public void testInvalidHelloMessage() { } } + @Test + public void testInvalidHelloMessage2() throws Exception { + Protocol.HelloMessage.Builder builder = getTestHelloMessageBuilder(); + Assert.assertTrue(new HelloMessage(builder.build().toByteArray()).valid()); + + builder.setAddress(ByteString.copyFrom(new byte[201])); + HelloMessage helloMessage = new HelloMessage(builder.build().toByteArray()); + Assert.assertFalse(helloMessage.valid()); + + builder.setAddress(ByteString.copyFrom(new byte[200])); + helloMessage = new HelloMessage(builder.build().toByteArray()); + Assert.assertTrue(helloMessage.valid()); + + builder.setSignature(ByteString.copyFrom(new byte[201])); + helloMessage = new HelloMessage(builder.build().toByteArray()); + Assert.assertFalse(helloMessage.valid()); + + builder.setSignature(ByteString.copyFrom(new byte[200])); + helloMessage = new HelloMessage(builder.build().toByteArray()); + Assert.assertTrue(helloMessage.valid()); + + builder.setCodeVersion(ByteString.copyFrom(new byte[201])); + helloMessage = new HelloMessage(builder.build().toByteArray()); + Assert.assertFalse(helloMessage.valid()); + + builder.setCodeVersion(ByteString.copyFrom(new byte[200])); + helloMessage = new HelloMessage(builder.build().toByteArray()); + Assert.assertTrue(helloMessage.valid()); + } + + @Test public void testRelayHelloMessage() throws NoSuchMethodException { InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); @@ -266,4 +298,13 @@ private Protocol.HelloMessage.Builder getHelloMessageBuilder(Node from, long tim return builder; } + + private Protocol.HelloMessage.Builder getTestHelloMessageBuilder() { + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); + Node node = new Node(NetUtil.getNodeId(), a1.getAddress().getHostAddress(), null, a1.getPort()); + Protocol.HelloMessage.Builder builder = + getHelloMessageBuilder(node, System.currentTimeMillis(), + ChainBaseManager.getChainBaseManager()); + return builder; + } } From 1225ace361bfce61f61f93305f3b407c89dfd9f1 Mon Sep 17 00:00:00 2001 From: liukai Date: Mon, 15 Jan 2024 20:25:37 +0800 Subject: [PATCH 0958/1197] test(case): optimize case --- .../core/actuator/ActuatorFactoryTest.java | 71 +++++++++++++++ .../AccountPermissionUpdateServletTest.java | 88 ------------------- .../services/http/ClearABIServletTest.java | 55 +++++++++++- .../http/CreateAccountServletTest.java | 33 ++++++- .../http/CreateAssetIssueServletTest.java | 33 ++++++- .../http/CreateSpendAuthSigServletTest.java | 60 +++++++++++++ .../http/CreateWitnessServletTest.java | 88 +++++++++++++++++++ ...tTransactionInfoByBlockNumServletTest.java | 39 ++++++++ .../GetTransactionInfoByIdServletTest.java | 88 ++++++++++++++++++- 9 files changed, 457 insertions(+), 98 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/actuator/ActuatorFactoryTest.java delete mode 100644 framework/src/test/java/org/tron/core/services/http/AccountPermissionUpdateServletTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/CreateSpendAuthSigServletTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/CreateWitnessServletTest.java 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/services/http/AccountPermissionUpdateServletTest.java b/framework/src/test/java/org/tron/core/services/http/AccountPermissionUpdateServletTest.java deleted file mode 100644 index 313a0a12a60..00000000000 --- a/framework/src/test/java/org/tron/core/services/http/AccountPermissionUpdateServletTest.java +++ /dev/null @@ -1,88 +0,0 @@ -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 AccountPermissionUpdateServletTest extends BaseTest { - - static { - Args.setParam( - new String[]{ - "--output-directory", dbPath(), - }, Constant.TEST_CONF - ); - } - - @Resource - private AccountPermissionUpdateServlet accountPermissionUpdateServlet; - - private String getParam() { - return "{" - + " \"owner_address\":\"TRGhNNfnmgLegT4zHNjEqDSADjgmnHvubJ\"," - + " \"owner\":{" - + " \"type\":0," - + " \"permission_name\":\"owner\"," - + " \"threshold\":1," - + " \"keys\":[" - + " {" - + " \"address\":\"TRGhNNfnmgLegT4zHNjEqDSADjgmnHvubJ\"," - + " \"weight\":1" - + " }" - + " ]" - + " }," - + " \"witness\":{" - + " \"type\":1," - + " \"permission_name\":\"witness\"," - + " \"threshold\":1," - + " \"keys\":[" - + " {" - + " \"address\":\"TRGhNNfnmgLegT4zHNjEqDSADjgmnHvubJ\"," - + " \"weight\":1" - + " }" - + " ]" - + " }," - + " \"actives\":[" - + " {" - + " \"type\":2," - + " \"permission_name\":\"active12323\"," - + " \"threshold\":2," - + " \"operations\":" - + "\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," - + " \"keys\":[" - + " {" - + " \"address\":\"TNhXo1GbRNCuorvYu5JFWN3m2NYr9QQpVR\"," - + " \"weight\":1" - + " }," - + " {" - + " \"address\":\"TKwhcDup8L2PH5r6hxp5CQvQzZqJLmKvZP\"," - + " \"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(); - - accountPermissionUpdateServlet.doPost(request, response); - Assert.assertEquals(200, response.getStatus()); - } -} 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 index 27bc2a6eb34..a3a051ec6c9 100644 --- a/framework/src/test/java/org/tron/core/services/http/ClearABIServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/ClearABIServletTest.java @@ -1,18 +1,28 @@ 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 { @@ -27,11 +37,39 @@ public class ClearABIServletTest extends BaseTest { @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 testClear() { - String jsonParam = "{\n" - + " \"owner_address\": \"41a7d8a35b260395c14aa456297662092ba3b76fc0\",\n" - + " \"contract_address\": \"417bcb781f4743afaacf9f9528f3ea903b3782339f\"\n" + 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"); @@ -40,6 +78,15 @@ public void testClear() { 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 index 70a319e6040..bbc00ce81f0 100644 --- a/framework/src/test/java/org/tron/core/services/http/CreateAccountServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/CreateAccountServletTest.java @@ -1,18 +1,27 @@ 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 { @@ -28,11 +37,23 @@ public class CreateAccountServletTest extends BaseTest { @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\": \"41d1e7a6bc354106cb410e65ff8b181c600ff14292\"," - + "\"account_address\": \"41e552f6487585c2b58bc2c9bb4492bc1f17132cd0\"" + + "\"owner_address\": \"A099357684BC659F5166046B56C95A0E99F1265CD1\"," + + "\"account_address\": \"A0B4750E2CD76E19DCA331BF5D089B71C3C2798541\"" + "}"; MockHttpServletRequest request = createRequest(HttpPost.METHOD_NAME); request.setContentType("application/json"); @@ -42,5 +63,13 @@ public void testCreate() { 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 index d9f9ccc412c..4c70eb9252c 100644 --- a/framework/src/test/java/org/tron/core/services/http/CreateAssetIssueServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/CreateAssetIssueServletTest.java @@ -1,18 +1,27 @@ 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 { @@ -24,14 +33,26 @@ public class CreateAssetIssueServletTest extends BaseTest { ); } - @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\": \"41e552f6487585c2b58bc2c9bb4492bc1f17132cd0\"," + + " \"owner_address\": \"A099357684BC659F5166046B56C95A0E99F1265CD1\"," + " \"name\": \"0x6173736574497373756531353330383934333132313538\"," + " \"abbr\": \"0x6162627231353330383934333132313538\"," + " \"total_supply\": 4321," @@ -55,6 +76,14 @@ public void testCreate() { 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/GetTransactionInfoByBlockNumServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetTransactionInfoByBlockNumServletTest.java index 5dde8b4abce..0a1a2e4ac5a 100644 --- a/framework/src/test/java/org/tron/core/services/http/GetTransactionInfoByBlockNumServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/GetTransactionInfoByBlockNumServletTest.java @@ -3,20 +3,33 @@ 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( @@ -26,6 +39,22 @@ public class GetTransactionInfoByBlockNumServletTest extends BaseTest { ); } + @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}"; @@ -36,5 +65,15 @@ public void testGetTransactionInfoByBlockNum() { 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 index f2ff962c5a6..900c41c7df8 100644 --- a/framework/src/test/java/org/tron/core/services/http/GetTransactionInfoByIdServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/GetTransactionInfoByIdServletTest.java @@ -3,20 +3,48 @@ 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( @@ -26,11 +54,59 @@ public class GetTransactionInfoByIdServletTest extends BaseTest { ); } + @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\" : " - + "\"309b6fa3d01353e46f57dd8a8f276" - + "11f98e392b50d035cef213f2c55225a8bd2\"}"; + + "\"" + ByteArray.toHexString(KEY_1) + "\"}"; MockHttpServletRequest request = createRequest(HttpPost.METHOD_NAME); request.setContentType("application/json"); request.setContent(jsonParam.getBytes(UTF_8)); @@ -38,5 +114,13 @@ public void testGetInfoById() { 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()); + } } } From ce04da413e3429a02e7cbc3e1d85605b800daa9f Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Thu, 18 Jan 2024 16:06:58 +0800 Subject: [PATCH 0959/1197] feat(proposal): prevent re-submission after `ALLOW_OLD_REWARD_OPT` is approved (#5683) --- .../org/tron/core/utils/ProposalUtil.java | 4 ++ .../core/actuator/utils/ProposalUtilTest.java | 69 ++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index cf013266bd0..b38c7135341 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -733,6 +733,10 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, throw new ContractValidateException( "Bad chain parameter id [ALLOW_OLD_REWARD_OPT]"); } + if (dynamicPropertiesStore.allowOldRewardOpt()) { + throw new ContractValidateException( + "[ALLOW_OLD_REWARD_OPT] has been valid, no need to propose again"); + } if (value != 1) { throw new ContractValidateException( "This value[ALLOW_OLD_REWARD_OPT] is only allowed to be 1"); diff --git a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java index 6f4df3cba8f..8866540a028 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; import org.junit.BeforeClass; @@ -12,6 +13,7 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.ForkController; import org.tron.core.Constant; +import org.tron.core.capsule.BytesCapsule; import org.tron.core.config.Parameter; import org.tron.core.config.Parameter.ForkBlockVersionEnum; import org.tron.core.config.args.Args; @@ -27,6 +29,11 @@ public class ProposalUtilTest extends BaseTest { private static final String LONG_VALUE_ERROR = "Bad chain parameter value, valid range is [0," + LONG_VALUE + "]"; + @Resource + private DynamicPropertiesStore dynamicPropertiesStore; + + ForkController forkUtils = ForkController.instance(); + /** * Init . */ @@ -60,8 +67,6 @@ public void validProposalTypeCheck() throws ContractValidateException { @Test public void validateCheck() { - DynamicPropertiesStore dynamicPropertiesStore = null; - ForkController forkUtils = ForkController.instance(); long invalidValue = -1; try { @@ -328,6 +333,66 @@ public void validateCheck() { e.getMessage()); } + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_OLD_REWARD_OPT.getCode(), 2); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "Bad chain parameter id [ALLOW_OLD_REWARD_OPT]", + e.getMessage()); + } + hardForkTime = + ((ForkBlockVersionEnum.VERSION_4_7_4.getHardForkTime() - 1) / maintenanceTimeInterval + 1) + * maintenanceTimeInterval; + forkUtils.getManager().getDynamicPropertiesStore() + .saveLatestBlockHeaderTimestamp(hardForkTime + 1); + forkUtils.getManager().getDynamicPropertiesStore() + .statsByVersion(ForkBlockVersionEnum.VERSION_4_7_4.getValue(), stats); + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_OLD_REWARD_OPT.getCode(), 2); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "This value[ALLOW_OLD_REWARD_OPT] is only allowed to be 1", + e.getMessage()); + } + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_OLD_REWARD_OPT.getCode(), 1); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "[ALLOW_NEW_REWARD] proposal must be approved " + + "before [ALLOW_OLD_REWARD_OPT] can be proposed", + e.getMessage()); + } + dynamicPropertiesStore.saveCurrentCycleNumber(0); + dynamicPropertiesStore.saveNewRewardAlgorithmEffectiveCycle(); + dynamicPropertiesStore.saveAllowNewReward(1); + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_OLD_REWARD_OPT.getCode(), 1); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "no need old reward opt, ALLOW_NEW_REWARD from start cycle 1", + e.getMessage()); + } + dynamicPropertiesStore.put("NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE".getBytes(), + new BytesCapsule(ByteArray.fromLong(4000))); + dynamicPropertiesStore.saveAllowOldRewardOpt(1); + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_OLD_REWARD_OPT.getCode(), 1); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "[ALLOW_OLD_REWARD_OPT] has been valid, no need to propose again", + e.getMessage()); + } + forkUtils.getManager().getDynamicPropertiesStore() .statsByVersion(ForkBlockVersionEnum.ENERGY_LIMIT.getValue(), stats); forkUtils.reset(); From f02d6bfcd2adb64cf94c9d3b6215bdc7864c60f4 Mon Sep 17 00:00:00 2001 From: Kayle Date: Thu, 18 Jan 2024 21:05:51 +0800 Subject: [PATCH 0960/1197] test(case): remove useless code (#5679) --- .../java/org/tron/core/db/ManagerTest.java | 48 ++++++++++++++++--- .../tron/core/db/TransactionStoreTest.java | 2 +- .../tron/core/zksnark/NoteEncDecryTest.java | 2 - .../core/zksnark/ShieldedReceiveTest.java | 5 +- .../src/test/resources/config-localtest.conf | 10 ---- 5 files changed, 45 insertions(+), 22 deletions(-) diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index bd79f7d9776..053647cc25a 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -580,14 +580,24 @@ public void pushSwitchFork() TaposException, ReceiptCheckErrException, TooBigTransactionException, AccountResourceInsufficientException, EventBloomException { - String key = "f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62"; - String key2 = "c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4"; + String key = PublicMethod.getRandomPrivateKey(); + String key2 = PublicMethod.getRandomPrivateKey(); byte[] privateKey = ByteArray.fromHexString(key); final ECKey ecKey = ECKey.fromPrivate(privateKey); byte[] address = ecKey.getAddress(); + + ByteString addressByte = ByteString.copyFrom(address); + AccountCapsule accountCapsule = + new AccountCapsule(Protocol.Account.newBuilder() + .setAddress(addressByte).build()); + chainManager.getAccountStore() + .put(addressByte.toByteArray(), accountCapsule); + WitnessCapsule sr1 = new WitnessCapsule( ByteString.copyFrom(address), "www.tron.net/first"); sr1.setVoteCount(1000000000L); + + byte[] privateKey2 = ByteArray.fromHexString(key2); final ECKey ecKey2 = ECKey.fromPrivate(privateKey2); byte[] address2 = ecKey2.getAddress(); @@ -703,13 +713,23 @@ public void fork() Args.setParam(new String[]{"--witness"}, Constant.TEST_CONF); long size = chainManager.getBlockStore().size(); // System.out.print("block store size:" + size + "\n"); - String key = "f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62"; + String key = PublicMethod.getRandomPrivateKey(); byte[] privateKey = ByteArray.fromHexString(key); final ECKey ecKey = ECKey.fromPrivate(privateKey); byte[] address = ecKey.getAddress(); + + ByteString addressByte = ByteString.copyFrom(address); + AccountCapsule accountCapsule = + new AccountCapsule(Protocol.Account.newBuilder() + .setAddress(addressByte).build()); + chainManager.getAccountStore() + .put(addressByte.toByteArray(), accountCapsule); + + WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address)); chainManager.getWitnessScheduleStore().saveActiveWitnesses(new ArrayList<>()); chainManager.addWitness(ByteString.copyFrom(address)); + chainManager.getWitnessStore().put(address, witnessCapsule); Block block = getSignedBlock(witnessCapsule.getAddress(), 1533529947843L, privateKey); @@ -822,14 +842,20 @@ public void doNotSwitch() Args.setParam(new String[]{"--witness"}, Constant.TEST_CONF); long size = chainManager.getBlockStore().size(); System.out.print("block store size:" + size + "\n"); - String key = "f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62"; + String key = PublicMethod.getRandomPrivateKey(); byte[] privateKey = ByteArray.fromHexString(key); final ECKey ecKey = ECKey.fromPrivate(privateKey); byte[] address = ecKey.getAddress(); - + ByteString addressByte = ByteString.copyFrom(address); + AccountCapsule accountCapsule = + new AccountCapsule(Protocol.Account.newBuilder() + .setAddress(addressByte).build()); + chainManager.getAccountStore() + .put(addressByte.toByteArray(), accountCapsule); WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address)); chainManager.getWitnessScheduleStore().saveActiveWitnesses(new ArrayList<>()); chainManager.addWitness(ByteString.copyFrom(address)); + chainManager.getWitnessStore().put(address, witnessCapsule); Block block = getSignedBlock(witnessCapsule.getAddress(), 1533529947843L, privateKey); dbManager.pushBlock(new BlockCapsule(block)); @@ -928,14 +954,22 @@ public void switchBack() Args.setParam(new String[]{"--witness"}, Constant.TEST_CONF); long size = chainManager.getBlockStore().size(); System.out.print("block store size:" + size + "\n"); - String key = "f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62"; + String key = PublicMethod.getRandomPrivateKey();; byte[] privateKey = ByteArray.fromHexString(key); final ECKey ecKey = ECKey.fromPrivate(privateKey); byte[] address = ecKey.getAddress(); + + ByteString addressByte = ByteString.copyFrom(address); + AccountCapsule accountCapsule = + new AccountCapsule(Protocol.Account.newBuilder() + .setAddress(addressByte).build()); + chainManager.getAccountStore() + .put(addressByte.toByteArray(), accountCapsule); + WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address)); chainManager.getWitnessScheduleStore().saveActiveWitnesses(new ArrayList<>()); chainManager.addWitness(ByteString.copyFrom(address)); - + chainManager.getWitnessStore().put(address, witnessCapsule); Block block = getSignedBlock(witnessCapsule.getAddress(), 1533529947843L, privateKey); dbManager.pushBlock(new BlockCapsule(block)); diff --git a/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java b/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java index 1edc4aca756..deeb135373f 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java @@ -112,7 +112,7 @@ private VoteWitnessContract getVoteWitnessContract(String address, String votead public void getTransactionTest() throws BadItemException, ItemNotFoundException { final BlockStore blockStore = chainBaseManager.getBlockStore(); final TransactionStore trxStore = chainBaseManager.getTransactionStore(); - String key = "f31db24bfbd1a2ef19beddca0a0fa37632eded9ac666a05d3bd925f01dde1f62"; + String key = PublicMethod.getRandomPrivateKey();; BlockCapsule blockCapsule = new BlockCapsule( diff --git a/framework/src/test/java/org/tron/core/zksnark/NoteEncDecryTest.java b/framework/src/test/java/org/tron/core/zksnark/NoteEncDecryTest.java index e59060540e9..3c3fb14b2b1 100644 --- a/framework/src/test/java/org/tron/core/zksnark/NoteEncDecryTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/NoteEncDecryTest.java @@ -23,7 +23,6 @@ public class NoteEncDecryTest extends BaseTest { private static final String FROM_ADDRESS; - private static final String ADDRESS_ONE_PRIVATE_KEY; private static final long OWNER_BALANCE = 100_000_000; private static final long FROM_AMOUNT = 110_000_000; private static final long tokenId = 1; @@ -42,7 +41,6 @@ public class NoteEncDecryTest extends BaseTest { static { Args.setParam(new String[]{"--output-directory", dbPath()}, "config-localtest.conf"); FROM_ADDRESS = Wallet.getAddressPreFixString() + "a7d8a35b260395c14aa456297662092ba3b76fc0"; - ADDRESS_ONE_PRIVATE_KEY = "7f7f701e94d4f1dd60ee5205e7ea8ee31121427210417b608a6b2e96433549a7"; } /** diff --git a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java index c963a92bb9d..f3ad1f36cd1 100755 --- a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java @@ -25,6 +25,7 @@ import org.tron.common.crypto.ECKey; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.PublicMethod; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.client.utils.TransactionUtils; import org.tron.common.zksnark.IncrementalMerkleTreeContainer; @@ -124,8 +125,8 @@ public class ShieldedReceiveTest extends BaseTest { static { Args.setParam(new String[]{"--output-directory", dbPath()}, "config-localtest.conf"); - FROM_ADDRESS = Wallet.getAddressPreFixString() + "a7d8a35b260395c14aa456297662092ba3b76fc0"; - ADDRESS_ONE_PRIVATE_KEY = "7f7f701e94d4f1dd60ee5205e7ea8ee31121427210417b608a6b2e96433549a7"; + ADDRESS_ONE_PRIVATE_KEY = PublicMethod.getRandomPrivateKey(); + FROM_ADDRESS = PublicMethod.getHexAddressByPrivateKey(ADDRESS_ONE_PRIVATE_KEY);; } /** diff --git a/framework/src/test/resources/config-localtest.conf b/framework/src/test/resources/config-localtest.conf index ff0fe8bf9d9..fc35ca9b66a 100644 --- a/framework/src/test/resources/config-localtest.conf +++ b/framework/src/test/resources/config-localtest.conf @@ -188,8 +188,6 @@ genesis.block = { accountType = "AssetIssue" address = "TJCnKsPa7y5okkXvQAidZBzqx3QyQ6sxMW" balance = "25000000000000000" - #priKey = D95611A9AF2A2A45359106222ED1AFED48853D9A44DEFF8DC7913F5CBA727366 - #password = 2VYRqa8qKkU1kQYiLtGv7UiFPZpE3v+Nx5E/XLpyc2Y= }, # the account of payment @@ -198,8 +196,6 @@ genesis.block = { accountType = "AssetIssue" address = "TGehVcNhud84JDCGrNHKVz9jEAVKUpbuiv" balance = "10000000000000000" - #priKey = cba92a516ea09f620a16ff7ee95ce0df1d56550a8babe9964981a7144c8a784a - #password = y6kqUW6gn2IKFv9+6Vzg3x1WVQqLq+mWSYGnFEyKeEo= }, # the account of coin burn @@ -208,8 +204,6 @@ genesis.block = { accountType = "AssetIssue" address = "THKrowiEfCe8evdbaBzDDvQjM5DGeB3s3F" balance = "-9223372036854775808" - #priKey = 8E812436A0E3323166E1F0E8BA79E19E217B2C4A53C970D4CCA0CFB1078979DF - #password = joEkNqDjMjFm4fDounnhniF7LEpTyXDUzKDPsQeJed8= } ] @@ -218,27 +212,23 @@ genesis.block = { address: TN3zfjYUmMFK3ZsHSsrdJoNRtGkQmZLBLz url = "http://test.org/", voteCount = 106 - #priKey = f4df789d3210ac881cb900464dd30409453044d2777060a0c391cbdf4c6a4f57 6666 }, // { // address: TPrLL5ckUdMaPNgJYmGv23qtYjBE34aBf8 // url = "http://mercury.org/", // voteCount = 105 - // #priKey = f5583fd20e13073900a513f333ed13db8c9e83e7e3cf37e74adacef96c5afeaa 7777 // }, // { // address: TEZBh76rouEQpB2zqYVopbRXGx7RfyWorT // #address: 27TfVERREG3FeWMHEAQ95tWHG4sb3ANn3Qe // url = "http://venus.org/", // voteCount = 104 - // #priKey = 9f5c5e48bf87cf92017313082e8cf0f58ccfce423097f0fcebf801695fc99bd4 8888 // }, // { // address: TN27wbfCLEN1gP2PZAxHgU3QZrntsLyxdj // #address: 27b8RUuyZnNPFNZGct2bZkNu9MnGWNAdH3Z // url = "http://earth.org/", // voteCount = 103 - // #priKey = 6781f44d9a2083b14fad1702b8e9ba82749162b795e2fc3f136192fc63f80de2 9999 // }, ] From 24da38479eb35577f9285121c1de1e23af941d79 Mon Sep 17 00:00:00 2001 From: liukai Date: Mon, 22 Jan 2024 11:33:01 +0800 Subject: [PATCH 0961/1197] feat(version): update version --- framework/src/main/java/org/tron/program/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index a01eb714297..6f26752524c 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -4,7 +4,7 @@ public class Version { public static final String VERSION_NAME = "GreatVoyage-v4.7.3-5-g788136ebe"; public static final String VERSION_CODE = "18180"; - private static final String VERSION = "4.7.3.1"; + private static final String VERSION = "4.7.4"; public static String getVersion() { return VERSION; From b5c6cbd3f756450f59da51467c52aef5058c2d47 Mon Sep 17 00:00:00 2001 From: lurais <107600021+lurais@users.noreply.github.com> Date: Mon, 22 Jan 2024 15:55:45 +0800 Subject: [PATCH 0962/1197] feat(log):optimize fork block version log (#5687) Co-authored-by: morgan.peng --- .../src/main/java/org/tron/common/utils/ForkController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainbase/src/main/java/org/tron/common/utils/ForkController.java b/chainbase/src/main/java/org/tron/common/utils/ForkController.java index c3db883a011..7cbac28e781 100644 --- a/chainbase/src/main/java/org/tron/common/utils/ForkController.java +++ b/chainbase/src/main/java/org/tron/common/utils/ForkController.java @@ -78,7 +78,7 @@ private boolean passOld(int version) { private boolean passNew(int version) { ForkBlockVersionEnum versionEnum = ForkBlockVersionEnum.getForkBlockVersionEnum(version); if (versionEnum == null) { - logger.error("Not exist block version: {}.", version); + logger.warn("Not exist block version: {}.", version); return false; } long latestBlockTime = manager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); From 245ddfb0167aad70fae35eb13e16843ec2ebf392 Mon Sep 17 00:00:00 2001 From: running-tomato <31307926+tomatoishealthy@users.noreply.github.com> Date: Mon, 22 Jan 2024 16:22:07 +0800 Subject: [PATCH 0963/1197] fix(dependency): mock jar version upgrade (#5689) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e3611a27a73..a56be97afa1 100644 --- a/build.gradle +++ b/build.gradle @@ -55,7 +55,7 @@ subprojects { testAnnotationProcessor 'org.projectlombok:lombok:1.18.12' testImplementation group: 'junit', name: 'junit', version: '4.13.2' - testImplementation "org.mockito:mockito-core:2.1.0" + testImplementation "org.mockito:mockito-core:2.13.0" } task sourcesJar(type: Jar, dependsOn: classes) { From f0a46ff1fbb0160d93fdd1bc512af3f01bed9995 Mon Sep 17 00:00:00 2001 From: Brown Jiang <317787106@qq.com> Date: Tue, 23 Jan 2024 10:04:34 +0800 Subject: [PATCH 0964/1197] fix(api): fix the bug of determine if triggerConstantContract succeeds (#5688) * fix(api):fix the bug of determine if get scale factor succeed * fix(api):fix bug of isShieldedTRC20NoteSpent --- .../src/main/java/org/tron/core/Wallet.java | 14 +++--- .../tron/core/capsule/utils/RLPListTest.java | 43 +++++++++++++++++++ 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index cd2e26aa6f7..6e5c17417b7 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -3862,11 +3862,12 @@ private boolean isShieldedTRC20NoteSpent(GrpcAPI.Note note, long pos, byte[] ak, TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); TransactionExtention trxExt; + Transaction trx; try { TransactionCapsule trxCap = createTransactionCapsule(trigger, ContractType.TriggerSmartContract); - Transaction trx = triggerConstantContract(trigger, trxCap, trxExtBuilder, retBuilder); + trx = triggerConstantContract(trigger, trxCap, trxExtBuilder, retBuilder); retBuilder.setResult(true).setCode(response_code.SUCCESS); trxExtBuilder.setTransaction(trx); @@ -3889,10 +3890,10 @@ private boolean isShieldedTRC20NoteSpent(GrpcAPI.Note note, long pos, byte[] ak, logger.warn("unknown exception caught: " + e.getMessage(), e); } finally { trxExt = trxExtBuilder.build(); + trx = trxExt.getTransaction(); } - String code = trxExt.getResult().getCode().toString(); - if ("SUCCESS".equals(code)) { + if (code.SUCESS == trx.getRet(0).getRet()) { List list = trxExt.getConstantResultList(); byte[] listBytes = new byte[0]; for (ByteString bs : list) { @@ -4126,11 +4127,12 @@ public byte[] getShieldedContractScalingFactor(byte[] contractAddress) TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); TransactionExtention trxExt; + Transaction trx; try { TransactionCapsule trxCap = createTransactionCapsule(trigger, ContractType.TriggerSmartContract); - Transaction trx = triggerConstantContract(trigger, trxCap, trxExtBuilder, retBuilder); + trx = triggerConstantContract(trigger, trxCap, trxExtBuilder, retBuilder); retBuilder.setResult(true).setCode(response_code.SUCCESS); trxExtBuilder.setTransaction(trx); @@ -4153,10 +4155,10 @@ public byte[] getShieldedContractScalingFactor(byte[] contractAddress) logger.warn("Unknown exception caught: " + e.getMessage(), e); } finally { trxExt = trxExtBuilder.build(); + trx = trxExt.getTransaction(); } - String code = trxExt.getResult().getCode().toString(); - if ("SUCCESS".equals(code)) { + if (code.SUCESS == trx.getRet(0).getRet()) { List list = trxExt.getConstantResultList(); byte[] listBytes = new byte[0]; for (ByteString bs : list) { diff --git a/framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java b/framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java index 160ecd8f6dd..cba4a7d8040 100644 --- a/framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java +++ b/framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java @@ -2,8 +2,12 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.math.BigInteger; +import java.util.Random; +import org.bouncycastle.util.BigIntegers; import org.junit.Assert; import org.junit.Test; +import org.tron.common.utils.Value; public class RLPListTest { @@ -34,5 +38,44 @@ public void testToBytes() byte[] aBytes = new byte[10]; byte[] bBytes = (byte[]) method.invoke(RLP.class, aBytes); Assert.assertArrayEquals(aBytes, bBytes); + + int i = new Random().nextInt(); + byte[] cBytes = BigIntegers.asUnsignedByteArray(BigInteger.valueOf(i)); + byte[] dBytes = (byte[]) method.invoke(RLP.class, i); + Assert.assertArrayEquals(cBytes, dBytes); + + long j = new Random().nextInt(); + byte[] eBytes = BigIntegers.asUnsignedByteArray(BigInteger.valueOf(j)); + byte[] fBytes = (byte[]) method.invoke(RLP.class, j); + Assert.assertArrayEquals(eBytes, fBytes); + + String test = "testA"; + byte[] gBytes = test.getBytes(); + byte[] hBytes = (byte[]) method.invoke(RLP.class, test); + Assert.assertArrayEquals(gBytes, hBytes); + + BigInteger bigInteger = BigInteger.valueOf(100); + byte[] iBytes = BigIntegers.asUnsignedByteArray(bigInteger); + byte[] jBytes = (byte[]) method.invoke(RLP.class, bigInteger); + Assert.assertArrayEquals(iBytes, jBytes); + + Value v = new Value(new byte[0]); + byte[] kBytes = v.asBytes(); + byte[] lBytes = (byte[]) method.invoke(RLP.class, v); + Assert.assertArrayEquals(kBytes, lBytes); + + char c = 'a'; + try { + method.invoke(RLP.class, c); + Assert.fail(); + } catch (Exception e) { + Assert.assertTrue(true); + } + } + + @Test + public void testEncode() { + byte[] aBytes = RLP.encode(new byte[1]); + Assert.assertEquals(1, aBytes.length); } } From 8960a6bf6c49ad535b8a922cfac0ef1ca4cd5a08 Mon Sep 17 00:00:00 2001 From: Brown Jiang <317787106@qq.com> Date: Tue, 23 Jan 2024 16:56:48 +0800 Subject: [PATCH 0965/1197] feat(version):update libp2p version to 2.2.0 (#5692) --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index ba1c431e74c..2e5413269d9 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -46,7 +46,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v2.2.1',{ + compile group: 'io.github.tronprotocol', name: 'libp2p', version: '2.2.0',{ exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' From 931de4438f73f73a62baf650a369432282c9a2e9 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 24 Jan 2024 14:26:09 +0800 Subject: [PATCH 0966/1197] feat(dependency):update libp2p version to test-v2.2.2 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 2e5413269d9..8fbd2954f47 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -46,7 +46,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'io.github.tronprotocol', name: 'libp2p', version: '2.2.0',{ + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v2.2.2',{ exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' From 9911b054a5a22960d32e13f68144ff7a71b72a1e Mon Sep 17 00:00:00 2001 From: wubin01 Date: Thu, 25 Jan 2024 15:52:14 +0800 Subject: [PATCH 0967/1197] feat(dependency): update libp2p version to 2.2.1 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 8fbd2954f47..6c1545e5d13 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -46,7 +46,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v2.2.2',{ + compile group: 'io.github.tronprotocol', name: 'libp2p', version: '2.2.1',{ exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' From baddd4f90387be76253fffb39b6be294b902de0e Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Thu, 25 Jan 2024 17:55:19 +0800 Subject: [PATCH 0968/1197] feat(log): remove unused log for getnodeinfo api (#5697) --- framework/src/main/java/org/tron/core/db/Manager.java | 4 ++++ .../src/main/java/org/tron/core/services/NodeInfoService.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 445c48fdd94..63bbef9ff7f 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1914,6 +1914,10 @@ public long getSyncBeginNumber() { chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() - revokingStore.size(), chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum()); + return this.fetchSyncBeginNumber(); + } + + public long fetchSyncBeginNumber() { return chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() - revokingStore.size(); } diff --git a/framework/src/main/java/org/tron/core/services/NodeInfoService.java b/framework/src/main/java/org/tron/core/services/NodeInfoService.java index ddf72c64410..b55ce96748e 100644 --- a/framework/src/main/java/org/tron/core/services/NodeInfoService.java +++ b/framework/src/main/java/org/tron/core/services/NodeInfoService.java @@ -195,7 +195,7 @@ private void setConfigNodeInfo(NodeInfo nodeInfo) { } protected void setBlockInfo(NodeInfo nodeInfo) { - nodeInfo.setBeginSyncNum(dbManager.getSyncBeginNumber()); + nodeInfo.setBeginSyncNum(dbManager.fetchSyncBeginNumber()); nodeInfo.setBlock(chainBaseManager.getHeadBlockId().getString()); nodeInfo.setSolidityBlock(chainBaseManager.getSolidBlockId().getString()); } From cbf24173f47cc3f58df6b4223370f4601cb0a574 Mon Sep 17 00:00:00 2001 From: Brown Jiang <317787106@qq.com> Date: Fri, 26 Jan 2024 10:57:19 +0800 Subject: [PATCH 0969/1197] fix the bug of concurrent usage of toString in TransactionCapsule (#5696) --- .../tron/core/capsule/TransactionCapsule.java | 3 +-- .../actuator/utils/TransactionUtilTest.java | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java index 9598fd99a6b..5d5a5d5b462 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -102,7 +102,6 @@ public class TransactionCapsule implements ProtoCapsule { @Setter private TransactionTrace trxTrace; - private StringBuilder toStringBuff = new StringBuilder(); @Getter @Setter private long time; @@ -738,7 +737,7 @@ public Transaction getInstance() { @Override public String toString() { - + StringBuilder toStringBuff = new StringBuilder(); toStringBuff.setLength(0); toStringBuff.append("TransactionCapsule \n[ "); diff --git a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java index 9d56876a4da..3346a1aead5 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java @@ -14,6 +14,7 @@ import com.google.protobuf.ByteString; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.List; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; @@ -431,4 +432,22 @@ public void estimateConsumeBandWidthSizeCorner() { long actual = TransactionUtil.estimateConsumeBandWidthSize(dps, balance); Assert.assertEquals(expected, actual); } + + @Test + public void testConcurrentToString() throws InterruptedException { + Transaction.Builder builder = Transaction.newBuilder(); + TransactionCapsule trx = new TransactionCapsule(builder.build()); + List threadList = new ArrayList<>(); + int n = 10; + for (int i = 0; i < n; i++) { + threadList.add(new Thread(() -> trx.toString())); + } + for (int i = 0; i < n; i++) { + threadList.get(i).start(); + } + for (int i = 0; i < n; i++) { + threadList.get(i).join(); + } + Assert.assertTrue(true); + } } From 976d6f7a328db07e8fb59d7dd4bf77d9c12561a1 Mon Sep 17 00:00:00 2001 From: allen <56535423+jwrct@users.noreply.github.com> Date: Fri, 26 Jan 2024 21:36:03 +0800 Subject: [PATCH 0970/1197] fix(pbft): fix concurrent access issue of srPbftMessage (#5703) * fix(pbft): fix the concurrent access issue of srPbftMessage --- .../main/java/org/tron/consensus/pbft/PbftMessageHandle.java | 4 ++-- framework/src/test/java/org/tron/core/pbft/PbftTest.java | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/consensus/src/main/java/org/tron/consensus/pbft/PbftMessageHandle.java b/consensus/src/main/java/org/tron/consensus/pbft/PbftMessageHandle.java index ea7b00802b2..523ffac4d61 100644 --- a/consensus/src/main/java/org/tron/consensus/pbft/PbftMessageHandle.java +++ b/consensus/src/main/java/org/tron/consensus/pbft/PbftMessageHandle.java @@ -262,7 +262,7 @@ public boolean isSyncing() { } //Cleanup related status - private void remove(String no) { + private synchronized void remove(String no) { String pre = String.valueOf(no) + "_"; preVotes.remove(no); pareVoteMap.keySet().removeIf(vp -> StringUtils.startsWith(vp, pre)); @@ -285,7 +285,7 @@ private void remove(String no) { //just try once if (srPbftMessage != null && StringUtils.equals(no, srPbftMessage.getNo())) { try { - Thread.sleep(100); + wait(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (Exception e) { diff --git a/framework/src/test/java/org/tron/core/pbft/PbftTest.java b/framework/src/test/java/org/tron/core/pbft/PbftTest.java index a5d74ad7a37..33a46516988 100644 --- a/framework/src/test/java/org/tron/core/pbft/PbftTest.java +++ b/framework/src/test/java/org/tron/core/pbft/PbftTest.java @@ -29,6 +29,7 @@ public void testPbftSrMessage() { ByteString.copyFrom(ByteArray.fromHexString("41df309fef25b311e7895562bd9e11aab2a58816d2"))); PbftMessage pbftSrMessage = PbftMessage .prePrepareSRLMsg(blockCapsule, srList, 1, miner); + PbftMessage.fullNodePrePrepareSRLMsg(blockCapsule, srList, 1); System.out.println(pbftSrMessage); } From 5acf3efb97afe8b2f82d2bc6643c47843e133a40 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Sat, 27 Jan 2024 21:02:14 +0800 Subject: [PATCH 0971/1197] feat(dependency): update libp2p version to test-v2.2.3 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 6c1545e5d13..489a2fa9d49 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -46,7 +46,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'io.github.tronprotocol', name: 'libp2p', version: '2.2.1',{ + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v2.2.3',{ exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' From a578e85fbfede47bf4a7fe011f2646fabf280e3c Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Mon, 29 Jan 2024 12:40:32 +0800 Subject: [PATCH 0972/1197] feat(api): adjust API services to start first at startup (#5711) --- .../java/org/tron/common/application/ApplicationImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java index 9133fddf434..3cb75cb1e24 100644 --- a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java +++ b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java @@ -54,13 +54,13 @@ public void initServices(CommonParameter parameter) { * start up the app. */ public void startup() { + this.initServices(Args.getInstance()); + this.startServices(); if ((!Args.getInstance().isSolidityNode()) && (!Args.getInstance().isP2pDisable())) { tronNetService.start(); } consensusService.start(); MetricsUtil.init(); - this.initServices(Args.getInstance()); - this.startServices(); } @Override From dcf1103d5ea195c80a0ded3b4f49856e9368b61d Mon Sep 17 00:00:00 2001 From: allen <56535423+jwrct@users.noreply.github.com> Date: Mon, 29 Jan 2024 14:04:32 +0800 Subject: [PATCH 0973/1197] Revert "feat(dependency): update libp2p version to test-v2.2.3" (#5712) --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 489a2fa9d49..6c1545e5d13 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -46,7 +46,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v2.2.3',{ + compile group: 'io.github.tronprotocol', name: 'libp2p', version: '2.2.1',{ exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' From 9d00aef081018584ca9fdb6c5c9e46b6c849eeca Mon Sep 17 00:00:00 2001 From: wubin01 Date: Wed, 21 Feb 2024 11:52:40 +0800 Subject: [PATCH 0974/1197] feat(net): use the correct clearing function --- .../main/java/org/tron/core/net/peer/PeerConnection.java | 6 +++--- .../java/org/tron/core/net/peer/PeerConnectionTest.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index 6743f00421d..4fac50b82c7 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -197,10 +197,10 @@ public void onConnect() { public void onDisconnect() { syncService.onDisconnect(this); advService.onDisconnect(this); - advInvReceive.cleanUp(); - advInvSpread.cleanUp(); + advInvReceive.invalidateAll(); + advInvSpread.invalidateAll(); advInvRequest.clear(); - syncBlockIdCache.cleanUp(); + syncBlockIdCache.invalidateAll(); syncBlockToFetch.clear(); syncBlockRequested.clear(); syncBlockInProcess.clear(); diff --git a/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java b/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java index c0d81ca2763..9db5230ed45 100644 --- a/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java +++ b/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java @@ -60,9 +60,9 @@ public void testOnDisconnect() { peerConnection.onDisconnect(); - //Assert.assertEquals(0, peerConnection.getAdvInvReceive().size()); - //Assert.assertEquals(0, peerConnection.getAdvInvSpread().size()); - //Assert.assertEquals(0, peerConnection.getSyncBlockIdCache().size()); + Assert.assertEquals(0, peerConnection.getAdvInvReceive().size()); + Assert.assertEquals(0, peerConnection.getAdvInvSpread().size()); + Assert.assertEquals(0, peerConnection.getSyncBlockIdCache().size()); Assert.assertEquals(0, peerConnection.getSyncBlockToFetch().size()); Assert.assertEquals(0, peerConnection.getSyncBlockRequested().size()); Assert.assertEquals(0, peerConnection.getSyncBlockInProcess().size()); From 09573b7c921de045a9ce8b54787fddb3505284ab Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 22 Feb 2024 17:27:17 +0800 Subject: [PATCH 0975/1197] resolve the coverage changes that backupserver may start in testcase or not --- .../tron/common/backup/BackupManagerTest.java | 88 +++++++++++++++---- 1 file changed, 70 insertions(+), 18 deletions(-) diff --git a/framework/src/test/java/org/tron/common/backup/BackupManagerTest.java b/framework/src/test/java/org/tron/common/backup/BackupManagerTest.java index 8a5ff4f4bc2..9ace8f5b601 100644 --- a/framework/src/test/java/org/tron/common/backup/BackupManagerTest.java +++ b/framework/src/test/java/org/tron/common/backup/BackupManagerTest.java @@ -4,41 +4,62 @@ import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ExecutorService; import java.util.concurrent.ScheduledExecutorService; +import org.junit.After; import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.tron.common.backup.BackupManager.BackupStatusEnum; import org.tron.common.backup.message.KeepAliveMessage; +import org.tron.common.backup.socket.BackupServer; import org.tron.common.backup.socket.UdpEvent; import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.PublicMethod; import org.tron.core.Constant; import org.tron.core.config.args.Args; public class BackupManagerTest { + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + private BackupManager manager; + private BackupServer backupServer; + + @Before + public void setUp() throws Exception { + Args.setParam(new String[] {"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + CommonParameter.getInstance().setBackupPort(PublicMethod.chooseRandomPort()); + manager = new BackupManager(); + backupServer = new BackupServer(manager); + } + + @After + public void tearDown() { + Args.clearParam(); + } + @Test public void test() throws Exception { - String[] a = new String[0]; - Args.setParam(a, Constant.TESTNET_CONF); - CommonParameter parameter = CommonParameter.getInstance(); - parameter.setBackupPriority(8); + CommonParameter.getInstance().setBackupPriority(8); List members = new ArrayList<>(); members.add("127.0.0.2"); - parameter.setBackupMembers(members); + CommonParameter.getInstance().setBackupMembers(members); - BackupManager manager = new BackupManager(); - - Field field = manager.getClass().getDeclaredField("localIp"); + Field field = manager.getClass().getDeclaredField("localIp"); field.setAccessible(true); field.set(manager, "127.0.0.1"); - Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.MASTER); + Assert.assertEquals(BackupManager.BackupStatusEnum.MASTER, manager.getStatus()); - field = manager.getClass().getDeclaredField("executorService"); + field = manager.getClass().getDeclaredField("executorService"); field.setAccessible(true); ScheduledExecutorService executorService = (ScheduledExecutorService) field.get(manager); manager.init(); executorService.shutdown(); - Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.INIT); + Assert.assertEquals(BackupManager.BackupStatusEnum.INIT, manager.getStatus()); /* ip not in the members */ manager.setStatus(BackupManager.BackupStatusEnum.INIT); @@ -46,45 +67,76 @@ public void test() throws Exception { InetSocketAddress address = new InetSocketAddress("127.0.0.3", 1000); UdpEvent event = new UdpEvent(message, address); manager.handleEvent(event); - Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.INIT); + Assert.assertEquals(BackupManager.BackupStatusEnum.INIT, manager.getStatus()); /* ip not the member */ address = new InetSocketAddress("127.0.0.3", 1000); message = new KeepAliveMessage(false, 6); event = new UdpEvent(message, address); manager.handleEvent(event); - Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.INIT); + Assert.assertEquals(BackupManager.BackupStatusEnum.INIT, manager.getStatus()); /* keepAliveMessage.getFlag() || peerPriority > priority */ address = new InetSocketAddress("127.0.0.2", 1000); message = new KeepAliveMessage(false, 6); event = new UdpEvent(message, address); manager.handleEvent(event); - Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.INIT); + Assert.assertEquals(BackupStatusEnum.SLAVER, manager.getStatus()); /* keepAliveMessage.getFlag() || peerPriority > priority */ message = new KeepAliveMessage(false, 10); event = new UdpEvent(message, address); manager.handleEvent(event); - Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.SLAVER); + Assert.assertEquals(BackupManager.BackupStatusEnum.SLAVER, manager.getStatus()); /* keepAliveMessage.getFlag() || peerPriority > priority */ manager.setStatus(BackupManager.BackupStatusEnum.INIT); message = new KeepAliveMessage(true, 6); event = new UdpEvent(message, address); manager.handleEvent(event); - Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.SLAVER); + Assert.assertEquals(BackupManager.BackupStatusEnum.SLAVER, manager.getStatus()); manager.setStatus(BackupManager.BackupStatusEnum.MASTER); message = new KeepAliveMessage(false, 10); event = new UdpEvent(message, address); manager.handleEvent(event); - Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.MASTER); + Assert.assertEquals(BackupManager.BackupStatusEnum.MASTER, manager.getStatus()); message = new KeepAliveMessage(true, 10); event = new UdpEvent(message, address); manager.handleEvent(event); - Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.SLAVER); + Assert.assertEquals(BackupManager.BackupStatusEnum.SLAVER, manager.getStatus()); + + } + + @Test + public void testSendKeepAliveMessage() throws Exception { + CommonParameter parameter = CommonParameter.getInstance(); + parameter.setBackupPriority(8); + List members = new ArrayList<>(); + members.add("127.0.0.2"); + parameter.setBackupMembers(members); + + Field field = manager.getClass().getDeclaredField("localIp"); + field.setAccessible(true); + field.set(manager, "127.0.0.1"); + + Assert.assertEquals(manager.getStatus(), BackupManager.BackupStatusEnum.MASTER); + backupServer.initServer(); + manager.init(); + + Thread.sleep(parameter.getKeepAliveInterval() + 1000);//test send KeepAliveMessage + + field = manager.getClass().getDeclaredField("executorService"); + field.setAccessible(true); + ScheduledExecutorService executorService = (ScheduledExecutorService) field.get(manager); + executorService.shutdown(); + + Field field2 = backupServer.getClass().getDeclaredField("executor"); + field2.setAccessible(true); + ExecutorService executorService2 = (ExecutorService) field2.get(backupServer); + executorService2.shutdown(); + Assert.assertEquals(BackupManager.BackupStatusEnum.INIT, manager.getStatus()); } } From e81a5aa6894cb990ffed5f05c9a384b23a2db759 Mon Sep 17 00:00:00 2001 From: adir852 <59093315+adir852@users.noreply.github.com> Date: Fri, 23 Feb 2024 09:37:39 +0200 Subject: [PATCH 0976/1197] docs(README):fix code typos (#5730) --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 89101bbc4d1..bdb0877d70b 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ TRON enables large-scale development and engagement. With over 2000 transactions # Building the source -Building java-tron requires `git` and 64-bit version of `Oracle JDK 1.8` to be installed, other JDK versions are not supported yet. Make sure you operate on `Linux` and `MacOS` operating systems. +Building java-tron requires `git` package and 64-bit version of `Oracle JDK 1.8` to be installed, other JDK versions are not supported yet. Make sure you operate on `Linux` and `MacOS` operating systems. Clone the repo and switch to the `master` branch @@ -73,7 +73,7 @@ $ cd java-tron $ git checkout -t origin/master ``` -then run the following command to build java-tron, the `FullNode.jar` file can be found in `java-tron/build/libs/` after build successful. +then run the following command to build java-tron, the `FullNode.jar` file can be found in `java-tron/build/libs/` after build successfully. ```bash $ ./gradlew clean build -x test @@ -120,7 +120,7 @@ $ nohup java -Xms9G -Xmx9G -XX:ReservedCodeCacheSize=256m \ Adding the `--witness` parameter to the startup command, full node will run as a super representative node. The super representative node supports all the functions of the full node and also supports block production. Before running, make sure you have a super representative account and get votes from others. Once the number of obtained votes ranks in the top 27, your super representative node will participate in block production. -Fill in the private key of super representative address into the `localwitness` list in the `main_net_config.conf`. Here is an example: +Fill in the private key of a super representative address into the `localwitness` list in the `main_net_config.conf`. Here is an example: ``` localwitness = [ From 96afa1587e62afad2e023928ec3aae60b7d718dc Mon Sep 17 00:00:00 2001 From: running-tomato <31307926+tomatoishealthy@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:58:17 +0800 Subject: [PATCH 0977/1197] fix(conf): fix the config location of the RPC reflection servive (#5739) --- framework/src/main/resources/config.conf | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 019b6302911..f0479a29cb2 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -243,6 +243,9 @@ node { # Transactions can only be broadcast if the number of effective connections is reached. minEffectiveConnection = 1 + + # The switch of the reflection service, effective for all gRPC services + # reflectionService = true } # number of solidity thread in the FullNode. @@ -285,8 +288,6 @@ node { # "getnowblock2" # ] - # The switch of the reflection service, effective for all gRPC services - # reflectionService = true } ## rate limiter config From fa46c4f023562e75b228d43b575f4feaf89b3c08 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Wed, 6 Mar 2024 11:58:59 +0800 Subject: [PATCH 0978/1197] feat(*): optimize old rewards withdrawal (#5742) * remove useNewRewardAlgorithmFromStart * code clear * exit when the calculation task gets an exception * tools: add `db root` to calculate the data root * make reward-vi root configurable * fix race-condition for Merkel root calculation * optimize proposal design --- .../org/tron/core/utils/ProposalUtil.java | 6 +- .../tron/core/capsule/utils/MerkleTree.java | 2 + .../core/db/common/iterator/DBIterator.java | 6 - .../db/common/iterator/RockStoreIterator.java | 2 - .../db/common/iterator/StoreIterator.java | 2 - .../tron/core/service/RewardViCalService.java | 59 +++-- .../core/store/DynamicPropertiesStore.java | 17 +- .../tron/common/prometheus/MetricKeys.java | 2 - .../common/prometheus/MetricsHistogram.java | 2 - .../org/tron/common/utils/MerkleRoot.java | 68 ++++++ .../org/tron/core/config/args/Storage.java | 19 ++ .../java/org/tron/core/config/args/Args.java | 15 +- framework/src/main/resources/config.conf | 7 + .../core/actuator/utils/ProposalUtilTest.java | 14 +- .../core/capsule/utils/MerkleTreeTest.java | 35 ++- .../org/tron/core/config/args/ArgsTest.java | 11 + .../tron/core/services/ComputeRewardTest.java | 34 +++ .../core/services/ProposalServiceTest.java | 9 - framework/src/test/resources/args-test.conf | 224 ++++++++++++++++++ .../resources/config-test-storagetest.conf | 2 + framework/src/test/resources/config-test.conf | 6 + .../src/main/java/org/tron/plugins/Db.java | 3 +- .../main/java/org/tron/plugins/DbRoot.java | 99 ++++++++ .../org/tron/plugins/utils/MerkleRoot.java | 68 ++++++ .../org/tron/plugins/utils/Sha256Hash.java | 10 +- .../tron/plugins/utils/db/DBInterface.java | 2 + .../org/tron/plugins/utils/db/DbTool.java | 18 +- .../tron/plugins/utils/db/LevelDBImpl.java | 7 +- .../tron/plugins/utils/db/RocksDBImpl.java | 7 +- .../java/org/tron/plugins/DbRootTest.java | 82 +++++++ 30 files changed, 738 insertions(+), 100 deletions(-) create mode 100644 common/src/main/java/org/tron/common/utils/MerkleRoot.java create mode 100644 framework/src/test/resources/args-test.conf create mode 100644 plugins/src/main/java/org/tron/plugins/DbRoot.java create mode 100644 plugins/src/main/java/org/tron/plugins/utils/MerkleRoot.java create mode 100644 plugins/src/test/java/org/tron/plugins/DbRootTest.java diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index b38c7135341..cfec5b09d96 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -743,13 +743,9 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } if (!dynamicPropertiesStore.useNewRewardAlgorithm()) { throw new ContractValidateException( - "[ALLOW_NEW_REWARD] proposal must be approved " + "[ALLOW_NEW_REWARD] or [ALLOW_TVM_VOTE] proposal must be approved " + "before [ALLOW_OLD_REWARD_OPT] can be proposed"); } - if (dynamicPropertiesStore.useNewRewardAlgorithmFromStart()) { - throw new ContractValidateException( - "no need old reward opt, ALLOW_NEW_REWARD from start cycle 1"); - } break; } default: diff --git a/chainbase/src/main/java/org/tron/core/capsule/utils/MerkleTree.java b/chainbase/src/main/java/org/tron/core/capsule/utils/MerkleTree.java index 47ac45c9fb8..94d22f4b474 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/utils/MerkleTree.java +++ b/chainbase/src/main/java/org/tron/core/capsule/utils/MerkleTree.java @@ -5,10 +5,12 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; import lombok.Getter; +import net.jcip.annotations.NotThreadSafe; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.Sha256Hash; @Getter +@NotThreadSafe public class MerkleTree { private static volatile MerkleTree instance; diff --git a/chainbase/src/main/java/org/tron/core/db/common/iterator/DBIterator.java b/chainbase/src/main/java/org/tron/core/db/common/iterator/DBIterator.java index ec8d7fd85be..afbacac35db 100755 --- a/chainbase/src/main/java/org/tron/core/db/common/iterator/DBIterator.java +++ b/chainbase/src/main/java/org/tron/core/db/common/iterator/DBIterator.java @@ -16,12 +16,6 @@ public interface DBIterator extends Iterator>, AutoCloseab void seekToLast(); - default UnmodifiableIterator> prefixQueryAfterThat - (byte[] key, byte[] afterThat) { - this.seek(afterThat == null ? key : afterThat); - return Iterators.filter(this, entry -> Bytes.indexOf(entry.getKey(), key) == 0); - } - /** * An iterator is either positioned at a key/value pair, or * not valid. This method returns true iff the iterator is valid. diff --git a/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java b/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java index 1438b9247b5..541f71348af 100644 --- a/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java +++ b/chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java @@ -108,14 +108,12 @@ public boolean valid() { @Override public byte[] getKey() { - checkState(); checkValid(); return dbIterator.key(); } @Override public byte[] getValue() { - checkState(); checkValid(); return dbIterator.value(); } diff --git a/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java b/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java index 4c635660ea6..d771716a7e8 100755 --- a/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java +++ b/chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java @@ -93,14 +93,12 @@ public boolean valid() { @Override public byte[] getKey() { - checkState(); checkValid(); return dbIterator.peekNext().getKey(); } @Override public byte[] getValue() { - checkState(); checkValid(); return dbIterator.peekNext().getValue(); } diff --git a/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java b/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java index 33e5233b551..e27990f0403 100644 --- a/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java +++ b/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java @@ -3,7 +3,6 @@ import static org.tron.core.store.DelegationStore.DECIMAL_OF_VI_REWARD; import static org.tron.core.store.DelegationStore.REMARK; -import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Streams; import com.google.common.primitives.Bytes; import com.google.protobuf.ByteString; @@ -18,7 +17,6 @@ import java.util.stream.Collectors; import java.util.stream.LongStream; import javax.annotation.PreDestroy; -import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; @@ -27,9 +25,9 @@ import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.MerkleRoot; import org.tron.common.utils.Pair; import org.tron.common.utils.Sha256Hash; -import org.tron.core.capsule.utils.MerkleTree; import org.tron.core.db.common.iterator.DBIterator; import org.tron.core.db2.common.DB; import org.tron.core.store.DelegationStore; @@ -55,10 +53,11 @@ public class RewardViCalService { private volatile long lastBlockNumber = -1; - @VisibleForTesting - @Setter - private Sha256Hash rewardViRoot = Sha256Hash.wrap( - ByteString.fromHex("9debcb9924055500aaae98cdee10501c5c39d4daa75800a996f4bdda73dbccd8")); + private static final String MAIN_NET_ROOT_HEX = + "9debcb9924055500aaae98cdee10501c5c39d4daa75800a996f4bdda73dbccd8"; + + private final Sha256Hash rewardViRoot = CommonParameter.getInstance().getStorage().getDbRoot( + "reward-vi", Sha256Hash.wrap(ByteString.fromHex(MAIN_NET_ROOT_HEX))); private final CountDownLatch lock = new CountDownLatch(1); @@ -99,25 +98,30 @@ private boolean isDone() { } private void maybeRun() { - if (enableNewRewardAlgorithm()) { - if (this.newRewardCalStartCycle > 1) { - if (isDone()) { - this.clearUp(true); - logger.info("rewardViCalService is already done"); - } else { - if (lastBlockNumber == Long.MAX_VALUE // start rewardViCalService immediately - || this.getLatestBlockHeaderNumber() > lastBlockNumber) { - // checkpoint is flushed to db, so we can start rewardViCalService - startRewardCal(); - clearUp(true); + try { + if (enableNewRewardAlgorithm()) { + if (this.newRewardCalStartCycle > 1) { + if (isDone()) { + this.clearUp(true); + logger.info("rewardViCalService is already done"); } else { - logger.info("startRewardCal will run after checkpoint is flushed to db"); + if (lastBlockNumber == Long.MAX_VALUE // start rewardViCalService immediately + || this.getLatestBlockHeaderNumber() > lastBlockNumber) { + // checkpoint is flushed to db, so we can start rewardViCalService + startRewardCal(); + clearUp(true); + } else { + logger.info("startRewardCal will run after checkpoint is flushed to db"); + } } + } else { + clearUp(false); + logger.info("rewardViCalService is no need to run"); } - } else { - clearUp(false); - logger.info("rewardViCalService is no need to run"); } + } catch (Exception e) { + logger.error(" Find fatal error, program will be exited soon.", e); + System.exit(1); } } @@ -137,7 +141,7 @@ private void destroy() { public long getNewRewardAlgorithmReward(long beginCycle, long endCycle, List> votes) { - if (!rewardViStore.has(IS_DONE_KEY)) { + if (!isDone()) { logger.warn("rewardViCalService is not done, wait for it"); try { lock.await(); @@ -174,10 +178,13 @@ private void calcMerkleRoot() { .map(this::getHash) .collect(Collectors.toCollection(ArrayList::new)); - Sha256Hash rewardViRootLocal = MerkleTree.getInstance().createTree(ids).getRoot().getHash(); + Sha256Hash rewardViRootLocal = MerkleRoot.root(ids); if (!Objects.equals(rewardViRoot, rewardViRootLocal)) { - logger.warn("merkle root mismatch, expect: {}, actual: {}", - rewardViRoot, rewardViRootLocal); + logger.warn("Merkle root mismatch, expect: {}, actual: {}." + + " If you are quite sure that there is no miscalculation (not on the main network)" + + ", please configure 'storage.merkleRoot.reward-vi = {}'" + + "(for a specific network such as Nile, etc.) in config.conf to fix the hints", + rewardViRoot, rewardViRootLocal, rewardViRootLocal); } logger.info("calcMerkleRoot: {}", rewardViRootLocal); } diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 23693f9bab6..bf788232640 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -2525,10 +2525,6 @@ public boolean useNewRewardAlgorithm() { return getNewRewardAlgorithmEffectiveCycle() != Long.MAX_VALUE; } - public boolean useNewRewardAlgorithmFromStart() { - return getNewRewardAlgorithmEffectiveCycle() == 1; - } - public void saveNewRewardAlgorithmEffectiveCycle() { if (getNewRewardAlgorithmEffectiveCycle() == Long.MAX_VALUE) { long currentCycle = getCurrentCycleNumber(); @@ -2839,19 +2835,8 @@ public boolean supportMaxDelegateLockPeriod() { getUnfreezeDelayDays() > 0; } - /** - * @require NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE != Long.MAX_VALUE - * @require NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE > 1 - */ public void saveAllowOldRewardOpt(long allowOldRewardOpt) { - if (useNewRewardAlgorithm()) { - if (useNewRewardAlgorithmFromStart()) { - throw new IllegalStateException("no need old reward opt, ALLOW_NEW_REWARD from start"); - } - this.put(ALLOW_OLD_REWARD_OPT, new BytesCapsule(ByteArray.fromLong(allowOldRewardOpt))); - } else { - throw new IllegalStateException("not support old reward opt, ALLOW_NEW_REWARD not set"); - } + this.put(ALLOW_OLD_REWARD_OPT, new BytesCapsule(ByteArray.fromLong(allowOldRewardOpt))); } public boolean allowOldRewardOpt() { diff --git a/common/src/main/java/org/tron/common/prometheus/MetricKeys.java b/common/src/main/java/org/tron/common/prometheus/MetricKeys.java index 7e85771000e..87ab6fae0a3 100644 --- a/common/src/main/java/org/tron/common/prometheus/MetricKeys.java +++ b/common/src/main/java/org/tron/common/prometheus/MetricKeys.java @@ -62,8 +62,6 @@ public static class Histogram { public static final String MESSAGE_PROCESS_LATENCY = "tron:message_process_latency_seconds"; public static final String BLOCK_FETCH_LATENCY = "tron:block_fetch_latency_seconds"; public static final String BLOCK_RECEIVE_DELAY = "tron:block_receive_delay_seconds"; - public static final String DO_REWARD_CAL_DELAY = "tron:do_reward_cal_seconds"; - private Histogram() { throw new IllegalStateException("Histogram"); diff --git a/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java b/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java index d776474c92e..556db10feb5 100644 --- a/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java +++ b/common/src/main/java/org/tron/common/prometheus/MetricsHistogram.java @@ -48,8 +48,6 @@ public class MetricsHistogram { init(MetricKeys.Histogram.BLOCK_FETCH_LATENCY, "fetch block latency."); init(MetricKeys.Histogram.BLOCK_RECEIVE_DELAY, "receive block delay time, receiveTime - blockTime."); - init(MetricKeys.Histogram.DO_REWARD_CAL_DELAY, - "do reward cal delay time.", "depth"); } private MetricsHistogram() { diff --git a/common/src/main/java/org/tron/common/utils/MerkleRoot.java b/common/src/main/java/org/tron/common/utils/MerkleRoot.java new file mode 100644 index 00000000000..ccd8905b6c5 --- /dev/null +++ b/common/src/main/java/org/tron/common/utils/MerkleRoot.java @@ -0,0 +1,68 @@ +package org.tron.common.utils; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import lombok.Getter; + +public class MerkleRoot { + + private MerkleRoot() { + + } + + public static Sha256Hash root(List hashList) { + List leaves = createLeaves(hashList); + while (leaves.size() > 1) { + leaves = createParentLeaves(leaves); + } + return leaves.isEmpty() ? Sha256Hash.ZERO_HASH : leaves.get(0).hash; + } + + private static List createParentLeaves(List leaves) { + int step = 2; + int len = leaves.size(); + return IntStream.iterate(0, i -> i + step) + .limit(len) + .filter(i -> i < len) + .mapToObj(i -> { + Leaf right = i + 1 < len ? leaves.get(i + 1) : null; + return createLeaf(leaves.get(i), right); + }).collect(Collectors.toList()); + } + + private static List createLeaves(List hashList) { + int step = 2; + int len = hashList.size(); + return IntStream.iterate(0, i -> i + step) + .limit(len) + .filter(i -> i < len) + .mapToObj(i -> { + Leaf right = i + 1 < len ? createLeaf(hashList.get(i + 1)) : null; + return createLeaf(createLeaf(hashList.get(i)), right); + }).collect(Collectors.toList()); + } + + private static Leaf createLeaf(Leaf left, Leaf right) { + Leaf leaf = new Leaf(); + leaf.hash = right == null ? left.hash : computeHash(left.hash, right.hash); + return leaf; + } + + private static Leaf createLeaf(Sha256Hash hash) { + Leaf leaf = new Leaf(); + leaf.hash = hash; + return leaf; + } + + private static Sha256Hash computeHash(Sha256Hash leftHash, Sha256Hash rightHash) { + return Sha256Hash.of(true, + leftHash.getByteString().concat(rightHash.getByteString()).toByteArray()); + } + + @Getter + private static class Leaf { + + private Sha256Hash hash; + } +} diff --git a/common/src/main/java/org/tron/core/config/args/Storage.java b/common/src/main/java/org/tron/core/config/args/Storage.java index 22dc239c167..9cf6eb6bab1 100644 --- a/common/src/main/java/org/tron/core/config/args/Storage.java +++ b/common/src/main/java/org/tron/core/config/args/Storage.java @@ -16,6 +16,7 @@ package org.tron.core.config.args; import com.google.common.collect.Maps; +import com.google.protobuf.ByteString; import com.typesafe.config.Config; import com.typesafe.config.ConfigObject; import java.io.File; @@ -32,6 +33,7 @@ import org.tron.common.utils.DbOptionalsUtils; import org.tron.common.utils.FileUtil; import org.tron.common.utils.Property; +import org.tron.common.utils.Sha256Hash; /** * Custom storage configurations @@ -79,6 +81,8 @@ public class Storage { private static final String CACHE_STRATEGIES = "storage.cache.strategies"; public static final String TX_CACHE_INIT_OPTIMIZATION = "storage.txCache.initOptimization"; + private static final String MERKLE_ROOT = "storage.merkleRoot"; + /** * Default values of directory */ @@ -163,6 +167,9 @@ public class Storage { @Getter private Map propertyMap; + // db root + private final Map dbRoots = Maps.newConcurrentMap(); + public static String getDbEngineFromConfig(final Config config) { return config.hasPath(DB_ENGINE_CONFIG_KEY) ? config.getString(DB_ENGINE_CONFIG_KEY) : DEFAULT_DB_ENGINE; @@ -258,6 +265,18 @@ public String getCacheStrategy(CacheType dbName) { return this.cacheStrategies.getOrDefault(dbName, CacheStrategies.getCacheStrategy(dbName)); } + public Sha256Hash getDbRoot(String dbName, Sha256Hash defaultV) { + return this.dbRoots.getOrDefault(dbName, defaultV); + } + + public void setDbRoots(Config config) { + if (config.hasPath(MERKLE_ROOT)) { + config.getConfig(MERKLE_ROOT).resolve().entrySet().forEach(c -> + this.dbRoots.put(c.getKey(), Sha256Hash.wrap( + ByteString.fromHex(c.getValue().unwrapped().toString())))); + } + } + private Property createProperty(final ConfigObject conf) { Property property = new Property(); diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 9694668af01..610e491c100 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -530,6 +530,7 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.storage.setDefaultDbOptions(config); PARAMETER.storage.setPropertyMapFromConfig(config); PARAMETER.storage.setCacheStrategies(config); + PARAMETER.storage.setDbRoots(config); PARAMETER.seedNode = new SeedNode(); PARAMETER.seedNode.setAddressList(loadSeeds(config)); @@ -1192,9 +1193,17 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.MAX_UNSOLIDIFIED_BLOCKS) ? config .getInt(Constant.MAX_UNSOLIDIFIED_BLOCKS) : 1000; - PARAMETER.allowOldRewardOpt = - config.hasPath(Constant.COMMITTEE_ALLOW_OLD_REWARD_OPT) ? config - .getInt(Constant.COMMITTEE_ALLOW_OLD_REWARD_OPT) : 0; + long allowOldRewardOpt = config.hasPath(Constant.COMMITTEE_ALLOW_OLD_REWARD_OPT) ? config + .getInt(Constant.COMMITTEE_ALLOW_OLD_REWARD_OPT) : 0; + if (allowOldRewardOpt == 1 && PARAMETER.allowNewRewardAlgorithm != 1 + && PARAMETER.allowNewReward != 1 && PARAMETER.allowTvmVote != 1) { + throw new IllegalArgumentException( + "At least one of the following proposals is required to be opened first: " + + "committee.allowNewRewardAlgorithm = 1" + + " or committee.allowNewReward = 1" + + " or committee.allowTvmVote = 1."); + } + PARAMETER.allowOldRewardOpt = allowOldRewardOpt; logConfig(); } diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index f0479a29cb2..5fe32b82880 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -97,6 +97,13 @@ storage { # txCache.estimatedTransactions = 1000 # if true, transaction cache initialization will be faster. default false # txCache.initOptimization = true + + # data root setting, for check data, currently, only reward-vi is used. + + # merkleRoot = { + # reward-vi = 9debcb9924055500aaae98cdee10501c5c39d4daa75800a996f4bdda73dbccd8 // main-net, Sha256Hash, hexString + # } + } node.discovery = { diff --git a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java index 8866540a028..8e2b7647967 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java @@ -364,22 +364,10 @@ public void validateCheck() { Assert.fail(); } catch (ContractValidateException e) { Assert.assertEquals( - "[ALLOW_NEW_REWARD] proposal must be approved " + "[ALLOW_NEW_REWARD] or [ALLOW_TVM_VOTE] proposal must be approved " + "before [ALLOW_OLD_REWARD_OPT] can be proposed", e.getMessage()); } - dynamicPropertiesStore.saveCurrentCycleNumber(0); - dynamicPropertiesStore.saveNewRewardAlgorithmEffectiveCycle(); - dynamicPropertiesStore.saveAllowNewReward(1); - try { - ProposalUtil.validator(dynamicPropertiesStore, forkUtils, - ProposalType.ALLOW_OLD_REWARD_OPT.getCode(), 1); - Assert.fail(); - } catch (ContractValidateException e) { - Assert.assertEquals( - "no need old reward opt, ALLOW_NEW_REWARD from start cycle 1", - e.getMessage()); - } dynamicPropertiesStore.put("NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE".getBytes(), new BytesCapsule(ByteArray.fromLong(4000))); dynamicPropertiesStore.saveAllowOldRewardOpt(1); diff --git a/framework/src/test/java/org/tron/core/capsule/utils/MerkleTreeTest.java b/framework/src/test/java/org/tron/core/capsule/utils/MerkleTreeTest.java index 4e3273203c8..3662fb524b8 100644 --- a/framework/src/test/java/org/tron/core/capsule/utils/MerkleTreeTest.java +++ b/framework/src/test/java/org/tron/core/capsule/utils/MerkleTreeTest.java @@ -1,18 +1,28 @@ package org.tron.core.capsule.utils; +import com.google.protobuf.ByteString; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.MerkleRoot; import org.tron.common.utils.Sha256Hash; import org.tron.core.capsule.utils.MerkleTree.Leaf; @Slf4j public class MerkleTreeTest { + @Rule + public ExpectedException exception = ExpectedException.none(); + private static List getHash(int hashNum) { List hashList = new ArrayList(); for (int i = 0; i < hashNum; i++) { @@ -173,4 +183,27 @@ public void testAnyHashNum() { pareTree(root, hashList, maxRank, 0, 0); } } -} \ No newline at end of file + + @Test + public void testConcurrent() { + Sha256Hash root1 = Sha256Hash.wrap( + ByteString.fromHex("6cb38b4f493db8bacf26123cd4253bbfc530c708b97b3747e782f64097c3c482")); + Sha256Hash root2 = Sha256Hash.wrap( + ByteString.fromHex("4bfc60ea3de4f5d1476f839874df0aba38eec4e524d6fa63f5b19c4bf527eaf3")); + List list1 = IntStream.range(0, 10000).mapToObj(i -> + Sha256Hash.of(true, ("byte1-" + i).getBytes(StandardCharsets.UTF_8))) + .collect(Collectors.toList()); + List list2 = IntStream.range(0, 10000).mapToObj(i -> + Sha256Hash.of(true, ("byte2-" + i).getBytes(StandardCharsets.UTF_8))) + .collect(Collectors.toList()); + Assert.assertEquals(root1, MerkleTree.getInstance().createTree(list1).getRoot().getHash()); + Assert.assertEquals(root2, MerkleTree.getInstance().createTree(list2).getRoot().getHash()); + Assert.assertEquals(root1, MerkleRoot.root(list1)); + Assert.assertEquals(root2, MerkleRoot.root(list2)); + exception.expect(ArrayIndexOutOfBoundsException.class); + IntStream.range(0, 1000).parallel().forEach(i -> Assert.assertEquals( + MerkleTree.getInstance().createTree(i % 2 == 0 ? list1 : list2).getRoot().getHash(), + MerkleRoot.root(i % 2 == 0 ? list1 : list2)) + ); + } +} diff --git a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java index 59b684b338f..bd3d34e77f7 100644 --- a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java @@ -25,7 +25,9 @@ import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.tron.common.args.GenesisBlock; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; @@ -41,6 +43,9 @@ public class ArgsTest { private String address; private LocalWitnesses localWitnesses; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @After public void destroy() { Args.clearParam(); @@ -138,5 +143,11 @@ public void testIpFromLibP2p() Assert.assertNotEquals(configuredExternalIp, parameter.getNodeExternalIp()); } + + @Test + public void testOldRewardOpt() { + thrown.expect(IllegalArgumentException.class); + Args.setParam(new String[] {"-w"}, "args-test.conf"); + } } diff --git a/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java b/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java index 00e0799cf11..0082c8728da 100644 --- a/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java +++ b/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java @@ -17,13 +17,16 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.contrib.java.lang.system.ExpectedSystemExit; import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; import org.tron.common.error.TronDBException; import org.tron.common.es.ExecutorServiceManager; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.ReflectUtils; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.BytesCapsule; import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; @@ -32,6 +35,7 @@ import org.tron.core.store.AccountStore; import org.tron.core.store.DelegationStore; import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.store.RewardViStore; import org.tron.core.store.WitnessStore; import org.tron.protos.Protocol; @@ -106,9 +110,13 @@ public class ComputeRewardTest { private static RewardViCalService rewardViCalService; private static WitnessStore witnessStore; private static MortgageService mortgageService; + private static RewardViStore rewardViStore; @Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder(); + @Rule + public final ExpectedSystemExit exit = ExpectedSystemExit.none(); + @After public void destroy() { context.destroy(); @@ -129,6 +137,7 @@ public void init() throws IOException { rewardViCalService = context.getBean(RewardViCalService.class); witnessStore = context.getBean(WitnessStore.class); mortgageService = context.getBean(MortgageService.class); + rewardViStore = context.getBean(RewardViStore.class); setUp(); } @@ -254,7 +263,32 @@ private void setUp() { @Test public void query() { + exit.expectSystemExitWithStatus(1); Assert.assertEquals(3189, mortgageService.queryReward(OWNER_ADDRESS)); + // mock root is error + rewardViStore.put("test".getBytes(), "test".getBytes()); + ReflectUtils.invokeMethod(rewardViCalService,"maybeRun"); + + // mock no need + propertiesStore.saveCurrentCycleNumber(0); + // reset + propertiesStore.put("NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE".getBytes(), + new BytesCapsule(ByteArray.fromLong(Long.MAX_VALUE))); + // set + propertiesStore.saveNewRewardAlgorithmEffectiveCycle(); + ReflectUtils.invokeMethod(rewardViCalService,"maybeRun"); + + // mock maybeRun exception + propertiesStore.saveCurrentCycleNumber(4); + // reset + propertiesStore.put("NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE".getBytes(), + new BytesCapsule(ByteArray.fromLong(Long.MAX_VALUE))); + // set + propertiesStore.saveNewRewardAlgorithmEffectiveCycle(); + propertiesStore.saveCurrentCycleNumber(5); + rewardViStore.close(); + ReflectUtils.invokeMethod(rewardViCalService,"maybeRun"); + } static class Vote { diff --git a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java index e248af647c3..0ba32b27f2e 100644 --- a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java @@ -1,6 +1,5 @@ package org.tron.core.services; -import static org.tron.core.utils.ProposalUtil.ProposalType.ALLOW_OLD_REWARD_OPT; import static org.tron.core.utils.ProposalUtil.ProposalType.ENERGY_FEE; import static org.tron.core.utils.ProposalUtil.ProposalType.TRANSACTION_FEE; import static org.tron.core.utils.ProposalUtil.ProposalType.WITNESS_127_PAY_PER_BLOCK; @@ -11,9 +10,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.tron.common.BaseTest; import org.tron.core.Constant; import org.tron.core.capsule.ProposalCapsule; @@ -25,9 +22,6 @@ @Slf4j public class ProposalServiceTest extends BaseTest { - @Rule - public ExpectedException thrown = ExpectedException.none(); - private static boolean init; @BeforeClass @@ -69,9 +63,6 @@ public void test() { proposal = Proposal.newBuilder().putParameters(proposalType.getCode(), 1).build(); } proposalCapsule = new ProposalCapsule(proposal); - if (proposalType == ALLOW_OLD_REWARD_OPT) { - thrown.expect(IllegalStateException.class); - } result = ProposalService.process(dbManager, proposalCapsule); Assert.assertTrue(result); } diff --git a/framework/src/test/resources/args-test.conf b/framework/src/test/resources/args-test.conf new file mode 100644 index 00000000000..91913dfe32e --- /dev/null +++ b/framework/src/test/resources/args-test.conf @@ -0,0 +1,224 @@ +net { + // type = mainnet + type = testnet +} + + +storage { + # Directory for storing persistent data + + db.engine = "LEVELDB" + db.directory = "database", + index.directory = "index", + + # You can custom these 14 databases' configs: + + # account, account-index, asset-issue, block, block-index, + # block_KDB, peers, properties, recent-block, trans, + # utxo, votes, witness, witness_schedule. + + # Otherwise, db configs will remain defualt and data will be stored in + # the path of "output-directory" or which is set by "-d" ("--output-directory"). + + # Attention: name is a required field that must be set !!! + default = { + maxOpenFiles = 50 + } + defaultM = { + maxOpenFiles = 500 + } + defaultL = { + maxOpenFiles = 1000 + } + properties = [ + { + name = "account", + path = "storage_directory_test", + createIfMissing = true, + paranoidChecks = true, + verifyChecksums = true, + compressionType = 1, // compressed with snappy + blockSize = 4096, // 4 KB = 4 * 1024 B + writeBufferSize = 10485760, // 10 MB = 10 * 1024 * 1024 B + cacheSize = 10485760, // 10 MB = 10 * 1024 * 1024 B + maxOpenFiles = 100 + }, + { + name = "account-index", + path = "storage_directory_test", + createIfMissing = true, + paranoidChecks = true, + verifyChecksums = true, + compressionType = 1, // compressed with snappy + blockSize = 4096, // 4 KB = 4 * 1024 B + writeBufferSize = 10485760, // 10 MB = 10 * 1024 * 1024 B + cacheSize = 10485760, // 10 MB = 10 * 1024 * 1024 B + maxOpenFiles = 100 + }, + { # only for unit test + name = "test_name", + path = "test_path", + createIfMissing = false, + paranoidChecks = false, + verifyChecksums = false, + compressionType = 1, + blockSize = 2, + writeBufferSize = 3, + cacheSize = 4, + maxOpenFiles = 5 + }, + ] + + needToUpdateAsset = false + +} + +node.discovery = { + enable = true + persist = true + external.ip = "46.168.1.1" +} + +node { + + trustNode = "127.0.0.1:50051" + + listen.port = 18888 + + connection.timeout = 2 + + active = [] + + maxConnections = 30 + minConnections = 8 + minActiveConnections = 3 + + p2p { + version = 43 # 43: testnet; 101: debug + } + + rpc { + port = 50051 + } + +} + +sync { + node.count = 30 +} + +seed.node = { + ip.list = [ + ] +} + +genesis.block = { + # Reserve balance + assets = [ + { + accountName = "Devaccount" + accountType = "AssetIssue" + address = "27d3byPxZXKQWfXX7sJvemJJuv5M65F3vjS" + balance = "10000000000000000" + }, + { + accountName = "Zion" + accountType = "AssetIssue" + address = "27fXgQ46DcjEsZ444tjZPKULcxiUfDrDjqj" + balance = "15000000000000000" + }, + { + accountName = "Sun" + accountType = "AssetIssue" + address = "27SWXcHuQgFf9uv49FknBBBYBaH3DUk4JPx" + balance = "10000000000000000" + }, + { + accountName = "Blackhole" + accountType = "AssetIssue" + address = "27WtBq2KoSy5v8VnVZBZHHJcDuWNiSgjbE3" + balance = "-9223372036854775808" + } + ] + + witnesses = [ + { + address: 27Ssb1WE8FArwJVRRb8Dwy3ssVGuLY8L3S1 + url = "http://mercury.org/", + voteCount = 105 + }, + { + address: 27anh4TDZJGYpsn4BjXzb7uEArNALxwiZZW + url = "http://venus.org/", + voteCount = 104 + }, + { + address: 27Wkfa5iEJtsKAKdDzSmF1b2gDm5s49kvdZ + url = "http://earth.org/", + voteCount = 103 + }, + { + address: 27bqKYX9Bgv7dgTY7xBw5SUHZ8EGaPSikjx + url = "http://mars.org/", + voteCount = 102 + }, + { + address: 27fASUY6qKtsaAEPz6QxhZac2KYVz2ZRTXW + url = "http://jupiter.org/", + voteCount = 101 + }, + { + address: 27Q3RSbiqm59VXcF8shQWHKbyztfso5FwvP + url = "http://saturn.org/", + voteCount = 100 + }, + { + address: 27YkUVSuvCK3K84DbnFnxYUxozpi793PTqZ + url = "http://uranus.org/", + voteCount = 99 + }, + { + address: 27kdTBTDJ16hK3Xqr8PpCuQJmje1b94CDJU + url = "http://neptune.org/", + voteCount = 98 + }, + { + address: 27mw9UpRy7inTMQ5kUzsdTc2QZ6KvtCX4uB + url = "http://pluto.org/", + voteCount = 97 + }, + { + address: 27QzC4PeQZJ2kFMUXiCo4S8dx3VWN5U9xcg + url = "http://altair.org/", + voteCount = 96 + }, + { + address: 27VZHn9PFZwNh7o2EporxmLkpe157iWZVkh + url = "http://alphalyrae.org/", + voteCount = 95 + } + ] + + timestamp = "0" #2017-8-26 12:00:00 + + parentHash = "0x0000000000000000000000000000000000000000000000000000000000000000" +} + + +localwitness = [ + +] + +block = { + needSyncCheck = true # first node : false, other : true +} + +vm = { + supportConstant = true + minTimeRatio = 0.0 + maxTimeRatio = 5.0 +} +committee = { + allowCreationOfContracts = 1 //mainnet:0 (reset by committee),test:1 + allowOldRewardOpt = 1 +} diff --git a/framework/src/test/resources/config-test-storagetest.conf b/framework/src/test/resources/config-test-storagetest.conf index d2dc27b795a..25127cdab91 100644 --- a/framework/src/test/resources/config-test-storagetest.conf +++ b/framework/src/test/resources/config-test-storagetest.conf @@ -284,4 +284,6 @@ vm = { } committee = { allowCreationOfContracts = 1 //mainnet:0 (reset by committee),test:1 + allowOldRewardOpt = 1 + allowNewRewardAlgorithm = 1 } diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index 68a48ca64b2..db24bb2a8a0 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -69,6 +69,12 @@ storage { # if true, transaction cache initialization will be faster. default false txCache.initOptimization = true + # data root setting, for check data, currently, only reward-vi is used. + + merkleRoot = { + reward-vi = e0ebe2f3243391ed674dff816a07f589a3279420d6d88bc823b6a9d5778337ce + } + } node.discovery = { diff --git a/plugins/src/main/java/org/tron/plugins/Db.java b/plugins/src/main/java/org/tron/plugins/Db.java index c67c838a3d6..84654dca934 100644 --- a/plugins/src/main/java/org/tron/plugins/Db.java +++ b/plugins/src/main/java/org/tron/plugins/Db.java @@ -11,7 +11,8 @@ DbArchive.class, DbConvert.class, DbLite.class, - DbCopy.class + DbCopy.class, + DbRoot.class }, commandListHeading = "%nCommands:%n%nThe most commonly used db commands are:%n" ) diff --git a/plugins/src/main/java/org/tron/plugins/DbRoot.java b/plugins/src/main/java/org/tron/plugins/DbRoot.java new file mode 100644 index 00000000000..69555c16d33 --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/DbRoot.java @@ -0,0 +1,99 @@ +package org.tron.plugins; + +import com.google.common.collect.Streams; +import com.google.common.primitives.Bytes; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import me.tongfei.progressbar.ProgressBar; +import org.rocksdb.RocksDBException; +import org.tron.plugins.utils.MerkleRoot; +import org.tron.plugins.utils.Sha256Hash; +import org.tron.plugins.utils.db.DBInterface; +import org.tron.plugins.utils.db.DBIterator; +import org.tron.plugins.utils.db.DbTool; +import picocli.CommandLine; + +@Slf4j(topic = "db-root") +@CommandLine.Command(name = "root", + description = "compute merkle root for tiny db. NOTE: large db may GC overhead limit exceeded.", + exitCodeListHeading = "Exit Codes:%n", + exitCodeList = { + "0:Successful", + "n:query failed,please check toolkit.log"}) +public class DbRoot implements Callable { + + @CommandLine.Spec + CommandLine.Model.CommandSpec spec; + @CommandLine.Parameters(index = "0", defaultValue = "output-directory/database", + description = "Input path. Default: ${DEFAULT-VALUE}") + private Path db; + + @CommandLine.Option(names = { "--db"}, + description = "db name for show root") + private List dbs; + + @CommandLine.Option(names = {"-h", "--help"}, help = true, description = "display a help message") + private boolean help; + + + @Override + public Integer call() throws Exception { + if (help) { + spec.commandLine().usage(System.out); + return 0; + } + if (!db.toFile().exists()) { + logger.info(" {} does not exist.", db); + spec.commandLine().getErr().println(spec.commandLine().getColorScheme() + .errorText(String.format("%s does not exist.", db))); + return 404; + } + + // remove not exit + if (dbs != null) { + dbs.removeIf(s -> !Paths.get(db.toString(), s).toFile().exists()); + } + + if (dbs == null || dbs.isEmpty()) { + logger.info("Specify at least one exit database: --db dbName."); + spec.commandLine().getErr().println(spec.commandLine().getColorScheme() + .errorText("Specify at least one exit database: --db dbName.")); + return 404; + } + if (dbs.size() > 1) { + ProgressBar.wrap(dbs.stream(), "root task").parallel().forEach(this::calcMerkleRoot); + } else { + calcMerkleRoot(dbs.get(0)); + } + spec.commandLine().getOut().println("root task done."); + return 0; + } + + private void calcMerkleRoot(String name) { + try (DBInterface database = DbTool.getDB(this.db, name)) { + DBIterator iterator = database.iterator(); + iterator.seekToFirst(); + ArrayList ids = Streams.stream(iterator) + .map(this::getHash) + .collect(Collectors.toCollection(ArrayList::new)); + Sha256Hash root = MerkleRoot.root(ids); + logger.info("db: {},root: {}", database.getName(), root); + spec.commandLine().getOut().println(String.format("db: %s,root: %s", + database.getName(), root)); + } catch (RocksDBException | IOException e) { + logger.error("calc db {} fail", name, e); + } + } + + private Sha256Hash getHash(Map.Entry entry) { + return Sha256Hash.of(true, + Bytes.concat(entry.getKey(), entry.getValue())); + } +} diff --git a/plugins/src/main/java/org/tron/plugins/utils/MerkleRoot.java b/plugins/src/main/java/org/tron/plugins/utils/MerkleRoot.java new file mode 100644 index 00000000000..055f5dcdee0 --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/utils/MerkleRoot.java @@ -0,0 +1,68 @@ +package org.tron.plugins.utils; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import lombok.Getter; + +public class MerkleRoot { + + private MerkleRoot() { + + } + + public static Sha256Hash root(List hashList) { + List leaves = createLeaves(hashList); + while (leaves.size() > 1) { + leaves = createParentLeaves(leaves); + } + return leaves.isEmpty() ? Sha256Hash.ZERO_HASH : leaves.get(0).hash; + } + + private static List createParentLeaves(List leaves) { + int step = 2; + int len = leaves.size(); + return IntStream.iterate(0, i -> i + step) + .limit(len) + .filter(i -> i < len) + .mapToObj(i -> { + Leaf right = i + 1 < len ? leaves.get(i + 1) : null; + return createLeaf(leaves.get(i), right); + }).collect(Collectors.toList()); + } + + private static List createLeaves(List hashList) { + int step = 2; + int len = hashList.size(); + return IntStream.iterate(0, i -> i + step) + .limit(len) + .filter(i -> i < len) + .mapToObj(i -> { + Leaf right = i + 1 < len ? createLeaf(hashList.get(i + 1)) : null; + return createLeaf(createLeaf(hashList.get(i)), right); + }).collect(Collectors.toList()); + } + + private static Leaf createLeaf(Leaf left, Leaf right) { + Leaf leaf = new Leaf(); + leaf.hash = right == null ? left.hash : computeHash(left.hash, right.hash); + return leaf; + } + + private static Leaf createLeaf(Sha256Hash hash) { + Leaf leaf = new Leaf(); + leaf.hash = hash; + return leaf; + } + + private static Sha256Hash computeHash(Sha256Hash leftHash, Sha256Hash rightHash) { + return Sha256Hash.of(true, + leftHash.getByteString().concat(rightHash.getByteString()).toByteArray()); + } + + @Getter + private static class Leaf { + + private Sha256Hash hash; + } +} diff --git a/plugins/src/main/java/org/tron/plugins/utils/Sha256Hash.java b/plugins/src/main/java/org/tron/plugins/utils/Sha256Hash.java index 5fe80601b66..67e6e64ea79 100644 --- a/plugins/src/main/java/org/tron/plugins/utils/Sha256Hash.java +++ b/plugins/src/main/java/org/tron/plugins/utils/Sha256Hash.java @@ -21,6 +21,7 @@ import com.google.common.io.ByteStreams; import com.google.common.primitives.Ints; +import com.google.protobuf.ByteString; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -39,7 +40,7 @@ public class Sha256Hash implements Serializable, Comparable { public static final int LENGTH = 32; // bytes - + public static final Sha256Hash ZERO_HASH = wrap(new byte[LENGTH]); private final byte[] bytes; /** @@ -184,6 +185,13 @@ public byte[] getBytes() { return bytes; } + /** + * For pb return ByteString. + */ + public ByteString getByteString() { + return ByteString.copyFrom(bytes); + } + @Override public int compareTo(final Sha256Hash other) { diff --git a/plugins/src/main/java/org/tron/plugins/utils/db/DBInterface.java b/plugins/src/main/java/org/tron/plugins/utils/db/DBInterface.java index b0f7c58c587..513e021c83c 100644 --- a/plugins/src/main/java/org/tron/plugins/utils/db/DBInterface.java +++ b/plugins/src/main/java/org/tron/plugins/utils/db/DBInterface.java @@ -18,4 +18,6 @@ public interface DBInterface extends Closeable { void close() throws IOException; + String getName(); + } diff --git a/plugins/src/main/java/org/tron/plugins/utils/db/DbTool.java b/plugins/src/main/java/org/tron/plugins/utils/db/DbTool.java index 6e8df4c59fb..429025e8f8b 100644 --- a/plugins/src/main/java/org/tron/plugins/utils/db/DbTool.java +++ b/plugins/src/main/java/org/tron/plugins/utils/db/DbTool.java @@ -23,7 +23,7 @@ public class DbTool { private static final Map dbMap = Maps.newConcurrentMap(); - enum DbType { + public enum DbType { LevelDB, RocksDB } @@ -83,11 +83,11 @@ public static DBInterface getDB(String sourceDir, String dbName, DbType type) DBInterface db; switch (type) { case LevelDB: - db = openLevelDb(path); + db = openLevelDb(path, dbName); dbMap.put(path.toString(), db); break; case RocksDB: - db = openRocksDb(path); + db = openRocksDb(path, dbName); dbMap.put(path.toString(), db); break; default: @@ -114,9 +114,9 @@ public static DBInterface getDB(Path sourceDir, String dbName) DbType type = getDbType(sourceDir.toString(), dbName); switch (type) { case LevelDB: - return openLevelDb(path); + return openLevelDb(path, dbName); case RocksDB: - return openRocksDb(path); + return openRocksDb(path, dbName); default: throw new IllegalStateException("Unexpected value: " + type); } @@ -175,12 +175,12 @@ private static DbType getDbType(String sourceDir, String dbName) { } } - private static LevelDBImpl openLevelDb(Path db) throws IOException { - return new LevelDBImpl(DBUtils.newLevelDb(db)); + private static LevelDBImpl openLevelDb(Path db, String name) throws IOException { + return new LevelDBImpl(DBUtils.newLevelDb(db), name); } - private static RocksDBImpl openRocksDb(Path db) throws RocksDBException { - return new RocksDBImpl(DBUtils.newRocksDb(db)); + private static RocksDBImpl openRocksDb(Path db, String name) throws RocksDBException { + return new RocksDBImpl(DBUtils.newRocksDb(db), name); } diff --git a/plugins/src/main/java/org/tron/plugins/utils/db/LevelDBImpl.java b/plugins/src/main/java/org/tron/plugins/utils/db/LevelDBImpl.java index 3a89e77af40..511f4dfd5b4 100644 --- a/plugins/src/main/java/org/tron/plugins/utils/db/LevelDBImpl.java +++ b/plugins/src/main/java/org/tron/plugins/utils/db/LevelDBImpl.java @@ -2,6 +2,7 @@ import com.google.common.collect.Streams; import java.io.IOException; +import lombok.Getter; import org.iq80.leveldb.DB; import org.iq80.leveldb.ReadOptions; @@ -10,8 +11,12 @@ public class LevelDBImpl implements DBInterface { private DB leveldb; - public LevelDBImpl(DB leveldb) { + @Getter + private final String name; + + public LevelDBImpl(DB leveldb, String name) { this.leveldb = leveldb; + this.name = name; } @Override diff --git a/plugins/src/main/java/org/tron/plugins/utils/db/RocksDBImpl.java b/plugins/src/main/java/org/tron/plugins/utils/db/RocksDBImpl.java index 88b25b0413f..50957bbe61b 100644 --- a/plugins/src/main/java/org/tron/plugins/utils/db/RocksDBImpl.java +++ b/plugins/src/main/java/org/tron/plugins/utils/db/RocksDBImpl.java @@ -1,6 +1,7 @@ package org.tron.plugins.utils.db; import java.io.IOException; +import lombok.Getter; import org.rocksdb.RocksDBException; import org.rocksdb.RocksIterator; @@ -8,8 +9,12 @@ public class RocksDBImpl implements DBInterface { private org.rocksdb.RocksDB rocksDB; - public RocksDBImpl(org.rocksdb.RocksDB rocksDB) { + @Getter + private final String name; + + public RocksDBImpl(org.rocksdb.RocksDB rocksDB, String name) { this.rocksDB = rocksDB; + this.name = name; } @Override diff --git a/plugins/src/test/java/org/tron/plugins/DbRootTest.java b/plugins/src/test/java/org/tron/plugins/DbRootTest.java new file mode 100644 index 00000000000..4b2c6c7d373 --- /dev/null +++ b/plugins/src/test/java/org/tron/plugins/DbRootTest.java @@ -0,0 +1,82 @@ +package org.tron.plugins; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.rocksdb.RocksDBException; +import org.tron.plugins.utils.DBUtils; +import org.tron.plugins.utils.db.DBInterface; +import org.tron.plugins.utils.db.DbTool; +import org.tron.plugins.utils.db.LevelDBImpl; +import picocli.CommandLine; + +@Slf4j +public class DbRootTest { + + @Rule + public final TemporaryFolder folder = new TemporaryFolder(); + + CommandLine cli = new CommandLine(new Toolkit()); + + private static final String NORMAL_DB = "normal"; + private static final String EMPTY_DB = "empty"; + private static final String ERROR_DB = "error"; + + @Test + public void testRoot() throws IOException, RocksDBException { + + File file = folder.newFolder(); + + File database = Paths.get(file.getPath(),"database").toFile(); + Assert.assertTrue(database.mkdirs()); + + + try (DBInterface normal = DbTool.getDB(database.toString(), NORMAL_DB, DbTool.DbType.LevelDB); + DBInterface empty = DbTool.getDB(database.toString(), EMPTY_DB, DbTool.DbType.RocksDB)) { + for (int i = 0; i < 10; i++) { + normal.put(("" + i).getBytes(), (NORMAL_DB + "-" + i).getBytes()); + } + } + + String[] args = new String[] {"db", "root", database.toString(), + "--db", NORMAL_DB, "--db", EMPTY_DB}; + Assert.assertEquals(0, cli.execute(args)); + args = new String[] {"db", "root", database.toString(), + "--db", NORMAL_DB}; + Assert.assertEquals(0, cli.execute(args)); + args = new String[] {"db", "root", database.toString(), + "--db", EMPTY_DB}; + Assert.assertEquals(0, cli.execute(args)); + + try (DBInterface errorDb = new LevelDBImpl( + DBUtils.newLevelDb(Paths.get(database.toString(), ERROR_DB)), ERROR_DB)) { + for (int i = 0; i < 10; i++) { + errorDb.put(("" + i).getBytes(), (ERROR_DB + "-" + i).getBytes()); + } + args = new String[] {"db", "root", database.toString(), "--db", ERROR_DB}; + Assert.assertEquals(0, cli.execute(args)); + } + + } + + @Test + public void testHelp() { + String[] args = new String[] {"db", "root", "-h"}; + Assert.assertEquals(0, cli.execute(args)); + } + + @Test + public void testEmpty() throws IOException { + File file = folder.newFolder(); + File database = Paths.get(file.getPath(),"database").toFile(); + String[] args = new String[] {"db", "root", database.toString()}; + Assert.assertEquals(404, cli.execute(args)); + Assert.assertTrue(database.mkdirs()); + Assert.assertEquals(404, cli.execute(args)); + } +} From 074e0d69b6b87ea1d070758b29f80dd6917cdd15 Mon Sep 17 00:00:00 2001 From: Brown Jiang <317787106@qq.com> Date: Wed, 6 Mar 2024 12:37:55 +0800 Subject: [PATCH 0979/1197] hotfix(net):throw exception if scalingFactor <=0 (#5746) --- .../tron/core/capsule/TransactionCapsule.java | 1 - .../src/main/java/org/tron/core/Wallet.java | 17 +++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java index 5d5a5d5b462..a588b28c748 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -738,7 +738,6 @@ public Transaction getInstance() { @Override public String toString() { StringBuilder toStringBuff = new StringBuilder(); - toStringBuff.setLength(0); toStringBuff.append("TransactionCapsule \n[ "); toStringBuff.append("hash=").append(getTransactionId()).append("\n"); diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 6e5c17417b7..96af6fc7476 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -3862,12 +3862,11 @@ private boolean isShieldedTRC20NoteSpent(GrpcAPI.Note note, long pos, byte[] ak, TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); TransactionExtention trxExt; - Transaction trx; try { TransactionCapsule trxCap = createTransactionCapsule(trigger, ContractType.TriggerSmartContract); - trx = triggerConstantContract(trigger, trxCap, trxExtBuilder, retBuilder); + Transaction trx = triggerConstantContract(trigger, trxCap, trxExtBuilder, retBuilder); retBuilder.setResult(true).setCode(response_code.SUCCESS); trxExtBuilder.setTransaction(trx); @@ -3890,10 +3889,10 @@ private boolean isShieldedTRC20NoteSpent(GrpcAPI.Note note, long pos, byte[] ak, logger.warn("unknown exception caught: " + e.getMessage(), e); } finally { trxExt = trxExtBuilder.build(); - trx = trxExt.getTransaction(); } - if (code.SUCESS == trx.getRet(0).getRet()) { + String code = trxExt.getResult().getCode().toString(); + if ("SUCCESS".equals(code)) { List list = trxExt.getConstantResultList(); byte[] listBytes = new byte[0]; for (ByteString bs : list) { @@ -4086,6 +4085,9 @@ private long[] checkPublicAmount(byte[] address, BigInteger fromAmount, BigInteg } catch (ContractExeException e) { throw new ContractExeException("Get shielded contract scalingFactor failed"); } + if (scalingFactor.compareTo(BigInteger.ZERO) <= 0) { + throw new ContractValidateException("scalingFactor must be positive"); + } // fromAmount and toAmount must be a multiple of scalingFactor if (!(fromAmount.mod(scalingFactor).equals(BigInteger.ZERO) @@ -4127,12 +4129,11 @@ public byte[] getShieldedContractScalingFactor(byte[] contractAddress) TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); TransactionExtention trxExt; - Transaction trx; try { TransactionCapsule trxCap = createTransactionCapsule(trigger, ContractType.TriggerSmartContract); - trx = triggerConstantContract(trigger, trxCap, trxExtBuilder, retBuilder); + Transaction trx = triggerConstantContract(trigger, trxCap, trxExtBuilder, retBuilder); retBuilder.setResult(true).setCode(response_code.SUCCESS); trxExtBuilder.setTransaction(trx); @@ -4155,10 +4156,10 @@ public byte[] getShieldedContractScalingFactor(byte[] contractAddress) logger.warn("Unknown exception caught: " + e.getMessage(), e); } finally { trxExt = trxExtBuilder.build(); - trx = trxExt.getTransaction(); } - if (code.SUCESS == trx.getRet(0).getRet()) { + String code = trxExt.getResult().getCode().toString(); + if ("SUCCESS".equals(code)) { List list = trxExt.getConstantResultList(); byte[] listBytes = new byte[0]; for (ByteString bs : list) { From 9bb0ea36b2334404d14cb39289d9d8fe9890cead Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 6 Mar 2024 18:06:04 +0800 Subject: [PATCH 0980/1197] feat(test):fix the coverage change of org.tron.core.capsule.utils.FastByteComparisons --- framework/src/test/java/org/tron/core/tire/TrieTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/framework/src/test/java/org/tron/core/tire/TrieTest.java b/framework/src/test/java/org/tron/core/tire/TrieTest.java index ba5c536c987..7005198ad8b 100644 --- a/framework/src/test/java/org/tron/core/tire/TrieTest.java +++ b/framework/src/test/java/org/tron/core/tire/TrieTest.java @@ -26,6 +26,7 @@ import org.bouncycastle.util.Arrays; import org.junit.Assert; import org.junit.Test; +import org.tron.core.capsule.utils.FastByteComparisons; import org.tron.core.capsule.utils.RLP; import org.tron.core.trie.TrieImpl; import org.tron.core.trie.TrieImpl.Node; @@ -151,4 +152,11 @@ private void assertFalse(byte[] key1, byte[] key2, TrieImpl trieCopy) { Assert.assertFalse(trieCopy.verifyProof(trieCopy.getRootHash(), key2, trieCopy.prove(key1))); } + @Test + public void testFastByteComparisons() { + byte[] test1 = new byte[] {0x00, 0x00, 0x01, 0x02, 0x03, 0x04}; + byte[] test2 = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04}; + Assert.assertEquals(0, FastByteComparisons.compareTo(test1, 1, 5, test2, 0, 5)); + } + } From eaf2c34cbf52bf360b70a776d381a05d8a718f48 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Thu, 7 Mar 2024 12:20:12 +0800 Subject: [PATCH 0981/1197] feat(toolkit): show db root error to console (#5748) --- plugins/README.md | 11 ++++++ .../main/java/org/tron/plugins/DbRoot.java | 38 +++++++++++++++---- .../java/org/tron/plugins/DbRootTest.java | 2 +- 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/plugins/README.md b/plugins/README.md index 19c952372c1..0db6f2e6143 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -134,3 +134,14 @@ Execute move command. java -jar Toolkit.jar db mv -c main_net_config.conf -d /data/tron/output-directory ``` +## DB Root + +DB root provides a helper which can compute merkle root for tiny db. + +NOTE: large db may GC overhead limit exceeded. + +### Available parameters: + +- ``: Source path for database. Default: output-directory/database +- `--db`: db name. +- `-h | --help`: provide the help info diff --git a/plugins/src/main/java/org/tron/plugins/DbRoot.java b/plugins/src/main/java/org/tron/plugins/DbRoot.java index 69555c16d33..7c33219e180 100644 --- a/plugins/src/main/java/org/tron/plugins/DbRoot.java +++ b/plugins/src/main/java/org/tron/plugins/DbRoot.java @@ -67,16 +67,20 @@ public Integer call() throws Exception { .errorText("Specify at least one exit database: --db dbName.")); return 404; } - if (dbs.size() > 1) { - ProgressBar.wrap(dbs.stream(), "root task").parallel().forEach(this::calcMerkleRoot); - } else { - calcMerkleRoot(dbs.get(0)); + List task = ProgressBar.wrap(dbs.stream(), "root task").parallel() + .map(this::calcMerkleRoot).collect(Collectors.toList()); + task.forEach(this::printInfo); + int code = (int) task.stream().filter(r -> r.code == 1).count(); + if (code > 0) { + spec.commandLine().getErr().println(spec.commandLine().getColorScheme() + .errorText("There are some errors, please check toolkit.log for detail.")); } spec.commandLine().getOut().println("root task done."); - return 0; + return code; } - private void calcMerkleRoot(String name) { + private Ret calcMerkleRoot(String name) { + Ret info = new Ret(); try (DBInterface database = DbTool.getDB(this.db, name)) { DBIterator iterator = database.iterator(); iterator.seekToFirst(); @@ -85,15 +89,33 @@ private void calcMerkleRoot(String name) { .collect(Collectors.toCollection(ArrayList::new)); Sha256Hash root = MerkleRoot.root(ids); logger.info("db: {},root: {}", database.getName(), root); - spec.commandLine().getOut().println(String.format("db: %s,root: %s", - database.getName(), root)); + info.code = 0; + info.msg = String.format("db: %s,root: %s", database.getName(), root); } catch (RocksDBException | IOException e) { logger.error("calc db {} fail", name, e); + info.code = 1; + info.msg = String.format("db: %s,fail: %s", + name, e.getMessage()); } + return info; } private Sha256Hash getHash(Map.Entry entry) { return Sha256Hash.of(true, Bytes.concat(entry.getKey(), entry.getValue())); } + + private void printInfo(Ret ret) { + if (ret.code == 0) { + spec.commandLine().getOut().println(ret.msg); + } else { + spec.commandLine().getErr().println(spec.commandLine().getColorScheme() + .errorText(ret.msg)); + } + } + + private static class Ret { + private int code; + private String msg; + } } diff --git a/plugins/src/test/java/org/tron/plugins/DbRootTest.java b/plugins/src/test/java/org/tron/plugins/DbRootTest.java index 4b2c6c7d373..b86688f77d5 100644 --- a/plugins/src/test/java/org/tron/plugins/DbRootTest.java +++ b/plugins/src/test/java/org/tron/plugins/DbRootTest.java @@ -59,7 +59,7 @@ public void testRoot() throws IOException, RocksDBException { errorDb.put(("" + i).getBytes(), (ERROR_DB + "-" + i).getBytes()); } args = new String[] {"db", "root", database.toString(), "--db", ERROR_DB}; - Assert.assertEquals(0, cli.execute(args)); + Assert.assertEquals(1, cli.execute(args)); } } From 74c42e370688947c8be2fbe170f979fb13fa6d9b Mon Sep 17 00:00:00 2001 From: Brown Jiang <317787106@qq.com> Date: Mon, 11 Mar 2024 10:38:11 +0800 Subject: [PATCH 0982/1197] feat(conf):delete all bind.ip (#5750) --- framework/src/main/resources/config-backup.conf | 1 - framework/src/main/resources/config-beta.conf | 1 - framework/src/main/resources/config-localtest.conf | 1 - framework/src/main/resources/config-test-net.conf | 1 - framework/src/main/resources/config.conf | 2 +- framework/src/test/resources/config-localtest.conf | 1 - framework/src/test/resources/config-test-dbbackup.conf | 1 - framework/src/test/resources/config-test-index.conf | 1 - 8 files changed, 1 insertion(+), 8 deletions(-) diff --git a/framework/src/main/resources/config-backup.conf b/framework/src/main/resources/config-backup.conf index 2a1579fdc18..bb3082e42c2 100644 --- a/framework/src/main/resources/config-backup.conf +++ b/framework/src/main/resources/config-backup.conf @@ -51,7 +51,6 @@ storage { node.discovery = { enable = true persist = true - bind.ip = "" external.ip = null } diff --git a/framework/src/main/resources/config-beta.conf b/framework/src/main/resources/config-beta.conf index 1d4a914ce20..050df1e45ad 100644 --- a/framework/src/main/resources/config-beta.conf +++ b/framework/src/main/resources/config-beta.conf @@ -51,7 +51,6 @@ storage { node.discovery = { enable = true persist = true - bind.ip = "" external.ip = null } diff --git a/framework/src/main/resources/config-localtest.conf b/framework/src/main/resources/config-localtest.conf index 5ce30aeb1a4..f1ac104c9ed 100644 --- a/framework/src/main/resources/config-localtest.conf +++ b/framework/src/main/resources/config-localtest.conf @@ -57,7 +57,6 @@ storage { node.discovery = { enable = true persist = true - bind.ip = "" external.ip = null } diff --git a/framework/src/main/resources/config-test-net.conf b/framework/src/main/resources/config-test-net.conf index 58c40587fcc..ff292a3951c 100644 --- a/framework/src/main/resources/config-test-net.conf +++ b/framework/src/main/resources/config-test-net.conf @@ -53,7 +53,6 @@ storage { node.discovery = { enable = true persist = true - bind.ip = "" external.ip = null } diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 5fe32b82880..78427c30f87 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -220,7 +220,7 @@ node { dns { # dns urls to get nodes, url format tree://{pubkey}@{domain}, default empty treeUrls = [ - #"tree://AKMQMNAJJBL73LXWPXDI4I5ZWWIZ4AWO34DWQ636QOBBXNFXH3LQS@main.trondisco.net", //offical dns tree + #"tree://AKMQMNAJJBL73LXWPXDI4I5ZWWIZ4AWO34DWQ636QOBBXNFXH3LQS@main.trondisco.net", ] } diff --git a/framework/src/test/resources/config-localtest.conf b/framework/src/test/resources/config-localtest.conf index fc35ca9b66a..d7f573fe90e 100644 --- a/framework/src/test/resources/config-localtest.conf +++ b/framework/src/test/resources/config-localtest.conf @@ -57,7 +57,6 @@ storage { node.discovery = { enable = true persist = true - bind.ip = "" external.ip = null } diff --git a/framework/src/test/resources/config-test-dbbackup.conf b/framework/src/test/resources/config-test-dbbackup.conf index bb64a87ef69..4f9ddf8d32b 100644 --- a/framework/src/test/resources/config-test-dbbackup.conf +++ b/framework/src/test/resources/config-test-dbbackup.conf @@ -60,7 +60,6 @@ storage { node.discovery = { enable = true persist = true - bind.ip = "" external.ip = null } diff --git a/framework/src/test/resources/config-test-index.conf b/framework/src/test/resources/config-test-index.conf index b9fbf5b2c43..6eb3621e747 100644 --- a/framework/src/test/resources/config-test-index.conf +++ b/framework/src/test/resources/config-test-index.conf @@ -54,7 +54,6 @@ storage { node.discovery = { enable = true persist = true - bind.ip = "" external.ip = null } From 45a2af0f019d48ccbbe1f7ade36254713dfcc228 Mon Sep 17 00:00:00 2001 From: ss3344520 Date: Mon, 11 Mar 2024 14:11:47 +0800 Subject: [PATCH 0983/1197] feat(param): modify the default value of maxUnsolidifiedBlocks (#5751) * feat(param): modify the default value of maxUnsolidifiedBlocks --- .../src/main/java/org/tron/core/config/args/Args.java | 10 +++++----- .../test/java/org/tron/core/config/args/ArgsTest.java | 4 ++-- .../java/org/tron/core/net/TronNetDelegateTest.java | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 610e491c100..a8547b73948 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -229,8 +229,8 @@ public static void clearParam() { PARAMETER.dynamicConfigEnable = false; PARAMETER.dynamicConfigCheckInterval = 600; PARAMETER.allowTvmShangHai = 0; - PARAMETER.unsolidifiedBlockCheck = true; - PARAMETER.maxUnsolidifiedBlocks = 1000; + PARAMETER.unsolidifiedBlockCheck = false; + PARAMETER.maxUnsolidifiedBlocks = 54; PARAMETER.allowOldRewardOpt = 0; } @@ -1186,12 +1186,12 @@ public static void setParam(final String[] args, final String confFileName) { .getInt(Constant.COMMITTEE_ALLOW_TVM_SHANGHAI) : 0; PARAMETER.unsolidifiedBlockCheck = - !config.hasPath(Constant.UNSOLIDIFIED_BLOCK_CHECK) - || config.getBoolean(Constant.UNSOLIDIFIED_BLOCK_CHECK); + config.hasPath(Constant.UNSOLIDIFIED_BLOCK_CHECK) + && config.getBoolean(Constant.UNSOLIDIFIED_BLOCK_CHECK); PARAMETER.maxUnsolidifiedBlocks = config.hasPath(Constant.MAX_UNSOLIDIFIED_BLOCKS) ? config - .getInt(Constant.MAX_UNSOLIDIFIED_BLOCKS) : 1000; + .getInt(Constant.MAX_UNSOLIDIFIED_BLOCKS) : 54; long allowOldRewardOpt = config.hasPath(Constant.COMMITTEE_ALLOW_OLD_REWARD_OPT) ? config .getInt(Constant.COMMITTEE_ALLOW_OLD_REWARD_OPT) : 0; diff --git a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java index bd3d34e77f7..52307d9d294 100644 --- a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java @@ -99,8 +99,8 @@ public void get() { Assert.assertEquals(0, parameter.getActiveNodes().size()); Assert.assertEquals(30, parameter.getMaxConnections()); Assert.assertEquals(43, parameter.getNodeP2pVersion()); - Assert.assertEquals(1000, parameter.getMaxUnsolidifiedBlocks()); - Assert.assertEquals(true, parameter.isUnsolidifiedBlockCheck()); + Assert.assertEquals(54, parameter.getMaxUnsolidifiedBlocks()); + Assert.assertEquals(false, parameter.isUnsolidifiedBlockCheck()); //Assert.assertEquals(30, args.getSyncNodeCount()); // gRPC network configs checking diff --git a/framework/src/test/java/org/tron/core/net/TronNetDelegateTest.java b/framework/src/test/java/org/tron/core/net/TronNetDelegateTest.java index c1ac3df1599..727aad9dccb 100644 --- a/framework/src/test/java/org/tron/core/net/TronNetDelegateTest.java +++ b/framework/src/test/java/org/tron/core/net/TronNetDelegateTest.java @@ -20,6 +20,7 @@ public void test() throws Exception { Args.setParam(new String[] {"-w"}, Constant.TEST_CONF); CommonParameter parameter = Args.getInstance(); Args.logConfig(); + parameter.setUnsolidifiedBlockCheck(true); BlockCapsule.BlockId blockId = new BlockCapsule.BlockId(Sha256Hash.ZERO_HASH, 10000L); From 3b5ed16cdae99a1b33ca6b6f80ac93b0fc14afc2 Mon Sep 17 00:00:00 2001 From: fyyhtx <72650068+fyyhtx@users.noreply.github.com> Date: Mon, 11 Mar 2024 16:33:56 +0800 Subject: [PATCH 0984/1197] feat(net): optimize block processing logic (#5754) feat(net): optimize block processing logic --- .../net/messagehandler/BlockMsgHandler.java | 16 +++++++++------- .../messagehandler/PbftDataSyncHandler.java | 18 +++++++++++++----- .../net/messagehandler/PbftMsgHandler.java | 3 +++ .../PbftDataSyncHandlerTest.java | 7 ++++--- .../net/messagehandler/PbftMsgHandlerTest.java | 9 +++++++++ 5 files changed, 38 insertions(+), 15 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java index 9bb746346a6..14523df86a5 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java @@ -125,6 +125,14 @@ private void check(PeerConnection peer, BlockMessage msg) throws P2pException { private void processBlock(PeerConnection peer, BlockCapsule block) throws P2pException { BlockId blockId = block.getBlockId(); + boolean flag = tronNetDelegate.validBlock(block); + if (!flag) { + logger.warn("Receive a bad block from {}, {}, {}", + peer.getInetSocketAddress(), blockId.getString(), + Hex.toHexString(block.getWitnessAddress().toByteArray())); + return; + } + if (!tronNetDelegate.containBlock(block.getParentBlockId())) { logger.warn("Get unlink block {} from {}, head is {}", blockId.getString(), peer.getInetAddress(), tronNetDelegate.getHeadBlockId().getString()); @@ -138,16 +146,10 @@ private void processBlock(PeerConnection peer, BlockCapsule block) throws P2pExc return; } - boolean flag = tronNetDelegate.validBlock(block); - if (flag) { - broadcast(new BlockMessage(block)); - } + broadcast(new BlockMessage(block)); try { tronNetDelegate.processBlock(block, false); - if (!flag) { - broadcast(new BlockMessage(block)); - } witnessProductBlockService.validWitnessProductTwoBlock(block); diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java index 60f614632a4..d66fa6d41f7 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java @@ -1,5 +1,7 @@ package org.tron.core.net.messagehandler; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import com.google.common.collect.Sets; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; @@ -8,12 +10,11 @@ import java.security.SignatureException; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -37,7 +38,9 @@ @Service public class PbftDataSyncHandler implements TronMsgHandler, Closeable { - private Map pbftCommitMessageCache = new ConcurrentHashMap<>(); + private static final Cache pbftCommitMessageCache = + CacheBuilder.newBuilder().initialCapacity(100).maximumSize(200) + .expireAfterWrite(10, TimeUnit.MINUTES).build(); private final String esName = "valid-header-pbft-sign"; @@ -51,6 +54,9 @@ public class PbftDataSyncHandler implements TronMsgHandler, Closeable { public void processMessage(PeerConnection peer, TronMessage msg) throws P2pException { PbftCommitMessage pbftCommitMessage = (PbftCommitMessage) msg; try { + if (!chainBaseManager.getDynamicPropertiesStore().allowPBFT()) { + return; + } Raw raw = Raw.parseFrom(pbftCommitMessage.getPBFTCommitResult().getData()); pbftCommitMessageCache.put(raw.getViewN(), pbftCommitMessage); } catch (InvalidProtocolBufferException e) { @@ -64,7 +70,8 @@ public void processPBFTCommitData(BlockCapsule block) { return; } long epoch = 0; - PbftCommitMessage pbftCommitMessage = pbftCommitMessageCache.remove(block.getNum()); + PbftCommitMessage pbftCommitMessage = pbftCommitMessageCache.getIfPresent(block.getNum()); + pbftCommitMessageCache.invalidate(block.getNum()); long maintenanceTimeInterval = chainBaseManager.getDynamicPropertiesStore() .getMaintenanceTimeInterval(); if (pbftCommitMessage == null) { @@ -75,7 +82,8 @@ public void processPBFTCommitData(BlockCapsule block) { Raw raw = Raw.parseFrom(pbftCommitMessage.getPBFTCommitResult().getData()); epoch = raw.getEpoch(); } - pbftCommitMessage = pbftCommitMessageCache.remove(epoch); + pbftCommitMessage = pbftCommitMessageCache.getIfPresent(epoch); + pbftCommitMessageCache.invalidate(epoch); if (pbftCommitMessage != null) { processPBFTCommitMessage(pbftCommitMessage); } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/PbftMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/PbftMsgHandler.java index 4e4cc858898..d086cc28b6c 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/PbftMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/PbftMsgHandler.java @@ -33,6 +33,9 @@ public class PbftMsgHandler { private TronNetDelegate tronNetDelegate; public void processMessage(PeerConnection peer, PbftMessage msg) throws Exception { + if (!tronNetDelegate.allowPBFT()) { + return; + } if (Param.getInstance().getPbftInterface().isSyncing()) { return; } diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/PbftDataSyncHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/PbftDataSyncHandlerTest.java index d1fdfaa5d90..e5d242a6c4d 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/PbftDataSyncHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/PbftDataSyncHandlerTest.java @@ -32,9 +32,6 @@ public void testProcessMessage() throws Exception { Protocol.PBFTMessage.Raw raw = rawBuilder.build(); PbftSignCapsule pbftSignCapsule = new PbftSignCapsule(raw.toByteString(), new ArrayList<>()); PbftCommitMessage pbftCommitMessage = new PbftCommitMessage(pbftSignCapsule); - pbftDataSyncHandler.processMessage(null, pbftCommitMessage); - Assert.assertEquals(Protocol.PBFTMessage.Raw.parseFrom( - pbftCommitMessage.getPBFTCommitResult().getData()).getViewN(), 1); DynamicPropertiesStore dynamicPropertiesStore = Mockito.mock(DynamicPropertiesStore.class); PbftSignDataStore pbftSignDataStore = Mockito.mock(PbftSignDataStore.class); @@ -48,6 +45,10 @@ public void testProcessMessage() throws Exception { field.setAccessible(true); field.set(pbftDataSyncHandler, chainBaseManager); + pbftDataSyncHandler.processMessage(null, pbftCommitMessage); + Assert.assertEquals(Protocol.PBFTMessage.Raw.parseFrom( + pbftCommitMessage.getPBFTCommitResult().getData()).getViewN(), 1); + pbftDataSyncHandler.processPBFTCommitData(blockCapsule); Field field1 = PbftDataSyncHandler.class.getDeclaredField("pbftCommitMessageCache"); field1.setAccessible(true); diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java index 3fec10fc163..8b9d1969cfc 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java @@ -34,6 +34,7 @@ import org.tron.core.net.message.MessageTypes; import org.tron.core.net.peer.PeerConnection; import org.tron.core.net.peer.PeerManager; +import org.tron.core.store.DynamicPropertiesStore; import org.tron.p2p.P2pConfig; import org.tron.p2p.base.Parameter; import org.tron.p2p.connection.Channel; @@ -116,6 +117,14 @@ public void testPbft() throws Exception { Assert.assertEquals(P2pException.TypeEnum.BAD_MESSAGE, e.getType()); } + DynamicPropertiesStore dynamicPropertiesStore = context.getBean(DynamicPropertiesStore.class); + dynamicPropertiesStore.saveAllowPBFT(1); + try { + context.getBean(PbftMsgHandler.class).processMessage(peer, pbftMessage); + } catch (P2pException e) { + Assert.assertEquals(P2pException.TypeEnum.BAD_MESSAGE, e.getType()); + } + Assert.assertEquals(1, PeerManager.getPeers().size()); } } From 9532bc028f228b3fb66a7b0cca56db47cefaad0c Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 15 Mar 2024 11:50:54 +0800 Subject: [PATCH 0985/1197] remove unused test --- .../org/tron/common/cache/CacheManagerTest.java | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 framework/src/main/java/org/tron/common/cache/CacheManagerTest.java diff --git a/framework/src/main/java/org/tron/common/cache/CacheManagerTest.java b/framework/src/main/java/org/tron/common/cache/CacheManagerTest.java deleted file mode 100644 index b02b135552a..00000000000 --- a/framework/src/main/java/org/tron/common/cache/CacheManagerTest.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.tron.common.cache; - -import org.junit.Assert; -import org.junit.Test; - -public class CacheManagerTest { - - @Test - public void allocate() { - String strategy = String.format(CacheStrategies.PATTERNS, 1, 1, "30s", 1); - TronCache cache = CacheManager.allocate(CacheType.witnessStandby, strategy); - Assert.assertNull(cache.getIfPresent("test")); - } -} From 071f42065a02d1c5cc6cd834052eb3a5bae0fad5 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 15 Mar 2024 16:56:31 +0800 Subject: [PATCH 0986/1197] update a new version. version name:GreatVoyage-v4.7.3.1-78-ge84a9e778,version code:18260 --- framework/src/main/java/org/tron/program/Version.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 6f26752524c..483f5be713f 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,8 +2,8 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.7.3-5-g788136ebe"; - public static final String VERSION_CODE = "18180"; + public static final String VERSION_NAME = "GreatVoyage-v4.7.3.1-78-ge84a9e778"; + public static final String VERSION_CODE = "18260"; private static final String VERSION = "4.7.4"; public static String getVersion() { From 88bd6341a85274112ab7968b0eec29126e754bff Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Mon, 18 Mar 2024 15:20:45 +0800 Subject: [PATCH 0987/1197] docs(issue/template): update issue template for feature (#5774) add background,specification,test specification and scope of impact --- .github/ISSUE_TEMPLATE/request-a-feature.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/request-a-feature.md b/.github/ISSUE_TEMPLATE/request-a-feature.md index 5099a72008b..261f1088ded 100644 --- a/.github/ISSUE_TEMPLATE/request-a-feature.md +++ b/.github/ISSUE_TEMPLATE/request-a-feature.md @@ -6,13 +6,23 @@ labels: 'type:feature' assignees: '' --- +# Background # Rationale Why should this feature exist? + What are the use-cases? +# Specification + +# Test Specification + +# Scope Of Impact + + # Implementation Do you have ideas regarding the implementation of this feature? + Are you willing to implement this feature? From a126f2e40f207e0076811a6a821aa446447d0821 Mon Sep 17 00:00:00 2001 From: Casper Date: Mon, 18 Mar 2024 19:06:49 +0800 Subject: [PATCH 0988/1197] feat(docs): Update quickstart.md (#5773) --- quickstart.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index 7dc2d1009fb..6eda855f1e9 100644 --- a/quickstart.md +++ b/quickstart.md @@ -28,8 +28,9 @@ cd java-tron #### Build the docker image -Use below command to start the build: +Use the command below to navigate to the docker directory and start the build: ``` +cd docker docker build -t tronprotocol/java-tron . ``` From 40d7f2695c754ce6ae8c1191dfcbc0027c90bc34 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Thu, 28 Mar 2024 17:48:28 +0800 Subject: [PATCH 0989/1197] docs(issue/template): update issue template for bug (#5785) --- .github/ISSUE_TEMPLATE/report-a-bug.md | 36 +++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/report-a-bug.md b/.github/ISSUE_TEMPLATE/report-a-bug.md index cfadd364c21..d3cd98beeef 100644 --- a/.github/ISSUE_TEMPLATE/report-a-bug.md +++ b/.github/ISSUE_TEMPLATE/report-a-bug.md @@ -7,20 +7,50 @@ assignees: '' --- + + + + #### System information -java-tron version: `java -jar FullNode.jar -v` -OS & Version: Windows/Linux/OSX -Commit hash : (if `develop`) + +**Versions** +* Software version: [`java -jar FullNode.jar -v`] +* Java version: [`java -version`] +* OS Name & Version: [`cat /etc/*release`] +* Kernel Version: [`uname -a`] +* Virtual Machine software & version: [`vmware -v`] +* Docker Version: [`docker version`] +* Cloud VM, type, size: [Amazon Web Services I3-large] +* Node Type: [e.g. fullNode, liteFullNode] +* Blockchain Net: [e.g. main, test or private ] +* Commit hash : [if `develop`] + +**Smart contract information (If you're reporting an issue arising from deploying or calling a smart contract, please supply related information)** +* Solidity version [`solc --version`] +* Repo with minimal set of deployable/reproducible contract code - please provide a link +* Please include specifics on how you are deploying/calling the contract + +**Additional Information (Add any of the following or anything else that may be relevant)** +* setup info - startup script, config options +* System info - memory、 CPU、network bandwidth, disk type- #### Expected behaviour + #### Actual behaviour + + +#### Frequency + #### Steps to reproduce the behaviour +1. [Step 1] +2. [Step 2] +3. [Step ...] #### Backtrace From 20f02116146972912d0171209c3730f33351c7d2 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 19 Apr 2024 14:14:06 +0800 Subject: [PATCH 0990/1197] docs(issue/template): simplify issue template for bug --- .github/ISSUE_TEMPLATE/report-a-bug.md | 35 +++++++++----------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/report-a-bug.md b/.github/ISSUE_TEMPLATE/report-a-bug.md index d3cd98beeef..a0d68121565 100644 --- a/.github/ISSUE_TEMPLATE/report-a-bug.md +++ b/.github/ISSUE_TEMPLATE/report-a-bug.md @@ -11,29 +11,18 @@ assignees: '' -#### System information - - -**Versions** -* Software version: [`java -jar FullNode.jar -v`] -* Java version: [`java -version`] -* OS Name & Version: [`cat /etc/*release`] -* Kernel Version: [`uname -a`] -* Virtual Machine software & version: [`vmware -v`] -* Docker Version: [`docker version`] -* Cloud VM, type, size: [Amazon Web Services I3-large] -* Node Type: [e.g. fullNode, liteFullNode] -* Blockchain Net: [e.g. main, test or private ] -* Commit hash : [if `develop`] - -**Smart contract information (If you're reporting an issue arising from deploying or calling a smart contract, please supply related information)** -* Solidity version [`solc --version`] -* Repo with minimal set of deployable/reproducible contract code - please provide a link -* Please include specifics on how you are deploying/calling the contract - -**Additional Information (Add any of the following or anything else that may be relevant)** -* setup info - startup script, config options -* System info - memory、 CPU、network bandwidth, disk type- +#### Software Versions + + + #### Expected behaviour From 963868e44655737235106b6258f6f06b4413a956 Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 22 Apr 2024 11:34:42 +0800 Subject: [PATCH 0991/1197] docs(params): fix parameter descriptions for minTimeRatio and maxTimeRatio --- .../main/java/org/tron/common/parameter/CommonParameter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 95a1eb2d0ae..f9562e580e3 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -68,12 +68,12 @@ public class CommonParameter { @Getter @Setter @Parameter(names = {"--min-time-ratio"}, description = "Maximum CPU tolerance when executing " - + "non-timeout transactions while synchronizing blocks. (default: 5.0)") + + "timeout transactions while synchronizing blocks. (default: 0.0)") public double minTimeRatio = 0.0; @Getter @Setter @Parameter(names = {"--max-time-ratio"}, description = "Maximum CPU tolerance when executing " - + "timeout transactions while synchronizing blocks. (default: 0.0)") + + "non-timeout transactions while synchronizing blocks. (default: 5.0)") public double maxTimeRatio = calcMaxTimeRatio(); @Getter @Setter From 428ede2e5d3351167608634a972258c36061e601 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Sun, 28 Apr 2024 16:52:07 +0800 Subject: [PATCH 0992/1197] feat(consensus): optimize block production logic --- .../src/main/java/org/tron/consensus/dpos/DposTask.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java b/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java index 537fe49ae65..8d5697cdc89 100644 --- a/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java +++ b/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java @@ -91,6 +91,11 @@ private State produceBlock() { try { synchronized (dposService.getBlockHandle().getLock()) { + state = stateManager.getState(); + if (!State.OK.equals(state)) { + return state; + } + long slot = dposSlot.getSlot(System.currentTimeMillis() + 50); if (slot == 0) { return State.NOT_TIME_YET; From 8b4a5dddf31e49b7c86777b2a6efe609702fb825 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Sun, 28 Apr 2024 17:01:40 +0800 Subject: [PATCH 0993/1197] fix(net): solve the problem of concurrent access to syncBlockToFetch object --- .../java/org/tron/core/net/service/sync/SyncService.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 1e3e18441b9..9453700df0d 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -321,8 +321,9 @@ private void processSyncBlock(BlockCapsule block, PeerConnection peerConnection) } for (PeerConnection peer : tronNetDelegate.getActivePeer()) { - if (blockId.equals(peer.getSyncBlockToFetch().peek())) { - peer.getSyncBlockToFetch().pop(); + BlockId bid = peer.getSyncBlockToFetch().peek(); + if (blockId.equals(bid)) { + peer.getSyncBlockToFetch().remove(bid); if (flag) { peer.setBlockBothHave(blockId); if (peer.getSyncBlockToFetch().isEmpty() && peer.isFetchAble()) { From 934e04bc8ec840431a82791ba12d6b765eb018c8 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Sun, 28 Apr 2024 16:48:42 +0800 Subject: [PATCH 0994/1197] feat(net): optimize block message processing logic --- .../net/messagehandler/BlockMsgHandler.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java index 14523df86a5..623b0140701 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java @@ -61,6 +61,18 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep BlockMessage blockMessage = (BlockMessage) msg; BlockId blockId = blockMessage.getBlockId(); + BlockCapsule blockCapsule = blockMessage.getBlockCapsule(); + if (blockCapsule.getInstance().getSerializedSize() > maxBlockSize) { + logger.error("Receive bad block {} from peer {}, block size over limit", + blockMessage.getBlockId(), peer.getInetSocketAddress()); + throw new P2pException(TypeEnum.BAD_MESSAGE, "block size over limit"); + } + long gap = blockCapsule.getTimeStamp() - System.currentTimeMillis(); + if (gap >= BLOCK_PRODUCED_INTERVAL) { + logger.error("Receive bad block {} from peer {}, block time error", + blockMessage.getBlockId(), peer.getInetSocketAddress()); + throw new P2pException(TypeEnum.BAD_MESSAGE, "block time error"); + } if (!fastForward && !peer.isRelayPeer()) { check(peer, blockMessage); } @@ -109,18 +121,6 @@ private void check(PeerConnection peer, BlockMessage msg) throws P2pException { msg.getBlockId(), peer.getInetSocketAddress()); throw new P2pException(TypeEnum.BAD_MESSAGE, "no request"); } - BlockCapsule blockCapsule = msg.getBlockCapsule(); - if (blockCapsule.getInstance().getSerializedSize() > maxBlockSize) { - logger.error("Receive bad block {} from peer {}, block size over limit", - msg.getBlockId(), peer.getInetSocketAddress()); - throw new P2pException(TypeEnum.BAD_MESSAGE, "block size over limit"); - } - long gap = blockCapsule.getTimeStamp() - System.currentTimeMillis(); - if (gap >= BLOCK_PRODUCED_INTERVAL) { - logger.error("Receive bad block {} from peer {}, block time error", - msg.getBlockId(), peer.getInetSocketAddress()); - throw new P2pException(TypeEnum.BAD_MESSAGE, "block time error"); - } } private void processBlock(PeerConnection peer, BlockCapsule block) throws P2pException { From 089fa8a76a8dac38413318b2efe31770933649c0 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Sun, 28 Apr 2024 16:59:27 +0800 Subject: [PATCH 0995/1197] fix(net): solve the problem of concurrent access to fetchBlockInfo object --- .../tron/core/net/service/fetchblock/FetchBlockService.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java b/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java index 889f6f6e132..bda2646abbc 100644 --- a/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java +++ b/framework/src/main/java/org/tron/core/net/service/fetchblock/FetchBlockService.java @@ -71,9 +71,10 @@ public void fetchBlock(List sha256HashList, PeerConnection peer) { sha256HashList.stream().filter(sha256Hash -> new BlockCapsule.BlockId(sha256Hash).getNum() == chainBaseManager.getHeadBlockNum() + 1) .findFirst().ifPresent(sha256Hash -> { - fetchBlockInfo = new FetchBlockInfo(sha256Hash, peer, System.currentTimeMillis()); + long now = System.currentTimeMillis(); + fetchBlockInfo = new FetchBlockInfo(sha256Hash, peer, now); logger.info("Set fetchBlockInfo, block: {}, peer: {}, time: {}", sha256Hash, - fetchBlockInfo.getPeer().getInetAddress(), fetchBlockInfo.getTime()); + peer.getInetAddress(), now); }); } From e6f14edf37f60fc178eaa5796a3f5d2429a0a1c1 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 20 May 2024 14:20:31 +0800 Subject: [PATCH 0996/1197] test(plugins/DbCopy): solve directory creation failure due to limited permissions --- plugins/src/test/java/org/tron/plugins/DbCopyTest.java | 6 +++--- plugins/src/test/java/org/tron/plugins/DbTest.java | 10 ++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/plugins/src/test/java/org/tron/plugins/DbCopyTest.java b/plugins/src/test/java/org/tron/plugins/DbCopyTest.java index c5cc8f2bb31..9e488a592aa 100644 --- a/plugins/src/test/java/org/tron/plugins/DbCopyTest.java +++ b/plugins/src/test/java/org/tron/plugins/DbCopyTest.java @@ -11,7 +11,7 @@ public class DbCopyTest extends DbTest { @Test public void testRun() { String[] args = new String[] { "db", "cp", INPUT_DIRECTORY, - tmpDir + UUID.randomUUID()}; + genarateTmpDir()}; Assert.assertEquals(0, cli.execute(args)); } @@ -32,7 +32,7 @@ public void testNotExist() { @Test public void testEmpty() throws IOException { String[] args = new String[] {"db", "cp", temporaryFolder.newFolder().toString(), - tmpDir + UUID.randomUUID()}; + genarateTmpDir()}; Assert.assertEquals(0, cli.execute(args)); } @@ -46,7 +46,7 @@ public void testDestIsExist() throws IOException { @Test public void testSrcIsFile() throws IOException { String[] args = new String[] {"db", "cp", temporaryFolder.newFile().toString(), - tmpDir + UUID.randomUUID()}; + genarateTmpDir()}; Assert.assertEquals(403, cli.execute(args)); } diff --git a/plugins/src/test/java/org/tron/plugins/DbTest.java b/plugins/src/test/java/org/tron/plugins/DbTest.java index 8a5f9de4a67..8605fa18d50 100644 --- a/plugins/src/test/java/org/tron/plugins/DbTest.java +++ b/plugins/src/test/java/org/tron/plugins/DbTest.java @@ -86,4 +86,14 @@ private static void initDB(File file) throws IOException { } } } + + /** + * Generate a not-exist temporary directory path. + * @return temporary path + */ + public String genarateTmpDir() { + File dir = Paths.get(tmpDir, UUID.randomUUID().toString()).toFile(); + dir.deleteOnExit(); + return dir.getPath(); + } } From 9cc15de61a8db733852549de351d2ace645dbdcc Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Thu, 30 May 2024 10:23:53 +0800 Subject: [PATCH 0997/1197] feat(consensus): add unit test for DposTask --- .../org/tron/core/consensus/DposTaskTest.java | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/consensus/DposTaskTest.java diff --git a/framework/src/test/java/org/tron/core/consensus/DposTaskTest.java b/framework/src/test/java/org/tron/core/consensus/DposTaskTest.java new file mode 100644 index 00000000000..89d887d5fe9 --- /dev/null +++ b/framework/src/test/java/org/tron/core/consensus/DposTaskTest.java @@ -0,0 +1,64 @@ +package org.tron.core.consensus; + +import static org.mockito.Mockito.mock; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; +import org.tron.consensus.base.BlockHandle; +import org.tron.consensus.base.State; +import org.tron.consensus.dpos.DposService; +import org.tron.consensus.dpos.DposSlot; +import org.tron.consensus.dpos.DposTask; +import org.tron.consensus.dpos.StateManager; + +public class DposTaskTest { + private DposTask dposTask = new DposTask(); + + @Test + public void tet() throws Exception { + StateManager stateManager = mock(StateManager.class); + Mockito.when(stateManager.getState()).thenReturn(State.BACKUP_IS_NOT_MASTER); + + Field field = dposTask.getClass().getDeclaredField("stateManager"); + field.setAccessible(true); + field.set(dposTask, stateManager); + + Method method = dposTask.getClass().getDeclaredMethod("produceBlock"); + method.setAccessible(true); + State state = (State) method.invoke(dposTask); + + Assert.assertEquals(State.BACKUP_IS_NOT_MASTER, state); + + + Mockito.when(stateManager.getState()).thenReturn(State.OK); + + DposSlot dposSlot = mock(DposSlot.class); + Mockito.when(dposSlot.getTime(1)).thenReturn(Long.MAX_VALUE); + + field = dposTask.getClass().getDeclaredField("dposSlot"); + field.setAccessible(true); + field.set(dposTask, dposSlot); + + + Mockito.when(stateManager.getState()).thenReturn(State.OK); + + BlockHandle blockHandle = mock(BlockHandle.class); + Mockito.when(blockHandle.getLock()).thenReturn(new Object()); + + + DposService dposService = mock(DposService.class); + Mockito.when(dposService.getBlockHandle()).thenReturn(blockHandle); + + field = dposTask.getClass().getDeclaredField("dposService"); + field.setAccessible(true); + field.set(dposTask, dposService); + + state = (State) method.invoke(dposTask); + + Assert.assertEquals(State.NOT_TIME_YET, state); + } + +} From b311f9a6d0c4faf84eec61451c12b66432e684f2 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Thu, 30 May 2024 10:32:54 +0800 Subject: [PATCH 0998/1197] feat(net): remove redundant code --- .../org/tron/core/net/messagehandler/BlockMsgHandler.java | 7 ------- .../java/org/tron/core/net/service/adv/AdvService.java | 1 - 2 files changed, 8 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java index 14523df86a5..66ebeaa641a 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java @@ -150,14 +150,7 @@ private void processBlock(PeerConnection peer, BlockCapsule block) throws P2pExc try { tronNetDelegate.processBlock(block, false); - witnessProductBlockService.validWitnessProductTwoBlock(block); - - tronNetDelegate.getActivePeer().forEach(p -> { - if (p.getAdvInvReceive().getIfPresent(blockId) != null) { - p.setBlockBothHave(blockId); - } - }); } catch (Exception e) { logger.warn("Process adv block {} from peer {} failed. reason: {}", blockId, peer.getInetAddress(), e.getMessage()); diff --git a/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java b/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java index ea608c1ea86..505b53358c8 100644 --- a/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java +++ b/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java @@ -200,7 +200,6 @@ public void broadcast(Message msg) { logger.info("Ready to broadcast block {}", blockMsg.getBlockId().getString()); blockMsg.getBlockCapsule().getTransactions().forEach(transactionCapsule -> { Sha256Hash tid = transactionCapsule.getTransactionId(); - invToSpread.remove(tid); trxCache.put(new Item(tid, InventoryType.TRX), new TransactionMessage(transactionCapsule.getInstance())); }); From 9378787b8b8e2139ab3644d9bf335ec262a73836 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 30 May 2024 11:42:11 +0800 Subject: [PATCH 0999/1197] feat(version): update version to 4.7.5 --- framework/src/main/java/org/tron/program/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 483f5be713f..ee624f6078a 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -4,7 +4,7 @@ public class Version { public static final String VERSION_NAME = "GreatVoyage-v4.7.3.1-78-ge84a9e778"; public static final String VERSION_CODE = "18260"; - private static final String VERSION = "4.7.4"; + private static final String VERSION = "4.7.5"; public static String getVersion() { return VERSION; From e434b28444934c7d39e1dd1f0d5b734b92f33cdc Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 29 May 2024 22:53:27 +0800 Subject: [PATCH 1000/1197] feat(validate): validate account creation transaction size --- .../org/tron/core/utils/ProposalUtil.java | 19 ++++++- .../tron/core/capsule/TransactionCapsule.java | 3 ++ .../org/tron/core/db/BandwidthProcessor.java | 18 +++++-- .../org/tron/core/db/ResourceProcessor.java | 3 +- .../core/store/DynamicPropertiesStore.java | 14 ++++++ .../common/parameter/CommonParameter.java | 4 ++ .../src/main/java/org/tron/core/Constant.java | 3 ++ .../java/org/tron/core/config/Parameter.java | 5 +- .../src/main/java/org/tron/core/Wallet.java | 5 ++ .../tron/core/consensus/ProposalService.java | 4 ++ .../main/java/org/tron/core/db/Manager.java | 3 +- .../vm/BandWidthRuntimeOutOfTimeTest.java | 4 +- ...andWidthRuntimeOutOfTimeWithCheckTest.java | 4 +- .../runtime/vm/BandWidthRuntimeTest.java | 4 +- .../vm/BandWidthRuntimeWithCheckTest.java | 3 +- .../org/tron/core/BandwidthProcessorTest.java | 7 +++ .../actuator/ProposalCreateActuatorTest.java | 50 +++++++++++++++++++ .../org/tron/core/config/args/ArgsTest.java | 1 + 18 files changed, 142 insertions(+), 12 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index cfec5b09d96..c82ed0a8302 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -1,5 +1,7 @@ package org.tron.core.utils; +import static org.tron.core.Constant.CREATE_ACCOUNT_TRANSACTION_MAX_BYTE_SIZE; +import static org.tron.core.Constant.CREATE_ACCOUNT_TRANSACTION_MIN_BYTE_SIZE; import static org.tron.core.Constant.DYNAMIC_ENERGY_INCREASE_FACTOR_RANGE; import static org.tron.core.Constant.DYNAMIC_ENERGY_MAX_FACTOR_RANGE; import static org.tron.core.config.Parameter.ChainConstant.ONE_YEAR_BLOCK_NUMBERS; @@ -748,6 +750,20 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case MAX_CREATE_ACCOUNT_TX_SIZE: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7_5)) { + throw new ContractValidateException( + "Bad chain parameter id [MAX_CREATE_ACCOUNT_TX_SIZE]"); + } + if (value < CREATE_ACCOUNT_TRANSACTION_MIN_BYTE_SIZE + || value > CREATE_ACCOUNT_TRANSACTION_MAX_BYTE_SIZE) { + throw new ContractValidateException( + "This value[MAX_CREATE_ACCOUNT_TX_SIZE] is only allowed to be greater than or equal " + + "to " + CREATE_ACCOUNT_TRANSACTION_MIN_BYTE_SIZE + " and less than or equal to " + + CREATE_ACCOUNT_TRANSACTION_MAX_BYTE_SIZE + "!"); + } + break; + } default: break; } @@ -824,7 +840,8 @@ public enum ProposalType { // current value, value range ALLOW_TVM_SHANGHAI(76), // 0, 1 ALLOW_CANCEL_ALL_UNFREEZE_V2(77), // 0, 1 MAX_DELEGATE_LOCK_PERIOD(78), // (86400, 10512000] - ALLOW_OLD_REWARD_OPT(79); // 0, 1 + ALLOW_OLD_REWARD_OPT(79), // 0, 1 + MAX_CREATE_ACCOUNT_TX_SIZE(82); // [500, 10000] private long code; diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java index a588b28c748..f897e5d848a 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -114,6 +114,9 @@ public class TransactionCapsule implements ProtoCapsule { @Getter @Setter private boolean isTransactionCreate = false; + @Getter + @Setter + private boolean isInBlock = false; public byte[] getOwnerAddress() { if (this.ownerAddress == null) { diff --git a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java index f13002f2dfa..d6da5904aa3 100644 --- a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -1,8 +1,10 @@ package org.tron.core.db; +import static org.tron.core.Constant.PER_SIGN_LENGTH; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import static org.tron.protos.Protocol.Transaction.Contract.ContractType.ShieldedTransferContract; import static org.tron.protos.Protocol.Transaction.Contract.ContractType.TransferAssetContract; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; import com.google.protobuf.ByteString; import java.util.HashMap; @@ -19,13 +21,12 @@ import org.tron.core.capsule.TransactionCapsule; import org.tron.core.exception.AccountResourceInsufficientException; import org.tron.core.exception.ContractValidateException; +import org.tron.core.exception.TooBigTransactionException; import org.tron.core.exception.TooBigTransactionResultException; import org.tron.protos.Protocol.Transaction.Contract; import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; import org.tron.protos.contract.BalanceContract.TransferContract; -import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; - @Slf4j(topic = "DB") public class BandwidthProcessor extends ResourceProcessor { @@ -95,7 +96,7 @@ public void updateUsage(AssetIssueCapsule assetIssueCapsule, long now) { @Override public void consume(TransactionCapsule trx, TransactionTrace trace) throws ContractValidateException, AccountResourceInsufficientException, - TooBigTransactionResultException { + TooBigTransactionResultException, TooBigTransactionException { List contracts = trx.getInstance().getRawData().getContractList(); if (trx.getResultSerializedSize() > Constant.MAX_RESULT_SIZE_IN_TX * contracts.size()) { throw new TooBigTransactionResultException(); @@ -127,6 +128,17 @@ public void consume(TransactionCapsule trx, TransactionTrace trace) } long now = chainBaseManager.getHeadSlot(); if (contractCreateNewAccount(contract)) { + if (!trx.isInBlock()) { + long maxCreateAccountTxSize = dynamicPropertiesStore.getMaxCreateAccountTxSize(); + int signatureCount = trx.getInstance().getSignatureCount(); + long createAccountBytesSize = trx.getInstance().toBuilder().clearRet() + .build().getSerializedSize() - (signatureCount * PER_SIGN_LENGTH); + if (createAccountBytesSize > maxCreateAccountTxSize) { + throw new TooBigTransactionException(String.format( + "Too big new account transaction, TxId %s, the size is %d bytes, maxTxSize %d", + trx.getTransactionId(), createAccountBytesSize, maxCreateAccountTxSize)); + } + } consumeForCreateNewAccount(accountCapsule, bytesSize, now, trace); continue; } diff --git a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java index a7a22390958..c1875408850 100644 --- a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java @@ -11,6 +11,7 @@ import org.tron.core.exception.AccountResourceInsufficientException; import org.tron.core.exception.BalanceInsufficientException; import org.tron.core.exception.ContractValidateException; +import org.tron.core.exception.TooBigTransactionException; import org.tron.core.exception.TooBigTransactionResultException; import org.tron.core.store.AccountStore; import org.tron.core.store.DynamicPropertiesStore; @@ -35,7 +36,7 @@ protected ResourceProcessor(DynamicPropertiesStore dynamicPropertiesStore, } abstract void consume(TransactionCapsule trx, TransactionTrace trace) - throws ContractValidateException, AccountResourceInsufficientException, TooBigTransactionResultException; + throws ContractValidateException, AccountResourceInsufficientException, TooBigTransactionResultException, TooBigTransactionException; protected long increase(long lastUsage, long usage, long lastTime, long now) { return increase(lastUsage, usage, lastTime, now, windowSize); diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index bf788232640..57a21753b9a 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -219,6 +219,8 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_OLD_REWARD_OPT = "ALLOW_OLD_REWARD_OPT".getBytes(); + private static final byte[] MAX_CREATE_ACCOUNT_TX_SIZE = "MAX_CREATE_ACCOUNT_TX_SIZE".getBytes(); + @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { super(dbName); @@ -2850,6 +2852,18 @@ public long getAllowOldRewardOpt() { .orElse(CommonParameter.getInstance().getAllowOldRewardOpt()); } + public void saveMaxCreateAccountTxSize(long maxCreateAccountTxSize) { + this.put(MAX_CREATE_ACCOUNT_TX_SIZE, + new BytesCapsule(ByteArray.fromLong(maxCreateAccountTxSize))); + } + + public long getMaxCreateAccountTxSize() { + return Optional.ofNullable(getUnchecked(MAX_CREATE_ACCOUNT_TX_SIZE)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElse(CommonParameter.getInstance().getMaxCreateAccountTxSize()); + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index f9562e580e3..d511f6b0d49 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -666,6 +666,10 @@ public class CommonParameter { @Setter public long allowOldRewardOpt; + @Getter + @Setter + public long maxCreateAccountTxSize = 1000L; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 2cd9ea95f15..729f59c8317 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -24,6 +24,8 @@ public class Constant { // config for transaction public static final long TRANSACTION_MAX_BYTE_SIZE = 500 * 1_024L; + public static final int CREATE_ACCOUNT_TRANSACTION_MIN_BYTE_SIZE = 500; + public static final int CREATE_ACCOUNT_TRANSACTION_MAX_BYTE_SIZE = 10000; public static final long MAXIMUM_TIME_UNTIL_EXPIRATION = 24 * 60 * 60 * 1_000L; //one day public static final long TRANSACTION_DEFAULT_EXPIRATION_TIME = 60 * 1_000L; //60 seconds public static final long TRANSACTION_FEE_POOL_PERIOD = 1; //1 blocks @@ -31,6 +33,7 @@ public class Constant { public static final long SUN_PER_ENERGY = 100; // 1 us = 100 SUN = 100 * 10^-6 TRX public static final long ENERGY_LIMIT_IN_CONSTANT_TX = 3_000_000L; // ref: 1 us = 1 energy public static final long MAX_RESULT_SIZE_IN_TX = 64; // max 8 * 8 items in result + public static final long PER_SIGN_LENGTH = 65L; public static final long PB_DEFAULT_ENERGY_LIMIT = 0L; public static final long CREATOR_DEFAULT_ENERGY_LIMIT = 1000 * 10_000L; diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index 247826af77a..027c225eb5d 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -23,7 +23,8 @@ public enum ForkBlockVersionEnum { VERSION_4_7(26, 1596780000000L, 80), VERSION_4_7_1(27, 1596780000000L, 80), VERSION_4_7_2(28, 1596780000000L, 80), - VERSION_4_7_4(29, 1596780000000L, 80); + VERSION_4_7_4(29, 1596780000000L, 80), + VERSION_4_7_5(30, 1596780000000L, 80); // if add a version, modify BLOCK_VERSION simultaneously @Getter @@ -72,7 +73,7 @@ public class ChainConstant { public static final int SINGLE_REPEAT = 1; public static final int BLOCK_FILLED_SLOTS_NUMBER = 128; public static final int MAX_FROZEN_NUMBER = 1; - public static final int BLOCK_VERSION = 29; + public static final int BLOCK_VERSION = 30; public static final long FROZEN_PERIOD = 86_400_000L; public static final long DELEGATE_PERIOD = 3 * 86_400_000L; public static final long TRX_PRECISION = 1000_000L; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 96af6fc7476..50dffcf3c83 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1334,6 +1334,11 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getAllowOldRewardOpt()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getMaxCreateAccountTxSize") + .setValue(dbManager.getDynamicPropertiesStore().getMaxCreateAccountTxSize()) + .build()); + return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 58da117cfc6..73628c6e2b9 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -359,6 +359,10 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveAllowOldRewardOpt(entry.getValue()); break; } + case MAX_CREATE_ACCOUNT_TX_SIZE: { + manager.getDynamicPropertiesStore().saveMaxCreateAccountTxSize(entry.getValue()); + break; + } default: find = false; break; diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 63bbef9ff7f..69265951ea8 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -966,7 +966,7 @@ public void consumeMemoFee(TransactionCapsule trx, TransactionTrace trace) public void consumeBandwidth(TransactionCapsule trx, TransactionTrace trace) throws ContractValidateException, AccountResourceInsufficientException, - TooBigTransactionResultException { + TooBigTransactionResultException, TooBigTransactionException { BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager); processor.consume(trx, trace); } @@ -1422,6 +1422,7 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block if (Objects.nonNull(blockCap)) { chainBaseManager.getBalanceTraceStore().initCurrentTransactionBalanceTrace(trxCap); + trxCap.setInBlock(true); } validateTapos(trxCap); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java index afac8cd7d22..30bba35b43c 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java @@ -33,6 +33,7 @@ import org.tron.core.exception.AccountResourceInsufficientException; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; +import org.tron.core.exception.TooBigTransactionException; import org.tron.core.exception.TooBigTransactionResultException; import org.tron.core.exception.TronException; import org.tron.core.exception.VMIllegalException; @@ -154,7 +155,8 @@ public void testSuccess() { private byte[] createContract() throws ContractValidateException, AccountResourceInsufficientException, - TooBigTransactionResultException, ContractExeException, VMIllegalException { + TooBigTransactionResultException, ContractExeException, VMIllegalException, + TooBigTransactionException { AccountCapsule owner = dbManager.getAccountStore() .get(Commons.decodeFromBase58Check(OwnerAddress)); long energy = owner.getEnergyUsage(); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java index 7203388f815..0eef2266f9d 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java @@ -34,6 +34,7 @@ import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; +import org.tron.core.exception.TooBigTransactionException; import org.tron.core.exception.TooBigTransactionResultException; import org.tron.core.exception.TronException; import org.tron.core.exception.VMIllegalException; @@ -156,7 +157,8 @@ public void testSuccess() { private byte[] createContract() throws ContractValidateException, AccountResourceInsufficientException, - TooBigTransactionResultException, ContractExeException, VMIllegalException { + TooBigTransactionResultException, ContractExeException, VMIllegalException, + TooBigTransactionException { AccountCapsule owner = dbManager.getAccountStore() .get(Commons.decodeFromBase58Check(OwnerAddress)); long energy = owner.getEnergyUsage(); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java index 40c5908c2dd..8b8e3a3c1eb 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java @@ -35,6 +35,7 @@ import org.tron.core.exception.AccountResourceInsufficientException; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; +import org.tron.core.exception.TooBigTransactionException; import org.tron.core.exception.TooBigTransactionResultException; import org.tron.core.exception.TronException; import org.tron.core.exception.VMIllegalException; @@ -186,7 +187,8 @@ public void testSuccessNoBandd() { private byte[] createContract() throws ContractValidateException, AccountResourceInsufficientException, - TooBigTransactionResultException, ContractExeException, VMIllegalException { + TooBigTransactionResultException, ContractExeException, VMIllegalException, + TooBigTransactionException { AccountCapsule owner = dbManager.getAccountStore() .get(Commons.decodeFromBase58Check(OwnerAddress)); long energy = owner.getEnergyUsage(); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java index e359e7eab1a..4b3331187e2 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java @@ -34,6 +34,7 @@ import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; +import org.tron.core.exception.TooBigTransactionException; import org.tron.core.exception.TooBigTransactionResultException; import org.tron.core.exception.TronException; import org.tron.core.exception.VMIllegalException; @@ -198,7 +199,7 @@ public void testSuccessNoBandWidth() { private byte[] createContract() throws ContractValidateException, AccountResourceInsufficientException, TooBigTransactionResultException, ContractExeException, ReceiptCheckErrException, - VMIllegalException { + VMIllegalException, TooBigTransactionException { AccountCapsule owner = dbManager.getAccountStore() .get(Commons.decodeFromBase58Check(OwnerAddress)); long energy = owner.getEnergyUsage(); diff --git a/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java b/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java index 300c202e11a..7d13892c635 100755 --- a/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java +++ b/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java @@ -19,6 +19,7 @@ import org.tron.core.db.TransactionTrace; import org.tron.core.exception.AccountResourceInsufficientException; import org.tron.core.exception.ContractValidateException; +import org.tron.core.exception.TooBigTransactionException; import org.tron.core.exception.TooBigTransactionResultException; import org.tron.core.store.StoreFactory; import org.tron.protos.Protocol; @@ -646,6 +647,8 @@ public void sameTokenNameCloseConsumeSuccess() { Assert.assertFalse(e instanceof TooBigTransactionResultException); } catch (AccountResourceInsufficientException e) { Assert.assertFalse(e instanceof AccountResourceInsufficientException); + } catch (TooBigTransactionException e) { + Assert.fail(); } finally { chainBaseManager.getAccountStore().delete(ByteArray.fromHexString(OWNER_ADDRESS)); chainBaseManager.getAccountStore().delete(ByteArray.fromHexString(TO_ADDRESS)); @@ -752,6 +755,8 @@ public void sameTokenNameOpenConsumeSuccess() { Assert.assertFalse(e instanceof TooBigTransactionResultException); } catch (AccountResourceInsufficientException e) { Assert.assertFalse(e instanceof AccountResourceInsufficientException); + } catch (TooBigTransactionException e) { + Assert.fail(); } finally { chainBaseManager.getAccountStore().delete(ByteArray.fromHexString(OWNER_ADDRESS)); chainBaseManager.getAccountStore().delete(ByteArray.fromHexString(TO_ADDRESS)); @@ -821,6 +826,8 @@ public void sameTokenNameCloseTransferToAccountNotExist() { Assert.assertFalse(e instanceof TooBigTransactionResultException); } catch (AccountResourceInsufficientException e) { Assert.assertFalse(e instanceof AccountResourceInsufficientException); + } catch (TooBigTransactionException e) { + Assert.fail(); } finally { chainBaseManager.getAccountStore().delete(ByteArray.fromHexString(OWNER_ADDRESS)); chainBaseManager.getAccountStore().delete(ByteArray.fromHexString(TO_ADDRESS)); diff --git a/framework/src/test/java/org/tron/core/actuator/ProposalCreateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ProposalCreateActuatorTest.java index a42a4ffbe5a..7210fe8d074 100644 --- a/framework/src/test/java/org/tron/core/actuator/ProposalCreateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ProposalCreateActuatorTest.java @@ -1,6 +1,10 @@ package org.tron.core.actuator; import static junit.framework.TestCase.fail; +import static org.junit.Assert.assertThrows; +import static org.tron.core.Constant.CREATE_ACCOUNT_TRANSACTION_MAX_BYTE_SIZE; +import static org.tron.core.Constant.CREATE_ACCOUNT_TRANSACTION_MIN_BYTE_SIZE; +import static org.tron.core.config.Parameter.ChainConstant.ONE_YEAR_BLOCK_NUMBERS; import com.google.protobuf.Any; import com.google.protobuf.ByteString; @@ -9,8 +13,10 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.mockito.Mockito; import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.ForkController; import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; @@ -279,6 +285,50 @@ public void invalidPara() { Assert.assertEquals("This value[REMOVE_THE_POWER_OF_THE_GR] is only allowed to be 1", e.getMessage()); } + // verify Proposal No. 78 + paras = new HashMap<>(); + paras.put(78L, 10L); + actuator = new ProposalCreateActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setForkUtils(dbManager.getChainBaseManager().getForkController()) + .setAny(getContract(OWNER_ADDRESS_FIRST, paras)); + assertThrows( + "Bad chain parameter id [MAX_DELEGATE_LOCK_PERIOD]", + ContractValidateException.class, actuator::validate); + + actuator = new ProposalCreateActuator(); + ForkController forkController = Mockito.mock(ForkController.class); + Mockito.when(forkController.pass(Mockito.any())).thenReturn(true); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setForkUtils(forkController) + .setAny(getContract(OWNER_ADDRESS_FIRST, paras)); + dbManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(86400L); + long maxDelegateLockPeriod = dbManager.getDynamicPropertiesStore().getMaxDelegateLockPeriod(); + assertThrows( + "This value[MAX_DELEGATE_LOCK_PERIOD] is only allowed to be greater than " + + maxDelegateLockPeriod + " and less than or equal to " + ONE_YEAR_BLOCK_NUMBERS + "!", + ContractValidateException.class, actuator::validate); + + // verify Proposal No. 82 + paras = new HashMap<>(); + paras.put(82L, 0L); + actuator = new ProposalCreateActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setForkUtils(dbManager.getChainBaseManager().getForkController()) + .setAny(getContract(OWNER_ADDRESS_FIRST, paras)); + assertThrows( + "Bad chain parameter id [ALLOW_ENERGY_ADJUSTMENT]", + ContractValidateException.class, actuator::validate); + + actuator = new ProposalCreateActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setForkUtils(forkController) + .setAny(getContract(OWNER_ADDRESS_FIRST, paras)); + assertThrows( + "This value[MAX_CREATE_ACCOUNT_TX_SIZE] is only allowed to be greater than or equal " + + "to " + CREATE_ACCOUNT_TRANSACTION_MIN_BYTE_SIZE + " and less than or equal to " + + CREATE_ACCOUNT_TRANSACTION_MAX_BYTE_SIZE + "!", + ContractValidateException.class, actuator::validate); } /** diff --git a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java index 52307d9d294..5bbf08fd96e 100644 --- a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java @@ -101,6 +101,7 @@ public void get() { Assert.assertEquals(43, parameter.getNodeP2pVersion()); Assert.assertEquals(54, parameter.getMaxUnsolidifiedBlocks()); Assert.assertEquals(false, parameter.isUnsolidifiedBlockCheck()); + Assert.assertEquals(1000, parameter.getMaxCreateAccountTxSize()); //Assert.assertEquals(30, args.getSyncNodeCount()); // gRPC network configs checking From d1f851193b06f22e1a760c5f654d491384f1392f Mon Sep 17 00:00:00 2001 From: Asuka Date: Tue, 30 Apr 2024 16:44:17 +0800 Subject: [PATCH 1001/1197] func(proposal,tvm): add energy adjustment proposal and implement --- .../org/tron/core/actuator/VMActuator.java | 7 +++++ .../org/tron/core/utils/ProposalUtil.java | 13 +++++++- .../java/org/tron/core/vm/EnergyCost.java | 31 ++++++++++++++++++- .../org/tron/core/vm/OperationRegistry.java | 17 ++++++++++ .../main/java/org/tron/core/vm/VMUtils.java | 7 ++++- .../org/tron/core/vm/config/ConfigLoader.java | 1 + .../org/tron/core/vm/config/VMConfig.java | 10 ++++++ .../org/tron/core/vm/program/Program.java | 3 +- .../core/store/DynamicPropertiesStore.java | 13 ++++++++ .../common/parameter/CommonParameter.java | 4 +++ .../src/main/java/org/tron/core/Constant.java | 4 +++ .../java/org/tron/core/config/Parameter.java | 5 +-- .../src/main/java/org/tron/core/Wallet.java | 5 +++ .../java/org/tron/core/config/args/Args.java | 5 +++ .../tron/core/consensus/ProposalService.java | 4 +++ 15 files changed, 123 insertions(+), 6 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 326e2472757..31db5d799e2 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -189,6 +189,13 @@ public void execute(Object object) throws ContractExeException { VM.play(program, OperationRegistry.getTable()); result = program.getResult(); + if (VMConfig.allowEnergyAdjustment()) { + // If the last op consumed too much execution time, the CPU time limit for the whole tx can be exceeded. + // This is not fair for other txs in the same block. + // So when allowFairEnergyAdjustment is on, the CPU time limit will be checked at the end of tx execution. + program.checkCPUTimeLimit("TX_LAST_OP"); + } + if (TrxType.TRX_CONTRACT_CREATION_TYPE == trxType && !result.isRevert()) { byte[] code = program.getResult().getHReturn(); if (code.length != 0 && VMConfig.allowTvmLondon() && code[0] == (byte) 0xEF) { diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index cfec5b09d96..3521bacfa35 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -748,6 +748,16 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case ALLOW_ENERGY_ADJUSTMENT: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7_5)) { + throw new ContractValidateException( + "Bad chain parameter id [ALLOW_ENERGY_ADJUSTMENT]"); + } + if (value != 1) { + throw new ContractValidateException( + "This value[ALLOW_ENERGY_ADJUSTMENT] is only allowed to be 1"); + } + } default: break; } @@ -824,7 +834,8 @@ public enum ProposalType { // current value, value range ALLOW_TVM_SHANGHAI(76), // 0, 1 ALLOW_CANCEL_ALL_UNFREEZE_V2(77), // 0, 1 MAX_DELEGATE_LOCK_PERIOD(78), // (86400, 10512000] - ALLOW_OLD_REWARD_OPT(79); // 0, 1 + ALLOW_OLD_REWARD_OPT(79), // 0, 1 + ALLOW_ENERGY_ADJUSTMENT(80); // 0, 1 private long code; diff --git a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java index 3b62b2f549a..6638b22d47f 100644 --- a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java +++ b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java @@ -259,12 +259,19 @@ public static long getSuicideCost(Program ignored) { return SUICIDE; } + public static long getSuicideCost2(Program program) { + DataWord inheritorAddress = program.getStack().peek(); + if (isDeadAccount(program, inheritorAddress)) { + return getSuicideCost(program) + NEW_ACCT_CALL; + } + return getSuicideCost(program); + } + public static long getBalanceCost(Program ignored) { return BALANCE; } public static long getFreezeCost(Program program) { - Stack stack = program.getStack(); DataWord receiverAddressWord = stack.get(stack.size() - 3); if (isDeadAccount(program, receiverAddressWord)) { @@ -306,7 +313,27 @@ public static long getUnDelegateResourceCost(Program ignored) { } public static long getVoteWitnessCost(Program program) { + Stack stack = program.getStack(); + long oldMemSize = program.getMemSize(); + DataWord amountArrayLength = stack.get(stack.size() - 1).clone(); + DataWord amountArrayOffset = stack.get(stack.size() - 2); + DataWord witnessArrayLength = stack.get(stack.size() - 3).clone(); + DataWord witnessArrayOffset = stack.get(stack.size() - 4); + + DataWord wordSize = new DataWord(DataWord.WORD_SIZE); + + amountArrayLength.mul(wordSize); + BigInteger amountArrayMemoryNeeded = memNeeded(amountArrayOffset, amountArrayLength); + + witnessArrayLength.mul(wordSize); + BigInteger witnessArrayMemoryNeeded = memNeeded(witnessArrayOffset, witnessArrayLength); + + return VOTE_WITNESS + calcMemEnergy(oldMemSize, + (amountArrayMemoryNeeded.compareTo(witnessArrayMemoryNeeded) > 0 + ? amountArrayMemoryNeeded : witnessArrayMemoryNeeded), 0, Op.VOTEWITNESS); + } + public static long getVoteWitnessCost2(Program program) { Stack stack = program.getStack(); long oldMemSize = program.getMemSize(); DataWord amountArrayLength = stack.get(stack.size() - 1).clone(); @@ -317,9 +344,11 @@ public static long getVoteWitnessCost(Program program) { DataWord wordSize = new DataWord(DataWord.WORD_SIZE); amountArrayLength.mul(wordSize); + amountArrayLength.add(wordSize); // dynamic array length is at least 32 bytes BigInteger amountArrayMemoryNeeded = memNeeded(amountArrayOffset, amountArrayLength); witnessArrayLength.mul(wordSize); + witnessArrayLength.add(wordSize); // dynamic array length is at least 32 bytes BigInteger witnessArrayMemoryNeeded = memNeeded(witnessArrayOffset, witnessArrayLength); return VOTE_WITNESS + calcMemEnergy(oldMemSize, diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index e4b1e174702..8cf0ea7242a 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -67,6 +67,10 @@ public static JumpTable getTable() { adjustMemOperations(table); } + if (VMConfig.allowEnergyAdjustment()) { + ajustForFairEnergy(table); + } + return table; } @@ -635,4 +639,17 @@ public static void appendShangHaiOperations(JumpTable table) { OperationActions::push0Action, proposal)); } + + public static void ajustForFairEnergy(JumpTable table) { + table.set(new Operation( + Op.VOTEWITNESS, 4, 1, + EnergyCost::getVoteWitnessCost2, + OperationActions::voteWitnessAction, + VMConfig::allowTvmVote)); + + table.set(new Operation( + Op.SUICIDE, 1, 0, + EnergyCost::getSuicideCost2, + OperationActions::suicideAction)); + } } diff --git a/actuator/src/main/java/org/tron/core/vm/VMUtils.java b/actuator/src/main/java/org/tron/core/vm/VMUtils.java index abdf6c7fe4c..1df0e0e22f1 100644 --- a/actuator/src/main/java/org/tron/core/vm/VMUtils.java +++ b/actuator/src/main/java/org/tron/core/vm/VMUtils.java @@ -12,7 +12,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.Arrays; -import java.util.Map; import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; import lombok.extern.slf4j.Slf4j; @@ -20,6 +19,7 @@ import org.tron.common.utils.ByteUtil; import org.tron.common.utils.Commons; import org.tron.common.utils.DecodeUtil; +import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; import org.tron.core.exception.ContractValidateException; import org.tron.core.vm.config.VMConfig; @@ -33,6 +33,11 @@ public final class VMUtils { private VMUtils() { } + public static int getAddressSize() { + return VMConfig.allowEnergyAdjustment() ? + Constant.TRON_ADDRESS_SIZE : Constant.STANDARD_ADDRESS_SIZE; + } + public static void closeQuietly(Closeable closeable) { try { if (closeable != null) { diff --git a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java index 463d8c8995a..63c3ff791d6 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java +++ b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java @@ -39,6 +39,7 @@ public static void load(StoreFactory storeFactory) { VMConfig.initDynamicEnergyIncreaseFactor(ds.getDynamicEnergyIncreaseFactor()); VMConfig.initDynamicEnergyMaxFactor(ds.getDynamicEnergyMaxFactor()); VMConfig.initAllowTvmShangHai(ds.getAllowTvmShangHai()); + VMConfig.initAllowEnergyAdjustment(ds.getAllowEnergyAdjustment()); } } } diff --git a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java index 97202432598..3eb1f8fd4b8 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java +++ b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java @@ -49,6 +49,8 @@ public class VMConfig { private static boolean ALLOW_TVM_SHANGHAI = false; + private static boolean ALLOW_ENERGY_ADJUSTMENT = false; + private VMConfig() { } @@ -136,6 +138,10 @@ public static void initAllowTvmShangHai(long allow) { ALLOW_TVM_SHANGHAI = allow == 1; } + public static void initAllowEnergyAdjustment(long allow) { + ALLOW_ENERGY_ADJUSTMENT = allow == 1; + } + public static boolean getEnergyLimitHardFork() { return CommonParameter.ENERGY_LIMIT_HARD_FORK; } @@ -211,4 +217,8 @@ public static long getDynamicEnergyMaxFactor() { public static boolean allowTvmShanghai() { return ALLOW_TVM_SHANGHAI; } + + public static boolean allowEnergyAdjustment() { + return ALLOW_ENERGY_ADJUSTMENT; + } } diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index e02ba225c6b..2e547dc86f2 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -457,7 +457,8 @@ public void suicide(DataWord obtainerAddress) { InternalTransaction internalTx = addInternalTx(null, owner, obtainer, balance, null, "suicide", nonce, getContractState().getAccount(owner).getAssetMapV2()); - if (FastByteComparisons.compareTo(owner, 0, 20, obtainer, 0, 20) == 0) { + int ADDRESS_SIZE = VMUtils.getAddressSize(); + if (FastByteComparisons.compareTo(owner, 0, ADDRESS_SIZE, obtainer, 0, ADDRESS_SIZE) == 0) { // if owner == obtainer just zeroing account according to Yellow Paper getContractState().addBalance(owner, -balance); byte[] blackHoleAddress = getContractState().getBlackHoleAddress(); diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index bf788232640..5c1a3d7b460 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -219,6 +219,8 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_OLD_REWARD_OPT = "ALLOW_OLD_REWARD_OPT".getBytes(); + private static final byte[] ALLOW_ENERGY_ADJUSTMENT = "ALLOW_FAIR_ENERGY_ADJUSTMENT".getBytes(); + @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { super(dbName); @@ -2850,6 +2852,17 @@ public long getAllowOldRewardOpt() { .orElse(CommonParameter.getInstance().getAllowOldRewardOpt()); } + public void saveAllowEnergyAdjustment(long allowEnergyAdjustment) { + this.put(ALLOW_ENERGY_ADJUSTMENT, new BytesCapsule(ByteArray.fromLong(allowEnergyAdjustment))); + } + + public long getAllowEnergyAdjustment() { + return Optional.ofNullable(getUnchecked(ALLOW_ENERGY_ADJUSTMENT)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElse(CommonParameter.getInstance().getAllowEnergyAdjustment()); + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index f9562e580e3..eb6398d631b 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -666,6 +666,10 @@ public class CommonParameter { @Setter public long allowOldRewardOpt; + @Getter + @Setter + public long allowEnergyAdjustment; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 2cd9ea95f15..d91506d71fa 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -18,6 +18,8 @@ public class Constant { public static final String ADD_PRE_FIX_STRING_MAINNET = "41"; public static final byte ADD_PRE_FIX_BYTE_TESTNET = (byte) 0xa0; //a0 + address public static final String ADD_PRE_FIX_STRING_TESTNET = "a0"; + public static final int STANDARD_ADDRESS_SIZE = 20; + public static final int TRON_ADDRESS_SIZE = 21; public static final int NODE_TYPE_FULL_NODE = 0; public static final int NODE_TYPE_LIGHT_NODE = 1; @@ -376,4 +378,6 @@ public class Constant { public static final String MAX_UNSOLIDIFIED_BLOCKS = "node.maxUnsolidifiedBlocks"; public static final String COMMITTEE_ALLOW_OLD_REWARD_OPT = "committee.allowOldRewardOpt"; + + public static final String COMMITTEE_ALLOW_ENERGY_ADJUSTMENT = "committee.allowEnergyAdjustment"; } diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index 247826af77a..027c225eb5d 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -23,7 +23,8 @@ public enum ForkBlockVersionEnum { VERSION_4_7(26, 1596780000000L, 80), VERSION_4_7_1(27, 1596780000000L, 80), VERSION_4_7_2(28, 1596780000000L, 80), - VERSION_4_7_4(29, 1596780000000L, 80); + VERSION_4_7_4(29, 1596780000000L, 80), + VERSION_4_7_5(30, 1596780000000L, 80); // if add a version, modify BLOCK_VERSION simultaneously @Getter @@ -72,7 +73,7 @@ public class ChainConstant { public static final int SINGLE_REPEAT = 1; public static final int BLOCK_FILLED_SLOTS_NUMBER = 128; public static final int MAX_FROZEN_NUMBER = 1; - public static final int BLOCK_VERSION = 29; + public static final int BLOCK_VERSION = 30; public static final long FROZEN_PERIOD = 86_400_000L; public static final long DELEGATE_PERIOD = 3 * 86_400_000L; public static final long TRX_PRECISION = 1000_000L; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 96af6fc7476..d192fa020e0 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1334,6 +1334,11 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getAllowOldRewardOpt()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getAllowEnergyAdjustment") + .setValue(dbManager.getDynamicPropertiesStore().getAllowEnergyAdjustment()) + .build()); + return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index a8547b73948..422efefaed8 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -232,6 +232,7 @@ public static void clearParam() { PARAMETER.unsolidifiedBlockCheck = false; PARAMETER.maxUnsolidifiedBlocks = 54; PARAMETER.allowOldRewardOpt = 0; + PARAMETER.allowEnergyAdjustment = 0; } /** @@ -1205,6 +1206,10 @@ public static void setParam(final String[] args, final String confFileName) { } PARAMETER.allowOldRewardOpt = allowOldRewardOpt; + PARAMETER.allowEnergyAdjustment = + config.hasPath(Constant.COMMITTEE_ALLOW_ENERGY_ADJUSTMENT) ? config + .getInt(Constant.COMMITTEE_ALLOW_ENERGY_ADJUSTMENT) : 0; + logConfig(); } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 58da117cfc6..bd157a2592f 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -359,6 +359,10 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveAllowOldRewardOpt(entry.getValue()); break; } + case ALLOW_ENERGY_ADJUSTMENT: { + manager.getDynamicPropertiesStore().saveAllowEnergyAdjustment(entry.getValue()); + break; + } default: find = false; break; From 2fbb853d3d60006c494e5d11a8a52a6478c6c715 Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 6 May 2024 14:40:49 +0800 Subject: [PATCH 1002/1197] func(proposal): adjust proposal id --- actuator/src/main/java/org/tron/core/utils/ProposalUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 3521bacfa35..12d85901b30 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -835,7 +835,7 @@ public enum ProposalType { // current value, value range ALLOW_CANCEL_ALL_UNFREEZE_V2(77), // 0, 1 MAX_DELEGATE_LOCK_PERIOD(78), // (86400, 10512000] ALLOW_OLD_REWARD_OPT(79), // 0, 1 - ALLOW_ENERGY_ADJUSTMENT(80); // 0, 1 + ALLOW_ENERGY_ADJUSTMENT(81); // 0, 1 private long code; From 7491af6d4724e1c451e9ca6a7de9bc9baaf9b2b2 Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 9 May 2024 14:33:30 +0800 Subject: [PATCH 1003/1197] fix(proposal): should break for each proposal case --- actuator/src/main/java/org/tron/core/utils/ProposalUtil.java | 1 + 1 file changed, 1 insertion(+) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 12d85901b30..6501b40ac79 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -757,6 +757,7 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, throw new ContractValidateException( "This value[ALLOW_ENERGY_ADJUSTMENT] is only allowed to be 1"); } + break; } default: break; From 9da13ac1213813a2fbc62a8d2e5423ebdc9c0001 Mon Sep 17 00:00:00 2001 From: Asuka Date: Sat, 11 May 2024 12:20:20 +0800 Subject: [PATCH 1004/1197] func(test): add unit test for energy adjustment proposal --- .../org/tron/core/actuator/VMActuator.java | 3 +- .../org/tron/core/vm/OperationRegistry.java | 4 +- .../org/tron/core/vm/program/Program.java | 4 ++ .../common/runtime/vm/OperationsTest.java | 53 +++++++++++++++++++ 4 files changed, 61 insertions(+), 3 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 31db5d799e2..08d0f5a8da5 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -38,6 +38,7 @@ import org.tron.core.utils.TransactionUtil; import org.tron.core.vm.EnergyCost; import org.tron.core.vm.LogInfoTriggerParser; +import org.tron.core.vm.Op; import org.tron.core.vm.OperationRegistry; import org.tron.core.vm.VM; import org.tron.core.vm.VMConstant; @@ -193,7 +194,7 @@ public void execute(Object object) throws ContractExeException { // If the last op consumed too much execution time, the CPU time limit for the whole tx can be exceeded. // This is not fair for other txs in the same block. // So when allowFairEnergyAdjustment is on, the CPU time limit will be checked at the end of tx execution. - program.checkCPUTimeLimit("TX_LAST_OP"); + program.checkCPUTimeLimit(Op.getNameOf(program.getLastOp()) + "(TX_LAST_OP)"); } if (TrxType.TRX_CONTRACT_CREATION_TYPE == trxType && !result.isRevert()) { diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index 8cf0ea7242a..a2d3259ba89 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -68,7 +68,7 @@ public static JumpTable getTable() { } if (VMConfig.allowEnergyAdjustment()) { - ajustForFairEnergy(table); + adjustForFairEnergy(table); } return table; @@ -640,7 +640,7 @@ public static void appendShangHaiOperations(JumpTable table) { proposal)); } - public static void ajustForFairEnergy(JumpTable table) { + public static void adjustForFairEnergy(JumpTable table) { table.set(new Operation( Op.VOTEWITNESS, 4, 1, EnergyCost::getVoteWitnessCost2, diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 2e547dc86f2..0b0ef5bc9ba 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -275,6 +275,10 @@ public void setLastOp(byte op) { this.lastOp = op; } + public byte getLastOp() { + return this.lastOp; + } + /** * Returns the last fully executed OP. */ diff --git a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java index be031d7c00b..68104794384 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java @@ -3,6 +3,8 @@ import static org.junit.Assert.assertEquals; import java.util.List; +import java.util.Random; + import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; @@ -15,6 +17,7 @@ import org.tron.common.BaseTest; import org.tron.common.parameter.CommonParameter; import org.tron.common.runtime.InternalTransaction; +import org.tron.common.utils.DecodeUtil; import org.tron.core.Constant; import org.tron.core.config.args.Args; import org.tron.core.exception.ContractValidateException; @@ -864,6 +867,50 @@ public void testPush0() throws ContractValidateException { VMConfig.initAllowTvmShangHai(0); } + @Test + public void testSuicideCost() throws ContractValidateException { + invoke = new ProgramInvokeMockImpl(StoreFactory.getInstance(), new byte[0], new byte[21]); + program = new Program(null, null, invoke, + new InternalTransaction( + Protocol.Transaction.getDefaultInstance(), + InternalTransaction.TrxType.TRX_UNKNOWN_TYPE)); + + byte[] receiver1 = generateRandomAddress(); + program.stackPush(new DataWord(receiver1)); + Assert.assertEquals(0, EnergyCost.getSuicideCost(program)); + invoke.getDeposit().createAccount(receiver1, Protocol.AccountType.Normal); + Assert.assertEquals(0, EnergyCost.getSuicideCost(program)); + + byte[] receiver2 = generateRandomAddress(); + program.stackPush(new DataWord(receiver2)); + Assert.assertEquals(25000, EnergyCost.getSuicideCost2(program)); + invoke.getDeposit().createAccount(receiver2, Protocol.AccountType.Normal); + Assert.assertEquals(0, EnergyCost.getSuicideCost2(program)); + } + + @Test + public void testVoteWitnessCost() throws ContractValidateException { + // Build stack environment, the stack from top to bottom is 0x00, 0x80, 0x00, 0x80 + program = new Program(null, null, new ProgramInvokeMockImpl(), + new InternalTransaction( + Protocol.Transaction.getDefaultInstance(), + InternalTransaction.TrxType.TRX_UNKNOWN_TYPE)); + program.stackPush(DataWord.of((byte) 0x80)); + program.stackPush(DataWord.of((byte) 0x00)); + program.stackPush(DataWord.of((byte) 0x80)); + program.stackPush(DataWord.of((byte) 0x00)); + + // Test VoteWitness before EnergyAdjustment, should not have memory expand energy + Assert.assertEquals(30000, EnergyCost.getVoteWitnessCost(program)); + + // Test VoteWitness after EnergyAdjustment, should have memory expand energy + VMConfig.initAllowEnergyAdjustment(1); + + long memWords = (0x80 + 32) / 32; + long memoryExpandEnergy = 3 * memWords + memWords * memWords / 512; + Assert.assertEquals(30000 + memoryExpandEnergy, EnergyCost.getVoteWitnessCost2(program)); + } + private void testOperations(Program program) { try { while (!program.isStopped()) { @@ -954,4 +1001,10 @@ private byte[] compile(String code) { return new BytecodeCompiler().compile(code); } + private byte[] generateRandomAddress() { + byte[] address = new byte[21]; + new Random().nextBytes(address); + address[0] = DecodeUtil.addressPreFixByte; + return address; + } } From eb2b88095c94d155bfc700552fa7b927dea14969 Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 13 May 2024 09:35:09 +0800 Subject: [PATCH 1005/1197] func(proposal): proposal 81th will not be able to be reopened in the state in which it was opened. --- actuator/src/main/java/org/tron/core/utils/ProposalUtil.java | 4 ++++ .../main/java/org/tron/core/store/DynamicPropertiesStore.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 6501b40ac79..7c12c07f059 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -753,6 +753,10 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, throw new ContractValidateException( "Bad chain parameter id [ALLOW_ENERGY_ADJUSTMENT]"); } + if (dynamicPropertiesStore.getAllowEnergyAdjustment() == 1) { + throw new ContractValidateException( + "[ALLOW_ENERGY_ADJUSTMENT] has been valid, no need to propose again"); + } if (value != 1) { throw new ContractValidateException( "This value[ALLOW_ENERGY_ADJUSTMENT] is only allowed to be 1"); diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 5c1a3d7b460..9cadf1fdab9 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -219,7 +219,7 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_OLD_REWARD_OPT = "ALLOW_OLD_REWARD_OPT".getBytes(); - private static final byte[] ALLOW_ENERGY_ADJUSTMENT = "ALLOW_FAIR_ENERGY_ADJUSTMENT".getBytes(); + private static final byte[] ALLOW_ENERGY_ADJUSTMENT = "ALLOW_ENERGY_ADJUSTMENT".getBytes(); @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { From 40587026e8ae69ba9a0b1e17a16ccb6e145282ec Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 30 May 2024 14:33:48 +0800 Subject: [PATCH 1006/1197] func(test): add unit test for getAllowEnergyAdjustment proposal --- .../core/actuator/utils/ProposalUtilTest.java | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java index 8e2b7647967..0bb303cafa0 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -12,13 +13,18 @@ import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ForkController; +import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.BytesCapsule; +import org.tron.core.capsule.ProposalCapsule; import org.tron.core.config.Parameter; import org.tron.core.config.Parameter.ForkBlockVersionEnum; import org.tron.core.config.args.Args; +import org.tron.core.consensus.ProposalService; +import org.tron.core.db.Manager; import org.tron.core.exception.ContractValidateException; import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.store.StoreFactory; import org.tron.core.utils.ProposalUtil; import org.tron.core.utils.ProposalUtil.ProposalType; @@ -381,11 +387,76 @@ public void validateCheck() { e.getMessage()); } + testEnergyAdjustmentProposal(); + forkUtils.getManager().getDynamicPropertiesStore() .statsByVersion(ForkBlockVersionEnum.ENERGY_LIMIT.getValue(), stats); forkUtils.reset(); } + private void testEnergyAdjustmentProposal() { + // Should fail because cannot pass the fork controller check + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_ENERGY_ADJUSTMENT.getCode(), 1); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "Bad chain parameter id [ALLOW_ENERGY_ADJUSTMENT]", + e.getMessage()); + } + + long maintenanceTimeInterval = forkUtils.getManager().getDynamicPropertiesStore() + .getMaintenanceTimeInterval(); + + long hardForkTime = + ((ForkBlockVersionEnum.VERSION_4_7_5.getHardForkTime() - 1) / maintenanceTimeInterval + 1) + * maintenanceTimeInterval; + forkUtils.getManager().getDynamicPropertiesStore() + .saveLatestBlockHeaderTimestamp(hardForkTime + 1); + + byte[] stats = new byte[27]; + Arrays.fill(stats, (byte) 1); + forkUtils.getManager().getDynamicPropertiesStore() + .statsByVersion(ForkBlockVersionEnum.VERSION_4_7_5.getValue(), stats); + + // Should fail because the proposal value is invalid + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_ENERGY_ADJUSTMENT.getCode(), 2); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "This value[ALLOW_ENERGY_ADJUSTMENT] is only allowed to be 1", + e.getMessage()); + } + + // Should succeed + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_ENERGY_ADJUSTMENT.getCode(), 1); + } catch (Throwable t) { + Assert.fail(); + } + + ProposalCapsule proposalCapsule = new ProposalCapsule(ByteString.empty(), 0); + proposalCapsule.setParameters(new HashMap(){{ + put(81L, 1L); + }}); + + ProposalService.process(dbManager, proposalCapsule); + + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_ENERGY_ADJUSTMENT.getCode(), 1); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "[ALLOW_ENERGY_ADJUSTMENT] has been valid, no need to propose again", + e.getMessage()); + } + } + @Test public void blockVersionCheck() { for (ForkBlockVersionEnum forkVersion : ForkBlockVersionEnum.values()) { From 4ddd640bb7c25a29086e060cc0ede1b54691ca78 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 29 May 2024 23:04:07 +0800 Subject: [PATCH 1007/1197] feat(validate): limit big transaction size --- .../main/java/org/tron/core/db/Manager.java | 16 +++++++- .../java/org/tron/core/db/ManagerTest.java | 37 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 63bbef9ff7f..e190620d3e2 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1,6 +1,7 @@ package org.tron.core.db; import static org.tron.common.utils.Commons.adjustBalance; +import static org.tron.core.Constant.TRANSACTION_MAX_BYTE_SIZE; import static org.tron.core.exception.BadBlockException.TypeEnum.CALC_MERKLE_ROOT_FAILED; import static org.tron.protos.Protocol.Transaction.Contract.ContractType.TransferContract; import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS; @@ -793,9 +794,22 @@ void validateTapos(TransactionCapsule transactionCapsule) throws TaposException void validateCommon(TransactionCapsule transactionCapsule) throws TransactionExpirationException, TooBigTransactionException { + if (!transactionCapsule.isInBlock()) { + long generalBytesSize = + transactionCapsule.getInstance().toBuilder().clearRet().build().getSerializedSize() + + Constant.MAX_RESULT_SIZE_IN_TX + Constant.MAX_RESULT_SIZE_IN_TX; + if (generalBytesSize > TRANSACTION_MAX_BYTE_SIZE) { + throw new TooBigTransactionException(String.format( + "Too big transaction with result, TxId %s, the size is %d bytes, maxTxSize %d", + transactionCapsule.getTransactionId(), generalBytesSize, TRANSACTION_MAX_BYTE_SIZE)); + } + } + if (transactionCapsule.getData().length > Constant.TRANSACTION_MAX_BYTE_SIZE) { throw new TooBigTransactionException(String.format( - "Too big transaction, the size is %d bytes", transactionCapsule.getData().length)); + "Too big transaction, TxId %s, the size is %d bytes, maxTxSize %d", + transactionCapsule.getTransactionId(), transactionCapsule.getData().length, + TRANSACTION_MAX_BYTE_SIZE)); } long transactionExpiration = transactionCapsule.getExpiration(); long headBlockTime = chainBaseManager.getHeadBlockTimeStamp(); diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index 053647cc25a..a2a0718abaf 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -1,5 +1,6 @@ package org.tron.core.db; +import static org.junit.Assert.assertThrows; import static org.tron.common.utils.Commons.adjustAssetBalanceV2; import static org.tron.common.utils.Commons.adjustBalance; import static org.tron.common.utils.Commons.adjustTotalShieldedPoolValue; @@ -8,8 +9,10 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; +import com.google.protobuf.Any; import com.google.protobuf.ByteString; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -85,6 +88,7 @@ import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.Protocol.Transaction.raw; import org.tron.protos.contract.AccountContract; import org.tron.protos.contract.AssetIssueContractOuterClass; import org.tron.protos.contract.BalanceContract.TransferContract; @@ -1114,4 +1118,37 @@ public void testExpireTransaction() { Assert.fail(); } } + + @Test + public void testTooBigTransaction() { + TransferContract transferContract = + TransferContract.newBuilder() + .setAmount(10) + .setOwnerAddress(ByteString.copyFromUtf8("aaa")) + .setToAddress(ByteString.copyFromUtf8("bbb")) + .build(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 6666; i++) { + sb.append("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + } + Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder() + .setData(ByteString.copyFrom(sb.toString().getBytes(StandardCharsets.UTF_8))) + .addContract(Transaction.Contract.newBuilder().setParameter(Any.pack(transferContract)) + .setType(ContractType.TransferContract))).build(); + TransactionCapsule trx = new TransactionCapsule(transaction); + trx.setInBlock(false); + assertThrows( + "Too big transaction with result, " + + "TxId 1c05e9fca6a2d0c366ed4430456527eb40198e70c8b20f5ceca4739c68a79af8, " + + "the size is 533483 bytes, maxTxSize 512000", + TooBigTransactionException.class, ()-> dbManager.validateCommon(trx)); + + trx.setInBlock(true); + assertThrows( + "Too big transaction, " + + "TxId 1c05e9fca6a2d0c366ed4430456527eb40198e70c8b20f5ceca4739c68a79af8, " + + "the size is 1066643 bytes, maxTxSize 512000", + TooBigTransactionException.class, ()-> dbManager.validateCommon(trx)); + + } } From 3aa94e029ecb78334ddc9a1261ee0c30a434256e Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 30 May 2024 15:36:28 +0800 Subject: [PATCH 1008/1197] test(tvm): add unit test for suicide action --- .../common/runtime/vm/OperationsTest.java | 23 +++++++++++++++++++ .../core/actuator/utils/ProposalUtilTest.java | 11 ++++----- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java index 68104794384..2a70364b8d1 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java @@ -888,6 +888,29 @@ public void testSuicideCost() throws ContractValidateException { Assert.assertEquals(0, EnergyCost.getSuicideCost2(program)); } + @Test + public void testSuicideAction() throws ContractValidateException { + invoke = new ProgramInvokeMockImpl( + StoreFactory.getInstance(), + new byte[0], + Hex.decode("41471fd3ad3e9eeadeec4608b92d16ce6b500704cc")); + + program = new Program(null, null, invoke, + new InternalTransaction( + Protocol.Transaction.getDefaultInstance(), + InternalTransaction.TrxType.TRX_UNKNOWN_TYPE)); + + VMConfig.initAllowEnergyAdjustment(1); + byte prePrefixByte = DecodeUtil.addressPreFixByte; + DecodeUtil.addressPreFixByte = Constant.ADD_PRE_FIX_BYTE_MAINNET; + + program.suicide(new DataWord( + dbManager.getAccountStore().getBlackhole().getAddress().toByteArray())); + + DecodeUtil.addressPreFixByte = prePrefixByte; + VMConfig.initAllowEnergyAdjustment(0); + } + @Test public void testVoteWitnessCost() throws ContractValidateException { // Build stack environment, the stack from top to bottom is 0x00, 0x80, 0x00, 0x80 diff --git a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java index 0bb303cafa0..db122f90c4f 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java @@ -5,6 +5,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; +import java.util.Map; import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; @@ -13,7 +14,6 @@ import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ForkController; -import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.BytesCapsule; import org.tron.core.capsule.ProposalCapsule; @@ -21,10 +21,8 @@ import org.tron.core.config.Parameter.ForkBlockVersionEnum; import org.tron.core.config.args.Args; import org.tron.core.consensus.ProposalService; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractValidateException; import org.tron.core.store.DynamicPropertiesStore; -import org.tron.core.store.StoreFactory; import org.tron.core.utils.ProposalUtil; import org.tron.core.utils.ProposalUtil.ProposalType; @@ -440,10 +438,9 @@ private void testEnergyAdjustmentProposal() { } ProposalCapsule proposalCapsule = new ProposalCapsule(ByteString.empty(), 0); - proposalCapsule.setParameters(new HashMap(){{ - put(81L, 1L); - }}); - + Map parameter = new HashMap<>(); + parameter.put(81L, 1L); + proposalCapsule.setParameters(parameter); ProposalService.process(dbManager, proposalCapsule); try { From 271e3d01c400fd3aaeff1626ea4924f40297ddd0 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 29 May 2024 23:21:29 +0800 Subject: [PATCH 1009/1197] feat(*): remove redundant ret for transaction --- .../tron/core/capsule/TransactionCapsule.java | 24 +++++++++++++ .../org/tron/core/db/BandwidthProcessor.java | 7 ++++ .../src/main/java/org/tron/core/Constant.java | 1 + .../src/main/java/org/tron/core/Wallet.java | 6 ++-- .../main/java/org/tron/core/db/Manager.java | 27 +++++++++----- .../runtime/vm/BandWidthRuntimeTest.java | 15 ++++++++ .../org/tron/core/BandwidthProcessorTest.java | 34 ++++++++++++++++++ .../core/capsule/TransactionCapsuleTest.java | 20 +++++++++++ .../java/org/tron/core/db/ManagerTest.java | 36 +++++++++++++++++++ protocol/src/main/protos/core/Tron.proto | 1 + 10 files changed, 159 insertions(+), 12 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java index a588b28c748..11bd3a8a0cf 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -17,6 +17,7 @@ import static org.tron.common.utils.StringUtil.encode58Check; import static org.tron.common.utils.WalletUtil.checkPermissionOperations; +import static org.tron.core.Constant.MAX_CONTRACT_RESULT_SIZE; import static org.tron.core.exception.P2pException.TypeEnum.PROTOBUF_ERROR; import com.google.common.primitives.Bytes; @@ -730,6 +731,15 @@ public long getResultSerializedSize() { return size; } + public long getResultSizeWithMaxContractRet() { + long size = 0; + for (Result result : this.transaction.getRetList()) { + size += result.toBuilder().clearContractRet().build().getSerializedSize() + + MAX_CONTRACT_RESULT_SIZE; + } + return size; + } + @Override public Transaction getInstance() { return this.transaction; @@ -842,4 +852,18 @@ public BalanceContract.TransferContract getTransferContract() { return null; } } + + public void removeRedundantRet() { + Transaction tx = this.getInstance(); + List tmpList = new ArrayList<>(tx.getRetList()); + int contractCount = tx.getRawData().getContractCount(); + if (tx.getRetCount() > contractCount && contractCount > 0) { + Transaction.Builder transactionBuilder = tx.toBuilder().clearRet(); + for (int i = 0; i < contractCount; i++) { + Result result = tmpList.get(i); + transactionBuilder.addRet(result); + } + this.transaction = transactionBuilder.build(); + } + } } diff --git a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java index f13002f2dfa..0ae6b431217 100644 --- a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -97,6 +97,13 @@ public void consume(TransactionCapsule trx, TransactionTrace trace) throws ContractValidateException, AccountResourceInsufficientException, TooBigTransactionResultException { List contracts = trx.getInstance().getRawData().getContractList(); + long resultSizeWithMaxContractRet = trx.getResultSizeWithMaxContractRet(); + if (!trx.isInBlock() && resultSizeWithMaxContractRet > + Constant.MAX_RESULT_SIZE_IN_TX * contracts.size()) { + throw new TooBigTransactionResultException(String.format( + "Too big transaction result, TxId %s, the result size is %d bytes, maxResultSize %d", + trx.getTransactionId(), resultSizeWithMaxContractRet, Constant.MAX_RESULT_SIZE_IN_TX)); + } if (trx.getResultSerializedSize() > Constant.MAX_RESULT_SIZE_IN_TX * contracts.size()) { throw new TooBigTransactionResultException(); } diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 2cd9ea95f15..f0f275593c9 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -31,6 +31,7 @@ public class Constant { public static final long SUN_PER_ENERGY = 100; // 1 us = 100 SUN = 100 * 10^-6 TRX public static final long ENERGY_LIMIT_IN_CONSTANT_TX = 3_000_000L; // ref: 1 us = 1 energy public static final long MAX_RESULT_SIZE_IN_TX = 64; // max 8 * 8 items in result + public static final long MAX_CONTRACT_RESULT_SIZE = 2L; public static final long PB_DEFAULT_ENERGY_LIMIT = 0L; public static final long CREATOR_DEFAULT_ENERGY_LIMIT = 1000 * 10_000L; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 96af6fc7476..cdc9a589667 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -497,8 +497,6 @@ public GrpcAPI.Return broadcastTransaction(Transaction signedTransaction) { trx.setTime(System.currentTimeMillis()); Sha256Hash txID = trx.getTransactionId(); try { - TransactionMessage message = new TransactionMessage(signedTransaction.toByteArray()); - if (tronNetDelegate.isBlockUnsolidified()) { logger.warn("Broadcast transaction {} has failed, block unsolidified.", txID); return builder.setResult(false).setCode(response_code.BLOCK_UNSOLIDIFIED) @@ -550,6 +548,7 @@ public GrpcAPI.Return broadcastTransaction(Transaction signedTransaction) { if (trx.getInstance().getRawData().getContractCount() == 0) { throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); } + TransactionMessage message = new TransactionMessage(trx.getInstance().toByteArray()); dbManager.pushTransaction(trx); int num = tronNetService.fastBroadcastTransaction(message); if (num == 0 && minEffectiveConnection != 0) { @@ -592,8 +591,7 @@ public GrpcAPI.Return broadcastTransaction(Transaction signedTransaction) { } catch (TooBigTransactionException e) { logger.warn(BROADCAST_TRANS_FAILED, txID, e.getMessage()); return builder.setResult(false).setCode(response_code.TOO_BIG_TRANSACTION_ERROR) - .setMessage(ByteString.copyFromUtf8("Transaction size is too big.")) - .build(); + .setMessage(ByteString.copyFromUtf8(e.getMessage())).build(); } catch (TransactionExpirationException e) { logger.warn(BROADCAST_TRANS_FAILED, txID, e.getMessage()); return builder.setResult(false).setCode(response_code.TRANSACTION_EXPIRATION_ERROR) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 63bbef9ff7f..664d0cf4159 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1,6 +1,7 @@ package org.tron.core.db; import static org.tron.common.utils.Commons.adjustBalance; +import static org.tron.core.Constant.TRANSACTION_MAX_BYTE_SIZE; import static org.tron.core.exception.BadBlockException.TypeEnum.CALC_MERKLE_ROOT_FAILED; import static org.tron.protos.Protocol.Transaction.Contract.ContractType.TransferContract; import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS; @@ -793,6 +794,17 @@ void validateTapos(TransactionCapsule transactionCapsule) throws TaposException void validateCommon(TransactionCapsule transactionCapsule) throws TransactionExpirationException, TooBigTransactionException { + if (!transactionCapsule.isInBlock()) { + transactionCapsule.removeRedundantRet(); + long generalBytesSize = + transactionCapsule.getInstance().toBuilder().clearRet().build().getSerializedSize() + + Constant.MAX_RESULT_SIZE_IN_TX + Constant.MAX_RESULT_SIZE_IN_TX; + if (generalBytesSize > TRANSACTION_MAX_BYTE_SIZE) { + throw new TooBigTransactionException(String.format( + "Too big transaction with result, TxId %s, the size is %d bytes, maxTxSize %d", + transactionCapsule.getTransactionId(), generalBytesSize, TRANSACTION_MAX_BYTE_SIZE)); + } + } if (transactionCapsule.getData().length > Constant.TRANSACTION_MAX_BYTE_SIZE) { throw new TooBigTransactionException(String.format( "Too big transaction, the size is %d bytes", transactionCapsule.getData().length)); @@ -1411,8 +1423,14 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block if (trxCap == null) { return null; } - Contract contract = trxCap.getInstance().getRawData().getContract(0); Sha256Hash txId = trxCap.getTransactionId(); + if (trxCap.getInstance().getRawData().getContractList().size() != 1) { + throw new ContractSizeNotEqualToOneException( + String.format( + "tx %s contract size should be exactly 1, this is extend feature ,actual :%d", + txId, trxCap.getInstance().getRawData().getContractList().size())); + } + Contract contract = trxCap.getInstance().getRawData().getContract(0); final Histogram.Timer requestTimer = Metrics.histogramStartTimer( MetricKeys.Histogram.PROCESS_TRANSACTION_LATENCY, Objects.nonNull(blockCap) ? MetricLabels.BLOCK : MetricLabels.TRX, @@ -1427,13 +1445,6 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block validateTapos(trxCap); validateCommon(trxCap); - if (trxCap.getInstance().getRawData().getContractList().size() != 1) { - throw new ContractSizeNotEqualToOneException( - String.format( - "tx %s contract size should be exactly 1, this is extend feature ,actual :%d", - txId, trxCap.getInstance().getRawData().getContractList().size())); - } - validateDup(trxCap); if (!trxCap.validateSignature(chainBaseManager.getAccountStore(), diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java index 40c5908c2dd..82de20dc359 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java @@ -43,6 +43,8 @@ import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract; import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.Protocol.Transaction.Result; +import org.tron.protos.Protocol.Transaction.Result.contractResult; import org.tron.protos.Protocol.Transaction.raw; import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; @@ -235,4 +237,17 @@ private byte[] createContract() Assert.assertNull(trace.getRuntimeError()); return trace.getRuntimeResult().getContractAddress(); } + + @Test + public void testMaxContractResultSize() { + int maxSize = 0; + for (contractResult cr : contractResult.values()) { + if (cr.name().equals("UNRECOGNIZED")) { + continue; + } + Result result = Result.newBuilder().setContractRet(cr).build(); + maxSize = Math.max(maxSize, result.getSerializedSize()); + } + Assert.assertEquals(2, maxSize); + } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java b/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java index 300c202e11a..b17e9615b5a 100755 --- a/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java +++ b/framework/src/test/java/org/tron/core/BandwidthProcessorTest.java @@ -1,7 +1,10 @@ package org.tron.core; +import static org.junit.Assert.assertThrows; + import com.google.protobuf.Any; import com.google.protobuf.ByteString; +import java.nio.charset.StandardCharsets; import lombok.extern.slf4j.Slf4j; import org.joda.time.DateTime; import org.junit.Assert; @@ -23,6 +26,11 @@ import org.tron.core.store.StoreFactory; import org.tron.protos.Protocol; import org.tron.protos.Protocol.AccountType; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.Transaction.Contract; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; +import org.tron.protos.Protocol.Transaction.Result; +import org.tron.protos.Protocol.Transaction.raw; import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract; import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; import org.tron.protos.contract.BalanceContract.TransferContract; @@ -539,6 +547,32 @@ public void testUsingFee() throws Exception { dbManager.consumeBandwidth(trx, trace); } + @Test + public void testConsumeBandwidthTooBigTransactionResultException() { + TransferContract transferContract = + TransferContract.newBuilder() + .setAmount(10) + .setOwnerAddress(ByteString.copyFromUtf8("aaa")) + .setToAddress(ByteString.copyFromUtf8("bbb")) + .build(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 6666; i++) { + sb.append("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + } + Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder() + .setData(ByteString.copyFrom(sb.toString().getBytes(StandardCharsets.UTF_8))) + .addContract(Contract.newBuilder().setParameter(Any.pack(transferContract)) + .setType(ContractType.TransferContract))) + .addRet(Result.newBuilder().setAssetIssueID(sb.toString()).build()).build(); + TransactionCapsule trx = new TransactionCapsule(transaction); + trx.setInBlock(false); + TransactionTrace trace = new TransactionTrace(trx, StoreFactory + .getInstance(), new RuntimeImpl()); + assertThrows( + "Too big transaction result, TxId %s, the result size is %d bytes, maxResultSize %d", + TooBigTransactionResultException.class, () -> dbManager.consumeBandwidth(trx, trace)); + } + /** * sameTokenName close, consume success assetIssueCapsule.getOwnerAddress() != * fromAccount.getAddress()) contract.getType() = TransferAssetContract diff --git a/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java index fcb2a4fbfd5..17e9d3ac887 100644 --- a/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java @@ -1,5 +1,9 @@ package org.tron.core.capsule; +import static org.tron.protos.Protocol.Transaction.Result.contractResult.BAD_JUMP_DESTINATION; +import static org.tron.protos.Protocol.Transaction.Result.contractResult.PRECOMPILED_CONTRACT; +import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS; + import com.google.protobuf.ByteString; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; @@ -13,8 +17,10 @@ import org.tron.core.config.args.Args; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result; import org.tron.protos.Protocol.Transaction.Result.contractResult; +import org.tron.protos.Protocol.Transaction.raw; @Slf4j public class TransactionCapsuleTest extends BaseTest { @@ -1064,4 +1070,18 @@ public void trxCapsuleClearTest() { Assert.assertEquals(trxCap.getInstance() .getRet(0).getContractRet(), Result.contractResult.OUT_OF_TIME); } + + @Test + public void testRemoveRedundantRet() { + Transaction.Builder transaction = Transaction.newBuilder().setRawData(raw.newBuilder() + .addContract(Transaction.Contract.newBuilder().setType(ContractType.TriggerSmartContract)) + .setFeeLimit(1000000000)).build().toBuilder(); + transaction.addRet(Result.newBuilder().setContractRet(SUCCESS).build()); + transaction.addRet(Result.newBuilder().setContractRet(PRECOMPILED_CONTRACT).build()); + transaction.addRet(Result.newBuilder().setContractRet(BAD_JUMP_DESTINATION).build()); + TransactionCapsule transactionCapsule = new TransactionCapsule(transaction.build()); + transactionCapsule.removeRedundantRet(); + Assert.assertEquals(1, transactionCapsule.getInstance().getRetCount()); + Assert.assertEquals(SUCCESS, transactionCapsule.getInstance().getRet(0).getContractRet()); + } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index 053647cc25a..de68af58c50 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -1,5 +1,6 @@ package org.tron.core.db; +import static org.junit.Assert.assertThrows; import static org.tron.common.utils.Commons.adjustAssetBalanceV2; import static org.tron.common.utils.Commons.adjustBalance; import static org.tron.common.utils.Commons.adjustTotalShieldedPoolValue; @@ -8,8 +9,10 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; +import com.google.protobuf.Any; import com.google.protobuf.ByteString; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -1114,4 +1117,37 @@ public void testExpireTransaction() { Assert.fail(); } } + + @Test + public void testTooBigTransaction() { + TransferContract transferContract = + TransferContract.newBuilder() + .setAmount(10) + .setOwnerAddress(ByteString.copyFromUtf8("aaa")) + .setToAddress(ByteString.copyFromUtf8("bbb")) + .build(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 6666; i++) { + sb.append("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + } + Transaction transaction = Transaction.newBuilder().setRawData(Transaction.raw.newBuilder() + .setData(ByteString.copyFrom(sb.toString().getBytes(StandardCharsets.UTF_8))) + .addContract(Transaction.Contract.newBuilder().setParameter(Any.pack(transferContract)) + .setType(ContractType.TransferContract))).build(); + TransactionCapsule trx = new TransactionCapsule(transaction); + trx.setInBlock(false); + assertThrows( + "Too big transaction with result, " + + "TxId 1c05e9fca6a2d0c366ed4430456527eb40198e70c8b20f5ceca4739c68a79af8, " + + "the size is 533483 bytes, maxTxSize 512000", + TooBigTransactionException.class, () -> dbManager.validateCommon(trx)); + + trx.setInBlock(true); + assertThrows( + "Too big transaction, " + + "TxId 1c05e9fca6a2d0c366ed4430456527eb40198e70c8b20f5ceca4739c68a79af8, " + + "the size is 1066643 bytes, maxTxSize 512000", + TooBigTransactionException.class, () -> dbManager.validateCommon(trx)); + + } } diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 41ef968d907..2ffefbf9f3e 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -407,6 +407,7 @@ message Transaction { UNKNOWN = 13; TRANSFER_FAILED = 14; INVALID_CODE = 15; + // please fill in the order according to the serial number } int64 fee = 1; code ret = 2; From 163dedf933aacd9d93b99ced59d537a7a558d7e1 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 30 May 2024 20:07:03 +0800 Subject: [PATCH 1010/1197] update a new version. version name:GreatVoyage-v4.7.4-44-g8720e06a6,version code:18306 --- framework/src/main/java/org/tron/program/Version.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index ee624f6078a..eb21aa292f7 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,8 +2,8 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.7.3.1-78-ge84a9e778"; - public static final String VERSION_CODE = "18260"; + public static final String VERSION_NAME = "GreatVoyage-v4.7.4-44-g8720e06a6"; + public static final String VERSION_CODE = "18306"; private static final String VERSION = "4.7.5"; public static String getVersion() { From 31e05446575b8e7c1974ee60487afbffd06c6238 Mon Sep 17 00:00:00 2001 From: tomatoishealthy Date: Tue, 14 May 2024 14:26:45 +0800 Subject: [PATCH 1011/1197] fix(http/metric): change endpoint variable from member to local --- .../java/org/tron/core/services/filter/HttpInterceptor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java index 2cce8272dd5..8b43cfef642 100644 --- a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java +++ b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java @@ -18,7 +18,6 @@ @Slf4j(topic = "httpInterceptor") public class HttpInterceptor implements Filter { - private String endpoint; private final int HTTP_SUCCESS = 200; private final int HTTP_BAD_REQUEST = 400; private final int HTTP_NOT_ACCEPTABLE = 406; @@ -29,6 +28,7 @@ public void init(FilterConfig filterConfig) { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { + String endpoint = MetricLabels.UNDEFINED; try { if (!(request instanceof HttpServletRequest)) { chain.doFilter(request, response); From 28a07687613cdf5510cb3fc6045e25352df512c6 Mon Sep 17 00:00:00 2001 From: tomatoishealthy Date: Tue, 21 May 2024 15:33:03 +0800 Subject: [PATCH 1012/1197] feat(event): optimize event subscribe exception handling --- .../main/java/org/tron/core/db/Manager.java | 27 ++++++++++++------- .../java/org/tron/core/db/ManagerTest.java | 14 ++++++++++ 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index ef2f5c81124..0dc9b230795 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1321,23 +1321,17 @@ public void pushBlock(final BlockCapsule block) return; } + long oldSolidNum = getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); try (ISession tmpSession = revokingStore.buildSession()) { - - long oldSolidNum = - chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); - applyBlock(newBlock, txs); tmpSession.commit(); - // if event subscribe is enabled, post block trigger to queue - postBlockTrigger(newBlock); - // if event subscribe is enabled, post solidity trigger to queue - postSolidityTrigger(oldSolidNum, - getDynamicPropertiesStore().getLatestSolidifiedBlockNum()); } catch (Throwable throwable) { logger.error(throwable.getMessage(), throwable); khaosDb.removeBlk(block.getBlockId()); throw throwable; } + long newSolidNum = getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); + blockTrigger(newBlock, oldSolidNum, newSolidNum); } logger.info(SAVE_BLOCK, newBlock); } @@ -1367,6 +1361,19 @@ public void pushBlock(final BlockCapsule block) } } + void blockTrigger(final BlockCapsule block, long oldSolid, long newSolid) { + try { + // if event subscribe is enabled, post block trigger to queue + postBlockTrigger(block); + // if event subscribe is enabled, post solidity trigger to queue + postSolidityTrigger(oldSolid, newSolid); + } catch (Exception e) { + logger.error("Block trigger failed. head: {}, oldSolid: {}, newSolid: {}", + block.getNum(), oldSolid, newSolid, e); + System.exit(1); + } + } + public void updateDynamicProperties(BlockCapsule block) { chainBaseManager.getDynamicPropertiesStore() @@ -2206,7 +2213,7 @@ private void postLogsFilter(final BlockCapsule blockCapsule, boolean solidified, } } - private void postBlockTrigger(final BlockCapsule blockCapsule) { + void postBlockTrigger(final BlockCapsule blockCapsule) { // post block and logs for jsonrpc if (CommonParameter.getInstance().isJsonRpcHttpFullNodeEnable()) { postBlockFilter(blockCapsule, false); diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index 10cc766d8ed..ddf741fb6fa 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -1,6 +1,9 @@ package org.tron.core.db; import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.spy; import static org.tron.common.utils.Commons.adjustAssetBalanceV2; import static org.tron.common.utils.Commons.adjustBalance; import static org.tron.common.utils.Commons.adjustTotalShieldedPoolValue; @@ -27,6 +30,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.contrib.java.lang.system.ExpectedSystemExit; import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; import org.tron.common.crypto.ECKey; @@ -107,6 +111,8 @@ public class ManagerTest extends BlockGenerate { private static BlockCapsule blockCapsule2; @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); + @Rule + public final ExpectedSystemExit exit = ExpectedSystemExit.none(); private static AtomicInteger port = new AtomicInteger(0); private static String accountAddress = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; @@ -1151,4 +1157,12 @@ public void testTooBigTransaction() { TooBigTransactionException.class, () -> dbManager.validateCommon(trx)); } + + @Test + public void blockTrigger() { + exit.expectSystemExitWithStatus(1); + Manager manager = spy(new Manager()); + doThrow(new RuntimeException("postBlockTrigger mock")).when(manager).postBlockTrigger(any()); + manager.blockTrigger(new BlockCapsule(Block.newBuilder().build()), 1, 1); + } } From b7401e6c8723f176ac84fb5c62e51f809fa4f26b Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 2 Apr 2024 16:26:39 +0800 Subject: [PATCH 1013/1197] gradlew wrapper --gradle-version=7.6.4 --- gradle/wrapper/gradle-wrapper.jar | Bin 56172 -> 55616 bytes gradle/wrapper/gradle-wrapper.properties | 3 +-- gradlew | 22 +++++++++++++++++++--- gradlew.bat | 18 +++++++++++++++++- 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 28861d273a5d270fd8f65dd74570c17c9c507736..5c2d1cf016b3885f6930543d57b744ea8c220a1a 100644 GIT binary patch delta 47414 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 delta 47982 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 Orw`I9xB+3o!2TZq3*2e| diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1b00285c540..3994438e229 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Thu Aug 01 15:17:43 CST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/gradlew b/gradlew index cccdd3d517f..83f2acfdc31 100755 --- a/gradlew +++ b/gradlew @@ -1,5 +1,21 @@ #!/usr/bin/env sh +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + ############################################################################## ## ## Gradle start up script for UN*X @@ -28,7 +44,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -109,8 +125,8 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` diff --git a/gradlew.bat b/gradlew.bat index e95643d6a2c..24467a141f7 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -14,7 +30,7 @@ set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome From ccaff60c49556cba4feaf91c1df7ce3a9ea7c2b4 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 2 Apr 2024 16:53:58 +0800 Subject: [PATCH 1014/1197] remove unused gradle wrapper --- protocol/gradle/wrapper/gradle-wrapper.jar | Bin 56172 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 ------ 2 files changed, 6 deletions(-) delete mode 100644 protocol/gradle/wrapper/gradle-wrapper.jar delete mode 100644 protocol/gradle/wrapper/gradle-wrapper.properties diff --git a/protocol/gradle/wrapper/gradle-wrapper.jar b/protocol/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 28861d273a5d270fd8f65dd74570c17c9c507736..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56172 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

ZM+x{iQDVZRnLYbdXrQjU&=u%hsN4|smH&B~F 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 b+=;!jU|P+J`>$CfFsoU|bwOU-ceCsYH7qU$ diff --git a/protocol/gradle/wrapper/gradle-wrapper.properties b/protocol/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 1b0ff046d00..00000000000 --- a/protocol/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Thu Aug 01 15:17:43 CST 2019 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip From 285e115b8d41ec7177da6421ccf77da0540aa9a7 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 2 Apr 2024 17:01:02 +0800 Subject: [PATCH 1015/1197] update plugin --- build.gradle | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index a56be97afa1..1abb18f6341 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,10 @@ allprojects { version = "1.0.0" - apply plugin: "java" + apply plugin: "java-library" } subprojects { - apply plugin: "java" apply plugin: "jacoco" - apply plugin: "maven" apply plugin: "maven-publish" sourceCompatibility = JavaVersion.VERSION_1_8 From c33e747c80ba5862b894ae950ef1c6b8d605f5cd Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 2 Apr 2024 17:02:13 +0800 Subject: [PATCH 1016/1197] compile is deprecated replace with implementation or api --- actuator/build.gradle | 6 ++-- build.gradle | 24 ++++++++-------- chainbase/build.gradle | 12 ++++---- common/build.gradle | 34 +++++++++++------------ consensus/build.gradle | 4 +-- crypto/build.gradle | 2 +- example/actuator-example/build.gradle | 2 +- framework/build.gradle | 40 +++++++++++++-------------- plugins/build.gradle | 26 ++++++++--------- protocol/build.gradle | 16 +++++------ 10 files changed, 83 insertions(+), 83 deletions(-) diff --git a/actuator/build.gradle b/actuator/build.gradle index 9b200064fb0..1143dc83618 100644 --- a/actuator/build.gradle +++ b/actuator/build.gradle @@ -1,9 +1,9 @@ description = "actuator – a series of transactions for blockchain." dependencies { - compile project(":chainbase") - compile project(":protocol") - compile project(":crypto") + api project(":chainbase") + api project(":protocol") + api project(":crypto") } test { diff --git a/build.gradle b/build.gradle index 1abb18f6341..3efa4592963 100644 --- a/build.gradle +++ b/build.gradle @@ -34,18 +34,18 @@ subprojects { } dependencies { - compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25' - compile group: 'org.slf4j', name: 'jcl-over-slf4j', version: '1.7.25' - compile group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.9' - compile group: 'com.google.guava', name: 'guava', version: '30.1-jre' - compile "com.google.code.findbugs:jsr305:3.0.0" - compile group: 'org.springframework', name: 'spring-context', version: '5.3.18' - compile group: 'org.springframework', name: 'spring-tx', version: '5.3.18' - compile "org.apache.commons:commons-lang3:3.4" - compile group: 'org.apache.commons', name: 'commons-math', version: '2.2' - compile "org.apache.commons:commons-collections4:4.1" - compile group: 'joda-time', name: 'joda-time', version: '2.3' - compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' + implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25' + implementation group: 'org.slf4j', name: 'jcl-over-slf4j', version: '1.7.25' + implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.9' + implementation group: 'com.google.guava', name: 'guava', version: '30.1-jre' + implementation "com.google.code.findbugs:jsr305:3.0.0" + implementation group: 'org.springframework', name: 'spring-context', version: '5.3.18' + implementation group: 'org.springframework', name: 'spring-tx', version: '5.3.18' + implementation "org.apache.commons:commons-lang3:3.4" + implementation group: 'org.apache.commons', name: 'commons-math', version: '2.2' + implementation "org.apache.commons:commons-collections4:4.1" + implementation group: 'joda-time', name: 'joda-time', version: '2.3' + implementation group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' compileOnly 'org.projectlombok:lombok:1.18.12' annotationProcessor 'org.projectlombok:lombok:1.18.12' diff --git a/chainbase/build.gradle b/chainbase/build.gradle index 408fe56ba42..79a246014d7 100644 --- a/chainbase/build.gradle +++ b/chainbase/build.gradle @@ -7,12 +7,12 @@ def jansiVersion = "1.16" // -------------------------------------- dependencies { - compile project(":protocol") - compile project(":common") - compile project(":crypto") - compile "org.fusesource.jansi:jansi:$jansiVersion" - compile 'io.github.tronprotocol:zksnark-java-sdk:1.0.0' - compile 'org.reflections:reflections:0.9.11' + api project(":protocol") + api project(":common") + api project(":crypto") + api "org.fusesource.jansi:jansi:$jansiVersion" + api 'io.github.tronprotocol:zksnark-java-sdk:1.0.0' + api 'org.reflections:reflections:0.9.11' } diff --git a/common/build.gradle b/common/build.gradle index 6c1545e5d13..08425606237 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -30,30 +30,30 @@ if (isWindows()) { } dependencies { - compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.13.4.1' - compile "com.cedarsoftware:java-util:1.8.0" - compile group: 'org.apache.httpcomponents', name: 'httpasyncclient', version: '4.1.1' - compile group: 'commons-codec', name: 'commons-codec', version: '1.11' - compile group: 'com.beust', name: 'jcommander', version: '1.72' - compile group: 'com.typesafe', name: 'config', version: '1.3.2' - compile group: leveldbGroup, name: leveldbName, version: leveldbVersion - compile group: 'org.rocksdb', name: 'rocksdbjni', version: '5.15.10' + api group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.13.4.1' + api "com.cedarsoftware:java-util:1.8.0" + api group: 'org.apache.httpcomponents', name: 'httpasyncclient', version: '4.1.1' + api group: 'commons-codec', name: 'commons-codec', version: '1.11' + api group: 'com.beust', name: 'jcommander', version: '1.72' + api group: 'com.typesafe', name: 'config', version: '1.3.2' + api group: leveldbGroup, name: leveldbName, version: leveldbVersion + api group: 'org.rocksdb', name: 'rocksdbjni', version: '5.15.10' // https://mvnrepository.com/artifact/org.quartz-scheduler/quartz - compile group: 'org.quartz-scheduler', name: 'quartz', version: '2.3.2' - compile group: 'io.prometheus', name: 'simpleclient', version: '0.15.0' - compile group: 'io.prometheus', name: 'simpleclient_httpserver', version: '0.15.0' - compile group: 'io.prometheus', name: 'simpleclient_hotspot', version: '0.15.0' - compile 'org.aspectj:aspectjrt:1.8.13' - compile 'org.aspectj:aspectjweaver:1.8.13' - compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'io.github.tronprotocol', name: 'libp2p', version: '2.2.1',{ + api group: 'org.quartz-scheduler', name: 'quartz', version: '2.3.2' + api group: 'io.prometheus', name: 'simpleclient', version: '0.15.0' + api group: 'io.prometheus', name: 'simpleclient_httpserver', version: '0.15.0' + api group: 'io.prometheus', name: 'simpleclient_hotspot', version: '0.15.0' + api 'org.aspectj:aspectjrt:1.8.13' + api 'org.aspectj:aspectjweaver:1.8.13' + api 'org.aspectj:aspectjtools:1.8.13' + api group: 'io.github.tronprotocol', name: 'libp2p', version: '2.2.1',{ exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' exclude group: 'com.google.protobuf', module: 'protobuf-java' exclude group: 'com.google.protobuf', module: 'protobuf-java-util' } - compile project(":protocol") + api project(":protocol") } jacocoTestReport { diff --git a/consensus/build.gradle b/consensus/build.gradle index 4ecd7180d13..04cc24be5fd 100644 --- a/consensus/build.gradle +++ b/consensus/build.gradle @@ -1,8 +1,8 @@ description = "consensus – a distributed consensus arithmetic for blockchain." dependencies { - compile project(":chainbase") - compile project(":protocol") + api project(":chainbase") + api project(":protocol") } test { diff --git a/crypto/build.gradle b/crypto/build.gradle index b551471bf49..82814af49e6 100644 --- a/crypto/build.gradle +++ b/crypto/build.gradle @@ -11,7 +11,7 @@ repositories { } dependencies { - compile project(":common") + api project(":common") } jacocoTestReport { diff --git a/example/actuator-example/build.gradle b/example/actuator-example/build.gradle index d0130e11375..e17c75895a1 100644 --- a/example/actuator-example/build.gradle +++ b/example/actuator-example/build.gradle @@ -1,6 +1,6 @@ description = "actuator-example – a example of actuator." dependencies { - compile project(":actuator") + api project(":actuator") } diff --git a/framework/build.gradle b/framework/build.gradle index 8c4fbfc4583..b92ae00ea97 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -38,38 +38,38 @@ task version(type: Exec) { dependencies { //local libraries - compile fileTree(dir: 'libs', include: '*.jar') + implementation fileTree(dir: 'libs', include: '*.jar') // end local libraries - testCompile group: 'org.hamcrest', name: 'hamcrest-junit', version: '1.0.0.1' - testCompile group: 'com.github.stefanbirkner', name: 'system-rules', version: '1.16.0' + testImplementation group: 'org.hamcrest', name: 'hamcrest-junit', version: '1.0.0.1' + testImplementation group: 'com.github.stefanbirkner', name: 'system-rules', version: '1.16.0' - compile group: 'com.google.inject', name: 'guice', version: '4.1.0' - compile group: 'io.dropwizard.metrics', name: 'metrics-core', version: '3.1.2' - compile group: 'com.github.davidb', name: 'metrics-influxdb', version: '0.8.2' - compile group: 'com.carrotsearch', name: 'java-sizeof', version: '0.0.5' + implementation group: 'com.google.inject', name: 'guice', version: '4.1.0' + implementation group: 'io.dropwizard.metrics', name: 'metrics-core', version: '3.1.2' + implementation group: 'com.github.davidb', name: 'metrics-influxdb', version: '0.8.2' + implementation group: 'com.carrotsearch', name: 'java-sizeof', version: '0.0.5' // http - compile 'org.eclipse.jetty:jetty-server:9.4.53.v20231009' - compile 'org.eclipse.jetty:jetty-servlet:9.4.53.v20231009' - compile 'com.alibaba:fastjson:1.2.83' + implementation 'org.eclipse.jetty:jetty-server:9.4.53.v20231009' + implementation 'org.eclipse.jetty:jetty-servlet:9.4.53.v20231009' + implementation 'com.alibaba:fastjson:1.2.83' // end http // https://mvnrepository.com/artifact/com.github.briandilley.jsonrpc4j/jsonrpc4j - compile group: 'com.github.briandilley.jsonrpc4j', name: 'jsonrpc4j', version: '1.6' + implementation group: 'com.github.briandilley.jsonrpc4j', name: 'jsonrpc4j', version: '1.6' // https://mvnrepository.com/artifact/javax.portlet/portlet-api compileOnly group: 'javax.portlet', name: 'portlet-api', version: '3.0.1' - compile "io.vavr:vavr:0.9.2" - compile group: 'org.pf4j', name: 'pf4j', version: '2.5.0' + implementation "io.vavr:vavr:0.9.2" + implementation group: 'org.pf4j', name: 'pf4j', version: '2.5.0' testImplementation group: 'org.springframework', name: 'spring-test', version: '5.2.0.RELEASE' testImplementation group: 'org.springframework', name: 'spring-web', version: '5.2.0.RELEASE' - compile group: 'org.zeromq', name: 'jeromq', version: '0.5.3' - compile project(":chainbase") - compile project(":protocol") - compile project(":actuator") - compile project(":consensus") + implementation group: 'org.zeromq', name: 'jeromq', version: '0.5.3' + api project(":chainbase") + api project(":protocol") + api project(":actuator") + api project(":consensus") } check.dependsOn 'lint' @@ -154,7 +154,7 @@ def binaryRelease(taskName, jarName, mainClass) { } from { - configurations.compile.collect { + configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } @@ -179,7 +179,7 @@ def createScript(project, mainClass, name) { outputDir = new File(project.buildDir, 'scripts') mainClassName = mainClass applicationName = name - classpath = project.tasks[JavaPlugin.JAR_TASK_NAME].outputs.files + project.configurations.runtime + classpath = project.tasks[JavaPlugin.JAR_TASK_NAME].outputs.files + project.configurations.runtimeClasspath // defaultJvmOpts = ['-XX:+UseConcMarkSweepGC', // '-XX:+PrintGCDetails', // '-Xloggc:./gc.log', diff --git a/plugins/build.gradle b/plugins/build.gradle index 7f226d7099c..b85a435dc30 100644 --- a/plugins/build.gradle +++ b/plugins/build.gradle @@ -25,17 +25,17 @@ configurations.getByName('checkstyleConfig') { dependencies { //local libraries - compile fileTree(dir: 'libs', include: '*.jar') - testCompile project(":framework") - testCompile project(":framework").sourceSets.test.output - compile group: 'info.picocli', name: 'picocli', version: '4.6.3' - compile group: 'com.typesafe', name: 'config', version: '1.3.2' - compile group: 'me.tongfei', name: 'progressbar', version: '0.9.3' - compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' - compile group: 'org.rocksdb', name: 'rocksdbjni', version: '5.15.10' - compile 'io.github.tronprotocol:leveldbjni-all:1.18.2' - compile 'io.github.tronprotocol:leveldb:1.18.2' - compile project(":protocol") + implementation fileTree(dir: 'libs', include: '*.jar') + testImplementation project(":framework") + testImplementation project(":framework").sourceSets.test.output + implementation group: 'info.picocli', name: 'picocli', version: '4.6.3' + implementation group: 'com.typesafe', name: 'config', version: '1.3.2' + implementation group: 'me.tongfei', name: 'progressbar', version: '0.9.3' + implementation group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' + implementation group: 'org.rocksdb', name: 'rocksdbjni', version: '5.15.10' + implementation 'io.github.tronprotocol:leveldbjni-all:1.18.2' + implementation 'io.github.tronprotocol:leveldb:1.18.2' + implementation project(":protocol") } check.dependsOn 'lint' @@ -99,7 +99,7 @@ def binaryRelease(taskName, jarName, mainClass) { } from { - configurations.compile.collect { + configurations.runtimeClasspath.collect { // https://docs.gradle.org/current/userguide/upgrading_version_6.html#changes_6.3 it.isDirectory() ? it : zipTree(it) } } @@ -120,7 +120,7 @@ def createScript(project, mainClass, name) { outputDir = new File(project.buildDir, 'scripts') mainClassName = mainClass applicationName = name - classpath = project.tasks[JavaPlugin.JAR_TASK_NAME].outputs.files + project.configurations.runtime + classpath = project.tasks[JavaPlugin.JAR_TASK_NAME].outputs.files + project.configurations.runtimeClasspath } project.tasks[name].dependsOn(project.jar) project.applicationDistribution.with { diff --git a/protocol/build.gradle b/protocol/build.gradle index 922d6d19859..0644004d247 100644 --- a/protocol/build.gradle +++ b/protocol/build.gradle @@ -4,20 +4,20 @@ def protobufVersion = '3.21.12' def grpcVersion = '1.52.1' dependencies { - compile group: 'com.google.protobuf', name: 'protobuf-java', version: protobufVersion - compile group: 'com.google.protobuf', name: 'protobuf-java-util', version: protobufVersion - compile group: 'net.jcip', name: 'jcip-annotations', version: '1.0' + api group: 'com.google.protobuf', name: 'protobuf-java', version: protobufVersion + api group: 'com.google.protobuf', name: 'protobuf-java-util', version: protobufVersion + api group: 'net.jcip', name: 'jcip-annotations', version: '1.0' // checkstyleConfig "com.puppycrawl.tools:checkstyle:${versions.checkstyle}" // google grpc - compile group: 'io.grpc', name: 'grpc-netty', version: grpcVersion - compile group: 'io.grpc', name: 'grpc-protobuf', version: grpcVersion - compile group: 'io.grpc', name: 'grpc-stub', version: grpcVersion - compile group: 'io.grpc', name: 'grpc-services', version: grpcVersion + api group: 'io.grpc', name: 'grpc-netty', version: grpcVersion + api group: 'io.grpc', name: 'grpc-protobuf', version: grpcVersion + api group: 'io.grpc', name: 'grpc-stub', version: grpcVersion + api group: 'io.grpc', name: 'grpc-services', version: grpcVersion // end google grpc - compile group: 'com.google.api.grpc', name: 'proto-google-common-protos', version: '2.15.0' + api group: 'com.google.api.grpc', name: 'proto-google-common-protos', version: '2.15.0' } tasks.matching { it instanceof Test }.all { From 987df9e7944919341760c7b1992d0a7b4ac1399a Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 2 Apr 2024 17:05:02 +0800 Subject: [PATCH 1017/1197] bump com.fasterxml.jackson.core:jackson-databind from 2.13.4.1 to 2.13.4.2 --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 08425606237..028356fe45d 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -30,7 +30,7 @@ if (isWindows()) { } dependencies { - api group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.13.4.1' + api group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.13.4.2' // https://github.com/FasterXML/jackson-databind/issues/3627 api "com.cedarsoftware:java-util:1.8.0" api group: 'org.apache.httpcomponents', name: 'httpasyncclient', version: '4.1.1' api group: 'commons-codec', name: 'commons-codec', version: '1.11' From d718455d289dab34e42834534fac2859339f6e00 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 2 Apr 2024 17:06:20 +0800 Subject: [PATCH 1018/1197] add duplicates strategy --- build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle b/build.gradle index 3efa4592963..0bdbfe6199a 100644 --- a/build.gradle +++ b/build.gradle @@ -59,12 +59,14 @@ subprojects { task sourcesJar(type: Jar, dependsOn: classes) { classifier = "sources" from sourceSets.main.allSource + duplicatesStrategy = DuplicatesStrategy.INCLUDE // allow duplicates } tasks.withType(AbstractArchiveTask) { preserveFileTimestamps = false reproducibleFileOrder = true + duplicatesStrategy = DuplicatesStrategy.INCLUDE // allow duplicates } configurations.all { From 40525fe6b1e4d9e0528071dd995ae2c043e31e5e Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 2 Apr 2024 17:09:37 +0800 Subject: [PATCH 1019/1197] dom4j exclude optional dependencies --- common/build.gradle | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/common/build.gradle b/common/build.gradle index 028356fe45d..f84bf529f81 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -52,6 +52,14 @@ dependencies { exclude group: 'io.grpc', module: 'grpc-netty' exclude group: 'com.google.protobuf', module: 'protobuf-java' exclude group: 'com.google.protobuf', module: 'protobuf-java-util' + // https://github.com/dom4j/dom4j/pull/116 + // https://github.com/gradle/gradle/issues/13656 + // https://github.com/dom4j/dom4j/issues/99 + exclude group: 'jaxen', module: 'jaxen' + exclude group: 'javax.xml.stream', module: 'stax-api' + exclude group: 'net.java.dev.msv', module: 'xsdlib' + exclude group: 'pull-parser', module: 'pull-parser' + exclude group: 'xpp3', module: 'xpp3' } api project(":protocol") } From 6550dfbef312f1e9c9b2e6a83e17fbca59bc068d Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 20 Mar 2024 13:31:53 +0800 Subject: [PATCH 1020/1197] fix(backup/backupServer): make the thread pool close after the netty channel closes --- .../main/java/org/tron/common/backup/socket/BackupServer.java | 2 +- .../test/java/org/tron/common/backup/BackupServerTest.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java b/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java index 2acf1e12633..67739ac50d2 100644 --- a/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java +++ b/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java @@ -95,7 +95,6 @@ public void initChannel(NioDatagramChannel ch) public void close() { logger.info("Closing backup server..."); shutdown = true; - ExecutorServiceManager.shutdownAndAwaitTermination(executor, name); backupManager.stop(); if (channel != null) { try { @@ -104,6 +103,7 @@ public void close() { logger.warn("Closing backup server failed.", e); } } + ExecutorServiceManager.shutdownAndAwaitTermination(executor, name); logger.info("Backup server closed."); } } diff --git a/framework/src/test/java/org/tron/common/backup/BackupServerTest.java b/framework/src/test/java/org/tron/common/backup/BackupServerTest.java index 34b17ec186f..bab587ef68a 100644 --- a/framework/src/test/java/org/tron/common/backup/BackupServerTest.java +++ b/framework/src/test/java/org/tron/common/backup/BackupServerTest.java @@ -37,8 +37,10 @@ public void tearDown() { Args.clearParam(); } - @Test + @Test(timeout = 60_000) public void test() throws InterruptedException { backupServer.initServer(); + // wait for the server to start + Thread.sleep(1000); } } From e8e61fe90622eec919ca5f9bab87fe743de98653 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Fri, 21 Jun 2024 10:01:55 +0800 Subject: [PATCH 1021/1197] feat(net) : optimizing the sortPeers method --- .../org/tron/core/net/peer/PeerManager.java | 6 +++- .../tron/core/net/peer/PeerManagerTest.java | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java index 537f2083691..442e0a3fab1 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java @@ -94,7 +94,11 @@ private static void remove(PeerConnection peerConnection) { } public static synchronized void sortPeers() { - peers.sort(Comparator.comparingDouble(c -> c.getChannel().getAvgLatency())); + try { + peers.sort(Comparator.comparingDouble(c -> c.getChannel().getAvgLatency())); + } catch (Exception e) { + logger.warn("Sort peers failed. {}", e.getMessage()); + } } public static PeerConnection getPeerConnection(Channel channel) { diff --git a/framework/src/test/java/org/tron/core/net/peer/PeerManagerTest.java b/framework/src/test/java/org/tron/core/net/peer/PeerManagerTest.java index a6151da6d1c..b8c03de1029 100644 --- a/framework/src/test/java/org/tron/core/net/peer/PeerManagerTest.java +++ b/framework/src/test/java/org/tron/core/net/peer/PeerManagerTest.java @@ -135,4 +135,32 @@ public void testGetPeers() throws Exception { Assert.assertEquals(2, peers.size()); } + @Test + public void testSortPeers() throws Exception { + PeerConnection p1 = new PeerConnection(); + PeerConnection p2 = new PeerConnection(); + + List peers = new ArrayList<>(); + peers.add(p1); + peers.add(p2); + + Field field = PeerManager.class.getDeclaredField("peers"); + field.setAccessible(true); + field.set(PeerManager.class, Collections.synchronizedList(peers)); + + PeerManager.sortPeers(); + + Channel c1 = new Channel(); + c1.updateAvgLatency(100000L); + ReflectUtils.setFieldValue(p1, "channel", c1); + + Channel c2 = new Channel(); + c2.updateAvgLatency(1000L); + ReflectUtils.setFieldValue(p2, "channel", c2); + + PeerManager.sortPeers(); + + Assert.assertEquals(PeerManager.getPeers().get(0), p2); + } + } From f23cb83431c097d033fbafdb95f77d5b7140664f Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Mon, 24 Jun 2024 15:17:20 +0800 Subject: [PATCH 1022/1197] feat(net): limit SR connections to relay nodes --- .../core/net/service/relay/RelayService.java | 15 ++++++ .../core/net/services/RelayServiceTest.java | 53 ++++++++++++++++++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java index dfc5f2e89da..107d086c1b7 100644 --- a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java @@ -40,6 +40,8 @@ @Component public class RelayService { + private static final int MAX_PEER_COUNT_PER_ADDRESS = 2; + @Autowired private ChainBaseManager chainBaseManager; @@ -139,6 +141,13 @@ public boolean checkHelloMessage(HelloMessage message, Channel channel) { return false; } + if (getPeerCountByAddress(msg.getAddress()) >= MAX_PEER_COUNT_PER_ADDRESS) { + logger.warn("HelloMessage from {}, the number of peers of {} exceeds 2.", + channel.getInetAddress(), + ByteArray.toHexString(msg.getAddress().toByteArray())); + return false; + } + boolean flag; try { Sha256Hash hash = Sha256Hash.of(CommonParameter @@ -164,6 +173,12 @@ public boolean checkHelloMessage(HelloMessage message, Channel channel) { } } + private long getPeerCountByAddress(ByteString address) { + return tronNetDelegate.getActivePeer().stream() + .filter(peer -> peer.getAddress() != null && peer.getAddress().equals(address)) + .count(); + } + private boolean isActiveWitness() { return parameter.isWitness() && keySize > 0 diff --git a/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java b/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java index 777472bdc35..5e22e538e80 100644 --- a/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java @@ -1,31 +1,45 @@ package org.tron.core.net.services; +import static org.mockito.Mockito.mock; + import com.google.common.collect.Lists; import com.google.protobuf.ByteString; +import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Set; import javax.annotation.Resource; + +import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.junit.Assert; -import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.context.ApplicationContext; import org.tron.common.BaseTest; import org.tron.common.utils.ReflectUtils; +import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.args.Args; import org.tron.core.net.P2pEventHandlerImpl; import org.tron.core.net.message.adv.BlockMessage; +import org.tron.core.net.message.handshake.HelloMessage; import org.tron.core.net.peer.Item; import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.peer.PeerManager; import org.tron.core.net.service.relay.RelayService; +import org.tron.p2p.connection.Channel; +import org.tron.p2p.discover.Node; +import org.tron.p2p.utils.NetUtil; import org.tron.protos.Protocol; +@Slf4j(topic = "net") public class RelayServiceTest extends BaseTest { @Resource @@ -49,6 +63,7 @@ public void test() throws Exception { initWitness(); testGetNextWitnesses(); testBroadcast(); + testCheckHelloMessage(); } private void initWitness() { @@ -119,4 +134,38 @@ private ByteString getFromHexString(String s) { return ByteString.copyFrom(Hex.decode(s)); } -} + private void testCheckHelloMessage() { + ByteString address = getFromHexString("A04711BF7AFBDF44557DEFBDF4C4E7AA6138C6331F"); + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); + Node node = new Node(NetUtil.getNodeId(), a1.getAddress().getHostAddress(), + null, a1.getPort()); + HelloMessage helloMessage = new HelloMessage(node, System.currentTimeMillis(), + ChainBaseManager.getChainBaseManager()); + helloMessage.setHelloMessage(helloMessage.getHelloMessage().toBuilder() + .setAddress(address).build()); + Channel c1 = mock(Channel.class); + Mockito.when(c1.getInetSocketAddress()).thenReturn(a1); + Mockito.when(c1.getInetAddress()).thenReturn(a1.getAddress()); + Channel c2 = mock(Channel.class); + Mockito.when(c2.getInetSocketAddress()).thenReturn(a1); + Mockito.when(c2.getInetAddress()).thenReturn(a1.getAddress()); + Args.getInstance().fastForward = true; + ApplicationContext ctx = (ApplicationContext) ReflectUtils.getFieldObject(p2pEventHandler, + "ctx"); + PeerConnection peer1 = PeerManager.add(ctx, c1); + assert peer1 != null; + peer1.setAddress(address); + PeerConnection peer2 = PeerManager.add(ctx, c2); + assert peer2 != null; + peer2.setAddress(address); + try { + Field field = service.getClass().getDeclaredField("witnessScheduleStore"); + field.setAccessible(true); + field.set(service, chainBaseManager.getWitnessScheduleStore()); + boolean res = service.checkHelloMessage(helloMessage, c1); + Assert.assertFalse(res); + } catch (Exception e) { + logger.info("{}", e.getMessage()); + } + } +} \ No newline at end of file From f9e595adf788fc6c45deddd0e8385e2fbd456d6c Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Mon, 1 Jul 2024 14:44:09 +0800 Subject: [PATCH 1023/1197] feat(net): use comparingLong method for sortPeers --- framework/src/main/java/org/tron/core/net/peer/PeerManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java index 442e0a3fab1..f564b90f3ed 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java @@ -95,7 +95,7 @@ private static void remove(PeerConnection peerConnection) { public static synchronized void sortPeers() { try { - peers.sort(Comparator.comparingDouble(c -> c.getChannel().getAvgLatency())); + peers.sort(Comparator.comparingLong(c -> c.getChannel().getAvgLatency())); } catch (Exception e) { logger.warn("Sort peers failed. {}", e.getMessage()); } From 18518a0932832ac217fb30fa97a20c9d4d2c1fa2 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 1 Jul 2024 15:04:55 +0800 Subject: [PATCH 1024/1197] test(CI): add test-retry plugin for test Mitigate flaky tests by retrying tests when they fail. --- framework/build.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/framework/build.gradle b/framework/build.gradle index b92ae00ea97..ec113c93cb1 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -1,4 +1,5 @@ plugins { + id "org.gradle.test-retry" version "1.5.9" id "org.sonarqube" version "2.6" id "com.gorylenko.gradle-git-properties" version "2.4.1" } @@ -113,6 +114,10 @@ run { } test { + retry { + maxRetries = 5 + maxFailures = 20 + } testLogging { exceptionFormat = 'full' } From 8b7ca9f4fb5fd758e5f3044a533ddf6fe19e0e88 Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 4 Jul 2024 10:40:16 +0800 Subject: [PATCH 1025/1197] chore(vm): adjust inappropriate log content --- .../tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index 56366bbdb0c..c8199651a7f 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -84,7 +84,7 @@ public void validate(UnfreezeBalanceV2Param param, Repository repo) if (!checkUnfreezeBalance(accountCapsule, param.getUnfreezeBalance(), param.getResourceType())) { throw new ContractValidateException( - "Invalid unfreeze_balance, [" + param.getUnfreezeBalance() + "] is error"); + "Invalid unfreeze_balance, [" + param.getUnfreezeBalance() + "] is too large"); } } From 2a3d5ca389ad14b08574d15f3d16da80447927ef Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 4 Jul 2024 10:48:16 +0800 Subject: [PATCH 1026/1197] impr(test): optimize some unit tests --- .../runtime/vm/BatchValidateSignContractTest.java | 2 +- .../org/tron/common/runtime/vm/Create2Test.java | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BatchValidateSignContractTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BatchValidateSignContractTest.java index d094f1a3d05..3fa52aa70c0 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BatchValidateSignContractTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BatchValidateSignContractTest.java @@ -79,7 +79,7 @@ public void staticCallTest() { @Test public void correctionTest() { - contract.setConstantCall(false); + contract.setConstantCall(true); List signatures = new ArrayList<>(); List addresses = new ArrayList<>(); byte[] hash = Hash.sha3(longData); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java index 79ed1c7e1f8..a63abd97930 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java @@ -160,9 +160,16 @@ public void testCreate2() // Trigger contract method: deploy(bytes,uint) long salt = 100L; String hexInput = AbiUtil.parseMethod(methodSign, Arrays.asList(testCode, salt)); - TVMTestResult result = TvmTestUtils - .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), - factoryAddress, Hex.decode(hexInput), 0, fee, manager, null); + + TVMTestResult result = null; + for (int i = 1; i < 3; i++) { + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), + factoryAddress, Hex.decode(hexInput), 0, fee, manager, null); + if (result.getRuntime().getRuntimeError() == null) { + break; + } + } Assert.assertNull(result.getRuntime().getRuntimeError()); byte[] returnValue = result.getRuntime().getResult().getHReturn(); From 1555a012434faf22056558d8d5e6683f94c0e9a7 Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 12 Jul 2024 12:29:20 +0800 Subject: [PATCH 1027/1197] func(vm): support for CANCELALLUNFREEZEV2 details --- .../main/java/org/tron/core/vm/VMConstant.java | 2 ++ .../CancelAllUnfreezeV2Processor.java | 13 +++++++++++-- .../java/org/tron/core/vm/program/Program.java | 15 ++++++++++++--- .../tron/common/parameter/CommonParameter.java | 6 ++++++ common/src/main/java/org/tron/core/Constant.java | 1 + .../main/java/org/tron/core/config/args/Args.java | 4 ++++ 6 files changed, 36 insertions(+), 5 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/VMConstant.java b/actuator/src/main/java/org/tron/core/vm/VMConstant.java index 4e7f6b29e3f..abbb6ae6d38 100644 --- a/actuator/src/main/java/org/tron/core/vm/VMConstant.java +++ b/actuator/src/main/java/org/tron/core/vm/VMConstant.java @@ -10,6 +10,8 @@ public class VMConstant { public static final int ONE_THOUSAND = 1000; public static final long SUN_PER_ENERGY = 100; + public static final String WITHDRAW_EXPIRE_BALANCE = "WithdrawExpireBalance"; + private VMConstant() { } } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java index 888071a177b..ec1f4363205 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/CancelAllUnfreezeV2Processor.java @@ -7,6 +7,8 @@ import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; import static org.tron.protos.contract.Common.ResourceCode.ENERGY; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; @@ -14,6 +16,7 @@ import org.tron.core.capsule.AccountCapsule; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; +import org.tron.core.vm.VMConstant; import org.tron.core.vm.nativecontract.param.CancelAllUnfreezeV2Param; import org.tron.core.vm.repository.Repository; import org.tron.protos.Protocol; @@ -38,13 +41,17 @@ public void validate(CancelAllUnfreezeV2Param param, Repository repo) throws Con } } - public long execute(CancelAllUnfreezeV2Param param, Repository repo) throws ContractExeException { + public Map execute(CancelAllUnfreezeV2Param param, Repository repo) throws ContractExeException { + Map result = new HashMap<>(); byte[] ownerAddress = param.getOwnerAddress(); AccountCapsule ownerCapsule = repo.getAccount(ownerAddress); long now = repo.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); long withdrawExpireBalance = 0L; for (Protocol.Account.UnFreezeV2 unFreezeV2: ownerCapsule.getUnfrozenV2List()) { if (unFreezeV2.getUnfreezeExpireTime() > now) { + String resourceName = unFreezeV2.getType().name(); + result.put(resourceName, result.getOrDefault(resourceName, 0L) + unFreezeV2.getUnfreezeAmount()); + updateFrozenInfoAndTotalResourceWeight(ownerCapsule, unFreezeV2, repo); } else { // withdraw @@ -57,7 +64,9 @@ public long execute(CancelAllUnfreezeV2Param param, Repository repo) throws Cont ownerCapsule.clearUnfrozenV2(); repo.updateAccount(ownerCapsule.createDbKey(), ownerCapsule); - return withdrawExpireBalance; + + result.put(VMConstant.WITHDRAW_EXPIRE_BALANCE, withdrawExpireBalance); + return result; } public void updateFrozenInfoAndTotalResourceWeight( diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 0b0ef5bc9ba..25eceb09849 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -1996,13 +1996,22 @@ public boolean cancelAllUnfreezeV2Action() { CancelAllUnfreezeV2Processor processor = new CancelAllUnfreezeV2Processor(); processor.validate(param, repository); - long withdrawExpireBalance = processor.execute(param, repository); + Map result = processor.execute(param, repository); repository.commit(); - if (withdrawExpireBalance > 0) { + + if (result.get(VMConstant.WITHDRAW_EXPIRE_BALANCE) > 0) { increaseNonce(); - addInternalTx(null, owner, owner, withdrawExpireBalance, null, + addInternalTx(null, owner, owner, result.get(VMConstant.WITHDRAW_EXPIRE_BALANCE), null, "withdrawExpireUnfreezeWhileCanceling", nonce, null); } + + if (internalTx != null && CommonParameter.getInstance().saveCancelAllUnfreezeV2Details) { + internalTx.setExtra(String.format("{\"%s\":%s,\"%s\":%d,\"%s\":%d}", + BANDWIDTH.name(), result.getOrDefault(BANDWIDTH.name(), 0L), + ENERGY.name(), result.getOrDefault(ENERGY.name(), 0L), + TRON_POWER.name(), result.getOrDefault(TRON_POWER.name(), 0L))); + } + return true; } catch (ContractValidateException e) { logger.warn("TVM CancelAllUnfreezeV2: validate failure. Reason: {}", e.getMessage()); diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 22159063333..1a4110a3908 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -88,6 +88,12 @@ public class CommonParameter { public boolean saveFeaturedInternalTx; @Getter @Setter + @Parameter(names = {"--save-cancel-all-unfreeze-v2-details"}, description = "Record the details of the internal " + + "transactions generated by the CANCELALLUNFREEZEV2 opcode, such as bandwidth/energy/tronpower cancel amount. " + + "(default: false)") + public boolean saveCancelAllUnfreezeV2Details; + @Getter + @Setter @Parameter(names = {"--long-running-time"}) public int longRunningTime = 10; @Getter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 0e634d3ef7d..fc566702ff3 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -221,6 +221,7 @@ public class Constant { public static final String VM_SAVE_INTERNAL_TX = "vm.saveInternalTx"; public static final String VM_SAVE_FEATURED_INTERNAL_TX = "vm.saveFeaturedInternalTx"; + public static final String VM_SAVE_CANCEL_ALL_UNFREEZE_V2_DETAILS = "vm.saveCancelAllUnfreezeV2Details"; // public static final String COMMITTEE_ALLOW_SHIELDED_TRANSACTION = "committee.allowShieldedTransaction"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 422efefaed8..0d56b06ad7e 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -883,6 +883,10 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.VM_SAVE_FEATURED_INTERNAL_TX) && config.getBoolean(Constant.VM_SAVE_FEATURED_INTERNAL_TX); + PARAMETER.saveCancelAllUnfreezeV2Details = + config.hasPath(Constant.VM_SAVE_CANCEL_ALL_UNFREEZE_V2_DETAILS) + && config.getBoolean(Constant.VM_SAVE_CANCEL_ALL_UNFREEZE_V2_DETAILS); + // PARAMETER.allowShieldedTransaction = // config.hasPath(Constant.COMMITTEE_ALLOW_SHIELDED_TRANSACTION) ? config // .getInt(Constant.COMMITTEE_ALLOW_SHIELDED_TRANSACTION) : 0; From 82d52d9f26b7ccd6bb07aa5b3fb3c19257c45cb9 Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 18 Jul 2024 10:39:16 +0800 Subject: [PATCH 1028/1197] func(vm): change some json format --- actuator/src/main/java/org/tron/core/vm/program/Program.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 25eceb09849..a7a0719695e 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -2006,7 +2006,7 @@ public boolean cancelAllUnfreezeV2Action() { } if (internalTx != null && CommonParameter.getInstance().saveCancelAllUnfreezeV2Details) { - internalTx.setExtra(String.format("{\"%s\":%s,\"%s\":%d,\"%s\":%d}", + internalTx.setExtra(String.format("{\"%s\":%d,\"%s\":%d,\"%s\":%d}", BANDWIDTH.name(), result.getOrDefault(BANDWIDTH.name(), 0L), ENERGY.name(), result.getOrDefault(ENERGY.name(), 0L), TRON_POWER.name(), result.getOrDefault(TRON_POWER.name(), 0L))); From ff69595ca0ef7a30bc7eab62279b4e1fd656a026 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 1 Jul 2024 15:04:55 +0800 Subject: [PATCH 1029/1197] test(CI): add test-retry plugin for test Mitigate flaky tests by retrying tests when they fail. --- framework/build.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/framework/build.gradle b/framework/build.gradle index 8c4fbfc4583..a297faed7a9 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -1,4 +1,5 @@ plugins { + id "org.gradle.test-retry" version "1.5.9" id "org.sonarqube" version "2.6" id "com.gorylenko.gradle-git-properties" version "2.4.1" } @@ -113,6 +114,10 @@ run { } test { + retry { + maxRetries = 5 + maxFailures = 20 + } testLogging { exceptionFormat = 'full' } From 496d64dd1226356c2b3cab1aeed53ff6b94ad3f6 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 18 Jul 2024 15:39:19 +0800 Subject: [PATCH 1030/1197] feat(version): update version to 4.7.6 --- framework/src/main/java/org/tron/program/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index eb21aa292f7..601f555a234 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -4,7 +4,7 @@ public class Version { public static final String VERSION_NAME = "GreatVoyage-v4.7.4-44-g8720e06a6"; public static final String VERSION_CODE = "18306"; - private static final String VERSION = "4.7.5"; + private static final String VERSION = "4.7.6"; public static String getVersion() { return VERSION; From 0dc7a3f01bb56220f7a3028ce30ee3636daf1682 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Mon, 24 Jun 2024 09:53:57 +0800 Subject: [PATCH 1031/1197] feat(net) : optimize the isIdle method --- .../src/main/java/org/tron/core/net/peer/PeerConnection.java | 2 +- .../test/java/org/tron/core/net/peer/PeerConnectionTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index 4fac50b82c7..e66f708b543 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -167,7 +167,7 @@ public void setBlockBothHave(BlockId blockId) { } public boolean isIdle() { - return advInvRequest.isEmpty() && syncBlockRequested.isEmpty() && syncChainRequested == null; + return syncBlockRequested.isEmpty() && syncChainRequested == null; } public void sendMessage(Message message) { diff --git a/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java b/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java index 9db5230ed45..2eaebb2715e 100644 --- a/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java +++ b/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java @@ -78,7 +78,7 @@ public void testIsIdle() { Long time = System.currentTimeMillis(); peerConnection.getAdvInvRequest().put(item, time); f = peerConnection.isIdle(); - Assert.assertTrue(!f); + Assert.assertTrue(f); peerConnection.getAdvInvRequest().clear(); f = peerConnection.isIdle(); From ddbe8f10b32f5e0df3239a7ad66e0f63d9353fb7 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Mon, 1 Jul 2024 14:20:07 +0800 Subject: [PATCH 1032/1197] feat(net): add isSyncIdle method --- .../tron/core/net/peer/PeerConnection.java | 4 +++ .../core/net/service/sync/SyncService.java | 4 +-- .../core/net/peer/PeerConnectionTest.java | 32 ++++++++++++++++++- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index e66f708b543..1c7560559e1 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -167,6 +167,10 @@ public void setBlockBothHave(BlockId blockId) { } public boolean isIdle() { + return advInvRequest.isEmpty() && isSyncIdle(); + } + + public boolean isSyncIdle() { return syncBlockRequested.isEmpty() && syncChainRequested == null; } diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 9453700df0d..8c673977962 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -134,7 +134,7 @@ public void processBlock(PeerConnection peer, BlockMessage blockMessage) { blockJustReceived.put(blockMessage, peer); } handleFlag = true; - if (peer.isIdle()) { + if (peer.isSyncIdle()) { if (peer.getRemainNum() > 0 && peer.getSyncBlockToFetch().size() <= syncFetchBatchNum) { syncNext(peer); @@ -226,7 +226,7 @@ private BlockId getBlockIdByNum(long num) throws P2pException { private void startFetchSyncBlock() { HashMap> send = new HashMap<>(); tronNetDelegate.getActivePeer().stream() - .filter(peer -> peer.isNeedSyncFromPeer() && peer.isIdle()) + .filter(peer -> peer.isNeedSyncFromPeer() && peer.isSyncIdle()) .filter(peer -> peer.isFetchAble()) .forEach(peer -> { if (!send.containsKey(peer)) { diff --git a/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java b/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java index 2eaebb2715e..5a67cd8f609 100644 --- a/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java +++ b/framework/src/test/java/org/tron/core/net/peer/PeerConnectionTest.java @@ -78,7 +78,7 @@ public void testIsIdle() { Long time = System.currentTimeMillis(); peerConnection.getAdvInvRequest().put(item, time); f = peerConnection.isIdle(); - Assert.assertTrue(f); + Assert.assertTrue(!f); peerConnection.getAdvInvRequest().clear(); f = peerConnection.isIdle(); @@ -98,6 +98,36 @@ public void testIsIdle() { Assert.assertTrue(!f); } + @Test + public void testIsSyncIdle() { + PeerConnection peerConnection = new PeerConnection(); + boolean f = peerConnection.isSyncIdle(); + Assert.assertTrue(f); + + Item item = new Item(Sha256Hash.ZERO_HASH, Protocol.Inventory.InventoryType.TRX); + Long time = System.currentTimeMillis(); + peerConnection.getAdvInvRequest().put(item, time); + f = peerConnection.isSyncIdle(); + Assert.assertTrue(f); + + peerConnection.getAdvInvRequest().clear(); + f = peerConnection.isSyncIdle(); + Assert.assertTrue(f); + + BlockCapsule.BlockId blockId = new BlockCapsule.BlockId(); + peerConnection.getSyncBlockRequested().put(blockId, time); + f = peerConnection.isSyncIdle(); + Assert.assertTrue(!f); + + peerConnection.getSyncBlockRequested().clear(); + f = peerConnection.isSyncIdle(); + Assert.assertTrue(f); + + peerConnection.setSyncChainRequested(new Pair<>(new LinkedList<>(), time)); + f = peerConnection.isSyncIdle(); + Assert.assertTrue(!f); + } + @Test public void testOnConnect() { PeerConnection peerConnection = new PeerConnection(); From 0779c0091cac1b184b6c5755ebd844b63661497a Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Tue, 25 Jun 2024 18:53:38 +0800 Subject: [PATCH 1033/1197] feat(net): optimize fetch inventory message check logic --- .../FetchInvDataMsgHandler.java | 4 +++ .../FetchInvDataMsgHandlerTest.java | 35 +++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java index 5e797c084b3..5415ea435e3 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java @@ -164,6 +164,10 @@ private void check(PeerConnection peer, FetchInvDataMessage fetchInvDataMsg) thr throw new P2pException(TypeEnum.BAD_MESSAGE, "minBlockNum: " + minBlockNum + ", blockNum: " + blockNum); } + if (blockNum > peer.getLastSyncBlockId().getNum()) { + throw new P2pException(TypeEnum.BAD_MESSAGE, + "maxBlockNum: " + peer.getLastSyncBlockId().getNum() + ", blockNum: " + blockNum); + } if (peer.getSyncBlockIdCache().getIfPresent(hash) != null) { throw new P2pException(TypeEnum.BAD_MESSAGE, new BlockId(hash).getString() + " is exist"); diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandlerTest.java index 404d275276a..5fd6d6725ba 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandlerTest.java @@ -21,8 +21,6 @@ import org.tron.core.net.service.adv.AdvService; import org.tron.protos.Protocol; - - public class FetchInvDataMsgHandlerTest { @Test @@ -62,4 +60,37 @@ public void testProcessMessage() throws Exception { new FetchInvDataMessage(blockIds, Protocol.Inventory.InventoryType.BLOCK)); Assert.assertNotNull(syncBlockIdCache.getIfPresent(blockId)); } + + @Test + public void testSyncFetchCheck() { + BlockCapsule.BlockId blockId = new BlockCapsule.BlockId(Sha256Hash.ZERO_HASH, 10000L); + List blockIds = new LinkedList<>(); + blockIds.add(blockId); + FetchInvDataMessage msg = + new FetchInvDataMessage(blockIds, Protocol.Inventory.InventoryType.BLOCK); + + PeerConnection peer = Mockito.mock(PeerConnection.class); + Mockito.when(peer.isNeedSyncFromUs()).thenReturn(true); + Cache advInvSpread = CacheBuilder.newBuilder().maximumSize(100) + .expireAfterWrite(1, TimeUnit.HOURS).recordStats().build(); + Mockito.when(peer.getAdvInvSpread()).thenReturn(advInvSpread); + + FetchInvDataMsgHandler fetchInvDataMsgHandler = new FetchInvDataMsgHandler(); + + try { + Mockito.when(peer.getLastSyncBlockId()) + .thenReturn(new BlockCapsule.BlockId(Sha256Hash.ZERO_HASH, 1000L)); + fetchInvDataMsgHandler.processMessage(peer, msg); + } catch (Exception e) { + Assert.assertEquals(e.getMessage(), "maxBlockNum: 1000, blockNum: 10000"); + } + + try { + Mockito.when(peer.getLastSyncBlockId()) + .thenReturn(new BlockCapsule.BlockId(Sha256Hash.ZERO_HASH, 20000L)); + fetchInvDataMsgHandler.processMessage(peer, msg); + } catch (Exception e) { + Assert.assertEquals(e.getMessage(), "minBlockNum: 16000, blockNum: 10000"); + } + } } From fdbfa17e1d99a5627fc8863e719889ff38ab7537 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Fri, 21 Jun 2024 10:01:55 +0800 Subject: [PATCH 1034/1197] feat(net) : optimizing the sortPeers method --- .../org/tron/core/net/peer/PeerManager.java | 6 +++- .../tron/core/net/peer/PeerManagerTest.java | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java index 537f2083691..442e0a3fab1 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java @@ -94,7 +94,11 @@ private static void remove(PeerConnection peerConnection) { } public static synchronized void sortPeers() { - peers.sort(Comparator.comparingDouble(c -> c.getChannel().getAvgLatency())); + try { + peers.sort(Comparator.comparingDouble(c -> c.getChannel().getAvgLatency())); + } catch (Exception e) { + logger.warn("Sort peers failed. {}", e.getMessage()); + } } public static PeerConnection getPeerConnection(Channel channel) { diff --git a/framework/src/test/java/org/tron/core/net/peer/PeerManagerTest.java b/framework/src/test/java/org/tron/core/net/peer/PeerManagerTest.java index a6151da6d1c..b8c03de1029 100644 --- a/framework/src/test/java/org/tron/core/net/peer/PeerManagerTest.java +++ b/framework/src/test/java/org/tron/core/net/peer/PeerManagerTest.java @@ -135,4 +135,32 @@ public void testGetPeers() throws Exception { Assert.assertEquals(2, peers.size()); } + @Test + public void testSortPeers() throws Exception { + PeerConnection p1 = new PeerConnection(); + PeerConnection p2 = new PeerConnection(); + + List peers = new ArrayList<>(); + peers.add(p1); + peers.add(p2); + + Field field = PeerManager.class.getDeclaredField("peers"); + field.setAccessible(true); + field.set(PeerManager.class, Collections.synchronizedList(peers)); + + PeerManager.sortPeers(); + + Channel c1 = new Channel(); + c1.updateAvgLatency(100000L); + ReflectUtils.setFieldValue(p1, "channel", c1); + + Channel c2 = new Channel(); + c2.updateAvgLatency(1000L); + ReflectUtils.setFieldValue(p2, "channel", c2); + + PeerManager.sortPeers(); + + Assert.assertEquals(PeerManager.getPeers().get(0), p2); + } + } From ea14933e02ec001650196c3113b1ee9889007b28 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Mon, 1 Jul 2024 14:44:09 +0800 Subject: [PATCH 1035/1197] feat(net): use comparingLong method for sortPeers --- framework/src/main/java/org/tron/core/net/peer/PeerManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java index 442e0a3fab1..f564b90f3ed 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java @@ -95,7 +95,7 @@ private static void remove(PeerConnection peerConnection) { public static synchronized void sortPeers() { try { - peers.sort(Comparator.comparingDouble(c -> c.getChannel().getAvgLatency())); + peers.sort(Comparator.comparingLong(c -> c.getChannel().getAvgLatency())); } catch (Exception e) { logger.warn("Sort peers failed. {}", e.getMessage()); } From 3b3b6686b9e79fd7d02cbad42a4cbee8f3725dbd Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 18 Jul 2024 16:30:20 +0800 Subject: [PATCH 1036/1197] initial commit of test isolated --- .../java/org/tron/core/ChainBaseManager.java | 5 + .../common/parameter/CommonParameter.java | 3 + .../src/main/java/org/tron/core/Constant.java | 2 + .../java/org/tron/core/config/args/Args.java | 4 + .../main/java/org/tron/core/db/Manager.java | 1 + .../org/tron/core/net/TronNetService.java | 8 +- .../net/messagehandler/BlockMsgHandler.java | 1 + .../ChainInventoryMsgHandler.java | 1 + .../FetchInvDataMsgHandler.java | 1 + .../messagehandler/InventoryMsgHandler.java | 3 + .../SyncBlockChainMsgHandler.java | 2 +- .../tron/core/net/peer/PeerConnection.java | 5 + .../service/effective/ResilienceService.java | 170 ++++++++++++++++ .../src/main/resources/config-localtest.conf | 1 + framework/src/main/resources/config.conf | 1 + .../net/services/ResilienceServiceTest.java | 182 ++++++++++++++++++ framework/src/test/resources/args-test.conf | 1 + .../src/test/resources/config-localtest.conf | 1 + framework/src/test/resources/config-test.conf | 1 + 19 files changed, 391 insertions(+), 2 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java create mode 100644 framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java diff --git a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java index e43d442534a..d148021f6c4 100644 --- a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java +++ b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java @@ -244,6 +244,10 @@ public class ChainBaseManager { @Setter private long lowestBlockNum = -1; // except num = 0. + @Getter + @Setter + private long latestSaveBlockTime; + // for test only public List getWitnesses() { return witnessScheduleStore.getActiveWitnesses(); @@ -381,6 +385,7 @@ private void init() { this.lowestBlockNum = this.blockIndexStore.getLimitNumber(1, 1).stream() .map(BlockId::getNum).findFirst().orElse(0L); this.nodeType = getLowestBlockNum() > 1 ? NodeType.LITE : NodeType.FULL; + this.latestSaveBlockTime = System.currentTimeMillis(); } public void shutdown() { diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 22159063333..62ed12d856c 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -333,6 +333,9 @@ public class CommonParameter { public boolean isOpenFullTcpDisconnect; @Getter @Setter + public int inactiveThreshold; + @Getter + @Setter public boolean nodeDetectEnable; @Getter @Setter diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 0e634d3ef7d..da3b2b1becc 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -198,6 +198,8 @@ public class Constant { public static final String NODE_IS_OPEN_FULL_TCP_DISCONNECT = "node.isOpenFullTcpDisconnect"; + public static final String NODE_INACTIVE_THRESHOLD = "node.inactiveThreshold"; + public static final String NODE_DETECT_ENABLE = "node.nodeDetectEnable"; public static final String NODE_MAX_TRANSACTION_PENDING_SIZE = "node.maxTransactionPendingSize"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 422efefaed8..7b089530a41 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -173,6 +173,7 @@ public static void clearParam() { PARAMETER.receiveTcpMinDataLength = 2048; PARAMETER.isOpenFullTcpDisconnect = false; PARAMETER.nodeDetectEnable = false; + PARAMETER.inactiveThreshold = 600; PARAMETER.supportConstant = false; PARAMETER.debug = false; PARAMETER.minTimeRatio = 0.0; @@ -845,6 +846,9 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.nodeDetectEnable = config.hasPath(Constant.NODE_DETECT_ENABLE) && config.getBoolean(Constant.NODE_DETECT_ENABLE); + PARAMETER.inactiveThreshold = config.hasPath(Constant.NODE_INACTIVE_THRESHOLD) + ? config.getInt(Constant.NODE_INACTIVE_THRESHOLD) : 600; + PARAMETER.maxTransactionPendingSize = config.hasPath(Constant.NODE_MAX_TRANSACTION_PENDING_SIZE) ? config.getInt(Constant.NODE_MAX_TRANSACTION_PENDING_SIZE) : 2000; diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index ef2f5c81124..66aeccdda39 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1384,6 +1384,7 @@ public void updateDynamicProperties(BlockCapsule block) { (chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() - chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum() + 1)); + chainBaseManager.setLatestSaveBlockTime(System.currentTimeMillis()); Metrics.gaugeSet(MetricKeys.Gauge.HEADER_HEIGHT, block.getNum()); Metrics.gaugeSet(MetricKeys.Gauge.HEADER_TIME, block.getTimeStamp()); } diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 03becf5d4e9..5b99f94c0db 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -22,6 +22,7 @@ import org.tron.core.net.peer.PeerStatusCheck; import org.tron.core.net.service.adv.AdvService; import org.tron.core.net.service.effective.EffectiveCheckService; +import org.tron.core.net.service.effective.ResilienceService; import org.tron.core.net.service.fetchblock.FetchBlockService; import org.tron.core.net.service.nodepersist.NodePersistService; import org.tron.core.net.service.relay.RelayService; @@ -50,6 +51,9 @@ public class TronNetService { @Autowired private PeerStatusCheck peerStatusCheck; + @Autowired + private ResilienceService resilienceService; + @Autowired private TransactionsMsgHandler transactionsMsgHandler; @@ -88,6 +92,7 @@ public void start() { advService.init(); syncService.init(); peerStatusCheck.init(); + resilienceService.init(); transactionsMsgHandler.init(); fetchBlockService.init(); nodePersistService.init(); @@ -110,6 +115,7 @@ public void close() { nodePersistService.close(); advService.close(); syncService.close(); + resilienceService.close(); peerStatusCheck.close(); transactionsMsgHandler.close(); fetchBlockService.close(); @@ -177,7 +183,7 @@ private P2pConfig updateConfig(P2pConfig config) { config.setMaxConnectionsWithSameIp(parameter.getMaxConnectionsWithSameIp()); config.setPort(parameter.getNodeListenPort()); config.setNetworkId(parameter.getNodeP2pVersion()); - config.setDisconnectionPolicyEnable(parameter.isOpenFullTcpDisconnect()); + config.setDisconnectionPolicyEnable(false); config.setNodeDetectEnable(parameter.isNodeDetectEnable()); config.setDiscoverEnable(parameter.isNodeDiscoveryEnable()); if (StringUtils.isEmpty(config.getIp()) && hasIpv4Stack(NetUtil.getAllLocalAddress())) { diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java index 926ed1a01ca..547f96036cb 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java @@ -76,6 +76,7 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep if (!fastForward && !peer.isRelayPeer()) { check(peer, blockMessage); } + peer.setLastActiveTime(System.currentTimeMillis()); if (peer.getSyncBlockRequested().containsKey(blockId)) { peer.getSyncBlockRequested().remove(blockId); diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java index bd2e428418c..4f99deb146b 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java @@ -142,6 +142,7 @@ private void check(PeerConnection peer, ChainInventoryMessage msg) throws P2pExc + msg.getRemainNum() + " > futureMaxNum: " + maxFutureNum); } } + peer.setLastActiveTime(System.currentTimeMillis()); } } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java index 5e797c084b3..2c4e94a66fa 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java @@ -171,6 +171,7 @@ private void check(PeerConnection peer, FetchInvDataMessage fetchInvDataMsg) thr peer.getSyncBlockIdCache().put(hash, System.currentTimeMillis()); } } + peer.setLastActiveTime(System.currentTimeMillis()); } } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java index a8ad8d0ec73..5e303bd3d6f 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java @@ -39,6 +39,9 @@ public void processMessage(PeerConnection peer, TronMessage msg) { Item item = new Item(id, type); peer.getAdvInvReceive().put(item, System.currentTimeMillis()); advService.addInv(item); + if (type.equals(InventoryType.BLOCK) && peer.getAdvInvSpread().getIfPresent(item) == null) { + peer.setLastActiveTime(System.currentTimeMillis()); + } } } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java index 958ebfe5561..e03e039ac4d 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java @@ -33,7 +33,7 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep peer.disconnect(Protocol.ReasonCode.BAD_PROTOCOL); return; } - + peer.setLastActiveTime(System.currentTimeMillis()); long remainNum = 0; List summaryChainIds = syncBlockChainMessage.getBlockIds(); diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index 4fac50b82c7..66903e7c64e 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -79,6 +79,10 @@ public class PeerConnection { @Setter private ByteString address; + @Getter + @Setter + private long lastActiveTime; + @Getter @Setter private TronState tronState = TronState.INIT; @@ -159,6 +163,7 @@ public void setChannel(Channel channel) { this.isRelayPeer = true; } this.nodeStatistics = TronStatsManager.getNodeStatistics(channel.getInetAddress()); + lastActiveTime = System.currentTimeMillis(); } public void setBlockBothHave(BlockId blockId) { diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java new file mode 100644 index 00000000000..bdf5892f260 --- /dev/null +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -0,0 +1,170 @@ +package org.tron.core.net.service.effective; + +import java.util.Comparator; +import java.util.List; +import java.util.Optional; +import java.util.Random; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.es.ExecutorServiceManager; +import org.tron.common.parameter.CommonParameter; +import org.tron.core.ChainBaseManager; +import org.tron.core.config.args.Args; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.peer.PeerConnection; +import org.tron.protos.Protocol.ReasonCode; + +@Slf4j(topic = "net") +@Component +public class ResilienceService { + + private final long inactiveThreshold = + CommonParameter.getInstance().getInactiveThreshold() * 1000L; + public static final long blockNotChangeThreshold = 90 * 1000L; + + //when node is isolated, retention percent peers will not be disconnected + public static final double retentionPercent = 0.8; + private static final int initialDelay = 300; + private final String esName = "resilience-service"; + + @Autowired + private TronNetDelegate tronNetDelegate; + + @Autowired + private ChainBaseManager chainBaseManager; + + private ScheduledExecutorService executor; + + public void init() { + executor = ExecutorServiceManager.newSingleThreadScheduledExecutor(esName); + + if (Args.getInstance().isOpenFullTcpDisconnect) { + executor.scheduleWithFixedDelay(() -> { + try { + disconnectRandom(); + } catch (Exception e) { + logger.error("DisconnectRandom node failed", e); + } + }, initialDelay, 60, TimeUnit.SECONDS); + } else { + logger.info("OpenFullTcpDisconnect is disabled"); + } + + executor.scheduleWithFixedDelay(() -> { + try { + disconnectLan(); + } catch (Exception e) { + logger.error("DisconnectLan node failed", e); + } + }, initialDelay, 10, TimeUnit.SECONDS); + + executor.scheduleWithFixedDelay(() -> { + try { + disconnectIsolated2(); + } catch (Exception e) { + logger.error("DisconnectIsolated node failed", e); + } + }, initialDelay, 30, TimeUnit.SECONDS); + } + + private void disconnectRandom() { + int peerSize = tronNetDelegate.getActivePeer().size(); + if (peerSize >= CommonParameter.getInstance().getMaxConnections()) { + long now = System.currentTimeMillis(); + List peers = tronNetDelegate.getActivePeer().stream() + .filter(peer -> !peer.isDisconnect()) + .filter(peer -> now - peer.getLastActiveTime() >= inactiveThreshold) + .filter(peer -> !peer.getChannel().isTrustPeer()) + .collect(Collectors.toList()); + if (!peers.isEmpty()) { + int index = new Random().nextInt(peers.size()); + disconnectFromPeer(peers.get(index), ReasonCode.RANDOM_ELIMINATION); + } + } + } + + private void disconnectLan() { + if (isLanNode()) { + // disconnect from the node that has keep inactive for more than inactiveThreshold + // and its lastActiveTime is smallest + int peerSize = tronNetDelegate.getActivePeer().size(); + if (peerSize >= CommonParameter.getInstance().getMinConnections()) { + long now = System.currentTimeMillis(); + Optional one = tronNetDelegate.getActivePeer().stream() + .filter(peer -> !peer.isDisconnect()) + .filter(peer -> now - peer.getLastActiveTime() >= inactiveThreshold) + .filter(peer -> !peer.getChannel().isTrustPeer()) + .min(Comparator.comparing(PeerConnection::getLastActiveTime, Long::compareTo)); + + one.ifPresent(peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL)); + } + } + } + + private void disconnectIsolated2() { + if (isIsolateLand2()) { + logger.info("Node is isolated, try to disconnect from peers"); + int peerSize = tronNetDelegate.getActivePeer().size(); + + //disconnect from the node whose lastActiveTime is smallest + if (peerSize >= CommonParameter.getInstance().getMinActiveConnections()) { + Optional one = tronNetDelegate.getActivePeer().stream() + .filter(peer -> !peer.isDisconnect()) + .filter(peer -> !peer.getChannel().isTrustPeer()) + .filter(peer -> peer.getChannel().isActive()) + .min(Comparator.comparing(PeerConnection::getLastActiveTime, Long::compareTo)); + + one.ifPresent(peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL)); + } + + //disconnect from some passive nodes, make sure retention nodes' num <= 0.8 * maxConnection + peerSize = tronNetDelegate.getActivePeer().size(); + int threshold = (int) (CommonParameter.getInstance().getMaxConnections() * retentionPercent); + if (peerSize > threshold) { + int disconnectSize = peerSize - threshold; + List peers = tronNetDelegate.getActivePeer().stream() + .filter(peer -> !peer.isDisconnect()) + .filter(peer -> !peer.getChannel().isTrustPeer()) + .filter(peer -> !peer.getChannel().isActive()) + .sorted(Comparator.comparing(PeerConnection::getLastActiveTime, Long::compareTo)) + .collect(Collectors.toList()); + + if (peers.size() > disconnectSize) { + peers = peers.subList(0, disconnectSize); + } + peers.forEach(peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL)); + } + } + } + + private boolean isLanNode() { + int peerSize = tronNetDelegate.getActivePeer().size(); + int activePeerSize = (int) tronNetDelegate.getActivePeer().stream() + .filter(peer -> peer.getChannel().isActive()) + .count(); + return peerSize > 0 && peerSize == activePeerSize; + } + + private boolean isIsolateLand2() { + int advPeerCount = (int) tronNetDelegate.getActivePeer().stream() + .filter(peer -> !peer.isNeedSyncFromPeer() && !peer.isNeedSyncFromUs()) + .count(); + long diff = System.currentTimeMillis() - chainBaseManager.getLatestSaveBlockTime(); + return advPeerCount >= 1 && diff >= blockNotChangeThreshold; + } + + private void disconnectFromPeer(PeerConnection peer, ReasonCode reasonCode) { + int inactiveSeconds = (int) ((System.currentTimeMillis() - peer.getLastActiveTime()) / 1000); + logger.info("Disconnect from peer {}, inactive seconds {}", peer.getInetSocketAddress(), + inactiveSeconds); + peer.disconnect(reasonCode); + } + + public void close() { + ExecutorServiceManager.shutdownAndAwaitTermination(executor, esName); + } +} diff --git a/framework/src/main/resources/config-localtest.conf b/framework/src/main/resources/config-localtest.conf index f1ac104c9ed..e1c0d55b002 100644 --- a/framework/src/main/resources/config-localtest.conf +++ b/framework/src/main/resources/config-localtest.conf @@ -99,6 +99,7 @@ node { # check the peer data transfer ,disconnect factor isOpenFullTcpDisconnect = true + inactiveThreshold = 600 p2p { version = 333 # 11111: mainnet; 20180622: testnet diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 78427c30f87..3b4a2b64968 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -180,6 +180,7 @@ node { minParticipationRate = 15 isOpenFullTcpDisconnect = false + inactiveThreshold = 600 p2p { version = 11111 # 11111: mainnet; 20180622: testnet diff --git a/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java b/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java new file mode 100644 index 00000000000..a8b8e04d3cb --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java @@ -0,0 +1,182 @@ +package org.tron.core.net.services; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.spy; + +import io.netty.channel.ChannelHandlerContext; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.HashSet; +import java.util.Set; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.mockito.Mockito; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.ReflectUtils; +import org.tron.core.ChainBaseManager; +import org.tron.core.Constant; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.peer.PeerManager; +import org.tron.core.net.service.effective.ResilienceService; +import org.tron.p2p.connection.Channel; + +public class ResilienceServiceTest { + + protected TronApplicationContext context; + private ResilienceService service; + private ChainBaseManager chainBaseManager; + + @Rule + public final TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Before + public void init() throws IOException { + Args.setParam(new String[] {"--output-directory", + temporaryFolder.newFolder().toString(), "--debug"}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + chainBaseManager = context.getBean(ChainBaseManager.class); + service = context.getBean(ResilienceService.class); + } + + @Test + public void testDisconnectRandom() { + int maxConnection = 30; + Assert.assertEquals(maxConnection, Args.getInstance().getMaxConnections()); + clearPeers(); + Assert.assertEquals(0, PeerManager.getPeers().size()); + + for (int i = 0; i < maxConnection; i++) { + InetSocketAddress inetSocketAddress = new InetSocketAddress("201.0.0." + i, 10001); + Channel c1 = spy(Channel.class); + ReflectUtils.setFieldValue(c1, "inetSocketAddress", inetSocketAddress); + ReflectUtils.setFieldValue(c1, "inetAddress", inetSocketAddress.getAddress()); + ReflectUtils.setFieldValue(c1, "ctx", spy(ChannelHandlerContext.class)); + Mockito.doNothing().when(c1).send((byte[]) any()); + + PeerManager.add(context, c1); + } + ReflectUtils.invokeMethod(service, "disconnectRandom"); + Assert.assertEquals(maxConnection, PeerManager.getPeers().size()); + + PeerConnection p1 = PeerManager.getPeers().get(1); + p1.setLastActiveTime( + System.currentTimeMillis() - Args.getInstance().inactiveThreshold * 1000L - 1000); + PeerConnection p2 = PeerManager.getPeers().get(10); + p2.setLastActiveTime( + System.currentTimeMillis() - Args.getInstance().inactiveThreshold * 1000L - 2000); + + ReflectUtils.invokeMethod(service, "disconnectRandom"); + Assert.assertEquals(maxConnection - 1, PeerManager.getPeers().size()); + } + + @Test + public void testDisconnectLan() { + int minConnection = 8; + Assert.assertEquals(minConnection, Args.getInstance().getMinConnections()); + clearPeers(); + Assert.assertEquals(0, PeerManager.getPeers().size()); + + for (int i = 0; i < 9; i++) { + InetSocketAddress inetSocketAddress = new InetSocketAddress("201.0.0." + i, 10001); + Channel c1 = spy(Channel.class); + ReflectUtils.setFieldValue(c1, "inetSocketAddress", inetSocketAddress); + ReflectUtils.setFieldValue(c1, "inetAddress", inetSocketAddress.getAddress()); + ReflectUtils.setFieldValue(c1, "isActive", true); + ReflectUtils.setFieldValue(c1, "ctx", spy(ChannelHandlerContext.class)); + Mockito.doNothing().when(c1).send((byte[]) any()); + + PeerManager.add(context, c1); + } + + Assert.assertEquals(9, PeerManager.getPeers().size()); + + boolean isLan = ReflectUtils.invokeMethod(service, "isLanNode"); + Assert.assertTrue(isLan); + + PeerConnection p1 = PeerManager.getPeers().get(1); + InetSocketAddress address1 = p1.getChannel().getInetSocketAddress(); + p1.setLastActiveTime( + System.currentTimeMillis() - Args.getInstance().inactiveThreshold * 1000L - 1000); + PeerConnection p2 = PeerManager.getPeers().get(2); + InetSocketAddress address2 = p2.getChannel().getInetSocketAddress(); + p2.setLastActiveTime( + System.currentTimeMillis() - Args.getInstance().inactiveThreshold * 1000L - 2000); + + ReflectUtils.invokeMethod(service, "disconnectLan"); + Assert.assertEquals(8, PeerManager.getPeers().size()); + Set addressSet = new HashSet<>(); + PeerManager.getPeers() + .forEach(p -> addressSet.add(p.getChannel().getInetSocketAddress())); + Assert.assertTrue(addressSet.contains(address1)); + Assert.assertFalse(addressSet.contains(address2)); + + ReflectUtils.invokeMethod(service, "disconnectLan"); + Assert.assertEquals(7, PeerManager.getPeers().size()); + addressSet.clear(); + PeerManager.getPeers() + .forEach(p -> addressSet.add(p.getChannel().getInetSocketAddress())); + Assert.assertFalse(addressSet.contains(address1)); + + ReflectUtils.invokeMethod(service, "disconnectLan"); + Assert.assertEquals(7, PeerManager.getPeers().size()); + } + + @Test + public void testDisconnectIsolated2() { + int maxConnection = 30; + Assert.assertEquals(maxConnection, Args.getInstance().getMaxConnections()); + clearPeers(); + Assert.assertEquals(0, PeerManager.getPeers().size()); + + int addSize = (int) (maxConnection * ResilienceService.retentionPercent) + 2; //26 + for (int i = 0; i < addSize; i++) { + InetSocketAddress inetSocketAddress = new InetSocketAddress("201.0.0." + i, 10001); + Channel c1 = spy(Channel.class); + ReflectUtils.setFieldValue(c1, "inetSocketAddress", inetSocketAddress); + ReflectUtils.setFieldValue(c1, "inetAddress", inetSocketAddress.getAddress()); + // 1 ~ 3 is active, 4 ~ 26 is not active + ReflectUtils.setFieldValue(c1, "isActive", i <= 2); + ReflectUtils.setFieldValue(c1, "ctx", spy(ChannelHandlerContext.class)); + Mockito.doNothing().when(c1).send((byte[]) any()); + + PeerManager.add(context, c1); + } + PeerManager.getPeers().get(10).setNeedSyncFromUs(false); + PeerManager.getPeers().get(10).setNeedSyncFromPeer(false); + chainBaseManager.setLatestSaveBlockTime( + System.currentTimeMillis() - ResilienceService.blockNotChangeThreshold - 100L); + boolean isIsolated = ReflectUtils.invokeMethod(service, "isIsolateLand2"); + Assert.assertTrue(isIsolated); + + ReflectUtils.invokeMethod(service, "disconnectIsolated2"); + int activeNodeSize = (int) PeerManager.getPeers().stream() + .filter(p -> p.getChannel().isActive()) + .count(); + int passiveSize = (int) PeerManager.getPeers().stream() + .filter(p -> !p.getChannel().isActive()) + .count(); + Assert.assertEquals(2, activeNodeSize); + Assert.assertEquals((int) (maxConnection * ResilienceService.retentionPercent), + activeNodeSize + passiveSize); + Assert.assertEquals((int) (maxConnection * ResilienceService.retentionPercent), + PeerManager.getPeers().size()); + } + + private void clearPeers() { + for (PeerConnection p : PeerManager.getPeers()) { + PeerManager.remove(p.getChannel()); + } + } + + @After + public void destroy() { + Args.clearParam(); + context.destroy(); + } +} \ No newline at end of file diff --git a/framework/src/test/resources/args-test.conf b/framework/src/test/resources/args-test.conf index 91913dfe32e..2d0c54c1d28 100644 --- a/framework/src/test/resources/args-test.conf +++ b/framework/src/test/resources/args-test.conf @@ -92,6 +92,7 @@ node { maxConnections = 30 minConnections = 8 minActiveConnections = 3 + inactiveThreshold = 600 p2p { version = 43 # 43: testnet; 101: debug diff --git a/framework/src/test/resources/config-localtest.conf b/framework/src/test/resources/config-localtest.conf index d7f573fe90e..e56318fea1a 100644 --- a/framework/src/test/resources/config-localtest.conf +++ b/framework/src/test/resources/config-localtest.conf @@ -96,6 +96,7 @@ node { # check the peer data transfer ,disconnect factor isOpenFullTcpDisconnect = true + inactiveThreshold = 600 p2p { version = 333 # 11111: mainnet; 20180622: testnet diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index db24bb2a8a0..19a8be9e25f 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -100,6 +100,7 @@ node { # nodeId = e437a4836b77ad9d9ffe73ee782ef2614e6d8370fcf62191a6e488276e23717147073a7ce0b444d485fff5a0c34c4577251a7a990cf80d8542e21b95aa8c5e6c # } ] + inactiveThreshold = 600 p2p { version = 43 # 43: testnet; 101: debug From 6466458ffe58e2ac985cac4c4da0bacf464a147d Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 18 Jul 2024 16:45:28 +0800 Subject: [PATCH 1037/1197] init commit of set_block_both_have2 --- .../org/tron/core/net/messagehandler/BlockMsgHandler.java | 7 +++++++ .../main/java/org/tron/core/net/peer/PeerConnection.java | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java index 926ed1a01ca..dc886517476 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java @@ -151,6 +151,13 @@ private void processBlock(PeerConnection peer, BlockCapsule block) throws P2pExc try { tronNetDelegate.processBlock(block, false); witnessProductBlockService.validWitnessProductTwoBlock(block); + + Item item = new Item(blockId, InventoryType.BLOCK); + tronNetDelegate.getActivePeer().forEach(p -> { + if (p.getAdvInvReceive().getIfPresent(item) != null) { + p.setBlockBothHave(blockId); + } + }); } catch (Exception e) { logger.warn("Process adv block {} from peer {} failed. reason: {}", blockId, peer.getInetAddress(), e.getMessage()); diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index 4fac50b82c7..30d7d8f5c4f 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -225,7 +225,8 @@ public String log() { channel.getInetSocketAddress(), (now - channel.getStartTime()) / Constant.ONE_THOUSAND, channel.getAvgLatency(), - fastForwardBlock != null ? fastForwardBlock.getNum() : blockBothHave.getNum(), + fastForwardBlock != null ? fastForwardBlock.getNum() : String.format("%d [%ds]", + blockBothHave.getNum(), (System.currentTimeMillis() - blockBothHaveUpdateTime) / 1000), isNeedSyncFromPeer(), isNeedSyncFromUs(), syncBlockToFetch.size(), From 6a08ac635f93a24715bae04107b990e3b2564380 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 1 Jul 2024 12:09:22 +0800 Subject: [PATCH 1038/1197] test(MerkleTree): ignore testConcurrent This is an unstable concurrent unit test. --- .../test/java/org/tron/core/capsule/utils/MerkleTreeTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/framework/src/test/java/org/tron/core/capsule/utils/MerkleTreeTest.java b/framework/src/test/java/org/tron/core/capsule/utils/MerkleTreeTest.java index 3662fb524b8..910b1adba67 100644 --- a/framework/src/test/java/org/tron/core/capsule/utils/MerkleTreeTest.java +++ b/framework/src/test/java/org/tron/core/capsule/utils/MerkleTreeTest.java @@ -8,6 +8,7 @@ import java.util.stream.IntStream; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -185,6 +186,7 @@ public void testAnyHashNum() { } @Test + @Ignore public void testConcurrent() { Sha256Hash root1 = Sha256Hash.wrap( ByteString.fromHex("6cb38b4f493db8bacf26123cd4253bbfc530c708b97b3747e782f64097c3c482")); From f5961f412d1f0d8789e438bd02ada2217cee5d05 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 19 Jul 2024 13:00:55 +0800 Subject: [PATCH 1039/1197] add testcase testProcessBlock for BlockMsgHandler --- .../messagehandler/BlockMsgHandlerTest.java | 51 +++++++++++++++++-- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java index 8154d01aded..56f023417aa 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java @@ -1,26 +1,33 @@ package org.tron.core.net.messagehandler; import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import com.google.common.collect.ImmutableList; import com.google.protobuf.ByteString; - import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.net.InetSocketAddress; +import java.util.ArrayList; import java.util.List; import javax.annotation.Resource; - import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.Mockito; 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.BlockCapsule.BlockId; import org.tron.core.config.Parameter; import org.tron.core.config.args.Args; import org.tron.core.exception.P2pException; +import org.tron.core.net.TronNetDelegate; import org.tron.core.net.message.adv.BlockMessage; import org.tron.core.net.peer.Item; import org.tron.core.net.peer.PeerConnection; @@ -41,9 +48,8 @@ public class BlockMsgHandlerTest extends BaseTest { */ @BeforeClass public static void init() { - Args.setParam(new String[]{"--output-directory", dbPath(), "--debug"}, + Args.setParam(new String[] {"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); - } @Before @@ -123,4 +129,41 @@ public void testProcessMessage() { logger.error("error", e); } } + + @Test + public void testProcessBlock() { + TronNetDelegate tronNetDelegate = Mockito.mock(TronNetDelegate.class); + + try { + Field field = handler.getClass().getDeclaredField("tronNetDelegate"); + field.setAccessible(true); + field.set(handler, tronNetDelegate); + + BlockCapsule blockCapsule0 = new BlockCapsule(1, + Sha256Hash.wrap(ByteString + .copyFrom(ByteArray + .fromHexString( + "9938a342238077182498b464ac0292229938a342238077182498b464ac029222"))), + 1234, + ByteString.copyFrom("1234567".getBytes())); + + peer.getAdvInvReceive() + .put(new Item(blockCapsule0.getBlockId(), InventoryType.BLOCK), System.currentTimeMillis()); + + Mockito.doReturn(true).when(tronNetDelegate).validBlock(any(BlockCapsule.class)); + Mockito.doReturn(true).when(tronNetDelegate).containBlock(any(BlockId.class)); + Mockito.doReturn(blockCapsule0.getBlockId()).when(tronNetDelegate).getHeadBlockId(); + Mockito.doNothing().when(tronNetDelegate).processBlock(any(BlockCapsule.class), anyBoolean()); + List peers = new ArrayList<>(); + peers.add(peer); + Mockito.doReturn(peers).when(tronNetDelegate).getActivePeer(); + + Method method = handler.getClass() + .getDeclaredMethod("processBlock", PeerConnection.class, BlockCapsule.class); + method.setAccessible(true); + method.invoke(handler, peer, blockCapsule0); + } catch (Exception e) { + Assert.fail(); + } + } } From 6706d83196547d828e08b80962dfb687ca52958a Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 19 Jul 2024 13:04:21 +0800 Subject: [PATCH 1040/1197] add testcase testProcessBlock for BlockMsgHandler --- .../org/tron/core/net/messagehandler/BlockMsgHandlerTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java index 56f023417aa..48e7d730520 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java @@ -148,7 +148,8 @@ public void testProcessBlock() { ByteString.copyFrom("1234567".getBytes())); peer.getAdvInvReceive() - .put(new Item(blockCapsule0.getBlockId(), InventoryType.BLOCK), System.currentTimeMillis()); + .put(new Item(blockCapsule0.getBlockId(), InventoryType.BLOCK), + System.currentTimeMillis()); Mockito.doReturn(true).when(tronNetDelegate).validBlock(any(BlockCapsule.class)); Mockito.doReturn(true).when(tronNetDelegate).containBlock(any(BlockId.class)); From 90a6e8f3adf5d1c60e860c202c9086243a00911e Mon Sep 17 00:00:00 2001 From: tomatoishealthy Date: Tue, 14 May 2024 14:26:45 +0800 Subject: [PATCH 1041/1197] fix(http/metric): change endpoint variable from member to local --- .../java/org/tron/core/services/filter/HttpInterceptor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java index 2cce8272dd5..8b43cfef642 100644 --- a/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java +++ b/framework/src/main/java/org/tron/core/services/filter/HttpInterceptor.java @@ -18,7 +18,6 @@ @Slf4j(topic = "httpInterceptor") public class HttpInterceptor implements Filter { - private String endpoint; private final int HTTP_SUCCESS = 200; private final int HTTP_BAD_REQUEST = 400; private final int HTTP_NOT_ACCEPTABLE = 406; @@ -29,6 +28,7 @@ public void init(FilterConfig filterConfig) { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { + String endpoint = MetricLabels.UNDEFINED; try { if (!(request instanceof HttpServletRequest)) { chain.doFilter(request, response); From e6703860a69bcef69ab36ba41b1361c253a46c22 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 22 Jul 2024 15:39:26 +0800 Subject: [PATCH 1042/1197] set lastactivetime in P2pEventHandlerImpl --- .../java/org/tron/core/net/P2pEventHandlerImpl.java | 5 +++++ .../tron/core/net/messagehandler/BlockMsgHandler.java | 1 - .../net/messagehandler/ChainInventoryMsgHandler.java | 1 - .../net/messagehandler/SyncBlockChainMsgHandler.java | 1 - .../java/org/tron/core/net/peer/PeerConnection.java | 2 +- .../core/net/service/effective/ResilienceService.java | 10 ++++------ framework/src/main/resources/config-localtest.conf | 2 +- framework/src/main/resources/config.conf | 2 +- framework/src/test/resources/args-test.conf | 2 +- framework/src/test/resources/config-localtest.conf | 2 +- framework/src/test/resources/config-test.conf | 2 +- 11 files changed, 15 insertions(+), 15 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java index 7518b1347a7..c38ddc8c439 100644 --- a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java +++ b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java @@ -19,6 +19,7 @@ import org.tron.core.net.message.PbftMessageFactory; import org.tron.core.net.message.TronMessage; import org.tron.core.net.message.TronMessageFactory; +import org.tron.core.net.message.adv.FetchInvDataMessage; import org.tron.core.net.message.adv.InventoryMessage; import org.tron.core.net.message.base.DisconnectMessage; import org.tron.core.net.message.handshake.HelloMessage; @@ -38,6 +39,7 @@ import org.tron.p2p.P2pEventHandler; import org.tron.p2p.connection.Channel; import org.tron.protos.Protocol; +import org.tron.protos.Protocol.Inventory.InventoryType; import org.tron.protos.Protocol.ReasonCode; @Slf4j(topic = "net") @@ -183,9 +185,11 @@ private void processMessage(PeerConnection peer, byte[] data) { break; case SYNC_BLOCK_CHAIN: syncBlockChainMsgHandler.processMessage(peer, msg); + peer.setLastActiveTime(System.currentTimeMillis()); break; case BLOCK_CHAIN_INVENTORY: chainInventoryMsgHandler.processMessage(peer, msg); + peer.setLastActiveTime(System.currentTimeMillis()); break; case INVENTORY: inventoryMsgHandler.processMessage(peer, msg); @@ -195,6 +199,7 @@ private void processMessage(PeerConnection peer, byte[] data) { break; case BLOCK: blockMsgHandler.processMessage(peer, msg); + peer.setLastActiveTime(System.currentTimeMillis()); break; case TRXS: transactionsMsgHandler.processMessage(peer, msg); diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java index 547f96036cb..926ed1a01ca 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java @@ -76,7 +76,6 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep if (!fastForward && !peer.isRelayPeer()) { check(peer, blockMessage); } - peer.setLastActiveTime(System.currentTimeMillis()); if (peer.getSyncBlockRequested().containsKey(blockId)) { peer.getSyncBlockRequested().remove(blockId); diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java index 4f99deb146b..bd2e428418c 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java @@ -142,7 +142,6 @@ private void check(PeerConnection peer, ChainInventoryMessage msg) throws P2pExc + msg.getRemainNum() + " > futureMaxNum: " + maxFutureNum); } } - peer.setLastActiveTime(System.currentTimeMillis()); } } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java index e03e039ac4d..f575253c50c 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java @@ -33,7 +33,6 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep peer.disconnect(Protocol.ReasonCode.BAD_PROTOCOL); return; } - peer.setLastActiveTime(System.currentTimeMillis()); long remainNum = 0; List summaryChainIds = syncBlockChainMessage.getBlockIds(); diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index 66903e7c64e..5981f46ae41 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -81,7 +81,7 @@ public class PeerConnection { @Getter @Setter - private long lastActiveTime; + private volatile long lastActiveTime; @Getter @Setter diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index bdf5892f260..166b0eb9cf6 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -22,14 +22,16 @@ @Component public class ResilienceService { - private final long inactiveThreshold = + private static final long inactiveThreshold = CommonParameter.getInstance().getInactiveThreshold() * 1000L; public static final long blockNotChangeThreshold = 90 * 1000L; //when node is isolated, retention percent peers will not be disconnected public static final double retentionPercent = 0.8; private static final int initialDelay = 300; - private final String esName = "resilience-service"; + private static final String esName = "resilience-service"; + private final ScheduledExecutorService executor = ExecutorServiceManager + .newSingleThreadScheduledExecutor(esName); @Autowired private TronNetDelegate tronNetDelegate; @@ -37,11 +39,7 @@ public class ResilienceService { @Autowired private ChainBaseManager chainBaseManager; - private ScheduledExecutorService executor; - public void init() { - executor = ExecutorServiceManager.newSingleThreadScheduledExecutor(esName); - if (Args.getInstance().isOpenFullTcpDisconnect) { executor.scheduleWithFixedDelay(() -> { try { diff --git a/framework/src/main/resources/config-localtest.conf b/framework/src/main/resources/config-localtest.conf index e1c0d55b002..50e7539c1d0 100644 --- a/framework/src/main/resources/config-localtest.conf +++ b/framework/src/main/resources/config-localtest.conf @@ -99,7 +99,7 @@ node { # check the peer data transfer ,disconnect factor isOpenFullTcpDisconnect = true - inactiveThreshold = 600 + inactiveThreshold = 600 //seconds p2p { version = 333 # 11111: mainnet; 20180622: testnet diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 3b4a2b64968..f9fc2dd673d 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -180,7 +180,7 @@ node { minParticipationRate = 15 isOpenFullTcpDisconnect = false - inactiveThreshold = 600 + inactiveThreshold = 600 //seconds p2p { version = 11111 # 11111: mainnet; 20180622: testnet diff --git a/framework/src/test/resources/args-test.conf b/framework/src/test/resources/args-test.conf index 2d0c54c1d28..cf5d0b8d718 100644 --- a/framework/src/test/resources/args-test.conf +++ b/framework/src/test/resources/args-test.conf @@ -92,7 +92,7 @@ node { maxConnections = 30 minConnections = 8 minActiveConnections = 3 - inactiveThreshold = 600 + inactiveThreshold = 600 //seconds p2p { version = 43 # 43: testnet; 101: debug diff --git a/framework/src/test/resources/config-localtest.conf b/framework/src/test/resources/config-localtest.conf index e56318fea1a..1d7ae09af7c 100644 --- a/framework/src/test/resources/config-localtest.conf +++ b/framework/src/test/resources/config-localtest.conf @@ -96,7 +96,7 @@ node { # check the peer data transfer ,disconnect factor isOpenFullTcpDisconnect = true - inactiveThreshold = 600 + inactiveThreshold = 600 //seconds p2p { version = 333 # 11111: mainnet; 20180622: testnet diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index 19a8be9e25f..62337f02fc5 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -100,7 +100,7 @@ node { # nodeId = e437a4836b77ad9d9ffe73ee782ef2614e6d8370fcf62191a6e488276e23717147073a7ce0b444d485fff5a0c34c4577251a7a990cf80d8542e21b95aa8c5e6c # } ] - inactiveThreshold = 600 + inactiveThreshold = 600 //seconds p2p { version = 43 # 43: testnet; 101: debug From 735bccb64a2fc41fe64b15b1e5f502b10fe68bd0 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 23 Jul 2024 12:36:50 +0800 Subject: [PATCH 1043/1197] add updateLastActiveTime --- .../tron/core/net/P2pEventHandlerImpl.java | 25 ++++++++++++++++--- .../FetchInvDataMsgHandler.java | 1 - .../core/net/P2pEventHandlerImplTest.java | 21 ++++++++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java index c38ddc8c439..0100dc443d9 100644 --- a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java +++ b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java @@ -185,11 +185,9 @@ private void processMessage(PeerConnection peer, byte[] data) { break; case SYNC_BLOCK_CHAIN: syncBlockChainMsgHandler.processMessage(peer, msg); - peer.setLastActiveTime(System.currentTimeMillis()); break; case BLOCK_CHAIN_INVENTORY: chainInventoryMsgHandler.processMessage(peer, msg); - peer.setLastActiveTime(System.currentTimeMillis()); break; case INVENTORY: inventoryMsgHandler.processMessage(peer, msg); @@ -199,7 +197,6 @@ private void processMessage(PeerConnection peer, byte[] data) { break; case BLOCK: blockMsgHandler.processMessage(peer, msg); - peer.setLastActiveTime(System.currentTimeMillis()); break; case TRXS: transactionsMsgHandler.processMessage(peer, msg); @@ -210,6 +207,7 @@ private void processMessage(PeerConnection peer, byte[] data) { default: throw new P2pException(P2pException.TypeEnum.NO_SUCH_MESSAGE, msg.getType().toString()); } + updateLastActiveTime(peer, msg); } catch (Exception e) { processException(peer, msg, e); } finally { @@ -225,6 +223,27 @@ private void processMessage(PeerConnection peer, byte[] data) { } } + private void updateLastActiveTime(PeerConnection peer, TronMessage msg) { + MessageTypes type = msg.getType(); + + boolean flag = false; + switch (type) { + case SYNC_BLOCK_CHAIN: + case BLOCK_CHAIN_INVENTORY: + case BLOCK: + flag = true; + break; + case FETCH_INV_DATA: + flag = ((FetchInvDataMessage) msg).getInventoryType().equals(InventoryType.BLOCK); + break; + default: + break; + } + if (flag) { + peer.setLastActiveTime(System.currentTimeMillis()); + } + } + private void processException(PeerConnection peer, TronMessage msg, Exception ex) { Protocol.ReasonCode code; diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java index 2c4e94a66fa..5e797c084b3 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java @@ -171,7 +171,6 @@ private void check(PeerConnection peer, FetchInvDataMessage fetchInvDataMsg) thr peer.getSyncBlockIdCache().put(hash, System.currentTimeMillis()); } } - peer.setLastActiveTime(System.currentTimeMillis()); } } diff --git a/framework/src/test/java/org/tron/core/net/P2pEventHandlerImplTest.java b/framework/src/test/java/org/tron/core/net/P2pEventHandlerImplTest.java index 0008ec315d5..7a3dc30cb86 100644 --- a/framework/src/test/java/org/tron/core/net/P2pEventHandlerImplTest.java +++ b/framework/src/test/java/org/tron/core/net/P2pEventHandlerImplTest.java @@ -12,10 +12,13 @@ import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; import org.tron.core.config.args.Args; +import org.tron.core.net.message.TronMessage; +import org.tron.core.net.message.adv.FetchInvDataMessage; import org.tron.core.net.message.adv.InventoryMessage; import org.tron.core.net.peer.PeerConnection; import org.tron.core.net.service.statistics.PeerStatistics; import org.tron.protos.Protocol; +import org.tron.protos.Protocol.Inventory.InventoryType; public class P2pEventHandlerImplTest { @@ -108,4 +111,22 @@ public void testProcessInventoryMessage() throws Exception { Assert.assertEquals(300, count); } + + @Test + public void testUpdateLastActiveTime() throws Exception { + String[] a = new String[0]; + Args.setParam(a, Constant.TESTNET_CONF); + + PeerConnection peer = new PeerConnection(); + P2pEventHandlerImpl p2pEventHandler = new P2pEventHandlerImpl(); + + Method method = p2pEventHandler.getClass() + .getDeclaredMethod("updateLastActiveTime", PeerConnection.class, TronMessage.class); + method.setAccessible(true); + + long t1 = System.currentTimeMillis(); + FetchInvDataMessage message = new FetchInvDataMessage(new ArrayList<>(), InventoryType.BLOCK); + method.invoke(p2pEventHandler, peer, message); + Assert.assertTrue(peer.getLastActiveTime() >= t1); + } } From 343c5f6a041646296cc363274c25e90b89d929cb Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 23 Jul 2024 14:41:55 +0800 Subject: [PATCH 1044/1197] optimize log method of PeerConnection --- .../src/main/java/org/tron/core/net/peer/PeerConnection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index 30d7d8f5c4f..d30ed92d830 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -226,7 +226,7 @@ public String log() { (now - channel.getStartTime()) / Constant.ONE_THOUSAND, channel.getAvgLatency(), fastForwardBlock != null ? fastForwardBlock.getNum() : String.format("%d [%ds]", - blockBothHave.getNum(), (System.currentTimeMillis() - blockBothHaveUpdateTime) / 1000), + blockBothHave.getNum(), (now - blockBothHaveUpdateTime) / Constant.ONE_THOUSAND), isNeedSyncFromPeer(), isNeedSyncFromUs(), syncBlockToFetch.size(), From a718006c257e2879d5d007e42a80d038947bc57e Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 25 Jul 2024 16:07:42 +0800 Subject: [PATCH 1045/1197] catch exception of sort peers --- .../core/net/service/effective/ResilienceService.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index 166b0eb9cf6..ffac784fd55 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -119,7 +119,8 @@ private void disconnectIsolated2() { one.ifPresent(peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL)); } - //disconnect from some passive nodes, make sure retention nodes' num <= 0.8 * maxConnection + //disconnect from some passive nodes, make sure retention nodes' num <= 0.8 * maxConnection, + //so new peers can come in peerSize = tronNetDelegate.getActivePeer().size(); int threshold = (int) (CommonParameter.getInstance().getMaxConnections() * retentionPercent); if (peerSize > threshold) { @@ -128,8 +129,13 @@ private void disconnectIsolated2() { .filter(peer -> !peer.isDisconnect()) .filter(peer -> !peer.getChannel().isTrustPeer()) .filter(peer -> !peer.getChannel().isActive()) - .sorted(Comparator.comparing(PeerConnection::getLastActiveTime, Long::compareTo)) .collect(Collectors.toList()); + try { + peers.sort(Comparator.comparing(PeerConnection::getLastActiveTime, Long::compareTo)); + } catch (Exception e) { + logger.warn("Sort peers failed: {}", e.getMessage()); + return; + } if (peers.size() > disconnectSize) { peers = peers.subList(0, disconnectSize); From 14fda8faecad2a1021a59e4999e1563a8f238c59 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 25 Jul 2024 16:47:15 +0800 Subject: [PATCH 1046/1197] catch exception min of peers --- .../service/effective/ResilienceService.java | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index ffac784fd55..fbbb2855934 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -92,12 +92,12 @@ private void disconnectLan() { int peerSize = tronNetDelegate.getActivePeer().size(); if (peerSize >= CommonParameter.getInstance().getMinConnections()) { long now = System.currentTimeMillis(); - Optional one = tronNetDelegate.getActivePeer().stream() + List peers = tronNetDelegate.getActivePeer().stream() .filter(peer -> !peer.isDisconnect()) .filter(peer -> now - peer.getLastActiveTime() >= inactiveThreshold) .filter(peer -> !peer.getChannel().isTrustPeer()) - .min(Comparator.comparing(PeerConnection::getLastActiveTime, Long::compareTo)); - + .collect(Collectors.toList()); + Optional one = getEarliestPeer(peers); one.ifPresent(peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL)); } } @@ -110,12 +110,13 @@ private void disconnectIsolated2() { //disconnect from the node whose lastActiveTime is smallest if (peerSize >= CommonParameter.getInstance().getMinActiveConnections()) { - Optional one = tronNetDelegate.getActivePeer().stream() + List peers = tronNetDelegate.getActivePeer().stream() .filter(peer -> !peer.isDisconnect()) .filter(peer -> !peer.getChannel().isTrustPeer()) .filter(peer -> peer.getChannel().isActive()) - .min(Comparator.comparing(PeerConnection::getLastActiveTime, Long::compareTo)); + .collect(Collectors.toList()); + Optional one = getEarliestPeer(peers); one.ifPresent(peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL)); } @@ -133,7 +134,7 @@ private void disconnectIsolated2() { try { peers.sort(Comparator.comparing(PeerConnection::getLastActiveTime, Long::compareTo)); } catch (Exception e) { - logger.warn("Sort peers failed: {}", e.getMessage()); + logger.warn("Sort disconnectIsolated2 peers failed: {}", e.getMessage()); return; } @@ -145,6 +146,17 @@ private void disconnectIsolated2() { } } + private Optional getEarliestPeer(List pees) { + Optional one = Optional.empty(); + try { + one = pees.stream() + .min(Comparator.comparing(PeerConnection::getLastActiveTime, Long::compareTo)); + } catch (Exception e) { + logger.warn("Get earliest peer failed: {}", e.getMessage()); + } + return one; + } + private boolean isLanNode() { int peerSize = tronNetDelegate.getActivePeer().size(); int activePeerSize = (int) tronNetDelegate.getActivePeer().stream() From d6faee8bdfc69588f4b20bd90d2e73e8c1c083fe Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Wed, 31 Jul 2024 12:10:08 +0800 Subject: [PATCH 1047/1197] feat(monitor): add tcp out traffic and udp in traffic statistics --- .../service/statistics/TronStatsManager.java | 8 +++++ .../net/services/TronStatsManagerTest.java | 36 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/framework/src/main/java/org/tron/core/net/service/statistics/TronStatsManager.java b/framework/src/main/java/org/tron/core/net/service/statistics/TronStatsManager.java index caac3f7f325..99e12834ced 100644 --- a/framework/src/main/java/org/tron/core/net/service/statistics/TronStatsManager.java +++ b/framework/src/main/java/org/tron/core/net/service/statistics/TronStatsManager.java @@ -63,11 +63,19 @@ private void work() { Metrics.histogramObserve(MetricKeys.Histogram.TCP_BYTES, stats.getTcpInSize() - TCP_TRAFFIC_IN, MetricLabels.Histogram.TRAFFIC_IN); + MetricsUtil.meterMark(MetricsKey.NET_TCP_OUT_TRAFFIC, stats.getTcpOutSize() - TCP_TRAFFIC_OUT); + Metrics.histogramObserve(MetricKeys.Histogram.TCP_BYTES, + stats.getTcpOutSize() - TCP_TRAFFIC_OUT, + MetricLabels.Histogram.TRAFFIC_OUT); + + MetricsUtil.meterMark(MetricsKey.NET_UDP_IN_TRAFFIC, + stats.getUdpInSize() - UDP_TRAFFIC_IN); Metrics.histogramObserve(MetricKeys.Histogram.UDP_BYTES, stats.getUdpInSize() - UDP_TRAFFIC_IN, MetricLabels.Histogram.TRAFFIC_IN); + MetricsUtil.meterMark(MetricsKey.NET_UDP_OUT_TRAFFIC, stats.getUdpOutSize() - UDP_TRAFFIC_OUT); Metrics.histogramObserve(MetricKeys.Histogram.UDP_BYTES, diff --git a/framework/src/test/java/org/tron/core/net/services/TronStatsManagerTest.java b/framework/src/test/java/org/tron/core/net/services/TronStatsManagerTest.java index 369955f4e7f..a940a14d392 100644 --- a/framework/src/test/java/org/tron/core/net/services/TronStatsManagerTest.java +++ b/framework/src/test/java/org/tron/core/net/services/TronStatsManagerTest.java @@ -1,5 +1,7 @@ package org.tron.core.net.services; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -24,4 +26,38 @@ public void testOnDisconnect() { Assert.assertEquals(Protocol.ReasonCode.UNKNOWN, statistics.getDisconnectReason()); } + @Test + public void testWork() throws Exception { + TronStatsManager manager = new TronStatsManager(); + Field field1 = manager.getClass().getDeclaredField("TCP_TRAFFIC_IN"); + field1.setAccessible(true); + field1.set(manager, 1L); + + Field field2 = manager.getClass().getDeclaredField("TCP_TRAFFIC_OUT"); + field2.setAccessible(true); + field2.set(manager, 1L); + + Field field3 = manager.getClass().getDeclaredField("UDP_TRAFFIC_IN"); + field3.setAccessible(true); + field3.set(manager, 1L); + + Field field4 = manager.getClass().getDeclaredField("UDP_TRAFFIC_OUT"); + field4.setAccessible(true); + field4.set(manager, 1L); + + Assert.assertEquals(field1.get(manager), 1L); + Assert.assertEquals(field2.get(manager), 1L); + Assert.assertEquals(field3.get(manager), 1L); + Assert.assertEquals(field4.get(manager), 1L); + + Method method = manager.getClass().getDeclaredMethod("work"); + method.setAccessible(true); + method.invoke(manager); + + Assert.assertEquals(field1.get(manager), 0L); + Assert.assertEquals(field2.get(manager), 0L); + Assert.assertEquals(field3.get(manager), 0L); + Assert.assertEquals(field4.get(manager), 0L); + } + } From 81bb50bd0190e2289d2d17d5ac12acf6a65e5f0e Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 7 Aug 2024 16:50:40 +0800 Subject: [PATCH 1048/1197] add some log for isolated2 disconnection --- .../tron/core/net/peer/PeerConnection.java | 2 ++ .../service/effective/ResilienceService.java | 20 +++++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index da97f74c241..24f43e1f3fa 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -230,6 +230,7 @@ public String log() { + "syncBlockRequestedSize:%d\n" + "remainNum:%d\n" + "syncChainRequested:%d\n" + + "inactiveSeconds:%d\n" + "blockInProcess:%d\n", channel.getInetSocketAddress(), (now - channel.getStartTime()) / Constant.ONE_THOUSAND, @@ -244,6 +245,7 @@ public String log() { remainNum, requested == null ? 0 : (now - requested.getValue()) / Constant.ONE_THOUSAND, + (now - lastActiveTime) / Constant.ONE_THOUSAND, syncBlockInProcess.size()); } diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index fbbb2855934..83ddc56655f 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -80,7 +80,7 @@ private void disconnectRandom() { .collect(Collectors.toList()); if (!peers.isEmpty()) { int index = new Random().nextInt(peers.size()); - disconnectFromPeer(peers.get(index), ReasonCode.RANDOM_ELIMINATION); + disconnectFromPeer(peers.get(index), ReasonCode.RANDOM_ELIMINATION, "random"); } } } @@ -98,14 +98,14 @@ private void disconnectLan() { .filter(peer -> !peer.getChannel().isTrustPeer()) .collect(Collectors.toList()); Optional one = getEarliestPeer(peers); - one.ifPresent(peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL)); + one.ifPresent(peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, "lan node")); } } } private void disconnectIsolated2() { if (isIsolateLand2()) { - logger.info("Node is isolated, try to disconnect from peers"); + logger.warn("Node is isolated, try to disconnect from peers"); int peerSize = tronNetDelegate.getActivePeer().size(); //disconnect from the node whose lastActiveTime is smallest @@ -117,7 +117,8 @@ private void disconnectIsolated2() { .collect(Collectors.toList()); Optional one = getEarliestPeer(peers); - one.ifPresent(peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL)); + one.ifPresent( + peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, "isolate2 and active")); } //disconnect from some passive nodes, make sure retention nodes' num <= 0.8 * maxConnection, @@ -141,7 +142,10 @@ private void disconnectIsolated2() { if (peers.size() > disconnectSize) { peers = peers.subList(0, disconnectSize); } - peers.forEach(peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL)); + logger.info("All peer Size:{}, avail:{}, disconnectSize:{}, ", peerSize, peers.size(), + disconnectSize); + peers.forEach( + peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, "isolate2 and passive")); } } } @@ -173,10 +177,10 @@ private boolean isIsolateLand2() { return advPeerCount >= 1 && diff >= blockNotChangeThreshold; } - private void disconnectFromPeer(PeerConnection peer, ReasonCode reasonCode) { + private void disconnectFromPeer(PeerConnection peer, ReasonCode reasonCode, String cause) { int inactiveSeconds = (int) ((System.currentTimeMillis() - peer.getLastActiveTime()) / 1000); - logger.info("Disconnect from peer {}, inactive seconds {}", peer.getInetSocketAddress(), - inactiveSeconds); + logger.info("Disconnect from peer {}, inactive seconds {}, cause: {}", + peer.getInetSocketAddress(), inactiveSeconds, cause); peer.disconnect(reasonCode); } From 0d21388fc0cdb91e2613bddd24a5d5cf72118f7e Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 7 Aug 2024 17:11:29 +0800 Subject: [PATCH 1049/1197] add log of candidate disconnect size when node is isolated --- .../tron/core/net/service/effective/ResilienceService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index 83ddc56655f..5544f6ede03 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -138,12 +138,12 @@ private void disconnectIsolated2() { logger.warn("Sort disconnectIsolated2 peers failed: {}", e.getMessage()); return; } - + int candidateSize = peers.size(); if (peers.size() > disconnectSize) { peers = peers.subList(0, disconnectSize); } - logger.info("All peer Size:{}, avail:{}, disconnectSize:{}, ", peerSize, peers.size(), - disconnectSize); + logger.info("All peer Size:{}, plan size:{}, candidate size:{}, real size:{}", peerSize, + disconnectSize, candidateSize, peers.size()); peers.forEach( peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, "isolate2 and passive")); } From 0acc84b252d9c1fbbc24c563997682c23922268b Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 9 Aug 2024 18:29:35 +0800 Subject: [PATCH 1050/1197] set blockNotChangeThreshold from 90 to 60 seconds --- .../java/org/tron/core/config/args/Args.java | 3 + .../service/effective/ResilienceService.java | 117 +++++++++--------- 2 files changed, 63 insertions(+), 57 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 7b089530a41..00142733f74 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -848,6 +848,9 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.inactiveThreshold = config.hasPath(Constant.NODE_INACTIVE_THRESHOLD) ? config.getInt(Constant.NODE_INACTIVE_THRESHOLD) : 600; + if (PARAMETER.inactiveThreshold < 1) { + PARAMETER.inactiveThreshold = 1; + } PARAMETER.maxTransactionPendingSize = config.hasPath(Constant.NODE_MAX_TRANSACTION_PENDING_SIZE) ? config.getInt(Constant.NODE_MAX_TRANSACTION_PENDING_SIZE) : 2000; diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index 5544f6ede03..73ca16da743 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -24,7 +24,7 @@ public class ResilienceService { private static final long inactiveThreshold = CommonParameter.getInstance().getInactiveThreshold() * 1000L; - public static final long blockNotChangeThreshold = 90 * 1000L; + public static final long blockNotChangeThreshold = 60 * 1000L; //when node is isolated, retention percent peers will not be disconnected public static final double retentionPercent = 0.8; @@ -86,67 +86,69 @@ private void disconnectRandom() { } private void disconnectLan() { - if (isLanNode()) { - // disconnect from the node that has keep inactive for more than inactiveThreshold - // and its lastActiveTime is smallest - int peerSize = tronNetDelegate.getActivePeer().size(); - if (peerSize >= CommonParameter.getInstance().getMinConnections()) { - long now = System.currentTimeMillis(); - List peers = tronNetDelegate.getActivePeer().stream() - .filter(peer -> !peer.isDisconnect()) - .filter(peer -> now - peer.getLastActiveTime() >= inactiveThreshold) - .filter(peer -> !peer.getChannel().isTrustPeer()) - .collect(Collectors.toList()); - Optional one = getEarliestPeer(peers); - one.ifPresent(peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, "lan node")); - } + if (!isLanNode()) { + return; + } + // disconnect from the node that has keep inactive for more than inactiveThreshold + // and its lastActiveTime is smallest + int peerSize = tronNetDelegate.getActivePeer().size(); + if (peerSize >= CommonParameter.getInstance().getMinConnections()) { + long now = System.currentTimeMillis(); + List peers = tronNetDelegate.getActivePeer().stream() + .filter(peer -> !peer.isDisconnect()) + .filter(peer -> now - peer.getLastActiveTime() >= inactiveThreshold) + .filter(peer -> !peer.getChannel().isTrustPeer()) + .collect(Collectors.toList()); + Optional one = getEarliestPeer(peers); + one.ifPresent(peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, "lan node")); } } private void disconnectIsolated2() { - if (isIsolateLand2()) { - logger.warn("Node is isolated, try to disconnect from peers"); - int peerSize = tronNetDelegate.getActivePeer().size(); - - //disconnect from the node whose lastActiveTime is smallest - if (peerSize >= CommonParameter.getInstance().getMinActiveConnections()) { - List peers = tronNetDelegate.getActivePeer().stream() - .filter(peer -> !peer.isDisconnect()) - .filter(peer -> !peer.getChannel().isTrustPeer()) - .filter(peer -> peer.getChannel().isActive()) - .collect(Collectors.toList()); - - Optional one = getEarliestPeer(peers); - one.ifPresent( - peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, "isolate2 and active")); - } + if (!isIsolateLand2()) { + return; + } + logger.warn("Node is isolated, try to disconnect from peers"); + int peerSize = tronNetDelegate.getActivePeer().size(); - //disconnect from some passive nodes, make sure retention nodes' num <= 0.8 * maxConnection, - //so new peers can come in - peerSize = tronNetDelegate.getActivePeer().size(); - int threshold = (int) (CommonParameter.getInstance().getMaxConnections() * retentionPercent); - if (peerSize > threshold) { - int disconnectSize = peerSize - threshold; - List peers = tronNetDelegate.getActivePeer().stream() - .filter(peer -> !peer.isDisconnect()) - .filter(peer -> !peer.getChannel().isTrustPeer()) - .filter(peer -> !peer.getChannel().isActive()) - .collect(Collectors.toList()); - try { - peers.sort(Comparator.comparing(PeerConnection::getLastActiveTime, Long::compareTo)); - } catch (Exception e) { - logger.warn("Sort disconnectIsolated2 peers failed: {}", e.getMessage()); - return; - } - int candidateSize = peers.size(); - if (peers.size() > disconnectSize) { - peers = peers.subList(0, disconnectSize); - } - logger.info("All peer Size:{}, plan size:{}, candidate size:{}, real size:{}", peerSize, - disconnectSize, candidateSize, peers.size()); - peers.forEach( - peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, "isolate2 and passive")); + //disconnect from the node whose lastActiveTime is smallest + if (peerSize >= CommonParameter.getInstance().getMinActiveConnections()) { + List peers = tronNetDelegate.getActivePeer().stream() + .filter(peer -> !peer.isDisconnect()) + .filter(peer -> !peer.getChannel().isTrustPeer()) + .filter(peer -> peer.getChannel().isActive()) + .collect(Collectors.toList()); + + Optional one = getEarliestPeer(peers); + one.ifPresent( + peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, "isolate2 and active")); + } + + //disconnect from some passive nodes, make sure retention nodes' num <= 0.8 * maxConnection, + //so new peers can come in + peerSize = tronNetDelegate.getActivePeer().size(); + int threshold = (int) (CommonParameter.getInstance().getMaxConnections() * retentionPercent); + if (peerSize > threshold) { + int disconnectSize = peerSize - threshold; + List peers = tronNetDelegate.getActivePeer().stream() + .filter(peer -> !peer.isDisconnect()) + .filter(peer -> !peer.getChannel().isTrustPeer()) + .filter(peer -> !peer.getChannel().isActive()) + .collect(Collectors.toList()); + try { + peers.sort(Comparator.comparing(PeerConnection::getLastActiveTime, Long::compareTo)); + } catch (Exception e) { + logger.warn("Sort disconnectIsolated2 peers failed: {}", e.getMessage()); + return; + } + int candidateSize = peers.size(); + if (peers.size() > disconnectSize) { + peers = peers.subList(0, disconnectSize); } + logger.info("All peer Size:{}, plan size:{}, candidate size:{}, real size:{}", peerSize, + disconnectSize, candidateSize, peers.size()); + peers.forEach( + peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, "isolate2 and passive")); } } @@ -166,7 +168,8 @@ private boolean isLanNode() { int activePeerSize = (int) tronNetDelegate.getActivePeer().stream() .filter(peer -> peer.getChannel().isActive()) .count(); - return peerSize > 0 && peerSize == activePeerSize; + return peerSize > CommonParameter.getInstance().getMinActiveConnections() + && peerSize == activePeerSize; } private boolean isIsolateLand2() { From 0fc9acb83fc1eb044b2592aa71a19cca12f24908 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 9 Aug 2024 20:15:57 +0800 Subject: [PATCH 1051/1197] remove the condition of peer.isDisconnect --- .../tron/core/net/service/effective/ResilienceService.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index 73ca16da743..d48c84a4562 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -74,7 +74,6 @@ private void disconnectRandom() { if (peerSize >= CommonParameter.getInstance().getMaxConnections()) { long now = System.currentTimeMillis(); List peers = tronNetDelegate.getActivePeer().stream() - .filter(peer -> !peer.isDisconnect()) .filter(peer -> now - peer.getLastActiveTime() >= inactiveThreshold) .filter(peer -> !peer.getChannel().isTrustPeer()) .collect(Collectors.toList()); @@ -95,7 +94,6 @@ private void disconnectLan() { if (peerSize >= CommonParameter.getInstance().getMinConnections()) { long now = System.currentTimeMillis(); List peers = tronNetDelegate.getActivePeer().stream() - .filter(peer -> !peer.isDisconnect()) .filter(peer -> now - peer.getLastActiveTime() >= inactiveThreshold) .filter(peer -> !peer.getChannel().isTrustPeer()) .collect(Collectors.toList()); @@ -114,7 +112,6 @@ private void disconnectIsolated2() { //disconnect from the node whose lastActiveTime is smallest if (peerSize >= CommonParameter.getInstance().getMinActiveConnections()) { List peers = tronNetDelegate.getActivePeer().stream() - .filter(peer -> !peer.isDisconnect()) .filter(peer -> !peer.getChannel().isTrustPeer()) .filter(peer -> peer.getChannel().isActive()) .collect(Collectors.toList()); @@ -131,7 +128,6 @@ private void disconnectIsolated2() { if (peerSize > threshold) { int disconnectSize = peerSize - threshold; List peers = tronNetDelegate.getActivePeer().stream() - .filter(peer -> !peer.isDisconnect()) .filter(peer -> !peer.getChannel().isTrustPeer()) .filter(peer -> !peer.getChannel().isActive()) .collect(Collectors.toList()); From 0f7c7f4695fbdd74d4f34576625dfd53eb42d6ca Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 13 Aug 2024 15:18:22 +0800 Subject: [PATCH 1052/1197] don't disconnect with syncing node when random disconnect --- .../org/tron/core/net/service/effective/ResilienceService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index d48c84a4562..c44f39b4dbd 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -76,6 +76,7 @@ private void disconnectRandom() { List peers = tronNetDelegate.getActivePeer().stream() .filter(peer -> now - peer.getLastActiveTime() >= inactiveThreshold) .filter(peer -> !peer.getChannel().isTrustPeer()) + .filter(peer -> !peer.isNeedSyncFromUs() && !peer.isNeedSyncFromPeer()) .collect(Collectors.toList()); if (!peers.isEmpty()) { int index = new Random().nextInt(peers.size()); From 7bdae3265360c0b22082c00ed43b37b7950fe3d5 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 13 Aug 2024 16:34:23 +0800 Subject: [PATCH 1053/1197] add DisConnectCause --- .../service/effective/ResilienceService.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index c44f39b4dbd..8d39372d003 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -80,7 +80,8 @@ private void disconnectRandom() { .collect(Collectors.toList()); if (!peers.isEmpty()) { int index = new Random().nextInt(peers.size()); - disconnectFromPeer(peers.get(index), ReasonCode.RANDOM_ELIMINATION, "random"); + disconnectFromPeer(peers.get(index), ReasonCode.RANDOM_ELIMINATION, + DisConnectCause.RANDOM_ELIMINATION); } } } @@ -99,7 +100,8 @@ private void disconnectLan() { .filter(peer -> !peer.getChannel().isTrustPeer()) .collect(Collectors.toList()); Optional one = getEarliestPeer(peers); - one.ifPresent(peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, "lan node")); + one.ifPresent( + peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, DisConnectCause.LAN_NODE)); } } @@ -118,8 +120,8 @@ private void disconnectIsolated2() { .collect(Collectors.toList()); Optional one = getEarliestPeer(peers); - one.ifPresent( - peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, "isolate2 and active")); + one.ifPresent(peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, + DisConnectCause.ISOLATE2_ACTIVE)); } //disconnect from some passive nodes, make sure retention nodes' num <= 0.8 * maxConnection, @@ -144,8 +146,8 @@ private void disconnectIsolated2() { } logger.info("All peer Size:{}, plan size:{}, candidate size:{}, real size:{}", peerSize, disconnectSize, candidateSize, peers.size()); - peers.forEach( - peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, "isolate2 and passive")); + peers.forEach(peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, + DisConnectCause.ISOLATE2_PASSIVE)); } } @@ -177,13 +179,21 @@ private boolean isIsolateLand2() { return advPeerCount >= 1 && diff >= blockNotChangeThreshold; } - private void disconnectFromPeer(PeerConnection peer, ReasonCode reasonCode, String cause) { + private void disconnectFromPeer(PeerConnection peer, ReasonCode reasonCode, + DisConnectCause cause) { int inactiveSeconds = (int) ((System.currentTimeMillis() - peer.getLastActiveTime()) / 1000); logger.info("Disconnect from peer {}, inactive seconds {}, cause: {}", peer.getInetSocketAddress(), inactiveSeconds, cause); peer.disconnect(reasonCode); } + private enum DisConnectCause { + RANDOM_ELIMINATION, + LAN_NODE, + ISOLATE2_ACTIVE, + ISOLATE2_PASSIVE, + } + public void close() { ExecutorServiceManager.shutdownAndAwaitTermination(executor, esName); } From ffbb69e0c8880a772935be8101dfd78190a49cec Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 13 Aug 2024 16:35:12 +0800 Subject: [PATCH 1054/1197] add DisConnectCause --- .../net/service/effective/ResilienceService.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index 8d39372d003..ac54c5b8b4e 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -81,7 +81,7 @@ private void disconnectRandom() { if (!peers.isEmpty()) { int index = new Random().nextInt(peers.size()); disconnectFromPeer(peers.get(index), ReasonCode.RANDOM_ELIMINATION, - DisConnectCause.RANDOM_ELIMINATION); + DisconnectCause.RANDOM_ELIMINATION); } } } @@ -101,7 +101,7 @@ private void disconnectLan() { .collect(Collectors.toList()); Optional one = getEarliestPeer(peers); one.ifPresent( - peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, DisConnectCause.LAN_NODE)); + peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, DisconnectCause.LAN_NODE)); } } @@ -121,7 +121,7 @@ private void disconnectIsolated2() { Optional one = getEarliestPeer(peers); one.ifPresent(peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, - DisConnectCause.ISOLATE2_ACTIVE)); + DisconnectCause.ISOLATE2_ACTIVE)); } //disconnect from some passive nodes, make sure retention nodes' num <= 0.8 * maxConnection, @@ -147,7 +147,7 @@ private void disconnectIsolated2() { logger.info("All peer Size:{}, plan size:{}, candidate size:{}, real size:{}", peerSize, disconnectSize, candidateSize, peers.size()); peers.forEach(peer -> disconnectFromPeer(peer, ReasonCode.BAD_PROTOCOL, - DisConnectCause.ISOLATE2_PASSIVE)); + DisconnectCause.ISOLATE2_PASSIVE)); } } @@ -180,14 +180,14 @@ private boolean isIsolateLand2() { } private void disconnectFromPeer(PeerConnection peer, ReasonCode reasonCode, - DisConnectCause cause) { + DisconnectCause cause) { int inactiveSeconds = (int) ((System.currentTimeMillis() - peer.getLastActiveTime()) / 1000); logger.info("Disconnect from peer {}, inactive seconds {}, cause: {}", peer.getInetSocketAddress(), inactiveSeconds, cause); peer.disconnect(reasonCode); } - private enum DisConnectCause { + private enum DisconnectCause { RANDOM_ELIMINATION, LAN_NODE, ISOLATE2_ACTIVE, From abf8c42d9f27b8ee67ef4fb3a210d45300d89768 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 13 Aug 2024 17:46:30 +0800 Subject: [PATCH 1055/1197] change the condition of isLanNode --- .../org/tron/core/net/service/effective/ResilienceService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index ac54c5b8b4e..6375995c853 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -167,7 +167,7 @@ private boolean isLanNode() { int activePeerSize = (int) tronNetDelegate.getActivePeer().stream() .filter(peer -> peer.getChannel().isActive()) .count(); - return peerSize > CommonParameter.getInstance().getMinActiveConnections() + return peerSize >= CommonParameter.getInstance().getMinActiveConnections() && peerSize == activePeerSize; } From 40cb055466aa4b7cbc1c49365a78dfe3145cf653 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 13 Aug 2024 18:02:49 +0800 Subject: [PATCH 1056/1197] don't disconnect with syncing peer if i am lan node --- .../org/tron/core/net/service/effective/ResilienceService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index 6375995c853..b0806457a4b 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -97,6 +97,7 @@ private void disconnectLan() { long now = System.currentTimeMillis(); List peers = tronNetDelegate.getActivePeer().stream() .filter(peer -> now - peer.getLastActiveTime() >= inactiveThreshold) + .filter(peer -> !peer.isNeedSyncFromPeer() && !peer.isNeedSyncFromUs()) .filter(peer -> !peer.getChannel().isTrustPeer()) .collect(Collectors.toList()); Optional one = getEarliestPeer(peers); From 14a07509108a979e14c14ebecf46fe414324a3b9 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 14 Aug 2024 15:14:23 +0800 Subject: [PATCH 1057/1197] modify testcase of ResilienceServiceTest --- .../tron/core/net/services/ResilienceServiceTest.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java b/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java index a8b8e04d3cb..cc09fb45c28 100644 --- a/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java @@ -61,6 +61,10 @@ public void testDisconnectRandom() { PeerManager.add(context, c1); } + for (PeerConnection peer : PeerManager.getPeers()) { + peer.setNeedSyncFromPeer(false); + peer.setNeedSyncFromUs(false); + } ReflectUtils.invokeMethod(service, "disconnectRandom"); Assert.assertEquals(maxConnection, PeerManager.getPeers().size()); @@ -93,7 +97,10 @@ public void testDisconnectLan() { PeerManager.add(context, c1); } - + for (PeerConnection peer : PeerManager.getPeers()) { + peer.setNeedSyncFromPeer(false); + peer.setNeedSyncFromUs(false); + } Assert.assertEquals(9, PeerManager.getPeers().size()); boolean isLan = ReflectUtils.invokeMethod(service, "isLanNode"); From 930362b94ad62a36d1ebeb828023a1b8ce33bda8 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Wed, 14 Aug 2024 16:33:19 +0800 Subject: [PATCH 1058/1197] feat(net): discard block inventory below the solidified block --- .../main/java/org/tron/core/net/TronNetDelegate.java | 4 ++++ .../org/tron/core/net/service/adv/AdvService.java | 12 ++++++++++-- .../org/tron/core/net/services/AdvServiceTest.java | 7 +++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index cd9c8f01d8b..100bad179bf 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -156,6 +156,10 @@ public BlockId getKhaosDbHeadBlockId() { return chainBaseManager.getKhaosDbHead().getBlockId(); } + public long getSolidifiedBlockNum() { + return chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); + } + public BlockId getSolidBlockId() { return chainBaseManager.getSolidBlockId(); } diff --git a/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java b/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java index 505b53358c8..2241ce8d1ce 100644 --- a/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java +++ b/framework/src/main/java/org/tron/core/net/service/adv/AdvService.java @@ -121,8 +121,16 @@ public boolean addInv(Item item) { if (item.getType().equals(InventoryType.TRX) && trxCache.getIfPresent(item) != null) { return false; } - if (item.getType().equals(InventoryType.BLOCK) && blockCache.getIfPresent(item) != null) { - return false; + + if (item.getType().equals(InventoryType.BLOCK)) { + if (blockCache.getIfPresent(item) != null) { + return false; + } + + long solidNum = tronNetDelegate.getSolidifiedBlockNum(); + if (new BlockId(item.getHash()).getNum() <= solidNum) { + return false; + } } synchronized (this) { diff --git a/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java b/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java index d79b54f6f45..8a105c81e0f 100644 --- a/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java @@ -73,10 +73,17 @@ private void testAddInv() { Item itemBlock = new Item(Sha256Hash.ZERO_HASH, InventoryType.BLOCK); flag = service.addInv(itemBlock); + Assert.assertFalse(flag); + + BlockCapsule.BlockId blockId = new BlockCapsule.BlockId(Sha256Hash.ZERO_HASH, 1000L); + itemBlock = new Item(blockId, InventoryType.BLOCK); + flag = service.addInv(itemBlock); Assert.assertTrue(flag); flag = service.addInv(itemBlock); Assert.assertFalse(flag); + blockId = new BlockCapsule.BlockId(Sha256Hash.ZERO_HASH, 10000L); + itemBlock = new Item(blockId, InventoryType.BLOCK); service.addInvToCache(itemBlock); flag = service.addInv(itemBlock); Assert.assertFalse(flag); From 471b522ed2b83dc4cf0d5ff11fab28e0d7f1306b Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 15 Aug 2024 13:26:26 +0800 Subject: [PATCH 1059/1197] use the condition: active size >= min active size in isolate2 --- .../core/net/service/effective/ResilienceService.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index b0806457a4b..53e20d45fd1 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -111,10 +111,12 @@ private void disconnectIsolated2() { return; } logger.warn("Node is isolated, try to disconnect from peers"); - int peerSize = tronNetDelegate.getActivePeer().size(); //disconnect from the node whose lastActiveTime is smallest - if (peerSize >= CommonParameter.getInstance().getMinActiveConnections()) { + int activePeerSize = (int) tronNetDelegate.getActivePeer().stream() + .filter(peer -> peer.getChannel().isActive()) + .count(); + if (activePeerSize >= CommonParameter.getInstance().getMinActiveConnections()) { List peers = tronNetDelegate.getActivePeer().stream() .filter(peer -> !peer.getChannel().isTrustPeer()) .filter(peer -> peer.getChannel().isActive()) @@ -127,7 +129,7 @@ private void disconnectIsolated2() { //disconnect from some passive nodes, make sure retention nodes' num <= 0.8 * maxConnection, //so new peers can come in - peerSize = tronNetDelegate.getActivePeer().size(); + int peerSize = tronNetDelegate.getActivePeer().size(); int threshold = (int) (CommonParameter.getInstance().getMaxConnections() * retentionPercent); if (peerSize > threshold) { int disconnectSize = peerSize - threshold; From 553fbb451ae42eef65ad3b8c2040a86bbe188741 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 16 Aug 2024 11:06:11 +0800 Subject: [PATCH 1060/1197] change varible name from lastActiveTime to lastInteractiveTime --- .../java/org/tron/core/net/P2pEventHandlerImpl.java | 7 +++---- .../core/net/messagehandler/InventoryMsgHandler.java | 2 +- .../java/org/tron/core/net/peer/PeerConnection.java | 6 +++--- .../core/net/service/effective/ResilienceService.java | 11 ++++++----- .../org/tron/core/net/P2pEventHandlerImplTest.java | 4 ++-- .../tron/core/net/services/ResilienceServiceTest.java | 8 ++++---- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java index 0100dc443d9..795c90b4edd 100644 --- a/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java +++ b/framework/src/main/java/org/tron/core/net/P2pEventHandlerImpl.java @@ -40,7 +40,6 @@ import org.tron.p2p.connection.Channel; import org.tron.protos.Protocol; import org.tron.protos.Protocol.Inventory.InventoryType; -import org.tron.protos.Protocol.ReasonCode; @Slf4j(topic = "net") @Component @@ -207,7 +206,7 @@ private void processMessage(PeerConnection peer, byte[] data) { default: throw new P2pException(P2pException.TypeEnum.NO_SUCH_MESSAGE, msg.getType().toString()); } - updateLastActiveTime(peer, msg); + updateLastInteractiveTime(peer, msg); } catch (Exception e) { processException(peer, msg, e); } finally { @@ -223,7 +222,7 @@ private void processMessage(PeerConnection peer, byte[] data) { } } - private void updateLastActiveTime(PeerConnection peer, TronMessage msg) { + private void updateLastInteractiveTime(PeerConnection peer, TronMessage msg) { MessageTypes type = msg.getType(); boolean flag = false; @@ -240,7 +239,7 @@ private void updateLastActiveTime(PeerConnection peer, TronMessage msg) { break; } if (flag) { - peer.setLastActiveTime(System.currentTimeMillis()); + peer.setLastInteractiveTime(System.currentTimeMillis()); } } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java index 5e303bd3d6f..e8783b25e95 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java @@ -40,7 +40,7 @@ public void processMessage(PeerConnection peer, TronMessage msg) { peer.getAdvInvReceive().put(item, System.currentTimeMillis()); advService.addInv(item); if (type.equals(InventoryType.BLOCK) && peer.getAdvInvSpread().getIfPresent(item) == null) { - peer.setLastActiveTime(System.currentTimeMillis()); + peer.setLastInteractiveTime(System.currentTimeMillis()); } } } diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index 24f43e1f3fa..2e08e105bed 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -81,7 +81,7 @@ public class PeerConnection { @Getter @Setter - private volatile long lastActiveTime; + private volatile long lastInteractiveTime; @Getter @Setter @@ -163,7 +163,7 @@ public void setChannel(Channel channel) { this.isRelayPeer = true; } this.nodeStatistics = TronStatsManager.getNodeStatistics(channel.getInetAddress()); - lastActiveTime = System.currentTimeMillis(); + lastInteractiveTime = System.currentTimeMillis(); } public void setBlockBothHave(BlockId blockId) { @@ -245,7 +245,7 @@ public String log() { remainNum, requested == null ? 0 : (now - requested.getValue()) / Constant.ONE_THOUSAND, - (now - lastActiveTime) / Constant.ONE_THOUSAND, + (now - lastInteractiveTime) / Constant.ONE_THOUSAND, syncBlockInProcess.size()); } diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index 53e20d45fd1..67c22616bed 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -74,7 +74,7 @@ private void disconnectRandom() { if (peerSize >= CommonParameter.getInstance().getMaxConnections()) { long now = System.currentTimeMillis(); List peers = tronNetDelegate.getActivePeer().stream() - .filter(peer -> now - peer.getLastActiveTime() >= inactiveThreshold) + .filter(peer -> now - peer.getLastInteractiveTime() >= inactiveThreshold) .filter(peer -> !peer.getChannel().isTrustPeer()) .filter(peer -> !peer.isNeedSyncFromUs() && !peer.isNeedSyncFromPeer()) .collect(Collectors.toList()); @@ -96,7 +96,7 @@ private void disconnectLan() { if (peerSize >= CommonParameter.getInstance().getMinConnections()) { long now = System.currentTimeMillis(); List peers = tronNetDelegate.getActivePeer().stream() - .filter(peer -> now - peer.getLastActiveTime() >= inactiveThreshold) + .filter(peer -> now - peer.getLastInteractiveTime() >= inactiveThreshold) .filter(peer -> !peer.isNeedSyncFromPeer() && !peer.isNeedSyncFromUs()) .filter(peer -> !peer.getChannel().isTrustPeer()) .collect(Collectors.toList()); @@ -138,7 +138,7 @@ private void disconnectIsolated2() { .filter(peer -> !peer.getChannel().isActive()) .collect(Collectors.toList()); try { - peers.sort(Comparator.comparing(PeerConnection::getLastActiveTime, Long::compareTo)); + peers.sort(Comparator.comparing(PeerConnection::getLastInteractiveTime, Long::compareTo)); } catch (Exception e) { logger.warn("Sort disconnectIsolated2 peers failed: {}", e.getMessage()); return; @@ -158,7 +158,7 @@ private Optional getEarliestPeer(List pees) { Optional one = Optional.empty(); try { one = pees.stream() - .min(Comparator.comparing(PeerConnection::getLastActiveTime, Long::compareTo)); + .min(Comparator.comparing(PeerConnection::getLastInteractiveTime, Long::compareTo)); } catch (Exception e) { logger.warn("Get earliest peer failed: {}", e.getMessage()); } @@ -184,7 +184,8 @@ private boolean isIsolateLand2() { private void disconnectFromPeer(PeerConnection peer, ReasonCode reasonCode, DisconnectCause cause) { - int inactiveSeconds = (int) ((System.currentTimeMillis() - peer.getLastActiveTime()) / 1000); + int inactiveSeconds = (int) ((System.currentTimeMillis() - peer.getLastInteractiveTime()) + / 1000); logger.info("Disconnect from peer {}, inactive seconds {}, cause: {}", peer.getInetSocketAddress(), inactiveSeconds, cause); peer.disconnect(reasonCode); diff --git a/framework/src/test/java/org/tron/core/net/P2pEventHandlerImplTest.java b/framework/src/test/java/org/tron/core/net/P2pEventHandlerImplTest.java index 7a3dc30cb86..27b98f4a441 100644 --- a/framework/src/test/java/org/tron/core/net/P2pEventHandlerImplTest.java +++ b/framework/src/test/java/org/tron/core/net/P2pEventHandlerImplTest.java @@ -113,7 +113,7 @@ public void testProcessInventoryMessage() throws Exception { } @Test - public void testUpdateLastActiveTime() throws Exception { + public void testUpdateLastInteractiveTime() throws Exception { String[] a = new String[0]; Args.setParam(a, Constant.TESTNET_CONF); @@ -127,6 +127,6 @@ public void testUpdateLastActiveTime() throws Exception { long t1 = System.currentTimeMillis(); FetchInvDataMessage message = new FetchInvDataMessage(new ArrayList<>(), InventoryType.BLOCK); method.invoke(p2pEventHandler, peer, message); - Assert.assertTrue(peer.getLastActiveTime() >= t1); + Assert.assertTrue(peer.getLastInteractiveTime() >= t1); } } diff --git a/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java b/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java index cc09fb45c28..2558e089b7e 100644 --- a/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java @@ -69,10 +69,10 @@ public void testDisconnectRandom() { Assert.assertEquals(maxConnection, PeerManager.getPeers().size()); PeerConnection p1 = PeerManager.getPeers().get(1); - p1.setLastActiveTime( + p1.setLastInteractiveTime( System.currentTimeMillis() - Args.getInstance().inactiveThreshold * 1000L - 1000); PeerConnection p2 = PeerManager.getPeers().get(10); - p2.setLastActiveTime( + p2.setLastInteractiveTime( System.currentTimeMillis() - Args.getInstance().inactiveThreshold * 1000L - 2000); ReflectUtils.invokeMethod(service, "disconnectRandom"); @@ -108,11 +108,11 @@ public void testDisconnectLan() { PeerConnection p1 = PeerManager.getPeers().get(1); InetSocketAddress address1 = p1.getChannel().getInetSocketAddress(); - p1.setLastActiveTime( + p1.setLastInteractiveTime( System.currentTimeMillis() - Args.getInstance().inactiveThreshold * 1000L - 1000); PeerConnection p2 = PeerManager.getPeers().get(2); InetSocketAddress address2 = p2.getChannel().getInetSocketAddress(); - p2.setLastActiveTime( + p2.setLastInteractiveTime( System.currentTimeMillis() - Args.getInstance().inactiveThreshold * 1000L - 2000); ReflectUtils.invokeMethod(service, "disconnectLan"); From 1a7abf39a691670ab0a55de7594c17109800e9bb Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 16 Aug 2024 11:53:23 +0800 Subject: [PATCH 1061/1197] fix the testcase of testUpdateLastInteractiveTime --- .../test/java/org/tron/core/net/P2pEventHandlerImplTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/test/java/org/tron/core/net/P2pEventHandlerImplTest.java b/framework/src/test/java/org/tron/core/net/P2pEventHandlerImplTest.java index 27b98f4a441..e0c816a537a 100644 --- a/framework/src/test/java/org/tron/core/net/P2pEventHandlerImplTest.java +++ b/framework/src/test/java/org/tron/core/net/P2pEventHandlerImplTest.java @@ -121,7 +121,7 @@ public void testUpdateLastInteractiveTime() throws Exception { P2pEventHandlerImpl p2pEventHandler = new P2pEventHandlerImpl(); Method method = p2pEventHandler.getClass() - .getDeclaredMethod("updateLastActiveTime", PeerConnection.class, TronMessage.class); + .getDeclaredMethod("updateLastInteractiveTime", PeerConnection.class, TronMessage.class); method.setAccessible(true); long t1 = System.currentTimeMillis(); From 31b5d46e8dba8c800550cc57136c881da7e3f34c Mon Sep 17 00:00:00 2001 From: fyyhtx <72650068+fyyhtx@users.noreply.github.com> Date: Mon, 19 Aug 2024 17:40:46 +0800 Subject: [PATCH 1062/1197] Add transaction expiration time check before execution (#1) feat(net): add transaction expiration time check before execution --- .../tron/core/capsule/TransactionCapsule.java | 9 +++ .../src/main/java/org/tron/core/Wallet.java | 1 + .../org/tron/core/net/TronNetDelegate.java | 8 ++ .../TransactionsMsgHandler.java | 5 ++ .../tron/core/db/TransactionExpireTest.java | 79 ++++++++++++++++--- .../TransactionsMsgHandlerTest.java | 43 ++++++++++ .../core/net/services/AdvServiceTest.java | 20 ++++- 7 files changed, 151 insertions(+), 14 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java index c0a0fa4d88c..2b5e8b98596 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -59,6 +59,7 @@ import org.tron.core.exception.P2pException; import org.tron.core.exception.PermissionException; import org.tron.core.exception.SignatureFormatException; +import org.tron.core.exception.TransactionExpirationException; import org.tron.core.exception.ValidateSignatureException; import org.tron.core.store.AccountStore; import org.tron.core.store.DynamicPropertiesStore; @@ -869,4 +870,12 @@ public void removeRedundantRet() { this.transaction = transactionBuilder.build(); } } + + public void checkExpiration(long nextSlotTime) throws TransactionExpirationException { + if (getExpiration() < nextSlotTime) { + throw new TransactionExpirationException(String.format( + "Transaction expiration time is %d, but next slot time is %d", + getExpiration(), nextSlotTime)); + } + } } diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 9d7eb75df1b..769274e8f2a 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -549,6 +549,7 @@ public GrpcAPI.Return broadcastTransaction(Transaction signedTransaction) { throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); } TransactionMessage message = new TransactionMessage(trx.getInstance().toByteArray()); + trx.checkExpiration(tronNetDelegate.getNextBlockSlotTime()); dbManager.pushTransaction(trx); int num = tronNetService.fastBroadcastTransaction(message); if (num == 0 && minEffectiveConnection != 0) { diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index cd9c8f01d8b..a6f9812a2d7 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -380,4 +380,12 @@ public boolean isBlockUnsolidified() { return headNum - solidNum >= maxUnsolidifiedBlocks; } + public long getNextBlockSlotTime() { + long slotCount = 1; + if (chainBaseManager.getDynamicPropertiesStore().getStateFlag() == 1) { + slotCount += chainBaseManager.getDynamicPropertiesStore().getMaintenanceSkipSlots(); + } + return chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp() + + slotCount * BLOCK_PRODUCED_INTERVAL; + } } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java index 665381b31a8..0c58fe08cd6 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java @@ -13,6 +13,7 @@ import org.tron.core.config.args.Args; import org.tron.core.exception.P2pException; import org.tron.core.exception.P2pException.TypeEnum; +import org.tron.core.exception.TransactionExpirationException; import org.tron.core.net.TronNetDelegate; import org.tron.core.net.message.TronMessage; import org.tron.core.net.message.adv.TransactionMessage; @@ -128,6 +129,7 @@ private void handleTransaction(PeerConnection peer, TransactionMessage trx) { } try { + trx.getTransactionCapsule().checkExpiration(tronNetDelegate.getNextBlockSlotTime()); tronNetDelegate.pushTransaction(trx.getTransactionCapsule()); advService.broadcast(trx); } catch (P2pException e) { @@ -137,6 +139,9 @@ private void handleTransaction(PeerConnection peer, TransactionMessage trx) { peer.setBadPeer(true); peer.disconnect(ReasonCode.BAD_TX); } + } catch (TransactionExpirationException e) { + logger.warn("{}. trx: {}, peer: {}", + e.getMessage(), trx.getMessageId(), peer.getInetAddress()); } catch (Exception e) { logger.error("Trx {} from peer {} process failed", trx.getMessageId(), peer.getInetAddress(), e); diff --git a/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java b/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java index 5243405b7e6..5193f4128cd 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java @@ -50,19 +50,6 @@ public void init() throws IOException { context = new TronApplicationContext(DefaultConfig.class); wallet = context.getBean(Wallet.class); dbManager = context.getBean(Manager.class); - - blockCapsule = new BlockCapsule( - 1, - Sha256Hash.wrap(ByteString.copyFrom( - ByteArray.fromHexString( - "0304f784e4e7bae517bcab94c3e0c9214fb4ac7ff9d7d5a937d1f40031f87b81"))), - 1, - ByteString.copyFromUtf8("testAddress")); - dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(blockCapsule.getNum()); - dbManager.getDynamicPropertiesStore() - .saveLatestBlockHeaderTimestamp(blockCapsule.getTimeStamp()); - dbManager.updateRecentBlock(blockCapsule); - initLocalWitness(); } private void initLocalWitness() { @@ -81,6 +68,19 @@ public void removeDb() { @Test public void testExpireTransaction() { + blockCapsule = new BlockCapsule( + 1, + Sha256Hash.wrap(ByteString.copyFrom( + ByteArray.fromHexString( + "0304f784e4e7bae517bcab94c3e0c9214fb4ac7ff9d7d5a937d1f40031f87b81"))), + 1, + ByteString.copyFromUtf8("testAddress")); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(blockCapsule.getNum()); + dbManager.getDynamicPropertiesStore() + .saveLatestBlockHeaderTimestamp(blockCapsule.getTimeStamp()); + dbManager.updateRecentBlock(blockCapsule); + initLocalWitness(); + TransferContract transferContract = TransferContract.newBuilder() .setAmount(1L) .setOwnerAddress(ByteString.copyFrom(Args.getLocalWitnesses() @@ -101,8 +101,61 @@ public void testExpireTransaction() { Assert.assertEquals(response_code.TRANSACTION_EXPIRATION_ERROR, result.getCode()); } + @Test + public void testExpireTransactionNew() { + blockCapsule = new BlockCapsule( + 1, + Sha256Hash.wrap(ByteString.copyFrom( + ByteArray.fromHexString( + "0304f784e4e7bae517bcab94c3e0c9214fb4ac7ff9d7d5a937d1f40031f87b81"))), + System.currentTimeMillis(), + ByteString.copyFromUtf8("testAddress")); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(blockCapsule.getNum()); + dbManager.getDynamicPropertiesStore() + .saveLatestBlockHeaderTimestamp(blockCapsule.getTimeStamp()); + dbManager.updateRecentBlock(blockCapsule); + initLocalWitness(); + byte[] address = Args.getLocalWitnesses() + .getWitnessAccountAddress(CommonParameter.getInstance().isECKeyCryptoEngine()); + ByteString addressByte = ByteString.copyFrom(address); + AccountCapsule accountCapsule = + new AccountCapsule(Protocol.Account.newBuilder().setAddress(addressByte).build()); + accountCapsule.setBalance(1000_000_000L); + dbManager.getChainBaseManager().getAccountStore() + .put(accountCapsule.createDbKey(), accountCapsule); + + TransferContract transferContract = TransferContract.newBuilder() + .setAmount(1L) + .setOwnerAddress(addressByte) + .setToAddress(ByteString.copyFrom(ByteArray.fromHexString( + (Wallet.getAddressPreFixString() + "A389132D6639FBDA4FBC8B659264E6B7C90DB086")))) + .build(); + TransactionCapsule transactionCapsule = + new TransactionCapsule(transferContract, ContractType.TransferContract); + transactionCapsule.setReference(blockCapsule.getNum(), blockCapsule.getBlockId().getBytes()); + + transactionCapsule.setExpiration(System.currentTimeMillis()); + transactionCapsule.sign(ByteArray.fromHexString(Args.getLocalWitnesses().getPrivateKey())); + + GrpcAPI.Return result = wallet.broadcastTransaction(transactionCapsule.getInstance()); + Assert.assertEquals(response_code.TRANSACTION_EXPIRATION_ERROR, result.getCode()); + } + @Test public void testTransactionApprovedList() { + blockCapsule = new BlockCapsule( + 1, + Sha256Hash.wrap(ByteString.copyFrom( + ByteArray.fromHexString( + "0304f784e4e7bae517bcab94c3e0c9214fb4ac7ff9d7d5a937d1f40031f87b81"))), + 1, + ByteString.copyFromUtf8("testAddress")); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(blockCapsule.getNum()); + dbManager.getDynamicPropertiesStore() + .saveLatestBlockHeaderTimestamp(blockCapsule.getTimeStamp()); + dbManager.updateRecentBlock(blockCapsule); + initLocalWitness(); + byte[] address = Args.getLocalWitnesses() .getWitnessAccountAddress(CommonParameter.getInstance().isECKeyCryptoEngine()); TransferContract transferContract = TransferContract.newBuilder() diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java index 47ffde30ac3..e1865543443 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java @@ -6,13 +6,18 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.LinkedBlockingQueue; + +import lombok.Getter; import org.joda.time.DateTime; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mockito; import org.tron.common.BaseTest; +import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.ByteArray; import org.tron.core.Constant; import org.tron.core.config.args.Args; @@ -75,10 +80,48 @@ public void testProcessMessage() { transactionsMsgHandler.processMessage(peer, new TransactionsMessage(transactionList)); Assert.assertNull(advInvRequest.get(item)); //Thread.sleep(10); + transactionsMsgHandler.close(); + BlockingQueue smartContractQueue = + new LinkedBlockingQueue(2); + smartContractQueue.offer(new TrxEvent(null, null)); + smartContractQueue.offer(new TrxEvent(null, null)); + Field field1 = TransactionsMsgHandler.class.getDeclaredField("smartContractQueue"); + field1.setAccessible(true); + field1.set(transactionsMsgHandler, smartContractQueue); + Protocol.Transaction trx1 = TvmTestUtils.generateTriggerSmartContractAndGetTransaction( + ByteArray.fromHexString("121212a9cf"), + ByteArray.fromHexString("121212a9cf"), + ByteArray.fromHexString("123456"), + 100, 100000000, 0, 0); + Map advInvRequest1 = new ConcurrentHashMap<>(); + Item item1 = new Item(new TransactionMessage(trx1).getMessageId(), + Protocol.Inventory.InventoryType.TRX); + advInvRequest1.put(item1, 0L); + Mockito.when(peer.getAdvInvRequest()).thenReturn(advInvRequest1); + List transactionList1 = new ArrayList<>(); + transactionList1.add(trx1); + transactionsMsgHandler.processMessage(peer, new TransactionsMessage(transactionList1)); + Assert.assertNull(advInvRequest.get(item1)); } catch (Exception e) { Assert.fail(); } finally { transactionsMsgHandler.close(); } } + + class TrxEvent { + + @Getter + private PeerConnection peer; + @Getter + private TransactionMessage msg; + @Getter + private long time; + + public TrxEvent(PeerConnection peer, TransactionMessage msg) { + this.peer = peer; + this.msg = msg; + this.time = System.currentTimeMillis(); + } + } } diff --git a/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java b/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java index d79b54f6f45..5eda8561236 100644 --- a/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java @@ -4,6 +4,8 @@ import java.io.IOException; import java.net.InetSocketAddress; + +import com.google.protobuf.Any; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -105,12 +107,28 @@ private void testBroadcast() { } private void testTrxBroadcast() { - Protocol.Transaction trx = Protocol.Transaction.newBuilder().build(); + Protocol.Transaction trx = Protocol.Transaction.newBuilder() + .setRawData( + Protocol.Transaction.raw.newBuilder() + .setRefBlockNum(1) + .setExpiration(System.currentTimeMillis() + 3000).build()).build(); CommonParameter.getInstance().setValidContractProtoThreadNum(1); TransactionMessage msg = new TransactionMessage(trx); service.broadcast(msg); Item item = new Item(msg.getMessageId(), InventoryType.TRX); Assert.assertNotNull(service.getMessage(item)); + + Protocol.Transaction expiredTrx = Protocol.Transaction.newBuilder() + .setRawData( + Protocol.Transaction.raw.newBuilder() + .setRefBlockNum(1) + .setExpiration(System.currentTimeMillis() - 1).build()) + .build(); + CommonParameter.getInstance().setValidContractProtoThreadNum(1); + TransactionMessage msg1 = new TransactionMessage(expiredTrx); + service.broadcast(msg); + Item item1 = new Item(msg1.getMessageId(), InventoryType.TRX); + Assert.assertNull(service.getMessage(item1)); } } From 8d496f8461b98e764dfce25e5bca6ed3364328c5 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Mon, 2 Sep 2024 17:27:41 +0800 Subject: [PATCH 1063/1197] prefer to disconnect from broadcast nodes when isOpenFullTcpDisconnect is enable --- .../net/service/effective/ResilienceService.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index 67c22616bed..cbef2a87742 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -47,7 +47,7 @@ public void init() { } catch (Exception e) { logger.error("DisconnectRandom node failed", e); } - }, initialDelay, 60, TimeUnit.SECONDS); + }, initialDelay, 30, TimeUnit.SECONDS); } else { logger.info("OpenFullTcpDisconnect is disabled"); } @@ -72,13 +72,19 @@ public void init() { private void disconnectRandom() { int peerSize = tronNetDelegate.getActivePeer().size(); if (peerSize >= CommonParameter.getInstance().getMaxConnections()) { - long now = System.currentTimeMillis(); List peers = tronNetDelegate.getActivePeer().stream() - .filter(peer -> now - peer.getLastInteractiveTime() >= inactiveThreshold) .filter(peer -> !peer.getChannel().isTrustPeer()) .filter(peer -> !peer.isNeedSyncFromUs() && !peer.isNeedSyncFromPeer()) .collect(Collectors.toList()); - if (!peers.isEmpty()) { + if (peers.size() >= 3) { + Optional one = getEarliestPeer(peers); + one.ifPresent(peer -> disconnectFromPeer(peer, ReasonCode.RANDOM_ELIMINATION, + DisconnectCause.RANDOM_ELIMINATION)); + } else { + peers = tronNetDelegate.getActivePeer().stream() + .filter(peer -> !peer.getChannel().isTrustPeer()) + .filter(peer -> peer.isNeedSyncFromUs() || peer.isNeedSyncFromPeer()) + .collect(Collectors.toList()); int index = new Random().nextInt(peers.size()); disconnectFromPeer(peers.get(index), ReasonCode.RANDOM_ELIMINATION, DisconnectCause.RANDOM_ELIMINATION); From f99d21636d3de0f8d2d7365d53447edfa9caa996 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 3 Sep 2024 12:34:10 +0800 Subject: [PATCH 1064/1197] adjust ResilienceServiceTest --- .../service/effective/ResilienceService.java | 3 +- .../net/services/ResilienceServiceTest.java | 34 ++++++++++++++----- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index cbef2a87742..48908cd350a 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -29,6 +29,7 @@ public class ResilienceService { //when node is isolated, retention percent peers will not be disconnected public static final double retentionPercent = 0.8; private static final int initialDelay = 300; + public static final int broadcastPeerSize = 3; private static final String esName = "resilience-service"; private final ScheduledExecutorService executor = ExecutorServiceManager .newSingleThreadScheduledExecutor(esName); @@ -76,7 +77,7 @@ private void disconnectRandom() { .filter(peer -> !peer.getChannel().isTrustPeer()) .filter(peer -> !peer.isNeedSyncFromUs() && !peer.isNeedSyncFromPeer()) .collect(Collectors.toList()); - if (peers.size() >= 3) { + if (peers.size() >= broadcastPeerSize) { Optional one = getEarliestPeer(peers); one.ifPresent(peer -> disconnectFromPeer(peer, ReasonCode.RANDOM_ELIMINATION, DisconnectCause.RANDOM_ELIMINATION)); diff --git a/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java b/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java index 2558e089b7e..1c3c6c27232 100644 --- a/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java @@ -51,7 +51,7 @@ public void testDisconnectRandom() { clearPeers(); Assert.assertEquals(0, PeerManager.getPeers().size()); - for (int i = 0; i < maxConnection; i++) { + for (int i = 0; i < maxConnection + 1; i++) { InetSocketAddress inetSocketAddress = new InetSocketAddress("201.0.0." + i, 10001); Channel c1 = spy(Channel.class); ReflectUtils.setFieldValue(c1, "inetSocketAddress", inetSocketAddress); @@ -61,21 +61,37 @@ public void testDisconnectRandom() { PeerManager.add(context, c1); } - for (PeerConnection peer : PeerManager.getPeers()) { + for (PeerConnection peer : PeerManager.getPeers() + .subList(0, ResilienceService.broadcastPeerSize)) { peer.setNeedSyncFromPeer(false); peer.setNeedSyncFromUs(false); + peer.setLastInteractiveTime(System.currentTimeMillis() - 1000); + } + for (PeerConnection peer : PeerManager.getPeers() + .subList(ResilienceService.broadcastPeerSize, maxConnection + 1)) { + peer.setNeedSyncFromPeer(false); + peer.setNeedSyncFromUs(true); } + int size1 = (int) PeerManager.getPeers().stream() + .filter(peer -> !peer.isNeedSyncFromUs() && !peer.isNeedSyncFromPeer()) + .count(); + Assert.assertEquals(ResilienceService.broadcastPeerSize, size1); + Assert.assertEquals(maxConnection + 1, PeerManager.getPeers().size()); + + //disconnect from broadcasting peer ReflectUtils.invokeMethod(service, "disconnectRandom"); + size1 = (int) PeerManager.getPeers().stream() + .filter(peer -> !peer.isNeedSyncFromUs() && !peer.isNeedSyncFromPeer()) + .count(); + Assert.assertEquals(ResilienceService.broadcastPeerSize - 1, size1); Assert.assertEquals(maxConnection, PeerManager.getPeers().size()); - PeerConnection p1 = PeerManager.getPeers().get(1); - p1.setLastInteractiveTime( - System.currentTimeMillis() - Args.getInstance().inactiveThreshold * 1000L - 1000); - PeerConnection p2 = PeerManager.getPeers().get(10); - p2.setLastInteractiveTime( - System.currentTimeMillis() - Args.getInstance().inactiveThreshold * 1000L - 2000); - + //disconnect from syncing peer ReflectUtils.invokeMethod(service, "disconnectRandom"); + size1 = (int) PeerManager.getPeers().stream() + .filter(peer -> !peer.isNeedSyncFromUs() && !peer.isNeedSyncFromPeer()) + .count(); + Assert.assertEquals(ResilienceService.broadcastPeerSize - 1, size1); Assert.assertEquals(maxConnection - 1, PeerManager.getPeers().size()); } From e242ae14738e61b6bf8c65e19cb2cff1fb188536 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 3 Sep 2024 17:38:27 +0800 Subject: [PATCH 1065/1197] add testcase PeerStatusCheckTest --- .../core/net/peer/PeerStatusCheckTest.java | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckTest.java diff --git a/framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckTest.java b/framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckTest.java new file mode 100644 index 00000000000..53e678c7ca4 --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckTest.java @@ -0,0 +1,73 @@ +package org.tron.core.net.peer; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.spy; + +import io.netty.channel.ChannelHandlerContext; +import java.io.IOException; +import java.net.InetSocketAddress; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.mockito.Mockito; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.utils.ReflectUtils; +import org.tron.core.Constant; +import org.tron.core.capsule.BlockCapsule.BlockId; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.Parameter.NetConstants; +import org.tron.core.config.args.Args; +import org.tron.p2p.connection.Channel; + + +public class PeerStatusCheckTest { + + protected TronApplicationContext context; + private PeerStatusCheck service; + @Rule + public final TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Before + public void init() throws IOException { + Args.setParam(new String[] {"--output-directory", + temporaryFolder.newFolder().toString(), "--debug"}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + service = context.getBean(PeerStatusCheck.class); + } + + /** + * destroy. + */ + @After + public void destroy() { + Args.clearParam(); + context.destroy(); + } + + @Test + public void testCheck() { + int maxConnection = 30; + Assert.assertEquals(maxConnection, Args.getInstance().getMaxConnections()); + Assert.assertEquals(0, PeerManager.getPeers().size()); + + for (int i = 0; i < maxConnection; i++) { + InetSocketAddress inetSocketAddress = new InetSocketAddress("201.0.0." + i, 10001); + Channel c1 = spy(Channel.class); + ReflectUtils.setFieldValue(c1, "inetSocketAddress", inetSocketAddress); + ReflectUtils.setFieldValue(c1, "inetAddress", inetSocketAddress.getAddress()); + ReflectUtils.setFieldValue(c1, "ctx", spy(ChannelHandlerContext.class)); + Mockito.doNothing().when(c1).send((byte[]) any()); + + PeerManager.add(context, c1); + } + + PeerManager.getPeers().get(0).getSyncBlockRequested() + .put(new BlockId(), System.currentTimeMillis() - NetConstants.SYNC_TIME_OUT - 1000); + ReflectUtils.invokeMethod(service, "statusCheck"); + + Assert.assertEquals(maxConnection - 1L, PeerManager.getPeers().size()); + } +} From 6c3a52637ad8816eb1fa2220a26157d8e49495d3 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 4 Sep 2024 12:52:35 +0800 Subject: [PATCH 1066/1197] use WeightedRandom to choose broadcast peer --- .../service/effective/ResilienceService.java | 73 +++++++++++++++---- 1 file changed, 57 insertions(+), 16 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index 48908cd350a..89065841d2f 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -1,7 +1,9 @@ package org.tron.core.net.service.effective; import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Random; import java.util.concurrent.ScheduledExecutorService; @@ -72,27 +74,40 @@ public void init() { private void disconnectRandom() { int peerSize = tronNetDelegate.getActivePeer().size(); - if (peerSize >= CommonParameter.getInstance().getMaxConnections()) { - List peers = tronNetDelegate.getActivePeer().stream() + if (peerSize < CommonParameter.getInstance().getMaxConnections()) { + return; + } + List peers = tronNetDelegate.getActivePeer().stream() + .filter(peer -> !peer.getChannel().isTrustPeer()) + .filter(peer -> !peer.isNeedSyncFromUs() && !peer.isNeedSyncFromPeer()) + .collect(Collectors.toList()); + + if (peers.size() >= broadcastPeerSize) { + long now = System.currentTimeMillis(); + Map weights = new HashMap<>(); + peers.forEach(peer -> weights.put(peer, + (int) Math.ceil((double) (now - peer.getLastInteractiveTime()) / 500))); + WeightedRandom weightedRandom = new WeightedRandom(weights); + PeerConnection one; + try { + one = (PeerConnection) weightedRandom.next(); + } catch (Exception e) { + logger.warn("Get random peer failed: {}", e.getMessage()); + return; + } + disconnectFromPeer(one, ReasonCode.RANDOM_ELIMINATION, DisconnectCause.RANDOM_ELIMINATION); + } else { + peers = tronNetDelegate.getActivePeer().stream() .filter(peer -> !peer.getChannel().isTrustPeer()) - .filter(peer -> !peer.isNeedSyncFromUs() && !peer.isNeedSyncFromPeer()) + .filter(peer -> peer.isNeedSyncFromUs() || peer.isNeedSyncFromPeer()) .collect(Collectors.toList()); - if (peers.size() >= broadcastPeerSize) { - Optional one = getEarliestPeer(peers); - one.ifPresent(peer -> disconnectFromPeer(peer, ReasonCode.RANDOM_ELIMINATION, - DisconnectCause.RANDOM_ELIMINATION)); - } else { - peers = tronNetDelegate.getActivePeer().stream() - .filter(peer -> !peer.getChannel().isTrustPeer()) - .filter(peer -> peer.isNeedSyncFromUs() || peer.isNeedSyncFromPeer()) - .collect(Collectors.toList()); - int index = new Random().nextInt(peers.size()); - disconnectFromPeer(peers.get(index), ReasonCode.RANDOM_ELIMINATION, - DisconnectCause.RANDOM_ELIMINATION); - } + int index = new Random().nextInt(peers.size()); + disconnectFromPeer(peers.get(index), ReasonCode.RANDOM_ELIMINATION, + DisconnectCause.RANDOM_ELIMINATION); } } + private void disconnectLan() { if (!isLanNode()) { return; @@ -205,6 +220,32 @@ private enum DisconnectCause { ISOLATE2_PASSIVE, } + class WeightedRandom { + + private final Map weights; + private final Random random; + + public WeightedRandom(Map weights) { + this.weights = weights; + this.random = new Random(); + } + + public Object next() { + int totalWeight = 0; + for (int weight : weights.values()) { + totalWeight += weight; + } + int randomNum = random.nextInt(totalWeight); + for (Object key : weights.keySet()) { + randomNum -= weights.get(key); + if (randomNum < 0) { + return key; + } + } + throw new IllegalStateException("Sum of weights should not be negative."); + } + } + public void close() { ExecutorServiceManager.shutdownAndAwaitTermination(executor, esName); } From 59e92c8d86d2439cad635bf80a3ed959be809e0c Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 4 Sep 2024 16:36:57 +0800 Subject: [PATCH 1067/1197] don't disconnect from high peer if its number <=1 --- .../service/effective/ResilienceService.java | 36 ++++++++++++------- .../net/services/ResilienceServiceTest.java | 10 +++--- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index 89065841d2f..a63fd4bf0a9 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -31,7 +31,7 @@ public class ResilienceService { //when node is isolated, retention percent peers will not be disconnected public static final double retentionPercent = 0.8; private static final int initialDelay = 300; - public static final int broadcastPeerSize = 3; + public static final int minBroadcastPeerSize = 3; private static final String esName = "resilience-service"; private final ScheduledExecutorService executor = ExecutorServiceManager .newSingleThreadScheduledExecutor(esName); @@ -82,25 +82,35 @@ private void disconnectRandom() { .filter(peer -> !peer.isNeedSyncFromUs() && !peer.isNeedSyncFromPeer()) .collect(Collectors.toList()); - if (peers.size() >= broadcastPeerSize) { + if (peers.size() >= minBroadcastPeerSize) { long now = System.currentTimeMillis(); Map weights = new HashMap<>(); - peers.forEach(peer -> weights.put(peer, - (int) Math.ceil((double) (now - peer.getLastInteractiveTime()) / 500))); + peers.forEach(peer -> { + int weight = (int) Math.ceil((double) (now - peer.getLastInteractiveTime()) / 500); + weights.put(peer, Math.max(weight, 1)); + }); WeightedRandom weightedRandom = new WeightedRandom(weights); - PeerConnection one; - try { - one = (PeerConnection) weightedRandom.next(); - } catch (Exception e) { - logger.warn("Get random peer failed: {}", e.getMessage()); - return; - } + PeerConnection one = (PeerConnection) weightedRandom.next(); disconnectFromPeer(one, ReasonCode.RANDOM_ELIMINATION, DisconnectCause.RANDOM_ELIMINATION); - } else { + return; + } + + int needSyncFromPeerCount = (int) tronNetDelegate.getActivePeer().stream() + .filter(peer -> !peer.getChannel().isTrustPeer()) + .filter(PeerConnection::isNeedSyncFromPeer) + .count(); + if (needSyncFromPeerCount >= 2) { peers = tronNetDelegate.getActivePeer().stream() .filter(peer -> !peer.getChannel().isTrustPeer()) .filter(peer -> peer.isNeedSyncFromUs() || peer.isNeedSyncFromPeer()) .collect(Collectors.toList()); + } else { + peers = tronNetDelegate.getActivePeer().stream() + .filter(peer -> !peer.getChannel().isTrustPeer()) + .filter(PeerConnection::isNeedSyncFromUs) + .collect(Collectors.toList()); + } + if (!peers.isEmpty()) { int index = new Random().nextInt(peers.size()); disconnectFromPeer(peers.get(index), ReasonCode.RANDOM_ELIMINATION, DisconnectCause.RANDOM_ELIMINATION); @@ -220,7 +230,7 @@ private enum DisconnectCause { ISOLATE2_PASSIVE, } - class WeightedRandom { + static class WeightedRandom { private final Map weights; private final Random random; diff --git a/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java b/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java index 1c3c6c27232..ce723e5c991 100644 --- a/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/ResilienceServiceTest.java @@ -62,20 +62,20 @@ public void testDisconnectRandom() { PeerManager.add(context, c1); } for (PeerConnection peer : PeerManager.getPeers() - .subList(0, ResilienceService.broadcastPeerSize)) { + .subList(0, ResilienceService.minBroadcastPeerSize)) { peer.setNeedSyncFromPeer(false); peer.setNeedSyncFromUs(false); peer.setLastInteractiveTime(System.currentTimeMillis() - 1000); } for (PeerConnection peer : PeerManager.getPeers() - .subList(ResilienceService.broadcastPeerSize, maxConnection + 1)) { + .subList(ResilienceService.minBroadcastPeerSize, maxConnection + 1)) { peer.setNeedSyncFromPeer(false); peer.setNeedSyncFromUs(true); } int size1 = (int) PeerManager.getPeers().stream() .filter(peer -> !peer.isNeedSyncFromUs() && !peer.isNeedSyncFromPeer()) .count(); - Assert.assertEquals(ResilienceService.broadcastPeerSize, size1); + Assert.assertEquals(ResilienceService.minBroadcastPeerSize, size1); Assert.assertEquals(maxConnection + 1, PeerManager.getPeers().size()); //disconnect from broadcasting peer @@ -83,7 +83,7 @@ public void testDisconnectRandom() { size1 = (int) PeerManager.getPeers().stream() .filter(peer -> !peer.isNeedSyncFromUs() && !peer.isNeedSyncFromPeer()) .count(); - Assert.assertEquals(ResilienceService.broadcastPeerSize - 1, size1); + Assert.assertEquals(ResilienceService.minBroadcastPeerSize - 1, size1); Assert.assertEquals(maxConnection, PeerManager.getPeers().size()); //disconnect from syncing peer @@ -91,7 +91,7 @@ public void testDisconnectRandom() { size1 = (int) PeerManager.getPeers().stream() .filter(peer -> !peer.isNeedSyncFromUs() && !peer.isNeedSyncFromPeer()) .count(); - Assert.assertEquals(ResilienceService.broadcastPeerSize - 1, size1); + Assert.assertEquals(ResilienceService.minBroadcastPeerSize - 1, size1); Assert.assertEquals(maxConnection - 1, PeerManager.getPeers().size()); } From 6c73edef1fedab8e05bdd7b0fe3b177e25f29036 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 12 Sep 2024 12:35:01 +0800 Subject: [PATCH 1068/1197] feat(net): delete useless test code --- .../src/test/java/org/tron/core/net/services/AdvServiceTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java b/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java index 5eda8561236..c4ac4b06c43 100644 --- a/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/AdvServiceTest.java @@ -5,7 +5,6 @@ import java.io.IOException; import java.net.InetSocketAddress; -import com.google.protobuf.Any; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; From bd7b3d18341abe326dbb65ebcf3d2dfb6ec185be Mon Sep 17 00:00:00 2001 From: waynercheung Date: Wed, 18 Sep 2024 17:54:35 +0800 Subject: [PATCH 1069/1197] feat(jsonrpc): ethGetBlockByNumber supports finalized --- .../src/main/java/org/tron/core/Wallet.java | 26 +++++++++++++++---- .../core/services/jsonrpc/JsonRpcApiUtil.java | 3 ++- .../services/jsonrpc/TronJsonRpcImpl.java | 2 ++ 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 9d7eb75df1b..b3754db9241 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -29,6 +29,10 @@ import static org.tron.core.config.Parameter.DatabaseConstants.PROPOSAL_COUNT_LIMIT_MAX; import static org.tron.core.services.jsonrpc.JsonRpcApiUtil.parseEnergyFee; import static org.tron.core.services.jsonrpc.TronJsonRpcImpl.EARLIEST_STR; +import static org.tron.core.services.jsonrpc.TronJsonRpcImpl.FINALIZED_STR; +import static org.tron.core.services.jsonrpc.TronJsonRpcImpl.LATEST_STR; +import static org.tron.core.services.jsonrpc.TronJsonRpcImpl.PENDING_STR; +import static org.tron.core.services.jsonrpc.TronJsonRpcImpl.TAG_PENDING_SUPPORT_ERROR; import static org.tron.core.vm.utils.FreezeV2Util.getV2EnergyUsage; import static org.tron.core.vm.utils.FreezeV2Util.getV2NetUsage; import static org.tron.protos.contract.Common.ResourceCode; @@ -681,6 +685,16 @@ public Block getBlockByNum(long blockNum) { } } + public Block getFinalizedBlock() { + try { + long blockNum = chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); + return chainBaseManager.getBlockByNum(blockNum).getInstance(); + } catch (StoreException e) { + logger.info(e.getMessage()); + return null; + } + } + public BlockCapsule getBlockCapsuleByNum(long blockNum) { try { return chainBaseManager.getBlockByNum(blockNum); @@ -706,10 +720,12 @@ public long getTransactionCountByBlockNum(long blockNum) { public Block getByJsonBlockId(String id) throws JsonRpcInvalidParamsException { if (EARLIEST_STR.equalsIgnoreCase(id)) { return getBlockByNum(0); - } else if ("latest".equalsIgnoreCase(id)) { + } else if (LATEST_STR.equalsIgnoreCase(id)) { return getNowBlock(); - } else if ("pending".equalsIgnoreCase(id)) { - throw new JsonRpcInvalidParamsException("TAG pending not supported"); + } else if (FINALIZED_STR.equalsIgnoreCase(id)) { + return getFinalizedBlock(); + } else if (PENDING_STR.equalsIgnoreCase(id)) { + throw new JsonRpcInvalidParamsException(TAG_PENDING_SUPPORT_ERROR); } else { long blockNumber; try { @@ -724,8 +740,8 @@ public Block getByJsonBlockId(String id) throws JsonRpcInvalidParamsException { public List getTransactionsByJsonBlockId(String id) throws JsonRpcInvalidParamsException { - if ("pending".equalsIgnoreCase(id)) { - throw new JsonRpcInvalidParamsException("TAG pending not supported"); + if (PENDING_STR.equalsIgnoreCase(id)) { + throw new JsonRpcInvalidParamsException(TAG_PENDING_SUPPORT_ERROR); } else { Block block = getByJsonBlockId(id); return block != null ? block.getTransactionsList() : null; diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java index 4efc5994c0d..3891e472e7c 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java @@ -3,6 +3,7 @@ import static org.tron.core.services.jsonrpc.TronJsonRpcImpl.EARLIEST_STR; import static org.tron.core.services.jsonrpc.TronJsonRpcImpl.LATEST_STR; import static org.tron.core.services.jsonrpc.TronJsonRpcImpl.PENDING_STR; +import static org.tron.core.services.jsonrpc.TronJsonRpcImpl.TAG_PENDING_SUPPORT_ERROR; import com.google.common.base.Throwables; import com.google.common.primitives.Longs; @@ -515,7 +516,7 @@ public static long parseEnergyFee(long timestamp, String energyPriceHistory) { public static long getByJsonBlockId(String blockNumOrTag) throws JsonRpcInvalidParamsException { if (PENDING_STR.equalsIgnoreCase(blockNumOrTag)) { - throw new JsonRpcInvalidParamsException("TAG pending not supported"); + throw new JsonRpcInvalidParamsException(TAG_PENDING_SUPPORT_ERROR); } if (StringUtils.isEmpty(blockNumOrTag) || LATEST_STR.equalsIgnoreCase(blockNumOrTag)) { return -1; diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 0ca57a3b98c..1bb93001055 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -136,6 +136,8 @@ public enum RequestSource { public static final String EARLIEST_STR = "earliest"; public static final String PENDING_STR = "pending"; public static final String LATEST_STR = "latest"; + public static final String FINALIZED_STR = "finalized"; + public static final String TAG_PENDING_SUPPORT_ERROR = "TAG pending not supported"; private static final String JSON_ERROR = "invalid json request"; private static final String BLOCK_NUM_ERROR = "invalid block number"; From f9a86f72058fc798835e736a58eedd0349867a3d Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 28 Aug 2024 18:28:49 +0800 Subject: [PATCH 1070/1197] feat(test): improve unit test coverage --- .../test/java/org/tron/common/EntityTest.java | 67 + .../tron/common/MultiLayoutPatternTest.java | 72 + .../java/org/tron/common/ParameterTest.java | 320 +++++ .../org/tron/common/cache/TronCacheTest.java | 100 ++ .../common/logsfilter/EventLoaderTest.java | 29 +- .../common/logsfilter/FilterQueryTest.java | 78 +- .../capsule/BlockFilterCapsuleTest.java | 38 + .../capsule/BlockLogTriggerCapsuleTest.java | 35 + .../ContractLogTriggerCapsuleTest.java | 36 + .../capsule/ContractTriggerCapsuleTest.java | 70 + .../capsule/LogsFilterCapsuleTest.java | 33 + .../logsfilter/capsule/RawDataTest.java | 33 + .../capsule/SolidityEventCapsuleTest.java | 32 + .../capsule/SolidityLogCapsuleTest.java | 31 + .../capsule/SolidityTriggerCapsuleTest.java | 37 + .../trigger/ContractLogTriggerTest.java | 82 ++ .../trigger/InternalTransactionPojoTest.java | 87 ++ .../logsfilter/trigger/LogPojoTest.java | 74 ++ .../tron/common/runtime/vm/BatchSendTest.java | 1 + .../tron/common/runtime/vm/DataWordTest.java | 86 +- .../java/org/tron/common/utils/ALockTest.java | 27 + .../org/tron/common/utils/BIUtilTest.java | 155 +++ .../tron/common/utils/ByteArrayMapTest.java | 145 ++ .../tron/common/utils/ByteArraySetTest.java | 143 ++ .../org/tron/common/utils/ByteArrayTest.java | 35 + .../common/utils/CollectionUtilsTest.java | 81 ++ .../org/tron/common/utils/FileUtilTest.java | 103 +- .../org/tron/common/utils/JsonUtilTest.java | 53 +- .../common/utils/RandomGeneratorTest.java | 25 +- .../org/tron/common/utils/SetAdapterTest.java | 114 ++ .../org/tron/common/utils/Sha256HashTest.java | 40 +- .../utils/SlidingWindowCounterTest.java | 63 + .../tron/common/utils/TypeConversionTest.java | 12 + .../java/org/tron/common/utils/UtilsTest.java | 74 ++ .../java/org/tron/common/utils/ValueTest.java | 198 +++ .../common/utils/client/utils/HttpMethed.java | 2 - .../common/zksnark/ZksnarkClientTest.java | 43 + .../java/org/tron/core/CoreExceptionTest.java | 1161 +++++++++++++++++ .../tron/core/capsule/utils/RLPListTest.java | 6 +- .../core/config/args/LocalWitnessTest.java | 25 +- .../java/org/tron/core/db/ManagerTest.java | 12 +- .../org/tron/core/db/api/pojo/PojoTest.java | 80 ++ .../ChainInventoryMsgHandlerTest.java | 13 +- .../SyncBlockChainMsgHandlerTest.java | 10 +- .../net/service/nodepersist/DBNodeTest.java | 52 + .../tron/core/zksnark/SendCoinShieldTest.java | 17 + .../core/zksnark/ShieldedReceiveTest.java | 31 +- .../java/org/tron/program/SupplementTest.java | 17 + 48 files changed, 3978 insertions(+), 100 deletions(-) create mode 100644 framework/src/test/java/org/tron/common/EntityTest.java create mode 100644 framework/src/test/java/org/tron/common/MultiLayoutPatternTest.java create mode 100644 framework/src/test/java/org/tron/common/ParameterTest.java create mode 100644 framework/src/test/java/org/tron/common/cache/TronCacheTest.java create mode 100644 framework/src/test/java/org/tron/common/logsfilter/capsule/BlockFilterCapsuleTest.java create mode 100644 framework/src/test/java/org/tron/common/logsfilter/capsule/BlockLogTriggerCapsuleTest.java create mode 100644 framework/src/test/java/org/tron/common/logsfilter/capsule/ContractLogTriggerCapsuleTest.java create mode 100644 framework/src/test/java/org/tron/common/logsfilter/capsule/ContractTriggerCapsuleTest.java create mode 100644 framework/src/test/java/org/tron/common/logsfilter/capsule/LogsFilterCapsuleTest.java create mode 100644 framework/src/test/java/org/tron/common/logsfilter/capsule/RawDataTest.java create mode 100644 framework/src/test/java/org/tron/common/logsfilter/capsule/SolidityEventCapsuleTest.java create mode 100644 framework/src/test/java/org/tron/common/logsfilter/capsule/SolidityLogCapsuleTest.java create mode 100644 framework/src/test/java/org/tron/common/logsfilter/capsule/SolidityTriggerCapsuleTest.java create mode 100644 framework/src/test/java/org/tron/common/logsfilter/trigger/ContractLogTriggerTest.java create mode 100644 framework/src/test/java/org/tron/common/logsfilter/trigger/InternalTransactionPojoTest.java create mode 100644 framework/src/test/java/org/tron/common/logsfilter/trigger/LogPojoTest.java create mode 100644 framework/src/test/java/org/tron/common/utils/ALockTest.java create mode 100644 framework/src/test/java/org/tron/common/utils/BIUtilTest.java create mode 100644 framework/src/test/java/org/tron/common/utils/ByteArrayMapTest.java create mode 100644 framework/src/test/java/org/tron/common/utils/ByteArraySetTest.java create mode 100644 framework/src/test/java/org/tron/common/utils/CollectionUtilsTest.java create mode 100644 framework/src/test/java/org/tron/common/utils/SetAdapterTest.java create mode 100644 framework/src/test/java/org/tron/common/utils/SlidingWindowCounterTest.java create mode 100644 framework/src/test/java/org/tron/common/utils/UtilsTest.java create mode 100644 framework/src/test/java/org/tron/common/utils/ValueTest.java create mode 100644 framework/src/test/java/org/tron/common/zksnark/ZksnarkClientTest.java create mode 100644 framework/src/test/java/org/tron/core/CoreExceptionTest.java create mode 100644 framework/src/test/java/org/tron/core/db/api/pojo/PojoTest.java create mode 100644 framework/src/test/java/org/tron/core/net/service/nodepersist/DBNodeTest.java diff --git a/framework/src/test/java/org/tron/common/EntityTest.java b/framework/src/test/java/org/tron/common/EntityTest.java new file mode 100644 index 00000000000..483475a453b --- /dev/null +++ b/framework/src/test/java/org/tron/common/EntityTest.java @@ -0,0 +1,67 @@ +package org.tron.common; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.google.common.collect.Lists; +import java.util.HashMap; +import org.apache.commons.collections4.CollectionUtils; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.entity.NodeInfo; +import org.tron.common.entity.NodeInfo.MachineInfo; +import org.tron.common.entity.NodeInfo.MachineInfo.DeadLockThreadInfo; + +public class EntityTest { + + private final MachineInfo machineInfo = new MachineInfo(); + private final DeadLockThreadInfo deadLockThreadInfo = new DeadLockThreadInfo(); + + @Before + public void setup() { + deadLockThreadInfo.setName("name"); + deadLockThreadInfo.setLockName("lockName"); + deadLockThreadInfo.setLockOwner("lockOwner"); + deadLockThreadInfo.setState("state"); + deadLockThreadInfo.setStackTrace("stackTrace"); + deadLockThreadInfo.setWaitTime(0L); + deadLockThreadInfo.setBlockTime(0L); + machineInfo.setDeadLockThreadInfoList(Lists.newArrayList(deadLockThreadInfo)); + machineInfo.setJavaVersion("1.8"); + machineInfo.setOsName("linux"); + } + + @Test + public void testMachineInfo() { + machineInfo.setDeadLockThreadCount(3); + assertTrue(CollectionUtils.isNotEmpty(machineInfo.getDeadLockThreadInfoList())); + assertEquals(3, machineInfo.getDeadLockThreadCount()); + + } + + @Test + public void testDeadLockThreadInfo() { + assertEquals("name", deadLockThreadInfo.getName()); + assertEquals("lockName", deadLockThreadInfo.getLockName()); + assertEquals("lockOwner", deadLockThreadInfo.getLockOwner()); + assertEquals("state", deadLockThreadInfo.getState()); + assertEquals("stackTrace", deadLockThreadInfo.getStackTrace()); + assertEquals(0, deadLockThreadInfo.getBlockTime()); + assertEquals(0, deadLockThreadInfo.getWaitTime()); + + } + + @Test + public void testNodeInfo() { + NodeInfo nodeInfo = new NodeInfo(); + nodeInfo.setTotalFlow(1L); + nodeInfo.setCheatWitnessInfoMap(new HashMap<>()); + assertEquals(1, nodeInfo.getTotalFlow()); + assertNotNull(nodeInfo.getCheatWitnessInfoMap()); + nodeInfo.setMachineInfo(machineInfo); + nodeInfo.setBlock("block"); + nodeInfo.setSolidityBlock("solidityBlock"); + nodeInfo.transferToProtoEntity(); + } +} diff --git a/framework/src/test/java/org/tron/common/MultiLayoutPatternTest.java b/framework/src/test/java/org/tron/common/MultiLayoutPatternTest.java new file mode 100644 index 00000000000..87223757e8e --- /dev/null +++ b/framework/src/test/java/org/tron/common/MultiLayoutPatternTest.java @@ -0,0 +1,72 @@ +package org.tron.common; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.LoggerFactory; +import org.tron.common.log.layout.MultiLayoutPattern; + +public class MultiLayoutPatternTest { + + private MultiLayoutPattern multiLayoutPattern; + private LoggerContext context; + + @Before + public void setUp() { + context = new LoggerContext(); + multiLayoutPattern = new MultiLayoutPattern(); + multiLayoutPattern.setContext(context); + + MultiLayoutPattern.Rule rule1 = new MultiLayoutPattern.Rule(); + rule1.setLogger("com.example.app1"); + assertNotNull(rule1.getLogger()); + rule1.setPattern("%date [%thread] %-5level %logger{36} - %msg%n"); + assertNotNull(rule1.getPattern()); + rule1.setOutputPatternAsHeader(true); + assertTrue(rule1.isOutputPatternAsHeader()); + multiLayoutPattern.addRule(rule1); + + MultiLayoutPattern.Rule rule2 = new MultiLayoutPattern.Rule(); + rule2.setLogger("com.example.app2"); + rule2.setPattern("%msg%n"); + multiLayoutPattern.addRule(rule2); + + multiLayoutPattern.start(); + } + + @Test + public void testEncodeForSpecificLogger() { + ILoggingEvent event1 = createLoggingEvent("com.example.app1", "Test message 1"); + byte[] encoded1 = multiLayoutPattern.encode(event1); + String result1 = new String(encoded1); + assertTrue(result1.contains("Test message 1")); + + ILoggingEvent event2 = createLoggingEvent("com.example.app2", "Test message 2"); + byte[] encoded2 = multiLayoutPattern.encode(event2); + String result2 = new String(encoded2); + assertEquals("Test message 2\n", result2); + } + + @Test + public void testEncodeForRootLogger() { + ILoggingEvent event = createLoggingEvent(Logger.ROOT_LOGGER_NAME, "Root logger message"); + byte[] encoded = multiLayoutPattern.encode(event); + String result = new String(encoded); + assertFalse(result.contains("Root logger message")); + } + + private ILoggingEvent createLoggingEvent(String loggerName, String message) { + Logger logger = (Logger) LoggerFactory.getLogger(loggerName); + return new LoggingEvent(loggerName, logger, Level.INFO, message, null, null); + } + +} diff --git a/framework/src/test/java/org/tron/common/ParameterTest.java b/framework/src/test/java/org/tron/common/ParameterTest.java new file mode 100644 index 00000000000..b16be405f61 --- /dev/null +++ b/framework/src/test/java/org/tron/common/ParameterTest.java @@ -0,0 +1,320 @@ +package org.tron.common; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.tron.common.parameter.RateLimiterInitialization.createHttpItem; +import static org.tron.common.parameter.RateLimiterInitialization.createRpcItem; +import static org.tron.core.Constant.ECKey_ENGINE; + +import com.google.common.collect.Lists; +import com.typesafe.config.ConfigFactory; +import com.typesafe.config.ConfigObject; +import java.util.ArrayList; +import java.util.HashSet; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.parameter.RateLimiterInitialization; +import org.tron.common.parameter.RateLimiterInitialization.HttpRateLimiterItem; +import org.tron.common.parameter.RateLimiterInitialization.RpcRateLimiterItem; +import org.tron.p2p.dns.update.PublishConfig; + +public class ParameterTest { + @Test + public void testConstructor_ValidConfig() { + String configStr = "{\"component\":\"testComponent\",\"strategy\":\"testStrategy\"," + + "\"paramString\":\"testParams\"}"; + ConfigObject config = ConfigFactory.parseString(configStr).root().toConfig().root(); + RpcRateLimiterItem item = new RpcRateLimiterItem(config); + HttpRateLimiterItem item1 = new HttpRateLimiterItem(config); + + assertEquals("testComponent", item.getComponent()); + assertEquals("testComponent", item1.getComponent()); + assertEquals("testStrategy", item.getStrategy()); + assertEquals("testParams", item.getParams()); + assertNull(createRpcItem(null)); + assertNull(createHttpItem(null)); + assertNotNull(createRpcItem(config)); + RateLimiterInitialization rateLimiterInitialization = new RateLimiterInitialization(); + rateLimiterInitialization.setRpcMap(Lists.newArrayList(item)); + assertFalse(rateLimiterInitialization.isHttpFlag()); + assertTrue(rateLimiterInitialization.isRpcFlag()); + } + + @Test + public void testCommonParameter() { + CommonParameter parameter = new CommonParameter(); + parameter.setWitness(false); + parameter.setSupportConstant(false); + parameter.setMaxEnergyLimitForConstant(1000000L); + parameter.setLruCacheSize(5); + parameter.setMinTimeRatio(0); + parameter.setMaxTimeRatio(20); + parameter.setSaveInternalTx(false); + parameter.setSaveFeaturedInternalTx(false); + parameter.setLongRunningTime(60); + parameter.setMaxHttpConnectNumber(5); + + assertEquals(StringUtils.EMPTY, parameter.getLogbackPath()); + assertEquals(1000000L, parameter.getMaxEnergyLimitForConstant()); + assertEquals(5, parameter.getLruCacheSize()); + assertEquals(60, parameter.getLongRunningTime()); + assertFalse(parameter.isHelp()); + assertFalse(parameter.isSaveFeaturedInternalTx()); + assertFalse(parameter.isSaveInternalTx()); + CollectionUtils.isEmpty(parameter.getSeedNodes()); + parameter.setChainId("123"); + assertEquals("123", parameter.getChainId()); + parameter.setNeedSyncCheck(false); + assertFalse(parameter.isNeedSyncCheck()); + parameter.setNodeDiscoveryEnable(false); + assertFalse(parameter.isNodeDiscoveryEnable()); + parameter.setNodeDiscoveryPersist(false); + assertFalse(parameter.isNodeDiscoveryPersist()); + parameter.setNodeEffectiveCheckEnable(false); + assertFalse(parameter.isNodeEffectiveCheckEnable()); + parameter.setNodeConnectionTimeout(500); + assertEquals(500, parameter.getNodeConnectionTimeout()); + parameter.setFetchBlockTimeout(500); + assertEquals(500, parameter.getFetchBlockTimeout()); + parameter.setNodeChannelReadTimeout(500); + assertEquals(500, parameter.getNodeChannelReadTimeout()); + parameter.setMaxConnections(500); + assertEquals(500, parameter.getMaxConnections()); + parameter.setMinConnections(500); + assertEquals(500, parameter.getMinConnections()); + parameter.setMinActiveConnections(500); + assertEquals(500, parameter.getMinActiveConnections()); + parameter.setMaxConnectionsWithSameIp(500); + assertEquals(500, parameter.getMaxConnectionsWithSameIp()); + parameter.setMaxTps(500); + assertEquals(500, parameter.getMaxTps()); + parameter.setMinParticipationRate(500); + assertEquals(500, parameter.getMinParticipationRate()); + parameter.setMaxConnectionsWithSameIp(500); + assertEquals(500, parameter.getMaxConnectionsWithSameIp()); + assertNull(parameter.getP2pConfig()); + parameter.setNodeLanIp("500"); + assertEquals("500", parameter.getNodeLanIp()); + parameter.setNodeP2pVersion(5); + assertEquals(5, parameter.getNodeP2pVersion()); + parameter.setNodeEnableIpv6(false); + assertFalse(parameter.isNodeEnableIpv6()); + parameter.setDnsTreeUrls(new ArrayList<>()); + assertTrue(CollectionUtils.isEmpty(parameter.getDnsTreeUrls())); + parameter.setDnsPublishConfig(new PublishConfig()); + parameter.setSyncFetchBatchNum(500); + assertEquals(500, parameter.getSyncFetchBatchNum()); + parameter.setDebug(false); + assertFalse(parameter.isDebug()); + parameter.setFullNodeHttpPort(80); + assertEquals(80, parameter.getFullNodeHttpPort()); + parameter.setSolidityHttpPort(80); + assertEquals(80, parameter.getSolidityHttpPort()); + parameter.setJsonRpcHttpFullNodePort(80); + assertEquals(80, parameter.getJsonRpcHttpFullNodePort()); + parameter.setJsonRpcHttpSolidityPort(80); + assertEquals(80, parameter.getJsonRpcHttpSolidityPort()); + parameter.setJsonRpcHttpPBFTPort(80); + assertEquals(80, parameter.getJsonRpcHttpPBFTPort()); + parameter.setRpcThreadNum(10); + assertEquals(10, parameter.getRpcThreadNum()); + parameter.setSolidityThreads(5); + assertEquals(5, parameter.getSolidityThreads()); + parameter.setMaxConcurrentCallsPerConnection(10); + assertEquals(10, parameter.getMaxConcurrentCallsPerConnection()); + parameter.setFlowControlWindow(20); + assertEquals(20, parameter.getFlowControlWindow()); + parameter.setMaxConnectionIdleInMillis(1000); + assertEquals(1000, parameter.getMaxConnectionIdleInMillis()); + parameter.setBlockProducedTimeOut(500); + assertEquals(500, parameter.getBlockProducedTimeOut()); + parameter.setNetMaxTrxPerSecond(15); + assertEquals(15, parameter.getNetMaxTrxPerSecond()); + parameter.setMaxConnectionAgeInMillis(1500); + assertEquals(1500, parameter.getMaxConnectionAgeInMillis()); + parameter.setMaxMessageSize(200); + assertEquals(200, parameter.getMaxMessageSize()); + parameter.setMaxHeaderListSize(100); + assertEquals(100, parameter.getMaxHeaderListSize()); + parameter.setRpcReflectionServiceEnable(false); + assertFalse(parameter.isRpcReflectionServiceEnable); + parameter.setValidateSignThreadNum(5); + assertEquals(5, parameter.getValidateSignThreadNum()); + parameter.setMaintenanceTimeInterval(200); + assertEquals(200, parameter.getMaintenanceTimeInterval()); + parameter.setProposalExpireTime(1000); + assertEquals(1000, parameter.getProposalExpireTime()); + parameter.setAllowCreationOfContracts(1); + assertEquals(1, parameter.getAllowCreationOfContracts()); + parameter.setAllowAdaptiveEnergy(1); + assertEquals(1, parameter.getAllowAdaptiveEnergy()); + parameter.setAllowDelegateResource(1); + assertEquals(1, parameter.getAllowDelegateResource()); + parameter.setAllowSameTokenName(1); + assertEquals(1, parameter.getAllowSameTokenName()); + parameter.setAllowTvmTransferTrc10(1); + assertEquals(1, parameter.getAllowTvmTransferTrc10()); + parameter.setAllowTvmConstantinople(1); + assertEquals(1, parameter.getAllowTvmConstantinople()); + parameter.setAllowTvmSolidity059(1); + assertEquals(1, parameter.getAllowTvmSolidity059()); + parameter.setForbidTransferToContract(1); + assertEquals(1, parameter.getForbidTransferToContract()); + parameter.setTcpNettyWorkThreadNum(5); + assertEquals(5, parameter.getTcpNettyWorkThreadNum()); + parameter.setUdpNettyWorkThreadNum(5); + assertEquals(5, parameter.getUdpNettyWorkThreadNum()); + parameter.setTrustNodeAddr("address"); + assertEquals("address", parameter.getTrustNodeAddr()); + parameter.setWalletExtensionApi(false); + assertFalse(parameter.isWalletExtensionApi()); + parameter.setEstimateEnergy(false); + assertFalse(parameter.isEstimateEnergy()); + parameter.setEstimateEnergyMaxRetry(2); + assertEquals(2, parameter.getEstimateEnergyMaxRetry()); + parameter.setKeepAliveInterval(1000); + assertEquals(1000, parameter.getKeepAliveInterval()); + parameter.setReceiveTcpMinDataLength(10); + assertEquals(10, parameter.getReceiveTcpMinDataLength()); + parameter.setOpenFullTcpDisconnect(false); + assertFalse(parameter.isOpenFullTcpDisconnect()); + parameter.setNodeDetectEnable(false); + assertFalse(parameter.isNodeDetectEnable()); + parameter.setAllowMultiSign(1); + assertEquals(1, parameter.getAllowMultiSign()); + parameter.setVmTrace(false); + assertFalse(parameter.isVmTrace()); + parameter.setNeedToUpdateAsset(false); + assertFalse(parameter.isNeedToUpdateAsset()); + parameter.setTrxReferenceBlock("test"); + assertEquals("test", parameter.getTrxReferenceBlock()); + parameter.setTrxCacheEnable(false); + assertFalse(parameter.isTrxCacheEnable()); + parameter.setAllowMarketTransaction(1); + assertEquals(1, parameter.getAllowMarketTransaction()); + parameter.setAllowTransactionFeePool(1); + assertEquals(1, parameter.getAllowTransactionFeePool()); + parameter.setAllowBlackHoleOptimization(1); + assertEquals(1, parameter.getAllowBlackHoleOptimization()); + parameter.setAllowNewResourceModel(1); + assertEquals(1, parameter.getAllowNewResourceModel()); + parameter.setEventSubscribe(false); + assertFalse(parameter.isEventSubscribe()); + parameter.setTrxExpirationTimeInMilliseconds(100); + assertEquals(100, parameter.getTrxExpirationTimeInMilliseconds()); + parameter.setAllowProtoFilterNum(10); + assertEquals(10, parameter.getAllowProtoFilterNum()); + parameter.setShieldedTransInPendingMaxCounts(1); + assertEquals(1, parameter.getShieldedTransInPendingMaxCounts()); + parameter.setChangedDelegation(1); + assertEquals(1, parameter.getChangedDelegation()); + parameter.setActuatorSet(new HashSet<>()); + assertTrue(CollectionUtils.isEmpty(parameter.getActuatorSet())); + parameter.setRateLimiterInitialization(new RateLimiterInitialization()); + assertNotNull(parameter.getRateLimiterInitialization()); + parameter.setRateLimiterGlobalQps(1000); + assertEquals(1000, parameter.getRateLimiterGlobalQps()); + parameter.setRateLimiterGlobalIpQps(100); + assertEquals(100, parameter.getRateLimiterGlobalIpQps()); + assertNull(parameter.getOverlay()); + assertNull(parameter.getEventPluginConfig()); + assertNull(parameter.getEventFilter()); + parameter.setCryptoEngine(ECKey_ENGINE); + assertEquals(ECKey_ENGINE, parameter.getCryptoEngine()); + parameter.setFullNodeHttpEnable(false); + assertFalse(parameter.isFullNodeHttpEnable()); + parameter.setSolidityNodeHttpEnable(false); + assertFalse(parameter.isSolidityNodeHttpEnable()); + parameter.setMaxTransactionPendingSize(500); + assertEquals(500, parameter.getMaxTransactionPendingSize()); + parameter.setPendingTransactionTimeout(500); + assertEquals(500, parameter.getPendingTransactionTimeout()); + parameter.setNodeMetricsEnable(false); + assertFalse(parameter.isNodeMetricsEnable()); + parameter.setMetricsStorageEnable(false); + assertFalse(parameter.isMetricsStorageEnable()); + parameter.setInfluxDbIp("127.0.0.1"); + assertEquals("127.0.0.1", parameter.getInfluxDbIp()); + parameter.setInfluxDbPort(90); + assertEquals(90, parameter.getInfluxDbPort()); + parameter.setInfluxDbDatabase("InfluxDb"); + assertEquals("InfluxDb", parameter.getInfluxDbDatabase()); + parameter.setMetricsReportInterval(100); + assertEquals(100, parameter.getMetricsReportInterval()); + parameter.setMetricsPrometheusPort(3000); + assertEquals(3000, parameter.getMetricsPrometheusPort()); + parameter.setAgreeNodeCount(10); + assertEquals(10, parameter.getAgreeNodeCount()); + parameter.setAllowPBFT(1); + assertEquals(1, parameter.getAllowPBFT()); + parameter.setPBFTHttpPort(70); + assertEquals(70, parameter.getPBFTHttpPort()); + parameter.setPBFTExpireNum(100); + assertEquals(100, parameter.getPBFTExpireNum()); + parameter.setAllowShieldedTRC20Transaction(10); + assertEquals(10, parameter.getAllowShieldedTRC20Transaction()); + parameter.setAllowTvmIstanbul(1); + assertEquals(1, parameter.getAllowTvmIstanbul()); + parameter.setAllowTvmVote(1); + assertEquals(1, parameter.getAllowTvmVote()); + parameter.setAllowTvmLondon(1); + assertEquals(1, parameter.getAllowTvmLondon()); + parameter.setAllowTvmCompatibleEvm(1); + assertEquals(1, parameter.getAllowTvmCompatibleEvm()); + parameter.setAllowHigherLimitForMaxCpuTimeOfOneTx(1); + assertEquals(1, parameter.getAllowHigherLimitForMaxCpuTimeOfOneTx()); + parameter.setHistoryBalanceLookup(false); + assertFalse(parameter.isHistoryBalanceLookup()); + parameter.setOpenPrintLog(false); + assertFalse(parameter.isOpenPrintLog()); + parameter.setOpenTransactionSort(false); + assertFalse(parameter.isOpenTransactionSort()); + parameter.setAllowAssetOptimization(1); + assertEquals(1, parameter.getAllowAssetOptimization()); + parameter.setAllowAccountAssetOptimization(1); + assertEquals(1, parameter.getAllowAccountAssetOptimization()); + parameter.setBlockCacheTimeout(60); + assertEquals(60, parameter.getBlockCacheTimeout()); + parameter.setAllowNewReward(1); + assertEquals(1, parameter.getAllowNewReward()); + parameter.setAllowNewRewardAlgorithm(1); + assertEquals(1, parameter.getAllowNewRewardAlgorithm()); + parameter.setMemoFee(100); + assertEquals(100, parameter.getMemoFee()); + parameter.setAllowDelegateOptimization(1); + assertEquals(1, parameter.getAllowDelegateOptimization()); + parameter.setUnfreezeDelayDays(10); + assertEquals(10, parameter.getUnfreezeDelayDays()); + parameter.setAllowOptimizedReturnValueOfChainId(1); + assertEquals(1, parameter.getAllowOptimizedReturnValueOfChainId()); + parameter.setAllowDynamicEnergy(1); + assertEquals(1, parameter.getAllowDynamicEnergy()); + parameter.setDynamicEnergyThreshold(1); + assertEquals(1, parameter.getDynamicEnergyThreshold()); + parameter.setDynamicEnergyIncreaseFactor(1); + assertEquals(1, parameter.getDynamicEnergyIncreaseFactor()); + parameter.setDynamicEnergyMaxFactor(1); + assertEquals(1, parameter.getDynamicEnergyMaxFactor()); + parameter.setDynamicConfigEnable(false); + assertFalse(parameter.isDynamicConfigEnable()); + parameter.setDynamicConfigCheckInterval(10); + assertEquals(10, parameter.getDynamicConfigCheckInterval()); + parameter.setAllowTvmShangHai(1); + assertEquals(1, parameter.getAllowTvmShangHai()); + parameter.setAllowCancelAllUnfreezeV2(1); + assertEquals(1, parameter.getAllowCancelAllUnfreezeV2()); + parameter.setMaxUnsolidifiedBlocks(100); + assertEquals(100, parameter.getMaxUnsolidifiedBlocks()); + parameter.setAllowOldRewardOpt(1); + assertEquals(1, parameter.getAllowOldRewardOpt()); + parameter.setAllowEnergyAdjustment(1); + assertEquals(1, parameter.getAllowEnergyAdjustment()); + parameter.setMaxCreateAccountTxSize(1000); + assertEquals(1000, parameter.getMaxCreateAccountTxSize()); + } +} diff --git a/framework/src/test/java/org/tron/common/cache/TronCacheTest.java b/framework/src/test/java/org/tron/common/cache/TronCacheTest.java new file mode 100644 index 00000000000..422bd1de881 --- /dev/null +++ b/framework/src/test/java/org/tron/common/cache/TronCacheTest.java @@ -0,0 +1,100 @@ +package org.tron.common.cache; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; +import static org.tron.common.cache.CacheManager.allocate; +import static org.tron.common.cache.CacheStrategies.CACHE_STRATEGY_DEFAULT; +import static org.tron.common.cache.CacheType.findByType; +import static org.tron.common.cache.CacheType.witness; +import static org.tron.common.cache.CacheType.witnessStandby; + +import com.google.common.cache.CacheLoader; +import java.util.concurrent.ExecutionException; +import javax.annotation.ParametersAreNonnullByDefault; +import lombok.extern.slf4j.Slf4j; +import org.junit.Before; +import org.junit.Test; + +@Slf4j +public class TronCacheTest { + + private TronCache cacheWithLoader; + private TronCache cacheWithoutLoader; + CacheLoader loader = new CacheLoader() { + @Override + @ParametersAreNonnullByDefault + public String load(String key) { + return "Loaded: " + key; + } + }; + + @Before + public void setUp() { + + cacheWithLoader = new TronCache<>(witness, CACHE_STRATEGY_DEFAULT, loader); + + cacheWithoutLoader = new TronCache<>(witnessStandby, CACHE_STRATEGY_DEFAULT); + } + + @Test + public void testGetIfPresent() { + cacheWithoutLoader.put("key1", "value1"); + assertEquals("value1", cacheWithoutLoader.getIfPresent("key1")); + assertNull(cacheWithoutLoader.getIfPresent("key2")); + } + + @Test + public void testGetWithLoader() throws ExecutionException { + String value = cacheWithLoader.get("key1", () -> "Fallback value"); + assertEquals("Fallback value", value); + } + + @Test + public void testPutAndGet() { + cacheWithoutLoader.put("key2", "value2"); + assertEquals("value2", cacheWithoutLoader.getIfPresent("key2")); + assertEquals(witnessStandby, cacheWithoutLoader.getName()); + logger.info("hash code: {}", cacheWithoutLoader.hashCode()); + } + + @Test + public void testStats() { + cacheWithoutLoader.put("key3", "value3"); + assertNotNull(cacheWithoutLoader.stats()); + assertEquals(0, cacheWithoutLoader.stats().hitCount()); + cacheWithoutLoader.getIfPresent("key3"); + assertTrue(cacheWithoutLoader.stats().hitCount() > 0); + } + + @Test + public void testInvalidateAll() { + cacheWithoutLoader.put("key4", "value4"); + assertEquals("value4", cacheWithoutLoader.getIfPresent("key4")); + cacheWithoutLoader.invalidateAll(); + assertNull(cacheWithoutLoader.getIfPresent("key4")); + } + + @Test + public void testEquals() { + TronCache tmpCache = cacheWithoutLoader; + assertEquals(cacheWithoutLoader, tmpCache); + assertNotEquals(cacheWithoutLoader, new Object()); + assertNotEquals(cacheWithoutLoader, cacheWithLoader); + tmpCache = new TronCache<>(witnessStandby, CACHE_STRATEGY_DEFAULT); + assertEquals(cacheWithoutLoader, tmpCache); + } + + @Test + public void testCacheManager() { + TronCache allocate = allocate(witness, CACHE_STRATEGY_DEFAULT); + TronCache allocate1 = allocate(witness, CACHE_STRATEGY_DEFAULT, loader); + assertNotNull(allocate); + assertNotNull(allocate1); + assertThrows(IllegalArgumentException.class, () -> findByType("test")); + } + +} diff --git a/framework/src/test/java/org/tron/common/logsfilter/EventLoaderTest.java b/framework/src/test/java/org/tron/common/logsfilter/EventLoaderTest.java index 8ff8167f52e..1e5268ddeb6 100644 --- a/framework/src/test/java/org/tron/common/logsfilter/EventLoaderTest.java +++ b/framework/src/test/java/org/tron/common/logsfilter/EventLoaderTest.java @@ -1,5 +1,9 @@ package org.tron.common.logsfilter; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + import java.util.ArrayList; import java.util.List; import org.junit.Assert; @@ -15,18 +19,31 @@ public void launchNativeQueue() { config.setSendQueueLength(1000); config.setBindPort(5555); config.setUseNativeQueue(true); + config.setPluginPath("pluginPath"); + config.setServerAddress("serverAddress"); + config.setDbConfig("dbConfig"); + assertEquals("pluginPath", config.getPluginPath()); + assertEquals("serverAddress", config.getServerAddress()); + assertEquals("dbConfig", config.getDbConfig()); List triggerConfigList = new ArrayList<>(); - TriggerConfig blockTriggerConfig = new TriggerConfig(); - blockTriggerConfig.setTriggerName("block"); - blockTriggerConfig.setEnabled(true); - blockTriggerConfig.setTopic("block"); - triggerConfigList.add(blockTriggerConfig); + TriggerConfig triggerConfig = new TriggerConfig(); + triggerConfig.setTriggerName("block"); + triggerConfig.setEnabled(true); + triggerConfig.setTopic("topic"); + triggerConfig.setRedundancy(false); + triggerConfig.setEthCompatible(false); + triggerConfig.setSolidified(false); + assertFalse(triggerConfig.isRedundancy()); + assertFalse(triggerConfig.isEthCompatible()); + assertFalse(triggerConfig.isSolidified()); + assertEquals("topic", triggerConfig.getTopic()); + triggerConfigList.add(triggerConfig); config.setTriggerConfigList(triggerConfigList); - Assert.assertTrue(EventPluginLoader.getInstance().start(config)); + assertTrue(EventPluginLoader.getInstance().start(config)); EventPluginLoader.getInstance().stopPlugin(); } diff --git a/framework/src/test/java/org/tron/common/logsfilter/FilterQueryTest.java b/framework/src/test/java/org/tron/common/logsfilter/FilterQueryTest.java index 601cf72b294..5ee32d98ee6 100644 --- a/framework/src/test/java/org/tron/common/logsfilter/FilterQueryTest.java +++ b/framework/src/test/java/org/tron/common/logsfilter/FilterQueryTest.java @@ -1,6 +1,13 @@ package org.tron.common.logsfilter; +import static org.apache.commons.lang3.StringUtils.EMPTY; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; import static org.tron.common.logsfilter.EventPluginLoader.matchFilter; +import static org.tron.common.logsfilter.FilterQuery.EARLIEST_BLOCK_NUM; +import static org.tron.common.logsfilter.FilterQuery.LATEST_BLOCK_NUM; import static org.tron.common.logsfilter.FilterQuery.parseFromBlockNumber; import static org.tron.common.logsfilter.FilterQuery.parseToBlockNumber; @@ -9,54 +16,57 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import lombok.extern.slf4j.Slf4j; import org.junit.Assert; import org.junit.Test; import org.tron.common.logsfilter.capsule.ContractEventTriggerCapsule; +import org.tron.common.logsfilter.capsule.FilterTriggerCapsule; +import org.tron.common.logsfilter.capsule.TriggerCapsule; import org.tron.common.runtime.LogEventWrapper; import org.tron.protos.contract.SmartContractOuterClass.SmartContract.ABI.Entry; +@Slf4j public class FilterQueryTest { @Test public synchronized void testParseFilterQueryBlockNumber() { - { - String blockNum = ""; - Assert.assertEquals(FilterQuery.LATEST_BLOCK_NUM, parseToBlockNumber(blockNum)); - } + assertEquals(LATEST_BLOCK_NUM, parseToBlockNumber(EMPTY)); + assertEquals(13245, parseToBlockNumber("13245")); - { - String blockNum = "earliest"; - Assert.assertEquals(FilterQuery.EARLIEST_BLOCK_NUM, parseFromBlockNumber(blockNum)); - } + assertEquals(EARLIEST_BLOCK_NUM, parseFromBlockNumber("earliest")); + assertEquals(13245, parseFromBlockNumber("13245")); + assertThrows(Exception.class, () -> parseFromBlockNumber("test")); + assertThrows(Exception.class, () -> parseToBlockNumber("test")); - { - String blockNum = "13245"; - Assert.assertEquals(13245, parseToBlockNumber(blockNum)); - } } @Test public synchronized void testMatchFilter() { - String[] addrList = {"address1", "address2"}; + String[] adrList = {"address1", "address2"}; String[] topList = {"top1", "top2"}; - Map topMap = new HashMap(); + Map topMap = new HashMap<>(); List addressList = new ArrayList<>(); - addressList.add(addrList[0].getBytes()); - addressList.add(addrList[1].getBytes()); + addressList.add(adrList[0].getBytes()); + addressList.add(adrList[1].getBytes()); topMap.put("1", topList[0]); topMap.put("2", topList[1]); LogEventWrapper event = new LogEventWrapper(); - ((LogEventWrapper) event).setTopicList(addressList); - ((LogEventWrapper) event).setData(new byte[]{}); - ((LogEventWrapper) event).setEventSignature(""); - ((LogEventWrapper) event).setAbiEntry(Entry.newBuilder().setName("testABI").build()); - event.setBlockNumber(new Long(123)); + event.setTopicList(addressList); + event.setData(new byte[]{}); + event.setEventSignature(""); + event.setAbiEntry(Entry.newBuilder().setName("testABI").build()); + event.setBlockNumber(123L); ContractEventTriggerCapsule capsule = new ContractEventTriggerCapsule(event); + capsule.setContractEventTrigger(capsule.getContractEventTrigger()); capsule.getContractEventTrigger().setContractAddress("address1"); + capsule.setLatestSolidifiedBlockNumber(0L); + capsule.setData(capsule.getData()); + capsule.setTopicList(capsule.getTopicList()); + capsule.setAbiEntry(capsule.getAbiEntry()); capsule.getContractEventTrigger().setTopicMap(topMap); { - Assert.assertEquals(true, matchFilter(capsule.getContractEventTrigger())); + Assert.assertTrue(matchFilter(capsule.getContractEventTrigger())); } { @@ -64,7 +74,7 @@ public synchronized void testMatchFilter() { filterQuery.setFromBlock(1); filterQuery.setToBlock(100); EventPluginLoader.getInstance().setFilterQuery(filterQuery); - Assert.assertEquals(false, matchFilter(capsule.getContractEventTrigger())); + Assert.assertFalse(matchFilter(capsule.getContractEventTrigger())); } { @@ -72,17 +82,33 @@ public synchronized void testMatchFilter() { filterQuery.setFromBlock(133); filterQuery.setToBlock(190); EventPluginLoader.getInstance().setFilterQuery(filterQuery); - Assert.assertEquals(false, matchFilter(capsule.getContractEventTrigger())); + Assert.assertFalse(matchFilter(capsule.getContractEventTrigger())); } { FilterQuery filterQuery = new FilterQuery(); filterQuery.setFromBlock(100); filterQuery.setToBlock(190); - filterQuery.setContractAddressList(Arrays.asList(addrList)); + filterQuery.setContractAddressList(Arrays.asList(adrList)); filterQuery.setContractTopicList(Arrays.asList(topList)); EventPluginLoader.getInstance().setFilterQuery(filterQuery); - Assert.assertEquals(true, matchFilter(capsule.getContractEventTrigger())); + Assert.assertTrue(matchFilter(capsule.getContractEventTrigger())); + capsule.processTrigger(); + assertNotNull(filterQuery.toString()); + } + + FilterTriggerCapsule filterTriggerCapsule = new FilterTriggerCapsule(); + try { + filterTriggerCapsule.processFilterTrigger(); + } catch (Exception e) { + logger.info(e.getMessage()); + } + + TriggerCapsule triggerCapsule = new TriggerCapsule(); + try { + triggerCapsule.processTrigger(); + } catch (Exception e) { + assertTrue(e instanceof UnsupportedOperationException); } } } diff --git a/framework/src/test/java/org/tron/common/logsfilter/capsule/BlockFilterCapsuleTest.java b/framework/src/test/java/org/tron/common/logsfilter/capsule/BlockFilterCapsuleTest.java new file mode 100644 index 00000000000..5381c6ab2de --- /dev/null +++ b/framework/src/test/java/org/tron/common/logsfilter/capsule/BlockFilterCapsuleTest.java @@ -0,0 +1,38 @@ +package org.tron.common.logsfilter.capsule; + +import com.google.protobuf.ByteString; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.BlockCapsule; + +public class BlockFilterCapsuleTest { + + private BlockFilterCapsule blockFilterCapsule; + + @Before + public void setUp() { + BlockCapsule blockCapsule = new BlockCapsule(1, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), ByteString.EMPTY); + blockFilterCapsule = new BlockFilterCapsule(blockCapsule, false); + } + + @Test + public void testSetAndGetBlockHash() { + blockFilterCapsule + .setBlockHash("e58f33f9baf9305dc6f82b9f1934ea8f0ade2defb951258d50167028c780351f"); + System.out.println(blockFilterCapsule); + Assert.assertEquals("e58f33f9baf9305dc6f82b9f1934ea8f0ade2defb951258d50167028c780351f", + blockFilterCapsule.getBlockHash()); + } + + @Test + public void testSetAndIsSolidified() { + blockFilterCapsule = new BlockFilterCapsule( + "e58f33f9baf9305dc6f82b9f1934ea8f0ade2defb951258d50167028c780351f", false); + blockFilterCapsule.setSolidified(true); + blockFilterCapsule.processFilterTrigger(); + Assert.assertTrue(blockFilterCapsule.isSolidified()); + } +} diff --git a/framework/src/test/java/org/tron/common/logsfilter/capsule/BlockLogTriggerCapsuleTest.java b/framework/src/test/java/org/tron/common/logsfilter/capsule/BlockLogTriggerCapsuleTest.java new file mode 100644 index 00000000000..f77869b8650 --- /dev/null +++ b/framework/src/test/java/org/tron/common/logsfilter/capsule/BlockLogTriggerCapsuleTest.java @@ -0,0 +1,35 @@ +package org.tron.common.logsfilter.capsule; + +import com.google.protobuf.ByteString; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.BlockCapsule; + +public class BlockLogTriggerCapsuleTest { + + private BlockLogTriggerCapsule blockLogTriggerCapsule; + + @Before + public void setUp() { + BlockCapsule blockCapsule = new BlockCapsule(1, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), ByteString.EMPTY); + blockLogTriggerCapsule = new BlockLogTriggerCapsule(blockCapsule); + } + + @Test + public void testSetAndGetBlockLogTrigger() { + blockLogTriggerCapsule + .setBlockLogTrigger(blockLogTriggerCapsule.getBlockLogTrigger()); + Assert.assertEquals(1, + blockLogTriggerCapsule.getBlockLogTrigger().getBlockNumber()); + } + + @Test + public void testSetLatestSolidifiedBlockNumber() { + blockLogTriggerCapsule.setLatestSolidifiedBlockNumber(100); + Assert.assertEquals(100, + blockLogTriggerCapsule.getBlockLogTrigger().getLatestSolidifiedBlockNumber()); + } +} diff --git a/framework/src/test/java/org/tron/common/logsfilter/capsule/ContractLogTriggerCapsuleTest.java b/framework/src/test/java/org/tron/common/logsfilter/capsule/ContractLogTriggerCapsuleTest.java new file mode 100644 index 00000000000..3d45eb026ea --- /dev/null +++ b/framework/src/test/java/org/tron/common/logsfilter/capsule/ContractLogTriggerCapsuleTest.java @@ -0,0 +1,36 @@ +package org.tron.common.logsfilter.capsule; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.tron.common.logsfilter.trigger.Trigger.CONTRACTLOG_TRIGGER_NAME; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.logsfilter.trigger.ContractLogTrigger; + +@Slf4j +public class ContractLogTriggerCapsuleTest { + + private ContractLogTriggerCapsule capsule; + + @Before + public void setUp() { + ContractLogTrigger contractLogTrigger = new ContractLogTrigger(); + contractLogTrigger.setBlockNumber(0L); + capsule = new ContractLogTriggerCapsule(contractLogTrigger); + capsule.setLatestSolidifiedBlockNumber(0); + } + + @Test + public void testSetAndGetContractLogTrigger() { + capsule.setContractLogTrigger(capsule.getContractLogTrigger()); + assertEquals(CONTRACTLOG_TRIGGER_NAME, capsule.getContractLogTrigger().getTriggerName()); + try { + capsule.processTrigger(); + } catch (Exception e) { + assertTrue(e instanceof NullPointerException); + } + } + +} diff --git a/framework/src/test/java/org/tron/common/logsfilter/capsule/ContractTriggerCapsuleTest.java b/framework/src/test/java/org/tron/common/logsfilter/capsule/ContractTriggerCapsuleTest.java new file mode 100644 index 00000000000..898447b3a75 --- /dev/null +++ b/framework/src/test/java/org/tron/common/logsfilter/capsule/ContractTriggerCapsuleTest.java @@ -0,0 +1,70 @@ +package org.tron.common.logsfilter.capsule; + +import static com.google.common.collect.Lists.newArrayList; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import com.beust.jcommander.internal.Lists; +import java.util.ArrayList; +import java.util.Arrays; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ArrayUtils; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.logsfilter.trigger.ContractTrigger; +import org.tron.common.runtime.vm.DataWord; +import org.tron.common.runtime.vm.LogInfo; + +@Slf4j +public class ContractTriggerCapsuleTest { + + private ContractTriggerCapsule capsule; + + private LogInfo logInfo; + + @Before + public void setUp() { + ContractTrigger contractTrigger = new ContractTrigger(); + contractTrigger.setBlockNumber(0L); + contractTrigger.setRemoved(false); + logInfo = new LogInfo(bytesToAddress(new byte[] {0x11}), + newArrayList(new DataWord()), new byte[0]); + contractTrigger.setLogInfo(logInfo); + contractTrigger.setRawData(new RawData(null, null, null)); + contractTrigger.setAbi(contractTrigger.getAbi()); + capsule = new ContractTriggerCapsule(contractTrigger); + + } + + private byte[] bytesToAddress(byte[] address) { + byte[] data = new byte[20]; + System.arraycopy(address, 0, data, 20 - address.length, address.length); + return data; + } + + @Test + public void testSetAndGetContractTrigger() { + capsule.setContractTrigger(capsule.getContractTrigger()); + capsule.setBlockHash("e58f33f9baf9305dc6f82b9f1934ea8f0ade2defb951258d50167028c780351f"); + capsule.setLatestSolidifiedBlockNumber(0); + assertEquals(0, capsule.getContractTrigger().getLatestSolidifiedBlockNumber()); + assertEquals("e58f33f9baf9305dc6f82b9f1934ea8f0ade2defb951258d50167028c780351f", + capsule.getContractTrigger().getBlockHash()); + try { + capsule.processTrigger(); + } catch (Exception e) { + assertTrue(e instanceof NullPointerException); + } + } + + @Test + public void testLogInfo() { + logger.info("log info to string: {}, ", logInfo.toString()); + logger.info("log clone data: {}, ", logInfo.getClonedData()); + CollectionUtils.isNotEmpty(logInfo.getClonedTopics()); + CollectionUtils.isNotEmpty(logInfo.getHexTopics()); + new LogInfo(null, null, null); + } + +} diff --git a/framework/src/test/java/org/tron/common/logsfilter/capsule/LogsFilterCapsuleTest.java b/framework/src/test/java/org/tron/common/logsfilter/capsule/LogsFilterCapsuleTest.java new file mode 100644 index 00000000000..691a3106b49 --- /dev/null +++ b/framework/src/test/java/org/tron/common/logsfilter/capsule/LogsFilterCapsuleTest.java @@ -0,0 +1,33 @@ +package org.tron.common.logsfilter.capsule; + +import static org.junit.Assert.assertNotNull; + +import java.util.ArrayList; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.bloom.Bloom; + +public class LogsFilterCapsuleTest { + + private LogsFilterCapsule capsule; + + @Before + public void setUp() { + capsule = new LogsFilterCapsule(0, + "e58f33f9baf9305dc6f82b9f1934ea8f0ade2defb951258d50167028c780351f", + new Bloom(), new ArrayList<>(), true, false); + } + + @Test + public void testSetAndGetLogsFilterCapsule() { + capsule.setBlockNumber(capsule.getBlockNumber()); + capsule.setBlockHash(capsule.getBlockHash()); + capsule.setSolidified(capsule.isSolidified()); + capsule.setBloom(capsule.getBloom()); + capsule.setRemoved(capsule.isRemoved()); + capsule.setTxInfoList(capsule.getTxInfoList()); + assertNotNull(capsule.toString()); + capsule.processFilterTrigger(); + } + +} diff --git a/framework/src/test/java/org/tron/common/logsfilter/capsule/RawDataTest.java b/framework/src/test/java/org/tron/common/logsfilter/capsule/RawDataTest.java new file mode 100644 index 00000000000..c14afcd903b --- /dev/null +++ b/framework/src/test/java/org/tron/common/logsfilter/capsule/RawDataTest.java @@ -0,0 +1,33 @@ +package org.tron.common.logsfilter.capsule; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.List; +import org.junit.Test; +import org.tron.common.runtime.vm.DataWord; + +public class RawDataTest { + @Test + public void testRawDataConstructor() { + byte[] addressBytes = {0x01, 0x02, 0x03, 0x04}; + byte[] dataBytes = {0x10, 0x20, 0x30, 0x40}; + List topics = Arrays.asList( + new DataWord("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + new DataWord("0000000000000000000000000000000000000000000000000000000000000001")); + + RawData rawData = new RawData(addressBytes, topics, dataBytes); + + assertEquals("01020304", rawData.getAddress()); + assertEquals(topics, rawData.getTopics()); + assertEquals("10203040", rawData.getData()); + + rawData = new RawData(null, null, null); + assertEquals("", rawData.getAddress()); + assertTrue(rawData.getTopics().isEmpty()); + assertEquals("", rawData.getData()); + assertNotNull(rawData.toString()); + } +} diff --git a/framework/src/test/java/org/tron/common/logsfilter/capsule/SolidityEventCapsuleTest.java b/framework/src/test/java/org/tron/common/logsfilter/capsule/SolidityEventCapsuleTest.java new file mode 100644 index 00000000000..9259ca3ea97 --- /dev/null +++ b/framework/src/test/java/org/tron/common/logsfilter/capsule/SolidityEventCapsuleTest.java @@ -0,0 +1,32 @@ +package org.tron.common.logsfilter.capsule; + +import static org.junit.Assert.assertTrue; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.logsfilter.trigger.ContractEventTrigger; + +@Slf4j +public class SolidityEventCapsuleTest { + + private SolidityEventCapsule capsule; + + @Before + public void setUp() { + ContractEventTrigger contractEventTrigger = new ContractEventTrigger(); + capsule = new SolidityEventCapsule(contractEventTrigger); + } + + @Test + public void testSetAndGetSolidityEventCapsule() { + capsule.setSolidityEventTrigger(capsule.getSolidityEventTrigger()); + try { + capsule.processTrigger(); + } catch (Exception e) { + assertTrue(e instanceof NullPointerException); + } + } + +} diff --git a/framework/src/test/java/org/tron/common/logsfilter/capsule/SolidityLogCapsuleTest.java b/framework/src/test/java/org/tron/common/logsfilter/capsule/SolidityLogCapsuleTest.java new file mode 100644 index 00000000000..4e663930530 --- /dev/null +++ b/framework/src/test/java/org/tron/common/logsfilter/capsule/SolidityLogCapsuleTest.java @@ -0,0 +1,31 @@ +package org.tron.common.logsfilter.capsule; + +import static org.junit.Assert.assertTrue; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.logsfilter.trigger.ContractLogTrigger; + +@Slf4j +public class SolidityLogCapsuleTest { + + private SolidityLogCapsule capsule; + + @Before + public void setUp() { + ContractLogTrigger trigger = new ContractLogTrigger(); + capsule = new SolidityLogCapsule(trigger); + } + + @Test + public void testSetAndGetSolidityLogCapsule() { + capsule.setSolidityLogTrigger(capsule.getSolidityLogTrigger()); + try { + capsule.processTrigger(); + } catch (Exception e) { + assertTrue(e instanceof NullPointerException); + } + } + +} diff --git a/framework/src/test/java/org/tron/common/logsfilter/capsule/SolidityTriggerCapsuleTest.java b/framework/src/test/java/org/tron/common/logsfilter/capsule/SolidityTriggerCapsuleTest.java new file mode 100644 index 00000000000..849803c1f04 --- /dev/null +++ b/framework/src/test/java/org/tron/common/logsfilter/capsule/SolidityTriggerCapsuleTest.java @@ -0,0 +1,37 @@ +package org.tron.common.logsfilter.capsule; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.logsfilter.trigger.SolidityTrigger; + +@Slf4j +public class SolidityTriggerCapsuleTest { + + private SolidityTriggerCapsule capsule; + + @Before + public void setUp() { + capsule = new SolidityTriggerCapsule(0); + SolidityTrigger trigger = new SolidityTrigger(); + assertNotNull(trigger.toString()); + capsule.setSolidityTrigger(trigger); + capsule.setTimeStamp(System.currentTimeMillis()); + } + + @Test + public void testSetAndGetSolidityLogCapsule() { + capsule.setSolidityTrigger(capsule.getSolidityTrigger()); + capsule.setTimeStamp(capsule.getSolidityTrigger().getTimeStamp()); + try { + capsule.processTrigger(); + } catch (Exception e) { + assertTrue(e instanceof NullPointerException); + } + } + +} diff --git a/framework/src/test/java/org/tron/common/logsfilter/trigger/ContractLogTriggerTest.java b/framework/src/test/java/org/tron/common/logsfilter/trigger/ContractLogTriggerTest.java new file mode 100644 index 00000000000..8d6e044c134 --- /dev/null +++ b/framework/src/test/java/org/tron/common/logsfilter/trigger/ContractLogTriggerTest.java @@ -0,0 +1,82 @@ +package org.tron.common.logsfilter.trigger; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.Arrays; +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.logsfilter.capsule.RawData; +import org.tron.common.runtime.vm.DataWord; + +public class ContractLogTriggerTest { + private ContractEventTrigger mockEventTrigger; + + @Before + public void setUp() { + mockEventTrigger = new ContractEventTrigger(); + byte[] addressBytes = {0x01, 0x02, 0x03, 0x04}; + byte[] dataBytes = {0x10, 0x20, 0x30, 0x40}; + List topics = Arrays.asList( + new DataWord("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + new DataWord("0000000000000000000000000000000000000000000000000000000000000001")); + + RawData rawData = new RawData(addressBytes, topics, dataBytes); + mockEventTrigger.setRawData(rawData); + mockEventTrigger.setLatestSolidifiedBlockNumber(12345L); + mockEventTrigger.setRemoved(false); + mockEventTrigger.setUniqueId("unique-id"); + mockEventTrigger.setTransactionId("tx-id"); + mockEventTrigger.setContractAddress("contract-addr"); + mockEventTrigger.setOriginAddress("origin-addr"); + mockEventTrigger.setCreatorAddress("creator-addr"); + mockEventTrigger.setBlockNumber(67890L); + mockEventTrigger.setTimeStamp(1622547200L); + mockEventTrigger.setBlockHash("block-hash"); + } + + @Test + public void testDefaultConstructor() { + ContractLogTrigger trigger = new ContractLogTrigger(); + assertEquals(Trigger.CONTRACTLOG_TRIGGER_NAME, trigger.getTriggerName()); + assertNull(trigger.getTopicList()); + assertNull(trigger.getData()); + } + + @Test + public void testConstructorWithEventTrigger() { + ContractLogTrigger trigger = new ContractLogTrigger(mockEventTrigger); + assertEquals(Trigger.CONTRACTLOG_TRIGGER_NAME, trigger.getTriggerName()); + assertEquals(mockEventTrigger.getRawData(), trigger.getRawData()); + assertEquals(mockEventTrigger.getLatestSolidifiedBlockNumber(), + trigger.getLatestSolidifiedBlockNumber()); + assertEquals(mockEventTrigger.isRemoved(), trigger.isRemoved()); + assertEquals(mockEventTrigger.getUniqueId(), trigger.getUniqueId()); + assertEquals(mockEventTrigger.getTransactionId(), trigger.getTransactionId()); + assertEquals(mockEventTrigger.getContractAddress(), trigger.getContractAddress()); + assertEquals(mockEventTrigger.getOriginAddress(), trigger.getOriginAddress()); + assertEquals("", trigger.getCallerAddress()); // Explicitly set to empty string + assertEquals(mockEventTrigger.getCreatorAddress(), trigger.getCreatorAddress()); + assertEquals(mockEventTrigger.getBlockNumber(), trigger.getBlockNumber()); + assertEquals(mockEventTrigger.getTimeStamp(), trigger.getTimeStamp()); + assertEquals(mockEventTrigger.getBlockHash(), trigger.getBlockHash()); + } + + @Test + public void testSetAndGetTopicList() { + ContractLogTrigger trigger = new ContractLogTrigger(); + List topics = Arrays.asList("topic1", "topic2"); + trigger.setTopicList(topics); + assertEquals(topics, trigger.getTopicList()); + } + + @Test + public void testSetAndGetData() { + ContractLogTrigger trigger = new ContractLogTrigger(); + String testData = "log data"; + trigger.setData(testData); + assertEquals(testData, trigger.getData()); + } + +} diff --git a/framework/src/test/java/org/tron/common/logsfilter/trigger/InternalTransactionPojoTest.java b/framework/src/test/java/org/tron/common/logsfilter/trigger/InternalTransactionPojoTest.java new file mode 100644 index 00000000000..9948c5535af --- /dev/null +++ b/framework/src/test/java/org/tron/common/logsfilter/trigger/InternalTransactionPojoTest.java @@ -0,0 +1,87 @@ +package org.tron.common.logsfilter.trigger; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; + +public class InternalTransactionPojoTest { + private InternalTransactionPojo internalTransactionPojo; + + @Before + public void setUp() { + internalTransactionPojo = new InternalTransactionPojo(); + } + + @Test + public void testHash() { + String testHash = "0x123456789abcdef0123456789abcdef0"; + internalTransactionPojo.setHash(testHash); + assertEquals(testHash, internalTransactionPojo.getHash()); + } + + @Test + public void testCallValue() { + long testCallValue = 123456789L; + internalTransactionPojo.setCallValue(testCallValue); + assertEquals(testCallValue, internalTransactionPojo.getCallValue()); + } + + @Test + public void testTokenInfo() { + Map testTokenInfo = new HashMap<>(); + testTokenInfo.put("token1", 100L); + testTokenInfo.put("token2", 200L); + internalTransactionPojo.setTokenInfo(testTokenInfo); + assertEquals(testTokenInfo, internalTransactionPojo.getTokenInfo()); + } + + @Test + public void testTransferToAddress() { + String testAddress = "0x0000000000000000000000000000000000000001"; + internalTransactionPojo.setTransferTo_address(testAddress); + assertEquals(testAddress, internalTransactionPojo.getTransferTo_address()); + } + + @Test + public void testData() { + String testData = "0x6060604052341561000f57600080fd5b5b6040516020806101158339810160405280805" + + "19060200190929190505050"; + internalTransactionPojo.setData(testData); + assertEquals(testData, internalTransactionPojo.getData()); + } + + @Test + public void testCallerAddress() { + String testCallerAddress = "0x0000000000000000000000000000000000000002"; + internalTransactionPojo.setCaller_address(testCallerAddress); + assertEquals(testCallerAddress, internalTransactionPojo.getCaller_address()); + } + + @Test + public void testRejected() { + internalTransactionPojo.setRejected(true); + assertTrue(internalTransactionPojo.isRejected()); + + internalTransactionPojo.setRejected(false); + assertFalse(internalTransactionPojo.isRejected()); + } + + @Test + public void testNote() { + String testNote = "This is a test note"; + internalTransactionPojo.setNote(testNote); + assertEquals(testNote, internalTransactionPojo.getNote()); + } + + @Test + public void testExtra() { + String testExtra = "extra_data_for_vote_witness"; + internalTransactionPojo.setExtra(testExtra); + assertEquals(testExtra, internalTransactionPojo.getExtra()); + } +} diff --git a/framework/src/test/java/org/tron/common/logsfilter/trigger/LogPojoTest.java b/framework/src/test/java/org/tron/common/logsfilter/trigger/LogPojoTest.java new file mode 100644 index 00000000000..7c94ec4f7ad --- /dev/null +++ b/framework/src/test/java/org/tron/common/logsfilter/trigger/LogPojoTest.java @@ -0,0 +1,74 @@ +package org.tron.common.logsfilter.trigger; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.List; +import org.junit.Before; +import org.junit.Test; + +public class LogPojoTest { + + private LogPojo logPojo; + + @Before + public void setUp() { + logPojo = new LogPojo(); + } + + @Test + public void testAddress() { + String testAddress = "123 Test Address"; + logPojo.setAddress(testAddress); + assertEquals(testAddress, logPojo.getAddress()); + } + + @Test + public void testBlockHash() { + String testBlockHash = "abcdef1234567890abcdef1234567890abcdef12"; + logPojo.setBlockHash(testBlockHash); + assertEquals(testBlockHash, logPojo.getBlockHash()); + } + + @Test + public void testBlockNumber() { + long testBlockNumber = 1234567L; + logPojo.setBlockNumber(testBlockNumber); + assertEquals(testBlockNumber, logPojo.getBlockNumber()); + } + + @Test + public void testData() { + String testData = "Some data here"; + logPojo.setData(testData); + assertEquals(testData, logPojo.getData()); + } + + @Test + public void testLogIndex() { + long testLogIndex = 5L; + logPojo.setLogIndex(testLogIndex); + assertEquals(testLogIndex, logPojo.getLogIndex()); + } + + @Test + public void testTopicList() { + List testTopicList = Arrays.asList("topic1", "topic2", "topic3"); + logPojo.setTopicList(testTopicList); + assertEquals(testTopicList, logPojo.getTopicList()); + } + + @Test + public void testTransactionHash() { + String testTransactionHash = "abcdef1234567890abcdef1234567890abcdef12"; + logPojo.setTransactionHash(testTransactionHash); + assertEquals(testTransactionHash, logPojo.getTransactionHash()); + } + + @Test + public void testTransactionIndex() { + long testTransactionIndex = 3L; + logPojo.setTransactionIndex(testTransactionIndex); + assertEquals(testTransactionIndex, logPojo.getTransactionIndex()); + } +} diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java index 5ada5612fce..cf67ae4b087 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BatchSendTest.java @@ -93,6 +93,7 @@ public void TransferTokenTest() ECKey ecKey3 = new ECKey(Utils.getRandom()); List params = new ArrayList<>(); + logger.info("show db key: {}", StringUtil.createDbKey(ByteString.copyFrom("test".getBytes()))); params.add(StringUtil.encode58Check(ecKey1.getAddress())); params.add(StringUtil.encode58Check(ecKey2.getAddress())); params.add(StringUtil.encode58Check(ecKey3.getAddress())); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/DataWordTest.java b/framework/src/test/java/org/tron/common/runtime/vm/DataWordTest.java index 8da6e4c96ea..172e3f17f1b 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/DataWordTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/DataWordTest.java @@ -18,14 +18,22 @@ package org.tron.common.runtime.vm; +import static org.apache.commons.lang3.ArrayUtils.isNotEmpty; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; +import static org.tron.common.runtime.vm.DataWord.isZero; import java.math.BigInteger; import java.util.Arrays; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; import org.bouncycastle.util.encoders.Hex; +import org.eclipse.jetty.util.ArrayUtil; import org.junit.Test; +import org.tron.core.db.ByteArrayWrapper; @Slf4j public class DataWordTest { @@ -70,16 +78,16 @@ public void testAddPerformance() { DataWord x = new DataWord(one); x.add(x); } - System.out.println("Add1: " + (System.currentTimeMillis() - now1) + "ms"); + logger.info("Add1: " + (System.currentTimeMillis() - now1) + "ms"); long now2 = System.currentTimeMillis(); for (int i = 0; i < ITERATIONS; i++) { DataWord x = new DataWord(one); x.add2(x); } - System.out.println("Add2: " + (System.currentTimeMillis() - now2) + "ms"); + logger.info("Add2: " + (System.currentTimeMillis() - now2) + "ms"); } else { - System.out.println("ADD performance test is disabled."); + logger.info("ADD performance test is disabled."); } } @@ -90,11 +98,11 @@ public void testAdd2() { DataWord x = new DataWord(two); x.add(new DataWord(two)); - System.out.println(Hex.toHexString(x.getData())); + logger.info(Hex.toHexString(x.getData())); DataWord y = new DataWord(two); y.add2(new DataWord(two)); - System.out.println(Hex.toHexString(y.getData())); + logger.info(Hex.toHexString(y.getData())); } @Test @@ -107,12 +115,12 @@ public void testAdd3() { DataWord x = new DataWord(three); x.add(new DataWord(three)); assertEquals(32, x.getData().length); - System.out.println(Hex.toHexString(x.getData())); + logger.info(Hex.toHexString(x.getData())); // FAIL // DataWord y = new DataWord(three); // y.add2(new DataWord(three)); - // System.out.println(Hex.toHexString(y.getData())); + // logger.info(Hex.toHexString(y.getData())); } @Test @@ -128,8 +136,8 @@ public void testMod() { } two[31] = 0x56; // 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff56 - DataWord x = new DataWord(one);// System.out.println(x.value()); - DataWord y = new DataWord(two);// System.out.println(y.value()); + DataWord x = new DataWord(one);// logger.info(x.value()); + DataWord y = new DataWord(two);// logger.info(y.value()); y.mod(x); assertEquals(32, y.getData().length); assertEquals(expected, Hex.toHexString(y.getData())); @@ -143,8 +151,8 @@ public void testMul() { byte[] two = new byte[32]; two[11] = 0x1; // 0x0000000000000000000000010000000000000000000000000000000000000000 - DataWord x = new DataWord(one);// System.out.println(x.value()); - DataWord y = new DataWord(two);// System.out.println(y.value()); + DataWord x = new DataWord(one);// logger.info(x.value()); + DataWord y = new DataWord(two);// logger.info(y.value()); x.mul(y); assertEquals(32, y.getData().length); assertEquals("0000000000000000000000010000000000000000000000000000000000000000", @@ -160,8 +168,8 @@ public void testMulOverflow() { byte[] two = new byte[32]; two[0] = 0x1; // 0x1000000000000000000000000000000000000000000000000000000000000000 - DataWord x = new DataWord(one);// System.out.println(x.value()); - DataWord y = new DataWord(two);// System.out.println(y.value()); + DataWord x = new DataWord(one);// logger.info(x.value()); + DataWord y = new DataWord(two);// logger.info(y.value()); x.mul(y); assertEquals(32, y.getData().length); assertEquals("0100000000000000000000000000000000000000000000000000000000000000", @@ -226,8 +234,8 @@ public void testPow() { BigInteger result1 = x.modPow(x, y); BigInteger result2 = pow(x, y); - System.out.println(result1); - System.out.println(result2); + logger.info(result1.toString()); + logger.info(result2.toString()); } @Test @@ -238,7 +246,7 @@ public void testSignExtend1() { String expected = "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2"; x.signExtend(k); - System.out.println(x.toString()); + logger.info(x.toString()); assertEquals(expected, x.toString()); } @@ -249,7 +257,7 @@ public void testSignExtend2() { String expected = "00000000000000000000000000000000000000000000000000000000000000f2"; x.signExtend(k); - System.out.println(x.toString()); + logger.info(x.toString()); assertEquals(expected, x.toString()); } @@ -261,7 +269,7 @@ public void testSignExtend3() { String expected = "00000000000000000000000000000000000000000000000000000000000000ab"; x.signExtend(k); - System.out.println(x.toString()); + logger.info(x.toString()); assertEquals(expected, x.toString()); } @@ -273,7 +281,7 @@ public void testSignExtend4() { String expected = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; x.signExtend(k); - System.out.println(x.toString()); + logger.info(x.toString()); assertEquals(expected, x.toString()); } @@ -285,7 +293,7 @@ public void testSignExtend5() { String expected = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; x.signExtend(k); - System.out.println(x.toString()); + logger.info(x.toString()); assertEquals(expected, x.toString()); } @@ -297,7 +305,7 @@ public void testSignExtend6() { String expected = "0000000000000000000000000000000000000000000000000000000002345678"; x.signExtend(k); - System.out.println(x.toString()); + logger.info(x.toString()); assertEquals(expected, x.toString()); } @@ -309,7 +317,7 @@ public void testSignExtend7() { String expected = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff82345678"; x.signExtend(k); - System.out.println(x.toString()); + logger.info(x.toString()); assertEquals(expected, x.toString()); } @@ -322,7 +330,7 @@ public void testSignExtend8() { String expected = "0034567882345678823456788234567882345678823456788234567882345678"; x.signExtend(k); - System.out.println(x.toString()); + logger.info(x.toString()); assertEquals(expected, x.toString()); } @@ -576,9 +584,39 @@ private void testShiftRightSigned(String[][] cases) { DataWord arg = new DataWord(c[1]); DataWord expected = new DataWord(c[2]); DataWord actual = value.shiftRightSigned(arg); - assertEquals(i + " " + Arrays.asList(c).toString(), expected, actual); + assertEquals(i + " " + Arrays.asList(c), expected, actual); } } + @Test + public void testIsZero() { + DataWord dataWord = new DataWord(new byte[0]); + DataWord d = new DataWord(new ByteArrayWrapper(new byte[0])); + assertTrue(d.isZero()); + d.negate(); + assertThrows(IllegalArgumentException.class, () -> new ByteArrayWrapper(null)); + assertTrue(dataWord.isZero()); + assertTrue(isZero(new byte[0])); + assertFalse(isZero(new byte[]{1})); + DataWord dataWord1 = new DataWord(new byte[]{0, 1}); + assertFalse(dataWord1.isZero()); + assertTrue(isNotEmpty(new DataWord((byte[]) null).getClonedData())); + assertTrue(isNotEmpty(dataWord1.getClonedData())); + logger.info(dataWord.toPrefixString()); + logger.info(dataWord1.toPrefixString()); + logger.info(new DataWord((new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8})).toPrefixString()); + logger.info(dataWord.shortHex()); + logger.info(DataWord.shortHex(new byte[0])); + logger.info(DataWord.bigIntValue(new byte[]{1})); + logger.info(dataWord.bigIntValue()); + logger.info("dataWord is Hex: {}", dataWord.isHex("test")); + logger.info(dataWord.asString()); + logger.info(Arrays.toString(dataWord.getNoEndZeroesData())); + DataWord tmp = dataWord; + assertEquals(dataWord, tmp); + assertNotEquals(dataWord, null); + assertEquals(-1, dataWord.compareTo(null)); + } + } diff --git a/framework/src/test/java/org/tron/common/utils/ALockTest.java b/framework/src/test/java/org/tron/common/utils/ALockTest.java new file mode 100644 index 00000000000..d4501756daa --- /dev/null +++ b/framework/src/test/java/org/tron/common/utils/ALockTest.java @@ -0,0 +1,27 @@ +package org.tron.common.utils; + +import static org.junit.Assert.assertNotNull; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import org.junit.Before; +import org.junit.Test; + +public class ALockTest { + private ALock aLock; + private Lock mockLock; + + @Before + public void setUp() { + mockLock = new ReentrantLock(); + aLock = new ALock(mockLock); + } + + @Test + public void testLockAndUnlock() { + aLock.lock(); + assertNotNull(aLock); + aLock.close(); + } + +} diff --git a/framework/src/test/java/org/tron/common/utils/BIUtilTest.java b/framework/src/test/java/org/tron/common/utils/BIUtilTest.java new file mode 100644 index 00000000000..d126eb2a6b1 --- /dev/null +++ b/framework/src/test/java/org/tron/common/utils/BIUtilTest.java @@ -0,0 +1,155 @@ +package org.tron.common.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.math.BigInteger; +import org.junit.Test; + +public class BIUtilTest { + + @Test + public void testIsLessThan() { + BigInteger valueA = BigInteger.valueOf(1); + BigInteger valueB = BigInteger.valueOf(2); + assertTrue(BIUtil.isLessThan(valueA, valueB)); + + valueA = BigInteger.valueOf(3); + valueB = BigInteger.valueOf(3); + assertFalse(BIUtil.isLessThan(valueA, valueB)); + + valueA = BigInteger.valueOf(4); + valueB = BigInteger.valueOf(2); + assertFalse(BIUtil.isLessThan(valueA, valueB)); + } + + @Test + public void testIsZero() { + BigInteger value = BigInteger.ZERO; + assertTrue(BIUtil.isZero(value)); + + value = BigInteger.valueOf(1); + assertFalse(BIUtil.isZero(value)); + + value = BigInteger.valueOf(-1); + assertFalse(BIUtil.isZero(value)); + } + + @Test + public void testIsEqual() { + BigInteger valueA = BigInteger.valueOf(1); + BigInteger valueB = BigInteger.valueOf(1); + assertTrue(BIUtil.isEqual(valueA, valueB)); + + valueA = BigInteger.valueOf(2); + valueB = BigInteger.valueOf(3); + assertFalse(BIUtil.isEqual(valueA, valueB)); + } + + @Test + public void testIsNotEqual() { + BigInteger valueA = BigInteger.valueOf(1); + BigInteger valueB = BigInteger.valueOf(2); + assertTrue(BIUtil.isNotEqual(valueA, valueB)); + + valueA = BigInteger.valueOf(3); + valueB = BigInteger.valueOf(3); + assertFalse(BIUtil.isNotEqual(valueA, valueB)); + } + + @Test + public void testIsMoreThan() { + BigInteger valueA = BigInteger.valueOf(3); + BigInteger valueB = BigInteger.valueOf(2); + assertTrue(BIUtil.isMoreThan(valueA, valueB)); + + valueA = BigInteger.valueOf(1); + valueB = BigInteger.valueOf(2); + assertFalse(BIUtil.isMoreThan(valueA, valueB)); + + valueA = BigInteger.valueOf(2); + valueB = BigInteger.valueOf(2); + assertFalse(BIUtil.isMoreThan(valueA, valueB)); + } + + @Test + public void testSum() { + BigInteger valueA = BigInteger.valueOf(5); + BigInteger valueB = BigInteger.valueOf(7); + BigInteger expected = BigInteger.valueOf(12); + assertEquals(expected, BIUtil.sum(valueA, valueB)); + } + + @Test + public void testToBI_byteArray() { + byte[] data = {1, 0, 0, 0, 0, 0, 0, 1}; // BigInteger(128) + BigInteger expected = new BigInteger(1, data); + assertEquals(expected, BIUtil.toBI(data)); + } + + @Test + public void testToBI_long() { + long data = 123456789L; + BigInteger expected = BigInteger.valueOf(data); + assertEquals(expected, BIUtil.toBI(data)); + } + + @Test + public void testIsPositive() { + BigInteger value = BigInteger.valueOf(1); + assertTrue(BIUtil.isPositive(value)); + + value = BigInteger.ZERO; + assertFalse(BIUtil.isPositive(value)); + + value = BigInteger.valueOf(-1); + assertFalse(BIUtil.isPositive(value)); + } + + @Test + public void testIsNotCovers() { + BigInteger covers = BigInteger.valueOf(5); + BigInteger value = BigInteger.valueOf(10); + assertTrue(BIUtil.isNotCovers(covers, value)); + + covers = BigInteger.valueOf(10); + value = BigInteger.valueOf(5); + assertFalse(BIUtil.isNotCovers(covers, value)); + + covers = BigInteger.valueOf(10); + value = BigInteger.valueOf(10); + assertFalse(BIUtil.isNotCovers(covers, value)); + } + + @Test + public void testMax() { + BigInteger first = BigInteger.valueOf(5); + BigInteger second = BigInteger.valueOf(10); + assertEquals(second, BIUtil.max(first, second)); + + first = BigInteger.valueOf(15); + second = BigInteger.valueOf(10); + assertEquals(first, BIUtil.max(first, second)); + + first = BigInteger.valueOf(10); + second = BigInteger.valueOf(10); + assertEquals(first, BIUtil.max(first, second)); + } + + @Test + public void testAddSafely() { + int a = Integer.MAX_VALUE; + int b = 1; + int expected = Integer.MAX_VALUE; + assertEquals(expected, BIUtil.addSafely(a, b)); + + a = Integer.MAX_VALUE - 1; + b = 2; + assertEquals(expected, BIUtil.addSafely(a, b)); + + a = 1; + expected = 3; + assertEquals(expected, BIUtil.addSafely(a, b)); + } +} diff --git a/framework/src/test/java/org/tron/common/utils/ByteArrayMapTest.java b/framework/src/test/java/org/tron/common/utils/ByteArrayMapTest.java new file mode 100644 index 00000000000..8abdc3e3def --- /dev/null +++ b/framework/src/test/java/org/tron/common/utils/ByteArrayMapTest.java @@ -0,0 +1,145 @@ +package org.tron.common.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import com.mchange.v2.collection.MapEntry; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import org.junit.Before; +import org.junit.Test; +import org.tron.core.db.ByteArrayWrapper; + +public class ByteArrayMapTest { + + private ByteArrayMap byteArrayMap; + + @Before + public void setUp() { + byteArrayMap = new ByteArrayMap<>(); + } + + @Test + public void testPutAndGet() { + byte[] key = "key1".getBytes(); + String value = "value1"; + byteArrayMap.put(key, value); + assertEquals("Should return the correct value", value, byteArrayMap.get(key)); + } + + @Test + public void testSize() { + byte[] key1 = "key1".getBytes(); + byte[] key2 = "key2".getBytes(); + byteArrayMap.put(key1, "value1"); + byteArrayMap.put(key2, "value2"); + assertEquals("Should return the correct size", 2, byteArrayMap.size()); + } + + @Test + public void testRemove() { + byte[] key = "key".getBytes(); + String value = "value"; + byteArrayMap.put(key, value); + byteArrayMap.remove(key); + assertNull("Should return null after removal", byteArrayMap.get(key)); + } + + @Test + public void testContainsKey() { + byte[] key = "key".getBytes(); + byteArrayMap.put(key, "value"); + assertTrue("Should contain the key", byteArrayMap.containsKey(key)); + } + + @Test + public void testPutAll() { + Map mapToPut = createTestMap(); + byteArrayMap.putAll(mapToPut); + assertEquals("Should contain all entries after putAll", 2, byteArrayMap.size()); + assertEquals("Should return the correct value for key1", + "value1", byteArrayMap.get("key1".getBytes())); + assertEquals("Should return the correct value for key2", + "value2", byteArrayMap.get("key2".getBytes())); + + } + + @Test + public void testClear() { + byte[] key1 = "key1".getBytes(); + byte[] key2 = "key2".getBytes(); + byteArrayMap.put(key1, "value1"); + byteArrayMap.put(key2, "value2"); + assertFalse(byteArrayMap.isEmpty()); + byteArrayMap.clear(); + } + + @Test + public void testKeySet() { + byte[] key1 = "key1".getBytes(); + byte[] key2 = "key2".getBytes(); + byteArrayMap.put(key1, "value1"); + byteArrayMap.put(key2, "value2"); + Set set = byteArrayMap.keySet(); + assertTrue("Key set should contain key1", set.contains(key1)); + assertTrue("Key set should contain key2", set.contains(key2)); + } + + @Test + public void testValues() { + byte[] key1 = "key1".getBytes(); + byte[] key2 = "key2".getBytes(); + byteArrayMap.put(key1, "value1"); + byteArrayMap.put(key2, "value2"); + Collection values = byteArrayMap.values(); + assertTrue("Values should contain value1", values.contains("value1")); + assertTrue("Values should contain value1", byteArrayMap.containsValue("value1")); + assertTrue("Values should contain value2", values.contains("value2")); + } + + @Test + public void testEntrySet() { + byte[] key1 = "key1".getBytes(); + byte[] key2 = "key2".getBytes(); + byteArrayMap.put(key1, "value1"); + byteArrayMap.put(key2, "value2"); + Set> entrySet = byteArrayMap.entrySet(); + assertFalse(entrySet.isEmpty()); + assertEquals("Entry set size should be 2", 2, entrySet.size()); + assertThrows(Exception.class, () -> entrySet.contains(new Object())); + assertThrows(Exception.class, entrySet::toArray); + assertThrows(Exception.class, () -> entrySet.toArray(new Map.Entry[0])); + assertThrows(Exception.class, () -> entrySet.add(new MapEntry(key1, "value1"))); + assertThrows(Exception.class, () -> entrySet.remove(new MapEntry(key1, "value1"))); + assertThrows(Exception.class, () -> entrySet.containsAll(new HashSet<>())); + assertThrows(Exception.class, () -> entrySet.removeAll(new HashSet<>())); + assertThrows(Exception.class, () -> entrySet.addAll(new HashSet<>())); + assertThrows(Exception.class, () -> entrySet.retainAll(new HashSet<>())); + assertThrows(Exception.class, entrySet::clear); + } + + // Helper method to create a map for testing putAll + private Map createTestMap() { + Map map = new ByteArrayMap<>(); + map.put("key1".getBytes(), "value1"); + map.put("key2".getBytes(), "value2"); + return map; + } + + + @Test + public void test() { + Map map = new ByteArrayMap<>(); + Map testMap = createTestMap(); + assertNotEquals(map, testMap); + assertTrue(testMap.hashCode() <= 0); + assertNotNull(testMap.toString()); + } +} diff --git a/framework/src/test/java/org/tron/common/utils/ByteArraySetTest.java b/framework/src/test/java/org/tron/common/utils/ByteArraySetTest.java new file mode 100644 index 00000000000..22695f713a7 --- /dev/null +++ b/framework/src/test/java/org/tron/common/utils/ByteArraySetTest.java @@ -0,0 +1,143 @@ +package org.tron.common.utils; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import org.junit.Before; +import org.junit.Test; + +public class ByteArraySetTest { + + private ByteArraySet byteArraySet; + + @Before + public void setUp() { + byteArraySet = new ByteArraySet(); + } + + @Test + public void testSizeIsEmptyInitially() { + assertEquals(0, byteArraySet.size()); + } + + @Test + public void testIsEmptyInitially() { + assertTrue(byteArraySet.isEmpty()); + } + + @Test + public void testAddAndGetSize() { + byte[] bytes1 = {1, 2, 3}; + byte[] bytes2 = {4, 5, 6}; + + byteArraySet.add(bytes1); + assertEquals(1, byteArraySet.size()); + + byteArraySet.add(bytes2); + assertEquals(2, byteArraySet.size()); + } + + @Test + public void testContains() { + byte[] bytes1 = {1, 2, 3}; + byte[] bytes2 = {4, 5, 6}; + + byteArraySet.add(bytes1); + assertTrue(byteArraySet.contains(bytes1)); + assertFalse(byteArraySet.contains(bytes2)); + + byteArraySet.add(bytes2); + assertTrue(byteArraySet.contains(bytes2)); + + assertThrows(Exception.class, () -> byteArraySet.containsAll(new HashSet<>())); + assertThrows(Exception.class, () -> byteArraySet.retainAll(new HashSet<>())); + assertThrows(Exception.class, () -> byteArraySet.removeAll(new HashSet<>())); + assertThrows(Exception.class, () -> byteArraySet.equals(new ByteArraySet())); + assertThrows(Exception.class, () -> byteArraySet.hashCode()); + } + + @Test + public void testIterator() { + byte[] bytes1 = {1, 2, 3}; + byte[] bytes2 = {4, 5, 6}; + + byteArraySet.add(bytes1); + byteArraySet.add(bytes2); + + Iterator iterator = byteArraySet.iterator(); + + assertTrue(iterator.hasNext()); + assertArrayEquals(bytes1, iterator.next()); + + assertTrue(iterator.hasNext()); + assertArrayEquals(bytes2, iterator.next()); + + assertFalse(iterator.hasNext()); + } + + @Test + public void testToArray() { + byte[] bytes1 = {1, 2, 3}; + byte[] bytes2 = {4, 5, 6}; + + byteArraySet.add(bytes1); + byteArraySet.add(bytes2); + + byte[][] array = byteArraySet.toArray(new byte[0][]); + + assertEquals(2, array.length); + assertArrayEquals(bytes1, array[0]); + assertArrayEquals(bytes2, array[1]); + } + + @Test + public void testAddAll() { + List list = Arrays.asList( + new byte[]{1, 2, 3}, + new byte[]{4, 5, 6} + ); + + boolean result = byteArraySet.addAll(list); + + assertTrue(result); + assertEquals(2, byteArraySet.size()); + assertTrue(byteArraySet.contains(new byte[]{1, 2, 3})); + assertTrue(byteArraySet.contains(new byte[]{4, 5, 6})); + } + + @Test + public void testRemove() { + byte[] bytes1 = {1, 2, 3}; + byte[] bytes2 = {4, 5, 6}; + + byteArraySet.add(bytes1); + byteArraySet.add(bytes2); + + boolean result = byteArraySet.remove(bytes1); + + assertTrue(result); + assertEquals(1, byteArraySet.size()); + assertFalse(byteArraySet.contains(bytes1)); + assertTrue(byteArraySet.contains(bytes2)); + } + + @Test + public void testClear() { + byte[] bytes1 = {1, 2, 3}; + byte[] bytes2 = {4, 5, 6}; + + byteArraySet.add(bytes1); + byteArraySet.add(bytes2); + assertTrue(byteArraySet.size() > 0); + + byteArraySet.clear(); + } +} diff --git a/framework/src/test/java/org/tron/common/utils/ByteArrayTest.java b/framework/src/test/java/org/tron/common/utils/ByteArrayTest.java index 226b00b8cb1..c0db8c4b418 100644 --- a/framework/src/test/java/org/tron/common/utils/ByteArrayTest.java +++ b/framework/src/test/java/org/tron/common/utils/ByteArrayTest.java @@ -17,6 +17,12 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.tron.common.utils.ByteArray.fromHex; +import static org.tron.common.utils.ByteArray.jsonHexToInt; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; @@ -80,4 +86,33 @@ public void test2ToHexString() { assertEquals("ByteArray.toHexString is not equals Hex.toHexString", ByteArray.toHexString(bss), Hex.toHexString(bss)); } + + @Test + public void testFromObject_SerializableObject() { + String testString = "Hello, World!"; + byte[] result = ByteArray.fromObject(testString); + assertNotNull(result); + assertTrue(result.length > 0); + } + + @Test + public void testJsonHexToInt_ValidHex() { + try { + int result = jsonHexToInt("0x1A"); + assertEquals(26, result); + } catch (Exception e) { + fail("Exception should not have been thrown for valid hex string."); + } + assertThrows(Exception.class, () -> ByteArray.jsonHexToInt("1A")); + } + + @Test + public void testFromHexWithPrefix() { + String input = "0x1A3F"; + String expected = "1A3F"; + String result = fromHex(input); + assertEquals(expected, result); + String input1 = "1A3"; + assertEquals("01A3", fromHex(input1)); + } } diff --git a/framework/src/test/java/org/tron/common/utils/CollectionUtilsTest.java b/framework/src/test/java/org/tron/common/utils/CollectionUtilsTest.java new file mode 100644 index 00000000000..8b8ef35fb4b --- /dev/null +++ b/framework/src/test/java/org/tron/common/utils/CollectionUtilsTest.java @@ -0,0 +1,81 @@ +package org.tron.common.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Predicate; +import org.junit.Test; + +public class CollectionUtilsTest { + + @Test + public void testCollectList() { + List numbers = Arrays.asList("1", "2", "3"); + Function toInt = Integer::parseInt; + List integers = CollectionUtils.collectList(numbers, toInt); + assertEquals(Arrays.asList(1, 2, 3), integers); + } + + @Test + public void testCollectSet() { + List numbers = Arrays.asList("1", "2", "2", "3"); + Function toInt = Integer::parseInt; + Set integers = CollectionUtils.collectSet(numbers, toInt); + assertEquals(new HashSet<>(Arrays.asList(1, 2, 3)), integers); + } + + @Test + public void testTruncate() { + List numbers = Arrays.asList(1, 2, 3, 4, 5); + List truncated = CollectionUtils.truncate(numbers, 3); + assertEquals(Arrays.asList(1, 2, 3), truncated); + } + + @Test + public void testTruncateNoLimit() { + List numbers = Arrays.asList(1, 2, 3, 4, 5); + List truncated = CollectionUtils.truncate(numbers, 10); + assertEquals(numbers, truncated); + } + + @Test + public void testTruncateRandom() { + List numbers = Arrays.asList(1, 2, 3, 4, 5); + List numbers1 = Arrays.asList(1, 2); + List truncated = CollectionUtils.truncateRandom(numbers, 3, 2); + List truncated1 = CollectionUtils.truncateRandom(numbers1, 3, 2); + assertEquals(2, truncated1.size()); + assertEquals(3, truncated.size()); + assertTrue(truncated.containsAll(Arrays.asList(1, 2, 3, 4, 5).subList(0, 2))); + // Last element could be 3, 4, or 5, so we just check that it's one of them + assertTrue(truncated.contains(3) || truncated.contains(4) || truncated.contains(5)); + } + + @Test + public void testTruncateRandomConfirmEqualLimit() { + List numbers = Arrays.asList(1, 2, 3, 4, 5); + List truncated = CollectionUtils.truncateRandom(numbers, 5, 5); + assertEquals(numbers, truncated); + } + + @Test + public void testSelectList() { + List numbers = Arrays.asList(1, 2, 3, 4, 5); + Predicate isEven = n -> n % 2 == 0; + List selected = CollectionUtils.selectList(numbers, isEven); + assertEquals(Arrays.asList(2, 4), selected); + } + + @Test + public void testSelectSet() { + List numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5); + Predicate isEven = n -> n % 2 == 0; + Set selected = CollectionUtils.selectSet(numbers, isEven); + assertEquals(new HashSet<>(Arrays.asList(2, 4)), selected); + } +} diff --git a/framework/src/test/java/org/tron/common/utils/FileUtilTest.java b/framework/src/test/java/org/tron/common/utils/FileUtilTest.java index 9aff1566ef3..126e0918520 100644 --- a/framework/src/test/java/org/tron/common/utils/FileUtilTest.java +++ b/framework/src/test/java/org/tron/common/utils/FileUtilTest.java @@ -1,11 +1,88 @@ package org.tron.common.utils; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.tron.common.utils.FileUtil.readData; + import java.io.File; +import java.io.FileWriter; import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.FileVisitor; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import org.junit.After; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; public class FileUtilTest { + private Path tempDir; + + @Before + public void setUp() throws IOException { + tempDir = Files.createTempDirectory("testDir"); + + Files.createFile(tempDir.resolve("file1.txt")); + Files.createFile(tempDir.resolve("file2.txt")); + + Path subDir = Files.createDirectory(tempDir.resolve("subdir")); + Files.createFile(subDir.resolve("file3.txt")); + } + + @After + public void tearDown() throws IOException { + Files.walk(tempDir) + .sorted(Comparator.reverseOrder()) + .forEach(path -> { + try { + Files.delete(path); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } + + @Test + public void testRecursiveList() throws IOException { + List files = FileUtil.recursiveList(tempDir.toString()); + + assertTrue(files.contains(tempDir.resolve("file1.txt").toString())); + assertTrue(files.contains(tempDir.resolve("file2.txt").toString())); + assertTrue(files.contains(tempDir.resolve("subdir").resolve("file3.txt").toString())); + + assertEquals(3, files.size()); + } + + @Test + public void testReadData_NormalFile() throws IOException { + Path tempFile = Files.createTempFile("testfile", ".txt"); + try (FileWriter writer = new FileWriter(tempFile.toFile())) { + writer.write("Hello, World!"); + } + + char[] buffer = new char[1024]; + int len = readData(tempFile.toString(), buffer); + + assertEquals(13, len); + assertArrayEquals("Hello, World!".toCharArray(), Arrays.copyOf(buffer, 13)); + } + + @Test + public void testReadData_IOException() { + char[] buffer = new char[1024]; + File dir = new File(System.getProperty("java.io.tmpdir")); + int len = readData(dir.getAbsolutePath(), buffer); + assertEquals(0, len); + } + @Test public void testCreateFileIfNotExists() { @@ -16,15 +93,15 @@ public void testCreateFileIfNotExists() { } catch (IOException e) { System.out.println("ignore this exception."); } - Assert.assertTrue(file1.exists()); - Assert.assertTrue(FileUtil.createDirIfNotExists(existFile)); - Assert.assertTrue(file1.exists()); + assertTrue(file1.exists()); + assertTrue(FileUtil.createDirIfNotExists(existFile)); + assertTrue(file1.exists()); String notExistFile = "notexistsfile.txt"; File file2 = new File(notExistFile); - Assert.assertTrue(!file2.exists()); - Assert.assertTrue(FileUtil.createDirIfNotExists(notExistFile)); - Assert.assertTrue(file2.exists()); + assertTrue(!file2.exists()); + assertTrue(FileUtil.createDirIfNotExists(notExistFile)); + assertTrue(file2.exists()); file1.delete(); file2.delete(); } @@ -34,16 +111,18 @@ public void testCreateDirIfNotExists() { String existDir = "existsdir"; File fileDir1 = new File(existDir); fileDir1.mkdir(); - Assert.assertTrue(fileDir1.exists()); - Assert.assertTrue(FileUtil.createDirIfNotExists(existDir)); - Assert.assertTrue(fileDir1.exists()); + assertTrue(fileDir1.exists()); + assertTrue(FileUtil.createDirIfNotExists(existDir)); + assertTrue(fileDir1.exists()); String notExistDir = "notexistsdir"; File fileDir2 = new File(notExistDir); - Assert.assertTrue(!fileDir2.exists()); - Assert.assertTrue(FileUtil.createDirIfNotExists(notExistDir)); - Assert.assertTrue(fileDir2.exists()); + assertTrue(!fileDir2.exists()); + assertTrue(FileUtil.createDirIfNotExists(notExistDir)); + assertTrue(fileDir2.exists()); fileDir1.delete(); fileDir2.delete(); } + + } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/common/utils/JsonUtilTest.java b/framework/src/test/java/org/tron/common/utils/JsonUtilTest.java index 9a4efb722e3..8681ff58270 100644 --- a/framework/src/test/java/org/tron/common/utils/JsonUtilTest.java +++ b/framework/src/test/java/org/tron/common/utils/JsonUtilTest.java @@ -1,7 +1,13 @@ package org.tron.common.utils; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.tron.common.utils.JsonUtil.json2Obj; +import static org.tron.common.utils.JsonUtil.obj2Json; + import lombok.Data; -import org.junit.Assert; import org.junit.Test; public class JsonUtilTest { @@ -25,11 +31,50 @@ public void test() { a1.setKey("abc"); a1.setValue(100); - String jsonString = JsonUtil.obj2Json(a1); + String jsonString = obj2Json(a1); A a2 = JsonUtil.json2Obj(jsonString, A.class); - Assert.assertEquals(a2.getKey(), "abc"); - Assert.assertEquals(a2.getValue(), 100); + assert a2 != null; + assertEquals("abc", a2.getKey()); + assertEquals(100, a2.getValue()); + assertNull(obj2Json(null)); + assertNull(json2Obj(null, null)); + + + } + + @Test + public void testObj2JsonWithCircularReference() { + Node node1 = new Node("Node1"); + Node node2 = new Node("Node2"); + node1.setNext(node2); + node2.setNext(node1); + + try { + obj2Json(node1); + fail("Expected a RuntimeException to be thrown"); + } catch (RuntimeException e) { + assertTrue(e.getCause() instanceof com.fasterxml.jackson.databind.JsonMappingException); + } + } + + @Test(expected = RuntimeException.class) + public void testInvalidJson() { + String invalidJson = "{invalid: json}"; + json2Obj(invalidJson, String.class); + } + + class Node { + private String name; + private org.tron.common.utils.JsonUtilTest.Node next; + + public Node(String name) { + this.name = name; + } + + public void setNext(org.tron.common.utils.JsonUtilTest.Node next) { + this.next = next; + } } } diff --git a/framework/src/test/java/org/tron/common/utils/RandomGeneratorTest.java b/framework/src/test/java/org/tron/common/utils/RandomGeneratorTest.java index 7bc922661cb..4de441d940d 100644 --- a/framework/src/test/java/org/tron/common/utils/RandomGeneratorTest.java +++ b/framework/src/test/java/org/tron/common/utils/RandomGeneratorTest.java @@ -1,19 +1,42 @@ package org.tron.common.utils; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + import com.beust.jcommander.internal.Lists; import com.google.protobuf.ByteString; +import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.joda.time.DateTime; +import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.tron.core.capsule.WitnessCapsule; @Slf4j -@Ignore public class RandomGeneratorTest { + private RandomGenerator randomGenerator; + + @Before + public void setUp() { + randomGenerator = new RandomGenerator<>(); + } + + @Test + public void testShufflePreservesElements() { + List list = Arrays.asList(1, 2, 3, 4, 5); + List shuffledList = randomGenerator.shuffle(list, System.currentTimeMillis()); + + assertEquals(list.size(), shuffledList.size()); + for (Integer num : list) { + assertTrue(shuffledList.contains(num)); + } + } + + @Ignore @Test public void shuffle() { final List witnessCapsuleListBefore = this.getWitnessList(); diff --git a/framework/src/test/java/org/tron/common/utils/SetAdapterTest.java b/framework/src/test/java/org/tron/common/utils/SetAdapterTest.java new file mode 100644 index 00000000000..1d53ea3dd1a --- /dev/null +++ b/framework/src/test/java/org/tron/common/utils/SetAdapterTest.java @@ -0,0 +1,114 @@ +package org.tron.common.utils; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import org.junit.Before; +import org.junit.Test; + +public class SetAdapterTest { + + private Map delegate; + private SetAdapter setAdapter; + + @Before + public void setUp() { + delegate = new HashMap<>(); + setAdapter = new SetAdapter<>(delegate); + } + + @Test + public void testSizeInitiallyEmpty() { + assertEquals(0, setAdapter.size()); + } + + @Test + public void testIsEmptyInitially() { + assertTrue(setAdapter.isEmpty()); + } + + @Test + public void testContainsWhenEmpty() { + assertFalse(setAdapter.contains("test")); + } + + @Test + public void testAddAndGetSize() { + setAdapter.add("one"); + assertEquals(1, setAdapter.size()); + } + + @Test + public void testAddAndCheckContains() { + setAdapter.add("two"); + assertTrue(setAdapter.contains("two")); + } + + @Test + public void testRemoveAndCheckContains() { + setAdapter.add("three"); + assertTrue(setAdapter.contains("three")); + setAdapter.remove("three"); + assertFalse(setAdapter.contains("three")); + } + + @Test + public void testIterator() { + setAdapter.add("four"); + setAdapter.add("five"); + Set expected = new HashSet<>(Arrays.asList("four", "five")); + Set actual = new HashSet<>(setAdapter); // Convert to HashSet to ignore order + assertEquals(expected, actual); + } + + @Test + public void testToArray() { + setAdapter.add("six"); + setAdapter.add("seven"); + Object[] array = setAdapter.toArray(); + Arrays.sort(array); // Sorting to ignore order + assertArrayEquals(new String[]{"seven", "six"}, array); + } + + @Test + public void testToArrayWithGivenType() { + setAdapter.add("eight"); + String[] array = setAdapter.toArray(new String[0]); + Arrays.sort(array); // Sorting to ignore order + assertArrayEquals(new String[]{"eight"}, array); + } + + @Test + public void testAddAll() { + setAdapter.addAll(Arrays.asList("nine", "ten")); + assertTrue(setAdapter.containsAll(Arrays.asList("nine", "ten"))); + } + + @Test + public void testRemoveAll() { + setAdapter.addAll(Arrays.asList("eleven", "twelve")); + setAdapter.removeAll(Collections.singletonList("eleven")); + assertFalse(setAdapter.contains("eleven")); + assertTrue(setAdapter.contains("twelve")); + } + + @Test + public void testClear() { + setAdapter.addAll(Arrays.asList("thirteen", "fourteen")); + setAdapter.clear(); + assertTrue(setAdapter.isEmpty()); + } + + @Test(expected = RuntimeException.class) + public void testRetainAllThrowsException() { + setAdapter.retainAll(Collections.emptyList()); + } +} diff --git a/framework/src/test/java/org/tron/common/utils/Sha256HashTest.java b/framework/src/test/java/org/tron/common/utils/Sha256HashTest.java index 51745e96e92..0df72cc125d 100644 --- a/framework/src/test/java/org/tron/common/utils/Sha256HashTest.java +++ b/framework/src/test/java/org/tron/common/utils/Sha256HashTest.java @@ -1,8 +1,19 @@ package org.tron.common.utils; +import static java.nio.file.Files.createTempFile; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import ch.qos.logback.core.util.FileUtil; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.Arrays; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.IntStream; +import org.apache.commons.io.FileUtils; import org.junit.Assert; import org.junit.Test; import org.tron.common.parameter.CommonParameter; @@ -10,18 +21,37 @@ public class Sha256HashTest { @Test - public void testHash() { + public void testHash() throws IOException { //Example from https://github.com/tronprotocol/tips/blob/master/TWP-001.md byte[] input = ByteArray.fromHexString("A0E11973395042BA3C0B52B4CDF4E15EA77818F275"); byte[] hash0 = Sha256Hash.hash(CommonParameter .getInstance().isECKeyCryptoEngine(), input); byte[] hash1 = Sha256Hash.hash(CommonParameter .getInstance().isECKeyCryptoEngine(), hash0); - Assert.assertEquals(Arrays.toString(hash0), Arrays.toString(ByteArray + assertEquals(Arrays.toString(hash0), Arrays.toString(ByteArray .fromHexString("CD5D4A7E8BE869C00E17F8F7712F41DBE2DDBD4D8EC36A7280CD578863717084"))); - Assert.assertEquals(Arrays.toString(hash1), Arrays.toString(ByteArray + assertEquals(Arrays.toString(hash1), Arrays.toString(ByteArray .fromHexString("10AE21E887E8FE30C591A22A5F8BB20EB32B2A739486DC5F3810E00BBDB58C5C"))); + Sha256Hash sha256Hash = new Sha256Hash(1, new byte[32]); + assertNotNull(sha256Hash.toBigInteger()); + + Sha256Hash.create(true, ("byte1-1").getBytes(StandardCharsets.UTF_8)); + File testfile = createTempFile("testfile", ".txt").toFile(); + Sha256Hash.of(true, testfile); + Sha256Hash.createDouble(true, new byte[0]); + Sha256Hash.twiceOf(true, new byte[0]); + Sha256Hash.hashTwice(true, new byte[0]); + Sha256Hash.hashTwice(false, new byte[0]); + Sha256Hash.hashTwice(true, new byte[0], 0, 0); + Sha256Hash.hashTwice(false, new byte[0], 0, 0); + Sha256Hash.hash(false, new byte[0], 0, 0); + Sha256Hash.hashTwice(true, new byte[0], 0, 0, new byte[0], 0, 0); + Sha256Hash.hashTwice(false, new byte[0], 0, 0, new byte[0], 0, 0); + assertTrue(testfile.delete()); + + + } @Test @@ -51,7 +81,7 @@ public void testMultiThreadingHash() { e.printStackTrace(); } }); - Assert.assertEquals(70000, countAll.get()); - Assert.assertEquals(0, countFailed.get()); + assertEquals(70000, countAll.get()); + assertEquals(0, countFailed.get()); } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/common/utils/SlidingWindowCounterTest.java b/framework/src/test/java/org/tron/common/utils/SlidingWindowCounterTest.java new file mode 100644 index 00000000000..016b7ac611b --- /dev/null +++ b/framework/src/test/java/org/tron/common/utils/SlidingWindowCounterTest.java @@ -0,0 +1,63 @@ +package org.tron.common.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.Before; +import org.junit.Test; + +public class SlidingWindowCounterTest { + + private SlidingWindowCounter counter; + + @Before + public void setUp() { + counter = new SlidingWindowCounter(3); + } + + @Test + public void testIncrease() { + counter.increase(); + counter.increase(); + counter.increase(); + assertEquals(3, counter.totalCount()); + counter.resizeWindow(5); + assertNotNull(counter.toString()); + } + + @Test + public void testTotalAndAdvance() { + counter.increase(); + counter.increase(); + counter.advance(); + counter.increase(); + int total = counter.totalAndAdvance(); + assertEquals(3, total); + assertEquals(3, counter.totalCount()); + } + + @Test + public void testTotalCount() { + counter.increase(); + counter.increase(); + counter.advance(); + assertEquals(2, counter.totalCount()); + } + + @Test + public void testCircularWindow() { + for (int i = 0; i < 3; i++) { + counter.increase(); + } + counter.increase(); + counter.advance(); + assertEquals(4, counter.totalCount()); + + counter.increase(); + counter.increase(); + counter.increase(); + int total = counter.totalAndAdvance(); + assertEquals(7, total); + assertEquals(7, counter.totalCount()); + } +} diff --git a/framework/src/test/java/org/tron/common/utils/TypeConversionTest.java b/framework/src/test/java/org/tron/common/utils/TypeConversionTest.java index b9188e96060..c98115af3f0 100644 --- a/framework/src/test/java/org/tron/common/utils/TypeConversionTest.java +++ b/framework/src/test/java/org/tron/common/utils/TypeConversionTest.java @@ -17,9 +17,13 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; import static org.tron.common.utils.TypeConversion.bytesToHexString; import static org.tron.common.utils.TypeConversion.bytesToLong; import static org.tron.common.utils.TypeConversion.hexStringToBytes; +import static org.tron.common.utils.TypeConversion.increment; import static org.tron.common.utils.TypeConversion.longToBytes; import lombok.extern.slf4j.Slf4j; @@ -58,6 +62,14 @@ public void testHexStringToBytes() { //logger.info("hex string 7f to bytes is: {}", result); byte[] expected = new byte[]{127}; assertArrayEquals(expected, result); + assertNull(hexStringToBytes("test")); + } + @Test + public void testIncrementNormalCase() { + byte[] bytes = {1, 2, 3}; + boolean result = increment(bytes); + assertTrue(result); + assertArrayEquals(new byte[]{1, 2, 4}, bytes); } } diff --git a/framework/src/test/java/org/tron/common/utils/UtilsTest.java b/framework/src/test/java/org/tron/common/utils/UtilsTest.java new file mode 100644 index 00000000000..6a593a7684f --- /dev/null +++ b/framework/src/test/java/org/tron/common/utils/UtilsTest.java @@ -0,0 +1,74 @@ +package org.tron.common.utils; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; + +import java.nio.charset.Charset; +import java.security.SecureRandom; +import org.junit.Test; + +public class UtilsTest { + + @Test + public void testGetRandom() { + SecureRandom random = Utils.getRandom(); + assertNotNull("SecureRandom should not be null", random); + } + + @Test + public void testGetBytes() { + char[] chars = "hello".toCharArray(); + byte[] bytes = Utils.getBytes(chars); + + // Convert back to String to check if it's the same + String result = new String(bytes, Charset.forName("UTF-8")); + assertEquals("Converted bytes should match the original string", "hello", result); + } + + @Test + public void testGetIdShort() { + String longId = "12345678901234567890"; + String shortId = Utils.getIdShort(longId); + assertEquals("Short ID should be the first 8 characters of the long ID", "12345678", shortId); + + String nullId = Utils.getIdShort(null); + assertEquals("ID should be '' for null input", "", nullId); + } + + @Test + public void testClone() { + byte[] original = {1, 2, 3, 4, 5}; + byte[] clone = Utils.clone(original); + + assertArrayEquals("Clone should be equal to the original", original, clone); + + // Modify the clone to ensure it's a new array + clone[0] = 99; + assertNotEquals("Modifying the clone should not affect the original", original[0], clone[0]); + } + + @Test + public void testAlignLeft() { + String result = Utils.align("abc", '-', 10, false); + String result1 = Utils.align("abc", '-', 2, false); + assertEquals("abc-------", result); + assertEquals("abc", result1); + } + + @Test + public void testAlignRight() { + String result = Utils.align("abc", '-', 10, true); + assertEquals("-------abc", result); + } + + @Test + public void testRepeat() { + String result = Utils.repeat("a", 5); + assertEquals("aaaaa", result); + + result = Utils.repeat("abc", 3); + assertEquals("abcabcabc", result); + } +} diff --git a/framework/src/test/java/org/tron/common/utils/ValueTest.java b/framework/src/test/java/org/tron/common/utils/ValueTest.java new file mode 100644 index 00000000000..f7e4f415f5f --- /dev/null +++ b/framework/src/test/java/org/tron/common/utils/ValueTest.java @@ -0,0 +1,198 @@ +package org.tron.common.utils; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.tron.common.utils.ByteUtil.EMPTY_BYTE_ARRAY; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; +import org.bouncycastle.util.encoders.Hex; +import org.junit.Before; +import org.junit.Test; + +public class ValueTest { + + private Value value; + + @Before + public void setUp() { + value = new Value(); + value.init(new byte[100]); + } + + @Test + public void testAsObj() { + Object obj = new Object(); + value = new Value(obj); + assertEquals("asObj should return the encapsulated object", obj, value.asObj()); + } + + @Test + public void testAsList() { + Object[] array = { "element1", "element2" }; + value = new Value(array); + List list = value.asList(); + assertEquals(2, list.size()); + assertEquals("element1", list.get(0)); + } + + @Test + public void testAsInt() { + value = new Value(123); + assertEquals(123, value.asInt()); + assertEquals(0, new Value(new byte[0]).asInt()); + assertEquals(0, new Value("test").asInt()); + } + + @Test + public void testAsLong() { + value = new Value(123456789L); + assertEquals(123456789L, value.asLong()); + assertEquals(0L, new Value(new byte[0]).asLong()); + assertEquals(0L, new Value("TEST").asLong()); + } + + @Test + public void testAsBigInt() { + BigInteger bigInteger = new BigInteger("12345678901234567890"); + value = new Value(bigInteger); + assertEquals(bigInteger, value.asBigInt()); + } + + @Test + public void testAsString() { + value = new Value("test string"); + assertEquals("test string", value.asString()); + assertNotNull(new Value(new byte[0]).asString()); + assertEquals("", new Value(100).asString()); + assertNotNull(value.get(0)); + + } + + @Test + public void testAsBytes() { + byte[] bytes = { 0x01, 0x02, 0x03 }; + value = new Value(bytes); + assertArrayEquals("asBytes should return the correct byte array", bytes, value.asBytes()); + assertEquals(EMPTY_BYTE_ARRAY, new Value(100).asBytes()); + } + + @Test + public void testGet() { + List list = Arrays.asList("element1", "element2"); + value = new Value(list.toArray()); + Value element = value.get(0); + assertEquals("element1", element.asString()); + assertNotNull(value.get(2)); + } + + @Test(expected = Exception.class) + public void testGetNegativeIndex() { + value = new Value(new Object[] { "element1", "element2" }); + value.get(-1); + } + + @Test + public void testCmp() { + Value value1 = new Value("test"); + Value value2 = new Value("test"); + assertTrue("cmp should return true for equal values", value1.cmp(value2)); + } + + @Test + public void testIsList() { + value = new Value(new Object[] { "element1", "element2" }); + assertTrue("isList should return true for an array", value.isList()); + assertNotNull(value.toString()); + } + + @Test + public void testIsString() { + value = new Value("test string"); + assertTrue("isString should return true for a string", value.isString()); + } + + @Test + public void testIsInt() { + value = new Value(123); + assertTrue("isInt should return true for an integer", value.isInt()); + } + + @Test + public void testIsLong() { + value = new Value(123456789L); + assertTrue("isLong should return true for a long", value.isLong()); + } + + @Test + public void testIsBigInt() { + value = new Value(new BigInteger("12345678901234567890")); + assertTrue("isBigInt should return true for a BigInteger", value.isBigInt()); + } + + @Test + public void testIsBytes() { + byte[] bytes = { 0x01, 0x02, 0x03 }; + value = new Value(bytes); + assertTrue("isBytes should return true for a byte array", value.isBytes()); + } + + @Test + public void testIsReadableString() { + byte[] readableBytes = "Hello World".getBytes(); + value = new Value(readableBytes); + assertTrue(value.isReadableString()); + } + + @Test + public void testIsHexString() { + byte[] hexBytes = Hex.decode("48656c6c6f20576f726c64"); + value = new Value(hexBytes); + assertFalse("isHexString should return true for hex byte array", value.isHexString()); + } + + @Test + public void testIsHashCode() { + byte[] hashBytes = new byte[32]; + value = new Value(hashBytes); + assertTrue("isHashCode should return true for a 32 byte array", value.isHashCode()); + } + + @Test + public void testIsNull() { + value = new Value(null); + assertTrue("isNull should return true for null", value.isNull()); + } + + @Test + public void testIsEmpty() { + value = new Value(""); + assertTrue("isEmpty should return true for an empty string", value.isEmpty()); + } + + @Test + public void testLength() { + value = new Value("test string"); + assertEquals(11, value.length()); + } + + @Test + public void testToString() { + value = new Value("test string"); + assertEquals("test string", value.toString()); + } + + @Test + public void testCountBranchNodes() { + Object[] array = { new Value("element1"), new Value("element2") }; + value = new Value(array); + assertEquals(0, value.countBranchNodes()); + value = new Value(new byte[0]); + assertEquals(0, value.countBranchNodes()); + + } +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java b/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java index ee872be6330..5a085e16ca6 100644 --- a/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java @@ -4234,10 +4234,8 @@ public static HttpResponse sendShieldCoinWithoutAsk( public static void freedResource( String httpNode, byte[] fromAddress, byte[] toAddress, String fromKey) { long balance = HttpMethed.getBalance(httpNode, fromAddress); - // System.out.println("剩余资源:" + balance); sendCoin(httpNode, fromAddress, toAddress, balance - 50000, fromKey); balance = HttpMethed.getBalance(httpNode, fromAddress); - // System.out.println("之后资源:" + balance); } /** constructor. */ diff --git a/framework/src/test/java/org/tron/common/zksnark/ZksnarkClientTest.java b/framework/src/test/java/org/tron/common/zksnark/ZksnarkClientTest.java new file mode 100644 index 00000000000..21275d548a0 --- /dev/null +++ b/framework/src/test/java/org/tron/common/zksnark/ZksnarkClientTest.java @@ -0,0 +1,43 @@ +package org.tron.common.zksnark; + +import static org.junit.Assert.assertThrows; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import io.grpc.StatusRuntimeException; +import java.nio.charset.StandardCharsets; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.utils.ByteArray; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.contract.BalanceContract; + +public class ZksnarkClientTest { + + public ZksnarkClient zksnarkClient; + + @Before + public void setUp() { + zksnarkClient = ZksnarkClient.getInstance(); + } + + @Test + public void testCheckZksnarkProof() { + BalanceContract.TransferContract transferContract = + BalanceContract.TransferContract.newBuilder() + .setAmount(10) + .setOwnerAddress(ByteString.copyFromUtf8("aaa")) + .setToAddress(ByteString.copyFromUtf8("bbb")) + .build(); + Transaction transaction = Transaction.newBuilder().setRawData(Transaction.raw.newBuilder() + .setData(ByteString.copyFrom("transfer".getBytes(StandardCharsets.UTF_8))) + .addContract(Transaction.Contract.newBuilder().setParameter(Any.pack(transferContract)) + .setType(Transaction.Contract.ContractType.TransferContract))) + .addRet(Transaction.Result.newBuilder().setAssetIssueID("1234567").build()).build(); + byte[] b = ByteArray + .fromHexString("ded9c2181fd7ea468a7a7b1475defe90bb0fc0ca8d0f2096b0617465cea6568c"); + assertThrows(StatusRuntimeException.class, () -> zksnarkClient.checkZksnarkProof(transaction, b, + 10000L)); + } + +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/CoreExceptionTest.java b/framework/src/test/java/org/tron/core/CoreExceptionTest.java new file mode 100644 index 00000000000..89feaba338c --- /dev/null +++ b/framework/src/test/java/org/tron/core/CoreExceptionTest.java @@ -0,0 +1,1161 @@ +package org.tron.core; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.tron.core.exception.BadBlockException.TypeEnum.CALC_MERKLE_ROOT_FAILED; +import static org.tron.core.exception.BadBlockException.TypeEnum.DEFAULT; +import static org.tron.core.exception.P2pException.TypeEnum.NO_SUCH_MESSAGE; +import static org.tron.core.exception.P2pException.TypeEnum.PARSE_MESSAGE_FAILED; +import static org.tron.core.exception.P2pException.TypeEnum.SYNC_FAILED; + +import org.junit.Test; +import org.tron.common.error.TronDBException; +import org.tron.core.exception.AccountResourceInsufficientException; +import org.tron.core.exception.BadBlockException; +import org.tron.core.exception.BadItemException; +import org.tron.core.exception.BadNumberBlockException; +import org.tron.core.exception.BadTransactionException; +import org.tron.core.exception.BalanceInsufficientException; +import org.tron.core.exception.CancelException; +import org.tron.core.exception.CipherException; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractSizeNotEqualToOneException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.exception.DupTransactionException; +import org.tron.core.exception.EventBloomException; +import org.tron.core.exception.HeaderNotFound; +import org.tron.core.exception.HighFreqException; +import org.tron.core.exception.ItemNotFoundException; +import org.tron.core.exception.JsonRpcInternalException; +import org.tron.core.exception.JsonRpcInvalidParamsException; +import org.tron.core.exception.JsonRpcInvalidRequestException; +import org.tron.core.exception.JsonRpcMethodNotFoundException; +import org.tron.core.exception.JsonRpcTooManyResultException; +import org.tron.core.exception.NonCommonBlockException; +import org.tron.core.exception.NonUniqueObjectException; +import org.tron.core.exception.P2pException; +import org.tron.core.exception.PermissionException; +import org.tron.core.exception.ReceiptCheckErrException; +import org.tron.core.exception.RevokingStoreIllegalStateException; +import org.tron.core.exception.SignatureFormatException; +import org.tron.core.exception.StoreException; +import org.tron.core.exception.TaposException; +import org.tron.core.exception.TooBigTransactionException; +import org.tron.core.exception.TooBigTransactionResultException; +import org.tron.core.exception.TraitorPeerException; +import org.tron.core.exception.TransactionExpirationException; +import org.tron.core.exception.TronRuntimeException; +import org.tron.core.exception.TypeMismatchNamingException; +import org.tron.core.exception.UnLinkedBlockException; +import org.tron.core.exception.UnReachBlockException; +import org.tron.core.exception.VMIllegalException; +import org.tron.core.exception.ValidateScheduleException; +import org.tron.core.exception.ValidateSignatureException; +import org.tron.core.exception.ZkProofValidateException; +import org.tron.core.exception.ZksnarkException; + +public class CoreExceptionTest { + + @Test + public void testAccountResourceInsufficientExceptionMessage() { + String expectedMessage = "Account resources are insufficient"; + AccountResourceInsufficientException exception = + new AccountResourceInsufficientException(expectedMessage); + + assertEquals(expectedMessage, exception.getMessage()); + } + + @Test + public void testBadBlockExceptionWithNoMessageAndDefaultType() { + BadBlockException exception = new BadBlockException(); + + assertNull(exception.getMessage()); + + assertEquals(DEFAULT, exception.getType()); + } + + @Test + public void testBadBlockExceptionWithMessageAndDefaultType() { + String testMessage = "Block is bad due to some reason"; + + BadBlockException exception = new BadBlockException(testMessage); + + assertEquals(testMessage, exception.getMessage()); + + assertEquals(DEFAULT, exception.getType()); + } + + @Test + public void testBadBlockExceptionWithSpecificTypeAndMessage() { + String testMessage = "Failed to calculate Merkle root"; + + BadBlockException exception = new BadBlockException(CALC_MERKLE_ROOT_FAILED, testMessage); + + assertEquals(testMessage, exception.getMessage()); + + assertEquals(CALC_MERKLE_ROOT_FAILED, exception.getType()); + } + + @Test + public void testTypeEnumValues() { + assertEquals(Integer.valueOf(1), CALC_MERKLE_ROOT_FAILED.getValue()); + + assertEquals(Integer.valueOf(100), DEFAULT.getValue()); + } + + @Test + public void testBadItemExceptionDefaultConstructor() { + BadItemException exception = new BadItemException(); + assertNotNull(exception); + } + + @Test + public void testBadItemExceptionMessageConstructor() { + String expectedMessage = "This item is bad!"; + BadItemException exception = new BadItemException(expectedMessage); + assertEquals(expectedMessage, exception.getMessage()); + assertNull(exception.getCause()); + assertNotNull(exception); + } + + @Test + public void testBadItemExceptionMessageAndCauseConstructor() { + String expectedMessage = "This item is really bad!"; + Throwable expectedCause = new Throwable("Some underlying cause"); + BadItemException exception = new BadItemException(expectedMessage, expectedCause); + assertEquals(expectedMessage, exception.getMessage()); + assertEquals(expectedCause, exception.getCause()); + assertNotNull(exception); + } + + @Test + public void testBadNumberBlockExceptionDefaultConstructor() { + BadNumberBlockException exception = new BadNumberBlockException(); + assertNull(exception.getMessage()); + assertNotNull(exception); + } + + @Test + public void testBadNumberBlockExceptionMessageConstructor() { + String expectedMessage = "Number block is bad!"; + BadNumberBlockException exception = new BadNumberBlockException(expectedMessage); + assertEquals(expectedMessage, exception.getMessage()); + assertNotNull(exception); + } + + @Test + public void testBadTransactionExceptionDefaultConstructor() { + BadTransactionException exception = new BadTransactionException(); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + assertNotNull(exception); + } + + @Test + public void testBadTransactionExceptionMessageConstructor() { + String expectedMessage = "Transaction is bad!"; + BadTransactionException exception = new BadTransactionException(expectedMessage); + + assertEquals(expectedMessage, exception.getMessage()); + + assertNull(exception.getCause()); + + assertNotNull(exception); + } + + @Test + public void testBadTransactionExceptionMessageAndCauseConstructor() { + String expectedMessage = "Transaction failed due to an error"; + Throwable cause = new IllegalArgumentException("Invalid transaction data"); + + BadTransactionException exception = new BadTransactionException(expectedMessage, cause); + + assertEquals(expectedMessage, exception.getMessage()); + + assertEquals(cause, exception.getCause()); + + assertNotNull(exception); + } + + @Test + public void testBalanceInsufficientExceptionWithNoMessage() { + BalanceInsufficientException exception = new BalanceInsufficientException(); + assertNull(exception.getMessage()); + } + + @Test + public void testBalanceInsufficientExceptionWithMessage() { + String testMessage = "Balance is insufficient for this transaction"; + BalanceInsufficientException exception = new BalanceInsufficientException(testMessage); + assertEquals(testMessage, exception.getMessage()); + } + + @Test + public void testCancelExceptionWithNoMessage() { + CancelException exception = new CancelException(); + + assertNull(exception.getMessage()); + } + + @Test + public void testCancelExceptionWithMessage() { + String testMessage = "Operation canceled by user"; + + CancelException exception = new CancelException(testMessage); + + assertEquals(testMessage, exception.getMessage()); + } + + @Test + public void testCipherExceptionWithMessage() { + String testMessage = "Cipher operation failed"; + + CipherException exception = new CipherException(testMessage); + + assertEquals(testMessage, exception.getMessage()); + + assertNull(exception.getCause()); + } + + @Test + public void testCipherExceptionWithCause() { + Throwable testCause = new Throwable("Underlying error"); + + CipherException exception = new CipherException(testCause); + + assertSame(testCause, exception.getCause()); + + } + + @Test + public void testCipherExceptionWithMessageAndCause() { + String testMessage = "Cipher operation failed due to error"; + + Throwable testCause = new Throwable("Underlying error"); + CipherException exception = new CipherException(testMessage, testCause); + + assertEquals(testMessage, exception.getMessage()); + + assertSame(testCause, exception.getCause()); + } + + @Test + public void testContractExeExceptionWithNoMessage() { + ContractExeException exception = new ContractExeException(); + + assertNull(exception.getMessage()); + } + + @Test + public void testContractExeExceptionWithMessage() { + String testMessage = "Contract execution failed"; + + ContractExeException exception = new ContractExeException(testMessage); + + assertEquals(testMessage, exception.getMessage()); + } + + @Test + public void testContractSizeNotEqualToOneExceptionWithNoMessage() { + ContractSizeNotEqualToOneException exception = new ContractSizeNotEqualToOneException(); + + assertNull(exception.getMessage()); + } + + @Test + public void testContractSizeNotEqualToOneExceptionWithMessage() { + String testMessage = "Contract size is not equal to one"; + + ContractSizeNotEqualToOneException exception = + new ContractSizeNotEqualToOneException(testMessage); + + assertEquals(testMessage, exception.getMessage()); + } + + @Test + public void testContractValidateExceptionWithNoMessageOrThrowable() { + ContractValidateException exception = new ContractValidateException(); + + assertNull(exception.getMessage()); + + assertNull(exception.getCause()); + } + + @Test + public void testContractValidateExceptionWithMessage() { + String testMessage = "Contract validation failed"; + + ContractValidateException exception = new ContractValidateException(testMessage); + + assertEquals(testMessage, exception.getMessage()); + + assertNull(exception.getCause()); + } + + @Test + public void testContractValidateExceptionWithMessageAndThrowable() { + String testMessage = "Contract validation failed due to internal error"; + + Throwable cause = new RuntimeException("Internal error"); + + ContractValidateException exception = new ContractValidateException(testMessage, cause); + + assertEquals(testMessage, exception.getMessage()); + + assertSame(cause, exception.getCause()); + } + + @Test + public void testDupTransactionExceptionDefaultConstructor() { + DupTransactionException exception = new DupTransactionException(); + + assertNotNull(exception); + + } + + @Test + public void testDupTransactionExceptionMessageConstructor() { + String testMessage = "Duplicate Transaction Exception"; + DupTransactionException exception = new DupTransactionException(testMessage); + + assertNotNull(exception); + + assertEquals(testMessage, exception.getMessage()); + } + + @Test + public void testEventBloomExceptionDefaultConstructor() { + EventBloomException exception = new EventBloomException(); + + assertNotNull(exception); + + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testEventBloomExceptionMessageConstructor() { + String testMessage = "Event Bloom Exception occurred"; + EventBloomException exception = new EventBloomException(testMessage); + + assertNotNull(exception); + + assertEquals(testMessage, exception.getMessage()); + + assertNull(exception.getCause()); + } + + @Test + public void testEventBloomExceptionMessageAndCauseConstructor() { + String testMessage = "Event Bloom Exception with cause"; + Throwable testCause = new Throwable("Root cause"); + EventBloomException exception = new EventBloomException(testMessage, testCause); + + assertNotNull(exception); + + assertEquals(testMessage, exception.getMessage()); + + assertEquals(testCause, exception.getCause()); + } + + @Test + public void testHeaderNotFoundDefaultConstructor() { + HeaderNotFound exception = new HeaderNotFound(); + + assertNotNull(exception); + + assertNull(exception.getMessage()); + } + + @Test + public void testHeaderNotFoundMessageConstructor() { + String testMessage = "Header not found"; + HeaderNotFound exception = new HeaderNotFound(testMessage); + + assertNotNull(exception); + + assertEquals(testMessage, exception.getMessage()); + } + + @Test + public void testHighFreqExceptionDefaultConstructor() { + HighFreqException exception = new HighFreqException(); + + assertNotNull("Exception object should not be null", exception); + + assertNull("Exception message should be null", exception.getMessage()); + } + + @Test + public void testHighFreqExceptionMessageConstructor() { + String testMessage = "High frequency error occurred"; + HighFreqException exception = new HighFreqException(testMessage); + + assertNotNull("Exception object should not be null", exception); + + assertEquals("Exception message should match the provided message", + testMessage, exception.getMessage()); + } + + @Test + public void testItemNotFoundExceptionWithMessage() { + String testMessage = "Item not found"; + ItemNotFoundException exception = new ItemNotFoundException(testMessage); + + assertNotNull("Exception object should not be null", exception); + assertEquals("Exception message should match the provided message", testMessage, + exception.getMessage()); + assertNull("Cause should be null when not provided", exception.getCause()); + } + + @Test + public void testItemNotFoundExceptionDefaultConstructor() { + ItemNotFoundException exception = new ItemNotFoundException(); + + assertNotNull("Exception object should not be null", exception); + assertNull("Exception message should be null when no message is provided", + exception.getMessage()); + assertNull("Cause should be null when not provided", exception.getCause()); + } + + @Test + public void testItemNotFoundExceptionWithMessageAndCause() { + String testMessage = "Item not found in database"; + Throwable testCause = new Throwable("Database error"); + ItemNotFoundException exception = new ItemNotFoundException(testMessage, testCause); + + assertNotNull("Exception object should not be null", exception); + assertEquals("Exception message should match the provided message", + testMessage, exception.getMessage()); + assertEquals("Cause should match the provided Throwable", testCause, exception.getCause()); + } + + @Test + public void testJsonRpcInternalExceptionDefaultConstructor() { + JsonRpcInternalException exception = new JsonRpcInternalException(); + + assertNotNull("Exception object should not be null", exception); + assertNull("Exception message should be null when no message is provided", + exception.getMessage()); + assertNull("Cause should be null when not provided", exception.getCause()); + } + + @Test + public void testJsonRpcInternalExceptionWithMessage() { + String testMessage = "Internal JSON-RPC error occurred"; + JsonRpcInternalException exception = new JsonRpcInternalException(testMessage); + + assertNotNull("Exception object should not be null", exception); + assertEquals("Exception message should match the provided message", testMessage, + exception.getMessage()); + assertNull("Cause should be null when not provided", exception.getCause()); + } + + @Test + public void testJsonRpcInternalExceptionWithMessageAndCause() { + String testMessage = "Internal JSON-RPC processing failed"; + Throwable testCause = new Throwable("Underlying system error"); + JsonRpcInternalException exception = new JsonRpcInternalException(testMessage, testCause); + + assertNotNull("Exception object should not be null", exception); + assertEquals("Exception message should match the provided message", + testMessage, exception.getMessage()); + assertEquals("Cause should match the provided Throwable", testCause, exception.getCause()); + } + + @Test + public void testJsonRpcInvalidParamsExceptionDefaultConstructor() { + JsonRpcInvalidParamsException exception = new JsonRpcInvalidParamsException(); + + assertNotNull("Exception object should not be null", exception); + assertNull("Exception message should be null when no message is provided", + exception.getMessage()); + assertNull("Cause should be null when not provided", exception.getCause()); + } + + @Test + public void testJsonRpcInvalidParamsExceptionWithMessage() { + String testMessage = "Invalid parameters provided"; + JsonRpcInvalidParamsException exception = new JsonRpcInvalidParamsException(testMessage); + + assertNotNull("Exception object should not be null", exception); + assertEquals("Exception message should match the provided message", + testMessage, exception.getMessage()); + assertNull("Cause should be null when not provided", exception.getCause()); + } + + @Test + public void testJsonRpcInvalidParamsExceptionWithMessageAndCause() { + String testMessage = "Parameter validation failed"; + Throwable testCause = new Throwable("Underlying validation error"); + JsonRpcInvalidParamsException e = new JsonRpcInvalidParamsException(testMessage, testCause); + + assertNotNull("Exception object should not be null", e); + assertEquals("Exception message should match the provided message", testMessage, + e.getMessage()); + assertEquals("Cause should match the provided Throwable", testCause, e.getCause()); + } + + @Test + public void testJsonRpcInvalidRequestExceptionDefaultConstructor() { + JsonRpcInvalidRequestException exception = new JsonRpcInvalidRequestException(); + assertNotNull(exception); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testJsonRpcInvalidRequestExceptionConstructorWithMessage() { + String testMessage = "Invalid JSON-RPC request"; + JsonRpcInvalidRequestException exception = new JsonRpcInvalidRequestException(testMessage); + assertNotNull(exception); + assertEquals(testMessage, exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testJsonRpcInvalidRequestExceptionConstructorWithMessageAndCause() { + String testMessage = "Invalid JSON-RPC request with cause"; + Throwable testCause = new Throwable("Root cause"); + JsonRpcInvalidRequestException e = new JsonRpcInvalidRequestException(testMessage, testCause); + assertNotNull(e); + assertEquals(testMessage, e.getMessage()); + assertEquals(testCause, e.getCause()); + } + + @Test + public void testJsonRpcMethodNotFoundExceptionDefaultConstructor() { + JsonRpcMethodNotFoundException exception = new JsonRpcMethodNotFoundException(); + assertNotNull(exception); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testJsonRpcMethodNotFoundExceptionConstructorWithMessage() { + String testMessage = "JSON-RPC method not found"; + JsonRpcMethodNotFoundException exception = new JsonRpcMethodNotFoundException(testMessage); + assertNotNull(exception); + assertEquals(testMessage, exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testJsonRpcMethodNotFoundExceptionConstructorWithMessageAndCause() { + String testMessage = "JSON-RPC method not found with cause"; + Throwable testCause = new Throwable("Root cause"); + JsonRpcMethodNotFoundException e = new JsonRpcMethodNotFoundException(testMessage, testCause); + assertNotNull(e); + assertEquals(testMessage, e.getMessage()); + assertEquals(testCause, e.getCause()); + } + + @Test + public void testJsonRpcTooManyResultExceptionDefaultConstructor() { + JsonRpcTooManyResultException exception = new JsonRpcTooManyResultException(); + assertNotNull("Exception object should not be null", exception); + assertNull(exception.getMessage()); + assertNull("Cause should be null for default constructor", exception.getCause()); + } + + @Test + public void testJsonRpcTooManyResultExceptionWithMessage() { + String testMessage = "Too many results returned by JSON-RPC method"; + JsonRpcTooManyResultException exception = new JsonRpcTooManyResultException(testMessage); + assertNotNull("Exception object should not be null", exception); + assertEquals("Message should match the provided message", testMessage, exception.getMessage()); + assertNull("Cause should be null when only message is provided", exception.getCause()); + } + + @Test + public void testJsonRpcTooManyResultExceptionWithMessageAndCause() { + String testMessage = "Too many results returned with cause"; + Throwable testCause = new Throwable("Root cause"); + JsonRpcTooManyResultException e = new JsonRpcTooManyResultException(testMessage, testCause); + assertNotNull("Exception object should not be null", e); + assertEquals("Message should match the provided message", testMessage, e.getMessage()); + assertEquals("Cause should match the provided cause", testCause, e.getCause()); + } + + @Test + public void testNonCommonBlockExceptionDefaultConstructor() { + NonCommonBlockException exception = new NonCommonBlockException(); + assertNotNull("Exception object should not be null", exception); + assertNull("Message should be null for default constructor", exception.getMessage()); + assertNull("Cause should be null for default constructor", exception.getCause()); + } + + @Test + public void testNonCommonBlockExceptionWithMessage() { + String testMessage = "Block is not common"; + NonCommonBlockException exception = new NonCommonBlockException(testMessage); + assertNotNull("Exception object should not be null", exception); + assertEquals("Message should match the provided message", testMessage, exception.getMessage()); + assertNull("Cause should be null when only message is provided", exception.getCause()); + } + + @Test + public void testNonCommonBlockExceptionWithMessageAndCause() { + String testMessage = "Block is not common due to some error"; + Throwable testCause = new Throwable("Root cause of the error"); + NonCommonBlockException exception = new NonCommonBlockException(testMessage, testCause); + assertNotNull("Exception object should not be null", exception); + assertEquals("Message should match the provided message", testMessage, exception.getMessage()); + assertEquals("Cause should match the provided cause", testCause, exception.getCause()); + } + + @Test + public void testDefaultConstructor() { + NonUniqueObjectException exception = new NonUniqueObjectException(); + assertNotNull("Exception object should not be null", exception); + assertNull("Message should be null for default constructor", exception.getMessage()); + assertNull("Cause should be null for default constructor", exception.getCause()); + } + + @Test + public void testConstructorWithMessage() { + String testMessage = "Object is not unique"; + NonUniqueObjectException exception = new NonUniqueObjectException(testMessage); + assertNotNull("Exception object should not be null", exception); + assertEquals("Message should match the provided message", testMessage, exception.getMessage()); + assertNull("Cause should be null when only message is provided", exception.getCause()); + } + + @Test + public void testConstructorWithMessageAndCause() { + String testMessage = "Object is not unique due to a conflict"; + Throwable testCause = new Throwable("Conflict error"); + NonUniqueObjectException exception = new NonUniqueObjectException(testMessage, testCause); + assertNotNull("Exception object should not be null", exception); + assertEquals("Message should match the provided message", testMessage, exception.getMessage()); + assertEquals("Cause should match the provided cause", testCause, exception.getCause()); + } + + @Test + public void testConstructorWithCauseOnly() { + Throwable testCause = new Throwable("Root cause of non-uniqueness"); + NonUniqueObjectException exception = new NonUniqueObjectException(testCause); + assertNotNull("Exception object should not be null", exception); + assertEquals("Message should be empty string when only cause is provided", "", + exception.getMessage()); + assertEquals("Cause should match the provided cause", testCause, exception.getCause()); + } + + @Test + public void testConstructorWithTypeEnumAndErrMsg() { + P2pException exception = new P2pException(NO_SUCH_MESSAGE, "Test error message"); + assertNotNull("Exception should not be null", exception); + assertEquals("Error message should match", "Test error message", exception.getMessage()); + assertEquals("Exception type should be NO_SUCH_MESSAGE", NO_SUCH_MESSAGE, exception.getType()); + } + + @Test + public void testConstructorWithTypeEnumAndThrowable() { + Throwable cause = new Throwable("Cause of the error"); + P2pException exception = new P2pException(PARSE_MESSAGE_FAILED, cause); + assertNotNull("Exception should not be null", exception); + assertEquals("Cause should match", cause, exception.getCause()); + } + + @Test + public void testConstructorWithTypeEnumErrMsgAndThrowable() { + Throwable cause = new Throwable("Cause of the error"); + P2pException exception = new P2pException(SYNC_FAILED, "Test error message", cause); + assertNotNull("Exception should not be null", exception); + assertEquals("Error message should match", + "Test error message", exception.getMessage()); + assertEquals("Cause should match", cause, exception.getCause()); + assertEquals("Exception type should be SYNC_FAILED", SYNC_FAILED, exception.getType()); + } + + @Test + public void testP2pExceptionTypeEnumValues() { + assertNotNull(NO_SUCH_MESSAGE.toString()); + assertEquals("NO_SUCH_MESSAGE value should be 1", + Integer.valueOf(1), NO_SUCH_MESSAGE.getValue()); + assertEquals("NO_SUCH_MESSAGE desc should be 'no such message'", + "no such message", NO_SUCH_MESSAGE.getDesc()); + + assertEquals("DEFAULT value should be 100", Integer.valueOf(100), + P2pException.TypeEnum.DEFAULT.getValue()); + assertEquals("DEFAULT desc should be 'default exception'", + "default exception", P2pException.TypeEnum.DEFAULT.getDesc()); + } + + @Test + public void testPermissionExceptionDefaultConstructor() { + PermissionException exception = new PermissionException(); + assertNotNull(exception); + } + + @Test + public void testPermissionExceptionWithMessage() { + String errorMessage = "You do not have sufficient permissions to perform this operation"; + PermissionException exception = new PermissionException(errorMessage); + assertNotNull(exception); + assertEquals(errorMessage, exception.getMessage()); + } + + @Test + public void testReceiptCheckErrExceptionDefaultConstructor() { + ReceiptCheckErrException exception = new ReceiptCheckErrException(); + assertNotNull("Exception object should not be null", exception); + assertNull("Message should be null for default constructor", exception.getMessage()); + assertNull("Cause should be null for default constructor", exception.getCause()); + } + + @Test + public void testReceiptCheckErrExceptionConstructorWithMessage() { + String errorMessage = "Receipt check failed due to invalid data"; + ReceiptCheckErrException exception = new ReceiptCheckErrException(errorMessage); + assertNotNull("Exception object should not be null", exception); + assertEquals("Message should match the input message", errorMessage, exception.getMessage()); + assertNull("Cause should be null when only message is provided", exception.getCause()); + } + + @Test + public void testReceiptCheckErrExceptionConstructorWithMessageAndCause() { + String errorMessage = "Receipt check error"; + Throwable cause = new Throwable("Underlying database error"); + ReceiptCheckErrException exception = new ReceiptCheckErrException(errorMessage, cause); + assertNotNull("Exception object should not be null", exception); + assertEquals("Message should match the input message", errorMessage, exception.getMessage()); + assertEquals("Cause should match the input cause", cause, exception.getCause()); + } + + @Test + public void testRevokingStoreIllegalStateExceptionDefaultConstructor() { + RevokingStoreIllegalStateException exception = new RevokingStoreIllegalStateException(); + assertNotNull("Exception should not be null", exception); + assertNull("Message should be null", exception.getMessage()); + assertNull("Cause should be null", exception.getCause()); + } + + @Test + public void testRevokingStoreIllegalStateExceptionConstructorWithMessage() { + String errorMessage = "Invalid state for revoking store"; + RevokingStoreIllegalStateException e = new RevokingStoreIllegalStateException(errorMessage); + assertNotNull("Exception should not be null", e); + assertEquals("Message should match the input message", errorMessage, e.getMessage()); + assertNull("Cause should be null", e.getCause()); + } + + @Test + public void testRevokingStoreIllegalStateExceptionConstructorWithMessageAndCause() { + String errorMessage = "Error occurred during revocation"; + Throwable cause = new Throwable("Database connection failed"); + RevokingStoreIllegalStateException e = + new RevokingStoreIllegalStateException(errorMessage, cause); + assertNotNull("Exception should not be null", e); + assertEquals("Message should match the input message", errorMessage, e.getMessage()); + assertEquals("Cause should match the input cause", cause, e.getCause()); + } + + @Test + public void testRevokingStoreIllegalStateExceptionConstructorWithCauseOnly() { + Throwable cause = new Throwable("Unknown error"); + RevokingStoreIllegalStateException exception = new RevokingStoreIllegalStateException(cause); + assertNotNull("Exception should not be null", exception); + assertEquals("Message should be empty string", "", exception.getMessage()); + assertEquals("Cause should match the input cause", cause, exception.getCause()); + } + + @Test + public void testRevokingStoreIllegalStateExceptionConstructorWithActiveSession() { + int activeSession = 0; + RevokingStoreIllegalStateException e = new RevokingStoreIllegalStateException(activeSession); + assertNotNull("Exception should not be null", e); + assertEquals("Message should indicate activeSession is not greater than 0", + "activeSession 0 has to be greater than 0", e.getMessage()); + } + + @Test + public void testSignatureFormatExceptionDefaultConstructor() { + SignatureFormatException exception = new SignatureFormatException(); + assertNotNull("Exception should not be null", exception); + assertNull("Message should be null", exception.getMessage()); + } + + @Test + public void testSignatureFormatExceptionWithMessage() { + String errorMessage = "Invalid signature format"; + SignatureFormatException exception = new SignatureFormatException(errorMessage); + assertNotNull("Exception should not be null", exception); + assertEquals("Message should match the provided error message", + errorMessage, exception.getMessage()); + } + + @Test + public void testStoreExceptionDefaultConstructor() { + StoreException exception = new StoreException(); + assertNotNull("Exception should not be null", exception); + assertNull("Message should be null", exception.getMessage()); + assertNull("Cause should be null", exception.getCause()); + } + + @Test + public void testStoreExceptionWithMessage() { + String errorMessage = "Store error occurred"; + StoreException exception = new StoreException(errorMessage); + assertNotNull("Exception should not be null", exception); + assertEquals("Message should match the provided error message", + errorMessage, exception.getMessage()); + assertNull("Cause should be null", exception.getCause()); + } + + @Test + public void testStoreExceptionWithMessageAndCause() { + String errorMessage = "Store error occurred"; + Throwable cause = new Throwable("Root cause"); + StoreException exception = new StoreException(errorMessage, cause); + assertNotNull("Exception should not be null", exception); + assertEquals("Message should match the provided error message", + errorMessage, exception.getMessage()); + assertEquals("Cause should match the provided cause", cause, exception.getCause()); + } + + @Test + public void testStoreExceptionWithCause() { + Throwable cause = new Throwable("Root cause"); + StoreException exception = new StoreException(cause); + assertNotNull("Exception should not be null", exception); + } + + + @Test + public void testTaposExceptionDefaultConstructor() { + TaposException exception = new TaposException(); + assertNotNull(exception); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testTaposExceptionWithMessage() { + String errorMessage = "Tapos error occurred"; + TaposException exception = new TaposException(errorMessage); + assertNotNull(exception); + assertEquals(errorMessage, exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testTaposExceptionWithMessageAndCause() { + String errorMessage = "Tapos error occurred"; + Throwable cause = new Throwable("Root cause"); + TaposException exception = new TaposException(errorMessage, cause); + assertNotNull(exception); + assertEquals(errorMessage, exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + + @Test + public void testTooBigTransactionExceptionDefaultConstructor() { + TooBigTransactionException exception = new TooBigTransactionException(); + assertNotNull(exception); + assertNull(exception.getMessage()); + } + + @Test + public void testTooBigTransactionExceptionWithMessage() { + String errorMessage = "Transaction is too big"; + TooBigTransactionException exception = new TooBigTransactionException(errorMessage); + assertNotNull(exception); + assertEquals(errorMessage, exception.getMessage()); + } + + @Test + public void testTooBigTransactionResultExceptionDefaultConstructor() { + TooBigTransactionResultException exception = new TooBigTransactionResultException(); + assertNotNull(exception); + assertEquals("too big transaction result", + exception.getMessage()); + } + + @Test + public void testTooBigTransactionResultExceptionWithMessage() { + String customMessage = "Custom error message for too big transaction result"; + TooBigTransactionResultException e = new TooBigTransactionResultException(customMessage); + assertNotNull(e); + assertEquals(customMessage, e.getMessage()); + } + + @Test + public void testTraitorPeerExceptionDefaultConstructor() { + TraitorPeerException exception = new TraitorPeerException(); + assertNotNull(exception); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testTraitorPeerExceptionWithMessage() { + String errorMessage = "Peer is a traitor"; + TraitorPeerException exception = new TraitorPeerException(errorMessage); + assertNotNull(exception); + assertEquals(errorMessage, exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testTraitorPeerExceptionWithMessageAndCause() { + String errorMessage = "Peer is a traitor and caused an error"; + Throwable cause = new Throwable("Underlying cause"); + TraitorPeerException exception = new TraitorPeerException(errorMessage, cause); + assertNotNull(exception); + assertEquals(errorMessage, exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + + @Test + public void testTransactionExpirationExceptionDefaultConstructor() { + TransactionExpirationException exception = new TransactionExpirationException(); + assertNotNull(exception); + assertNull(exception.getMessage()); + } + + @Test + public void testTransactionExpirationExceptionWithMessage() { + String errorMessage = "Transaction has expired"; + TransactionExpirationException exception = new TransactionExpirationException(errorMessage); + assertNotNull(exception); + assertEquals(errorMessage, exception.getMessage()); + } + + @Test + public void testTronRuntimeExceptionDefaultConstructor() { + TronRuntimeException exception = new TronRuntimeException(); + assertNotNull(exception); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testTronRuntimeExceptionWithMessage() { + String errorMessage = "An error occurred"; + TronRuntimeException exception = new TronRuntimeException(errorMessage); + assertNotNull(exception); + assertEquals(errorMessage, exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testTronRuntimeExceptionWithMessageAndCause() { + String errorMessage = "An error occurred due to a cause"; + Throwable cause = new Throwable("Underlying cause"); + TronRuntimeException exception = new TronRuntimeException(errorMessage, cause); + assertNotNull(exception); + assertEquals(errorMessage, exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + + @Test + public void testTronRuntimeExceptionWithCause() { + Throwable cause = new Throwable("Underlying cause without message"); + TronRuntimeException exception = new TronRuntimeException(cause); + assertEquals(cause, exception.getCause()); + } + + @Test + public void testTypeMismatchNamingException_WithRequiredAndActualTypes() { + try { + throw new TypeMismatchNamingException("someName", String.class, Integer.class); + } catch (TypeMismatchNamingException e) { + assertEquals("Object of type [class java.lang.Integer] available at store location " + + "[someName] is not assignable to [java.lang.String]", e.getMessage()); + assertEquals(String.class, e.getRequiredType()); + assertEquals(Integer.class, e.getActualType()); + } + } + + @Test + public void testTypeMismatchNamingException_WithExplanation() { + try { + throw new TypeMismatchNamingException("Custom explanation"); + } catch (TypeMismatchNamingException e) { + assertEquals("Custom explanation", e.getMessage()); + assertNull(e.getRequiredType()); + assertNull(e.getActualType()); + } + } + + @Test + public void testUnLinkedBlockExceptionDefaultConstructor() { + UnLinkedBlockException exception = new UnLinkedBlockException(); + assertNotNull("Exception should not be null", exception); + assertNull(exception.getMessage()); + assertNull("Cause should be null", exception.getCause()); + } + + @Test + public void testUnLinkedBlockExceptionWithMessage() { + String testMessage = "This block is not linked"; + UnLinkedBlockException exception = new UnLinkedBlockException(testMessage); + assertNotNull("Exception should not be null", exception); + assertEquals("Message should match", testMessage, exception.getMessage()); + assertNull("Cause should be null", exception.getCause()); + } + + @Test + public void testUnLinkedBlockExceptionWithMessageAndCause() { + String testMessage = "This block is not linked due to an error"; + Throwable testCause = new Throwable("Cause of the error"); + UnLinkedBlockException exception = new UnLinkedBlockException(testMessage, testCause); + assertNotNull("Exception should not be null", exception); + assertEquals("Message should match", testMessage, exception.getMessage()); + assertEquals("Cause should match", testCause, exception.getCause()); + } + + @Test + public void testUnReachBlockExceptionDefaultConstructor() { + UnReachBlockException exception = new UnReachBlockException(); + assertNotNull(exception); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testUnReachBlockExceptionWithMessage() { + String testMessage = "Block is unreachable"; + UnReachBlockException exception = new UnReachBlockException(testMessage); + assertNotNull(exception); + assertEquals(testMessage, exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testUnReachBlockExceptionWithMessageAndCause() { + String testMessage = "Block is unreachable due to an error"; + Throwable testCause = new Throwable("Cause of the error"); + UnReachBlockException exception = new UnReachBlockException(testMessage, testCause); + assertNotNull(exception); + assertEquals(testCause, exception.getCause()); + } + + @Test + public void testValidateScheduleExceptionDefaultConstructor() { + ValidateScheduleException exception = new ValidateScheduleException(); + + assertNotNull(exception); + + assertNull(exception.getMessage()); + } + + @Test + public void testValidateScheduleExceptionConstructorWithMessage() { + String testMessage = "Schedule validation failed"; + + ValidateScheduleException exception = new ValidateScheduleException(testMessage); + + assertNotNull(exception); + + assertEquals(testMessage, exception.getMessage()); + } + + @Test + public void testValidateSignatureExceptionDefaultConstructor() { + ValidateSignatureException exception = new ValidateSignatureException(); + assertNotNull("Exception should not be null", exception); + assertNull(exception.getMessage()); + } + + @Test + public void testValidateSignatureExceptionConstructorWithMessage() { + String testMessage = "Signature validation failed"; + ValidateSignatureException exception = new ValidateSignatureException(testMessage); + assertNotNull("Exception should not be null", exception); + assertEquals("Message should match", testMessage, exception.getMessage()); + } + + @Test + public void testVMIllegalExceptionDefaultConstructor() { + VMIllegalException exception = new VMIllegalException(); + assertNotNull("Exception should not be null", exception); + assertNull(exception.getMessage()); + } + + @Test + public void testVMIllegalExceptionConstructorWithMessage() { + String testMessage = "VM operation is illegal"; + VMIllegalException exception = new VMIllegalException(testMessage); + assertNotNull("Exception should not be null", exception); + assertEquals("Message should match", testMessage, exception.getMessage()); + } + + @Test + public void testZkProofValidateExceptionWithFirstValidatedTrue() { + String testMessage = "Zero-knowledge proof validation failed, but first part was validated"; + boolean firstValidated = true; + + ZkProofValidateException exception = new ZkProofValidateException(testMessage, firstValidated); + + assertNotNull("Exception should not be null", exception); + assertEquals("Message should match", testMessage, exception.getMessage()); + assertTrue("firstValidated should be true", exception.isFirstValidated()); + } + + @Test + public void testZkProofValidateExceptionWithFirstValidatedFalse() { + String testMessage = "Zero-knowledge proof validation failed, first part not validated"; + boolean firstValidated = false; + + ZkProofValidateException exception = new ZkProofValidateException(testMessage, firstValidated); + exception.setFirstValidated(true); + assertNotNull("Exception should not be null", exception); + assertEquals("Message should match", testMessage, exception.getMessage()); + assertTrue("firstValidated should be true", exception.isFirstValidated()); + } + + @Test + public void testZksnarkExceptionNoMessage() { + ZksnarkException exception = new ZksnarkException(); + assertNotNull("Exception should not be null", exception); + assertNull(exception.getMessage()); + } + + @Test + public void testZksnarkExceptionWithMessage() { + String testMessage = "Zksnark validation failed"; + ZksnarkException exception = new ZksnarkException(testMessage); + assertNotNull("Exception should not be null", exception); + assertEquals("Message should match", testMessage, exception.getMessage()); + } + + @Test + public void testTronDBExceptionNoArgs() { + TronDBException exception = new TronDBException(); + assertNotNull("Exception should not be null", exception); + assertNull("Message should be null", exception.getMessage()); + assertNull("Cause should be null", exception.getCause()); + } + + @Test + public void testTronDBExceptionWithMessage() { + String testMessage = "Database error occurred"; + TronDBException exception = new TronDBException(testMessage); + assertNotNull("Exception should not be null", exception); + assertEquals("Message should match", testMessage, exception.getMessage()); + assertNull("Cause should be null", exception.getCause()); + } + + @Test + public void testTronDBExceptionWithMessageAndThrowable() { + String testMessage = "Database error with specific cause"; + Throwable testCause = new Throwable("Root cause"); + TronDBException exception = new TronDBException(testMessage, testCause); + assertNotNull("Exception should not be null", exception); + assertEquals("Message should match", testMessage, exception.getMessage()); + assertEquals("Cause should match", testCause, exception.getCause()); + } + + @Test + public void testTronDBExceptionWithThrowable() { + Throwable testCause = new Throwable("Root cause without message"); + TronDBException exception = new TronDBException(testCause); + assertNotNull("Exception should not be null", exception); + assertEquals("Cause should match", testCause, exception.getCause()); + } +} diff --git a/framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java b/framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java index cba4a7d8040..500e7454dbe 100644 --- a/framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java +++ b/framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java @@ -14,12 +14,16 @@ public class RLPListTest { @Test public void testRecursivePrint() { RLPItem element = new RLPItem("rlpItem".getBytes()); - Assert.assertEquals(new String(element.getRLPData()), "rlpItem"); + Assert.assertEquals("rlpItem", new String(element.getRLPData())); RLPList.recursivePrint(element); RLPList rlpList = new RLPList(); rlpList.add(new RLPItem("rlpItem0".getBytes())); RLPList.recursivePrint(rlpList); Assert.assertThrows(RuntimeException.class, () -> RLPList.recursivePrint(null)); + + RLPItem rlpItem = new RLPItem(new byte[0]); + Assert.assertNull(rlpItem.getRLPData()); + } @Test diff --git a/framework/src/test/java/org/tron/core/config/args/LocalWitnessTest.java b/framework/src/test/java/org/tron/core/config/args/LocalWitnessTest.java index d0222254c7d..27d5effd6b1 100644 --- a/framework/src/test/java/org/tron/core/config/args/LocalWitnessTest.java +++ b/framework/src/test/java/org/tron/core/config/args/LocalWitnessTest.java @@ -24,8 +24,8 @@ public class LocalWitnessTest { - private LocalWitnesses localWitness = new LocalWitnesses(); - private static String PRIVATE_KEY = PublicMethod.getRandomPrivateKey(); + private final LocalWitnesses localWitness = new LocalWitnesses(); + private static final String PRIVATE_KEY = PublicMethod.getRandomPrivateKey(); @Before public void setLocalWitness() { @@ -38,11 +38,15 @@ public void setLocalWitness() { @Test public void whenSetNullPrivateKey() { localWitness.setPrivateKeys(null); + Assert.assertNotNull(localWitness.getPrivateKey()); + Assert.assertNotNull(localWitness.getPublicKey()); } @Test public void whenSetEmptyPrivateKey() { localWitness.setPrivateKeys(Lists.newArrayList("")); + Assert.assertNotNull(localWitness.getPrivateKey()); + Assert.assertNotNull(localWitness.getPublicKey()); } @Test(expected = IllegalArgumentException.class) @@ -58,6 +62,7 @@ public void whenSetPrefixPrivateKey() { localWitness .setPrivateKeys(Lists .newArrayList("0X" + PRIVATE_KEY)); + Assert.assertNotNull(localWitness.getPrivateKey()); } @Test @@ -66,4 +71,20 @@ public void getPrivateKey() { .newArrayList(PRIVATE_KEY), localWitness.getPrivateKeys()); } + + @Test + public void testConstructor() { + LocalWitnesses localWitnesses = new LocalWitnesses(PublicMethod.getRandomPrivateKey()); + LocalWitnesses localWitnesses1 = + new LocalWitnesses(Lists.newArrayList(PublicMethod.getRandomPrivateKey())); + localWitnesses.setWitnessAccountAddress(new byte[0]); + Assert.assertNotNull(localWitnesses1.getPublicKey()); + + LocalWitnesses localWitnesses2 = new LocalWitnesses(); + Assert.assertNull(localWitnesses2.getPrivateKey()); + Assert.assertNull(localWitnesses2.getPublicKey()); + localWitnesses2.initWitnessAccountAddress(true); + LocalWitnesses localWitnesses3 = new LocalWitnesses(); + Assert.assertNotNull(localWitnesses3.getWitnessAccountAddress(true)); + } } diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index ddf741fb6fa..07440435f41 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -367,12 +367,12 @@ public void entityTest() { Assert.assertTrue(trie.isEmpty()); AccountStateEntity entity = new AccountStateEntity(); AccountStateEntity parsedEntity = AccountStateEntity.parse("".getBytes()); - Assert.assertTrue(parsedEntity != null); - Assert.assertTrue(parsedEntity.getAccount() != null); - Assert.assertTrue(org.tron.core.db.api.pojo.Account.of() != null); - Assert.assertTrue(org.tron.core.db.api.pojo.AssetIssue.of() != null); - Assert.assertTrue(org.tron.core.db.api.pojo.Block.of() != null); - Assert.assertTrue(org.tron.core.db.api.pojo.Transaction.of() != null); + Assert.assertNotNull(parsedEntity); + Assert.assertNotNull(parsedEntity.getAccount()); + Assert.assertNotNull(org.tron.core.db.api.pojo.Account.of()); + Assert.assertNotNull(org.tron.core.db.api.pojo.AssetIssue.of()); + Assert.assertNotNull(org.tron.core.db.api.pojo.Block.of()); + Assert.assertNotNull(org.tron.core.db.api.pojo.Transaction.of()); } diff --git a/framework/src/test/java/org/tron/core/db/api/pojo/PojoTest.java b/framework/src/test/java/org/tron/core/db/api/pojo/PojoTest.java new file mode 100644 index 00000000000..f4661725a02 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/api/pojo/PojoTest.java @@ -0,0 +1,80 @@ +package org.tron.core.db.api.pojo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.google.common.collect.Lists; +import org.junit.Test; + +public class PojoTest { + + @Test + public void testAccountCreation() { + Account account = Account.of(); + account.setName("testName"); + account.setAddress("testAddress"); + account.setBalance(1622548800000L); + + assertNotNull(account); + assertEquals("testName", account.getName()); + assertEquals("testAddress", account.getAddress()); + assertEquals(1622548800000L, account.getBalance()); + } + + @Test + public void testAssetIssueCreation() { + AssetIssue assetIssue = AssetIssue.of(); + assetIssue.setName("testName"); + assetIssue.setAddress("testAddress"); + assetIssue.setStart(1622548800000L); + assetIssue.setEnd(1654084800000L); + + assertNotNull(assetIssue); + assertEquals("testName", assetIssue.getName()); + assertEquals("testAddress", assetIssue.getAddress()); + assertEquals(1622548800000L, assetIssue.getStart()); + assertEquals(1654084800000L, assetIssue.getEnd()); + } + + @Test + public void testBlockCreation() { + Block block = Block.of(); + block.setId("7654321"); + block.setNumber(1000L); + block.setTransactionIds(Lists.newArrayList("1234567")); + + assertNotNull(block); + assertEquals("7654321", block.getId()); + assertEquals(1000L, block.getNumber()); + assertEquals("1234567", block.getTransactionIds().get(0)); + } + + @Test + public void testTransactionCreation() { + Transaction transaction = Transaction.of(); + transaction.setId("7654321"); + transaction.setFrom("from"); + transaction.setTo("to"); + + assertNotNull(transaction); + assertEquals("7654321", transaction.getId()); + assertEquals("from", transaction.getFrom()); + assertEquals("to", transaction.getTo()); + } + + @Test + public void testWitnessCreation() { + Witness witness = Witness.of(); + witness.setAddress("testAddress"); + witness.setJobs(true); + witness.setUrl("https://cryptoai.com/"); + witness.setPublicKey("wergfsioejgbrotjsdfdoqwj"); + + assertNotNull(witness); + assertEquals("testAddress", witness.getAddress()); + assertTrue(witness.isJobs()); + assertEquals("https://cryptoai.com/", witness.getUrl()); + assertEquals("wergfsioejgbrotjsdfdoqwj", witness.getPublicKey()); + } +} diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandlerTest.java index 95cb9d0597f..dab76cfcb46 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandlerTest.java @@ -9,6 +9,7 @@ import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.config.Parameter.NetConstants; import org.tron.core.exception.P2pException; +import org.tron.core.net.message.keepalive.PingMessage; import org.tron.core.net.message.sync.ChainInventoryMessage; import org.tron.core.net.peer.PeerConnection; @@ -20,11 +21,11 @@ public class ChainInventoryMsgHandlerTest { private List blockIds = new ArrayList<>(); @Test - public void testProcessMessage() { + public void testProcessMessage() throws Exception { try { handler.processMessage(peer, msg); } catch (P2pException e) { - Assert.assertTrue(e.getMessage().equals("not send syncBlockChainMsg")); + Assert.assertEquals("not send syncBlockChainMsg", e.getMessage()); } peer.setSyncChainRequested(new Pair<>(new LinkedList<>(), System.currentTimeMillis())); @@ -32,7 +33,7 @@ public void testProcessMessage() { try { handler.processMessage(peer, msg); } catch (P2pException e) { - Assert.assertTrue(e.getMessage().equals("blockIds is empty")); + Assert.assertEquals("blockIds is empty", e.getMessage()); } long size = NetConstants.SYNC_FETCH_BATCH_NUM + 2; @@ -44,7 +45,7 @@ public void testProcessMessage() { try { handler.processMessage(peer, msg); } catch (P2pException e) { - Assert.assertTrue(e.getMessage().equals("big blockIds size: " + size)); + Assert.assertEquals(e.getMessage(), "big blockIds size: " + size); } blockIds.clear(); @@ -57,8 +58,10 @@ public void testProcessMessage() { try { handler.processMessage(peer, msg); } catch (P2pException e) { - Assert.assertTrue(e.getMessage().equals("remain: 100, blockIds size: " + size)); + Assert.assertEquals(e.getMessage(), "remain: 100, blockIds size: " + size); } + Assert.assertNotNull(msg.toString()); + Assert.assertNull(msg.getAnswerMessage()); } } diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java index d4ad32dd34f..e654e1c9cc2 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java @@ -19,6 +19,7 @@ import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.exception.P2pException; +import org.tron.core.net.message.sync.BlockInventoryMessage; import org.tron.core.net.message.sync.SyncBlockChainMessage; import org.tron.core.net.peer.PeerConnection; import org.tron.p2p.connection.Channel; @@ -56,7 +57,7 @@ public void testProcessMessage() throws Exception { try { handler.processMessage(peer, new SyncBlockChainMessage(new ArrayList<>())); } catch (P2pException e) { - Assert.assertTrue(e.getMessage().equals("SyncBlockChain blockIds is empty")); + Assert.assertEquals("SyncBlockChain blockIds is empty", e.getMessage()); } List blockIds = new ArrayList<>(); @@ -66,7 +67,10 @@ public void testProcessMessage() throws Exception { "check", PeerConnection.class, SyncBlockChainMessage.class); method.setAccessible(true); boolean f = (boolean)method.invoke(handler, peer, message); - Assert.assertTrue(!f); + Assert.assertNotNull(message.getAnswerMessage()); + Assert.assertNotNull(message.toString()); + Assert.assertNotNull(((BlockInventoryMessage) message).getAnswerMessage()); + Assert.assertFalse(f); Method method1 = handler.getClass().getDeclaredMethod( "getLostBlockIds", List.class, BlockId.class); @@ -80,7 +84,7 @@ public void testProcessMessage() throws Exception { Method method2 = handler.getClass().getDeclaredMethod( "getBlockIds", Long.class, BlockId.class); method2.setAccessible(true); - List list = (List) method2.invoke(handler, 0L, new BlockCapsule.BlockId()); + List list = (List) method2.invoke(handler, 0L, new BlockCapsule.BlockId()); Assert.assertEquals(1, list.size()); } diff --git a/framework/src/test/java/org/tron/core/net/service/nodepersist/DBNodeTest.java b/framework/src/test/java/org/tron/core/net/service/nodepersist/DBNodeTest.java new file mode 100644 index 00000000000..171701762ee --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/service/nodepersist/DBNodeTest.java @@ -0,0 +1,52 @@ +package org.tron.core.net.service.nodepersist; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import com.beust.jcommander.internal.Lists; +import org.junit.Before; +import org.junit.Test; + +public class DBNodeTest { + private DBNode dbNode1; + private DBNode dbNode2; + + @Before + public void setUp() { + dbNode1 = new DBNode("localhost", 3306); + dbNode2 = new DBNode(); + } + + @Test + public void testConstructorWithParameters() { + assertEquals("localhost", dbNode1.getHost()); + assertEquals(3306, dbNode1.getPort()); + } + + @Test + public void testDefaultConstructor() { + assertNull(dbNode2.getHost()); + assertEquals(0, dbNode2.getPort()); + } + + @Test + public void testSetAndGetHost() { + dbNode2.setHost("127.0.0.1"); + assertEquals("127.0.0.1", dbNode2.getHost()); + } + + @Test + public void testSetAndGetPort() { + dbNode2.setPort(5432); + assertEquals(5432, dbNode2.getPort()); + } + + + @Test + public void testDBNodes() { + DBNodes dbNodes = new DBNodes(); + dbNodes.setNodes(Lists.newArrayList(dbNode1, dbNode2)); + assertEquals(3306, dbNodes.getNodes().get(0).getPort()); + assertEquals(0, dbNodes.getNodes().get(1).getPort()); + } +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java b/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java index 4a844c49c3c..7746066abfa 100644 --- a/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/SendCoinShieldTest.java @@ -1695,6 +1695,7 @@ public SpendDescriptionCapsule generateSpendProof(SpendDescriptionInfo spend, lo System.out.println( "rk:" + ByteArray.toHexString(spendDescriptionCapsule.getRk().toByteArray())); spendDescriptionCapsule.setRk(fakeRk); + spendDescriptionCapsule.setRk(ByteString.copyFrom(fakeRk)); return spendDescriptionCapsule; } }; @@ -1737,6 +1738,9 @@ public SpendDescriptionCapsule generateSpendProof(SpendDescriptionInfo spend, lo .toHexString(spendDescriptionCapsule.getZkproof().toByteArray())); spendDescriptionCapsule.setZkproof(fakeProof); + spendDescriptionCapsule.setZkproof(ByteString.copyFrom(fakeProof)); + spendDescriptionCapsule.setSpendAuthoritySignature(spendDescriptionCapsule + .getSpendAuthoritySignature()); return spendDescriptionCapsule; } }; @@ -1775,6 +1779,7 @@ public SpendDescriptionCapsule generateSpendProof(SpendDescriptionInfo spend, lo System.out.println( "nf:" + ByteArray.toHexString(spendDescriptionCapsule.getNullifier().toByteArray())); spendDescriptionCapsule.setNullifier(bytes); + spendDescriptionCapsule.setNullifier(ByteString.copyFrom(bytes)); return spendDescriptionCapsule; } }; @@ -1811,6 +1816,9 @@ public SpendDescriptionCapsule generateSpendProof(SpendDescriptionInfo spend, lo System.out.println( "bytes:" + ByteArray.toHexString(spendDescriptionCapsule.getAnchor().toByteArray())); spendDescriptionCapsule.setAnchor(bytes); + spendDescriptionCapsule.setAnchor(ByteString.copyFrom(bytes)); + spendDescriptionCapsule.setValueCommitment(new byte[32]); + spendDescriptionCapsule.setValueCommitment(ByteString.copyFrom(new byte[32])); return spendDescriptionCapsule; } }; @@ -1827,5 +1835,14 @@ public SpendDescriptionCapsule generateSpendProof(SpendDescriptionInfo spend, lo System.out.println("Done"); } } + + SpendDescriptionCapsule c = new SpendDescriptionCapsule(new byte[32]); + SpendDescriptionCapsule c1 = new SpendDescriptionCapsule(ByteString.copyFrom(new byte[32]), + ByteString.copyFrom(new byte[32]), + ByteString.copyFrom(new byte[32]), + ByteString.copyFrom(new byte[32]), + ByteString.copyFrom(new byte[32]),ByteString.copyFrom(new byte[32])); + Assert.assertNotNull(c); + Assert.assertNotNull(c1); } } diff --git a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java index f3ad1f36cd1..157a7ba732f 100755 --- a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java @@ -369,6 +369,8 @@ public String[] generateSpendAndOutputParams() throws ZksnarkException, BadItemE // generate checkSpendParams SpendDescription spendDescription = builder.getContractBuilder().getSpendDescription(0); + SpendDescriptionCapsule spendDescriptionCapsule = new SpendDescriptionCapsule(spendDescription); + Assert.assertNotNull(spendDescriptionCapsule); CheckSpendParams checkSpendParams = new CheckSpendParams(ctx, spendDescription.getValueCommitment().toByteArray(), spendDescription.getAnchor().toByteArray(), @@ -873,20 +875,43 @@ private ReceiveDescriptionCapsule changeGenerateOutputProof(ReceiveDescriptionIn JLibrustzcash.librustzcashSaplingProvingCtxFree(ctx); throw new ZksnarkException("Output proof failed"); } - + ReceiveDescriptionCapsule c = new ReceiveDescriptionCapsule(new byte[32]); + ReceiveDescriptionCapsule c1 = + new ReceiveDescriptionCapsule(ReceiveDescription.newBuilder().build()); + ReceiveDescriptionCapsule c2 = + new ReceiveDescriptionCapsule(ByteString.copyFrom(new byte[32]), + ByteString.copyFrom(new byte[32]), + ByteString.copyFrom(new byte[32]), + ByteString.copyFrom(new byte[32]), + ByteString.copyFrom(new byte[32]), + ByteString.copyFrom(new byte[32])); + Assert.assertNotNull(c); + Assert.assertNotNull(c1); + Assert.assertNotNull(c2); ReceiveDescriptionCapsule receiveDescriptionCapsule = new ReceiveDescriptionCapsule(); receiveDescriptionCapsule.setValueCommitment(cv); + receiveDescriptionCapsule.setValueCommitment(ByteString.copyFrom(cv)); receiveDescriptionCapsule.setNoteCommitment(cm); + receiveDescriptionCapsule.setNoteCommitment(ByteString.copyFrom(cm)); receiveDescriptionCapsule.setEpk(encryptor.getEpk()); + receiveDescriptionCapsule.setEpk(ByteString.copyFrom(encryptor.getEpk())); receiveDescriptionCapsule.setCEnc(enc.getEncCiphertext()); + receiveDescriptionCapsule.setCEnc(ByteString.copyFrom(enc.getEncCiphertext())); receiveDescriptionCapsule.setZkproof(zkProof); + receiveDescriptionCapsule.setZkproof(ByteString.copyFrom(zkProof)); + receiveDescriptionCapsule.getEphemeralKey(); + receiveDescriptionCapsule.getData(); + receiveDescriptionCapsule.getZkproof(); + receiveDescriptionCapsule.getOutCiphertext(); OutgoingPlaintext outPlaintext = new OutgoingPlaintext(output.getNote().getPkD(), encryptor.getEsk()); - receiveDescriptionCapsule.setCOut(outPlaintext + byte[] bytes = outPlaintext .encrypt(output.getOvk(), receiveDescriptionCapsule.getValueCommitment().toByteArray(), receiveDescriptionCapsule.getCm().toByteArray(), - encryptor).getData()); + encryptor).getData(); + receiveDescriptionCapsule.setCOut(bytes); + receiveDescriptionCapsule.setCOut(ByteString.copyFrom(bytes)); Note newNote = output.getNote(); byte[] newCm; diff --git a/framework/src/test/java/org/tron/program/SupplementTest.java b/framework/src/test/java/org/tron/program/SupplementTest.java index ffa6b14f46b..3dfa23dfce4 100644 --- a/framework/src/test/java/org/tron/program/SupplementTest.java +++ b/framework/src/test/java/org/tron/program/SupplementTest.java @@ -1,8 +1,10 @@ package org.tron.program; +import static org.apache.commons.lang3.StringUtils.EMPTY; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.tron.keystore.WalletUtils.passwordValid; import java.io.File; import java.io.IOException; @@ -21,6 +23,7 @@ import org.tron.core.Constant; import org.tron.core.capsule.StorageRowCapsule; import org.tron.core.capsule.utils.RLP; +import org.tron.core.config.TronLogShutdownHook; import org.tron.core.config.args.Args; import org.tron.core.services.http.HttpSelfFormatFieldName; import org.tron.core.store.StorageRowStore; @@ -130,4 +133,18 @@ public void testGet() throws Exception { RLP.unwrapList(new byte[] {1,2,3,4,5,6,7}); } + @Test + public void testPasswordValid() { + assertFalse(passwordValid(EMPTY)); + assertFalse(passwordValid("12345")); + assertTrue(passwordValid("123456")); + } + + @Test + public void testRun() { + TronLogShutdownHook hook = new TronLogShutdownHook(); + hook.run(); + assertTrue(true); + } + } From ddccce40de79de2c1c1a1ca3e883fae0dbd54763 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 27 Sep 2024 12:40:13 +0800 Subject: [PATCH 1071/1197] print trx size from pending and repush after generating block --- .../main/java/org/tron/core/db/Manager.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 66aeccdda39..43e5838d1d5 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1569,6 +1569,7 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { List toBePacked = new ArrayList<>(); long currentSize = blockCapsule.getInstance().getSerializedSize(); boolean isSort = Args.getInstance().isOpenTransactionSort(); + int[] logSize = new int[] {pendingTransactions.size(), rePushTransactions.size(), 0, 0}; while (pendingTransactions.size() > 0 || rePushTransactions.size() > 0) { boolean fromPending = false; TransactionCapsule trx; @@ -1644,6 +1645,11 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { tmpSession.merge(); toBePacked.add(trx); currentSize += trxPackSize; + if (fromPending) { + logSize[2] += 1; + } else { + logSize[3] += 1; + } } catch (Exception e) { logger.warn("Process trx {} failed when generating block {}, {}.", trx.getTransactionId(), blockCapsule.getNum(), e.getMessage()); @@ -1660,11 +1666,14 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) { BlockCapsule capsule = new BlockCapsule(blockCapsule.getInstance()); capsule.generatedByMyself = true; Metrics.histogramObserve(timer); - logger.info("Generate block {} success, trxs:{}, pendingCount: {}, rePushCount: {}," - + " postponedCount: {}, blockSize: {} B", - capsule.getNum(), capsule.getTransactions().size(), - pendingTransactions.size(), rePushTransactions.size(), postponedTrxCount, - capsule.getSerializedSize()); + logger.info("Generate block {} success, trxs:{}, before pendingCount: {}, rePushCount: {}, " + + "from pending: {}, rePush: {}, after pendingCount: {}, rePushCount: {}, " + + "postponedCount: {}, blockSize: {} B", + capsule.getNum(), capsule.getTransactions().size(), + logSize[0], logSize[1], logSize[2], logSize[3], + pendingTransactions.size(), rePushTransactions.size(), postponedTrxCount, + capsule.getSerializedSize()); + return capsule; } From 450763b66d662ec854a99b702198dce9ecbace29 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 27 Sep 2024 17:37:40 +0800 Subject: [PATCH 1072/1197] add some test case --- .../org/tron/plugins/utils/ByteArrayTest.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 plugins/src/test/java/org/tron/plugins/utils/ByteArrayTest.java diff --git a/plugins/src/test/java/org/tron/plugins/utils/ByteArrayTest.java b/plugins/src/test/java/org/tron/plugins/utils/ByteArrayTest.java new file mode 100644 index 00000000000..300c983db3a --- /dev/null +++ b/plugins/src/test/java/org/tron/plugins/utils/ByteArrayTest.java @@ -0,0 +1,44 @@ +package org.tron.plugins.utils; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; + +@Slf4j +public class ByteArrayTest { + + @Test + public void testToStrToInt() { + String test = "abc"; + byte[] testBytes = test.getBytes(); + Assert.assertEquals(test, ByteArray.toStr(testBytes)); + + int i = 5; + Assert.assertEquals(ByteArray.toInt(ByteArray.fromInt(i)), 5); + } + + @Test + public void testFromHexString() { + Assert.assertArrayEquals(ByteArray.EMPTY_BYTE_ARRAY, ByteArray.fromHexString(null)); + + Assert.assertArrayEquals(ByteArray.fromHexString("12"), ByteArray.fromHexString("0x12")); + + Assert.assertArrayEquals(ByteArray.fromHexString("0x2"), ByteArray.fromHexString("0x02")); + } + + @Test + public void testCompareUnsigned() { + byte[] a = new byte[] {1, 2}; + Assert.assertEquals(0, ByteArray.compareUnsigned(a, a)); + Assert.assertEquals(-1, ByteArray.compareUnsigned(null, a)); + Assert.assertEquals(1, ByteArray.compareUnsigned(a, null)); + + byte[] b = new byte[] {1, 3}; + Assert.assertEquals(-1, ByteArray.compareUnsigned(a, b)); + Assert.assertEquals(1, ByteArray.compareUnsigned(b, a)); + + byte[] c = new byte[] {1, 2, 3}; + Assert.assertEquals(-1, ByteArray.compareUnsigned(a, c)); + Assert.assertEquals(1, ByteArray.compareUnsigned(c, a)); + } +} From 98a37b15baea9d4aa8d9e6fd1adb1ec962b2d983 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Sun, 22 Sep 2024 14:00:09 +0800 Subject: [PATCH 1073/1197] feat(dependencies): update dependencies for protobuf-java Bump com.google.protobuf:protobuf-java from 3.21.12 to 3.25.5 Bump io.github.tronprotocol:libp2p from 2.2.1 to 2.2.4 --- build.gradle | 7 ------- common/build.gradle | 2 +- protocol/build.gradle | 2 +- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index a56be97afa1..f5b144657f3 100644 --- a/build.gradle +++ b/build.gradle @@ -39,7 +39,6 @@ subprojects { compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25' compile group: 'org.slf4j', name: 'jcl-over-slf4j', version: '1.7.25' compile group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.9' - compile group: 'com.google.guava', name: 'guava', version: '30.1-jre' compile "com.google.code.findbugs:jsr305:3.0.0" compile group: 'org.springframework', name: 'spring-context', version: '5.3.18' compile group: 'org.springframework', name: 'spring-tx', version: '5.3.18' @@ -68,12 +67,6 @@ subprojects { preserveFileTimestamps = false reproducibleFileOrder = true } - - configurations.all { - resolutionStrategy { - force group: 'com.google.guava', name: 'guava', version: '30.1-jre' - } - } } task copyToParent(type: Copy) { diff --git a/common/build.gradle b/common/build.gradle index 6c1545e5d13..8c651e48455 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -46,7 +46,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'io.github.tronprotocol', name: 'libp2p', version: '2.2.1',{ + compile group: 'io.github.tronprotocol', name: 'libp2p', version: '2.2.4',{ exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' diff --git a/protocol/build.gradle b/protocol/build.gradle index 922d6d19859..d88687227e8 100644 --- a/protocol/build.gradle +++ b/protocol/build.gradle @@ -1,6 +1,6 @@ apply plugin: 'com.google.protobuf' -def protobufVersion = '3.21.12' +def protobufVersion = '3.25.5' def grpcVersion = '1.52.1' dependencies { From 89476176d3fa0efce1dd672f0eb63ecd12794141 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 4 Oct 2024 22:26:20 +0800 Subject: [PATCH 1074/1197] update a new version. version name:GreatVoyage-v4.7.5-64-g4103dfeb63,version code:18372 --- framework/src/main/java/org/tron/program/Version.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 601f555a234..250bc087be3 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,8 +2,8 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.7.4-44-g8720e06a6"; - public static final String VERSION_CODE = "18306"; + public static final String VERSION_NAME = "GreatVoyage-v4.7.5-64-g4103dfeb63"; + public static final String VERSION_CODE = "18372"; private static final String VERSION = "4.7.6"; public static String getVersion() { From c136a26f8140b17f2c05df06fb5efb1bb47d3baa Mon Sep 17 00:00:00 2001 From: omahs <73983677+omahs@users.noreply.github.com> Date: Wed, 9 Oct 2024 05:07:18 +0200 Subject: [PATCH 1075/1197] docs: fix spelling and formatting errors (#5981) * fix spelling and formatting errors --- README.md | 2 +- Tron protobuf protocol document.md | 32 +++++++++++++++--------------- shell.md | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index bdb0877d70b..0172aae90dc 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ Recommended: ## Running a full node for mainnet -Full node has full historical data, it is the entry point into the TRON network , it can be used by other processes as a gateway into the TRON network via HTTP and GRPC endpoints. You can interact with the TRON network through full node:transfer assets, deploy contracts, interact with contracts and so on. `-c` parameter specifies a configuration file to run a full node: +Full node has full historical data, it is the entry point into the TRON network, it can be used by other processes as a gateway into the TRON network via HTTP and GRPC endpoints. You can interact with the TRON network through full node:transfer assets, deploy contracts, interact with contracts and so on. `-c` parameter specifies a configuration file to run a full node: ```bash $ nohup java -Xms9G -Xmx9G -XX:ReservedCodeCacheSize=256m \ diff --git a/Tron protobuf protocol document.md b/Tron protobuf protocol document.md index 2ba2c3113a3..d8e621ed69a 100644 --- a/Tron protobuf protocol document.md +++ b/Tron protobuf protocol document.md @@ -975,7 +975,7 @@ Contract and contract-related messages. - message `VoteAssetContract` - `owner_address`: assress of contract owner. + `owner_address`: address of contract owner. `vote_address`: voted address of asset. @@ -1059,7 +1059,7 @@ Contract and contract-related messages. `total_supply`: maximum of asset. - `frozen_supply`: frozen supplt of asset. + `frozen_supply`: frozen supply of asset. `trx_num`: trx num defines token price. @@ -1079,11 +1079,11 @@ Contract and contract-related messages. `free_asset_net_limit`: free bandwidth limit each account owns when transfers asset. - `public_free_asset_net_limit`: free bandwidth limit for all acoounts. + `public_free_asset_net_limit`: free bandwidth limit for all accounts. `public_free_asset_net_usage`: free bandwidth usage of all accounts. - `public_latest_free_net_time`: the latest bandwidth consumption time fo token transfer. + `public_latest_free_net_time`: the latest bandwidth consumption time for token transfer. ```java message AssetIssueContract { @@ -1131,7 +1131,7 @@ Contract and contract-related messages. `owner_address`: owner address. - `to_address`: reveiver address. + `to_address`: receiver address. `asset_name`: target asset name. @@ -1461,7 +1461,7 @@ Contract and contract-related messages. `owner_address`: address of owner. - `owner`: autuority to execute all contracts. + `owner`: authority to execute all contracts. `witness`: used by SR for generating blocks. @@ -1514,7 +1514,7 @@ Contract and contract-related messages. `binding_signature`: signature to verify transaction. - `transparent_to_address`: transparent address of reveiver. + `transparent_to_address`: transparent address of receiver. `to_amount`: amount to transparent to_address @@ -1536,7 +1536,7 @@ Contract and contract-related messages. ### Smart Contract -message `SmartContract` has mutiple attributes and nested message `ABI` +message `SmartContract` has multiple attributes and nested message `ABI` - message `SmartContract` @@ -1559,7 +1559,7 @@ message `SmartContract` has mutiple attributes and nested message `ABI` - message `Param` - `indexed`: `true` if the field is part of the log’s topics, `false` if it one of the log’s data segment. + `indexed`: `true` if the field is part of the log’s topics, `false` if it is one of the log’s data segment. `name`: name of the parameter. @@ -1757,7 +1757,7 @@ message `SmartContract` has mutiple attributes and nested message `ABI` `tree`: incremental merkle tree. - `filled`: this is a array, it contains the root of the subtree which can be combined with the param tree to be a new merkle tree. + `filled`: this is an array, it contains the root of the subtree which can be combined with the param tree to be a new merkle tree. `cursor`: the node that can be combined to a subtree, when they are combined to a subtree, compute its root and put it into the filled. @@ -1782,7 +1782,7 @@ message `SmartContract` has mutiple attributes and nested message `ABI` `vouchers`: this is an array, each items represents the merklevoucher of the outputpoint. - `paths`: his is an array each items represents the path of the outputpoint. + `paths`: this is an array each items represents the path of the outputpoint. ```java message IncrementalMerkleVoucherInfo { @@ -2124,13 +2124,13 @@ message `SmartContract` has mutiple attributes and nested message `ABI` - #### Node Information - Node information is separaed into several parts and implemented by nested messages. + Node information is separated into several parts and implemented by nested messages. - message `NodeInfo` - `beginSyncNum`: beginning block height for synchornize. + `beginSyncNum`: beginning block height for synchronize. `block`: head block id. @@ -2154,13 +2154,13 @@ message `SmartContract` has mutiple attributes and nested message `ABI` - message `PeerInfo`: - `lastSyncBlock`: last block id for synchornize. + `lastSyncBlock`: last block id for synchronize. `remainNum`: number of remaining blocks. `lastBlockUpdateTime`: latest block update time . - `syncFlag`: is synchroniing or not. + `syncFlag`: is synchronizing or not. `headBlockTimeWeBothHave`: timestamp of common head block. @@ -2172,7 +2172,7 @@ message `SmartContract` has mutiple attributes and nested message `ABI` `port`: listening port. - `nodeId`: ramdomly generated node ID + `nodeId`: randomly generated node ID `connectTime`: connection time period from established. diff --git a/shell.md b/shell.md index e457be3c790..1f632e75a44 100644 --- a/shell.md +++ b/shell.md @@ -20,7 +20,7 @@ The script is available in the java-tron project at [github](https://github.com/ sh start.sh --run ``` - Start the servive with options. + Start the service with options. ``` sh start.sh --run -j /data/FullNode.jar -c /data/config.conf -d /data/output-directory From 59d7d95194a737ddec23f592d086b3d131f41ba7 Mon Sep 17 00:00:00 2001 From: Elias Rad <146735585+nnsW3@users.noreply.github.com> Date: Fri, 25 Oct 2024 11:00:48 +0300 Subject: [PATCH 1076/1197] Docs fix spelling issues (#6044) * Update CONTRIBUTING.md * Update shell.md --- CONTRIBUTING.md | 6 +++--- shell.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d8dc83ad51b..79bf8567a61 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -151,7 +151,7 @@ Please make sure your submission meets the following code style: ### Commit Messages -Commit messages should follow the rule below, we provide a template corresponding instructions. +Commit messages should follow the rule below, we provide a template with corresponding instructions. Template: ``` @@ -182,7 +182,7 @@ The subject contains a succinct description of the change: 4. Do not end the subject line with a period. 5. Avoid meaningless commits. It is recommended to use the git rebase command. -Message body use the imperative, present tense: "change" not "changed" nor "changes". The body should include the motivation for the change and contrast this with previous behavior. +Message body uses the imperative, present tense: "change" not "changed" nor "changes". The body should include the motivation for the change and contrast this with previous behavior. Here is an example: ``` @@ -217,7 +217,7 @@ If the purpose of this submission is to modify one issue, you need to refer to t ### Special Situations And How To Deal With Them -As a reviewer, you may find yourself in one of the sitations below. Here’s how to deal with those: +As a reviewer, you may find yourself in one of the situations below. Here’s how to deal with those: The author doesn’t follow up: ping them after a while (i.e. after a few days). If there is no further response, close the PR or complete the work yourself. diff --git a/shell.md b/shell.md index 1f632e75a44..700067a9aa3 100644 --- a/shell.md +++ b/shell.md @@ -162,7 +162,7 @@ Get the latest released version. sh start.sh --release --run ``` -Following file structure will be generated after executed the above command and the `FullNode.jar` will be started. +Following file structure will be generated after executing the above command and the `FullNode.jar` will be started. ``` ├── ... From c81c2fcc688df04a17e7571f4d39259d1f448ef4 Mon Sep 17 00:00:00 2001 From: Oleg Date: Fri, 25 Oct 2024 11:02:10 +0300 Subject: [PATCH 1077/1197] Docs: (README) (#6036) Minor changes have been made to the documentation --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0172aae90dc..9807afb04ed 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ ## Table of Contents - [What’s TRON?](#whats-tron) -- [Building the Source Code](#building-the-source) +- [Building the Source Code](#building-the-source-code) - [Running java-tron](#running-java-tron) - [Community](#community) - [Contribution](#contribution) @@ -51,7 +51,7 @@ - [Integrity Check](#integrity-check) - [License](#license) -## What's TRON? +# What's TRON? TRON is a project dedicated to building the infrastructure for a truly decentralized Internet. @@ -61,7 +61,7 @@ TRON is a project dedicated to building the infrastructure for a truly decentral TRON enables large-scale development and engagement. With over 2000 transactions per second (TPS), high concurrency, low latency, and massive data transmission. It is ideal for building decentralized entertainment applications. Free features and incentive systems allow developers to create premium app experiences for users. -# Building the source +# Building the Source Code Building java-tron requires `git` package and 64-bit version of `Oracle JDK 1.8` to be installed, other JDK versions are not supported yet. Make sure you operate on `Linux` and `MacOS` operating systems. From 333d25c6f6b52395b359c030eb130106fa8cbb38 Mon Sep 17 00:00:00 2001 From: Simon <107106002+CarlChaoCarl@users.noreply.github.com> Date: Fri, 25 Oct 2024 16:03:45 +0800 Subject: [PATCH 1078/1197] feat(test): improve tests coverage (#6034) * optimize tests coverage * optimize tests coverage --------- Co-authored-by: chaozhu --- build.gradle | 5 +- framework/build.gradle | 27 +- .../TransactionLogTriggerCapsuleMockTest.java | 130 ++ .../TransactionLogTriggerCapsuleTest.java | 69 + .../common/runtime/RuntimeImplMockTest.java | 57 + .../java/org/tron/core/WalletMockTest.java | 1174 +++++++++++++++++ .../org/tron/core/db/ManagerMockTest.java | 384 ++++++ .../net/peer/PeerStatusCheckMockTest.java | 33 + .../core/services/http/JsonFormatTest.java | 266 ++++ .../tron/core/services/http/UtilMockTest.java | 250 ++++ 10 files changed, 2393 insertions(+), 2 deletions(-) create mode 100644 framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleMockTest.java create mode 100644 framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java create mode 100644 framework/src/test/java/org/tron/core/WalletMockTest.java create mode 100755 framework/src/test/java/org/tron/core/db/ManagerMockTest.java create mode 100644 framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckMockTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/JsonFormatTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/UtilMockTest.java diff --git a/build.gradle b/build.gradle index b1aba1c0aa9..8db08f4fe7e 100644 --- a/build.gradle +++ b/build.gradle @@ -52,7 +52,10 @@ subprojects { testAnnotationProcessor 'org.projectlombok:lombok:1.18.12' testImplementation group: 'junit', name: 'junit', version: '4.13.2' - testImplementation "org.mockito:mockito-core:2.13.0" + testImplementation "org.mockito:mockito-core:3.10.0" + testImplementation group: 'org.powermock', name: 'powermock-module-junit4', version: '2.0.9' + testImplementation group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.9' + } task sourcesJar(type: Jar, dependsOn: classes) { diff --git a/framework/build.gradle b/framework/build.gradle index ec113c93cb1..4519f93e44d 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -2,12 +2,14 @@ plugins { id "org.gradle.test-retry" version "1.5.9" id "org.sonarqube" version "2.6" id "com.gorylenko.gradle-git-properties" version "2.4.1" + id "io.github.surpsg.offlins" version "0.3.0" } gitProperties.failOnNoGitDirectory = false; apply plugin: 'application' apply plugin: 'checkstyle' +apply plugin: "io.github.surpsg.offlins" mainClassName = 'org.tron.program.FullNode' @@ -16,7 +18,7 @@ def versions = [ ] jacoco { - toolVersion = "0.8.1" + toolVersion = "0.8.8" } @@ -121,10 +123,12 @@ test { testLogging { exceptionFormat = 'full' } + /* jacoco { destinationFile = file("$buildDir/jacoco/jacocoTest.exec") classDumpDir = file("$buildDir/jacoco/classpathdumps") } + */ if (isWindows()) { exclude '**/ShieldedTransferActuatorTest.class' exclude '**/BackupDbUtilTest.class' @@ -141,6 +145,7 @@ test { } } +/* jacocoTestReport { reports { xml.enabled true @@ -149,6 +154,26 @@ jacocoTestReport { } getExecutionData().setFrom(fileTree('../framework/build/jacoco').include("**.exec")) } + */ + +offlinsCoverage { + jacocoVersion = '0.8.8' // Optional. By default `0.8.8` + + reports { + html.enabled.set true // Optional. By default `true` + html.location.set project.file('build/reports/jacoco/test/html') // Optional. By default `build/reports/jacoco/html` + + xml.enabled.set true // Optional. By default `false` + xml.location.set project.file('build/reports/jacoco/test/jacocoTestReport.xml') + // Optional. By default `build/reports/jacoco/coverageReport.xml` + + csv.enabled.set true // Optional. By default `false` + csv.location.set project.file('build/reports/jacoco/test/csvCoverage.csv') + // Optional. By default `build/reports/jacoco/coverageReport.csv` + } +} + + def binaryRelease(taskName, jarName, mainClass) { return tasks.create("${taskName}", Jar) { diff --git a/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleMockTest.java b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleMockTest.java new file mode 100644 index 00000000000..8734206d3c5 --- /dev/null +++ b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleMockTest.java @@ -0,0 +1,130 @@ +package org.tron.common.logsfilter; + +import static org.powermock.api.mockito.PowerMockito.mock; +import static org.powermock.api.mockito.PowerMockito.spy; +import static org.powermock.api.mockito.PowerMockito.when; + +import com.google.protobuf.ByteString; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; +import org.tron.common.logsfilter.capsule.TransactionLogTriggerCapsule; +import org.tron.common.logsfilter.trigger.InternalTransactionPojo; +import org.tron.common.runtime.InternalTransaction; +import org.tron.common.runtime.ProgramResult; +import org.tron.common.runtime.RuntimeImpl; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.ReceiptCapsule; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.db.TransactionTrace; +import org.tron.p2p.utils.ByteArray; +import org.tron.protos.Protocol; +import org.tron.protos.contract.BalanceContract; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({ + TransactionLogTriggerCapsule.class, + TransactionTrace.class +}) +public class TransactionLogTriggerCapsuleMockTest { + + private static final String OWNER_ADDRESS = "41548794500882809695a8a687866e76d4271a1abc"; + private static final String RECEIVER_ADDRESS = "41abd4b9367799eaa3197fecb144eb71de1e049150"; + private static final String CONTRACT_ADDRESS = "A0B4750E2CD76E19DCA331BF5D089B71C3C2798548"; + + private TransactionCapsule transactionCapsule; + private BlockCapsule blockCapsule; + + @Before + public void setup() { + blockCapsule = new BlockCapsule(1, + Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), + Sha256Hash.ZERO_HASH.getByteString() + ); + } + + @After + public void clearMocks() { + Mockito.framework().clearInlineMocks(); + } + + + @Test + public void testConstructorWithTransactionTrace() { + BalanceContract.TransferContract.Builder builder2 = + BalanceContract.TransferContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); + transactionCapsule = spy(new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.TransferContract)); + + TransactionTrace trace = mock(TransactionTrace.class); + ReceiptCapsule receiptCapsule = new ReceiptCapsule(Sha256Hash.ZERO_HASH); + RuntimeImpl runtime = mock(RuntimeImpl.class); + List logs = new ArrayList<>(); + logs.add(Protocol.TransactionInfo.Log.newBuilder() + .setAddress(ByteString.copyFrom("address".getBytes())) + .setData(ByteString.copyFrom("data".getBytes())) + .addTopics(ByteString.copyFrom("topic".getBytes())) + .build()); + + Protocol.TransactionInfo.Builder builder = Protocol.TransactionInfo.newBuilder() + .addAllLog(logs); + + ProgramResult programResult = ProgramResult.createEmpty(); + programResult.setHReturn("hreturn".getBytes()); + programResult.setContractAddress(CONTRACT_ADDRESS.getBytes()); + + when(transactionCapsule.getTrxTrace()).thenReturn(trace); + when(trace.getReceipt()).thenReturn(receiptCapsule); + when(trace.getRuntime()).thenReturn(runtime); + when(runtime.getResult()).thenReturn(programResult); + + transactionCapsule.setTrxTrace(trace); + + TransactionLogTriggerCapsule triggerCapsule = new TransactionLogTriggerCapsule( + transactionCapsule, blockCapsule,0,0,0, + builder.build(),0); + + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger()); + } + + @Test + public void testGetInternalTransactionList() throws Exception { + BalanceContract.TransferContract.Builder builder2 = + BalanceContract.TransferContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); + transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.TransferContract); + InternalTransaction internalTransaction = new InternalTransaction( + "parentHash".getBytes(), 10, 0, + "sendAddress".getBytes(), + "transferToAddress".getBytes(), + 100L, "data".getBytes(), "note", + 0L, new HashMap<>() + ); + List internalTransactionList = new ArrayList<>(); + internalTransactionList.add(internalTransaction); + TransactionLogTriggerCapsule triggerCapsule = + new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + + List pojoList = Whitebox.invokeMethod(triggerCapsule, + "getInternalTransactionList", internalTransactionList); + + Assert.assertNotNull(pojoList); + } + +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java index 76dd6e99158..93401e0d415 100644 --- a/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java +++ b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java @@ -13,13 +13,16 @@ import org.tron.core.capsule.TransactionCapsule; import org.tron.p2p.utils.ByteArray; import org.tron.protos.Protocol; +import org.tron.protos.contract.AssetIssueContractOuterClass; import org.tron.protos.contract.BalanceContract; import org.tron.protos.contract.Common; +import org.tron.protos.contract.SmartContractOuterClass; public class TransactionLogTriggerCapsuleTest { private static final String OWNER_ADDRESS = "41548794500882809695a8a687866e76d4271a1abc"; private static final String RECEIVER_ADDRESS = "41abd4b9367799eaa3197fecb144eb71de1e049150"; + private static final String CONTRACT_ADDRESS = "A0B4750E2CD76E19DCA331BF5D089B71C3C2798548"; public TransactionCapsule transactionCapsule; public BlockCapsule blockCapsule; @@ -175,4 +178,70 @@ public void testConstructorWithCancelAllUnfreezeTrxCapsule() { triggerCapsule.getTransactionLogTrigger().getExtMap().get(BANDWIDTH.name()).longValue()); } + @Test + public void testConstructorWithTransferCapsule() { + BalanceContract.TransferContract.Builder builder2 = + BalanceContract.TransferContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); + transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.TransferContract); + + TransactionLogTriggerCapsule triggerCapsule = + new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getToAddress()); + } + + @Test + public void testConstructorWithTransferAssetCapsule() { + AssetIssueContractOuterClass.TransferAssetContract.Builder builder2 = + AssetIssueContractOuterClass.TransferAssetContract.newBuilder() + .setAssetName(ByteString.copyFrom("AssetName".getBytes())) + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); + transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.TransferAssetContract); + + TransactionLogTriggerCapsule triggerCapsule = + new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getToAddress()); + } + + @Test + public void testConstructorWithTriggerSmartContract() { + SmartContractOuterClass.TriggerSmartContract.Builder builder2 = + SmartContractOuterClass.TriggerSmartContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setContractAddress(ByteString.copyFrom(ByteArray.fromHexString(CONTRACT_ADDRESS))); + transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.TriggerSmartContract); + + TransactionLogTriggerCapsule triggerCapsule = + new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getToAddress()); + } + + @Test + public void testConstructorWithCreateSmartContract() { + SmartContractOuterClass.CreateSmartContract.Builder builder2 = + SmartContractOuterClass.CreateSmartContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); + transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.CreateSmartContract); + + TransactionLogTriggerCapsule triggerCapsule = + new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); + } + + + + } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java b/framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java new file mode 100644 index 00000000000..0b8228f28ba --- /dev/null +++ b/framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java @@ -0,0 +1,57 @@ +package org.tron.common.runtime; + +import lombok.extern.slf4j.Slf4j; +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; +import org.tron.core.vm.program.Program; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({RuntimeImpl.class}) +@Slf4j +public class RuntimeImplMockTest { + @After + public void clearMocks() { + Mockito.framework().clearInlineMocks(); + } + + @Test + public void testSetResultCode1() throws Exception { + RuntimeImpl runtime = new RuntimeImpl(); + ProgramResult programResult = new ProgramResult(); + + Program.BadJumpDestinationException badJumpDestinationException + = new Program.BadJumpDestinationException("Operation with pc isn't 'JUMPDEST': PC[%d];", 0); + programResult.setException(badJumpDestinationException); + Whitebox.invokeMethod(runtime,"setResultCode", programResult); + + Program.OutOfTimeException outOfTimeException + = new Program.OutOfTimeException("CPU timeout for 0x0a executing"); + programResult.setException(outOfTimeException); + Whitebox.invokeMethod(runtime,"setResultCode", programResult); + + Program.PrecompiledContractException precompiledContractException + = new Program.PrecompiledContractException("precompiled contract exception"); + programResult.setException(precompiledContractException); + Whitebox.invokeMethod(runtime,"setResultCode", programResult); + + Program.StackTooSmallException stackTooSmallException + = new Program.StackTooSmallException("Expected stack size %d but actual %d;", 100, 10); + programResult.setException(stackTooSmallException); + Whitebox.invokeMethod(runtime,"setResultCode", programResult); + + Program.JVMStackOverFlowException jvmStackOverFlowException + = new Program.JVMStackOverFlowException(); + programResult.setException(jvmStackOverFlowException); + Whitebox.invokeMethod(runtime,"setResultCode", programResult); + + Assert.assertTrue(true); + } + +} + diff --git a/framework/src/test/java/org/tron/core/WalletMockTest.java b/framework/src/test/java/org/tron/core/WalletMockTest.java new file mode 100644 index 00000000000..e3b4384ff1b --- /dev/null +++ b/framework/src/test/java/org/tron/core/WalletMockTest.java @@ -0,0 +1,1174 @@ +package org.tron.core; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.powermock.api.mockito.PowerMockito.mockStatic; +import static org.powermock.api.mockito.PowerMockito.whenNew; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import com.google.protobuf.LazyStringArrayList; + +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; +import org.tron.api.GrpcAPI; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.ByteUtil; +import org.tron.common.utils.Sha256Hash; +import org.tron.common.utils.client.WalletClient; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.ContractCapsule; +import org.tron.core.capsule.ContractStateCapsule; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.db.TransactionStore; +import org.tron.core.exception.AccountResourceInsufficientException; +import org.tron.core.exception.BadItemException; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.exception.DupTransactionException; +import org.tron.core.exception.HeaderNotFound; +import org.tron.core.exception.ItemNotFoundException; +import org.tron.core.exception.TaposException; +import org.tron.core.exception.TooBigTransactionException; +import org.tron.core.exception.TronException; +import org.tron.core.exception.VMIllegalException; +import org.tron.core.exception.ValidateSignatureException; +import org.tron.core.exception.ZksnarkException; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.message.adv.TransactionMessage; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.store.AbiStore; +import org.tron.core.store.AccountStore; +import org.tron.core.store.CodeStore; +import org.tron.core.store.ContractStateStore; +import org.tron.core.store.ContractStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.store.TransactionHistoryStore; +import org.tron.core.store.TransactionRetStore; +import org.tron.core.zen.ShieldedTRC20ParametersBuilder; +import org.tron.core.zen.address.DiversifierT; +import org.tron.core.zen.address.ExpandedSpendingKey; +import org.tron.core.zen.address.KeyIo; +import org.tron.core.zen.address.PaymentAddress; +import org.tron.protos.Protocol; +import org.tron.protos.contract.BalanceContract; +import org.tron.protos.contract.ShieldContract; +import org.tron.protos.contract.SmartContractOuterClass; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({ + Wallet.class, + Args.class, + CommonParameter.class, + TransactionCapsule.class, + com.google.protobuf.Message.class, + ByteUtil.class, + KeyIo.class, + PaymentAddress.class, + Protocol.Transaction.Contract.ContractType.class +}) +public class WalletMockTest { + + @After + public void clearMocks() { + Mockito.framework().clearInlineMocks(); + } + + @Test + public void testSetTransactionNullException() throws Exception { + Wallet wallet = new Wallet(); + TransactionCapsule transactionCapsuleMock + = mock(TransactionCapsule.class); + Whitebox.invokeMethod(wallet, + "setTransaction", transactionCapsuleMock); + assertTrue(true); + } + + @Test + public void testCreateTransactionCapsuleWithoutValidateWithTimeoutNullException() + throws Exception { + Wallet wallet = new Wallet(); + com.google.protobuf.Message message = + mock(com.google.protobuf.Message.class); + Protocol.Transaction.Contract.ContractType contractType = + mock(Protocol.Transaction.Contract.ContractType.class); + long timeout = 100L; + TransactionCapsule transactionCapsuleMock = + mock(TransactionCapsule.class); + + whenNew(TransactionCapsule.class) + .withAnyArguments().thenReturn(transactionCapsuleMock); + try { + Whitebox.invokeMethod(wallet, + "createTransactionCapsuleWithoutValidateWithTimeout", + message, contractType, timeout); + } catch (Exception e) { + assertTrue(false); + } + + assertTrue(true); + } + + @Test + public void testCreateTransactionCapsuleWithoutValidateWithTimeout() + throws Exception { + Wallet wallet = new Wallet(); + com.google.protobuf.Message message = + mock(com.google.protobuf.Message.class); + Protocol.Transaction.Contract.ContractType contractType = + mock(Protocol.Transaction.Contract.ContractType.class); + long timeout = 100L; + BlockCapsule.BlockId blockId = new BlockCapsule.BlockId(); + + TransactionCapsule transactionCapsuleMock = mock(TransactionCapsule.class); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); + + when(chainBaseManagerMock.getHeadBlockId()).thenReturn(blockId); + + whenNew(TransactionCapsule.class) + .withAnyArguments().thenReturn(transactionCapsuleMock); + Whitebox.invokeMethod(wallet, + "createTransactionCapsuleWithoutValidateWithTimeout", + message, contractType, timeout); + assertTrue(true); + } + + + @Test + public void testBroadcastTransactionBlockUnsolidified() throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + + TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); + when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(true); + + Whitebox.setInternalState(wallet, "tronNetDelegate", tronNetDelegateMock); + + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + + assertEquals(GrpcAPI.Return.response_code.BLOCK_UNSOLIDIFIED, ret.getCode()); + } + + @Test + public void testBroadcastTransactionNoConnection() throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + List peerConnections = new ArrayList<>(); + + TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); + when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); + + Whitebox.setInternalState(wallet, "tronNetDelegate", tronNetDelegateMock); + Whitebox.setInternalState(wallet, "minEffectiveConnection", 10); + when(tronNetDelegateMock.getActivePeer()).thenReturn(peerConnections); + + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + + assertEquals(GrpcAPI.Return.response_code.NO_CONNECTION, ret.getCode()); + } + + @Test + public void testBroadcastTransactionConnectionNotEnough() throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + List peerConnections = new ArrayList<>(); + PeerConnection p1 = new PeerConnection(); + PeerConnection p2 = new PeerConnection(); + peerConnections.add(p1); + peerConnections.add(p2); + + TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); + when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); + + Whitebox.setInternalState(wallet, "tronNetDelegate", tronNetDelegateMock); + Whitebox.setInternalState(wallet, "minEffectiveConnection", 10); + when(tronNetDelegateMock.getActivePeer()).thenReturn(peerConnections); + + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + + assertEquals(GrpcAPI.Return.response_code.NOT_ENOUGH_EFFECTIVE_CONNECTION, + ret.getCode()); + } + + @Test + public void testBroadcastTransactionTooManyPending() throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + + TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); + Manager managerMock = mock(Manager.class); + when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); + when(managerMock.isTooManyPending()).thenReturn(true); + + Whitebox.setInternalState(wallet, "tronNetDelegate", tronNetDelegateMock); + Whitebox.setInternalState(wallet, "dbManager", managerMock); + + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + + assertEquals(GrpcAPI.Return.response_code.SERVER_BUSY, ret.getCode()); + } + + @Test + public void testBroadcastTransactionAlreadyExists() throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + TransactionCapsule trx = new TransactionCapsule(transaction); + trx.setTime(System.currentTimeMillis()); + Sha256Hash txID = trx.getTransactionId(); + + Cache transactionIdCache = CacheBuilder + .newBuilder().maximumSize(10) + .expireAfterWrite(1, TimeUnit.HOURS).recordStats().build(); + transactionIdCache.put(txID, true); + + TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); + Manager managerMock = mock(Manager.class); + when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); + when(managerMock.isTooManyPending()).thenReturn(false); + when(managerMock.getTransactionIdCache()).thenReturn(transactionIdCache); + + Whitebox.setInternalState(wallet, "tronNetDelegate", tronNetDelegateMock); + Whitebox.setInternalState(wallet, "dbManager", managerMock); + Whitebox.setInternalState(wallet, "trxCacheEnable", true); + + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + + assertEquals(GrpcAPI.Return.response_code.DUP_TRANSACTION_ERROR, + ret.getCode()); + } + + + @Test + public void testBroadcastTransactionNoContract() throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + + TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); + Manager managerMock = mock(Manager.class); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + DynamicPropertiesStore dynamicPropertiesStoreMock + = mock(DynamicPropertiesStore.class); + when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); + when(managerMock.isTooManyPending()).thenReturn(false); + when(chainBaseManagerMock.getDynamicPropertiesStore()) + .thenReturn(dynamicPropertiesStoreMock); + when(dynamicPropertiesStoreMock.supportVM()).thenReturn(false); + + Whitebox.setInternalState(wallet, "tronNetDelegate", tronNetDelegateMock); + Whitebox.setInternalState(wallet, "dbManager", managerMock); + Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); + Whitebox.setInternalState(wallet, "trxCacheEnable", false); + + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + + assertEquals(GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR, + ret.getCode()); + } + + @Test + public void testBroadcastTransactionOtherException() throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = getExampleTrans(); + + TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); + Manager managerMock = mock(Manager.class); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + DynamicPropertiesStore dynamicPropertiesStoreMock + = mock(DynamicPropertiesStore.class); + when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); + when(managerMock.isTooManyPending()).thenReturn(false); + when(chainBaseManagerMock.getDynamicPropertiesStore()) + .thenReturn(dynamicPropertiesStoreMock); + when(dynamicPropertiesStoreMock.supportVM()).thenReturn(false); + + Whitebox.setInternalState(wallet, "tronNetDelegate", tronNetDelegateMock); + Whitebox.setInternalState(wallet, "dbManager", managerMock); + Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); + Whitebox.setInternalState(wallet, "trxCacheEnable", false); + + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + + assertEquals(GrpcAPI.Return.response_code.OTHER_ERROR, ret.getCode()); + } + + private Protocol.Transaction getExampleTrans() { + BalanceContract.TransferContract transferContract = + BalanceContract.TransferContract.newBuilder() + .setAmount(10) + .setOwnerAddress(ByteString.copyFromUtf8("aaa")) + .setToAddress(ByteString.copyFromUtf8("bbb")) + .build(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 6666; i++) { + sb.append("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + } + return Protocol.Transaction.newBuilder().setRawData( + Protocol.Transaction.raw.newBuilder() + .setData(ByteString.copyFrom(sb.toString().getBytes(StandardCharsets.UTF_8))) + .addContract( + Protocol.Transaction.Contract.newBuilder() + .setParameter(Any.pack(transferContract)) + .setType(Protocol.Transaction.Contract.ContractType.TransferContract))) + .build(); + } + + private void mockEnv(Wallet wallet, TronException tronException) throws Exception { + TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); + Manager managerMock = mock(Manager.class); + ChainBaseManager chainBaseManagerMock + = mock(ChainBaseManager.class); + DynamicPropertiesStore dynamicPropertiesStoreMock + = mock(DynamicPropertiesStore.class); + TransactionMessage transactionMessageMock + = mock(TransactionMessage.class); + + when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); + when(managerMock.isTooManyPending()).thenReturn(false); + when(chainBaseManagerMock.getDynamicPropertiesStore()) + .thenReturn(dynamicPropertiesStoreMock); + when(dynamicPropertiesStoreMock.supportVM()).thenReturn(false); + whenNew(TransactionMessage.class) + .withAnyArguments().thenReturn(transactionMessageMock); + doThrow(tronException).when(managerMock).pushTransaction(any()); + + Whitebox.setInternalState(wallet, "tronNetDelegate", tronNetDelegateMock); + Whitebox.setInternalState(wallet, "dbManager", managerMock); + Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); + Whitebox.setInternalState(wallet, "trxCacheEnable", false); + } + + @Test + public void testBroadcastTransactionValidateSignatureException() throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = getExampleTrans(); + mockEnv(wallet, new ValidateSignatureException()); + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + assertEquals(GrpcAPI.Return.response_code.SIGERROR, ret.getCode()); + } + + @Test + public void testBroadcastTransactionValidateContractExeException() throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = getExampleTrans(); + mockEnv(wallet, new ContractExeException()); + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + assertEquals(GrpcAPI.Return.response_code.CONTRACT_EXE_ERROR, ret.getCode()); + } + + @Test + public void testBroadcastTransactionValidateAccountResourceInsufficientException() + throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = getExampleTrans(); + mockEnv(wallet, new AccountResourceInsufficientException("")); + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + assertEquals(GrpcAPI.Return.response_code.BANDWITH_ERROR, ret.getCode()); + } + + @Test + public void testBroadcastTransactionValidateDupTransactionException() + throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = getExampleTrans(); + mockEnv(wallet, new DupTransactionException("")); + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + assertEquals(GrpcAPI.Return.response_code.DUP_TRANSACTION_ERROR, ret.getCode()); + } + + @Test + public void testBroadcastTransactionValidateTaposException() throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = getExampleTrans(); + mockEnv(wallet, new TaposException("")); + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + assertEquals(GrpcAPI.Return.response_code.TAPOS_ERROR, ret.getCode()); + } + + @Test + public void testBroadcastTransactionValidateTooBigTransactionException() + throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = getExampleTrans(); + mockEnv(wallet, new TooBigTransactionException("")); + + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + assertEquals(GrpcAPI.Return.response_code.TOO_BIG_TRANSACTION_ERROR, ret.getCode()); + } + + @Test + public void testGetBlockByNum() throws Exception { + Wallet wallet = new Wallet(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); + doThrow(new ItemNotFoundException()).when(chainBaseManagerMock).getBlockByNum(anyLong()); + + Protocol.Block block = wallet.getBlockByNum(0L); + assertNull(block); + } + + @Test + public void testGetBlockCapsuleByNum() throws Exception { + Wallet wallet = new Wallet(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); + doThrow(new ItemNotFoundException()).when(chainBaseManagerMock).getBlockByNum(anyLong()); + + BlockCapsule blockCapsule = wallet.getBlockCapsuleByNum(0L); + assertNull(blockCapsule); + } + + @Test + public void testGetTransactionCountByBlockNum() throws Exception { + Wallet wallet = new Wallet(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); + doThrow(new ItemNotFoundException()).when(chainBaseManagerMock).getBlockByNum(anyLong()); + + long count = wallet.getTransactionCountByBlockNum(0L); + assertEquals(count, 0L); + } + + @Test + public void testGetTransactionById() throws Exception { + Wallet wallet = new Wallet(); + ByteString transactionId = null; + Protocol.Transaction transaction = wallet.getTransactionById(transactionId); + assertNull(transaction); + } + + @Test + public void testGetTransactionById2() throws Exception { + Wallet wallet = new Wallet(); + ByteString transactionId = ByteString.empty(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + TransactionStore transactionStoreMock = mock(TransactionStore.class); + + when(chainBaseManagerMock.getTransactionStore()).thenReturn(transactionStoreMock); + Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); + doThrow(new BadItemException()).when(transactionStoreMock).get(any()); + + Protocol.Transaction transaction = wallet.getTransactionById(transactionId); + assertNull(transaction); + } + + @Test + public void testGetTransactionById3() throws Exception { + Wallet wallet = new Wallet(); + ByteString transactionId = ByteString.empty(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + TransactionStore transactionStoreMock = mock(TransactionStore.class); + TransactionCapsule transactionCapsuleMock = mock(TransactionCapsule.class); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + + when(chainBaseManagerMock.getTransactionStore()).thenReturn(transactionStoreMock); + Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); + when(transactionStoreMock.get(any())).thenReturn(transactionCapsuleMock); + when(transactionCapsuleMock.getInstance()).thenReturn(transaction); + + Protocol.Transaction transactionRet = wallet.getTransactionById(transactionId); + assertEquals(transaction, transactionRet); + } + + @Test + public void testGetTransactionCapsuleById() throws Exception { + Wallet wallet = new Wallet(); + ByteString transactionId = null; + TransactionCapsule transactionCapsule = wallet.getTransactionCapsuleById(transactionId); + assertNull(transactionCapsule); + } + + @Test + public void testGetTransactionCapsuleById1() throws Exception { + Wallet wallet = new Wallet(); + ByteString transactionId = ByteString.empty(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + TransactionStore transactionStoreMock = mock(TransactionStore.class); + + when(chainBaseManagerMock.getTransactionStore()).thenReturn(transactionStoreMock); + Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); + doThrow(new BadItemException()).when(transactionStoreMock).get(any()); + + TransactionCapsule transactionCapsule = wallet.getTransactionCapsuleById(transactionId); + assertNull(transactionCapsule); + } + + @Test + public void testGetTransactionInfoById() throws Exception { + Wallet wallet = new Wallet(); + ByteString transactionId = null; + Protocol.TransactionInfo transactionInfo = wallet.getTransactionInfoById(transactionId); + assertNull(transactionInfo); + } + + @Test + public void testGetTransactionInfoById1() throws Exception { + Wallet wallet = new Wallet(); + ByteString transactionId = ByteString.empty(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + TransactionRetStore transactionRetStoreMock = mock(TransactionRetStore.class); + + when(chainBaseManagerMock.getTransactionRetStore()).thenReturn(transactionRetStoreMock); + Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); + doThrow(new BadItemException()).when(transactionRetStoreMock).getTransactionInfo(any()); + + Protocol.TransactionInfo transactionInfo = wallet.getTransactionInfoById(transactionId); + assertNull(transactionInfo); + } + + @Test + public void testGetTransactionInfoById2() throws Exception { + Wallet wallet = new Wallet(); + ByteString transactionId = ByteString.empty(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + TransactionRetStore transactionRetStoreMock = mock(TransactionRetStore.class); + TransactionHistoryStore transactionHistoryStoreMock = + mock(TransactionHistoryStore.class); + + when(chainBaseManagerMock.getTransactionRetStore()) + .thenReturn(transactionRetStoreMock); + when(chainBaseManagerMock.getTransactionHistoryStore()) + .thenReturn(transactionHistoryStoreMock); + Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); + when(transactionRetStoreMock.getTransactionInfo(any())).thenReturn(null); + doThrow(new BadItemException()).when(transactionHistoryStoreMock).get(any()); + + Protocol.TransactionInfo transactionInfo = wallet.getTransactionInfoById(transactionId); + assertNull(transactionInfo); + } + + @Test + public void testGetProposalById() throws Exception { + Wallet wallet = new Wallet(); + ByteString proposalId = null; + Protocol.Proposal proposal = wallet.getProposalById(proposalId); + assertNull(proposal); + } + + @Test + public void testGetMemoFeePrices() throws Exception { + Wallet wallet = new Wallet(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + DynamicPropertiesStore dynamicPropertiesStoreMock = + mock(DynamicPropertiesStore.class); + + when(chainBaseManagerMock.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStoreMock); + doThrow(new IllegalArgumentException("not found MEMO_FEE_HISTORY")) + .when(dynamicPropertiesStoreMock).getMemoFeeHistory(); + + Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); + + GrpcAPI.PricesResponseMessage responseMessage = wallet.getMemoFeePrices(); + assertNull(responseMessage); + } + + @Test + public void testGetEnergyFeeByTime() throws Exception { + Wallet wallet = new Wallet(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + DynamicPropertiesStore dynamicPropertiesStoreMock = + mock(DynamicPropertiesStore.class); + long now = System.currentTimeMillis(); + + when(chainBaseManagerMock.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStoreMock); + doThrow(new IllegalArgumentException("not found ENERGY_PRICE_HISTORY")) + .when(dynamicPropertiesStoreMock).getEnergyPriceHistory(); + when(dynamicPropertiesStoreMock.getEnergyFee()).thenReturn(10L); + + Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); + + long energyFee = wallet.getEnergyFee(now); + assertEquals(energyFee, 10L); + } + + @Test + public void testGetEnergyPrices() throws Exception { + Wallet wallet = new Wallet(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + DynamicPropertiesStore dynamicPropertiesStoreMock = + mock(DynamicPropertiesStore.class); + + when(chainBaseManagerMock.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStoreMock); + doThrow(new IllegalArgumentException("not found ENERGY_PRICE_HISTORY")) + .when(dynamicPropertiesStoreMock).getEnergyPriceHistory(); + + Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); + + GrpcAPI.PricesResponseMessage pricesResponseMessage = wallet.getEnergyPrices(); + assertNull(pricesResponseMessage); + } + + @Test + public void testGetBandwidthPrices() throws Exception { + Wallet wallet = new Wallet(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + DynamicPropertiesStore dynamicPropertiesStoreMock = + mock(DynamicPropertiesStore.class); + + when(chainBaseManagerMock.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStoreMock); + doThrow(new IllegalArgumentException("not found BANDWIDTH_PRICE_HISTORY")) + .when(dynamicPropertiesStoreMock).getBandwidthPriceHistory(); + + Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); + + GrpcAPI.PricesResponseMessage pricesResponseMessage = wallet.getBandwidthPrices(); + assertNull(pricesResponseMessage); + } + + @Test + public void testCheckBlockIdentifier() { + Wallet wallet = new Wallet(); + BalanceContract.BlockBalanceTrace.BlockIdentifier blockIdentifier = + BalanceContract.BlockBalanceTrace.BlockIdentifier.newBuilder() + .build(); + blockIdentifier = blockIdentifier.getDefaultInstanceForType(); + + BalanceContract.BlockBalanceTrace.BlockIdentifier blockIdentifier1 = + blockIdentifier; + assertThrows( + IllegalArgumentException.class, + () -> { + wallet.checkBlockIdentifier(blockIdentifier1); + } + ); + + BalanceContract.BlockBalanceTrace.BlockIdentifier blockIdentifier2 = + BalanceContract.BlockBalanceTrace.BlockIdentifier.newBuilder() + .setNumber(-1L) + .build(); + + assertThrows( + IllegalArgumentException.class, + () -> { + wallet.checkBlockIdentifier(blockIdentifier2); + } + ); + + BalanceContract.BlockBalanceTrace.BlockIdentifier blockIdentifier3 = + BalanceContract.BlockBalanceTrace.BlockIdentifier.newBuilder() + .setHash(ByteString.copyFrom("".getBytes(StandardCharsets.UTF_8))) + .build(); + assertThrows( + IllegalArgumentException.class, + () -> { + wallet.checkBlockIdentifier(blockIdentifier3); + } + ); + } + + @Test + public void testCheckAccountIdentifier() { + Wallet wallet = new Wallet(); + BalanceContract.AccountIdentifier accountIdentifier = + BalanceContract.AccountIdentifier.newBuilder().build(); + accountIdentifier = accountIdentifier.getDefaultInstanceForType(); + + BalanceContract.AccountIdentifier accountIdentifier2 = accountIdentifier; + assertThrows( + IllegalArgumentException.class, + () -> { + wallet.checkAccountIdentifier(accountIdentifier2); + } + ); + + BalanceContract.AccountIdentifier accountIdentifier1 + = BalanceContract.AccountIdentifier.newBuilder().build(); + + assertThrows( + IllegalArgumentException.class, + () -> { + wallet.checkAccountIdentifier(accountIdentifier1); + } + ); + } + + @Test + public void testGetTriggerInputForShieldedTRC20Contract() { + Wallet wallet = new Wallet(); + GrpcAPI.ShieldedTRC20TriggerContractParameters.Builder triggerParam = + GrpcAPI.ShieldedTRC20TriggerContractParameters + .newBuilder(); + GrpcAPI.ShieldedTRC20Parameters shieldedTRC20Parameters = + GrpcAPI.ShieldedTRC20Parameters.newBuilder().build(); + GrpcAPI.BytesMessage bytesMessage = + GrpcAPI.BytesMessage.newBuilder().build(); + + triggerParam.setShieldedTRC20Parameters(shieldedTRC20Parameters); + triggerParam.addSpendAuthoritySignature(bytesMessage); + + CommonParameter commonParameterMock = mock(Args.class); + mockStatic(CommonParameter.class); + when(CommonParameter.getInstance()).thenReturn(commonParameterMock); + when(commonParameterMock.isFullNodeAllowShieldedTransactionArgs()).thenReturn(true); + + assertThrows( + ZksnarkException.class, + () -> { + wallet.getTriggerInputForShieldedTRC20Contract(triggerParam.build()); + } + ); + } + + @Test + public void testGetTriggerInputForShieldedTRC20Contract1() + throws ZksnarkException, ContractValidateException { + Wallet wallet = new Wallet(); + ShieldContract.SpendDescription spendDescription = + ShieldContract.SpendDescription.newBuilder().build(); + GrpcAPI.ShieldedTRC20TriggerContractParameters.Builder triggerParam = + GrpcAPI.ShieldedTRC20TriggerContractParameters + .newBuilder(); + GrpcAPI.ShieldedTRC20Parameters shieldedTRC20Parameters = + GrpcAPI.ShieldedTRC20Parameters.newBuilder() + .addSpendDescription(spendDescription) + .setParameterType("transfer") + .build(); + GrpcAPI.BytesMessage bytesMessage = + GrpcAPI.BytesMessage.newBuilder().build(); + + triggerParam.setShieldedTRC20Parameters(shieldedTRC20Parameters); + triggerParam.addSpendAuthoritySignature(bytesMessage); + + CommonParameter commonParameterMock = mock(Args.class); + mockStatic(CommonParameter.class); + when(CommonParameter.getInstance()).thenReturn(commonParameterMock); + when(commonParameterMock.isFullNodeAllowShieldedTransactionArgs()).thenReturn(true); + + GrpcAPI.BytesMessage reponse = + wallet.getTriggerInputForShieldedTRC20Contract(triggerParam.build()); + assertNotNull(reponse); + } + + @Test + public void testGetShieldedContractScalingFactorException() { + Wallet wallet = new Wallet(); + byte[] contractAddress = "".getBytes(StandardCharsets.UTF_8); + + assertThrows( + ContractExeException.class, + () -> { + wallet.getShieldedContractScalingFactor(contractAddress); + } + ); + } + + @Test + public void testGetShieldedContractScalingFactorRuntimeException() + throws VMIllegalException, HeaderNotFound, ContractValidateException, ContractExeException { + Wallet walletMock = mock(Wallet.class); + byte[] contractAddress = "".getBytes(StandardCharsets.UTF_8); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + when(walletMock.triggerConstantContract(any(),any(),any(),any())).thenReturn(transaction); + when(walletMock.getShieldedContractScalingFactor(any())).thenCallRealMethod(); + + assertThrows( + ContractExeException.class, + () -> { + walletMock.getShieldedContractScalingFactor(contractAddress); + } + ); + } + + @Test + public void testGetShieldedContractScalingFactorSuccess() + throws Exception { + Wallet walletMock = mock(Wallet.class); + byte[] contractAddress = "".getBytes(StandardCharsets.UTF_8); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + when(walletMock.triggerConstantContract(any(),any(),any(),any())) + .thenReturn(transaction); + when(walletMock.createTransactionCapsule(any(), any())) + .thenReturn(new TransactionCapsule(transaction)); + when(walletMock.getShieldedContractScalingFactor(any())).thenCallRealMethod(); + try { + byte[] listBytes = walletMock.getShieldedContractScalingFactor(contractAddress); + assertNotNull(listBytes); + } catch (Exception e) { + assertNull(e); + } + } + + @Test + public void testGetShieldedContractScalingFactorContractExeException() + throws Exception { + Wallet walletMock = mock(Wallet.class); + byte[] contractAddress = "".getBytes(StandardCharsets.UTF_8); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + doThrow(new ContractExeException("")) + .when(walletMock).triggerConstantContract(any(),any(),any(),any()); + when(walletMock.createTransactionCapsule(any(), any())) + .thenReturn(new TransactionCapsule(transaction)); + when(walletMock.getShieldedContractScalingFactor(any())).thenCallRealMethod(); + + assertThrows( + ContractExeException.class, + () -> { + walletMock.getShieldedContractScalingFactor(contractAddress); + } + ); + } + + @Test + public void testCheckBigIntegerRange() { + Wallet wallet = new Wallet(); + + assertThrows( + "public amount must be non-negative", + Exception.class, + () -> { + Whitebox.invokeMethod(wallet, "checkBigIntegerRange", + new BigInteger("-1")); + } + ); + } + + @Test + public void testCheckPublicAmount() throws ContractExeException { + Wallet walletMock = mock(Wallet.class); + + byte[] address = "".getBytes(StandardCharsets.UTF_8); + BigInteger fromAmount = new BigInteger("10"); + BigInteger toAmount = new BigInteger("10"); + doThrow(new ContractExeException("")).when(walletMock).getShieldedContractScalingFactor(any()); + + assertThrows( + ContractExeException.class, + () -> { + PowerMockito.when(walletMock, + "checkPublicAmount", + address, fromAmount, toAmount + ).thenCallRealMethod(); + } + ); + } + + @Test + public void testCheckPublicAmount1() throws ContractExeException { + Wallet walletMock = mock(Wallet.class); + + byte[] address = "".getBytes(StandardCharsets.UTF_8); + BigInteger fromAmount = new BigInteger("300"); + BigInteger toAmount = new BigInteger("255"); + + byte[] scalingFactorBytes = ByteUtil.bigIntegerToBytes(new BigInteger("-1")); + + when(walletMock.getShieldedContractScalingFactor(any())).thenReturn(scalingFactorBytes); + assertThrows( + ContractValidateException.class, + () -> { + PowerMockito.when(walletMock, + "checkPublicAmount", + address, fromAmount, toAmount + ).thenCallRealMethod(); + } + ); + } + + @Test + public void testCheckPublicAmount2() throws ContractExeException { + Wallet walletMock = mock(Wallet.class); + + byte[] address = "".getBytes(StandardCharsets.UTF_8); + BigInteger fromAmount = new BigInteger("300"); + BigInteger toAmount = new BigInteger("255"); + + byte[] scalingFactorBytes = ByteUtil.bigIntegerToBytes(new BigInteger("-1")); + mockStatic(ByteUtil.class); + when(ByteUtil.bytesToBigInteger(any())).thenReturn(new BigInteger("-1")); + when(walletMock.getShieldedContractScalingFactor(any())).thenReturn(scalingFactorBytes); + + assertThrows( + ContractValidateException.class, + () -> { + PowerMockito.when(walletMock, + "checkPublicAmount", + address, fromAmount, toAmount + ).thenCallRealMethod(); + } + ); + } + + @Test + public void testGetShieldedTRC20Nullifier() { + GrpcAPI.Note note = GrpcAPI.Note.newBuilder() + .setValue(100) + .setPaymentAddress("address") + .setRcm(ByteString.copyFrom("rcm".getBytes(StandardCharsets.UTF_8))) + .setMemo(ByteString.copyFrom("memo".getBytes(StandardCharsets.UTF_8))) + .build(); + long pos = 100L; + byte[] ak = "ak".getBytes(StandardCharsets.UTF_8); + byte[] nk = "nk".getBytes(StandardCharsets.UTF_8); + Wallet walletMock = mock(Wallet.class); + mockStatic(KeyIo.class); + when(KeyIo.decodePaymentAddress(any())).thenReturn(null); + + assertThrows( + ZksnarkException.class, + () -> { + PowerMockito.when(walletMock, + "getShieldedTRC20Nullifier", + note, pos, ak, nk + ).thenCallRealMethod(); + } + ); + } + + @Test + public void testGetShieldedTRC20LogType() { + Wallet walletMock = mock(Wallet.class); + Protocol.TransactionInfo.Log log = Protocol.TransactionInfo.Log.newBuilder().build(); + byte[] contractAddress = "contractAddress".getBytes(StandardCharsets.UTF_8); + LazyStringArrayList topicsList = new LazyStringArrayList(); + assertThrows( + ZksnarkException.class, + () -> { + Whitebox.invokeMethod(walletMock, "getShieldedTRC20LogType", + log, contractAddress, topicsList); + } + ); + } + + @Test + public void testGetShieldedTRC20LogType1() { + Wallet wallet = new Wallet(); + final String SHIELDED_CONTRACT_ADDRESS_STR = "TGAmX5AqVUoXCf8MoHxbuhQPmhGfWTnEgA"; + byte[] contractAddress = WalletClient.decodeFromBase58Check(SHIELDED_CONTRACT_ADDRESS_STR); + + byte[] addressWithoutPrefix = new byte[20]; + System.arraycopy(contractAddress, 1, addressWithoutPrefix, 0, 20); + Protocol.TransactionInfo.Log log = Protocol.TransactionInfo.Log.newBuilder() + .setAddress(ByteString.copyFrom(addressWithoutPrefix)) + .build(); + + LazyStringArrayList topicsList = new LazyStringArrayList(); + try { + Whitebox.invokeMethod(wallet, + "getShieldedTRC20LogType", + log, + contractAddress, + topicsList); + } catch (Exception e) { + assertTrue(false); + } + assertTrue(true); + } + + + @Test + public void testGetShieldedTRC20LogType2() { + Wallet wallet = new Wallet(); + final String SHIELDED_CONTRACT_ADDRESS_STR = "TGAmX5AqVUoXCf8MoHxbuhQPmhGfWTnEgA"; + byte[] contractAddress = WalletClient.decodeFromBase58Check(SHIELDED_CONTRACT_ADDRESS_STR); + + byte[] addressWithoutPrefix = new byte[20]; + System.arraycopy(contractAddress, 1, addressWithoutPrefix, 0, 20); + Protocol.TransactionInfo.Log log = Protocol.TransactionInfo.Log.newBuilder() + .setAddress(ByteString.copyFrom(addressWithoutPrefix)) + .addTopics(ByteString.copyFrom("topic".getBytes())) + .build(); + + LazyStringArrayList topicsList = new LazyStringArrayList(); + topicsList.add("topic"); + try { + Whitebox.invokeMethod(wallet, + "getShieldedTRC20LogType", + log, + contractAddress, + topicsList); + } catch (Exception e) { + assertTrue(false); + } + assertTrue(true); + } + + @Test + public void testBuildShieldedTRC20InputWithAK() throws ZksnarkException { + ShieldedTRC20ParametersBuilder builder = new ShieldedTRC20ParametersBuilder("transfer"); + GrpcAPI.Note note = GrpcAPI.Note.newBuilder() + .setValue(100) + .setPaymentAddress("address") + .setRcm(ByteString.copyFrom("rcm".getBytes(StandardCharsets.UTF_8))) + .setMemo(ByteString.copyFrom("memo".getBytes(StandardCharsets.UTF_8))) + .build(); + GrpcAPI.SpendNoteTRC20 spendNote = GrpcAPI.SpendNoteTRC20.newBuilder() + .setNote(note) + .setAlpha(ByteString.copyFrom("alpha".getBytes())) + .setRoot(ByteString.copyFrom("root".getBytes())) + .setPath(ByteString.copyFrom("path".getBytes())) + .setPos(0L) + .build(); + byte[] ak = "ak".getBytes(StandardCharsets.UTF_8); + byte[] nk = "nk".getBytes(StandardCharsets.UTF_8); + Wallet walletMock = mock(Wallet.class); + mockStatic(KeyIo.class); + when(KeyIo.decodePaymentAddress(any())).thenReturn(null); + + assertThrows( + ZksnarkException.class, + () -> { + PowerMockito.when(walletMock, + "buildShieldedTRC20InputWithAK", + builder, + spendNote, + ak, nk + ).thenCallRealMethod(); + } + ); + } + + @Test + public void testBuildShieldedTRC20InputWithAK1() throws Exception { + ShieldedTRC20ParametersBuilder builder = new ShieldedTRC20ParametersBuilder("transfer"); + GrpcAPI.Note note = GrpcAPI.Note.newBuilder() + .setValue(100) + .setPaymentAddress("address") + .setRcm(ByteString.copyFrom("rcm".getBytes(StandardCharsets.UTF_8))) + .setMemo(ByteString.copyFrom("memo".getBytes(StandardCharsets.UTF_8))) + .build(); + GrpcAPI.SpendNoteTRC20 spendNote = GrpcAPI.SpendNoteTRC20.newBuilder() + .setNote(note) + .setAlpha(ByteString.copyFrom("alpha".getBytes())) + .setRoot(ByteString.copyFrom("root".getBytes())) + .setPath(ByteString.copyFrom("path".getBytes())) + .setPos(0L) + .build(); + byte[] ak = "ak".getBytes(StandardCharsets.UTF_8); + byte[] nk = "nk".getBytes(StandardCharsets.UTF_8); + PaymentAddress paymentAddress = mock(PaymentAddress.class); + DiversifierT diversifierT = mock(DiversifierT.class); + Wallet walletMock = mock(Wallet.class); + mockStatic(KeyIo.class); + when(KeyIo.decodePaymentAddress(any())).thenReturn(paymentAddress); + when(paymentAddress.getD()).thenReturn(diversifierT); + when(paymentAddress.getPkD()).thenReturn("pkd".getBytes()); + + PowerMockito.when(walletMock, + "buildShieldedTRC20InputWithAK", + builder, + spendNote, + ak, nk + ).thenCallRealMethod(); + assertTrue(true); + } + + @Test + public void testBuildShieldedTRC20Input() throws ZksnarkException { + ShieldedTRC20ParametersBuilder builder = new ShieldedTRC20ParametersBuilder("transfer"); + GrpcAPI.Note note = GrpcAPI.Note.newBuilder() + .setValue(100) + .setPaymentAddress("address") + .setRcm(ByteString.copyFrom("rcm".getBytes(StandardCharsets.UTF_8))) + .setMemo(ByteString.copyFrom("memo".getBytes(StandardCharsets.UTF_8))) + .build(); + GrpcAPI.SpendNoteTRC20 spendNote = GrpcAPI.SpendNoteTRC20.newBuilder() + .setNote(note) + .setAlpha(ByteString.copyFrom("alpha".getBytes())) + .setRoot(ByteString.copyFrom("root".getBytes())) + .setPath(ByteString.copyFrom("path".getBytes())) + .setPos(0L) + .build(); + ExpandedSpendingKey expandedSpendingKey = mock(ExpandedSpendingKey.class); + PaymentAddress paymentAddress = mock(PaymentAddress.class); + DiversifierT diversifierT = mock(DiversifierT.class); + Wallet walletMock = mock(Wallet.class); + mockStatic(KeyIo.class); + when(KeyIo.decodePaymentAddress(any())).thenReturn(paymentAddress); + when(paymentAddress.getD()).thenReturn(diversifierT); + when(paymentAddress.getPkD()).thenReturn("pkd".getBytes()); + try { + PowerMockito.when(walletMock, + "buildShieldedTRC20Input", + builder, + spendNote, + expandedSpendingKey + ).thenCallRealMethod(); + } catch (Exception e) { + assertTrue(false); + } + } + + @Test + public void testGetContractInfo() { + Wallet wallet = new Wallet(); + GrpcAPI.BytesMessage bytesMessage = GrpcAPI.BytesMessage.newBuilder() + .setValue(ByteString.copyFrom("test".getBytes())) + .build(); + + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + AccountStore accountStore = mock(AccountStore.class); + Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); + when(chainBaseManagerMock.getAccountStore()).thenReturn(accountStore); + when(accountStore.get(any())).thenReturn(null); + + SmartContractOuterClass.SmartContractDataWrapper smartContractDataWrapper = + wallet.getContractInfo(bytesMessage); + assertNull(smartContractDataWrapper); + } + + @Test + public void testGetContractInfo1() { + Wallet wallet = new Wallet(); + GrpcAPI.BytesMessage bytesMessage = GrpcAPI.BytesMessage.newBuilder() + .setValue(ByteString.copyFrom("test".getBytes())) + .build(); + + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + AccountStore accountStore = mock(AccountStore.class); + ContractStore contractStore = mock(ContractStore.class); + AbiStore abiStore = mock(AbiStore.class); + CodeStore codeStore = mock(CodeStore.class); + ContractStateStore contractStateStore = mock(ContractStateStore.class); + DynamicPropertiesStore dynamicPropertiesStore = mock(DynamicPropertiesStore.class); + + AccountCapsule accountCapsule = mock(AccountCapsule.class); + ContractCapsule contractCapsule = mock(ContractCapsule.class); + ContractStateCapsule contractStateCapsule = new ContractStateCapsule(10L); + + Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); + when(chainBaseManagerMock.getAccountStore()).thenReturn(accountStore); + when(chainBaseManagerMock.getContractStore()).thenReturn(contractStore); + when(chainBaseManagerMock.getAbiStore()).thenReturn(abiStore); + when(chainBaseManagerMock.getCodeStore()).thenReturn(codeStore); + when(chainBaseManagerMock.getContractStateStore()).thenReturn(contractStateStore); + when(chainBaseManagerMock.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStore); + + when(accountStore.get(any())).thenReturn(accountCapsule); + when(contractStore.get(any())).thenReturn(contractCapsule); + when(contractCapsule.generateWrapper()) + .thenReturn(SmartContractOuterClass.SmartContractDataWrapper.newBuilder().build()); + when(abiStore.get(any())).thenReturn(null); + when(codeStore.get(any())).thenReturn(null); + when(contractStateStore.get(any())).thenReturn(contractStateCapsule); + when(dynamicPropertiesStore.getCurrentCycleNumber()).thenReturn(100L); + + SmartContractOuterClass.SmartContractDataWrapper smartContractDataWrapper = + wallet.getContractInfo(bytesMessage); + assertNotNull(smartContractDataWrapper); + } +} diff --git a/framework/src/test/java/org/tron/core/db/ManagerMockTest.java b/framework/src/test/java/org/tron/core/db/ManagerMockTest.java new file mode 100755 index 00000000000..62ffcc9c43d --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/ManagerMockTest.java @@ -0,0 +1,384 @@ +package org.tron.core.db; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.powermock.api.mockito.PowerMockito.spy; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import java.nio.charset.StandardCharsets; + +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; +import org.quartz.CronExpression; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.runtime.ProgramResult; +import org.tron.common.runtime.RuntimeImpl; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.ChainBaseManager; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.capsule.TransactionInfoCapsule; +import org.tron.core.capsule.utils.TransactionUtil; +import org.tron.core.config.args.Args; +import org.tron.core.exception.ContractSizeNotEqualToOneException; +import org.tron.core.exception.DupTransactionException; +import org.tron.core.exception.ItemNotFoundException; +import org.tron.core.exception.ReceiptCheckErrException; +import org.tron.core.exception.TaposException; +import org.tron.core.exception.TooBigTransactionException; +import org.tron.core.exception.TooBigTransactionResultException; +import org.tron.core.exception.TransactionExpirationException; +import org.tron.core.exception.ValidateSignatureException; +import org.tron.core.store.AccountStore; +import org.tron.core.store.BalanceTraceStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.Protocol; +import org.tron.protos.contract.BalanceContract; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({Manager.class, + CommonParameter.class, + Args.class, + TransactionUtil.class}) +@Slf4j +public class ManagerMockTest { + @After + public void clearMocks() { + Mockito.framework().clearInlineMocks(); + } + + @Test + public void processTransactionCostTimeMoreThan100() throws Exception { + Manager dbManager = spy(new Manager()); + BalanceContract.TransferContract transferContract = + BalanceContract.TransferContract.newBuilder() + .setAmount(10) + .setOwnerAddress(ByteString.copyFromUtf8("aaa")) + .setToAddress(ByteString.copyFromUtf8("bbb")) + .build(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 6666; i++) { + sb.append("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + } + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().setRawData( + Protocol.Transaction.raw.newBuilder() + .setData(ByteString.copyFrom(sb.toString().getBytes(StandardCharsets.UTF_8))) + .addContract( + Protocol.Transaction.Contract.newBuilder() + .setParameter(Any.pack(transferContract)) + .setType(Protocol.Transaction.Contract.ContractType.TransferContract))) + .build(); + TransactionCapsule trxCap = new TransactionCapsule(transaction); + ProgramResult result = new ProgramResult(); + result.setResultCode(Protocol.Transaction.Result.contractResult.SUCCESS); + + Sha256Hash transactionId = trxCap.getTransactionId(); + TransactionCapsule trxCapMock = mock(TransactionCapsule.class); + TransactionTrace traceMock = mock(TransactionTrace.class); + RuntimeImpl runtimeMock = mock(RuntimeImpl.class); + BandwidthProcessor bandwidthProcessorMock = mock(BandwidthProcessor.class); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + BalanceTraceStore balanceTraceStoreMock = mock(BalanceTraceStore.class); + TransactionStore transactionStoreMock = mock(TransactionStore.class); + TransactionInfoCapsule transactionInfoCapsuleMock = mock(TransactionInfoCapsule.class); + Protocol.TransactionInfo transactionInfo = Protocol.TransactionInfo.newBuilder().build(); + + // mock static + PowerMockito.mockStatic(TransactionUtil.class); + + Whitebox.setInternalState(dbManager, "chainBaseManager", chainBaseManagerMock); + + BlockCapsule blockCapMock = Mockito.mock(BlockCapsule.class); + + PowerMockito.when(TransactionUtil + .buildTransactionInfoInstance(trxCapMock, blockCapMock, traceMock)) + .thenReturn(transactionInfoCapsuleMock); + + // this make cost > 100 cond is true + PowerMockito.when(blockCapMock.isMerkleRootEmpty()).thenAnswer(new Answer() { + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + Thread.sleep(100); + return true; + } + }); + + when(chainBaseManagerMock.getBalanceTraceStore()).thenReturn(balanceTraceStoreMock); + when(chainBaseManagerMock.getAccountStore()).thenReturn(mock(AccountStore.class)); + when(chainBaseManagerMock.getDynamicPropertiesStore()) + .thenReturn(mock(DynamicPropertiesStore.class)); + when(chainBaseManagerMock.getTransactionStore()).thenReturn(transactionStoreMock); + when(trxCapMock.getTransactionId()).thenReturn(transactionId); + when(traceMock.getRuntimeResult()).thenReturn(result); + when(transactionInfoCapsuleMock.getId()).thenReturn(transactionId.getBytes()); + when(transactionInfoCapsuleMock.getInstance()).thenReturn(transactionInfo); + + doNothing().when(dbManager).validateTapos(trxCapMock); + doNothing().when(dbManager).validateCommon(trxCapMock); + doNothing().when(dbManager).validateDup(trxCapMock); + + // mock construct + PowerMockito.whenNew(RuntimeImpl.class).withAnyArguments().thenReturn(runtimeMock); + PowerMockito.whenNew(TransactionTrace.class).withAnyArguments().thenReturn(traceMock); + PowerMockito.whenNew(BandwidthProcessor.class).withAnyArguments() + .thenReturn(bandwidthProcessorMock); + + doNothing().when(transactionStoreMock).put(transactionId.getBytes(), trxCapMock); + doNothing().when(bandwidthProcessorMock).consume(trxCapMock, traceMock); + doNothing().when(dbManager).consumeBandwidth(trxCapMock, traceMock); + doNothing().when(balanceTraceStoreMock).initCurrentTransactionBalanceTrace(trxCapMock); + doNothing().when(balanceTraceStoreMock).updateCurrentTransactionStatus(anyString()); + doNothing().when(balanceTraceStoreMock).resetCurrentTransactionTrace(); + + when(trxCapMock.getInstance()).thenReturn(trxCap.getInstance()); + when(trxCapMock.validatePubSignature( + Mockito.any(AccountStore.class), + Mockito.any(DynamicPropertiesStore.class))).thenReturn(true); + when(trxCapMock.validateSignature( + Mockito.any(AccountStore.class), + Mockito.any(DynamicPropertiesStore.class))).thenReturn(true); + + assertNotNull(dbManager.processTransaction(trxCapMock, blockCapMock)); + } + + private void initMockEnv(Manager dbManager, long headNum, long headTime, + long exitHeight, long exitCount, String blockTime) + throws Exception { + ChainBaseManager chainBaseManagerMock = PowerMockito.mock(ChainBaseManager.class); + Args argsMock = PowerMockito.mock(Args.class); + + PowerMockito.mockStatic(CommonParameter.class); + PowerMockito.mockStatic(Args.class); + PowerMockito.when(Args.getInstance()).thenReturn(argsMock); + + when(chainBaseManagerMock.getHeadBlockNum()).thenReturn(headNum); + when(chainBaseManagerMock.getHeadBlockTimeStamp()).thenReturn(headTime); + + when(argsMock.getShutdownBlockHeight()).thenReturn(exitHeight); + when(argsMock.getShutdownBlockCount()).thenReturn(exitCount); + when(argsMock.isP2pDisable()).thenReturn(false); + when(argsMock.getShutdownBlockTime()) + .thenReturn(new CronExpression(blockTime)); //"0 0 12 * * ?" + + Whitebox.setInternalState(dbManager, + "chainBaseManager", chainBaseManagerMock); + } + + @Test + public void testInitAutoStop() throws Exception { + Manager dbManager = spy(new Manager()); + initMockEnv(dbManager, 100L, 12345L, + 10L, 0L, "0 0 12 * * ?"); + + assertThrows( + "shutDownBlockHeight 10 is less than headNum 100", + Exception.class, + () -> { + Whitebox.invokeMethod(dbManager, "initAutoStop"); + } + ); + } + + @Test + public void testInitAutoStop1() throws Exception { + Manager dbManager = spy(new Manager()); + initMockEnv(dbManager,10L, 12345L, + 100L, 0L, "0 0 12 * * ?"); + + assertThrows( + "shutDownBlockCount 0 is less than 1", + Exception.class, + () -> { + Whitebox.invokeMethod(dbManager, "initAutoStop"); + } + ); + } + + @Test + public void testInitAutoStop2() throws Exception { + Manager dbManager = spy(new Manager()); + initMockEnv(dbManager,10L, 99726143865000L, + 100L, 1L, "0 0 12 * * ?"); + + assertThrows( + "shutDownBlockTime 0 0 12 * * ? is illegal", + Exception.class, + () -> { + Whitebox.invokeMethod(dbManager, "initAutoStop"); + } + ); + } + + @Test + public void testInitAutoStop3() throws Exception { + Manager dbManager = spy(new Manager()); + initMockEnv(dbManager,10L, 12345L, + 100L, 1L, "0 0 12 * * ?"); + + assertThrows( + "shutDownBlockHeight 100 and shutDownBlockCount 1 set both", + Exception.class, + () -> { + Whitebox.invokeMethod(dbManager, "initAutoStop"); + } + ); + } + + @Test + public void testInitAutoStop4() throws Exception { + Manager dbManager = spy(new Manager()); + initMockEnv(dbManager, 10L, 12345L, + 100L, -1L, "0 0 12 * * ?"); + + assertThrows( + "shutDownBlockHeight 100 and shutDownBlockTime 0 0 12 * * ? set both", + Exception.class, + () -> { + Whitebox.invokeMethod(dbManager, "initAutoStop"); + } + ); + } + + @Test + public void testInitAutoStop5() throws Exception { + Manager dbManager = spy(new Manager()); + initMockEnv(dbManager,10L, 12345L, + 0L, 1L, "0 0 12 * * ?"); + + assertThrows( + "shutDownBlockCount 1 and shutDownBlockTime 0 0 12 * * ? set both", + Exception.class, + () -> { + Whitebox.invokeMethod(dbManager, "initAutoStop"); + } + ); + } + + @Test + public void testProcessTransaction() throws Exception { + Manager dbManager = spy(new Manager()); + TransactionCapsule transactionCapsuleMock = null; + BlockCapsule blockCapsuleMock = PowerMockito.mock(BlockCapsule.class); + Whitebox.invokeMethod(dbManager, "processTransaction", + transactionCapsuleMock, blockCapsuleMock); + assertTrue(true); + } + + @Test + public void testProcessTransaction1() { + Manager dbManager = spy(new Manager()); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().setRawData( + Protocol.Transaction.raw.newBuilder() + .setData(ByteString.copyFrom("sb.toString()".getBytes(StandardCharsets.UTF_8)))) + .build(); + TransactionCapsule trxCap = new TransactionCapsule(transaction); + + BlockCapsule blockCapsuleMock = PowerMockito.mock(BlockCapsule.class); + + assertThrows( + ContractSizeNotEqualToOneException.class, + () -> { + Whitebox.invokeMethod(dbManager, "processTransaction", + trxCap, blockCapsuleMock); + } + ); + } + + @SneakyThrows + @Test + public void testRePush() { + Manager dbManager = spy(new Manager()); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + TransactionCapsule trx = new TransactionCapsule(transaction); + TransactionStore transactionStoreMock = mock(TransactionStore.class); + + ChainBaseManager chainBaseManagerMock = PowerMockito.mock(ChainBaseManager.class); + Whitebox.setInternalState(dbManager, "chainBaseManager", chainBaseManagerMock); + when(chainBaseManagerMock.getTransactionStore()).thenReturn(transactionStoreMock); + when(transactionStoreMock.has(any())).thenReturn(true); + + dbManager.rePush(trx); + assertTrue(true); + } + + @SneakyThrows + @Test + public void testRePush1() { + Manager dbManager = spy(new Manager()); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + TransactionCapsule trx = new TransactionCapsule(transaction); + TransactionStore transactionStoreMock = mock(TransactionStore.class); + + ChainBaseManager chainBaseManagerMock = PowerMockito.mock(ChainBaseManager.class); + Whitebox.setInternalState(dbManager, "chainBaseManager", chainBaseManagerMock); + when(chainBaseManagerMock.getTransactionStore()).thenReturn(transactionStoreMock); + when(transactionStoreMock.has(any())).thenReturn(false); + + doThrow(new ValidateSignatureException()).when(dbManager).pushTransaction(any()); + dbManager.rePush(trx); + + doThrow(new DupTransactionException()).when(dbManager).pushTransaction(any()); + dbManager.rePush(trx); + + doThrow(new TaposException()).when(dbManager).pushTransaction(any()); + dbManager.rePush(trx); + + doThrow(new TooBigTransactionException()).when(dbManager).pushTransaction(any()); + dbManager.rePush(trx); + + doThrow(new TransactionExpirationException()).when(dbManager).pushTransaction(any()); + dbManager.rePush(trx); + + doThrow(new ReceiptCheckErrException()).when(dbManager).pushTransaction(any()); + dbManager.rePush(trx); + + doThrow(new TooBigTransactionResultException()).when(dbManager).pushTransaction(any()); + dbManager.rePush(trx); + assertTrue(true); + } + + @Test + public void testPostSolidityFilter() throws Exception { + Manager dbManager = spy(new Manager()); + Whitebox.invokeMethod(dbManager, "postSolidityFilter", + 100L, 10L); + assertTrue(true); + } + + @Test + public void testReOrgLogsFilter() throws Exception { + Manager dbManager = spy(new Manager()); + CommonParameter commonParameterMock = PowerMockito.mock(Args.class); + PowerMockito.mockStatic(CommonParameter.class); + ChainBaseManager chainBaseManagerMock = PowerMockito.mock(ChainBaseManager.class); + + PowerMockito.when(CommonParameter.getInstance()).thenReturn(commonParameterMock); + when(commonParameterMock.isJsonRpcHttpFullNodeEnable()).thenReturn(true); + when(chainBaseManagerMock.getDynamicPropertiesStore()) + .thenReturn(mock(DynamicPropertiesStore.class)); + Whitebox.setInternalState(dbManager, "chainBaseManager", chainBaseManagerMock); + doThrow(new ItemNotFoundException()).when(chainBaseManagerMock).getBlockById(any()); + + Whitebox.invokeMethod(dbManager, "reOrgLogsFilter"); + assertTrue(true); + } + +} diff --git a/framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckMockTest.java b/framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckMockTest.java new file mode 100644 index 00000000000..92bf06edd72 --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckMockTest.java @@ -0,0 +1,33 @@ +package org.tron.core.net.peer; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.spy; + +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({PeerStatusCheckMockTest.class}) +public class PeerStatusCheckMockTest { + @After + public void clearMocks() { + Mockito.framework().clearInlineMocks(); + } + + @Test + public void testInitException() throws InterruptedException { + PeerStatusCheck peerStatusCheck = spy(new PeerStatusCheck()); + doThrow(new RuntimeException("test exception")).when(peerStatusCheck).statusCheck(); + peerStatusCheck.init(); + + // the initialDelay of scheduleWithFixedDelay is 5s + Thread.sleep(5000L); + assertTrue(true); + } + +} diff --git a/framework/src/test/java/org/tron/core/services/http/JsonFormatTest.java b/framework/src/test/java/org/tron/core/services/http/JsonFormatTest.java new file mode 100644 index 00000000000..1b3fc354c95 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/JsonFormatTest.java @@ -0,0 +1,266 @@ +package org.tron.core.services.http; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; + +import com.google.protobuf.ByteString; +import com.google.protobuf.UnknownFieldSet; + +import java.io.CharArrayReader; +import java.io.IOException; +import java.io.StringWriter; + +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; +import org.tron.protos.Protocol; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({ + JsonFormat.class, +}) +public class JsonFormatTest { + @After + public void clearMocks() { + Mockito.framework().clearInlineMocks(); + } + + @Test + public void testPrintErrorMsg() { + Exception ex = new Exception("test"); + String out = JsonFormat.printErrorMsg(ex); + assertEquals("{\"Error\":\"test\"}", out); + } + + @Test + public void testPrintWithHelloMessage() throws IOException { + Protocol.HelloMessage message = Protocol.HelloMessage.newBuilder() + .setAddress(ByteString.copyFrom("address".getBytes())) + .build(); + StringWriter output = new StringWriter(); + + JsonFormat.print(message, output, true); + assertNotNull(output.toString()); + } + + private UnknownFieldSet createValidUnknownFieldSet() { + UnknownFieldSet unknownFieldSet2 = UnknownFieldSet.newBuilder().build(); + UnknownFieldSet.Field unknownField1 = UnknownFieldSet.Field.newBuilder() + .addFixed32(123) + .addFixed64(12345L) + .addGroup(unknownFieldSet2) + .addLengthDelimited(ByteString.copyFrom("length".getBytes())) + .addVarint(12345678L) + .build(); + + return UnknownFieldSet.newBuilder() + .addField(1, unknownField1) + .build(); + } + + @Test + public void testPrintWithFields() throws IOException { + UnknownFieldSet unknownFieldSet = createValidUnknownFieldSet(); + StringWriter output = new StringWriter(); + JsonFormat.print(unknownFieldSet, output, true); + assertNotNull(output.toString()); + } + + @Test + public void testPrintToString() { + UnknownFieldSet unknownFieldSet = createValidUnknownFieldSet(); + String output = JsonFormat.printToString(unknownFieldSet, true); + assertNotNull(output); + } + + @Test + public void testUnsignedToString() throws Exception { + String out1 = Whitebox.invokeMethod(JsonFormat.class, + "unsignedToString", 100L); + assertEquals("100", out1); + String out2 = Whitebox.invokeMethod(JsonFormat.class, + "unsignedToString", -100L); + assertNotNull(out2); + + String out3 = Whitebox.invokeMethod(JsonFormat.class, + "unsignedToString", 100); + assertEquals("100", out3); + String out4 = Whitebox.invokeMethod(JsonFormat.class, + "unsignedToString", -100); + assertNotNull(out4); + } + + @Test + public void testToStringBuilderWithNonReadableInput() throws Exception { + String inputString = "Hello, World!"; + Readable input = new CharArrayReader(inputString.toCharArray()); + + StringBuilder out = Whitebox.invokeMethod(JsonFormat.class, + "toStringBuilder", input); + assertEquals(inputString, out.toString()); + } + + + @Test + public void testUnicodeEscaped() throws Exception { + char input1 = 0x09; + String out = Whitebox.invokeMethod(JsonFormat.class, + "unicodeEscaped", input1); + assertNotNull(out); + + char input2 = 0x99; + String out2 = Whitebox.invokeMethod(JsonFormat.class, + "unicodeEscaped", input2); + assertNotNull(out2); + + char input3 = 0x999; + String out3 = Whitebox.invokeMethod(JsonFormat.class, + "unicodeEscaped", input3); + assertNotNull(out3); + + char input4 = 0x1001; + String out4 = Whitebox.invokeMethod(JsonFormat.class, + "unicodeEscaped", input4); + assertNotNull(out4); + } + + @Test + public void testEscapeText() throws Exception { + String input1 = "\b\f\n\r\t\\\"\\b\\f\\n\\r\\t\\\\\"test123"; + String out = Whitebox.invokeMethod(JsonFormat.class, + "escapeText", input1); + assertNotNull(out); + } + + @Test + public void testAppendEscapedUnicode() throws Exception { + char input1 = 0x09; + StringBuilder out1 = new StringBuilder(); + Whitebox.invokeMethod(JsonFormat.class, + "appendEscapedUnicode", out1, input1); + assertNotNull(out1); + + char input2 = 0x99; + StringBuilder out2 = new StringBuilder(); + Whitebox.invokeMethod(JsonFormat.class, + "appendEscapedUnicode", out2, input2); + assertNotNull(out2); + + char input3 = 0x999; + StringBuilder out3 = new StringBuilder(); + Whitebox.invokeMethod(JsonFormat.class, + "appendEscapedUnicode", out3, input3); + assertNotNull(out3); + + char input4 = 0x1001; + StringBuilder out4 = new StringBuilder(); + Whitebox.invokeMethod(JsonFormat.class, + "appendEscapedUnicode", out4, input4); + assertNotNull(out4); + } + + @Test + public void testUnescapeText() throws Exception { + String input = "\\u1234\\b\\f\\n\\r\\t\\\\\"test123";; + String out = Whitebox.invokeMethod(JsonFormat.class, + "unescapeText", input); + assertNotNull(out); + } + + @Test + public void testDigitValue() throws Exception { + char input = '1'; + int out = Whitebox.invokeMethod(JsonFormat.class, + "digitValue", input); + assertEquals(1, out); + + char input1 = 'b'; + int out1 = Whitebox.invokeMethod(JsonFormat.class, + "digitValue", input1); + assertEquals(11, out1); + + char input2 = 'B'; + int out2 = Whitebox.invokeMethod(JsonFormat.class, + "digitValue", input2); + assertEquals(11, out2); + } + + @Test + public void testParseUInt64() throws Exception { + String input = "12312312312"; + long out = Whitebox.invokeMethod(JsonFormat.class, + "parseUInt64", input); + assertEquals(12312312312L, out); + + String input1 = "0x10"; + long out1 = Whitebox.invokeMethod(JsonFormat.class, + "parseUInt64", input1); + assertEquals(16L, out1); + + String input2 = "010"; + long out2 = Whitebox.invokeMethod(JsonFormat.class, + "parseUInt64", input2); + assertEquals(8L, out2); + + String input3 = "-12312312312"; + assertThrows( + NumberFormatException.class, + () -> { + Whitebox.invokeMethod(JsonFormat.class, + "parseUInt64", input3); + } + ); + } + + @Test + public void testParseInteger() { + String input1 = "92233720368547758070"; + assertThrows( + NumberFormatException.class, + () -> { + Whitebox.invokeMethod(JsonFormat.class, "parseInteger", + input1, true, true); + } + ); + String input5 = "92233720368547758070"; + assertThrows( + NumberFormatException.class, + () -> { + Whitebox.invokeMethod(JsonFormat.class, "parseInteger", + input5, false, true); + } + ); + + String input2 = "-92233720368547758"; + assertThrows( + NumberFormatException.class, + () -> { + Whitebox.invokeMethod(JsonFormat.class, "parseInteger", + input2, false, true); + } + ); + + String input3 = "92233720368547758070"; + assertThrows( + NumberFormatException.class, + () -> { + Whitebox.invokeMethod(JsonFormat.class, "parseInteger", + input3, false, false); + } + ); + String input4 = "-92233720368547758070"; + assertThrows( + NumberFormatException.class, + () -> { + Whitebox.invokeMethod(JsonFormat.class, "parseInteger", + input4, true, false); + } + ); + } + +} diff --git a/framework/src/test/java/org/tron/core/services/http/UtilMockTest.java b/framework/src/test/java/org/tron/core/services/http/UtilMockTest.java new file mode 100644 index 00000000000..a2b5bcbe342 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/UtilMockTest.java @@ -0,0 +1,250 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import com.google.protobuf.ByteString; + +import java.security.InvalidParameterException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.tron.api.GrpcAPI; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.p2p.utils.ByteArray; +import org.tron.protos.Protocol; +import org.tron.protos.contract.BalanceContract; +import org.tron.protos.contract.SmartContractOuterClass; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({ + Util.class, +}) +public class UtilMockTest { + @After + public void clearMocks() { + Mockito.framework().clearInlineMocks(); + } + + + @Test + public void testPrintTransactionFee() { + Protocol.ResourceReceipt resourceReceipt = Protocol.ResourceReceipt.newBuilder() + .build(); + Protocol.TransactionInfo result = Protocol.TransactionInfo.newBuilder() + .setReceipt(resourceReceipt) + .build(); + String transactionFee = JsonFormat.printToString(result, true); + String out = Util.printTransactionFee(transactionFee); + Assert.assertNotNull(out); + } + + @Test + public void testPrintBlockList() { + BlockCapsule blockCapsule1 = new BlockCapsule(1, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), Sha256Hash.ZERO_HASH.getByteString()); + BlockCapsule blockCapsule2 = new BlockCapsule(1, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), Sha256Hash.ZERO_HASH.getByteString()); + GrpcAPI.BlockList list = GrpcAPI.BlockList.newBuilder() + .addBlock(blockCapsule1.getInstance()) + .addBlock(blockCapsule2.getInstance()) + .build(); + String out = Util.printBlockList(list, true); + Assert.assertNotNull(out); + } + + @Test + public void testPrintTransactionList() { + TransactionCapsule transactionCapsule = getTransactionCapsuleExample(); + GrpcAPI.TransactionList list = GrpcAPI.TransactionList.newBuilder() + .addTransaction(transactionCapsule.getInstance()) + .build(); + String out = Util.printTransactionList(list, true); + Assert.assertNotNull(out); + } + + private TransactionCapsule getTransactionCapsuleExample() { + final String OWNER_ADDRESS = "41548794500882809695a8a687866e76d4271a1abc"; + final String RECEIVER_ADDRESS = "41abd4b9367799eaa3197fecb144eb71de1e049150"; + BalanceContract.TransferContract.Builder builder2 = + BalanceContract.TransferContract.newBuilder() + .setOwnerAddress( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setToAddress( + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); + return new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.TransferContract); + } + + @Test + public void testPrintTransactionSignWeight() { + TransactionCapsule transactionCapsule = getTransactionCapsuleExample(); + GrpcAPI.TransactionExtention transactionExtention = + GrpcAPI.TransactionExtention.newBuilder() + .setTransaction(transactionCapsule.getInstance()) + .build(); + GrpcAPI.TransactionSignWeight txSignWeight = + GrpcAPI.TransactionSignWeight.newBuilder() + .setTransaction(transactionExtention) + .build(); + + String out = Util.printTransactionSignWeight(txSignWeight, true); + Assert.assertNotNull(out); + } + + @Test + public void testPrintTransactionApprovedList() { + TransactionCapsule transactionCapsule = getTransactionCapsuleExample(); + GrpcAPI.TransactionExtention transactionExtention = + GrpcAPI.TransactionExtention.newBuilder() + .setTransaction(transactionCapsule.getInstance()) + .build(); + GrpcAPI.TransactionApprovedList transactionApprovedList = + GrpcAPI.TransactionApprovedList.newBuilder() + .setTransaction(transactionExtention) + .build(); + String out = Util.printTransactionApprovedList( + transactionApprovedList, true); + Assert.assertNotNull(out); + } + + @Test + public void testGenerateContractAddress() { + final String OWNER_ADDRESS = "41548794500882809695a8a687866e76d4271a1abc"; + TransactionCapsule transactionCapsule = getTransactionCapsuleExample(); + byte[] out = Util.generateContractAddress( + transactionCapsule.getInstance(), OWNER_ADDRESS.getBytes()); + Assert.assertNotNull(out); + } + + @Test + public void testPrintTransactionToJSON() { + final String OWNER_ADDRESS = "41548794500882809695a8a687866e76d4271a1abc"; + SmartContractOuterClass.CreateSmartContract.Builder builder2 = + SmartContractOuterClass.CreateSmartContract.newBuilder() + .setOwnerAddress( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); + TransactionCapsule transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.CreateSmartContract); + + JSONObject out = Util.printTransactionToJSON( + transactionCapsule.getInstance(), true); + Assert.assertNotNull(out); + } + + @Test + public void testGetContractType() { + String out = Util.getContractType("{\"contractType\":\"123\"}\n"); + Assert.assertEquals("123", out); + } + + @Test + public void testGetHexAddress() { + String out = Util.getHexAddress("TBxSocpujP6UGKV5ydXNVTDQz7fAgdmoaB"); + Assert.assertNotNull(out); + + Assert.assertNull(Util.getHexAddress(null)); + } + + @Test + public void testSetTransactionPermissionId() { + TransactionCapsule transactionCapsule = getTransactionCapsuleExample(); + Protocol.Transaction out = Util.setTransactionPermissionId( + 123, transactionCapsule.getInstance()); + Assert.assertNotNull(out); + } + + @Test + public void testSetTransactionExtraData() { + TransactionCapsule transactionCapsule = getTransactionCapsuleExample(); + JSONObject jsonObject = JSONObject.parseObject("{\"extra_data\":\"test\"}"); + Protocol.Transaction out = Util.setTransactionExtraData(jsonObject, + transactionCapsule.getInstance(), true); + Assert.assertNotNull(out); + } + + @Test + public void testConvertOutput() { + Protocol.Account account = Protocol.Account.newBuilder().build(); + String out = Util.convertOutput(account); + Assert.assertNotNull(out); + + account = Protocol.Account.newBuilder() + .setAssetIssuedID(ByteString.copyFrom("asset_issued_ID".getBytes())) + .build(); + out = Util.convertOutput(account); + Assert.assertNotNull(out); + } + + @Test + public void testConvertLogAddressToTronAddress() { + List logs = new ArrayList<>(); + logs.add(Protocol.TransactionInfo.Log.newBuilder() + .setAddress(ByteString.copyFrom("address".getBytes())) + .setData(ByteString.copyFrom("data".getBytes())) + .addTopics(ByteString.copyFrom("topic".getBytes())) + .build()); + + Protocol.TransactionInfo.Builder builder = Protocol.TransactionInfo.newBuilder() + .addAllLog(logs); + List logList = + Util.convertLogAddressToTronAddress(builder.build()); + Assert.assertNotNull(logList.size() > 0); + } + + @Test + public void testValidateParameter() { + String contract = "{\"address\":\"owner_address\"}"; + Assert.assertThrows( + InvalidParameterException.class, + () -> { + Util.validateParameter(contract); + } + ); + String contract1 = + "{\"owner_address\":\"owner_address\"," + + " \"contract_address1\":\"contract_address\", \"data1\":\"data\"}"; + Assert.assertThrows( + InvalidParameterException.class, + () -> { + Util.validateParameter(contract1); + } + ); + String contract2 = + "{\"owner_address\":\"owner_address\", " + + "\"function_selector\":\"function_selector\", \"data\":\"data\"}"; + Assert.assertThrows( + InvalidParameterException.class, + () -> { + Util.validateParameter(contract2); + } + ); + } + + @Test + public void testGetJsonString() { + String str = ""; + String ret = Util.getJsonString(str); + Assert.assertTrue(StringUtils.isEmpty(ret)); + + String str1 = "{\"owner_address\":\"owner_address\"}"; + String ret1 = Util.getJsonString(str1); + Assert.assertTrue(str1.equals(ret1)); + + String str2 = "owner_address=owner_address&contract_address=contract_address"; + String ret2 = Util.getJsonString(str2); + String expect = + "{\"owner_address\":\"owner_address\"," + + "\"contract_address\":\"contract_address\"}"; + Assert.assertEquals(expect, ret2); + } + +} From 9d168e821f5e5e40f709c1fb5d66ba4767de6781 Mon Sep 17 00:00:00 2001 From: halibobo1205 <82020050+halibobo1205@users.noreply.github.com> Date: Fri, 1 Nov 2024 14:27:55 +0800 Subject: [PATCH 1079/1197] doc(README): update free space required (#6064) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9807afb04ed..0d0eeb6ef71 100644 --- a/README.md +++ b/README.md @@ -91,13 +91,13 @@ Minimum: - CPU with 8 cores - 16GB RAM -- 2TB free storage space to sync the Mainnet +- 3TB free storage space to sync the Mainnet Recommended: - CPU with 16+ cores(32+ cores for a super representative) - 32GB+ RAM(64GB+ for a super representative) -- High Performance SSD with at least 2.5TB free space +- High Performance SSD with at least 4TB free space - 100+ MB/s download Internet service ## Running a full node for mainnet From 3bbc91da6604ba93dd3a4cda223003fdd0706d8a Mon Sep 17 00:00:00 2001 From: tomatoishealthy Date: Tue, 21 May 2024 15:33:03 +0800 Subject: [PATCH 1080/1197] feat(event): optimize event subscribe exception handling --- .../main/java/org/tron/core/db/Manager.java | 27 ++++++++++++------- .../java/org/tron/core/db/ManagerTest.java | 14 ++++++++++ 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 43e5838d1d5..908e248bdee 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1321,23 +1321,17 @@ public void pushBlock(final BlockCapsule block) return; } + long oldSolidNum = getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); try (ISession tmpSession = revokingStore.buildSession()) { - - long oldSolidNum = - chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); - applyBlock(newBlock, txs); tmpSession.commit(); - // if event subscribe is enabled, post block trigger to queue - postBlockTrigger(newBlock); - // if event subscribe is enabled, post solidity trigger to queue - postSolidityTrigger(oldSolidNum, - getDynamicPropertiesStore().getLatestSolidifiedBlockNum()); } catch (Throwable throwable) { logger.error(throwable.getMessage(), throwable); khaosDb.removeBlk(block.getBlockId()); throw throwable; } + long newSolidNum = getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); + blockTrigger(newBlock, oldSolidNum, newSolidNum); } logger.info(SAVE_BLOCK, newBlock); } @@ -1367,6 +1361,19 @@ public void pushBlock(final BlockCapsule block) } } + void blockTrigger(final BlockCapsule block, long oldSolid, long newSolid) { + try { + // if event subscribe is enabled, post block trigger to queue + postBlockTrigger(block); + // if event subscribe is enabled, post solidity trigger to queue + postSolidityTrigger(oldSolid, newSolid); + } catch (Exception e) { + logger.error("Block trigger failed. head: {}, oldSolid: {}, newSolid: {}", + block.getNum(), oldSolid, newSolid, e); + System.exit(1); + } + } + public void updateDynamicProperties(BlockCapsule block) { chainBaseManager.getDynamicPropertiesStore() @@ -2216,7 +2223,7 @@ private void postLogsFilter(final BlockCapsule blockCapsule, boolean solidified, } } - private void postBlockTrigger(final BlockCapsule blockCapsule) { + void postBlockTrigger(final BlockCapsule blockCapsule) { // post block and logs for jsonrpc if (CommonParameter.getInstance().isJsonRpcHttpFullNodeEnable()) { postBlockFilter(blockCapsule, false); diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index 10cc766d8ed..ddf741fb6fa 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -1,6 +1,9 @@ package org.tron.core.db; import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.spy; import static org.tron.common.utils.Commons.adjustAssetBalanceV2; import static org.tron.common.utils.Commons.adjustBalance; import static org.tron.common.utils.Commons.adjustTotalShieldedPoolValue; @@ -27,6 +30,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.contrib.java.lang.system.ExpectedSystemExit; import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; import org.tron.common.crypto.ECKey; @@ -107,6 +111,8 @@ public class ManagerTest extends BlockGenerate { private static BlockCapsule blockCapsule2; @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); + @Rule + public final ExpectedSystemExit exit = ExpectedSystemExit.none(); private static AtomicInteger port = new AtomicInteger(0); private static String accountAddress = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; @@ -1151,4 +1157,12 @@ public void testTooBigTransaction() { TooBigTransactionException.class, () -> dbManager.validateCommon(trx)); } + + @Test + public void blockTrigger() { + exit.expectSystemExitWithStatus(1); + Manager manager = spy(new Manager()); + doThrow(new RuntimeException("postBlockTrigger mock")).when(manager).postBlockTrigger(any()); + manager.blockTrigger(new BlockCapsule(Block.newBuilder().build()), 1, 1); + } } From 2333531a97122d350d1df3fbc282abeb487409a3 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 20 Mar 2024 13:31:53 +0800 Subject: [PATCH 1081/1197] fix(backup/backupServer): make the thread pool close after the netty channel closes --- .../java/org/tron/common/backup/socket/BackupServer.java | 2 +- .../test/java/org/tron/common/backup/BackupServerTest.java | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java b/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java index 2acf1e12633..67739ac50d2 100644 --- a/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java +++ b/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java @@ -95,7 +95,6 @@ public void initChannel(NioDatagramChannel ch) public void close() { logger.info("Closing backup server..."); shutdown = true; - ExecutorServiceManager.shutdownAndAwaitTermination(executor, name); backupManager.stop(); if (channel != null) { try { @@ -104,6 +103,7 @@ public void close() { logger.warn("Closing backup server failed.", e); } } + ExecutorServiceManager.shutdownAndAwaitTermination(executor, name); logger.info("Backup server closed."); } } diff --git a/framework/src/test/java/org/tron/common/backup/BackupServerTest.java b/framework/src/test/java/org/tron/common/backup/BackupServerTest.java index 34b17ec186f..9bff6eed677 100644 --- a/framework/src/test/java/org/tron/common/backup/BackupServerTest.java +++ b/framework/src/test/java/org/tron/common/backup/BackupServerTest.java @@ -7,6 +7,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; +import org.junit.rules.Timeout; import org.tron.common.backup.socket.BackupServer; import org.tron.common.parameter.CommonParameter; import org.tron.core.Constant; @@ -17,6 +18,9 @@ public class BackupServerTest { @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Rule + public Timeout globalTimeout = Timeout.seconds(60); private BackupServer backupServer; @Before @@ -40,5 +44,7 @@ public void tearDown() { @Test public void test() throws InterruptedException { backupServer.initServer(); + // wait for the server to start + Thread.sleep(1000); } } From 4e65c21678a75964dbf1243555ca6793731bfd0d Mon Sep 17 00:00:00 2001 From: waynercheung Date: Wed, 13 Nov 2024 13:25:41 +0800 Subject: [PATCH 1082/1197] feat(jsonrpc): make other jsonrpc apis process finalized parameter --- framework/src/main/java/org/tron/core/Wallet.java | 10 +++++++--- .../core/services/jsonrpc/JsonRpcApiUtil.java | 6 +++++- .../core/services/jsonrpc/TronJsonRpcImpl.java | 15 ++++++++++----- .../jsonrpc/filters/LogFilterWrapper.java | 8 ++++---- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index b3754db9241..e7c239511d9 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -685,9 +685,9 @@ public Block getBlockByNum(long blockNum) { } } - public Block getFinalizedBlock() { + public Block getSolidBlock() { try { - long blockNum = chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); + long blockNum = getSolidBlockNum(); return chainBaseManager.getBlockByNum(blockNum).getInstance(); } catch (StoreException e) { logger.info(e.getMessage()); @@ -695,6 +695,10 @@ public Block getFinalizedBlock() { } } + public long getSolidBlockNum() { + return chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); + } + public BlockCapsule getBlockCapsuleByNum(long blockNum) { try { return chainBaseManager.getBlockByNum(blockNum); @@ -723,7 +727,7 @@ public Block getByJsonBlockId(String id) throws JsonRpcInvalidParamsException { } else if (LATEST_STR.equalsIgnoreCase(id)) { return getNowBlock(); } else if (FINALIZED_STR.equalsIgnoreCase(id)) { - return getFinalizedBlock(); + return getSolidBlock(); } else if (PENDING_STR.equalsIgnoreCase(id)) { throw new JsonRpcInvalidParamsException(TAG_PENDING_SUPPORT_ERROR); } else { diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java index 3891e472e7c..955ba55060f 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java @@ -1,6 +1,7 @@ package org.tron.core.services.jsonrpc; import static org.tron.core.services.jsonrpc.TronJsonRpcImpl.EARLIEST_STR; +import static org.tron.core.services.jsonrpc.TronJsonRpcImpl.FINALIZED_STR; import static org.tron.core.services.jsonrpc.TronJsonRpcImpl.LATEST_STR; import static org.tron.core.services.jsonrpc.TronJsonRpcImpl.PENDING_STR; import static org.tron.core.services.jsonrpc.TronJsonRpcImpl.TAG_PENDING_SUPPORT_ERROR; @@ -514,7 +515,8 @@ public static long parseEnergyFee(long timestamp, String energyPriceHistory) { return -1; } - public static long getByJsonBlockId(String blockNumOrTag) throws JsonRpcInvalidParamsException { + public static long getByJsonBlockId(String blockNumOrTag, Wallet wallet) + throws JsonRpcInvalidParamsException { if (PENDING_STR.equalsIgnoreCase(blockNumOrTag)) { throw new JsonRpcInvalidParamsException(TAG_PENDING_SUPPORT_ERROR); } @@ -522,6 +524,8 @@ public static long getByJsonBlockId(String blockNumOrTag) throws JsonRpcInvalidP return -1; } else if (EARLIEST_STR.equalsIgnoreCase(blockNumOrTag)) { return 0; + } else if (FINALIZED_STR.equalsIgnoreCase(blockNumOrTag)) { + return wallet.getSolidBlockNum(); } else { return ByteArray.jsonHexToLong(blockNumOrTag); } diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 1bb93001055..5ff915dbdc9 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -141,7 +141,8 @@ public enum RequestSource { private static final String JSON_ERROR = "invalid json request"; private static final String BLOCK_NUM_ERROR = "invalid block number"; - private static final String TAG_NOT_SUPPORT_ERROR = "TAG [earliest | pending] not supported"; + private static final String TAG_NOT_SUPPORT_ERROR = + "TAG [earliest | pending | finalized] not supported"; private static final String QUANTITY_NOT_SUPPORT_ERROR = "QUANTITY not supported, just support TAG as latest"; private static final String NO_BLOCK_HEADER = "header not found"; @@ -353,7 +354,8 @@ public String getLatestBlockNum() { public String getTrxBalance(String address, String blockNumOrTag) throws JsonRpcInvalidParamsException { if (EARLIEST_STR.equalsIgnoreCase(blockNumOrTag) - || PENDING_STR.equalsIgnoreCase(blockNumOrTag)) { + || PENDING_STR.equalsIgnoreCase(blockNumOrTag) + || FINALIZED_STR.equalsIgnoreCase(blockNumOrTag)) { throw new JsonRpcInvalidParamsException(TAG_NOT_SUPPORT_ERROR); } else if (LATEST_STR.equalsIgnoreCase(blockNumOrTag)) { byte[] addressData = addressCompatibleToByteArray(address); @@ -490,7 +492,8 @@ private String call(byte[] ownerAddressByte, byte[] contractAddressByte, long va public String getStorageAt(String address, String storageIdx, String blockNumOrTag) throws JsonRpcInvalidParamsException { if (EARLIEST_STR.equalsIgnoreCase(blockNumOrTag) - || PENDING_STR.equalsIgnoreCase(blockNumOrTag)) { + || PENDING_STR.equalsIgnoreCase(blockNumOrTag) + || FINALIZED_STR.equalsIgnoreCase(blockNumOrTag)) { throw new JsonRpcInvalidParamsException(TAG_NOT_SUPPORT_ERROR); } else if (LATEST_STR.equalsIgnoreCase(blockNumOrTag)) { byte[] addressByte = addressCompatibleToByteArray(address); @@ -525,7 +528,8 @@ public String getStorageAt(String address, String storageIdx, String blockNumOrT public String getABIOfSmartContract(String contractAddress, String blockNumOrTag) throws JsonRpcInvalidParamsException { if (EARLIEST_STR.equalsIgnoreCase(blockNumOrTag) - || PENDING_STR.equalsIgnoreCase(blockNumOrTag)) { + || PENDING_STR.equalsIgnoreCase(blockNumOrTag) + || FINALIZED_STR.equalsIgnoreCase(blockNumOrTag)) { throw new JsonRpcInvalidParamsException(TAG_NOT_SUPPORT_ERROR); } else if (LATEST_STR.equalsIgnoreCase(blockNumOrTag)) { byte[] addressData = addressCompatibleToByteArray(contractAddress); @@ -825,7 +829,8 @@ public String getCall(CallArguments transactionCall, Object blockParamObj) } if (EARLIEST_STR.equalsIgnoreCase(blockNumOrTag) - || PENDING_STR.equalsIgnoreCase(blockNumOrTag)) { + || PENDING_STR.equalsIgnoreCase(blockNumOrTag) + || FINALIZED_STR.equalsIgnoreCase(blockNumOrTag)) { throw new JsonRpcInvalidParamsException(TAG_NOT_SUPPORT_ERROR); } else if (LATEST_STR.equalsIgnoreCase(blockNumOrTag)) { byte[] addressData = addressCompatibleToByteArray(transactionCall.getFrom()); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java index cf04a1769aa..cf5c5567299 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java @@ -51,7 +51,7 @@ public LogFilterWrapper(FilterRequest fr, long currentMaxBlockNum, Wallet wallet // then if toBlock < maxBlockNum, set fromBlock = toBlock // then if toBlock >= maxBlockNum, set fromBlock = maxBlockNum if (StringUtils.isEmpty(fr.getFromBlock()) && StringUtils.isNotEmpty(fr.getToBlock())) { - toBlockSrc = JsonRpcApiUtil.getByJsonBlockId(fr.getToBlock()); + toBlockSrc = JsonRpcApiUtil.getByJsonBlockId(fr.getToBlock(), wallet); if (toBlockSrc == -1) { toBlockSrc = Long.MAX_VALUE; } @@ -59,7 +59,7 @@ public LogFilterWrapper(FilterRequest fr, long currentMaxBlockNum, Wallet wallet } else if (StringUtils.isNotEmpty(fr.getFromBlock()) && StringUtils.isEmpty(fr.getToBlock())) { - fromBlockSrc = JsonRpcApiUtil.getByJsonBlockId(fr.getFromBlock()); + fromBlockSrc = JsonRpcApiUtil.getByJsonBlockId(fr.getFromBlock(), wallet); if (fromBlockSrc == -1) { fromBlockSrc = currentMaxBlockNum; } @@ -70,8 +70,8 @@ public LogFilterWrapper(FilterRequest fr, long currentMaxBlockNum, Wallet wallet toBlockSrc = Long.MAX_VALUE; } else { - fromBlockSrc = JsonRpcApiUtil.getByJsonBlockId(fr.getFromBlock()); - toBlockSrc = JsonRpcApiUtil.getByJsonBlockId(fr.getToBlock()); + fromBlockSrc = JsonRpcApiUtil.getByJsonBlockId(fr.getFromBlock(), wallet); + toBlockSrc = JsonRpcApiUtil.getByJsonBlockId(fr.getToBlock(), wallet); if (fromBlockSrc == -1 && toBlockSrc == -1) { fromBlockSrc = currentMaxBlockNum; toBlockSrc = Long.MAX_VALUE; From a8ea72166e75c0a5cd52febf8887dc2ad93aae6c Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 13 Nov 2024 17:13:08 +0800 Subject: [PATCH 1083/1197] initial commit --- .../logsfilter/DesensitizedConverter.java | 50 +++++++++++++++++++ .../core/net/service/relay/RelayService.java | 7 +++ framework/src/main/resources/logback.xml | 2 + .../logsfilter/DesensitizedConverterTest.java | 22 ++++++++ 4 files changed, 81 insertions(+) create mode 100644 framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java create mode 100644 framework/src/test/java/org/tron/common/logsfilter/DesensitizedConverterTest.java diff --git a/framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java b/framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java new file mode 100644 index 00000000000..073495d1015 --- /dev/null +++ b/framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java @@ -0,0 +1,50 @@ +package org.tron.common.logsfilter; + +import ch.qos.logback.classic.pattern.ClassicConverter; +import ch.qos.logback.classic.spi.ILoggingEvent; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import lombok.extern.slf4j.Slf4j; +import org.tron.core.config.args.Args; + +@Slf4j(topic = "Parser") +public class DesensitizedConverter extends ClassicConverter { + + private static final int SENSITIVE_WORD_SIZE = 1_000; + + private static final Pattern pattern = Pattern.compile( + "/(((25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))\\.){3}(25[0-5]|2[0-4]\\d|((1\\d{2})|" + + "([1-9]?\\d))))"); + + private static final Cache sensitiveCache = CacheBuilder.newBuilder() + .maximumSize(SENSITIVE_WORD_SIZE) + .recordStats().build(); + + public static void addSensitive(String key, String value) { + sensitiveCache.put(key, value); + } + + public String desensitization(String content) { + if (sensitiveCache.size() > 0) { + Matcher matcher = pattern.matcher(content); + while (matcher.find()) { + String key = matcher.group(); + String value = sensitiveCache.getIfPresent(key); + if (value != null) { + content = content.replaceAll(key, value); + } else { + content = content.replaceAll(key, "unknown"); + } + } + } + return content; + } + + @Override + public String convert(ILoggingEvent iLoggingEvent) { + String source = iLoggingEvent.getFormattedMessage(); + return Args.getInstance().isFastForward() ? desensitization(source) : source; + } +} diff --git a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java index dfc5f2e89da..388080a1039 100644 --- a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java @@ -18,8 +18,11 @@ import org.tron.common.crypto.SignInterface; import org.tron.common.crypto.SignUtils; import org.tron.common.es.ExecutorServiceManager; +import org.tron.common.logsfilter.DesensitizedConverter; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.ByteUtil; +import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.Sha256Hash; import org.tron.core.ChainBaseManager; import org.tron.core.capsule.TransactionCapsule; @@ -156,6 +159,10 @@ public boolean checkHelloMessage(HelloMessage message, Channel channel) { } if (flag) { TronNetService.getP2pConfig().getTrustNodes().add(channel.getInetAddress()); + byte[] addressByte = ByteUtil.merge(new byte[] {DecodeUtil.addressPreFixByte}, + msg.getAddress().toByteArray()); + DesensitizedConverter.addSensitive(channel.getInetAddress().toString(), + ByteArray.toHexString(addressByte)); } return flag; } catch (Exception e) { diff --git a/framework/src/main/resources/logback.xml b/framework/src/main/resources/logback.xml index 39c7f463172..7d761bda931 100644 --- a/framework/src/main/resources/logback.xml +++ b/framework/src/main/resources/logback.xml @@ -4,6 +4,8 @@ + diff --git a/framework/src/test/java/org/tron/common/logsfilter/DesensitizedConverterTest.java b/framework/src/test/java/org/tron/common/logsfilter/DesensitizedConverterTest.java new file mode 100644 index 00000000000..03ba6276e55 --- /dev/null +++ b/framework/src/test/java/org/tron/common/logsfilter/DesensitizedConverterTest.java @@ -0,0 +1,22 @@ +package org.tron.common.logsfilter; + +import org.junit.Assert; +import org.junit.Test; + +public class DesensitizedConverterTest { + + @Test + public void testReplace() { + DesensitizedConverter converter = new DesensitizedConverter(); + DesensitizedConverter.addSensitive("/192.168.1.10", "address1"); + DesensitizedConverter.addSensitive("/197.168.1.10", "address2"); + + String logStr1 = "This is test log /192.168.1.10:100, /197.168.1.10:200, /197.168.1.10:100"; + Assert.assertEquals("This is test log address1:100, address2:200, address2:100", + converter.desensitization(logStr1)); + + String logStr2 = "This is test log /192.168.1.100:100, /197.168.1.10:200, /197.168.1.10:100"; + Assert.assertEquals("This is test log unknown:100, address2:200, address2:100", + converter.desensitization(logStr2)); + } +} From a31763e43a0965c17c9fa1c9eea788e99a8dce6f Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 13 Nov 2024 17:24:24 +0800 Subject: [PATCH 1084/1197] revise if sensitiveCache is empty --- .../logsfilter/DesensitizedConverter.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java b/framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java index 073495d1015..a618d1243de 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java +++ b/framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java @@ -27,18 +27,17 @@ public static void addSensitive(String key, String value) { } public String desensitization(String content) { - if (sensitiveCache.size() > 0) { - Matcher matcher = pattern.matcher(content); - while (matcher.find()) { - String key = matcher.group(); - String value = sensitiveCache.getIfPresent(key); - if (value != null) { - content = content.replaceAll(key, value); - } else { - content = content.replaceAll(key, "unknown"); - } + Matcher matcher = pattern.matcher(content); + while (matcher.find()) { + String key = matcher.group(); + String value = sensitiveCache.getIfPresent(key); + if (value != null) { + content = content.replaceAll(key, value); + } else { + content = content.replaceAll(key, "unknown"); } } + return content; } From a154dcbe5f48a74972ea11ec831458ee81b34956 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 13 Nov 2024 17:51:41 +0800 Subject: [PATCH 1085/1197] ignore / of address --- .../java/org/tron/common/logsfilter/DesensitizedConverter.java | 2 +- .../main/java/org/tron/core/net/service/relay/RelayService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java b/framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java index a618d1243de..84a681fe379 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java +++ b/framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java @@ -15,7 +15,7 @@ public class DesensitizedConverter extends ClassicConverter { private static final int SENSITIVE_WORD_SIZE = 1_000; private static final Pattern pattern = Pattern.compile( - "/(((25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))\\.){3}(25[0-5]|2[0-4]\\d|((1\\d{2})|" + "(((25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))\\.){3}(25[0-5]|2[0-4]\\d|((1\\d{2})|" + "([1-9]?\\d))))"); private static final Cache sensitiveCache = CacheBuilder.newBuilder() diff --git a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java index 388080a1039..90463f8ab46 100644 --- a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java @@ -161,7 +161,7 @@ public boolean checkHelloMessage(HelloMessage message, Channel channel) { TronNetService.getP2pConfig().getTrustNodes().add(channel.getInetAddress()); byte[] addressByte = ByteUtil.merge(new byte[] {DecodeUtil.addressPreFixByte}, msg.getAddress().toByteArray()); - DesensitizedConverter.addSensitive(channel.getInetAddress().toString(), + DesensitizedConverter.addSensitive(channel.getInetAddress().toString().substring(1), ByteArray.toHexString(addressByte)); } return flag; From 7bd057d4356380bfc26e90e655a7aa6ba6887340 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 14 Nov 2024 10:35:22 +0800 Subject: [PATCH 1086/1197] replace unknown ip with string IP --- .../logsfilter/DesensitizedConverter.java | 4 ++-- .../logsfilter/DesensitizedConverterTest.java | 23 +++++++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java b/framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java index 84a681fe379..1cbe5101f40 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java +++ b/framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java @@ -26,7 +26,7 @@ public static void addSensitive(String key, String value) { sensitiveCache.put(key, value); } - public String desensitization(String content) { + private String desensitization(String content) { Matcher matcher = pattern.matcher(content); while (matcher.find()) { String key = matcher.group(); @@ -34,7 +34,7 @@ public String desensitization(String content) { if (value != null) { content = content.replaceAll(key, value); } else { - content = content.replaceAll(key, "unknown"); + content = content.replaceAll(key, "IP"); } } diff --git a/framework/src/test/java/org/tron/common/logsfilter/DesensitizedConverterTest.java b/framework/src/test/java/org/tron/common/logsfilter/DesensitizedConverterTest.java index 03ba6276e55..c584d5adf06 100644 --- a/framework/src/test/java/org/tron/common/logsfilter/DesensitizedConverterTest.java +++ b/framework/src/test/java/org/tron/common/logsfilter/DesensitizedConverterTest.java @@ -1,22 +1,31 @@ package org.tron.common.logsfilter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import org.junit.Assert; import org.junit.Test; public class DesensitizedConverterTest { @Test - public void testReplace() { + public void testReplace() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { DesensitizedConverter converter = new DesensitizedConverter(); - DesensitizedConverter.addSensitive("/192.168.1.10", "address1"); - DesensitizedConverter.addSensitive("/197.168.1.10", "address2"); + DesensitizedConverter.addSensitive("192.168.1.10", "address1"); + DesensitizedConverter.addSensitive("197.168.1.10", "address2"); + + Method method = converter.getClass().getDeclaredMethod( + "desensitization", String.class); + method.setAccessible(true); String logStr1 = "This is test log /192.168.1.10:100, /197.168.1.10:200, /197.168.1.10:100"; - Assert.assertEquals("This is test log address1:100, address2:200, address2:100", - converter.desensitization(logStr1)); + String result1 = (String) method.invoke(converter, logStr1); + Assert.assertEquals("This is test log /address1:100, /address2:200, /address2:100", + result1); String logStr2 = "This is test log /192.168.1.100:100, /197.168.1.10:200, /197.168.1.10:100"; - Assert.assertEquals("This is test log unknown:100, address2:200, address2:100", - converter.desensitization(logStr2)); + String result2 = (String) method.invoke(converter, logStr2); + Assert.assertEquals("This is test log /IP:100, /address2:200, /address2:100", + result2); } } From fe065dac0672311a40df0d71f1de526c582dd5bc Mon Sep 17 00:00:00 2001 From: chaozhu Date: Thu, 14 Nov 2024 17:56:01 +0800 Subject: [PATCH 1087/1197] update jacoco version --- plugins/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/build.gradle b/plugins/build.gradle index b85a435dc30..7028686f3d0 100644 --- a/plugins/build.gradle +++ b/plugins/build.gradle @@ -6,7 +6,7 @@ apply plugin: 'application' apply plugin: 'checkstyle' jacoco { - toolVersion = "0.8.4" + toolVersion = "0.8.8" } def versions = [ checkstyle: '8.7', From 3da676e260fc5e631445d00b7c807f4f1293d77e Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 15 Nov 2024 14:28:12 +0800 Subject: [PATCH 1088/1197] fix the bug of eth_getLogs --- .../jsonrpc/filters/LogBlockQuery.java | 8 ++-- .../org/tron/core/jsonrpc/JsonRpcTest.java | 46 +++++++++++++++++-- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogBlockQuery.java b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogBlockQuery.java index 94e29e657be..7ee6ce74c10 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogBlockQuery.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogBlockQuery.java @@ -191,17 +191,17 @@ public int[][][] getConditions() { Bloom bloom = Bloom.create(hash); BitSet bs = BitSet.valueOf(bloom.getData()); - int[] bitIndex = new int[3]; //must same as the number of hash function in Bloom - int nonZeroCount = 0; + //number of nonZero positions may be equal or less than number(3) of hash function in Bloom + List bitIndexList = new ArrayList<>(); for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) { // operate on index i here if (i == Integer.MAX_VALUE) { break; // or (i+1) would overflow } - bitIndex[nonZeroCount++] = i; + bitIndexList.add(i); } - bitIndexes[j] = bitIndex; + bitIndexes[j] = bitIndexList.stream().mapToInt(Integer::intValue).toArray(); } allConditionsIndex[k] = bitIndexes; } diff --git a/framework/src/test/java/org/tron/core/jsonrpc/JsonRpcTest.java b/framework/src/test/java/org/tron/core/jsonrpc/JsonRpcTest.java index f221d0c95ac..81d2af47bbf 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/JsonRpcTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/JsonRpcTest.java @@ -347,17 +347,16 @@ private int[] getBloomIndex(String s) { Bloom bloom = Bloom.create(Hash.sha3(ByteArray.fromHexString(s))); BitSet bs = BitSet.valueOf(bloom.getData()); - int[] bitIndex = new int[3]; //must same as the number of hash function in Bloom - int nonZeroCount = 0; + List bitIndexList = new ArrayList<>(); for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) { // operate on index i here if (i == Integer.MAX_VALUE) { break; // or (i+1) would overflow } - bitIndex[nonZeroCount++] = i; + bitIndexList.add(i); } - return bitIndex; + return bitIndexList.stream().mapToInt(Integer::intValue).toArray(); } @Test @@ -416,4 +415,43 @@ public void testGetConditions() { Assert.fail(); } } + + @Test + public void testGetConditionWithHashCollision() { + try { + List addressList = new ArrayList<>(); + addressList.add("0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85"); + addressList.add("0x3038114c1a1e72c5bfa8b003bc3650ad2ba254a0"); + + Object[] topics = new Object[0]; + + LogFilterWrapper logFilterWrapper = + new LogFilterWrapper(new FilterRequest(null, + null, + addressList, + topics, + null), + 100, + null); + + LogBlockQuery logBlockQuery = new LogBlockQuery(logFilterWrapper, null, 100, null); + int[][][] conditions = logBlockQuery.getConditions(); + //level = depth(address) + depth(topics), skip null + Assert.assertEquals(1, conditions.length); + //elements number + Assert.assertEquals(2, conditions[0].length); + + Assert.assertEquals(3, conditions[0][0].length); + //Hash collision, only two nonZero position + Assert.assertEquals(2, conditions[0][1].length); + + Assert.assertArrayEquals(conditions[0][0], + getBloomIndex("0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85")); + Assert.assertArrayEquals(conditions[0][1], + getBloomIndex("0x3038114c1a1e72c5bfa8b003bc3650ad2ba254a0")); + + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + } } From 86ab5add57f683f5f87e9a323cb3ff0e777cd744 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 15 Nov 2024 17:29:31 +0800 Subject: [PATCH 1089/1197] checkout payment in checkShieldedTRC20NoteValue --- framework/src/main/java/org/tron/core/Wallet.java | 6 ++++++ .../src/main/java/org/tron/core/zen/address/KeyIo.java | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 769274e8f2a..dd5087288dc 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -3438,6 +3438,9 @@ private void checkShieldedTRC20NoteValue( if (spendNote.getNote().getValue() < 0) { throw new ContractValidateException("The value in SpendNoteTRC20 must >= 0"); } + if (StringUtils.isEmpty(spendNote.getNote().getPaymentAddress())) { + throw new ContractValidateException("Payment Address in SpendNote should not be empty"); + } } } @@ -3446,6 +3449,9 @@ private void checkShieldedTRC20NoteValue( if (receiveNote.getNote().getValue() < 0) { throw new ContractValidateException("The value in ReceiveNote must >= 0"); } + if (StringUtils.isEmpty(receiveNote.getNote().getPaymentAddress())) { + throw new ContractValidateException("Payment Address in ReceiveNote should not be empty"); + } } } } diff --git a/framework/src/main/java/org/tron/core/zen/address/KeyIo.java b/framework/src/main/java/org/tron/core/zen/address/KeyIo.java index 9dc28b9ff03..85e90f6ad8d 100644 --- a/framework/src/main/java/org/tron/core/zen/address/KeyIo.java +++ b/framework/src/main/java/org/tron/core/zen/address/KeyIo.java @@ -19,6 +19,7 @@ import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.List; +import org.apache.commons.lang3.StringUtils; import org.tron.common.utils.Bech32; import org.tron.common.utils.Bech32.Bech32Data; @@ -29,6 +30,9 @@ public class KeyIo { private static String SAPLING_PAYMENT_ADDRESS = "ztron"; public static PaymentAddress decodePaymentAddress(String str) { + if (StringUtils.isEmpty(str)) { + return null; + } byte[] data; Bech32Data bech = Bech32.decode(str); if (bech.hrp.equals(SAPLING_PAYMENT_ADDRESS) From 4717f87407706b848f792ff6d72c89f5ed5e7d1a Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Tue, 19 Nov 2024 15:10:05 +0800 Subject: [PATCH 1090/1197] add test case testCreateShieldedContractParameters2 without payment_address --- .../java/org/tron/core/ShieldWalletTest.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/framework/src/test/java/org/tron/core/ShieldWalletTest.java b/framework/src/test/java/org/tron/core/ShieldWalletTest.java index 5bc2a31c9d0..fe095723c77 100644 --- a/framework/src/test/java/org/tron/core/ShieldWalletTest.java +++ b/framework/src/test/java/org/tron/core/ShieldWalletTest.java @@ -19,6 +19,7 @@ import org.tron.core.capsule.TransactionCapsule; import org.tron.core.config.args.Args; import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; import org.tron.core.services.http.JsonFormat; import org.tron.core.services.http.JsonFormat.ParseException; @@ -337,6 +338,48 @@ public void testCreateShieldedContractParameters() throws ContractExeException { } } + @Test + public void testCreateShieldedContractParameters2() throws ContractExeException { + librustzcashInitZksnarkParams(); + Args.getInstance().setFullNodeAllowShieldedTransactionArgs(true); + Wallet wallet1 = spy(new Wallet()); + + doReturn(BigInteger.valueOf(1).toByteArray()) + .when(wallet1).getShieldedContractScalingFactor( + ByteArray.fromHexString("4144007979359ECAC395BBD3CEF8060D3DF2DC3F01")); + String parameter = new String(ByteArray.fromHexString( + "7b0a202020202261736b223a2263323531336539653330383439343933326264383265306365353336" + + "363264313734323164393062373261383437316130613132623835353261333336653032222c0a202" + + "02020226e736b223a2234633662663364643461303634336432306236323866376534353938306335" + + "653138376630376135316436663365383661616631616239313663303765623064222c0a202020202" + + "26f766b223a2231376135386439613530353864613665343263613132636432383964306136616131" + + "363962393236633138653139626361353138623864366638363734653433222c0a202020202266726" + + "f6d5f616d6f756e74223a22313030222c0a2020202022736869656c6465645f726563656976657322" + + "3a5b0a20202020202020207b0a202020202020202020202020226e6f7465223a7b0a2020202020202" + + "02020202020202020202276616c7565223a3130302c0a202020202020202020202020202020202270" + + "61796d656e745f61646472657373223a22222c0a202020202020202020202020202020202272636d2" + + "23a223136623666356534303434346162376565616231316165363631336332376633353131373937" + + "3165666138376237313536306235383133383239633933393064220a2020202020202020202020207" + + "d0a20202020202020207d0a202020205d2c0a2020202022736869656c6465645f54524332305f636f" + + "6e74726163745f61646472657373223a2234313434303037393739333539454341433339354242443" + + "3434546383036304433444632444333463031220a7d")); + PrivateShieldedTRC20Parameters.Builder builder = PrivateShieldedTRC20Parameters.newBuilder(); + try { + JsonFormat.merge(parameter, builder, false); + } catch (ParseException e) { + Assert.fail(); + } + + try { + wallet1.createShieldedContractParameters(builder.build()); + Assert.fail(); + } catch (Exception e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Payment Address in ReceiveNote should not be empty", + e.getMessage()); + } + } + @Test public void testCreateShieldedContractParametersWithoutAsk() throws ContractExeException { librustzcashInitZksnarkParams(); From e15eccecf2ff84c639e643f3d64e5850eccbf6b0 Mon Sep 17 00:00:00 2001 From: Simon <107106002+CarlChaoCarl@users.noreply.github.com> Date: Wed, 20 Nov 2024 14:40:54 +0800 Subject: [PATCH 1091/1197] Revert "feat(test): improve tests coverage (#6034)" This reverts commit 333d25c6f6b52395b359c030eb130106fa8cbb38. --- build.gradle | 5 +- framework/build.gradle | 27 +- .../TransactionLogTriggerCapsuleMockTest.java | 130 -- .../TransactionLogTriggerCapsuleTest.java | 69 - .../common/runtime/RuntimeImplMockTest.java | 57 - .../java/org/tron/core/WalletMockTest.java | 1174 ----------------- .../org/tron/core/db/ManagerMockTest.java | 384 ------ .../net/peer/PeerStatusCheckMockTest.java | 33 - .../core/services/http/JsonFormatTest.java | 266 ---- .../tron/core/services/http/UtilMockTest.java | 250 ---- 10 files changed, 2 insertions(+), 2393 deletions(-) delete mode 100644 framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleMockTest.java delete mode 100644 framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java delete mode 100644 framework/src/test/java/org/tron/core/WalletMockTest.java delete mode 100755 framework/src/test/java/org/tron/core/db/ManagerMockTest.java delete mode 100644 framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckMockTest.java delete mode 100644 framework/src/test/java/org/tron/core/services/http/JsonFormatTest.java delete mode 100644 framework/src/test/java/org/tron/core/services/http/UtilMockTest.java diff --git a/build.gradle b/build.gradle index 8db08f4fe7e..b1aba1c0aa9 100644 --- a/build.gradle +++ b/build.gradle @@ -52,10 +52,7 @@ subprojects { testAnnotationProcessor 'org.projectlombok:lombok:1.18.12' testImplementation group: 'junit', name: 'junit', version: '4.13.2' - testImplementation "org.mockito:mockito-core:3.10.0" - testImplementation group: 'org.powermock', name: 'powermock-module-junit4', version: '2.0.9' - testImplementation group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.9' - + testImplementation "org.mockito:mockito-core:2.13.0" } task sourcesJar(type: Jar, dependsOn: classes) { diff --git a/framework/build.gradle b/framework/build.gradle index 4519f93e44d..ec113c93cb1 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -2,14 +2,12 @@ plugins { id "org.gradle.test-retry" version "1.5.9" id "org.sonarqube" version "2.6" id "com.gorylenko.gradle-git-properties" version "2.4.1" - id "io.github.surpsg.offlins" version "0.3.0" } gitProperties.failOnNoGitDirectory = false; apply plugin: 'application' apply plugin: 'checkstyle' -apply plugin: "io.github.surpsg.offlins" mainClassName = 'org.tron.program.FullNode' @@ -18,7 +16,7 @@ def versions = [ ] jacoco { - toolVersion = "0.8.8" + toolVersion = "0.8.1" } @@ -123,12 +121,10 @@ test { testLogging { exceptionFormat = 'full' } - /* jacoco { destinationFile = file("$buildDir/jacoco/jacocoTest.exec") classDumpDir = file("$buildDir/jacoco/classpathdumps") } - */ if (isWindows()) { exclude '**/ShieldedTransferActuatorTest.class' exclude '**/BackupDbUtilTest.class' @@ -145,7 +141,6 @@ test { } } -/* jacocoTestReport { reports { xml.enabled true @@ -154,26 +149,6 @@ jacocoTestReport { } getExecutionData().setFrom(fileTree('../framework/build/jacoco').include("**.exec")) } - */ - -offlinsCoverage { - jacocoVersion = '0.8.8' // Optional. By default `0.8.8` - - reports { - html.enabled.set true // Optional. By default `true` - html.location.set project.file('build/reports/jacoco/test/html') // Optional. By default `build/reports/jacoco/html` - - xml.enabled.set true // Optional. By default `false` - xml.location.set project.file('build/reports/jacoco/test/jacocoTestReport.xml') - // Optional. By default `build/reports/jacoco/coverageReport.xml` - - csv.enabled.set true // Optional. By default `false` - csv.location.set project.file('build/reports/jacoco/test/csvCoverage.csv') - // Optional. By default `build/reports/jacoco/coverageReport.csv` - } -} - - def binaryRelease(taskName, jarName, mainClass) { return tasks.create("${taskName}", Jar) { diff --git a/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleMockTest.java b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleMockTest.java deleted file mode 100644 index 8734206d3c5..00000000000 --- a/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleMockTest.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.tron.common.logsfilter; - -import static org.powermock.api.mockito.PowerMockito.mock; -import static org.powermock.api.mockito.PowerMockito.spy; -import static org.powermock.api.mockito.PowerMockito.when; - -import com.google.protobuf.ByteString; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; -import org.tron.common.logsfilter.capsule.TransactionLogTriggerCapsule; -import org.tron.common.logsfilter.trigger.InternalTransactionPojo; -import org.tron.common.runtime.InternalTransaction; -import org.tron.common.runtime.ProgramResult; -import org.tron.common.runtime.RuntimeImpl; -import org.tron.common.utils.Sha256Hash; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.ReceiptCapsule; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.db.TransactionTrace; -import org.tron.p2p.utils.ByteArray; -import org.tron.protos.Protocol; -import org.tron.protos.contract.BalanceContract; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({ - TransactionLogTriggerCapsule.class, - TransactionTrace.class -}) -public class TransactionLogTriggerCapsuleMockTest { - - private static final String OWNER_ADDRESS = "41548794500882809695a8a687866e76d4271a1abc"; - private static final String RECEIVER_ADDRESS = "41abd4b9367799eaa3197fecb144eb71de1e049150"; - private static final String CONTRACT_ADDRESS = "A0B4750E2CD76E19DCA331BF5D089B71C3C2798548"; - - private TransactionCapsule transactionCapsule; - private BlockCapsule blockCapsule; - - @Before - public void setup() { - blockCapsule = new BlockCapsule(1, - Sha256Hash.ZERO_HASH, - System.currentTimeMillis(), - Sha256Hash.ZERO_HASH.getByteString() - ); - } - - @After - public void clearMocks() { - Mockito.framework().clearInlineMocks(); - } - - - @Test - public void testConstructorWithTransactionTrace() { - BalanceContract.TransferContract.Builder builder2 = - BalanceContract.TransferContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) - .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); - transactionCapsule = spy(new TransactionCapsule(builder2.build(), - Protocol.Transaction.Contract.ContractType.TransferContract)); - - TransactionTrace trace = mock(TransactionTrace.class); - ReceiptCapsule receiptCapsule = new ReceiptCapsule(Sha256Hash.ZERO_HASH); - RuntimeImpl runtime = mock(RuntimeImpl.class); - List logs = new ArrayList<>(); - logs.add(Protocol.TransactionInfo.Log.newBuilder() - .setAddress(ByteString.copyFrom("address".getBytes())) - .setData(ByteString.copyFrom("data".getBytes())) - .addTopics(ByteString.copyFrom("topic".getBytes())) - .build()); - - Protocol.TransactionInfo.Builder builder = Protocol.TransactionInfo.newBuilder() - .addAllLog(logs); - - ProgramResult programResult = ProgramResult.createEmpty(); - programResult.setHReturn("hreturn".getBytes()); - programResult.setContractAddress(CONTRACT_ADDRESS.getBytes()); - - when(transactionCapsule.getTrxTrace()).thenReturn(trace); - when(trace.getReceipt()).thenReturn(receiptCapsule); - when(trace.getRuntime()).thenReturn(runtime); - when(runtime.getResult()).thenReturn(programResult); - - transactionCapsule.setTrxTrace(trace); - - TransactionLogTriggerCapsule triggerCapsule = new TransactionLogTriggerCapsule( - transactionCapsule, blockCapsule,0,0,0, - builder.build(),0); - - Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger()); - } - - @Test - public void testGetInternalTransactionList() throws Exception { - BalanceContract.TransferContract.Builder builder2 = - BalanceContract.TransferContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) - .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); - transactionCapsule = new TransactionCapsule(builder2.build(), - Protocol.Transaction.Contract.ContractType.TransferContract); - InternalTransaction internalTransaction = new InternalTransaction( - "parentHash".getBytes(), 10, 0, - "sendAddress".getBytes(), - "transferToAddress".getBytes(), - 100L, "data".getBytes(), "note", - 0L, new HashMap<>() - ); - List internalTransactionList = new ArrayList<>(); - internalTransactionList.add(internalTransaction); - TransactionLogTriggerCapsule triggerCapsule = - new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); - - List pojoList = Whitebox.invokeMethod(triggerCapsule, - "getInternalTransactionList", internalTransactionList); - - Assert.assertNotNull(pojoList); - } - -} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java index 93401e0d415..76dd6e99158 100644 --- a/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java +++ b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java @@ -13,16 +13,13 @@ import org.tron.core.capsule.TransactionCapsule; import org.tron.p2p.utils.ByteArray; import org.tron.protos.Protocol; -import org.tron.protos.contract.AssetIssueContractOuterClass; import org.tron.protos.contract.BalanceContract; import org.tron.protos.contract.Common; -import org.tron.protos.contract.SmartContractOuterClass; public class TransactionLogTriggerCapsuleTest { private static final String OWNER_ADDRESS = "41548794500882809695a8a687866e76d4271a1abc"; private static final String RECEIVER_ADDRESS = "41abd4b9367799eaa3197fecb144eb71de1e049150"; - private static final String CONTRACT_ADDRESS = "A0B4750E2CD76E19DCA331BF5D089B71C3C2798548"; public TransactionCapsule transactionCapsule; public BlockCapsule blockCapsule; @@ -178,70 +175,4 @@ public void testConstructorWithCancelAllUnfreezeTrxCapsule() { triggerCapsule.getTransactionLogTrigger().getExtMap().get(BANDWIDTH.name()).longValue()); } - @Test - public void testConstructorWithTransferCapsule() { - BalanceContract.TransferContract.Builder builder2 = - BalanceContract.TransferContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) - .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); - transactionCapsule = new TransactionCapsule(builder2.build(), - Protocol.Transaction.Contract.ContractType.TransferContract); - - TransactionLogTriggerCapsule triggerCapsule = - new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); - - Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); - Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getToAddress()); - } - - @Test - public void testConstructorWithTransferAssetCapsule() { - AssetIssueContractOuterClass.TransferAssetContract.Builder builder2 = - AssetIssueContractOuterClass.TransferAssetContract.newBuilder() - .setAssetName(ByteString.copyFrom("AssetName".getBytes())) - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) - .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); - transactionCapsule = new TransactionCapsule(builder2.build(), - Protocol.Transaction.Contract.ContractType.TransferAssetContract); - - TransactionLogTriggerCapsule triggerCapsule = - new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); - - Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); - Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getToAddress()); - } - - @Test - public void testConstructorWithTriggerSmartContract() { - SmartContractOuterClass.TriggerSmartContract.Builder builder2 = - SmartContractOuterClass.TriggerSmartContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) - .setContractAddress(ByteString.copyFrom(ByteArray.fromHexString(CONTRACT_ADDRESS))); - transactionCapsule = new TransactionCapsule(builder2.build(), - Protocol.Transaction.Contract.ContractType.TriggerSmartContract); - - TransactionLogTriggerCapsule triggerCapsule = - new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); - - Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); - Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getToAddress()); - } - - @Test - public void testConstructorWithCreateSmartContract() { - SmartContractOuterClass.CreateSmartContract.Builder builder2 = - SmartContractOuterClass.CreateSmartContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); - transactionCapsule = new TransactionCapsule(builder2.build(), - Protocol.Transaction.Contract.ContractType.CreateSmartContract); - - TransactionLogTriggerCapsule triggerCapsule = - new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); - - Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); - } - - - - } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java b/framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java deleted file mode 100644 index 0b8228f28ba..00000000000 --- a/framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.tron.common.runtime; - -import lombok.extern.slf4j.Slf4j; -import org.junit.After; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; -import org.tron.core.vm.program.Program; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({RuntimeImpl.class}) -@Slf4j -public class RuntimeImplMockTest { - @After - public void clearMocks() { - Mockito.framework().clearInlineMocks(); - } - - @Test - public void testSetResultCode1() throws Exception { - RuntimeImpl runtime = new RuntimeImpl(); - ProgramResult programResult = new ProgramResult(); - - Program.BadJumpDestinationException badJumpDestinationException - = new Program.BadJumpDestinationException("Operation with pc isn't 'JUMPDEST': PC[%d];", 0); - programResult.setException(badJumpDestinationException); - Whitebox.invokeMethod(runtime,"setResultCode", programResult); - - Program.OutOfTimeException outOfTimeException - = new Program.OutOfTimeException("CPU timeout for 0x0a executing"); - programResult.setException(outOfTimeException); - Whitebox.invokeMethod(runtime,"setResultCode", programResult); - - Program.PrecompiledContractException precompiledContractException - = new Program.PrecompiledContractException("precompiled contract exception"); - programResult.setException(precompiledContractException); - Whitebox.invokeMethod(runtime,"setResultCode", programResult); - - Program.StackTooSmallException stackTooSmallException - = new Program.StackTooSmallException("Expected stack size %d but actual %d;", 100, 10); - programResult.setException(stackTooSmallException); - Whitebox.invokeMethod(runtime,"setResultCode", programResult); - - Program.JVMStackOverFlowException jvmStackOverFlowException - = new Program.JVMStackOverFlowException(); - programResult.setException(jvmStackOverFlowException); - Whitebox.invokeMethod(runtime,"setResultCode", programResult); - - Assert.assertTrue(true); - } - -} - diff --git a/framework/src/test/java/org/tron/core/WalletMockTest.java b/framework/src/test/java/org/tron/core/WalletMockTest.java deleted file mode 100644 index e3b4384ff1b..00000000000 --- a/framework/src/test/java/org/tron/core/WalletMockTest.java +++ /dev/null @@ -1,1174 +0,0 @@ -package org.tron.core; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.powermock.api.mockito.PowerMockito.mockStatic; -import static org.powermock.api.mockito.PowerMockito.whenNew; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.protobuf.Any; -import com.google.protobuf.ByteString; -import com.google.protobuf.LazyStringArrayList; - -import java.math.BigInteger; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import org.junit.After; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; -import org.tron.api.GrpcAPI; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.Sha256Hash; -import org.tron.common.utils.client.WalletClient; -import org.tron.core.capsule.AccountCapsule; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.ContractCapsule; -import org.tron.core.capsule.ContractStateCapsule; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; -import org.tron.core.db.TransactionStore; -import org.tron.core.exception.AccountResourceInsufficientException; -import org.tron.core.exception.BadItemException; -import org.tron.core.exception.ContractExeException; -import org.tron.core.exception.ContractValidateException; -import org.tron.core.exception.DupTransactionException; -import org.tron.core.exception.HeaderNotFound; -import org.tron.core.exception.ItemNotFoundException; -import org.tron.core.exception.TaposException; -import org.tron.core.exception.TooBigTransactionException; -import org.tron.core.exception.TronException; -import org.tron.core.exception.VMIllegalException; -import org.tron.core.exception.ValidateSignatureException; -import org.tron.core.exception.ZksnarkException; -import org.tron.core.net.TronNetDelegate; -import org.tron.core.net.message.adv.TransactionMessage; -import org.tron.core.net.peer.PeerConnection; -import org.tron.core.store.AbiStore; -import org.tron.core.store.AccountStore; -import org.tron.core.store.CodeStore; -import org.tron.core.store.ContractStateStore; -import org.tron.core.store.ContractStore; -import org.tron.core.store.DynamicPropertiesStore; -import org.tron.core.store.TransactionHistoryStore; -import org.tron.core.store.TransactionRetStore; -import org.tron.core.zen.ShieldedTRC20ParametersBuilder; -import org.tron.core.zen.address.DiversifierT; -import org.tron.core.zen.address.ExpandedSpendingKey; -import org.tron.core.zen.address.KeyIo; -import org.tron.core.zen.address.PaymentAddress; -import org.tron.protos.Protocol; -import org.tron.protos.contract.BalanceContract; -import org.tron.protos.contract.ShieldContract; -import org.tron.protos.contract.SmartContractOuterClass; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({ - Wallet.class, - Args.class, - CommonParameter.class, - TransactionCapsule.class, - com.google.protobuf.Message.class, - ByteUtil.class, - KeyIo.class, - PaymentAddress.class, - Protocol.Transaction.Contract.ContractType.class -}) -public class WalletMockTest { - - @After - public void clearMocks() { - Mockito.framework().clearInlineMocks(); - } - - @Test - public void testSetTransactionNullException() throws Exception { - Wallet wallet = new Wallet(); - TransactionCapsule transactionCapsuleMock - = mock(TransactionCapsule.class); - Whitebox.invokeMethod(wallet, - "setTransaction", transactionCapsuleMock); - assertTrue(true); - } - - @Test - public void testCreateTransactionCapsuleWithoutValidateWithTimeoutNullException() - throws Exception { - Wallet wallet = new Wallet(); - com.google.protobuf.Message message = - mock(com.google.protobuf.Message.class); - Protocol.Transaction.Contract.ContractType contractType = - mock(Protocol.Transaction.Contract.ContractType.class); - long timeout = 100L; - TransactionCapsule transactionCapsuleMock = - mock(TransactionCapsule.class); - - whenNew(TransactionCapsule.class) - .withAnyArguments().thenReturn(transactionCapsuleMock); - try { - Whitebox.invokeMethod(wallet, - "createTransactionCapsuleWithoutValidateWithTimeout", - message, contractType, timeout); - } catch (Exception e) { - assertTrue(false); - } - - assertTrue(true); - } - - @Test - public void testCreateTransactionCapsuleWithoutValidateWithTimeout() - throws Exception { - Wallet wallet = new Wallet(); - com.google.protobuf.Message message = - mock(com.google.protobuf.Message.class); - Protocol.Transaction.Contract.ContractType contractType = - mock(Protocol.Transaction.Contract.ContractType.class); - long timeout = 100L; - BlockCapsule.BlockId blockId = new BlockCapsule.BlockId(); - - TransactionCapsule transactionCapsuleMock = mock(TransactionCapsule.class); - ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); - Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); - - when(chainBaseManagerMock.getHeadBlockId()).thenReturn(blockId); - - whenNew(TransactionCapsule.class) - .withAnyArguments().thenReturn(transactionCapsuleMock); - Whitebox.invokeMethod(wallet, - "createTransactionCapsuleWithoutValidateWithTimeout", - message, contractType, timeout); - assertTrue(true); - } - - - @Test - public void testBroadcastTransactionBlockUnsolidified() throws Exception { - Wallet wallet = new Wallet(); - Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); - - TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); - when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(true); - - Whitebox.setInternalState(wallet, "tronNetDelegate", tronNetDelegateMock); - - GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); - - assertEquals(GrpcAPI.Return.response_code.BLOCK_UNSOLIDIFIED, ret.getCode()); - } - - @Test - public void testBroadcastTransactionNoConnection() throws Exception { - Wallet wallet = new Wallet(); - Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); - List peerConnections = new ArrayList<>(); - - TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); - when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); - - Whitebox.setInternalState(wallet, "tronNetDelegate", tronNetDelegateMock); - Whitebox.setInternalState(wallet, "minEffectiveConnection", 10); - when(tronNetDelegateMock.getActivePeer()).thenReturn(peerConnections); - - GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); - - assertEquals(GrpcAPI.Return.response_code.NO_CONNECTION, ret.getCode()); - } - - @Test - public void testBroadcastTransactionConnectionNotEnough() throws Exception { - Wallet wallet = new Wallet(); - Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); - List peerConnections = new ArrayList<>(); - PeerConnection p1 = new PeerConnection(); - PeerConnection p2 = new PeerConnection(); - peerConnections.add(p1); - peerConnections.add(p2); - - TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); - when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); - - Whitebox.setInternalState(wallet, "tronNetDelegate", tronNetDelegateMock); - Whitebox.setInternalState(wallet, "minEffectiveConnection", 10); - when(tronNetDelegateMock.getActivePeer()).thenReturn(peerConnections); - - GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); - - assertEquals(GrpcAPI.Return.response_code.NOT_ENOUGH_EFFECTIVE_CONNECTION, - ret.getCode()); - } - - @Test - public void testBroadcastTransactionTooManyPending() throws Exception { - Wallet wallet = new Wallet(); - Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); - - TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); - Manager managerMock = mock(Manager.class); - when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); - when(managerMock.isTooManyPending()).thenReturn(true); - - Whitebox.setInternalState(wallet, "tronNetDelegate", tronNetDelegateMock); - Whitebox.setInternalState(wallet, "dbManager", managerMock); - - GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); - - assertEquals(GrpcAPI.Return.response_code.SERVER_BUSY, ret.getCode()); - } - - @Test - public void testBroadcastTransactionAlreadyExists() throws Exception { - Wallet wallet = new Wallet(); - Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); - TransactionCapsule trx = new TransactionCapsule(transaction); - trx.setTime(System.currentTimeMillis()); - Sha256Hash txID = trx.getTransactionId(); - - Cache transactionIdCache = CacheBuilder - .newBuilder().maximumSize(10) - .expireAfterWrite(1, TimeUnit.HOURS).recordStats().build(); - transactionIdCache.put(txID, true); - - TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); - Manager managerMock = mock(Manager.class); - when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); - when(managerMock.isTooManyPending()).thenReturn(false); - when(managerMock.getTransactionIdCache()).thenReturn(transactionIdCache); - - Whitebox.setInternalState(wallet, "tronNetDelegate", tronNetDelegateMock); - Whitebox.setInternalState(wallet, "dbManager", managerMock); - Whitebox.setInternalState(wallet, "trxCacheEnable", true); - - GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); - - assertEquals(GrpcAPI.Return.response_code.DUP_TRANSACTION_ERROR, - ret.getCode()); - } - - - @Test - public void testBroadcastTransactionNoContract() throws Exception { - Wallet wallet = new Wallet(); - Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); - - TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); - Manager managerMock = mock(Manager.class); - ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); - DynamicPropertiesStore dynamicPropertiesStoreMock - = mock(DynamicPropertiesStore.class); - when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); - when(managerMock.isTooManyPending()).thenReturn(false); - when(chainBaseManagerMock.getDynamicPropertiesStore()) - .thenReturn(dynamicPropertiesStoreMock); - when(dynamicPropertiesStoreMock.supportVM()).thenReturn(false); - - Whitebox.setInternalState(wallet, "tronNetDelegate", tronNetDelegateMock); - Whitebox.setInternalState(wallet, "dbManager", managerMock); - Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); - Whitebox.setInternalState(wallet, "trxCacheEnable", false); - - GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); - - assertEquals(GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR, - ret.getCode()); - } - - @Test - public void testBroadcastTransactionOtherException() throws Exception { - Wallet wallet = new Wallet(); - Protocol.Transaction transaction = getExampleTrans(); - - TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); - Manager managerMock = mock(Manager.class); - ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); - DynamicPropertiesStore dynamicPropertiesStoreMock - = mock(DynamicPropertiesStore.class); - when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); - when(managerMock.isTooManyPending()).thenReturn(false); - when(chainBaseManagerMock.getDynamicPropertiesStore()) - .thenReturn(dynamicPropertiesStoreMock); - when(dynamicPropertiesStoreMock.supportVM()).thenReturn(false); - - Whitebox.setInternalState(wallet, "tronNetDelegate", tronNetDelegateMock); - Whitebox.setInternalState(wallet, "dbManager", managerMock); - Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); - Whitebox.setInternalState(wallet, "trxCacheEnable", false); - - GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); - - assertEquals(GrpcAPI.Return.response_code.OTHER_ERROR, ret.getCode()); - } - - private Protocol.Transaction getExampleTrans() { - BalanceContract.TransferContract transferContract = - BalanceContract.TransferContract.newBuilder() - .setAmount(10) - .setOwnerAddress(ByteString.copyFromUtf8("aaa")) - .setToAddress(ByteString.copyFromUtf8("bbb")) - .build(); - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < 6666; i++) { - sb.append("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - } - return Protocol.Transaction.newBuilder().setRawData( - Protocol.Transaction.raw.newBuilder() - .setData(ByteString.copyFrom(sb.toString().getBytes(StandardCharsets.UTF_8))) - .addContract( - Protocol.Transaction.Contract.newBuilder() - .setParameter(Any.pack(transferContract)) - .setType(Protocol.Transaction.Contract.ContractType.TransferContract))) - .build(); - } - - private void mockEnv(Wallet wallet, TronException tronException) throws Exception { - TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); - Manager managerMock = mock(Manager.class); - ChainBaseManager chainBaseManagerMock - = mock(ChainBaseManager.class); - DynamicPropertiesStore dynamicPropertiesStoreMock - = mock(DynamicPropertiesStore.class); - TransactionMessage transactionMessageMock - = mock(TransactionMessage.class); - - when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); - when(managerMock.isTooManyPending()).thenReturn(false); - when(chainBaseManagerMock.getDynamicPropertiesStore()) - .thenReturn(dynamicPropertiesStoreMock); - when(dynamicPropertiesStoreMock.supportVM()).thenReturn(false); - whenNew(TransactionMessage.class) - .withAnyArguments().thenReturn(transactionMessageMock); - doThrow(tronException).when(managerMock).pushTransaction(any()); - - Whitebox.setInternalState(wallet, "tronNetDelegate", tronNetDelegateMock); - Whitebox.setInternalState(wallet, "dbManager", managerMock); - Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); - Whitebox.setInternalState(wallet, "trxCacheEnable", false); - } - - @Test - public void testBroadcastTransactionValidateSignatureException() throws Exception { - Wallet wallet = new Wallet(); - Protocol.Transaction transaction = getExampleTrans(); - mockEnv(wallet, new ValidateSignatureException()); - GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); - assertEquals(GrpcAPI.Return.response_code.SIGERROR, ret.getCode()); - } - - @Test - public void testBroadcastTransactionValidateContractExeException() throws Exception { - Wallet wallet = new Wallet(); - Protocol.Transaction transaction = getExampleTrans(); - mockEnv(wallet, new ContractExeException()); - GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); - assertEquals(GrpcAPI.Return.response_code.CONTRACT_EXE_ERROR, ret.getCode()); - } - - @Test - public void testBroadcastTransactionValidateAccountResourceInsufficientException() - throws Exception { - Wallet wallet = new Wallet(); - Protocol.Transaction transaction = getExampleTrans(); - mockEnv(wallet, new AccountResourceInsufficientException("")); - GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); - assertEquals(GrpcAPI.Return.response_code.BANDWITH_ERROR, ret.getCode()); - } - - @Test - public void testBroadcastTransactionValidateDupTransactionException() - throws Exception { - Wallet wallet = new Wallet(); - Protocol.Transaction transaction = getExampleTrans(); - mockEnv(wallet, new DupTransactionException("")); - GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); - assertEquals(GrpcAPI.Return.response_code.DUP_TRANSACTION_ERROR, ret.getCode()); - } - - @Test - public void testBroadcastTransactionValidateTaposException() throws Exception { - Wallet wallet = new Wallet(); - Protocol.Transaction transaction = getExampleTrans(); - mockEnv(wallet, new TaposException("")); - GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); - assertEquals(GrpcAPI.Return.response_code.TAPOS_ERROR, ret.getCode()); - } - - @Test - public void testBroadcastTransactionValidateTooBigTransactionException() - throws Exception { - Wallet wallet = new Wallet(); - Protocol.Transaction transaction = getExampleTrans(); - mockEnv(wallet, new TooBigTransactionException("")); - - GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); - assertEquals(GrpcAPI.Return.response_code.TOO_BIG_TRANSACTION_ERROR, ret.getCode()); - } - - @Test - public void testGetBlockByNum() throws Exception { - Wallet wallet = new Wallet(); - ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); - Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); - doThrow(new ItemNotFoundException()).when(chainBaseManagerMock).getBlockByNum(anyLong()); - - Protocol.Block block = wallet.getBlockByNum(0L); - assertNull(block); - } - - @Test - public void testGetBlockCapsuleByNum() throws Exception { - Wallet wallet = new Wallet(); - ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); - Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); - doThrow(new ItemNotFoundException()).when(chainBaseManagerMock).getBlockByNum(anyLong()); - - BlockCapsule blockCapsule = wallet.getBlockCapsuleByNum(0L); - assertNull(blockCapsule); - } - - @Test - public void testGetTransactionCountByBlockNum() throws Exception { - Wallet wallet = new Wallet(); - ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); - Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); - doThrow(new ItemNotFoundException()).when(chainBaseManagerMock).getBlockByNum(anyLong()); - - long count = wallet.getTransactionCountByBlockNum(0L); - assertEquals(count, 0L); - } - - @Test - public void testGetTransactionById() throws Exception { - Wallet wallet = new Wallet(); - ByteString transactionId = null; - Protocol.Transaction transaction = wallet.getTransactionById(transactionId); - assertNull(transaction); - } - - @Test - public void testGetTransactionById2() throws Exception { - Wallet wallet = new Wallet(); - ByteString transactionId = ByteString.empty(); - ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); - TransactionStore transactionStoreMock = mock(TransactionStore.class); - - when(chainBaseManagerMock.getTransactionStore()).thenReturn(transactionStoreMock); - Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); - doThrow(new BadItemException()).when(transactionStoreMock).get(any()); - - Protocol.Transaction transaction = wallet.getTransactionById(transactionId); - assertNull(transaction); - } - - @Test - public void testGetTransactionById3() throws Exception { - Wallet wallet = new Wallet(); - ByteString transactionId = ByteString.empty(); - ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); - TransactionStore transactionStoreMock = mock(TransactionStore.class); - TransactionCapsule transactionCapsuleMock = mock(TransactionCapsule.class); - Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); - - when(chainBaseManagerMock.getTransactionStore()).thenReturn(transactionStoreMock); - Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); - when(transactionStoreMock.get(any())).thenReturn(transactionCapsuleMock); - when(transactionCapsuleMock.getInstance()).thenReturn(transaction); - - Protocol.Transaction transactionRet = wallet.getTransactionById(transactionId); - assertEquals(transaction, transactionRet); - } - - @Test - public void testGetTransactionCapsuleById() throws Exception { - Wallet wallet = new Wallet(); - ByteString transactionId = null; - TransactionCapsule transactionCapsule = wallet.getTransactionCapsuleById(transactionId); - assertNull(transactionCapsule); - } - - @Test - public void testGetTransactionCapsuleById1() throws Exception { - Wallet wallet = new Wallet(); - ByteString transactionId = ByteString.empty(); - ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); - TransactionStore transactionStoreMock = mock(TransactionStore.class); - - when(chainBaseManagerMock.getTransactionStore()).thenReturn(transactionStoreMock); - Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); - doThrow(new BadItemException()).when(transactionStoreMock).get(any()); - - TransactionCapsule transactionCapsule = wallet.getTransactionCapsuleById(transactionId); - assertNull(transactionCapsule); - } - - @Test - public void testGetTransactionInfoById() throws Exception { - Wallet wallet = new Wallet(); - ByteString transactionId = null; - Protocol.TransactionInfo transactionInfo = wallet.getTransactionInfoById(transactionId); - assertNull(transactionInfo); - } - - @Test - public void testGetTransactionInfoById1() throws Exception { - Wallet wallet = new Wallet(); - ByteString transactionId = ByteString.empty(); - ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); - TransactionRetStore transactionRetStoreMock = mock(TransactionRetStore.class); - - when(chainBaseManagerMock.getTransactionRetStore()).thenReturn(transactionRetStoreMock); - Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); - doThrow(new BadItemException()).when(transactionRetStoreMock).getTransactionInfo(any()); - - Protocol.TransactionInfo transactionInfo = wallet.getTransactionInfoById(transactionId); - assertNull(transactionInfo); - } - - @Test - public void testGetTransactionInfoById2() throws Exception { - Wallet wallet = new Wallet(); - ByteString transactionId = ByteString.empty(); - ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); - TransactionRetStore transactionRetStoreMock = mock(TransactionRetStore.class); - TransactionHistoryStore transactionHistoryStoreMock = - mock(TransactionHistoryStore.class); - - when(chainBaseManagerMock.getTransactionRetStore()) - .thenReturn(transactionRetStoreMock); - when(chainBaseManagerMock.getTransactionHistoryStore()) - .thenReturn(transactionHistoryStoreMock); - Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); - when(transactionRetStoreMock.getTransactionInfo(any())).thenReturn(null); - doThrow(new BadItemException()).when(transactionHistoryStoreMock).get(any()); - - Protocol.TransactionInfo transactionInfo = wallet.getTransactionInfoById(transactionId); - assertNull(transactionInfo); - } - - @Test - public void testGetProposalById() throws Exception { - Wallet wallet = new Wallet(); - ByteString proposalId = null; - Protocol.Proposal proposal = wallet.getProposalById(proposalId); - assertNull(proposal); - } - - @Test - public void testGetMemoFeePrices() throws Exception { - Wallet wallet = new Wallet(); - ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); - DynamicPropertiesStore dynamicPropertiesStoreMock = - mock(DynamicPropertiesStore.class); - - when(chainBaseManagerMock.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStoreMock); - doThrow(new IllegalArgumentException("not found MEMO_FEE_HISTORY")) - .when(dynamicPropertiesStoreMock).getMemoFeeHistory(); - - Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); - - GrpcAPI.PricesResponseMessage responseMessage = wallet.getMemoFeePrices(); - assertNull(responseMessage); - } - - @Test - public void testGetEnergyFeeByTime() throws Exception { - Wallet wallet = new Wallet(); - ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); - DynamicPropertiesStore dynamicPropertiesStoreMock = - mock(DynamicPropertiesStore.class); - long now = System.currentTimeMillis(); - - when(chainBaseManagerMock.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStoreMock); - doThrow(new IllegalArgumentException("not found ENERGY_PRICE_HISTORY")) - .when(dynamicPropertiesStoreMock).getEnergyPriceHistory(); - when(dynamicPropertiesStoreMock.getEnergyFee()).thenReturn(10L); - - Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); - - long energyFee = wallet.getEnergyFee(now); - assertEquals(energyFee, 10L); - } - - @Test - public void testGetEnergyPrices() throws Exception { - Wallet wallet = new Wallet(); - ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); - DynamicPropertiesStore dynamicPropertiesStoreMock = - mock(DynamicPropertiesStore.class); - - when(chainBaseManagerMock.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStoreMock); - doThrow(new IllegalArgumentException("not found ENERGY_PRICE_HISTORY")) - .when(dynamicPropertiesStoreMock).getEnergyPriceHistory(); - - Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); - - GrpcAPI.PricesResponseMessage pricesResponseMessage = wallet.getEnergyPrices(); - assertNull(pricesResponseMessage); - } - - @Test - public void testGetBandwidthPrices() throws Exception { - Wallet wallet = new Wallet(); - ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); - DynamicPropertiesStore dynamicPropertiesStoreMock = - mock(DynamicPropertiesStore.class); - - when(chainBaseManagerMock.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStoreMock); - doThrow(new IllegalArgumentException("not found BANDWIDTH_PRICE_HISTORY")) - .when(dynamicPropertiesStoreMock).getBandwidthPriceHistory(); - - Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); - - GrpcAPI.PricesResponseMessage pricesResponseMessage = wallet.getBandwidthPrices(); - assertNull(pricesResponseMessage); - } - - @Test - public void testCheckBlockIdentifier() { - Wallet wallet = new Wallet(); - BalanceContract.BlockBalanceTrace.BlockIdentifier blockIdentifier = - BalanceContract.BlockBalanceTrace.BlockIdentifier.newBuilder() - .build(); - blockIdentifier = blockIdentifier.getDefaultInstanceForType(); - - BalanceContract.BlockBalanceTrace.BlockIdentifier blockIdentifier1 = - blockIdentifier; - assertThrows( - IllegalArgumentException.class, - () -> { - wallet.checkBlockIdentifier(blockIdentifier1); - } - ); - - BalanceContract.BlockBalanceTrace.BlockIdentifier blockIdentifier2 = - BalanceContract.BlockBalanceTrace.BlockIdentifier.newBuilder() - .setNumber(-1L) - .build(); - - assertThrows( - IllegalArgumentException.class, - () -> { - wallet.checkBlockIdentifier(blockIdentifier2); - } - ); - - BalanceContract.BlockBalanceTrace.BlockIdentifier blockIdentifier3 = - BalanceContract.BlockBalanceTrace.BlockIdentifier.newBuilder() - .setHash(ByteString.copyFrom("".getBytes(StandardCharsets.UTF_8))) - .build(); - assertThrows( - IllegalArgumentException.class, - () -> { - wallet.checkBlockIdentifier(blockIdentifier3); - } - ); - } - - @Test - public void testCheckAccountIdentifier() { - Wallet wallet = new Wallet(); - BalanceContract.AccountIdentifier accountIdentifier = - BalanceContract.AccountIdentifier.newBuilder().build(); - accountIdentifier = accountIdentifier.getDefaultInstanceForType(); - - BalanceContract.AccountIdentifier accountIdentifier2 = accountIdentifier; - assertThrows( - IllegalArgumentException.class, - () -> { - wallet.checkAccountIdentifier(accountIdentifier2); - } - ); - - BalanceContract.AccountIdentifier accountIdentifier1 - = BalanceContract.AccountIdentifier.newBuilder().build(); - - assertThrows( - IllegalArgumentException.class, - () -> { - wallet.checkAccountIdentifier(accountIdentifier1); - } - ); - } - - @Test - public void testGetTriggerInputForShieldedTRC20Contract() { - Wallet wallet = new Wallet(); - GrpcAPI.ShieldedTRC20TriggerContractParameters.Builder triggerParam = - GrpcAPI.ShieldedTRC20TriggerContractParameters - .newBuilder(); - GrpcAPI.ShieldedTRC20Parameters shieldedTRC20Parameters = - GrpcAPI.ShieldedTRC20Parameters.newBuilder().build(); - GrpcAPI.BytesMessage bytesMessage = - GrpcAPI.BytesMessage.newBuilder().build(); - - triggerParam.setShieldedTRC20Parameters(shieldedTRC20Parameters); - triggerParam.addSpendAuthoritySignature(bytesMessage); - - CommonParameter commonParameterMock = mock(Args.class); - mockStatic(CommonParameter.class); - when(CommonParameter.getInstance()).thenReturn(commonParameterMock); - when(commonParameterMock.isFullNodeAllowShieldedTransactionArgs()).thenReturn(true); - - assertThrows( - ZksnarkException.class, - () -> { - wallet.getTriggerInputForShieldedTRC20Contract(triggerParam.build()); - } - ); - } - - @Test - public void testGetTriggerInputForShieldedTRC20Contract1() - throws ZksnarkException, ContractValidateException { - Wallet wallet = new Wallet(); - ShieldContract.SpendDescription spendDescription = - ShieldContract.SpendDescription.newBuilder().build(); - GrpcAPI.ShieldedTRC20TriggerContractParameters.Builder triggerParam = - GrpcAPI.ShieldedTRC20TriggerContractParameters - .newBuilder(); - GrpcAPI.ShieldedTRC20Parameters shieldedTRC20Parameters = - GrpcAPI.ShieldedTRC20Parameters.newBuilder() - .addSpendDescription(spendDescription) - .setParameterType("transfer") - .build(); - GrpcAPI.BytesMessage bytesMessage = - GrpcAPI.BytesMessage.newBuilder().build(); - - triggerParam.setShieldedTRC20Parameters(shieldedTRC20Parameters); - triggerParam.addSpendAuthoritySignature(bytesMessage); - - CommonParameter commonParameterMock = mock(Args.class); - mockStatic(CommonParameter.class); - when(CommonParameter.getInstance()).thenReturn(commonParameterMock); - when(commonParameterMock.isFullNodeAllowShieldedTransactionArgs()).thenReturn(true); - - GrpcAPI.BytesMessage reponse = - wallet.getTriggerInputForShieldedTRC20Contract(triggerParam.build()); - assertNotNull(reponse); - } - - @Test - public void testGetShieldedContractScalingFactorException() { - Wallet wallet = new Wallet(); - byte[] contractAddress = "".getBytes(StandardCharsets.UTF_8); - - assertThrows( - ContractExeException.class, - () -> { - wallet.getShieldedContractScalingFactor(contractAddress); - } - ); - } - - @Test - public void testGetShieldedContractScalingFactorRuntimeException() - throws VMIllegalException, HeaderNotFound, ContractValidateException, ContractExeException { - Wallet walletMock = mock(Wallet.class); - byte[] contractAddress = "".getBytes(StandardCharsets.UTF_8); - Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); - when(walletMock.triggerConstantContract(any(),any(),any(),any())).thenReturn(transaction); - when(walletMock.getShieldedContractScalingFactor(any())).thenCallRealMethod(); - - assertThrows( - ContractExeException.class, - () -> { - walletMock.getShieldedContractScalingFactor(contractAddress); - } - ); - } - - @Test - public void testGetShieldedContractScalingFactorSuccess() - throws Exception { - Wallet walletMock = mock(Wallet.class); - byte[] contractAddress = "".getBytes(StandardCharsets.UTF_8); - Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); - when(walletMock.triggerConstantContract(any(),any(),any(),any())) - .thenReturn(transaction); - when(walletMock.createTransactionCapsule(any(), any())) - .thenReturn(new TransactionCapsule(transaction)); - when(walletMock.getShieldedContractScalingFactor(any())).thenCallRealMethod(); - try { - byte[] listBytes = walletMock.getShieldedContractScalingFactor(contractAddress); - assertNotNull(listBytes); - } catch (Exception e) { - assertNull(e); - } - } - - @Test - public void testGetShieldedContractScalingFactorContractExeException() - throws Exception { - Wallet walletMock = mock(Wallet.class); - byte[] contractAddress = "".getBytes(StandardCharsets.UTF_8); - Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); - doThrow(new ContractExeException("")) - .when(walletMock).triggerConstantContract(any(),any(),any(),any()); - when(walletMock.createTransactionCapsule(any(), any())) - .thenReturn(new TransactionCapsule(transaction)); - when(walletMock.getShieldedContractScalingFactor(any())).thenCallRealMethod(); - - assertThrows( - ContractExeException.class, - () -> { - walletMock.getShieldedContractScalingFactor(contractAddress); - } - ); - } - - @Test - public void testCheckBigIntegerRange() { - Wallet wallet = new Wallet(); - - assertThrows( - "public amount must be non-negative", - Exception.class, - () -> { - Whitebox.invokeMethod(wallet, "checkBigIntegerRange", - new BigInteger("-1")); - } - ); - } - - @Test - public void testCheckPublicAmount() throws ContractExeException { - Wallet walletMock = mock(Wallet.class); - - byte[] address = "".getBytes(StandardCharsets.UTF_8); - BigInteger fromAmount = new BigInteger("10"); - BigInteger toAmount = new BigInteger("10"); - doThrow(new ContractExeException("")).when(walletMock).getShieldedContractScalingFactor(any()); - - assertThrows( - ContractExeException.class, - () -> { - PowerMockito.when(walletMock, - "checkPublicAmount", - address, fromAmount, toAmount - ).thenCallRealMethod(); - } - ); - } - - @Test - public void testCheckPublicAmount1() throws ContractExeException { - Wallet walletMock = mock(Wallet.class); - - byte[] address = "".getBytes(StandardCharsets.UTF_8); - BigInteger fromAmount = new BigInteger("300"); - BigInteger toAmount = new BigInteger("255"); - - byte[] scalingFactorBytes = ByteUtil.bigIntegerToBytes(new BigInteger("-1")); - - when(walletMock.getShieldedContractScalingFactor(any())).thenReturn(scalingFactorBytes); - assertThrows( - ContractValidateException.class, - () -> { - PowerMockito.when(walletMock, - "checkPublicAmount", - address, fromAmount, toAmount - ).thenCallRealMethod(); - } - ); - } - - @Test - public void testCheckPublicAmount2() throws ContractExeException { - Wallet walletMock = mock(Wallet.class); - - byte[] address = "".getBytes(StandardCharsets.UTF_8); - BigInteger fromAmount = new BigInteger("300"); - BigInteger toAmount = new BigInteger("255"); - - byte[] scalingFactorBytes = ByteUtil.bigIntegerToBytes(new BigInteger("-1")); - mockStatic(ByteUtil.class); - when(ByteUtil.bytesToBigInteger(any())).thenReturn(new BigInteger("-1")); - when(walletMock.getShieldedContractScalingFactor(any())).thenReturn(scalingFactorBytes); - - assertThrows( - ContractValidateException.class, - () -> { - PowerMockito.when(walletMock, - "checkPublicAmount", - address, fromAmount, toAmount - ).thenCallRealMethod(); - } - ); - } - - @Test - public void testGetShieldedTRC20Nullifier() { - GrpcAPI.Note note = GrpcAPI.Note.newBuilder() - .setValue(100) - .setPaymentAddress("address") - .setRcm(ByteString.copyFrom("rcm".getBytes(StandardCharsets.UTF_8))) - .setMemo(ByteString.copyFrom("memo".getBytes(StandardCharsets.UTF_8))) - .build(); - long pos = 100L; - byte[] ak = "ak".getBytes(StandardCharsets.UTF_8); - byte[] nk = "nk".getBytes(StandardCharsets.UTF_8); - Wallet walletMock = mock(Wallet.class); - mockStatic(KeyIo.class); - when(KeyIo.decodePaymentAddress(any())).thenReturn(null); - - assertThrows( - ZksnarkException.class, - () -> { - PowerMockito.when(walletMock, - "getShieldedTRC20Nullifier", - note, pos, ak, nk - ).thenCallRealMethod(); - } - ); - } - - @Test - public void testGetShieldedTRC20LogType() { - Wallet walletMock = mock(Wallet.class); - Protocol.TransactionInfo.Log log = Protocol.TransactionInfo.Log.newBuilder().build(); - byte[] contractAddress = "contractAddress".getBytes(StandardCharsets.UTF_8); - LazyStringArrayList topicsList = new LazyStringArrayList(); - assertThrows( - ZksnarkException.class, - () -> { - Whitebox.invokeMethod(walletMock, "getShieldedTRC20LogType", - log, contractAddress, topicsList); - } - ); - } - - @Test - public void testGetShieldedTRC20LogType1() { - Wallet wallet = new Wallet(); - final String SHIELDED_CONTRACT_ADDRESS_STR = "TGAmX5AqVUoXCf8MoHxbuhQPmhGfWTnEgA"; - byte[] contractAddress = WalletClient.decodeFromBase58Check(SHIELDED_CONTRACT_ADDRESS_STR); - - byte[] addressWithoutPrefix = new byte[20]; - System.arraycopy(contractAddress, 1, addressWithoutPrefix, 0, 20); - Protocol.TransactionInfo.Log log = Protocol.TransactionInfo.Log.newBuilder() - .setAddress(ByteString.copyFrom(addressWithoutPrefix)) - .build(); - - LazyStringArrayList topicsList = new LazyStringArrayList(); - try { - Whitebox.invokeMethod(wallet, - "getShieldedTRC20LogType", - log, - contractAddress, - topicsList); - } catch (Exception e) { - assertTrue(false); - } - assertTrue(true); - } - - - @Test - public void testGetShieldedTRC20LogType2() { - Wallet wallet = new Wallet(); - final String SHIELDED_CONTRACT_ADDRESS_STR = "TGAmX5AqVUoXCf8MoHxbuhQPmhGfWTnEgA"; - byte[] contractAddress = WalletClient.decodeFromBase58Check(SHIELDED_CONTRACT_ADDRESS_STR); - - byte[] addressWithoutPrefix = new byte[20]; - System.arraycopy(contractAddress, 1, addressWithoutPrefix, 0, 20); - Protocol.TransactionInfo.Log log = Protocol.TransactionInfo.Log.newBuilder() - .setAddress(ByteString.copyFrom(addressWithoutPrefix)) - .addTopics(ByteString.copyFrom("topic".getBytes())) - .build(); - - LazyStringArrayList topicsList = new LazyStringArrayList(); - topicsList.add("topic"); - try { - Whitebox.invokeMethod(wallet, - "getShieldedTRC20LogType", - log, - contractAddress, - topicsList); - } catch (Exception e) { - assertTrue(false); - } - assertTrue(true); - } - - @Test - public void testBuildShieldedTRC20InputWithAK() throws ZksnarkException { - ShieldedTRC20ParametersBuilder builder = new ShieldedTRC20ParametersBuilder("transfer"); - GrpcAPI.Note note = GrpcAPI.Note.newBuilder() - .setValue(100) - .setPaymentAddress("address") - .setRcm(ByteString.copyFrom("rcm".getBytes(StandardCharsets.UTF_8))) - .setMemo(ByteString.copyFrom("memo".getBytes(StandardCharsets.UTF_8))) - .build(); - GrpcAPI.SpendNoteTRC20 spendNote = GrpcAPI.SpendNoteTRC20.newBuilder() - .setNote(note) - .setAlpha(ByteString.copyFrom("alpha".getBytes())) - .setRoot(ByteString.copyFrom("root".getBytes())) - .setPath(ByteString.copyFrom("path".getBytes())) - .setPos(0L) - .build(); - byte[] ak = "ak".getBytes(StandardCharsets.UTF_8); - byte[] nk = "nk".getBytes(StandardCharsets.UTF_8); - Wallet walletMock = mock(Wallet.class); - mockStatic(KeyIo.class); - when(KeyIo.decodePaymentAddress(any())).thenReturn(null); - - assertThrows( - ZksnarkException.class, - () -> { - PowerMockito.when(walletMock, - "buildShieldedTRC20InputWithAK", - builder, - spendNote, - ak, nk - ).thenCallRealMethod(); - } - ); - } - - @Test - public void testBuildShieldedTRC20InputWithAK1() throws Exception { - ShieldedTRC20ParametersBuilder builder = new ShieldedTRC20ParametersBuilder("transfer"); - GrpcAPI.Note note = GrpcAPI.Note.newBuilder() - .setValue(100) - .setPaymentAddress("address") - .setRcm(ByteString.copyFrom("rcm".getBytes(StandardCharsets.UTF_8))) - .setMemo(ByteString.copyFrom("memo".getBytes(StandardCharsets.UTF_8))) - .build(); - GrpcAPI.SpendNoteTRC20 spendNote = GrpcAPI.SpendNoteTRC20.newBuilder() - .setNote(note) - .setAlpha(ByteString.copyFrom("alpha".getBytes())) - .setRoot(ByteString.copyFrom("root".getBytes())) - .setPath(ByteString.copyFrom("path".getBytes())) - .setPos(0L) - .build(); - byte[] ak = "ak".getBytes(StandardCharsets.UTF_8); - byte[] nk = "nk".getBytes(StandardCharsets.UTF_8); - PaymentAddress paymentAddress = mock(PaymentAddress.class); - DiversifierT diversifierT = mock(DiversifierT.class); - Wallet walletMock = mock(Wallet.class); - mockStatic(KeyIo.class); - when(KeyIo.decodePaymentAddress(any())).thenReturn(paymentAddress); - when(paymentAddress.getD()).thenReturn(diversifierT); - when(paymentAddress.getPkD()).thenReturn("pkd".getBytes()); - - PowerMockito.when(walletMock, - "buildShieldedTRC20InputWithAK", - builder, - spendNote, - ak, nk - ).thenCallRealMethod(); - assertTrue(true); - } - - @Test - public void testBuildShieldedTRC20Input() throws ZksnarkException { - ShieldedTRC20ParametersBuilder builder = new ShieldedTRC20ParametersBuilder("transfer"); - GrpcAPI.Note note = GrpcAPI.Note.newBuilder() - .setValue(100) - .setPaymentAddress("address") - .setRcm(ByteString.copyFrom("rcm".getBytes(StandardCharsets.UTF_8))) - .setMemo(ByteString.copyFrom("memo".getBytes(StandardCharsets.UTF_8))) - .build(); - GrpcAPI.SpendNoteTRC20 spendNote = GrpcAPI.SpendNoteTRC20.newBuilder() - .setNote(note) - .setAlpha(ByteString.copyFrom("alpha".getBytes())) - .setRoot(ByteString.copyFrom("root".getBytes())) - .setPath(ByteString.copyFrom("path".getBytes())) - .setPos(0L) - .build(); - ExpandedSpendingKey expandedSpendingKey = mock(ExpandedSpendingKey.class); - PaymentAddress paymentAddress = mock(PaymentAddress.class); - DiversifierT diversifierT = mock(DiversifierT.class); - Wallet walletMock = mock(Wallet.class); - mockStatic(KeyIo.class); - when(KeyIo.decodePaymentAddress(any())).thenReturn(paymentAddress); - when(paymentAddress.getD()).thenReturn(diversifierT); - when(paymentAddress.getPkD()).thenReturn("pkd".getBytes()); - try { - PowerMockito.when(walletMock, - "buildShieldedTRC20Input", - builder, - spendNote, - expandedSpendingKey - ).thenCallRealMethod(); - } catch (Exception e) { - assertTrue(false); - } - } - - @Test - public void testGetContractInfo() { - Wallet wallet = new Wallet(); - GrpcAPI.BytesMessage bytesMessage = GrpcAPI.BytesMessage.newBuilder() - .setValue(ByteString.copyFrom("test".getBytes())) - .build(); - - ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); - AccountStore accountStore = mock(AccountStore.class); - Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); - when(chainBaseManagerMock.getAccountStore()).thenReturn(accountStore); - when(accountStore.get(any())).thenReturn(null); - - SmartContractOuterClass.SmartContractDataWrapper smartContractDataWrapper = - wallet.getContractInfo(bytesMessage); - assertNull(smartContractDataWrapper); - } - - @Test - public void testGetContractInfo1() { - Wallet wallet = new Wallet(); - GrpcAPI.BytesMessage bytesMessage = GrpcAPI.BytesMessage.newBuilder() - .setValue(ByteString.copyFrom("test".getBytes())) - .build(); - - ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); - AccountStore accountStore = mock(AccountStore.class); - ContractStore contractStore = mock(ContractStore.class); - AbiStore abiStore = mock(AbiStore.class); - CodeStore codeStore = mock(CodeStore.class); - ContractStateStore contractStateStore = mock(ContractStateStore.class); - DynamicPropertiesStore dynamicPropertiesStore = mock(DynamicPropertiesStore.class); - - AccountCapsule accountCapsule = mock(AccountCapsule.class); - ContractCapsule contractCapsule = mock(ContractCapsule.class); - ContractStateCapsule contractStateCapsule = new ContractStateCapsule(10L); - - Whitebox.setInternalState(wallet, "chainBaseManager", chainBaseManagerMock); - when(chainBaseManagerMock.getAccountStore()).thenReturn(accountStore); - when(chainBaseManagerMock.getContractStore()).thenReturn(contractStore); - when(chainBaseManagerMock.getAbiStore()).thenReturn(abiStore); - when(chainBaseManagerMock.getCodeStore()).thenReturn(codeStore); - when(chainBaseManagerMock.getContractStateStore()).thenReturn(contractStateStore); - when(chainBaseManagerMock.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStore); - - when(accountStore.get(any())).thenReturn(accountCapsule); - when(contractStore.get(any())).thenReturn(contractCapsule); - when(contractCapsule.generateWrapper()) - .thenReturn(SmartContractOuterClass.SmartContractDataWrapper.newBuilder().build()); - when(abiStore.get(any())).thenReturn(null); - when(codeStore.get(any())).thenReturn(null); - when(contractStateStore.get(any())).thenReturn(contractStateCapsule); - when(dynamicPropertiesStore.getCurrentCycleNumber()).thenReturn(100L); - - SmartContractOuterClass.SmartContractDataWrapper smartContractDataWrapper = - wallet.getContractInfo(bytesMessage); - assertNotNull(smartContractDataWrapper); - } -} diff --git a/framework/src/test/java/org/tron/core/db/ManagerMockTest.java b/framework/src/test/java/org/tron/core/db/ManagerMockTest.java deleted file mode 100755 index 62ffcc9c43d..00000000000 --- a/framework/src/test/java/org/tron/core/db/ManagerMockTest.java +++ /dev/null @@ -1,384 +0,0 @@ -package org.tron.core.db; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.powermock.api.mockito.PowerMockito.spy; - -import com.google.protobuf.Any; -import com.google.protobuf.ByteString; -import java.nio.charset.StandardCharsets; - -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.junit.After; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; -import org.quartz.CronExpression; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.runtime.ProgramResult; -import org.tron.common.runtime.RuntimeImpl; -import org.tron.common.utils.Sha256Hash; -import org.tron.core.ChainBaseManager; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.capsule.TransactionInfoCapsule; -import org.tron.core.capsule.utils.TransactionUtil; -import org.tron.core.config.args.Args; -import org.tron.core.exception.ContractSizeNotEqualToOneException; -import org.tron.core.exception.DupTransactionException; -import org.tron.core.exception.ItemNotFoundException; -import org.tron.core.exception.ReceiptCheckErrException; -import org.tron.core.exception.TaposException; -import org.tron.core.exception.TooBigTransactionException; -import org.tron.core.exception.TooBigTransactionResultException; -import org.tron.core.exception.TransactionExpirationException; -import org.tron.core.exception.ValidateSignatureException; -import org.tron.core.store.AccountStore; -import org.tron.core.store.BalanceTraceStore; -import org.tron.core.store.DynamicPropertiesStore; -import org.tron.protos.Protocol; -import org.tron.protos.contract.BalanceContract; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({Manager.class, - CommonParameter.class, - Args.class, - TransactionUtil.class}) -@Slf4j -public class ManagerMockTest { - @After - public void clearMocks() { - Mockito.framework().clearInlineMocks(); - } - - @Test - public void processTransactionCostTimeMoreThan100() throws Exception { - Manager dbManager = spy(new Manager()); - BalanceContract.TransferContract transferContract = - BalanceContract.TransferContract.newBuilder() - .setAmount(10) - .setOwnerAddress(ByteString.copyFromUtf8("aaa")) - .setToAddress(ByteString.copyFromUtf8("bbb")) - .build(); - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < 6666; i++) { - sb.append("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - } - Protocol.Transaction transaction = Protocol.Transaction.newBuilder().setRawData( - Protocol.Transaction.raw.newBuilder() - .setData(ByteString.copyFrom(sb.toString().getBytes(StandardCharsets.UTF_8))) - .addContract( - Protocol.Transaction.Contract.newBuilder() - .setParameter(Any.pack(transferContract)) - .setType(Protocol.Transaction.Contract.ContractType.TransferContract))) - .build(); - TransactionCapsule trxCap = new TransactionCapsule(transaction); - ProgramResult result = new ProgramResult(); - result.setResultCode(Protocol.Transaction.Result.contractResult.SUCCESS); - - Sha256Hash transactionId = trxCap.getTransactionId(); - TransactionCapsule trxCapMock = mock(TransactionCapsule.class); - TransactionTrace traceMock = mock(TransactionTrace.class); - RuntimeImpl runtimeMock = mock(RuntimeImpl.class); - BandwidthProcessor bandwidthProcessorMock = mock(BandwidthProcessor.class); - ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); - BalanceTraceStore balanceTraceStoreMock = mock(BalanceTraceStore.class); - TransactionStore transactionStoreMock = mock(TransactionStore.class); - TransactionInfoCapsule transactionInfoCapsuleMock = mock(TransactionInfoCapsule.class); - Protocol.TransactionInfo transactionInfo = Protocol.TransactionInfo.newBuilder().build(); - - // mock static - PowerMockito.mockStatic(TransactionUtil.class); - - Whitebox.setInternalState(dbManager, "chainBaseManager", chainBaseManagerMock); - - BlockCapsule blockCapMock = Mockito.mock(BlockCapsule.class); - - PowerMockito.when(TransactionUtil - .buildTransactionInfoInstance(trxCapMock, blockCapMock, traceMock)) - .thenReturn(transactionInfoCapsuleMock); - - // this make cost > 100 cond is true - PowerMockito.when(blockCapMock.isMerkleRootEmpty()).thenAnswer(new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - Thread.sleep(100); - return true; - } - }); - - when(chainBaseManagerMock.getBalanceTraceStore()).thenReturn(balanceTraceStoreMock); - when(chainBaseManagerMock.getAccountStore()).thenReturn(mock(AccountStore.class)); - when(chainBaseManagerMock.getDynamicPropertiesStore()) - .thenReturn(mock(DynamicPropertiesStore.class)); - when(chainBaseManagerMock.getTransactionStore()).thenReturn(transactionStoreMock); - when(trxCapMock.getTransactionId()).thenReturn(transactionId); - when(traceMock.getRuntimeResult()).thenReturn(result); - when(transactionInfoCapsuleMock.getId()).thenReturn(transactionId.getBytes()); - when(transactionInfoCapsuleMock.getInstance()).thenReturn(transactionInfo); - - doNothing().when(dbManager).validateTapos(trxCapMock); - doNothing().when(dbManager).validateCommon(trxCapMock); - doNothing().when(dbManager).validateDup(trxCapMock); - - // mock construct - PowerMockito.whenNew(RuntimeImpl.class).withAnyArguments().thenReturn(runtimeMock); - PowerMockito.whenNew(TransactionTrace.class).withAnyArguments().thenReturn(traceMock); - PowerMockito.whenNew(BandwidthProcessor.class).withAnyArguments() - .thenReturn(bandwidthProcessorMock); - - doNothing().when(transactionStoreMock).put(transactionId.getBytes(), trxCapMock); - doNothing().when(bandwidthProcessorMock).consume(trxCapMock, traceMock); - doNothing().when(dbManager).consumeBandwidth(trxCapMock, traceMock); - doNothing().when(balanceTraceStoreMock).initCurrentTransactionBalanceTrace(trxCapMock); - doNothing().when(balanceTraceStoreMock).updateCurrentTransactionStatus(anyString()); - doNothing().when(balanceTraceStoreMock).resetCurrentTransactionTrace(); - - when(trxCapMock.getInstance()).thenReturn(trxCap.getInstance()); - when(trxCapMock.validatePubSignature( - Mockito.any(AccountStore.class), - Mockito.any(DynamicPropertiesStore.class))).thenReturn(true); - when(trxCapMock.validateSignature( - Mockito.any(AccountStore.class), - Mockito.any(DynamicPropertiesStore.class))).thenReturn(true); - - assertNotNull(dbManager.processTransaction(trxCapMock, blockCapMock)); - } - - private void initMockEnv(Manager dbManager, long headNum, long headTime, - long exitHeight, long exitCount, String blockTime) - throws Exception { - ChainBaseManager chainBaseManagerMock = PowerMockito.mock(ChainBaseManager.class); - Args argsMock = PowerMockito.mock(Args.class); - - PowerMockito.mockStatic(CommonParameter.class); - PowerMockito.mockStatic(Args.class); - PowerMockito.when(Args.getInstance()).thenReturn(argsMock); - - when(chainBaseManagerMock.getHeadBlockNum()).thenReturn(headNum); - when(chainBaseManagerMock.getHeadBlockTimeStamp()).thenReturn(headTime); - - when(argsMock.getShutdownBlockHeight()).thenReturn(exitHeight); - when(argsMock.getShutdownBlockCount()).thenReturn(exitCount); - when(argsMock.isP2pDisable()).thenReturn(false); - when(argsMock.getShutdownBlockTime()) - .thenReturn(new CronExpression(blockTime)); //"0 0 12 * * ?" - - Whitebox.setInternalState(dbManager, - "chainBaseManager", chainBaseManagerMock); - } - - @Test - public void testInitAutoStop() throws Exception { - Manager dbManager = spy(new Manager()); - initMockEnv(dbManager, 100L, 12345L, - 10L, 0L, "0 0 12 * * ?"); - - assertThrows( - "shutDownBlockHeight 10 is less than headNum 100", - Exception.class, - () -> { - Whitebox.invokeMethod(dbManager, "initAutoStop"); - } - ); - } - - @Test - public void testInitAutoStop1() throws Exception { - Manager dbManager = spy(new Manager()); - initMockEnv(dbManager,10L, 12345L, - 100L, 0L, "0 0 12 * * ?"); - - assertThrows( - "shutDownBlockCount 0 is less than 1", - Exception.class, - () -> { - Whitebox.invokeMethod(dbManager, "initAutoStop"); - } - ); - } - - @Test - public void testInitAutoStop2() throws Exception { - Manager dbManager = spy(new Manager()); - initMockEnv(dbManager,10L, 99726143865000L, - 100L, 1L, "0 0 12 * * ?"); - - assertThrows( - "shutDownBlockTime 0 0 12 * * ? is illegal", - Exception.class, - () -> { - Whitebox.invokeMethod(dbManager, "initAutoStop"); - } - ); - } - - @Test - public void testInitAutoStop3() throws Exception { - Manager dbManager = spy(new Manager()); - initMockEnv(dbManager,10L, 12345L, - 100L, 1L, "0 0 12 * * ?"); - - assertThrows( - "shutDownBlockHeight 100 and shutDownBlockCount 1 set both", - Exception.class, - () -> { - Whitebox.invokeMethod(dbManager, "initAutoStop"); - } - ); - } - - @Test - public void testInitAutoStop4() throws Exception { - Manager dbManager = spy(new Manager()); - initMockEnv(dbManager, 10L, 12345L, - 100L, -1L, "0 0 12 * * ?"); - - assertThrows( - "shutDownBlockHeight 100 and shutDownBlockTime 0 0 12 * * ? set both", - Exception.class, - () -> { - Whitebox.invokeMethod(dbManager, "initAutoStop"); - } - ); - } - - @Test - public void testInitAutoStop5() throws Exception { - Manager dbManager = spy(new Manager()); - initMockEnv(dbManager,10L, 12345L, - 0L, 1L, "0 0 12 * * ?"); - - assertThrows( - "shutDownBlockCount 1 and shutDownBlockTime 0 0 12 * * ? set both", - Exception.class, - () -> { - Whitebox.invokeMethod(dbManager, "initAutoStop"); - } - ); - } - - @Test - public void testProcessTransaction() throws Exception { - Manager dbManager = spy(new Manager()); - TransactionCapsule transactionCapsuleMock = null; - BlockCapsule blockCapsuleMock = PowerMockito.mock(BlockCapsule.class); - Whitebox.invokeMethod(dbManager, "processTransaction", - transactionCapsuleMock, blockCapsuleMock); - assertTrue(true); - } - - @Test - public void testProcessTransaction1() { - Manager dbManager = spy(new Manager()); - Protocol.Transaction transaction = Protocol.Transaction.newBuilder().setRawData( - Protocol.Transaction.raw.newBuilder() - .setData(ByteString.copyFrom("sb.toString()".getBytes(StandardCharsets.UTF_8)))) - .build(); - TransactionCapsule trxCap = new TransactionCapsule(transaction); - - BlockCapsule blockCapsuleMock = PowerMockito.mock(BlockCapsule.class); - - assertThrows( - ContractSizeNotEqualToOneException.class, - () -> { - Whitebox.invokeMethod(dbManager, "processTransaction", - trxCap, blockCapsuleMock); - } - ); - } - - @SneakyThrows - @Test - public void testRePush() { - Manager dbManager = spy(new Manager()); - Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); - TransactionCapsule trx = new TransactionCapsule(transaction); - TransactionStore transactionStoreMock = mock(TransactionStore.class); - - ChainBaseManager chainBaseManagerMock = PowerMockito.mock(ChainBaseManager.class); - Whitebox.setInternalState(dbManager, "chainBaseManager", chainBaseManagerMock); - when(chainBaseManagerMock.getTransactionStore()).thenReturn(transactionStoreMock); - when(transactionStoreMock.has(any())).thenReturn(true); - - dbManager.rePush(trx); - assertTrue(true); - } - - @SneakyThrows - @Test - public void testRePush1() { - Manager dbManager = spy(new Manager()); - Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); - TransactionCapsule trx = new TransactionCapsule(transaction); - TransactionStore transactionStoreMock = mock(TransactionStore.class); - - ChainBaseManager chainBaseManagerMock = PowerMockito.mock(ChainBaseManager.class); - Whitebox.setInternalState(dbManager, "chainBaseManager", chainBaseManagerMock); - when(chainBaseManagerMock.getTransactionStore()).thenReturn(transactionStoreMock); - when(transactionStoreMock.has(any())).thenReturn(false); - - doThrow(new ValidateSignatureException()).when(dbManager).pushTransaction(any()); - dbManager.rePush(trx); - - doThrow(new DupTransactionException()).when(dbManager).pushTransaction(any()); - dbManager.rePush(trx); - - doThrow(new TaposException()).when(dbManager).pushTransaction(any()); - dbManager.rePush(trx); - - doThrow(new TooBigTransactionException()).when(dbManager).pushTransaction(any()); - dbManager.rePush(trx); - - doThrow(new TransactionExpirationException()).when(dbManager).pushTransaction(any()); - dbManager.rePush(trx); - - doThrow(new ReceiptCheckErrException()).when(dbManager).pushTransaction(any()); - dbManager.rePush(trx); - - doThrow(new TooBigTransactionResultException()).when(dbManager).pushTransaction(any()); - dbManager.rePush(trx); - assertTrue(true); - } - - @Test - public void testPostSolidityFilter() throws Exception { - Manager dbManager = spy(new Manager()); - Whitebox.invokeMethod(dbManager, "postSolidityFilter", - 100L, 10L); - assertTrue(true); - } - - @Test - public void testReOrgLogsFilter() throws Exception { - Manager dbManager = spy(new Manager()); - CommonParameter commonParameterMock = PowerMockito.mock(Args.class); - PowerMockito.mockStatic(CommonParameter.class); - ChainBaseManager chainBaseManagerMock = PowerMockito.mock(ChainBaseManager.class); - - PowerMockito.when(CommonParameter.getInstance()).thenReturn(commonParameterMock); - when(commonParameterMock.isJsonRpcHttpFullNodeEnable()).thenReturn(true); - when(chainBaseManagerMock.getDynamicPropertiesStore()) - .thenReturn(mock(DynamicPropertiesStore.class)); - Whitebox.setInternalState(dbManager, "chainBaseManager", chainBaseManagerMock); - doThrow(new ItemNotFoundException()).when(chainBaseManagerMock).getBlockById(any()); - - Whitebox.invokeMethod(dbManager, "reOrgLogsFilter"); - assertTrue(true); - } - -} diff --git a/framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckMockTest.java b/framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckMockTest.java deleted file mode 100644 index 92bf06edd72..00000000000 --- a/framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckMockTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.tron.core.net.peer; - -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.spy; - -import org.junit.After; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({PeerStatusCheckMockTest.class}) -public class PeerStatusCheckMockTest { - @After - public void clearMocks() { - Mockito.framework().clearInlineMocks(); - } - - @Test - public void testInitException() throws InterruptedException { - PeerStatusCheck peerStatusCheck = spy(new PeerStatusCheck()); - doThrow(new RuntimeException("test exception")).when(peerStatusCheck).statusCheck(); - peerStatusCheck.init(); - - // the initialDelay of scheduleWithFixedDelay is 5s - Thread.sleep(5000L); - assertTrue(true); - } - -} diff --git a/framework/src/test/java/org/tron/core/services/http/JsonFormatTest.java b/framework/src/test/java/org/tron/core/services/http/JsonFormatTest.java deleted file mode 100644 index 1b3fc354c95..00000000000 --- a/framework/src/test/java/org/tron/core/services/http/JsonFormatTest.java +++ /dev/null @@ -1,266 +0,0 @@ -package org.tron.core.services.http; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThrows; - -import com.google.protobuf.ByteString; -import com.google.protobuf.UnknownFieldSet; - -import java.io.CharArrayReader; -import java.io.IOException; -import java.io.StringWriter; - -import org.junit.After; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; -import org.tron.protos.Protocol; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({ - JsonFormat.class, -}) -public class JsonFormatTest { - @After - public void clearMocks() { - Mockito.framework().clearInlineMocks(); - } - - @Test - public void testPrintErrorMsg() { - Exception ex = new Exception("test"); - String out = JsonFormat.printErrorMsg(ex); - assertEquals("{\"Error\":\"test\"}", out); - } - - @Test - public void testPrintWithHelloMessage() throws IOException { - Protocol.HelloMessage message = Protocol.HelloMessage.newBuilder() - .setAddress(ByteString.copyFrom("address".getBytes())) - .build(); - StringWriter output = new StringWriter(); - - JsonFormat.print(message, output, true); - assertNotNull(output.toString()); - } - - private UnknownFieldSet createValidUnknownFieldSet() { - UnknownFieldSet unknownFieldSet2 = UnknownFieldSet.newBuilder().build(); - UnknownFieldSet.Field unknownField1 = UnknownFieldSet.Field.newBuilder() - .addFixed32(123) - .addFixed64(12345L) - .addGroup(unknownFieldSet2) - .addLengthDelimited(ByteString.copyFrom("length".getBytes())) - .addVarint(12345678L) - .build(); - - return UnknownFieldSet.newBuilder() - .addField(1, unknownField1) - .build(); - } - - @Test - public void testPrintWithFields() throws IOException { - UnknownFieldSet unknownFieldSet = createValidUnknownFieldSet(); - StringWriter output = new StringWriter(); - JsonFormat.print(unknownFieldSet, output, true); - assertNotNull(output.toString()); - } - - @Test - public void testPrintToString() { - UnknownFieldSet unknownFieldSet = createValidUnknownFieldSet(); - String output = JsonFormat.printToString(unknownFieldSet, true); - assertNotNull(output); - } - - @Test - public void testUnsignedToString() throws Exception { - String out1 = Whitebox.invokeMethod(JsonFormat.class, - "unsignedToString", 100L); - assertEquals("100", out1); - String out2 = Whitebox.invokeMethod(JsonFormat.class, - "unsignedToString", -100L); - assertNotNull(out2); - - String out3 = Whitebox.invokeMethod(JsonFormat.class, - "unsignedToString", 100); - assertEquals("100", out3); - String out4 = Whitebox.invokeMethod(JsonFormat.class, - "unsignedToString", -100); - assertNotNull(out4); - } - - @Test - public void testToStringBuilderWithNonReadableInput() throws Exception { - String inputString = "Hello, World!"; - Readable input = new CharArrayReader(inputString.toCharArray()); - - StringBuilder out = Whitebox.invokeMethod(JsonFormat.class, - "toStringBuilder", input); - assertEquals(inputString, out.toString()); - } - - - @Test - public void testUnicodeEscaped() throws Exception { - char input1 = 0x09; - String out = Whitebox.invokeMethod(JsonFormat.class, - "unicodeEscaped", input1); - assertNotNull(out); - - char input2 = 0x99; - String out2 = Whitebox.invokeMethod(JsonFormat.class, - "unicodeEscaped", input2); - assertNotNull(out2); - - char input3 = 0x999; - String out3 = Whitebox.invokeMethod(JsonFormat.class, - "unicodeEscaped", input3); - assertNotNull(out3); - - char input4 = 0x1001; - String out4 = Whitebox.invokeMethod(JsonFormat.class, - "unicodeEscaped", input4); - assertNotNull(out4); - } - - @Test - public void testEscapeText() throws Exception { - String input1 = "\b\f\n\r\t\\\"\\b\\f\\n\\r\\t\\\\\"test123"; - String out = Whitebox.invokeMethod(JsonFormat.class, - "escapeText", input1); - assertNotNull(out); - } - - @Test - public void testAppendEscapedUnicode() throws Exception { - char input1 = 0x09; - StringBuilder out1 = new StringBuilder(); - Whitebox.invokeMethod(JsonFormat.class, - "appendEscapedUnicode", out1, input1); - assertNotNull(out1); - - char input2 = 0x99; - StringBuilder out2 = new StringBuilder(); - Whitebox.invokeMethod(JsonFormat.class, - "appendEscapedUnicode", out2, input2); - assertNotNull(out2); - - char input3 = 0x999; - StringBuilder out3 = new StringBuilder(); - Whitebox.invokeMethod(JsonFormat.class, - "appendEscapedUnicode", out3, input3); - assertNotNull(out3); - - char input4 = 0x1001; - StringBuilder out4 = new StringBuilder(); - Whitebox.invokeMethod(JsonFormat.class, - "appendEscapedUnicode", out4, input4); - assertNotNull(out4); - } - - @Test - public void testUnescapeText() throws Exception { - String input = "\\u1234\\b\\f\\n\\r\\t\\\\\"test123";; - String out = Whitebox.invokeMethod(JsonFormat.class, - "unescapeText", input); - assertNotNull(out); - } - - @Test - public void testDigitValue() throws Exception { - char input = '1'; - int out = Whitebox.invokeMethod(JsonFormat.class, - "digitValue", input); - assertEquals(1, out); - - char input1 = 'b'; - int out1 = Whitebox.invokeMethod(JsonFormat.class, - "digitValue", input1); - assertEquals(11, out1); - - char input2 = 'B'; - int out2 = Whitebox.invokeMethod(JsonFormat.class, - "digitValue", input2); - assertEquals(11, out2); - } - - @Test - public void testParseUInt64() throws Exception { - String input = "12312312312"; - long out = Whitebox.invokeMethod(JsonFormat.class, - "parseUInt64", input); - assertEquals(12312312312L, out); - - String input1 = "0x10"; - long out1 = Whitebox.invokeMethod(JsonFormat.class, - "parseUInt64", input1); - assertEquals(16L, out1); - - String input2 = "010"; - long out2 = Whitebox.invokeMethod(JsonFormat.class, - "parseUInt64", input2); - assertEquals(8L, out2); - - String input3 = "-12312312312"; - assertThrows( - NumberFormatException.class, - () -> { - Whitebox.invokeMethod(JsonFormat.class, - "parseUInt64", input3); - } - ); - } - - @Test - public void testParseInteger() { - String input1 = "92233720368547758070"; - assertThrows( - NumberFormatException.class, - () -> { - Whitebox.invokeMethod(JsonFormat.class, "parseInteger", - input1, true, true); - } - ); - String input5 = "92233720368547758070"; - assertThrows( - NumberFormatException.class, - () -> { - Whitebox.invokeMethod(JsonFormat.class, "parseInteger", - input5, false, true); - } - ); - - String input2 = "-92233720368547758"; - assertThrows( - NumberFormatException.class, - () -> { - Whitebox.invokeMethod(JsonFormat.class, "parseInteger", - input2, false, true); - } - ); - - String input3 = "92233720368547758070"; - assertThrows( - NumberFormatException.class, - () -> { - Whitebox.invokeMethod(JsonFormat.class, "parseInteger", - input3, false, false); - } - ); - String input4 = "-92233720368547758070"; - assertThrows( - NumberFormatException.class, - () -> { - Whitebox.invokeMethod(JsonFormat.class, "parseInteger", - input4, true, false); - } - ); - } - -} diff --git a/framework/src/test/java/org/tron/core/services/http/UtilMockTest.java b/framework/src/test/java/org/tron/core/services/http/UtilMockTest.java deleted file mode 100644 index a2b5bcbe342..00000000000 --- a/framework/src/test/java/org/tron/core/services/http/UtilMockTest.java +++ /dev/null @@ -1,250 +0,0 @@ -package org.tron.core.services.http; - -import com.alibaba.fastjson.JSONObject; -import com.google.protobuf.ByteString; - -import java.security.InvalidParameterException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.lang3.StringUtils; -import org.junit.After; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.tron.api.GrpcAPI; -import org.tron.common.utils.Sha256Hash; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.p2p.utils.ByteArray; -import org.tron.protos.Protocol; -import org.tron.protos.contract.BalanceContract; -import org.tron.protos.contract.SmartContractOuterClass; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({ - Util.class, -}) -public class UtilMockTest { - @After - public void clearMocks() { - Mockito.framework().clearInlineMocks(); - } - - - @Test - public void testPrintTransactionFee() { - Protocol.ResourceReceipt resourceReceipt = Protocol.ResourceReceipt.newBuilder() - .build(); - Protocol.TransactionInfo result = Protocol.TransactionInfo.newBuilder() - .setReceipt(resourceReceipt) - .build(); - String transactionFee = JsonFormat.printToString(result, true); - String out = Util.printTransactionFee(transactionFee); - Assert.assertNotNull(out); - } - - @Test - public void testPrintBlockList() { - BlockCapsule blockCapsule1 = new BlockCapsule(1, Sha256Hash.ZERO_HASH, - System.currentTimeMillis(), Sha256Hash.ZERO_HASH.getByteString()); - BlockCapsule blockCapsule2 = new BlockCapsule(1, Sha256Hash.ZERO_HASH, - System.currentTimeMillis(), Sha256Hash.ZERO_HASH.getByteString()); - GrpcAPI.BlockList list = GrpcAPI.BlockList.newBuilder() - .addBlock(blockCapsule1.getInstance()) - .addBlock(blockCapsule2.getInstance()) - .build(); - String out = Util.printBlockList(list, true); - Assert.assertNotNull(out); - } - - @Test - public void testPrintTransactionList() { - TransactionCapsule transactionCapsule = getTransactionCapsuleExample(); - GrpcAPI.TransactionList list = GrpcAPI.TransactionList.newBuilder() - .addTransaction(transactionCapsule.getInstance()) - .build(); - String out = Util.printTransactionList(list, true); - Assert.assertNotNull(out); - } - - private TransactionCapsule getTransactionCapsuleExample() { - final String OWNER_ADDRESS = "41548794500882809695a8a687866e76d4271a1abc"; - final String RECEIVER_ADDRESS = "41abd4b9367799eaa3197fecb144eb71de1e049150"; - BalanceContract.TransferContract.Builder builder2 = - BalanceContract.TransferContract.newBuilder() - .setOwnerAddress( - ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) - .setToAddress( - ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); - return new TransactionCapsule(builder2.build(), - Protocol.Transaction.Contract.ContractType.TransferContract); - } - - @Test - public void testPrintTransactionSignWeight() { - TransactionCapsule transactionCapsule = getTransactionCapsuleExample(); - GrpcAPI.TransactionExtention transactionExtention = - GrpcAPI.TransactionExtention.newBuilder() - .setTransaction(transactionCapsule.getInstance()) - .build(); - GrpcAPI.TransactionSignWeight txSignWeight = - GrpcAPI.TransactionSignWeight.newBuilder() - .setTransaction(transactionExtention) - .build(); - - String out = Util.printTransactionSignWeight(txSignWeight, true); - Assert.assertNotNull(out); - } - - @Test - public void testPrintTransactionApprovedList() { - TransactionCapsule transactionCapsule = getTransactionCapsuleExample(); - GrpcAPI.TransactionExtention transactionExtention = - GrpcAPI.TransactionExtention.newBuilder() - .setTransaction(transactionCapsule.getInstance()) - .build(); - GrpcAPI.TransactionApprovedList transactionApprovedList = - GrpcAPI.TransactionApprovedList.newBuilder() - .setTransaction(transactionExtention) - .build(); - String out = Util.printTransactionApprovedList( - transactionApprovedList, true); - Assert.assertNotNull(out); - } - - @Test - public void testGenerateContractAddress() { - final String OWNER_ADDRESS = "41548794500882809695a8a687866e76d4271a1abc"; - TransactionCapsule transactionCapsule = getTransactionCapsuleExample(); - byte[] out = Util.generateContractAddress( - transactionCapsule.getInstance(), OWNER_ADDRESS.getBytes()); - Assert.assertNotNull(out); - } - - @Test - public void testPrintTransactionToJSON() { - final String OWNER_ADDRESS = "41548794500882809695a8a687866e76d4271a1abc"; - SmartContractOuterClass.CreateSmartContract.Builder builder2 = - SmartContractOuterClass.CreateSmartContract.newBuilder() - .setOwnerAddress( - ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); - TransactionCapsule transactionCapsule = new TransactionCapsule(builder2.build(), - Protocol.Transaction.Contract.ContractType.CreateSmartContract); - - JSONObject out = Util.printTransactionToJSON( - transactionCapsule.getInstance(), true); - Assert.assertNotNull(out); - } - - @Test - public void testGetContractType() { - String out = Util.getContractType("{\"contractType\":\"123\"}\n"); - Assert.assertEquals("123", out); - } - - @Test - public void testGetHexAddress() { - String out = Util.getHexAddress("TBxSocpujP6UGKV5ydXNVTDQz7fAgdmoaB"); - Assert.assertNotNull(out); - - Assert.assertNull(Util.getHexAddress(null)); - } - - @Test - public void testSetTransactionPermissionId() { - TransactionCapsule transactionCapsule = getTransactionCapsuleExample(); - Protocol.Transaction out = Util.setTransactionPermissionId( - 123, transactionCapsule.getInstance()); - Assert.assertNotNull(out); - } - - @Test - public void testSetTransactionExtraData() { - TransactionCapsule transactionCapsule = getTransactionCapsuleExample(); - JSONObject jsonObject = JSONObject.parseObject("{\"extra_data\":\"test\"}"); - Protocol.Transaction out = Util.setTransactionExtraData(jsonObject, - transactionCapsule.getInstance(), true); - Assert.assertNotNull(out); - } - - @Test - public void testConvertOutput() { - Protocol.Account account = Protocol.Account.newBuilder().build(); - String out = Util.convertOutput(account); - Assert.assertNotNull(out); - - account = Protocol.Account.newBuilder() - .setAssetIssuedID(ByteString.copyFrom("asset_issued_ID".getBytes())) - .build(); - out = Util.convertOutput(account); - Assert.assertNotNull(out); - } - - @Test - public void testConvertLogAddressToTronAddress() { - List logs = new ArrayList<>(); - logs.add(Protocol.TransactionInfo.Log.newBuilder() - .setAddress(ByteString.copyFrom("address".getBytes())) - .setData(ByteString.copyFrom("data".getBytes())) - .addTopics(ByteString.copyFrom("topic".getBytes())) - .build()); - - Protocol.TransactionInfo.Builder builder = Protocol.TransactionInfo.newBuilder() - .addAllLog(logs); - List logList = - Util.convertLogAddressToTronAddress(builder.build()); - Assert.assertNotNull(logList.size() > 0); - } - - @Test - public void testValidateParameter() { - String contract = "{\"address\":\"owner_address\"}"; - Assert.assertThrows( - InvalidParameterException.class, - () -> { - Util.validateParameter(contract); - } - ); - String contract1 = - "{\"owner_address\":\"owner_address\"," - + " \"contract_address1\":\"contract_address\", \"data1\":\"data\"}"; - Assert.assertThrows( - InvalidParameterException.class, - () -> { - Util.validateParameter(contract1); - } - ); - String contract2 = - "{\"owner_address\":\"owner_address\", " - + "\"function_selector\":\"function_selector\", \"data\":\"data\"}"; - Assert.assertThrows( - InvalidParameterException.class, - () -> { - Util.validateParameter(contract2); - } - ); - } - - @Test - public void testGetJsonString() { - String str = ""; - String ret = Util.getJsonString(str); - Assert.assertTrue(StringUtils.isEmpty(ret)); - - String str1 = "{\"owner_address\":\"owner_address\"}"; - String ret1 = Util.getJsonString(str1); - Assert.assertTrue(str1.equals(ret1)); - - String str2 = "owner_address=owner_address&contract_address=contract_address"; - String ret2 = Util.getJsonString(str2); - String expect = - "{\"owner_address\":\"owner_address\"," - + "\"contract_address\":\"contract_address\"}"; - Assert.assertEquals(expect, ret2); - } - -} From 555a839be9d5b350c496306628feb22876d373c8 Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 28 Nov 2024 13:19:14 +0800 Subject: [PATCH 1092/1197] feat(version): update version to 4.7.7 --- framework/src/main/java/org/tron/program/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 250bc087be3..4790ee62bad 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -4,7 +4,7 @@ public class Version { public static final String VERSION_NAME = "GreatVoyage-v4.7.5-64-g4103dfeb63"; public static final String VERSION_CODE = "18372"; - private static final String VERSION = "4.7.6"; + private static final String VERSION = "4.7.7"; public static String getVersion() { return VERSION; From 39d99eea3cfe1eaa1111f0362c71a32c7e5b227f Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 6 Jun 2024 17:07:32 +0800 Subject: [PATCH 1093/1197] feat(metric): add prometheus interceptor --- .../org/tron/core/services/RpcApiService.java | 8 ++++ .../interfaceOnPBFT/RpcApiServiceOnPBFT.java | 9 ++++ .../RpcApiServiceOnSolidity.java | 9 ++++ .../ratelimiter/PrometheusInterceptor.java | 46 +++++++++++++++++++ .../ratelimiter/RpcApiAccessInterceptor.java | 9 +--- .../core/services/RpcApiServicesTest.java | 2 + 6 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/services/ratelimiter/PrometheusInterceptor.java diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 85ad2dd18dd..3cc50c77890 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -98,6 +98,7 @@ import org.tron.core.exception.ZksnarkException; import org.tron.core.metrics.MetricsApiService; import org.tron.core.services.filter.LiteFnQueryGrpcInterceptor; +import org.tron.core.services.ratelimiter.PrometheusInterceptor; import org.tron.core.services.ratelimiter.RateLimiterInterceptor; import org.tron.core.services.ratelimiter.RpcApiAccessInterceptor; import org.tron.core.utils.TransactionUtil; @@ -189,6 +190,8 @@ public class RpcApiService extends RpcService { private RpcApiAccessInterceptor apiAccessInterceptor; @Autowired private MetricsApiService metricsApiService; + @Autowired + private PrometheusInterceptor prometheusInterceptor; @Getter private DatabaseApi databaseApi = new DatabaseApi(); private WalletApi walletApi = new WalletApi(); @@ -252,6 +255,11 @@ public void start() { // add lite fullnode query interceptor serverBuilder.intercept(liteFnQueryGrpcInterceptor); + // add prometheus interceptor + if (parameter.isMetricsPrometheusEnable()) { + serverBuilder.intercept(prometheusInterceptor); + } + if (parameter.isRpcReflectionServiceEnable()) { serverBuilder.addService(ProtoReflectionService.newInstance()); } diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java index 4d801f20e5c..cf945f664d1 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java @@ -41,6 +41,7 @@ import org.tron.core.config.args.Args; import org.tron.core.services.RpcApiService; import org.tron.core.services.filter.LiteFnQueryGrpcInterceptor; +import org.tron.core.services.ratelimiter.PrometheusInterceptor; import org.tron.core.services.ratelimiter.RateLimiterInterceptor; import org.tron.core.services.ratelimiter.RpcApiAccessInterceptor; import org.tron.protos.Protocol.Account; @@ -79,6 +80,9 @@ public class RpcApiServiceOnPBFT extends RpcService { @Autowired private RpcApiAccessInterceptor apiAccessInterceptor; + @Autowired + private PrometheusInterceptor prometheusInterceptor; + private final String executorName = "rpc-pbft-executor"; @Override @@ -124,6 +128,11 @@ public void start() { // add lite fullnode query interceptor serverBuilder.intercept(liteFnQueryGrpcInterceptor); + // add prometheus interceptor + if (args.isMetricsPrometheusEnable()) { + serverBuilder.intercept(prometheusInterceptor); + } + if (args.isRpcReflectionServiceEnable()) { serverBuilder.addService(ProtoReflectionService.newInstance()); } diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java index 6bdfc824163..4bd3fbe4fef 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java @@ -42,6 +42,7 @@ import org.tron.core.config.args.Args; import org.tron.core.services.RpcApiService; import org.tron.core.services.filter.LiteFnQueryGrpcInterceptor; +import org.tron.core.services.ratelimiter.PrometheusInterceptor; import org.tron.core.services.ratelimiter.RateLimiterInterceptor; import org.tron.core.services.ratelimiter.RpcApiAccessInterceptor; import org.tron.protos.Protocol.Account; @@ -81,6 +82,9 @@ public class RpcApiServiceOnSolidity extends RpcService { @Autowired private RpcApiAccessInterceptor apiAccessInterceptor; + @Autowired + private PrometheusInterceptor prometheusInterceptor; + private final String executorName = "rpc-solidity-executor"; @Override @@ -125,6 +129,11 @@ public void start() { // add lite fullnode query interceptor serverBuilder.intercept(liteFnQueryGrpcInterceptor); + // add prometheus interceptor + if (parameter.isMetricsPrometheusEnable()) { + serverBuilder.intercept(prometheusInterceptor); + } + if (parameter.isRpcReflectionServiceEnable()) { serverBuilder.addService(ProtoReflectionService.newInstance()); } diff --git a/framework/src/main/java/org/tron/core/services/ratelimiter/PrometheusInterceptor.java b/framework/src/main/java/org/tron/core/services/ratelimiter/PrometheusInterceptor.java new file mode 100644 index 00000000000..97458ffb1c4 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/ratelimiter/PrometheusInterceptor.java @@ -0,0 +1,46 @@ + +package org.tron.core.services.ratelimiter; + +import io.grpc.ForwardingServerCall; +import io.grpc.Metadata; +import io.grpc.ServerCall; +import io.grpc.ServerCallHandler; +import io.grpc.ServerInterceptor; +import io.grpc.Status; +import io.prometheus.client.Histogram; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.tron.common.prometheus.MetricKeys; +import org.tron.common.prometheus.Metrics; + +/** + * A {@link ServerInterceptor} which sends latency stats about incoming grpc calls to Prometheus. + */ +@Slf4j(topic = "metrics") +@Component +public class PrometheusInterceptor implements ServerInterceptor { + + @Override + public ServerCall.Listener interceptCall( + ServerCall call, Metadata requestMetadata, ServerCallHandler next) { + return next.startCall(new MonitoringServerCall<>(call), requestMetadata); + } + + static class MonitoringServerCall extends ForwardingServerCall + .SimpleForwardingServerCall { + + private final Histogram.Timer requestTimer; + + MonitoringServerCall(ServerCall delegate) { + super(delegate); + this.requestTimer = Metrics.histogramStartTimer( + MetricKeys.Histogram.GRPC_SERVICE_LATENCY, getMethodDescriptor().getFullMethodName()); + } + + @Override + public void close(Status status, Metadata responseHeaders) { + Metrics.histogramObserve(requestTimer); + super.close(status, responseHeaders); + } + } +} diff --git a/framework/src/main/java/org/tron/core/services/ratelimiter/RpcApiAccessInterceptor.java b/framework/src/main/java/org/tron/core/services/ratelimiter/RpcApiAccessInterceptor.java index 8b5812129a2..c3471c2829c 100644 --- a/framework/src/main/java/org/tron/core/services/ratelimiter/RpcApiAccessInterceptor.java +++ b/framework/src/main/java/org/tron/core/services/ratelimiter/RpcApiAccessInterceptor.java @@ -6,13 +6,10 @@ import io.grpc.ServerCallHandler; import io.grpc.ServerInterceptor; import io.grpc.Status; -import io.prometheus.client.Histogram; import java.util.List; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.tron.common.parameter.CommonParameter; -import org.tron.common.prometheus.MetricKeys; -import org.tron.common.prometheus.Metrics; @Slf4j @Component @@ -32,11 +29,7 @@ public Listener interceptCall(ServerCall call, return new ServerCall.Listener() {}; } else { - Histogram.Timer requestTimer = Metrics.histogramStartTimer( - MetricKeys.Histogram.GRPC_SERVICE_LATENCY, endpoint); - Listener res = next.startCall(call, headers); - Metrics.histogramObserve(requestTimer); - return res; + return next.startCall(call, headers); } } catch (Exception e) { logger.error("check rpc api access Error: {}", e.getMessage()); diff --git a/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java b/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java index ebb9e0bb223..83930403312 100644 --- a/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java +++ b/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java @@ -138,6 +138,8 @@ public static void init() throws IOException { getInstance().setRpcPort(PublicMethod.chooseRandomPort()); getInstance().setRpcOnSolidityPort(PublicMethod.chooseRandomPort()); getInstance().setRpcOnPBFTPort(PublicMethod.chooseRandomPort()); + getInstance().setMetricsPrometheusPort(PublicMethod.chooseRandomPort()); + getInstance().setMetricsPrometheusEnable(true); String fullNode = String.format("%s:%d", getInstance().getNodeLanIp(), getInstance().getRpcPort()); String solidityNode = String.format("%s:%d", getInstance().getNodeLanIp(), From 3278ced62a40676736023f12610bda220918f7ae Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 21 Oct 2024 15:38:32 +0800 Subject: [PATCH 1094/1197] feat(math): migrate `pow` operation from java.lang.Math to java.lang.StrictMath --- .../actuator/ExchangeTransactionActuator.java | 6 +- .../org/tron/core/utils/ProposalUtil.java | 18 +- .../org/tron/core/vm/config/ConfigLoader.java | 1 + .../org/tron/core/vm/config/VMConfig.java | 10 + .../org/tron/core/vm/program/Program.java | 3 +- .../main/java/org/tron/common/math/Maths.java | 20 ++ .../core/capsule/ContractStateCapsule.java | 10 +- .../tron/core/capsule/ExchangeCapsule.java | 4 +- .../tron/core/capsule/ExchangeProcessor.java | 12 +- .../java/org/tron/core/db/StorageMarket.java | 234 ---------------- .../core/store/DynamicPropertiesStore.java | 14 + .../org/tron/common/math/MathWrapper.java | 14 + .../tron/common/math/StrictMathWrapper.java | 8 + .../common/parameter/CommonParameter.java | 4 + .../src/main/java/org/tron/core/Constant.java | 1 + .../java/org/tron/core/config/Parameter.java | 5 +- .../src/main/java/org/tron/core/Wallet.java | 5 + .../java/org/tron/core/config/args/Args.java | 5 + .../tron/core/consensus/ProposalService.java | 4 + .../java/org/tron/core/StorageMarketTest.java | 256 ------------------ .../ExchangeTransactionActuatorTest.java | 6 +- .../core/actuator/utils/ProposalUtilTest.java | 46 ++++ .../capsule/ContractStateCapsuleTest.java | 46 +++- .../core/capsule/ExchangeCapsuleTest.java | 6 +- .../capsule/utils/ExchangeProcessorTest.java | 12 +- 25 files changed, 224 insertions(+), 526 deletions(-) create mode 100644 chainbase/src/main/java/org/tron/common/math/Maths.java delete mode 100644 chainbase/src/main/java/org/tron/core/db/StorageMarket.java create mode 100644 common/src/main/java/org/tron/common/math/MathWrapper.java create mode 100644 common/src/main/java/org/tron/common/math/StrictMathWrapper.java delete mode 100644 framework/src/test/java/org/tron/core/StorageMarketTest.java diff --git a/actuator/src/main/java/org/tron/core/actuator/ExchangeTransactionActuator.java b/actuator/src/main/java/org/tron/core/actuator/ExchangeTransactionActuator.java index 612f673832e..6f50d61c235 100755 --- a/actuator/src/main/java/org/tron/core/actuator/ExchangeTransactionActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/ExchangeTransactionActuator.java @@ -66,7 +66,8 @@ public boolean execute(Object object) throws ContractExeException { long tokenQuant = exchangeTransactionContract.getQuant(); byte[] anotherTokenID; - long anotherTokenQuant = exchangeCapsule.transaction(tokenID, tokenQuant); + long anotherTokenQuant = exchangeCapsule.transaction(tokenID, tokenQuant, + dynamicStore.allowStrictMath()); if (Arrays.equals(tokenID, firstTokenID)) { anotherTokenID = secondTokenID; @@ -205,7 +206,8 @@ public boolean validate() throws ContractValidateException { } } - long anotherTokenQuant = exchangeCapsule.transaction(tokenID, tokenQuant); + long anotherTokenQuant = exchangeCapsule.transaction(tokenID, tokenQuant, + dynamicStore.allowStrictMath()); if (anotherTokenQuant < tokenExpected) { throw new ContractValidateException("token required must greater than expected"); } diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 8f3501442f0..fb4d6f76228 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -779,6 +779,21 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case ALLOW_STRICT_MATH: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7_7)) { + throw new ContractValidateException( + "Bad chain parameter id [ALLOW_STRICT_MATH]"); + } + if (dynamicPropertiesStore.allowStrictMath()) { + throw new ContractValidateException( + "[ALLOW_STRICT_MATH] has been valid, no need to propose again"); + } + if (value != 1) { + throw new ContractValidateException( + "This value[ALLOW_STRICT_MATH] is only allowed to be 1"); + } + break; + } default: break; } @@ -857,7 +872,8 @@ public enum ProposalType { // current value, value range MAX_DELEGATE_LOCK_PERIOD(78), // (86400, 10512000] ALLOW_OLD_REWARD_OPT(79), // 0, 1 ALLOW_ENERGY_ADJUSTMENT(81), // 0, 1 - MAX_CREATE_ACCOUNT_TX_SIZE(82); // [500, 10000] + MAX_CREATE_ACCOUNT_TX_SIZE(82), // [500, 10000] + ALLOW_STRICT_MATH(87); // 0, 1 private long code; diff --git a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java index 63c3ff791d6..79a536f4cbf 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java +++ b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java @@ -40,6 +40,7 @@ public static void load(StoreFactory storeFactory) { VMConfig.initDynamicEnergyMaxFactor(ds.getDynamicEnergyMaxFactor()); VMConfig.initAllowTvmShangHai(ds.getAllowTvmShangHai()); VMConfig.initAllowEnergyAdjustment(ds.getAllowEnergyAdjustment()); + VMConfig.initAllowStrictMath(ds.getAllowStrictMath()); } } } diff --git a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java index 3eb1f8fd4b8..90a2c6335f6 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java +++ b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java @@ -51,6 +51,8 @@ public class VMConfig { private static boolean ALLOW_ENERGY_ADJUSTMENT = false; + private static boolean ALLOW_STRICT_MATH = false; + private VMConfig() { } @@ -142,6 +144,10 @@ public static void initAllowEnergyAdjustment(long allow) { ALLOW_ENERGY_ADJUSTMENT = allow == 1; } + public static void initAllowStrictMath(long allow) { + ALLOW_STRICT_MATH = allow == 1; + } + public static boolean getEnergyLimitHardFork() { return CommonParameter.ENERGY_LIMIT_HARD_FORK; } @@ -221,4 +227,8 @@ public static boolean allowTvmShanghai() { public static boolean allowEnergyAdjustment() { return ALLOW_ENERGY_ADJUSTMENT; } + + public static boolean allowStrictMath() { + return ALLOW_STRICT_MATH; + } } diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 0b0ef5bc9ba..4273778a7d6 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -2230,7 +2230,8 @@ public long updateContextContractFactor() { contractState.getDynamicPropertiesStore().getCurrentCycleNumber(), VMConfig.getDynamicEnergyThreshold(), VMConfig.getDynamicEnergyIncreaseFactor(), - VMConfig.getDynamicEnergyMaxFactor())) { + VMConfig.getDynamicEnergyMaxFactor(), + VMConfig.allowStrictMath())) { contractState.updateContractState(getContextAddress(), contractStateCapsule ); } diff --git a/chainbase/src/main/java/org/tron/common/math/Maths.java b/chainbase/src/main/java/org/tron/common/math/Maths.java new file mode 100644 index 00000000000..a1ff6ed89a1 --- /dev/null +++ b/chainbase/src/main/java/org/tron/common/math/Maths.java @@ -0,0 +1,20 @@ +package org.tron.common.math; + +/** + * This class is deprecated and should not be used in new code, + * for cross-platform consistency, please use {@link StrictMathWrapper} instead, + * especially for floating-point calculations. + */ +@Deprecated +public class Maths { + + /** + * Returns the value of the first argument raised to the power of the second argument. + * @param a the base. + * @param b the exponent. + * @return the value {@code a}{@code b}. + */ + public static double pow(double a, double b, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.pow(a, b) : MathWrapper.pow(a, b); + } +} diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java index 8633534280b..8ebb86ea332 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java @@ -5,6 +5,7 @@ import com.google.protobuf.InvalidProtocolBufferException; import lombok.extern.slf4j.Slf4j; +import org.tron.common.math.Maths; import org.tron.core.store.DynamicPropertiesStore; import org.tron.protos.contract.SmartContractOuterClass; import org.tron.protos.contract.SmartContractOuterClass.ContractState; @@ -77,12 +78,13 @@ public boolean catchUpToCycle(DynamicPropertiesStore dps) { dps.getCurrentCycleNumber(), dps.getDynamicEnergyThreshold(), dps.getDynamicEnergyIncreaseFactor(), - dps.getDynamicEnergyMaxFactor() + dps.getDynamicEnergyMaxFactor(), + dps.allowStrictMath() ); } public boolean catchUpToCycle( - long newCycle, long threshold, long increaseFactor, long maxFactor + long newCycle, long threshold, long increaseFactor, long maxFactor, boolean useStrictMath ) { long lastCycle = getUpdateCycle(); @@ -119,9 +121,9 @@ public boolean catchUpToCycle( } // Calc the decrease percent (decrease factor [75% ~ 100%]) - double decreasePercent = Math.pow( + double decreasePercent = Maths.pow( 1 - (double) increaseFactor / DYNAMIC_ENERGY_DECREASE_DIVISION / precisionFactor, - cycleCount + cycleCount, useStrictMath ); // Decrease to this cycle diff --git a/chainbase/src/main/java/org/tron/core/capsule/ExchangeCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ExchangeCapsule.java index 1cf91301b43..0dec7d60820 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ExchangeCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ExchangeCapsule.java @@ -112,9 +112,9 @@ public byte[] createDbKey() { return calculateDbKey(getID()); } - public long transaction(byte[] sellTokenID, long sellTokenQuant) { + public long transaction(byte[] sellTokenID, long sellTokenQuant, boolean useStrictMath) { long supply = 1_000_000_000_000_000_000L; - ExchangeProcessor processor = new ExchangeProcessor(supply); + ExchangeProcessor processor = new ExchangeProcessor(supply, useStrictMath); long buyTokenQuant = 0; long firstTokenBalance = this.exchange.getFirstTokenBalance(); diff --git a/chainbase/src/main/java/org/tron/core/capsule/ExchangeProcessor.java b/chainbase/src/main/java/org/tron/core/capsule/ExchangeProcessor.java index e1b536b3e7a..91f5c101b58 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ExchangeProcessor.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ExchangeProcessor.java @@ -1,14 +1,17 @@ package org.tron.core.capsule; import lombok.extern.slf4j.Slf4j; +import org.tron.common.math.Maths; @Slf4j(topic = "capsule") public class ExchangeProcessor { private long supply; + private final boolean useStrictMath; - public ExchangeProcessor(long supply) { + public ExchangeProcessor(long supply, boolean useStrictMath) { this.supply = supply; + this.useStrictMath = useStrictMath; } private long exchangeToSupply(long balance, long quant) { @@ -16,7 +19,8 @@ private long exchangeToSupply(long balance, long quant) { long newBalance = balance + quant; logger.debug("balance + quant: " + newBalance); - double issuedSupply = -supply * (1.0 - Math.pow(1.0 + (double) quant / newBalance, 0.0005)); + double issuedSupply = -supply * (1.0 + - Maths.pow(1.0 + (double) quant / newBalance, 0.0005, this.useStrictMath)); logger.debug("issuedSupply: " + issuedSupply); long out = (long) issuedSupply; supply += out; @@ -27,8 +31,8 @@ private long exchangeToSupply(long balance, long quant) { private long exchangeFromSupply(long balance, long supplyQuant) { supply -= supplyQuant; - double exchangeBalance = - balance * (Math.pow(1.0 + (double) supplyQuant / supply, 2000.0) - 1.0); + double exchangeBalance = balance + * (Maths.pow(1.0 + (double) supplyQuant / supply, 2000.0, this.useStrictMath) - 1.0); logger.debug("exchangeBalance: " + exchangeBalance); return (long) exchangeBalance; diff --git a/chainbase/src/main/java/org/tron/core/db/StorageMarket.java b/chainbase/src/main/java/org/tron/core/db/StorageMarket.java deleted file mode 100644 index 10a3b656565..00000000000 --- a/chainbase/src/main/java/org/tron/core/db/StorageMarket.java +++ /dev/null @@ -1,234 +0,0 @@ -package org.tron.core.db; - -import lombok.extern.slf4j.Slf4j; -import org.tron.core.capsule.AccountCapsule; -import org.tron.core.store.AccountStore; -import org.tron.core.store.DynamicPropertiesStore; - -@Slf4j(topic = "DB") -public class StorageMarket { - private static final String LOG_MSG = "NewTotalPool: {}, newTotalReserved: {}."; - private static final long MS_PER_YEAR = 365 * 24 * 3600 * 1000L; - private AccountStore accountStore; - private DynamicPropertiesStore dynamicPropertiesStore; - private long supply = 1_000_000_000_000_000L; - - - public StorageMarket(AccountStore accountStore, DynamicPropertiesStore dynamicPropertiesStore) { - this.accountStore = accountStore; - this.dynamicPropertiesStore = dynamicPropertiesStore; - } - - private long exchangeToSupply(boolean isTRX, long quant) { - logger.info("IsTRX: {}.", isTRX); - long balance = isTRX ? dynamicPropertiesStore.getTotalStoragePool() : - dynamicPropertiesStore.getTotalStorageReserved(); - logger.info("Balance: {}.", balance); - long newBalance = balance + quant; - logger.info("Balance + quant: {}.", balance + quant); - -// if (isTRX) { -// dbManager.getDynamicPropertiesStore().saveTotalStoragePool(newBalance); -// } else { -// dbManager.getDynamicPropertiesStore().saveTotalStorageReserved(newBalance); -// } - - double issuedSupply = -supply * (1.0 - Math.pow(1.0 + (double) quant / newBalance, 0.0005)); - logger.info("IssuedSupply: {}.", issuedSupply); - long out = (long) issuedSupply; - supply += out; - - return out; - } - - private long exchangeToSupply2(boolean isTRX, long quant) { - logger.info("IsTRX: {}.", isTRX); - long balance = isTRX ? dynamicPropertiesStore.getTotalStoragePool() : - dynamicPropertiesStore.getTotalStorageReserved(); - logger.info("Balance: {}.", balance); - long newBalance = balance - quant; - logger.info("Balance - quant: {}.", balance - quant); - -// if (isTRX) { -// dbManager.getDynamicPropertiesStore().saveTotalStoragePool(newBalance); -// } else { -// dbManager.getDynamicPropertiesStore().saveTotalStorageReserved(newBalance); -// } - - double issuedSupply = -supply * (1.0 - Math.pow(1.0 + (double) quant / newBalance, 0.0005)); - logger.info("IssuedSupply: {}.", issuedSupply); - long out = (long) issuedSupply; - supply += out; - - return out; - } - - private long exchange_from_supply(boolean isTRX, long supplyQuant) { - long balance = isTRX ? dynamicPropertiesStore.getTotalStoragePool() : - dynamicPropertiesStore.getTotalStorageReserved(); - supply -= supplyQuant; - - double exchangeBalance = - balance * (Math.pow(1.0 + (double) supplyQuant / supply, 2000.0) - 1.0); - logger.info("ExchangeBalance: {}.", exchangeBalance); - long out = (long) exchangeBalance; - - if (isTRX) { - out = Math.round(exchangeBalance / 100000) * 100000; - logger.info("Out: {}.", out); - } - - return out; - } - - public long exchange(long from, boolean isTRX) { - long relay = exchangeToSupply(isTRX, from); - return exchange_from_supply(!isTRX, relay); - } - - public long calculateTax(long duration, long limit) { - // todo: Support for change by the committee - double ratePerYear = dynamicPropertiesStore.getStorageExchangeTaxRate() / 100.0; - double millisecondPerYear = MS_PER_YEAR; - double feeRate = duration / millisecondPerYear * ratePerYear; - long storageTax = (long) (limit * feeRate); - logger.info("StorageTax: {}.", storageTax); - return storageTax; - } - - - public long tryPayTax(long duration, long limit) { - long storageTax = calculateTax(duration, limit); - long tax = exchange(storageTax, false); - logger.info("Tax: {}.", tax); - - long newTotalTax = dynamicPropertiesStore.getTotalStorageTax() + tax; - long newTotalPool = dynamicPropertiesStore.getTotalStoragePool() - tax; - long newTotalReserved = dynamicPropertiesStore.getTotalStorageReserved() - + storageTax; - logger.info("Reserved: {}.", dynamicPropertiesStore.getTotalStorageReserved()); - boolean eq = dynamicPropertiesStore.getTotalStorageReserved() - == 128L * 1024 * 1024 * 1024; - logger.info("Reserved == 128GB: {}.", eq); - logger.info("NewTotalTax: {}, newTotalPool: {}, newTotalReserved: {}.", - newTotalTax, newTotalPool, newTotalReserved); - - return storageTax; - } - - public long payTax(long duration, long limit) { - long storageTax = calculateTax(duration, limit); - long tax = exchange(storageTax, false); - logger.info("Tax: {}.", tax); - - long newTotalTax = dynamicPropertiesStore.getTotalStorageTax() + tax; - long newTotalPool = dynamicPropertiesStore.getTotalStoragePool() - tax; - long newTotalReserved = dynamicPropertiesStore.getTotalStorageReserved() - + storageTax; - logger.info("Reserved: {}.", dynamicPropertiesStore.getTotalStorageReserved()); - boolean eq = dynamicPropertiesStore.getTotalStorageReserved() - == 128L * 1024 * 1024 * 1024; - logger.info("Reserved == 128GB: {}.", eq); - logger.info("NewTotalTax: {}, newTotalPool: {}, newTotalReserved: {}.", - newTotalTax, newTotalPool, newTotalReserved); - dynamicPropertiesStore.saveTotalStorageTax(newTotalTax); - dynamicPropertiesStore.saveTotalStoragePool(newTotalPool); - dynamicPropertiesStore.saveTotalStorageReserved(newTotalReserved); - - return storageTax; - } - - public long tryBuyStorageBytes(long storageBought) { - long relay = exchangeToSupply2(false, storageBought); - return exchange_from_supply(true, relay); - } - - public long tryBuyStorage(long quant) { - return exchange(quant, true); - } - - public long trySellStorage(long bytes) { - return exchange(bytes, false); - } - - public AccountCapsule buyStorageBytes(AccountCapsule accountCapsule, long storageBought) { - long now = dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); - long currentStorageLimit = accountCapsule.getStorageLimit(); - - long relay = exchangeToSupply2(false, storageBought); - long quant = exchange_from_supply(true, relay); - - long newBalance = accountCapsule.getBalance() - quant; - logger.info("New balance: {}.", newBalance); - - long newStorageLimit = currentStorageLimit + storageBought; - logger.info("StorageBought: {}, newStorageLimit: {}.", storageBought, newStorageLimit); - - accountCapsule.setLatestExchangeStorageTime(now); - accountCapsule.setStorageLimit(newStorageLimit); - accountCapsule.setBalance(newBalance); - accountStore.put(accountCapsule.createDbKey(), accountCapsule); - - long newTotalPool = dynamicPropertiesStore.getTotalStoragePool() + quant; - long newTotalReserved = dynamicPropertiesStore.getTotalStorageReserved() - - storageBought; - logger.info(LOG_MSG, newTotalPool, newTotalReserved); - dynamicPropertiesStore.saveTotalStoragePool(newTotalPool); - dynamicPropertiesStore.saveTotalStorageReserved(newTotalReserved); - return accountCapsule; - } - - - public void buyStorage(AccountCapsule accountCapsule, long quant) { - long now = dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); - long currentStorageLimit = accountCapsule.getStorageLimit(); - - long newBalance = accountCapsule.getBalance() - quant; - logger.info("New balance: {}.", newBalance); - - long storageBought = exchange(quant, true); - long newStorageLimit = currentStorageLimit + storageBought; - logger.info("StorageBought: {}, newStorageLimit: {}.", storageBought, newStorageLimit); - - accountCapsule.setLatestExchangeStorageTime(now); - accountCapsule.setStorageLimit(newStorageLimit); - accountCapsule.setBalance(newBalance); - accountStore.put(accountCapsule.createDbKey(), accountCapsule); - - long newTotalPool = dynamicPropertiesStore.getTotalStoragePool() + quant; - long newTotalReserved = dynamicPropertiesStore.getTotalStorageReserved() - - storageBought; - logger.info(LOG_MSG, newTotalPool, newTotalReserved); - dynamicPropertiesStore.saveTotalStoragePool(newTotalPool); - dynamicPropertiesStore.saveTotalStorageReserved(newTotalReserved); - - } - - public void sellStorage(AccountCapsule accountCapsule, long bytes) { - long now = dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); - long currentStorageLimit = accountCapsule.getStorageLimit(); - - long quant = exchange(bytes, false); - long newBalance = accountCapsule.getBalance() + quant; - - long newStorageLimit = currentStorageLimit - bytes; - logger.info("Quant: {}, newStorageLimit: {}.", quant, newStorageLimit); - - accountCapsule.setLatestExchangeStorageTime(now); - accountCapsule.setStorageLimit(newStorageLimit); - accountCapsule.setBalance(newBalance); - accountStore.put(accountCapsule.createDbKey(), accountCapsule); - - long newTotalPool = dynamicPropertiesStore.getTotalStoragePool() - quant; - long newTotalReserved = dynamicPropertiesStore.getTotalStorageReserved() - + bytes; - logger.info(LOG_MSG, newTotalPool, newTotalReserved); - dynamicPropertiesStore.saveTotalStoragePool(newTotalPool); - dynamicPropertiesStore.saveTotalStorageReserved(newTotalReserved); - - } - - public long getAccountLeftStorageInByteFromBought(AccountCapsule accountCapsule) { - return accountCapsule.getStorageLimit() - accountCapsule.getStorageUsage(); - } -} diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 2b50ec76af2..4af338f09bb 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -222,6 +222,7 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_ENERGY_ADJUSTMENT = "ALLOW_ENERGY_ADJUSTMENT".getBytes(); private static final byte[] MAX_CREATE_ACCOUNT_TX_SIZE = "MAX_CREATE_ACCOUNT_TX_SIZE".getBytes(); + private static final byte[] ALLOW_STRICT_MATH = "ALLOW_STRICT_MATH".getBytes(); @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { @@ -2876,6 +2877,19 @@ public long getMaxCreateAccountTxSize() { .map(ByteArray::toLong) .orElse(CommonParameter.getInstance().getMaxCreateAccountTxSize()); } + public long getAllowStrictMath() { + return Optional.ofNullable(getUnchecked(ALLOW_STRICT_MATH)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElse(CommonParameter.getInstance().getAllowStrictMath()); + } + public void saveAllowStrictMath(long allowStrictMath) { + this.put(ALLOW_STRICT_MATH, new BytesCapsule(ByteArray.fromLong(allowStrictMath))); + } + + public boolean allowStrictMath() { + return getAllowStrictMath() == 1L; + } private static class DynamicResourceProperties { diff --git a/common/src/main/java/org/tron/common/math/MathWrapper.java b/common/src/main/java/org/tron/common/math/MathWrapper.java new file mode 100644 index 00000000000..519dafb9d42 --- /dev/null +++ b/common/src/main/java/org/tron/common/math/MathWrapper.java @@ -0,0 +1,14 @@ +package org.tron.common.math; + +/** + * This class is deprecated and should not be used in new code, + * for cross-platform consistency, please use {@link StrictMathWrapper} instead, + * especially for floating-point calculations. + */ +@Deprecated +public class MathWrapper { + + public static double pow(double a, double b) { + return Math.pow(a, b); + } +} diff --git a/common/src/main/java/org/tron/common/math/StrictMathWrapper.java b/common/src/main/java/org/tron/common/math/StrictMathWrapper.java new file mode 100644 index 00000000000..6285f6567c0 --- /dev/null +++ b/common/src/main/java/org/tron/common/math/StrictMathWrapper.java @@ -0,0 +1,8 @@ +package org.tron.common.math; + +public class StrictMathWrapper { + + public static double pow(double a, double b) { + return StrictMath.pow(a, b); + } +} diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 62ed12d856c..1aa3befe8aa 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -677,6 +677,10 @@ public class CommonParameter { @Setter public long maxCreateAccountTxSize = 1000L; + @Getter + @Setter + public long allowStrictMath; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index da3b2b1becc..96ff41b91da 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -386,4 +386,5 @@ public class Constant { public static final String COMMITTEE_ALLOW_OLD_REWARD_OPT = "committee.allowOldRewardOpt"; public static final String COMMITTEE_ALLOW_ENERGY_ADJUSTMENT = "committee.allowEnergyAdjustment"; + public static final String COMMITTEE_ALLOW_STRICT_MATH = "committee.allowStrictMath"; } diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index 027c225eb5d..247c5dd4fe2 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -24,7 +24,8 @@ public enum ForkBlockVersionEnum { VERSION_4_7_1(27, 1596780000000L, 80), VERSION_4_7_2(28, 1596780000000L, 80), VERSION_4_7_4(29, 1596780000000L, 80), - VERSION_4_7_5(30, 1596780000000L, 80); + VERSION_4_7_5(30, 1596780000000L, 80), + VERSION_4_7_7(31, 1596780000000L, 80); // if add a version, modify BLOCK_VERSION simultaneously @Getter @@ -73,7 +74,7 @@ public class ChainConstant { public static final int SINGLE_REPEAT = 1; public static final int BLOCK_FILLED_SLOTS_NUMBER = 128; public static final int MAX_FROZEN_NUMBER = 1; - public static final int BLOCK_VERSION = 30; + public static final int BLOCK_VERSION = 31; public static final long FROZEN_PERIOD = 86_400_000L; public static final long DELEGATE_PERIOD = 3 * 86_400_000L; public static final long TRX_PRECISION = 1000_000L; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 769274e8f2a..0943723f2f4 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1343,6 +1343,11 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getMaxCreateAccountTxSize()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getAllowStrictMath") + .setValue(dbManager.getDynamicPropertiesStore().getAllowStrictMath()) + .build()); + return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 00142733f74..8853971a5f8 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -234,6 +234,7 @@ public static void clearParam() { PARAMETER.maxUnsolidifiedBlocks = 54; PARAMETER.allowOldRewardOpt = 0; PARAMETER.allowEnergyAdjustment = 0; + PARAMETER.allowStrictMath = 0; } /** @@ -1217,6 +1218,10 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.COMMITTEE_ALLOW_ENERGY_ADJUSTMENT) ? config .getInt(Constant.COMMITTEE_ALLOW_ENERGY_ADJUSTMENT) : 0; + PARAMETER.allowStrictMath = + config.hasPath(Constant.COMMITTEE_ALLOW_STRICT_MATH) ? config + .getInt(Constant.COMMITTEE_ALLOW_STRICT_MATH) : 0; + logConfig(); } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index d0c106a7e57..29eef1c3cb3 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -367,6 +367,10 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveMaxCreateAccountTxSize(entry.getValue()); break; } + case ALLOW_STRICT_MATH: { + manager.getDynamicPropertiesStore().saveAllowStrictMath(entry.getValue()); + break; + } default: find = false; break; diff --git a/framework/src/test/java/org/tron/core/StorageMarketTest.java b/framework/src/test/java/org/tron/core/StorageMarketTest.java deleted file mode 100644 index 8b6e90e1c67..00000000000 --- a/framework/src/test/java/org/tron/core/StorageMarketTest.java +++ /dev/null @@ -1,256 +0,0 @@ -package org.tron.core; - -import static org.tron.core.config.Parameter.ChainConstant.TRANSFER_FEE; - -import com.google.protobuf.Any; -import com.google.protobuf.ByteString; -import lombok.extern.slf4j.Slf4j; -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.capsule.AccountCapsule; -import org.tron.core.config.args.Args; -import org.tron.core.db.StorageMarket; -import org.tron.protos.Protocol.AccountType; -import org.tron.protos.contract.StorageContract.BuyStorageContract; - -@Slf4j -public class StorageMarketTest extends BaseTest { - - private static final String OWNER_ADDRESS; - private static final long initBalance = 10_000_000_000_000_000L; - private static StorageMarket storageMarket; - - static { - Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); - OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; - } - - /** - * create temp Capsule test need. - */ - @Before - public void createAccountCapsule() { - storageMarket = new StorageMarket(dbManager.getAccountStore(), - dbManager.getDynamicPropertiesStore()); - - AccountCapsule ownerCapsule = - new AccountCapsule( - ByteString.copyFromUtf8("owner"), - ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), - AccountType.Normal, - initBalance); - dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); - - dbManager.getDynamicPropertiesStore().saveTotalStorageReserved( - 128L * 1024 * 1024 * 1024); - dbManager.getDynamicPropertiesStore().saveTotalStoragePool(100_000_000_000000L); - dbManager.getDynamicPropertiesStore().saveTotalStorageTax(0); - - dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(0); - } - - private Any getContract(String ownerAddress, long quant) { - return Any.pack( - BuyStorageContract.newBuilder() - .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress))) - .setQuant(quant) - .build()); - } - - @Test - public void testBuyStorage() { - long currentPool = dbManager.getDynamicPropertiesStore().getTotalStoragePool(); - long currentReserved = dbManager.getDynamicPropertiesStore().getTotalStorageReserved(); - Assert.assertEquals(currentPool, 100_000_000_000000L); - Assert.assertEquals(currentReserved, 128L * 1024 * 1024 * 1024); - - AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); - - long quant = 2_000_000_000_000L; // 2 million trx - storageMarket.buyStorage(owner, quant); - - Assert.assertEquals(owner.getBalance(), initBalance - quant - - TRANSFER_FEE); - Assert.assertEquals(2694881440L, owner.getStorageLimit()); - Assert.assertEquals(currentReserved - 2694881440L, - dbManager.getDynamicPropertiesStore().getTotalStorageReserved()); - Assert.assertEquals(currentPool + quant, - dbManager.getDynamicPropertiesStore().getTotalStoragePool()); - - } - - @Test - public void testBuyStorage2() { - long currentPool = dbManager.getDynamicPropertiesStore().getTotalStoragePool(); - long currentReserved = dbManager.getDynamicPropertiesStore().getTotalStorageReserved(); - Assert.assertEquals(currentPool, 100_000_000_000000L); - Assert.assertEquals(currentReserved, 128L * 1024 * 1024 * 1024); - - AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); - - long quant = 1_000_000_000_000L; // 1 million trx - - storageMarket.buyStorage(owner, quant); - - Assert.assertEquals(owner.getBalance(), initBalance - quant - - TRANSFER_FEE); - Assert.assertEquals(1360781717L, owner.getStorageLimit()); - Assert.assertEquals(currentReserved - 1360781717L, - dbManager.getDynamicPropertiesStore().getTotalStorageReserved()); - Assert.assertEquals(currentPool + quant, - dbManager.getDynamicPropertiesStore().getTotalStoragePool()); - - storageMarket.buyStorage(owner, quant); - - Assert.assertEquals(owner.getBalance(), initBalance - 2 * quant - - TRANSFER_FEE); - Assert.assertEquals(2694881439L, owner.getStorageLimit()); - Assert.assertEquals(currentReserved - 2694881439L, - dbManager.getDynamicPropertiesStore().getTotalStorageReserved()); - Assert.assertEquals(currentPool + 2 * quant, - dbManager.getDynamicPropertiesStore().getTotalStoragePool()); - - } - - - @Test - public void testBuyStorageBytes() { - long currentPool = dbManager.getDynamicPropertiesStore().getTotalStoragePool(); - long currentReserved = dbManager.getDynamicPropertiesStore().getTotalStorageReserved(); - Assert.assertEquals(currentPool, 100_000_000_000000L); - Assert.assertEquals(currentReserved, 128L * 1024 * 1024 * 1024); - - AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); - - long bytes = 2694881440L; // 2 million trx - storageMarket.buyStorageBytes(owner, bytes); - - Assert.assertEquals(owner.getBalance(), initBalance - 2_000_000_000_000L - - TRANSFER_FEE); - Assert.assertEquals(bytes, owner.getStorageLimit()); - Assert.assertEquals(currentReserved - bytes, - dbManager.getDynamicPropertiesStore().getTotalStorageReserved()); - Assert.assertEquals(currentPool + 2_000_000_000_000L, - dbManager.getDynamicPropertiesStore().getTotalStoragePool()); - - } - - @Test - public void testBuyStorageBytes2() { - long currentPool = dbManager.getDynamicPropertiesStore().getTotalStoragePool(); - long currentReserved = dbManager.getDynamicPropertiesStore().getTotalStorageReserved(); - Assert.assertEquals(currentPool, 100_000_000_000000L); - Assert.assertEquals(currentReserved, 128L * 1024 * 1024 * 1024); - - AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); - - long bytes1 = 1360781717L; - - storageMarket.buyStorageBytes(owner, bytes1); - - Assert.assertEquals(owner.getBalance(), initBalance - 1_000_000_000_000L - - TRANSFER_FEE); - Assert.assertEquals(bytes1, owner.getStorageLimit()); - Assert.assertEquals(currentReserved - bytes1, - dbManager.getDynamicPropertiesStore().getTotalStorageReserved()); - Assert.assertEquals(currentPool + 1_000_000_000_000L, - dbManager.getDynamicPropertiesStore().getTotalStoragePool()); - - long bytes2 = 1334099723L; - storageMarket.buyStorageBytes(owner, bytes2); - Assert.assertEquals(owner.getBalance(), initBalance - 2 * 1_000_000_000_000L - - TRANSFER_FEE); - Assert.assertEquals(bytes1 + bytes2, owner.getStorageLimit()); - Assert.assertEquals(currentReserved - (bytes1 + bytes2), - dbManager.getDynamicPropertiesStore().getTotalStorageReserved()); - Assert.assertEquals(currentPool + 2 * 1_000_000_000_000L, - dbManager.getDynamicPropertiesStore().getTotalStoragePool()); - - } - - @Test - public void testSellStorage() { - long currentPool = dbManager.getDynamicPropertiesStore().getTotalStoragePool(); - long currentReserved = dbManager.getDynamicPropertiesStore().getTotalStorageReserved(); - Assert.assertEquals(currentPool, 100_000_000_000000L); - Assert.assertEquals(currentReserved, 128L * 1024 * 1024 * 1024); - - AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); - - long quant = 2_000_000_000_000L; // 2 million trx - storageMarket.buyStorage(owner, quant); - - Assert.assertEquals(owner.getBalance(), initBalance - quant - - TRANSFER_FEE); - Assert.assertEquals(2694881440L, owner.getStorageLimit()); - Assert.assertEquals(currentReserved - 2694881440L, - dbManager.getDynamicPropertiesStore().getTotalStorageReserved()); - Assert.assertEquals(currentPool + quant, - dbManager.getDynamicPropertiesStore().getTotalStoragePool()); - - long bytes = 2694881440L; - storageMarket.sellStorage(owner, bytes); - - Assert.assertEquals(owner.getBalance(), initBalance); - Assert.assertEquals(0, owner.getStorageLimit()); - Assert.assertEquals(currentReserved, - dbManager.getDynamicPropertiesStore().getTotalStorageReserved()); - Assert.assertEquals(100_000_000_000_000L, - dbManager.getDynamicPropertiesStore().getTotalStoragePool()); - - } - - @Test - public void testSellStorage2() { - long currentPool = dbManager.getDynamicPropertiesStore().getTotalStoragePool(); - long currentReserved = dbManager.getDynamicPropertiesStore().getTotalStorageReserved(); - Assert.assertEquals(currentPool, 100_000_000_000000L); - Assert.assertEquals(currentReserved, 128L * 1024 * 1024 * 1024); - - AccountCapsule owner = - dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); - - long quant = 2_000_000_000_000L; // 2 million trx - storageMarket.buyStorage(owner, quant); - - Assert.assertEquals(owner.getBalance(), initBalance - quant - - TRANSFER_FEE); - Assert.assertEquals(2694881440L, owner.getStorageLimit()); - Assert.assertEquals(currentReserved - 2694881440L, - dbManager.getDynamicPropertiesStore().getTotalStorageReserved()); - Assert.assertEquals(currentPool + quant, - dbManager.getDynamicPropertiesStore().getTotalStoragePool()); - - long bytes1 = 2694881440L - 1360781717L; // 1 million trx - long bytes2 = 1360781717L; // 1 million trx - - storageMarket.sellStorage(owner, bytes1); - - Assert.assertEquals(owner.getBalance(), initBalance - 1_000_000_000_000L); - Assert.assertEquals(1360781717L, owner.getStorageLimit()); - Assert.assertEquals(currentReserved - 1360781717L, - dbManager.getDynamicPropertiesStore().getTotalStorageReserved()); - Assert.assertEquals(currentPool + 1_000_000_000_000L, - dbManager.getDynamicPropertiesStore().getTotalStoragePool()); - - storageMarket.sellStorage(owner, bytes2); - - Assert.assertEquals(owner.getBalance(), initBalance); - Assert.assertEquals(0, owner.getStorageLimit()); - Assert.assertEquals(currentReserved, - dbManager.getDynamicPropertiesStore().getTotalStorageReserved()); - Assert.assertEquals(currentPool, - dbManager.getDynamicPropertiesStore().getTotalStoragePool()); - - } - - -} diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java index 02107427cad..bf60b1cd910 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java @@ -1502,6 +1502,7 @@ public void SameTokenNameOpenTokenBalanceNotEnough() { @Test public void SameTokenNameCloseTokenRequiredNotEnough() { dbManager.getDynamicPropertiesStore().saveAllowSameTokenName(0); + final boolean useStrictMath = dbManager.getDynamicPropertiesStore().allowStrictMath(); InitExchangeBeforeSameTokenNameActive(); long exchangeId = 2; String tokenId = "abc"; @@ -1520,7 +1521,7 @@ public void SameTokenNameCloseTokenRequiredNotEnough() { try { ExchangeCapsule exchangeCapsule = dbManager.getExchangeStore() .get(ByteArray.fromLong(exchangeId)); - expected = exchangeCapsule.transaction(tokenId.getBytes(), quant); + expected = exchangeCapsule.transaction(tokenId.getBytes(), quant, useStrictMath); } catch (ItemNotFoundException e) { fail(); } @@ -1555,6 +1556,7 @@ public void SameTokenNameCloseTokenRequiredNotEnough() { @Test public void SameTokenNameOpenTokenRequiredNotEnough() { dbManager.getDynamicPropertiesStore().saveAllowSameTokenName(1); + final boolean useStrictMath = dbManager.getDynamicPropertiesStore().allowStrictMath(); InitExchangeSameTokenNameActive(); long exchangeId = 2; String tokenId = "123"; @@ -1575,7 +1577,7 @@ public void SameTokenNameOpenTokenRequiredNotEnough() { try { ExchangeCapsule exchangeCapsuleV2 = dbManager.getExchangeV2Store() .get(ByteArray.fromLong(exchangeId)); - expected = exchangeCapsuleV2.transaction(tokenId.getBytes(), quant); + expected = exchangeCapsuleV2.transaction(tokenId.getBytes(), quant, useStrictMath); } catch (ItemNotFoundException e) { fail(); } diff --git a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java index db122f90c4f..52f8cdacc00 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java @@ -25,6 +25,7 @@ import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.utils.ProposalUtil; import org.tron.core.utils.ProposalUtil.ProposalType; +import org.tron.protos.Protocol; @Slf4j(topic = "actuator") public class ProposalUtilTest extends BaseTest { @@ -385,6 +386,51 @@ public void validateCheck() { e.getMessage()); } + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_STRICT_MATH.getCode(), 2); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "Bad chain parameter id [ALLOW_STRICT_MATH]", + e.getMessage()); + } + hardForkTime = + ((ForkBlockVersionEnum.VERSION_4_7_7.getHardForkTime() - 1) / maintenanceTimeInterval + 1) + * maintenanceTimeInterval; + forkUtils.getManager().getDynamicPropertiesStore() + .saveLatestBlockHeaderTimestamp(hardForkTime + 1); + forkUtils.getManager().getDynamicPropertiesStore() + .statsByVersion(ForkBlockVersionEnum.VERSION_4_7_7.getValue(), stats); + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_STRICT_MATH.getCode(), 2); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "This value[ALLOW_STRICT_MATH] is only allowed to be 1", + e.getMessage()); + } + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_STRICT_MATH.getCode(), 1); + } catch (ContractValidateException e) { + Assert.fail(e.getMessage()); + } + Protocol.Proposal proposal = Protocol.Proposal.newBuilder().putParameters( + ProposalType.ALLOW_STRICT_MATH.getCode(), 1).build(); + ProposalCapsule proposalCapsule = new ProposalCapsule(proposal); + ProposalService.process(dbManager, proposalCapsule); + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_STRICT_MATH.getCode(), 1); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "[ALLOW_STRICT_MATH] has been valid, no need to propose again", + e.getMessage()); + } + testEnergyAdjustmentProposal(); forkUtils.getManager().getDynamicPropertiesStore() diff --git a/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java index 90f74074a9b..0465cd2e867 100644 --- a/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java @@ -1,7 +1,12 @@ package org.tron.core.capsule; +import org.junit.After; import org.junit.Assert; import org.junit.Test; +import org.mockito.Mockito; +import org.tron.core.config.args.Args; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.vm.config.VMConfig; import org.tron.protos.contract.SmartContractOuterClass; public class ContractStateCapsuleTest { @@ -15,12 +20,12 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertFalse(capsule.catchUpToCycle(1000L, 2_000_000L, 2000L, 10_00L)); + Assert.assertFalse(capsule.catchUpToCycle(1000L, 2_000_000L, 2000L, 10_00L, false)); Assert.assertEquals(1000L, capsule.getUpdateCycle()); Assert.assertEquals(1_000_000L, capsule.getEnergyUsage()); Assert.assertEquals(5000L, capsule.getEnergyFactor()); - Assert.assertTrue(capsule.catchUpToCycle(1010L, 900_000L, 1000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1010L, 900_000L, 1000L, 10_000L, false)); Assert.assertEquals(1010L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(3137L, capsule.getEnergyFactor()); @@ -32,7 +37,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1001L, 2_000_000L, 2000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 2_000_000L, 2000L, 10_000L, false)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(4250L, capsule.getEnergyFactor()); @@ -44,7 +49,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 2000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 2000L, 10_000L, false)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(4250L, capsule.getEnergyFactor()); @@ -56,7 +61,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1001L, 900_000L, 2000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 900_000L, 2000L, 10_000L, false)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(8000L, capsule.getEnergyFactor()); @@ -68,7 +73,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1001L, 900_000L, 5000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 900_000L, 5000L, 10_000L, false)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(10_000L, capsule.getEnergyFactor()); @@ -80,7 +85,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1002L, 900_000L, 5000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1002L, 900_000L, 5000L, 10_000L, false)); Assert.assertEquals(1002L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(7500L, capsule.getEnergyFactor()); @@ -92,7 +97,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1003L, 900_000L, 5000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1003L, 900_000L, 5000L, 10_000L, false)); Assert.assertEquals(1003L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(5312L, capsule.getEnergyFactor()); @@ -104,7 +109,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1004L, 900_000L, 5000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1004L, 900_000L, 5000L, 10_000L, false)); Assert.assertEquals(1004L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(3398L, capsule.getEnergyFactor()); @@ -116,7 +121,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1005L, 900_000L, 5000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1005L, 900_000L, 5000L, 10_000L, true)); Assert.assertEquals(1005L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(1723L, capsule.getEnergyFactor()); @@ -128,7 +133,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1005L, 900_000L, 5000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1005L, 900_000L, 5000L, 10_000L, true)); Assert.assertEquals(1005L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(1723L, capsule.getEnergyFactor()); @@ -140,7 +145,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1006L, 900_000L, 5000L, 10_000L)); + Assert.assertTrue(capsule.catchUpToCycle(1006L, 900_000L, 5000L, 10_000L, true)); Assert.assertEquals(1006L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(258L, capsule.getEnergyFactor()); @@ -151,12 +156,25 @@ public void testCatchUpCycle() { .setEnergyFactor(5000L) .setUpdateCycle(1000L) .build()); - - Assert.assertTrue(capsule.catchUpToCycle(1007L, 900_000L, 5000L, 10_000L)); + Args.getInstance().setAllowStrictMath(1); + VMConfig.initAllowStrictMath(Args.getInstance().getAllowStrictMath()); + DynamicPropertiesStore dps = Mockito.mock(DynamicPropertiesStore.class); + Mockito.when(dps.getCurrentCycleNumber()).thenReturn(1007L); + Mockito.when(dps.getDynamicEnergyThreshold()).thenReturn(900_000L); + Mockito.when(dps.getDynamicEnergyIncreaseFactor()).thenReturn(5000L); + Mockito.when(dps.getDynamicEnergyMaxFactor()).thenReturn(10_000L); + Mockito.when(dps.allowStrictMath()).thenReturn(VMConfig.allowStrictMath()); + Assert.assertTrue(capsule.catchUpToCycle(dps)); Assert.assertEquals(1007L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(0L, capsule.getEnergyFactor()); } + @After + public void reset() { + Args.clearParam(); + + } + } diff --git a/framework/src/test/java/org/tron/core/capsule/ExchangeCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/ExchangeCapsuleTest.java index 791767a952f..5fcd259d738 100644 --- a/framework/src/test/java/org/tron/core/capsule/ExchangeCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/ExchangeCapsuleTest.java @@ -52,8 +52,8 @@ public void testExchange() { long sellQuant = 1_000_000L; byte[] sellID = "abc".getBytes(); - - long result = exchangeCapsule.transaction(sellID, sellQuant); + boolean useStrictMath = chainBaseManager.getDynamicPropertiesStore().allowStrictMath(); + long result = exchangeCapsule.transaction(sellID, sellQuant, useStrictMath); Assert.assertEquals(990_099L, result); sellBalance += sellQuant; Assert.assertEquals(sellBalance, exchangeCapsule.getFirstTokenBalance()); @@ -61,7 +61,7 @@ public void testExchange() { Assert.assertEquals(buyBalance, exchangeCapsule.getSecondTokenBalance()); sellQuant = 9_000_000L; - long result2 = exchangeCapsule.transaction(sellID, sellQuant); + long result2 = exchangeCapsule.transaction(sellID, sellQuant, useStrictMath); Assert.assertEquals(9090909L, result + result2); sellBalance += sellQuant; Assert.assertEquals(sellBalance, exchangeCapsule.getFirstTokenBalance()); diff --git a/framework/src/test/java/org/tron/core/capsule/utils/ExchangeProcessorTest.java b/framework/src/test/java/org/tron/core/capsule/utils/ExchangeProcessorTest.java index 3437eb0ea42..717c62b01a8 100644 --- a/framework/src/test/java/org/tron/core/capsule/utils/ExchangeProcessorTest.java +++ b/framework/src/test/java/org/tron/core/capsule/utils/ExchangeProcessorTest.java @@ -24,7 +24,7 @@ public class ExchangeProcessorTest extends BaseTest { @BeforeClass public static void init() { long supply = 1_000_000_000_000_000_000L; - processor = new ExchangeProcessor(supply); + processor = new ExchangeProcessor(supply, false); } @Test @@ -135,5 +135,15 @@ public void testWithdraw() { } + @Test + public void testStrictMath() { + long supply = 1_000_000_000_000_000_000L; + ExchangeProcessor processor = new ExchangeProcessor(supply, false); + long anotherTokenQuant = processor.exchange(4732214, 2202692725330L, 29218); + processor = new ExchangeProcessor(supply, true); + long result = processor.exchange(4732214, 2202692725330L, 29218); + Assert.assertNotEquals(anotherTokenQuant, result); + } + } From eafada1e2dbc7f7e2103cd2a9d670e66df778efa Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 28 Nov 2024 22:21:24 +0800 Subject: [PATCH 1095/1197] opt(vm): optimize contract (#6101) * opt(vm): get optimized contract when calling is constant --- .../org/tron/core/vm/OperationActions.java | 3 + .../tron/core/vm/PrecompiledContracts.java | 10 +++ .../test/java/org/tron/core/WalletTest.java | 76 +++++++++++++++++++ 3 files changed, 89 insertions(+) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index 5ed6ead075f..e8e5eb86b98 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -989,6 +989,9 @@ public static void exeCall(Program program, DataWord adjustedCallEnergy, PrecompiledContracts.PrecompiledContract contract = PrecompiledContracts.getContractForAddress(codeAddress); if (contract != null) { + if (program.isConstantCall()) { + contract = PrecompiledContracts.getOptimizedContractForConstant(contract); + } program.callToPrecompiledAddress(msg, contract); } else { program.callToAddress(msg); diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index be7b9423f5c..79d08af1aad 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -16,6 +16,8 @@ import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import com.google.protobuf.ByteString; + +import java.lang.reflect.Constructor; import java.math.BigInteger; import java.security.MessageDigest; import java.util.ArrayList; @@ -194,6 +196,14 @@ public class PrecompiledContracts { private static final DataWord blake2FAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000000020009"); + public static PrecompiledContract getOptimizedContractForConstant(PrecompiledContract contract) { + try { + Constructor constructor = contract.getClass().getDeclaredConstructor(); + return (PrecompiledContracts.PrecompiledContract) constructor.newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } public static PrecompiledContract getContractForAddress(DataWord address) { diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 357a2d2ca08..a3258cba322 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -48,6 +48,7 @@ import org.tron.api.GrpcAPI.ProposalList; import org.tron.common.BaseTest; import org.tron.common.crypto.ECKey; +import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Utils; import org.tron.core.actuator.DelegateResourceActuator; @@ -72,6 +73,8 @@ import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.utils.ProposalUtil.ProposalType; import org.tron.core.utils.TransactionUtil; +import org.tron.core.vm.config.ConfigLoader; +import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.program.Program; import org.tron.protos.Protocol; import org.tron.protos.Protocol.Block; @@ -1043,6 +1046,79 @@ public void testGetAssetIssueByName() { chainBaseManager.getDynamicPropertiesStore().saveAllowSameTokenName(0); } + @Test + @SneakyThrows + public void testTriggerConstant() { + boolean preDebug = CommonParameter.getInstance().debug; + CommonParameter.getInstance().debug = true; + ConfigLoader.disable = true; + VMConfig.initAllowTvmTransferTrc10(1); + VMConfig.initAllowTvmConstantinople(1); + VMConfig.initAllowTvmShangHai(1); + + String contractAddress = + Wallet.getAddressPreFixString() + "1A622D84ed49f01045f5f1a5AfcEb9c57e9cC3cc"; + + AccountCapsule accountCap = new AccountCapsule( + ByteString.copyFrom(ByteArray.fromHexString(contractAddress)), + Protocol.AccountType.Normal); + dbManager.getAccountStore().put(accountCap.createDbKey(), accountCap); + + SmartContractOuterClass.SmartContract smartContract = + SmartContractOuterClass.SmartContract.newBuilder().build(); + ContractCapsule contractCap = new ContractCapsule(smartContract); + dbManager.getContractStore().put(ByteArray.fromHexString(contractAddress), contractCap); + + String codeString = "608060405234801561000f575f80fd5b50d3801561001b575f80fd5b50d280156100" + + "27575f80fd5b506004361061004c575f3560e01c80638da5cb5b14610050578063f8a8fd6d1461006e57" + + "5b5f80fd5b61005861008c565b6040516100659190610269565b60405180910390f35b6100766100af565b" + + "6040516100839190610269565b60405180910390f35b5f8054906101000a900473ffffffffffffffffffff" + + "ffffffffffffffffffff1681565b5f60017fbe0166938e2ea2f3f3e0746fdaf46e25c4d8de37ce56d70400" + + "cf284c80d47bbe601b7f10afab946e2be82aa3e4280cf24e2cab294911c3beb06ca9dd7ead06081265d07f" + + "1e1855bcdc3ed57c6f3c3874cde035782427d1236e2d819bd16c75676ecc003a6040515f81526020016040" + + "52604051610133949392919061038f565b6020604051602081039080840390855afa158015610153573d5f" + + "803e3d5ffd5b505050602060405103515f806101000a81548173ffffffffffffffffffffffffffffffffff" + + "ffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550734c95a52686a9b3" + + "ff9cf787b94b8549a988334c5773ffffffffffffffffffffffffffffffffffffffff165f8054906101000a" + + "900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffff" + + "ffff1614610205575f80fd5b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff" + + "16905090565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6102538261" + + "022a565b9050919050565b61026381610249565b82525050565b5f60208201905061027c5f83018461025a" + + "565b92915050565b5f819050919050565b5f819050919050565b5f815f1b9050919050565b5f6102b96102" + + "b46102af84610282565b610294565b61028b565b9050919050565b6102c98161029f565b82525050565b5f" + + "819050919050565b5f60ff82169050919050565b5f819050919050565b5f6103076103026102fd846102cf" + + "565b6102e4565b6102d8565b9050919050565b610317816102ed565b82525050565b5f819050919050565b" + + "5f61034061033b6103368461031d565b610294565b61028b565b9050919050565b61035081610326565b82" + + "525050565b5f819050919050565b5f61037961037461036f84610356565b610294565b61028b565b905091" + + "9050565b6103898161035f565b82525050565b5f6080820190506103a25f8301876102c0565b6103af6020" + + "83018661030e565b6103bc6040830185610347565b6103c96060830184610380565b9594505050505056fe" + + "a26474726f6e58221220e967690f9c06386434cbe4d8dd6dce394130f190d17621cbd4ae4cabdef4ad7964" + + "736f6c63430008140033"; + CodeCapsule codeCap = new CodeCapsule(ByteArray.fromHexString(codeString)); + dbManager.getCodeStore().put(ByteArray.fromHexString(contractAddress), codeCap); + + SmartContractOuterClass.TriggerSmartContract contract = + SmartContractOuterClass.TriggerSmartContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(contractAddress))) + .setContractAddress(ByteString.copyFrom(ByteArray.fromHexString(contractAddress))) + .setData(ByteString.copyFrom(ByteArray.fromHexString("f8a8fd6d"))) + .build(); + TransactionCapsule trxCap = wallet.createTransactionCapsule(contract, + ContractType.TriggerSmartContract); + + GrpcAPI.TransactionExtention.Builder trxExtBuilder = GrpcAPI.TransactionExtention.newBuilder(); + GrpcAPI.Return.Builder retBuilder = GrpcAPI.Return.newBuilder(); + + Transaction tx = wallet.triggerConstantContract(contract, trxCap, trxExtBuilder, retBuilder); + Assert.assertEquals(Transaction.Result.code.SUCESS, tx.getRet(0).getRet()); + + VMConfig.initAllowTvmTransferTrc10(0); + VMConfig.initAllowTvmConstantinople(0); + VMConfig.initAllowTvmShangHai(0); + ConfigLoader.disable = false; + CommonParameter.getInstance().debug = preDebug; + } + @Test @SneakyThrows public void testEstimateEnergy() { From 16026e97400606ec7867b2837842a6589d81c6eb Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 29 Nov 2024 12:14:10 +0800 Subject: [PATCH 1096/1197] update a new version. version name:GreatVoyage-v4.7.6-12-gf4da4fafb1,version code:18386 --- framework/src/main/java/org/tron/program/Version.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 4790ee62bad..ec0e14d786a 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,8 +2,8 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.7.5-64-g4103dfeb63"; - public static final String VERSION_CODE = "18372"; + public static final String VERSION_NAME = "GreatVoyage-v4.7.6-12-gf4da4fafb1"; + public static final String VERSION_CODE = "18386"; private static final String VERSION = "4.7.7"; public static String getVersion() { From 704720187336e69d2b9d3dbf14128fe46532bee8 Mon Sep 17 00:00:00 2001 From: chaozhu Date: Mon, 9 Dec 2024 20:14:59 +0800 Subject: [PATCH 1097/1197] upgrade mockito and optimize tests coverage --- build.gradle | 3 +- .../TransactionLogTriggerCapsuleMockTest.java | 127 ++ .../TransactionLogTriggerCapsuleTest.java | 69 + .../common/runtime/RuntimeImplMockTest.java | 54 + .../java/org/tron/core/WalletMockTest.java | 1330 +++++++++++++++++ .../org/tron/core/db/ManagerMockTest.java | 447 ++++++ .../net/peer/PeerStatusCheckMockTest.java | 28 + .../core/services/http/JsonFormatTest.java | 255 ++++ .../tron/core/services/http/UtilMockTest.java | 243 +++ 9 files changed, 2555 insertions(+), 1 deletion(-) create mode 100644 framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleMockTest.java create mode 100644 framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java create mode 100644 framework/src/test/java/org/tron/core/WalletMockTest.java create mode 100644 framework/src/test/java/org/tron/core/db/ManagerMockTest.java create mode 100644 framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckMockTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/JsonFormatTest.java create mode 100644 framework/src/test/java/org/tron/core/services/http/UtilMockTest.java diff --git a/build.gradle b/build.gradle index b1aba1c0aa9..c74a31a3c8e 100644 --- a/build.gradle +++ b/build.gradle @@ -52,7 +52,8 @@ subprojects { testAnnotationProcessor 'org.projectlombok:lombok:1.18.12' testImplementation group: 'junit', name: 'junit', version: '4.13.2' - testImplementation "org.mockito:mockito-core:2.13.0" + testImplementation "org.mockito:mockito-core:4.11.0" + testImplementation "org.mockito:mockito-inline:4.11.0" } task sourcesJar(type: Jar, dependsOn: classes) { diff --git a/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleMockTest.java b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleMockTest.java new file mode 100644 index 00000000000..65c485b22d9 --- /dev/null +++ b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleMockTest.java @@ -0,0 +1,127 @@ +package org.tron.common.logsfilter; + + +import com.google.protobuf.ByteString; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.logsfilter.capsule.TransactionLogTriggerCapsule; +import org.tron.common.logsfilter.trigger.InternalTransactionPojo; +import org.tron.common.runtime.InternalTransaction; +import org.tron.common.runtime.ProgramResult; +import org.tron.common.runtime.RuntimeImpl; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.ReceiptCapsule; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.db.TransactionTrace; +import org.tron.p2p.utils.ByteArray; +import org.tron.protos.Protocol; +import org.tron.protos.contract.BalanceContract; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + + +public class TransactionLogTriggerCapsuleMockTest { + + private static final String OWNER_ADDRESS = "41548794500882809695a8a687866e76d4271a1abc"; + private static final String RECEIVER_ADDRESS = "41abd4b9367799eaa3197fecb144eb71de1e049150"; + private static final String CONTRACT_ADDRESS = "A0B4750E2CD76E19DCA331BF5D089B71C3C2798548"; + + private TransactionCapsule transactionCapsule; + private BlockCapsule blockCapsule; + + @Before + public void setup() { + blockCapsule = new BlockCapsule(1, + Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), + Sha256Hash.ZERO_HASH.getByteString() + ); + } + + @After + public void clearMocks() { + + } + + + @Test + public void testConstructorWithTransactionTrace() { + BalanceContract.TransferContract.Builder builder2 = + BalanceContract.TransferContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); + transactionCapsule = spy(new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.TransferContract)); + + TransactionTrace trace = mock(TransactionTrace.class); + ReceiptCapsule receiptCapsule = new ReceiptCapsule(Sha256Hash.ZERO_HASH); + RuntimeImpl runtime = mock(RuntimeImpl.class); + List logs = new ArrayList<>(); + logs.add(Protocol.TransactionInfo.Log.newBuilder() + .setAddress(ByteString.copyFrom("address".getBytes())) + .setData(ByteString.copyFrom("data".getBytes())) + .addTopics(ByteString.copyFrom("topic".getBytes())) + .build()); + + Protocol.TransactionInfo.Builder builder = Protocol.TransactionInfo.newBuilder() + .addAllLog(logs); + + ProgramResult programResult = ProgramResult.createEmpty(); + programResult.setHReturn("hreturn".getBytes()); + programResult.setContractAddress(CONTRACT_ADDRESS.getBytes()); + + when(transactionCapsule.getTrxTrace()).thenReturn(trace); + when(trace.getReceipt()).thenReturn(receiptCapsule); + when(trace.getRuntime()).thenReturn(runtime); + when(runtime.getResult()).thenReturn(programResult); + + transactionCapsule.setTrxTrace(trace); + + TransactionLogTriggerCapsule triggerCapsule = new TransactionLogTriggerCapsule( + transactionCapsule, blockCapsule,0,0,0, + builder.build(),0); + + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger()); + } + + @Test + public void testGetInternalTransactionList() throws Exception { + BalanceContract.TransferContract.Builder builder2 = + BalanceContract.TransferContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); + transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.TransferContract); + InternalTransaction internalTransaction = new InternalTransaction( + "parentHash".getBytes(), 10, 0, + "sendAddress".getBytes(), + "transferToAddress".getBytes(), + 100L, "data".getBytes(), "note", + 0L, new HashMap<>() + ); + List internalTransactionList = new ArrayList<>(); + internalTransactionList.add(internalTransaction); + TransactionLogTriggerCapsule triggerCapsule = + new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + + Method privateMethod = TransactionLogTriggerCapsule.class.getDeclaredMethod( + "getInternalTransactionList", List.class); + privateMethod.setAccessible(true); + List pojoList = (List) + privateMethod.invoke(triggerCapsule, internalTransactionList); + + Assert.assertNotNull(pojoList); + } + +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java index 76dd6e99158..a2487ac470b 100644 --- a/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java +++ b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java @@ -13,13 +13,16 @@ import org.tron.core.capsule.TransactionCapsule; import org.tron.p2p.utils.ByteArray; import org.tron.protos.Protocol; +import org.tron.protos.contract.AssetIssueContractOuterClass; import org.tron.protos.contract.BalanceContract; import org.tron.protos.contract.Common; +import org.tron.protos.contract.SmartContractOuterClass; public class TransactionLogTriggerCapsuleTest { private static final String OWNER_ADDRESS = "41548794500882809695a8a687866e76d4271a1abc"; private static final String RECEIVER_ADDRESS = "41abd4b9367799eaa3197fecb144eb71de1e049150"; + private static final String CONTRACT_ADDRESS = "A0B4750E2CD76E19DCA331BF5D089B71C3C2798548"; public TransactionCapsule transactionCapsule; public BlockCapsule blockCapsule; @@ -175,4 +178,70 @@ public void testConstructorWithCancelAllUnfreezeTrxCapsule() { triggerCapsule.getTransactionLogTrigger().getExtMap().get(BANDWIDTH.name()).longValue()); } + + @Test + public void testConstructorWithTransferCapsule() { + BalanceContract.TransferContract.Builder builder2 = + BalanceContract.TransferContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); + transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.TransferContract); + + TransactionLogTriggerCapsule triggerCapsule = + new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getToAddress()); + } + + @Test + public void testConstructorWithTransferAssetCapsule() { + AssetIssueContractOuterClass.TransferAssetContract.Builder builder2 = + AssetIssueContractOuterClass.TransferAssetContract.newBuilder() + .setAssetName(ByteString.copyFrom("AssetName".getBytes())) + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); + transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.TransferAssetContract); + + TransactionLogTriggerCapsule triggerCapsule = + new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getToAddress()); + } + + @Test + public void testConstructorWithTriggerSmartContract() { + SmartContractOuterClass.TriggerSmartContract.Builder builder2 = + SmartContractOuterClass.TriggerSmartContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setContractAddress(ByteString.copyFrom(ByteArray.fromHexString(CONTRACT_ADDRESS))); + transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.TriggerSmartContract); + + TransactionLogTriggerCapsule triggerCapsule = + new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getToAddress()); + } + + @Test + public void testConstructorWithCreateSmartContract() { + SmartContractOuterClass.CreateSmartContract.Builder builder2 = + SmartContractOuterClass.CreateSmartContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); + transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.CreateSmartContract); + + TransactionLogTriggerCapsule triggerCapsule = + new TransactionLogTriggerCapsule(transactionCapsule, blockCapsule); + + Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); + } + + + } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java b/framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java new file mode 100644 index 00000000000..b9381df8460 --- /dev/null +++ b/framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java @@ -0,0 +1,54 @@ +package org.tron.common.runtime; + +import lombok.extern.slf4j.Slf4j; +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; +import org.tron.core.vm.program.Program; + +import java.lang.reflect.Method; + +@Slf4j +public class RuntimeImplMockTest { + @After + public void clearMocks() { + + } + + @Test + public void testSetResultCode1() throws Exception { + RuntimeImpl runtime = new RuntimeImpl(); + ProgramResult programResult = new ProgramResult(); + Method privateMethod = RuntimeImpl.class.getDeclaredMethod( + "setResultCode", ProgramResult.class); + privateMethod.setAccessible(true); + + Program.BadJumpDestinationException badJumpDestinationException + = new Program.BadJumpDestinationException("Operation with pc isn't 'JUMPDEST': PC[%d];", 0); + programResult.setException(badJumpDestinationException); + privateMethod.invoke(runtime, programResult); + + Program.OutOfTimeException outOfTimeException + = new Program.OutOfTimeException("CPU timeout for 0x0a executing"); + programResult.setException(outOfTimeException); + privateMethod.invoke(runtime, programResult); + + Program.PrecompiledContractException precompiledContractException + = new Program.PrecompiledContractException("precompiled contract exception"); + programResult.setException(precompiledContractException); + privateMethod.invoke(runtime, programResult); + + Program.StackTooSmallException stackTooSmallException + = new Program.StackTooSmallException("Expected stack size %d but actual %d;", 100, 10); + programResult.setException(stackTooSmallException); + privateMethod.invoke(runtime, programResult); + + Program.JVMStackOverFlowException jvmStackOverFlowException + = new Program.JVMStackOverFlowException(); + programResult.setException(jvmStackOverFlowException); + privateMethod.invoke(runtime, programResult); + + Assert.assertTrue(true); + } + +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/WalletMockTest.java b/framework/src/test/java/org/tron/core/WalletMockTest.java new file mode 100644 index 00000000000..9dc0323f8fc --- /dev/null +++ b/framework/src/test/java/org/tron/core/WalletMockTest.java @@ -0,0 +1,1330 @@ +package org.tron.core; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockConstruction; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import com.google.protobuf.LazyStringArrayList; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import com.google.protobuf.ProtocolStringList; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.MockedConstruction; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.tron.api.GrpcAPI; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.ByteUtil; +import org.tron.common.utils.Sha256Hash; +import org.tron.common.utils.client.WalletClient; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.ContractCapsule; +import org.tron.core.capsule.ContractStateCapsule; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.db.TransactionStore; +import org.tron.core.exception.AccountResourceInsufficientException; +import org.tron.core.exception.BadItemException; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.exception.DupTransactionException; +import org.tron.core.exception.HeaderNotFound; +import org.tron.core.exception.ItemNotFoundException; +import org.tron.core.exception.TaposException; +import org.tron.core.exception.TooBigTransactionException; +import org.tron.core.exception.TronException; +import org.tron.core.exception.VMIllegalException; +import org.tron.core.exception.ValidateSignatureException; +import org.tron.core.exception.ZksnarkException; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.message.adv.TransactionMessage; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.store.AbiStore; +import org.tron.core.store.AccountStore; +import org.tron.core.store.CodeStore; +import org.tron.core.store.ContractStateStore; +import org.tron.core.store.ContractStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.store.TransactionHistoryStore; +import org.tron.core.store.TransactionRetStore; +import org.tron.core.zen.ShieldedTRC20ParametersBuilder; +import org.tron.core.zen.address.DiversifierT; +import org.tron.core.zen.address.ExpandedSpendingKey; +import org.tron.core.zen.address.KeyIo; +import org.tron.core.zen.address.PaymentAddress; +import org.tron.protos.Protocol; +import org.tron.protos.contract.BalanceContract; +import org.tron.protos.contract.ShieldContract; +import org.tron.protos.contract.SmartContractOuterClass; + + +public class WalletMockTest { + + @Before + public void init() { + CommonParameter.PARAMETER.setMinEffectiveConnection(0); + } + + @After + public void clearMocks() { + Mockito.clearAllCaches(); + } + + @Test + public void testSetTransactionNullException() throws Exception { + Wallet wallet = new Wallet(); + TransactionCapsule transactionCapsuleMock + = mock(TransactionCapsule.class); + + Method privateMethod = Wallet.class.getDeclaredMethod( + "setTransaction", TransactionCapsule.class); + privateMethod.setAccessible(true); + privateMethod.invoke(wallet, transactionCapsuleMock); + + assertTrue(true); + } + + @Test + public void testCreateTransactionCapsuleWithoutValidateWithTimeoutNullException() + throws Exception { + Wallet wallet = new Wallet(); + com.google.protobuf.Message message = + mock(com.google.protobuf.Message.class); + Protocol.Transaction.Contract.ContractType contractType = + mock(Protocol.Transaction.Contract.ContractType.class); + long timeout = 100L; + + try (MockedConstruction mocked = mockConstruction(TransactionCapsule.class, + (mock, context) -> { + when(mock.getInstance()).thenReturn(Protocol.Transaction.newBuilder().build()); + })) { + Method privateMethod = Wallet.class.getDeclaredMethod( + "createTransactionCapsuleWithoutValidateWithTimeout", + com.google.protobuf.Message.class, + Protocol.Transaction.Contract.ContractType.class, + long.class); + privateMethod.setAccessible(true); + privateMethod.invoke(wallet, message, contractType, timeout); + assertTrue(true); + } + } + + @Test + public void testCreateTransactionCapsuleWithoutValidateWithTimeout() + throws Exception { + Wallet wallet = new Wallet(); + com.google.protobuf.Message message = + mock(com.google.protobuf.Message.class); + Protocol.Transaction.Contract.ContractType contractType = + mock(Protocol.Transaction.Contract.ContractType.class); + long timeout = 100L; + BlockCapsule.BlockId blockId = new BlockCapsule.BlockId(); + + try (MockedConstruction mocked = mockConstruction(TransactionCapsule.class, + (mock, context) -> { + when(mock.getInstance()).thenReturn(Protocol.Transaction.newBuilder().build()); + })) { + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + + Field field = wallet.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(wallet, chainBaseManagerMock); + + when(chainBaseManagerMock.getHeadBlockId()).thenReturn(blockId); + + Method privateMethod = Wallet.class.getDeclaredMethod( + "createTransactionCapsuleWithoutValidateWithTimeout", + com.google.protobuf.Message.class, + Protocol.Transaction.Contract.ContractType.class, + long.class); + privateMethod.setAccessible(true); + privateMethod.invoke(wallet, message, contractType, timeout); + + assertTrue(true); + } + } + + + @Test + public void testBroadcastTransactionBlockUnsolidified() throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + + TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); + when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(true); + + Field field = wallet.getClass().getDeclaredField("tronNetDelegate"); + field.setAccessible(true); + field.set(wallet, tronNetDelegateMock); + + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + + assertEquals(GrpcAPI.Return.response_code.BLOCK_UNSOLIDIFIED, ret.getCode()); + } + + @Test + public void testBroadcastTransactionNoConnection() throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + List peerConnections = new ArrayList<>(); + + TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); + when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); + + Field field = wallet.getClass().getDeclaredField("tronNetDelegate"); + field.setAccessible(true); + field.set(wallet, tronNetDelegateMock); + + Field field2 = wallet.getClass().getDeclaredField("minEffectiveConnection"); + field2.setAccessible(true); + field2.set(wallet, 10); + + when(tronNetDelegateMock.getActivePeer()).thenReturn(peerConnections); + + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + + assertEquals(GrpcAPI.Return.response_code.NO_CONNECTION, ret.getCode()); + } + + @Test + public void testBroadcastTransactionConnectionNotEnough() throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + List peerConnections = new ArrayList<>(); + PeerConnection p1 = new PeerConnection(); + PeerConnection p2 = new PeerConnection(); + peerConnections.add(p1); + peerConnections.add(p2); + + TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); + when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); + + Field field = wallet.getClass().getDeclaredField("tronNetDelegate"); + field.setAccessible(true); + field.set(wallet, tronNetDelegateMock); + + Field field2 = wallet.getClass().getDeclaredField("minEffectiveConnection"); + field2.setAccessible(true); + field2.set(wallet, 10); + when(tronNetDelegateMock.getActivePeer()).thenReturn(peerConnections); + + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + + assertEquals(GrpcAPI.Return.response_code.NOT_ENOUGH_EFFECTIVE_CONNECTION, + ret.getCode()); + } + + @Test + public void testBroadcastTransactionTooManyPending() throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + + TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); + Manager managerMock = mock(Manager.class); + when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); + when(managerMock.isTooManyPending()).thenReturn(true); + + Field field = wallet.getClass().getDeclaredField("tronNetDelegate"); + field.setAccessible(true); + field.set(wallet, tronNetDelegateMock); + + Field field2 = wallet.getClass().getDeclaredField("dbManager"); + field2.setAccessible(true); + field2.set(wallet, managerMock); + + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + + assertEquals(GrpcAPI.Return.response_code.SERVER_BUSY, ret.getCode()); + } + + @Test + public void testBroadcastTransactionAlreadyExists() throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + TransactionCapsule trx = new TransactionCapsule(transaction); + trx.setTime(System.currentTimeMillis()); + Sha256Hash txID = trx.getTransactionId(); + + Cache transactionIdCache = CacheBuilder + .newBuilder().maximumSize(10) + .expireAfterWrite(1, TimeUnit.HOURS).recordStats().build(); + transactionIdCache.put(txID, true); + + TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); + Manager managerMock = mock(Manager.class); + when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); + when(managerMock.isTooManyPending()).thenReturn(false); + when(managerMock.getTransactionIdCache()).thenReturn(transactionIdCache); + + Field field = wallet.getClass().getDeclaredField("tronNetDelegate"); + field.setAccessible(true); + field.set(wallet, tronNetDelegateMock); + + Field field2 = wallet.getClass().getDeclaredField("dbManager"); + field2.setAccessible(true); + field2.set(wallet, managerMock); + + Field field3 = wallet.getClass().getDeclaredField("trxCacheEnable"); + field3.setAccessible(true); + field3.set(wallet, true); + + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + + assertEquals(GrpcAPI.Return.response_code.DUP_TRANSACTION_ERROR, + ret.getCode()); + } + + + @Test + public void testBroadcastTransactionNoContract() throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + + TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); + Manager managerMock = mock(Manager.class); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + DynamicPropertiesStore dynamicPropertiesStoreMock + = mock(DynamicPropertiesStore.class); + when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); + when(managerMock.isTooManyPending()).thenReturn(false); + when(chainBaseManagerMock.getDynamicPropertiesStore()) + .thenReturn(dynamicPropertiesStoreMock); + when(dynamicPropertiesStoreMock.supportVM()).thenReturn(false); + + Field field = wallet.getClass().getDeclaredField("tronNetDelegate"); + field.setAccessible(true); + field.set(wallet, tronNetDelegateMock); + + Field field2 = wallet.getClass().getDeclaredField("dbManager"); + field2.setAccessible(true); + field2.set(wallet, managerMock); + + Field field4 = wallet.getClass().getDeclaredField("chainBaseManager"); + field4.setAccessible(true); + field4.set(wallet, chainBaseManagerMock); + + Field field3 = wallet.getClass().getDeclaredField("trxCacheEnable"); + field3.setAccessible(true); + field3.set(wallet, false); + + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + + assertEquals(GrpcAPI.Return.response_code.CONTRACT_VALIDATE_ERROR, + ret.getCode()); + } + + @Test + public void testBroadcastTransactionOtherException() throws Exception { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = getExampleTrans(); + + TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); + Manager managerMock = mock(Manager.class); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + DynamicPropertiesStore dynamicPropertiesStoreMock + = mock(DynamicPropertiesStore.class); + when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); + when(managerMock.isTooManyPending()).thenReturn(false); + when(chainBaseManagerMock.getDynamicPropertiesStore()) + .thenReturn(dynamicPropertiesStoreMock); + when(dynamicPropertiesStoreMock.supportVM()).thenReturn(false); + + Field field = wallet.getClass().getDeclaredField("tronNetDelegate"); + field.setAccessible(true); + field.set(wallet, tronNetDelegateMock); + + Field field2 = wallet.getClass().getDeclaredField("dbManager"); + field2.setAccessible(true); + field2.set(wallet, managerMock); + + Field field4 = wallet.getClass().getDeclaredField("chainBaseManager"); + field4.setAccessible(true); + field4.set(wallet, chainBaseManagerMock); + + Field field3 = wallet.getClass().getDeclaredField("trxCacheEnable"); + field3.setAccessible(true); + field3.set(wallet, false); + + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + + assertEquals(GrpcAPI.Return.response_code.OTHER_ERROR, ret.getCode()); + } + + private Protocol.Transaction getExampleTrans() { + BalanceContract.TransferContract transferContract = + BalanceContract.TransferContract.newBuilder() + .setAmount(10) + .setOwnerAddress(ByteString.copyFromUtf8("aaa")) + .setToAddress(ByteString.copyFromUtf8("bbb")) + .build(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 6666; i++) { + sb.append("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + } + return Protocol.Transaction.newBuilder().setRawData( + Protocol.Transaction.raw.newBuilder() + .setData(ByteString.copyFrom(sb.toString().getBytes(StandardCharsets.UTF_8))) + .addContract( + Protocol.Transaction.Contract.newBuilder() + .setParameter(Any.pack(transferContract)) + .setType(Protocol.Transaction.Contract.ContractType.TransferContract))) + .build(); + } + + private void mockEnv(Wallet wallet, TronException tronException) throws Exception { + TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class); + Manager managerMock = mock(Manager.class); + ChainBaseManager chainBaseManagerMock + = mock(ChainBaseManager.class); + DynamicPropertiesStore dynamicPropertiesStoreMock + = mock(DynamicPropertiesStore.class); + + when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(false); + when(managerMock.isTooManyPending()).thenReturn(false); + when(chainBaseManagerMock.getDynamicPropertiesStore()) + .thenReturn(dynamicPropertiesStoreMock); + when(dynamicPropertiesStoreMock.supportVM()).thenReturn(false); + + doThrow(tronException).when(managerMock).pushTransaction(any()); + + Field field = wallet.getClass().getDeclaredField("tronNetDelegate"); + field.setAccessible(true); + field.set(wallet, tronNetDelegateMock); + + Field field2 = wallet.getClass().getDeclaredField("dbManager"); + field2.setAccessible(true); + field2.set(wallet, managerMock); + + Field field4 = wallet.getClass().getDeclaredField("chainBaseManager"); + field4.setAccessible(true); + field4.set(wallet, chainBaseManagerMock); + + Field field3 = wallet.getClass().getDeclaredField("trxCacheEnable"); + field3.setAccessible(true); + field3.set(wallet, false); + } + + @Test + public void testBroadcastTransactionValidateSignatureException() throws Exception { + try (MockedConstruction mocked = mockConstruction(TransactionMessage.class, + (mock, context) -> { + + })) { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = getExampleTrans(); + mockEnv(wallet, new ValidateSignatureException()); + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + assertEquals(GrpcAPI.Return.response_code.SIGERROR, ret.getCode()); + } + + } + + @Test + public void testBroadcastTransactionValidateContractExeException() throws Exception { + try (MockedConstruction mocked = mockConstruction(TransactionMessage.class, + (mock, context) -> { + + })) { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = getExampleTrans(); + mockEnv(wallet, new ContractExeException()); + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + assertEquals(GrpcAPI.Return.response_code.CONTRACT_EXE_ERROR, ret.getCode()); + } + + } + + @Test + public void testBroadcastTransactionValidateAccountResourceInsufficientException() + throws Exception { + try (MockedConstruction mocked = mockConstruction(TransactionMessage.class, + (mock, context) -> { + + })) { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = getExampleTrans(); + mockEnv(wallet, new AccountResourceInsufficientException("")); + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + assertEquals(GrpcAPI.Return.response_code.BANDWITH_ERROR, ret.getCode()); + } + + } + + @Test + public void testBroadcastTransactionValidateDupTransactionException() + throws Exception { + try (MockedConstruction mocked = mockConstruction(TransactionMessage.class, + (mock, context) -> { + + })) { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = getExampleTrans(); + mockEnv(wallet, new DupTransactionException("")); + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + assertEquals(GrpcAPI.Return.response_code.DUP_TRANSACTION_ERROR, ret.getCode()); + } + + } + + @Test + public void testBroadcastTransactionValidateTaposException() throws Exception { + try (MockedConstruction mocked = mockConstruction(TransactionMessage.class, + (mock, context) -> { + + })) { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = getExampleTrans(); + mockEnv(wallet, new TaposException("")); + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + assertEquals(GrpcAPI.Return.response_code.TAPOS_ERROR, ret.getCode()); + } + + } + + @Test + public void testBroadcastTransactionValidateTooBigTransactionException() + throws Exception { + try (MockedConstruction mocked = mockConstruction(TransactionMessage.class, + (mock, context) -> { + + })) { + Wallet wallet = new Wallet(); + Protocol.Transaction transaction = getExampleTrans(); + mockEnv(wallet, new TooBigTransactionException("")); + + GrpcAPI.Return ret = wallet.broadcastTransaction(transaction); + assertEquals(GrpcAPI.Return.response_code.TOO_BIG_TRANSACTION_ERROR, ret.getCode()); + } + + } + + @Test + public void testGetBlockByNum() throws Exception { + Wallet wallet = new Wallet(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + + Field field = wallet.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(wallet, chainBaseManagerMock); + + doThrow(new ItemNotFoundException()).when(chainBaseManagerMock).getBlockByNum(anyLong()); + + Protocol.Block block = wallet.getBlockByNum(0L); + assertNull(block); + } + + @Test + public void testGetBlockCapsuleByNum() throws Exception { + Wallet wallet = new Wallet(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + Field field = wallet.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(wallet, chainBaseManagerMock); + doThrow(new ItemNotFoundException()).when(chainBaseManagerMock).getBlockByNum(anyLong()); + + BlockCapsule blockCapsule = wallet.getBlockCapsuleByNum(0L); + assertNull(blockCapsule); + } + + @Test + public void testGetTransactionCountByBlockNum() throws Exception { + Wallet wallet = new Wallet(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + Field field = wallet.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(wallet, chainBaseManagerMock); + doThrow(new ItemNotFoundException()).when(chainBaseManagerMock).getBlockByNum(anyLong()); + + long count = wallet.getTransactionCountByBlockNum(0L); + assertEquals(count, 0L); + } + + @Test + public void testGetTransactionById() throws Exception { + Wallet wallet = new Wallet(); + ByteString transactionId = null; + Protocol.Transaction transaction = wallet.getTransactionById(transactionId); + assertNull(transaction); + } + + @Test + public void testGetTransactionById2() throws Exception { + Wallet wallet = new Wallet(); + ByteString transactionId = ByteString.empty(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + TransactionStore transactionStoreMock = mock(TransactionStore.class); + + when(chainBaseManagerMock.getTransactionStore()).thenReturn(transactionStoreMock); + Field field = wallet.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(wallet, chainBaseManagerMock); + doThrow(new BadItemException()).when(transactionStoreMock).get(any()); + + Protocol.Transaction transaction = wallet.getTransactionById(transactionId); + assertNull(transaction); + } + + @Test + public void testGetTransactionById3() throws Exception { + Wallet wallet = new Wallet(); + ByteString transactionId = ByteString.empty(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + TransactionStore transactionStoreMock = mock(TransactionStore.class); + TransactionCapsule transactionCapsuleMock = mock(TransactionCapsule.class); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + + when(chainBaseManagerMock.getTransactionStore()).thenReturn(transactionStoreMock); + Field field = wallet.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(wallet, chainBaseManagerMock); + when(transactionStoreMock.get(any())).thenReturn(transactionCapsuleMock); + when(transactionCapsuleMock.getInstance()).thenReturn(transaction); + + Protocol.Transaction transactionRet = wallet.getTransactionById(transactionId); + assertEquals(transaction, transactionRet); + } + + @Test + public void testGetTransactionCapsuleById() throws Exception { + Wallet wallet = new Wallet(); + ByteString transactionId = null; + TransactionCapsule transactionCapsule = wallet.getTransactionCapsuleById(transactionId); + assertNull(transactionCapsule); + } + + @Test + public void testGetTransactionCapsuleById1() throws Exception { + Wallet wallet = new Wallet(); + ByteString transactionId = ByteString.empty(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + TransactionStore transactionStoreMock = mock(TransactionStore.class); + + when(chainBaseManagerMock.getTransactionStore()).thenReturn(transactionStoreMock); + Field field = wallet.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(wallet, chainBaseManagerMock); + doThrow(new BadItemException()).when(transactionStoreMock).get(any()); + + TransactionCapsule transactionCapsule = wallet.getTransactionCapsuleById(transactionId); + assertNull(transactionCapsule); + } + + @Test + public void testGetTransactionInfoById() throws Exception { + Wallet wallet = new Wallet(); + ByteString transactionId = null; + Protocol.TransactionInfo transactionInfo = wallet.getTransactionInfoById(transactionId); + assertNull(transactionInfo); + } + + @Test + public void testGetTransactionInfoById1() throws Exception { + Wallet wallet = new Wallet(); + ByteString transactionId = ByteString.empty(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + TransactionRetStore transactionRetStoreMock = mock(TransactionRetStore.class); + + when(chainBaseManagerMock.getTransactionRetStore()).thenReturn(transactionRetStoreMock); + Field field = wallet.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(wallet, chainBaseManagerMock); + doThrow(new BadItemException()).when(transactionRetStoreMock).getTransactionInfo(any()); + + Protocol.TransactionInfo transactionInfo = wallet.getTransactionInfoById(transactionId); + assertNull(transactionInfo); + } + + @Test + public void testGetTransactionInfoById2() throws Exception { + Wallet wallet = new Wallet(); + ByteString transactionId = ByteString.empty(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + TransactionRetStore transactionRetStoreMock = mock(TransactionRetStore.class); + TransactionHistoryStore transactionHistoryStoreMock = + mock(TransactionHistoryStore.class); + + when(chainBaseManagerMock.getTransactionRetStore()) + .thenReturn(transactionRetStoreMock); + when(chainBaseManagerMock.getTransactionHistoryStore()) + .thenReturn(transactionHistoryStoreMock); + Field field = wallet.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(wallet, chainBaseManagerMock); + when(transactionRetStoreMock.getTransactionInfo(any())).thenReturn(null); + doThrow(new BadItemException()).when(transactionHistoryStoreMock).get(any()); + + Protocol.TransactionInfo transactionInfo = wallet.getTransactionInfoById(transactionId); + assertNull(transactionInfo); + } + + @Test + public void testGetProposalById() throws Exception { + Wallet wallet = new Wallet(); + ByteString proposalId = null; + Protocol.Proposal proposal = wallet.getProposalById(proposalId); + assertNull(proposal); + } + + @Test + public void testGetMemoFeePrices() throws Exception { + Wallet wallet = new Wallet(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + DynamicPropertiesStore dynamicPropertiesStoreMock = + mock(DynamicPropertiesStore.class); + + when(chainBaseManagerMock.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStoreMock); + doThrow(new IllegalArgumentException("not found MEMO_FEE_HISTORY")) + .when(dynamicPropertiesStoreMock).getMemoFeeHistory(); + + Field field = wallet.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(wallet, chainBaseManagerMock); + + GrpcAPI.PricesResponseMessage responseMessage = wallet.getMemoFeePrices(); + assertNull(responseMessage); + } + + @Test + public void testGetEnergyFeeByTime() throws Exception { + Wallet wallet = new Wallet(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + DynamicPropertiesStore dynamicPropertiesStoreMock = + mock(DynamicPropertiesStore.class); + long now = System.currentTimeMillis(); + + when(chainBaseManagerMock.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStoreMock); + doThrow(new IllegalArgumentException("not found ENERGY_PRICE_HISTORY")) + .when(dynamicPropertiesStoreMock).getEnergyPriceHistory(); + when(dynamicPropertiesStoreMock.getEnergyFee()).thenReturn(10L); + + Field field = wallet.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(wallet, chainBaseManagerMock); + + long energyFee = wallet.getEnergyFee(now); + assertEquals(energyFee, 10L); + } + + @Test + public void testGetEnergyPrices() throws Exception { + Wallet wallet = new Wallet(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + DynamicPropertiesStore dynamicPropertiesStoreMock = + mock(DynamicPropertiesStore.class); + + when(chainBaseManagerMock.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStoreMock); + doThrow(new IllegalArgumentException("not found ENERGY_PRICE_HISTORY")) + .when(dynamicPropertiesStoreMock).getEnergyPriceHistory(); + + Field field = wallet.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(wallet, chainBaseManagerMock); + + GrpcAPI.PricesResponseMessage pricesResponseMessage = wallet.getEnergyPrices(); + assertNull(pricesResponseMessage); + } + + @Test + public void testGetBandwidthPrices() throws Exception { + Wallet wallet = new Wallet(); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + DynamicPropertiesStore dynamicPropertiesStoreMock = + mock(DynamicPropertiesStore.class); + + when(chainBaseManagerMock.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStoreMock); + doThrow(new IllegalArgumentException("not found BANDWIDTH_PRICE_HISTORY")) + .when(dynamicPropertiesStoreMock).getBandwidthPriceHistory(); + + Field field = wallet.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(wallet, chainBaseManagerMock); + + GrpcAPI.PricesResponseMessage pricesResponseMessage = wallet.getBandwidthPrices(); + assertNull(pricesResponseMessage); + } + + @Test + public void testCheckBlockIdentifier() { + Wallet wallet = new Wallet(); + BalanceContract.BlockBalanceTrace.BlockIdentifier blockIdentifier = + BalanceContract.BlockBalanceTrace.BlockIdentifier.newBuilder() + .build(); + blockIdentifier = blockIdentifier.getDefaultInstanceForType(); + + BalanceContract.BlockBalanceTrace.BlockIdentifier blockIdentifier1 = + blockIdentifier; + + assertThrows(IllegalArgumentException.class, () -> { + wallet.checkBlockIdentifier(blockIdentifier1); + }); + + BalanceContract.BlockBalanceTrace.BlockIdentifier blockIdentifier2 = + BalanceContract.BlockBalanceTrace.BlockIdentifier.newBuilder() + .setNumber(-1L) + .build(); + + assertThrows(IllegalArgumentException.class, () -> { + wallet.checkBlockIdentifier(blockIdentifier2); + }); + + BalanceContract.BlockBalanceTrace.BlockIdentifier blockIdentifier3 = + BalanceContract.BlockBalanceTrace.BlockIdentifier.newBuilder() + .setHash(ByteString.copyFrom("".getBytes(StandardCharsets.UTF_8))) + .build(); + + assertThrows(IllegalArgumentException.class, () -> { + wallet.checkBlockIdentifier(blockIdentifier3); + }); + } + + @Test + public void testCheckAccountIdentifier() { + Wallet wallet = new Wallet(); + BalanceContract.AccountIdentifier accountIdentifier = + BalanceContract.AccountIdentifier.newBuilder().build(); + accountIdentifier = accountIdentifier.getDefaultInstanceForType(); + + BalanceContract.AccountIdentifier accountIdentifier2 = accountIdentifier; + + assertThrows(IllegalArgumentException.class, () -> { + wallet.checkAccountIdentifier(accountIdentifier2); + }); + + BalanceContract.AccountIdentifier accountIdentifier1 + = BalanceContract.AccountIdentifier.newBuilder().build(); + + assertThrows(IllegalArgumentException.class, () -> { + wallet.checkAccountIdentifier(accountIdentifier1); + }); + } + + @Test + public void testGetTriggerInputForShieldedTRC20Contract() { + Wallet wallet = new Wallet(); + GrpcAPI.ShieldedTRC20TriggerContractParameters.Builder triggerParam = + GrpcAPI.ShieldedTRC20TriggerContractParameters + .newBuilder(); + GrpcAPI.ShieldedTRC20Parameters shieldedTRC20Parameters = + GrpcAPI.ShieldedTRC20Parameters.newBuilder().build(); + GrpcAPI.BytesMessage bytesMessage = + GrpcAPI.BytesMessage.newBuilder().build(); + + triggerParam.setShieldedTRC20Parameters(shieldedTRC20Parameters); + triggerParam.addSpendAuthoritySignature(bytesMessage); + + CommonParameter commonParameterMock = mock(Args.class); + try (MockedStatic mockedStatic = mockStatic(CommonParameter.class)) { + when(CommonParameter.getInstance()).thenReturn(commonParameterMock); + when(commonParameterMock.isFullNodeAllowShieldedTransactionArgs()).thenReturn(true); + + assertThrows(ZksnarkException.class, () -> { + wallet.getTriggerInputForShieldedTRC20Contract(triggerParam.build()); + }); + } + } + + @Test + public void testGetTriggerInputForShieldedTRC20Contract1() + throws ZksnarkException, ContractValidateException { + Wallet wallet = new Wallet(); + ShieldContract.SpendDescription spendDescription = + ShieldContract.SpendDescription.newBuilder().build(); + GrpcAPI.ShieldedTRC20TriggerContractParameters.Builder triggerParam = + GrpcAPI.ShieldedTRC20TriggerContractParameters + .newBuilder(); + GrpcAPI.ShieldedTRC20Parameters shieldedTRC20Parameters = + GrpcAPI.ShieldedTRC20Parameters.newBuilder() + .addSpendDescription(spendDescription) + .setParameterType("transfer") + .build(); + GrpcAPI.BytesMessage bytesMessage = + GrpcAPI.BytesMessage.newBuilder().build(); + + triggerParam.setShieldedTRC20Parameters(shieldedTRC20Parameters); + triggerParam.addSpendAuthoritySignature(bytesMessage); + + CommonParameter commonParameterMock = mock(Args.class); + try (MockedStatic mockedStatic = mockStatic(CommonParameter.class)) { + when(CommonParameter.getInstance()).thenReturn(commonParameterMock); + when(commonParameterMock.isFullNodeAllowShieldedTransactionArgs()).thenReturn(true); + + GrpcAPI.BytesMessage reponse = + wallet.getTriggerInputForShieldedTRC20Contract(triggerParam.build()); + assertNotNull(reponse); + } + + } + + @Test + public void testGetShieldedContractScalingFactorException() throws Exception { + Wallet walletMock = mock(Wallet.class); + byte[] contractAddress = "".getBytes(StandardCharsets.UTF_8); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + when(walletMock.createTransactionCapsule(any(), any())) + .thenReturn(new TransactionCapsule(transaction)); + + try { + when(walletMock.getShieldedContractScalingFactor(contractAddress)).thenCallRealMethod(); + } catch (Exception e) { + assertNotNull(e); + } + } + + @Test + public void testGetShieldedContractScalingFactorRuntimeException() + throws VMIllegalException, HeaderNotFound, ContractValidateException, ContractExeException { + Wallet walletMock = mock(Wallet.class); + byte[] contractAddress = "".getBytes(StandardCharsets.UTF_8); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + when(walletMock.triggerConstantContract(any(),any(),any(),any())).thenReturn(transaction); + when(walletMock.getShieldedContractScalingFactor(any())).thenCallRealMethod(); + + assertThrows(ContractExeException.class, () -> { + walletMock.getShieldedContractScalingFactor(contractAddress); + }); + } + + @Test + public void testGetShieldedContractScalingFactorSuccess() + throws Exception { + Wallet walletMock = mock(Wallet.class); + byte[] contractAddress = "".getBytes(StandardCharsets.UTF_8); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + when(walletMock.triggerConstantContract(any(),any(),any(),any())) + .thenReturn(transaction); + when(walletMock.createTransactionCapsule(any(), any())) + .thenReturn(new TransactionCapsule(transaction)); + when(walletMock.getShieldedContractScalingFactor(any())).thenCallRealMethod(); + try { + byte[] listBytes = walletMock.getShieldedContractScalingFactor(contractAddress); + assertNotNull(listBytes); + } catch (Exception e) { + assertNull(e); + } + } + + @Test + public void testGetShieldedContractScalingFactorContractExeException() + throws Exception { + Wallet walletMock = mock(Wallet.class); + byte[] contractAddress = "".getBytes(StandardCharsets.UTF_8); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + doThrow(new ContractExeException("")) + .when(walletMock).triggerConstantContract(any(),any(),any(),any()); + when(walletMock.createTransactionCapsule(any(), any())) + .thenReturn(new TransactionCapsule(transaction)); + when(walletMock.getShieldedContractScalingFactor(any())).thenCallRealMethod(); + + assertThrows(ContractExeException.class, () -> { + walletMock.getShieldedContractScalingFactor(contractAddress); + }); + } + + @Test + public void testCheckBigIntegerRange() { + Wallet wallet = new Wallet(); + + assertThrows( + Exception.class, + () -> { + Method privateMethod = Wallet.class.getDeclaredMethod( + "checkBigIntegerRange", BigInteger.class); + privateMethod.setAccessible(true); + privateMethod.invoke(wallet, new BigInteger("-1")); + } + ); + } + + @Test + public void testCheckPublicAmount() throws ContractExeException { + Wallet walletMock = mock(Wallet.class); + + byte[] address = "".getBytes(StandardCharsets.UTF_8); + BigInteger fromAmount = new BigInteger("10"); + BigInteger toAmount = new BigInteger("10"); + doThrow(new ContractExeException("")).when(walletMock).getShieldedContractScalingFactor(any()); + + Throwable thrown = assertThrows(InvocationTargetException.class, () -> { + Method privateMethod = Wallet.class.getDeclaredMethod( + "checkPublicAmount", + byte[].class, BigInteger.class, BigInteger.class); + privateMethod.setAccessible(true); + privateMethod.invoke(walletMock, address, fromAmount, toAmount); + }); + Throwable cause = thrown.getCause(); + assertTrue(cause instanceof ContractExeException); + } + + @Test + public void testCheckPublicAmount1() throws ContractExeException { + Wallet walletMock = mock(Wallet.class); + + byte[] address = "".getBytes(StandardCharsets.UTF_8); + BigInteger fromAmount = new BigInteger("300"); + BigInteger toAmount = new BigInteger("255"); + + byte[] scalingFactorBytes = ByteUtil.bigIntegerToBytes(new BigInteger("-1")); + + when(walletMock.getShieldedContractScalingFactor(any())).thenReturn(scalingFactorBytes); + + Throwable thrown = assertThrows(InvocationTargetException.class, () -> { + Method privateMethod = Wallet.class.getDeclaredMethod( + "checkPublicAmount", + byte[].class, BigInteger.class, BigInteger.class); + privateMethod.setAccessible(true); + privateMethod.invoke(walletMock, address, fromAmount, toAmount); + }); + Throwable cause = thrown.getCause(); + assertTrue(cause instanceof ContractValidateException); + } + + @Test + public void testCheckPublicAmount2() throws ContractExeException { + Wallet walletMock = mock(Wallet.class); + + byte[] address = "".getBytes(StandardCharsets.UTF_8); + BigInteger fromAmount = new BigInteger("300"); + BigInteger toAmount = new BigInteger("255"); + + byte[] scalingFactorBytes = ByteUtil.bigIntegerToBytes(new BigInteger("-1")); + try (MockedStatic mockedStatic = mockStatic(ByteUtil.class)) { + when(ByteUtil.bytesToBigInteger(any())).thenReturn(new BigInteger("-1")); + when(walletMock.getShieldedContractScalingFactor(any())).thenReturn(scalingFactorBytes); + + Throwable thrown = assertThrows(InvocationTargetException.class, () -> { + Method privateMethod = Wallet.class.getDeclaredMethod( + "checkPublicAmount", + byte[].class, BigInteger.class, BigInteger.class); + privateMethod.setAccessible(true); + privateMethod.invoke(walletMock, address, fromAmount, toAmount); + }); + Throwable cause = thrown.getCause(); + assertTrue(cause instanceof ContractValidateException); + } + + } + + @Test + public void testGetShieldedTRC20Nullifier() { + Wallet wallet = new Wallet(); + GrpcAPI.Note note = GrpcAPI.Note.newBuilder() + .setValue(100) + .setPaymentAddress("address") + .setRcm(ByteString.copyFrom("rcm".getBytes(StandardCharsets.UTF_8))) + .setMemo(ByteString.copyFrom("memo".getBytes(StandardCharsets.UTF_8))) + .build(); + long pos = 100L; + byte[] ak = "ak".getBytes(StandardCharsets.UTF_8); + byte[] nk = "nk".getBytes(StandardCharsets.UTF_8); + try (MockedStatic keyIoMockedStatic = mockStatic(KeyIo.class)) { + when(KeyIo.decodePaymentAddress(any())).thenReturn(null); + + Throwable thrown = assertThrows(InvocationTargetException.class, () -> { + Method privateMethod = Wallet.class.getDeclaredMethod( + "getShieldedTRC20Nullifier", + GrpcAPI.Note.class, long.class, byte[].class, + byte[].class); + privateMethod.setAccessible(true); + privateMethod.invoke(wallet, + note, pos, ak, nk); + }); + Throwable cause = thrown.getCause(); + assertTrue(cause instanceof ZksnarkException); + } + } + + @Test + public void testGetShieldedTRC20LogType() { + Wallet wallet = new Wallet(); + Protocol.TransactionInfo.Log log = Protocol.TransactionInfo.Log.newBuilder().build(); + byte[] contractAddress = "contractAddress".getBytes(StandardCharsets.UTF_8); + LazyStringArrayList topicsList = new LazyStringArrayList(); + + Throwable thrown = assertThrows(InvocationTargetException.class, () -> { + Method privateMethod = Wallet.class.getDeclaredMethod( + "getShieldedTRC20LogType", + Protocol.TransactionInfo.Log.class, + byte[].class, + ProtocolStringList.class); + privateMethod.setAccessible(true); + privateMethod.invoke(wallet, + log, + contractAddress, + topicsList); + }); + Throwable cause = thrown.getCause(); + assertTrue(cause instanceof ZksnarkException); + } + + @Test + public void testGetShieldedTRC20LogType1() { + Wallet wallet = new Wallet(); + final String SHIELDED_CONTRACT_ADDRESS_STR = "TGAmX5AqVUoXCf8MoHxbuhQPmhGfWTnEgA"; + byte[] contractAddress = WalletClient.decodeFromBase58Check(SHIELDED_CONTRACT_ADDRESS_STR); + + byte[] addressWithoutPrefix = new byte[20]; + System.arraycopy(contractAddress, 1, addressWithoutPrefix, 0, 20); + Protocol.TransactionInfo.Log log = Protocol.TransactionInfo.Log.newBuilder() + .setAddress(ByteString.copyFrom(addressWithoutPrefix)) + .build(); + + LazyStringArrayList topicsList = new LazyStringArrayList(); + try { + Method privateMethod = Wallet.class.getDeclaredMethod( + "getShieldedTRC20LogType", + Protocol.TransactionInfo.Log.class, + byte[].class, + ProtocolStringList.class); + privateMethod.setAccessible(true); + privateMethod.invoke(wallet, + log, + contractAddress, + topicsList); + } catch (Exception e) { + assertTrue(false); + } + assertTrue(true); + } + + + @Test + public void testGetShieldedTRC20LogType2() { + Wallet wallet = new Wallet(); + final String SHIELDED_CONTRACT_ADDRESS_STR = "TGAmX5AqVUoXCf8MoHxbuhQPmhGfWTnEgA"; + byte[] contractAddress = WalletClient.decodeFromBase58Check(SHIELDED_CONTRACT_ADDRESS_STR); + + byte[] addressWithoutPrefix = new byte[20]; + System.arraycopy(contractAddress, 1, addressWithoutPrefix, 0, 20); + Protocol.TransactionInfo.Log log = Protocol.TransactionInfo.Log.newBuilder() + .setAddress(ByteString.copyFrom(addressWithoutPrefix)) + .addTopics(ByteString.copyFrom("topic".getBytes())) + .build(); + + LazyStringArrayList topicsList = new LazyStringArrayList(); + topicsList.add("topic"); + try { + Method privateMethod = Wallet.class.getDeclaredMethod( + "getShieldedTRC20LogType", + Protocol.TransactionInfo.Log.class, + byte[].class, + ProtocolStringList.class); + privateMethod.setAccessible(true); + privateMethod.invoke(wallet, + log, + contractAddress, + topicsList); + } catch (Exception e) { + assertTrue(false); + } + assertTrue(true); + } + + @Test + public void testBuildShieldedTRC20InputWithAK() throws ZksnarkException { + Wallet wallet = new Wallet(); + ShieldedTRC20ParametersBuilder builder = new ShieldedTRC20ParametersBuilder("transfer"); + GrpcAPI.Note note = GrpcAPI.Note.newBuilder() + .setValue(100) + .setPaymentAddress("address") + .setRcm(ByteString.copyFrom("rcm".getBytes(StandardCharsets.UTF_8))) + .setMemo(ByteString.copyFrom("memo".getBytes(StandardCharsets.UTF_8))) + .build(); + GrpcAPI.SpendNoteTRC20 spendNote = GrpcAPI.SpendNoteTRC20.newBuilder() + .setNote(note) + .setAlpha(ByteString.copyFrom("alpha".getBytes())) + .setRoot(ByteString.copyFrom("root".getBytes())) + .setPath(ByteString.copyFrom("path".getBytes())) + .setPos(0L) + .build(); + byte[] ak = "ak".getBytes(StandardCharsets.UTF_8); + byte[] nk = "nk".getBytes(StandardCharsets.UTF_8); + + try (MockedStatic keyIoMockedStatic = mockStatic(KeyIo.class)) { + when(KeyIo.decodePaymentAddress(any())).thenReturn(null); + + Throwable thrown = assertThrows(InvocationTargetException.class, () -> { + Method privateMethod = Wallet.class.getDeclaredMethod( + "buildShieldedTRC20InputWithAK", + ShieldedTRC20ParametersBuilder.class, + GrpcAPI.SpendNoteTRC20.class, + byte[].class, byte[].class); + privateMethod.setAccessible(true); + privateMethod.invoke(wallet, + builder, + spendNote, + ak, nk); + }); + Throwable cause = thrown.getCause(); + assertTrue(cause instanceof ZksnarkException); + } + + } + + @Test + public void testBuildShieldedTRC20InputWithAK1() throws Exception { + Wallet wallet = new Wallet(); + ShieldedTRC20ParametersBuilder builder = new ShieldedTRC20ParametersBuilder("transfer"); + GrpcAPI.Note note = GrpcAPI.Note.newBuilder() + .setValue(100) + .setPaymentAddress("address") + .setRcm(ByteString.copyFrom("rcm".getBytes(StandardCharsets.UTF_8))) + .setMemo(ByteString.copyFrom("memo".getBytes(StandardCharsets.UTF_8))) + .build(); + GrpcAPI.SpendNoteTRC20 spendNote = GrpcAPI.SpendNoteTRC20.newBuilder() + .setNote(note) + .setAlpha(ByteString.copyFrom("alpha".getBytes())) + .setRoot(ByteString.copyFrom("root".getBytes())) + .setPath(ByteString.copyFrom("path".getBytes())) + .setPos(0L) + .build(); + byte[] ak = "ak".getBytes(StandardCharsets.UTF_8); + byte[] nk = "nk".getBytes(StandardCharsets.UTF_8); + PaymentAddress paymentAddress = mock(PaymentAddress.class); + DiversifierT diversifierT = mock(DiversifierT.class); + + try (MockedStatic keyIoMockedStatic = mockStatic(KeyIo.class)) { + when(KeyIo.decodePaymentAddress(any())).thenReturn(paymentAddress); + when(paymentAddress.getD()).thenReturn(diversifierT); + when(paymentAddress.getPkD()).thenReturn("pkd".getBytes()); + + Method privateMethod = Wallet.class.getDeclaredMethod( + "buildShieldedTRC20InputWithAK", + ShieldedTRC20ParametersBuilder.class, + GrpcAPI.SpendNoteTRC20.class, + byte[].class, byte[].class); + privateMethod.setAccessible(true); + privateMethod.invoke(wallet, + builder, + spendNote, + ak, nk); + assertTrue(true); + } + + } + + @Test + public void testBuildShieldedTRC20Input() throws Exception { + Wallet wallet = new Wallet(); + ShieldedTRC20ParametersBuilder builder = new ShieldedTRC20ParametersBuilder("transfer"); + GrpcAPI.Note note = GrpcAPI.Note.newBuilder() + .setValue(100) + .setPaymentAddress("address") + .setRcm(ByteString.copyFrom("rcm".getBytes(StandardCharsets.UTF_8))) + .setMemo(ByteString.copyFrom("memo".getBytes(StandardCharsets.UTF_8))) + .build(); + GrpcAPI.SpendNoteTRC20 spendNote = GrpcAPI.SpendNoteTRC20.newBuilder() + .setNote(note) + .setAlpha(ByteString.copyFrom("alpha".getBytes())) + .setRoot(ByteString.copyFrom("root".getBytes())) + .setPath(ByteString.copyFrom("path".getBytes())) + .setPos(0L) + .build(); + ExpandedSpendingKey expandedSpendingKey = mock(ExpandedSpendingKey.class); + PaymentAddress paymentAddress = mock(PaymentAddress.class); + DiversifierT diversifierT = mock(DiversifierT.class); + + try (MockedStatic keyIoMockedStatic = mockStatic(KeyIo.class)) { + when(KeyIo.decodePaymentAddress(any())).thenReturn(paymentAddress); + when(paymentAddress.getD()).thenReturn(diversifierT); + when(paymentAddress.getPkD()).thenReturn("pkd".getBytes()); + Method privateMethod = Wallet.class.getDeclaredMethod( + "buildShieldedTRC20Input", + ShieldedTRC20ParametersBuilder.class, + GrpcAPI.SpendNoteTRC20.class, + ExpandedSpendingKey.class); + privateMethod.setAccessible(true); + privateMethod.invoke(wallet, + builder, + spendNote, + expandedSpendingKey); + } + } + + @Test + public void testGetContractInfo() throws Exception { + Wallet wallet = new Wallet(); + GrpcAPI.BytesMessage bytesMessage = GrpcAPI.BytesMessage.newBuilder() + .setValue(ByteString.copyFrom("test".getBytes())) + .build(); + + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + AccountStore accountStore = mock(AccountStore.class); + Field field = wallet.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(wallet, chainBaseManagerMock); + when(chainBaseManagerMock.getAccountStore()).thenReturn(accountStore); + when(accountStore.get(any())).thenReturn(null); + + SmartContractOuterClass.SmartContractDataWrapper smartContractDataWrapper = + wallet.getContractInfo(bytesMessage); + assertNull(smartContractDataWrapper); + } + + @Test + public void testGetContractInfo1() throws Exception { + Wallet wallet = new Wallet(); + GrpcAPI.BytesMessage bytesMessage = GrpcAPI.BytesMessage.newBuilder() + .setValue(ByteString.copyFrom("test".getBytes())) + .build(); + + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + AccountStore accountStore = mock(AccountStore.class); + ContractStore contractStore = mock(ContractStore.class); + AbiStore abiStore = mock(AbiStore.class); + CodeStore codeStore = mock(CodeStore.class); + ContractStateStore contractStateStore = mock(ContractStateStore.class); + DynamicPropertiesStore dynamicPropertiesStore = mock(DynamicPropertiesStore.class); + + AccountCapsule accountCapsule = mock(AccountCapsule.class); + ContractCapsule contractCapsule = mock(ContractCapsule.class); + ContractStateCapsule contractStateCapsule = new ContractStateCapsule(10L); + + Field field = wallet.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(wallet, chainBaseManagerMock); + when(chainBaseManagerMock.getAccountStore()).thenReturn(accountStore); + when(chainBaseManagerMock.getContractStore()).thenReturn(contractStore); + when(chainBaseManagerMock.getAbiStore()).thenReturn(abiStore); + when(chainBaseManagerMock.getCodeStore()).thenReturn(codeStore); + when(chainBaseManagerMock.getContractStateStore()).thenReturn(contractStateStore); + when(chainBaseManagerMock.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStore); + + when(accountStore.get(any())).thenReturn(accountCapsule); + when(contractStore.get(any())).thenReturn(contractCapsule); + when(contractCapsule.generateWrapper()) + .thenReturn(SmartContractOuterClass.SmartContractDataWrapper.newBuilder().build()); + when(abiStore.get(any())).thenReturn(null); + when(codeStore.get(any())).thenReturn(null); + when(contractStateStore.get(any())).thenReturn(contractStateCapsule); + when(dynamicPropertiesStore.getCurrentCycleNumber()).thenReturn(100L); + + SmartContractOuterClass.SmartContractDataWrapper smartContractDataWrapper = + wallet.getContractInfo(bytesMessage); + assertNotNull(smartContractDataWrapper); + } +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/db/ManagerMockTest.java b/framework/src/test/java/org/tron/core/db/ManagerMockTest.java new file mode 100644 index 00000000000..ff6e0dce3d8 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/ManagerMockTest.java @@ -0,0 +1,447 @@ +package org.tron.core.db; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockConstruction; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; + +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.junit.After; +import org.junit.Test; +import org.mockito.MockedConstruction; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import org.quartz.CronExpression; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.runtime.ProgramResult; +import org.tron.common.runtime.RuntimeImpl; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.ChainBaseManager; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.capsule.TransactionInfoCapsule; +import org.tron.core.capsule.utils.TransactionUtil; +import org.tron.core.config.args.Args; +import org.tron.core.exception.ContractSizeNotEqualToOneException; +import org.tron.core.exception.DupTransactionException; +import org.tron.core.exception.ItemNotFoundException; +import org.tron.core.exception.ReceiptCheckErrException; +import org.tron.core.exception.TaposException; +import org.tron.core.exception.TooBigTransactionException; +import org.tron.core.exception.TooBigTransactionResultException; +import org.tron.core.exception.TransactionExpirationException; +import org.tron.core.exception.ValidateSignatureException; +import org.tron.core.store.AccountStore; +import org.tron.core.store.BalanceTraceStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.Protocol; +import org.tron.protos.contract.BalanceContract; + +@Slf4j +public class ManagerMockTest { + @After + public void clearMocks() { + Mockito.framework().clearInlineMocks(); + } + + @Test + public void processTransactionCostTimeMoreThan100() throws Exception { + TransactionTrace traceMock = mock(TransactionTrace.class); + BandwidthProcessor bandwidthProcessorMock = mock(BandwidthProcessor.class); + try (MockedConstruction mockedConstruction2 = mockConstruction(TransactionTrace.class,(mock, context) -> { + when(mock).thenReturn(traceMock); + }); + MockedConstruction mockedConstruction3 = mockConstruction(BandwidthProcessor.class,(mock, context) -> { + when(mock).thenReturn(bandwidthProcessorMock); + }); + MockedStatic mockedStatic = mockStatic(TransactionUtil.class)) { + Manager dbManager = mock(Manager.class); + BalanceContract.TransferContract transferContract = + BalanceContract.TransferContract.newBuilder() + .setAmount(10) + .setOwnerAddress(ByteString.copyFromUtf8("aaa")) + .setToAddress(ByteString.copyFromUtf8("bbb")) + .build(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 6666; i++) { + sb.append("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + } + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().setRawData( + Protocol.Transaction.raw.newBuilder() + .setData(ByteString.copyFrom(sb.toString().getBytes(StandardCharsets.UTF_8))) + .addContract( + Protocol.Transaction.Contract.newBuilder() + .setParameter(Any.pack(transferContract)) + .setType(Protocol.Transaction.Contract.ContractType.TransferContract))) + .build(); + TransactionCapsule trxCap = new TransactionCapsule(transaction); + ProgramResult result = new ProgramResult(); + result.setResultCode(Protocol.Transaction.Result.contractResult.SUCCESS); + + Sha256Hash transactionId = trxCap.getTransactionId(); + TransactionCapsule trxCapMock = mock(TransactionCapsule.class); + + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + BalanceTraceStore balanceTraceStoreMock = mock(BalanceTraceStore.class); + TransactionStore transactionStoreMock = mock(TransactionStore.class); + TransactionInfoCapsule transactionInfoCapsuleMock = mock(TransactionInfoCapsule.class); + Protocol.TransactionInfo transactionInfo = Protocol.TransactionInfo.newBuilder().build(); + + Field field = dbManager.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(dbManager, chainBaseManagerMock); + + BlockCapsule blockCapMock = Mockito.mock(BlockCapsule.class); + + when(TransactionUtil + .buildTransactionInfoInstance(trxCapMock, blockCapMock, traceMock)) + .thenReturn(transactionInfoCapsuleMock); + + // this make cost > 100 cond is true + when(blockCapMock.isMerkleRootEmpty()).thenAnswer(new Answer() { + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + Thread.sleep(100); + return true; + } + }); + + when(chainBaseManagerMock.getBalanceTraceStore()).thenReturn(balanceTraceStoreMock); + when(chainBaseManagerMock.getAccountStore()).thenReturn(mock(AccountStore.class)); + when(chainBaseManagerMock.getDynamicPropertiesStore()) + .thenReturn(mock(DynamicPropertiesStore.class)); + when(chainBaseManagerMock.getTransactionStore()).thenReturn(transactionStoreMock); + when(trxCapMock.getTransactionId()).thenReturn(transactionId); + when(traceMock.getRuntimeResult()).thenReturn(result); + when(transactionInfoCapsuleMock.getId()).thenReturn(transactionId.getBytes()); + when(transactionInfoCapsuleMock.getInstance()).thenReturn(transactionInfo); + when(trxCapMock.getInstance()).thenReturn(trxCap.getInstance()); + when(trxCapMock.validatePubSignature( + Mockito.any(AccountStore.class), + Mockito.any(DynamicPropertiesStore.class))).thenReturn(true); + when(trxCapMock.validateSignature( + Mockito.any(AccountStore.class), + Mockito.any(DynamicPropertiesStore.class))).thenReturn(true); + + doNothing().when(dbManager).validateTapos(trxCapMock); + doNothing().when(dbManager).validateCommon(trxCapMock); + doNothing().when(dbManager).validateDup(trxCapMock); + + + doNothing().when(transactionStoreMock).put(transactionId.getBytes(), trxCapMock); + doNothing().when(bandwidthProcessorMock).consume(trxCapMock, traceMock); + doNothing().when(dbManager).consumeBandwidth(trxCapMock, traceMock); + doNothing().when(balanceTraceStoreMock).initCurrentTransactionBalanceTrace(trxCapMock); + doNothing().when(balanceTraceStoreMock).updateCurrentTransactionStatus(anyString()); + doNothing().when(balanceTraceStoreMock).resetCurrentTransactionTrace(); + + + assertNotNull( + when(dbManager.processTransaction(trxCapMock, blockCapMock)).thenCallRealMethod() + ); + } + } + + private void initMockEnv(Manager dbManager, long headNum, long headTime, + long exitHeight, long exitCount, String blockTime) + throws Exception { + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + Args argsMock = mock(Args.class); + + when(Args.getInstance()).thenReturn(argsMock); + + when(chainBaseManagerMock.getHeadBlockNum()).thenReturn(headNum); + when(chainBaseManagerMock.getHeadBlockTimeStamp()).thenReturn(headTime); + + when(argsMock.getShutdownBlockHeight()).thenReturn(exitHeight); + when(argsMock.getShutdownBlockCount()).thenReturn(exitCount); + when(argsMock.isP2pDisable()).thenReturn(false); + when(argsMock.getShutdownBlockTime()) + .thenReturn(new CronExpression(blockTime)); //"0 0 12 * * ?" + + Field field = dbManager.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(dbManager, chainBaseManagerMock); + } + + @Test + public void testInitAutoStop() throws Exception { + Manager dbManager = spy(new Manager()); + try (MockedStatic methodTestMockedStatic + = mockStatic(CommonParameter.class)) { + initMockEnv(dbManager, 100L, 12345L, + 10L, 0L, "0 0 12 * * ?"); + + assertThrows( + "shutDownBlockHeight 10 is less than headNum 100", + Exception.class, + () -> { + Method privateMethod = Manager.class.getDeclaredMethod( + "initAutoStop"); + privateMethod.setAccessible(true); + privateMethod.invoke(dbManager); + } + ); + } + + } + + @Test + public void testInitAutoStop1() throws Exception { + Manager dbManager = spy(new Manager()); + try (MockedStatic methodTestMockedStatic + = mockStatic(CommonParameter.class)) { + initMockEnv(dbManager,10L, 12345L, + 100L, 0L, "0 0 12 * * ?"); + + assertThrows( + "shutDownBlockCount 0 is less than 1", + Exception.class, + () -> { + Method privateMethod = Manager.class.getDeclaredMethod( + "initAutoStop"); + privateMethod.setAccessible(true); + privateMethod.invoke(dbManager); + } + ); + } + } + + @Test + public void testInitAutoStop2() throws Exception { + Manager dbManager = spy(new Manager()); + try (MockedStatic methodTestMockedStatic + = mockStatic(CommonParameter.class)) { + initMockEnv(dbManager,10L, 99726143865000L, + 100L, 1L, "0 0 12 * * ?"); + + assertThrows( + "shutDownBlockTime 0 0 12 * * ? is illegal", + Exception.class, + () -> { + Method privateMethod = Manager.class.getDeclaredMethod( + "initAutoStop"); + privateMethod.setAccessible(true); + privateMethod.invoke(dbManager); + } + ); + } + + } + + @Test + public void testInitAutoStop3() throws Exception { + Manager dbManager = spy(new Manager()); + try (MockedStatic methodTestMockedStatic + = mockStatic(CommonParameter.class)) { + initMockEnv(dbManager,10L, 12345L, + 100L, 1L, "0 0 12 * * ?"); + + assertThrows( + "shutDownBlockHeight 100 and shutDownBlockCount 1 set both", + Exception.class, + () -> { + Method privateMethod = Manager.class.getDeclaredMethod( + "initAutoStop"); + privateMethod.setAccessible(true); + privateMethod.invoke(dbManager); + } + ); + } + + } + + @Test + public void testInitAutoStop4() throws Exception { + Manager dbManager = spy(new Manager()); + try (MockedStatic methodTestMockedStatic + = mockStatic(CommonParameter.class)) { + initMockEnv(dbManager, 10L, 12345L, + 100L, -1L, "0 0 12 * * ?"); + + assertThrows( + "shutDownBlockHeight 100 and shutDownBlockTime 0 0 12 * * ? set both", + Exception.class, + () -> { + Method privateMethod = Manager.class.getDeclaredMethod( + "initAutoStop"); + privateMethod.setAccessible(true); + privateMethod.invoke(dbManager); + } + ); + } + + } + + @Test + public void testInitAutoStop5() throws Exception { + Manager dbManager = spy(new Manager()); + try (MockedStatic methodTestMockedStatic + = mockStatic(CommonParameter.class)) { + initMockEnv(dbManager,10L, 12345L, + 0L, 1L, "0 0 12 * * ?"); + + assertThrows( + "shutDownBlockCount 1 and shutDownBlockTime 0 0 12 * * ? set both", + Exception.class, + () -> { + Method privateMethod = Manager.class.getDeclaredMethod( + "initAutoStop"); + privateMethod.setAccessible(true); + privateMethod.invoke(dbManager); + } + ); + } + + } + + @Test + public void testProcessTransaction() throws Exception { + Manager dbManager = spy(new Manager()); + TransactionCapsule transactionCapsuleMock = null; + BlockCapsule blockCapsuleMock = mock(BlockCapsule.class); + + Method privateMethod = Manager.class.getDeclaredMethod( + "processTransaction", + TransactionCapsule.class, BlockCapsule.class); + privateMethod.setAccessible(true); + privateMethod.invoke(dbManager, transactionCapsuleMock, blockCapsuleMock); + + assertTrue(true); + } + + @Test + public void testProcessTransaction1() { + Manager dbManager = spy(new Manager()); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().setRawData( + Protocol.Transaction.raw.newBuilder() + .setData(ByteString.copyFrom("sb.toString()".getBytes(StandardCharsets.UTF_8)))) + .build(); + TransactionCapsule trxCap = new TransactionCapsule(transaction); + + BlockCapsule blockCapsuleMock = mock(BlockCapsule.class); + + Throwable thrown = assertThrows(InvocationTargetException.class, () -> { + Method privateMethod = Manager.class.getDeclaredMethod( + "processTransaction", + TransactionCapsule.class, BlockCapsule.class); + privateMethod.setAccessible(true); + privateMethod.invoke(dbManager, trxCap, blockCapsuleMock); + }); + Throwable cause = thrown.getCause(); + assertTrue(cause instanceof ContractSizeNotEqualToOneException); + } + + @SneakyThrows + @Test + public void testRePush() { + Manager dbManager = spy(new Manager()); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + TransactionCapsule trx = new TransactionCapsule(transaction); + TransactionStore transactionStoreMock = mock(TransactionStore.class); + + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + Field field = dbManager.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(dbManager, chainBaseManagerMock); + when(chainBaseManagerMock.getTransactionStore()).thenReturn(transactionStoreMock); + when(transactionStoreMock.has(any())).thenReturn(true); + + dbManager.rePush(trx); + assertTrue(true); + } + + @SneakyThrows + @Test + public void testRePush1() { + Manager dbManager = spy(new Manager()); + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().build(); + TransactionCapsule trx = new TransactionCapsule(transaction); + TransactionStore transactionStoreMock = mock(TransactionStore.class); + + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + + Field field = dbManager.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(dbManager, chainBaseManagerMock); + + when(chainBaseManagerMock.getTransactionStore()).thenReturn(transactionStoreMock); + when(transactionStoreMock.has(any())).thenReturn(false); + + doThrow(new ValidateSignatureException()).when(dbManager).pushTransaction(any()); + dbManager.rePush(trx); + + doThrow(new DupTransactionException()).when(dbManager).pushTransaction(any()); + dbManager.rePush(trx); + + doThrow(new TaposException()).when(dbManager).pushTransaction(any()); + dbManager.rePush(trx); + + doThrow(new TooBigTransactionException()).when(dbManager).pushTransaction(any()); + dbManager.rePush(trx); + + doThrow(new TransactionExpirationException()).when(dbManager).pushTransaction(any()); + dbManager.rePush(trx); + + doThrow(new ReceiptCheckErrException()).when(dbManager).pushTransaction(any()); + dbManager.rePush(trx); + + doThrow(new TooBigTransactionResultException()).when(dbManager).pushTransaction(any()); + dbManager.rePush(trx); + assertTrue(true); + } + + @Test + public void testPostSolidityFilter() throws Exception { + Manager dbManager = spy(new Manager()); + + Method privateMethod = Manager.class.getDeclaredMethod( + "postSolidityFilter", long.class, long.class); + privateMethod.setAccessible(true); + privateMethod.invoke(dbManager, 100L, 10L); + assertTrue(true); + } + + @Test + public void testReOrgLogsFilter() throws Exception { + Manager dbManager = spy(new Manager()); + CommonParameter commonParameterMock = mock(Args.class); + mockStatic(CommonParameter.class); + ChainBaseManager chainBaseManagerMock = mock(ChainBaseManager.class); + + when(CommonParameter.getInstance()).thenReturn(commonParameterMock); + when(commonParameterMock.isJsonRpcHttpFullNodeEnable()).thenReturn(true); + when(chainBaseManagerMock.getDynamicPropertiesStore()) + .thenReturn(mock(DynamicPropertiesStore.class)); + Field field = dbManager.getClass().getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(dbManager, chainBaseManagerMock); + doThrow(new ItemNotFoundException()).when(chainBaseManagerMock).getBlockById(any()); + + Method privateMethod = Manager.class.getDeclaredMethod("reOrgLogsFilter"); + privateMethod.setAccessible(true); + privateMethod.invoke(dbManager); + assertTrue(true); + } + +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckMockTest.java b/framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckMockTest.java new file mode 100644 index 00000000000..5e8c69fdd6a --- /dev/null +++ b/framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckMockTest.java @@ -0,0 +1,28 @@ +package org.tron.core.net.peer; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.spy; + +import org.junit.After; +import org.junit.Test; +import org.mockito.Mockito; + +public class PeerStatusCheckMockTest { + @After + public void clearMocks() { + Mockito.framework().clearInlineMocks(); + } + + @Test + public void testInitException() throws InterruptedException { + PeerStatusCheck peerStatusCheck = spy(new PeerStatusCheck()); + doThrow(new RuntimeException("test exception")).when(peerStatusCheck).statusCheck(); + peerStatusCheck.init(); + + // the initialDelay of scheduleWithFixedDelay is 5s + Thread.sleep(5000L); + assertTrue(true); + } + +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/services/http/JsonFormatTest.java b/framework/src/test/java/org/tron/core/services/http/JsonFormatTest.java new file mode 100644 index 00000000000..a8525b0f526 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/JsonFormatTest.java @@ -0,0 +1,255 @@ +package org.tron.core.services.http; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import com.google.protobuf.ByteString; +import com.google.protobuf.UnknownFieldSet; + +import java.io.CharArrayReader; +import java.io.IOException; +import java.io.StringWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.junit.After; +import org.junit.Test; +import org.mockito.Mockito; +import org.tron.protos.Protocol; + +public class JsonFormatTest { + @After + public void clearMocks() { + Mockito.framework().clearInlineMocks(); + } + + @Test + public void testPrintErrorMsg() { + Exception ex = new Exception("test"); + String out = JsonFormat.printErrorMsg(ex); + assertEquals("{\"Error\":\"test\"}", out); + } + + @Test + public void testPrintWithHelloMessage() throws IOException { + Protocol.HelloMessage message = Protocol.HelloMessage.newBuilder() + .setAddress(ByteString.copyFrom("address".getBytes())) + .build(); + StringWriter output = new StringWriter(); + + JsonFormat.print(message, output, true); + assertNotNull(output.toString()); + } + + private UnknownFieldSet createValidUnknownFieldSet() { + UnknownFieldSet unknownFieldSet2 = UnknownFieldSet.newBuilder().build(); + UnknownFieldSet.Field unknownField1 = UnknownFieldSet.Field.newBuilder() + .addFixed32(123) + .addFixed64(12345L) + .addGroup(unknownFieldSet2) + .addLengthDelimited(ByteString.copyFrom("length".getBytes())) + .addVarint(12345678L) + .build(); + + return UnknownFieldSet.newBuilder() + .addField(1, unknownField1) + .build(); + } + + @Test + public void testPrintWithFields() throws IOException { + UnknownFieldSet unknownFieldSet = createValidUnknownFieldSet(); + StringWriter output = new StringWriter(); + JsonFormat.print(unknownFieldSet, output, true); + assertNotNull(output.toString()); + } + + @Test + public void testPrintToString() { + UnknownFieldSet unknownFieldSet = createValidUnknownFieldSet(); + String output = JsonFormat.printToString(unknownFieldSet, true); + assertNotNull(output); + } + + @Test + public void testUnsignedToString() throws Exception { + Method privateMethod = JsonFormat.class.getDeclaredMethod("unsignedToString", int.class); + privateMethod.setAccessible(true); + String out3 = (String)privateMethod.invoke(null, 100); + assertEquals("100", out3); + String out4 = (String)privateMethod.invoke(null, -100); + assertNotNull(out4); + } + + @Test + public void testToStringBuilderWithNonReadableInput() throws Exception { + String inputString = "Hello, World!"; + Readable input = new CharArrayReader(inputString.toCharArray()); + + Method privateMethod = JsonFormat.class.getDeclaredMethod("toStringBuilder", Readable.class); + privateMethod.setAccessible(true); + + StringBuilder out = (StringBuilder)privateMethod.invoke(null, input); + assertEquals(inputString, out.toString()); + } + + + @Test + public void testUnicodeEscaped() throws Exception { + Method privateMethod = JsonFormat.class.getDeclaredMethod("unicodeEscaped", char.class); + privateMethod.setAccessible(true); + + + char input1 = 0x09; + String out = (String)privateMethod.invoke(null, input1); + assertNotNull(out); + + char input2 = 0x99; + String out2 = (String)privateMethod.invoke(null, input2); + assertNotNull(out2); + + char input3 = 0x999; + String out3 = (String)privateMethod.invoke(null, input3); + assertNotNull(out3); + + char input4 = 0x1001; + String out4 = (String)privateMethod.invoke(null, input4); + assertNotNull(out4); + } + + @Test + public void testEscapeText() throws Exception { + Method privateMethod = JsonFormat.class.getDeclaredMethod("escapeText", String.class); + privateMethod.setAccessible(true); + + String input1 = "\b\f\n\r\t\\\"\\b\\f\\n\\r\\t\\\\\"test123"; + String out = (String)privateMethod.invoke(null, input1); + assertNotNull(out); + } + + @Test + public void testAppendEscapedUnicode() throws Exception { + Method privateMethod = JsonFormat.class.getDeclaredMethod("appendEscapedUnicode", + StringBuilder.class, char.class); + privateMethod.setAccessible(true); + + char input1 = 0x09; + StringBuilder out1 = new StringBuilder(); + + privateMethod.invoke(null, out1, input1); + assertNotNull(out1); + + char input2 = 0x99; + StringBuilder out2 = new StringBuilder(); + privateMethod.invoke(null, out2, input2); + assertNotNull(out2); + + char input3 = 0x999; + StringBuilder out3 = new StringBuilder(); + privateMethod.invoke(null, out3, input3); + assertNotNull(out3); + + char input4 = 0x1001; + StringBuilder out4 = new StringBuilder(); + privateMethod.invoke(null, out4, input4); + assertNotNull(out4); + } + + @Test + public void testUnescapeText() throws Exception { + Method privateMethod = JsonFormat.class.getDeclaredMethod("unescapeText", String.class); + privateMethod.setAccessible(true); + + String input = "\\u1234\\b\\f\\n\\r\\t\\\\\"test123";; + String out = (String)privateMethod.invoke(null, input); + assertNotNull(out); + } + + @Test + public void testDigitValue() throws Exception { + Method privateMethod = JsonFormat.class.getDeclaredMethod("digitValue", char.class); + privateMethod.setAccessible(true); + + char input = '1'; + int out = (int)privateMethod.invoke(null, input); + assertEquals(1, out); + + char input1 = 'b'; + int out1 = (int)privateMethod.invoke(null, input1); + assertEquals(11, out1); + + char input2 = 'B'; + int out2 = (int)privateMethod.invoke(null, input2); + assertEquals(11, out2); + } + + @Test + public void testParseUInt64() throws Exception { + Method privateMethod = JsonFormat.class.getDeclaredMethod("parseUInt64", String.class); + privateMethod.setAccessible(true); + + String input = "12312312312"; + long out = (long)privateMethod.invoke(null, input); + assertEquals(12312312312L, out); + + String input1 = "0x10"; + long out1 = (long)privateMethod.invoke(null, input1); + assertEquals(16L, out1); + + String input2 = "010"; + long out2 = (long)privateMethod.invoke(null, input2); + assertEquals(8L, out2); + + String input3 = "-12312312312"; + Throwable thrown = assertThrows(InvocationTargetException.class, () -> { + privateMethod.invoke(null, input3); + }); + Throwable cause = thrown.getCause(); + assertTrue(cause instanceof NumberFormatException); + } + + @Test + public void testParseInteger() throws Exception { + Method privateMethod = JsonFormat.class.getDeclaredMethod("parseInteger", + String.class, boolean.class, boolean.class); + privateMethod.setAccessible(true); + + String input1 = "92233720368547758070"; + Throwable thrown = assertThrows(InvocationTargetException.class, () -> { + privateMethod.invoke(null,input1, true, true); + }); + Throwable cause = thrown.getCause(); + assertTrue(cause instanceof NumberFormatException); + + String input5 = "92233720368547758070"; + thrown = assertThrows(InvocationTargetException.class, () -> { + privateMethod.invoke(null,input5, false, true); + }); + cause = thrown.getCause(); + assertTrue(cause instanceof NumberFormatException); + + String input2 = "-92233720368547758"; + thrown = assertThrows(InvocationTargetException.class, () -> { + privateMethod.invoke(null,input2, false, true); + }); + cause = thrown.getCause(); + assertTrue(cause instanceof NumberFormatException); + + String input3 = "92233720368547758070"; + thrown = assertThrows(InvocationTargetException.class, () -> { + privateMethod.invoke(null,input3, false, false); + }); + cause = thrown.getCause(); + assertTrue(cause instanceof NumberFormatException); + + String input4 = "-92233720368547758070"; + thrown = assertThrows(InvocationTargetException.class, () -> { + privateMethod.invoke(null,input4, true, false); + }); + cause = thrown.getCause(); + assertTrue(cause instanceof NumberFormatException); + } + +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/services/http/UtilMockTest.java b/framework/src/test/java/org/tron/core/services/http/UtilMockTest.java new file mode 100644 index 00000000000..221c5a7a165 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/UtilMockTest.java @@ -0,0 +1,243 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import com.google.protobuf.ByteString; + +import java.security.InvalidParameterException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; +import org.tron.api.GrpcAPI; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.p2p.utils.ByteArray; +import org.tron.protos.Protocol; +import org.tron.protos.contract.BalanceContract; +import org.tron.protos.contract.SmartContractOuterClass; + +public class UtilMockTest { + @After + public void clearMocks() { + Mockito.framework().clearInlineMocks(); + } + + + @Test + public void testPrintTransactionFee() { + Protocol.ResourceReceipt resourceReceipt = Protocol.ResourceReceipt.newBuilder() + .build(); + Protocol.TransactionInfo result = Protocol.TransactionInfo.newBuilder() + .setReceipt(resourceReceipt) + .build(); + String transactionFee = JsonFormat.printToString(result, true); + String out = Util.printTransactionFee(transactionFee); + Assert.assertNotNull(out); + } + + @Test + public void testPrintBlockList() { + BlockCapsule blockCapsule1 = new BlockCapsule(1, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), Sha256Hash.ZERO_HASH.getByteString()); + BlockCapsule blockCapsule2 = new BlockCapsule(1, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), Sha256Hash.ZERO_HASH.getByteString()); + GrpcAPI.BlockList list = GrpcAPI.BlockList.newBuilder() + .addBlock(blockCapsule1.getInstance()) + .addBlock(blockCapsule2.getInstance()) + .build(); + String out = Util.printBlockList(list, true); + Assert.assertNotNull(out); + } + + @Test + public void testPrintTransactionList() { + TransactionCapsule transactionCapsule = getTransactionCapsuleExample(); + GrpcAPI.TransactionList list = GrpcAPI.TransactionList.newBuilder() + .addTransaction(transactionCapsule.getInstance()) + .build(); + String out = Util.printTransactionList(list, true); + Assert.assertNotNull(out); + } + + private TransactionCapsule getTransactionCapsuleExample() { + final String OWNER_ADDRESS = "41548794500882809695a8a687866e76d4271a1abc"; + final String RECEIVER_ADDRESS = "41abd4b9367799eaa3197fecb144eb71de1e049150"; + BalanceContract.TransferContract.Builder builder2 = + BalanceContract.TransferContract.newBuilder() + .setOwnerAddress( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))) + .setToAddress( + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); + return new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.TransferContract); + } + + @Test + public void testPrintTransactionSignWeight() { + TransactionCapsule transactionCapsule = getTransactionCapsuleExample(); + GrpcAPI.TransactionExtention transactionExtention = + GrpcAPI.TransactionExtention.newBuilder() + .setTransaction(transactionCapsule.getInstance()) + .build(); + GrpcAPI.TransactionSignWeight txSignWeight = + GrpcAPI.TransactionSignWeight.newBuilder() + .setTransaction(transactionExtention) + .build(); + + String out = Util.printTransactionSignWeight(txSignWeight, true); + Assert.assertNotNull(out); + } + + @Test + public void testPrintTransactionApprovedList() { + TransactionCapsule transactionCapsule = getTransactionCapsuleExample(); + GrpcAPI.TransactionExtention transactionExtention = + GrpcAPI.TransactionExtention.newBuilder() + .setTransaction(transactionCapsule.getInstance()) + .build(); + GrpcAPI.TransactionApprovedList transactionApprovedList = + GrpcAPI.TransactionApprovedList.newBuilder() + .setTransaction(transactionExtention) + .build(); + String out = Util.printTransactionApprovedList( + transactionApprovedList, true); + Assert.assertNotNull(out); + } + + @Test + public void testGenerateContractAddress() { + final String OWNER_ADDRESS = "41548794500882809695a8a687866e76d4271a1abc"; + TransactionCapsule transactionCapsule = getTransactionCapsuleExample(); + byte[] out = Util.generateContractAddress( + transactionCapsule.getInstance(), OWNER_ADDRESS.getBytes()); + Assert.assertNotNull(out); + } + + @Test + public void testPrintTransactionToJSON() { + final String OWNER_ADDRESS = "41548794500882809695a8a687866e76d4271a1abc"; + SmartContractOuterClass.CreateSmartContract.Builder builder2 = + SmartContractOuterClass.CreateSmartContract.newBuilder() + .setOwnerAddress( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); + TransactionCapsule transactionCapsule = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.CreateSmartContract); + + JSONObject out = Util.printTransactionToJSON( + transactionCapsule.getInstance(), true); + Assert.assertNotNull(out); + } + + @Test + public void testGetContractType() { + String out = Util.getContractType("{\"contractType\":\"123\"}\n"); + Assert.assertEquals("123", out); + } + + @Test + public void testGetHexAddress() { + String out = Util.getHexAddress("TBxSocpujP6UGKV5ydXNVTDQz7fAgdmoaB"); + Assert.assertNotNull(out); + + Assert.assertNull(Util.getHexAddress(null)); + } + + @Test + public void testSetTransactionPermissionId() { + TransactionCapsule transactionCapsule = getTransactionCapsuleExample(); + Protocol.Transaction out = Util.setTransactionPermissionId( + 123, transactionCapsule.getInstance()); + Assert.assertNotNull(out); + } + + @Test + public void testSetTransactionExtraData() { + TransactionCapsule transactionCapsule = getTransactionCapsuleExample(); + JSONObject jsonObject = JSONObject.parseObject("{\"extra_data\":\"test\"}"); + Protocol.Transaction out = Util.setTransactionExtraData(jsonObject, + transactionCapsule.getInstance(), true); + Assert.assertNotNull(out); + } + + @Test + public void testConvertOutput() { + Protocol.Account account = Protocol.Account.newBuilder().build(); + String out = Util.convertOutput(account); + Assert.assertNotNull(out); + + account = Protocol.Account.newBuilder() + .setAssetIssuedID(ByteString.copyFrom("asset_issued_ID".getBytes())) + .build(); + out = Util.convertOutput(account); + Assert.assertNotNull(out); + } + + @Test + public void testConvertLogAddressToTronAddress() { + List logs = new ArrayList<>(); + logs.add(Protocol.TransactionInfo.Log.newBuilder() + .setAddress(ByteString.copyFrom("address".getBytes())) + .setData(ByteString.copyFrom("data".getBytes())) + .addTopics(ByteString.copyFrom("topic".getBytes())) + .build()); + + Protocol.TransactionInfo.Builder builder = Protocol.TransactionInfo.newBuilder() + .addAllLog(logs); + List logList = + Util.convertLogAddressToTronAddress(builder.build()); + Assert.assertNotNull(logList.size() > 0); + } + + @Test + public void testValidateParameter() { + String contract = "{\"address\":\"owner_address\"}"; + Assert.assertThrows( + InvalidParameterException.class, + () -> { + Util.validateParameter(contract); + } + ); + String contract1 = + "{\"owner_address\":\"owner_address\"," + + " \"contract_address1\":\"contract_address\", \"data1\":\"data\"}"; + Assert.assertThrows( + InvalidParameterException.class, + () -> { + Util.validateParameter(contract1); + } + ); + String contract2 = + "{\"owner_address\":\"owner_address\", " + + "\"function_selector\":\"function_selector\", \"data\":\"data\"}"; + Assert.assertThrows( + InvalidParameterException.class, + () -> { + Util.validateParameter(contract2); + } + ); + } + + @Test + public void testGetJsonString() { + String str = ""; + String ret = Util.getJsonString(str); + Assert.assertTrue(StringUtils.isEmpty(ret)); + + String str1 = "{\"owner_address\":\"owner_address\"}"; + String ret1 = Util.getJsonString(str1); + Assert.assertTrue(str1.equals(ret1)); + + String str2 = "owner_address=owner_address&contract_address=contract_address"; + String ret2 = Util.getJsonString(str2); + String expect = + "{\"owner_address\":\"owner_address\"," + + "\"contract_address\":\"contract_address\"}"; + Assert.assertEquals(expect, ret2); + } + +} \ No newline at end of file From 5c53c3b31f7eae4e2cc0291cb73445642f4cbe73 Mon Sep 17 00:00:00 2001 From: InventiveCoder Date: Tue, 10 Dec 2024 14:18:48 +0800 Subject: [PATCH 1098/1197] chore: fix some typos in comment Signed-off-by: InventiveCoder --- .../src/main/java/org/tron/common/crypto/cryptohash/Digest.java | 2 +- crypto/src/main/java/org/tron/common/crypto/sm2/SM2Signer.java | 2 +- .../test/java/org/tron/core/zksnark/ShieldedReceiveTest.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crypto/src/main/java/org/tron/common/crypto/cryptohash/Digest.java b/crypto/src/main/java/org/tron/common/crypto/cryptohash/Digest.java index cb1ca99944f..62362d1d62d 100644 --- a/crypto/src/main/java/org/tron/common/crypto/cryptohash/Digest.java +++ b/crypto/src/main/java/org/tron/common/crypto/cryptohash/Digest.java @@ -19,7 +19,7 @@ package org.tron.common.crypto.cryptohash; /** - * Copyright (c) 2007-2010 Projet RNRT SAPHIR + * Copyright (c) 2007-2010 Project RNRT SAPHIR * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and * associated documentation files (the "Software"), to deal in the Software without restriction, diff --git a/crypto/src/main/java/org/tron/common/crypto/sm2/SM2Signer.java b/crypto/src/main/java/org/tron/common/crypto/sm2/SM2Signer.java index 01a4fc0aef6..817b909de58 100644 --- a/crypto/src/main/java/org/tron/common/crypto/sm2/SM2Signer.java +++ b/crypto/src/main/java/org/tron/common/crypto/sm2/SM2Signer.java @@ -185,7 +185,7 @@ public boolean verifySignature(byte[] message, BigInteger r, BigInteger s, } /** - * verfify the hash signature + * verify the hash signature */ public boolean verifyHashSignature(byte[] hash, BigInteger r, BigInteger s) { BigInteger n = ecParams.getN(); diff --git a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java index 157a7ba732f..171011fc8d3 100755 --- a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java @@ -317,7 +317,7 @@ public void testBroadcastBeforeAllowZksnark() } /* - * generate spendproof, dataToBeSigned, outputproof example dynamicly according to the params file + * generate spendproof, dataToBeSigned, outputproof example dynamically according to the params file */ public String[] generateSpendAndOutputParams() throws ZksnarkException, BadItemException { librustzcashInitZksnarkParams(); From e08511b68f47e0a6c53b166b44670ac17d327f02 Mon Sep 17 00:00:00 2001 From: chaozhu Date: Thu, 12 Dec 2024 23:51:34 +0800 Subject: [PATCH 1099/1197] fix check style error --- .../TransactionLogTriggerCapsuleMockTest.java | 7 ++++--- .../tron/common/runtime/RuntimeImplMockTest.java | 4 +++- .../src/test/java/org/tron/core/WalletMockTest.java | 2 +- .../test/java/org/tron/core/db/ManagerMockTest.java | 13 +++++++------ 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleMockTest.java b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleMockTest.java index 65c485b22d9..975d41a9051 100644 --- a/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleMockTest.java +++ b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleMockTest.java @@ -1,5 +1,8 @@ package org.tron.common.logsfilter; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; import com.google.protobuf.ByteString; @@ -26,9 +29,7 @@ import org.tron.protos.Protocol; import org.tron.protos.contract.BalanceContract; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; + public class TransactionLogTriggerCapsuleMockTest { diff --git a/framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java b/framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java index b9381df8460..ee126049ad0 100644 --- a/framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java +++ b/framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java @@ -1,12 +1,14 @@ package org.tron.common.runtime; +import java.lang.reflect.Method; + import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; import org.junit.Test; import org.tron.core.vm.program.Program; -import java.lang.reflect.Method; + @Slf4j public class RuntimeImplMockTest { diff --git a/framework/src/test/java/org/tron/core/WalletMockTest.java b/framework/src/test/java/org/tron/core/WalletMockTest.java index 9dc0323f8fc..a52da0a95c9 100644 --- a/framework/src/test/java/org/tron/core/WalletMockTest.java +++ b/framework/src/test/java/org/tron/core/WalletMockTest.java @@ -18,6 +18,7 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; import com.google.protobuf.LazyStringArrayList; +import com.google.protobuf.ProtocolStringList; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -28,7 +29,6 @@ import java.util.List; import java.util.concurrent.TimeUnit; -import com.google.protobuf.ProtocolStringList; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/framework/src/test/java/org/tron/core/db/ManagerMockTest.java b/framework/src/test/java/org/tron/core/db/ManagerMockTest.java index ff6e0dce3d8..f0e850faf7f 100644 --- a/framework/src/test/java/org/tron/core/db/ManagerMockTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerMockTest.java @@ -68,12 +68,13 @@ public void clearMocks() { public void processTransactionCostTimeMoreThan100() throws Exception { TransactionTrace traceMock = mock(TransactionTrace.class); BandwidthProcessor bandwidthProcessorMock = mock(BandwidthProcessor.class); - try (MockedConstruction mockedConstruction2 = mockConstruction(TransactionTrace.class,(mock, context) -> { - when(mock).thenReturn(traceMock); - }); - MockedConstruction mockedConstruction3 = mockConstruction(BandwidthProcessor.class,(mock, context) -> { - when(mock).thenReturn(bandwidthProcessorMock); - }); + try (MockedConstruction mockedConstruction2 + = mockConstruction(TransactionTrace.class,(mock, context) -> { + when(mock).thenReturn(traceMock); }); + MockedConstruction mockedConstruction3 + = mockConstruction(BandwidthProcessor.class,(mock, context) -> { + when(mock).thenReturn(bandwidthProcessorMock); + }); MockedStatic mockedStatic = mockStatic(TransactionUtil.class)) { Manager dbManager = mock(Manager.class); BalanceContract.TransferContract transferContract = From b70078c9c6301c4571e87e4ccdaf00ef68cdd2e9 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 24 Dec 2024 14:46:57 +0800 Subject: [PATCH 1100/1197] feat(net): reduce the interval between batch request blocks to 100ms --- framework/src/main/java/org/tron/core/config/args/Args.java | 2 +- .../main/java/org/tron/core/net/service/sync/SyncService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 8853971a5f8..a04e144d2be 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -953,7 +953,7 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.fastForwardNodes = getInetSocketAddress(config, Constant.NODE_FAST_FORWARD, true); PARAMETER.maxFastForwardNum = config.hasPath(Constant.NODE_MAX_FAST_FORWARD_NUM) ? config - .getInt(Constant.NODE_MAX_FAST_FORWARD_NUM) : 3; + .getInt(Constant.NODE_MAX_FAST_FORWARD_NUM) : 4; if (PARAMETER.maxFastForwardNum > MAX_ACTIVE_WITNESS_NUM) { PARAMETER.maxFastForwardNum = MAX_ACTIVE_WITNESS_NUM; } diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 8c673977962..0bce4b8baa5 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -90,7 +90,7 @@ public void init() { } catch (Exception e) { logger.error("Handle sync block error", e); } - }, 10, 1, TimeUnit.SECONDS); + }, 10000, 100, TimeUnit.MILLISECONDS); } public void close() { From c36118fc66e0ec3165c4d3d336224d4e395477ea Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 24 Dec 2024 15:38:01 +0800 Subject: [PATCH 1101/1197] fix(net): add check for the number of contracts in the transaction --- .../TransactionsMsgHandler.java | 4 ++++ .../TransactionsMsgHandlerTest.java | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java index 0c58fe08cd6..6ccd12016b1 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java @@ -98,6 +98,10 @@ private void check(PeerConnection peer, TransactionsMessage msg) throws P2pExcep "trx: " + msg.getMessageId() + " without request."); } peer.getAdvInvRequest().remove(item); + if (trx.getRawData().getContractCount() < 1) { + throw new P2pException(TypeEnum.BAD_TRX, + "tx " + item.getHash() + " contract size should be greater than 0"); + } } } diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java index e1865543443..54e5f78d85a 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java @@ -102,6 +102,29 @@ public void testProcessMessage() { transactionList1.add(trx1); transactionsMsgHandler.processMessage(peer, new TransactionsMessage(transactionList1)); Assert.assertNull(advInvRequest.get(item1)); + + // test 0 contract + Protocol.Transaction trx2 = Protocol.Transaction.newBuilder().setRawData( + Protocol.Transaction.raw.newBuilder().setTimestamp(transactionTimestamp) + .setRefBlockNum(1).build()) + .build(); + List transactionList2 = new ArrayList<>(); + transactionList2.add(trx2); + try { + transactionsMsgHandler.processMessage(peer, new TransactionsMessage(transactionList2)); + } catch (Exception ep) { + Assert.assertTrue(true); + } + Map advInvRequest2 = new ConcurrentHashMap<>(); + Item item2 = new Item(new TransactionMessage(trx2).getMessageId(), + Protocol.Inventory.InventoryType.TRX); + advInvRequest2.put(item2, 0L); + Mockito.when(peer.getAdvInvRequest()).thenReturn(advInvRequest2); + try { + transactionsMsgHandler.processMessage(peer, new TransactionsMessage(transactionList2)); + } catch (Exception ep) { + Assert.assertTrue(true); + } } catch (Exception e) { Assert.fail(); } finally { From 42e79c279b7932344c48a60fdfdcda2cb1f4ba2c Mon Sep 17 00:00:00 2001 From: chaozhu Date: Thu, 26 Dec 2024 15:47:42 +0800 Subject: [PATCH 1102/1197] jacoco.toolVersion optimize --- build.gradle | 3 +++ chainbase/build.gradle | 5 ----- framework/build.gradle | 3 --- plugins/build.gradle | 3 --- 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/build.gradle b/build.gradle index c74a31a3c8e..aefae7956ec 100644 --- a/build.gradle +++ b/build.gradle @@ -11,6 +11,9 @@ subprojects { targetCompatibility = JavaVersion.VERSION_1_8 [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' + jacoco { + toolVersion = "0.8.12" // see https://www.jacoco.org/jacoco/trunk/doc/changes.html + } buildscript { repositories { diff --git a/chainbase/build.gradle b/chainbase/build.gradle index 79a246014d7..0fb98629856 100644 --- a/chainbase/build.gradle +++ b/chainbase/build.gradle @@ -2,7 +2,6 @@ description = "chainbase – a decentralized database for blockchain." // Dependency versions // --------------------------------------- -def jacocoVersion = "0.8.0" def jansiVersion = "1.16" // -------------------------------------- @@ -41,10 +40,6 @@ test { } } -jacoco { - toolVersion = jacocoVersion // See http://www.eclemma.org/jacoco/. -} - jacocoTestReport { reports { xml.enabled = true diff --git a/framework/build.gradle b/framework/build.gradle index ec113c93cb1..10477fb71b3 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -15,9 +15,6 @@ def versions = [ checkstyle: '8.7', ] -jacoco { - toolVersion = "0.8.1" -} configurations { diff --git a/plugins/build.gradle b/plugins/build.gradle index 7028686f3d0..03ac6d84150 100644 --- a/plugins/build.gradle +++ b/plugins/build.gradle @@ -5,9 +5,6 @@ plugins { apply plugin: 'application' apply plugin: 'checkstyle' -jacoco { - toolVersion = "0.8.8" -} def versions = [ checkstyle: '8.7', ] From 7f0b1848d152852029eca6cc4817b7193687beec Mon Sep 17 00:00:00 2001 From: Asuka Date: Tue, 7 Jan 2025 11:32:49 +0800 Subject: [PATCH 1103/1197] impr(test): revert changes and optimize those tests in a safer way --- .../vm/BatchValidateSignContractTest.java | 4 ++-- .../tron/common/runtime/vm/Create2Test.java | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BatchValidateSignContractTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BatchValidateSignContractTest.java index 3fa52aa70c0..fc60d8c0648 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BatchValidateSignContractTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BatchValidateSignContractTest.java @@ -79,7 +79,6 @@ public void staticCallTest() { @Test public void correctionTest() { - contract.setConstantCall(true); List signatures = new ArrayList<>(); List addresses = new ArrayList<>(); byte[] hash = Hash.sha3(longData); @@ -128,7 +127,8 @@ Pair validateMultiSign(byte[] hash, List signatures, List parameters = Arrays.asList("0x" + Hex.toHexString(hash), signatures, addresses); byte[] input = Hex.decode(AbiUtil.parseParameters(METHOD_SIGN, parameters)); contract.getEnergyForData(input); - contract.setVmShouldEndInUs(System.nanoTime() / 1000 + 500 * 1000); + long maxExecutionTime = 2000; // ms + contract.setVmShouldEndInUs(System.nanoTime() / 1000 + maxExecutionTime * 1000); Pair ret = contract.execute(input); logger.info("BytesArray:{},HexString:{}", Arrays.toString(ret.getValue()), Hex.toHexString(ret.getValue())); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java index a63abd97930..b1ed4f7af70 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java @@ -161,15 +161,15 @@ public void testCreate2() long salt = 100L; String hexInput = AbiUtil.parseMethod(methodSign, Arrays.asList(testCode, salt)); - TVMTestResult result = null; - for (int i = 1; i < 3; i++) { - result = TvmTestUtils - .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), - factoryAddress, Hex.decode(hexInput), 0, fee, manager, null); - if (result.getRuntime().getRuntimeError() == null) { - break; - } - } + long preTime = manager.getDynamicPropertiesStore().getMaxCpuTimeOfOneTx(); + // set max cpu time to 500 + manager.getDynamicPropertiesStore().saveMaxCpuTimeOfOneTx(500L); + TVMTestResult result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), + factoryAddress, Hex.decode(hexInput), 0, fee, manager, null); + // restore max cpu time + manager.getDynamicPropertiesStore().saveMaxCpuTimeOfOneTx(preTime); + Assert.assertNull(result.getRuntime().getRuntimeError()); byte[] returnValue = result.getRuntime().getResult().getHReturn(); From 659db96b6e5d3d2b019a44d831ae857b3b3f1ab4 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 8 Jan 2025 16:46:59 +0800 Subject: [PATCH 1104/1197] move DesensitizedConverter to package common --- .../org/tron/common/log/layout}/DesensitizedConverter.java | 6 +++--- .../java/org/tron/core/net/service/relay/RelayService.java | 2 +- framework/src/main/resources/logback.xml | 2 +- .../tron/common/logsfilter/DesensitizedConverterTest.java | 1 + 4 files changed, 6 insertions(+), 5 deletions(-) rename {framework/src/main/java/org/tron/common/logsfilter => common/src/main/java/org/tron/common/log/layout}/DesensitizedConverter.java (88%) diff --git a/framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java b/common/src/main/java/org/tron/common/log/layout/DesensitizedConverter.java similarity index 88% rename from framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java rename to common/src/main/java/org/tron/common/log/layout/DesensitizedConverter.java index 1cbe5101f40..2777d6ba283 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/DesensitizedConverter.java +++ b/common/src/main/java/org/tron/common/log/layout/DesensitizedConverter.java @@ -1,4 +1,4 @@ -package org.tron.common.logsfilter; +package org.tron.common.log.layout; import ch.qos.logback.classic.pattern.ClassicConverter; import ch.qos.logback.classic.spi.ILoggingEvent; @@ -7,7 +7,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import lombok.extern.slf4j.Slf4j; -import org.tron.core.config.args.Args; +import org.tron.common.parameter.CommonParameter; @Slf4j(topic = "Parser") public class DesensitizedConverter extends ClassicConverter { @@ -44,6 +44,6 @@ private String desensitization(String content) { @Override public String convert(ILoggingEvent iLoggingEvent) { String source = iLoggingEvent.getFormattedMessage(); - return Args.getInstance().isFastForward() ? desensitization(source) : source; + return CommonParameter.getInstance().isFastForward() ? desensitization(source) : source; } } diff --git a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java index 90463f8ab46..d4f60b13e1c 100644 --- a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java @@ -18,7 +18,7 @@ import org.tron.common.crypto.SignInterface; import org.tron.common.crypto.SignUtils; import org.tron.common.es.ExecutorServiceManager; -import org.tron.common.logsfilter.DesensitizedConverter; +import org.tron.common.log.layout.DesensitizedConverter; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ByteUtil; diff --git a/framework/src/main/resources/logback.xml b/framework/src/main/resources/logback.xml index 7d761bda931..03d870e92e0 100644 --- a/framework/src/main/resources/logback.xml +++ b/framework/src/main/resources/logback.xml @@ -5,7 +5,7 @@ + converterClass="org.tron.common.log.layout.DesensitizedConverter"/> diff --git a/framework/src/test/java/org/tron/common/logsfilter/DesensitizedConverterTest.java b/framework/src/test/java/org/tron/common/logsfilter/DesensitizedConverterTest.java index c584d5adf06..abdc0eccdfd 100644 --- a/framework/src/test/java/org/tron/common/logsfilter/DesensitizedConverterTest.java +++ b/framework/src/test/java/org/tron/common/logsfilter/DesensitizedConverterTest.java @@ -4,6 +4,7 @@ import java.lang.reflect.Method; import org.junit.Assert; import org.junit.Test; +import org.tron.common.log.layout.DesensitizedConverter; public class DesensitizedConverterTest { From 021a5c1c2f4dd17542c434ca6e849d5c16dbf026 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Thu, 18 Jul 2024 15:58:44 +0800 Subject: [PATCH 1105/1197] feat(consensus): add consensus logic optimization proposal --- .../org/tron/core/utils/ProposalUtil.java | 20 ++++++++-- .../core/store/DynamicPropertiesStore.java | 15 +++++++ .../common/parameter/CommonParameter.java | 4 ++ .../src/main/java/org/tron/core/Constant.java | 3 ++ .../java/org/tron/core/config/Parameter.java | 5 ++- .../org/tron/consensus/dpos/DposService.java | 5 +-- .../src/main/java/org/tron/core/Wallet.java | 5 +++ .../java/org/tron/core/config/args/Args.java | 5 +++ .../tron/core/consensus/ProposalService.java | 5 +++ .../core/actuator/utils/ProposalUtilTest.java | 39 +++++++++++++++++++ .../org/tron/core/config/args/ArgsTest.java | 1 + .../core/services/ProposalServiceTest.java | 18 +++++++++ 12 files changed, 116 insertions(+), 9 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index fb4d6f76228..fc60316eb40 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -782,15 +782,26 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, case ALLOW_STRICT_MATH: { if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7_7)) { throw new ContractValidateException( - "Bad chain parameter id [ALLOW_STRICT_MATH]"); + "Bad chain parameter id [ALLOW_STRICT_MATH]"); } if (dynamicPropertiesStore.allowStrictMath()) { throw new ContractValidateException( - "[ALLOW_STRICT_MATH] has been valid, no need to propose again"); + "[ALLOW_STRICT_MATH] has been valid, no need to propose again"); } if (value != 1) { throw new ContractValidateException( - "This value[ALLOW_STRICT_MATH] is only allowed to be 1"); + "This value[ALLOW_STRICT_MATH] is only allowed to be 1"); + } + break; + } + case CONSENSUS_LOGIC_OPTIMIZATION: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_8_0)) { + throw new ContractValidateException( + "Bad chain parameter id [CONSENSUS_LOGIC_OPTIMIZATION]"); + } + if (value != 1) { + throw new ContractValidateException( + "This value[CONSENSUS_LOGIC_OPTIMIZATION] is only allowed to be 1"); } break; } @@ -873,7 +884,8 @@ public enum ProposalType { // current value, value range ALLOW_OLD_REWARD_OPT(79), // 0, 1 ALLOW_ENERGY_ADJUSTMENT(81), // 0, 1 MAX_CREATE_ACCOUNT_TX_SIZE(82), // [500, 10000] - ALLOW_STRICT_MATH(87); // 0, 1 + ALLOW_STRICT_MATH(87), // 0, 1 + CONSENSUS_LOGIC_OPTIMIZATION(88); // 0, 1 private long code; diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 4af338f09bb..261b4462f55 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -224,6 +224,9 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] MAX_CREATE_ACCOUNT_TX_SIZE = "MAX_CREATE_ACCOUNT_TX_SIZE".getBytes(); private static final byte[] ALLOW_STRICT_MATH = "ALLOW_STRICT_MATH".getBytes(); + private static final byte[] CONSENSUS_LOGIC_OPTIMIZATION + = "CONSENSUS_LOGIC_OPTIMIZATION".getBytes(); + @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { super(dbName); @@ -2891,6 +2894,18 @@ public boolean allowStrictMath() { return getAllowStrictMath() == 1L; } + public void saveConsensusLogicOptimization(long value) { + this.put(CONSENSUS_LOGIC_OPTIMIZATION, + new BytesCapsule(ByteArray.fromLong(value))); + } + + public long getConsensusLogicOptimization() { + return Optional.ofNullable(getUnchecked(CONSENSUS_LOGIC_OPTIMIZATION)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElse(CommonParameter.getInstance().getConsensusLogicOptimization()); + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 1aa3befe8aa..d4a7b064cbb 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -681,6 +681,10 @@ public class CommonParameter { @Setter public long allowStrictMath; + @Getter + @Setter + public long consensusLogicOptimization; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 96ff41b91da..3bdbf2113af 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -387,4 +387,7 @@ public class Constant { public static final String COMMITTEE_ALLOW_ENERGY_ADJUSTMENT = "committee.allowEnergyAdjustment"; public static final String COMMITTEE_ALLOW_STRICT_MATH = "committee.allowStrictMath"; + + public static final String COMMITTEE_CONSENSUS_LOGIC_OPTIMIZATION + = "committee.consensusLogicOptimization"; } diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index 247c5dd4fe2..a71dc58e8bd 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -25,7 +25,8 @@ public enum ForkBlockVersionEnum { VERSION_4_7_2(28, 1596780000000L, 80), VERSION_4_7_4(29, 1596780000000L, 80), VERSION_4_7_5(30, 1596780000000L, 80), - VERSION_4_7_7(31, 1596780000000L, 80); + VERSION_4_7_7(31, 1596780000000L, 80), + VERSION_4_8_0(32, 1596780000000L, 80); // if add a version, modify BLOCK_VERSION simultaneously @Getter @@ -74,7 +75,7 @@ public class ChainConstant { public static final int SINGLE_REPEAT = 1; public static final int BLOCK_FILLED_SLOTS_NUMBER = 128; public static final int MAX_FROZEN_NUMBER = 1; - public static final int BLOCK_VERSION = 31; + public static final int BLOCK_VERSION = 32; public static final long FROZEN_PERIOD = 86_400_000L; public static final long DELEGATE_PERIOD = 3 * 86_400_000L; public static final long TRX_PRECISION = 1000_000L; diff --git a/consensus/src/main/java/org/tron/consensus/dpos/DposService.java b/consensus/src/main/java/org/tron/consensus/dpos/DposService.java index 5ec6c7c554b..bc46345da08 100644 --- a/consensus/src/main/java/org/tron/consensus/dpos/DposService.java +++ b/consensus/src/main/java/org/tron/consensus/dpos/DposService.java @@ -1,8 +1,5 @@ package org.tron.consensus.dpos; -import static org.tron.core.config.Parameter.ChainConstant.MAX_ACTIVE_WITNESS_NUM; -import static org.tron.core.config.Parameter.ChainConstant.SOLIDIFIED_THRESHOLD; - import com.google.protobuf.ByteString; import java.util.ArrayList; import java.util.Comparator; @@ -27,6 +24,8 @@ import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.WitnessCapsule; +import static org.tron.core.config.Parameter.ChainConstant.*; + @Slf4j(topic = "consensus") @Component public class DposService implements ConsensusInterface { diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 0943723f2f4..e2eea8700d1 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1348,6 +1348,11 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getAllowStrictMath()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getConsensusLogicOptimization") + .setValue(dbManager.getDynamicPropertiesStore().getConsensusLogicOptimization()) + .build()); + return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 8853971a5f8..7397b69cde3 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -235,6 +235,7 @@ public static void clearParam() { PARAMETER.allowOldRewardOpt = 0; PARAMETER.allowEnergyAdjustment = 0; PARAMETER.allowStrictMath = 0; + PARAMETER.consensusLogicOptimization = 0; } /** @@ -1222,6 +1223,10 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.COMMITTEE_ALLOW_STRICT_MATH) ? config .getInt(Constant.COMMITTEE_ALLOW_STRICT_MATH) : 0; + PARAMETER.consensusLogicOptimization = + config.hasPath(Constant.COMMITTEE_CONSENSUS_LOGIC_OPTIMIZATION) ? config + .getInt(Constant.COMMITTEE_CONSENSUS_LOGIC_OPTIMIZATION) : 0; + logConfig(); } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 29eef1c3cb3..120394de1be 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -371,6 +371,11 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveAllowStrictMath(entry.getValue()); break; } + case CONSENSUS_LOGIC_OPTIMIZATION: { + manager.getDynamicPropertiesStore() + .saveConsensusLogicOptimization(entry.getValue()); + break; + } default: find = false; break; diff --git a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java index 52f8cdacc00..cc82ed88cc8 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java @@ -433,6 +433,8 @@ public void validateCheck() { testEnergyAdjustmentProposal(); + testConsensusLogicOptimizationProposal(); + forkUtils.getManager().getDynamicPropertiesStore() .statsByVersion(ForkBlockVersionEnum.ENERGY_LIMIT.getValue(), stats); forkUtils.reset(); @@ -500,6 +502,43 @@ private void testEnergyAdjustmentProposal() { } } + private void testConsensusLogicOptimizationProposal() { + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.CONSENSUS_LOGIC_OPTIMIZATION.getCode(), 1); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "Bad chain parameter id [CONSENSUS_LOGIC_OPTIMIZATION]", + e.getMessage()); + } + + long maintenanceTimeInterval = forkUtils.getManager().getDynamicPropertiesStore() + .getMaintenanceTimeInterval(); + + long hardForkTime = + ((ForkBlockVersionEnum.VERSION_4_8_0.getHardForkTime() - 1) / maintenanceTimeInterval + 1) + * maintenanceTimeInterval; + forkUtils.getManager().getDynamicPropertiesStore() + .saveLatestBlockHeaderTimestamp(hardForkTime + 1); + + byte[] stats = new byte[27]; + Arrays.fill(stats, (byte) 1); + forkUtils.getManager().getDynamicPropertiesStore() + .statsByVersion(ForkBlockVersionEnum.VERSION_4_8_0.getValue(), stats); + + // Should fail because the proposal value is invalid + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.CONSENSUS_LOGIC_OPTIMIZATION.getCode(), 2); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "This value[CONSENSUS_LOGIC_OPTIMIZATION] is only allowed to be 1", + e.getMessage()); + } + } + @Test public void blockVersionCheck() { for (ForkBlockVersionEnum forkVersion : ForkBlockVersionEnum.values()) { diff --git a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java index 5bbf08fd96e..61f34b647c5 100644 --- a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java @@ -115,6 +115,7 @@ public void get() { Assert.assertEquals(GrpcUtil.DEFAULT_MAX_MESSAGE_SIZE, parameter.getMaxMessageSize()); Assert.assertEquals(GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE, parameter.getMaxHeaderListSize()); Assert.assertEquals(1L, parameter.getAllowCreationOfContracts()); + Assert.assertEquals(0, parameter.getConsensusLogicOptimization()); Assert.assertEquals(privateKey, Args.getLocalWitnesses().getPrivateKey()); diff --git a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java index 0ba32b27f2e..5975c83b88f 100644 --- a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java @@ -1,5 +1,6 @@ package org.tron.core.services; +import static org.tron.core.utils.ProposalUtil.ProposalType.CONSENSUS_LOGIC_OPTIMIZATION; import static org.tron.core.utils.ProposalUtil.ProposalType.ENERGY_FEE; import static org.tron.core.utils.ProposalUtil.ProposalType.TRANSACTION_FEE; import static org.tron.core.utils.ProposalUtil.ProposalType.WITNESS_127_PAY_PER_BLOCK; @@ -106,4 +107,21 @@ public void testUpdateTransactionFee() { Assert.assertEquals(expResult, currentHistory); } + @Test + public void testUpdateConsensusLogicOptimization() { + long v = dbManager.getDynamicPropertiesStore().getConsensusLogicOptimization(); + Assert.assertEquals(v, 0); + + long value = 1; + Proposal proposal = + Proposal.newBuilder().putParameters(CONSENSUS_LOGIC_OPTIMIZATION.getCode(), value).build(); + ProposalCapsule proposalCapsule = new ProposalCapsule(proposal); + proposalCapsule.setExpirationTime(1627279200000L); + boolean result = ProposalService.process(dbManager, proposalCapsule); + Assert.assertTrue(result); + + v = dbManager.getDynamicPropertiesStore().getConsensusLogicOptimization(); + Assert.assertEquals(v, value); + } + } \ No newline at end of file From 6a32bb12334ba79b72911c2f21d38862efa709e1 Mon Sep 17 00:00:00 2001 From: waynercheung Date: Fri, 10 Jan 2025 00:31:43 +0800 Subject: [PATCH 1106/1197] typo --- framework/src/main/java/org/tron/core/Wallet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index e7c239511d9..14663d45998 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -696,7 +696,7 @@ public Block getSolidBlock() { } public long getSolidBlockNum() { - return chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); + return chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); } public BlockCapsule getBlockCapsuleByNum(long blockNum) { From 81a04e52737ccba2a41cc7b4df61b8ea85e23ed7 Mon Sep 17 00:00:00 2001 From: chaozhu Date: Fri, 10 Jan 2025 11:02:02 +0800 Subject: [PATCH 1107/1197] remove assertTrue(true) --- .../java/org/tron/common/runtime/RuntimeImplMockTest.java | 3 --- framework/src/test/java/org/tron/core/WalletMockTest.java | 8 -------- .../src/test/java/org/tron/core/db/ManagerMockTest.java | 7 ------- .../org/tron/core/net/peer/PeerStatusCheckMockTest.java | 2 -- 4 files changed, 20 deletions(-) diff --git a/framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java b/framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java index ee126049ad0..e694f1c194f 100644 --- a/framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java +++ b/framework/src/test/java/org/tron/common/runtime/RuntimeImplMockTest.java @@ -4,7 +4,6 @@ import lombok.extern.slf4j.Slf4j; import org.junit.After; -import org.junit.Assert; import org.junit.Test; import org.tron.core.vm.program.Program; @@ -49,8 +48,6 @@ public void testSetResultCode1() throws Exception { = new Program.JVMStackOverFlowException(); programResult.setException(jvmStackOverFlowException); privateMethod.invoke(runtime, programResult); - - Assert.assertTrue(true); } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/WalletMockTest.java b/framework/src/test/java/org/tron/core/WalletMockTest.java index a52da0a95c9..098ba9aee61 100644 --- a/framework/src/test/java/org/tron/core/WalletMockTest.java +++ b/framework/src/test/java/org/tron/core/WalletMockTest.java @@ -105,8 +105,6 @@ public void testSetTransactionNullException() throws Exception { "setTransaction", TransactionCapsule.class); privateMethod.setAccessible(true); privateMethod.invoke(wallet, transactionCapsuleMock); - - assertTrue(true); } @Test @@ -130,7 +128,6 @@ public void testCreateTransactionCapsuleWithoutValidateWithTimeoutNullException( long.class); privateMethod.setAccessible(true); privateMethod.invoke(wallet, message, contractType, timeout); - assertTrue(true); } } @@ -164,8 +161,6 @@ public void testCreateTransactionCapsuleWithoutValidateWithTimeout() long.class); privateMethod.setAccessible(true); privateMethod.invoke(wallet, message, contractType, timeout); - - assertTrue(true); } } @@ -1108,7 +1103,6 @@ public void testGetShieldedTRC20LogType1() { } catch (Exception e) { assertTrue(false); } - assertTrue(true); } @@ -1141,7 +1135,6 @@ public void testGetShieldedTRC20LogType2() { } catch (Exception e) { assertTrue(false); } - assertTrue(true); } @Test @@ -1222,7 +1215,6 @@ public void testBuildShieldedTRC20InputWithAK1() throws Exception { builder, spendNote, ak, nk); - assertTrue(true); } } diff --git a/framework/src/test/java/org/tron/core/db/ManagerMockTest.java b/framework/src/test/java/org/tron/core/db/ManagerMockTest.java index f0e850faf7f..65726857809 100644 --- a/framework/src/test/java/org/tron/core/db/ManagerMockTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerMockTest.java @@ -34,7 +34,6 @@ import org.quartz.CronExpression; import org.tron.common.parameter.CommonParameter; import org.tron.common.runtime.ProgramResult; -import org.tron.common.runtime.RuntimeImpl; import org.tron.common.utils.Sha256Hash; import org.tron.core.ChainBaseManager; import org.tron.core.capsule.BlockCapsule; @@ -327,8 +326,6 @@ public void testProcessTransaction() throws Exception { TransactionCapsule.class, BlockCapsule.class); privateMethod.setAccessible(true); privateMethod.invoke(dbManager, transactionCapsuleMock, blockCapsuleMock); - - assertTrue(true); } @Test @@ -369,7 +366,6 @@ public void testRePush() { when(transactionStoreMock.has(any())).thenReturn(true); dbManager.rePush(trx); - assertTrue(true); } @SneakyThrows @@ -409,7 +405,6 @@ public void testRePush1() { doThrow(new TooBigTransactionResultException()).when(dbManager).pushTransaction(any()); dbManager.rePush(trx); - assertTrue(true); } @Test @@ -420,7 +415,6 @@ public void testPostSolidityFilter() throws Exception { "postSolidityFilter", long.class, long.class); privateMethod.setAccessible(true); privateMethod.invoke(dbManager, 100L, 10L); - assertTrue(true); } @Test @@ -442,7 +436,6 @@ public void testReOrgLogsFilter() throws Exception { Method privateMethod = Manager.class.getDeclaredMethod("reOrgLogsFilter"); privateMethod.setAccessible(true); privateMethod.invoke(dbManager); - assertTrue(true); } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckMockTest.java b/framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckMockTest.java index 5e8c69fdd6a..80b1abdc35d 100644 --- a/framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckMockTest.java +++ b/framework/src/test/java/org/tron/core/net/peer/PeerStatusCheckMockTest.java @@ -1,6 +1,5 @@ package org.tron.core.net.peer; -import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.spy; @@ -22,7 +21,6 @@ public void testInitException() throws InterruptedException { // the initialDelay of scheduleWithFixedDelay is 5s Thread.sleep(5000L); - assertTrue(true); } } \ No newline at end of file From eb8e59a1dce7cb8f148d28534faaa98dc477706f Mon Sep 17 00:00:00 2001 From: waynercheung Date: Tue, 14 Jan 2025 01:47:47 +0800 Subject: [PATCH 1108/1197] feat(jsonrpc): add test cases for jsonrpc finalized --- .../test/java/org/tron/core/WalletTest.java | 23 +- .../org/tron/core/jsonrpc/JsonRpcTest.java | 104 +--- .../tron/core/jsonrpc/JsonrpcServiceTest.java | 448 +++++++++++++++--- 3 files changed, 406 insertions(+), 169 deletions(-) diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java index 357a2d2ca08..6b984ff2fa8 100644 --- a/framework/src/test/java/org/tron/core/WalletTest.java +++ b/framework/src/test/java/org/tron/core/WalletTest.java @@ -139,7 +139,7 @@ public class WalletTest extends BaseTest { private static boolean init; static { - Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); + Args.setParam(new String[] {"-d", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; RECEIVER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049150"; } @@ -152,7 +152,8 @@ public void before() { } initTransaction(); initBlock(); - chainBaseManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(5); + chainBaseManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(BLOCK_NUM_FIVE); + chainBaseManager.getDynamicPropertiesStore().saveLatestSolidifiedBlockNum(BLOCK_NUM_TWO); chainBaseManager.getDelegatedResourceStore().reset(); init = true; } @@ -166,6 +167,7 @@ private void initTransaction() { TRANSACTION_TIMESTAMP_ONE, BLOCK_NUM_ONE); addTransactionToStore(transaction1); + // solidified transaction2 = getBuildTransaction( getBuildTransferContract(ACCOUNT_ADDRESS_TWO, ACCOUNT_ADDRESS_THREE), TRANSACTION_TIMESTAMP_TWO, BLOCK_NUM_TWO); @@ -284,6 +286,7 @@ private void initBlock() { private void addBlockToStore(Block block) { BlockCapsule blockCapsule = new BlockCapsule(block); + chainBaseManager.getBlockIndexStore().put(blockCapsule.getBlockId()); chainBaseManager.getBlockStore().put(blockCapsule.getBlockId().getBytes(), blockCapsule); } @@ -1169,19 +1172,19 @@ public void testListNodes() { * delegate_balance = 1000_000L; => 277 * delegate_balance = 1000_000_000L; => 279 * delegate_balance = 1000_000_000_000L => 280 - * + *

* We initialize account information as follows * account balance = 1000_000_000_000L * account frozen_balance = 1000_000_000L - * + *

* then estimateConsumeBandWidthSize cost 279 - * + *

* so we have following result: * TransactionUtil.estimateConsumeBandWidthSize( * dynamicStore,ownerCapsule.getBalance()) ===> false * TransactionUtil.estimateConsumeBandWidthSize( * dynamicStore,ownerCapsule.getFrozenV2BalanceForBandwidth()) ===> true - * + *

* This test case is used to verify the above conclusions */ @Test @@ -1206,5 +1209,13 @@ public void testGetCanDelegatedMaxSizeBandWidth123() { chainBaseManager.getDynamicPropertiesStore().saveMaxDelegateLockPeriod(DELEGATE_PERIOD / 3000); } + @Test + public void testGetSolidBlock() { + long blkNum = wallet.getSolidBlockNum(); + Assert.assertEquals(BLOCK_NUM_TWO, blkNum); + + Block block = wallet.getSolidBlock(); + assertEquals(block2, block); + } } diff --git a/framework/src/test/java/org/tron/core/jsonrpc/JsonRpcTest.java b/framework/src/test/java/org/tron/core/jsonrpc/JsonRpcTest.java index f221d0c95ac..0e1e09219cc 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/JsonRpcTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/JsonRpcTest.java @@ -190,6 +190,7 @@ public void testLogFilter() { } catch (JsonRpcInvalidParamsException e) { Assert.fail(); } + try { new LogFilter(new FilterRequest(null, null, null, new String[] {"0x0"}, null)); } catch (JsonRpcInvalidParamsException e) { @@ -240,109 +241,6 @@ public void testLogFilter() { } } - /** - * test fromBlock and toBlock parameters - */ - @Test - public void testLogFilterWrapper() { - - // fromBlock and toBlock are both empty - try { - LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest(null, null, null, null, null), 100, null); - Assert.assertEquals(logFilterWrapper.getFromBlock(), 100); - Assert.assertEquals(logFilterWrapper.getToBlock(), Long.MAX_VALUE); - } catch (JsonRpcInvalidParamsException e) { - Assert.fail(); - } - - // fromBlock is not empty and smaller than currentMaxBlockNum, toBlock is empty - try { - LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest("0x14", null, null, null, null), 100, null); - Assert.assertEquals(logFilterWrapper.getFromBlock(), 20); - Assert.assertEquals(logFilterWrapper.getToBlock(), Long.MAX_VALUE); - } catch (JsonRpcInvalidParamsException e) { - Assert.fail(); - } - - // fromBlock is not empty and bigger than currentMaxBlockNum, toBlock is empty - try { - LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest("0x78", null, null, null, null), 100, null); - Assert.assertEquals(logFilterWrapper.getFromBlock(), 120); - Assert.assertEquals(logFilterWrapper.getToBlock(), Long.MAX_VALUE); - } catch (JsonRpcInvalidParamsException e) { - Assert.fail(); - } - - // fromBlock is empty, toBlock is not empty and smaller than currentMaxBlockNum - try { - LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest(null, "0x14", null, null, null), 100, null); - Assert.assertEquals(logFilterWrapper.getFromBlock(), 20); - Assert.assertEquals(logFilterWrapper.getToBlock(), 20); - } catch (JsonRpcInvalidParamsException e) { - Assert.fail(); - } - - // fromBlock is empty, toBlock is not empty and bigger than currentMaxBlockNum - try { - LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest(null, "0x78", null, null, null), 100, null); - Assert.assertEquals(logFilterWrapper.getFromBlock(), 100); - Assert.assertEquals(logFilterWrapper.getToBlock(), 120); - } catch (JsonRpcInvalidParamsException e) { - Assert.fail(); - } - - // fromBlock is not empty, toBlock is not empty - try { - LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest("0x14", "0x78", null, null, null), 100, null); - Assert.assertEquals(logFilterWrapper.getFromBlock(), 20); - Assert.assertEquals(logFilterWrapper.getToBlock(), 120); - } catch (JsonRpcInvalidParamsException e) { - Assert.fail(); - } - try { - LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest("0x78", "0x14", null, null, null), 100, null); - } catch (JsonRpcInvalidParamsException e) { - Assert.assertEquals("please verify: fromBlock <= toBlock", e.getMessage()); - } - - //fromBlock or toBlock is not hex num - try { - LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest("earliest", null, null, null, null), 100, null); - Assert.assertEquals(logFilterWrapper.getFromBlock(), 0); - Assert.assertEquals(logFilterWrapper.getToBlock(), Long.MAX_VALUE); - } catch (JsonRpcInvalidParamsException e) { - Assert.fail(); - } - try { - LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest("latest", null, null, null, null), 100, null); - Assert.assertEquals(logFilterWrapper.getFromBlock(), 100); - Assert.assertEquals(logFilterWrapper.getToBlock(), Long.MAX_VALUE); - } catch (JsonRpcInvalidParamsException e) { - Assert.fail(); - } - try { - LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest("pending", null, null, null, null), 100, null); - } catch (JsonRpcInvalidParamsException e) { - Assert.assertEquals("TAG pending not supported", e.getMessage()); - } - try { - LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest("test", null, null, null, null), 100, null); - } catch (JsonRpcInvalidParamsException e) { - Assert.assertEquals("Incorrect hex syntax", e.getMessage()); - } - } - private int[] getBloomIndex(String s) { Bloom bloom = Bloom.create(Hash.sha3(ByteArray.fromHexString(s))); BitSet bs = BitSet.valueOf(bloom.getData()); diff --git a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java index b3ed26b591f..3a54f5a1a8e 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java @@ -1,5 +1,7 @@ package org.tron.core.jsonrpc; +import static org.tron.core.services.jsonrpc.JsonRpcApiUtil.getByJsonBlockId; + import com.alibaba.fastjson.JSON; import com.google.gson.JsonArray; import com.google.gson.JsonObject; @@ -27,12 +29,16 @@ import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.capsule.utils.BlockUtil; import org.tron.core.config.args.Args; +import org.tron.core.exception.JsonRpcInvalidParamsException; import org.tron.core.services.NodeInfoService; import org.tron.core.services.interfaceJsonRpcOnPBFT.JsonRpcServiceOnPBFT; import org.tron.core.services.interfaceJsonRpcOnSolidity.JsonRpcServiceOnSolidity; import org.tron.core.services.jsonrpc.FullNodeJsonRpcHttpService; +import org.tron.core.services.jsonrpc.TronJsonRpc.FilterRequest; import org.tron.core.services.jsonrpc.TronJsonRpcImpl; +import org.tron.core.services.jsonrpc.filters.LogFilterWrapper; import org.tron.core.services.jsonrpc.types.BlockResult; import org.tron.core.services.jsonrpc.types.TransactionResult; import org.tron.protos.Protocol; @@ -42,14 +48,19 @@ @Slf4j public class JsonrpcServiceTest extends BaseTest { + private static final String OWNER_ADDRESS; private static final String OWNER_ADDRESS_ACCOUNT_NAME = "first"; + private static final long LATEST_BLOCK_NUM = 10L; + private static final long LATEST_SOLIDIFIED_BLOCK_NUM = 4L; private static TronJsonRpcImpl tronJsonRpc; @Resource private NodeInfoService nodeInfoService; - private static BlockCapsule blockCapsule; + private static BlockCapsule blockCapsule0; + private static BlockCapsule blockCapsule1; + private static BlockCapsule blockCapsule2; private static TransactionCapsule transactionCapsule1; @Resource private Wallet wallet; @@ -64,65 +75,77 @@ public class JsonrpcServiceTest extends BaseTest { private JsonRpcServiceOnSolidity jsonRpcServiceOnSolidity; static { - Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); + Args.setParam(new String[] {"--output-directory", dbPath()}, Constant.TEST_CONF); CommonParameter.getInstance().setJsonRpcHttpFullNodeEnable(true); CommonParameter.getInstance().setJsonRpcHttpPBFTNodeEnable(true); CommonParameter.getInstance().setJsonRpcHttpSolidityNodeEnable(true); CommonParameter.getInstance().setMetricsPrometheusEnable(true); Metrics.init(); - OWNER_ADDRESS = - Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; } @Before public void init() { AccountCapsule accountCapsule = - new AccountCapsule( - ByteString.copyFromUtf8(OWNER_ADDRESS_ACCOUNT_NAME), + new AccountCapsule(ByteString.copyFromUtf8(OWNER_ADDRESS_ACCOUNT_NAME), ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), - Protocol.AccountType.Normal, - 10000_000_000L); + Protocol.AccountType.Normal, 10000_000_000L); dbManager.getAccountStore().put(accountCapsule.getAddress().toByteArray(), accountCapsule); - blockCapsule = new BlockCapsule( - 1, - Sha256Hash.wrap(ByteString.copyFrom( - ByteArray.fromHexString( - "0304f784e4e7bae517bcab94c3e0c9214fb4ac7ff9d7d5a937d1f40031f87b81"))), - 1, + blockCapsule0 = BlockUtil.newGenesisBlockCapsule(); + blockCapsule1 = new BlockCapsule(LATEST_BLOCK_NUM, Sha256Hash.wrap(ByteString.copyFrom( + ByteArray.fromHexString( + "0304f784e4e7bae517bcab94c3e0c9214fb4ac7ff9d7d5a937d1f40031f87b81"))), 1, + ByteString.copyFromUtf8("testAddress")); + blockCapsule2 = new BlockCapsule(LATEST_SOLIDIFIED_BLOCK_NUM, Sha256Hash.wrap( + ByteString.copyFrom(ByteArray.fromHexString( + "9938a342238077182498b464ac029222ae169360e540d1fd6aee7c2ae9575a06"))), 1, ByteString.copyFromUtf8("testAddress")); - TransferContract transferContract1 = TransferContract.newBuilder() - .setAmount(1L) - .setOwnerAddress(ByteString.copyFrom("0x0000000000000000000".getBytes())) - .setToAddress(ByteString.copyFrom(ByteArray.fromHexString( - (Wallet.getAddressPreFixString() + "A389132D6639FBDA4FBC8B659264E6B7C90DB086")))) - .build(); - TransferContract transferContract2 = TransferContract.newBuilder() - .setAmount(2L) - .setOwnerAddress(ByteString.copyFrom("0x0000000000000000000".getBytes())) - .setToAddress(ByteString.copyFrom(ByteArray.fromHexString( - (Wallet.getAddressPreFixString() + "ED738B3A0FE390EAA71B768B6D02CDBD18FB207B")))) + TransferContract transferContract1 = TransferContract.newBuilder().setAmount(1L) + .setOwnerAddress(ByteString.copyFrom("0x0000000000000000000".getBytes())).setToAddress( + ByteString.copyFrom(ByteArray.fromHexString( + (Wallet.getAddressPreFixString() + "A389132D6639FBDA4FBC8B659264E6B7C90DB086")))) + .build(); + TransferContract transferContract2 = TransferContract.newBuilder().setAmount(2L) + .setOwnerAddress(ByteString.copyFrom("0x0000000000000000000".getBytes())).setToAddress( + ByteString.copyFrom(ByteArray.fromHexString( + (Wallet.getAddressPreFixString() + "ED738B3A0FE390EAA71B768B6D02CDBD18FB207B")))) + .build(); + TransferContract transferContract3 = TransferContract.newBuilder().setAmount(3L) + .setOwnerAddress(ByteString.copyFrom("0x0000000000000000000".getBytes())).setToAddress( + ByteString.copyFrom(ByteArray.fromHexString( + (Wallet.getAddressPreFixString() + "ED738B3A0FE390EAA71B768B6D02CDBD18FB207B")))) .build(); - transactionCapsule1 = - new TransactionCapsule(transferContract1, ContractType.TransferContract); - transactionCapsule1.setBlockNum(blockCapsule.getNum()); + transactionCapsule1 = new TransactionCapsule(transferContract1, ContractType.TransferContract); + transactionCapsule1.setBlockNum(blockCapsule1.getNum()); TransactionCapsule transactionCapsule2 = new TransactionCapsule(transferContract2, ContractType.TransferContract); - transactionCapsule2.setBlockNum(2L); + transactionCapsule2.setBlockNum(blockCapsule1.getNum()); + TransactionCapsule transactionCapsule3 = new TransactionCapsule(transferContract3, + ContractType.TransferContract); + transactionCapsule3.setBlockNum(blockCapsule2.getNum()); + + blockCapsule1.addTransaction(transactionCapsule1); + blockCapsule1.addTransaction(transactionCapsule2); + blockCapsule2.addTransaction(transactionCapsule3); + + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(LATEST_BLOCK_NUM); + dbManager.getBlockIndexStore().put(blockCapsule1.getBlockId()); + dbManager.getBlockStore().put(blockCapsule1.getBlockId().getBytes(), blockCapsule1); - blockCapsule.addTransaction(transactionCapsule1); - blockCapsule.addTransaction(transactionCapsule2); - dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(1L); - dbManager.getBlockIndexStore().put(blockCapsule.getBlockId()); - dbManager.getBlockStore().put(blockCapsule.getBlockId().getBytes(), blockCapsule); + dbManager.getDynamicPropertiesStore().saveLatestSolidifiedBlockNum(LATEST_SOLIDIFIED_BLOCK_NUM); + dbManager.getBlockIndexStore().put(blockCapsule2.getBlockId()); + dbManager.getBlockStore().put(blockCapsule2.getBlockId().getBytes(), blockCapsule2); dbManager.getTransactionStore() .put(transactionCapsule1.getTransactionId().getBytes(), transactionCapsule1); dbManager.getTransactionStore() .put(transactionCapsule2.getTransactionId().getBytes(), transactionCapsule2); + dbManager.getTransactionStore() + .put(transactionCapsule3.getTransactionId().getBytes(), transactionCapsule3); tronJsonRpc = new TronJsonRpcImpl(nodeInfoService, wallet, dbManager); } @@ -165,11 +188,11 @@ public void testGetBlockTransactionCountByHash() { try { result = tronJsonRpc.ethGetBlockTransactionCountByHash( - Hex.toHexString((blockCapsule.getBlockId().getBytes()))); + Hex.toHexString((blockCapsule1.getBlockId().getBytes()))); } catch (Exception e) { Assert.fail(); } - Assert.assertEquals(ByteArray.toJsonHex(blockCapsule.getTransactions().size()), result); + Assert.assertEquals(ByteArray.toJsonHex(blockCapsule1.getTransactions().size()), result); } @@ -199,15 +222,15 @@ public void testGetBlockTransactionCountByNumber() { } catch (Exception e) { Assert.fail(); } - Assert.assertEquals(ByteArray.toJsonHex(blockCapsule.getTransactions().size()), result); + Assert.assertEquals(ByteArray.toJsonHex(blockCapsule1.getTransactions().size()), result); try { - result = tronJsonRpc - .ethGetBlockTransactionCountByNumber(ByteArray.toJsonHex(blockCapsule.getNum())); + result = tronJsonRpc.ethGetBlockTransactionCountByNumber( + ByteArray.toJsonHex(blockCapsule1.getNum())); } catch (Exception e) { Assert.fail(); } - Assert.assertEquals(ByteArray.toJsonHex(blockCapsule.getTransactions().size()), result); + Assert.assertEquals(ByteArray.toJsonHex(blockCapsule1.getTransactions().size()), result); } @@ -215,32 +238,74 @@ public void testGetBlockTransactionCountByNumber() { public void testGetBlockByHash() { BlockResult blockResult = null; try { - blockResult = tronJsonRpc - .ethGetBlockByHash(Hex.toHexString((blockCapsule.getBlockId().getBytes())), false); + blockResult = + tronJsonRpc.ethGetBlockByHash(Hex.toHexString((blockCapsule1.getBlockId().getBytes())), + false); } catch (Exception e) { Assert.fail(); } - Assert.assertEquals(ByteArray.toJsonHex(blockCapsule.getNum()), blockResult.getNumber()); - Assert - .assertEquals(blockCapsule.getTransactions().size(), blockResult.getTransactions().length); + Assert.assertEquals(ByteArray.toJsonHex(blockCapsule1.getNum()), blockResult.getNumber()); + Assert.assertEquals(blockCapsule1.getTransactions().size(), + blockResult.getTransactions().length); } @Test public void testGetBlockByNumber() { BlockResult blockResult = null; + + // by number try { - blockResult = tronJsonRpc - .ethGetBlockByNumber(ByteArray.toJsonHex(blockCapsule.getNum()), false); + blockResult = + tronJsonRpc.ethGetBlockByNumber(ByteArray.toJsonHex(blockCapsule1.getNum()), false); } catch (Exception e) { Assert.fail(); } - - Assert.assertEquals(ByteArray.toJsonHex(blockCapsule.getNum()), blockResult.getNumber()); - Assert - .assertEquals(blockCapsule.getTransactions().size(), blockResult.getTransactions().length); + Assert.assertEquals(ByteArray.toJsonHex(blockCapsule1.getNum()), blockResult.getNumber()); + Assert.assertEquals(blockCapsule1.getTransactions().size(), + blockResult.getTransactions().length); Assert.assertEquals("0x0000000000000000", blockResult.getNonce()); - } + // earliest + try { + blockResult = tronJsonRpc.ethGetBlockByNumber("earliest", false); + } catch (Exception e) { + Assert.fail(); + } + Assert.assertEquals(ByteArray.toJsonHex(0L), blockResult.getNumber()); + Assert.assertEquals(ByteArray.toJsonHex(blockCapsule0.getNum()), blockResult.getNumber()); + + // latest + try { + blockResult = tronJsonRpc.ethGetBlockByNumber("latest", false); + } catch (Exception e) { + Assert.fail(); + } + Assert.assertEquals(ByteArray.toJsonHex(LATEST_BLOCK_NUM), blockResult.getNumber()); + Assert.assertEquals(ByteArray.toJsonHex(blockCapsule1.getNum()), blockResult.getNumber()); + + // finalized + try { + blockResult = tronJsonRpc.ethGetBlockByNumber("finalized", false); + } catch (Exception e) { + Assert.fail(); + } + Assert.assertEquals(ByteArray.toJsonHex(LATEST_SOLIDIFIED_BLOCK_NUM), blockResult.getNumber()); + Assert.assertEquals(ByteArray.toJsonHex(blockCapsule2.getNum()), blockResult.getNumber()); + + // pending + try { + tronJsonRpc.ethGetBlockByNumber("pending", false); + } catch (Exception e) { + Assert.assertEquals("TAG pending not supported", e.getMessage()); + } + + // invalid + try { + tronJsonRpc.ethGetBlockByNumber("0x", false); + } catch (Exception e) { + Assert.assertEquals("invalid block number", e.getMessage()); + } + } @Test public void testGetTransactionByHash() { @@ -268,7 +333,7 @@ public void testGetBlockByNumber2() { fullNodeJsonRpcHttpService.init(Args.getInstance()); fullNodeJsonRpcHttpService.start(); JsonArray params = new JsonArray(); - params.add(ByteArray.toJsonHex(blockCapsule.getNum())); + params.add(ByteArray.toJsonHex(blockCapsule1.getNum())); params.add(false); JsonObject requestBody = new JsonObject(); requestBody.addProperty("jsonrpc", "2.0"); @@ -283,16 +348,14 @@ public void testGetBlockByNumber2() { response = httpClient.execute(httpPost); String resp = EntityUtils.toString(response.getEntity()); BlockResult blockResult = JSON.parseObject(resp).getObject("result", BlockResult.class); - Assert.assertEquals(ByteArray.toJsonHex(blockCapsule.getNum()), - blockResult.getNumber()); - Assert.assertEquals(blockCapsule.getTransactions().size(), + Assert.assertEquals(ByteArray.toJsonHex(blockCapsule1.getNum()), blockResult.getNumber()); + Assert.assertEquals(blockCapsule1.getTransactions().size(), blockResult.getTransactions().length); - Assert.assertEquals("0x0000000000000000", - blockResult.getNonce()); + Assert.assertEquals("0x0000000000000000", blockResult.getNonce()); response.close(); Assert.assertEquals(1, CollectorRegistry.defaultRegistry.getSampleValue( - "tron:jsonrpc_service_latency_seconds_count", - new String[] {"method"}, new String[] {"eth_getBlockByNumber"}).intValue()); + "tron:jsonrpc_service_latency_seconds_count", new String[] {"method"}, + new String[] {"eth_getBlockByNumber"}).intValue()); } catch (Exception e) { Assert.fail(e.getMessage()); } finally { @@ -313,4 +376,269 @@ public void testServicesInit() { } } + @Test + public void testGetByJsonBlockId() { + long blkNum = 0; + + try { + getByJsonBlockId("pending", wallet); + } catch (Exception e) { + Assert.assertEquals("TAG pending not supported", e.getMessage()); + } + + try { + blkNum = getByJsonBlockId(null, wallet); + } catch (Exception e) { + Assert.fail(); + } + Assert.assertEquals(-1, blkNum); + + try { + blkNum = getByJsonBlockId("latest", wallet); + } catch (Exception e) { + Assert.fail(); + } + Assert.assertEquals(-1, blkNum); + + try { + blkNum = getByJsonBlockId("finalized", wallet); + } catch (Exception e) { + Assert.fail(); + } + Assert.assertEquals(LATEST_SOLIDIFIED_BLOCK_NUM, blkNum); + + try { + blkNum = getByJsonBlockId("0xa", wallet); + } catch (Exception e) { + Assert.fail(); + } + Assert.assertEquals(10L, blkNum); + + try { + getByJsonBlockId("abc", wallet); + } catch (Exception e) { + Assert.assertEquals("Incorrect hex syntax", e.getMessage()); + } + + try { + getByJsonBlockId("0xxabc", wallet); + } catch (Exception e) { + Assert.assertEquals("For input string: \"xabc\"", e.getMessage()); + } + } + + @Test + public void testGetTrxBalance() { + String balance = ""; + + try { + tronJsonRpc.getTrxBalance("", "earliest"); + } catch (Exception e) { + Assert.assertEquals("TAG [earliest | pending | finalized] not supported", + e.getMessage()); + } + + try { + tronJsonRpc.getTrxBalance("", "pending"); + } catch (Exception e) { + Assert.assertEquals("TAG [earliest | pending | finalized] not supported", + e.getMessage()); + } + + try { + tronJsonRpc.getTrxBalance("", "finalized"); + } catch (Exception e) { + Assert.assertEquals("TAG [earliest | pending | finalized] not supported", + e.getMessage()); + } + + try { + balance = tronJsonRpc.getTrxBalance("0xabd4b9367799eaa3197fecb144eb71de1e049abc", + "latest"); + } catch (Exception e) { + Assert.fail(); + } + Assert.assertEquals("0x2540be400", balance); + } + + @Test + public void testGetStorageAt() { + try { + tronJsonRpc.getStorageAt("", "", "earliest"); + } catch (Exception e) { + Assert.assertEquals("TAG [earliest | pending | finalized] not supported", + e.getMessage()); + } + + try { + tronJsonRpc.getStorageAt("", "", "pending"); + } catch (Exception e) { + Assert.assertEquals("TAG [earliest | pending | finalized] not supported", + e.getMessage()); + } + + try { + tronJsonRpc.getStorageAt("", "", "finalized"); + } catch (Exception e) { + Assert.assertEquals("TAG [earliest | pending | finalized] not supported", + e.getMessage()); + } + } + + @Test + public void testGetABIOfSmartContract() { + try { + tronJsonRpc.getABIOfSmartContract("", "earliest"); + } catch (Exception e) { + Assert.assertEquals("TAG [earliest | pending | finalized] not supported", + e.getMessage()); + } + + try { + tronJsonRpc.getABIOfSmartContract("", "pending"); + } catch (Exception e) { + Assert.assertEquals("TAG [earliest | pending | finalized] not supported", + e.getMessage()); + } + + try { + tronJsonRpc.getABIOfSmartContract("", "finalized"); + } catch (Exception e) { + Assert.assertEquals("TAG [earliest | pending | finalized] not supported", + e.getMessage()); + } + } + + @Test + public void testGetCall() { + try { + tronJsonRpc.getCall(null, "earliest"); + } catch (Exception e) { + Assert.assertEquals("TAG [earliest | pending | finalized] not supported", + e.getMessage()); + } + + try { + tronJsonRpc.getCall(null, "pending"); + } catch (Exception e) { + Assert.assertEquals("TAG [earliest | pending | finalized] not supported", + e.getMessage()); + } + + try { + tronJsonRpc.getCall(null, "finalized"); + } catch (Exception e) { + Assert.assertEquals("TAG [earliest | pending | finalized] not supported", + e.getMessage()); + } + } + + /** + * test fromBlock and toBlock parameters + */ + @Test + public void testLogFilterWrapper() { + + // fromBlock and toBlock are both empty + try { + LogFilterWrapper logFilterWrapper = + new LogFilterWrapper(new FilterRequest(null, null, null, null, null), 100, null); + Assert.assertEquals(100, logFilterWrapper.getFromBlock()); + Assert.assertEquals(Long.MAX_VALUE, logFilterWrapper.getToBlock()); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + + // fromBlock is not empty and smaller than currentMaxBlockNum, toBlock is empty + try { + LogFilterWrapper logFilterWrapper = + new LogFilterWrapper(new FilterRequest("0x14", null, null, null, null), 100, null); + Assert.assertEquals(20, logFilterWrapper.getFromBlock()); + Assert.assertEquals(Long.MAX_VALUE, logFilterWrapper.getToBlock()); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + + // fromBlock is not empty and bigger than currentMaxBlockNum, toBlock is empty + try { + LogFilterWrapper logFilterWrapper = + new LogFilterWrapper(new FilterRequest("0x78", null, null, null, null), 100, null); + Assert.assertEquals(120, logFilterWrapper.getFromBlock()); + Assert.assertEquals(Long.MAX_VALUE, logFilterWrapper.getToBlock()); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + + // fromBlock is empty, toBlock is not empty and smaller than currentMaxBlockNum + try { + LogFilterWrapper logFilterWrapper = + new LogFilterWrapper(new FilterRequest(null, "0x14", null, null, null), 100, null); + Assert.assertEquals(20, logFilterWrapper.getFromBlock()); + Assert.assertEquals(20, logFilterWrapper.getToBlock()); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + + // fromBlock is empty, toBlock is not empty and bigger than currentMaxBlockNum + try { + LogFilterWrapper logFilterWrapper = + new LogFilterWrapper(new FilterRequest(null, "0x78", null, null, null), 100, null); + Assert.assertEquals(100, logFilterWrapper.getFromBlock()); + Assert.assertEquals(120, logFilterWrapper.getToBlock()); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + + // fromBlock is not empty, toBlock is not empty + try { + LogFilterWrapper logFilterWrapper = + new LogFilterWrapper(new FilterRequest("0x14", "0x78", null, null, null), 100, null); + Assert.assertEquals(20, logFilterWrapper.getFromBlock()); + Assert.assertEquals(120, logFilterWrapper.getToBlock()); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + try { + LogFilterWrapper logFilterWrapper = + new LogFilterWrapper(new FilterRequest("0x78", "0x14", null, null, null), 100, null); + } catch (JsonRpcInvalidParamsException e) { + Assert.assertEquals("please verify: fromBlock <= toBlock", e.getMessage()); + } + + //fromBlock or toBlock is not hex num + try { + LogFilterWrapper logFilterWrapper = + new LogFilterWrapper(new FilterRequest("earliest", null, null, null, null), 100, null); + Assert.assertEquals(0, logFilterWrapper.getFromBlock()); + Assert.assertEquals(Long.MAX_VALUE, logFilterWrapper.getToBlock()); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + try { + LogFilterWrapper logFilterWrapper = + new LogFilterWrapper(new FilterRequest("latest", null, null, null, null), 100, null); + Assert.assertEquals(100, logFilterWrapper.getFromBlock()); + Assert.assertEquals(Long.MAX_VALUE, logFilterWrapper.getToBlock()); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + try { + new LogFilterWrapper(new FilterRequest("pending", null, null, null, null), 100, null); + } catch (JsonRpcInvalidParamsException e) { + Assert.assertEquals("TAG pending not supported", e.getMessage()); + } + try { + LogFilterWrapper logFilterWrapper = + new LogFilterWrapper(new FilterRequest("finalized", null, null, null, null), 100, wallet); + Assert.assertEquals(LATEST_SOLIDIFIED_BLOCK_NUM, logFilterWrapper.getFromBlock()); + Assert.assertEquals(Long.MAX_VALUE, logFilterWrapper.getToBlock()); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + try { + new LogFilterWrapper(new FilterRequest("test", null, null, null, null), 100, null); + } catch (JsonRpcInvalidParamsException e) { + Assert.assertEquals("Incorrect hex syntax", e.getMessage()); + } + } } From 46826a70a97bef3dcc3c5bfaebdb367775d8b75e Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Tue, 14 Jan 2025 21:19:53 +0800 Subject: [PATCH 1109/1197] feat(consensus): modify the review comments --- .../java/org/tron/core/utils/ProposalUtil.java | 14 +++++++++----- .../tron/core/store/DynamicPropertiesStore.java | 4 ++++ .../java/org/tron/consensus/dpos/DposService.java | 5 +++-- .../tron/core/actuator/utils/ProposalUtilTest.java | 12 ++++++++++++ .../tron/core/services/ProposalServiceTest.java | 3 +++ 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index fc60316eb40..081b91dfd6c 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -782,26 +782,30 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, case ALLOW_STRICT_MATH: { if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7_7)) { throw new ContractValidateException( - "Bad chain parameter id [ALLOW_STRICT_MATH]"); + "Bad chain parameter id [ALLOW_STRICT_MATH]"); } if (dynamicPropertiesStore.allowStrictMath()) { throw new ContractValidateException( - "[ALLOW_STRICT_MATH] has been valid, no need to propose again"); + "[ALLOW_STRICT_MATH] has been valid, no need to propose again"); } if (value != 1) { throw new ContractValidateException( - "This value[ALLOW_STRICT_MATH] is only allowed to be 1"); + "This value[ALLOW_STRICT_MATH] is only allowed to be 1"); } break; } case CONSENSUS_LOGIC_OPTIMIZATION: { if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_8_0)) { throw new ContractValidateException( - "Bad chain parameter id [CONSENSUS_LOGIC_OPTIMIZATION]"); + "Bad chain parameter id [CONSENSUS_LOGIC_OPTIMIZATION]"); + } + if (dynamicPropertiesStore.getConsensusLogicOptimization() == 1) { + throw new ContractValidateException( + "[CONSENSUS_LOGIC_OPTIMIZATION] has been valid, no need to propose again"); } if (value != 1) { throw new ContractValidateException( - "This value[CONSENSUS_LOGIC_OPTIMIZATION] is only allowed to be 1"); + "This value[CONSENSUS_LOGIC_OPTIMIZATION] is only allowed to be 1"); } break; } diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 261b4462f55..85f958ada8b 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -2906,6 +2906,10 @@ public long getConsensusLogicOptimization() { .orElse(CommonParameter.getInstance().getConsensusLogicOptimization()); } + public boolean allowConsensusLogicOptimization() { + return getConsensusLogicOptimization() == 1L; + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/consensus/src/main/java/org/tron/consensus/dpos/DposService.java b/consensus/src/main/java/org/tron/consensus/dpos/DposService.java index bc46345da08..5ec6c7c554b 100644 --- a/consensus/src/main/java/org/tron/consensus/dpos/DposService.java +++ b/consensus/src/main/java/org/tron/consensus/dpos/DposService.java @@ -1,5 +1,8 @@ package org.tron.consensus.dpos; +import static org.tron.core.config.Parameter.ChainConstant.MAX_ACTIVE_WITNESS_NUM; +import static org.tron.core.config.Parameter.ChainConstant.SOLIDIFIED_THRESHOLD; + import com.google.protobuf.ByteString; import java.util.ArrayList; import java.util.Comparator; @@ -24,8 +27,6 @@ import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.WitnessCapsule; -import static org.tron.core.config.Parameter.ChainConstant.*; - @Slf4j(topic = "consensus") @Component public class DposService implements ConsensusInterface { diff --git a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java index cc82ed88cc8..1cfc4d1887f 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java @@ -537,6 +537,18 @@ private void testConsensusLogicOptimizationProposal() { "This value[CONSENSUS_LOGIC_OPTIMIZATION] is only allowed to be 1", e.getMessage()); } + + dynamicPropertiesStore.saveConsensusLogicOptimization(1); + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.CONSENSUS_LOGIC_OPTIMIZATION.getCode(), 1); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "[CONSENSUS_LOGIC_OPTIMIZATION] has been valid, no need to propose again", + e.getMessage()); + } + } @Test diff --git a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java index 5975c83b88f..cda9bfe4186 100644 --- a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java @@ -111,6 +111,7 @@ public void testUpdateTransactionFee() { public void testUpdateConsensusLogicOptimization() { long v = dbManager.getDynamicPropertiesStore().getConsensusLogicOptimization(); Assert.assertEquals(v, 0); + Assert.assertTrue(!dbManager.getDynamicPropertiesStore().allowConsensusLogicOptimization()); long value = 1; Proposal proposal = @@ -122,6 +123,8 @@ public void testUpdateConsensusLogicOptimization() { v = dbManager.getDynamicPropertiesStore().getConsensusLogicOptimization(); Assert.assertEquals(v, value); + + Assert.assertTrue(dbManager.getDynamicPropertiesStore().allowConsensusLogicOptimization()); } } \ No newline at end of file From 4e4881f08b2004cf6e9a5b5e8ee5ffa4c04484d8 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 22 Jan 2025 16:48:47 +0800 Subject: [PATCH 1110/1197] feat(witness): sort witness from address hashcode to address --- .../tron/core/service/MortgageService.java | 14 ++-------- .../core/store/DynamicPropertiesStore.java | 4 +++ .../org/tron/core/store/WitnessStore.java | 22 ++++++++++++--- .../org/tron/consensus/ConsensusDelegate.java | 4 +++ .../org/tron/consensus/dpos/DposService.java | 6 +---- .../actuator/VoteWitnessActuatorTest.java | 1 + .../java/org/tron/core/db/ManagerTest.java | 6 +++-- .../org/tron/core/db/WitnessStoreTest.java | 27 ++++++++++++++++++- .../core/services/DelegationServiceTest.java | 1 + .../core/services/ProposalServiceTest.java | 2 ++ 10 files changed, 63 insertions(+), 24 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/service/MortgageService.java b/chainbase/src/main/java/org/tron/core/service/MortgageService.java index 805245d53f2..29ea32208eb 100644 --- a/chainbase/src/main/java/org/tron/core/service/MortgageService.java +++ b/chainbase/src/main/java/org/tron/core/service/MortgageService.java @@ -1,8 +1,6 @@ package org.tron.core.service; -import com.google.protobuf.ByteString; import java.math.BigInteger; -import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; import lombok.Getter; @@ -51,7 +49,8 @@ public void initStore(WitnessStore witnessStore, DelegationStore delegationStore } public void payStandbyWitness() { - List witnessStandbys = witnessStore.getWitnessStandby(); + List witnessStandbys = witnessStore.getWitnessStandby( + dynamicPropertiesStore.allowWitnessSortOptimization()); long voteSum = witnessStandbys.stream().mapToLong(WitnessCapsule::getVoteCount).sum(); if (voteSum < 1) { return; @@ -227,10 +226,6 @@ private long computeReward(long beginCycle, long endCycle, AccountCapsule accoun return reward; } - public WitnessCapsule getWitnessByAddress(ByteString address) { - return witnessStore.get(address.toByteArray()); - } - public void adjustAllowance(byte[] address, long amount) { try { if (amount <= 0) { @@ -259,11 +254,6 @@ public void adjustAllowance(AccountStore accountStore, byte[] accountAddress, lo accountStore.put(account.createDbKey(), account); } - private void sortWitness(List list) { - list.sort(Comparator.comparingLong((ByteString b) -> getWitnessByAddress(b).getVoteCount()) - .reversed().thenComparing(Comparator.comparingInt(ByteString::hashCode).reversed())); - } - private long getOldReward(long begin, long end, List> votes) { if (dynamicPropertiesStore.allowOldRewardOpt()) { return rewardViCalService.getNewRewardAlgorithmReward(begin, end, votes); diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 85f958ada8b..6fe29a7a136 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -2910,6 +2910,10 @@ public boolean allowConsensusLogicOptimization() { return getConsensusLogicOptimization() == 1L; } + public boolean allowWitnessSortOptimization() { + return this.allowConsensusLogicOptimization(); + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/chainbase/src/main/java/org/tron/core/store/WitnessStore.java b/chainbase/src/main/java/org/tron/core/store/WitnessStore.java index d23a73f92f9..9f444d3333d 100644 --- a/chainbase/src/main/java/org/tron/core/store/WitnessStore.java +++ b/chainbase/src/main/java/org/tron/core/store/WitnessStore.java @@ -1,6 +1,7 @@ package org.tron.core.store; import com.google.common.collect.Streams; +import com.google.protobuf.ByteString; import java.util.ArrayList; import java.util.Comparator; import java.util.List; @@ -11,6 +12,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import org.tron.common.utils.ByteArray; import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.Parameter; import org.tron.core.db.TronStoreWithRevoking; @@ -39,12 +41,10 @@ public WitnessCapsule get(byte[] key) { return ArrayUtils.isEmpty(value) ? null : new WitnessCapsule(value); } - public List getWitnessStandby() { + public List getWitnessStandby(boolean isSortOpt) { List ret; List all = getAllWitnesses(); - all.sort(Comparator.comparingLong(WitnessCapsule::getVoteCount) - .reversed().thenComparing(Comparator.comparingInt( - (WitnessCapsule w) -> w.getAddress().hashCode()).reversed())); + sortWitnesses(all, isSortOpt); if (all.size() > Parameter.ChainConstant.WITNESS_STANDBY_LENGTH) { ret = new ArrayList<>(all.subList(0, Parameter.ChainConstant.WITNESS_STANDBY_LENGTH)); } else { @@ -55,4 +55,18 @@ public List getWitnessStandby() { return ret; } + public void sortWitnesses(List witnesses, boolean isSortOpt) { + witnesses.sort(Comparator.comparingLong(WitnessCapsule::getVoteCount).reversed() + .thenComparing(isSortOpt + ? Comparator.comparing(WitnessCapsule::createReadableString).reversed() + : Comparator.comparingInt((WitnessCapsule w) -> w.getAddress().hashCode()).reversed())); + } + + public void sortWitness(List list, boolean isSortOpt) { + list.sort(Comparator.comparingLong((ByteString b) -> get(b.toByteArray()).getVoteCount()) + .reversed().thenComparing(isSortOpt + ? Comparator.comparing( + (ByteString b) -> ByteArray.toHexString(b.toByteArray())).reversed() + : Comparator.comparingInt(ByteString::hashCode).reversed())); + } } diff --git a/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java b/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java index 767463a6a5b..ef3a35d1ec7 100644 --- a/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java +++ b/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java @@ -135,4 +135,8 @@ public void applyBlock(boolean flag) { public boolean allowChangeDelegation() { return dynamicPropertiesStore.allowChangeDelegation(); } + + public void sortWitness(List list) { + witnessStore.sortWitness(list, dynamicPropertiesStore.allowWitnessSortOptimization()); + } } \ No newline at end of file diff --git a/consensus/src/main/java/org/tron/consensus/dpos/DposService.java b/consensus/src/main/java/org/tron/consensus/dpos/DposService.java index 5ec6c7c554b..292294b2c2d 100644 --- a/consensus/src/main/java/org/tron/consensus/dpos/DposService.java +++ b/consensus/src/main/java/org/tron/consensus/dpos/DposService.java @@ -163,11 +163,7 @@ private void updateSolidBlock() { } public void updateWitness(List list) { - list.sort(Comparator.comparingLong((ByteString b) -> - consensusDelegate.getWitness(b.toByteArray()).getVoteCount()) - .reversed() - .thenComparing(Comparator.comparingInt(ByteString::hashCode).reversed())); - + consensusDelegate.sortWitness(list); if (list.size() > MAX_ACTIVE_WITNESS_NUM) { consensusDelegate .saveActiveWitnesses(list.subList(0, MAX_ACTIVE_WITNESS_NUM)); diff --git a/framework/src/test/java/org/tron/core/actuator/VoteWitnessActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/VoteWitnessActuatorTest.java index 1a152555931..d7fef2ab2f5 100644 --- a/framework/src/test/java/org/tron/core/actuator/VoteWitnessActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/VoteWitnessActuatorTest.java @@ -52,6 +52,7 @@ public class VoteWitnessActuatorTest extends BaseTest { static { Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); + Args.getInstance().setConsensusLogicOptimization(1); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; WITNESS_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; WITNESS_ADDRESS_NOACCOUNT = diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index 07440435f41..70aba258594 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -618,7 +618,8 @@ public void pushSwitchFork() WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address)); chainManager.getWitnessScheduleStore().saveActiveWitnesses(new ArrayList<>()); chainManager.addWitness(ByteString.copyFrom(address)); - List witnessStandby1 = chainManager.getWitnessStore().getWitnessStandby(); + List witnessStandby1 = chainManager.getWitnessStore().getWitnessStandby( + chainManager.getDynamicPropertiesStore().allowWitnessSortOptimization()); Block block = getSignedBlock(witnessCapsule.getAddress(), 1533529947843L, privateKey); dbManager.pushBlock(new BlockCapsule(block)); @@ -656,7 +657,8 @@ public void pushSwitchFork() Assert.assertTrue(e instanceof Exception); } chainManager.getWitnessStore().put(address, sr2); - List witnessStandby2 = chainManager.getWitnessStore().getWitnessStandby(); + List witnessStandby2 = chainManager.getWitnessStore().getWitnessStandby( + chainManager.getDynamicPropertiesStore().allowWitnessSortOptimization()); Assert.assertNotEquals(witnessStandby1, witnessStandby2); } diff --git a/framework/src/test/java/org/tron/core/db/WitnessStoreTest.java b/framework/src/test/java/org/tron/core/db/WitnessStoreTest.java index 3190e226689..d141a5fd790 100755 --- a/framework/src/test/java/org/tron/core/db/WitnessStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/WitnessStoreTest.java @@ -1,6 +1,9 @@ package org.tron.core.db; import com.google.protobuf.ByteString; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; @@ -46,5 +49,27 @@ public void putAndGetWitness() { Assert.assertEquals(100L, witnessSource.getVoteCount()); } - + @Test + public void testSortWitness() { + this.witnessStore.reset(); + WitnessCapsule s1 = new WitnessCapsule( + ByteString.copyFrom(new byte[]{1, 2, 3}), 100L, "URL-1"); + this.witnessStore.put(s1.getAddress().toByteArray(), s1); + WitnessCapsule s2 = new WitnessCapsule( + ByteString.copyFrom(new byte[]{1, 1, 34}), 100L, "URL-2"); + this.witnessStore.put(s2.getAddress().toByteArray(), s2); + List allWitnesses = this.witnessStore.getAllWitnesses(); + List witnessAddress = allWitnesses.stream().map(WitnessCapsule::getAddress) + .collect(Collectors.toList()); + this.witnessStore.sortWitness(witnessAddress, false); + this.witnessStore.sortWitnesses(allWitnesses, false); + Assert.assertEquals(witnessAddress, allWitnesses.stream().map(WitnessCapsule::getAddress) + .collect(Collectors.toList())); + List pre = new ArrayList<>(witnessAddress); + this.witnessStore.sortWitness(witnessAddress, true); + this.witnessStore.sortWitnesses(allWitnesses, true); + Assert.assertEquals(witnessAddress, allWitnesses.stream().map(WitnessCapsule::getAddress) + .collect(Collectors.toList())); + Assert.assertNotEquals(pre, witnessAddress); + } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/services/DelegationServiceTest.java b/framework/src/test/java/org/tron/core/services/DelegationServiceTest.java index e2ea87a1d0f..5c898eb42d6 100644 --- a/framework/src/test/java/org/tron/core/services/DelegationServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/DelegationServiceTest.java @@ -107,6 +107,7 @@ private void testWithdraw() { public void test() { manager.getDynamicPropertiesStore().saveChangeDelegation(1); + manager.getDynamicPropertiesStore().saveConsensusLogicOptimization(1); byte[] sr27 = decodeFromBase58Check("TLTDZBcPoJ8tZ6TTEeEqEvwYFk2wgotSfD"); manager.getDelegationStore().setBrokerage(0, sr27, 10); manager.getDelegationStore().setBrokerage(1, sr27, 20); diff --git a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java index cda9bfe4186..211e7228289 100644 --- a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java @@ -112,6 +112,7 @@ public void testUpdateConsensusLogicOptimization() { long v = dbManager.getDynamicPropertiesStore().getConsensusLogicOptimization(); Assert.assertEquals(v, 0); Assert.assertTrue(!dbManager.getDynamicPropertiesStore().allowConsensusLogicOptimization()); + Assert.assertFalse(dbManager.getDynamicPropertiesStore().allowWitnessSortOptimization()); long value = 1; Proposal proposal = @@ -125,6 +126,7 @@ public void testUpdateConsensusLogicOptimization() { Assert.assertEquals(v, value); Assert.assertTrue(dbManager.getDynamicPropertiesStore().allowConsensusLogicOptimization()); + Assert.assertTrue(dbManager.getDynamicPropertiesStore().allowWitnessSortOptimization()); } } \ No newline at end of file From c3686aae2de1af2c3475afbb3d63a15c269fb489 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 1 Jan 2025 18:30:39 +0800 Subject: [PATCH 1111/1197] feat(*): optimize sensitive information --- .../tron/common/crypto/BouncyCastleTest.java | 25 +- .../org/tron/common/crypto/ECKeyTest.java | 14 +- .../org/tron/common/crypto/SM2KeyTest.java | 16 +- .../common/utils/client/utils/AbiUtil.java | 10 + .../core/capsule/TransactionCapsuleTest.java | 1015 ----------------- .../tron/core/config/ConfigurationTest.java | 15 +- .../core/zksnark/ShieldedReceiveTest.java | 13 +- framework/src/test/resources/config-test.conf | 2 +- framework/src/test/resources/testng.conf | 46 +- .../java/org/tron/plugins/DbLiteTest.java | 4 +- 10 files changed, 63 insertions(+), 1097 deletions(-) diff --git a/framework/src/test/java/org/tron/common/crypto/BouncyCastleTest.java b/framework/src/test/java/org/tron/common/crypto/BouncyCastleTest.java index 880a6623a38..ab6b2832c12 100644 --- a/framework/src/test/java/org/tron/common/crypto/BouncyCastleTest.java +++ b/framework/src/test/java/org/tron/common/crypto/BouncyCastleTest.java @@ -2,6 +2,7 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.tron.common.utils.client.utils.AbiUtil.generateOccupationConstantPrivateKey; import java.math.BigInteger; import java.security.SignatureException; @@ -20,12 +21,13 @@ */ public class BouncyCastleTest { - private String privString = "c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4"; - private BigInteger privateKey = new BigInteger(privString, 16); + // For safety reasons, test with a placeholder private key + private final String privString = generateOccupationConstantPrivateKey(); + private final BigInteger privateKey = new BigInteger(privString, 16); @Test public void testHex() { - String spongyAddress = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826"; + String spongyAddress = "2e988a386a799f506693793c6a5af6b54dfaabfb"; ECKey key = ECKey.fromPrivate(privateKey); byte[] address = key.getAddress(); assertEquals(spongyAddress, @@ -55,10 +57,9 @@ public void testSha3Hash() { @Test public void testECKeyAddress() { - String spongyPubkey = - "040947751e3022ecf3016be03ec77ab0ce3c2662b4843898cb068d74f698ccc8ad75" - + "aa17564ae80a20bb044ee7a6d903e8e8df624b089c95d66a0570f051e5a05b"; - String spongyAddress = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826"; + String spongyPubkey = "04e90c7d3640a1568839c31b70a893ab6714ef8415b9de90cedfc1c8f353a6983e625529" + + "392df7fa514bdd65a2003f6619567d79bee89830e63e932dbd42362d34"; + String spongyAddress = "2e988a386a799f506693793c6a5af6b54dfaabfb"; ECKey key = ECKey.fromPrivate(privateKey); byte[] pubkey = key.getPubKey(); assertEquals(spongyPubkey, Hex.toHexString(pubkey)); @@ -71,7 +72,7 @@ public void testECKeyAddress() { public void testECKeySignature() throws SignatureException { SignInterface sign = SignUtils.fromPrivate(Hex.decode(privString), true); String msg = "transaction raw data"; - String spongyAddress = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826"; + String spongyAddress = "2e988a386a799f506693793c6a5af6b54dfaabfb"; byte[] hash = Sha256Hash.hash(true, msg.getBytes()); String sig = sign.signHash(hash); byte[] address = SignUtils.signatureToAddress(hash, sig, true); @@ -102,9 +103,9 @@ public void testSM3Hash() { @Test public void testSM2Address() { - String spongyPublickey = "04f9539070c135be6183cbff4539f8298755df5981022769cd16cfdcb917fa7e32" - + "4e83b50f0bdbb34acd6ccbb78d45a8a383403f26bbd03805a178c43407dfdeae"; - String spongyAddress = "7dc44d739a5226c0d3037bb7919f653eb2f938b9"; + String spongyPublickey = "04dc3547dbbc4c90a9cde599848e26cb145e805b3d11daaf9daae0680d9c6824058ac" + + "35ddecb12f3a8bbc3104a2b91a2b7d04851d773d9b4ab8d5e0359243c8628"; + String spongyAddress = "6cb22f88564bdd61eb4cdb36215add53bc702ff1"; SM2 key = SM2.fromPrivate(privateKey); assertEquals(spongyPublickey, Hex.toHexString(key.getPubKey())); byte[] address = key.getAddress(); @@ -115,7 +116,7 @@ public void testSM2Address() { public void testSM2Signature() throws SignatureException { SignInterface sign = SignUtils.fromPrivate(Hex.decode(privString), false); String msg = "transaction raw data"; - String spongyAddress = "7dc44d739a5226c0d3037bb7919f653eb2f938b9"; + String spongyAddress = "6cb22f88564bdd61eb4cdb36215add53bc702ff1"; byte[] hash = Sha256Hash.hash(false, msg.getBytes()); String sig = sign.signHash(hash); byte[] address = SignUtils.signatureToAddress(hash, sig, false); diff --git a/framework/src/test/java/org/tron/common/crypto/ECKeyTest.java b/framework/src/test/java/org/tron/common/crypto/ECKeyTest.java index bf268f14320..4e7d45ee8d7 100644 --- a/framework/src/test/java/org/tron/common/crypto/ECKeyTest.java +++ b/framework/src/test/java/org/tron/common/crypto/ECKeyTest.java @@ -7,6 +7,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.tron.common.utils.client.utils.AbiUtil.generateOccupationConstantPrivateKey; import java.math.BigInteger; import java.security.KeyPairGenerator; @@ -27,16 +28,17 @@ @Slf4j public class ECKeyTest { - private String privString = "c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4"; + // For safety reasons, test with a placeholder private key + private String privString = generateOccupationConstantPrivateKey(); private BigInteger privateKey = new BigInteger(privString, 16); - private String pubString = "040947751e3022ecf3016be03ec77ab0ce3c2662b4843898cb068d74f698ccc" - + "8ad75aa17564ae80a20bb044ee7a6d903e8e8df624b089c95d66a0570f051e5a05b"; + private String pubString = "04e90c7d3640a1568839c31b70a893ab6714ef8415b9de90cedfc1c8f353a6983e62" + + "5529392df7fa514bdd65a2003f6619567d79bee89830e63e932dbd42362d34"; private String compressedPubString = - "030947751e3022ecf3016be03ec77ab0ce3c2662b4843898cb068d74f6" + "98ccc8ad"; + "02e90c7d3640a1568839c31b70a893ab6714ef8415b9de90cedfc1c8f353a6983e"; private byte[] pubKey = Hex.decode(pubString); private byte[] compressedPubKey = Hex.decode(compressedPubString); - private String address = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826"; + private String address = "2e988a386a799f506693793c6a5af6b54dfaabfb"; String eventSign = "eventBytesL(address,bytes,bytes32,uint256,string)"; @Test @@ -46,7 +48,7 @@ public void testSha3() { @Test public void testHashCode() { - assertEquals(-351262686, ECKey.fromPrivate(privateKey).hashCode()); + assertEquals(-827927068, ECKey.fromPrivate(privateKey).hashCode()); } @Test diff --git a/framework/src/test/java/org/tron/common/crypto/SM2KeyTest.java b/framework/src/test/java/org/tron/common/crypto/SM2KeyTest.java index 62e800679c1..b84026d2085 100644 --- a/framework/src/test/java/org/tron/common/crypto/SM2KeyTest.java +++ b/framework/src/test/java/org/tron/common/crypto/SM2KeyTest.java @@ -6,6 +6,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.tron.common.utils.client.utils.AbiUtil.generateOccupationConstantPrivateKey; import java.math.BigInteger; import java.security.KeyPairGenerator; @@ -30,19 +31,20 @@ public class SM2KeyTest { //private String IDa = "ALICE123@YAHOO.COM"; private static BigInteger SM2_N = new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6" + "B21C6052B53BBF40939D54123", 16); - private String privString = "128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263"; + // For safety reasons, test with a placeholder private key + private String privString = generateOccupationConstantPrivateKey(); private BigInteger privateKey = new BigInteger(privString, 16); - private String pubString = "04d5548c7825cbb56150a3506cd57464af8a1ae0519dfaf3c58221dc810caf28d" - + "d921073768fe3d59ce54e79a49445cf73fed23086537027264d168946d479533e"; + private String pubString = "04dc3547dbbc4c90a9cde599848e26cb145e805b3d11daaf9daae0680d9c6824058ac" + + "35ddecb12f3a8bbc3104a2b91a2b7d04851d773d9b4ab8d5e0359243c8628"; private String compressedPubString = - "02d5548c7825cbb56150a3506cd57464af8a1ae0519dfaf3c58221dc810caf28dd"; + "02dc3547dbbc4c90a9cde599848e26cb145e805b3d11daaf9daae0680d9c682405"; private byte[] pubKey = Hex.decode(pubString); private byte[] compressedPubKey = Hex.decode(compressedPubString); - private String address = "62e49e4c2f4e3c0653a02f8859c1e6991b759e87"; + private String address = "6cb22f88564bdd61eb4cdb36215add53bc702ff1"; @Test public void testHashCode() { - assertEquals(1126288006, SM2.fromPrivate(privateKey).hashCode()); + assertEquals(578690511, SM2.fromPrivate(privateKey).hashCode()); } @Test @@ -114,7 +116,7 @@ public void testSM3Hash() { SM2Signer signer = key.getSM2SignerForHash(); String message = "message digest"; byte[] hash = signer.generateSM3Hash(message.getBytes()); - assertEquals("299C7DDB0D8DD2A85381BACBB92F738F390210A493A144C78E18C67B430DA882", + assertEquals("2A723761EAE35429DF643648FD69FB7787E7FC32F321BFAF7E294390F529BAF4", Hex.toHexString(hash).toUpperCase()); } diff --git a/framework/src/test/java/org/tron/common/utils/client/utils/AbiUtil.java b/framework/src/test/java/org/tron/common/utils/client/utils/AbiUtil.java index 976490b8c80..7f00431ed0a 100644 --- a/framework/src/test/java/org/tron/common/utils/client/utils/AbiUtil.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/AbiUtil.java @@ -238,6 +238,16 @@ public static byte[] encodeInput(String methodSign, String input) { return pack(coders, items); } + public static String generateOccupationConstantPrivateKey() { + StringBuilder privateKey = new StringBuilder(); + String baseKey = "1234567890"; + for (int i = 0; i < 6; i++) { + privateKey.append(baseKey); + } + privateKey.append("1234"); + return privateKey.toString(); + } + public static void main(String[] args) { String method = "test(string,int2,string)"; String params = "asdf,3123,adf"; diff --git a/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java index 17e9d3ac887..7065608f188 100644 --- a/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java @@ -26,48 +26,11 @@ public class TransactionCapsuleTest extends BaseTest { private static String OWNER_ADDRESS; - /*private static String OWNER_KEY = - "bfa67cb3dc6609b3a0c98e717d66f38ed1a159b5b3421678dfab85961c40de2f"; - private static String TO_ADDRESS; - private static String OWNER_ACCOUNT_NOT_Exist; - private static String KEY_11 = "1111111111111111111111111111111111111111111111111111111111111111"; - private static String KEY_12 = "1212121212121212121212121212121212121212121212121212121212121212"; - private static String KEY_13 = "1313131313131313131313131313131313131313131313131313131313131313"; - private static String KEY_21 = "2121212121212121212121212121212121212121212121212121212121212121"; - private static String KEY_22 = "2222222222222222222222222222222222222222222222222222222222222222"; - private static String KEY_23 = "2323232323232323232323232323232323232323232323232323232323232323"; - private static String KEY_31 = "3131313131313131313131313131313131313131313131313131313131313131"; - private static String KEY_32 = "3232323232323232323232323232323232323232323232323232323232323232"; - private static String KEY_33 = "3333333333333333333333333333333333333333333333333333333333333333"; - - private static String KEY_ADDRESS_11; - private static String KEY_ADDRESS_12; - private static String KEY_ADDRESS_13; - private static String KEY_ADDRESS_21; - private static String KEY_ADDRESS_22; - private static String KEY_ADDRESS_23; - private static String KEY_ADDRESS_31; - private static String KEY_ADDRESS_32; - private static String KEY_ADDRESS_33;*/ @BeforeClass public static void init() { Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "03702350064AD5C1A8AA6B4D74B051199CFF8EA7"; - /*TO_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; - OWNER_ACCOUNT_NOT_Exist = - Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a3456"; - KEY_ADDRESS_11 = Wallet.getAddressPreFixString() + "19E7E376E7C213B7E7E7E46CC70A5DD086DAFF2A"; - KEY_ADDRESS_12 = Wallet.getAddressPreFixString() + "1C5A77D9FA7EF466951B2F01F724BCA3A5820B63"; - KEY_ADDRESS_13 = Wallet.getAddressPreFixString() + "03A1BBA60B5AA37094CF16123ADD674C01589488"; - - KEY_ADDRESS_21 = Wallet.getAddressPreFixString() + "2BD0C9FE079C8FCA0E3352EB3D02839C371E5C41"; - KEY_ADDRESS_22 = Wallet.getAddressPreFixString() + "1563915E194D8CFBA1943570603F7606A3115508"; - KEY_ADDRESS_23 = Wallet.getAddressPreFixString() + "D3E442496EB66A4748912EC4A3B7A111D0B855D6"; - - KEY_ADDRESS_31 = Wallet.getAddressPreFixString() + "77952CE83CA3CAD9F7ADCFABEDA85BD2F1F52008"; - KEY_ADDRESS_32 = Wallet.getAddressPreFixString() + "94622CC2A5B64A58C25A129D48A2BEEC4B65B779"; - KEY_ADDRESS_33 = Wallet.getAddressPreFixString() + "5CBDD86A2FA8DC4BDDD8A8F69DBA48572EEC07FB";*/ } /** @@ -80,984 +43,6 @@ public void createAccountCapsule() { dbManager.getAccountStore().put(ownerCapsule.createDbKey(), ownerCapsule); } - /*@Test - public void getDefaultPermission() { - String[] names = {"active", "owner", "other"}; - ByteString address = ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)); - for (String name : names) { - Permission permission = TransactionCapsule - .getDefaultPermission(address, name); - Assert.assertEquals(permission.getName(), name); - Assert.assertEquals(permission.getThreshold(), 1); - if ("owner".equalsIgnoreCase(name)) { - Assert.assertEquals(permission.getParent(), ""); - } else { - Assert.assertEquals(permission.getParent(), "owner"); - } - Assert.assertEquals(permission.getKeysCount(), 1); - Key key = permission.getKeys(0); - Assert.assertEquals(key.getAddress(), address); - Assert.assertEquals(key.getWeight(), 1); - } - } - - public TransferContract createTransferContract(byte[] to, byte[] owner, long amount) { - TransferContract.Builder builder = TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - return builder.build(); - } - - public PermissionAddKeyContract createPermissionAddKeyContract(byte[] owner, String name, - byte[] address, int weight) { - PermissionAddKeyContract.Builder contractBuilder = PermissionAddKeyContract.newBuilder(); - contractBuilder.setOwnerAddress(ByteString.copyFrom(owner)); - contractBuilder.setPermissionName(name); - Key.Builder keyBuilder = Key.newBuilder(); - keyBuilder.setAddress(ByteString.copyFrom(address)); - keyBuilder.setWeight(weight); - contractBuilder.setKey(keyBuilder.build()); - return contractBuilder.build(); - } - - public void updatePermission(List permissions, byte[] address) { - Account account = dbManager.getAccountStore().get(address).getInstance(); - Account.Builder builder = account.toBuilder(); - for (Permission permission : permissions) { - builder.addPermissions(permission); - } - dbManager.getAccountStore().put(address, new AccountCapsule(builder.build())); - } - - public List buildPermissions() { - Permission.Builder builder1 = Permission.newBuilder(); - Key.Builder key11 = Key.newBuilder(); - Key.Builder key12 = Key.newBuilder(); - Key.Builder key13 = Key.newBuilder(); - key11.setAddress(ByteString.copyFrom(ByteArray.fromHexString(KEY_ADDRESS_11))).setWeight(1); - key12.setAddress(ByteString.copyFrom(ByteArray.fromHexString(KEY_ADDRESS_12))).setWeight(1); - key13.setAddress(ByteString.copyFrom(ByteArray.fromHexString(KEY_ADDRESS_13))).setWeight(1); - builder1.setName("owner").setThreshold(2).setParent("").addKeys(key11).addKeys(key12) - .addKeys(key13); - Permission.Builder builder2 = Permission.newBuilder(); - Key.Builder key21 = Key.newBuilder(); - Key.Builder key22 = Key.newBuilder(); - Key.Builder key23 = Key.newBuilder(); - key21.setAddress(ByteString.copyFrom(ByteArray.fromHexString(KEY_ADDRESS_21))).setWeight(1); - key22.setAddress(ByteString.copyFrom(ByteArray.fromHexString(KEY_ADDRESS_22))).setWeight(1); - key23.setAddress(ByteString.copyFrom(ByteArray.fromHexString(KEY_ADDRESS_23))).setWeight(1); - builder2.setName("active").setThreshold(2).setParent("").addKeys(key21).addKeys(key22) - .addKeys(key23); - Permission.Builder builder3 = Permission.newBuilder(); - Key.Builder key31 = Key.newBuilder(); - Key.Builder key32 = Key.newBuilder(); - Key.Builder key33 = Key.newBuilder(); - key31.setAddress(ByteString.copyFrom(ByteArray.fromHexString(KEY_ADDRESS_31))).setWeight(1); - key32.setAddress(ByteString.copyFrom(ByteArray.fromHexString(KEY_ADDRESS_32))).setWeight(1); - key33.setAddress(ByteString.copyFrom(ByteArray.fromHexString(KEY_ADDRESS_33))).setWeight(1); - builder3.setName("other").setThreshold(2).setParent("").addKeys(key31).addKeys(key32) - .addKeys(key33); - List list = new ArrayList<>(); - list.add(builder1.build()); - list.add(builder2.build()); - list.add(builder3.build()); - return list; - } - - @Test - public void getPermission() { - //Default "active" permission - byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); - Account account = dbManager.getAccountStore().get(owner).getInstance(); - try { - Permission permission = TransactionCapsule.getPermission(account, "active"); - Permission permission1 = TransactionCapsule - .getDefaultPermission(ByteString.copyFrom(owner), "active"); - Assert.assertEquals(permission, permission1); - } catch (PermissionException e) { - Assert.assertFalse(true); - } - //Default "owner" permission - try { - Permission permission = TransactionCapsule.getPermission(account, "owner"); - Permission permission1 = TransactionCapsule - .getDefaultPermission(ByteString.copyFrom(owner), "owner"); - Assert.assertEquals(permission, permission1); - } catch (PermissionException e) { - Assert.assertFalse(true); - } - //Add 3 permission : owner active other - List permissions = buildPermissions(); - updatePermission(permissions, owner); - Permission permission1 = permissions.get(0); - Permission permission2 = permissions.get(1); - account = dbManager.getAccountStore().get(owner).getInstance(); - try { - Permission permission = TransactionCapsule.getPermission(account, "owner"); - Assert.assertEquals(permission, permission1); - } catch (PermissionException e) { - Assert.assertFalse(true); - } - - try { - Permission permission = TransactionCapsule.getPermission(account, "active"); - Assert.assertEquals(permission, permission2); - } catch (PermissionException e) { - Assert.assertFalse(true); - } - } - - @Test - public void getWeight() { - List permissions = buildPermissions(); - Permission permission1 = permissions.get(0); - Permission permission2 = permissions.get(1); - Permission permission3 = permissions.get(2); - Assert.assertEquals(1, - TransactionCapsule.getWeight(permission1, ByteArray.fromHexString(KEY_ADDRESS_11))); - Assert.assertEquals(1, - TransactionCapsule.getWeight(permission1, ByteArray.fromHexString(KEY_ADDRESS_12))); - Assert.assertEquals(1, - TransactionCapsule.getWeight(permission1, ByteArray.fromHexString(KEY_ADDRESS_13))); - Assert.assertEquals(0, - TransactionCapsule.getWeight(permission1, ByteArray.fromHexString(KEY_ADDRESS_21))); - Assert.assertEquals(0, - TransactionCapsule.getWeight(permission1, ByteArray.fromHexString(KEY_ADDRESS_22))); - Assert.assertEquals(0, - TransactionCapsule.getWeight(permission1, ByteArray.fromHexString(KEY_ADDRESS_23))); - Assert.assertEquals(0, - TransactionCapsule.getWeight(permission1, ByteArray.fromHexString(KEY_ADDRESS_31))); - Assert.assertEquals(0, - TransactionCapsule.getWeight(permission1, ByteArray.fromHexString(KEY_ADDRESS_32))); - Assert.assertEquals(0, - TransactionCapsule.getWeight(permission1, ByteArray.fromHexString(KEY_ADDRESS_33))); - - Assert.assertEquals(0, - TransactionCapsule.getWeight(permission2, ByteArray.fromHexString(KEY_ADDRESS_11))); - Assert.assertEquals(0, - TransactionCapsule.getWeight(permission2, ByteArray.fromHexString(KEY_ADDRESS_12))); - Assert.assertEquals(0, - TransactionCapsule.getWeight(permission2, ByteArray.fromHexString(KEY_ADDRESS_13))); - Assert.assertEquals(1, - TransactionCapsule.getWeight(permission2, ByteArray.fromHexString(KEY_ADDRESS_21))); - Assert.assertEquals(1, - TransactionCapsule.getWeight(permission2, ByteArray.fromHexString(KEY_ADDRESS_22))); - Assert.assertEquals(1, - TransactionCapsule.getWeight(permission2, ByteArray.fromHexString(KEY_ADDRESS_23))); - Assert.assertEquals(0, - TransactionCapsule.getWeight(permission2, ByteArray.fromHexString(KEY_ADDRESS_31))); - Assert.assertEquals(0, - TransactionCapsule.getWeight(permission2, ByteArray.fromHexString(KEY_ADDRESS_32))); - Assert.assertEquals(0, - TransactionCapsule.getWeight(permission2, ByteArray.fromHexString(KEY_ADDRESS_33))); - - Assert.assertEquals(0, - TransactionCapsule.getWeight(permission3, ByteArray.fromHexString(KEY_ADDRESS_11))); - Assert.assertEquals(0, - TransactionCapsule.getWeight(permission3, ByteArray.fromHexString(KEY_ADDRESS_12))); - Assert.assertEquals(0, - TransactionCapsule.getWeight(permission3, ByteArray.fromHexString(KEY_ADDRESS_13))); - Assert.assertEquals(0, - TransactionCapsule.getWeight(permission3, ByteArray.fromHexString(KEY_ADDRESS_21))); - Assert.assertEquals(0, - TransactionCapsule.getWeight(permission3, ByteArray.fromHexString(KEY_ADDRESS_22))); - Assert.assertEquals(0, - TransactionCapsule.getWeight(permission3, ByteArray.fromHexString(KEY_ADDRESS_23))); - Assert.assertEquals(1, - TransactionCapsule.getWeight(permission3, ByteArray.fromHexString(KEY_ADDRESS_31))); - Assert.assertEquals(1, - TransactionCapsule.getWeight(permission3, ByteArray.fromHexString(KEY_ADDRESS_32))); - Assert.assertEquals(1, - TransactionCapsule.getWeight(permission3, ByteArray.fromHexString(KEY_ADDRESS_33))); - } - - public ArrayList sign(List priKeys, byte[] hash) { - ArrayList list = new ArrayList<>(); - for (byte[] priKey : priKeys) { - ECKey ecKey = ECKey.fromPrivate(priKey); - ECDSASignature signature = ecKey.sign(hash); - ByteString result = ByteString.copyFrom(signature.toByteArray()); - list.add(result); - } - return list; - } - - @Test - public void checkWeight() { - List permissions = buildPermissions(); - Permission permission = permissions.get(0); - byte[] hash = Sha256Hash.hash("test".getBytes()); - - //SignatureFormatException - ArrayList list = new ArrayList<>(); - ByteString test = ByteString.copyFromUtf8("test"); - list.add(test); - try { - TransactionCapsule.checkWeight(permission, list, hash, null); - Assert.assertFalse(true); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertEquals(e.getMessage(), "Signature size is " + test.size()); - } - //SignatureException: Header byte out of range: - //Ignore more exception case. - byte[] rand = new byte[65]; - new Random().nextBytes(rand); - rand[64] = 8; // v = 8 < 27 v += 35 > 35 - try { - ArrayList list1 = new ArrayList<>(); - list1.add(ByteString.copyFrom(rand)); - TransactionCapsule.checkWeight(permission, list1, hash, null); - Assert.assertFalse(true); - } catch (SignatureException e) { - Assert.assertEquals(e.getMessage(), "Header byte out of range: 35"); - } catch (PermissionException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - //Permission does not contain KEY - List prikeys = new ArrayList<>(); - prikeys.add(ByteArray.fromHexString(KEY_11)); - prikeys.add(ByteArray.fromHexString(KEY_21)); - ArrayList sign11_21 = sign(prikeys, hash); - try { - TransactionCapsule.checkWeight(permission, sign11_21, hash, null); - Assert.assertFalse(true); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (PermissionException e) { - ByteString sign21 = sign11_21.get(1); - Assert.assertEquals(e.getMessage(), - ByteArray.toHexString(sign21.toByteArray()) + " is signed by " + Wallet - .encode58Check(ByteArray.fromHexString(KEY_ADDRESS_21)) - + " but it is not contained of permission."); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - //Too many signature - prikeys.add(ByteArray.fromHexString(KEY_12)); - prikeys.add(ByteArray.fromHexString(KEY_13)); - ArrayList sign11_21_12_13 = sign(prikeys, hash); - try { - TransactionCapsule.checkWeight(permission, sign11_21_12_13, hash, null); - Assert.assertFalse(true); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertEquals(e.getMessage(), - "Signature count is " + prikeys.size() + " more than key counts of permission : " - + permission.getKeysCount()); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - - //Sign twice by same key - prikeys = new ArrayList<>(); - prikeys.add(ByteArray.fromHexString(KEY_11)); - prikeys.add(ByteArray.fromHexString(KEY_12)); - prikeys.add(ByteArray.fromHexString(KEY_11)); - ArrayList sign11_12_11 = sign(prikeys, hash); - try { - TransactionCapsule.checkWeight(permission, sign11_12_11, hash, null); - Assert.assertFalse(true); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertEquals(e.getMessage(), - WalletUtil.encode58Check(ByteArray.fromHexString(KEY_ADDRESS_11)) + " has signed twice!"); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - - // - prikeys = new ArrayList<>(); - List approveList = new ArrayList<>(); - prikeys.add(ByteArray.fromHexString(KEY_11)); - ArrayList sign11 = sign(prikeys, hash); - try { - long weight = TransactionCapsule.checkWeight(permission, sign11, hash, approveList); - Assert.assertEquals(weight, 1); - Assert.assertEquals(approveList.size(), 1); - Assert.assertEquals(approveList.get(0), - ByteString.copyFrom(ByteArray.fromHexString(KEY_ADDRESS_11))); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - - approveList = new ArrayList<>(); - prikeys.add(ByteArray.fromHexString(KEY_12)); - ArrayList sign11_12 = sign(prikeys, hash); - try { - long weight = TransactionCapsule.checkWeight(permission, sign11_12, hash, approveList); - Assert.assertEquals(weight, 2); - Assert.assertEquals(approveList.size(), 2); - Assert.assertEquals(approveList.get(0), - ByteString.copyFrom(ByteArray.fromHexString(KEY_ADDRESS_11))); - Assert.assertEquals(approveList.get(1), - ByteString.copyFrom(ByteArray.fromHexString(KEY_ADDRESS_12))); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - - approveList = new ArrayList<>(); - prikeys.add(ByteArray.fromHexString(KEY_13)); - ArrayList sign11_12_13 = sign(prikeys, hash); - try { - long weight = TransactionCapsule.checkWeight(permission, sign11_12_13, hash, approveList); - Assert.assertEquals(weight, 3); - Assert.assertEquals(approveList.size(), 3); - Assert.assertEquals(approveList.get(0), - ByteString.copyFrom(ByteArray.fromHexString(KEY_ADDRESS_11))); - Assert.assertEquals(approveList.get(1), - ByteString.copyFrom(ByteArray.fromHexString(KEY_ADDRESS_12))); - Assert.assertEquals(approveList.get(2), - ByteString.copyFrom(ByteArray.fromHexString(KEY_ADDRESS_13))); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - } - - @Test - public void addSign() { - - byte[] to = ByteArray.fromHexString(TO_ADDRESS); - byte[] owner_not_exist = ByteArray.fromHexString(OWNER_ACCOUNT_NOT_Exist); - TransferContract transferContract = createTransferContract(to, owner_not_exist, 1); - Transaction.Builder trxBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = Transaction.raw.newBuilder(); - Contract.Builder contractBuilder = Contract.newBuilder(); - contractBuilder.setType(ContractType.TransferContract).setParameter(Any.pack(transferContract)) - .build(); - rawBuilder.addContract(contractBuilder); - trxBuilder.setRawData(rawBuilder); - AccountStore accountStore = dbManager.getAccountStore(); - TransactionCapsule transactionCapsule = new TransactionCapsule(trxBuilder.build()); - //Accout not exist - try { - transactionCapsule.addSign(ByteArray.fromHexString(KEY_11), accountStore); - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertEquals(e.getMessage(), "Account is not exist!"); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - - byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); - transferContract = createTransferContract(to, owner, 1); - transactionCapsule = new TransactionCapsule(transferContract, accountStore); - //Defalut permission - try { - transactionCapsule.addSign(ByteArray.fromHexString(KEY_11), accountStore); - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertEquals(e.getMessage(), - KEY_11 + "'s address is " + WalletUtil - .encode58Check(ByteArray.fromHexString(KEY_ADDRESS_11)) - + " but it is not contained of permission."); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - - try { - transactionCapsule.addSign(ByteArray.fromHexString(OWNER_KEY), accountStore); - Assert.assertEquals(transactionCapsule.getInstance().getSignatureCount(), 1); - ByteString signature = transactionCapsule.getInstance().getSignature(0); - Assert.assertEquals(signature.size(), 65); - byte[] sign = signature.toByteArray(); - byte[] r = ByteArray.subArray(sign, 0, 32); - byte[] s = ByteArray.subArray(sign, 32, 64); - byte v = sign[64]; - ECDSASignature ecdsaSignature = ECDSASignature.fromComponents(r, s, (byte) (v + 27)); - byte[] address = ECKey - .signatureToAddress(transactionCapsule.getTransactionId().getBytes(), ecdsaSignature); - Assert.assertTrue(Arrays.equals(address, ByteArray.fromHexString(OWNER_ADDRESS))); - } catch (PermissionException e) { - Assert.assertFalse(true); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - // Sign twice - try { - transactionCapsule.addSign(ByteArray.fromHexString(OWNER_KEY), accountStore); - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertEquals(e.getMessage(), - WalletUtil.encode58Check(ByteArray.fromHexString(OWNER_ADDRESS)) + " had signed!"); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - //Update permission, can signed by key21 key22 key23 - List permissions = buildPermissions(); - Account account = accountStore.get(ByteArray.fromHexString(OWNER_ADDRESS)).getInstance(); - Account.Builder builder = account.toBuilder(); - builder.addPermissions(permissions.get(0)); - builder.addPermissions(permissions.get(1)); - builder.addPermissions(permissions.get(2)); - accountStore.put(ByteArray.fromHexString(OWNER_ADDRESS), new AccountCapsule(builder.build())); - - transactionCapsule = new TransactionCapsule(transferContract, accountStore); - try { - transactionCapsule.addSign(ByteArray.fromHexString(OWNER_KEY), accountStore); - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertEquals(e.getMessage(), - OWNER_KEY + "'s address is " + Wallet - .encode58Check(ByteArray.fromHexString(OWNER_ADDRESS)) - + " but it is not contained of permission."); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - //Sign KEY_21 - try { - transactionCapsule.addSign(ByteArray.fromHexString(KEY_21), accountStore); - Assert.assertEquals(transactionCapsule.getInstance().getSignatureCount(), 1); - ByteString signature = transactionCapsule.getInstance().getSignature(0); - Assert.assertEquals(signature.size(), 65); - byte[] sign = signature.toByteArray(); - byte[] r = ByteArray.subArray(sign, 0, 32); - byte[] s = ByteArray.subArray(sign, 32, 64); - byte v = sign[64]; - ECDSASignature ecdsaSignature = ECDSASignature.fromComponents(r, s, (byte) (v + 27)); - byte[] address = ECKey - .signatureToAddress(transactionCapsule.getTransactionId().getBytes(), ecdsaSignature); - Assert.assertTrue(Arrays.equals(address, ByteArray.fromHexString(KEY_ADDRESS_21))); - } catch (PermissionException e) { - Assert.assertFalse(true); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - //Sign KEY_12 - try { - transactionCapsule.addSign(ByteArray.fromHexString(KEY_22), accountStore); - Assert.assertEquals(transactionCapsule.getInstance().getSignatureCount(), 2); - ByteString signature = transactionCapsule.getInstance().getSignature(0); - Assert.assertEquals(signature.size(), 65); - byte[] sign = signature.toByteArray(); - byte[] r21 = ByteArray.subArray(sign, 0, 32); - byte[] s21 = ByteArray.subArray(sign, 32, 64); - byte v21 = sign[64]; - ECDSASignature ecdsaSignature11 = ECDSASignature.fromComponents(r21, s21, (byte) (v21 + 27)); - byte[] address21 = ECKey - .signatureToAddress(transactionCapsule.getTransactionId().getBytes(), ecdsaSignature11); - Assert.assertTrue(Arrays.equals(address21, ByteArray.fromHexString(KEY_ADDRESS_21))); - - ByteString signature1 = transactionCapsule.getInstance().getSignature(1); - - byte[] r22 = ByteArray.subArray(signature1.toByteArray(), 0, 32); - byte[] s22 = ByteArray.subArray(signature1.toByteArray(), 32, 64); - byte v22 = signature1.toByteArray()[64]; - ECDSASignature ecdsaSignature12 = ECDSASignature.fromComponents(r22, s22, (byte) (v22 + 27)); - byte[] address22 = ECKey - .signatureToAddress(transactionCapsule.getTransactionId().getBytes(), ecdsaSignature12); - Assert.assertTrue(Arrays.equals(address22, ByteArray.fromHexString(KEY_ADDRESS_22))); - } catch (PermissionException e) { - Assert.assertFalse(true); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - //Sign KEY_23 - try { - transactionCapsule.addSign(ByteArray.fromHexString(KEY_23), accountStore); - Assert.assertEquals(transactionCapsule.getInstance().getSignatureCount(), 3); - ByteString signature = transactionCapsule.getInstance().getSignature(0); - Assert.assertEquals(signature.size(), 65); - byte[] sign = signature.toByteArray(); - byte[] r21 = ByteArray.subArray(sign, 0, 32); - byte[] s21 = ByteArray.subArray(sign, 32, 64); - byte v21 = sign[64]; - ECDSASignature ecdsaSignature21 = ECDSASignature.fromComponents(r21, s21, (byte) (v21 + 27)); - byte[] address21 = ECKey - .signatureToAddress(transactionCapsule.getTransactionId().getBytes(), ecdsaSignature21); - Assert.assertTrue(Arrays.equals(address21, ByteArray.fromHexString(KEY_ADDRESS_21))); - - ByteString signature1 = transactionCapsule.getInstance().getSignature(1); - Assert.assertEquals(signature1.size(), 65); - byte[] sign1 = signature1.toByteArray(); - byte[] r22 = ByteArray.subArray(sign1, 0, 32); - byte[] s22 = ByteArray.subArray(sign1, 32, 64); - byte v22 = sign1[64]; - ECDSASignature ecdsaSignature22 = ECDSASignature.fromComponents(r22, s22, (byte) (v22 + 27)); - byte[] address22 = ECKey - .signatureToAddress(transactionCapsule.getTransactionId().getBytes(), ecdsaSignature22); - Assert.assertTrue(Arrays.equals(address22, ByteArray.fromHexString(KEY_ADDRESS_22))); - - ByteString signature2 = transactionCapsule.getInstance().getSignature(2); - Assert.assertEquals(signature2.size(), 65); - byte[] sign2 = signature2.toByteArray(); - byte[] r23 = ByteArray.subArray(sign2, 0, 32); - byte[] s23 = ByteArray.subArray(sign2, 32, 64); - byte v23 = sign2[64]; - ECDSASignature ecdsaSignature23 = ECDSASignature.fromComponents(r23, s23, (byte) (v23 + 27)); - byte[] address23 = ECKey - .signatureToAddress(transactionCapsule.getTransactionId().getBytes(), ecdsaSignature23); - Assert.assertTrue(Arrays.equals(address23, ByteArray.fromHexString(KEY_ADDRESS_23))); - } catch (PermissionException e) { - Assert.assertFalse(true); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - //Sign KEY_11, throw exception - try { - transactionCapsule.addSign(ByteArray.fromHexString(KEY_11), accountStore); - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertEquals(e.getMessage(), - KEY_11 + "'s address is " + Wallet - .encode58Check(ByteArray.fromHexString(KEY_ADDRESS_11)) - + " but it is not contained of permission."); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - //invalidate signature - transactionCapsule = new TransactionCapsule(transferContract, accountStore); - Transaction.Builder builder1 = transactionCapsule.getInstance().toBuilder(); - builder1.addSignature(ByteString.copyFromUtf8("test")); - transactionCapsule = new TransactionCapsule(builder1.build()); - //Sign KEY_21, throw exception - try { - transactionCapsule.addSign(ByteArray.fromHexString(KEY_11), accountStore); - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertFalse(true); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertEquals(e.getMessage(), "Signature size is " + "test".length()); - } - - //invalidate signature - transactionCapsule = new TransactionCapsule(transferContract, accountStore); - builder1 = transactionCapsule.getInstance().toBuilder(); - builder1.addSignature(ByteString.copyFromUtf8("test")); - transactionCapsule = new TransactionCapsule(builder1.build()); - //Sign KEY_21, throw exception - try { - transactionCapsule.addSign(ByteArray.fromHexString(KEY_11), accountStore); - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertFalse(true); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertEquals(e.getMessage(), "Signature size is " + "test".length()); - } - //transaction already have a signature signed by a invalidate key - //that the key is not in the permission. - transactionCapsule = new TransactionCapsule(transferContract, accountStore); - List prikeys = new ArrayList<>(); - prikeys.add(ByteArray.fromHexString(KEY_11)); - ArrayList sign11 = sign(prikeys, transactionCapsule.getTransactionId().getBytes()); - builder1 = transactionCapsule.getInstance().toBuilder(); - builder1.addAllSignature(sign11); - transactionCapsule = new TransactionCapsule(builder1.build()); - - try { - transactionCapsule.addSign(ByteArray.fromHexString(KEY_21), accountStore); - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertEquals(e.getMessage(), - ByteArray.toHexString(sign11.get(0).toByteArray()) + " is signed by " + Wallet - .encode58Check(ByteArray.fromHexString(KEY_ADDRESS_11)) - + " but it is not contained of permission."); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - } - - @Test - // test public static boolean validateSignature(Transaction.Contract contract, - ByteString sigs, byte[] hash, AccountStore accountStore) - public void validateSignature0() { - //Update permission, can signed by key21 key22 key23 - AccountStore accountStore = dbManager.getAccountStore(); - List permissions = buildPermissions(); - - byte[] to = ByteArray.fromHexString(TO_ADDRESS); - byte[] owner_not_exist = ByteArray.fromHexString(OWNER_ACCOUNT_NOT_Exist); - TransferContract transferContract = createTransferContract(to, owner_not_exist, 1); - Transaction.Builder trxBuilder = Transaction - .newBuilder(); - Transaction.raw.Builder rawBuilder = Transaction.raw.newBuilder(); - Contract.Builder contractBuilder = Contract.newBuilder(); - contractBuilder.setType(ContractType.TransferContract).setParameter(Any.pack(transferContract)); - rawBuilder.addContract(contractBuilder.build()); - trxBuilder.setRawData(rawBuilder.build()); - List prikeys = new ArrayList<>(); - prikeys.add(ByteArray.fromHexString(KEY_21)); - ArrayList sign = sign(prikeys, Sha256Hash.hash(rawBuilder.build().toByteArray())); - trxBuilder.addAllSignature(sign); - - Account account = accountStore.get(ByteArray.fromHexString(OWNER_ADDRESS)).getInstance(); - Account.Builder builder = account.toBuilder(); - builder.clearPermissions(); - builder.addPermissions(permissions.get(0)); - builder.addPermissions(permissions.get(1)); - builder.addPermissions(permissions.get(2)); - accountStore.put(ByteArray.fromHexString(OWNER_ADDRESS), new AccountCapsule(builder.build())); - byte[] hash = Sha256Hash.hash("test".getBytes()); - - byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); - transferContract = createTransferContract(to, owner, 1); - contractBuilder = Contract.newBuilder(); - contractBuilder.setParameter(Any.pack(transferContract)).setType(ContractType.TransferContract); - rawBuilder.clearContract().addContract(contractBuilder.build()); - trxBuilder.setRawData(rawBuilder.build()); - - //SignatureFormatException - ByteString test = ByteString.copyFromUtf8("test"); - trxBuilder.clearSignature().addSignature(test); - try { - TransactionCapsule.validateSignature(trxBuilder.build(), hash, accountStore); - Assert.assertFalse(true); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertEquals(e.getMessage(), "Signature size is " + test.size()); - } - //SignatureException: Header byte out of range: - //Ignore more exception case. - byte[] rand = new byte[65]; - new Random().nextBytes(rand); - rand[64] = 8; // v = 8 < 27 v += 35 > 35 - trxBuilder.clearSignature().addSignature(ByteString.copyFrom(rand)); - try { - TransactionCapsule.validateSignature(trxBuilder.build(), hash, - accountStore); - Assert.assertFalse(true); - } catch (SignatureException e) { - Assert.assertEquals(e.getMessage(), "Header byte out of range: 35"); - } catch (PermissionException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - //Permission is not contain KEY - prikeys = new ArrayList<>(); - prikeys.clear(); - prikeys.add(ByteArray.fromHexString(KEY_21)); - prikeys.add(ByteArray.fromHexString(KEY_11)); - ArrayList sign21_11 = sign(prikeys, hash); - trxBuilder.clearSignature().addAllSignature(sign21_11); - try { - TransactionCapsule.validateSignature(trxBuilder.build(), hash, accountStore); - Assert.assertFalse(true); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (PermissionException e) { - ByteString sign21 = sign21_11.get(1); - Assert.assertEquals(e.getMessage(), - ByteArray.toHexString(sign21.toByteArray()) + " is signed by " + Wallet - .encode58Check(ByteArray.fromHexString(KEY_ADDRESS_11)) - + " but it is not contained of permission."); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - //Too many signature - prikeys.add(ByteArray.fromHexString(KEY_22)); - prikeys.add(ByteArray.fromHexString(KEY_23)); - ArrayList sign21_11_22_23 = sign(prikeys, hash); - trxBuilder.clearSignature().addAllSignature(sign21_11_22_23); - try { - TransactionCapsule - .validateSignature(trxBuilder.build(), hash, accountStore); - Assert.assertFalse(true); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertEquals(e.getMessage(), - "Signature count is " + prikeys.size() + " more than key counts of permission : " - + permissions.get(1).getKeysCount()); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - - //Sign twices by same key - prikeys = new ArrayList<>(); - prikeys.add(ByteArray.fromHexString(KEY_21)); - prikeys.add(ByteArray.fromHexString(KEY_22)); - prikeys.add(ByteArray.fromHexString(KEY_21)); - ArrayList sign21_22_21 = sign(prikeys, hash); - trxBuilder.clearSignature().addAllSignature(sign21_22_21); - try { - TransactionCapsule - .validateSignature(trxBuilder.build(), hash, accountStore); - Assert.assertFalse(true); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertEquals(e.getMessage(), - WalletUtil.encode58Check(ByteArray.fromHexString(KEY_ADDRESS_21)) + " has signed twice!"); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - - // - prikeys = new ArrayList<>(); - prikeys.add(ByteArray.fromHexString(KEY_21)); - ArrayList sign21 = sign(prikeys, hash); - trxBuilder.clearSignature().addAllSignature(sign21); - try { - boolean result = TransactionCapsule - .validateSignature(trxBuilder.build(), hash, accountStore); - Assert.assertFalse(result); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - - prikeys.add(ByteArray.fromHexString(KEY_22)); - ArrayList sign21_22 = sign(prikeys, hash); - trxBuilder.clearSignature().addAllSignature(sign21_22); - try { - boolean result = TransactionCapsule - .validateSignature(trxBuilder.build(), hash, accountStore); - Assert.assertTrue(result); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - - prikeys.add(ByteArray.fromHexString(KEY_23)); - ArrayList sign21_22_23 = sign(prikeys, hash); - trxBuilder.clearSignature().addAllSignature(sign21_22_23); - try { - boolean result = TransactionCapsule - .validateSignature(trxBuilder.build(), hash, accountStore); - Assert.assertTrue(result); - } catch (SignatureException e) { - Assert.assertFalse(true); - } catch (PermissionException e) { - Assert.assertFalse(true); - } catch (SignatureFormatException e) { - Assert.assertFalse(true); - } - } - - @Test - // test public boolean validateSignature(AccountStore accountStore) - public void validateSignature1() { - //Update permission, can signed by key21 key22 key23 - List permissions = buildPermissions(); - Account account = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)) - .getInstance(); - Account.Builder builder = account.toBuilder(); - builder.clearPermissions(); - builder.addPermissions(permissions.get(0)); - builder.addPermissions(permissions.get(1)); - builder.addPermissions(permissions.get(2)); - dbManager.getAccountStore() - .put(ByteArray.fromHexString(OWNER_ADDRESS), new AccountCapsule(builder.build())); - - byte[] to = ByteArray.fromHexString(TO_ADDRESS); - byte[] owner_not_exist = ByteArray.fromHexString(OWNER_ACCOUNT_NOT_Exist); - TransferContract transferContract = createTransferContract(to, owner_not_exist, 1); - Transaction.Builder trxBuilder = Transaction.newBuilder(); - Transaction.raw.Builder rawBuilder = Transaction.raw.newBuilder(); - Contract.Builder contractBuilder = Contract.newBuilder(); - contractBuilder.setType(ContractType.TransferContract).setParameter(Any.pack(transferContract)) - .build(); - rawBuilder.addContract(contractBuilder); - trxBuilder.setRawData(rawBuilder); - TransactionCapsule transactionCapsule = new TransactionCapsule(trxBuilder.build()); - List prikeys = new ArrayList<>(); - prikeys.add(ByteArray.fromHexString(KEY_21)); - ArrayList sign = sign(prikeys, Sha256Hash.hash(rawBuilder.build().toByteArray())); - trxBuilder.addAllSignature(sign); - transactionCapsule = new TransactionCapsule(trxBuilder.build()); - - // no contract - prikeys.clear(); - prikeys.add(ByteArray.fromHexString(KEY_21)); - trxBuilder = Transaction.newBuilder(); - rawBuilder = Transaction.raw.newBuilder(); - rawBuilder.setTimestamp(System.currentTimeMillis()); - trxBuilder.setRawData(rawBuilder); - sign = sign(prikeys, Sha256Hash.hash(rawBuilder.build().toByteArray())); - trxBuilder.addAllSignature(sign); - transactionCapsule = new TransactionCapsule(trxBuilder.build()); - try { - transactionCapsule.validateSignature(dbManager); - Assert.assertFalse(true); - } catch (ValidateSignatureException e) { - Assert.assertEquals(e.getMessage(), "miss sig or contract"); - } - // no sign - byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); - transferContract = createTransferContract(to, owner, 1); - transactionCapsule = new TransactionCapsule(transferContract, dbManager.getAccountStore()); - try { - transactionCapsule.validateSignature(dbManager); - Assert.assertFalse(true); - } catch (ValidateSignatureException e) { - Assert.assertEquals(e.getMessage(), "miss sig or contract"); - } - - transactionCapsule = new TransactionCapsule(transferContract, dbManager.getAccountStore()); - byte[] hash = transactionCapsule.getTransactionId().getBytes(); - trxBuilder = transactionCapsule.getInstance().toBuilder(); - //SignatureFormatException - ByteString test = ByteString.copyFromUtf8("test"); - trxBuilder.clearSignature(); - trxBuilder.addSignature(test); - transactionCapsule = new TransactionCapsule(trxBuilder.build()); - try { - transactionCapsule.validateSignature(dbManager); - Assert.assertFalse(true); - } catch (ValidateSignatureException e) { - Assert.assertEquals(e.getMessage(), "Signature size is " + test.size()); - } - //SignatureException: Header byte out of range: - //Ignore more exception case. - byte[] rand = new byte[65]; - new Random().nextBytes(rand); - rand[64] = 8; // v = 8 < 27 v += 35 > 35 - trxBuilder.clearSignature(); - trxBuilder.addSignature(ByteString.copyFrom(rand)); - transactionCapsule = new TransactionCapsule(trxBuilder.build()); - try { - transactionCapsule.validateSignature(dbManager); - Assert.assertFalse(true); - } catch (ValidateSignatureException e) { - Assert.assertEquals(e.getMessage(), "Header byte out of range: 35"); - } - //Permission is not contain KEY - prikeys.clear(); - prikeys.add(ByteArray.fromHexString(KEY_21)); - prikeys.add(ByteArray.fromHexString(KEY_11)); - ArrayList sign21_11 = sign(prikeys, hash); - trxBuilder.clearSignature(); - trxBuilder.addAllSignature(sign21_11); - transactionCapsule = new TransactionCapsule(trxBuilder.build()); - try { - transactionCapsule.validateSignature(dbManager); - Assert.assertFalse(true); - } catch (ValidateSignatureException e) { - ByteString sign21 = sign21_11.get(1); - Assert.assertEquals(e.getMessage(), - ByteArray.toHexString(sign21.toByteArray()) + " is signed by " + Wallet - .encode58Check(ByteArray.fromHexString(KEY_ADDRESS_11)) - + " but it is not contained of permission."); - } - //Too many signature - prikeys.add(ByteArray.fromHexString(KEY_22)); - prikeys.add(ByteArray.fromHexString(KEY_23)); - ArrayList sign21_11_22_23 = sign(prikeys, hash); - trxBuilder.clearSignature(); - trxBuilder.addAllSignature(sign21_11_22_23); - transactionCapsule = new TransactionCapsule(trxBuilder.build()); - try { - transactionCapsule.validateSignature(dbManager); - Assert.assertFalse(true); - } catch (ValidateSignatureException e) { - Assert.assertEquals(e.getMessage(), - "Signature count is " + prikeys.size() + " more than key counts of permission : " - + permissions.get(1).getKeysCount()); - } - - //Sign twices by same key - prikeys = new ArrayList<>(); - prikeys.add(ByteArray.fromHexString(KEY_21)); - prikeys.add(ByteArray.fromHexString(KEY_22)); - prikeys.add(ByteArray.fromHexString(KEY_21)); - ArrayList sign21_22_21 = sign(prikeys, hash); - trxBuilder.clearSignature(); - trxBuilder.addAllSignature(sign21_22_21); - transactionCapsule = new TransactionCapsule(trxBuilder.build()); - try { - transactionCapsule.validateSignature(dbManager); - Assert.assertFalse(true); - } catch (ValidateSignatureException e) { - Assert.assertEquals(e.getMessage(), - WalletUtil.encode58Check(ByteArray.fromHexString(KEY_ADDRESS_21)) + " has signed twice!"); - } - - // - prikeys = new ArrayList<>(); - prikeys.add(ByteArray.fromHexString(KEY_21)); - ArrayList sign21 = sign(prikeys, hash); - trxBuilder.clearSignature(); - trxBuilder.addAllSignature(sign21); - transactionCapsule = new TransactionCapsule(trxBuilder.build()); - try { - transactionCapsule.validateSignature(dbManager); - Assert.assertFalse(true); - } catch (ValidateSignatureException e) { - Assert.assertEquals(e.getMessage(), "sig error"); - } - - prikeys.add(ByteArray.fromHexString(KEY_22)); - ArrayList sign21_22 = sign(prikeys, hash); - trxBuilder.clearSignature(); - trxBuilder.addAllSignature(sign21_22); - transactionCapsule = new TransactionCapsule(trxBuilder.build()); - try { - boolean result = transactionCapsule.validateSignature(dbManager); - Assert.assertTrue(result); - } catch (ValidateSignatureException e) { - Assert.assertFalse(true); - } - - prikeys.add(ByteArray.fromHexString(KEY_23)); - ArrayList sign21_22_23 = sign(prikeys, hash); - trxBuilder.clearSignature(); - trxBuilder.addAllSignature(sign21_22_23); - transactionCapsule = new TransactionCapsule(trxBuilder.build()); - try { - boolean result = transactionCapsule.validateSignature(dbManager); - Assert.assertTrue(result); - } catch (ValidateSignatureException e) { - Assert.assertFalse(true); - } - }*/ - @Test public void trxCapsuleClearTest() { Transaction tx = Transaction.newBuilder() diff --git a/framework/src/test/java/org/tron/core/config/ConfigurationTest.java b/framework/src/test/java/org/tron/core/config/ConfigurationTest.java index 24a34dbcd0e..f3ca2da5312 100644 --- a/framework/src/test/java/org/tron/core/config/ConfigurationTest.java +++ b/framework/src/test/java/org/tron/core/config/ConfigurationTest.java @@ -17,7 +17,11 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.tron.common.utils.PublicMethod.getRandomPrivateKey; +import static org.tron.common.utils.client.utils.AbiUtil.generateOccupationConstantPrivateKey; +import static org.tron.core.Constant.ADD_PRE_FIX_STRING_MAINNET; import com.typesafe.config.Config; import java.lang.reflect.Field; @@ -46,13 +50,10 @@ public void resetSingleton() @Test public void testGetEcKey() { - ECKey key = ECKey.fromPrivate( - Hex.decode("1cd5a70741c6e583d2dd3c5f17231e608eb1e52437210d948c5085e141c2d830")); - - //log.debug("address = {}", ByteArray.toHexString(key.getOwnerAddress())); - - assertEquals(Wallet.getAddressPreFixString() + "125b6c87b3d67114b3873977888c34582f27bbb0", - ByteArray.toHexString(key.getAddress())); + ECKey key = ECKey.fromPrivate(Hex.decode(generateOccupationConstantPrivateKey())); + assertNotNull(key); + assertEquals("2e988a386a799f506693793c6a5af6b54dfaabfb", + ByteArray.toHexString(key.getAddress()).substring(2)); } @Test(expected = IllegalArgumentException.class) diff --git a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java index 157a7ba732f..94d7f38cd8a 100755 --- a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java @@ -1,5 +1,8 @@ package org.tron.core.zksnark; +import static org.tron.common.utils.PublicMethod.getHexAddressByPrivateKey; +import static org.tron.common.utils.PublicMethod.getRandomPrivateKey; + import com.google.common.primitives.Bytes; import com.google.protobuf.Any; import com.google.protobuf.ByteString; @@ -125,8 +128,8 @@ public class ShieldedReceiveTest extends BaseTest { static { Args.setParam(new String[]{"--output-directory", dbPath()}, "config-localtest.conf"); - ADDRESS_ONE_PRIVATE_KEY = PublicMethod.getRandomPrivateKey(); - FROM_ADDRESS = PublicMethod.getHexAddressByPrivateKey(ADDRESS_ONE_PRIVATE_KEY);; + ADDRESS_ONE_PRIVATE_KEY = getRandomPrivateKey(); + FROM_ADDRESS = getHexAddressByPrivateKey(ADDRESS_ONE_PRIVATE_KEY);; } /** @@ -2395,10 +2398,10 @@ public void testMemoNotEnough() throws ContractValidateException, TooBigTransact */ @Test public void pushSameSkAndScanAndSpend() throws Exception { - - byte[] privateKey = ByteArray - .fromHexString("f4df789d3210ac881cb900464dd30409453044d2777060a0c391cbdf4c6a4f57"); + List localPrivateKeys = Args.getLocalWitnesses().getPrivateKeys(); + byte[] privateKey = ByteArray.fromHexString(localPrivateKeys.get(0)); final ECKey ecKey = ECKey.fromPrivate(privateKey); + assert ecKey != null; byte[] witnessAddress = ecKey.getAddress(); WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(witnessAddress)); chainBaseManager.addWitness(ByteString.copyFrom(witnessAddress)); diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index 62337f02fc5..92179ec6b54 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -132,7 +132,7 @@ node { dnsDomain = "nodes1.example.org" # dns private key used to publish, required if publish is true, hex string of length 64 - dnsPrivate = "b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291" + dnsPrivate = "1234567890123456789012345678901234567890123456789012345678901234" # known dns urls to publish if publish is true, url format tree://{pubkey}@{domain}, default empty knownUrls = [ diff --git a/framework/src/test/resources/testng.conf b/framework/src/test/resources/testng.conf index 2e5b9a375e0..ea4f25ad87b 100644 --- a/framework/src/test/resources/testng.conf +++ b/framework/src/test/resources/testng.conf @@ -98,56 +98,16 @@ ethHttpsNode = { foundationAccount = { - key1 = FC8BF0238748587B9617EB6D15D47A66C0E07C1A1959033CF249C6532DC29FE6 - key2 = 6815B367FDDE637E53E9ADC8E69424E07724333C9A2B973CFA469975E20753FC - #Main_in_mock_foundationAccount_key - #key1 = 324a2052e491e99026442d81df4d2777292840c1b3949e20696c49096c6bacb8 - #key2 = 2925e186bb1e88988855f11ebf20ea3a6e19ed92328b0ffb576122e769d45b68 + } witness = { - key1 = 369F095838EB6EED45D4F6312AF962D5B9DE52927DA9F04174EE49F9AF54BC77 - key2 = 9FD8E129DE181EA44C6129F727A6871440169568ADE002943EAD0E7A16D8EDAC - key3 = 291C233A5A7660FB148BAE07FCBCF885224F2DF453239BD983F859E8E5AA4602 - key4 = 99676348CBF9501D07819BD4618ED885210CB5A03FEAF6BFF28F0AF8E1DE7DBE - key5 = FA090CFB9F3A6B00BE95FE185E82BBCFC4DA959CA6A795D275635ECF5D58466D - #replay env witness - #key1 = 0528dc17428585fc4dece68b79fa7912270a1fe8e85f244372f59eb7e8925e04 - #key2 = 553c7b0dee17d3f5b334925f5a90fe99fb0b93d47073d69ec33eead8459d171e - #key3 = 324a2052e491e99026442d81df4d2777292840c1b3949e20696c49096c6bacb8 - #key4 = ff5d867c4434ac17d264afc6696e15365832d5e8000f75733ebb336d66df148d - #key5 = 2925e186bb1e88988855f11ebf20ea3a6e19ed92328b0ffb576122e769d45b68 + } mainWitness = { - key1 = 22a6aca17f8ec257cc57e190902767d7fedf908bba920b4fbeaab8f158e0da17 - key2 = b6d8d3382c32d4d066c4f830a7e53c3da9ad8b9665dda4ca081b6cd4e807d09c - key3 = 03caf867c46aaf86d56aa446db80cb49305126b77bfaccfe57ab17bdb4993ccc - key4 = 763009595dd132aaf2d248999f2c6e7ba0acbbd9a9dfd88f7c2c158d97327645 - key5 = a21a3074d4d84685efaffcd7c04e3eccb541ec4c85f61c41a099cd598ad39825 - key6 = 541a2d585fcea7e9b1803df4eb49af0eb09f1fa2ce06aa5b8ed60ac95655d66d - key7 = 7d5a7396d6430edb7f66aa5736ef388f2bea862c9259de8ad8c2cfe080f6f5a0 - key8 = 7c4977817417495f4ca0c35ab3d5a25e247355d68f89f593f3fea2ab62c8644f - key9 = 4521c13f65cc9f5c1daa56923b8598d4015801ad28379675c64106f5f6afec30 - key10 = f33101ea976d90491dcb9669be568db8bbc1ad23d90be4dede094976b67d550e - key11 = 1bb32958909299db452d3c9bbfd15fd745160d63e4985357874ee57708435a00 - key12 = 29c91bd8b27c807d8dc2d2991aa0fbeafe7f54f4de9fac1e1684aa57242e3922 - key13 = 97317d4d68a0c5ce14e74ad04dfc7521f142f5c0f247b632c8f94c755bdbe669 - key14 = 1fe1d91bbe3ac4ac5dc9866c157ef7615ec248e3fd4f7d2b49b0428da5e046b2 - key15 = 7c37ef485e186e07952bcc8e30cd911a6cd9f2a847736c89132762fb67a42329 - key16 = bcc142d57d872cd2cc1235bca454f2efd5a87f612856c979cc5b45a7399272a8 - key17 = 6054824dc03546f903a06da1f405e72409379b83395d0bbb3d4563f56e828d52 - key18 = 87cc8832b1b4860c3c69994bbfcdae9b520e6ce40cbe2a90566e707a7e04fc70 - key19 = c96c92c8a5f68ffba2ced3f7cd4baa6b784838a366f62914efdc79c6c18cd7d0 - key20 = d29e34899a21dc801c2be88184bed29a66246b5d85f26e8c77922ee2403a1934 - key21 = dc51f31e4de187c1c2530d65fb8f2958dff4c37f8cea430ce98d254baae37564 - key22 = ff43b371d67439bb8b6fa6c4ff615c954682008343d4cb2583b19f50adbac90f - key23 = dbc78781ad27f3751358333412d5edc85b13e5eee129a1a77f7232baadafae0e - key24 = a79a37a3d868e66456d76b233cb894d664b75fd91861340f3843db05ab3a8c66 - key25 = a8107ea1c97c90cd4d84e79cd79d327def6362cc6fd498fc3d3766a6a71924f6 - key26 = b5076206430b2ca069ae2f4dc6f20dd0d74551559878990d1df12a723c228039 - key27 = 442513e2e801bc42d14d33b8148851dae756d08eeb48881a44e1b2002b3fb700 + } defaultParameter = { diff --git a/plugins/src/test/java/org/tron/plugins/DbLiteTest.java b/plugins/src/test/java/org/tron/plugins/DbLiteTest.java index 5cb8c26c4bc..a0ab366e9fc 100644 --- a/plugins/src/test/java/org/tron/plugins/DbLiteTest.java +++ b/plugins/src/test/java/org/tron/plugins/DbLiteTest.java @@ -1,5 +1,7 @@ package org.tron.plugins; +import static org.tron.common.utils.PublicMethod.getRandomPrivateKey; + import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.io.File; @@ -159,7 +161,7 @@ private void generateSomeTransactions(int during) { ECKey ecKey2 = new ECKey(Utils.getRandom()); byte[] address = ecKey2.getAddress(); - String sunPri = "cba92a516ea09f620a16ff7ee95ce0df1d56550a8babe9964981a7144c8a784a"; + String sunPri = getRandomPrivateKey(); byte[] sunAddress = PublicMethod.getFinalAddress(sunPri); PublicMethod.sendcoin(address, 1L, sunAddress, sunPri, blockingStubFull); From 0642903884e47fb0d988776a8ffd59a96c6133f2 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 8 Jan 2025 14:22:53 +0800 Subject: [PATCH 1112/1197] feat(exception): add TronError --- .../org/tron/core/exception/TronError.java | 56 +++++++++++++++++++ .../tron/core/exception/TronErrorTest.java | 19 +++++++ 2 files changed, 75 insertions(+) create mode 100644 common/src/main/java/org/tron/core/exception/TronError.java create mode 100644 framework/src/test/java/org/tron/core/exception/TronErrorTest.java diff --git a/common/src/main/java/org/tron/core/exception/TronError.java b/common/src/main/java/org/tron/core/exception/TronError.java new file mode 100644 index 00000000000..c7ddfc38bad --- /dev/null +++ b/common/src/main/java/org/tron/core/exception/TronError.java @@ -0,0 +1,56 @@ +package org.tron.core.exception; + +import lombok.Getter; + +/** + * If a {@link TronError} is thrown, the service will trigger {@link System#exit(int)} by + * {@link Thread#setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler)}. + * NOTE: Do not attempt to catch {@link TronError}. + */ +@Getter +public class TronError extends Error { + + private final ErrCode errCode; + + public TronError(String message, ErrCode exitCode) { + super(message); + this.errCode = exitCode; + } + + public TronError(String message, Throwable cause, ErrCode exitCode) { + super(message, cause); + this.errCode = exitCode; + } + + public TronError(Throwable cause, ErrCode exitCode) { + super(cause); + this.errCode = exitCode; + } + + @Getter + public enum ErrCode { + WITNESS_KEYSTORE_LOAD(-1), + CHECKPOINT_VERSION(-1), + LEVELDB_INIT(1), + ROCKSDB_INIT(1), + DB_FLUSH(1), + REWARD_VI_CALCULATOR(1), + KHAOS_DB_INIT(1), + GENESIS_BLOCK_INIT(1), + EVENT_SUBSCRIBE_ERROR(1), + AUTO_STOP_PARAMS(1), + API_SERVER_INIT(1), + SOLID_NODE_INIT(0); + + private final int code; + + ErrCode(int code) { + this.code = code; + } + + @Override + public String toString() { + return name() + "(" + code + ")"; + } + } +} diff --git a/framework/src/test/java/org/tron/core/exception/TronErrorTest.java b/framework/src/test/java/org/tron/core/exception/TronErrorTest.java new file mode 100644 index 00000000000..0ec1bcca349 --- /dev/null +++ b/framework/src/test/java/org/tron/core/exception/TronErrorTest.java @@ -0,0 +1,19 @@ +package org.tron.core.exception; + +import org.junit.Assert; +import org.junit.Test; + +public class TronErrorTest { + + @Test + public void testTronError() { + TronError tronError = new TronError("message", TronError.ErrCode.WITNESS_KEYSTORE_LOAD); + Assert.assertEquals(tronError.getErrCode(), TronError.ErrCode.WITNESS_KEYSTORE_LOAD); + Assert.assertEquals(tronError.getErrCode().toString(), "WITNESS_KEYSTORE_LOAD(-1)"); + Assert.assertEquals(tronError.getErrCode().getCode(), -1); + tronError = new TronError("message", new Throwable(), TronError.ErrCode.API_SERVER_INIT); + Assert.assertEquals(tronError.getErrCode(), TronError.ErrCode.API_SERVER_INIT); + tronError = new TronError(new Throwable(), TronError.ErrCode.LEVELDB_INIT); + Assert.assertEquals(tronError.getErrCode(), TronError.ErrCode.LEVELDB_INIT); + } +} From b57411fd827d3798180fb0cc9f2a5ff068b2b82d Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Thu, 6 Feb 2025 15:31:23 +0800 Subject: [PATCH 1113/1197] feat(transaction): optimize transactions during the consensus phase --- .../java/org/tron/core/ChainBaseManager.java | 9 +++++++ .../org/tron/core/db/BandwidthProcessor.java | 6 +++-- .../src/main/java/org/tron/core/Wallet.java | 2 +- .../main/java/org/tron/core/db/Manager.java | 8 ++++++- .../org/tron/core/net/TronNetDelegate.java | 8 ------- .../TransactionsMsgHandler.java | 5 +++- .../java/org/tron/core/db/ManagerTest.java | 24 +++++++++++++++++++ 7 files changed, 49 insertions(+), 13 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java index d148021f6c4..21f0bac8d77 100644 --- a/chainbase/src/main/java/org/tron/core/ChainBaseManager.java +++ b/chainbase/src/main/java/org/tron/core/ChainBaseManager.java @@ -380,6 +380,15 @@ public static synchronized void init(ChainBaseManager manager) { AssetUtil.setDynamicPropertiesStore(manager.getDynamicPropertiesStore()); } + public long getNextBlockSlotTime() { + long slotCount = 1; + if (dynamicPropertiesStore.getStateFlag() == 1) { + slotCount += dynamicPropertiesStore.getMaintenanceSkipSlots(); + } + return dynamicPropertiesStore.getLatestBlockHeaderTimestamp() + + slotCount * BLOCK_PRODUCED_INTERVAL; + } + @PostConstruct private void init() { this.lowestBlockNum = this.blockIndexStore.getLimitNumber(1, 1).stream() diff --git a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java index 3f0db86c537..73b9efaa35e 100644 --- a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -99,7 +99,9 @@ public void consume(TransactionCapsule trx, TransactionTrace trace) TooBigTransactionResultException, TooBigTransactionException { List contracts = trx.getInstance().getRawData().getContractList(); long resultSizeWithMaxContractRet = trx.getResultSizeWithMaxContractRet(); - if (!trx.isInBlock() && resultSizeWithMaxContractRet > + boolean optimizeTxs = !trx.isInBlock() || chainBaseManager + .getDynamicPropertiesStore().allowConsensusLogicOptimization(); + if (optimizeTxs && resultSizeWithMaxContractRet > Constant.MAX_RESULT_SIZE_IN_TX * contracts.size()) { throw new TooBigTransactionResultException(String.format( "Too big transaction result, TxId %s, the result size is %d bytes, maxResultSize %d", @@ -135,7 +137,7 @@ public void consume(TransactionCapsule trx, TransactionTrace trace) } long now = chainBaseManager.getHeadSlot(); if (contractCreateNewAccount(contract)) { - if (!trx.isInBlock()) { + if (optimizeTxs) { long maxCreateAccountTxSize = dynamicPropertiesStore.getMaxCreateAccountTxSize(); int signatureCount = trx.getInstance().getSignatureCount(); long createAccountBytesSize = trx.getInstance().toBuilder().clearRet() diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index e2eea8700d1..3297eb02df8 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -549,7 +549,7 @@ public GrpcAPI.Return broadcastTransaction(Transaction signedTransaction) { throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); } TransactionMessage message = new TransactionMessage(trx.getInstance().toByteArray()); - trx.checkExpiration(tronNetDelegate.getNextBlockSlotTime()); + trx.checkExpiration(chainBaseManager.getNextBlockSlotTime()); dbManager.pushTransaction(trx); int num = tronNetService.fastBroadcastTransaction(message); if (num == 0 && minEffectiveConnection != 0) { diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 908e248bdee..8311c8c6a71 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -794,7 +794,9 @@ void validateTapos(TransactionCapsule transactionCapsule) throws TaposException void validateCommon(TransactionCapsule transactionCapsule) throws TransactionExpirationException, TooBigTransactionException { - if (!transactionCapsule.isInBlock()) { + boolean optimizeTxs = !transactionCapsule.isInBlock() || chainBaseManager + .getDynamicPropertiesStore().allowConsensusLogicOptimization(); + if (optimizeTxs) { transactionCapsule.removeRedundantRet(); long generalBytesSize = transactionCapsule.getInstance().toBuilder().clearRet().build().getSerializedSize() @@ -813,6 +815,10 @@ void validateCommon(TransactionCapsule transactionCapsule) } long transactionExpiration = transactionCapsule.getExpiration(); long headBlockTime = chainBaseManager.getHeadBlockTimeStamp(); + if (transactionCapsule.isInBlock() + && chainBaseManager.getDynamicPropertiesStore().allowConsensusLogicOptimization()) { + transactionCapsule.checkExpiration(chainBaseManager.getNextBlockSlotTime()); + } if (transactionExpiration <= headBlockTime || transactionExpiration > headBlockTime + Constant.MAXIMUM_TIME_UNTIL_EXPIRATION) { throw new TransactionExpirationException( diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index a6f9812a2d7..cd9c8f01d8b 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -380,12 +380,4 @@ public boolean isBlockUnsolidified() { return headNum - solidNum >= maxUnsolidifiedBlocks; } - public long getNextBlockSlotTime() { - long slotCount = 1; - if (chainBaseManager.getDynamicPropertiesStore().getStateFlag() == 1) { - slotCount += chainBaseManager.getDynamicPropertiesStore().getMaintenanceSkipSlots(); - } - return chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp() - + slotCount * BLOCK_PRODUCED_INTERVAL; - } } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java index 0c58fe08cd6..e537e7edfbe 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java @@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.common.es.ExecutorServiceManager; +import org.tron.core.ChainBaseManager; import org.tron.core.config.args.Args; import org.tron.core.exception.P2pException; import org.tron.core.exception.P2pException.TypeEnum; @@ -36,6 +37,8 @@ public class TransactionsMsgHandler implements TronMsgHandler { private TronNetDelegate tronNetDelegate; @Autowired private AdvService advService; + @Autowired + private ChainBaseManager chainBaseManager; private BlockingQueue smartContractQueue = new LinkedBlockingQueue(MAX_TRX_SIZE); @@ -129,7 +132,7 @@ private void handleTransaction(PeerConnection peer, TransactionMessage trx) { } try { - trx.getTransactionCapsule().checkExpiration(tronNetDelegate.getNextBlockSlotTime()); + trx.getTransactionCapsule().checkExpiration(chainBaseManager.getNextBlockSlotTime()); tronNetDelegate.pushTransaction(trx.getTransactionCapsule()); advService.broadcast(trx); } catch (P2pException e) { diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index 07440435f41..1553ba15ec3 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -1158,6 +1158,30 @@ public void testTooBigTransaction() { } + @Test + public void testExpiration() { + dbManager.getDynamicPropertiesStore().saveConsensusLogicOptimization(1); + TransferContract transferContract = + TransferContract.newBuilder() + .setAmount(10) + .setOwnerAddress(ByteString.copyFromUtf8("aaa")) + .setToAddress(ByteString.copyFromUtf8("bbb")) + .build(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 100; i++) { + sb.append("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + } + Transaction transaction = Transaction.newBuilder().setRawData(Transaction.raw.newBuilder() + .setData(ByteString.copyFrom(sb.toString().getBytes(StandardCharsets.UTF_8))) + .addContract(Transaction.Contract.newBuilder().setParameter(Any.pack(transferContract)) + .setType(ContractType.TransferContract))).build(); + TransactionCapsule trx = new TransactionCapsule(transaction); + trx.setInBlock(true); + + assertThrows(TransactionExpirationException.class, () -> dbManager.validateCommon(trx)); + + } + @Test public void blockTrigger() { exit.expectSystemExitWithStatus(1); From 5619441399fb5535b1010593e452b4eee6f26fbe Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 13 May 2024 21:31:51 +0800 Subject: [PATCH 1114/1197] feat(api): optimize api service startup --- .../common/parameter/CommonParameter.java | 18 + .../src/main/java/org/tron/core/Constant.java | 8 +- .../common/application/AbstractService.java | 73 +++ .../tron/common/application/Application.java | 10 - .../common/application/ApplicationImpl.java | 33 +- .../common/application/CliApplication.java | 22 - .../tron/common/application/HttpService.java | 76 ++- .../tron/common/application/RpcService.java | 121 +++-- .../org/tron/common/application/Service.java | 23 +- .../common/application/ServiceContainer.java | 91 ++-- .../java/org/tron/core/config/args/Args.java | 28 ++ .../org/tron/core/services/RpcApiService.java | 93 +--- .../services/http/FullNodeHttpApiService.java | 475 +++++++++--------- .../solidity/SolidityNodeHttpApiService.java | 232 ++++----- .../JsonRpcServiceOnPBFT.java | 36 +- .../JsonRpcServiceOnSolidity.java | 35 +- .../interfaceOnPBFT/RpcApiServiceOnPBFT.java | 82 +-- .../http/PBFT/HttpApiOnPBFTService.java | 204 ++++---- .../RpcApiServiceOnSolidity.java | 80 +-- .../solidity/HttpApiOnSolidityService.java | 242 +++++---- .../jsonrpc/FullNodeJsonRpcHttpService.java | 47 +- .../org/tron/core/zen/ZksnarkInitService.java | 2 - .../main/java/org/tron/program/FullNode.java | 59 --- .../java/org/tron/program/SolidityNode.java | 25 +- framework/src/main/resources/config.conf | 8 +- .../tron/common/jetty/JettyServerTest.java | 3 +- .../org/tron/core/config/args/ArgsTest.java | 99 +++- .../tron/core/jsonrpc/JsonrpcServiceTest.java | 11 +- .../core/metrics/MetricsApiServiceTest.java | 4 +- .../test/java/org/tron/core/net/BaseNet.java | 12 +- .../java/org/tron/core/pbft/PbftApiTest.java | 8 +- .../core/services/RpcApiServicesTest.java | 11 +- .../org/tron/core/services/WalletApiTest.java | 30 +- .../filter/HttpApiAccessFilterTest.java | 20 +- .../LiteFnQueryGrpcInterceptorTest.java | 9 +- .../filter/LiteFnQueryHttpFilterTest.java | 26 +- .../filter/RpcApiAccessInterceptorTest.java | 11 +- .../services/http/BroadcastServletTest.java | 4 +- .../http/TriggerSmartContractServletTest.java | 21 +- ...GetTransactionByIdSolidityServletTest.java | 7 +- .../org/tron/program/SolidityNodeTest.java | 41 +- .../src/test/resources/config-localtest.conf | 20 +- .../src/test/resources/config-test-index.conf | 16 +- .../test/resources/config-test-mainnet.conf | 18 + framework/src/test/resources/config-test.conf | 16 +- .../java/org/tron/plugins/DbLiteTest.java | 5 +- 46 files changed, 1175 insertions(+), 1340 deletions(-) create mode 100644 framework/src/main/java/org/tron/common/application/AbstractService.java diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index d4a7b064cbb..8b599035f64 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -456,12 +456,30 @@ public class CommonParameter { @Getter @Setter public String cryptoEngine = Constant.ECKey_ENGINE; + + @Getter + @Setter + public boolean rpcEnable = true; + + @Getter + @Setter + public boolean rpcSolidityEnable = true; + + @Getter + @Setter + public boolean rpcPBFTEnable = true; + @Getter @Setter public boolean fullNodeHttpEnable = true; @Getter @Setter public boolean solidityNodeHttpEnable = true; + + @Getter + @Setter + public boolean pBFTHttpEnable = true; + @Getter @Setter public boolean jsonRpcHttpFullNodeEnable = false; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 3bdbf2113af..2043ba7fcdc 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -124,15 +124,21 @@ public class Constant { public static final String NODE_DNS_AWS_REGION = "node.dns.awsRegion"; public static final String NODE_DNS_AWS_HOST_ZONE_ID = "node.dns.awsHostZoneId"; + // config for rpc public static final String NODE_RPC_PORT = "node.rpc.port"; public static final String NODE_RPC_SOLIDITY_PORT = "node.rpc.solidityPort"; public static final String NODE_RPC_PBFT_PORT = "node.rpc.PBFTPort"; + public static final String NODE_RPC_ENABLE = "node.rpc.enable"; + public static final String NODE_RPC_SOLIDITY_ENABLE = "node.rpc.solidityEnable"; + public static final String NODE_RPC_PBFT_ENABLE = "node.rpc.PBFTEnable"; + // config for http public static final String NODE_HTTP_FULLNODE_PORT = "node.http.fullNodePort"; public static final String NODE_HTTP_SOLIDITY_PORT = "node.http.solidityPort"; public static final String NODE_HTTP_FULLNODE_ENABLE = "node.http.fullNodeEnable"; public static final String NODE_HTTP_SOLIDITY_ENABLE = "node.http.solidityEnable"; + public static final String NODE_HTTP_PBFT_ENABLE = "node.http.PBFTEnable"; public static final String NODE_HTTP_PBFT_PORT = "node.http.PBFTPort"; - + // config for jsonrpc public static final String NODE_JSONRPC_HTTP_FULLNODE_ENABLE = "node.jsonrpc.httpFullNodeEnable"; public static final String NODE_JSONRPC_HTTP_FULLNODE_PORT = "node.jsonrpc.httpFullNodePort"; public static final String NODE_JSONRPC_HTTP_SOLIDITY_ENABLE = "node.jsonrpc.httpSolidityEnable"; diff --git a/framework/src/main/java/org/tron/common/application/AbstractService.java b/framework/src/main/java/org/tron/common/application/AbstractService.java new file mode 100644 index 00000000000..79c25dc4944 --- /dev/null +++ b/framework/src/main/java/org/tron/common/application/AbstractService.java @@ -0,0 +1,73 @@ +package org.tron.common.application; + +import com.google.common.base.Objects; +import java.util.concurrent.CompletableFuture; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.tron.core.config.args.Args; + + +@Slf4j(topic = "service") +public abstract class AbstractService implements Service { + + protected int port; + @Getter + protected boolean enable; + @Getter + protected final String name = this.getClass().getSimpleName(); + + + @Override + public CompletableFuture start() { + logger.info("{} starting on {}", name, port); + final CompletableFuture resultFuture = new CompletableFuture<>(); + try { + innerStart(); + resultFuture.complete(true); + logger.info("{} started, listening on {}", name, port); + } catch (Exception e) { + resultFuture.completeExceptionally(e); + } + return resultFuture; + } + + @Override + public CompletableFuture stop() { + logger.info("{} shutdown...", name); + final CompletableFuture resultFuture = new CompletableFuture<>(); + try { + innerStop(); + resultFuture.complete(true); + logger.info("{} shutdown complete", name); + } catch (Exception e) { + resultFuture.completeExceptionally(e); + } + return resultFuture; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AbstractService that = (AbstractService) o; + return port == that.port; + } + + @Override + public int hashCode() { + return Objects.hashCode(name, port); + } + + public abstract void innerStart() throws Exception; + + public abstract void innerStop() throws Exception; + + protected boolean isFullNode() { + return !Args.getInstance().isSolidityNode(); + } + +} diff --git a/framework/src/main/java/org/tron/common/application/Application.java b/framework/src/main/java/org/tron/common/application/Application.java index 3d7e7a10864..0cdcca70580 100644 --- a/framework/src/main/java/org/tron/common/application/Application.java +++ b/framework/src/main/java/org/tron/common/application/Application.java @@ -15,19 +15,11 @@ package org.tron.common.application; -import org.tron.common.parameter.CommonParameter; import org.tron.core.ChainBaseManager; -import org.tron.core.config.args.Args; import org.tron.core.db.Manager; public interface Application { - void setOptions(Args args); - - void init(CommonParameter parameter); - - void initServices(CommonParameter parameter); - void startup(); void shutdown(); @@ -40,8 +32,6 @@ default void blockUntilShutdown() { void shutdownServices(); - void addService(Service service); - Manager getDbManager(); ChainBaseManager getChainBaseManager(); diff --git a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java index 3cb75cb1e24..bfd6c939e89 100644 --- a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java +++ b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java @@ -1,9 +1,9 @@ package org.tron.common.application; +import java.util.concurrent.CountDownLatch; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.common.parameter.CommonParameter; import org.tron.core.ChainBaseManager; import org.tron.core.config.args.Args; import org.tron.core.consensus.ConsensusService; @@ -15,6 +15,7 @@ @Component public class ApplicationImpl implements Application { + @Autowired private ServiceContainer services; @Autowired @@ -29,32 +30,12 @@ public class ApplicationImpl implements Application { @Autowired private ConsensusService consensusService; - @Override - public void setOptions(Args args) { - // not used - } - - @Override - @Autowired - public void init(CommonParameter parameter) { - services = new ServiceContainer(); - } - - @Override - public void addService(Service service) { - services.add(service); - } - - @Override - public void initServices(CommonParameter parameter) { - services.init(parameter); - } + private final CountDownLatch shutdown = new CountDownLatch(1); /** * start up the app. */ public void startup() { - this.initServices(Args.getInstance()); this.startServices(); if ((!Args.getInstance().isSolidityNode()) && (!Args.getInstance().isP2pDisable())) { tronNetService.start(); @@ -71,6 +52,7 @@ public void shutdown() { tronNetService.close(); } dbManager.close(); + shutdown.countDown(); } @Override @@ -80,7 +62,12 @@ public void startServices() { @Override public void blockUntilShutdown() { - services.blockUntilShutdown(); + try { + shutdown.await(); + } catch (final InterruptedException e) { + logger.debug("Interrupted, exiting", e); + Thread.currentThread().interrupt(); + } } @Override diff --git a/framework/src/main/java/org/tron/common/application/CliApplication.java b/framework/src/main/java/org/tron/common/application/CliApplication.java index 288149da4e4..bb056a34c11 100644 --- a/framework/src/main/java/org/tron/common/application/CliApplication.java +++ b/framework/src/main/java/org/tron/common/application/CliApplication.java @@ -15,28 +15,11 @@ package org.tron.common.application; -import org.tron.common.parameter.CommonParameter; import org.tron.core.ChainBaseManager; -import org.tron.core.config.args.Args; import org.tron.core.db.Manager; public class CliApplication implements Application { - @Override - public void setOptions(Args args) { - - } - - @Override - public void init(CommonParameter parameter) { - - } - - @Override - public void initServices(CommonParameter parameter) { - - } - @Override public void startup() { @@ -57,11 +40,6 @@ public void shutdownServices() { } - @Override - public void addService(Service service) { - - } - @Override public Manager getDbManager() { return null; diff --git a/framework/src/main/java/org/tron/common/application/HttpService.java b/framework/src/main/java/org/tron/common/application/HttpService.java index 76f8e74d65c..e9a902002ba 100644 --- a/framework/src/main/java/org/tron/common/application/HttpService.java +++ b/framework/src/main/java/org/tron/common/application/HttpService.java @@ -15,67 +15,61 @@ package org.tron.common.application; -import com.google.common.base.Objects; +import java.util.concurrent.CompletableFuture; import lombok.extern.slf4j.Slf4j; +import org.eclipse.jetty.server.ConnectionLimit; import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.tron.core.config.args.Args; @Slf4j(topic = "rpc") -public abstract class HttpService implements Service { +public abstract class HttpService extends AbstractService { protected Server apiServer; - protected int port; + + protected String contextPath; @Override - public void blockUntilShutdown() { - if (apiServer != null) { - try { - apiServer.join(); - } catch (InterruptedException e) { - logger.warn("{}", e.getMessage()); - Thread.currentThread().interrupt(); - } + public void innerStart() throws Exception { + if (this.apiServer != null) { + this.apiServer.start(); } } @Override - public void start() { - if (apiServer != null) { - try { - apiServer.start(); - logger.info("{} started, listening on {}", this.getClass().getSimpleName(), port); - } catch (Exception e) { - logger.error("{}", this.getClass().getSimpleName(), e); - } + public void innerStop() throws Exception { + if (this.apiServer != null) { + this.apiServer.stop(); } } @Override - public void stop() { - if (apiServer != null) { - logger.info("{} shutdown...", this.getClass().getSimpleName()); - try { - apiServer.stop(); - } catch (Exception e) { - logger.warn("{}", this.getClass().getSimpleName(), e); - } - logger.info("{} shutdown complete", this.getClass().getSimpleName()); - } + public CompletableFuture start() { + initServer(); + ServletContextHandler context = initContextHandler(); + addServlet(context); + addFilter(context); + return super.start(); } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + protected void initServer() { + this.apiServer = new Server(this.port); + int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); + if (maxHttpConnectNumber > 0) { + this.apiServer.addBean(new ConnectionLimit(maxHttpConnectNumber, this.apiServer)); } - if (o == null || getClass() != o.getClass()) { - return false; - } - HttpService that = (HttpService) o; - return port == that.port; } - @Override - public int hashCode() { - return Objects.hashCode(getClass().getSimpleName(), port); + protected ServletContextHandler initContextHandler() { + ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); + context.setContextPath(this.contextPath); + this.apiServer.setHandler(context); + return context; + } + + protected abstract void addServlet(ServletContextHandler context); + + protected void addFilter(ServletContextHandler context) { + } } diff --git a/framework/src/main/java/org/tron/common/application/RpcService.java b/framework/src/main/java/org/tron/common/application/RpcService.java index cb89441174a..2d118806e2c 100644 --- a/framework/src/main/java/org/tron/common/application/RpcService.java +++ b/framework/src/main/java/org/tron/common/application/RpcService.java @@ -15,71 +15,106 @@ package org.tron.common.application; -import com.google.common.base.Objects; import io.grpc.Server; -import java.io.IOException; +import io.grpc.netty.NettyServerBuilder; +import io.grpc.protobuf.services.ProtoReflectionService; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.tron.common.es.ExecutorServiceManager; +import org.tron.common.parameter.CommonParameter; +import org.tron.core.config.args.Args; +import org.tron.core.services.filter.LiteFnQueryGrpcInterceptor; +import org.tron.core.services.ratelimiter.PrometheusInterceptor; +import org.tron.core.services.ratelimiter.RateLimiterInterceptor; +import org.tron.core.services.ratelimiter.RpcApiAccessInterceptor; @Slf4j(topic = "rpc") -public abstract class RpcService implements Service { +public abstract class RpcService extends AbstractService { - protected Server apiServer; - protected int port; + private Server apiServer; + protected String executorName; + + @Autowired + private RateLimiterInterceptor rateLimiterInterceptor; + + @Autowired + private LiteFnQueryGrpcInterceptor liteFnQueryGrpcInterceptor; + + @Autowired + private RpcApiAccessInterceptor apiAccessInterceptor; + + @Autowired + private PrometheusInterceptor prometheusInterceptor; @Override - public void blockUntilShutdown() { - if (apiServer != null) { - try { - apiServer.awaitTermination(); - } catch (InterruptedException e) { - logger.warn("{}", e.getMessage()); - Thread.currentThread().interrupt(); - } + public void innerStart() throws Exception { + if (this.apiServer != null) { + this.apiServer.start(); } } @Override - public void start() { - if (apiServer != null) { - try { - apiServer.start(); - logger.info("{} started, listening on {}", this.getClass().getSimpleName(), port); - } catch (IOException e) { - logger.error("{}", this.getClass().getSimpleName(), e); - } + public void innerStop() throws Exception { + if (this.apiServer != null) { + this.apiServer.shutdown().awaitTermination(5, TimeUnit.SECONDS); } } @Override - public void stop() { - if (apiServer != null) { - logger.info("{} shutdown...", this.getClass().getSimpleName()); - try { - apiServer.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - logger.warn("{}", this.getClass().getSimpleName(), e); - } - logger.info("{} shutdown complete", this.getClass().getSimpleName()); - } + public CompletableFuture start() { + NettyServerBuilder serverBuilder = initServerBuilder(); + addService(serverBuilder); + addInterceptor(serverBuilder); + initServer(serverBuilder); + this.rateLimiterInterceptor.init(this.apiServer); + return super.start(); } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + protected NettyServerBuilder initServerBuilder() { + NettyServerBuilder serverBuilder = NettyServerBuilder.forPort(this.port); + CommonParameter parameter = Args.getInstance(); + if (parameter.getRpcThreadNum() > 0) { + serverBuilder = serverBuilder + .executor(ExecutorServiceManager.newFixedThreadPool( + this.executorName, parameter.getRpcThreadNum())); } - if (o == null || getClass() != o.getClass()) { - return false; + // Set configs from config.conf or default value + serverBuilder + .maxConcurrentCallsPerConnection(parameter.getMaxConcurrentCallsPerConnection()) + .flowControlWindow(parameter.getFlowControlWindow()) + .maxConnectionIdle(parameter.getMaxConnectionIdleInMillis(), TimeUnit.MILLISECONDS) + .maxConnectionAge(parameter.getMaxConnectionAgeInMillis(), TimeUnit.MILLISECONDS) + .maxInboundMessageSize(parameter.getMaxMessageSize()) + .maxHeaderListSize(parameter.getMaxHeaderListSize()); + + if (parameter.isRpcReflectionServiceEnable()) { + serverBuilder.addService(ProtoReflectionService.newInstance()); } - RpcService that = (RpcService) o; - return port == that.port; + return serverBuilder; } - @Override - public int hashCode() { - return Objects.hashCode(getClass().getSimpleName(), port); + protected abstract void addService(NettyServerBuilder serverBuilder); + + protected void addInterceptor(NettyServerBuilder serverBuilder) { + // add a ratelimiter interceptor + serverBuilder.intercept(this.rateLimiterInterceptor); + + // add api access interceptor + serverBuilder.intercept(this.apiAccessInterceptor); + + // add lite fullnode query interceptor + serverBuilder.intercept(this.liteFnQueryGrpcInterceptor); + + // add prometheus interceptor + if (Args.getInstance().isMetricsPrometheusEnable()) { + serverBuilder.intercept(prometheusInterceptor); + } + } + + protected void initServer(NettyServerBuilder serverBuilder) { + this.apiServer = serverBuilder.build(); } } diff --git a/framework/src/main/java/org/tron/common/application/Service.java b/framework/src/main/java/org/tron/common/application/Service.java index 67b4e3ce9ae..629e7e61a4c 100644 --- a/framework/src/main/java/org/tron/common/application/Service.java +++ b/framework/src/main/java/org/tron/common/application/Service.java @@ -15,22 +15,25 @@ package org.tron.common.application; -import org.tron.common.parameter.CommonParameter; +import java.util.concurrent.CompletableFuture; public interface Service { - void init(); - - void init(CommonParameter parameter); + /** + * Starts the service and all needed backend systems. + * + * @return completion state + */ + CompletableFuture start(); /** - * Start the service. - * {@link Service#init(CommonParameter parameter) init(CommonParameter parameter)} must be called - * before this method. + * Stops the service and performs needed cleanup. + * + * @return completion state */ - void start(); + CompletableFuture stop(); - void stop(); + boolean isEnable(); - void blockUntilShutdown(); + String getName(); } diff --git a/framework/src/main/java/org/tron/common/application/ServiceContainer.java b/framework/src/main/java/org/tron/common/application/ServiceContainer.java index 2951596add7..38ca3910e42 100644 --- a/framework/src/main/java/org/tron/common/application/ServiceContainer.java +++ b/framework/src/main/java/org/tron/common/application/ServiceContainer.java @@ -15,59 +15,80 @@ package org.tron.common.application; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.Set; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.stream.Collectors; +import javax.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; -import org.tron.common.parameter.CommonParameter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.exception.TronError; @Slf4j(topic = "app") +@Component public class ServiceContainer { - private final Set services; + @Autowired + private List services; - public ServiceContainer() { - this.services = Collections.synchronizedSet(new LinkedHashSet<>()); - } - - public void add(Service service) { - this.services.add(service); - } + private List enabledServices; - - public void init() { - this.services.forEach(service -> { - logger.debug("Initing {}.", service.getClass().getSimpleName()); - service.init(); - }); + public ServiceContainer() { } - public void init(CommonParameter parameter) { - this.services.forEach(service -> { - logger.debug("Initing {}.", service.getClass().getSimpleName()); - service.init(parameter); - }); + @PostConstruct + private void initEnabledServices() { + this.enabledServices = this.services.stream() + .filter(Service::isEnable) + .collect(Collectors.toList()); } - public void start() { + void start() { logger.info("Starting api services."); - this.services.forEach(service -> { - logger.debug("Starting {}.", service.getClass().getSimpleName()); - service.start(); - }); + this.enabledServices.forEach(this::waitForServiceToStart); logger.info("All api services started."); } - public void stop() { + void stop() { logger.info("Stopping api services."); - this.services.forEach(service -> { - logger.debug("Stopping {}.", service.getClass().getSimpleName()); - service.stop(); - }); + this.enabledServices.forEach(this::waitForServiceToStop); logger.info("All api services stopped."); } - public void blockUntilShutdown() { - this.services.stream().findFirst().ifPresent(Service::blockUntilShutdown); + private void waitForServiceToStart(Service service) { + final String serviceName = service.getName(); + final CompletableFuture startFuture = service.start(); + do { + try { + startFuture.get(60, TimeUnit.SECONDS); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + throw new TronError("Interrupted while waiting for service to start", e, + TronError.ErrCode.API_SERVER_INIT); + } catch (final ExecutionException e) { + throw new TronError("Service " + serviceName + " failed to start", e, + TronError.ErrCode.API_SERVER_INIT); + } catch (final TimeoutException e) { + logger.warn("Service {} is taking an unusually long time to start", serviceName); + } + } while (!startFuture.isDone()); + } + + private void waitForServiceToStop(Service service) { + final String serviceName = service.getName(); + final CompletableFuture stopFuture = service.stop(); + try { + stopFuture.get(30, TimeUnit.SECONDS); + } catch (final InterruptedException e) { + logger.debug("Interrupted while waiting for service {} to complete", serviceName, e); + Thread.currentThread().interrupt(); + } catch (final ExecutionException e) { + logger.error("Service {} failed to shutdown", serviceName, e); + } catch (final TimeoutException e) { + logger.error("Service {} did not shut down cleanly", serviceName); + } } } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 7397b69cde3..2ac3e69eced 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -96,6 +96,7 @@ public class Args extends CommonParameter { public static void clearParam() { + PARAMETER.shellConfFileName = ""; PARAMETER.outputDirectory = "output-directory"; PARAMETER.help = false; PARAMETER.witness = false; @@ -190,8 +191,12 @@ public static void clearParam() { PARAMETER.validContractProtoThreadNum = 1; PARAMETER.shieldedTransInPendingMaxCounts = 10; PARAMETER.changedDelegation = 0; + PARAMETER.rpcEnable = true; + PARAMETER.rpcSolidityEnable = true; + PARAMETER.rpcPBFTEnable = true; PARAMETER.fullNodeHttpEnable = true; PARAMETER.solidityNodeHttpEnable = true; + PARAMETER.pBFTHttpEnable = true; PARAMETER.jsonRpcHttpFullNodeEnable = false; PARAMETER.jsonRpcHttpSolidityNodeEnable = false; PARAMETER.jsonRpcHttpPBFTNodeEnable = false; @@ -364,6 +369,13 @@ public static void setParam(final String[] args, final String confFileName) { } Config config = Configuration.getByFileName(PARAMETER.shellConfFileName, confFileName); + setParam(config); + } + + /** + * set parameters. + */ + public static void setParam(final Config config) { if (config.hasPath(Constant.NET_TYPE) && Constant.TESTNET.equalsIgnoreCase(config.getString(Constant.NET_TYPE))) { @@ -451,6 +463,18 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.lruCacheSize = config.getInt(Constant.VM_LRU_CACHE_SIZE); } + if (config.hasPath(Constant.NODE_RPC_ENABLE)) { + PARAMETER.rpcEnable = config.getBoolean(Constant.NODE_RPC_ENABLE); + } + + if (config.hasPath(Constant.NODE_RPC_SOLIDITY_ENABLE)) { + PARAMETER.rpcSolidityEnable = config.getBoolean(Constant.NODE_RPC_SOLIDITY_ENABLE); + } + + if (config.hasPath(Constant.NODE_RPC_PBFT_ENABLE)) { + PARAMETER.rpcPBFTEnable = config.getBoolean(Constant.NODE_RPC_PBFT_ENABLE); + } + if (config.hasPath(Constant.NODE_HTTP_FULLNODE_ENABLE)) { PARAMETER.fullNodeHttpEnable = config.getBoolean(Constant.NODE_HTTP_FULLNODE_ENABLE); } @@ -459,6 +483,10 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.solidityNodeHttpEnable = config.getBoolean(Constant.NODE_HTTP_SOLIDITY_ENABLE); } + if (config.hasPath(Constant.NODE_HTTP_PBFT_ENABLE)) { + PARAMETER.pBFTHttpEnable = config.getBoolean(Constant.NODE_HTTP_PBFT_ENABLE); + } + if (config.hasPath(Constant.NODE_JSONRPC_HTTP_FULLNODE_ENABLE)) { PARAMETER.jsonRpcHttpFullNodeEnable = config.getBoolean(Constant.NODE_JSONRPC_HTTP_FULLNODE_ENABLE); diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index 3cc50c77890..8f9c6b15bb7 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -8,10 +8,8 @@ import io.grpc.Status; import io.grpc.StatusRuntimeException; import io.grpc.netty.NettyServerBuilder; -import io.grpc.protobuf.services.ProtoReflectionService; import io.grpc.stub.StreamObserver; import java.util.Objects; -import java.util.concurrent.TimeUnit; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -75,7 +73,6 @@ import org.tron.api.WalletGrpc.WalletImplBase; import org.tron.api.WalletSolidityGrpc.WalletSolidityImplBase; import org.tron.common.application.RpcService; -import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; @@ -97,10 +94,6 @@ import org.tron.core.exception.VMIllegalException; import org.tron.core.exception.ZksnarkException; import org.tron.core.metrics.MetricsApiService; -import org.tron.core.services.filter.LiteFnQueryGrpcInterceptor; -import org.tron.core.services.ratelimiter.PrometheusInterceptor; -import org.tron.core.services.ratelimiter.RateLimiterInterceptor; -import org.tron.core.services.ratelimiter.RpcApiAccessInterceptor; import org.tron.core.utils.TransactionUtil; import org.tron.core.zen.address.DiversifierT; import org.tron.core.zen.address.IncomingViewingKey; @@ -183,15 +176,7 @@ public class RpcApiService extends RpcService { @Autowired private NodeInfoService nodeInfoService; @Autowired - private RateLimiterInterceptor rateLimiterInterceptor; - @Autowired - private LiteFnQueryGrpcInterceptor liteFnQueryGrpcInterceptor; - @Autowired - private RpcApiAccessInterceptor apiAccessInterceptor; - @Autowired private MetricsApiService metricsApiService; - @Autowired - private PrometheusInterceptor prometheusInterceptor; @Getter private DatabaseApi databaseApi = new DatabaseApi(); private WalletApi walletApi = new WalletApi(); @@ -200,75 +185,27 @@ public class RpcApiService extends RpcService { @Getter private MonitorApi monitorApi = new MonitorApi(); - private final String executorName = "rpc-full-executor"; - - @Override - public void init() { - - } - - @Override - public void init(CommonParameter args) { + public RpcApiService() { port = Args.getInstance().getRpcPort(); + enable = Args.getInstance().isRpcEnable(); + executorName = "rpc-full-executor"; } @Override - public void start() { - try { - NettyServerBuilder serverBuilder = NettyServerBuilder.forPort(port).addService(databaseApi); - CommonParameter parameter = Args.getInstance(); - - if (parameter.getRpcThreadNum() > 0) { - serverBuilder = serverBuilder - .executor(ExecutorServiceManager.newFixedThreadPool( - executorName, parameter.getRpcThreadNum())); - } - - if (parameter.isSolidityNode()) { - serverBuilder = serverBuilder.addService(walletSolidityApi); - if (parameter.isWalletExtensionApi()) { - serverBuilder = serverBuilder.addService(new WalletExtensionApi()); - } - } else { - serverBuilder = serverBuilder.addService(walletApi); - } - - if (parameter.isNodeMetricsEnable()) { - serverBuilder = serverBuilder.addService(monitorApi); - } - - // Set configs from config.conf or default value - serverBuilder - .maxConcurrentCallsPerConnection(parameter.getMaxConcurrentCallsPerConnection()) - .flowControlWindow(parameter.getFlowControlWindow()) - .maxConnectionIdle(parameter.getMaxConnectionIdleInMillis(), TimeUnit.MILLISECONDS) - .maxConnectionAge(parameter.getMaxConnectionAgeInMillis(), TimeUnit.MILLISECONDS) - .maxInboundMessageSize(parameter.getMaxMessageSize()) - .maxHeaderListSize(parameter.getMaxHeaderListSize()); - - // add a rate limiter interceptor - serverBuilder.intercept(rateLimiterInterceptor); - - // add api access interceptor - serverBuilder.intercept(apiAccessInterceptor); - - // add lite fullnode query interceptor - serverBuilder.intercept(liteFnQueryGrpcInterceptor); - - // add prometheus interceptor - if (parameter.isMetricsPrometheusEnable()) { - serverBuilder.intercept(prometheusInterceptor); - } - - if (parameter.isRpcReflectionServiceEnable()) { - serverBuilder.addService(ProtoReflectionService.newInstance()); + protected void addService(NettyServerBuilder serverBuilder) { + serverBuilder.addService(databaseApi); + CommonParameter parameter = Args.getInstance(); + if (parameter.isSolidityNode()) { + serverBuilder.addService(walletSolidityApi); + if (parameter.isWalletExtensionApi()) { + serverBuilder.addService(new WalletExtensionApi()); } + } else { + serverBuilder.addService(walletApi); + } - apiServer = serverBuilder.build(); - rateLimiterInterceptor.init(apiServer); - super.start(); - } catch (Exception e) { - logger.debug(e.getMessage(), e); + if (parameter.isNodeMetricsEnable()) { + serverBuilder.addService(monitorApi); } } diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index 55e6e07b5ec..76785218096 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -4,8 +4,6 @@ import javax.servlet.DispatcherType; import javax.servlet.Filter; import lombok.extern.slf4j.Slf4j; -import org.eclipse.jetty.server.ConnectionLimit; -import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHandler; @@ -13,7 +11,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.common.application.HttpService; -import org.tron.common.parameter.CommonParameter; import org.tron.core.config.args.Args; import org.tron.core.services.filter.HttpApiAccessFilter; import org.tron.core.services.filter.HttpInterceptor; @@ -294,261 +291,247 @@ public class FullNodeHttpApiService extends HttpService { @Autowired private CancelAllUnfreezeV2Servlet cancelAllUnfreezeV2Servlet; - @Override - public void init() { - } - - @Override - public void init(CommonParameter args) { + public FullNodeHttpApiService() { port = Args.getInstance().getFullNodeHttpPort(); + enable = isFullNode() && Args.getInstance().isFullNodeHttpEnable(); + contextPath = "/"; } @Override - public void start() { - try { - apiServer = new Server(port); - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath("/"); - apiServer.setHandler(context); + protected void addServlet(ServletContextHandler context) { + context.addServlet(new ServletHolder(getAccountServlet), "/wallet/getaccount"); + context.addServlet(new ServletHolder(transferServlet), "/wallet/createtransaction"); + context.addServlet(new ServletHolder(broadcastServlet), "/wallet/broadcasttransaction"); + context.addServlet(new ServletHolder(updateAccountServlet), "/wallet/updateaccount"); + context.addServlet(new ServletHolder(voteWitnessAccountServlet), + "/wallet/votewitnessaccount"); + context.addServlet(new ServletHolder(createAssetIssueServlet), "/wallet/createassetissue"); + context.addServlet(new ServletHolder(updateWitnessServlet), "/wallet/updatewitness"); + context.addServlet(new ServletHolder(createAccountServlet), "/wallet/createaccount"); + context.addServlet(new ServletHolder(createWitnessServlet), "/wallet/createwitness"); + context.addServlet(new ServletHolder(transferAssetServlet), "/wallet/transferasset"); + context.addServlet(new ServletHolder(participateAssetIssueServlet), + "/wallet/participateassetissue"); + context.addServlet(new ServletHolder(freezeBalanceServlet), "/wallet/freezebalance"); + context.addServlet(new ServletHolder(unFreezeBalanceServlet), "/wallet/unfreezebalance"); + context.addServlet(new ServletHolder(unFreezeAssetServlet), "/wallet/unfreezeasset"); + context.addServlet(new ServletHolder(withdrawBalanceServlet), "/wallet/withdrawbalance"); + context.addServlet(new ServletHolder(updateAssetServlet), "/wallet/updateasset"); + context.addServlet(new ServletHolder(listNodesServlet), "/wallet/listnodes"); + context.addServlet( + new ServletHolder(getAssetIssueByAccountServlet), "/wallet/getassetissuebyaccount"); + context.addServlet(new ServletHolder(getAccountNetServlet), "/wallet/getaccountnet"); + context.addServlet(new ServletHolder(getAssetIssueByNameServlet), + "/wallet/getassetissuebyname"); + context.addServlet(new ServletHolder(getAssetIssueListByNameServlet), + "/wallet/getassetissuelistbyname"); + context.addServlet(new ServletHolder(getAssetIssueByIdServlet), "/wallet/getassetissuebyid"); + context.addServlet(new ServletHolder(getNowBlockServlet), "/wallet/getnowblock"); + context.addServlet(new ServletHolder(getBlockByNumServlet), "/wallet/getblockbynum"); + context.addServlet(new ServletHolder(getBlockByIdServlet), "/wallet/getblockbyid"); + context.addServlet(new ServletHolder(getBlockByLimitNextServlet), + "/wallet/getblockbylimitnext"); + context.addServlet(new ServletHolder(getBlockByLatestNumServlet), + "/wallet/getblockbylatestnum"); + context.addServlet(new ServletHolder(getTransactionByIdServlet), + "/wallet/gettransactionbyid"); + context.addServlet( + new ServletHolder(getTransactionInfoByIdServlet), "/wallet/gettransactioninfobyid"); + context.addServlet( + new ServletHolder(getTransactionReceiptByIdServlet), "/wallet/gettransactionreceiptbyid"); + context.addServlet( + new ServletHolder(getTransactionCountByBlockNumServlet), + "/wallet/gettransactioncountbyblocknum"); + context.addServlet(new ServletHolder(listWitnessesServlet), "/wallet/listwitnesses"); + context.addServlet(new ServletHolder(getAssetIssueListServlet), "/wallet/getassetissuelist"); + context.addServlet( + new ServletHolder(getPaginatedAssetIssueListServlet), + "/wallet/getpaginatedassetissuelist"); + context.addServlet( + new ServletHolder(getPaginatedProposalListServlet), "/wallet/getpaginatedproposallist"); + context.addServlet( + new ServletHolder(getPaginatedExchangeListServlet), "/wallet/getpaginatedexchangelist"); + context.addServlet(new ServletHolder(totalTransactionServlet), "/wallet/totaltransaction"); + context.addServlet( + new ServletHolder(getNextMaintenanceTimeServlet), "/wallet/getnextmaintenancetime"); + context.addServlet(new ServletHolder(validateAddressServlet), "/wallet/validateaddress"); + context.addServlet(new ServletHolder(deployContractServlet), "/wallet/deploycontract"); + context.addServlet(new ServletHolder(triggerSmartContractServlet), + "/wallet/triggersmartcontract"); + context.addServlet(new ServletHolder(triggerConstantContractServlet), + "/wallet/triggerconstantcontract"); + context.addServlet(new ServletHolder(estimateEnergyServlet), "/wallet/estimateenergy"); + context.addServlet(new ServletHolder(getContractServlet), "/wallet/getcontract"); + context.addServlet(new ServletHolder(getContractInfoServlet), "/wallet/getcontractinfo"); + context.addServlet(new ServletHolder(clearABIServlet), "/wallet/clearabi"); + context.addServlet(new ServletHolder(proposalCreateServlet), "/wallet/proposalcreate"); + context.addServlet(new ServletHolder(proposalApproveServlet), "/wallet/proposalapprove"); + context.addServlet(new ServletHolder(proposalDeleteServlet), "/wallet/proposaldelete"); + context.addServlet(new ServletHolder(listProposalsServlet), "/wallet/listproposals"); + context.addServlet(new ServletHolder(getProposalByIdServlet), "/wallet/getproposalbyid"); + context.addServlet(new ServletHolder(exchangeCreateServlet), "/wallet/exchangecreate"); + context.addServlet(new ServletHolder(exchangeInjectServlet), "/wallet/exchangeinject"); + context.addServlet(new ServletHolder(exchangeTransactionServlet), + "/wallet/exchangetransaction"); + context.addServlet(new ServletHolder(exchangeWithdrawServlet), "/wallet/exchangewithdraw"); + context.addServlet(new ServletHolder(getExchangeByIdServlet), "/wallet/getexchangebyid"); + context.addServlet(new ServletHolder(listExchangesServlet), "/wallet/listexchanges"); + context.addServlet(new ServletHolder(getChainParametersServlet), + "/wallet/getchainparameters"); + context.addServlet(new ServletHolder(getAccountResourceServlet), + "/wallet/getaccountresource"); + context.addServlet(new ServletHolder(getTransactionSignWeightServlet), + "/wallet/getsignweight"); + context.addServlet(new ServletHolder(getTransactionApprovedListServlet), + "/wallet/getapprovedlist"); + context.addServlet(new ServletHolder(accountPermissionUpdateServlet), + "/wallet/accountpermissionupdate"); + context.addServlet(new ServletHolder(getNodeInfoServlet), "/wallet/getnodeinfo"); + context.addServlet(new ServletHolder(updateSettingServlet), "/wallet/updatesetting"); + context.addServlet(new ServletHolder(updateEnergyLimitServlet), "/wallet/updateenergylimit"); + context.addServlet(new ServletHolder(getDelegatedResourceServlet), + "/wallet/getdelegatedresource"); + context.addServlet(new ServletHolder(getDelegatedResourceV2Servlet), + "/wallet/getdelegatedresourcev2"); + context.addServlet(new ServletHolder(getCanDelegatedMaxSizeServlet), + "/wallet/getcandelegatedmaxsize"); + context.addServlet(new ServletHolder(getAvailableUnfreezeCountServlet), + "/wallet/getavailableunfreezecount"); + context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountServlet), + "/wallet/getcanwithdrawunfreezeamount"); + context.addServlet( + new ServletHolder(getDelegatedResourceAccountIndexServlet), + "/wallet/getdelegatedresourceaccountindex"); + context.addServlet( + new ServletHolder(getDelegatedResourceAccountIndexV2Servlet), + "/wallet/getdelegatedresourceaccountindexv2"); + context.addServlet(new ServletHolder(setAccountServlet), "/wallet/setaccountid"); + context.addServlet(new ServletHolder(getAccountByIdServlet), "/wallet/getaccountbyid"); + context + .addServlet(new ServletHolder(getExpandedSpendingKeyServlet), + "/wallet/getexpandedspendingkey"); + context.addServlet(new ServletHolder(getAkFromAskServlet), "/wallet/getakfromask"); + context.addServlet(new ServletHolder(getNkFromNskServlet), "/wallet/getnkfromnsk"); + context.addServlet(new ServletHolder(getSpendingKeyServlet), "/wallet/getspendingkey"); + context + .addServlet(new ServletHolder(getNewShieldedAddressServlet), + "/wallet/getnewshieldedaddress"); + context.addServlet(new ServletHolder(getDiversifierServlet), "/wallet/getdiversifier"); + context.addServlet(new ServletHolder(getIncomingViewingKeyServlet), + "/wallet/getincomingviewingkey"); + context.addServlet(new ServletHolder(getZenPaymentAddressServlet), + "/wallet/getzenpaymentaddress"); + // context.addServlet(new ServletHolder(createShieldedTransactionServlet), + // "/wallet/createshieldedtransaction"); + // context.addServlet(new ServletHolder(createShieldedTransactionWithoutSpendAuthSigServlet), + // "/wallet/createshieldedtransactionwithoutspendauthsig"); + // context.addServlet(new ServletHolder(scanNoteByIvkServlet), "/wallet/scannotebyivk"); + // context.addServlet(new ServletHolder(scanAndMarkNoteByIvkServlet), + // "/wallet/scanandmarknotebyivk"); + // context.addServlet(new ServletHolder(scanNoteByOvkServlet), "/wallet/scannotebyovk"); + context.addServlet(new ServletHolder(getRcmServlet), "/wallet/getrcm"); + // context.addServlet(new ServletHolder(getMerkleTreeVoucherInfoServlet), + // "/wallet/getmerkletreevoucherinfo"); + // context.addServlet(new ServletHolder(isSpendServlet), "/wallet/isspend"); + context.addServlet(new ServletHolder(createSpendAuthSigServlet), + "/wallet/createspendauthsig"); + // context.addServlet(new ServletHolder(createShieldNullifierServlet), + // "/wallet/createshieldnullifier"); + // context.addServlet(new ServletHolder(getShieldTransactionHashServlet), + // "/wallet/getshieldtransactionhash"); - context.addServlet(new ServletHolder(getAccountServlet), "/wallet/getaccount"); - context.addServlet(new ServletHolder(transferServlet), "/wallet/createtransaction"); - context.addServlet(new ServletHolder(broadcastServlet), "/wallet/broadcasttransaction"); - context.addServlet(new ServletHolder(updateAccountServlet), "/wallet/updateaccount"); - context.addServlet(new ServletHolder(voteWitnessAccountServlet), - "/wallet/votewitnessaccount"); - context.addServlet(new ServletHolder(createAssetIssueServlet), "/wallet/createassetissue"); - context.addServlet(new ServletHolder(updateWitnessServlet), "/wallet/updatewitness"); - context.addServlet(new ServletHolder(createAccountServlet), "/wallet/createaccount"); - context.addServlet(new ServletHolder(createWitnessServlet), "/wallet/createwitness"); - context.addServlet(new ServletHolder(transferAssetServlet), "/wallet/transferasset"); - context.addServlet(new ServletHolder(participateAssetIssueServlet), - "/wallet/participateassetissue"); - context.addServlet(new ServletHolder(freezeBalanceServlet), "/wallet/freezebalance"); - context.addServlet(new ServletHolder(unFreezeBalanceServlet), "/wallet/unfreezebalance"); - context.addServlet(new ServletHolder(unFreezeAssetServlet), "/wallet/unfreezeasset"); - context.addServlet(new ServletHolder(withdrawBalanceServlet), "/wallet/withdrawbalance"); - context.addServlet(new ServletHolder(updateAssetServlet), "/wallet/updateasset"); - context.addServlet(new ServletHolder(listNodesServlet), "/wallet/listnodes"); - context.addServlet( - new ServletHolder(getAssetIssueByAccountServlet), "/wallet/getassetissuebyaccount"); - context.addServlet(new ServletHolder(getAccountNetServlet), "/wallet/getaccountnet"); - context.addServlet(new ServletHolder(getAssetIssueByNameServlet), - "/wallet/getassetissuebyname"); - context.addServlet(new ServletHolder(getAssetIssueListByNameServlet), - "/wallet/getassetissuelistbyname"); - context.addServlet(new ServletHolder(getAssetIssueByIdServlet), "/wallet/getassetissuebyid"); - context.addServlet(new ServletHolder(getNowBlockServlet), "/wallet/getnowblock"); - context.addServlet(new ServletHolder(getBlockByNumServlet), "/wallet/getblockbynum"); - context.addServlet(new ServletHolder(getBlockByIdServlet), "/wallet/getblockbyid"); - context.addServlet(new ServletHolder(getBlockByLimitNextServlet), - "/wallet/getblockbylimitnext"); - context.addServlet(new ServletHolder(getBlockByLatestNumServlet), - "/wallet/getblockbylatestnum"); - context.addServlet(new ServletHolder(getTransactionByIdServlet), - "/wallet/gettransactionbyid"); - context.addServlet( - new ServletHolder(getTransactionInfoByIdServlet), "/wallet/gettransactioninfobyid"); - context.addServlet( - new ServletHolder(getTransactionReceiptByIdServlet), "/wallet/gettransactionreceiptbyid"); - context.addServlet( - new ServletHolder(getTransactionCountByBlockNumServlet), - "/wallet/gettransactioncountbyblocknum"); - context.addServlet(new ServletHolder(listWitnessesServlet), "/wallet/listwitnesses"); - context.addServlet(new ServletHolder(getAssetIssueListServlet), "/wallet/getassetissuelist"); - context.addServlet( - new ServletHolder(getPaginatedAssetIssueListServlet), - "/wallet/getpaginatedassetissuelist"); - context.addServlet( - new ServletHolder(getPaginatedProposalListServlet), "/wallet/getpaginatedproposallist"); - context.addServlet( - new ServletHolder(getPaginatedExchangeListServlet), "/wallet/getpaginatedexchangelist"); - context.addServlet(new ServletHolder(totalTransactionServlet), "/wallet/totaltransaction"); - context.addServlet( - new ServletHolder(getNextMaintenanceTimeServlet), "/wallet/getnextmaintenancetime"); - context.addServlet(new ServletHolder(validateAddressServlet), "/wallet/validateaddress"); - context.addServlet(new ServletHolder(deployContractServlet), "/wallet/deploycontract"); - context.addServlet(new ServletHolder(triggerSmartContractServlet), - "/wallet/triggersmartcontract"); - context.addServlet(new ServletHolder(triggerConstantContractServlet), - "/wallet/triggerconstantcontract"); - context.addServlet(new ServletHolder(estimateEnergyServlet), "/wallet/estimateenergy"); - context.addServlet(new ServletHolder(getContractServlet), "/wallet/getcontract"); - context.addServlet(new ServletHolder(getContractInfoServlet), "/wallet/getcontractinfo"); - context.addServlet(new ServletHolder(clearABIServlet), "/wallet/clearabi"); - context.addServlet(new ServletHolder(proposalCreateServlet), "/wallet/proposalcreate"); - context.addServlet(new ServletHolder(proposalApproveServlet), "/wallet/proposalapprove"); - context.addServlet(new ServletHolder(proposalDeleteServlet), "/wallet/proposaldelete"); - context.addServlet(new ServletHolder(listProposalsServlet), "/wallet/listproposals"); - context.addServlet(new ServletHolder(getProposalByIdServlet), "/wallet/getproposalbyid"); - context.addServlet(new ServletHolder(exchangeCreateServlet), "/wallet/exchangecreate"); - context.addServlet(new ServletHolder(exchangeInjectServlet), "/wallet/exchangeinject"); - context.addServlet(new ServletHolder(exchangeTransactionServlet), - "/wallet/exchangetransaction"); - context.addServlet(new ServletHolder(exchangeWithdrawServlet), "/wallet/exchangewithdraw"); - context.addServlet(new ServletHolder(getExchangeByIdServlet), "/wallet/getexchangebyid"); - context.addServlet(new ServletHolder(listExchangesServlet), "/wallet/listexchanges"); - context.addServlet(new ServletHolder(getChainParametersServlet), - "/wallet/getchainparameters"); - context.addServlet(new ServletHolder(getAccountResourceServlet), - "/wallet/getaccountresource"); - context.addServlet(new ServletHolder(getTransactionSignWeightServlet), - "/wallet/getsignweight"); - context.addServlet(new ServletHolder(getTransactionApprovedListServlet), - "/wallet/getapprovedlist"); - context.addServlet(new ServletHolder(accountPermissionUpdateServlet), - "/wallet/accountpermissionupdate"); - context.addServlet(new ServletHolder(getNodeInfoServlet), "/wallet/getnodeinfo"); - context.addServlet(new ServletHolder(updateSettingServlet), "/wallet/updatesetting"); - context.addServlet(new ServletHolder(updateEnergyLimitServlet), "/wallet/updateenergylimit"); - context.addServlet(new ServletHolder(getDelegatedResourceServlet), - "/wallet/getdelegatedresource"); - context.addServlet(new ServletHolder(getDelegatedResourceV2Servlet), - "/wallet/getdelegatedresourcev2"); - context.addServlet(new ServletHolder(getCanDelegatedMaxSizeServlet), - "/wallet/getcandelegatedmaxsize"); - context.addServlet(new ServletHolder(getAvailableUnfreezeCountServlet), - "/wallet/getavailableunfreezecount"); - context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountServlet), - "/wallet/getcanwithdrawunfreezeamount"); - context.addServlet( - new ServletHolder(getDelegatedResourceAccountIndexServlet), - "/wallet/getdelegatedresourceaccountindex"); - context.addServlet( - new ServletHolder(getDelegatedResourceAccountIndexV2Servlet), - "/wallet/getdelegatedresourceaccountindexv2"); - context.addServlet(new ServletHolder(setAccountServlet), "/wallet/setaccountid"); - context.addServlet(new ServletHolder(getAccountByIdServlet), "/wallet/getaccountbyid"); - context - .addServlet(new ServletHolder(getExpandedSpendingKeyServlet), - "/wallet/getexpandedspendingkey"); - context.addServlet(new ServletHolder(getAkFromAskServlet), "/wallet/getakfromask"); - context.addServlet(new ServletHolder(getNkFromNskServlet), "/wallet/getnkfromnsk"); - context.addServlet(new ServletHolder(getSpendingKeyServlet), "/wallet/getspendingkey"); - context - .addServlet(new ServletHolder(getNewShieldedAddressServlet), - "/wallet/getnewshieldedaddress"); - context.addServlet(new ServletHolder(getDiversifierServlet), "/wallet/getdiversifier"); - context.addServlet(new ServletHolder(getIncomingViewingKeyServlet), - "/wallet/getincomingviewingkey"); - context.addServlet(new ServletHolder(getZenPaymentAddressServlet), - "/wallet/getzenpaymentaddress"); - // context.addServlet(new ServletHolder(createShieldedTransactionServlet), - // "/wallet/createshieldedtransaction"); - // context.addServlet(new ServletHolder(createShieldedTransactionWithoutSpendAuthSigServlet), - // "/wallet/createshieldedtransactionwithoutspendauthsig"); - // context.addServlet(new ServletHolder(scanNoteByIvkServlet), "/wallet/scannotebyivk"); - // context.addServlet(new ServletHolder(scanAndMarkNoteByIvkServlet), - // "/wallet/scanandmarknotebyivk"); - // context.addServlet(new ServletHolder(scanNoteByOvkServlet), "/wallet/scannotebyovk"); - context.addServlet(new ServletHolder(getRcmServlet), "/wallet/getrcm"); - // context.addServlet(new ServletHolder(getMerkleTreeVoucherInfoServlet), - // "/wallet/getmerkletreevoucherinfo"); - // context.addServlet(new ServletHolder(isSpendServlet), "/wallet/isspend"); - context.addServlet(new ServletHolder(createSpendAuthSigServlet), - "/wallet/createspendauthsig"); - // context.addServlet(new ServletHolder(createShieldNullifierServlet), - // "/wallet/createshieldnullifier"); - // context.addServlet(new ServletHolder(getShieldTransactionHashServlet), - // "/wallet/getshieldtransactionhash"); + context + .addServlet(new ServletHolder(isShieldedTRC20ContractNoteSpentServlet), + "/wallet/isshieldedtrc20contractnotespent"); + context.addServlet(new ServletHolder(createShieldedContractParametersServlet), + "/wallet/createshieldedcontractparameters"); + context.addServlet(new ServletHolder(createShieldedContractParametersWithoutAskServlet), + "/wallet/createshieldedcontractparameterswithoutask"); + context.addServlet(new ServletHolder(scanShieldedTRC20NotesByIvkServlet), + "/wallet/scanshieldedtrc20notesbyivk"); + context.addServlet(new ServletHolder(scanShieldedTRC20NotesByOvkServlet), + "/wallet/scanshieldedtrc20notesbyovk"); + context.addServlet(new ServletHolder(getTriggerInputForShieldedTRC20ContractServlet), + "/wallet/gettriggerinputforshieldedtrc20contract"); - context - .addServlet(new ServletHolder(isShieldedTRC20ContractNoteSpentServlet), - "/wallet/isshieldedtrc20contractnotespent"); - context.addServlet(new ServletHolder(createShieldedContractParametersServlet), - "/wallet/createshieldedcontractparameters"); - context.addServlet(new ServletHolder(createShieldedContractParametersWithoutAskServlet), - "/wallet/createshieldedcontractparameterswithoutask"); - context.addServlet(new ServletHolder(scanShieldedTRC20NotesByIvkServlet), - "/wallet/scanshieldedtrc20notesbyivk"); - context.addServlet(new ServletHolder(scanShieldedTRC20NotesByOvkServlet), - "/wallet/scanshieldedtrc20notesbyovk"); - context.addServlet(new ServletHolder(getTriggerInputForShieldedTRC20ContractServlet), - "/wallet/gettriggerinputforshieldedtrc20contract"); + context.addServlet(new ServletHolder(broadcastHexServlet), "/wallet/broadcasthex"); + context.addServlet(new ServletHolder(getBrokerageServlet), "/wallet/getBrokerage"); + context.addServlet(new ServletHolder(getRewardServlet), "/wallet/getReward"); + context.addServlet(new ServletHolder(updateBrokerageServlet), "/wallet/updateBrokerage"); + context.addServlet(new ServletHolder(createCommonTransactionServlet), + "/wallet/createCommonTransaction"); + context.addServlet(new ServletHolder(getTransactionInfoByBlockNumServlet), + "/wallet/gettransactioninfobyblocknum"); + context.addServlet(new ServletHolder(listNodesServlet), "/net/listnodes"); - context.addServlet(new ServletHolder(broadcastHexServlet), "/wallet/broadcasthex"); - context.addServlet(new ServletHolder(getBrokerageServlet), "/wallet/getBrokerage"); - context.addServlet(new ServletHolder(getRewardServlet), "/wallet/getReward"); - context.addServlet(new ServletHolder(updateBrokerageServlet), "/wallet/updateBrokerage"); - context.addServlet(new ServletHolder(createCommonTransactionServlet), - "/wallet/createCommonTransaction"); - context.addServlet(new ServletHolder(getTransactionInfoByBlockNumServlet), - "/wallet/gettransactioninfobyblocknum"); - context.addServlet(new ServletHolder(listNodesServlet), "/net/listnodes"); + context.addServlet(new ServletHolder(metricsServlet), "/monitor/getstatsinfo"); + context.addServlet(new ServletHolder(getNodeInfoServlet), "/monitor/getnodeinfo"); + context.addServlet(new ServletHolder(marketSellAssetServlet), "/wallet/marketsellasset"); + context.addServlet(new ServletHolder(marketCancelOrderServlet), "/wallet/marketcancelorder"); + context.addServlet(new ServletHolder(getMarketOrderByAccountServlet), + "/wallet/getmarketorderbyaccount"); + context.addServlet(new ServletHolder(getMarketOrderByIdServlet), + "/wallet/getmarketorderbyid"); + context.addServlet(new ServletHolder(getMarketPriceByPairServlet), + "/wallet/getmarketpricebypair"); + context.addServlet(new ServletHolder(getMarketOrderListByPairServlet), + "/wallet/getmarketorderlistbypair"); + context.addServlet(new ServletHolder(getMarketPairListServlet), + "/wallet/getmarketpairlist"); - context.addServlet(new ServletHolder(metricsServlet), "/monitor/getstatsinfo"); - context.addServlet(new ServletHolder(getNodeInfoServlet), "/monitor/getnodeinfo"); - context.addServlet(new ServletHolder(marketSellAssetServlet), "/wallet/marketsellasset"); - context.addServlet(new ServletHolder(marketCancelOrderServlet), "/wallet/marketcancelorder"); - context.addServlet(new ServletHolder(getMarketOrderByAccountServlet), - "/wallet/getmarketorderbyaccount"); - context.addServlet(new ServletHolder(getMarketOrderByIdServlet), - "/wallet/getmarketorderbyid"); - context.addServlet(new ServletHolder(getMarketPriceByPairServlet), - "/wallet/getmarketpricebypair"); - context.addServlet(new ServletHolder(getMarketOrderListByPairServlet), - "/wallet/getmarketorderlistbypair"); - context.addServlet(new ServletHolder(getMarketPairListServlet), - "/wallet/getmarketpairlist"); + context.addServlet(new ServletHolder(getAccountBalanceServlet), + "/wallet/getaccountbalance"); + context.addServlet(new ServletHolder(getBlockBalanceServlet), + "/wallet/getblockbalance"); + context.addServlet(new ServletHolder(getBurnTrxServlet), "/wallet/getburntrx"); + context.addServlet(new ServletHolder(getTransactionFromPendingServlet), + "/wallet/gettransactionfrompending"); + context.addServlet(new ServletHolder(getTransactionListFromPendingServlet), + "/wallet/gettransactionlistfrompending"); + context.addServlet(new ServletHolder(getPendingSizeServlet), "/wallet/getpendingsize"); + context.addServlet(new ServletHolder(getEnergyPricesServlet), "/wallet/getenergyprices"); + context.addServlet(new ServletHolder(getBandwidthPricesServlet), + "/wallet/getbandwidthprices"); + context.addServlet(new ServletHolder(getBlockServlet), "/wallet/getblock"); + context.addServlet(new ServletHolder(getMemoFeePricesServlet), "/wallet/getmemofee"); - context.addServlet(new ServletHolder(getAccountBalanceServlet), - "/wallet/getaccountbalance"); - context.addServlet(new ServletHolder(getBlockBalanceServlet), - "/wallet/getblockbalance"); - context.addServlet(new ServletHolder(getBurnTrxServlet), "/wallet/getburntrx"); - context.addServlet(new ServletHolder(getTransactionFromPendingServlet), - "/wallet/gettransactionfrompending"); - context.addServlet(new ServletHolder(getTransactionListFromPendingServlet), - "/wallet/gettransactionlistfrompending"); - context.addServlet(new ServletHolder(getPendingSizeServlet), "/wallet/getpendingsize"); - context.addServlet(new ServletHolder(getEnergyPricesServlet), "/wallet/getenergyprices"); - context.addServlet(new ServletHolder(getBandwidthPricesServlet), - "/wallet/getbandwidthprices"); - context.addServlet(new ServletHolder(getBlockServlet), "/wallet/getblock"); - context.addServlet(new ServletHolder(getMemoFeePricesServlet), "/wallet/getmemofee"); + context.addServlet(new ServletHolder(freezeBalanceV2Servlet), + "/wallet/freezebalancev2"); + context.addServlet(new ServletHolder(unFreezeBalanceV2Servlet), + "/wallet/unfreezebalancev2"); + context.addServlet(new ServletHolder(withdrawExpireUnfreezeServlet), + "/wallet/withdrawexpireunfreeze"); + context.addServlet(new ServletHolder(delegateResourceServlet), + "/wallet/delegateresource"); + context.addServlet(new ServletHolder(unDelegateResourceServlet), + "/wallet/undelegateresource"); + context.addServlet(new ServletHolder(cancelAllUnfreezeV2Servlet), + "/wallet/cancelallunfreezev2"); - context.addServlet(new ServletHolder(freezeBalanceV2Servlet), - "/wallet/freezebalancev2"); - context.addServlet(new ServletHolder(unFreezeBalanceV2Servlet), - "/wallet/unfreezebalancev2"); - context.addServlet(new ServletHolder(withdrawExpireUnfreezeServlet), - "/wallet/withdrawexpireunfreeze"); - context.addServlet(new ServletHolder(delegateResourceServlet), - "/wallet/delegateresource"); - context.addServlet(new ServletHolder(unDelegateResourceServlet), - "/wallet/undelegateresource"); - context.addServlet(new ServletHolder(cancelAllUnfreezeV2Servlet), - "/wallet/cancelallunfreezev2"); - - int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); - if (maxHttpConnectNumber > 0) { - apiServer.addBean(new ConnectionLimit(maxHttpConnectNumber, apiServer)); - } + } - // filters the specified APIs - // when node is lite fullnode and openHistoryQueryWhenLiteFN is false - context.addFilter(new FilterHolder(liteFnQueryHttpFilter), "/*", - EnumSet.allOf(DispatcherType.class)); + @Override + protected void addFilter(ServletContextHandler context) { + // filters the specified APIs + // when node is lite fullnode and openHistoryQueryWhenLiteFN is false + context.addFilter(new FilterHolder(liteFnQueryHttpFilter), "/*", + EnumSet.allOf(DispatcherType.class)); - // http access filter, it should have higher priority than HttpInterceptor - context.addFilter(new FilterHolder(httpApiAccessFilter), "/*", - EnumSet.allOf(DispatcherType.class)); - // note: if the pathSpec of servlet is not started with wallet, it should be included here - context.getServletHandler().getFilterMappings()[1] - .setPathSpecs(new String[] {"/wallet/*", - "/net/listnodes", - "/monitor/getstatsinfo", - "/monitor/getnodeinfo"}); + // http access filter, it should have higher priority than HttpInterceptor + context.addFilter(new FilterHolder(httpApiAccessFilter), "/*", + EnumSet.allOf(DispatcherType.class)); + // note: if the pathSpec of servlet is not started with wallet, it should be included here + context.getServletHandler().getFilterMappings()[1] + .setPathSpecs(new String[] {"/wallet/*", + "/net/listnodes", + "/monitor/getstatsinfo", + "/monitor/getnodeinfo"}); - // metrics filter - ServletHandler handler = new ServletHandler(); - FilterHolder fh = handler - .addFilterWithMapping((Class) HttpInterceptor.class, "/*", - EnumSet.of(DispatcherType.REQUEST)); - context.addFilter(fh, "/*", EnumSet.of(DispatcherType.REQUEST)); - super.start(); - } catch (Exception e) { - logger.debug("IOException: {}", e.getMessage()); - } + // metrics filter + ServletHandler handler = new ServletHandler(); + FilterHolder fh = handler + .addFilterWithMapping((Class) HttpInterceptor.class, "/*", + EnumSet.of(DispatcherType.REQUEST)); + context.addFilter(fh, "/*", EnumSet.of(DispatcherType.REQUEST)); } } diff --git a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java index 0c66b220e09..ea08d2d42cf 100644 --- a/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java @@ -3,15 +3,12 @@ import java.util.EnumSet; import javax.servlet.DispatcherType; import lombok.extern.slf4j.Slf4j; -import org.eclipse.jetty.server.ConnectionLimit; -import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.common.application.HttpService; -import org.tron.common.parameter.CommonParameter; import org.tron.core.config.args.Args; import org.tron.core.services.filter.HttpApiAccessFilter; import org.tron.core.services.http.EstimateEnergyServlet; @@ -166,140 +163,123 @@ public class SolidityNodeHttpApiService extends HttpService { private GetEnergyPricesServlet getEnergyPricesServlet; - @Override - public void init() { - } - - @Override - public void init(CommonParameter args) { + public SolidityNodeHttpApiService() { port = Args.getInstance().getSolidityHttpPort(); + enable = !isFullNode() && Args.getInstance().isSolidityNodeHttpEnable(); + contextPath = "/"; } @Override - public void start() { - try { - apiServer = new Server(port); - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath("/"); - apiServer.setHandler(context); - - // same as FullNode - context.addServlet(new ServletHolder(getAccountServlet), "/walletsolidity/getaccount"); - context.addServlet(new ServletHolder(listWitnessesServlet), "/walletsolidity/listwitnesses"); - context.addServlet(new ServletHolder(getAssetIssueListServlet), - "/walletsolidity/getassetissuelist"); - context.addServlet(new ServletHolder(getPaginatedAssetIssueListServlet), - "/walletsolidity/getpaginatedassetissuelist"); - context.addServlet(new ServletHolder(getAssetIssueByNameServlet), - "/walletsolidity/getassetissuebyname"); - context.addServlet(new ServletHolder(getAssetIssueByIdServlet), - "/walletsolidity/getassetissuebyid"); - context.addServlet(new ServletHolder(getAssetIssueListByNameServlet), - "/walletsolidity/getassetissuelistbyname"); - context.addServlet(new ServletHolder(getNowBlockServlet), "/walletsolidity/getnowblock"); - context.addServlet(new ServletHolder(getBlockByNumServlet), "/walletsolidity/getblockbynum"); - context.addServlet(new ServletHolder(getDelegatedResourceServlet), - "/walletsolidity/getdelegatedresource"); - context.addServlet(new ServletHolder(getDelegatedResourceV2Servlet), - "/walletsolidity/getdelegatedresourcev2"); - context.addServlet(new ServletHolder(getCanDelegatedMaxSizeServlet), - "/walletsolidity/getcandelegatedmaxsize"); - context.addServlet(new ServletHolder(getAvailableUnfreezeCountServlet), - "/walletsolidity/getavailableunfreezecount"); - context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountServlet), - "/walletsolidity/getcanwithdrawunfreezeamount"); - context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexServlet), - "/walletsolidity/getdelegatedresourceaccountindex"); - context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexV2Servlet), - "/walletsolidity/getdelegatedresourceaccountindexv2"); - context - .addServlet(new ServletHolder(getExchangeByIdServlet), - "/walletsolidity/getexchangebyid"); - context.addServlet(new ServletHolder(listExchangesServlet), - "/walletsolidity/listexchanges"); + protected void addServlet(ServletContextHandler context) { + // same as FullNode + context.addServlet(new ServletHolder(getAccountServlet), "/walletsolidity/getaccount"); + context.addServlet(new ServletHolder(listWitnessesServlet), "/walletsolidity/listwitnesses"); + context.addServlet(new ServletHolder(getAssetIssueListServlet), + "/walletsolidity/getassetissuelist"); + context.addServlet(new ServletHolder(getPaginatedAssetIssueListServlet), + "/walletsolidity/getpaginatedassetissuelist"); + context.addServlet(new ServletHolder(getAssetIssueByNameServlet), + "/walletsolidity/getassetissuebyname"); + context.addServlet(new ServletHolder(getAssetIssueByIdServlet), + "/walletsolidity/getassetissuebyid"); + context.addServlet(new ServletHolder(getAssetIssueListByNameServlet), + "/walletsolidity/getassetissuelistbyname"); + context.addServlet(new ServletHolder(getNowBlockServlet), "/walletsolidity/getnowblock"); + context.addServlet(new ServletHolder(getBlockByNumServlet), "/walletsolidity/getblockbynum"); + context.addServlet(new ServletHolder(getDelegatedResourceServlet), + "/walletsolidity/getdelegatedresource"); + context.addServlet(new ServletHolder(getDelegatedResourceV2Servlet), + "/walletsolidity/getdelegatedresourcev2"); + context.addServlet(new ServletHolder(getCanDelegatedMaxSizeServlet), + "/walletsolidity/getcandelegatedmaxsize"); + context.addServlet(new ServletHolder(getAvailableUnfreezeCountServlet), + "/walletsolidity/getavailableunfreezecount"); + context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountServlet), + "/walletsolidity/getcanwithdrawunfreezeamount"); + context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexServlet), + "/walletsolidity/getdelegatedresourceaccountindex"); + context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexV2Servlet), + "/walletsolidity/getdelegatedresourceaccountindexv2"); + context + .addServlet(new ServletHolder(getExchangeByIdServlet), + "/walletsolidity/getexchangebyid"); + context.addServlet(new ServletHolder(listExchangesServlet), + "/walletsolidity/listexchanges"); - context.addServlet(new ServletHolder(getAccountByIdServlet), - "/walletsolidity/getaccountbyid"); - context.addServlet(new ServletHolder(getBlockByIdServlet), - "/walletsolidity/getblockbyid"); - context.addServlet(new ServletHolder(getBlockByLimitNextServlet), - "/walletsolidity/getblockbylimitnext"); - context.addServlet(new ServletHolder(getBlockByLatestNumServlet), - "/walletsolidity/getblockbylatestnum"); + context.addServlet(new ServletHolder(getAccountByIdServlet), + "/walletsolidity/getaccountbyid"); + context.addServlet(new ServletHolder(getBlockByIdServlet), + "/walletsolidity/getblockbyid"); + context.addServlet(new ServletHolder(getBlockByLimitNextServlet), + "/walletsolidity/getblockbylimitnext"); + context.addServlet(new ServletHolder(getBlockByLatestNumServlet), + "/walletsolidity/getblockbylatestnum"); - // context.addServlet(new ServletHolder(getMerkleTreeVoucherInfoServlet), - // "/walletsolidity/getmerkletreevoucherinfo"); - // context.addServlet(new ServletHolder(scanAndMarkNoteByIvkServlet), - // "/walletsolidity/scanandmarknotebyivk"); - // context.addServlet(new ServletHolder(scanNoteByIvkServlet), - // "/walletsolidity/scannotebyivk"); - // context.addServlet(new ServletHolder(scanNoteByOvkServlet), - // "/walletsolidity/scannotebyovk"); - // context.addServlet(new ServletHolder(isSpendServlet), - // "/walletsolidity/isspend"); + // context.addServlet(new ServletHolder(getMerkleTreeVoucherInfoServlet), + // "/walletsolidity/getmerkletreevoucherinfo"); + // context.addServlet(new ServletHolder(scanAndMarkNoteByIvkServlet), + // "/walletsolidity/scanandmarknotebyivk"); + // context.addServlet(new ServletHolder(scanNoteByIvkServlet), + // "/walletsolidity/scannotebyivk"); + // context.addServlet(new ServletHolder(scanNoteByOvkServlet), + // "/walletsolidity/scannotebyovk"); + // context.addServlet(new ServletHolder(isSpendServlet), + // "/walletsolidity/isspend"); + context.addServlet(new ServletHolder(scanShieldedTRC20NotesByIvkServlet), + "/walletsolidity/scanshieldedtrc20notesbyivk"); + context.addServlet(new ServletHolder(scanShieldedTRC20NotesByOvkServlet), + "/walletsolidity/scanshieldedtrc20notesbyovk"); + context.addServlet(new ServletHolder(isShieldedTRC20ContractNoteSpentServlet), + "/walletsolidity/isshieldedtrc20contractnotespent"); - context.addServlet(new ServletHolder(scanShieldedTRC20NotesByIvkServlet), - "/walletsolidity/scanshieldedtrc20notesbyivk"); - context.addServlet(new ServletHolder(scanShieldedTRC20NotesByOvkServlet), - "/walletsolidity/scanshieldedtrc20notesbyovk"); - context.addServlet(new ServletHolder(isShieldedTRC20ContractNoteSpentServlet), - "/walletsolidity/isshieldedtrc20contractnotespent"); + context.addServlet(new ServletHolder(getTransactionInfoByBlockNumServlet), + "/walletsolidity/gettransactioninfobyblocknum"); - context.addServlet(new ServletHolder(getTransactionInfoByBlockNumServlet), - "/walletsolidity/gettransactioninfobyblocknum"); + context.addServlet(new ServletHolder(getMarketOrderByAccountServlet), + "/walletsolidity/getmarketorderbyaccount"); + context.addServlet(new ServletHolder(getMarketOrderByIdServlet), + "/walletsolidity/getmarketorderbyid"); + context.addServlet(new ServletHolder(getMarketPriceByPairServlet), + "/walletsolidity/getmarketpricebypair"); + context.addServlet(new ServletHolder(getMarketOrderListByPairServlet), + "/walletsolidity/getmarketorderlistbypair"); + context.addServlet(new ServletHolder(getMarketPairListServlet), + "/walletsolidity/getmarketpairlist"); - context.addServlet(new ServletHolder(getMarketOrderByAccountServlet), - "/walletsolidity/getmarketorderbyaccount"); - context.addServlet(new ServletHolder(getMarketOrderByIdServlet), - "/walletsolidity/getmarketorderbyid"); - context.addServlet(new ServletHolder(getMarketPriceByPairServlet), - "/walletsolidity/getmarketpricebypair"); - context.addServlet(new ServletHolder(getMarketOrderListByPairServlet), - "/walletsolidity/getmarketorderlistbypair"); - context.addServlet(new ServletHolder(getMarketPairListServlet), - "/walletsolidity/getmarketpairlist"); + // only for SolidityNode + context.addServlet(new ServletHolder(getTransactionByIdServlet), + "/walletsolidity/gettransactionbyid"); - // only for SolidityNode - context.addServlet(new ServletHolder(getTransactionByIdServlet), - "/walletsolidity/gettransactionbyid"); + context + .addServlet(new ServletHolder(getTransactionInfoByIdServlet), + "/walletsolidity/gettransactioninfobyid"); + context + .addServlet(new ServletHolder(getTransactionCountByBlockNumServlet), + "/walletsolidity/gettransactioncountbyblocknum"); + context.addServlet(new ServletHolder(triggerConstantContractServlet), + "/walletsolidity/triggerconstantcontract"); + context.addServlet(new ServletHolder(estimateEnergyServlet), + "/walletsolidity/estimateenergy"); - context - .addServlet(new ServletHolder(getTransactionInfoByIdServlet), - "/walletsolidity/gettransactioninfobyid"); - context - .addServlet(new ServletHolder(getTransactionCountByBlockNumServlet), - "/walletsolidity/gettransactioncountbyblocknum"); - context.addServlet(new ServletHolder(triggerConstantContractServlet), - "/walletsolidity/triggerconstantcontract"); - context.addServlet(new ServletHolder(estimateEnergyServlet), - "/walletsolidity/estimateenergy"); - - context.addServlet(new ServletHolder(getNodeInfoServlet), "/wallet/getnodeinfo"); - context.addServlet(new ServletHolder(getNodeInfoServlet), "/walletsolidity/getnodeinfo"); - context.addServlet(new ServletHolder(getBrokerageServlet), "/walletsolidity/getBrokerage"); - context.addServlet(new ServletHolder(getRewardServlet), "/walletsolidity/getReward"); - context.addServlet(new ServletHolder(getBurnTrxServlet), "/walletsolidity/getburntrx"); - context.addServlet(new ServletHolder(getBlockServlet), "/walletsolidity/getblock"); - context.addServlet(new ServletHolder(getBandwidthPricesServlet), - "/walletsolidity/getbandwidthprices"); - context.addServlet(new ServletHolder(getEnergyPricesServlet), - "/walletsolidity/getenergyprices"); - - // http access filter - context.addFilter(new FilterHolder(httpApiAccessFilter), "/walletsolidity/*", - EnumSet.allOf(DispatcherType.class)); - context.getServletHandler().getFilterMappings()[0] - .setPathSpecs(new String[] {"/walletsolidity/*", - "/wallet/getnodeinfo"}); - - int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); - if (maxHttpConnectNumber > 0) { - apiServer.addBean(new ConnectionLimit(maxHttpConnectNumber, apiServer)); - } + context.addServlet(new ServletHolder(getNodeInfoServlet), "/wallet/getnodeinfo"); + context.addServlet(new ServletHolder(getNodeInfoServlet), "/walletsolidity/getnodeinfo"); + context.addServlet(new ServletHolder(getBrokerageServlet), "/walletsolidity/getBrokerage"); + context.addServlet(new ServletHolder(getRewardServlet), "/walletsolidity/getReward"); + context.addServlet(new ServletHolder(getBurnTrxServlet), "/walletsolidity/getburntrx"); + context.addServlet(new ServletHolder(getBlockServlet), "/walletsolidity/getblock"); + context.addServlet(new ServletHolder(getBandwidthPricesServlet), + "/walletsolidity/getbandwidthprices"); + context.addServlet(new ServletHolder(getEnergyPricesServlet), + "/walletsolidity/getenergyprices"); + } - super.start(); - } catch (Exception e) { - logger.debug("IOException: {}", e.getMessage()); - } + @Override + protected void addFilter(ServletContextHandler context) { + // http access filter + context.addFilter(new FilterHolder(httpApiAccessFilter), "/walletsolidity/*", + EnumSet.allOf(DispatcherType.class)); + context.getServletHandler().getFilterMappings()[0] + .setPathSpecs(new String[] {"/walletsolidity/*", + "/wallet/getnodeinfo"}); } } diff --git a/framework/src/main/java/org/tron/core/services/interfaceJsonRpcOnPBFT/JsonRpcServiceOnPBFT.java b/framework/src/main/java/org/tron/core/services/interfaceJsonRpcOnPBFT/JsonRpcServiceOnPBFT.java index 1893a46045a..fffaf8d4e7b 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceJsonRpcOnPBFT/JsonRpcServiceOnPBFT.java +++ b/framework/src/main/java/org/tron/core/services/interfaceJsonRpcOnPBFT/JsonRpcServiceOnPBFT.java @@ -1,14 +1,12 @@ package org.tron.core.services.interfaceJsonRpcOnPBFT; import lombok.extern.slf4j.Slf4j; -import org.eclipse.jetty.server.ConnectionLimit; -import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.common.application.HttpService; -import org.tron.common.parameter.CommonParameter; +import org.tron.core.config.args.Args; @Component @Slf4j(topic = "API") @@ -17,34 +15,14 @@ public class JsonRpcServiceOnPBFT extends HttpService { @Autowired private JsonRpcOnPBFTServlet jsonRpcOnPBFTServlet; - @Override - public void init() { - } - - @Override - public void init(CommonParameter args) { - port = CommonParameter.getInstance().getJsonRpcHttpPBFTPort(); + public JsonRpcServiceOnPBFT() { + port = Args.getInstance().getJsonRpcHttpPBFTPort(); + enable = isFullNode() && Args.getInstance().isJsonRpcHttpPBFTNodeEnable(); + contextPath = "/"; } @Override - public void start() { - try { - apiServer = new Server(port); - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath("/"); - apiServer.setHandler(context); - - context.addServlet(new ServletHolder(jsonRpcOnPBFTServlet), "/jsonrpc"); - - int maxHttpConnectNumber = CommonParameter.getInstance().getMaxHttpConnectNumber(); - if (maxHttpConnectNumber > 0) { - apiServer.addBean(new ConnectionLimit(maxHttpConnectNumber, apiServer)); - } - - super.start(); - - } catch (Exception e) { - logger.debug("IOException: {}", e.getMessage()); - } + public void addServlet(ServletContextHandler context) { + context.addServlet(new ServletHolder(jsonRpcOnPBFTServlet), "/jsonrpc"); } } diff --git a/framework/src/main/java/org/tron/core/services/interfaceJsonRpcOnSolidity/JsonRpcServiceOnSolidity.java b/framework/src/main/java/org/tron/core/services/interfaceJsonRpcOnSolidity/JsonRpcServiceOnSolidity.java index 52f5b761ae2..a6f7d5dd5e7 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceJsonRpcOnSolidity/JsonRpcServiceOnSolidity.java +++ b/framework/src/main/java/org/tron/core/services/interfaceJsonRpcOnSolidity/JsonRpcServiceOnSolidity.java @@ -1,14 +1,12 @@ package org.tron.core.services.interfaceJsonRpcOnSolidity; import lombok.extern.slf4j.Slf4j; -import org.eclipse.jetty.server.ConnectionLimit; -import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.common.application.HttpService; -import org.tron.common.parameter.CommonParameter; +import org.tron.core.config.args.Args; @Component @Slf4j(topic = "API") @@ -17,33 +15,14 @@ public class JsonRpcServiceOnSolidity extends HttpService { @Autowired private JsonRpcOnSolidityServlet jsonRpcOnSolidityServlet; - @Override - public void init() { - } - - @Override - public void init(CommonParameter args) { - port = CommonParameter.getInstance().getJsonRpcHttpSolidityPort(); + public JsonRpcServiceOnSolidity() { + port = Args.getInstance().getJsonRpcHttpSolidityPort(); + enable = isFullNode() && Args.getInstance().isJsonRpcHttpSolidityNodeEnable(); + contextPath = "/"; } @Override - public void start() { - try { - apiServer = new Server(port); - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath("/"); - apiServer.setHandler(context); - - context.addServlet(new ServletHolder(jsonRpcOnSolidityServlet), "/jsonrpc"); - - int maxHttpConnectNumber = CommonParameter.getInstance().getMaxHttpConnectNumber(); - if (maxHttpConnectNumber > 0) { - apiServer.addBean(new ConnectionLimit(maxHttpConnectNumber, apiServer)); - } - super.start(); - - } catch (Exception e) { - logger.debug("IOException: {}", e.getMessage()); - } + public void addServlet(ServletContextHandler context) { + context.addServlet(new ServletHolder(jsonRpcOnSolidityServlet), "/jsonrpc"); } } diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java index cf945f664d1..54e7b69f7fc 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java @@ -1,9 +1,7 @@ package org.tron.core.services.interfaceOnPBFT; import io.grpc.netty.NettyServerBuilder; -import io.grpc.protobuf.services.ProtoReflectionService; import io.grpc.stub.StreamObserver; -import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.tron.api.DatabaseGrpc.DatabaseImplBase; @@ -36,14 +34,8 @@ import org.tron.api.GrpcAPI.WitnessList; import org.tron.api.WalletSolidityGrpc.WalletSolidityImplBase; import org.tron.common.application.RpcService; -import org.tron.common.es.ExecutorServiceManager; -import org.tron.common.parameter.CommonParameter; import org.tron.core.config.args.Args; import org.tron.core.services.RpcApiService; -import org.tron.core.services.filter.LiteFnQueryGrpcInterceptor; -import org.tron.core.services.ratelimiter.PrometheusInterceptor; -import org.tron.core.services.ratelimiter.RateLimiterInterceptor; -import org.tron.core.services.ratelimiter.RpcApiAccessInterceptor; import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.DelegatedResourceAccountIndex; @@ -71,78 +63,16 @@ public class RpcApiServiceOnPBFT extends RpcService { @Autowired private RpcApiService rpcApiService; - @Autowired - private RateLimiterInterceptor rateLimiterInterceptor; - - @Autowired - private LiteFnQueryGrpcInterceptor liteFnQueryGrpcInterceptor; - - @Autowired - private RpcApiAccessInterceptor apiAccessInterceptor; - - @Autowired - private PrometheusInterceptor prometheusInterceptor; - - private final String executorName = "rpc-pbft-executor"; - - @Override - public void init() { - } - - @Override - public void init(CommonParameter parameter) { + public RpcApiServiceOnPBFT() { port = Args.getInstance().getRpcOnPBFTPort(); + enable = isFullNode() && Args.getInstance().isRpcPBFTEnable(); + executorName = "rpc-pbft-executor"; } @Override - public void start() { - try { - NettyServerBuilder serverBuilder = NettyServerBuilder.forPort(port) - .addService(new DatabaseApi()); - - CommonParameter args = CommonParameter.getInstance(); - - if (args.getRpcThreadNum() > 0) { - serverBuilder = serverBuilder - .executor(ExecutorServiceManager.newFixedThreadPool( - executorName, args.getRpcThreadNum())); - } - - serverBuilder = serverBuilder.addService(new WalletPBFTApi()); - - // Set configs from config.conf or default value - serverBuilder - .maxConcurrentCallsPerConnection(args.getMaxConcurrentCallsPerConnection()) - .flowControlWindow(args.getFlowControlWindow()) - .maxConnectionIdle(args.getMaxConnectionIdleInMillis(), TimeUnit.MILLISECONDS) - .maxConnectionAge(args.getMaxConnectionAgeInMillis(), TimeUnit.MILLISECONDS) - .maxInboundMessageSize(args.getMaxMessageSize()) - .maxHeaderListSize(args.getMaxHeaderListSize()); - - // add a ratelimiter interceptor - serverBuilder.intercept(rateLimiterInterceptor); - - // add api access interceptor - serverBuilder.intercept(apiAccessInterceptor); - - // add lite fullnode query interceptor - serverBuilder.intercept(liteFnQueryGrpcInterceptor); - - // add prometheus interceptor - if (args.isMetricsPrometheusEnable()) { - serverBuilder.intercept(prometheusInterceptor); - } - - if (args.isRpcReflectionServiceEnable()) { - serverBuilder.addService(ProtoReflectionService.newInstance()); - } - - apiServer = serverBuilder.build(); - rateLimiterInterceptor.init(apiServer); - super.start(); - } catch (Exception e) { - logger.debug(e.getMessage(), e); - } + protected void addService(NettyServerBuilder serverBuilder) { + serverBuilder.addService(new DatabaseApi()); + serverBuilder.addService(new WalletPBFTApi()); } /** diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java index 7a5fd0cbcde..828d36e664f 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java @@ -3,14 +3,11 @@ import java.util.EnumSet; import javax.servlet.DispatcherType; import lombok.extern.slf4j.Slf4j; -import org.eclipse.jetty.server.ConnectionLimit; -import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.springframework.beans.factory.annotation.Autowired; import org.tron.common.application.HttpService; -import org.tron.common.parameter.CommonParameter; import org.tron.core.config.args.Args; import org.tron.core.services.filter.HttpApiAccessFilter; import org.tron.core.services.filter.LiteFnQueryHttpFilter; @@ -172,126 +169,109 @@ public class HttpApiOnPBFTService extends HttpService { @Autowired private GetDelegatedResourceV2OnPBFTServlet getDelegatedResourceV2OnPBFTServlet; - @Override - public void init() { - - } - - @Override - public void init(CommonParameter parameter) { + public HttpApiOnPBFTService() { port = Args.getInstance().getPBFTHttpPort(); + enable = isFullNode() && Args.getInstance().isPBFTHttpEnable(); + contextPath = "/walletpbft/"; } @Override - public void start() { - try { - apiServer = new Server(port); - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath("/walletpbft/"); - apiServer.setHandler(context); + protected void addServlet(ServletContextHandler context) { + // same as FullNode + context.addServlet(new ServletHolder(accountOnPBFTServlet), "/getaccount"); + context.addServlet(new ServletHolder(listWitnessesOnPBFTServlet), "/listwitnesses"); + context.addServlet(new ServletHolder(getAssetIssueListOnPBFTServlet), "/getassetissuelist"); + context.addServlet(new ServletHolder(getPaginatedAssetIssueListOnPBFTServlet), + "/getpaginatedassetissuelist"); + context + .addServlet(new ServletHolder(getAssetIssueByNameOnPBFTServlet), "/getassetissuebyname"); + context.addServlet(new ServletHolder(getAssetIssueByIdOnPBFTServlet), "/getassetissuebyid"); + context.addServlet(new ServletHolder(getAssetIssueListByNameOnPBFTServlet), + "/getassetissuelistbyname"); + context.addServlet(new ServletHolder(getNowBlockOnPBFTServlet), "/getnowblock"); + context.addServlet(new ServletHolder(getBlockByNumOnPBFTServlet), "/getblockbynum"); + context.addServlet(new ServletHolder(getDelegatedResourceOnPBFTServlet), + "/getdelegatedresource"); + context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexOnPBFTServlet), + "/getdelegatedresourceaccountindex"); + context.addServlet(new ServletHolder(getExchangeByIdOnPBFTServlet), "/getexchangebyid"); + context.addServlet(new ServletHolder(listExchangesOnPBFTServlet), "/listexchanges"); + context.addServlet(new ServletHolder(getAccountByIdOnPBFTServlet), "/getaccountbyid"); + context.addServlet(new ServletHolder(getBlockByIdOnPBFTServlet), "/getblockbyid"); + context + .addServlet(new ServletHolder(getBlockByLimitNextOnPBFTServlet), "/getblockbylimitnext"); + context + .addServlet(new ServletHolder(getBlockByLatestNumOnPBFTServlet), "/getblockbylatestnum"); + context.addServlet(new ServletHolder(getMerkleTreeVoucherInfoOnPBFTServlet), + "/getmerkletreevoucherinfo"); + context.addServlet(new ServletHolder(scanAndMarkNoteByIvkOnPBFTServlet), + "/scanandmarknotebyivk"); + context.addServlet(new ServletHolder(scanNoteByIvkOnPBFTServlet), "/scannotebyivk"); + context.addServlet(new ServletHolder(scanNoteByOvkOnPBFTServlet), "/scannotebyovk"); + context.addServlet(new ServletHolder(isSpendOnPBFTServlet), "/isspend"); + context.addServlet(new ServletHolder(triggerConstantContractOnPBFTServlet), + "/triggerconstantcontract"); + context.addServlet(new ServletHolder(estimateEnergyOnPBFTServlet), "/estimateenergy"); - // same as FullNode - context.addServlet(new ServletHolder(accountOnPBFTServlet), "/getaccount"); - context.addServlet(new ServletHolder(listWitnessesOnPBFTServlet), "/listwitnesses"); - context.addServlet(new ServletHolder(getAssetIssueListOnPBFTServlet), "/getassetissuelist"); - context.addServlet(new ServletHolder(getPaginatedAssetIssueListOnPBFTServlet), - "/getpaginatedassetissuelist"); - context - .addServlet(new ServletHolder(getAssetIssueByNameOnPBFTServlet), "/getassetissuebyname"); - context.addServlet(new ServletHolder(getAssetIssueByIdOnPBFTServlet), "/getassetissuebyid"); - context.addServlet(new ServletHolder(getAssetIssueListByNameOnPBFTServlet), - "/getassetissuelistbyname"); - context.addServlet(new ServletHolder(getNowBlockOnPBFTServlet), "/getnowblock"); - context.addServlet(new ServletHolder(getBlockByNumOnPBFTServlet), "/getblockbynum"); - context.addServlet(new ServletHolder(getDelegatedResourceOnPBFTServlet), - "/getdelegatedresource"); - context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexOnPBFTServlet), - "/getdelegatedresourceaccountindex"); - context.addServlet(new ServletHolder(getExchangeByIdOnPBFTServlet), "/getexchangebyid"); - context.addServlet(new ServletHolder(listExchangesOnPBFTServlet), "/listexchanges"); - context.addServlet(new ServletHolder(getAccountByIdOnPBFTServlet), "/getaccountbyid"); - context.addServlet(new ServletHolder(getBlockByIdOnPBFTServlet), "/getblockbyid"); - context - .addServlet(new ServletHolder(getBlockByLimitNextOnPBFTServlet), "/getblockbylimitnext"); - context - .addServlet(new ServletHolder(getBlockByLatestNumOnPBFTServlet), "/getblockbylatestnum"); - context.addServlet(new ServletHolder(getMerkleTreeVoucherInfoOnPBFTServlet), - "/getmerkletreevoucherinfo"); - context.addServlet(new ServletHolder(scanAndMarkNoteByIvkOnPBFTServlet), - "/scanandmarknotebyivk"); - context.addServlet(new ServletHolder(scanNoteByIvkOnPBFTServlet), "/scannotebyivk"); - context.addServlet(new ServletHolder(scanNoteByOvkOnPBFTServlet), "/scannotebyovk"); - context.addServlet(new ServletHolder(isSpendOnPBFTServlet), "/isspend"); - context.addServlet(new ServletHolder(triggerConstantContractOnPBFTServlet), - "/triggerconstantcontract"); - context.addServlet(new ServletHolder(estimateEnergyOnPBFTServlet), "/estimateenergy"); + // only for PBFTNode + context.addServlet(new ServletHolder(getTransactionByIdOnPBFTServlet), "/gettransactionbyid"); + context.addServlet(new ServletHolder(getTransactionInfoByIdOnPBFTServlet), + "/gettransactioninfobyid"); - // only for PBFTNode - context.addServlet(new ServletHolder(getTransactionByIdOnPBFTServlet), "/gettransactionbyid"); - context.addServlet(new ServletHolder(getTransactionInfoByIdOnPBFTServlet), - "/gettransactioninfobyid"); + context.addServlet(new ServletHolder(getTransactionCountByBlockNumOnPBFTServlet), + "/gettransactioncountbyblocknum"); - context.addServlet(new ServletHolder(getTransactionCountByBlockNumOnPBFTServlet), - "/gettransactioncountbyblocknum"); + context.addServlet(new ServletHolder(getNodeInfoOnPBFTServlet), "/getnodeinfo"); + context.addServlet(new ServletHolder(getBrokerageServlet), "/getBrokerage"); + context.addServlet(new ServletHolder(getRewardServlet), "/getReward"); - context.addServlet(new ServletHolder(getNodeInfoOnPBFTServlet), "/getnodeinfo"); - context.addServlet(new ServletHolder(getBrokerageServlet), "/getBrokerage"); - context.addServlet(new ServletHolder(getRewardServlet), "/getReward"); + context.addServlet(new ServletHolder(getMarketOrderByAccountOnPBFTServlet), + "/getmarketorderbyaccount"); + context.addServlet(new ServletHolder(getMarketOrderByIdOnPBFTServlet), + "/getmarketorderbyid"); + context.addServlet(new ServletHolder(getMarketPriceByPairOnPBFTServlet), + "/getmarketpricebypair"); + context.addServlet(new ServletHolder(getMarketOrderListByPairOnPBFTServlet), + "/getmarketorderlistbypair"); + context.addServlet(new ServletHolder(getMarketPairListOnPBFTServlet), + "/getmarketpairlist"); - context.addServlet(new ServletHolder(getMarketOrderByAccountOnPBFTServlet), - "/getmarketorderbyaccount"); - context.addServlet(new ServletHolder(getMarketOrderByIdOnPBFTServlet), - "/getmarketorderbyid"); - context.addServlet(new ServletHolder(getMarketPriceByPairOnPBFTServlet), - "/getmarketpricebypair"); - context.addServlet(new ServletHolder(getMarketOrderListByPairOnPBFTServlet), - "/getmarketorderlistbypair"); - context.addServlet(new ServletHolder(getMarketPairListOnPBFTServlet), - "/getmarketpairlist"); + context.addServlet(new ServletHolder(scanShieldedTRC20NotesByIvkOnPBFTServlet), + "/scanshieldedtrc20notesbyivk"); + context.addServlet(new ServletHolder(scanShieldedTRC20NotesByOvkOnPBFTServlet), + "/scanshieldedtrc20notesbyovk"); + context.addServlet(new ServletHolder(isShieldedTRC20ContractNoteSpentOnPBFTServlet), + "/isshieldedtrc20contractnotespent"); + context.addServlet(new ServletHolder(getBurnTrxOnPBFTServlet), + "/getburntrx"); + context.addServlet(new ServletHolder(getBandwidthPricesOnPBFTServlet), + "/getbandwidthprices"); + context.addServlet(new ServletHolder(getEnergyPricesOnPBFTServlet), + "/getenergyprices"); + context.addServlet(new ServletHolder(getBlockOnPBFTServlet), + "/getblock"); - context.addServlet(new ServletHolder(scanShieldedTRC20NotesByIvkOnPBFTServlet), - "/scanshieldedtrc20notesbyivk"); - context.addServlet(new ServletHolder(scanShieldedTRC20NotesByOvkOnPBFTServlet), - "/scanshieldedtrc20notesbyovk"); - context.addServlet(new ServletHolder(isShieldedTRC20ContractNoteSpentOnPBFTServlet), - "/isshieldedtrc20contractnotespent"); - context.addServlet(new ServletHolder(getBurnTrxOnPBFTServlet), - "/getburntrx"); - context.addServlet(new ServletHolder(getBandwidthPricesOnPBFTServlet), - "/getbandwidthprices"); - context.addServlet(new ServletHolder(getEnergyPricesOnPBFTServlet), - "/getenergyprices"); - context.addServlet(new ServletHolder(getBlockOnPBFTServlet), - "/getblock"); - - context.addServlet(new ServletHolder(getAvailableUnfreezeCountOnPBFTServlet), - "/getavailableunfreezecount"); - context.addServlet(new ServletHolder(getCanDelegatedMaxSizeOnPBFTServlet), - "/getcandelegatedmaxsize"); - context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountOnPBFTServlet), - "/getcanwithdrawunfreezeamount"); - context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexV2OnPBFTServlet), - "/getdelegatedresourceaccountindexv2"); - context.addServlet(new ServletHolder(getDelegatedResourceV2OnPBFTServlet), - "/getdelegatedresourcev2"); - - int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); - if (maxHttpConnectNumber > 0) { - apiServer.addBean(new ConnectionLimit(maxHttpConnectNumber, apiServer)); - } - - // filters the specified APIs - // when node is lite fullnode and openHistoryQueryWhenLiteFN is false - context.addFilter(new FilterHolder(liteFnQueryHttpFilter), "/*", - EnumSet.allOf(DispatcherType.class)); + context.addServlet(new ServletHolder(getAvailableUnfreezeCountOnPBFTServlet), + "/getavailableunfreezecount"); + context.addServlet(new ServletHolder(getCanDelegatedMaxSizeOnPBFTServlet), + "/getcandelegatedmaxsize"); + context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountOnPBFTServlet), + "/getcanwithdrawunfreezeamount"); + context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexV2OnPBFTServlet), + "/getdelegatedresourceaccountindexv2"); + context.addServlet(new ServletHolder(getDelegatedResourceV2OnPBFTServlet), + "/getdelegatedresourcev2"); + } - // api access filter - context.addFilter(new FilterHolder(httpApiAccessFilter), "/*", - EnumSet.allOf(DispatcherType.class)); + @Override + protected void addFilter(ServletContextHandler context) { + // filters the specified APIs + // when node is lite fullnode and openHistoryQueryWhenLiteFN is false + context.addFilter(new FilterHolder(liteFnQueryHttpFilter), "/*", + EnumSet.allOf(DispatcherType.class)); - super.start(); - } catch (Exception e) { - logger.debug("IOException: {}", e.getMessage()); - } + // api access filter + context.addFilter(new FilterHolder(httpApiAccessFilter), "/*", + EnumSet.allOf(DispatcherType.class)); } } diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java index 4bd3fbe4fef..aa566f56042 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java @@ -2,9 +2,7 @@ import com.google.protobuf.ByteString; import io.grpc.netty.NettyServerBuilder; -import io.grpc.protobuf.services.ProtoReflectionService; import io.grpc.stub.StreamObserver; -import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.tron.api.DatabaseGrpc.DatabaseImplBase; @@ -35,16 +33,11 @@ import org.tron.api.GrpcAPI.WitnessList; import org.tron.api.WalletSolidityGrpc.WalletSolidityImplBase; import org.tron.common.application.RpcService; -import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.Sha256Hash; import org.tron.core.capsule.BlockCapsule; import org.tron.core.config.args.Args; import org.tron.core.services.RpcApiService; -import org.tron.core.services.filter.LiteFnQueryGrpcInterceptor; -import org.tron.core.services.ratelimiter.PrometheusInterceptor; -import org.tron.core.services.ratelimiter.RateLimiterInterceptor; -import org.tron.core.services.ratelimiter.RpcApiAccessInterceptor; import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.DelegatedResourceAccountIndex; @@ -73,77 +66,16 @@ public class RpcApiServiceOnSolidity extends RpcService { @Autowired private RpcApiService rpcApiService; - @Autowired - private RateLimiterInterceptor rateLimiterInterceptor; - - @Autowired - private LiteFnQueryGrpcInterceptor liteFnQueryGrpcInterceptor; - - @Autowired - private RpcApiAccessInterceptor apiAccessInterceptor; - - @Autowired - private PrometheusInterceptor prometheusInterceptor; - - private final String executorName = "rpc-solidity-executor"; - - @Override - public void init() { - } - - @Override - public void init(CommonParameter args) { + public RpcApiServiceOnSolidity() { port = Args.getInstance().getRpcOnSolidityPort(); + enable = isFullNode() && Args.getInstance().isRpcSolidityEnable(); + executorName = "rpc-solidity-executor"; } @Override - public void start() { - try { - NettyServerBuilder serverBuilder = NettyServerBuilder.forPort(port) - .addService(new DatabaseApi()); - - CommonParameter parameter = Args.getInstance(); - - if (parameter.getRpcThreadNum() > 0) { - serverBuilder = serverBuilder - .executor(ExecutorServiceManager.newFixedThreadPool( - executorName, parameter.getRpcThreadNum())); - } - - serverBuilder = serverBuilder.addService(new WalletSolidityApi()); - - // Set configs from config.conf or default value - serverBuilder.maxConcurrentCallsPerConnection(parameter.getMaxConcurrentCallsPerConnection()) - .flowControlWindow(parameter.getFlowControlWindow()) - .maxConnectionIdle(parameter.getMaxConnectionIdleInMillis(), TimeUnit.MILLISECONDS) - .maxConnectionAge(parameter.getMaxConnectionAgeInMillis(), TimeUnit.MILLISECONDS) - .maxInboundMessageSize(parameter.getMaxMessageSize()) - .maxHeaderListSize(parameter.getMaxHeaderListSize()); - - // add a ratelimiter interceptor - serverBuilder.intercept(rateLimiterInterceptor); - - // add api access interceptor - serverBuilder.intercept(apiAccessInterceptor); - - // add lite fullnode query interceptor - serverBuilder.intercept(liteFnQueryGrpcInterceptor); - - // add prometheus interceptor - if (parameter.isMetricsPrometheusEnable()) { - serverBuilder.intercept(prometheusInterceptor); - } - - if (parameter.isRpcReflectionServiceEnable()) { - serverBuilder.addService(ProtoReflectionService.newInstance()); - } - - apiServer = serverBuilder.build(); - rateLimiterInterceptor.init(apiServer); - super.start(); - } catch (Exception e) { - logger.debug(e.getMessage(), e); - } + protected void addService(NettyServerBuilder serverBuilder) { + serverBuilder.addService(new DatabaseApi()); + serverBuilder.addService(new WalletSolidityApi()); } private TransactionExtention transaction2Extention(Transaction transaction) { diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java index f89be80c71b..b1d940ce2cd 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java @@ -10,7 +10,6 @@ import org.eclipse.jetty.servlet.ServletHolder; import org.springframework.beans.factory.annotation.Autowired; import org.tron.common.application.HttpService; -import org.tron.common.parameter.CommonParameter; import org.tron.core.config.args.Args; import org.tron.core.services.filter.HttpApiAccessFilter; import org.tron.core.services.filter.LiteFnQueryHttpFilter; @@ -178,144 +177,129 @@ public class HttpApiOnSolidityService extends HttpService { @Autowired private GetBlockOnSolidityServlet getBlockOnSolidityServlet; - @Override - public void init() { - - } - - @Override - public void init(CommonParameter args) { + public HttpApiOnSolidityService() { port = Args.getInstance().getSolidityHttpPort(); + enable = isFullNode() && Args.getInstance().isSolidityNodeHttpEnable(); + contextPath = "/"; } @Override - public void start() { - try { - apiServer = new Server(port); - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath("/"); - apiServer.setHandler(context); - - // same as FullNode - context.addServlet(new ServletHolder(accountOnSolidityServlet), "/walletsolidity/getaccount"); - context.addServlet(new ServletHolder(listWitnessesOnSolidityServlet), - "/walletsolidity/listwitnesses"); - context.addServlet(new ServletHolder(getAssetIssueListOnSolidityServlet), - "/walletsolidity/getassetissuelist"); - context.addServlet(new ServletHolder(getPaginatedAssetIssueListOnSolidityServlet), - "/walletsolidity/getpaginatedassetissuelist"); - context.addServlet(new ServletHolder(getAssetIssueByNameOnSolidityServlet), - "/walletsolidity/getassetissuebyname"); - context.addServlet(new ServletHolder(getAssetIssueByIdOnSolidityServlet), - "/walletsolidity/getassetissuebyid"); - context.addServlet(new ServletHolder(getAssetIssueListByNameOnSolidityServlet), - "/walletsolidity/getassetissuelistbyname"); - context.addServlet(new ServletHolder(getNowBlockOnSolidityServlet), - "/walletsolidity/getnowblock"); - context.addServlet(new ServletHolder(getBlockByNumOnSolidityServlet), - "/walletsolidity/getblockbynum"); - context.addServlet(new ServletHolder(getDelegatedResourceOnSolidityServlet), - "/walletsolidity/getdelegatedresource"); - context.addServlet(new ServletHolder(getDelegatedResourceV2OnSolidityServlet), - "/walletsolidity/getdelegatedresourcev2"); - context.addServlet(new ServletHolder(getCanDelegatedMaxSizeOnSolidityServlet), - "/walletsolidity/getcandelegatedmaxsize"); - context.addServlet(new ServletHolder(getAvailableUnfreezeCountOnSolidityServlet), - "/walletsolidity/getavailableunfreezecount"); - context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountOnSolidityServlet), - "/walletsolidity/getcanwithdrawunfreezeamount"); - context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexOnSolidityServlet), - "/walletsolidity/getdelegatedresourceaccountindex"); - context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexV2OnSolidityServlet), - "/walletsolidity/getdelegatedresourceaccountindexv2"); - context.addServlet(new ServletHolder(getExchangeByIdOnSolidityServlet), - "/walletsolidity/getexchangebyid"); - context.addServlet(new ServletHolder(listExchangesOnSolidityServlet), - "/walletsolidity/listexchanges"); - context.addServlet(new ServletHolder(getAccountByIdOnSolidityServlet), - "/walletsolidity/getaccountbyid"); - context.addServlet(new ServletHolder(getBlockByIdOnSolidityServlet), - "/walletsolidity/getblockbyid"); - context.addServlet(new ServletHolder(getBlockByLimitNextOnSolidityServlet), - "/walletsolidity/getblockbylimitnext"); - context.addServlet(new ServletHolder(getBlockByLatestNumOnSolidityServlet), - "/walletsolidity/getblockbylatestnum"); - // context.addServlet(new ServletHolder(getMerkleTreeVoucherInfoOnSolidityServlet), - // "/walletsolidity/getmerkletreevoucherinfo"); - // context.addServlet(new ServletHolder(scanAndMarkNoteByIvkOnSolidityServlet), - // "/walletsolidity/scanandmarknotebyivk"); - // context.addServlet(new ServletHolder(scanNoteByIvkOnSolidityServlet), - // "/walletsolidity/scannotebyivk"); - // context.addServlet(new ServletHolder(scanNoteByOvkOnSolidityServlet), - // "/walletsolidity/scannotebyovk"); - // context.addServlet(new ServletHolder(isSpendOnSolidityServlet), - // "/walletsolidity/isspend"); - context.addServlet(new ServletHolder(scanShieldedTRC20NotesByIvkOnSolidityServlet), - "/walletsolidity/scanshieldedtrc20notesbyivk"); - context.addServlet(new ServletHolder(scanShieldedTRC20NotesByOvkOnSolidityServlet), - "/walletsolidity/scanshieldedtrc20notesbyovk"); - context.addServlet(new ServletHolder(isShieldedTRC20ContractNoteSpentOnSolidityServlet), - "/walletsolidity/isshieldedtrc20contractnotespent"); - context.addServlet(new ServletHolder(triggerConstantContractOnSolidityServlet), - "/walletsolidity/triggerconstantcontract"); - context.addServlet(new ServletHolder(estimateEnergyOnSolidityServlet), - "/walletsolidity/estimateenergy"); - context.addServlet(new ServletHolder(getTransactionInfoByBlockNumOnSolidityServlet), - "/walletsolidity/gettransactioninfobyblocknum"); - context.addServlet(new ServletHolder(getMarketOrderByAccountOnSolidityServlet), - "/walletsolidity/getmarketorderbyaccount"); - context.addServlet(new ServletHolder(getMarketOrderByIdOnSolidityServlet), - "/walletsolidity/getmarketorderbyid"); - context.addServlet(new ServletHolder(getMarketPriceByPairOnSolidityServlet), - "/walletsolidity/getmarketpricebypair"); - context.addServlet(new ServletHolder(getMarketOrderListByPairOnSolidityServlet), - "/walletsolidity/getmarketorderlistbypair"); - context.addServlet(new ServletHolder(getMarketPairListOnSolidityServlet), - "/walletsolidity/getmarketpairlist"); + protected void addServlet(ServletContextHandler context) { + // same as FullNode + context.addServlet(new ServletHolder(accountOnSolidityServlet), "/walletsolidity/getaccount"); + context.addServlet(new ServletHolder(listWitnessesOnSolidityServlet), + "/walletsolidity/listwitnesses"); + context.addServlet(new ServletHolder(getAssetIssueListOnSolidityServlet), + "/walletsolidity/getassetissuelist"); + context.addServlet(new ServletHolder(getPaginatedAssetIssueListOnSolidityServlet), + "/walletsolidity/getpaginatedassetissuelist"); + context.addServlet(new ServletHolder(getAssetIssueByNameOnSolidityServlet), + "/walletsolidity/getassetissuebyname"); + context.addServlet(new ServletHolder(getAssetIssueByIdOnSolidityServlet), + "/walletsolidity/getassetissuebyid"); + context.addServlet(new ServletHolder(getAssetIssueListByNameOnSolidityServlet), + "/walletsolidity/getassetissuelistbyname"); + context.addServlet(new ServletHolder(getNowBlockOnSolidityServlet), + "/walletsolidity/getnowblock"); + context.addServlet(new ServletHolder(getBlockByNumOnSolidityServlet), + "/walletsolidity/getblockbynum"); + context.addServlet(new ServletHolder(getDelegatedResourceOnSolidityServlet), + "/walletsolidity/getdelegatedresource"); + context.addServlet(new ServletHolder(getDelegatedResourceV2OnSolidityServlet), + "/walletsolidity/getdelegatedresourcev2"); + context.addServlet(new ServletHolder(getCanDelegatedMaxSizeOnSolidityServlet), + "/walletsolidity/getcandelegatedmaxsize"); + context.addServlet(new ServletHolder(getAvailableUnfreezeCountOnSolidityServlet), + "/walletsolidity/getavailableunfreezecount"); + context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountOnSolidityServlet), + "/walletsolidity/getcanwithdrawunfreezeamount"); + context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexOnSolidityServlet), + "/walletsolidity/getdelegatedresourceaccountindex"); + context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexV2OnSolidityServlet), + "/walletsolidity/getdelegatedresourceaccountindexv2"); + context.addServlet(new ServletHolder(getExchangeByIdOnSolidityServlet), + "/walletsolidity/getexchangebyid"); + context.addServlet(new ServletHolder(listExchangesOnSolidityServlet), + "/walletsolidity/listexchanges"); + context.addServlet(new ServletHolder(getAccountByIdOnSolidityServlet), + "/walletsolidity/getaccountbyid"); + context.addServlet(new ServletHolder(getBlockByIdOnSolidityServlet), + "/walletsolidity/getblockbyid"); + context.addServlet(new ServletHolder(getBlockByLimitNextOnSolidityServlet), + "/walletsolidity/getblockbylimitnext"); + context.addServlet(new ServletHolder(getBlockByLatestNumOnSolidityServlet), + "/walletsolidity/getblockbylatestnum"); + // context.addServlet(new ServletHolder(getMerkleTreeVoucherInfoOnSolidityServlet), + // "/walletsolidity/getmerkletreevoucherinfo"); + // context.addServlet(new ServletHolder(scanAndMarkNoteByIvkOnSolidityServlet), + // "/walletsolidity/scanandmarknotebyivk"); + // context.addServlet(new ServletHolder(scanNoteByIvkOnSolidityServlet), + // "/walletsolidity/scannotebyivk"); + // context.addServlet(new ServletHolder(scanNoteByOvkOnSolidityServlet), + // "/walletsolidity/scannotebyovk"); + // context.addServlet(new ServletHolder(isSpendOnSolidityServlet), + // "/walletsolidity/isspend"); + context.addServlet(new ServletHolder(scanShieldedTRC20NotesByIvkOnSolidityServlet), + "/walletsolidity/scanshieldedtrc20notesbyivk"); + context.addServlet(new ServletHolder(scanShieldedTRC20NotesByOvkOnSolidityServlet), + "/walletsolidity/scanshieldedtrc20notesbyovk"); + context.addServlet(new ServletHolder(isShieldedTRC20ContractNoteSpentOnSolidityServlet), + "/walletsolidity/isshieldedtrc20contractnotespent"); + context.addServlet(new ServletHolder(triggerConstantContractOnSolidityServlet), + "/walletsolidity/triggerconstantcontract"); + context.addServlet(new ServletHolder(estimateEnergyOnSolidityServlet), + "/walletsolidity/estimateenergy"); + context.addServlet(new ServletHolder(getTransactionInfoByBlockNumOnSolidityServlet), + "/walletsolidity/gettransactioninfobyblocknum"); + context.addServlet(new ServletHolder(getMarketOrderByAccountOnSolidityServlet), + "/walletsolidity/getmarketorderbyaccount"); + context.addServlet(new ServletHolder(getMarketOrderByIdOnSolidityServlet), + "/walletsolidity/getmarketorderbyid"); + context.addServlet(new ServletHolder(getMarketPriceByPairOnSolidityServlet), + "/walletsolidity/getmarketpricebypair"); + context.addServlet(new ServletHolder(getMarketOrderListByPairOnSolidityServlet), + "/walletsolidity/getmarketorderlistbypair"); + context.addServlet(new ServletHolder(getMarketPairListOnSolidityServlet), + "/walletsolidity/getmarketpairlist"); - // only for SolidityNode - context.addServlet(new ServletHolder(getTransactionByIdOnSolidityServlet), - "/walletsolidity/gettransactionbyid"); - context.addServlet(new ServletHolder(getTransactionInfoByIdOnSolidityServlet), - "/walletsolidity/gettransactioninfobyid"); + // only for SolidityNode + context.addServlet(new ServletHolder(getTransactionByIdOnSolidityServlet), + "/walletsolidity/gettransactionbyid"); + context.addServlet(new ServletHolder(getTransactionInfoByIdOnSolidityServlet), + "/walletsolidity/gettransactioninfobyid"); - context.addServlet(new ServletHolder(getTransactionCountByBlockNumOnSolidityServlet), - "/walletsolidity/gettransactioncountbyblocknum"); + context.addServlet(new ServletHolder(getTransactionCountByBlockNumOnSolidityServlet), + "/walletsolidity/gettransactioncountbyblocknum"); - context.addServlet(new ServletHolder(getNodeInfoOnSolidityServlet), "/wallet/getnodeinfo"); - context.addServlet(new ServletHolder(getNodeInfoOnSolidityServlet), - "/walletsolidity/getnodeinfo"); - context.addServlet(new ServletHolder(getBrokerageServlet), "/walletsolidity/getBrokerage"); - context.addServlet(new ServletHolder(getRewardServlet), "/walletsolidity/getReward"); - context - .addServlet(new ServletHolder(getBurnTrxOnSolidityServlet), "/walletsolidity/getburntrx"); - context.addServlet(new ServletHolder(getBandwidthPricesOnSolidityServlet), - "/walletsolidity/getbandwidthprices"); - context.addServlet(new ServletHolder(getEnergyPricesOnSolidityServlet), - "/walletsolidity/getenergyprices"); + context.addServlet(new ServletHolder(getNodeInfoOnSolidityServlet), "/wallet/getnodeinfo"); + context.addServlet(new ServletHolder(getNodeInfoOnSolidityServlet), + "/walletsolidity/getnodeinfo"); + context.addServlet(new ServletHolder(getBrokerageServlet), "/walletsolidity/getBrokerage"); + context.addServlet(new ServletHolder(getRewardServlet), "/walletsolidity/getReward"); + context + .addServlet(new ServletHolder(getBurnTrxOnSolidityServlet), "/walletsolidity/getburntrx"); + context.addServlet(new ServletHolder(getBandwidthPricesOnSolidityServlet), + "/walletsolidity/getbandwidthprices"); + context.addServlet(new ServletHolder(getEnergyPricesOnSolidityServlet), + "/walletsolidity/getenergyprices"); - context.addServlet(new ServletHolder(getBlockOnSolidityServlet), - "/walletsolidity/getblock"); + context.addServlet(new ServletHolder(getBlockOnSolidityServlet), + "/walletsolidity/getblock"); - // filters the specified APIs - // when node is lite fullnode and openHistoryQueryWhenLiteFN is false - context.addFilter(new FilterHolder(liteFnQueryHttpFilter), "/*", - EnumSet.allOf(DispatcherType.class)); + } - // api access filter - context.addFilter(new FilterHolder(httpApiAccessFilter), "/walletsolidity/*", - EnumSet.allOf(DispatcherType.class)); - context.getServletHandler().getFilterMappings()[1] - .setPathSpecs(new String[] {"/walletsolidity/*", - "/wallet/getnodeinfo"}); + @Override + protected void addFilter(ServletContextHandler context) { + // filters the specified APIs + // when node is lite fullnode and openHistoryQueryWhenLiteFN is false + context.addFilter(new FilterHolder(liteFnQueryHttpFilter), "/*", + EnumSet.allOf(DispatcherType.class)); - int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); - if (maxHttpConnectNumber > 0) { - apiServer.addBean(new ConnectionLimit(maxHttpConnectNumber, apiServer)); - } - super.start(); - } catch (Exception e) { - logger.debug("IOException: {}", e.getMessage()); - } + // api access filter + context.addFilter(new FilterHolder(httpApiAccessFilter), "/walletsolidity/*", + EnumSet.allOf(DispatcherType.class)); + context.getServletHandler().getFilterMappings()[1] + .setPathSpecs(new String[] {"/walletsolidity/*", + "/wallet/getnodeinfo"}); } } diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/FullNodeJsonRpcHttpService.java b/framework/src/main/java/org/tron/core/services/jsonrpc/FullNodeJsonRpcHttpService.java index ff017f9562e..566ad33a722 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/FullNodeJsonRpcHttpService.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/FullNodeJsonRpcHttpService.java @@ -3,8 +3,6 @@ import java.util.EnumSet; import javax.servlet.DispatcherType; import lombok.extern.slf4j.Slf4j; -import org.eclipse.jetty.server.ConnectionLimit; -import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHandler; @@ -12,7 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.common.application.HttpService; -import org.tron.common.parameter.CommonParameter; +import org.tron.core.config.args.Args; import org.tron.core.services.filter.HttpInterceptor; @Component @@ -22,41 +20,24 @@ public class FullNodeJsonRpcHttpService extends HttpService { @Autowired private JsonRpcServlet jsonRpcServlet; - @Override - public void init() { + public FullNodeJsonRpcHttpService() { + port = Args.getInstance().getJsonRpcHttpFullNodePort(); + enable = isFullNode() && Args.getInstance().isJsonRpcHttpFullNodeEnable(); + contextPath = "/"; } @Override - public void init(CommonParameter args) { - port = CommonParameter.getInstance().getJsonRpcHttpFullNodePort(); + protected void addServlet(ServletContextHandler context) { + context.addServlet(new ServletHolder(jsonRpcServlet), "/jsonrpc"); } @Override - public void start() { - try { - apiServer = new Server(port); - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath("/"); - apiServer.setHandler(context); - - context.addServlet(new ServletHolder(jsonRpcServlet), "/jsonrpc"); - - int maxHttpConnectNumber = CommonParameter.getInstance().getMaxHttpConnectNumber(); - if (maxHttpConnectNumber > 0) { - apiServer.addBean(new ConnectionLimit(maxHttpConnectNumber, apiServer)); - } - - // filter - ServletHandler handler = new ServletHandler(); - FilterHolder fh = handler - .addFilterWithMapping(HttpInterceptor.class, "/*", - EnumSet.of(DispatcherType.REQUEST)); - context.addFilter(fh, "/*", EnumSet.of(DispatcherType.REQUEST)); - - super.start(); - - } catch (Exception e) { - logger.debug("IOException: {}", e.getMessage()); - } + protected void addFilter(ServletContextHandler context) { + // filter + ServletHandler handler = new ServletHandler(); + FilterHolder fh = handler + .addFilterWithMapping(HttpInterceptor.class, "/*", + EnumSet.of(DispatcherType.REQUEST)); + context.addFilter(fh, "/*", EnumSet.of(DispatcherType.REQUEST)); } } diff --git a/framework/src/main/java/org/tron/core/zen/ZksnarkInitService.java b/framework/src/main/java/org/tron/core/zen/ZksnarkInitService.java index 8b9aafe4715..04405dfc758 100644 --- a/framework/src/main/java/org/tron/core/zen/ZksnarkInitService.java +++ b/framework/src/main/java/org/tron/core/zen/ZksnarkInitService.java @@ -6,7 +6,6 @@ import javax.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; -import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Component; import org.tron.common.zksnark.JLibrustzcash; import org.tron.common.zksnark.LibrustzcashParam; @@ -14,7 +13,6 @@ @Slf4j(topic = "API") @Component -@DependsOn("fullNodeHttpApiService") public class ZksnarkInitService { @PostConstruct diff --git a/framework/src/main/java/org/tron/program/FullNode.java b/framework/src/main/java/org/tron/program/FullNode.java index 0fd87eb5de0..b7adf0ffe1a 100644 --- a/framework/src/main/java/org/tron/program/FullNode.java +++ b/framework/src/main/java/org/tron/program/FullNode.java @@ -15,16 +15,6 @@ import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.net.P2pEventHandlerImpl; -import org.tron.core.services.RpcApiService; -import org.tron.core.services.http.FullNodeHttpApiService; -import org.tron.core.services.interfaceJsonRpcOnPBFT.JsonRpcServiceOnPBFT; -import org.tron.core.services.interfaceJsonRpcOnSolidity.JsonRpcServiceOnSolidity; -import org.tron.core.services.interfaceOnPBFT.RpcApiServiceOnPBFT; -import org.tron.core.services.interfaceOnPBFT.http.PBFT.HttpApiOnPBFTService; -import org.tron.core.services.interfaceOnSolidity.RpcApiServiceOnSolidity; -import org.tron.core.services.interfaceOnSolidity.http.solidity.HttpApiOnSolidityService; -import org.tron.core.services.jsonrpc.FullNodeJsonRpcHttpService; @Slf4j(topic = "app") public class FullNode { @@ -80,55 +70,6 @@ public static void main(String[] args) { context.refresh(); Application appT = ApplicationFactory.create(context); context.registerShutdownHook(); - - // grpc api server - RpcApiService rpcApiService = context.getBean(RpcApiService.class); - appT.addService(rpcApiService); - - // http api server - FullNodeHttpApiService httpApiService = context.getBean(FullNodeHttpApiService.class); - if (CommonParameter.getInstance().fullNodeHttpEnable) { - appT.addService(httpApiService); - } - - // JSON-RPC http server - if (CommonParameter.getInstance().jsonRpcHttpFullNodeEnable) { - FullNodeJsonRpcHttpService jsonRpcHttpService = - context.getBean(FullNodeJsonRpcHttpService.class); - appT.addService(jsonRpcHttpService); - } - - // full node and solidity node fuse together - // provide solidity rpc and http server on the full node. - RpcApiServiceOnSolidity rpcApiServiceOnSolidity = context - .getBean(RpcApiServiceOnSolidity.class); - appT.addService(rpcApiServiceOnSolidity); - HttpApiOnSolidityService httpApiOnSolidityService = context - .getBean(HttpApiOnSolidityService.class); - if (CommonParameter.getInstance().solidityNodeHttpEnable) { - appT.addService(httpApiOnSolidityService); - } - - // JSON-RPC on solidity - if (CommonParameter.getInstance().jsonRpcHttpSolidityNodeEnable) { - JsonRpcServiceOnSolidity jsonRpcServiceOnSolidity = context - .getBean(JsonRpcServiceOnSolidity.class); - appT.addService(jsonRpcServiceOnSolidity); - } - - // PBFT API (HTTP and GRPC) - RpcApiServiceOnPBFT rpcApiServiceOnPBFT = context - .getBean(RpcApiServiceOnPBFT.class); - appT.addService(rpcApiServiceOnPBFT); - HttpApiOnPBFTService httpApiOnPBFTService = context - .getBean(HttpApiOnPBFTService.class); - appT.addService(httpApiOnPBFTService); - - // JSON-RPC on PBFT - if (CommonParameter.getInstance().jsonRpcHttpPBFTNodeEnable) { - JsonRpcServiceOnPBFT jsonRpcServiceOnPBFT = context.getBean(JsonRpcServiceOnPBFT.class); - appT.addService(jsonRpcServiceOnPBFT); - } appT.startup(); appT.blockUntilShutdown(); } diff --git a/framework/src/main/java/org/tron/program/SolidityNode.java b/framework/src/main/java/org/tron/program/SolidityNode.java index 4cf71177803..8def8ed7ebc 100644 --- a/framework/src/main/java/org/tron/program/SolidityNode.java +++ b/framework/src/main/java/org/tron/program/SolidityNode.java @@ -6,9 +6,8 @@ import java.util.concurrent.atomic.AtomicLong; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.BooleanUtils; -import org.springframework.context.ApplicationContext; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; @@ -21,8 +20,6 @@ import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; -import org.tron.core.services.RpcApiService; -import org.tron.core.services.http.solidity.SolidityNodeHttpApiService; import org.tron.protos.Protocol.Block; @Slf4j(topic = "app") @@ -71,9 +68,6 @@ public static void main(String[] args) { } parameter.setSolidityNode(true); - TronApplicationContext context = new TronApplicationContext(DefaultConfig.class); - context.registerShutdownHook(); - if (parameter.isHelp()) { logger.info("Here is the help message."); return; @@ -81,18 +75,17 @@ public static void main(String[] args) { // init metrics first Metrics.init(); + DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); + beanFactory.setAllowCircularReferences(false); + TronApplicationContext context = + new TronApplicationContext(beanFactory); + context.register(DefaultConfig.class); + context.refresh(); Application appT = ApplicationFactory.create(context); - RpcApiService rpcApiService = context.getBean(RpcApiService.class); - appT.addService(rpcApiService); - //http - SolidityNodeHttpApiService httpApiService = context.getBean(SolidityNodeHttpApiService.class); - if (CommonParameter.getInstance().solidityNodeHttpEnable) { - appT.addService(httpApiService); - } - + context.registerShutdownHook(); + appT.startup(); SolidityNode node = new SolidityNode(appT.getDbManager()); node.start(); - appT.startup(); appT.blockUntilShutdown(); } diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index f9fc2dd673d..49b11d41e42 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -210,6 +210,8 @@ node { fullNodePort = 8090 solidityEnable = true solidityPort = 8091 + PBFTEnable = true + PBFTPort = 8092 } # use your ipv6 address for node discovery and tcp connection, default false @@ -226,8 +228,12 @@ node { } rpc { + enable = true port = 50051 - #solidityPort = 50061 + solidityEnable = true + solidityPort = 50061 + PBFTEnable = true + PBFTPort = 50071 # Number of gRPC thread, default availableProcessors / 2 # thread = 16 diff --git a/framework/src/test/java/org/tron/common/jetty/JettyServerTest.java b/framework/src/test/java/org/tron/common/jetty/JettyServerTest.java index fec29de0cb6..fbb2721f502 100644 --- a/framework/src/test/java/org/tron/common/jetty/JettyServerTest.java +++ b/framework/src/test/java/org/tron/common/jetty/JettyServerTest.java @@ -15,6 +15,7 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.tron.common.utils.PublicMethod; @Slf4j public class JettyServerTest { @@ -25,7 +26,7 @@ public class JettyServerTest { public static void startJetty() throws Exception { server = new Server(); ServerConnector connector = new ServerConnector(server); - connector.setPort(0); + connector.setPort(PublicMethod.chooseRandomPort()); server.addConnector(connector); ServletContextHandler context = new ServletContextHandler(); diff --git a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java index 61f34b647c5..196941328b4 100644 --- a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java @@ -17,11 +17,14 @@ import com.google.common.collect.Lists; import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; import io.grpc.internal.GrpcUtil; import io.grpc.netty.NettyServerBuilder; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; @@ -31,6 +34,7 @@ import org.tron.common.args.GenesisBlock; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.LocalWitnesses; import org.tron.common.utils.PublicMethod; import org.tron.core.Constant; @@ -53,7 +57,7 @@ public void destroy() { @Test public void get() { - Args.setParam(new String[] {"-w"}, Constant.TEST_CONF); + Args.setParam(new String[] {"-w", "-c", Constant.TEST_CONF}, Constant.TESTNET_CONF); CommonParameter parameter = Args.getInstance(); @@ -65,7 +69,7 @@ public void get() { Args.setLocalWitnesses(localWitnesses); address = ByteArray.toHexString(Args.getLocalWitnesses() .getWitnessAccountAddress(CommonParameter.getInstance().isECKeyCryptoEngine())); - + Assert.assertEquals(Constant.ADD_PRE_FIX_STRING_TESTNET, DecodeUtil.addressPreFixString); Assert.assertEquals(0, parameter.getBackupPriority()); Assert.assertEquals(3000, parameter.getKeepAliveInterval()); @@ -149,7 +153,96 @@ public void testIpFromLibP2p() @Test public void testOldRewardOpt() { thrown.expect(IllegalArgumentException.class); - Args.setParam(new String[] {"-w"}, "args-test.conf"); + Args.setParam(new String[] {"-w", "-c", "args-test.conf"}, Constant.TESTNET_CONF); + } + + @Test + public void testInitService() { + Map storage = new HashMap<>(); + // avoid the exception for the missing storage + storage.put("storage.db.directory", "database"); + Config config = ConfigFactory.defaultOverrides().withFallback(ConfigFactory.parseMap(storage)); + // test default value + Args.setParam(config); + Assert.assertTrue(Args.getInstance().isRpcEnable()); + Assert.assertTrue(Args.getInstance().isRpcSolidityEnable()); + Assert.assertTrue(Args.getInstance().isRpcPBFTEnable()); + Assert.assertTrue(Args.getInstance().isFullNodeHttpEnable()); + Assert.assertTrue(Args.getInstance().isSolidityNodeHttpEnable()); + Assert.assertTrue(Args.getInstance().isPBFTHttpEnable()); + Assert.assertFalse(Args.getInstance().isJsonRpcHttpFullNodeEnable()); + Assert.assertFalse(Args.getInstance().isJsonRpcHttpSolidityNodeEnable()); + Assert.assertFalse(Args.getInstance().isJsonRpcHttpPBFTNodeEnable()); + Args.clearParam(); + // test set all true value + storage.put("node.rpc.enable", "true"); + storage.put("node.rpc.solidityEnable", "true"); + storage.put("node.rpc.PBFTEnable", "true"); + storage.put("node.http.fullNodeEnable", "true"); + storage.put("node.http.solidityEnable", "true"); + storage.put("node.http.PBFTEnable", "true"); + storage.put("node.jsonrpc.httpFullNodeEnable", "true"); + storage.put("node.jsonrpc.httpSolidityEnable", "true"); + storage.put("node.jsonrpc.httpPBFTEnable", "true"); + config = ConfigFactory.defaultOverrides().withFallback(ConfigFactory.parseMap(storage)); + // test value + Args.setParam(config); + Assert.assertTrue(Args.getInstance().isRpcEnable()); + Assert.assertTrue(Args.getInstance().isRpcSolidityEnable()); + Assert.assertTrue(Args.getInstance().isRpcPBFTEnable()); + Assert.assertTrue(Args.getInstance().isFullNodeHttpEnable()); + Assert.assertTrue(Args.getInstance().isSolidityNodeHttpEnable()); + Assert.assertTrue(Args.getInstance().isPBFTHttpEnable()); + Assert.assertTrue(Args.getInstance().isJsonRpcHttpFullNodeEnable()); + Assert.assertTrue(Args.getInstance().isJsonRpcHttpSolidityNodeEnable()); + Assert.assertTrue(Args.getInstance().isJsonRpcHttpPBFTNodeEnable()); + Args.clearParam(); + // test set all false value + storage.put("node.rpc.enable", "false"); + storage.put("node.rpc.solidityEnable", "false"); + storage.put("node.rpc.PBFTEnable", "false"); + storage.put("node.http.fullNodeEnable", "false"); + storage.put("node.http.solidityEnable", "false"); + storage.put("node.http.PBFTEnable", "false"); + storage.put("node.jsonrpc.httpFullNodeEnable", "false"); + storage.put("node.jsonrpc.httpSolidityEnable", "false"); + storage.put("node.jsonrpc.httpPBFTEnable", "false"); + config = ConfigFactory.defaultOverrides().withFallback(ConfigFactory.parseMap(storage)); + // test value + Args.setParam(config); + Assert.assertFalse(Args.getInstance().isRpcEnable()); + Assert.assertFalse(Args.getInstance().isRpcSolidityEnable()); + Assert.assertFalse(Args.getInstance().isRpcPBFTEnable()); + Assert.assertFalse(Args.getInstance().isFullNodeHttpEnable()); + Assert.assertFalse(Args.getInstance().isSolidityNodeHttpEnable()); + Assert.assertFalse(Args.getInstance().isPBFTHttpEnable()); + Assert.assertFalse(Args.getInstance().isJsonRpcHttpFullNodeEnable()); + Assert.assertFalse(Args.getInstance().isJsonRpcHttpSolidityNodeEnable()); + Assert.assertFalse(Args.getInstance().isJsonRpcHttpPBFTNodeEnable()); + Args.clearParam(); + // test set random value + storage.put("node.rpc.enable", "false"); + storage.put("node.rpc.solidityEnable", "false"); + storage.put("node.rpc.PBFTEnable", "true"); + storage.put("node.http.fullNodeEnable", "false"); + storage.put("node.http.solidityEnable", "true"); + storage.put("node.http.PBFTEnable", "false"); + storage.put("node.jsonrpc.httpFullNodeEnable", "true"); + storage.put("node.jsonrpc.httpSolidityEnable", "false"); + storage.put("node.jsonrpc.httpPBFTEnable", "true"); + config = ConfigFactory.defaultOverrides().withFallback(ConfigFactory.parseMap(storage)); + // test value + Args.setParam(config); + Assert.assertFalse(Args.getInstance().isRpcEnable()); + Assert.assertFalse(Args.getInstance().isRpcSolidityEnable()); + Assert.assertTrue(Args.getInstance().isRpcPBFTEnable()); + Assert.assertFalse(Args.getInstance().isFullNodeHttpEnable()); + Assert.assertTrue(Args.getInstance().isSolidityNodeHttpEnable()); + Assert.assertFalse(Args.getInstance().isPBFTHttpEnable()); + Assert.assertTrue(Args.getInstance().isJsonRpcHttpFullNodeEnable()); + Assert.assertFalse(Args.getInstance().isJsonRpcHttpSolidityNodeEnable()); + Assert.assertTrue(Args.getInstance().isJsonRpcHttpPBFTNodeEnable()); + Args.clearParam(); } } diff --git a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java index b3ed26b591f..6bf83ddc534 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java @@ -21,6 +21,7 @@ import org.tron.common.parameter.CommonParameter; import org.tron.common.prometheus.Metrics; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.PublicMethod; import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -66,9 +67,13 @@ public class JsonrpcServiceTest extends BaseTest { static { Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); CommonParameter.getInstance().setJsonRpcHttpFullNodeEnable(true); + CommonParameter.getInstance().setJsonRpcHttpFullNodePort(PublicMethod.chooseRandomPort()); CommonParameter.getInstance().setJsonRpcHttpPBFTNodeEnable(true); + CommonParameter.getInstance().setJsonRpcHttpPBFTPort(PublicMethod.chooseRandomPort()); CommonParameter.getInstance().setJsonRpcHttpSolidityNodeEnable(true); + CommonParameter.getInstance().setJsonRpcHttpSolidityPort(PublicMethod.chooseRandomPort()); CommonParameter.getInstance().setMetricsPrometheusEnable(true); + CommonParameter.getInstance().setMetricsPrometheusPort(PublicMethod.chooseRandomPort()); Metrics.init(); OWNER_ADDRESS = @@ -265,7 +270,6 @@ public void testGetTransactionByHash() { @Test public void testGetBlockByNumber2() { - fullNodeJsonRpcHttpService.init(Args.getInstance()); fullNodeJsonRpcHttpService.start(); JsonArray params = new JsonArray(); params.add(ByteArray.toJsonHex(blockCapsule.getNum())); @@ -277,7 +281,8 @@ public void testGetBlockByNumber2() { requestBody.addProperty("id", 1); CloseableHttpResponse response; try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpPost httpPost = new HttpPost("http://127.0.0.1:8545/jsonrpc"); + HttpPost httpPost = new HttpPost("http://127.0.0.1/" + + CommonParameter.getInstance().getJsonRpcHttpFullNodePort() + "/jsonrpc"); httpPost.addHeader("Content-Type", "application/json"); httpPost.setEntity(new StringEntity(requestBody.toString())); response = httpClient.execute(httpPost); @@ -303,9 +308,7 @@ public void testGetBlockByNumber2() { @Test public void testServicesInit() { try { - jsonRpcServiceOnPBFT.init(Args.getInstance()); jsonRpcServiceOnPBFT.start(); - jsonRpcServiceOnSolidity.init(Args.getInstance()); jsonRpcServiceOnSolidity.start(); } finally { jsonRpcServiceOnPBFT.stop(); diff --git a/framework/src/test/java/org/tron/core/metrics/MetricsApiServiceTest.java b/framework/src/test/java/org/tron/core/metrics/MetricsApiServiceTest.java index 51a46b09388..e36029c6141 100644 --- a/framework/src/test/java/org/tron/core/metrics/MetricsApiServiceTest.java +++ b/framework/src/test/java/org/tron/core/metrics/MetricsApiServiceTest.java @@ -44,7 +44,7 @@ public void init() throws IOException { "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory }, - "config.conf" + Constant.TEST_CONF ); CommonParameter parameter = Args.getInstance(); parameter.setNodeListenPort(port); @@ -52,9 +52,7 @@ public void init() throws IOException { parameter.setNodeExternalIp("127.0.0.1"); context = new TronApplicationContext(DefaultConfig.class); appT = ApplicationFactory.create(context); - rpcApiService = context.getBean(RpcApiService.class); metricsApiService = context.getBean(MetricsApiService.class); - appT.addService(rpcApiService); appT.startup(); } diff --git a/framework/src/test/java/org/tron/core/net/BaseNet.java b/framework/src/test/java/org/tron/core/net/BaseNet.java index 7ae8b355168..65771bae952 100644 --- a/framework/src/test/java/org/tron/core/net/BaseNet.java +++ b/framework/src/test/java/org/tron/core/net/BaseNet.java @@ -30,12 +30,12 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.FileUtil; +import org.tron.common.utils.PublicMethod; import org.tron.common.utils.ReflectUtils; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.net.peer.PeerConnection; -import org.tron.core.services.RpcApiService; @Slf4j public class BaseNet { @@ -48,7 +48,6 @@ public class BaseNet { protected static TronApplicationContext context; - private static RpcApiService rpcApiService; private static Application appT; private static TronNetDelegate tronNetDelegate; @@ -98,10 +97,15 @@ public static void init() throws Exception { parameter.setNodeListenPort(port); parameter.getSeedNode().getAddressList().clear(); parameter.setNodeExternalIp(Constant.LOCAL_HOST); + parameter.setRpcEnable(true); + parameter.setRpcPort(PublicMethod.chooseRandomPort()); + parameter.setRpcSolidityEnable(false); + parameter.setRpcPBFTEnable(false); + parameter.setFullNodeHttpEnable(false); + parameter.setSolidityNodeHttpEnable(false); + parameter.setPBFTHttpEnable(false); context = new TronApplicationContext(DefaultConfig.class); appT = ApplicationFactory.create(context); - rpcApiService = context.getBean(RpcApiService.class); - appT.addService(rpcApiService); appT.startup(); try { Thread.sleep(2000); diff --git a/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java b/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java index 9bc942d6684..a7fb2644495 100755 --- a/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java +++ b/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java @@ -17,6 +17,8 @@ import org.junit.Test; import org.tron.common.BaseTest; import org.tron.common.crypto.ECKey; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.PublicMethod; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.Utils; import org.tron.core.ChainBaseManager; @@ -36,6 +38,8 @@ public class PbftApiTest extends BaseTest { @BeforeClass public static void init() { Args.setParam(new String[]{"-d", dbPath(), "-w"}, Constant.TEST_CONF); + CommonParameter.getInstance().setPBFTHttpEnable(true); + CommonParameter.getInstance().setPBFTHttpPort(PublicMethod.chooseRandomPort()); } @Test @@ -58,11 +62,11 @@ public void pbftapi() throws IOException { Assert.assertTrue(dynamicPropertiesStore.getLatestBlockHeaderNumber() >= 10); commonDataBase.saveLatestPbftBlockNum(6); - httpApiOnPBFTService.init(Args.getInstance()); httpApiOnPBFTService.start(); CloseableHttpResponse response; try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpGet httpGet = new HttpGet("http://127.0.0.1:8092/walletpbft/getnowblock"); + HttpGet httpGet = new HttpGet("http://127.0.0.1/" + + CommonParameter.getInstance().getPBFTHttpPort() + "/walletpbft/getnowblock"); response = httpClient.execute(httpGet); String responseString = EntityUtils.toString(response.getEntity()); JSONObject jsonObject = JSON.parseObject(responseString); diff --git a/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java b/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java index 83930403312..7179215393f 100644 --- a/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java +++ b/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java @@ -135,8 +135,11 @@ public static void init() throws IOException { Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); String OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + getInstance().setRpcEnable(true); getInstance().setRpcPort(PublicMethod.chooseRandomPort()); + getInstance().setRpcSolidityEnable(true); getInstance().setRpcOnSolidityPort(PublicMethod.chooseRandomPort()); + getInstance().setRpcPBFTEnable(true); getInstance().setRpcOnPBFTPort(PublicMethod.chooseRandomPort()); getInstance().setMetricsPrometheusPort(PublicMethod.chooseRandomPort()); getInstance().setMetricsPrometheusEnable(true); @@ -164,11 +167,6 @@ public static void init() throws IOException { blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); blockingStubPBFT = WalletSolidityGrpc.newBlockingStub(channelPBFT); - RpcApiService rpcApiService = context.getBean(RpcApiService.class); - RpcApiServiceOnSolidity rpcApiServiceOnSolidity = - context.getBean(RpcApiServiceOnSolidity.class); - RpcApiServiceOnPBFT rpcApiServiceOnPBFT = context.getBean(RpcApiServiceOnPBFT.class); - Manager manager = context.getBean(Manager.class); ownerAddress = ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)); @@ -178,9 +176,6 @@ public static void init() throws IOException { manager.getDynamicPropertiesStore().saveAllowShieldedTransaction(1); manager.getDynamicPropertiesStore().saveAllowShieldedTRC20Transaction(1); Application appTest = ApplicationFactory.create(context); - appTest.addService(rpcApiService); - appTest.addService(rpcApiServiceOnSolidity); - appTest.addService(rpcApiServiceOnPBFT); appTest.startup(); } diff --git a/framework/src/test/java/org/tron/core/services/WalletApiTest.java b/framework/src/test/java/org/tron/core/services/WalletApiTest.java index 0a87c348fdb..8890d4bfd9e 100644 --- a/framework/src/test/java/org/tron/core/services/WalletApiTest.java +++ b/framework/src/test/java/org/tron/core/services/WalletApiTest.java @@ -5,8 +5,8 @@ import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; +import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.tron.api.GrpcAPI.EmptyMessage; @@ -14,7 +14,7 @@ import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; -import org.tron.common.utils.client.Configuration; +import org.tron.common.utils.PublicMethod; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; @@ -23,34 +23,34 @@ @Slf4j public class WalletApiTest { - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); + @ClassRule + public static TemporaryFolder temporaryFolder = new TemporaryFolder(); private static TronApplicationContext context; - private String fullnode = Configuration.getByPath("testng.conf") - .getStringList("fullnode.ip.list").get(0); - private RpcApiService rpcApiService; - private Application appT; + private static Application appT; - @Before - public void init() throws IOException { + + @BeforeClass + public static void init() throws IOException { Args.setParam(new String[]{ "-d", temporaryFolder.newFolder().toString(), "--p2p-disable", "true"}, Constant.TEST_CONF); + Args.getInstance().setRpcPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setRpcEnable(true); context = new TronApplicationContext(DefaultConfig.class); appT = ApplicationFactory.create(context); - rpcApiService = context.getBean(RpcApiService.class); - appT.addService(rpcApiService); appT.startup(); } @Test public void listNodesTest() { + String fullNode = String.format("%s:%d", "127.0.0.1", + Args.getInstance().getRpcPort()); WalletGrpc.WalletBlockingStub walletStub = WalletGrpc - .newBlockingStub(ManagedChannelBuilder.forTarget(fullnode) + .newBlockingStub(ManagedChannelBuilder.forTarget(fullNode) .usePlaintext() .build()); Assert.assertTrue(walletStub.listNodes(EmptyMessage.getDefaultInstance()) - .getNodesList().size() == 0); + .getNodesList().isEmpty()); } @After diff --git a/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java b/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java index 5f883fc8c07..9484155a0b7 100644 --- a/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java @@ -14,10 +14,10 @@ import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; import org.tron.common.BaseTest; import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.PublicMethod; import org.tron.core.Constant; import org.tron.core.config.args.Args; import org.tron.core.services.http.FullNodeHttpApiService; @@ -39,21 +39,17 @@ public class HttpApiAccessFilterTest extends BaseTest { static { Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); Args.getInstance().setFullNodeAllowShieldedTransactionArgs(false); - } - - /** - * init dependencies. - */ - @Before - public void init() { - appT.addService(httpApiService); - appT.addService(httpApiOnSolidityService); - appT.addService(httpApiOnPBFTService); - appT.startup(); + Args.getInstance().setFullNodeHttpEnable(true); + Args.getInstance().setFullNodeHttpPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setPBFTHttpEnable(true); + Args.getInstance().setPBFTHttpPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setSolidityNodeHttpEnable(true); + Args.getInstance().setSolidityHttpPort(PublicMethod.chooseRandomPort()); } @Test public void testHttpFilter() { + appT.startup(); List disabledApiList = new ArrayList<>(); disabledApiList.add("getaccount"); disabledApiList.add("getnowblock"); diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java index 081b5839f84..c5c7185b6d8 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java @@ -55,8 +55,11 @@ public class LiteFnQueryGrpcInterceptorTest { @BeforeClass public static void init() throws IOException { Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + Args.getInstance().setRpcEnable(true); Args.getInstance().setRpcPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setRpcSolidityEnable(true); Args.getInstance().setRpcOnSolidityPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setRpcPBFTEnable(true); Args.getInstance().setRpcOnPBFTPort(PublicMethod.chooseRandomPort()); String fullnode = String.format("%s:%d", Args.getInstance().getNodeLanIp(), Args.getInstance().getRpcPort()); @@ -78,14 +81,8 @@ public static void init() throws IOException { blockingStubFull = WalletGrpc.newBlockingStub(channelFull); blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); blockingStubpBFT = WalletSolidityGrpc.newBlockingStub(channelpBFT); - RpcApiService rpcApiService = context.getBean(RpcApiService.class); - RpcApiServiceOnSolidity rpcOnSolidity = context.getBean(RpcApiServiceOnSolidity.class); - RpcApiServiceOnPBFT rpcApiServiceOnPBFT = context.getBean(RpcApiServiceOnPBFT.class); chainBaseManager = context.getBean(ChainBaseManager.class); Application appTest = ApplicationFactory.create(context); - appTest.addService(rpcApiService); - appTest.addService(rpcOnSolidity); - appTest.addService(rpcApiServiceOnPBFT); appTest.startup(); } diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java index 5fd4711273e..a9068c228b6 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java @@ -7,7 +7,6 @@ import java.io.IOException; import java.io.InputStreamReader; import java.util.Set; -import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; @@ -19,28 +18,32 @@ import org.junit.Before; import org.junit.Test; import org.tron.common.BaseTest; +import org.tron.common.utils.PublicMethod; import org.tron.core.Constant; import org.tron.core.config.args.Args; -import org.tron.core.services.http.FullNodeHttpApiService; -import org.tron.core.services.interfaceOnPBFT.http.PBFT.HttpApiOnPBFTService; -import org.tron.core.services.interfaceOnSolidity.http.solidity.HttpApiOnSolidityService; @Slf4j public class LiteFnQueryHttpFilterTest extends BaseTest { private final String ip = "127.0.0.1"; private int fullHttpPort; - @Resource - private FullNodeHttpApiService httpApiService; - @Resource - private HttpApiOnSolidityService httpApiOnSolidityService; - @Resource - private HttpApiOnPBFTService httpApiOnPBFTService; private final CloseableHttpClient httpClient = HttpClients.createDefault(); static { Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); Args.getInstance().setFullNodeAllowShieldedTransactionArgs(false); + Args.getInstance().setRpcEnable(false); + Args.getInstance().setRpcSolidityEnable(false); + Args.getInstance().setRpcPBFTEnable(false); + Args.getInstance().setFullNodeHttpEnable(true); + Args.getInstance().setFullNodeHttpPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setPBFTHttpEnable(true); + Args.getInstance().setPBFTHttpPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setSolidityNodeHttpEnable(true); + Args.getInstance().setSolidityHttpPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setJsonRpcHttpFullNodeEnable(false); + Args.getInstance().setJsonRpcHttpSolidityNodeEnable(false); + Args.getInstance().setJsonRpcHttpPBFTNodeEnable(false); } /** @@ -48,9 +51,6 @@ public class LiteFnQueryHttpFilterTest extends BaseTest { */ @Before public void init() { - appT.addService(httpApiService); - appT.addService(httpApiOnSolidityService); - appT.addService(httpApiOnPBFTService); appT.startup(); } diff --git a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java index 38af756f790..5845a89c2e4 100644 --- a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java @@ -56,8 +56,11 @@ public class RpcApiAccessInterceptorTest { @BeforeClass public static void init() throws IOException { Args.setParam(new String[] {"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); + Args.getInstance().setRpcEnable(true); Args.getInstance().setRpcPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setRpcSolidityEnable(true); Args.getInstance().setRpcOnSolidityPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setRpcPBFTEnable(true); Args.getInstance().setRpcOnPBFTPort(PublicMethod.chooseRandomPort()); String fullNode = String.format("%s:%d", Args.getInstance().getNodeLanIp(), Args.getInstance().getRpcPort()); @@ -82,15 +85,7 @@ public static void init() throws IOException { blockingStubSolidity = WalletSolidityGrpc.newBlockingStub(channelSolidity); blockingStubPBFT = WalletSolidityGrpc.newBlockingStub(channelPBFT); - RpcApiService rpcApiService = context.getBean(RpcApiService.class); - RpcApiServiceOnSolidity rpcApiServiceOnSolidity = - context.getBean(RpcApiServiceOnSolidity.class); - RpcApiServiceOnPBFT rpcApiServiceOnPBFT = context.getBean(RpcApiServiceOnPBFT.class); - Application appTest = ApplicationFactory.create(context); - appTest.addService(rpcApiService); - appTest.addService(rpcApiServiceOnSolidity); - appTest.addService(rpcApiServiceOnPBFT); appTest.startup(); } diff --git a/framework/src/test/java/org/tron/core/services/http/BroadcastServletTest.java b/framework/src/test/java/org/tron/core/services/http/BroadcastServletTest.java index 37956e71762..d6bf3850f30 100644 --- a/framework/src/test/java/org/tron/core/services/http/BroadcastServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/BroadcastServletTest.java @@ -27,6 +27,7 @@ import org.junit.BeforeClass; import org.junit.Test; import org.tron.common.utils.FileUtil; +import org.tron.common.utils.PublicMethod; import org.tron.core.services.http.solidity.mockito.HttpUrlStreamHandler; @Slf4j @@ -100,7 +101,8 @@ public void doPostTest() throws IOException { final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); System.setOut(new PrintStream(outContent)); - String href = "http://127.0.0.1:8090/wallet/broadcasttransaction"; + String href = "http://127.0.0.1/" + + PublicMethod.chooseRandomPort() + "/wallet/broadcasttransaction"; httpUrlStreamHandler.addConnection(new URL(href), httpUrlConnection); httpUrlConnection.setRequestMethod("POST"); httpUrlConnection.setRequestProperty("Content-Type", "application/json"); diff --git a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java index f363b7fbefc..e9cd9cb1f26 100644 --- a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java @@ -1,7 +1,6 @@ package org.tron.core.services.http; import com.google.gson.JsonObject; -import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpResponse; import org.bouncycastle.util.encoders.Hex; @@ -9,10 +8,9 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.tron.common.BaseTest; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.client.Configuration; +import org.tron.common.utils.PublicMethod; import org.tron.common.utils.client.utils.HttpMethed; import org.tron.core.Constant; import org.tron.core.capsule.ContractCapsule; @@ -25,31 +23,24 @@ @Slf4j public class TriggerSmartContractServletTest extends BaseTest { - private static final String httpNode = Configuration.getByPath("testng.conf") - .getStringList("httpnode.ip.list") - .get(0); + private static String httpNode; private static final byte[] ownerAddr = Hex.decode("410000000000000000000000000000000000000000"); private static final byte[] contractAddr = Hex.decode( "41000000000000000000000000000000000000dEaD"); - @Resource - private FullNodeHttpApiService httpApiService; - @BeforeClass public static void init() throws Exception { Args.setParam( new String[]{"--output-directory", dbPath(), "--debug", "--witness"}, Constant.TEST_CONF); Args.getInstance().needSyncCheck = false; - - // build app context - DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); - beanFactory.setAllowCircularReferences(false); + Args.getInstance().setFullNodeHttpEnable(true); + Args.getInstance().setFullNodeHttpPort(PublicMethod.chooseRandomPort()); + httpNode = String.format("%s:%d", "127.0.0.1", + Args.getInstance().getFullNodeHttpPort()); } @Before public void before() { - appT.addService(httpApiService); - // start services appT.startup(); diff --git a/framework/src/test/java/org/tron/core/services/http/solidity/GetTransactionByIdSolidityServletTest.java b/framework/src/test/java/org/tron/core/services/http/solidity/GetTransactionByIdSolidityServletTest.java index 70c74e3a2a7..e1abb41d1e1 100644 --- a/framework/src/test/java/org/tron/core/services/http/solidity/GetTransactionByIdSolidityServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/solidity/GetTransactionByIdSolidityServletTest.java @@ -27,6 +27,7 @@ import org.junit.BeforeClass; import org.junit.Test; import org.tron.common.utils.FileUtil; +import org.tron.common.utils.PublicMethod; import org.tron.core.services.http.solidity.mockito.HttpUrlStreamHandler; @@ -91,7 +92,8 @@ public void doPostTest() throws IOException { final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); System.setOut(new PrintStream(outContent)); - String href = "http://127.0.0.1:8091/walletsolidity/gettransactioninfobyid"; + String href = "http://127.0.0.1/" + + PublicMethod.chooseRandomPort() + "/walletsolidity/gettransactioninfobyid"; httpUrlStreamHandler.addConnection(new URL(href), httpUrlConnection); httpUrlConnection.setRequestMethod("POST"); httpUrlConnection.setRequestProperty("Content-Type", "application/json"); @@ -146,7 +148,8 @@ public void doGetTest() throws IOException { final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); System.setOut(new PrintStream(outContent)); - String href = "http://127.0.0.1:8091/walletsolidity/gettransactioninfobyid"; + String href = "http://127.0.0.1/" + + PublicMethod.chooseRandomPort() + "/walletsolidity/gettransactioninfobyid"; httpUrlStreamHandler.addConnection(new URL(href), httpUrlConnection); httpUrlConnection.setRequestMethod("GET"); httpUrlConnection.setRequestProperty("Content-Type", "application/json"); diff --git a/framework/src/test/java/org/tron/program/SolidityNodeTest.java b/framework/src/test/java/org/tron/program/SolidityNodeTest.java index a77fa2fa8c6..a95d07c0c11 100755 --- a/framework/src/test/java/org/tron/program/SolidityNodeTest.java +++ b/framework/src/test/java/org/tron/program/SolidityNodeTest.java @@ -1,12 +1,8 @@ package org.tron.program; -import java.io.File; -import java.io.IOException; import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.BeforeClass; import org.junit.Test; import org.tron.common.BaseTest; import org.tron.common.client.DatabaseGrpcClient; @@ -26,41 +22,10 @@ public class SolidityNodeTest extends BaseTest { SolidityNodeHttpApiService solidityNodeHttpApiService; static { - try { - Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); - } catch (IOException e) { - Assert.fail("create temp directory failed."); - } + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); Args.getInstance().setSolidityNode(true); } - /** - * init db. - */ - @BeforeClass - public static void init() { - } - - /** - * remo db when after test. - */ - @AfterClass - public static void removeDb() { - Args.clearParam(); - } - - private static Boolean deleteFolder(File index) { - if (!index.isDirectory() || index.listFiles().length <= 0) { - return index.delete(); - } - for (File file : index.listFiles()) { - if (null != file && !deleteFolder(file)) { - return false; - } - } - return index.delete(); - } - @Test public void testSolidityArgs() { Assert.assertNotNull(Args.getInstance().getTrustNodeAddr()); @@ -69,7 +34,6 @@ public void testSolidityArgs() { @Test public void testSolidityGrpcCall() { - rpcApiService.init(Args.getInstance()); rpcApiService.start(); DatabaseGrpcClient databaseGrpcClient = null; String address = Args.getInstance().getTrustNodeAddr(); @@ -99,7 +63,8 @@ public void testSolidityGrpcCall() { @Test public void testSolidityNodeHttpApiService() { - solidityNodeHttpApiService.init(Args.getInstance()); + solidityNodeHttpApiService.start(); + // start again solidityNodeHttpApiService.start(); solidityNodeHttpApiService.stop(); Assert.assertTrue(true); diff --git a/framework/src/test/resources/config-localtest.conf b/framework/src/test/resources/config-localtest.conf index 1d7ae09af7c..44c051e1079 100644 --- a/framework/src/test/resources/config-localtest.conf +++ b/framework/src/test/resources/config-localtest.conf @@ -117,14 +117,30 @@ node { ] http { + fullNodeEnable = false fullNodePort = 8090 + solidityEnable = false solidityPort = 8091 + PBFTEnable = false + PBFTPort = 8092 + } + + jsonrpc { + httpFullNodeEnable = false + httpFullNodePort = 8545 + httpSolidityEnable = false + httpSolidityPort = 8555 + httpPBFTEnable = false + httpPBFTPort = 8565 } rpc { + enable = false port = 50051 - # default value is 50061 - # solidityPort = 50061 + solidityEnable = false + solidityPort = 50061 + PBFTEnable = false + PBFTPort = 50071 # Number of gRPC thread, default availableProcessors / 2 # thread = 16 diff --git a/framework/src/test/resources/config-test-index.conf b/framework/src/test/resources/config-test-index.conf index 6eb3621e747..cff08fd3abb 100644 --- a/framework/src/test/resources/config-test-index.conf +++ b/framework/src/test/resources/config-test-index.conf @@ -76,9 +76,23 @@ node { version = 43 # 43: testnet; 101: debug } + http { + fullNodeEnable = false + solidityEnable = false + PBFTEnable = false + } + + jsonrpc { + httpFullNodeEnable = false + httpSolidityEnable = false + httpPBFTEnable = false + } + rpc { port = 50051 - + enable = false + solidityEnable = false + PBFTEnable = false # Number of gRPC thread, default availableProcessors / 2 # thread = 16 diff --git a/framework/src/test/resources/config-test-mainnet.conf b/framework/src/test/resources/config-test-mainnet.conf index ad72d2afaaa..de9170a0ec4 100644 --- a/framework/src/test/resources/config-test-mainnet.conf +++ b/framework/src/test/resources/config-test-mainnet.conf @@ -82,6 +82,24 @@ node { version = 43 # 43: testnet; 101: debug } + http { + fullNodeEnable = false + solidityEnable = false + PBFTEnable = false + } + + jsonrpc { + httpFullNodeEnable = false + httpSolidityEnable = false + httpPBFTEnable = false + } + + rpc { + enable = false + solidityEnable = false + PBFTEnable = false + } + } sync { diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index 62337f02fc5..997f3e98b37 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -107,10 +107,15 @@ node { } http { - fullNodeEnable = true - fullNodePort = 8090 - solidityEnable = true - solidityPort = 8091 + fullNodeEnable = false + solidityEnable = false + PBFTEnable = false + } + + jsonrpc { + httpFullNodeEnable = false + httpSolidityEnable = false + httpPBFTEnable = false } # use your ipv6 address for node discovery and tcp connection, default false @@ -172,6 +177,9 @@ node { } rpc { + enable = false + solidityEnable = false + PBFTEnable = false port = 50051 PBFTPort = 50072 diff --git a/plugins/src/test/java/org/tron/plugins/DbLiteTest.java b/plugins/src/test/java/org/tron/plugins/DbLiteTest.java index 5cb8c26c4bc..7e7e3c38f33 100644 --- a/plugins/src/test/java/org/tron/plugins/DbLiteTest.java +++ b/plugins/src/test/java/org/tron/plugins/DbLiteTest.java @@ -22,8 +22,6 @@ 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 picocli.CommandLine; @Slf4j @@ -47,8 +45,6 @@ public class DbLiteTest { 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", @@ -76,6 +72,7 @@ public void init() throws IOException { // allow account root Args.getInstance().setAllowAccountStateRoot(1); Args.getInstance().setRpcPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setRpcEnable(true); databaseDir = Args.getInstance().getStorage().getDbDirectory(); // init dbBackupConfig to avoid NPE Args.getInstance().dbBackupConfig = DbBackupConfig.getInstance(); From a86d0ed919df5079a16387253c3dc51bce337491 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 3 Jan 2025 16:54:02 +0800 Subject: [PATCH 1115/1197] feat(*): reactor system.exit --- .../leveldb/LevelDbDataSourceImpl.java | 3 +- .../rocksdb/RocksDbDataSourceImpl.java | 3 +- .../tron/core/db2/core/SnapshotManager.java | 35 ++++-------- .../tron/core/service/RewardViCalService.java | 3 +- .../org/tron/common/exit/ExitManager.java | 53 +++++++++++++++++++ framework/build.gradle | 1 - .../org/tron/core/config/DefaultConfig.java | 1 - .../java/org/tron/core/config/args/Args.java | 4 +- .../main/java/org/tron/core/db/Manager.java | 16 +++--- .../main/java/org/tron/program/FullNode.java | 2 + .../java/org/tron/program/SolidityNode.java | 5 +- .../leveldb/LevelDbDataSourceImplTest.java | 7 +-- .../leveldb/RocksDbDataSourceImplTest.java | 7 +-- .../java/org/tron/core/db/ManagerTest.java | 8 +-- .../tron/core/db2/SnapshotManagerTest.java | 30 ++++++++++- .../tron/core/services/ComputeRewardTest.java | 7 +-- 16 files changed, 128 insertions(+), 57 deletions(-) create mode 100644 common/src/main/java/org/tron/common/exit/ExitManager.java diff --git a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java index 43a24ff4416..506ecdcb6c7 100644 --- a/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java @@ -59,6 +59,7 @@ import org.tron.core.db.common.iterator.StoreIterator; import org.tron.core.db2.common.Instance; import org.tron.core.db2.common.WrappedByteArray; +import org.tron.core.exception.TronError; @Slf4j(topic = "DB") @NoArgsConstructor @@ -157,7 +158,7 @@ private void openDatabase(Options dbOptions) throws IOException { } else { logger.error("Open Database {} failed", dataBaseName, e); } - System.exit(1); + throw new TronError(e, TronError.ErrCode.LEVELDB_INIT); } } diff --git a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java index 6c5d8018487..5c051bdc101 100644 --- a/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java +++ b/chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java @@ -45,6 +45,7 @@ import org.tron.core.db.common.iterator.RockStoreIterator; import org.tron.core.db2.common.Instance; import org.tron.core.db2.common.WrappedByteArray; +import org.tron.core.exception.TronError; @Slf4j(topic = "DB") @@ -272,7 +273,7 @@ protected void log(InfoLogLevel infoLogLevel, String logMsg) { } else { logger.error("Open Database {} failed", dataBaseName, e); } - System.exit(1); + throw new TronError(e, TronError.ErrCode.ROCKSDB_INIT); } alive = true; diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java index f0f169ae340..eb27141a82c 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java @@ -20,7 +20,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.LockSupport; import java.util.stream.Collectors; import javax.annotation.PostConstruct; import lombok.Getter; @@ -42,6 +41,7 @@ import org.tron.core.db2.common.Value; import org.tron.core.db2.common.WrappedByteArray; import org.tron.core.exception.RevokingStoreIllegalStateException; +import org.tron.core.exception.TronError; import org.tron.core.store.CheckPointV2Store; import org.tron.core.store.CheckTmpStore; @@ -68,7 +68,6 @@ public class SnapshotManager implements RevokingDatabase { private volatile int flushCount = 0; - private Thread exitThread; private volatile boolean hitDown; private Map flushServices = new HashMap<>(); @@ -105,15 +104,6 @@ public void init() { } }, 10000, 3600, TimeUnit.MILLISECONDS); } - exitThread = new Thread(() -> { - LockSupport.park(); - // to Guarantee Some other thread invokes unpark with the current thread as the target - if (hitDown) { - System.exit(1); - } - }); - exitThread.setName("exit-thread"); - exitThread.start(); } public static String simpleDecode(byte[] bytes) { @@ -281,13 +271,6 @@ public void shutdown() { ExecutorServiceManager.shutdownAndAwaitTermination(pruneCheckpointThread, pruneName); flushServices.forEach((key, value) -> ExecutorServiceManager.shutdownAndAwaitTermination(value, "flush-service-" + key)); - try { - exitThread.interrupt(); - // help GC - exitThread = null; - } catch (Exception e) { - logger.warn("exitThread interrupt error", e); - } } public void updateSolidity(int hops) { @@ -298,7 +281,7 @@ public void updateSolidity(int hops) { } } - private boolean shouldBeRefreshed() { + public boolean shouldBeRefreshed() { return flushCount >= maxFlushCount; } @@ -367,12 +350,12 @@ public void flush() { } catch (TronDBException e) { logger.error(" Find fatal error, program will be exited soon.", e); hitDown = true; - LockSupport.unpark(exitThread); + throw new TronError(e, TronError.ErrCode.DB_FLUSH); } } } - private void createCheckpoint() { + public void createCheckpoint() { TronDatabase checkPointStore = null; boolean syncFlag; try { @@ -430,7 +413,7 @@ private TronDatabase getCheckpointDB(String dbName) { return new CheckPointV2Store(CHECKPOINT_V2_DIR+"/"+dbName); } - private List getCheckpointList() { + public List getCheckpointList() { String dbPath = Paths.get(StorageUtils.getOutputDirectoryByDbName(CHECKPOINT_V2_DIR), CommonParameter.getInstance().getStorage().getDbDirectory()).toString(); File file = new File(Paths.get(dbPath, CHECKPOINT_V2_DIR).toString()); @@ -490,10 +473,10 @@ public void check() { if (!isV2Open()) { List cpList = getCheckpointList(); if (cpList != null && cpList.size() != 0) { - logger.error("checkpoint check failed, the checkpoint version of database not match your " + - "config file, please set storage.checkpoint.version = 2 in your config file " + - "and restart the node."); - System.exit(-1); + String msg = "checkpoint check failed, the checkpoint version of database not match your " + + "config file, please set storage.checkpoint.version = 2 in your config file " + + "and restart the node."; + throw new TronError(msg, TronError.ErrCode.CHECKPOINT_VERSION); } checkV1(); } else { diff --git a/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java b/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java index e27990f0403..b3ef76b091e 100644 --- a/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java +++ b/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java @@ -30,6 +30,7 @@ import org.tron.common.utils.Sha256Hash; import org.tron.core.db.common.iterator.DBIterator; import org.tron.core.db2.common.DB; +import org.tron.core.exception.TronError; import org.tron.core.store.DelegationStore; import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.store.RewardViStore; @@ -121,7 +122,7 @@ private void maybeRun() { } } catch (Exception e) { logger.error(" Find fatal error, program will be exited soon.", e); - System.exit(1); + throw new TronError(e, TronError.ErrCode.REWARD_VI_CALCULATOR); } } diff --git a/common/src/main/java/org/tron/common/exit/ExitManager.java b/common/src/main/java/org/tron/common/exit/ExitManager.java new file mode 100644 index 00000000000..ff3e0de734b --- /dev/null +++ b/common/src/main/java/org/tron/common/exit/ExitManager.java @@ -0,0 +1,53 @@ +package org.tron.common.exit; + +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ThreadFactory; +import lombok.extern.slf4j.Slf4j; +import org.tron.core.exception.TronError; + +@Slf4j(topic = "Exit") +public class ExitManager { + + private static final ThreadFactory exitThreadFactory = r -> { + Thread thread = new Thread(r, "System-Exit-Thread"); + thread.setDaemon(true); + return thread; + }; + + private ExitManager() { + + } + + public static void initExceptionHandler() { + Thread.setDefaultUncaughtExceptionHandler((t, e) -> { + findTronError(e).ifPresent(ExitManager::logAndExit); + logger.error("Uncaught exception", e); + }); + } + + public static Optional findTronError(Throwable e) { + if (e == null) { + return Optional.empty(); + } + + Set seen = new HashSet<>(); + + while (e != null && !seen.contains(e)) { + if (e instanceof TronError) { + return Optional.of((TronError) e); + } + seen.add(e); + e = e.getCause(); + } + return Optional.empty(); + } + + private static void logAndExit(TronError exit) { + final int code = exit.getErrCode().getCode(); + logger.error("Shutting down with code: {}.", exit.getErrCode(), exit); + Thread exitThread = exitThreadFactory.newThread(() -> System.exit(code)); + exitThread.start(); + } +} \ No newline at end of file diff --git a/framework/build.gradle b/framework/build.gradle index 10477fb71b3..83b6df6d95e 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -39,7 +39,6 @@ dependencies { implementation fileTree(dir: 'libs', include: '*.jar') // end local libraries testImplementation group: 'org.hamcrest', name: 'hamcrest-junit', version: '1.0.0.1' - testImplementation group: 'com.github.stefanbirkner', name: 'system-rules', version: '1.16.0' implementation group: 'com.google.inject', name: 'guice', version: '4.1.0' implementation group: 'io.dropwizard.metrics', name: 'metrics-core', version: '3.1.2' diff --git a/framework/src/main/java/org/tron/core/config/DefaultConfig.java b/framework/src/main/java/org/tron/core/config/DefaultConfig.java index 7cc32d9a581..d01820626c3 100755 --- a/framework/src/main/java/org/tron/core/config/DefaultConfig.java +++ b/framework/src/main/java/org/tron/core/config/DefaultConfig.java @@ -37,7 +37,6 @@ public class DefaultConfig { public CommonConfig commonConfig; public DefaultConfig() { - Thread.setDefaultUncaughtExceptionHandler((t, e) -> logger.error("Uncaught exception", e)); } @Bean(destroyMethod = "") diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 2ac3e69eced..852d271497d 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -66,6 +66,7 @@ import org.tron.core.config.Parameter.NetConstants; import org.tron.core.config.Parameter.NodeConstant; import org.tron.core.exception.CipherException; +import org.tron.core.exception.TronError; import org.tron.core.store.AccountStore; import org.tron.keystore.Credentials; import org.tron.keystore.WalletUtils; @@ -433,9 +434,8 @@ public static void setParam(final Config config) { String prikey = ByteArray.toHexString(sign.getPrivateKey()); privateKeys.add(prikey); } catch (IOException | CipherException e) { - logger.error(e.getMessage()); logger.error("Witness node start failed!"); - exit(-1); + throw new TronError(e, TronError.ErrCode.WITNESS_KEYSTORE_LOAD); } } } diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 908e248bdee..cfd12fffce2 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -123,6 +123,7 @@ import org.tron.core.exception.TooBigTransactionException; import org.tron.core.exception.TooBigTransactionResultException; import org.tron.core.exception.TransactionExpirationException; +import org.tron.core.exception.TronError; import org.tron.core.exception.UnLinkedBlockException; import org.tron.core.exception.VMIllegalException; import org.tron.core.exception.ValidateScheduleException; @@ -498,13 +499,13 @@ public void init() { logger.error( "Please delete database directory({}) and restart", Args.getInstance().getOutputDirectory()); - System.exit(1); + throw new TronError(e, TronError.ErrCode.KHAOS_DB_INIT); } catch (BadItemException e) { logger.error("DB data broken {}.", e.getMessage()); logger.error( "Please delete database directory({}) and restart.", Args.getInstance().getOutputDirectory()); - System.exit(1); + throw new TronError(e, TronError.ErrCode.KHAOS_DB_INIT); } getChainBaseManager().getForkController().init(this.chainBaseManager); @@ -569,7 +570,7 @@ public void init() { initAutoStop(); } catch (IllegalArgumentException e) { logger.error("Auto-stop params error: {}", e.getMessage()); - System.exit(1); + throw new TronError(e, TronError.ErrCode.AUTO_STOP_PARAMS); } maxFlushCount = CommonParameter.getInstance().getStorage().getMaxFlushCount(); @@ -586,10 +587,9 @@ public void initGenesis() { Args.getInstance().setChainId(genesisBlock.getBlockId().toString()); } else { if (chainBaseManager.hasBlocks()) { - logger.error( - "Genesis block modify, please delete database directory({}) and restart.", - Args.getInstance().getOutputDirectory()); - System.exit(1); + String msg = String.format("Genesis block modify, please delete database directory(%s) and " + + "restart.", Args.getInstance().getOutputDirectory()); + throw new TronError(msg, TronError.ErrCode.GENESIS_BLOCK_INIT); } else { logger.info("Create genesis block."); Args.getInstance().setChainId(genesisBlock.getBlockId().toString()); @@ -1370,7 +1370,7 @@ void blockTrigger(final BlockCapsule block, long oldSolid, long newSolid) { } catch (Exception e) { logger.error("Block trigger failed. head: {}, oldSolid: {}, newSolid: {}", block.getNum(), oldSolid, newSolid, e); - System.exit(1); + throw new TronError(e, TronError.ErrCode.EVENT_SUBSCRIBE_ERROR); } } diff --git a/framework/src/main/java/org/tron/program/FullNode.java b/framework/src/main/java/org/tron/program/FullNode.java index b7adf0ffe1a..7fc72e6ba88 100644 --- a/framework/src/main/java/org/tron/program/FullNode.java +++ b/framework/src/main/java/org/tron/program/FullNode.java @@ -10,6 +10,7 @@ import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; +import org.tron.common.exit.ExitManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.prometheus.Metrics; import org.tron.core.Constant; @@ -40,6 +41,7 @@ public static void load(String path) { * Start the FullNode. */ public static void main(String[] args) { + ExitManager.initExceptionHandler(); logger.info("Full node running."); Args.setParam(args, Constant.TESTNET_CONF); CommonParameter parameter = Args.getInstance(); diff --git a/framework/src/main/java/org/tron/program/SolidityNode.java b/framework/src/main/java/org/tron/program/SolidityNode.java index 8def8ed7ebc..b774ab03aaa 100644 --- a/framework/src/main/java/org/tron/program/SolidityNode.java +++ b/framework/src/main/java/org/tron/program/SolidityNode.java @@ -12,6 +12,7 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.client.DatabaseGrpcClient; +import org.tron.common.exit.ExitManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.prometheus.Metrics; import org.tron.core.ChainBaseManager; @@ -20,6 +21,7 @@ import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; +import org.tron.core.exception.TronError; import org.tron.protos.Protocol.Block; @Slf4j(topic = "app") @@ -54,6 +56,7 @@ public SolidityNode(Manager dbManager) { * Start the SolidityNode. */ public static void main(String[] args) { + ExitManager.initExceptionHandler(); logger.info("Solidity node is running."); Args.setParam(args, Constant.TESTNET_CONF); CommonParameter parameter = CommonParameter.getInstance(); @@ -98,7 +101,7 @@ private void start() { } catch (Exception e) { logger.error("Failed to start solid node, address: {}.", CommonParameter.getInstance().getTrustNodeAddr()); - System.exit(0); + throw new TronError(e, TronError.ErrCode.SOLID_NODE_INIT); } } diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java index 50a55d24a0f..03bf7b21956 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java @@ -43,7 +43,7 @@ import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; -import org.junit.contrib.java.lang.system.ExpectedSystemExit; +import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; @@ -51,6 +51,7 @@ import org.tron.core.Constant; import org.tron.core.config.args.Args; import org.tron.core.db2.common.WrappedByteArray; +import org.tron.core.exception.TronError; @Slf4j public class LevelDbDataSourceImplTest { @@ -74,7 +75,7 @@ public class LevelDbDataSourceImplTest { private byte[] key6 = "00000006aa".getBytes(); @Rule - public final ExpectedSystemExit exit = ExpectedSystemExit.none(); + public final ExpectedException exception = ExpectedException.none(); /** * Release resources. @@ -350,7 +351,7 @@ public void prefixQueryTest() { @Test public void initDbTest() { - exit.expectSystemExitWithStatus(1); + exception.expect(TronError.class); makeExceptionDb("test_initDb"); LevelDbDataSourceImpl dataSource = new LevelDbDataSourceImpl( Args.getInstance().getOutputDirectory(), "test_initDb"); diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java index ed37c1e4bcd..b7846ac2d70 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java @@ -25,7 +25,7 @@ import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; -import org.junit.contrib.java.lang.system.ExpectedSystemExit; +import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.tron.common.storage.rocksdb.RocksDbDataSourceImpl; import org.tron.common.utils.ByteArray; @@ -34,6 +34,7 @@ import org.tron.common.utils.PublicMethod; import org.tron.core.config.args.Args; import org.tron.core.db2.common.WrappedByteArray; +import org.tron.core.exception.TronError; @Slf4j public class RocksDbDataSourceImplTest { @@ -56,7 +57,7 @@ public class RocksDbDataSourceImplTest { private byte[] key6 = "00000006aa".getBytes(); @Rule - public final ExpectedSystemExit exit = ExpectedSystemExit.none(); + public final ExpectedException exception = ExpectedException.none(); /** * Release resources. @@ -392,7 +393,7 @@ public void prefixQueryTest() { @Test public void initDbTest() { - exit.expectSystemExitWithStatus(1); + exception.expect(TronError.class); makeExceptionDb("test_initDb"); RocksDbDataSourceImpl dataSource = new RocksDbDataSourceImpl( Args.getInstance().getOutputDirectory(), "test_initDb"); diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index 70aba258594..e9b79487204 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -30,7 +30,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.contrib.java.lang.system.ExpectedSystemExit; +import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; import org.tron.common.crypto.ECKey; @@ -76,6 +76,7 @@ import org.tron.core.exception.TooBigTransactionException; import org.tron.core.exception.TooBigTransactionResultException; import org.tron.core.exception.TransactionExpirationException; +import org.tron.core.exception.TronError; import org.tron.core.exception.UnLinkedBlockException; import org.tron.core.exception.VMIllegalException; import org.tron.core.exception.ValidateScheduleException; @@ -92,7 +93,6 @@ import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; -import org.tron.protos.Protocol.Transaction.raw; import org.tron.protos.contract.AccountContract; import org.tron.protos.contract.AssetIssueContractOuterClass; import org.tron.protos.contract.BalanceContract.TransferContract; @@ -112,7 +112,7 @@ public class ManagerTest extends BlockGenerate { @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); @Rule - public final ExpectedSystemExit exit = ExpectedSystemExit.none(); + public final ExpectedException exception = ExpectedException.none(); private static AtomicInteger port = new AtomicInteger(0); private static String accountAddress = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; @@ -1162,7 +1162,7 @@ public void testTooBigTransaction() { @Test public void blockTrigger() { - exit.expectSystemExitWithStatus(1); + exception.expect(TronError.class); Manager manager = spy(new Manager()); doThrow(new RuntimeException("postBlockTrigger mock")).when(manager).postBlockTrigger(any()); manager.blockTrigger(new BlockCapsule(Block.newBuilder().build()), 1, 1); diff --git a/framework/src/test/java/org/tron/core/db2/SnapshotManagerTest.java b/framework/src/test/java/org/tron/core/db2/SnapshotManagerTest.java index 966e947d828..87834246fba 100644 --- a/framework/src/test/java/org/tron/core/db2/SnapshotManagerTest.java +++ b/framework/src/test/java/org/tron/core/db2/SnapshotManagerTest.java @@ -1,11 +1,13 @@ package org.tron.core.db2; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + import com.google.common.collect.Maps; -import com.google.common.primitives.Bytes; import com.google.common.primitives.Longs; import com.google.protobuf.ByteString; import java.io.File; -import java.util.Iterator; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -13,7 +15,9 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; @@ -29,6 +33,7 @@ import org.tron.core.db2.core.SnapshotManager; import org.tron.core.exception.BadItemException; import org.tron.core.exception.ItemNotFoundException; +import org.tron.core.exception.TronError; @Slf4j public class SnapshotManagerTest { @@ -38,6 +43,9 @@ public class SnapshotManagerTest { private Application appT; private TestRevokingTronStore tronDatabase; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Before public void init() { Args.setParam(new String[]{"-d", "output_SnapshotManager_test"}, @@ -111,4 +119,22 @@ public synchronized void testClose() { tronDatabase.get(protoCapsule.getData())); } + + @Test + public void testCheckError() { + thrown.expect(TronError.class); + SnapshotManager manager = spy(new SnapshotManager("")); + when(manager.getCheckpointList()).thenReturn(Arrays.asList("check1", "check2")); + manager.check(); + } + + @Test + public void testFlushError() { + thrown.expect(TronError.class); + SnapshotManager manager = spy(new SnapshotManager("")); + manager.setUnChecked(false); + when(manager.getCheckpointList()).thenReturn(Arrays.asList("check1", "check2")); + when(manager.shouldBeRefreshed()).thenReturn(true); + manager.flush(); + } } diff --git a/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java b/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java index 0082c8728da..8ff6b62d7ef 100644 --- a/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java +++ b/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java @@ -17,7 +17,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.contrib.java.lang.system.ExpectedSystemExit; +import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; import org.tron.common.error.TronDBException; @@ -30,6 +30,7 @@ import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; +import org.tron.core.exception.TronError; import org.tron.core.service.MortgageService; import org.tron.core.service.RewardViCalService; import org.tron.core.store.AccountStore; @@ -115,7 +116,7 @@ public class ComputeRewardTest { public final TemporaryFolder temporaryFolder = new TemporaryFolder(); @Rule - public final ExpectedSystemExit exit = ExpectedSystemExit.none(); + public final ExpectedException exception = ExpectedException.none(); @After public void destroy() { @@ -263,7 +264,7 @@ private void setUp() { @Test public void query() { - exit.expectSystemExitWithStatus(1); + exception.expect(TronError.class); Assert.assertEquals(3189, mortgageService.queryReward(OWNER_ADDRESS)); // mock root is error rewardViStore.put("test".getBytes(), "test".getBytes()); From b5a53afa2061218f264549d3ea327682cf997a33 Mon Sep 17 00:00:00 2001 From: Liulei Date: Wed, 26 Jun 2024 18:31:56 +0800 Subject: [PATCH 1116/1197] feat(tvm): cancun opcodes TLOAD, TSORE, MCOPY --- .../org/tron/core/utils/ProposalUtil.java | 16 +++++++ .../java/org/tron/core/vm/EnergyCost.java | 22 +++++++++ .../src/main/java/org/tron/core/vm/Op.java | 6 +++ .../org/tron/core/vm/OperationActions.java | 31 ++++++++++++ .../org/tron/core/vm/OperationRegistry.java | 32 ++++++++++++- .../org/tron/core/vm/config/ConfigLoader.java | 1 + .../org/tron/core/vm/config/VMConfig.java | 10 ++++ .../tron/core/vm/program/ContractState.java | 15 ++++++ .../java/org/tron/core/vm/program/Memory.java | 8 ++++ .../org/tron/core/vm/program/Program.java | 4 ++ .../tron/core/vm/repository/Repository.java | 6 +++ .../core/vm/repository/RepositoryImpl.java | 45 ++++++++++++++++++ .../core/store/DynamicPropertiesStore.java | 14 ++++++ .../common/parameter/CommonParameter.java | 4 ++ .../src/main/java/org/tron/core/Constant.java | 2 + .../src/main/java/org/tron/core/Wallet.java | 5 ++ .../java/org/tron/core/config/args/Args.java | 5 ++ .../tron/core/consensus/ProposalService.java | 4 ++ .../common/runtime/vm/OperationsTest.java | 47 +++++++++++++++++++ 19 files changed, 276 insertions(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 081b91dfd6c..6b558011c73 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -809,6 +809,21 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case ALLOW_TVM_CANCUN: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_8_0)) { + throw new ContractValidateException( + "Bad chain parameter id [ALLOW_TVM_CANCUN]"); + } + if (dynamicPropertiesStore.getAllowTvmCancun() == 1) { + throw new ContractValidateException( + "[ALLOW_TVM_CANCUN] has been valid, no need to propose again"); + } + if (value != 1) { + throw new ContractValidateException( + "This value[ALLOW_TVM_CANCUN] is only allowed to be 1"); + } + break; + } default: break; } @@ -888,6 +903,7 @@ public enum ProposalType { // current value, value range ALLOW_OLD_REWARD_OPT(79), // 0, 1 ALLOW_ENERGY_ADJUSTMENT(81), // 0, 1 MAX_CREATE_ACCOUNT_TX_SIZE(82), // [500, 10000] + ALLOW_TVM_CANCUN(83), // 0, 1 ALLOW_STRICT_MATH(87), // 0, 1 CONSENSUS_LOGIC_OPTIMIZATION(88); // 0, 1 diff --git a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java index 6638b22d47f..5c78fb89ffb 100644 --- a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java +++ b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java @@ -57,6 +57,8 @@ public class EnergyCost { private static final long SUICIDE = 0; private static final long STOP = 0; private static final long CREATE_DATA = 200; + private static final long TLOAD = 100; + private static final long TSTORE = 100; public static long getZeroTierCost(Program ignored) { return ZERO_TIER; @@ -232,6 +234,26 @@ public static long getSstoreCost(Program program) { } + public static long getTLoadCost(Program ignored) { + return TLOAD; + } + + public static long getTStoreCost(Program ignored) { + return TSTORE; + } + + public static long getMCopyCost(Program program) { + Stack stack = program.getStack(); + long oldMemSize = program.getMemSize(); + + int dstOffset = stack.peek().intValue(); + int srcOffset = stack.get(stack.size() - 2).intValue(); + DataWord maxOffset = new DataWord(Math.max(dstOffset, srcOffset)); + return VERY_LOW_TIER + calcMemEnergy(oldMemSize, + memNeeded(maxOffset, stack.get(stack.size() - 3)), + stack.get(stack.size() - 3).longValueSafe(), Op.MCOPY); + } + public static long getLogCost(Program program) { Stack stack = program.getStack(); long oldMemSize = program.getMemSize(); diff --git a/actuator/src/main/java/org/tron/core/vm/Op.java b/actuator/src/main/java/org/tron/core/vm/Op.java index f6987c12942..4b4488ef427 100644 --- a/actuator/src/main/java/org/tron/core/vm/Op.java +++ b/actuator/src/main/java/org/tron/core/vm/Op.java @@ -145,6 +145,12 @@ public class Op { // (0x5a) Get the amount of available gas public static final int GAS = 0x5a; public static final int JUMPDEST = 0x5b; + // (0x5c) Load word from transient memory + public static final int TLOAD = 0x5c; + // (0x5d) Save word to transient memory + public static final int TSTORE = 0x5d; + // (0x5e) Copy word from memory + public static final int MCOPY = 0x5e; /* Push Operations */ // Place item on stack diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index e8e5eb86b98..713c43851a0 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -643,6 +643,37 @@ public static void jumpDestAction(Program program) { program.step(); } + public static void tLoadAction(Program program) { + DataWord key = program.stackPop(); + DataWord address = program.getContractAddress(); + + byte[] data = + program.getContractState().getTransientStorageValue(address.getData(), key.getData()); + DataWord value = data != null ? new DataWord(data) : DataWord.ZERO; + + program.stackPush(value); + program.step(); + } + + public static void tStoreAction(Program program) { + DataWord key = program.stackPop(); + DataWord value = program.stackPop(); + DataWord address = program.getContractAddress(); + + program.getContractState() + .updateTransientStorageValue(address.getData(), key.getData(), value.getData()); + program.step(); + } + + public static void mCopyAction(Program program) { + int dstOffset = program.stackPop().intValueSafe(); + int srcOffset = program.stackPop().intValueSafe(); + int length = program.stackPop().intValueSafe(); + + program.memoryCopy(dstOffset, srcOffset, length); + program.step(); + } + public static void push0Action(Program program) { program.stackPush(DataWord.ZERO()); program.step(); diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index a2d3259ba89..da1c9b38e9e 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -12,6 +12,7 @@ public enum Version { TRON_V1_1, TRON_V1_2, TRON_V1_3, + TRON_V1_4, // add more // TRON_V2, // ETH @@ -24,6 +25,7 @@ public enum Version { tableMap.put(Version.TRON_V1_1, newTronV11OperationSet()); tableMap.put(Version.TRON_V1_2, newTronV12OperationSet()); tableMap.put(Version.TRON_V1_3, newTronV13OperationSet()); + tableMap.put(Version.TRON_V1_4, newTronV14OperationSet()); } public static JumpTable newTronV10OperationSet() { @@ -55,12 +57,18 @@ public static JumpTable newTronV13OperationSet() { return table; } + public static JumpTable newTronV14OperationSet() { + JumpTable table = newTronV13OperationSet(); + appendCancunOperations(table); + return table; + } + // Just for warming up class to avoid out_of_time public static void init() {} public static JumpTable getTable() { // always get the table which has the newest version - JumpTable table = tableMap.get(Version.TRON_V1_3); + JumpTable table = tableMap.get(Version.TRON_V1_4); // next make the corresponding changes, exclude activating opcode if (VMConfig.allowHigherLimitForMaxCpuTimeOfOneTx()) { @@ -652,4 +660,26 @@ public static void adjustForFairEnergy(JumpTable table) { EnergyCost::getSuicideCost2, OperationActions::suicideAction)); } + + public static void appendCancunOperations(JumpTable table) { + BooleanSupplier proposal = VMConfig::allowTvmCancun; + + table.set(new Operation( + Op.TLOAD, 1, 1, + EnergyCost::getTLoadCost, + OperationActions::tLoadAction, + proposal)); + + table.set(new Operation( + Op.TSTORE, 2, 0, + EnergyCost::getTStoreCost, + OperationActions::tStoreAction, + proposal)); + + table.set(new Operation( + Op.MCOPY, 3, 0, + EnergyCost::getMCopyCost, + OperationActions::mCopyAction, + proposal)); + } } diff --git a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java index 79a536f4cbf..5c4acb31bae 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java +++ b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java @@ -41,6 +41,7 @@ public static void load(StoreFactory storeFactory) { VMConfig.initAllowTvmShangHai(ds.getAllowTvmShangHai()); VMConfig.initAllowEnergyAdjustment(ds.getAllowEnergyAdjustment()); VMConfig.initAllowStrictMath(ds.getAllowStrictMath()); + VMConfig.initAllowTvmCancun(ds.getAllowTvmCancun()); } } } diff --git a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java index 90a2c6335f6..9f567344337 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java +++ b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java @@ -53,6 +53,8 @@ public class VMConfig { private static boolean ALLOW_STRICT_MATH = false; + private static boolean ALLOW_TVM_CANCUN = false; + private VMConfig() { } @@ -148,6 +150,10 @@ public static void initAllowStrictMath(long allow) { ALLOW_STRICT_MATH = allow == 1; } + public static void initAllowTvmCancun(long allow) { + ALLOW_TVM_CANCUN = allow == 1; + } + public static boolean getEnergyLimitHardFork() { return CommonParameter.ENERGY_LIMIT_HARD_FORK; } @@ -231,4 +237,8 @@ public static boolean allowEnergyAdjustment() { public static boolean allowStrictMath() { return ALLOW_STRICT_MATH; } + + public static boolean allowTvmCancun() { + return ALLOW_TVM_CANCUN; + } } diff --git a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java index 657558b3725..e095201e393 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/ContractState.java +++ b/actuator/src/main/java/org/tron/core/vm/program/ContractState.java @@ -229,6 +229,11 @@ public void putDelegatedResourceAccountIndex(Key key, Value value) { repository.putDelegatedResourceAccountIndex(key, value); } + @Override + public void putTransientStorageValue(Key address, Key key, Value value) { + repository.putTransientStorageValue(address, key, value); + } + @Override public long addTokenBalance(byte[] address, byte[] tokenId, long value) { return repository.addTokenBalance(address, tokenId, value); @@ -314,6 +319,11 @@ public DelegatedResourceAccountIndexCapsule getDelegatedResourceAccountIndex(byt return repository.getDelegatedResourceAccountIndex(key); } + @Override + public byte[] getTransientStorageValue(byte[] address, byte[] key) { + return repository.getTransientStorageValue(address, key); + } + @Override public void updateDynamicProperty(byte[] word, BytesCapsule bytesCapsule) { repository.updateDynamicProperty(word, bytesCapsule); @@ -354,6 +364,11 @@ public void updateDelegatedResourceAccountIndex(byte[] word, DelegatedResourceAc repository.updateDelegatedResourceAccountIndex(word, delegatedResourceAccountIndexCapsule); } + @Override + public void updateTransientStorageValue(byte[] address, byte[] key, byte[] value) { + repository.updateTransientStorageValue(address, key, value); + } + @Override public void putDynamicProperty(Key key, Value value) { repository.putDynamicProperty(key, value); diff --git a/actuator/src/main/java/org/tron/core/vm/program/Memory.java b/actuator/src/main/java/org/tron/core/vm/program/Memory.java index e5cbebad2b9..8f263ca7344 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Memory.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Memory.java @@ -181,6 +181,14 @@ public List getChunks() { return new LinkedList<>(chunks); } + public void copy(int destPos, int srcPos, int size) { + if (size <= 0) { + return; + } + byte[] data = read(srcPos, size); + write(destPos, data, size, false); + } + private int captureMax(int chunkIndex, int chunkOffset, int size, byte[] src, int srcPos) { byte[] chunk = chunks.get(chunkIndex); diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 4273778a7d6..9dda3ed6b7f 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -429,6 +429,10 @@ public byte[] memoryChunk(int offset, int size) { return memory.read(offset, size); } + public void memoryCopy(int dst, int src, int size) { + memory.copy(dst, src, size); + } + /** * . Allocates extra memory in the program for a specified size, calculated from a given offset * diff --git a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java index b4324bb8d18..664ee26ee92 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/Repository.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/Repository.java @@ -41,6 +41,8 @@ public interface Repository { DelegatedResourceAccountIndexCapsule getDelegatedResourceAccountIndex(byte[] key); + byte[] getTransientStorageValue(byte[] address, byte[] key); + void deleteContract(byte[] address); void createContract(byte[] address, ContractCapsule contractCapsule); @@ -71,6 +73,8 @@ public interface Repository { void updateDelegatedResourceAccountIndex(byte[] word, DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule); + void updateTransientStorageValue(byte[] address, byte[] key, byte[] value); + void saveCode(byte[] address, byte[] code); byte[] getCode(byte[] address); @@ -113,6 +117,8 @@ public interface Repository { void putDelegatedResourceAccountIndex(Key key, Value value); + void putTransientStorageValue(Key address, Key key, Value value); + long addTokenBalance(byte[] address, byte[] tokenId, long value); long getTokenBalance(byte[] address, byte[] tokenId); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 50fa5385c23..7fcfbe8ef78 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -4,6 +4,7 @@ import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import com.google.common.collect.HashBasedTable; import com.google.protobuf.ByteString; import java.util.HashMap; import java.util.Optional; @@ -131,6 +132,7 @@ public class RepositoryImpl implements Repository { private final HashMap> votesCache = new HashMap<>(); private final HashMap> delegationCache = new HashMap<>(); private final HashMap> delegatedResourceAccountIndexCache = new HashMap<>(); + private final HashBasedTable> transientStorage = HashBasedTable.create(); public static void removeLruCache(byte[] address) { } @@ -442,6 +444,27 @@ public DelegatedResourceAccountIndexCapsule getDelegatedResourceAccountIndex(byt return delegatedResourceAccountIndexCapsule; } + public byte[] getTransientStorageValue(byte[] address, byte[] key) { + Key cacheAddress = new Key(address); + Key cacheKey = new Key(key); + if (transientStorage.contains(cacheAddress, cacheKey)) { + return transientStorage.get(cacheAddress, cacheKey).getValue(); + } + + byte[] value; + if (parent != null) { + value = parent.getTransientStorageValue(address, key); + } else{ + value = null; + } + + if (value != null) { + transientStorage.put(cacheAddress, cacheKey, Value.create(value)); + } + + return value; + } + @Override public void deleteContract(byte[] address) { @@ -565,6 +588,11 @@ public void updateDelegatedResourceAccountIndex( Key.create(word), Value.create(delegatedResourceAccountIndexCapsule, Type.DIRTY)); } + @Override + public void updateTransientStorageValue(byte[] address, byte[] key, byte[] value) { + transientStorage.put(Key.create(address), Key.create(key), Value.create(value, Type.DIRTY)); + } + @Override public void saveCode(byte[] address, byte[] code) { codeCache.put(Key.create(address), Value.create(code, Type.CREATE)); @@ -709,6 +737,7 @@ public void commit() { commitVotesCache(repository); commitDelegationCache(repository); commitDelegatedResourceAccountIndexCache(repository); + commitTransientStorage(repository); } @Override @@ -767,6 +796,11 @@ public void putDelegatedResourceAccountIndex(Key key, Value value) { delegatedResourceAccountIndexCache.put(key, value); } + @Override + public void putTransientStorageValue(Key address, Key key, Value value) { + transientStorage.put(address, key, value); + } + @Override public long addTokenBalance(byte[] address, byte[] tokenId, long value) { byte[] tokenIdWithoutLeadingZero = ByteUtil.stripLeadingZeroes(tokenId); @@ -1013,6 +1047,17 @@ private void commitDelegatedResourceAccountIndexCache(Repository deposit) { })); } + public void commitTransientStorage(Repository deposit) { + if (deposit != null) { + transientStorage.cellSet().forEach(cell -> { + if (cell.getValue().getType().isDirty() || cell.getValue().getType().isCreate()) { + deposit.putTransientStorageValue( + cell.getRowKey(), cell.getColumnKey(), cell.getValue()); + } + }); + } + } + /** * Get the block id from the number. */ diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 6fe29a7a136..399c3a6b292 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -227,6 +227,8 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] CONSENSUS_LOGIC_OPTIMIZATION = "CONSENSUS_LOGIC_OPTIMIZATION".getBytes(); + private static final byte[] ALLOW_TVM_CANCUN = "ALLOW_TVM_CANCUN".getBytes(); + @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { super(dbName); @@ -2914,6 +2916,18 @@ public boolean allowWitnessSortOptimization() { return this.allowConsensusLogicOptimization(); } + public void saveAllowTvmCancun(long allowTvmCancun) { + this.put(ALLOW_TVM_CANCUN, + new BytesCapsule(ByteArray.fromLong(allowTvmCancun))); + } + + public long getAllowTvmCancun() { + return Optional.ofNullable(getUnchecked(ALLOW_TVM_CANCUN)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElse(CommonParameter.getInstance().getAllowTvmCancun()); + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 8b599035f64..ae03372ea48 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -703,6 +703,10 @@ public class CommonParameter { @Setter public long consensusLogicOptimization; + @Getter + @Setter + public long allowTvmCancun; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 2043ba7fcdc..f18a7c055f3 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -396,4 +396,6 @@ public class Constant { public static final String COMMITTEE_CONSENSUS_LOGIC_OPTIMIZATION = "committee.consensusLogicOptimization"; + + public static final String COMMITTEE_ALLOW_TVM_CANCUN = "committee.allowTvmCancun"; } diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index e2eea8700d1..ce70d8b4cb7 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1353,6 +1353,11 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getConsensusLogicOptimization()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getAllowTvmCancun") + .setValue(dbManager.getDynamicPropertiesStore().getAllowTvmCancun()) + .build()); + return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 2ac3e69eced..f53a0125466 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -241,6 +241,7 @@ public static void clearParam() { PARAMETER.allowEnergyAdjustment = 0; PARAMETER.allowStrictMath = 0; PARAMETER.consensusLogicOptimization = 0; + PARAMETER.allowTvmCancun = 0; } /** @@ -1255,6 +1256,10 @@ public static void setParam(final Config config) { config.hasPath(Constant.COMMITTEE_CONSENSUS_LOGIC_OPTIMIZATION) ? config .getInt(Constant.COMMITTEE_CONSENSUS_LOGIC_OPTIMIZATION) : 0; + PARAMETER.allowTvmCancun = + config.hasPath(Constant.COMMITTEE_ALLOW_TVM_CANCUN) ? config + .getInt(Constant.COMMITTEE_ALLOW_TVM_CANCUN) : 0; + logConfig(); } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 120394de1be..1a95fd5064d 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -376,6 +376,10 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) .saveConsensusLogicOptimization(entry.getValue()); break; } + case ALLOW_TVM_CANCUN: { + manager.getDynamicPropertiesStore().saveAllowTvmCancun(entry.getValue()); + break; + } default: find = false; break; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java index 2a70364b8d1..ed4c8c47a2c 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java @@ -934,6 +934,53 @@ public void testVoteWitnessCost() throws ContractValidateException { Assert.assertEquals(30000 + memoryExpandEnergy, EnergyCost.getVoteWitnessCost2(program)); } + @Test + public void testTransientStorageOperations() throws ContractValidateException { + VMConfig.initAllowTvmCancun(1); + + invoke = new ProgramInvokeMockImpl(); + invoke.setEnergyLimit(20000); + Protocol.Transaction trx = Protocol.Transaction.getDefaultInstance(); + InternalTransaction interTrx = + new InternalTransaction(trx, InternalTransaction.TrxType.TRX_UNKNOWN_TYPE); + + // TLOAD = 0x5c; + byte[] op = new byte[] {0x60, 0x01, 0x5c}; + program = new Program(op, op, invoke, interTrx); + testOperations(program); + Assert.assertEquals(103, program.getResult().getEnergyUsed()); + Assert.assertEquals(new DataWord(0x00), program.getStack().pop()); + + // TSTORE = 0x5d; + op = new byte[] {0x60, 0x01, 0x60, 0x01, 0x5d}; + program = new Program(op, op, invoke, interTrx); + testOperations(program); + Assert.assertEquals(106, program.getResult().getEnergyUsed()); + Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001", + Hex.toHexString(program.getContractState().getTransientStorageValue( + program.getContractAddress().getData(), new DataWord(0x01).getData()))); + VMConfig.initAllowTvmCancun(0); + } + + @Test + public void testMCOPY() throws ContractValidateException { + VMConfig.initAllowTvmCancun(1); + + invoke = new ProgramInvokeMockImpl(); + Protocol.Transaction trx = Protocol.Transaction.getDefaultInstance(); + InternalTransaction interTrx = + new InternalTransaction(trx, InternalTransaction.TrxType.TRX_UNKNOWN_TYPE); + + // MCOPY = 0x5e + byte[] op = new byte[] {0x60, 0x20, 0x60, 0x01, 0x60, 0x20, 0x5e}; + program = new Program(op, op, invoke, interTrx); + testOperations(program); + Assert.assertEquals(21, program.getResult().getEnergyUsed()); + Assert.assertEquals(64, program.getMemSize()); + + VMConfig.initAllowTvmCancun(0); + } + private void testOperations(Program program) { try { while (!program.isStopped()) { From 2d2195c9f99e90372ba1af179cd067327de2d474 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Fri, 14 Feb 2025 12:01:30 +0800 Subject: [PATCH 1117/1197] fix(test): update test case --- .../src/test/java/org/tron/common/config/args/ArgsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index 0b66064f663..01a49f6df40 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -36,7 +36,7 @@ public void testConfig() { Args.logConfig(); Assert.assertEquals(Args.getInstance().getMaxTransactionPendingSize(), 2000); Assert.assertEquals(Args.getInstance().getPendingTransactionTimeout(), 60_000); - Assert.assertEquals(Args.getInstance().getMaxFastForwardNum(), 3); + Assert.assertEquals(Args.getInstance().getMaxFastForwardNum(), 4); Assert.assertEquals(Args.getInstance().getBlockCacheTimeout(), 60); Assert.assertEquals(Args.getInstance().isNodeDetectEnable(), false); Assert.assertFalse(Args.getInstance().isNodeEffectiveCheckEnable()); From 60364ab9f546c3a0cd5d4b3217284a96ac623350 Mon Sep 17 00:00:00 2001 From: Liulei Date: Thu, 27 Jun 2024 17:05:50 +0800 Subject: [PATCH 1118/1197] feat(tvm): update comments and tests --- .../src/main/java/org/tron/core/vm/Op.java | 4 ++-- .../org/tron/core/vm/OperationActions.java | 2 +- .../common/runtime/vm/OperationsTest.java | 21 ++++++++++++++++--- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/Op.java b/actuator/src/main/java/org/tron/core/vm/Op.java index 4b4488ef427..5125f067d31 100644 --- a/actuator/src/main/java/org/tron/core/vm/Op.java +++ b/actuator/src/main/java/org/tron/core/vm/Op.java @@ -145,9 +145,9 @@ public class Op { // (0x5a) Get the amount of available gas public static final int GAS = 0x5a; public static final int JUMPDEST = 0x5b; - // (0x5c) Load word from transient memory + // (0x5c) Load word from transient storage public static final int TLOAD = 0x5c; - // (0x5d) Save word to transient memory + // (0x5d) Save word to transient storage public static final int TSTORE = 0x5d; // (0x5e) Copy word from memory public static final int MCOPY = 0x5e; diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index 713c43851a0..1208a94b61b 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -649,7 +649,7 @@ public static void tLoadAction(Program program) { byte[] data = program.getContractState().getTransientStorageValue(address.getData(), key.getData()); - DataWord value = data != null ? new DataWord(data) : DataWord.ZERO; + DataWord value = data != null ? new DataWord(data) : DataWord.ZERO(); program.stackPush(value); program.step(); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java index ed4c8c47a2c..0eb00244d21 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java @@ -956,9 +956,17 @@ public void testTransientStorageOperations() throws ContractValidateException { program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(106, program.getResult().getEnergyUsed()); - Assert.assertEquals("0000000000000000000000000000000000000000000000000000000000000001", - Hex.toHexString(program.getContractState().getTransientStorageValue( - program.getContractAddress().getData(), new DataWord(0x01).getData()))); + Assert.assertArrayEquals(new DataWord(0x01).getData(), + program.getContractState().getTransientStorageValue( + program.getContractAddress().getData(), new DataWord(0x01).getData())); + + // TLOAD = 0x5c; + op = new byte[] {0x60, 0x01, 0x5c}; + program = new Program(op, op, invoke, interTrx); + testOperations(program); + Assert.assertEquals(103, program.getResult().getEnergyUsed()); + Assert.assertEquals(new DataWord(0x01), program.getStack().pop()); + VMConfig.initAllowTvmCancun(0); } @@ -978,6 +986,13 @@ public void testMCOPY() throws ContractValidateException { Assert.assertEquals(21, program.getResult().getEnergyUsed()); Assert.assertEquals(64, program.getMemSize()); + op = + new byte[] { + 0x60, 0x01, 0x60, 0x01, 0x52, 0x60, 0x20, 0x60, 0x01, 0x60, 0x20, 0x5e, 0x60, 0x20, 0x51}; + program = new Program(op, op, invoke, interTrx); + testOperations(program); + Assert.assertEquals(new DataWord(0x01), program.getStack().pop()); + VMConfig.initAllowTvmCancun(0); } From 2d2200c771f8673a0ae5aa6fcfd7214fd678bc2d Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Fri, 14 Feb 2025 13:54:19 +0800 Subject: [PATCH 1119/1197] feat(consensus): check block header time is an integer multiple of 3s --- .../org/tron/consensus/dpos/DposService.java | 7 +++ .../tron/core/consensus/DposServiceTest.java | 47 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/consensus/DposServiceTest.java diff --git a/consensus/src/main/java/org/tron/consensus/dpos/DposService.java b/consensus/src/main/java/org/tron/consensus/dpos/DposService.java index 5ec6c7c554b..e8e162bd0a8 100644 --- a/consensus/src/main/java/org/tron/consensus/dpos/DposService.java +++ b/consensus/src/main/java/org/tron/consensus/dpos/DposService.java @@ -1,5 +1,6 @@ package org.tron.consensus.dpos; +import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.MAX_ACTIVE_WITNESS_NUM; import static org.tron.core.config.Parameter.ChainConstant.SOLIDIFIED_THRESHOLD; @@ -116,6 +117,12 @@ public boolean validBlock(BlockCapsule blockCapsule) { } ByteString witnessAddress = blockCapsule.getWitnessAddress(); long timeStamp = blockCapsule.getTimeStamp(); + if (timeStamp % BLOCK_PRODUCED_INTERVAL != 0 + && consensusDelegate.getDynamicPropertiesStore().allowConsensusLogicOptimization()) { + logger.warn("ValidBlock failed: witness: {}, timeStamp: {}", + ByteArray.toHexString(witnessAddress.toByteArray()), timeStamp); + return false; + } long bSlot = dposSlot.getAbSlot(timeStamp); long hSlot = dposSlot.getAbSlot(consensusDelegate.getLatestBlockHeaderTimestamp()); if (bSlot <= hSlot) { diff --git a/framework/src/test/java/org/tron/core/consensus/DposServiceTest.java b/framework/src/test/java/org/tron/core/consensus/DposServiceTest.java new file mode 100644 index 00000000000..6f1a14e5c2d --- /dev/null +++ b/framework/src/test/java/org/tron/core/consensus/DposServiceTest.java @@ -0,0 +1,47 @@ +package org.tron.core.consensus; + +import static org.mockito.Mockito.mock; + +import java.lang.reflect.Field; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; +import org.tron.consensus.ConsensusDelegate; +import org.tron.consensus.dpos.DposService; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.Protocol; + +public class DposServiceTest { + DposService service = new DposService(); + + @Test + public void test() throws Exception { + long headTime = 1724036757000L; + + ConsensusDelegate consensusDelegate = mock(ConsensusDelegate.class); + Field field = service.getClass().getDeclaredField("consensusDelegate"); + field.setAccessible(true); + field.set(service, consensusDelegate); + + DynamicPropertiesStore store = mock(DynamicPropertiesStore.class); + Mockito.when(consensusDelegate.getDynamicPropertiesStore()).thenReturn(store); + + Mockito.when(consensusDelegate.getLatestBlockHeaderNumber()).thenReturn(0L); + boolean f = service.validBlock(null); + Assert.assertTrue(f); + + Protocol.BlockHeader.raw raw = Protocol.BlockHeader.raw.newBuilder() + .setTimestamp(headTime + 3001).build(); + Protocol.BlockHeader header = Protocol.BlockHeader.newBuilder().setRawData(raw).build(); + Protocol.Block block = Protocol.Block.newBuilder().setBlockHeader(header).build(); + + Mockito.when(consensusDelegate.getLatestBlockHeaderNumber()).thenReturn(100L); + Mockito.when(store.allowConsensusLogicOptimization()).thenReturn(true); + + Mockito.when(consensusDelegate.getLatestBlockHeaderTimestamp()).thenReturn(headTime + 3000); + f = service.validBlock(new BlockCapsule(block)); + Assert.assertTrue(!f); + + } +} \ No newline at end of file From e90c3213a0b9b64143018fc15315c2d4820eafad Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Fri, 14 Feb 2025 14:13:17 +0800 Subject: [PATCH 1120/1197] feat(consensus): verify the slot to avoid block generation during maintenance period --- .../org/tron/consensus/dpos/DposService.java | 6 ++ .../tron/core/consensus/DposServiceTest.java | 82 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/consensus/DposServiceTest.java diff --git a/consensus/src/main/java/org/tron/consensus/dpos/DposService.java b/consensus/src/main/java/org/tron/consensus/dpos/DposService.java index 292294b2c2d..4ab9f8ea26e 100644 --- a/consensus/src/main/java/org/tron/consensus/dpos/DposService.java +++ b/consensus/src/main/java/org/tron/consensus/dpos/DposService.java @@ -124,6 +124,12 @@ public boolean validBlock(BlockCapsule blockCapsule) { } long slot = dposSlot.getSlot(timeStamp); + if (slot == 0 + && consensusDelegate.getDynamicPropertiesStore().allowConsensusLogicOptimization()) { + logger.warn("ValidBlock failed: slot error, witness: {}, timeStamp: {}", + ByteArray.toHexString(witnessAddress.toByteArray()), new DateTime(timeStamp)); + return false; + } final ByteString scheduledWitness = dposSlot.getScheduledWitness(slot); if (!scheduledWitness.equals(witnessAddress)) { logger.warn("ValidBlock failed: sWitness: {}, bWitness: {}, bTimeStamp: {}, slot: {}", diff --git a/framework/src/test/java/org/tron/core/consensus/DposServiceTest.java b/framework/src/test/java/org/tron/core/consensus/DposServiceTest.java new file mode 100644 index 00000000000..02e8dc6b809 --- /dev/null +++ b/framework/src/test/java/org/tron/core/consensus/DposServiceTest.java @@ -0,0 +1,82 @@ +package org.tron.core.consensus; + +import static org.mockito.Mockito.mock; + +import com.google.protobuf.ByteString; +import java.lang.reflect.Field; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; +import org.tron.common.parameter.CommonParameter; +import org.tron.consensus.ConsensusDelegate; +import org.tron.consensus.dpos.DposService; +import org.tron.consensus.dpos.DposSlot; +import org.tron.core.Constant; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.p2p.utils.NetUtil; +import org.tron.protos.Protocol; + +public class DposServiceTest { + DposService service = new DposService(); + + @Test + public void testValiedSlot() throws Exception { + Args.setParam(new String[] {"-w"}, Constant.TEST_CONF); + CommonParameter parameter = Args.getInstance(); + long headTime = 1724036757000L; + ByteString witness = ByteString.copyFrom(NetUtil.getNodeId()); + ByteString witness2 = ByteString.copyFrom(NetUtil.getNodeId()); + + ConsensusDelegate consensusDelegate = mock(ConsensusDelegate.class); + Field field = service.getClass().getDeclaredField("consensusDelegate"); + field.setAccessible(true); + field.set(service, consensusDelegate); + + + DposSlot dposSlot = mock(DposSlot.class); + field = service.getClass().getDeclaredField("dposSlot"); + field.setAccessible(true); + field.set(service, dposSlot); + + Mockito.when(dposSlot.getAbSlot(headTime)).thenReturn(headTime / 3000); + Mockito.when(dposSlot.getAbSlot(headTime + 3000)).thenReturn((headTime + 3000) / 3000); + + DynamicPropertiesStore store = mock(DynamicPropertiesStore.class); + Mockito.when(consensusDelegate.getDynamicPropertiesStore()).thenReturn(store); + + Mockito.when(consensusDelegate.getLatestBlockHeaderNumber()).thenReturn(0L); + boolean f = service.validBlock(null); + Assert.assertTrue(f); + + Mockito.when(consensusDelegate.getLatestBlockHeaderNumber()).thenReturn(100L); + + Protocol.BlockHeader.raw raw = Protocol.BlockHeader.raw.newBuilder() + .setTimestamp(headTime + 3000) + .setWitnessAddress(witness).build(); + Protocol.BlockHeader header = Protocol.BlockHeader.newBuilder().setRawData(raw).build(); + Protocol.Block block = Protocol.Block.newBuilder().setBlockHeader(header).build(); + + Mockito.when(consensusDelegate.getLatestBlockHeaderTimestamp()).thenReturn(headTime + 3000); + f = service.validBlock(new BlockCapsule(block)); + Assert.assertTrue(!f); + + Mockito.when(consensusDelegate.getLatestBlockHeaderTimestamp()).thenReturn(headTime); + + Mockito.when(dposSlot.getSlot(headTime + 3000)).thenReturn(0L); + + Mockito.when(dposSlot.getScheduledWitness(0L)).thenReturn(witness2); + f = service.validBlock(new BlockCapsule(block)); + Assert.assertTrue(!f); + + Mockito.when(dposSlot.getScheduledWitness(0L)).thenReturn(witness); + f = service.validBlock(new BlockCapsule(block)); + Assert.assertTrue(f); + + Mockito.when(store.allowConsensusLogicOptimization()).thenReturn(true); + f = service.validBlock(new BlockCapsule(block)); + Assert.assertTrue(!f); + } + +} From bdea53ff0e25f2af16bc357e638018791ead79f3 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Fri, 14 Feb 2025 14:19:10 +0800 Subject: [PATCH 1121/1197] feat(net): change the MAX_PEER_COUNT_PER_ADDRESS value to 5 --- .../main/java/org/tron/core/net/service/relay/RelayService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java index 107d086c1b7..fa5df2e5edc 100644 --- a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java @@ -40,7 +40,7 @@ @Component public class RelayService { - private static final int MAX_PEER_COUNT_PER_ADDRESS = 2; + private static final int MAX_PEER_COUNT_PER_ADDRESS = 5; @Autowired private ChainBaseManager chainBaseManager; From 00d994b01deaefed7b2e719e08620e36000c12f1 Mon Sep 17 00:00:00 2001 From: Asuka Date: Fri, 14 Feb 2025 17:17:56 +0800 Subject: [PATCH 1122/1197] test(vm): enable saving details for cancelcallunfreeze opcode test --- .../src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java index 9558c701109..d8f7570b213 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -22,6 +22,7 @@ import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; +import org.tron.common.parameter.CommonParameter; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.RuntimeImpl; import org.tron.common.runtime.TVMTestResult; @@ -274,6 +275,7 @@ private TVMTestResult triggerWithdrawExpireUnfreeze( private TVMTestResult triggerCancelAllUnfreezeV2( byte[] callerAddr, byte[] contractAddr, contractResult expectedResult, Consumer check) throws Exception { + CommonParameter.getInstance().saveCancelAllUnfreezeV2Details = true; return triggerContract( callerAddr, contractAddr, fee, expectedResult, check, "cancelAllUnfreezeBalanceV2()"); } From 878dffcf455f6805e2f9e064c41d4675dc80550b Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Fri, 14 Feb 2025 17:24:28 +0800 Subject: [PATCH 1123/1197] fix(test): update test case --- .../test/java/org/tron/core/net/services/SyncServiceTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java b/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java index 89c081eaab5..c2883fb349d 100644 --- a/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/SyncServiceTest.java @@ -85,9 +85,11 @@ public void testStartSync() { peer.setChannel(c1); + ReflectUtils.setFieldValue(peer, "tronState", TronState.SYNCING); + service.startSync(peer); - ReflectUtils.setFieldValue(peer, "tronState", TronState.SYNCING); + ReflectUtils.setFieldValue(peer, "tronState", TronState.INIT); service.startSync(peer); } catch (Exception e) { From 0640dd6a35b1d23b656b344e00e15ea531d4103a Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Wed, 5 Feb 2025 17:32:02 +0800 Subject: [PATCH 1124/1197] feat(event): optimize the event service --- .../common/logsfilter/EventPluginConfig.java | 8 + .../logsfilter/trigger/BlockLogTrigger.java | 2 +- .../logsfilter/trigger/SolidityTrigger.java | 2 +- .../src/main/java/org/tron/core/Constant.java | 2 + .../common/application/ApplicationImpl.java | 6 + .../common/logsfilter/EventPluginLoader.java | 17 + .../java/org/tron/core/config/args/Args.java | 9 + .../main/java/org/tron/core/db/Manager.java | 37 +- .../core/services/event/BlockEventCache.java | 96 +++++ .../core/services/event/BlockEventGet.java | 387 ++++++++++++++++++ .../core/services/event/BlockEventLoad.java | 86 ++++ .../core/services/event/EventService.java | 61 +++ .../services/event/HistoryEventService.java | 76 ++++ .../services/event/RealtimeEventService.java | 120 ++++++ .../services/event/SolidEventService.java | 110 +++++ .../core/services/event/bo/BlockEvent.java | 28 ++ .../tron/core/services/event/bo/Event.java | 14 + .../event/bo/SmartContractTrigger.java | 14 + .../event/exception/EventException.java | 7 + .../tron/core/event/BlockEventCacheTest.java | 90 ++++ .../tron/core/event/BlockEventGetTest.java | 185 +++++++++ .../tron/core/event/BlockEventLoadTest.java | 124 ++++++ .../org/tron/core/event/EventServiceTest.java | 34 ++ .../core/event/HistoryEventServiceTest.java | 85 ++++ .../core/event/RealtimeEventServiceTest.java | 118 ++++++ .../core/event/SolidEventServiceTest.java | 116 ++++++ 26 files changed, 1818 insertions(+), 16 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/services/event/BlockEventCache.java create mode 100644 framework/src/main/java/org/tron/core/services/event/BlockEventGet.java create mode 100644 framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java create mode 100644 framework/src/main/java/org/tron/core/services/event/EventService.java create mode 100644 framework/src/main/java/org/tron/core/services/event/HistoryEventService.java create mode 100644 framework/src/main/java/org/tron/core/services/event/RealtimeEventService.java create mode 100644 framework/src/main/java/org/tron/core/services/event/SolidEventService.java create mode 100644 framework/src/main/java/org/tron/core/services/event/bo/BlockEvent.java create mode 100644 framework/src/main/java/org/tron/core/services/event/bo/Event.java create mode 100644 framework/src/main/java/org/tron/core/services/event/bo/SmartContractTrigger.java create mode 100644 framework/src/main/java/org/tron/core/services/event/exception/EventException.java create mode 100644 framework/src/test/java/org/tron/core/event/BlockEventCacheTest.java create mode 100644 framework/src/test/java/org/tron/core/event/BlockEventGetTest.java create mode 100644 framework/src/test/java/org/tron/core/event/BlockEventLoadTest.java create mode 100644 framework/src/test/java/org/tron/core/event/EventServiceTest.java create mode 100644 framework/src/test/java/org/tron/core/event/HistoryEventServiceTest.java create mode 100644 framework/src/test/java/org/tron/core/event/RealtimeEventServiceTest.java create mode 100644 framework/src/test/java/org/tron/core/event/SolidEventServiceTest.java diff --git a/common/src/main/java/org/tron/common/logsfilter/EventPluginConfig.java b/common/src/main/java/org/tron/common/logsfilter/EventPluginConfig.java index 050499b6123..e2aa0950d72 100644 --- a/common/src/main/java/org/tron/common/logsfilter/EventPluginConfig.java +++ b/common/src/main/java/org/tron/common/logsfilter/EventPluginConfig.java @@ -15,6 +15,14 @@ public class EventPluginConfig { public static final String SOLIDITY_EVENT_NAME = "solidityevent"; public static final String SOLIDITY_LOG_NAME = "soliditylog"; + @Getter + @Setter + private int version; + + @Getter + @Setter + private long startSyncBlockNum; + @Getter @Setter private String pluginPath; diff --git a/common/src/main/java/org/tron/common/logsfilter/trigger/BlockLogTrigger.java b/common/src/main/java/org/tron/common/logsfilter/trigger/BlockLogTrigger.java index 5e64c5a1050..b878597045d 100644 --- a/common/src/main/java/org/tron/common/logsfilter/trigger/BlockLogTrigger.java +++ b/common/src/main/java/org/tron/common/logsfilter/trigger/BlockLogTrigger.java @@ -34,7 +34,7 @@ public BlockLogTrigger() { @Override public String toString() { return new StringBuilder().append("triggerName: ").append(getTriggerName()) - .append("timestamp: ") + .append(", timestamp: ") .append(timeStamp) .append(", blockNumber: ") .append(blockNumber) diff --git a/common/src/main/java/org/tron/common/logsfilter/trigger/SolidityTrigger.java b/common/src/main/java/org/tron/common/logsfilter/trigger/SolidityTrigger.java index d9745f4724a..230544a91ff 100644 --- a/common/src/main/java/org/tron/common/logsfilter/trigger/SolidityTrigger.java +++ b/common/src/main/java/org/tron/common/logsfilter/trigger/SolidityTrigger.java @@ -16,7 +16,7 @@ public SolidityTrigger() { @Override public String toString() { return new StringBuilder().append("triggerName: ").append(getTriggerName()) - .append("timestamp: ") + .append(", timestamp: ") .append(timeStamp) .append(", latestSolidifiedBlockNumber: ") .append(latestSolidifiedBlockNumber).toString(); diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 3bdbf2113af..00f9723abed 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -280,6 +280,8 @@ public class Constant { public static final String NATIVE_QUEUE_SEND_LENGTH = "event.subscribe.native.sendqueuelength"; + public static final String EVENT_SUBSCRIBE_VERSION = "event.subscribe.version"; + public static final String EVENT_SUBSCRIBE_START_SYNC_BLOCK_NUM = "event.subscribe.startSyncBlockNum"; public static final String EVENT_SUBSCRIBE_PATH = "event.subscribe.path"; public static final String EVENT_SUBSCRIBE_SERVER = "event.subscribe.server"; public static final String EVENT_SUBSCRIBE_DB_CONFIG = "event.subscribe.dbconfig"; diff --git a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java index 3cb75cb1e24..443f93e446d 100644 --- a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java +++ b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java @@ -10,6 +10,7 @@ import org.tron.core.db.Manager; import org.tron.core.metrics.MetricsUtil; import org.tron.core.net.TronNetService; +import org.tron.core.services.event.EventService; @Slf4j(topic = "app") @Component @@ -17,6 +18,9 @@ public class ApplicationImpl implements Application { private ServiceContainer services; + @Autowired + private EventService eventService; + @Autowired private TronNetService tronNetService; @@ -56,6 +60,7 @@ public void initServices(CommonParameter parameter) { public void startup() { this.initServices(Args.getInstance()); this.startServices(); + eventService.init(); if ((!Args.getInstance().isSolidityNode()) && (!Args.getInstance().isP2pDisable())) { tronNetService.start(); } @@ -66,6 +71,7 @@ public void startup() { @Override public void shutdown() { this.shutdownServices(); + eventService.close(); consensusService.stop(); if (!Args.getInstance().isSolidityNode() && (!Args.getInstance().p2pDisable)) { tronNetService.close(); diff --git a/framework/src/main/java/org/tron/common/logsfilter/EventPluginLoader.java b/framework/src/main/java/org/tron/common/logsfilter/EventPluginLoader.java index c8019dac93a..7896eeffae4 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/EventPluginLoader.java +++ b/framework/src/main/java/org/tron/common/logsfilter/EventPluginLoader.java @@ -24,6 +24,7 @@ import org.tron.common.logsfilter.trigger.SolidityTrigger; import org.tron.common.logsfilter.trigger.TransactionLogTrigger; import org.tron.common.logsfilter.trigger.Trigger; +import org.tron.common.utils.JsonUtil; @Slf4j public class EventPluginLoader { @@ -42,6 +43,10 @@ public class EventPluginLoader { private List triggerConfigList; + private int version = 0; + + private long startSyncBlockNum = 0; + private boolean blockLogTriggerEnable = false; private boolean blockLogTriggerSolidified = false; @@ -219,6 +224,10 @@ public boolean start(EventPluginConfig config) { return false; } + this.version = config.getVersion(); + + this.startSyncBlockNum = config.getStartSyncBlockNum(); + this.triggerConfigList = config.getTriggerConfigList(); useNativeQueue = config.isUseNativeQueue(); @@ -358,6 +367,14 @@ public void postSolidityTrigger(SolidityTrigger trigger) { } } + public synchronized int getVersion() { + return version; + } + + public synchronized long getStartSyncBlockNum() { + return startSyncBlockNum; + } + public synchronized boolean isBlockLogTriggerEnable() { return blockLogTriggerEnable; } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 7397b69cde3..2dbfc04e8d5 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1323,6 +1323,15 @@ private static EventPluginConfig getEventPluginConfig( final com.typesafe.config.Config config) { EventPluginConfig eventPluginConfig = new EventPluginConfig(); + if (config.hasPath(Constant.EVENT_SUBSCRIBE_VERSION)) { + eventPluginConfig.setVersion(config.getInt(Constant.EVENT_SUBSCRIBE_VERSION)); + } + + if (config.hasPath(Constant.EVENT_SUBSCRIBE_START_SYNC_BLOCK_NUM)) { + eventPluginConfig.setStartSyncBlockNum(config + .getLong(Constant.EVENT_SUBSCRIBE_START_SYNC_BLOCK_NUM)); + } + boolean useNativeQueue = false; int bindPort = 0; int sendQueueLength = 0; diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 908e248bdee..f6076c1f292 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -237,6 +237,7 @@ public class Manager { Collections.synchronizedList(Lists.newArrayList()); // the capacity is equal to Integer.MAX_VALUE default private BlockingQueue rePushTransactions; + @Getter private BlockingQueue triggerCapsuleQueue; // log filter private boolean isRunFilterProcessThread = true; @@ -1100,7 +1101,9 @@ private void switchFork(BlockCapsule newHead) while (!getDynamicPropertiesStore() .getLatestBlockHeaderHash() .equals(binaryTree.getValue().peekLast().getParentHash())) { - reOrgContractTrigger(); + if (EventPluginLoader.getInstance().getVersion() == 0) { + reOrgContractTrigger(); + } reOrgLogsFilter(); eraseBlock(); } @@ -1362,11 +1365,26 @@ public void pushBlock(final BlockCapsule block) } void blockTrigger(final BlockCapsule block, long oldSolid, long newSolid) { + // post block and logs for jsonrpc try { + if (CommonParameter.getInstance().isJsonRpcHttpFullNodeEnable()) { + postBlockFilter(block, false); + postLogsFilter(block, false, false); + } + + if (CommonParameter.getInstance().isJsonRpcHttpSolidityNodeEnable()) { + postSolidityFilter(oldSolid, newSolid); + } + + if (EventPluginLoader.getInstance().getVersion() != 0) { + lastUsedSolidityNum = newSolid; + return; + } + // if event subscribe is enabled, post block trigger to queue postBlockTrigger(block); // if event subscribe is enabled, post solidity trigger to queue - postSolidityTrigger(oldSolid, newSolid); + postSolidityTrigger(newSolid); } catch (Exception e) { logger.error("Block trigger failed. head: {}, oldSolid: {}, newSolid: {}", block.getNum(), oldSolid, newSolid, e); @@ -1506,7 +1524,8 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block // if event subscribe is enabled, post contract triggers to queue // only trigger when process block - if (Objects.nonNull(blockCap) && !blockCap.isMerkleRootEmpty()) { + if (Objects.nonNull(blockCap) && !blockCap.isMerkleRootEmpty() + && EventPluginLoader.getInstance().getVersion() == 0) { String blockHash = blockCap.getBlockId().toString(); postContractTrigger(trace, false, blockHash); } @@ -2083,7 +2102,7 @@ private void postSolidityFilter(final long oldSolidNum, final long latestSolidif } } - private void postSolidityTrigger(final long oldSolidNum, final long latestSolidifiedBlockNumber) { + private void postSolidityTrigger(final long latestSolidifiedBlockNumber) { if (eventPluginLoaded && EventPluginLoader.getInstance().isSolidityLogTriggerEnable()) { for (Long i : Args.getSolidityContractLogTriggerMap().keySet()) { postSolidityLogContractTrigger(i, latestSolidifiedBlockNumber); @@ -2109,10 +2128,6 @@ private void postSolidityTrigger(final long oldSolidNum, final long latestSolidi } } } - - if (CommonParameter.getInstance().isJsonRpcHttpSolidityNodeEnable()) { - postSolidityFilter(oldSolidNum, latestSolidifiedBlockNumber); - } lastUsedSolidityNum = latestSolidifiedBlockNumber; } @@ -2224,12 +2239,6 @@ private void postLogsFilter(final BlockCapsule blockCapsule, boolean solidified, } void postBlockTrigger(final BlockCapsule blockCapsule) { - // post block and logs for jsonrpc - if (CommonParameter.getInstance().isJsonRpcHttpFullNodeEnable()) { - postBlockFilter(blockCapsule, false); - postLogsFilter(blockCapsule, false, false); - } - // process block trigger long solidityBlkNum = getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); if (eventPluginLoaded && EventPluginLoader.getInstance().isBlockLogTriggerEnable()) { diff --git a/framework/src/main/java/org/tron/core/services/event/BlockEventCache.java b/framework/src/main/java/org/tron/core/services/event/BlockEventCache.java new file mode 100644 index 00000000000..40abae07946 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/event/BlockEventCache.java @@ -0,0 +1,96 @@ +package org.tron.core.services.event; + +import com.google.common.collect.Lists; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.services.event.bo.BlockEvent; +import org.tron.core.services.event.exception.EventException; + +@Slf4j(topic = "event") +public class BlockEventCache { + @Getter + private static volatile long solidNum; + + @Getter + private static volatile BlockEvent head; + + @Getter + private static volatile BlockCapsule.BlockId solidId; + + private static Map blockEventMap = new ConcurrentHashMap<>(); + + private static Map> numMap = new ConcurrentHashMap<>(); + + public static BlockEvent getBlockEvent(BlockCapsule.BlockId blockId) { + return blockEventMap.get(blockId); + } + + public static void init(BlockCapsule.BlockId blockId) { + blockEventMap.clear(); + numMap.clear(); + solidNum = blockId.getNum(); + head = new BlockEvent(blockId); + solidId = blockId; + List list = new ArrayList<>(); + list.add(head); + numMap.put(blockId.getNum(), list); + blockEventMap.put(blockId, head); + } + + public static void add(BlockEvent blockEvent) throws EventException { + logger.info("Add block event, {}", blockEvent.getBlockId().getString(), + blockEvent.getParentId().getString()); + if (blockEventMap.get(blockEvent.getParentId()) == null) { + throw new EventException("unlink BlockEvent, " + + blockEvent.getBlockId().getString() + ", " + + blockEvent.getParentId().getString()); + } + + long num = blockEvent.getBlockId().getNum(); + List list = numMap.get(num); + if (list == null) { + list = new ArrayList<>(); + numMap.put(num, list); + } + list.add(blockEvent); + + blockEventMap.put(blockEvent.getBlockId(), blockEvent); + + if (num > head.getBlockId().getNum()) { + head = blockEvent; + } + + if (blockEvent.getSolidId().getNum() > solidId.getNum()) { + solidId = blockEvent.getSolidId(); + } + } + + public static void remove(BlockCapsule.BlockId solidId) { + logger.info("Remove solidId {}, solidNum {}, {}, {}", + solidId.getString(), solidNum, numMap.size(), blockEventMap.size()); + numMap.forEach((k, v) -> { + if (k < solidId.getNum()) { + v.forEach(value -> blockEventMap.remove(value.getBlockId())); + numMap.remove(k); + } + }); + solidNum = solidId.getNum(); + } + + public static List getSolidBlockEvents(BlockCapsule.BlockId solidId) { + List blockEvents = new ArrayList<>(); + BlockCapsule.BlockId tmp = solidId; + while (tmp.getNum() > solidNum) { + BlockEvent blockEvent = blockEventMap.get(tmp); + blockEvents.add(blockEvent); + tmp = blockEvent.getParentId(); + } + + return Lists.reverse(blockEvents); + } +} diff --git a/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java b/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java new file mode 100644 index 00000000000..8ffc333eda4 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java @@ -0,0 +1,387 @@ +package org.tron.core.services.event; + +import com.google.common.collect.Lists; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.api.GrpcAPI; +import org.tron.common.crypto.Hash; +import org.tron.common.logsfilter.ContractEventParserAbi; +import org.tron.common.logsfilter.EventPluginLoader; +import org.tron.common.logsfilter.capsule.BlockLogTriggerCapsule; +import org.tron.common.logsfilter.capsule.RawData; +import org.tron.common.logsfilter.capsule.SolidityTriggerCapsule; +import org.tron.common.logsfilter.capsule.TransactionLogTriggerCapsule; +import org.tron.common.logsfilter.trigger.ContractEventTrigger; +import org.tron.common.logsfilter.trigger.ContractLogTrigger; +import org.tron.common.logsfilter.trigger.ContractTrigger; +import org.tron.common.runtime.vm.DataWord; +import org.tron.common.runtime.vm.LogInfo; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.StringUtil; +import org.tron.core.capsule.AbiCapsule; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.ContractCapsule; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.capsule.TransactionRetCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.db.TransactionTrace; +import org.tron.core.exception.BadItemException; +import org.tron.core.services.event.bo.BlockEvent; +import org.tron.core.services.event.bo.SmartContractTrigger; +import org.tron.core.store.StoreFactory; +import org.tron.protos.Protocol; +import org.tron.protos.contract.SmartContractOuterClass; + +@Slf4j(topic = "event") +@Component +public class BlockEventGet { + + private EventPluginLoader instance = EventPluginLoader.getInstance(); + + @Autowired + private Manager manager; + + public BlockEvent getBlockEvent(long blockNum) throws Exception { + BlockCapsule block = manager.getChainBaseManager().getBlockByNum(blockNum); + long solidNum = manager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); + BlockEvent blockEvent = new BlockEvent(); + blockEvent.setBlockId(block.getBlockId()); + blockEvent.setParentId(block.getParentBlockId()); + blockEvent.setSolidId(manager.getChainBaseManager().getBlockIdByNum(solidNum)); + blockEvent.setBlockTime(block.getTimeStamp()); + if (instance.isBlockLogTriggerEnable()) { + blockEvent.setBlockLogTriggerCapsule(getBlockLogTrigger(block, solidNum)); + } + + if (instance.isTransactionLogTriggerEnable()) { + blockEvent.setTransactionLogTriggerCapsules(getTransactionLogTrigger(block, solidNum)); + } + + if (instance.isContractLogTriggerEnable() + || instance.isContractEventTriggerEnable() + || instance.isSolidityLogTriggerEnable() + || instance.isSolidityEventTriggerEnable()) { + blockEvent.setSmartContractTrigger(getContractTrigger(block, solidNum)); + } + + if (instance.isSolidityTriggerEnable()) { + SolidityTriggerCapsule capsule = new SolidityTriggerCapsule(block.getNum()); + capsule.setTimeStamp(block.getTimeStamp()); + blockEvent.setSolidityTriggerCapsule(capsule); + } + + return blockEvent; + } + + public SmartContractTrigger getContractTrigger(BlockCapsule block, long solidNum) { + TransactionRetCapsule result; + try { + result = manager.getChainBaseManager().getTransactionRetStore() + .getTransactionInfoByBlockNum(ByteArray.fromLong(block.getNum())); + } catch (BadItemException e) { + throw new RuntimeException(e); + } + + SmartContractTrigger contractTrigger = new SmartContractTrigger(); + for (int i = 0; i < block.getTransactions().size(); i++) { + Protocol.Transaction tx = block.getInstance().getTransactions(i); + Protocol.TransactionInfo txInfo = result.getInstance().getTransactioninfo(i); + + List triggers = parseLogs(tx, txInfo); + for (ContractTrigger trigger : triggers) { + if (!EventPluginLoader.matchFilter(trigger)) { + continue; + } + ContractTrigger eventOrLog = processTrigger(trigger); + eventOrLog.setBlockHash(Hex.toHexString(block.getBlockId().getBytes())); + eventOrLog.setLatestSolidifiedBlockNumber(solidNum); + if (eventOrLog instanceof ContractEventTrigger) { + ContractEventTrigger event = (ContractEventTrigger) eventOrLog; + if (instance.isContractEventTriggerEnable() || instance.isSolidityEventTriggerEnable()) { + contractTrigger.getContractEventTriggers().add(event); + } + if ((instance.isContractLogTriggerEnable() + && instance.isContractLogTriggerRedundancy()) + || (instance.isSolidityLogTriggerEnable() + && instance.isSolidityLogTriggerRedundancy())) { + ContractLogTrigger logTrigger = new ContractLogTrigger(event); + logTrigger.setTopicList(trigger.getLogInfo().getHexTopics()); + logTrigger.setData(trigger.getLogInfo().getHexData()); + contractTrigger.getRedundancies().add(logTrigger); + } + } else if (eventOrLog instanceof ContractLogTrigger) { + ContractLogTrigger log = (ContractLogTrigger) eventOrLog; + if (instance.isContractLogTriggerEnable() || instance.isSolidityLogTriggerEnable()) { + contractTrigger.getContractLogTriggers().add(log); + } + } + } + } + + return contractTrigger; + } + + private List parseLogs(Protocol.Transaction tx, + Protocol.TransactionInfo txInfo) { + String originAddress = StringUtil + .encode58Check(TransactionCapsule.getOwner(tx.getRawData().getContract(0))); + + List logs = txInfo.getLogList(); + List list = new LinkedList<>(); + if (logs.isEmpty()) { + return list; + } + + Map addrMap = new HashMap<>(); + Map abiMap = new HashMap<>(); + + for (Protocol.TransactionInfo.Log log : logs) { + + byte[] contractAddress = TransactionTrace + .convertToTronAddress(log.getAddress().toByteArray()); + String strContractAddr = + ArrayUtils.isEmpty(contractAddress) ? "" : StringUtil.encode58Check(contractAddress); + if (addrMap.get(strContractAddr) != null) { + continue; + } + ContractCapsule contract = manager.getContractStore().get(contractAddress); + if (contract == null) { + // never + addrMap.put(strContractAddr, originAddress); + abiMap.put(strContractAddr, SmartContractOuterClass.SmartContract.ABI.getDefaultInstance()); + continue; + } + AbiCapsule abiCapsule = StoreFactory.getInstance().getChainBaseManager() + .getAbiStore().get(contractAddress); + SmartContractOuterClass.SmartContract.ABI abi; + if (abiCapsule == null || abiCapsule.getInstance() == null) { + abi = SmartContractOuterClass.SmartContract.ABI.getDefaultInstance(); + } else { + abi = abiCapsule.getInstance(); + } + String creatorAddr = StringUtil.encode58Check(TransactionTrace + .convertToTronAddress(contract.getInstance().getOriginAddress().toByteArray())); + addrMap.put(strContractAddr, creatorAddr); + abiMap.put(strContractAddr, abi); + } + + int index = 1; + for (Protocol.TransactionInfo.Log log : logs) { + + byte[] contractAddress = TransactionTrace + .convertToTronAddress(log.getAddress().toByteArray()); + String strContractAddress = + ArrayUtils.isEmpty(contractAddress) ? "" : StringUtil.encode58Check(contractAddress); + SmartContractOuterClass.SmartContract.ABI abi = abiMap.get(strContractAddress); + ContractTrigger event = new ContractTrigger(); + String creatorAddr = addrMap.get(strContractAddress); + String txId = Hex.toHexString(txInfo.getId().toByteArray()); + event.setUniqueId(txId + "_" + index); + event.setTransactionId(txId); + event.setContractAddress(strContractAddress); + event.setOriginAddress(originAddress); + event.setCallerAddress(""); + event.setCreatorAddress(StringUtils.isEmpty(creatorAddr) ? "" : creatorAddr); + event.setBlockNumber(txInfo.getBlockNumber()); + event.setTimeStamp(txInfo.getBlockTimeStamp()); + event.setLogInfo(buildLogInfo(log)); + event.setAbi(abi); + + list.add(event); + index++; + } + + return list; + } + + private LogInfo buildLogInfo(Protocol.TransactionInfo.Log log) { + List topics = Lists.newArrayList(); + log.getTopicsList().forEach(topic -> + topics.add(new DataWord(topic.toByteArray())) + ); + byte[] address = log.getAddress().toByteArray(); + byte[] data = log.getData().toByteArray(); + return new LogInfo(address, topics, data); + } + + private ContractTrigger processTrigger(ContractTrigger contractTrigger) { + ContractTrigger event; + boolean isEvent = false; + LogInfo logInfo = contractTrigger.getLogInfo(); + SmartContractOuterClass.SmartContract.ABI abi = contractTrigger.getAbi(); + List topics = logInfo.getTopics(); + + String eventSignature = ""; + String eventSignatureFull = "fallback()"; + String entryName = ""; + SmartContractOuterClass.SmartContract.ABI.Entry eventEntry = null; + + if (abi != null && abi.getEntrysCount() > 0 && topics != null && !topics.isEmpty() + && !ArrayUtils.isEmpty(topics.get(0).getData()) + && Args.getInstance().getStorage().isContractParseSwitch()) { + String logHash = topics.get(0).toString(); + + for (SmartContractOuterClass.SmartContract.ABI.Entry entry : abi.getEntrysList()) { + if (entry.getType() != SmartContractOuterClass.SmartContract.ABI.Entry.EntryType.Event + || entry.getAnonymous()) { + continue; + } + + String signature = entry.getName() + "("; + String signatureFull = entry.getName() + "("; + StringBuilder signBuilder = new StringBuilder(); + StringBuilder signFullBuilder = new StringBuilder(); + for (SmartContractOuterClass.SmartContract.ABI.Entry.Param param : entry.getInputsList()) { + if (signBuilder.length() > 0) { + signBuilder.append(","); + signFullBuilder.append(","); + } + String type = param.getType(); + String name = param.getName(); + signBuilder.append(type); + signFullBuilder.append(type); + if (org.pf4j.util.StringUtils.isNotNullOrEmpty(name)) { + signFullBuilder.append(" ").append(name); + } + } + signature += signBuilder + ")"; + signatureFull += signFullBuilder + ")"; + String sha3 = Hex.toHexString(Hash.sha3(signature.getBytes())); + if (sha3.equals(logHash)) { + eventSignature = signature; + eventSignatureFull = signatureFull; + entryName = entry.getName(); + eventEntry = entry; + isEvent = true; + break; + } + } + } + + if (isEvent) { + event = new ContractEventTrigger(); + ((ContractEventTrigger) event).setEventSignature(eventSignature); + ((ContractEventTrigger) event).setEventSignatureFull(eventSignatureFull); + ((ContractEventTrigger) event).setEventName(entryName); + + List topicList = logInfo.getClonedTopics(); + byte[] data = logInfo.getClonedData(); + + ((ContractEventTrigger) event) + .setTopicMap(ContractEventParserAbi.parseTopics(topicList, eventEntry)); + ((ContractEventTrigger) event) + .setDataMap(ContractEventParserAbi.parseEventData(data, topicList, eventEntry)); + } else { + event = new ContractLogTrigger(); + ((ContractLogTrigger) event).setTopicList(logInfo.getHexTopics()); + ((ContractLogTrigger) event).setData(logInfo.getHexData()); + } + + RawData rawData = new RawData(logInfo.getAddress(), logInfo.getTopics(), logInfo.getData()); + + event.setRawData(rawData); + + event.setLatestSolidifiedBlockNumber(contractTrigger.getLatestSolidifiedBlockNumber()); + event.setRemoved(contractTrigger.isRemoved()); + event.setUniqueId(contractTrigger.getUniqueId()); + event.setTransactionId(contractTrigger.getTransactionId()); + event.setContractAddress(contractTrigger.getContractAddress()); + event.setOriginAddress(contractTrigger.getOriginAddress()); + event.setCallerAddress(""); + event.setCreatorAddress(contractTrigger.getCreatorAddress()); + event.setBlockNumber(contractTrigger.getBlockNumber()); + event.setTimeStamp(contractTrigger.getTimeStamp()); + event.setBlockHash(contractTrigger.getBlockHash()); + + return event; + } + + public BlockLogTriggerCapsule getBlockLogTrigger(BlockCapsule block, long solidNum) { + BlockLogTriggerCapsule blockLogTriggerCapsule = new BlockLogTriggerCapsule(block); + blockLogTriggerCapsule.setLatestSolidifiedBlockNumber(solidNum); + return blockLogTriggerCapsule; + } + + public List getTransactionLogTrigger(BlockCapsule block, + long solidNum) { + List transactionLogTriggerCapsules = new ArrayList<>(); + if (!EventPluginLoader.getInstance().isTransactionLogTriggerEthCompatible()) { + for (TransactionCapsule t : block.getTransactions()) { + TransactionLogTriggerCapsule trx = new TransactionLogTriggerCapsule(t, block); + trx.setLatestSolidifiedBlockNumber(solidNum); + transactionLogTriggerCapsules.add(trx); + } + return transactionLogTriggerCapsules; + } + List transactionCapsuleList = block.getTransactions(); + GrpcAPI.TransactionInfoList transactionInfoList = GrpcAPI + .TransactionInfoList.newBuilder().build(); + GrpcAPI.TransactionInfoList.Builder transactionInfoListBuilder = GrpcAPI + .TransactionInfoList.newBuilder(); + try { + TransactionRetCapsule result = manager.getChainBaseManager().getTransactionRetStore() + .getTransactionInfoByBlockNum(ByteArray.fromLong(block.getNum())); + if (!Objects.isNull(result) && !Objects.isNull(result.getInstance())) { + result.getInstance().getTransactioninfoList() + .forEach(transactionInfoListBuilder::addTransactionInfo); + transactionInfoList = transactionInfoListBuilder.build(); + } + } catch (BadItemException e) { + logger.error("Get TransactionInfo failed, blockNum {}, {}.", block.getNum(), e.getMessage()); + } + if (transactionCapsuleList.size() != transactionInfoList.getTransactionInfoCount()) { + logger.error("Get TransactionInfo size not eq, blockNum {}, {}, {}", + block.getNum(), transactionCapsuleList.size(), + transactionInfoList.getTransactionInfoCount()); + for (TransactionCapsule t : block.getTransactions()) { + TransactionLogTriggerCapsule trx = new TransactionLogTriggerCapsule(t, block); + trx.setLatestSolidifiedBlockNumber(solidNum); + transactionLogTriggerCapsules.add(trx); + } + return transactionLogTriggerCapsules; + } + long cumulativeEnergyUsed = 0; + long cumulativeLogCount = 0; + long energyUnitPrice = getEnergyPrice(block.getTimeStamp()); + for (int i = 0; i < transactionCapsuleList.size(); i++) { + Protocol.TransactionInfo transactionInfo = transactionInfoList.getTransactionInfo(i); + TransactionCapsule transactionCapsule = transactionCapsuleList.get(i); + transactionCapsule.setBlockNum(block.getNum()); + TransactionLogTriggerCapsule trx = new TransactionLogTriggerCapsule(transactionCapsule, block, + i, cumulativeEnergyUsed, cumulativeLogCount, transactionInfo, energyUnitPrice); + trx.setLatestSolidifiedBlockNumber(solidNum); + cumulativeEnergyUsed += trx.getTransactionLogTrigger().getEnergyUsageTotal(); + cumulativeLogCount += transactionInfo.getLogCount(); + transactionLogTriggerCapsules.add(trx); + } + return transactionLogTriggerCapsules; + } + + public long getEnergyPrice(long blockTime) { + String energyPriceHistory = manager.getDynamicPropertiesStore().getEnergyPriceHistory(); + + String[] energyPrices = energyPriceHistory.split(","); + String[] lastPrice = energyPrices[energyPrices.length - 1].split(":"); + long energyPrice = Long.parseLong(lastPrice[1]); + + for (int i = 1; i < energyPrices.length; i++) { + long effectiveTime = Long.parseLong(energyPrices[i].split(":")[0]); + if (blockTime < effectiveTime) { + energyPrice = Long.parseLong(energyPrices[i - 1].split(":")[1]); + break; + } + } + return energyPrice; + } +} \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java b/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java new file mode 100644 index 00000000000..1af9d768c19 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java @@ -0,0 +1,86 @@ +package org.tron.core.services.event; + +import com.google.common.collect.Lists; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.tron.common.es.ExecutorServiceManager; +import org.tron.core.db.Manager; +import org.tron.core.services.event.bo.BlockEvent; +import org.tron.core.services.event.bo.Event; + +@Service +@Slf4j(topic = "event") +public class BlockEventLoad { + + @Autowired + private Manager manager; + + @Autowired + private RealtimeEventService realtimeEventService; + + @Autowired + private BlockEventGet blockEventGet; + + private final ScheduledExecutorService executor = ExecutorServiceManager + .newSingleThreadScheduledExecutor("event-load"); + + public void init() { + executor.scheduleWithFixedDelay(() -> { + try { + load(); + } catch (Exception exception) { + close(); + logger.error("Spread thread error", exception); + } + }, 100, 100, TimeUnit.MILLISECONDS); + logger.info("Event load service start."); + } + + public void close() { + executor.shutdown(); + logger.info("Event load service close."); + } + + public void load() throws Exception { + long cacheHeadNum = BlockEventCache.getHead().getBlockId().getNum(); + long tmpNum = manager.getDynamicPropertiesStore().getLatestBlockHeaderNumber(); + if (cacheHeadNum >= tmpNum) { + return; + } + synchronized (manager) { + tmpNum = manager.getDynamicPropertiesStore().getLatestBlockHeaderNumber(); + if (cacheHeadNum >= tmpNum) { + return; + } + List l1 = new ArrayList<>(); + List l2 = new ArrayList<>(); + BlockEvent tmp = BlockEventCache.getHead(); + + BlockEvent blockEvent = blockEventGet.getBlockEvent(tmpNum); + l1.add(blockEvent); + while (!blockEvent.getParentId().equals(tmp.getBlockId())) { + tmpNum--; + if (tmpNum == tmp.getBlockId().getNum()) { + l2.add(tmp); + tmp = BlockEventCache.getBlockEvent(tmp.getParentId()); + } + blockEvent = blockEventGet.getBlockEvent(tmpNum); + l1.add(blockEvent); + } + + l2.forEach(e -> realtimeEventService.add(new Event(e, true))); + + List l = Lists.reverse(l1); + for (BlockEvent e: l) { + BlockEventCache.add(e); + realtimeEventService.add(new Event(e, false)); + } + } + } + +} diff --git a/framework/src/main/java/org/tron/core/services/event/EventService.java b/framework/src/main/java/org/tron/core/services/event/EventService.java new file mode 100644 index 00000000000..b2e01ab3a9d --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/event/EventService.java @@ -0,0 +1,61 @@ +package org.tron.core.services.event; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.logsfilter.EventPluginLoader; +import org.tron.core.db.Manager; + +@Slf4j(topic = "event") +@Component +public class EventService { + @Autowired + private RealtimeEventService realtimeEventService; + + @Autowired + private BlockEventLoad blockEventLoad; + + @Autowired + private HistoryEventService historyEventService; + + @Autowired + private Manager manager; + + public void init() { + logger.info("Start to load eventPlugin. {}, {}, {} " + + "block: {}, {} trx: {}, {}, {} event: {}, {} log: {}, {}, {}, {} solid: {}", + manager.isEventPluginLoaded(), + + EventPluginLoader.getInstance().getVersion(), + EventPluginLoader.getInstance().getStartSyncBlockNum(), + + EventPluginLoader.getInstance().isBlockLogTriggerEnable(), + EventPluginLoader.getInstance().isBlockLogTriggerSolidified(), + + EventPluginLoader.getInstance().isTransactionLogTriggerEnable(), + EventPluginLoader.getInstance().isTransactionLogTriggerSolidified(), + EventPluginLoader.getInstance().isTransactionLogTriggerEthCompatible(), + + EventPluginLoader.getInstance().isContractEventTriggerEnable(), + EventPluginLoader.getInstance().isSolidityEventTriggerEnable(), + + EventPluginLoader.getInstance().isContractLogTriggerEnable(), + EventPluginLoader.getInstance().isContractLogTriggerRedundancy(), + EventPluginLoader.getInstance().isSolidityLogTriggerEnable(), + EventPluginLoader.getInstance().isSolidityLogTriggerRedundancy(), + + EventPluginLoader.getInstance().isSolidityTriggerEnable()); + + if (!manager.isEventPluginLoaded() || EventPluginLoader.getInstance().getVersion() != 1) { + return; + } + + historyEventService.init(); + } + + public void close() { + realtimeEventService.close(); + blockEventLoad.close(); + historyEventService.close(); + } +} diff --git a/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java b/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java new file mode 100644 index 00000000000..0f26490d16b --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java @@ -0,0 +1,76 @@ +package org.tron.core.services.event; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.logsfilter.EventPluginLoader; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.db.Manager; +import org.tron.core.services.event.bo.BlockEvent; + +@Slf4j(topic = "event") +@Component +public class HistoryEventService { + + private EventPluginLoader instance = EventPluginLoader.getInstance(); + + @Autowired + private BlockEventGet blockEventGet; + + @Autowired + private SolidEventService solidEventService; + + @Autowired + private RealtimeEventService realtimeEventService; + + @Autowired + private BlockEventLoad blockEventLoad; + + @Autowired + private Manager manager; + + private volatile boolean isRunning; + + public void init() { + if (instance.getStartSyncBlockNum() <= 0) { + initEventService(manager.getChainBaseManager().getHeadBlockId()); + return; + } + + isRunning = true; + + new Thread(() -> syncEvent()).start(); + + logger.info("History event service start."); + } + + public void close() { + isRunning = false; + } + + private void syncEvent() { + try { + long tmp = instance.getStartSyncBlockNum(); + long endNum = manager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); + while (tmp <= endNum && isRunning) { + BlockEvent blockEvent = blockEventGet.getBlockEvent(tmp); + realtimeEventService.flush(blockEvent, false); + solidEventService.flush(blockEvent); + tmp++; + endNum = manager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); + Thread.sleep(30); + } + initEventService(manager.getChainBaseManager().getBlockIdByNum(endNum)); + } catch (Exception e) { + logger.error("Sync event failed.", e); + } + } + + private void initEventService(BlockCapsule.BlockId blockId) { + logger.info("Init event service, {}", blockId.getString()); + BlockEventCache.init(blockId); + realtimeEventService.init(); + blockEventLoad.init(); + solidEventService.init(); + } +} diff --git a/framework/src/main/java/org/tron/core/services/event/RealtimeEventService.java b/framework/src/main/java/org/tron/core/services/event/RealtimeEventService.java new file mode 100644 index 00000000000..8375b2fd114 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/event/RealtimeEventService.java @@ -0,0 +1,120 @@ +package org.tron.core.services.event; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.es.ExecutorServiceManager; +import org.tron.common.logsfilter.EventPluginLoader; +import org.tron.common.logsfilter.trigger.Trigger; +import org.tron.core.db.Manager; +import org.tron.core.services.event.bo.BlockEvent; +import org.tron.core.services.event.bo.Event; + +@Slf4j(topic = "event") +@Component +public class RealtimeEventService { + + private EventPluginLoader instance = EventPluginLoader.getInstance(); + + @Autowired + private Manager manager; + + @Autowired + private SolidEventService solidEventService; + + private static BlockingQueue queue = new LinkedBlockingQueue<>(); + + private int maxEventSize = 10000; + + private final ScheduledExecutorService executor = ExecutorServiceManager + .newSingleThreadScheduledExecutor("realtime-event"); + + public void init() { + executor.scheduleWithFixedDelay(() -> { + try { + work(); + } catch (Exception e) { + logger.info("Real-time event service fail. {}", e); + } + }, 1, 1, TimeUnit.SECONDS); + logger.info("Realtime event service start."); + } + + public void close() { + executor.shutdown(); + logger.info("Realtime event service close."); + } + + public void add(Event event) { + if (queue.size() >= maxEventSize) { + logger.warn("Add event failed, blockId {}.", event.getBlockEvent().getBlockId().getString()); + return; + } + queue.offer(event); + } + + public void work() { + while (queue.size() > 0) { + Event event = queue.poll(); + flush(event.getBlockEvent(), event.isRemove()); + } + } + + public void flush(BlockEvent blockEvent, boolean isRemove) { + logger.info("Flush realtime event {}", blockEvent.getBlockId().getString()); + + if (instance.isBlockLogTriggerEnable() + && !instance.isBlockLogTriggerSolidified() + && !isRemove) { + if (blockEvent.getBlockLogTriggerCapsule() == null) { + logger.warn("BlockLogTriggerCapsule is null. {}", blockEvent.getBlockId().getString()); + } else { + manager.getTriggerCapsuleQueue().offer(blockEvent.getBlockLogTriggerCapsule()); + } + } + + if (instance.isTransactionLogTriggerEnable() + && !instance.isTransactionLogTriggerSolidified() + && !isRemove) { + if (blockEvent.getTransactionLogTriggerCapsules() == null) { + logger.info("TransactionLogTriggerCapsules is null. {}", + blockEvent.getBlockId().getString()); + } else { + blockEvent.getTransactionLogTriggerCapsules().forEach(v -> + manager.getTriggerCapsuleQueue().offer(v)); + } + } + + if (instance.isContractEventTriggerEnable()) { + if (blockEvent.getSmartContractTrigger() == null) { + logger.info("SmartContractTrigger is null. {}", blockEvent.getBlockId().getString()); + } else { + blockEvent.getSmartContractTrigger().getContractEventTriggers().forEach(v -> { + v.setTriggerName(Trigger.CONTRACTEVENT_TRIGGER_NAME); + v.setRemoved(isRemove); + EventPluginLoader.getInstance().postContractEventTrigger(v); + }); + } + } + + if (instance.isContractLogTriggerEnable() && blockEvent.getSmartContractTrigger() != null) { + blockEvent.getSmartContractTrigger().getContractLogTriggers().forEach(v -> { + v.setTriggerName(Trigger.CONTRACTLOG_TRIGGER_NAME); + v.setRemoved(isRemove); + EventPluginLoader.getInstance().postContractLogTrigger(v); + }); + if (instance.isContractLogTriggerRedundancy()) { + blockEvent.getSmartContractTrigger().getRedundancies().forEach(v -> { + v.setTriggerName(Trigger.CONTRACTLOG_TRIGGER_NAME); + v.setRemoved(isRemove); + EventPluginLoader.getInstance().postContractLogTrigger(v); + }); + } + } + } + +} diff --git a/framework/src/main/java/org/tron/core/services/event/SolidEventService.java b/framework/src/main/java/org/tron/core/services/event/SolidEventService.java new file mode 100644 index 00000000000..5bf83ea0da9 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/event/SolidEventService.java @@ -0,0 +1,110 @@ +package org.tron.core.services.event; + +import java.util.List; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.es.ExecutorServiceManager; +import org.tron.common.logsfilter.EventPluginLoader; +import org.tron.common.logsfilter.trigger.Trigger; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.db.Manager; +import org.tron.core.services.event.bo.BlockEvent; + +@Slf4j(topic = "event") +@Component +public class SolidEventService { + + private EventPluginLoader instance = EventPluginLoader.getInstance(); + + @Autowired + private Manager manager; + + private final ScheduledExecutorService executor = ExecutorServiceManager + .newSingleThreadScheduledExecutor("solid-event"); + + public void init() { + executor.scheduleWithFixedDelay(() -> { + try { + work(); + } catch (Exception exception) { + logger.error("Spread thread error", exception); + } + }, 1, 1, TimeUnit.SECONDS); + logger.info("Solid event service start."); + } + + public void close() { + executor.shutdown(); + logger.info("Solid event service close."); + } + + public void work() { + BlockCapsule.BlockId solidId = BlockEventCache.getSolidId(); + if (solidId.getNum() <= BlockEventCache.getSolidNum()) { + return; + } + + List blockEvents = BlockEventCache.getSolidBlockEvents(solidId); + + blockEvents.forEach(v -> flush(v)); + + BlockEventCache.remove(solidId); + } + + public void flush(BlockEvent blockEvent) { + logger.info("Flush solid event {}", blockEvent.getBlockId().getString()); + + if (instance.isBlockLogTriggerEnable() && instance.isBlockLogTriggerSolidified()) { + if (blockEvent.getBlockLogTriggerCapsule() == null) { + logger.warn("BlockLogTrigger is null. {}", blockEvent.getBlockId()); + } else { + manager.getTriggerCapsuleQueue().offer(blockEvent.getBlockLogTriggerCapsule()); + } + } + + if (instance.isTransactionLogTriggerEnable() && instance.isTransactionLogTriggerSolidified()) { + if (blockEvent.getTransactionLogTriggerCapsules() == null) { + logger.info("TransactionLogTrigger is null. {}", blockEvent.getBlockId()); + } else { + blockEvent.getTransactionLogTriggerCapsules().forEach(v -> + manager.getTriggerCapsuleQueue().offer(v)); + } + } + + if (instance.isSolidityEventTriggerEnable()) { + if (blockEvent.getSmartContractTrigger() == null) { + logger.info("SmartContractTrigger is null. {}", blockEvent.getBlockId()); + } else { + blockEvent.getSmartContractTrigger().getContractEventTriggers().forEach(v -> { + v.setTriggerName(Trigger.SOLIDITYEVENT_TRIGGER_NAME); + EventPluginLoader.getInstance().postSolidityEventTrigger(v); + }); + } + } + + if (instance.isSolidityLogTriggerEnable() && blockEvent.getSmartContractTrigger() != null) { + blockEvent.getSmartContractTrigger().getContractLogTriggers().forEach(v -> { + v.setTriggerName(Trigger.SOLIDITYLOG_TRIGGER_NAME); + EventPluginLoader.getInstance().postSolidityLogTrigger(v); + }); + if (instance.isSolidityLogTriggerRedundancy()) { + blockEvent.getSmartContractTrigger().getRedundancies().forEach(v -> { + v.setTriggerName(Trigger.SOLIDITYLOG_TRIGGER_NAME); + EventPluginLoader.getInstance().postSolidityLogTrigger(v); + }); + } + } + + if (instance.isSolidityTriggerEnable()) { + if (blockEvent.getSolidityTriggerCapsule() == null) { + logger.info("SolidityTrigger is null. {}", blockEvent.getBlockId()); + } else { + manager.getTriggerCapsuleQueue().offer(blockEvent.getSolidityTriggerCapsule()); + } + } + } + +} diff --git a/framework/src/main/java/org/tron/core/services/event/bo/BlockEvent.java b/framework/src/main/java/org/tron/core/services/event/bo/BlockEvent.java new file mode 100644 index 00000000000..9e314bc7d5a --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/event/bo/BlockEvent.java @@ -0,0 +1,28 @@ +package org.tron.core.services.event.bo; + +import java.util.List; +import lombok.Data; +import org.tron.common.logsfilter.capsule.BlockLogTriggerCapsule; +import org.tron.common.logsfilter.capsule.SolidityTriggerCapsule; +import org.tron.common.logsfilter.capsule.TransactionLogTriggerCapsule; +import org.tron.core.capsule.BlockCapsule; + +@Data +public class BlockEvent { + private BlockCapsule.BlockId blockId; + private BlockCapsule.BlockId parentId; + private BlockCapsule.BlockId solidId; + private long blockTime; + + private BlockLogTriggerCapsule blockLogTriggerCapsule; + private List transactionLogTriggerCapsules; + private SolidityTriggerCapsule solidityTriggerCapsule; + private SmartContractTrigger smartContractTrigger; + + public BlockEvent() {} + + public BlockEvent(BlockCapsule.BlockId blockId) { + this.blockId = blockId; + } +} + diff --git a/framework/src/main/java/org/tron/core/services/event/bo/Event.java b/framework/src/main/java/org/tron/core/services/event/bo/Event.java new file mode 100644 index 00000000000..142e1be3c22 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/event/bo/Event.java @@ -0,0 +1,14 @@ +package org.tron.core.services.event.bo; + +import lombok.Data; + +@Data +public class Event { + private boolean isRemove; + private BlockEvent blockEvent; + + public Event(BlockEvent blockEvent, boolean isRemove) { + this.blockEvent = blockEvent; + this.isRemove = isRemove; + } +} diff --git a/framework/src/main/java/org/tron/core/services/event/bo/SmartContractTrigger.java b/framework/src/main/java/org/tron/core/services/event/bo/SmartContractTrigger.java new file mode 100644 index 00000000000..7413c309169 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/event/bo/SmartContractTrigger.java @@ -0,0 +1,14 @@ +package org.tron.core.services.event.bo; + +import java.util.ArrayList; +import java.util.List; +import lombok.Data; +import org.tron.common.logsfilter.trigger.ContractEventTrigger; +import org.tron.common.logsfilter.trigger.ContractLogTrigger; + +@Data +public class SmartContractTrigger { + private List contractLogTriggers = new ArrayList<>(); + private List contractEventTriggers = new ArrayList<>(); + private List redundancies = new ArrayList<>(); +} diff --git a/framework/src/main/java/org/tron/core/services/event/exception/EventException.java b/framework/src/main/java/org/tron/core/services/event/exception/EventException.java new file mode 100644 index 00000000000..09df1d832f4 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/event/exception/EventException.java @@ -0,0 +1,7 @@ +package org.tron.core.services.event.exception; + +public class EventException extends Exception { + public EventException(String errMsg) { + super(errMsg); + } +} diff --git a/framework/src/test/java/org/tron/core/event/BlockEventCacheTest.java b/framework/src/test/java/org/tron/core/event/BlockEventCacheTest.java new file mode 100644 index 00000000000..a23c4b5c9c8 --- /dev/null +++ b/framework/src/test/java/org/tron/core/event/BlockEventCacheTest.java @@ -0,0 +1,90 @@ +package org.tron.core.event; + +import java.util.List; +import java.util.Random; +import org.junit.Assert; +import org.junit.Test; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.services.event.BlockEventCache; +import org.tron.core.services.event.bo.BlockEvent; +import org.tron.core.services.event.exception.EventException; + +public class BlockEventCacheTest { + + @Test + public void test() throws Exception { + BlockEvent be1 = new BlockEvent(); + BlockCapsule.BlockId b1 = new BlockCapsule.BlockId(getBlockId(), 1); + be1.setBlockId(b1); + be1.setParentId(b1); + try { + BlockEventCache.add(be1); + Assert.fail(); + } catch (Exception e) { + Assert.assertTrue(e instanceof EventException); + } + + BlockEventCache.init(new BlockCapsule.BlockId(getBlockId(), 100)); + + try { + BlockEventCache.add(be1); + Assert.fail(); + } catch (Exception e) { + Assert.assertTrue(e instanceof EventException); + } + + BlockEventCache.init(b1); + + BlockEvent be2 = new BlockEvent(); + BlockCapsule.BlockId b2 = new BlockCapsule.BlockId(getBlockId(), 2); + be2.setBlockId(b2); + be2.setParentId(b1); + be2.setSolidId(b1); + BlockEventCache.add(be2); + Assert.assertEquals(be2, BlockEventCache.getHead()); + Assert.assertEquals(be2, BlockEventCache.getBlockEvent(b2)); + + BlockEvent be22 = new BlockEvent(); + BlockCapsule.BlockId b22 = new BlockCapsule.BlockId(getBlockId(), 2); + be22.setBlockId(b22); + be22.setParentId(b1); + be22.setSolidId(b22); + BlockEventCache.add(be22); + Assert.assertEquals(be2, BlockEventCache.getHead()); + Assert.assertEquals(be22, BlockEventCache.getBlockEvent(b22)); + Assert.assertEquals(b22, BlockEventCache.getSolidId()); + + BlockEvent be3 = new BlockEvent(); + BlockCapsule.BlockId b3 = new BlockCapsule.BlockId(getBlockId(), 3); + be3.setBlockId(b3); + be3.setParentId(b22); + be3.setSolidId(b22); + BlockEventCache.add(be3); + Assert.assertEquals(be3, BlockEventCache.getHead()); + + List list = BlockEventCache.getSolidBlockEvents(b2); + Assert.assertEquals(1, list.size()); + list = BlockEventCache.getSolidBlockEvents(b22); + Assert.assertEquals(1, list.size()); + + list = BlockEventCache.getSolidBlockEvents(b3); + Assert.assertEquals(2, list.size()); + + BlockEventCache.remove(b22); + Assert.assertEquals(2, BlockEventCache.getSolidNum()); + + list = BlockEventCache.getSolidBlockEvents(b2); + Assert.assertEquals(0, list.size()); + list = BlockEventCache.getSolidBlockEvents(b22); + Assert.assertEquals(0, list.size()); + + list = BlockEventCache.getSolidBlockEvents(b3); + Assert.assertEquals(1, list.size()); + } + + public static byte[] getBlockId() { + byte[] id = new byte[32]; + new Random().nextBytes(id); + return id; + } +} diff --git a/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java b/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java new file mode 100644 index 00000000000..db959d9a0fd --- /dev/null +++ b/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java @@ -0,0 +1,185 @@ +package org.tron.core.event; + +import com.google.protobuf.ByteString; +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.concurrent.atomic.AtomicInteger; +import lombok.extern.slf4j.Slf4j; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.logsfilter.EventPluginConfig; +import org.tron.common.logsfilter.EventPluginLoader; +import org.tron.common.logsfilter.TriggerConfig; +import org.tron.common.runtime.TvmTestUtils; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.PublicMethod; +import org.tron.core.ChainBaseManager; +import org.tron.core.Constant; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.WitnessCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.consensus.ConsensusService; +import org.tron.core.db.BlockGenerate; +import org.tron.core.db.Manager; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.services.event.BlockEventGet; +import org.tron.core.services.event.bo.BlockEvent; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.Protocol; + +@Slf4j +public class BlockEventGetTest extends BlockGenerate { + + @ClassRule + public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); + + static ChainBaseManager chainManager; + + private final String key = PublicMethod.getRandomPrivateKey(); + private final byte[] privateKey = ByteArray.fromHexString(key); + private final byte[] address = PublicMethod.getAddressByteByPrivateKey(key); + + private final AtomicInteger port = new AtomicInteger(0); + protected String dbPath; + protected Manager dbManager; + long currentHeader = -1; + private TronNetDelegate tronNetDelegate; + private TronApplicationContext context; + + + static LocalDateTime localDateTime = LocalDateTime.now(); + private long time = ZonedDateTime.of(localDateTime, + ZoneId.systemDefault()).toInstant().toEpochMilli(); + + protected void initDbPath() throws IOException { + dbPath = temporaryFolder.newFolder().toString(); + } + + @Before + public void before() throws IOException { + initDbPath(); + logger.info("Full node running."); + Args.setParam(new String[] {"-d", dbPath, "-w"}, Constant.TEST_CONF); + Args.getInstance().setNodeListenPort(10000 + port.incrementAndGet()); + + context = new TronApplicationContext(DefaultConfig.class); + + dbManager = context.getBean(Manager.class); + setManager(dbManager); + + context.getBean(ConsensusService.class).start(); + chainManager = dbManager.getChainBaseManager(); + tronNetDelegate = context.getBean(TronNetDelegate.class); + tronNetDelegate.setExit(false); + currentHeader = dbManager.getDynamicPropertiesStore() + .getLatestBlockHeaderNumberFromDB(); + + ByteString addressBS = ByteString.copyFrom(address); + WitnessCapsule witnessCapsule = new WitnessCapsule(addressBS); + chainManager.getWitnessStore().put(address, witnessCapsule); + chainManager.addWitness(addressBS); + + AccountCapsule accountCapsule = new AccountCapsule(Protocol.Account.newBuilder() + .setAddress(addressBS).setBalance((long) 1e10).build()); + chainManager.getAccountStore().put(address, accountCapsule); + + DynamicPropertiesStore dps = dbManager.getDynamicPropertiesStore(); + dps.saveAllowTvmTransferTrc10(1); + dps.saveAllowTvmConstantinople(1); + dps.saveAllowTvmShangHai(1); + } + + @After + public void after() throws IOException { + } + + @Test + public void test() throws Exception { + BlockEventGet blockEventGet = context.getBean(BlockEventGet.class); + Manager manager = context.getBean(Manager.class); + + WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address)); + ChainBaseManager.getChainBaseManager() + .getWitnessScheduleStore().saveActiveWitnesses(new ArrayList<>()); + ChainBaseManager.getChainBaseManager().addWitness(ByteString.copyFrom(address)); + + String code = "608060405234801561000f575f80fd5b50d3801561001b575f80fd5b50d28015610027575f" + + "80fd5b503373ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffff" + + "ffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3" + + "ef6402540be40060405161008a91906100e2565b60405180910390a36100fb565b5f81905091905056" + + "5b5f819050919050565b5f819050919050565b5f6100cc6100c76100c284610097565b6100a9565b61" + + "00a0565b9050919050565b6100dc816100b2565b82525050565b5f6020820190506100f55f83018461" + + "00d3565b92915050565b603e806101075f395ff3fe60806040525f80fdfea26474726f6e582212200c" + + "57c973388f044038eff0e6474425b38037e75e66d6b3047647290605449c7764736f6c63430008140033"; + Protocol.Transaction trx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( + "TestTRC20", address, "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\"" + + ":\"from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"to\",\"type\":\"address\"}" + + ",{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\"," + + "\"type\":\"event\"}]", code, 0, (long) 1e9, 100, null, 1); + trx = trx.toBuilder().addRet( + Protocol.Transaction.Result.newBuilder() + .setContractRetValue(Protocol.Transaction.Result.contractResult.SUCCESS_VALUE) + .build()).build(); + + Protocol.Block block = getSignedBlock(witnessCapsule.getAddress(), time, privateKey); + BlockCapsule blockCapsule = new BlockCapsule(block.toBuilder().addTransactions(trx).build()); + blockCapsule.generatedByMyself = true; + blockCapsule.getTransactions().forEach(txCap -> { + txCap.setVerified(true); + chainManager.setBlockReference(txCap); + txCap.setExpiration(3000); + }); + manager.pushBlock(blockCapsule); + + EventPluginConfig config = new EventPluginConfig(); + config.setSendQueueLength(1000); + config.setBindPort(5555); + config.setUseNativeQueue(true); + config.setTriggerConfigList(new ArrayList<>()); + + TriggerConfig blockTriggerConfig = new TriggerConfig(); + blockTriggerConfig.setTriggerName("block"); + blockTriggerConfig.setEnabled(true); + config.getTriggerConfigList().add(blockTriggerConfig); + + TriggerConfig txTriggerConfig = new TriggerConfig(); + txTriggerConfig.setTriggerName("transaction"); + txTriggerConfig.setEnabled(true); + txTriggerConfig.setEthCompatible(true); + config.getTriggerConfigList().add(txTriggerConfig); + + TriggerConfig solidityTriggerConfig = new TriggerConfig(); + solidityTriggerConfig.setTriggerName("solidity"); + solidityTriggerConfig.setEnabled(true); + config.getTriggerConfigList().add(solidityTriggerConfig); + + TriggerConfig contracteventTriggerConfig = new TriggerConfig(); + contracteventTriggerConfig.setTriggerName("contractevent"); + contracteventTriggerConfig.setEnabled(true); + config.getTriggerConfigList().add(contracteventTriggerConfig); + + TriggerConfig contractlogTriggerConfig = new TriggerConfig(); + contractlogTriggerConfig.setTriggerName("contractlog"); + contractlogTriggerConfig.setEnabled(true); + contractlogTriggerConfig.setRedundancy(true); + config.getTriggerConfigList().add(contractlogTriggerConfig); + + EventPluginLoader.getInstance().start(config); + try { + BlockEvent blockEvent = blockEventGet.getBlockEvent(1); + Assert.assertNotNull(blockEvent); + } catch (Exception e) { + Assert.fail(); + } + } +} \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/event/BlockEventLoadTest.java b/framework/src/test/java/org/tron/core/event/BlockEventLoadTest.java new file mode 100644 index 00000000000..991133fee78 --- /dev/null +++ b/framework/src/test/java/org/tron/core/event/BlockEventLoadTest.java @@ -0,0 +1,124 @@ +package org.tron.core.event; + +import static org.mockito.Mockito.mock; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.concurrent.BlockingQueue; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; +import org.tron.common.utils.ReflectUtils; +import org.tron.core.ChainBaseManager; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.db.Manager; +import org.tron.core.services.event.BlockEventCache; +import org.tron.core.services.event.BlockEventGet; +import org.tron.core.services.event.BlockEventLoad; +import org.tron.core.services.event.RealtimeEventService; +import org.tron.core.services.event.bo.BlockEvent; +import org.tron.core.services.event.bo.Event; +import org.tron.core.store.DynamicPropertiesStore; + +public class BlockEventLoadTest { + BlockEventLoad blockEventLoad = new BlockEventLoad(); + + @Test + public void test() throws Exception { + Method method = blockEventLoad.getClass().getDeclaredMethod("load"); + method.setAccessible(true); + + RealtimeEventService realtimeEventService = new RealtimeEventService(); + Field field = realtimeEventService.getClass().getDeclaredField("queue"); + field.setAccessible(true); + BlockingQueue queue = (BlockingQueue)field.get(BlockingQueue.class); + + BlockEventGet blockEventGet = mock(BlockEventGet.class); + Manager manager = mock(Manager.class); + ReflectUtils.setFieldValue(blockEventLoad, "realtimeEventService", realtimeEventService); + ReflectUtils.setFieldValue(blockEventLoad, "blockEventGet", blockEventGet); + ReflectUtils.setFieldValue(blockEventLoad, "manager", manager); + + DynamicPropertiesStore dynamicPropertiesStore = mock(DynamicPropertiesStore.class); + ChainBaseManager chainBaseManager = mock(ChainBaseManager.class); + Mockito.when(manager.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStore); + Mockito.when(manager.getChainBaseManager()).thenReturn(chainBaseManager); + + BlockCapsule.BlockId b0 = new BlockCapsule.BlockId(BlockEventCacheTest.getBlockId(), 0); + BlockEventCache.init(b0); + + /********** 1 ***********/ + Mockito.when(dynamicPropertiesStore.getLatestBlockHeaderNumber()).thenReturn(0L); + method.invoke(blockEventLoad); + Assert.assertEquals(0, queue.size()); + + /********** 2 ***********/ + BlockEvent be1 = new BlockEvent(); + BlockCapsule.BlockId b1 = new BlockCapsule.BlockId(BlockEventCacheTest.getBlockId(), 1); + be1.setBlockId(b1); + be1.setParentId(b0); + be1.setSolidId(b0); + + Mockito.when(dynamicPropertiesStore.getLatestBlockHeaderNumber()).thenReturn(1L); + Mockito.when(blockEventGet.getBlockEvent(1L)).thenReturn(be1); + method.invoke(blockEventLoad); + Assert.assertEquals(1, queue.size()); + Assert.assertEquals(b1, BlockEventCache.getHead().getBlockId()); + + /********** 3 ***********/ + BlockEventCache.init(b0); + queue.clear(); + + BlockEvent be2 = new BlockEvent(); + BlockCapsule.BlockId b2 = new BlockCapsule.BlockId(BlockEventCacheTest.getBlockId(), 2L); + be2.setBlockId(b2); + be2.setParentId(b1); + be2.setSolidId(b0); + + Mockito.when(dynamicPropertiesStore.getLatestBlockHeaderNumber()).thenReturn(2L); + Mockito.when(blockEventGet.getBlockEvent(2L)).thenReturn(be2); + method.invoke(blockEventLoad); + Assert.assertEquals(2, queue.size()); + Assert.assertEquals(b2, BlockEventCache.getHead().getBlockId()); + + /********** 4 ***********/ + BlockEventCache.init(b0); + queue.clear(); + + Mockito.when(dynamicPropertiesStore.getLatestBlockHeaderNumber()).thenReturn(1L); + method.invoke(blockEventLoad); + Assert.assertEquals(1, queue.size()); + queue.clear(); + + BlockEvent be21 = new BlockEvent(); + BlockCapsule.BlockId b21 = new BlockCapsule.BlockId(BlockEventCacheTest.getBlockId(), 1L); + be21.setBlockId(b21); + be21.setParentId(b0); + be21.setSolidId(b0); + + BlockEvent be22 = new BlockEvent(); + BlockCapsule.BlockId b22 = new BlockCapsule.BlockId(BlockEventCacheTest.getBlockId(), 2L); + be22.setBlockId(b22); + be22.setParentId(b21); + be22.setSolidId(b21); + + Mockito.when(dynamicPropertiesStore.getLatestBlockHeaderNumber()).thenReturn(2L); + Mockito.when(blockEventGet.getBlockEvent(1L)).thenReturn(be21); + Mockito.when(blockEventGet.getBlockEvent(2L)).thenReturn(be22); + method.invoke(blockEventLoad); + Assert.assertEquals(3, queue.size()); + Assert.assertEquals(b22, BlockEventCache.getHead().getBlockId()); + + Event event = queue.poll(); + Assert.assertEquals(b1, event.getBlockEvent().getBlockId()); + Assert.assertEquals(true, event.isRemove()); + + event = queue.poll(); + Assert.assertEquals(b21, event.getBlockEvent().getBlockId()); + Assert.assertEquals(false, event.isRemove()); + + event = queue.poll(); + Assert.assertEquals(b22, event.getBlockEvent().getBlockId()); + Assert.assertEquals(false, event.isRemove()); + } +} diff --git a/framework/src/test/java/org/tron/core/event/EventServiceTest.java b/framework/src/test/java/org/tron/core/event/EventServiceTest.java new file mode 100644 index 00000000000..b20e33404fd --- /dev/null +++ b/framework/src/test/java/org/tron/core/event/EventServiceTest.java @@ -0,0 +1,34 @@ +package org.tron.core.event; + +import static org.mockito.Mockito.mock; + +import org.junit.Test; +import org.mockito.Mockito; +import org.tron.common.utils.ReflectUtils; +import org.tron.core.db.Manager; +import org.tron.core.services.event.BlockEventLoad; +import org.tron.core.services.event.EventService; +import org.tron.core.services.event.HistoryEventService; +import org.tron.core.services.event.RealtimeEventService; + +public class EventServiceTest { + + @Test + public void test() { + EventService eventService = new EventService(); + HistoryEventService historyEventService = new HistoryEventService(); + RealtimeEventService realtimeEventService = new RealtimeEventService(); + BlockEventLoad blockEventLoad = new BlockEventLoad(); + + ReflectUtils.setFieldValue(eventService, "historyEventService", historyEventService); + ReflectUtils.setFieldValue(eventService, "realtimeEventService", realtimeEventService); + ReflectUtils.setFieldValue(eventService, "blockEventLoad", blockEventLoad); + + Manager manager = mock(Manager.class); + ReflectUtils.setFieldValue(eventService, "manager", manager); + Mockito.when(manager.isEventPluginLoaded()).thenReturn(true); + + eventService.init(); + eventService.close(); + } +} diff --git a/framework/src/test/java/org/tron/core/event/HistoryEventServiceTest.java b/framework/src/test/java/org/tron/core/event/HistoryEventServiceTest.java new file mode 100644 index 00000000000..f51d2dbe490 --- /dev/null +++ b/framework/src/test/java/org/tron/core/event/HistoryEventServiceTest.java @@ -0,0 +1,85 @@ +package org.tron.core.event; + +import static org.mockito.Mockito.mock; + +import java.lang.reflect.Method; +import org.junit.Test; +import org.mockito.Mockito; +import org.tron.common.logsfilter.EventPluginLoader; +import org.tron.common.utils.ReflectUtils; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.ChainBaseManager; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.db.Manager; +import org.tron.core.services.event.BlockEventGet; +import org.tron.core.services.event.BlockEventLoad; +import org.tron.core.services.event.HistoryEventService; +import org.tron.core.services.event.RealtimeEventService; +import org.tron.core.services.event.SolidEventService; +import org.tron.core.services.event.bo.BlockEvent; +import org.tron.core.store.DynamicPropertiesStore; + +public class HistoryEventServiceTest { + + HistoryEventService historyEventService = new HistoryEventService(); + + @Test + public void test() throws Exception { + EventPluginLoader instance = mock(EventPluginLoader.class); + ReflectUtils.setFieldValue(historyEventService, "instance", instance); + + DynamicPropertiesStore dynamicPropertiesStore = mock(DynamicPropertiesStore.class); + ChainBaseManager chainBaseManager = mock(ChainBaseManager.class); + Manager manager = mock(Manager.class); + ReflectUtils.setFieldValue(historyEventService, "manager", manager); + Mockito.when(manager.getChainBaseManager()).thenReturn(chainBaseManager); + Mockito.when(manager.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStore); + Mockito.when(chainBaseManager.getHeadBlockId()).thenReturn(new BlockCapsule.BlockId()); + + SolidEventService solidEventService = new SolidEventService(); + RealtimeEventService realtimeEventService = new RealtimeEventService(); + BlockEventLoad blockEventLoad = new BlockEventLoad(); + + ReflectUtils.setFieldValue(historyEventService, "solidEventService", solidEventService); + ReflectUtils.setFieldValue(historyEventService, "realtimeEventService", realtimeEventService); + ReflectUtils.setFieldValue(historyEventService, "blockEventLoad", blockEventLoad); + historyEventService.init(); + solidEventService.close(); + realtimeEventService.close(); + blockEventLoad.close(); + + solidEventService = mock(SolidEventService.class); + ReflectUtils.setFieldValue(historyEventService, "solidEventService", solidEventService); + realtimeEventService = mock(RealtimeEventService.class); + ReflectUtils.setFieldValue(historyEventService, "realtimeEventService", realtimeEventService); + blockEventLoad = mock(BlockEventLoad.class); + ReflectUtils.setFieldValue(historyEventService, "blockEventLoad", blockEventLoad); + + Mockito.when(instance.getStartSyncBlockNum()).thenReturn(0L); + + Mockito.when(dynamicPropertiesStore.getLatestSolidifiedBlockNum()).thenReturn(0L); + Mockito.when(chainBaseManager.getBlockIdByNum(0L)) + .thenReturn(new BlockCapsule.BlockId(Sha256Hash.ZERO_HASH, 0)); + historyEventService.init(); + + BlockEvent be2 = new BlockEvent(); + BlockCapsule.BlockId b2 = new BlockCapsule.BlockId(BlockEventCacheTest.getBlockId(), 2); + be2.setBlockId(b2); + + BlockEventGet blockEventGet = mock(BlockEventGet.class); + ReflectUtils.setFieldValue(historyEventService, "blockEventGet", blockEventGet); + Mockito.when(blockEventGet.getBlockEvent(1)).thenReturn(be2); + + Mockito.when(instance.getStartSyncBlockNum()).thenReturn(1L); + ReflectUtils.setFieldValue(historyEventService, "isRunning", true); + Mockito.when(dynamicPropertiesStore.getLatestSolidifiedBlockNum()).thenReturn(1L); + + Mockito.when(chainBaseManager.getBlockIdByNum(1L)) + .thenReturn(new BlockCapsule.BlockId(Sha256Hash.ZERO_HASH, 1)); + + Method method1 = historyEventService.getClass().getDeclaredMethod("syncEvent"); + method1.setAccessible(true); + method1.invoke(historyEventService); + + } +} diff --git a/framework/src/test/java/org/tron/core/event/RealtimeEventServiceTest.java b/framework/src/test/java/org/tron/core/event/RealtimeEventServiceTest.java new file mode 100644 index 00000000000..91dcea71322 --- /dev/null +++ b/framework/src/test/java/org/tron/core/event/RealtimeEventServiceTest.java @@ -0,0 +1,118 @@ +package org.tron.core.event; + +import static org.mockito.Mockito.mock; + +import com.google.protobuf.ByteString; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import org.eclipse.jetty.util.BlockingArrayQueue; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; +import org.tron.common.logsfilter.EventPluginLoader; +import org.tron.common.logsfilter.capsule.BlockLogTriggerCapsule; +import org.tron.common.logsfilter.capsule.TransactionLogTriggerCapsule; +import org.tron.common.logsfilter.capsule.TriggerCapsule; +import org.tron.common.logsfilter.trigger.ContractEventTrigger; +import org.tron.common.logsfilter.trigger.ContractLogTrigger; +import org.tron.common.utils.ReflectUtils; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.db.Manager; +import org.tron.core.services.event.BlockEventCache; +import org.tron.core.services.event.RealtimeEventService; +import org.tron.core.services.event.bo.BlockEvent; +import org.tron.core.services.event.bo.Event; +import org.tron.core.services.event.bo.SmartContractTrigger; + +public class RealtimeEventServiceTest { + + RealtimeEventService realtimeEventService = new RealtimeEventService(); + + @Test + public void test() throws Exception { + BlockEvent be1 = new BlockEvent(); + BlockCapsule.BlockId b1 = new BlockCapsule.BlockId(BlockEventCacheTest.getBlockId(), 1); + be1.setBlockId(b1); + be1.setParentId(b1); + be1.setSolidId(b1); + BlockEventCache.init(b1); + + BlockEvent be2 = new BlockEvent(); + BlockCapsule.BlockId b2 = new BlockCapsule.BlockId(BlockEventCacheTest.getBlockId(), 2); + be2.setBlockId(b2); + be2.setParentId(b1); + be2.setSolidId(b1); + BlockEventCache.add(be2); + Assert.assertEquals(be2, BlockEventCache.getHead()); + Assert.assertEquals(be2, BlockEventCache.getBlockEvent(b2)); + + Event event = new Event(be2, true); + + realtimeEventService.add(event); + realtimeEventService.work(); + + EventPluginLoader instance = mock(EventPluginLoader.class); + ReflectUtils.setFieldValue(realtimeEventService, "instance", instance); + + BlockingQueue queue = new BlockingArrayQueue<>(); + Manager manager = mock(Manager.class); + Mockito.when(manager.getTriggerCapsuleQueue()).thenReturn(queue); + ReflectUtils.setFieldValue(realtimeEventService, "manager", manager); + + BlockCapsule blockCapsule = new BlockCapsule(0L, Sha256Hash.ZERO_HASH, 0L, + ByteString.copyFrom(BlockEventCacheTest.getBlockId())); + be2.setBlockLogTriggerCapsule(new BlockLogTriggerCapsule(blockCapsule)); + Mockito.when(instance.isBlockLogTriggerEnable()).thenReturn(true); + Mockito.when(instance.isBlockLogTriggerSolidified()).thenReturn(false); + + realtimeEventService.add(event); + realtimeEventService.work(); + + Assert.assertEquals(0, queue.size()); + + event = new Event(be2, false); + realtimeEventService.add(event); + realtimeEventService.work(); + + Assert.assertEquals(1, queue.size()); + + be2.setBlockLogTriggerCapsule(null); + queue.poll(); + + List list = new ArrayList<>(); + list.add(mock(TransactionLogTriggerCapsule.class)); + be2.setTransactionLogTriggerCapsules(list); + + Mockito.when(instance.isTransactionLogTriggerEnable()).thenReturn(true); + Mockito.when(instance.isTransactionLogTriggerSolidified()).thenReturn(false); + realtimeEventService.flush(be2, event.isRemove()); + Assert.assertEquals(1, queue.size()); + + be2.setTransactionLogTriggerCapsules(null); + + SmartContractTrigger contractTrigger = new SmartContractTrigger(); + be2.setSmartContractTrigger(contractTrigger); + + contractTrigger.getContractEventTriggers().add(mock(ContractEventTrigger.class)); + Mockito.when(instance.isContractLogTriggerEnable()).thenReturn(true); + try { + realtimeEventService.flush(be2, event.isRemove()); + } catch (Exception e) { + Assert.assertTrue(e instanceof NullPointerException); + } + + contractTrigger.getContractEventTriggers().clear(); + + realtimeEventService.flush(be2, event.isRemove()); + + contractTrigger.getContractLogTriggers().add(mock(ContractLogTrigger.class)); + Mockito.when(instance.isContractEventTriggerEnable()).thenReturn(true); + try { + realtimeEventService.flush(be2, event.isRemove()); + } catch (Exception e) { + Assert.assertTrue(e instanceof NullPointerException); + } + } +} diff --git a/framework/src/test/java/org/tron/core/event/SolidEventServiceTest.java b/framework/src/test/java/org/tron/core/event/SolidEventServiceTest.java new file mode 100644 index 00000000000..ef71a3d39a9 --- /dev/null +++ b/framework/src/test/java/org/tron/core/event/SolidEventServiceTest.java @@ -0,0 +1,116 @@ +package org.tron.core.event; + +import static org.mockito.Mockito.mock; + +import com.google.protobuf.ByteString; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import org.eclipse.jetty.util.BlockingArrayQueue; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; +import org.tron.common.logsfilter.EventPluginLoader; +import org.tron.common.logsfilter.capsule.BlockLogTriggerCapsule; +import org.tron.common.logsfilter.capsule.SolidityTriggerCapsule; +import org.tron.common.logsfilter.capsule.TransactionLogTriggerCapsule; +import org.tron.common.logsfilter.capsule.TriggerCapsule; +import org.tron.common.logsfilter.trigger.ContractEventTrigger; +import org.tron.common.logsfilter.trigger.ContractLogTrigger; +import org.tron.common.utils.ReflectUtils; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.db.Manager; +import org.tron.core.services.event.BlockEventCache; +import org.tron.core.services.event.SolidEventService; +import org.tron.core.services.event.bo.BlockEvent; +import org.tron.core.services.event.bo.SmartContractTrigger; + +public class SolidEventServiceTest { + + SolidEventService solidEventService = new SolidEventService(); + + @Test + public void test() throws Exception { + BlockEvent be1 = new BlockEvent(); + BlockCapsule.BlockId b1 = new BlockCapsule.BlockId(BlockEventCacheTest.getBlockId(), 1); + be1.setBlockId(b1); + be1.setParentId(b1); + be1.setSolidId(b1); + BlockEventCache.init(b1); + + BlockEvent be2 = new BlockEvent(); + BlockCapsule.BlockId b2 = new BlockCapsule.BlockId(BlockEventCacheTest.getBlockId(), 2); + be2.setBlockId(b2); + be2.setParentId(b1); + be2.setSolidId(b1); + BlockEventCache.add(be2); + Assert.assertEquals(be2, BlockEventCache.getHead()); + Assert.assertEquals(be2, BlockEventCache.getBlockEvent(b2)); + + solidEventService.flush(be2); + + EventPluginLoader instance = mock(EventPluginLoader.class); + ReflectUtils.setFieldValue(solidEventService, "instance", instance); + + BlockingQueue queue = new BlockingArrayQueue<>(); + Manager manager = mock(Manager.class); + Mockito.when(manager.getTriggerCapsuleQueue()).thenReturn(queue); + ReflectUtils.setFieldValue(solidEventService, "manager", manager); + + BlockCapsule blockCapsule = new BlockCapsule(0L, Sha256Hash.ZERO_HASH, 0L, + ByteString.copyFrom(BlockEventCacheTest.getBlockId())); + be2.setBlockLogTriggerCapsule(new BlockLogTriggerCapsule(blockCapsule)); + Mockito.when(instance.isBlockLogTriggerEnable()).thenReturn(true); + Mockito.when(instance.isBlockLogTriggerSolidified()).thenReturn(true); + + solidEventService.flush(be2); + + Assert.assertEquals(1, queue.size()); + + be2.setBlockLogTriggerCapsule(null); + queue.poll(); + + List list = new ArrayList<>(); + list.add(mock(TransactionLogTriggerCapsule.class)); + be2.setTransactionLogTriggerCapsules(list); + + Mockito.when(instance.isTransactionLogTriggerEnable()).thenReturn(true); + Mockito.when(instance.isTransactionLogTriggerSolidified()).thenReturn(true); + solidEventService.flush(be2); + Assert.assertEquals(1, queue.size()); + + be2.setTransactionLogTriggerCapsules(null); + + SmartContractTrigger contractTrigger = new SmartContractTrigger(); + be2.setSmartContractTrigger(contractTrigger); + + contractTrigger.getContractEventTriggers().add(mock(ContractEventTrigger.class)); + Mockito.when(instance.isSolidityLogTriggerEnable()).thenReturn(true); + try { + solidEventService.flush(be2); + } catch (Exception e) { + Assert.assertTrue(e instanceof NullPointerException); + } + + contractTrigger.getContractEventTriggers().clear(); + + solidEventService.flush(be2); + + contractTrigger.getContractLogTriggers().add(mock(ContractLogTrigger.class)); + Mockito.when(instance.isSolidityEventTriggerEnable()).thenReturn(true); + try { + solidEventService.flush(be2); + } catch (Exception e) { + Assert.assertTrue(e instanceof NullPointerException); + } + + be2.setSmartContractTrigger(null); + + Mockito.when(instance.isSolidityTriggerEnable()).thenReturn(true); + be2.setSolidityTriggerCapsule(new SolidityTriggerCapsule(1)); + queue.clear(); + solidEventService.flush(be2); + Assert.assertEquals(1, queue.size()); + } +} From f7a371103792ba1d8b89b0bc7337b99e74bbcf28 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 13 Feb 2025 18:33:06 +0800 Subject: [PATCH 1125/1197] bump jcommander from 1.72 to 1.78 --- common/build.gradle | 2 +- .../main/java/org/tron/core/config/args/Args.java | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/common/build.gradle b/common/build.gradle index efd966897a4..a7393d2d739 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -34,7 +34,7 @@ dependencies { api "com.cedarsoftware:java-util:1.8.0" api group: 'org.apache.httpcomponents', name: 'httpasyncclient', version: '4.1.1' api group: 'commons-codec', name: 'commons-codec', version: '1.11' - api group: 'com.beust', name: 'jcommander', version: '1.72' + api group: 'com.beust', name: 'jcommander', version: '1.78' api group: 'com.typesafe', name: 'config', version: '1.3.2' api group: leveldbGroup, name: leveldbName, version: leveldbVersion api group: 'org.rocksdb', name: 'rocksdbjni', version: '5.15.10' diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 852d271497d..a4752351625 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -260,14 +260,15 @@ private static void printVersion() { } catch (IOException e) { logger.error(e.getMessage()); } - JCommander.getConsole().println("OS : " + System.getProperty("os.name")); - JCommander.getConsole().println("JVM : " + System.getProperty("java.vendor") + " " + JCommander jCommander = new JCommander(); + jCommander.getConsole().println("OS : " + System.getProperty("os.name")); + jCommander.getConsole().println("JVM : " + System.getProperty("java.vendor") + " " + System.getProperty("java.version") + " " + System.getProperty("os.arch")); if (!noGitProperties) { - JCommander.getConsole().println("Git : " + properties.getProperty("git.commit.id")); + jCommander.getConsole().println("Git : " + properties.getProperty("git.commit.id")); } - JCommander.getConsole().println("Version : " + Version.getVersion()); - JCommander.getConsole().println("Code : " + Version.VERSION_CODE); + jCommander.getConsole().println("Version : " + Version.getVersion()); + jCommander.getConsole().println("Code : " + Version.VERSION_CODE); } public static void printHelp(JCommander jCommander) { @@ -311,7 +312,7 @@ public static void printHelp(JCommander jCommander) { helpStr.append(tmpOptionDesc); } } - JCommander.getConsole().println(helpStr.toString()); + jCommander.getConsole().println(helpStr.toString()); } public static String upperFirst(String name) { From 7149763f749bd380af94ec41cd777c64ac9a4f74 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 13 Feb 2025 18:33:47 +0800 Subject: [PATCH 1126/1197] bump pf4j from 2.5.0 to 3.10.0 --- framework/build.gradle | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/framework/build.gradle b/framework/build.gradle index 83b6df6d95e..fb4f2278294 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -57,7 +57,9 @@ dependencies { compileOnly group: 'javax.portlet', name: 'portlet-api', version: '3.0.1' implementation "io.vavr:vavr:0.9.2" - implementation group: 'org.pf4j', name: 'pf4j', version: '2.5.0' + implementation (group: 'org.pf4j', name: 'pf4j', version: '3.10.0') { + exclude group: "org.slf4j", module: "slf4j-api" + } testImplementation group: 'org.springframework', name: 'spring-test', version: '5.2.0.RELEASE' testImplementation group: 'org.springframework', name: 'spring-web', version: '5.2.0.RELEASE' From f9f592ebfa7635f4afb988031cadc22e9a416c91 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 13 Feb 2025 18:34:25 +0800 Subject: [PATCH 1127/1197] bump grpc from 1.52.1 to 1.60.0 --- .../java/org/tron/common/client/DatabaseGrpcClient.java | 8 ++++++++ protocol/build.gradle | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java b/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java index f3650bfd2be..0c22c264188 100644 --- a/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java +++ b/framework/src/main/java/org/tron/common/client/DatabaseGrpcClient.java @@ -1,7 +1,9 @@ package org.tron.common.client; +import io.grpc.LoadBalancerRegistry; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import io.grpc.internal.PickFirstLoadBalancerProvider; import org.tron.api.DatabaseGrpc; import org.tron.api.GrpcAPI.EmptyMessage; import org.tron.api.GrpcAPI.NumberMessage; @@ -13,6 +15,12 @@ public class DatabaseGrpcClient { private final ManagedChannel channel; private final DatabaseGrpc.DatabaseBlockingStub databaseBlockingStub; + static { + LoadBalancerRegistry + .getDefaultRegistry() + .register(new PickFirstLoadBalancerProvider()); + } + public DatabaseGrpcClient(String host, int port) { channel = ManagedChannelBuilder.forAddress(host, port) .usePlaintext() diff --git a/protocol/build.gradle b/protocol/build.gradle index ce4091afff1..02158f9fdd4 100644 --- a/protocol/build.gradle +++ b/protocol/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.google.protobuf' def protobufVersion = '3.25.5' -def grpcVersion = '1.52.1' +def grpcVersion = '1.60.0' dependencies { api group: 'com.google.protobuf', name: 'protobuf-java', version: protobufVersion From f500778a17688506c288e42f88eb7b3f648ad8f1 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 13 Feb 2025 18:35:25 +0800 Subject: [PATCH 1128/1197] bump libp2p from 2.2.4 to 2.2.5 --- common/build.gradle | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index a7393d2d739..25709c9b7a6 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -46,7 +46,7 @@ dependencies { api 'org.aspectj:aspectjrt:1.8.13' api 'org.aspectj:aspectjweaver:1.8.13' api 'org.aspectj:aspectjtools:1.8.13' - api group: 'io.github.tronprotocol', name: 'libp2p', version: '2.2.4',{ + api group: 'io.github.tronprotocol', name: 'libp2p', version: '2.2.5',{ exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' @@ -60,6 +60,8 @@ dependencies { exclude group: 'net.java.dev.msv', module: 'xsdlib' exclude group: 'pull-parser', module: 'pull-parser' exclude group: 'xpp3', module: 'xpp3' + exclude group: 'org.bouncycastle', module: 'bcprov-jdk18on' + exclude group: 'org.bouncycastle', module: 'bcutil-jdk18on' } api project(":protocol") } From 9485e85e708477d83ef8ea12c8e1ac2f70107b29 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 14 Feb 2025 19:20:13 +0800 Subject: [PATCH 1129/1197] add test case ApiUtilTest --- .../org/tron/core/jsonrpc/ApiUtilTest.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/jsonrpc/ApiUtilTest.java diff --git a/framework/src/test/java/org/tron/core/jsonrpc/ApiUtilTest.java b/framework/src/test/java/org/tron/core/jsonrpc/ApiUtilTest.java new file mode 100644 index 00000000000..84aba180138 --- /dev/null +++ b/framework/src/test/java/org/tron/core/jsonrpc/ApiUtilTest.java @@ -0,0 +1,47 @@ +package org.tron.core.jsonrpc; + + +import static org.tron.common.utils.Commons.decodeFromBase58Check; +import static org.tron.keystore.Wallet.generateRandomBytes; + +import com.google.protobuf.ByteString; +import org.junit.Assert; +import org.junit.Test; +import org.tron.common.utils.ByteArray; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.services.jsonrpc.JsonRpcApiUtil; +import org.tron.protos.Protocol.Block; +import org.tron.protos.Protocol.BlockHeader; +import org.tron.protos.Protocol.BlockHeader.raw; +import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; + +public class ApiUtilTest { + + @Test + public void testGetBlockID() { + byte[] mockedHash = generateRandomBytes(128); + // common parent block + BlockCapsule blockCapsule = new BlockCapsule(Block.newBuilder().setBlockHeader( + BlockHeader.newBuilder().setRawData( + raw.newBuilder().setParentHash(ByteString.copyFrom(mockedHash)) + .setNumber(0))).build()); + String blockIdStr = JsonRpcApiUtil.getBlockID(blockCapsule.getInstance()); + Assert.assertEquals(2 + 64, blockIdStr.length()); + } + + @Test + public void testTriggerCallContract() { + byte[] address = decodeFromBase58Check("TEPRbQxXQEpHpeEx8tK5xHVs7NWudAAZgu"); + //nile usdt + byte[] contractAddress = decodeFromBase58Check("TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf"); + long callValue = 100; + //transfer to address TVjsyZ7fYF3qLF6BQgPmTEZy1xrNNyVAAA with 10*10^6 + byte[] data = ByteArray.fromHexString("a9059cbb000000000000000000000000d8dd39e2dea27a4000" + + "1884901735e3940829bb440000000000000000000000000000000000000000000000000000000000989680"); + long tokenValue = 10; + String tokenId = "1000001"; + TriggerSmartContract triggerSmartContract = JsonRpcApiUtil.triggerCallContract(address, + contractAddress, callValue, data, tokenValue, tokenId); + Assert.assertNotNull(triggerSmartContract); + } +} From 61eb74632154b3dec41ce6dc095ffe6511989fa5 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Sat, 8 Feb 2025 16:01:42 +0800 Subject: [PATCH 1130/1197] feat(math): migrate all operations from java.lang.Math to java.lang.StrictMath --- .github/workflows/math-check.yml | 93 ++++++++++++ .../tron/core/actuator/AbstractActuator.java | 62 ++++++++ .../AccountPermissionUpdateActuator.java | 7 +- .../core/actuator/AssetIssueActuator.java | 5 +- .../core/actuator/CreateAccountActuator.java | 6 +- .../actuator/DelegateResourceActuator.java | 6 +- .../core/actuator/ExchangeCreateActuator.java | 3 +- .../core/actuator/ExchangeInjectActuator.java | 8 +- .../actuator/ExchangeWithdrawActuator.java | 8 -- .../actuator/MarketCancelOrderActuator.java | 3 +- .../actuator/MarketSellAssetActuator.java | 25 ++-- .../ParticipateAssetIssueActuator.java | 16 +-- .../actuator/ShieldedTransferActuator.java | 14 +- .../tron/core/actuator/TransferActuator.java | 11 +- .../core/actuator/TransferAssetActuator.java | 6 +- .../actuator/UnDelegateResourceActuator.java | 4 +- .../org/tron/core/actuator/VMActuator.java | 60 +++++--- .../core/actuator/WitnessCreateActuator.java | 6 +- .../org/tron/core/utils/TransactionUtil.java | 3 +- .../java/org/tron/core/vm/EnergyCost.java | 4 +- .../tron/core/vm/PrecompiledContracts.java | 11 +- .../main/java/org/tron/core/vm/VMUtils.java | 6 +- .../org/tron/core/vm/config/ConfigLoader.java | 1 + .../DelegateResourceProcessor.java | 5 +- .../UnDelegateResourceProcessor.java | 6 +- .../UnfreezeBalanceProcessor.java | 6 +- .../java/org/tron/core/vm/program/Memory.java | 20 +-- .../org/tron/core/vm/program/Program.java | 29 ++-- .../core/vm/repository/RepositoryImpl.java | 10 +- .../org/tron/core/vm/utils/FreezeV2Util.java | 27 ++-- .../main/java/org/tron/common/math/Maths.java | 20 --- .../java/org/tron/common/utils/Commons.java | 18 ++- .../org/tron/common/utils/ForkController.java | 5 +- .../org/tron/core/capsule/AccountCapsule.java | 75 +++++----- .../tron/core/capsule/ContractCapsule.java | 8 +- .../core/capsule/ContractStateCapsule.java | 22 +-- .../org/tron/core/capsule/ReceiptCapsule.java | 19 ++- .../tron/core/capsule/utils/MarketUtils.java | 38 ++--- .../org/tron/core/db/EnergyProcessor.java | 14 +- .../org/tron/core/db/ResourceProcessor.java | 29 ++-- .../org/tron/core/db/TransactionTrace.java | 14 +- .../tron/core/service/MortgageService.java | 5 +- .../org/tron/core/store/AssetIssueStore.java | 7 - .../core/store/DynamicPropertiesStore.java | 11 +- .../org/tron/common/math/MathWrapper.java | 64 +++++++++ .../main/java/org/tron/common/math/Maths.java | 92 ++++++++++++ .../tron/common/math/StrictMathWrapper.java | 136 ++++++++++++++++++ .../org/tron/common/runtime/vm/DataWord.java | 8 +- .../java/org/tron/common/utils/ByteUtil.java | 6 +- .../org/tron/core/vm/config/VMConfig.java | 10 ++ .../logsfilter/ContractEventParser.java | 4 +- .../src/main/java/org/tron/core/Wallet.java | 25 ++-- .../java/org/tron/core/capsule/utils/RLP.java | 3 +- .../java/org/tron/core/config/args/Args.java | 29 ++-- .../main/java/org/tron/core/db/Manager.java | 37 +++-- .../SyncBlockChainMsgHandler.java | 4 +- .../service/effective/ResilienceService.java | 7 +- .../jsonrpc/filters/LogFilterWrapper.java | 4 +- .../main/java/org/tron/program/DBConvert.java | 3 +- .../test/java/org/tron/common/BaseTest.java | 9 ++ .../runtime/vm/BandWidthRuntimeTest.java | 5 +- .../tron/common/runtime/vm/FreezeV2Test.java | 4 +- .../tron/common/runtime/vm/MemoryTest.java | 4 +- .../PrecompiledContractsVerifyProofTest.java | 4 +- .../org/tron/common/runtime/vm/VoteTest.java | 4 +- .../common/utils/client/utils/AbiUtil.java | 4 +- .../common/utils/client/utils/DataWord.java | 4 +- .../actuator/ExchangeCreateActuatorTest.java | 68 ++++----- .../actuator/ExchangeInjectActuatorTest.java | 44 +++--- .../ExchangeTransactionActuatorTest.java | 24 ++-- .../ExchangeWithdrawActuatorTest.java | 18 +-- .../ParticipateAssetIssueActuatorTest.java | 2 +- .../UpdateSettingContractActuatorTest.java | 12 +- .../actuator/utils/TransactionUtilTest.java | 21 +-- .../tron/core/capsule/AccountCapsuleTest.java | 4 +- .../capsule/ContractStateCapsuleTest.java | 24 ++-- .../core/capsule/utils/MerkleTreeTest.java | 4 +- .../java/org/tron/core/db/ManagerTest.java | 9 +- .../db/MarketPairPriceToOrderStoreTest.java | 5 +- .../core/jsonrpc/ConcurrentHashMapTest.java | 5 +- .../core/services/ProposalServiceTest.java | 2 + .../tron/core/zksnark/LibrustzcashTest.java | 4 +- .../tron/core/zksnark/SaplingNoteTest.java | 5 +- .../org/tron/plugins/utils/ByteArray.java | 2 +- .../java/org/tron/plugins/utils/DBUtils.java | 3 +- .../org/tron/plugins/utils/MarketUtils.java | 4 +- 86 files changed, 1036 insertions(+), 450 deletions(-) create mode 100644 .github/workflows/math-check.yml delete mode 100644 chainbase/src/main/java/org/tron/common/math/Maths.java create mode 100644 common/src/main/java/org/tron/common/math/Maths.java rename {actuator => common}/src/main/java/org/tron/core/vm/config/VMConfig.java (96%) diff --git a/.github/workflows/math-check.yml b/.github/workflows/math-check.yml new file mode 100644 index 00000000000..0f0255815d5 --- /dev/null +++ b/.github/workflows/math-check.yml @@ -0,0 +1,93 @@ +name: Check Math Usage + +on: + push: + branches: [ 'master', 'release_**' ] + pull_request: + branches: [ 'develop', 'release_**' ] + workflow_dispatch: + +jobs: + check-math: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Check for java.lang.Math usage + id: check-math + shell: bash + run: | + echo "Checking for java.lang.Math usage..." + + touch math_usage.txt + + while IFS= read -r file; do + filename=$(basename "$file") + if [[ "$filename" == "StrictMathWrapper.java" || "$filename" == "MathWrapper.java" ]]; then + continue + fi + + perl -0777 -ne ' + s/"([^"\\]|\\.)*"//g; + s/'\''([^'\''\\]|\\.)*'\''//g; + s!/\*([^*]|\*[^/])*\*/!!g; + s!//[^\n]*!!g; + $hasMath = 0; + $hasMath = 1 if /^[\s]*import[\s]+java\.lang\.Math\b/m; + $hasMath = 1 if /\bjava\s*\.\s*lang\s*\.\s*Math\s*\./; + $hasMath = 1 if /(?> math_usage.txt + done < <(find . -type f -name "*.java") + + sort -u math_usage.txt -o math_usage.txt + + if [ -s math_usage.txt ]; then + echo "❌ Error: Forbidden Math usage found in the following files:" + cat math_usage.txt + echo "math_found=true" >> $GITHUB_OUTPUT + echo "Please use org.tron.common.math.StrictMathWrapper instead of direct Math usage." + else + echo "✅ No forbidden Math usage found" + echo "math_found=false" >> $GITHUB_OUTPUT + fi + + - name: Upload findings + if: steps.check-math.outputs.math_found == 'true' + uses: actions/upload-artifact@v4 + with: + name: math-usage-report + path: math_usage.txt + + - name: Create comment + if: github.event_name == 'pull_request' && steps.check-math.outputs.math_found == 'true' + uses: actions/github-script@v6 + with: + script: | + const fs = require('fs'); + const findings = fs.readFileSync('math_usage.txt', 'utf8'); + const body = `### ❌ Math Usage Detection Results + + Found forbidden usage of \`java.lang.Math\` in the following files: + + \`\`\` + ${findings} + \`\`\` + + **Please review if this usage is intended.** + > [!CAUTION] + > Note: You should use \`org.tron.common.math.StrictMathWrapper\`. + > If you need to use \`java.lang.Math\`, please provide a justification. + `; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: body + }); + + - name: Fail if Math usage found + if: steps.check-math.outputs.math_found == 'true' + run: exit 1 diff --git a/actuator/src/main/java/org/tron/core/actuator/AbstractActuator.java b/actuator/src/main/java/org/tron/core/actuator/AbstractActuator.java index c88baf9b3ca..2f1bb450d1b 100644 --- a/actuator/src/main/java/org/tron/core/actuator/AbstractActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/AbstractActuator.java @@ -2,9 +2,14 @@ import com.google.protobuf.Any; import com.google.protobuf.GeneratedMessageV3; +import org.tron.common.math.Maths; +import org.tron.common.utils.Commons; import org.tron.common.utils.ForkController; import org.tron.core.ChainBaseManager; +import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.exception.BalanceInsufficientException; +import org.tron.core.store.AccountStore; import org.tron.protos.Protocol.Transaction.Contract; import org.tron.protos.Protocol.Transaction.Contract.ContractType; @@ -63,4 +68,61 @@ public AbstractActuator setForkUtils(ForkController forkController) { return this; } + public long addExact(long x, long y) { + return Maths.addExact(x, y, chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } + + public long addExact(int x, int y) { + return Maths.addExact(x, y, chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } + + public long floorDiv(long x, long y) { + return Maths.floorDiv(x, y, chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } + + public long floorDiv(long x, int y) { + return this.floorDiv(x, (long) y); + } + + public long multiplyExact(long x, long y) { + return Maths.multiplyExact(x, y, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } + + public long multiplyExact(long x, int y) { + return this.multiplyExact(x, (long) y); + } + + public int multiplyExact(int x, int y) { + return Maths.multiplyExact(x, y, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } + + public long subtractExact(long x, long y) { + return Maths.subtractExact(x, y, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } + + public int min(int a, int b) { + return Maths.min(a, b, chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } + + public long min(long a, long b) { + return Maths.min(a, b, chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } + + public void adjustBalance(AccountStore accountStore, byte[] accountAddress, long amount) + throws BalanceInsufficientException { + AccountCapsule account = accountStore.getUnchecked(accountAddress); + this.adjustBalance(accountStore, account, amount); + } + + /** + * judge balance. + */ + public void adjustBalance(AccountStore accountStore, AccountCapsule account, long amount) + throws BalanceInsufficientException { + Commons.adjustBalance(accountStore, account, amount, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } } diff --git a/actuator/src/main/java/org/tron/core/actuator/AccountPermissionUpdateActuator.java b/actuator/src/main/java/org/tron/core/actuator/AccountPermissionUpdateActuator.java index fcc4d775d43..f2eafb20a5e 100644 --- a/actuator/src/main/java/org/tron/core/actuator/AccountPermissionUpdateActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/AccountPermissionUpdateActuator.java @@ -8,7 +8,6 @@ import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.tron.common.utils.Commons; import org.tron.common.utils.DecodeUtil; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionResultCapsule; @@ -52,11 +51,11 @@ public boolean execute(Object object) throws ContractExeException { accountPermissionUpdateContract.getActivesList()); accountStore.put(ownerAddress, account); - Commons.adjustBalance(accountStore, ownerAddress, -fee); + adjustBalance(accountStore, ownerAddress, -fee); if (chainBaseManager.getDynamicPropertiesStore().supportBlackHoleOptimization()) { chainBaseManager.getDynamicPropertiesStore().burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole(), fee); + adjustBalance(accountStore, accountStore.getBlackhole(), fee); } result.setStatus(fee, code.SUCESS); @@ -111,7 +110,7 @@ private boolean checkPermission(Permission permission) throws ContractValidateEx throw new ContractValidateException("key's weight should be greater than 0"); } try { - weightSum = Math.addExact(weightSum, key.getWeight()); + weightSum = addExact(weightSum, key.getWeight()); } catch (ArithmeticException e) { throw new ContractValidateException(e.getMessage()); } diff --git a/actuator/src/main/java/org/tron/core/actuator/AssetIssueActuator.java b/actuator/src/main/java/org/tron/core/actuator/AssetIssueActuator.java index 55218897c5d..331b45f106a 100644 --- a/actuator/src/main/java/org/tron/core/actuator/AssetIssueActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/AssetIssueActuator.java @@ -24,7 +24,6 @@ import java.util.List; import java.util.Objects; import lombok.extern.slf4j.Slf4j; -import org.tron.common.utils.Commons; import org.tron.common.utils.DecodeUtil; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; @@ -84,11 +83,11 @@ public boolean execute(Object result) throws ContractExeException { .put(assetIssueCapsuleV2.createDbV2Key(), assetIssueCapsuleV2); } - Commons.adjustBalance(accountStore, ownerAddress, -fee); + adjustBalance(accountStore, ownerAddress, -fee); if (dynamicStore.supportBlackHoleOptimization()) { dynamicStore.burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole(), fee);//send to blackhole + adjustBalance(accountStore, accountStore.getBlackhole(), fee);//send to blackhole } AccountCapsule accountCapsule = accountStore.get(ownerAddress); List frozenSupplyList = assetIssueContract.getFrozenSupplyList(); diff --git a/actuator/src/main/java/org/tron/core/actuator/CreateAccountActuator.java b/actuator/src/main/java/org/tron/core/actuator/CreateAccountActuator.java index 1c6aca4d7d7..352f394d6cb 100755 --- a/actuator/src/main/java/org/tron/core/actuator/CreateAccountActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/CreateAccountActuator.java @@ -6,7 +6,6 @@ import com.google.protobuf.InvalidProtocolBufferException; import java.util.Objects; import lombok.extern.slf4j.Slf4j; -import org.tron.common.utils.Commons; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; @@ -48,13 +47,12 @@ public boolean execute(Object result) accountStore .put(accountCreateContract.getAccountAddress().toByteArray(), accountCapsule); - Commons - .adjustBalance(accountStore, accountCreateContract.getOwnerAddress().toByteArray(), -fee); + adjustBalance(accountStore, accountCreateContract.getOwnerAddress().toByteArray(), -fee); // Add to blackhole address if (dynamicStore.supportBlackHoleOptimization()) { dynamicStore.burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole(), fee); + adjustBalance(accountStore, accountStore.getBlackhole(), fee); } ret.setStatus(fee, code.SUCESS); } catch (BalanceInsufficientException | InvalidProtocolBufferException e) { diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 161f22cfb17..90e91d8d3b2 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -162,7 +162,8 @@ public boolean validate() throws ContractValidateException { } long netUsage = (long) (accountNetUsage * TRX_PRECISION * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); - long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage); + long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage, + dynamicStore.allowStrictMath2()); if (ownerCapsule.getFrozenV2BalanceForBandwidth() - v2NetUsage < delegateBalance) { throw new ContractValidateException( "delegateBalance must be less than or equal to available FreezeBandwidthV2 balance"); @@ -175,7 +176,8 @@ public boolean validate() throws ContractValidateException { long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); - long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage); + long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage, + dynamicStore.allowStrictMath2()); if (ownerCapsule.getFrozenV2BalanceForEnergy() - v2EnergyUsage < delegateBalance) { throw new ContractValidateException( "delegateBalance must be less than or equal to available FreezeEnergyV2 balance"); diff --git a/actuator/src/main/java/org/tron/core/actuator/ExchangeCreateActuator.java b/actuator/src/main/java/org/tron/core/actuator/ExchangeCreateActuator.java index b7f5b90da45..27d3da509b4 100755 --- a/actuator/src/main/java/org/tron/core/actuator/ExchangeCreateActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/ExchangeCreateActuator.java @@ -9,7 +9,6 @@ import java.util.Arrays; import java.util.Objects; import lombok.extern.slf4j.Slf4j; -import org.tron.common.utils.Commons; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; @@ -121,7 +120,7 @@ public boolean execute(Object object) throws ContractExeException { if (dynamicStore.supportBlackHoleOptimization()) { dynamicStore.burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole(), fee); + adjustBalance(accountStore, accountStore.getBlackhole(), fee); } ret.setExchangeId(id); ret.setStatus(fee, code.SUCESS); diff --git a/actuator/src/main/java/org/tron/core/actuator/ExchangeInjectActuator.java b/actuator/src/main/java/org/tron/core/actuator/ExchangeInjectActuator.java index 7848f898ced..482f5bdf081 100755 --- a/actuator/src/main/java/org/tron/core/actuator/ExchangeInjectActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/ExchangeInjectActuator.java @@ -71,14 +71,14 @@ public boolean execute(Object object) throws ContractExeException { if (Arrays.equals(tokenID, firstTokenID)) { anotherTokenID = secondTokenID; - anotherTokenQuant = Math - .floorDiv(Math.multiplyExact(secondTokenBalance, tokenQuant), firstTokenBalance); + anotherTokenQuant = floorDiv(multiplyExact( + secondTokenBalance, tokenQuant), firstTokenBalance); exchangeCapsule.setBalance(firstTokenBalance + tokenQuant, secondTokenBalance + anotherTokenQuant); } else { anotherTokenID = firstTokenID; - anotherTokenQuant = Math - .floorDiv(Math.multiplyExact(firstTokenBalance, tokenQuant), secondTokenBalance); + anotherTokenQuant = floorDiv(multiplyExact( + firstTokenBalance, tokenQuant), secondTokenBalance); exchangeCapsule.setBalance(firstTokenBalance + anotherTokenQuant, secondTokenBalance + tokenQuant); } diff --git a/actuator/src/main/java/org/tron/core/actuator/ExchangeWithdrawActuator.java b/actuator/src/main/java/org/tron/core/actuator/ExchangeWithdrawActuator.java index 8929305d68c..fb8fe9384d3 100755 --- a/actuator/src/main/java/org/tron/core/actuator/ExchangeWithdrawActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/ExchangeWithdrawActuator.java @@ -76,16 +76,12 @@ public boolean execute(Object object) throws ContractExeException { BigInteger bigTokenQuant = new BigInteger(String.valueOf(tokenQuant)); if (Arrays.equals(tokenID, firstTokenID)) { anotherTokenID = secondTokenID; -// anotherTokenQuant = Math -// .floorDiv(Math.multiplyExact(secondTokenBalance, tokenQuant), firstTokenBalance); anotherTokenQuant = bigSecondTokenBalance.multiply(bigTokenQuant) .divide(bigFirstTokenBalance).longValueExact(); exchangeCapsule.setBalance(firstTokenBalance - tokenQuant, secondTokenBalance - anotherTokenQuant); } else { anotherTokenID = firstTokenID; -// anotherTokenQuant = Math -// .floorDiv(Math.multiplyExact(firstTokenBalance, tokenQuant), secondTokenBalance); anotherTokenQuant = bigFirstTokenBalance.multiply(bigTokenQuant) .divide(bigSecondTokenBalance).longValueExact(); exchangeCapsule.setBalance(firstTokenBalance - anotherTokenQuant, @@ -210,8 +206,6 @@ public boolean validate() throws ContractValidateException { BigDecimal bigSecondTokenBalance = new BigDecimal(String.valueOf(secondTokenBalance)); BigDecimal bigTokenQuant = new BigDecimal(String.valueOf(tokenQuant)); if (Arrays.equals(tokenID, firstTokenID)) { -// anotherTokenQuant = Math -// .floorDiv(Math.multiplyExact(secondTokenBalance, tokenQuant), firstTokenBalance); anotherTokenQuant = bigSecondTokenBalance.multiply(bigTokenQuant) .divideToIntegralValue(bigFirstTokenBalance).longValueExact(); if (firstTokenBalance < tokenQuant || secondTokenBalance < anotherTokenQuant) { @@ -230,8 +224,6 @@ public boolean validate() throws ContractValidateException { } } else { -// anotherTokenQuant = Math -// .floorDiv(Math.multiplyExact(firstTokenBalance, tokenQuant), secondTokenBalance); anotherTokenQuant = bigFirstTokenBalance.multiply(bigTokenQuant) .divideToIntegralValue(bigSecondTokenBalance).longValueExact(); if (secondTokenBalance < tokenQuant || firstTokenBalance < anotherTokenQuant) { diff --git a/actuator/src/main/java/org/tron/core/actuator/MarketCancelOrderActuator.java b/actuator/src/main/java/org/tron/core/actuator/MarketCancelOrderActuator.java index f859e580253..31b5e87e12d 100644 --- a/actuator/src/main/java/org/tron/core/actuator/MarketCancelOrderActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/MarketCancelOrderActuator.java @@ -23,7 +23,6 @@ import com.google.protobuf.InvalidProtocolBufferException; import java.util.Objects; import lombok.extern.slf4j.Slf4j; -import org.tron.common.utils.Commons; import org.tron.common.utils.DecodeUtil; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.MarketOrderCapsule; @@ -100,7 +99,7 @@ public boolean execute(Object object) throws ContractExeException { if (dynamicStore.supportBlackHoleOptimization()) { dynamicStore.burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole(), fee); + adjustBalance(accountStore, accountStore.getBlackhole(), fee); } // 1. return balance and token MarketUtils diff --git a/actuator/src/main/java/org/tron/core/actuator/MarketSellAssetActuator.java b/actuator/src/main/java/org/tron/core/actuator/MarketSellAssetActuator.java index 15e5a98f86a..43f21b716d8 100644 --- a/actuator/src/main/java/org/tron/core/actuator/MarketSellAssetActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/MarketSellAssetActuator.java @@ -129,7 +129,7 @@ public boolean execute(Object object) throws ContractExeException { if (dynamicStore.supportBlackHoleOptimization()) { dynamicStore.burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole(), fee); + adjustBalance(accountStore, accountStore.getBlackhole(), fee); } // 1. transfer of balance transferBalanceOrToken(accountCapsule); @@ -244,7 +244,7 @@ public boolean validate() throws ContractValidateException { long fee = calcFee(); if (Arrays.equals(sellTokenID, "_".getBytes())) { - if (ownerAccount.getBalance() < Math.addExact(sellTokenQuantity, fee)) { + if (ownerAccount.getBalance() < addExact(sellTokenQuantity, fee)) { throw new ContractValidateException("No enough balance !"); } } else { @@ -400,8 +400,10 @@ private void matchSingleOrder(MarketOrderCapsule takerOrderCapsule, // => takerBuyTokenQuantityCurrent_A = takerSellTokenQuantityRemain_TRX * // makerSellTokenQuantity_A/makerBuyTokenQuantity_TRX + boolean useStrictMath2 = dynamicStore.allowStrictMath2(); long takerBuyTokenQuantityRemain = MarketUtils - .multiplyAndDivide(takerSellRemainQuantity, makerSellQuantity, makerBuyQuantity); + .multiplyAndDivide(takerSellRemainQuantity, makerSellQuantity, makerBuyQuantity, + useStrictMath2); if (takerBuyTokenQuantityRemain == 0) { // quantity too small, return sellToken to user @@ -424,7 +426,8 @@ private void matchSingleOrder(MarketOrderCapsule takerOrderCapsule, // makerBuyTokenQuantity_TRX / makerSellTokenQuantity_A makerBuyTokenQuantityReceive = MarketUtils - .multiplyAndDivide(makerSellRemainQuantity, makerBuyQuantity, makerSellQuantity); + .multiplyAndDivide(makerSellRemainQuantity, makerBuyQuantity, makerSellQuantity, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); takerBuyTokenQuantityReceive = makerOrderCapsule.getSellTokenQuantityRemain(); long takerSellTokenLeft = @@ -447,7 +450,7 @@ private void matchSingleOrder(MarketOrderCapsule takerOrderCapsule, takerOrderCapsule.setSellTokenQuantityRemain(0); MarketUtils.updateOrderState(takerOrderCapsule, State.INACTIVE, marketAccountStore); - makerOrderCapsule.setSellTokenQuantityRemain(Math.subtractExact( + makerOrderCapsule.setSellTokenQuantityRemain(subtractExact( makerOrderCapsule.getSellTokenQuantityRemain(), takerBuyTokenQuantityRemain)); } else { // taker > maker @@ -458,7 +461,8 @@ private void matchSingleOrder(MarketOrderCapsule takerOrderCapsule, // makerSellTokenQuantityRemain_A/makerBuyTokenQuantityCurrent_TRX = // makerSellTokenQuantity_A/makerBuyTokenQuantity_TRX makerBuyTokenQuantityReceive = MarketUtils - .multiplyAndDivide(makerSellRemainQuantity, makerBuyQuantity, makerSellQuantity); + .multiplyAndDivide(makerSellRemainQuantity, makerBuyQuantity, makerSellQuantity, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); MarketUtils.updateOrderState(makerOrderCapsule, State.INACTIVE, marketAccountStore); if (makerBuyTokenQuantityReceive == 0) { @@ -475,7 +479,7 @@ private void matchSingleOrder(MarketOrderCapsule takerOrderCapsule, return; } else { makerOrderCapsule.setSellTokenQuantityRemain(0); - takerOrderCapsule.setSellTokenQuantityRemain(Math.subtractExact( + takerOrderCapsule.setSellTokenQuantityRemain(subtractExact( takerOrderCapsule.getSellTokenQuantityRemain(), makerBuyTokenQuantityReceive)); } } @@ -524,7 +528,8 @@ private MarketOrderCapsule createAndSaveOrder(AccountCapsule accountCapsule, private void transferBalanceOrToken(AccountCapsule accountCapsule) { if (Arrays.equals(sellTokenID, "_".getBytes())) { - accountCapsule.setBalance(Math.subtractExact(accountCapsule.getBalance(), sellTokenQuantity)); + accountCapsule.setBalance(subtractExact( + accountCapsule.getBalance(), sellTokenQuantity)); } else { accountCapsule .reduceAssetAmountV2(sellTokenID, sellTokenQuantity, dynamicStore, assetIssueStore); @@ -537,7 +542,7 @@ private void addTrxOrToken(MarketOrderCapsule orderCapsule, long num, byte[] buyTokenId = orderCapsule.getBuyTokenId(); if (Arrays.equals(buyTokenId, "_".getBytes())) { - accountCapsule.setBalance(Math.addExact(accountCapsule.getBalance(), num)); + accountCapsule.setBalance(addExact(accountCapsule.getBalance(), num)); } else { accountCapsule .addAssetAmountV2(buyTokenId, num, dynamicStore, assetIssueStore); @@ -550,7 +555,7 @@ private void addTrxOrToken(MarketOrderCapsule orderCapsule, long num) { byte[] buyTokenId = orderCapsule.getBuyTokenId(); if (Arrays.equals(buyTokenId, "_".getBytes())) { - accountCapsule.setBalance(Math.addExact(accountCapsule.getBalance(), num)); + accountCapsule.setBalance(addExact(accountCapsule.getBalance(), num)); } else { accountCapsule .addAssetAmountV2(buyTokenId, num, dynamicStore, assetIssueStore); diff --git a/actuator/src/main/java/org/tron/core/actuator/ParticipateAssetIssueActuator.java b/actuator/src/main/java/org/tron/core/actuator/ParticipateAssetIssueActuator.java index 77e345b2a92..7fdf15acd18 100755 --- a/actuator/src/main/java/org/tron/core/actuator/ParticipateAssetIssueActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/ParticipateAssetIssueActuator.java @@ -64,8 +64,8 @@ public boolean execute(Object object) throws ContractExeException { //subtract from owner address byte[] ownerAddress = participateAssetIssueContract.getOwnerAddress().toByteArray(); AccountCapsule ownerAccount = accountStore.get(ownerAddress); - long balance = Math.subtractExact(ownerAccount.getBalance(), cost); - balance = Math.subtractExact(balance, fee); + long balance = subtractExact(ownerAccount.getBalance(), cost); + balance = subtractExact(balance, fee); ownerAccount.setBalance(balance); byte[] key = participateAssetIssueContract.getAssetName().toByteArray(); @@ -74,14 +74,14 @@ public boolean execute(Object object) throws ContractExeException { assetIssueCapsule = Commons .getAssetIssueStoreFinal(dynamicStore, assetIssueStore, assetIssueV2Store).get(key); - long exchangeAmount = Math.multiplyExact(cost, assetIssueCapsule.getNum()); - exchangeAmount = Math.floorDiv(exchangeAmount, assetIssueCapsule.getTrxNum()); + long exchangeAmount = multiplyExact(cost, assetIssueCapsule.getNum()); + exchangeAmount = floorDiv(exchangeAmount, assetIssueCapsule.getTrxNum()); ownerAccount.addAssetAmountV2(key, exchangeAmount, dynamicStore, assetIssueStore); //add to to_address byte[] toAddress = participateAssetIssueContract.getToAddress().toByteArray(); AccountCapsule toAccount = accountStore.get(toAddress); - toAccount.setBalance(Math.addExact(toAccount.getBalance(), cost)); + toAccount.setBalance(addExact(toAccount.getBalance(), cost)); if (!toAccount.reduceAssetAmountV2(key, exchangeAmount, dynamicStore, assetIssueStore)) { throw new ContractExeException("reduceAssetAmount failed !"); } @@ -156,7 +156,7 @@ public boolean validate() throws ContractValidateException { try { //Whether the balance is enough long fee = calcFee(); - if (ownerAccount.getBalance() < Math.addExact(amount, fee)) { + if (ownerAccount.getBalance() < addExact(amount, fee)) { throw new ContractValidateException("No enough balance !"); } @@ -181,8 +181,8 @@ public boolean validate() throws ContractValidateException { int trxNum = assetIssueCapsule.getTrxNum(); int num = assetIssueCapsule.getNum(); - long exchangeAmount = Math.multiplyExact(amount, num); - exchangeAmount = Math.floorDiv(exchangeAmount, trxNum); + long exchangeAmount = multiplyExact(amount, num); + exchangeAmount = floorDiv(exchangeAmount, trxNum); if (exchangeAmount <= 0) { throw new ContractValidateException("Can not process the exchange!"); } diff --git a/actuator/src/main/java/org/tron/core/actuator/ShieldedTransferActuator.java b/actuator/src/main/java/org/tron/core/actuator/ShieldedTransferActuator.java index 284650f1ffb..2773dc07d26 100644 --- a/actuator/src/main/java/org/tron/core/actuator/ShieldedTransferActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/ShieldedTransferActuator.java @@ -96,9 +96,9 @@ public boolean execute(Object result) //adjust and verify total shielded pool value try { - Commons.adjustTotalShieldedPoolValue( - Math.addExact(Math.subtractExact(shieldedTransferContract.getToAmount(), - shieldedTransferContract.getFromAmount()), fee), dynamicStore); + Commons.adjustTotalShieldedPoolValue(addExact(subtractExact( + shieldedTransferContract.getToAmount(), + shieldedTransferContract.getFromAmount()), fee), dynamicStore); } catch (ArithmeticException | BalanceInsufficientException e) { logger.debug(e.getMessage(), e); ret.setStatus(0, code.FAILED); @@ -327,9 +327,11 @@ private void checkProof(List spendDescriptions, long totalShieldedPoolValue = dynamicStore .getTotalShieldedPoolValue(); try { - valueBalance = Math.addExact(Math.subtractExact(shieldedTransferContract.getToAmount(), + valueBalance = addExact(subtractExact( + shieldedTransferContract.getToAmount(), shieldedTransferContract.getFromAmount()), fee); - totalShieldedPoolValue = Math.subtractExact(totalShieldedPoolValue, valueBalance); + totalShieldedPoolValue = subtractExact( + totalShieldedPoolValue, valueBalance); } catch (ArithmeticException e) { logger.debug(e.getMessage(), e); throw new ZkProofValidateException(e.getMessage(), true); @@ -452,7 +454,7 @@ private void validateTransparent(ShieldedTransferContract shieldedTransferContra AccountCapsule toAccount = accountStore.get(toAddress); if (toAccount != null) { try { - Math.addExact(getZenBalance(toAccount), toAmount); + addExact(getZenBalance(toAccount), toAmount); } catch (ArithmeticException e) { logger.debug(e.getMessage(), e); throw new ContractValidateException(e.getMessage()); diff --git a/actuator/src/main/java/org/tron/core/actuator/TransferActuator.java b/actuator/src/main/java/org/tron/core/actuator/TransferActuator.java index 5e3d605aed7..a0deabf8f00 100755 --- a/actuator/src/main/java/org/tron/core/actuator/TransferActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/TransferActuator.java @@ -7,7 +7,6 @@ import java.util.Arrays; import java.util.Objects; import lombok.extern.slf4j.Slf4j; -import org.tron.common.utils.Commons; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; @@ -58,13 +57,13 @@ public boolean execute(Object object) throws ContractExeException { fee = fee + dynamicStore.getCreateNewAccountFeeInSystemContract(); } - Commons.adjustBalance(accountStore, ownerAddress, -(Math.addExact(fee, amount))); + adjustBalance(accountStore, ownerAddress, -(addExact(fee, amount))); if (dynamicStore.supportBlackHoleOptimization()) { dynamicStore.burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole(), fee); + adjustBalance(accountStore, accountStore.getBlackhole(), fee); } - Commons.adjustBalance(accountStore, toAddress, amount); + adjustBalance(accountStore, toAddress, amount); ret.setStatus(fee, code.SUCESS); } catch (BalanceInsufficientException | ArithmeticException | InvalidProtocolBufferException e) { logger.debug(e.getMessage(), e); @@ -156,7 +155,7 @@ public boolean validate() throws ContractValidateException { } } - if (balance < Math.addExact(amount, fee)) { + if (balance < addExact(amount, fee)) { logger.warn("Balance is not sufficient. Account: {}, balance: {}, amount: {}, fee: {}.", StringUtil.encode58Check(ownerAddress), balance, amount, fee); throw new ContractValidateException( @@ -164,7 +163,7 @@ public boolean validate() throws ContractValidateException { } if (toAccount != null) { - Math.addExact(toAccount.getBalance(), amount); + addExact(toAccount.getBalance(), amount); } } catch (ArithmeticException e) { logger.debug(e.getMessage(), e); diff --git a/actuator/src/main/java/org/tron/core/actuator/TransferAssetActuator.java b/actuator/src/main/java/org/tron/core/actuator/TransferAssetActuator.java index de2b2faec86..d93263055eb 100644 --- a/actuator/src/main/java/org/tron/core/actuator/TransferAssetActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/TransferAssetActuator.java @@ -83,11 +83,11 @@ public boolean execute(Object result) throws ContractExeException { .addAssetAmountV2(assetName.toByteArray(), amount, dynamicStore, assetIssueStore); accountStore.put(toAddress, toAccountCapsule); - Commons.adjustBalance(accountStore, ownerAccountCapsule, -fee); + adjustBalance(accountStore, ownerAccountCapsule, -fee); if (dynamicStore.supportBlackHoleOptimization()) { dynamicStore.burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole(), fee); + adjustBalance(accountStore, accountStore.getBlackhole(), fee); } ret.setStatus(fee, code.SUCESS); } catch (BalanceInsufficientException e) { @@ -177,7 +177,7 @@ public boolean validate() throws ContractValidateException { assetBalance = toAccount.getAsset(dynamicStore, ByteArray.toStr(assetName)); if (assetBalance != null) { try { - assetBalance = Math.addExact(assetBalance, amount); //check if overflow + assetBalance = addExact(assetBalance, amount); //check if overflow } catch (Exception e) { logger.debug(e.getMessage(), e); throw new ContractValidateException(e.getMessage()); diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index 79a09664180..2f2eed7fded 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -82,7 +82,7 @@ public boolean execute(Object result) throws ContractExeException { * ((double) (dynamicStore.getTotalNetLimit()) / dynamicStore.getTotalNetWeight())); transferUsage = (long) (receiverCapsule.getNetUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForBandwidth())); - transferUsage = Math.min(unDelegateMaxUsage, transferUsage); + transferUsage = min(unDelegateMaxUsage, transferUsage); receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForBandwidth(-unDelegateBalance); } @@ -105,7 +105,7 @@ public boolean execute(Object result) throws ContractExeException { * ((double) (dynamicStore.getTotalEnergyCurrentLimit()) / dynamicStore.getTotalEnergyWeight())); transferUsage = (long) (receiverCapsule.getEnergyUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForEnergy())); - transferUsage = Math.min(unDelegateMaxUsage, transferUsage); + transferUsage = min(unDelegateMaxUsage, transferUsage); receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForEnergy(-unDelegateBalance); } diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 08d0f5a8da5..42ddc65c745 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -1,9 +1,11 @@ package org.tron.core.actuator; -import static java.lang.Math.max; -import static java.lang.Math.min; import static org.apache.commons.lang3.ArrayUtils.getLength; import static org.apache.commons.lang3.ArrayUtils.isNotEmpty; +import static org.tron.common.math.Maths.addExact; +import static org.tron.common.math.Maths.floorDiv; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import com.google.protobuf.ByteString; @@ -124,9 +126,9 @@ public void validate(Object object) throws ContractValidateException { trx = context.getTrxCap().getInstance(); // If tx`s fee limit is set, use it to calc max energy limit for constant call if (isConstantCall && trx.getRawData().getFeeLimit() > 0) { - maxEnergyLimit = Math.min(maxEnergyLimit, trx.getRawData().getFeeLimit() + maxEnergyLimit = min(maxEnergyLimit, trx.getRawData().getFeeLimit() / context.getStoreFactory().getChainBaseManager() - .getDynamicPropertiesStore().getEnergyFee()); + .getDynamicPropertiesStore().getEnergyFee(), VMConfig.allowStrictMath2()); } blockCap = context.getBlockCap(); if ((VMConfig.allowTvmFreeze() || VMConfig.allowTvmFreezeV2()) @@ -563,8 +565,10 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi receipt.setCallerEnergyLeft(leftFrozenEnergy); } - long energyFromBalance = max(account.getBalance() - callValue, 0) / sunPerEnergy; - long availableEnergy = Math.addExact(leftFrozenEnergy, energyFromBalance); + long energyFromBalance = max(account.getBalance() - callValue, 0, + VMConfig.allowStrictMath2()) / sunPerEnergy; + long availableEnergy = addExact(leftFrozenEnergy, energyFromBalance, + VMConfig.allowStrictMath2()); long energyFromFeeLimit = feeLimit / sunPerEnergy; if (VMConfig.allowTvmFreezeV2()) { @@ -580,12 +584,13 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi receipt.setCallerEnergyWindowSizeV2(account.getWindowSizeV2(ENERGY)); account.setEnergyUsage( energyProcessor.increase(account, ENERGY, - account.getEnergyUsage(), min(leftFrozenEnergy, energyFromFeeLimit), now, now)); + account.getEnergyUsage(), min(leftFrozenEnergy, energyFromFeeLimit, + VMConfig.allowStrictMath2()), now, now)); receipt.setCallerEnergyMergedUsage(account.getEnergyUsage()); receipt.setCallerEnergyMergedWindowSize(account.getWindowSize(ENERGY)); rootRepository.updateAccount(account.createDbKey(), account); } - return min(availableEnergy, energyFromFeeLimit); + return min(availableEnergy, energyFromFeeLimit, VMConfig.allowStrictMath2()); } @@ -598,9 +603,10 @@ private long getAccountEnergyLimitWithFloatRatio(AccountCapsule account, long fe } // can change the calc way long leftEnergyFromFreeze = rootRepository.getAccountLeftEnergyFromFreeze(account); - callValue = max(callValue, 0); - long energyFromBalance = Math - .floorDiv(max(account.getBalance() - callValue, 0), sunPerEnergy); + boolean isStrict2 = VMConfig.allowStrictMath2(); + callValue = max(callValue, 0, isStrict2); + long energyFromBalance = floorDiv(max( + account.getBalance() - callValue, 0, isStrict2), sunPerEnergy, isStrict2); long energyFromFeeLimit; long totalBalanceForEnergyFreeze = account.getAllFrozenBalanceForEnergy(); @@ -619,13 +625,14 @@ private long getAccountEnergyLimitWithFloatRatio(AccountCapsule account, long fe .multiply(BigInteger.valueOf(feeLimit)) .divide(BigInteger.valueOf(totalBalanceForEnergyFreeze)).longValueExact(); } else { - energyFromFeeLimit = Math - .addExact(leftEnergyFromFreeze, - (feeLimit - leftBalanceForEnergyFreeze) / sunPerEnergy); + energyFromFeeLimit = addExact( + leftEnergyFromFreeze, (feeLimit - leftBalanceForEnergyFreeze) / sunPerEnergy, + VMConfig.allowStrictMath2()); } } - return min(Math.addExact(leftEnergyFromFreeze, energyFromBalance), energyFromFeeLimit); + return min(addExact(leftEnergyFromFreeze, energyFromBalance, + VMConfig.allowStrictMath2()), energyFromFeeLimit, VMConfig.allowStrictMath2()); } public long getTotalEnergyLimit(AccountCapsule creator, AccountCapsule caller, @@ -700,7 +707,8 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu long creatorEnergyLimit = 0; ContractCapsule contractCapsule = rootRepository .getContract(contract.getContractAddress().toByteArray()); - long consumeUserResourcePercent = contractCapsule.getConsumeUserResourcePercent(); + long consumeUserResourcePercent = contractCapsule.getConsumeUserResourcePercent( + VMConfig.allowStrictMath2()); long originEnergyLimit = contractCapsule.getOriginEnergyLimit(); if (originEnergyLimit < 0) { @@ -715,7 +723,8 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu } } if (consumeUserResourcePercent <= 0) { - creatorEnergyLimit = min(originEnergyLeft, originEnergyLimit); + creatorEnergyLimit = min(originEnergyLeft, originEnergyLimit, + VMConfig.allowStrictMath2()); } else { if (consumeUserResourcePercent < VMConstant.ONE_HUNDRED) { // creatorEnergyLimit = @@ -726,8 +735,8 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu BigInteger.valueOf(callerEnergyLimit) .multiply(BigInteger.valueOf(VMConstant.ONE_HUNDRED - consumeUserResourcePercent)) .divide(BigInteger.valueOf(consumeUserResourcePercent)).longValueExact(), - min(originEnergyLeft, originEnergyLimit) - ); + min(originEnergyLeft, originEnergyLimit, VMConfig.allowStrictMath2()), + VMConfig.allowStrictMath2()); } } if (VMConfig.allowTvmFreezeV2()) { @@ -748,7 +757,8 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu receipt.setOriginEnergyMergedWindowSize(creator.getWindowSize(ENERGY)); rootRepository.updateAccount(creator.createDbKey(), creator); } - return Math.addExact(callerEnergyLimit, creatorEnergyLimit); + return addExact(callerEnergyLimit, creatorEnergyLimit, + VMConfig.allowStrictMath2()); } private long getTotalEnergyLimitWithFloatRatio(AccountCapsule creator, AccountCapsule caller, @@ -764,13 +774,17 @@ private long getTotalEnergyLimitWithFloatRatio(AccountCapsule creator, AccountCa ContractCapsule contractCapsule = rootRepository .getContract(contract.getContractAddress().toByteArray()); - long consumeUserResourcePercent = contractCapsule.getConsumeUserResourcePercent(); + long consumeUserResourcePercent = contractCapsule.getConsumeUserResourcePercent( + VMConfig.allowStrictMath2()); if (creatorEnergyLimit * consumeUserResourcePercent > (VMConstant.ONE_HUNDRED - consumeUserResourcePercent) * callerEnergyLimit) { - return Math.floorDiv(callerEnergyLimit * VMConstant.ONE_HUNDRED, consumeUserResourcePercent); + return floorDiv( + callerEnergyLimit * VMConstant.ONE_HUNDRED, consumeUserResourcePercent, + VMConfig.allowStrictMath2()); } else { - return Math.addExact(callerEnergyLimit, creatorEnergyLimit); + return addExact(callerEnergyLimit, creatorEnergyLimit, + VMConfig.allowStrictMath2()); } } diff --git a/actuator/src/main/java/org/tron/core/actuator/WitnessCreateActuator.java b/actuator/src/main/java/org/tron/core/actuator/WitnessCreateActuator.java index ee223a32ffa..fc908a1713f 100755 --- a/actuator/src/main/java/org/tron/core/actuator/WitnessCreateActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/WitnessCreateActuator.java @@ -6,7 +6,6 @@ import com.google.protobuf.InvalidProtocolBufferException; import java.util.Objects; import lombok.extern.slf4j.Slf4j; -import org.tron.common.utils.Commons; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; @@ -140,12 +139,11 @@ private void createWitness(final WitnessCreateContract witnessCreateContract) } accountStore.put(accountCapsule.createDbKey(), accountCapsule); long cost = dynamicStore.getAccountUpgradeCost(); - Commons - .adjustBalance(accountStore, witnessCreateContract.getOwnerAddress().toByteArray(), -cost); + adjustBalance(accountStore, witnessCreateContract.getOwnerAddress().toByteArray(), -cost); if (dynamicStore.supportBlackHoleOptimization()) { dynamicStore.burnTrx(cost); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole(), +cost); + adjustBalance(accountStore, accountStore.getBlackhole(), +cost); } dynamicStore.addTotalCreateWitnessCost(cost); } diff --git a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java index 7044564b1e1..a34afa9d32e 100644 --- a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java @@ -16,6 +16,7 @@ package org.tron.core.utils; import static org.tron.common.crypto.Hash.sha3omit12; +import static org.tron.common.math.Maths.max; import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_COST_BASE_SIZE; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; @@ -270,7 +271,7 @@ public static long estimateConsumeBandWidthSize(DynamicPropertiesStore dps, long DelegateResourceContract.Builder builder2 = DelegateResourceContract.newBuilder() .setBalance(TRX_PRECISION); long builder2Size = builder2.build().getSerializedSize(); - long addSize = Math.max(builderSize - builder2Size, 0L); + long addSize = max(builderSize - builder2Size, 0L, dps.allowStrictMath2()); return DELEGATE_COST_BASE_SIZE + addSize; } diff --git a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java index 5c78fb89ffb..74dbaa741c3 100644 --- a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java +++ b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java @@ -1,5 +1,7 @@ package org.tron.core.vm; +import static org.tron.common.math.Maths.max; + import java.math.BigInteger; import org.tron.common.runtime.vm.DataWord; import org.tron.core.vm.config.VMConfig; @@ -248,7 +250,7 @@ public static long getMCopyCost(Program program) { int dstOffset = stack.peek().intValue(); int srcOffset = stack.get(stack.size() - 2).intValue(); - DataWord maxOffset = new DataWord(Math.max(dstOffset, srcOffset)); + DataWord maxOffset = new DataWord(max(dstOffset, srcOffset, VMConfig.allowStrictMath2())); return VERY_LOW_TIER + calcMemEnergy(oldMemSize, memNeeded(maxOffset, stack.get(stack.size() - 3)), stack.get(stack.size() - 3).longValueSafe(), Op.MCOPY); diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 79d08af1aad..53e2cba90d4 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -1,6 +1,8 @@ package org.tron.core.vm; import static java.util.Arrays.copyOfRange; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; import static org.tron.common.runtime.vm.DataWord.WORD_SIZE; import static org.tron.common.utils.BIUtil.addSafely; import static org.tron.common.utils.BIUtil.isLessThan; @@ -624,14 +626,17 @@ public long getEnergyForData(byte[] data) { int expLen = parseLen(data, 1); int modLen = parseLen(data, 2); - byte[] expHighBytes = parseBytes(data, addSafely(ARGS_OFFSET, baseLen), Math.min(expLen, 32)); + boolean allowStrictMath2 = VMConfig.allowStrictMath2(); - long multComplexity = getMultComplexity(Math.max(baseLen, modLen)); + byte[] expHighBytes = parseBytes(data, addSafely(ARGS_OFFSET, baseLen), min(expLen, 32, + allowStrictMath2)); + + long multComplexity = getMultComplexity(max(baseLen, modLen, allowStrictMath2)); long adjExpLen = getAdjustedExponentLength(expHighBytes, expLen); // use big numbers to stay safe in case of overflow BigInteger energy = BigInteger.valueOf(multComplexity) - .multiply(BigInteger.valueOf(Math.max(adjExpLen, 1))) + .multiply(BigInteger.valueOf(max(adjExpLen, 1, allowStrictMath2))) .divide(GQUAD_DIVISOR); return isLessThan(energy, BigInteger.valueOf(Long.MAX_VALUE)) ? energy.longValueExact() diff --git a/actuator/src/main/java/org/tron/core/vm/VMUtils.java b/actuator/src/main/java/org/tron/core/vm/VMUtils.java index 1df0e0e22f1..090c4c54898 100644 --- a/actuator/src/main/java/org/tron/core/vm/VMUtils.java +++ b/actuator/src/main/java/org/tron/core/vm/VMUtils.java @@ -2,6 +2,7 @@ import static java.lang.String.format; import static org.apache.commons.codec.binary.Base64.encodeBase64String; +import static org.tron.common.math.Maths.addExact; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -169,7 +170,7 @@ public static boolean validateForSmartContract(Repository deposit, byte[] ownerA "Validate InternalTransfer error, balance is not sufficient."); } - Math.addExact(toAccount.getBalance(), amount); + addExact(toAccount.getBalance(), amount, VMConfig.allowStrictMath2()); } catch (ArithmeticException e) { logger.debug(e.getMessage(), e); throw new ContractValidateException(e.getMessage()); @@ -230,7 +231,8 @@ public static boolean validateForSmartContract(Repository deposit, byte[] ownerA ByteArray.toStr(tokenIdWithoutLeadingZero)); if (assetBalance != null) { try { - assetBalance = Math.addExact(assetBalance, amount); //check if overflow + addExact(assetBalance, amount, + VMConfig.allowStrictMath2()); //check if overflow } catch (Exception e) { logger.debug(e.getMessage(), e); throw new ContractValidateException(e.getMessage()); diff --git a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java index 5c4acb31bae..508bedc34dc 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java +++ b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java @@ -42,6 +42,7 @@ public static void load(StoreFactory storeFactory) { VMConfig.initAllowEnergyAdjustment(ds.getAllowEnergyAdjustment()); VMConfig.initAllowStrictMath(ds.getAllowStrictMath()); VMConfig.initAllowTvmCancun(ds.getAllowTvmCancun()); + VMConfig.initAllowStrictMath2(ds.getConsensusLogicOptimization()); } } } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index bb0d4e8297c..164f9711a20 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -54,6 +54,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra throw new ContractValidateException("delegateBalance must be greater than or equal to 1 TRX"); } + boolean allowStrictMath2 = dynamicStore.allowStrictMath2(); switch (param.getResourceType()) { case BANDWIDTH: { BandwidthProcessor processor = new BandwidthProcessor(ChainBaseManager.getInstance()); @@ -62,7 +63,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra long netUsage = (long) (ownerCapsule.getNetUsage() * TRX_PRECISION * ((double) (repo.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); - long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage); + long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage, allowStrictMath2); if (ownerCapsule.getFrozenV2BalanceForBandwidth() - v2NetUsage < delegateBalance) { throw new ContractValidateException( @@ -78,7 +79,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) (repo.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); - long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage); + long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage, allowStrictMath2); if (ownerCapsule.getFrozenV2BalanceForEnergy() - v2EnergyUsage < delegateBalance) { throw new ContractValidateException( diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index d521e596e3e..fc95f23cc03 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -1,5 +1,6 @@ package org.tron.core.vm.nativecontract; +import static org.tron.common.math.Maths.min; import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; @@ -21,6 +22,7 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.store.DelegatedResourceAccountIndexStore; import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.nativecontract.param.UnDelegateResourceParam; import org.tron.core.vm.repository.Repository; @@ -115,7 +117,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { * dynamicStore.getTotalNetLimit() / repo.getTotalNetWeight()); transferUsage = (long) (receiverCapsule.getNetUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForBandwidth())); - transferUsage = Math.min(unDelegateMaxUsage, transferUsage); + transferUsage = min(unDelegateMaxUsage, transferUsage, VMConfig.allowStrictMath2()); receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForBandwidth(-unDelegateBalance); } @@ -139,7 +141,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { * dynamicStore.getTotalEnergyCurrentLimit() / repo.getTotalEnergyWeight()); transferUsage = (long) (receiverCapsule.getEnergyUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForEnergy())); - transferUsage = Math.min(unDelegateMaxUsage, transferUsage); + transferUsage = min(unDelegateMaxUsage, transferUsage, VMConfig.allowStrictMath2()); receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForEnergy(-unDelegateBalance); } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceProcessor.java index 211784d279b..2167635a28f 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceProcessor.java @@ -136,10 +136,12 @@ public long execute(UnfreezeBalanceParam param, Repository repo) { if (receiverCapsule != null) { switch (param.getResourceType()) { case BANDWIDTH: - receiverCapsule.safeAddAcquiredDelegatedFrozenBalanceForBandwidth(-unfreezeBalance); + receiverCapsule.safeAddAcquiredDelegatedFrozenBalanceForBandwidth(-unfreezeBalance, + VMConfig.allowStrictMath2()); break; case ENERGY: - receiverCapsule.safeAddAcquiredDelegatedFrozenBalanceForEnergy(-unfreezeBalance); + receiverCapsule.safeAddAcquiredDelegatedFrozenBalanceForEnergy(-unfreezeBalance, + VMConfig.allowStrictMath2()); break; default: //this should never happen diff --git a/actuator/src/main/java/org/tron/core/vm/program/Memory.java b/actuator/src/main/java/org/tron/core/vm/program/Memory.java index 8f263ca7344..70e4005a54a 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Memory.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Memory.java @@ -1,14 +1,16 @@ package org.tron.core.vm.program; -import static java.lang.Math.ceil; -import static java.lang.Math.min; import static java.lang.String.format; +import static org.tron.common.math.Maths.addExact; +import static org.tron.common.math.Maths.ceil; +import static org.tron.common.math.Maths.min; import static org.tron.common.utils.ByteUtil.EMPTY_BYTE_ARRAY; import static org.tron.common.utils.ByteUtil.oneByteToHexString; import java.util.LinkedList; import java.util.List; import org.tron.common.runtime.vm.DataWord; +import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.program.listener.ProgramListener; import org.tron.core.vm.program.listener.ProgramListenerAware; @@ -103,17 +105,17 @@ public void extend(int address, int size) { if (size <= 0) { return; } - - final int newSize = Math.addExact(address, size); + boolean allowStrictMath2 = VMConfig.allowStrictMath2(); + final int newSize = addExact(address, size, allowStrictMath2); int toAllocate = newSize - internalSize(); if (toAllocate > 0) { - addChunks((int) ceil((double) toAllocate / CHUNK_SIZE)); + addChunks((int) ceil((double) toAllocate / CHUNK_SIZE, allowStrictMath2)); } toAllocate = newSize - softSize; if (toAllocate > 0) { - toAllocate = (int) ceil((double) toAllocate / WORD_SIZE) * WORD_SIZE; - softSize = Math.addExact(softSize, toAllocate); + toAllocate = (int) ceil((double) toAllocate / WORD_SIZE, allowStrictMath2) * WORD_SIZE; + softSize = addExact(softSize, toAllocate, allowStrictMath2); if (programListener != null) { programListener.onMemoryExtend(toAllocate); @@ -192,7 +194,7 @@ public void copy(int destPos, int srcPos, int size) { private int captureMax(int chunkIndex, int chunkOffset, int size, byte[] src, int srcPos) { byte[] chunk = chunks.get(chunkIndex); - int toCapture = min(size, chunk.length - chunkOffset); + int toCapture = min(size, chunk.length - chunkOffset, VMConfig.allowStrictMath2()); System.arraycopy(src, srcPos, chunk, chunkOffset, toCapture); return toCapture; @@ -201,7 +203,7 @@ private int captureMax(int chunkIndex, int chunkOffset, int size, byte[] src, in private int grabMax(int chunkIndex, int chunkOffset, int size, byte[] dest, int destPos) { byte[] chunk = chunks.get(chunkIndex); - int toGrab = min(size, chunk.length - chunkOffset); + int toGrab = min(size, chunk.length - chunkOffset, VMConfig.allowStrictMath2()); System.arraycopy(chunk, chunkOffset, dest, destPos, toGrab); diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 9dda3ed6b7f..28e501feb78 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -1,12 +1,15 @@ package org.tron.core.vm.program; -import static java.lang.StrictMath.min; import static java.lang.String.format; import static org.apache.commons.lang3.ArrayUtils.EMPTY_BYTE_ARRAY; import static org.apache.commons.lang3.ArrayUtils.getLength; import static org.apache.commons.lang3.ArrayUtils.isEmpty; import static org.apache.commons.lang3.ArrayUtils.isNotEmpty; import static org.apache.commons.lang3.ArrayUtils.nullToEmpty; +import static org.tron.common.math.Maths.addExact; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; +import static org.tron.common.math.Maths.multiplyExact; import static org.tron.common.utils.ByteUtil.stripLeadingZeroes; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; @@ -159,11 +162,13 @@ public Program(byte[] ops, byte[] codeAddress, ProgramInvoke programInvoke, this.nonce = internalTransaction.getNonce(); } + @SuppressWarnings("unused") static String formatBinData(byte[] binData, int startPC) { StringBuilder ret = new StringBuilder(); for (int i = 0; i < binData.length; i += 16) { ret.append(Utils.align("" + Integer.toHexString(startPC + (i)) + ":", ' ', 8, false)); - ret.append(Hex.toHexString(binData, i, min(16, binData.length - i))).append('\n'); + ret.append(Hex.toHexString(binData, i, min(16, binData.length - i, + VMConfig.allowStrictMath2()))).append('\n'); } return ret.toString(); } @@ -633,7 +638,7 @@ private void withdrawRewardAndCancelVote(byte[] owner, Repository repo) { long balance = ownerCapsule.getBalance(); long allowance = ownerCapsule.getAllowance(); ownerCapsule.setInstance(ownerCapsule.getInstance().toBuilder() - .setBalance(Math.addExact(balance, allowance)) + .setBalance(addExact(balance, allowance, VMConfig.allowStrictMath2())) .setAllowance(0) .setLatestWithdrawTime(getTimestamp().longValue() * 1000) .build()); @@ -1231,7 +1236,8 @@ public DataWord getContractAddress() { public DataWord getBlockHash(int index) { if (index < this.getNumber().longValue() - && index >= Math.max(256, this.getNumber().longValue()) - 256) { + && index >= max(256, this.getNumber().longValue(), + VMConfig.allowStrictMath2()) - 256) { BlockCapsule blockCapsule = contractState.getBlockByNum(index); @@ -2155,11 +2161,13 @@ public boolean voteWitness(int witnessArrayOffset, int witnessArrayLength, try { VoteWitnessParam param = new VoteWitnessParam(); param.setVoterAddress(owner); - - byte[] witnessArrayData = memoryChunk(Math.addExact(witnessArrayOffset, DataWord.WORD_SIZE), - Math.multiplyExact(witnessArrayLength, DataWord.WORD_SIZE)); - byte[] amountArrayData = memoryChunk(Math.addExact(amountArrayOffset, DataWord.WORD_SIZE), - Math.multiplyExact(amountArrayLength, DataWord.WORD_SIZE)); + boolean allowStrictMath2 = VMConfig.allowStrictMath2(); + byte[] witnessArrayData = memoryChunk( + addExact(witnessArrayOffset, DataWord.WORD_SIZE, allowStrictMath2), + multiplyExact(witnessArrayLength, DataWord.WORD_SIZE, allowStrictMath2)); + byte[] amountArrayData = memoryChunk( + addExact(amountArrayOffset, DataWord.WORD_SIZE, allowStrictMath2), + multiplyExact(amountArrayLength, DataWord.WORD_SIZE, allowStrictMath2)); for (int i = 0; i < witnessArrayLength; i++) { DataWord witness = new DataWord(Arrays.copyOfRange(witnessArrayData, @@ -2235,7 +2243,8 @@ public long updateContextContractFactor() { VMConfig.getDynamicEnergyThreshold(), VMConfig.getDynamicEnergyIncreaseFactor(), VMConfig.getDynamicEnergyMaxFactor(), - VMConfig.allowStrictMath())) { + VMConfig.allowStrictMath(), + VMConfig.allowStrictMath2())) { contractState.updateContractState(getContextAddress(), contractStateCapsule ); } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 7fcfbe8ef78..321efb729b9 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -1,6 +1,8 @@ package org.tron.core.vm.repository; -import static java.lang.Long.max; +import static org.tron.common.math.Maths.addExact; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.round; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; @@ -187,7 +189,7 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { long newEnergyUsage = recover(energyUsage, latestConsumeTime, now, windowSize); - return max(energyLimit - newEnergyUsage, 0); // us + return max(energyLimit - newEnergyUsage, 0, VMConfig.allowStrictMath2()); // us } @Override @@ -709,7 +711,7 @@ public long addBalance(byte[] address, long value) { StringUtil.createReadableString(accountCapsule.createDbKey()) + " insufficient balance"); } - accountCapsule.setBalance(Math.addExact(balance, value)); + accountCapsule.setBalance(addExact(balance, value, VMConfig.allowStrictMath2())); Key key = Key.create(address); accountCache.put(key, Value.create(accountCapsule, accountCache.get(key).getType().addType(Type.DIRTY))); @@ -875,7 +877,7 @@ private long increase(long lastUsage, long usage, long lastTime, long now, long if (lastTime + windowSize > now) { long delta = now - lastTime; double decay = (windowSize - delta) / (double) windowSize; - averageLastUsage = Math.round(averageLastUsage * decay); + averageLastUsage = round(averageLastUsage * decay, VMConfig.allowStrictMath2()); } else { averageLastUsage = 0; } diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index 7bc760f9edf..753313afe43 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -1,5 +1,8 @@ package org.tron.core.vm.utils; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; + import java.util.List; import java.util.stream.Collectors; @@ -132,7 +135,8 @@ public static long queryAvailableUnfreezeV2Size(byte[] address, Repository repos long now = repository.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); int unfreezingV2Count = accountCapsule.getUnfreezingV2Count(now); - return Long.max(UnfreezeBalanceV2Actuator.getUNFREEZE_MAX_TIMES() - unfreezingV2Count, 0L); + return max(UnfreezeBalanceV2Actuator.getUNFREEZE_MAX_TIMES() - unfreezingV2Count, 0L, + VMConfig.allowStrictMath2()); } public static long queryDelegatableResource(byte[] address, long type, Repository repository) { @@ -140,6 +144,7 @@ public static long queryDelegatableResource(byte[] address, long type, Repositor return 0L; } + boolean allowStrictMath2 = VMConfig.allowStrictMath2(); AccountCapsule accountCapsule = repository.getAccount(address); if (accountCapsule == null) { return 0L; @@ -161,8 +166,8 @@ public static long queryDelegatableResource(byte[] address, long type, Repositor return frozenV2Resource; } - long v2NetUsage = getV2NetUsage(accountCapsule, usage); - return Math.max(0L, frozenV2Resource - v2NetUsage); + long v2NetUsage = getV2NetUsage(accountCapsule, usage, allowStrictMath2); + return max(0L, frozenV2Resource - v2NetUsage, allowStrictMath2); } if (type == 1) { @@ -181,8 +186,8 @@ public static long queryDelegatableResource(byte[] address, long type, Repositor return frozenV2Resource; } - long v2EnergyUsage = getV2EnergyUsage(accountCapsule, usage); - return Math.max(0L, frozenV2Resource - v2EnergyUsage); + long v2EnergyUsage = getV2EnergyUsage(accountCapsule, usage, allowStrictMath2); + return max(0L, frozenV2Resource - v2EnergyUsage, allowStrictMath2); } return 0L; @@ -218,7 +223,7 @@ public static Triple checkUndelegateResource(byte[] address, l return Triple.of(0L, 0L, 0L); } - amount = Math.min(amount, resourceLimit); + amount = min(amount, resourceLimit, VMConfig.allowStrictMath2()); if (resourceLimit <= usagePair.getLeft()) { return Triple.of(0L, amount, usagePair.getRight()); } @@ -238,20 +243,22 @@ private static List getTotalWithdrawList(List{@code b}. - */ - public static double pow(double a, double b, boolean useStrictMath) { - return useStrictMath ? StrictMathWrapper.pow(a, b) : MathWrapper.pow(a, b); - } -} diff --git a/chainbase/src/main/java/org/tron/common/utils/Commons.java b/chainbase/src/main/java/org/tron/common/utils/Commons.java index 55542d494b4..6bcff7ec6e9 100644 --- a/chainbase/src/main/java/org/tron/common/utils/Commons.java +++ b/chainbase/src/main/java/org/tron/common/utils/Commons.java @@ -1,5 +1,8 @@ package org.tron.common.utils; +import static org.tron.common.math.Maths.addExact; +import static org.tron.common.math.Maths.subtractExact; + import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.tron.common.parameter.CommonParameter; @@ -55,16 +58,18 @@ public static byte[] decodeFromBase58Check(String addressBase58) { return address; } - public static void adjustBalance(AccountStore accountStore, byte[] accountAddress, long amount) + public static void adjustBalance(AccountStore accountStore, byte[] accountAddress, long amount, + boolean useStrict) throws BalanceInsufficientException { AccountCapsule account = accountStore.getUnchecked(accountAddress); - adjustBalance(accountStore, account, amount); + adjustBalance(accountStore, account, amount, useStrict); } /** * judge balance. */ - public static void adjustBalance(AccountStore accountStore, AccountCapsule account, long amount) + public static void adjustBalance(AccountStore accountStore, AccountCapsule account, long amount, + boolean useStrict) throws BalanceInsufficientException { long balance = account.getBalance(); @@ -77,7 +82,7 @@ public static void adjustBalance(AccountStore accountStore, AccountCapsule accou String.format("%s insufficient balance, balance: %d, amount: %d", StringUtil.createReadableString(account.createDbKey()), balance, -amount)); } - account.setBalance(Math.addExact(balance, amount)); + account.setBalance(addExact(balance, amount, useStrict)); accountStore.put(account.getAddress().toByteArray(), account); } @@ -137,8 +142,9 @@ public static void adjustAssetBalanceV2(AccountCapsule account, String AssetID, public static void adjustTotalShieldedPoolValue(long valueBalance, DynamicPropertiesStore dynamicPropertiesStore) throws BalanceInsufficientException { - long totalShieldedPoolValue = Math - .subtractExact(dynamicPropertiesStore.getTotalShieldedPoolValue(), valueBalance); + long totalShieldedPoolValue = subtractExact( + dynamicPropertiesStore.getTotalShieldedPoolValue(), valueBalance, + dynamicPropertiesStore.allowStrictMath2()); if (totalShieldedPoolValue < 0) { throw new BalanceInsufficientException(String.format( "total shielded pool value can not below 0, actual: %d", totalShieldedPoolValue)); diff --git a/chainbase/src/main/java/org/tron/common/utils/ForkController.java b/chainbase/src/main/java/org/tron/common/utils/ForkController.java index 7cbac28e781..0a782b31e5b 100644 --- a/chainbase/src/main/java/org/tron/common/utils/ForkController.java +++ b/chainbase/src/main/java/org/tron/common/utils/ForkController.java @@ -1,5 +1,6 @@ package org.tron.common.utils; +import static org.tron.common.math.Maths.ceil; import static org.tron.common.utils.StringUtil.encode58Check; import com.google.common.collect.Maps; @@ -98,8 +99,8 @@ private boolean passNew(int version) { ++count; } } - return count >= Math - .ceil((double) versionEnum.getHardForkRate() * stats.length / 100); + return count >= ceil((double) versionEnum.getHardForkRate() * stats.length / 100, + manager.getDynamicPropertiesStore().allowStrictMath2()); } diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index b60fed63cda..26ee5bab34b 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -15,9 +15,23 @@ package org.tron.core.capsule; +import static org.tron.common.math.Maths.addExact; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.subtractExact; +import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; +import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_MS; +import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; +import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; + import com.google.common.collect.Maps; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; +import java.util.List; +import java.util.Map; +import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.tron.common.utils.ByteArray; @@ -27,8 +41,8 @@ import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.Account.AccountResource; import org.tron.protos.Protocol.Account.Builder; -import org.tron.protos.Protocol.Account.Frozen; import org.tron.protos.Protocol.Account.FreezeV2; +import org.tron.protos.Protocol.Account.Frozen; import org.tron.protos.Protocol.Account.UnFreezeV2; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Key; @@ -38,19 +52,6 @@ import org.tron.protos.contract.AccountContract.AccountCreateContract; import org.tron.protos.contract.AccountContract.AccountUpdateContract; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import static java.lang.Math.ceil; -import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; -import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_MS; -import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_PRECISION; -import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; -import static org.tron.protos.contract.Common.ResourceCode.ENERGY; -import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; -import static org.tron.protos.contract.Common.ResourceCode; - @Slf4j(topic = "capsule") public class AccountCapsule implements ProtoCapsule, Comparable { @@ -401,15 +402,18 @@ public void addAcquiredDelegatedFrozenV2BalanceForBandwidth(long balance) { this.account.getAcquiredDelegatedFrozenV2BalanceForBandwidth() + balance).build(); } - public void safeAddAcquiredDelegatedFrozenBalanceForBandwidth(long balance) { + public void safeAddAcquiredDelegatedFrozenBalanceForBandwidth(long balance, boolean useStrict) { this.account = this.account.toBuilder().setAcquiredDelegatedFrozenBalanceForBandwidth( - Math.max(0, this.account.getAcquiredDelegatedFrozenBalanceForBandwidth() + balance)) + max(0, this.account.getAcquiredDelegatedFrozenBalanceForBandwidth() + balance, + useStrict)) .build(); } - public void safeAddAcquiredDelegatedFrozenV2BalanceForBandwidth(long balance) { + @SuppressWarnings("unused") + public void safeAddAcquiredDelegatedFrozenV2BalanceForBandwidth(long balance, boolean useStrict) { this.account = this.account.toBuilder().setAcquiredDelegatedFrozenV2BalanceForBandwidth( - Math.max(0, this.account.getAcquiredDelegatedFrozenV2BalanceForBandwidth() + balance)) + max(0, this.account.getAcquiredDelegatedFrozenV2BalanceForBandwidth() + balance, + useStrict)) .build(); } @@ -496,10 +500,11 @@ public void addAcquiredDelegatedFrozenV2BalanceForEnergy(long balance) { this.account = this.account.toBuilder().setAccountResource(newAccountResource).build(); } - public void safeAddAcquiredDelegatedFrozenBalanceForEnergy(long balance) { + public void safeAddAcquiredDelegatedFrozenBalanceForEnergy(long balance, boolean useStrict) { AccountResource newAccountResource = getAccountResource().toBuilder() .setAcquiredDelegatedFrozenBalanceForEnergy( - Math.max(0, getAccountResource().getAcquiredDelegatedFrozenBalanceForEnergy() + balance)) + max(0, getAccountResource().getAcquiredDelegatedFrozenBalanceForEnergy() + balance, + useStrict)) .build(); this.account = this.account.toBuilder() @@ -507,10 +512,11 @@ public void safeAddAcquiredDelegatedFrozenBalanceForEnergy(long balance) { .build(); } - public void safeAddAcquiredDelegatedFrozenV2BalanceForEnergy(long balance) { + @SuppressWarnings("unused") + public void safeAddAcquiredDelegatedFrozenV2BalanceForEnergy(long balance, boolean useStrict) { AccountResource newAccountResource = getAccountResource().toBuilder() - .setAcquiredDelegatedFrozenV2BalanceForEnergy(Math.max(0, getAccountResource() - .getAcquiredDelegatedFrozenV2BalanceForEnergy() + balance)).build(); + .setAcquiredDelegatedFrozenV2BalanceForEnergy(max(0, getAccountResource() + .getAcquiredDelegatedFrozenV2BalanceForEnergy() + balance, useStrict)).build(); this.account = this.account.toBuilder().setAccountResource(newAccountResource).build(); } @@ -711,14 +717,15 @@ public boolean assetBalanceEnoughV2(byte[] key, long amount, return amount > 0 && null != currentAmount && amount <= currentAmount; } - public boolean addAssetAmount(byte[] key, long amount) { + public boolean addAssetAmount(byte[] key, long amount, boolean useStrict) { Map assetMap = this.account.getAssetMap(); String nameKey = ByteArray.toStr(key); Long currentAmount = assetMap.get(nameKey); if (currentAmount == null) { currentAmount = 0L; } - this.account = this.account.toBuilder().putAsset(nameKey, Math.addExact(currentAmount, amount)) + this.account = this.account.toBuilder().putAsset(nameKey, + addExact(currentAmount, amount, useStrict)) .build(); return true; } @@ -726,6 +733,7 @@ public boolean addAssetAmount(byte[] key, long amount) { public boolean addAssetAmountV2(byte[] key, long amount, DynamicPropertiesStore dynamicPropertiesStore, AssetIssueStore assetIssueStore) { importAsset(key); + boolean useStrict2 = dynamicPropertiesStore.allowStrictMath2(); //key is token name if (dynamicPropertiesStore.getAllowSameTokenName() == 0) { Map assetMap = this.account.getAssetMap(); @@ -737,8 +745,8 @@ public boolean addAssetAmountV2(byte[] key, long amount, currentAmount = 0L; } this.account = this.account.toBuilder() - .putAsset(nameKey, Math.addExact(currentAmount, amount)) - .putAssetV2(tokenID, Math.addExact(currentAmount, amount)) + .putAsset(nameKey, addExact(currentAmount, amount, useStrict2)) + .putAssetV2(tokenID, addExact(currentAmount, amount, useStrict2)) .build(); } //key is token id @@ -750,19 +758,19 @@ public boolean addAssetAmountV2(byte[] key, long amount, currentAmount = 0L; } this.account = this.account.toBuilder() - .putAssetV2(tokenIDStr, Math.addExact(currentAmount, amount)) + .putAssetV2(tokenIDStr, addExact(currentAmount, amount, useStrict2)) .build(); } return true; } - public boolean reduceAssetAmount(byte[] key, long amount) { + public boolean reduceAssetAmount(byte[] key, long amount, boolean useStrict2) { Map assetMap = this.account.getAssetMap(); String nameKey = ByteArray.toStr(key); Long currentAmount = assetMap.get(nameKey); if (amount > 0 && null != currentAmount && amount <= currentAmount) { this.account = this.account.toBuilder() - .putAsset(nameKey, Math.subtractExact(currentAmount, amount)).build(); + .putAsset(nameKey, subtractExact(currentAmount, amount, useStrict2)).build(); return true; } @@ -773,6 +781,7 @@ public boolean reduceAssetAmountV2(byte[] key, long amount, DynamicPropertiesStore dynamicPropertiesStore, AssetIssueStore assetIssueStore) { importAsset(key); //key is token name + boolean useStrict2 = dynamicPropertiesStore.allowStrictMath2(); if (dynamicPropertiesStore.getAllowSameTokenName() == 0) { Map assetMap = this.account.getAssetMap(); AssetIssueCapsule assetIssueCapsule = assetIssueStore.get(key); @@ -781,8 +790,8 @@ public boolean reduceAssetAmountV2(byte[] key, long amount, Long currentAmount = assetMap.get(nameKey); if (amount > 0 && null != currentAmount && amount <= currentAmount) { this.account = this.account.toBuilder() - .putAsset(nameKey, Math.subtractExact(currentAmount, amount)) - .putAssetV2(tokenID, Math.subtractExact(currentAmount, amount)) + .putAsset(nameKey, subtractExact(currentAmount, amount, useStrict2)) + .putAssetV2(tokenID, subtractExact(currentAmount, amount, useStrict2)) .build(); return true; } @@ -794,7 +803,7 @@ public boolean reduceAssetAmountV2(byte[] key, long amount, Long currentAmount = assetMapV2.get(tokenID); if (amount > 0 && null != currentAmount && amount <= currentAmount) { this.account = this.account.toBuilder() - .putAssetV2(tokenID, Math.subtractExact(currentAmount, amount)) + .putAssetV2(tokenID, subtractExact(currentAmount, amount, useStrict2)) .build(); return true; } diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java index cb6292ed290..be73a338b90 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java @@ -15,8 +15,8 @@ package org.tron.core.capsule; -import static java.lang.Math.max; -import static java.lang.Math.min; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; import com.google.protobuf.Any; import com.google.protobuf.ByteString; @@ -109,9 +109,9 @@ public byte[] getOriginAddress() { return this.smartContract.getOriginAddress().toByteArray(); } - public long getConsumeUserResourcePercent() { + public long getConsumeUserResourcePercent(boolean useStrictMath2) { long percent = this.smartContract.getConsumeUserResourcePercent(); - return max(0, min(percent, Constant.ONE_HUNDRED)); + return max(0, min(percent, Constant.ONE_HUNDRED, useStrictMath2), useStrictMath2); } public long getOriginEnergyLimit() { diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java index 8ebb86ea332..8deeebaa758 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java @@ -1,11 +1,13 @@ package org.tron.core.capsule; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; +import static org.tron.common.math.Maths.pow; import static org.tron.core.Constant.DYNAMIC_ENERGY_DECREASE_DIVISION; import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; import com.google.protobuf.InvalidProtocolBufferException; import lombok.extern.slf4j.Slf4j; -import org.tron.common.math.Maths; import org.tron.core.store.DynamicPropertiesStore; import org.tron.protos.contract.SmartContractOuterClass; import org.tron.protos.contract.SmartContractOuterClass.ContractState; @@ -79,12 +81,14 @@ public boolean catchUpToCycle(DynamicPropertiesStore dps) { dps.getDynamicEnergyThreshold(), dps.getDynamicEnergyIncreaseFactor(), dps.getDynamicEnergyMaxFactor(), - dps.allowStrictMath() + dps.allowStrictMath(), + dps.allowStrictMath2() ); } public boolean catchUpToCycle( - long newCycle, long threshold, long increaseFactor, long maxFactor, boolean useStrictMath + long newCycle, long threshold, long increaseFactor, long maxFactor, + boolean useStrictMath, boolean useStrictMath2 ) { long lastCycle = getUpdateCycle(); @@ -108,9 +112,10 @@ public boolean catchUpToCycle( double increasePercent = 1 + (double) increaseFactor / precisionFactor; this.contractState = ContractState.newBuilder() .setUpdateCycle(lastCycle) - .setEnergyFactor(Math.min( + .setEnergyFactor(min( maxFactor, - (long) ((getEnergyFactor() + precisionFactor) * increasePercent) - precisionFactor)) + (long) ((getEnergyFactor() + precisionFactor) * increasePercent) - precisionFactor, + useStrictMath2)) .build(); } @@ -121,7 +126,7 @@ public boolean catchUpToCycle( } // Calc the decrease percent (decrease factor [75% ~ 100%]) - double decreasePercent = Maths.pow( + double decreasePercent = pow( 1 - (double) increaseFactor / DYNAMIC_ENERGY_DECREASE_DIVISION / precisionFactor, cycleCount, useStrictMath ); @@ -132,9 +137,10 @@ public boolean catchUpToCycle( // That means we merge this special case to normal cases) this.contractState = ContractState.newBuilder() .setUpdateCycle(newCycle) - .setEnergyFactor(Math.max( + .setEnergyFactor(max( 0, - (long) ((getEnergyFactor() + precisionFactor) * decreasePercent) - precisionFactor)) + (long) ((getEnergyFactor() + precisionFactor) * decreasePercent) - precisionFactor, + useStrictMath2)) .build(); return true; diff --git a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index 7d003b6b0e4..29d80cebe3f 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -1,5 +1,8 @@ package org.tron.core.capsule; +import static org.tron.common.math.Maths.min; +import static org.tron.common.math.Maths.multiplyExact; + import java.util.Objects; import lombok.Getter; import lombok.Setter; @@ -215,12 +218,13 @@ public void payEnergyBill(DynamicPropertiesStore dynamicPropertiesStore, receipt.getEnergyUsageTotal(), receipt.getResult(), energyProcessor, now); return; } + boolean useStrict2 = dynamicPropertiesStore.allowStrictMath2(); if ((!Objects.isNull(origin)) && caller.getAddress().equals(origin.getAddress())) { payEnergyBill(dynamicPropertiesStore, accountStore, forkController, caller, receipt.getEnergyUsageTotal(), receipt.getResult(), energyProcessor, now); } else { - long originUsage = Math.multiplyExact(receipt.getEnergyUsageTotal(), percent) / 100; + long originUsage = multiplyExact(receipt.getEnergyUsageTotal(), percent, useStrict2) / 100; originUsage = getOriginUsage(dynamicPropertiesStore, origin, originEnergyLimit, energyProcessor, originUsage); @@ -236,17 +240,18 @@ public void payEnergyBill(DynamicPropertiesStore dynamicPropertiesStore, private long getOriginUsage(DynamicPropertiesStore dynamicPropertiesStore, AccountCapsule origin, long originEnergyLimit, EnergyProcessor energyProcessor, long originUsage) { - + boolean useStrict2 = dynamicPropertiesStore.allowStrictMath2(); if (dynamicPropertiesStore.getAllowTvmFreeze() == 1 || dynamicPropertiesStore.supportUnfreezeDelay()) { - return Math.min(originUsage, Math.min(originEnergyLeft, originEnergyLimit)); + return min(originUsage, min(originEnergyLeft, originEnergyLimit, useStrict2), useStrict2); } if (checkForEnergyLimit(dynamicPropertiesStore)) { - return Math.min(originUsage, - Math.min(energyProcessor.getAccountLeftEnergyFromFreeze(origin), originEnergyLimit)); + return min(originUsage, + min(energyProcessor.getAccountLeftEnergyFromFreeze(origin), originEnergyLimit, + useStrict2), useStrict2); } - return Math.min(originUsage, energyProcessor.getAccountLeftEnergyFromFreeze(origin)); + return min(originUsage, energyProcessor.getAccountLeftEnergyFromFreeze(origin), useStrict2); } private void payEnergyBill( @@ -301,7 +306,7 @@ private void payEnergyBill( } else { //send to blackHole Commons.adjustBalance(accountStore, accountStore.getBlackhole(), - energyFee); + energyFee, dynamicPropertiesStore.allowStrictMath2()); } } diff --git a/chainbase/src/main/java/org/tron/core/capsule/utils/MarketUtils.java b/chainbase/src/main/java/org/tron/core/capsule/utils/MarketUtils.java index f345a96df81..fb86cb1f456 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/utils/MarketUtils.java +++ b/chainbase/src/main/java/org/tron/core/capsule/utils/MarketUtils.java @@ -15,6 +15,10 @@ package org.tron.core.capsule.utils; +import static org.tron.common.math.Maths.addExact; +import static org.tron.common.math.Maths.floorDiv; +import static org.tron.common.math.Maths.multiplyExact; + import com.google.protobuf.ByteString; import java.math.BigInteger; import java.util.Arrays; @@ -230,8 +234,8 @@ public static byte[] createPairKey(byte[] sellTokenId, byte[] buyTokenId) { public static int comparePrice(long price1SellQuantity, long price1BuyQuantity, long price2SellQuantity, long price2BuyQuantity) { try { - return Long.compare(Math.multiplyExact(price1BuyQuantity, price2SellQuantity), - Math.multiplyExact(price2BuyQuantity, price1SellQuantity)); + return Long.compare(multiplyExact(price1BuyQuantity, price2SellQuantity, true), + multiplyExact(price2BuyQuantity, price1SellQuantity, true)); } catch (ArithmeticException ex) { // do nothing here, because we will use BigInteger to compute again @@ -246,25 +250,6 @@ public static int comparePrice(long price1SellQuantity, long price1BuyQuantity, .compareTo(price2BuyQuantityBI.multiply(price1SellQuantityBI)); } - /** - * ex. - * for sellToken is A, buyToken is TRX. - * price_A_maker * sellQuantity_maker = Price_TRX * buyQuantity_maker - * ==> price_A_maker = Price_TRX * buyQuantity_maker/sellQuantity_maker - * - * price_A_maker_1 < price_A_maker_2 - * ==> buyQuantity_maker_1/sellQuantity_maker_1 < buyQuantity_maker_2/sellQuantity_maker_2 - * ==> buyQuantity_maker_1*sellQuantity_maker_2 < buyQuantity_maker_2 * sellQuantity_maker_1 - */ - public static int comparePrice(MarketPrice price1, MarketPrice price2) { - return comparePrice(price1.getSellTokenQuantity(), price1.getBuyTokenQuantity(), - price2.getSellTokenQuantity(), price2.getBuyTokenQuantity()); - } - - public static boolean isLowerPrice(MarketPrice price1, MarketPrice price2) { - return comparePrice(price1, price2) == -1; - } - /** * if takerPrice >= makerPrice, return True * note: here are two different token pairs @@ -297,10 +282,10 @@ public static void updateOrderState(MarketOrderCapsule orderCapsule, } } - public static long multiplyAndDivide(long a, long b, long c) { + public static long multiplyAndDivide(long a, long b, long c, boolean useStrictMath2) { try { - long tmp = Math.multiplyExact(a, b); - return Math.floorDiv(tmp, c); + long tmp = multiplyExact(a, b, useStrictMath2); + return floorDiv(tmp, c, useStrictMath2); } catch (ArithmeticException ex) { // do nothing here, because we will use BigInteger to compute again } @@ -320,8 +305,9 @@ public static void returnSellTokenRemain(MarketOrderCapsule orderCapsule, byte[] sellTokenId = orderCapsule.getSellTokenId(); long sellTokenQuantityRemain = orderCapsule.getSellTokenQuantityRemain(); if (Arrays.equals(sellTokenId, "_".getBytes())) { - accountCapsule.setBalance(Math.addExact( - accountCapsule.getBalance(), sellTokenQuantityRemain)); + accountCapsule.setBalance(addExact( + accountCapsule.getBalance(), sellTokenQuantityRemain, + dynamicStore.allowStrictMath2())); } else { accountCapsule .addAssetAmountV2(sellTokenId, sellTokenQuantityRemain, dynamicStore, assetIssueStore); diff --git a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java index 5cd0f796374..ef326977451 100644 --- a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java @@ -1,6 +1,7 @@ package org.tron.core.db; -import static java.lang.Long.max; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; @@ -78,11 +79,10 @@ public void updateAdaptiveTotalEnergyLimit() { / AdaptiveResourceLimitConstants.EXPAND_RATE_DENOMINATOR; // logger.info(totalEnergyAverageUsage + "<" + targetTotalEnergyLimit + "\n" + result); } - - result = Math.min( - Math.max(result, totalEnergyLimit), - totalEnergyLimit * dynamicPropertiesStore.getAdaptiveResourceLimitMultiplier() - ); + boolean useStrict2 = dynamicPropertiesStore.allowStrictMath2(); + result = min(max(result, totalEnergyLimit, useStrict2), + totalEnergyLimit * dynamicPropertiesStore.getAdaptiveResourceLimitMultiplier(), + useStrict2); dynamicPropertiesStore.saveTotalEnergyCurrentLimit(result); logger.debug("Adjust totalEnergyCurrentLimit, old: {}, new: {}.", @@ -178,7 +178,7 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { long newEnergyUsage = recovery(accountCapsule, ENERGY, energyUsage, latestConsumeTime, now); - return max(energyLimit - newEnergyUsage, 0); // us + return max(energyLimit - newEnergyUsage, 0, dynamicPropertiesStore.allowStrictMath2()); // us } private long getHeadSlot() { diff --git a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java index c1875408850..9b446079337 100644 --- a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java @@ -1,5 +1,7 @@ package org.tron.core.db; +import static org.tron.common.math.Maths.min; +import static org.tron.common.math.Maths.round; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_PRECISION; @@ -51,7 +53,8 @@ protected long increase(long lastUsage, long usage, long lastTime, long now, lon if (lastTime + windowSize > now) { long delta = now - lastTime; double decay = (windowSize - delta) / (double) windowSize; - averageLastUsage = Math.round(averageLastUsage * decay); + averageLastUsage = round(averageLastUsage * decay, + dynamicPropertiesStore.allowStrictMath2()); } else { averageLastUsage = 0; } @@ -79,7 +82,8 @@ public long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, if (lastTime + oldWindowSize > now) { long delta = now - lastTime; double decay = (oldWindowSize - delta) / (double) oldWindowSize; - averageLastUsage = Math.round(averageLastUsage * decay); + averageLastUsage = round(averageLastUsage * decay, + dynamicPropertiesStore.allowStrictMath2()); } else { averageLastUsage = 0; } @@ -111,7 +115,8 @@ public long increaseV2(AccountCapsule accountCapsule, ResourceCode resourceCode, if (lastTime + oldWindowSize > now) { long delta = now - lastTime; double decay = (oldWindowSize - delta) / (double) oldWindowSize; - averageLastUsage = Math.round(averageLastUsage * decay); + averageLastUsage = round(averageLastUsage * decay, + dynamicPropertiesStore.allowStrictMath2()); } else { averageLastUsage = 0; } @@ -127,7 +132,8 @@ public long increaseV2(AccountCapsule accountCapsule, ResourceCode resourceCode, long remainWindowSize = oldWindowSizeV2 - (now - lastTime) * WINDOW_SIZE_PRECISION; long newWindowSize = divideCeil( remainUsage * remainWindowSize + usage * this.windowSize * WINDOW_SIZE_PRECISION, newUsage); - newWindowSize = Math.min(newWindowSize, this.windowSize * WINDOW_SIZE_PRECISION); + newWindowSize = min(newWindowSize, this.windowSize * WINDOW_SIZE_PRECISION, + dynamicPropertiesStore.allowStrictMath2()); accountCapsule.setNewWindowSizeV2(resourceCode, newWindowSize); return newUsage; } @@ -189,7 +195,8 @@ public void unDelegateIncreaseV2(AccountCapsule owner, final AccountCapsule rece divideCeil( ownerUsage * remainOwnerWindowSizeV2 + transferUsage * remainReceiverWindowSizeV2, newOwnerUsage); - newOwnerWindowSize = Math.min(newOwnerWindowSize, this.windowSize * WINDOW_SIZE_PRECISION); + newOwnerWindowSize = min(newOwnerWindowSize, this.windowSize * WINDOW_SIZE_PRECISION, + dynamicPropertiesStore.allowStrictMath2()); owner.setNewWindowSizeV2(resourceCode, newOwnerWindowSize); owner.setUsage(resourceCode, newOwnerUsage); owner.setLatestTime(resourceCode, now); @@ -216,13 +223,15 @@ protected boolean consumeFeeForBandwidth(AccountCapsule accountCapsule, long fee try { long latestOperationTime = dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); accountCapsule.setLatestOperationTime(latestOperationTime); - Commons.adjustBalance(accountStore, accountCapsule, -fee); + Commons.adjustBalance(accountStore, accountCapsule, -fee, + dynamicPropertiesStore.allowStrictMath2()); if (dynamicPropertiesStore.supportTransactionFeePool()) { dynamicPropertiesStore.addTransactionFeePool(fee); } else if (dynamicPropertiesStore.supportBlackHoleOptimization()) { dynamicPropertiesStore.burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole().createDbKey(), +fee); + Commons.adjustBalance(accountStore, accountStore.getBlackhole().createDbKey(), +fee, + dynamicPropertiesStore.allowStrictMath2()); } return true; @@ -235,11 +244,13 @@ protected boolean consumeFeeForNewAccount(AccountCapsule accountCapsule, long fe try { long latestOperationTime = dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); accountCapsule.setLatestOperationTime(latestOperationTime); - Commons.adjustBalance(accountStore, accountCapsule, -fee); + Commons.adjustBalance(accountStore, accountCapsule, -fee, + dynamicPropertiesStore.allowStrictMath2()); if (dynamicPropertiesStore.supportBlackHoleOptimization()) { dynamicPropertiesStore.burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole().createDbKey(), +fee); + Commons.adjustBalance(accountStore, accountStore.getBlackhole().createDbKey(), +fee, + dynamicPropertiesStore.allowStrictMath2()); } return true; diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java index e9c4feb7e18..114197a3407 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java @@ -1,5 +1,7 @@ package org.tron.core.db; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; import static org.tron.common.runtime.InternalTransaction.TrxType.TRX_CONTRACT_CALL_TYPE; import static org.tron.common.runtime.InternalTransaction.TrxType.TRX_CONTRACT_CREATION_TYPE; import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_PRECISION; @@ -244,9 +246,11 @@ public void pay() throws BalanceInsufficientException { callerAccount = callContract.getOwnerAddress().toByteArray(); originAccount = contractCapsule.getOriginAddress(); - percent = Math - .max(Constant.ONE_HUNDRED - contractCapsule.getConsumeUserResourcePercent(), 0); - percent = Math.min(percent, Constant.ONE_HUNDRED); + boolean useStrictMath2 = dynamicPropertiesStore.allowStrictMath2(); + percent = max(Constant.ONE_HUNDRED - contractCapsule.getConsumeUserResourcePercent( + useStrictMath2), 0, useStrictMath2); + percent = min(percent, Constant.ONE_HUNDRED, + useStrictMath2); originEnergyLimit = contractCapsule.getOriginEnergyLimit(); break; default: @@ -299,7 +303,7 @@ private void resetAccountUsage(AccountCapsule accountCap, // If area merging happened during suicide, use the current window size long newSize = mergedSize == currentSize ? size : currentSize; // Calc new usage by fixed x-axes - long newUsage = Long.max(0, newArea / newSize); + long newUsage = max(0, newArea / newSize, dynamicPropertiesStore.allowStrictMath2()); // Reset account usage and window size accountCap.setEnergyUsage(newUsage); accountCap.setNewWindowSize(ENERGY, newUsage == 0 ? 0L : newSize); @@ -316,7 +320,7 @@ private void resetAccountUsageV2(AccountCapsule accountCap, long newSize = mergedSize == currentSize ? size : currentSize; long newSize2 = mergedSize == currentSize ? size2 : currentSize2; // Calc new usage by fixed x-axes - long newUsage = Long.max(0, newArea / newSize); + long newUsage = max(0, newArea / newSize, dynamicPropertiesStore.allowStrictMath2()); // Reset account usage and window size accountCap.setEnergyUsage(newUsage); accountCap.setNewWindowSizeV2(ENERGY, newUsage == 0 ? 0L : newSize2); diff --git a/chainbase/src/main/java/org/tron/core/service/MortgageService.java b/chainbase/src/main/java/org/tron/core/service/MortgageService.java index 29ea32208eb..233c142f053 100644 --- a/chainbase/src/main/java/org/tron/core/service/MortgageService.java +++ b/chainbase/src/main/java/org/tron/core/service/MortgageService.java @@ -1,5 +1,7 @@ package org.tron.core.service; +import static org.tron.common.math.Maths.min; + import java.math.BigInteger; import java.util.List; import java.util.stream.Collectors; @@ -205,7 +207,8 @@ private long computeReward(long beginCycle, long endCycle, AccountCapsule accoun .map(vote -> new Pair<>(vote.getVoteAddress().toByteArray(), vote.getVoteCount())) .collect(Collectors.toList()); if (beginCycle < newAlgorithmCycle) { - long oldEndCycle = Math.min(endCycle, newAlgorithmCycle); + long oldEndCycle = min(endCycle, newAlgorithmCycle, + dynamicPropertiesStore.allowStrictMath2()); reward = getOldReward(beginCycle, oldEndCycle, srAddresses); beginCycle = oldEndCycle; } diff --git a/chainbase/src/main/java/org/tron/core/store/AssetIssueStore.java b/chainbase/src/main/java/org/tron/core/store/AssetIssueStore.java index d38a5f0677e..4f69a6c3c66 100644 --- a/chainbase/src/main/java/org/tron/core/store/AssetIssueStore.java +++ b/chainbase/src/main/java/org/tron/core/store/AssetIssueStore.java @@ -43,13 +43,6 @@ private List getAssetIssuesPaginated(List return null; } -// return Streams.stream(iterator()) -// .map(Entry::getValue) -// .sorted(Comparator.comparing(a -> a.getName().toStringUtf8(), String::compareTo)) -// .skip(offset) -// .limit(Math.min(limit, ASSET_ISSUE_COUNT_LIMIT_MAX)) -// .collect(Collectors.toList()); - if (assetIssueList.size() <= offset) { return null; } diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 399c3a6b292..8d1fb19ea2b 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -1,5 +1,6 @@ package org.tron.core.store; +import static org.tron.common.math.Maths.max; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; @@ -2245,7 +2246,7 @@ public void addTotalNetWeight(long amount) { long totalNetWeight = getTotalNetWeight(); totalNetWeight += amount; if (allowNewReward()) { - totalNetWeight = Math.max(0, totalNetWeight); + totalNetWeight = max(0, totalNetWeight, allowStrictMath2()); } saveTotalNetWeight(totalNetWeight); } @@ -2258,7 +2259,7 @@ public void addTotalEnergyWeight(long amount) { long totalEnergyWeight = getTotalEnergyWeight(); totalEnergyWeight += amount; if (allowNewReward()) { - totalEnergyWeight = Math.max(0, totalEnergyWeight); + totalEnergyWeight = max(0, totalEnergyWeight, allowStrictMath2()); } saveTotalEnergyWeight(totalEnergyWeight); } @@ -2271,7 +2272,7 @@ public void addTotalTronPowerWeight(long amount) { long totalWeight = getTotalTronPowerWeight(); totalWeight += amount; if (allowNewReward()) { - totalWeight = Math.max(0, totalWeight); + totalWeight = max(0, totalWeight, allowStrictMath2()); } saveTotalTronPowerWeight(totalWeight); } @@ -2896,6 +2897,10 @@ public boolean allowStrictMath() { return getAllowStrictMath() == 1L; } + public boolean allowStrictMath2() { + return this.allowConsensusLogicOptimization(); + } + public void saveConsensusLogicOptimization(long value) { this.put(CONSENSUS_LOGIC_OPTIMIZATION, new BytesCapsule(ByteArray.fromLong(value))); diff --git a/common/src/main/java/org/tron/common/math/MathWrapper.java b/common/src/main/java/org/tron/common/math/MathWrapper.java index 519dafb9d42..758a0f18370 100644 --- a/common/src/main/java/org/tron/common/math/MathWrapper.java +++ b/common/src/main/java/org/tron/common/math/MathWrapper.java @@ -11,4 +11,68 @@ public class MathWrapper { public static double pow(double a, double b) { return Math.pow(a, b); } + + public static long addExact(long x, long y) { + return Math.addExact(x, y); + } + + public static int addExact(int x, int y) { + return Math.addExact(x, y); + } + + public static long floorDiv(long x, long y) { + return Math.floorDiv(x, y); + } + + public static int multiplyExact(int x, int y) { + return Math.multiplyExact(x, y); + } + + public static long multiplyExact(long x, long y) { + return Math.multiplyExact(x, y); + } + + public static long subtractExact(long x, long y) { + return Math.subtractExact(x, y); + } + + public static int min(int a, int b) { + return Math.min(a, b); + } + + public static long min(long a, long b) { + return Math.min(a, b); + } + + public static int max(int a, int b) { + return Math.max(a, b); + } + + public static long max(long a, long b) { + return Math.max(a, b); + } + + public static int round(float a) { + return Math.round(a); + } + + public static long round(double a) { + return Math.round(a); + } + + public static double ceil(double a) { + return Math.ceil(a); + } + + public static double signum(double a) { + return Math.signum(a); + } + + public static double random() { + return Math.random(); + } + + public static long abs(long a) { + return Math.abs(a); + } } diff --git a/common/src/main/java/org/tron/common/math/Maths.java b/common/src/main/java/org/tron/common/math/Maths.java new file mode 100644 index 00000000000..f0503cee2e4 --- /dev/null +++ b/common/src/main/java/org/tron/common/math/Maths.java @@ -0,0 +1,92 @@ +package org.tron.common.math; + +/** + * This class is deprecated and should not be used in new code, + * for cross-platform consistency, please use {@link StrictMathWrapper} instead, + * especially for floating-point calculations. + */ +@Deprecated +public class Maths { + + /** + * Returns the value of the first argument raised to the power of the second argument. + * @param a the base. + * @param b the exponent. + * @return the value {@code a}{@code b}. + */ + public static double pow(double a, double b, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.pow(a, b) : MathWrapper.pow(a, b); + } + + /** + * Adds two integers together, checking for overflow. + * @param x the first value. + * @param y the second value. + * @return the sum of {@code x} and {@code y}. + * @throws ArithmeticException if the result overflows an int. + */ + public static long addExact(long x, long y, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.addExact(x, y) : MathWrapper.addExact(x, y); + } + + public static int addExact(int x, int y, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.addExact(x, y) : MathWrapper.addExact(x, y); + } + + public static long floorDiv(long x, long y, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.floorDiv(x, y) : MathWrapper.floorDiv(x, y); + } + + public static int multiplyExact(int x, int y, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.multiplyExact(x, y) : MathWrapper.multiplyExact(x, y); + } + + public static long multiplyExact(long x, long y, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.multiplyExact(x, y) : MathWrapper.multiplyExact(x, y); + } + + public static long subtractExact(long x, long y, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.subtractExact(x, y) : MathWrapper.subtractExact(x, y); + } + + public static int min(int a, int b, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.min(a, b) : MathWrapper.min(a, b); + } + + public static long min(long a, long b, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.min(a, b) : MathWrapper.min(a, b); + } + + public static int max(int a, int b, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.max(a, b) : MathWrapper.max(a, b); + } + + public static long max(long a, long b, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.max(a, b) : MathWrapper.max(a, b); + } + + public static int round(float a, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.round(a) : MathWrapper.round(a); + } + + public static long round(double a, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.round(a) : MathWrapper.round(a); + } + + public static double ceil(double a, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.ceil(a) : MathWrapper.ceil(a); + } + + public static double signum(double a, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.signum(a) : MathWrapper.signum(a); + } + + public static double random(boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.random() : MathWrapper.random(); + } + + public static long abs(long a, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.abs(a) : MathWrapper.abs(a); + } + +} diff --git a/common/src/main/java/org/tron/common/math/StrictMathWrapper.java b/common/src/main/java/org/tron/common/math/StrictMathWrapper.java index 6285f6567c0..6a4d9c4e1a6 100644 --- a/common/src/main/java/org/tron/common/math/StrictMathWrapper.java +++ b/common/src/main/java/org/tron/common/math/StrictMathWrapper.java @@ -5,4 +5,140 @@ public class StrictMathWrapper { public static double pow(double a, double b) { return StrictMath.pow(a, b); } + + /** + * *** methods are same as {@link java.lang.Math} methods, guaranteed by the call start *** + */ + + /** + * finally calls {@link java.lang.Math#addExact(long, long)} + */ + + public static long addExact(long x, long y) { + return StrictMath.addExact(x, y); + } + + /** + * finally calls {@link java.lang.Math#addExact(int, int)} + */ + + public static int addExact(int x, int y) { + return StrictMath.addExact(x, y); + } + + /** + * finally calls {@link java.lang.Math#subtractExact(long, long)} + */ + + public static long subtractExact(long x, long y) { + return StrictMath.subtractExact(x, y); + } + + /** + * finally calls {@link java.lang.Math#floorMod(long, long)} + */ + public static long multiplyExact(long x, long y) { + return StrictMath.multiplyExact(x, y); + } + + public static long multiplyExact(long x, int y) { + return multiplyExact(x, (long) y); + } + + public static int multiplyExact(int x, int y) { + return StrictMath.multiplyExact(x, y); + } + + /** + * finally calls {@link java.lang.Math#floorDiv(long, long)} + */ + public static long floorDiv(long x, long y) { + return StrictMath.floorDiv(x, y); + } + + public static long floorDiv(long x, int y) { + return floorDiv(x, (long) y); + } + + /** + * finally calls {@link java.lang.Math#min(int, int)} + */ + public static int min(int a, int b) { + return StrictMath.min(a, b); + } + + /** + * finally calls {@link java.lang.Math#min(long, long)} + */ + public static long min(long a, long b) { + return StrictMath.min(a, b); + } + + /** + * finally calls {@link java.lang.Math#max(int, int)} + */ + public static int max(int a, int b) { + return StrictMath.max(a, b); + } + + /** + * finally calls {@link java.lang.Math#max(long, long)} + */ + public static long max(long a, long b) { + return StrictMath.max(a, b); + } + + /** + * finally calls {@link java.lang.Math#round(float)} + */ + public static int round(float a) { + return StrictMath.round(a); + } + + /** + * finally calls {@link java.lang.Math#round(double)} + */ + public static long round(double a) { + return StrictMath.round(a); + } + + /** + * finally calls {@link java.lang.Math#signum(double)} + */ + public static double signum(double d) { + return StrictMath.signum(d); + } + + /** + * finally calls {@link java.lang.Math#signum(float)} + */ + public static long abs(long a) { + return StrictMath.abs(a); + } + + /** + * *** methods are same as {@link java.lang.Math} methods, guaranteed by the call end *** + */ + + /** + * *** methods are same as {@link java.lang.Math} methods by mathematical algorithms*** + * / + + + /** + * mathematical integer: ceil(i) = floor(i) = i + * @return the smallest (closest to negative infinity) double value that is greater + * than or equal to the argument and is equal to a mathematical integer. + */ + public static double ceil(double a) { + return StrictMath.ceil(a); + } + + /** + * *** methods are no matters *** + */ + public static double random() { + return StrictMath.random(); + } + } diff --git a/common/src/main/java/org/tron/common/runtime/vm/DataWord.java b/common/src/main/java/org/tron/common/runtime/vm/DataWord.java index 0eb0487a534..1601dcaad28 100644 --- a/common/src/main/java/org/tron/common/runtime/vm/DataWord.java +++ b/common/src/main/java/org/tron/common/runtime/vm/DataWord.java @@ -17,6 +17,9 @@ */ package org.tron.common.runtime.vm; +import static org.tron.common.math.Maths.min; +import static org.tron.common.math.Maths.signum; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import java.math.BigInteger; @@ -28,6 +31,7 @@ import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.FastByteComparisons; import org.tron.core.db.ByteArrayWrapper; +import org.tron.core.vm.config.VMConfig; /** * DataWord is the 32-byte array representation of a 256-bit number Calculations can be done on this @@ -165,7 +169,7 @@ public byte[] getClonedData() { byte[] ret = ByteUtil.EMPTY_BYTE_ARRAY; if (data != null) { ret = new byte[WORD_SIZE]; - int dataSize = Math.min(data.length, WORD_SIZE); + int dataSize = min(data.length, WORD_SIZE, VMConfig.allowStrictMath2()); System.arraycopy(data, 0, ret, 0, dataSize); } return ret; @@ -484,7 +488,7 @@ public int compareTo(DataWord o) { data, 0, data.length, o.getData(), 0, o.getData().length); // Convert result into -1, 0 or 1 as is the convention - return (int) Math.signum(result); + return (int) signum(result, VMConfig.allowStrictMath2()); } public void signExtend(byte k) { diff --git a/common/src/main/java/org/tron/common/utils/ByteUtil.java b/common/src/main/java/org/tron/common/utils/ByteUtil.java index 54d637d3f01..88d4cfdf90b 100644 --- a/common/src/main/java/org/tron/common/utils/ByteUtil.java +++ b/common/src/main/java/org/tron/common/utils/ByteUtil.java @@ -18,6 +18,8 @@ package org.tron.common.utils; +import static org.tron.common.math.Maths.min; + import com.google.common.base.Preconditions; import com.google.common.primitives.UnsignedBytes; import java.io.ByteArrayOutputStream; @@ -70,7 +72,7 @@ public static byte[] bigIntegerToBytes(BigInteger b, int numBytes) { byte[] bytes = new byte[numBytes]; byte[] biBytes = b.toByteArray(); int start = (biBytes.length == numBytes + 1) ? 1 : 0; - int length = Math.min(biBytes.length, numBytes); + int length = min(biBytes.length, numBytes, true); System.arraycopy(biBytes, start, bytes, numBytes - length, length); return bytes; } @@ -346,7 +348,7 @@ public static byte[] parseBytes(byte[] input, int offset, int len) { } byte[] bytes = new byte[len]; - System.arraycopy(input, offset, bytes, 0, Math.min(input.length - offset, len)); + System.arraycopy(input, offset, bytes, 0, min(input.length - offset, len, true)); return bytes; } diff --git a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java b/common/src/main/java/org/tron/core/vm/config/VMConfig.java similarity index 96% rename from actuator/src/main/java/org/tron/core/vm/config/VMConfig.java rename to common/src/main/java/org/tron/core/vm/config/VMConfig.java index 9f567344337..fa99daf20f4 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java +++ b/common/src/main/java/org/tron/core/vm/config/VMConfig.java @@ -55,6 +55,8 @@ public class VMConfig { private static boolean ALLOW_TVM_CANCUN = false; + private static Boolean ALLOW_STRICT_MATH_2 = false; + private VMConfig() { } @@ -154,6 +156,10 @@ public static void initAllowTvmCancun(long allow) { ALLOW_TVM_CANCUN = allow == 1; } + public static void initAllowStrictMath2(long allow) { + ALLOW_STRICT_MATH_2 = allow == 1; + } + public static boolean getEnergyLimitHardFork() { return CommonParameter.ENERGY_LIMIT_HARD_FORK; } @@ -241,4 +247,8 @@ public static boolean allowStrictMath() { public static boolean allowTvmCancun() { return ALLOW_TVM_CANCUN; } + + public static boolean allowStrictMath2() { + return ALLOW_STRICT_MATH_2; + } } diff --git a/framework/src/main/java/org/tron/common/logsfilter/ContractEventParser.java b/framework/src/main/java/org/tron/common/logsfilter/ContractEventParser.java index b2d8a0d8d3a..48181cb1255 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/ContractEventParser.java +++ b/framework/src/main/java/org/tron/common/logsfilter/ContractEventParser.java @@ -1,5 +1,7 @@ package org.tron.common.logsfilter; +import static org.tron.common.math.Maths.min; + import java.math.BigInteger; import java.util.regex.Pattern; import lombok.extern.slf4j.Slf4j; @@ -76,7 +78,7 @@ protected static byte[] subBytes(byte[] src, int start, int length) { throw new OutputLengthException("data start:" + start + ", length:" + length); } byte[] dst = new byte[length]; - System.arraycopy(src, start, dst, 0, Math.min(length, src.length - start)); + System.arraycopy(src, start, dst, 0, min(length, src.length - start, true)); return dst; } diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index ce70d8b4cb7..86bff8fb665 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -18,6 +18,9 @@ package org.tron.core; +import static org.tron.common.math.Maths.addExact; +import static org.tron.common.math.Maths.ceil; +import static org.tron.common.math.Maths.max; import static org.tron.common.utils.Commons.getAssetIssueStoreFinal; import static org.tron.common.utils.Commons.getExchangeStoreFinal; import static org.tron.common.utils.WalletUtil.isConstant; @@ -880,10 +883,10 @@ public long calcCanDelegatedBandWidthMaxSize( long netUsage = (long) (accountNetUsage * TRX_PRECISION * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); - long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage); + long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage, dynamicStore.allowStrictMath2()); long maxSize = ownerCapsule.getFrozenV2BalanceForBandwidth() - v2NetUsage; - return Math.max(0, maxSize); + return max(0, maxSize, dynamicStore.allowStrictMath2()); } public long calcCanDelegatedEnergyMaxSize(ByteString ownerAddress) { @@ -900,10 +903,11 @@ public long calcCanDelegatedEnergyMaxSize(ByteString ownerAddress) { long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); - long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage); + long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage, + dynamicStore.allowStrictMath2()); long maxSize = ownerCapsule.getFrozenV2BalanceForEnergy() - v2EnergyUsage; - return Math.max(0, maxSize); + return max(0, maxSize, dynamicStore.allowStrictMath2()); } public DelegatedResourceAccountIndex getDelegatedResourceAccountIndex(ByteString address) { @@ -2985,7 +2989,8 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, if (transaction.getRet(0).getRet().equals(code.SUCESS)) { txRetBuilder.setResult(true); txRetBuilder.setCode(response_code.SUCCESS); - estimateBuilder.setEnergyRequired((long) Math.ceil((double) high / dps.getEnergyFee())); + estimateBuilder.setEnergyRequired((long) ceil((double) high / dps.getEnergyFee(), + dps.allowStrictMath2())); } return transaction; @@ -3539,8 +3544,9 @@ public ShieldedTRC20Parameters createShieldedContractParameters( long totalToAmount = 0; if (scaledToAmount > 0) { try { - totalToAmount = receiveSize == 0 ? scaledToAmount - : (Math.addExact(scaledToAmount, shieldedReceives.get(0).getNote().getValue())); + totalToAmount = receiveSize == 0 ? scaledToAmount : (addExact( + scaledToAmount, shieldedReceives.get(0).getNote().getValue(), + dbManager.getDynamicPropertiesStore().allowStrictMath2())); } catch (ArithmeticException e) { throw new ZksnarkException("Unbalanced burn!"); } @@ -3671,8 +3677,9 @@ public ShieldedTRC20Parameters createShieldedContractParametersWithoutAsk( long totalToAmount = 0; if (scaledToAmount > 0) { try { - totalToAmount = receiveSize == 0 ? scaledToAmount - : Math.addExact(scaledToAmount, shieldedReceives.get(0).getNote().getValue()); + totalToAmount = receiveSize == 0 ? scaledToAmount : addExact( + scaledToAmount, shieldedReceives.get(0).getNote().getValue(), + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); } catch (ArithmeticException e) { throw new ZksnarkException("Unbalanced burn!"); } diff --git a/framework/src/main/java/org/tron/core/capsule/utils/RLP.java b/framework/src/main/java/org/tron/core/capsule/utils/RLP.java index 60a84cfd3d3..24b5c502a1c 100644 --- a/framework/src/main/java/org/tron/core/capsule/utils/RLP.java +++ b/framework/src/main/java/org/tron/core/capsule/utils/RLP.java @@ -3,6 +3,7 @@ import static java.util.Arrays.copyOfRange; import static org.bouncycastle.util.Arrays.concatenate; import static org.bouncycastle.util.BigIntegers.asUnsignedByteArray; +import static org.tron.common.math.Maths.pow; import static org.tron.common.utils.ByteUtil.byteArrayToInt; import static org.tron.common.utils.ByteUtil.intToBytesNoLeadZeroes; import static org.tron.common.utils.ByteUtil.isNullOrZeroArray; @@ -49,7 +50,7 @@ public class RLP { /** * Allow for content up to size of 2^64 bytes * */ - private static final double MAX_ITEM_LENGTH = Math.pow(256, 8); + private static final double MAX_ITEM_LENGTH = pow(256, 8, true); /** * Reason for threshold according to Vitalik Buterin: - 56 bytes maximizes the benefit of both * options - if we went with 60 then we would have only had 4 slots for long strings so RLP would diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 3a37490ee69..83ecbc1c1ab 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1,7 +1,8 @@ package org.tron.core.config.args; -import static java.lang.Math.max; import static java.lang.System.exit; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; import static org.tron.core.Constant.ADD_PRE_FIX_BYTE_MAINNET; import static org.tron.core.Constant.DYNAMIC_ENERGY_INCREASE_FACTOR_RANGE; import static org.tron.core.Constant.DYNAMIC_ENERGY_MAX_FACTOR_RANGE; @@ -457,7 +458,7 @@ public static void setParam(final Config config) { if (config.hasPath(Constant.VM_MAX_ENERGY_LIMIT_FOR_CONSTANT)) { long configLimit = config.getLong(Constant.VM_MAX_ENERGY_LIMIT_FOR_CONSTANT); - PARAMETER.maxEnergyLimitForConstant = max(3_000_000L, configLimit); + PARAMETER.maxEnergyLimitForConstant = max(3_000_000L, configLimit, true); } if (config.hasPath(Constant.VM_LRU_CACHE_SIZE)) { @@ -1163,8 +1164,8 @@ public static void setParam(final Config config) { if (config.hasPath(Constant.ALLOW_DELEGATE_OPTIMIZATION)) { PARAMETER.allowDelegateOptimization = config.getLong(Constant.ALLOW_DELEGATE_OPTIMIZATION); - PARAMETER.allowDelegateOptimization = Math.min(PARAMETER.allowDelegateOptimization, 1); - PARAMETER.allowDelegateOptimization = Math.max(PARAMETER.allowDelegateOptimization, 0); + PARAMETER.allowDelegateOptimization = min(PARAMETER.allowDelegateOptimization, 1, true); + PARAMETER.allowDelegateOptimization = max(PARAMETER.allowDelegateOptimization, 0, true); } if (config.hasPath(Constant.COMMITTEE_UNFREEZE_DELAY_DAYS)) { @@ -1179,33 +1180,31 @@ public static void setParam(final Config config) { if (config.hasPath(Constant.ALLOW_DYNAMIC_ENERGY)) { PARAMETER.allowDynamicEnergy = config.getLong(Constant.ALLOW_DYNAMIC_ENERGY); - PARAMETER.allowDynamicEnergy = Math.min(PARAMETER.allowDynamicEnergy, 1); - PARAMETER.allowDynamicEnergy = Math.max(PARAMETER.allowDynamicEnergy, 0); + PARAMETER.allowDynamicEnergy = min(PARAMETER.allowDynamicEnergy, 1, true); + PARAMETER.allowDynamicEnergy = max(PARAMETER.allowDynamicEnergy, 0, true); } if (config.hasPath(Constant.DYNAMIC_ENERGY_THRESHOLD)) { PARAMETER.dynamicEnergyThreshold = config.getLong(Constant.DYNAMIC_ENERGY_THRESHOLD); PARAMETER.dynamicEnergyThreshold - = Math.min(PARAMETER.dynamicEnergyThreshold, 100_000_000_000_000_000L); - PARAMETER.dynamicEnergyThreshold = Math.max(PARAMETER.dynamicEnergyThreshold, 0); + = min(PARAMETER.dynamicEnergyThreshold, 100_000_000_000_000_000L, true); + PARAMETER.dynamicEnergyThreshold = max(PARAMETER.dynamicEnergyThreshold, 0, true); } if (config.hasPath(Constant.DYNAMIC_ENERGY_INCREASE_FACTOR)) { PARAMETER.dynamicEnergyIncreaseFactor = config.getLong(Constant.DYNAMIC_ENERGY_INCREASE_FACTOR); PARAMETER.dynamicEnergyIncreaseFactor = - Math.min(PARAMETER.dynamicEnergyIncreaseFactor, DYNAMIC_ENERGY_INCREASE_FACTOR_RANGE); - PARAMETER.dynamicEnergyIncreaseFactor = - Math.max(PARAMETER.dynamicEnergyIncreaseFactor, 0); + min(PARAMETER.dynamicEnergyIncreaseFactor, DYNAMIC_ENERGY_INCREASE_FACTOR_RANGE, true); + PARAMETER.dynamicEnergyIncreaseFactor = max(PARAMETER.dynamicEnergyIncreaseFactor, 0, true); } if (config.hasPath(Constant.DYNAMIC_ENERGY_MAX_FACTOR)) { PARAMETER.dynamicEnergyMaxFactor = config.getLong(Constant.DYNAMIC_ENERGY_MAX_FACTOR); PARAMETER.dynamicEnergyMaxFactor = - Math.min(PARAMETER.dynamicEnergyMaxFactor, DYNAMIC_ENERGY_MAX_FACTOR_RANGE); - PARAMETER.dynamicEnergyMaxFactor = - Math.max(PARAMETER.dynamicEnergyMaxFactor, 0); + min(PARAMETER.dynamicEnergyMaxFactor, DYNAMIC_ENERGY_MAX_FACTOR_RANGE, true); + PARAMETER.dynamicEnergyMaxFactor = max(PARAMETER.dynamicEnergyMaxFactor, 0, true); } PARAMETER.dynamicConfigEnable = config.hasPath(Constant.DYNAMIC_CONFIG_ENABLE) @@ -1624,7 +1623,7 @@ private static void initRocksDbSettings(Config config) { ? config.getInt(prefix + "levelNumber") : 7; int compactThreads = config.hasPath(prefix + "compactThreads") ? config.getInt(prefix + "compactThreads") - : max(Runtime.getRuntime().availableProcessors(), 1); + : max(Runtime.getRuntime().availableProcessors(), 1, true); int blocksize = config.hasPath(prefix + "blocksize") ? config.getInt(prefix + "blocksize") : 16; long maxBytesForLevelBase = config.hasPath(prefix + "maxBytesForLevelBase") diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index cfd12fffce2..43ea4460140 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1,5 +1,8 @@ package org.tron.core.db; +import static org.tron.common.math.Maths.floorDiv; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; import static org.tron.common.utils.Commons.adjustBalance; import static org.tron.core.Constant.TRANSACTION_MAX_BYTE_SIZE; import static org.tron.core.exception.BadBlockException.TypeEnum.CALC_MERKLE_ROOT_FAILED; @@ -916,19 +919,20 @@ public void consumeMultiSignFee(TransactionCapsule trx, TransactionTrace trace) throws AccountResourceInsufficientException { if (trx.getInstance().getSignatureCount() > 1) { long fee = getDynamicPropertiesStore().getMultiSignFee(); - + boolean useStrictMath2 = getDynamicPropertiesStore().allowStrictMath2(); List contracts = trx.getInstance().getRawData().getContractList(); for (Contract contract : contracts) { byte[] address = TransactionCapsule.getOwner(contract); AccountCapsule accountCapsule = getAccountStore().get(address); try { if (accountCapsule != null) { - adjustBalance(getAccountStore(), accountCapsule, -fee); + adjustBalance(getAccountStore(), accountCapsule, -fee, useStrictMath2); if (getDynamicPropertiesStore().supportBlackHoleOptimization()) { getDynamicPropertiesStore().burnTrx(fee); } else { - adjustBalance(getAccountStore(), this.getAccountStore().getBlackhole(), +fee); + adjustBalance(getAccountStore(), this.getAccountStore().getBlackhole(), +fee, + useStrictMath2); } } } catch (BalanceInsufficientException e) { @@ -953,19 +957,20 @@ public void consumeMemoFee(TransactionCapsule trx, TransactionTrace trace) if (fee == 0) { return; } - + boolean useStrictMath2 = getDynamicPropertiesStore().allowStrictMath2(); List contracts = trx.getInstance().getRawData().getContractList(); for (Contract contract : contracts) { byte[] address = TransactionCapsule.getOwner(contract); AccountCapsule accountCapsule = getAccountStore().get(address); try { if (accountCapsule != null) { - adjustBalance(getAccountStore(), accountCapsule, -fee); + adjustBalance(getAccountStore(), accountCapsule, -fee, useStrictMath2); if (getDynamicPropertiesStore().supportBlackHoleOptimization()) { getDynamicPropertiesStore().burnTrx(fee); } else { - adjustBalance(getAccountStore(), this.getAccountStore().getBlackhole(), +fee); + adjustBalance(getAccountStore(), this.getAccountStore().getBlackhole(), +fee, + useStrictMath2); } } } catch (BalanceInsufficientException e) { @@ -1834,9 +1839,10 @@ private void payReward(BlockCapsule block) { mortgageService.payStandbyWitness(); if (chainBaseManager.getDynamicPropertiesStore().supportTransactionFeePool()) { - long transactionFeeReward = Math - .floorDiv(chainBaseManager.getDynamicPropertiesStore().getTransactionFeePool(), - Constant.TRANSACTION_FEE_POOL_PERIOD); + long transactionFeeReward = floorDiv( + chainBaseManager.getDynamicPropertiesStore().getTransactionFeePool(), + Constant.TRANSACTION_FEE_POOL_PERIOD, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); mortgageService.payTransactionFeeReward(witnessCapsule.getAddress().toByteArray(), transactionFeeReward); chainBaseManager.getDynamicPropertiesStore().saveTransactionFeePool( @@ -1850,9 +1856,10 @@ private void payReward(BlockCapsule block) { + chainBaseManager.getDynamicPropertiesStore().getWitnessPayPerBlock()); if (chainBaseManager.getDynamicPropertiesStore().supportTransactionFeePool()) { - long transactionFeeReward = Math - .floorDiv(chainBaseManager.getDynamicPropertiesStore().getTransactionFeePool(), - Constant.TRANSACTION_FEE_POOL_PERIOD); + long transactionFeeReward = floorDiv( + chainBaseManager.getDynamicPropertiesStore().getTransactionFeePool(), + Constant.TRANSACTION_FEE_POOL_PERIOD, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); account.setAllowance(account.getAllowance() + transactionFeeReward); chainBaseManager.getDynamicPropertiesStore().saveTransactionFeePool( chainBaseManager.getDynamicPropertiesStore().getTransactionFeePool() @@ -2433,8 +2440,10 @@ private void initLiteNode() { } transactionCount += trx.getTransactionIds().size(); long blockNum = trx.getNum(); - maxBlock = Math.max(maxBlock, blockNum); - minBlock = Math.min(minBlock, blockNum); + maxBlock = max(maxBlock, blockNum, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + minBlock = min(minBlock, blockNum, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); item.setBlockNum(blockNum); trx.getTransactionIds().forEach( tid -> chainBaseManager.getTransactionStore().put(Hex.decode(tid), item)); diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java index f575253c50c..55446593bd0 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java @@ -1,5 +1,7 @@ package org.tron.core.net.messagehandler; +import static org.tron.common.math.Maths.min; + import java.util.LinkedList; import java.util.List; import lombok.extern.slf4j.Slf4j; @@ -117,7 +119,7 @@ private BlockId getUnForkId(List blockIds) throws P2pException { private LinkedList getBlockIds(Long unForkNum, BlockId headID) throws P2pException { long headNum = headID.getNum(); - long len = Math.min(headNum, unForkNum + NetConstants.SYNC_FETCH_BATCH_NUM); + long len = min(headNum, unForkNum + NetConstants.SYNC_FETCH_BATCH_NUM, true); LinkedList ids = new LinkedList<>(); for (long i = unForkNum; i <= len; i++) { diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index a63fd4bf0a9..b99b5b52bad 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -1,5 +1,8 @@ package org.tron.core.net.service.effective; +import static org.tron.common.math.Maths.ceil; +import static org.tron.common.math.Maths.max; + import java.util.Comparator; import java.util.HashMap; import java.util.List; @@ -86,8 +89,8 @@ private void disconnectRandom() { long now = System.currentTimeMillis(); Map weights = new HashMap<>(); peers.forEach(peer -> { - int weight = (int) Math.ceil((double) (now - peer.getLastInteractiveTime()) / 500); - weights.put(peer, Math.max(weight, 1)); + int weight = (int) ceil((double) (now - peer.getLastInteractiveTime()) / 500, true); + weights.put(peer, max(weight, 1, true)); }); WeightedRandom weightedRandom = new WeightedRandom(weights); PeerConnection one = (PeerConnection) weightedRandom.next(); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java index cf04a1769aa..a6cc451b41c 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java @@ -1,5 +1,7 @@ package org.tron.core.services.jsonrpc.filters; +import static org.tron.common.math.Maths.min; + import com.google.protobuf.ByteString; import lombok.Getter; import org.apache.commons.lang3.StringUtils; @@ -55,7 +57,7 @@ public LogFilterWrapper(FilterRequest fr, long currentMaxBlockNum, Wallet wallet if (toBlockSrc == -1) { toBlockSrc = Long.MAX_VALUE; } - fromBlockSrc = Math.min(toBlockSrc, currentMaxBlockNum); + fromBlockSrc = min(toBlockSrc, currentMaxBlockNum, true); } else if (StringUtils.isNotEmpty(fr.getFromBlock()) && StringUtils.isEmpty(fr.getToBlock())) { diff --git a/framework/src/main/java/org/tron/program/DBConvert.java b/framework/src/main/java/org/tron/program/DBConvert.java index a13a2ffefb5..7b9d63544dc 100644 --- a/framework/src/main/java/org/tron/program/DBConvert.java +++ b/framework/src/main/java/org/tron/program/DBConvert.java @@ -1,6 +1,7 @@ package org.tron.program; import static org.fusesource.leveldbjni.JniDBFactory.factory; +import static org.tron.common.math.Maths.max; import java.io.File; import java.nio.file.Path; @@ -190,7 +191,7 @@ private Options newDefaultRocksDbOptions() { options.setTargetFileSizeBase(64 * 1024 * 1024); options.setTargetFileSizeMultiplier(1); options.setMaxBytesForLevelBase(512 * 1024 * 1024); - options.setMaxBackgroundCompactions(Math.max(1, Runtime.getRuntime().availableProcessors())); + options.setMaxBackgroundCompactions(max(1, Runtime.getRuntime().availableProcessors(), true)); options.setLevel0FileNumCompactionTrigger(4); options.setLevelCompactionDynamicLevelBytes(true); if ("market_pair_price_to_order".equalsIgnoreCase(this.dbName)) { diff --git a/framework/src/test/java/org/tron/common/BaseTest.java b/framework/src/test/java/org/tron/common/BaseTest.java index 959a746a141..9eddef83fba 100644 --- a/framework/src/test/java/org/tron/common/BaseTest.java +++ b/framework/src/test/java/org/tron/common/BaseTest.java @@ -16,6 +16,7 @@ import org.tron.common.application.Application; import org.tron.common.crypto.ECKey; import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.Commons; import org.tron.common.utils.Sha256Hash; import org.tron.consensus.base.Param; import org.tron.core.ChainBaseManager; @@ -23,6 +24,8 @@ import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; +import org.tron.core.exception.BalanceInsufficientException; +import org.tron.core.store.AccountStore; import org.tron.protos.Protocol; @Slf4j @@ -102,4 +105,10 @@ public Protocol.Block getSignedBlock(ByteString witness, long time, byte[] priva return block.toBuilder().setBlockHeader(blockHeader).build(); } + + public void adjustBalance(AccountStore accountStore, byte[] accountAddress, long amount) + throws BalanceInsufficientException { + Commons.adjustBalance(accountStore, accountAddress, amount, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java index 7debeb12772..9e58233c922 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java @@ -15,6 +15,8 @@ package org.tron.common.runtime.vm; +import static org.tron.common.math.Maths.max; + import com.google.protobuf.Any; import com.google.protobuf.ByteString; import org.junit.Assert; @@ -248,7 +250,8 @@ public void testMaxContractResultSize() { continue; } Result result = Result.newBuilder().setContractRet(cr).build(); - maxSize = Math.max(maxSize, result.getSerializedSize()); + maxSize = max(maxSize, result.getSerializedSize(), + dbManager.getDynamicPropertiesStore().allowStrictMath2()); } Assert.assertEquals(2, maxSize); } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java index 9558c701109..524a858d2b5 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -1,5 +1,6 @@ package org.tron.common.runtime.vm; +import static org.tron.common.math.Maths.min; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_MS; @@ -856,7 +857,8 @@ private TVMTestResult unDelegateResource( transferUsage = (long) (oldReceiver.getEnergyUsage() * ((double) (amount) / oldReceiver.getAllFrozenBalanceForEnergy())); } - transferUsage = Math.min(unDelegateMaxUsage, transferUsage); + transferUsage = min(unDelegateMaxUsage, transferUsage, + manager.getDynamicPropertiesStore().allowStrictMath2()); } DelegatedResourceStore delegatedResourceStore = manager.getDelegatedResourceStore(); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/MemoryTest.java b/framework/src/test/java/org/tron/common/runtime/vm/MemoryTest.java index b6e9cfe109c..dbbf6921567 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/MemoryTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/MemoryTest.java @@ -18,9 +18,9 @@ package org.tron.common.runtime.vm; -import static java.lang.Math.ceil; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertTrue; +import static org.tron.common.math.Maths.ceil; import java.util.Arrays; import lombok.extern.slf4j.Slf4j; @@ -43,7 +43,7 @@ private static void checkMemoryExtend(int dataSize) { } private static int calcSize(int dataSize, int chunkSize) { - return (int) ceil((double) dataSize / chunkSize) * chunkSize; + return (int) ceil((double) dataSize / chunkSize, true) * chunkSize; } @Test diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java index 833ed6b0ac3..27e7891e6d8 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java @@ -1,6 +1,8 @@ package org.tron.common.runtime.vm; import static org.junit.Assert.assertNotNull; +import static org.tron.common.math.Maths.random; +import static org.tron.common.math.Maths.round; import com.google.protobuf.ByteString; import java.math.BigInteger; @@ -4504,7 +4506,7 @@ private byte[] longTo32Bytes(long value) { } private long randomLong() { - return Math.round(Math.random() * Long.MAX_VALUE / 2); + return round(random(true) * Long.MAX_VALUE / 2, true); } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java b/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java index 1d85e9a7eab..fc3b16f8f2e 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java @@ -1,5 +1,6 @@ package org.tron.common.runtime.vm; +import static org.tron.common.math.Maths.max; import static org.tron.protos.Protocol.Transaction.Result.contractResult; import static org.tron.protos.Protocol.Transaction.Result.contractResult.REVERT; import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS; @@ -863,7 +864,8 @@ private void checkRewardAndWithdraw(byte[] contract, boolean isZero) throws Exce long rewardBySystem = mortgageService.queryReward(contract); long beginCycle = manager.getDelegationStore().getBeginCycle(contract); long currentCycle = manager.getDynamicPropertiesStore().getCurrentCycleNumber(); - long passedCycle = Math.max(0, currentCycle - beginCycle); + long passedCycle = max(0, currentCycle - beginCycle, + manager.getDynamicPropertiesStore().allowStrictMath2()); Assert.assertTrue(isZero ? rewardBySystem == 0 : rewardBySystem > 0); triggerContract(contract, SUCCESS, getConsumer(">=", rewardBySystem) diff --git a/framework/src/test/java/org/tron/common/utils/client/utils/AbiUtil.java b/framework/src/test/java/org/tron/common/utils/client/utils/AbiUtil.java index 976490b8c80..d518776adb2 100644 --- a/framework/src/test/java/org/tron/common/utils/client/utils/AbiUtil.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/AbiUtil.java @@ -1,5 +1,7 @@ package org.tron.common.utils.client.utils; +import static org.tron.common.math.Maths.abs; + import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.ArrayList; @@ -340,7 +342,7 @@ static class CoderNumber extends Coder { @Override byte[] encode(String value) { long n = Long.valueOf(value); - DataWord word = new DataWord(Math.abs(n)); + DataWord word = new DataWord(abs(n, true)); if (n < 0) { word.negate(); } diff --git a/framework/src/test/java/org/tron/common/utils/client/utils/DataWord.java b/framework/src/test/java/org/tron/common/utils/client/utils/DataWord.java index 6c36f4d636a..f676ef6c8e4 100644 --- a/framework/src/test/java/org/tron/common/utils/client/utils/DataWord.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/DataWord.java @@ -18,6 +18,8 @@ * along with the ethereumJ library. If not, see . */ +import static org.tron.common.math.Maths.signum; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import java.math.BigInteger; @@ -466,7 +468,7 @@ public int compareTo(DataWord o) { data, 0, data.length, o.getData(), 0, o.getData().length); // Convert result into -1, 0 or 1 as is the convention - return (int) Math.signum(result); + return (int) signum(result, true); } /** diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java index 807d0e1be02..179ba56e7ed 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java @@ -125,8 +125,8 @@ public void sameTokenNameCloseSuccessExchangeCreate() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -216,7 +216,7 @@ public void sameTokenNameCloseSuccessExchangeCreate2() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.setBalance(200_000_000_000000L); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L, true); dbManager.getAccountStore().put(ownerAddress, accountCapsule); ExchangeCreateActuator actuator = new ExchangeCreateActuator(); @@ -710,8 +710,8 @@ public void sameTokenNameCloseNoEnoughBalance() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance, true); accountCapsule.setBalance(1000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -748,8 +748,8 @@ public void sameTokenNameOpenNoEnoughBalance() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance, true); accountCapsule.setBalance(1000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -785,8 +785,8 @@ public void sameTokenNameCloseSameTokens() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -822,8 +822,8 @@ public void sameTokenNameOpenSameTokens() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -859,8 +859,8 @@ public void sameTokenNameCloseLessToken() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 1000); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 1000, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -897,8 +897,8 @@ public void sameTokenNameOpenLessToken() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 1000); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 1000, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -934,8 +934,8 @@ public void sameTokenNameCloseMoreThanBalanceLimit() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -972,8 +972,8 @@ public void sameTokenNameOpenMoreThanBalanceLimit() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1010,7 +1010,7 @@ public void sameTokenNameCloseBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.setBalance(firstTokenBalance + 1000L); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L, false); dbManager.getAccountStore().put(ownerAddress, accountCapsule); ExchangeCreateActuator actuator = new ExchangeCreateActuator(); @@ -1047,7 +1047,7 @@ public void sameTokenNameOpenBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.setBalance(firstTokenBalance + 1000L); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L, false); dbManager.getAccountStore().put(ownerAddress, accountCapsule); ExchangeCreateActuator actuator = new ExchangeCreateActuator(); @@ -1082,8 +1082,8 @@ public void sameTokenNameCloseFirstTokenBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance - 1000L); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance - 1000L, false); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1120,8 +1120,8 @@ public void sameTokenNameOpenFirstTokenBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance - 1000L); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance - 1000L, false); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1158,7 +1158,7 @@ public void sameTokenNameCloseBalanceNotEnough2() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.setBalance(secondTokenBalance + 1000L); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), 200_000_000L); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), 200_000_000L, false); dbManager.getAccountStore().put(ownerAddress, accountCapsule); ExchangeCreateActuator actuator = new ExchangeCreateActuator(); @@ -1195,7 +1195,7 @@ public void sameTokenNameOpenBalanceNotEnough2() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.setBalance(secondTokenBalance + 1000L); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), 200_000_000L); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), 200_000_000L, false); dbManager.getAccountStore().put(ownerAddress, accountCapsule); ExchangeCreateActuator actuator = new ExchangeCreateActuator(); @@ -1230,8 +1230,8 @@ public void sameTokenNameCloseSecondTokenBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 90_000_000L); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, false); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 90_000_000L, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1268,8 +1268,8 @@ public void sameTokenNameOpenSecondTokenBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 90_000_000L); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 90_000_000L, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1305,7 +1305,7 @@ public void sameTokenNameCloseSecondTokenNotExist() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1342,7 +1342,7 @@ public void sameTokenNameOpenSecondTokenNotExist() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1388,7 +1388,7 @@ public void commonErrorCheck() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.setBalance(200_000_000_000000L); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L, true); dbManager.getAccountStore().put(ownerAddress, accountCapsule); actuatorTest.setContract(getContract( diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java index 6268c226c7e..7aef11ed793 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java @@ -190,8 +190,8 @@ public void SameTokenNameCloseSuccessExchangeInject() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, false); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -451,7 +451,7 @@ public void SameTokenNameCloseSuccessExchangeInject2() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, false); accountCapsule.setBalance(firstTokenQuant); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -731,8 +731,8 @@ public void SameTokenNameCloseExchangeNotExist() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -819,8 +819,8 @@ public void SameTokenNameCloseAccountIsNotCreator() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -910,7 +910,7 @@ public void SameTokenNameCloseTokenIsNotInExchange() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, false); accountCapsule.setBalance(firstTokenQuant); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -995,8 +995,8 @@ public void SameTokenNameCloseTokenBalanceZero() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant, false); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, false); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1099,8 +1099,8 @@ public void SameTokenNameCloseTokenQuantLessThanZero() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000L); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000L, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1187,7 +1187,7 @@ public void SameTokenNameCloseCalculatedTokenQuantLessThanZero() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(firstTokenQuant); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1273,7 +1273,7 @@ public void SameTokenNameCloseTokenBalanceGreaterThanBalanceLimit() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(firstTokenQuant); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1358,7 +1358,7 @@ public void SameTokenNameCloseBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(firstTokenQuant - 1); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1445,8 +1445,8 @@ public void SameTokenNameCloseTokenBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant - 1); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant - 1, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1533,7 +1533,7 @@ public void SameTokenNameCloseBalanceNotEnough2() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(399_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1618,8 +1618,8 @@ public void SameTokenNameCloseAnotherTokenBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant - 1); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant - 1, false); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, false); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1785,8 +1785,8 @@ public void sameTokennullTransationResult() { TransactionResultCapsule ret = null; byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java index bf60b1cd910..d39706e0699 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java @@ -430,7 +430,7 @@ public void SameTokenNameCloseSuccessExchangeTransaction2() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -588,7 +588,7 @@ public void SameTokenNameCloseInvalidAddress() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, false); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -679,7 +679,7 @@ public void SameTokenNameCloseNoEnoughBalance() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, false); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -729,7 +729,7 @@ public void SameTokenNameOpenNoEnoughBalance() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -779,7 +779,7 @@ public void SameTokenNameCloseNoAccount() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -870,7 +870,7 @@ public void SameTokenNameCloseExchangeNotExist() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -959,7 +959,7 @@ public void SameTokenNameCloseTokenIsNotInExchange() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -1049,7 +1049,7 @@ public void SameTokenNameCloseTokenBalanceZero() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -1155,7 +1155,7 @@ public void SameTokenNameCloseTokenQuantLessThanZero() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -1245,7 +1245,7 @@ public void SameTokenNameCloseTokenBalanceGreaterThanBalanceLimit() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -1421,7 +1421,7 @@ public void SameTokenNameCloseTokenBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), quant - 1); + accountCapsule.addAssetAmount(tokenId.getBytes(), quant - 1, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -1511,7 +1511,7 @@ public void SameTokenNameCloseTokenRequiredNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), quant); + accountCapsule.addAssetAmount(tokenId.getBytes(), quant, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java index 6844925288e..5c5536f873c 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java @@ -851,8 +851,8 @@ public void SameTokenNameCloseAccountIsNotCreator() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -943,7 +943,7 @@ public void SameTokenNameCloseTokenIsNotInExchange() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(firstTokenQuant); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1030,8 +1030,8 @@ public void SameTokenNameCloseTokenBalanceZero() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant, false); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, false); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1136,8 +1136,8 @@ public void SameTokenNameCloseTokenQuantLessThanZero() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000L); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000L, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1227,8 +1227,8 @@ public void SameTokenNameCloseTnotherTokenQuantLessThanZero() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000L); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000L, false); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, false); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); diff --git a/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java index 52e5f554374..88db0791b0a 100755 --- a/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java @@ -1230,7 +1230,7 @@ public void sameTokenNameCloseNotEnoughAssetTest() { AccountCapsule toAccount = chainBaseManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); toAccount.reduceAssetAmount(ByteString.copyFromUtf8(ASSET_NAME).toByteArray(), - TOTAL_SUPPLY - 10000); + TOTAL_SUPPLY - 10000, true); chainBaseManager.getAccountStore().put(toAccount.getAddress().toByteArray(), toAccount); ParticipateAssetIssueActuator actuator = new ParticipateAssetIssueActuator(); actuator.setChainBaseManager(chainBaseManager).setAny(getContract(1)); diff --git a/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java index 508cee731f0..1f9a9af825c 100644 --- a/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java @@ -108,8 +108,8 @@ public void successUpdateSettingContract() { Assert.assertEquals(ret.getInstance().getRet(), Protocol.Transaction.Result.code.SUCESS); Assert.assertEquals( dbManager.getContractStore().get(ByteArray.fromHexString(CONTRACT_ADDRESS)) - .getConsumeUserResourcePercent(), - TARGET_PERCENT); + .getConsumeUserResourcePercent( + dbManager.getDynamicPropertiesStore().allowStrictMath2()), TARGET_PERCENT); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -245,8 +245,8 @@ public void twiceUpdateSettingContract() { Assert.assertEquals(ret.getInstance().getRet(), Protocol.Transaction.Result.code.SUCESS); Assert.assertEquals( dbManager.getContractStore().get(ByteArray.fromHexString(CONTRACT_ADDRESS)) - .getConsumeUserResourcePercent(), - TARGET_PERCENT); + .getConsumeUserResourcePercent( + dbManager.getDynamicPropertiesStore().allowStrictMath2()), TARGET_PERCENT); // second secondActuator.validate(); @@ -255,8 +255,8 @@ public void twiceUpdateSettingContract() { Assert.assertEquals(ret.getInstance().getRet(), Protocol.Transaction.Result.code.SUCESS); Assert.assertEquals( dbManager.getContractStore().get(ByteArray.fromHexString(CONTRACT_ADDRESS)) - .getConsumeUserResourcePercent(), - 90L); + .getConsumeUserResourcePercent( + dbManager.getDynamicPropertiesStore().allowStrictMath2()), 90L); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); diff --git a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java index 3346a1aead5..0eb69f8fd66 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.tron.common.math.Maths.max; import static org.tron.core.capsule.utils.TransactionUtil.isNumber; import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_COST_BASE_SIZE; import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; @@ -114,7 +115,7 @@ public static long estimateConsumeBandWidthSize(final AccountCapsule ownerCapsul TransactionCapsule fakeTransactionCapsule2 = new TransactionCapsule(builder2.build(), ContractType.DelegateResourceContract); long size2 = consumeBandWidthSize(fakeTransactionCapsule2, chainBaseManager); - long addSize = Math.max(size1 - size2, 0L); + long addSize = max(size1 - size2, 0L, true); return DELEGATE_COST_BASE_SIZE + addSize; } @@ -135,7 +136,7 @@ public static long estimateConsumeBandWidthSizeOld( TransactionCapsule fakeTransactionCapsule2 = new TransactionCapsule(builder2.build(), ContractType.DelegateResourceContract); long size2 = consumeBandWidthSize(fakeTransactionCapsule2, chainBaseManager); - long addSize = Math.max(size1 - size2, 0L); + long addSize = max(size1 - size2, 0L, true); return DELEGATE_COST_BASE_SIZE + addSize; } @@ -373,8 +374,8 @@ public void estimateConsumeBandWidthSizePositive() { DelegateResourceContract.newBuilder() .setBalance(TRX_PRECISION); - long expected = DELEGATE_COST_BASE_SIZE + Math.max( - builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L); + long expected = DELEGATE_COST_BASE_SIZE + max( + builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L, true); long actual = TransactionUtil.estimateConsumeBandWidthSize(dps, balance); Assert.assertEquals(expected, actual); } @@ -391,8 +392,8 @@ public void estimateConsumeBandWidthSizeBoundary() { DelegateResourceContract.newBuilder() .setBalance(TRX_PRECISION); - long expected = DELEGATE_COST_BASE_SIZE + Math.max( - builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L); + long expected = DELEGATE_COST_BASE_SIZE + max( + builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L, true); long actual = TransactionUtil.estimateConsumeBandWidthSize(dps, balance); Assert.assertEquals(expected, actual); } @@ -409,8 +410,8 @@ public void estimateConsumeBandWidthSizeEdge() { DelegateResourceContract.newBuilder() .setBalance(TRX_PRECISION); - long expected = DELEGATE_COST_BASE_SIZE + Math.max( - builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L); + long expected = DELEGATE_COST_BASE_SIZE + max( + builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L, true); long actual = TransactionUtil.estimateConsumeBandWidthSize(dps, balance); Assert.assertEquals(expected, actual); } @@ -427,8 +428,8 @@ public void estimateConsumeBandWidthSizeCorner() { DelegateResourceContract.newBuilder() .setBalance(TRX_PRECISION); - long expected = DELEGATE_COST_BASE_SIZE + Math.max( - builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L); + long expected = DELEGATE_COST_BASE_SIZE + max( + builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L, true); long actual = TransactionUtil.estimateConsumeBandWidthSize(dps, balance); Assert.assertEquals(expected, actual); } diff --git a/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java index de72b4be276..0ee0faa550a 100644 --- a/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java @@ -90,7 +90,7 @@ public void AssetAmountTest() { String nameAdd = "TokenX"; long amountAdd = 222L; boolean addBoolean = accountCapsuleTest - .addAssetAmount(nameAdd.getBytes(), amountAdd); + .addAssetAmount(nameAdd.getBytes(), amountAdd, true); Assert.assertTrue(addBoolean); @@ -102,7 +102,7 @@ public void AssetAmountTest() { long amountReduce = 22L; boolean reduceBoolean = accountCapsuleTest - .reduceAssetAmount(ByteArray.fromString("TokenX"), amountReduce); + .reduceAssetAmount(ByteArray.fromString("TokenX"), amountReduce, false); Assert.assertTrue(reduceBoolean); Map assetMapAfter = accountCapsuleTest.getAssetMapForTest(); diff --git a/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java index 0465cd2e867..c90ad89abb3 100644 --- a/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java @@ -20,12 +20,12 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertFalse(capsule.catchUpToCycle(1000L, 2_000_000L, 2000L, 10_00L, false)); + Assert.assertFalse(capsule.catchUpToCycle(1000L, 2_000_000L, 2000L, 10_00L, false, false)); Assert.assertEquals(1000L, capsule.getUpdateCycle()); Assert.assertEquals(1_000_000L, capsule.getEnergyUsage()); Assert.assertEquals(5000L, capsule.getEnergyFactor()); - Assert.assertTrue(capsule.catchUpToCycle(1010L, 900_000L, 1000L, 10_000L, false)); + Assert.assertTrue(capsule.catchUpToCycle(1010L, 900_000L, 1000L, 10_000L, false, false)); Assert.assertEquals(1010L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(3137L, capsule.getEnergyFactor()); @@ -37,7 +37,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1001L, 2_000_000L, 2000L, 10_000L, false)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 2_000_000L, 2000L, 10_000L, false, false)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(4250L, capsule.getEnergyFactor()); @@ -49,7 +49,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 2000L, 10_000L, false)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 2000L, 10_000L, false, false)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(4250L, capsule.getEnergyFactor()); @@ -61,7 +61,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1001L, 900_000L, 2000L, 10_000L, false)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 900_000L, 2000L, 10_000L, false, false)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(8000L, capsule.getEnergyFactor()); @@ -73,7 +73,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1001L, 900_000L, 5000L, 10_000L, false)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 900_000L, 5000L, 10_000L, false, false)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(10_000L, capsule.getEnergyFactor()); @@ -85,7 +85,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1002L, 900_000L, 5000L, 10_000L, false)); + Assert.assertTrue(capsule.catchUpToCycle(1002L, 900_000L, 5000L, 10_000L, false, false)); Assert.assertEquals(1002L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(7500L, capsule.getEnergyFactor()); @@ -97,7 +97,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1003L, 900_000L, 5000L, 10_000L, false)); + Assert.assertTrue(capsule.catchUpToCycle(1003L, 900_000L, 5000L, 10_000L, false, false)); Assert.assertEquals(1003L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(5312L, capsule.getEnergyFactor()); @@ -109,7 +109,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1004L, 900_000L, 5000L, 10_000L, false)); + Assert.assertTrue(capsule.catchUpToCycle(1004L, 900_000L, 5000L, 10_000L, false, false)); Assert.assertEquals(1004L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(3398L, capsule.getEnergyFactor()); @@ -121,7 +121,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1005L, 900_000L, 5000L, 10_000L, true)); + Assert.assertTrue(capsule.catchUpToCycle(1005L, 900_000L, 5000L, 10_000L, true, true)); Assert.assertEquals(1005L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(1723L, capsule.getEnergyFactor()); @@ -133,7 +133,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1005L, 900_000L, 5000L, 10_000L, true)); + Assert.assertTrue(capsule.catchUpToCycle(1005L, 900_000L, 5000L, 10_000L, true, true)); Assert.assertEquals(1005L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(1723L, capsule.getEnergyFactor()); @@ -145,7 +145,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1006L, 900_000L, 5000L, 10_000L, true)); + Assert.assertTrue(capsule.catchUpToCycle(1006L, 900_000L, 5000L, 10_000L, true, true)); Assert.assertEquals(1006L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(258L, capsule.getEnergyFactor()); diff --git a/framework/src/test/java/org/tron/core/capsule/utils/MerkleTreeTest.java b/framework/src/test/java/org/tron/core/capsule/utils/MerkleTreeTest.java index 910b1adba67..df84433726e 100644 --- a/framework/src/test/java/org/tron/core/capsule/utils/MerkleTreeTest.java +++ b/framework/src/test/java/org/tron/core/capsule/utils/MerkleTreeTest.java @@ -1,5 +1,7 @@ package org.tron.core.capsule.utils; +import static org.tron.common.math.Maths.pow; + import com.google.protobuf.ByteString; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -86,7 +88,7 @@ private static int getRank(int num) { num = num >> 1; rank++; } - if (temp == Math.pow(2, rank - 1)) { + if (temp == pow(2, rank - 1, true)) { rank -= 1; } return rank; diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index e9b79487204..683ac49e8ad 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -5,7 +5,6 @@ import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.spy; import static org.tron.common.utils.Commons.adjustAssetBalanceV2; -import static org.tron.common.utils.Commons.adjustBalance; import static org.tron.common.utils.Commons.adjustTotalShieldedPoolValue; import static org.tron.common.utils.Commons.getExchangeStoreFinal; import static org.tron.core.exception.BadBlockException.TypeEnum.CALC_MERKLE_ROOT_FAILED; @@ -36,6 +35,7 @@ import org.tron.common.crypto.ECKey; import org.tron.common.runtime.RuntimeImpl; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Commons; import org.tron.common.utils.JsonUtil; import org.tron.common.utils.LocalWitnesses; import org.tron.common.utils.PublicMethod; @@ -82,6 +82,7 @@ import org.tron.core.exception.ValidateScheduleException; import org.tron.core.exception.ValidateSignatureException; import org.tron.core.exception.ZksnarkException; +import org.tron.core.store.AccountStore; import org.tron.core.store.CodeStore; import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.store.ExchangeStore; @@ -1167,4 +1168,10 @@ public void blockTrigger() { doThrow(new RuntimeException("postBlockTrigger mock")).when(manager).postBlockTrigger(any()); manager.blockTrigger(new BlockCapsule(Block.newBuilder().build()), 1, 1); } + + public void adjustBalance(AccountStore accountStore, byte[] accountAddress, long amount) + throws BalanceInsufficientException { + Commons.adjustBalance(accountStore, accountAddress, amount, + chainManager.getDynamicPropertiesStore().allowStrictMath2()); + } } diff --git a/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreTest.java b/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreTest.java index 1f453cb9b41..d74229fb216 100755 --- a/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreTest.java @@ -1,5 +1,8 @@ package org.tron.core.db; +import static org.tron.common.math.Maths.random; +import static org.tron.common.math.Maths.round; + import java.util.List; import lombok.extern.slf4j.Slf4j; import org.junit.After; @@ -43,7 +46,7 @@ public void cleanDb() { } private static int randomInt(int minInt, int maxInt) { - return (int) Math.round(Math.random() * (maxInt - minInt) + minInt); + return (int) round(random(true) * (maxInt - minInt) + minInt, true); } @Test diff --git a/framework/src/test/java/org/tron/core/jsonrpc/ConcurrentHashMapTest.java b/framework/src/test/java/org/tron/core/jsonrpc/ConcurrentHashMapTest.java index ea0c0354bb0..1de106f68e8 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/ConcurrentHashMapTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/ConcurrentHashMapTest.java @@ -1,5 +1,8 @@ package org.tron.core.jsonrpc; +import static org.tron.common.math.Maths.random; +import static org.tron.common.math.Maths.round; + import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -17,7 +20,7 @@ public class ConcurrentHashMapTest { private static int randomInt(int minInt, int maxInt) { - return (int) Math.round(Math.random() * (maxInt - minInt) + minInt); + return (int) round(random(true) * (maxInt - minInt) + minInt, true); } /** diff --git a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java index 211e7228289..c1b0f8bb507 100644 --- a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java @@ -113,6 +113,7 @@ public void testUpdateConsensusLogicOptimization() { Assert.assertEquals(v, 0); Assert.assertTrue(!dbManager.getDynamicPropertiesStore().allowConsensusLogicOptimization()); Assert.assertFalse(dbManager.getDynamicPropertiesStore().allowWitnessSortOptimization()); + Assert.assertFalse(dbManager.getDynamicPropertiesStore().allowStrictMath2()); long value = 1; Proposal proposal = @@ -127,6 +128,7 @@ public void testUpdateConsensusLogicOptimization() { Assert.assertTrue(dbManager.getDynamicPropertiesStore().allowConsensusLogicOptimization()); Assert.assertTrue(dbManager.getDynamicPropertiesStore().allowWitnessSortOptimization()); + Assert.assertTrue(dbManager.getDynamicPropertiesStore().allowStrictMath2()); } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java b/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java index 67353eb24b1..915742d3f0d 100644 --- a/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java @@ -4,6 +4,8 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; +import static org.tron.common.math.Maths.random; +import static org.tron.common.math.Maths.round; import static org.tron.common.zksnark.JLibrustzcash.librustzcashCheckDiversifier; import static org.tron.common.zksnark.JLibrustzcash.librustzcashComputeCm; import static org.tron.common.zksnark.JLibrustzcash.librustzcashIvkToPkd; @@ -87,7 +89,7 @@ public static void init() { } private static int randomInt(int minInt, int maxInt) { - return (int) Math.round(Math.random() * (maxInt - minInt) + minInt); + return (int) round(random(true) * (maxInt - minInt) + minInt, true); } public static void test(byte[] K, byte[] ovk, byte[] cv, byte[] cm, byte[] epk) diff --git a/framework/src/test/java/org/tron/core/zksnark/SaplingNoteTest.java b/framework/src/test/java/org/tron/core/zksnark/SaplingNoteTest.java index 60f6c8c0826..da4df70d9ac 100644 --- a/framework/src/test/java/org/tron/core/zksnark/SaplingNoteTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/SaplingNoteTest.java @@ -1,5 +1,8 @@ package org.tron.core.zksnark; +import static org.tron.common.math.Maths.random; +import static org.tron.common.math.Maths.round; + import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -30,7 +33,7 @@ public static void removeDb() { } private static int randomInt(int minInt, int maxInt) { - return (int) Math.round(Math.random() * (maxInt - minInt) + minInt); + return (int) round(random(true) * (maxInt - minInt) + minInt, true); } @Test diff --git a/plugins/src/main/java/org/tron/plugins/utils/ByteArray.java b/plugins/src/main/java/org/tron/plugins/utils/ByteArray.java index 3422c36ca9d..2922d110b7c 100644 --- a/plugins/src/main/java/org/tron/plugins/utils/ByteArray.java +++ b/plugins/src/main/java/org/tron/plugins/utils/ByteArray.java @@ -59,7 +59,7 @@ public static int compareUnsigned(byte[] a, byte[] b) { if (b == null) { return 1; } - int minLen = Math.min(a.length, b.length); + int minLen = StrictMath.min(a.length, b.length); for (int i = 0; i < minLen; ++i) { int aVal = a[i] & 0xFF; int bVal = b[i] & 0xFF; diff --git a/plugins/src/main/java/org/tron/plugins/utils/DBUtils.java b/plugins/src/main/java/org/tron/plugins/utils/DBUtils.java index 19547e2b5a5..f8559d5dba8 100644 --- a/plugins/src/main/java/org/tron/plugins/utils/DBUtils.java +++ b/plugins/src/main/java/org/tron/plugins/utils/DBUtils.java @@ -95,7 +95,8 @@ private static Options newDefaultRocksDbOptions(boolean forBulkLoad) { options.setTargetFileSizeBase(64 * 1024 * 1024); options.setTargetFileSizeMultiplier(1); options.setMaxBytesForLevelBase(512 * 1024 * 1024); - options.setMaxBackgroundCompactions(Math.max(1, Runtime.getRuntime().availableProcessors())); + options.setMaxBackgroundCompactions(StrictMath.max( + 1, Runtime.getRuntime().availableProcessors())); options.setLevel0FileNumCompactionTrigger(4); options.setLevelCompactionDynamicLevelBytes(true); final BlockBasedTableConfig tableCfg; diff --git a/plugins/src/main/java/org/tron/plugins/utils/MarketUtils.java b/plugins/src/main/java/org/tron/plugins/utils/MarketUtils.java index a36fc8ad57c..dbd578a59a3 100644 --- a/plugins/src/main/java/org/tron/plugins/utils/MarketUtils.java +++ b/plugins/src/main/java/org/tron/plugins/utils/MarketUtils.java @@ -130,8 +130,8 @@ public static int comparePriceKey(byte[] o1, byte[] o2) { public static int comparePrice(long price1SellQuantity, long price1BuyQuantity, long price2SellQuantity, long price2BuyQuantity) { try { - return Long.compare(Math.multiplyExact(price1BuyQuantity, price2SellQuantity), - Math.multiplyExact(price2BuyQuantity, price1SellQuantity)); + return Long.compare(StrictMath.multiplyExact(price1BuyQuantity, price2SellQuantity), + StrictMath.multiplyExact(price2BuyQuantity, price1SellQuantity)); } catch (ArithmeticException ex) { // do nothing here, because we will use BigInteger to compute again From b84c4f69d30966395b6b7a0e76b25a60cef3ecac Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 14 Feb 2025 19:59:44 +0800 Subject: [PATCH 1131/1197] add test case of empty Payment Address in SpendNote --- .../java/org/tron/core/ShieldWalletTest.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/framework/src/test/java/org/tron/core/ShieldWalletTest.java b/framework/src/test/java/org/tron/core/ShieldWalletTest.java index fe095723c77..7eed5273586 100644 --- a/framework/src/test/java/org/tron/core/ShieldWalletTest.java +++ b/framework/src/test/java/org/tron/core/ShieldWalletTest.java @@ -363,6 +363,7 @@ public void testCreateShieldedContractParameters2() throws ContractExeException + "d0a20202020202020207d0a202020205d2c0a2020202022736869656c6465645f54524332305f636f" + "6e74726163745f61646472657373223a2234313434303037393739333539454341433339354242443" + "3434546383036304433444632444333463031220a7d")); + PrivateShieldedTRC20Parameters.Builder builder = PrivateShieldedTRC20Parameters.newBuilder(); try { JsonFormat.merge(parameter, builder, false); @@ -378,6 +379,39 @@ public void testCreateShieldedContractParameters2() throws ContractExeException Assert.assertEquals("Payment Address in ReceiveNote should not be empty", e.getMessage()); } + + String parameter2 = new String(ByteArray.fromHexString( + "7b0a202020202261736b223a2263323531336539653330383439343933326264383265306365353336" + + "363264313734323164393062373261383437316130613132623835353261333336653032222c0a202" + + "02020226e736b223a2234633662663364643461303634336432306236323866376534353938306335" + + "653138376630376135316436663365383661616631616239313663303765623064222c0a202020202" + + "26f766b223a2231376135386439613530353864613665343263613132636432383964306136616131" + + "363962393236633138653139626361353138623864366638363734653433222c0a202020202266726" + + "f6d5f616d6f756e74223a22313030222c0a2020202022736869656c6465645f7370656e6473223a5b" + + "0a20202020202020207b0a202020202020202020202020226e6f7465223a7b0a20202020202020202" + + "0202020202020202276616c7565223a3130302c0a2020202020202020202020202020202022706179" + + "6d656e745f61646472657373223a22222c0a202020202020202020202020202020202272636d223a2" + + "231366236663565343034343461623765656162313161653636313363323766333531313739373165" + + "666138376237313536306235383133383239633933393064220a2020202020202020202020207d0a2" + + "0202020202020207d0a202020205d2c0a2020202022736869656c6465645f54524332305f636f6e74" + + "726163745f61646472657373223a22343134343030373937393335394543414333393542424433434" + + "546383036304433444632444333463031220a7d")); + + builder = PrivateShieldedTRC20Parameters.newBuilder(); + try { + JsonFormat.merge(parameter2, builder, false); + } catch (ParseException e) { + Assert.fail(); + } + + try { + wallet1.createShieldedContractParameters(builder.build()); + Assert.fail(); + } catch (Exception e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Payment Address in SpendNote should not be empty", + e.getMessage()); + } } @Test From b9a49120150340966a01bbb871aa579ab0eba3da Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 14 Feb 2025 20:09:41 +0800 Subject: [PATCH 1132/1197] add test case of generateFilterId --- .../src/test/java/org/tron/core/jsonrpc/JsonRpcTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/framework/src/test/java/org/tron/core/jsonrpc/JsonRpcTest.java b/framework/src/test/java/org/tron/core/jsonrpc/JsonRpcTest.java index e75e4b17ab5..c9e6d6a2330 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/JsonRpcTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/JsonRpcTest.java @@ -19,6 +19,7 @@ import org.tron.common.utils.ByteUtil; import org.tron.common.utils.Commons; import org.tron.core.exception.JsonRpcInvalidParamsException; +import org.tron.core.services.jsonrpc.JsonRpcApiUtil; import org.tron.core.services.jsonrpc.TronJsonRpc.FilterRequest; import org.tron.core.services.jsonrpc.filters.LogBlockQuery; import org.tron.core.services.jsonrpc.filters.LogFilter; @@ -352,4 +353,9 @@ public void testGetConditionWithHashCollision() { Assert.fail(); } } + + @Test + public void testGenerateFilterId() { + Assert.assertEquals(32, JsonRpcApiUtil.generateFilterId().length()); + } } From e72dbc4efbac614520db5e5dbd0c68014f71ce3f Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Fri, 14 Feb 2025 20:58:24 +0800 Subject: [PATCH 1133/1197] format style of ApiUtilTest --- framework/src/test/java/org/tron/core/jsonrpc/ApiUtilTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/test/java/org/tron/core/jsonrpc/ApiUtilTest.java b/framework/src/test/java/org/tron/core/jsonrpc/ApiUtilTest.java index 84aba180138..570e7ed3498 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/ApiUtilTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/ApiUtilTest.java @@ -1,6 +1,5 @@ package org.tron.core.jsonrpc; - import static org.tron.common.utils.Commons.decodeFromBase58Check; import static org.tron.keystore.Wallet.generateRandomBytes; From a6b21420dcc6d344798057cc6c81da0c05aa7b80 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Sat, 15 Feb 2025 09:53:06 +0800 Subject: [PATCH 1134/1197] modify test case of isShieldedTRC20ContractNoteSpent --- .../src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java b/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java index ff30537ee7a..2c97473b6c3 100644 --- a/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java +++ b/framework/src/test/java/org/tron/core/ShieldedTRC20BuilderTest.java @@ -2269,7 +2269,7 @@ public void testscanShieldedTRC20NotesByOvk() throws Exception { } } - @Test(expected = IllegalArgumentException.class) + @Test(expected = ZksnarkException.class) public void isShieldedTRC20ContractNoteSpent() throws Exception { int statNum = 9200; int endNum = 9240; From ff44e093610613ed3e96cc3f079a19cb49fe0552 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Mon, 17 Feb 2025 11:48:10 +0800 Subject: [PATCH 1135/1197] solve the sonar problem --- .../core/services/event/BlockEventGet.java | 63 ++++++++++--------- .../services/event/HistoryEventService.java | 7 ++- .../core/services/event/bo/BlockEvent.java | 20 ++++-- .../tron/core/services/event/bo/Event.java | 8 ++- .../event/bo/SmartContractTrigger.java | 10 ++- 5 files changed, 69 insertions(+), 39 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java b/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java index 8ffc333eda4..25fb54bce8c 100644 --- a/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java +++ b/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java @@ -59,7 +59,6 @@ public BlockEvent getBlockEvent(long blockNum) throws Exception { blockEvent.setBlockId(block.getBlockId()); blockEvent.setParentId(block.getParentBlockId()); blockEvent.setSolidId(manager.getChainBaseManager().getBlockIdByNum(solidNum)); - blockEvent.setBlockTime(block.getTimeStamp()); if (instance.isBlockLogTriggerEnable()) { blockEvent.setBlockLogTriggerCapsule(getBlockLogTrigger(block, solidNum)); } @@ -145,11 +144,45 @@ private List parseLogs(Protocol.Transaction tx, Map addrMap = new HashMap<>(); Map abiMap = new HashMap<>(); + parseLogs(logs, originAddress, addrMap, abiMap); + int index = 1; for (Protocol.TransactionInfo.Log log : logs) { byte[] contractAddress = TransactionTrace .convertToTronAddress(log.getAddress().toByteArray()); + String strContractAddress = + ArrayUtils.isEmpty(contractAddress) ? "" : StringUtil.encode58Check(contractAddress); + SmartContractOuterClass.SmartContract.ABI abi = abiMap.get(strContractAddress); + ContractTrigger event = new ContractTrigger(); + String creatorAddr = addrMap.get(strContractAddress); + String txId = Hex.toHexString(txInfo.getId().toByteArray()); + event.setUniqueId(txId + "_" + index); + event.setTransactionId(txId); + event.setContractAddress(strContractAddress); + event.setOriginAddress(originAddress); + event.setCallerAddress(""); + event.setCreatorAddress(StringUtils.isEmpty(creatorAddr) ? "" : creatorAddr); + event.setBlockNumber(txInfo.getBlockNumber()); + event.setTimeStamp(txInfo.getBlockTimeStamp()); + event.setLogInfo(buildLogInfo(log)); + event.setAbi(abi); + + list.add(event); + index++; + } + + return list; + } + + private void parseLogs(List logs, + String originAddress, + Map addrMap, Map abiMap) { + for (Protocol.TransactionInfo.Log log : logs) { + + byte[] contractAddress = TransactionTrace + .convertToTronAddress(log.getAddress().toByteArray()); String strContractAddr = ArrayUtils.isEmpty(contractAddress) ? "" : StringUtil.encode58Check(contractAddress); if (addrMap.get(strContractAddr) != null) { @@ -175,34 +208,6 @@ private List parseLogs(Protocol.Transaction tx, addrMap.put(strContractAddr, creatorAddr); abiMap.put(strContractAddr, abi); } - - int index = 1; - for (Protocol.TransactionInfo.Log log : logs) { - - byte[] contractAddress = TransactionTrace - .convertToTronAddress(log.getAddress().toByteArray()); - String strContractAddress = - ArrayUtils.isEmpty(contractAddress) ? "" : StringUtil.encode58Check(contractAddress); - SmartContractOuterClass.SmartContract.ABI abi = abiMap.get(strContractAddress); - ContractTrigger event = new ContractTrigger(); - String creatorAddr = addrMap.get(strContractAddress); - String txId = Hex.toHexString(txInfo.getId().toByteArray()); - event.setUniqueId(txId + "_" + index); - event.setTransactionId(txId); - event.setContractAddress(strContractAddress); - event.setOriginAddress(originAddress); - event.setCallerAddress(""); - event.setCreatorAddress(StringUtils.isEmpty(creatorAddr) ? "" : creatorAddr); - event.setBlockNumber(txInfo.getBlockNumber()); - event.setTimeStamp(txInfo.getBlockTimeStamp()); - event.setLogInfo(buildLogInfo(log)); - event.setAbi(abi); - - list.add(event); - index++; - } - - return list; } private LogInfo buildLogInfo(Protocol.TransactionInfo.Log log) { diff --git a/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java b/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java index 0f26490d16b..af9b7818640 100644 --- a/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java +++ b/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java @@ -61,8 +61,11 @@ private void syncEvent() { Thread.sleep(30); } initEventService(manager.getChainBaseManager().getBlockIdByNum(endNum)); - } catch (Exception e) { - logger.error("Sync event failed.", e); + } catch (InterruptedException e1) { + logger.warn("Sync event interrupted."); + Thread.currentThread().interrupt(); + } catch (Exception e2) { + logger.error("Sync event failed.", e2); } } diff --git a/framework/src/main/java/org/tron/core/services/event/bo/BlockEvent.java b/framework/src/main/java/org/tron/core/services/event/bo/BlockEvent.java index 9e314bc7d5a..f573a486738 100644 --- a/framework/src/main/java/org/tron/core/services/event/bo/BlockEvent.java +++ b/framework/src/main/java/org/tron/core/services/event/bo/BlockEvent.java @@ -1,22 +1,34 @@ package org.tron.core.services.event.bo; import java.util.List; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; import org.tron.common.logsfilter.capsule.BlockLogTriggerCapsule; import org.tron.common.logsfilter.capsule.SolidityTriggerCapsule; import org.tron.common.logsfilter.capsule.TransactionLogTriggerCapsule; import org.tron.core.capsule.BlockCapsule; -@Data public class BlockEvent { + @Getter + @Setter private BlockCapsule.BlockId blockId; + @Getter + @Setter private BlockCapsule.BlockId parentId; + @Getter + @Setter private BlockCapsule.BlockId solidId; - private long blockTime; - + @Getter + @Setter private BlockLogTriggerCapsule blockLogTriggerCapsule; + @Getter + @Setter private List transactionLogTriggerCapsules; + @Getter + @Setter private SolidityTriggerCapsule solidityTriggerCapsule; + @Getter + @Setter private SmartContractTrigger smartContractTrigger; public BlockEvent() {} diff --git a/framework/src/main/java/org/tron/core/services/event/bo/Event.java b/framework/src/main/java/org/tron/core/services/event/bo/Event.java index 142e1be3c22..7d99747c087 100644 --- a/framework/src/main/java/org/tron/core/services/event/bo/Event.java +++ b/framework/src/main/java/org/tron/core/services/event/bo/Event.java @@ -1,10 +1,14 @@ package org.tron.core.services.event.bo; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; -@Data public class Event { + @Getter + @Setter private boolean isRemove; + @Getter + @Setter private BlockEvent blockEvent; public Event(BlockEvent blockEvent, boolean isRemove) { diff --git a/framework/src/main/java/org/tron/core/services/event/bo/SmartContractTrigger.java b/framework/src/main/java/org/tron/core/services/event/bo/SmartContractTrigger.java index 7413c309169..e981d5db7da 100644 --- a/framework/src/main/java/org/tron/core/services/event/bo/SmartContractTrigger.java +++ b/framework/src/main/java/org/tron/core/services/event/bo/SmartContractTrigger.java @@ -2,13 +2,19 @@ import java.util.ArrayList; import java.util.List; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; import org.tron.common.logsfilter.trigger.ContractEventTrigger; import org.tron.common.logsfilter.trigger.ContractLogTrigger; -@Data public class SmartContractTrigger { + @Getter + @Setter private List contractLogTriggers = new ArrayList<>(); + @Getter + @Setter private List contractEventTriggers = new ArrayList<>(); + @Getter + @Setter private List redundancies = new ArrayList<>(); } From 8249971ddd9a34155972d2d6a0eecac0a374ae04 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 8 Jul 2024 15:17:37 +0800 Subject: [PATCH 1136/1197] feat(build): enable dependency checksum sha256 verification This file was automatically generated using `./gradlew --write-verification-metadata sha256 help` --- gradle/verification-metadata.xml | 2565 ++++++++++++++++++++++++++++++ 1 file changed, 2565 insertions(+) create mode 100644 gradle/verification-metadata.xml diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml new file mode 100644 index 00000000000..3e061306873 --- /dev/null +++ b/gradle/verification-metadata.xml @@ -0,0 +1,2565 @@ + + + + true + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From a464aa8b8c905a1b1ddd19d0f9706037d96bb413 Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 17 Feb 2025 15:35:58 +0800 Subject: [PATCH 1137/1197] feat(tvm): compare dataword in mcopy energy cost --- actuator/src/main/java/org/tron/core/vm/EnergyCost.java | 8 +++----- .../java/org/tron/core/vm/repository/RepositoryImpl.java | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java index 74dbaa741c3..b758438c940 100644 --- a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java +++ b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java @@ -1,7 +1,5 @@ package org.tron.core.vm; -import static org.tron.common.math.Maths.max; - import java.math.BigInteger; import org.tron.common.runtime.vm.DataWord; import org.tron.core.vm.config.VMConfig; @@ -248,9 +246,9 @@ public static long getMCopyCost(Program program) { Stack stack = program.getStack(); long oldMemSize = program.getMemSize(); - int dstOffset = stack.peek().intValue(); - int srcOffset = stack.get(stack.size() - 2).intValue(); - DataWord maxOffset = new DataWord(max(dstOffset, srcOffset, VMConfig.allowStrictMath2())); + DataWord dstOffset = stack.peek(); + DataWord srcOffset = stack.get(stack.size() - 2); + DataWord maxOffset = dstOffset.compareTo(srcOffset) > 0 ? dstOffset : srcOffset; return VERY_LOW_TIER + calcMemEnergy(oldMemSize, memNeeded(maxOffset, stack.get(stack.size() - 3)), stack.get(stack.size() - 3).longValueSafe(), Op.MCOPY); diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 321efb729b9..e81aba2a862 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -456,7 +456,7 @@ public byte[] getTransientStorageValue(byte[] address, byte[] key) { byte[] value; if (parent != null) { value = parent.getTransientStorageValue(address, key); - } else{ + } else { value = null; } From 01dd7e1183175c40f4232707622eab9e11ec850e Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 17 Feb 2025 18:05:34 +0800 Subject: [PATCH 1138/1197] fix(tvm): clone tload value --- actuator/src/main/java/org/tron/core/vm/OperationActions.java | 2 +- .../test/java/org/tron/common/runtime/vm/OperationsTest.java | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index 1208a94b61b..95370ff16bb 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -649,7 +649,7 @@ public static void tLoadAction(Program program) { byte[] data = program.getContractState().getTransientStorageValue(address.getData(), key.getData()); - DataWord value = data != null ? new DataWord(data) : DataWord.ZERO(); + DataWord value = data != null ? new DataWord(data).clone() : DataWord.ZERO(); program.stackPush(value); program.step(); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java index 0eb00244d21..01d54c2194a 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java @@ -960,6 +960,10 @@ public void testTransientStorageOperations() throws ContractValidateException { program.getContractState().getTransientStorageValue( program.getContractAddress().getData(), new DataWord(0x01).getData())); + op = new byte[] {0x60, 0x02, 0x60, 0x01, 0x5c, 0x16}; + program = new Program(op, op, invoke, interTrx); + testOperations(program); + // TLOAD = 0x5c; op = new byte[] {0x60, 0x01, 0x5c}; program = new Program(op, op, invoke, interTrx); From 973a0af4b8f6a1c007f22a695a40fa90285054c3 Mon Sep 17 00:00:00 2001 From: imalasong <2879499479@qq.com> Date: Tue, 18 Feb 2025 17:17:25 +0800 Subject: [PATCH 1139/1197] opt(framework): optimization Help Instruction Signed-off-by: xiaochangbai <704566072@qq.com> --- .../src/main/java/org/tron/core/config/args/Args.java | 7 +++++++ framework/src/main/java/org/tron/program/FullNode.java | 8 -------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 7397b69cde3..34c0b4a8b7e 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -363,6 +363,13 @@ public static void setParam(final String[] args, final String confFileName) { exit(0); } + if (PARAMETER.isHelp()) { + JCommander jCommander = JCommander.newBuilder().addObject(Args.PARAMETER).build(); + jCommander.parse(args); + Args.printHelp(jCommander); + exit(0); + } + Config config = Configuration.getByFileName(PARAMETER.shellConfFileName, confFileName); if (config.hasPath(Constant.NET_TYPE) diff --git a/framework/src/main/java/org/tron/program/FullNode.java b/framework/src/main/java/org/tron/program/FullNode.java index 0fd87eb5de0..0ffcca909ff 100644 --- a/framework/src/main/java/org/tron/program/FullNode.java +++ b/framework/src/main/java/org/tron/program/FullNode.java @@ -2,7 +2,6 @@ import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.joran.JoranConfigurator; -import com.beust.jcommander.JCommander; import java.io.File; import lombok.extern.slf4j.Slf4j; import org.slf4j.LoggerFactory; @@ -56,13 +55,6 @@ public static void main(String[] args) { load(parameter.getLogbackPath()); - if (parameter.isHelp()) { - JCommander jCommander = JCommander.newBuilder().addObject(Args.PARAMETER).build(); - jCommander.parse(args); - Args.printHelp(jCommander); - return; - } - if (Args.getInstance().isDebug()) { logger.info("in debug mode, it won't check energy time"); } else { From 41f751fc7a2ac4ca74e1274206fe7299491a9942 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Tue, 18 Feb 2025 17:26:38 +0800 Subject: [PATCH 1140/1197] feat(net): optimize handshake log information --- .../java/org/tron/core/net/service/relay/RelayService.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java index b871596b373..35d13ccf64f 100644 --- a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java @@ -145,9 +145,10 @@ public boolean checkHelloMessage(HelloMessage message, Channel channel) { } if (getPeerCountByAddress(msg.getAddress()) >= MAX_PEER_COUNT_PER_ADDRESS) { - logger.warn("HelloMessage from {}, the number of peers of {} exceeds 2.", + logger.warn("HelloMessage from {}, the number of peers of {} exceeds {}.", channel.getInetAddress(), - ByteArray.toHexString(msg.getAddress().toByteArray())); + ByteArray.toHexString(msg.getAddress().toByteArray()), + MAX_PEER_COUNT_PER_ADDRESS); return false; } From 5f39d97d273da1c6d93ba5c3862d4ea9e1b5d44f Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 19 Feb 2025 16:11:50 +0800 Subject: [PATCH 1141/1197] don't use prefix 41 when add address to sensitiveCache map --- .../java/org/tron/core/net/service/relay/RelayService.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java index 35d13ccf64f..a1afa7dd1a8 100644 --- a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java @@ -21,8 +21,6 @@ import org.tron.common.log.layout.DesensitizedConverter; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.Sha256Hash; import org.tron.core.ChainBaseManager; import org.tron.core.capsule.TransactionCapsule; @@ -169,10 +167,8 @@ public boolean checkHelloMessage(HelloMessage message, Channel channel) { } if (flag) { TronNetService.getP2pConfig().getTrustNodes().add(channel.getInetAddress()); - byte[] addressByte = ByteUtil.merge(new byte[] {DecodeUtil.addressPreFixByte}, - msg.getAddress().toByteArray()); DesensitizedConverter.addSensitive(channel.getInetAddress().toString().substring(1), - ByteArray.toHexString(addressByte)); + ByteArray.toHexString(msg.getAddress().toByteArray())); } return flag; } catch (Exception e) { From 964daeb07a908721e448e803d6ddaf47923f951a Mon Sep 17 00:00:00 2001 From: Asuka Date: Wed, 19 Feb 2025 18:43:27 +0800 Subject: [PATCH 1142/1197] fix(cfg): the setParam method overrides the internal tx switches initialized by @Parameter --- .../java/org/tron/core/config/args/Args.java | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index d94dfc52f0a..45fedbb3906 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -915,17 +915,24 @@ public static void setParam(final Config config) { PARAMETER.vmTrace = config.hasPath(Constant.VM_TRACE) && config.getBoolean(Constant.VM_TRACE); - PARAMETER.saveInternalTx = - config.hasPath(Constant.VM_SAVE_INTERNAL_TX) - && config.getBoolean(Constant.VM_SAVE_INTERNAL_TX); + if (config.hasPath(Constant.VM_SAVE_INTERNAL_TX)) { + PARAMETER.saveInternalTx = config.getBoolean(Constant.VM_SAVE_INTERNAL_TX); + } - PARAMETER.saveFeaturedInternalTx = - config.hasPath(Constant.VM_SAVE_FEATURED_INTERNAL_TX) - && config.getBoolean(Constant.VM_SAVE_FEATURED_INTERNAL_TX); + if (config.hasPath(Constant.VM_SAVE_FEATURED_INTERNAL_TX)) { + PARAMETER.saveFeaturedInternalTx = config.getBoolean(Constant.VM_SAVE_FEATURED_INTERNAL_TX); + } - PARAMETER.saveCancelAllUnfreezeV2Details = - config.hasPath(Constant.VM_SAVE_CANCEL_ALL_UNFREEZE_V2_DETAILS) - && config.getBoolean(Constant.VM_SAVE_CANCEL_ALL_UNFREEZE_V2_DETAILS); + if (config.hasPath(Constant.VM_SAVE_CANCEL_ALL_UNFREEZE_V2_DETAILS)) { + PARAMETER.saveCancelAllUnfreezeV2Details = + config.getBoolean(Constant.VM_SAVE_CANCEL_ALL_UNFREEZE_V2_DETAILS); + } + + if (PARAMETER.saveCancelAllUnfreezeV2Details + && (!PARAMETER.saveInternalTx || !PARAMETER.saveFeaturedInternalTx)) { + logger.warn("Configuring [vm.saveCancelAllUnfreezeV2Details] won't work as " + + "vm.saveInternalTx or vm.saveFeaturedInternalTx is off."); + } // PARAMETER.allowShieldedTransaction = // config.hasPath(Constant.COMMITTEE_ALLOW_SHIELDED_TRANSACTION) ? config From ca285532149b7a677936c01ddd9b6faf05d351a7 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 20 Feb 2025 17:29:41 +0800 Subject: [PATCH 1143/1197] feat(system.exit): adapt TronError for ExecutorService --- .../tron/core/service/RewardViCalService.java | 2 +- .../common/es/ExecutorServiceManager.java | 29 +++++++++++++++++++ .../org/tron/common/exit/ExitManager.java | 2 +- .../org/tron/consensus/dpos/DposTask.java | 6 +++- .../main/java/org/tron/core/db/Manager.java | 10 +++++-- .../TransactionsMsgHandler.java | 8 +++-- .../core/net/service/sync/SyncService.java | 4 +-- 7 files changed, 50 insertions(+), 11 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java b/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java index b3ef76b091e..f88fd02c539 100644 --- a/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java +++ b/chainbase/src/main/java/org/tron/core/service/RewardViCalService.java @@ -82,7 +82,7 @@ public void init() { // checkpoint is flushed to db, we can start rewardViCalService immediately lastBlockNumber = Long.MAX_VALUE; } - es.scheduleWithFixedDelay(this::maybeRun, 0, 3, TimeUnit.SECONDS); + ExecutorServiceManager.scheduleWithFixedDelay(es, this::maybeRun, 0, 3, TimeUnit.SECONDS); } private boolean enableNewRewardAlgorithm() { diff --git a/common/src/main/java/org/tron/common/es/ExecutorServiceManager.java b/common/src/main/java/org/tron/common/es/ExecutorServiceManager.java index 196d44ba722..779a8edf75d 100644 --- a/common/src/main/java/org/tron/common/es/ExecutorServiceManager.java +++ b/common/src/main/java/org/tron/common/es/ExecutorServiceManager.java @@ -4,10 +4,13 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; +import org.tron.common.exit.ExitManager; @Slf4j(topic = "common-executor") public class ExecutorServiceManager { @@ -80,4 +83,30 @@ public static void shutdownAndAwaitTermination(ExecutorService pool, String name } logger.info("Pool {} shutdown done", name); } + + public static Future submit(ExecutorService es, Runnable task) { + return es.submit(() -> { + try { + task.run(); + } catch (Throwable e) { + ExitManager.findTronError(e).ifPresent(ExitManager::logAndExit); + throw e; + } + }); + } + + public static ScheduledFuture scheduleWithFixedDelay(ScheduledExecutorService es, + Runnable command, + long initialDelay, + long delay, + TimeUnit unit) { + return es.scheduleWithFixedDelay(() -> { + try { + command.run(); + } catch (Throwable e) { + ExitManager.findTronError(e).ifPresent(ExitManager::logAndExit); + throw e; + } + }, initialDelay, delay, unit); + } } diff --git a/common/src/main/java/org/tron/common/exit/ExitManager.java b/common/src/main/java/org/tron/common/exit/ExitManager.java index ff3e0de734b..d80b7838c08 100644 --- a/common/src/main/java/org/tron/common/exit/ExitManager.java +++ b/common/src/main/java/org/tron/common/exit/ExitManager.java @@ -44,7 +44,7 @@ public static Optional findTronError(Throwable e) { return Optional.empty(); } - private static void logAndExit(TronError exit) { + public static void logAndExit(TronError exit) { final int code = exit.getErrCode().getCode(); logger.error("Shutting down with code: {}.", exit.getErrCode(), exit); Thread exitThread = exitThreadFactory.newThread(() -> System.exit(code)); diff --git a/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java b/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java index 8d5697cdc89..9e42552c80f 100644 --- a/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java +++ b/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java @@ -11,6 +11,7 @@ import org.springframework.stereotype.Component; import org.springframework.util.ObjectUtils; import org.tron.common.es.ExecutorServiceManager; +import org.tron.common.exit.ExitManager; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; @@ -68,10 +69,13 @@ public void init() { Thread.currentThread().interrupt(); } catch (Throwable throwable) { logger.error("Produce block error.", throwable); + ExitManager.findTronError(throwable).ifPresent(e -> { + throw e; + }); } } }; - produceExecutor.submit(runnable); + ExecutorServiceManager.submit(produceExecutor, runnable); logger.info("DPoS task started."); } diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 993198d60f3..55c248b1c14 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -53,6 +53,7 @@ import org.tron.common.args.GenesisBlock; import org.tron.common.bloom.Bloom; import org.tron.common.es.ExecutorServiceManager; +import org.tron.common.exit.ExitManager; import org.tron.common.logsfilter.EventPluginLoader; import org.tron.common.logsfilter.FilterQuery; import org.tron.common.logsfilter.capsule.BlockFilterCapsule; @@ -293,6 +294,9 @@ public class Manager { Metrics.counterInc(MetricKeys.Counter.TXS, 1, MetricLabels.Counter.TXS_FAIL, MetricLabels.Counter.TXS_FAIL_ERROR); } + ExitManager.findTronError(ex).ifPresent(e -> { + throw e; + }); } finally { if (tx != null && getRePushTransactions().remove(tx)) { Metrics.gaugeInc(MetricKeys.Gauge.MANAGER_QUEUE, -1, @@ -550,18 +554,18 @@ public void init() { validateSignService = ExecutorServiceManager .newFixedThreadPool(validateSignName, Args.getInstance().getValidateSignThreadNum()); rePushEs = ExecutorServiceManager.newSingleThreadExecutor(rePushEsName, true); - rePushEs.submit(rePushLoop); + ExecutorServiceManager.submit(rePushEs, rePushLoop); // add contract event listener for subscribing if (Args.getInstance().isEventSubscribe()) { startEventSubscribing(); triggerEs = ExecutorServiceManager.newSingleThreadExecutor(triggerEsName, true); - triggerEs.submit(triggerCapsuleProcessLoop); + ExecutorServiceManager.submit(triggerEs, triggerCapsuleProcessLoop); } // start json rpc filter process if (CommonParameter.getInstance().isJsonRpcFilterEnabled()) { filterEs = ExecutorServiceManager.newSingleThreadExecutor(filterEsName); - filterEs.submit(filterProcessLoop); + ExecutorServiceManager.submit(filterEs, filterProcessLoop); } //initStoreFactory diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java index 0ea0f24e7ae..5fab8bc6f33 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java @@ -83,7 +83,8 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep dropSmartContractCount++; } } else { - trxHandlePool.submit(() -> handleTransaction(peer, new TransactionMessage(trx))); + ExecutorServiceManager.submit( + trxHandlePool, () -> handleTransaction(peer, new TransactionMessage(trx))); } } @@ -109,11 +110,12 @@ private void check(PeerConnection peer, TransactionsMessage msg) throws P2pExcep } private void handleSmartContract() { - smartContractExecutor.scheduleWithFixedDelay(() -> { + ExecutorServiceManager.scheduleWithFixedDelay(smartContractExecutor, () -> { try { while (queue.size() < MAX_SMART_CONTRACT_SUBMIT_SIZE && smartContractQueue.size() > 0) { TrxEvent event = smartContractQueue.take(); - trxHandlePool.submit(() -> handleTransaction(event.getPeer(), event.getMsg())); + ExecutorServiceManager.submit( + trxHandlePool, () -> handleTransaction(event.getPeer(), event.getMsg())); } } catch (InterruptedException e) { logger.warn("Handle smart server interrupted"); diff --git a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java index 0bce4b8baa5..e387329c467 100644 --- a/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java +++ b/framework/src/main/java/org/tron/core/net/service/sync/SyncService.java @@ -70,7 +70,7 @@ public class SyncService { private final long syncFetchBatchNum = Args.getInstance().getSyncFetchBatchNum(); public void init() { - fetchExecutor.scheduleWithFixedDelay(() -> { + ExecutorServiceManager.scheduleWithFixedDelay(fetchExecutor, () -> { try { if (fetchFlag) { fetchFlag = false; @@ -81,7 +81,7 @@ public void init() { } }, 10, 1, TimeUnit.SECONDS); - blockHandleExecutor.scheduleWithFixedDelay(() -> { + ExecutorServiceManager.scheduleWithFixedDelay(blockHandleExecutor, () -> { try { if (handleFlag) { handleFlag = false; From 6a4f7a0466a42ae531de9bec80324a76dce22d3b Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Fri, 21 Feb 2025 11:17:33 +0800 Subject: [PATCH 1144/1197] feat(log): optimize event service logs --- framework/src/main/java/org/tron/core/db/Manager.java | 2 -- .../org/tron/core/net/service/relay/RelayService.java | 2 +- .../org/tron/core/services/event/BlockEventCache.java | 2 +- .../org/tron/core/services/event/BlockEventLoad.java | 4 ++-- .../tron/core/services/event/HistoryEventService.java | 4 ++-- .../tron/core/services/event/RealtimeEventService.java | 6 +++--- .../tron/core/services/event/SolidEventService.java | 10 +++++----- 7 files changed, 14 insertions(+), 16 deletions(-) diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 55c248b1c14..096476a1bbe 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -2107,8 +2107,6 @@ private void startEventSubscribing() { private void postSolidityFilter(final long oldSolidNum, final long latestSolidifiedBlockNumber) { if (oldSolidNum >= latestSolidifiedBlockNumber) { - logger.warn("Post solidity filter failed, oldSolidity: {} >= latestSolidity: {}.", - oldSolidNum, latestSolidifiedBlockNumber); return; } diff --git a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java index a1afa7dd1a8..161e918336b 100644 --- a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java @@ -142,7 +142,7 @@ public boolean checkHelloMessage(HelloMessage message, Channel channel) { return false; } - if (getPeerCountByAddress(msg.getAddress()) >= MAX_PEER_COUNT_PER_ADDRESS) { + if (getPeerCountByAddress(msg.getAddress()) > MAX_PEER_COUNT_PER_ADDRESS) { logger.warn("HelloMessage from {}, the number of peers of {} exceeds {}.", channel.getInetAddress(), ByteArray.toHexString(msg.getAddress().toByteArray()), diff --git a/framework/src/main/java/org/tron/core/services/event/BlockEventCache.java b/framework/src/main/java/org/tron/core/services/event/BlockEventCache.java index 40abae07946..aac457ba29b 100644 --- a/framework/src/main/java/org/tron/core/services/event/BlockEventCache.java +++ b/framework/src/main/java/org/tron/core/services/event/BlockEventCache.java @@ -43,7 +43,7 @@ public static void init(BlockCapsule.BlockId blockId) { } public static void add(BlockEvent blockEvent) throws EventException { - logger.info("Add block event, {}", blockEvent.getBlockId().getString(), + logger.info("Add block event, {}, {}", blockEvent.getBlockId().getString(), blockEvent.getParentId().getString()); if (blockEventMap.get(blockEvent.getParentId()) == null) { throw new EventException("unlink BlockEvent, " diff --git a/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java b/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java index 1af9d768c19..bebe3bcbc60 100644 --- a/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java +++ b/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java @@ -33,9 +33,9 @@ public void init() { executor.scheduleWithFixedDelay(() -> { try { load(); - } catch (Exception exception) { + } catch (Exception e) { close(); - logger.error("Spread thread error", exception); + logger.error("Event load service fail.", e); } }, 100, 100, TimeUnit.MILLISECONDS); logger.info("Event load service start."); diff --git a/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java b/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java index af9b7818640..73422944f08 100644 --- a/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java +++ b/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java @@ -62,10 +62,10 @@ private void syncEvent() { } initEventService(manager.getChainBaseManager().getBlockIdByNum(endNum)); } catch (InterruptedException e1) { - logger.warn("Sync event interrupted."); + logger.warn("History event service interrupted."); Thread.currentThread().interrupt(); } catch (Exception e2) { - logger.error("Sync event failed.", e2); + logger.error("History event service fail.", e2); } } diff --git a/framework/src/main/java/org/tron/core/services/event/RealtimeEventService.java b/framework/src/main/java/org/tron/core/services/event/RealtimeEventService.java index 8375b2fd114..0f46115bc5a 100644 --- a/framework/src/main/java/org/tron/core/services/event/RealtimeEventService.java +++ b/framework/src/main/java/org/tron/core/services/event/RealtimeEventService.java @@ -38,7 +38,7 @@ public void init() { try { work(); } catch (Exception e) { - logger.info("Real-time event service fail. {}", e); + logger.error("Realtime event service fail.", e); } }, 1, 1, TimeUnit.SECONDS); logger.info("Realtime event service start."); @@ -81,7 +81,7 @@ public void flush(BlockEvent blockEvent, boolean isRemove) { && !instance.isTransactionLogTriggerSolidified() && !isRemove) { if (blockEvent.getTransactionLogTriggerCapsules() == null) { - logger.info("TransactionLogTriggerCapsules is null. {}", + logger.warn("TransactionLogTriggerCapsules is null. {}", blockEvent.getBlockId().getString()); } else { blockEvent.getTransactionLogTriggerCapsules().forEach(v -> @@ -91,7 +91,7 @@ public void flush(BlockEvent blockEvent, boolean isRemove) { if (instance.isContractEventTriggerEnable()) { if (blockEvent.getSmartContractTrigger() == null) { - logger.info("SmartContractTrigger is null. {}", blockEvent.getBlockId().getString()); + logger.warn("SmartContractTrigger is null. {}", blockEvent.getBlockId().getString()); } else { blockEvent.getSmartContractTrigger().getContractEventTriggers().forEach(v -> { v.setTriggerName(Trigger.CONTRACTEVENT_TRIGGER_NAME); diff --git a/framework/src/main/java/org/tron/core/services/event/SolidEventService.java b/framework/src/main/java/org/tron/core/services/event/SolidEventService.java index 5bf83ea0da9..6178b247b1d 100644 --- a/framework/src/main/java/org/tron/core/services/event/SolidEventService.java +++ b/framework/src/main/java/org/tron/core/services/event/SolidEventService.java @@ -29,8 +29,8 @@ public void init() { executor.scheduleWithFixedDelay(() -> { try { work(); - } catch (Exception exception) { - logger.error("Spread thread error", exception); + } catch (Exception e) { + logger.error("Solid event service fail.", e); } }, 1, 1, TimeUnit.SECONDS); logger.info("Solid event service start."); @@ -67,7 +67,7 @@ public void flush(BlockEvent blockEvent) { if (instance.isTransactionLogTriggerEnable() && instance.isTransactionLogTriggerSolidified()) { if (blockEvent.getTransactionLogTriggerCapsules() == null) { - logger.info("TransactionLogTrigger is null. {}", blockEvent.getBlockId()); + logger.warn("TransactionLogTrigger is null. {}", blockEvent.getBlockId()); } else { blockEvent.getTransactionLogTriggerCapsules().forEach(v -> manager.getTriggerCapsuleQueue().offer(v)); @@ -76,7 +76,7 @@ public void flush(BlockEvent blockEvent) { if (instance.isSolidityEventTriggerEnable()) { if (blockEvent.getSmartContractTrigger() == null) { - logger.info("SmartContractTrigger is null. {}", blockEvent.getBlockId()); + logger.warn("SmartContractTrigger is null. {}", blockEvent.getBlockId()); } else { blockEvent.getSmartContractTrigger().getContractEventTriggers().forEach(v -> { v.setTriggerName(Trigger.SOLIDITYEVENT_TRIGGER_NAME); @@ -100,7 +100,7 @@ public void flush(BlockEvent blockEvent) { if (instance.isSolidityTriggerEnable()) { if (blockEvent.getSolidityTriggerCapsule() == null) { - logger.info("SolidityTrigger is null. {}", blockEvent.getBlockId()); + logger.warn("SolidityTrigger is null. {}", blockEvent.getBlockId()); } else { manager.getTriggerCapsuleQueue().offer(blockEvent.getSolidityTriggerCapsule()); } From 128b5d35a4f8514db40abfcfd811cdd464bb4ef9 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 21 Feb 2025 15:55:26 +0800 Subject: [PATCH 1145/1197] feat(dependencies): bump logback from 1.2.9 to 1.2.13 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index aefae7956ec..14b095b1795 100644 --- a/build.gradle +++ b/build.gradle @@ -39,7 +39,7 @@ subprojects { dependencies { implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25' implementation group: 'org.slf4j', name: 'jcl-over-slf4j', version: '1.7.25' - implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.9' + implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.13' implementation "com.google.code.findbugs:jsr305:3.0.0" implementation group: 'org.springframework', name: 'spring-context', version: '5.3.18' implementation group: 'org.springframework', name: 'spring-tx', version: '5.3.18' From 698f895a1633d6b5d0297e243112bb733aa3089b Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 24 Feb 2025 14:28:41 +0800 Subject: [PATCH 1146/1197] reactor(actuator):rename allowStrictMath2 to disableJavaLangMath --- .../tron/core/actuator/AbstractActuator.java | 26 +++++++-------- .../actuator/DelegateResourceActuator.java | 5 ++- .../actuator/MarketSellAssetActuator.java | 8 ++--- .../org/tron/core/actuator/VMActuator.java | 32 +++++++++---------- .../org/tron/core/utils/TransactionUtil.java | 4 +-- .../tron/core/vm/PrecompiledContracts.java | 2 +- .../main/java/org/tron/core/vm/VMUtils.java | 4 +-- .../org/tron/core/vm/config/ConfigLoader.java | 2 +- .../DelegateResourceProcessor.java | 3 +- .../UnDelegateResourceProcessor.java | 4 +-- .../UnfreezeBalanceProcessor.java | 4 +-- .../java/org/tron/core/vm/program/Memory.java | 6 ++-- .../org/tron/core/vm/program/Program.java | 10 +++--- .../core/vm/repository/RepositoryImpl.java | 6 ++-- .../org/tron/core/vm/utils/FreezeV2Util.java | 6 ++-- .../java/org/tron/common/utils/Commons.java | 2 +- .../org/tron/common/utils/ForkController.java | 2 +- .../org/tron/core/capsule/AccountCapsule.java | 4 +-- .../tron/core/capsule/ContractCapsule.java | 4 +-- .../core/capsule/ContractStateCapsule.java | 8 ++--- .../org/tron/core/capsule/ReceiptCapsule.java | 6 ++-- .../tron/core/capsule/utils/MarketUtils.java | 8 ++--- .../org/tron/core/db/EnergyProcessor.java | 4 +-- .../org/tron/core/db/ResourceProcessor.java | 18 +++++------ .../org/tron/core/db/TransactionTrace.java | 12 +++---- .../tron/core/service/MortgageService.java | 2 +- .../core/store/DynamicPropertiesStore.java | 8 ++--- .../org/tron/common/runtime/vm/DataWord.java | 4 +-- .../org/tron/core/vm/config/VMConfig.java | 10 +++--- .../src/main/java/org/tron/core/Wallet.java | 14 ++++---- .../main/java/org/tron/core/db/Manager.java | 20 ++++++------ .../test/java/org/tron/common/BaseTest.java | 2 +- .../runtime/vm/BandWidthRuntimeTest.java | 2 +- .../tron/common/runtime/vm/FreezeV2Test.java | 2 +- .../org/tron/common/runtime/vm/VoteTest.java | 4 +-- .../UpdateSettingContractActuatorTest.java | 6 ++-- .../java/org/tron/core/db/ManagerTest.java | 2 +- .../core/services/ProposalServiceTest.java | 4 +-- 38 files changed, 131 insertions(+), 139 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/AbstractActuator.java b/actuator/src/main/java/org/tron/core/actuator/AbstractActuator.java index 2f1bb450d1b..b5bdb9bcafc 100644 --- a/actuator/src/main/java/org/tron/core/actuator/AbstractActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/AbstractActuator.java @@ -69,15 +69,15 @@ public AbstractActuator setForkUtils(ForkController forkController) { } public long addExact(long x, long y) { - return Maths.addExact(x, y, chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + return Maths.addExact(x, y, this.disableJavaLangMath()); } public long addExact(int x, int y) { - return Maths.addExact(x, y, chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + return Maths.addExact(x, y, this.disableJavaLangMath()); } public long floorDiv(long x, long y) { - return Maths.floorDiv(x, y, chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + return Maths.floorDiv(x, y, this.disableJavaLangMath()); } public long floorDiv(long x, int y) { @@ -85,8 +85,7 @@ public long floorDiv(long x, int y) { } public long multiplyExact(long x, long y) { - return Maths.multiplyExact(x, y, - chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + return Maths.multiplyExact(x, y, this.disableJavaLangMath()); } public long multiplyExact(long x, int y) { @@ -94,21 +93,19 @@ public long multiplyExact(long x, int y) { } public int multiplyExact(int x, int y) { - return Maths.multiplyExact(x, y, - chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + return Maths.multiplyExact(x, y, this.disableJavaLangMath()); } public long subtractExact(long x, long y) { - return Maths.subtractExact(x, y, - chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + return Maths.subtractExact(x, y, this.disableJavaLangMath()); } public int min(int a, int b) { - return Maths.min(a, b, chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + return Maths.min(a, b, this.disableJavaLangMath()); } public long min(long a, long b) { - return Maths.min(a, b, chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + return Maths.min(a, b, this.disableJavaLangMath()); } public void adjustBalance(AccountStore accountStore, byte[] accountAddress, long amount) @@ -122,7 +119,10 @@ public void adjustBalance(AccountStore accountStore, byte[] accountAddress, long */ public void adjustBalance(AccountStore accountStore, AccountCapsule account, long amount) throws BalanceInsufficientException { - Commons.adjustBalance(accountStore, account, amount, - chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + Commons.adjustBalance(accountStore, account, amount, this.disableJavaLangMath()); + } + + private boolean disableJavaLangMath() { + return chainBaseManager.getDynamicPropertiesStore().disableJavaLangMath(); } } diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 90e91d8d3b2..547171486ee 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -15,7 +15,6 @@ import java.util.Arrays; import java.util.Objects; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.ArrayUtils; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; @@ -163,7 +162,7 @@ public boolean validate() throws ContractValidateException { long netUsage = (long) (accountNetUsage * TRX_PRECISION * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage, - dynamicStore.allowStrictMath2()); + dynamicStore.disableJavaLangMath()); if (ownerCapsule.getFrozenV2BalanceForBandwidth() - v2NetUsage < delegateBalance) { throw new ContractValidateException( "delegateBalance must be less than or equal to available FreezeBandwidthV2 balance"); @@ -177,7 +176,7 @@ public boolean validate() throws ContractValidateException { long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage, - dynamicStore.allowStrictMath2()); + dynamicStore.disableJavaLangMath()); if (ownerCapsule.getFrozenV2BalanceForEnergy() - v2EnergyUsage < delegateBalance) { throw new ContractValidateException( "delegateBalance must be less than or equal to available FreezeEnergyV2 balance"); diff --git a/actuator/src/main/java/org/tron/core/actuator/MarketSellAssetActuator.java b/actuator/src/main/java/org/tron/core/actuator/MarketSellAssetActuator.java index 43f21b716d8..b5b375ee391 100644 --- a/actuator/src/main/java/org/tron/core/actuator/MarketSellAssetActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/MarketSellAssetActuator.java @@ -400,10 +400,10 @@ private void matchSingleOrder(MarketOrderCapsule takerOrderCapsule, // => takerBuyTokenQuantityCurrent_A = takerSellTokenQuantityRemain_TRX * // makerSellTokenQuantity_A/makerBuyTokenQuantity_TRX - boolean useStrictMath2 = dynamicStore.allowStrictMath2(); + boolean disableMath = dynamicStore.disableJavaLangMath(); long takerBuyTokenQuantityRemain = MarketUtils .multiplyAndDivide(takerSellRemainQuantity, makerSellQuantity, makerBuyQuantity, - useStrictMath2); + disableMath); if (takerBuyTokenQuantityRemain == 0) { // quantity too small, return sellToken to user @@ -427,7 +427,7 @@ private void matchSingleOrder(MarketOrderCapsule takerOrderCapsule, makerBuyTokenQuantityReceive = MarketUtils .multiplyAndDivide(makerSellRemainQuantity, makerBuyQuantity, makerSellQuantity, - chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + chainBaseManager.getDynamicPropertiesStore().disableJavaLangMath()); takerBuyTokenQuantityReceive = makerOrderCapsule.getSellTokenQuantityRemain(); long takerSellTokenLeft = @@ -462,7 +462,7 @@ private void matchSingleOrder(MarketOrderCapsule takerOrderCapsule, // makerSellTokenQuantity_A/makerBuyTokenQuantity_TRX makerBuyTokenQuantityReceive = MarketUtils .multiplyAndDivide(makerSellRemainQuantity, makerBuyQuantity, makerSellQuantity, - chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + chainBaseManager.getDynamicPropertiesStore().disableJavaLangMath()); MarketUtils.updateOrderState(makerOrderCapsule, State.INACTIVE, marketAccountStore); if (makerBuyTokenQuantityReceive == 0) { diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 42ddc65c745..bd34c96a9d9 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -128,7 +128,7 @@ public void validate(Object object) throws ContractValidateException { if (isConstantCall && trx.getRawData().getFeeLimit() > 0) { maxEnergyLimit = min(maxEnergyLimit, trx.getRawData().getFeeLimit() / context.getStoreFactory().getChainBaseManager() - .getDynamicPropertiesStore().getEnergyFee(), VMConfig.allowStrictMath2()); + .getDynamicPropertiesStore().getEnergyFee(), VMConfig.disableJavaLangMath()); } blockCap = context.getBlockCap(); if ((VMConfig.allowTvmFreeze() || VMConfig.allowTvmFreezeV2()) @@ -566,9 +566,9 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi } long energyFromBalance = max(account.getBalance() - callValue, 0, - VMConfig.allowStrictMath2()) / sunPerEnergy; + VMConfig.disableJavaLangMath()) / sunPerEnergy; long availableEnergy = addExact(leftFrozenEnergy, energyFromBalance, - VMConfig.allowStrictMath2()); + VMConfig.disableJavaLangMath()); long energyFromFeeLimit = feeLimit / sunPerEnergy; if (VMConfig.allowTvmFreezeV2()) { @@ -585,12 +585,12 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi account.setEnergyUsage( energyProcessor.increase(account, ENERGY, account.getEnergyUsage(), min(leftFrozenEnergy, energyFromFeeLimit, - VMConfig.allowStrictMath2()), now, now)); + VMConfig.disableJavaLangMath()), now, now)); receipt.setCallerEnergyMergedUsage(account.getEnergyUsage()); receipt.setCallerEnergyMergedWindowSize(account.getWindowSize(ENERGY)); rootRepository.updateAccount(account.createDbKey(), account); } - return min(availableEnergy, energyFromFeeLimit, VMConfig.allowStrictMath2()); + return min(availableEnergy, energyFromFeeLimit, VMConfig.disableJavaLangMath()); } @@ -603,7 +603,7 @@ private long getAccountEnergyLimitWithFloatRatio(AccountCapsule account, long fe } // can change the calc way long leftEnergyFromFreeze = rootRepository.getAccountLeftEnergyFromFreeze(account); - boolean isStrict2 = VMConfig.allowStrictMath2(); + boolean isStrict2 = VMConfig.disableJavaLangMath(); callValue = max(callValue, 0, isStrict2); long energyFromBalance = floorDiv(max( account.getBalance() - callValue, 0, isStrict2), sunPerEnergy, isStrict2); @@ -627,12 +627,12 @@ private long getAccountEnergyLimitWithFloatRatio(AccountCapsule account, long fe } else { energyFromFeeLimit = addExact( leftEnergyFromFreeze, (feeLimit - leftBalanceForEnergyFreeze) / sunPerEnergy, - VMConfig.allowStrictMath2()); + VMConfig.disableJavaLangMath()); } } return min(addExact(leftEnergyFromFreeze, energyFromBalance, - VMConfig.allowStrictMath2()), energyFromFeeLimit, VMConfig.allowStrictMath2()); + VMConfig.disableJavaLangMath()), energyFromFeeLimit, VMConfig.disableJavaLangMath()); } public long getTotalEnergyLimit(AccountCapsule creator, AccountCapsule caller, @@ -708,7 +708,7 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu ContractCapsule contractCapsule = rootRepository .getContract(contract.getContractAddress().toByteArray()); long consumeUserResourcePercent = contractCapsule.getConsumeUserResourcePercent( - VMConfig.allowStrictMath2()); + VMConfig.disableJavaLangMath()); long originEnergyLimit = contractCapsule.getOriginEnergyLimit(); if (originEnergyLimit < 0) { @@ -724,7 +724,7 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu } if (consumeUserResourcePercent <= 0) { creatorEnergyLimit = min(originEnergyLeft, originEnergyLimit, - VMConfig.allowStrictMath2()); + VMConfig.disableJavaLangMath()); } else { if (consumeUserResourcePercent < VMConstant.ONE_HUNDRED) { // creatorEnergyLimit = @@ -735,8 +735,8 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu BigInteger.valueOf(callerEnergyLimit) .multiply(BigInteger.valueOf(VMConstant.ONE_HUNDRED - consumeUserResourcePercent)) .divide(BigInteger.valueOf(consumeUserResourcePercent)).longValueExact(), - min(originEnergyLeft, originEnergyLimit, VMConfig.allowStrictMath2()), - VMConfig.allowStrictMath2()); + min(originEnergyLeft, originEnergyLimit, VMConfig.disableJavaLangMath()), + VMConfig.disableJavaLangMath()); } } if (VMConfig.allowTvmFreezeV2()) { @@ -758,7 +758,7 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu rootRepository.updateAccount(creator.createDbKey(), creator); } return addExact(callerEnergyLimit, creatorEnergyLimit, - VMConfig.allowStrictMath2()); + VMConfig.disableJavaLangMath()); } private long getTotalEnergyLimitWithFloatRatio(AccountCapsule creator, AccountCapsule caller, @@ -775,16 +775,16 @@ private long getTotalEnergyLimitWithFloatRatio(AccountCapsule creator, AccountCa ContractCapsule contractCapsule = rootRepository .getContract(contract.getContractAddress().toByteArray()); long consumeUserResourcePercent = contractCapsule.getConsumeUserResourcePercent( - VMConfig.allowStrictMath2()); + VMConfig.disableJavaLangMath()); if (creatorEnergyLimit * consumeUserResourcePercent > (VMConstant.ONE_HUNDRED - consumeUserResourcePercent) * callerEnergyLimit) { return floorDiv( callerEnergyLimit * VMConstant.ONE_HUNDRED, consumeUserResourcePercent, - VMConfig.allowStrictMath2()); + VMConfig.disableJavaLangMath()); } else { return addExact(callerEnergyLimit, creatorEnergyLimit, - VMConfig.allowStrictMath2()); + VMConfig.disableJavaLangMath()); } } diff --git a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java index a34afa9d32e..53d6caf5691 100644 --- a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java @@ -40,7 +40,6 @@ import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.Sha256Hash; import org.tron.core.ChainBaseManager; -import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.exception.PermissionException; @@ -53,7 +52,6 @@ import org.tron.protos.Protocol.Transaction.Result.contractResult; import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract; import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.contract.BalanceContract.DelegateResourceContract; @Slf4j(topic = "capsule") @@ -271,7 +269,7 @@ public static long estimateConsumeBandWidthSize(DynamicPropertiesStore dps, long DelegateResourceContract.Builder builder2 = DelegateResourceContract.newBuilder() .setBalance(TRX_PRECISION); long builder2Size = builder2.build().getSerializedSize(); - long addSize = max(builderSize - builder2Size, 0L, dps.allowStrictMath2()); + long addSize = max(builderSize - builder2Size, 0L, dps.disableJavaLangMath()); return DELEGATE_COST_BASE_SIZE + addSize; } diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 53e2cba90d4..b53a196e0b6 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -626,7 +626,7 @@ public long getEnergyForData(byte[] data) { int expLen = parseLen(data, 1); int modLen = parseLen(data, 2); - boolean allowStrictMath2 = VMConfig.allowStrictMath2(); + boolean allowStrictMath2 = VMConfig.disableJavaLangMath(); byte[] expHighBytes = parseBytes(data, addSafely(ARGS_OFFSET, baseLen), min(expLen, 32, allowStrictMath2)); diff --git a/actuator/src/main/java/org/tron/core/vm/VMUtils.java b/actuator/src/main/java/org/tron/core/vm/VMUtils.java index 090c4c54898..2f469e0579a 100644 --- a/actuator/src/main/java/org/tron/core/vm/VMUtils.java +++ b/actuator/src/main/java/org/tron/core/vm/VMUtils.java @@ -170,7 +170,7 @@ public static boolean validateForSmartContract(Repository deposit, byte[] ownerA "Validate InternalTransfer error, balance is not sufficient."); } - addExact(toAccount.getBalance(), amount, VMConfig.allowStrictMath2()); + addExact(toAccount.getBalance(), amount, VMConfig.disableJavaLangMath()); } catch (ArithmeticException e) { logger.debug(e.getMessage(), e); throw new ContractValidateException(e.getMessage()); @@ -232,7 +232,7 @@ public static boolean validateForSmartContract(Repository deposit, byte[] ownerA if (assetBalance != null) { try { addExact(assetBalance, amount, - VMConfig.allowStrictMath2()); //check if overflow + VMConfig.disableJavaLangMath()); //check if overflow } catch (Exception e) { logger.debug(e.getMessage(), e); throw new ContractValidateException(e.getMessage()); diff --git a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java index 508bedc34dc..81ed4ba2b8f 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java +++ b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java @@ -42,7 +42,7 @@ public static void load(StoreFactory storeFactory) { VMConfig.initAllowEnergyAdjustment(ds.getAllowEnergyAdjustment()); VMConfig.initAllowStrictMath(ds.getAllowStrictMath()); VMConfig.initAllowTvmCancun(ds.getAllowTvmCancun()); - VMConfig.initAllowStrictMath2(ds.getConsensusLogicOptimization()); + VMConfig.initDisableJavaLangMath(ds.getConsensusLogicOptimization()); } } } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index 164f9711a20..b711eb427d1 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -10,7 +10,6 @@ import com.google.protobuf.ByteString; import java.util.Arrays; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.ArrayUtils; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.ChainBaseManager; @@ -54,7 +53,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra throw new ContractValidateException("delegateBalance must be greater than or equal to 1 TRX"); } - boolean allowStrictMath2 = dynamicStore.allowStrictMath2(); + boolean allowStrictMath2 = dynamicStore.disableJavaLangMath(); switch (param.getResourceType()) { case BANDWIDTH: { BandwidthProcessor processor = new BandwidthProcessor(ChainBaseManager.getInstance()); diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index fc95f23cc03..99bcecdbd44 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -117,7 +117,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { * dynamicStore.getTotalNetLimit() / repo.getTotalNetWeight()); transferUsage = (long) (receiverCapsule.getNetUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForBandwidth())); - transferUsage = min(unDelegateMaxUsage, transferUsage, VMConfig.allowStrictMath2()); + transferUsage = min(unDelegateMaxUsage, transferUsage, VMConfig.disableJavaLangMath()); receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForBandwidth(-unDelegateBalance); } @@ -141,7 +141,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { * dynamicStore.getTotalEnergyCurrentLimit() / repo.getTotalEnergyWeight()); transferUsage = (long) (receiverCapsule.getEnergyUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForEnergy())); - transferUsage = min(unDelegateMaxUsage, transferUsage, VMConfig.allowStrictMath2()); + transferUsage = min(unDelegateMaxUsage, transferUsage, VMConfig.disableJavaLangMath()); receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForEnergy(-unDelegateBalance); } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceProcessor.java index 2167635a28f..53981a22d34 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceProcessor.java @@ -137,11 +137,11 @@ public long execute(UnfreezeBalanceParam param, Repository repo) { switch (param.getResourceType()) { case BANDWIDTH: receiverCapsule.safeAddAcquiredDelegatedFrozenBalanceForBandwidth(-unfreezeBalance, - VMConfig.allowStrictMath2()); + VMConfig.disableJavaLangMath()); break; case ENERGY: receiverCapsule.safeAddAcquiredDelegatedFrozenBalanceForEnergy(-unfreezeBalance, - VMConfig.allowStrictMath2()); + VMConfig.disableJavaLangMath()); break; default: //this should never happen diff --git a/actuator/src/main/java/org/tron/core/vm/program/Memory.java b/actuator/src/main/java/org/tron/core/vm/program/Memory.java index 70e4005a54a..4811bfb6e12 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Memory.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Memory.java @@ -105,7 +105,7 @@ public void extend(int address, int size) { if (size <= 0) { return; } - boolean allowStrictMath2 = VMConfig.allowStrictMath2(); + boolean allowStrictMath2 = VMConfig.disableJavaLangMath(); final int newSize = addExact(address, size, allowStrictMath2); int toAllocate = newSize - internalSize(); if (toAllocate > 0) { @@ -194,7 +194,7 @@ public void copy(int destPos, int srcPos, int size) { private int captureMax(int chunkIndex, int chunkOffset, int size, byte[] src, int srcPos) { byte[] chunk = chunks.get(chunkIndex); - int toCapture = min(size, chunk.length - chunkOffset, VMConfig.allowStrictMath2()); + int toCapture = min(size, chunk.length - chunkOffset, VMConfig.disableJavaLangMath()); System.arraycopy(src, srcPos, chunk, chunkOffset, toCapture); return toCapture; @@ -203,7 +203,7 @@ private int captureMax(int chunkIndex, int chunkOffset, int size, byte[] src, in private int grabMax(int chunkIndex, int chunkOffset, int size, byte[] dest, int destPos) { byte[] chunk = chunks.get(chunkIndex); - int toGrab = min(size, chunk.length - chunkOffset, VMConfig.allowStrictMath2()); + int toGrab = min(size, chunk.length - chunkOffset, VMConfig.disableJavaLangMath()); System.arraycopy(chunk, chunkOffset, dest, destPos, toGrab); diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 77326e0d81f..024acb670a0 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -168,7 +168,7 @@ static String formatBinData(byte[] binData, int startPC) { for (int i = 0; i < binData.length; i += 16) { ret.append(Utils.align("" + Integer.toHexString(startPC + (i)) + ":", ' ', 8, false)); ret.append(Hex.toHexString(binData, i, min(16, binData.length - i, - VMConfig.allowStrictMath2()))).append('\n'); + VMConfig.disableJavaLangMath()))).append('\n'); } return ret.toString(); } @@ -638,7 +638,7 @@ private void withdrawRewardAndCancelVote(byte[] owner, Repository repo) { long balance = ownerCapsule.getBalance(); long allowance = ownerCapsule.getAllowance(); ownerCapsule.setInstance(ownerCapsule.getInstance().toBuilder() - .setBalance(addExact(balance, allowance, VMConfig.allowStrictMath2())) + .setBalance(addExact(balance, allowance, VMConfig.disableJavaLangMath())) .setAllowance(0) .setLatestWithdrawTime(getTimestamp().longValue() * 1000) .build()); @@ -1237,7 +1237,7 @@ public DataWord getContractAddress() { public DataWord getBlockHash(int index) { if (index < this.getNumber().longValue() && index >= max(256, this.getNumber().longValue(), - VMConfig.allowStrictMath2()) - 256) { + VMConfig.disableJavaLangMath()) - 256) { BlockCapsule blockCapsule = contractState.getBlockByNum(index); @@ -2170,7 +2170,7 @@ public boolean voteWitness(int witnessArrayOffset, int witnessArrayLength, try { VoteWitnessParam param = new VoteWitnessParam(); param.setVoterAddress(owner); - boolean allowStrictMath2 = VMConfig.allowStrictMath2(); + boolean allowStrictMath2 = VMConfig.disableJavaLangMath(); byte[] witnessArrayData = memoryChunk( addExact(witnessArrayOffset, DataWord.WORD_SIZE, allowStrictMath2), multiplyExact(witnessArrayLength, DataWord.WORD_SIZE, allowStrictMath2)); @@ -2253,7 +2253,7 @@ public long updateContextContractFactor() { VMConfig.getDynamicEnergyIncreaseFactor(), VMConfig.getDynamicEnergyMaxFactor(), VMConfig.allowStrictMath(), - VMConfig.allowStrictMath2())) { + VMConfig.disableJavaLangMath())) { contractState.updateContractState(getContextAddress(), contractStateCapsule ); } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index e81aba2a862..a064cbf6c8a 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -189,7 +189,7 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { long newEnergyUsage = recover(energyUsage, latestConsumeTime, now, windowSize); - return max(energyLimit - newEnergyUsage, 0, VMConfig.allowStrictMath2()); // us + return max(energyLimit - newEnergyUsage, 0, VMConfig.disableJavaLangMath()); // us } @Override @@ -711,7 +711,7 @@ public long addBalance(byte[] address, long value) { StringUtil.createReadableString(accountCapsule.createDbKey()) + " insufficient balance"); } - accountCapsule.setBalance(addExact(balance, value, VMConfig.allowStrictMath2())); + accountCapsule.setBalance(addExact(balance, value, VMConfig.disableJavaLangMath())); Key key = Key.create(address); accountCache.put(key, Value.create(accountCapsule, accountCache.get(key).getType().addType(Type.DIRTY))); @@ -877,7 +877,7 @@ private long increase(long lastUsage, long usage, long lastTime, long now, long if (lastTime + windowSize > now) { long delta = now - lastTime; double decay = (windowSize - delta) / (double) windowSize; - averageLastUsage = round(averageLastUsage * decay, VMConfig.allowStrictMath2()); + averageLastUsage = round(averageLastUsage * decay, VMConfig.disableJavaLangMath()); } else { averageLastUsage = 0; } diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index 753313afe43..28c190e2e7e 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -136,7 +136,7 @@ public static long queryAvailableUnfreezeV2Size(byte[] address, Repository repos long now = repository.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); int unfreezingV2Count = accountCapsule.getUnfreezingV2Count(now); return max(UnfreezeBalanceV2Actuator.getUNFREEZE_MAX_TIMES() - unfreezingV2Count, 0L, - VMConfig.allowStrictMath2()); + VMConfig.disableJavaLangMath()); } public static long queryDelegatableResource(byte[] address, long type, Repository repository) { @@ -144,7 +144,7 @@ public static long queryDelegatableResource(byte[] address, long type, Repositor return 0L; } - boolean allowStrictMath2 = VMConfig.allowStrictMath2(); + boolean allowStrictMath2 = VMConfig.disableJavaLangMath(); AccountCapsule accountCapsule = repository.getAccount(address); if (accountCapsule == null) { return 0L; @@ -223,7 +223,7 @@ public static Triple checkUndelegateResource(byte[] address, l return Triple.of(0L, 0L, 0L); } - amount = min(amount, resourceLimit, VMConfig.allowStrictMath2()); + amount = min(amount, resourceLimit, VMConfig.disableJavaLangMath()); if (resourceLimit <= usagePair.getLeft()) { return Triple.of(0L, amount, usagePair.getRight()); } diff --git a/chainbase/src/main/java/org/tron/common/utils/Commons.java b/chainbase/src/main/java/org/tron/common/utils/Commons.java index 6bcff7ec6e9..b121e84ecfe 100644 --- a/chainbase/src/main/java/org/tron/common/utils/Commons.java +++ b/chainbase/src/main/java/org/tron/common/utils/Commons.java @@ -144,7 +144,7 @@ public static void adjustTotalShieldedPoolValue(long valueBalance, DynamicPropertiesStore dynamicPropertiesStore) throws BalanceInsufficientException { long totalShieldedPoolValue = subtractExact( dynamicPropertiesStore.getTotalShieldedPoolValue(), valueBalance, - dynamicPropertiesStore.allowStrictMath2()); + dynamicPropertiesStore.disableJavaLangMath()); if (totalShieldedPoolValue < 0) { throw new BalanceInsufficientException(String.format( "total shielded pool value can not below 0, actual: %d", totalShieldedPoolValue)); diff --git a/chainbase/src/main/java/org/tron/common/utils/ForkController.java b/chainbase/src/main/java/org/tron/common/utils/ForkController.java index 0a782b31e5b..a702234f4cd 100644 --- a/chainbase/src/main/java/org/tron/common/utils/ForkController.java +++ b/chainbase/src/main/java/org/tron/common/utils/ForkController.java @@ -100,7 +100,7 @@ private boolean passNew(int version) { } } return count >= ceil((double) versionEnum.getHardForkRate() * stats.length / 100, - manager.getDynamicPropertiesStore().allowStrictMath2()); + manager.getDynamicPropertiesStore().disableJavaLangMath()); } diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index 26ee5bab34b..2768c06a393 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -733,7 +733,7 @@ public boolean addAssetAmount(byte[] key, long amount, boolean useStrict) { public boolean addAssetAmountV2(byte[] key, long amount, DynamicPropertiesStore dynamicPropertiesStore, AssetIssueStore assetIssueStore) { importAsset(key); - boolean useStrict2 = dynamicPropertiesStore.allowStrictMath2(); + boolean useStrict2 = dynamicPropertiesStore.disableJavaLangMath(); //key is token name if (dynamicPropertiesStore.getAllowSameTokenName() == 0) { Map assetMap = this.account.getAssetMap(); @@ -781,7 +781,7 @@ public boolean reduceAssetAmountV2(byte[] key, long amount, DynamicPropertiesStore dynamicPropertiesStore, AssetIssueStore assetIssueStore) { importAsset(key); //key is token name - boolean useStrict2 = dynamicPropertiesStore.allowStrictMath2(); + boolean useStrict2 = dynamicPropertiesStore.disableJavaLangMath(); if (dynamicPropertiesStore.getAllowSameTokenName() == 0) { Map assetMap = this.account.getAssetMap(); AssetIssueCapsule assetIssueCapsule = assetIssueStore.get(key); diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java index be73a338b90..f566a128d6b 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java @@ -109,9 +109,9 @@ public byte[] getOriginAddress() { return this.smartContract.getOriginAddress().toByteArray(); } - public long getConsumeUserResourcePercent(boolean useStrictMath2) { + public long getConsumeUserResourcePercent(boolean disableMath) { long percent = this.smartContract.getConsumeUserResourcePercent(); - return max(0, min(percent, Constant.ONE_HUNDRED, useStrictMath2), useStrictMath2); + return max(0, min(percent, Constant.ONE_HUNDRED, disableMath), disableMath); } public long getOriginEnergyLimit() { diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java index 8deeebaa758..bd932ea50ae 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java @@ -82,13 +82,13 @@ public boolean catchUpToCycle(DynamicPropertiesStore dps) { dps.getDynamicEnergyIncreaseFactor(), dps.getDynamicEnergyMaxFactor(), dps.allowStrictMath(), - dps.allowStrictMath2() + dps.disableJavaLangMath() ); } public boolean catchUpToCycle( long newCycle, long threshold, long increaseFactor, long maxFactor, - boolean useStrictMath, boolean useStrictMath2 + boolean useStrictMath, boolean disableMath ) { long lastCycle = getUpdateCycle(); @@ -115,7 +115,7 @@ public boolean catchUpToCycle( .setEnergyFactor(min( maxFactor, (long) ((getEnergyFactor() + precisionFactor) * increasePercent) - precisionFactor, - useStrictMath2)) + disableMath)) .build(); } @@ -140,7 +140,7 @@ public boolean catchUpToCycle( .setEnergyFactor(max( 0, (long) ((getEnergyFactor() + precisionFactor) * decreasePercent) - precisionFactor, - useStrictMath2)) + disableMath)) .build(); return true; diff --git a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index 29d80cebe3f..73c852805a2 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -218,7 +218,7 @@ public void payEnergyBill(DynamicPropertiesStore dynamicPropertiesStore, receipt.getEnergyUsageTotal(), receipt.getResult(), energyProcessor, now); return; } - boolean useStrict2 = dynamicPropertiesStore.allowStrictMath2(); + boolean useStrict2 = dynamicPropertiesStore.disableJavaLangMath(); if ((!Objects.isNull(origin)) && caller.getAddress().equals(origin.getAddress())) { payEnergyBill(dynamicPropertiesStore, accountStore, forkController, caller, @@ -240,7 +240,7 @@ public void payEnergyBill(DynamicPropertiesStore dynamicPropertiesStore, private long getOriginUsage(DynamicPropertiesStore dynamicPropertiesStore, AccountCapsule origin, long originEnergyLimit, EnergyProcessor energyProcessor, long originUsage) { - boolean useStrict2 = dynamicPropertiesStore.allowStrictMath2(); + boolean useStrict2 = dynamicPropertiesStore.disableJavaLangMath(); if (dynamicPropertiesStore.getAllowTvmFreeze() == 1 || dynamicPropertiesStore.supportUnfreezeDelay()) { return min(originUsage, min(originEnergyLeft, originEnergyLimit, useStrict2), useStrict2); @@ -306,7 +306,7 @@ private void payEnergyBill( } else { //send to blackHole Commons.adjustBalance(accountStore, accountStore.getBlackhole(), - energyFee, dynamicPropertiesStore.allowStrictMath2()); + energyFee, dynamicPropertiesStore.disableJavaLangMath()); } } diff --git a/chainbase/src/main/java/org/tron/core/capsule/utils/MarketUtils.java b/chainbase/src/main/java/org/tron/core/capsule/utils/MarketUtils.java index fb86cb1f456..d711ac0d63b 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/utils/MarketUtils.java +++ b/chainbase/src/main/java/org/tron/core/capsule/utils/MarketUtils.java @@ -282,10 +282,10 @@ public static void updateOrderState(MarketOrderCapsule orderCapsule, } } - public static long multiplyAndDivide(long a, long b, long c, boolean useStrictMath2) { + public static long multiplyAndDivide(long a, long b, long c, boolean disableMath) { try { - long tmp = multiplyExact(a, b, useStrictMath2); - return floorDiv(tmp, c, useStrictMath2); + long tmp = multiplyExact(a, b, disableMath); + return floorDiv(tmp, c, disableMath); } catch (ArithmeticException ex) { // do nothing here, because we will use BigInteger to compute again } @@ -307,7 +307,7 @@ public static void returnSellTokenRemain(MarketOrderCapsule orderCapsule, if (Arrays.equals(sellTokenId, "_".getBytes())) { accountCapsule.setBalance(addExact( accountCapsule.getBalance(), sellTokenQuantityRemain, - dynamicStore.allowStrictMath2())); + dynamicStore.disableJavaLangMath())); } else { accountCapsule .addAssetAmountV2(sellTokenId, sellTokenQuantityRemain, dynamicStore, assetIssueStore); diff --git a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java index ef326977451..b7c6354af37 100644 --- a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java @@ -79,7 +79,7 @@ public void updateAdaptiveTotalEnergyLimit() { / AdaptiveResourceLimitConstants.EXPAND_RATE_DENOMINATOR; // logger.info(totalEnergyAverageUsage + "<" + targetTotalEnergyLimit + "\n" + result); } - boolean useStrict2 = dynamicPropertiesStore.allowStrictMath2(); + boolean useStrict2 = dynamicPropertiesStore.disableJavaLangMath(); result = min(max(result, totalEnergyLimit, useStrict2), totalEnergyLimit * dynamicPropertiesStore.getAdaptiveResourceLimitMultiplier(), useStrict2); @@ -178,7 +178,7 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { long newEnergyUsage = recovery(accountCapsule, ENERGY, energyUsage, latestConsumeTime, now); - return max(energyLimit - newEnergyUsage, 0, dynamicPropertiesStore.allowStrictMath2()); // us + return max(energyLimit - newEnergyUsage, 0, dynamicPropertiesStore.disableJavaLangMath()); // us } private long getHeadSlot() { diff --git a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java index 9b446079337..1d6cd1c7415 100644 --- a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java @@ -54,7 +54,7 @@ protected long increase(long lastUsage, long usage, long lastTime, long now, lon long delta = now - lastTime; double decay = (windowSize - delta) / (double) windowSize; averageLastUsage = round(averageLastUsage * decay, - dynamicPropertiesStore.allowStrictMath2()); + dynamicPropertiesStore.disableJavaLangMath()); } else { averageLastUsage = 0; } @@ -83,7 +83,7 @@ public long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, long delta = now - lastTime; double decay = (oldWindowSize - delta) / (double) oldWindowSize; averageLastUsage = round(averageLastUsage * decay, - dynamicPropertiesStore.allowStrictMath2()); + dynamicPropertiesStore.disableJavaLangMath()); } else { averageLastUsage = 0; } @@ -116,7 +116,7 @@ public long increaseV2(AccountCapsule accountCapsule, ResourceCode resourceCode, long delta = now - lastTime; double decay = (oldWindowSize - delta) / (double) oldWindowSize; averageLastUsage = round(averageLastUsage * decay, - dynamicPropertiesStore.allowStrictMath2()); + dynamicPropertiesStore.disableJavaLangMath()); } else { averageLastUsage = 0; } @@ -133,7 +133,7 @@ public long increaseV2(AccountCapsule accountCapsule, ResourceCode resourceCode, long newWindowSize = divideCeil( remainUsage * remainWindowSize + usage * this.windowSize * WINDOW_SIZE_PRECISION, newUsage); newWindowSize = min(newWindowSize, this.windowSize * WINDOW_SIZE_PRECISION, - dynamicPropertiesStore.allowStrictMath2()); + dynamicPropertiesStore.disableJavaLangMath()); accountCapsule.setNewWindowSizeV2(resourceCode, newWindowSize); return newUsage; } @@ -196,7 +196,7 @@ public void unDelegateIncreaseV2(AccountCapsule owner, final AccountCapsule rece ownerUsage * remainOwnerWindowSizeV2 + transferUsage * remainReceiverWindowSizeV2, newOwnerUsage); newOwnerWindowSize = min(newOwnerWindowSize, this.windowSize * WINDOW_SIZE_PRECISION, - dynamicPropertiesStore.allowStrictMath2()); + dynamicPropertiesStore.disableJavaLangMath()); owner.setNewWindowSizeV2(resourceCode, newOwnerWindowSize); owner.setUsage(resourceCode, newOwnerUsage); owner.setLatestTime(resourceCode, now); @@ -224,14 +224,14 @@ protected boolean consumeFeeForBandwidth(AccountCapsule accountCapsule, long fee long latestOperationTime = dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); accountCapsule.setLatestOperationTime(latestOperationTime); Commons.adjustBalance(accountStore, accountCapsule, -fee, - dynamicPropertiesStore.allowStrictMath2()); + dynamicPropertiesStore.disableJavaLangMath()); if (dynamicPropertiesStore.supportTransactionFeePool()) { dynamicPropertiesStore.addTransactionFeePool(fee); } else if (dynamicPropertiesStore.supportBlackHoleOptimization()) { dynamicPropertiesStore.burnTrx(fee); } else { Commons.adjustBalance(accountStore, accountStore.getBlackhole().createDbKey(), +fee, - dynamicPropertiesStore.allowStrictMath2()); + dynamicPropertiesStore.disableJavaLangMath()); } return true; @@ -245,12 +245,12 @@ protected boolean consumeFeeForNewAccount(AccountCapsule accountCapsule, long fe long latestOperationTime = dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); accountCapsule.setLatestOperationTime(latestOperationTime); Commons.adjustBalance(accountStore, accountCapsule, -fee, - dynamicPropertiesStore.allowStrictMath2()); + dynamicPropertiesStore.disableJavaLangMath()); if (dynamicPropertiesStore.supportBlackHoleOptimization()) { dynamicPropertiesStore.burnTrx(fee); } else { Commons.adjustBalance(accountStore, accountStore.getBlackhole().createDbKey(), +fee, - dynamicPropertiesStore.allowStrictMath2()); + dynamicPropertiesStore.disableJavaLangMath()); } return true; diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java index 114197a3407..a65c814246d 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java @@ -4,7 +4,6 @@ import static org.tron.common.math.Maths.min; import static org.tron.common.runtime.InternalTransaction.TrxType.TRX_CONTRACT_CALL_TYPE; import static org.tron.common.runtime.InternalTransaction.TrxType.TRX_CONTRACT_CREATION_TYPE; -import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_PRECISION; import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import java.util.Objects; @@ -41,7 +40,6 @@ import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result.contractResult; -import org.tron.protos.contract.Common; import org.tron.protos.contract.SmartContractOuterClass.SmartContract.ABI; import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; @@ -246,11 +244,11 @@ public void pay() throws BalanceInsufficientException { callerAccount = callContract.getOwnerAddress().toByteArray(); originAccount = contractCapsule.getOriginAddress(); - boolean useStrictMath2 = dynamicPropertiesStore.allowStrictMath2(); + boolean disableMath = dynamicPropertiesStore.disableJavaLangMath(); percent = max(Constant.ONE_HUNDRED - contractCapsule.getConsumeUserResourcePercent( - useStrictMath2), 0, useStrictMath2); + disableMath), 0, disableMath); percent = min(percent, Constant.ONE_HUNDRED, - useStrictMath2); + disableMath); originEnergyLimit = contractCapsule.getOriginEnergyLimit(); break; default: @@ -303,7 +301,7 @@ private void resetAccountUsage(AccountCapsule accountCap, // If area merging happened during suicide, use the current window size long newSize = mergedSize == currentSize ? size : currentSize; // Calc new usage by fixed x-axes - long newUsage = max(0, newArea / newSize, dynamicPropertiesStore.allowStrictMath2()); + long newUsage = max(0, newArea / newSize, dynamicPropertiesStore.disableJavaLangMath()); // Reset account usage and window size accountCap.setEnergyUsage(newUsage); accountCap.setNewWindowSize(ENERGY, newUsage == 0 ? 0L : newSize); @@ -320,7 +318,7 @@ private void resetAccountUsageV2(AccountCapsule accountCap, long newSize = mergedSize == currentSize ? size : currentSize; long newSize2 = mergedSize == currentSize ? size2 : currentSize2; // Calc new usage by fixed x-axes - long newUsage = max(0, newArea / newSize, dynamicPropertiesStore.allowStrictMath2()); + long newUsage = max(0, newArea / newSize, dynamicPropertiesStore.disableJavaLangMath()); // Reset account usage and window size accountCap.setEnergyUsage(newUsage); accountCap.setNewWindowSizeV2(ENERGY, newUsage == 0 ? 0L : newSize2); diff --git a/chainbase/src/main/java/org/tron/core/service/MortgageService.java b/chainbase/src/main/java/org/tron/core/service/MortgageService.java index 233c142f053..b1fd279c2db 100644 --- a/chainbase/src/main/java/org/tron/core/service/MortgageService.java +++ b/chainbase/src/main/java/org/tron/core/service/MortgageService.java @@ -208,7 +208,7 @@ private long computeReward(long beginCycle, long endCycle, AccountCapsule accoun .collect(Collectors.toList()); if (beginCycle < newAlgorithmCycle) { long oldEndCycle = min(endCycle, newAlgorithmCycle, - dynamicPropertiesStore.allowStrictMath2()); + dynamicPropertiesStore.disableJavaLangMath()); reward = getOldReward(beginCycle, oldEndCycle, srAddresses); beginCycle = oldEndCycle; } diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 8d1fb19ea2b..865555b35a8 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -2246,7 +2246,7 @@ public void addTotalNetWeight(long amount) { long totalNetWeight = getTotalNetWeight(); totalNetWeight += amount; if (allowNewReward()) { - totalNetWeight = max(0, totalNetWeight, allowStrictMath2()); + totalNetWeight = max(0, totalNetWeight, disableJavaLangMath()); } saveTotalNetWeight(totalNetWeight); } @@ -2259,7 +2259,7 @@ public void addTotalEnergyWeight(long amount) { long totalEnergyWeight = getTotalEnergyWeight(); totalEnergyWeight += amount; if (allowNewReward()) { - totalEnergyWeight = max(0, totalEnergyWeight, allowStrictMath2()); + totalEnergyWeight = max(0, totalEnergyWeight, disableJavaLangMath()); } saveTotalEnergyWeight(totalEnergyWeight); } @@ -2272,7 +2272,7 @@ public void addTotalTronPowerWeight(long amount) { long totalWeight = getTotalTronPowerWeight(); totalWeight += amount; if (allowNewReward()) { - totalWeight = max(0, totalWeight, allowStrictMath2()); + totalWeight = max(0, totalWeight, disableJavaLangMath()); } saveTotalTronPowerWeight(totalWeight); } @@ -2897,7 +2897,7 @@ public boolean allowStrictMath() { return getAllowStrictMath() == 1L; } - public boolean allowStrictMath2() { + public boolean disableJavaLangMath() { return this.allowConsensusLogicOptimization(); } diff --git a/common/src/main/java/org/tron/common/runtime/vm/DataWord.java b/common/src/main/java/org/tron/common/runtime/vm/DataWord.java index 1601dcaad28..faeae45782e 100644 --- a/common/src/main/java/org/tron/common/runtime/vm/DataWord.java +++ b/common/src/main/java/org/tron/common/runtime/vm/DataWord.java @@ -169,7 +169,7 @@ public byte[] getClonedData() { byte[] ret = ByteUtil.EMPTY_BYTE_ARRAY; if (data != null) { ret = new byte[WORD_SIZE]; - int dataSize = min(data.length, WORD_SIZE, VMConfig.allowStrictMath2()); + int dataSize = min(data.length, WORD_SIZE, VMConfig.disableJavaLangMath()); System.arraycopy(data, 0, ret, 0, dataSize); } return ret; @@ -488,7 +488,7 @@ public int compareTo(DataWord o) { data, 0, data.length, o.getData(), 0, o.getData().length); // Convert result into -1, 0 or 1 as is the convention - return (int) signum(result, VMConfig.allowStrictMath2()); + return (int) signum(result, VMConfig.disableJavaLangMath()); } public void signExtend(byte k) { diff --git a/common/src/main/java/org/tron/core/vm/config/VMConfig.java b/common/src/main/java/org/tron/core/vm/config/VMConfig.java index fa99daf20f4..23210f284c0 100644 --- a/common/src/main/java/org/tron/core/vm/config/VMConfig.java +++ b/common/src/main/java/org/tron/core/vm/config/VMConfig.java @@ -55,7 +55,7 @@ public class VMConfig { private static boolean ALLOW_TVM_CANCUN = false; - private static Boolean ALLOW_STRICT_MATH_2 = false; + private static Boolean DISABLE_JAVA_LANG_MATH = false; private VMConfig() { } @@ -156,8 +156,8 @@ public static void initAllowTvmCancun(long allow) { ALLOW_TVM_CANCUN = allow == 1; } - public static void initAllowStrictMath2(long allow) { - ALLOW_STRICT_MATH_2 = allow == 1; + public static void initDisableJavaLangMath(long allow) { + DISABLE_JAVA_LANG_MATH = allow == 1; } public static boolean getEnergyLimitHardFork() { @@ -248,7 +248,7 @@ public static boolean allowTvmCancun() { return ALLOW_TVM_CANCUN; } - public static boolean allowStrictMath2() { - return ALLOW_STRICT_MATH_2; + public static boolean disableJavaLangMath() { + return DISABLE_JAVA_LANG_MATH; } } diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index b7a1bdd9501..27c942bf6b4 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -903,10 +903,10 @@ public long calcCanDelegatedBandWidthMaxSize( long netUsage = (long) (accountNetUsage * TRX_PRECISION * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); - long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage, dynamicStore.allowStrictMath2()); + long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage, dynamicStore.disableJavaLangMath()); long maxSize = ownerCapsule.getFrozenV2BalanceForBandwidth() - v2NetUsage; - return max(0, maxSize, dynamicStore.allowStrictMath2()); + return max(0, maxSize, dynamicStore.disableJavaLangMath()); } public long calcCanDelegatedEnergyMaxSize(ByteString ownerAddress) { @@ -924,10 +924,10 @@ public long calcCanDelegatedEnergyMaxSize(ByteString ownerAddress) { (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage, - dynamicStore.allowStrictMath2()); + dynamicStore.disableJavaLangMath()); long maxSize = ownerCapsule.getFrozenV2BalanceForEnergy() - v2EnergyUsage; - return max(0, maxSize, dynamicStore.allowStrictMath2()); + return max(0, maxSize, dynamicStore.disableJavaLangMath()); } public DelegatedResourceAccountIndex getDelegatedResourceAccountIndex(ByteString address) { @@ -3010,7 +3010,7 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, txRetBuilder.setResult(true); txRetBuilder.setCode(response_code.SUCCESS); estimateBuilder.setEnergyRequired((long) ceil((double) high / dps.getEnergyFee(), - dps.allowStrictMath2())); + dps.disableJavaLangMath())); } return transaction; @@ -3572,7 +3572,7 @@ public ShieldedTRC20Parameters createShieldedContractParameters( try { totalToAmount = receiveSize == 0 ? scaledToAmount : (addExact( scaledToAmount, shieldedReceives.get(0).getNote().getValue(), - dbManager.getDynamicPropertiesStore().allowStrictMath2())); + dbManager.getDynamicPropertiesStore().disableJavaLangMath())); } catch (ArithmeticException e) { throw new ZksnarkException("Unbalanced burn!"); } @@ -3705,7 +3705,7 @@ public ShieldedTRC20Parameters createShieldedContractParametersWithoutAsk( try { totalToAmount = receiveSize == 0 ? scaledToAmount : addExact( scaledToAmount, shieldedReceives.get(0).getNote().getValue(), - chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + chainBaseManager.getDynamicPropertiesStore().disableJavaLangMath()); } catch (ArithmeticException e) { throw new ZksnarkException("Unbalanced burn!"); } diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 096476a1bbe..cb7164a3bac 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -930,20 +930,20 @@ public void consumeMultiSignFee(TransactionCapsule trx, TransactionTrace trace) throws AccountResourceInsufficientException { if (trx.getInstance().getSignatureCount() > 1) { long fee = getDynamicPropertiesStore().getMultiSignFee(); - boolean useStrictMath2 = getDynamicPropertiesStore().allowStrictMath2(); + boolean disableMath = getDynamicPropertiesStore().disableJavaLangMath(); List contracts = trx.getInstance().getRawData().getContractList(); for (Contract contract : contracts) { byte[] address = TransactionCapsule.getOwner(contract); AccountCapsule accountCapsule = getAccountStore().get(address); try { if (accountCapsule != null) { - adjustBalance(getAccountStore(), accountCapsule, -fee, useStrictMath2); + adjustBalance(getAccountStore(), accountCapsule, -fee, disableMath); if (getDynamicPropertiesStore().supportBlackHoleOptimization()) { getDynamicPropertiesStore().burnTrx(fee); } else { adjustBalance(getAccountStore(), this.getAccountStore().getBlackhole(), +fee, - useStrictMath2); + disableMath); } } } catch (BalanceInsufficientException e) { @@ -968,20 +968,20 @@ public void consumeMemoFee(TransactionCapsule trx, TransactionTrace trace) if (fee == 0) { return; } - boolean useStrictMath2 = getDynamicPropertiesStore().allowStrictMath2(); + boolean disableMath = getDynamicPropertiesStore().disableJavaLangMath(); List contracts = trx.getInstance().getRawData().getContractList(); for (Contract contract : contracts) { byte[] address = TransactionCapsule.getOwner(contract); AccountCapsule accountCapsule = getAccountStore().get(address); try { if (accountCapsule != null) { - adjustBalance(getAccountStore(), accountCapsule, -fee, useStrictMath2); + adjustBalance(getAccountStore(), accountCapsule, -fee, disableMath); if (getDynamicPropertiesStore().supportBlackHoleOptimization()) { getDynamicPropertiesStore().burnTrx(fee); } else { adjustBalance(getAccountStore(), this.getAccountStore().getBlackhole(), +fee, - useStrictMath2); + disableMath); } } } catch (BalanceInsufficientException e) { @@ -1871,7 +1871,7 @@ private void payReward(BlockCapsule block) { long transactionFeeReward = floorDiv( chainBaseManager.getDynamicPropertiesStore().getTransactionFeePool(), Constant.TRANSACTION_FEE_POOL_PERIOD, - chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + chainBaseManager.getDynamicPropertiesStore().disableJavaLangMath()); mortgageService.payTransactionFeeReward(witnessCapsule.getAddress().toByteArray(), transactionFeeReward); chainBaseManager.getDynamicPropertiesStore().saveTransactionFeePool( @@ -1888,7 +1888,7 @@ private void payReward(BlockCapsule block) { long transactionFeeReward = floorDiv( chainBaseManager.getDynamicPropertiesStore().getTransactionFeePool(), Constant.TRANSACTION_FEE_POOL_PERIOD, - chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + chainBaseManager.getDynamicPropertiesStore().disableJavaLangMath()); account.setAllowance(account.getAllowance() + transactionFeeReward); chainBaseManager.getDynamicPropertiesStore().saveTransactionFeePool( chainBaseManager.getDynamicPropertiesStore().getTransactionFeePool() @@ -2458,9 +2458,9 @@ private void initLiteNode() { transactionCount += trx.getTransactionIds().size(); long blockNum = trx.getNum(); maxBlock = max(maxBlock, blockNum, - chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + chainBaseManager.getDynamicPropertiesStore().disableJavaLangMath()); minBlock = min(minBlock, blockNum, - chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + chainBaseManager.getDynamicPropertiesStore().disableJavaLangMath()); item.setBlockNum(blockNum); trx.getTransactionIds().forEach( tid -> chainBaseManager.getTransactionStore().put(Hex.decode(tid), item)); diff --git a/framework/src/test/java/org/tron/common/BaseTest.java b/framework/src/test/java/org/tron/common/BaseTest.java index 9eddef83fba..552808b842c 100644 --- a/framework/src/test/java/org/tron/common/BaseTest.java +++ b/framework/src/test/java/org/tron/common/BaseTest.java @@ -109,6 +109,6 @@ public Protocol.Block getSignedBlock(ByteString witness, long time, byte[] priva public void adjustBalance(AccountStore accountStore, byte[] accountAddress, long amount) throws BalanceInsufficientException { Commons.adjustBalance(accountStore, accountAddress, amount, - chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + chainBaseManager.getDynamicPropertiesStore().disableJavaLangMath()); } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java index 9e58233c922..698ba5f2923 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java @@ -251,7 +251,7 @@ public void testMaxContractResultSize() { } Result result = Result.newBuilder().setContractRet(cr).build(); maxSize = max(maxSize, result.getSerializedSize(), - dbManager.getDynamicPropertiesStore().allowStrictMath2()); + dbManager.getDynamicPropertiesStore().disableJavaLangMath()); } Assert.assertEquals(2, maxSize); } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java index 276a4a547f4..907398f163b 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -860,7 +860,7 @@ private TVMTestResult unDelegateResource( * ((double) (amount) / oldReceiver.getAllFrozenBalanceForEnergy())); } transferUsage = min(unDelegateMaxUsage, transferUsage, - manager.getDynamicPropertiesStore().allowStrictMath2()); + manager.getDynamicPropertiesStore().disableJavaLangMath()); } DelegatedResourceStore delegatedResourceStore = manager.getDelegatedResourceStore(); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java b/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java index fc3b16f8f2e..d6493ed8018 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java @@ -5,7 +5,6 @@ import static org.tron.protos.Protocol.Transaction.Result.contractResult.REVERT; import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS; -import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -30,7 +29,6 @@ import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.Commons; -import org.tron.common.utils.FileUtil; import org.tron.common.utils.StringUtil; import org.tron.common.utils.WalletUtil; import org.tron.common.utils.client.utils.AbiUtil; @@ -865,7 +863,7 @@ private void checkRewardAndWithdraw(byte[] contract, boolean isZero) throws Exce long beginCycle = manager.getDelegationStore().getBeginCycle(contract); long currentCycle = manager.getDynamicPropertiesStore().getCurrentCycleNumber(); long passedCycle = max(0, currentCycle - beginCycle, - manager.getDynamicPropertiesStore().allowStrictMath2()); + manager.getDynamicPropertiesStore().disableJavaLangMath()); Assert.assertTrue(isZero ? rewardBySystem == 0 : rewardBySystem > 0); triggerContract(contract, SUCCESS, getConsumer(">=", rewardBySystem) diff --git a/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java index 1f9a9af825c..213bbd6cb85 100644 --- a/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java @@ -109,7 +109,7 @@ public void successUpdateSettingContract() { Assert.assertEquals( dbManager.getContractStore().get(ByteArray.fromHexString(CONTRACT_ADDRESS)) .getConsumeUserResourcePercent( - dbManager.getDynamicPropertiesStore().allowStrictMath2()), TARGET_PERCENT); + dbManager.getDynamicPropertiesStore().disableJavaLangMath()), TARGET_PERCENT); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -246,7 +246,7 @@ public void twiceUpdateSettingContract() { Assert.assertEquals( dbManager.getContractStore().get(ByteArray.fromHexString(CONTRACT_ADDRESS)) .getConsumeUserResourcePercent( - dbManager.getDynamicPropertiesStore().allowStrictMath2()), TARGET_PERCENT); + dbManager.getDynamicPropertiesStore().disableJavaLangMath()), TARGET_PERCENT); // second secondActuator.validate(); @@ -256,7 +256,7 @@ public void twiceUpdateSettingContract() { Assert.assertEquals( dbManager.getContractStore().get(ByteArray.fromHexString(CONTRACT_ADDRESS)) .getConsumeUserResourcePercent( - dbManager.getDynamicPropertiesStore().allowStrictMath2()), 90L); + dbManager.getDynamicPropertiesStore().disableJavaLangMath()), 90L); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index c17cba03304..a7fc2feaf87 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -1196,6 +1196,6 @@ public void blockTrigger() { public void adjustBalance(AccountStore accountStore, byte[] accountAddress, long amount) throws BalanceInsufficientException { Commons.adjustBalance(accountStore, accountAddress, amount, - chainManager.getDynamicPropertiesStore().allowStrictMath2()); + chainManager.getDynamicPropertiesStore().disableJavaLangMath()); } } diff --git a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java index c1b0f8bb507..300a38a0916 100644 --- a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java @@ -113,7 +113,7 @@ public void testUpdateConsensusLogicOptimization() { Assert.assertEquals(v, 0); Assert.assertTrue(!dbManager.getDynamicPropertiesStore().allowConsensusLogicOptimization()); Assert.assertFalse(dbManager.getDynamicPropertiesStore().allowWitnessSortOptimization()); - Assert.assertFalse(dbManager.getDynamicPropertiesStore().allowStrictMath2()); + Assert.assertFalse(dbManager.getDynamicPropertiesStore().disableJavaLangMath()); long value = 1; Proposal proposal = @@ -128,7 +128,7 @@ public void testUpdateConsensusLogicOptimization() { Assert.assertTrue(dbManager.getDynamicPropertiesStore().allowConsensusLogicOptimization()); Assert.assertTrue(dbManager.getDynamicPropertiesStore().allowWitnessSortOptimization()); - Assert.assertTrue(dbManager.getDynamicPropertiesStore().allowStrictMath2()); + Assert.assertTrue(dbManager.getDynamicPropertiesStore().disableJavaLangMath()); } } \ No newline at end of file From 87695361b6e45fc71742ae0b2b6d2969e22f5283 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Mon, 24 Feb 2025 15:04:52 +0800 Subject: [PATCH 1147/1197] feat(config): modify fastForward configuration --- framework/src/main/resources/config.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 49b11d41e42..a89d6fd094e 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -201,7 +201,7 @@ node { ] fastForward = [ - "100.26.245.209:18888", + "100.27.171.62:18888", "15.188.6.125:18888" ] From 5460d12f84b6222eaa9a1b2da1a2f3896d53264c Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 24 Feb 2025 15:21:40 +0800 Subject: [PATCH 1148/1197] clear ch.qos.logback:1.2.9 --- gradle/verification-metadata.xml | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 3e061306873..34ab41b748a 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -33,14 +33,6 @@ - - - - - - - - @@ -49,24 +41,11 @@ - - - - - - - - - - - - - From fbaa09bf989070c42f673122b619b0bea1278097 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 24 Feb 2025 16:06:43 +0800 Subject: [PATCH 1149/1197] feat(workflows): upgrade CodeQL Action to v3 see: https://github.blog/changelog/2025-01-10-code-scanning-codeql-action-v2-is-now-deprecated/ --- .github/workflows/codeql.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 4ab98d5cf3c..5a0f120e116 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -33,7 +33,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -46,7 +46,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -59,6 +59,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" From f187e1031f36a147f7aac5e708b6663b2eb8b134 Mon Sep 17 00:00:00 2001 From: Liulei Date: Tue, 25 Feb 2025 11:53:37 +0800 Subject: [PATCH 1150/1197] fix(tvm): revert tstore in staticcall --- .../src/main/java/org/tron/core/vm/OperationActions.java | 3 +++ .../core/vm/program/invoke/ProgramInvokeMockImpl.java | 4 ++++ .../java/org/tron/common/runtime/vm/OperationsTest.java | 9 +++++++++ 3 files changed, 16 insertions(+) diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index 95370ff16bb..fa1aedbb5f8 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -656,6 +656,9 @@ public static void tLoadAction(Program program) { } public static void tStoreAction(Program program) { + if (program.isStaticCall()) { + throw new Program.StaticCallModificationException(); + } DataWord key = program.stackPop(); DataWord value = program.stackPop(); DataWord address = program.getContractAddress(); diff --git a/actuator/src/main/java/org/tron/core/vm/program/invoke/ProgramInvokeMockImpl.java b/actuator/src/main/java/org/tron/core/vm/program/invoke/ProgramInvokeMockImpl.java index e22c5d06578..567ac72931a 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/invoke/ProgramInvokeMockImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/program/invoke/ProgramInvokeMockImpl.java @@ -210,6 +210,10 @@ public void setOwnerAddress(byte[] ownerAddress) { this.ownerAddress = Arrays.clone(ownerAddress); } + public void setStaticCall(boolean isStatic) { + isStaticCall = isStatic; + } + @Override public boolean isStaticCall() { return isStaticCall; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java index 01d54c2194a..fe04b4719a6 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java @@ -953,6 +953,15 @@ public void testTransientStorageOperations() throws ContractValidateException { // TSTORE = 0x5d; op = new byte[] {0x60, 0x01, 0x60, 0x01, 0x5d}; + + invoke.setStaticCall(true); + program = new Program(op, op, invoke, interTrx); + testOperations(program); + Assert.assertEquals(20000, program.getResult().getEnergyUsed()); + Assert.assertTrue(program.getResult().getException() + instanceof Program.StaticCallModificationException); + + invoke.setStaticCall(false); program = new Program(op, op, invoke, interTrx); testOperations(program); Assert.assertEquals(106, program.getResult().getEnergyUsed()); From adab9ddeb44476500a702133fca040be5ff30d18 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 26 Feb 2025 11:08:41 +0800 Subject: [PATCH 1151/1197] feat(start): adjust consensusService start before tronNetService Closes #6215 --- .../java/org/tron/common/application/ApplicationImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java index 9224ddaee14..ffb70722822 100644 --- a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java +++ b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java @@ -42,10 +42,10 @@ public class ApplicationImpl implements Application { public void startup() { this.startServices(); eventService.init(); + consensusService.start(); if ((!Args.getInstance().isSolidityNode()) && (!Args.getInstance().isP2pDisable())) { tronNetService.start(); } - consensusService.start(); MetricsUtil.init(); } @@ -53,10 +53,10 @@ public void startup() { public void shutdown() { this.shutdownServices(); eventService.close(); - consensusService.stop(); if (!Args.getInstance().isSolidityNode() && (!Args.getInstance().p2pDisable)) { tronNetService.close(); } + consensusService.stop(); dbManager.close(); shutdown.countDown(); } From 34393f62128db9e2930a26e7e5a1a3f1b5c27420 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Wed, 26 Feb 2025 18:57:05 +0800 Subject: [PATCH 1152/1197] feat(test): optimize unit testing configuration --- .../common/utils/client/WalletClient.java | 59 --- .../common/utils/client/utils/HttpMethed.java | 17 +- .../core/services/NodeInfoServiceTest.java | 16 - .../src/test/resources/config-localtest.conf | 4 +- framework/src/test/resources/testng.conf | 499 ------------------ 5 files changed, 9 insertions(+), 586 deletions(-) delete mode 100644 framework/src/test/resources/testng.conf diff --git a/framework/src/test/java/org/tron/common/utils/client/WalletClient.java b/framework/src/test/java/org/tron/common/utils/client/WalletClient.java index 37b67ffaa46..9d9a68da49d 100644 --- a/framework/src/test/java/org/tron/common/utils/client/WalletClient.java +++ b/framework/src/test/java/org/tron/common/utils/client/WalletClient.java @@ -96,65 +96,6 @@ public WalletClient(final ECKey ecKey) { this.ecKey = ecKey; } - /** - * constructor. - */ - - public static boolean init(int itype) { - Config config = Configuration.getByPath("testng.conf"); - dbPath = config.getString("CityDb.DbPath"); - txtPath = System.getProperty("user.dir") + '/' + config.getString("CityDb.TxtPath"); - - String fullNodepathname = ""; - - if (1000 == itype) { - fullNodepathname = "checkfullnode.ip.list"; - } else { - fullNodepathname = "fullnode.ip.list"; - } - String fullNode = ""; - String solidityNode = ""; - if (config.hasPath("soliditynode.ip.list")) { - solidityNode = config.getStringList("soliditynode.ip.list").get(0); - } - if (config.hasPath(fullNodepathname)) { - fullNode = config.getStringList(fullNodepathname).get(itype); - } - if (config.hasPath("net.type") && "mainnet".equalsIgnoreCase(config.getString("net.type"))) { - WalletClient.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } else { - WalletClient.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_TESTNET); - } - rpcCli = new GrpcClient(fullNode, solidityNode); - return true; - } - - /** - * constructor. - */ - - public static GrpcClient init() { - //Config config = org.tron.core.config.Configuration.getByPath("config.conf"); - Config config = Configuration.getByPath("testng.conf"); - dbPath = config.getString("CityDb.DbPath"); - txtPath = System.getProperty("user.dir") + "/" + config.getString("CityDb.TxtPath"); - - String fullNode = ""; - String solidityNode = ""; - if (config.hasPath("soliditynode.ip.list")) { - solidityNode = config.getStringList("soliditynode.ip.list").get(0); - } - if (config.hasPath("fullnode.ip.list")) { - fullNode = config.getStringList("fullnode.ip.list").get(0); - } - if (config.hasPath("net.type") && "mainnet".equalsIgnoreCase(config.getString("net.type"))) { - WalletClient.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - } else { - WalletClient.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_TESTNET); - } - return new GrpcClient(fullNode, solidityNode); - } - public static byte getAddressPreFixByte() { return addressPreFixByte; } diff --git a/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java b/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java index 5a085e16ca6..a68bb616f11 100644 --- a/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/HttpMethed.java @@ -36,10 +36,8 @@ public class HttpMethed { static HttpClient httpClient; static HttpPost httppost; static HttpResponse response; - static Integer connectionTimeout = - Configuration.getByPath("testng.conf").getInt("defaultParameter.httpConnectionTimeout"); - static Integer soTimeout = - Configuration.getByPath("testng.conf").getInt("defaultParameter.httpSoTimeout"); + static Integer connectionTimeout = 19000; + static Integer soTimeout = 18000; static String transactionString; static String transactionSignString; static JSONObject responseContent; @@ -48,8 +46,7 @@ public class HttpMethed { public static volatile Integer witnessNum; /** constructor. */ - private static volatile String httpnode = - Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list").get(1); + private static volatile String httpnode = "127.0.0.1:50052"; /** constructor. */ public static Integer getWitnessNum() { @@ -1171,7 +1168,7 @@ public static String gettransactionsign( String httpNode, String transactionString, String privateKey) { try { transactionSignString = TransactionUtils.getTransactionSign(transactionString, privateKey, - false); + false); } catch (Exception e) { e.printStackTrace(); httppost.releaseConnection(); @@ -3446,7 +3443,7 @@ public static Boolean getSpendResult( String jsonString = responseContent.toJSONString(); if (jsonString.contains("result") && (responseContent.getString("result").equals("true") - && responseContent.getString("message").equals("Input note has been spent"))) { + && responseContent.getString("message").equals("Input note has been spent"))) { return Boolean.TRUE; } else { return Boolean.FALSE; @@ -3501,7 +3498,7 @@ public static Boolean getSpendResultFromSolidity( String jsonString = responseContent.toJSONString(); if (jsonString.contains("result") && (responseContent.getString("result").equals("true") - && responseContent.getString("message").equals("Input note has been spent"))) { + && responseContent.getString("message").equals("Input note has been spent"))) { return Boolean.TRUE; } else { return Boolean.FALSE; @@ -3552,7 +3549,7 @@ public static Boolean getSpendResultFromPbft( String jsonString = responseContent.toJSONString(); if (jsonString.contains("result") && (responseContent.getString("result").equals("true") - && responseContent.getString("message").equals("Input note has been spent"))) { + && responseContent.getString("message").equals("Input note has been spent"))) { return Boolean.TRUE; } else { return Boolean.FALSE; diff --git a/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java b/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java index 19d0540e5e6..be0a96f632b 100644 --- a/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/NodeInfoServiceTest.java @@ -4,21 +4,15 @@ import com.alibaba.fastjson.JSON; import com.google.protobuf.ByteString; -import io.grpc.ManagedChannelBuilder; import java.net.InetSocketAddress; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; import org.mockito.Mockito; -import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.WalletGrpc; -import org.tron.api.WalletGrpc.WalletBlockingStub; import org.tron.common.application.TronApplicationContext; import org.tron.common.entity.NodeInfo; import org.tron.common.utils.Sha256Hash; -import org.tron.common.utils.client.Configuration; import org.tron.core.capsule.BlockCapsule; import org.tron.core.net.P2pEventHandlerImpl; -import org.tron.core.net.peer.PeerManager; import org.tron.p2p.connection.Channel; import org.tron.program.Version; @@ -29,8 +23,6 @@ public class NodeInfoServiceTest { private NodeInfoService nodeInfoService; private WitnessProductBlockService witnessProductBlockService; private P2pEventHandlerImpl p2pEventHandler; - private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") - .get(0); public NodeInfoServiceTest(TronApplicationContext context) { nodeInfoService = context.getBean("nodeInfoService", NodeInfoService.class); @@ -60,12 +52,4 @@ public void test() { logger.info("{}", JSON.toJSONString(nodeInfo)); } - public void testGrpc() { - WalletBlockingStub walletStub = WalletGrpc - .newBlockingStub(ManagedChannelBuilder.forTarget(fullnode) - .usePlaintext() - .build()); - logger.info("getNodeInfo: {}", walletStub.getNodeInfo(EmptyMessage.getDefaultInstance())); - } - } diff --git a/framework/src/test/resources/config-localtest.conf b/framework/src/test/resources/config-localtest.conf index 44c051e1079..b6c1f41154a 100644 --- a/framework/src/test/resources/config-localtest.conf +++ b/framework/src/test/resources/config-localtest.conf @@ -225,7 +225,7 @@ genesis.block = { witnesses = [ { - address: TN3zfjYUmMFK3ZsHSsrdJoNRtGkQmZLBLz + address: TEDapYSVvAZ3aYH7w8N9tMEEFKaNKUD5Bp url = "http://test.org/", voteCount = 106 }, @@ -262,7 +262,7 @@ genesis.block = { //localWitnessAccountAddress = TN3zfjYUmMFK3ZsHSsrdJoNRtGkQmZLBLz localwitness = [ - f4df789d3210ac881cb900464dd30409453044d2777060a0c391cbdf4c6a4f57 + 1234567890123456789012345678901234567890123456789012345678901234 ] diff --git a/framework/src/test/resources/testng.conf b/framework/src/test/resources/testng.conf deleted file mode 100644 index ea4f25ad87b..00000000000 --- a/framework/src/test/resources/testng.conf +++ /dev/null @@ -1,499 +0,0 @@ -net { - type = mainnet -} - -fullnode = { - ip.list = [ - #Docker env - "127.0.0.1:50051", - "127.0.0.1:50052", - - #New beat1 - "39.106.145.222:50051", - "101.200.46.37:50051", - #"101.200.46.37:50051", - - #New beta2 - "101.200.46.37:50052", - "39.106.145.222:50052", - "101.200.46.37:50052", - - #Stress env - #"47.94.243.150:50051", - #"39.106.110.112:50051", - - #MainNet env - #"47.95.206.44:50051", - #"47.95.206.44:50051", - - - ] -} - -solidityNode = { - ip.list = [ - #Docker env - "127.0.0.1:50053", - "127.0.0.1:50062", - "127.0.0.1:50071", - - #New beat 1 - "39.106.145.222:50061", - "39.106.145.222:50061", - #"39.106.145.222:50071", - - #New beat 2 - "101.200.46.37:50053", - "101.200.46.37:50062", - "101.200.46.37:50071", - #"101.200.46.37:50071", - - - #Main Net env - #"47.95.206.44:50061", - ] -} - -httpnode = { - ip.list = [ - #docker env - "127.0.0.1:8090", - "127.0.0.1:8093", - "127.0.0.1:8097", - "127.0.0.1:8091", - "127.0.0.1:8098", - - - #New beta 2 - "101.200.46.37:50091", - "39.106.145.222:50091", - "101.200.46.37:50192", - "101.200.46.37:50094", - "101.200.46.37:50082", - #"101.200.46.37:50082", - ] -} - -eventnode = { - ip.list = [ - "tcp://127.0.0.1:50096", - #"tcp://39.106.145.222:50096", - ] -} - -jsonRpcNode = { - ip.list = [ - #"101.200.46.37:50545", - "127.0.0.1:50545", - "127.0.0.1:50555", - ] -} - -ethHttpsNode = { - host.list = [ - "mainnet.infura.io", - #"47.95.206.44:50545", - ] -} - - -foundationAccount = { - -} - - -witness = { - -} - -mainWitness = { - -} - -defaultParameter = { - maxFeeLimit = 1000000000 - assetDescription = stest-assetissue - assetUrl = github.com/tronprotocol/wallet/stest - multiSignFee = 1000000 - updateAccountPermissionFee = 100000000 - httpConnectionTimeout = 19000 - httpSoTimeout = 18000 - createWitnessAmount = 9999000000 - operations = 7fff1fc0033e3300000000000000000000000000000000000000000000000000 - delayTransactionFee = 100000 - cancleDelayTransactionFee = 50000 - solidityCompilerVersion = "v5" - solidityCompile = "../solcDIR/solc" - zenTokenOwnerKey = 2925e186bb1e88988855f11ebf20ea3a6e19ed92328b0ffb576122e769d45b68 - zenTokenId = 1000001 - zenTokenFee = 10000000 - zenTokenWhenCreateNewAddress = 1000000 - zenTrc20TokenOwnerKey = ede941a01eb8234866f60c7e8e95db4614bb0d05298d82bae0abea81f1861046 - jsonRpcOwnerKey = dbc78781ad27f3751358333412d5edc85b13e5eee129a1a77f7232baadafae0e - blackHoleAddress = THmtHi1Rzq4gSKYGEKv1DPkV7au6xU1AUB -} - - -code = { - code_AssertException_testdivideInt = "608060405234801561001057600080fd5b5060ac8061001f6000396000f300608060405260043610603d5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166226ff5581146042575b600080fd5b348015604d57600080fd5b50605a600435602435606c565b60408051918252519081900360200190f35b60008183811515607857fe5b0593925050505600a165627a7a72305820b587002bc926764a997a3925613203906e484069ff4e2f8324b4dce6088326220029" - code_AssertException_testfindArgsContractMinTest = "608060405234801561001057600080fd5b50610134806100206000396000f3006080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663329000b58114610045575b600080fd5b34801561005157600080fd5b5061005d60043561006f565b60408051918252519081900360200190f35b604080516003808252608082019092526000916060919060208201838038833901905050905060018160008151811015156100a657fe5b602090810290910101528051600290829060019081106100c257fe5b602090810290910101528051600390829060029081106100de57fe5b6020908102909101015280518190849081106100f657fe5b906020019060200201519150509190505600a165627a7a72305820e426d63fe06962cb78b523edb9295a369bc2cc1b82cac5740d74e924b1a398c40029" - code_AssertException_testbyteMinContract = "608060405234801561001057600080fd5b50610305806100206000396000f3006080604052600436106100405763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166383be82a38114610045575b600080fd5b34801561005157600080fd5b5061005d600435610092565b604080517fff000000000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b60408051600380825281830190925260009160208201606080388339505081516100c392600092506020019061023e565b50600c60f860020a0260008081546001816001161561010002031660029004811015156100ec57fe5b81546001161561010b5790600052602060002090602091828204019190065b601f036101000a81548160ff0219169060f860020a84040217905550600d60f860020a0260006001815460018160011615610100020316600290048110151561015057fe5b81546001161561016f5790600052602060002090602091828204019190065b601f036101000a81548160ff0219169060f860020a84040217905550600e60f860020a026000600281546001816001161561010002031660029004811015156101b457fe5b8154600116156101d35790600052602060002090602091828204019190065b601f036101000a81548160ff0219169060f860020a84040217905550600082815460018160011615610100020316600290048110151561020f57fe5b81546001161561022e5790600052602060002090602091828204019190065b905460f860020a911a0292915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061027f57805160ff19168380011785556102ac565b828001600101855582156102ac579182015b828111156102ac578251825591602001919060010190610291565b506102b89291506102bc565b5090565b6102d691905b808211156102b857600081556001016102c2565b905600a165627a7a72305820c42a0dcadb40b736d1d61cf46a58a66e740573568264ed5ce2f9b1de442d39fe0029" - code_AssertException_testenum = "608060405234801561001057600080fd5b5060f18061001f6000396000f30060806040526004361060485763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166367cb61b68114604d578063fb76fa52146082575b600080fd5b348015605857600080fd5b50605f609c565b60405180826003811115606e57fe5b60ff16815260200191505060405180910390f35b348015608d57600080fd5b50609a60ff6004351660a5565b005b60005460ff1690565b6000805482919060ff1916600183600381111560bd57fe5b0217905550505600a165627a7a723058201ad3f79794ab99b9429a737984c9e0722214f7412fa23f4f8895f58032e222360029" - code_AssertException_testmoveRight = "608060405234801561001057600080fd5b5060b38061001f6000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630599d3dc81146043575b600080fd5b348015604e57600080fd5b506058600435606a565b60408051918252519081900360200190f35b60008160056000821215607957fe5b60029190910a9005929150505600a165627a7a72305820e944c4077f7d4f205074c52900d041d56d5f700a779aed8ced4af969f99464760029" - code_AssertException_testuninitializedContract = "608060405234801561001057600080fd5b5060e18061001f6000396000f30060806040526004361060485763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166366e41cb78114604d5780636b59084d146071575b600080fd5b348015605857600080fd5b50605f6083565b60408051918252519081900360200190f35b348015607c57600080fd5b50605f609c565b600060b36096600460058363ffffffff16565b91505090565b600060af60966004600563ffffffff8416565b0290565bfe00a165627a7a72305820adcb5758cba4260d0f840e31e0b97435395f43728ddfe8024de688c29583dd220029" - code_AssertException_testTestAssertContract = "608060405234801561001057600080fd5b5060b58061001f6000396000f300608060405260043610605c5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632b813bc081146061578063357815c414607557806350bff6bf146075578063a26388bb146075575b600080fd5b348015606c57600080fd5b5060736087565b005b348015608057600080fd5b506073605c565bfe00a165627a7a723058209284d2c51e121903dde36db88dae131b1b20dc83b987a6f491dcac2d9b2d30db0029" - - code_ContractGrammar001_testGrammar001 = "608060405234801561001057600080fd5b50610105806100206000396000f30060806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630a75057381146057578063cd580ff3146083578063f0fdf834146098575b600080fd5b348015606257600080fd5b506071600435151560243560ad565b60408051918252519081900360200190f35b348015608e57600080fd5b50607160043560ce565b34801560a357600080fd5b50607160043560d4565b600060d4831560ba575060ce5b60c6838263ffffffff16565b949350505050565b60020290565b8002905600a165627a7a7230582032df33d18c9876ca1a32117c2b4c526215a9dd8feeb3c9d849690539b3a992ac0029" - code_ContractGrammar001_testGrammar002 = "610199610030600b82828239805160001a6073146000811461002057610022565bfe5b5030600052607381538281f300730000000000000000000000000000000000000000301460806040526004361061006d5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663483b8a1481146100725780636ce8e081146100a1578063831cb739146100bc575b600080fd5b81801561007e57600080fd5b5061008d6004356024356100d7565b604080519115158252519081900360200190f35b8180156100ad57600080fd5b5061008d600435602435610117565b8180156100c857600080fd5b5061008d60043560243561012d565b60008181526020839052604081205460ff1615156100f757506000610111565b506000818152602083905260409020805460ff1916905560015b92915050565b6000908152602091909152604090205460ff1690565b60008181526020839052604081205460ff161561014c57506000610111565b50600090815260209190915260409020805460ff19166001908117909155905600a165627a7a723058205198109bfdc1087cafa3e909576bdb656bb058100cf618ef42eecaeb64e30b7f0029" - code1_ContractGrammar001_testGrammar002 = "608060405234801561001057600080fd5b50610139806100206000396000f3006080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663f207564e8114610045575b600080fd5b34801561005157600080fd5b5061005d60043561005f565b005b73__browser/TvmTest_p1_Grammar_002.sol:S__63831cb7396000836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808381526020018281526020019250505060206040518083038186803b1580156100d357600080fd5b505af41580156100e7573d6000803e3d6000fd5b505050506040513d60208110156100fd57600080fd5b5051151561010a57600080fd5b505600a165627a7a7230582044978981980e6552ad10452a66a2038edf7739f149dcced7705b0e329d594f300029" - code_ContractGrammar001_testGrammar003 = "610199610030600b82828239805160001a6073146000811461002057610022565bfe5b5030600052607381538281f300730000000000000000000000000000000000000000301460806040526004361061006d5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663483b8a1481146100725780636ce8e081146100a1578063831cb739146100bc575b600080fd5b81801561007e57600080fd5b5061008d6004356024356100d7565b604080519115158252519081900360200190f35b8180156100ad57600080fd5b5061008d600435602435610117565b8180156100c857600080fd5b5061008d60043560243561012d565b60008181526020839052604081205460ff1615156100f757506000610111565b506000818152602083905260409020805460ff1916905560015b92915050565b6000908152602091909152604090205460ff1690565b60008181526020839052604081205460ff161561014c57506000610111565b50600090815260209190915260409020805460ff19166001908117909155905600a165627a7a72305820026d1eee826a0f8eb329643f3547e967fb7631f83b1855c607bdd82706af37520029" - code1_ContractGrammar001_testGrammar003 = "608060405234801561001057600080fd5b50610137806100206000396000f3006080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663f207564e8114610045575b600080fd5b34801561005157600080fd5b5061005d60043561005f565b005b604080517f831cb7390000000000000000000000000000000000000000000000000000000081526000600482015260248101839052905173__browser/TvmTest_p1_Grammar_003.sol:S__9163831cb739916044808301926020929190829003018186803b1580156100d157600080fd5b505af41580156100e5573d6000803e3d6000fd5b505050506040513d60208110156100fb57600080fd5b5051151561010857600080fd5b505600a165627a7a72305820de817c43c8f916d8e300ee0f317061f220ba7971379253fc437c52ab40295d6f0029" - code_ContractGrammar001_testGrammar004 = "60f561002f600b82828239805160001a6073146000811461001f57610021565bfe5b5030600052607381538281f300730000000000000000000000000000000000000000301460806040526004361060555763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166324fef5c88114605a575b600080fd5b818015606557600080fd5b5060726004356024356084565b60408051918252519081900360200190f35b6000805b835481101560bc57828482815481101515609e57fe5b9060005260206000200154141560b55780915060c2565b6001016088565b60001991505b50929150505600a165627a7a72305820dd50badae5d39d8013dd477274519025531d3c7c11cd98cd10290fbace71b9510029" - code1_ContractGrammar001_testGrammar004 = "608060405234801561001057600080fd5b50610281806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630178fe3f8114610066578063e33b870714610090578063e81cf24c146100aa578063f0ba8440146100c5575b600080fd5b34801561007257600080fd5b5061007e6004356100dd565b60408051918252519081900360200190f35b34801561009c57600080fd5b506100a86004356100ff565b005b3480156100b657600080fd5b506100a8600435602435610131565b3480156100d157600080fd5b5061007e600435610236565b600080828154811015156100ed57fe5b90600052602060002001549050919050565b600080546001810182559080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5630155565b604080517f24fef5c800000000000000000000000000000000000000000000000000000000815260006004820181905260248201859052915173__browser/TvmTest_p1_Grammar_004.sol:S__916324fef5c8916044808301926020929190829003018186803b1580156101a557600080fd5b505af41580156101b9573d6000803e3d6000fd5b505050506040513d60208110156101cf57600080fd5b5051905060001981141561021457600080546001810182559080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56301829055610231565b8160008281548110151561022457fe5b6000918252602090912001555b505050565b600080548290811061024457fe5b6000918252602090912001549050815600a165627a7a72305820e8c6ea7734c94bd93e5388cb46b5a5ba3807df808e86fb52d4fa2a792685d9280029" - code_ContractGrammar001_testGrammar006 = "608060405234801561001057600080fd5b50610159806100206000396000f3006080604052600436106100825763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166321183e8d81146100875780637f6b590c146100a15780638de6f511146100b9578063b3de648b146100a1578063e668f6b6146100b9578063e7708d03146100b9578063fb095f2e146100a1575b600080fd5b34801561009357600080fd5b5061009f6004356100d1565b005b3480156100ad57600080fd5b5061009f6004356100e2565b3480156100c557600080fd5b5061009f6004356100e5565b600a5b6000190180156100d4575050565b50565b6100e2565b50919050565b828110156100ea576002909102906001016100f0565b60008180156101245761011b60018403610106565b830291506100ea565b506001929150505600a165627a7a723058209488a62acdb28a3bac209504cc3dd53d2ef7bf56cbb835e431c507bbc2b0b20b0029" - - code_ContractGrammar002_testGrammar007 = "608060405234801561001057600080fd5b506000602081905260017fe831479d2c88b7e2c4154b0e3fd4b67c62580aba2734ac954410a8c097fac7c35560027f156aefbe71d87b3f83e37064ce76ea7eb25ea897d2708aad4c1d03439058d3a3557f7a7a790000000000000000000000000000000000000000000000000000000000905260077fd0d0b23e4a00f3e9683c2bc8ad2b8ee67c66dc4b2ae07ae98ee14d014badcf83556101b2806100b66000396000f3006080604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166337721ab7811461005b578063a633d8d414610129578063ec56a37314610153575b600080fd5b34801561006757600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526100b494369492936024939284019190819084018382808284375094975061016b9650505050505050565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100ee5781810151838201526020016100d6565b50505050905090810190601f16801561011b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561013557600080fd5b5061014160043561016e565b60408051918252519081900360200190f35b34801561015f57600080fd5b50610141600435610174565b90565b60030a90565b600060208190529081526040902054815600a165627a7a72305820dda8d0ad404466b0389ba7a490a63e5acc2d4eaf8ee3f4937e09084fba1f5a5a0029" - code1_ContractGrammar002_testGrammar007 = "608060405234801561001057600080fd5b5060405160208061033d833981016040525160018054600160a060020a0319908116600160a060020a039384161791829055600280549290931691161790556102df8061005e6000396000f3006080604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166349de3f08811461005b5780639e3151a814610085578063f6598275146100b5575b600080fd5b34801561006757600080fd5b506100736004356100cd565b60408051918252519081900360200190f35b34801561009157600080fd5b506100b373ffffffffffffffffffffffffffffffffffffffff600435166101c9565b005b3480156100c157600080fd5b50610073600435610205565b600254604080517fec56a37300000000000000000000000000000000000000000000000000000000815260048101849052905160009273ffffffffffffffffffffffffffffffffffffffff169163ec56a37391602480830192602092919082900301818787803b15801561014057600080fd5b505af1158015610154573d6000803e3d6000fd5b505050506040513d602081101561016a57600080fd5b50506001546040805173ffffffffffffffffffffffffffffffffffffffff9092168252336020830152818101849052517f09208868f8090ea021d1f0e2ed8182e6a6f23a1f447267430e531bf2003c09199181900360600190a1919050565b6000805473ffffffffffffffffffffffffffffffffffffffff191673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600254604080517fa633d8d4000000000000000000000000000000000000000000000000000000008152600481018490529051600092839273ffffffffffffffffffffffffffffffffffffffff9091169163a633d8d49160248082019260209290919082900301818787803b15801561027d57600080fd5b505af1158015610291573d6000803e3d6000fd5b505050506040513d60208110156102a757600080fd5b505192909201929150505600a165627a7a723058208c58520ab7ab3c09ab693d81d3c7746deb66b7515d4258f26a379367fca4b95d0029" - code_ContractGrammar002_testGrammar008 = "608060405234801561001057600080fd5b50610188806100206000396000f30060806040526004361061004b5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663dba7ab6c8114610050578063f5f5ba7214610077575b600080fd5b34801561005c57600080fd5b50610065610101565b60408051918252519081900360200190f35b34801561008357600080fd5b5061008c610125565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100c65781810151838201526020016100ae565b50505050905090810190601f1680156100f35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b7f6d69616f7700000000000000000000000000000000000000000000000000000090565b60408051808201909152600681527f46656c696e6500000000000000000000000000000000000000000000000000006020820152905600a165627a7a723058206cd9ce9902b03355d5f4bd8e0e4c4d9cd5b5d65364c50454f2418305ab515b4f0029" - code_ContractGrammar002_testGrammar010 = "608060405234801561001057600080fd5b506101b7806100206000396000f30060806040526004361061004b5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166355b775ea8114610050578063f198f5df14610080575b600080fd5b34801561005c57600080fd5b5061007e73ffffffffffffffffffffffffffffffffffffffff60043516610095565b005b34801561008c57600080fd5b5061007e6100d1565b6000805473ffffffffffffffffffffffffffffffffffffffff191673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663370158ea600a610320906040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016020604051808303818589803b15801561015b57600080fd5b5088f115801561016f573d6000803e3d6000fd5b5050505050506040513d602081101561018757600080fd5b50505600a165627a7a72305820f2b3e0e175369ea0df0aef7c6b9e8644b34c144efe85d21cb38539d1abd32e970029" - code_ContractGrammar002_testGrammar011 = "608060405234801561001057600080fd5b5060c88061001f6000396000f30060806040526004361060485763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166313d1aa2e8114604d578063e2179b8e146077575b600080fd5b348015605857600080fd5b506065600435602435608b565b60408051918252519081900360200190f35b348015608257600080fd5b506089608f565b005b5090565b609960036002608b565b505600a165627a7a723058202aeac1a0dbc6913a9378d4e8294f1061e5798083067aa9db5d95d8d78f24d5430029" - code_ContractGrammar002_testGrammar012 = "608060405234801561001057600080fd5b50610169806100206000396000f3006080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663370158ea8114610045575b600080fd5b61004d6100c7565b6040805198895273ffffffffffffffffffffffffffffffffffffffff97881660208a01527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19909616888701526060880194909452608087019290925260a086015290921660c084015260e083019190915251908190036101000190f35b6000806000806000806000806000806000806000806000805a9f50339e50507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19600035169c50349b50429a503a995032985050303196508d95508c94508b93508a925089915088905050505050505090919293949596975600a165627a7a72305820ba2fd5e479d9fa3924efa9cef8dde8690cf0618a742fe972533b7eb5b2b3ca990029" - code_ContractGrammar002_testGrammar013 = "60806040526000805534801561001457600080fd5b5060018054600160a060020a0319163317905561014c806100366000396000f3006080604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166341c0e1b5811461005b578063a87d942c14610072578063d09de08a14610099575b600080fd5b34801561006757600080fd5b506100706100ae565b005b34801561007e57600080fd5b506100876100eb565b60408051918252519081900360200190f35b3480156100a557600080fd5b506100706100f1565b60015473ffffffffffffffffffffffffffffffffffffffff163314156100e95760015473ffffffffffffffffffffffffffffffffffffffff16ff5b565b60005490565b600154600a9073ffffffffffffffffffffffffffffffffffffffff1633141561011d5760008054820190555b505600a165627a7a72305820604072633e1ae10ab2bb71c55f8678aafe925bee8ebffa82a1eddc5c2ed1fc2d0029" - - code_ContractGrammar003_testGrammar014 = "608060405234801561001057600080fd5b50610435806100206000396000f3006080604052600436106100745763ffffffff60e060020a6000350416633da5d187811461007957806343c3a43a1461009f578063b053ebd4146100c3578063c8287909146100f4578063d7d21f5b14610109578063dd92afef1461012d578063ee9e398114610154578063fa06834b14610175575b600080fd5b34801561008557600080fd5b5061009d600160a060020a036004351660243561018a565b005b3480156100ab57600080fd5b5061009d600160a060020a0360043516602435610205565b3480156100cf57600080fd5b506100d8610282565b60408051600160a060020a039092168252519081900360200190f35b34801561010057600080fd5b506100d8610291565b34801561011557600080fd5b5061009d600160a060020a03600435166024356102a0565b34801561013957600080fd5b5061014261031d565b60408051918252519081900360200190f35b34801561016057600080fd5b5061009d600160a060020a0360043516610323565b34801561018157600080fd5b50610142610403565b81600160a060020a031660405180807f73657456616c75652875696e74323536290000000000000000000000000000008152506011019050604051809103902060e060020a9004826040518263ffffffff1660e060020a02815260040180828152602001915050600060405180830381865af4505050505050565b81600160a060020a031660405180807f73657456616c75652875696e74323536290000000000000000000000000000008152506011019050604051809103902060e060020a9004826040518263ffffffff1660e060020a028152600401808281526020019150506000604051808303816000875af1505050505050565b600154600160a060020a031681565b600154600160a060020a031690565b81600160a060020a031660405180807f73657456616c75652875696e74323536290000000000000000000000000000008152506011019050604051809103902060e060020a9004826040518263ffffffff1660e060020a028152600401808281526020019150506000604051808303816000875af2505050505050565b60005481565b80600160a060020a031660405180807f61646428290000000000000000000000000000000000000000000000000000008152506005019050604051809103902060e060020a90046040518163ffffffff1660e060020a0281526004016000604051808303816000875af1925050505080600160a060020a031660405180807f61646428290000000000000000000000000000000000000000000000000000008152506005019050604051809103902060e060020a90046040518163ffffffff1660e060020a0281526004016000604051808303816000875af15050505050565b600054905600a165627a7a7230582093a7a067c2321655a53783d1d54310cf8d57828093eeb9cf511536f8834f2de50029" - code1_ContractGrammar003_testGrammar014 = "608060405234801561001057600080fd5b5061055d806100206000396000f30060806040526004361061007f5763ffffffff60e060020a6000350416630eec1aba81146100845780631645c6c8146100b5578063466427c0146100cd5780634f2be91f146100e557806355241077146100fc578063b053ebd414610114578063c828790914610129578063dd92afef1461013e578063fa06834b14610165575b600080fd5b34801561009057600080fd5b5061009961017a565b60408051600160a060020a039092168252519081900360200190f35b3480156100c157600080fd5b50610099600435610189565b3480156100d957600080fd5b506100996004356101a4565b3480156100f157600080fd5b506100fa6101bf565b005b34801561010857600080fd5b506100fa600435610407565b34801561012057600080fd5b5061009961042b565b34801561013557600080fd5b5061009961043a565b34801561014a57600080fd5b50610153610449565b60408051918252519081900360200190f35b34801561017157600080fd5b5061015361044f565b600254600160a060020a031681565b600460205260009081526040902054600160a060020a031681565b600360205260009081526040902054600160a060020a031681565b600080546001018155806101d1610455565b604051809103906000f0801580156101ed573d6000803e3d6000fd5b50915081600160a060020a03166338cc48316040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561022e57600080fd5b505af1158015610242573d6000803e3d6000fd5b505050506040513d602081101561025857600080fd5b5051600080548152600360209081526040808320805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0395861617905580517f38cc48310000000000000000000000000000000000000000000000000000000081529051938616936338cc483193600480840194938390030190829087803b1580156102e157600080fd5b505af11580156102f5573d6000803e3d6000fd5b505050506040513d602081101561030b57600080fd5b50516002805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03909216919091179055610341610455565b604051809103906000f08015801561035d573d6000803e3d6000fd5b50905080600160a060020a03166338cc48316040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561039e57600080fd5b505af11580156103b2573d6000803e3d6000fd5b505050506040513d60208110156103c857600080fd5b5051600080548152600460205260409020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039092169190911790555050565b6000556001805473ffffffffffffffffffffffffffffffffffffffff191633179055565b600154600160a060020a031681565b600154600160a060020a031690565b60005481565b60005490565b60405160cd80610465833901905600608060405234801561001057600080fd5b5060ae8061001f6000396000f300608060405260043610603e5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166338cc483181146043575b600080fd5b348015604e57600080fd5b506055607e565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b30905600a165627a7a7230582002da030c3a635a762a2cd57a6d82b2c8a097197a64cad72ca827e7e227e67dd90029a165627a7a7230582023d343e99ca6abe7ec5591fd8706cb1a6d5bb25e9868b17445ad3171a6e295fd0029" - code_ContractGrammar003_testGrammar015 = "608060405234801561001057600080fd5b50610317806100206000396000f3006080604052600436106100535763ffffffff60e060020a600035041663292a1c6881146100b357806342a78883146100da57806342bb5a26146100f457806366b0bae0146101095780637c06885a1461011e575b34801561005f57600080fd5b507f17c1956f6e992470102c5fc953bf560fda31fabee8737cf8e77bdde00eb5698d6000366040518080602001828103825284848281815260200192508082843760405192018290039550909350505050a1005b3480156100bf57600080fd5b506100c8610133565b60408051918252519081900360200190f35b3480156100e657600080fd5b506100f2600435610168565b005b34801561010057600080fd5b506100c86101c4565b34801561011557600080fd5b506100f26101f9565b34801561012a57600080fd5b506100f261027c565b604080517f457869737446756e6343616c6c65642862797465732c75696e743235362900008152905190819003601e01902090565b7fb776d49293459725ca7d6a5abc60e389d2f3d067d4f028ba9cd790f69659984660003683604051808060200183815260200182810382528585828181526020019250808284376040519201829003965090945050505050a150565b604080517f46616c6c6261636b43616c6c65642862797465732900000000000000000000008152905190819003601501902090565b600060405180807f66756e6374696f6e4e6f744578697374282900000000000000000000000000008152506012019050604051809103902090503073ffffffffffffffffffffffffffffffffffffffff168160e060020a90046040518163ffffffff1660e060020a0281526004016000604051808303816000875af15050505050565b604080517f657869737446756e632875696e743235362900000000000000000000000000008152815190819003601201812063ffffffff60e060020a8083049182160283526001600484015292519092309290916024808301926000929190829003018183875af150505050505600a165627a7a7230582065d5e244faea44396a1826f0c2919055c883a00eef975f72a579ee7f0c654a0b0029" - code_ContractGrammar003_testGrammar016 = "608060405234801561001057600080fd5b50610270806100206000396000f3006080604052600436106100275763ffffffff60e060020a600035041663bef55ef3811461002c575b600080fd5b34801561003857600080fd5b50610041610043565b005b60008061004e610157565b604051809103906000f08015801561006a573d6000803e3d6000fd5b5091508173ffffffffffffffffffffffffffffffffffffffff16635b4b73a960036040518263ffffffff1660e060020a02815260040180828152602001915050600060405180830381600087803b1580156100c457600080fd5b505af11580156100d8573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff16633bc5de306040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561012757600080fd5b505af115801561013b573d6000803e3d6000fd5b505050506040513d602081101561015157600080fd5b50505050565b60405160de80610167833901905600608060405234801561001057600080fd5b5060bf8061001f6000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633bc5de308114604d5780635b4b73a9146071575b600080fd5b348015605857600080fd5b50605f6088565b60408051918252519081900360200190f35b348015607c57600080fd5b506086600435608e565b005b60005490565b6000555600a165627a7a72305820f4a95b9ecc5b7f7b57cbf2caff1c5f2f5e6e2dbd28464523cc05abde5864fd010029a165627a7a723058207ab90bb4123df32a1805dc37faaac054a403d1ab28007eb48c99ea48fefae6e90029" - code1_ContractGrammar003_testGrammar016 = "608060405234801561001057600080fd5b50610214806100206000396000f3006080604052600436106100565763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633bc5de30811461005b5780635b4b73a914610082578063e2179b8e1461009c575b600080fd5b34801561006757600080fd5b506100706100b1565b60408051918252519081900360200190f35b34801561008e57600080fd5b5061009a6004356100b7565b005b3480156100a857600080fd5b5061009a6100bc565b60005490565b600055565b6000806100c76100fb565b604051809103906000f0801580156100e3573d6000803e3d6000fd5b5091506100f2600360056100f7565b505050565b0190565b60405160de8061010b833901905600608060405234801561001057600080fd5b5060bf8061001f6000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633bc5de308114604d5780635b4b73a9146071575b600080fd5b348015605857600080fd5b50605f6088565b60408051918252519081900360200190f35b348015607c57600080fd5b506086600435608e565b005b60005490565b6000555600a165627a7a72305820f4a95b9ecc5b7f7b57cbf2caff1c5f2f5e6e2dbd28464523cc05abde5864fd010029a165627a7a723058205eb1e089faa9ff3eba073d682ee515d9d086d2ce3d4043109292b99a8a91d15f0029" - code_ContractGrammar003_testGrammar017 = "608060405234801561001057600080fd5b50610306806100206000396000f3006080604052600436106100565763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630121b93f811461005b5780635f72f4501461006857806397a9dae914610094575b600080fd5b6100666004356100d7565b005b34801561007457600080fd5b50610080600435610160565b604080519115158252519081900360200190f35b3480156100a057600080fd5b506100c573ffffffffffffffffffffffffffffffffffffffff600435166024356101e4565b60408051918252519081900360200190f35b60009081526001602081815260408084208151808301835233815234818501818152600384018054808901909155885260048401909552929095209451855473ffffffffffffffffffffffffffffffffffffffff191673ffffffffffffffffffffffffffffffffffffffff90911617855591519390920192909255600290910180549091019055565b600081815260016020819052604082209081015460028201548391111561018a57600092506101dd565b506002810180546000918290558254604051919273ffffffffffffffffffffffffffffffffffffffff9091169183156108fc0291849190818181858888f1935050505015156101d857600080fd5b600192505b5050919050565b6040805160808101825273ffffffffffffffffffffffffffffffffffffffff9384168152602080820193845260009282018381526060830184815293805260019182905291517fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49805473ffffffffffffffffffffffffffffffffffffffff1916919096161790945591517fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4a5590517fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4b55517fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4c55905600a165627a7a72305820774c07868cec7fa6d603c6bffa4ad224b2c7523a44248047a445872f15b064980029" - code_ContractGrammar003_testGrammar018 = "608060405234801561001057600080fd5b5061025b806100206000396000f3006080604052600436106100775763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166307423b35811461007c5780634c15d6db146100a35780635ee41656146100b8578063a449e8eb146100cd578063b7a0961a146100e2578063d23d7e8a1461007c575b600080fd5b34801561008857600080fd5b506100916100f7565b60408051918252519081900360200190f35b3480156100af57600080fd5b5061009161012c565b3480156100c457600080fd5b5061009161013a565b3480156100d957600080fd5b50610091610147565b3480156100ee57600080fd5b506100916101b4565b604080517f31310000000000000000000000000000000000000000000000000000000000008152905190819003600201902090565b600060046003600209905090565b6000600360028008905090565b6000600260405180807f313100000000000000000000000000000000000000000000000000000000000081525060020190506020604051808303816000865af1158015610198573d6000803e3d6000fd5b5050506040513d60208110156101ad57600080fd5b5051905090565b6000600360405180807f313100000000000000000000000000000000000000000000000000000000000081525060020190506020604051808303816000865af1158015610205573d6000803e3d6000fd5b505050604051516c01000000000000000000000000026bffffffffffffffffffffffff19169050905600a165627a7a72305820af56e004716c8ccf6d0609f6bcdc39fa45fda7fbc38e049ef6bab4609abf86e10029" - code_ContractGrammar003_testGrammar019 = "6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00a165627a7a7230582027e85e5bf589c5cecb1dd0d8712fa54ff07ff16b4dca5a602c53587c17898b2f0029" - code_ContractGrammar003_testGrammar020 = "608060405234801561001057600080fd5b5060a48061001f6000396000f300608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ccb5f721146044575b600080fd5b348015604f57600080fd5b5060566058565b005b620f424080141515606857600080fd5b600180141515607657600080fd5b5600a165627a7a72305820fdd16dc5b670249de6546a7474b1c29f5894578d17a251188bc616cc4476022c0029" - code_ContractScenario004_deployErc20TronToken = "60c0604052600660808190527f54726f6e6978000000000000000000000000000000000000000000000000000060a090815261003e916000919061013c565b506040805180820190915260038082527f545258000000000000000000000000000000000000000000000000000000000060209092019182526100839160019161013c565b506006600281905560006005558054600160a860020a03191690553480156100aa57600080fd5b50604051602080610abc83398101604081815291516006805461010060a860020a031916336101000217905567016345785d8a00006005819055600160a060020a03821660008181526003602090815286822084905592855294519294909390927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a3506101d7565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785556101aa565b828001600101855582156101aa579182015b828111156101aa57825182559160200191906001019061018f565b506101b69291506101ba565b5090565b6101d491905b808211156101b657600081556001016101c0565b90565b6108d6806101e66000396000f3006080604052600436106100cf5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100d457806307da68f51461015e578063095ea7b31461017557806318160ddd146101ad57806323b872dd146101d4578063313ce567146101fe57806342966c681461021357806370a082311461022b57806375f12b211461024c57806395d89b4114610261578063a9059cbb14610276578063be9a65551461029a578063c47f0027146102af578063dd62ed3e14610308575b600080fd5b3480156100e057600080fd5b506100e961032f565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561012357818101518382015260200161010b565b50505050905090810190601f1680156101505780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561016a57600080fd5b506101736103bd565b005b34801561018157600080fd5b50610199600160a060020a03600435166024356103e5565b604080519115158252519081900360200190f35b3480156101b957600080fd5b506101c261049e565b60408051918252519081900360200190f35b3480156101e057600080fd5b50610199600160a060020a03600435811690602435166044356104a4565b34801561020a57600080fd5b506101c26105c1565b34801561021f57600080fd5b506101736004356105c7565b34801561023757600080fd5b506101c2600160a060020a036004351661065e565b34801561025857600080fd5b50610199610670565b34801561026d57600080fd5b506100e9610679565b34801561028257600080fd5b50610199600160a060020a03600435166024356106d3565b3480156102a657600080fd5b5061017361079d565b3480156102bb57600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526101739436949293602493928401919081908401838280828437509497506107c29650505050505050565b34801561031457600080fd5b506101c2600160a060020a03600435811690602435166107f2565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103b55780601f1061038a576101008083540402835291602001916103b5565b820191906000526020600020905b81548152906001019060200180831161039857829003601f168201915b505050505081565b6006546101009004600160a060020a031633146103d657fe5b6006805460ff19166001179055565b60065460009060ff16156103f557fe5b3315156103fe57fe5b81158061042c5750336000908152600460209081526040808320600160a060020a0387168452909152902054155b151561043757600080fd5b336000818152600460209081526040808320600160a060020a03881680855290835292819020869055805186815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a350600192915050565b60055481565b60065460009060ff16156104b457fe5b3315156104bd57fe5b600160a060020a0384166000908152600360205260409020548211156104e257600080fd5b600160a060020a038316600090815260036020526040902054828101101561050957600080fd5b600160a060020a038416600090815260046020908152604080832033845290915290205482111561053957600080fd5b600160a060020a03808416600081815260036020908152604080832080548801905593881680835284832080548890039055600482528483203384528252918490208054879003905583518681529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35060019392505050565b60025481565b336000908152600360205260409020548111156105e357600080fd5b336000818152600360209081526040808320805486900390558280527f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92eff805486019055805185815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350565b60036020526000908152604090205481565b60065460ff1681565b60018054604080516020600284861615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103b55780601f1061038a576101008083540402835291602001916103b5565b60065460009060ff16156106e357fe5b3315156106ec57fe5b3360009081526003602052604090205482111561070857600080fd5b600160a060020a038316600090815260036020526040902054828101101561072f57600080fd5b33600081815260036020908152604080832080548790039055600160a060020a03871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350600192915050565b6006546101009004600160a060020a031633146107b657fe5b6006805460ff19169055565b6006546101009004600160a060020a031633146107db57fe5b80516107ee90600090602084019061080f565b5050565b600460209081526000928352604080842090915290825290205481565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061085057805160ff191683800117855561087d565b8280016001018555821561087d579182015b8281111561087d578251825591602001919060010190610862565b5061088992915061088d565b5090565b6108a791905b808211156108895760008155600101610893565b905600a165627a7a72305820d00bcb788ca406de94859b8bc4bda50c3c65ca67e1217ccccee92f59a92ae5e20029" - code_ContractScenario005_deployIcoContract = "60c0604052600660808190527f54726f6e6978000000000000000000000000000000000000000000000000000060a090815261003e916000919061013c565b506040805180820190915260038082527f545258000000000000000000000000000000000000000000000000000000000060209092019182526100839160019161013c565b506006600281905560006005558054600160a860020a03191690553480156100aa57600080fd5b50604051602080610abc83398101604081815291516006805461010060a860020a031916336101000217905567016345785d8a00006005819055600160a060020a03821660008181526003602090815286822084905592855294519294909390927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a3506101d7565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785556101aa565b828001600101855582156101aa579182015b828111156101aa57825182559160200191906001019061018f565b506101b69291506101ba565b5090565b6101d491905b808211156101b657600081556001016101c0565b90565b6108d6806101e66000396000f3006080604052600436106100cf5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100d457806307da68f51461015e578063095ea7b31461017557806318160ddd146101ad57806323b872dd146101d4578063313ce567146101fe57806342966c681461021357806370a082311461022b57806375f12b211461024c57806395d89b4114610261578063a9059cbb14610276578063be9a65551461029a578063c47f0027146102af578063dd62ed3e14610308575b600080fd5b3480156100e057600080fd5b506100e961032f565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561012357818101518382015260200161010b565b50505050905090810190601f1680156101505780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561016a57600080fd5b506101736103bd565b005b34801561018157600080fd5b50610199600160a060020a03600435166024356103e5565b604080519115158252519081900360200190f35b3480156101b957600080fd5b506101c261049e565b60408051918252519081900360200190f35b3480156101e057600080fd5b50610199600160a060020a03600435811690602435166044356104a4565b34801561020a57600080fd5b506101c26105c1565b34801561021f57600080fd5b506101736004356105c7565b34801561023757600080fd5b506101c2600160a060020a036004351661065e565b34801561025857600080fd5b50610199610670565b34801561026d57600080fd5b506100e9610679565b34801561028257600080fd5b50610199600160a060020a03600435166024356106d3565b3480156102a657600080fd5b5061017361079d565b3480156102bb57600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526101739436949293602493928401919081908401838280828437509497506107c29650505050505050565b34801561031457600080fd5b506101c2600160a060020a03600435811690602435166107f2565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103b55780601f1061038a576101008083540402835291602001916103b5565b820191906000526020600020905b81548152906001019060200180831161039857829003601f168201915b505050505081565b6006546101009004600160a060020a031633146103d657fe5b6006805460ff19166001179055565b60065460009060ff16156103f557fe5b3315156103fe57fe5b81158061042c5750336000908152600460209081526040808320600160a060020a0387168452909152902054155b151561043757600080fd5b336000818152600460209081526040808320600160a060020a03881680855290835292819020869055805186815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a350600192915050565b60055481565b60065460009060ff16156104b457fe5b3315156104bd57fe5b600160a060020a0384166000908152600360205260409020548211156104e257600080fd5b600160a060020a038316600090815260036020526040902054828101101561050957600080fd5b600160a060020a038416600090815260046020908152604080832033845290915290205482111561053957600080fd5b600160a060020a03808416600081815260036020908152604080832080548801905593881680835284832080548890039055600482528483203384528252918490208054879003905583518681529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35060019392505050565b60025481565b336000908152600360205260409020548111156105e357600080fd5b336000818152600360209081526040808320805486900390558280527f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92eff805486019055805185815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350565b60036020526000908152604090205481565b60065460ff1681565b60018054604080516020600284861615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103b55780601f1061038a576101008083540402835291602001916103b5565b60065460009060ff16156106e357fe5b3315156106ec57fe5b3360009081526003602052604090205482111561070857600080fd5b600160a060020a038316600090815260036020526040902054828101101561072f57600080fd5b33600081815260036020908152604080832080548790039055600160a060020a03871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350600192915050565b6006546101009004600160a060020a031633146107b657fe5b6006805460ff19169055565b6006546101009004600160a060020a031633146107db57fe5b80516107ee90600090602084019061080f565b5050565b600460209081526000928352604080842090915290825290205481565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061085057805160ff191683800117855561087d565b8280016001018555821561087d579182015b8281111561087d578251825591602001919060010190610862565b5061088992915061088d565b5090565b6108a791905b808211156108895760008155600101610893565b905600a165627a7a72305820d00bcb788ca406de94859b8bc4bda50c3c65ca67e1217ccccee92f59a92ae5e20029" - code_ContractScenario006_deployFomo3D = "60c0604052600660808190527f464f4d4f3344000000000000000000000000000000000000000000000000000060a0908152620000409160009190620000b8565b506040805180820190915260038082527f463344000000000000000000000000000000000000000000000000000000000060209092019182526200008791600191620000b8565b5068056bc75e2d631000006002556000600855600b805460ff19169055348015620000b157600080fd5b506200015d565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620000fb57805160ff19168380011785556200012b565b828001600101855582156200012b579182015b828111156200012b5782518255916020019190600101906200010e565b50620001399291506200013d565b5090565b6200015a91905b8082111562000139576000815560010162000144565b90565b611688806200016d6000396000f3006080604052600436106101685763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166265318b811461017657806306fdde03146101a957806310d0ffdd1461023357806318160ddd1461024b578063226093731461026057806327defa1f14610278578063313ce567146102a1578063392efb52146102cc5780633ccfd60b146102e45780634b750334146102fb57806356d399e814610310578063688abbf7146103255780636b2f46321461033f57806370a08231146103545780638328b610146103755780638620410b1461038d57806389135ae9146103a25780638fea64bd146103bf578063949e8acd146103d457806395d89b41146103e9578063a8e04f34146103fe578063a9059cbb14610413578063b84c824614610437578063c47f002714610490578063e4849b32146104e9578063e9fad8ee14610501578063f088d54714610516578063fdb5a03e1461052a575b61017334600061053f565b50005b34801561018257600080fd5b50610197600160a060020a0360043516610b15565b60408051918252519081900360200190f35b3480156101b557600080fd5b506101be610b50565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101f85781810151838201526020016101e0565b50505050905090810190601f1680156102255780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023f57600080fd5b50610197600435610bde565b34801561025757600080fd5b50610197610c0e565b34801561026c57600080fd5b50610197600435610c15565b34801561028457600080fd5b5061028d610c4e565b604080519115158252519081900360200190f35b3480156102ad57600080fd5b506102b6610c57565b6040805160ff9092168252519081900360200190f35b3480156102d857600080fd5b5061028d600435610c5c565b3480156102f057600080fd5b506102f9610c71565b005b34801561030757600080fd5b50610197610d44565b34801561031c57600080fd5b50610197610d98565b34801561033157600080fd5b506101976004351515610d9e565b34801561034b57600080fd5b50610197610de1565b34801561036057600080fd5b50610197600160a060020a0360043516610de6565b34801561038157600080fd5b506102f9600435610e01565b34801561039957600080fd5b50610197610e48565b3480156103ae57600080fd5b506102f96004356024351515610e90565b3480156103cb57600080fd5b506102f9610ef2565b3480156103e057600080fd5b50610197610ef4565b3480156103f557600080fd5b506101be610f07565b34801561040a57600080fd5b506102f9610f61565b34801561041f57600080fd5b5061028d600160a060020a0360043516602435610faf565b34801561044357600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526102f99436949293602493928401919081908401838280828437509497506111699650505050505050565b34801561049c57600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526102f99436949293602493928401919081908401838280828437509497506111c29650505050505050565b3480156104f557600080fd5b506102f9600435611216565b34801561050d57600080fd5b506102f9611367565b610197600160a060020a0360043516611394565b34801561053657600080fd5b506102f96113a0565b60008060008060008060008060008a6000339050600b60009054906101000a900460ff16801561058157506801158e460913d000008261057d610de1565b0311155b1561088e57600160a060020a03811660009081526003602052604090205460ff16151560011480156105d65750600160a060020a038116600090815260076020526040902054670de0b6b3a764000090830111155b15156105e157600080fd5b600160a060020a0381166000908152600760205260409020546106049083611456565b600160a060020a03821660009081526007602052604090205533995061062b8d600561146c565b985061063889600361146c565b97506106448989611483565b96506106508d8a611483565b955061065b86611495565b9450680100000000000000008702935060008511801561068557506008546106838682611456565b115b151561069057600080fd5b600160a060020a038c16158015906106ba575089600160a060020a03168c600160a060020a031614155b80156106e05750600254600160a060020a038d1660009081526004602052604090205410155b1561072657600160a060020a038c166000908152600560205260409020546107089089611456565b600160a060020a038d16600090815260056020526040902055610741565b6107308789611456565b965068010000000000000000870293505b600060085411156107a55761075860085486611456565b600881905568010000000000000000880281151561077257fe5b6009805492909104909101905560085468010000000000000000880281151561079757fe5b0485028403840393506107ab565b60088590555b600160a060020a038a166000908152600460205260409020546107ce9086611456565b600460008c600160a060020a0316600160a060020a031681526020019081526020016000208190555083856009540203925082600660008c600160a060020a0316600160a060020a03168152602001908152602001600020600082825401925050819055508b600160a060020a03168a600160a060020a03167f022c0d992e4d873a3748436d960d5140c1f9721cf73f7ca5ec679d3d9f4fe2d58f88604051808381526020018281526020019250505060405180910390a3849a50610b05565b600b805460ff191690553399506108a68d600561146c565b98506108b389600361146c565b97506108bf8989611483565b96506108cb8d8a611483565b95506108d686611495565b9450680100000000000000008702935060008511801561090057506008546108fe8682611456565b115b151561090b57600080fd5b600160a060020a038c1615801590610935575089600160a060020a03168c600160a060020a031614155b801561095b5750600254600160a060020a038d1660009081526004602052604090205410155b156109a157600160a060020a038c166000908152600560205260409020546109839089611456565b600160a060020a038d166000908152600560205260409020556109bc565b6109ab8789611456565b965068010000000000000000870293505b60006008541115610a20576109d360085486611456565b60088190556801000000000000000088028115156109ed57fe5b60098054929091049091019055600854680100000000000000008802811515610a1257fe5b048502840384039350610a26565b60088590555b600160a060020a038a16600090815260046020526040902054610a499086611456565b600460008c600160a060020a0316600160a060020a031681526020019081526020016000208190555083856009540203925082600660008c600160a060020a0316600160a060020a03168152602001908152602001600020600082825401925050819055508b600160a060020a03168a600160a060020a03167f022c0d992e4d873a3748436d960d5140c1f9721cf73f7ca5ec679d3d9f4fe2d58f88604051808381526020018281526020019250505060405180910390a3849a505b5050505050505050505092915050565b600160a060020a0316600090815260066020908152604080832054600490925290912054600954680100000000000000009102919091030490565b6000805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610bd65780601f10610bab57610100808354040283529160200191610bd6565b820191906000526020600020905b815481529060010190602001808311610bb957829003601f168201915b505050505081565b6000808080610bee85600561146c565b9250610bfa8584611483565b9150610c0582611495565b95945050505050565b6008545b90565b6000806000806008548511151515610c2c57600080fd5b610c358561152d565b9250610c4283600561146c565b9150610c058383611483565b600b5460ff1681565b601281565b600a6020526000908152604090205460ff1681565b6000806000610c806001610d9e565b11610c8a57600080fd5b339150610c976000610d9e565b600160a060020a038316600081815260066020908152604080832080546801000000000000000087020190556005909152808220805490839055905193019350909183156108fc0291849190818181858888f19350505050158015610d00573d6000803e3d6000fd5b50604080518281529051600160a060020a038416917fccad973dcd043c7d680389db4378bd6b9775db7124092e9e0422c9e46d7985dc919081900360200190a25050565b60008060008060085460001415610d62576414f46b04009350610d92565b610d73670de0b6b3a764000061152d565b9250610d8083600561146c565b9150610d8c8383611483565b90508093505b50505090565b60025481565b60003382610db457610daf81610b15565b610dd8565b600160a060020a038116600090815260056020526040902054610dd682610b15565b015b91505b50919050565b303190565b600160a060020a031660009081526004602052604090205490565b604080516c010000000000000000000000003390810282528251918290036014019091206000908152600a602052919091205460ff161515610e4257600080fd5b50600255565b60008060008060085460001415610e665764199c82cc009350610d92565b610e77670de0b6b3a764000061152d565b9250610e8483600561146c565b9150610d8c8383611456565b604080516c010000000000000000000000003390810282528251918290036014019091206000908152600a602052919091205460ff161515610ed157600080fd5b506000918252600a6020526040909120805460ff1916911515919091179055565b565b600033610f0081610de6565b91505b5090565b60018054604080516020600284861615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610bd65780601f10610bab57610100808354040283529160200191610bd6565b604080516c010000000000000000000000003390810282528251918290036014019091206000908152600a602052919091205460ff161515610fa257600080fd5b50600b805460ff19169055565b600080600080600080610fc0610ef4565b11610fca57600080fd5b600b5433945060ff16158015610ff85750600160a060020a0384166000908152600460205260409020548611155b151561100357600080fd5b600061100f6001610d9e565b111561101d5761101d610c71565b61102886600561146c565b92506110348684611483565b915061103f8361152d565b905061104d60085484611483565b600855600160a060020a0384166000908152600460205260409020546110739087611483565b600160a060020a0380861660009081526004602052604080822093909355908916815220546110a29083611456565b600160a060020a0388811660008181526004602090815260408083209590955560098054948a16835260069091528482208054948c02909403909355825491815292909220805492850290920190915554600854611116919068010000000000000000840281151561111057fe5b04611456565b600955604080518381529051600160a060020a03808a1692908716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35060019695505050505050565b604080516c010000000000000000000000003390810282528251918290036014019091206000908152600a602052919091205460ff1615156111aa57600080fd5b81516111bd9060019060208501906115ce565b505050565b604080516c010000000000000000000000003390810282528251918290036014019091206000908152600a602052919091205460ff16151561120357600080fd5b81516111bd9060009060208501906115ce565b6000806000806000806000611229610ef4565b1161123357600080fd5b3360008181526004602052604090205490965087111561125257600080fd5b86945061125e8561152d565b935061126b84600561146c565b92506112778484611483565b915061128560085486611483565b600855600160a060020a0386166000908152600460205260409020546112ab9086611483565b600160a060020a0387166000908152600460209081526040808320939093556009546006909152918120805492880268010000000000000000860201928390039055600854919250101561131b5761131760095460085468010000000000000000860281151561111057fe5b6009555b60408051868152602081018490528151600160a060020a038916927fc4823739c5787d2ca17e404aa47d5569ae71dfb49cbf21b3f6152ed238a31139928290030190a250505050505050565b33600081815260046020526040812054908111156113885761138881611216565b611390610c71565b5050565b6000610ddb348361053f565b6000806000806113b06001610d9e565b116113ba57600080fd5b6113c46000610d9e565b3360008181526006602090815260408083208054680100000000000000008702019055600590915281208054908290559092019450925061140690849061053f565b905081600160a060020a03167fbe339fc14b041c2b0e0f3dd2cd325d0c3668b78378001e53160eab36153264588483604051808381526020018281526020019250505060405180910390a2505050565b60008282018381101561146557fe5b9392505050565b600080828481151561147a57fe5b04949350505050565b60008282111561148f57fe5b50900390565b6008546000906c01431e0fae6d7217caa00000009082906402540be40061151a611514730380d4bd8a8678c1bb542c80deb4800000000000880268056bc75e2d631000006002860a02017005e0a1fd2712875988becaad0000000000850201780197d4df19d605767337e9f14d3eec8920e40000000000000001611599565b85611483565b81151561152357fe5b0403949350505050565b600854600090670de0b6b3a76400008381019181019083906115866414f46b04008285046402540be40002018702600283670de0b6b3a763ffff1982890a8b900301046402540be4000281151561158057fe5b04611483565b81151561158f57fe5b0495945050505050565b80600260018201045b81811015610ddb5780915060028182858115156115bb57fe5b04018115156115c657fe5b0490506115a2565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061160f57805160ff191683800117855561163c565b8280016001018555821561163c579182015b8281111561163c578251825591602001919060010190611621565b50610f0392610c129250905b80821115610f0357600081556001016116485600a165627a7a723058202986f1ef7924e33e9f5613300f260c5fd9f05700de3217343d70f3a5fea5f76d0029" - code_ContractScenario007_deployErc721CardMigration = "6000805460a060020a60ff021916905560e0604052602360808190527f68747470733a2f2f6170692e676f6473756e636861696e65642e636f6d2f636160a09081527f72642f000000000000000000000000000000000000000000000000000000000060c0526200007491601091906200023e565b503480156200008257600080fd5b5060405160208062004212833981016040525160008054600160a060020a03191633179055620000db7f01ffc9a700000000000000000000000000000000000000000000000000000000640100000000620001d1810204565b6200010f7f80ac58cd00000000000000000000000000000000000000000000000000000000640100000000620001d1810204565b620001437f4f558e7900000000000000000000000000000000000000000000000000000000640100000000620001d1810204565b620001777f780e9d6300000000000000000000000000000000000000000000000000000000640100000000620001d1810204565b620001ab7f5b5e139f00000000000000000000000000000000000000000000000000000000640100000000620001d1810204565b60158054600160a060020a031916600160a060020a0392909216919091179055620002e3565b7fffffffff0000000000000000000000000000000000000000000000000000000080821614156200020157600080fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152600c60205260409020805460ff19166001179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200028157805160ff1916838001178555620002b1565b82800160010185558215620002b1579182015b82811115620002b157825182559160200191906001019062000294565b50620002bf929150620002c3565b5090565b620002e091905b80821115620002bf5760008155600101620002ca565b90565b613f1f80620002f36000396000f3006080604052600436106103425763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166301ffc9a7811461034757806305c4af9d1461037d57806306fdde031461040c578063081812fc14610496578063095ea7b3146104ca5780630bbe0ee3146104f05780630c340a241461055b5780630e359f1614610570578063100cdd911461058857806318160ddd146105dd57806319fa8f50146106045780631fa24aa71461063657806323b872dd1461065157806324a96d701461067b5780632f745c59146106c5578063396ed600146106e95780633cb4ff3c146107015780633f4ba83a1461071657806342842e0e1461072b57806342966c6814610755578063454b06081461076d5780634cc90115146107855780634f558e791461079d5780634f6ccce7146107b55780634fb31a6a146107cd578063524773ce1461080d5780635bd9d9a5146108225780635c975abb1461083d5780635dcbd8bb146108525780636352211e1461087b57806367025dcf1461089357806370a08231146108e95780637a8b9b851461090a578063818d4b5d14610925578063821f830f146109495780638456cb591461096a578063850e37601461097f5780638dc10768146109b15780638e7e879f146109ea5780639188d31214610a3f578063943b82f114610a5757806395d89b4114610a97578063986e82f214610aac578063a22cb46514610ac8578063a3f4df7e14610aee578063a5487e5114610b03578063a71aec7314610b1b578063a9059cbb14610b37578063ad94d90114610b4e578063b5cab1ce14610bb1578063b84c139214610bc6578063b88d4fde14610bde578063bc734f0f14610c4d578063bcb3962114610c62578063c42cf53514610c77578063c87b56dd14610c98578063c968aab314610cb0578063caa1916814610ccb578063ce9fdb7014610ced578063ced28d7714610d2c578063d7643e1814610d78578063d80f862114610d8d578063dfb6a75f14610da5578063e3c7336b14610dea578063e7cf548c14611007578063e985e9c51461101c578063eeffbe4e14611043578063f03034521461105b578063f5f23b52146110be578063f76f8d78146110d9578063fb36eba1146110ee575b600080fd5b34801561035357600080fd5b50610369600160e060020a03196004351661111c565b604080519115158252519081900360200190f35b34801561038957600080fd5b5061039961ffff6004351661113b565b604080518a1515815260ff808b166020830152898116928201929092529087166060820152608081018660048111156103ce57fe5b60ff90811682529586166020820152938516604080860191909152928516606085015250909216608082015290519081900360a00195509350505050f35b34801561041857600080fd5b50610421611296565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561045b578181015183820152602001610443565b50505050905090810190601f1680156104885780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104a257600080fd5b506104ae6004356112ce565b60408051600160a060020a039092168252519081900360200190f35b3480156104d657600080fd5b506104ee600160a060020a03600435166024356112e9565b005b3480156104fc57600080fd5b5060408051602060046044358181013583810280860185019096528085526104ee958335600160a060020a0390811696602480359092169636969560649592949301928291850190849080828437509497506113299650505050505050565b34801561056757600080fd5b506104ae611365565b34801561057c57600080fd5b50610369600435611374565b34801561059457600080fd5b50604080516020600480358082013583810280860185019096528085526104ee953695939460249493850192918291850190849080828437509497506113899650505050505050565b3480156105e957600080fd5b506105f26113bd565b60408051918252519081900360200190f35b34801561061057600080fd5b506106196113c3565b60408051600160e060020a03199092168252519081900360200190f35b34801561064257600080fd5b506104ee60ff600435166113e7565b34801561065d57600080fd5b506104ee600160a060020a036004358116906024351660443561143c565b34801561068757600080fd5b506106ae61ffff6004351660ff602435811690604435811690606435166084351515611469565b6040805161ffff9092168252519081900360200190f35b3480156106d157600080fd5b506105f2600160a060020a03600435166024356114ff565b3480156106f557600080fd5b506106ae60043561156f565b34801561070d57600080fd5b506105f26115a5565b34801561072257600080fd5b506104ee6115b8565b34801561073757600080fd5b506104ee600160a060020a036004358116906024351660443561162e565b34801561076157600080fd5b506104ee600435611660565b34801561077957600080fd5b506104ee600435611691565b34801561079157600080fd5b506106ae60043561180c565b3480156107a957600080fd5b5061036960043561181a565b3480156107c157600080fd5b506105f2600435611837565b3480156107d957600080fd5b506104ee61ffff6004351660ff60243581169060443581169060643581169060843581169060a43581169060c43516611850565b34801561081957600080fd5b506105f2611b03565b34801561082e57600080fd5b5061036960ff60043516611b09565b34801561084957600080fd5b50610369611b1e565b34801561085e57600080fd5b506104ee61ffff6004351667ffffffffffffffff60243516611b2e565b34801561088757600080fd5b506104ae600435611c0c565b6040805160206004602480358281013584810280870186019097528086526104ee968435600160a060020a031696369660449591949091019291829185019084908082843750949750611c369650505050505050565b3480156108f557600080fd5b506105f2600160a060020a0360043516611c6b565b34801561091657600080fd5b5061036960ff60043516611c86565b34801561093157600080fd5b50610369600160a060020a0360043516602435611c9b565b34801561095557600080fd5b506104ee600160a060020a0360043516611cc1565b34801561097657600080fd5b506104ee611d37565b34801561098b57600080fd5b5061099b61ffff60043516611db2565b6040805160ff9092168252519081900360200190f35b3480156109bd57600080fd5b506109c9600435611dc0565b6040805161ffff938416815291909216602082015281519081900390910190f35b3480156109f657600080fd5b50604080516020600480358082013583810280860185019096528085526104ee95369593946024949385019291829185019084908082843750949750611ded9650505050505050565b348015610a4b57600080fd5b506109c9600435611e21565b348015610a6357600080fd5b50610a7361ffff60043516611e75565b6040805167ffffffffffffffff909316835290151560208301528051918290030190f35b348015610aa357600080fd5b50610421611ecc565b348015610ab857600080fd5b50610a7361ffff60043516611f03565b348015610ad457600080fd5b506104ee600160a060020a03600435166024351515611f30565b348015610afa57600080fd5b50610421611fb4565b348015610b0f57600080fd5b506106ae600435611feb565b348015610b2757600080fd5b5061036961ffff60043516611ff9565b6104ee600160a060020a0360043516602435612029565b348015610b5a57600080fd5b50604080516020600460248035828101358481028087018601909752808652610369968435600160a060020a0316963696604495919490910192918291850190849080828437509497506120849650505050505050565b348015610bbd57600080fd5b506104216120e8565b348015610bd257600080fd5b506104ae600435612176565b348015610bea57600080fd5b50604080516020601f6064356004818101359283018490048402850184019095528184526104ee94600160a060020a03813581169560248035909216956044359536956084940191819084018382808284375094975061219e9650505050505050565b348015610c5957600080fd5b506104ee6121d6565b348015610c6e57600080fd5b5061099b61225e565b348015610c8357600080fd5b506104ee600160a060020a0360043516612267565b348015610ca457600080fd5b506104216004356122ad565b348015610cbc57600080fd5b506104ee60ff6004351661234f565b348015610cd757600080fd5b506106ae60ff6004351661ffff602435166123a0565b348015610cf957600080fd5b506106ae61ffff6004351660ff60243581169060443581169060643581169060843581169060a4351660c4351515612534565b348015610d3857600080fd5b506106ae61ffff6004351660ff60243581169060443581169060643581169060843581169060a43581169060c43581169060e435166101043515156125cc565b348015610d8457600080fd5b506106ae61266c565b348015610d9957600080fd5b506106ae60043561267b565b348015610db157600080fd5b506106ae61ffff6004351660ff60243581169060443581169060643581169060843581169060a43581169060c4351660e4351515612689565b348015610df657600080fd5b50604080516020600480358082013583810280860185019096528085526106ae95369593946024949385019291829185019084908082843750506040805187358901803560208181028481018201909552818452989b9a998901989297509082019550935083925085019084908082843750506040805187358901803560208181028481018201909552818452989b9a998901989297509082019550935083925085019084908082843750506040805187358901803560208181028481018201909552818452989b9a998901989297509082019550935083925085019084908082843750506040805187358901803560208181028481018201909552818452989b9a998901989297509082019550935083925085019084908082843750506040805187358901803560208181028481018201909552818452989b9a998901989297509082019550935083925085019084908082843750506040805187358901803560208181028481018201909552818452989b9a998901989297509082019550935083925085019084908082843750506040805187358901803560208181028481018201909552818452989b9a998901989297509082019550935083925085019084908082843750506040805187358901803560208181028481018201909552818452989b9a9989019892975090820195509350839250850190849080828437509497506127269650505050505050565b34801561101357600080fd5b506105f26128b5565b34801561102857600080fd5b50610369600160a060020a03600435811690602435166128bb565b34801561104f57600080fd5b506106ae6004356128e9565b34801561106757600080fd5b506040805160206004602480358281013584810280870186019097528086526104ee968435600160a060020a0316963696604495919490910192918291850190849080828437509497506128f79650505050505050565b3480156110ca57600080fd5b506104ee60ff6004351661292c565b3480156110e557600080fd5b50610421612961565b3480156110fa57600080fd5b506105f2600160a060020a036004351661ffff60243581169060443516612998565b600160e060020a0319166000908152600c602052604090205460ff1690565b6000806000806000806000806000611151613df2565b61ffff8b16600090815260066020908152604091829020825161012081018452815460ff8082161515835261010082048116948301949094526201000081048416948201949094526301000000840483166060820152929091608084019164010000000090041660048111156111c357fe5b60048111156111ce57fe5b81526020016000820160059054906101000a900460ff1660ff1660ff1681526020016000820160069054906101000a900460ff1660ff1660ff1681526020016000820160079054906101000a900460ff1660ff1660ff1681526020016000820160089054906101000a900460ff1660ff1660ff16815250509050806000015181602001518260400151836060015184608001518560a001518660c001518760e00151886101000151995099509950995099509950995099509950509193959799909294969850565b60408051808201909152600e81527f476f647320556e636861696e656400000000000000000000000000000000000060208201525b90565b6000908152600e6020526040902054600160a060020a031690565b6113106001828154811015156112fb57fe5b60009182526020909120015461ffff16611ff9565b151561131b57600080fd5b6113258282612b50565b5050565b60005b815181101561135f576113578484848481518110151561134857fe5b9060200190602002015161143c565b60010161132c565b50505050565b600054600160a060020a031681565b60166020526000908152604090205460ff1681565b60005b8151811015611325576113b582828151811015156113a657fe5b90602001906020020151611660565b60010161138c565b60015490565b7f01ffc9a70000000000000000000000000000000000000000000000000000000081565b600054600160a060020a031633146113fe57600080fd5b60ff80821660009081526003602052604090205416151561141e57600080fd5b60ff166000908152600460205260409020805460ff19166001179055565b61144e6001828154811015156112fb57fe5b151561145957600080fd5b611464838383612c06565b505050565b6000611473613df2565b600054600160a060020a0316331461148a57600080fd5b6040805161012081018252600180825260ff808a16602084015260055416928201929092526060810191909152608081018660048111156114c757fe5b815260ff861660208201526000604082018190526060820181905260809091015290506114f5878285612c99565b5095945050505050565b600061150a83611c6b565b821061151557600080fd5b600160a060020a038316600090815260116020526040902080548390811061153957fe5b90600052602060002090600691828204019190066005029054906101000a900464ffffffffff1664ffffffffff16905092915050565b600b80548290811061157d57fe5b9060005260206000209060109182820401919006600202915054906101000a900461ffff1681565b60006013546115b26113bd565b03905090565b600054600160a060020a031633146115cf57600080fd5b60005460a060020a900460ff1615156115e757600080fd5b6000805474ff0000000000000000000000000000000000000000191681556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b339190a1565b80611639338261312c565b151561164457600080fd5b61135f848484602060405190810160405280600081525061219e565b803361166b82611c0c565b600160a060020a03161461167e57600080fd5b601380546001019055611325338361318b565b6000818152601660205260408120548190819060ff16156116b157600080fd5b6000848152601660209081526040808320805460ff1916600117905560155481517f6352211e000000000000000000000000000000000000000000000000000000008152600481018990529151600160a060020a0390911693636352211e93602480850194919392918390030190829087803b15801561173057600080fd5b505af1158015611744573d6000803e3d6000fd5b505050506040513d602081101561175a57600080fd5b5051601554604080517f9188d312000000000000000000000000000000000000000000000000000000008152600481018890528151939650600160a060020a0390921692639188d3129260248082019392918290030181600087803b1580156117c257600080fd5b505af11580156117d6573d6000803e3d6000fd5b505050506040513d60408110156117ec57600080fd5b50805160209091015190925090506118058383836131c9565b5050505050565b600780548290811061157d57fe5b6000908152600d6020526040902054600160a060020a0316151590565b60006118416113bd565b821061184c57600080fd5b5090565b611858613df2565b600054600160a060020a0316331461186f57600080fd5b61ffff8816600090815260066020908152604091829020825161012081018452815460ff8082161515835261010082048116948301949094526201000081048416948201949094526301000000840483166060820152929091608084019164010000000090041660048111156118e157fe5b60048111156118ec57fe5b8152905460ff650100000000008204811660208085019190915266010000000000008304821660408086019190915267010000000000000084048316606086015268010000000000000000909304821660809094019390935283820151811660009081526003909352912054919250161561196657600080fd5b610120604051908101604052806001151581526020018860ff168152602001826040015160ff1681526020018760ff168152602001826080015160048111156119ab57fe5b815260ff87811660208084019190915287821660408085019190915287831660608086019190915287841660809586015261ffff8e166000908152600684528290208651815494880151938801519288015160ff199095169015151761ff001916610100938616939093029290921762ff0000191662010000918516919091021763ff00000019166301000000929093169190910291909117808255918301519091829064ff000000001916640100000000836004811115611a6957fe5b021790555060a0820151815460c084015160e08501516101009095015165ff0000000000199092166501000000000060ff948516021766ff00000000000019166601000000000000918416919091021767ff000000000000001916670100000000000000948316949094029390931768ff000000000000000019166801000000000000000091909316029190911790555050505050505050565b60135481565b60046020526000908152604090205460ff1681565b60005460a060020a900460ff1681565b611b36613e3e565b600054600160a060020a03163314611b4d57600080fd5b5061ffff821660009081526002602090815260409182902082518084019093525467ffffffffffffffff8116835268010000000000000000900460ff1615801591830191909152611b9d57600080fd5b5060408051808201825267ffffffffffffffff92831681526001602080830191825261ffff90951660009081526002909552919093209251835491511515680100000000000000000268ff0000000000000000199190931667ffffffffffffffff199092169190911716179055565b6000818152600d6020526040812054600160a060020a0316801515611c3057600080fd5b92915050565b60005b815181101561146457611c63838383815181101515611c5457fe5b90602001906020020151612029565b600101611c39565b600160a060020a031660009081526011602052604090205490565b60036020526000908152604090205460ff1681565b600082600160a060020a0316611cb083611c0c565b600160a060020a0316149392505050565b600054600160a060020a03163314611cd857600080fd5b601480546001810182556000919091527fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec01805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600054600160a060020a03163314611d4e57600080fd5b60005460a060020a900460ff1615611d6557600080fd5b6000805474ff0000000000000000000000000000000000000000191660a060020a1781556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff6259190a1565b6103e861ffff919091160490565b6001805482908110611dce57fe5b60009182526020909120015461ffff8082169250620100009091041682565b60005b815181101561132557611e198282815181101515611e0a57fe5b90602001906020020151611691565b600101611df0565b600080611e2c613e3e565b6001805485908110611e3a57fe5b60009182526020918290206040805180820190915291015461ffff808216808452620100009092041691909201819052909590945092505050565b600080611e80613e3e565b50505061ffff1660009081526002602090815260409182902082518084019093525467ffffffffffffffff81168084526801000000000000000090910460ff1615159290910182905291565b60408051808201909152600481527f474f445300000000000000000000000000000000000000000000000000000000602082015290565b60026020526000908152604090205467ffffffffffffffff81169068010000000000000000900460ff1682565b600160a060020a038216331415611f4657600080fd5b336000818152600f60209081526040808320600160a060020a03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b60408051808201909152600e81527f476f647320556e636861696e6564000000000000000000000000000000000000602082015281565b600a80548290811061157d57fe5b61ffff1660009081526006602090815260408083205462010000900460ff90811684526003909252909120541690565b803361203482611c0c565b600160a060020a03161461204757600080fd5b6120596001838154811015156112fb57fe5b151561206457600080fd5b600160a060020a038316151561207957600080fd5b6114643384846132ae565b6000806000835111151561209757600080fd5b5060005b82518110156120dc576120c58484838151811015156120b657fe5b90602001906020020151611c9b565b15156120d457600091506120e1565b60010161209b565b600191505b5092915050565b6010805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561216e5780601f106121435761010080835404028352916020019161216e565b820191906000526020600020905b81548152906001019060200180831161215157829003601f168201915b505050505081565b601480548290811061218457fe5b600091825260209091200154600160a060020a0316905081565b816121a9338261312c565b15156121b457600080fd5b6121bf85858561143c565b6121cb85858585613300565b151561180557600080fd5b600054600160a060020a031633146121ed57600080fd5b60055460ff908116111561220057600080fd5b6005805460ff8082166001011660ff199091161790556000612223600782613e55565b506000612231600882613e55565b50600061223f600982613e55565b50600061224d600a82613e55565b50600061225b600b82613e55565b50565b60055460ff1681565b600054600160a060020a0316331461227e57600080fd5b6000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6010805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152606093611c30939192909183018282801561233c5780601f106123115761010080835404028352916020019161233c565b820191906000526020600020905b81548152906001019060200180831161231f57829003601f168201915b505050505061234a8461346d565b613560565b600054600160a060020a0316331461236657600080fd5b60ff808216600090815260046020526040902054161561238557600080fd5b60ff166000908152600360205260409020805460ff19169055565b600080808080808760048111156123b357fe5b141561240357600b805461ffff88168115156123cb57fe5b068154811015156123d857fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16945061252a565b600187600481111561241157fe5b141561242957600a805461ffff88168115156123cb57fe5b600287600481111561243757fe5b141561244f576009805461ffff88168115156123cb57fe5b600387600481111561245d57fe5b1415612475576008805461ffff88168115156123cb57fe5b600487600481111561248357fe5b1415610342575060005b600754811015612518576007805461ffff881683018115156124ab57fe5b068154811015156124b857fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1693506124e784611e75565b9093509150818015612503575060008367ffffffffffffffff16115b156125105783945061252a565b60010161248d565b6008805461ffff88168115156123cb57fe5b5050505092915050565b600061253e613df2565b600054600160a060020a0316331461255557600080fd5b60408051610120810182526001815260ff808b1660208301526005541691810191909152600360608201526080810188600481111561259057fe5b815260ff8089166020830152878116604083015286166060820152600060809091015290506125c0898285612c99565b50979650505050505050565b60006125d6613df2565b600054600160a060020a031633146125ed57600080fd5b60408051610120810182526001815260ff808d1660208301526005548116928201929092529086166060820152608081018a600481111561262a57fe5b81526020018960ff1681526020018860ff1681526020018760ff1681526020018560ff16815250905061265e8b8285612c99565b509998505050505050505050565b600554610100900461ffff1681565b600980548290811061157d57fe5b6000612693613df2565b600054600160a060020a031633146126aa57600080fd5b60408051610120810182526001815260ff808c166020830152600554169181019190915260026060820152608081018960048111156126e557fe5b81526020018860ff1681526020018760ff1681526020018660ff1681526020018560ff1681525090506127198a8285612c99565b5098975050505050505050565b600080612731613df2565b600054600160a060020a0316331461274857600080fd5b600091505b8b518210156128a657610120604051908101604052806001151581526020018c8481518110151561277a57fe5b602090810290910181015160ff9081168352600554169082015287516040909101908890859081106127a857fe5b9060200190602002015160ff1681526020018b848151811015156127c857fe5b9060200190602002015160048111156127dd57fe5b81526020018a848151811015156127f057fe5b9060200190602002015160ff168152602001898481518110151561281057fe5b9060200190602002015160ff168152602001888481518110151561283057fe5b9060200190602002015160ff168152602001868481518110151561285057fe5b9060200190602002015160ff16815250905061289b8c8381518110151561287357fe5b9060200190602002015182868581518110151561288c57fe5b90602001906020020151612c99565b60019091019061274d565b50509998505050505050505050565b60135490565b600160a060020a039182166000908152600f6020908152604080832093909416825291909152205460ff1690565b600880548290811061157d57fe5b60005b81518110156114645761292483838381518110151561291557fe5b906020019060200201516112e9565b6001016128fa565b600054600160a060020a0316331461294357600080fd5b60ff166000908152600360205260409020805460ff19166001179055565b60408051808201909152600481527f474f445300000000000000000000000000000000000000000000000000000000602082015281565b60006129a2613df2565b60008054819060a060020a900460ff16156129bc57600080fd5b6129c461359c565b15156129cf57600080fd5b61ffff8616600090815260066020908152604091829020825161012081018452815460ff808216151583526101008204811694830194909452620100008104841694820194909452630100000084048316606082015292909160808401916401000000009004166004811115612a4157fe5b6004811115612a4c57fe5b8152905460ff6501000000000082048116602084015266010000000000008204811660408085019190915267010000000000000083048216606085015268010000000000000000909204811660809093019290925260055490830151929550918116911614612aba57600080fd5b600483608001516004811115612acc57fe5b1415612b3a57612adb86611e75565b9092509050801580612af7575060008267ffffffffffffffff16115b1515612b0257600080fd5b61ffff86166000908152600260205260409020805467ffffffffffffffff19811667ffffffffffffffff918216600019019091161790555b612b458787876131c9565b979650505050505050565b6000612b5b82611c0c565b9050600160a060020a038381169082161415612b7657600080fd5b33600160a060020a0382161480612b925750612b9281336128bb565b1515612b9d57600080fd5b6000828152600e6020526040808220805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b80612c11338261312c565b1515612c1c57600080fd5b600160a060020a0384161515612c3157600080fd5b600160a060020a0383161515612c4657600080fd5b612c5084836135ed565b612c5a848361365c565b612c6483836138bd565b8183600160a060020a031685600160a060020a0316600080516020613ed483398151915260405160405180910390a450505050565b61ffff831660009081526006602052604081205460ff1615612cba57600080fd5b6001835261ffff8416600090815260066020908152604091829020855181549287015193870151606088015160ff199094169115159190911761ff00191661010060ff958616021762ff0000191662010000918516919091021763ff000000191663010000009390921692909202178082556080850151859291829064ff000000001916640100000000836004811115612d5057fe5b021790555060a08201518160000160056101000a81548160ff021916908360ff16021790555060c08201518160000160066101000a81548160ff021916908360ff16021790555060e08201518160000160076101000a81548160ff021916908360ff1602179055506101008201518160000160086101000a81548160ff021916908360ff1602179055509050506005600181819054906101000a900461ffff168092919060010191906101000a81548161ffff021916908361ffff160217905550507f2f7e8f79713fd202353aaa4d413bb73a3bc66d59a540f646415fd9acee7e59c684600560009054906101000a900460ff16856020015186608001518760a001518860c001518960e001518a606001518b61010001518b604051808b61ffff1661ffff1681526020018a60ff1660ff1681526020018960ff1660ff168152602001886004811115612e9f57fe5b60ff90811682529788166020820152958716604080880191909152948716606087015250918516608085015290931660a083015291151560c082015290519081900360e001945092505050a1811561135f575060808201516000816004811115612f0557fe5b1415612f6857600b80546001810182556000919091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db960108204018054600f9092166002026101000a61ffff818102199093169287160291909117905561135f565b6001816004811115612f7657fe5b1415612fd957600a80546001810182556000919091527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a860108204018054600f9092166002026101000a61ffff818102199093169287160291909117905561135f565b6002816004811115612fe757fe5b141561304a57600980546001810182556000919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af60108204018054600f9092166002026101000a61ffff818102199093169287160291909117905561135f565b600381600481111561305857fe5b14156130bb57600880546001810182556000919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee360108204018054600f9092166002026101000a61ffff818102199093169287160291909117905561135f565b60048160048111156130c957fe5b141561034257600780546001810182556000919091527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860108204018054600f9092166002026101000a61ffff818102199093169287160291909117905561135f565b60008061313883611c0c565b905080600160a060020a031684600160a060020a03161480613173575083600160a060020a0316613168846112ce565b600160a060020a0316145b80613183575061318381856128bb565b949350505050565b61319582826135ed565b61319f828261365c565b6040518190600090600160a060020a03851690600080516020613ed4833981519152908390a45050565b60006131d3613e3e565b506040805180820190915261ffff80851682528381166020830190815260018054808201825560009190915283517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf68201805493518516620100000263ffff0000199290951661ffff199094169390931716929092179055613255868261398e565b6040805161ffff808816825286166020820152600160a060020a03881681830152905182917fe8a3345b7ca502cc541c08a705987fa4c03d9f59c0427175387a64cbd8f46594919081900360600190a295945050505050565b6132b883826135ed565b6132c2838261365c565b6132cc82826138bd565b8082600160a060020a031684600160a060020a0316600080516020613ed483398151915260405160405180910390a4505050565b60008061331585600160a060020a03166139d7565b15156133245760019150613464565b6040517f150b7a020000000000000000000000000000000000000000000000000000000081523360048201818152600160a060020a03898116602485015260448401889052608060648501908152875160848601528751918a169463150b7a0294938c938b938b93909160a490910190602085019080838360005b838110156133b757818101518382015260200161339f565b50505050905090810190601f1680156133e45780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561340657600080fd5b505af115801561341a573d6000803e3d6000fd5b505050506040513d602081101561343057600080fd5b5051600160e060020a031981167f150b7a020000000000000000000000000000000000000000000000000000000014925090505b50949350505050565b606060008082818515156134b65760408051808201909152600181527f300000000000000000000000000000000000000000000000000000000000000060208201529450613557565b8593505b83156134d157600190920191600a840493506134ba565b826040519080825280601f01601f1916602001820160405280156134ff578160200160208202803883390190505b5091505060001982015b851561355357815160001982019160f860020a6030600a8a06010291849190811061353057fe5b906020010190600160f860020a031916908160001a905350600a86049550613509565b8194505b50505050919050565b6040805160208181018352600080835283518083018552818152845192830190945281526060926135959286928692906139df565b9392505050565b6000805b6014548110156135e55760148054829081106135b857fe5b600091825260209091200154600160a060020a03163314156135dd576001915061184c565b6001016135a0565b600091505090565b81600160a060020a031661360082611c0c565b600160a060020a03161461361357600080fd5b6000818152600e6020526040902054600160a060020a031615611325576000908152600e60205260409020805473ffffffffffffffffffffffffffffffffffffffff1916905550565b600080600061366b8585613c40565b601280548590811061367957fe5b60009182526020808320600883040154600160a060020a0389168452601190915260409092205460079091166004026101000a90910463ffffffff90811694506136c79190600190613c9216565b600160a060020a0386166000908152601160205260409020805491935090839081106136ef57fe5b90600052602060002090600691828204019190066005029054906101000a900464ffffffffff169050806011600087600160a060020a0316600160a060020a031681526020019081526020016000208463ffffffff1681548110151561375157fe5b90600052602060002090600691828204019190066005026101000a81548164ffffffffff021916908364ffffffffff16021790555060006011600087600160a060020a0316600160a060020a03168152602001908152602001600020838154811015156137ba57fe5b90600052602060002090600691828204019190066005026101000a81548164ffffffffff021916908364ffffffffff1602179055506011600086600160a060020a0316600160a060020a031681526020019081526020016000208054809190600190036138279190613e89565b50600060128581548110151561383957fe5b90600052602060002090600891828204019190066004026101000a81548163ffffffff021916908363ffffffff1602179055508260128264ffffffffff1681548110151561388357fe5b90600052602060002090600891828204019190066004026101000a81548163ffffffff021916908363ffffffff1602179055505050505050565b60006138c98383613ca4565b50600160a060020a03821660009081526011602052604090205463ffffffff811681146138f557600080fd5b600160a060020a038316600090815260116020908152604082208054600181018255908352912060068083049091018054919092066005026101000a64ffffffffff8181021990921691851602179055601280548291908490811061395657fe5b90600052602060002090600891828204019190066004026101000a81548163ffffffff021916908363ffffffff160217905550505050565b600160a060020a03821615156139a357600080fd5b6139ad8282613d01565b6040518190600160a060020a03841690600090600080516020613ed4833981519152908290a45050565b6000903b1190565b6060806060806060806060806000808e98508d97508c96508b95508a94508451865188518a518c51010101016040519080825280601f01601f191660200182016040528015613a38578160200160208202803883390190505b50935083925060009150600090505b8851811015613aa5578881815181101515613a5e57fe5b90602001015160f860020a900460f860020a028383806001019450815181101515613a8557fe5b906020010190600160f860020a031916908160001a905350600101613a47565b5060005b8751811015613b07578781815181101515613ac057fe5b90602001015160f860020a900460f860020a028383806001019450815181101515613ae757fe5b906020010190600160f860020a031916908160001a905350600101613aa9565b5060005b8651811015613b69578681815181101515613b2257fe5b90602001015160f860020a900460f860020a028383806001019450815181101515613b4957fe5b906020010190600160f860020a031916908160001a905350600101613b0b565b5060005b8551811015613bcb578581815181101515613b8457fe5b90602001015160f860020a900460f860020a028383806001019450815181101515613bab57fe5b906020010190600160f860020a031916908160001a905350600101613b6d565b5060005b8451811015613c2d578481815181101515613be657fe5b90602001015160f860020a900460f860020a028383806001019450815181101515613c0d57fe5b906020010190600160f860020a031916908160001a905350600101613bcf565b50909d9c50505050505050505050505050565b81600160a060020a0316613c5382611c0c565b600160a060020a031614613c6657600080fd5b6000908152600d60205260409020805473ffffffffffffffffffffffffffffffffffffffff1916905550565b600082821115613c9e57fe5b50900390565b6000818152600d6020526040902054600160a060020a031615613cc657600080fd5b6000908152600d60205260409020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6000613d0d8383613ca4565b50600160a060020a03821660009081526011602052604090205463ffffffff81168114613d3957600080fd5b600160a060020a039290921660009081526011602090815260408220805460018082018355918452918320600680840490910180549190930660050261010090810a64ffffffffff818102199093169690921691909102949094179091556012805491820181559091527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec344460088204018054600790921660040290920a63ffffffff818102199092169190931692909202919091179055565b6040805161012081018252600080825260208201819052918101829052606081018290529060808201908152600060208201819052604082018190526060820181905260809091015290565b604080518082019091526000808252602082015290565b81548183558181111561146457600f016010900481600f016010900483600052602060002091820191016114649190613eb9565b81548183558181111561146457600501600690048160050160069004836000526020600020918201910161146491905b6112cb91905b8082111561184c5760008155600101613ebf5600ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa165627a7a7230582010fa10dfd0372688e0f7a010b360af415423fe495c99c201f4e1bfab3b1c44210029000000000000000000000000512fbd15bde6570ff09e4438af27ede604024515" - code_ContractScenario008_deployErc721CryptoKitties = "606060409081526002805460a060020a60ff02191690556101c090519081016040908152603c82526078602083015261012c9082015261025860608201526107086080820152610e1060a0820152611c2060c082015261384060e082015261708061010082015261e100610120820152620151806101408201526202a3006101608201526205460061018082015262093a806101a0820152620000a790600390600e620004e4565b50600f60055566071afd498d0000600e553415620000c457600080fd5b6002805460008054600160a060020a033316600160a060020a03199182168117835560a060020a60ff02199093167401000000000000000000000000000000000000000017169091179091556200012f90808060001981640100000000620028f06200013682021704565b5062000649565b6000806200014362000587565b600063ffffffff891689146200015857600080fd5b63ffffffff881688146200016b57600080fd5b61ffff871687146200017c57600080fd5b600287049250600d8361ffff1611156200019557600d92505b61010060405190810160409081528782526001604060020a0342166020830152600090820181905263ffffffff808c1660608401528a16608083015260a082015261ffff80851660c0830152881660e082015260068054919350600191808301620002018382620005cb565b6000928352602090922085916002020181518155602082015160018201805467ffffffffffffffff19166001604060020a039290921691909117905560408201518160010160086101000a8154816001604060020a0302191690836001604060020a0316021790555060608201518160010160106101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555060c082015181600101601c6101000a81548161ffff021916908361ffff16021790555060e08201516001909101805461ffff929092167e0100000000000000000000000000000000000000000000000000000000000002600160f060020a039092169190911790555003905063ffffffff811681146200035e57600080fd5b7f0a5311bd2a6608f08a180df2ee7c5946819a649b204b554bb8e39825b2c50ad58582846060015163ffffffff16856080015163ffffffff168651604051600160a060020a03909516855260208501939093526040808501929092526060840152608083019190915260a0909101905180910390a1620003ef60008683640100000000620025e0620003fb82021704565b98975050505050505050565b600160a060020a03808316600081815260086020908152604080832080546001019055858352600790915290208054600160a060020a03191690911790558316156200048f57600160a060020a03831660009081526008602090815260408083208054600019019055838352600a82528083208054600160a060020a03199081169091556009909252909120805490911690555b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef838383604051600160a060020a039384168152919092166020820152604080820192909252606001905180910390a1505050565b600283019183908215620005755791602002820160005b838211156200054157835183826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302620004fb565b8015620005735782816101000a81549063ffffffff021916905560040160208160030104928301926001030262000541565b505b5062000583929150620005ff565b5090565b6101006040519081016040908152600080835260208301819052908201819052606082018190526080820181905260a0820181905260c0820181905260e082015290565b815481835581811511620005fa57600202816002028360005260206000209182019101620005fa919062000626565b505050565b6200062391905b808211156200058357805463ffffffff1916815560010162000606565b90565b6200062391905b808211156200058357600080825560018201556002016200062d565b61309380620006596000396000f3006060604052600436106102a55763ffffffff60e060020a60003504166301ffc9a781146102dd5780630519ce79146103295780630560ff441461035857806305e45546146103f157806306fdde0314610416578063095ea7b3146104295780630a0f81681461044b5780630e583df01461045e57806314001f4c1461047157806318160ddd14610490578063183a7947146104a35780631940a936146104b657806319c2f201146104cc57806321717ebf146104df57806323b872dd146104f257806324e7a38a1461051a57806327d7874c146105395780632ba73c15146105585780633d7d3f5a146105775780633f4ba83a1461059657806346116e6f146105a957806346d22c70146105bf578063481af3d3146105d85780634ad8c938146105ee5780634b85fd551461060d5780634dfff04f146106235780634e0a33791461064557806356129134146106645780635663896e146106865780635c975abb1461069c5780635fd8c710146106af5780636352211e146106c2578063680eba27146106d85780636af04a57146106eb5780636fbde40d146106fe57806370a082311461071d578063715879881461073c5780637a7d49371461075b5780638456cb591461076e5780638462151c1461078157806388c2a0bf146107f357806391876e571461080957806395d89b411461081c5780639d6fac6f1461082f578063a45f4bfc1461085e578063a9059cbb14610874578063b047fb5014610896578063b0c35c05146108a9578063bc4006f5146108bc578063c3bea9af146108cf578063d3e6f49f146108e5578063defb9584146108fb578063e17b25af1461090e578063e6cbe3511461092d578063e98b7f4d14610940578063ed60ade6146109ae578063f1ca9410146109bc578063f2b47d52146109cf578063f7d8c883146109e2575b600b5433600160a060020a03908116911614806102d05750600c5433600160a060020a039081169116145b15156102db57600080fd5b005b34156102e857600080fd5b6103157fffffffff00000000000000000000000000000000000000000000000000000000600435166109f0565b604051901515815260200160405180910390f35b341561033457600080fd5b61033c610c77565b604051600160a060020a03909116815260200160405180910390f35b341561036357600080fd5b61037a600480359060248035908101910135610c86565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156103b657808201518382015260200161039e565b50505050905090810190601f1680156103e35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103fc57600080fd5b610404610d63565b60405190815260200160405180910390f35b341561042157600080fd5b61037a610d69565b341561043457600080fd5b6102db600160a060020a0360043516602435610da0565b341561045657600080fd5b61033c610e2a565b341561046957600080fd5b610404610e39565b341561047c57600080fd5b6102db600160a060020a0360043516610e44565b341561049b57600080fd5b610404610ef1565b34156104ae57600080fd5b610404610efc565b34156104c157600080fd5b610315600435610f02565b34156104d757600080fd5b610404610f47565b34156104ea57600080fd5b61033c610f4e565b34156104fd57600080fd5b6102db600160a060020a0360043581169060243516604435610f5d565b341561052557600080fd5b6102db600160a060020a0360043516610fe4565b341561054457600080fd5b6102db600160a060020a0360043516611091565b341561056357600080fd5b6102db600160a060020a03600435166110e3565b341561058257600080fd5b6102db600435602435604435606435611135565b34156105a157600080fd5b6102db611214565b34156105b457600080fd5b61033c6004356112ac565b34156105ca57600080fd5b6103156004356024356112c7565b34156105e357600080fd5b61033c600435611347565b34156105f957600080fd5b6102db600435602435604435606435611362565b341561061857600080fd5b6102db600435611428565b341561062e57600080fd5b6102db600160a060020a0360043516602435611448565b341561065057600080fd5b6102db600160a060020a03600435166114a2565b341561066f57600080fd5b6102db600435600160a060020a03602435166114f4565b341561069157600080fd5b6102db600435611560565b34156106a757600080fd5b6103156115c8565b34156106ba57600080fd5b6102db6115d8565b34156106cd57600080fd5b61033c600435611649565b34156106e357600080fd5b61040461166d565b34156106f657600080fd5b61033c611673565b341561070957600080fd5b6102db600160a060020a0360043516611682565b341561072857600080fd5b610404600160a060020a036004351661172f565b341561074757600080fd5b6102db600160a060020a036004351661174a565b341561076657600080fd5b6104046117d8565b341561077957600080fd5b6102db6117de565b341561078c57600080fd5b6107a0600160a060020a036004351661186a565b60405160208082528190810183818151815260200191508051906020019060200280838360005b838110156107df5780820151838201526020016107c7565b505050509050019250505060405180910390f35b34156107fe57600080fd5b61040460043561194b565b341561081457600080fd5b6102db611c1b565b341561082757600080fd5b61037a611d0e565b341561083a57600080fd5b610845600435611d45565b60405163ffffffff909116815260200160405180910390f35b341561086957600080fd5b61033c600435611d72565b341561087f57600080fd5b6102db600160a060020a0360043516602435611d8d565b34156108a157600080fd5b61033c611e30565b34156108b457600080fd5b610404611e3f565b34156108c757600080fd5b61033c611e45565b34156108da57600080fd5b6102db600435611e54565b34156108f057600080fd5b610315600435611f47565b341561090657600080fd5b610404612010565b341561091957600080fd5b6102db600160a060020a0360043516612016565b341561093857600080fd5b61033c612053565b341561094b57600080fd5b610956600435612062565b6040519915158a5297151560208a01526040808a01979097526060890195909552608088019390935260a087019190915260c086015260e0850152610100840152610120830191909152610140909101905180910390f35b6102db6004356024356121c3565b34156109c757600080fd5b610404612316565b34156109da57600080fd5b61033c61231c565b6102db60043560243561232b565b60006040517f737570706f727473496e7465726661636528627974657334290000000000000081526019016040518091039020600160e060020a03191682600160e060020a0319161480610c6f57506040517f746f6b656e4d657461646174612875696e743235362c737472696e67290000008152601d0160405180910390206040517f746f6b656e734f664f776e657228616464726573732900000000000000000000815260160160405180910390206040517f7472616e7366657246726f6d28616464726573732c616464726573732c75696e81527f7432353629000000000000000000000000000000000000000000000000000000602082015260250160405180910390206040517f7472616e7366657228616464726573732c75696e743235362900000000000000815260190160405180910390206040517f617070726f766528616464726573732c75696e74323536290000000000000000815260180160405180910390206040517f6f776e65724f662875696e743235362900000000000000000000000000000000815260100160405180910390206040517f62616c616e63654f662861646472657373290000000000000000000000000000815260120160405180910390206040517f746f74616c537570706c792829000000000000000000000000000000000000008152600d0160405180910390206040517f73796d626f6c2829000000000000000000000000000000000000000000000000815260080160405180910390206040517f6e616d652829000000000000000000000000000000000000000000000000000081526006016040518091039020181818181818181818600160e060020a03191682600160e060020a031916145b90505b919050565b600154600160a060020a031681565b610c8e612fa0565b610c96612fb2565b600d54600090600160a060020a03161515610cb057600080fd5b600d54600160a060020a031663cb4799f2878787600060405160a0015260405160e060020a63ffffffff861602815260048101848152604060248301908152604483018490529091606401848480828437820191505094505050505060a060405180830381600087803b1515610d2557600080fd5b6102c65a03f11515610d3657600080fd5b50505060405180608001805160209091016040529092509050610d59828261251d565b9695505050505050565b60115481565b60408051908101604052600d81527f43727970746f4b69747469657300000000000000000000000000000000000000602082015281565b60025460a060020a900460ff1615610db757600080fd5b610dc13382612572565b1515610dcc57600080fd5b610dd68183612592565b7f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925338383604051600160a060020a039384168152919092166020820152604080820192909252606001905180910390a15050565b600054600160a060020a031681565b662386f26fc1000081565b6000805433600160a060020a03908116911614610e6057600080fd5b5080600160a060020a0381166376190f8f6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610ea857600080fd5b6102c65a03f11515610eb957600080fd5b505050604051805190501515610ece57600080fd5b600c8054600160a060020a031916600160a060020a039290921691909117905550565b600654600019015b90565b600f5481565b6000808211610f1057600080fd5b6006805483908110610f1e57fe5b600091825260209091206002909102016001015460c060020a900463ffffffff16151592915050565b6201518081565b600c54600160a060020a031681565b60025460a060020a900460ff1615610f7457600080fd5b600160a060020a0382161515610f8957600080fd5b30600160a060020a031682600160a060020a031614151515610faa57600080fd5b610fb433826125c0565b1515610fbf57600080fd5b610fc98382612572565b1515610fd457600080fd5b610fdf8383836125e0565b505050565b6000805433600160a060020a0390811691161461100057600080fd5b5080600160a060020a0381166354c15b826000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561104857600080fd5b6102c65a03f1151561105957600080fd5b50505060405180519050151561106e57600080fd5b60108054600160a060020a031916600160a060020a039290921691909117905550565b60005433600160a060020a039081169116146110ac57600080fd5b600160a060020a03811615156110c157600080fd5b60008054600160a060020a031916600160a060020a0392909216919091179055565b60005433600160a060020a039081169116146110fe57600080fd5b600160a060020a038116151561111357600080fd5b60028054600160a060020a031916600160a060020a0392909216919091179055565b60025460a060020a900460ff161561114c57600080fd5b6111563385612572565b151561116157600080fd5b61116a84610f02565b1561117457600080fd5b600b5461118b908590600160a060020a0316612592565b600b54600160a060020a03166327ebe40a858585853360405160e060020a63ffffffff88160281526004810195909552602485019390935260448401919091526064830152600160a060020a0316608482015260a401600060405180830381600087803b15156111fa57600080fd5b6102c65a03f1151561120b57600080fd5b50505050505050565b60005433600160a060020a0390811691161461122f57600080fd5b60025460a060020a900460ff16151561124757600080fd5b600b54600160a060020a0316151561125e57600080fd5b600c54600160a060020a0316151561127557600080fd5b601054600160a060020a0316151561128c57600080fd5b601354600160a060020a0316156112a257600080fd5b6112aa6126c8565b565b600a60205260009081526040902054600160a060020a031681565b600080808085116112d757600080fd5b600084116112e457600080fd5b60068054869081106112f257fe5b9060005260206000209060020201915060068481548110151561131157fe5b9060005260206000209060020201905061132d8286838761271b565b801561133e575061133e848661289b565b95945050505050565b600960205260009081526040902054600160a060020a031681565b60025460a060020a900460ff161561137957600080fd5b6113833385612572565b151561138e57600080fd5b61139784611f47565b15156113a257600080fd5b600c546113b9908590600160a060020a0316612592565b600c54600160a060020a03166327ebe40a858585853360405160e060020a63ffffffff88160281526004810195909552602485019390935260448401919091526064830152600160a060020a0316608482015260a401600060405180830381600087803b15156111fa57600080fd5b60025433600160a060020a0390811691161461144357600080fd5b600e55565b60025460a060020a900460ff161561145f57600080fd5b6114693382612572565b151561147457600080fd5b6000908152600a602052604090208054600160a060020a031916600160a060020a0392909216919091179055565b60005433600160a060020a039081169116146114bd57600080fd5b600160a060020a03811615156114d257600080fd5b60018054600160a060020a031916600160a060020a0392909216919091179055565b60025460009033600160a060020a0390811691161461151257600080fd5b5080600160a060020a03811615156115325750600254600160a060020a03165b601154611388901061154357600080fd5b60118054600101905561155a6000808086856128f0565b50505050565b60025433600160a060020a039081169116148061158b575060005433600160a060020a039081169116145b806115a4575060015433600160a060020a039081169116145b15156115af57600080fd5b60035463ffffffff1681106115c357600080fd5b600555565b60025460a060020a900460ff1681565b600154600090819033600160a060020a039081169116146115f857600080fd5b30600160a060020a0316319150600e54600f546001010290508082111561164557600154600160a060020a031681830380156108fc0290604051600060405180830381858888f150505050505b5050565b600081815260076020526040902054600160a060020a0316801515610c7257600080fd5b61afc881565b601354600160a060020a031681565b6000805433600160a060020a0390811691161461169e57600080fd5b5080600160a060020a0381166385b861886000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156116e657600080fd5b6102c65a03f115156116f757600080fd5b50505060405180519050151561170c57600080fd5b600b8054600160a060020a031916600160a060020a039290921691909117905550565b600160a060020a031660009081526008602052604090205490565b60005433600160a060020a0390811691161461176557600080fd5b60025460a060020a900460ff16151561177d57600080fd5b60138054600160a060020a031916600160a060020a0383161790557f450db8da6efbe9c22f2347f7c2021231df1fc58d3ae9a2fa75d39fa44619930581604051600160a060020a03909116815260200160405180910390a150565b60055481565b60025433600160a060020a0390811691161480611809575060005433600160a060020a039081169116145b80611822575060015433600160a060020a039081169116145b151561182d57600080fd5b60025460a060020a900460ff161561184457600080fd5b6002805474ff0000000000000000000000000000000000000000191660a060020a179055565b611872612fa0565b600061187c612fa0565b600080600061188a8761172f565b94508415156118ba5760006040518059106118a25750595b90808252806020026020018201604052509550611941565b846040518059106118c85750595b908082528060200260200182016040525093506118e3610ef1565b925060009150600190505b82811161193d57600081815260076020526040902054600160a060020a0388811691161415611935578084838151811061192457fe5b602090810290910101526001909101905b6001016118ee565b8395505b5050505050919050565b600080600080600080600080600260149054906101000a900460ff1615151561197357600080fd5b600680548a90811061198157fe5b60009182526020909120600290910201600181015490975067ffffffffffffffff1615156119ae57600080fd5b611a438761010060405190810160409081528254825260019092015467ffffffffffffffff8082166020840152680100000000000000008204169282019290925263ffffffff608060020a83048116606083015260a060020a83048116608083015260c060020a83041660a082015261ffff60e060020a8304811660c083015260f060020a90920490911660e0820152612b9c565b1515611a4e57600080fd5b60018701546006805460c060020a90920463ffffffff1697509087908110611a7257fe5b600091825260209091206001808a015460029093029091019081015490965061ffff60f060020a92839004811696509190041684901115611ac057600185015460f060020a900461ffff1693505b6010548754865460018a0154600160a060020a0390931692630d9f5aed92919068010000000000000000900467ffffffffffffffff166000190160006040516020015260405160e060020a63ffffffff86160281526004810193909352602483019190915267ffffffffffffffff166044820152606401602060405180830381600087803b1515611b5057600080fd5b6102c65a03f11515611b6157600080fd5b505050604051805160008b81526007602052604090205460018a810154929650600160a060020a039091169450611bb092508b9160c060020a900463ffffffff1690870161ffff1686866128f0565b6001880180547bffffffff00000000000000000000000000000000000000000000000019169055600f8054600019019055600e54909150600160a060020a0333169080156108fc0290604051600060405180830381858888f150939c9b505050505050505050505050565b60025433600160a060020a0390811691161480611c46575060005433600160a060020a039081169116145b80611c5f575060015433600160a060020a039081169116145b1515611c6a57600080fd5b600b54600160a060020a0316635fd8c7106040518163ffffffff1660e060020a028152600401600060405180830381600087803b1515611ca957600080fd5b6102c65a03f11515611cba57600080fd5b5050600c54600160a060020a03169050635fd8c7106040518163ffffffff1660e060020a028152600401600060405180830381600087803b1515611cfd57600080fd5b6102c65a03f11515610fdf57600080fd5b60408051908101604052600281527f434b000000000000000000000000000000000000000000000000000000000000602082015281565b600381600e8110611d5257fe5b60089182820401919006600402915054906101000a900463ffffffff1681565b600760205260009081526040902054600160a060020a031681565b60025460a060020a900460ff1615611da457600080fd5b600160a060020a0382161515611db957600080fd5b30600160a060020a031682600160a060020a031614151515611dda57600080fd5b600b54600160a060020a0383811691161415611df557600080fd5b600c54600160a060020a0383811691161415611e1057600080fd5b611e1a3382612572565b1515611e2557600080fd5b6116453383836125e0565b600254600160a060020a031681565b600e5481565b600d54600160a060020a031681565b60025460009033600160a060020a03908116911614611e7257600080fd5b60125461afc89010611e8357600080fd5b611e92600080600085306128f0565b600b54909150611eac908290600160a060020a0316612592565b600b54600160a060020a03166327ebe40a82611ec6612bd4565b6000620151803060405160e060020a63ffffffff88160281526004810195909552602485019390935260448401919091526064830152600160a060020a0316608482015260a401600060405180830381600087803b1515611f2657600080fd5b6102c65a03f11515611f3757600080fd5b5050601280546001019055505050565b600080808311611f5657600080fd5b6006805484908110611f6457fe5b906000526020600020906002020190506120098161010060405190810160409081528254825260019092015467ffffffffffffffff8082166020840152680100000000000000008204169282019290925263ffffffff608060020a83048116606083015260a060020a83048116608083015260c060020a83041660a082015261ffff60e060020a8304811660c083015260f060020a90920490911660e0820152612c82565b9392505050565b61138881565b60005433600160a060020a0390811691161461203157600080fd5b600d8054600160a060020a031916600160a060020a0392909216919091179055565b600b54600160a060020a031681565b600080600080600080600080600080600060068c81548110151561208257fe5b906000526020600020906002020190508060010160189054906101000a900463ffffffff1663ffffffff16600014159a50438160010160089054906101000a900467ffffffffffffffff1667ffffffffffffffff161115995080600101601c9054906101000a900461ffff1661ffff1698508060010160089054906101000a900467ffffffffffffffff1667ffffffffffffffff1697508060010160189054906101000a900463ffffffff1663ffffffff1696508060010160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1695508060010160109054906101000a900463ffffffff1663ffffffff1694508060010160149054906101000a900463ffffffff1663ffffffff16935080600101601e9054906101000a900461ffff1661ffff16925080600001549150509193959799509193959799565b60025460009060a060020a900460ff16156121dd57600080fd5b6121e73383612572565b15156121f257600080fd5b6121fb82611f47565b151561220657600080fd5b6122108284612cb9565b151561221b57600080fd5b600c54600160a060020a031663c55d0f568460006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561226c57600080fd5b6102c65a03f1151561227d57600080fd5b5050506040518051600e549092508201341015905061229b57600080fd5b600c54600e54600160a060020a039091169063454a2ab39034038560405160e060020a63ffffffff851602815260048101919091526024016000604051808303818588803b15156122eb57600080fd5b6125ee5a03f115156122fc57600080fd5b50505050610fdf8263ffffffff168463ffffffff16612d08565b60125481565b601054600160a060020a031681565b600254600090819060a060020a900460ff161561234757600080fd5b600e5434101561235657600080fd5b6123603385612572565b151561236b57600080fd5b612375838561289b565b151561238057600080fd5b600680548590811061238e57fe5b906000526020600020906002020191506124338261010060405190810160409081528254825260019092015467ffffffffffffffff8082166020840152680100000000000000008204169282019290925263ffffffff608060020a83048116606083015260a060020a83048116608083015260c060020a83041660a082015261ffff60e060020a8304811660c083015260f060020a90920490911660e0820152612c82565b151561243e57600080fd5b600680548490811061244c57fe5b906000526020600020906002020190506124f18161010060405190810160409081528254825260019092015467ffffffffffffffff8082166020840152680100000000000000008204169282019290925263ffffffff608060020a83048116606083015260a060020a83048116608083015260c060020a83041660a082015261ffff60e060020a8304811660c083015260f060020a90920490911660e0820152612c82565b15156124fc57600080fd5b6125088285838661271b565b151561251357600080fd5b61155a8484612d08565b612525612fa0565b61252d612fa0565b6000808460405180591061253e5750595b818152601f19601f8301168101602001604052905092505060208201905084612568828287612e72565b5090949350505050565b600090815260076020526040902054600160a060020a0391821691161490565b6000918252600960205260409091208054600160a060020a031916600160a060020a03909216919091179055565b600090815260096020526040902054600160a060020a0391821691161490565b600160a060020a03808316600081815260086020908152604080832080546001019055858352600790915290208054600160a060020a031916909117905583161561267357600160a060020a03831660009081526008602090815260408083208054600019019055838352600a82528083208054600160a060020a03199081169091556009909252909120805490911690555b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef838383604051600160a060020a039384168152919092166020820152604080820192909252606001905180910390a1505050565b60005433600160a060020a039081169116146126e357600080fd5b60025460a060020a900460ff1615156126fb57600080fd5b6002805474ff000000000000000000000000000000000000000019169055565b60008184141561272d57506000612893565b6001850154608060020a900463ffffffff1682148061275c5750600185015460a060020a900463ffffffff1682145b1561276957506000612893565b6001830154608060020a900463ffffffff168414806127985750600183015460a060020a900463ffffffff1684145b156127a557506000612893565b6001830154608060020a900463ffffffff1615806127d257506001850154608060020a900463ffffffff16155b156127df57506001612893565b60018581015490840154608060020a9182900463ffffffff9081169290910416148061282a575060018086015490840154608060020a900463ffffffff90811660a060020a90920416145b1561283757506000612893565b6001808601549084015460a060020a900463ffffffff908116608060020a90920416148061288257506001858101549084015460a060020a9182900463ffffffff9081169290910416145b1561288f57506000612893565b5060015b949350505050565b6000818152600760205260408082205484835290822054600160a060020a0391821691168082148061133e57506000858152600a6020526040902054600160a060020a03908116908316149250505092915050565b6000806128fb612fdb565b600063ffffffff8916891461290f57600080fd5b63ffffffff8816881461292157600080fd5b61ffff8716871461293157600080fd5b600287049250600d8361ffff16111561294957600d92505b610100604051908101604090815287825267ffffffffffffffff42166020830152600090820181905263ffffffff808c1660608401528a16608083015260a082015261ffff80851660c0830152881660e0820152600680549193506001918083016129b4838261301f565b6000928352602090922085916002020181518155602082015160018201805467ffffffffffffffff191667ffffffffffffffff9290921691909117905560408201518160010160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060608201518160010160106101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555060c082015181600101601c6101000a81548161ffff021916908361ffff16021790555060e08201516001909101805461ffff9290921660f060020a027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092169190911790555003905063ffffffff81168114612b0f57600080fd5b7f0a5311bd2a6608f08a180df2ee7c5946819a649b204b554bb8e39825b2c50ad58582846060015163ffffffff16856080015163ffffffff168651604051600160a060020a03909516855260208501939093526040808501929092526060840152608083019190915260a0909101905180910390a1612b90600086836125e0565b98975050505050505050565b60008160a0015163ffffffff1615801590610c6f57504367ffffffffffffffff16826040015167ffffffffffffffff16111592915050565b600b5460009081908190600160a060020a031663eac9d94c82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515612c2257600080fd5b6102c65a03f11515612c3357600080fd5b50505060405180519250506fffffffffffffffffffffffffffffffff82168214612c5c57600080fd5b50600281048101662386f26fc10000811015612c7c5750662386f26fc100005b92915050565b60008160a0015163ffffffff16158015610c6f57504367ffffffffffffffff16826040015167ffffffffffffffff16111592915050565b6000806000600685815481101515612ccd57fe5b90600052602060002090600202019150600684815481101515612cec57fe5b9060005260206000209060020201905061133e8286838761271b565b600080600683815481101515612d1a57fe5b90600052602060002090600202019150600684815481101515612d3957fe5b600091825260209091206002909102016001810180547bffffffff000000000000000000000000000000000000000000000000191660c060020a63ffffffff8716021790559050612d8982612eb7565b612d9281612eb7565b6000848152600a602090815260408083208054600160a060020a031990811690915586845281842080549091169055600f8054600190810190915587845260079092529182902054908301547f241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b8092600160a060020a0390921691879187916801000000000000000090910467ffffffffffffffff1690518085600160a060020a0316600160a060020a031681526020018481526020018381526020018267ffffffffffffffff16815260200194505050505060405180910390a150505050565b60005b60208210612e985782518452602084019350602083019250602082039150612e75565b6001826020036101000a03905080198351168185511617909352505050565b600554600182015443919060039060e060020a900461ffff16600e8110612eda57fe5b600891828204019190066004029054906101000a900463ffffffff1663ffffffff16811515612f0557fe5b6001840180546fffffffffffffffff0000000000000000191668010000000000000000939092049390930167ffffffffffffffff16919091021790819055600d60e060020a90910461ffff161015612f9d576001818101805461ffff60e060020a8083048216909401169092027fffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092169190911790555b50565b60206040519081016040526000815290565b60806040519081016040526004815b60008152600019919091019060200181612fc15790505090565b6101006040519081016040908152600080835260208301819052908201819052606082018190526080820181905260a0820181905260c0820181905260e082015290565b815481835581811511610fdf57600083815260209020610fdf91610ef99160029182028101918502015b808211156130635760008082556001820155600201613049565b50905600a165627a7a72305820a6465fc1ce7ab1a92906ff7206b23d80a21bbd50b85b4bde6a91f8e6b2e3edde0029" - code_ContractScenario009_deployContainLibraryContract = "608060405234801561001057600080fd5b50610139806100206000396000f3006080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663f207564e8114610045575b600080fd5b34801561005157600080fd5b5061005d60043561005f565b005b73610199610030600b82828239805160001a6073146000811461002057610022565bfe5b5030600052607381538281f300730000000000000000000000000000000000000000301460806040526004361061006d5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663483b8a1481146100725780636ce8e081146100a1578063831cb739146100bc575b600080fd5b81801561007e57600080fd5b5061008d6004356024356100d7565b604080519115158252519081900360200190f35b8180156100ad57600080fd5b5061008d600435602435610117565b8180156100c857600080fd5b5061008d60043560243561012d565b60008181526020839052604081205460ff1615156100f757506000610111565b506000818152602083905260409020805460ff1916905560015b92915050565b6000908152602091909152604090205460ff1690565b60008181526020839052604081205460ff161561014c57506000610111565b50600090815260209190915260409020805460ff19166001908117909155905600a165627a7a723058200bc4068752b78840d32288f8eeffe2618c356d76fe09451d92f808cf28d4d22e0029" - code_ContractScenario010_deployContainLibraryContract = "608060405234801561001057600080fd5b50610731806100206000396000f3006080604052600436106100a35763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100a8578063095ea7b31461013257806318160ddd146101585780632f745c591461017f5780636352211e146101a35780636914db60146101d757806370a08231146101ef57806395d89b4114610210578063a9059cbb14610225578063b2e6ceeb14610249575b600080fd5b3480156100b457600080fd5b506100bd610261565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100f75781810151838201526020016100df565b50505050905090810190601f1680156101245780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561013e57600080fd5b50610156600160a060020a0360043516602435610298565b005b34801561016457600080fd5b5061016d61032d565b60408051918252519081900360200190f35b34801561018b57600080fd5b5061016d600160a060020a0360043516602435610336565b3480156101af57600080fd5b506101bb60043561035e565b60408051600160a060020a039092168252519081900360200190f35b3480156101e357600080fd5b506100bd600435610397565b3480156101fb57600080fd5b5061016d600160a060020a0360043516610438565b34801561021c57600080fd5b506100bd610453565b34801561023157600080fd5b50610156600160a060020a036004351660243561048a565b34801561025557600080fd5b5061015660043561059d565b60408051808201909152601181527f54726f6e2045524337323120546f6b656e000000000000000000000000000000602082015290565b6102a18161035e565b600160a060020a031633146102b557600080fd5b33600160a060020a03831614156102cb57600080fd5b336000818152600360209081526040808320600160a060020a03871680855290835292819020859055805185815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35050565b64e8d4a5100090565b600160a060020a03919091166000908152600460209081526040808320938352929052205490565b60008181526002602052604081205460ff16151561037b57600080fd5b50600090815260016020526040902054600160a060020a031690565b60008181526005602090815260409182902080548351601f600260001961010060018616150201909316929092049182018490048402810184019094528084526060939283018282801561042c5780601f106104015761010080835404028352916020019161042c565b820191906000526020600020905b81548152906001019060200180831161040f57829003601f168201915b50505050509050919050565b600160a060020a031660009081526020819052604090205490565b60408051808201909152600581527f5437323154000000000000000000000000000000000000000000000000000000602082015290565b6000818152600260205260408120543391849160ff1615156104ab57600080fd5b6104b48461035e565b600160a060020a038481169116146104cb57600080fd5b600160a060020a0383811690831614156104e457600080fd5b600160a060020a03821615156104f957600080fd5b508161050581856106a7565b600160a060020a0381811660008181526020818152604080832080546000190190558883526001808352818420805473ffffffffffffffffffffffffffffffffffffffff19169689169687179055858452838352928190208054909301909255815188815291517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050505050565b600081815260026020526040812054819060ff1615156105bc57600080fd5b6105c58361035e565b9150339050600160a060020a0382168114156105e057600080fd5b600160a060020a03808316600090815260036020908152604080832093851683529290522054831461061157600080fd5b600160a060020a0382811660008181526020818152604080832080546000190190558783526001808352818420805473ffffffffffffffffffffffffffffffffffffffff19169688169687179055858452838352928190208054909301909255815187815291517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a3505050565b60005b600160a060020a0383166000908152600460209081526040808320848452909152902054821461070057600160a060020a03831660009081526004602090815260408083208484529091528120556001016106aa565b5050505600a165627a7a72305820d3ca2ca957b72f4c5028c633a6ad4bafe13572bf949793fabe72e34eb640d2c50029" - code_ContractScenario012_deployTransactionCoin = "60806040526000805561029f806100176000396000f3006080604052600436106100985763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166312065fe0811461009d5780632e52d606146100b7578063483f5a7f146100cc5780634f8632ba146100e25780635896476c146101135780638b47145f14610128578063b6b55f2514610144578063f46771d91461014f578063ff18253b14610163575b600080fd5b6100a561019b565b60408051918252519081900360200190f35b3480156100c357600080fd5b506100a56101a0565b6100e0600160a060020a03600435166101a6565b005b3480156100ee57600080fd5b506100f76101df565b60408051600160a060020a039092168252519081900360200190f35b34801561011f57600080fd5b506100e06101ee565b6101306101f9565b604080519115158252519081900360200190f35b610130600435610217565b6100e0600160a060020a036004351661023a565b34801561016f57600080fd5b5061017861026c565b60408051600160a060020a03909316835260208301919091528051918290030190f35b303190565b60005481565b604051600160a060020a038216903480156108fc02916000818181858888f193505050501580156101db573d6000803e3d6000fd5b5050565b600154600160a060020a031681565b600080546001019055565b6040516000903390829060019082818181858883f194505050505090565b604051600090339083156108fc0290849084818181858888f19695505050505050565b604051600160a060020a0382169060009060059082818181858883f193505050501580156101db573d6000803e3d6000fd5b33803190915600a165627a7a72305820fd081d59bd77b97252e4a657177023ae7352e1fe802dd638ec6b9fa5df59d6110029" - code_ContractScenario013_deployTronTrxAndSunContract = "6080604052348015600f57600080fd5b50600180141515601e57600080fd5b603c80141515602c57600080fd5b610e1080141515603b57600080fd5b6201518080141515604b57600080fd5b62093a8080141515605b57600080fd5b6301e1338080141515606c57600080fd5b620f424080141515607c57600080fd5b60358060896000396000f3006080604052600080fd00a165627a7a723058206a36395ee2292959a89e7956d6826a7107c490331e4505fc319010873c26392b0029" - code_ContractScenario013_triggerTronTrxAndSunContract = "608060405234801561001057600080fd5b5061011a806100206000396000f300608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806316ada547146044575b600080fd5b348015604f57600080fd5b506056606c565b6040518082815260200191505060405180910390f35b6000600180141515607c57600080fd5b603c80141515608a57600080fd5b610e1080141515609957600080fd5b620151808014151560a957600080fd5b62093a808014151560b957600080fd5b6301e133808014151560ca57600080fd5b620f42408014151560da57600080fd5b60018014151560e857600080fd5b429050905600a165627a7a72305820eacfee595582d9244a2fb5f052905bd240f87864fb8f602f85fd31fe3b89cda80029" - code_ContractScenario014_testTripleTrigger = "608060405260d2806100126000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633d96d24c81146043575b600080fd5b606273ffffffffffffffffffffffffffffffffffffffff600435166064565b005b60405173ffffffffffffffffffffffffffffffffffffffff82169060009060059082818181858883f1935050505015801560a2573d6000803e3d6000fd5b50505600a165627a7a72305820e2d0e2bbf60a802771a52693e71a934ef01e5c5f6a584b5a3f24f5088866de4d0029" - code1_ContractScenario014_testTripleTrigger = "6080604052604051602080610263833981016040525160008054600160a060020a03909216600160a060020a031990921691909117905561021e806100456000396000f30060806040526004361061003d5763ffffffff60e060020a600035041663b3b638ab8114610042578063df5dd9c814610065578063ecb0b86214610086575b600080fd5b61006373ffffffffffffffffffffffffffffffffffffffff600435166100c4565b005b61006373ffffffffffffffffffffffffffffffffffffffff6004351661014e565b34801561009257600080fd5b5061009b6101d6565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b60008054604080517f73656e643553756e546f526563656976657228616464726573732900000000008152815190819003601b01812063ffffffff60e060020a91829004908116909102825273ffffffffffffffffffffffffffffffffffffffff8681166004840152925192909316936024808301939192829003018183875af150505050600080fd5b60008054604080517f73656e643553756e546f526563656976657228616464726573732900000000008152815190819003601b01812063ffffffff60e060020a91829004908116909102825273ffffffffffffffffffffffffffffffffffffffff8681166004840152925192909316936024808301939192829003018183875af15050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16815600a165627a7a7230582065632ad682ad1abe06031e0f1471af18b8caeaddc98c67de6765b9f01ce8aa320029" - code2_ContractScenario014_testTripleTrigger = "60806040526040516020806101df833981016040525160008054600160a060020a03909216600160a060020a031990921691909117905561019a806100456000396000f30060806040526004361061004b5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663025750698114610050578063ecb0b86214610073575b600080fd5b61007173ffffffffffffffffffffffffffffffffffffffff600435166100b1565b005b34801561007f57600080fd5b50610088610152565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b60008054604080517f74726967676572436f6e747261637431286164647265737329000000000000008152815190819003601901812063ffffffff7c010000000000000000000000000000000000000000000000000000000091829004908116909102825273ffffffffffffffffffffffffffffffffffffffff8681166004840152925192909316936024808301939192829003018183875af15050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16815600a165627a7a723058205a66bc83322abbfb01da52698e6f5a6b2ca2ff7c17793c1ff9db3a6c7e7f6cb10029" - code_TronDice_tronDice = "6080604052620ef420600155600060678190558054600160a060020a03191633179055610699806100316000396000f3006080604052600436106100825763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633ccfd60b81146100875780638da5cb5b146100ae578063acfff377146100df578063d0e30db0146100ea578063d263b7eb146100f4578063f2fde38b14610109578063fd2ba8b01461012a575b600080fd5b34801561009357600080fd5b5061009c61013f565b60408051918252519081900360200190f35b3480156100ba57600080fd5b506100c3610221565b60408051600160a060020a039092168252519081900360200190f35b61009c600435610230565b6100f26104b8565b005b34801561010057600080fd5b506100f2610504565b34801561011557600080fd5b506100f2600160a060020a0360043516610529565b34801561013657600080fd5b5061009c6105bd565b3360009081526002602052604081205481811161015b57600080fd5b336000818152600260205260408082208290555183156108fc0291849190818181858888f19350505050151561019057600080fd5b33600360646067548115156101a157fe5b06606481106101ac57fe5b01805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055606780546001019055604080513381526020810183905281517f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364929181900390910190a1919050565b600054600160a060020a031681565b600080600080600080600080600060618a10801561024e575060018a115b151561025957600080fd5b620f42403410158015610270575064174876e80034105b151561027b57600080fd5b336003606460675481151561028c57fe5b066064811061029757fe5b01805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03929092169190911790556067805460010190553497504360001901409650600360648806606481106102e757fe5b015460675460408051600160a060020a039093168a81014182019081014201909301845290519283900360200190922091975095506064900660010193508984101561045c576103388a60016105d0565b9250610346600154846105e4565b91507fdef9eb05d56d654703e420fad711aa89f7a03dc78c4d1c9a9d6d2548dad540653031610377846127106105e4565b60408051928352349190910260208301528051918290030190a161039d826127106105e4565b34023031116103ab57600080fd5b6103c06103b88984610622565b6127106105e4565b336000908152600260205260409020549091506103dd9082610646565b3360008181526002602090815260409182902093909355805191825234928201929092528082018c9052606081018690526080810185905260a0810184905260c0810183905260e081018a905290517fec1c9e10dd62d178aa9c345b3dc5e131cd479d8388331e77b668a16b8f95bdc0918190036101000190a16104aa565b604080513381523460208201528082018c905260608101869052608081018a905290517fc16d5d73a3ed9d2611bf92d1b1bcfa0568410a9b7c94ba5c70135d3a4657a8989181900360a00190a15b509198975050505050505050565b600054600160a060020a031633146104cf57600080fd5b6040805134815290517f4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e384269181900360200190a1565b600054600160a060020a0316331461051b57600080fd5b600054600160a060020a0316ff5b600054600160a060020a0316331461054057600080fd5b600160a060020a038116151561055557600080fd5b60008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b3360009081526002602052604090205490565b60006105de8383111561065e565b50900390565b6000806105f36000841161065e565b82848115156105fe57fe5b04905061061b838581151561060f57fe5b0682850201851461065e565b9392505050565b600082820261061b841580610641575083858381151561063e57fe5b04145b61065e565b600082820161061b8482108015906106415750838210155b80151561066a57600080fd5b505600a165627a7a7230582094b570d711e59ef03fa2e2ac5e6b4b46cd0bec830c732bc75460783f0392ea000029" - code_TvmContract_deployErc721CryptoKitties = "606060409081526002805460a060020a60ff02191690556101c090519081016040908152603c82526078602083015261012c9082015261025860608201526107086080820152610e1060a0820152611c2060c082015261384060e082015261708061010082015261e100610120820152620151806101408201526202a3006101608201526205460061018082015262093a806101a0820152620000a790600390600e620004e4565b50600f60055566071afd498d0000600e553415620000c457600080fd5b6002805460008054600160a060020a033316600160a060020a03199182168117835560a060020a60ff02199093167401000000000000000000000000000000000000000017169091179091556200012f90808060001981640100000000620028f06200013682021704565b5062000649565b6000806200014362000587565b600063ffffffff891689146200015857600080fd5b63ffffffff881688146200016b57600080fd5b61ffff871687146200017c57600080fd5b600287049250600d8361ffff1611156200019557600d92505b61010060405190810160409081528782526001604060020a0342166020830152600090820181905263ffffffff808c1660608401528a16608083015260a082015261ffff80851660c0830152881660e082015260068054919350600191808301620002018382620005cb565b6000928352602090922085916002020181518155602082015160018201805467ffffffffffffffff19166001604060020a039290921691909117905560408201518160010160086101000a8154816001604060020a0302191690836001604060020a0316021790555060608201518160010160106101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555060c082015181600101601c6101000a81548161ffff021916908361ffff16021790555060e08201516001909101805461ffff929092167e0100000000000000000000000000000000000000000000000000000000000002600160f060020a039092169190911790555003905063ffffffff811681146200035e57600080fd5b7f0a5311bd2a6608f08a180df2ee7c5946819a649b204b554bb8e39825b2c50ad58582846060015163ffffffff16856080015163ffffffff168651604051600160a060020a03909516855260208501939093526040808501929092526060840152608083019190915260a0909101905180910390a1620003ef60008683640100000000620025e0620003fb82021704565b98975050505050505050565b600160a060020a03808316600081815260086020908152604080832080546001019055858352600790915290208054600160a060020a03191690911790558316156200048f57600160a060020a03831660009081526008602090815260408083208054600019019055838352600a82528083208054600160a060020a03199081169091556009909252909120805490911690555b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef838383604051600160a060020a039384168152919092166020820152604080820192909252606001905180910390a1505050565b600283019183908215620005755791602002820160005b838211156200054157835183826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302620004fb565b8015620005735782816101000a81549063ffffffff021916905560040160208160030104928301926001030262000541565b505b5062000583929150620005ff565b5090565b6101006040519081016040908152600080835260208301819052908201819052606082018190526080820181905260a0820181905260c0820181905260e082015290565b815481835581811511620005fa57600202816002028360005260206000209182019101620005fa919062000626565b505050565b6200062391905b808211156200058357805463ffffffff1916815560010162000606565b90565b6200062391905b808211156200058357600080825560018201556002016200062d565b61309380620006596000396000f3006060604052600436106102a55763ffffffff60e060020a60003504166301ffc9a781146102dd5780630519ce79146103295780630560ff441461035857806305e45546146103f157806306fdde0314610416578063095ea7b3146104295780630a0f81681461044b5780630e583df01461045e57806314001f4c1461047157806318160ddd14610490578063183a7947146104a35780631940a936146104b657806319c2f201146104cc57806321717ebf146104df57806323b872dd146104f257806324e7a38a1461051a57806327d7874c146105395780632ba73c15146105585780633d7d3f5a146105775780633f4ba83a1461059657806346116e6f146105a957806346d22c70146105bf578063481af3d3146105d85780634ad8c938146105ee5780634b85fd551461060d5780634dfff04f146106235780634e0a33791461064557806356129134146106645780635663896e146106865780635c975abb1461069c5780635fd8c710146106af5780636352211e146106c2578063680eba27146106d85780636af04a57146106eb5780636fbde40d146106fe57806370a082311461071d578063715879881461073c5780637a7d49371461075b5780638456cb591461076e5780638462151c1461078157806388c2a0bf146107f357806391876e571461080957806395d89b411461081c5780639d6fac6f1461082f578063a45f4bfc1461085e578063a9059cbb14610874578063b047fb5014610896578063b0c35c05146108a9578063bc4006f5146108bc578063c3bea9af146108cf578063d3e6f49f146108e5578063defb9584146108fb578063e17b25af1461090e578063e6cbe3511461092d578063e98b7f4d14610940578063ed60ade6146109ae578063f1ca9410146109bc578063f2b47d52146109cf578063f7d8c883146109e2575b600b5433600160a060020a03908116911614806102d05750600c5433600160a060020a039081169116145b15156102db57600080fd5b005b34156102e857600080fd5b6103157fffffffff00000000000000000000000000000000000000000000000000000000600435166109f0565b604051901515815260200160405180910390f35b341561033457600080fd5b61033c610c77565b604051600160a060020a03909116815260200160405180910390f35b341561036357600080fd5b61037a600480359060248035908101910135610c86565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156103b657808201518382015260200161039e565b50505050905090810190601f1680156103e35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103fc57600080fd5b610404610d63565b60405190815260200160405180910390f35b341561042157600080fd5b61037a610d69565b341561043457600080fd5b6102db600160a060020a0360043516602435610da0565b341561045657600080fd5b61033c610e2a565b341561046957600080fd5b610404610e39565b341561047c57600080fd5b6102db600160a060020a0360043516610e44565b341561049b57600080fd5b610404610ef1565b34156104ae57600080fd5b610404610efc565b34156104c157600080fd5b610315600435610f02565b34156104d757600080fd5b610404610f47565b34156104ea57600080fd5b61033c610f4e565b34156104fd57600080fd5b6102db600160a060020a0360043581169060243516604435610f5d565b341561052557600080fd5b6102db600160a060020a0360043516610fe4565b341561054457600080fd5b6102db600160a060020a0360043516611091565b341561056357600080fd5b6102db600160a060020a03600435166110e3565b341561058257600080fd5b6102db600435602435604435606435611135565b34156105a157600080fd5b6102db611214565b34156105b457600080fd5b61033c6004356112ac565b34156105ca57600080fd5b6103156004356024356112c7565b34156105e357600080fd5b61033c600435611347565b34156105f957600080fd5b6102db600435602435604435606435611362565b341561061857600080fd5b6102db600435611428565b341561062e57600080fd5b6102db600160a060020a0360043516602435611448565b341561065057600080fd5b6102db600160a060020a03600435166114a2565b341561066f57600080fd5b6102db600435600160a060020a03602435166114f4565b341561069157600080fd5b6102db600435611560565b34156106a757600080fd5b6103156115c8565b34156106ba57600080fd5b6102db6115d8565b34156106cd57600080fd5b61033c600435611649565b34156106e357600080fd5b61040461166d565b34156106f657600080fd5b61033c611673565b341561070957600080fd5b6102db600160a060020a0360043516611682565b341561072857600080fd5b610404600160a060020a036004351661172f565b341561074757600080fd5b6102db600160a060020a036004351661174a565b341561076657600080fd5b6104046117d8565b341561077957600080fd5b6102db6117de565b341561078c57600080fd5b6107a0600160a060020a036004351661186a565b60405160208082528190810183818151815260200191508051906020019060200280838360005b838110156107df5780820151838201526020016107c7565b505050509050019250505060405180910390f35b34156107fe57600080fd5b61040460043561194b565b341561081457600080fd5b6102db611c1b565b341561082757600080fd5b61037a611d0e565b341561083a57600080fd5b610845600435611d45565b60405163ffffffff909116815260200160405180910390f35b341561086957600080fd5b61033c600435611d72565b341561087f57600080fd5b6102db600160a060020a0360043516602435611d8d565b34156108a157600080fd5b61033c611e30565b34156108b457600080fd5b610404611e3f565b34156108c757600080fd5b61033c611e45565b34156108da57600080fd5b6102db600435611e54565b34156108f057600080fd5b610315600435611f47565b341561090657600080fd5b610404612010565b341561091957600080fd5b6102db600160a060020a0360043516612016565b341561093857600080fd5b61033c612053565b341561094b57600080fd5b610956600435612062565b6040519915158a5297151560208a01526040808a01979097526060890195909552608088019390935260a087019190915260c086015260e0850152610100840152610120830191909152610140909101905180910390f35b6102db6004356024356121c3565b34156109c757600080fd5b610404612316565b34156109da57600080fd5b61033c61231c565b6102db60043560243561232b565b60006040517f737570706f727473496e7465726661636528627974657334290000000000000081526019016040518091039020600160e060020a03191682600160e060020a0319161480610c6f57506040517f746f6b656e4d657461646174612875696e743235362c737472696e67290000008152601d0160405180910390206040517f746f6b656e734f664f776e657228616464726573732900000000000000000000815260160160405180910390206040517f7472616e7366657246726f6d28616464726573732c616464726573732c75696e81527f7432353629000000000000000000000000000000000000000000000000000000602082015260250160405180910390206040517f7472616e7366657228616464726573732c75696e743235362900000000000000815260190160405180910390206040517f617070726f766528616464726573732c75696e74323536290000000000000000815260180160405180910390206040517f6f776e65724f662875696e743235362900000000000000000000000000000000815260100160405180910390206040517f62616c616e63654f662861646472657373290000000000000000000000000000815260120160405180910390206040517f746f74616c537570706c792829000000000000000000000000000000000000008152600d0160405180910390206040517f73796d626f6c2829000000000000000000000000000000000000000000000000815260080160405180910390206040517f6e616d652829000000000000000000000000000000000000000000000000000081526006016040518091039020181818181818181818600160e060020a03191682600160e060020a031916145b90505b919050565b600154600160a060020a031681565b610c8e612fa0565b610c96612fb2565b600d54600090600160a060020a03161515610cb057600080fd5b600d54600160a060020a031663cb4799f2878787600060405160a0015260405160e060020a63ffffffff861602815260048101848152604060248301908152604483018490529091606401848480828437820191505094505050505060a060405180830381600087803b1515610d2557600080fd5b6102c65a03f11515610d3657600080fd5b50505060405180608001805160209091016040529092509050610d59828261251d565b9695505050505050565b60115481565b60408051908101604052600d81527f43727970746f4b69747469657300000000000000000000000000000000000000602082015281565b60025460a060020a900460ff1615610db757600080fd5b610dc13382612572565b1515610dcc57600080fd5b610dd68183612592565b7f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925338383604051600160a060020a039384168152919092166020820152604080820192909252606001905180910390a15050565b600054600160a060020a031681565b662386f26fc1000081565b6000805433600160a060020a03908116911614610e6057600080fd5b5080600160a060020a0381166376190f8f6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610ea857600080fd5b6102c65a03f11515610eb957600080fd5b505050604051805190501515610ece57600080fd5b600c8054600160a060020a031916600160a060020a039290921691909117905550565b600654600019015b90565b600f5481565b6000808211610f1057600080fd5b6006805483908110610f1e57fe5b600091825260209091206002909102016001015460c060020a900463ffffffff16151592915050565b6201518081565b600c54600160a060020a031681565b60025460a060020a900460ff1615610f7457600080fd5b600160a060020a0382161515610f8957600080fd5b30600160a060020a031682600160a060020a031614151515610faa57600080fd5b610fb433826125c0565b1515610fbf57600080fd5b610fc98382612572565b1515610fd457600080fd5b610fdf8383836125e0565b505050565b6000805433600160a060020a0390811691161461100057600080fd5b5080600160a060020a0381166354c15b826000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561104857600080fd5b6102c65a03f1151561105957600080fd5b50505060405180519050151561106e57600080fd5b60108054600160a060020a031916600160a060020a039290921691909117905550565b60005433600160a060020a039081169116146110ac57600080fd5b600160a060020a03811615156110c157600080fd5b60008054600160a060020a031916600160a060020a0392909216919091179055565b60005433600160a060020a039081169116146110fe57600080fd5b600160a060020a038116151561111357600080fd5b60028054600160a060020a031916600160a060020a0392909216919091179055565b60025460a060020a900460ff161561114c57600080fd5b6111563385612572565b151561116157600080fd5b61116a84610f02565b1561117457600080fd5b600b5461118b908590600160a060020a0316612592565b600b54600160a060020a03166327ebe40a858585853360405160e060020a63ffffffff88160281526004810195909552602485019390935260448401919091526064830152600160a060020a0316608482015260a401600060405180830381600087803b15156111fa57600080fd5b6102c65a03f1151561120b57600080fd5b50505050505050565b60005433600160a060020a0390811691161461122f57600080fd5b60025460a060020a900460ff16151561124757600080fd5b600b54600160a060020a0316151561125e57600080fd5b600c54600160a060020a0316151561127557600080fd5b601054600160a060020a0316151561128c57600080fd5b601354600160a060020a0316156112a257600080fd5b6112aa6126c8565b565b600a60205260009081526040902054600160a060020a031681565b600080808085116112d757600080fd5b600084116112e457600080fd5b60068054869081106112f257fe5b9060005260206000209060020201915060068481548110151561131157fe5b9060005260206000209060020201905061132d8286838761271b565b801561133e575061133e848661289b565b95945050505050565b600960205260009081526040902054600160a060020a031681565b60025460a060020a900460ff161561137957600080fd5b6113833385612572565b151561138e57600080fd5b61139784611f47565b15156113a257600080fd5b600c546113b9908590600160a060020a0316612592565b600c54600160a060020a03166327ebe40a858585853360405160e060020a63ffffffff88160281526004810195909552602485019390935260448401919091526064830152600160a060020a0316608482015260a401600060405180830381600087803b15156111fa57600080fd5b60025433600160a060020a0390811691161461144357600080fd5b600e55565b60025460a060020a900460ff161561145f57600080fd5b6114693382612572565b151561147457600080fd5b6000908152600a602052604090208054600160a060020a031916600160a060020a0392909216919091179055565b60005433600160a060020a039081169116146114bd57600080fd5b600160a060020a03811615156114d257600080fd5b60018054600160a060020a031916600160a060020a0392909216919091179055565b60025460009033600160a060020a0390811691161461151257600080fd5b5080600160a060020a03811615156115325750600254600160a060020a03165b601154611388901061154357600080fd5b60118054600101905561155a6000808086856128f0565b50505050565b60025433600160a060020a039081169116148061158b575060005433600160a060020a039081169116145b806115a4575060015433600160a060020a039081169116145b15156115af57600080fd5b60035463ffffffff1681106115c357600080fd5b600555565b60025460a060020a900460ff1681565b600154600090819033600160a060020a039081169116146115f857600080fd5b30600160a060020a0316319150600e54600f546001010290508082111561164557600154600160a060020a031681830380156108fc0290604051600060405180830381858888f150505050505b5050565b600081815260076020526040902054600160a060020a0316801515610c7257600080fd5b61afc881565b601354600160a060020a031681565b6000805433600160a060020a0390811691161461169e57600080fd5b5080600160a060020a0381166385b861886000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156116e657600080fd5b6102c65a03f115156116f757600080fd5b50505060405180519050151561170c57600080fd5b600b8054600160a060020a031916600160a060020a039290921691909117905550565b600160a060020a031660009081526008602052604090205490565b60005433600160a060020a0390811691161461176557600080fd5b60025460a060020a900460ff16151561177d57600080fd5b60138054600160a060020a031916600160a060020a0383161790557f450db8da6efbe9c22f2347f7c2021231df1fc58d3ae9a2fa75d39fa44619930581604051600160a060020a03909116815260200160405180910390a150565b60055481565b60025433600160a060020a0390811691161480611809575060005433600160a060020a039081169116145b80611822575060015433600160a060020a039081169116145b151561182d57600080fd5b60025460a060020a900460ff161561184457600080fd5b6002805474ff0000000000000000000000000000000000000000191660a060020a179055565b611872612fa0565b600061187c612fa0565b600080600061188a8761172f565b94508415156118ba5760006040518059106118a25750595b90808252806020026020018201604052509550611941565b846040518059106118c85750595b908082528060200260200182016040525093506118e3610ef1565b925060009150600190505b82811161193d57600081815260076020526040902054600160a060020a0388811691161415611935578084838151811061192457fe5b602090810290910101526001909101905b6001016118ee565b8395505b5050505050919050565b600080600080600080600080600260149054906101000a900460ff1615151561197357600080fd5b600680548a90811061198157fe5b60009182526020909120600290910201600181015490975067ffffffffffffffff1615156119ae57600080fd5b611a438761010060405190810160409081528254825260019092015467ffffffffffffffff8082166020840152680100000000000000008204169282019290925263ffffffff608060020a83048116606083015260a060020a83048116608083015260c060020a83041660a082015261ffff60e060020a8304811660c083015260f060020a90920490911660e0820152612b9c565b1515611a4e57600080fd5b60018701546006805460c060020a90920463ffffffff1697509087908110611a7257fe5b600091825260209091206001808a015460029093029091019081015490965061ffff60f060020a92839004811696509190041684901115611ac057600185015460f060020a900461ffff1693505b6010548754865460018a0154600160a060020a0390931692630d9f5aed92919068010000000000000000900467ffffffffffffffff166000190160006040516020015260405160e060020a63ffffffff86160281526004810193909352602483019190915267ffffffffffffffff166044820152606401602060405180830381600087803b1515611b5057600080fd5b6102c65a03f11515611b6157600080fd5b505050604051805160008b81526007602052604090205460018a810154929650600160a060020a039091169450611bb092508b9160c060020a900463ffffffff1690870161ffff1686866128f0565b6001880180547bffffffff00000000000000000000000000000000000000000000000019169055600f8054600019019055600e54909150600160a060020a0333169080156108fc0290604051600060405180830381858888f150939c9b505050505050505050505050565b60025433600160a060020a0390811691161480611c46575060005433600160a060020a039081169116145b80611c5f575060015433600160a060020a039081169116145b1515611c6a57600080fd5b600b54600160a060020a0316635fd8c7106040518163ffffffff1660e060020a028152600401600060405180830381600087803b1515611ca957600080fd5b6102c65a03f11515611cba57600080fd5b5050600c54600160a060020a03169050635fd8c7106040518163ffffffff1660e060020a028152600401600060405180830381600087803b1515611cfd57600080fd5b6102c65a03f11515610fdf57600080fd5b60408051908101604052600281527f434b000000000000000000000000000000000000000000000000000000000000602082015281565b600381600e8110611d5257fe5b60089182820401919006600402915054906101000a900463ffffffff1681565b600760205260009081526040902054600160a060020a031681565b60025460a060020a900460ff1615611da457600080fd5b600160a060020a0382161515611db957600080fd5b30600160a060020a031682600160a060020a031614151515611dda57600080fd5b600b54600160a060020a0383811691161415611df557600080fd5b600c54600160a060020a0383811691161415611e1057600080fd5b611e1a3382612572565b1515611e2557600080fd5b6116453383836125e0565b600254600160a060020a031681565b600e5481565b600d54600160a060020a031681565b60025460009033600160a060020a03908116911614611e7257600080fd5b60125461afc89010611e8357600080fd5b611e92600080600085306128f0565b600b54909150611eac908290600160a060020a0316612592565b600b54600160a060020a03166327ebe40a82611ec6612bd4565b6000620151803060405160e060020a63ffffffff88160281526004810195909552602485019390935260448401919091526064830152600160a060020a0316608482015260a401600060405180830381600087803b1515611f2657600080fd5b6102c65a03f11515611f3757600080fd5b5050601280546001019055505050565b600080808311611f5657600080fd5b6006805484908110611f6457fe5b906000526020600020906002020190506120098161010060405190810160409081528254825260019092015467ffffffffffffffff8082166020840152680100000000000000008204169282019290925263ffffffff608060020a83048116606083015260a060020a83048116608083015260c060020a83041660a082015261ffff60e060020a8304811660c083015260f060020a90920490911660e0820152612c82565b9392505050565b61138881565b60005433600160a060020a0390811691161461203157600080fd5b600d8054600160a060020a031916600160a060020a0392909216919091179055565b600b54600160a060020a031681565b600080600080600080600080600080600060068c81548110151561208257fe5b906000526020600020906002020190508060010160189054906101000a900463ffffffff1663ffffffff16600014159a50438160010160089054906101000a900467ffffffffffffffff1667ffffffffffffffff161115995080600101601c9054906101000a900461ffff1661ffff1698508060010160089054906101000a900467ffffffffffffffff1667ffffffffffffffff1697508060010160189054906101000a900463ffffffff1663ffffffff1696508060010160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1695508060010160109054906101000a900463ffffffff1663ffffffff1694508060010160149054906101000a900463ffffffff1663ffffffff16935080600101601e9054906101000a900461ffff1661ffff16925080600001549150509193959799509193959799565b60025460009060a060020a900460ff16156121dd57600080fd5b6121e73383612572565b15156121f257600080fd5b6121fb82611f47565b151561220657600080fd5b6122108284612cb9565b151561221b57600080fd5b600c54600160a060020a031663c55d0f568460006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561226c57600080fd5b6102c65a03f1151561227d57600080fd5b5050506040518051600e549092508201341015905061229b57600080fd5b600c54600e54600160a060020a039091169063454a2ab39034038560405160e060020a63ffffffff851602815260048101919091526024016000604051808303818588803b15156122eb57600080fd5b6125ee5a03f115156122fc57600080fd5b50505050610fdf8263ffffffff168463ffffffff16612d08565b60125481565b601054600160a060020a031681565b600254600090819060a060020a900460ff161561234757600080fd5b600e5434101561235657600080fd5b6123603385612572565b151561236b57600080fd5b612375838561289b565b151561238057600080fd5b600680548590811061238e57fe5b906000526020600020906002020191506124338261010060405190810160409081528254825260019092015467ffffffffffffffff8082166020840152680100000000000000008204169282019290925263ffffffff608060020a83048116606083015260a060020a83048116608083015260c060020a83041660a082015261ffff60e060020a8304811660c083015260f060020a90920490911660e0820152612c82565b151561243e57600080fd5b600680548490811061244c57fe5b906000526020600020906002020190506124f18161010060405190810160409081528254825260019092015467ffffffffffffffff8082166020840152680100000000000000008204169282019290925263ffffffff608060020a83048116606083015260a060020a83048116608083015260c060020a83041660a082015261ffff60e060020a8304811660c083015260f060020a90920490911660e0820152612c82565b15156124fc57600080fd5b6125088285838661271b565b151561251357600080fd5b61155a8484612d08565b612525612fa0565b61252d612fa0565b6000808460405180591061253e5750595b818152601f19601f8301168101602001604052905092505060208201905084612568828287612e72565b5090949350505050565b600090815260076020526040902054600160a060020a0391821691161490565b6000918252600960205260409091208054600160a060020a031916600160a060020a03909216919091179055565b600090815260096020526040902054600160a060020a0391821691161490565b600160a060020a03808316600081815260086020908152604080832080546001019055858352600790915290208054600160a060020a031916909117905583161561267357600160a060020a03831660009081526008602090815260408083208054600019019055838352600a82528083208054600160a060020a03199081169091556009909252909120805490911690555b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef838383604051600160a060020a039384168152919092166020820152604080820192909252606001905180910390a1505050565b60005433600160a060020a039081169116146126e357600080fd5b60025460a060020a900460ff1615156126fb57600080fd5b6002805474ff000000000000000000000000000000000000000019169055565b60008184141561272d57506000612893565b6001850154608060020a900463ffffffff1682148061275c5750600185015460a060020a900463ffffffff1682145b1561276957506000612893565b6001830154608060020a900463ffffffff168414806127985750600183015460a060020a900463ffffffff1684145b156127a557506000612893565b6001830154608060020a900463ffffffff1615806127d257506001850154608060020a900463ffffffff16155b156127df57506001612893565b60018581015490840154608060020a9182900463ffffffff9081169290910416148061282a575060018086015490840154608060020a900463ffffffff90811660a060020a90920416145b1561283757506000612893565b6001808601549084015460a060020a900463ffffffff908116608060020a90920416148061288257506001858101549084015460a060020a9182900463ffffffff9081169290910416145b1561288f57506000612893565b5060015b949350505050565b6000818152600760205260408082205484835290822054600160a060020a0391821691168082148061133e57506000858152600a6020526040902054600160a060020a03908116908316149250505092915050565b6000806128fb612fdb565b600063ffffffff8916891461290f57600080fd5b63ffffffff8816881461292157600080fd5b61ffff8716871461293157600080fd5b600287049250600d8361ffff16111561294957600d92505b610100604051908101604090815287825267ffffffffffffffff42166020830152600090820181905263ffffffff808c1660608401528a16608083015260a082015261ffff80851660c0830152881660e0820152600680549193506001918083016129b4838261301f565b6000928352602090922085916002020181518155602082015160018201805467ffffffffffffffff191667ffffffffffffffff9290921691909117905560408201518160010160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060608201518160010160106101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555060c082015181600101601c6101000a81548161ffff021916908361ffff16021790555060e08201516001909101805461ffff9290921660f060020a027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092169190911790555003905063ffffffff81168114612b0f57600080fd5b7f0a5311bd2a6608f08a180df2ee7c5946819a649b204b554bb8e39825b2c50ad58582846060015163ffffffff16856080015163ffffffff168651604051600160a060020a03909516855260208501939093526040808501929092526060840152608083019190915260a0909101905180910390a1612b90600086836125e0565b98975050505050505050565b60008160a0015163ffffffff1615801590610c6f57504367ffffffffffffffff16826040015167ffffffffffffffff16111592915050565b600b5460009081908190600160a060020a031663eac9d94c82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515612c2257600080fd5b6102c65a03f11515612c3357600080fd5b50505060405180519250506fffffffffffffffffffffffffffffffff82168214612c5c57600080fd5b50600281048101662386f26fc10000811015612c7c5750662386f26fc100005b92915050565b60008160a0015163ffffffff16158015610c6f57504367ffffffffffffffff16826040015167ffffffffffffffff16111592915050565b6000806000600685815481101515612ccd57fe5b90600052602060002090600202019150600684815481101515612cec57fe5b9060005260206000209060020201905061133e8286838761271b565b600080600683815481101515612d1a57fe5b90600052602060002090600202019150600684815481101515612d3957fe5b600091825260209091206002909102016001810180547bffffffff000000000000000000000000000000000000000000000000191660c060020a63ffffffff8716021790559050612d8982612eb7565b612d9281612eb7565b6000848152600a602090815260408083208054600160a060020a031990811690915586845281842080549091169055600f8054600190810190915587845260079092529182902054908301547f241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b8092600160a060020a0390921691879187916801000000000000000090910467ffffffffffffffff1690518085600160a060020a0316600160a060020a031681526020018481526020018381526020018267ffffffffffffffff16815260200194505050505060405180910390a150505050565b60005b60208210612e985782518452602084019350602083019250602082039150612e75565b6001826020036101000a03905080198351168185511617909352505050565b600554600182015443919060039060e060020a900461ffff16600e8110612eda57fe5b600891828204019190066004029054906101000a900463ffffffff1663ffffffff16811515612f0557fe5b6001840180546fffffffffffffffff0000000000000000191668010000000000000000939092049390930167ffffffffffffffff16919091021790819055600d60e060020a90910461ffff161015612f9d576001818101805461ffff60e060020a8083048216909401169092027fffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092169190911790555b50565b60206040519081016040526000815290565b60806040519081016040526004815b60008152600019919091019060200181612fc15790505090565b6101006040519081016040908152600080835260208301819052908201819052606082018190526080820181905260a0820181905260c0820181905260e082015290565b815481835581811511610fdf57600083815260209020610fdf91610ef99160029182028101918502015b808211156130635760008082556001820155600201613049565b50905600a165627a7a72305820a6465fc1ce7ab1a92906ff7206b23d80a21bbd50b85b4bde6a91f8e6b2e3edde0029" - code_ContractScenario011_deployErc721KittyCore = "6002805460a060020a60ff0219169055610240604052603c6080908152607860a05261012c60c05261025860e05261070861010052610e1061012052611c2061014052613840610160526170806101805261e1006101a052620151806101c0526202a3006101e052620546006102005262093a80610220526200008790600390600e620004e3565b50600f6005556301312d00600e55348015620000a257600080fd5b506002805460008054600160a060020a031990811633908117835560a060020a60ff0219909316740100000000000000000000000000000000000000001716909117909155620001019080806000198164010000000062000108810204565b50620005f1565b6000806200011562000586565b600063ffffffff891689146200012a57600080fd5b63ffffffff881688146200013d57600080fd5b61ffff871687146200014e57600080fd5b600287049250600d8361ffff1611156200016757600d92505b505060408051610100810182528581524267ffffffffffffffff90811660208301908152600093830184815263ffffffff8c8116606086019081528c82166080870190815260a0870188815261ffff8a811660c08a019081528f821660e08b01908152600680546001810182559c528a517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f60028e029081019190915598517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40909901805498519651955194519251915167ffffffffffffffff19909916998b1699909917604060020a608060020a0319166801000000000000000096909a169590950298909817608060020a63ffffffff021916700100000000000000000000000000000000938616939093029290921760a060020a63ffffffff02191674010000000000000000000000000000000000000000918516919091021760c060020a63ffffffff0219167801000000000000000000000000000000000000000000000000968416969096029590951760e060020a61ffff0219167c01000000000000000000000000000000000000000000000000000000009186169190910217600160f060020a03167e010000000000000000000000000000000000000000000000000000000000009290941691909102929092179055909190811681146200036f57600080fd5b606080830151608080850151855160408051600160a060020a038c1681526020810188905263ffffffff95861681830152929094169482019490945290810192909252517f0a5311bd2a6608f08a180df2ee7c5946819a649b204b554bb8e39825b2c50ad59181900360a00190a1620003f46000868364010000000062000400810204565b98975050505050505050565b600160a060020a03808316600081815260086020908152604080832080546001019055858352600790915290208054600160a060020a03191690911790558316156200049457600160a060020a03831660009081526008602090815260408083208054600019019055838352600a82528083208054600160a060020a03199081169091556009909252909120805490911690555b60408051600160a060020a0380861682528416602082015280820183905290517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360600190a1505050565b600283019183908215620005745791602002820160005b838211156200054057835183826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302620004fa565b8015620005725782816101000a81549063ffffffff021916905560040160208160030104928301926001030262000540565b505b5062000582929150620005ca565b5090565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915290565b620005ee91905b808211156200058257805463ffffffff19168155600101620005d1565b90565b6130f380620006016000396000f3006080604052600436106102a55763ffffffff60e060020a60003504166301ffc9a781146102d55780630519ce79146103205780630560ff441461035157806305e45546146103ea57806306fdde0314610411578063095ea7b3146104265780630a0f81681461044a5780630e583df01461045f57806314001f4c1461047457806318160ddd14610495578063183a7947146104aa5780631940a936146104bf57806319c2f201146104d757806321717ebf146104ec57806323b872dd1461050157806324e7a38a1461052b57806327d7874c1461054c5780632ba73c151461056d5780633d7d3f5a1461058e5780633f4ba83a146105af57806346116e6f146105c457806346d22c70146105dc578063481af3d3146105f75780634ad8c9381461060f5780634b85fd55146106305780634dfff04f146106485780634e0a33791461066c578063561291341461068d5780635663896e146106b15780635c975abb146106c95780635fd8c710146106de5780636352211e146106f3578063680eba271461070b5780636af04a57146107205780636fbde40d1461073557806370a082311461075657806371587988146107775780637a7d4937146107985780638456cb59146107ad5780638462151c146107c257806388c2a0bf1461083357806391876e571461084b57806395d89b41146108605780639d6fac6f14610875578063a45f4bfc146108a6578063a9059cbb146108be578063b047fb50146108e2578063b0c35c05146108f7578063bc4006f51461090c578063c3bea9af14610921578063d3e6f49f14610939578063defb958414610951578063e17b25af14610966578063e6cbe35114610987578063e98b7f4d1461099c578063ed60ade614610a06578063f1ca941014610a14578063f2b47d5214610a29578063f7d8c88314610a3e575b600b54600160a060020a03163314806102c85750600c54600160a060020a031633145b15156102d357600080fd5b005b3480156102e157600080fd5b5061030c7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1960043516610a4c565b604080519115158252519081900360200190f35b34801561032c57600080fd5b50610335610cdf565b60408051600160a060020a039092168252519081900360200190f35b34801561035d57600080fd5b50610375600480359060248035908101910135610cee565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103af578181015183820152602001610397565b50505050905090810190601f1680156103dc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103f657600080fd5b506103ff610df1565b60408051918252519081900360200190f35b34801561041d57600080fd5b50610375610df7565b34801561043257600080fd5b506102d3600160a060020a0360043516602435610e2e565b34801561045657600080fd5b50610335610eb0565b34801561046b57600080fd5b506103ff610ebf565b34801561048057600080fd5b506102d3600160a060020a0360043516610ec6565b3480156104a157600080fd5b506103ff610f79565b3480156104b657600080fd5b506103ff610f83565b3480156104cb57600080fd5b5061030c600435610f89565b3480156104e357600080fd5b506103ff610fce565b3480156104f857600080fd5b50610335610fd5565b34801561050d57600080fd5b506102d3600160a060020a0360043581169060243516604435610fe4565b34801561053757600080fd5b506102d3600160a060020a0360043516611060565b34801561055857600080fd5b506102d3600160a060020a0360043516611113565b34801561057957600080fd5b506102d3600160a060020a0360043516611161565b34801561059a57600080fd5b506102d36004356024356044356064356111af565b3480156105bb57600080fd5b506102d36112a4565b3480156105d057600080fd5b50610335600435611338565b3480156105e857600080fd5b5061030c600435602435611353565b34801561060357600080fd5b506103356004356113d3565b34801561061b57600080fd5b506102d36004356024356044356064356113ee565b34801561063c57600080fd5b506102d36004356114c6565b34801561065457600080fd5b506102d3600160a060020a03600435166024356114e2565b34801561067857600080fd5b506102d3600160a060020a036004351661153c565b34801561069957600080fd5b506102d3600435600160a060020a036024351661158a565b3480156106bd57600080fd5b506102d36004356115f1565b3480156106d557600080fd5b5061030c61164d565b3480156106ea57600080fd5b506102d361165d565b3480156106ff57600080fd5b506103356004356116c1565b34801561071757600080fd5b506103ff6116e5565b34801561072c57600080fd5b506103356116eb565b34801561074157600080fd5b506102d3600160a060020a03600435166116fa565b34801561076257600080fd5b506103ff600160a060020a03600435166117ad565b34801561078357600080fd5b506102d3600160a060020a03600435166117c8565b3480156107a457600080fd5b506103ff61184b565b3480156107b957600080fd5b506102d3611851565b3480156107ce57600080fd5b506107e3600160a060020a03600435166118d1565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561081f578181015183820152602001610807565b505050509050019250505060405180910390f35b34801561083f57600080fd5b506103ff6004356119a3565b34801561085757600080fd5b506102d3611c7f565b34801561086c57600080fd5b50610375611d94565b34801561088157600080fd5b5061088d600435611dcb565b6040805163ffffffff9092168252519081900360200190f35b3480156108b257600080fd5b50610335600435611df8565b3480156108ca57600080fd5b506102d3600160a060020a0360043516602435611e13565b3480156108ee57600080fd5b50610335611eab565b34801561090357600080fd5b506103ff611eba565b34801561091857600080fd5b50610335611ec0565b34801561092d57600080fd5b506102d3600435611ecf565b34801561094557600080fd5b5061030c600435611fb9565b34801561095d57600080fd5b506103ff612088565b34801561097257600080fd5b506102d3600160a060020a036004351661208e565b34801561099357600080fd5b506103356120c7565b3480156109a857600080fd5b506109b46004356120d6565b604080519a15158b5298151560208b0152898901979097526060890195909552608088019390935260a087019190915260c086015260e085015261010084015261012083015251908190036101400190f35b6102d3600435602435612237565b348015610a2057600080fd5b506103ff6123d1565b348015610a3557600080fd5b506103356123d7565b6102d36004356024356123e6565b604080517f737570706f727473496e74657266616365286279746573342900000000000000815290519081900360190190206000907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1983811691161480610cd75750604080517f746f6b656e4d657461646174612875696e743235362c737472696e67290000008152815190819003601d0181207f746f6b656e734f664f776e657228616464726573732900000000000000000000825282519182900360160182207f7472616e7366657246726f6d28616464726573732c616464726573732c75696e83527f7432353629000000000000000000000000000000000000000000000000000000602084015283519283900360250183207f7472616e7366657228616464726573732c75696e743235362900000000000000845284519384900360190184207f617070726f766528616464726573732c75696e74323536290000000000000000855285519485900360180185207f6f776e65724f662875696e743235362900000000000000000000000000000000865286519586900360100186207f62616c616e63654f662861646472657373290000000000000000000000000000875287519687900360120187207f746f74616c537570706c792829000000000000000000000000000000000000008852885197889003600d0188207f73796d626f6c2829000000000000000000000000000000000000000000000000895289519889900360080189207f6e616d65282900000000000000000000000000000000000000000000000000008a529951988990036006019098207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff198c811691909a189098181818181818181891909116145b90505b919050565b600154600160a060020a031681565b6060610cf8613064565b600d54600090600160a060020a03161515610d1257600080fd5b600d54604080517fcb4799f2000000000000000000000000000000000000000000000000000000008152600481018981526024820192835260448201889052600160a060020a039093169263cb4799f2928a928a928a929091606401848480828437820191505094505050505060a060405180830381600087803b158015610d9957600080fd5b505af1158015610dad573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525060a0811015610dd257600080fd5b5060808101519092509050610de782826125e4565b9695505050505050565b60115481565b60408051808201909152600d81527f43727970746f4b69747469657300000000000000000000000000000000000000602082015281565b60025460a060020a900460ff1615610e4557600080fd5b610e4f3382612638565b1515610e5a57600080fd5b610e648183612658565b60408051338152600160a060020a038416602082015280820183905290517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360600190a15050565b600054600160a060020a031681565b6298968081565b60008054600160a060020a03163314610ede57600080fd5b81905080600160a060020a03166376190f8f6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015610f1f57600080fd5b505af1158015610f33573d6000803e3d6000fd5b505050506040513d6020811015610f4957600080fd5b50511515610f5657600080fd5b600c8054600160a060020a031916600160a060020a039290921691909117905550565b6006546000190190565b600f5481565b6000808211610f9757600080fd5b6006805483908110610fa557fe5b600091825260209091206002909102016001015460c060020a900463ffffffff16151592915050565b6201518081565b600c54600160a060020a031681565b60025460a060020a900460ff1615610ffb57600080fd5b600160a060020a038216151561101057600080fd5b600160a060020a03821630141561102657600080fd5b6110303382612686565b151561103b57600080fd5b6110458382612638565b151561105057600080fd5b61105b8383836126a6565b505050565b60008054600160a060020a0316331461107857600080fd5b81905080600160a060020a03166354c15b826040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156110b957600080fd5b505af11580156110cd573d6000803e3d6000fd5b505050506040513d60208110156110e357600080fd5b505115156110f057600080fd5b60108054600160a060020a031916600160a060020a039290921691909117905550565b600054600160a060020a0316331461112a57600080fd5b600160a060020a038116151561113f57600080fd5b60008054600160a060020a031916600160a060020a0392909216919091179055565b600054600160a060020a0316331461117857600080fd5b600160a060020a038116151561118d57600080fd5b60028054600160a060020a031916600160a060020a0392909216919091179055565b60025460a060020a900460ff16156111c657600080fd5b6111d03385612638565b15156111db57600080fd5b6111e484610f89565b156111ee57600080fd5b600b54611205908590600160a060020a0316612658565b600b54604080517f27ebe40a000000000000000000000000000000000000000000000000000000008152600481018790526024810186905260448101859052606481018490523360848201529051600160a060020a03909216916327ebe40a9160a48082019260009290919082900301818387803b15801561128657600080fd5b505af115801561129a573d6000803e3d6000fd5b5050505050505050565b600054600160a060020a031633146112bb57600080fd5b60025460a060020a900460ff1615156112d357600080fd5b600b54600160a060020a031615156112ea57600080fd5b600c54600160a060020a0316151561130157600080fd5b601054600160a060020a0316151561131857600080fd5b601354600160a060020a03161561132e57600080fd5b611336612788565b565b600a60205260009081526040902054600160a060020a031681565b6000808080851161136357600080fd5b6000841161137057600080fd5b600680548690811061137e57fe5b9060005260206000209060020201915060068481548110151561139d57fe5b906000526020600020906002020190506113b9828683876127d7565b80156113ca57506113ca8486612957565b95945050505050565b600960205260009081526040902054600160a060020a031681565b60025460a060020a900460ff161561140557600080fd5b61140f3385612638565b151561141a57600080fd5b61142384611fb9565b151561142e57600080fd5b600c54611445908590600160a060020a0316612658565b600c54604080517f27ebe40a000000000000000000000000000000000000000000000000000000008152600481018790526024810186905260448101859052606481018490523360848201529051600160a060020a03909216916327ebe40a9160a48082019260009290919082900301818387803b15801561128657600080fd5b600254600160a060020a031633146114dd57600080fd5b600e55565b60025460a060020a900460ff16156114f957600080fd5b6115033382612638565b151561150e57600080fd5b6000908152600a602052604090208054600160a060020a031916600160a060020a0392909216919091179055565b600054600160a060020a0316331461155357600080fd5b600160a060020a038116151561156857600080fd5b60018054600160a060020a031916600160a060020a0392909216919091179055565b600254600090600160a060020a031633146115a457600080fd5b5080600160a060020a03811615156115c45750600254600160a060020a03165b601154611388116115d457600080fd5b6011805460010190556115eb6000808086856129ac565b50505050565b600254600160a060020a03163314806116145750600054600160a060020a031633145b806116295750600154600160a060020a031633145b151561163457600080fd5b60035463ffffffff16811061164857600080fd5b600555565b60025460a060020a900460ff1681565b6001546000908190600160a060020a0316331461167957600080fd5b5050600e54600f54303191600190910102808211156116bd57600154604051600160a060020a039091169082840380156108fc02916000818181858888f150505050505b5050565b600081815260076020526040902054600160a060020a0316801515610cda57600080fd5b61afc881565b601354600160a060020a031681565b60008054600160a060020a0316331461171257600080fd5b81905080600160a060020a03166385b861886040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561175357600080fd5b505af1158015611767573d6000803e3d6000fd5b505050506040513d602081101561177d57600080fd5b5051151561178a57600080fd5b600b8054600160a060020a031916600160a060020a039290921691909117905550565b600160a060020a031660009081526008602052604090205490565b600054600160a060020a031633146117df57600080fd5b60025460a060020a900460ff1615156117f757600080fd5b60138054600160a060020a038316600160a060020a0319909116811790915560408051918252517f450db8da6efbe9c22f2347f7c2021231df1fc58d3ae9a2fa75d39fa4461993059181900360200190a150565b60055481565b600254600160a060020a03163314806118745750600054600160a060020a031633145b806118895750600154600160a060020a031633145b151561189457600080fd5b60025460a060020a900460ff16156118ab57600080fd5b6002805474ff0000000000000000000000000000000000000000191660a060020a179055565b60606000606060008060006118e5876117ad565b9450841515611904576040805160008152602081019091529550611999565b8460405190808252806020026020018201604052801561192e578160200160208202803883390190505b509350611939610f79565b925060009150600190505b82811161199557600081815260076020526040902054600160a060020a038881169116141561198d5780848381518110151561197c57fe5b602090810290910101526001909101905b600101611944565b8395505b5050505050919050565b600080600080600080600080600260149054906101000a900460ff161515156119cb57600080fd5b600680548a9081106119d957fe5b60009182526020909120600290910201600181015490975067ffffffffffffffff161515611a0657600080fd5b604080516101008101825288548152600189015467ffffffffffffffff8082166020840152680100000000000000008204169282019290925263ffffffff608060020a83048116606083015260a060020a83048116608083015260c060020a83041660a082015261ffff60e060020a8304811660c083015260f060020a90920490911660e0820152611a9790612c89565b1515611aa257600080fd5b60018701546006805460c060020a90920463ffffffff1697509087908110611ac657fe5b600091825260209091206001808a015460029093029091019081015490965061ffff60f060020a928390048116965091900416841015611b1357600185015460f060020a900461ffff1693505b6010548754865460018a0154604080517f0d9f5aed0000000000000000000000000000000000000000000000000000000081526004810194909452602484019290925260001967ffffffffffffffff6801000000000000000090920482160116604483015251600160a060020a0390921691630d9f5aed916064808201926020929091908290030181600087803b158015611bad57600080fd5b505af1158015611bc1573d6000803e3d6000fd5b505050506040513d6020811015611bd757600080fd5b505160008a815260076020526040902054600189810154929550600160a060020a039091169350611c20918b9160c060020a90910463ffffffff1690870161ffff1686866129ac565b6001880180547bffffffff00000000000000000000000000000000000000000000000019169055600f8054600019019055600e54604051919250339181156108fc0291906000818181858888f150939c9b505050505050505050505050565b600254600160a060020a0316331480611ca25750600054600160a060020a031633145b80611cb75750600154600160a060020a031633145b1515611cc257600080fd5b600b60009054906101000a9004600160a060020a0316600160a060020a0316635fd8c7106040518163ffffffff1660e060020a028152600401600060405180830381600087803b158015611d1557600080fd5b505af1158015611d29573d6000803e3d6000fd5b50505050600c60009054906101000a9004600160a060020a0316600160a060020a0316635fd8c7106040518163ffffffff1660e060020a028152600401600060405180830381600087803b158015611d8057600080fd5b505af11580156115eb573d6000803e3d6000fd5b60408051808201909152600281527f434b000000000000000000000000000000000000000000000000000000000000602082015281565b600381600e8110611dd857fe5b60089182820401919006600402915054906101000a900463ffffffff1681565b600760205260009081526040902054600160a060020a031681565b60025460a060020a900460ff1615611e2a57600080fd5b600160a060020a0382161515611e3f57600080fd5b600160a060020a038216301415611e5557600080fd5b600b54600160a060020a0383811691161415611e7057600080fd5b600c54600160a060020a0383811691161415611e8b57600080fd5b611e953382612638565b1515611ea057600080fd5b6116bd3383836126a6565b600254600160a060020a031681565b600e5481565b600d54600160a060020a031681565b600254600090600160a060020a03163314611ee957600080fd5b60125461afc811611ef957600080fd5b611f08600080600085306129ac565b600b54909150611f22908290600160a060020a0316612658565b600b54600160a060020a03166327ebe40a82611f3c612cb9565b6040805160e060020a63ffffffff861602815260048101939093526024830191909152600060448301819052620151806064840152306084840152905160a48084019382900301818387803b158015611f9457600080fd5b505af1158015611fa8573d6000803e3d6000fd5b505060128054600101905550505050565b600080808311611fc857600080fd5b6006805484908110611fd657fe5b60009182526020918290206040805161010081018252600290930290910180548352600181015467ffffffffffffffff808216958501959095526801000000000000000081049094169183019190915263ffffffff608060020a84048116606084015260a060020a84048116608084015260c060020a84041660a083015261ffff60e060020a8404811660c084015260f060020a90930490921660e082015290915061208190612d7b565b9392505050565b61138881565b600054600160a060020a031633146120a557600080fd5b600d8054600160a060020a031916600160a060020a0392909216919091179055565b600b54600160a060020a031681565b600080600080600080600080600080600060068c8154811015156120f657fe5b906000526020600020906002020190508060010160189054906101000a900463ffffffff1663ffffffff16600014159a50438160010160089054906101000a900467ffffffffffffffff1667ffffffffffffffff161115995080600101601c9054906101000a900461ffff1661ffff1698508060010160089054906101000a900467ffffffffffffffff1667ffffffffffffffff1697508060010160189054906101000a900463ffffffff1663ffffffff1696508060010160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1695508060010160109054906101000a900463ffffffff1663ffffffff1694508060010160149054906101000a900463ffffffff1663ffffffff16935080600101601e9054906101000a900461ffff1661ffff16925080600001549150509193959799509193959799565b60025460009060a060020a900460ff161561225157600080fd5b61225b3383612638565b151561226657600080fd5b61226f82611fb9565b151561227a57600080fd5b6122848284612daa565b151561228f57600080fd5b600c54604080517fc55d0f56000000000000000000000000000000000000000000000000000000008152600481018690529051600160a060020a039092169163c55d0f56916024808201926020929091908290030181600087803b1580156122f657600080fd5b505af115801561230a573d6000803e3d6000fd5b505050506040513d602081101561232057600080fd5b5051600e54909150810134101561233657600080fd5b600c54600e54604080517f454a2ab3000000000000000000000000000000000000000000000000000000008152600481018790529051600160a060020a039093169263454a2ab39234039160248082019260009290919082900301818588803b1580156123a257600080fd5b505af11580156123b6573d6000803e3d6000fd5b505050505061105b8263ffffffff168463ffffffff16612df9565b60125481565b601054600160a060020a031681565b600254600090819060a060020a900460ff161561240257600080fd5b600e5434101561241157600080fd5b61241b3385612638565b151561242657600080fd5b6124308385612957565b151561243b57600080fd5b600680548590811061244957fe5b60009182526020918290206040805161010081018252600290930290910180548352600181015467ffffffffffffffff808216958501959095526801000000000000000081049094169183019190915263ffffffff608060020a84048116606084015260a060020a84048116608084015260c060020a84041660a083015261ffff60e060020a8404811660c084015260f060020a90930490921660e08201529092506124f490612d7b565b15156124ff57600080fd5b600680548490811061250d57fe5b60009182526020918290206040805161010081018252600290930290910180548352600181015467ffffffffffffffff808216958501959095526801000000000000000081049094169183019190915263ffffffff608060020a84048116606084015260a060020a84048116608084015260c060020a84041660a083015261ffff60e060020a8404811660c084015260f060020a90930490921660e08201529091506125b890612d7b565b15156125c357600080fd5b6125cf828583866127d7565b15156125da57600080fd5b6115eb8484612df9565b606080600080846040519080825280601f01601f191660200182016040528015612618578160200160208202803883390190505b509250506020820190508461262e828287612f37565b5090949350505050565b600090815260076020526040902054600160a060020a0391821691161490565b6000918252600960205260409091208054600160a060020a031916600160a060020a03909216919091179055565b600090815260096020526040902054600160a060020a0391821691161490565b600160a060020a03808316600081815260086020908152604080832080546001019055858352600790915290208054600160a060020a031916909117905583161561273957600160a060020a03831660009081526008602090815260408083208054600019019055838352600a82528083208054600160a060020a03199081169091556009909252909120805490911690555b60408051600160a060020a0380861682528416602082015280820183905290517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360600190a1505050565b600054600160a060020a0316331461279f57600080fd5b60025460a060020a900460ff1615156127b757600080fd5b6002805474ff000000000000000000000000000000000000000019169055565b6000818414156127e95750600061294f565b6001850154608060020a900463ffffffff168214806128185750600185015460a060020a900463ffffffff1682145b156128255750600061294f565b6001830154608060020a900463ffffffff168414806128545750600183015460a060020a900463ffffffff1684145b156128615750600061294f565b6001830154608060020a900463ffffffff16158061288e57506001850154608060020a900463ffffffff16155b1561289b5750600161294f565b60018581015490840154608060020a9182900463ffffffff908116929091041614806128e6575060018086015490840154608060020a900463ffffffff90811660a060020a90920416145b156128f35750600061294f565b6001808601549084015460a060020a900463ffffffff908116608060020a90920416148061293e57506001858101549084015460a060020a9182900463ffffffff9081169290910416145b1561294b5750600061294f565b5060015b949350505050565b6000818152600760205260408082205484835290822054600160a060020a039182169116808214806113ca57506000858152600a6020526040902054600160a060020a03908116908316149250505092915050565b6000806129b7613083565b600063ffffffff891689146129cb57600080fd5b63ffffffff881688146129dd57600080fd5b61ffff871687146129ed57600080fd5b600287049250600d8361ffff161115612a0557600d92505b505060408051610100810182528581524267ffffffffffffffff90811660208301908152600093830184815263ffffffff8c8116606086019081528c82166080870190815260a0870188815261ffff8a811660c08a019081528f821660e08b01908152600680546001810182559c528a517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f60028e029081019190915598517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40909901805498519651955194519251915167ffffffffffffffff19909916998b16999099176fffffffffffffffff000000000000000019166801000000000000000096909a16959095029890981773ffffffff000000000000000000000000000000001916608060020a938616939093029290921777ffffffff0000000000000000000000000000000000000000191660a060020a91851691909102177bffffffff000000000000000000000000000000000000000000000000191660c060020a96841696909602959095177fffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660e060020a91861691909102177dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f060020a929094169190910292909217905590919081168114612c0357600080fd5b606080830151608080850151855160408051600160a060020a038c1681526020810188905263ffffffff95861681830152929094169482019490945290810192909252517f0a5311bd2a6608f08a180df2ee7c5946819a649b204b554bb8e39825b2c50ad59181900360a00190a1612c7d600086836126a6565b98975050505050505050565b60008160a0015163ffffffff16600014158015610cd75750506040015167ffffffffffffffff4381169116111590565b6000806000600b60009054906101000a9004600160a060020a0316600160a060020a031663eac9d94c6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015612d1157600080fd5b505af1158015612d25573d6000803e3d6000fd5b505050506040513d6020811015612d3b57600080fd5b505191506fffffffffffffffffffffffffffffffff82168214612d5d57600080fd5b5060028104810162989680811015612d755750629896805b92915050565b60008160a0015163ffffffff166000148015610cd75750506040015167ffffffffffffffff4381169116111590565b6000806000600685815481101515612dbe57fe5b90600052602060002090600202019150600684815481101515612ddd57fe5b906000526020600020906002020190506113ca828683876127d7565b600080600683815481101515612e0b57fe5b90600052602060002090600202019150600684815481101515612e2a57fe5b600091825260209091206002909102016001810180547bffffffff000000000000000000000000000000000000000000000000191660c060020a63ffffffff8716021790559050612e7a82612f7b565b612e8381612f7b565b6000848152600a602090815260408083208054600160a060020a031990811690915586845281842080549091169055600f80546001908101909155878452600783529281902054928401548151600160a060020a0390941684529183018790528281018690526801000000000000000090910467ffffffffffffffff166060830152517f241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b80916080908290030190a150505050565b60005b60208210612f5c578251845260209384019390920191601f1990910190612f3a565b50905182516020929092036101000a6000190180199091169116179052565b600554600182015443919060039060e060020a900461ffff16600e8110612f9e57fe5b600891828204019190066004029054906101000a900463ffffffff1663ffffffff16811515612fc957fe5b6001840180546fffffffffffffffff0000000000000000191668010000000000000000939092049390930167ffffffffffffffff16919091021790819055600d60e060020a90910461ffff161015613061576001818101805461ffff60e060020a8083048216909401169092027fffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092169190911790555b50565b6080604051908101604052806004906020820280388339509192915050565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152905600a165627a7a723058201424bf1db41fa7ec76f5506a53d8bbcb84ed5b5a6ade2df0bac8deaacb118a8b0029" - code_ContractScenario011_deploySaleClockAuction = "60806040526000805460a060020a60ff02191690556004805460ff1916600117905534801561002d57600080fd5b50604051604080610ee883398101604052805160209091015160008054600160a060020a031916331781558290829061271082111561006b57600080fd5b506002819055604080517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f9a20483d00000000000000000000000000000000000000000000000000000000600482015290518391600160a060020a038316916301ffc9a7916024808201926020929091908290030181600087803b1580156100f557600080fd5b505af1158015610109573d6000803e3d6000fd5b505050506040513d602081101561011f57600080fd5b5051151561012c57600080fd5b60018054600160a060020a03909216600160a060020a031990921691909117905550505050610d88806101606000396000f3006080604052600436106100fb5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166327ebe40a81146101005780633f4ba83a1461012f578063454a2ab314610158578063484eccb4146101635780635c975abb1461018d5780635fd8c710146101a257806378bd7935146101b757806383b5ff8b146102045780638456cb591461021957806385b861881461022e578063878eb368146102435780638a98a9cc1461025b5780638da5cb5b1461027057806396b5a755146102a1578063c55d0f56146102b9578063dd1b7a0f146102d1578063eac9d94c146102e6578063f2fde38b146102fb575b600080fd5b34801561010c57600080fd5b5061012d600435602435604435606435600160a060020a036084351661031c565b005b34801561013b57600080fd5b50610144610414565b604080519115158252519081900360200190f35b61012d60043561048f565b34801561016f57600080fd5b5061017b6004356104f9565b60408051918252519081900360200190f35b34801561019957600080fd5b5061014461050d565b3480156101ae57600080fd5b5061012d61051d565b3480156101c357600080fd5b506101cf60043561057a565b60408051600160a060020a03909616865260208601949094528484019290925260608401526080830152519081900360a00190f35b34801561021057600080fd5b5061017b610610565b34801561022557600080fd5b50610144610616565b34801561023a57600080fd5b50610144610696565b34801561024f57600080fd5b5061012d60043561069f565b34801561026757600080fd5b5061017b61070c565b34801561027c57600080fd5b50610285610712565b60408051600160a060020a039092168252519081900360200190f35b3480156102ad57600080fd5b5061012d600435610721565b3480156102c557600080fd5b5061017b600435610766565b3480156102dd57600080fd5b50610285610798565b3480156102f257600080fd5b5061017b6107a7565b34801561030757600080fd5b5061012d600160a060020a03600435166107db565b610324610d2e565b6fffffffffffffffffffffffffffffffff8516851461034257600080fd5b6fffffffffffffffffffffffffffffffff8416841461036057600080fd5b67ffffffffffffffff8316831461037657600080fd5b600154600160a060020a0316331461038d57600080fd5b610397828761082d565b60a06040519081016040528083600160a060020a03168152602001866fffffffffffffffffffffffffffffffff168152602001856fffffffffffffffffffffffffffffffff1681526020018467ffffffffffffffff1681526020014267ffffffffffffffff16815250905061040c86826108b5565b505050505050565b60008054600160a060020a0316331461042c57600080fd5b60005460a060020a900460ff16151561044457600080fd5b6000805474ff0000000000000000000000000000000000000000191681556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b339190a150600190565b600081815260036020526040812054600160a060020a0316906104b28334610a09565b90506104be3384610b2f565b600154600160a060020a03838116911614156104f45760058054829160069106600581106104e857fe5b01556005805460010190555b505050565b6006816005811061050657fe5b0154905081565b60005460a060020a900460ff1681565b60015460008054600160a060020a039283169216331480610546575033600160a060020a038316145b151561055157600080fd5b604051600160a060020a03831690303180156108fc02916000818181858888f150505050505050565b6000818152600360205260408120819081908190819061059981610b9d565b15156105a457600080fd5b80546001820154600290920154600160a060020a03909116986fffffffffffffffffffffffffffffffff8084169950700100000000000000000000000000000000909304909216965067ffffffffffffffff808216965068010000000000000000909104169350915050565b60025481565b60008054600160a060020a0316331461062e57600080fd5b60005460a060020a900460ff161561064557600080fd5b6000805474ff0000000000000000000000000000000000000000191660a060020a1781556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff6259190a150600190565b60045460ff1681565b6000805460a060020a900460ff1615156106b857600080fd5b600054600160a060020a031633146106cf57600080fd5b5060008181526003602052604090206106e781610b9d565b15156106f257600080fd5b8054610708908390600160a060020a0316610bbe565b5050565b60055481565b600054600160a060020a031681565b60008181526003602052604081209061073982610b9d565b151561074457600080fd5b508054600160a060020a031633811461075c57600080fd5b6104f48382610bbe565b600081815260036020526040812061077d81610b9d565b151561078857600080fd5b61079181610c08565b9392505050565b600154600160a060020a031681565b600080805b60058110156107d157600681600581106107c257fe5b015491909101906001016107ac565b5060059004919050565b600054600160a060020a031633146107f257600080fd5b600160a060020a0381161561082a576000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b50565b600154604080517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a03858116600483015230602483015260448201859052915191909216916323b872dd91606480830192600092919082900301818387803b1580156108a157600080fd5b505af115801561040c573d6000803e3d6000fd5b603c816060015167ffffffffffffffff16101515156108d357600080fd5b60008281526003602090815260409182902083518154600160a060020a0390911673ffffffffffffffffffffffffffffffffffffffff1990911617815581840151600182018054858701516fffffffffffffffffffffffffffffffff90811670010000000000000000000000000000000081029482166fffffffffffffffffffffffffffffffff19909316831790911693909317909155606080870151600290940180546080808a015167ffffffffffffffff90811668010000000000000000026fffffffffffffffff0000000000000000199190981667ffffffffffffffff1990931683171696909617909155865189815295860192909252848601929092529083015291517fa9c8dfcda5664a5a124c713e386da27de87432d5b668e79458501eb296389ba7929181900390910190a15050565b60008281526003602052604081208180808080610a2586610b9d565b1515610a3057600080fd5b610a3986610c08565b945084881015610a4857600080fd5b8554600160a060020a03169350610a5e89610c98565b6000851115610ab057610a7085610ce5565b6040519093508386039250600160a060020a0385169083156108fc029084906000818181858888f19350505050158015610aae573d6000803e3d6000fd5b505b5060405184880390339082156108fc029083906000818181858888f19350505050158015610ae2573d6000803e3d6000fd5b50604080518a815260208101879052338183015290517f4fcc30d90a842164dd58501ab874a101a3749c3d4747139cefe7c876f4ccebd29181900360600190a15092979650505050505050565b600154604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a038581166004830152602482018590529151919092169163a9059cbb91604480830192600092919082900301818387803b1580156108a157600080fd5b6002015460006801000000000000000090910467ffffffffffffffff161190565b610bc782610c98565b610bd18183610b2f565b6040805183815290517f2809c7e17bf978fbc7194c0a694b638c4215e9140cacc6c38ca36010b45697df9181900360200190a15050565b6002810154600090819068010000000000000000900467ffffffffffffffff16421115610c4e5750600282015468010000000000000000900467ffffffffffffffff1642035b60018301546002840154610791916fffffffffffffffffffffffffffffffff80821692700100000000000000000000000000000000909204169067ffffffffffffffff1684610cf1565b6000908152600360205260408120805473ffffffffffffffffffffffffffffffffffffffff19168155600181019190915560020180546fffffffffffffffffffffffffffffffff19169055565b60025461271091020490565b6000808080858510610d0557869350610d23565b878703925085858402811515610d1757fe5b05915081880190508093505b505050949350505050565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152905600a165627a7a723058203c3d7d4039d9d9a82dd65c7bc046590e8fe3580af952a66fe24052959889bef50029" - code_ContractScenario011_deploySiringClockAuction = "60806040526000805460a060020a60ff02191690556004805460ff1916600117905534801561002d57600080fd5b50604051604080610e1a83398101604052805160209091015160008054600160a060020a031916331781558290829061271082111561006b57600080fd5b506002819055604080517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f9a20483d00000000000000000000000000000000000000000000000000000000600482015290518391600160a060020a038316916301ffc9a7916024808201926020929091908290030181600087803b1580156100f557600080fd5b505af1158015610109573d6000803e3d6000fd5b505050506040513d602081101561011f57600080fd5b5051151561012c57600080fd5b60018054600160a060020a03909216600160a060020a031990921691909117905550505050610cba806101606000396000f3006080604052600436106100da5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166327ebe40a81146100df5780633f4ba83a1461010e578063454a2ab3146101375780635c975abb146101425780635fd8c7101461015757806376190f8f1461016c57806378bd79351461018157806383b5ff8b146101ce5780638456cb59146101f5578063878eb3681461020a5780638da5cb5b1461022257806396b5a75514610253578063c55d0f561461026b578063dd1b7a0f14610283578063f2fde38b14610298575b600080fd5b3480156100eb57600080fd5b5061010c600435602435604435606435600160a060020a03608435166102b9565b005b34801561011a57600080fd5b506101236103b1565b604080519115158252519081900360200190f35b61010c60043561042c565b34801561014e57600080fd5b50610123610478565b34801561016357600080fd5b5061010c610488565b34801561017857600080fd5b506101236104e5565b34801561018d57600080fd5b506101996004356104ee565b60408051600160a060020a03909616865260208601949094528484019290925260608401526080830152519081900360a00190f35b3480156101da57600080fd5b506101e3610584565b60408051918252519081900360200190f35b34801561020157600080fd5b5061012361058a565b34801561021657600080fd5b5061010c60043561060a565b34801561022e57600080fd5b50610237610673565b60408051600160a060020a039092168252519081900360200190f35b34801561025f57600080fd5b5061010c600435610682565b34801561027757600080fd5b506101e36004356106cc565b34801561028f57600080fd5b506102376106fe565b3480156102a457600080fd5b5061010c600160a060020a036004351661070d565b6102c1610c60565b6fffffffffffffffffffffffffffffffff851685146102df57600080fd5b6fffffffffffffffffffffffffffffffff841684146102fd57600080fd5b67ffffffffffffffff8316831461031357600080fd5b600154600160a060020a0316331461032a57600080fd5b610334828761075f565b60a06040519081016040528083600160a060020a03168152602001866fffffffffffffffffffffffffffffffff168152602001856fffffffffffffffffffffffffffffffff1681526020018467ffffffffffffffff1681526020014267ffffffffffffffff1681525090506103a986826107e7565b505050505050565b60008054600160a060020a031633146103c957600080fd5b60005460a060020a900460ff1615156103e157600080fd5b6000805474ff0000000000000000000000000000000000000000191681556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b339190a150600190565b600154600090600160a060020a0316331461044657600080fd5b50600081815260036020526040902054600160a060020a0316610469823461093b565b506104748183610a61565b5050565b60005460a060020a900460ff1681565b60015460008054600160a060020a0392831692163314806104b1575033600160a060020a038316145b15156104bc57600080fd5b604051600160a060020a03831690303180156108fc02916000818181858888f150505050505050565b60045460ff1681565b6000818152600360205260408120819081908190819061050d81610acf565b151561051857600080fd5b80546001820154600290920154600160a060020a03909116986fffffffffffffffffffffffffffffffff8084169950700100000000000000000000000000000000909304909216965067ffffffffffffffff808216965068010000000000000000909104169350915050565b60025481565b60008054600160a060020a031633146105a257600080fd5b60005460a060020a900460ff16156105b957600080fd5b6000805474ff0000000000000000000000000000000000000000191660a060020a1781556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff6259190a150600190565b6000805460a060020a900460ff16151561062357600080fd5b600054600160a060020a0316331461063a57600080fd5b50600081815260036020526040902061065281610acf565b151561065d57600080fd5b8054610474908390600160a060020a0316610af0565b600054600160a060020a031681565b60008181526003602052604081209061069a82610acf565b15156106a557600080fd5b508054600160a060020a03163381146106bd57600080fd5b6106c78382610af0565b505050565b60008181526003602052604081206106e381610acf565b15156106ee57600080fd5b6106f781610b3a565b9392505050565b600154600160a060020a031681565b600054600160a060020a0316331461072457600080fd5b600160a060020a0381161561075c576000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b50565b600154604080517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a03858116600483015230602483015260448201859052915191909216916323b872dd91606480830192600092919082900301818387803b1580156107d357600080fd5b505af11580156103a9573d6000803e3d6000fd5b603c816060015167ffffffffffffffff161015151561080557600080fd5b60008281526003602090815260409182902083518154600160a060020a0390911673ffffffffffffffffffffffffffffffffffffffff1990911617815581840151600182018054858701516fffffffffffffffffffffffffffffffff90811670010000000000000000000000000000000081029482166fffffffffffffffffffffffffffffffff19909316831790911693909317909155606080870151600290940180546080808a015167ffffffffffffffff90811668010000000000000000026fffffffffffffffff0000000000000000199190981667ffffffffffffffff1990931683171696909617909155865189815295860192909252848601929092529083015291517fa9c8dfcda5664a5a124c713e386da27de87432d5b668e79458501eb296389ba7929181900390910190a15050565b6000828152600360205260408120818080808061095786610acf565b151561096257600080fd5b61096b86610b3a565b94508488101561097a57600080fd5b8554600160a060020a0316935061099089610bca565b60008511156109e2576109a285610c17565b6040519093508386039250600160a060020a0385169083156108fc029084906000818181858888f193505050501580156109e0573d6000803e3d6000fd5b505b5060405184880390339082156108fc029083906000818181858888f19350505050158015610a14573d6000803e3d6000fd5b50604080518a815260208101879052338183015290517f4fcc30d90a842164dd58501ab874a101a3749c3d4747139cefe7c876f4ccebd29181900360600190a15092979650505050505050565b600154604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a038581166004830152602482018590529151919092169163a9059cbb91604480830192600092919082900301818387803b1580156107d357600080fd5b6002015460006801000000000000000090910467ffffffffffffffff161190565b610af982610bca565b610b038183610a61565b6040805183815290517f2809c7e17bf978fbc7194c0a694b638c4215e9140cacc6c38ca36010b45697df9181900360200190a15050565b6002810154600090819068010000000000000000900467ffffffffffffffff16421115610b805750600282015468010000000000000000900467ffffffffffffffff1642035b600183015460028401546106f7916fffffffffffffffffffffffffffffffff80821692700100000000000000000000000000000000909204169067ffffffffffffffff1684610c23565b6000908152600360205260408120805473ffffffffffffffffffffffffffffffffffffffff19168155600181019190915560020180546fffffffffffffffffffffffffffffffff19169055565b60025461271091020490565b6000808080858510610c3757869350610c55565b878703925085858402811515610c4957fe5b05915081880190508093505b505050949350505050565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152905600a165627a7a723058208d1842c4569ecc7005642ae981f6c77b856b1d9a921f3792bdb4219144ae25e00029" - code_ContractScenario011_deployGeneScienceInterface = "608060405234801561001057600080fd5b5060dc8061001f6000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630d9f5aed8114604d57806354c15b8214607a575b600080fd5b348015605857600080fd5b50606860043560243560443560a0565b60408051918252519081900360200190f35b348015608557600080fd5b50608c60ab565b604080519115158252519081900360200190f35b600292909101010490565b6001905600a165627a7a72305820d9550024d511527e5124d542daf0a0f3168b9bece6a238bcbccba8b61d3f0bdb0029" - code_WalletTestAccount012_storageAndCpu = "608060405234801561001057600080fd5b5061045c806100206000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806304c58438146100725780634f2be91f1461009f578063812db772146100b657806393cd5755146100e3578063d1cd64e914610189575b600080fd5b34801561007e57600080fd5b5061009d600480360381019080803590602001909291905050506101a0565b005b3480156100ab57600080fd5b506100b4610230565b005b3480156100c257600080fd5b506100e1600480360381019080803590602001909291905050506102a2565b005b3480156100ef57600080fd5b5061010e600480360381019080803590602001909291905050506102c3565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561014e578082015181840152602081019050610133565b50505050905090810190601f16801561017b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561019557600080fd5b5061019e61037e565b005b6000600190505b8181101561022c5760008060018154018082558091505090600182039060005260206000200160006040805190810160405280600881526020017f31323334353637380000000000000000000000000000000000000000000000008152509091909150908051906020019061021d92919061038b565b505080806001019150506101a7565b5050565b60008060018154018082558091505090600182039060005260206000200160006040805190810160405280600881526020017f61626364656667680000000000000000000000000000000000000000000000008152509091909150908051906020019061029e92919061038b565b5050565b6000600190505b81811115156102bf5780806001019150506102a9565b5050565b6000818154811015156102d257fe5b906000526020600020016000915090508054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103765780601f1061034b57610100808354040283529160200191610376565b820191906000526020600020905b81548152906001019060200180831161035957829003601f168201915b505050505081565b6000808060010191505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106103cc57805160ff19168380011785556103fa565b828001600101855582156103fa579182015b828111156103f95782518255916020019190600101906103de565b5b509050610407919061040b565b5090565b61042d91905b80821115610429576000816000905550600101610411565b5090565b905600a165627a7a7230582087d9880a135295a17100f63b8941457f4369204d3ccc9ce4a1abf99820eb68480029" - code_TestExceptionCodeAndAbi_testtimeout = "6080604052600060035534801561001557600080fd5b5061027b806100256000396000f3006080604052600436106100825763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633755cd3c81146100875780637d965688146100b1578063a05b2577146100c9578063b0d6304d146100e1578063bbe1d75b14610115578063f8a8fd6d1461012a578063fe75faab14610141575b600080fd5b34801561009357600080fd5b5061009f600435610159565b60408051918252519081900360200190f35b3480156100bd57600080fd5b5061009f600435610178565b3480156100d557600080fd5b5061009f600435610198565b3480156100ed57600080fd5b5061009f73ffffffffffffffffffffffffffffffffffffffff600435811690602435166101e2565b34801561012157600080fd5b5061009f6101ff565b34801561013657600080fd5b5061013f610205565b005b34801561014d57600080fd5b5061009f600435610218565b600080548290811061016757fe5b600091825260209091200154905081565b600080805b83811015610191576001918201910161017d565b5092915050565b600080805b838110156101915760008054600181810183559180527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56301829055918201910161019d565b600260209081526000928352604080842090915290825290205481565b60015481565b600380546001019055610216610205565b565b60006102238261022e565b600181905592915050565b600061023c6002830361022e565b6102486001840361022e565b01929150505600a165627a7a7230582077fd7ac1cd0908622d05db388922d485d6f8e3a546590b97ec8398f87f0c8a580029" - code_TestMapBigLongAndNumbers_deployErc721KittyCore = "608060405234801561001057600080fd5b506108e3806100206000396000f3006080604052600436106100985763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663058294c5811461009d5780630f8286c61461011d57806327e235e3146101b35780634a53ac83146101e65780637d9656881461020757806386b714e21461021f578063931fdba214610234578063babfe8e114610258578063e68c24ae146102bc575b600080fd5b3480156100a957600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261010194369492936024939284019190819084018382808284375094975050509235600160a060020a031693506102e092505050565b60408051600160a060020a039092168252519081900360200190f35b34801561012957600080fd5b5061013e600160a060020a0360043516610310565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610178578181015183820152602001610160565b50505050905090810190601f1680156101a55780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156101bf57600080fd5b506101d4600160a060020a03600435166103aa565b60408051918252519081900360200190f35b3480156101f257600080fd5b5061013e600160a060020a03600435166103bc565b34801561021357600080fd5b506101d4600435610422565b34801561022b57600080fd5b5061013e610442565b34801561024057600080fd5b50610101600160a060020a036004351660243561049d565b34801561026457600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261010194369492936024939284019190819084018382808284375094975050509235600160a060020a0316935061066892505050565b3480156102c857600080fd5b50610101600435600160a060020a0360243516610690565b600160a060020a03811660009081526002602090815260408220845161030892860190610790565b509092915050565b60016020818152600092835260409283902080548451600294821615610100026000190190911693909304601f81018390048302840183019094528383529192908301828280156103a25780601f10610377576101008083540402835291602001916103a2565b820191906000526020600020905b81548152906001019060200180831161038557829003601f168201915b505050505081565b60006020819052908152604090205481565b600260208181526000928352604092839020805484516001821615610100026000190190911693909304601f81018390048302840183019094528383529192908301828280156103a25780601f10610377576101008083540402835291602001916103a2565b600080805b8381101561043b5760019182019101610427565b5092915050565b6003805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103a25780601f10610377576101008083540402835291602001916103a2565b6040805180820190915260018082527f6100000000000000000000000000000000000000000000000000000000000000602090920191825260009182916104e691600391610790565b50600090505b82811015610619576003805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181526105fc9361058e93919290918301828280156105845780601f1061055957610100808354040283529160200191610584565b820191906000526020600020905b81548152906001019060200180831161056757829003601f168201915b50505050506106af565b60038054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526105f093909290918301828280156105845780601f1061055957610100808354040283529160200191610584565b9063ffffffff6106d516565b805161061091600391602090910190610790565b506001016104ec565b60036001600086600160a060020a0316600160a060020a03168152602001908152602001600020908054600181600116156101000203166002900461065f92919061080e565b50929392505050565b600160a060020a03811660009081526001602090815260408220845161030892860190610790565b600160a060020a03811660009081526020819052604090209190915590565b6106b7610883565b50604080518082019091528151815260209182019181019190915290565b606080600083600001518560000151016040519080825280601f01601f191660200182016040528015610712578160200160208202803883390190505b50915060208201905061072e818660200151876000015161074c565b845160208501518551610744928401919061074c565b509392505050565b60005b60208210610771578251845260209384019390920191601f199091019061074f565b50905182516020929092036101000a6000190180199091169116179052565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106107d157805160ff19168380011785556107fe565b828001600101855582156107fe579182015b828111156107fe5782518255916020019190600101906107e3565b5061080a92915061089a565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061084757805485556107fe565b828001600101855582156107fe57600052602060002091601f016020900482015b828111156107fe578254825591600101919060010190610868565b604080518082019091526000808252602082015290565b6108b491905b8082111561080a57600081556001016108a0565b905600a165627a7a72305820f826fbe07a4ee048e7cd47a00e3ca43677011f846fb9e00e1f8202a84a5159540029" - code_TestNetErc721Cat_deployErc721KittyCore = "6002805460a060020a60ff0219169055610240604052603c6080908152607860a05261012c60c05261025860e05261070861010052610e1061012052611c2061014052613840610160526170806101805261e1006101a052620151806101c0526202a3006101e052620546006102005262093a80610220526200008790600390600e620004e3565b50600f6005556301312d00600e55348015620000a257600080fd5b506002805460008054600160a060020a031990811633908117835560a060020a60ff0219909316740100000000000000000000000000000000000000001716909117909155620001019080806000198164010000000062000108810204565b50620005f1565b6000806200011562000586565b600063ffffffff891689146200012a57600080fd5b63ffffffff881688146200013d57600080fd5b61ffff871687146200014e57600080fd5b600287049250600d8361ffff1611156200016757600d92505b505060408051610100810182528581524267ffffffffffffffff90811660208301908152600093830184815263ffffffff8c8116606086019081528c82166080870190815260a0870188815261ffff8a811660c08a019081528f821660e08b01908152600680546001810182559c528a517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f60028e029081019190915598517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40909901805498519651955194519251915167ffffffffffffffff19909916998b1699909917604060020a608060020a0319166801000000000000000096909a169590950298909817608060020a63ffffffff021916700100000000000000000000000000000000938616939093029290921760a060020a63ffffffff02191674010000000000000000000000000000000000000000918516919091021760c060020a63ffffffff0219167801000000000000000000000000000000000000000000000000968416969096029590951760e060020a61ffff0219167c01000000000000000000000000000000000000000000000000000000009186169190910217600160f060020a03167e010000000000000000000000000000000000000000000000000000000000009290941691909102929092179055909190811681146200036f57600080fd5b606080830151608080850151855160408051600160a060020a038c1681526020810188905263ffffffff95861681830152929094169482019490945290810192909252517f0a5311bd2a6608f08a180df2ee7c5946819a649b204b554bb8e39825b2c50ad59181900360a00190a1620003f46000868364010000000062000400810204565b98975050505050505050565b600160a060020a03808316600081815260086020908152604080832080546001019055858352600790915290208054600160a060020a03191690911790558316156200049457600160a060020a03831660009081526008602090815260408083208054600019019055838352600a82528083208054600160a060020a03199081169091556009909252909120805490911690555b60408051600160a060020a0380861682528416602082015280820183905290517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360600190a1505050565b600283019183908215620005745791602002820160005b838211156200054057835183826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302620004fa565b8015620005725782816101000a81549063ffffffff021916905560040160208160030104928301926001030262000540565b505b5062000582929150620005ca565b5090565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915290565b620005ee91905b808211156200058257805463ffffffff19168155600101620005d1565b90565b6130f380620006016000396000f3006080604052600436106102a55763ffffffff60e060020a60003504166301ffc9a781146102d55780630519ce79146103205780630560ff441461035157806305e45546146103ea57806306fdde0314610411578063095ea7b3146104265780630a0f81681461044a5780630e583df01461045f57806314001f4c1461047457806318160ddd14610495578063183a7947146104aa5780631940a936146104bf57806319c2f201146104d757806321717ebf146104ec57806323b872dd1461050157806324e7a38a1461052b57806327d7874c1461054c5780632ba73c151461056d5780633d7d3f5a1461058e5780633f4ba83a146105af57806346116e6f146105c457806346d22c70146105dc578063481af3d3146105f75780634ad8c9381461060f5780634b85fd55146106305780634dfff04f146106485780634e0a33791461066c578063561291341461068d5780635663896e146106b15780635c975abb146106c95780635fd8c710146106de5780636352211e146106f3578063680eba271461070b5780636af04a57146107205780636fbde40d1461073557806370a082311461075657806371587988146107775780637a7d4937146107985780638456cb59146107ad5780638462151c146107c257806388c2a0bf1461083357806391876e571461084b57806395d89b41146108605780639d6fac6f14610875578063a45f4bfc146108a6578063a9059cbb146108be578063b047fb50146108e2578063b0c35c05146108f7578063bc4006f51461090c578063c3bea9af14610921578063d3e6f49f14610939578063defb958414610951578063e17b25af14610966578063e6cbe35114610987578063e98b7f4d1461099c578063ed60ade614610a06578063f1ca941014610a14578063f2b47d5214610a29578063f7d8c88314610a3e575b600b54600160a060020a03163314806102c85750600c54600160a060020a031633145b15156102d357600080fd5b005b3480156102e157600080fd5b5061030c7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1960043516610a4c565b604080519115158252519081900360200190f35b34801561032c57600080fd5b50610335610cdf565b60408051600160a060020a039092168252519081900360200190f35b34801561035d57600080fd5b50610375600480359060248035908101910135610cee565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103af578181015183820152602001610397565b50505050905090810190601f1680156103dc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103f657600080fd5b506103ff610df1565b60408051918252519081900360200190f35b34801561041d57600080fd5b50610375610df7565b34801561043257600080fd5b506102d3600160a060020a0360043516602435610e2e565b34801561045657600080fd5b50610335610eb0565b34801561046b57600080fd5b506103ff610ebf565b34801561048057600080fd5b506102d3600160a060020a0360043516610ec6565b3480156104a157600080fd5b506103ff610f79565b3480156104b657600080fd5b506103ff610f83565b3480156104cb57600080fd5b5061030c600435610f89565b3480156104e357600080fd5b506103ff610fce565b3480156104f857600080fd5b50610335610fd5565b34801561050d57600080fd5b506102d3600160a060020a0360043581169060243516604435610fe4565b34801561053757600080fd5b506102d3600160a060020a0360043516611060565b34801561055857600080fd5b506102d3600160a060020a0360043516611113565b34801561057957600080fd5b506102d3600160a060020a0360043516611161565b34801561059a57600080fd5b506102d36004356024356044356064356111af565b3480156105bb57600080fd5b506102d36112a4565b3480156105d057600080fd5b50610335600435611338565b3480156105e857600080fd5b5061030c600435602435611353565b34801561060357600080fd5b506103356004356113d3565b34801561061b57600080fd5b506102d36004356024356044356064356113ee565b34801561063c57600080fd5b506102d36004356114c6565b34801561065457600080fd5b506102d3600160a060020a03600435166024356114e2565b34801561067857600080fd5b506102d3600160a060020a036004351661153c565b34801561069957600080fd5b506102d3600435600160a060020a036024351661158a565b3480156106bd57600080fd5b506102d36004356115f1565b3480156106d557600080fd5b5061030c61164d565b3480156106ea57600080fd5b506102d361165d565b3480156106ff57600080fd5b506103356004356116c1565b34801561071757600080fd5b506103ff6116e5565b34801561072c57600080fd5b506103356116eb565b34801561074157600080fd5b506102d3600160a060020a03600435166116fa565b34801561076257600080fd5b506103ff600160a060020a03600435166117ad565b34801561078357600080fd5b506102d3600160a060020a03600435166117c8565b3480156107a457600080fd5b506103ff61184b565b3480156107b957600080fd5b506102d3611851565b3480156107ce57600080fd5b506107e3600160a060020a03600435166118d1565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561081f578181015183820152602001610807565b505050509050019250505060405180910390f35b34801561083f57600080fd5b506103ff6004356119a3565b34801561085757600080fd5b506102d3611c7f565b34801561086c57600080fd5b50610375611d94565b34801561088157600080fd5b5061088d600435611dcb565b6040805163ffffffff9092168252519081900360200190f35b3480156108b257600080fd5b50610335600435611df8565b3480156108ca57600080fd5b506102d3600160a060020a0360043516602435611e13565b3480156108ee57600080fd5b50610335611eab565b34801561090357600080fd5b506103ff611eba565b34801561091857600080fd5b50610335611ec0565b34801561092d57600080fd5b506102d3600435611ecf565b34801561094557600080fd5b5061030c600435611fb9565b34801561095d57600080fd5b506103ff612088565b34801561097257600080fd5b506102d3600160a060020a036004351661208e565b34801561099357600080fd5b506103356120c7565b3480156109a857600080fd5b506109b46004356120d6565b604080519a15158b5298151560208b0152898901979097526060890195909552608088019390935260a087019190915260c086015260e085015261010084015261012083015251908190036101400190f35b6102d3600435602435612237565b348015610a2057600080fd5b506103ff6123d1565b348015610a3557600080fd5b506103356123d7565b6102d36004356024356123e6565b604080517f737570706f727473496e74657266616365286279746573342900000000000000815290519081900360190190206000907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1983811691161480610cd75750604080517f746f6b656e4d657461646174612875696e743235362c737472696e67290000008152815190819003601d0181207f746f6b656e734f664f776e657228616464726573732900000000000000000000825282519182900360160182207f7472616e7366657246726f6d28616464726573732c616464726573732c75696e83527f7432353629000000000000000000000000000000000000000000000000000000602084015283519283900360250183207f7472616e7366657228616464726573732c75696e743235362900000000000000845284519384900360190184207f617070726f766528616464726573732c75696e74323536290000000000000000855285519485900360180185207f6f776e65724f662875696e743235362900000000000000000000000000000000865286519586900360100186207f62616c616e63654f662861646472657373290000000000000000000000000000875287519687900360120187207f746f74616c537570706c792829000000000000000000000000000000000000008852885197889003600d0188207f73796d626f6c2829000000000000000000000000000000000000000000000000895289519889900360080189207f6e616d65282900000000000000000000000000000000000000000000000000008a529951988990036006019098207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff198c811691909a189098181818181818181891909116145b90505b919050565b600154600160a060020a031681565b6060610cf8613064565b600d54600090600160a060020a03161515610d1257600080fd5b600d54604080517fcb4799f2000000000000000000000000000000000000000000000000000000008152600481018981526024820192835260448201889052600160a060020a039093169263cb4799f2928a928a928a929091606401848480828437820191505094505050505060a060405180830381600087803b158015610d9957600080fd5b505af1158015610dad573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525060a0811015610dd257600080fd5b5060808101519092509050610de782826125e4565b9695505050505050565b60115481565b60408051808201909152600d81527f43727970746f4b69747469657300000000000000000000000000000000000000602082015281565b60025460a060020a900460ff1615610e4557600080fd5b610e4f3382612638565b1515610e5a57600080fd5b610e648183612658565b60408051338152600160a060020a038416602082015280820183905290517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360600190a15050565b600054600160a060020a031681565b6298968081565b60008054600160a060020a03163314610ede57600080fd5b81905080600160a060020a03166376190f8f6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015610f1f57600080fd5b505af1158015610f33573d6000803e3d6000fd5b505050506040513d6020811015610f4957600080fd5b50511515610f5657600080fd5b600c8054600160a060020a031916600160a060020a039290921691909117905550565b6006546000190190565b600f5481565b6000808211610f9757600080fd5b6006805483908110610fa557fe5b600091825260209091206002909102016001015460c060020a900463ffffffff16151592915050565b6201518081565b600c54600160a060020a031681565b60025460a060020a900460ff1615610ffb57600080fd5b600160a060020a038216151561101057600080fd5b600160a060020a03821630141561102657600080fd5b6110303382612686565b151561103b57600080fd5b6110458382612638565b151561105057600080fd5b61105b8383836126a6565b505050565b60008054600160a060020a0316331461107857600080fd5b81905080600160a060020a03166354c15b826040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156110b957600080fd5b505af11580156110cd573d6000803e3d6000fd5b505050506040513d60208110156110e357600080fd5b505115156110f057600080fd5b60108054600160a060020a031916600160a060020a039290921691909117905550565b600054600160a060020a0316331461112a57600080fd5b600160a060020a038116151561113f57600080fd5b60008054600160a060020a031916600160a060020a0392909216919091179055565b600054600160a060020a0316331461117857600080fd5b600160a060020a038116151561118d57600080fd5b60028054600160a060020a031916600160a060020a0392909216919091179055565b60025460a060020a900460ff16156111c657600080fd5b6111d03385612638565b15156111db57600080fd5b6111e484610f89565b156111ee57600080fd5b600b54611205908590600160a060020a0316612658565b600b54604080517f27ebe40a000000000000000000000000000000000000000000000000000000008152600481018790526024810186905260448101859052606481018490523360848201529051600160a060020a03909216916327ebe40a9160a48082019260009290919082900301818387803b15801561128657600080fd5b505af115801561129a573d6000803e3d6000fd5b5050505050505050565b600054600160a060020a031633146112bb57600080fd5b60025460a060020a900460ff1615156112d357600080fd5b600b54600160a060020a031615156112ea57600080fd5b600c54600160a060020a0316151561130157600080fd5b601054600160a060020a0316151561131857600080fd5b601354600160a060020a03161561132e57600080fd5b611336612788565b565b600a60205260009081526040902054600160a060020a031681565b6000808080851161136357600080fd5b6000841161137057600080fd5b600680548690811061137e57fe5b9060005260206000209060020201915060068481548110151561139d57fe5b906000526020600020906002020190506113b9828683876127d7565b80156113ca57506113ca8486612957565b95945050505050565b600960205260009081526040902054600160a060020a031681565b60025460a060020a900460ff161561140557600080fd5b61140f3385612638565b151561141a57600080fd5b61142384611fb9565b151561142e57600080fd5b600c54611445908590600160a060020a0316612658565b600c54604080517f27ebe40a000000000000000000000000000000000000000000000000000000008152600481018790526024810186905260448101859052606481018490523360848201529051600160a060020a03909216916327ebe40a9160a48082019260009290919082900301818387803b15801561128657600080fd5b600254600160a060020a031633146114dd57600080fd5b600e55565b60025460a060020a900460ff16156114f957600080fd5b6115033382612638565b151561150e57600080fd5b6000908152600a602052604090208054600160a060020a031916600160a060020a0392909216919091179055565b600054600160a060020a0316331461155357600080fd5b600160a060020a038116151561156857600080fd5b60018054600160a060020a031916600160a060020a0392909216919091179055565b600254600090600160a060020a031633146115a457600080fd5b5080600160a060020a03811615156115c45750600254600160a060020a03165b601154611388116115d457600080fd5b6011805460010190556115eb6000808086856129ac565b50505050565b600254600160a060020a03163314806116145750600054600160a060020a031633145b806116295750600154600160a060020a031633145b151561163457600080fd5b60035463ffffffff16811061164857600080fd5b600555565b60025460a060020a900460ff1681565b6001546000908190600160a060020a0316331461167957600080fd5b5050600e54600f54303191600190910102808211156116bd57600154604051600160a060020a039091169082840380156108fc02916000818181858888f150505050505b5050565b600081815260076020526040902054600160a060020a0316801515610cda57600080fd5b61afc881565b601354600160a060020a031681565b60008054600160a060020a0316331461171257600080fd5b81905080600160a060020a03166385b861886040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561175357600080fd5b505af1158015611767573d6000803e3d6000fd5b505050506040513d602081101561177d57600080fd5b5051151561178a57600080fd5b600b8054600160a060020a031916600160a060020a039290921691909117905550565b600160a060020a031660009081526008602052604090205490565b600054600160a060020a031633146117df57600080fd5b60025460a060020a900460ff1615156117f757600080fd5b60138054600160a060020a038316600160a060020a0319909116811790915560408051918252517f450db8da6efbe9c22f2347f7c2021231df1fc58d3ae9a2fa75d39fa4461993059181900360200190a150565b60055481565b600254600160a060020a03163314806118745750600054600160a060020a031633145b806118895750600154600160a060020a031633145b151561189457600080fd5b60025460a060020a900460ff16156118ab57600080fd5b6002805474ff0000000000000000000000000000000000000000191660a060020a179055565b60606000606060008060006118e5876117ad565b9450841515611904576040805160008152602081019091529550611999565b8460405190808252806020026020018201604052801561192e578160200160208202803883390190505b509350611939610f79565b925060009150600190505b82811161199557600081815260076020526040902054600160a060020a038881169116141561198d5780848381518110151561197c57fe5b602090810290910101526001909101905b600101611944565b8395505b5050505050919050565b600080600080600080600080600260149054906101000a900460ff161515156119cb57600080fd5b600680548a9081106119d957fe5b60009182526020909120600290910201600181015490975067ffffffffffffffff161515611a0657600080fd5b604080516101008101825288548152600189015467ffffffffffffffff8082166020840152680100000000000000008204169282019290925263ffffffff608060020a83048116606083015260a060020a83048116608083015260c060020a83041660a082015261ffff60e060020a8304811660c083015260f060020a90920490911660e0820152611a9790612c89565b1515611aa257600080fd5b60018701546006805460c060020a90920463ffffffff1697509087908110611ac657fe5b600091825260209091206001808a015460029093029091019081015490965061ffff60f060020a928390048116965091900416841015611b1357600185015460f060020a900461ffff1693505b6010548754865460018a0154604080517f0d9f5aed0000000000000000000000000000000000000000000000000000000081526004810194909452602484019290925260001967ffffffffffffffff6801000000000000000090920482160116604483015251600160a060020a0390921691630d9f5aed916064808201926020929091908290030181600087803b158015611bad57600080fd5b505af1158015611bc1573d6000803e3d6000fd5b505050506040513d6020811015611bd757600080fd5b505160008a815260076020526040902054600189810154929550600160a060020a039091169350611c20918b9160c060020a90910463ffffffff1690870161ffff1686866129ac565b6001880180547bffffffff00000000000000000000000000000000000000000000000019169055600f8054600019019055600e54604051919250339181156108fc0291906000818181858888f150939c9b505050505050505050505050565b600254600160a060020a0316331480611ca25750600054600160a060020a031633145b80611cb75750600154600160a060020a031633145b1515611cc257600080fd5b600b60009054906101000a9004600160a060020a0316600160a060020a0316635fd8c7106040518163ffffffff1660e060020a028152600401600060405180830381600087803b158015611d1557600080fd5b505af1158015611d29573d6000803e3d6000fd5b50505050600c60009054906101000a9004600160a060020a0316600160a060020a0316635fd8c7106040518163ffffffff1660e060020a028152600401600060405180830381600087803b158015611d8057600080fd5b505af11580156115eb573d6000803e3d6000fd5b60408051808201909152600281527f434b000000000000000000000000000000000000000000000000000000000000602082015281565b600381600e8110611dd857fe5b60089182820401919006600402915054906101000a900463ffffffff1681565b600760205260009081526040902054600160a060020a031681565b60025460a060020a900460ff1615611e2a57600080fd5b600160a060020a0382161515611e3f57600080fd5b600160a060020a038216301415611e5557600080fd5b600b54600160a060020a0383811691161415611e7057600080fd5b600c54600160a060020a0383811691161415611e8b57600080fd5b611e953382612638565b1515611ea057600080fd5b6116bd3383836126a6565b600254600160a060020a031681565b600e5481565b600d54600160a060020a031681565b600254600090600160a060020a03163314611ee957600080fd5b60125461afc811611ef957600080fd5b611f08600080600085306129ac565b600b54909150611f22908290600160a060020a0316612658565b600b54600160a060020a03166327ebe40a82611f3c612cb9565b6040805160e060020a63ffffffff861602815260048101939093526024830191909152600060448301819052620151806064840152306084840152905160a48084019382900301818387803b158015611f9457600080fd5b505af1158015611fa8573d6000803e3d6000fd5b505060128054600101905550505050565b600080808311611fc857600080fd5b6006805484908110611fd657fe5b60009182526020918290206040805161010081018252600290930290910180548352600181015467ffffffffffffffff808216958501959095526801000000000000000081049094169183019190915263ffffffff608060020a84048116606084015260a060020a84048116608084015260c060020a84041660a083015261ffff60e060020a8404811660c084015260f060020a90930490921660e082015290915061208190612d7b565b9392505050565b61138881565b600054600160a060020a031633146120a557600080fd5b600d8054600160a060020a031916600160a060020a0392909216919091179055565b600b54600160a060020a031681565b600080600080600080600080600080600060068c8154811015156120f657fe5b906000526020600020906002020190508060010160189054906101000a900463ffffffff1663ffffffff16600014159a50438160010160089054906101000a900467ffffffffffffffff1667ffffffffffffffff161115995080600101601c9054906101000a900461ffff1661ffff1698508060010160089054906101000a900467ffffffffffffffff1667ffffffffffffffff1697508060010160189054906101000a900463ffffffff1663ffffffff1696508060010160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1695508060010160109054906101000a900463ffffffff1663ffffffff1694508060010160149054906101000a900463ffffffff1663ffffffff16935080600101601e9054906101000a900461ffff1661ffff16925080600001549150509193959799509193959799565b60025460009060a060020a900460ff161561225157600080fd5b61225b3383612638565b151561226657600080fd5b61226f82611fb9565b151561227a57600080fd5b6122848284612daa565b151561228f57600080fd5b600c54604080517fc55d0f56000000000000000000000000000000000000000000000000000000008152600481018690529051600160a060020a039092169163c55d0f56916024808201926020929091908290030181600087803b1580156122f657600080fd5b505af115801561230a573d6000803e3d6000fd5b505050506040513d602081101561232057600080fd5b5051600e54909150810134101561233657600080fd5b600c54600e54604080517f454a2ab3000000000000000000000000000000000000000000000000000000008152600481018790529051600160a060020a039093169263454a2ab39234039160248082019260009290919082900301818588803b1580156123a257600080fd5b505af11580156123b6573d6000803e3d6000fd5b505050505061105b8263ffffffff168463ffffffff16612df9565b60125481565b601054600160a060020a031681565b600254600090819060a060020a900460ff161561240257600080fd5b600e5434101561241157600080fd5b61241b3385612638565b151561242657600080fd5b6124308385612957565b151561243b57600080fd5b600680548590811061244957fe5b60009182526020918290206040805161010081018252600290930290910180548352600181015467ffffffffffffffff808216958501959095526801000000000000000081049094169183019190915263ffffffff608060020a84048116606084015260a060020a84048116608084015260c060020a84041660a083015261ffff60e060020a8404811660c084015260f060020a90930490921660e08201529092506124f490612d7b565b15156124ff57600080fd5b600680548490811061250d57fe5b60009182526020918290206040805161010081018252600290930290910180548352600181015467ffffffffffffffff808216958501959095526801000000000000000081049094169183019190915263ffffffff608060020a84048116606084015260a060020a84048116608084015260c060020a84041660a083015261ffff60e060020a8404811660c084015260f060020a90930490921660e08201529091506125b890612d7b565b15156125c357600080fd5b6125cf828583866127d7565b15156125da57600080fd5b6115eb8484612df9565b606080600080846040519080825280601f01601f191660200182016040528015612618578160200160208202803883390190505b509250506020820190508461262e828287612f37565b5090949350505050565b600090815260076020526040902054600160a060020a0391821691161490565b6000918252600960205260409091208054600160a060020a031916600160a060020a03909216919091179055565b600090815260096020526040902054600160a060020a0391821691161490565b600160a060020a03808316600081815260086020908152604080832080546001019055858352600790915290208054600160a060020a031916909117905583161561273957600160a060020a03831660009081526008602090815260408083208054600019019055838352600a82528083208054600160a060020a03199081169091556009909252909120805490911690555b60408051600160a060020a0380861682528416602082015280820183905290517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360600190a1505050565b600054600160a060020a0316331461279f57600080fd5b60025460a060020a900460ff1615156127b757600080fd5b6002805474ff000000000000000000000000000000000000000019169055565b6000818414156127e95750600061294f565b6001850154608060020a900463ffffffff168214806128185750600185015460a060020a900463ffffffff1682145b156128255750600061294f565b6001830154608060020a900463ffffffff168414806128545750600183015460a060020a900463ffffffff1684145b156128615750600061294f565b6001830154608060020a900463ffffffff16158061288e57506001850154608060020a900463ffffffff16155b1561289b5750600161294f565b60018581015490840154608060020a9182900463ffffffff908116929091041614806128e6575060018086015490840154608060020a900463ffffffff90811660a060020a90920416145b156128f35750600061294f565b6001808601549084015460a060020a900463ffffffff908116608060020a90920416148061293e57506001858101549084015460a060020a9182900463ffffffff9081169290910416145b1561294b5750600061294f565b5060015b949350505050565b6000818152600760205260408082205484835290822054600160a060020a039182169116808214806113ca57506000858152600a6020526040902054600160a060020a03908116908316149250505092915050565b6000806129b7613083565b600063ffffffff891689146129cb57600080fd5b63ffffffff881688146129dd57600080fd5b61ffff871687146129ed57600080fd5b600287049250600d8361ffff161115612a0557600d92505b505060408051610100810182528581524267ffffffffffffffff90811660208301908152600093830184815263ffffffff8c8116606086019081528c82166080870190815260a0870188815261ffff8a811660c08a019081528f821660e08b01908152600680546001810182559c528a517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f60028e029081019190915598517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40909901805498519651955194519251915167ffffffffffffffff19909916998b16999099176fffffffffffffffff000000000000000019166801000000000000000096909a16959095029890981773ffffffff000000000000000000000000000000001916608060020a938616939093029290921777ffffffff0000000000000000000000000000000000000000191660a060020a91851691909102177bffffffff000000000000000000000000000000000000000000000000191660c060020a96841696909602959095177fffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660e060020a91861691909102177dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f060020a929094169190910292909217905590919081168114612c0357600080fd5b606080830151608080850151855160408051600160a060020a038c1681526020810188905263ffffffff95861681830152929094169482019490945290810192909252517f0a5311bd2a6608f08a180df2ee7c5946819a649b204b554bb8e39825b2c50ad59181900360a00190a1612c7d600086836126a6565b98975050505050505050565b60008160a0015163ffffffff16600014158015610cd75750506040015167ffffffffffffffff4381169116111590565b6000806000600b60009054906101000a9004600160a060020a0316600160a060020a031663eac9d94c6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015612d1157600080fd5b505af1158015612d25573d6000803e3d6000fd5b505050506040513d6020811015612d3b57600080fd5b505191506fffffffffffffffffffffffffffffffff82168214612d5d57600080fd5b5060028104810162989680811015612d755750629896805b92915050565b60008160a0015163ffffffff166000148015610cd75750506040015167ffffffffffffffff4381169116111590565b6000806000600685815481101515612dbe57fe5b90600052602060002090600202019150600684815481101515612ddd57fe5b906000526020600020906002020190506113ca828683876127d7565b600080600683815481101515612e0b57fe5b90600052602060002090600202019150600684815481101515612e2a57fe5b600091825260209091206002909102016001810180547bffffffff000000000000000000000000000000000000000000000000191660c060020a63ffffffff8716021790559050612e7a82612f7b565b612e8381612f7b565b6000848152600a602090815260408083208054600160a060020a031990811690915586845281842080549091169055600f80546001908101909155878452600783529281902054928401548151600160a060020a0390941684529183018790528281018690526801000000000000000090910467ffffffffffffffff166060830152517f241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b80916080908290030190a150505050565b60005b60208210612f5c578251845260209384019390920191601f1990910190612f3a565b50905182516020929092036101000a6000190180199091169116179052565b600554600182015443919060039060e060020a900461ffff16600e8110612f9e57fe5b600891828204019190066004029054906101000a900463ffffffff1663ffffffff16811515612fc957fe5b6001840180546fffffffffffffffff0000000000000000191668010000000000000000939092049390930167ffffffffffffffff16919091021790819055600d60e060020a90910461ffff161015613061576001818101805461ffff60e060020a8083048216909401169092027fffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092169190911790555b50565b6080604051908101604052806004906020820280388339509192915050565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152905600a165627a7a723058201424bf1db41fa7ec76f5506a53d8bbcb84ed5b5a6ade2df0bac8deaacb118a8b0029" - code_TestNetErc721Cat_deploySaleClockAuction = "60806040526000805460a060020a60ff02191690556004805460ff1916600117905534801561002d57600080fd5b50604051604080610ee883398101604052805160209091015160008054600160a060020a031916331781558290829061271082111561006b57600080fd5b506002819055604080517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f9a20483d00000000000000000000000000000000000000000000000000000000600482015290518391600160a060020a038316916301ffc9a7916024808201926020929091908290030181600087803b1580156100f557600080fd5b505af1158015610109573d6000803e3d6000fd5b505050506040513d602081101561011f57600080fd5b5051151561012c57600080fd5b60018054600160a060020a03909216600160a060020a031990921691909117905550505050610d88806101606000396000f3006080604052600436106100fb5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166327ebe40a81146101005780633f4ba83a1461012f578063454a2ab314610158578063484eccb4146101635780635c975abb1461018d5780635fd8c710146101a257806378bd7935146101b757806383b5ff8b146102045780638456cb591461021957806385b861881461022e578063878eb368146102435780638a98a9cc1461025b5780638da5cb5b1461027057806396b5a755146102a1578063c55d0f56146102b9578063dd1b7a0f146102d1578063eac9d94c146102e6578063f2fde38b146102fb575b600080fd5b34801561010c57600080fd5b5061012d600435602435604435606435600160a060020a036084351661031c565b005b34801561013b57600080fd5b50610144610414565b604080519115158252519081900360200190f35b61012d60043561048f565b34801561016f57600080fd5b5061017b6004356104f9565b60408051918252519081900360200190f35b34801561019957600080fd5b5061014461050d565b3480156101ae57600080fd5b5061012d61051d565b3480156101c357600080fd5b506101cf60043561057a565b60408051600160a060020a03909616865260208601949094528484019290925260608401526080830152519081900360a00190f35b34801561021057600080fd5b5061017b610610565b34801561022557600080fd5b50610144610616565b34801561023a57600080fd5b50610144610696565b34801561024f57600080fd5b5061012d60043561069f565b34801561026757600080fd5b5061017b61070c565b34801561027c57600080fd5b50610285610712565b60408051600160a060020a039092168252519081900360200190f35b3480156102ad57600080fd5b5061012d600435610721565b3480156102c557600080fd5b5061017b600435610766565b3480156102dd57600080fd5b50610285610798565b3480156102f257600080fd5b5061017b6107a7565b34801561030757600080fd5b5061012d600160a060020a03600435166107db565b610324610d2e565b6fffffffffffffffffffffffffffffffff8516851461034257600080fd5b6fffffffffffffffffffffffffffffffff8416841461036057600080fd5b67ffffffffffffffff8316831461037657600080fd5b600154600160a060020a0316331461038d57600080fd5b610397828761082d565b60a06040519081016040528083600160a060020a03168152602001866fffffffffffffffffffffffffffffffff168152602001856fffffffffffffffffffffffffffffffff1681526020018467ffffffffffffffff1681526020014267ffffffffffffffff16815250905061040c86826108b5565b505050505050565b60008054600160a060020a0316331461042c57600080fd5b60005460a060020a900460ff16151561044457600080fd5b6000805474ff0000000000000000000000000000000000000000191681556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b339190a150600190565b600081815260036020526040812054600160a060020a0316906104b28334610a09565b90506104be3384610b2f565b600154600160a060020a03838116911614156104f45760058054829160069106600581106104e857fe5b01556005805460010190555b505050565b6006816005811061050657fe5b0154905081565b60005460a060020a900460ff1681565b60015460008054600160a060020a039283169216331480610546575033600160a060020a038316145b151561055157600080fd5b604051600160a060020a03831690303180156108fc02916000818181858888f150505050505050565b6000818152600360205260408120819081908190819061059981610b9d565b15156105a457600080fd5b80546001820154600290920154600160a060020a03909116986fffffffffffffffffffffffffffffffff8084169950700100000000000000000000000000000000909304909216965067ffffffffffffffff808216965068010000000000000000909104169350915050565b60025481565b60008054600160a060020a0316331461062e57600080fd5b60005460a060020a900460ff161561064557600080fd5b6000805474ff0000000000000000000000000000000000000000191660a060020a1781556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff6259190a150600190565b60045460ff1681565b6000805460a060020a900460ff1615156106b857600080fd5b600054600160a060020a031633146106cf57600080fd5b5060008181526003602052604090206106e781610b9d565b15156106f257600080fd5b8054610708908390600160a060020a0316610bbe565b5050565b60055481565b600054600160a060020a031681565b60008181526003602052604081209061073982610b9d565b151561074457600080fd5b508054600160a060020a031633811461075c57600080fd5b6104f48382610bbe565b600081815260036020526040812061077d81610b9d565b151561078857600080fd5b61079181610c08565b9392505050565b600154600160a060020a031681565b600080805b60058110156107d157600681600581106107c257fe5b015491909101906001016107ac565b5060059004919050565b600054600160a060020a031633146107f257600080fd5b600160a060020a0381161561082a576000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b50565b600154604080517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a03858116600483015230602483015260448201859052915191909216916323b872dd91606480830192600092919082900301818387803b1580156108a157600080fd5b505af115801561040c573d6000803e3d6000fd5b603c816060015167ffffffffffffffff16101515156108d357600080fd5b60008281526003602090815260409182902083518154600160a060020a0390911673ffffffffffffffffffffffffffffffffffffffff1990911617815581840151600182018054858701516fffffffffffffffffffffffffffffffff90811670010000000000000000000000000000000081029482166fffffffffffffffffffffffffffffffff19909316831790911693909317909155606080870151600290940180546080808a015167ffffffffffffffff90811668010000000000000000026fffffffffffffffff0000000000000000199190981667ffffffffffffffff1990931683171696909617909155865189815295860192909252848601929092529083015291517fa9c8dfcda5664a5a124c713e386da27de87432d5b668e79458501eb296389ba7929181900390910190a15050565b60008281526003602052604081208180808080610a2586610b9d565b1515610a3057600080fd5b610a3986610c08565b945084881015610a4857600080fd5b8554600160a060020a03169350610a5e89610c98565b6000851115610ab057610a7085610ce5565b6040519093508386039250600160a060020a0385169083156108fc029084906000818181858888f19350505050158015610aae573d6000803e3d6000fd5b505b5060405184880390339082156108fc029083906000818181858888f19350505050158015610ae2573d6000803e3d6000fd5b50604080518a815260208101879052338183015290517f4fcc30d90a842164dd58501ab874a101a3749c3d4747139cefe7c876f4ccebd29181900360600190a15092979650505050505050565b600154604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a038581166004830152602482018590529151919092169163a9059cbb91604480830192600092919082900301818387803b1580156108a157600080fd5b6002015460006801000000000000000090910467ffffffffffffffff161190565b610bc782610c98565b610bd18183610b2f565b6040805183815290517f2809c7e17bf978fbc7194c0a694b638c4215e9140cacc6c38ca36010b45697df9181900360200190a15050565b6002810154600090819068010000000000000000900467ffffffffffffffff16421115610c4e5750600282015468010000000000000000900467ffffffffffffffff1642035b60018301546002840154610791916fffffffffffffffffffffffffffffffff80821692700100000000000000000000000000000000909204169067ffffffffffffffff1684610cf1565b6000908152600360205260408120805473ffffffffffffffffffffffffffffffffffffffff19168155600181019190915560020180546fffffffffffffffffffffffffffffffff19169055565b60025461271091020490565b6000808080858510610d0557869350610d23565b878703925085858402811515610d1757fe5b05915081880190508093505b505050949350505050565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152905600a165627a7a723058203c3d7d4039d9d9a82dd65c7bc046590e8fe3580af952a66fe24052959889bef50029" - code_TestNetErc721Cat_deploySiringClockAuction = "60806040526000805460a060020a60ff02191690556004805460ff1916600117905534801561002d57600080fd5b50604051604080610e1a83398101604052805160209091015160008054600160a060020a031916331781558290829061271082111561006b57600080fd5b506002819055604080517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f9a20483d00000000000000000000000000000000000000000000000000000000600482015290518391600160a060020a038316916301ffc9a7916024808201926020929091908290030181600087803b1580156100f557600080fd5b505af1158015610109573d6000803e3d6000fd5b505050506040513d602081101561011f57600080fd5b5051151561012c57600080fd5b60018054600160a060020a03909216600160a060020a031990921691909117905550505050610cba806101606000396000f3006080604052600436106100da5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166327ebe40a81146100df5780633f4ba83a1461010e578063454a2ab3146101375780635c975abb146101425780635fd8c7101461015757806376190f8f1461016c57806378bd79351461018157806383b5ff8b146101ce5780638456cb59146101f5578063878eb3681461020a5780638da5cb5b1461022257806396b5a75514610253578063c55d0f561461026b578063dd1b7a0f14610283578063f2fde38b14610298575b600080fd5b3480156100eb57600080fd5b5061010c600435602435604435606435600160a060020a03608435166102b9565b005b34801561011a57600080fd5b506101236103b1565b604080519115158252519081900360200190f35b61010c60043561042c565b34801561014e57600080fd5b50610123610478565b34801561016357600080fd5b5061010c610488565b34801561017857600080fd5b506101236104e5565b34801561018d57600080fd5b506101996004356104ee565b60408051600160a060020a03909616865260208601949094528484019290925260608401526080830152519081900360a00190f35b3480156101da57600080fd5b506101e3610584565b60408051918252519081900360200190f35b34801561020157600080fd5b5061012361058a565b34801561021657600080fd5b5061010c60043561060a565b34801561022e57600080fd5b50610237610673565b60408051600160a060020a039092168252519081900360200190f35b34801561025f57600080fd5b5061010c600435610682565b34801561027757600080fd5b506101e36004356106cc565b34801561028f57600080fd5b506102376106fe565b3480156102a457600080fd5b5061010c600160a060020a036004351661070d565b6102c1610c60565b6fffffffffffffffffffffffffffffffff851685146102df57600080fd5b6fffffffffffffffffffffffffffffffff841684146102fd57600080fd5b67ffffffffffffffff8316831461031357600080fd5b600154600160a060020a0316331461032a57600080fd5b610334828761075f565b60a06040519081016040528083600160a060020a03168152602001866fffffffffffffffffffffffffffffffff168152602001856fffffffffffffffffffffffffffffffff1681526020018467ffffffffffffffff1681526020014267ffffffffffffffff1681525090506103a986826107e7565b505050505050565b60008054600160a060020a031633146103c957600080fd5b60005460a060020a900460ff1615156103e157600080fd5b6000805474ff0000000000000000000000000000000000000000191681556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b339190a150600190565b600154600090600160a060020a0316331461044657600080fd5b50600081815260036020526040902054600160a060020a0316610469823461093b565b506104748183610a61565b5050565b60005460a060020a900460ff1681565b60015460008054600160a060020a0392831692163314806104b1575033600160a060020a038316145b15156104bc57600080fd5b604051600160a060020a03831690303180156108fc02916000818181858888f150505050505050565b60045460ff1681565b6000818152600360205260408120819081908190819061050d81610acf565b151561051857600080fd5b80546001820154600290920154600160a060020a03909116986fffffffffffffffffffffffffffffffff8084169950700100000000000000000000000000000000909304909216965067ffffffffffffffff808216965068010000000000000000909104169350915050565b60025481565b60008054600160a060020a031633146105a257600080fd5b60005460a060020a900460ff16156105b957600080fd5b6000805474ff0000000000000000000000000000000000000000191660a060020a1781556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff6259190a150600190565b6000805460a060020a900460ff16151561062357600080fd5b600054600160a060020a0316331461063a57600080fd5b50600081815260036020526040902061065281610acf565b151561065d57600080fd5b8054610474908390600160a060020a0316610af0565b600054600160a060020a031681565b60008181526003602052604081209061069a82610acf565b15156106a557600080fd5b508054600160a060020a03163381146106bd57600080fd5b6106c78382610af0565b505050565b60008181526003602052604081206106e381610acf565b15156106ee57600080fd5b6106f781610b3a565b9392505050565b600154600160a060020a031681565b600054600160a060020a0316331461072457600080fd5b600160a060020a0381161561075c576000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b50565b600154604080517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a03858116600483015230602483015260448201859052915191909216916323b872dd91606480830192600092919082900301818387803b1580156107d357600080fd5b505af11580156103a9573d6000803e3d6000fd5b603c816060015167ffffffffffffffff161015151561080557600080fd5b60008281526003602090815260409182902083518154600160a060020a0390911673ffffffffffffffffffffffffffffffffffffffff1990911617815581840151600182018054858701516fffffffffffffffffffffffffffffffff90811670010000000000000000000000000000000081029482166fffffffffffffffffffffffffffffffff19909316831790911693909317909155606080870151600290940180546080808a015167ffffffffffffffff90811668010000000000000000026fffffffffffffffff0000000000000000199190981667ffffffffffffffff1990931683171696909617909155865189815295860192909252848601929092529083015291517fa9c8dfcda5664a5a124c713e386da27de87432d5b668e79458501eb296389ba7929181900390910190a15050565b6000828152600360205260408120818080808061095786610acf565b151561096257600080fd5b61096b86610b3a565b94508488101561097a57600080fd5b8554600160a060020a0316935061099089610bca565b60008511156109e2576109a285610c17565b6040519093508386039250600160a060020a0385169083156108fc029084906000818181858888f193505050501580156109e0573d6000803e3d6000fd5b505b5060405184880390339082156108fc029083906000818181858888f19350505050158015610a14573d6000803e3d6000fd5b50604080518a815260208101879052338183015290517f4fcc30d90a842164dd58501ab874a101a3749c3d4747139cefe7c876f4ccebd29181900360600190a15092979650505050505050565b600154604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a038581166004830152602482018590529151919092169163a9059cbb91604480830192600092919082900301818387803b1580156107d357600080fd5b6002015460006801000000000000000090910467ffffffffffffffff161190565b610af982610bca565b610b038183610a61565b6040805183815290517f2809c7e17bf978fbc7194c0a694b638c4215e9140cacc6c38ca36010b45697df9181900360200190a15050565b6002810154600090819068010000000000000000900467ffffffffffffffff16421115610b805750600282015468010000000000000000900467ffffffffffffffff1642035b600183015460028401546106f7916fffffffffffffffffffffffffffffffff80821692700100000000000000000000000000000000909204169067ffffffffffffffff1684610c23565b6000908152600360205260408120805473ffffffffffffffffffffffffffffffffffffffff19168155600181019190915560020180546fffffffffffffffffffffffffffffffff19169055565b60025461271091020490565b6000808080858510610c3757869350610c55565b878703925085858402811515610c4957fe5b05915081880190508093505b505050949350505050565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152905600a165627a7a723058208d1842c4569ecc7005642ae981f6c77b856b1d9a921f3792bdb4219144ae25e00029" - code_TestNetErc721Cat_deployGeneScienceInterface = "608060405234801561001057600080fd5b5060dc8061001f6000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630d9f5aed8114604d57806354c15b8214607a575b600080fd5b348015605857600080fd5b50606860043560243560443560a0565b60408051918252519081900360200190f35b348015608557600080fd5b50608c60ab565b604080519115158252519081900360200190f35b600292909101010490565b6001905600a165627a7a72305820d9550024d511527e5124d542daf0a0f3168b9bece6a238bcbccba8b61d3f0bdb0029" - code_TestNetFomo3D_deployErc721CryptoKitties = "60c0604052600660808190527f464f4d4f3344000000000000000000000000000000000000000000000000000060a0908152620000409160009190620000b3565b506040805180820190915260038082527f463344000000000000000000000000000000000000000000000000000000000060209092019182526200008791600191620000b3565b506305f5e1006002556000600855600b805460ff19169055348015620000ac57600080fd5b5062000158565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620000f657805160ff191683800117855562000126565b8280016001018555821562000126579182015b828111156200012657825182559160200191906001019062000109565b506200013492915062000138565b5090565b6200015591905b808211156200013457600081556001016200013f565b90565b61165980620001686000396000f3006080604052600436106101685763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166265318b811461017657806306fdde03146101a957806310d0ffdd1461023357806318160ddd1461024b578063226093731461026057806327defa1f14610278578063313ce567146102a1578063392efb52146102cc5780633ccfd60b146102e45780634b750334146102fb57806356d399e814610310578063688abbf7146103255780636b2f46321461033f57806370a08231146103545780638328b610146103755780638620410b1461038d57806389135ae9146103a25780638fea64bd146103bf578063949e8acd146103d457806395d89b41146103e9578063a8e04f34146103fe578063a9059cbb14610413578063b84c824614610437578063c47f002714610490578063e4849b32146104e9578063e9fad8ee14610501578063f088d54714610516578063fdb5a03e1461052a575b61017334600061053f565b50005b34801561018257600080fd5b50610197600160a060020a0360043516610b15565b60408051918252519081900360200190f35b3480156101b557600080fd5b506101be610b50565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101f85781810151838201526020016101e0565b50505050905090810190601f1680156102255780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023f57600080fd5b50610197600435610bde565b34801561025757600080fd5b50610197610c0e565b34801561026c57600080fd5b50610197600435610c15565b34801561028457600080fd5b5061028d610c4e565b604080519115158252519081900360200190f35b3480156102ad57600080fd5b506102b6610c57565b6040805160ff9092168252519081900360200190f35b3480156102d857600080fd5b5061028d600435610c5c565b3480156102f057600080fd5b506102f9610c71565b005b34801561030757600080fd5b50610197610d44565b34801561031c57600080fd5b50610197610d93565b34801561033157600080fd5b506101976004351515610d99565b34801561034b57600080fd5b50610197610ddc565b34801561036057600080fd5b50610197600160a060020a0360043516610de1565b34801561038157600080fd5b506102f9600435610dfc565b34801561039957600080fd5b50610197610e43565b3480156103ae57600080fd5b506102f96004356024351515610e87565b3480156103cb57600080fd5b506102f9610ee9565b3480156103e057600080fd5b50610197610eeb565b3480156103f557600080fd5b506101be610efe565b34801561040a57600080fd5b506102f9610f58565b34801561041f57600080fd5b5061028d600160a060020a0360043516602435610fa6565b34801561044357600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526102f99436949293602493928401919081908401838280828437509497506111609650505050505050565b34801561049c57600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526102f99436949293602493928401919081908401838280828437509497506111b99650505050505050565b3480156104f557600080fd5b506102f960043561120d565b34801561050d57600080fd5b506102f961135e565b610197600160a060020a036004351661138b565b34801561053657600080fd5b506102f9611397565b60008060008060008060008060008a6000339050600b60009054906101000a900460ff16801561058157506801158e460913d000008261057d610ddc565b0311155b1561088e57600160a060020a03811660009081526003602052604090205460ff16151560011480156105d65750600160a060020a038116600090815260076020526040902054670de0b6b3a764000090830111155b15156105e157600080fd5b600160a060020a038116600090815260076020526040902054610604908361144d565b600160a060020a03821660009081526007602052604090205533995061062b8d6005611463565b9850610638896003611463565b9750610644898961147a565b96506106508d8a61147a565b955061065b8661148c565b945068010000000000000000870293506000851180156106855750600854610683868261144d565b115b151561069057600080fd5b600160a060020a038c16158015906106ba575089600160a060020a03168c600160a060020a031614155b80156106e05750600254600160a060020a038d1660009081526004602052604090205410155b1561072657600160a060020a038c16600090815260056020526040902054610708908961144d565b600160a060020a038d16600090815260056020526040902055610741565b610730878961144d565b965068010000000000000000870293505b600060085411156107a5576107586008548661144d565b600881905568010000000000000000880281151561077257fe5b6009805492909104909101905560085468010000000000000000880281151561079757fe5b0485028403840393506107ab565b60088590555b600160a060020a038a166000908152600460205260409020546107ce908661144d565b600460008c600160a060020a0316600160a060020a031681526020019081526020016000208190555083856009540203925082600660008c600160a060020a0316600160a060020a03168152602001908152602001600020600082825401925050819055508b600160a060020a03168a600160a060020a03167f022c0d992e4d873a3748436d960d5140c1f9721cf73f7ca5ec679d3d9f4fe2d58f88604051808381526020018281526020019250505060405180910390a3849a50610b05565b600b805460ff191690553399506108a68d6005611463565b98506108b3896003611463565b97506108bf898961147a565b96506108cb8d8a61147a565b95506108d68661148c565b9450680100000000000000008702935060008511801561090057506008546108fe868261144d565b115b151561090b57600080fd5b600160a060020a038c1615801590610935575089600160a060020a03168c600160a060020a031614155b801561095b5750600254600160a060020a038d1660009081526004602052604090205410155b156109a157600160a060020a038c16600090815260056020526040902054610983908961144d565b600160a060020a038d166000908152600560205260409020556109bc565b6109ab878961144d565b965068010000000000000000870293505b60006008541115610a20576109d36008548661144d565b60088190556801000000000000000088028115156109ed57fe5b60098054929091049091019055600854680100000000000000008802811515610a1257fe5b048502840384039350610a26565b60088590555b600160a060020a038a16600090815260046020526040902054610a49908661144d565b600460008c600160a060020a0316600160a060020a031681526020019081526020016000208190555083856009540203925082600660008c600160a060020a0316600160a060020a03168152602001908152602001600020600082825401925050819055508b600160a060020a03168a600160a060020a03167f022c0d992e4d873a3748436d960d5140c1f9721cf73f7ca5ec679d3d9f4fe2d58f88604051808381526020018281526020019250505060405180910390a3849a505b5050505050505050505092915050565b600160a060020a0316600090815260066020908152604080832054600490925290912054600954680100000000000000009102919091030490565b6000805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610bd65780601f10610bab57610100808354040283529160200191610bd6565b820191906000526020600020905b815481529060010190602001808311610bb957829003601f168201915b505050505081565b6000808080610bee856005611463565b9250610bfa858461147a565b9150610c058261148c565b95945050505050565b6008545b90565b6000806000806008548511151515610c2c57600080fd5b610c3585611508565b9250610c42836005611463565b9150610c05838361147a565b600b5460ff1681565b600681565b600a6020526000908152604090205460ff1681565b6000806000610c806001610d99565b11610c8a57600080fd5b339150610c976000610d99565b600160a060020a038316600081815260066020908152604080832080546801000000000000000087020190556005909152808220805490839055905193019350909183156108fc0291849190818181858888f19350505050158015610d00573d6000803e3d6000fd5b50604080518281529051600160a060020a038416917fccad973dcd043c7d680389db4378bd6b9775db7124092e9e0422c9e46d7985dc919081900360200190a25050565b60008060008060085460001415610d625764d18c2e28009350610d8d565b610d6e620f4240611508565b9250610d7b836005611463565b9150610d87838361147a565b90508093505b50505090565b60025481565b60003382610daf57610daa81610b15565b610dd3565b600160a060020a038116600090815260056020526040902054610dd182610b15565b015b91505b50919050565b303190565b600160a060020a031660009081526004602052604090205490565b604080516c010000000000000000000000003390810282528251918290036014019091206000908152600a602052919091205460ff161515610e3d57600080fd5b50600255565b60008060008060085460001415610e62576501001d1bf8009350610d8d565b610e6e620f4240611508565b9250610e7b836005611463565b9150610d87838361144d565b604080516c010000000000000000000000003390810282528251918290036014019091206000908152600a602052919091205460ff161515610ec857600080fd5b506000918252600a6020526040909120805460ff1916911515919091179055565b565b600033610ef781610de1565b91505b5090565b60018054604080516020600284861615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610bd65780601f10610bab57610100808354040283529160200191610bd6565b604080516c010000000000000000000000003390810282528251918290036014019091206000908152600a602052919091205460ff161515610f9957600080fd5b50600b805460ff19169055565b600080600080600080610fb7610eeb565b11610fc157600080fd5b600b5433945060ff16158015610fef5750600160a060020a0384166000908152600460205260409020548611155b1515610ffa57600080fd5b60006110066001610d99565b111561101457611014610c71565b61101f866005611463565b925061102b868461147a565b915061103683611508565b90506110446008548461147a565b600855600160a060020a03841660009081526004602052604090205461106a908761147a565b600160a060020a038086166000908152600460205260408082209390935590891681522054611099908361144d565b600160a060020a0388811660008181526004602090815260408083209590955560098054948a16835260069091528482208054948c0290940390935582549181529290922080549285029092019091555460085461110d919068010000000000000000840281151561110757fe5b0461144d565b600955604080518381529051600160a060020a03808a1692908716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35060019695505050505050565b604080516c010000000000000000000000003390810282528251918290036014019091206000908152600a602052919091205460ff1615156111a157600080fd5b81516111b490600190602085019061159f565b505050565b604080516c010000000000000000000000003390810282528251918290036014019091206000908152600a602052919091205460ff1615156111fa57600080fd5b81516111b490600090602085019061159f565b6000806000806000806000611220610eeb565b1161122a57600080fd5b3360008181526004602052604090205490965087111561124957600080fd5b86945061125585611508565b9350611262846005611463565b925061126e848461147a565b915061127c6008548661147a565b600855600160a060020a0386166000908152600460205260409020546112a2908661147a565b600160a060020a038716600090815260046020908152604080832093909355600954600690915291812080549288026801000000000000000086020192839003905560085491925010156113125761130e60095460085468010000000000000000860281151561110757fe5b6009555b60408051868152602081018490528151600160a060020a038916927fc4823739c5787d2ca17e404aa47d5569ae71dfb49cbf21b3f6152ed238a31139928290030190a250505050505050565b336000818152600460205260408120549081111561137f5761137f8161120d565b611387610c71565b5050565b6000610dd6348361053f565b6000806000806113a76001610d99565b116113b157600080fd5b6113bb6000610d99565b336000818152600660209081526040808320805468010000000000000000870201905560059091528120805490829055909201945092506113fd90849061053f565b905081600160a060020a03167fbe339fc14b041c2b0e0f3dd2cd325d0c3668b78378001e53160eab36153264588483604051808381526020018281526020019250505060405180910390a2505050565b60008282018381101561145c57fe5b9392505050565b600080828481151561147157fe5b04949350505050565b60008282111561148657fe5b50900390565b600854600090670de0b6b3a764000090829064174876e8006114f56114ef692a5a058fc295ed000000880269021e19e0c9bab24000006002860a02016c02863c1f5cdae42f95400000008502016ec097ce7bc90715b34b9f10000000000161156a565b8561147a565b8115156114fe57fe5b0403949350505050565b600854600090620f424083810191810190839061155764d18c2e280082850464174876e80002018702600283620f423f1982890a8b9003010464174876e8000281151561155157fe5b0461147a565b81151561156057fe5b0495945050505050565b80600260018201045b81811015610dd657809150600281828581151561158c57fe5b040181151561159757fe5b049050611573565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106115e057805160ff191683800117855561160d565b8280016001018555821561160d579182015b8281111561160d5782518255916020019190600101906115f2565b50610efa92610c129250905b80821115610efa57600081556001016116195600a165627a7a72305820bf757ace6c45263e75b0a8eb6c539065f0ca610f7bf4378df93a0eff2d0551060029" - code1_TestNetFomo3D_deployErc721CryptoKitties = "608060405234801561001057600080fd5b5061011a806100206000396000f300608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063f8a8fd6d146044575b600080fd5b348015604f57600080fd5b506056606c565b6040518082815260200191505060405180910390f35b6000600180141515607c57600080fd5b603c80141515608a57600080fd5b610e1080141515609957600080fd5b620151808014151560a957600080fd5b62093a808014151560b957600080fd5b6301e133808014151560ca57600080fd5b620f42408014151560da57600080fd5b60018014151560e857600080fd5b429050905600a165627a7a72305820e8f9994ec320bbc329299a1cec491445178da2a60b219fb25e91adb9c4e4aa930029" - code_TestNetFomo3D_tooLargeStorage = "60e0604090815260808190527f313233343536373831323334353637383132333435363738313233343536373860a081815260c091909152610044916001919061009e565b50604080516060810182528181527f6162636466657467616263646665746761626364666574676162636466657467602082018181529183015261008b916002919061009e565b5034801561009857600080fd5b50610139565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100df57805160ff191683800117855561010c565b8280016001018555821561010c579182015b8281111561010c5782518255916020019190600101906100f1565b5061011892915061011c565b5090565b61013691905b808211156101185760008155600101610122565b90565b6105bb806101486000396000f3006080604052600436106100615763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166386b714e28114610066578063c2985578146100f0578063e6a01b5a14610105578063f8ac93e81461011f575b600080fd5b34801561007257600080fd5b5061007b610134565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100b557818101518382015260200161009d565b50505050905090810190601f1680156100e25780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156100fc57600080fd5b5061007b6101c2565b34801561011157600080fd5b5061011d6004356102cc565b005b34801561012b57600080fd5b5061011d6103e0565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156101ba5780601f1061018f576101008083540402835291602001916101ba565b820191906000526020600020905b81548152906001019060200180831161019d57829003601f168201915b505050505081565b60028054604080516020601f600019610100600187161502019094168590049384018190048102820181019092528281526060936102c6936102599383018282801561024f5780601f106102245761010080835404028352916020019161024f565b820191906000526020600020905b81548152906001019060200180831161023257829003601f168201915b50505050506103ff565b60018054604080516020601f6002600019610100878916150201909516949094049384018190048102820181019092528281526102ba939092909183018282801561024f5780601f106102245761010080835404028352916020019161024f565b9063ffffffff61042516565b90505b90565b60006102d66101c2565b80516102ea916000916020909101906104e0565b50600090505b818110156103dc576000805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181526103bf9361035d939192909183018282801561024f5780601f106102245761010080835404028352916020019161024f565b60008054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526102ba939092909183018282801561024f5780601f106102245761010080835404028352916020019161024f565b80516103d3916000916020909101906104e0565b506001016102f0565b5050565b6040805160208101918290526000908190526103fc91816104e0565b50565b61040761055e565b50604080518082019091528151815260209182019181019190915290565b606080600083600001518560000151016040519080825280601f01601f191660200182016040528015610462578160200160208202803883390190505b50915060208201905061047e818660200151876000015161049c565b845160208501518551610494928401919061049c565b509392505050565b60005b602082106104c1578251845260209384019390920191601f199091019061049f565b50905182516020929092036101000a6000190180199091169116179052565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061052157805160ff191683800117855561054e565b8280016001018555821561054e579182015b8281111561054e578251825591602001919060010190610533565b5061055a929150610575565b5090565b604080518082019091526000808252602082015290565b6102c991905b8082111561055a576000815560010161057b5600a165627a7a723058207e0cfcb8e796037851028c428aca173ecd924a4572c51605ecebbf548fecdf3d0029" - code_TestStorageAndCpu_storageAndCpu = "6080604052600060045534801561001557600080fd5b506104c0806100256000396000f3006080604052600436106100a35763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632656df4881146100a85780633755cd3c146100bf5780636f269385146100e95780637d965688146100fe578063a05b257714610116578063b0d6304d1461012e578063b648763914610162578063bbe1d75b146101ec578063f8a8fd6d14610201578063fe75faab14610216575b600080fd5b3480156100b457600080fd5b506100bd61022e565b005b3480156100cb57600080fd5b506100d7600435610230565b60408051918252519081900360200190f35b3480156100f557600080fd5b506100bd61024f565b34801561010a57600080fd5b506100d7600435610296565b34801561012257600080fd5b506100d76004356102b6565b34801561013a57600080fd5b506100d773ffffffffffffffffffffffffffffffffffffffff60043581169060243516610300565b34801561016e57600080fd5b5061017761031d565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101b1578181015183820152602001610199565b50505050905090810190601f1680156101de5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156101f857600080fd5b506100d76103ab565b34801561020d57600080fd5b506100bd6103b1565b34801561022257600080fd5b506100d76004356103c2565b565b600180548290811061023e57fe5b600091825260209091200154905081565b6040805180820190915260088082527f31323334353637380000000000000000000000000000000000000000000000006020909201918252610293916000916103f9565b50565b600080805b838110156102af576001918201910161029b565b5092915050565b600080805b838110156102af5760018054808201825560008290527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60182905591820191016102bb565b600360209081526000928352604080842090915290825290205481565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103a35780601f10610378576101008083540402835291602001916103a3565b820191906000526020600020905b81548152906001019060200180831161038657829003601f168201915b505050505081565b60025481565b60048054600101905561022e6103b1565b60006103cd826103d8565b600281905592915050565b60006103e6600283036103d8565b6103f2600184036103d8565b0192915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061043a57805160ff1916838001178555610467565b82800160010185558215610467579182015b8281111561046757825182559160200191906001019061044c565b50610473929150610477565b5090565b61049191905b80821115610473576000815560010161047d565b905600a165627a7a72305820ca3a4850a926264dc27c0e3483830bac3385c61565c738281b05d747d20676670029" - code_WalletTestAccount013 = "608060405234801561001057600080fd5b5061045c806100206000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806304c58438146100725780634f2be91f1461009f578063812db772146100b657806393cd5755146100e3578063d1cd64e914610189575b600080fd5b34801561007e57600080fd5b5061009d600480360381019080803590602001909291905050506101a0565b005b3480156100ab57600080fd5b506100b4610230565b005b3480156100c257600080fd5b506100e1600480360381019080803590602001909291905050506102a2565b005b3480156100ef57600080fd5b5061010e600480360381019080803590602001909291905050506102c3565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561014e578082015181840152602081019050610133565b50505050905090810190601f16801561017b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561019557600080fd5b5061019e61037e565b005b6000600190505b8181101561022c5760008060018154018082558091505090600182039060005260206000200160006040805190810160405280600881526020017f31323334353637380000000000000000000000000000000000000000000000008152509091909150908051906020019061021d92919061038b565b505080806001019150506101a7565b5050565b60008060018154018082558091505090600182039060005260206000200160006040805190810160405280600881526020017f61626364656667680000000000000000000000000000000000000000000000008152509091909150908051906020019061029e92919061038b565b5050565b6000600190505b81811115156102bf5780806001019150506102a9565b5050565b6000818154811015156102d257fe5b906000526020600020016000915090508054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103765780601f1061034b57610100808354040283529160200191610376565b820191906000526020600020905b81548152906001019060200180831161035957829003601f168201915b505050505081565b6000808060010191505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106103cc57805160ff19168380011785556103fa565b828001600101855582156103fa579182015b828111156103f95782518255916020019190600101906103de565b5b509050610407919061040b565b5090565b61042d91905b80821115610429576000816000905550600101610411565b5090565b905600a165627a7a7230582087d9880a135295a17100f63b8941457f4369204d3ccc9ce4a1abf99820eb68480029" - code_ContractEventAndLog1 = "608060405234801561001057600080fd5b50610e6c806100206000396000f3006080604052600436106100fc576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630265ec371461010b5780630a98bcec146101155780630d16a1e31461013557806312d2c2091461013f57806340de00d314610149578063462da3081461017c57806360edcb5f1461018657806367392426146101905780636cb244f11461019a5780636e5f4528146101cd57806372f48b1a146101d7578063797d1255146101f75780638615960d14610232578063bd85753b14610249578063ce6db7c0146102f8578063d0a0eadc146103a7578063d228d484146103be578063d52aca67146103e9575b34801561010857600080fd5b50005b6101136103f3565b005b61013360048036038101908080359060200190929190505050610485565b005b61013d610535565b005b61014761057c565b005b34801561015557600080fd5b5061015e610669565b60405180826000191660001916815260200191505060405180910390f35b6101846106cc565b005b61018e610798565b005b61019861080a565b005b3480156101a657600080fd5b506101af610872565b60405180826000191660001916815260200191505060405180910390f35b6101d56108af565b005b6101f56004803603810190808035906020019092919050505061095b565b005b34801561020357600080fd5b506102306004803603810190808035151590602001909291908035151590602001909291905050506109e1565b005b34801561023e57600080fd5b50610247610a23565b005b34801561025557600080fd5b506102f6600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610aba565b005b34801561030457600080fd5b506103a5600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610bbd565b005b3480156103b357600080fd5b506103bc610c9f565b005b3480156103ca57600080fd5b506103d3610d7c565b6040518082815260200191505060405180910390f35b6103f1610d9b565b005b60008030915034905034600102600019168273ffffffffffffffffffffffffffffffffffffffff16600102600019163373ffffffffffffffffffffffffffffffffffffffff16600102600019167fbeabacc8ffedac16e9a60acdb2ca743d80c2ebb44977a93fa8e483c74d2b35a860010260405180826000191660001916815260200191505060405180910390a35050565b6000806000309250349150600090505b8381101561052f5734600102600019168373ffffffffffffffffffffffffffffffffffffffff16600102600019163373ffffffffffffffffffffffffffffffffffffffff16600102600019167fbeabacc8ffedac16e9a60acdb2ca743d80c2ebb44977a93fa8e483c74d2b35a860010260405180826000191660001916815260200191505060405180910390a38080600101915050610495565b50505050565b600080309150349050808273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1660405160405180910390a35050565b600080309150349050808273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fbeabacc8ffedac16e9a60acdb2ca743d80c2ebb44977a93fa8e483c74d2b35a860405160405180910390a48173ffffffffffffffffffffffffffffffffffffffff16600102600019163373ffffffffffffffffffffffffffffffffffffffff166001026000191634600102600019167fbeabacc8ffedac16e9a60acdb2ca743d80c2ebb44977a93fa8e483c74d2b35a860010260405180826000191660001916815260200191505060405180910390a35050565b600060405180807f7472616e7366657228616464726573732c616464726573732c75696e7432353681526020017f290000000000000000000000000000000000000000000000000000000000000081525060210190506040518091039020905090565b600080309150349050808273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1660405160405180910390a38173ffffffffffffffffffffffffffffffffffffffff16600102600019163373ffffffffffffffffffffffffffffffffffffffff166001026000191634600102600019167fbeabacc8ffedac16e9a60acdb2ca743d80c2ebb44977a93fa8e483c74d2b35a860010260405180826000191660001916815260200191505060405180910390a35050565b6000803091503490508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f233b34846284da6adf1006478380fa328232b0a6ede5041bfe21ea9be1b3b88a836040518082815260200191505060405180910390a35050565b600080309150349050808273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fbeabacc8ffedac16e9a60acdb2ca743d80c2ebb44977a93fa8e483c74d2b35a860405160405180910390a45050565b600060405180807f4465706f73697428616464726573732c686173683235362c75696e743235362981525060200190506040518091039020905090565b6000803091503490507f0c2fb0b24194d40c1d753915af9ba7185bd7a703e4374ca9fb376a4f7c91dcca338383604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a15050565b6000806000309250349150600090505b838110156109db57818373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fbeabacc8ffedac16e9a60acdb2ca743d80c2ebb44977a93fa8e483c74d2b35a860405160405180910390a4808060010191505061096b565b50505050565b8015157f37f1c240387a938c945ab44c1cff92ff6d224ce37ee4db1d770944201f6fcc2983604051808215151515815260200191505060405180910390a25050565b7f4e2428acf9e70e881e61b1dabc7589a9c3800a9737a6a67e29f70a1397925b2c600160c8610bb8619c40604051808560ff1681526020018467ffffffffffffffff168152602001836fffffffffffffffffffffffffffffffff168152602001827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260200194505050505060405180910390a1565b806040518082805190602001908083835b602083101515610af05780518252602082019150602081019050602083039250610acb565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207fcb164b075277ecd24c68a6ff14fbdd71a2c6cc9cf7bec9797b8227471f740dfa836040518080602001828103825283818151815260200191508051906020019080838360005b83811015610b7f578082015181840152602081019050610b64565b50505050905090810190601f168015610bac5780820380516001836020036101000a031916815260200191505b509250505060405180910390a25050565b806040518082805190602001908083835b602083101515610bf35780518252602082019150602081019050602083039250610bce565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020826040518080602001828103825283818151815260200191508051906020019080838360005b83811015610c61578082015181840152602081019050610c46565b50505050905090810190601f168015610c8e5780820380516001836020036101000a031916815260200191505b509250505060405180910390a15050565b7fb24eee86cea7aa22cfdcfaa01da5152afa042fd9a0a446ef038034c705bc25d57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8307ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4487ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd9da600604051808560000b81526020018460080b81526020018360100b815260200182601c0b815260200194505050505060405180910390a1565b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b600080309150349050807f39f02551491f3fe37d6822a5987d21ac6d6385c6dc38b97a29699a5bb45f038a3384604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a250505600a165627a7a723058206121fcbe7b56027d526e504c463f8f29064931be358774a6a065110af09d21b70029" - code_ContractEventAndLog2 = "608060405234801561001057600080fd5b50610369806100206000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680634247b80e14610066578063d0e30db014610070578063d228d4841461007a575b34801561006357600080fd5b50005b61006e6100a5565b005b6100786102b6565b005b34801561008657600080fd5b5061008f61031e565b6040518082815260200191505060405180910390f35b6000806000630420042076010000000000000000000000000000000000000000000002925063042004206f01000000000000000000000000000000029150630420042060010290507f88c75e92614e379252c5b1847e9753f9668ebb5ebb9a148333bdf0458d3d9cdf838383604051808475ffffffffffffffffffffffffffffffffffffffffffff191675ffffffffffffffffffffffffffffffffffffffffffff19168152602001836effffffffffffffffffffffffffffff19166effffffffffffffffffffffffffffff191681526020018260001916600019168152602001935050505060405180910390a1828282604051808475ffffffffffffffffffffffffffffffffffffffffffff191675ffffffffffffffffffffffffffffffffffffffffffff19168152602001836effffffffffffffffffffffffffffff19166effffffffffffffffffffffffffffff191681526020018260001916600019168152602001935050505060405180910390a08060001916826effffffffffffffffffffffffffffff19168475ffffffffffffffffffffffffffffffffffffffffffff19167f47f711f8177f4e1a7a44e07049543e0b69ef4b740c817c404c3ef911623fa89160405160405180910390a48060001916826effffffffffffffffffffffffffffff19168475ffffffffffffffffffffffffffffffffffffffffffff191660405160405180910390a3505050565b600080309150349050808273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fbeabacc8ffedac16e9a60acdb2ca743d80c2ebb44977a93fa8e483c74d2b35a860405160405180910390a45050565b60003073ffffffffffffffffffffffffffffffffffffffff16319050905600a165627a7a72305820f5c3bb96350b175387f95b45f915f736ba0468b0880f65c542b8b55d261e72760029" - - code_OriginEnergyLimit001 = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b5061014e8061003a6000396000f3006080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663329000b58114610045575b600080fd5b34801561005157600080fd5b50d3801561005e57600080fd5b50d2801561006b57600080fd5b50610077600435610089565b60408051918252519081900360200190f35b604080516003808252608082019092526000916060919060208201838038833901905050905060018160008151811015156100c057fe5b602090810290910101528051600290829060019081106100dc57fe5b602090810290910101528051600390829060029081106100f857fe5b60209081029091010152805181908490811061011057fe5b906020019060200201519150509190505600a165627a7a7230582058dd457e2aeba46e78dd8b9c36b777d362763c05ec1ad62e0d79de51ff3dde790029" - code_OriginEnergyLimit004 = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b5061014e8061003a6000396000f3006080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663329000b58114610045575b600080fd5b34801561005157600080fd5b50d3801561005e57600080fd5b50d2801561006b57600080fd5b50610077600435610089565b60408051918252519081900360200190f35b604080516003808252608082019092526000916060919060208201838038833901905050905060018160008151811015156100c057fe5b602090810290910101528051600290829060019081106100dc57fe5b602090810290910101528051600390829060029081106100f857fe5b60209081029091010152805181908490811061011057fe5b906020019060200201519150509190505600a165627a7a723058206503efa46ed431a2604563d7764b4b9e6ca03238259cb133c878592fc43a4b670029" - - - code_ContractTrcToken001_transferTokenContract = "6080604052d3600055d2600155346002556101418061001f6000396000f3006080604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166305c24200811461005b5780633be9ece71461008157806371dc08ce146100aa575b600080fd5b6100636100b2565b60408051938452602084019290925282820152519081900360600190f35b6100a873ffffffffffffffffffffffffffffffffffffffff600435166024356044356100c0565b005b61006361010d565b600054600154600254909192565b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad0945050505050158015610107573d6000803e3d6000fd5b50505050565bd3d2349091925600a165627a7a72305820a2fb39541e90eda9a2f5f9e7905ef98e66e60dd4b38e00b05de418da3154e7570029" - code_ContractTrcToken002_transferTokenContract = "6080604052610118806100136000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633be9ece78114604d57806371dc08ce146074575b600080fd5b607273ffffffffffffffffffffffffffffffffffffffff600435166024356044356098565b005b607a60e4565b60408051938452602084019290925282820152519081900360600190f35b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad094505050505015801560de573d6000803e3d6000fd5b50505050565bd3d2349091925600a165627a7a72305820b8d4f8ea5443a03d615ea5dfe7a7435498522f9c7abeb25583d953ee2d20be4a0029" - code_ContractTrcToken005_transferTokenContract = "6080604052610118806100136000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633be9ece78114604d57806371dc08ce146074575b600080fd5b607273ffffffffffffffffffffffffffffffffffffffff600435166024356044356098565b005b607a60e4565b60408051938452602084019290925282820152519081900360600190f35b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad094505050505015801560de573d6000803e3d6000fd5b50505050565bd3d2349091925600a165627a7a72305820b8d4f8ea5443a03d615ea5dfe7a7435498522f9c7abeb25583d953ee2d20be4a0029" - code_ContractTrcToken006_transferTokenContract = "6080604052610118806100136000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633be9ece78114604d57806371dc08ce146074575b600080fd5b607273ffffffffffffffffffffffffffffffffffffffff600435166024356044356098565b005b607a60e4565b60408051938452602084019290925282820152519081900360600190f35b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad094505050505015801560de573d6000803e3d6000fd5b50505050565bd3d2349091925600a165627a7a72305820b8d4f8ea5443a03d615ea5dfe7a7435498522f9c7abeb25583d953ee2d20be4a0029" - code_ContractTrcToken011_transferTokenContract = "6080604052610343806100136000396000f3006080604052600436106100985763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663144401f6811461009a5780631ea31431146100b45780632c5c6641146100c8578063544051aa146100dc578063584d4262146100f057806371dc08ce1461011657806393bc91fd14610137578063a730416e1461014b578063acea104514610162575b005b610098600160a060020a0360043516602435604435610176565b610098600160a060020a03600435166101b6565b610098600160a060020a03600435166101f1565b610098600160a060020a0360043516610231565b610104600160a060020a0360043516610270565b60408051918252519081900360200190f35b61011e610281565b6040805192835260208301919091528051918290030190f35b610098600160a060020a0360043516610287565b610104600160a060020a03600435166024356102c7565b610098600160a060020a03600435166102d8565b604051600160a060020a0384169083156108fc029084908490600081818185878a8ad09450505050501580156101b0573d6000803e3d6000fd5b50505050565b604051600160a060020a038216906000906000199082908181818181878a82d09450505050501580156101ed573d6000803e3d6000fd5b5050565b604051600160a060020a0382169060009067800000000000000090620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b604051600160a060020a03821690600090600190680200000000000f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a0316620f4241d190565bd3d29091565b604051600160a060020a03821690600090677fffffffffffffff90620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a039190911690d190565b604051600160a060020a038216906108fc90600090678000000000000001908281818185828a8ad09450505050501580156101ed573d6000803e3d6000fd00a165627a7a72305820716217ff39873b1f852cdc214cfb38a4c2337d18fbd1128b69b2866f7f24ae1c0029" - code_ContractTrcToken011_resultContract = "608060405260658060116000396000f30060806040819052d38152d260a0523460c0527fd1ed7a3c020c4f5939654147940a147a8e4e638fa1e8f5664b5efbd1e1f3c4a690606090a10000a165627a7a72305820ea1e6d9606638e6c9e72dcdcc749561b826ec85713c003fae9d4700a2919040f0029" - code_ContractTrcToken012_transferTokenContract = "6080604052610343806100136000396000f3006080604052600436106100985763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663144401f6811461009a5780631ea31431146100b45780632c5c6641146100c8578063544051aa146100dc578063584d4262146100f057806371dc08ce1461011657806393bc91fd14610137578063a730416e1461014b578063acea104514610162575b005b610098600160a060020a0360043516602435604435610176565b610098600160a060020a03600435166101b6565b610098600160a060020a03600435166101f1565b610098600160a060020a0360043516610231565b610104600160a060020a0360043516610270565b60408051918252519081900360200190f35b61011e610281565b6040805192835260208301919091528051918290030190f35b610098600160a060020a0360043516610287565b610104600160a060020a03600435166024356102c7565b610098600160a060020a03600435166102d8565b604051600160a060020a0384169083156108fc029084908490600081818185878a8ad09450505050501580156101b0573d6000803e3d6000fd5b50505050565b604051600160a060020a038216906000906000199082908181818181878a82d09450505050501580156101ed573d6000803e3d6000fd5b5050565b604051600160a060020a0382169060009067800000000000000090620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b604051600160a060020a03821690600090600190680200000000000f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a0316620f4241d190565bd3d29091565b604051600160a060020a03821690600090677fffffffffffffff90620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a039190911690d190565b604051600160a060020a038216906108fc90600090678000000000000001908281818185828a8ad09450505050501580156101ed573d6000803e3d6000fd00a165627a7a72305820716217ff39873b1f852cdc214cfb38a4c2337d18fbd1128b69b2866f7f24ae1c0029" - code_ContractTrcToken014_transferTokenContract = "6080604052610343806100136000396000f3006080604052600436106100985763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663144401f6811461009a5780631ea31431146100b45780632c5c6641146100c8578063544051aa146100dc578063584d4262146100f057806371dc08ce1461011657806393bc91fd14610137578063a730416e1461014b578063acea104514610162575b005b610098600160a060020a0360043516602435604435610176565b610098600160a060020a03600435166101b6565b610098600160a060020a03600435166101f1565b610098600160a060020a0360043516610231565b610104600160a060020a0360043516610270565b60408051918252519081900360200190f35b61011e610281565b6040805192835260208301919091528051918290030190f35b610098600160a060020a0360043516610287565b610104600160a060020a03600435166024356102c7565b610098600160a060020a03600435166102d8565b604051600160a060020a0384169083156108fc029084908490600081818185878a8ad09450505050501580156101b0573d6000803e3d6000fd5b50505050565b604051600160a060020a038216906000906000199082908181818181878a82d09450505050501580156101ed573d6000803e3d6000fd5b5050565b604051600160a060020a0382169060009067800000000000000090620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b604051600160a060020a03821690600090600190680200000000000f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a0316620f4241d190565bd3d29091565b604051600160a060020a03821690600090677fffffffffffffff90620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a039190911690d190565b604051600160a060020a038216906108fc90600090678000000000000001908281818185828a8ad09450505050501580156101ed573d6000803e3d6000fd00a165627a7a72305820716217ff39873b1f852cdc214cfb38a4c2337d18fbd1128b69b2866f7f24ae1c0029" - code_ContractTrcToken014_resultContract = "608060405260658060116000396000f30060806040819052d38152d260a0523460c0527fd1ed7a3c020c4f5939654147940a147a8e4e638fa1e8f5664b5efbd1e1f3c4a690606090a10000a165627a7a72305820ea1e6d9606638e6c9e72dcdcc749561b826ec85713c003fae9d4700a2919040f0029" - code_ContractTrcToken016_transferTokenContract = "6080604052610343806100136000396000f3006080604052600436106100985763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663144401f6811461009a5780631ea31431146100b45780632c5c6641146100c8578063544051aa146100dc578063584d4262146100f057806371dc08ce1461011657806393bc91fd14610137578063a730416e1461014b578063acea104514610162575b005b610098600160a060020a0360043516602435604435610176565b610098600160a060020a03600435166101b6565b610098600160a060020a03600435166101f1565b610098600160a060020a0360043516610231565b610104600160a060020a0360043516610270565b60408051918252519081900360200190f35b61011e610281565b6040805192835260208301919091528051918290030190f35b610098600160a060020a0360043516610287565b610104600160a060020a03600435166024356102c7565b610098600160a060020a03600435166102d8565b604051600160a060020a0384169083156108fc029084908490600081818185878a8ad09450505050501580156101b0573d6000803e3d6000fd5b50505050565b604051600160a060020a038216906000906000199082908181818181878a82d09450505050501580156101ed573d6000803e3d6000fd5b5050565b604051600160a060020a0382169060009067800000000000000090620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b604051600160a060020a03821690600090600190680200000000000f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a0316620f4241d190565bd3d29091565b604051600160a060020a03821690600090677fffffffffffffff90620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a039190911690d190565b604051600160a060020a038216906108fc90600090678000000000000001908281818185828a8ad09450505050501580156101ed573d6000803e3d6000fd00a165627a7a72305820716217ff39873b1f852cdc214cfb38a4c2337d18fbd1128b69b2866f7f24ae1c0029" - code_ContractTrcToken016_resultContract = "608060405260658060116000396000f30060806040819052d38152d260a0523460c0527fd1ed7a3c020c4f5939654147940a147a8e4e638fa1e8f5664b5efbd1e1f3c4a690606090a10000a165627a7a72305820ea1e6d9606638e6c9e72dcdcc749561b826ec85713c003fae9d4700a2919040f0029" - code_ContractTrcToken017_recieveTokenContract = "60806040526000805560c5806100166000396000f30060806040526004361060485763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166362548c7b8114604a578063890eba68146050575b005b6048608c565b348015605b57600080fd5b50d38015606757600080fd5b50d28015607357600080fd5b50607a6093565b60408051918252519081900360200190f35b6001600055565b600054815600a165627a7a723058204c4f1bb8eca0c4f1678cc7cc1179e03d99da2a980e6792feebe4d55c89c022830029" - code_ContractTrcToken042_transferTokenContract = "6080604052610343806100136000396000f3006080604052600436106100985763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663144401f6811461009a5780631ea31431146100b45780632c5c6641146100c8578063544051aa146100dc578063584d4262146100f057806371dc08ce1461011657806393bc91fd14610137578063a730416e1461014b578063acea104514610162575b005b610098600160a060020a0360043516602435604435610176565b610098600160a060020a03600435166101b6565b610098600160a060020a03600435166101f1565b610098600160a060020a0360043516610231565b610104600160a060020a0360043516610270565b60408051918252519081900360200190f35b61011e610281565b6040805192835260208301919091528051918290030190f35b610098600160a060020a0360043516610287565b610104600160a060020a03600435166024356102c7565b610098600160a060020a03600435166102d8565b604051600160a060020a0384169083156108fc029084908490600081818185878a8ad09450505050501580156101b0573d6000803e3d6000fd5b50505050565b604051600160a060020a038216906000906000199082908181818181878a82d09450505050501580156101ed573d6000803e3d6000fd5b5050565b604051600160a060020a0382169060009067800000000000000090620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b604051600160a060020a03821690600090600190680200000000000f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a0316620f4241d190565bd3d29091565b604051600160a060020a03821690600090677fffffffffffffff90620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a039190911690d190565b604051600160a060020a038216906108fc90600090678000000000000001908281818185828a8ad09450505050501580156101ed573d6000803e3d6000fd00a165627a7a72305820716217ff39873b1f852cdc214cfb38a4c2337d18fbd1128b69b2866f7f24ae1c0029" - code_ContractTrcToken042_recieveTokenContract = "608060405260658060116000396000f30060806040819052d38152d260a0523460c0527fd1ed7a3c020c4f5939654147940a147a8e4e638fa1e8f5664b5efbd1e1f3c4a690606090a10000a165627a7a72305820ea1e6d9606638e6c9e72dcdcc749561b826ec85713c003fae9d4700a2919040f0029" - code_ContractTrcToken043_transferTokenContract = "6080604052610343806100136000396000f3006080604052600436106100985763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663144401f6811461009a5780631ea31431146100b45780632c5c6641146100c8578063544051aa146100dc578063584d4262146100f057806371dc08ce1461011657806393bc91fd14610137578063a730416e1461014b578063acea104514610162575b005b610098600160a060020a0360043516602435604435610176565b610098600160a060020a03600435166101b6565b610098600160a060020a03600435166101f1565b610098600160a060020a0360043516610231565b610104600160a060020a0360043516610270565b60408051918252519081900360200190f35b61011e610281565b6040805192835260208301919091528051918290030190f35b610098600160a060020a0360043516610287565b610104600160a060020a03600435166024356102c7565b610098600160a060020a03600435166102d8565b604051600160a060020a0384169083156108fc029084908490600081818185878a8ad09450505050501580156101b0573d6000803e3d6000fd5b50505050565b604051600160a060020a038216906000906000199082908181818181878a82d09450505050501580156101ed573d6000803e3d6000fd5b5050565b604051600160a060020a0382169060009067800000000000000090620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b604051600160a060020a03821690600090600190680200000000000f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a0316620f4241d190565bd3d29091565b604051600160a060020a03821690600090677fffffffffffffff90620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a039190911690d190565b604051600160a060020a038216906108fc90600090678000000000000001908281818185828a8ad09450505050501580156101ed573d6000803e3d6000fd00a165627a7a72305820716217ff39873b1f852cdc214cfb38a4c2337d18fbd1128b69b2866f7f24ae1c0029" - code_ContractTrcToken043_recieveTokenContract = "608060405260658060116000396000f30060806040819052d38152d260a0523460c0527fd1ed7a3c020c4f5939654147940a147a8e4e638fa1e8f5664b5efbd1e1f3c4a690606090a10000a165627a7a72305820ea1e6d9606638e6c9e72dcdcc749561b826ec85713c003fae9d4700a2919040f0029" - code_ContractTrcToken046_transferTokenContract = "6080604052610118806100136000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633be9ece78114604d57806371dc08ce146074575b600080fd5b607273ffffffffffffffffffffffffffffffffffffffff600435166024356044356098565b005b607a60e4565b60408051938452602084019290925282820152519081900360600190f35b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad094505050505015801560de573d6000803e3d6000fd5b50505050565bd3d2349091925600a165627a7a72305820b8d4f8ea5443a03d615ea5dfe7a7435498522f9c7abeb25583d953ee2d20be4a0029" - code_ContractTrcToken047_transferTokenContract = "6080604052610118806100136000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633be9ece78114604d57806371dc08ce146074575b600080fd5b607273ffffffffffffffffffffffffffffffffffffffff600435166024356044356098565b005b607a60e4565b60408051938452602084019290925282820152519081900360600190f35b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad094505050505015801560de573d6000803e3d6000fd5b50505050565bd3d2349091925600a165627a7a72305820b8d4f8ea5443a03d615ea5dfe7a7435498522f9c7abeb25583d953ee2d20be4a0029" - code2_ContractTrcToken023_tokenTest = "608060405260e2806100126000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633be9ece781146043575b600080fd5b606873ffffffffffffffffffffffffffffffffffffffff60043516602435604435606a565b005b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad094505050505015801560b0573d6000803e3d6000fd5b505050505600a165627a7a7230582006508824be321d3ad4594b1b2dae9099960f982a99b5e1121896fbbb115967780029" - code_ContractTrcToken023_tokenTest = "60806040526000805560b3806100166000396000f300608060405260043610603e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663890eba6881146045575b6001600055005b348015605057600080fd5b50d38015605c57600080fd5b50d28015606857600080fd5b50606f6081565b60408051918252519081900360200190f35b600054815600a165627a7a72305820fc51dbe84825144f5e50d2ab8c418a5b1bfe75a31b054528816f2311b2632d6d0029" - code_ContractTrcToken026_BTest = "6080604052610145806100136000396000f3006080604052600436106100275763ffffffff60e060020a600035041663cb35b7e28114610029575b005b61002773ffffffffffffffffffffffffffffffffffffffff600435811690602435166044356064358373ffffffffffffffffffffffffffffffffffffffff1660405180807f7472616e7328616464726573732c75696e743235362c747263546f6b656e2900815250601f019050604051809103902060e060020a90048484846040518463ffffffff1660e060020a028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200183815260200182815260200193505050506000604051808303816000875af150505050505050505600a165627a7a72305820f80979e10a32bf6d6995716d7c5b159944473c2db9ac4ca5e780cfcd620261260029" - code1_ContractTrcToken026_CTest = "608060405260d9806100126000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634f53d8a881146040575b005b603e73ffffffffffffffffffffffffffffffffffffffff6004351660243560443560405173ffffffffffffffffffffffffffffffffffffffff84169083156108fc029084908490600081818185878a8ad094505050505015801560a7573d6000803e3d6000fd5b505050505600a165627a7a723058203db4692a33e354b8bb6b6274f3c25ca36facafc80e996629c2b7c8e79ef40f2e0029" - code1_ContractTrcToken026_tokenTest = "6080604052610257806100136000396000f3006080604052600436106100325763ffffffff60e060020a6000350416636409a1c0811461003457806383efe58114610067575b005b61003273ffffffffffffffffffffffffffffffffffffffff6004358116906024358116906044351660643560843561009a565b61003273ffffffffffffffffffffffffffffffffffffffff60043581169060243581169060443516606435608435610163565b604080517f7472616e734328616464726573732c616464726573732c75696e743235362c7481527f7263546f6b656e290000000000000000000000000000000000000000000000006020820152815190819003602801812063ffffffff60e060020a91829004908116909102825273ffffffffffffffffffffffffffffffffffffffff8781166004840152868116602484015260448301869052606483018590529251928816929091608480820192600092909190829003018183875af1505050505050505050565b604080517f7472616e734328616464726573732c616464726573732c75696e743235362c7481527f7263546f6b656e290000000000000000000000000000000000000000000000006020820152815190819003602801812063ffffffff60e060020a91829004908116909102825273ffffffffffffffffffffffffffffffffffffffff87811660048401528681166024840152604483018690526064830185905292519288169290916084808201926000929091908290030181865af45050505050505050505600a165627a7a72305820554cb78d3d6082a8b93092e5edd2b66b83a47707eb8cbbfdbb06a0806fce72840029" - code_ContractTrcToken027_BTest = "6080604052610145806100136000396000f3006080604052600436106100275763ffffffff60e060020a600035041663cb35b7e28114610029575b005b61002773ffffffffffffffffffffffffffffffffffffffff600435811690602435166044356064358373ffffffffffffffffffffffffffffffffffffffff1660405180807f7472616e7328616464726573732c75696e743235362c747263546f6b656e2900815250601f019050604051809103902060e060020a90048484846040518463ffffffff1660e060020a028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200183815260200182815260200193505050506000604051808303816000875af150505050505050505600a165627a7a72305820f80979e10a32bf6d6995716d7c5b159944473c2db9ac4ca5e780cfcd620261260029" - code_ContractTrcToken027_CTest = "608060405260d9806100126000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634f53d8a881146040575b005b603e73ffffffffffffffffffffffffffffffffffffffff6004351660243560443560405173ffffffffffffffffffffffffffffffffffffffff84169083156108fc029084908490600081818185878a8ad094505050505015801560a7573d6000803e3d6000fd5b505050505600a165627a7a723058203db4692a33e354b8bb6b6274f3c25ca36facafc80e996629c2b7c8e79ef40f2e0029" - - code_ContractTrcToken027_tokenTest = "6080604052610257806100136000396000f3006080604052600436106100325763ffffffff60e060020a6000350416636409a1c0811461003457806383efe58114610067575b005b61003273ffffffffffffffffffffffffffffffffffffffff6004358116906024358116906044351660643560843561009a565b61003273ffffffffffffffffffffffffffffffffffffffff60043581169060243581169060443516606435608435610163565b604080517f7472616e734328616464726573732c616464726573732c75696e743235362c7481527f7263546f6b656e290000000000000000000000000000000000000000000000006020820152815190819003602801812063ffffffff60e060020a91829004908116909102825273ffffffffffffffffffffffffffffffffffffffff8781166004840152868116602484015260448301869052606483018590529251928816929091608480820192600092909190829003018183875af1505050505050505050565b604080517f7472616e734328616464726573732c616464726573732c75696e743235362c7481527f7263546f6b656e290000000000000000000000000000000000000000000000006020820152815190819003602801812063ffffffff60e060020a91829004908116909102825273ffffffffffffffffffffffffffffffffffffffff87811660048401528681166024840152604483018690526064830185905292519288169290916084808201926000929091908290030181865af45050505050505050505600a165627a7a72305820554cb78d3d6082a8b93092e5edd2b66b83a47707eb8cbbfdbb06a0806fce72840029" - code_ContractTrcToken028_tokenTest = "608060405260016000556102a5806100186000396000f3006080604052600436106100565763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630dbe671f811461005b578063baf462821461009c578063d46300fd146100a9575b600080fd5b34801561006757600080fd5b50d3801561007457600080fd5b50d2801561008157600080fd5b5061008a6100b1565b60408051918252519081900360200190f35b6100a76004356100b7565b005b61008a610182565b60005481565b60006100c1610188565b604051809103906000f0801580156100dd573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663205e3c9c836040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b15801561014f57600080fd5b505af1158015610163573d6000803e3d6000fd5b505050506040513d602081101561017957600080fd5b50516000555050565b60005490565b60405160e28061019883390190560060806040526000805560cc806100166000396000f30060806040526004361060485763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663205e3c9c8114604a578063890eba68146065575b005b6053600435608f565b60408051918252519081900360200190f35b348015607057600080fd5b50d38015607c57600080fd5b50d28015608857600080fd5b506053609a565b506009600081905590565b600054815600a165627a7a7230582000d7b938c0aa356a26f89e8816d8cafa65acdc21fbfc77112e7b774cc35ec6fa0029a165627a7a723058204f7b7aa7d1a83605c6830eee3ee774b9a06722e6c70a9dce28a51064abe834160029" - code_ContractTrcToken054_transferTokenContract = "6080604052610118806100136000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633be9ece78114604d57806371dc08ce146074575b600080fd5b607273ffffffffffffffffffffffffffffffffffffffff600435166024356044356098565b005b607a60e4565b60408051938452602084019290925282820152519081900360600190f35b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad094505050505015801560de573d6000803e3d6000fd5b50505050565bd3d2349091925600a165627a7a72305820b8d4f8ea5443a03d615ea5dfe7a7435498522f9c7abeb25583d953ee2d20be4a0029" - code_ContractTrcToken055_transferTokenContract = "6080604052610118806100136000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633be9ece78114604d57806371dc08ce146074575b600080fd5b607273ffffffffffffffffffffffffffffffffffffffff600435166024356044356098565b005b607a60e4565b60408051938452602084019290925282820152519081900360600190f35b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad094505050505015801560de573d6000803e3d6000fd5b50505050565bd3d2349091925600a165627a7a72305820b8d4f8ea5443a03d615ea5dfe7a7435498522f9c7abeb25583d953ee2d20be4a0029" - code_ContractTrcToken060_transferTokenContract = "6080604052d3600055d2600155346002556101418061001f6000396000f3006080604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166305c24200811461005b5780633be9ece71461008157806371dc08ce146100aa575b600080fd5b6100636100b2565b60408051938452602084019290925282820152519081900360600190f35b6100a873ffffffffffffffffffffffffffffffffffffffff600435166024356044356100c0565b005b61006361010d565b600054600154600254909192565b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad0945050505050158015610107573d6000803e3d6000fd5b50505050565bd3d2349091925600a165627a7a72305820a2fb39541e90eda9a2f5f9e7905ef98e66e60dd4b38e00b05de418da3154e7570029" - code_ContractTrcToken061_transferTokenContract = "6080604052d3600055d2600155346002556101418061001f6000396000f3006080604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166305c24200811461005b5780633be9ece71461008157806371dc08ce146100aa575b600080fd5b6100636100b2565b60408051938452602084019290925282820152519081900360600190f35b6100a873ffffffffffffffffffffffffffffffffffffffff600435166024356044356100c0565b005b61006361010d565b600054600154600254909192565b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad0945050505050158015610107573d6000803e3d6000fd5b50505050565bd3d2349091925600a165627a7a72305820a2fb39541e90eda9a2f5f9e7905ef98e66e60dd4b38e00b05de418da3154e7570029" - code_ContractTrcToken062_transferTokenContract = "6080604052610343806100136000396000f3006080604052600436106100985763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663144401f6811461009a5780631ea31431146100b45780632c5c6641146100c8578063544051aa146100dc578063584d4262146100f057806371dc08ce1461011657806393bc91fd14610137578063a730416e1461014b578063acea104514610162575b005b610098600160a060020a0360043516602435604435610176565b610098600160a060020a03600435166101b6565b610098600160a060020a03600435166101f1565b610098600160a060020a0360043516610231565b610104600160a060020a0360043516610270565b60408051918252519081900360200190f35b61011e610281565b6040805192835260208301919091528051918290030190f35b610098600160a060020a0360043516610287565b610104600160a060020a03600435166024356102c7565b610098600160a060020a03600435166102d8565b604051600160a060020a0384169083156108fc029084908490600081818185878a8ad09450505050501580156101b0573d6000803e3d6000fd5b50505050565b604051600160a060020a038216906000906000199082908181818181878a82d09450505050501580156101ed573d6000803e3d6000fd5b5050565b604051600160a060020a0382169060009067800000000000000090620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b604051600160a060020a03821690600090600190680200000000000f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a0316620f4241d190565bd3d29091565b604051600160a060020a03821690600090677fffffffffffffff90620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a039190911690d190565b604051600160a060020a038216906108fc90600090678000000000000001908281818185828a8ad09450505050501580156101ed573d6000803e3d6000fd00a165627a7a72305820716217ff39873b1f852cdc214cfb38a4c2337d18fbd1128b69b2866f7f24ae1c0029" - code_ContractTrcToken062_recieveTokenContract = "608060405260658060116000396000f30060806040819052d38152d260a0523460c0527fd1ed7a3c020c4f5939654147940a147a8e4e638fa1e8f5664b5efbd1e1f3c4a690606090a10000a165627a7a72305820ea1e6d9606638e6c9e72dcdcc749561b826ec85713c003fae9d4700a2919040f0029" - code_ContractTrcToken063_transferTokenContract = "6080604052610343806100136000396000f3006080604052600436106100985763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663144401f6811461009a5780631ea31431146100b45780632c5c6641146100c8578063544051aa146100dc578063584d4262146100f057806371dc08ce1461011657806393bc91fd14610137578063a730416e1461014b578063acea104514610162575b005b610098600160a060020a0360043516602435604435610176565b610098600160a060020a03600435166101b6565b610098600160a060020a03600435166101f1565b610098600160a060020a0360043516610231565b610104600160a060020a0360043516610270565b60408051918252519081900360200190f35b61011e610281565b6040805192835260208301919091528051918290030190f35b610098600160a060020a0360043516610287565b610104600160a060020a03600435166024356102c7565b610098600160a060020a03600435166102d8565b604051600160a060020a0384169083156108fc029084908490600081818185878a8ad09450505050501580156101b0573d6000803e3d6000fd5b50505050565b604051600160a060020a038216906000906000199082908181818181878a82d09450505050501580156101ed573d6000803e3d6000fd5b5050565b604051600160a060020a0382169060009067800000000000000090620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b604051600160a060020a03821690600090600190680200000000000f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a0316620f4241d190565bd3d29091565b604051600160a060020a03821690600090677fffffffffffffff90620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a039190911690d190565b604051600160a060020a038216906108fc90600090678000000000000001908281818185828a8ad09450505050501580156101ed573d6000803e3d6000fd00a165627a7a72305820716217ff39873b1f852cdc214cfb38a4c2337d18fbd1128b69b2866f7f24ae1c0029" - code_ContractTrcToken063_recieveTokenContract = "608060405260658060116000396000f30060806040819052d38152d260a0523460c0527fd1ed7a3c020c4f5939654147940a147a8e4e638fa1e8f5664b5efbd1e1f3c4a690606090a10000a165627a7a72305820ea1e6d9606638e6c9e72dcdcc749561b826ec85713c003fae9d4700a2919040f0029" - code_ContractTrcToken064_transferTokenContract = "6080604052610343806100136000396000f3006080604052600436106100985763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663144401f6811461009a5780631ea31431146100b45780632c5c6641146100c8578063544051aa146100dc578063584d4262146100f057806371dc08ce1461011657806393bc91fd14610137578063a730416e1461014b578063acea104514610162575b005b610098600160a060020a0360043516602435604435610176565b610098600160a060020a03600435166101b6565b610098600160a060020a03600435166101f1565b610098600160a060020a0360043516610231565b610104600160a060020a0360043516610270565b60408051918252519081900360200190f35b61011e610281565b6040805192835260208301919091528051918290030190f35b610098600160a060020a0360043516610287565b610104600160a060020a03600435166024356102c7565b610098600160a060020a03600435166102d8565b604051600160a060020a0384169083156108fc029084908490600081818185878a8ad09450505050501580156101b0573d6000803e3d6000fd5b50505050565b604051600160a060020a038216906000906000199082908181818181878a82d09450505050501580156101ed573d6000803e3d6000fd5b5050565b604051600160a060020a0382169060009067800000000000000090620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b604051600160a060020a03821690600090600190680200000000000f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a0316620f4241d190565bd3d29091565b604051600160a060020a03821690600090677fffffffffffffff90620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a039190911690d190565b604051600160a060020a038216906108fc90600090678000000000000001908281818185828a8ad09450505050501580156101ed573d6000803e3d6000fd00a165627a7a72305820716217ff39873b1f852cdc214cfb38a4c2337d18fbd1128b69b2866f7f24ae1c0029" - code_ContractTrcToken064_recieveTokenContract = "608060405260658060116000396000f30060806040819052d38152d260a0523460c0527fd1ed7a3c020c4f5939654147940a147a8e4e638fa1e8f5664b5efbd1e1f3c4a690606090a10000a165627a7a72305820ea1e6d9606638e6c9e72dcdcc749561b826ec85713c003fae9d4700a2919040f0029" - code_ContractTrcToken066_transferTokenContract = "6080604052610343806100136000396000f3006080604052600436106100985763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663144401f6811461009a5780631ea31431146100b45780632c5c6641146100c8578063544051aa146100dc578063584d4262146100f057806371dc08ce1461011657806393bc91fd14610137578063a730416e1461014b578063acea104514610162575b005b610098600160a060020a0360043516602435604435610176565b610098600160a060020a03600435166101b6565b610098600160a060020a03600435166101f1565b610098600160a060020a0360043516610231565b610104600160a060020a0360043516610270565b60408051918252519081900360200190f35b61011e610281565b6040805192835260208301919091528051918290030190f35b610098600160a060020a0360043516610287565b610104600160a060020a03600435166024356102c7565b610098600160a060020a03600435166102d8565b604051600160a060020a0384169083156108fc029084908490600081818185878a8ad09450505050501580156101b0573d6000803e3d6000fd5b50505050565b604051600160a060020a038216906000906000199082908181818181878a82d09450505050501580156101ed573d6000803e3d6000fd5b5050565b604051600160a060020a0382169060009067800000000000000090620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b604051600160a060020a03821690600090600190680200000000000f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a0316620f4241d190565bd3d29091565b604051600160a060020a03821690600090677fffffffffffffff90620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a039190911690d190565b604051600160a060020a038216906108fc90600090678000000000000001908281818185828a8ad09450505050501580156101ed573d6000803e3d6000fd00a165627a7a72305820716217ff39873b1f852cdc214cfb38a4c2337d18fbd1128b69b2866f7f24ae1c0029" - code_ContractTrcToken066_recieveTokenContract = "608060405260658060116000396000f30060806040819052d38152d260a0523460c0527fd1ed7a3c020c4f5939654147940a147a8e4e638fa1e8f5664b5efbd1e1f3c4a690606090a10000a165627a7a72305820ea1e6d9606638e6c9e72dcdcc749561b826ec85713c003fae9d4700a2919040f0029" - code_ContractTrcToken067_transferTokenContract = "6080604052610343806100136000396000f3006080604052600436106100985763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663144401f6811461009a5780631ea31431146100b45780632c5c6641146100c8578063544051aa146100dc578063584d4262146100f057806371dc08ce1461011657806393bc91fd14610137578063a730416e1461014b578063acea104514610162575b005b610098600160a060020a0360043516602435604435610176565b610098600160a060020a03600435166101b6565b610098600160a060020a03600435166101f1565b610098600160a060020a0360043516610231565b610104600160a060020a0360043516610270565b60408051918252519081900360200190f35b61011e610281565b6040805192835260208301919091528051918290030190f35b610098600160a060020a0360043516610287565b610104600160a060020a03600435166024356102c7565b610098600160a060020a03600435166102d8565b604051600160a060020a0384169083156108fc029084908490600081818185878a8ad09450505050501580156101b0573d6000803e3d6000fd5b50505050565b604051600160a060020a038216906000906000199082908181818181878a82d09450505050501580156101ed573d6000803e3d6000fd5b5050565b604051600160a060020a0382169060009067800000000000000090620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b604051600160a060020a03821690600090600190680200000000000f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a0316620f4241d190565bd3d29091565b604051600160a060020a03821690600090677fffffffffffffff90620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a039190911690d190565b604051600160a060020a038216906108fc90600090678000000000000001908281818185828a8ad09450505050501580156101ed573d6000803e3d6000fd00a165627a7a72305820716217ff39873b1f852cdc214cfb38a4c2337d18fbd1128b69b2866f7f24ae1c0029" - code_ContractTrcToken067_recieveTokenContract = "608060405260658060116000396000f30060806040819052d38152d260a0523460c0527fd1ed7a3c020c4f5939654147940a147a8e4e638fa1e8f5664b5efbd1e1f3c4a690606090a10000a165627a7a72305820ea1e6d9606638e6c9e72dcdcc749561b826ec85713c003fae9d4700a2919040f0029" - code_ContractTrcToken068_transferTokenContract = "6080604052610343806100136000396000f3006080604052600436106100985763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663144401f6811461009a5780631ea31431146100b45780632c5c6641146100c8578063544051aa146100dc578063584d4262146100f057806371dc08ce1461011657806393bc91fd14610137578063a730416e1461014b578063acea104514610162575b005b610098600160a060020a0360043516602435604435610176565b610098600160a060020a03600435166101b6565b610098600160a060020a03600435166101f1565b610098600160a060020a0360043516610231565b610104600160a060020a0360043516610270565b60408051918252519081900360200190f35b61011e610281565b6040805192835260208301919091528051918290030190f35b610098600160a060020a0360043516610287565b610104600160a060020a03600435166024356102c7565b610098600160a060020a03600435166102d8565b604051600160a060020a0384169083156108fc029084908490600081818185878a8ad09450505050501580156101b0573d6000803e3d6000fd5b50505050565b604051600160a060020a038216906000906000199082908181818181878a82d09450505050501580156101ed573d6000803e3d6000fd5b5050565b604051600160a060020a0382169060009067800000000000000090620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b604051600160a060020a03821690600090600190680200000000000f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a0316620f4241d190565bd3d29091565b604051600160a060020a03821690600090677fffffffffffffff90620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a039190911690d190565b604051600160a060020a038216906108fc90600090678000000000000001908281818185828a8ad09450505050501580156101ed573d6000803e3d6000fd00a165627a7a72305820716217ff39873b1f852cdc214cfb38a4c2337d18fbd1128b69b2866f7f24ae1c0029" - - code_ContractTrcToken068_recieveTokenContract = "608060405260658060116000396000f30060806040819052d38152d260a0523460c0527fd1ed7a3c020c4f5939654147940a147a8e4e638fa1e8f5664b5efbd1e1f3c4a690606090a10000a165627a7a72305820ea1e6d9606638e6c9e72dcdcc749561b826ec85713c003fae9d4700a2919040f0029" - code_ContractTrcToken071_transferTokenContract = "608060405261022e806100136000396000f3006080604052600436106100775763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663144401f68114610079578063544051aa14610093578063584d4262146100a757806371dc08ce146100cd5780639663d3f2146100ee578063a730416e14610102575b005b610077600160a060020a0360043516602435604435610119565b610077600160a060020a0360043516610159565b6100bb600160a060020a036004351661019c565b60408051918252519081900360200190f35b6100d56101ad565b6040805192835260208301919091528051918290030190f35b610077600160a060020a03600435166101b3565b6100bb600160a060020a03600435166024356101f1565b604051600160a060020a0384169083156108fc029084908490600081818185878a8ad0945050505050158015610153573d6000803e3d6000fd5b50505050565b604051600160a060020a03821690600090600190680200000000000f4241908381818185878a84d0945050505050158015610198573d6000803e3d6000fd5b5050565b600160a060020a0316620f4241d190565bd3d29091565b604051600160a060020a03821690600090600190678000000000000001908381818185878a84d0945050505050158015610198573d6000803e3d6000fd5b600160a060020a039190911690d1905600a165627a7a72305820d37032d630dfb2b80dac39db09b9eabfc228e157e20131e49ccde99a2cc3e2710029" - code_ContractTrcToken071_recieveTokenContract = "608060405260658060116000396000f30060806040819052d38152d260a0523460c0527fd1ed7a3c020c4f5939654147940a147a8e4e638fa1e8f5664b5efbd1e1f3c4a690606090a10000a165627a7a72305820ea1e6d9606638e6c9e72dcdcc749561b826ec85713c003fae9d4700a2919040f0029" - code_ContractTrcToken073_transferTokenContract = "608060405260e5806100126000396000f300608060405260043610603e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663dfc0db988114606f575b34d2d37f70536dc19abf7e0862a7afc0755f548bfd5f0b40cbd9fc87fa19b2e50b454a5660405160405180910390a4005b6078600435607a565b005b604080513481529051d291d3913385d1917fe8e04df6a82498bd5fb1fe7f2168f525c54ee1003b3a56638c858e94fd9e4854919081900360200190a4505600a165627a7a72305820dca795a21bfc9451314c14306b0220175611298bdb59c8b2cfdb1120cb3fda390029" - code_ContractTrcToken074_transferTokenContract = "608060405260e5806100126000396000f300608060405260043610603e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663dfc0db988114606f575b34d2d37f70536dc19abf7e0862a7afc0755f548bfd5f0b40cbd9fc87fa19b2e50b454a5660405160405180910390a4005b6078600435607a565b005b604080513481529051d291d3913385d1917fe8e04df6a82498bd5fb1fe7f2168f525c54ee1003b3a56638c858e94fd9e4854919081900360200190a4505600a165627a7a72305820dca795a21bfc9451314c14306b0220175611298bdb59c8b2cfdb1120cb3fda390029" - code_ContractTrcToken075_transferTokenContract = "608060405261019c806100136000396000f3006080604052600436106100565763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632ab5cf918114610087578063dfc0db9814610091578063f9a677791461009c575b34d2d37f70536dc19abf7e0862a7afc0755f548bfd5f0b40cbd9fc87fa19b2e50b454a5660405160405180910390a4005b61008f6100a4565b005b61008f6004356100eb565b61008f61012a565b604080513481529051d291d391336780000000000f425319d1917fe8e04df6a82498bd5fb1fe7f2168f525c54ee1003b3a56638c858e94fd9e4854919081900360200190a4565b604080513481529051d291d3913385d1917fe8e04df6a82498bd5fb1fe7f2168f525c54ee1003b3a56638c858e94fd9e4854919081900360200190a450565b604080513481529051d291d391336780000000000f4253d1917fe8e04df6a82498bd5fb1fe7f2168f525c54ee1003b3a56638c858e94fd9e4854919081900360200190a45600a165627a7a723058204eef0c9d8221d37dbe366e9af0815246c4f9239d3f22f27b9db0aa0a3e23aa580029" - code_ContractTrcToken0552_transferTokenContract = "6080604052610118806100136000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633be9ece78114604d57806371dc08ce146074575b600080fd5b607273ffffffffffffffffffffffffffffffffffffffff600435166024356044356098565b005b607a60e4565b60408051938452602084019290925282820152519081900360600190f35b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad094505050505015801560de573d6000803e3d6000fd5b50505050565bd3d2349091925600a165627a7a72305820b8d4f8ea5443a03d615ea5dfe7a7435498522f9c7abeb25583d953ee2d20be4a0029" - code_ContractTrcToken0553_transferTokenContract = "6080604052610118806100136000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633be9ece78114604d57806371dc08ce146074575b600080fd5b607273ffffffffffffffffffffffffffffffffffffffff600435166024356044356098565b005b607a60e4565b60408051938452602084019290925282820152519081900360600190f35b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad094505050505015801560de573d6000803e3d6000fd5b50505050565bd3d2349091925600a165627a7a72305820b8d4f8ea5443a03d615ea5dfe7a7435498522f9c7abeb25583d953ee2d20be4a0029" - code_ContractTrcToken0612_transferTokenContract = "6080604052d3600055d2600155346002556101418061001f6000396000f3006080604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166305c24200811461005b5780633be9ece71461008157806371dc08ce146100aa575b600080fd5b6100636100b2565b60408051938452602084019290925282820152519081900360600190f35b6100a873ffffffffffffffffffffffffffffffffffffffff600435166024356044356100c0565b005b61006361010d565b600054600154600254909192565b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad0945050505050158015610107573d6000803e3d6000fd5b50505050565bd3d2349091925600a165627a7a72305820a2fb39541e90eda9a2f5f9e7905ef98e66e60dd4b38e00b05de418da3154e7570029" - code_ContractTrcToken0613_transferTokenContract = "6080604052d3600055d2600155346002556101418061001f6000396000f3006080604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166305c24200811461005b5780633be9ece71461008157806371dc08ce146100aa575b600080fd5b6100636100b2565b60408051938452602084019290925282820152519081900360600190f35b6100a873ffffffffffffffffffffffffffffffffffffffff600435166024356044356100c0565b005b61006361010d565b600054600154600254909192565b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad0945050505050158015610107573d6000803e3d6000fd5b50505050565bd3d2349091925600a165627a7a72305820a2fb39541e90eda9a2f5f9e7905ef98e66e60dd4b38e00b05de418da3154e7570029" - code_ContractTrcToken0672_transferTokenContract = "6080604052610343806100136000396000f3006080604052600436106100985763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663144401f6811461009a5780631ea31431146100b45780632c5c6641146100c8578063544051aa146100dc578063584d4262146100f057806371dc08ce1461011657806393bc91fd14610137578063a730416e1461014b578063acea104514610162575b005b610098600160a060020a0360043516602435604435610176565b610098600160a060020a03600435166101b6565b610098600160a060020a03600435166101f1565b610098600160a060020a0360043516610231565b610104600160a060020a0360043516610270565b60408051918252519081900360200190f35b61011e610281565b6040805192835260208301919091528051918290030190f35b610098600160a060020a0360043516610287565b610104600160a060020a03600435166024356102c7565b610098600160a060020a03600435166102d8565b604051600160a060020a0384169083156108fc029084908490600081818185878a8ad09450505050501580156101b0573d6000803e3d6000fd5b50505050565b604051600160a060020a038216906000906000199082908181818181878a82d09450505050501580156101ed573d6000803e3d6000fd5b5050565b604051600160a060020a0382169060009067800000000000000090620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b604051600160a060020a03821690600090600190680200000000000f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a0316620f4241d190565bd3d29091565b604051600160a060020a03821690600090677fffffffffffffff90620f4241908381818185878a84d09450505050501580156101ed573d6000803e3d6000fd5b600160a060020a039190911690d190565b604051600160a060020a038216906108fc90600090678000000000000001908281818185828a8ad09450505050501580156101ed573d6000803e3d6000fd00a165627a7a72305820716217ff39873b1f852cdc214cfb38a4c2337d18fbd1128b69b2866f7f24ae1c0029" - code_ContractTrcToken0672_recieveTokenContract = "608060405260658060116000396000f30060806040819052d38152d260a0523460c0527fd1ed7a3c020c4f5939654147940a147a8e4e638fa1e8f5664b5efbd1e1f3c4a690606090a10000a165627a7a72305820ea1e6d9606638e6c9e72dcdcc749561b826ec85713c003fae9d4700a2919040f0029" - code_ContractTrcToken029_tokenTest = "608060405261034f806100136000396000f30060806040526004361061004b5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630dbe671f8114610050578063c3e911d4146100a8575b600080fd5b34801561005c57600080fd5b50d3801561006957600080fd5b50d2801561007657600080fd5b5061007f6100b8565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6100b66004356024356100d4565b005b60005473ffffffffffffffffffffffffffffffffffffffff1681565b60006100de6101de565b604051809103906000f0801580156100fa573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663071f65a883856040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018083815260200182815260200192505050602060405180830381600087803b15801561017457600080fd5b505af1158015610188573d6000803e3d6000fd5b505050506040513d602081101561019e57600080fd5b50506000805473ffffffffffffffffffffffffffffffffffffffff191673ffffffffffffffffffffffffffffffffffffffff929092169190911790555050565b604051610135806101ef83390190560060806040526000805561011e806100176000396000f30060806040526004361060525763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663071f65a881146054578063890eba68146074578063f96339301460b0575b005b606060043560243560da565b604080519115158252519081900360200190f35b348015607f57600080fd5b50d38015608b57600080fd5b50d28015609757600080fd5b50609e60e6565b60408051918252519081900360200190f35b34801560bb57600080fd5b50d3801560c757600080fd5b50d2801560d357600080fd5b50609e60ec565b50506009600090815590565b60005481565b600054905600a165627a7a72305820a699d9eec788d2a222b703af447d9c2ddffb626fc07a57834af8e3f9bce64dc90029a165627a7a72305820626050611353c2f66f9b94e3935c21fd4dad7cc494b7459f3597451e1b6004de0029" - code_ContractTrcToken030_tokenTest = "608060405260a9806100126000396000f300608060405260043610603e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663cbf0b0c081146043575b600080fd5b606273ffffffffffffffffffffffffffffffffffffffff600435166064565b005b8073ffffffffffffffffffffffffffffffffffffffff16ff00a165627a7a72305820ad0052aaf68fac3eec3da8d49432d1529ec4df4fa82c1dd2847c088f2575ddb10029" - code_ContractTrcToken031_tokenTest = "608060405260a9806100126000396000f300608060405260043610603e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663cbf0b0c081146043575b600080fd5b606273ffffffffffffffffffffffffffffffffffffffff600435166064565b005b8073ffffffffffffffffffffffffffffffffffffffff16ff00a165627a7a72305820ad0052aaf68fac3eec3da8d49432d1529ec4df4fa82c1dd2847c088f2575ddb10029" - code_ContractTrcToken034_tokenTest = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b506101638061003a6000396000f30060806040526004361061004b5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634957baa18114610050578063e308c52714610079575b600080fd5b61007773ffffffffffffffffffffffffffffffffffffffff600435166024356044356100a0565b005b61007773ffffffffffffffffffffffffffffffffffffffff600435166024356044356100ea565b60405173ffffffffffffffffffffffffffffffffffffffff84169083156108fc029084908490600081818185878a8ad09450505050501580156100e7573d6000803e3d6000fd5b50fe5b60405173ffffffffffffffffffffffffffffffffffffffff84169083156108fc029084908490600081818185878a8ad0945050505050158015610131573d6000803e3d6000fd5b50600080fd00a165627a7a723058204c2d6334ac3ea724949482094951c3b7d11fea1e87b58110d562ef47ddd45c7b0029" - code_ContractTrcToken035_tokenTest = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b506101638061003a6000396000f30060806040526004361061004b5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634957baa18114610050578063e308c52714610079575b600080fd5b61007773ffffffffffffffffffffffffffffffffffffffff600435166024356044356100a0565b005b61007773ffffffffffffffffffffffffffffffffffffffff600435166024356044356100ea565b60405173ffffffffffffffffffffffffffffffffffffffff84169083156108fc029084908490600081818185878a8ad09450505050501580156100e7573d6000803e3d6000fd5b50fe5b60405173ffffffffffffffffffffffffffffffffffffffff84169083156108fc029084908490600081818185878a8ad0945050505050158015610131573d6000803e3d6000fd5b50600080fd00a165627a7a723058204c2d6334ac3ea724949482094951c3b7d11fea1e87b58110d562ef47ddd45c7b0029" - code_ContractTrcToken036_transferTokenWithPureTest = "60806040526101db806100136000396000f3006080604052600436106100405763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416639d9e5a388114610042575b005b34801561004e57600080fd5b50d3801561005b57600080fd5b50d2801561006857600080fd5b5061004073ffffffffffffffffffffffffffffffffffffffff600435166024356040805134815290517ff82c50f1848136e6c140b186ea0c768b7deda5efffe42c25e96336a90b26c7449181900360200190a160408051d2815290517ff82c50f1848136e6c140b186ea0c768b7deda5efffe42c25e96336a90b26c7449181900360200190a160408051d3815290517ff82c50f1848136e6c140b186ea0c768b7deda5efffe42c25e96336a90b26c7449181900360200190a160405173ffffffffffffffffffffffffffffffffffffffff831690d280156108fc0291d390600081818185878a8ad0945050505050158015610167573d6000803e3d6000fd5b5060405173ffffffffffffffffffffffffffffffffffffffff8316903480156108fc02916000818181858888f193505050501580156101aa573d6000803e3d6000fd5b5050505600a165627a7a7230582052825d8daae4fb444ce76f049e019c2c66d7b29584058ee7cc88a389e22f41dc0029" - code_ContractTrcToken036_transferTokenWithViewTest = "60806040526101db806100136000396000f3006080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663abecd9838114610042575b005b34801561004e57600080fd5b50d3801561005b57600080fd5b50d2801561006857600080fd5b5061004073ffffffffffffffffffffffffffffffffffffffff600435166024356040805134815290517ff82c50f1848136e6c140b186ea0c768b7deda5efffe42c25e96336a90b26c7449181900360200190a160408051d2815290517ff82c50f1848136e6c140b186ea0c768b7deda5efffe42c25e96336a90b26c7449181900360200190a160408051d3815290517ff82c50f1848136e6c140b186ea0c768b7deda5efffe42c25e96336a90b26c7449181900360200190a160405173ffffffffffffffffffffffffffffffffffffffff831690d280156108fc0291d390600081818185878a8ad0945050505050158015610167573d6000803e3d6000fd5b5060405173ffffffffffffffffffffffffffffffffffffffff8316903480156108fc02916000818181858888f193505050501580156101aa573d6000803e3d6000fd5b5050505600a165627a7a7230582020ddb4a20df32d91af717609926b277d218ac25965d8003ff48adf57a0f10f950029" - code_ContractTrcToken036_transferTokenWithOutPayableTest = "60806040526101db806100136000396000f3006080604052600436106100405763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632b38e5478114610042575b005b34801561004e57600080fd5b50d3801561005b57600080fd5b50d2801561006857600080fd5b5061004073ffffffffffffffffffffffffffffffffffffffff600435166024356040805134815290517ff82c50f1848136e6c140b186ea0c768b7deda5efffe42c25e96336a90b26c7449181900360200190a160408051d2815290517ff82c50f1848136e6c140b186ea0c768b7deda5efffe42c25e96336a90b26c7449181900360200190a160408051d3815290517ff82c50f1848136e6c140b186ea0c768b7deda5efffe42c25e96336a90b26c7449181900360200190a160405173ffffffffffffffffffffffffffffffffffffffff831690d280156108fc0291d390600081818185878a8ad0945050505050158015610167573d6000803e3d6000fd5b5060405173ffffffffffffffffffffffffffffffffffffffff8316903480156108fc02916000818181858888f193505050501580156101aa573d6000803e3d6000fd5b5050505600a165627a7a723058203c20218af63eda8b09394f27964892ee199fa89d93e03506f9a0390dc0b9605d0029" - code_ContractTrcToken037_receiveTrc10Test = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b5060ba806100396000396000f300608060405260043610603e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663ec17fded81146040575b005b348015604b57600080fd5b50d38015605757600080fd5b50d28015606357600080fd5b50603e6004356024356044353082d18314607c57600080fd5b3382d18114608957600080fd5b5050505600a165627a7a723058205da58c4884728798dd87f6219bad7230ff56c1859ca6402bcc3f1584ca0af8080029" - code_ContractTrcToken037_tokenTest = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b506101ff8061003a6000396000f3006080604052600436106100275763ffffffff60e060020a6000350416639d01174f811461002c575b600080fd5b61004d73ffffffffffffffffffffffffffffffffffffffff6004351661004f565b005b30d39081d19073ffffffffffffffffffffffffffffffffffffffff831690d1d2821461007a57600080fd5bd2821461008657600080fd5b60405173ffffffffffffffffffffffffffffffffffffffff84169083156108fc02908490d390600081818185878a8ad09450505050501580156100cd573d6000803e3d6000fd5b5030d3d1156100db57600080fd5b80820173ffffffffffffffffffffffffffffffffffffffff8416d3d11461010157600080fd5b8273ffffffffffffffffffffffffffffffffffffffff1660405180807f636865636b54726331302875696e743235362c747263546f6b656e2c75696e7481526020017f32353629000000000000000000000000000000000000000000000000000000008152506024019050604051809103902060e060020a9004838301d360006040518463ffffffff1660e060020a028152600401808481526020018381526020018260ff16815260200193505050506000604051808303816000875af19250505015156101ce57600080fd5b5050505600a165627a7a72305820e91d5a5eda7d9da85983cf55171fa13b3dbf99ebe851321c02831b3f74d7bafc0029" - code_ContractTrcToken038_tokenTest = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b506101b78061003a6000396000f3006080604052600436106100275763ffffffff60e060020a6000350416639d01174f811461002c575b600080fd5b61004d73ffffffffffffffffffffffffffffffffffffffff6004351661004f565b005b30d39081d19073ffffffffffffffffffffffffffffffffffffffff831690d1d2821461007a57600080fd5bd2821461008657600080fd5b60405173ffffffffffffffffffffffffffffffffffffffff84169083156108fc02908490d390600081818185878a8ad09450505050501580156100cd573d6000803e3d6000fd5b508273ffffffffffffffffffffffffffffffffffffffff1660405180807f4173736572744572726f72282900000000000000000000000000000000000000815250600d019050604051809103902060e060020a90046040518163ffffffff1660e060020a0281526004016000604051808303816000875af192505050151561015457600080fd5b30d3d1821461016257600080fd5b73ffffffffffffffffffffffffffffffffffffffff8316d3d1811461018657600080fd5b5050505600a165627a7a72305820962d49fbc330584b84b59e537e7450a5ca38cccf106466907e402f8653ab1dee0029" - code_ContractTrcToken038_BTest = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b506094806100396000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631966216581146040575b005b348015604b57600080fd5b50d38015605757600080fd5b50d28015606357600080fd5b50603efe00a165627a7a723058200fc1cef003f4eb28c1edc4c7b62c1012237dd9db791e8dac7a9671319ac003440029" - code_ContractTrcToken039_ProxyTest = "60806040526101bc806100136000396000f30060806040526004361061004b5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633659cfe681146100965780635c60da1b146100e0575b60005473ffffffffffffffffffffffffffffffffffffffff1680151561007057600080fd5b6040513660008237600081368185600019f43d6000833e808015610092573d83f35b3d83fd5b3480156100a257600080fd5b50d380156100af57600080fd5b50d280156100bc57600080fd5b506100de73ffffffffffffffffffffffffffffffffffffffff60043516610138565b005b3480156100ec57600080fd5b50d380156100f957600080fd5b50d2801561010657600080fd5b5061010f610174565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6000805473ffffffffffffffffffffffffffffffffffffffff191673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff16815600a165627a7a7230582047b47a8f57880f0c2c028e44406b1868bbee2151938629caad7b65668d6a8a140029" - code_ContractTrcToken039_ATest = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b5060de806100396000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630455012181146043575b600080fd5b606860043573ffffffffffffffffffffffffffffffffffffffff60243516604435606a565b005b60405173ffffffffffffffffffffffffffffffffffffffff83169084156108fc029085906000818181858888f1935050505015801560ac573d6000803e3d6000fd5b505050505600a165627a7a72305820542cde58d75afb60ec2226b95c592a973666b56931d8ea8d7ed0d0a6bd16e7ea0029" - code_ContractTrcToken039_BTest = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b5060e2806100396000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630455012181146043575b600080fd5b606860043573ffffffffffffffffffffffffffffffffffffffff60243516604435606a565b005b60405173ffffffffffffffffffffffffffffffffffffffff83169084156108fc029085908490600081818185878a8ad094505050505015801560b0573d6000803e3d6000fd5b505050505600a165627a7a72305820cccc1489247eb5366214a034107ebfbea955aac5229e03907a82321a1a4484240029" - code_ContractTrcToken041_transferTokenContract = "608060405260e2806100126000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633be9ece781146043575b600080fd5b606873ffffffffffffffffffffffffffffffffffffffff60043516602435604435606a565b005b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad094505050505015801560b0573d6000803e3d6000fd5b505050505600a165627a7a72305820d7ac1a3b49eeff286b7f2402b93047e60deb6dba47f4f889d921dbcb3bb81f8a0029" - code_ContractTrcToken048_transferTokenContract = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b5061010f8061003a6000396000f30060806040526004361060485763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663a94b16d08114604d578063c0063993146065575b600080fd5b6053606b565b60408051918252519081900360200190f35b605360a7565b6040805134815290516000917ff82c50f1848136e6c140b186ea0c768b7deda5efffe42c25e96336a90b26c744919081900360200190a1503490565b60408051d2815290516000917ff82c50f1848136e6c140b186ea0c768b7deda5efffe42c25e96336a90b26c744919081900360200190a150d2905600a165627a7a7230582016ef7f5bc613147860a1de990c4258eaa2ca12ceb1ab21cd9069f50d1db238020029" - code_ContractTrcToken049_transferTokenContract = "608060405260e2806100126000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633be9ece781146043575b600080fd5b606873ffffffffffffffffffffffffffffffffffffffff60043516602435604435606a565b005b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad094505050505015801560b0573d6000803e3d6000fd5b505050505600a165627a7a72305820d7ac1a3b49eeff286b7f2402b93047e60deb6dba47f4f889d921dbcb3bb81f8a0029" - code_ContractTrcToken050_transferTokenContract = "608060405260e2806100126000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633be9ece781146043575b600080fd5b606873ffffffffffffffffffffffffffffffffffffffff60043516602435604435606a565b005b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad094505050505015801560b0573d6000803e3d6000fd5b505050505600a165627a7a72305820d7ac1a3b49eeff286b7f2402b93047e60deb6dba47f4f889d921dbcb3bb81f8a0029" - code_ContractTrcToken051_transferTokenContract = "608060405260e2806100126000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633be9ece781146043575b600080fd5b606873ffffffffffffffffffffffffffffffffffffffff60043516602435604435606a565b005b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad094505050505015801560b0573d6000803e3d6000fd5b505050505600a165627a7a72305820d7ac1a3b49eeff286b7f2402b93047e60deb6dba47f4f889d921dbcb3bb81f8a0029" - code_ContractTrcToken052_transferTokenContract = "608060405260e2806100126000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633be9ece781146043575b600080fd5b606873ffffffffffffffffffffffffffffffffffffffff60043516602435604435606a565b005b60405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8ad094505050505015801560b0573d6000803e3d6000fd5b505050505600a165627a7a72305820d7ac1a3b49eeff286b7f2402b93047e60deb6dba47f4f889d921dbcb3bb81f8a0029" - code_ContractTrcToken036_tokenTest = "60806040526101b4806100136000396000f3006080604052600436106100405763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632849fa4f8114610042575b005b61004073ffffffffffffffffffffffffffffffffffffffff600435166024356040805134815290517ff82c50f1848136e6c140b186ea0c768b7deda5efffe42c25e96336a90b26c7449181900360200190a160408051d2815290517ff82c50f1848136e6c140b186ea0c768b7deda5efffe42c25e96336a90b26c7449181900360200190a160408051d3815290517ff82c50f1848136e6c140b186ea0c768b7deda5efffe42c25e96336a90b26c7449181900360200190a160405173ffffffffffffffffffffffffffffffffffffffff831690d280156108fc0291d390600081818185878a8ad0945050505050158015610140573d6000803e3d6000fd5b5060405173ffffffffffffffffffffffffffffffffffffffff8316903480156108fc02916000818181858888f19350505050158015610183573d6000803e3d6000fd5b5050505600a165627a7a72305820ddc15bf8809c92f9c6b6175f2ce1245ef1d65e5fbeccc2bb2772980cedee1eee0029" - code_ContractTrcToken076_originTest = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b506103698061003a6000396000f3006080604052600436106100825763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166317ca5481811461008757806360d10813146100ca57806367e404ce146100f95780638be988cd14610151578063938b5f3214610159578063e8da042414610188578063f8a8fd6d14610190575b600080fd5b34801561009357600080fd5b50d380156100a057600080fd5b50d280156100ad57600080fd5b506100b66101c1565b604080519115158252519081900360200190f35b3480156100d657600080fd5b50d380156100e357600080fd5b50d280156100f057600080fd5b506100b66101e3565b34801561010557600080fd5b50d3801561011257600080fd5b50d2801561011f57600080fd5b50610128610204565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6100b6610220565b34801561016557600080fd5b50d3801561017257600080fd5b50d2801561017f57600080fd5b50610128610241565b6100b661025d565b34801561019c57600080fd5b50d380156101a957600080fd5b50d280156101b657600080fd5b506101bf61027f565b005b6001547501000000000000000000000000000000000000000000900460ff1681565b60015474010000000000000000000000000000000000000000900460ff1681565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60015474010000000000000000000000000000000000000000900460ff1690565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b6001547501000000000000000000000000000000000000000000900460ff1690565b600080543273ffffffffffffffffffffffffffffffffffffffff199182168117928390556001805475ff0000000000000000000000000000000000000000001993163390811774ff00000000000000000000000000000000000000001916921474010000000000000000000000000000000000000000029190911791821673ffffffffffffffffffffffffffffffffffffffff92831692909316919091147501000000000000000000000000000000000000000000029190911790555600a165627a7a72305820487fd902512ac719158b1ec219e9e6648b9f47f7f0396d24044f4dca1de4a3c60029" - code_ContractTrcToken077_AddressTest = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b5060b6806100396000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416636241c1d881146043575b600080fd5b348015604e57600080fd5b50d38015605a57600080fd5b50d28015606657600080fd5b50606d607f565b60408051918252519081900360200190f35b6040513090819052905600a165627a7a723058207faa3a33e3b875c23563f2fb8ee4506affcd21d818c8399a71dd76fa973f487d0029" - code_ContractTrcToken077_AddressTest1 = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b506092806100396000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416636241c1d881146043575b600080fd5b6049605b565b60408051918252519081900360200190f35b6040513090819052905600a165627a7a723058200245dccce3c678939aba5ad813f3fd8d551ef14f01409a8e36bc3dac301113c40029" - code_ContractTrcToken078_AddressTest1 = "6080604052610264806100136000396000f30060806040526004361061003d5763ffffffff60e060020a600035041663648efe8b811461003f578063b45f578b14610059578063d818452114610073575b005b61003d600160a060020a036004358116906024351661008d565b61003d600160a060020a036004358116906024351661011c565b61003d600160a060020a03600435811690602435166101a9565b81600160a060020a031660405180807f7472616e73666572546f286164647265737329000000000000000000000000008152506013019050604051809103902060e060020a9004826040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031681526020019150506000604051808303816000875af2505050505050565b81600160a060020a031660405180807f7472616e73666572546f286164647265737329000000000000000000000000008152506013019050604051809103902060e060020a9004826040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050600060405180830381865af4505050505050565b81600160a060020a031660405180807f7472616e73666572546f286164647265737329000000000000000000000000008152506013019050604051809103902060e060020a9004826040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031681526020019150506000604051808303816000875af15050505050505600a165627a7a7230582068a85b5cb5a41f10a7ba8250baed5adf37129ff04399bccae69e483fc85448a90029" - code_ContractTrcToken078_AddressTest2 = "6080604052610166806100136000396000f3006080604052600436106100325763ffffffff60e060020a6000350416630223024e8114610034578063a03fa7e314610055575b005b61003273ffffffffffffffffffffffffffffffffffffffff60043516610076565b61003273ffffffffffffffffffffffffffffffffffffffff600435166100f7565b8073ffffffffffffffffffffffffffffffffffffffff16600560405180807f73657449282900000000000000000000000000000000000000000000000000008152506006019050604051809103902060e060020a9004906040518263ffffffff1660e060020a02815260040160006040518083038185885af1505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff82169060009060059082818181858883f19350505050158015610136573d6000803e3d6000fd5b50505600a165627a7a72305820ede28ac9884104396c5d52bbf3f480cb637f61bc331c2dc561670e6d2700ad630029" - code_ContractTrcToken078_AddressTest3 = "6080604052610172806100136000396000f30060806040526004361061004b5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166367e404ce8114610087578063938b5f32146100df575b6040805132815233602082015281517fdaf0d4aa9a5679e832ac921da67b43572b4326ee2565442d3ed255b48cfb5161929181900390910190a1005b34801561009357600080fd5b50d380156100a057600080fd5b50d280156100ad57600080fd5b506100b661010e565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b3480156100eb57600080fd5b50d380156100f857600080fd5b50d2801561010557600080fd5b506100b661012a565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60005473ffffffffffffffffffffffffffffffffffffffff16815600a165627a7a7230582084426e82a8fde9cefb0ae9f1561ce743354adada27d217c8614c28829eecbcda0029" - code_ContractTrcToken078_AddressTest4 = "6080604052610264806100136000396000f30060806040526004361061003d5763ffffffff60e060020a600035041663648efe8b811461003f578063b45f578b14610059578063d818452114610073575b005b61003d600160a060020a036004358116906024351661008d565b61003d600160a060020a036004358116906024351661011c565b61003d600160a060020a03600435811690602435166101a9565b81600160a060020a031660405180807f7472616e73666572546f286164647265737329000000000000000000000000008152506013019050604051809103902060e060020a9004826040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031681526020019150506000604051808303816000875af2505050505050565b81600160a060020a031660405180807f7472616e73666572546f286164647265737329000000000000000000000000008152506013019050604051809103902060e060020a9004826040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050600060405180830381865af4505050505050565b81600160a060020a031660405180807f7472616e73666572546f286164647265737329000000000000000000000000008152506013019050604051809103902060e060020a9004826040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031681526020019150506000604051808303816000875af15050505050505600a165627a7a7230582068a85b5cb5a41f10a7ba8250baed5adf37129ff04399bccae69e483fc85448a90029" - code_ContractTrcToken078_AddressTest5 = "6080604052610166806100136000396000f3006080604052600436106100325763ffffffff60e060020a6000350416630223024e8114610034578063a03fa7e314610055575b005b61003273ffffffffffffffffffffffffffffffffffffffff60043516610076565b61003273ffffffffffffffffffffffffffffffffffffffff600435166100f7565b8073ffffffffffffffffffffffffffffffffffffffff16600560405180807f73657449282900000000000000000000000000000000000000000000000000008152506006019050604051809103902060e060020a9004906040518263ffffffff1660e060020a02815260040160006040518083038185885af1505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff82169060009060059082818181858883f19350505050158015610136573d6000803e3d6000fd5b50505600a165627a7a72305820ede28ac9884104396c5d52bbf3f480cb637f61bc331c2dc561670e6d2700ad630029" - code_ContractTrcToken078_AddressTest6 = "6080604052610172806100136000396000f30060806040526004361061004b5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166367e404ce8114610087578063938b5f32146100df575b6040805132815233602082015281517fdaf0d4aa9a5679e832ac921da67b43572b4326ee2565442d3ed255b48cfb5161929181900390910190a1005b34801561009357600080fd5b50d380156100a057600080fd5b50d280156100ad57600080fd5b506100b661010e565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b3480156100eb57600080fd5b50d380156100f857600080fd5b50d2801561010557600080fd5b506100b661012a565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60005473ffffffffffffffffffffffffffffffffffffffff16815600a165627a7a7230582084426e82a8fde9cefb0ae9f1561ce743354adada27d217c8614c28829eecbcda0029" - code_veryLarge = "60806040523480156200001157600080fd5b50d380156200001f57600080fd5b50d280156200002d57600080fd5b5061c2ec806200003e6000396000f3fe6080604052600436106200003c577c010000000000000000000000000000000000000000000000000000000060003504631a695230811462000041575b600080fd5b62000077600480360360208110156200005957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1662000079565b005b6040516000906200008a906200c1dc565b604051809103906000f080158015620000a7573d6000803e3d6000fd5b5050604051620000b7906200c1dc565b604051809103906000f080158015620000d4573d6000803e3d6000fd5b5050604051620000e4906200c1dc565b604051809103906000f08015801562000101573d6000803e3d6000fd5b505060405162000111906200c1dc565b604051809103906000f0801580156200012e573d6000803e3d6000fd5b50506040516200013e906200c1dc565b604051809103906000f0801580156200015b573d6000803e3d6000fd5b50506040516200016b906200c1dc565b604051809103906000f08015801562000188573d6000803e3d6000fd5b505060405162000198906200c1dc565b604051809103906000f080158015620001b5573d6000803e3d6000fd5b5050604051620001c5906200c1dc565b604051809103906000f080158015620001e2573d6000803e3d6000fd5b5050604051620001f2906200c1dc565b604051809103906000f0801580156200020f573d6000803e3d6000fd5b50506040516200021f906200c1dc565b604051809103906000f0801580156200023c573d6000803e3d6000fd5b50506040516200024c906200c1dc565b604051809103906000f08015801562000269573d6000803e3d6000fd5b505060405162000279906200c1dc565b604051809103906000f08015801562000296573d6000803e3d6000fd5b5050604051620002a6906200c1dc565b604051809103906000f080158015620002c3573d6000803e3d6000fd5b5050604051620002d3906200c1dc565b604051809103906000f080158015620002f0573d6000803e3d6000fd5b505060405162000300906200c1dc565b604051809103906000f0801580156200031d573d6000803e3d6000fd5b50506040516200032d906200c1dc565b604051809103906000f0801580156200034a573d6000803e3d6000fd5b50506040516200035a906200c1dc565b604051809103906000f08015801562000377573d6000803e3d6000fd5b505060405162000387906200c1dc565b604051809103906000f080158015620003a4573d6000803e3d6000fd5b5050604051620003b4906200c1dc565b604051809103906000f080158015620003d1573d6000803e3d6000fd5b5050604051620003e1906200c1dc565b604051809103906000f080158015620003fe573d6000803e3d6000fd5b50506040516200040e906200c1dc565b604051809103906000f0801580156200042b573d6000803e3d6000fd5b50506040516200043b906200c1dc565b604051809103906000f08015801562000458573d6000803e3d6000fd5b505060405162000468906200c1dc565b604051809103906000f08015801562000485573d6000803e3d6000fd5b505060405162000495906200c1dc565b604051809103906000f080158015620004b2573d6000803e3d6000fd5b5050604051620004c2906200c1dc565b604051809103906000f080158015620004df573d6000803e3d6000fd5b5050604051620004ef906200c1dc565b604051809103906000f0801580156200050c573d6000803e3d6000fd5b50506040516200051c906200c1dc565b604051809103906000f08015801562000539573d6000803e3d6000fd5b505060405162000549906200c1dc565b604051809103906000f08015801562000566573d6000803e3d6000fd5b505060405162000576906200c1dc565b604051809103906000f08015801562000593573d6000803e3d6000fd5b5050604051620005a3906200c1dc565b604051809103906000f080158015620005c0573d6000803e3d6000fd5b5050604051620005d0906200c1dc565b604051809103906000f080158015620005ed573d6000803e3d6000fd5b5050604051620005fd906200c1dc565b604051809103906000f0801580156200061a573d6000803e3d6000fd5b50506040516200062a906200c1dc565b604051809103906000f08015801562000647573d6000803e3d6000fd5b505060405162000657906200c1dc565b604051809103906000f08015801562000674573d6000803e3d6000fd5b505060405162000684906200c1dc565b604051809103906000f080158015620006a1573d6000803e3d6000fd5b5050604051620006b1906200c1dc565b604051809103906000f080158015620006ce573d6000803e3d6000fd5b5050604051620006de906200c1dc565b604051809103906000f080158015620006fb573d6000803e3d6000fd5b50506040516200070b906200c1dc565b604051809103906000f08015801562000728573d6000803e3d6000fd5b505060405162000738906200c1dc565b604051809103906000f08015801562000755573d6000803e3d6000fd5b505060405162000765906200c1dc565b604051809103906000f08015801562000782573d6000803e3d6000fd5b505060405162000792906200c1dc565b604051809103906000f080158015620007af573d6000803e3d6000fd5b5050604051620007bf906200c1dc565b604051809103906000f080158015620007dc573d6000803e3d6000fd5b5050604051620007ec906200c1dc565b604051809103906000f08015801562000809573d6000803e3d6000fd5b505060405162000819906200c1dc565b604051809103906000f08015801562000836573d6000803e3d6000fd5b505060405162000846906200c1dc565b604051809103906000f08015801562000863573d6000803e3d6000fd5b505060405162000873906200c1dc565b604051809103906000f08015801562000890573d6000803e3d6000fd5b5050604051620008a0906200c1dc565b604051809103906000f080158015620008bd573d6000803e3d6000fd5b5050604051620008cd906200c1dc565b604051809103906000f080158015620008ea573d6000803e3d6000fd5b5050604051620008fa906200c1dc565b604051809103906000f08015801562000917573d6000803e3d6000fd5b505060405162000927906200c1dc565b604051809103906000f08015801562000944573d6000803e3d6000fd5b505060405162000954906200c1dc565b604051809103906000f08015801562000971573d6000803e3d6000fd5b505060405162000981906200c1dc565b604051809103906000f0801580156200099e573d6000803e3d6000fd5b5050604051620009ae906200c1dc565b604051809103906000f080158015620009cb573d6000803e3d6000fd5b5050604051620009db906200c1dc565b604051809103906000f080158015620009f8573d6000803e3d6000fd5b505060405162000a08906200c1dc565b604051809103906000f08015801562000a25573d6000803e3d6000fd5b505060405162000a35906200c1dc565b604051809103906000f08015801562000a52573d6000803e3d6000fd5b505060405162000a62906200c1dc565b604051809103906000f08015801562000a7f573d6000803e3d6000fd5b505060405162000a8f906200c1dc565b604051809103906000f08015801562000aac573d6000803e3d6000fd5b505060405162000abc906200c1dc565b604051809103906000f08015801562000ad9573d6000803e3d6000fd5b505060405162000ae9906200c1dc565b604051809103906000f08015801562000b06573d6000803e3d6000fd5b505060405162000b16906200c1dc565b604051809103906000f08015801562000b33573d6000803e3d6000fd5b505060405162000b43906200c1dc565b604051809103906000f08015801562000b60573d6000803e3d6000fd5b505060405162000b70906200c1dc565b604051809103906000f08015801562000b8d573d6000803e3d6000fd5b505060405162000b9d906200c1dc565b604051809103906000f08015801562000bba573d6000803e3d6000fd5b505060405162000bca906200c1dc565b604051809103906000f08015801562000be7573d6000803e3d6000fd5b505060405162000bf7906200c1dc565b604051809103906000f08015801562000c14573d6000803e3d6000fd5b505060405162000c24906200c1dc565b604051809103906000f08015801562000c41573d6000803e3d6000fd5b505060405162000c51906200c1dc565b604051809103906000f08015801562000c6e573d6000803e3d6000fd5b505060405162000c7e906200c1dc565b604051809103906000f08015801562000c9b573d6000803e3d6000fd5b505060405162000cab906200c1dc565b604051809103906000f08015801562000cc8573d6000803e3d6000fd5b505060405162000cd8906200c1dc565b604051809103906000f08015801562000cf5573d6000803e3d6000fd5b505060405162000d05906200c1dc565b604051809103906000f08015801562000d22573d6000803e3d6000fd5b505060405162000d32906200c1dc565b604051809103906000f08015801562000d4f573d6000803e3d6000fd5b505060405162000d5f906200c1dc565b604051809103906000f08015801562000d7c573d6000803e3d6000fd5b505060405162000d8c906200c1dc565b604051809103906000f08015801562000da9573d6000803e3d6000fd5b505060405162000db9906200c1dc565b604051809103906000f08015801562000dd6573d6000803e3d6000fd5b505060405162000de6906200c1dc565b604051809103906000f08015801562000e03573d6000803e3d6000fd5b505060405162000e13906200c1dc565b604051809103906000f08015801562000e30573d6000803e3d6000fd5b505060405162000e40906200c1dc565b604051809103906000f08015801562000e5d573d6000803e3d6000fd5b505060405162000e6d906200c1dc565b604051809103906000f08015801562000e8a573d6000803e3d6000fd5b505060405162000e9a906200c1dc565b604051809103906000f08015801562000eb7573d6000803e3d6000fd5b505060405162000ec7906200c1dc565b604051809103906000f08015801562000ee4573d6000803e3d6000fd5b505060405162000ef4906200c1dc565b604051809103906000f08015801562000f11573d6000803e3d6000fd5b505060405162000f21906200c1dc565b604051809103906000f08015801562000f3e573d6000803e3d6000fd5b505060405162000f4e906200c1dc565b604051809103906000f08015801562000f6b573d6000803e3d6000fd5b505060405162000f7b906200c1dc565b604051809103906000f08015801562000f98573d6000803e3d6000fd5b505060405162000fa8906200c1dc565b604051809103906000f08015801562000fc5573d6000803e3d6000fd5b505060405162000fd5906200c1dc565b604051809103906000f08015801562000ff2573d6000803e3d6000fd5b505060405162001002906200c1dc565b604051809103906000f0801580156200101f573d6000803e3d6000fd5b50506040516200102f906200c1dc565b604051809103906000f0801580156200104c573d6000803e3d6000fd5b50506040516200105c906200c1dc565b604051809103906000f08015801562001079573d6000803e3d6000fd5b505060405162001089906200c1dc565b604051809103906000f080158015620010a6573d6000803e3d6000fd5b5050604051620010b6906200c1dc565b604051809103906000f080158015620010d3573d6000803e3d6000fd5b5050604051620010e3906200c1dc565b604051809103906000f08015801562001100573d6000803e3d6000fd5b505060405162001110906200c1dc565b604051809103906000f0801580156200112d573d6000803e3d6000fd5b50506040516200113d906200c1dc565b604051809103906000f0801580156200115a573d6000803e3d6000fd5b50506040516200116a906200c1dc565b604051809103906000f08015801562001187573d6000803e3d6000fd5b505060405162001197906200c1dc565b604051809103906000f080158015620011b4573d6000803e3d6000fd5b5050604051620011c4906200c1dc565b604051809103906000f080158015620011e1573d6000803e3d6000fd5b5050604051620011f1906200c1dc565b604051809103906000f0801580156200120e573d6000803e3d6000fd5b50506040516200121e906200c1dc565b604051809103906000f0801580156200123b573d6000803e3d6000fd5b50506040516200124b906200c1dc565b604051809103906000f08015801562001268573d6000803e3d6000fd5b505060405162001278906200c1dc565b604051809103906000f08015801562001295573d6000803e3d6000fd5b5050604051620012a5906200c1dc565b604051809103906000f080158015620012c2573d6000803e3d6000fd5b5050604051620012d2906200c1dc565b604051809103906000f080158015620012ef573d6000803e3d6000fd5b5050604051620012ff906200c1dc565b604051809103906000f0801580156200131c573d6000803e3d6000fd5b50506040516200132c906200c1dc565b604051809103906000f08015801562001349573d6000803e3d6000fd5b505060405162001359906200c1dc565b604051809103906000f08015801562001376573d6000803e3d6000fd5b505060405162001386906200c1dc565b604051809103906000f080158015620013a3573d6000803e3d6000fd5b5050604051620013b3906200c1dc565b604051809103906000f080158015620013d0573d6000803e3d6000fd5b5050604051620013e0906200c1dc565b604051809103906000f080158015620013fd573d6000803e3d6000fd5b50506040516200140d906200c1dc565b604051809103906000f0801580156200142a573d6000803e3d6000fd5b50506040516200143a906200c1dc565b604051809103906000f08015801562001457573d6000803e3d6000fd5b505060405162001467906200c1dc565b604051809103906000f08015801562001484573d6000803e3d6000fd5b505060405162001494906200c1dc565b604051809103906000f080158015620014b1573d6000803e3d6000fd5b5050604051620014c1906200c1dc565b604051809103906000f080158015620014de573d6000803e3d6000fd5b5050604051620014ee906200c1dc565b604051809103906000f0801580156200150b573d6000803e3d6000fd5b50506040516200151b906200c1dc565b604051809103906000f08015801562001538573d6000803e3d6000fd5b505060405162001548906200c1dc565b604051809103906000f08015801562001565573d6000803e3d6000fd5b505060405162001575906200c1dc565b604051809103906000f08015801562001592573d6000803e3d6000fd5b5050604051620015a2906200c1dc565b604051809103906000f080158015620015bf573d6000803e3d6000fd5b5050604051620015cf906200c1dc565b604051809103906000f080158015620015ec573d6000803e3d6000fd5b5050604051620015fc906200c1dc565b604051809103906000f08015801562001619573d6000803e3d6000fd5b505060405162001629906200c1dc565b604051809103906000f08015801562001646573d6000803e3d6000fd5b505060405162001656906200c1dc565b604051809103906000f08015801562001673573d6000803e3d6000fd5b505060405162001683906200c1dc565b604051809103906000f080158015620016a0573d6000803e3d6000fd5b5050604051620016b0906200c1dc565b604051809103906000f080158015620016cd573d6000803e3d6000fd5b5050604051620016dd906200c1dc565b604051809103906000f080158015620016fa573d6000803e3d6000fd5b50506040516200170a906200c1dc565b604051809103906000f08015801562001727573d6000803e3d6000fd5b505060405162001737906200c1dc565b604051809103906000f08015801562001754573d6000803e3d6000fd5b505060405162001764906200c1dc565b604051809103906000f08015801562001781573d6000803e3d6000fd5b505060405162001791906200c1dc565b604051809103906000f080158015620017ae573d6000803e3d6000fd5b5050604051620017be906200c1dc565b604051809103906000f080158015620017db573d6000803e3d6000fd5b5050604051620017eb906200c1dc565b604051809103906000f08015801562001808573d6000803e3d6000fd5b505060405162001818906200c1dc565b604051809103906000f08015801562001835573d6000803e3d6000fd5b505060405162001845906200c1dc565b604051809103906000f08015801562001862573d6000803e3d6000fd5b505060405162001872906200c1dc565b604051809103906000f0801580156200188f573d6000803e3d6000fd5b50506040516200189f906200c1dc565b604051809103906000f080158015620018bc573d6000803e3d6000fd5b5050604051620018cc906200c1dc565b604051809103906000f080158015620018e9573d6000803e3d6000fd5b5050604051620018f9906200c1dc565b604051809103906000f08015801562001916573d6000803e3d6000fd5b505060405162001926906200c1dc565b604051809103906000f08015801562001943573d6000803e3d6000fd5b505060405162001953906200c1dc565b604051809103906000f08015801562001970573d6000803e3d6000fd5b505060405162001980906200c1dc565b604051809103906000f0801580156200199d573d6000803e3d6000fd5b5050604051620019ad906200c1dc565b604051809103906000f080158015620019ca573d6000803e3d6000fd5b5050604051620019da906200c1dc565b604051809103906000f080158015620019f7573d6000803e3d6000fd5b505060405162001a07906200c1dc565b604051809103906000f08015801562001a24573d6000803e3d6000fd5b505060405162001a34906200c1dc565b604051809103906000f08015801562001a51573d6000803e3d6000fd5b505060405162001a61906200c1dc565b604051809103906000f08015801562001a7e573d6000803e3d6000fd5b505060405162001a8e906200c1dc565b604051809103906000f08015801562001aab573d6000803e3d6000fd5b505060405162001abb906200c1dc565b604051809103906000f08015801562001ad8573d6000803e3d6000fd5b505060405162001ae8906200c1dc565b604051809103906000f08015801562001b05573d6000803e3d6000fd5b505060405162001b15906200c1dc565b604051809103906000f08015801562001b32573d6000803e3d6000fd5b505060405162001b42906200c1dc565b604051809103906000f08015801562001b5f573d6000803e3d6000fd5b505060405162001b6f906200c1dc565b604051809103906000f08015801562001b8c573d6000803e3d6000fd5b505060405162001b9c906200c1dc565b604051809103906000f08015801562001bb9573d6000803e3d6000fd5b505060405162001bc9906200c1dc565b604051809103906000f08015801562001be6573d6000803e3d6000fd5b505060405162001bf6906200c1dc565b604051809103906000f08015801562001c13573d6000803e3d6000fd5b505060405162001c23906200c1dc565b604051809103906000f08015801562001c40573d6000803e3d6000fd5b505060405162001c50906200c1dc565b604051809103906000f08015801562001c6d573d6000803e3d6000fd5b505060405162001c7d906200c1dc565b604051809103906000f08015801562001c9a573d6000803e3d6000fd5b505060405162001caa906200c1dc565b604051809103906000f08015801562001cc7573d6000803e3d6000fd5b505060405162001cd7906200c1dc565b604051809103906000f08015801562001cf4573d6000803e3d6000fd5b505060405162001d04906200c1dc565b604051809103906000f08015801562001d21573d6000803e3d6000fd5b505060405162001d31906200c1dc565b604051809103906000f08015801562001d4e573d6000803e3d6000fd5b505060405162001d5e906200c1dc565b604051809103906000f08015801562001d7b573d6000803e3d6000fd5b505060405162001d8b906200c1dc565b604051809103906000f08015801562001da8573d6000803e3d6000fd5b505060405162001db8906200c1dc565b604051809103906000f08015801562001dd5573d6000803e3d6000fd5b505060405162001de5906200c1dc565b604051809103906000f08015801562001e02573d6000803e3d6000fd5b505060405162001e12906200c1dc565b604051809103906000f08015801562001e2f573d6000803e3d6000fd5b505060405162001e3f906200c1dc565b604051809103906000f08015801562001e5c573d6000803e3d6000fd5b505060405162001e6c906200c1dc565b604051809103906000f08015801562001e89573d6000803e3d6000fd5b505060405162001e99906200c1dc565b604051809103906000f08015801562001eb6573d6000803e3d6000fd5b505060405162001ec6906200c1dc565b604051809103906000f08015801562001ee3573d6000803e3d6000fd5b505060405162001ef3906200c1dc565b604051809103906000f08015801562001f10573d6000803e3d6000fd5b505060405162001f20906200c1dc565b604051809103906000f08015801562001f3d573d6000803e3d6000fd5b505060405162001f4d906200c1dc565b604051809103906000f08015801562001f6a573d6000803e3d6000fd5b505060405162001f7a906200c1dc565b604051809103906000f08015801562001f97573d6000803e3d6000fd5b505060405162001fa7906200c1dc565b604051809103906000f08015801562001fc4573d6000803e3d6000fd5b505060405162001fd4906200c1dc565b604051809103906000f08015801562001ff1573d6000803e3d6000fd5b505060405162002001906200c1dc565b604051809103906000f0801580156200201e573d6000803e3d6000fd5b50506040516200202e906200c1dc565b604051809103906000f0801580156200204b573d6000803e3d6000fd5b50506040516200205b906200c1dc565b604051809103906000f08015801562002078573d6000803e3d6000fd5b505060405162002088906200c1dc565b604051809103906000f080158015620020a5573d6000803e3d6000fd5b5050604051620020b5906200c1dc565b604051809103906000f080158015620020d2573d6000803e3d6000fd5b5050604051620020e2906200c1dc565b604051809103906000f080158015620020ff573d6000803e3d6000fd5b50506040516200210f906200c1dc565b604051809103906000f0801580156200212c573d6000803e3d6000fd5b50506040516200213c906200c1dc565b604051809103906000f08015801562002159573d6000803e3d6000fd5b505060405162002169906200c1dc565b604051809103906000f08015801562002186573d6000803e3d6000fd5b505060405162002196906200c1dc565b604051809103906000f080158015620021b3573d6000803e3d6000fd5b5050604051620021c3906200c1dc565b604051809103906000f080158015620021e0573d6000803e3d6000fd5b5050604051620021f0906200c1dc565b604051809103906000f0801580156200220d573d6000803e3d6000fd5b50506040516200221d906200c1dc565b604051809103906000f0801580156200223a573d6000803e3d6000fd5b50506040516200224a906200c1dc565b604051809103906000f08015801562002267573d6000803e3d6000fd5b505060405162002277906200c1dc565b604051809103906000f08015801562002294573d6000803e3d6000fd5b5050604051620022a4906200c1dc565b604051809103906000f080158015620022c1573d6000803e3d6000fd5b5050604051620022d1906200c1dc565b604051809103906000f080158015620022ee573d6000803e3d6000fd5b5050604051620022fe906200c1dc565b604051809103906000f0801580156200231b573d6000803e3d6000fd5b50506040516200232b906200c1dc565b604051809103906000f08015801562002348573d6000803e3d6000fd5b505060405162002358906200c1dc565b604051809103906000f08015801562002375573d6000803e3d6000fd5b505060405162002385906200c1dc565b604051809103906000f080158015620023a2573d6000803e3d6000fd5b5050604051620023b2906200c1dc565b604051809103906000f080158015620023cf573d6000803e3d6000fd5b5050604051620023df906200c1dc565b604051809103906000f080158015620023fc573d6000803e3d6000fd5b50506040516200240c906200c1dc565b604051809103906000f08015801562002429573d6000803e3d6000fd5b505060405162002439906200c1dc565b604051809103906000f08015801562002456573d6000803e3d6000fd5b505060405162002466906200c1dc565b604051809103906000f08015801562002483573d6000803e3d6000fd5b505060405162002493906200c1dc565b604051809103906000f080158015620024b0573d6000803e3d6000fd5b5050604051620024c0906200c1dc565b604051809103906000f080158015620024dd573d6000803e3d6000fd5b5050604051620024ed906200c1dc565b604051809103906000f0801580156200250a573d6000803e3d6000fd5b50506040516200251a906200c1dc565b604051809103906000f08015801562002537573d6000803e3d6000fd5b505060405162002547906200c1dc565b604051809103906000f08015801562002564573d6000803e3d6000fd5b505060405162002574906200c1dc565b604051809103906000f08015801562002591573d6000803e3d6000fd5b5050604051620025a1906200c1dc565b604051809103906000f080158015620025be573d6000803e3d6000fd5b5050604051620025ce906200c1dc565b604051809103906000f080158015620025eb573d6000803e3d6000fd5b5050604051620025fb906200c1dc565b604051809103906000f08015801562002618573d6000803e3d6000fd5b505060405162002628906200c1dc565b604051809103906000f08015801562002645573d6000803e3d6000fd5b505060405162002655906200c1dc565b604051809103906000f08015801562002672573d6000803e3d6000fd5b505060405162002682906200c1dc565b604051809103906000f0801580156200269f573d6000803e3d6000fd5b5050604051620026af906200c1dc565b604051809103906000f080158015620026cc573d6000803e3d6000fd5b5050604051620026dc906200c1dc565b604051809103906000f080158015620026f9573d6000803e3d6000fd5b505060405162002709906200c1dc565b604051809103906000f08015801562002726573d6000803e3d6000fd5b505060405162002736906200c1dc565b604051809103906000f08015801562002753573d6000803e3d6000fd5b505060405162002763906200c1dc565b604051809103906000f08015801562002780573d6000803e3d6000fd5b505060405162002790906200c1dc565b604051809103906000f080158015620027ad573d6000803e3d6000fd5b5050604051620027bd906200c1dc565b604051809103906000f080158015620027da573d6000803e3d6000fd5b5050604051620027ea906200c1dc565b604051809103906000f08015801562002807573d6000803e3d6000fd5b505060405162002817906200c1dc565b604051809103906000f08015801562002834573d6000803e3d6000fd5b505060405162002844906200c1dc565b604051809103906000f08015801562002861573d6000803e3d6000fd5b505060405162002871906200c1dc565b604051809103906000f0801580156200288e573d6000803e3d6000fd5b50506040516200289e906200c1dc565b604051809103906000f080158015620028bb573d6000803e3d6000fd5b5050604051620028cb906200c1dc565b604051809103906000f080158015620028e8573d6000803e3d6000fd5b5050604051620028f8906200c1dc565b604051809103906000f08015801562002915573d6000803e3d6000fd5b505060405162002925906200c1dc565b604051809103906000f08015801562002942573d6000803e3d6000fd5b505060405162002952906200c1dc565b604051809103906000f0801580156200296f573d6000803e3d6000fd5b50506040516200297f906200c1dc565b604051809103906000f0801580156200299c573d6000803e3d6000fd5b5050604051620029ac906200c1dc565b604051809103906000f080158015620029c9573d6000803e3d6000fd5b5050604051620029d9906200c1dc565b604051809103906000f080158015620029f6573d6000803e3d6000fd5b505060405162002a06906200c1dc565b604051809103906000f08015801562002a23573d6000803e3d6000fd5b505060405162002a33906200c1dc565b604051809103906000f08015801562002a50573d6000803e3d6000fd5b505060405162002a60906200c1dc565b604051809103906000f08015801562002a7d573d6000803e3d6000fd5b505060405162002a8d906200c1dc565b604051809103906000f08015801562002aaa573d6000803e3d6000fd5b505060405162002aba906200c1dc565b604051809103906000f08015801562002ad7573d6000803e3d6000fd5b505060405162002ae7906200c1dc565b604051809103906000f08015801562002b04573d6000803e3d6000fd5b505060405162002b14906200c1dc565b604051809103906000f08015801562002b31573d6000803e3d6000fd5b505060405162002b41906200c1dc565b604051809103906000f08015801562002b5e573d6000803e3d6000fd5b505060405162002b6e906200c1dc565b604051809103906000f08015801562002b8b573d6000803e3d6000fd5b505060405162002b9b906200c1dc565b604051809103906000f08015801562002bb8573d6000803e3d6000fd5b505060405162002bc8906200c1dc565b604051809103906000f08015801562002be5573d6000803e3d6000fd5b505060405162002bf5906200c1dc565b604051809103906000f08015801562002c12573d6000803e3d6000fd5b505060405162002c22906200c1dc565b604051809103906000f08015801562002c3f573d6000803e3d6000fd5b505060405162002c4f906200c1dc565b604051809103906000f08015801562002c6c573d6000803e3d6000fd5b505060405162002c7c906200c1dc565b604051809103906000f08015801562002c99573d6000803e3d6000fd5b505060405162002ca9906200c1dc565b604051809103906000f08015801562002cc6573d6000803e3d6000fd5b505060405162002cd6906200c1dc565b604051809103906000f08015801562002cf3573d6000803e3d6000fd5b505060405162002d03906200c1dc565b604051809103906000f08015801562002d20573d6000803e3d6000fd5b505060405162002d30906200c1dc565b604051809103906000f08015801562002d4d573d6000803e3d6000fd5b505060405162002d5d906200c1dc565b604051809103906000f08015801562002d7a573d6000803e3d6000fd5b505060405162002d8a906200c1dc565b604051809103906000f08015801562002da7573d6000803e3d6000fd5b505060405162002db7906200c1dc565b604051809103906000f08015801562002dd4573d6000803e3d6000fd5b505060405162002de4906200c1dc565b604051809103906000f08015801562002e01573d6000803e3d6000fd5b505060405162002e11906200c1dc565b604051809103906000f08015801562002e2e573d6000803e3d6000fd5b505060405162002e3e906200c1dc565b604051809103906000f08015801562002e5b573d6000803e3d6000fd5b505060405162002e6b906200c1dc565b604051809103906000f08015801562002e88573d6000803e3d6000fd5b505060405162002e98906200c1dc565b604051809103906000f08015801562002eb5573d6000803e3d6000fd5b505060405162002ec5906200c1dc565b604051809103906000f08015801562002ee2573d6000803e3d6000fd5b505060405162002ef2906200c1dc565b604051809103906000f08015801562002f0f573d6000803e3d6000fd5b505060405162002f1f906200c1dc565b604051809103906000f08015801562002f3c573d6000803e3d6000fd5b505060405162002f4c906200c1dc565b604051809103906000f08015801562002f69573d6000803e3d6000fd5b505060405162002f79906200c1dc565b604051809103906000f08015801562002f96573d6000803e3d6000fd5b505060405162002fa6906200c1dc565b604051809103906000f08015801562002fc3573d6000803e3d6000fd5b505060405162002fd3906200c1dc565b604051809103906000f08015801562002ff0573d6000803e3d6000fd5b505060405162003000906200c1dc565b604051809103906000f0801580156200301d573d6000803e3d6000fd5b50506040516200302d906200c1dc565b604051809103906000f0801580156200304a573d6000803e3d6000fd5b50506040516200305a906200c1dc565b604051809103906000f08015801562003077573d6000803e3d6000fd5b505060405162003087906200c1dc565b604051809103906000f080158015620030a4573d6000803e3d6000fd5b5050604051620030b4906200c1dc565b604051809103906000f080158015620030d1573d6000803e3d6000fd5b5050604051620030e1906200c1dc565b604051809103906000f080158015620030fe573d6000803e3d6000fd5b50506040516200310e906200c1dc565b604051809103906000f0801580156200312b573d6000803e3d6000fd5b50506040516200313b906200c1dc565b604051809103906000f08015801562003158573d6000803e3d6000fd5b505060405162003168906200c1dc565b604051809103906000f08015801562003185573d6000803e3d6000fd5b505060405162003195906200c1dc565b604051809103906000f080158015620031b2573d6000803e3d6000fd5b5050604051620031c2906200c1dc565b604051809103906000f080158015620031df573d6000803e3d6000fd5b5050604051620031ef906200c1dc565b604051809103906000f0801580156200320c573d6000803e3d6000fd5b50506040516200321c906200c1dc565b604051809103906000f08015801562003239573d6000803e3d6000fd5b505060405162003249906200c1dc565b604051809103906000f08015801562003266573d6000803e3d6000fd5b505060405162003276906200c1dc565b604051809103906000f08015801562003293573d6000803e3d6000fd5b5050604051620032a3906200c1dc565b604051809103906000f080158015620032c0573d6000803e3d6000fd5b5050604051620032d0906200c1dc565b604051809103906000f080158015620032ed573d6000803e3d6000fd5b5050604051620032fd906200c1dc565b604051809103906000f0801580156200331a573d6000803e3d6000fd5b50506040516200332a906200c1dc565b604051809103906000f08015801562003347573d6000803e3d6000fd5b505060405162003357906200c1dc565b604051809103906000f08015801562003374573d6000803e3d6000fd5b505060405162003384906200c1dc565b604051809103906000f080158015620033a1573d6000803e3d6000fd5b5050604051620033b1906200c1dc565b604051809103906000f080158015620033ce573d6000803e3d6000fd5b5050604051620033de906200c1dc565b604051809103906000f080158015620033fb573d6000803e3d6000fd5b50506040516200340b906200c1dc565b604051809103906000f08015801562003428573d6000803e3d6000fd5b505060405162003438906200c1dc565b604051809103906000f08015801562003455573d6000803e3d6000fd5b505060405162003465906200c1dc565b604051809103906000f08015801562003482573d6000803e3d6000fd5b505060405162003492906200c1dc565b604051809103906000f080158015620034af573d6000803e3d6000fd5b5050604051620034bf906200c1dc565b604051809103906000f080158015620034dc573d6000803e3d6000fd5b5050604051620034ec906200c1dc565b604051809103906000f08015801562003509573d6000803e3d6000fd5b505060405162003519906200c1dc565b604051809103906000f08015801562003536573d6000803e3d6000fd5b505060405162003546906200c1dc565b604051809103906000f08015801562003563573d6000803e3d6000fd5b505060405162003573906200c1dc565b604051809103906000f08015801562003590573d6000803e3d6000fd5b5050604051620035a0906200c1dc565b604051809103906000f080158015620035bd573d6000803e3d6000fd5b5050604051620035cd906200c1dc565b604051809103906000f080158015620035ea573d6000803e3d6000fd5b5050604051620035fa906200c1dc565b604051809103906000f08015801562003617573d6000803e3d6000fd5b505060405162003627906200c1dc565b604051809103906000f08015801562003644573d6000803e3d6000fd5b505060405162003654906200c1dc565b604051809103906000f08015801562003671573d6000803e3d6000fd5b505060405162003681906200c1dc565b604051809103906000f0801580156200369e573d6000803e3d6000fd5b5050604051620036ae906200c1dc565b604051809103906000f080158015620036cb573d6000803e3d6000fd5b5050604051620036db906200c1dc565b604051809103906000f080158015620036f8573d6000803e3d6000fd5b505060405162003708906200c1dc565b604051809103906000f08015801562003725573d6000803e3d6000fd5b505060405162003735906200c1dc565b604051809103906000f08015801562003752573d6000803e3d6000fd5b505060405162003762906200c1dc565b604051809103906000f0801580156200377f573d6000803e3d6000fd5b50506040516200378f906200c1dc565b604051809103906000f080158015620037ac573d6000803e3d6000fd5b5050604051620037bc906200c1dc565b604051809103906000f080158015620037d9573d6000803e3d6000fd5b5050604051620037e9906200c1dc565b604051809103906000f08015801562003806573d6000803e3d6000fd5b505060405162003816906200c1dc565b604051809103906000f08015801562003833573d6000803e3d6000fd5b505060405162003843906200c1dc565b604051809103906000f08015801562003860573d6000803e3d6000fd5b505060405162003870906200c1dc565b604051809103906000f0801580156200388d573d6000803e3d6000fd5b50506040516200389d906200c1dc565b604051809103906000f080158015620038ba573d6000803e3d6000fd5b5050604051620038ca906200c1dc565b604051809103906000f080158015620038e7573d6000803e3d6000fd5b5050604051620038f7906200c1dc565b604051809103906000f08015801562003914573d6000803e3d6000fd5b505060405162003924906200c1dc565b604051809103906000f08015801562003941573d6000803e3d6000fd5b505060405162003951906200c1dc565b604051809103906000f0801580156200396e573d6000803e3d6000fd5b50506040516200397e906200c1dc565b604051809103906000f0801580156200399b573d6000803e3d6000fd5b5050604051620039ab906200c1dc565b604051809103906000f080158015620039c8573d6000803e3d6000fd5b5050604051620039d8906200c1dc565b604051809103906000f080158015620039f5573d6000803e3d6000fd5b505060405162003a05906200c1dc565b604051809103906000f08015801562003a22573d6000803e3d6000fd5b505060405162003a32906200c1dc565b604051809103906000f08015801562003a4f573d6000803e3d6000fd5b505060405162003a5f906200c1dc565b604051809103906000f08015801562003a7c573d6000803e3d6000fd5b505060405162003a8c906200c1dc565b604051809103906000f08015801562003aa9573d6000803e3d6000fd5b505060405162003ab9906200c1dc565b604051809103906000f08015801562003ad6573d6000803e3d6000fd5b505060405162003ae6906200c1dc565b604051809103906000f08015801562003b03573d6000803e3d6000fd5b505060405162003b13906200c1dc565b604051809103906000f08015801562003b30573d6000803e3d6000fd5b505060405162003b40906200c1dc565b604051809103906000f08015801562003b5d573d6000803e3d6000fd5b505060405162003b6d906200c1dc565b604051809103906000f08015801562003b8a573d6000803e3d6000fd5b505060405162003b9a906200c1dc565b604051809103906000f08015801562003bb7573d6000803e3d6000fd5b505060405162003bc7906200c1dc565b604051809103906000f08015801562003be4573d6000803e3d6000fd5b505060405162003bf4906200c1dc565b604051809103906000f08015801562003c11573d6000803e3d6000fd5b505060405162003c21906200c1dc565b604051809103906000f08015801562003c3e573d6000803e3d6000fd5b505060405162003c4e906200c1dc565b604051809103906000f08015801562003c6b573d6000803e3d6000fd5b505060405162003c7b906200c1dc565b604051809103906000f08015801562003c98573d6000803e3d6000fd5b505060405162003ca8906200c1dc565b604051809103906000f08015801562003cc5573d6000803e3d6000fd5b505060405162003cd5906200c1dc565b604051809103906000f08015801562003cf2573d6000803e3d6000fd5b505060405162003d02906200c1dc565b604051809103906000f08015801562003d1f573d6000803e3d6000fd5b505060405162003d2f906200c1dc565b604051809103906000f08015801562003d4c573d6000803e3d6000fd5b505060405162003d5c906200c1dc565b604051809103906000f08015801562003d79573d6000803e3d6000fd5b505060405162003d89906200c1dc565b604051809103906000f08015801562003da6573d6000803e3d6000fd5b505060405162003db6906200c1dc565b604051809103906000f08015801562003dd3573d6000803e3d6000fd5b505060405162003de3906200c1dc565b604051809103906000f08015801562003e00573d6000803e3d6000fd5b505060405162003e10906200c1dc565b604051809103906000f08015801562003e2d573d6000803e3d6000fd5b505060405162003e3d906200c1dc565b604051809103906000f08015801562003e5a573d6000803e3d6000fd5b505060405162003e6a906200c1dc565b604051809103906000f08015801562003e87573d6000803e3d6000fd5b505060405162003e97906200c1dc565b604051809103906000f08015801562003eb4573d6000803e3d6000fd5b505060405162003ec4906200c1dc565b604051809103906000f08015801562003ee1573d6000803e3d6000fd5b505060405162003ef1906200c1dc565b604051809103906000f08015801562003f0e573d6000803e3d6000fd5b505060405162003f1e906200c1dc565b604051809103906000f08015801562003f3b573d6000803e3d6000fd5b505060405162003f4b906200c1dc565b604051809103906000f08015801562003f68573d6000803e3d6000fd5b505060405162003f78906200c1dc565b604051809103906000f08015801562003f95573d6000803e3d6000fd5b505060405162003fa5906200c1dc565b604051809103906000f08015801562003fc2573d6000803e3d6000fd5b505060405162003fd2906200c1dc565b604051809103906000f08015801562003fef573d6000803e3d6000fd5b505060405162003fff906200c1dc565b604051809103906000f0801580156200401c573d6000803e3d6000fd5b50506040516200402c906200c1dc565b604051809103906000f08015801562004049573d6000803e3d6000fd5b505060405162004059906200c1dc565b604051809103906000f08015801562004076573d6000803e3d6000fd5b505060405162004086906200c1dc565b604051809103906000f080158015620040a3573d6000803e3d6000fd5b5050604051620040b3906200c1dc565b604051809103906000f080158015620040d0573d6000803e3d6000fd5b5050604051620040e0906200c1dc565b604051809103906000f080158015620040fd573d6000803e3d6000fd5b50506040516200410d906200c1dc565b604051809103906000f0801580156200412a573d6000803e3d6000fd5b50506040516200413a906200c1dc565b604051809103906000f08015801562004157573d6000803e3d6000fd5b505060405162004167906200c1dc565b604051809103906000f08015801562004184573d6000803e3d6000fd5b505060405162004194906200c1dc565b604051809103906000f080158015620041b1573d6000803e3d6000fd5b5050604051620041c1906200c1dc565b604051809103906000f080158015620041de573d6000803e3d6000fd5b5050604051620041ee906200c1dc565b604051809103906000f0801580156200420b573d6000803e3d6000fd5b50506040516200421b906200c1dc565b604051809103906000f08015801562004238573d6000803e3d6000fd5b505060405162004248906200c1dc565b604051809103906000f08015801562004265573d6000803e3d6000fd5b505060405162004275906200c1dc565b604051809103906000f08015801562004292573d6000803e3d6000fd5b5050604051620042a2906200c1dc565b604051809103906000f080158015620042bf573d6000803e3d6000fd5b5050604051620042cf906200c1dc565b604051809103906000f080158015620042ec573d6000803e3d6000fd5b5050604051620042fc906200c1dc565b604051809103906000f08015801562004319573d6000803e3d6000fd5b505060405162004329906200c1dc565b604051809103906000f08015801562004346573d6000803e3d6000fd5b505060405162004356906200c1dc565b604051809103906000f08015801562004373573d6000803e3d6000fd5b505060405162004383906200c1dc565b604051809103906000f080158015620043a0573d6000803e3d6000fd5b5050604051620043b0906200c1dc565b604051809103906000f080158015620043cd573d6000803e3d6000fd5b5050604051620043dd906200c1dc565b604051809103906000f080158015620043fa573d6000803e3d6000fd5b50506040516200440a906200c1dc565b604051809103906000f08015801562004427573d6000803e3d6000fd5b505060405162004437906200c1dc565b604051809103906000f08015801562004454573d6000803e3d6000fd5b505060405162004464906200c1dc565b604051809103906000f08015801562004481573d6000803e3d6000fd5b505060405162004491906200c1dc565b604051809103906000f080158015620044ae573d6000803e3d6000fd5b5050604051620044be906200c1dc565b604051809103906000f080158015620044db573d6000803e3d6000fd5b5050604051620044eb906200c1dc565b604051809103906000f08015801562004508573d6000803e3d6000fd5b505060405162004518906200c1dc565b604051809103906000f08015801562004535573d6000803e3d6000fd5b505060405162004545906200c1dc565b604051809103906000f08015801562004562573d6000803e3d6000fd5b505060405162004572906200c1dc565b604051809103906000f0801580156200458f573d6000803e3d6000fd5b50506040516200459f906200c1dc565b604051809103906000f080158015620045bc573d6000803e3d6000fd5b5050604051620045cc906200c1dc565b604051809103906000f080158015620045e9573d6000803e3d6000fd5b5050604051620045f9906200c1dc565b604051809103906000f08015801562004616573d6000803e3d6000fd5b505060405162004626906200c1dc565b604051809103906000f08015801562004643573d6000803e3d6000fd5b505060405162004653906200c1dc565b604051809103906000f08015801562004670573d6000803e3d6000fd5b505060405162004680906200c1dc565b604051809103906000f0801580156200469d573d6000803e3d6000fd5b5050604051620046ad906200c1dc565b604051809103906000f080158015620046ca573d6000803e3d6000fd5b5050604051620046da906200c1dc565b604051809103906000f080158015620046f7573d6000803e3d6000fd5b505060405162004707906200c1dc565b604051809103906000f08015801562004724573d6000803e3d6000fd5b505060405162004734906200c1dc565b604051809103906000f08015801562004751573d6000803e3d6000fd5b505060405162004761906200c1dc565b604051809103906000f0801580156200477e573d6000803e3d6000fd5b50506040516200478e906200c1dc565b604051809103906000f080158015620047ab573d6000803e3d6000fd5b5050604051620047bb906200c1dc565b604051809103906000f080158015620047d8573d6000803e3d6000fd5b5050604051620047e8906200c1dc565b604051809103906000f08015801562004805573d6000803e3d6000fd5b505060405162004815906200c1dc565b604051809103906000f08015801562004832573d6000803e3d6000fd5b505060405162004842906200c1dc565b604051809103906000f0801580156200485f573d6000803e3d6000fd5b50506040516200486f906200c1dc565b604051809103906000f0801580156200488c573d6000803e3d6000fd5b50506040516200489c906200c1dc565b604051809103906000f080158015620048b9573d6000803e3d6000fd5b5050604051620048c9906200c1dc565b604051809103906000f080158015620048e6573d6000803e3d6000fd5b5050604051620048f6906200c1dc565b604051809103906000f08015801562004913573d6000803e3d6000fd5b505060405162004923906200c1dc565b604051809103906000f08015801562004940573d6000803e3d6000fd5b505060405162004950906200c1dc565b604051809103906000f0801580156200496d573d6000803e3d6000fd5b50506040516200497d906200c1dc565b604051809103906000f0801580156200499a573d6000803e3d6000fd5b5050604051620049aa906200c1dc565b604051809103906000f080158015620049c7573d6000803e3d6000fd5b5050604051620049d7906200c1dc565b604051809103906000f080158015620049f4573d6000803e3d6000fd5b505060405162004a04906200c1dc565b604051809103906000f08015801562004a21573d6000803e3d6000fd5b505060405162004a31906200c1dc565b604051809103906000f08015801562004a4e573d6000803e3d6000fd5b505060405162004a5e906200c1dc565b604051809103906000f08015801562004a7b573d6000803e3d6000fd5b505060405162004a8b906200c1dc565b604051809103906000f08015801562004aa8573d6000803e3d6000fd5b505060405162004ab8906200c1dc565b604051809103906000f08015801562004ad5573d6000803e3d6000fd5b505060405162004ae5906200c1dc565b604051809103906000f08015801562004b02573d6000803e3d6000fd5b505060405162004b12906200c1dc565b604051809103906000f08015801562004b2f573d6000803e3d6000fd5b505060405162004b3f906200c1dc565b604051809103906000f08015801562004b5c573d6000803e3d6000fd5b505060405162004b6c906200c1dc565b604051809103906000f08015801562004b89573d6000803e3d6000fd5b505060405162004b99906200c1dc565b604051809103906000f08015801562004bb6573d6000803e3d6000fd5b505060405162004bc6906200c1dc565b604051809103906000f08015801562004be3573d6000803e3d6000fd5b505060405162004bf3906200c1dc565b604051809103906000f08015801562004c10573d6000803e3d6000fd5b505060405162004c20906200c1dc565b604051809103906000f08015801562004c3d573d6000803e3d6000fd5b505060405162004c4d906200c1dc565b604051809103906000f08015801562004c6a573d6000803e3d6000fd5b505060405162004c7a906200c1dc565b604051809103906000f08015801562004c97573d6000803e3d6000fd5b505060405162004ca7906200c1dc565b604051809103906000f08015801562004cc4573d6000803e3d6000fd5b505060405162004cd4906200c1dc565b604051809103906000f08015801562004cf1573d6000803e3d6000fd5b505060405162004d01906200c1dc565b604051809103906000f08015801562004d1e573d6000803e3d6000fd5b505060405162004d2e906200c1dc565b604051809103906000f08015801562004d4b573d6000803e3d6000fd5b505060405162004d5b906200c1dc565b604051809103906000f08015801562004d78573d6000803e3d6000fd5b505060405162004d88906200c1dc565b604051809103906000f08015801562004da5573d6000803e3d6000fd5b505060405162004db5906200c1dc565b604051809103906000f08015801562004dd2573d6000803e3d6000fd5b505060405162004de2906200c1dc565b604051809103906000f08015801562004dff573d6000803e3d6000fd5b505060405162004e0f906200c1dc565b604051809103906000f08015801562004e2c573d6000803e3d6000fd5b505060405162004e3c906200c1dc565b604051809103906000f08015801562004e59573d6000803e3d6000fd5b505060405162004e69906200c1dc565b604051809103906000f08015801562004e86573d6000803e3d6000fd5b505060405162004e96906200c1dc565b604051809103906000f08015801562004eb3573d6000803e3d6000fd5b505060405162004ec3906200c1dc565b604051809103906000f08015801562004ee0573d6000803e3d6000fd5b505060405162004ef0906200c1dc565b604051809103906000f08015801562004f0d573d6000803e3d6000fd5b505060405162004f1d906200c1dc565b604051809103906000f08015801562004f3a573d6000803e3d6000fd5b505060405162004f4a906200c1dc565b604051809103906000f08015801562004f67573d6000803e3d6000fd5b505060405162004f77906200c1dc565b604051809103906000f08015801562004f94573d6000803e3d6000fd5b505060405162004fa4906200c1dc565b604051809103906000f08015801562004fc1573d6000803e3d6000fd5b505060405162004fd1906200c1dc565b604051809103906000f08015801562004fee573d6000803e3d6000fd5b505060405162004ffe906200c1dc565b604051809103906000f0801580156200501b573d6000803e3d6000fd5b50506040516200502b906200c1dc565b604051809103906000f08015801562005048573d6000803e3d6000fd5b505060405162005058906200c1dc565b604051809103906000f08015801562005075573d6000803e3d6000fd5b505060405162005085906200c1dc565b604051809103906000f080158015620050a2573d6000803e3d6000fd5b5050604051620050b2906200c1dc565b604051809103906000f080158015620050cf573d6000803e3d6000fd5b5050604051620050df906200c1dc565b604051809103906000f080158015620050fc573d6000803e3d6000fd5b50506040516200510c906200c1dc565b604051809103906000f08015801562005129573d6000803e3d6000fd5b505060405162005139906200c1dc565b604051809103906000f08015801562005156573d6000803e3d6000fd5b505060405162005166906200c1dc565b604051809103906000f08015801562005183573d6000803e3d6000fd5b505060405162005193906200c1dc565b604051809103906000f080158015620051b0573d6000803e3d6000fd5b5050604051620051c0906200c1dc565b604051809103906000f080158015620051dd573d6000803e3d6000fd5b5050604051620051ed906200c1dc565b604051809103906000f0801580156200520a573d6000803e3d6000fd5b50506040516200521a906200c1dc565b604051809103906000f08015801562005237573d6000803e3d6000fd5b505060405162005247906200c1dc565b604051809103906000f08015801562005264573d6000803e3d6000fd5b505060405162005274906200c1dc565b604051809103906000f08015801562005291573d6000803e3d6000fd5b5050604051620052a1906200c1dc565b604051809103906000f080158015620052be573d6000803e3d6000fd5b5050604051620052ce906200c1dc565b604051809103906000f080158015620052eb573d6000803e3d6000fd5b5050604051620052fb906200c1dc565b604051809103906000f08015801562005318573d6000803e3d6000fd5b505060405162005328906200c1dc565b604051809103906000f08015801562005345573d6000803e3d6000fd5b505060405162005355906200c1dc565b604051809103906000f08015801562005372573d6000803e3d6000fd5b505060405162005382906200c1dc565b604051809103906000f0801580156200539f573d6000803e3d6000fd5b5050604051620053af906200c1dc565b604051809103906000f080158015620053cc573d6000803e3d6000fd5b5050604051620053dc906200c1dc565b604051809103906000f080158015620053f9573d6000803e3d6000fd5b505060405162005409906200c1dc565b604051809103906000f08015801562005426573d6000803e3d6000fd5b505060405162005436906200c1dc565b604051809103906000f08015801562005453573d6000803e3d6000fd5b505060405162005463906200c1dc565b604051809103906000f08015801562005480573d6000803e3d6000fd5b505060405162005490906200c1dc565b604051809103906000f080158015620054ad573d6000803e3d6000fd5b5050604051620054bd906200c1dc565b604051809103906000f080158015620054da573d6000803e3d6000fd5b5050604051620054ea906200c1dc565b604051809103906000f08015801562005507573d6000803e3d6000fd5b505060405162005517906200c1dc565b604051809103906000f08015801562005534573d6000803e3d6000fd5b505060405162005544906200c1dc565b604051809103906000f08015801562005561573d6000803e3d6000fd5b505060405162005571906200c1dc565b604051809103906000f0801580156200558e573d6000803e3d6000fd5b50506040516200559e906200c1dc565b604051809103906000f080158015620055bb573d6000803e3d6000fd5b5050604051620055cb906200c1dc565b604051809103906000f080158015620055e8573d6000803e3d6000fd5b5050604051620055f8906200c1dc565b604051809103906000f08015801562005615573d6000803e3d6000fd5b505060405162005625906200c1dc565b604051809103906000f08015801562005642573d6000803e3d6000fd5b505060405162005652906200c1dc565b604051809103906000f0801580156200566f573d6000803e3d6000fd5b50506040516200567f906200c1dc565b604051809103906000f0801580156200569c573d6000803e3d6000fd5b5050604051620056ac906200c1dc565b604051809103906000f080158015620056c9573d6000803e3d6000fd5b5050604051620056d9906200c1dc565b604051809103906000f080158015620056f6573d6000803e3d6000fd5b505060405162005706906200c1dc565b604051809103906000f08015801562005723573d6000803e3d6000fd5b505060405162005733906200c1dc565b604051809103906000f08015801562005750573d6000803e3d6000fd5b505060405162005760906200c1dc565b604051809103906000f0801580156200577d573d6000803e3d6000fd5b50506040516200578d906200c1dc565b604051809103906000f080158015620057aa573d6000803e3d6000fd5b5050604051620057ba906200c1dc565b604051809103906000f080158015620057d7573d6000803e3d6000fd5b5050604051620057e7906200c1dc565b604051809103906000f08015801562005804573d6000803e3d6000fd5b505060405162005814906200c1dc565b604051809103906000f08015801562005831573d6000803e3d6000fd5b505060405162005841906200c1dc565b604051809103906000f0801580156200585e573d6000803e3d6000fd5b50506040516200586e906200c1dc565b604051809103906000f0801580156200588b573d6000803e3d6000fd5b50506040516200589b906200c1dc565b604051809103906000f080158015620058b8573d6000803e3d6000fd5b5050604051620058c8906200c1dc565b604051809103906000f080158015620058e5573d6000803e3d6000fd5b5050604051620058f5906200c1dc565b604051809103906000f08015801562005912573d6000803e3d6000fd5b505060405162005922906200c1dc565b604051809103906000f0801580156200593f573d6000803e3d6000fd5b50506040516200594f906200c1dc565b604051809103906000f0801580156200596c573d6000803e3d6000fd5b50506040516200597c906200c1dc565b604051809103906000f08015801562005999573d6000803e3d6000fd5b5050604051620059a9906200c1dc565b604051809103906000f080158015620059c6573d6000803e3d6000fd5b5050604051620059d6906200c1dc565b604051809103906000f080158015620059f3573d6000803e3d6000fd5b505060405162005a03906200c1dc565b604051809103906000f08015801562005a20573d6000803e3d6000fd5b505060405162005a30906200c1dc565b604051809103906000f08015801562005a4d573d6000803e3d6000fd5b505060405162005a5d906200c1dc565b604051809103906000f08015801562005a7a573d6000803e3d6000fd5b505060405162005a8a906200c1dc565b604051809103906000f08015801562005aa7573d6000803e3d6000fd5b505060405162005ab7906200c1dc565b604051809103906000f08015801562005ad4573d6000803e3d6000fd5b505060405162005ae4906200c1dc565b604051809103906000f08015801562005b01573d6000803e3d6000fd5b505060405162005b11906200c1dc565b604051809103906000f08015801562005b2e573d6000803e3d6000fd5b505060405162005b3e906200c1dc565b604051809103906000f08015801562005b5b573d6000803e3d6000fd5b505060405162005b6b906200c1dc565b604051809103906000f08015801562005b88573d6000803e3d6000fd5b505060405162005b98906200c1dc565b604051809103906000f08015801562005bb5573d6000803e3d6000fd5b505060405162005bc5906200c1dc565b604051809103906000f08015801562005be2573d6000803e3d6000fd5b505060405162005bf2906200c1dc565b604051809103906000f08015801562005c0f573d6000803e3d6000fd5b505060405162005c1f906200c1dc565b604051809103906000f08015801562005c3c573d6000803e3d6000fd5b505060405162005c4c906200c1dc565b604051809103906000f08015801562005c69573d6000803e3d6000fd5b505060405162005c79906200c1dc565b604051809103906000f08015801562005c96573d6000803e3d6000fd5b505060405162005ca6906200c1dc565b604051809103906000f08015801562005cc3573d6000803e3d6000fd5b505060405162005cd3906200c1dc565b604051809103906000f08015801562005cf0573d6000803e3d6000fd5b505060405162005d00906200c1dc565b604051809103906000f08015801562005d1d573d6000803e3d6000fd5b505060405162005d2d906200c1dc565b604051809103906000f08015801562005d4a573d6000803e3d6000fd5b505060405162005d5a906200c1dc565b604051809103906000f08015801562005d77573d6000803e3d6000fd5b505060405162005d87906200c1dc565b604051809103906000f08015801562005da4573d6000803e3d6000fd5b505060405162005db4906200c1dc565b604051809103906000f08015801562005dd1573d6000803e3d6000fd5b505060405162005de1906200c1dc565b604051809103906000f08015801562005dfe573d6000803e3d6000fd5b505060405162005e0e906200c1dc565b604051809103906000f08015801562005e2b573d6000803e3d6000fd5b505060405162005e3b906200c1dc565b604051809103906000f08015801562005e58573d6000803e3d6000fd5b505060405162005e68906200c1dc565b604051809103906000f08015801562005e85573d6000803e3d6000fd5b505060405162005e95906200c1dc565b604051809103906000f08015801562005eb2573d6000803e3d6000fd5b505060405162005ec2906200c1dc565b604051809103906000f08015801562005edf573d6000803e3d6000fd5b505060405162005eef906200c1dc565b604051809103906000f08015801562005f0c573d6000803e3d6000fd5b505060405162005f1c906200c1dc565b604051809103906000f08015801562005f39573d6000803e3d6000fd5b505060405162005f49906200c1dc565b604051809103906000f08015801562005f66573d6000803e3d6000fd5b505060405162005f76906200c1dc565b604051809103906000f08015801562005f93573d6000803e3d6000fd5b505060405162005fa3906200c1dc565b604051809103906000f08015801562005fc0573d6000803e3d6000fd5b505060405162005fd0906200c1dc565b604051809103906000f08015801562005fed573d6000803e3d6000fd5b505060405162005ffd906200c1dc565b604051809103906000f0801580156200601a573d6000803e3d6000fd5b50506040516200602a906200c1dc565b604051809103906000f08015801562006047573d6000803e3d6000fd5b505060405162006057906200c1dc565b604051809103906000f08015801562006074573d6000803e3d6000fd5b505060405162006084906200c1dc565b604051809103906000f080158015620060a1573d6000803e3d6000fd5b5050604051620060b1906200c1dc565b604051809103906000f080158015620060ce573d6000803e3d6000fd5b5050604051620060de906200c1dc565b604051809103906000f080158015620060fb573d6000803e3d6000fd5b50506040516200610b906200c1dc565b604051809103906000f08015801562006128573d6000803e3d6000fd5b505060405162006138906200c1dc565b604051809103906000f08015801562006155573d6000803e3d6000fd5b505060405162006165906200c1dc565b604051809103906000f08015801562006182573d6000803e3d6000fd5b505060405162006192906200c1dc565b604051809103906000f080158015620061af573d6000803e3d6000fd5b5050604051620061bf906200c1dc565b604051809103906000f080158015620061dc573d6000803e3d6000fd5b5050604051620061ec906200c1dc565b604051809103906000f08015801562006209573d6000803e3d6000fd5b505060405162006219906200c1dc565b604051809103906000f08015801562006236573d6000803e3d6000fd5b505060405162006246906200c1dc565b604051809103906000f08015801562006263573d6000803e3d6000fd5b505060405162006273906200c1dc565b604051809103906000f08015801562006290573d6000803e3d6000fd5b5050604051620062a0906200c1dc565b604051809103906000f080158015620062bd573d6000803e3d6000fd5b5050604051620062cd906200c1dc565b604051809103906000f080158015620062ea573d6000803e3d6000fd5b5050604051620062fa906200c1dc565b604051809103906000f08015801562006317573d6000803e3d6000fd5b505060405162006327906200c1dc565b604051809103906000f08015801562006344573d6000803e3d6000fd5b505060405162006354906200c1dc565b604051809103906000f08015801562006371573d6000803e3d6000fd5b505060405162006381906200c1dc565b604051809103906000f0801580156200639e573d6000803e3d6000fd5b5050604051620063ae906200c1dc565b604051809103906000f080158015620063cb573d6000803e3d6000fd5b5050604051620063db906200c1dc565b604051809103906000f080158015620063f8573d6000803e3d6000fd5b505060405162006408906200c1dc565b604051809103906000f08015801562006425573d6000803e3d6000fd5b505060405162006435906200c1dc565b604051809103906000f08015801562006452573d6000803e3d6000fd5b505060405162006462906200c1dc565b604051809103906000f0801580156200647f573d6000803e3d6000fd5b50506040516200648f906200c1dc565b604051809103906000f080158015620064ac573d6000803e3d6000fd5b5050604051620064bc906200c1dc565b604051809103906000f080158015620064d9573d6000803e3d6000fd5b5050604051620064e9906200c1dc565b604051809103906000f08015801562006506573d6000803e3d6000fd5b505060405162006516906200c1dc565b604051809103906000f08015801562006533573d6000803e3d6000fd5b505060405162006543906200c1dc565b604051809103906000f08015801562006560573d6000803e3d6000fd5b505060405162006570906200c1dc565b604051809103906000f0801580156200658d573d6000803e3d6000fd5b50506040516200659d906200c1dc565b604051809103906000f080158015620065ba573d6000803e3d6000fd5b5050604051620065ca906200c1dc565b604051809103906000f080158015620065e7573d6000803e3d6000fd5b5050604051620065f7906200c1dc565b604051809103906000f08015801562006614573d6000803e3d6000fd5b505060405162006624906200c1dc565b604051809103906000f08015801562006641573d6000803e3d6000fd5b505060405162006651906200c1dc565b604051809103906000f0801580156200666e573d6000803e3d6000fd5b50506040516200667e906200c1dc565b604051809103906000f0801580156200669b573d6000803e3d6000fd5b5050604051620066ab906200c1dc565b604051809103906000f080158015620066c8573d6000803e3d6000fd5b5050604051620066d8906200c1dc565b604051809103906000f080158015620066f5573d6000803e3d6000fd5b505060405162006705906200c1dc565b604051809103906000f08015801562006722573d6000803e3d6000fd5b505060405162006732906200c1dc565b604051809103906000f0801580156200674f573d6000803e3d6000fd5b50506040516200675f906200c1dc565b604051809103906000f0801580156200677c573d6000803e3d6000fd5b50506040516200678c906200c1dc565b604051809103906000f080158015620067a9573d6000803e3d6000fd5b5050604051620067b9906200c1dc565b604051809103906000f080158015620067d6573d6000803e3d6000fd5b5050604051620067e6906200c1dc565b604051809103906000f08015801562006803573d6000803e3d6000fd5b505060405162006813906200c1dc565b604051809103906000f08015801562006830573d6000803e3d6000fd5b505060405162006840906200c1dc565b604051809103906000f0801580156200685d573d6000803e3d6000fd5b50506040516200686d906200c1dc565b604051809103906000f0801580156200688a573d6000803e3d6000fd5b50506040516200689a906200c1dc565b604051809103906000f080158015620068b7573d6000803e3d6000fd5b5050604051620068c7906200c1dc565b604051809103906000f080158015620068e4573d6000803e3d6000fd5b5050604051620068f4906200c1dc565b604051809103906000f08015801562006911573d6000803e3d6000fd5b505060405162006921906200c1dc565b604051809103906000f0801580156200693e573d6000803e3d6000fd5b50506040516200694e906200c1dc565b604051809103906000f0801580156200696b573d6000803e3d6000fd5b50506040516200697b906200c1dc565b604051809103906000f08015801562006998573d6000803e3d6000fd5b5050604051620069a8906200c1dc565b604051809103906000f080158015620069c5573d6000803e3d6000fd5b5050604051620069d5906200c1dc565b604051809103906000f080158015620069f2573d6000803e3d6000fd5b505060405162006a02906200c1dc565b604051809103906000f08015801562006a1f573d6000803e3d6000fd5b505060405162006a2f906200c1dc565b604051809103906000f08015801562006a4c573d6000803e3d6000fd5b505060405162006a5c906200c1dc565b604051809103906000f08015801562006a79573d6000803e3d6000fd5b505060405162006a89906200c1dc565b604051809103906000f08015801562006aa6573d6000803e3d6000fd5b505060405162006ab6906200c1dc565b604051809103906000f08015801562006ad3573d6000803e3d6000fd5b505060405162006ae3906200c1dc565b604051809103906000f08015801562006b00573d6000803e3d6000fd5b505060405162006b10906200c1dc565b604051809103906000f08015801562006b2d573d6000803e3d6000fd5b505060405162006b3d906200c1dc565b604051809103906000f08015801562006b5a573d6000803e3d6000fd5b505060405162006b6a906200c1dc565b604051809103906000f08015801562006b87573d6000803e3d6000fd5b505060405162006b97906200c1dc565b604051809103906000f08015801562006bb4573d6000803e3d6000fd5b505060405162006bc4906200c1dc565b604051809103906000f08015801562006be1573d6000803e3d6000fd5b505060405162006bf1906200c1dc565b604051809103906000f08015801562006c0e573d6000803e3d6000fd5b505060405162006c1e906200c1dc565b604051809103906000f08015801562006c3b573d6000803e3d6000fd5b505060405162006c4b906200c1dc565b604051809103906000f08015801562006c68573d6000803e3d6000fd5b505060405162006c78906200c1dc565b604051809103906000f08015801562006c95573d6000803e3d6000fd5b505060405162006ca5906200c1dc565b604051809103906000f08015801562006cc2573d6000803e3d6000fd5b505060405162006cd2906200c1dc565b604051809103906000f08015801562006cef573d6000803e3d6000fd5b505060405162006cff906200c1dc565b604051809103906000f08015801562006d1c573d6000803e3d6000fd5b505060405162006d2c906200c1dc565b604051809103906000f08015801562006d49573d6000803e3d6000fd5b505060405162006d59906200c1dc565b604051809103906000f08015801562006d76573d6000803e3d6000fd5b505060405162006d86906200c1dc565b604051809103906000f08015801562006da3573d6000803e3d6000fd5b505060405162006db3906200c1dc565b604051809103906000f08015801562006dd0573d6000803e3d6000fd5b505060405162006de0906200c1dc565b604051809103906000f08015801562006dfd573d6000803e3d6000fd5b505060405162006e0d906200c1dc565b604051809103906000f08015801562006e2a573d6000803e3d6000fd5b505060405162006e3a906200c1dc565b604051809103906000f08015801562006e57573d6000803e3d6000fd5b505060405162006e67906200c1dc565b604051809103906000f08015801562006e84573d6000803e3d6000fd5b505060405162006e94906200c1dc565b604051809103906000f08015801562006eb1573d6000803e3d6000fd5b505060405162006ec1906200c1dc565b604051809103906000f08015801562006ede573d6000803e3d6000fd5b505060405162006eee906200c1dc565b604051809103906000f08015801562006f0b573d6000803e3d6000fd5b505060405162006f1b906200c1dc565b604051809103906000f08015801562006f38573d6000803e3d6000fd5b505060405162006f48906200c1dc565b604051809103906000f08015801562006f65573d6000803e3d6000fd5b505060405162006f75906200c1dc565b604051809103906000f08015801562006f92573d6000803e3d6000fd5b505060405162006fa2906200c1dc565b604051809103906000f08015801562006fbf573d6000803e3d6000fd5b505060405162006fcf906200c1dc565b604051809103906000f08015801562006fec573d6000803e3d6000fd5b505060405162006ffc906200c1dc565b604051809103906000f08015801562007019573d6000803e3d6000fd5b505060405162007029906200c1dc565b604051809103906000f08015801562007046573d6000803e3d6000fd5b505060405162007056906200c1dc565b604051809103906000f08015801562007073573d6000803e3d6000fd5b505060405162007083906200c1dc565b604051809103906000f080158015620070a0573d6000803e3d6000fd5b5050604051620070b0906200c1dc565b604051809103906000f080158015620070cd573d6000803e3d6000fd5b5050604051620070dd906200c1dc565b604051809103906000f080158015620070fa573d6000803e3d6000fd5b50506040516200710a906200c1dc565b604051809103906000f08015801562007127573d6000803e3d6000fd5b505060405162007137906200c1dc565b604051809103906000f08015801562007154573d6000803e3d6000fd5b505060405162007164906200c1dc565b604051809103906000f08015801562007181573d6000803e3d6000fd5b505060405162007191906200c1dc565b604051809103906000f080158015620071ae573d6000803e3d6000fd5b5050604051620071be906200c1dc565b604051809103906000f080158015620071db573d6000803e3d6000fd5b5050604051620071eb906200c1dc565b604051809103906000f08015801562007208573d6000803e3d6000fd5b505060405162007218906200c1dc565b604051809103906000f08015801562007235573d6000803e3d6000fd5b505060405162007245906200c1dc565b604051809103906000f08015801562007262573d6000803e3d6000fd5b505060405162007272906200c1dc565b604051809103906000f0801580156200728f573d6000803e3d6000fd5b50506040516200729f906200c1dc565b604051809103906000f080158015620072bc573d6000803e3d6000fd5b5050604051620072cc906200c1dc565b604051809103906000f080158015620072e9573d6000803e3d6000fd5b5050604051620072f9906200c1dc565b604051809103906000f08015801562007316573d6000803e3d6000fd5b505060405162007326906200c1dc565b604051809103906000f08015801562007343573d6000803e3d6000fd5b505060405162007353906200c1dc565b604051809103906000f08015801562007370573d6000803e3d6000fd5b505060405162007380906200c1dc565b604051809103906000f0801580156200739d573d6000803e3d6000fd5b5050604051620073ad906200c1dc565b604051809103906000f080158015620073ca573d6000803e3d6000fd5b5050604051620073da906200c1dc565b604051809103906000f080158015620073f7573d6000803e3d6000fd5b505060405162007407906200c1dc565b604051809103906000f08015801562007424573d6000803e3d6000fd5b505060405162007434906200c1dc565b604051809103906000f08015801562007451573d6000803e3d6000fd5b505060405162007461906200c1dc565b604051809103906000f0801580156200747e573d6000803e3d6000fd5b50506040516200748e906200c1dc565b604051809103906000f080158015620074ab573d6000803e3d6000fd5b5050604051620074bb906200c1dc565b604051809103906000f080158015620074d8573d6000803e3d6000fd5b5050604051620074e8906200c1dc565b604051809103906000f08015801562007505573d6000803e3d6000fd5b505060405162007515906200c1dc565b604051809103906000f08015801562007532573d6000803e3d6000fd5b505060405162007542906200c1dc565b604051809103906000f0801580156200755f573d6000803e3d6000fd5b50506040516200756f906200c1dc565b604051809103906000f0801580156200758c573d6000803e3d6000fd5b50506040516200759c906200c1dc565b604051809103906000f080158015620075b9573d6000803e3d6000fd5b5050604051620075c9906200c1dc565b604051809103906000f080158015620075e6573d6000803e3d6000fd5b5050604051620075f6906200c1dc565b604051809103906000f08015801562007613573d6000803e3d6000fd5b505060405162007623906200c1dc565b604051809103906000f08015801562007640573d6000803e3d6000fd5b505060405162007650906200c1dc565b604051809103906000f0801580156200766d573d6000803e3d6000fd5b50506040516200767d906200c1dc565b604051809103906000f0801580156200769a573d6000803e3d6000fd5b5050604051620076aa906200c1dc565b604051809103906000f080158015620076c7573d6000803e3d6000fd5b5050604051620076d7906200c1dc565b604051809103906000f080158015620076f4573d6000803e3d6000fd5b505060405162007704906200c1dc565b604051809103906000f08015801562007721573d6000803e3d6000fd5b505060405162007731906200c1dc565b604051809103906000f0801580156200774e573d6000803e3d6000fd5b50506040516200775e906200c1dc565b604051809103906000f0801580156200777b573d6000803e3d6000fd5b50506040516200778b906200c1dc565b604051809103906000f080158015620077a8573d6000803e3d6000fd5b5050604051620077b8906200c1dc565b604051809103906000f080158015620077d5573d6000803e3d6000fd5b5050604051620077e5906200c1dc565b604051809103906000f08015801562007802573d6000803e3d6000fd5b505060405162007812906200c1dc565b604051809103906000f0801580156200782f573d6000803e3d6000fd5b50506040516200783f906200c1dc565b604051809103906000f0801580156200785c573d6000803e3d6000fd5b50506040516200786c906200c1dc565b604051809103906000f08015801562007889573d6000803e3d6000fd5b505060405162007899906200c1dc565b604051809103906000f080158015620078b6573d6000803e3d6000fd5b5050604051620078c6906200c1dc565b604051809103906000f080158015620078e3573d6000803e3d6000fd5b5050604051620078f3906200c1dc565b604051809103906000f08015801562007910573d6000803e3d6000fd5b505060405162007920906200c1dc565b604051809103906000f0801580156200793d573d6000803e3d6000fd5b50506040516200794d906200c1dc565b604051809103906000f0801580156200796a573d6000803e3d6000fd5b50506040516200797a906200c1dc565b604051809103906000f08015801562007997573d6000803e3d6000fd5b5050604051620079a7906200c1dc565b604051809103906000f080158015620079c4573d6000803e3d6000fd5b5050604051620079d4906200c1dc565b604051809103906000f080158015620079f1573d6000803e3d6000fd5b505060405162007a01906200c1dc565b604051809103906000f08015801562007a1e573d6000803e3d6000fd5b505060405162007a2e906200c1dc565b604051809103906000f08015801562007a4b573d6000803e3d6000fd5b505060405162007a5b906200c1dc565b604051809103906000f08015801562007a78573d6000803e3d6000fd5b505060405162007a88906200c1dc565b604051809103906000f08015801562007aa5573d6000803e3d6000fd5b505060405162007ab5906200c1dc565b604051809103906000f08015801562007ad2573d6000803e3d6000fd5b505060405162007ae2906200c1dc565b604051809103906000f08015801562007aff573d6000803e3d6000fd5b505060405162007b0f906200c1dc565b604051809103906000f08015801562007b2c573d6000803e3d6000fd5b505060405162007b3c906200c1dc565b604051809103906000f08015801562007b59573d6000803e3d6000fd5b505060405162007b69906200c1dc565b604051809103906000f08015801562007b86573d6000803e3d6000fd5b505060405162007b96906200c1dc565b604051809103906000f08015801562007bb3573d6000803e3d6000fd5b505060405162007bc3906200c1dc565b604051809103906000f08015801562007be0573d6000803e3d6000fd5b505060405162007bf0906200c1dc565b604051809103906000f08015801562007c0d573d6000803e3d6000fd5b505060405162007c1d906200c1dc565b604051809103906000f08015801562007c3a573d6000803e3d6000fd5b505060405162007c4a906200c1dc565b604051809103906000f08015801562007c67573d6000803e3d6000fd5b505060405162007c77906200c1dc565b604051809103906000f08015801562007c94573d6000803e3d6000fd5b505060405162007ca4906200c1dc565b604051809103906000f08015801562007cc1573d6000803e3d6000fd5b505060405162007cd1906200c1dc565b604051809103906000f08015801562007cee573d6000803e3d6000fd5b505060405162007cfe906200c1dc565b604051809103906000f08015801562007d1b573d6000803e3d6000fd5b505060405162007d2b906200c1dc565b604051809103906000f08015801562007d48573d6000803e3d6000fd5b505060405162007d58906200c1dc565b604051809103906000f08015801562007d75573d6000803e3d6000fd5b505060405162007d85906200c1dc565b604051809103906000f08015801562007da2573d6000803e3d6000fd5b505060405162007db2906200c1dc565b604051809103906000f08015801562007dcf573d6000803e3d6000fd5b505060405162007ddf906200c1dc565b604051809103906000f08015801562007dfc573d6000803e3d6000fd5b505060405162007e0c906200c1dc565b604051809103906000f08015801562007e29573d6000803e3d6000fd5b505060405162007e39906200c1dc565b604051809103906000f08015801562007e56573d6000803e3d6000fd5b505060405162007e66906200c1dc565b604051809103906000f08015801562007e83573d6000803e3d6000fd5b505060405162007e93906200c1dc565b604051809103906000f08015801562007eb0573d6000803e3d6000fd5b505060405162007ec0906200c1dc565b604051809103906000f08015801562007edd573d6000803e3d6000fd5b505060405162007eed906200c1dc565b604051809103906000f08015801562007f0a573d6000803e3d6000fd5b505060405162007f1a906200c1dc565b604051809103906000f08015801562007f37573d6000803e3d6000fd5b505060405162007f47906200c1dc565b604051809103906000f08015801562007f64573d6000803e3d6000fd5b505060405162007f74906200c1dc565b604051809103906000f08015801562007f91573d6000803e3d6000fd5b505060405162007fa1906200c1dc565b604051809103906000f08015801562007fbe573d6000803e3d6000fd5b505060405162007fce906200c1dc565b604051809103906000f08015801562007feb573d6000803e3d6000fd5b505060405162007ffb906200c1dc565b604051809103906000f08015801562008018573d6000803e3d6000fd5b505060405162008028906200c1dc565b604051809103906000f08015801562008045573d6000803e3d6000fd5b505060405162008055906200c1dc565b604051809103906000f08015801562008072573d6000803e3d6000fd5b505060405162008082906200c1dc565b604051809103906000f0801580156200809f573d6000803e3d6000fd5b5050604051620080af906200c1dc565b604051809103906000f080158015620080cc573d6000803e3d6000fd5b5050604051620080dc906200c1dc565b604051809103906000f080158015620080f9573d6000803e3d6000fd5b505060405162008109906200c1dc565b604051809103906000f08015801562008126573d6000803e3d6000fd5b505060405162008136906200c1dc565b604051809103906000f08015801562008153573d6000803e3d6000fd5b505060405162008163906200c1dc565b604051809103906000f08015801562008180573d6000803e3d6000fd5b505060405162008190906200c1dc565b604051809103906000f080158015620081ad573d6000803e3d6000fd5b5050604051620081bd906200c1dc565b604051809103906000f080158015620081da573d6000803e3d6000fd5b5050604051620081ea906200c1dc565b604051809103906000f08015801562008207573d6000803e3d6000fd5b505060405162008217906200c1dc565b604051809103906000f08015801562008234573d6000803e3d6000fd5b505060405162008244906200c1dc565b604051809103906000f08015801562008261573d6000803e3d6000fd5b505060405162008271906200c1dc565b604051809103906000f0801580156200828e573d6000803e3d6000fd5b50506040516200829e906200c1dc565b604051809103906000f080158015620082bb573d6000803e3d6000fd5b5050604051620082cb906200c1dc565b604051809103906000f080158015620082e8573d6000803e3d6000fd5b5050604051620082f8906200c1dc565b604051809103906000f08015801562008315573d6000803e3d6000fd5b505060405162008325906200c1dc565b604051809103906000f08015801562008342573d6000803e3d6000fd5b505060405162008352906200c1dc565b604051809103906000f0801580156200836f573d6000803e3d6000fd5b50506040516200837f906200c1dc565b604051809103906000f0801580156200839c573d6000803e3d6000fd5b5050604051620083ac906200c1dc565b604051809103906000f080158015620083c9573d6000803e3d6000fd5b5050604051620083d9906200c1dc565b604051809103906000f080158015620083f6573d6000803e3d6000fd5b505060405162008406906200c1dc565b604051809103906000f08015801562008423573d6000803e3d6000fd5b505060405162008433906200c1dc565b604051809103906000f08015801562008450573d6000803e3d6000fd5b505060405162008460906200c1dc565b604051809103906000f0801580156200847d573d6000803e3d6000fd5b50506040516200848d906200c1dc565b604051809103906000f080158015620084aa573d6000803e3d6000fd5b5050604051620084ba906200c1dc565b604051809103906000f080158015620084d7573d6000803e3d6000fd5b5050604051620084e7906200c1dc565b604051809103906000f08015801562008504573d6000803e3d6000fd5b505060405162008514906200c1dc565b604051809103906000f08015801562008531573d6000803e3d6000fd5b505060405162008541906200c1dc565b604051809103906000f0801580156200855e573d6000803e3d6000fd5b50506040516200856e906200c1dc565b604051809103906000f0801580156200858b573d6000803e3d6000fd5b50506040516200859b906200c1dc565b604051809103906000f080158015620085b8573d6000803e3d6000fd5b5050604051620085c8906200c1dc565b604051809103906000f080158015620085e5573d6000803e3d6000fd5b5050604051620085f5906200c1dc565b604051809103906000f08015801562008612573d6000803e3d6000fd5b505060405162008622906200c1dc565b604051809103906000f0801580156200863f573d6000803e3d6000fd5b50506040516200864f906200c1dc565b604051809103906000f0801580156200866c573d6000803e3d6000fd5b50506040516200867c906200c1dc565b604051809103906000f08015801562008699573d6000803e3d6000fd5b5050604051620086a9906200c1dc565b604051809103906000f080158015620086c6573d6000803e3d6000fd5b5050604051620086d6906200c1dc565b604051809103906000f080158015620086f3573d6000803e3d6000fd5b505060405162008703906200c1dc565b604051809103906000f08015801562008720573d6000803e3d6000fd5b505060405162008730906200c1dc565b604051809103906000f0801580156200874d573d6000803e3d6000fd5b50506040516200875d906200c1dc565b604051809103906000f0801580156200877a573d6000803e3d6000fd5b50506040516200878a906200c1dc565b604051809103906000f080158015620087a7573d6000803e3d6000fd5b5050604051620087b7906200c1dc565b604051809103906000f080158015620087d4573d6000803e3d6000fd5b5050604051620087e4906200c1dc565b604051809103906000f08015801562008801573d6000803e3d6000fd5b505060405162008811906200c1dc565b604051809103906000f0801580156200882e573d6000803e3d6000fd5b50506040516200883e906200c1dc565b604051809103906000f0801580156200885b573d6000803e3d6000fd5b50506040516200886b906200c1dc565b604051809103906000f08015801562008888573d6000803e3d6000fd5b505060405162008898906200c1dc565b604051809103906000f080158015620088b5573d6000803e3d6000fd5b5050604051620088c5906200c1dc565b604051809103906000f080158015620088e2573d6000803e3d6000fd5b5050604051620088f2906200c1dc565b604051809103906000f0801580156200890f573d6000803e3d6000fd5b50506040516200891f906200c1dc565b604051809103906000f0801580156200893c573d6000803e3d6000fd5b50506040516200894c906200c1dc565b604051809103906000f08015801562008969573d6000803e3d6000fd5b505060405162008979906200c1dc565b604051809103906000f08015801562008996573d6000803e3d6000fd5b5050604051620089a6906200c1dc565b604051809103906000f080158015620089c3573d6000803e3d6000fd5b5050604051620089d3906200c1dc565b604051809103906000f080158015620089f0573d6000803e3d6000fd5b505060405162008a00906200c1dc565b604051809103906000f08015801562008a1d573d6000803e3d6000fd5b505060405162008a2d906200c1dc565b604051809103906000f08015801562008a4a573d6000803e3d6000fd5b505060405162008a5a906200c1dc565b604051809103906000f08015801562008a77573d6000803e3d6000fd5b505060405162008a87906200c1dc565b604051809103906000f08015801562008aa4573d6000803e3d6000fd5b505060405162008ab4906200c1dc565b604051809103906000f08015801562008ad1573d6000803e3d6000fd5b505060405162008ae1906200c1dc565b604051809103906000f08015801562008afe573d6000803e3d6000fd5b505060405162008b0e906200c1dc565b604051809103906000f08015801562008b2b573d6000803e3d6000fd5b505060405162008b3b906200c1dc565b604051809103906000f08015801562008b58573d6000803e3d6000fd5b505060405162008b68906200c1dc565b604051809103906000f08015801562008b85573d6000803e3d6000fd5b505060405162008b95906200c1dc565b604051809103906000f08015801562008bb2573d6000803e3d6000fd5b505060405162008bc2906200c1dc565b604051809103906000f08015801562008bdf573d6000803e3d6000fd5b505060405162008bef906200c1dc565b604051809103906000f08015801562008c0c573d6000803e3d6000fd5b505060405162008c1c906200c1dc565b604051809103906000f08015801562008c39573d6000803e3d6000fd5b505060405162008c49906200c1dc565b604051809103906000f08015801562008c66573d6000803e3d6000fd5b505060405162008c76906200c1dc565b604051809103906000f08015801562008c93573d6000803e3d6000fd5b505060405162008ca3906200c1dc565b604051809103906000f08015801562008cc0573d6000803e3d6000fd5b505060405162008cd0906200c1dc565b604051809103906000f08015801562008ced573d6000803e3d6000fd5b505060405162008cfd906200c1dc565b604051809103906000f08015801562008d1a573d6000803e3d6000fd5b505060405162008d2a906200c1dc565b604051809103906000f08015801562008d47573d6000803e3d6000fd5b505060405162008d57906200c1dc565b604051809103906000f08015801562008d74573d6000803e3d6000fd5b505060405162008d84906200c1dc565b604051809103906000f08015801562008da1573d6000803e3d6000fd5b505060405162008db1906200c1dc565b604051809103906000f08015801562008dce573d6000803e3d6000fd5b505060405162008dde906200c1dc565b604051809103906000f08015801562008dfb573d6000803e3d6000fd5b505060405162008e0b906200c1dc565b604051809103906000f08015801562008e28573d6000803e3d6000fd5b505060405162008e38906200c1dc565b604051809103906000f08015801562008e55573d6000803e3d6000fd5b505060405162008e65906200c1dc565b604051809103906000f08015801562008e82573d6000803e3d6000fd5b505060405162008e92906200c1dc565b604051809103906000f08015801562008eaf573d6000803e3d6000fd5b505060405162008ebf906200c1dc565b604051809103906000f08015801562008edc573d6000803e3d6000fd5b505060405162008eec906200c1dc565b604051809103906000f08015801562008f09573d6000803e3d6000fd5b505060405162008f19906200c1dc565b604051809103906000f08015801562008f36573d6000803e3d6000fd5b505060405162008f46906200c1dc565b604051809103906000f08015801562008f63573d6000803e3d6000fd5b505060405162008f73906200c1dc565b604051809103906000f08015801562008f90573d6000803e3d6000fd5b505060405162008fa0906200c1dc565b604051809103906000f08015801562008fbd573d6000803e3d6000fd5b505060405162008fcd906200c1dc565b604051809103906000f08015801562008fea573d6000803e3d6000fd5b505060405162008ffa906200c1dc565b604051809103906000f08015801562009017573d6000803e3d6000fd5b505060405162009027906200c1dc565b604051809103906000f08015801562009044573d6000803e3d6000fd5b505060405162009054906200c1dc565b604051809103906000f08015801562009071573d6000803e3d6000fd5b505060405162009081906200c1dc565b604051809103906000f0801580156200909e573d6000803e3d6000fd5b5050604051620090ae906200c1dc565b604051809103906000f080158015620090cb573d6000803e3d6000fd5b5050604051620090db906200c1dc565b604051809103906000f080158015620090f8573d6000803e3d6000fd5b505060405162009108906200c1dc565b604051809103906000f08015801562009125573d6000803e3d6000fd5b505060405162009135906200c1dc565b604051809103906000f08015801562009152573d6000803e3d6000fd5b505060405162009162906200c1dc565b604051809103906000f0801580156200917f573d6000803e3d6000fd5b50506040516200918f906200c1dc565b604051809103906000f080158015620091ac573d6000803e3d6000fd5b5050604051620091bc906200c1dc565b604051809103906000f080158015620091d9573d6000803e3d6000fd5b5050604051620091e9906200c1dc565b604051809103906000f08015801562009206573d6000803e3d6000fd5b505060405162009216906200c1dc565b604051809103906000f08015801562009233573d6000803e3d6000fd5b505060405162009243906200c1dc565b604051809103906000f08015801562009260573d6000803e3d6000fd5b505060405162009270906200c1dc565b604051809103906000f0801580156200928d573d6000803e3d6000fd5b50506040516200929d906200c1dc565b604051809103906000f080158015620092ba573d6000803e3d6000fd5b5050604051620092ca906200c1dc565b604051809103906000f080158015620092e7573d6000803e3d6000fd5b5050604051620092f7906200c1dc565b604051809103906000f08015801562009314573d6000803e3d6000fd5b505060405162009324906200c1dc565b604051809103906000f08015801562009341573d6000803e3d6000fd5b505060405162009351906200c1dc565b604051809103906000f0801580156200936e573d6000803e3d6000fd5b50506040516200937e906200c1dc565b604051809103906000f0801580156200939b573d6000803e3d6000fd5b5050604051620093ab906200c1dc565b604051809103906000f080158015620093c8573d6000803e3d6000fd5b5050604051620093d8906200c1dc565b604051809103906000f080158015620093f5573d6000803e3d6000fd5b505060405162009405906200c1dc565b604051809103906000f08015801562009422573d6000803e3d6000fd5b505060405162009432906200c1dc565b604051809103906000f0801580156200944f573d6000803e3d6000fd5b50506040516200945f906200c1dc565b604051809103906000f0801580156200947c573d6000803e3d6000fd5b50506040516200948c906200c1dc565b604051809103906000f080158015620094a9573d6000803e3d6000fd5b5050604051620094b9906200c1dc565b604051809103906000f080158015620094d6573d6000803e3d6000fd5b5050604051620094e6906200c1dc565b604051809103906000f08015801562009503573d6000803e3d6000fd5b505060405162009513906200c1dc565b604051809103906000f08015801562009530573d6000803e3d6000fd5b505060405162009540906200c1dc565b604051809103906000f0801580156200955d573d6000803e3d6000fd5b50506040516200956d906200c1dc565b604051809103906000f0801580156200958a573d6000803e3d6000fd5b50506040516200959a906200c1dc565b604051809103906000f080158015620095b7573d6000803e3d6000fd5b5050604051620095c7906200c1dc565b604051809103906000f080158015620095e4573d6000803e3d6000fd5b5050604051620095f4906200c1dc565b604051809103906000f08015801562009611573d6000803e3d6000fd5b505060405162009621906200c1dc565b604051809103906000f0801580156200963e573d6000803e3d6000fd5b50506040516200964e906200c1dc565b604051809103906000f0801580156200966b573d6000803e3d6000fd5b50506040516200967b906200c1dc565b604051809103906000f08015801562009698573d6000803e3d6000fd5b5050604051620096a8906200c1dc565b604051809103906000f080158015620096c5573d6000803e3d6000fd5b5050604051620096d5906200c1dc565b604051809103906000f080158015620096f2573d6000803e3d6000fd5b505060405162009702906200c1dc565b604051809103906000f0801580156200971f573d6000803e3d6000fd5b50506040516200972f906200c1dc565b604051809103906000f0801580156200974c573d6000803e3d6000fd5b50506040516200975c906200c1dc565b604051809103906000f08015801562009779573d6000803e3d6000fd5b505060405162009789906200c1dc565b604051809103906000f080158015620097a6573d6000803e3d6000fd5b5050604051620097b6906200c1dc565b604051809103906000f080158015620097d3573d6000803e3d6000fd5b5050604051620097e3906200c1dc565b604051809103906000f08015801562009800573d6000803e3d6000fd5b505060405162009810906200c1dc565b604051809103906000f0801580156200982d573d6000803e3d6000fd5b50506040516200983d906200c1dc565b604051809103906000f0801580156200985a573d6000803e3d6000fd5b50506040516200986a906200c1dc565b604051809103906000f08015801562009887573d6000803e3d6000fd5b505060405162009897906200c1dc565b604051809103906000f080158015620098b4573d6000803e3d6000fd5b5050604051620098c4906200c1dc565b604051809103906000f080158015620098e1573d6000803e3d6000fd5b5050604051620098f1906200c1dc565b604051809103906000f0801580156200990e573d6000803e3d6000fd5b50506040516200991e906200c1dc565b604051809103906000f0801580156200993b573d6000803e3d6000fd5b50506040516200994b906200c1dc565b604051809103906000f08015801562009968573d6000803e3d6000fd5b505060405162009978906200c1dc565b604051809103906000f08015801562009995573d6000803e3d6000fd5b5050604051620099a5906200c1dc565b604051809103906000f080158015620099c2573d6000803e3d6000fd5b5050604051620099d2906200c1dc565b604051809103906000f080158015620099ef573d6000803e3d6000fd5b5050604051620099ff906200c1dc565b604051809103906000f08015801562009a1c573d6000803e3d6000fd5b505060405162009a2c906200c1dc565b604051809103906000f08015801562009a49573d6000803e3d6000fd5b505060405162009a59906200c1dc565b604051809103906000f08015801562009a76573d6000803e3d6000fd5b505060405162009a86906200c1dc565b604051809103906000f08015801562009aa3573d6000803e3d6000fd5b505060405162009ab3906200c1dc565b604051809103906000f08015801562009ad0573d6000803e3d6000fd5b505060405162009ae0906200c1dc565b604051809103906000f08015801562009afd573d6000803e3d6000fd5b505060405162009b0d906200c1dc565b604051809103906000f08015801562009b2a573d6000803e3d6000fd5b505060405162009b3a906200c1dc565b604051809103906000f08015801562009b57573d6000803e3d6000fd5b505060405162009b67906200c1dc565b604051809103906000f08015801562009b84573d6000803e3d6000fd5b505060405162009b94906200c1dc565b604051809103906000f08015801562009bb1573d6000803e3d6000fd5b505060405162009bc1906200c1dc565b604051809103906000f08015801562009bde573d6000803e3d6000fd5b505060405162009bee906200c1dc565b604051809103906000f08015801562009c0b573d6000803e3d6000fd5b505060405162009c1b906200c1dc565b604051809103906000f08015801562009c38573d6000803e3d6000fd5b505060405162009c48906200c1dc565b604051809103906000f08015801562009c65573d6000803e3d6000fd5b505060405162009c75906200c1dc565b604051809103906000f08015801562009c92573d6000803e3d6000fd5b505060405162009ca2906200c1dc565b604051809103906000f08015801562009cbf573d6000803e3d6000fd5b505060405162009ccf906200c1dc565b604051809103906000f08015801562009cec573d6000803e3d6000fd5b505060405162009cfc906200c1dc565b604051809103906000f08015801562009d19573d6000803e3d6000fd5b505060405162009d29906200c1dc565b604051809103906000f08015801562009d46573d6000803e3d6000fd5b505060405162009d56906200c1dc565b604051809103906000f08015801562009d73573d6000803e3d6000fd5b505060405162009d83906200c1dc565b604051809103906000f08015801562009da0573d6000803e3d6000fd5b505060405162009db0906200c1dc565b604051809103906000f08015801562009dcd573d6000803e3d6000fd5b505060405162009ddd906200c1dc565b604051809103906000f08015801562009dfa573d6000803e3d6000fd5b505060405162009e0a906200c1dc565b604051809103906000f08015801562009e27573d6000803e3d6000fd5b505060405162009e37906200c1dc565b604051809103906000f08015801562009e54573d6000803e3d6000fd5b505060405162009e64906200c1dc565b604051809103906000f08015801562009e81573d6000803e3d6000fd5b505060405162009e91906200c1dc565b604051809103906000f08015801562009eae573d6000803e3d6000fd5b505060405162009ebe906200c1dc565b604051809103906000f08015801562009edb573d6000803e3d6000fd5b505060405162009eeb906200c1dc565b604051809103906000f08015801562009f08573d6000803e3d6000fd5b505060405162009f18906200c1dc565b604051809103906000f08015801562009f35573d6000803e3d6000fd5b505060405162009f45906200c1dc565b604051809103906000f08015801562009f62573d6000803e3d6000fd5b505060405162009f72906200c1dc565b604051809103906000f08015801562009f8f573d6000803e3d6000fd5b505060405162009f9f906200c1dc565b604051809103906000f08015801562009fbc573d6000803e3d6000fd5b505060405162009fcc906200c1dc565b604051809103906000f08015801562009fe9573d6000803e3d6000fd5b505060405162009ff9906200c1dc565b604051809103906000f0801580156200a016573d6000803e3d6000fd5b50506040516200a026906200c1dc565b604051809103906000f0801580156200a043573d6000803e3d6000fd5b50506040516200a053906200c1dc565b604051809103906000f0801580156200a070573d6000803e3d6000fd5b50506040516200a080906200c1dc565b604051809103906000f0801580156200a09d573d6000803e3d6000fd5b50506040516200a0ad906200c1dc565b604051809103906000f0801580156200a0ca573d6000803e3d6000fd5b50506040516200a0da906200c1dc565b604051809103906000f0801580156200a0f7573d6000803e3d6000fd5b50506040516200a107906200c1dc565b604051809103906000f0801580156200a124573d6000803e3d6000fd5b50506040516200a134906200c1dc565b604051809103906000f0801580156200a151573d6000803e3d6000fd5b50506040516200a161906200c1dc565b604051809103906000f0801580156200a17e573d6000803e3d6000fd5b50506040516200a18e906200c1dc565b604051809103906000f0801580156200a1ab573d6000803e3d6000fd5b50506040516200a1bb906200c1dc565b604051809103906000f0801580156200a1d8573d6000803e3d6000fd5b50506040516200a1e8906200c1dc565b604051809103906000f0801580156200a205573d6000803e3d6000fd5b50506040516200a215906200c1dc565b604051809103906000f0801580156200a232573d6000803e3d6000fd5b50506040516200a242906200c1dc565b604051809103906000f0801580156200a25f573d6000803e3d6000fd5b50506040516200a26f906200c1dc565b604051809103906000f0801580156200a28c573d6000803e3d6000fd5b50506040516200a29c906200c1dc565b604051809103906000f0801580156200a2b9573d6000803e3d6000fd5b50506040516200a2c9906200c1dc565b604051809103906000f0801580156200a2e6573d6000803e3d6000fd5b50506040516200a2f6906200c1dc565b604051809103906000f0801580156200a313573d6000803e3d6000fd5b50506040516200a323906200c1dc565b604051809103906000f0801580156200a340573d6000803e3d6000fd5b50506040516200a350906200c1dc565b604051809103906000f0801580156200a36d573d6000803e3d6000fd5b50506040516200a37d906200c1dc565b604051809103906000f0801580156200a39a573d6000803e3d6000fd5b50506040516200a3aa906200c1dc565b604051809103906000f0801580156200a3c7573d6000803e3d6000fd5b50506040516200a3d7906200c1dc565b604051809103906000f0801580156200a3f4573d6000803e3d6000fd5b50506040516200a404906200c1dc565b604051809103906000f0801580156200a421573d6000803e3d6000fd5b50506040516200a431906200c1dc565b604051809103906000f0801580156200a44e573d6000803e3d6000fd5b50506040516200a45e906200c1dc565b604051809103906000f0801580156200a47b573d6000803e3d6000fd5b50506040516200a48b906200c1dc565b604051809103906000f0801580156200a4a8573d6000803e3d6000fd5b50506040516200a4b8906200c1dc565b604051809103906000f0801580156200a4d5573d6000803e3d6000fd5b50506040516200a4e5906200c1dc565b604051809103906000f0801580156200a502573d6000803e3d6000fd5b50506040516200a512906200c1dc565b604051809103906000f0801580156200a52f573d6000803e3d6000fd5b50506040516200a53f906200c1dc565b604051809103906000f0801580156200a55c573d6000803e3d6000fd5b50506040516200a56c906200c1dc565b604051809103906000f0801580156200a589573d6000803e3d6000fd5b50506040516200a599906200c1dc565b604051809103906000f0801580156200a5b6573d6000803e3d6000fd5b50506040516200a5c6906200c1dc565b604051809103906000f0801580156200a5e3573d6000803e3d6000fd5b50506040516200a5f3906200c1dc565b604051809103906000f0801580156200a610573d6000803e3d6000fd5b50506040516200a620906200c1dc565b604051809103906000f0801580156200a63d573d6000803e3d6000fd5b50506040516200a64d906200c1dc565b604051809103906000f0801580156200a66a573d6000803e3d6000fd5b50506040516200a67a906200c1dc565b604051809103906000f0801580156200a697573d6000803e3d6000fd5b50506040516200a6a7906200c1dc565b604051809103906000f0801580156200a6c4573d6000803e3d6000fd5b50506040516200a6d4906200c1dc565b604051809103906000f0801580156200a6f1573d6000803e3d6000fd5b50506040516200a701906200c1dc565b604051809103906000f0801580156200a71e573d6000803e3d6000fd5b50506040516200a72e906200c1dc565b604051809103906000f0801580156200a74b573d6000803e3d6000fd5b50506040516200a75b906200c1dc565b604051809103906000f0801580156200a778573d6000803e3d6000fd5b50506040516200a788906200c1dc565b604051809103906000f0801580156200a7a5573d6000803e3d6000fd5b50506040516200a7b5906200c1dc565b604051809103906000f0801580156200a7d2573d6000803e3d6000fd5b50506040516200a7e2906200c1dc565b604051809103906000f0801580156200a7ff573d6000803e3d6000fd5b50506040516200a80f906200c1dc565b604051809103906000f0801580156200a82c573d6000803e3d6000fd5b50506040516200a83c906200c1dc565b604051809103906000f0801580156200a859573d6000803e3d6000fd5b50506040516200a869906200c1dc565b604051809103906000f0801580156200a886573d6000803e3d6000fd5b50506040516200a896906200c1dc565b604051809103906000f0801580156200a8b3573d6000803e3d6000fd5b50506040516200a8c3906200c1dc565b604051809103906000f0801580156200a8e0573d6000803e3d6000fd5b50506040516200a8f0906200c1dc565b604051809103906000f0801580156200a90d573d6000803e3d6000fd5b50506040516200a91d906200c1dc565b604051809103906000f0801580156200a93a573d6000803e3d6000fd5b50506040516200a94a906200c1dc565b604051809103906000f0801580156200a967573d6000803e3d6000fd5b50506040516200a977906200c1dc565b604051809103906000f0801580156200a994573d6000803e3d6000fd5b50506040516200a9a4906200c1dc565b604051809103906000f0801580156200a9c1573d6000803e3d6000fd5b50506040516200a9d1906200c1dc565b604051809103906000f0801580156200a9ee573d6000803e3d6000fd5b50506040516200a9fe906200c1dc565b604051809103906000f0801580156200aa1b573d6000803e3d6000fd5b50506040516200aa2b906200c1dc565b604051809103906000f0801580156200aa48573d6000803e3d6000fd5b50506040516200aa58906200c1dc565b604051809103906000f0801580156200aa75573d6000803e3d6000fd5b50506040516200aa85906200c1dc565b604051809103906000f0801580156200aaa2573d6000803e3d6000fd5b50506040516200aab2906200c1dc565b604051809103906000f0801580156200aacf573d6000803e3d6000fd5b50506040516200aadf906200c1dc565b604051809103906000f0801580156200aafc573d6000803e3d6000fd5b50506040516200ab0c906200c1dc565b604051809103906000f0801580156200ab29573d6000803e3d6000fd5b50506040516200ab39906200c1dc565b604051809103906000f0801580156200ab56573d6000803e3d6000fd5b50506040516200ab66906200c1dc565b604051809103906000f0801580156200ab83573d6000803e3d6000fd5b50506040516200ab93906200c1dc565b604051809103906000f0801580156200abb0573d6000803e3d6000fd5b50506040516200abc0906200c1dc565b604051809103906000f0801580156200abdd573d6000803e3d6000fd5b50506040516200abed906200c1dc565b604051809103906000f0801580156200ac0a573d6000803e3d6000fd5b50506040516200ac1a906200c1dc565b604051809103906000f0801580156200ac37573d6000803e3d6000fd5b50506040516200ac47906200c1dc565b604051809103906000f0801580156200ac64573d6000803e3d6000fd5b50506040516200ac74906200c1dc565b604051809103906000f0801580156200ac91573d6000803e3d6000fd5b50506040516200aca1906200c1dc565b604051809103906000f0801580156200acbe573d6000803e3d6000fd5b50506040516200acce906200c1dc565b604051809103906000f0801580156200aceb573d6000803e3d6000fd5b50506040516200acfb906200c1dc565b604051809103906000f0801580156200ad18573d6000803e3d6000fd5b50506040516200ad28906200c1dc565b604051809103906000f0801580156200ad45573d6000803e3d6000fd5b50506040516200ad55906200c1dc565b604051809103906000f0801580156200ad72573d6000803e3d6000fd5b50506040516200ad82906200c1dc565b604051809103906000f0801580156200ad9f573d6000803e3d6000fd5b50506040516200adaf906200c1dc565b604051809103906000f0801580156200adcc573d6000803e3d6000fd5b50506040516200addc906200c1dc565b604051809103906000f0801580156200adf9573d6000803e3d6000fd5b50506040516200ae09906200c1dc565b604051809103906000f0801580156200ae26573d6000803e3d6000fd5b50506040516200ae36906200c1dc565b604051809103906000f0801580156200ae53573d6000803e3d6000fd5b50506040516200ae63906200c1dc565b604051809103906000f0801580156200ae80573d6000803e3d6000fd5b50506040516200ae90906200c1dc565b604051809103906000f0801580156200aead573d6000803e3d6000fd5b50506040516200aebd906200c1dc565b604051809103906000f0801580156200aeda573d6000803e3d6000fd5b50506040516200aeea906200c1dc565b604051809103906000f0801580156200af07573d6000803e3d6000fd5b50506040516200af17906200c1dc565b604051809103906000f0801580156200af34573d6000803e3d6000fd5b50506040516200af44906200c1dc565b604051809103906000f0801580156200af61573d6000803e3d6000fd5b50506040516200af71906200c1dc565b604051809103906000f0801580156200af8e573d6000803e3d6000fd5b50506040516200af9e906200c1dc565b604051809103906000f0801580156200afbb573d6000803e3d6000fd5b50506040516200afcb906200c1dc565b604051809103906000f0801580156200afe8573d6000803e3d6000fd5b50506040516200aff8906200c1dc565b604051809103906000f0801580156200b015573d6000803e3d6000fd5b50506040516200b025906200c1dc565b604051809103906000f0801580156200b042573d6000803e3d6000fd5b50506040516200b052906200c1dc565b604051809103906000f0801580156200b06f573d6000803e3d6000fd5b50506040516200b07f906200c1dc565b604051809103906000f0801580156200b09c573d6000803e3d6000fd5b50506040516200b0ac906200c1dc565b604051809103906000f0801580156200b0c9573d6000803e3d6000fd5b50506040516200b0d9906200c1dc565b604051809103906000f0801580156200b0f6573d6000803e3d6000fd5b50506040516200b106906200c1dc565b604051809103906000f0801580156200b123573d6000803e3d6000fd5b50506040516200b133906200c1dc565b604051809103906000f0801580156200b150573d6000803e3d6000fd5b50506040516200b160906200c1dc565b604051809103906000f0801580156200b17d573d6000803e3d6000fd5b50506040516200b18d906200c1dc565b604051809103906000f0801580156200b1aa573d6000803e3d6000fd5b50506040516200b1ba906200c1dc565b604051809103906000f0801580156200b1d7573d6000803e3d6000fd5b50506040516200b1e7906200c1dc565b604051809103906000f0801580156200b204573d6000803e3d6000fd5b50506040516200b214906200c1dc565b604051809103906000f0801580156200b231573d6000803e3d6000fd5b50506040516200b241906200c1dc565b604051809103906000f0801580156200b25e573d6000803e3d6000fd5b50506040516200b26e906200c1dc565b604051809103906000f0801580156200b28b573d6000803e3d6000fd5b50506040516200b29b906200c1dc565b604051809103906000f0801580156200b2b8573d6000803e3d6000fd5b50506040516200b2c8906200c1dc565b604051809103906000f0801580156200b2e5573d6000803e3d6000fd5b50506040516200b2f5906200c1dc565b604051809103906000f0801580156200b312573d6000803e3d6000fd5b50506040516200b322906200c1dc565b604051809103906000f0801580156200b33f573d6000803e3d6000fd5b50506040516200b34f906200c1dc565b604051809103906000f0801580156200b36c573d6000803e3d6000fd5b50506040516200b37c906200c1dc565b604051809103906000f0801580156200b399573d6000803e3d6000fd5b50506040516200b3a9906200c1dc565b604051809103906000f0801580156200b3c6573d6000803e3d6000fd5b50506040516200b3d6906200c1dc565b604051809103906000f0801580156200b3f3573d6000803e3d6000fd5b50506040516200b403906200c1dc565b604051809103906000f0801580156200b420573d6000803e3d6000fd5b50506040516200b430906200c1dc565b604051809103906000f0801580156200b44d573d6000803e3d6000fd5b50506040516200b45d906200c1dc565b604051809103906000f0801580156200b47a573d6000803e3d6000fd5b50506040516200b48a906200c1dc565b604051809103906000f0801580156200b4a7573d6000803e3d6000fd5b50506040516200b4b7906200c1dc565b604051809103906000f0801580156200b4d4573d6000803e3d6000fd5b50506040516200b4e4906200c1dc565b604051809103906000f0801580156200b501573d6000803e3d6000fd5b50506040516200b511906200c1dc565b604051809103906000f0801580156200b52e573d6000803e3d6000fd5b50506040516200b53e906200c1dc565b604051809103906000f0801580156200b55b573d6000803e3d6000fd5b50506040516200b56b906200c1dc565b604051809103906000f0801580156200b588573d6000803e3d6000fd5b50506040516200b598906200c1dc565b604051809103906000f0801580156200b5b5573d6000803e3d6000fd5b50506040516200b5c5906200c1dc565b604051809103906000f0801580156200b5e2573d6000803e3d6000fd5b50506040516200b5f2906200c1dc565b604051809103906000f0801580156200b60f573d6000803e3d6000fd5b50506040516200b61f906200c1dc565b604051809103906000f0801580156200b63c573d6000803e3d6000fd5b50506040516200b64c906200c1dc565b604051809103906000f0801580156200b669573d6000803e3d6000fd5b50506040516200b679906200c1dc565b604051809103906000f0801580156200b696573d6000803e3d6000fd5b50506040516200b6a6906200c1dc565b604051809103906000f0801580156200b6c3573d6000803e3d6000fd5b50506040516200b6d3906200c1dc565b604051809103906000f0801580156200b6f0573d6000803e3d6000fd5b50506040516200b700906200c1dc565b604051809103906000f0801580156200b71d573d6000803e3d6000fd5b50506040516200b72d906200c1dc565b604051809103906000f0801580156200b74a573d6000803e3d6000fd5b50506040516200b75a906200c1dc565b604051809103906000f0801580156200b777573d6000803e3d6000fd5b50506040516200b787906200c1dc565b604051809103906000f0801580156200b7a4573d6000803e3d6000fd5b50506040516200b7b4906200c1dc565b604051809103906000f0801580156200b7d1573d6000803e3d6000fd5b50506040516200b7e1906200c1dc565b604051809103906000f0801580156200b7fe573d6000803e3d6000fd5b50506040516200b80e906200c1dc565b604051809103906000f0801580156200b82b573d6000803e3d6000fd5b50506040516200b83b906200c1dc565b604051809103906000f0801580156200b858573d6000803e3d6000fd5b50506040516200b868906200c1dc565b604051809103906000f0801580156200b885573d6000803e3d6000fd5b50506040516200b895906200c1dc565b604051809103906000f0801580156200b8b2573d6000803e3d6000fd5b50506040516200b8c2906200c1dc565b604051809103906000f0801580156200b8df573d6000803e3d6000fd5b50506040516200b8ef906200c1dc565b604051809103906000f0801580156200b90c573d6000803e3d6000fd5b50506040516200b91c906200c1dc565b604051809103906000f0801580156200b939573d6000803e3d6000fd5b50506040516200b949906200c1dc565b604051809103906000f0801580156200b966573d6000803e3d6000fd5b50506040516200b976906200c1dc565b604051809103906000f0801580156200b993573d6000803e3d6000fd5b50506040516200b9a3906200c1dc565b604051809103906000f0801580156200b9c0573d6000803e3d6000fd5b50506040516200b9d0906200c1dc565b604051809103906000f0801580156200b9ed573d6000803e3d6000fd5b50506040516200b9fd906200c1dc565b604051809103906000f0801580156200ba1a573d6000803e3d6000fd5b50506040516200ba2a906200c1dc565b604051809103906000f0801580156200ba47573d6000803e3d6000fd5b50506040516200ba57906200c1dc565b604051809103906000f0801580156200ba74573d6000803e3d6000fd5b50506040516200ba84906200c1dc565b604051809103906000f0801580156200baa1573d6000803e3d6000fd5b50506040516200bab1906200c1dc565b604051809103906000f0801580156200bace573d6000803e3d6000fd5b50506040516200bade906200c1dc565b604051809103906000f0801580156200bafb573d6000803e3d6000fd5b50506040516200bb0b906200c1dc565b604051809103906000f0801580156200bb28573d6000803e3d6000fd5b50506040516200bb38906200c1dc565b604051809103906000f0801580156200bb55573d6000803e3d6000fd5b50506040516200bb65906200c1dc565b604051809103906000f0801580156200bb82573d6000803e3d6000fd5b50506040516200bb92906200c1dc565b604051809103906000f0801580156200bbaf573d6000803e3d6000fd5b50506040516200bbbf906200c1dc565b604051809103906000f0801580156200bbdc573d6000803e3d6000fd5b50506040516200bbec906200c1dc565b604051809103906000f0801580156200bc09573d6000803e3d6000fd5b50506040516200bc19906200c1dc565b604051809103906000f0801580156200bc36573d6000803e3d6000fd5b50506040516200bc46906200c1dc565b604051809103906000f0801580156200bc63573d6000803e3d6000fd5b50506040516200bc73906200c1dc565b604051809103906000f0801580156200bc90573d6000803e3d6000fd5b50506040516200bca0906200c1dc565b604051809103906000f0801580156200bcbd573d6000803e3d6000fd5b50506040516200bccd906200c1dc565b604051809103906000f0801580156200bcea573d6000803e3d6000fd5b50506040516200bcfa906200c1dc565b604051809103906000f0801580156200bd17573d6000803e3d6000fd5b50506040516200bd27906200c1dc565b604051809103906000f0801580156200bd44573d6000803e3d6000fd5b50506040516200bd54906200c1dc565b604051809103906000f0801580156200bd71573d6000803e3d6000fd5b50506040516200bd81906200c1dc565b604051809103906000f0801580156200bd9e573d6000803e3d6000fd5b50506040516200bdae906200c1dc565b604051809103906000f0801580156200bdcb573d6000803e3d6000fd5b50506040516200bddb906200c1dc565b604051809103906000f0801580156200bdf8573d6000803e3d6000fd5b50506040516200be08906200c1dc565b604051809103906000f0801580156200be25573d6000803e3d6000fd5b50506040516200be35906200c1dc565b604051809103906000f0801580156200be52573d6000803e3d6000fd5b50506040516200be62906200c1dc565b604051809103906000f0801580156200be7f573d6000803e3d6000fd5b50506040516200be8f906200c1dc565b604051809103906000f0801580156200beac573d6000803e3d6000fd5b50506040516200bebc906200c1dc565b604051809103906000f0801580156200bed9573d6000803e3d6000fd5b50506040516200bee9906200c1dc565b604051809103906000f0801580156200bf06573d6000803e3d6000fd5b50506040516200bf16906200c1dc565b604051809103906000f0801580156200bf33573d6000803e3d6000fd5b50506040516200bf43906200c1dc565b604051809103906000f0801580156200bf60573d6000803e3d6000fd5b50506040516200bf70906200c1dc565b604051809103906000f0801580156200bf8d573d6000803e3d6000fd5b50506040516200bf9d906200c1dc565b604051809103906000f0801580156200bfba573d6000803e3d6000fd5b50506040516200bfca906200c1dc565b604051809103906000f0801580156200bfe7573d6000803e3d6000fd5b50506040516200bff7906200c1dc565b604051809103906000f0801580156200c014573d6000803e3d6000fd5b50506040516200c024906200c1dc565b604051809103906000f0801580156200c041573d6000803e3d6000fd5b50506040516200c051906200c1dc565b604051809103906000f0801580156200c06e573d6000803e3d6000fd5b50506040516200c07e906200c1dc565b604051809103906000f0801580156200c09b573d6000803e3d6000fd5b50506040516200c0ab906200c1dc565b604051809103906000f0801580156200c0c8573d6000803e3d6000fd5b50506040516200c0d8906200c1dc565b604051809103906000f0801580156200c0f5573d6000803e3d6000fd5b50506040516200c105906200c1dc565b604051809103906000f0801580156200c122573d6000803e3d6000fd5b50506040516200c132906200c1dc565b604051809103906000f0801580156200c14f573d6000803e3d6000fd5b50506040516200c15f906200c1dc565b604051809103906000f0801580156200c17c573d6000803e3d6000fd5b50506040516200c18c906200c1dc565b604051809103906000f0801580156200c1a9573d6000803e3d6000fd5b50506040516200c1b9906200c1dc565b604051809103906000f0801580156200c1d6573d6000803e3d6000fd5b50505050565b60d7806200c1ea8339019056fe608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b50609e806100396000396000f3fe6080604052600436106038577c010000000000000000000000000000000000000000000000000000000060003504631a6952308114603d575b600080fd5b606d60048036036020811015605157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16606f565b005b5056fea165627a7a7230582083f7a0331a259c77978d4e827b5b676f9e07ff2fa04be79c314e25873f3b11040029a165627a7a7230582084782da67a2e82014f2871d2e67c7a7d13b0595d88286112fb82e4f6ea3cf8700029" - code_Scenario015_TRC20_TRON = "6060604052604060405190810160405280600681526020017f54726f6e697800000000000000000000000000000000000000000000000000008152506000908051906020019062000052929190620001b6565b50604060405190810160405280600381526020017f545258000000000000000000000000000000000000000000000000000000000081525060019080519060200190620000a1929190620001b6565b50600660025560006005556000600660006101000a81548160ff0219169083151502179055506000600660016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034156200011257fe5b5b33600660016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555067016345785d8a000060058190555067016345785d8a0000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b62000265565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620001f957805160ff19168380011785556200022a565b828001600101855582156200022a579182015b82811115620002295782518255916020019190600101906200020c565b5b5090506200023991906200023d565b5090565b6200026291905b808211156200025e57600081600090555060010162000244565b5090565b90565b61111480620002756000396000f300606060405236156100ce576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100d057806307da68f514610169578063095ea7b31461017b57806318160ddd146101d257806323b872dd146101f8578063313ce5671461026e57806342966c681461029457806370a08231146102b457806375f12b21146102fe57806395d89b4114610328578063a9059cbb146103c1578063be9a655514610418578063c47f00271461042a578063dd62ed3e14610484575bfe5b34156100d857fe5b6100e06104ed565b604051808060200182810382528381815181526020019150805190602001908083836000831461012f575b80518252602083111561012f5760208201915060208101905060208303925061010b565b505050905090810190601f16801561015b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561017157fe5b61017961058b565b005b341561018357fe5b6101b8600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610603565b604051808215151515815260200191505060405180910390f35b34156101da57fe5b6101e26107cb565b6040518082815260200191505060405180910390f35b341561020057fe5b610254600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506107d1565b604051808215151515815260200191505060405180910390f35b341561027657fe5b61027e610b11565b6040518082815260200191505060405180910390f35b341561029c57fe5b6102b26004808035906020019091905050610b17565b005b34156102bc57fe5b6102e8600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610c3f565b6040518082815260200191505060405180910390f35b341561030657fe5b61030e610c57565b604051808215151515815260200191505060405180910390f35b341561033057fe5b610338610c6a565b6040518080602001828103825283818151815260200191508051906020019080838360008314610387575b80518252602083111561038757602082019150602081019050602083039250610363565b505050905090810190601f1680156103b35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103c957fe5b6103fe600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610d08565b604051808215151515815260200191505060405180910390f35b341561042057fe5b610428610f31565b005b341561043257fe5b610482600480803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050610fa9565b005b341561048c57fe5b6104d7600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061101e565b6040518082815260200191505060405180910390f35b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105835780601f1061055857610100808354040283529160200191610583565b820191906000526020600020905b81548152906001019060200180831161056657829003601f168201915b505050505081565b3373ffffffffffffffffffffffffffffffffffffffff16600660019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415156105e457fe5b6001600660006101000a81548160ff0219169083151502179055505b5b565b6000600660009054906101000a900460ff1615151561061e57fe5b3373ffffffffffffffffffffffffffffffffffffffff1660001415151561064157fe5b60008214806106cc57506000600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054145b15156106d85760006000fd5b81600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a3600190505b5b5b92915050565b60055481565b6000600660009054906101000a900460ff161515156107ec57fe5b3373ffffffffffffffffffffffffffffffffffffffff1660001415151561080f57fe5b81600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561085e5760006000fd5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401101515156108ee5760006000fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561097a5760006000fd5b81600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190505b5b5b9392505050565b60025481565b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610b665760006000fd5b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508060036000600073ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060003373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35b50565b60036020528060005260406000206000915090505481565b600660009054906101000a900460ff1681565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610d005780601f10610cd557610100808354040283529160200191610d00565b820191906000526020600020905b815481529060010190602001808311610ce357829003601f168201915b505050505081565b6000600660009054906101000a900460ff16151515610d2357fe5b3373ffffffffffffffffffffffffffffffffffffffff16600014151515610d4657fe5b81600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610d955760006000fd5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540110151515610e255760006000fd5b81600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190505b5b5b92915050565b3373ffffffffffffffffffffffffffffffffffffffff16600660019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515610f8a57fe5b6000600660006101000a81548160ff0219169083151502179055505b5b565b3373ffffffffffffffffffffffffffffffffffffffff16600660019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561100257fe5b8060009080519060200190611018929190611043565b505b5b50565b6004602052816000526040600020602052806000526040600020600091509150505481565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061108457805160ff19168380011785556110b2565b828001600101855582156110b2579182015b828111156110b1578251825591602001919060010190611096565b5b5090506110bf91906110c3565b5090565b6110e591905b808211156110e15760008160009055506001016110c9565b5090565b905600a165627a7a723058204858328431ff0a4e0db74ff432e5805ce4bcf91a1c59650a93bd7c1aec5e0fe10029" - code_MainGateway = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b50604051602080611df8833981016040818152915160008054600160a060020a0319163317815560016004819055600160a060020a0383168083526003602090815292869020805460ff191690921790915583529251909283927f51b292b9f000ae271c781ab0e5f63c49de0000ab30e186d92a03bbaf3325a4a3929081900390910190a15050611d38806100c06000396000f3006080604052600436106101195763ffffffff60e060020a6000350416630aa33f758114610144578063190791da146101935780634b398e991461021c5780635821563e1461022457806361857b441461022c578063715018a61461026a5780637276575c146102995780637ecebe00146102d7578063898de999146103245780638d3e651d146103535780638da5cb5b146103dc57806394042b46146104275780639435455f14610459578063a165302a14610499578063a8ced426146104d7578063bc2de9b01461055d578063bcad917b14610598578063cb912b1e14610650578063cd9df8e1146106d3578063d3d5177b14610702578063e77256f814610743578063e7fc18f8146107c6578063f2fde38b14610801575b620f4240d311156101315761012c61083c565b610142565b6000341115610142576101426108b4565b005b34801561015057600080fd5b50d3801561015d57600080fd5b50d2801561016a57600080fd5b5061017f600160a060020a0360043516610906565b604080519115158252519081900360200190f35b34801561019f57600080fd5b50d380156101ac57600080fd5b50d280156101b957600080fd5b50604080516020601f60643560048181013592830184900484028501840190955281845261014294600160a060020a0381358116956024803590921695604435953695608494019181908401838280828437509497506109489650505050505050565b6101426108b4565b61014261083c565b34801561023857600080fd5b50d3801561024557600080fd5b50d2801561025257600080fd5b50610142600435600160a060020a0360243516610cb2565b34801561027657600080fd5b50d3801561028357600080fd5b50d2801561029057600080fd5b50610142610e35565b3480156102a557600080fd5b50d380156102b257600080fd5b50d280156102bf57600080fd5b50610142600435600160a060020a0360243516610ea1565b3480156102e357600080fd5b50d380156102f057600080fd5b50d280156102fd57600080fd5b50610312600160a060020a0360043516610ff6565b60408051918252519081900360200190f35b34801561033057600080fd5b50d3801561033d57600080fd5b50d2801561034a57600080fd5b50610312611008565b34801561035f57600080fd5b50d3801561036c57600080fd5b50d2801561037957600080fd5b50604080516020601f60643560048181013592830184900484028501840190955281845261014294600160a060020a03813581169560248035909216956044359536956084940191819084018382808284375094975061100e9650505050505050565b3480156103e857600080fd5b50d380156103f557600080fd5b50d2801561040257600080fd5b5061040b6112ed565b60408051600160a060020a039092168252519081900360200190f35b34801561043357600080fd5b50d3801561044057600080fd5b50d2801561044d57600080fd5b506103126004356112fc565b34801561046557600080fd5b50d3801561047257600080fd5b50d2801561047f57600080fd5b50610142600160a060020a0360043516602435151561130e565b3480156104a557600080fd5b50d380156104b257600080fd5b50d280156104bf57600080fd5b5061017f600435600160a060020a0360243516611350565b3480156104e357600080fd5b50d380156104f057600080fd5b50d280156104fd57600080fd5b50604080516020601f60643560048181013592830184900484028501840190955281845261014294600160a060020a0381351694602480359560443595369560849493019181908401838280828437509497506113789650505050505050565b34801561056957600080fd5b50d3801561057657600080fd5b50d2801561058357600080fd5b5061040b600160a060020a036004351661163a565b3480156105a457600080fd5b50d380156105b157600080fd5b50d280156105be57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261061b948235600160a060020a03169460248035953695946064949201919081908401838280828437509497506116559650505050505050565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b34801561065c57600080fd5b50d3801561066957600080fd5b50d2801561067657600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261061b948235600160a060020a031694602480359536959460649492019190819084018382808284375094975061172c9650505050505050565b3480156106df57600080fd5b50d380156106ec57600080fd5b50d280156106f957600080fd5b50610312611803565b34801561070e57600080fd5b50d3801561071b57600080fd5b50d2801561072857600080fd5b50610142600160a060020a0360043581169060243516611809565b34801561074f57600080fd5b50d3801561075c57600080fd5b50d2801561076957600080fd5b50604080516020600460443581810135601f8101849004840285018401909552848452610142948235600160a060020a03169460248035953695946064949201919081908401838280828437509497506118589650505050505050565b3480156107d257600080fd5b50d380156107df57600080fd5b50d280156107ec57600080fd5b50610312600160a060020a0360043516611af6565b34801561080d57600080fd5b50d3801561081a57600080fd5b50d2801561082757600080fd5b50610142600160a060020a0360043516611b11565bd360009081526006602052604090205461085c90d263ffffffff611b3416565bd3600081815260066020908152604091829020939093558051338152d29381019390935282810191909152517f752bc43ba57e4a49162727f5fb5d6f7b0e017826011a02a0b3cddcd70c49b1459181900360600190a1565b6005546108c7903463ffffffff611b3416565b6005556040805133815234602082015281517f1bab02886c659969cbb004cc17dc19be19f193323a306e26c669bedb29c651f7929181900390910190a1565b60008054600160a060020a038381169116141561092557506001610943565b50600160a060020a03811660009081526003602052604090205460ff165b919050565b83828483606060008061095a33610906565b151561096557600080fd5b6040805160028082526060820183529091602083019080388339505050600160a060020a03881660009081526002602052604081205482519295509185919081106109ac57fe5b6020908102909101015282518690849060019081106109c757fe5b906020019060200201818152505084836040516020018083600160a060020a0316600160a060020a03166c01000000000000000000000000028152601401828051906020019060200280838360005b83811015610a2e578181015183820152602001610a16565b50505050905001925050506040516020818303038152906040526040518082805190602001908083835b60208310610a775780518252601f199092019160209182019101610a58565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091209450610ab29250849150869050611b4a565b9050600160a060020a0380821690881614610b05576040805160e560020a62461bcd02815260206004820152601e6024820152600080516020611ced833981519152604482015290519081900360640190fd5b600160a060020a038a1660009081526008602090815260408083208c845290915290205460ff161515610b82576040805160e560020a62461bcd02815260206004820152601260248201527f446f6573206e6f74206f776e20746f6b656e0000000000000000000000000000604482015290519081900360640190fd5b89600160a060020a031663a9059cbb8c8b6040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050600060405180830381600087803b158015610be557600080fd5b505af1158015610bf9573d6000803e3d6000fd5b505050600160a060020a03808c1660009081526008602090815260408083208e845290915290819020805460ff1916905551908d1691507f591f2d33d85291e32c4067b5a497caf3ddb5b1830eba9909e66006ec3a0051b4906003908d908d9080845b60ff168152600160a060020a0390931660208401525060408083019190915251908190036060019150a2505050600160a060020a0390931660009081526002602052604090208054600101905550505050505050565b600160a060020a03818116600090815260016020526040902054161515610d11576040805160e560020a62461bcd0281526020600482015260136024820152600080516020611ccd833981519152604482015290519081900360640190fd5b604080517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018490529051600160a060020a038316916323b872dd9160648083019260209291908290030181600087803b158015610d7f57600080fd5b505af1158015610d93573d6000803e3d6000fd5b505050506040513d6020811015610da957600080fd5b5050600160a060020a038116600090815260076020526040902054610dd4908363ffffffff611b3416565b600160a060020a03821660008181526007602090815260409182902093909355805133815292830185905282810191909152517fe669217c299ce4efdf9b6269aaa41cc844a89016bdb0badde25a2e2f469cc3409181900360600190a15050565b600054600160a060020a03163314610e4c57600080fd5b60008054604051600160a060020a03909116917ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482091a26000805473ffffffffffffffffffffffffffffffffffffffff19169055565b600160a060020a03818116600090815260016020526040902054161515610f00576040805160e560020a62461bcd0281526020600482015260136024820152600080516020611ccd833981519152604482015290519081900360640190fd5b604080517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018490529051600160a060020a038316916323b872dd91606480830192600092919082900301818387803b158015610f6d57600080fd5b505af1158015610f81573d6000803e3d6000fd5b505050600160a060020a0382166000818152600860209081526040808320878452825291829020805460ff19166001179055815133815290810186905280820192909252517fdf4b094c64ac1ec490d3302edb22d396ed9c1f23b14d2c307e04858399cc393292509081900360600190a15050565b60026020526000908152604090205481565b60045481565b83828483606060008061102033610906565b151561102b57600080fd5b6040805160028082526060820183529091602083019080388339505050600160a060020a038816600090815260026020526040812054825192955091859190811061107257fe5b60209081029091010152825186908490600190811061108d57fe5b906020019060200201818152505084836040516020018083600160a060020a0316600160a060020a03166c01000000000000000000000000028152601401828051906020019060200280838360005b838110156110f45781810151838201526020016110dc565b50505050905001925050506040516020818303038152906040526040518082805190602001908083835b6020831061113d5780518252601f19909201916020918201910161111e565b5181516020939093036101000a6000190180199091169216919091179052604051920182900390912094506111789250849150869050611b4a565b9050600160a060020a03808216908816146111cb576040805160e560020a62461bcd02815260206004820152601e6024820152600080516020611ced833981519152604482015290519081900360640190fd5b600160a060020a038a166000908152600760205260409020546111f4908a63ffffffff611be116565b600560020160008c600160a060020a0316600160a060020a031681526020019081526020016000208190555089600160a060020a031663a9059cbb8c8b6040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050602060405180830381600087803b15801561128357600080fd5b505af1158015611297573d6000803e3d6000fd5b505050506040513d60208110156112ad57600080fd5b5050604051600160a060020a038c16907f591f2d33d85291e32c4067b5a497caf3ddb5b1830eba9909e66006ec3a0051b4906002908d908d908084610c5c565b600054600160a060020a031681565b60009081526006602052604090205490565b600054600160a060020a0316331461132557600080fd5b600160a060020a03919091166000908152600360205260409020805460ff1916911515919091179055565b600160a060020a03166000908152600860209081526040808320938352929052205460ff1690565b83828483606060008061138a33610906565b151561139557600080fd5b604080516003808252608082019092529060208201606080388339019050509250848360008151811015156113c657fe5b6020908102909101810191909152600160a060020a0388166000908152600290915260409020548351849060019081106113fc57fe5b60209081029091010152825186908490600290811061141757fe5b90602001906020020181815250508260405160200180828051906020019060200280838360005b8381101561145657818101518382015260200161143e565b505050509050019150506040516020818303038152906040526040518082805190602001908083835b6020831061149e5780518252601f19909201916020918201910161147f565b5181516020939093036101000a6000190180199091169216919091179052604051920182900390912094506114d99250849150869050611b4a565b9050600160a060020a038082169088161461152c576040805160e560020a62461bcd02815260206004820152601e6024820152600080516020611ced833981519152604482015290519081900360640190fd5b60008a81526006602052604090205461154b908a63ffffffff611be116565b60008b815260066020526040902055600160a060020a038b1689156108fc028a8c8015801561157957600080fd5b50806780000000000000001115801561159157600080fd5b5080620f4240101580156115a457600080fd5b50604051600081818185878a8ad09450505050501580156115c9573d6000803e3d6000fd5b506040805160018152602081018c90528082018b9052905133917f472adea2ebbd52a19b140bc25ddcbbe8d3317953a32da818924bab945e4709b1919081900360600190a2505050600160a060020a0390931660009081526002602052604090208054600101905550505050505050565b600160205260009081526040902054600160a060020a031681565b33600090815260016020526040812054600160a060020a031615156116b2576040805160e560020a62461bcd0281526020600482015260136024820152600080516020611ccd833981519152604482015290519081900360640190fd5b6116bb83611bf6565b60408051600160a060020a038616815260208101859052338183015290517fe669217c299ce4efdf9b6269aaa41cc844a89016bdb0badde25a2e2f469cc3409181900360600190a1507fbcad917b000000000000000000000000000000000000000000000000000000009392505050565b33600090815260016020526040812054600160a060020a03161515611789576040805160e560020a62461bcd0281526020600482015260136024820152600080516020611ccd833981519152604482015290519081900360640190fd5b61179283611c29565b60408051600160a060020a038616815260208101859052338183015290517fdf4b094c64ac1ec490d3302edb22d396ed9c1f23b14d2c307e04858399cc39329181900360600190a1507fcb912b1e000000000000000000000000000000000000000000000000000000009392505050565b60055490565b61181233610906565b151561181d57600080fd5b600160a060020a039182166000908152600160205260409020805473ffffffffffffffffffffffffffffffffffffffff191691909216179055565b82823083606060008061186a33610906565b151561187557600080fd5b6040805160028082526060820183529091602083019080388339505050600160a060020a03881660009081526002602052604081205482519295509185919081106118bc57fe5b6020908102909101015282518690849060019081106118d757fe5b906020019060200201818152505084836040516020018083600160a060020a0316600160a060020a03166c01000000000000000000000000028152601401828051906020019060200280838360005b8381101561193e578181015183820152602001611926565b50505050905001925050506040516020818303038152906040526040518082805190602001908083835b602083106119875780518252601f199092019160209182019101611968565b5181516020939093036101000a6000190180199091169216919091179052604051920182900390912094506119c29250849150869050611b4a565b9050600160a060020a0380821690881614611a15576040805160e560020a62461bcd02815260206004820152601e6024820152600080516020611ced833981519152604482015290519081900360640190fd5b600554611a28908a63ffffffff611be116565b600555604051600160a060020a038b16908a156108fc02908b906000818181858888f19350505050158015611a61573d6000803e3d6000fd5b5089600160a060020a03167f591f2d33d85291e32c4067b5a497caf3ddb5b1830eba9909e66006ec3a0051b46000808c60405180846003811115611aa157fe5b60ff168152600160a060020a0390931660208401525060408083019190915251908190036060019150a2505050600160a060020a03909316600090815260026020526040902080546001019055505050505050565b600160a060020a031660009081526007602052604090205490565b600054600160a060020a03163314611b2857600080fd5b611b3181611c4f565b50565b81810182811015611b4457600080fd5b92915050565b60208101516040820151604183015160009260ff90911691601b831015611b7257601b830192505b60408051600080825260208083018085528a905260ff8716838501526060830186905260808301859052925160019360a0808501949193601f19840193928390039091019190865af1158015611bcc573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b600082821115611bf057600080fd5b50900390565b33600090815260076020526040902054611c16908263ffffffff611b3416565b3360009081526007602052604090205550565b33600090815260086020908152604080832093835292905220805460ff19166001179055565b600160a060020a0381161515611c6457600080fd5b60008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039290921691909117905556004e6f7420616e20616c6c6f776520746f6b656e000000000000000000000000004d657373616765206e6f74207369676e65642062792061206761696e65720000a165627a7a723058205cb7d7406fcca2093208cdfb8fa6d9a1ce5e4ae6b526286910d1b63990e322030029" - code_SideGateway = "608060405260068054600160a060020a03199081166201000017909155600780549091166201000117905534801561003657600080fd5b50d3801561004357600080fd5b50d2801561005057600080fd5b50604051602080613c54833981016040908152905160048054600160a060020a03191633179055600160a060020a03166000908152600360205220805460ff19166001179055613baf806100a56000396000f300608060405260043610620001195763ffffffff60e060020a6000350416630a61c59f81146200011e5780630bb0482f14620001605780630f40ef09146200028e5780631f1767eb14620002dc57806331775cc6146200032e578063455042361462000377578063473c3bd714620003c257806355781fcf146200041e57806367bf590314620005175780637ce67366146200054b5780638da5cb5b14620005ce5780639435455f1462000602578063ab15bdf81462000647578063addd5099146200073b578063bcad917b146200077b578063cb912b1e1462000838578063db13a12b14620008c0578063ded8454a1462000900578063ede1a1e91462000940578063eff457d2146200098e578063fce16fec14620009d1575b600080fd5b3480156200012b57600080fd5b50d380156200013957600080fd5b50d280156200014757600080fd5b506200015e600160a060020a036004351662000a1a565b005b3480156200016d57600080fd5b50d380156200017b57600080fd5b50d280156200018957600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526200021694369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975062000ac29650505050505050565b6040805160208082528351818301528351919283929083019185019080838360005b838110156200025257818101518382015260200162000238565b50505050905090810190601f168015620002805780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6040805160206004803580820135601f81018490048402850184019095528484526200015e94369492936024939284019190819084018382808284375094975062000bb49650505050505050565b348015620002e957600080fd5b50d38015620002f757600080fd5b50d280156200030557600080fd5b506200015e600160a060020a036004351660243560443560643560843560ff60a4351662000ca3565b3480156200033b57600080fd5b50d380156200034957600080fd5b50d280156200035757600080fd5b506200015e600160a060020a036004358116906024351660443562000e9c565b3480156200038457600080fd5b50d380156200039257600080fd5b50d28015620003a057600080fd5b50620003ae60043562001022565b604080519115158252519081900360200190f35b348015620003cf57600080fd5b50d38015620003dd57600080fd5b50d28015620003eb57600080fd5b5062000402600160a060020a036004351662001037565b60408051600160a060020a039092168252519081900360200190f35b3480156200042b57600080fd5b50d380156200043957600080fd5b50d280156200044757600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526200040294369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a9998810197919650918201945092508291508401838280828437509497505050923560ff1693506200105292505050565b3480156200052457600080fd5b50d380156200053257600080fd5b50d280156200054057600080fd5b506200040262001344565b3480156200055857600080fd5b50d380156200056657600080fd5b50d280156200057457600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526200040294369492936024939284019190819084018382808284375094975050509235600160a060020a031693506200135392505050565b348015620005db57600080fd5b50d38015620005e957600080fd5b50d28015620005f757600080fd5b5062000402620013da565b3480156200060f57600080fd5b50d380156200061d57600080fd5b50d280156200062b57600080fd5b506200015e600160a060020a03600435166024351515620013e9565b3480156200065457600080fd5b50d380156200066257600080fd5b50d280156200067057600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526200040294369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a9998810197919650918201945092508291508401838280828437509497506200142c9650505050505050565b3480156200074857600080fd5b50d380156200075657600080fd5b50d280156200076457600080fd5b50620003ae600160a060020a036004351662001712565b3480156200078857600080fd5b50d380156200079657600080fd5b50d28015620007a457600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845262000803948235600160a060020a0316946024803595369594606494920191908190840183828082843750949750620017279650505050505050565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b3480156200084557600080fd5b50d380156200085357600080fd5b50d280156200086157600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845262000803948235600160a060020a0316946024803595369594606494920191908190840183828082843750949750620019019650505050505050565b348015620008cd57600080fd5b50d38015620008db57600080fd5b50d28015620008e957600080fd5b5062000402600160a060020a036004351662001b01565b3480156200090d57600080fd5b50d380156200091b57600080fd5b50d280156200092957600080fd5b5062000216600160a060020a036004351662001b1c565b6040805160206004803580820135601f81018490048402850184019095528484526200015e94369492936024939284019190819084018382808284375094975062001b519650505050505050565b3480156200099b57600080fd5b50d38015620009a957600080fd5b50d28015620009b757600080fd5b506200015e600160a060020a036004351660243562001cf1565b348015620009de57600080fd5b50d38015620009ec57600080fd5b50d28015620009fa57600080fd5b506200015e600160a060020a036004358116906024351660443562001dbf565b600454600160a060020a0316331462000a3257600080fd5b600160a060020a038116151562000a93576040805160e560020a62461bcd02815260206004820152601e60248201527f5f73756e546f6b656e41646472657373203d3d20616464726573732830290000604482015290519081900360640190fd5b6005805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6060826041836040516020018084805190602001908083835b6020831062000afc5780518252601f19909201916020918201910162000adb565b6001836020036101000a0380198251168184511680821785525050505050509050018360ff167f010000000000000000000000000000000000000000000000000000000000000002815260010182805190602001908083835b6020831062000b765780518252601f19909201916020918201910162000b55565b6001836020036101000a0380198251168184511680821785525050505050509050019350505050604051602081830303815290604052905092915050565b6040516000903480156108fc029183818181858288f1935050505015801562000be1573d6000803e3d6000fd5b507f7a47a70a1221ce1b92f8d000c55e2c92c0255a381cf1be25c3ca697593ecc96a3334836040518084600160a060020a0316600160a060020a0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101562000c6357818101518382015260200162000c49565b50505050905090810190601f16801562000c915780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a150565b3360009081526003602052604081205460ff16151562000cc257600080fd5b620f42408611801562000cd85750621e84808611155b151562000d55576040805160e560020a62461bcd02815260206004820152602360248201527f7472633130203c3d2031303030303030206f72207472633130203e203230303060448201527f3030300000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b5060008581526002602052604090205460ff1680151562000d8a576000868152600260205260409020805460ff191660011790555b60075460408051878152602081018990528082018790526060810186905260ff851660808201529051600160a060020a039092169160a0808301926000929190829003018183865af1505050600160a060020a0387166108fc86150286888015801562000df657600080fd5b50806780000000000000001115801562000e0f57600080fd5b5080620f42401015801562000e2357600080fd5b50604051600081818185878a8ad094505050505015801562000e49573d6000803e3d6000fd5b5060408051600160a060020a03891681526020810188905280820187905290517f4aac44dc080543b9fe45d9dfaad396001ee0ecdc07499d64e2e798bfffc42fde9181900360600190a150505050505050565b3360009081526003602052604081205460ff16151562000ebb57600080fd5b50600160a060020a038083166000908152602081905260409020541680151562000f54576040805160e560020a62461bcd028152602060048201526024808201527f746865206d61696e20636861696e2061646472657373206861736e2774206d6160448201527f7070656400000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b80600160a060020a03166340c10f1985846040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050600060405180830381600087803b15801562000fb857600080fd5b505af115801562000fcd573d6000803e3d6000fd5b505060408051600160a060020a0380861682528816602082015280820186905290517f48c104169bad147dfc9c0b2ac8fc83202a035d4d9632e24e839680be759772089350908190036060019150a150505050565b60026020526000908152604090205460ff1681565b600060208190529081526040902054600160a060020a031681565b600080600062001063873362001353565b600160a060020a038082166000908152602081905260409020549193501615620010fd576040805160e560020a62461bcd02815260206004820152602160248201527f746865206d61696e20636861696e206164647265737320686173206d6170706560448201527f6400000000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600554600160a060020a03838116911614156200118a576040805160e560020a62461bcd02815260206004820152602360248201527f6d61696e436861696e41646472657373203d3d2073756e546f6b656e4164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b308686866200119862001f45565b600160a060020a038516815260ff82166060820152608060208083018281528651928401929092528551604084019160a08501919088019080838360005b83811015620011f0578181015183820152602001620011d6565b50505050905090810190601f1680156200121e5780820380516001836020036101000a031916815260200191505b50838103825285518152855160209182019187019080838360005b838110156200125357818101518382015260200162001239565b50505050905090810190601f168015620012815780820380516001836020036101000a031916815260200191505b509650505050505050604051809103906000f080158015620012a7573d6000803e3d6000fd5b50600160a060020a03808416600081815260208181526040808320805495871673ffffffffffffffffffffffffffffffffffffffff1996871681179091558084526001835292819020805490951684179094558351338152908101929092528183015290519192507fee201bea1b0aff77f5f792b979e4732ba6605c2203d0f92f9aa45625eff88222919081900360600190a19695505050505050565b600554600160a060020a031681565b6000606080620013638462001b1c565b915062001371858362000ac2565b9050806040518082805190602001908083835b60208310620013a55780518252601f19909201916020918201910162001384565b5181516020939093036101000a6000190180199091169216919091179052604051920182900390912098975050505050505050565b600454600160a060020a031681565b600454600160a060020a031633146200140157600080fd5b600160a060020a03919091166000908152600360205260409020805460ff1916911515919091179055565b60008060006200143d863362001353565b600160a060020a038082166000908152602081905260409020549193501615620014d7576040805160e560020a62461bcd02815260206004820152602160248201527f746865206d61696e20636861696e206164647265737320686173206d6170706560448201527f6400000000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600554600160a060020a038381169116141562001564576040805160e560020a62461bcd02815260206004820152602360248201527f6d61696e436861696e41646472657373203d3d2073756e546f6b656e4164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b3085856200157162001f56565b600160a060020a0384168152606060208083018281528551928401929092528451604084019160808501919087019080838360005b83811015620015c0578181015183820152602001620015a6565b50505050905090810190601f168015620015ee5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b838110156200162357818101518382015260200162001609565b50505050905090810190601f168015620016515780820380516001836020036101000a031916815260200191505b5095505050505050604051809103906000f08015801562001676573d6000803e3d6000fd5b50600160a060020a03808416600081815260208181526040808320805495871673ffffffffffffffffffffffffffffffffffffffff1996871681179091558084526001835292819020805490951684179094558351338152908101929092528183015290519192507fa2399d6f422f35b470d7aff96f7b2d8ce1c07bc14d978c9fbad6083461c564a7919081900360600190a195945050505050565b60036020526000908152604090205460ff1681565b33600081815260016020526040812054909190600160a060020a03168015156200179b576040805160e560020a62461bcd02815260206004820152601e60248201527f6d61696e436861696e41646472657373203d3d20616464726573732830290000604482015290519081900360640190fd5b81600160a060020a03166342966c68866040518263ffffffff1660e060020a02815260040180828152602001915050600060405180830381600087803b158015620017e557600080fd5b505af1158015620017fa573d6000803e3d6000fd5b505050507fc7b54407df97321a6170a99eeb667db3dc95205c9a9b12a4f1673bac84066544868683876040518085600160a060020a0316600160a060020a0316815260200184815260200183600160a060020a0316600160a060020a0316815260200180602001828103825283818151815260200191508051906020019080838360005b83811015620018985781810151838201526020016200187e565b50505050905090810190601f168015620018c65780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a1507fbcad917b0000000000000000000000000000000000000000000000000000000095945050505050565b33600081815260016020526040812054909190600160a060020a03168015156200199b576040805160e560020a62461bcd02815260206004820152602360248201527f74686520747263373231206d7573742068617665206265656e206465706f736960448201527f7465640000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b81600160a060020a03166342966c68866040518263ffffffff1660e060020a02815260040180828152602001915050600060405180830381600087803b158015620019e557600080fd5b505af1158015620019fa573d6000803e3d6000fd5b505050507fa93bdc38faeb2081566bca9d2c041ba1545a11a459c67a8baf5c671a262e9b7c868683876040518085600160a060020a0316600160a060020a0316815260200184815260200183600160a060020a0316600160a060020a0316815260200180602001828103825283818151815260200191508051906020019080838360005b8381101562001a9857818101518382015260200162001a7e565b50505050905090810190601f16801562001ac65780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a1507fcb912b1e0000000000000000000000000000000000000000000000000000000095945050505050565b600160205260009081526040902054600160a060020a031681565b60408051600160a060020a03929092167414000000000000000000000000000000000000000018601483015260348201905290565bd360009081526002602052604090205460ff16151562001bbb576040805160e560020a62461bcd02815260206004820152601e60248201527f74726331304d61705b6d73672e746f6b656e69645d203d3d2066616c73650000604482015290519081900360640190fd5b6000d280156108fc0290d38015801562001bd457600080fd5b50806780000000000000001115801562001bed57600080fd5b5080620f42401015801562001c0157600080fd5b50604051600081818185878a8ad094505050505015801562001c27573d6000803e3d6000fd5b507f4cdc0dc16c2640bf1cbeebfe9055747d6c36b74120ed1d06440846a8150cc4c333d2d3846040518085600160a060020a0316600160a060020a0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101562001cb057818101518382015260200162001c96565b50505050905090810190601f16801562001cde5780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a150565b3360009081526003602052604090205460ff16151562001d1057600080fd5b600654604080518381529051600160a060020a03909216916020808301926000929190829003018183865af15050604051600160a060020a038416915082156108fc029083906000818181858888f1935050505015801562001d76573d6000803e3d6000fd5b5060408051600160a060020a03841681526020810183905281517f0e3147459e9437f793e793b98df267ee885cfe4ad096b279287f03dcd0ca0497929181900390910190a15050565b3360009081526003602052604081205460ff16151562001dde57600080fd5b50600160a060020a038083166000908152602081905260409020541680151562001e77576040805160e560020a62461bcd028152602060048201526024808201527f746865206d61696e20636861696e2061646472657373206861736e2774206d6160448201527f7070656400000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b80600160a060020a03166340c10f1985846040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050600060405180830381600087803b15801562001edb57600080fd5b505af115801562001ef0573d6000803e3d6000fd5b505060408051600160a060020a0380861682528816602082015280820186905290517fb49dbda83c867b85d55c88d22a084e7db05c8a29e16d027af1b02105906d16bc9350908190036060019150a150505050565b604051610d7c8062001f6883390190565b604051610ea08062002ce4833901905600608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b50604051610d7c380380610d7c833981016040908152815160208084015192840151606085015160038054600160a060020a031916600160a060020a0386161790559385018051939590949101929091610089916004918601906100bf565b50815161009d9060059060208501906100bf565b506006805460ff191660ff92909216919091179055505060006002555061015a565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061010057805160ff191683800117855561012d565b8280016001018555821561012d579182015b8281111561012d578251825591602001919060010190610112565b5061013992915061013d565b5090565b61015791905b808211156101395760008155600101610143565b90565b610c13806101696000396000f3006080604052600436106100da5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100df578063095ea7b314610183578063116191b6146101d557806318160ddd1461022057806323b872dd14610261578063313ce567146102a557806339509351146102ea57806340c10f191461032857806342966c681461036857806349e118931461039a57806370a082311461041257806395d89b411461044d578063a457c2d71461047c578063a9059cbb146104ba578063dd62ed3e146104f8575b600080fd5b3480156100eb57600080fd5b50d380156100f857600080fd5b50d2801561010557600080fd5b5061010e610539565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610148578181015183820152602001610130565b50505050905090810190601f1680156101755780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561018f57600080fd5b50d3801561019c57600080fd5b50d280156101a957600080fd5b506101c1600160a060020a03600435166024356105c7565b604080519115158252519081900360200190f35b3480156101e157600080fd5b50d380156101ee57600080fd5b50d280156101fb57600080fd5b506102046105dd565b60408051600160a060020a039092168252519081900360200190f35b34801561022c57600080fd5b50d3801561023957600080fd5b50d2801561024657600080fd5b5061024f6105ec565b60408051918252519081900360200190f35b34801561026d57600080fd5b50d3801561027a57600080fd5b50d2801561028757600080fd5b506101c1600160a060020a03600435811690602435166044356105f2565b3480156102b157600080fd5b50d380156102be57600080fd5b50d280156102cb57600080fd5b506102d4610649565b6040805160ff9092168252519081900360200190f35b3480156102f657600080fd5b50d3801561030357600080fd5b50d2801561031057600080fd5b506101c1600160a060020a0360043516602435610652565b34801561033457600080fd5b50d3801561034157600080fd5b50d2801561034e57600080fd5b50610366600160a060020a036004351660243561068e565b005b34801561037457600080fd5b50d3801561038157600080fd5b50d2801561038e57600080fd5b5061036660043561074f565b3480156103a657600080fd5b50d380156103b357600080fd5b50d280156103c057600080fd5b5060408051602060046024803582810135601f810185900485028601850190965285855261036695833595369560449491939091019190819084018382808284375094975061075c9650505050505050565b34801561041e57600080fd5b50d3801561042b57600080fd5b50d2801561043857600080fd5b5061024f600160a060020a03600435166108d0565b34801561045957600080fd5b50d3801561046657600080fd5b50d2801561047357600080fd5b5061010e6108eb565b34801561048857600080fd5b50d3801561049557600080fd5b50d280156104a257600080fd5b506101c1600160a060020a0360043516602435610946565b3480156104c657600080fd5b50d380156104d357600080fd5b50d280156104e057600080fd5b506101c1600160a060020a0360043516602435610982565b34801561050457600080fd5b50d3801561051157600080fd5b50d2801561051e57600080fd5b5061024f600160a060020a036004358116906024351661098f565b6004805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156105bf5780601f10610594576101008083540402835291602001916105bf565b820191906000526020600020905b8154815290600101906020018083116105a257829003601f168201915b505050505081565b60006105d43384846109ba565b50600192915050565b600354600160a060020a031681565b60025490565b60006105ff848484610a46565b600160a060020a03841660009081526001602090815260408083203380855292529091205461063f91869161063a908663ffffffff610b1316565b6109ba565b5060019392505050565b60065460ff1681565b336000818152600160209081526040808320600160a060020a038716845290915281205490916105d491859061063a908663ffffffff610b2816565b600354600160a060020a031633146106a557600080fd5b600160a060020a03821615156106ba57600080fd5b6002546106cd908263ffffffff610b2816565b600255600160a060020a0382166000908152602081905260409020546106f9908263ffffffff610b2816565b600160a060020a0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6107593382610b3e565b50565b60035460009061077590600160a060020a031684610982565b506003546040517fbcad917b000000000000000000000000000000000000000000000000000000008152336004820181815260248301879052606060448401908152865160648501528651600160a060020a039095169463bcad917b94899389939092909160840190602085019080838360005b838110156108015781810151838201526020016107e9565b50505050905090810190601f16801561082e5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b15801561084f57600080fd5b505af1158015610863573d6000803e3d6000fd5b505050506040513d602081101561087957600080fd5b505190507fffffffff0000000000000000000000000000000000000000000000000000000081167fbcad917b00000000000000000000000000000000000000000000000000000000146108cb57600080fd5b505050565b600160a060020a031660009081526020819052604090205490565b6005805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156105bf5780601f10610594576101008083540402835291602001916105bf565b336000818152600160209081526040808320600160a060020a038716845290915281205490916105d491859061063a908663ffffffff610b1316565b60006105d4338484610a46565b600160a060020a03918216600090815260016020908152604080832093909416825291909152205490565b600160a060020a03821615156109cf57600080fd5b600160a060020a03831615156109e457600080fd5b600160a060020a03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600160a060020a0382161515610a5b57600080fd5b600160a060020a038316600090815260208190526040902054610a84908263ffffffff610b1316565b600160a060020a038085166000908152602081905260408082209390935590841681522054610ab9908263ffffffff610b2816565b600160a060020a038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600082821115610b2257600080fd5b50900390565b81810182811015610b3857600080fd5b92915050565b600160a060020a0382161515610b5357600080fd5b600254610b66908263ffffffff610b1316565b600255600160a060020a038216600090815260208190526040902054610b92908263ffffffff610b1316565b600160a060020a038316600081815260208181526040808320949094558351858152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a350505600a165627a7a7230582030edf24eb27134d7c77898452315198f9886970c7fed0049b49cd05f121562db0029608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b5060405162000ea038038062000ea083398101604090815281516020808401519284015160048054600160a060020a031916600160a060020a038516179055928401805192949093019161008491600591908501906100a1565b5080516100989060069060208401906100a1565b5050505061013c565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100e257805160ff191683800117855561010f565b8280016001018555821561010f579182015b8281111561010f5782518255916020019190600101906100f4565b5061011b92915061011f565b5090565b61013991905b8082111561011b5760008155600101610125565b90565b610d54806200014c6000396000f3006080604052600436106100cf5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100d4578063081812fc14610178578063095ea7b3146101c6578063116191b61461020657806323b872dd1461023557806340c10f191461027957806342966c68146102b757806349e11893146102e95780636352211e1461036157806370a082311461039357806395d89b41146103e0578063a22cb4651461040f578063a9059cbb1461044f578063e985e9c51461048d575b600080fd5b3480156100e057600080fd5b50d380156100ed57600080fd5b50d280156100fa57600080fd5b506101036104e2565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561013d578181015183820152602001610125565b50505050905090810190601f16801561016a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561018457600080fd5b50d3801561019157600080fd5b50d2801561019e57600080fd5b506101aa600435610570565b60408051600160a060020a039092168252519081900360200190f35b3480156101d257600080fd5b50d380156101df57600080fd5b50d280156101ec57600080fd5b50610204600160a060020a03600435166024356105a2565b005b34801561021257600080fd5b50d3801561021f57600080fd5b50d2801561022c57600080fd5b506101aa610658565b34801561024157600080fd5b50d3801561024e57600080fd5b50d2801561025b57600080fd5b50610204600160a060020a0360043581169060243516604435610667565b34801561028557600080fd5b50d3801561029257600080fd5b50d2801561029f57600080fd5b50610204600160a060020a036004351660243561068c565b3480156102c357600080fd5b50d380156102d057600080fd5b50d280156102dd57600080fd5b50610204600435610763565b3480156102f557600080fd5b50d3801561030257600080fd5b50d2801561030f57600080fd5b5060408051602060046024803582810135601f81018590048502860185019096528585526102049583359536956044949193909101919081908401838280828437509497506107709650505050505050565b34801561036d57600080fd5b50d3801561037a57600080fd5b50d2801561038757600080fd5b506101aa6004356108e0565b34801561039f57600080fd5b50d380156103ac57600080fd5b50d280156103b957600080fd5b506103ce600160a060020a036004351661090a565b60408051918252519081900360200190f35b3480156103ec57600080fd5b50d380156103f957600080fd5b50d2801561040657600080fd5b5061010361093d565b34801561041b57600080fd5b50d3801561042857600080fd5b50d2801561043557600080fd5b50610204600160a060020a03600435166024351515610998565b34801561045b57600080fd5b50d3801561046857600080fd5b50d2801561047557600080fd5b50610204600160a060020a0360043516602435610a1c565b34801561049957600080fd5b50d380156104a657600080fd5b50d280156104b357600080fd5b506104ce600160a060020a0360043581169060243516610a2b565b604080519115158252519081900360200190f35b6005805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156105685780601f1061053d57610100808354040283529160200191610568565b820191906000526020600020905b81548152906001019060200180831161054b57829003601f168201915b505050505081565b600061057b82610a59565b151561058657600080fd5b50600090815260016020526040902054600160a060020a031690565b60006105ad826108e0565b9050600160a060020a0383811690821614156105c857600080fd5b33600160a060020a03821614806105e457506105e48133610a2b565b15156105ef57600080fd5b600082815260016020526040808220805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b600454600160a060020a031681565b6106713382610a76565b151561067c57600080fd5b610687838383610ad5565b505050565b600454600160a060020a031633146106a357600080fd5b600160a060020a03821615156106b857600080fd5b6106c181610a59565b156106cb57600080fd5b600081815260208181526040808320805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03871690811790915583526002909152902054610718906001610bf0565b600160a060020a0383166000818152600260205260408082209390935591518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b61076d3382610c00565b50565b60045460009061078990600160a060020a031684610a1c565b600480546040517fcb912b1e0000000000000000000000000000000000000000000000000000000081523392810183815260248201879052606060448301908152865160648401528651600160a060020a039094169463cb912b1e949093899389939092909160840190602085019080838360005b838110156108165781810151838201526020016107fe565b50505050905090810190601f1680156108435780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b15801561086457600080fd5b505af1158015610878573d6000803e3d6000fd5b505050506040513d602081101561088e57600080fd5b505190507fffffffff0000000000000000000000000000000000000000000000000000000081167fcb912b1e000000000000000000000000000000000000000000000000000000001461068757600080fd5b600081815260208190526040812054600160a060020a031680151561090457600080fd5b92915050565b6000600160a060020a038216151561092157600080fd5b50600160a060020a031660009081526002602052604090205490565b6006805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156105685780601f1061053d57610100808354040283529160200191610568565b600160a060020a0382163314156109ae57600080fd5b336000818152600360209081526040808320600160a060020a03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b610a27338383610ad5565b5050565b600160a060020a03918216600090815260036020908152604080832093909416825291909152205460ff1690565b600090815260208190526040902054600160a060020a0316151590565b600080610a82836108e0565b905080600160a060020a031684600160a060020a03161480610abd575083600160a060020a0316610ab284610570565b600160a060020a0316145b80610acd5750610acd8185610a2b565b949350505050565b82600160a060020a0316610ae8826108e0565b600160a060020a031614610afb57600080fd5b600160a060020a0382161515610b1057600080fd5b610b1981610ccb565b600160a060020a038316600090815260026020526040902054610b4390600163ffffffff610d1316565b600160a060020a038085166000908152600260205260408082209390935590841681522054610b7990600163ffffffff610bf016565b600160a060020a03808416600081815260026020908152604080832095909555858252819052838120805473ffffffffffffffffffffffffffffffffffffffff1916831790559251849391928716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b8181018281101561090457600080fd5b81600160a060020a0316610c13826108e0565b600160a060020a031614610c2657600080fd5b610c2f81610ccb565b600160a060020a038216600090815260026020526040902054610c5990600163ffffffff610d1316565b600160a060020a038316600081815260026020908152604080832094909455848252819052828120805473ffffffffffffffffffffffffffffffffffffffff191690559151839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b600081815260016020526040902054600160a060020a03161561076d576000908152600160205260409020805473ffffffffffffffffffffffffffffffffffffffff19169055565b600082821115610d2257600080fd5b509003905600a165627a7a72305820e95bf2b25cae43edb66a8c2c9a5784778a3163ec94f09ffb86ca32624f6a8b1b0029a165627a7a72305820642e8c16e0d0768025001430bcf8dea875428b07fc9214f0b1b37c74a5b34c660029" - code_shieldTrc20Token = "60806040526002805460ff1916600617905534801561001d57600080fd5b506040516109a53803806109a583398101604090815281516020808401518385015160025460ff16600a0a84026003819055336000908152600485529586205590850180519395909491019261007592850190610092565b508051610089906001906020840190610092565b5050505061012d565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100d357805160ff1916838001178555610100565b82800160010185558215610100579182015b828111156101005782518255916020019190600101906100e5565b5061010c929150610110565b5090565b61012a91905b8082111561010c5760008155600101610116565b90565b6108698061013c6000396000f3006080604052600436106100b95763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100be578063095ea7b31461014857806318160ddd1461018057806323b872dd146101a7578063313ce567146101d157806342966c68146101fc57806370a082311461021457806379cc67901461023557806395d89b4114610259578063a9059cbb1461026e578063cae9ca5114610292578063dd62ed3e146102fb575b600080fd5b3480156100ca57600080fd5b506100d3610322565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561010d5781810151838201526020016100f5565b50505050905090810190601f16801561013a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015457600080fd5b5061016c600160a060020a03600435166024356103b0565b604080519115158252519081900360200190f35b34801561018c57600080fd5b506101956103dd565b60408051918252519081900360200190f35b3480156101b357600080fd5b5061016c600160a060020a03600435811690602435166044356103e3565b3480156101dd57600080fd5b506101e6610453565b6040805160ff9092168252519081900360200190f35b34801561020857600080fd5b5061016c60043561045c565b34801561022057600080fd5b50610195600160a060020a03600435166104d4565b34801561024157600080fd5b5061016c600160a060020a03600435166024356104e6565b34801561026557600080fd5b506100d36105b7565b34801561027a57600080fd5b5061016c600160a060020a0360043516602435610611565b34801561029e57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261016c948235600160a060020a03169460248035953695946064949201919081908401838280828437509497506106259650505050505050565b34801561030757600080fd5b50610195600160a060020a036004358116906024351661073e565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103a85780601f1061037d576101008083540402835291602001916103a8565b820191906000526020600020905b81548152906001019060200180831161038b57829003601f168201915b505050505081565b336000908152600560209081526040808320600160a060020a039590951683529390529190912055600190565b60035481565b600160a060020a038316600090815260056020908152604080832033845290915281205482111561041357600080fd5b600160a060020a038416600090815260056020908152604080832033845290915290208054839003905561044884848461075b565b506001949350505050565b60025460ff1681565b3360009081526004602052604081205482111561047857600080fd5b3360008181526004602090815260409182902080548690039055600380548690039055815185815291517fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca59281900390910190a2506001919050565b60046020526000908152604090205481565b600160a060020a03821660009081526004602052604081205482111561050b57600080fd5b600160a060020a038316600090815260056020908152604080832033845290915290205482111561053b57600080fd5b600160a060020a0383166000818152600460209081526040808320805487900390556005825280832033845282529182902080548690039055600380548690039055815185815291517fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca59281900390910190a250600192915050565b60018054604080516020600284861615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103a85780601f1061037d576101008083540402835291602001916103a8565b600061061e33848461075b565b9392505050565b60008361063281856103b0565b15610736576040517f8f4ffcb10000000000000000000000000000000000000000000000000000000081523360048201818152602483018790523060448401819052608060648501908152875160848601528751600160a060020a03871695638f4ffcb195948b94938b939192909160a490910190602085019080838360005b838110156106ca5781810151838201526020016106b2565b50505050905090810190601f1680156106f75780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b15801561071957600080fd5b505af115801561072d573d6000803e3d6000fd5b50505050600191505b509392505050565b600560209081526000928352604080842090915290825290205481565b600080600160a060020a038416151561077357600080fd5b600160a060020a03851660009081526004602052604090205483111561079857600080fd5b600160a060020a03841660009081526004602052604090205483810110156107bf57600080fd5b50600160a060020a0380841660008181526004602090815260408083208054958a1680855282852080548a81039091559486905281548901909155815188815291519390950194927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a35060019493505050505600a165627a7a723058208600353fffbf658cb8b57929fba657c57e83d756e4101cf874b153cc6eb4bb1c0029" - code_shield = "6104806040527f010000000000000000000000000000000000000000000000000000000000000060809081527f817de36ab2d57feb077634bca77819c8e0bd298c04f6fed0e6a83cc1356ca15560a0527fffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e3460c0527fd8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c60e0527fe110de65c907b9dea4ae0bd83a4b0a51bea175646a64c12b4c9f931b2cb31b49610100527f912d82b2c2bca231f71efcf61737fbf0a08befa0416215aeef53e8bb6d23390a610120527f8ac9cf9c391e3fd42891d27238a81a8a5c1d3a72b1bcbea8cf44a58ce7389613610140527fd6c639ac24b46bd19341c91b13fdcab31581ddaf7f1411336a271f3d0aa52813610160527f7b99abdc3730991cc9274727d7d82d28cb794edbc7034b4f0053ff7c4b680444610180527f43ff5457f13b926b61df552d4e402ee6dc1463f99a535f9a713439264d5b616b6101a0527fba49b659fbd0b7334211ea6a9d9df185c757e70aa81da562fb912b84f49bce726101c0527f4777c8776a3b1e69b73a62fa701fa4f7a6282d9aee2c7a6b82e7937d7081c23c6101e0527fec677114c27206f5debc1c1ed66f95e2b1885da5b7be3d736b1de98579473048610200527f1b77dac4d24fb7258c3c528704c59430b630718bec486421837021cf75dab651610220527fbd74b25aacb92378a871bf27d225cfc26baca344a1ea35fdd94510f3d157082c610240527fd6acdedf95f608e09fa53fb43dcd0990475726c5131210c9e5caeab97f0e642f610260527f1ea6675f9551eeb9dfaaa9247bc9858270d3d3a4c5afa7177a984d5ed1be2451610280527f6edb16d01907b759977d7650dad7e3ec049af1a3d875380b697c862c9ec5d51c6102a0527fcd1c8dbf6e3acc7a80439bc4962cf25b9dce7c896f3a5bd70803fc5a0e33cf006102c0527f6aca8448d8263e547d5ff2950e2ed3839e998d31cbc6ac9fd57bc6002b1592166102e0527f8d5fa43e5a10d11605ac7430ba1f5d81fb1b68d29a640405767749e841527673610300527f08eeab0c13abd6069e6310197bf80f9c1ea6de78fd19cbae24d4a520e6cf3023610320527f0769557bc682b1bf308646fd0b22e648e8b9e98f57e29f5af40f6edb833e2c49610340527f4c6937d78f42685f84b43ad3b7b00f81285662f85c6a68ef11d62ad1a3ee0850610360527ffee0e52802cb0c46b1eb4d376c62697f4759f6c8917fa352571202fd778fd712610380527f16d6252968971a83da8521d65382e61f0176646d771c91528e3276ee45383e4a6103a0527fd2e1642c9a462229289e5b0e3b7f9008e0301cbb93385ee0e21da2545073cb586103c0527fa5122c08ff9c161d9ca6fc462073396c7d7d38e8ee48cdb3bea7e2230134ed6a6103e0527f28e7b841dcbc47cceb69d7cb8d94245fb7cb2ba3a7a6bc18f13f945f7dbd6e2a610400527fe1f34b034d4a3cd28557e2907ebf990c918f64ecb50a94f01d6fda5ca5c7ef72610420527f12935f14b676509b81eb49ef25f39269ed72309238b4c145803544b646dca62d610440527fb2eed031d4d6a4f02a097f80b54cc1541d4163c6b6f5971f88b6e41d35c5381461046052620004b390602890602062000580565b50348015620004c157600080fd5b50d38015620004cf57600080fd5b50d28015620004dd57600080fd5b506040516200354738038062003547833981016040819052620005009162000615565b604d811062000546576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200053d90620006b5565b60405180910390fd5b600a0a60005560488054336001600160a01b031991821617909155604980549091166001600160a01b039290921691909117905562000713565b8260208101928215620005b1579160200282015b82811115620005b157825182559160200191906001019062000594565b50620005bf929150620005c3565b5090565b620005e091905b80821115620005bf5760008155600101620005ca565b90565b8051620005f081620006ee565b620005fb81620006d0565b9392505050565b80516200060f8162000708565b92915050565b600080604083850312156200062957600080fd5b6000620006378585620005e3565b92505060206200064a8582860162000602565b9150509250929050565b600062000663602a83620006c7565b7f546865207363616c696e67466163746f724578706f6e656e74206973206f757481527f206f662072616e67652100000000000000000000000000000000000000000000602082015260400192915050565b602080825281016200060f8162000654565b90815260200190565b60006001600160a01b0382166200060f565b6001600160a81b031690565b620006f981620006e2565b81146200070557600080fd5b50565b620006f981620005e0565b612e2480620007236000396000f3fe608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b50600436106100c35760003560e01c80639110a55b1161008b5780639110a55b14610134578063ae6dead714610147578063cc1058751461015a578063d7b0fef11461016d578063e176507314610175578063ed3437f814610196576100c3565b80632997e86b146100c85780632a6bb45a146100f157806330e69fc314610104578063313529361461010c578063855d175e1461011f575b600080fd5b6100db6100d6366004611c30565b61019e565b6040516100e89190612a7d565b60405180910390f35b6100db6100ff366004611c30565b6101b0565b6100db6101c2565b6100db61011a366004611c30565b6101c8565b61013261012d366004611c6c565b6101da565b005b610132610142366004611a3d565b6105a9565b6100db610155366004611c30565b610bd4565b610132610168366004611b22565b610be6565b6100db61106c565b610188610183366004611c30565b611072565b6040516100e8929190612a8b565b6100db6111c5565b60036020526000908152604090205481565b60066020526000908152604090205481565b60015481565b60056020526000908152604090205481565b6049546040516323b872dd60e01b815233916000916001600160a01b03909116906323b872dd9061021390859030908b90600401612852565b602060405180830381600087803b15801561022d57600080fd5b505af1158015610241573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506102659190810190611c12565b90508061028d5760405162461bcd60e51b815260040161028490612ad8565b60405180910390fd5b8435600090815260066020526040902054156102bb5760405162461bcd60e51b815260040161028490612b58565b60006102c6876111cb565b905060006002308389886040516020016102e394939291906127fc565b60408051601f19818403018152908290526102fd91612846565b602060405180830381855afa15801561031a573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525061033d9190810190611c4e565b90506060630100000188888585600760015460405161036196959493929190612a1d565b600060405180830381855afa15801561037e573d6000803e3d6000fd5b5050503d80600081146103ad576040519150601f19603f3d011682016040523d82523d6000602084013e6103b2565b606091505b5090506000816000815181106103c457fe5b602002602001015160001c9050806001146103f15760405162461bcd60e51b815260040161028490612b68565b60008260018151811061040057fe5b60209081029190910181015160015463ffffffff016000818152600590935260409092208c359055915081610435578a356007555b60015b826001018110156104aa576002600019830104915084816001018151811061045c57fe5b60200260200101516005600084815260200190815260200160002081905550828114156104a2576000828152600560205260409020546007846021811061049f57fe5b01555b600101610438565b508382600201815181106104ba57fe5b60209081029190910181015160028190556000818152600490925260408220558b906020020135600660008d81602090810291909101358252810191909152604001600090812091909155600180548082019091557fbe22cbc129fd01d04b02a7b3258b72e8c8ae5bfcf054d7f0359779be627a6b27918d9060200201358d600160200201358e600260200201358d60405161055a959493929190612bb8565b60405180910390a17f36bf5aa3964be01dbd95a0154a8930793fe68353bdc580871ffb2c911366bbc7888d60405161059392919061287a565b60405180910390a1505050505050505050505050565b600188108015906105bb575060028811155b6105d75760405162461bcd60e51b815260040161028490612b98565b8786146105f65760405162461bcd60e51b815260040161028490612b08565b60018410801590610608575060028411155b6106245760405162461bcd60e51b815260040161028490612b18565b8381146106435760405162461bcd60e51b815260040161028490612b38565b60005b8881101561070757600360008b8b8481811061065e57fe5b905061014002016000600a811061067157fe5b60200201358152602001908152602001600020546000801b146106a65760405162461bcd60e51b815260040161028490612ba8565b600460008b8b848181106106b657fe5b905061014002016001600a81106106c957fe5b60200201358152602001908152602001600020546000801b14156106ff5760405162461bcd60e51b815260040161028490612af8565b600101610646565b5060005b84811015610773576006600087878481811061072357fe5b9050610120020160006009811061073657fe5b60200201358152602001908152602001600020546000801b1461076b5760405162461bcd60e51b815260040161028490612ae8565b60010161070b565b5060006002308b8b898988886040516020016107959796959493929190612751565b60408051601f19818403018152908290526107af91612846565b602060405180830381855afa1580156107cc573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506107ef9190810190611c4e565b9050606063010000028b8b8b8b8b8b8b896000600760015460405161081e9b9a999897969594939291906128bd565b600060405180830381855afa15801561083b573d6000803e3d6000fd5b5050503d806000811461086a576040519150601f19603f3d011682016040523d82523d6000602084013e61086f565b606091505b50905060008160008151811061088157fe5b602002602001015160001c9050806001146108ae5760405162461bcd60e51b815260040161028490612b68565b600160005b888110156109d95760008483806001019450815181106108cf57fe5b602090810291909101015160015490915063ffffffff018b8b848181106108f257fe5b9050610120020160006009811061090557fe5b60008381526005602090815260409091209102919091013590558161094c578b8b8481811061093057fe5b9050610120020160006009811061094357fe5b60200201356007555b60015b826001018110156109c4576002600019830104915086858060010196508151811061097657fe5b60200260200101516005600084815260200190815260200160002081905550828114156109bc57600082815260056020526040902054600784602181106109b957fe5b01555b60010161094f565b505060018054810181559190910190506108b3565b508281815181106109e657fe5b60209081029190910181015160028190556000818152600490925260408220555b8c811015610a8f5760008e8e83818110610a1d57fe5b905061014002016000600a8110610a3057fe5b602002013590508060036000838152602001908152602001600020819055507fd13faa8100906cf559aebacf9c16532cfc9708645c198c8f15798ee049dbcfc181604051610a7e9190612a7d565b60405180910390a150600101610a07565b5060005b88811015610bc457898982818110610aa757fe5b90506101200201600060098110610aba57fe5b6020020135600660008c8c85818110610acf57fe5b90506101200201600060098110610ae257fe5b60200201358152602001908152602001600020819055507f0f190e6ff1f0e1c1f4ec51aecdafdd02278c568898b57df5ca7dccba83a8181c818b8b905003600154038b8b84818110610b3057fe5b90506101200201600060098110610b4357fe5b60200201358c8c85818110610b5457fe5b90506101200201600160098110610b6757fe5b60200201358d8d86818110610b7857fe5b90506101200201600260098110610b8b57fe5b60200201358b8b87818110610b9c57fe5b90506102a00201604051610bb4959493929190612bb8565b60405180910390a1600101610a93565b5050505050505050505050505050565b60046020526000908152604090205481565b6000610bf1896111cb565b905060006002308d888888888e89604051602001610c16989796959493929190612795565b60408051601f1981840301815290829052610c3091612846565b602060405180830381855afa158015610c4d573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250610c709190810190611c4e565b8c356000818152600360209081526040909120549293509091908e01359015610cab5760405162461bcd60e51b815260040161028490612ba8565b600081815260046020526040902054610cd65760405162461bcd60e51b815260040161028490612af8565b6001871115610cf75760405162461bcd60e51b815260040161028490612b28565b868514610d165760405162461bcd60e51b815260040161028490612b88565b86610d9d57600063010000038f8f878f88604051610d389594939291906129cc565b602060405180830381855afa158015610d55573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250610d789190810190611c12565b905080610d975760405162461bcd60e51b815260040161028490612b68565b50610f21565b610f218e600a806020026040519081016040528092919082600a60200280828437600081840152601f19601f8201169050808301925050505050508e6002806020026040519081016040528092919082600260200280828437600081840152601f19601f820116905080830192505050505050868e6002806020026040519081016040528092919082600260200280828437600081840152601f19601f820116905080830192505050505050878d8d808060200260200160405190810160405280939291908181526020016000905b82821015610eae576040805161012081810190925290808402870190600990839083908082843760009201919091525050508152600190910190602001610e6c565b50505050508c8c808060200260200160405190810160405280939291908181526020016000905b82821015610f1757604080516102a081810190925290808402870190601590839083908082843760009201919091525050508152600190910190602001610ed5565b505050505061124e565b60008281526003602052604090819020839055517fd13faa8100906cf559aebacf9c16532cfc9708645c198c8f15798ee049dbcfc190610f62908490612a7d565b60405180910390a16000604960009054906101000a90046001600160a01b03166001600160a01b031663a9059cbb8c8f6040518363ffffffff1660e01b8152600401610faf92919061287a565b602060405180830381600087803b158015610fc957600080fd5b505af1158015610fdd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506110019190810190611c12565b9050806110205760405162461bcd60e51b815260040161028490612b48565b7f1daf70c304f467a9efbc9ac1ca7bfe859a478aa6c4b88131b4dbb1547029b9728b8e8c60405161105393929190612895565b60405180910390a1505050505050505050505050505050565b60025481565b600061107c611842565b600154831061109d5760405162461bcd60e51b815260040161028490612b78565b63ffffffff83016110ac611842565b60006110b7866115ab565b905060006110c587836115fa565b905060005b60208163ffffffff1610156111b4578263ffffffff168163ffffffff16141561110d57818482601f0363ffffffff166020811061110357fe5b60200201526111a2565b600285066111415760056000600187038152602001908152602001600020548482601f0363ffffffff166020811061110357fe5b60018501600090815260056020526040902054156111715760018501600090815260056020526040902054611187565b60288163ffffffff166020811061118457fe5b01545b8482601f0363ffffffff166020811061119c57fe5b60200201525b600260001986010494506001016110ca565b505060025494509092505050915091565b60005481565b60008082116111ec5760405162461bcd60e51b815260040161028490612ac8565b60005461120090839063ffffffff61174c16565b1561121d5760405162461bcd60e51b815260040161028490612ab8565b6000805461123290849063ffffffff61179516565b9050677fffffffffffffff811061124857600080fd5b92915050565b60008260008151811061125d57fe5b602002602001015160006009811061127157fe5b6020020151905060066000828152602001908152602001600020546000801b146112ad5760405162461bcd60e51b815260040161028490612ae8565b604080516001808252818301909252606091816020015b6112cc611861565b8152602001906001900390816112c457905050905088816000815181106112ef57fe5b6020908102919091010152604080516001808252818301909252606091816020015b611319611880565b815260200190600190039081611311579050509050888160008151811061133c57fe5b6020026020010181905250606063010000028383888b8b8e600760015460405161136d98979695949392919061294e565b600060405180830381855afa15801561138a573d6000803e3d6000fd5b5050503d80600081146113b9576040519150601f19603f3d011682016040523d82523d6000602084013e6113be565b606091505b5090506000816000815181106113d057fe5b602002602001015160001c9050806001146113fd5760405162461bcd60e51b815260040161028490612b68565b60008260018151811061140c57fe5b60209081029190910181015160015463ffffffff016000818152600590935260409092208890559150816114405760078790555b60015b826001018110156114b5576002600019830104915084816001018151811061146757fe5b60200260200101516005600084815260200190815260200160002081905550828114156114ad57600082815260056020526040902054600784602181106114aa57fe5b01555b600101611443565b508382600201815181106114c557fe5b602090810291909101810151600281905560008181526004835260408082209290925589815260069092528120889055600180548082019091558a517f3814d251636df4a739162facca3862684b45af01ce54bcc56ea488fa6a69412d928a918d919061152e57fe5b602002602001015160016009811061154257fe5b60200201518c60008151811061155457fe5b602002602001015160026009811061156857fe5b60200201518c60008151811061157a57fe5b6020026020010151604051611593959493929190612bfb565b60405180910390a15050505050505050505050505050565b60015460009063ffffffff83019063fffffffe01825b60026000198301046002600019850104146115f25760026000198401049250600260001983010491506001016115c1565b949350505050565b60015463fffffffe0160008181526005602052604081205490918291829163ffffffff8088019290871661167b578183101561163c5794506112489350505050565b8183141561167b576002830661166b575050600019016000908152600560205260409020549250611248915050565b5050602854935061124892505050565b60005b8763ffffffff168163ffffffff16101561174057600283066116ba576000198301600090815260056020526040902054955090935083906116d5565b81955060288163ffffffff16602081106116d057fe5b015494505b63010000048187876040516116ec93929190612c3e565b602060405180830381855afa158015611709573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525061172c9190810190611c4e565b91506002600019840104925060010161167e565b50979650505050505050565b600061178e83836040518060400160405280601881526020017f536166654d6174683a206d6f64756c6f206279207a65726f00000000000000008152506117d7565b9392505050565b600061178e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061180b565b600081836117f85760405162461bcd60e51b81526004016102849190612aa7565b5082848161180257fe5b06949350505050565b6000818361182c5760405162461bcd60e51b81526004016102849190612aa7565b50600083858161183857fe5b0495945050505050565b6040518061040001604052806020906020820280388339509192915050565b604051806101400160405280600a906020820280388339509192915050565b60405180604001604052806002906020820280388339509192915050565b80356118a981612d93565b61178e81612cbd565b60008083601f8401126118c457600080fd5b50813567ffffffffffffffff8111156118dc57600080fd5b602083019150836101408202830111156118f557600080fd5b9250929050565b60008083601f84011261190e57600080fd5b50813567ffffffffffffffff81111561192657600080fd5b602083019150836102a08202830111156118f557600080fd5b60008083601f84011261195157600080fd5b50813567ffffffffffffffff81111561196957600080fd5b6020830191508360408202830111156118f557600080fd5b60008083601f84011261199357600080fd5b50813567ffffffffffffffff8111156119ab57600080fd5b602083019150836101208202830111156118f557600080fd5b80610140810183101561124857600080fd5b806102a0810183101561124857600080fd5b806040810183101561124857600080fd5b806060810183101561124857600080fd5b80610120810183101561124857600080fd5b805161124881612daa565b803561124881612db3565b805161124881612db3565b600080600080600080600080600060c08a8c031215611a5b57600080fd5b893567ffffffffffffffff811115611a7257600080fd5b611a7e8c828d016118b2565b995099505060208a013567ffffffffffffffff811115611a9d57600080fd5b611aa98c828d0161193f565b975097505060408a013567ffffffffffffffff811115611ac857600080fd5b611ad48c828d01611981565b95509550506060611ae78c828d016119e8565b93505060a08a013567ffffffffffffffff811115611b0457600080fd5b611b108c828d016118fc565b92509250509295985092959850929598565b6000806000806000806000806000806102a08b8d031215611b4257600080fd5b6000611b4e8d8d6119c4565b9a5050610140611b608d828e016119e8565b995050610180611b728d828e01611a27565b9850506101a0611b848d828e016119e8565b9750506101e0611b968d828e0161189e565b965050610200611ba88d828e016119f9565b9550506102608b013567ffffffffffffffff811115611bc657600080fd5b611bd28d828e01611981565b94509450506102808b013567ffffffffffffffff811115611bf257600080fd5b611bfe8d828e016118fc565b92509250509295989b9194979a5092959850565b600060208284031215611c2457600080fd5b60006115f28484611a1c565b600060208284031215611c4257600080fd5b60006115f28484611a27565b600060208284031215611c6057600080fd5b60006115f28484611a32565b6000806000806104208587031215611c8357600080fd5b6000611c8f8787611a27565b9450506020611ca087828801611a0a565b935050610140611cb2878288016119e8565b925050610180611cc4878288016119d6565b91505092959194509250565b6000611cdc838361203e565b50506101400190565b6000611cdc838361204f565b6000611cfd83836120a3565b50506102a00190565b6000611d1283836120fc565b505060400190565b6000611d128383612154565b6000611d32838361224b565b50506101200190565b6000611d328383612258565b6000611d5383836122a4565b505060200190565b611d6481612cbd565b82525050565b611d64611d7682612cbd565b612d55565b6000611d878385612cab565b9350611d9282612c59565b8060005b85811015611dc857611da88284612cb9565b611db28882611cd0565b9750611dbd83612c8a565b925050600101611d96565b509495945050505050565b6000611ddf8385612cb4565b9350611dea82612c59565b8060005b85811015611dc857611e008284612cb9565b611e0a8882611cd0565b9750611e1583612c8a565b925050600101611dee565b6000611e2b82612c62565b611e358185612cab565b9350611e4083612c5c565b8060005b83811015611dc8578151611e588882611ce5565b9750611e6383612c5c565b925050600101611e44565b6000611e7a8385612cb4565b9350611e8582612c59565b8060005b85811015611dc857611e9b8284612cb9565b611ea58882611cf1565b9750611eb083612c91565b925050600101611e89565b6000611ec78385612cab565b9350611ed282612c59565b8060005b85811015611dc857611ee88284612cb9565b611ef28882611d06565b9750611efd83612c98565b925050600101611ed6565b6000611f1382612c62565b611f1d8185612cab565b9350611f2883612c5c565b8060005b83811015611dc8578151611f408882611d1a565b9750611f4b83612c5c565b925050600101611f2c565b6000611f628385612cab565b9350611f6d82612c59565b8060005b85811015611dc857611f838284612cb9565b611f8d8882611d26565b9750611f9883612c9e565b925050600101611f71565b6000611faf8385612cb4565b9350611fba82612c59565b8060005b85811015611dc857611fd08284612cb9565b611fda8882611d26565b9750611fe583612c9e565b925050600101611fbe565b6000611ffb82612c62565b6120058185612cab565b935061201083612c5c565b8060005b83811015611dc85781516120288882611d3b565b975061203383612c5c565b925050600101612014565b61204b6101408383612d06565b5050565b61205881612c66565b6120628184612cb4565b925061206d82612c59565b8060005b8381101561209b5781516120858782611d47565b965061209083612c5c565b925050600101612071565b505050505050565b61204b6102a08383612d06565b6120b981612c6c565b6120c38184612cb4565b92506120ce82612c59565b8060005b8381101561209b5781516120e68782611d47565b96506120f183612c5c565b9250506001016120d2565b61204b60408383612d06565b61211181612c72565b61211b8184612cb4565b925061212682612c59565b8060005b8381101561209b57815161213e8782611d47565b965061214983612c5c565b92505060010161212a565b61215d81612c72565b6121678184612cb4565b925061217282612c59565b8060005b8381101561209b57815161218a8782611d47565b965061219583612c5c565b925050600101612176565b6121a981612c78565b6121b38184612cb4565b92506121be82612c59565b8060005b8381101561209b5781516121d68782611d47565b96506121e183612c5c565b9250506001016121c2565b6121f581612c7e565b6121ff8184612cb4565b925061220a82612c59565b8060005b8381101561209b5761221f82612d71565b6122298782611d47565b965061223483612ca5565b92505060010161220e565b61204b60608383612d06565b61204b6101208383612d06565b61226181612c84565b61226b8184612cb4565b925061227682612c59565b8060005b8381101561209b57815161228e8782611d47565b965061229983612c5c565b92505060010161227a565b611d6481612c59565b60006122b882612c62565b6122c28185612cb4565b93506122d2818560208601612d12565b9290920192915050565b611d6481612cfb565b60006122f082612c62565b6122fa8185612cab565b935061230a818560208601612d12565b61231381612d7d565b9093019392505050565b600061232a603183612cab565b7f56616c7565206d75737420626520696e7465676572206d756c7469706c6573208152706f66207363616c696e67466163746f722160781b602082015260400192915050565b600061237d601783612cab565b7f56616c7565206d75737420626520706f73697469766521000000000000000000815260200192915050565b60006123b6601483612cab565b735472616e7366657246726f6d206661696c65642160601b815260200192915050565b60006123e6601983612cab565b7f4475706c6963617465206e6f7465436f6d6d69746d656e742100000000000000815260200192915050565b600061241f601683612cab565b7554686520616e63686f72206d7573742065786973742160501b815260200192915050565b6000612451603d83612cab565b7f496e707574206e756d626572206d75737420626520657175616c20746f20737081527f656e64417574686f726974795369676e6174757265206e756d62657221000000602082015260400192915050565b60006124b0601d83612cab565b7f4f7574707574206e756d626572206d7573742062652031206f72203221000000815260200192915050565b60006124e9601e83612cab565b7f4f7574707574206e756d6265722063616e6e6f74206578636565642031210000815260200192915050565b6000612522602883612cab565b7f4f7574707574206e756d626572206d75737420626520657175616c20746f2063815267206e756d6265722160c01b602082015260400192915050565b600061256c601083612cab565b6f5472616e73666572206661696c65642160801b815260200192915050565b6000612598601a83612cab565b7f4475706c6963617465206e6f7465436f6d6d69746d656e747321000000000000815260200192915050565b60006125d1603f83612cab565b7f5468652070726f6f6620616e64207369676e61747572652068617665206e6f7481527f206265656e2076657269666965642062792074686520636f6e74726163742100602082015260400192915050565b6000612630602a83612cab565b7f506f736974696f6e2073686f756c6420626520736d616c6c6572207468616e208152696c656166436f756e742160b01b602082015260400192915050565b600061267c602b83612cab565b7f4f7574707574206e756d626572206d75737420626520657175616c20746f206c81526a656e677468206f6620632160a81b602082015260400192915050565b60006126c9601c83612cab565b7f496e707574206e756d626572206d7573742062652031206f7220322100000000815260200192915050565b6000612702602083612cab565b7f546865206e6f74652068617320616c7265616479206265656e207370656e7421815260200192915050565b611d6481612ce5565b611d6481612cee565b611d6461274c82612cee565b612d66565b600061275d828a611d6a565b60148201915061276e82888a611dd3565b915061277b828688611fa3565b9150612788828486611e6e565b9998505050505050505050565b60006127a1828b611d6a565b6014820191506127b1828a61203e565b610140820191506127c382888a611fa3565b91506127d0828688611e6e565b91506127dc8285611d6a565b6014820191506127ec8284612740565b5060080198975050505050505050565b60006128088287611d6a565b6014820191506128188286612740565b600882019150612828828561224b565b6101208201915061283982846120a3565b506102a001949350505050565b600061178e82846122ad565b606081016128608286611d5b565b61286d6020830185611d5b565b6115f260408301846122a4565b604081016128888285611d5b565b61178e60208301846122a4565b60a081016128a38286611d5b565b6128b060208301856122a4565b6115f2604083018461223f565b61052080825281016128d0818d8f611d7b565b905081810360208301526128e5818b8d611ebb565b905081810360408301526128fa81898b611f56565b905061290960608301886120fc565b61291660a08301876122a4565b61292360c08301866122dc565b61293060e08301856121ec565b61293e6105008301846122a4565b9c9b505050505050505050505050565b6105208082528101612960818b611e20565b90508181036020830152612974818a611f08565b905081810360408301526129888189611ff0565b90506129976060830188612108565b6129a460a08301876122a4565b6129b160c0830186612737565b6129be60e08301856121ec565b6127886105008301846122a4565b61020081016129db828861203e565b6129e96101408301876120fc565b6129f7610180830186612737565b612a056101a08301856120fc565b612a136101e08301846122a4565b9695505050505050565b6105e08101612a2c828961224b565b612a3a6101208301886120fc565b612a48610160830187612737565b612a566101808301866122a4565b612a646101a08301856121ec565b612a726105c08301846122a4565b979650505050505050565b6020810161124882846122a4565b6104208101612a9a82856122a4565b61178e60208301846121a0565b6020808252810161178e81846122e5565b602080825281016112488161231d565b6020808252810161124881612370565b60208082528101611248816123a9565b60208082528101611248816123d9565b6020808252810161124881612412565b6020808252810161124881612444565b60208082528101611248816124a3565b60208082528101611248816124dc565b6020808252810161124881612515565b602080825281016112488161255f565b602080825281016112488161258b565b60208082528101611248816125c4565b6020808252810161124881612623565b602080825281016112488161266f565b60208082528101611248816126bc565b60208082528101611248816126f5565b6103208101612bc782886122a4565b612bd460208301876122a4565b612be160408301866122a4565b612bee60608301856122a4565b612a1360808301846120a3565b6103208101612c0a82886122a4565b612c1760208301876122a4565b612c2460408301866122a4565b612c3160608301856122a4565b612a1360808301846120b0565b60608101612c4c828661272e565b61286d60208301856122a4565b90565b60200190565b5190565b50600a90565b50601590565b50600290565b50602090565b50602190565b50600990565b6101400190565b6102a00190565b60400190565b6101200190565b60010190565b90815260200190565b919050565b5090565b600061124882612ccd565b151590565b6001600160a01b031690565b6001600160a81b031690565b63ffffffff1690565b67ffffffffffffffff1690565b600061124882612cee565b82818337506000910152565b60005b83811015612d2d578181015183820152602001612d15565b83811115612d3c576000848401525b50505050565b6000611248612d5083612c59565b612c59565b600061124882600061124882612d8d565b600061124882612d87565b60006112488254612d42565b601f01601f191690565b60c01b90565b60601b90565b612d9c81612cd9565b8114612da757600080fd5b50565b612d9c81612cc8565b612d9c81612c5956fea36474726f6e58207ef421e01e827fa1d2e384579b655503e18aef0f4bf9ff3e5176a254c97da9036c6578706572696d656e74616cf564736f6c637828302e352e31322d646576656c6f702e323032302e362e31352b636f6d6d69742e34323336323638380065" - code_getAddressChange = "608060405260e3806100126000396000f3fe6080604052348015600f57600080fd5b50d38015601b57600080fd5b50d28015602757600080fd5b5060043610604a5760003560e01c806358c6464814604f578063b4cef28d146071575b600080fd5b605560a6565b604080516001600160a01b039092168252519081900360200190f35b609460048036036020811015608557600080fd5b50356001600160a01b031660aa565b60408051918252519081900360200190f35b3090565b50479056fea26474726f6e58208f096542a0e814a7dd8434fd85def0ee9521b022f5cad9176f1c993e2615bdad64736f6c634300050f0031" - code_fallbackOldVersionTest = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b506101d98061003a6000396000f3fe60c0604052600860808190526766616c6c6261636b60c01b60a0908152610029916000919061010a565b506040805181815260008054600260001961010060018416150201909116049282018390527f1f0af026fd1015e37743a803fa8c7b92c09a6fc99890b1681a1e3c888427c25e9290918291369190819060208201906060830190869080156100d25780601f106100a7576101008083540402835291602001916100d2565b820191906000526020600020905b8154815290600101906020018083116100b557829003601f168201915b50508381038252848152602001858580828437600083820152604051601f909101601f191690920182900397509095505050505050a1005b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061014b57805160ff1916838001178555610178565b82800160010185558215610178579182015b8281111561017857825182559160200191906001019061015d565b50610184929150610188565b5090565b6101a291905b80821115610184576000815560010161018e565b9056fea26474726f6e5820e77b862582c00095aa34fd5c2839c0d8f209bdac194c0adeec660fa15a08fbe464736f6c634300050f0031" - code_fallbackOldVersionCall = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b506101748061003a6000396000f3fe60806040526004361061001e5760003560e01c8063f55332ab14610023575b600080fd5b6100496004803603602081101561003957600080fd5b50356001600160a01b031661005d565b604080519115158252519081900360200190f35b60408051600481526024810182526020810180516001600160e01b031663f85396d760e01b1781529151815160009384936001600160a01b038716939092909182918083835b602083106100c25780518252601f1990920191602091820191016100a3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610124576040519150601f19603f3d011682016040523d82523d6000602084013e610129565b606091505b505090508061013757600080fd5b5060019291505056fea26474726f6e58203498e1c23a661ae640e44836405d25839850ec79748cabd2dab945fd13ee0c7c64736f6c634300050f0031" - code_arrayLength_0.5.15 = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b506102708061003a6000396000f3fe608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b50600436106100455760003560e01c8063cbcec91e1461004a575b600080fd5b6100526100a2565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561008e578181015183820152602001610076565b505050509050019250505060405180910390f35b60008054600181018255818052602081047f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56301805460ff601f9093166101000a928302191690911790556060906003906100fc90826101e5565b50600080549061010f90600183016101e5565b5060008054906101239060001983016101e5565b5060008054906101379060001983016101e5565b50600080548061014357fe5b60008281526020808220600019909301818104909301805460ff601f86166101000a0219169055919092558154604080518284028101840190915281815292918301828280156101da57602002820191906000526020600020906000905b825461010083900a900460f81b6001600160f81b0319168152602060019283018181049485019490930390920291018084116101a15790505b505050505090505b90565b81548183558181111561021957601f016020900481601f01602090048360005260206000209182019101610219919061021e565b505050565b6101e291905b808211156102385760008155600101610224565b509056fea26474726f6e582030f1b13e292e442f2c4de67e0d5bb6f78dd7f44f99e5f2fa3952de6c9d94dd8b64736f6c634300050e0031" - code_override001 = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b5060d8806100396000396000f3fe6080604052348015600f57600080fd5b50d38015601b57600080fd5b50d28015602757600080fd5b506004361060545760003560e01c80630c55699c14605957806355241077146071578063a56dfe4a14608d575b600080fd5b605f6093565b60408051918252519081900360200190f35b608b60048036036020811015608557600080fd5b50356099565b005b605f609e565b60005481565b600155565b6001548156fea26474726f6e58204b9c06785956097a789fe5d4b75dbe9390a30c48c3080d3c14d8655cb84e11e564736f6c634300050f0031" - code_override002 = "6080604052600460005534801561001557600080fd5b50d3801561002257600080fd5b50d2801561002f57600080fd5b5061012b8061003f6000396000f3fe6080604052348015600f57600080fd5b50d38015601b57600080fd5b50d28015602757600080fd5b506004361060545760003560e01c80630c55699c1460595780635524107714607157806374d393f014608d575b600080fd5b605f60a7565b60408051918252519081900360200190f35b608b60048036036020811015608557600080fd5b503560ad565b005b608b6004803603602081101560a157600080fd5b503560f2565b60005481565b6006600054101560f2576040805162461bcd60e51b815260206004820152600b60248201526a3c1036bab9ba101f1e901b60a91b604482015290519081900360640190fd5b60005556fea26474726f6e5820d72f89553adaa33af6034260ea794957bdaebd8e26bccaac25c685c1bd1e8f2764736f6c634300050f0031" - code_override003 = "608060405260008054600160ff19918216811761ff0019169092556301efa6ad9091556301efa6ac19600255630166654f6003908155600480546001600160a01b03191673dcad3a6d3569df655070ded06cb7a1b2ccd1d3af1790557fb55a21aaee0ce8f1c8ffaa0dbd23105cb55a21aaee0ce8f1c8ffaa0dbd23105c6005556006805490921617905534801561009557600080fd5b50d380156100a257600080fd5b50d280156100af57600080fd5b506101c8806100bf6000396000f3fe608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b50600436106100a25760003560e01c806398f42fe31161007557806398f42fe31461012d578063a223e05d14610135578063e5aa3d581461013d578063f8aab23814610145576100a2565b806375f12b21146100a757806383cdfab8146100c357806387cfa5bf146100dd578063938b5f3214610109575b600080fd5b6100af61014d565b604080519115158252519081900360200190f35b6100cb61015b565b60408051918252519081900360200190f35b6100e5610161565b604051808260038111156100f557fe5b60ff16815260200191505060405180910390f35b61011161016a565b604080516001600160a01b039092168252519081900360200190f35b6100e5610179565b6100cb610182565b6100cb610188565b6100cb61018e565b600054610100900460ff1681565b60025481565b60005460ff1681565b6004546001600160a01b031681565b60065460ff1681565b60035481565b60015481565b6005548156fea26474726f6e5820dacca6ecfb02875aede259b98aa35a6aba6aea8284a01f0c82fdeba6ffc8012d64736f6c634300050f0031" - code_virtual001 = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b506103778061003a6000396000f3fe608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b506004361061007c5760003560e01c80630c55699c146100815780631e26fd331461009b57806355241077146100bc5780637fcaf666146100d9578063a56dfe4a14610149578063c5d7802e14610165575b600080fd5b6100896101e2565b60408051918252519081900360200190f35b6100ba600480360360208110156100b157600080fd5b503515156101e8565b005b6100ba600480360360208110156100d257600080fd5b50356101fb565b6100ba600480360360208110156100ef57600080fd5b81019060208101813564010000000081111561010a57600080fd5b82018360208201111561011c57600080fd5b8035906020019184600183028401116401000000008311171561013e57600080fd5b509092509050610200565b610151610211565b604080519115158252519081900360200190f35b61016d61021a565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101a757818101518382015260200161018f565b50505050905090810190601f1680156101d45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60015481565b6002805460ff1916911515919091179055565b600155565b61020c600083836102a8565b505050565b60025460ff1681565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156102a05780601f10610275576101008083540402835291602001916102a0565b820191906000526020600020905b81548152906001019060200180831161028357829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106102e95782800160ff19823516178555610316565b82800160010185558215610316579182015b828111156103165782358255916020019190600101906102fb565b50610322929150610326565b5090565b61034091905b80821115610322576000815560010161032c565b9056fea26474726f6e5820b48ac0b0a646831f6a4069f95888081a6e12cd0ffb453b66d879c3f04e3b71ec64736f6c634300050f0031" - code_slotAndOffset_06x = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b5060ba806100396000396000f3fe6080604052348015600f57600080fd5b50d38015601b57600080fd5b50d28015602757600080fd5b5060043610604a5760003560e01c8063b1cb267b14604f578063d46300fd14606e575b600080fd5b60556074565b6040805192835260208301919091528051918290030190f35b6055607c565b600460009091565b60016000909156fea264697066735822122076bb65351c887d12efbc6982560551c4979591981777ea571d32f7f267f8888864736f6c634300060c0033" -} - - -abi = { - abi_Scenario015_TRC20_TRON = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"view\"},{\"constant\":false,\"inputs\":[],\"name\":\"stop\",\"outputs\":[],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"nonpayable\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"nonpayable\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"view\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"nonpayable\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"view\"},{\"constant\":false,\"inputs\":[{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"nonpayable\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"view\"},{\"constant\":true,\"inputs\":[],\"name\":\"stopped\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"view\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"view\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"nonpayable\"},{\"constant\":false,\"inputs\":[],\"name\":\"start\",\"outputs\":[],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"nonpayable\"},{\"constant\":false,\"inputs\":[{\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"nonpayable\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"view\"},{\"inputs\":[],\"payable\":false,\"type\":\"constructor\",\"stateMutability\":\"nonpayable\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"}]" - abi_AssertException_testdivideInt = "[{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"int256\"},{\"name\":\"y\",\"type\":\"int256\"}],\"name\":\"divideIHaveArgsReturn\",\"outputs\":[{\"name\":\"z\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_AssertException_testfindArgsContractMinTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"i\",\"type\":\"uint256\"}],\"name\":\"findArgsByIndexTest\",\"outputs\":[{\"name\":\"z\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_AssertException_testbyteMinContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"i\",\"type\":\"uint256\"}],\"name\":\"testBytesGet\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes1\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_AssertException_testenum = "[{\"constant\":true,\"inputs\":[],\"name\":\"getChoice\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"choice\",\"type\":\"uint8\"}],\"name\":\"setGoStraight\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_AssertException_testmoveRight = "[{\"constant\":false,\"inputs\":[{\"name\":\"i\",\"type\":\"int256\"}],\"name\":\"binaryMoveR\",\"outputs\":[{\"name\":\"z\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_AssertException_testuninitializedContract = "[{\"constant\":false,\"inputs\":[],\"name\":\"test2\",\"outputs\":[{\"name\":\"\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"test1\",\"outputs\":[{\"name\":\"\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_AssertException_testTestAssertContract = "[{\"constant\":false,\"inputs\":[],\"name\":\"testAssert\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"testRequire\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"testThrow\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"testRevert\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - - abi_ContractGrammar001_testGrammar001 = "[{\"constant\":false,\"inputs\":[{\"name\":\"useB\",\"type\":\"bool\"},{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"select\",\"outputs\":[{\"name\":\"z\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"b\",\"outputs\":[{\"name\":\"z\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"a\",\"outputs\":[{\"name\":\"z\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_ContractGrammar001_testGrammar002 = "[{\"constant\":false,\"inputs\":[{\"name\":\"self\",\"type\":\"Set.Data storage\"},{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"remove\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"self\",\"type\":\"Set.Data storage\"},{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"contains\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"self\",\"type\":\"Set.Data storage\"},{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"insert\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi1_ContractGrammar001_testGrammar002 = "[{\"constant\":false,\"inputs\":[{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"register\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_ContractGrammar001_testGrammar003 = "[{\"constant\":false,\"inputs\":[{\"name\":\"self\",\"type\":\"Set.Data storage\"},{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"remove\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"self\",\"type\":\"Set.Data storage\"},{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"contains\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"self\",\"type\":\"Set.Data storage\"},{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"insert\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi1_ContractGrammar001_testGrammar003 = "[{\"constant\":false,\"inputs\":[{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"register\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_ContractGrammar001_testGrammar004 = "[{\"constant\":false,\"inputs\":[{\"name\":\"self\",\"type\":\"uint256[] storage\"},{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"indexOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi1_ContractGrammar001_testGrammar004 = "[{\"constant\":false,\"inputs\":[{\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"append\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_old\",\"type\":\"uint256\"},{\"name\":\"_new\",\"type\":\"uint256\"}],\"name\":\"replace\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"data\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]" - abi_ContractGrammar001_testGrammar006 = "[{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"d4\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"d\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"d5\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"f\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"d6\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"d1\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"d2\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - - abi_ContractGrammar002_testGrammar007 = "[{\"constant\":true,\"inputs\":[{\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"getDougName\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_age\",\"type\":\"uint256\"}],\"name\":\"getDougAge\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"contracts\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]" - abi1_ContractGrammar002_testGrammar007 = "[{\"constant\":false,\"inputs\":[{\"name\":\"_name\",\"type\":\"bytes32\"}],\"name\":\"uintOfName\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_doug\",\"type\":\"address\"}],\"name\":\"setDOUG\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_age\",\"type\":\"uint256\"}],\"name\":\"dougOfage\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"dogInterfaceAddress\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"name\",\"type\":\"bytes32\"}],\"name\":\"FetchContract\",\"type\":\"event\"}]" - abi_ContractGrammar002_testGrammar008 = "[{\"constant\":false,\"inputs\":[],\"name\":\"utterance\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"getContractName\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_ContractGrammar002_testGrammar010 = "[{\"constant\":false,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"setFeed\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"callFeed\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_ContractGrammar002_testGrammar011 = "[{\"constant\":false,\"inputs\":[{\"name\":\"key\",\"type\":\"uint256\"},{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"f\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"g\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_ContractGrammar002_testGrammar012 = "[{\"constant\":false,\"inputs\":[],\"name\":\"info\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"bytes4\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"}]" - abi_ContractGrammar002_testGrammar013 = "[{\"constant\":false,\"inputs\":[],\"name\":\"kill\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"getCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"increment\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]" - - abi_ContractGrammar003_testGrammar014 = "[{\"constant\":false,\"inputs\":[{\"name\":\"bAddress\",\"type\":\"address\"},{\"name\":\"_number\",\"type\":\"uint256\"}],\"name\":\"delegatecallTest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"bAddress\",\"type\":\"address\"},{\"name\":\"_number\",\"type\":\"uint256\"}],\"name\":\"callTest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"senderForB\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"getsenderForB\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"bAddress\",\"type\":\"address\"},{\"name\":\"_number\",\"type\":\"uint256\"}],\"name\":\"callcodeTest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"numberForB\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"bAddress\",\"type\":\"address\"}],\"name\":\"callAddTest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"getnumberForB\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi1_ContractGrammar003_testGrammar014 = "[{\"constant\":true,\"inputs\":[],\"name\":\"addr11\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"addr2\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"addr1\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"add\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_number\",\"type\":\"uint256\"}],\"name\":\"setValue\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"senderForB\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"getsenderForB\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"numberForB\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"getnumberForB\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_ContractGrammar003_testGrammar015 = "[{\"constant\":true,\"inputs\":[],\"name\":\"ExistFuncCalledTopic\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"para\",\"type\":\"uint256\"}],\"name\":\"existFunc\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"FallbackCalledTopic\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"callNonExistFunc\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"callExistFunc\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"FallbackCalled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"data\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"para\",\"type\":\"uint256\"}],\"name\":\"ExistFuncCalled\",\"type\":\"event\"}]" - abi_ContractGrammar003_testGrammar016 = "[{\"constant\":false,\"inputs\":[],\"name\":\"readData\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi1_ContractGrammar003_testGrammar016 = "[{\"constant\":false,\"inputs\":[],\"name\":\"getData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"setData\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"g\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_ContractGrammar003_testGrammar017 = "[{\"constant\":false,\"inputs\":[{\"name\":\"compaingnID\",\"type\":\"uint256\"}],\"name\":\"vote\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"comapingnId\",\"type\":\"uint256\"}],\"name\":\"check\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"beneficiary\",\"type\":\"address\"},{\"name\":\"goal\",\"type\":\"uint256\"}],\"name\":\"candidate\",\"outputs\":[{\"name\":\"compaingnID\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_ContractGrammar003_testGrammar018 = "[{\"constant\":false,\"inputs\":[],\"name\":\"testKeccak256\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"testMulmod\",\"outputs\":[{\"name\":\"z\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"testAddmod\",\"outputs\":[{\"name\":\"z\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"testSha256\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"testRipemd160\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"testSha3\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_ContractGrammar003_testGrammar019 = "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]" - abi_ContractGrammar003_testGrammar020 = "[{\"constant\":false,\"inputs\":[],\"name\":\"timetest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_ContractScenario004_deployErc20TronToken = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"stop\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"stopped\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"start\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_addressFounder\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"}]" - abi_ContractScenario005_deployIcoContract = "[{\"constant\":false,\"inputs\":[],\"name\":\"checkGoalReached\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"deadline\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"beneficiary\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"tokenReward\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"fundingGoal\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"amountRaised\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"price\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"safeWithdrawal\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"ifSuccessfulSendTo\",\"type\":\"address\"},{\"name\":\"fundingGoalInEthers\",\"type\":\"uint256\"},{\"name\":\"durationInMinutes\",\"type\":\"uint256\"},{\"name\":\"finneyCostOfEachToken\",\"type\":\"uint256\"},{\"name\":\"addressOfTokenUsedAsReward\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"totalAmountRaised\",\"type\":\"uint256\"}],\"name\":\"GoalReached\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"backer\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"isContribution\",\"type\":\"bool\"}],\"name\":\"FundTransfer\",\"type\":\"event\"}]" - abi_ContractScenario006_deployFomo3D = "[{\"constant\":true,\"inputs\":[{\"name\":\"_customerAddress\",\"type\":\"address\"}],\"name\":\"dividendsOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_ethereumToSpend\",\"type\":\"uint256\"}],\"name\":\"calculateTokensReceived\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokensToSell\",\"type\":\"uint256\"}],\"name\":\"calculateEthereumReceived\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"onlyAmbassadors\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"administrators\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"withdraw\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"sellPrice\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"stakingRequirement\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_includeReferralBonus\",\"type\":\"bool\"}],\"name\":\"myDividends\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalEthereumBalance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_customerAddress\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_amountOfTokens\",\"type\":\"uint256\"}],\"name\":\"setStakingRequirement\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"buyPrice\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_identifier\",\"type\":\"bytes32\"},{\"name\":\"_status\",\"type\":\"bool\"}],\"name\":\"setAdministrator\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"Hourglass\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"myTokens\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"disableInitialStage\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_toAddress\",\"type\":\"address\"},{\"name\":\"_amountOfTokens\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_symbol\",\"type\":\"string\"}],\"name\":\"setSymbol\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_amountOfTokens\",\"type\":\"uint256\"}],\"name\":\"sell\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"exit\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_referredBy\",\"type\":\"address\"}],\"name\":\"buy\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"reinvest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"customerAddress\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"incomingEthereum\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"tokensMinted\",\"type\":\"uint256\"},{\"indexed\":true,\"name\":\"referredBy\",\"type\":\"address\"}],\"name\":\"onTokenPurchase\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"customerAddress\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"tokensBurned\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"ethereumEarned\",\"type\":\"uint256\"}],\"name\":\"onTokenSell\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"customerAddress\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"ethereumReinvested\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"tokensMinted\",\"type\":\"uint256\"}],\"name\":\"onReinvestment\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"customerAddress\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"ethereumWithdrawn\",\"type\":\"uint256\"}],\"name\":\"onWithdraw\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"}]" - abi_ContractScenario007_deployErc721CardMigration = "[{\"constant\":true,\"inputs\":[{\"name\":\"_interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"id\",\"type\":\"uint16\"}],\"name\":\"getProto\",\"outputs\":[{\"name\":\"exists\",\"type\":\"bool\"},{\"name\":\"god\",\"type\":\"uint8\"},{\"name\":\"season\",\"type\":\"uint8\"},{\"name\":\"cardType\",\"type\":\"uint8\"},{\"name\":\"rarity\",\"type\":\"uint8\"},{\"name\":\"mana\",\"type\":\"uint8\"},{\"name\":\"attack\",\"type\":\"uint8\"},{\"name\":\"health\",\"type\":\"uint8\"},{\"name\":\"tribe\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"to\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"from\",\"type\":\"address\"},{\"name\":\"to\",\"type\":\"address\"},{\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"transferAllFrom\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"migrated\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"burnAll\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"InterfaceId_ERC165\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes4\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"season\",\"type\":\"uint8\"}],\"name\":\"makePermanantlyTradable\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"from\",\"type\":\"address\"},{\"name\":\"to\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"externalID\",\"type\":\"uint16\"},{\"name\":\"god\",\"type\":\"uint8\"},{\"name\":\"rarity\",\"type\":\"uint8\"},{\"name\":\"mana\",\"type\":\"uint8\"},{\"name\":\"packable\",\"type\":\"bool\"}],\"name\":\"addSpell\",\"outputs\":[{\"name\":\"\",\"type\":\"uint16\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"common\",\"outputs\":[{\"name\":\"\",\"type\":\"uint16\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getActiveCards\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"migrate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"mythic\",\"outputs\":[{\"name\":\"\",\"type\":\"uint16\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"exists\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"tokenByIndex\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"index\",\"type\":\"uint16\"},{\"name\":\"god\",\"type\":\"uint8\"},{\"name\":\"cardType\",\"type\":\"uint8\"},{\"name\":\"mana\",\"type\":\"uint8\"},{\"name\":\"attack\",\"type\":\"uint8\"},{\"name\":\"health\",\"type\":\"uint8\"},{\"name\":\"tribe\",\"type\":\"uint8\"}],\"name\":\"replaceProto\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"burnCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"name\":\"seasonTradabilityLocked\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"id\",\"type\":\"uint16\"},{\"name\":\"limit\",\"type\":\"uint64\"}],\"name\":\"setLimit\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"to\",\"type\":\"address\"},{\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"transferAll\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"name\":\"seasonTradable\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"proposed\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"owns\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"approved\",\"type\":\"address\"}],\"name\":\"addPack\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"purity\",\"type\":\"uint16\"}],\"name\":\"getShine\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"cards\",\"outputs\":[{\"name\":\"proto\",\"type\":\"uint16\"},{\"name\":\"purity\",\"type\":\"uint16\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"migrateAll\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getCard\",\"outputs\":[{\"name\":\"proto\",\"type\":\"uint16\"},{\"name\":\"purity\",\"type\":\"uint16\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"id\",\"type\":\"uint16\"}],\"name\":\"getLimit\",\"outputs\":[{\"name\":\"limit\",\"type\":\"uint64\"},{\"name\":\"set\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint16\"}],\"name\":\"limits\",\"outputs\":[{\"name\":\"limit\",\"type\":\"uint64\"},{\"name\":\"exists\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"NAME\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"rare\",\"outputs\":[{\"name\":\"\",\"type\":\"uint16\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"proto\",\"type\":\"uint16\"}],\"name\":\"isTradable\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"to\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"proposed\",\"type\":\"address\"},{\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"ownsAll\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"tokenMetadataBaseURI\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"packs\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"nextSeason\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"currentSeason\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_gov\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"season\",\"type\":\"uint8\"}],\"name\":\"makeUntradable\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"rarity\",\"type\":\"uint8\"},{\"name\":\"random\",\"type\":\"uint16\"}],\"name\":\"getRandomCard\",\"outputs\":[{\"name\":\"\",\"type\":\"uint16\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"externalID\",\"type\":\"uint16\"},{\"name\":\"god\",\"type\":\"uint8\"},{\"name\":\"rarity\",\"type\":\"uint8\"},{\"name\":\"mana\",\"type\":\"uint8\"},{\"name\":\"attack\",\"type\":\"uint8\"},{\"name\":\"durability\",\"type\":\"uint8\"},{\"name\":\"packable\",\"type\":\"bool\"}],\"name\":\"addWeapon\",\"outputs\":[{\"name\":\"\",\"type\":\"uint16\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"externalID\",\"type\":\"uint16\"},{\"name\":\"god\",\"type\":\"uint8\"},{\"name\":\"rarity\",\"type\":\"uint8\"},{\"name\":\"mana\",\"type\":\"uint8\"},{\"name\":\"attack\",\"type\":\"uint8\"},{\"name\":\"health\",\"type\":\"uint8\"},{\"name\":\"cardType\",\"type\":\"uint8\"},{\"name\":\"tribe\",\"type\":\"uint8\"},{\"name\":\"packable\",\"type\":\"bool\"}],\"name\":\"addProto\",\"outputs\":[{\"name\":\"\",\"type\":\"uint16\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"protoCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint16\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"epic\",\"outputs\":[{\"name\":\"\",\"type\":\"uint16\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"externalID\",\"type\":\"uint16\"},{\"name\":\"god\",\"type\":\"uint8\"},{\"name\":\"rarity\",\"type\":\"uint8\"},{\"name\":\"mana\",\"type\":\"uint8\"},{\"name\":\"attack\",\"type\":\"uint8\"},{\"name\":\"health\",\"type\":\"uint8\"},{\"name\":\"tribe\",\"type\":\"uint8\"},{\"name\":\"packable\",\"type\":\"bool\"}],\"name\":\"addMinion\",\"outputs\":[{\"name\":\"\",\"type\":\"uint16\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"externalIDs\",\"type\":\"uint16[]\"},{\"name\":\"gods\",\"type\":\"uint8[]\"},{\"name\":\"rarities\",\"type\":\"uint8[]\"},{\"name\":\"manas\",\"type\":\"uint8[]\"},{\"name\":\"attacks\",\"type\":\"uint8[]\"},{\"name\":\"healths\",\"type\":\"uint8[]\"},{\"name\":\"cardTypes\",\"type\":\"uint8[]\"},{\"name\":\"tribes\",\"type\":\"uint8[]\"},{\"name\":\"packable\",\"type\":\"bool[]\"}],\"name\":\"addProtos\",\"outputs\":[{\"name\":\"\",\"type\":\"uint16\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBurnCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"legendary\",\"outputs\":[{\"name\":\"\",\"type\":\"uint16\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"to\",\"type\":\"address\"},{\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"approveAll\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"season\",\"type\":\"uint8\"}],\"name\":\"makeTradable\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"SYMBOL\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"owner\",\"type\":\"address\"},{\"name\":\"proto\",\"type\":\"uint16\"},{\"name\":\"purity\",\"type\":\"uint16\"}],\"name\":\"createCard\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"previous\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"proto\",\"type\":\"uint16\"},{\"indexed\":false,\"name\":\"purity\",\"type\":\"uint16\"},{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"CardCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_approved\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_operator\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"id\",\"type\":\"uint16\"},{\"indexed\":false,\"name\":\"season\",\"type\":\"uint8\"},{\"indexed\":false,\"name\":\"god\",\"type\":\"uint8\"},{\"indexed\":false,\"name\":\"rarity\",\"type\":\"uint8\"},{\"indexed\":false,\"name\":\"mana\",\"type\":\"uint8\"},{\"indexed\":false,\"name\":\"attack\",\"type\":\"uint8\"},{\"indexed\":false,\"name\":\"health\",\"type\":\"uint8\"},{\"indexed\":false,\"name\":\"cardType\",\"type\":\"uint8\"},{\"indexed\":false,\"name\":\"tribe\",\"type\":\"uint8\"},{\"indexed\":false,\"name\":\"packable\",\"type\":\"bool\"}],\"name\":\"NewProtoCard\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Pause\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Unpause\",\"type\":\"event\"}]" - abi_ContractScenario008_deployErc721CryptoKitties = "[{\"constant\":true,\"inputs\":[{\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"cfoAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"name\":\"_preferredTransport\",\"type\":\"string\"}],\"name\":\"tokenMetadata\",\"outputs\":[{\"name\":\"infoUrl\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"promoCreatedCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"ceoAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GEN0_STARTING_PRICE\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setSiringAuctionAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pregnantKitties\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_kittyId\",\"type\":\"uint256\"}],\"name\":\"isPregnant\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GEN0_AUCTION_DURATION\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"siringAuction\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setGeneScienceAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newCEO\",\"type\":\"address\"}],\"name\":\"setCEO\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newCOO\",\"type\":\"address\"}],\"name\":\"setCOO\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_kittyId\",\"type\":\"uint256\"},{\"name\":\"_startingPrice\",\"type\":\"uint256\"},{\"name\":\"_endingPrice\",\"type\":\"uint256\"},{\"name\":\"_duration\",\"type\":\"uint256\"}],\"name\":\"createSaleAuction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"sireAllowedToAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_matronId\",\"type\":\"uint256\"},{\"name\":\"_sireId\",\"type\":\"uint256\"}],\"name\":\"canBreedWith\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"kittyIndexToApproved\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_kittyId\",\"type\":\"uint256\"},{\"name\":\"_startingPrice\",\"type\":\"uint256\"},{\"name\":\"_endingPrice\",\"type\":\"uint256\"},{\"name\":\"_duration\",\"type\":\"uint256\"}],\"name\":\"createSiringAuction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"setAutoBirthFee\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_addr\",\"type\":\"address\"},{\"name\":\"_sireId\",\"type\":\"uint256\"}],\"name\":\"approveSiring\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newCFO\",\"type\":\"address\"}],\"name\":\"setCFO\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_genes\",\"type\":\"uint256\"},{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"createPromoKitty\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"secs\",\"type\":\"uint256\"}],\"name\":\"setSecondsPerBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"withdrawBalance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"name\":\"owner\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GEN0_CREATION_LIMIT\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"newContractAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setSaleAuctionAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"count\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_v2Address\",\"type\":\"address\"}],\"name\":\"setNewAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"secondsPerBlock\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"tokensOfOwner\",\"outputs\":[{\"name\":\"ownerTokens\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_matronId\",\"type\":\"uint256\"}],\"name\":\"giveBirth\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"withdrawAuctionBalances\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"cooldowns\",\"outputs\":[{\"name\":\"\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"kittyIndexToOwner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"cooAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"autoBirthFee\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"erc721Metadata\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_genes\",\"type\":\"uint256\"}],\"name\":\"createGen0Auction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_kittyId\",\"type\":\"uint256\"}],\"name\":\"isReadyToBreed\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"PROMO_CREATION_LIMIT\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_contractAddress\",\"type\":\"address\"}],\"name\":\"setMetadataAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"saleAuction\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_id\",\"type\":\"uint256\"}],\"name\":\"getKitty\",\"outputs\":[{\"name\":\"isGestating\",\"type\":\"bool\"},{\"name\":\"isReady\",\"type\":\"bool\"},{\"name\":\"cooldownIndex\",\"type\":\"uint256\"},{\"name\":\"nextActionAt\",\"type\":\"uint256\"},{\"name\":\"siringWithId\",\"type\":\"uint256\"},{\"name\":\"birthTime\",\"type\":\"uint256\"},{\"name\":\"matronId\",\"type\":\"uint256\"},{\"name\":\"sireId\",\"type\":\"uint256\"},{\"name\":\"generation\",\"type\":\"uint256\"},{\"name\":\"genes\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_sireId\",\"type\":\"uint256\"},{\"name\":\"_matronId\",\"type\":\"uint256\"}],\"name\":\"bidOnSiringAuction\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"gen0CreatedCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"geneScience\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_matronId\",\"type\":\"uint256\"},{\"name\":\"_sireId\",\"type\":\"uint256\"}],\"name\":\"breedWithAuto\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"matronId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"sireId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"cooldownEndBlock\",\"type\":\"uint256\"}],\"name\":\"Pregnant\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"kittyId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"matronId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"sireId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"genes\",\"type\":\"uint256\"}],\"name\":\"Birth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"newContract\",\"type\":\"address\"}],\"name\":\"ContractUpgrade\",\"type\":\"event\"}]" - abi_ContractScenario009_deployContainLibraryContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"self\",\"type\":\"Set.Data storage\"},{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"remove\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"self\",\"type\":\"Set.Data storage\"},{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"contains\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"self\",\"type\":\"Set.Data storage\"},{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"insert\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_ContractScenario010_deployContainLibraryContract = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"name\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"supply\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"name\":\"owner\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenMetadata\",\"outputs\":[{\"name\":\"infoUrl\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"symbol\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"takeOwnership\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_approved\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"}]" - abi_ContractScenario012_deployTransactionCoin = "[{\"constant\":false,\"inputs\":[],\"name\":\"getBalance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"n\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"sendToAddress\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"user\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"nPlusOne\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"depositOneCoin\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"money\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"sendToAddress2\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getSenderBalance\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_ContractScenario013_deployTronTrxAndSunContract = "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]" - abi_ContractScenario013_triggerTronTrxAndSunContract = "[{\"constant\":false,\"inputs\":[],\"name\":\"time\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_ContractScenario014_testTripleTrigger = "[{\"constant\":false,\"inputs\":[{\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"send5SunToReceiver\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi1_ContractScenario014_testTripleTrigger = "[{\"constant\":false,\"inputs\":[{\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"triggerContract1ButRevert\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"triggerContract1\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"payContract\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_add\",\"type\":\"address\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi2_ContractScenario014_testTripleTrigger = "[{\"constant\":false,\"inputs\":[{\"name\":\"_receiver\",\"type\":\"address\"}],\"name\":\"triggerContract2\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"payContract\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_add\",\"type\":\"address\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_TronDice_tronDice = "[{\"constant\":false,\"inputs\":[],\"name\":\"withdraw\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_point\",\"type\":\"uint256\"}],\"name\":\"rollDice\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"deposit\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"ownerkill\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getPendingBalane\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_amount\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_point\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_random\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_P\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_O\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_W\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_B\",\"type\":\"uint256\"}],\"name\":\"UserWin\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_amount\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_point\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_random\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_B\",\"type\":\"uint256\"}],\"name\":\"UserLose\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_balance\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_reward\",\"type\":\"uint256\"}],\"name\":\"RollDice\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"}]" - abi_TvmContract_deployErc721CryptoKitties = "[{\"constant\":true,\"inputs\":[{\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"cfoAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"name\":\"_preferredTransport\",\"type\":\"string\"}],\"name\":\"tokenMetadata\",\"outputs\":[{\"name\":\"infoUrl\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"promoCreatedCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"ceoAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GEN0_STARTING_PRICE\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setSiringAuctionAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pregnantKitties\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_kittyId\",\"type\":\"uint256\"}],\"name\":\"isPregnant\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GEN0_AUCTION_DURATION\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"siringAuction\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setGeneScienceAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newCEO\",\"type\":\"address\"}],\"name\":\"setCEO\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newCOO\",\"type\":\"address\"}],\"name\":\"setCOO\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_kittyId\",\"type\":\"uint256\"},{\"name\":\"_startingPrice\",\"type\":\"uint256\"},{\"name\":\"_endingPrice\",\"type\":\"uint256\"},{\"name\":\"_duration\",\"type\":\"uint256\"}],\"name\":\"createSaleAuction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"sireAllowedToAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_matronId\",\"type\":\"uint256\"},{\"name\":\"_sireId\",\"type\":\"uint256\"}],\"name\":\"canBreedWith\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"kittyIndexToApproved\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_kittyId\",\"type\":\"uint256\"},{\"name\":\"_startingPrice\",\"type\":\"uint256\"},{\"name\":\"_endingPrice\",\"type\":\"uint256\"},{\"name\":\"_duration\",\"type\":\"uint256\"}],\"name\":\"createSiringAuction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"setAutoBirthFee\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_addr\",\"type\":\"address\"},{\"name\":\"_sireId\",\"type\":\"uint256\"}],\"name\":\"approveSiring\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newCFO\",\"type\":\"address\"}],\"name\":\"setCFO\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_genes\",\"type\":\"uint256\"},{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"createPromoKitty\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"secs\",\"type\":\"uint256\"}],\"name\":\"setSecondsPerBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"withdrawBalance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"name\":\"owner\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GEN0_CREATION_LIMIT\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"newContractAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setSaleAuctionAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"count\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_v2Address\",\"type\":\"address\"}],\"name\":\"setNewAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"secondsPerBlock\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"tokensOfOwner\",\"outputs\":[{\"name\":\"ownerTokens\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_matronId\",\"type\":\"uint256\"}],\"name\":\"giveBirth\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"withdrawAuctionBalances\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"cooldowns\",\"outputs\":[{\"name\":\"\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"kittyIndexToOwner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"cooAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"autoBirthFee\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"erc721Metadata\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_genes\",\"type\":\"uint256\"}],\"name\":\"createGen0Auction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_kittyId\",\"type\":\"uint256\"}],\"name\":\"isReadyToBreed\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"PROMO_CREATION_LIMIT\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_contractAddress\",\"type\":\"address\"}],\"name\":\"setMetadataAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"saleAuction\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_id\",\"type\":\"uint256\"}],\"name\":\"getKitty\",\"outputs\":[{\"name\":\"isGestating\",\"type\":\"bool\"},{\"name\":\"isReady\",\"type\":\"bool\"},{\"name\":\"cooldownIndex\",\"type\":\"uint256\"},{\"name\":\"nextActionAt\",\"type\":\"uint256\"},{\"name\":\"siringWithId\",\"type\":\"uint256\"},{\"name\":\"birthTime\",\"type\":\"uint256\"},{\"name\":\"matronId\",\"type\":\"uint256\"},{\"name\":\"sireId\",\"type\":\"uint256\"},{\"name\":\"generation\",\"type\":\"uint256\"},{\"name\":\"genes\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_sireId\",\"type\":\"uint256\"},{\"name\":\"_matronId\",\"type\":\"uint256\"}],\"name\":\"bidOnSiringAuction\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"gen0CreatedCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"geneScience\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_matronId\",\"type\":\"uint256\"},{\"name\":\"_sireId\",\"type\":\"uint256\"}],\"name\":\"breedWithAuto\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"matronId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"sireId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"cooldownEndBlock\",\"type\":\"uint256\"}],\"name\":\"Pregnant\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"kittyId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"matronId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"sireId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"genes\",\"type\":\"uint256\"}],\"name\":\"Birth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"newContract\",\"type\":\"address\"}],\"name\":\"ContractUpgrade\",\"type\":\"event\"}]" - abi_ContractScenario011_deployErc721KittyCore = "[{\"constant\":true,\"inputs\":[{\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"cfoAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"name\":\"_preferredTransport\",\"type\":\"string\"}],\"name\":\"tokenMetadata\",\"outputs\":[{\"name\":\"infoUrl\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"promoCreatedCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"ceoAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GEN0_STARTING_PRICE\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setSiringAuctionAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pregnantKitties\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_kittyId\",\"type\":\"uint256\"}],\"name\":\"isPregnant\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GEN0_AUCTION_DURATION\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"siringAuction\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setGeneScienceAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newCEO\",\"type\":\"address\"}],\"name\":\"setCEO\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newCOO\",\"type\":\"address\"}],\"name\":\"setCOO\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_kittyId\",\"type\":\"uint256\"},{\"name\":\"_startingPrice\",\"type\":\"uint256\"},{\"name\":\"_endingPrice\",\"type\":\"uint256\"},{\"name\":\"_duration\",\"type\":\"uint256\"}],\"name\":\"createSaleAuction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"sireAllowedToAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_matronId\",\"type\":\"uint256\"},{\"name\":\"_sireId\",\"type\":\"uint256\"}],\"name\":\"canBreedWith\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"kittyIndexToApproved\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_kittyId\",\"type\":\"uint256\"},{\"name\":\"_startingPrice\",\"type\":\"uint256\"},{\"name\":\"_endingPrice\",\"type\":\"uint256\"},{\"name\":\"_duration\",\"type\":\"uint256\"}],\"name\":\"createSiringAuction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"setAutoBirthFee\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_addr\",\"type\":\"address\"},{\"name\":\"_sireId\",\"type\":\"uint256\"}],\"name\":\"approveSiring\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newCFO\",\"type\":\"address\"}],\"name\":\"setCFO\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_genes\",\"type\":\"uint256\"},{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"createPromoKitty\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"secs\",\"type\":\"uint256\"}],\"name\":\"setSecondsPerBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"withdrawBalance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"name\":\"owner\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GEN0_CREATION_LIMIT\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"newContractAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setSaleAuctionAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"count\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_v2Address\",\"type\":\"address\"}],\"name\":\"setNewAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"secondsPerBlock\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"tokensOfOwner\",\"outputs\":[{\"name\":\"ownerTokens\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_matronId\",\"type\":\"uint256\"}],\"name\":\"giveBirth\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"withdrawAuctionBalances\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"cooldowns\",\"outputs\":[{\"name\":\"\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"kittyIndexToOwner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"cooAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"autoBirthFee\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"erc721Metadata\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_genes\",\"type\":\"uint256\"}],\"name\":\"createGen0Auction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_kittyId\",\"type\":\"uint256\"}],\"name\":\"isReadyToBreed\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"PROMO_CREATION_LIMIT\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_contractAddress\",\"type\":\"address\"}],\"name\":\"setMetadataAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"saleAuction\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_id\",\"type\":\"uint256\"}],\"name\":\"getKitty\",\"outputs\":[{\"name\":\"isGestating\",\"type\":\"bool\"},{\"name\":\"isReady\",\"type\":\"bool\"},{\"name\":\"cooldownIndex\",\"type\":\"uint256\"},{\"name\":\"nextActionAt\",\"type\":\"uint256\"},{\"name\":\"siringWithId\",\"type\":\"uint256\"},{\"name\":\"birthTime\",\"type\":\"uint256\"},{\"name\":\"matronId\",\"type\":\"uint256\"},{\"name\":\"sireId\",\"type\":\"uint256\"},{\"name\":\"generation\",\"type\":\"uint256\"},{\"name\":\"genes\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_sireId\",\"type\":\"uint256\"},{\"name\":\"_matronId\",\"type\":\"uint256\"}],\"name\":\"bidOnSiringAuction\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"gen0CreatedCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"geneScience\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_matronId\",\"type\":\"uint256\"},{\"name\":\"_sireId\",\"type\":\"uint256\"}],\"name\":\"breedWithAuto\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"matronId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"sireId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"cooldownEndBlock\",\"type\":\"uint256\"}],\"name\":\"Pregnant\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"kittyId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"matronId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"sireId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"genes\",\"type\":\"uint256\"}],\"name\":\"Birth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"newContract\",\"type\":\"address\"}],\"name\":\"ContractUpgrade\",\"type\":\"event\"}]" - abi_ContractScenario011_deploySaleClockAuction = "[{\"constant\":false,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"name\":\"_startingPrice\",\"type\":\"uint256\"},{\"name\":\"_endingPrice\",\"type\":\"uint256\"},{\"name\":\"_duration\",\"type\":\"uint256\"},{\"name\":\"_seller\",\"type\":\"address\"}],\"name\":\"createAuction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"unpause\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"bid\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastGen0SalePrices\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"withdrawBalance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getAuction\",\"outputs\":[{\"name\":\"seller\",\"type\":\"address\"},{\"name\":\"startingPrice\",\"type\":\"uint256\"},{\"name\":\"endingPrice\",\"type\":\"uint256\"},{\"name\":\"duration\",\"type\":\"uint256\"},{\"name\":\"startedAt\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"ownerCut\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pause\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isSaleClockAuction\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"cancelAuctionWhenPaused\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"gen0SaleCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"cancelAuction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getCurrentPrice\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"nonFungibleContract\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"averageGen0SalePrice\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_nftAddr\",\"type\":\"address\"},{\"name\":\"_cut\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"startingPrice\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"endingPrice\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"duration\",\"type\":\"uint256\"}],\"name\":\"AuctionCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"totalPrice\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"winner\",\"type\":\"address\"}],\"name\":\"AuctionSuccessful\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"AuctionCancelled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Pause\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Unpause\",\"type\":\"event\"}]" - abi_ContractScenario011_deploySiringClockAuction = "[{\"constant\":false,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"name\":\"_startingPrice\",\"type\":\"uint256\"},{\"name\":\"_endingPrice\",\"type\":\"uint256\"},{\"name\":\"_duration\",\"type\":\"uint256\"},{\"name\":\"_seller\",\"type\":\"address\"}],\"name\":\"createAuction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"unpause\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"bid\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"withdrawBalance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isSiringClockAuction\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getAuction\",\"outputs\":[{\"name\":\"seller\",\"type\":\"address\"},{\"name\":\"startingPrice\",\"type\":\"uint256\"},{\"name\":\"endingPrice\",\"type\":\"uint256\"},{\"name\":\"duration\",\"type\":\"uint256\"},{\"name\":\"startedAt\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"ownerCut\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pause\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"cancelAuctionWhenPaused\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"cancelAuction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getCurrentPrice\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"nonFungibleContract\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_nftAddr\",\"type\":\"address\"},{\"name\":\"_cut\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"startingPrice\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"endingPrice\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"duration\",\"type\":\"uint256\"}],\"name\":\"AuctionCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"totalPrice\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"winner\",\"type\":\"address\"}],\"name\":\"AuctionSuccessful\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"AuctionCancelled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Pause\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Unpause\",\"type\":\"event\"}]" - abi_ContractScenario011_deployGeneScienceInterface = "[{\"constant\":true,\"inputs\":[{\"name\":\"genes1\",\"type\":\"uint256\"},{\"name\":\"genes2\",\"type\":\"uint256\"},{\"name\":\"targetBlock\",\"type\":\"uint256\"}],\"name\":\"mixGenes\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isGeneScience\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"}]" - abi_WalletTestAccount012_storageAndCpu = "[{\"constant\":false,\"inputs\":[{\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"add2\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"add\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"fori2\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"args\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"fori\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]" - abi_TestExceptionCodeAndAbi_testExceptionCodeAndAbi = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"_name\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply1\",\"outputs\":[{\"name\":\"_totalSupply1\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"_decimals\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"MAX_UINT256\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"_symbol\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"},{\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"},{\"name\":\"_data\",\"type\":\"bytes\"},{\"name\":\"_custom_fallback\",\"type\":\"string\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"Transfer\",\"type\":\"event\"}]" - abi_TestExceptionCodeAndAbi_testtimeout = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"iarray\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"testUseCpu\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"testUseStorage\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"address\"}],\"name\":\"m\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"calculatedFibNumber\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"test\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"n\",\"type\":\"uint256\"}],\"name\":\"setFibonacci\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_TestMapBigLongAndNumbers_deployErc721KittyCore = "[{\"constant\":false,\"inputs\":[{\"name\":\"amount\",\"type\":\"bytes\"},{\"name\":\"addr3\",\"type\":\"address\"}],\"name\":\"update3\",\"outputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"balances1\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"balances3\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"testUseCpu\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"s\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"addr2\",\"type\":\"address\"},{\"name\":\"times\",\"type\":\"uint256\"}],\"name\":\"update1\",\"outputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"amount\",\"type\":\"string\"},{\"name\":\"addr3\",\"type\":\"address\"}],\"name\":\"update2\",\"outputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"addr1\",\"type\":\"address\"}],\"name\":\"update\",\"outputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_TestNetErc721Cat_deployErc721KittyCore = "[{\"constant\":true,\"inputs\":[{\"name\":\"_interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"cfoAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"name\":\"_preferredTransport\",\"type\":\"string\"}],\"name\":\"tokenMetadata\",\"outputs\":[{\"name\":\"infoUrl\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"promoCreatedCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"ceoAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GEN0_STARTING_PRICE\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setSiringAuctionAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pregnantKitties\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_kittyId\",\"type\":\"uint256\"}],\"name\":\"isPregnant\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GEN0_AUCTION_DURATION\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"siringAuction\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setGeneScienceAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newCEO\",\"type\":\"address\"}],\"name\":\"setCEO\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newCOO\",\"type\":\"address\"}],\"name\":\"setCOO\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_kittyId\",\"type\":\"uint256\"},{\"name\":\"_startingPrice\",\"type\":\"uint256\"},{\"name\":\"_endingPrice\",\"type\":\"uint256\"},{\"name\":\"_duration\",\"type\":\"uint256\"}],\"name\":\"createSaleAuction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"sireAllowedToAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_matronId\",\"type\":\"uint256\"},{\"name\":\"_sireId\",\"type\":\"uint256\"}],\"name\":\"canBreedWith\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"kittyIndexToApproved\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_kittyId\",\"type\":\"uint256\"},{\"name\":\"_startingPrice\",\"type\":\"uint256\"},{\"name\":\"_endingPrice\",\"type\":\"uint256\"},{\"name\":\"_duration\",\"type\":\"uint256\"}],\"name\":\"createSiringAuction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"setAutoBirthFee\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_addr\",\"type\":\"address\"},{\"name\":\"_sireId\",\"type\":\"uint256\"}],\"name\":\"approveSiring\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newCFO\",\"type\":\"address\"}],\"name\":\"setCFO\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_genes\",\"type\":\"uint256\"},{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"createPromoKitty\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"secs\",\"type\":\"uint256\"}],\"name\":\"setSecondsPerBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"withdrawBalance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"name\":\"owner\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GEN0_CREATION_LIMIT\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"newContractAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setSaleAuctionAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"count\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_v2Address\",\"type\":\"address\"}],\"name\":\"setNewAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"secondsPerBlock\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"tokensOfOwner\",\"outputs\":[{\"name\":\"ownerTokens\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_matronId\",\"type\":\"uint256\"}],\"name\":\"giveBirth\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"withdrawAuctionBalances\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"cooldowns\",\"outputs\":[{\"name\":\"\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"kittyIndexToOwner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"cooAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"autoBirthFee\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"erc721Metadata\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_genes\",\"type\":\"uint256\"}],\"name\":\"createGen0Auction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_kittyId\",\"type\":\"uint256\"}],\"name\":\"isReadyToBreed\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"PROMO_CREATION_LIMIT\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_contractAddress\",\"type\":\"address\"}],\"name\":\"setMetadataAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"saleAuction\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_id\",\"type\":\"uint256\"}],\"name\":\"getKitty\",\"outputs\":[{\"name\":\"isGestating\",\"type\":\"bool\"},{\"name\":\"isReady\",\"type\":\"bool\"},{\"name\":\"cooldownIndex\",\"type\":\"uint256\"},{\"name\":\"nextActionAt\",\"type\":\"uint256\"},{\"name\":\"siringWithId\",\"type\":\"uint256\"},{\"name\":\"birthTime\",\"type\":\"uint256\"},{\"name\":\"matronId\",\"type\":\"uint256\"},{\"name\":\"sireId\",\"type\":\"uint256\"},{\"name\":\"generation\",\"type\":\"uint256\"},{\"name\":\"genes\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_sireId\",\"type\":\"uint256\"},{\"name\":\"_matronId\",\"type\":\"uint256\"}],\"name\":\"bidOnSiringAuction\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"gen0CreatedCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"geneScience\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_matronId\",\"type\":\"uint256\"},{\"name\":\"_sireId\",\"type\":\"uint256\"}],\"name\":\"breedWithAuto\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"matronId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"sireId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"cooldownEndBlock\",\"type\":\"uint256\"}],\"name\":\"Pregnant\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"kittyId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"matronId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"sireId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"genes\",\"type\":\"uint256\"}],\"name\":\"Birth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"newContract\",\"type\":\"address\"}],\"name\":\"ContractUpgrade\",\"type\":\"event\"}]" - abi_TestNetErc721Cat_deploySaleClockAuction = "[{\"constant\":false,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"name\":\"_startingPrice\",\"type\":\"uint256\"},{\"name\":\"_endingPrice\",\"type\":\"uint256\"},{\"name\":\"_duration\",\"type\":\"uint256\"},{\"name\":\"_seller\",\"type\":\"address\"}],\"name\":\"createAuction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"unpause\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"bid\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastGen0SalePrices\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"withdrawBalance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getAuction\",\"outputs\":[{\"name\":\"seller\",\"type\":\"address\"},{\"name\":\"startingPrice\",\"type\":\"uint256\"},{\"name\":\"endingPrice\",\"type\":\"uint256\"},{\"name\":\"duration\",\"type\":\"uint256\"},{\"name\":\"startedAt\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"ownerCut\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pause\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isSaleClockAuction\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"cancelAuctionWhenPaused\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"gen0SaleCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"cancelAuction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getCurrentPrice\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"nonFungibleContract\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"averageGen0SalePrice\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_nftAddr\",\"type\":\"address\"},{\"name\":\"_cut\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"startingPrice\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"endingPrice\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"duration\",\"type\":\"uint256\"}],\"name\":\"AuctionCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"totalPrice\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"winner\",\"type\":\"address\"}],\"name\":\"AuctionSuccessful\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"AuctionCancelled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Pause\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Unpause\",\"type\":\"event\"}]" - abi_TestNetErc721Cat_deploySiringClockAuction = "[{\"constant\":false,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"name\":\"_startingPrice\",\"type\":\"uint256\"},{\"name\":\"_endingPrice\",\"type\":\"uint256\"},{\"name\":\"_duration\",\"type\":\"uint256\"},{\"name\":\"_seller\",\"type\":\"address\"}],\"name\":\"createAuction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"unpause\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"bid\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"withdrawBalance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isSiringClockAuction\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getAuction\",\"outputs\":[{\"name\":\"seller\",\"type\":\"address\"},{\"name\":\"startingPrice\",\"type\":\"uint256\"},{\"name\":\"endingPrice\",\"type\":\"uint256\"},{\"name\":\"duration\",\"type\":\"uint256\"},{\"name\":\"startedAt\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"ownerCut\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pause\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"cancelAuctionWhenPaused\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"cancelAuction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getCurrentPrice\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"nonFungibleContract\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_nftAddr\",\"type\":\"address\"},{\"name\":\"_cut\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"startingPrice\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"endingPrice\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"duration\",\"type\":\"uint256\"}],\"name\":\"AuctionCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"totalPrice\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"winner\",\"type\":\"address\"}],\"name\":\"AuctionSuccessful\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"AuctionCancelled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Pause\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Unpause\",\"type\":\"event\"}]" - abi_TestNetErc721Cat_deployGeneScienceInterface = "[{\"constant\":true,\"inputs\":[{\"name\":\"genes1\",\"type\":\"uint256\"},{\"name\":\"genes2\",\"type\":\"uint256\"},{\"name\":\"targetBlock\",\"type\":\"uint256\"}],\"name\":\"mixGenes\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isGeneScience\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"}]" - abi_TestNetFomo3D_deployErc721CryptoKitties = "[{\"constant\":true,\"inputs\":[{\"name\":\"_customerAddress\",\"type\":\"address\"}],\"name\":\"dividendsOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_ethereumToSpend\",\"type\":\"uint256\"}],\"name\":\"calculateTokensReceived\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokensToSell\",\"type\":\"uint256\"}],\"name\":\"calculateEthereumReceived\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"onlyAmbassadors\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"administrators\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"withdraw\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"sellPrice\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"stakingRequirement\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_includeReferralBonus\",\"type\":\"bool\"}],\"name\":\"myDividends\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalEthereumBalance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_customerAddress\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_amountOfTokens\",\"type\":\"uint256\"}],\"name\":\"setStakingRequirement\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"buyPrice\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_identifier\",\"type\":\"bytes32\"},{\"name\":\"_status\",\"type\":\"bool\"}],\"name\":\"setAdministrator\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"Hourglass\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"myTokens\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"disableInitialStage\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_toAddress\",\"type\":\"address\"},{\"name\":\"_amountOfTokens\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_symbol\",\"type\":\"string\"}],\"name\":\"setSymbol\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_amountOfTokens\",\"type\":\"uint256\"}],\"name\":\"sell\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"exit\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_referredBy\",\"type\":\"address\"}],\"name\":\"buy\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"reinvest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"customerAddress\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"incomingEthereum\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"tokensMinted\",\"type\":\"uint256\"},{\"indexed\":true,\"name\":\"referredBy\",\"type\":\"address\"}],\"name\":\"onTokenPurchase\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"customerAddress\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"tokensBurned\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"ethereumEarned\",\"type\":\"uint256\"}],\"name\":\"onTokenSell\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"customerAddress\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"ethereumReinvested\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"tokensMinted\",\"type\":\"uint256\"}],\"name\":\"onReinvestment\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"customerAddress\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"ethereumWithdrawn\",\"type\":\"uint256\"}],\"name\":\"onWithdraw\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"}]" - abi1_TestNetFomo3D_deployErc721CryptoKitties = "[{\"constant\":false,\"inputs\":[],\"name\":\"test\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_TestNetFomo3D_tooLargeStorage = "[{\"constant\":true,\"inputs\":[],\"name\":\"s\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"foo\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"times\",\"type\":\"uint256\"}],\"name\":\"slice\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"refresh\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_TestStorageAndCpu_storageAndCpu = "[{\"constant\":false,\"inputs\":[],\"name\":\"oneCpu\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"iarray\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"storage8Char\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"testUseCpu\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"testUseStorage\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"address\"}],\"name\":\"m\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"iarray1\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"calculatedFibNumber\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"test\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"n\",\"type\":\"uint256\"}],\"name\":\"setFibonacci\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_WalletTestAccount013 = "[{\"constant\":false,\"inputs\":[{\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"add2\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"add\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"fori2\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"args\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"fori\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}] " - abi_ContractEventAndLog1 = "[{\"constant\":false,\"inputs\":[],\"name\":\"depositForLog\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"depositForLogCycle\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"depositForAnonymousNoLog\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"depositForEventAndLog\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getTransactionKeccak256\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"depositForAnonymousHasLog\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"depositForEventTwoIndex\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"depositForEvent\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getDepositKeccak256\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"depositForEventNoIndex\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"depositForEventCycle\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"yes\",\"type\":\"bool\"},{\"name\":\"no\",\"type\":\"bool\"}],\"name\":\"triggerBoolEvent\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"triggerUintEvent\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"age\",\"type\":\"string\"}],\"name\":\"triggerStringEvent\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"age\",\"type\":\"string\"}],\"name\":\"triggerStringEventAnonymous\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"triggerintEvent\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBanlance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"depositForEventOneIndex\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"value1\",\"type\":\"uint8\"},{\"indexed\":false,\"name\":\"value2\",\"type\":\"uint64\"},{\"indexed\":false,\"name\":\"value3\",\"type\":\"uint128\"},{\"indexed\":false,\"name\":\"value4\",\"type\":\"uint248\"}],\"name\":\"uintErgodic\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"value1\",\"type\":\"int8\"},{\"indexed\":false,\"name\":\"value2\",\"type\":\"int72\"},{\"indexed\":false,\"name\":\"value3\",\"type\":\"int136\"},{\"indexed\":false,\"name\":\"value4\",\"type\":\"int232\"}],\"name\":\"intErgodic\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"name\",\"type\":\"string\"},{\"indexed\":true,\"name\":\"age\",\"type\":\"string\"}],\"name\":\"stringEvent\",\"type\":\"event\"},{\"anonymous\":true,\"inputs\":[{\"indexed\":false,\"name\":\"name\",\"type\":\"string\"},{\"indexed\":true,\"name\":\"age\",\"type\":\"string\"}],\"name\":\"stringEventAnonymous\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"yes\",\"type\":\"bool\"},{\"indexed\":true,\"name\":\"no\",\"type\":\"bool\"}],\"name\":\"boolEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferNoIndex\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferOneIndex\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferTwoIndex\",\"type\":\"event\"},{\"anonymous\":true,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferAnonymous\",\"type\":\"event\"}]" - abi_ContractEventAndLog2 = "[{\"constant\":false,\"inputs\":[],\"name\":\"triggerEventBytes\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"deposit\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getBanlance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"value10\",\"type\":\"bytes10\"},{\"indexed\":false,\"name\":\"value17\",\"type\":\"bytes17\"},{\"indexed\":false,\"name\":\"value32\",\"type\":\"bytes32\"}],\"name\":\"eventBytes\",\"type\":\"event\"},{\"anonymous\":true,\"inputs\":[{\"indexed\":false,\"name\":\"value10\",\"type\":\"bytes10\"},{\"indexed\":false,\"name\":\"value17\",\"type\":\"bytes17\"},{\"indexed\":false,\"name\":\"value32\",\"type\":\"bytes32\"}],\"name\":\"triggerBytesAnonymous\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"value10\",\"type\":\"bytes10\"},{\"indexed\":true,\"name\":\"value17\",\"type\":\"bytes17\"},{\"indexed\":true,\"name\":\"value32\",\"type\":\"bytes32\"}],\"name\":\"eventBytesIndex\",\"type\":\"event\"},{\"anonymous\":true,\"inputs\":[{\"indexed\":true,\"name\":\"value10\",\"type\":\"bytes10\"},{\"indexed\":true,\"name\":\"value17\",\"type\":\"bytes17\"},{\"indexed\":true,\"name\":\"value32\",\"type\":\"bytes32\"}],\"name\":\"triggerBytesAnonymousIndex\",\"type\":\"event\"}]" - - abi_OriginEnergyLimit001 = "[{\"constant\":false,\"inputs\":[{\"name\":\"i\",\"type\":\"uint256\"}],\"name\":\"findArgsByIndexTest\",\"outputs\":[{\"name\":\"z\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_OriginEnergyLimit004 = "[{\"constant\":false,\"inputs\":[{\"name\":\"i\",\"type\":\"uint256\"}],\"name\":\"findArgsByIndexTest\",\"outputs\":[{\"name\":\"z\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - - abi_ContractTrcToken001_transferTokenContract = "[{\"constant\":false,\"inputs\":[],\"name\":\"getResultInCon\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]\n" - abi_ContractTrcToken002_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_ContractTrcToken005_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_ContractTrcToken006_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_ContractTrcToken011_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenValue\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"transferTokenTest\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueOverBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueRandomIdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"accountAddress\",\"type\":\"address\"}],\"name\":\"getTokenBalanceTest\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxLong\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getTokenBalnce\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValue0IdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken011_resultContract = "[{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"log\",\"type\":\"event\"}]" - abi_ContractTrcToken012_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenValue\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"transferTokenTest\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueOverBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueRandomIdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"accountAddress\",\"type\":\"address\"}],\"name\":\"getTokenBalanceTest\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxLong\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getTokenBalnce\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValue0IdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken014_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenValue\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"transferTokenTest\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueOverBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueRandomIdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"accountAddress\",\"type\":\"address\"}],\"name\":\"getTokenBalanceTest\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxLong\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getTokenBalnce\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValue0IdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken014_resultContract = "[{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"log\",\"type\":\"event\"}]" - abi_ContractTrcToken016_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenValue\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"transferTokenTest\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueOverBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueRandomIdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"accountAddress\",\"type\":\"address\"}],\"name\":\"getTokenBalanceTest\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxLong\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getTokenBalnce\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValue0IdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken016_resultContract = "[{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"log\",\"type\":\"event\"}]" - abi_ContractTrcToken017_recieveTokenContract = "[{\"constant\":false,\"inputs\":[],\"name\":\"setFlag\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"flag\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken042_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenValue\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"transferTokenTest\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueOverBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueRandomIdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"accountAddress\",\"type\":\"address\"}],\"name\":\"getTokenBalanceTest\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxLong\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getTokenBalnce\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValue0IdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken042_recieveTokenContract = "[{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"log\",\"type\":\"event\"}]" - abi_ContractTrcToken043_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenValue\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"transferTokenTest\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueOverBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueRandomIdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"accountAddress\",\"type\":\"address\"}],\"name\":\"getTokenBalanceTest\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxLong\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getTokenBalnce\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValue0IdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken043_recieveTokenContract = "[{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"log\",\"type\":\"event\"}]" - abi_ContractTrcToken046_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_ContractTrcToken047_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi2_ContractTrcToken023_tokenTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_ContractTrcToken023_tokenTest = "[{\"constant\":true,\"inputs\":[],\"name\":\"flag\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken026_BTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"callCAddress\",\"type\":\"address\"},{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"transC\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi1_ContractTrcToken026_CTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"trans\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi1_ContractTrcToken026_tokenTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"callBAddress\",\"type\":\"address\"},{\"name\":\"callCAddress\",\"type\":\"address\"},{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"testInCall\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"callBddress\",\"type\":\"address\"},{\"name\":\"callAddressC\",\"type\":\"address\"},{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"testIndelegateCall\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken027_BTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"callCAddress\",\"type\":\"address\"},{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"transC\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken027_CTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"trans\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken027_tokenTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"callBAddress\",\"type\":\"address\"},{\"name\":\"callCAddress\",\"type\":\"address\"},{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"testIndelegateCall\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"callBddress\",\"type\":\"address\"},{\"name\":\"callAddressC\",\"type\":\"address\"},{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"testIndelegateCall\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken028_tokenTest = "[{\"constant\":true,\"inputs\":[],\"name\":\"a\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"tokenBalanceWithSameName\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"getA\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_ContractTrcToken054_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_ContractTrcToken055_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_ContractTrcToken060_transferTokenContract = "[{\"constant\":false,\"inputs\":[],\"name\":\"getResultInCon\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]\n" - abi_ContractTrcToken061_transferTokenContract = "[{\"constant\":false,\"inputs\":[],\"name\":\"getResultInCon\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]\n" - abi_ContractTrcToken062_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenValue\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"transferTokenTest\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueOverBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueRandomIdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"accountAddress\",\"type\":\"address\"}],\"name\":\"getTokenBalanceTest\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxLong\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getTokenBalnce\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValue0IdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken062_recieveTokenContract = "[{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"log\",\"type\":\"event\"}]" - abi_ContractTrcToken063_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenValue\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"transferTokenTest\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueOverBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueRandomIdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"accountAddress\",\"type\":\"address\"}],\"name\":\"getTokenBalanceTest\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxLong\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getTokenBalnce\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValue0IdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken063_recieveTokenContract = "[{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"log\",\"type\":\"event\"}]" - abi_ContractTrcToken064_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenValue\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"transferTokenTest\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueOverBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueRandomIdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"accountAddress\",\"type\":\"address\"}],\"name\":\"getTokenBalanceTest\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxLong\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getTokenBalnce\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValue0IdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken064_recieveTokenContract = "[{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"log\",\"type\":\"event\"}]" - abi_ContractTrcToken066_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenValue\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"transferTokenTest\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueOverBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueRandomIdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"accountAddress\",\"type\":\"address\"}],\"name\":\"getTokenBalanceTest\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxLong\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getTokenBalnce\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValue0IdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken066_recieveTokenContract = "[{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"log\",\"type\":\"event\"}]" - abi_ContractTrcToken067_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenValue\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"transferTokenTest\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueOverBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueRandomIdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"accountAddress\",\"type\":\"address\"}],\"name\":\"getTokenBalanceTest\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxLong\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getTokenBalnce\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValue0IdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken067_recieveTokenContract = "[{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"log\",\"type\":\"event\"}]" - abi_ContractTrcToken068_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenValue\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"transferTokenTest\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueOverBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueRandomIdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"accountAddress\",\"type\":\"address\"}],\"name\":\"getTokenBalanceTest\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxLong\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getTokenBalnce\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValue0IdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken068_recieveTokenContract = "[{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"log\",\"type\":\"event\"}]" - abi_ContractTrcToken071_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenValue\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"transferTokenTest\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueRandomIdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"accountAddress\",\"type\":\"address\"}],\"name\":\"getTokenBalanceTest\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestIDOverBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getTokenBalnce\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken071_recieveTokenContract = "[{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"log\",\"type\":\"event\"}]" - abi_ContractTrcToken073_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getToken\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"logFallback\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"logGetToken\",\"type\":\"event\"}]" - abi_ContractTrcToken074_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getToken\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"logFallback\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"logGetToken\",\"type\":\"event\"}]" - abi_ContractTrcToken075_transferTokenContract = "[{\"constant\":false,\"inputs\":[],\"name\":\"getTokenLongMin\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getToken\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"getTokenLongMax\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"logFallback\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"logGetToken\",\"type\":\"event\"}]" - abi_ContractTrcToken0552_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_ContractTrcToken0553_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_ContractTrcToken0612_transferTokenContract = "[{\"constant\":false,\"inputs\":[],\"name\":\"getResultInCon\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]\n" - abi_ContractTrcToken0613_transferTokenContract = "[{\"constant\":false,\"inputs\":[],\"name\":\"getResultInCon\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]\n" - abi_ContractTrcToken0672_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenValue\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"transferTokenTest\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueOverBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueRandomIdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"accountAddress\",\"type\":\"address\"}],\"name\":\"getTokenBalanceTest\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"msgTokenValueAndTokenIdTest\",\"outputs\":[{\"name\":\"\",\"type\":\"trcToken\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValueMaxLong\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenId\",\"type\":\"trcToken\"}],\"name\":\"getTokenBalnce\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTokenTestValue0IdBigInteger\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken0672_recieveTokenContract = "[{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"log\",\"type\":\"event\"}]" - - abi_ContractTrcToken029_tokenTest = "[{\"constant\":true,\"inputs\":[],\"name\":\"a\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferTokenWithSameName\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_ContractTrcToken030_tokenTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"kill\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_ContractTrcToken031_tokenTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"kill\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_ContractTrcToken034_tokenTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"failTransferTokenError\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"failTransferTokenRevert\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"}]" - abi_ContractTrcToken035_tokenTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"failTransferTokenError\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"failTransferTokenRevert\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"}]" - abi_ContractTrcToken036_transferTokenWithPureTest = "[{\"constant\":true,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenValue\",\"type\":\"uint256\"}],\"name\":\"transferTokenWithConstant\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"log\",\"type\":\"event\"}]" - - abi_ContractTrcToken036_transferTokenWithViewTest = "[{\"constant\":true,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenValue\",\"type\":\"uint256\"}],\"name\":\"transferTokenWithView\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"log\",\"type\":\"event\"}]" - abi_ContractTrcToken036_transferTokenWithOutPayableTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenValue\",\"type\":\"uint256\"}],\"name\":\"transferTokenWithOutPayable\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"log\",\"type\":\"event\"}]" - abi_ContractTrcToken037_receiveTrc10Test = "[{\"constant\":false,\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"tid\",\"type\":\"trcToken\"},{\"name\":\"meamount\",\"type\":\"uint256\"}],\"name\":\"checkTrc10\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - - abi_ContractTrcToken037_tokenTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"rec\",\"type\":\"address\"}],\"name\":\"receive\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"}]" - abi_ContractTrcToken038_tokenTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"rec\",\"type\":\"address\"}],\"name\":\"receive\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"}]" - abi_ContractTrcToken038_BTest = "[{\"constant\":false,\"inputs\":[],\"name\":\"AssertError\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - - abi_ContractTrcToken039_ProxyTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - - abi_ContractTrcToken039_ATest = "[{\"constant\":false,\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"trans\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"}]" - abi_ContractTrcToken039_BTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"}],\"name\":\"trans\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"}]" - abi_ContractTrcToken041_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_ContractTrcToken048_transferTokenContract = "[{\"constant\":false,\"inputs\":[],\"name\":\"testMsgValue\",\"outputs\":[{\"name\":\"value\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"testMsgTokenValue\",\"outputs\":[{\"name\":\"value\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"log\",\"type\":\"event\"}]" - - abi_ContractTrcToken050_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - - abi_ContractTrcToken051_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - - - abi_ContractTrcToken052_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_ContractTrcToken036_tokenTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"tokenValue\",\"type\":\"uint256\"}],\"name\":\"transferTokenWithPure\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"log\",\"type\":\"event\"}]" - abi_ContractTrcToken049_transferTokenContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"},{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_ContractTrcToken076_originTest = "[{\"constant\":true,\"inputs\":[],\"name\":\"result2\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"result1\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"sender\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"getResult1\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"origin\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"getResult2\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"test\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_ContractTrcToken077_AddressTest = "[{\"constant\":true,\"inputs\":[],\"name\":\"addressTest\",\"outputs\":[{\"name\":\"addressValue\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]" - abi_ContractTrcToken077_AddressTest1 = "[{\"constant\":false,\"inputs\":[],\"name\":\"addressTest\",\"outputs\":[{\"name\":\"addressValue\",\"type\":\"bytes32\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"}]" - abi_ContractTrcToken078_AddressTest1 = "[{\"constant\":false,\"inputs\":[{\"name\":\"called_address\",\"type\":\"address\"},{\"name\":\"c\",\"type\":\"address\"}],\"name\":\"sendToB3\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"called_address\",\"type\":\"address\"},{\"name\":\"c\",\"type\":\"address\"}],\"name\":\"sendToB\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"called_address\",\"type\":\"address\"},{\"name\":\"c\",\"type\":\"address\"}],\"name\":\"sendToB2\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken078_AddressTest2 = "[{\"constant\":false,\"inputs\":[{\"name\":\"c\",\"type\":\"address\"}],\"name\":\"setIinC\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken078_AddressTest3 = "[{\"constant\":true,\"inputs\":[],\"name\":\"sender\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"origin\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"\",\"type\":\"address\"}],\"name\":\"log\",\"type\":\"event\"}]" - - abi_ContractTrcToken078_AddressTest4 = "[{\"constant\":false,\"inputs\":[{\"name\":\"called_address\",\"type\":\"address\"},{\"name\":\"c\",\"type\":\"address\"}],\"name\":\"sendToB3\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"called_address\",\"type\":\"address\"},{\"name\":\"c\",\"type\":\"address\"}],\"name\":\"sendToB\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"called_address\",\"type\":\"address\"},{\"name\":\"c\",\"type\":\"address\"}],\"name\":\"sendToB2\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - - abi_ContractTrcToken078_AddressTest5 = "[{\"constant\":false,\"inputs\":[{\"name\":\"c\",\"type\":\"address\"}],\"name\":\"setIinC\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"transferTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_ContractTrcToken078_AddressTest6 = "[{\"constant\":true,\"inputs\":[],\"name\":\"sender\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"origin\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"\",\"type\":\"address\"}],\"name\":\"log\",\"type\":\"event\"}]" - abi_veryLarge = "[{\"constant\":false,\"inputs\":[],\"name\":\"getBalance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"Address\",\"type\":\"address\"}],\"name\":\"transfer\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"num\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]" - abi_MainGateway = "[{\"constant\":true,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"checkOracle\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"contractAddress\",\"type\":\"address\"},{\"name\":\"uid\",\"type\":\"uint256\"},{\"name\":\"sig\",\"type\":\"bytes\"}],\"name\":\"withdrawTRC721\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"depositTRX\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"depositTRC10\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"contractAddress\",\"type\":\"address\"}],\"name\":\"depositTRC20\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"uid\",\"type\":\"uint256\"},{\"name\":\"contractAddress\",\"type\":\"address\"}],\"name\":\"depositTRC721\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"numOracles\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"contractAddress\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"sig\",\"type\":\"bytes\"}],\"name\":\"withdrawTRC20\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"getTRC10\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_oracle\",\"type\":\"address\"},{\"name\":\"isOracle\",\"type\":\"bool\"}],\"name\":\"modifyOracle\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"uid\",\"type\":\"uint256\"},{\"name\":\"contractAddress\",\"type\":\"address\"}],\"name\":\"getNFT\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"tokenId\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"sig\",\"type\":\"bytes\"}],\"name\":\"withdrawTRC10\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowes\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onTRC20Received\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes4\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_uid\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onTRC721Received\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes4\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getTRX\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"mainChainToken\",\"type\":\"address\"},{\"name\":\"sideChainToken\",\"type\":\"address\"}],\"name\":\"migrationToken\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"sig\",\"type\":\"bytes\"}],\"name\":\"withdrawTRX\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"contractAddress\",\"type\":\"address\"}],\"name\":\"getTRC20\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_oracle\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TRXReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"TRC10Received\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"contractAddress\",\"type\":\"address\"}],\"name\":\"TRC20Received\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"uid\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"contractAddress\",\"type\":\"address\"}],\"name\":\"TRC721Received\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"kind\",\"type\":\"uint8\"},{\"indexed\":false,\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"kind\",\"type\":\"uint8\"},{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"trcToken\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Token10Withdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"oracle\",\"type\":\"address\"}],\"name\":\"NewOracles\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"previousOwner\",\"type\":\"address\"}],\"name\":\"OwnershipRenounced\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"}]" - abi_SideGateway = "[{\"constant\":false,\"inputs\":[{\"name\":\"_sunTokenAddress\",\"type\":\"address\"}],\"name\":\"setSunTokenAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"b1\",\"type\":\"bytes\"},{\"name\":\"b2\",\"type\":\"bytes\"}],\"name\":\"concatBytes\",\"outputs\":[{\"name\":\"r\",\"type\":\"bytes\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"txData\",\"type\":\"bytes\"}],\"name\":\"withdrawTRX\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"to\",\"type\":\"address\"},{\"name\":\"trc10\",\"type\":\"uint256\"},{\"name\":\"value\",\"type\":\"uint256\"},{\"name\":\"name\",\"type\":\"bytes32\"},{\"name\":\"symbol\",\"type\":\"bytes32\"},{\"name\":\"decimals\",\"type\":\"uint8\"}],\"name\":\"depositTRC10\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"to\",\"type\":\"address\"},{\"name\":\"mainChainAddress\",\"type\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"depositTRC20\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"trc10Map\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"mainToSideContractMap\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"txId\",\"type\":\"bytes\"},{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"symbol\",\"type\":\"string\"},{\"name\":\"decimals\",\"type\":\"uint8\"}],\"name\":\"deployDAppTRC20AndMapping\",\"outputs\":[{\"name\":\"r\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"sunTokenAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"txId\",\"type\":\"bytes\"},{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"calcContractAddress\",\"outputs\":[{\"name\":\"r\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_oracle\",\"type\":\"address\"},{\"name\":\"isOracle\",\"type\":\"bool\"}],\"name\":\"modifyOracle\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"txId\",\"type\":\"bytes\"},{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"symbol\",\"type\":\"string\"}],\"name\":\"deployDAppTRC721AndMapping\",\"outputs\":[{\"name\":\"r\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"oracles\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"from\",\"type\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\"},{\"name\":\"txData\",\"type\":\"bytes\"}],\"name\":\"onTRC20Received\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes4\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"from\",\"type\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\"},{\"name\":\"txData\",\"type\":\"bytes\"}],\"name\":\"onTRC721Received\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes4\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"sideToMainContractMap\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"a\",\"type\":\"address\"}],\"name\":\"addressToBytes\",\"outputs\":[{\"name\":\"b\",\"type\":\"bytes\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"txData\",\"type\":\"bytes\"}],\"name\":\"withdrawTRC10\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"to\",\"type\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"depositTRX\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"to\",\"type\":\"address\"},{\"name\":\"mainChainAddress\",\"type\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"depositTRC721\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_oracle\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"developer\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"mainChainAddress\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"sideChainAddress\",\"type\":\"address\"}],\"name\":\"DeployDAppTRC20AndMapping\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"developer\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"mainChainAddress\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"sideChainAddress\",\"type\":\"address\"}],\"name\":\"DeployDAppTRC721AndMapping\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"trc10\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"DepositTRC10\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"sideChainAddress\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"DepositTRC20\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"sideChainAddress\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"DepositTRC721\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"DepositTRX\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"trc10\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"txData\",\"type\":\"bytes\"}],\"name\":\"WithdrawTRC10\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"mainChainAddress\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"txData\",\"type\":\"bytes\"}],\"name\":\"WithdrawTRC20\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"mainChainAddress\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"txData\",\"type\":\"bytes\"}],\"name\":\"WithdrawTRC721\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"txData\",\"type\":\"bytes\"}],\"name\":\"WithdrawTRX\",\"type\":\"event\"}]" - abi_shieldTrc20Token = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"burnFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"},{\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"approveAndCall\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialSupply\",\"type\":\"uint256\"},{\"name\":\"tokenName\",\"type\":\"string\"},{\"name\":\"tokenSymbol\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Burn\",\"type\":\"event\"}]" - abi_shield = "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"trc20ContractAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"scalingFactorExponent\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"position\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"cm\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"cv\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"epk\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32[21]\",\"name\":\"c\",\"type\":\"bytes32[21]\"}],\"name\":\"BurnNewLeaf\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"position\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"cm\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"cv\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"epk\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32[21]\",\"name\":\"c\",\"type\":\"bytes32[21]\"}],\"name\":\"MintNewLeaf\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"nf\",\"type\":\"bytes32\"}],\"name\":\"NoteSpent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32[3]\",\"name\":\"ciphertext\",\"type\":\"bytes32[3]\"}],\"name\":\"TokenBurn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TokenMint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"position\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"cm\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"cv\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"epk\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32[21]\",\"name\":\"c\",\"type\":\"bytes32[21]\"}],\"name\":\"TransferNewLeaf\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bytes32[10]\",\"name\":\"input\",\"type\":\"bytes32[10]\"},{\"internalType\":\"bytes32[2]\",\"name\":\"spendAuthoritySignature\",\"type\":\"bytes32[2]\"},{\"internalType\":\"uint256\",\"name\":\"rawValue\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[2]\",\"name\":\"bindingSignature\",\"type\":\"bytes32[2]\"},{\"internalType\":\"address\",\"name\":\"payTo\",\"type\":\"address\"},{\"internalType\":\"bytes32[3]\",\"name\":\"burnCipher\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes32[9][]\",\"name\":\"output\",\"type\":\"bytes32[9][]\"},{\"internalType\":\"bytes32[21][]\",\"name\":\"c\",\"type\":\"bytes32[21][]\"}],\"name\":\"burn\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"position\",\"type\":\"uint256\"}],\"name\":\"getPath\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[32]\",\"name\":\"\",\"type\":\"bytes32[32]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"latestRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"leafCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"rawValue\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[9]\",\"name\":\"output\",\"type\":\"bytes32[9]\"},{\"internalType\":\"bytes32[2]\",\"name\":\"bindingSignature\",\"type\":\"bytes32[2]\"},{\"internalType\":\"bytes32[21]\",\"name\":\"c\",\"type\":\"bytes32[21]\"}],\"name\":\"mint\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"noteCommitment\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"nullifiers\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"roots\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"scalingFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bytes32[10][]\",\"name\":\"input\",\"type\":\"bytes32[10][]\"},{\"internalType\":\"bytes32[2][]\",\"name\":\"spendAuthoritySignature\",\"type\":\"bytes32[2][]\"},{\"internalType\":\"bytes32[9][]\",\"name\":\"output\",\"type\":\"bytes32[9][]\"},{\"internalType\":\"bytes32[2]\",\"name\":\"bindingSignature\",\"type\":\"bytes32[2]\"},{\"internalType\":\"bytes32[21][]\",\"name\":\"c\",\"type\":\"bytes32[21][]\"}],\"name\":\"transfer\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tree\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]" - abi_getAddressChange = "[{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"getamount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"testaddress1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]" - abi_fallbackOldVersionTest = "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"data\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"msg\",\"type\":\"bytes\"}],\"name\":\"FallbackCall\",\"type\":\"event\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]" - abi_fallbackOldversionCall = "[{\"constant\":false,\"inputs\":[{\"internalType\":\"contract Test0\",\"name\":\"test\",\"type\":\"address\"}],\"name\":\"call\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"}]" - abi_arrayLenth_0.5.15 = "[{\"constant\":false,\"inputs\":[],\"name\":\"ChangeSize\",\"outputs\":[{\"internalType\":\"bytes1[]\",\"name\":\"\",\"type\":\"bytes1[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - abi_override001 = "[{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_y\",\"type\":\"uint256\"}],\"name\":\"setValue\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"x\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"y\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]" - abi_override002 = "[{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_x\",\"type\":\"uint256\"}],\"name\":\"setValue\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_x\",\"type\":\"uint256\"}],\"name\":\"setValue2\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"x\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]" - abi_override003 = "[{\"constant\":true,\"inputs\":[],\"name\":\"b32\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"choice\",\"outputs\":[{\"internalType\":\"enum Base.ActionChoices\",\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"choice2\",\"outputs\":[{\"internalType\":\"enum Base.ActionChoices\",\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"i\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"i2\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"origin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"stopped\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"ui\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]" - abi_virtual001 = "[{\"constant\":false,\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_y\",\"type\":\"bool\"}],\"name\":\"setBool\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"string\",\"name\":\"_z\",\"type\":\"string\"}],\"name\":\"setString\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_x\",\"type\":\"uint256\"}],\"name\":\"setValue\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"x\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"y\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"z\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]" - abi_slotAndOffset_06x = "[{\"inputs\":[],\"name\":\"getA\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" -} \ No newline at end of file From af3a0028febc8dc4fbfc4d67894c58b29b5ed4f8 Mon Sep 17 00:00:00 2001 From: liuxincheng Date: Thu, 27 Feb 2025 10:14:14 +0800 Subject: [PATCH 1153/1197] feat(validate): strengthen transaction result verification --- .../tron/core/capsule/TransactionCapsule.java | 13 ++++ .../org/tron/core/db/BandwidthProcessor.java | 2 +- .../main/java/org/tron/core/db/Manager.java | 6 ++ .../java/org/tron/core/db/ManagerTest.java | 61 +++++++++++++++++-- 4 files changed, 76 insertions(+), 6 deletions(-) diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java index 2b5e8b98596..95f436b19f0 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -878,4 +878,17 @@ public void checkExpiration(long nextSlotTime) throws TransactionExpirationExcep getExpiration(), nextSlotTime)); } } + + public boolean retCountIsGreatThanContractCount() { + int contractCount = getContractCount(); + return getRetCount() > contractCount && contractCount > 0; + } + + public int getRetCount() { + return this.getInstance().getRetCount(); + } + + public int getContractCount() { + return this.getInstance().getRawData().getContractCount(); + } } diff --git a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java index 73b9efaa35e..2488686bfb0 100644 --- a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -101,7 +101,7 @@ public void consume(TransactionCapsule trx, TransactionTrace trace) long resultSizeWithMaxContractRet = trx.getResultSizeWithMaxContractRet(); boolean optimizeTxs = !trx.isInBlock() || chainBaseManager .getDynamicPropertiesStore().allowConsensusLogicOptimization(); - if (optimizeTxs && resultSizeWithMaxContractRet > + if (!trx.isInBlock() && resultSizeWithMaxContractRet > Constant.MAX_RESULT_SIZE_IN_TX * contracts.size()) { throw new TooBigTransactionResultException(String.format( "Too big transaction result, TxId %s, the result size is %d bytes, maxResultSize %d", diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index cb7164a3bac..9b7bbf65621 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1802,6 +1802,12 @@ private void processBlock(BlockCapsule block, List txs) List results = new ArrayList<>(); long num = block.getNum(); for (TransactionCapsule transactionCapsule : block.getTransactions()) { + if (chainBaseManager.getDynamicPropertiesStore().allowConsensusLogicOptimization() + && transactionCapsule.retCountIsGreatThanContractCount()) { + throw new BadBlockException(String.format("The result count %d of this transaction %s is " + + "greater than its contract count %d", transactionCapsule.getRetCount(), + transactionCapsule.getTransactionId(), transactionCapsule.getContractCount())); + } transactionCapsule.setBlockNum(num); if (block.generatedByMyself) { transactionCapsule.setVerified(true); diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index a7fc2feaf87..a9cf1087c2a 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -7,8 +7,11 @@ import static org.tron.common.utils.Commons.adjustAssetBalanceV2; import static org.tron.common.utils.Commons.adjustTotalShieldedPoolValue; import static org.tron.common.utils.Commons.getExchangeStoreFinal; +import static org.tron.common.utils.StringUtil.encode58Check; import static org.tron.core.exception.BadBlockException.TypeEnum.CALC_MERKLE_ROOT_FAILED; +import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS; +import com.beust.jcommander.internal.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.protobuf.Any; @@ -481,7 +484,7 @@ public void adjustAssetBalanceV2Test() { } catch (BalanceInsufficientException e) { Assert.assertTrue(e instanceof BalanceInsufficientException); Assert.assertEquals( - "reduceAssetAmount failed! account: " + StringUtil.encode58Check(account.createDbKey()), + "reduceAssetAmount failed! account: " + encode58Check(account.createDbKey()), e.getMessage()); } @@ -744,7 +747,7 @@ public void fork() chainManager.addWitness(ByteString.copyFrom(address)); chainManager.getWitnessStore().put(address, witnessCapsule); - Block block = getSignedBlock(witnessCapsule.getAddress(), 1533529947843L, privateKey); + Block block = getSignedBlock(witnessCapsule.getAddress(), 1533529947000L, privateKey); dbManager.pushBlock(new BlockCapsule(block)); @@ -754,7 +757,7 @@ public void fork() long num = chainManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber(); BlockCapsule blockCapsule0 = createTestBlockCapsule( - 1533529947843L + 3000, + 1533529947000L + 3000, num + 1, chainManager.getDynamicPropertiesStore().getLatestBlockHeaderHash() .getByteString(), @@ -762,7 +765,7 @@ public void fork() BlockCapsule blockCapsule1 = createTestBlockCapsule( - 1533529947843L + 3000, + 1533529947000L + 3000, num + 1, chainManager.getDynamicPropertiesStore().getLatestBlockHeaderHash() .getByteString(), @@ -773,7 +776,7 @@ public void fork() BlockCapsule blockCapsule2 = createTestBlockCapsule( - 1533529947843L + 6000, + 1533529947000L + 6000, num + 2, blockCapsule1.getBlockId().getByteString(), addressToProvateKeys); dbManager.pushBlock(blockCapsule2); @@ -800,6 +803,24 @@ public void fork() Assert.assertEquals( chainManager.getHead().getBlockId(), chainManager.getDynamicPropertiesStore().getLatestBlockHeaderHash()); + + dbManager.getDynamicPropertiesStore().saveConsensusLogicOptimization(1); + BlockCapsule blockCapsule3 = + createTestBlockCapsule2(1533529947000L + 9000, + num + 3, blockCapsule2.getBlockId().getByteString(), addressToProvateKeys); + + assertThrows(BadBlockException.class, () -> dbManager.pushBlock(blockCapsule3)); + } + + private Transaction buildTransaction(com.google.protobuf.Message message, + ContractType contractType) { + Transaction.raw.Builder rawBuilder = Transaction.raw.newBuilder().addContract( + Transaction.Contract.newBuilder().setType(contractType).setParameter( + (message instanceof Any ? (Any) message : Any.pack(message))).build()); + Transaction.Builder transactionBuilder = Transaction.newBuilder().setRawData(rawBuilder) + .addRet(Transaction.Result.newBuilder().setContractRet(SUCCESS).build()) + .addRet(Transaction.Result.newBuilder().setContractRet(SUCCESS).build()); + return transactionBuilder.build(); } @Test @@ -1095,6 +1116,36 @@ private BlockCapsule createTestBlockCapsule(long time, return blockCapsule; } + private BlockCapsule createTestBlockCapsule2(long time, long number, ByteString hash, + Map addressToProvateKeys) { + TransferContract c1 = TransferContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom("f1".getBytes())) + .setAmount(1).build(); + ByteString witnessAddress = dposSlot.getScheduledWitness(dposSlot.getSlot(time)); + Protocol.BlockHeader.raw.Builder blockHeaderRawBuild = Protocol.BlockHeader.raw.newBuilder(); + Protocol.BlockHeader.raw blockHeaderRaw = blockHeaderRawBuild + .setTimestamp(time) + .setParentHash(hash) + .setWitnessAddress(witnessAddress) + .setNumber(number) + .build(); + + // block header + Protocol.BlockHeader.Builder blockHeaderBuild = Protocol.BlockHeader.newBuilder(); + Protocol.BlockHeader blockHeader = blockHeaderBuild.setRawData(blockHeaderRaw).build(); + + // block + Block.Builder blockBuild = Block.newBuilder(); + List transactions = Lists.newArrayList(buildTransaction(c1, + ContractType.TransferContract)); + transactions.forEach(blockBuild::addTransactions); + BlockCapsule blockCapsule = new BlockCapsule(blockBuild.setBlockHeader(blockHeader).build()); + blockCapsule.generatedByMyself = true; + blockCapsule.setMerkleRoot(); + blockCapsule.sign(ByteArray.fromHexString(addressToProvateKeys.get(witnessAddress))); + return blockCapsule; + } + private BlockCapsule createTestBlockCapsuleError(long time, long number, ByteString hash, Map addressToProvateKeys) { From f653cfd109ba72557ca0a7b077892ee9b000646c Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Mon, 3 Mar 2025 19:05:33 +0800 Subject: [PATCH 1154/1197] feat(event): optimize event service log --- .../org/tron/core/services/event/BlockEventCache.java | 5 +++-- .../org/tron/core/services/event/SolidEventService.java | 9 ++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/event/BlockEventCache.java b/framework/src/main/java/org/tron/core/services/event/BlockEventCache.java index aac457ba29b..3548859262e 100644 --- a/framework/src/main/java/org/tron/core/services/event/BlockEventCache.java +++ b/framework/src/main/java/org/tron/core/services/event/BlockEventCache.java @@ -43,8 +43,8 @@ public static void init(BlockCapsule.BlockId blockId) { } public static void add(BlockEvent blockEvent) throws EventException { - logger.info("Add block event, {}, {}", blockEvent.getBlockId().getString(), - blockEvent.getParentId().getString()); + logger.info("Add block event, {}, {}, {}", blockEvent.getBlockId().getString(), + blockEvent.getParentId().getString(), blockEvent.getSolidId().getString()); if (blockEventMap.get(blockEvent.getParentId()) == null) { throw new EventException("unlink BlockEvent, " + blockEvent.getBlockId().getString() + ", " @@ -83,6 +83,7 @@ public static void remove(BlockCapsule.BlockId solidId) { } public static List getSolidBlockEvents(BlockCapsule.BlockId solidId) { + logger.info("Get solid events {}, {}", solidNum, solidId); List blockEvents = new ArrayList<>(); BlockCapsule.BlockId tmp = solidId; while (tmp.getNum() > solidNum) { diff --git a/framework/src/main/java/org/tron/core/services/event/SolidEventService.java b/framework/src/main/java/org/tron/core/services/event/SolidEventService.java index 6178b247b1d..e67a1618ce1 100644 --- a/framework/src/main/java/org/tron/core/services/event/SolidEventService.java +++ b/framework/src/main/java/org/tron/core/services/event/SolidEventService.java @@ -47,7 +47,14 @@ public void work() { return; } - List blockEvents = BlockEventCache.getSolidBlockEvents(solidId); + List blockEvents; + + try { + blockEvents = BlockEventCache.getSolidBlockEvents(solidId); + } catch (Exception e) { + logger.warn("Get solid events failed. {}", e.getMessage()); + return; + } blockEvents.forEach(v -> flush(v)); From ae24ba84264dc7c70fa835f4805c0363b4ce7150 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Tue, 4 Mar 2025 10:42:04 +0800 Subject: [PATCH 1155/1197] fix BlockEventCacheTest unit test issue --- .../src/test/java/org/tron/core/event/BlockEventCacheTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/test/java/org/tron/core/event/BlockEventCacheTest.java b/framework/src/test/java/org/tron/core/event/BlockEventCacheTest.java index a23c4b5c9c8..e99433db3c6 100644 --- a/framework/src/test/java/org/tron/core/event/BlockEventCacheTest.java +++ b/framework/src/test/java/org/tron/core/event/BlockEventCacheTest.java @@ -17,6 +17,7 @@ public void test() throws Exception { BlockCapsule.BlockId b1 = new BlockCapsule.BlockId(getBlockId(), 1); be1.setBlockId(b1); be1.setParentId(b1); + be1.setSolidId(b1); try { BlockEventCache.add(be1); Assert.fail(); From a75e41dbbe888882d9077322da61076a7a6ced0a Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Tue, 4 Mar 2025 11:46:29 +0800 Subject: [PATCH 1156/1197] add SolidEventServiceTest unit test --- .../java/org/tron/core/event/SolidEventServiceTest.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/framework/src/test/java/org/tron/core/event/SolidEventServiceTest.java b/framework/src/test/java/org/tron/core/event/SolidEventServiceTest.java index ef71a3d39a9..de0300e31d7 100644 --- a/framework/src/test/java/org/tron/core/event/SolidEventServiceTest.java +++ b/framework/src/test/java/org/tron/core/event/SolidEventServiceTest.java @@ -32,6 +32,15 @@ public class SolidEventServiceTest { @Test public void test() throws Exception { + BlockEvent be0 = new BlockEvent(); + BlockCapsule.BlockId b0 = new BlockCapsule.BlockId(BlockEventCacheTest.getBlockId(), 1); + be0.setBlockId(b0); + be0.setParentId(b0); + be0.setSolidId(new BlockCapsule.BlockId(BlockEventCacheTest.getBlockId(), 100)); + BlockEventCache.init(b0); + BlockEventCache.add(be0); + solidEventService.work(); + BlockEvent be1 = new BlockEvent(); BlockCapsule.BlockId b1 = new BlockCapsule.BlockId(BlockEventCacheTest.getBlockId(), 1); be1.setBlockId(b1); From 7a5ae39a3eaedcf54f628c47de8d275d7fcb253a Mon Sep 17 00:00:00 2001 From: Asuka Date: Tue, 4 Mar 2025 12:45:29 +0800 Subject: [PATCH 1157/1197] func(cfg): parameters should have a higher priority on the command line than in the configuration file --- .../src/main/java/org/tron/core/config/args/Args.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 45fedbb3906..aebff31e95d 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -915,15 +915,18 @@ public static void setParam(final Config config) { PARAMETER.vmTrace = config.hasPath(Constant.VM_TRACE) && config.getBoolean(Constant.VM_TRACE); - if (config.hasPath(Constant.VM_SAVE_INTERNAL_TX)) { + if (!PARAMETER.saveInternalTx + && config.hasPath(Constant.VM_SAVE_INTERNAL_TX)) { PARAMETER.saveInternalTx = config.getBoolean(Constant.VM_SAVE_INTERNAL_TX); } - if (config.hasPath(Constant.VM_SAVE_FEATURED_INTERNAL_TX)) { + if (!PARAMETER.saveFeaturedInternalTx + && config.hasPath(Constant.VM_SAVE_FEATURED_INTERNAL_TX)) { PARAMETER.saveFeaturedInternalTx = config.getBoolean(Constant.VM_SAVE_FEATURED_INTERNAL_TX); } - if (config.hasPath(Constant.VM_SAVE_CANCEL_ALL_UNFREEZE_V2_DETAILS)) { + if (!PARAMETER.saveCancelAllUnfreezeV2Details + && config.hasPath(Constant.VM_SAVE_CANCEL_ALL_UNFREEZE_V2_DETAILS)) { PARAMETER.saveCancelAllUnfreezeV2Details = config.getBoolean(Constant.VM_SAVE_CANCEL_ALL_UNFREEZE_V2_DETAILS); } From 658a4e22dc69081496913df4ea28dfd304764039 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Tue, 4 Mar 2025 16:17:47 +0800 Subject: [PATCH 1158/1197] feat(event): optimize transaction trigger acquisition --- .../capsule/TransactionLogTriggerCapsule.java | 43 +++++++++++++++-- .../core/services/event/BlockEventGet.java | 47 ++++++++++++++++--- .../services/event/HistoryEventService.java | 2 +- .../TransactionLogTriggerCapsuleTest.java | 42 +++++++++++++++++ .../tron/core/event/BlockEventGetTest.java | 28 +++++++++++ 5 files changed, 152 insertions(+), 10 deletions(-) diff --git a/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java b/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java index f5d457f541d..efd580a60cd 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java +++ b/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java @@ -49,6 +49,12 @@ public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule this(trxCapsule, blockCapsule, 0, 0, 0, null, 0); } + public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, + BlockCapsule blockCapsule, + TransactionInfo transactionInfo) { + this(trxCapsule, blockCapsule, 0, 0, 0, transactionInfo, 0); + } + public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule blockCapsule, int txIndex, long preCumulativeEnergyUsed, long preCumulativeLogCount, TransactionInfo transactionInfo, long energyUnitPrice) { @@ -63,7 +69,7 @@ public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule String transactionHash = trxCapsule.getTransactionId().toString(); transactionLogTrigger.setTransactionId(transactionHash); transactionLogTrigger.setTimeStamp(blockCapsule.getTimeStamp()); - transactionLogTrigger.setBlockNumber(trxCapsule.getBlockNum()); + transactionLogTrigger.setBlockNumber(blockCapsule.getNum()); transactionLogTrigger.setData(Hex.toHexString(trxCapsule .getInstance().getRawData().getData().toByteArray())); @@ -281,6 +287,7 @@ public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule if (Objects.nonNull(contractAddress) && contractAddress.size() > 0) { if (Objects.nonNull(transactionInfo) + && EventPluginLoader.getInstance().isTransactionLogTriggerEthCompatible() && contractType != null && contractType != CreateSmartContract) { transactionLogTrigger.setContractAddress(null); } else { @@ -294,8 +301,38 @@ public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule getInternalTransactionList(programResult.getInternalTransactions())); } + if (Objects.isNull(trxTrace) && Objects.nonNull(transactionInfo)) { + Protocol.ResourceReceipt receipt = transactionInfo.getReceipt(); + energyUsageTotal = receipt.getEnergyUsageTotal(); + transactionLogTrigger.setEnergyFee(receipt.getEnergyFee()); + transactionLogTrigger.setOriginEnergyUsage(receipt.getOriginEnergyUsage()); + transactionLogTrigger.setEnergyUsageTotal(energyUsageTotal); + transactionLogTrigger.setNetUsage(receipt.getNetUsage()); + transactionLogTrigger.setNetFee(receipt.getNetFee()); + transactionLogTrigger.setEnergyUsage(receipt.getEnergyUsage()); + + if (transactionInfo.getContractResultCount() > 0) { + ByteString contractResult = transactionInfo.getContractResult(0); + if (Objects.nonNull(contractResult) && contractResult.size() > 0) { + transactionLogTrigger.setContractResult(Hex.toHexString(contractResult.toByteArray())); + } + } + + ByteString contractAddress = transactionInfo.getContractAddress(); + if (Objects.nonNull(contractAddress) && contractAddress.size() > 0) { + if (EventPluginLoader.getInstance().isTransactionLogTriggerEthCompatible() + && contractType != null && contractType != CreateSmartContract) { + transactionLogTrigger.setContractAddress(null); + } else { + transactionLogTrigger + .setContractAddress(StringUtil.encode58Check((contractAddress.toByteArray()))); + } + } + } + // process transactionInfo list, only enabled when ethCompatible is true - if (Objects.nonNull(transactionInfo)) { + if (Objects.nonNull(transactionInfo) + && EventPluginLoader.getInstance().isTransactionLogTriggerEthCompatible()) { transactionLogTrigger.setTransactionIndex(txIndex); transactionLogTrigger.setCumulativeEnergyUsed(preCumulativeEnergyUsed + energyUsageTotal); transactionLogTrigger.setPreCumulativeLogCount(preCumulativeLogCount); @@ -309,7 +346,7 @@ public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule logPojo.setAddress((log.getAddress() != null) ? Hex.toHexString(log.getAddress().toByteArray()) : ""); logPojo.setBlockHash(blockHash); - logPojo.setBlockNumber(trxCapsule.getBlockNum()); + logPojo.setBlockNumber(blockCapsule.getNum()); logPojo.setData(Hex.toHexString(log.getData().toByteArray())); logPojo.setLogIndex(preCumulativeLogCount + index); diff --git a/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java b/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java index 25fb54bce8c..8733faaa1c4 100644 --- a/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java +++ b/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java @@ -322,12 +322,7 @@ public List getTransactionLogTrigger(BlockCapsule long solidNum) { List transactionLogTriggerCapsules = new ArrayList<>(); if (!EventPluginLoader.getInstance().isTransactionLogTriggerEthCompatible()) { - for (TransactionCapsule t : block.getTransactions()) { - TransactionLogTriggerCapsule trx = new TransactionLogTriggerCapsule(t, block); - trx.setLatestSolidifiedBlockNumber(solidNum); - transactionLogTriggerCapsules.add(trx); - } - return transactionLogTriggerCapsules; + return getTransactionTriggers(block, solidNum); } List transactionCapsuleList = block.getTransactions(); GrpcAPI.TransactionInfoList transactionInfoList = GrpcAPI @@ -389,4 +384,44 @@ public long getEnergyPrice(long blockTime) { } return energyPrice; } + + public List getTransactionTriggers(BlockCapsule block, + long solidNum) { + List list = new ArrayList<>(); + if (block.getTransactions().size() == 0) { + return list; + } + GrpcAPI.TransactionInfoList transactionInfoList = GrpcAPI + .TransactionInfoList.newBuilder().build(); + GrpcAPI.TransactionInfoList.Builder transactionInfoListBuilder = GrpcAPI + .TransactionInfoList.newBuilder(); + try { + TransactionRetCapsule result = manager.getChainBaseManager().getTransactionRetStore() + .getTransactionInfoByBlockNum(ByteArray.fromLong(block.getNum())); + if (!Objects.isNull(result) && !Objects.isNull(result.getInstance())) { + result.getInstance().getTransactioninfoList() + .forEach(transactionInfoListBuilder::addTransactionInfo); + transactionInfoList = transactionInfoListBuilder.build(); + } + } catch (Exception e) { + logger.warn("Get TransactionInfo failed, blockNum {}, {}.", block.getNum(), e.getMessage()); + } + + if (block.getTransactions().size() != transactionInfoList.getTransactionInfoCount()) { + for (TransactionCapsule t : block.getTransactions()) { + TransactionLogTriggerCapsule triggerCapsule = new TransactionLogTriggerCapsule(t, block); + triggerCapsule.setLatestSolidifiedBlockNumber(solidNum); + list.add(triggerCapsule); + } + } else { + for (int i = 0; i < transactionInfoList.getTransactionInfoCount(); i++) { + TransactionLogTriggerCapsule triggerCapsule = new TransactionLogTriggerCapsule( + block.getTransactions().get(i), block, transactionInfoList.getTransactionInfo(i)); + triggerCapsule.setLatestSolidifiedBlockNumber(solidNum); + list.add(triggerCapsule); + } + } + + return list; + } } \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java b/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java index 73422944f08..fb202734b22 100644 --- a/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java +++ b/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java @@ -39,7 +39,7 @@ public void init() { isRunning = true; - new Thread(() -> syncEvent()).start(); + new Thread(() -> syncEvent(), "history-event").start(); logger.info("History event service start."); } diff --git a/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java index a2487ac470b..ce0f63ef7a4 100644 --- a/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java +++ b/framework/src/test/java/org/tron/common/logsfilter/TransactionLogTriggerCapsuleTest.java @@ -4,11 +4,13 @@ import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; import com.google.protobuf.ByteString; +import org.bouncycastle.util.encoders.Hex; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.tron.common.logsfilter.capsule.TransactionLogTriggerCapsule; import org.tron.common.utils.Sha256Hash; +import org.tron.common.utils.StringUtil; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.p2p.utils.ByteArray; @@ -242,6 +244,46 @@ public void testConstructorWithCreateSmartContract() { Assert.assertNotNull(triggerCapsule.getTransactionLogTrigger().getFromAddress()); } + @Test + public void testConstructorWithCreateTransactionInfo() { + Protocol.TransactionInfo.Builder infoBuild = Protocol.TransactionInfo.newBuilder(); + + Protocol.ResourceReceipt.Builder resourceBuild = Protocol.ResourceReceipt.newBuilder(); + resourceBuild.setEnergyFee(1); + resourceBuild.setEnergyUsageTotal(2); + resourceBuild.setEnergyUsage(3); + resourceBuild.setOriginEnergyUsage(4); + resourceBuild.setNetFee(5); + resourceBuild.setNetUsage(6); + + infoBuild + .setContractAddress(ByteString.copyFrom(ByteArray.fromHexString(CONTRACT_ADDRESS))) + .addContractResult(ByteString.copyFrom(ByteArray.fromHexString("112233"))) + .setReceipt(resourceBuild.build()); + + SmartContractOuterClass.CreateSmartContract.Builder builder2 = + SmartContractOuterClass.CreateSmartContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); + TransactionCapsule tc = new TransactionCapsule(builder2.build(), + Protocol.Transaction.Contract.ContractType.CreateSmartContract); + BlockCapsule bc = new BlockCapsule(1, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), Sha256Hash.ZERO_HASH.getByteString()); + + + TransactionLogTriggerCapsule trigger = + new TransactionLogTriggerCapsule(tc, bc, infoBuild.build()); + + Assert.assertEquals(1, trigger.getTransactionLogTrigger().getEnergyFee()); + Assert.assertEquals(2, trigger.getTransactionLogTrigger().getEnergyUsageTotal()); + Assert.assertEquals(3, trigger.getTransactionLogTrigger().getEnergyUsage()); + Assert.assertEquals(4, trigger.getTransactionLogTrigger().getOriginEnergyUsage()); + Assert.assertEquals(5, trigger.getTransactionLogTrigger().getNetFee()); + Assert.assertEquals(6, trigger.getTransactionLogTrigger().getNetUsage()); + + Assert.assertEquals(StringUtil.encode58Check(Hex.decode(CONTRACT_ADDRESS)), + trigger.getTransactionLogTrigger().getContractAddress()); + Assert.assertEquals("112233", trigger.getTransactionLogTrigger().getContractResult()); + } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java b/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java index db959d9a0fd..fb10f261482 100644 --- a/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java +++ b/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java @@ -6,6 +6,7 @@ import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.ArrayList; +import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import lombok.extern.slf4j.Slf4j; import org.junit.After; @@ -18,9 +19,11 @@ import org.tron.common.logsfilter.EventPluginConfig; import org.tron.common.logsfilter.EventPluginLoader; import org.tron.common.logsfilter.TriggerConfig; +import org.tron.common.logsfilter.capsule.TransactionLogTriggerCapsule; import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.ByteArray; import org.tron.common.utils.PublicMethod; +import org.tron.common.utils.Sha256Hash; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; @@ -182,4 +185,29 @@ public void test() throws Exception { Assert.fail(); } } + + @Test + public void getTransactionTriggers() { + BlockEventGet blockEventGet = new BlockEventGet(); + BlockCapsule bc = new BlockCapsule(1, Sha256Hash.ZERO_HASH, + 100, Sha256Hash.ZERO_HASH.getByteString()); + + List list = blockEventGet.getTransactionTriggers(bc, 1); + Assert.assertEquals(0, list.size()); + + List transactionList = new ArrayList<>(); + + Protocol.Transaction.raw rw = Protocol.Transaction.raw.newBuilder() + .addContract(Protocol.Transaction.Contract.newBuilder().build()).build(); + + Protocol.Transaction transaction = Protocol.Transaction.newBuilder().setRawData(rw).build(); + + transactionList.add(transaction); + + bc = new BlockCapsule(100, ByteString.empty(), 1, transactionList); + + list = blockEventGet.getTransactionTriggers(bc, 1); + Assert.assertEquals(1, list.size()); + Assert.assertEquals(100, list.get(0).getTransactionLogTrigger().getTimeStamp()); + } } \ No newline at end of file From 67c4a09842d513ab653647dde0f697583b010789 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 4 Mar 2025 15:51:38 +0800 Subject: [PATCH 1159/1197] feat(service): exit when services init failed 1. init logback xml 2. init event plugin 3. init prometheus 4. init p2p service 5. init zksnark --- .../java/org/tron/common/log/LogService.java | 26 ++++++++++ .../org/tron/common/prometheus/Metrics.java | 7 ++- .../org/tron/core/exception/TronError.java | 5 ++ .../main/java/org/tron/core/db/Manager.java | 5 +- .../org/tron/core/net/TronNetService.java | 3 +- .../org/tron/core/zen/ZksnarkInitService.java | 3 +- .../main/java/org/tron/program/FullNode.java | 24 +--------- .../tron/core/db/TransactionExpireTest.java | 1 + .../tron/core/exception/TronErrorTest.java | 48 +++++++++++++++++++ .../core/services/RpcApiServicesTest.java | 1 + .../filter/HttpApiAccessFilterTest.java | 1 + .../LiteFnQueryGrpcInterceptorTest.java | 1 + .../filter/LiteFnQueryHttpFilterTest.java | 1 + .../filter/RpcApiAccessInterceptorTest.java | 1 + .../http/TriggerSmartContractServletTest.java | 1 + 15 files changed, 98 insertions(+), 30 deletions(-) create mode 100644 common/src/main/java/org/tron/common/log/LogService.java diff --git a/common/src/main/java/org/tron/common/log/LogService.java b/common/src/main/java/org/tron/common/log/LogService.java new file mode 100644 index 00000000000..801e13f54f7 --- /dev/null +++ b/common/src/main/java/org/tron/common/log/LogService.java @@ -0,0 +1,26 @@ +package org.tron.common.log; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import java.io.File; +import org.slf4j.LoggerFactory; +import org.tron.core.exception.TronError; + +public class LogService { + + public static void load(String path) { + try { + File file = new File(path); + if (!file.exists() || !file.isFile() || !file.canRead()) { + return; + } + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(lc); + lc.reset(); + configurator.doConfigure(file); + } catch (Exception e) { + throw new TronError(e, TronError.ErrCode.LOG_LOAD); + } + } +} diff --git a/common/src/main/java/org/tron/common/prometheus/Metrics.java b/common/src/main/java/org/tron/common/prometheus/Metrics.java index 3f37cf331aa..6774dd7c315 100644 --- a/common/src/main/java/org/tron/common/prometheus/Metrics.java +++ b/common/src/main/java/org/tron/common/prometheus/Metrics.java @@ -5,9 +5,9 @@ import io.prometheus.client.Histogram; import io.prometheus.client.exporter.HTTPServer; import io.prometheus.client.hotspot.DefaultExports; -import java.io.IOException; import lombok.extern.slf4j.Slf4j; import org.tron.common.parameter.CommonParameter; +import org.tron.core.exception.TronError; @Slf4j(topic = "metrics") public class Metrics { @@ -32,9 +32,8 @@ public static synchronized void init() { new HTTPServer.Builder().withPort(port).build(); logger.info("prometheus exposed on port : {}", port); initialized = true; - } catch (IOException e) { - CommonParameter.getInstance().setMetricsPrometheusEnable(false); - logger.error("{}", e.getMessage()); + } catch (Exception e) { + throw new TronError(e, TronError.ErrCode.PROMETHEUS_INIT); } } } diff --git a/common/src/main/java/org/tron/core/exception/TronError.java b/common/src/main/java/org/tron/core/exception/TronError.java index c7ddfc38bad..8946a6528b3 100644 --- a/common/src/main/java/org/tron/core/exception/TronError.java +++ b/common/src/main/java/org/tron/core/exception/TronError.java @@ -40,6 +40,11 @@ public enum ErrCode { EVENT_SUBSCRIBE_ERROR(1), AUTO_STOP_PARAMS(1), API_SERVER_INIT(1), + EVENT_SUBSCRIBE_INIT(1), + PROMETHEUS_INIT(1), + TRON_NET_SERVICE_INIT(1), + ZCASH_INIT(1), + LOG_LOAD(1), SOLID_NODE_INIT(0); private final int code; diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 9b7bbf65621..3635f38d9ad 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -137,6 +137,7 @@ import org.tron.core.metrics.MetricsUtil; import org.tron.core.service.MortgageService; import org.tron.core.service.RewardViCalService; +import org.tron.core.services.event.exception.EventException; import org.tron.core.store.AccountAssetStore; import org.tron.core.store.AccountIdIndexStore; import org.tron.core.store.AccountIndexStore; @@ -2098,7 +2099,7 @@ private void startEventSubscribing() { .start(Args.getInstance().getEventPluginConfig()); if (!eventPluginLoaded) { - logger.error("Failed to load eventPlugin."); + throw new EventException("Failed to load eventPlugin."); } FilterQuery eventFilter = Args.getInstance().getEventFilter(); @@ -2107,7 +2108,7 @@ private void startEventSubscribing() { } } catch (Exception e) { - logger.error("{}", e); + throw new TronError(e, TronError.ErrCode.EVENT_SUBSCRIBE_INIT); } } diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 5b99f94c0db..8b97c8d9f4d 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -15,6 +15,7 @@ import org.tron.common.overlay.message.Message; import org.tron.common.parameter.CommonParameter; import org.tron.core.config.args.Args; +import org.tron.core.exception.TronError; import org.tron.core.net.message.adv.TransactionMessage; import org.tron.core.net.messagehandler.TransactionsMsgHandler; import org.tron.core.net.peer.PeerConnection; @@ -102,7 +103,7 @@ public void start() { effectiveCheckService.init(); logger.info("Net service start successfully"); } catch (Exception e) { - logger.error("Net service start failed", e); + throw new TronError(e, TronError.ErrCode.TRON_NET_SERVICE_INIT); } } diff --git a/framework/src/main/java/org/tron/core/zen/ZksnarkInitService.java b/framework/src/main/java/org/tron/core/zen/ZksnarkInitService.java index 04405dfc758..a1f812426f7 100644 --- a/framework/src/main/java/org/tron/core/zen/ZksnarkInitService.java +++ b/framework/src/main/java/org/tron/core/zen/ZksnarkInitService.java @@ -9,6 +9,7 @@ import org.springframework.stereotype.Component; import org.tron.common.zksnark.JLibrustzcash; import org.tron.common.zksnark.LibrustzcashParam; +import org.tron.core.exception.TronError; import org.tron.core.exception.ZksnarkException; @Slf4j(topic = "API") @@ -40,7 +41,7 @@ public static void librustzcashInitZksnarkParams() { JLibrustzcash.librustzcashInitZksnarkParams( new LibrustzcashParam.InitZksnarkParams(spendPath, spendHash, outputPath, outputHash)); } catch (ZksnarkException e) { - logger.error("librustzcashInitZksnarkParams fail!", e); + throw new TronError(e, TronError.ErrCode.ZCASH_INIT); } logger.info("init zk param done"); } diff --git a/framework/src/main/java/org/tron/program/FullNode.java b/framework/src/main/java/org/tron/program/FullNode.java index 7fc72e6ba88..ef23d20ce52 100644 --- a/framework/src/main/java/org/tron/program/FullNode.java +++ b/framework/src/main/java/org/tron/program/FullNode.java @@ -1,16 +1,13 @@ package org.tron.program; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; import com.beust.jcommander.JCommander; -import java.io.File; import lombok.extern.slf4j.Slf4j; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.exit.ExitManager; +import org.tron.common.log.LogService; import org.tron.common.parameter.CommonParameter; import org.tron.common.prometheus.Metrics; import org.tron.core.Constant; @@ -20,23 +17,6 @@ @Slf4j(topic = "app") public class FullNode { - - public static void load(String path) { - try { - File file = new File(path); - if (!file.exists() || !file.isFile() || !file.canRead()) { - return; - } - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - JoranConfigurator configurator = new JoranConfigurator(); - configurator.setContext(lc); - lc.reset(); - configurator.doConfigure(file); - } catch (Exception e) { - logger.error(e.getMessage()); - } - } - /** * Start the FullNode. */ @@ -46,7 +26,7 @@ public static void main(String[] args) { Args.setParam(args, Constant.TESTNET_CONF); CommonParameter parameter = Args.getInstance(); - load(parameter.getLogbackPath()); + LogService.load(parameter.getLogbackPath()); if (parameter.isHelp()) { JCommander jCommander = JCommander.newBuilder().addObject(Args.PARAMETER).build(); diff --git a/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java b/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java index 5193f4128cd..420b54525e4 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java @@ -46,6 +46,7 @@ public void init() throws IOException { Args.setParam(new String[] {"--output-directory", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); CommonParameter.PARAMETER.setMinEffectiveConnection(0); + CommonParameter.getInstance().setP2pDisable(true); context = new TronApplicationContext(DefaultConfig.class); wallet = context.getBean(Wallet.class); diff --git a/framework/src/test/java/org/tron/core/exception/TronErrorTest.java b/framework/src/test/java/org/tron/core/exception/TronErrorTest.java index 0ec1bcca349..3176a62f56c 100644 --- a/framework/src/test/java/org/tron/core/exception/TronErrorTest.java +++ b/framework/src/test/java/org/tron/core/exception/TronErrorTest.java @@ -1,10 +1,36 @@ package org.tron.core.exception; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mockStatic; + +import java.io.IOException; +import java.nio.file.Path; +import org.junit.After; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.junit.runner.RunWith; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.tron.common.log.LogService; +import org.tron.common.zksnark.JLibrustzcash; +import org.tron.core.zen.ZksnarkInitService; +@RunWith(MockitoJUnitRunner.class) public class TronErrorTest { + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @After + public void clearMocks() { + Mockito.clearAllCaches(); + } + @Test public void testTronError() { TronError tronError = new TronError("message", TronError.ErrCode.WITNESS_KEYSTORE_LOAD); @@ -16,4 +42,26 @@ public void testTronError() { tronError = new TronError(new Throwable(), TronError.ErrCode.LEVELDB_INIT); Assert.assertEquals(tronError.getErrCode(), TronError.ErrCode.LEVELDB_INIT); } + + @Test + public void ZksnarkInitTest() { + try (MockedStatic mock = mockStatic(JLibrustzcash.class)) { + mock.when(JLibrustzcash::isOpenZen).thenReturn(true); + mock.when(() -> JLibrustzcash.librustzcashInitZksnarkParams(any())) + .thenAnswer(invocation -> { + throw new ZksnarkException("Zksnark init failed"); + }); + TronError thrown = assertThrows(TronError.class, + ZksnarkInitService::librustzcashInitZksnarkParams); + assertEquals(TronError.ErrCode.ZCASH_INIT, thrown.getErrCode()); + } + } + + @Test + public void LogLoadTest() throws IOException { + LogService.load("non-existent.xml"); + Path path = temporaryFolder.newFile("logback.xml").toPath(); + TronError thrown = assertThrows(TronError.class, () -> LogService.load(path.toString())); + assertEquals(TronError.ErrCode.LOG_LOAD, thrown.getErrCode()); + } } diff --git a/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java b/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java index 7179215393f..3ae090d3caf 100644 --- a/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java +++ b/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java @@ -143,6 +143,7 @@ public static void init() throws IOException { getInstance().setRpcOnPBFTPort(PublicMethod.chooseRandomPort()); getInstance().setMetricsPrometheusPort(PublicMethod.chooseRandomPort()); getInstance().setMetricsPrometheusEnable(true); + getInstance().setP2pDisable(true); String fullNode = String.format("%s:%d", getInstance().getNodeLanIp(), getInstance().getRpcPort()); String solidityNode = String.format("%s:%d", getInstance().getNodeLanIp(), diff --git a/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java b/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java index 9484155a0b7..420d890aa48 100644 --- a/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/HttpApiAccessFilterTest.java @@ -45,6 +45,7 @@ public class HttpApiAccessFilterTest extends BaseTest { Args.getInstance().setPBFTHttpPort(PublicMethod.chooseRandomPort()); Args.getInstance().setSolidityNodeHttpEnable(true); Args.getInstance().setSolidityHttpPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setP2pDisable(true); } @Test diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java index c5c7185b6d8..84869ea0750 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryGrpcInterceptorTest.java @@ -61,6 +61,7 @@ public static void init() throws IOException { Args.getInstance().setRpcOnSolidityPort(PublicMethod.chooseRandomPort()); Args.getInstance().setRpcPBFTEnable(true); Args.getInstance().setRpcOnPBFTPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setP2pDisable(true); String fullnode = String.format("%s:%d", Args.getInstance().getNodeLanIp(), Args.getInstance().getRpcPort()); String solidityNode = String.format("%s:%d", Args.getInstance().getNodeLanIp(), diff --git a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java index a9068c228b6..0f0bdf1eb1f 100644 --- a/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/LiteFnQueryHttpFilterTest.java @@ -44,6 +44,7 @@ public class LiteFnQueryHttpFilterTest extends BaseTest { Args.getInstance().setJsonRpcHttpFullNodeEnable(false); Args.getInstance().setJsonRpcHttpSolidityNodeEnable(false); Args.getInstance().setJsonRpcHttpPBFTNodeEnable(false); + Args.getInstance().setP2pDisable(true); } /** diff --git a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java index 5845a89c2e4..900ca304e7d 100644 --- a/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java +++ b/framework/src/test/java/org/tron/core/services/filter/RpcApiAccessInterceptorTest.java @@ -62,6 +62,7 @@ public static void init() throws IOException { Args.getInstance().setRpcOnSolidityPort(PublicMethod.chooseRandomPort()); Args.getInstance().setRpcPBFTEnable(true); Args.getInstance().setRpcOnPBFTPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setP2pDisable(true); String fullNode = String.format("%s:%d", Args.getInstance().getNodeLanIp(), Args.getInstance().getRpcPort()); String solidityNode = String.format("%s:%d", Args.getInstance().getNodeLanIp(), diff --git a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java index e9cd9cb1f26..4cbb729a787 100644 --- a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java @@ -35,6 +35,7 @@ public static void init() throws Exception { Args.getInstance().needSyncCheck = false; Args.getInstance().setFullNodeHttpEnable(true); Args.getInstance().setFullNodeHttpPort(PublicMethod.chooseRandomPort()); + Args.getInstance().setP2pDisable(true); httpNode = String.format("%s:%d", "127.0.0.1", Args.getInstance().getFullNodeHttpPort()); } From 300d3ac381fa2ec28590a454623a32645f9fde93 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Thu, 6 Mar 2025 22:18:11 +0800 Subject: [PATCH 1160/1197] feat(build): add implicit_dependency for build Task ':xxx' uses this output of task ':xxx' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed. --- chainbase/build.gradle | 1 + framework/build.gradle | 4 ++++ plugins/build.gradle | 2 +- protocol/build.gradle | 1 + 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/chainbase/build.gradle b/chainbase/build.gradle index 0fb98629856..bc82d9496c3 100644 --- a/chainbase/build.gradle +++ b/chainbase/build.gradle @@ -41,6 +41,7 @@ test { } jacocoTestReport { + dependsOn(processResources) // explicit_dependency reports { xml.enabled = true html.enabled = true diff --git a/framework/build.gradle b/framework/build.gradle index fb4f2278294..0f04685f2d8 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -156,6 +156,10 @@ def binaryRelease(taskName, jarName, mainClass) { include "/**" } + // explicit_dependency + dependsOn (project(':actuator').jar, project(':consensus').jar, project(':chainbase').jar, + project(':crypto').jar, project(':common').jar, project(':protocol').jar) + from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) diff --git a/plugins/build.gradle b/plugins/build.gradle index 03ac6d84150..01afaa01708 100644 --- a/plugins/build.gradle +++ b/plugins/build.gradle @@ -94,7 +94,7 @@ def binaryRelease(taskName, jarName, mainClass) { from(sourceSets.main.output) { include "/**" } - + dependsOn project(':protocol').jar // explicit_dependency from { configurations.runtimeClasspath.collect { // https://docs.gradle.org/current/userguide/upgrading_version_6.html#changes_6.3 it.isDirectory() ? it : zipTree(it) diff --git a/protocol/build.gradle b/protocol/build.gradle index 02158f9fdd4..535fac43a65 100644 --- a/protocol/build.gradle +++ b/protocol/build.gradle @@ -66,3 +66,4 @@ clean.doFirst { delete "src/main/java" } +processResources.dependsOn(generateProto) // explicit_dependency From 09c803ffc32dc52f87f81d5d7b39ee01b3ec2d38 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Fri, 7 Mar 2025 12:48:16 +0800 Subject: [PATCH 1161/1197] add getTransactionTriggers unit test --- .../capsule/TransactionLogTriggerCapsule.java | 20 ++++-- .../core/services/event/BlockEventGet.java | 4 +- .../tron/core/event/BlockEventGetTest.java | 69 ++++++++++++++++++- 3 files changed, 85 insertions(+), 8 deletions(-) diff --git a/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java b/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java index efd580a60cd..ace19060b1f 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java +++ b/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java @@ -6,7 +6,9 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import lombok.Getter; import lombok.Setter; @@ -50,14 +52,20 @@ public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule } public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, - BlockCapsule blockCapsule, - TransactionInfo transactionInfo) { - this(trxCapsule, blockCapsule, 0, 0, 0, transactionInfo, 0); + BlockCapsule blockCapsule, TransactionInfo transactionInfo) { + this(trxCapsule, blockCapsule, 0, 0, 0, transactionInfo, 0, true); } public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule blockCapsule, int txIndex, long preCumulativeEnergyUsed, long preCumulativeLogCount, TransactionInfo transactionInfo, long energyUnitPrice) { + this(trxCapsule, blockCapsule, txIndex, preCumulativeEnergyUsed, preCumulativeLogCount, + transactionInfo, energyUnitPrice, false); + } + + public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule blockCapsule, + int txIndex, long preCumulativeEnergyUsed, long preCumulativeLogCount, + TransactionInfo transactionInfo, long energyUnitPrice, boolean flag) { transactionLogTrigger = new TransactionLogTrigger(); String blockHash = ""; @@ -69,7 +77,7 @@ public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule String transactionHash = trxCapsule.getTransactionId().toString(); transactionLogTrigger.setTransactionId(transactionHash); transactionLogTrigger.setTimeStamp(blockCapsule.getTimeStamp()); - transactionLogTrigger.setBlockNumber(blockCapsule.getNum()); + transactionLogTrigger.setBlockNumber(trxCapsule.getBlockNum()); transactionLogTrigger.setData(Hex.toHexString(trxCapsule .getInstance().getRawData().getData().toByteArray())); @@ -301,7 +309,7 @@ public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule getInternalTransactionList(programResult.getInternalTransactions())); } - if (Objects.isNull(trxTrace) && Objects.nonNull(transactionInfo)) { + if (Objects.isNull(trxTrace) && Objects.nonNull(transactionInfo) && flag) { Protocol.ResourceReceipt receipt = transactionInfo.getReceipt(); energyUsageTotal = receipt.getEnergyUsageTotal(); transactionLogTrigger.setEnergyFee(receipt.getEnergyFee()); @@ -346,7 +354,7 @@ public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule logPojo.setAddress((log.getAddress() != null) ? Hex.toHexString(log.getAddress().toByteArray()) : ""); logPojo.setBlockHash(blockHash); - logPojo.setBlockNumber(blockCapsule.getNum()); + logPojo.setBlockNumber(trxCapsule.getBlockNum()); logPojo.setData(Hex.toHexString(log.getData().toByteArray())); logPojo.setLogIndex(preCumulativeLogCount + index); diff --git a/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java b/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java index 8733faaa1c4..fd34a1fe50f 100644 --- a/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java +++ b/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java @@ -54,6 +54,7 @@ public class BlockEventGet { public BlockEvent getBlockEvent(long blockNum) throws Exception { BlockCapsule block = manager.getChainBaseManager().getBlockByNum(blockNum); + block.getTransactions().forEach(t -> t.setBlockNum(block.getNum())); long solidNum = manager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); BlockEvent blockEvent = new BlockEvent(); blockEvent.setBlockId(block.getBlockId()); @@ -359,7 +360,7 @@ public List getTransactionLogTrigger(BlockCapsule TransactionCapsule transactionCapsule = transactionCapsuleList.get(i); transactionCapsule.setBlockNum(block.getNum()); TransactionLogTriggerCapsule trx = new TransactionLogTriggerCapsule(transactionCapsule, block, - i, cumulativeEnergyUsed, cumulativeLogCount, transactionInfo, energyUnitPrice); + i, cumulativeEnergyUsed, cumulativeLogCount, transactionInfo, energyUnitPrice, true); trx.setLatestSolidifiedBlockNumber(solidNum); cumulativeEnergyUsed += trx.getTransactionLogTrigger().getEnergyUsageTotal(); cumulativeLogCount += transactionInfo.getLogCount(); @@ -391,6 +392,7 @@ public List getTransactionTriggers(BlockCapsule bl if (block.getTransactions().size() == 0) { return list; } + GrpcAPI.TransactionInfoList transactionInfoList = GrpcAPI .TransactionInfoList.newBuilder().build(); GrpcAPI.TransactionInfoList.Builder transactionInfoListBuilder = GrpcAPI diff --git a/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java b/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java index fb10f261482..14479566815 100644 --- a/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java +++ b/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java @@ -1,5 +1,7 @@ package org.tron.core.event; +import static org.mockito.Mockito.mock; + import com.google.protobuf.ByteString; import java.io.IOException; import java.time.LocalDateTime; @@ -15,6 +17,7 @@ import org.junit.ClassRule; import org.junit.Test; import org.junit.rules.TemporaryFolder; +import org.mockito.Mockito; import org.tron.common.application.TronApplicationContext; import org.tron.common.logsfilter.EventPluginConfig; import org.tron.common.logsfilter.EventPluginLoader; @@ -23,11 +26,13 @@ import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.ByteArray; import org.tron.common.utils.PublicMethod; +import org.tron.common.utils.ReflectUtils; import org.tron.common.utils.Sha256Hash; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.TransactionRetCapsule; import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; @@ -38,6 +43,7 @@ import org.tron.core.services.event.BlockEventGet; import org.tron.core.services.event.bo.BlockEvent; import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.store.TransactionRetStore; import org.tron.protos.Protocol; @Slf4j @@ -187,7 +193,7 @@ public void test() throws Exception { } @Test - public void getTransactionTriggers() { + public void getTransactionTriggers() throws Exception { BlockEventGet blockEventGet = new BlockEventGet(); BlockCapsule bc = new BlockCapsule(1, Sha256Hash.ZERO_HASH, 100, Sha256Hash.ZERO_HASH.getByteString()); @@ -209,5 +215,66 @@ public void getTransactionTriggers() { list = blockEventGet.getTransactionTriggers(bc, 1); Assert.assertEquals(1, list.size()); Assert.assertEquals(100, list.get(0).getTransactionLogTrigger().getTimeStamp()); + + Protocol.TransactionInfo.Builder infoBuild = Protocol.TransactionInfo.newBuilder(); + + Protocol.ResourceReceipt.Builder resourceBuild = Protocol.ResourceReceipt.newBuilder(); + resourceBuild.setEnergyFee(1); + resourceBuild.setEnergyUsageTotal(2); + resourceBuild.setEnergyUsage(3); + resourceBuild.setOriginEnergyUsage(4); + resourceBuild.setNetFee(5); + resourceBuild.setNetUsage(6); + + String address = "A0B4750E2CD76E19DCA331BF5D089B71C3C2798548"; + infoBuild + .setContractAddress(ByteString.copyFrom(ByteArray.fromHexString(address))) + .addContractResult(ByteString.copyFrom(ByteArray.fromHexString("112233"))) + .setReceipt(resourceBuild.build()); + + Manager manager = mock(Manager.class); + ReflectUtils.setFieldValue(blockEventGet, "manager", manager); + + ChainBaseManager chainBaseManager = mock(ChainBaseManager.class); + Mockito.when(manager.getChainBaseManager()).thenReturn(chainBaseManager); + + TransactionRetStore transactionRetStore = mock(TransactionRetStore.class); + Mockito.when(chainBaseManager.getTransactionRetStore()).thenReturn(transactionRetStore); + + Protocol.TransactionRet transactionRet = Protocol.TransactionRet.newBuilder() + .addTransactioninfo(infoBuild.build()).build(); + + TransactionRetCapsule result = new TransactionRetCapsule(transactionRet.toByteArray()); + + Mockito.when(transactionRetStore.getTransactionInfoByBlockNum(ByteArray.fromLong(0))) + .thenReturn(result); + + Protocol.Block block = Protocol.Block.newBuilder() + .addTransactions(transaction).build(); + + BlockCapsule blockCapsule = new BlockCapsule(block); + blockCapsule.getTransactions().forEach(t -> t.setBlockNum(blockCapsule.getNum())); + + list = blockEventGet.getTransactionTriggers(blockCapsule, 1); + + Assert.assertEquals(1, list.size()); + Assert.assertEquals(1, + list.get(0).getTransactionLogTrigger().getLatestSolidifiedBlockNumber()); + Assert.assertEquals(0, + list.get(0).getTransactionLogTrigger().getBlockNumber()); + Assert.assertEquals(2, + list.get(0).getTransactionLogTrigger().getEnergyUsageTotal()); + + Mockito.when(transactionRetStore.getTransactionInfoByBlockNum(ByteArray.fromLong(0))) + .thenReturn(null); + list = blockEventGet.getTransactionTriggers(blockCapsule, 1); + Assert.assertEquals(1, list.size()); + Assert.assertEquals(1, + list.get(0).getTransactionLogTrigger().getLatestSolidifiedBlockNumber()); + Assert.assertEquals(0, + list.get(0).getTransactionLogTrigger().getBlockNumber()); + Assert.assertEquals(0, + list.get(0).getTransactionLogTrigger().getEnergyUsageTotal()); } + } \ No newline at end of file From bfb11973d89ab3dce8c72b5885ebe780891e0369 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Fri, 7 Mar 2025 16:40:00 +0800 Subject: [PATCH 1162/1197] optimize event service close logic --- .../org/tron/core/services/event/BlockEventLoad.java | 11 ++++++++--- .../org/tron/core/services/event/EventService.java | 8 ++++++-- .../core/services/event/RealtimeEventService.java | 3 ++- .../tron/core/services/event/SolidEventService.java | 3 ++- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java b/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java index bebe3bcbc60..382973ccfa5 100644 --- a/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java +++ b/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java @@ -42,11 +42,16 @@ public void init() { } public void close() { - executor.shutdown(); - logger.info("Event load service close."); + try { + load(); + executor.shutdown(); + logger.info("Event load service close."); + } catch (Exception e) { + logger.warn("Stop event load service fail. {}", e.getMessage()); + } } - public void load() throws Exception { + public synchronized void load() throws Exception { long cacheHeadNum = BlockEventCache.getHead().getBlockId().getNum(); long tmpNum = manager.getDynamicPropertiesStore().getLatestBlockHeaderNumber(); if (cacheHeadNum >= tmpNum) { diff --git a/framework/src/main/java/org/tron/core/services/event/EventService.java b/framework/src/main/java/org/tron/core/services/event/EventService.java index b2e01ab3a9d..0dc61a7809c 100644 --- a/framework/src/main/java/org/tron/core/services/event/EventService.java +++ b/framework/src/main/java/org/tron/core/services/event/EventService.java @@ -18,6 +18,9 @@ public class EventService { @Autowired private HistoryEventService historyEventService; + @Autowired + private SolidEventService solidEventService; + @Autowired private Manager manager; @@ -54,8 +57,9 @@ public void init() { } public void close() { - realtimeEventService.close(); - blockEventLoad.close(); historyEventService.close(); + blockEventLoad.close(); + realtimeEventService.close(); + solidEventService.close(); } } diff --git a/framework/src/main/java/org/tron/core/services/event/RealtimeEventService.java b/framework/src/main/java/org/tron/core/services/event/RealtimeEventService.java index 0f46115bc5a..02dc3aab364 100644 --- a/framework/src/main/java/org/tron/core/services/event/RealtimeEventService.java +++ b/framework/src/main/java/org/tron/core/services/event/RealtimeEventService.java @@ -45,6 +45,7 @@ public void init() { } public void close() { + work(); executor.shutdown(); logger.info("Realtime event service close."); } @@ -57,7 +58,7 @@ public void add(Event event) { queue.offer(event); } - public void work() { + public synchronized void work() { while (queue.size() > 0) { Event event = queue.poll(); flush(event.getBlockEvent(), event.isRemove()); diff --git a/framework/src/main/java/org/tron/core/services/event/SolidEventService.java b/framework/src/main/java/org/tron/core/services/event/SolidEventService.java index e67a1618ce1..a27c5bf7ab8 100644 --- a/framework/src/main/java/org/tron/core/services/event/SolidEventService.java +++ b/framework/src/main/java/org/tron/core/services/event/SolidEventService.java @@ -37,11 +37,12 @@ public void init() { } public void close() { + work(); executor.shutdown(); logger.info("Solid event service close."); } - public void work() { + public synchronized void work() { BlockCapsule.BlockId solidId = BlockEventCache.getSolidId(); if (solidId.getNum() <= BlockEventCache.getSolidNum()) { return; From c8195ca55838c24012eea6841c4d32be9a342e13 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Fri, 7 Mar 2025 17:44:26 +0800 Subject: [PATCH 1163/1197] fix EventServiceTest unit test --- .../java/org/tron/common/application/ApplicationImpl.java | 2 +- .../test/java/org/tron/core/event/EventServiceTest.java | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java index ffb70722822..2c41bedffb7 100644 --- a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java +++ b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java @@ -52,11 +52,11 @@ public void startup() { @Override public void shutdown() { this.shutdownServices(); - eventService.close(); if (!Args.getInstance().isSolidityNode() && (!Args.getInstance().p2pDisable)) { tronNetService.close(); } consensusService.stop(); + eventService.close(); dbManager.close(); shutdown.countDown(); } diff --git a/framework/src/test/java/org/tron/core/event/EventServiceTest.java b/framework/src/test/java/org/tron/core/event/EventServiceTest.java index b20e33404fd..373bfe7d3ec 100644 --- a/framework/src/test/java/org/tron/core/event/EventServiceTest.java +++ b/framework/src/test/java/org/tron/core/event/EventServiceTest.java @@ -5,22 +5,30 @@ import org.junit.Test; import org.mockito.Mockito; import org.tron.common.utils.ReflectUtils; +import org.tron.core.capsule.BlockCapsule; import org.tron.core.db.Manager; +import org.tron.core.services.event.BlockEventCache; import org.tron.core.services.event.BlockEventLoad; import org.tron.core.services.event.EventService; import org.tron.core.services.event.HistoryEventService; import org.tron.core.services.event.RealtimeEventService; +import org.tron.core.services.event.SolidEventService; public class EventServiceTest { @Test public void test() { + BlockCapsule.BlockId b1 = new BlockCapsule.BlockId(BlockEventCacheTest.getBlockId(), 1); + BlockEventCache.init(b1); + EventService eventService = new EventService(); HistoryEventService historyEventService = new HistoryEventService(); RealtimeEventService realtimeEventService = new RealtimeEventService(); + SolidEventService solidEventService = new SolidEventService(); BlockEventLoad blockEventLoad = new BlockEventLoad(); ReflectUtils.setFieldValue(eventService, "historyEventService", historyEventService); + ReflectUtils.setFieldValue(eventService, "solidEventService", solidEventService); ReflectUtils.setFieldValue(eventService, "realtimeEventService", realtimeEventService); ReflectUtils.setFieldValue(eventService, "blockEventLoad", blockEventLoad); From d56502f87bdc07e6508b0fa90b666ac15681d5db Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Fri, 7 Mar 2025 18:51:41 +0800 Subject: [PATCH 1164/1197] fix unit test when process exit --- .../tron/core/services/event/RealtimeEventService.java | 10 +++++++--- .../tron/core/services/event/SolidEventService.java | 10 +++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/event/RealtimeEventService.java b/framework/src/main/java/org/tron/core/services/event/RealtimeEventService.java index 02dc3aab364..093594f1c95 100644 --- a/framework/src/main/java/org/tron/core/services/event/RealtimeEventService.java +++ b/framework/src/main/java/org/tron/core/services/event/RealtimeEventService.java @@ -45,9 +45,13 @@ public void init() { } public void close() { - work(); - executor.shutdown(); - logger.info("Realtime event service close."); + try { + work(); + executor.shutdown(); + logger.info("Realtime event service close."); + } catch (Exception e) { + logger.warn("Close realtime event service fail. {}", e.getMessage()); + } } public void add(Event event) { diff --git a/framework/src/main/java/org/tron/core/services/event/SolidEventService.java b/framework/src/main/java/org/tron/core/services/event/SolidEventService.java index a27c5bf7ab8..6102a87f892 100644 --- a/framework/src/main/java/org/tron/core/services/event/SolidEventService.java +++ b/framework/src/main/java/org/tron/core/services/event/SolidEventService.java @@ -37,9 +37,13 @@ public void init() { } public void close() { - work(); - executor.shutdown(); - logger.info("Solid event service close."); + try { + work(); + executor.shutdown(); + logger.info("Solid event service close."); + } catch (Exception e) { + logger.warn("Close solid event service fail. {}", e.getMessage()); + } } public synchronized void work() { From a30a3b72c7a46ea92d7c5f5a53959e1096afd1ae Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 10 Mar 2025 17:07:15 +0800 Subject: [PATCH 1165/1197] feat(tvm): add blob opcodes add kzg point evaluation precompile contract --- .../src/main/java/org/tron/core/vm/Op.java | 4 + .../org/tron/core/vm/OperationActions.java | 10 + .../org/tron/core/vm/OperationRegistry.java | 12 + .../tron/core/vm/PrecompiledContracts.java | 54 ++++ .../java/ethereum/ckzg4844/CKZG4844JNI.java | 257 ++++++++++++++++++ .../java/ethereum/ckzg4844/CKZGException.java | 45 +++ .../ethereum/ckzg4844/CellsAndProofs.java | 23 ++ .../java/ethereum/ckzg4844/ProofAndY.java | 23 ++ .../lib/aarch64/libckzg4844jni.dylib | Bin 0 -> 259496 bytes .../resources/lib/aarch64/libckzg4844jni.so | Bin 0 -> 251848 bytes .../main/resources/lib/amd64/ckzg4844jni.dll | Bin 0 -> 288032 bytes .../resources/lib/amd64/libckzg4844jni.so | Bin 0 -> 293960 bytes .../resources/lib/x86_64/libckzg4844jni.dylib | Bin 0 -> 275232 bytes .../zen/KZGPointEvaluationInitService.java | 53 ++++ .../common/runtime/vm/OperationsTest.java | 38 +++ .../runtime/vm/PrecompiledContractsTest.java | 54 ++++ .../core/zksnark/KZGPointEvaluationTest.java | 21 ++ 17 files changed, 594 insertions(+) create mode 100644 crypto/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java create mode 100644 crypto/src/main/java/ethereum/ckzg4844/CKZGException.java create mode 100644 crypto/src/main/java/ethereum/ckzg4844/CellsAndProofs.java create mode 100644 crypto/src/main/java/ethereum/ckzg4844/ProofAndY.java create mode 100755 crypto/src/main/resources/lib/aarch64/libckzg4844jni.dylib create mode 100755 crypto/src/main/resources/lib/aarch64/libckzg4844jni.so create mode 100755 crypto/src/main/resources/lib/amd64/ckzg4844jni.dll create mode 100755 crypto/src/main/resources/lib/amd64/libckzg4844jni.so create mode 100755 crypto/src/main/resources/lib/x86_64/libckzg4844jni.dylib create mode 100644 framework/src/main/java/org/tron/core/zen/KZGPointEvaluationInitService.java create mode 100644 framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java diff --git a/actuator/src/main/java/org/tron/core/vm/Op.java b/actuator/src/main/java/org/tron/core/vm/Op.java index 5125f067d31..f1bc3003d36 100644 --- a/actuator/src/main/java/org/tron/core/vm/Op.java +++ b/actuator/src/main/java/org/tron/core/vm/Op.java @@ -120,6 +120,10 @@ public class Op { public static final int SELFBALANCE = 0x47; // (0x48) Get block's basefee public static final int BASEFEE = 0x48; + // (0x49) Get blob hash + public static final int BLOBAHASH = 0x49; + // (0x4a) Get block's blob basefee + public static final int BLOBBASEFEE = 0x4a; /* Memory, Storage and Flow Operations */ // (0x50) Remove item from stack diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index fa1aedbb5f8..4ace088a6c9 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -677,6 +677,16 @@ public static void mCopyAction(Program program) { program.step(); } + public static void blobHashAction(Program program) { + program.stackPush(DataWord.ZERO()); + program.step(); + } + + public static void blobBaseFeeAction(Program program) { + program.stackPush(DataWord.ZERO()); + program.step(); + } + public static void push0Action(Program program) { program.stackPush(DataWord.ZERO()); program.step(); diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index da1c9b38e9e..bc73cfd9aa7 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -681,5 +681,17 @@ public static void appendCancunOperations(JumpTable table) { EnergyCost::getMCopyCost, OperationActions::mCopyAction, proposal)); + + table.set(new Operation( + Op.BLOBAHASH, 1, 1, + EnergyCost::getVeryLowTierCost, + OperationActions::blobHashAction, + proposal)); + + table.set(new Operation( + Op.BLOBBASEFEE, 0, 1, + EnergyCost::getBaseTierCost, + OperationActions::blobBaseFeeAction, + proposal)); } } diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index b53a196e0b6..a8dbfe1dbf7 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -32,6 +32,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import ethereum.ckzg4844.CKZG4844JNI; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; @@ -39,6 +40,7 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Triple; +import org.bouncycastle.util.encoders.Hex; import org.tron.common.crypto.Blake2bfMessageDigest; import org.tron.common.crypto.Hash; import org.tron.common.crypto.SignUtils; @@ -104,6 +106,7 @@ public class PrecompiledContracts { private static final EthRipemd160 ethRipemd160 = new EthRipemd160(); private static final Blake2F blake2F = new Blake2F(); + private static final KZGPointEvaluation kzgPointEvaluation = new KZGPointEvaluation(); // FreezeV2 PrecompileContracts private static final GetChainParameter getChainParameter = new GetChainParameter(); @@ -198,6 +201,9 @@ public class PrecompiledContracts { private static final DataWord blake2FAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000000020009"); + private static final DataWord kzgPointEvaluationAddr = new DataWord( + "000000000000000000000000000000000000000000000000000000000002000a"); + public static PrecompiledContract getOptimizedContractForConstant(PrecompiledContract contract) { try { Constructor constructor = contract.getClass().getDeclaredConstructor(); @@ -279,6 +285,9 @@ public static PrecompiledContract getContractForAddress(DataWord address) { if (VMConfig.allowTvmCompatibleEvm() && address.equals(blake2FAddr)) { return blake2F; } + if (VMConfig.allowTvmCancun() && address.equals(kzgPointEvaluationAddr)) { + return kzgPointEvaluation; + } if (VMConfig.allowTvmFreezeV2()) { if (address.equals(getChainParameterAddr)) { @@ -2191,4 +2200,49 @@ public Pair execute(byte[] data) { } } + public static class KZGPointEvaluation extends PrecompiledContract { + + private static final int BLOB_VERIFY_INPUT_LENGTH = 192; + private static final byte BLOB_COMMITMENT_VERSION_KZG = 0x01; + private static final byte[] BLOB_PRECOMPILED_RETURN_VALUE = Hex.decode( + "0000000000000000000000000000000000000000000000000000000000001000" + + "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); + + @Override + public long getEnergyForData(byte[] data) { + return 50000; + } + + @Override + public Pair execute(byte[] data) { + if (data == null || data.length != BLOB_VERIFY_INPUT_LENGTH) { + return Pair.of(false, DataWord.ZERO().getData()); + } + + byte[] versionedHash = parseBytes(data, 0, 32); + byte[] z = parseBytes(data, 32, 32); + byte[] y = parseBytes(data, 64, 32); + byte[] commitment = parseBytes(data, 96, 48); + byte[] proof = parseBytes(data, 144, 48); + + byte[] hash = Sha256Hash.hash( + CommonParameter.getInstance().isECKeyCryptoEngine(), commitment); + hash[0] = BLOB_COMMITMENT_VERSION_KZG; + if (!Arrays.equals(versionedHash, hash)) { + return Pair.of(false, DataWord.ZERO().getData()); + } + + try { + if (CKZG4844JNI.verifyKzgProof(commitment, z, y, proof)) { + return Pair.of(true, BLOB_PRECOMPILED_RETURN_VALUE); + } else { + return Pair.of(false, DataWord.ZERO().getData()); + } + } catch (RuntimeException exception) { + logger.warn("KZG point evaluation precompile contract failed", exception); + return Pair.of(false, DataWord.ZERO().getData()); + } + } + } + } diff --git a/crypto/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java b/crypto/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java new file mode 100644 index 00000000000..782e8e3710f --- /dev/null +++ b/crypto/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java @@ -0,0 +1,257 @@ +package ethereum.ckzg4844; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.math.BigInteger; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; + +public class CKZG4844JNI { + + private static final String LIBRARY_NAME = "ckzg4844jni"; + private static final String PLATFORM_NATIVE_LIBRARY_NAME = System.mapLibraryName(LIBRARY_NAME); + + /** Loads the appropriate native library based on your platform. */ + public static void loadNativeLibrary() { + String libraryResourcePath = + "/lib/" + System.getProperty("os.arch") + "/" + PLATFORM_NATIVE_LIBRARY_NAME; + InputStream libraryResource = CKZG4844JNI.class.getResourceAsStream(libraryResourcePath); + if (libraryResource == null) { + try { + System.loadLibrary(LIBRARY_NAME); + } catch (UnsatisfiedLinkError __) { + String exceptionMessage = + String.format( + "Couldn't load native library (%s). It wasn't available at %s or the library path.", + LIBRARY_NAME, libraryResourcePath); + throw new RuntimeException(exceptionMessage); + } + } else { + try { + Path tempDir = Files.createTempDirectory(LIBRARY_NAME + "@"); + tempDir.toFile().deleteOnExit(); + Path tempDll = tempDir.resolve(PLATFORM_NATIVE_LIBRARY_NAME); + tempDll.toFile().deleteOnExit(); + Files.copy(libraryResource, tempDll, StandardCopyOption.REPLACE_EXISTING); + libraryResource.close(); + System.load(tempDll.toString()); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } + } + + /** Scalar field modulus of BLS12-381. */ + public static final BigInteger BLS_MODULUS = + new BigInteger( + "52435875175126190479447740508185965837690552500527637822603658699938581184513"); + + /** The number of bytes in a g1 point. */ + protected static final int BYTES_PER_G1 = 48; + + /** The number of bytes in a g2 point. */ + protected static final int BYTES_PER_G2 = 96; + + /** The number of bytes in a BLS scalar field element. */ + public static final int BYTES_PER_FIELD_ELEMENT = 32; + + /** The number of bits in a BLS scalar field element. */ + protected static final int BITS_PER_FIELD_ELEMENT = 255; + + /** The number of field elements in a blob. */ + public static final int FIELD_ELEMENTS_PER_BLOB = 4096; + + /** The number of field elements in an extended blob. */ + protected static final int FIELD_ELEMENTS_PER_EXT_BLOB = FIELD_ELEMENTS_PER_BLOB * 2; + + /** The number of field elements in a cell. */ + public static final int FIELD_ELEMENTS_PER_CELL = 64; + + /** The number of bytes in a KZG commitment. */ + public static final int BYTES_PER_COMMITMENT = 48; + + /** The number of bytes in a KZG proof. */ + public static final int BYTES_PER_PROOF = 48; + + /** The number of bytes in a blob. */ + public static final int BYTES_PER_BLOB = FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT; + + /** The number of bytes in a single cell. */ + public static final int BYTES_PER_CELL = BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_CELL; + + /** The number of cells in an extended blob. */ + public static final int CELLS_PER_EXT_BLOB = + FIELD_ELEMENTS_PER_EXT_BLOB / FIELD_ELEMENTS_PER_CELL; + + private CKZG4844JNI() {} + + /** + * Loads the trusted setup from a file. Once loaded, the same setup will be used for all the + * crypto native calls. To load a new setup, free the current one by calling {@link + * #freeTrustedSetup()} and then load the new one. If no trusted setup has been loaded, all the + * crypto native calls will throw a {@link RuntimeException}. + * + * @param file a path to a trusted setup file + * @param precompute configurable value between 0-15 + * @throws CKZGException if there is a crypto error + */ + public static native void loadTrustedSetup(String file, long precompute); + + /** + * An alternative to {@link #loadTrustedSetup(String,long)}. Loads the trusted setup from method + * parameters instead of a file. + * + * @param g1MonomialBytes g1 values in monomial form as bytes + * @param g1LagrangeBytes g1 values in Lagrange form as bytes + * @param g2MonomialBytes g2 values in monomial form as bytes + * @param precompute configurable value between 0-15 + * @throws CKZGException if there is a crypto error + */ + public static native void loadTrustedSetup( + byte[] g1MonomialBytes, byte[] g1LagrangeBytes, byte[] g2MonomialBytes, long precompute); + + /** + * An alternative to {@link #loadTrustedSetup(String,long)}. Loads the trusted setup from a + * resource. + * + * @param clazz the class to use to get the resource + * @param resource the resource name that contains the trusted setup + * @param precompute configurable value between 0-15 + * @param the type of the class + * @throws CKZGException if there is a crypto error + * @throws IllegalArgumentException if the resource does not exist + */ + public static void loadTrustedSetupFromResource( + String resource, Class clazz, long precompute) { + InputStream is = clazz.getResourceAsStream(resource); + if (is == null) { + throw new IllegalArgumentException("Resource " + resource + " does not exist."); + } + + try (InputStream closableIs = is) { + Path jniWillLoadFrom = Files.createTempFile("kzg-trusted-setup", ".txt"); + jniWillLoadFrom.toFile().deleteOnExit(); + Files.copy(closableIs, jniWillLoadFrom, StandardCopyOption.REPLACE_EXISTING); + loadTrustedSetup(jniWillLoadFrom.toString(), precompute); + } catch (IOException ex) { + throw new UncheckedIOException("Error loading trusted setup from resource " + resource, ex); + } + } + + /** + * Free the current trusted setup. This method will throw an exception if no trusted setup has + * been loaded. + */ + public static native void freeTrustedSetup(); + + /** + * Calculates commitment for a given blob + * + * @param blob blob bytes + * @return the commitment + * @throws CKZGException if there is a crypto error + */ + public static native byte[] blobToKzgCommitment(byte[] blob); + + /** + * Compute proof at point z for the polynomial represented by blob. + * + * @param blob blob bytes + * @param zBytes a point + * @return an instance of {@link ProofAndY} holding the proof and the value y = f(z) + * @throws CKZGException if there is a crypto error + */ + public static native ProofAndY computeKzgProof(byte[] blob, byte[] zBytes); + + /** + * Given a blob, return the KZG proof that is used to verify it against the commitment + * + * @param blob blob bytes + * @param commitmentBytes commitment bytes + * @return the proof + * @throws CKZGException if there is a crypto error + */ + public static native byte[] computeBlobKzgProof(byte[] blob, byte[] commitmentBytes); + + /** + * Verify the proof by point evaluation for the given commitment + * + * @param commitmentBytes commitment bytes + * @param zBytes Z + * @param yBytes Y + * @param proofBytes the proof that needs verifying + * @return true if the proof is valid and false otherwise + * @throws CKZGException if there is a crypto error + */ + public static native boolean verifyKzgProof( + byte[] commitmentBytes, byte[] zBytes, byte[] yBytes, byte[] proofBytes); + + /** + * Given a blob and a KZG proof, verify that the blob data corresponds to the provided commitment. + * + * @param blob blob bytes + * @param commitmentBytes commitment bytes + * @param proofBytes proof bytes + * @return true if the proof is valid and false otherwise + * @throws CKZGException if there is a crypto error + */ + public static native boolean verifyBlobKzgProof( + byte[] blob, byte[] commitmentBytes, byte[] proofBytes); + + /** + * Given a list of blobs and blob KZG proofs, verify that they correspond to the provided + * commitments. + * + * @param blobs flattened blobs bytes + * @param commitmentsBytes flattened commitments bytes + * @param proofsBytes flattened proofs bytes + * @param count the number of blobs (should be same as the number of proofs and commitments) + * @return true if the proof is valid and false otherwise + * @throws CKZGException if there is a crypto error + */ + public static native boolean verifyBlobKzgProofBatch( + byte[] blobs, byte[] commitmentsBytes, byte[] proofsBytes, long count); + + /** + * Get the cells for a given blob. + * + * @param blob the blob to get cells for + * @return the cells + * @throws CKZGException if there is a crypto error + */ + public static native byte[] computeCells(byte[] blob); + + /** + * Get the cells and proofs for a given blob. + * + * @param blob the blob to get cells/proofs for + * @return a CellsAndProofs object + * @throws CKZGException if there is a crypto error + */ + public static native CellsAndProofs computeCellsAndKzgProofs(byte[] blob); + + /** + * Given at least 50% of cells, reconstruct the missing cells/proofs. + * + * @param cellIndices the identifiers for the cells you have + * @param cells the cells you have + * @return all cells/proofs for that blob + * @throws CKZGException if there is a crypto error + */ + public static native CellsAndProofs recoverCellsAndKzgProofs(long[] cellIndices, byte[] cells); + + /** + * Verify that multiple cells' proofs are valid. + * + * @param commitmentsBytes the commitments for each cell + * @param cellIndices the column index for each cell + * @param cells the cells to verify + * @param proofsBytes the proof for each cell + * @return true if the cells are valid with respect to the given commitments + * @throws CKZGException if there is a crypto error + */ + public static native boolean verifyCellKzgProofBatch( + byte[] commitmentsBytes, long[] cellIndices, byte[] cells, byte[] proofsBytes); +} diff --git a/crypto/src/main/java/ethereum/ckzg4844/CKZGException.java b/crypto/src/main/java/ethereum/ckzg4844/CKZGException.java new file mode 100644 index 00000000000..cbf087364d2 --- /dev/null +++ b/crypto/src/main/java/ethereum/ckzg4844/CKZGException.java @@ -0,0 +1,45 @@ +package ethereum.ckzg4844; + + +import java.util.Arrays; + +/** Thrown when there is an error in the underlying c-kzg library. */ +public class CKZGException extends RuntimeException { + + private final CKZGError error; + private final String errorMessage; + + public CKZGException(int errorCode, String errorMessage) { + super(String.format("%s (%s)", errorMessage, CKZGError.fromErrorCode(errorCode))); + this.error = CKZGError.fromErrorCode(errorCode); + this.errorMessage = errorMessage; + } + + public CKZGError getError() { + return error; + } + + public String getErrorMessage() { + return errorMessage; + } + + public enum CKZGError { + UNKNOWN(0), + C_KZG_BADARGS(1), + C_KZG_ERROR(2), + C_KZG_MALLOC(3); + + public final int errorCode; + + CKZGError(int errorCode) { + this.errorCode = errorCode; + } + + public static CKZGError fromErrorCode(int errorCode) { + return Arrays.stream(CKZGError.values()) + .filter(error -> error.errorCode == errorCode) + .findFirst() + .orElse(UNKNOWN); + } + } +} diff --git a/crypto/src/main/java/ethereum/ckzg4844/CellsAndProofs.java b/crypto/src/main/java/ethereum/ckzg4844/CellsAndProofs.java new file mode 100644 index 00000000000..7f57431acab --- /dev/null +++ b/crypto/src/main/java/ethereum/ckzg4844/CellsAndProofs.java @@ -0,0 +1,23 @@ +package ethereum.ckzg4844; + +public class CellsAndProofs { + private final byte[] cells; + private final byte[] proofs; + + public CellsAndProofs(final byte[] cells, final byte[] proofs) { + this.cells = cells; + this.proofs = proofs; + } + + public byte[] getCells() { + return cells; + } + + public byte[] getProofs() { + return proofs; + } + + public static CellsAndProofs of(final byte[] cells, final byte[] proofs) { + return new CellsAndProofs(cells, proofs); + } +} diff --git a/crypto/src/main/java/ethereum/ckzg4844/ProofAndY.java b/crypto/src/main/java/ethereum/ckzg4844/ProofAndY.java new file mode 100644 index 00000000000..ada1034ee4e --- /dev/null +++ b/crypto/src/main/java/ethereum/ckzg4844/ProofAndY.java @@ -0,0 +1,23 @@ +package ethereum.ckzg4844; + +public class ProofAndY { + private final byte[] proof; + private final byte[] y; + + public ProofAndY(byte[] proof, byte[] y) { + this.proof = proof; + this.y = y; + } + + public byte[] getProof() { + return proof; + } + + public byte[] getY() { + return y; + } + + public static ProofAndY of(byte[] proof, byte[] y) { + return new ProofAndY(proof, y); + } +} diff --git a/crypto/src/main/resources/lib/aarch64/libckzg4844jni.dylib b/crypto/src/main/resources/lib/aarch64/libckzg4844jni.dylib new file mode 100755 index 0000000000000000000000000000000000000000..733aca4f74782cff6d4e47dadc4b99d37ebfd713 GIT binary patch literal 259496 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 pR`B~~GbooT0jA9(Mh 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±2@DOFMH$!0ihhALUl}dIEU;{qtSZRE%7v0I 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

eb3FKa*a? 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 (obfG_sY7Z^vvK%e{PpegF7DyBD5>IZGo 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 literal 0 HcmV?d00001 diff --git a/crypto/src/main/resources/lib/amd64/ckzg4844jni.dll b/crypto/src/main/resources/lib/amd64/ckzg4844jni.dll new file mode 100755 index 0000000000000000000000000000000000000000..7be02e81985a87c7970cbc5805aeea3ff67eb624 GIT binary patch literal 288032 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

)@ks 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 z¬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ñ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 MMKuBFySz1^9(oot~ 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 literal 0 HcmV?d00001 diff --git a/crypto/src/main/resources/lib/x86_64/libckzg4844jni.dylib b/crypto/src/main/resources/lib/x86_64/libckzg4844jni.dylib new file mode 100755 index 0000000000000000000000000000000000000000..7ab7c008aa9a8eda14deb34c7503033a19a798da GIT binary patch literal 275232 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%0D`@m<;GT_!x-7A7xz5DbJ`rAzkN50r(!u*@@ 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 ef*)Zq?)+tg4_6^-biB6VB!$mM res = contract.execute(null); + Assert.assertFalse(res.getLeft()); + Assert.assertArrayEquals(DataWord.ZERO().getData(), res.getRight()); + + byte[] data1 = Arrays.copyOf(data, data.length); + data1[0] = 0x02; + res = contract.execute(data1); + Assert.assertFalse(res.getLeft()); + Assert.assertArrayEquals(DataWord.ZERO().getData(), res.getRight()); + + byte[] data2 = Arrays.copyOf(data, data.length); + byte[] z2 = Hex.decode("0000000000000000000000000000000000000000000000000000000000000066"); + System.arraycopy(z2, 0, data2, 32, 32); + res = contract.execute(data2); + Assert.assertFalse(res.getLeft()); + Assert.assertArrayEquals(DataWord.ZERO().getData(), res.getRight()); + + res = contract.execute(data); + byte[] expected = Hex.decode( + "0000000000000000000000000000000000000000000000000000000000001000" + + "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); + Assert.assertTrue(res.getLeft()); + Assert.assertArrayEquals(expected, res.getRight()); + VMConfig.initAllowTvmCancun(0); + } } diff --git a/framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java b/framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java new file mode 100644 index 00000000000..24e2f9f0f1c --- /dev/null +++ b/framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java @@ -0,0 +1,21 @@ +package org.tron.core.zksnark; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.tron.common.BaseTest; +import org.tron.core.zen.KZGPointEvaluationInitService; + +@Slf4j +public class KZGPointEvaluationTest extends BaseTest { + + @Test + public void testKZGPointEvaluation() { + KZGPointEvaluationInitService.freeSetup(); + + KZGPointEvaluationInitService.initCKZG4844(); + + + + + } +} From 0a2fb53e175e60c684697687745f8ca847ac32c0 Mon Sep 17 00:00:00 2001 From: textml <37575478+textml@users.noreply.github.com> Date: Mon, 10 Mar 2025 17:55:13 +0800 Subject: [PATCH 1166/1197] feat(tvm): add allowTvmBlob proposal for TVM blob related ops and precompiles --- .../java/org/tron/core/utils/ProposalUtil.java | 18 +++++++++++++++++- .../src/main/java/org/tron/core/vm/Op.java | 2 +- .../org/tron/core/vm/OperationActions.java | 1 + .../org/tron/core/vm/OperationRegistry.java | 7 ++++--- .../org/tron/core/vm/PrecompiledContracts.java | 2 +- .../org/tron/core/vm/config/ConfigLoader.java | 1 + .../core/store/DynamicPropertiesStore.java | 13 +++++++++++++ .../tron/common/parameter/CommonParameter.java | 4 ++++ .../src/main/java/org/tron/core/Constant.java | 2 ++ .../java/org/tron/core/vm/config/VMConfig.java | 10 ++++++++++ .../src/main/java/org/tron/core/Wallet.java | 5 +++++ .../java/org/tron/core/config/args/Args.java | 5 +++++ .../tron/core/consensus/ProposalService.java | 4 ++++ .../tron/common/runtime/vm/OperationsTest.java | 8 ++++---- .../runtime/vm/PrecompiledContractsTest.java | 4 ++-- 15 files changed, 74 insertions(+), 12 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 6b558011c73..0bad940da7e 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -824,6 +824,21 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case ALLOW_TVM_BLOB: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_8_0)) { + throw new ContractValidateException( + "Bad chain parameter id [ALLOW_TVM_BLOB]"); + } + if (dynamicPropertiesStore.getAllowTvmBlob() == 1) { + throw new ContractValidateException( + "[ALLOW_TVM_BLOB] has been valid, no need to propose again"); + } + if (value != 1) { + throw new ContractValidateException( + "This value[ALLOW_TVM_BLOB] is only allowed to be 1"); + } + break; + } default: break; } @@ -905,7 +920,8 @@ public enum ProposalType { // current value, value range MAX_CREATE_ACCOUNT_TX_SIZE(82), // [500, 10000] ALLOW_TVM_CANCUN(83), // 0, 1 ALLOW_STRICT_MATH(87), // 0, 1 - CONSENSUS_LOGIC_OPTIMIZATION(88); // 0, 1 + CONSENSUS_LOGIC_OPTIMIZATION(88), // 0, 1 + ALLOW_TVM_BLOB(89); // 0, 1 private long code; diff --git a/actuator/src/main/java/org/tron/core/vm/Op.java b/actuator/src/main/java/org/tron/core/vm/Op.java index f1bc3003d36..ed2d8eb2f53 100644 --- a/actuator/src/main/java/org/tron/core/vm/Op.java +++ b/actuator/src/main/java/org/tron/core/vm/Op.java @@ -121,7 +121,7 @@ public class Op { // (0x48) Get block's basefee public static final int BASEFEE = 0x48; // (0x49) Get blob hash - public static final int BLOBAHASH = 0x49; + public static final int BLOBHASH = 0x49; // (0x4a) Get block's blob basefee public static final int BLOBBASEFEE = 0x4a; diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java index 4ace088a6c9..f10fb37dd7e 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java @@ -678,6 +678,7 @@ public static void mCopyAction(Program program) { } public static void blobHashAction(Program program) { + program.stackPop(); program.stackPush(DataWord.ZERO()); program.step(); } diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index bc73cfd9aa7..be29238a775 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -663,6 +663,7 @@ public static void adjustForFairEnergy(JumpTable table) { public static void appendCancunOperations(JumpTable table) { BooleanSupplier proposal = VMConfig::allowTvmCancun; + BooleanSupplier tvmBlobProposal = VMConfig::allowTvmBlob; table.set(new Operation( Op.TLOAD, 1, 1, @@ -683,15 +684,15 @@ public static void appendCancunOperations(JumpTable table) { proposal)); table.set(new Operation( - Op.BLOBAHASH, 1, 1, + Op.BLOBHASH, 1, 1, EnergyCost::getVeryLowTierCost, OperationActions::blobHashAction, - proposal)); + tvmBlobProposal)); table.set(new Operation( Op.BLOBBASEFEE, 0, 1, EnergyCost::getBaseTierCost, OperationActions::blobBaseFeeAction, - proposal)); + tvmBlobProposal)); } } diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index a8dbfe1dbf7..1245bc23718 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -285,7 +285,7 @@ public static PrecompiledContract getContractForAddress(DataWord address) { if (VMConfig.allowTvmCompatibleEvm() && address.equals(blake2FAddr)) { return blake2F; } - if (VMConfig.allowTvmCancun() && address.equals(kzgPointEvaluationAddr)) { + if (VMConfig.allowTvmBlob() && address.equals(kzgPointEvaluationAddr)) { return kzgPointEvaluation; } diff --git a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java index 81ed4ba2b8f..1ec8a75d669 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java +++ b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java @@ -43,6 +43,7 @@ public static void load(StoreFactory storeFactory) { VMConfig.initAllowStrictMath(ds.getAllowStrictMath()); VMConfig.initAllowTvmCancun(ds.getAllowTvmCancun()); VMConfig.initDisableJavaLangMath(ds.getConsensusLogicOptimization()); + VMConfig.initAllowTvmBlob(ds.getAllowTvmBlob()); } } } diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 865555b35a8..91b0cff68a0 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -230,6 +230,8 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_TVM_CANCUN = "ALLOW_TVM_CANCUN".getBytes(); + private static final byte[] ALLOW_TVM_BLOB = "ALLOW_TVM_BLOB".getBytes(); + @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { super(dbName); @@ -2933,6 +2935,17 @@ public long getAllowTvmCancun() { .orElse(CommonParameter.getInstance().getAllowTvmCancun()); } + public void saveAllowTvmBlob(long allowTvmBlob) { + this.put(ALLOW_TVM_BLOB, new BytesCapsule(ByteArray.fromLong(allowTvmBlob))); + } + + public long getAllowTvmBlob() { + return Optional.ofNullable(getUnchecked(ALLOW_TVM_BLOB)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElse(CommonParameter.getInstance().getAllowTvmBlob()); + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 506b9c20ea3..16fb752d82a 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -713,6 +713,10 @@ public class CommonParameter { @Setter public long allowTvmCancun; + @Getter + @Setter + public long allowTvmBlob; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 1b974052a01..bb35b207795 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -401,4 +401,6 @@ public class Constant { = "committee.consensusLogicOptimization"; public static final String COMMITTEE_ALLOW_TVM_CANCUN = "committee.allowTvmCancun"; + + public static final String COMMITTEE_ALLOW_TVM_BLOB = "committee.allowTvmBlob"; } diff --git a/common/src/main/java/org/tron/core/vm/config/VMConfig.java b/common/src/main/java/org/tron/core/vm/config/VMConfig.java index 23210f284c0..2bdbeb78b92 100644 --- a/common/src/main/java/org/tron/core/vm/config/VMConfig.java +++ b/common/src/main/java/org/tron/core/vm/config/VMConfig.java @@ -57,6 +57,8 @@ public class VMConfig { private static Boolean DISABLE_JAVA_LANG_MATH = false; + private static boolean ALLOW_TVM_BLOB = false; + private VMConfig() { } @@ -160,6 +162,10 @@ public static void initDisableJavaLangMath(long allow) { DISABLE_JAVA_LANG_MATH = allow == 1; } + public static void initAllowTvmBlob(long allow) { + ALLOW_TVM_BLOB = allow == 1; + } + public static boolean getEnergyLimitHardFork() { return CommonParameter.ENERGY_LIMIT_HARD_FORK; } @@ -251,4 +257,8 @@ public static boolean allowTvmCancun() { public static boolean disableJavaLangMath() { return DISABLE_JAVA_LANG_MATH; } + + public static boolean allowTvmBlob() { + return ALLOW_TVM_BLOB; + } } diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 27c942bf6b4..24978304fba 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1382,6 +1382,11 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getAllowTvmCancun()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getAllowTvmBlob") + .setValue(dbManager.getDynamicPropertiesStore().getAllowTvmBlob()) + .build()); + return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index aebff31e95d..4eab79b16fa 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -244,6 +244,7 @@ public static void clearParam() { PARAMETER.allowStrictMath = 0; PARAMETER.consensusLogicOptimization = 0; PARAMETER.allowTvmCancun = 0; + PARAMETER.allowTvmBlob = 0; } /** @@ -1274,6 +1275,10 @@ public static void setParam(final Config config) { config.hasPath(Constant.COMMITTEE_ALLOW_TVM_CANCUN) ? config .getInt(Constant.COMMITTEE_ALLOW_TVM_CANCUN) : 0; + PARAMETER.allowTvmBlob = + config.hasPath(Constant.COMMITTEE_ALLOW_TVM_BLOB) ? config + .getInt(Constant.COMMITTEE_ALLOW_TVM_BLOB) : 0; + logConfig(); } diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 1a95fd5064d..b25f0d6fa8d 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -380,6 +380,10 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveAllowTvmCancun(entry.getValue()); break; } + case ALLOW_TVM_BLOB: { + manager.getDynamicPropertiesStore().saveAllowTvmBlob(entry.getValue()); + break; + } default: find = false; break; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java index 8b4c80c49c2..3315005b7d2 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java @@ -1011,7 +1011,7 @@ public void testMCOPY() throws ContractValidateException { @Test public void testBlobHash() throws ContractValidateException { - VMConfig.initAllowTvmCancun(1); + VMConfig.initAllowTvmBlob(1); invoke = new ProgramInvokeMockImpl(); Protocol.Transaction trx = Protocol.Transaction.getDefaultInstance(); @@ -1025,12 +1025,12 @@ public void testBlobHash() throws ContractValidateException { Assert.assertEquals(6, program.getResult().getEnergyUsed()); Assert.assertEquals(DataWord.ZERO(), program.getStack().pop()); - VMConfig.initAllowTvmCancun(0); + VMConfig.initAllowTvmBlob(0); } @Test public void testBlobBaseFee() throws ContractValidateException { - VMConfig.initAllowTvmCancun(1); + VMConfig.initAllowTvmBlob(1); invoke = new ProgramInvokeMockImpl(); Protocol.Transaction trx = Protocol.Transaction.getDefaultInstance(); @@ -1044,7 +1044,7 @@ public void testBlobBaseFee() throws ContractValidateException { Assert.assertEquals(5, program.getResult().getEnergyUsed()); Assert.assertEquals(DataWord.ZERO(), program.getStack().pop()); - VMConfig.initAllowTvmCancun(0); + VMConfig.initAllowTvmBlob(0); } private void testOperations(Program program) { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index 90d66dc00bc..0f1b8754fd5 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -1172,7 +1172,7 @@ private static byte[] encodeMultiWord(byte[]... words) { @Test public void ckzgPointEvaluationTest() { - VMConfig.initAllowTvmCancun(1); + VMConfig.initAllowTvmBlob(1); PrecompiledContract contract = createPrecompiledContract(kzgPointEvaluationAddr, OWNER_ADDRESS); @@ -1217,6 +1217,6 @@ public void ckzgPointEvaluationTest() { "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); Assert.assertTrue(res.getLeft()); Assert.assertArrayEquals(expected, res.getRight()); - VMConfig.initAllowTvmCancun(0); + VMConfig.initAllowTvmBlob(0); } } From d442c9318237a7bf9b8be1622d96b989e39ae0f1 Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 10 Mar 2025 18:19:21 +0800 Subject: [PATCH 1167/1197] feat(crypto): add setup file --- .../kzg-trusted-setups/trusted_setup.txt | 8259 +++++++++++++++++ 1 file changed, 8259 insertions(+) create mode 100644 framework/src/main/resources/kzg-trusted-setups/trusted_setup.txt diff --git a/framework/src/main/resources/kzg-trusted-setups/trusted_setup.txt b/framework/src/main/resources/kzg-trusted-setups/trusted_setup.txt new file mode 100644 index 00000000000..5ecccf5e5e5 --- /dev/null +++ b/framework/src/main/resources/kzg-trusted-setups/trusted_setup.txt @@ -0,0 +1,8259 @@ +4096 +65 +a0413c0dcafec6dbc9f47d66785cf1e8c981044f7d13cfe3e4fcbb71b5408dfde6312493cb3c1d30516cb3ca88c03654 +8b997fb25730d661918371bb41f2a6e899cac23f04fc5365800b75433c0a953250e15e7a98fb5ca5cc56a8cd34c20c57 +83302852db89424d5699f3f157e79e91dc1380f8d5895c5a772bb4ea3a5928e7c26c07db6775203ce33e62a114adaa99 +a759c48b7e4a685e735c01e5aa6ef9c248705001f470f9ad856cd87806983e917a8742a3bd5ee27db8d76080269b7c83 +967f8dc45ebc3be14c8705f43249a30ff48e96205fb02ae28daeab47b72eb3f45df0625928582aa1eb4368381c33e127 +a418eb1e9fb84cb32b370610f56f3cb470706a40ac5a47c411c464299c45c91f25b63ae3fcd623172aa0f273c0526c13 +8f44e3f0387293bc7931e978165abbaed08f53acd72a0a23ac85f6da0091196b886233bcee5b4a194db02f3d5a9b3f78 +97173434b336be73c89412a6d70d416e170ea355bf1956c32d464090b107c090ef2d4e1a467a5632fbc332eeb679bf2d +a24052ad8d55ad04bc5d951f78e14213435681594110fd18173482609d5019105b8045182d53ffce4fc29fc8810516c1 +b950768136b260277590b5bec3f56bbc2f7a8bc383d44ce8600e85bf8cf19f479898bcc999d96dfbd2001ede01d94949 +92ab8077871037bd3b57b95cbb9fb10eb11efde9191690dcac655356986fd02841d8fdb25396faa0feadfe3f50baf56d +a79b096dff98038ac30f91112dd14b78f8ad428268af36d20c292e2b3b6d9ed4fb28480bb04e465071cc67d05786b6d1 +b9ff71461328f370ce68bf591aa7fb13027044f42a575517f3319e2be4aa4843fa281e756d0aa5645428d6dfa857cef2 +8d765808c00b3543ff182e2d159c38ae174b12d1314da88ea08e13bd9d1c37184cb515e6bf6420531b5d41767987d7ce +b8c9a837d20c3b53e6f578e4a257bb7ef8fc43178614ec2a154915b267ad2be135981d01ed2ee1b5fbd9d9bb27f0800a +a9773d92cf23f65f98ef68f6cf95c72b53d0683af2f9bf886bb9036e4a38184b1131b26fd24397910b494fbef856f3aa +b41ebe38962d112da4a01bf101cb248d808fbd50aaf749fc7c151cf332032eb3e3bdbd716db899724b734d392f26c412 +90fbb030167fb47dcc13d604a726c0339418567c1d287d1d87423fa0cb92eec3455fbb46bcbe2e697144a2d3972142e4 +b11d298bd167464b35fb923520d14832bd9ed50ed841bf6d7618424fd6f3699190af21759e351b89142d355952149da1 +8bc36066f69dc89f7c4d1e58d67497675050c6aa002244cebd9fc957ec5e364c46bab4735ea3db02b73b3ca43c96e019 +ab7ab92c5d4d773068e485aa5831941ebd63db7118674ca38089635f3b4186833af2455a6fb9ed2b745df53b3ce96727 +af191ca3089892cb943cd97cf11a51f38e38bd9be50844a4e8da99f27e305e876f9ed4ab0628e8ae3939066b7d34a15f +a3204c1747feabc2c11339a542195e7cb6628fd3964f846e71e2e3f2d6bb379a5e51700682ea1844eba12756adb13216 +903a29883846b7c50c15968b20e30c471aeac07b872c40a4d19eb1a42da18b649d5bbfde4b4cf6225d215a461b0deb6d +8e6e9c15ffbf1e16e5865a5fef7ed751dc81957a9757b535cb38b649e1098cda25d42381dc4f776778573cdf90c3e6e0 +a8f6dd26100b512a8c96c52e00715c4b2cb9ac457f17aed8ffe1cf1ea524068fe5a1ddf218149845fc1417b789ecfc98 +a5b0ffc819451ea639cfd1c18cbc9365cc79368d3b2e736c0ae54eba2f0801e6eb0ee14a5f373f4a70ca463bdb696c09 +879f91ccd56a1b9736fbfd20d8747354da743fb121f0e308a0d298ff0d9344431890e41da66b5009af3f442c636b4f43 +81bf3a2d9755e206b515a508ac4d1109bf933c282a46a4ae4a1b4cb4a94e1d23642fad6bd452428845afa155742ade7e +8de778d4742f945df40004964e165592f9c6b1946263adcdd5a88b00244bda46c7bb49098c8eb6b3d97a0dd46148a8ca +b7a57b21d13121907ee28c5c1f80ee2e3e83a3135a8101e933cf57171209a96173ff5037f5af606e9fd6d066de6ed693 +b0877d1963fd9200414a38753dffd9f23a10eb3198912790d7eddbc9f6b477019d52ddd4ebdcb9f60818db076938a5a9 +88da2d7a6611bc16adc55fc1c377480c828aba4496c645e3efe0e1a67f333c05a0307f7f1d2df8ac013602c655c6e209 +95719eb02e8a9dede1a888c656a778b1c69b7716fbe3d1538fe8afd4a1bc972183c7d32aa7d6073376f7701df80116d8 +8e8a1ca971f2444b35af3376e85dccda3abb8e8e11d095d0a4c37628dfe5d3e043a377c3de68289ef142e4308e9941a0 +b720caaff02f6d798ac84c4f527203e823ff685869e3943c979e388e1c34c3f77f5c242c6daa7e3b30e511aab917b866 +86040d55809afeec10e315d1ad950d269d37cfee8c144cd8dd4126459e3b15a53b3e68df5981df3c2346d23c7b4baaf4 +82d8cabf13ab853db0377504f0aec00dba3a5cd3119787e8ad378ddf2c40b022ecfc67c642b7acc8c1e3dd03ab50993e +b8d873927936719d2484cd03a6687d65697e17dcf4f0d5aed6f5e4750f52ef2133d4645894e7ebfc4ef6ce6788d404c8 +b1235594dbb15b674a419ff2b2deb644ad2a93791ca05af402823f87114483d6aa1689b7a9bea0f547ad12fe270e4344 +a53fda86571b0651f5affb74312551a082fffc0385cfd24c1d779985b72a5b1cf7c78b42b4f7e51e77055f8e5e915b00 +b579adcfd9c6ef916a5a999e77a0cb21d378c4ea67e13b7c58709d5da23a56c2e54218691fc4ac39a4a3d74f88cc31f7 +ab79e584011713e8a2f583e483a91a0c2a40771b77d91475825b5acbea82db4262132901cb3e4a108c46d7c9ee217a4e +a0fe58ea9eb982d7654c8aaf9366230578fc1362f6faae0594f8b9e659bcb405dff4aac0c7888bbe07f614ecf0d800a6 +867e50e74281f28ecd4925560e2e7a6f8911b135557b688254623acce0dbc41e23ac3e706a184a45d54c586edc416eb0 +89f81b61adda20ea9d0b387a36d0ab073dc7c7cbff518501962038be19867042f11fcc7ff78096e5d3b68c6d8dc04d9b +a58ee91bb556d43cf01f1398c5811f76dc0f11efdd569eed9ef178b3b0715e122060ec8f945b4dbf6eebfa2b90af6fa6 +ac460be540f4c840def2eef19fc754a9af34608d107cbadb53334cf194cc91138d53b9538fcd0ec970b5d4aa455b224a +b09b91f929de52c09d48ca0893be6eb44e2f5210a6c394689dc1f7729d4be4e11d0474b178e80cea8c2ac0d081f0e811 +8d37a442a76b06a02a4e64c2504aea72c8b9b020ab7bcc94580fe2b9603c7c50d7b1e9d70d2a7daea19c68667e8f8c31 +a9838d4c4e3f3a0075a952cf7dd623307ec633fcc81a7cf9e52e66c31780de33dbb3d74c320dc7f0a4b72f7a49949515 +a44766b6251af458fe4f5f9ed1e02950f35703520b8656f09fc42d9a2d38a700c11a7c8a0436ac2e5e9f053d0bb8ff91 +ad78d9481c840f5202546bea0d13c776826feb8b1b7c72e83d99a947622f0bf38a4208551c4c41beb1270d7792075457 +b619ffa8733b470039451e224b777845021e8dc1125f247a4ff2476cc774657d0ff9c5279da841fc1236047de9d81c60 +af760b0a30a1d6af3bc5cd6686f396bd41779aeeb6e0d70a09349bd5da17ca2e7965afc5c8ec22744198fbe3f02fb331 +a0cc209abdb768b589fcb7b376b6e1cac07743288c95a1cf1a0354b47f0cf91fca78a75c1fcafa6f5926d6c379116608 +864add673c89c41c754eeb3cd8dcff5cdde1d739fce65c30e474a082bb5d813cba6412e61154ce88fdb6c12c5d9be35b +b091443b0ce279327dc37cb484e9a5b69b257a714ce21895d67539172f95ffa326903747b64a3649e99aea7bb10d03f7 +a8c452b8c4ca8e0a61942a8e08e28f17fb0ef4c5b018b4e6d1a64038280afa2bf1169202f05f14af24a06ca72f448ccd +a23c24721d18bc48d5dcf70effcbef89a7ae24e67158d70ae1d8169ee75d9a051d34b14e9cf06488bac324fe58549f26 +92a730e30eb5f3231feb85f6720489dbb1afd42c43f05a1610c6b3c67bb949ec8fde507e924498f4ffc646f7b07d9123 +8dbe5abf4031ec9ba6bb06d1a47dd1121fb9e03b652804069250967fd5e9577d0039e233441b7f837a7c9d67ba18c28e +aa456bcfef6a21bb88181482b279df260297b3778e84594ebddbdf337e85d9e3d46ca1d0b516622fb0b103df8ec519b7 +a3b31ae621bd210a2b767e0e6f22eb28fe3c4943498a7e91753225426168b9a26da0e02f1dc5264da53a5ad240d9f51b +aa8d66857127e6e71874ce2202923385a7d2818b84cb73a6c42d71afe70972a70c6bdd2aad1a6e8c5e4ca728382a8ea8 +ac7e8e7a82f439127a5e40558d90d17990f8229852d21c13d753c2e97facf077cf59582b603984c3dd3faebd80aff4f5 +93a8bcf4159f455d1baa73d2ef2450dcd4100420de84169bbe28b8b7a5d1746273f870091a87a057e834f754f34204b1 +89d0ebb287c3613cdcae7f5acc43f17f09c0213fc40c074660120b755d664109ffb9902ed981ede79e018ddb0c845698 +a87ccbfad431406aadbee878d9cf7d91b13649d5f7e19938b7dfd32645a43b114eef64ff3a13201398bd9b0337832e5a +833c51d0d0048f70c3eefb4e70e4ff66d0809c41838e8d2c21c288dd3ae9d9dfaf26d1742bf4976dab83a2b381677011 +8bcd6b1c3b02fffead432e8b1680bad0a1ac5a712d4225e220690ee18df3e7406e2769e1f309e2e803b850bc96f0e768 +b61e3dbd88aaf4ff1401521781e2eea9ef8b66d1fac5387c83b1da9e65c2aa2a56c262dea9eceeb4ad86c90211672db0 +866d3090db944ecf190dd0651abf67659caafd31ae861bab9992c1e3915cb0952da7c561cc7e203560a610f48fae633b +a5e8971543c14274a8dc892b0be188c1b4fbc75c692ed29f166e0ea80874bc5520c2791342b7c1d2fb5dd454b03b8a5b +8f2f9fc50471bae9ea87487ebd1bc8576ef844cc42d606af5c4c0969670fdf2189afd643e4de3145864e7773d215f37f +b1bb0f2527db6d51f42b9224383c0f96048bbc03d469bf01fe1383173ef8b1cc9455d9dd8ba04d46057f46949bfc92b5 +aa7c99d906b4d7922296cfe2520473fc50137c03d68b7865c5bfb8adbc316b1034310ec4b5670c47295f4a80fb8d61e9 +a5d1da4d6aba555919df44cbaa8ff79378a1c9e2cfdfbf9d39c63a4a00f284c5a5724e28ecbc2d9dba27fe4ee5018bd5 +a8db53224f70af4d991b9aae4ffe92d2aa5b618ad9137784b55843e9f16cefbfd25ada355d308e9bbf55f6d2f7976fb3 +b6536c4232bb20e22af1a8bb12de76d5fec2ad9a3b48af1f38fa67e0f8504ef60f305a73d19385095bb6a9603fe29889 +87f7e371a1817a63d6838a8cf4ab3a8473d19ce0d4f40fd013c03d5ddd5f4985df2956531cc9f187928ef54c68f4f9a9 +ae13530b1dbc5e4dced9d909ea61286ec09e25c12f37a1ed2f309b0eb99863d236c3b25ed3484acc8c076ad2fa8cd430 +98928d850247c6f7606190e687d5c94a627550198dbdbea0161ef9515eacdb1a0f195cae3bb293112179082daccf8b35 +918528bb8e6a055ad4db6230d3a405e9e55866da15c4721f5ddd1f1f37962d4904aad7a419218fe6d906fe191a991806 +b71e31a06afe065773dd3f4a6e9ef81c3292e27a3b7fdfdd452d03e05af3b6dd654c355f7516b2a93553360c6681a73a +8870b83ab78a98820866f91ac643af9f3ff792a2b7fda34185a9456a63abdce42bfe8ad4dc67f08a6392f250d4062df4 +91eea1b668e52f7a7a5087fabf1cab803b0316f78d9fff469fbfde2162f660c250e4336a9eea4cb0450bd30ac067bc8b +8b74990946de7b72a92147ceac1bd9d55999a8b576e8df68639e40ed5dc2062cfcd727903133de482b6dca19d0aaed82 +8ebad537fece090ebbab662bdf2618e21ca30cf6329c50935e8346d1217dcbe3c1fe1ea28efca369c6003ce0a94703c1 +a8640479556fb59ebd1c40c5f368fbd960932fdbb782665e4a0e24e2bdb598fc0164ce8c0726d7759cfc59e60a62e182 +a9a52a6bf98ee4d749f6d38be2c60a6d54b64d5cbe4e67266633dc096cf28c97fe998596707d31968cbe2064b72256bf +847953c48a4ce6032780e9b39d0ed4384e0be202c2bbe2dfda3910f5d87aa5cd3c2ffbfcfae4dddce16d6ab657599b95 +b6f6e1485d3ec2a06abaecd23028b200b2e4a0096c16144d07403e1720ff8f9ba9d919016b5eb8dc5103880a7a77a1d3 +98dfc2065b1622f596dbe27131ea60bef7a193b12922cecb27f8c571404f483014f8014572e86ae2e341ab738e4887ef +acb0d205566bacc87bbe2e25d10793f63f7a1f27fd9e58f4f653ceae3ffeba511eaf658e068fad289eeb28f9edbeb35b +ae4411ed5b263673cee894c11fe4abc72a4bf642d94022a5c0f3369380fcdfc1c21e277f2902972252503f91ada3029a +ac4a7a27ba390a75d0a247d93d4a8ef1f0485f8d373a4af4e1139369ec274b91b3464d9738eeaceb19cd6f509e2f8262 +87379c3bf231fdafcf6472a79e9e55a938d851d4dd662ab6e0d95fd47a478ed99e2ad1e6e39be3c0fc4f6d996a7dd833 +81316904b035a8bcc2041199a789a2e6879486ba9fddcba0a82c745cc8dd8374a39e523b91792170cd30be7aa3005b85 +b8206809c6cd027ed019f472581b45f7e12288f89047928ba32b4856b6560ad30395830d71e5e30c556f6f182b1fe690 +88d76c028f534a62e019b4a52967bb8642ede6becfa3807be68fdd36d366fc84a4ac8dc176e80a68bc59eb62caf5dff9 +8c3b8be685b0f8aad131ee7544d0e12f223f08a6f8edaf464b385ac644e0ddc9eff7cc7cb5c1b50ab5d71ea0f41d2213 +8d91410e004f76c50fdc05784157b4d839cb5090022c629c7c97a5e0c3536eeafee17a527b54b1165c3cd81774bb54ce +b25c2863bc28ec5281ce800ddf91a7e1a53f4c6d5da1e6c86ef4616e93bcf55ed49e297216d01379f5c6e7b3c1e46728 +865f7b09ac3ca03f20be90c48f6975dd2588838c2536c7a3532a6aa5187ed0b709cd03d91ff4048061c10d0aa72b69ce +b3f7477c90c11596eb4f8bbf34adbcb832638c4ff3cdd090d4d477ee50472ac9ddaf5be9ad7eca3f148960d362bbd098 +8db35fd53fca04faecd1c76a8227160b3ab46ac1af070f2492445a19d8ff7c25bbaef6c9fa0c8c088444561e9f7e4eb2 +a478b6e9d058a2e01d2fc053b739092e113c23a6a2770a16afbef044a3709a9e32f425ace9ba7981325f02667c3f9609 +98caa6bd38916c08cf221722a675a4f7577f33452623de801d2b3429595f988090907a7e99960fff7c076d6d8e877b31 +b79aaaacefc49c3038a14d2ac468cfec8c2161e88bdae91798d63552cdbe39e0e02f9225717436b9b8a40a022c633c6e +845a31006c680ee6a0cc41d3dc6c0c95d833fcf426f2e7c573fa15b2c4c641fbd6fe5ebb0e23720cc3467d6ee1d80dc4 +a1bc287e272cf8b74dbf6405b3a5190883195806aa351f1dc8e525aa342283f0a35ff687e3b434324dedee74946dd185 +a4fd2dc8db75d3783a020856e2b3aa266dc6926e84f5c491ef739a3bddd46dc8e9e0fc1177937839ef1b18d062ffbb9e +acbf0d3c697f57c202bb8c5dc4f3fc341b8fc509a455d44bd86acc67cad2a04495d5537bcd3e98680185e8aa286f2587 +a5caf423a917352e1b8e844f5968a6da4fdeae467d10c6f4bbd82b5eea46a660b82d2f5440d3641c717b2c3c9ed0be52 +8a39d763c08b926599ab1233219c49c825368fad14d9afc7c0c039224d37c00d8743293fd21645bf0b91eaf579a99867 +b2b53a496def0ba06e80b28f36530fbe0fb5d70a601a2f10722e59abee529369c1ae8fd0f2db9184dd4a2519bb832d94 +a73980fcef053f1b60ebbb5d78ba6332a475e0b96a0c724741a3abf3b59dd344772527f07203cf4c9cb5155ebed81fa0 +a070d20acce42518ece322c9db096f16aed620303a39d8d5735a0df6e70fbeceb940e8d9f5cc38f3314b2240394ec47b +a50cf591f522f19ca337b73089557f75929d9f645f3e57d4f241e14cdd1ea3fb48d84bcf05e4f0377afbb789fbdb5d20 +82a5ffce451096aca8eeb0cd2ae9d83db3ed76da3f531a80d9a70a346359bf05d74863ce6a7c848522b526156a5e20cd +88e0e84d358cbb93755a906f329db1537c3894845f32b9b0b691c29cbb455373d9452fadd1e77e20a623f6eaf624de6f +aa07ac7b84a6d6838826e0b9e350d8ec75e398a52e9824e6b0da6ae4010e5943fec4f00239e96433f291fef9d1d1e609 +ac8887bf39366034bc63f6cc5db0c26fd27307cbc3d6cce47894a8a019c22dd51322fb5096edc018227edfafc053a8f6 +b7d26c26c5b33f77422191dca94977588ab1d4b9ce7d0e19c4a3b4cd1c25211b78c328dbf81e755e78cd7d1d622ad23e +99a676d5af49f0ba44047009298d8474cabf2d5bca1a76ba21eff7ee3c4691a102fdefea27bc948ccad8894a658abd02 +b0d09a91909ab3620c183bdf1d53d43d39eb750dc7a722c661c3de3a1a5d383ad221f71bae374f8a71867505958a3f76 +84681a883de8e4b93d68ac10e91899c2bbb815ce2de74bb48a11a6113b2a3f4df8aceabda1f5f67bc5aacac8c9da7221 +9470259957780fa9b43521fab3644f555f5343281c72582b56d2efd11991d897b3b481cafa48681c5aeb80c9663b68f7 +ab1b29f7ece686e6fa968a4815da1d64f3579fed3bc92e1f3e51cd13a3c076b6cf695ed269d373300a62463dc98a4234 +8ab415bfcd5f1061f7687597024c96dd9c7cb4942b5989379a7a3b5742f7d394337886317659cbeacaf030234a24f972 +b9b524aad924f9acc63d002d617488f31b0016e0f0548f050cada285ce7491b74a125621638f19e9c96eabb091d945be +8c4c373e79415061837dd0def4f28a2d5d74d21cb13a76c9049ad678ca40228405ab0c3941df49249847ecdefc1a5b78 +a8edf4710b5ab2929d3db6c1c0e3e242261bbaa8bcec56908ddadd7d2dad2dca9d6eb9de630b960b122ebeea41040421 +8d66bb3b50b9df8f373163629f9221b3d4b6980a05ea81dc3741bfe9519cf3ebba7ab98e98390bae475e8ede5821bd5c +8d3c21bae7f0cfb97c56952bb22084b58e7bb718890935b73103f33adf5e4d99cd262f929c6eeab96209814f0dbae50a +a5c66cfab3d9ebf733c4af24bebc97070e7989fe3c73e79ac85fb0e4d40ae44fb571e0fad4ad72560e13ed453900d14f +9362e6b50b43dbefbc3254471372297b5dcce809cd3b60bf74a1268ab68bdb50e46e462cbd78f0d6c056330e982846af +854630d08e3f0243d570cc2e856234cb4c1a158d9c1883bf028a76525aaa34be897fe918d5f6da9764a3735fa9ebd24a +8c7d246985469ff252c3f4df6c7c9196fc79f05c1c66a609d84725c78001d0837c7a7049394ba5cf7e863e2d58af8417 +ae050271e01b528925302e71903f785b782f7bf4e4e7a7f537140219bc352dc7540c657ed03d3a297ad36798ecdb98cd +8d2ae9179fcf2b0c69850554580b52c1f4a5bd865af5f3028f222f4acad9c1ad69a8ef6c7dc7b03715ee5c506b74325e +b8ef8de6ce6369a8851cd36db0ccf00a85077e816c14c4e601f533330af9e3acf0743a95d28962ed8bfcfc2520ef3cfe +a6ecad6fdfb851b40356a8b1060f38235407a0f2706e7b8bb4a13465ca3f81d4f5b99466ac2565c60af15f022d26732e +819ff14cdea3ab89d98e133cd2d0379361e2e2c67ad94eeddcdb9232efd509f51d12f4f03ebd4dd953bd262a886281f7 +8561cd0f7a6dbcddd83fcd7f472d7dbcba95b2d4fb98276f48fccf69f76d284e626d7e41314b633352df8e6333fd52a1 +b42557ccce32d9a894d538c48712cb3e212d06ac05cd5e0527ccd2db1078ee6ae399bf6a601ffdab1f5913d35fc0b20c +89b4008d767aad3c6f93c349d3b956e28307311a5b1cec237e8d74bb0dee7e972c24f347fd56afd915a2342bd7bc32f0 +877487384b207e53f5492f4e36c832c2227f92d1bb60542cfeb35e025a4a7afc2b885fae2528b33b40ab09510398f83e +8c411050b63c9053dd0cd81dacb48753c3d7f162028098e024d17cd6348482703a69df31ad6256e3d25a8bbf7783de39 +a8506b54a88d17ac10fb1b0d1fe4aa40eae7553a064863d7f6b52ccc4236dd4b82d01dca6ba87da9a239e3069ba879fb +b1a24caef9df64750c1350789bb8d8a0db0f39474a1c74ea9ba064b1516db6923f00af8d57c632d58844fb8786c3d47a +959d6e255f212b0708c58a2f75cb1fe932248c9d93424612c1b8d1e640149656059737e4db2139afd5556bcdacf3eda2 +84525af21a8d78748680b6535bbc9dc2f0cf9a1d1740d12f382f6ecb2e73811d6c1da2ad9956070b1a617c61fcff9fe5 +b74417d84597a485d0a8e1be07bf78f17ebb2e7b3521b748f73935b9afbbd82f34b710fb7749e7d4ab55b0c7f9de127d +a4a9aecb19a6bab167af96d8b9d9aa5308eab19e6bfb78f5a580f9bf89bdf250a7b52a09b75f715d651cb73febd08e84 +9777b30be2c5ffe7d29cc2803a562a32fb43b59d8c3f05a707ab60ec05b28293716230a7d264d7cd9dd358fc031cc13e +95dce7a3d4f23ac0050c510999f5fbf8042f771e8f8f94192e17bcbfa213470802ebdbe33a876cb621cf42e275cbfc8b +b0b963ebcbbee847ab8ae740478544350b3ac7e86887e4dfb2299ee5096247cd2b03c1de74c774d9bde94ae2ee2dcd59 +a4ab20bafa316030264e13f7ef5891a2c3b29ab62e1668fcb5881f50a9acac6adbe3d706c07e62f2539715db768f6c43 +901478a297669d608e406fe4989be75264b6c8be12169aa9e0ad5234f459ca377f78484ffd2099a2fe2db5e457826427 +88c76e5c250810c057004a03408b85cd918e0c8903dc55a0dd8bb9b4fc2b25c87f9b8cf5943eb19fbbe99d36490050c5 +91607322bbad4a4f03fc0012d0821eff5f8c516fda45d1ec1133bface6f858bf04b25547be24159cab931a7aa08344d4 +843203e07fce3c6c81f84bc6dc5fb5e9d1c50c8811ace522dc66e8658433a0ef9784c947e6a62c11bf705307ef05212e +91dd8813a5d6dddcda7b0f87f672b83198cd0959d8311b2b26fb1fae745185c01f796fbd03aad9db9b58482483fdadd8 +8d15911aacf76c8bcd7136e958febd6963104addcd751ce5c06b6c37213f9c4fb0ffd4e0d12c8e40c36d658999724bfd +8a36c5732d3f1b497ebe9250610605ee62a78eaa9e1a45f329d09aaa1061131cf1d9df00f3a7d0fe8ad614a1ff9caaae +a407d06affae03660881ce20dab5e2d2d6cddc23cd09b95502a9181c465e57597841144cb34d22889902aff23a76d049 +b5fd856d0578620a7e25674d9503be7d97a2222900e1b4738c1d81ff6483b144e19e46802e91161e246271f90270e6cf +91b7708869cdb5a7317f88c0312d103f8ce90be14fb4f219c2e074045a2a83636fdc3e69e862049fc7c1ef000e832541 +b64719cc5480709d1dae958f1d3082b32a43376da446c8f9f64cb02a301effc9c34d9102051733315a8179aed94d53cc +94347a9542ff9d18f7d9eaa2f4d9b832d0e535fe49d52aa2de08aa8192400eddabdb6444a2a78883e27c779eed7fdf5a +840ef44a733ff1376466698cd26f82cf56bb44811e196340467f932efa3ae1ef9958a0701b3b032f50fd9c1d2aed9ab5 +90ab3f6f67688888a31ffc2a882bb37adab32d1a4b278951a21646f90d03385fc976715fc639a785d015751171016f10 +b56f35d164c24b557dbcbc8a4bfa681ec916f8741ffcb27fb389c164f4e3ed2be325210ef5bdaeae7a172ca9599ab442 +a7921a5a80d7cf6ae81ba9ee05e0579b18c20cd2852762c89d6496aa4c8ca9d1ca2434a67b2c16d333ea8e382cdab1e3 +a506bcfbd7e7e5a92f68a1bd87d07ad5fe3b97aeee40af2bf2cae4efcd77fff03f872732c5b7883aa6584bee65d6f8cb +a8c46cff58931a1ce9cbe1501e1da90b174cddd6d50f3dfdfb759d1d4ad4673c0a8feed6c1f24c7af32865a7d6c984e5 +b45686265a83bff69e312c5149db7bb70ac3ec790dc92e392b54d9c85a656e2bf58596ce269f014a906eafc97461aa5f +8d4009a75ccb2f29f54a5f16684b93202c570d7a56ec1a8b20173269c5f7115894f210c26b41e8d54d4072de2d1c75d0 +aef8810af4fc676bf84a0d57b189760ddc3375c64e982539107422e3de2580b89bd27aa6da44e827b56db1b5555e4ee8 +888f0e1e4a34f48eb9a18ef4de334c27564d72f2cf8073e3d46d881853ac1424d79e88d8ddb251914890588937c8f711 +b64b0aa7b3a8f6e0d4b3499fe54e751b8c3e946377c0d5a6dbb677be23736b86a7e8a6be022411601dd75012012c3555 +8d57776f519f0dd912ea14f79fbab53a30624e102f9575c0bad08d2dc754e6be54f39b11278c290977d9b9c7c0e1e0ad +a018fc00d532ceb2e4de908a15606db9b6e0665dd77190e2338da7c87a1713e6b9b61554e7c1462f0f6d4934b960b15c +8c932be83ace46f65c78e145b384f58e41546dc0395270c1397874d88626fdeda395c8a289d602b4c312fe98c1311856 +89174838e21639d6bdd91a0621f04dc056907b88e305dd66e46a08f6d65f731dea72ae87ca5e3042d609e8de8de9aa26 +b7b7f508bb74f7a827ac8189daa855598ff1d96fa3a02394891fd105d8f0816224cd50ac4bf2ed1cf469ace516c48184 +b31877ad682583283baadd68dc1bebd83f5748b165aadd7fe9ef61a343773b88bcd3a022f36d6c92f339b7bfd72820a9 +b79d77260b25daf9126dab7a193df2d7d30542786fa1733ffaf6261734770275d3ca8bae1d9915d1181a78510b3439db +91894fb94cd4c1dd2ceaf9c53a7020c5799ba1217cf2d251ea5bc91ed26e1159dd758e98282ebe35a0395ef9f1ed15a0 +ab59895cdafd33934ceedfc3f0d5d89880482cba6c99a6db93245f9e41987efd76e0640e80aef31782c9a8c7a83fccec +aa22ea63654315e033e09d4d4432331904a6fc5fb1732557987846e3c564668ca67c60a324b4af01663a23af11a9ce4b +b53ba3ef342601467e1f71aa280e100fbabbd38518fa0193e0099505036ee517c1ac78e96e9baeb549bb6879bb698fb0 +943fd69fd656f37487cca3605dc7e5a215fddd811caf228595ec428751fc1de484a0cb84c667fe4d7c35599bfa0e5e34 +9353128b5ebe0dddc555093cf3e5942754f938173541033e8788d7331fafc56f68d9f97b4131e37963ab7f1c8946f5f1 +a76cd3c566691f65cfb86453b5b31dbaf3cab8f84fe1f795dd1e570784b9b01bdd5f0b3c1e233942b1b5838290e00598 +983d84b2e53ffa4ae7f3ba29ef2345247ea2377686b74a10479a0ef105ecf90427bf53b74c96dfa346d0f842b6ffb25b +92e0fe9063306894a2c6970c001781cff416c87e87cb5fbac927a3192655c3da4063e6fa93539f6ff58efac6adcc5514 +b00a81f03c2b8703acd4e2e4c21e06973aba696415d0ea1a648ace2b0ea19b242fede10e4f9d7dcd61c546ab878bc8f9 +b0d08d880f3b456a10bf65cff983f754f545c840c413aea90ce7101a66eb0a0b9b1549d6c4d57725315828607963f15a +90cb64d03534f913b411375cce88a9e8b1329ce67a9f89ca5df8a22b8c1c97707fec727dbcbb9737f20c4cf751359277 +8327c2d42590dfcdb78477fc18dcf71608686ad66c49bce64d7ee874668be7e1c17cc1042a754bbc77c9daf50b2dae07 +8532171ea13aa7e37178e51a6c775da469d2e26ec854eb16e60f3307db4acec110d2155832c202e9ba525fc99174e3b0 +83ca44b15393d021de2a511fa5511c5bd4e0ac7d67259dce5a5328f38a3cce9c3a269405959a2486016bc27bb140f9ff +b1d36e8ca812be545505c8214943b36cabee48112cf0de369957afa796d37f86bf7249d9f36e8e990f26f1076f292b13 +9803abf45be5271e2f3164c328d449efc4b8fc92dfc1225d38e09630909fe92e90a5c77618daa5f592d23fc3ad667094 +b268ad68c7bf432a01039cd889afae815c3e120f57930d463aece10af4fd330b5bd7d8869ef1bcf6b2e78e4229922edc +a4c91a0d6f16b1553264592b4cbbbf3ca5da32ab053ffbdd3dbb1aed1afb650fb6e0dc5274f71a51d7160856477228db +ad89d043c2f0f17806277ffdf3ecf007448e93968663f8a0b674254f36170447b7527d5906035e5e56f4146b89b5af56 +8b6964f757a72a22a642e4d69102951897e20c21449184e44717bd0681d75f7c5bfa5ee5397f6e53febf85a1810d6ed1 +b08f5cdaabec910856920cd6e836c830b863eb578423edf0b32529488f71fe8257d90aed4a127448204df498b6815d79 +af26bb3358be9d280d39b21d831bb53145c4527a642446073fee5a86215c4c89ff49a3877a7a549486262f6f57a0f476 +b4010b37ec4d7c2af20800e272539200a6b623ae4636ecbd0e619484f4ab9240d02bc5541ace3a3fb955dc0a3d774212 +82752ab52bdcc3cc2fc405cb05a2e694d3df4a3a68f2179ec0652536d067b43660b96f85f573f26fbd664a9ef899f650 +96d392dde067473a81faf2d1fea55b6429126b88b160e39b4210d31d0a82833ffd3a80e07d24d495aea2d96be7251547 +a76d8236d6671204d440c33ac5b8deb71fa389f6563d80e73be8b043ec77d4c9b06f9a586117c7f957f4af0331cbc871 +b6c90961f68b5e385d85c9830ec765d22a425f506904c4d506b87d8944c2b2c09615e740ed351df0f9321a7b93979cae +a6ec5ea80c7558403485b3b1869cdc63bde239bafdf936d9b62a37031628402a36a2cfa5cfbb8e26ac922cb0a209b3ba +8c3195bbdbf9bc0fc95fa7e3d7f739353c947f7767d1e3cb24d8c8602d8ea0a1790ac30b815be2a2ba26caa5227891e2 +a7f8a63d809f1155722c57f375ea00412b00147776ae4444f342550279ef4415450d6f400000a326bf11fea6c77bf941 +97fa404df48433a00c85793440e89bb1af44c7267588ae937a1f5d53e01e1c4d4fc8e4a6d517f3978bfdd6c2dfde012f +a984a0a3836de3d8d909c4629a2636aacb85393f6f214a2ef68860081e9db05ad608024762db0dc35e895dc00e2d4cdd +9526cf088ab90335add1db4d3a4ac631b58cbfbe88fa0845a877d33247d1cfeb85994522e1eb8f8874651bfb1df03e2a +ac83443fd0afe99ad49de9bf8230158c118e2814c9c89db5ac951c240d6c2ce45e7677221279d9e97848ec466b99aafe +aeeefdbaba612e971697798ceaf63b247949dc823a0ad771ae5b988a5e882b338a98d3d0796230f49d533ec5ba411b39 +ae3f248b5a7b0f92b7820a6c5ae21e5bd8f4265d4f6e21a22512079b8ee9be06393fd3133ce8ebac0faf23f4f8517e36 +a64a831b908eee784b8388b45447d2885ec0551b26b0c2b15e5f417d0a12c79e867fb7bd3d008d0af98b44336f8ec1ad +b242238cd8362b6e440ba21806905714dd55172db25ec7195f3fc4937b2aba146d5cbf3cf691a1384b4752dc3b54d627 +819f97f337eea1ffb2a678cc25f556f1aab751c6b048993a1d430fe1a3ddd8bb411c152e12ca60ec6e057c190cd1db9a +b9d7d187407380df54ee9fef224c54eec1bfabf17dc8abf60765b7951f538f59aa26fffd5846cfe05546c35f59b573f4 +aa6e3c14efa6a5962812e3f94f8ce673a433f4a82d07a67577285ea0eaa07f8be7115853122d12d6d4e1fdf64c504be1 +82268bee9c1662d3ddb5fb785abfae6fb8b774190f30267f1d47091d2cd4b3874db4372625aa36c32f27b0eee986269b +b236459565b7b966166c4a35b2fa71030b40321821b8e96879d95f0e83a0baf33fa25721f30af4a631df209e25b96061 +8708d752632d2435d2d5b1db4ad1fa2558d776a013655f88e9a3556d86b71976e7dfe5b8834fdec97682cd94560d0d0d +ae1424a68ae2dbfb0f01211f11773732a50510b5585c1fb005cb892b2c6a58f4a55490b5c5b4483c6fce40e9d3236a52 +b3f5f722af9dddb07293c871ce97abbccba0093ca98c8d74b1318fa21396fc1b45b69c15084f63d728f9908442024506 +9606f3ce5e63886853ca476dc0949e7f1051889d529365c0cb0296fdc02abd088f0f0318ecd2cf36740a3634132d36f6 +b11a833a49fa138db46b25ff8cdda665295226595bc212c0931b4931d0a55c99da972c12b4ef753f7e37c6332356e350 +afede34e7dab0a9e074bc19a7daddb27df65735581ca24ad70c891c98b1349fcebbcf3ba6b32c2617fe06a5818dabc2d +97993d456e459e66322d01f8eb13918979761c3e8590910453944bdff90b24091bb018ac6499792515c9923be289f99f +977e3e967eff19290a192cd11df3667d511b398fb3ac9a5114a0f3707e25a0edcb56105648b1b85a8b7519fc529fc6f6 +b873a7c88bf58731fe1bf61ff6828bf114cf5228f254083304a4570e854e83748fc98683ddba62d978fff7909f2c5c47 +ad4b2691f6f19da1d123aaa23cca3e876247ed9a4ab23c599afdbc0d3aa49776442a7ceaa996ac550d0313d9b9a36cee +b9210713c78e19685608c6475bfa974b57ac276808a443f8b280945c5d5f9c39da43effa294bfb1a6c6f7b6b9f85bf6c +a65152f376113e61a0e468759de38d742caa260291b4753391ee408dea55927af08a4d4a9918600a3bdf1df462dffe76 +8bf8c27ad5140dde7f3d2280fd4cc6b29ab76537e8d7aa7011a9d2796ee3e56e9a60c27b5c2da6c5e14fc866301dc195 +92fde8effc9f61393a2771155812b863cff2a0c5423d7d40aa04d621d396b44af94ddd376c28e7d2f53c930aea947484 +97a01d1dd9ee30553ce676011aea97fa93d55038ada95f0057d2362ae9437f3ed13de8290e2ff21e3167dd7ba10b9c3f +89affffaa63cb2df3490f76f0d1e1d6ca35c221dd34057176ba739fa18d492355e6d2a5a5ad93a136d3b1fed0bb8aa19 +928b8e255a77e1f0495c86d3c63b83677b4561a5fcbbe5d3210f1e0fc947496e426d6bf3b49394a5df796c9f25673fc4 +842a0af91799c9b533e79ee081efe2a634cac6c584c2f054fb7d1db67dde90ae36de36cbf712ec9cd1a0c7ee79e151ea +a65b946cf637e090baf2107c9a42f354b390e7316beb8913638130dbc67c918926eb87bec3b1fe92ef72bc77a170fa3b +aafc0f19bfd71ab5ae4a8510c7861458b70ad062a44107b1b1dbacbfa44ba3217028c2824bd7058e2fa32455f624040b +95269dc787653814e0be899c95dba8cfa384f575a25e671c0806fd80816ad6797dc819d30ae06e1d0ed9cb01c3950d47 +a1e760f7fa5775a1b2964b719ff961a92083c5c617f637fc46e0c9c20ab233f8686f7f38c3cb27d825c54dd95e93a59b +ac3b8a7c2317ea967f229eddc3e23e279427f665c4705c7532ed33443f1243d33453c1088f57088d2ab1e3df690a9cc9 +b787beeddfbfe36dd51ec4efd9cf83e59e84d354c3353cc9c447be53ae53d366ed1c59b686e52a92f002142c8652bfe0 +b7a64198300cb6716aa7ac6b25621f8bdec46ad5c07a27e165b3f774cdf65bcfdbf31e9bae0c16b44de4b00ada7a4244 +b8ae9f1452909e0c412c7a7fe075027691ea8df1347f65a5507bc8848f1d2c833d69748076db1129e5b4fb912f65c86c +9682e41872456b9fa67def89e71f06d362d6c8ca85c9c48536615bc401442711e1c9803f10ab7f8ab5feaec0f9df20a6 +88889ff4e271dc1c7e21989cc39f73cde2f0475acd98078281591ff6c944fadeb9954e72334319050205d745d4df73df +8f79b5b8159e7fd0d93b0645f3c416464f39aec353b57d99ecf24f96272df8a068ad67a6c90c78d82c63b40bb73989bb +838c01a009a3d8558a3f0bdd5e22de21af71ca1aefc8423c91dc577d50920e9516880e87dce3e6d086e11cd45c9052d9 +b97f1c6eee8a78f137c840667cc288256e39294268a3009419298a04a1d0087c9c9077b33c917c65caf76637702dda8a +972284ce72f96a61c899260203dfa06fc3268981732bef74060641c1a5068ead723e3399431c247ca034b0dae861e8df +945a8d52d6d3db6663dbd3110c6587f9e9c44132045eeffba15621576d178315cb52870fa5861669f84f0bee646183fe +a0a547b5f0967b1c3e5ec6c6a9a99f0578521489180dfdfbb5561f4d166baac43a2f06f950f645ce991664e167537eed +a0592cda5cdddf1340033a745fd13a6eff2021f2e26587116c61c60edead067e0f217bc2bef4172a3c9839b0b978ab35 +b9c223b65a3281587fa44ec829e609154b32f801fd1de6950e01eafb07a8324243b960d5735288d0f89f0078b2c42b5b +99ebfc3b8f9f98249f4d37a0023149ed85edd7a5abe062c8fb30c8c84555258b998bdcdd1d400bc0fa2a4aaa8b224466 +955b68526e6cb3937b26843270f4e60f9c6c8ece2fa9308fe3e23afa433309c068c66a4bc16ee2cf04220f095e9afce4 +b766caeafcc00378135ae53397f8a67ed586f5e30795462c4a35853de6681b1f17401a1c40958de32b197c083b7279c1 +921bf87cad947c2c33fa596d819423c10337a76fe5a63813c0a9dc78a728207ae7b339407a402fc4d0f7cba3af6da6fc +a74ba1f3bc3e6c025db411308f49b347ec91da1c916bda9da61e510ec8d71d25e0ac0f124811b7860e5204f93099af27 +a29b4d144e0bf17a7e8353f2824cef0ce85621396babe8a0b873ca1e8a5f8d508b87866cf86da348470649fceefd735c +a8040e12ffc3480dd83a349d06741d1572ef91932c46f5cf03aee8454254156ee95786fd013d5654725e674c920cec32 +8c4cf34ca60afd33923f219ffed054f90cd3f253ffeb2204a3b61b0183417e366c16c07fae860e362b0f2bfe3e1a1d35 +8195eede4ddb1c950459df6c396b2e99d83059f282b420acc34220cadeed16ab65c856f2c52568d86d3c682818ed7b37 +91fff19e54c15932260aa990c7fcb3c3c3da94845cc5aa8740ef56cf9f58d19b4c3c55596f8d6c877f9f4d22921d93aa +a3e0bf7e5d02a80b75cf75f2db7e66cb625250c45436e3c136d86297d652590ec97c2311bafe407ad357c79ab29d107b +81917ff87e5ed2ae4656b481a63ced9e6e5ff653b8aa6b7986911b8bc1ee5b8ef4f4d7882c3f250f2238e141b227e510 +915fdbe5e7de09c66c0416ae14a8750db9412e11dc576cf6158755fdcaf67abdbf0fa79b554cac4fe91c4ec245be073f +8df27eafb5c3996ba4dc5773c1a45ca77e626b52e454dc1c4058aa94c2067c18332280630cc3d364821ee53bf2b8c130 +934f8a17c5cbb827d7868f5c8ca00cb027728a841000a16a3428ab16aa28733f16b52f58c9c4fbf75ccc45df72d9c4df +b83f4da811f9183c25de8958bc73b504cf790e0f357cbe74ef696efa7aca97ad3b7ead1faf76e9f982c65b6a4d888fc2 +87188213c8b5c268dc2b6da413f0501c95749e953791b727450af3e43714149c115b596b33b63a2f006a1a271b87efd0 +83e9e888ab9c3e30761de635d9aabd31248cdd92f7675fc43e4b21fd96a03ec1dc4ad2ec94fec857ffb52683ac98e360 +b4b9a1823fe2d983dc4ec4e3aaea297e581c3fc5ab4b4af5fa1370caa37af2d1cc7fc6bfc5e7da60ad8fdce27dfe4b24 +856388bc78aef465dbcdd1f559252e028c9e9a2225c37d645c138e78f008f764124522705822a61326a6d1c79781e189 +a6431b36db93c3b47353ba22e7c9592c9cdfb9cbdd052ecf2cc3793f5b60c1e89bc96e6bae117bfd047f2308da00dd2f +b619972d48e7e4291542dcde08f7a9cdc883c892986ded2f23ccb216e245cd8d9ad1d285347b0f9d7611d63bf4cee2bc +8845cca6ff8595955f37440232f8e61d5351500bd016dfadd182b9d39544db77a62f4e0102ff74dd4173ae2c181d24ef +b2f5f7fa26dcd3b6550879520172db2d64ee6aaa213cbef1a12befbce03f0973a22eb4e5d7b977f466ac2bf8323dcedd +858b7f7e2d44bdf5235841164aa8b4f3d33934e8cb122794d90e0c1cac726417b220529e4f896d7b77902ab0ccd35b3a +80b0408a092dae2b287a5e32ea1ad52b78b10e9c12f49282976cd738f5d834e03d1ad59b09c5ccaccc39818b87d06092 +b996b0a9c6a2d14d984edcd6ab56bc941674102980d65b3ad9733455f49473d3f587c8cbf661228a7e125ddbe07e3198 +90224fcebb36865293bd63af786e0c5ade6b67c4938d77eb0cbae730d514fdd0fe2d6632788e858afd29d46310cf86df +b71351fdfff7168b0a5ec48397ecc27ac36657a8033d9981e97002dcca0303e3715ce6dd3f39423bc8ef286fa2e9e669 +ae2a3f078b89fb753ce4ed87e0c1a58bb19b4f0cfb6586dedb9fcab99d097d659a489fb40e14651741e1375cfc4b6c5f +8ef476b118e0b868caed297c161f4231bbeb863cdfa5e2eaa0fc6b6669425ce7af50dc374abceac154c287de50c22307 +92e46ab472c56cfc6458955270d3c72b7bde563bb32f7d4ab4d959db6f885764a3d864e1aa19802fefaa5e16b0cb0b54 +96a3f68323d1c94e73d5938a18a377af31b782f56212de3f489d22bc289cf24793a95b37f1d6776edf88114b5c1fa695 +962cc068cfce6faaa27213c4e43e44eeff0dfbb6d25b814e82c7da981fb81d7d91868fa2344f05fb552362f98cfd4a72 +895d4e4c4ad670abf66d43d59675b1add7afad7438ada8f42a0360c704cee2060f9ac15b4d27e9b9d0996bb801276fe3 +b3ad18d7ece71f89f2ef749b853c45dc56bf1c796250024b39a1e91ed11ca32713864049c9aaaea60cde309b47486bbf +8f05404e0c0258fdbae50e97ccb9b72ee17e0bd2400d9102c0dad981dac8c4c71585f03e9b5d50086d0a2d3334cb55d1 +8bd877e9d4591d02c63c6f9fc9976c109de2d0d2df2bfa5f6a3232bab5b0b8b46e255679520480c2d7a318545efa1245 +8d4c16b5d98957c9da13d3f36c46f176e64e5be879f22be3179a2c0e624fe4758a82bf8c8027410002f973a3b84cd55a +86e2a8dea86427b424fa8eada881bdff896907084a495546e66556cbdf070b78ba312bf441eb1be6a80006d25d5097a3 +8608b0c117fd8652fdab0495b08fadbeba95d9c37068e570de6fddfef1ba4a1773b42ac2be212836141d1bdcdef11a17 +a13d6febf5fb993ae76cae08423ca28da8b818d6ef0fde32976a4db57839cd45b085026b28ee5795f10a9a8e3098c683 +8e261967fa6de96f00bc94a199d7f72896a6ad8a7bbb1d6187cca8fad824e522880e20f766620f4f7e191c53321d70f9 +8b8e8972ac0218d7e3d922c734302803878ad508ca19f5f012bc047babd8a5c5a53deb5fe7c15a4c00fd6d1cb9b1dbd0 +b5616b233fb3574a2717d125a434a2682ff68546dccf116dd8a3b750a096982f185614b9fb6c7678107ff40a451f56fa +aa6adf9b0c3334b0d0663f583a4914523b2ac2e7adffdb026ab9109295ff6af003ef8357026dbcf789896d2afded8d73 +acb72df56a0b65496cd534448ed4f62950bb1e11e50873b6ed349c088ee364441821294ce0f7c61bd7d38105bea3b442 +abae12df83e01ec947249fedd0115dc501d2b03ff7232092979eda531dbbca29ace1d46923427c7dde4c17bdf3fd7708 +820b4fc2b63a9fda7964acf5caf19a2fc4965007cb6d6b511fcafcb1f71c3f673a1c0791d3f86e3a9a1eb6955b191cc0 +af277259d78c6b0f4f030a10c53577555df5e83319ddbad91afbd7c30bc58e7671c56d00d66ec3ab5ef56470cd910cee +ad4a861c59f1f5ca1beedd488fb3d131dea924fffd8e038741a1a7371fad7370ca5cf80dc01f177fbb9576713bb9a5b3 +b67a5162982ce6a55ccfb2f177b1ec26b110043cf18abd6a6c451cf140b5af2d634591eb4f28ad92177d8c7e5cd0a5e8 +96176d0a83816330187798072d449cbfccff682561e668faf6b1220c9a6535b32a6e4f852e8abb00f79abb87493df16b +b0afe6e7cb672e18f0206e4423f51f8bd0017bf464c4b186d46332c5a5847647f89ff7fa4801a41c1b0b42f6135bcc92 +8fc5e7a95ef20c1278c645892811f6fe3f15c431ebc998a32ec0da44e7213ea934ed2be65239f3f49b8ec471e9914160 +b7793e41adda6c82ba1f2a31f656f6205f65bf8a3d50d836ee631bc7ce77c153345a2d0fc5c60edf8b37457c3729c4ec +a504dd7e4d6b2f4379f22cc867c65535079c75ccc575955f961677fa63ecb9f74026fa2f60c9fb6323c1699259e5e9c8 +ab899d00ae693649cc1afdf30fb80d728973d2177c006e428bf61c7be01e183866614e05410041bc82cb14a33330e69c +8a3bd8b0b1be570b65c4432a0f6dc42f48a2000e30ab089cf781d38f4090467b54f79c0d472fcbf18ef6a00df69cc6f3 +b4d7028f7f76a96a3d7803fca7f507ae11a77c5346e9cdfccb120a833a59bda1f4264e425aa588e7a16f8e7638061d84 +b9c7511a76ea5fb105de905d44b02edb17008335766ee357ed386b7b3cf19640a98b38785cb14603c1192bee5886c9b6 +8563afb12e53aed71ac7103ab8602bfa8371ae095207cb0d59e8fd389b6ad1aff0641147e53cb6a7ca16c7f37c9c5e6b +8e108be614604e09974a9ed90960c28c4ea330a3d9a0cb4af6dd6f193f84ab282b243ecdf549b3131036bebc8905690c +b794d127fbedb9c5b58e31822361706ffac55ce023fbfe55716c3c48c2fd2f2c7660a67346864dfe588812d369cb50b6 +b797a3442fc3b44f41baefd30346f9ac7f96e770d010d53c146ce74ce424c10fb62758b7e108b8abfdc5fafd89d745cb +993bb71e031e8096442e6205625e1bfddfe6dd6a83a81f3e2f84fafa9e5082ab4cad80a099f21eff2e81c83457c725c3 +8711ab833fc03e37acf2e1e74cfd9133b101ff4144fe30260654398ae48912ab46549d552eb9d15d2ea57760d35ac62e +b21321fd2a12083863a1576c5930e1aecb330391ef83326d9d92e1f6f0d066d1394519284ddab55b2cb77417d4b0292f +877d98f731ffe3ee94b0b5b72d127630fa8a96f6ca4f913d2aa581f67732df6709493693053b3e22b0181632ac6c1e3b +ae391c12e0eb8c145103c62ea64f41345973311c3bf7281fa6bf9b7faafac87bcf0998e5649b9ef81e288c369c827e07 +b83a2842f36998890492ab1cd5a088d9423d192681b9a3a90ec518d4c541bce63e6c5f4df0f734f31fbfdd87785a2463 +a21b6a790011396e1569ec5b2a423857b9bec16f543e63af28024e116c1ea24a3b96e8e4c75c6537c3e4611fd265e896 +b4251a9c4aab3a495da7a42e684ba4860dbcf940ad1da4b6d5ec46050cbe8dab0ab9ae6b63b5879de97b905723a41576 +8222f70aebfe6ac037f8543a08498f4cadb3edaac00336fc00437eb09f2cba758f6c38e887cc634b4d5b7112b6334836 +86f05038e060594c46b5d94621a1d9620aa8ba59a6995baf448734e21f58e23c1ea2993d3002ad5250d6edd5ba59b34f +a7c0c749baef811ab31b973c39ceb1d94750e2bc559c90dc5eeb20d8bb6b78586a2b363c599ba2107d6be65cd435f24e +861d46a5d70b38d6c1cd72817a2813803d9f34c00320c8b62f8b9deb67f5b5687bc0b37c16d28fd017367b92e05da9ca +b3365d3dab639bffbe38e35383686a435c8c88b397b717cd4aeced2772ea1053ceb670f811f883f4e02975e5f1c4ac58 +a5750285f61ab8f64cd771f6466e2c0395e01b692fd878f2ef2d5c78bdd8212a73a3b1dfa5e4c8d9e1afda7c84857d3b +835a10809ccf939bc46cf950a33b36d71be418774f51861f1cd98a016ade30f289114a88225a2c11e771b8b346cbe6ef +a4f59473a037077181a0a62f1856ec271028546ca9452b45cedfcb229d0f4d1aabfc13062b07e536cc8a0d4b113156a2 +95cd14802180b224d44a73cc1ed599d6c4ca62ddcaa503513ccdc80aaa8be050cc98bd4b4f3b639549beb4587ac6caf9 +973b731992a3e69996253d7f36dd7a0af1982b5ed21624b77a7965d69e9a377b010d6dabf88a8a97eec2a476259859cc +af8a1655d6f9c78c8eb9a95051aa3baaf9c811adf0ae8c944a8d3fcba87b15f61021f3baf6996fa0aa51c81b3cb69de1 +835aad5c56872d2a2d6c252507b85dd742bf9b8c211ccb6b25b52d15c07245b6d89b2a40f722aeb5083a47cca159c947 +abf4e970b02bef8a102df983e22e97e2541dd3650b46e26be9ee394a3ea8b577019331857241d3d12b41d4eacd29a3ac +a13c32449dbedf158721c13db9539ae076a6ce5aeaf68491e90e6ad4e20e20d1cdcc4a89ed9fd49cb8c0dd50c17633c1 +8c8f78f88b7e22dd7e9150ab1c000f10c28e696e21d85d6469a6fe315254740f32e73d81ab1f3c1cf8f544c86df506e8 +b4b77f2acfe945abf81f2605f906c10b88fb4d28628487fb4feb3a09f17f28e9780445dfcee4878349d4c6387a9d17d4 +8d255c235f3812c6ecc646f855fa3832be5cb4dbb9c9e544989fafdf3f69f05bfd370732eaf954012f0044aa013fc9c6 +b982efd3f34b47df37c910148ac56a84e8116647bea24145a49e34e0a6c0176e3284d838dae6230cb40d0be91c078b85 +983f365aa09bd85df2a6a2ad8e4318996b1e27d02090755391d4486144e40d80b1fbfe1c798d626db92f52e33aa634da +95fd1981271f3ea3a41d654cf497e6696730d9ff7369f26bc4d7d15c7adb4823dd0c42e4a005a810af12d234065e5390 +a9f5219bd4b913c186ef30c02f995a08f0f6f1462614ea5f236964e02bdaa33db9d9b816c4aee5829947840a9a07ba60 +9210e6ceb05c09b46fd09d036287ca33c45124ab86315e5d6911ff89054f1101faaa3e83d123b7805056d388bcec6664 +8ed9cbf69c6ff3a5c62dd9fe0d7264578c0f826a29e614bc2fb4d621d90c8c9992438accdd7a614b1dca5d1bb73dc315 +85cf2a8cca93e00da459e3cecd22c342d697eee13c74d5851634844fc215f60053cf84b0e03c327cb395f48d1c71a8a4 +8818a18e9a2ec90a271b784400c1903089ffb0e0b40bc5abbbe12fbebe0f731f91959d98c5519ef1694543e31e2016d4 +8dabc130f296fa7a82870bf9a8405aaf542b222ed9276bba9bd3c3555a0f473acb97d655ee7280baff766a827a8993f0 +ac7952b84b0dc60c4d858f034093b4d322c35959605a3dad2b806af9813a4680cb038c6d7f4485b4d6b2ff502aaeca25 +ad65cb6d57b48a2602568d2ec8010baed0eb440eec7638c5ec8f02687d764e9de5b5d42ad5582934e592b48471c22d26 +a02ab8bd4c3d114ea23aebdd880952f9495912817da8c0c08eabc4e6755439899d635034413d51134c72a6320f807f1c +8319567764b8295402ec1ebef4c2930a138480b37e6d7d01c8b4c9cd1f2fc3f6e9a44ae6e380a0c469b25b06db23305f +afec53b2301dc0caa8034cd9daef78c48905e6068d692ca23d589b84a6fa9ddc2ed24a39480597e19cb3e83eec213b3f +ac0b4ffdb5ae08e586a9cdb98f9fe56f4712af3a97065e89e274feacfb52b53c839565aee93c4cfaaccfe51432c4fab0 +8972cbf07a738549205b1094c5987818124144bf187bc0a85287c94fdb22ce038c0f11df1aa16ec5992e91b44d1af793 +b7267aa6f9e3de864179b7da30319f1d4cb2a3560f2ea980254775963f1523b44c680f917095879bebfa3dc2b603efcf +80f68f4bfc337952e29504ee5149f15093824ea7ab02507efd1317a670f6cbc3611201848560312e3e52e9d9af72eccf +8897fee93ce8fc1e1122e46b6d640bba309384dbd92e46e185e6364aa8210ebf5f9ee7e5e604b6ffba99aa80a10dd7d0 +b58ea6c02f2360be60595223d692e82ee64874fda41a9f75930f7d28586f89be34b1083e03bbc1575bbfdda2d30db1ea +85a523a33d903280d70ac5938770453a58293480170c84926457ac2df45c10d5ff34322ab130ef4a38c916e70d81af53 +a2cbf045e1bed38937492c1f2f93a5ba41875f1f262291914bc1fc40c60bd0740fb3fea428faf6da38b7c180fe8ac109 +8c09328770ed8eb17afc6ac7ddd87bb476de18ed63cab80027234a605806895959990c47bd10d259d7f3e2ecb50074c9 +b4b9e19edb4a33bde8b7289956568a5b6b6557404e0a34584b5721fe6f564821091013fbb158e2858c6d398293bb4b59 +8a47377df61733a2aa5a0e945fce00267f8e950f37e109d4487d92d878fb8b573317bb382d902de515b544e9e233458d +b5804c9d97efeff5ca94f3689b8088c62422d92a1506fd1d8d3b1b30e8a866ad0d6dad4abfa051dfc4471250cac4c5d9 +9084a6ee8ec22d4881e9dcc8a9eb3c2513523d8bc141942370fd191ad2601bf9537a0b1e84316f3209b3d8a54368051e +85447eea2fa26656a649f8519fa67279183044791d61cf8563d0783d46d747d96af31d0a93507bbb2242666aa87d3720 +97566a84481027b60116c751aec552adfff2d9038e68d48c4db9811fb0cbfdb3f1d91fc176a0b0d988a765f8a020bce1 +ae87e5c1b9e86c49a23dceda4ecfd1dcf08567f1db8e5b6ec752ebd45433c11e7da4988573cdaebbb6f4135814fc059e +abee05cf9abdbc52897ac1ce9ed157f5466ed6c383d6497de28616238d60409e5e92619e528af8b62cc552bf09970dc2 +ae6d31cd7bf9599e5ee0828bab00ceb4856d829bba967278a73706b5f388465367aa8a6c7da24b5e5f1fdd3256ef8e63 +ac33e7b1ee47e1ee4af472e37ab9e9175260e506a4e5ce449788075da1b53c44cb035f3792d1eea2aa24b1f688cc6ed3 +80f65b205666b0e089bb62152251c48c380a831e5f277f11f3ef4f0d52533f0851c1b612267042802f019ec900dc0e8f +858520ad7aa1c9fed738e3b583c84168f2927837ad0e1d326afe9935c26e9b473d7f8c382e82ef1fe37d2b39bb40a1ee +b842dd4af8befe00a97c2d0f0c33c93974761e2cb9e5ab8331b25170318ddd5e4bdbc02d8f90cbfdd5f348f4f371c1f7 +8bf2cb79bc783cb57088aae7363320cbeaabd078ffdec9d41bc74ff49e0043d0dad0086a30e5112b689fd2f5a606365d +982eb03bbe563e8850847cd37e6a3306d298ab08c4d63ab6334e6b8c1fa13fce80cf2693b09714c7621d74261a0ff306 +b143edb113dec9f1e5105d4a93fbe502b859e587640d3db2f628c09a17060e6aec9e900e2c8c411cda99bc301ff96625 +af472d9befa750dcebc5428fe1a024f18ec1c07bca0f95643ce6b5f4189892a910285afb03fd7ed7068fbe614e80d33c +a97e3bc57ede73ecd1bbf02de8f51b4e7c1a067da68a3cd719f4ba26a0156cbf1cef2169fd35a18c5a4cced50d475998 +a862253c937cf3d75d7183e5f5be6a4385d526aeda5171c1c60a8381fea79f88f5f52a4fab244ecc70765d5765e6dfd5 +90cb776f8e5a108f1719df4a355bebb04bf023349356382cae55991b31720f0fd03206b895fa10c56c98f52453be8778 +a7614e8d0769dccd520ea4b46f7646e12489951efaef5176bc889e9eb65f6e31758df136b5bf1e9107e68472fa9b46ec +ac3a9b80a3254c42e5ed3a090a0dd7aee2352f480de96ad187027a3bb6c791eddfc3074b6ffd74eea825188f107cda4d +82a01d0168238ef04180d4b6e0a0e39024c02c2d75b065017c2928039e154d093e1af4503f4d1f3d8a948917abb5d09f +8fab000a2b0eef851a483aec8d2dd85fe60504794411a2f73ed82e116960547ac58766cb73df71aea71079302630258d +872451a35c6db61c63e9b8bb9f16b217f985c20be4451c14282c814adb29d7fb13f201367c664435c7f1d4d9375d7a58 +887d9ff54cc96b35d562df4a537ff972d7c4b3fd91ab06354969a4cfede0b9fc68bbffb61d0dbf1a58948dc701e54f5a +8cb5c2a6bd956875d88f41ae24574434f1308514d44057b55c9c70f13a3366ed054150eed0955a38fda3f757be73d55f +89ad0163cad93e24129d63f8e38422b7674632a8d0a9016ee8636184cab177659a676c4ee7efba3abe1a68807c656d60 +b9ec01c7cab6d00359b5a0b4a1573467d09476e05ca51a9227cd16b589a9943d161eef62dcc73f0de2ec504d81f4d252 +8031d17635d39dfe9705c485d2c94830b6fc9bc67b91300d9d2591b51e36a782e77ab5904662effa9382d9cca201f525 +8be5a5f6bc8d680e5092d6f9a6585acbaaaa2ddc671da560dcf5cfa4472f4f184b9597b5b539438accd40dda885687cc +b1fc0f052fae038a2e3de3b3a96b0a1024b009de8457b8b3adb2d315ae68a89af905720108a30038e5ab8d0d97087785 +8b8bdc77bd3a6bc7ca5492b6f8c614852c39a70d6c8a74916eaca0aeb4533b11898b8820a4c2620a97bf35e275480029 +af35f4dc538d4ad5cdf710caa38fd1eb496c3fa890a047b6a659619c5ad3054158371d1e88e0894428282eed9f47f76b +8166454a7089cc07758ad78724654f4e7a1a13e305bbf88ddb86f1a4b2904c4fc8ab872d7da364cdd6a6c0365239e2ad +ab287c7d3addce74ce40491871c768abe01daaa0833481276ff2e56926b38a7c6d2681ffe837d2cc323045ad1a4414f9 +b90317f4505793094d89365beb35537f55a6b5618904236258dd04ca61f21476837624a2f45fef8168acf732cab65579 +98ae5ea27448e236b6657ab5ef7b1cccb5372f92ab25f5fa651fbac97d08353a1dae1b280b1cd42b17d2c6a70a63ab9d +adcf54e752d32cbaa6cb98fbca48d8cd087b1db1d131d465705a0d8042c8393c8f4d26b59006eb50129b21e6240f0c06 +b591a3e4db18a7345fa935a8dd7994bbac5cc270b8ebd84c8304c44484c7a74afb45471fdbe4ab22156a30fae1149b40 +806b53ac049a42f1dcc1d6335505371da0bf27c614f441b03bbf2e356be7b2fb4eed7117eabcce9e427a542eaa2bf7d8 +800482e7a772d49210b81c4a907f5ce97f270b959e745621ee293cf8c71e8989363d61f66a98f2d16914439544ca84c7 +99de9eafdad3617445312341644f2bb888680ff01ce95ca9276b1d2e5ef83fa02dab5e948ebf66c17df0752f1bd37b70 +961ee30810aa4c93ae157fbe9009b8e443c082192bd36a73a6764ff9b2ad8b0948fe9a73344556e01399dd77badb4257 +ae0a361067c52efbe56c8adf982c00432cd478929459fc7f74052c8ee9531cd031fe1335418fde53f7c2ef34254eb7ac +a3503d16b6b27eb20c1b177bcf90d13706169220523a6271b85b2ce35a9a2b9c5bed088540031c0a4ebfdae3a4c6ab04 +909420122c3e723289ca4e7b81c2df5aff312972a2203f4c45821b176e7c862bf9cac7f7df3adf1d59278f02694d06e7 +989f42380ae904b982f85d0c6186c1aef5d6bcba29bcfbb658e811b587eb2749c65c6e4a8cc6409c229a107499a4f5d7 +8037a6337195c8e26a27ea4ef218c6e7d79a9720aaab43932d343192abc2320fe72955f5e431c109093bda074103330a +b312e168663842099b88445e940249cc508f080ab0c94331f672e7760258dbd86be5267e4cf25ea25facb80bff82a7e9 +aaa3ff8639496864fcdbfdda1ac97edc4f08e3c9288b768f6c8073038c9fbbf7e1c4bea169b4d45c31935cdf0680d45e +97dbd3df37f0b481a311dfc5f40e59227720f367912200d71908ef6650f32cc985cb05b981e3eea38958f7e48d10a15d +a89d49d1e267bb452d6cb621b9a90826fe55e9b489c0427b94442d02a16f390eed758e209991687f73f6b5a032321f42 +9530dea4e0e19d6496f536f2e75cf7d814d65fde567055eb20db48fd8d20d501cd2a22fb506db566b94c9ee10f413d43 +81a7009b9e67f1965fa7da6a57591c307de91bf0cd35ab4348dc4a98a4961e096d004d7e7ad318000011dc4342c1b809 +83440a9402b766045d7aca61a58bba2aa29cac1cf718199e472ba086f5d48093d9dda4d135292ba51d049a23964eceae +a06c9ce5e802df14f6b064a3d1a0735d429b452f0e2e276042800b0a4f16df988fd94cf3945921d5dd3802ab2636f867 +b1359e358b89936dee9e678a187aad3e9ab14ac40e96a0a68f70ee2583cdcf467ae03bef4215e92893f4e12f902adec8 +835304f8619188b4d14674d803103d5a3fa594d48e96d9699e653115dd05fdc2dda6ba3641cf7ad53994d448da155f02 +8327cba5a9ff0d3f5cd0ae55e77167448926d5fcf76550c0ad978092a14122723090c51c415e88e42a2b62eb07cc3981 +b373dcdaea85f85ce9978b1426a7ef4945f65f2d3467a9f1cc551a99766aac95df4a09e2251d3f89ca8c9d1a7cfd7b0e +ab1422dc41af2a227b973a6fd124dfcb2367e2a11a21faa1d381d404f51b7257e5bc82e9cf20cd7fe37d7ae761a2ab37 +a93774a03519d2f20fdf2ef46547b0a5b77c137d6a3434b48d56a2cbef9e77120d1b85d0092cf8842909213826699477 +8eb967a495a38130ea28711580b7e61bcd1d051cd9e4f2dbf62f1380bd86e0d60e978d72f6f31e909eb97b3b9a2b867c +ae8213378da1287ba1fe4242e1acaec19b877b6fe872400013c6eac1084b8d03156792fa3020201725b08228a1e80f49 +b143daf6893d674d607772b3b02d8ac48f294237e2f2c87963c0d4e26d9227d94a2a13512457c3d5883544bbc259f0ef +b343bd2aca8973888e42542218924e2dda2e938fd1150d06878af76f777546213912b7c7a34a0f94186817d80ffa185c +b188ebc6a8c3007001aa347ae72cc0b15d09bc6c19a80e386ee4b334734ec0cc2fe8b493c2422f38d1e6d133cc3db6fe +b795f6a8b9b826aaeee18ccd6baf6c5adeeec85f95eb5b6d19450085ec7217e95a2d9e221d77f583b297d0872073ba0e +b1c7dbd998ad32ae57bfa95deafa147024afd57389e98992c36b6e52df915d3d5a39db585141ec2423173e85d212fed8 +812bcdeb9fe5f12d0e1df9964798056e1f1c3de3b17b6bd2919b6356c4b86d8e763c01933efbe0224c86a96d5198a4be +b19ebeda61c23d255cbf472ef0b8a441f4c55b70f0d8ed47078c248b1d3c7c62e076b43b95c00a958ec8b16d5a7cb0d7 +b02adc9aaa20e0368a989c2af14ff48b67233d28ebee44ff3418bb0473592e6b681af1cc45450bd4b175df9051df63d9 +8d87f0714acee522eb58cec00360e762adc411901dba46adc9227124fa70ee679f9a47e91a6306d6030dd4eb8de2f3c1 +8be54cec21e74bcc71de29dc621444263737db15f16d0bb13670f64e42f818154e04b484593d19ef95f2ee17e4b3fe21 +ab8e20546c1db38d31493b5d5f535758afb17e459645c1b70813b1cf7d242fd5d1f4354a7c929e8f7259f6a25302e351 +89f035a1ed8a1e302ac893349ba8ddf967580fcb6e73d44af09e3929cde445e97ff60c87dafe489e2c0ab9c9986cfa00 +8b2b0851a795c19191a692af55f7e72ad2474efdc5401bc3733cfdd910e34c918aaebe69d5ea951bdddf3c01cabbfc67 +a4edb52c2b51495ccd1ee6450fc14b7b3ede8b3d106808929d02fb31475bacb403e112ba9c818d2857651e508b3a7dd1 +9569341fded45d19f00bcf3cbf3f20eb2b4d82ef92aba3c8abd95866398438a2387437e580d8b646f17cf6fde8c5af23 +aa4b671c6d20f72f2f18a939a6ff21cc37e0084b44b4a717f1be859a80b39fb1be026b3205adec2a66a608ec2bcd578f +94902e980de23c4de394ad8aec91b46f888d18f045753541492bfbb92c59d3daa8de37ae755a6853744af8472ba7b72b +af651ef1b2a0d30a7884557edfad95b6b5d445a7561caebdc46a485aedd25932c62c0798465c340a76f6feaa196dd712 +b7b669b8e5a763452128846dd46b530dca4893ace5cc5881c7ddcd3d45969d7e73fbebdb0e78aa81686e5f7b22ec5759 +82507fd4ebe9fa656a7f2e084d64a1fa6777a2b0bc106d686e2d9d2edafc58997e58cb6bfd0453b2bf415704aa82ae62 +b40bce2b42b88678400ecd52955bbdadd15f8b9e1b3751a1a3375dc0efb5ca3ee258cf201e1140b3c09ad41217d1d49e +b0210d0cbb3fbf3b8cdb39e862f036b0ff941cd838e7aaf3a8354e24246e64778d22f3de34572e6b2a580614fb6425be +876693cba4301b251523c7d034108831df3ce133d8be5a514e7a2ca494c268ca0556fa2ad8310a1d92a16b55bcd99ea9 +8660281406d22a4950f5ef050bf71dd3090edb16eff27fa29ef600cdea628315e2054211ed2cc6eaf8f2a1771ef689fd +a610e7e41e41ab66955b809ba4ade0330b8e9057d8efc9144753caed81995edeb1a42a53f93ce93540feca1fae708dac +a49e2c176a350251daef1218efaccc07a1e06203386ede59c136699d25ca5cb2ac1b800c25b28dd05678f14e78e51891 +83e0915aa2b09359604566080d411874af8c993beba97d4547782fdbe1a68e59324b800ff1f07b8db30c71adcbd102a8 +a19e84e3541fb6498e9bb8a099c495cbfcad113330e0262a7e4c6544495bb8a754b2208d0c2d895c93463558013a5a32 +87f2bd49859a364912023aca7b19a592c60214b8d6239e2be887ae80b69ebdeb59742bdebcfa73a586ab23b2c945586c +b8e8fdddae934a14b57bc274b8dcd0d45ebb95ddbaabef4454e0f6ce7d3a5a61c86181929546b3d60c447a15134d08e1 +87e0c31dcb736ea4604727e92dc1d9a3cf00adcff79df3546e02108355260f3dd171531c3c0f57be78d8b28058fcc8c0 +9617d74e8f808a4165a8ac2e30878c349e1c3d40972006f0787b31ea62d248c2d9f3fc3da83181c6e57e95feedfd0e8c +8949e2cee582a2f8db86e89785a6e46bc1565c2d8627d5b6bf43ba71ffadfab7e3c5710f88dcb5fb2fc6edf6f4fae216 +ad3fa7b0edceb83118972a2935a09f409d09a8db3869f30be3a76f67aa9fb379cabb3a3aff805ba023a331cad7d7eb64 +8c95718a4112512c4efbd496be38bf3ca6cdcaad8a0d128f32a3f9aae57f3a57bdf295a3b372a8c549fda8f4707cffed +88f3261d1e28a58b2dee3fcc799777ad1c0eb68b3560f9b4410d134672d9533532a91ea7be28a041784872632d3c9d80 +b47472a41d72dd2e8b72f5c4f8ad626737dde3717f63d6bc776639ab299e564cbad0a2ad5452a07f02ff49a359c437e5 +9896d21dc2e8aad87b76d6df1654f10cd7bceed4884159d50a818bea391f8e473e01e14684814c7780235f28e69dca6e +82d47c332bbd31bbe83b5eb44a23da76d4a7a06c45d7f80f395035822bc27f62f59281d5174e6f8e77cc9b5c3193d6f0 +95c74cd46206e7f70c9766117c34c0ec45c2b0f927a15ea167901a160e1530d8522943c29b61e03568aa0f9c55926c53 +a89d7757825ae73a6e81829ff788ea7b3d7409857b378ebccd7df73fdbe62c8d9073741cf038314971b39af6c29c9030 +8c1cd212d0b010905d560688cfc036ae6535bc334fa8b812519d810b7e7dcf1bb7c5f43deaa40f097158358987324a7f +b86993c383c015ed8d847c6b795164114dd3e9efd25143f509da318bfba89389ea72a420699e339423afd68b6512fafb +8d06bd379c6d87c6ed841d8c6e9d2d0de21653a073725ff74be1934301cc3a79b81ef6dd0aad4e7a9dc6eac9b73019bc +81af4d2d87219985b9b1202d724fe39ef988f14fef07dfe3c3b11714e90ffba2a97250838e8535eb63f107abfe645e96 +8c5e0af6330a8becb787e4b502f34f528ef5756e298a77dc0c7467433454347f3a2e0bd2641fbc2a45b95e231c6e1c02 +8e2a8f0f04562820dc8e7da681d5cad9fe2e85dd11c785fb6fba6786c57a857e0b3bd838fb849b0376c34ce1665e4837 +a39be8269449bfdfc61b1f62077033649f18dae9bef7c6163b9314ca8923691fb832f42776f0160b9e8abd4d143aa4e1 +8c154e665706355e1cc98e0a4cabf294ab019545ba9c4c399d666e6ec5c869ca9e1faf8fb06cd9c0a5c2f51a7d51b70a +a046a7d4de879d3ebd4284f08f24398e9e3bf006cd4e25b5c67273ade248689c69affff92ae810c07941e4904296a563 +afd94c1cb48758e5917804df03fb38a6da0e48cd9b6262413ea13b26973f9e266690a1b7d9d24bbaf7e82718e0e594b0 +859e21080310c8d6a38e12e2ac9f90a156578cdeb4bb2e324700e97d9a5511cd6045dc39d1d0de3f94aeed043a24119d +a219fb0303c379d0ab50893264919f598e753aac9065e1f23ef2949abc992577ab43c636a1d2c089203ec9ddb941e27d +b0fdb639d449588a2ca730afcba59334e7c387342d56defdfb7ef79c493f7fd0e5277eff18e7203e756c7bdda5803047 +87f9c3b7ed01f54368aca6dbcf2f6e06bff96e183c4b2c65f8baa23b377988863a0a125d5cdd41a072da8462ced4c070 +99ef7a5d5ac2f1c567160e1f8c95f2f38d41881850f30c461a205f7b1b9fb181277311333839b13fb3ae203447e17727 +aeaca9b1c2afd24e443326cc68de67b4d9cedb22ad7b501a799d30d39c85bb2ea910d4672673e39e154d699e12d9b3dc +a11675a1721a4ba24dd3d0e4c3c33a6edf4cd1b9f6b471070b4386c61f77452266eae6e3f566a40cfc885eada9a29f23 +b228334445e37b9b49cb4f2cc56b454575e92173ddb01370a553bba665adadd52df353ad74470d512561c2c3473c7bb9 +a18177087c996572d76f81178d18ed1ceebc8362a396348ce289f1d8bd708b9e99539be6fccd4acb1112381cfc5749b4 +8e7b8bf460f0d3c99abb19803b9e43422e91507a1c0c22b29ee8b2c52d1a384da4b87c292e28eff040db5be7b1f8641f +b03d038d813e29688b6e6f444eb56fec3abba64c3d6f890a6bcf2e916507091cdb2b9d2c7484617be6b26552ed1c56cb +a1c88ccd30e934adfc5494b72655f8afe1865a84196abfb376968f22ddc07761210b6a9fb7638f1413d1b4073d430290 +961b714faebf172ad2dbc11902461e286e4f24a99a939152a53406117767682a571057044decbeb3d3feef81f4488497 +a03dc4059b46effdd786a0a03cc17cfee8585683faa35bb07936ded3fa3f3a097f518c0b8e2db92fd700149db1937789 +adf60180c99ca574191cbcc23e8d025b2f931f98ca7dfcebfc380226239b6329347100fcb8b0fcb12db108c6ad101c07 +805d4f5ef24d46911cbf942f62cb84b0346e5e712284f82b0db223db26d51aabf43204755eb19519b00e665c7719fcaa +8dea7243e9c139662a7fe3526c6c601eee72fd8847c54c8e1f2ad93ef7f9e1826b170afe58817dac212427164a88e87f +a2ba42356606d651b077983de1ad643650997bb2babb188c9a3b27245bb65d2036e46667c37d4ce02cb1be5ae8547abe +af2ae50b392bdc013db2d12ce2544883472d72424fc767d3f5cb0ca2d973fc7d1f425880101e61970e1a988d0670c81b +98e6bec0568d3939b31d00eb1040e9b8b2a35db46ddf4369bdaee41bbb63cc84423d29ee510a170fb5b0e2df434ba589 +822ff3cd12fbef4f508f3ca813c04a2e0b9b799c99848e5ad3563265979e753ee61a48f6adc2984a850f1b46c1a43d35 +891e8b8b92a394f36653d55725ef514bd2e2a46840a0a2975c76c2a935577f85289026aaa74384da0afe26775cbddfb9 +b2a3131a5d2fe7c8967047aa66e4524babae941d90552171cc109527f345f42aa0df06dcbb2fa01b33d0043917bbed69 +80c869469900431f3eeefafdbe07b8afd8cee7739e659e6d0109b397cacff85a88247698f87dc4e2fe39a592f250ac64 +9091594f488b38f9d2bb5df49fd8b4f8829d9c2f11a197dd1431ed5abbc5c954bbde3387088f9ee3a5a834beb7619bce +b472e241e6956146cca57b97a8a204668d050423b4e76f857bad5b47f43b203a04c8391ba9d9c3e95093c071f9d376a1 +b7dd2de0284844392f7dfb56fe7ca3ede41e27519753ffc579a0a8d2d65ceb8108d06b6b0d4c3c1a2588951297bd1a1e +902116ce70d0a079ac190321c1f48701318c05f8e69ee09694754885d33a835a849cafe56f499a2f49f6cda413ddf9a7 +b18105cc736787fafaf7c3c11c448bce9466e683159dff52723b7951dff429565e466e4841d982e3aaa9ee2066838666 +97ab9911f3f659691762d568ae0b7faa1047b0aed1009c319fa79d15d0db8db9f808fc385dc9a68fa388c10224985379 +b2a2cba65f5b927e64d2904ba412e2bac1cf18c9c3eda9c72fb70262497ecf505b640827e2afebecf10eebbcf48ccd3e +b36a3fd677baa0d3ef0dac4f1548ff50a1730286b8c99d276a0a45d576e17b39b3cbadd2fe55e003796d370d4be43ce3 +a5dfec96ca3c272566e89dc453a458909247e3895d3e44831528130bc47cc9d0a0dac78dd3cad680a4351d399d241967 +8029382113909af6340959c3e61db27392531d62d90f92370a432aec3eb1e4c36ae1d4ef2ba8ec6edb4d7320c7a453f6 +971d85121ea108e6769d54f9c51299b0381ece8b51d46d49c89f65bedc123bab4d5a8bc14d6f67f4f680077529cbae4c +98ff6afc01d0bec80a278f25912e1b1ebff80117adae72e31d5b9fa4d9624db4ba2065b444df49b489b0607c45e26c4c +8fa29be10fb3ab30ce25920fec0187e6e91e458947009dabb869aade7136c8ba23602682b71e390c251f3743164cbdaa +b3345c89eb1653418fe3940cf3e56a9a9c66526389b98f45ca02dd62bfb37baa69a4baaa7132d7320695f8ea6ad1fd94 +b72c7f5541c9ac6b60a7ec9f5415e7fb14da03f7164ea529952a29399f3a071576608dbbcc0d45994f21f92ddbeb1e19 +aa3450bb155a5f9043d0ef95f546a2e6ade167280bfb75c9f09c6f9cdb1fffb7ce8181436161a538433afa3681c7a141 +92a18fecaded7854b349f441e7102b638ababa75b1b0281dd0bded6541abe7aa37d96693595be0b01fe0a2e2133d50f9 +980756ddf9d2253cfe6c94960b516c94889d09e612810935150892627d2ecee9a2517e04968eea295d0106850c04ca44 +ae68c6ccc454318cdd92f32b11d89116a3b8350207a36d22a0f626718cad671d960090e054c0c77ac3162ae180ecfd4b +99f31f66eaaa551749ad91d48a0d4e3ff4d82ef0e8b28f3184c54e852422ba1bdafd53b1e753f3a070f3b55f3c23b6a2 +a44eaeaa6589206069e9c0a45ff9fc51c68da38d4edff1d15529b7932e6f403d12b9387019c44a1488a5d5f27782a51f +b80b5d54d4b344840e45b79e621bd77a3f83fb4ce6d8796b7d6915107b3f3c34d2e7d95bdafd120f285669e5acf2437a +b36c069ec085a612b5908314d6b84c00a83031780261d1c77a0384c406867c9847d5b0845deddfa512cc04a8df2046fb +b09dbe501583220f640d201acea7ee3e39bf9eda8b91aa07b5c50b7641d86d71acb619b38d27835ce97c3759787f08e9 +87403d46a2bf63170fff0b857acacf42ee801afe9ccba8e5b4aea967b68eac73a499a65ca46906c2eb4c8f27bc739faa +82b93669f42a0a2aa5e250ffe6097269da06a9c02fcd1801abbad415a7729a64f830754bafc702e64600ba47671c2208 +8e3a3029be7edb8dd3ab1f8216664c8dc50d395f603736061d802cef77627db7b859ef287ed850382c13b4d22d6a2d80 +968e9ec7194ff424409d182ce0259acd950c384c163c04463bc8700a40b79beba6146d22b7fa7016875a249b7b31c602 +8b42c984bbe4996e0c20862059167c6bdc5164b1ffcd928f29512664459212d263e89f0f0e30eed4e672ffa5ed0b01b5 +96bac54062110dada905363211133f1f15dc7e4fd80a4c6e4a83bc9a0bcbbaba11cd2c7a13debcf0985e1a954c1da66b +a16dc8a653d67a7cd7ae90b2fffac0bf1ca587005430fe5ba9403edd70ca33e38ba5661d2ed6e9d2864400d997626a62 +a68ab11a570a27853c8d67e491591dcba746bfbee08a2e75ae0790399130d027ed387f41ef1d7de8df38b472df309161 +92532b74886874447c0300d07eda9bbe4b41ed25349a3da2e072a93fe32c89d280f740d8ff70d5816793d7f2b97373cc +88e35711b471e89218fd5f4d0eadea8a29405af1cd81974427bc4a5fb26ed60798daaf94f726c96e779b403a2cd82820 +b5c72aa4147c19f8c4f3a0a62d32315b0f4606e0a7025edc5445571eaf4daff64f4b7a585464821574dd50dbe1b49d08 +9305d9b4095258e79744338683fd93f9e657367b3ab32d78080e51d54eec331edbc224fad5093ebf8ee4bd4286757eb8 +b2a17abb3f6a05bcb14dc7b98321fa8b46d299626c73d7c6eb12140bf4c3f8e1795250870947af817834f033c88a59d6 +b3477004837dbd8ba594e4296f960fc91ab3f13551458445e6c232eb04b326da803c4d93e2e8dcd268b4413305ff84da +924b4b2ebaafdcfdfedb2829a8bf46cd32e1407d8d725a5bd28bdc821f1bafb3614f030ea4352c671076a63494275a3f +8b81b9ef6125c82a9bece6fdcb9888a767ac16e70527753428cc87c56a1236e437da8be4f7ecfe57b9296dc3ae7ba807 +906e19ec8b8edd58bdf9ae05610a86e4ea2282b1bbc1e8b00b7021d093194e0837d74cf27ac9916bdb8ec308b00da3da +b41c5185869071760ac786078a57a2ab4e2af60a890037ac0c0c28d6826f15c2cf028fddd42a9b6de632c3d550bfbc14 +a646e5dec1b713ae9dfdf7bdc6cd474d5731a320403c7dfcfd666ffc9ae0cff4b5a79530e8df3f4aa9cb80568cb138e9 +b0efad22827e562bd3c3e925acbd0d9425d19057868608d78c2209a531cccd0f2c43dc5673acf9822247428ffa2bb821 +a94c19468d14b6f99002fc52ac06bbe59e5c472e4a0cdb225144a62f8870b3f10593749df7a2de0bd3c9476ce682e148 +803864a91162f0273d49271dafaab632d93d494d1af935aefa522768af058fce52165018512e8d6774976d52bd797e22 +a08711c2f7d45c68fb340ac23597332e1bcaec9198f72967b9921204b9d48a7843561ff318f87908c05a44fc35e3cc9d +91c3cad94a11a3197ae4f9461faab91a669e0dddb0371d3cab3ed9aeb1267badc797d8375181130e461eadd05099b2a2 +81bdaaf48aae4f7b480fc13f1e7f4dd3023a41439ba231760409ce9292c11128ab2b0bdbbf28b98af4f97b3551f363af +8d60f9df9fd303f625af90e8272c4ecb95bb94e6efc5da17b8ab663ee3b3f673e9f6420d890ccc94acf4d2cae7a860d8 +a7b75901520c06e9495ab983f70b61483504c7ff2a0980c51115d11e0744683ce022d76e3e09f4e99e698cbd21432a0d +82956072df0586562fda7e7738226f694e1c73518dd86e0799d2e820d7f79233667192c9236dcb27637e4c65ef19d493 +a586beb9b6ffd06ad200957490803a7cd8c9bf76e782734e0f55e04a3dc38949de75dc607822ec405736c576cf83bca3 +a179a30d00def9b34a7e85607a447eea0401e32ab5abeee1a281f2acd1cf6ec81a178020666f641d9492b1bdf66f05a3 +83e129705c538787ed8e0fdc1275e6466a3f4ee21a1e6abedd239393b1df72244723b92f9d9d9339a0cab6ebf28f5a16 +811bd8d1e3722b64cd2f5b431167e7f91456e8bba2cc669d3fbbce7d553e29c3c19f629fcedd2498bc26d33a24891d17 +a243c030c858f1f60cccd26b45b024698cc6d9d9e6198c1ed4964a235d9f8d0baf9cde10c8e63dfaa47f8e74e51a6e85 +ab839eb82e23ca52663281f863b55b0a3d6d4425c33ffb4eeb1d7979488ab068bf99e2a60e82cea4dc42c56c26cbfebe +8b896f9bb21d49343e67aec6ad175b58c0c81a3ca73d44d113ae4354a0065d98eb1a5cafedaf232a2bb9cdc62152f309 +af6230340cc0b66f5bf845540ed4fc3e7d6077f361d60762e488d57834c3e7eb7eacc1b0ed73a7d134f174a01410e50c +88975e1b1af678d1b5179f72300a30900736af580dd748fd9461ef7afccc91ccd9bed33f9da55c8711a7635b800e831f +a97486bb9047391661718a54b8dd5a5e363964e495eae6c692730264478c927cf3e66dd3602413189a3699fbeae26e15 +a5973c161ab38732885d1d2785fd74bf156ba34881980cba27fe239caef06b24a533ffe6dbbbeca5e6566682cc00300a +a24776e9a840afda0003fa73b415d5bd6ecd9b5c2cc842b643ee51b8c6087f4eead4d0bfbd987eb174c489a7b952ff2a +a8a6ee06e3af053b705a12b59777267c546f33ba8a0f49493af8e6df4e15cf8dd2d4fb4daf7e84c6b5d3a7363118ff03 +a28e59ce6ad02c2ce725067c0123117e12ac5a52c8f5af13eec75f4a9efc4f696777db18a374fa33bcae82e0734ebd16 +86dfc3b78e841c708aff677baa8ee654c808e5d257158715097c1025d46ece94993efe12c9d188252ad98a1e0e331fec +a88d0275510f242eab11fdb0410ff6e1b9d7a3cbd3658333539815f1b450a84816e6613d15aa8a8eb15d87cdad4b27a2 +8440acea2931118a5b481268ff9f180ee4ede85d14a52c026adc882410825b8275caa44aff0b50c2b88d39f21b1a0696 +a7c3182eab25bd6785bacf12079d0afb0a9b165d6ed327814e2177148539f249eb9b5b2554538f54f3c882d37c0a8abe +85291fbe10538d7da38efdd55a7acebf03b1848428a2f664c3ce55367aece60039f4f320b1771c9c89a35941797f717c +a2c6414eeb1234728ab0de94aa98fc06433a58efa646ca3fcbd97dbfb8d98ae59f7ce6d528f669c8149e1e13266f69c9 +840c8462785591ee93aee2538d9f1ec44ba2ca61a569ab51d335ac873f5d48099ae8d7a7efa0725d9ff8f9475bfa4f56 +a7065a9d02fb3673acf7702a488fbc01aa69580964932f6f40b6c2d1c386b19e50b0e104fcac24ea26c4e723611d0238 +b72db6d141267438279e032c95e6106c2ccb3164b842ba857a2018f3a35f4b040da92680881eb17cd61d0920d5b8f006 +a8005d6c5960e090374747307ef0be2871a7a43fa4e76a16c35d2baab808e9777b496e9f57a4218b23390887c33a0b55 +8e152cea1e00a451ca47c20a1e8875873419700af15a5f38ee2268d3fbc974d4bd5f4be38008fa6f404dbdedd6e6e710 +a3391aed1fcd68761f06a7d1008ec62a09b1cb3d0203cd04e300a0c91adfed1812d8bc1e4a3fd7976dc0aae0e99f52f1 +967eb57bf2aa503ee0c6e67438098149eac305089c155f1762cf5e84e31f0fbf27c34a9af05621e34645c1ec96afaec8 +88af97ddc4937a95ec0dcd25e4173127260f91c8db2f6eac84afb789b363705fb3196235af631c70cafd09411d233589 +a32df75b3f2c921b8767638fd289bcfc61e08597170186637a7128ffedd52c798c434485ac2c7de07014f9e895c2c3d8 +b0a783832153650aa0d766a3a73ec208b6ce5caeb40b87177ffc035ab03c7705ecdd1090b6456a29f5fb7e90e2fa8930 +b59c8e803b4c3486777d15fc2311b97f9ded1602fa570c7b0200bada36a49ee9ef4d4c1474265af8e1c38a93eb66b18b +982f2c85f83e852022998ff91bafbb6ff093ef22cf9d5063e083a48b29175ccbd51b9c6557151409e439096300981a6c +939e3b5989fefebb9d272a954659a4eb125b98c9da6953f5e628d26266bd0525ec38304b8d56f08d65abc4d6da4a8dbb +8898212fe05bc8de7d18503cb84a1c1337cc2c09d1eeef2b475aa79185b7322bf1f8e065f1bf871c0c927dd19faf1f6d +94b0393a41cd00f724aee2d4bc72103d626a5aecb4b5486dd1ef8ac27528398edf56df9db5c3d238d8579af368afeb09 +96ac564450d998e7445dd2ea8e3fc7974d575508fa19e1c60c308d83b645864c029f2f6b7396d4ff4c1b24e92e3bac37 +8adf6638e18aff3eb3b47617da696eb6c4bdfbecbbc3c45d3d0ab0b12cbad00e462fdfbe0c35780d21aa973fc150285e +b53f94612f818571b5565bbb295e74bada9b5f9794b3b91125915e44d6ddcc4da25510eab718e251a09c99534d6042d9 +8b96462508d77ee083c376cd90807aebad8de96bca43983c84a4a6f196d5faf6619a2351f43bfeec101864c3bf255519 +aeadf34657083fc71df33bd44af73bf5281c9ca6d906b9c745536e1819ea90b56107c55e2178ebad08f3ba75b3f81c86 +9784ba29b2f0057b5af1d3ab2796d439b8753f1f749c73e791037461bdfc3f7097394283105b8ab01788ea5255a96710 +8756241bda159d4a33bf74faba0d4594d963c370fb6a18431f279b4a865b070b0547a6d1613cf45b8cfb5f9236bbf831 +b03ebfd6b71421dfd49a30460f9f57063eebfe31b9ceaa2a05c37c61522b35bdc09d7db3ad75c76c253c00ba282d3cd2 +b34e7e6341fa9d854b2d3153bdda0c4ae2b2f442ab7af6f99a0975d45725aa48e36ae5f7011edd249862e91f499687d4 +b462ee09dc3963a14354244313e3444de5cc37ea5ccfbf14cd9aca8027b59c4cb2a949bc30474497cab8123e768460e6 +aea753290e51e2f6a21a9a0ee67d3a2713f95c2a5c17fe41116c87d3aa77b1683761264d704df1ac34f8b873bc88ef7b +98430592afd414394f98ddfff9f280fcb1c322dbe3510f45e1e9c4bb8ee306b3e0cf0282c0ee73ebb8ba087d4d9e0858 +b95d3b5aaf54ffca11f4be8d57f76e14afdb20afc859dc7c7471e0b42031e8f3d461b726ecb979bdb2f353498dfe95ea +984d17f9b11a683132e0b5a9ee5945e3ff7054c2d5c716be73b29078db1d36f54c6e652fd2f52a19da313112e97ade07 +ab232f756b3fff3262be418a1af61a7e0c95ceebbc775389622a8e10610508cd6784ab7960441917a83cc191c58829ea +a28f41678d6e60de76b0e36ab10e4516e53e02e9c77d2b5af3cfeee3ce94cfa30c5797bd1daab20c98e1cad83ad0f633 +b55395fca84dd3ccc05dd480cb9b430bf8631ff06e24cb51d54519703d667268c2f8afcde4ba4ed16bece8cc7bc8c6e0 +8a8a5392a0e2ea3c7a8c51328fab11156004e84a9c63483b64e8f8ebf18a58b6ffa8fe8b9d95af0a2f655f601d096396 +ab480000fe194d23f08a7a9ec1c392334e9c687e06851f083845121ce502c06b54dda8c43092bcc1035df45cc752fe9b +b265644c29f628d1c7e8e25a5e845cabb21799371814730a41a363e1bda8a7be50fee7c3996a365b7fcba4642add10db +b8a915a3c685c2d4728f6931c4d29487cad764c5ce23c25e64b1a3259ac27235e41b23bfe7ae982921b4cb84463097df +8efa7338442a4b6318145a5440fc213b97869647eeae41b9aa3c0a27ee51285b73e3ae3b4a9423df255e6add58864aa9 +9106d65444f74d217f4187dfc8fcf3810b916d1e4275f94f6a86d1c4f3565b131fd6cde1fa708bc05fe183c49f14941a +948252dac8026bbbdb0a06b3c9d66ec4cf9532163bab68076fda1bd2357b69e4b514729c15aaa83b5618b1977bbc60c4 +ae6596ccfdf5cbbc5782efe3bb0b101bb132dbe1d568854ca24cacc0b2e0e9fabcb2ca7ab42aecec412efd15cf8cb7a2 +84a0b6c198ff64fd7958dfd1b40eac9638e8e0b2c4cd8cf5d8cdf80419baee76a05184bce6c5b635f6bf2d30055476a7 +8893118be4a055c2b3da593dbca51b1ae2ea2469911acfb27ee42faf3e6c3ad0693d3914c508c0b05b36a88c8b312b76 +b097479e967504deb6734785db7e60d1d8034d6ca5ba9552887e937f5e17bb413fccac2c1d1082154ed76609127860ad +a0294e6b9958f244d29943debf24b00b538b3da1116269b6e452bb12dc742226712fd1a15b9c88195afeb5d2415f505c +b3cc15f635080bc038f61b615f62b5b5c6f2870586191f59476e8368a73641d6ac2f7d0c1f54621982defdb318020230 +99856f49b9fe1604d917c94d09cc0ed753d13d015d30587a94e6631ffd964b214e607deb8a69a8b5e349a7edf4309206 +a8571e113ea22b4b4fce41a094da8c70de37830ae32e62c65c2fa5ad06a9bc29e884b945e73d448c72b176d6ecebfb58 +a9e9c6e52beb0013273c29844956b3ce291023678107cdc785f7b44eff5003462841ad8780761b86aefc6b734adde7cf +80a784b0b27edb51ef2bad3aee80e51778dcaa0f3f5d3dcb5dc5d4f4b2cf7ae35b08de6680ea9dac53f8438b92eb09ef +827b543e609ea328e97e373f70ad72d4915a2d1daae0c60d44ac637231070e164c43a2a58db80a64df1c624a042b38f9 +b449c65e8195202efdcb9bdb4e869a437313b118fef8b510cbbf8b79a4e99376adb749b37e9c20b51b31ed3310169e27 +8ea3028f4548a79a94c717e1ed28ad4d8725b8d6ab18b021063ce46f665c79da3c49440c6577319dab2d036b7e08f387 +897798431cfb17fe39f08f5f854005dc37b1c1ec1edba6c24bc8acb3b88838d0534a75475325a5ea98b326ad47dbad75 +89cf232e6303b0751561960fd4dea5754a28c594daf930326b4541274ffb03c7dd75938e411eb9a375006a70ce38097f +9727c6ae7f0840f0b6c8bfb3a1a5582ceee705e0b5c59b97def7a7a2283edd4d3f47b7971e902a3a2079e40b53ff69b8 +b76ed72b122c48679d221072efc0eeea063cb205cbf5f9ef0101fd10cb1075b8628166c83577cced654e1c001c7882f7 +ae908c42d208759da5ee9b405df85a6532ea35c6f0f6a1288d22870f59d98edc896841b8ac890a538e6c8d1e8b02d359 +809d12fe4039a0ec80dc9be6a89acaab7797e5f7f9b163378f52f9a75a1d73b2e9ae6e3dd49e32ced439783c1cabbef5 +a4149530b7f85d1098ba534d69548c6c612c416e8d35992fc1f64f4deeb41e09e49c6cf7aadbed7e846b91299358fe2d +a49342eacd1ec1148b8df1e253b1c015f603c39de11fa0a364ccb86ea32d69c34fd7aa6980a1fadcd8e785a57fa46f60 +87d43eff5a006dc4dddcf76cc96c656a1f3a68f19f124181feab86c6cc9a52cb9189cdbb423414defdd9bb0ca8ff1ddc +861367e87a9aa2f0f68296ba50aa5dbc5713008d260cc2c7e62d407c2063064749324c4e8156dc21b749656cfebce26b +b5303c2f72e84e170e66ae1b0fbd51b8c7a6f27476eaf5694b64e8737d5c84b51fe90100b256465a4c4156dd873cddb0 +b62849a4f891415d74f434cdc1d23c4a69074487659ca96e1762466b2b7a5d8525b056b891d0feea6fe6845cba8bc7fb +923dd9e0d6590a9307e8c4c23f13bae3306b580e297a937711a8b13e8de85e41a61462f25b7d352b682e8437bf2b4ab3 +9147379860cd713cd46c94b8cdf75125d36c37517fbecf81ace9680b98ce6291cd1c3e472f84249cc3b2b445e314b1b6 +a808a4f17ac21e3fb5cfef404e61fae3693ca3e688d375f99b6116779696059a146c27b06de3ac36da349b0649befd56 +87787e9322e1b75e66c1f0d9ea0915722a232770930c2d2a95e9478c4b950d15ab767e30cea128f9ed65893bfc2d0743 +9036a6ee2577223be105defe1081c48ea7319e112fff9110eb9f61110c319da25a6cea0464ce65e858635b079691ef1f +af5548c7c24e1088c23b57ee14d26c12a83484c9fd9296edf1012d8dcf88243f20039b43c8c548c265ef9a1ffe9c1c88 +a0fff520045e14065965fb8accd17e878d3fcaf9e0af2962c8954e50be6683d31fa0bf4816ab68f08630dbac6bfce52a +b4c1b249e079f6ae1781af1d97a60b15855f49864c50496c09c91fe1946266915b799f0406084d7783f5b1039116dd8b +8b0ffa5e7c498cb3879dddca34743b41eee8e2dea3d4317a6e961b58adb699ef0c92400c068d5228881a2b08121226bf +852ae8b19a1d80aa8ae5382e7ee5c8e7670ceb16640871c56b20b96b66b3b60e00015a3dde039446972e57b49a999ddd +a49942f04234a7d8492169da232cfff8051df86e8e1ba3db46aede02422c689c87dc1d99699c25f96cb763f5ca0983e5 +b04b597b7760cf5dcf411ef896d1661e6d5b0db3257ac2cf64b20b60c6cc18fa10523bb958a48d010b55bac7b02ab3b1 +a494591b51ea8285daecc194b5e5bd45ae35767d0246ac94fae204d674ee180c8e97ff15f71f28b7aeb175b8aea59710 +97d2624919e78406e7460730680dea8e71c8571cf988e11441aeea54512b95bd820e78562c99372d535d96f7e200d20d +ac693ddb00e48f76e667243b9b6a7008424043fb779e4f2252330285232c3fccac4da25cbd6d95fe9ad959ff305a91f6 +8d20ca0a71a64a3f702a0825bb46bd810d03bebfb227683680d474a52f965716ff99e19a165ebaf6567987f4f9ee3c94 +a5c516a438f916d1d68ca76996404792e0a66e97b7f18fc54c917bf10cf3211b62387932756e39e67e47b0bd6e88385a +b089614d830abc0afa435034cec7f851f2f095d479cacf1a3fb57272da826c499a52e7dcbc0eb85f4166fb94778e18e9 +a8dacc943765d930848288192f4c69e2461c4b9bc6e79e30eeef9a543318cf9ae9569d6986c65c5668a89d49993f8e07 +ab5a9361fa339eec8c621bdad0a58078983abd8942d4282b22835d7a3a47e132d42414b7c359694986f7db39386c2e19 +94230517fb57bd8eb26c6f64129b8b2abd0282323bf7b94b8bac7fab27b4ecc2c4290c294275e1a759de19f2216134f3 +b8f158ea5006bc3b90b285246625faaa6ac9b5f5030dc69701b12f3b79a53ec7e92eeb5a63bbd1f9509a0a3469ff3ffc +8b6944fd8cb8540957a91a142fdcda827762aa777a31e8810ca6d026e50370ee1636fc351724767e817ca38804ebe005 +82d1ee40fe1569c29644f79fa6c4033b7ed45cd2c3b343881f6eb0de2e79548fded4787fae19bed6ee76ed76ff9f2f11 +a8924c7035e99eaed244ca165607e7e568b6c8085510dcdbaf6ebdbed405af2e6c14ee27d94ffef10d30aa52a60bf66d +956f82a6c2ae044635e85812581e4866c5fa2f427b01942047d81f6d79a14192f66fbbe77c9ffeaef4e6147097fdd2b5 +b1100255a1bcf5e05b6aff1dfeb6e1d55b5d68d43a7457ba10cc76b61885f67f4d0d5179abda786e037ae95deb8eea45 +99510799025e3e5e8fbf06dedb14c060c6548ba2bda824f687d3999dc395e794b1fb6514b9013f3892b6cf65cb0d65aa +8f9091cebf5e9c809aab415942172258f894e66e625d7388a05289183f01b8d994d52e05a8e69f784fba41db9ea357f0 +a13d2eeb0776bdee9820ecb6693536720232848c51936bb4ef4fe65588d3f920d08a21907e1fdb881c1ad70b3725e726 +a68b8f18922d550284c5e5dc2dda771f24c21965a6a4d5e7a71678178f46df4d8a421497aad8fcb4c7e241aba26378a0 +8b7601f0a3c6ad27f03f2d23e785c81c1460d60100f91ea9d1cab978aa03b523150206c6d52ce7c7769c71d2c8228e9e +a8e02926430813caa851bb2b46de7f0420f0a64eb5f6b805401c11c9091d3b6d67d841b5674fa2b1dce0867714124cd8 +b7968ecba568b8193b3058400af02c183f0a6df995a744450b3f7e0af7a772454677c3857f99c140bbdb2a09e832e8e0 +8f20b1e9ba87d0a3f35309b985f3c18d2e8800f1ca7f0c52cadef773f1496b6070c936eea48c4a1cae83fd2524e9d233 +88aef260042db0d641a51f40639dbeeefa9e9811df30bee695f3791f88a2f84d318f04e8926b7f47bf25956cb9e3754f +9725345893b647e9ba4e6a29e12f96751f1ae25fcaec2173e9a259921a1a7edb7a47159b3c8767e44d9e2689f5aa0f72 +8c281e6f72752cb11e239e4df9341c45106eb7993c160e54423c2bffe10bc39d42624b45a1f673936ef2e1a02fc92f1a +90aba2f68bddb2fcce6c51430dacdfeec43ea8dc379660c99095df11017691ccf5faa27665cf4b9f0eea7728ae53c327 +b7022695c16521c5704f49b7ddbdbec9b5f57ce0ceebe537bc0ebb0906d8196cc855a9afeb8950a1710f6a654464d93f +8fe1b9dd3c6a258116415d36e08374e094b22f0afb104385a5da48be17123e86fb8327baacc4f0d9ebae923d55d99bb5 +817e85d8e3d19a4cbc1dec31597142c2daa4871bda89c2177fa719c00eda3344eb08b82eb92d4aa91a9eaacb3fc09783 +b59053e1081d2603f1ca0ba553804d6fa696e1fd996631db8f62087b26a40dfef02098b0326bb75f99ec83b9267ca738 +990a173d857d3ba81ff3789b931bfc9f5609cde0169b7f055fa3cb56451748d593d62d46ba33f80f9cafffe02b68dd14 +b0c538dbba4954b809ab26f9f94a3cf1dcb77ce289eaec1d19f556c0ae4be1fa03af4a9b7057837541c3cc0a80538736 +ac3ba42f5f44f9e1fc453ce49c4ab79d0e1d5c42d3b30b1e098f3ab3f414c4c262fa12fb2be249f52d4aaf3c5224beb9 +af47467eb152e59870e21f0d4da2f43e093daf40180ab01438030684b114d025326928eaab12c41b81a066d94fce8436 +98d1b58ba22e7289b1c45c79a24624f19b1d89e00f778eef327ec4856a9a897278e6f1a9a7e673844b31dde949153000 +97ccb15dfadc7c59dca08cfe0d22df2e52c684cf97de1d94bc00d7ba24e020025130b0a39c0f4d46e4fc872771ee7875 +b699e4ed9a000ff96ca296b2f09dce278832bc8ac96851ff3cff99ed3f6f752cfc0fea8571be28cd9b5a7ec36f1a08ee +b9f49f0edb7941cc296435ff0a912e3ad16848ee8765ab5f60a050b280d6ea585e5b34051b15f6b8934ef01ceb85f648 +ac3893df7b4ceab23c6b9054e48e8ba40d6e5beda8fbe90b814f992f52494186969b35d8c4cdc3c99890a222c9c09008 +a41293ad22fae81dea94467bc1488c3707f3d4765059173980be93995fa4fcc3c9340796e3eed0beeb0ba0d9bb4fa3aa +a0543e77acd2aeecde13d18d258aeb2c7397b77f17c35a1992e8666ea7abcd8a38ec6c2741bd929abba2f766138618cc +92e79b22bc40e69f6527c969500ca543899105837b6b1075fa1796755c723462059b3d1b028e0b3df2559fa440e09175 +a1fa1eac8f41a5197a6fb4aa1eae1a031c89f9c13ff9448338b222780cf9022e0b0925d930c37501a0ef7b2b00fdaf83 +b3cb29ff73229f0637335f28a08ad8c5f166066f27c6c175164d0f26766a927f843b987ee9b309ed71cbf0a65d483831 +84d4ab787f0ac00f104f4a734dc693d62d48c2aeb03913153da62c2ae2c27d11b1110dcef8980368dd84682ea2c1a308 +ab6a8e4bbc78d4a7b291ad3e9a8fe2d65f640524ba3181123b09d2d18a9e300e2509ccf7000fe47e75b65f3e992a2e7e +b7805ebe4f1a4df414003dc10bca805f2ab86ca75820012653e8f9b79c405196b0e2cab099f2ab953d67f0d60d31a0f9 +b12c582454148338ea605d22bd00a754109063e22617f1f8ac8ddf5502c22a181c50c216c3617b9852aa5f26af56b323 +86333ad9f898947e31ce747728dc8c887479e18d36ff3013f69ebef807d82c6981543b5c3788af93c4d912ba084d3cba +b514efa310dc4ad1258add138891e540d8c87142a881b5f46563cc58ecd1488e6d3a2fca54c0b72a929f3364ca8c333e +aa0a30f92843cf2f484066a783a1d75a7aa6f41f00b421d4baf20a6ac7886c468d0eea7ca8b17dd22f4f74631b62b640 +b3b7dc63baec9a752e8433c0cdee4d0f9bc41f66f2b8d132faf925eef9cf89aae756fc132c45910f057122462605dc10 +b9b8190dac5bfdeb59fd44f4da41a57e7f1e7d2c21faba9da91fa45cbeca06dcf299c9ae22f0c89ece11ac46352d619f +89f8cf36501ad8bdfeab863752a9090e3bfda57cf8fdeca2944864dc05925f501e252c048221bcc57136ab09a64b64b2 +b0cbfaf317f05f97be47fc9d69eda2dd82500e00d42612f271a1fe24626408c28881f171e855bd5bd67409f9847502b4 +a7c21a8fcede581bfd9847b6835eda62ba250bea81f1bb17372c800a19c732abe03064e64a2f865d974fb636cab4b859 +95f9df524ba7a4667351696c4176b505d8ea3659f5ff2701173064acc624af69a0fad4970963736383b979830cb32260 +856a74fe8b37a2e3afeac858c8632200485d438422a16ae3b29f359e470e8244995c63ad79c7e007ed063f178d0306fd +b37faa4d78fdc0bb9d403674dbea0176c2014a171c7be8527b54f7d1a32a76883d3422a3e7a5f5fcc5e9b31b57822eeb +8d37234d8594ec3fe75670b5c9cc1ec3537564d4739b2682a75b18b08401869a4264c0f264354219d8d896cded715db4 +b5289ee5737f0e0bde485d32096d23387d68dab8f01f47821ab4f06cc79a967afe7355e72dc0c751d96b2747b26f6255 +9085e1fdf9f813e9c3b8232d3c8863cd84ab30d45e8e0d3d6a0abd9ebc6fd70cdf749ff4d04390000e14c7d8c6655fc7 +93a388c83630331eca4da37ea4a97b3b453238af474817cc0a0727fd3138dcb4a22de38c04783ec829c22cb459cb4e8e +a5377116027c5d061dbe24c240b891c08cdd8cd3f0899e848d682c873aff5b8132c1e7cfe76d2e5ed97ee0eb1d42cb68 +a274c84b04338ed28d74683e2a7519c2591a3ce37c294d6f6e678f7d628be2db8eff253ede21823e2df7183e6552f622 +8bc201147a842453a50bec3ac97671397bc086d6dfc9377fa38c2124cdc286abda69b7324f47d64da094ae011d98d9d9 +9842d0c066c524592b76fbec5132bc628e5e1d21c424bec4555efca8619cc1fd8ea3161febcb8b9e8ab54702f4e815e2 +a19191b713a07efe85c266f839d14e25660ee74452e6c691cd9997d85ae4f732052d802d3deb018bdd847caa298a894b +a24f71fc0db504da4e287dd118a4a74301cbcd16033937ba2abc8417956fcb4ae19b8e63b931795544a978137eff51cb +a90eec4a6a3a4b8f9a5b93d978b5026fcf812fe65585b008d7e08c4aaf21195a1d0699f12fc16f79b6a18a369af45771 +8b551cf89737d7d06d9b3b9c4c1c73b41f2ea0af4540999c70b82dabff8580797cf0a3caf34c86c59a7069eb2e38f087 +b8d312e6c635e7a216a1cda075ae77ba3e1d2fd501dc31e83496e6e81ed5d9c7799f8e578869c2e0e256fb29f5de10a7 +8d144bdb8cae0b2cdb5b33d44bbc96984a5925202506a8cc65eb67ac904b466f5a7fe3e1cbf04aa785bbb7348c4bb73c +a101b3d58b7a98659244b88de0b478b3fb87dc5fc6031f6e689b99edf498abd43e151fd32bd4bbd240e0b3e59c440359 +907453abca7d8e7151a05cc3d506c988007692fe7401395dc93177d0d07d114ab6cca0cc658eb94c0223fe8658295cad +825329ffbe2147ddb68f63a0a67f32d7f309657b8e5d9ab5bb34b3730bfa2c77a23eaaadb05def7d9f94a9e08fdc1e96 +88ee923c95c1dac99ae7ed6067906d734d793c5dc5d26339c1bb3314abe201c5dccb33b9007351885eb2754e9a8ea06c +98bc9798543f5f1adc9f2cfcfa72331989420e9c3f6598c45269f0dc9b7c8607bbeaf03faa0aea2ddde2b8f17fdceff5 +8ee87877702a79aef923ab970db6fa81561b3c07d5bf1a072af0a7bad765b4cbaec910afe1a91703feacc7822fa38a94 +8060b9584aa294fe8adc2b22f67e988bc6da768eae91e429dcc43ddc53cfcc5d6753fdc1b420b268c7eb2fb50736a970 +b344a5524d80a2f051870c7001f74fcf348a70fcf78dbd20c6ff9ca85d81567d2318c8b8089f2c4f195d6aec9fc15fa6 +8f5a5d893e1936ed062149d20eb73d98b62b7f50ab5d93a6429c03656b36688d1c80cb5010e4977491e51fa0d7dd35d5 +86fa32ebbf97328c5f5f15564e1238297e289ec3219b9a741724e9f3ae8d5c15277008f555863a478b247ba5dc601d44 +9557e55377e279f4b6b5e0ffe01eca037cc13aac242d67dfcd0374a1e775c5ed5cb30c25fe21143fee54e3302d34a3ea +8cb6bcbc39372d23464a416ea7039f57ba8413cf3f00d9a7a5b356ab20dcb8ed11b3561f7bce372b8534d2870c7ee270 +b5d59075cb5abde5391f64b6c3b8b50adc6e1f654e2a580b6d6d6eff3f4fbdd8fffc92e06809c393f5c8eab37f774c4b +afcfb6903ef13e493a1f7308675582f15af0403b6553e8c37afb8b2808ad21b88b347dc139464367dc260df075fea1ad +810fbbe808375735dd22d5bc7fc3828dc49fdd22cc2d7661604e7ac9c4535c1df578780affb3b895a0831640a945bcad +8056b0c678803b416f924e09a6299a33cf9ad7da6fe1ad7accefe95c179e0077da36815fde3716711c394e2c5ea7127f +8b67403702d06979be19f1d6dc3ec73cc2e81254d6b7d0cc49cd4fdda8cd51ab0835c1d2d26fc0ecab5df90585c2f351 +87f97f9e6d4be07e8db250e5dd2bffdf1390665bc5709f2b631a6fa69a7fca958f19bd7cc617183da1f50ee63e9352b5 +ae151310985940471e6803fcf37600d7fa98830613e381e00dab943aec32c14162d51c4598e8847148148000d6e5af5c +81eb537b35b7602c45441cfc61b27fa9a30d3998fad35a064e05bc9479e9f10b62eba2b234b348219eea3cadcaac64bb +8a441434934180ab6f5bc541f86ebd06eadbee01f438836d797e930fa803a51510e005c9248cecc231a775b74d12b5e9 +81f3c250a27ba14d8496a5092b145629eb2c2e6a5298438670375363f57e2798207832c8027c3e9238ad94ecdadfc4df +a6217c311f2f3db02ceaa5b6096849fe92b6f4b6f1491535ef8525f6ccee6130bed2809e625073ecbaddd4a3eb3df186 +82d1c396f0388b942cf22b119d7ef1ad03d3dad49a74d9d01649ee284f377c8daddd095d596871669e16160299a210db +a40ddf7043c5d72a7246bd727b07f7fff1549f0e443d611de6f9976c37448b21664c5089c57f20105102d935ab82f27b +b6c03c1c97adf0c4bf4447ec71366c6c1bff401ba46236cd4a33d39291e7a1f0bb34bd078ba3a18d15c98993b153a279 +8a94f5f632068399c359c4b3a3653cb6df2b207379b3d0cdace51afdf70d6d5cce6b89a2b0fee66744eba86c98fb21c2 +b2f19e78ee85073f680c3bba1f07fd31b057c00b97040357d97855b54a0b5accb0d3b05b2a294568fcd6a4be6f266950 +a74632d13bbe2d64b51d7a9c3ae0a5a971c19f51cf7596a807cea053e6a0f3719700976d4e394b356c0329a2dced9aa2 +afef616d341a9bc94393b8dfba68ff0581436aa3a3adb7c26a1bbf2cf19fa877066191681f71f17f3cd6f9cf6bf70b5a +8ce96d93ae217408acf7eb0f9cbb9563363e5c7002e19bbe1e80760bc9d449daee2118f3878b955163ed664516b97294 +8414f79b496176bc8b8e25f8e4cfee28f4f1c2ddab099d63d2aca1b6403d26a571152fc3edb97794767a7c4686ad557c +b6c61d01fd8ce087ef9f079bf25bf10090db483dd4f88c4a786d31c1bdf52065651c1f5523f20c21e75cea17df69ab73 +a5790fd629be70545093631efadddc136661f63b65ec682609c38ef7d3d7fa4e56bdf94f06e263bc055b90cb1c6bcefe +b515a767e95704fb7597bca9e46f1753abacdc0e56e867ee3c6f4cd382643c2a28e65312c05ad040eaa3a8cbe7217a65 +8135806a02ead6aa92e9adb6fefb91349837ab73105aaa7be488ef966aa8dfaafdfa64bbae30fcbfa55dd135a036a863 +8f22435702716d76b1369750694540742d909d5e72b54d0878245fab7c269953b1c6f2b29c66f08d5e0263ca3a731771 +8e0f8a8e8753e077dac95848212aeffd51c23d9b6d611df8b102f654089401954413ecbedc6367561ca599512ae5dda7 +815a9084e3e2345f24c5fa559deec21ee1352fb60f4025c0779be65057f2d528a3d91593bd30d3a185f5ec53a9950676 +967e6555ccba395b2cc1605f8484c5112c7b263f41ce8439a99fd1c71c5ed14ad02684d6f636364199ca48afbbde13be +8cd0ccf17682950b34c796a41e2ea7dd5367aba5e80a907e01f4cdc611e4a411918215e5aebf4292f8b24765d73314a6 +a58bf1bbb377e4b3915df6f058a0f53b8fb8130fdec8c391f6bc82065694d0be59bb67ffb540e6c42cc8b380c6e36359 +92af3151d9e6bfb3383d85433e953c0160859f759b0988431ec5893542ba40288f65db43c78a904325ef8d324988f09d +8011bbb05705167afb47d4425065630f54cb86cd462095e83b81dfebf348f846e4d8fbcf1c13208f5de1931f81da40b9 +81c743c104fc3cb047885c9fa0fb9705c3a83ee24f690f539f4985509c3dafd507af3f6a2128276f45d5939ef70c167f +a2c9679b151c041aaf5efeac5a737a8f70d1631d931609fca16be1905682f35e291292874cb3b03f14994f98573c6f44 +a4949b86c4e5b1d5c82a337e5ce6b2718b1f7c215148c8bfb7e7c44ec86c5c9476048fc5c01f57cb0920876478c41ad6 +86c2495088bd1772152e527a1da0ef473f924ea9ab0e5b8077df859c28078f73c4e22e3a906b507fdf217c3c80808b5c +892e0a910dcf162bcea379763c3e2349349e4cda9402949255ac4a78dd5a47e0bf42f5bd0913951576b1d206dc1e536a +a7009b2c6b396138afe4754b7cc10dee557c51c7f1a357a11486b3253818531f781ea8107360c8d4c3b1cd96282353c0 +911763ef439c086065cc7b4e57484ed6d693ea44acee4b18c9fd998116da55fbe7dcb8d2a0f0f9b32132fca82d73dff6 +a722000b95a4a2d40bed81870793f15ba2af633f9892df507f2842e52452e02b5ea8dea6a043c2b2611d82376e33742a +9387ac49477bd719c2f92240d0bdfcf9767aad247ca93dc51e56106463206bc343a8ec855eb803471629a66fffb565d6 +92819a1fa48ab4902939bb72a0a4e6143c058ea42b42f9bc6cea5df45f49724e2530daf3fc4f097cceefa2a8b9db0076 +98eac7b04537653bc0f4941aae732e4b1f84bd276c992c64a219b8715eb1fb829b5cbd997d57feb15c7694c468f95f70 +b275e7ba848ce21bf7996e12dbeb8dadb5d0e4f1cb5a0248a4f8f9c9fe6c74e3c93f4b61edbcb0a51af5a141e1c14bc7 +97243189285aba4d49c53770c242f2faf5fd3914451da4931472e3290164f7663c726cf86020f8f181e568c72fd172d1 +839b0b3c25dd412bee3dc24653b873cc65454f8f16186bb707bcd58259c0b6765fa4c195403209179192a4455c95f3b8 +8689d1a870514568a074a38232e2ceb4d7df30fabeb76cff0aed5b42bf7f02baea12c5fadf69f4713464dbd52aafa55f +8958ae7b290f0b00d17c3e9fdb4dbf168432b457c7676829299dd428984aba892de1966fc106cfc58a772862ecce3976 +a422bc6bd68b8870cfa5bc4ce71781fd7f4368b564d7f1e0917f6013c8bbb5b240a257f89ecfdbecb40fe0f3aa31d310 +aa61f78130cebe09bc9a2c0a37f0dd57ed2d702962e37d38b1df7f17dc554b1d4b7a39a44182a452ce4c5eb31fa4cfcc +b7918bd114f37869bf1a459023386825821bfadce545201929d13ac3256d92a431e34f690a55d944f77d0b652cefeffc +819bba35fb6ace1510920d4dcff30aa682a3c9af9022e287751a6a6649b00c5402f14b6309f0aeef8fce312a0402915e +8b7c9ad446c6f63c11e1c24e24014bd570862b65d53684e107ba9ad381e81a2eaa96731b4b33536efd55e0f055071274 +8fe79b53f06d33386c0ec7d6d521183c13199498594a46d44a8a716932c3ec480c60be398650bbfa044fa791c4e99b65 +9558e10fb81250b9844c99648cf38fa05ec1e65d0ccbb18aa17f2d1f503144baf59d802c25be8cc0879fff82ed5034ad +b538a7b97fbd702ba84645ca0a63725be1e2891c784b1d599e54e3480e4670d0025526674ef5cf2f87dddf2290ba09f0 +92eafe2e869a3dd8519bbbceb630585c6eb21712b2f31e1b63067c0acb5f9bdbbcbdb612db4ea7f9cc4e7be83d31973f +b40d21390bb813ab7b70a010dff64c57178418c62685761784e37d327ba3cb9ef62df87ecb84277c325a637fe3709732 +b349e6fbf778c4af35fbed33130bd8a7216ed3ba0a79163ebb556e8eb8e1a7dad3456ddd700dad9d08d202491c51b939 +a8fdaedecb251f892b66c669e34137f2650509ade5d38fbe8a05d9b9184bb3b2d416186a3640429bd1f3e4b903c159dd +ac6167ebfee1dbab338eff7642f5e785fc21ef0b4ddd6660333fe398068cbd6c42585f62e81e4edbb72161ce852a1a4f +874b1fbf2ebe140c683bd7e4e0ab017afa5d4ad38055aaa83ee6bbef77dbc88a6ce8eb0dcc48f0155244af6f86f34c2d +903c58e57ddd9c446afab8256a6bb6c911121e6ccfb4f9b4ed3e2ed922a0e500a5cb7fa379d5285bc16e11dac90d1fda +8dae7a0cffa2fd166859cd1bf10ff82dd1932e488af377366b7efc0d5dec85f85fe5e8150ff86a79a39cefc29631733a +aa047857a47cc4dfc08585f28640420fcf105b881fd59a6cf7890a36516af0644d143b73f3515ab48faaa621168f8c31 +864508f7077c266cc0cb3f7f001cb6e27125ebfe79ab57a123a8195f2e27d3799ff98413e8483c533b46a816a3557f1f +8bcd45ab1f9cbab36937a27e724af819838f66dfeb15923f8113654ff877bd8667c54f6307aaf0c35027ca11b6229bfd +b21aa34da9ab0a48fcfdd291df224697ce0c1ebc0e9b022fdee8750a1a4b5ba421c419541ed5c98b461eecf363047471 +a9a18a2ab2fae14542dc336269fe612e9c1af6cf0c9ac933679a2f2cb77d3c304114f4d219ca66fe288adde30716775b +b5205989b92c58bdda71817f9a897e84100b5c4e708de1fced5c286f7a6f01ae96b1c8d845f3a320d77c8e2703c0e8b1 +a364059412bbcc17b8907d43ac8e5df90bc87fd1724b5f99832d0d24559fae6fa76a74cff1d1eac8cbac6ec80b44af20 +ae709f2c339886b31450834cf29a38b26eb3b0779bd77c9ac269a8a925d1d78ea3837876c654b61a8fe834b3b6940808 +8802581bba66e1952ac4dab36af371f66778958f4612901d95e5cac17f59165e6064371d02de8fb6fccf89c6dc8bd118 +a313252df653e29c672cbcfd2d4f775089cb77be1077381cf4dc9533790e88af6cedc8a119158e7da5bf6806ad9b91a1 +992a065b4152c7ef11515cd54ba9d191fda44032a01aed954acff3443377ee16680c7248d530b746b8c6dee2d634e68c +b627b683ee2b32c1ab4ccd27b9f6cce2fe097d96386fa0e5c182ad997c4c422ab8dfc03870cd830b8c774feb66537282 +b823cf8a9aee03dadd013eb9efe40a201b4b57ef67efaae9f99683005f5d1bf55e950bf4af0774f50859d743642d3fea +b8a7449ffac0a3f206677097baf7ce00ca07a4d2bd9b5356fbcb83f3649b0fda07cfebad220c1066afba89e5a52abf4b +b2dd1a2f986395bb4e3e960fbbe823dbb154f823284ebc9068502c19a7609790ec0073d08bfa63f71e30c7161b6ef966 +98e5236de4281245234f5d40a25b503505af140b503a035fc25a26159a9074ec81512b28f324c56ea2c9a5aa7ce90805 +89070847dc8bbf5bc4ed073aa2e2a1f699cf0c2ca226f185a0671cecc54e7d3e14cd475c7752314a7a8e7476829da4bc +a9402dc9117fdb39c4734c0688254f23aed3dce94f5f53f5b7ef2b4bf1b71a67f85ab1a38ec224a59691f3bee050aeb3 +957288f9866a4bf56a4204218ccc583f717d7ce45c01ea27142a7e245ad04a07f289cc044f8cf1f21d35e67e39299e9c +b2fb31ccb4e69113763d7247d0fc8edaae69b550c5c56aecacfd780c7217dc672f9fb7496edf4aba65dacf3361268e5b +b44a4526b2f1d6eb2aa8dba23bfa385ff7634572ab2afddd0546c3beb630fbfe85a32f42dd287a7fec069041411537f7 +8db5a6660c3ac7fd7a093573940f068ee79a82bc17312af900b51c8c439336bc86ca646c6b7ab13aaaa008a24ca508ab +8f9899a6d7e8eb4367beb5c060a1f8e94d8a21099033ae582118477265155ba9e72176a67f7f25d7bad75a152b56e21a +a67de0e91ade8d69a0e00c9ff33ee2909b8a609357095fa12319e6158570c232e5b6f4647522efb7345ce0052aa9d489 +82eb2414898e9c3023d57907a2b17de8e7eea5269029d05a94bfd7bf5685ac4a799110fbb375eb5e0e2bd16acf6458ae +94451fc7fea3c5a89ba701004a9693bab555cb622caf0896b678faba040409fdfd14a978979038b2a81e8f0abc4994d2 +ac879a5bb433998e289809a4a966bd02b4bf6a9c1cc276454e39c886efcf4fc68baebed575826bde577ab5aa71d735a9 +880c0f8f49c875dfd62b4ddedde0f5c8b19f5687e693717f7e5c031bc580e58e13ab497d48b4874130a18743c59fdce3 +b582af8d8ff0bf76f0a3934775e0b54c0e8fed893245d7d89cae65b03c8125b7237edc29dc45b4fe1a3fe6db45d280ee +89f337882ed3ae060aaee98efa20d79b6822bde9708c1c5fcee365d0ec9297f694cae37d38fd8e3d49717c1e86f078e7 +826d2c1faea54061848b484e288a5f4de0d221258178cf87f72e14baaa4acc21322f8c9eab5dde612ef497f2d2e1d60b +a5333d4f227543e9cd741ccf3b81db79f2f03ca9e649e40d6a6e8ff9073e06da83683566d3b3c8d7b258c62970fb24d1 +a28f08c473db06aaf4c043a2fae82b3c8cfaa160bce793a4c208e4e168fb1c65115ff8139dea06453c5963d95e922b94 +8162546135cc5e124e9683bdfaa45833c18553ff06a0861c887dc84a5b12ae8cd4697f6794c7ef6230492c32faba7014 +b23f0d05b74c08d6a7df1760792be83a761b36e3f8ae360f3c363fb196e2a9dd2de2e492e49d36561366e14daa77155c +b6f70d6c546722d3907c708d630dbe289771d2c8bf059c2e32b77f224696d750b4dda9b3a014debda38e7d02c9a77585 +83bf4c4a9f3ca022c631017e7a30ea205ba97f7f5927cba8fc8489a4646eac6712cb821c5668c9ffe94d69d524374a27 +b0371475425a8076d0dd5f733f55aabbe42d20a7c8ea7da352e736d4d35a327b2beb370dfcb05284e22cfd69c5f6c4cc +a0031ba7522c79211416c2cca3aa5450f96f8fee711552a30889910970ba13608646538781a2c08b834b140aadd7166f +99d273c80c7f2dc6045d4ed355d9fc6f74e93549d961f4a3b73cd38683f905934d359058cd1fc4da8083c7d75070487f +b0e4b0efa3237793e9dcce86d75aafe9879c5fa23f0d628649aef2130454dcf72578f9bf227b9d2b9e05617468e82588 +a5ab076fa2e1c5c51f3ae101afdd596ad9d106bba7882b359c43d8548b64f528af19afa76cd6f40da1e6c5fca4def3fa +8ce2299e570331d60f6a6eff1b271097cd5f1c0e1113fc69b89c6a0f685dabea3e5bc2ac6bd789aa492ab189f89be494 +91b829068874d911a310a5f9dee001021f97471307b5a3de9ec336870ec597413e1d92010ce320b619f38bed7c4f7910 +b14fe91f4b07bf33b046e9285b66cb07927f3a8da0af548ac2569b4c4fb1309d3ced76d733051a20814e90dd5b75ffd1 +abaab92ea6152d40f82940277c725aa768a631ee0b37f5961667f82fb990fc11e6d3a6a2752b0c6f94563ed9bb28265c +b7fe28543eca2a716859a76ab9092f135337e28109544f6bd2727728d0a7650428af5713171ea60bfc273d1c821d992c +8a4917b2ab749fc7343fc64bdf51b6c0698ff15d740cc7baf248c030475c097097d5a473bcc00d8c25817563fe0447b4 +aa96156d1379553256350a0a3250166add75948fb9cde62aa555a0a9dc0a9cb7f2f7b8428aff66097bf6bfedaf14bbe2 +ae4ffeb9bdc76830d3eca2b705f30c1bdede6412fa064260a21562c8850c7fb611ec62bc68479fe48f692833e6f66d8d +b96543caaba9d051600a14997765d49e4ab10b07c7a92cccf0c90b309e6da334fdd6d18c96806cbb67a7801024fbd3c7 +97b2b9ad76f19f500fcc94ca8e434176249f542ac66e5881a3dccd07354bdab6a2157018b19f8459437a68d8b86ba8e0 +a8d206f6c5a14c80005849474fde44b1e7bcf0b2d52068f5f97504c3c035b09e65e56d1cf4b5322791ae2c2fdbd61859 +936bad397ad577a70cf99bf9056584a61bd7f02d2d5a6cf219c05d770ae30a5cd902ba38366ce636067fc1dd10108d31 +a77e30195ee402b84f3882e2286bf5380c0ed374a112dbd11e16cef6b6b61ab209d4635e6f35cdaaa72c1a1981d5dabe +a46ba4d3947188590a43c180757886a453a0503f79cc435322d92490446f37419c7b999fdf868a023601078070e03346 +80d8d4c5542f223d48240b445d4d8cf6a75d120b060bc08c45e99a13028b809d910b534d2ac47fb7068930c54efd8da9 +803be9c68c91b42b68e1f55e58917a477a9a6265e679ca44ee30d3eb92453f8c89c64eafc04c970d6831edd33d066902 +b14b2b3d0dfe2bb57cee4cd72765b60ac33c1056580950be005790176543826c1d4fbd737f6cfeada6c735543244ab57 +a9e480188bba1b8fb7105ff12215706665fd35bf1117bacfb6ab6985f4dbc181229873b82e5e18323c2b8f5de03258e0 +a66a0f0779436a9a3999996d1e6d3000f22c2cac8e0b29cddef9636393c7f1457fb188a293b6c875b05d68d138a7cc4a +848397366300ab40c52d0dbbdafbafef6cd3dadf1503bb14b430f52bb9724188928ac26f6292a2412bc7d7aa620763c8 +95466cc1a78c9f33a9aaa3829a4c8a690af074916b56f43ae46a67a12bb537a5ac6dbe61590344a25b44e8512355a4a7 +8b5f7a959f818e3baf0887f140f4575cac093d0aece27e23b823cf421f34d6e4ff4bb8384426e33e8ec7b5eed51f6b5c +8d5e1368ec7e3c65640d216bcc5d076f3d9845924c734a34f3558ac0f16e40597c1a775a25bf38b187213fbdba17c93b +b4647c1b823516880f60d20c5cc38c7f80b363c19d191e8992226799718ee26b522a12ecb66556ed3d483aa4824f3326 +ac3abaea9cd283eb347efda4ed9086ea3acf495043e08d0d19945876329e8675224b685612a6badf8fd72fb6274902b1 +8eae1ce292d317aaa71bcf6e77e654914edd5090e2e1ebab78b18bb41b9b1bc2e697439f54a44c0c8aa0d436ebe6e1a9 +94dc7d1aec2c28eb43d93b111fa59aaa0d77d5a09501220bd411768c3e52208806abf973c6a452fd8292ff6490e0c9e2 +8fd8967f8e506fef27d17b435d6b86b232ec71c1036351f12e6fb8a2e12daf01d0ee04451fb944d0f1bf7fd20e714d02 +824e6865be55d43032f0fec65b3480ea89b0a2bf860872237a19a54bc186a85d2f8f9989cc837fbb325b7c72d9babe2c +8bd361f5adb27fd6f4e3f5de866e2befda6a8454efeb704aacc606f528c03f0faae888f60310e49440496abd84083ce2 +b098a3c49f2aaa28b6b3e85bc40ce6a9cdd02134ee522ae73771e667ad7629c8d82c393fba9f27f5416986af4c261438 +b385f5ca285ff2cfe64dcaa32dcde869c28996ed091542600a0b46f65f3f5a38428cca46029ede72b6cf43e12279e3d3 +8196b03d011e5be5288196ef7d47137d6f9237a635ab913acdf9c595fa521d9e2df722090ec7eb0203544ee88178fc5f +8ed1270211ef928db18e502271b7edf24d0bbd11d97f2786aee772d70c2029e28095cf8f650b0328cc8a4c38d045316d +a52ab60e28d69b333d597a445884d44fd2a7e1923dd60f763951e1e45f83e27a4dac745f3b9eff75977b3280e132c15d +91e9fe78cdac578f4a4687f71b800b35da54b824b1886dafec073a3c977ce7a25038a2f3a5b1e35c2c8c9d1a7312417c +a42832173f9d9491c7bd93b21497fbfa4121687cd4d2ab572e80753d7edcbb42cfa49f460026fbde52f420786751a138 +97b947126d84dcc70c97be3c04b3de3f239b1c4914342fa643b1a4bb8c4fe45c0fcb585700d13a7ed50784790c54bef9 +860e407d353eac070e2418ef6cb80b96fc5f6661d6333e634f6f306779651588037be4c2419562c89c61f9aa2c4947f5 +b2c9d93c3ba4e511b0560b55d3501bf28a510745fd666b3cb532db051e6a8617841ea2f071dda6c9f15619c7bfd2737f +8596f4d239aeeac78311207904d1bd863ef68e769629cc379db60e019aaf05a9d5cd31dc8e630b31e106a3a93e47cbc5 +8b26e14e2e136b65c5e9e5c2022cee8c255834ea427552f780a6ca130a6446102f2a6f334c3f9a0308c53df09e3dba7e +b54724354eb515a3c8bed0d0677ff1db94ac0a07043459b4358cb90e3e1aa38ac23f2caa3072cf9647275d7cd61d0e80 +b7ce9fe0e515e7a6b2d7ddcb92bc0196416ff04199326aea57996eef8c5b1548bd8569012210da317f7c0074691d01b7 +a1a13549c82c877253ddefa36a29ea6a23695ee401fdd48e65f6f61e5ebd956d5e0edeff99484e9075cb35071fec41e2 +838ba0c1e5bd1a6da05611ff1822b8622457ebd019cb065ece36a2d176bd2d889511328120b8a357e44569e7f640c1e6 +b916eccff2a95519400bbf76b5f576cbe53cf200410370a19d77734dc04c05b585cfe382e8864e67142d548cd3c4c2f4 +a610447cb7ca6eea53a6ff1f5fe562377dcb7f4aaa7300f755a4f5e8eba61e863c51dc2aa9a29b35525b550fbc32a0fe +9620e8f0f0ee9a4719aa9685eeb1049c5c77659ba6149ec4c158f999cfd09514794b23388879931fe26fea03fa471fd3 +a9dcf8b679e276583cf5b9360702a185470d09aea463dc474ee9c8aee91ef089dacb073e334e47fbc78ec5417c90465c +8c9adee8410bdd99e5b285744cee61e2593b6300ff31a8a83b0ec28da59475a5c6fb9346fe43aadea2e6c3dad2a8e30a +97d5afe9b3897d7b8bb628b7220cf02d8ee4e9d0b78f5000d500aaf4c1df9251aaaabfd1601626519f9d66f00a821d4e +8a382418157b601ce4c3501d3b8409ca98136a4ef6abcbf62885e16e215b76b035c94d149cc41ff92e42ccd7c43b9b3d +b64b8d11fb3b01abb2646ac99fdb9c02b804ce15d98f9fe0fbf1c9df8440c71417487feb6cdf51e3e81d37104b19e012 +849d7d044f9d8f0aab346a9374f0b3a5d14a9d1faa83dbacccbdc629ad1ef903a990940255564770537f8567521d17f0 +829dbb0c76b996c2a91b4cbbe93ba455ca0d5729755e5f0c92aaee37dff7f36fcdc06f33aca41f1b609c784127b67d88 +85a7c0069047b978422d264d831ab816435f63938015d2e977222b6b5746066c0071b7f89267027f8a975206ed25c1b0 +84b9fbc1cfb302df1acdcf3dc5d66fd1edfe7839f7a3b2fb3a0d5548656249dd556104d7c32b73967bccf0f5bdcf9e3b +972220ac5b807f53eac37dccfc2ad355d8b21ea6a9c9b011c09fe440ddcdf7513e0b43d7692c09ded80d7040e26aa28f +855885ed0b21350baeca890811f344c553cf9c21024649c722453138ba29193c6b02c4b4994cd414035486f923472e28 +841874783ae6d9d0e59daea03e96a01cbbe4ecaced91ae4f2c8386e0d87b3128e6d893c98d17c59e4de1098e1ad519dd +827e50fc9ce56f97a4c3f2f4cbaf0b22f1c3ce6f844ff0ef93a9c57a09b8bf91ebfbd2ba9c7f83c442920bffdaf288cc +a441f9136c7aa4c08d5b3534921b730e41ee91ab506313e1ba5f7c6f19fd2d2e1594e88c219834e92e6fb95356385aa7 +97d75b144471bf580099dd6842b823ec0e6c1fb86dd0da0db195e65524129ea8b6fd4a7a9bbf37146269e938a6956596 +a4b6fa87f09d5a29252efb2b3aaab6b3b6ea9fab343132a651630206254a25378e3e9d6c96c3d14c150d01817d375a8e +a31a671876d5d1e95fe2b8858dc69967231190880529d57d3cab7f9f4a2b9b458ac9ee5bdaa3289158141bf18f559efb +90bee6fff4338ba825974021b3b2a84e36d617e53857321f13d2b3d4a28954e6de3b3c0e629d61823d18a9763313b3bf +96b622a63153f393bb419bfcf88272ea8b3560dbd46b0aa07ada3a6223990d0abdd6c2adb356ef4be5641688c8d83941 +84c202adeaff9293698022bc0381adba2cd959f9a35a4e8472288fd68f96f6de8be9da314c526d88e291c96b1f3d6db9 +8ca01a143b8d13809e5a8024d03e6bc9492e22226073ef6e327edf1328ef4aff82d0bcccee92cb8e212831fa35fe1204 +b2f970dbad15bfbefb38903c9bcc043d1367055c55dc1100a850f5eb816a4252c8c194b3132c929105511e14ea10a67d +a5e36556472a95ad57eb90c3b6623671b03eafd842238f01a081997ffc6e2401f76e781d049bb4aa94d899313577a9cf +8d1057071051772f7c8bedce53a862af6fd530dd56ae6321eaf2b9fc6a68beff5ed745e1c429ad09d5a118650bfd420a +8aadc4f70ace4fcb8d93a78610779748dcffc36182d45b932c226dc90e48238ea5daa91f137c65ed532352c4c4d57416 +a2ea05ae37e673b4343232ae685ee14e6b88b867aef6dfac35db3589cbcd76f99540fed5c2641d5bb5a4a9f808e9bf0d +947f1abad982d65648ae4978e094332b4ecb90f482c9be5741d5d1cf5a28acf4680f1977bf6e49dd2174c37f11e01296 +a27b144f1565e4047ba0e3f4840ef19b5095d1e281eaa463c5358f932114cbd018aa6dcf97546465cf2946d014d8e6d6 +8574e1fc3acade47cd4539df578ce9205e745e161b91e59e4d088711a7ab5aa3b410d517d7304b92109924d9e2af8895 +a48ee6b86b88015d6f0d282c1ae01d2a5b9e8c7aa3d0c18b35943dceb1af580d08a65f54dc6903cde82fd0d73ce94722 +8875650cec543a7bf02ea4f2848a61d167a66c91ffaefe31a9e38dc8511c6a25bde431007eefe27a62af3655aca208dc +999b0a6e040372e61937bf0d68374e230346b654b5a0f591a59d33a4f95bdb2f3581db7c7ccb420cd7699ed709c50713 +878c9e56c7100c5e47bbe77dc8da5c5fe706cec94d37fa729633bca63cace7c40102eee780fcdabb655f5fa47a99600e +865006fb5b475ada5e935f27b96f9425fc2d5449a3c106aa366e55ebed3b4ee42adc3c3f0ac19fd129b40bc7d6bc4f63 +b7a7da847f1202e7bc1672553e68904715e84fd897d529243e3ecda59faa4e17ba99c649a802d53f6b8dfdd51f01fb74 +8b2fb4432c05653303d8c8436473682933a5cb604da10c118ecfcd2c8a0e3132e125afef562bdbcc3df936164e5ce4f2 +808d95762d33ddfa5d0ee3d7d9f327de21a994d681a5f372e2e3632963ea974da7f1f9e5bac8ccce24293509d1f54d27 +932946532e3c397990a1df0e94c90e1e45133e347a39b6714c695be21aeb2d309504cb6b1dde7228ff6f6353f73e1ca2 +9705e7c93f0cdfaa3fa96821f830fe53402ad0806036cd1b48adc2f022d8e781c1fbdab60215ce85c653203d98426da3 +aa180819531c3ec1feb829d789cb2092964c069974ae4faad60e04a6afcce5c3a59aec9f11291e6d110a788d22532bc6 +88f755097f7e25cb7dd3c449520c89b83ae9e119778efabb54fbd5c5714b6f37c5f9e0346c58c6ab09c1aef2483f895d +99fc03ab7810e94104c494f7e40b900f475fde65bdec853e60807ffd3f531d74de43335c3b2646b5b8c26804a7448898 +af2dea9683086bed1a179110efb227c9c00e76cd00a2015b089ccbcee46d1134aa18bda5d6cab6f82ae4c5cd2461ac21 +a500f87ba9744787fdbb8e750702a3fd229de6b8817594348dec9a723b3c4240ddfa066262d002844b9e38240ce55658 +924d0e45c780f5bc1c1f35d15dfc3da28036bdb59e4c5440606750ecc991b85be18bc9a240b6c983bc5430baa4c68287 +865b11e0157b8bf4c5f336024b016a0162fc093069d44ac494723f56648bc4ded13dfb3896e924959ea11c96321afefc +93672d8607d4143a8f7894f1dcca83fb84906dc8d6dd7dd063bb0049cfc20c1efd933e06ca7bd03ea4cb5a5037990bfe +826891efbdff0360446825a61cd1fa04326dd90dae8c33dfb1ed97b045e165766dd070bd7105560994d0b2044bdea418 +93c4a4a8bcbc8b190485cc3bc04175b7c0ed002c28c98a540919effd6ed908e540e6594f6db95cd65823017258fb3b1c +aeb2a0af2d2239fda9aa6b8234b019708e8f792834ff0dd9c487fa09d29800ddceddd6d7929faa9a3edcb9e1b3aa0d6b +87f11de7236d387863ec660d2b04db9ac08143a9a2c4dfff87727c95b4b1477e3bc473a91e5797313c58754905079643 +80dc1db20067a844fe8baceca77f80db171a5ca967acb24e2d480eae9ceb91a3343c31ad1c95b721f390829084f0eae6 +9825c31f1c18da0de3fa84399c8b40f8002c3cae211fb6a0623c76b097b4d39f5c50058f57a16362f7a575909d0a44a2 +a99fc8de0c38dbf7b9e946de83943a6b46a762167bafe2a603fb9b86f094da30d6de7ed55d639aafc91936923ee414b3 +ad594678b407db5d6ea2e90528121f84f2b96a4113a252a30d359a721429857c204c1c1c4ff71d8bb5768c833f82e80e +b33d985e847b54510b9b007e31053732c8a495e43be158bd2ffcea25c6765bcbc7ca815f7c60b36ad088b955dd6e9350 +815f8dfc6f90b3342ca3fbd968c67f324dae8f74245cbf8bc3bef10e9440c65d3a2151f951e8d18959ba01c1b50b0ec1 +94c608a362dd732a1abc56e338637c900d59013db8668e49398b3c7a0cae3f7e2f1d1bf94c0299eeafe6af7f76c88618 +8ebd8446b23e5adfcc393adc5c52fe172f030a73e63cd2d515245ca0dd02782ceed5bcdd9ccd9c1b4c5953dfac9c340c +820437f3f6f9ad0f5d7502815b221b83755eb8dc56cd92c29e9535eb0b48fb8d08c9e4fcc26945f9c8cca60d89c44710 +8910e4e8a56bf4be9cc3bbf0bf6b1182a2f48837a2ed3c2aaec7099bfd7f0c83e14e608876b17893a98021ff4ab2f20d +9633918fde348573eec15ce0ad53ac7e1823aac86429710a376ad661002ae6d049ded879383faaa139435122f64047c6 +a1f5e3fa558a9e89318ca87978492f0fb4f6e54a9735c1b8d2ecfb1d1c57194ded6e0dd82d077b2d54251f3bee1279e1 +b208e22d04896abfd515a95c429ff318e87ff81a5d534c8ac2c33c052d6ffb73ef1dccd39c0bbe0734b596c384014766 +986d5d7d2b5bde6d16336f378bd13d0e671ad23a8ec8a10b3fc09036faeeb069f60662138d7a6df3dfb8e0d36180f770 +a2d4e6c5f5569e9cef1cddb569515d4b6ace38c8aed594f06da7434ba6b24477392cc67ba867c2b079545ca0c625c457 +b5ac32b1d231957d91c8b7fc43115ce3c5c0d8c13ca633374402fa8000b6d9fb19499f9181844f0c10b47357f3f757ce +96b8bf2504b4d28fa34a4ec378e0e0b684890c5f44b7a6bb6e19d7b3db2ab27b1e2686389d1de9fbd981962833a313ea +953bfd7f6c3a0469ad432072b9679a25486f5f4828092401eff494cfb46656c958641a4e6d0d97d400bc59d92dba0030 +876ab3cea7484bbfd0db621ec085b9ac885d94ab55c4bb671168d82b92e609754b86aaf472c55df3d81421d768fd108a +885ff4e67d9ece646d02dd425aa5a087e485c3f280c3471b77532b0db6145b69b0fbefb18aa2e3fa5b64928b43a94e57 +b91931d93f806d0b0e6cc62a53c718c099526140f50f45d94b8bbb57d71e78647e06ee7b42aa5714aed9a5c05ac8533f +a0313eeadd39c720c9c27b3d671215331ab8d0a794e71e7e690f06bcd87722b531d6525060c358f35f5705dbb7109ccb +874c0944b7fedc6701e53344100612ddcb495351e29305c00ec40a7276ea5455465ffb7bded898886c1853139dfb1fc7 +8dc31701a01ee8137059ca1874a015130d3024823c0576aa9243e6942ec99d377e7715ed1444cd9b750a64b85dcaa3e5 +836d2a757405e922ec9a2dfdcf489a58bd48b5f9683dd46bf6047688f778c8dee9bc456de806f70464df0b25f3f3d238 +b30b0a1e454a503ea3e2efdec7483eaf20b0a5c3cefc42069e891952b35d4b2c955cf615f3066285ed8fafd9fcfbb8f6 +8e6d4044b55ab747e83ec8762ea86845f1785cc7be0279c075dadf08aca3ccc5a096c015bb3c3f738f647a4eadea3ba5 +ad7735d16ab03cbe09c029610aa625133a6daecfc990b297205b6da98eda8c136a7c50db90f426d35069708510d5ae9c +8d62d858bbb59ec3c8cc9acda002e08addab4d3ad143b3812098f3d9087a1b4a1bb255dcb1635da2402487d8d0249161 +805beec33238b832e8530645a3254aeef957e8f7ea24bcfc1054f8b9c69421145ebb8f9d893237e8a001c857fedfc77e +b1005644be4b085e3f5775aa9bd3e09a283e87ddada3082c04e7a62d303dcef3b8cf8f92944c200c7ae6bb6bdf63f832 +b4ba0e0790dc29063e577474ffe3b61f5ea2508169f5adc1e394934ebb473e356239413a17962bc3e5d3762d72cce8c2 +a157ba9169c9e3e6748d9f1dd67fbe08b9114ade4c5d8fc475f87a764fb7e6f1d21f66d7905cd730f28a1c2d8378682a +913e52b5c93989b5d15e0d91aa0f19f78d592bc28bcfdfddc885a9980c732b1f4debb8166a7c4083c42aeda93a702898 +90fbfc1567e7cd4e096a38433704d3f96a2de2f6ed3371515ccc30bc4dd0721a704487d25a97f3c3d7e4344472702d8d +89646043028ffee4b69d346907586fd12c2c0730f024acb1481abea478e61031966e72072ff1d5e65cb8c64a69ad4eb1 +b125a45e86117ee11d2fb42f680ab4a7894edd67ff927ae2c808920c66c3e55f6a9d4588eee906f33a05d592e5ec3c04 +aad47f5b41eae9be55fb4f67674ff1e4ae2482897676f964a4d2dcb6982252ee4ff56aac49578b23f72d1fced707525e +b9ddff8986145e33851b4de54d3e81faa3352e8385895f357734085a1616ef61c692d925fe62a5ed3be8ca49f5d66306 +b3cb0963387ed28c0c0adf7fe645f02606e6e1780a24d6cecef5b7c642499109974c81a7c2a198b19862eedcea2c2d8c +ac9c53c885457aaf5cb36c717a6f4077af701e0098eebd7aa600f5e4b14e6c1067255b3a0bc40e4a552025231be7de60 +8e1a8d823c4603f6648ec21d064101094f2a762a4ed37dd2f0a2d9aa97b2d850ce1e76f4a4b8cae58819b058180f7031 +b268b73bf7a179b6d22bd37e5e8cb514e9f5f8968c78e14e4f6d5700ca0d0ca5081d0344bb73b028970eebde3cb4124e +a7f57d71940f0edbd29ed8473d0149cae71d921dd15d1ff589774003e816b54b24de2620871108cec1ab9fa956ad6ce6 +8053e6416c8b120e2b999cc2fc420a6a55094c61ac7f2a6c6f0a2c108a320890e389af96cbe378936132363c0d551277 +b3823f4511125e5aa0f4269e991b435a0d6ceb523ebd91c04d7add5534e3df5fc951c504b4fd412a309fd3726b7f940b +ae6eb04674d04e982ca9a6add30370ab90e303c71486f43ed3efbe431af1b0e43e9d06c11c3412651f304c473e7dbf39 +96ab55e641ed2e677591f7379a3cd126449614181fce403e93e89b1645d82c4af524381ff986cae7f9cebe676878646d +b52423b4a8c37d3c3e2eca8f0ddbf7abe0938855f33a0af50f117fab26415fb0a3da5405908ec5fdc22a2c1f2ca64892 +82a69ce1ee92a09cc709d0e3cd22116c9f69d28ea507fe5901f5676000b5179b9abe4c1875d052b0dd42d39925e186bb +a84c8cb84b9d5cfb69a5414f0a5283a5f2e90739e9362a1e8c784b96381b59ac6c18723a4aa45988ee8ef5c1f45cc97d +afd7efce6b36813082eb98257aae22a4c1ae97d51cac7ea9c852d4a66d05ef2732116137d8432e3f117119725a817d24 +a0f5fe25af3ce021b706fcff05f3d825384a272284d04735574ce5fb256bf27100fad0b1f1ba0e54ae9dcbb9570ecad3 +8751786cb80e2e1ff819fc7fa31c2833d25086534eb12b373d31f826382430acfd87023d2a688c65b5e983927e146336 +8cf5c4b17fa4f3d35c78ce41e1dc86988fd1135cd5e6b2bb0c108ee13538d0d09ae7102609c6070f39f937b439b31e33 +a9108967a2fedd7c322711eca8159c533dd561bedcb181b646de98bf5c3079449478eab579731bee8d215ae8852c7e21 +b54c5171704f42a6f0f4e70767cdb3d96ffc4888c842eece343a01557da405961d53ffdc34d2f902ea25d3e1ed867cad +ae8d4b764a7a25330ba205bf77e9f46182cd60f94a336bbd96773cf8064e3d39caf04c310680943dc89ed1fbad2c6e0d +aa5150e911a8e1346868e1b71c5a01e2a4bb8632c195861fb6c3038a0e9b85f0e09b3822e9283654a4d7bb17db2fc5f4 +9685d3756ce9069bf8bb716cf7d5063ebfafe37e15b137fc8c3159633c4e006ff4887ddd0ae90360767a25c3f90cba7f +82155fd70f107ab3c8e414eadf226c797e07b65911508c76c554445422325e71af8c9a8e77fd52d94412a6fc29417cd3 +abfae52f53a4b6e00760468d973a267f29321997c3dbb5aee36dc1f20619551229c0c45b9d9749f410e7f531b73378e8 +81a76d921f8ef88e774fd985e786a4a330d779b93fad7def718c014685ca0247379e2e2a007ad63ee7f729cd9ed6ce1b +81947c84bc5e28e26e2e533af5ae8fe10407a7b77436dbf8f1d5b0bbe86fc659eae10f974659dc7c826c6dabd03e3a4b +92b8c07050d635b8dd4fd09df9054efe4edae6b86a63c292e73cc819a12a21dd7d104ce51fa56af6539dedf6dbe6f7b6 +b44c579e3881f32b32d20c82c207307eca08e44995dd2aac3b2692d2c8eb2a325626c80ac81c26eeb38c4137ff95add5 +97efab8941c90c30860926dea69a841f2dcd02980bf5413b9fd78d85904588bf0c1021798dbc16c8bbb32cce66c82621 +913363012528b50698e904de0588bf55c8ec5cf6f0367cfd42095c4468fcc64954fbf784508073e542fee242d0743867 +8ed203cf215148296454012bd10fddaf119203db1919a7b3d2cdc9f80e66729464fdfae42f1f2fc5af1ed53a42b40024 +ab84312db7b87d711e9a60824f4fe50e7a6190bf92e1628688dfcb38930fe87b2d53f9e14dd4de509b2216856d8d9188 +880726def069c160278b12d2258eac8fa63f729cd351a710d28b7e601c6712903c3ac1e7bbd0d21e4a15f13ca49db5aa +980699cd51bac6283959765f5174e543ed1e5f5584b5127980cbc2ef18d984ecabba45042c6773b447b8e694db066028 +aeb019cb80dc4cb4207430d0f2cd24c9888998b6f21d9bf286cc638449668d2eec0018a4cf3fe6448673cd6729335e2b +b29852f6aa6c60effdffe96ae88590c88abae732561d35cc19e82d3a51e26cb35ea00986193e07f90060756240f5346e +a0fa855adc5ba469f35800c48414b8921455950a5c0a49945d1ef6e8f2a1881f2e2dfae47de6417270a6bf49deeb091d +b6c7332e3b14813641e7272d4f69ecc7e09081df0037d6dab97ce13a9e58510f5c930d300633f208181d9205c5534001 +85a6c050f42fce560b5a8d54a11c3bbb8407abbadd859647a7b0c21c4b579ec65671098b74f10a16245dc779dff7838e +8f3eb34bb68759d53c6677de4de78a6c24dd32c8962a7fb355ed362572ef8253733e6b52bc21c9f92ecd875020a9b8de +a17dd44181e5dab4dbc128e1af93ec22624b57a448ca65d2d9e246797e4af7d079e09c6e0dfb62db3a9957ce92f098d5 +a56a1b854c3183082543a8685bb34cae1289f86cfa8123a579049dbd059e77982886bfeb61bf6e05b4b1fe4e620932e7 +aedae3033cb2fb7628cb4803435bdd7757370a86f808ae4cecb9a268ad0e875f308c048c80cbcac523de16b609683887 +9344905376aa3982b1179497fac5a1d74b14b7038fd15e3b002db4c11c8bfc7c39430db492cdaf58b9c47996c9901f28 +a3bfafdae011a19f030c749c3b071f83580dee97dd6f949e790366f95618ca9f828f1daaeabad6dcd664fcef81b6556d +81c03d8429129e7e04434dee2c529194ddb01b414feda3adee2271eb680f6c85ec872a55c9fa9d2096f517e13ed5abcc +98205ef3a72dff54c5a9c82d293c3e45d908946fa74bb749c3aabe1ab994ea93c269bcce1a266d2fe67a8f02133c5985 +85a70aeed09fda24412fadbafbbbf5ba1e00ac92885df329e147bfafa97b57629a3582115b780d8549d07d19b7867715 +b0fbe81c719f89a57d9ea3397705f898175808c5f75f8eb81c2193a0b555869ba7bd2e6bc54ee8a60cea11735e21c68c +b03a0bd160495ee626ff3a5c7d95bc79d7da7e5a96f6d10116600c8fa20bedd1132f5170f25a22371a34a2d763f2d6d0 +a90ab04091fbca9f433b885e6c1d60ab45f6f1daf4b35ec22b09909d493a6aab65ce41a6f30c98239cbca27022f61a8b +b66f92aa3bf2549f9b60b86f99a0bd19cbdd97036d4ae71ca4b83d669607f275260a497208f6476cde1931d9712c2402 +b08e1fdf20e6a9b0b4942f14fa339551c3175c1ffc5d0ab5b226b6e6a322e9eb0ba96adc5c8d59ca4259e2bdd04a7eb0 +a2812231e92c1ce74d4f5ac3ab6698520288db6a38398bb38a914ac9326519580af17ae3e27cde26607e698294022c81 +abfcbbcf1d3b9e84c02499003e490a1d5d9a2841a9e50c7babbef0b2dd20d7483371d4dc629ba07faf46db659459d296 +b0fe9f98c3da70927c23f2975a9dc4789194d81932d2ad0f3b00843dd9cbd7fb60747a1da8fe5a79f136a601becf279d +b130a6dba7645165348cb90f023713bed0eefbd90a976b313521c60a36d34f02032e69a2bdcf5361e343ed46911297ec +862f0cffe3020cea7a5fd4703353aa1eb1be335e3b712b29d079ff9f7090d1d8b12013011e1bdcbaa80c44641fd37c9f +8c6f11123b26633e1abb9ed857e0bce845b2b3df91cc7b013b2fc77b477eee445da0285fc6fc793e29d5912977f40916 +91381846126ea819d40f84d3005e9fb233dc80071d1f9bb07f102bf015f813f61e5884ffffb4f5cd333c1b1e38a05a58 +8add7d908de6e1775adbd39c29a391f06692b936518db1f8fde74eb4f533fc510673a59afb86e3a9b52ade96e3004c57 +8780e086a244a092206edcde625cafb87c9ab1f89cc3e0d378bc9ee776313836160960a82ec397bc3800c0a0ec3da283 +a6cb4cd9481e22870fdd757fae0785edf4635e7aacb18072fe8dc5876d0bab53fb99ce40964a7d3e8bcfff6f0ab1332f +af30ff47ecc5b543efba1ba4706921066ca8bb625f40e530fb668aea0551c7647a9d126e8aba282fbcce168c3e7e0130 +91b0bcf408ce3c11555dcb80c4410b5bc2386d3c05caec0b653352377efdcb6bab4827f2018671fc8e4a0e90d772acc1 +a9430b975ef138b6b2944c7baded8fe102d31da4cfe3bd3d8778bda79189c99d38176a19c848a19e2d1ee0bddd9a13c1 +aa5a4eef849d7c9d2f4b018bd01271c1dd83f771de860c4261f385d3bdcc130218495860a1de298f14b703ec32fa235f +b0ce79e7f9ae57abe4ff366146c3b9bfb38b0dee09c28c28f5981a5d234c6810ad4d582751948affb480d6ae1c8c31c4 +b75122748560f73d15c01a8907d36d06dc068e82ce22b84b322ac1f727034493572f7907dec34ebc3ddcc976f2f89ed7 +b0fc7836369a3e4411d34792d6bd5617c14f61d9bba023dda64e89dc5fb0f423244e9b48ee64869258931daa9753a56f +8956d7455ae9009d70c6e4a0bcd7610e55f37494cf9897a8f9e1b904cc8febc3fd2d642ebd09025cfff4609ad7e3bc52 +ad741efe9e472026aa49ae3d9914cb9c1a6f37a54f1a6fe6419bebd8c7d68dca105a751c7859f4389505ede40a0de786 +b52f418797d719f0d0d0ffb0846788b5cba5d0454a69a2925de4b0b80fa4dd7e8c445e5eac40afd92897ed28ca650566 +a0ab65fb9d42dd966cd93b1de01d7c822694669dd2b7a0c04d99cd0f3c3de795f387b9c92da11353412f33af5c950e9a +a0052f44a31e5741a331f7cac515a08b3325666d388880162d9a7b97598fde8b61f9ff35ff220df224eb5c4e40ef0567 +a0101cfdc94e42b2b976c0d89612a720e55d145a5ef6ef6f1f78cf6de084a49973d9b5d45915349c34ce712512191e3c +a0dd99fcf3f5cead5aaf08e82212df3a8bb543c407a4d6fab88dc5130c1769df3f147e934a46f291d6c1a55d92b86917 +a5939153f0d1931bbda5cf6bdf20562519ea55fbfa978d6dbc6828d298260c0da7a50c37c34f386e59431301a96c2232 +9568269f3f5257200f9ca44afe1174a5d3cf92950a7f553e50e279c239e156a9faaa2a67f288e3d5100b4142efe64856 +b746b0832866c23288e07f24991bbf687cad794e7b794d3d3b79367566ca617d38af586cdc8d6f4a85a34835be41d54f +a871ce28e39ab467706e32fec1669fda5a4abba2f8c209c6745df9f7a0fa36bbf1919cf14cb89ea26fa214c4c907ae03 +a08dacdd758e523cb8484f6bd070642c0c20e184abdf8e2a601f61507e93952d5b8b0c723c34fcbdd70a8485eec29db2 +85bdb78d501382bb95f1166b8d032941005661aefd17a5ac32df9a3a18e9df2fc5dc2c1f07075f9641af10353cecc0c9 +98d730c28f6fa692a389e97e368b58f4d95382fad8f0baa58e71a3d7baaea1988ead47b13742ce587456f083636fa98e +a557198c6f3d5382be9fb363feb02e2e243b0c3c61337b3f1801c4a0943f18e38ce1a1c36b5c289c8fa2aa9d58742bab +89174f79201742220ac689c403fc7b243eed4f8e3f2f8aba0bf183e6f5d4907cb55ade3e238e3623d9885f03155c4d2b +b891d600132a86709e06f3381158db300975f73ea4c1f7c100358e14e98c5fbe792a9af666b85c4e402707c3f2db321e +b9e5b2529ef1043278c939373fc0dbafe446def52ddd0a8edecd3e4b736de87e63e187df853c54c28d865de18a358bb6 +8589b2e9770340c64679062c5badb7bbef68f55476289b19511a158a9a721f197da03ece3309e059fc4468b15ac33aa3 +aad8c6cd01d785a881b446f06f1e9cd71bca74ba98674c2dcddc8af01c40aa7a6d469037498b5602e76e9c91a58d3dbd +abaccb1bd918a8465f1bf8dbe2c9ad4775c620b055550b949a399f30cf0d9eb909f3851f5b55e38f9e461e762f88f499 +ae62339d26db46e85f157c0151bd29916d5cc619bd4b832814b3fd2f00af8f38e7f0f09932ffe5bba692005dab2d9a74 +93a6ff30a5c0edf8058c89aba8c3259e0f1b1be1b80e67682de651e5346f7e1b4b4ac3d87cbaebf198cf779524aff6bf +8980a2b1d8f574af45b459193c952400b10a86122b71fca2acb75ee0dbd492e7e1ef5b959baf609a5172115e371f3177 +8c2f49f3666faee6940c75e8c7f6f8edc3f704cca7a858bbb7ee5e96bba3b0cf0993996f781ba6be3b0821ef4cb75039 +b14b9e348215b278696018330f63c38db100b0542cfc5be11dc33046e3bca6a13034c4ae40d9cef9ea8b34fef0910c4e +b59bc3d0a30d66c16e6a411cb641f348cb1135186d5f69fda8b0a0934a5a2e7f6199095ba319ec87d3fe8f1ec4a06368 +8874aca2a3767aa198e4c3fec2d9c62d496bc41ff71ce242e9e082b7f38cdf356089295f80a301a3cf1182bde5308c97 +b1820ebd61376d91232423fc20bf008b2ba37e761199f4ef0648ea2bd70282766799b4de814846d2f4d516d525c8daa7 +a6b202e5dedc16a4073e04a11af3a8509b23dfe5a1952f899adeb240e75c3f5bde0c424f811a81ea48d343591faffe46 +a69becee9c93734805523b92150a59a62eed4934f66056b645728740d42223f2925a1ad38359ba644da24d9414f4cdda +ad72f0f1305e37c7e6b48c272323ee883320994cb2e0d850905d6655fafc9f361389bcb9c66b3ff8d2051dbb58c8aa96 +b563600bd56fad7c8853af21c6a02a16ed9d8a8bbeea2c31731d63b976d83cb05b9779372d898233e8fd597a75424797 +b0abb78ce465bf7051f563c62e8be9c57a2cc997f47c82819300f36e301fefd908894bb2053a9d27ce2d0f8c46d88b5b +a071a85fb8274bac2202e0cb8e0e2028a5e138a82d6e0374d39ca1884a549c7c401312f00071b91f455c3a2afcfe0cda +b931c271513a0f267b9f41444a5650b1918100b8f1a64959c552aff4e2193cc1b9927906c6fa7b8a8c68ef13d79aaa52 +a6a1bb9c7d32cb0ca44d8b75af7e40479fbce67d216b48a2bb680d3f3a772003a49d3cd675fc64e9e0f8fabeb86d6d61 +b98d609858671543e1c3b8564162ad828808bb50ded261a9f8690ded5b665ed8368c58f947365ed6e84e5a12e27b423d +b3dca58cd69ec855e2701a1d66cad86717ff103ef862c490399c771ad28f675680f9500cb97be48de34bcdc1e4503ffd +b34867c6735d3c49865e246ddf6c3b33baf8e6f164db3406a64ebce4768cb46b0309635e11be985fee09ab7a31d81402 +acb966c554188c5b266624208f31fab250b3aa197adbdd14aee5ab27d7fb886eb4350985c553b20fdf66d5d332bfd3fe +943c36a18223d6c870d54c3b051ef08d802b85e9dd6de37a51c932f90191890656c06adfa883c87b906557ae32d09da0 +81bca7954d0b9b6c3d4528aadf83e4bc2ef9ea143d6209bc45ae9e7ae9787dbcd8333c41f12c0b6deee8dcb6805e826a +aba176b92256efb68f574e543479e5cf0376889fb48e3db4ebfb7cba91e4d9bcf19dcfec444c6622d9398f06de29e2b9 +b9f743691448053216f6ece7cd699871fff4217a1409ceb8ab7bdf3312d11696d62c74b0664ba0a631b1e0237a8a0361 +a383c2b6276fa9af346b21609326b53fb14fdf6f61676683076e80f375b603645f2051985706d0401e6fbed7eb0666b6 +a9ef2f63ec6d9beb8f3d04e36807d84bda87bdd6b351a3e4a9bf7edcb5618c46c1f58cfbf89e64b40f550915c6988447 +a141b2d7a82f5005eaea7ae7d112c6788b9b95121e5b70b7168d971812f3381de8b0082ac1f0a82c7d365922ebd2d26a +b1b76ef8120e66e1535c17038b75255a07849935d3128e3e99e56567b842fb1e8d56ef932d508d2fb18b82f7868fe1a9 +8e2e234684c81f21099f5c54f6bbe2dd01e3b172623836c77668a0c49ce1fe218786c3827e4d9ae2ea25c50a8924fb3c +a5caf5ff948bfd3c4ca3ffbdfcd91eec83214a6c6017235f309a0bbf7061d3b0b466307c00b44a1009cf575163898b43 +986415a82ca16ebb107b4c50b0c023c28714281db0bcdab589f6cb13d80e473a3034b7081b3c358e725833f6d845cb14 +b94836bf406ac2cbacb10e6df5bcdfcc9d9124ae1062767ca4e322d287fd5e353fdcebd0e52407cb3cd68571258a8900 +83c6d70a640b33087454a4788dfd9ef3ed00272da084a8d36be817296f71c086b23b576f98178ab8ca6a74f04524b46b +ad4115182ad784cfe11bcfc5ce21fd56229cc2ce77ac82746e91a2f0aa53ca6593a22efd2dc4ed8d00f84542643d9c58 +ab1434c5e5065da826d10c2a2dba0facccab0e52b506ce0ce42fbe47ced5a741797151d9ecc99dc7d6373cfa1779bbf6 +8a8b591d82358d55e6938f67ea87a89097ab5f5496f7260adb9f649abb289da12b498c5b2539c2f9614fb4e21b1f66b0 +964f355d603264bc1f44c64d6d64debca66f37dff39c971d9fc924f2bc68e6c187b48564a6dc82660a98b035f8addb5d +b66235eaaf47456bc1dc4bde454a028e2ce494ece6b713a94cd6bf27cf18c717fd0c57a5681caaa2ad73a473593cdd7a +9103e3bb74304186fa4e3e355a02da77da4aca9b7e702982fc2082af67127ebb23a455098313c88465bc9b7d26820dd5 +b6a42ff407c9dd132670cdb83cbad4b20871716e44133b59a932cd1c3f97c7ac8ff7f61acfaf8628372508d8dc8cad7c +883a9c21c16a167a4171b0f084565c13b6f28ba7c4977a0de69f0a25911f64099e7bbb4da8858f2e93068f4155d04e18 +8dbb3220abc6a43220adf0331e3903d3bfd1d5213aadfbd8dfcdf4b2864ce2e96a71f35ecfb7a07c3bbabf0372b50271 +b4ad08aee48e176bda390b7d9acf2f8d5eb008f30d20994707b757dc6a3974b2902d29cd9b4d85e032810ad25ac49e97 +865bb0f33f7636ec501bb634e5b65751c8a230ae1fa807a961a8289bbf9c7fe8c59e01fbc4c04f8d59b7f539cf79ddd5 +86a54d4c12ad1e3605b9f93d4a37082fd26e888d2329847d89afa7802e815f33f38185c5b7292293d788ad7d7da1df97 +b26c8615c5e47691c9ff3deca3021714662d236c4d8401c5d27b50152ce7e566266b9d512d14eb63e65bc1d38a16f914 +827639d5ce7db43ba40152c8a0eaad443af21dc92636cc8cc2b35f10647da7d475a1e408901cd220552fddad79db74df +a2b79a582191a85dbe22dc384c9ca3de345e69f6aa370aa6d3ff1e1c3de513e30b72df9555b15a46586bd27ea2854d9d +ae0d74644aba9a49521d3e9553813bcb9e18f0b43515e4c74366e503c52f47236be92dfbd99c7285b3248c267b1de5a0 +80fb0c116e0fd6822a04b9c25f456bdca704e2be7bdc5d141dbf5d1c5eeb0a2c4f5d80db583b03ef3e47517e4f9a1b10 +ac3a1fa3b4a2f30ea7e0a114cdc479eb51773573804c2a158d603ad9902ae8e39ffe95df09c0d871725a5d7f9ba71a57 +b56b2b0d601cba7f817fa76102c68c2e518c6f20ff693aad3ff2e07d6c4c76203753f7f91686b1801e8c4659e4d45c48 +89d50c1fc56e656fb9d3915964ebce703cb723fe411ab3c9eaa88ccc5d2b155a9b2e515363d9c600d3c0cee782c43f41 +b24207e61462f6230f3cd8ccf6828357d03e725769f7d1de35099ef9ee4dca57dbce699bb49ed994462bee17059d25ce +b886f17fcbcbfcd08ac07f04bb9543ef58510189decaccea4b4158c9174a067cb67d14b6be3c934e6e2a18c77efa9c9c +b9c050ad9cafd41c6e2e192b70d080076eed59ed38ea19a12bd92fa17b5d8947d58d5546aaf5e8e27e1d3b5481a6ce51 +aaf7a34d3267e3b1ddbc54c641e3922e89303f7c86ebebc7347ebca4cffad5b76117dac0cbae1a133053492799cd936f +a9ee604ada50adef82e29e893070649d2d4b7136cc24fa20e281ce1a07bd736bf0de7c420369676bcbcecff26fb6e900 +9855315a12a4b4cf80ab90b8bd13003223ba25206e52fd4fe6a409232fbed938f30120a3db23eab9c53f308bd8b9db81 +8cd488dd7a24f548a3cf03c54dec7ff61d0685cb0f6e5c46c2d728e3500d8c7bd6bba0156f4bf600466fda53e5b20444 +890ad4942ebac8f5b16c777701ab80c68f56fa542002b0786f8fea0fb073154369920ac3dbfc07ea598b82f4985b8ced +8de0cf9ddc84c9b92c59b9b044387597799246b30b9f4d7626fc12c51f6e423e08ee4cbfe9289984983c1f9521c3e19d +b474dfb5b5f4231d7775b3c3a8744956b3f0c7a871d835d7e4fd9cc895222c7b868d6c6ce250de568a65851151fac860 +86433b6135d9ed9b5ee8cb7a6c40e5c9d30a68774cec04988117302b8a02a11a71a1e03fd8e0264ef6611d219f103007 +80b9ed4adbe9538fb1ef69dd44ec0ec5b57cbfea820054d8d445b4261962624b4c70ac330480594bc5168184378379c3 +8b2e83562ccd23b7ad2d17f55b1ab7ef5fbef64b3a284e6725b800f3222b8bdf49937f4a873917ada9c4ddfb090938c2 +abe78cebc0f5a45d754140d1f685e387489acbfa46d297a8592aaa0d676a470654f417a4f7d666fc0b2508fab37d908e +a9c5f8ff1f8568e252b06d10e1558326db9901840e6b3c26bbd0cd5e850cb5fb3af3f117dbb0f282740276f6fd84126f +975f8dc4fb55032a5df3b42b96c8c0ffecb75456f01d4aef66f973cb7270d4eff32c71520ceefc1adcf38d77b6b80c67 +b043306ed2c3d8a5b9a056565afd8b5e354c8c4569fda66b0d797a50a3ce2c08cffbae9bbe292da69f39e89d5dc7911e +8d2afc36b1e44386ba350c14a6c1bb31ff6ea77128a0c5287584ac3584282d18516901ce402b4644a53db1ed8e7fa581 +8c294058bed53d7290325c363fe243f6ec4f4ea2343692f4bac8f0cb86f115c069ccb8334b53d2e42c067691ad110dba +b92157b926751aaf7ef82c1aa8c654907dccab6376187ee8b3e8c0c82811eae01242832de953faa13ebaff7da8698b3e +a780c4bdd9e4ba57254b09d745075cecab87feda78c88ffee489625c5a3cf96aa6b3c9503a374a37927d9b78de9bd22b +811f548ef3a2e6a654f7dcb28ac9378de9515ed61e5a428515d9594a83e80b35c60f96a5cf743e6fab0d3cb526149f49 +85a4dccf6d90ee8e094731eec53bd00b3887aec6bd81a0740efddf812fd35e3e4fe4f983afb49a8588691c202dabf942 +b152c2da6f2e01c8913079ae2b40a09b1f361a80f5408a0237a8131b429677c3157295e11b365b1b1841924b9efb922e +849b9efee8742502ffd981c4517c88ed33e4dd518a330802caff168abae3cd09956a5ee5eda15900243bc2e829016b74 +955a933f3c18ec0f1c0e38fa931e4427a5372c46a3906ebe95082bcf878c35246523c23f0266644ace1fa590ffa6d119 +911989e9f43e580c886656377c6f856cdd4ff1bd001b6db3bbd86e590a821d34a5c6688a29b8d90f28680e9fdf03ba69 +b73b8b4f1fd6049fb68d47cd96a18fcba3f716e0a1061aa5a2596302795354e0c39dea04d91d232aec86b0bf2ba10522 +90f87456d9156e6a1f029a833bf3c7dbed98ca2f2f147a8564922c25ae197a55f7ea9b2ee1f81bf7383197c4bad2e20c +903cba8b1e088574cb04a05ca1899ab00d8960580c884bd3c8a4c98d680c2ad11410f2b75739d6050f91d7208cac33a5 +9329987d42529c261bd15ecedd360be0ea8966e7838f32896522c965adfc4febf187db392bd441fb43bbd10c38fdf68b +8178ee93acf5353baa349285067b20e9bb41aa32d77b5aeb7384fe5220c1fe64a2461bd7a83142694fe673e8bbf61b7c +a06a8e53abcff271b1394bcc647440f81fb1c1a5f29c27a226e08f961c3353f4891620f2d59b9d1902bf2f5cc07a4553 +aaf5fe493b337810889e777980e6bbea6cac39ac66bc0875c680c4208807ac866e9fda9b5952aa1d04539b9f4a4bec57 +aa058abb1953eceac14ccfa7c0cc482a146e1232905dcecc86dd27f75575285f06bbae16a8c9fe8e35d8713717f5f19f +8f15dd732799c879ca46d2763453b359ff483ca33adb1d0e0a57262352e0476c235987dc3a8a243c74bc768f93d3014c +a61cc8263e9bc03cce985f1663b8a72928a607121005a301b28a278e9654727fd1b22bc8a949af73929c56d9d3d4a273 +98d6dc78502d19eb9f921225475a6ebcc7b44f01a2df6f55ccf6908d65b27af1891be2a37735f0315b6e0f1576c1f8d8 +8bd258b883f3b3793ec5be9472ad1ff3dc4b51bc5a58e9f944acfb927349ead8231a523cc2175c1f98e7e1e2b9f363b8 +aeacc2ecb6e807ad09bedd99654b097a6f39840e932873ace02eabd64ccfbb475abdcb62939a698abf17572d2034c51e +b8ccf78c08ccd8df59fd6eda2e01de328bc6d8a65824d6f1fc0537654e9bc6bf6f89c422dd3a295cce628749da85c864 +8f91fd8cb253ba2e71cc6f13da5e05f62c2c3b485c24f5d68397d04665673167fce1fc1aec6085c69e87e66ec555d3fd +a254baa10cb26d04136886073bb4c159af8a8532e3fd36b1e9c3a2e41b5b2b6a86c4ebc14dbe624ee07b7ccdaf59f9ab +94e3286fe5cd68c4c7b9a7d33ae3d714a7f265cf77cd0e9bc19fc51015b1d1c34ad7e3a5221c459e89f5a043ee84e3a9 +a279da8878af8d449a9539bec4b17cea94f0242911f66fab275b5143ab040825f78c89cb32a793930609415cfa3a1078 +ac846ceb89c9e5d43a2991c8443079dc32298cd63e370e64149cec98cf48a6351c09c856f2632fd2f2b3d685a18bbf8b +a847b27995c8a2e2454aaeb983879fb5d3a23105c33175839f7300b7e1e8ec3efd6450e9fa3f10323609dee7b98c6fd5 +a2f432d147d904d185ff4b2de8c6b82fbea278a2956bc406855b44c18041854c4f0ecccd472d1d0dff1d8aa8e281cb1d +94a48ad40326f95bd63dff4755f863a1b79e1df771a1173b17937f9baba57b39e651e7695be9f66a472f098b339364fc +a12a0ccd8f96e96e1bc6494341f7ebce959899341b3a084aa1aa87d1c0d489ac908552b7770b887bb47e7b8cbc3d8e66 +81a1f1681bda923bd274bfe0fbb9181d6d164fe738e54e25e8d4849193d311e2c4253614ed673c98af2c798f19a93468 +abf71106a05d501e84cc54610d349d7d5eae21a70bd0250f1bebbf412a130414d1c8dbe673ffdb80208fd72f1defa4d4 +96266dc2e0df18d8136d79f5b59e489978eee0e6b04926687fe389d4293c14f36f055c550657a8e27be4118b64254901 +8df5dcbefbfb4810ae3a413ca6b4bf08619ca53cd50eb1dde2a1c035efffc7b7ac7dff18d403253fd80104bd83dc029e +9610b87ff02e391a43324a7122736876d5b3af2a137d749c52f75d07b17f19900b151b7f439d564f4529e77aa057ad12 +a90a5572198b40fe2fcf47c422274ff36c9624df7db7a89c0eb47eb48a73a03c985f4ac5016161c76ca317f64339bce1 +98e5e61a6ab6462ba692124dba7794b6c6bde4249ab4fcc98c9edd631592d5bc2fb5e38466691a0970a38e48d87c2e43 +918cefb8f292f78d4db81462c633daf73b395e772f47b3a7d2cea598025b1d8c3ec0cbff46cdb23597e74929981cde40 +a98918a5dc7cf610fe55f725e4fd24ce581d594cb957bb9b4e888672e9c0137003e1041f83e3f1d7b9caab06462c87d4 +b92b74ac015262ca66c33f2d950221e19d940ba3bf4cf17845f961dc1729ae227aa9e1f2017829f2135b489064565c29 +a053ee339f359665feb178b4e7ee30a85df37debd17cacc5a27d6b3369d170b0114e67ad1712ed26d828f1df641bcd99 +8c3c8bad510b35da5ce5bd84b35c958797fbea024ad1c97091d2ff71d9b962e9222f65a9b776e5b3cc29c36e1063d2ee +af99dc7330fe7c37e850283eb47cc3257888e7c197cb0d102edf94439e1e02267b6a56306d246c326c4c79f9dc8c6986 +afecb2dc34d57a725efbd7eb93d61eb29dbe8409b668ab9ea040791f5b796d9be6d4fc10d7f627bf693452f330cf0435 +93334fedf19a3727a81a6b6f2459db859186227b96fe7a391263f69f1a0884e4235de64d29edebc7b99c44d19e7c7d7a +89579c51ac405ad7e9df13c904061670ce4b38372492764170e4d3d667ed52e5d15c7cd5c5991bbfa3a5e4e3fa16363e +9778f3e8639030f7ef1c344014f124e375acb8045bd13d8e97a92c5265c52de9d1ffebaa5bc3e1ad2719da0083222991 +88f77f34ee92b3d36791bdf3326532524a67d544297dcf1a47ff00b47c1b8219ff11e34034eab7d23b507caa2fd3c6b9 +a699c1e654e7c484431d81d90657892efeb4adcf72c43618e71ca7bd7c7a7ebbb1db7e06e75b75dc4c74efd306b5df3f +81d13153baebb2ef672b5bdb069d3cd669ce0be96b742c94e04038f689ff92a61376341366b286eee6bf3ae85156f694 +81efb17de94400fdacc1deec2550cbe3eecb27c7af99d8207e2f9be397e26be24a40446d2a09536bb5172c28959318d9 +989b21ebe9ceab02488992673dc071d4d5edec24bff0e17a4306c8cb4b3c83df53a2063d1827edd8ed16d6e837f0d222 +8d6005d6536825661b13c5fdce177cb37c04e8b109b7eb2b6d82ea1cb70efecf6a0022b64f84d753d165edc2bba784a3 +a32607360a71d5e34af2271211652d73d7756d393161f4cf0da000c2d66a84c6826e09e759bd787d4fd0305e2439d342 +aaad8d6f6e260db45d51b2da723be6fa832e76f5fbcb77a9a31e7f090dd38446d3b631b96230d78208cae408c288ac4e +abcfe425255fd3c5cffd3a818af7650190c957b6b07b632443f9e33e970a8a4c3bf79ac9b71f4d45f238a04d1c049857 +aeabf026d4c783adc4414b5923dbd0be4b039cc7201219f7260d321f55e9a5b166d7b5875af6129c034d0108fdc5d666 +af49e740c752d7b6f17048014851f437ffd17413c59797e5078eaaa36f73f0017c3e7da020310cfe7d3c85f94a99f203 +8854ca600d842566e3090040cd66bb0b3c46dae6962a13946f0024c4a8aca447e2ccf6f240045f1ceee799a88cb9210c +b6c03b93b1ab1b88ded8edfa1b487a1ed8bdce8535244dddb558ffb78f89b1c74058f80f4db2320ad060d0c2a9c351cc +b5bd7d17372faff4898a7517009b61a7c8f6f0e7ed4192c555db264618e3f6e57fb30a472d169fea01bf2bf0362a19a8 +96eb1d38319dc74afe7e7eb076fcd230d19983f645abd14a71e6103545c01301b31c47ae931e025f3ecc01fb3d2f31fa +b55a8d30d4403067def9b65e16f867299f8f64c9b391d0846d4780bc196569622e7e5b64ce799b5aefac8f965b2a7a7b +8356d199a991e5cbbff608752b6291731b6b6771aed292f8948b1f41c6543e4ab1bedc82dd26d10206c907c03508df06 +97f4137445c2d98b0d1d478049de952610ad698c91c9d0f0e7227d2aae690e9935e914ec4a2ea1fbf3fc1dddfeeacebb +af5621707e0938320b15ddfc87584ab325fbdfd85c30efea36f8f9bd0707d7ec12c344eff3ec21761189518d192df035 +8ac7817e71ea0825b292687928e349da7140285d035e1e1abff0c3704fa8453faaae343a441b7143a74ec56539687cc4 +8a5e0a9e4758449489df10f3386029ada828d1762e4fb0a8ffe6b79e5b6d5d713cb64ed95960e126398b0cdb89002bc9 +81324be4a71208bbb9bca74b77177f8f1abb9d3d5d9db195d1854651f2cf333cd618d35400da0f060f3e1b025124e4b2 +849971d9d095ae067525b3cbc4a7dfae81f739537ade6d6cec1b42fb692d923176197a8770907c58069754b8882822d6 +89f830825416802477cc81fdf11084885865ee6607aa15aa4eb28e351c569c49b8a1b9b5e95ddc04fa0ebafe20071313 +9240aeeaff37a91af55f860b9badd466e8243af9e8c96a7aa8cf348cd270685ab6301bc135b246dca9eda696f8b0e350 +acf74db78cc33138273127599eba35b0fb4e7b9a69fe02dae18fc6692d748ca332bd00b22afa8e654ed587aab11833f3 +b091e6d37b157b50d76bd297ad752220cd5c9390fac16dc838f8557aed6d9833fc920b61519df21265406216315e883f +a6446c429ebf1c7793c622250e23594c836b2fbcaf6c5b3d0995e1595a37f50ea643f3e549b0be8bbdadd69044d72ab9 +93e675353bd60e996bf1c914d5267eeaa8a52fc3077987ccc796710ef9becc6b7a00e3d82671a6bdfb8145ee3c80245a +a2f731e43251d04ed3364aa2f072d05355f299626f2d71a8a38b6f76cf08c544133f7d72dd0ab4162814b674b9fc7fa6 +97a8b791a5a8f6e1d0de192d78615d73d0c38f1e557e4e15d15adc663d649e655bc8da3bcc499ef70112eafe7fb45c7a +98cd624cbbd6c53a94469be4643c13130916b91143425bcb7d7028adbbfede38eff7a21092af43b12d4fab703c116359 +995783ce38fd5f6f9433027f122d4cf1e1ff3caf2d196ce591877f4a544ce9113ead60de2de1827eaff4dd31a20d79a8 +8cf251d6f5229183b7f3fe2f607a90b4e4b6f020fb4ba2459d28eb8872426e7be8761a93d5413640a661d73e34a5b81f +b9232d99620652a3aa7880cad0876f153ff881c4ed4c0c2e7b4ea81d5d42b70daf1a56b869d752c3743c6d4c947e6641 +849716f938f9d37250cccb1bf77f5f9fde53096cdfc6f2a25536a6187029a8f1331cdbed08909184b201f8d9f04b792f +80c7c4de098cbf9c6d17b14eba1805e433b5bc905f6096f8f63d34b94734f2e4ebf4bce8a177efd1186842a61204a062 +b790f410cf06b9b8daadceeb4fd5ff40a2deda820c8df2537e0a7554613ae3948e149504e3e79aa84889df50c8678eeb +813aab8bd000299cd37485b73cd7cba06e205f8efb87f1efc0bae8b70f6db2bc7702eb39510ad734854fb65515fe9d0f +94f0ab7388ac71cdb67f6b85dfd5945748afb2e5abb622f0b5ad104be1d4d0062b651f134ba22385c9e32c2dfdcccce1 +ab6223dca8bd6a4f969e21ccd9f8106fc5251d321f9e90cc42cea2424b3a9c4e5060a47eeef6b23c7976109b548498e8 +859c56b71343fce4d5c5b87814c47bf55d581c50fd1871a17e77b5e1742f5af639d0e94d19d909ec7dfe27919e954e0c +aae0d632b6191b8ad71b027791735f1578e1b89890b6c22e37de0e4a6074886126988fe8319ae228ac9ef3b3bcccb730 +8ca9f32a27a024c3d595ecfaf96b0461de57befa3b331ab71dc110ec3be5824fed783d9516597537683e77a11d334338 +a061df379fb3f4b24816c9f6cd8a94ecb89b4c6dc6cd81e4b8096fa9784b7f97ab3540259d1de9c02eb91d9945af4823 +998603102ac63001d63eb7347a4bb2bf4cf33b28079bb48a169076a65c20d511ccd3ef696d159e54cc8e772fb5d65d50 +94444d96d39450872ac69e44088c252c71f46be8333a608a475147752dbb99db0e36acfc5198f158509401959c12b709 +ac1b51b6c09fe055c1d7c9176eea9adc33f710818c83a1fbfa073c8dc3a7eb3513cbdd3f5960b7845e31e3e83181e6ba +803d530523fc9e1e0f11040d2412d02baef3f07eeb9b177fa9bfa396af42eea898a4276d56e1db998dc96ae47b644cb2 +85a3c9fc7638f5bf2c3e15ba8c2fa1ae87eb1ceb44c6598c67a2948667a9dfa41e61f66d535b4e7fda62f013a5a8b885 +a961cf5654c46a1a22c29baf7a4e77837a26b7f138f410e9d1883480ed5fa42411d522aba32040b577046c11f007388e +ad1154142344f494e3061ef45a34fab1aaacf5fdf7d1b26adbb5fbc3d795655fa743444e39d9a4119b4a4f82a6f30441 +b1d6c30771130c77806e7ab893b73d4deb590b2ff8f2f8b5e54c2040c1f3e060e2bd99afc668cf706a2df666a508bbf6 +a00361fd440f9decabd98d96c575cd251dc94c60611025095d1201ef2dedde51cb4de7c2ece47732e5ed9b3526c2012c +a85c5ab4d17d328bda5e6d839a9a6adcc92ff844ec25f84981e4f44a0e8419247c081530f8d9aa629c7eb4ca21affba6 +a4ddd3eab4527a2672cf9463db38bc29f61460e2a162f426b7852b7a7645fbd62084fd39a8e4d60e1958cce436dd8f57 +811648140080fe55b8618f4cf17f3c5a250adb0cd53d885f2ddba835d2b4433188e41fc0661faac88e4ff910b16278c0 +b85c7f1cfb0ed29addccf7546023a79249e8f15ac2d14a20accbfef4dd9dc11355d599815fa09d2b6b4e966e6ea8cff1 +a10b5d8c260b159043b020d5dd62b3467df2671afea6d480ca9087b7e60ed170c82b121819d088315902842d66c8fb45 +917e191df1bcf3f5715419c1e2191da6b8680543b1ba41fe84ed07ef570376e072c081beb67b375fca3565a2565bcabb +881fd967407390bfd7badc9ab494e8a287559a01eb07861f527207c127eadea626e9bcc5aa9cca2c5112fbac3b3f0e9c +959fd71149af82cc733619e0e5bf71760ca2650448c82984b3db74030d0e10f8ab1ce1609a6de6f470fe8b5bd90df5b3 +a3370898a1c5f33d15adb4238df9a6c945f18b9ada4ce2624fc32a844f9ece4c916a64e9442225b6592afa06d2e015f2 +817efb8a791435e4236f7d7b278181a5fa34587578c629dbc14fbf9a5c26772290611395eecd20222a4c58649fc256d8 +a04c9876acf2cfdc8ef96de4879742709270fa1d03fe4c8511fbef2d59eb0aaf0336fa2c7dfe41a651157377fa217813 +81e15875d7ea7f123e418edf14099f2e109d4f3a6ce0eb65f67fe9fb10d2f809a864a29f60ad3fc949f89e2596b21783 +b49f529975c09e436e6bc202fdc16e3fdcbe056db45178016ad6fdece9faad4446343e83aed096209690b21a6910724f +879e8eda589e1a279f7f49f6dd0580788c040d973748ec4942dbe51ea8fbd05983cc919b78f0c6b92ef3292ae29db875 +81a2b74b2118923f34139a102f3d95e7eee11c4c2929c2576dee200a5abfd364606158535a6c9e4178a6a83dbb65f3c4 +8913f281d8927f2b45fc815d0f7104631cb7f5f7278a316f1327d670d15868daadd2a64e3eb98e1f53fe7e300338cc80 +a6f815fba7ef9af7fbf45f93bc952e8b351f5de6568a27c7c47a00cb39a254c6b31753794f67940fc7d2e9cc581529f4 +b3722a15c66a0014ce4d082de118def8d39190c15678a472b846225585f3a83756ae1b255b2e3f86a26168878e4773b2 +817ae61ab3d0dd5b6e24846b5a5364b1a7dc2e77432d9fed587727520ae2f307264ea0948c91ad29f0aea3a11ff38624 +b3db467464415fcad36dc1de2d6ba7686772a577cc2619242ac040d6734881a45d3b40ed4588db124e4289cfeec4bbf6 +ad66a14f5a54ac69603b16e5f1529851183da77d3cc60867f10aea41339dd5e06a5257982e9e90a352cdd32750f42ee4 +adafa3681ef45d685555601a25a55cf23358319a17f61e2179e704f63df83a73bdd298d12cf6cef86db89bd17119e11d +a379dc44cb6dd3b9d378c07b2ec654fec7ca2f272de6ba895e3d00d20c9e4c5550498a843c8ac67e4221db2115bedc1c +b7bf81c267a78efc6b9e5a904574445a6487678d7ef70054e3e93ea6a23f966c2b68787f9164918e3b16d2175459ed92 +b41d66a13a4afafd5760062b77f79de7e6ab8ccacde9c6c5116a6d886912fb491dc027af435b1b44aacc6af7b3c887f2 +9904d23a7c1c1d2e4bab85d69f283eb0a8e26d46e8b7b30224438015c936729b2f0af7c7c54c03509bb0500acb42d8a4 +ae30d65e9e20c3bfd603994ae2b175ff691d51f3e24b2d058b3b8556d12ca4c75087809062dddd4aaac81c94d15d8a17 +9245162fab42ac01527424f6013310c3eb462982518debef6c127f46ba8a06c705d7dc9f0a41e796ba8d35d60ae6cc64 +87fab853638d7a29a20f3ba2b1a7919d023e9415bfa78ebb27973d8cbc7626f584dc5665d2e7ad71f1d760eba9700d88 +85aac46ecd330608e5272430970e6081ff02a571e8ea444f1e11785ea798769634a22a142d0237f67b75369d3c484a8a +938c85ab14894cc5dfce3d80456f189a2e98eddbc8828f4ff6b1df1dcb7b42b17ca2ff40226a8a1390a95d63dca698dd +a18ce1f846e3e3c4d846822f60271eecf0f5d7d9f986385ac53c5ace9589dc7c0188910448c19b91341a1ef556652fa9 +8611608a9d844f0e9d7584ad6ccf62a5087a64f764caf108db648a776b5390feb51e5120f0ef0e9e11301af3987dd7dc +8106333ba4b4de8d1ae43bc9735d3fea047392e88efd6a2fa6f7b924a18a7a265ca6123c3edc0f36307dd7fb7fe89257 +a91426fa500951ff1b051a248c050b7139ca30dde8768690432d597d2b3c4357b11a577be6b455a1c5d145264dcf81fc +b7f9f90e0e450f37b081297f7f651bad0496a8b9afd2a4cf4120a2671aaaa8536dce1af301258bfbfdb122afa44c5048 +84126da6435699b0c09fa4032dec73d1fca21d2d19f5214e8b0bea43267e9a8dd1fc44f8132d8315e734c8e2e04d7291 +aff064708103884cb4f1a3c1718b3fc40a238d35cf0a7dc24bdf9823693b407c70da50df585bf5bc4e9c07d1c2d203e8 +a8b40fc6533752983a5329c31d376c7a5c13ce6879cc7faee648200075d9cd273537001fb4c86e8576350eaac6ba60c2 +a02db682bdc117a84dcb9312eb28fcbde12d49f4ce915cc92c610bb6965ec3cc38290f8c5b5ec70afe153956692cda95 +86decd22b25d300508472c9ce75d3e465b737e7ce13bc0fcce32835e54646fe12322ba5bc457be18bfd926a1a6ca4a38 +a18666ef65b8c2904fd598791f5627207165315a85ee01d5fb0e6b2e10bdd9b00babc447da5bd63445e3337de33b9b89 +89bb0c06effadefdaf34ffe4b123e1678a90d4451ee856c863df1e752eef41fd984689ded8f0f878bf8916d5dd8e8024 +97cfcba08ebec05d0073992a66b1d7d6fb9d95871f2cdc36db301f78bf8069294d1c259efef5c93d20dc937eedae3a1a +ac2643b14ece79dcb2e289c96776a47e2bebd40dd6dc74fd035df5bb727b5596f40e3dd2d2202141e69b0993717ede09 +a5e6fd88a2f9174d9bd4c6a55d9c30974be414992f22aa852f552c7648f722ed8077acf5aba030abd47939bb451b2c60 +8ad40a612824a7994487731a40b311b7349038c841145865539c6ada75c56de6ac547a1c23df190e0caaafecddd80ccc +953a7cea1d857e09202c438c6108060961f195f88c32f0e012236d7a4b39d840c61b162ec86436e8c38567328bea0246 +80d8b47a46dae1868a7b8ccfe7029445bbe1009dad4a6c31f9ef081be32e8e1ac1178c3c8fb68d3e536c84990cc035b1 +81ecd99f22b3766ce0aca08a0a9191793f68c754fdec78b82a4c3bdc2db122bbb9ebfd02fc2dcc6e1567a7d42d0cc16a +b1dd0446bccc25846fb95d08c1c9cc52fb51c72c4c5d169ffde56ecfe800f108dc1106d65d5c5bd1087c656de3940b63 +b87547f0931e164e96de5c550ca5aa81273648fe34f6e193cd9d69cf729cb432e17aa02e25b1c27a8a0d20a3b795e94e +820a94e69a927e077082aae66f6b292cfbe4589d932edf9e68e268c9bd3d71ef76cf7d169dd445b93967c25db11f58f1 +b0d07ddf2595270c39adfa0c8cf2ab1322979b0546aa4d918f641be53cd97f36c879bb75d205e457c011aca3bbd9f731 +8700b876b35b4b10a8a9372c5230acecd39539c1bb87515640293ad4464a9e02929d7d6a6a11112e8a29564815ac0de4 +a61a601c5bb27dcb97e37c8e2b9ce479c6b192a5e04d9ed5e065833c5a1017ee5f237b77d1a17be5d48f8e7cc0bcacf6 +92fb88fe774c1ba1d4a08cae3c0e05467ad610e7a3f1d2423fd47751759235fe0a3036db4095bd6404716aa03820f484 +b274f140d77a3ce0796f5e09094b516537ccaf27ae1907099bff172e6368ba85e7c3ef8ea2a07457cac48ae334da95b3 +b2292d9181f16581a9a9142490b2bdcdfb218ca6315d1effc8592100d792eb89d5356996c890441f04f2b4a95763503e +8897e73f576d86bc354baa3bd96e553107c48cf5889dcc23c5ba68ab8bcd4e81f27767be2233fdfa13d39f885087e668 +a29eac6f0829791c728d71abc49569df95a4446ecbfc534b39f24f56c88fe70301838dfc1c19751e7f3c5c1b8c6af6a0 +9346dc3720adc5df500a8df27fd9c75ef38dc5c8f4e8ed66983304750e66d502c3c59b8e955be781b670a0afc70a2167 +9566d534e0e30a5c5f1428665590617e95fd05d45f573715f58157854ad596ece3a3cfec61356aee342308d623e029d5 +a464fb8bffe6bd65f71938c1715c6e296cc6d0311a83858e4e7eb5873b7f2cf0c584d2101e3407b85b64ca78b2ac93ce +b54088f7217987c87e9498a747569ac5b2f8afd5348f9c45bf3fd9fbf713a20f495f49c8572d087efe778ac7313ad6d3 +91fa9f5f8000fe050f5b224d90b59fcce13c77e903cbf98ded752e5b3db16adb2bc1f8c94be48b69f65f1f1ad81d6264 +92d04a5b0ac5d8c8e313709b432c9434ecd3e73231f01e9b4e7952b87df60cbfa97b5dedd2200bd033b4b9ea8ba45cc1 +a94b90ad3c3d6c4bbe169f8661a790c40645b40f0a9d1c7220f01cf7fc176e04d80bab0ced9323fcafb93643f12b2760 +94d86149b9c8443b46196f7e5a3738206dd6f3be7762df488bcbb9f9ee285a64c997ed875b7b16b26604fa59020a8199 +82efe4ae2c50a2d7645240c173a047f238536598c04a2c0b69c96e96bd18e075a99110f1206bc213f39edca42ba00cc1 +ab8667685f831bc14d4610f84a5da27b4ea5b133b4d991741a9e64dceb22cb64a3ce8f1b6e101d52af6296df7127c9ad +83ba433661c05dcc5d562f4a9a261c8110dac44b8d833ae1514b1fc60d8b4ee395b18804baea04cb10adb428faf713c3 +b5748f6f660cc5277f1211d2b8649493ed8a11085b871cd33a5aea630abd960a740f08c08be5f9c21574600ac9bf5737 +a5c8dd12af48fb710642ad65ebb97ca489e8206741807f7acfc334f8035d3c80593b1ff2090c9bb7bd138f0c48714ca8 +a2b382fd5744e3babf454b1d806cc8783efeb4761bc42b6914ea48a46a2eae835efbe0a18262b6bc034379e03cf1262b +b3145ffaf603f69f15a64936d32e3219eea5ed49fdfd2f5bf40ea0dfd974b36fb6ff12164d4c2282d892db4cf3ff3ce1 +87a316fb213f4c5e30c5e3face049db66be4f28821bd96034714ec23d3e97849d7b301930f90a4323c7ccf53de23050c +b9de09a919455070fed6220fc179c8b7a4c753062bcd27acf28f5b9947a659c0b364298daf7c85c4ca6fca7f945add1f +806fbd98d411b76979464c40ad88bc07a151628a27fcc1012ba1dfbaf5b5cc9d962fb9b3386008978a12515edce934bc +a15268877fae0d21610ae6a31061ed7c20814723385955fac09fdc9693a94c33dea11db98bb89fdfe68f933490f5c381 +8d633fb0c4da86b2e0b37d8fad5972d62bff2ac663c5ec815d095cd4b7e1fe66ebef2a2590995b57eaf941983c7ad7a4 +8139e5dd9cf405e8ef65f11164f0440827d98389ce1b418b0c9628be983a9ddd6cf4863036ccb1483b40b8a527acd9ed +88b15fa94a08eac291d2b94a2b30eb851ff24addf2cc30b678e72e32cfcb3424cf4b33aa395d741803f3e578ddf524de +b5eaf0c8506e101f1646bcf049ee38d99ea1c60169730da893fd6020fd00a289eb2f415947e44677af49e43454a7b1be +8489822ad0647a7e06aa2aa5595960811858ddd4542acca419dd2308a8c5477648f4dd969a6740bb78aa26db9bfcc555 +b1e9a7b9f3423c220330d45f69e45fa03d7671897cf077f913c252e3e99c7b1b1cf6d30caad65e4228d5d7b80eb86e5e +b28fe9629592b9e6a55a1406903be76250b1c50c65296c10c5e48c64b539fb08fe11f68cf462a6edcbba71b0cee3feb2 +a41acf96a02c96cd8744ff6577c244fc923810d17ade133587e4c223beb7b4d99fa56eae311a500d7151979267d0895c +880798938fe4ba70721be90e666dfb62fcab4f3556fdb7b0dc8ec5bc34f6b4513df965eae78527136eb391889fe2caf9 +98d4d89d358e0fb7e212498c73447d94a83c1b66e98fc81427ab13acddb17a20f52308983f3a5a8e0aaacec432359604 +81430b6d2998fc78ba937a1639c6020199c52da499f68109da227882dc26d005b73d54c5bdcac1a04e8356a8ca0f7017 +a8d906a4786455eb74613aba4ce1c963c60095ffb8658d368df9266fdd01e30269ce10bf984e7465f34b4fd83beba26a +af54167ac1f954d10131d44a8e0045df00d581dd9e93596a28d157543fbe5fb25d213806ed7fb3cba6b8f5b5423562db +8511e373a978a12d81266b9afbd55035d7bc736835cfa921903a92969eeba3624437d1346b55382e61415726ab84a448 +8cf43eea93508ae586fa9a0f1354a1e16af659782479c2040874a46317f9e8d572a23238efa318fdfb87cc63932602b7 +b0bdd3bacff077173d302e3a9678d1d37936188c7ecc34950185af6b462b7c679815176f3cce5db19aac8b282f2d60ad +a355e9b87f2f2672052f5d4d65b8c1c827d24d89b0d8594641fccfb69aef1b94009105f3242058bb31c8bf51caae5a41 +b8baa9e4b950b72ff6b88a6509e8ed1304bc6fd955748b2e59a523a1e0c5e99f52aec3da7fa9ff407a7adf259652466c +840bc3dbb300ea6f27d1d6dd861f15680bd098be5174f45d6b75b094d0635aced539fa03ddbccb453879de77fb5d1fe9 +b4bc7e7e30686303856472bae07e581a0c0bfc815657c479f9f5931cff208d5c12930d2fd1ff413ebd8424bcd7a9b571 +89b5d514155d7999408334a50822508b9d689add55d44a240ff2bdde2eee419d117031f85e924e2a2c1ca77db9b91eea +a8604b6196f87a04e1350302e8aa745bba8dc162115d22657b37a1d1a98cb14876ddf7f65840b5dbd77e80cd22b4256c +83cb7acdb9e03247515bb2ce0227486ccf803426717a14510f0d59d45e998b245797d356f10abca94f7a14e1a2f0d552 +aeb3266a9f16649210ab2df0e1908ac259f34ce1f01162c22b56cf1019096ee4ea5854c36e30bb2feb06c21a71e8a45c +89e72e86edf2aa032a0fc9acf4d876a40865fbb2c8f87cb7e4d88856295c4ac14583e874142fd0c314a49aba68c0aa3c +8c3576eba0583c2a7884976b4ed11fe1fda4f6c32f6385d96c47b0e776afa287503b397fa516a455b4b8c3afeedc76db +a31e5b633bda9ffa174654fee98b5d5930a691c3c42fcf55673d927dbc8d91c58c4e42e615353145431baa646e8bbb30 +89f2f3f7a8da1544f24682f41c68114a8f78c86bd36b066e27da13acb70f18d9f548773a16bd8e24789420e17183f137 +ada27fa4e90a086240c9164544d2528621a415a5497badb79f8019dc3dce4d12eb6b599597e47ec6ac39c81efda43520 +90dc1eb21bf21c0187f359566fc4bf5386abea52799306a0e5a1151c0817c5f5bc60c86e76b1929c092c0f3ff48cedd2 +b702a53ebcc17ae35d2e735a347d2c700e9cbef8eadbece33cac83df483b2054c126593e1f462cfc00a3ce9d737e2af5 +9891b06455ec925a6f8eafffba05af6a38cc5e193acaaf74ffbf199df912c5197106c5e06d72942bbb032ce277b6417f +8c0ee71eb01197b019275bcf96cae94e81d2cdc3115dbf2d8e3080074260318bc9303597e8f72b18f965ad601d31ec43 +8aaf580aaf75c1b7a5f99ccf60503506e62058ef43b28b02f79b8536a96be3f019c9f71caf327b4e6730134730d1bef5 +ae6f9fc21dd7dfa672b25a87eb0a41644f7609fab5026d5cedb6e43a06dbbfd6d6e30322a2598c8dedde88c52eaed626 +8159b953ffece5693edadb2e906ebf76ff080ee1ad22698950d2d3bfc36ac5ea78f58284b2ca180664452d55bd54716c +ab7647c32ca5e9856ac283a2f86768d68de75ceeba9e58b74c5324f8298319e52183739aba4340be901699d66ac9eb3f +a4d85a5701d89bcfaf1572db83258d86a1a0717603d6f24ac2963ffcf80f1265e5ab376a4529ca504f4396498791253c +816080c0cdbfe61b4d726c305747a9eb58ac26d9a35f501dd32ba43c098082d20faf3ccd41aad24600aa73bfa453dfac +84f3afac024f576b0fd9acc6f2349c2fcefc3f77dbe5a2d4964d14b861b88e9b1810334b908cf3427d9b67a8aee74b18 +94b390655557b1a09110018e9b5a14490681ade275bdc83510b6465a1218465260d9a7e2a6e4ec700f58c31dc3659962 +a8c66826b1c04a2dd4c682543242e7a57acae37278bd09888a3d17747c5b5fec43548101e6f46d703638337e2fd3277b +86e6f4608a00007fa533c36a5b054c5768ccafe41ad52521d772dcae4c8a4bcaff8f7609be30d8fab62c5988cbbb6830 +837da4cf09ae8aa0bceb16f8b3bfcc3b3367aecac9eed6b4b56d7b65f55981ef066490764fb4c108792623ecf8cad383 +941ff3011462f9b5bf97d8cbdb0b6f5d37a1b1295b622f5485b7d69f2cb2bcabc83630dae427f0259d0d9539a77d8424 +b99e5d6d82aa9cf7d5970e7f710f4039ac32c2077530e4c2779250c6b9b373bc380adb0a03b892b652f649720672fc8c +a791c78464b2d65a15440b699e1e30ebd08501d6f2720adbc8255d989a82fcded2f79819b5f8f201bed84a255211b141 +84af7ad4a0e31fcbb3276ab1ad6171429cf39adcf78dc03750dc5deaa46536d15591e26d53e953dfb31e1622bc0743ab +a833e62fe97e1086fae1d4917fbaf09c345feb6bf1975b5cb863d8b66e8d621c7989ab3dbecda36bc9eaffc5eaa6fa66 +b4ef79a46a2126f53e2ebe62770feb57fd94600be29459d70a77c5e9cc260fa892be06cd60f886bf48459e48eb50d063 +b43b8f61919ea380bf151c294e54d3a3ff98e20d1ee5efbfe38aa2b66fafbc6a49739793bd5cb1c809f8b30466277c3a +ab37735af2412d2550e62df9d8b3b5e6f467f20de3890bf56faf1abf2bf3bd1d98dc3fa0ad5e7ab3fce0fa20409eb392 +82416b74b1551d484250d85bb151fabb67e29cce93d516125533df585bc80779ab057ea6992801a3d7d5c6dcff87a018 +8145d0787f0e3b5325190ae10c1d6bee713e6765fb6a0e9214132c6f78f4582bb2771aaeae40d3dad4bafb56bf7e36d8 +b6935886349ecbdd5774e12196f4275c97ec8279fdf28ccf940f6a022ebb6de8e97d6d2173c3fe402cbe9643bed3883b +87ef9b4d3dc71ac86369f8ed17e0dd3b91d16d14ae694bc21a35b5ae37211b043d0e36d8ff07dcc513fb9e6481a1f37f +ae1d0ded32f7e6f1dc8fef495879c1d9e01826f449f903c1e5034aeeabc5479a9e323b162b688317d46d35a42d570d86 +a40d16497004db4104c6794e2f4428d75bdf70352685944f3fbe17526df333e46a4ca6de55a4a48c02ecf0bde8ba03c0 +8d45121efba8cc308a498e8ee39ea6fa5cae9fb2e4aab1c2ff9d448aa8494ccbec9a078f978a86fcd97b5d5e7be7522a +a8173865c64634ba4ac2fa432740f5c05056a9deaf6427cb9b4b8da94ca5ddbc8c0c5d3185a89b8b28878194de9cdfcd +b6ec06a74d690f6545f0f0efba236e63d1fdfba54639ca2617408e185177ece28901c457d02b849fd00f1a53ae319d0a +b69a12df293c014a40070e3e760169b6f3c627caf9e50b35a93f11ecf8df98b2bc481b410eecb7ab210bf213bbe944de +97e7dc121795a533d4224803e591eef3e9008bab16f12472210b73aaf77890cf6e3877e0139403a0d3003c12c8f45636 +acdfa6fdd4a5acb7738cc8768f7cba84dbb95c639399b291ae8e4e63df37d2d4096900a84d2f0606bf534a9ccaa4993f +86ee253f3a9446a33e4d1169719b7d513c6b50730988415382faaf751988c10a421020609f7bcdef91be136704b906e2 +aac9438382a856caf84c5a8a234282f71b5fc5f65219103b147e7e6cf565522285fbfd7417b513bdad8277a00f652ca1 +83f3799d8e5772527930f5dc071a2e0a65471618993ec8990a96ccdeee65270e490bda9d26bb877612475268711ffd80 +93f28a81ac8c0ec9450b9d762fae9c7f8feaace87a6ee6bd141ef1d2d0697ef1bbd159fe6e1de640dbdab2b0361fca8a +a0825c95ba69999b90eac3a31a3fd830ea4f4b2b7409bde5f202b61d741d6326852ce790f41de5cb0eccec7af4db30c1 +83924b0e66233edd603c3b813d698daa05751fc34367120e3cf384ea7432e256ccee4d4daf13858950549d75a377107d +956fd9fa58345277e06ba2ec72f49ed230b8d3d4ff658555c52d6cddeb84dd4e36f1a614f5242d5ca0192e8daf0543c2 +944869912476baae0b114cced4ff65c0e4c90136f73ece5656460626599051b78802df67d7201c55d52725a97f5f29fe +865cb25b64b4531fb6fe4814d7c8cd26b017a6c6b72232ff53defc18a80fe3b39511b23f9e4c6c7249d06e03b2282ed2 +81e09ff55214960775e1e7f2758b9a6c4e4cd39edf7ec1adfaad51c52141182b79fe2176b23ddc7df9fd153e5f82d668 +b31006896f02bc90641121083f43c3172b1039334501fbaf1672f7bf5d174ddd185f945adf1a9c6cf77be34c5501483d +88b92f6f42ae45e9f05b16e52852826e933efd0c68b0f2418ac90957fd018df661bc47c8d43c2a7d7bfcf669dab98c3c +92fc68f595853ee8683930751789b799f397135d002eda244fe63ecef2754e15849edde3ba2f0cc8b865c9777230b712 +99ca06a49c5cd0bb097c447793fcdd809869b216a34c66c78c7e41e8c22f05d09168d46b8b1f3390db9452d91bc96dea +b48b9490a5d65296802431852d548d81047bbefc74fa7dc1d4e2a2878faacdfcb365ae59209cb0ade01901a283cbd15d +aff0fdbef7c188b120a02bc9085d7b808e88f73973773fef54707bf2cd772cd066740b1b6f4127b5c349f657bd97e738 +966fd4463b4f43dd8ccba7ad50baa42292f9f8b2e70da23bb6780e14155d9346e275ef03ddaf79e47020dcf43f3738bd +9330c3e1fadd9e08ac85f4839121ae20bbeb0a5103d84fa5aadbd1213805bdcda67bf2fb75fc301349cbc851b5559d20 +993bb99867bd9041a71a55ad5d397755cfa7ab6a4618fc526179bfc10b7dc8b26e4372fe9a9b4a15d64f2b63c1052dda +a29b59bcfab51f9b3c490a3b96f0bf1934265c315349b236012adbd64a56d7f6941b2c8cc272b412044bc7731f71e1dc +a65c9cefe1fc35d089fe8580c2e7671ebefdb43014ac291528ff4deefd4883fd4df274af83711dad610dad0d615f9d65 +944c78c56fb227ae632805d448ca3884cd3d2a89181cead3d2b7835e63297e6d740aa79a112edb1d4727824991636df5 +a73d782da1db7e4e65d7b26717a76e16dd9fab4df65063310b8e917dc0bc24e0d6755df5546c58504d04d9e68c3b474a +af80f0b87811ae3124f68108b4ca1937009403f87928bbc53480e7c5408d072053ace5eeaf5a5aba814dab8a45502085 +88aaf1acfc6e2e19b8387c97da707cb171c69812fefdd4650468e9b2c627bd5ccfb459f4d8e56bdfd84b09ddf87e128f +92c97276ff6f72bab6e9423d02ad6dc127962dbce15a0dd1e4a393b4510c555df6aa27be0f697c0d847033a9ca8b8dfd +a0e07d43d96e2d85b6276b3c60aadb48f0aedf2de8c415756dc597249ea64d2093731d8735231dadc961e5682ac59479 +adc9e6718a8f9298957d1da3842a7751c5399bbdf56f8de6c1c4bc39428f4aee6f1ba6613d37bf46b9403345e9d6fc81 +951da434da4b20d949b509ceeba02e24da7ed2da964c2fcdf426ec787779c696b385822c7dbea4df3e4a35921f1e912c +a04cbce0d2b2e87bbf038c798a12ec828423ca6aca08dc8d481cf6466e3c9c73d4d4a7fa47df9a7e2e15aae9e9f67208 +8f855cca2e440d248121c0469de1f94c2a71b8ee2682bbad3a78243a9e03da31d1925e6760dbc48a1957e040fae9abe8 +b642e5b17c1df4a4e101772d73851180b3a92e9e8b26c918050f51e6dd3592f102d20b0a1e96f0e25752c292f4c903ff +a92454c300781f8ae1766dbbb50a96192da7d48ef4cbdd72dd8cbb44c6eb5913c112cc38e9144615fdc03684deb99420 +8b74f7e6c2304f8e780df4649ef8221795dfe85fdbdaa477a1542d135b75c8be45bf89adbbb6f3ddf54ca40f02e733e9 +85cf66292cbb30cec5fd835ab10c9fcb3aea95e093aebf123e9a83c26f322d76ebc89c4e914524f6c5f6ee7d74fc917d +ae0bfe0cdc97c09542a7431820015f2d16067b30dca56288013876025e81daa8c519e5e347268e19aa1a85fa1dc28793 +921322fc6a47dc091afa0ad6df18ed14cde38e48c6e71550aa513918b056044983aee402de21051235eecf4ce8040fbe +96c030381e97050a45a318d307dcb3c8377b79b4dd5daf6337cded114de26eb725c14171b9b8e1b3c08fe1f5ea6b49e0 +90c23b86b6111818c8baaf53a13eaee1c89203b50e7f9a994bf0edf851919b48edbac7ceef14ac9414cf70c486174a77 +8bf6c301240d2d1c8d84c71d33a6dfc6d9e8f1cfae66d4d0f7a256d98ae12b0bcebfa94a667735ee89f810bcd7170cff +a41a4ffbbea0e36874d65c009ee4c3feffff322f6fc0e30d26ee4dbc1f46040d05e25d9d0ecb378cef0d24a7c2c4b850 +a8d4cdd423986bb392a0a92c12a8bd4da3437eec6ef6af34cf5310944899287452a2eb92eb5386086d5063381189d10e +a81dd26ec057c4032a4ed7ad54d926165273ed51d09a1267b2e477535cf6966835a257c209e4e92d165d74fa75695fa3 +8d7f708c3ee8449515d94fc26b547303b53d8dd55f177bc3b25d3da2768accd9bc8e9f09546090ebb7f15c66e6c9c723 +839ba65cffcd24cfffa7ab3b21faabe3c66d4c06324f07b2729c92f15cad34e474b0f0ddb16cd652870b26a756b731d3 +87f1a3968afec354d92d77e2726b702847c6afcabb8438634f9c6f7766de4c1504317dc4fa9a4a735acdbf985e119564 +91a8a7fd6542f3e0673f07f510d850864b34ac087eb7eef8845a1d14b2b1b651cbdc27fa4049bdbf3fea54221c5c8549 +aef3cf5f5e3a2385ead115728d7059e622146c3457d266c612e778324b6e06fbfb8f98e076624d2f3ce1035d65389a07 +819915d6232e95ccd7693fdd78d00492299b1983bc8f96a08dcb50f9c0a813ed93ae53c0238345d5bea0beda2855a913 +8e9ba68ded0e94935131b392b28218315a185f63bf5e3c1a9a9dd470944509ca0ba8f6122265f8da851b5cc2abce68f1 +b28468e9b04ee9d69003399a3cf4457c9bf9d59f36ab6ceeb8e964672433d06b58beeea198fedc7edbaa1948577e9fa2 +a633005e2c9f2fd94c8bce2dd5bb708fe946b25f1ec561ae65e54e15cdd88dc339f1a083e01f0d39610c8fe24151aaf0 +841d0031e22723f9328dd993805abd13e0c99b0f59435d2426246996b08d00ce73ab906f66c4eab423473b409e972ce0 +85758d1b084263992070ec8943f33073a2d9b86a8606672550c17545507a5b3c88d87382b41916a87ee96ff55a7aa535 +8581b06b0fc41466ef94a76a1d9fb8ae0edca6d018063acf6a8ca5f4b02d76021902feba58972415691b4bdbc33ae3b4 +83539597ff5e327357ee62bc6bf8c0bcaec2f227c55c7c385a4806f0d37fb461f1690bad5066b8a5370950af32fafbef +aee3557290d2dc10827e4791d00e0259006911f3f3fce4179ed3c514b779160613eca70f720bff7804752715a1266ffa +b48d2f0c4e90fc307d5995464e3f611a9b0ef5fe426a289071f4168ed5cc4f8770c9332960c2ca5c8c427f40e6bb389f +847af8973b4e300bb06be69b71b96183fd1a0b9d51b91701bef6fcfde465068f1eb2b1503b07afda380f18d69de5c9e1 +a70a6a80ce407f07804c0051ac21dc24d794b387be94eb24e1db94b58a78e1bcfb48cd0006db8fc1f9bedaece7a44fbe +b40e942b8fa5336910ff0098347df716bff9d1fa236a1950c16eeb966b3bc1a50b8f7b0980469d42e75ae13ced53cead +b208fabaa742d7db3148515330eb7a3577487845abdb7bd9ed169d0e081db0a5816595c33d375e56aeac5b51e60e49d3 +b7c8194b30d3d6ef5ab66ec88ad7ebbc732a3b8a41731b153e6f63759a93f3f4a537eab9ad369705bd730184bdbbdc34 +9280096445fe7394d04aa1bc4620c8f9296e991cc4d6c131bd703cb1cc317510e6e5855ac763f4d958c5edfe7eebeed7 +abc2aa4616a521400af1a12440dc544e3c821313d0ab936c86af28468ef8bbe534837e364598396a81cf8d06274ed5a6 +b18ca8a3325adb0c8c18a666d4859535397a1c3fe08f95eebfac916a7a99bbd40b3c37b919e8a8ae91da38bc00fa56c0 +8a40c33109ecea2a8b3558565877082f79121a432c45ec2c5a5e0ec4d1c203a6788e6b69cb37f1fd5b8c9a661bc5476d +88c47301dd30998e903c84e0b0f2c9af2e1ce6b9f187dab03528d44f834dc991e4c86d0c474a2c63468cf4020a1e24a0 +920c832853e6ab4c851eecfa9c11d3acc7da37c823be7aa1ab15e14dfd8beb5d0b91d62a30cec94763bd8e4594b66600 +98e1addbe2a6b8edc7f12ecb9be81c3250aeeca54a1c6a7225772ca66549827c15f3950d01b8eb44aecb56fe0fff901a +8cfb0fa1068be0ec088402f5950c4679a2eb9218c729da67050b0d1b2d7079f3ddf4bf0f57d95fe2a8db04bc6bcdb20c +b70f381aafe336b024120453813aeab70baac85b9c4c0f86918797b6aee206e6ed93244a49950f3d8ec9f81f4ac15808 +a4c8edf4aa33b709a91e1062939512419711c1757084e46f8f4b7ed64f8e682f4e78b7135920c12f0eb0422fe9f87a6a +b4817e85fd0752d7ebb662d3a51a03367a84bac74ebddfba0e5af5e636a979500f72b148052d333b3dedf9edd2b4031b +a87430169c6195f5d3e314ff2d1c2f050e766fd5d2de88f5207d72dba4a7745bb86d0baca6e9ae156582d0d89e5838c7 +991b00f8b104566b63a12af4826b61ce7aa40f4e5b8fff3085e7a99815bdb4471b6214da1e480214fac83f86a0b93cc5 +b39966e3076482079de0678477df98578377a094054960ee518ef99504d6851f8bcd3203e8da5e1d4f6f96776e1fe6eb +a448846d9dc2ab7a0995fa44b8527e27f6b3b74c6e03e95edb64e6baa4f1b866103f0addb97c84bef1d72487b2e21796 +894bec21a453ae84b592286e696c35bc30e820e9c2fd3e63dd4fbe629e07df16439c891056070faa490155f255bf7187 +a9ec652a491b11f6a692064e955f3f3287e7d2764527e58938571469a1e29b5225b9415bd602a45074dfbfe9c131d6ca +b39d37822e6cbe28244b5f42ce467c65a23765bd16eb6447c5b3e942278069793763483dafd8c4dd864f8917aad357fe +88dba51133f2019cb266641c56101e3e5987d3b77647a2e608b5ff9113dfc5f85e2b7c365118723131fbc0c9ca833c9c +b566579d904b54ecf798018efcb824dccbebfc6753a0fd2128ac3b4bd3b038c2284a7c782b5ca6f310eb7ea4d26a3f0a +a97a55c0a492e53c047e7d6f9d5f3e86fb96f3dddc68389c0561515343b66b4bc02a9c0d5722dff1e3445308240b27f7 +a044028ab4bcb9e1a2b9b4ca4efbf04c5da9e4bf2fff0e8bd57aa1fc12a71e897999c25d9117413faf2f45395dee0f13 +a78dc461decbeaeed8ebd0909369b491a5e764d6a5645a7dac61d3140d7dc0062526f777b0eb866bff27608429ebbdde +b2c2a8991f94c39ca35fea59f01a92cb3393e0eccb2476dfbf57261d406a68bd34a6cff33ed80209991688c183609ef4 +84189eefb521aff730a4fd3fd5b10ddfd29f0d365664caef63bb015d07e689989e54c33c2141dd64427805d37a7e546e +85ac80bd734a52235da288ff042dea9a62e085928954e8eacd2c751013f61904ed110e5b3afe1ab770a7e6485efb7b5e +9183a560393dcb22d0d5063e71182020d0fbabb39e32493eeffeb808df084aa243eb397027f150b55a247d1ed0c8513e +81c940944df7ecc58d3c43c34996852c3c7915ed185d7654627f7af62abae7e0048dd444a6c09961756455000bd96d09 +aa8c34e164019743fd8284b84f06c3b449aae7996e892f419ee55d82ad548cb300fd651de329da0384243954c0ef6a60 +89a7b7bdfc7e300d06a14d463e573d6296d8e66197491900cc9ae49504c4809ff6e61b758579e9091c61085ba1237b83 +878d21809ba540f50bd11f4c4d9590fb6f3ab9de5692606e6e2ef4ed9d18520119e385be5e1f4b3f2e2b09c319f0e8fc +8eb248390193189cf0355365e630b782cd15751e672dc478b39d75dc681234dcd9309df0d11f4610dbb249c1e6be7ef9 +a1d7fb3aecb896df3a52d6bd0943838b13f1bd039c936d76d03de2044c371d48865694b6f532393b27fd10a4cf642061 +a34bca58a24979be442238cbb5ece5bee51ae8c0794dd3efb3983d4db713bc6f28a96e976ac3bd9a551d3ed9ba6b3e22 +817c608fc8cacdd178665320b5a7587ca21df8bdd761833c3018b967575d25e3951cf3d498a63619a3cd2ad4406f5f28 +86c95707db0495689afd0c2e39e97f445f7ca0edffad5c8b4cacd1421f2f3cc55049dfd504f728f91534e20383955582 +99c3b0bb15942c301137765d4e19502f65806f3b126dc01a5b7820c87e8979bce6a37289a8f6a4c1e4637227ad5bf3bf +8aa1518a80ea8b074505a9b3f96829f5d4afa55a30efe7b4de4e5dbf666897fdd2cf31728ca45921e21a78a80f0e0f10 +8d74f46361c79e15128ac399e958a91067ef4cec8983408775a87eca1eed5b7dcbf0ddf30e66f51780457413496c7f07 +a41cde4a786b55387458a1db95171aca4fd146507b81c4da1e6d6e495527c3ec83fc42fad1dfe3d92744084a664fd431 +8c352852c906fae99413a84ad11701f93f292fbf7bd14738814f4c4ceab32db02feb5eb70bc73898b0bc724a39d5d017 +a5993046e8f23b71ba87b7caa7ace2d9023fb48ce4c51838813174880d918e9b4d2b0dc21a2b9c6f612338c31a289df8 +83576d3324bf2d8afbfb6eaecdc5d767c8e22e7d25160414924f0645491df60541948a05e1f4202e612368e78675de8a +b43749b8df4b15bc9a3697e0f1c518e6b04114171739ef1a0c9c65185d8ec18e40e6954d125cbc14ebc652cf41ad3109 +b4eebd5d80a7327a040cafb9ccdb12b2dfe1aa86e6bc6d3ac8a57fadfb95a5b1a7332c66318ff72ba459f525668af056 +9198be7f1d413c5029b0e1c617bcbc082d21abe2c60ec8ce9b54ca1a85d3dba637b72fda39dae0c0ae40d047eab9f55a +8d96a0232832e24d45092653e781e7a9c9520766c3989e67bbe86b3a820c4bf621ea911e7cd5270a4bfea78b618411f6 +8d7160d0ea98161a2d14d46ef01dff72d566c330cd4fabd27654d300e1bc7644c68dc8eabf2a20a59bfe7ba276545f9b +abb60fce29dec7ba37e3056e412e0ec3e05538a1fc0e2c68877378c867605966108bc5742585ab6a405ce0c962b285b6 +8fabffa3ed792f05e414f5839386f6449fd9f7b41a47595c5d71074bd1bb3784cc7a1a7e1ad6b041b455035957e5b2dc +90ff017b4804c2d0533b72461436b10603ab13a55f86fd4ec11b06a70ef8166f958c110519ca1b4cc7beba440729fe2d +b340cfd120f6a4623e3a74cf8c32bfd7cd61a280b59dfd17b15ca8fae4d82f64a6f15fbde4c02f424debc72b7db5fe67 +871311c9c7220c932e738d59f0ecc67a34356d1429fe570ca503d340c9996cb5ee2cd188fad0e3bd16e4c468ec1dbebd +a772470262186e7b94239ba921b29f2412c148d6f97c4412e96d21e55f3be73f992f1ad53c71008f0558ec3f84e2b5a7 +b2a897dcb7ffd6257f3f2947ec966f2077d57d5191a88840b1d4f67effebe8c436641be85524d0a21be734c63ab5965d +a044f6eacc48a4a061fa149500d96b48cbf14853469aa4d045faf3dca973be1bd4b4ce01646d83e2f24f7c486d03205d +981af5dc2daa73f7fa9eae35a93d81eb6edba4a7f673b55d41f6ecd87a37685d31bb40ef4f1c469b3d72f2f18b925a17 +912d2597a07864de9020ac77083eff2f15ceb07600f15755aba61251e8ce3c905a758453b417f04d9c38db040954eb65 +9642b7f6f09394ba5e0805734ef6702c3eddf9eea187ba98c676d5bbaec0e360e3e51dc58433aaa1e2da6060c8659cb7 +8ab3836e0a8ac492d5e707d056310c4c8e0489ca85eb771bff35ba1d658360084e836a6f51bb990f9e3d2d9aeb18fbb5 +879e058e72b73bb1f4642c21ffdb90544b846868139c6511f299aafe59c2d0f0b944dffc7990491b7c4edcd6a9889250 +b9e60b737023f61479a4a8fd253ed0d2a944ea6ba0439bbc0a0d3abf09b0ad1f18d75555e4a50405470ae4990626f390 +b9c2535d362796dcd673640a9fa2ebdaec274e6f8b850b023153b0a7a30fffc87f96e0b72696f647ebe7ab63099a6963 +94aeff145386a087b0e91e68a84a5ede01f978f9dd9fe7bebca78941938469495dc30a96bba9508c0d017873aeea9610 +98b179f8a3d9f0d0a983c30682dd425a2ddc7803be59bd626c623c8951a5179117d1d2a68254c95c9952989877d0ee55 +889ecf5f0ee56938273f74eb3e9ecfb5617f04fb58e83fe4c0e4aef51615cf345bc56f3f61b17f6eed3249d4afd54451 +a0f2b2c39bcea4b50883e2587d16559e246248a66ecb4a4b7d9ab3b51fb39fe98d83765e087eee37a0f86b0ba4144c02 +b2a61e247ed595e8a3830f7973b07079cbda510f28ad8c78c220b26cb6acde4fbb5ee90c14a665f329168ee951b08cf0 +95bd0fcfb42f0d6d8a8e73d7458498a85bcddd2fb132fd7989265648d82ac2707d6d203fac045504977af4f0a2aca4b7 +843e5a537c298666e6cf50fcc044f13506499ef83c802e719ff2c90e85003c132024e04711be7234c04d4b0125512d5d +a46d1797c5959dcd3a5cfc857488f4d96f74277c3d13b98b133620192f79944abcb3a361d939a100187f1b0856eae875 +a1c7786736d6707a48515c38660615fcec67eb8a2598f46657855215f804fd72ab122d17f94fcffad8893f3be658dca7 +b23dc9e610abc7d8bd21d147e22509a0fa49db5be6ea7057b51aae38e31654b3aa044df05b94b718153361371ba2f622 +b00cc8f257d659c22d30e6d641f79166b1e752ea8606f558e4cad6fc01532e8319ea4ee12265ba4140ac45aa4613c004 +ac7019af65221b0cc736287b32d7f1a3561405715ba9a6a122342e04e51637ba911c41573de53e4781f2230fdcb2475f +81a630bc41b3da8b3eb4bf56cba10cd9f93153c3667f009dc332287baeb707d505fb537e6233c8e53d299ec0f013290c +a6b7aea5c545bb76df0f230548539db92bc26642572cb7dd3d5a30edca2b4c386f44fc8466f056b42de2a452b81aff5b +8271624ff736b7b238e43943c81de80a1612207d32036d820c11fc830c737972ccc9c60d3c2359922b06652311e3c994 +8a684106458cb6f4db478170b9ad595d4b54c18bf63b9058f095a2fa1b928c15101472c70c648873d5887880059ed402 +a5cc3c35228122f410184e4326cf61a37637206e589fcd245cb5d0cec91031f8f7586b80503070840fdfd8ce75d3c88b +9443fc631aed8866a7ed220890911057a1f56b0afe0ba15f0a0e295ab97f604b134b1ed9a4245e46ee5f9a93aa74f731 +984b6f7d79835dffde9558c6bb912d992ca1180a2361757bdba4a7b69dc74b056e303adc69fe67414495dd9c2dd91e64 +b15a5c8cba5de080224c274d31c68ed72d2a7126d347796569aef0c4e97ed084afe3da4d4b590b9dda1a07f0c2ff3dfb +991708fe9650a1f9a4e43938b91d45dc68c230e05ee999c95dbff3bf79b1c1b2bb0e7977de454237c355a73b8438b1d9 +b4f7edc7468b176a4a7c0273700c444fa95c726af6697028bed4f77eee887e3400f9c42ee15b782c0ca861c4c3b8c98a +8c60dcc16c51087eb477c13e837031d6c6a3dc2b8bf8cb43c23f48006bc7173151807e866ead2234b460c2de93b31956 +83ad63e9c910d1fc44bc114accfb0d4d333b7ebe032f73f62d25d3e172c029d5e34a1c9d547273bf6c0fead5c8801007 +85de73213cc236f00777560756bdbf2b16841ba4b55902cf2cad9742ecaf5d28209b012ceb41f337456dfeca93010cd7 +a7561f8827ccd75b6686ba5398bb8fc3083351c55a589b18984e186820af7e275af04bcd4c28e1dc11be1e8617a0610b +88c0a4febd4068850557f497ea888035c7fc9f404f6cc7794e7cc8722f048ad2f249e7dc62743e7a339eb7473ad3b0cd +932b22b1d3e6d5a6409c34980d176feb85ada1bf94332ef5c9fc4d42b907dabea608ceef9b5595ef3feee195151f18d8 +a2867bb3f5ab88fbdae3a16c9143ab8a8f4f476a2643c505bb9f37e5b1fd34d216cab2204c9a017a5a67b7ad2dda10e8 +b573d5f38e4e9e8a3a6fd82f0880dc049efa492a946d00283019bf1d5e5516464cf87039e80aef667cb86fdea5075904 +b948f1b5ab755f3f5f36af27d94f503b070696d793b1240c1bdfd2e8e56890d69e6904688b5f8ff5a4bdf5a6abfe195f +917eae95ebc4109a2e99ddd8fec7881d2f7aaa0e25fda44dec7ce37458c2ee832f1829db7d2dcfa4ca0f06381c7fe91d +95751d17ed00a3030bce909333799bb7f4ab641acf585807f355b51d6976dceee410798026a1a004ef4dcdff7ec0f5b8 +b9b7bd266f449a79bbfe075e429613e76c5a42ac61f01c8f0bbbd34669650682efe01ff9dbbc400a1e995616af6aa278 +ac1722d097ce9cd7617161f8ec8c23d68f1fb1c9ca533e2a8b4f78516c2fd8fb38f23f834e2b9a03bb06a9d655693ca9 +a7ad9e96ffd98db2ecdb6340c5d592614f3c159abfd832fe27ee9293519d213a578e6246aae51672ee353e3296858873 +989b8814d5de7937c4acafd000eec2b4cd58ba395d7b25f98cafd021e8efa37029b29ad8303a1f6867923f5852a220eb +a5bfe6282c771bc9e453e964042d44eff4098decacb89aecd3be662ea5b74506e1357ab26f3527110ba377711f3c9f41 +8900a7470b656639721d2abbb7b06af0ac4222ab85a1976386e2a62eb4b88bfb5b72cf7921ddb3cf3a395d7eeb192a2e +95a71b55cd1f35a438cf5e75f8ff11c5ec6a2ebf2e4dba172f50bfad7d6d5dca5de1b1afc541662c81c858f7604c1163 +82b5d62fea8db8d85c5bc3a76d68dedd25794cf14d4a7bc368938ffca9e09f7e598fdad2a5aac614e0e52f8112ae62b9 +997173f07c729202afcde3028fa7f52cefc90fda2d0c8ac2b58154a5073140683e54c49ed1f254481070d119ce0ce02a +aeffb91ccc7a72bbd6ffe0f9b99c9e66e67d59cec2e02440465e9636a613ab3017278cfa72ea8bc4aba9a8dc728cb367 +952743b06e8645894aeb6440fc7a5f62dd3acf96dab70a51e20176762c9751ea5f2ba0b9497ccf0114dc4892dc606031 +874c63baeddc56fbbca2ff6031f8634b745f6e34ea6791d7c439201aee8f08ef5ee75f7778700a647f3b21068513fce6 +85128fec9c750c1071edfb15586435cc2f317e3e9a175bb8a9697bcda1eb9375478cf25d01e7fed113483b28f625122d +85522c9576fd9763e32af8495ae3928ed7116fb70d4378448926bc9790e8a8d08f98cf47648d7da1b6e40d6a210c7924 +97d0f37a13cfb723b848099ca1c14d83e9aaf2f7aeb71829180e664b7968632a08f6a85f557d74b55afe6242f2a36e7c +abaa472d6ad61a5fccd1a57c01aa1bc081253f95abbcba7f73923f1f11c4e79b904263890eeb66926de3e2652f5d1c70 +b3c04945ba727a141e5e8aec2bf9aa3772b64d8fd0e2a2b07f3a91106a95cbcb249adcd074cbe498caf76fffac20d4ef +82c46781a3d730d9931bcabd7434a9171372dde57171b6180e5516d4e68db8b23495c8ac3ab96994c17ddb1cf249b9fb +a202d8b65613c42d01738ccd68ed8c2dbc021631f602d53f751966e04182743ebc8e0747d600b8a8676b1da9ae7f11ab +ae73e7256e9459db04667a899e0d3ea5255211fb486d084e6550b6dd64ca44af6c6b2d59d7aa152de9f96ce9b58d940d +b67d87b176a9722945ec7593777ee461809861c6cfd1b945dde9ee4ff009ca4f19cf88f4bbb5c80c9cbab2fe25b23ac8 +8f0b7a317a076758b0dac79959ee4a06c08b07d0f10538a4b53d3da2eda16e2af26922feb32c090330dc4d969cf69bd3 +90b36bf56adbd8c4b6cb32febc3a8d5f714370c2ac3305c10fa6d168dffb2a026804517215f9a2d4ec8310cdb6bb459b +aa80c19b0682ead69934bf18cf476291a0beddd8ef4ed75975d0a472e2ab5c70f119722a8574ae4973aceb733d312e57 +a3fc9abb12574e5c28dcb51750b4339b794b8e558675eef7d26126edf1de920c35e992333bcbffcbf6a5f5c0d383ce62 +a1573ff23ab972acdcd08818853b111fc757fdd35aa070186d3e11e56b172fb49d840bf297ac0dd222e072fc09f26a81 +98306f2be4caa92c2b4392212d0cbf430b409b19ff7d5b899986613bd0e762c909fc01999aa94be3bd529d67f0113d7f +8c1fc42482a0819074241746d17dc89c0304a2acdae8ed91b5009e9e3e70ff725ba063b4a3e68fdce05b74f5180c545e +a6c6113ebf72d8cf3163b2b8d7f3fa24303b13f55752522c660a98cd834d85d8c79214d900fa649499365e2e7641f77a +ab95eea424f8a2cfd9fb1c78bb724e5b1d71a0d0d1e4217c5d0f98b0d8bbd3f8400a2002abc0a0e4576d1f93f46fefad +823c5a4fd8cf4a75fdc71d5f2dd511b6c0f189b82affeacd2b7cfcad8ad1a5551227dcc9bfdb2e34b2097eaa00efbb51 +b97314dfff36d80c46b53d87a61b0e124dc94018a0bb680c32765b9a2d457f833a7c42bbc90b3b1520c33a182580398d +b17566ee3dcc6bb3b004afe4c0136dfe7dd27df9045ae896dca49fb36987501ae069eb745af81ba3fc19ff037e7b1406 +b0bdc0f55cfd98d331e3a0c4fbb776a131936c3c47c6bffdc3aaf7d8c9fa6803fbc122c2fefbb532e634228687d52174 +aa5d9e60cc9f0598559c28bb9bdd52aa46605ab4ffe3d192ba982398e72cec9a2a44c0d0d938ce69935693cabc0887ea +802b6459d2354fa1d56c592ac1346c428dadea6b6c0a87bf7d309bab55c94e1cf31dd98a7a86bd92a840dd51f218b91b +a526914efdc190381bf1a73dd33f392ecf01350b9d3f4ae96b1b1c3d1d064721c7d6eec5788162c933245a3943f5ee51 +b3b8fcf637d8d6628620a1a99dbe619eabb3e5c7ce930d6efd2197e261bf394b74d4e5c26b96c4b8009c7e523ccfd082 +8f7510c732502a93e095aba744535f3928f893f188adc5b16008385fb9e80f695d0435bfc5b91cdad4537e87e9d2551c +97b90beaa56aa936c3ca45698f79273a68dd3ccd0076eab48d2a4db01782665e63f33c25751c1f2e070f4d1a8525bf96 +b9fb798324b1d1283fdc3e48288e3861a5449b2ab5e884b34ebb8f740225324af86e4711da6b5cc8361c1db15466602f +b6d52b53cea98f1d1d4c9a759c25bf9d8a50b604b144e4912acbdbdc32aab8b9dbb10d64a29aa33a4f502121a6fb481c +9174ffff0f2930fc228f0e539f5cfd82c9368d26b074467f39c07a774367ff6cccb5039ac63f107677d77706cd431680 +a33b6250d4ac9e66ec51c063d1a6a31f253eb29bbaed12a0d67e2eccfffb0f3a52750fbf52a1c2aaba8c7692346426e7 +a97025fd5cbcebe8ef865afc39cd3ea707b89d4e765ec817fd021d6438e02fa51e3544b1fd45470c58007a08efac6edd +b32a78480edd9ff6ba2f1eec4088db5d6ceb2d62d7e59e904ecaef7bb4a2e983a4588e51692b3be76e6ffbc0b5f911a5 +b5ab590ef0bb77191f00495b33d11c53c65a819f7d0c1f9dc4a2caa147a69c77a4fff7366a602d743ee1f395ce934c1e +b3fb0842f9441fb1d0ee0293b6efbc70a8f58d12d6f769b12872db726b19e16f0f65efbc891cf27a28a248b0ef9c7e75 +9372ad12856fefb928ccb0d34e198df99e2f8973b07e9d417a3134d5f69e12e79ff572c4e03ccd65415d70639bc7c73e +aa8d6e83d09ce216bfe2009a6b07d0110d98cf305364d5529c170a23e693aabb768b2016befb5ada8dabdd92b4d012bb +a954a75791eeb0ce41c85200c3763a508ed8214b5945a42c79bfdcfb1ec4f86ad1dd7b2862474a368d4ac31911a2b718 +8e2081cfd1d062fe3ab4dab01f68062bac802795545fede9a188f6c9f802cb5f884e60dbe866710baadbf55dc77c11a4 +a2f06003b9713e7dd5929501ed485436b49d43de80ea5b15170763fd6346badf8da6de8261828913ee0dacd8ff23c0e1 +98eecc34b838e6ffd1931ca65eec27bcdb2fdcb61f33e7e5673a93028c5865e0d1bf6d3bec040c5e96f9bd08089a53a4 +88cc16019741b341060b95498747db4377100d2a5bf0a5f516f7dec71b62bcb6e779de2c269c946d39040e03b3ae12b7 +ad1135ccbc3019d5b2faf59a688eef2500697642be8cfbdf211a1ab59abcc1f24483e50d653b55ff1834675ac7b4978f +a946f05ed9972f71dfde0020bbb086020fa35b482cce8a4cc36dd94355b2d10497d7f2580541bb3e81b71ac8bba3c49f +a83aeed488f9a19d8cfd743aa9aa1982ab3723560b1cd337fc2f91ad82f07afa412b3993afb845f68d47e91ba4869840 +95eebe006bfc316810cb71da919e5d62c2cebb4ac99d8e8ef67be420302320465f8b69873470982de13a7c2e23516be9 +a55f8961295a11e91d1e5deadc0c06c15dacbfc67f04ccba1d069cba89d72aa3b3d64045579c3ea8991b150ac29366ae +b321991d12f6ac07a5de3c492841d1a27b0d3446082fbce93e7e1f9e8d8fe3b45d41253556261c21b70f5e189e1a7a6f +a0b0822f15f652ce7962a4f130104b97bf9529797c13d6bd8e24701c213cc37f18157bd07f3d0f3eae6b7cd1cb40401f +96e2fa4da378aa782cc2d5e6e465fc9e49b5c805ed01d560e9b98abb5c0de8b74a2e7bec3aa5e2887d25cccb12c66f0c +97e4ab610d414f9210ed6f35300285eb3ccff5b0b6a95ed33425100d7725e159708ea78704497624ca0a2dcabce3a2f9 +960a375b17bdb325761e01e88a3ea57026b2393e1d887b34b8fa5d2532928079ce88dc9fd06a728b26d2bb41b12b9032 +8328a1647398e832aadc05bd717487a2b6fcdaa0d4850d2c4da230c6a2ed44c3e78ec4837b6094f3813f1ee99414713f +aa283834ebd18e6c99229ce4b401eda83f01d904f250fedd4e24f1006f8fa0712a6a89a7296a9bf2ce8de30e28d1408e +b29e097f2caadae3e0f0ae3473c072b0cd0206cf6d2e9b22c1a5ad3e07d433e32bd09ed1f4e4276a2da4268633357b7f +9539c5cbba14538b2fe077ecf67694ef240da5249950baaabea0340718b882a966f66d97f08556b08a4320ceb2cc2629 +b4529f25e9b42ae8cf8338d2eface6ba5cd4b4d8da73af502d081388135c654c0b3afb3aa779ffc80b8c4c8f4425dd2b +95be0739c4330619fbe7ee2249c133c91d6c07eab846c18c5d6c85fc21ac5528c5d56dcb0145af68ed0c6a79f68f2ccd +ac0c83ea802227bfc23814a24655c9ff13f729619bcffdb487ccbbf029b8eaee709f8bddb98232ef33cd70e30e45ca47 +b503becb90acc93b1901e939059f93e671900ca52c6f64ae701d11ac891d3a050b505d89324ce267bc43ab8275da6ffe +98e3811b55b1bacb70aa409100abb1b870f67e6d059475d9f278c751b6e1e2e2d6f2e586c81a9fb6597fda06e7923274 +b0b0f61a44053fa6c715dbb0731e35d48dba257d134f851ee1b81fd49a5c51a90ebf5459ec6e489fce25da4f184fbdb1 +b1d2117fe811720bb997c7c93fe9e4260dc50fca8881b245b5e34f724aaf37ed970cdad4e8fcb68e05ac8cf55a274a53 +a10f502051968f14b02895393271776dee7a06db9de14effa0b3471825ba94c3f805302bdddac4d397d08456f620999d +a3dbad2ef060ae0bb7b02eaa4a13594f3f900450faa1854fc09620b01ac94ab896321dfb1157cf2374c27e5718e8026a +b550fdec503195ecb9e079dcdf0cad559d64d3c30818ef369b4907e813e689da316a74ad2422e391b4a8c2a2bef25fc0 +a25ba865e2ac8f28186cea497294c8649a201732ecb4620c4e77b8e887403119910423df061117e5f03fc5ba39042db1 +b3f88174e03fdb443dd6addd01303cf88a4369352520187c739fc5ae6b22fa99629c63c985b4383219dab6acc5f6f532 +97a7503248e31e81b10eb621ba8f5210c537ad11b539c96dfb7cf72b846c7fe81bd7532c5136095652a9618000b7f8d3 +a8bcdc1ce5aa8bfa683a2fc65c1e79de8ff5446695dcb8620f7350c26d2972a23da22889f9e2b1cacb3f688c6a2953dc +8458c111df2a37f5dd91a9bee6c6f4b79f4f161c93fe78075b24a35f9817da8dde71763218d627917a9f1f0c4709c1ed +ac5f061a0541152b876cbc10640f26f1cc923c9d4ae1b6621e4bb3bf2cec59bbf87363a4eb72fb0e5b6d4e1c269b52d5 +a9a25ca87006e8a9203cbb78a93f50a36694aa4aad468b8d80d3feff9194455ca559fcc63838128a0ab75ad78c07c13a +a450b85f5dfffa8b34dfd8bc985f921318efacf8857cf7948f93884ba09fb831482ee90a44224b1a41e859e19b74962f +8ed91e7f92f5c6d7a71708b6132f157ac226ecaf8662af7d7468a4fa25627302efe31e4620ad28719318923e3a59bf82 +ab524165fd4c71b1fd395467a14272bd2b568592deafa039d8492e9ef36c6d3f96927c95c72d410a768dc0b6d1fbbc9b +b662144505aa8432c75ffb8d10318526b6d5777ac7af9ebfad87d9b0866c364f7905a6352743bd8fd79ffd9d5dd4f3e6 +a48f1677550a5cd40663bb3ba8f84caaf8454f332d0ceb1d94dbea52d0412fe69c94997f7749929712fd3995298572f7 +8391cd6e2f6b0c242de1117a612be99776c3dc95cb800b187685ea5bf7e2722275eddb79fd7dfc8be8e389c4524cdf70 +875d3acb9af47833b72900bc0a2448999d638f153c5e97e8a14ec02d0c76f6264353a7e275e1f1a5855daced523d243b +91f1823657d30b59b2f627880a9a9cb530f5aca28a9fd217fe6f2f5133690dfe7ad5a897872e400512db2e788b3f7628 +ad3564332aa56cea84123fc7ca79ea70bb4fef2009fa131cb44e4b15e8613bd11ca1d83b9d9bf456e4b7fee9f2e8b017 +8c530b84001936d5ab366c84c0b105241a26d1fb163669f17c8f2e94776895c2870edf3e1bc8ccd04d5e65531471f695 +932d01fa174fdb0c366f1230cffde2571cc47485f37f23ba5a1825532190cc3b722aeb1f15aed62cf83ccae9403ba713 +88b28c20585aca50d10752e84b901b5c2d58efef5131479fbbe53de7bce2029e1423a494c0298e1497669bd55be97a5d +b914148ca717721144ebb3d3bf3fcea2cd44c30c5f7051b89d8001502f3856fef30ec167174d5b76265b55d70f8716b5 +81d0173821c6ddd2a068d70766d9103d1ee961c475156e0cbd67d54e668a796310474ef698c7ab55abe6f2cf76c14679 +8f28e8d78e2fe7fa66340c53718e0db4b84823c8cfb159c76eac032a62fb53da0a5d7e24ca656cf9d2a890cb2a216542 +8a26360335c73d1ab51cec3166c3cf23b9ea51e44a0ad631b0b0329ef55aaae555420348a544e18d5760969281759b61 +94f326a32ed287545b0515be9e08149eb0a565025074796d72387cc3a237e87979776410d78339e23ef3172ca43b2544 +a785d2961a2fa5e70bffa137858a92c48fe749fee91b02599a252b0cd50d311991a08efd7fa5e96b78d07e6e66ffe746 +94af9030b5ac792dd1ce517eaadcec1482206848bea4e09e55cc7f40fd64d4c2b3e9197027c5636b70d6122c51d2235d +9722869f7d1a3992850fe7be405ec93aa17dc4d35e9e257d2e469f46d2c5a59dbd504056c85ab83d541ad8c13e8bcd54 +b13c4088b61a06e2c03ac9813a75ff1f68ffdfee9df6a8f65095179a475e29cc49119cad2ce05862c3b1ac217f3aace9 +8c64d51774753623666b10ca1b0fe63ae42f82ed6aa26b81dc1d48c86937c5772eb1402624c52a154b86031854e1fb9f +b47e4df18002b7dac3fee945bf9c0503159e1b8aafcce2138818e140753011b6d09ef1b20894e08ba3006b093559061b +93cb5970076522c5a0483693f6a35ffd4ea2aa7aaf3730c4eccd6af6d1bebfc1122fc4c67d53898ae13eb6db647be7e2 +a68873ef80986795ea5ed1a597d1cd99ed978ec25e0abb57fdcc96e89ef0f50aeb779ff46e3dce21dc83ada3157a8498 +8cab67f50949cc8eee6710e27358aea373aae3c92849f8f0b5531c080a6300cdf2c2094fe6fecfef6148de0d28446919 +993e932bcb616dbaa7ad18a4439e0565211d31071ef1b85a0627db74a05d978c60d507695eaeea5c7bd9868a21d06923 +acdadff26e3132d9478a818ef770e9fa0d2b56c6f5f48bd3bd674436ccce9bdfc34db884a73a30c04c5f5e9764cb2218 +a0d3e64c9c71f84c0eef9d7a9cb4fa184224b969db5514d678e93e00f98b41595588ca802643ea225512a4a272f5f534 +91c9140c9e1ba6e330cb08f6b2ce4809cd0d5a0f0516f70032bf30e912b0ed684d07b413b326ab531ee7e5b4668c799b +87bc2ee7a0c21ba8334cd098e35cb703f9af57f35e091b8151b9b63c3a5b0f89bd7701dbd44f644ea475901fa6d9ef08 +9325ccbf64bf5d71b303e31ee85d486298f9802c5e55b2c3d75427097bf8f60fa2ab4fcaffa9b60bf922c3e24fbd4b19 +95d0506e898318f3dc8d28d16dfd9f0038b54798838b3c9be2a2ae3c2bf204eb496166353fc042220b0bd4f6673b9285 +811de529416331fe9c416726d45df9434c29dcd7e949045eb15740f47e97dde8f31489242200e19922cac2a8b7c6fd1f +ade632d04a4c8bbab6ca7df370b2213cb9225023e7973f0e29f4f5e52e8aeaabc65171306bbdd12a67b195dfbb96d48f +88b7f029e079b6ae956042c0ea75d53088c5d0efd750dd018adaeacf46be21bf990897c58578c491f41afd3978d08073 +91f477802de507ffd2be3f4319903119225b277ad24f74eb50f28b66c14d32fae53c7edb8c7590704741af7f7f3e3654 +809838b32bb4f4d0237e98108320d4b079ee16ed80c567e7548bd37e4d7915b1192880f4812ac0e00476d246aec1dbc8 +84183b5fc4a7997a8ae5afedb4d21dce69c480d5966b5cbdafd6dd10d29a9a6377f3b90ce44da0eb8b176ac3af0253bb +8508abbf6d3739a16b9165caf0f95afb3b3ac1b8c38d6d374cf0c91296e2c1809a99772492b539cda184510bce8a0271 +8722054e59bab2062e6419a6e45fc803af77fde912ef2cd23055ad0484963de65a816a2debe1693d93c18218d2b8e81a +8e895f80e485a7c4f56827bf53d34b956281cdc74856c21eb3b51f6288c01cc3d08565a11cc6f3e2604775885490e8c5 +afc92714771b7aa6e60f3aee12efd9c2595e9659797452f0c1e99519f67c8bc3ac567119c1ddfe82a3e961ee9defea9a +818ff0fd9cefd32db87b259e5fa32967201016fc02ef44116cdca3c63ce5e637756f60477a408709928444a8ad69c471 +8251e29af4c61ae806fc5d032347fb332a94d472038149225298389495139ce5678fae739d02dfe53a231598a992e728 +a0ea39574b26643f6f1f48f99f276a8a64b5481989cfb2936f9432a3f8ef5075abfe5c067dc5512143ce8bf933984097 +af67a73911b372bf04e57e21f289fc6c3dfac366c6a01409b6e76fea4769bdb07a6940e52e8d7d3078f235c6d2f632c6 +b5291484ef336024dd2b9b4cf4d3a6b751133a40656d0a0825bcc6d41c21b1c79cb50b0e8f4693f90c29c8f4358641f9 +8bc0d9754d70f2cb9c63f991902165a87c6535a763d5eece43143b5064ae0bcdce7c7a8f398f2c1c29167b2d5a3e6867 +8d7faff53579ec8f6c92f661c399614cc35276971752ce0623270f88be937c414eddcb0997e14724a783905a026c8883 +9310b5f6e675fdf60796f814dbaa5a6e7e9029a61c395761e330d9348a7efab992e4e115c8be3a43d08e90d21290c892 +b5eb4f3eb646038ad2a020f0a42202532d4932e766da82b2c1002bf9c9c2e5336b54c8c0ffcc0e02d19dde2e6a35b6cc +91dabfd30a66710f1f37a891136c9be1e23af4abf8cb751f512a40c022a35f8e0a4fb05b17ec36d4208de02d56f0d53a +b3ded14e82d62ac7a5a036122a62f00ff8308498f3feae57d861babaff5a6628d43f0a0c5fc903f10936bcf4e2758ceb +a88e8348fed2b26acca6784d19ef27c75963450d99651d11a950ea81d4b93acd2c43e0ecce100eaf7e78508263d5baf3 +b1f5bbf7c4756877b87bb42163ac570e08c6667c4528bf68b5976680e19beeff7c5effd17009b0718797077e2955457a +ad2e7b516243f915d4d1415326e98b1a7390ae88897d0b03b66c2d9bd8c3fba283d7e8fe44ed3333296a736454cef6d8 +8f82eae096d5b11f995de6724a9af895f5e1c58d593845ad16ce8fcae8507e0d8e2b2348a0f50a1f66a17fd6fac51a5c +890e4404d0657c6c1ee14e1aac132ecf7a568bb3e04137b85ac0f84f1d333bd94993e8750f88eee033a33fb00f85dcc7 +82ac7d3385e035115f1d39a99fc73e5919de44f5e6424579776d118d711c8120b8e5916372c6f27bed4cc64cac170b6c +85ee16d8901c272cfbbe966e724b7a891c1bd5e68efd5d863043ad8520fc409080af61fd726adc680b3f1186fe0ac8b8 +86dc564c9b545567483b43a38f24c41c6551a49cabeebb58ce86404662a12dbfafd0778d30d26e1c93ce222e547e3898 +a29f5b4522db26d88f5f95f18d459f8feefab02e380c2edb65aa0617a82a3c1a89474727a951cef5f15050bcf7b380fb +a1ce039c8f6cac53352899edb0e3a72c76da143564ad1a44858bd7ee88552e2fe6858d1593bbd74aeee5a6f8034b9b9d +97f10d77983f088286bd7ef3e7fdd8fa275a56bec19919adf33cf939a90c8f2967d2b1b6fc51195cb45ad561202a3ed7 +a25e2772e8c911aaf8712bdac1dd40ee061c84d3d224c466cfaae8e5c99604053f940cde259bd1c3b8b69595781dbfec +b31bb95a0388595149409c48781174c340960d59032ab2b47689911d03c68f77a2273576fbe0c2bf4553e330656058c7 +b8b2e9287ad803fb185a13f0d7456b397d4e3c8ad5078f57f49e8beb2e85f661356a3392dbd7bcf6a900baa5582b86a1 +a3d0893923455eb6e96cc414341cac33d2dbc88fba821ac672708cce131761d85a0e08286663a32828244febfcae6451 +82310cb42f647d99a136014a9f881eb0b9791efd2e01fc1841907ad3fc8a9654d3d1dab6689c3607214b4dc2aca01cee +874022d99c16f60c22de1b094532a0bc6d4de700ad01a31798fac1d5088b9a42ad02bef8a7339af7ed9c0d4f16b186ee +94981369e120265aed40910eebc37eded481e90f4596b8d57c3bec790ab7f929784bd33ddd05b7870aad6c02e869603b +a4f1f50e1e2a73f07095e0dd31cb45154f24968dae967e38962341c1241bcd473102fff1ff668b20c6547e9732d11701 +ae2328f3b0ad79fcda807e69a1b5278145225083f150f67511dafc97e079f860c3392675f1752ae7e864c056e592205b +875d8c971e593ca79552c43d55c8c73b17cd20c81ff2c2fed1eb19b1b91e4a3a83d32df150dbfd5db1092d0aebde1e1f +add2e80aa46aae95da73a11f130f4bda339db028e24c9b11e5316e75ba5e63bc991d2a1da172c7c8e8fee038baae3433 +b46dbe1cb3424002aa7de51e82f600852248e251465c440695d52538d3f36828ff46c90ed77fc1d11534fe3c487df8ef +a5e5045d28b4e83d0055863c30c056628c58d4657e6176fd0536f5933f723d60e851bb726d5bf3c546b8ce4ac4a57ef8 +91fec01e86dd1537e498fff7536ea3ca012058b145f29d9ada49370cd7b7193ac380e116989515df1b94b74a55c45df3 +a7428176d6918cd916a310bdc75483c72de660df48cac4e6e7478eef03205f1827ea55afc0df5d5fa7567d14bbea7fc9 +851d89bef45d9761fe5fdb62972209335193610015e16a675149519f9911373bac0919add226ef118d9f3669cfdf4734 +b74acf5c149d0042021cb2422ea022be4c4f72a77855f42393e71ffd12ebb3eec16bdf16f812159b67b79a9706e7156d +99f35dce64ec99aa595e7894b55ce7b5a435851b396e79036ffb249c28206087db4c85379df666c4d95857db02e21ff9 +b6b9a384f70db9e298415b8ab394ee625dafff04be2886476e59df8d052ca832d11ac68a9b93fba7ab055b7bc36948a4 +898ee4aefa923ffec9e79f2219c7389663eb11eb5b49014e04ed4a336399f6ea1691051d86991f4c46ca65bcd4fdf359 +b0f948217b0d65df7599a0ba4654a5e43c84db477936276e6f11c8981efc6eaf14c90d3650107ed4c09af4cc8ec11137 +aa6286e27ac54f73e63dbf6f41865dd94d24bc0cf732262fcaff67319d162bb43af909f6f8ee27b1971939cfbba08141 +8bca7cdf730cf56c7b2c8a2c4879d61361a6e1dba5a3681a1a16c17a56e168ace0e99cf0d15826a1f5e67e6b8a8a049a +a746d876e8b1ce225fcafca603b099b36504846961526589af977a88c60d31ba2cc56e66a3dec8a77b3f3531bf7524c9 +a11e2e1927e6704cdb8874c75e4f1842cef84d7d43d7a38e339e61dc8ba90e61bbb20dd3c12e0b11d2471d58eed245be +a36395e22bc1d1ba8b0459a235203177737397da5643ce54ded3459d0869ff6d8d89f50c73cb62394bf66a959cde9b90 +8b49f12ba2fdf9aca7e5f81d45c07d47f9302a2655610e7634d1e4bd16048381a45ef2c95a8dd5b0715e4b7cf42273af +91cffa2a17e64eb7f76bccbe4e87280ee1dd244e04a3c9eac12e15d2d04845d876eb24fe2ec6d6d266cce9efb281077f +a6b8afabf65f2dee01788114e33a2f3ce25376fb47a50b74da7c3c25ff1fdc8aa9f41307534abbf48acb6f7466068f69 +8d13db896ccfea403bd6441191995c1a65365cab7d0b97fbe9526da3f45a877bd1f4ef2edef160e8a56838cd1586330e +98c717de9e01bef8842c162a5e757fe8552d53269c84862f4d451e7c656ae6f2ae473767b04290b134773f63be6fdb9d +8c2036ace1920bd13cf018e82848c49eb511fad65fd0ff51f4e4b50cf3bfc294afb63cba682c16f52fb595a98fa84970 +a3520fdff05dbad9e12551b0896922e375f9e5589368bcb2cc303bde252743b74460cb5caf99629325d3620f13adc796 +8d4f83a5bfec05caf5910e0ce538ee9816ee18d0bd44c1d0da2a87715a23cd2733ad4d47552c6dc0eb397687d611dd19 +a7b39a0a6a02823452d376533f39d35029867b3c9a6ad6bca181f18c54132d675613a700f9db2440fb1b4fa13c8bf18a +80bcb114b2544b80f404a200fc36860ed5e1ad31fe551acd4661d09730c452831751baa9b19d7d311600d267086a70bc +90dcce03c6f88fc2b08f2b42771eedde90cc5330fe0336e46c1a7d1b5a6c1641e5fcc4e7b3d5db00bd8afca9ec66ed81 +aec15f40805065c98e2965b1ae12a6c9020cfdb094c2d0549acfc7ea2401a5fb48d3ea7d41133cf37c4e096e7ff53eb9 +80e129b735dba49fa627a615d6c273119acec8e219b2f2c4373a332b5f98d66cbbdd688dfbe72a8f8bfefaccc02c50c1 +a9b596da3bdfe23e6799ece5f7975bf7a1979a75f4f546deeaf8b34dfe3e0d623217cb4cf4ccd504cfa3625b88cd53f1 +abcbbb70b16f6e517c0ab4363ab76b46e4ff58576b5f8340e5c0e8cc0e02621b6e23d742d73b015822a238b17cfd7665 +a046937cc6ea6a2e1adae543353a9fe929c1ae4ad655be1cc051378482cf88b041e28b1e9a577e6ccff2d3570f55e200 +831279437282f315e65a60184ef158f0a3dddc15a648dc552bdc88b3e6fe8288d3cfe9f0031846d81350f5e7874b4b33 +993d7916fa213c6d66e7c4cafafc1eaec9a2a86981f91c31eb8a69c5df076c789cbf498a24c84e0ee77af95b42145026 +823907a3b6719f8d49b3a4b7c181bd9bb29fcf842d7c70660c4f351852a1e197ca46cf5e879b47fa55f616fa2b87ce5e +8d228244e26132b234930ee14c75d88df0943cdb9c276a8faf167d259b7efc1beec2a87c112a6c608ad1600a239e9aae +ab6e55766e5bfb0cf0764ed909a8473ab5047d3388b4f46faeba2d1425c4754c55c6daf6ad4751e634c618b53e549529 +ab0cab6860e55a84c5ad2948a7e0989e2b4b1fd637605634b118361497332df32d9549cb854b2327ca54f2bcb85eed8f +b086b349ae03ef34f4b25a57bcaa5d1b29bd94f9ebf87e22be475adfe475c51a1230c1ebe13506cb72c4186192451658 +8a0b49d8a254ca6d91500f449cbbfbb69bb516c6948ac06808c65595e46773e346f97a5ce0ef7e5a5e0de278af22709c +ac49de11edaaf04302c73c578cc0824bdd165c0d6321be1c421c1950e68e4f3589aa3995448c9699e93c6ebae8803e27 +884f02d841cb5d8f4c60d1402469216b114ab4e93550b5bc1431756e365c4f870a9853449285384a6fa49e12ce6dc654 +b75f3a28fa2cc8d36b49130cb7448a23d73a7311d0185ba803ad55c8219741d451c110f48b786e96c728bc525903a54f +80ae04dbd41f4a35e33f9de413b6ad518af0919e5a30cb0fa1b061b260420780bb674f828d37fd3b52b5a31673cbd803 +b9a8011eb5fcea766907029bf743b45262db3e49d24f84503687e838651ed11cb64c66281e20a0ae9f6aa51acc552263 +90bfdd75e2dc9cf013e22a5d55d2d2b8a754c96103a17524488e01206e67f8b6d52b1be8c4e3d5307d4fe06d0e51f54c +b4af353a19b06203a815ec43e79a88578cc678c46f5a954b85bc5c53b84059dddba731f3d463c23bfd5273885c7c56a4 +aa125e96d4553b64f7140e5453ff5d2330318b69d74d37d283e84c26ad672fa00e3f71e530eb7e28be1e94afb9c4612e +a18e060aee3d49cde2389b10888696436bb7949a79ca7d728be6456a356ea5541b55492b2138da90108bd1ce0e6f5524 +93e55f92bdbccc2de655d14b1526836ea2e52dba65eb3f87823dd458a4cb5079bf22ce6ef625cb6d6bfdd0995ab9a874 +89f5a683526b90c1c3ceebbb8dc824b21cff851ce3531b164f6626e326d98b27d3e1d50982e507d84a99b1e04e86a915 +83d1c38800361633a3f742b1cb2bfc528129496e80232611682ddbe403e92c2ac5373aea0bca93ecb5128b0b2b7a719e +8ecba560ac94905e19ce8d9c7af217bf0a145d8c8bd38e2db82f5e94cc3f2f26f55819176376b51f154b4aab22056059 +a7e2a4a002b60291924850642e703232994acb4cfb90f07c94d1e0ecd2257bb583443283c20fc6017c37e6bfe85b7366 +93ed7316fa50b528f1636fc6507683a672f4f4403e55e94663f91221cc198199595bd02eef43d609f451acc9d9b36a24 +a1220a8ebc5c50ceed76a74bc3b7e0aa77f6884c71b64b67c4310ac29ce5526cb8992d6abc13ef6c8413ce62486a6795 +b2f6eac5c869ad7f4a25161d3347093e2f70e66cd925032747e901189355022fab3038bca4d610d2f68feb7e719c110b +b703fa11a4d511ca01c7462979a94acb40b5d933759199af42670eb48f83df202fa0c943f6ab3b4e1cc54673ea3aab1e +b5422912afbfcb901f84791b04f1ddb3c3fbdc76d961ee2a00c5c320e06d3cc5b5909c3bb805df66c5f10c47a292b13d +ad0934368da823302e1ac08e3ede74b05dfdbfffca203e97ffb0282c226814b65c142e6e15ec1e754518f221f01b30f7 +a1dd302a02e37df15bf2f1147efe0e3c06933a5a767d2d030e1132f5c3ce6b98e216b6145eb39e1e2f74e76a83165b8d +a346aab07564432f802ae44738049a36f7ca4056df2d8f110dbe7fef4a3e047684dea609b2d03dc6bf917c9c2a47608f +b96c5f682a5f5d02123568e50f5d0d186e4b2c4c9b956ec7aabac1b3e4a766d78d19bd111adb5176b898e916e49be2aa +8a96676d56876fc85538db2e806e1cba20fd01aeb9fa3cb43ca6ca94a2c102639f65660db330e5d74a029bb72d6a0b39 +ab0048336bd5c3def1a4064eadd49e66480c1f2abb4df46e03afbd8a3342c2c9d74ee35d79f08f4768c1646681440984 +888427bdf76caec90814c57ee1c3210a97d107dd88f7256f14f883ad0f392334b82be11e36dd8bfec2b37935177c7831 +b622b282becf0094a1916fa658429a5292ba30fb48a4c8066ce1ddcefb71037948262a01c95bab6929ed3a76ba5db9fe +b5b9e005c1f456b6a368a3097634fb455723abe95433a186e8278dceb79d4ca2fbe21f8002e80027b3c531e5bf494629 +a3c6707117a1e48697ed41062897f55d8119403eea6c2ee88f60180f6526f45172664bfee96bf61d6ec0b7fbae6aa058 +b02a9567386a4fbbdb772d8a27057b0be210447348efe6feb935ceec81f361ed2c0c211e54787dc617cdffed6b4a6652 +a9b8364e40ef15c3b5902e5534998997b8493064fa2bea99600def58279bb0f64574c09ba11e9f6f669a8354dd79dc85 +9998a2e553a9aa9a206518fae2bc8b90329ee59ab23005b10972712389f2ec0ee746033c733092ffe43d73d33abbb8ef +843a4b34d9039bf79df96d79f2d15e8d755affb4d83d61872daf540b68c0a3888cf8fc00d5b8b247b38524bcb3b5a856 +84f7128920c1b0bb40eee95701d30e6fc3a83b7bb3709f16d97e72acbb6057004ee7ac8e8f575936ca9dcb7866ab45f7 +918d3e2222e10e05edb34728162a899ad5ada0aaa491aeb7c81572a9c0d506e31d5390e1803a91ff3bd8e2bb15d47f31 +9442d18e2489613a7d47bb1cb803c8d6f3259d088cd079460976d87f7905ee07dea8f371b2537f6e1d792d36d7e42723 +b491976970fe091995b2ed86d629126523ccf3e9daf8145302faca71b5a71a5da92e0e05b62d7139d3efac5c4e367584 +aa628006235dc77c14cef4c04a308d66b07ac92d377df3de1a2e6ecfe3144f2219ad6d7795e671e1cb37a3641910b940 +99d386adaea5d4981d7306feecac9a555b74ffdc218c907c5aa7ac04abaead0ec2a8237300d42a3fbc464673e417ceed +8f78e8b1556f9d739648ea3cab9606f8328b52877fe72f9305545a73b74d49884044ba9c1f1c6db7d9b7c7b7c661caba +8fb357ae49932d0babdf74fc7aa7464a65d3b6a2b3acf4f550b99601d3c0215900cfd67f2b6651ef94cfc323bac79fae +9906f2fa25c0290775aa001fb6198113d53804262454ae8b83ef371b5271bde189c0460a645829cb6c59f9ee3a55ce4d +8f4379b3ebb50e052325b27655ca6a82e6f00b87bf0d2b680d205dd2c7afdc9ff32a9047ae71a1cdf0d0ce6b9474d878 +a85534e88c2bd43c043792eaa75e50914b21741a566635e0e107ae857aed0412035f7576cf04488ade16fd3f35fdbb87 +b4ce93199966d3c23251ca7f28ec5af7efea1763d376b0385352ffb2e0a462ef95c69940950278cf0e3dafd638b7bd36 +b10cb3d0317dd570aa73129f4acf63c256816f007607c19b423fb42f65133ce21f2f517e0afb41a5378cccf893ae14d0 +a9b231c9f739f7f914e5d943ed9bff7eba9e2c333fbd7c34eb1648a362ee01a01af6e2f7c35c9fe962b11152cddf35de +99ff6a899e156732937fb81c0cced80ae13d2d44c40ba99ac183aa246103b31ec084594b1b7feb96da58f4be2dd5c0ed +8748d15d18b75ff2596f50d6a9c4ce82f61ecbcee123a6ceae0e43cab3012a29b6f83cf67b48c22f6f9d757c6caf76b2 +b88ab05e4248b7fb634cf640a4e6a945d13e331237410f7217d3d17e3e384ddd48897e7a91e4516f1b9cbd30f35f238b +8d826deaeeb84a3b2d2c04c2300ca592501f992810582d6ae993e0d52f6283a839dba66c6c72278cff5871802b71173b +b36fed027c2f05a5ef625ca00b0364b930901e9e4420975b111858d0941f60e205546474bb25d6bfa6928d37305ae95f +af2fcfc6b87967567e8b8a13a4ed914478185705724e56ce68fb2df6d1576a0cf34a61e880997a0d35dc2c3276ff7501 +ac351b919cd1fbf106feb8af2c67692bfcddc84762d18cea681cfa7470a5644839caace27efee5f38c87d3df306f4211 +8d6665fb1d4d8d1fa23bd9b8a86e043b8555663519caac214d1e3e3effbc6bee7f2bcf21e645f77de0ced279d69a8a8b +a9fc1c2061756b2a1a169c1b149f212ff7f0d2488acd1c5a0197eba793cffa593fc6d1d1b40718aa75ca3ec77eff10e1 +aff64f0fa009c7a6cf0b8d7a22ddb2c8170c3cb3eec082e60d5aadb00b0040443be8936d728d99581e33c22178c41c87 +82e0b181adc5e3b1c87ff8598447260e839d53debfae941ebea38265575546c3a74a14b4325a030833a62ff6c52d9365 +b7ad43cbb22f6f892c2a1548a41dc120ab1f4e1b8dea0cb6272dd9cb02054c542ecabc582f7e16de709d48f5166cae86 +985e0c61094281532c4afb788ecb2dfcba998e974b5d4257a22040a161883908cdd068fe80f8eb49b8953cfd11acf43a +ae46895c6d67ea6d469b6c9c07b9e5d295d9ae73b22e30da4ba2c973ba83a130d7eef39717ec9d0f36e81d56bf742671 +8600177ea1f7e7ef90514b38b219a37dedfc39cb83297e4c7a5b479817ef56479d48cf6314820960c751183f6edf8b0e +b9208ec1c1d7a1e99b59c62d3e4e61dfb706b0e940d09d3abfc3454c19749083260614d89cfd7e822596c3cdbcc6bb95 +a1e94042c796c2b48bc724352d2e9f3a22291d9a34705993357ddb6adabd76da6fc25dac200a8cb0b5bbd99ecddb7af6 +b29c3adedd0bcad8a930625bc4dfdc3552a9afd5ca6dd9c0d758f978068c7982b50b711aa0eb5b97f2b84ee784637835 +af0632a238bb1f413c7ea8e9b4c3d68f2827bd2e38cd56024391fba6446ac5d19a780d0cfd4a78fe497d537b766a591a +aaf6e7f7d54f8ef5e2e45dd59774ecbeecf8683aa70483b2a75be6a6071b5981bbaf1627512a65d212817acdfab2e428 +8c751496065da2e927cf492aa5ca9013b24f861d5e6c24b30bbf52ec5aaf1905f40f9a28175faef283dd4ed4f2182a09 +8952377d8e80a85cf67d6b45499f3bad5fd452ea7bcd99efc1b066c4720d8e5bff1214cea90fd1f972a7f0baac3d29be +a1946ee543d1a6e21f380453be4d446e4130950c5fc3d075794eb8260f6f52d0a795c1ff91d028a648dc1ce7d9ab6b47 +89f3fefe37af31e0c17533d2ca1ce0884cc1dc97c15cbfab9c331b8debd94781c9396abef4bb2f163d09277a08d6adf0 +a2753f1e6e1a154fb117100a5bd9052137add85961f8158830ac20541ab12227d83887d10acf7fd36dcaf7c2596d8d23 +814955b4198933ee11c3883863b06ff98c7eceb21fc3e09df5f916107827ccf3323141983e74b025f46ae00284c9513b +8cc5c6bb429073bfef47cae7b3bfccb0ffa076514d91a1862c6bda4d581e0df87db53cc6c130bf8a7826304960f5a34e +909f22c1f1cdc87f7be7439c831a73484a49acbf8f23d47087d7cf867c64ef61da3bde85dc57d705682b4c3fc710d36e +8048fee7f276fcd504aed91284f28e73693615e0eb3858fa44bcf79d7285a9001c373b3ef71d9a3054817ba293ebe28c +94400e5cf5d2700ca608c5fe35ce14623f71cc24959f2bc27ca3684092850f76b67fb1f07ca9e5b2ca3062cf8ad17bd4 +81c2ae7d4d1b17f8b6de6a0430acc0d58260993980fe48dc2129c4948269cdc74f9dbfbf9c26b19360823fd913083d48 +8c41fe765128e63f6889d6a979f6a4342300327c8b245a8cfe3ecfbcac1e09c3da30e2a1045b24b78efc6d6d50c8c6ac +a5dd4ae51ae48c8be4b218c312ade226cffce671cf121cb77810f6c0990768d6dd767badecb5c69921d5574d5e8433d3 +b7642e325f4ba97ae2a39c1c9d97b35aafd49d53dba36aed3f3cb0ca816480b3394079f46a48252d46596559c90f4d58 +ae87375b40f35519e7bd4b1b2f73cd0b329b0c2cb9d616629342a71c6c304338445eda069b78ea0fbe44087f3de91e09 +b08918cb6f736855e11d3daca1ddfbdd61c9589b203b5493143227bf48e2c77c2e8c94b0d1aa2fab2226e0eae83f2681 +ac36b84a4ac2ebd4d6591923a449c564e3be8a664c46092c09e875c2998eba16b5d32bfd0882fd3851762868e669f0b1 +a44800a3bb192066fa17a3f29029a23697240467053b5aa49b9839fb9b9b8b12bcdcbfc557f024b61f4f51a9aacdefcb +9064c688fec23441a274cdf2075e5a449caf5c7363cc5e8a5dc9747183d2e00a0c69f2e6b3f6a7057079c46014c93b3b +aa367b021469af9f5b764a79bb3afbe2d87fe1e51862221672d1a66f954b165778b7c27a705e0f93841fab4c8468344d +a1a8bfc593d4ab71f91640bc824de5c1380ab2591cfdafcbc78a14b32de3c0e15f9d1b461d85c504baa3d4232c16bb53 +97df48da1799430f528184d30b6baa90c2a2f88f34cdfb342d715339c5ebd6d019aa693cea7c4993daafc9849063a3aa +abd923831fbb427e06e0dd335253178a9e5791395c84d0ab1433c07c53c1209161097e9582fb8736f8a60bde62d8693e +84cd1a43f1a438b43dc60ffc775f646937c4f6871438163905a3cebf1115f814ccd38a6ccb134130bff226306e412f32 +91426065996b0743c5f689eb3ca68a9f7b9e4d01f6c5a2652b57fa9a03d8dc7cd4bdbdab0ca5a891fee1e97a7f00cf02 +a4bee50249db3df7fd75162b28f04e57c678ba142ce4d3def2bc17bcb29e4670284a45f218dad3969af466c62a903757 +83141ebcc94d4681404e8b67a12a46374fded6df92b506aff3490d875919631408b369823a08b271d006d5b93136f317 +a0ea1c8883d58d5a784da3d8c8a880061adea796d7505c1f903d07c287c5467f71e4563fc0faafbc15b5a5538b0a7559 +89d9d480574f201a87269d26fb114278ed2c446328df431dc3556e3500e80e4cd01fcac196a2459d8646361ebda840df +8bf302978973632dd464bec819bdb91304712a3ec859be071e662040620422c6e75eba6f864f764cffa2799272efec39 +922f666bc0fd58b6d7d815c0ae4f66d193d32fc8382c631037f59eeaeae9a8ca6c72d08e72944cf9e800b8d639094e77 +81ad8714f491cdff7fe4399f2eb20e32650cff2999dd45b9b3d996d54a4aba24cc6c451212e78c9e5550368a1a38fb3f +b58fcf4659d73edb73175bd9139d18254e94c3e32031b5d4b026f2ed37aa19dca17ec2eb54c14340231615277a9d347e +b365ac9c2bfe409b710928c646ea2fb15b28557e0f089d39878e365589b9d1c34baf5566d20bb28b33bb60fa133f6eff +8fcae1d75b53ab470be805f39630d204853ca1629a14158bac2f52632277d77458dec204ff84b7b2d77e641c2045be65 +a03efa6bebe84f4f958a56e2d76b5ba4f95dd9ed7eb479edc7cc5e646c8d4792e5b0dfc66cc86aa4b4afe2f7a4850760 +af1c823930a3638975fb0cc5c59651771b2719119c3cd08404fbd4ce77a74d708cefbe3c56ea08c48f5f10e6907f338f +8260c8299b17898032c761c325ac9cabb4c5b7e735de81eacf244f647a45fb385012f4f8df743128888c29aefcaaad16 +ab2f37a573c82e96a8d46198691cd694dfa860615625f477e41f91b879bc58a745784fccd8ffa13065834ffd150d881d +986c746c9b4249352d8e5c629e8d7d05e716b3c7aab5e529ca969dd1e984a14b5be41528baef4c85d2369a42d7209216 +b25e32da1a8adddf2a6080725818b75bc67240728ad1853d90738485d8924ea1e202df0a3034a60ffae6f965ec55cf63 +a266e627afcebcefea6b6b44cbc50f5c508f7187e87d047b0450871c2a030042c9e376f3ede0afcf9d1952f089582f71 +86c3bbca4c0300606071c0a80dbdec21ce1dd4d8d4309648151c420854032dff1241a1677d1cd5de4e4de4385efda986 +b9a21a1fe2d1f3273a8e4a9185abf2ff86448cc98bfa435e3d68306a2b8b4a6a3ea33a155be3cb62a2170a86f77679a5 +b117b1ea381adce87d8b342cba3a15d492ff2d644afa28f22424cb9cbc820d4f7693dfc1a4d1b3697046c300e1c9b4c8 +9004c425a2e68870d6c69b658c344e3aa3a86a8914ee08d72b2f95c2e2d8a4c7bb0c6e7e271460c0e637cec11117bf8e +86a18aa4783b9ebd9131580c8b17994825f27f4ac427b0929a1e0236907732a1c8139e98112c605488ee95f48bbefbfc +84042243b955286482ab6f0b5df4c2d73571ada00716d2f737ca05a0d2e88c6349e8ee9e67934cfee4a1775dbf7f4800 +92c2153a4733a62e4e1d5b60369f3c26777c7d01cd3c8679212660d572bd3bac9b8a8a64e1f10f7dbf5eaa7579c4e423 +918454b6bb8e44a2afa144695ba8d48ae08d0cdfef4ad078f67709eddf3bb31191e8b006f04e82ea45a54715ef4d5817 +acf0b54f6bf34cf6ed6c2b39cf43194a40d68de6bcf1e4b82c34c15a1343e9ac3737885e1a30b78d01fa3a5125463db8 +a7d60dbe4b6a7b054f7afe9ee5cbbfeca0d05dc619e6041fa2296b549322529faddb8a11e949562309aecefb842ac380 +91ffb53e6d7e5f11159eaf13e783d6dbdfdb1698ed1e6dbf3413c6ea23492bbb9e0932230a9e2caac8fe899a17682795 +b6e8d7be5076ee3565d5765a710c5ecf17921dd3cf555c375d01e958a365ae087d4a88da492a5fb81838b7b92bf01143 +a8c6b763de2d4b2ed42102ef64eccfef31e2fb2a8a2776241c82912fa50fc9f77f175b6d109a97ede331307c016a4b1a +99839f86cb700c297c58bc33e28d46b92931961548deac29ba8df91d3e11721b10ea956c8e16984f9e4acf1298a79b37 +8c2e2c338f25ea5c25756b7131cde0d9a2b35abf5d90781180a00fe4b8e64e62590dc63fe10a57fba3a31c76d784eb01 +9687d7df2f41319ca5469d91978fed0565a5f11f829ebadaa83db92b221755f76c6eacd7700735e75c91e257087512e3 +8795fdfb7ff8439c58b9bf58ed53873d2780d3939b902b9ddaaa4c99447224ced9206c3039a23c2c44bcc461e2bb637f +a803697b744d2d087f4e2307218d48fa88620cf25529db9ce71e2e3bbcc65bac5e8bb9be04777ef7bfb5ed1a5b8e6170 +80f3d3efbbb9346ddd413f0a8e36b269eb5d7ff6809d5525ff9a47c4bcab2c01b70018b117f6fe05253775612ff70c6b +9050e0e45bcc83930d4c505af35e5e4d7ca01cd8681cba92eb55821aececcebe32bb692ebe1a4daac4e7472975671067 +8d206812aac42742dbaf233e0c080b3d1b30943b54b60283515da005de05ea5caa90f91fedcfcba72e922f64d7040189 +a2d44faaeb2eff7915c83f32b13ca6f31a6847b1c1ce114ea240bac3595eded89f09b2313b7915ad882292e2b586d5b4 +961776c8576030c39f214ea6e0a3e8b3d32f023d2600958c098c95c8a4e374deeb2b9dc522adfbd6bda5949bdc09e2a2 +993fa7d8447407af0fbcd9e6d77f815fa5233ab00674efbcf74a1f51c37481445ae291cc7b76db7c178f9cb0e570e0fc +abd5b1c78e05f9d7c8cc99bdaef8b0b6a57f2daf0f02bf492bec48ea4a27a8f1e38b5854da96efff11973326ff980f92 +8f15af4764bc275e6ccb892b3a4362cacb4e175b1526a9a99944e692fe6ccb1b4fc19abf312bb2a089cb1f344d91a779 +a09b27ccd71855512aba1d0c30a79ffbe7f6707a55978f3ced50e674b511a79a446dbc6d7946add421ce111135a460af +94b2f98ce86a9271fbd4153e1fc37de48421fe3490fb3840c00f2d5a4d0ba8810c6a32880b002f6374b59e0a7952518b +8650ac644f93bbcb88a6a0f49fee2663297fd4bc6fd47b6a89b9d8038d32370438ab3a4775ec9b58cb10aea8a95ef7b6 +95e5c2f2e84eed88c6980bbba5a1c0bb375d5a628bff006f7516d45bb7d723da676add4fdd45956f312e7bab0f052644 +b3278a3fa377ac93af7cfc9453f8cb594aae04269bbc99d2e0e45472ff4b6a2f97a26c4c57bf675b9d86f5e77a5d55d1 +b4bcbe6eb666a206e2ea2f877912c1d3b5bdbd08a989fc4490eb06013e1a69ad1ba08bcdac048bf29192312be399077b +a76d70b78c99fffcbf9bb9886eab40f1ea4f99a309710b660b64cbf86057cbcb644d243f6e341711bb7ef0fedf0435a7 +b2093c1ee945dca7ac76ad5aed08eae23af31dd5a77c903fd7b6f051f4ab84425d33a03c3d45bf2907bc93c02d1f3ad8 +904b1f7534e053a265b22d20be859912b9c9ccb303af9a8d6f1d8f6ccdc5c53eb4a45a1762b880d8444d9be0cd55e7f9 +8f664a965d65bc730c9ef1ec7467be984d4b8eb46bd9b0d64e38e48f94e6e55dda19aeac82cbcf4e1473440e64c4ca18 +8bcee65c4cc7a7799353d07b114c718a2aae0cd10a3f22b7eead5185d159dafd64852cb63924bf87627d176228878bce +8c78f2e3675096fef7ebaa898d2615cd50d39ca3d8f02b9bdfb07e67da648ae4be3da64838dffc5935fd72962c4b96c7 +8c40afd3701629421fec1df1aac4e849384ef2e80472c0e28d36cb1327acdf2826f99b357f3d7afdbc58a6347fc40b3c +a197813b1c65a8ea5754ef782522a57d63433ef752215ecda1e7da76b0412ee619f58d904abd2e07e0c097048b6ae1dd +a670542629e4333884ad7410f9ea3bd6f988df4a8f8a424ca74b9add2312586900cf9ae8bd50411f9146e82626b4af56 +a19875cc07ab84e569d98b8b67fb1dbbdfb59093c7b748fae008c8904a6fd931a63ca8d03ab5fea9bc8d263568125a9b +b57e7f68e4eb1bd04aafa917b1db1bdab759a02aa8a9cdb1cba34ba8852b5890f655645c9b4e15d5f19bf37e9f2ffe9f +8abe4e2a4f6462b6c64b3f10e45db2a53c2b0d3c5d5443d3f00a453e193df771eda635b098b6c8604ace3557514027af +8459e4fb378189b22b870a6ef20183deb816cefbf66eca1dc7e86d36a2e011537db893729f500dc154f14ce24633ba47 +930851df4bc7913c0d8c0f7bd3b071a83668987ed7c397d3d042fdc0d9765945a39a3bae83da9c88cb6b686ed8aeeb26 +8078c9e5cd05e1a8c932f8a1d835f61a248b6e7133fcbb3de406bf4ffc0e584f6f9f95062740ba6008d98348886cf76b +addff62bb29430983fe578e3709b0949cdc0d47a13a29bc3f50371a2cb5c822ce53e2448cfaa01bcb6e0aa850d5a380e +9433add687b5a1e12066721789b1db2edf9b6558c3bdc0f452ba33b1da67426abe326e9a34d207bfb1c491c18811bde1 +822beda3389963428cccc4a2918fa9a8a51cf0919640350293af70821967108cded5997adae86b33cb917780b097f1ca +a7a9f52bda45e4148ed56dd176df7bd672e9b5ed18888ccdb405f47920fdb0844355f8565cefb17010b38324edd8315f +b35c3a872e18e607b2555c51f9696a17fa18da1f924d503b163b4ec9fe22ed0c110925275cb6c93ce2d013e88f173d6a +adf34b002b2b26ab84fc1bf94e05bd8616a1d06664799ab149363c56a6e0c807fdc473327d25632416e952ea327fcd95 +ae4a6b9d22a4a3183fac29e2551e1124a8ce4a561a9a2afa9b23032b58d444e6155bb2b48f85c7b6d70393274e230db7 +a2ea3be4fc17e9b7ce3110284038d46a09e88a247b6971167a7878d9dcf36925d613c382b400cfa4f37a3ebea3699897 +8e5863786b641ce3140fbfe37124d7ad3925472e924f814ebfc45959aaf3f61dc554a597610b5defaecc85b59a99b50f +aefde3193d0f700d0f515ab2aaa43e2ef1d7831c4f7859f48e52693d57f97fa9e520090f3ed700e1c966f4b76048e57f +841a50f772956622798e5cd208dc7534d4e39eddee30d8ce133383d66e5f267e389254a0cdae01b770ecd0a9ca421929 +8fbc2bfd28238c7d47d4c03b1b910946c0d94274a199575e5b23242619b1de3497784e646a92aa03e3e24123ae4fcaba +926999579c8eec1cc47d7330112586bdca20b4149c8b2d066f527c8b9f609e61ce27feb69db67eea382649c6905efcf9 +b09f31f305efcc65589adf5d3690a76cf339efd67cd43a4e3ced7b839507466e4be72dd91f04e89e4bbef629d46e68c0 +b917361f6b95f759642638e0b1d2b3a29c3bdef0b94faa30de562e6078c7e2d25976159df3edbacbf43614635c2640b4 +8e7e8a1253bbda0e134d62bfe003a2669d471b47bd2b5cde0ff60d385d8e62279d54022f5ac12053b1e2d3aaa6910b4c +b69671a3c64e0a99d90b0ed108ce1912ff8ed983e4bddd75a370e9babde25ee1f5efb59ec707edddd46793207a8b1fe7 +910b2f4ebd37b7ae94108922b233d0920b4aba0bd94202c70f1314418b548d11d8e9caa91f2cd95aff51b9432d122b7f +82f645c90dfb52d195c1020346287c43a80233d3538954548604d09fbab7421241cde8593dbc4acc4986e0ea39a27dd9 +8fee895f0a140d88104ce442fed3966f58ff9d275e7373483f6b4249d64a25fb5374bbdc6bce6b5ab0270c2847066f83 +84f5bd7aab27b2509397aeb86510dd5ac0a53f2c8f73799bf720f2f87a52277f8d6b0f77f17bc80739c6a7119b7eb062 +9903ceced81099d7e146e661bcf01cbaccab5ba54366b85e2177f07e2d8621e19d9c9c3eee14b9266de6b3f9b6ea75ae +b9c16ea2a07afa32dd6c7c06df0dec39bca2067a9339e45475c98917f47e2320f6f235da353fd5e15b477de97ddc68dd +9820a9bbf8b826bec61ebf886de2c4f404c1ebdc8bab82ee1fea816d9de29127ce1852448ff717a3fe8bbfe9e92012e5 +817224d9359f5da6f2158c2c7bf9165501424f063e67ba9859a07ab72ee2ee62eb00ca6da821cfa19065c3282ca72c74 +94b95c465e6cb00da400558a3c60cfec4b79b27e602ca67cbc91aead08de4b6872d8ea096b0dc06dca4525c8992b8547 +a2b539a5bccd43fa347ba9c15f249b417997c6a38c63517ca38394976baa08e20be384a360969ff54e7e721db536b3e5 +96caf707e34f62811ee8d32ccf28d8d6ec579bc33e424d0473529af5315c456fd026aa910c1fed70c91982d51df7d3ca +8a77b73e890b644c6a142bdbac59b22d6a676f3b63ddafb52d914bb9d395b8bf5aedcbcc90429337df431ebd758a07a6 +8857830a7351025617a08bc44caec28d2fae07ebf5ffc9f01d979ce2a53839a670e61ae2783e138313929129790a51a1 +aa3e420321ed6f0aa326d28d1a10f13facec6f605b6218a6eb9cbc074801f3467bf013a456d1415a5536f12599efa3d3 +824aed0951957b00ea2f3d423e30328a3527bf6714cf9abbae84cf27e58e5c35452ba89ccc011de7c68c75d6e021d8f1 +a2e87cc06bf202e953fb1081933d8b4445527dde20e38ed1a4f440144fd8fa464a2b73e068b140562e9045e0f4bd3144 +ae3b8f06ad97d7ae3a5e5ca839efff3e4824dc238c0c03fc1a8d2fc8aa546cdfd165b784a31bb4dec7c77e9305b99a4b +b30c3e12395b1fb8b776f3ec9f87c70e35763a7b2ddc68f0f60a4982a84017f27c891a98561c830038deb033698ed7fc +874e507757cd1177d0dff0b0c62ce90130324442a33da3b2c8ee09dbca5d543e3ecfe707e9f1361e7c7db641c72794bb +b53012dd10b5e7460b57c092eaa06d6502720df9edbbe3e3f61a9998a272bf5baaac4a5a732ad4efe35d6fac6feca744 +85e6509d711515534d394e6cacbed6c81da710074d16ef3f4950bf2f578d662a494d835674f79c4d6315bced4defc5f0 +b6132b2a34b0905dcadc6119fd215419a7971fe545e52f48b768006944b4a9d7db1a74b149e2951ea48c083b752d0804 +989867da6415036d19b4bacc926ce6f4df7a556f50a1ba5f3c48eea9cefbb1c09da81481c8009331ee83f0859185e164 +960a6c36542876174d3fbc1505413e29f053ed87b8d38fef3af180491c7eff25200b45dd5fe5d4d8e63c7e8c9c00f4c8 +9040b59bd739d9cc2e8f6e894683429e4e876a8106238689ff4c22770ae5fdae1f32d962b30301fa0634ee163b524f35 +af3fcd0a45fe9e8fe256dc7eab242ef7f582dd832d147444483c62787ac820fafc6ca55d639a73f76bfa5e7f5462ab8f +b934c799d0736953a73d91e761767fdb78454355c4b15c680ce08accb57ccf941b13a1236980001f9e6195801cffd692 +8871e8e741157c2c326b22cf09551e78da3c1ec0fc0543136f581f1550f8bab03b0a7b80525c1e99812cdbf3a9698f96 +a8a977f51473a91d178ee8cfa45ffef8d6fd93ab1d6e428f96a3c79816d9c6a93cd70f94d4deda0125fd6816e30f3bea +a7688b3b0a4fc1dd16e8ba6dc758d3cfe1b7cf401c31739484c7fa253cce0967df1b290769bcefc9d23d3e0cb19e6218 +8ae84322662a57c6d729e6ff9d2737698cc2da2daeb1f39e506618750ed23442a6740955f299e4a15dda6db3e534d2c6 +a04a961cdccfa4b7ef83ced17ab221d6a043b2c718a0d6cc8e6f798507a31f10bf70361f70a049bc8058303fa7f96864 +b463e39732a7d9daec8a456fb58e54b30a6e160aa522a18b9a9e836488cce3342bcbb2e1deab0f5e6ec0a8796d77197d +b1434a11c6750f14018a2d3bcf94390e2948f4f187e93bb22070ca3e5393d339dc328cbfc3e48815f51929465ffe7d81 +84ff81d73f3828340623d7e3345553610aa22a5432217ef0ebd193cbf4a24234b190c65ca0873c22d10ea7b63bd1fbed +b6fe2723f0c47757932c2ddde7a4f8434f665612f7b87b4009c2635d56b6e16b200859a8ade49276de0ef27a2b6c970a +9742884ed7cd52b4a4a068a43d3faa02551a424136c85a9313f7cb58ea54c04aa83b0728fd741d1fe39621e931e88f8f +b7d2d65ea4d1ad07a5dee39e40d6c03a61264a56b1585b4d76fc5b2a68d80a93a42a0181d432528582bf08d144c2d6a9 +88c0f66bada89f8a43e5a6ead2915088173d106c76f724f4a97b0f6758aed6ae5c37c373c6b92cdd4aea8f6261f3a374 +81f9c43582cb42db3900747eb49ec94edb2284999a499d1527f03315fd330e5a509afa3bff659853570e9886aab5b28b +821f9d27d6beb416abf9aa5c79afb65a50ed276dbda6060103bc808bcd34426b82da5f23e38e88a55e172f5c294b4d40 +8ba307b9e7cb63a6c4f3851b321aebfdb6af34a5a4c3bd949ff7d96603e59b27ff4dc4970715d35f7758260ff942c9e9 +b142eb6c5f846de33227d0bda61d445a7c33c98f0a8365fe6ab4c1fabdc130849be597ef734305894a424ea715372d08 +a732730ae4512e86a741c8e4c87fee8a05ee840fec0e23b2e037d58dba8dde8d10a9bc5191d34d00598941becbbe467f +adce6f7c30fd221f6b10a0413cc76435c4bb36c2d60bca821e5c67409fe9dbb2f4c36ef85eb3d734695e4be4827e9fd3 +a74f00e0f9b23aff7b2527ce69852f8906dab9d6abe62ecd497498ab21e57542e12af9918d4fd610bb09e10b0929c510 +a593b6b0ef26448ce4eb3ab07e84238fc020b3cb10d542ff4b16d4e2be1bcde3797e45c9cf753b8dc3b0ffdb63984232 +aed3913afccf1aa1ac0eb4980eb8426d0baccebd836d44651fd72af00d09fac488a870223c42aca3ceb39752070405ae +b2c44c66a5ea7fde626548ba4cef8c8710191343d3dadfd3bb653ce715c0e03056a5303a581d47dde66e70ea5a2d2779 +8e5029b2ccf5128a12327b5103f7532db599846e422531869560ceaff392236434d87159f597937dbf4054f810c114f4 +82beed1a2c4477e5eb39fc5b0e773b30cfec77ef2b1bf17eadaf60eb35b6d0dd9d8cf06315c48d3546badb3f21cd0cca +90077bd6cc0e4be5fff08e5d07a5a158d36cebd1d1363125bc4fae0866ffe825b26f933d4ee5427ba5cd0c33c19a7b06 +a7ec0d8f079970e8e34f0ef3a53d3e0e45428ddcef9cc776ead5e542ef06f3c86981644f61c5a637e4faf001fb8c6b3e +ae6d4add6d1a6f90b22792bc9d40723ee6850c27d0b97eefafd5b7fd98e424aa97868b5287cc41b4fbd7023bca6a322c +831aa917533d077da07c01417feaa1408846363ba2b8d22c6116bb858a95801547dd88b7d7fa1d2e3f0a02bdeb2e103d +96511b860b07c8a5ed773f36d4aa9d02fb5e7882753bf56303595bcb57e37ccc60288887eb83bef08c657ec261a021a2 +921d2a3e7e9790f74068623de327443666b634c8443aba80120a45bba450df920b2374d96df1ce3fb1b06dd06f8cf6e3 +aa74451d51fe82b4581ead8e506ec6cd881010f7e7dd51fc388eb9a557db5d3c6721f81c151d08ebd9c2591689fbc13e +a972bfbcf4033d5742d08716c927c442119bdae336bf5dff914523b285ccf31953da2733759aacaa246a9af9f698342c +ad1fcd0cae0e76840194ce4150cb8a56ebed728ec9272035f52a799d480dfc85840a4d52d994a18b6edb31e79be6e8ad +a2c69fe1d36f235215432dad48d75887a44c99dfa0d78149acc74087da215a44bdb5f04e6eef88ff7eff80a5a7decc77 +a94ab2af2b6ee1bc6e0d4e689ca45380d9fbd3c5a65b9bd249d266a4d4c07bf5d5f7ef2ae6000623aee64027892bf8fe +881ec1fc514e926cdc66480ac59e139148ff8a2a7895a49f0dff45910c90cdda97b66441a25f357d6dd2471cddd99bb3 +884e6d3b894a914c8cef946a76d5a0c8351843b2bffa2d1e56c6b5b99c84104381dd1320c451d551c0b966f4086e60f9 +817c6c10ce2677b9fc5223500322e2b880583254d0bb0d247d728f8716f5e05c9ff39f135854342a1afecd9fbdcf7c46 +aaf4a9cb686a14619aa1fc1ac285dd3843ac3dd99f2b2331c711ec87b03491c02f49101046f3c5c538dc9f8dba2a0ac2 +97ecea5ce53ca720b5d845227ae61d70269a2f53540089305c86af35f0898bfd57356e74a8a5e083fa6e1ea70080bd31 +a22d811e1a20a75feac0157c418a4bfe745ccb5d29466ffa854dca03e395b6c3504a734341746b2846d76583a780b32e +940cbaa0d2b2db94ae96b6b9cf2deefbfd059e3e5745de9aec4a25f0991b9721e5cd37ef71c631575d1a0c280b01cd5b +ae33cb4951191258a11044682de861bf8d92d90ce751b354932dd9f3913f542b6a0f8a4dc228b3cd9244ac32c4582832 +a580df5e58c4274fe0f52ac2da1837e32f5c9db92be16c170187db4c358f43e5cfdda7c5911dcc79d77a5764e32325f5 +81798178cb9d8affa424f8d3be67576ba94d108a28ccc01d330c51d5a63ca45bb8ca63a2f569b5c5fe1303cecd2d777f +89975b91b94c25c9c3660e4af4047a8bacf964783010820dbc91ff8281509379cb3b24c25080d5a01174dd9a049118d5 +a7327fcb3710ed3273b048650bde40a32732ef40a7e58cf7f2f400979c177944c8bc54117ba6c80d5d4260801dddab79 +92b475dc8cb5be4b90c482f122a51bcb3b6c70593817e7e2459c28ea54a7845c50272af38119406eaadb9bcb993368d0 +9645173e9ecefc4f2eae8363504f7c0b81d85f8949a9f8a6c01f2d49e0a0764f4eacecf3e94016dd407fc14494fce9f9 +9215fd8983d7de6ae94d35e6698226fc1454977ae58d42d294be9aad13ac821562ad37d5e7ee5cdfe6e87031d45cd197 +810360a1c9b88a9e36f520ab5a1eb8bed93f52deefbe1312a69225c0a08edb10f87cc43b794aced9c74220cefcc57e7d +ad7e810efd61ed4684aeda9ed8bb02fb9ae4b4b63fda8217d37012b94ff1b91c0087043bfa4e376f961fff030c729f3b +8b07c95c6a06db8738d10bb03ec11b89375c08e77f0cab7e672ce70b2685667ca19c7e1c8b092821d31108ea18dfd4c7 +968825d025ded899ff7c57245250535c732836f7565eab1ae23ee7e513201d413c16e1ba3f5166e7ac6cf74de8ceef4f +908243370c5788200703ade8164943ad5f8c458219186432e74dbc9904a701ea307fd9b94976c866e6c58595fd891c4b +959969d16680bc535cdc6339e6186355d0d6c0d53d7bbfb411641b9bf4b770fd5f575beef5deec5c4fa4d192d455c350 +ad177f4f826a961adeac76da40e2d930748effff731756c797eddc4e5aa23c91f070fb69b19221748130b0961e68a6bb +82f8462bcc25448ef7e0739425378e9bb8a05e283ce54aae9dbebaf7a3469f57833c9171672ad43a79778366c72a5e37 +a28fb275b1845706c2814d9638573e9bc32ff552ebaed761fe96fdbce70395891ca41c400ae438369264e31a2713b15f +8a9c613996b5e51dadb587a787253d6081ea446bf5c71096980bf6bd3c4b69905062a8e8a3792de2d2ece3b177a71089 +8d5aefef9f60cb27c1db2c649221204dda48bb9bf8bf48f965741da051340e8e4cab88b9d15c69f3f84f4c854709f48a +93ebf2ca6ad85ab6deace6de1a458706285b31877b1b4d7dcb9d126b63047efaf8c06d580115ec9acee30c8a7212fa55 +b3ee46ce189956ca298057fa8223b7fd1128cf52f39159a58bca03c71dd25161ac13f1472301f72aef3e1993fe1ab269 +a24d7a8d066504fc3f5027ccb13120e2f22896860e02c45b5eba1dbd512d6a17c28f39155ea581619f9d33db43a96f92 +ae9ceacbfe12137db2c1a271e1b34b8f92e4816bad1b3b9b6feecc34df0f8b3b0f7ed0133acdf59c537d43d33fc8d429 +83967e69bf2b361f86361bd705dce0e1ad26df06da6c52b48176fe8dfcbeb03c462c1a4c9e649eff8c654b18c876fdef +9148e6b814a7d779c19c31e33a068e97b597de1f8100513db3c581190513edc4d544801ce3dd2cf6b19e0cd6daedd28a +94ccdafc84920d320ed22de1e754adea072935d3c5f8c2d1378ebe53d140ea29853f056fb3fb1e375846061a038cc9bc +afb43348498c38b0fa5f971b8cdd3a62c844f0eb52bc33daf2f67850af0880fce84ecfb96201b308d9e6168a0d443ae3 +86d5736520a83538d4cd058cc4b4e84213ed00ebd6e7af79ae787adc17a92ba5359e28ba6c91936d967b4b28d24c3070 +b5210c1ff212c5b1e9ef9126e08fe120a41e386bb12c22266f7538c6d69c7fd8774f11c02b81fd4e88f9137b020801fe +b78cfd19f94d24e529d0f52e18ce6185cb238edc6bd43086270fd51dd99f664f43dd4c7d2fe506762fbd859028e13fcf +a6e7220598c554abdcc3fdc587b988617b32c7bb0f82c06205467dbedb58276cc07cae317a190f19d19078773f4c2bbb +b88862809487ee430368dccd85a5d72fa4d163ca4aad15c78800e19c1a95be2192719801e315d86cff7795e0544a77e4 +87ecb13a03921296f8c42ceb252d04716f10e09c93962239fcaa0a7fef93f19ab3f2680bc406170108bc583e9ff2e721 +a810cd473832b6581c36ec4cb403f2849357ba2d0b54df98ef3004b8a530c078032922a81d40158f5fb0043d56477f6e +a247b45dd85ca7fbb718b328f30a03f03c84aef2c583fbdc9fcc9eb8b52b34529e8c8f535505c10598b1b4dac3d7c647 +96ee0b91313c68bac4aa9e065ce9e1d77e51ca4cff31d6a438718c58264dee87674bd97fc5c6b8008be709521e4fd008 +837567ad073e42266951a9a54750919280a2ac835a73c158407c3a2b1904cf0d17b7195a393c71a18ad029cbd9cf79ee +a6a469c44b67ebf02196213e7a63ad0423aab9a6e54acc6fcbdbb915bc043586993454dc3cd9e4be8f27d67c1050879b +8712d380a843b08b7b294f1f06e2f11f4ad6bcc655fdde86a4d8bc739c23916f6fad2b902fe47d6212f03607907e9f0e +920adfb644b534789943cdae1bdd6e42828dda1696a440af2f54e6b97f4f97470a1c6ea9fa6a2705d8f04911d055acd1 +a161c73adf584a0061e963b062f59d90faac65c9b3a936b837a10d817f02fcabfa748824607be45a183dd40f991fe83f +874f4ecd408c76e625ea50bc59c53c2d930ee25baf4b4eca2440bfbffb3b8bc294db579caa7c68629f4d9ec24187c1ba +8bff18087f112be7f4aa654e85c71fef70eee8ae480f61d0383ff6f5ab1a0508f966183bb3fc4d6f29cb7ca234aa50d3 +b03b46a3ca3bc743a173cbc008f92ab1aedd7466b35a6d1ca11e894b9482ea9dc75f8d6db2ddd1add99bfbe7657518b7 +8b4f3691403c3a8ad9e097f02d130769628feddfa8c2b3dfe8cff64e2bed7d6e5d192c1e2ba0ac348b8585e94acd5fa1 +a0d9ca4a212301f97591bf65d5ef2b2664766b427c9dd342e23cb468426e6a56be66b1cb41fea1889ac5d11a8e3c50a5 +8c93ed74188ca23b3df29e5396974b9cc135c91fdefdea6c0df694c8116410e93509559af55533a3776ac11b228d69b1 +82dd331fb3f9e344ebdeeb557769b86a2cc8cc38f6c298d7572a33aea87c261afa9dbd898989139b9fc16bc1e880a099 +a65faedf326bcfd8ef98a51410c78b021d39206704e8291cd1f09e096a66b9b0486be65ff185ca224c45918ac337ddeb +a188b37d363ac072a766fd5d6fa27df07363feff1342217b19e3c37385e42ffde55e4be8355aceaa2f267b6d66b4ac41 +810fa3ba3e96d843e3bafd3f2995727f223d3567c8ba77d684c993ba1773c66551eb5009897c51b3fe9b37196984f5ec +87631537541852da323b4353af45a164f68b304d24c01183bf271782e11687f3fcf528394e1566c2a26cb527b3148e64 +b721cb2b37b3c477a48e3cc0044167d51ff568a5fd2fb606e5aec7a267000f1ddc07d3db919926ae12761a8e017c767c +904dfad4ba2cc1f6e60d1b708438a70b1743b400164cd981f13c064b8328d5973987d4fb9cf894068f29d3deaf624dfb +a70491538893552c20939fae6be2f07bfa84d97e2534a6bbcc0f1729246b831103505e9f60e97a8fa7d2e6c1c2384579 +8726cf1b26b41f443ff7485adcfddc39ace2e62f4d65dd0bb927d933e262b66f1a9b367ded5fbdd6f3b0932553ac1735 +ae8a11cfdf7aa54c08f80cb645e3339187ab3886babe9fae5239ba507bb3dd1c0d161ca474a2df081dcd3d63e8fe445e +92328719e97ce60e56110f30a00ac5d9c7a2baaf5f8d22355d53c1c77941e3a1fec7d1405e6fbf8959665fe2ba7a8cad +8d9d6255b65798d0018a8cccb0b6343efd41dc14ff2058d3eed9451ceaad681e4a0fa6af67b0a04318aa628024e5553d +b70209090055459296006742d946a513f0cba6d83a05249ee8e7a51052b29c0ca9722dc4af5f9816a1b7938a5dac7f79 +aab7b766b9bf91786dfa801fcef6d575dc6f12b77ecc662eb4498f0312e54d0de9ea820e61508fc8aeee5ab5db529349 +a8104b462337748b7f086a135d0c3f87f8e51b7165ca6611264b8fb639d9a2f519926cb311fa2055b5fadf03da70c678 +b0d2460747d5d8b30fc6c6bd0a87cb343ddb05d90a51b465e8f67d499cfc5e3a9e365da05ae233bbee792cdf90ec67d5 +aa55f5bf3815266b4a149f85ed18e451c93de9163575e3ec75dd610381cc0805bb0a4d7c4af5b1f94d10231255436d2c +8d4c6a1944ff94426151909eb5b99cfd92167b967dabe2bf3aa66bb3c26c449c13097de881b2cfc1bf052862c1ef7b03 +8862296162451b9b6b77f03bf32e6df71325e8d7485cf3335d66fd48b74c2a8334c241db8263033724f26269ad95b395 +901aa96deb26cda5d9321190ae6624d357a41729d72ef1abfd71bebf6139af6d690798daba53b7bc5923462115ff748a +96c195ec4992728a1eb38cdde42d89a7bce150db43adbc9e61e279ea839e538deec71326b618dd39c50d589f78fc0614 +b6ff8b8aa0837b99a1a8b46fb37f20ad4aecc6a98381b1308697829a59b8442ffc748637a88cb30c9b1f0f28a926c4f6 +8d807e3dca9e7bef277db1d2cfb372408dd587364e8048b304eff00eacde2c723bfc84be9b98553f83cba5c7b3cba248 +8800c96adb0195c4fc5b24511450dee503c32bf47044f5e2e25bd6651f514d79a2dd9b01cd8c09f3c9d3859338490f57 +89fe366096097e38ec28dd1148887112efa5306cc0c3da09562aafa56f4eb000bf46ff79bf0bdd270cbde6bf0e1c8957 +af409a90c2776e1e7e3760b2042507b8709e943424606e31e791d42f17873a2710797f5baaab4cc4a19998ef648556b0 +8d761863c9b6edbd232d35ab853d944f5c950c2b643f84a1a1327ebb947290800710ff01dcfa26dc8e9828481240e8b1 +90b95e9be1e55c463ed857c4e0617d6dc3674e99b6aa62ed33c8e79d6dfcf7d122f4f4cc2ee3e7c5a49170cb617d2e2e +b3ff381efefabc4db38cc4727432e0301949ae4f16f8d1dea9b4f4de611cf5a36d84290a0bef160dac4e1955e516b3b0 +a8a84564b56a9003adcadb3565dc512239fc79572762cda7b5901a255bc82656bb9c01212ad33d6bef4fbbce18dacc87 +90a081890364b222eef54bf0075417f85e340d2fec8b7375995f598aeb33f26b44143ebf56fca7d8b4ebb36b5747b0eb +ade6ee49e1293224ddf2d8ab7f14bb5be6bc6284f60fd5b3a1e0cf147b73cff57cf19763b8a36c5083badc79c606b103 +b2fa99806dd2fa3de09320b615a2570c416c9bcdb052e592b0aead748bbe407ec9475a3d932ae48b71c2627eb81986a6 +91f3b7b73c8ccc9392542711c45fe6f236057e6efad587d661ad5cb4d6e88265f86b807bb1151736b1009ab74fd7acb4 +8800e2a46af96696dfbdcbf2ca2918b3dcf28ad970170d2d1783b52b8d945a9167d052beeb55f56c126da7ffa7059baa +9862267a1311c385956b977c9aa08548c28d758d7ba82d43dbc3d0a0fd1b7a221d39e8399997fea9014ac509ff510ac4 +b7d24f78886fd3e2d283e18d9ad5a25c1a904e7d9b9104bf47da469d74f34162e27e531380dbbe0a9d051e6ffd51d6e7 +b0f445f9d143e28b9df36b0f2c052da87ee2ca374d9d0fbe2eff66ca6fe5fe0d2c1951b428d58f7314b7e74e45d445ea +b63fc4083eabb8437dafeb6a904120691dcb53ce2938b820bb553da0e1eecd476f72495aacb72600cf9cad18698fd3db +b9ffd8108eaebd582d665f8690fe8bb207fd85185e6dd9f0b355a09bac1bbff26e0fdb172bc0498df025414e88fe2eda +967ed453e1f1a4c5b7b6834cc9f75c13f6889edc0cc91dc445727e9f408487bbf05c337103f61397a10011dfbe25d61d +98ceb673aff36e1987d5521a3984a07079c3c6155974bb8b413e8ae1ce84095fe4f7862fba7aefa14753eb26f2a5805f +85f01d28603a8fdf6ce6a50cb5c44f8a36b95b91302e3f4cd95c108ce8f4d212e73aec1b8d936520d9226802a2bd9136 +88118e9703200ca07910345fbb789e7a8f92bd80bbc79f0a9e040e8767d33df39f6eded403a9b636eabf9101e588482a +90833a51eef1b10ed74e8f9bbd6197e29c5292e469c854eed10b0da663e2bceb92539710b1858bbb21887bd538d28d89 +b513b905ec19191167c6193067b5cfdf5a3d3828375360df1c7e2ced5815437dfd37f0c4c8f009d7fb29ff3c8793f560 +b1b6d405d2d18f9554b8a358cc7e2d78a3b34269737d561992c8de83392ac9a2857be4bf15de5a6c74e0c9d0f31f393c +b828bd3e452b797323b798186607849f85d1fb20c616833c0619360dfd6b3e3aa000fd09dafe4b62d74abc41072ff1a9 +8efde67d0cca56bb2c464731879c9ac46a52e75bac702a63200a5e192b4f81c641f855ca6747752b84fe469cb7113b6c +b2762ba1c89ac3c9a983c242e4d1c2610ff0528585ed5c0dfc8a2c0253551142af9b59f43158e8915a1da7cc26b9df67 +8a3f1157fb820d1497ef6b25cd70b7e16bb8b961b0063ad340d82a79ee76eb2359ca9e15e6d42987ed7f154f5eeaa2da +a75e29f29d38f09c879f971c11beb5368affa084313474a5ecafa2896180b9e47ea1995c2733ec46f421e395a1d9cffe +8e8c3dd3e7196ef0b4996b531ec79e4a1f211db5d5635e48ceb80ff7568b2ff587e845f97ee703bb23a60945ad64314a +8e7f32f4a3e3c584af5e3d406924a0aa34024c42eca74ef6cc2a358fd3c9efaf25f1c03aa1e66bb94b023a2ee2a1cace +ab7dce05d59c10a84feb524fcb62478906b3fa045135b23afbede3bb32e0c678d8ebe59feabccb5c8f3550ea76cae44b +b38bb4b44d827f6fd3bd34e31f9186c59e312dbfadd4a7a88e588da10146a78b1f8716c91ad8b806beb8da65cab80c4c +9490ce9442bbbd05438c7f5c4dea789f74a7e92b1886a730544b55ba377840740a3ae4f2f146ee73f47c9278b0e233bc +83c003fab22a7178eed1a668e0f65d4fe38ef3900044e9ec63070c23f2827d36a1e73e5c2b883ec6a2afe2450171b3b3 +9982f02405978ddc4fca9063ebbdb152f524c84e79398955e66fe51bc7c1660ec1afc3a86ec49f58d7b7dde03505731c +ab337bd83ccdd2322088ffa8d005f450ced6b35790f37ab4534313315ee84312adc25e99cce052863a8bedee991729ed +8312ce4bec94366d88f16127a17419ef64285cd5bf9e5eda010319b48085966ed1252ed2f5a9fd3e0259b91bb65f1827 +a60d5a6327c4041b0c00a1aa2f0af056520f83c9ce9d9ccd03a0bd4d9e6a1511f26a422ea86bd858a1f77438adf07e6c +b84a0a0b030bdad83cf5202aa9afe58c9820e52483ab41f835f8c582c129ee3f34aa096d11c1cd922eda02ea1196a882 +8077d105317f4a8a8f1aadeb05e0722bb55f11abcb490c36c0904401107eb3372875b0ac233144829e734f0c538d8c1d +9202503bd29a6ec198823a1e4e098f9cfe359ed51eb5174d1ca41368821bfeebcbd49debfd02952c41359d1c7c06d2b1 +abc28c155e09365cb77ffead8dc8f602335ef93b2f44e4ef767ce8fc8ef9dd707400f3a722e92776c2e0b40192c06354 +b0f6d1442533ca45c9399e0a63a11f85ff288d242cea6cb3b68c02e77bd7d158047cae2d25b3bcd9606f8f66d9b32855 +b01c3d56a0db84dc94575f4b6ee2de4beca3230e86bed63e2066beb22768b0a8efb08ebaf8ac3dedb5fe46708b084807 +8c8634b0432159f66feaabb165842d1c8ac378f79565b1b90c381aa8450eb4231c3dad11ec9317b9fc2b155c3a771e32 +8e67f623d69ecd430c9ee0888520b6038f13a2b6140525b056dc0951f0cfed2822e62cf11d952a483107c5c5acac4826 +9590bb1cba816dd6acd5ac5fba5142c0a19d53573e422c74005e0bcf34993a8138c83124cad35a3df65879dba6134edd +801cd96cde0749021a253027118d3ea135f3fcdbe895db08a6c145641f95ebd368dd6a1568d995e1d0084146aebe224a +848b5d196427f6fc1f762ee3d36e832b64a76ec1033cfedc8b985dea93932a7892b8ef1035c653fb9dcd9ab2d9a44ac8 +a1017eb83d5c4e2477e7bd2241b2b98c4951a3b391081cae7d75965cadc1acaec755cf350f1f3d29741b0828e36fedea +8d6d2785e30f3c29aad17bd677914a752f831e96d46caf54446d967cb2432be2c849e26f0d193a60bee161ea5c6fe90a +935c0ba4290d4595428e034b5c8001cbd400040d89ab00861108e8f8f4af4258e41f34a7e6b93b04bc253d3b9ffc13bf +aac02257146246998477921cef2e9892228590d323b839f3e64ea893b991b463bc2f47e1e5092ddb47e70b2f5bce7622 +b921fde9412970a5d4c9a908ae8ce65861d06c7679af577cf0ad0d5344c421166986bee471fd6a6cecb7d591f06ec985 +8ef4c37487b139d6756003060600bb6ebac7ea810b9c4364fc978e842f13ac196d1264fbe5af60d76ff6d9203d8e7d3f +94b65e14022b5cf6a9b95f94be5ace2711957c96f4211c3f7bb36206bd39cfbd0ea82186cab5ad0577a23214a5c86e9e +a31c166d2a2ca1d5a75a5920fef7532681f62191a50d8555fdaa63ba4581c3391cc94a536fc09aac89f64eafceec3f90 +919a8cc128de01e9e10f5d83b08b52293fdd41bde2b5ae070f3d95842d4a16e5331cf2f3d61c765570c8022403610fa4 +b23d6f8331eef100152d60483cfa14232a85ee712c8538c9b6417a5a7c5b353c2ac401390c6c215cb101f5cee6b5f43e +ab357160c08a18319510a571eafff154298ce1020de8e1dc6138a09fcb0fcbcdd8359f7e9386bda00b7b9cdea745ffdc +ab55079aea34afa5c0bd1124b9cdfe01f325b402fdfa017301bf87812eaa811ea5798c3aaf818074d420d1c782b10ada +ade616010dc5009e7fc4f8d8b00dc716686a5fa0a7816ad9e503e15839d3b909b69d9dd929b7575376434ffec0d2bea8 +863997b97ed46898a8a014599508fa3079f414b1f4a0c4fdc6d74ae8b444afa350f327f8bfc2a85d27f9e2d049c50135 +8d602ff596334efd4925549ed95f2aa762b0629189f0df6dbb162581657cf3ea6863cd2287b4d9c8ad52813d87fcd235 +b70f68c596dcdeed92ad5c6c348578b26862a51eb5364237b1221e840c47a8702f0fbc56eb520a22c0eed99795d3903e +9628088f8e0853cefadee305a8bf47fa990c50fa96a82511bbe6e5dc81ef4b794e7918a109070f92fc8384d77ace226f +97e26a46e068b605ce96007197ecd943c9a23881862f4797a12a3e96ba2b8d07806ad9e2a0646796b1889c6b7d75188c +b1edf467c068cc163e2d6413cc22b16751e78b3312fe47b7ea82b08a1206d64415b2c8f2a677fa89171e82cc49797150 +a44d15ef18745b251429703e3cab188420e2d974de07251501799b016617f9630643fcd06f895634d8ecdd579e1bf000 +abd126df3917ba48c618ee4dbdf87df506193462f792874439043fa1b844466f6f4e0ff2e42516e63b5b23c0892b2695 +a2a67f57c4aa3c2aa1eeddbfd5009a89c26c2ce8fa3c96a64626aba19514beb125f27df8559506f737de3eae0f1fc18f +a633e0132197e6038197304b296ab171f1d8e0d0f34dcf66fe9146ac385b0239232a8470b9205a4802ab432389f4836d +a914b3a28509a906c3821463b936455d58ff45dcbe158922f9efb2037f2eb0ce8e92532d29b5d5a3fcd0d23fa773f272 +a0e1412ce4505daf1a2e59ce4f0fc0e0023e335b50d2b204422f57cd65744cc7a8ed35d5ef131a42c70b27111d3115b7 +a2339e2f2b6072e88816224fdd612c04d64e7967a492b9f8829db15367f565745325d361fd0607b0def1be384d010d9e +a7309fc41203cb99382e8193a1dcf03ac190a7ce04835304eb7e341d78634e83ea47cb15b885601956736d04cdfcaa01 +81f3ccd6c7f5b39e4e873365f8c37b214e8ab122d04a606fbb7339dc3298c427e922ec7418002561d4106505b5c399ee +92c121cf914ca549130e352eb297872a63200e99b148d88fbc9506ad882bec9d0203d65f280fb5b0ba92e336b7f932e8 +a4b330cf3f064f5b131578626ad7043ce2a433b6f175feb0b52d36134a454ca219373fd30d5e5796410e005b69082e47 +86fe5774112403ad83f9c55d58317eeb17ad8e1176d9f2f69c2afb7ed83bc718ed4e0245ceab4b377f5f062dcd4c00e7 +809d152a7e2654c7fd175b57f7928365a521be92e1ed06c05188a95864ddb25f7cab4c71db7d61bbf4cae46f3a1d96ce +b82d663e55c2a5ada7e169e9b1a87bc1c0177baf1ec1c96559b4cb1c5214ce1ddf2ab8d345014cab6402f3774235cf5a +86580af86df1bd2c385adb8f9a079e925981b7184db66fc5fe5b14cddb82e7d836b06eaeef14924ac529487b23dae111 +b5f5f4c5c94944ecc804df6ab8687d64e27d988cbfeae1ba7394e0f6adbf778c5881ead7cd8082dd7d68542b9bb4ecd5 +a6016916146c2685c46e8fdd24186394e2d5496e77e08c0c6a709d4cd7dfa97f1efcef94922b89196819076a91ad37b5 +b778e7367ded3b6eab53d5fc257f7a87e8faf74a593900f2f517220add2125be3f6142022660d8181df8d164ad9441ce +8581b2d36abe6f553add4d24be761bec1b8efaa2929519114346615380b3c55b59e6ad86990e312f7e234d0203bdf59b +9917e74fd45c3f71a829ff5498a7f6b5599b48c098dda2339bf04352bfc7f368ccf1a407f5835901240e76452ae807d7 +afd196ce6f9335069138fd2e3d133134da253978b4ce373152c0f26affe77a336505787594022e610f8feb722f7cc1fb +a477491a1562e329764645e8f24d8e228e5ef28c9f74c6b5b3abc4b6a562c15ffb0f680d372aed04d9e1bf944dece7be +9767440d58c57d3077319d3a330e5322b9ba16981ec74a5a14d53462eab59ae7fd2b14025bfc63b268862094acb444e6 +80986d921be3513ef69264423f351a61cb48390c1be8673aee0f089076086aaebea7ebe268fd0aa7182695606116f679 +a9554c5c921c07b450ee04e34ec58e054ac1541b26ce2ce5a393367a97348ba0089f53db6660ad76b60278b66fd12e3e +95097e7d2999b3e84bf052c775581cf361325325f4a50192521d8f4693c830bed667d88f482dc1e3f833aa2bd22d2cbf +9014c91d0f85aefd28436b5228c12f6353c055a9326c7efbf5e071e089e2ee7c070fcbc84c5fafc336cbb8fa6fec1ca1 +90f57ba36ee1066b55d37384942d8b57ae00f3cf9a3c1d6a3dfee1d1af42d4b5fa9baeb0cd7e46687d1d6d090ddb931d +8e4b1db12fd760a17214c9e47f1fce6e43c0dbb4589a827a13ac61aaae93759345697bb438a00edab92e0b7b62414683 +8022a959a513cdc0e9c705e0fc04eafd05ff37c867ae0f31f6d01cddd5df86138a426cab2ff0ac8ff03a62e20f7e8f51 +914e9a38829834c7360443b8ed86137e6f936389488eccf05b4b4db7c9425611705076ecb3f27105d24b85c852be7511 +957fb10783e2bd0db1ba66b18e794df710bc3b2b05776be146fa5863c15b1ebdd39747b1a95d9564e1772cdfc4f37b8a +b6307028444daed8ed785ac9d0de76bc3fe23ff2cc7e48102553613bbfb5afe0ebe45e4212a27021c8eb870721e62a1f +8f76143597777d940b15a01b39c5e1b045464d146d9a30a6abe8b5d3907250e6c7f858ff2308f8591e8b0a7b3f3c568a +96163138ac0ce5fd00ae9a289648fd9300a0ca0f63a88481d703ecd281c06a52a3b5178e849e331f9c85ca4ba398f4cc +a63ef47c3e18245b0482596a09f488a716df3cbd0f9e5cfabed0d742843e65db8961c556f45f49762f3a6ac8b627b3ef +8cb595466552e7c4d42909f232d4063e0a663a8ef6f6c9b7ce3a0542b2459cde04e0e54c7623d404acb5b82775ac04f6 +b47fe69960eb45f399368807cff16d941a5a4ebad1f5ec46e3dc8a2e4d598a7e6114d8f0ca791e9720fd786070524e2b +89eb5ff83eea9df490e5beca1a1fbbbbcf7184a37e2c8c91ede7a1e654c81e8cd41eceece4042ea7918a4f4646b67fd6 +a84f5d155ed08b9054eecb15f689ba81e44589e6e7207a99790c598962837ca99ec12344105b16641ca91165672f7153 +a6cc8f25c2d5b2d2f220ec359e6a37a52b95fa6af6e173c65e7cd55299eff4aa9e6d9e6f2769e6459313f1f2aecb0fab +afcde944411f017a9f7979755294981e941cc41f03df5e10522ef7c7505e5f1babdd67b3bf5258e8623150062eb41d9b +8fab39f39c0f40182fcd996ade2012643fe7731808afbc53f9b26900b4d4d1f0f5312d9d40b3df8baa4739970a49c732 +ae193af9726da0ebe7df1f9ee1c4846a5b2a7621403baf8e66c66b60f523e719c30c6b4f897bb14b27d3ff3da8392eeb +8ac5adb82d852eba255764029f42e6da92dcdd0e224d387d1ef94174038db9709ac558d90d7e7c57ad4ce7f89bbfc38c +a2066b3458fdf678ee487a55dd5bfb74fde03b54620cb0e25412a89ee28ad0d685e309a51e3e4694be2fa6f1593a344c +88d031745dd0ae07d61a15b594be5d4b2e2a29e715d081649ad63605e3404b0c3a5353f0fd9fad9c05c18e93ce674fa1 +8283cfb0ef743a043f2b77ecaeba3005e2ca50435585b5dd24777ee6bce12332f85e21b446b536da38508807f0f07563 +b376de22d5f6b0af0b59f7d9764561f4244cf8ffe22890ecd3dcf2ff1832130c9b821e068c9d8773136f4796721e5963 +ae3afc50c764f406353965363840bf28ee85e7064eb9d5f0bb3c31c64ab10f48c853e942ee2c9b51bae59651eaa08c2f +948b204d103917461a01a6c57a88f2d66b476eae5b00be20ec8c747650e864bc8a83aee0aff59cb7584b7a3387e0ee48 +81ab098a082b07f896c5ffd1e4446cb7fb44804cbbf38d125208b233fc82f8ec9a6a8d8dd1c9a1162dc28ffeec0dde50 +a149c6f1312821ced2969268789a3151bdda213451760b397139a028da609c4134ac083169feb0ee423a0acafd10eceb +b0ac9e27a5dadaf523010f730b28f0ebac01f460d3bbbe277dc9d44218abb5686f4fac89ae462682fef9edbba663520a +8d0e0073cca273daaaa61b6fc54bfe5a009bc3e20ae820f6c93ba77b19eca517d457e948a2de5e77678e4241807157cb +ad61d3a2edf7c7533a04964b97499503fd8374ca64286dba80465e68fe932e96749b476f458c6fc57cb1a7ca85764d11 +90eb5e121ae46bc01a30881eaa556f46bd8457a4e80787cf634aab355082de34ac57d7f497446468225f7721e68e2a47 +8cdac557de7c42d1f3780e33dec1b81889f6352279be81c65566cdd4952d4c15d79e656cbd46035ab090b385e90245ef +82b67e61b88b84f4f4d4f65df37b3e3dcf8ec91ea1b5c008fdccd52da643adbe6468a1cfdb999e87d195afe2883a3b46 +8503b467e8f5d6048a4a9b78496c58493a462852cab54a70594ae3fd064cfd0deb4b8f336a262155d9fedcaa67d2f6fd +8db56c5ac763a57b6ce6832930c57117058e3e5a81532b7d19346346205e2ec614eb1a2ee836ef621de50a7bc9b7f040 +ad344699198f3c6e8c0a3470f92aaffc805b76266734414c298e10b5b3797ca53578de7ccb2f458f5e0448203f55282b +80602032c43c9e2a09154cc88b83238343b7a139f566d64cb482d87436b288a98f1ea244fd3bff8da3c398686a900c14 +a6385bd50ecd548cfb37174cdbb89e10025b5cadaf3cff164c95d7aef5a33e3d6a9bf0c681b9e11db9ef54ebeee2a0c1 +abf2d95f4aa34b0581eb9257a0cc8462b2213941a5deb8ba014283293e8b36613951b61261cc67bbd09526a54cbbff76 +a3d5de52f48df72c289ff713e445991f142390798cd42bd9d9dbefaee4af4f5faf09042d126b975cf6b98711c3072553 +8e627302ff3d686cff8872a1b7c2a57b35f45bf2fc9aa42b049d8b4d6996a662b8e7cbac6597f0cb79b0cc4e29fbf133 +8510702e101b39a1efbf4e504e6123540c34b5689645e70d0bac1ecc1baf47d86c05cef6c4317a4e99b4edaeb53f2d00 +aa173f0ecbcc6088f878f8726d317748c81ebf501bba461f163b55d66099b191ec7c55f7702f351a9c8eb42cfa3280e2 +b560a697eafab695bcef1416648a0a664a71e311ecbe5823ae903bd0ed2057b9d7574b9a86d3fe22aa3e6ddce38ea513 +8df6304a3d9cf40100f3f687575419c998cd77e5cc27d579cf4f8e98642de3609af384a0337d145dd7c5635172d26a71 +8105c7f3e4d30a29151849673853b457c1885c186c132d0a98e63096c3774bc9deb956cf957367e633d0913680bda307 +95373fc22c0917c3c2044ac688c4f29a63ed858a45c0d6d2d0fe97afd6f532dcb648670594290c1c89010ecc69259bef +8c2fae9bcadab341f49b55230310df93cac46be42d4caa0d42e45104148a91e527af1b4209c0d972448162aed28fab64 +b05a77baab70683f76209626eaefdda2d36a0b66c780a20142d23c55bd479ddd4ad95b24579384b6cf62c8eb4c92d021 +8e6bc6a7ea2755b4aaa19c1c1dee93811fcde514f03485fdc3252f0ab7f032c315614f6336e57cea25dcfb8fb6084eeb +b656a27d06aade55eadae2ad2a1059198918ea6cc3fd22c0ed881294d34d5ac7b5e4700cc24350e27d76646263b223aa +a296469f24f6f56da92d713afcd4dd606e7da1f79dc4e434593c53695847eefc81c7c446486c4b3b8c8d00c90c166f14 +87a326f57713ac2c9dffeb3af44b9f3c613a8f952676fc46343299122b47ee0f8d792abaa4b5db6451ced5dd153aabd0 +b689e554ba9293b9c1f6344a3c8fcb6951d9f9eac4a2e2df13de021aade7c186be27500e81388e5b8bcab4c80f220a31 +87ae0aa0aa48eac53d1ca5a7b93917de12db9e40ceabf8fdb40884ae771cfdf095411deef7c9f821af0b7070454a2608 +a71ffa7eae8ace94e6c3581d4cb2ad25d48cbd27edc9ec45baa2c8eb932a4773c3272b2ffaf077b40f76942a1f3af7f2 +94c218c91a9b73da6b7a495b3728f3028df8ad9133312fc0c03e8c5253b7ccb83ed14688fd4602e2fd41f29a0bc698bd +ae1e77b90ca33728af07a4c03fb2ef71cd92e2618e7bf8ed4d785ce90097fc4866c29999eb84a6cf1819d75285a03af2 +b7a5945b277dab9993cf761e838b0ac6eaa903d7111fca79f9fde3d4285af7a89bf6634a71909d095d7619d913972c9c +8c43b37be02f39b22029b20aca31bff661abce4471dca88aa3bddefd9c92304a088b2dfc8c4795acc301ca3160656af2 +b32e5d0fba024554bd5fe8a793ebe8003335ddd7f585876df2048dcf759a01285fecb53daae4950ba57f3a282a4d8495 +85ea7fd5e10c7b659df5289b2978b2c89e244f269e061b9a15fcab7983fc1962b63546e82d5731c97ec74b6804be63ef +96b89f39181141a7e32986ac02d7586088c5a9662cec39843f397f3178714d02f929af70630c12cbaba0268f8ba2d4fa +929ab1a2a009b1eb37a2817c89696a06426529ebe3f306c586ab717bd34c35a53eca2d7ddcdef36117872db660024af9 +a696dccf439e9ca41511e16bf3042d7ec0e2f86c099e4fc8879d778a5ea79e33aa7ce96b23dc4332b7ba26859d8e674d +a8fe69a678f9a194b8670a41e941f0460f6e2dbc60470ab4d6ae2679cc9c6ce2c3a39df2303bee486dbfde6844e6b31a +95f58f5c82de2f2a927ca99bf63c9fc02e9030c7e46d0bf6b67fe83a448d0ae1c99541b59caf0e1ccab8326231af09a5 +a57badb2c56ca2c45953bd569caf22968f76ed46b9bac389163d6fe22a715c83d5e94ae8759b0e6e8c2f27bff7748f3f +868726fd49963b24acb5333364dffea147e98f33aa19c7919dc9aca0fd26661cfaded74ede7418a5fadbe7f5ae67b67b +a8d8550dcc64d9f1dd7bcdab236c4122f2b65ea404bb483256d712c7518f08bb028ff8801f1da6aed6cbfc5c7062e33b +97e25a87dae23155809476232178538d4bc05d4ff0882916eb29ae515f2a62bfce73083466cc0010ca956aca200aeacc +b4ea26be3f4bd04aa82d7c4b0913b97bcdf5e88b76c57eb1a336cbd0a3eb29de751e1bc47c0e8258adec3f17426d0c71 +99ee555a4d9b3cf2eb420b2af8e3bc99046880536116d0ce7193464ac40685ef14e0e3c442f604e32f8338cb0ef92558 +8c64efa1da63cd08f319103c5c7a761221080e74227bbc58b8fb35d08aa42078810d7af3e60446cbaff160c319535648 +8d9fd88040076c28420e3395cbdfea402e4077a3808a97b7939d49ecbcf1418fe50a0460e1c1b22ac3f6e7771d65169a +ae3c19882d7a9875d439265a0c7003c8d410367627d21575a864b9cb4918de7dbdb58a364af40c5e045f3df40f95d337 +b4f7bfacab7b2cafe393f1322d6dcc6f21ffe69cd31edc8db18c06f1a2b512c27bd0618091fd207ba8df1808e9d45914 +94f134acd0007c623fb7934bcb65ef853313eb283a889a3ffa79a37a5c8f3665f3d5b4876bc66223610c21dc9b919d37 +aa15f74051171daacdc1f1093d3f8e2d13da2833624b80a934afec86fc02208b8f55d24b7d66076444e7633f46375c6a +a32d6bb47ef9c836d9d2371807bafbbbbb1ae719530c19d6013f1d1f813c49a60e4fa51d83693586cba3a840b23c0404 +b61b3599145ea8680011aa2366dc511a358b7d67672d5b0c5be6db03b0efb8ca5a8294cf220ea7409621f1664e00e631 +859cafc3ee90b7ececa1ed8ef2b2fc17567126ff10ca712d5ffdd16aa411a5a7d8d32c9cab1fbf63e87dce1c6e2f5f53 +a2fef1b0b2874387010e9ae425f3a9676d01a095d017493648bcdf3b31304b087ccddb5cf76abc4e1548b88919663b6b +939e18c73befc1ba2932a65ede34c70e4b91e74cc2129d57ace43ed2b3af2a9cc22a40fbf50d79a63681b6d98852866d +b3b4259d37b1b14aee5b676c9a0dd2d7f679ab95c120cb5f09f9fbf10b0a920cb613655ddb7b9e2ba5af4a221f31303c +997255fe51aaca6e5a9cb3359bcbf25b2bb9e30649bbd53a8a7c556df07e441c4e27328b38934f09c09d9500b5fabf66 +abb91be2a2d860fd662ed4f1c6edeefd4da8dc10e79251cf87f06029906e7f0be9b486462718f0525d5e049472692cb7 +b2398e593bf340a15f7801e1d1fbda69d93f2a32a889ec7c6ae5e8a37567ac3e5227213c1392ee86cfb3b56ec2787839 +8ddf10ccdd72922bed36829a36073a460c2118fc7a56ff9c1ac72581c799b15c762cb56cb78e3d118bb9f6a7e56cb25e +93e6bc0a4708d16387cacd44cf59363b994dc67d7ada7b6d6dbd831c606d975247541b42b2a309f814c1bfe205681fc6 +b93fc35c05998cffda2978e12e75812122831523041f10d52f810d34ff71944979054b04de0117e81ddf5b0b4b3e13c0 +92221631c44d60d68c6bc7b287509f37ee44cbe5fdb6935cee36b58b17c7325098f98f7910d2c3ca5dc885ad1d6dabc7 +a230124424a57fad3b1671f404a94d7c05f4c67b7a8fbacfccea28887b78d7c1ed40b92a58348e4d61328891cd2f6cee +a6a230edb8518a0f49d7231bc3e0bceb5c2ac427f045819f8584ba6f3ae3d63ed107a9a62aad543d7e1fcf1f20605706 +845be1fe94223c7f1f97d74c49d682472585d8f772762baad8a9d341d9c3015534cc83d102113c51a9dea2ab10d8d27b +b44262515e34f2db597c8128c7614d33858740310a49cdbdf9c8677c5343884b42c1292759f55b8b4abc4c86e4728033 +805592e4a3cd07c1844bc23783408310accfdb769cca882ad4d07d608e590a288b7370c2cb327f5336e72b7083a0e30f +95153e8b1140df34ee864f4ca601cb873cdd3efa634af0c4093fbaede36f51b55571ab271e6a133020cd34db8411241f +82878c1285cfa5ea1d32175c9401f3cc99f6bb224d622d3fd98cc7b0a27372f13f7ab463ce3a33ec96f9be38dbe2dfe3 +b7588748f55783077c27fc47d33e20c5c0f5a53fc0ac10194c003aa09b9f055d08ec971effa4b7f760553997a56967b3 +b36b4de6d1883b6951f59cfae381581f9c6352fcfcf1524fccdab1571a20f80441d9152dc6b48bcbbf00371337ca0bd5 +89c5523f2574e1c340a955cbed9c2f7b5fbceb260cb1133160dabb7d41c2f613ec3f6e74bbfab3c4a0a6f0626dbe068f +a52f58cc39f968a9813b1a8ddc4e83f4219e4dd82c7aa1dd083bea7edf967151d635aa9597457f879771759b876774e4 +8300a67c2e2e123f89704abfde095463045dbd97e20d4c1157bab35e9e1d3d18f1f4aaba9cbe6aa2d544e92578eaa1b6 +ac6a7f2918768eb6a43df9d3a8a04f8f72ee52f2e91c064c1c7d75cad1a3e83e5aba9fe55bb94f818099ac91ccf2e961 +8d64a2b0991cf164e29835c8ddef6069993a71ec2a7de8157bbfa2e00f6367be646ed74cbaf524f0e9fe13fb09fa15fd +8b2ffe5a545f9f680b49d0a9797a4a11700a2e2e348c34a7a985fc278f0f12def6e06710f40f9d48e4b7fbb71e072229 +8ab8f71cd337fa19178924e961958653abf7a598e3f022138b55c228440a2bac4176cea3aea393549c03cd38a13eb3fc +8419d28318c19ea4a179b7abb43669fe96347426ef3ac06b158d79c0acf777a09e8e770c2fb10e14b3a0421705990b23 +8bacdac310e1e49660359d0a7a17fe3d334eb820e61ae25e84cb52f863a2f74cbe89c2e9fc3283745d93a99b79132354 +b57ace3fa2b9f6b2db60c0d861ace7d7e657c5d35d992588aeed588c6ce3a80b6f0d49f8a26607f0b17167ab21b675e4 +83e265cde477f2ecc164f49ddc7fb255bb05ff6adc347408353b7336dc3a14fdedc86d5a7fb23f36b8423248a7a67ed1 +a60ada971f9f2d79d436de5d3d045f5ab05308cae3098acaf5521115134b2a40d664828bb89895840db7f7fb499edbc5 +a63eea12efd89b62d3952bf0542a73890b104dd1d7ff360d4755ebfa148fd62de668edac9eeb20507967ea37fb220202 +a0275767a270289adc991cc4571eff205b58ad6d3e93778ddbf95b75146d82517e8921bd0d0564e5b75fa0ccdab8e624 +b9b03fd3bf07201ba3a039176a965d736b4ef7912dd9e9bf69fe1b57c330a6aa170e5521fe8be62505f3af81b41d7806 +a95f640e26fb1106ced1729d6053e41a16e4896acac54992279ff873e5a969aad1dcfa10311e28b8f409ac1dab7f03bb +b144778921742418053cb3c70516c63162c187f00db2062193bb2c14031075dbe055d020cde761b26e8c58d0ea6df2c1 +8432fbb799e0435ef428d4fefc309a05dd589bce74d7a87faf659823e8c9ed51d3e42603d878e80f439a38be4321c2fa +b08ddef14e42d4fd5d8bf39feb7485848f0060d43b51ed5bdda39c05fe154fb111d29719ee61a23c392141358c0cfcff +8ae3c5329a5e025b86b5370e06f5e61177df4bda075856fade20a17bfef79c92f54ed495f310130021ba94fb7c33632b +92b6d3c9444100b4d7391febfc1dddaa224651677c3695c47a289a40d7a96d200b83b64e6d9df51f534564f272a2c6c6 +b432bc2a3f93d28b5e506d68527f1efeb2e2570f6be0794576e2a6ef9138926fdad8dd2eabfa979b79ab7266370e86bc +8bc315eacedbcfc462ece66a29662ca3dcd451f83de5c7626ef8712c196208fb3d8a0faf80b2e80384f0dd9772f61a23 +a72375b797283f0f4266dec188678e2b2c060dfed5880fc6bb0c996b06e91a5343ea2b695adaab0a6fd183b040b46b56 +a43445036fbaa414621918d6a897d3692fdae7b2961d87e2a03741360e45ebb19fcb1703d23f1e15bb1e2babcafc56ac +b9636b2ffe305e63a1a84bd44fb402442b1799bd5272638287aa87ca548649b23ce8ce7f67be077caed6aa2dbc454b78 +99a30bf0921d854c282b83d438a79f615424f28c2f99d26a05201c93d10378ab2cd94a792b571ddae5d4e0c0013f4006 +8648e3c2f93d70b392443be116b48a863e4b75991bab5db656a4ef3c1e7f645e8d536771dfe4e8d1ceda3be8d32978b0 +ab50dc9e6924c1d2e9d2e335b2d679fc7d1a7632e84964d3bac0c9fe57e85aa5906ec2e7b0399d98ddd022e9b19b5904 +ab729328d98d295f8f3272afaf5d8345ff54d58ff9884da14f17ecbdb7371857fdf2f3ef58080054e9874cc919b46224 +83fa5da7592bd451cad3ad7702b4006332b3aae23beab4c4cb887fa6348317d234bf62a359e665b28818e5410c278a09 +8bdbff566ae9d368f114858ef1f009439b3e9f4649f73efa946e678d6c781d52c69af195df0a68170f5f191b2eac286b +91245e59b4425fd4edb2a61d0d47c1ccc83d3ced8180de34887b9655b5dcda033d48cde0bdc3b7de846d246c053a02e8 +a2cb00721e68f1cad8933947456f07144dc69653f96ceed845bd577d599521ba99cdc02421118971d56d7603ed118cbf +af8cd66d303e808b22ec57860dd909ca64c27ec2c60e26ffecfdc1179d8762ffd2739d87b43959496e9fee4108df71df +9954136812dffcd5d3f167a500e7ab339c15cfc9b3398d83f64b0daa3dd5b9a851204f424a3493b4e326d3de81e50a62 +93252254d12511955f1aa464883ad0da793f84d900fea83e1df8bca0f2f4cf5b5f9acbaec06a24160d33f908ab5fea38 +997cb55c26996586ba436a95566bd535e9c22452ca5d2a0ded2bd175376557fa895f9f4def4519241ff386a063f2e526 +a12c78ad451e0ac911260ade2927a768b50cb4125343025d43474e7f465cdc446e9f52a84609c5e7e87ae6c9b3f56cda +a789d4ca55cbba327086563831b34487d63d0980ba8cf55197c016702ed6da9b102b1f0709ce3da3c53ff925793a3d73 +a5d76acbb76741ce85be0e655b99baa04f7f587347947c0a30d27f8a49ae78cce06e1cde770a8b618d3db402be1c0c4b +873c0366668c8faddb0eb7c86f485718d65f8c4734020f1a18efd5fa123d3ea8a990977fe13592cd01d17e60809cb5ff +b659b71fe70f37573ff7c5970cc095a1dc0da3973979778f80a71a347ef25ad5746b2b9608bad4ab9a4a53a4d7df42d7 +a34cbe05888e5e5f024a2db14cb6dcdc401a9cbd13d73d3c37b348f68688f87c24ca790030b8f84fef9e74b4eab5e412 +94ce8010f85875c045b0f014db93ef5ab9f1f6842e9a5743dce9e4cb872c94affd9e77c1f1d1ab8b8660b52345d9acb9 +adefa9b27a62edc0c5b019ddd3ebf45e4de846165256cf6329331def2e088c5232456d3de470fdce3fa758bfdd387512 +a6b83821ba7c1f83cc9e4529cf4903adb93b26108e3d1f20a753070db072ad5a3689643144bdd9c5ea06bb9a7a515cd0 +a3a9ddedc2a1b183eb1d52de26718151744db6050f86f3580790c51d09226bf05f15111691926151ecdbef683baa992c +a64bac89e7686932cdc5670d07f0b50830e69bfb8c93791c87c7ffa4913f8da881a9d8a8ce8c1a9ce5b6079358c54136 +a77b5a63452cb1320b61ab6c7c2ef9cfbcade5fd4727583751fb2bf3ea330b5ca67757ec1f517bf4d503ec924fe32fbd +8746fd8d8eb99639d8cd0ca34c0d9c3230ed5a312aab1d3d925953a17973ee5aeb66e68667e93caf9cb817c868ea8f3d +88a2462a26558fc1fbd6e31aa8abdc706190a17c27fdc4217ffd2297d1b1f3321016e5c4b2384c5454d5717dc732ed03 +b78893a97e93d730c8201af2e0d3b31cb923d38dc594ffa98a714e627c473d42ea82e0c4d2eeb06862ee22a9b2c54588 +920cc8b5f1297cf215a43f6fc843e379146b4229411c44c0231f6749793d40f07b9af7699fd5d21fd69400b97febe027 +a0f0eafce1e098a6b58c7ad8945e297cd93aaf10bc55e32e2e32503f02e59fc1d5776936577d77c0b1162cb93b88518b +98480ba0064e97a2e7a6c4769b4d8c2a322cfc9a3b2ca2e67e9317e2ce04c6e1108169a20bd97692e1cb1f1423b14908 +83dbbb2fda7e287288011764a00b8357753a6a44794cc8245a2275237f11affdc38977214e463ad67aec032f3dfa37e9 +86442fff37598ce2b12015ff19b01bb8a780b40ad353d143a0f30a06f6d23afd5c2b0a1253716c855dbf445cc5dd6865 +b8a4c60c5171189414887847b9ed9501bff4e4c107240f063e2d254820d2906b69ef70406c585918c4d24f1dd052142b +919f33a98e84015b2034b57b5ffe9340220926b2c6e45f86fd79ec879dbe06a148ae68b77b73bf7d01bd638a81165617 +95c13e78d89474a47fbc0664f6f806744b75dede95a479bbf844db4a7f4c3ae410ec721cb6ffcd9fa9c323da5740d5ae +ab7151acc41fffd8ec6e90387700bcd7e1cde291ea669567295bea1b9dd3f1df2e0f31f3588cd1a1c08af8120aca4921 +80e74c5c47414bd6eeef24b6793fb1fa2d8fb397467045fcff887c52476741d5bc4ff8b6d3387cb53ad285485630537f +a296ad23995268276aa351a7764d36df3a5a3cffd7dbeddbcea6b1f77adc112629fdeffa0918b3242b3ccd5e7587e946 +813d2506a28a2b01cb60f49d6bd5e63c9b056aa56946faf2f33bd4f28a8d947569cfead3ae53166fc65285740b210f86 +924b265385e1646287d8c09f6c855b094daaee74b9e64a0dddcf9ad88c6979f8280ba30c8597b911ef58ddb6c67e9fe3 +8d531513c70c2d3566039f7ca47cd2352fd2d55b25675a65250bdb8b06c3843db7b2d29c626eed6391c238fc651cf350 +82b338181b62fdc81ceb558a6843df767b6a6e3ceedc5485664b4ea2f555904b1a45fbb35f6cf5d96f27da10df82a325 +92e62faaedea83a37f314e1d3cb4faaa200178371d917938e59ac35090be1db4b4f4e0edb78b9c991de202efe4f313d8 +99d645e1b642c2dc065bac9aaa0621bc648c9a8351efb6891559c3a41ba737bd155fb32d7731950514e3ecf4d75980e4 +b34a13968b9e414172fb5d5ece9a39cf2eb656128c3f2f6cc7a9f0c69c6bae34f555ecc8f8837dc34b5e470e29055c78 +a2a0bb7f3a0b23a2cbc6585d59f87cd7e56b2bbcb0ae48f828685edd9f7af0f5edb4c8e9718a0aaf6ef04553ba71f3b7 +8e1a94bec053ed378e524b6685152d2b52d428266f2b6eadd4bcb7c4e162ed21ab3e1364879673442ee2162635b7a4d8 +9944adaff14a85eab81c73f38f386701713b52513c4d4b838d58d4ffa1d17260a6d056b02334850ea9a31677c4b078bd +a450067c7eceb0854b3eca3db6cf38669d72cb7143c3a68787833cbca44f02c0be9bfbe082896f8a57debb13deb2afb1 +8be4ad3ac9ef02f7df09254d569939757101ee2eda8586fefcd8c847adc1efe5bdcb963a0cafa17651befaafb376a531 +90f6de91ea50255f148ac435e08cf2ac00c772a466e38155bd7e8acf9197af55662c7b5227f88589b71abe9dcf7ba343 +86e5a24f0748b106dee2d4d54e14a3b0af45a96cbee69cac811a4196403ebbee17fd24946d7e7e1b962ac7f66dbaf610 +afdd96fbcda7aa73bf9eeb2292e036c25753d249caee3b9c013009cc22e10d3ec29e2aa6ddbb21c4e949b0c0bccaa7f4 +b5a4e7436d5473647c002120a2cb436b9b28e27ad4ebdd7c5f122b91597c507d256d0cbd889d65b3a908531936e53053 +b632414c3da704d80ac2f3e5e0e9f18a3637cdc2ebeb613c29300745582427138819c4e7b0bec3099c1b8739dac1807b +a28df1464d3372ce9f37ef1db33cc010f752156afae6f76949d98cd799c0cf225c20228ae86a4da592d65f0cffe3951b +898b93d0a31f7d3f11f253cb7a102db54b669fd150da302d8354d8e02b1739a47cb9bd88015f3baf12b00b879442464e +96fb88d89a12049091070cb0048a381902965e67a8493e3991eaabe5d3b7ff7eecd5c94493a93b174df3d9b2c9511755 +b899cb2176f59a5cfba3e3d346813da7a82b03417cad6342f19cc8f12f28985b03bf031e856a4743fd7ebe16324805b0 +a60e2d31bc48e0c0579db15516718a03b73f5138f15037491f4dae336c904e312eda82d50862f4debd1622bb0e56d866 +979fc8b987b5cef7d4f4b58b53a2c278bd25a5c0ea6f41c715142ea5ff224c707de38451b0ad3aa5e749aa219256650a +b2a75bff18e1a6b9cf2a4079572e41205741979f57e7631654a3c0fcec57c876c6df44733c9da3d863db8dff392b44a3 +b7a0f0e811222c91e3df98ff7f286b750bc3b20d2083966d713a84a2281744199e664879401e77470d44e5a90f3e5181 +82b74ba21c9d147fbc338730e8f1f8a6e7fc847c3110944eb17a48bea5e06eecded84595d485506d15a3e675fd0e5e62 +a7f44eef817d5556f0d1abcf420301217d23c69dd2988f44d91ea1f1a16c322263cbacd0f190b9ba22b0f141b9267b4f +aadb68164ede84fc1cb3334b3194d84ba868d5a88e4c9a27519eef4923bc4abf81aab8114449496c073c2a6a0eb24114 +b5378605fabe9a8c12a5dc55ef2b1de7f51aedb61960735c08767a565793cea1922a603a6983dc25f7cea738d0f7c40d +a97a4a5cd8d51302e5e670aee78fe6b5723f6cc892902bbb4f131e82ca1dfd5de820731e7e3367fb0c4c1922a02196e3 +8bdfeb15c29244d4a28896f2b2cb211243cd6a1984a3f5e3b0ebe5341c419beeab3304b390a009ffb47588018034b0ea +a9af3022727f2aa2fca3b096968e97edad3f08edcbd0dbca107b892ae8f746a9c0485e0d6eb5f267999b23a845923ed0 +8e7594034feef412f055590fbb15b6322dc4c6ab7a4baef4685bd13d71a83f7d682b5781bdfa0d1c659489ce9c2b8000 +84977ca6c865ebee021c58106c1a4ad0c745949ecc5332948002fd09bd9b890524878d0c29da96fd11207621136421fe +8687551a79158e56b2375a271136756313122132a6670fa51f99a1b5c229ed8eea1655a734abae13228b3ebfd2a825dd +a0227d6708979d99edfc10f7d9d3719fd3fc68b0d815a7185b60307e4c9146ad2f9be2b8b4f242e320d4288ceeb9504c +89f75583a16735f9dd8b7782a130437805b34280ccea8dac6ecaee4b83fe96947e7b53598b06fecfffdf57ffc12cc445 +a0056c3353227f6dd9cfc8e3399aa5a8f1d71edf25d3d64c982910f50786b1e395c508d3e3727ac360e3e040c64b5298 +b070e61a6d813626144b312ded1788a6d0c7cec650a762b2f8df6e4743941dd82a2511cd956a3f141fc81e15f4e092da +b4e6db232e028a1f989bb5fc13416711f42d389f63564d60851f009dcffac01acfd54efa307aa6d4c0f932892d4e62b0 +89b5991a67db90024ddd844e5e1a03ef9b943ad54194ae0a97df775dde1addf31561874f4e40fbc37a896630f3bbda58 +ad0e8442cb8c77d891df49cdb9efcf2b0d15ac93ec9be1ad5c3b3cca1f4647b675e79c075335c1f681d56f14dc250d76 +b5d55a6ae65bb34dd8306806cb49b5ccb1c83a282ee47085cf26c4e648e19a52d9c422f65c1cd7e03ca63e926c5e92ea +b749501347e5ec07e13a79f0cb112f1b6534393458b3678a77f02ca89dca973fa7b30e55f0b25d8b92b97f6cb0120056 +94144b4a3ffc5eec6ba35ce9c245c148b39372d19a928e236a60e27d7bc227d18a8cac9983851071935d8ffb64b3a34f +92bb4f9f85bc8c028a3391306603151c6896673135f8a7aefedd27acb322c04ef5dac982fc47b455d6740023e0dd3ea3 +b9633a4a101461a782fc2aa092e9dbe4e2ad00987578f18cd7cf0021a909951d60fe79654eb7897806795f93c8ff4d1c +809f0196753024821b48a016eca5dbb449a7c55750f25981bb7a4b4c0e0846c09b8f6128137905055fc43a3f0deb4a74 +a27dc9cdd1e78737a443570194a03d89285576d3d7f3a3cf15cc55b3013e42635d4723e2e8fe1d0b274428604b630db9 +861f60f0462e04cd84924c36a28163def63e777318d00884ab8cb64c8df1df0bce5900342163edb60449296484a6c5bf +b7bc23fb4e14af4c4704a944253e760adefeca8caee0882b6bbd572c84434042236f39ae07a8f21a560f486b15d82819 +b9a6eb492d6dd448654214bd01d6dc5ff12067a11537ab82023fc16167507ee25eed2c91693912f4155d1c07ed9650b3 +97678af29c68f9a5e213bf0fb85c265303714482cfc4c2c00b4a1e8a76ed08834ee6af52357b143a1ca590fb0265ea5a +8a15b499e9eca5b6cac3070b5409e8296778222018ad8b53a5d1f6b70ad9bb10c68a015d105c941ed657bf3499299e33 +b487fefede2e8091f2c7bfe85770db2edff1db83d4effe7f7d87bff5ab1ace35e9b823a71adfec6737fede8d67b3c467 +8b51b916402aa2c437fce3bcad6dad3be8301a1a7eab9d163085b322ffb6c62abf28637636fe6114573950117fc92898 +b06a2106d031a45a494adec0881cb2f82275dff9dcdd2bc16807e76f3bec28a6734edd3d54f0be8199799a78cd6228ad +af0a185391bbe2315eb97feac98ad6dd2e5d931d012c621abd6e404a31cc188b286fef14871762190acf086482b2b5e2 +8e78ee8206506dd06eb7729e32fceda3bebd8924a64e4d8621c72e36758fda3d0001af42443851d6c0aea58562870b43 +a1ba52a569f0461aaf90b49b92be976c0e73ec4a2c884752ee52ffb62dd137770c985123d405dfb5de70692db454b54a +8d51b692fa1543c51f6b62b9acb8625ed94b746ef96c944ca02859a4133a5629da2e2ce84e111a7af8d9a5b836401c64 +a7a20d45044cf6492e0531d0b8b26ffbae6232fa05a96ed7f06bdb64c2b0f5ca7ec59d5477038096a02579e633c7a3ff +84df867b98c53c1fcd4620fef133ee18849c78d3809d6aca0fb6f50ff993a053a455993f216c42ab6090fa5356b8d564 +a7227c439f14c48e2577d5713c97a5205feb69acb0b449152842e278fa71e8046adfab468089c8b2288af1fc51fa945b +855189b3a105670779997690876dfaa512b4a25a24931a912c2f0f1936971d2882fb4d9f0b3d9daba77eaf660e9d05d5 +b5696bd6706de51c502f40385f87f43040a5abf99df705d6aac74d88c913b8ecf7a99a63d7a37d9bdf3a941b9e432ff5 +ab997beb0d6df9c98d5b49864ef0b41a2a2f407e1687dfd6089959757ba30ed02228940b0e841afe6911990c74d536c4 +b36b65f85546ebfdbe98823d5555144f96b4ab39279facd19c0de3b8919f105ba0315a0784dce4344b1bc62d8bb4a5a3 +b8371f0e4450788720ac5e0f6cd3ecc5413d33895083b2c168d961ec2b5c3de411a4cc0712481cbe8df8c2fa1a7af006 +98325d8026b810a8b7a114171ae59a57e8bbc9848e7c3df992efc523621729fd8c9f52114ce01d7730541a1ada6f1df1 +8d0e76dbd37806259486cd9a31bc8b2306c2b95452dc395546a1042d1d17863ef7a74c636b782e214d3aa0e8d717f94a +a4e15ead76da0214d702c859fb4a8accdcdad75ed08b865842bd203391ec4cba2dcc916455e685f662923b96ee0c023f +8618190972086ebb0c4c1b4a6c94421a13f378bc961cc8267a301de7390c5e73c3333864b3b7696d81148f9d4843fd02 +85369d6cc7342e1aa15b59141517d8db8baaaeb7ab9670f3ba3905353948d575923d283b7e5a05b13a30e7baf1208a86 +87c51ef42233c24a6da901f28c9a075d9ba3c625687c387ad6757b72ca6b5a8885e6902a3082da7281611728b1e45f26 +aa6348a4f71927a3106ad0ea8b02fc8d8c65531e4ab0bd0a17243e66f35afe252e40ab8eef9f13ae55a72566ffdaff5c +96a3bc976e9d03765cc3fee275fa05b4a84c94fed6b767e23ca689394501e96f56f7a97cffddc579a6abff632bf153be +97dbf96c6176379fdb2b888be4e757b2bca54e74124bd068d3fa1dbd82a011bbeb75079da38e0cd22a761fe208ecad9b +b70cf0a1d14089a4129ec4e295313863a59da8c7e26bf74cc0e704ed7f0ee4d7760090d0ddf7728180f1bf2c5ac64955 +882d664714cc0ffe53cbc9bef21f23f3649824f423c4dbad1f893d22c4687ab29583688699efc4d5101aa08b0c3e267a +80ecb7cc963e677ccaddbe3320831dd6ee41209acf4ed41b16dc4817121a3d86a1aac9c4db3d8c08a55d28257088af32 +a25ba667d832b145f9ce18c3f9b1bd00737aa36db020e1b99752c8ef7d27c6c448982bd8d352e1b6df266b8d8358a8d5 +83734841c13dee12759d40bdd209b277e743b0d08cc0dd1e0b7afd2d65bfa640400eefcf6be4a52e463e5b3d885eeac6 +848d16505b04804afc773aebabb51b36fd8aacfbb0e09b36c0d5d57df3c0a3b92f33e7d5ad0a7006ec46ebb91df42b8c +909a8d793f599e33bb9f1dc4792a507a97169c87cd5c087310bc05f30afcd247470b4b56dec59894c0fb1d48d39bb54e +8e558a8559df84a1ba8b244ece667f858095c50bb33a5381e60fcc6ba586b69693566d8819b4246a27287f16846c1dfa +84d6b69729f5aaa000cd710c2352087592cfbdf20d5e1166977e195818e593fa1a50d1e04566be23163a2523dc1612f1 +9536d262b7a42125d89f4f32b407d737ba8d9242acfc99d965913ab3e043dcac9f7072a43708553562cac4cba841df30 +9598548923ca119d6a15fd10861596601dd1dedbcccca97bb208cdc1153cf82991ea8cc17686fbaa867921065265970c +b87f2d4af6d026e4d2836bc3d390a4a18e98a6e386282ce96744603bab74974272e97ac2da281afa21885e2cbb3a8001 +991ece62bf07d1a348dd22191868372904b9f8cf065ae7aa4e44fd24a53faf6d851842e35fb472895963aa1992894918 +a8c53dea4c665b30e51d22ca6bc1bc78aaf172b0a48e64a1d4b93439b053877ec26cb5221c55efd64fa841bbf7d5aff4 +93487ec939ed8e740f15335b58617c3f917f72d07b7a369befd479ae2554d04deb240d4a14394b26192efae4d2f4f35d +a44793ab4035443f8f2968a40e043b4555960193ffa3358d22112093aadfe2c136587e4139ffd46d91ed4107f61ea5e0 +b13fe033da5f0d227c75927d3dacb06dbaf3e1322f9d5c7c009de75cdcba5e308232838785ab69a70f0bedea755e003f +970a29b075faccd0700fe60d1f726bdebf82d2cc8252f4a84543ebd3b16f91be42a75c9719a39c4096139f0f31393d58 +a4c3eb1f7160f8216fc176fb244df53008ff32f2892363d85254002e66e2de21ccfe1f3b1047589abee50f29b9d507e3 +8c552885eab04ba40922a8f0c3c38c96089c95ff1405258d3f1efe8d179e39e1295cbf67677894c607ae986e4e6b1fb0 +b3671746fa7f848c4e2ae6946894defadd815230b906b419143523cc0597bc1d6c0a4c1e09d49b66b4a2c11cde3a4de3 +937a249a95813a5e2ef428e355efd202e15a37d73e56cfb7e57ea9f943f2ce5ca8026f2f1fd25bf164ba89d07077d858 +83646bdf6053a04aa9e2f112499769e5bd5d0d10f2e13db3ca89bd45c0b3b7a2d752b7d137fb3909f9c62b78166c9339 +b4eac4b91e763666696811b7ed45e97fd78310377ebea1674b58a2250973f80492ac35110ed1240cd9bb2d17493d708c +82db43a99bc6573e9d92a3fd6635dbbb249ac66ba53099c3c0c8c8080b121dd8243cd5c6e36ba0a4d2525bae57f5c89c +a64d6a264a681b49d134c655d5fc7756127f1ee7c93d328820f32bca68869f53115c0d27fef35fe71f7bc4fdaed97348 +8739b7a9e2b4bc1831e7f04517771bc7cde683a5e74e052542517f8375a2f64e53e0d5ac925ef722327e7bb195b4d1d9 +8f337cdd29918a2493515ebb5cf702bbe8ecb23b53c6d18920cc22f519e276ca9b991d3313e2d38ae17ae8bdfa4f8b7e +b0edeab9850e193a61f138ef2739fc42ceec98f25e7e8403bfd5fa34a7bc956b9d0898250d18a69fa4625a9b3d6129da +a9920f26fe0a6d51044e623665d998745c9eca5bce12051198b88a77d728c8238f97d4196f26e43b24f8841500b998d0 +86e655d61502b979eeeeb6f9a7e1d0074f936451d0a1b0d2fa4fb3225b439a3770767b649256fe481361f481a8dbc276 +84d3b32fa62096831cc3bf013488a9f3f481dfe293ae209ed19585a03f7db8d961a7a9dd0db82bd7f62d612707575d9c +81c827826ec9346995ffccf62a241e3b2d32f7357acd1b1f8f7a7dbc97022d3eb51b8a1230e23ce0b401d2e535e8cd78 +94a1e40c151191c5b055b21e86f32e69cbc751dcbdf759a48580951834b96a1eed75914c0d19a38aefd21fb6c8d43d0c +ab890222b44bc21b71f7c75e15b6c6e16bb03371acce4f8d4353ff3b8fcd42a14026589c5ed19555a3e15e4d18bfc3a3 +accb0be851e93c6c8cc64724cdb86887eea284194b10e7a43c90528ed97e9ec71ca69c6fac13899530593756dd49eab2 +b630220aa9e1829c233331413ee28c5efe94ea8ea08d0c6bfd781955078b43a4f92915257187d8526873e6c919c6a1de +add389a4d358c585f1274b73f6c3c45b58ef8df11f9d11221f620e241bf3579fba07427b288c0c682885a700cc1fa28d +a9fe6ca8bf2961a3386e8b8dcecc29c0567b5c0b3bcf3b0f9169f88e372b80151af883871fc5229815f94f43a6f5b2b0 +ad839ae003b92b37ea431fa35998b46a0afc3f9c0dd54c3b3bf7a262467b13ff3c323ada1c1ae02ac7716528bdf39e3e +9356d3fd0edcbbb65713c0f2a214394f831b26f792124b08c5f26e7f734b8711a87b7c4623408da6a091c9aef1f6af3c +896b25b083c35ac67f0af3784a6a82435b0e27433d4d74cd6d1eafe11e6827827799490fb1c77c11de25f0d75f14e047 +8bfa019391c9627e8e5f05c213db625f0f1e51ec68816455f876c7e55b8f17a4f13e5aae9e3fb9e1cf920b1402ee2b40 +8ba3a6faa6a860a8f3ce1e884aa8769ceded86380a86520ab177ab83043d380a4f535fe13884346c5e51bee68da6ab41 +a8292d0844084e4e3bb7af92b1989f841a46640288c5b220fecfad063ee94e86e13d3d08038ec2ac82f41c96a3bfe14d +8229bb030b2fc566e11fd33c7eab7a1bb7b49fed872ea1f815004f7398cb03b85ea14e310ec19e1f23e0bdaf60f8f76c +8cfbf869ade3ec551562ff7f63c2745cc3a1f4d4dc853a0cd42dd5f6fe54228f86195ea8fe217643b32e9f513f34a545 +ac52a3c8d3270ddfe1b5630159da9290a5ccf9ccbdef43b58fc0a191a6c03b8a5974cf6e2bbc7bd98d4a40a3581482d7 +ab13decb9e2669e33a7049b8eca3ca327c40dea15ad6e0e7fa63ed506db1d258bc36ac88b35f65cae0984e937eb6575d +b5e748eb1a7a1e274ff0cc56311c198f2c076fe4b7e73e5f80396fe85358549df906584e6bb2c8195b3e2be7736850a5 +b5cb911325d8f963c41f691a60c37831c7d3bbd92736efa33d1f77a22b3fde7f283127256c2f47e197571e6fe0b46149 +8a01dc6ed1b55f26427a014faa347130738b191a06b800e32042a46c13f60b49534520214359d68eb2e170c31e2b8672 +a72fa874866e19b2efb8e069328362bf7921ec375e3bcd6b1619384c3f7ee980f6cf686f3544e9374ff54b4d17a1629c +8db21092f7c5f110fba63650b119e82f4b42a997095d65f08f8237b02dd66fdf959f788df2c35124db1dbd330a235671 +8c65d50433d9954fe28a09fa7ba91a70a590fe7ba6b3060f5e4be0f6cef860b9897fa935fb4ebc42133524eb071dd169 +b4614058e8fa21138fc5e4592623e78b8982ed72aa35ee4391b164f00c68d277fa9f9eba2eeefc890b4e86eba5124591 +ab2ad3a1bce2fbd55ca6b7c23786171fe1440a97d99d6df4d80d07dd56ac2d7203c294b32fc9e10a6c259381a73f24a1 +812ae3315fdc18774a8da3713a4679e8ed10b9405edc548c00cacbe25a587d32040566676f135e4723c5dc25df5a22e9 +a464b75f95d01e5655b54730334f443c8ff27c3cb79ec7af4b2f9da3c2039c609908cd128572e1fd0552eb597e8cef8d +a0db3172e93ca5138fe419e1c49a1925140999f6eff7c593e5681951ee0ec1c7e454c851782cbd2b8c9bc90d466e90e0 +806db23ba7d00b87d544eed926b3443f5f9c60da6b41b1c489fba8f73593b6e3b46ebfcab671ee009396cd77d5e68aa1 +8bfdf2c0044cc80260994e1c0374588b6653947b178e8b312be5c2a05e05767e98ea15077278506aee7df4fee1aaf89e +827f6558c16841b5592ff089c9c31e31eb03097623524394813a2e4093ad2d3f8f845504e2af92195aaa8a1679d8d692 +925c4f8eab2531135cd71a4ec88e7035b5eea34ba9d799c5898856080256b4a15ed1a746e002552e2a86c9c157e22e83 +a9f9a368f0e0b24d00a35b325964c85b69533013f9c2cfad9708be5fb87ff455210f8cb8d2ce3ba58ca3f27495552899 +8ac0d3bebc1cae534024187e7c71f8927ba8fcc6a1926cb61c2b6c8f26bb7831019e635a376146c29872a506784a4aaa +97c577be2cbbfdb37ad754fae9df2ada5fc5889869efc7e18a13f8e502fbf3f4067a509efbd46fd990ab47ce9a70f5a8 +935e7d82bca19f16614aa43b4a3474e4d20d064e4bfdf1cea2909e5c9ab72cfe3e54dc50030e41ee84f3588cebc524e9 +941aafc08f7c0d94cebfbb1f0aad5202c02e6e37f2c12614f57e727efa275f3926348f567107ee6d8914dd71e6060271 +af0fbc1ba05b4b5b63399686df3619968be5d40073de0313cbf5f913d3d4b518d4c249cdd2176468ccaa36040a484f58 +a0c414f23f46ca6d69ce74c6f8a00c036cb0edd098af0c1a7d39c802b52cfb2d5dbdf93fb0295453d4646e2af7954d45 +909cf39e11b3875bb63b39687ae1b5d1f5a15445e39bf164a0b14691b4ddb39a8e4363f584ef42213616abc4785b5d66 +a92bac085d1194fbd1c88299f07a061d0bdd3f980b663e81e6254dbb288bf11478c0ee880e28e01560f12c5ccb3c0103 +841705cd5cd76b943e2b7c5e845b9dd3c8defe8ef67e93078d6d5e67ade33ad4b0fd413bc196f93b0a4073c855cd97d4 +8e7eb8364f384a9161e81d3f1d52ceca9b65536ae49cc35b48c3e2236322ba4ae9973e0840802d9fa4f4d82ea833544f +aed3ab927548bc8bec31467ba80689c71a168e34f50dcb6892f19a33a099f5aa6b3f9cb79f5c0699e837b9a8c7f27efe +b8fbf7696210a36e20edabd77839f4dfdf50d6d015cdf81d587f90284a9bcef7d2a1ff520728d7cc69a4843d6c20dedd +a9d533769ce6830211c884ae50a82a7bf259b44ac71f9fb11f0296fdb3981e6b4c1753fe744647b247ebc433a5a61436 +8b4bdf90d33360b7f428c71cde0a49fb733badba8c726876945f58c620ce7768ae0e98fc8c31fa59d8955a4823336bb1 +808d42238e440e6571c59e52a35ae32547d502dc24fd1759d8ea70a7231a95859baf30b490a4ba55fa2f3aaa11204597 +85594701f1d2fee6dc1956bc44c7b31db93bdeec2f3a7d622c1a08b26994760773e3d57521a44cfd7e407ac3fd430429 +a66de045ce7173043a6825e9dc440ac957e2efb6df0a337f4f8003eb0c719d873a52e6eba3cb0d69d977ca37d9187674 +87a1c6a1fdff993fa51efa5c3ba034c079c0928a7d599b906336af7c2dcab9721ceaf3108c646490af9dff9a754f54b3 +926424223e462ceb75aed7c22ade8a7911a903b7e5dd4bc49746ddce8657f4616325cd12667d4393ac52cdd866396d0e +b5dc96106593b42b30f06f0b0a1e0c1aafc70432e31807252d3674f0b1ea5e58eac8424879d655c9488d85a879a3e572 +997ca0987735cc716507cb0124b1d266d218b40c9d8e0ecbf26a1d65719c82a637ce7e8be4b4815d307df717bde7c72a +92994d3f57a569b7760324bb5ae4e8e14e1633d175dab06aa57b8e391540e05f662fdc08b8830f489a063f59b689a688 +a8087fcc6aa4642cb998bea11facfe87eb33b90a9aa428ab86a4124ad032fc7d2e57795311a54ec9f55cc120ebe42df1 +a9bd7d1de6c0706052ca0b362e2e70e8c8f70f1f026ea189b4f87a08ce810297ebfe781cc8004430776c54c1a05ae90c +856d33282e8a8e33a3d237fb0a0cbabaf77ba9edf2fa35a831fdafcadf620561846aa6cbb6bdc5e681118e1245834165 +9524a7aa8e97a31a6958439c5f3339b19370f03e86b89b1d02d87e4887309dbbe9a3a8d2befd3b7ed5143c8da7e0a8ad +824fdf433e090f8acbd258ac7429b21f36f9f3b337c6d0b71d1416a5c88a767883e255b2888b7c906dd2e9560c4af24c +88c7fee662ca7844f42ed5527996b35723abffd0d22d4ca203b9452c639a5066031207a5ae763dbc0865b3299d19b1ec +919dca5c5595082c221d5ab3a5bc230f45da7f6dec4eb389371e142c1b9c6a2c919074842479c2844b72c0d806170c0c +b939be8175715e55a684578d8be3ceff3087f60fa875fff48e52a6e6e9979c955efef8ff67cfa2b79499ea23778e33b0 +873b6db725e7397d11bc9bed9ac4468e36619135be686790a79bc6ed4249058f1387c9a802ea86499f692cf635851066 +aeae06db3ec47e9e5647323fa02fac44e06e59b885ad8506bf71b184ab3895510c82f78b6b22a5d978e8218e7f761e9f +b99c0a8359c72ab88448bae45d4bf98797a26bca48b0d4460cd6cf65a4e8c3dd823970ac3eb774ae5d0cea4e7fadf33e +8f10c8ec41cdfb986a1647463076a533e6b0eec08520c1562401b36bb063ac972aa6b28a0b6ce717254e35940b900e3c +a106d9be199636d7add43b942290269351578500d8245d4aae4c083954e4f27f64740a3138a66230391f2d0e6043a8de +a469997908244578e8909ff57cffc070f1dbd86f0098df3cfeb46b7a085cfecc93dc69ee7cad90ff1dc5a34d50fe580c +a4ef087bea9c20eb0afc0ee4caba7a9d29dfa872137828c721391273e402fb6714afc80c40e98bbd8276d3836bffa080 +b07a013f73cd5b98dae0d0f9c1c0f35bff8a9f019975c4e1499e9bee736ca6fcd504f9bc32df1655ff333062382cff04 +b0a77188673e87cc83348c4cc5db1eecf6b5184e236220c8eeed7585e4b928db849944a76ec60ef7708ef6dac02d5592 +b1284b37e59b529f0084c0dacf0af6c0b91fc0f387bf649a8c74819debf606f7b07fc3e572500016fb145ec2b24e9f17 +97b20b5b4d6b9129da185adfbf0d3d0b0faeba5b9715f10299e48ea0521709a8296a9264ce77c275a59c012b50b6519a +b9d37e946fae5e4d65c1fbfacc8a62e445a1c9d0f882e60cca649125af303b3b23af53c81d7bac544fb7fcfc7a314665 +8e5acaac379f4bb0127efbef26180f91ff60e4c525bc9b798fc50dfaf4fe8a5aa84f18f3d3cfb8baead7d1e0499af753 +b0c0b8ab1235bf1cda43d4152e71efc1a06c548edb964eb4afceb201c8af24240bf8ab5cae30a08604e77432b0a5faf0 +8cc28d75d5c8d062d649cbc218e31c4d327e067e6dbd737ec0a35c91db44fbbd0d40ec424f5ed79814add16947417572 +95ae6219e9fd47efaa9cb088753df06bc101405ba50a179d7c9f7c85679e182d3033f35b00dbba71fdcd186cd775c52e +b5d28fa09f186ebc5aa37453c9b4d9474a7997b8ae92748ecb940c14868792292ac7d10ade01e2f8069242b308cf97e5 +8c922a0faa14cc6b7221f302df3342f38fc8521ec6c653f2587890192732c6da289777a6cd310747ea7b7d104af95995 +b9ad5f660b65230de54de535d4c0fcae5bc6b59db21dea5500fdc12eea4470fb8ea003690fdd16d052523418d5e01e8c +a39a9dd41a0ff78c82979483731f1cd68d3921c3e9965869662c22e02dde3877802e180ba93f06e7346f96d9fa9261d2 +8b32875977ec372c583b24234c27ed73aef00cdff61eb3c3776e073afbdeade548de9497c32ec6d703ff8ad0a5cb7fe4 +9644cbe755a5642fe9d26cfecf170d3164f1848c2c2e271d5b6574a01755f3980b3fc870b98cf8528fef6ecef4210c16 +81ea9d1fdd9dd66d60f40ce0712764b99da9448ae0b300f8324e1c52f154e472a086dda840cb2e0b9813dc8ce8afd4b5 +906aaa4a7a7cdf01909c5cfbc7ded2abc4b869213cbf7c922d4171a4f2e637e56f17020b852ad339d83b8ac92f111666 +939b5f11acbdeff998f2a080393033c9b9d8d5c70912ea651c53815c572d36ee822a98d6dfffb2e339f29201264f2cf4 +aba4898bf1ccea9b9e2df1ff19001e05891581659c1cbbde7ee76c349c7fc7857261d9785823c9463a8aea3f40e86b38 +83ca1a56b8a0be4820bdb5a9346357c68f9772e43f0b887729a50d2eb2a326bbcede676c8bf2e51d7c89bbd8fdb778a6 +94e86e9fe6addfe2c3ee3a547267ed921f4230d877a85bb4442c2d9350c2fa9a9c54e6fe662de82d1a2407e4ab1691c2 +a0cc3bdef671a59d77c6984338b023fa2b431b32e9ed2abe80484d73edc6540979d6f10812ecc06d4d0c5d4eaca7183c +b5343413c1b5776b55ea3c7cdd1f3af1f6bd802ea95effe3f2b91a523817719d2ecc3f8d5f3cc2623ace7e35f99ca967 +92085d1ed0ed28d8cabe3e7ff1905ed52c7ceb1eac5503760c52fb5ee3a726aba7c90b483c032acc3f166b083d7ec370 +8ec679520455275cd957fca8122724d287db5df7d29f1702a322879b127bff215e5b71d9c191901465d19c86c8d8d404 +b65eb2c63d8a30332eb24ee8a0c70156fc89325ebbb38bacac7cf3f8636ad8a472d81ccca80423772abc00192d886d8a +a9fe1c060b974bee4d590f2873b28635b61bfcf614e61ff88b1be3eee4320f4874e21e8d666d8ac8c9aba672efc6ecae +b3fe2a9a389c006a831dea7e777062df84b5c2803f9574d7fbe10b7e1c125817986af8b6454d6be9d931a5ac94cfe963 +95418ad13b734b6f0d33822d9912c4c49b558f68d08c1b34a0127fcfa666bcae8e6fda8832d2c75bb9170794a20e4d7c +a9a7df761e7f18b79494bf429572140c8c6e9d456c4d4e336184f3f51525a65eb9582bea1e601bdb6ef8150b7ca736a5 +a0de03b1e75edf7998c8c1ac69b4a1544a6fa675a1941950297917366682e5644a4bda9cdeedfaf9473d7fccd9080b0c +a61838af8d95c95edf32663a68f007d95167bf6e41b0c784a30b22d8300cfdd5703bd6d16e86396638f6db6ae7e42a85 +8866d62084d905c145ff2d41025299d8b702ac1814a7dec4e277412c161bc9a62fed735536789cb43c88693c6b423882 +91da22c378c81497fe363e7f695c0268443abee50f8a6625b8a41e865638a643f07b157ee566de09ba09846934b4e2d7 +941d21dd57c9496aa68f0c0c05507405fdd413acb59bc668ce7e92e1936c68ec4b065c3c30123319884149e88228f0b2 +a77af9b094bc26966ddf2bf9e1520c898194a5ccb694915950dadc204facbe3066d3d89f50972642d76b14884cfbaa21 +8e76162932346869f4618bde744647f7ab52ab498ad654bdf2a4feeb986ac6e51370841e5acbb589e38b6e7142bb3049 +b60979ace17d6937ece72e4f015da4657a443dd01cebc7143ef11c09e42d4aa8855999a65a79e2ea0067f31c9fc2ab0f +b3e2ffdd5ee6fd110b982fd4fad4b93d0fca65478f986d086eeccb0804960bfaa1919afa743c2239973ea65091fe57d2 +8ce0ce05e7d7160d44574011da687454dbd3c8b8290aa671731b066e2c82f8cf2d63cb8e932d78c6122ec610e44660e6 +ab005dd8d297045c39e2f72fb1c48edb501ccf3575d3d04b9817b3afee3f0bb0f3f53f64bda37d1d9cde545aae999bae +95bd7edb4c4cd60e3cb8a72558845a3cce6bb7032ccdf33d5a49ebb6ddf203bc3c79e7b7e550735d2d75b04c8b2441e8 +889953ee256206284094e4735dbbb17975bafc7c3cb94c9fbfee4c3e653857bfd49e818f64a47567f721b98411a3b454 +b188423e707640ab0e75a061e0b62830cde8afab8e1ad3dae30db69ffae4e2fc005bababbdcbd7213b918ed4f70e0c14 +a97e0fafe011abd70d4f99a0b36638b3d6e7354284588f17a88970ed48f348f88392779e9a038c6cbc9208d998485072 +87db11014a91cb9b63e8dfaa82cdebca98272d89eb445ee1e3ff9dbaf2b3fad1a03b888cffc128e4fe208ed0dddece0f +aad2e40364edd905d66ea4ac9d51f9640d6fda9a54957d26ba233809851529b32c85660fa401dbee3679ec54fa6dd966 +863e99336ca6edf03a5a259e59a2d0f308206e8a2fb320cfc0be06057366df8e0f94b33a28f574092736b3c5ada84270 +b34bcc56a057589f34939a1adc51de4ff6a9f4fee9c7fa9aa131e28d0cf0759a0c871b640162acdfbf91f3f1b59a3703 +935dd28f2896092995c5eff1618e5b6efe7a40178888d7826da9b0503c2d6e68a28e7fac1a334e166d0205f0695ef614 +b842cd5f8f5de5ca6c68cb4a5c1d7b451984930eb4cc18fd0934d52fdc9c3d2d451b1c395594d73bc3451432bfba653f +9014537885ce2debad736bc1926b25fdab9f69b216bf024f589c49dc7e6478c71d595c3647c9f65ff980b14f4bb2283b +8e827ccca1dd4cd21707140d10703177d722be0bbe5cac578db26f1ef8ad2909103af3c601a53795435b27bf95d0c9ed +8a0b8ad4d466c09d4f1e9167410dbe2edc6e0e6229d4b3036d30f85eb6a333a18b1c968f6ca6d6889bb08fecde017ef4 +9241ee66c0191b06266332dc9161dede384c4bb4e116dbd0890f3c3790ec5566da4568243665c4725b718ac0f6b5c179 +aeb4d5fad81d2b505d47958a08262b6f1b1de9373c2c9ba6362594194dea3e002ab03b8cbb43f867be83065d3d370f19 +8781bc83bb73f7760628629fe19e4714b494dbed444c4e4e4729b7f6a8d12ee347841a199888794c2234f51fa26fc2b9 +b58864f0acd1c2afa29367e637cbde1968d18589245d9936c9a489c6c495f54f0113ecdcbe4680ac085dd3c397c4d0c3 +94a24284afaeead61e70f3e30f87248d76e9726759445ca18cdb9360586c60cc9f0ec1c397f9675083e0b56459784e2e +aed358853f2b54dcbddf865e1816c2e89be12e940e1abfa661e2ee63ffc24a8c8096be2072fa83556482c0d89e975124 +b95374e6b4fc0765708e370bc881e271abf2e35c08b056a03b847e089831ef4fe3124b9c5849d9c276eb2e35b3daf264 +b834cdbcfb24c8f84bfa4c552e7fadc0028a140952fd69ed13a516e1314a4cd35d4b954a77d51a1b93e1f5d657d0315d +8fb6d09d23bfa90e7443753d45a918d91d75d8e12ec7d016c0dfe94e5c592ba6aaf483d2f16108d190822d955ad9cdc3 +aa315cd3c60247a6ad4b04f26c5404c2713b95972843e4b87b5a36a89f201667d70f0adf20757ebe1de1b29ae27dda50 +a116862dca409db8beff5b1ccd6301cdd0c92ca29a3d6d20eb8b87f25965f42699ca66974dd1a355200157476b998f3b +b4c2f5fe173c4dc8311b60d04a65ce1be87f070ac42e13cd19c6559a2931c6ee104859cc2520edebbc66a13dc7d30693 +8d4a02bf99b2260c334e7d81775c5cf582b00b0c982ce7745e5a90624919028278f5e9b098573bad5515ce7fa92a80c8 +8543493bf564ce6d97bd23be9bff1aba08bd5821ca834f311a26c9139c92a48f0c2d9dfe645afa95fec07d675d1fd53b +9344239d13fde08f98cb48f1f87d34cf6abe8faecd0b682955382a975e6eed64e863fa19043290c0736261622e00045c +aa49d0518f343005ca72b9e6c7dcaa97225ce6bb8b908ebbe7b1a22884ff8bfb090890364e325a0d414ad180b8f161d1 +907d7fd3e009355ab326847c4a2431f688627faa698c13c03ffdd476ecf988678407f029b8543a475dcb3dafdf2e7a9c +845f1f10c6c5dad2adc7935f5cd2e2b32f169a99091d4f1b05babe7317b9b1cdce29b5e62f947dc621b9acbfe517a258 +8f3be8e3b380ea6cdf9e9c237f5e88fd5a357e5ded80ea1fc2019810814de82501273b4da38916881125b6fa0cfd4459 +b9c7f487c089bf1d20c822e579628db91ed9c82d6ca652983aa16d98b4270c4da19757f216a71b9c13ddee3e6e43705f +8ba2d8c88ad2b872db104ea8ddbb006ec2f3749fd0e19298a804bb3a5d94de19285cc7fb19fee58a66f7851d1a66c39f +9375ecd3ed16786fe161af5d5c908f56eeb467a144d3bbddfc767e90065b7c94fc53431adebecba2b6c9b5821184d36e +a49e069bfadb1e2e8bff6a4286872e2a9765d62f0eaa4fcb0e5af4bbbed8be3510fb19849125a40a8a81d1e33e81c3eb +9522cc66757b386aa6b88619525c8ce47a5c346d590bb3647d12f991e6c65c3ab3c0cfc28f0726b6756c892eae1672be +a9a0f1f51ff877406fa83a807aeb17b92a283879f447b8a2159653db577848cc451cbadd01f70441e351e9ed433c18bc +8ff7533dcff6be8714df573e33f82cf8e9f2bcaaa43e939c4759d52b754e502717950de4b4252fb904560fc31dce94a4 +959724671e265a28d67c29d95210e97b894b360da55e4cf16e6682e7912491ed8ca14bfaa4dce9c25a25b16af580494f +92566730c3002f4046c737032487d0833c971e775de59fe02d9835c9858e2e3bc37f157424a69764596c625c482a2219 +a84b47ceff13ed9c3e5e9cdf6739a66d3e7c2bd8a6ba318fefb1a9aecf653bb2981da6733ddb33c4b0a4523acc429d23 +b4ddf571317e44f859386d6140828a42cf94994e2f1dcbcc9777f4eebbfc64fc1e160b49379acc27c4672b8e41835c5d +8ab95c94072b853d1603fdd0a43b30db617d13c1d1255b99075198e1947bfa5f59aed2b1147548a1b5e986cd9173d15c +89511f2eab33894fd4b3753d24249f410ff7263052c1fef6166fc63a79816656b0d24c529e45ccce6be28de6e375d916 +a0866160ca63d4f2be1b4ea050dac6b59db554e2ebb4e5b592859d8df339b46fd7cb89aaed0951c3ee540aee982c238a +8fcc5cbba1b94970f5ff2eb1922322f5b0aa7d918d4b380c9e7abfd57afd8b247c346bff7b87af82efbce3052511cd1b +99aeb2a5e846b0a2874cca02c66ed40d5569eb65ab2495bc3f964a092e91e1517941f2688e79f8cca49cd3674c4e06dc +b7a096dc3bad5ca49bee94efd884aa3ff5615cf3825cf95fbe0ce132e35f46581d6482fa82666c7ef5f1643eaee8f1ca +94393b1da6eaac2ffd186b7725eca582f1ddc8cdd916004657f8a564a7c588175cb443fc6943b39029f5bbe0add3fad8 +884b85fe012ccbcd849cb68c3ad832d83b3ef1c40c3954ffdc97f103b1ed582c801e1a41d9950f6bddc1d11f19d5ec76 +b00061c00131eded8305a7ce76362163deb33596569afb46fe499a7c9d7a0734c084d336b38d168024c2bb42b58e7660 +a439153ac8e6ca037381e3240e7ba08d056c83d7090f16ed538df25901835e09e27de2073646e7d7f3c65056af6e4ce7 +830fc9ca099097d1f38b90e6843dc86f702be9d20bdacc3e52cae659dc41df5b8d2c970effa6f83a5229b0244a86fe22 +b81ea2ffaaff2bb00dd59a9ab825ba5eed4db0d8ac9c8ed1a632ce8f086328a1cddd045fbe1ace289083c1325881b7e7 +b51ea03c58daf2db32c99b9c4789b183365168cb5019c72c4cc91ac30b5fb7311d3db76e6fa41b7cd4a8c81e2f6cdc94 +a4170b2c6d09ca5beb08318730419b6f19215ce6c631c854116f904be3bc30dd85a80c946a8ab054d3e307afaa3f8fbc +897cc42ff28971ff54d2a55dd6b35cfb8610ac902f3c06e3a5cea0e0a257e870c471236a8e84709211c742a09c5601a6 +a18f2e98d389dace36641621488664ecbb422088ab03b74e67009b8b8acacaaa24fdcf42093935f355207d934adc52a8 +92adcfb678cc2ba19c866f3f2b988fdcb4610567f3ab436cc0cb9acaf5a88414848d71133ebdbec1983e38e6190f1b5f +a86d43c2ce01b366330d3b36b3ca85f000c3548b8297e48478da1ee7d70d8576d4650cba7852ed125c0d7cb6109aa7f3 +8ed31ceed9445437d7732dce78a762d72ff32a7636bfb3fd7974b7ae15db414d8184a1766915244355deb354fbc5803b +9268f70032584f416e92225d65af9ea18c466ebc7ae30952d56a4e36fd9ea811dde0a126da9220ba3c596ec54d8a335e +9433b99ee94f2d3fbdd63b163a2bdf440379334c52308bd24537f7defd807145a062ff255a50d119a7f29f4b85d250e3 +90ce664f5e4628a02278f5cf5060d1a34f123854634b1870906e5723ac9afd044d48289be283b267d45fcbf3f4656aaf +aaf21c4d59378bb835d42ae5c5e5ab7a3c8c36a59e75997989313197752b79a472d866a23683b329ea69b048b87fa13e +b83c0589b304cec9ede549fde54f8a7c2a468c6657da8c02169a6351605261202610b2055c639b9ed2d5b8c401fb8f56 +9370f326ea0f170c2c05fe2c5a49189f20aec93b6b18a5572a818cd4c2a6adb359e68975557b349fb54f065d572f4c92 +ac3232fa5ce6f03fca238bef1ce902432a90b8afce1c85457a6bee5571c033d4bceefafc863af04d4e85ac72a4d94d51 +80d9ea168ff821b22c30e93e4c7960ce3ad3c1e6deeebedd342a36d01bd942419b187e2f382dbfd8caa34cca08d06a48 +a387a3c61676fb3381eefa2a45d82625635a666e999aba30e3b037ec9e040f414f9e1ad9652abd3bcad63f95d85038db +a1b229fe32121e0b391b0f6e0180670b9dc89d79f7337de4c77ea7ad0073e9593846f06797c20e923092a08263204416 +92164a9d841a2b828cedf2511213268b698520f8d1285852186644e9a0c97512cafa4bfbe29af892c929ebccd102e998 +82ee2fa56308a67c7db4fd7ef539b5a9f26a1c2cc36da8c3206ba4b08258fbb3cec6fe5cdbd111433fb1ba2a1e275927 +8c77bfe9e191f190a49d46f05600603fa42345592539b82923388d72392404e0b29a493a15e75e8b068dddcd444c2928 +80b927f93ccf79dcf5c5b20bcf5a7d91d7a17bc0401bb7cc9b53a6797feac31026eb114257621f5a64a52876e4474cc1 +b6b68b6501c37804d4833d5a063dd108a46310b1400549074e3cac84acc6d88f73948b7ad48d686de89c1ec043ae8c1a +ab3da00f9bdc13e3f77624f58a3a18fc3728956f84b5b549d62f1033ae4b300538e53896e2d943f160618e05af265117 +b6830e87233b8eace65327fdc764159645b75d2fd4024bf8f313b2dd5f45617d7ecfb4a0b53ccafb5429815a9a1adde6 +b9251cfe32a6dc0440615aadcd98b6b1b46e3f4e44324e8f5142912b597ee3526bea2431e2b0282bb58f71be5b63f65e +af8d70711e81cdddfb39e67a1b76643292652584c1ce7ce4feb1641431ad596e75c9120e85f1a341e7a4da920a9cdd94 +98cd4e996594e89495c078bfd52a4586b932c50a449a7c8dfdd16043ca4cda94dafbaa8ad1b44249c99bbcc52152506e +b9fc6d1c24f48404a4a64fbe3e43342738797905db46e4132aee5f086aaa4c704918ad508aaefa455cfe1b36572e6242 +a365e871d30ba9291cedaba1be7b04e968905d003e9e1af7e3b55c5eb048818ae5b913514fb08b24fb4fbdccbb35d0b8 +93bf99510971ea9af9f1e364f1234c898380677c8e8de9b0dd24432760164e46c787bc9ec42a7ad450500706cf247b2d +b872f825a5b6e7b9c7a9ddfeded3516f0b1449acc9b4fd29fc6eba162051c17416a31e5be6d3563f424d28e65bab8b8f +b06b780e5a5e8eb4f4c9dc040f749cf9709c8a4c9ef15e925f442b696e41e5095db0778a6c73bcd329b265f2c6955c8b +848f1a981f5fc6cd9180cdddb8d032ad32cdfa614fc750d690dbae36cc0cd355cbf1574af9b3ffc8b878f1b2fafb9544 +a03f48cbff3e9e8a3a655578051a5ae37567433093ac500ed0021c6250a51b767afac9bdb194ee1e3eac38a08c0eaf45 +b5be78ce638ff8c4aa84352b536628231d3f7558c5be3bf010b28feac3022e64691fa672f358c8b663904aebe24a54ed +a9d4da70ff676fa55d1728ba6ab03b471fa38b08854d99e985d88c2d050102d8ccffbe1c90249a5607fa7520b15fe791 +8fe9f7092ffb0b69862c8e972fb1ecf54308c96d41354ed0569638bb0364f1749838d6d32051fff1599112978c6e229c +ae6083e95f37770ecae0df1e010456f165d96cfe9a7278c85c15cffd61034081ce5723e25e2bede719dc9341ec8ed481 +a260891891103089a7afbd9081ea116cfd596fd1015f5b65e10b0961eb37fab7d09c69b7ce4be8bf35e4131848fb3fe4 +8d729fa32f6eb9fd2f6a140bef34e8299a2f3111bffd0fe463aa8622c9d98bfd31a1df3f3e87cd5abc52a595f96b970e +a30ec6047ae4bc7da4daa7f4c28c93aedb1112cfe240e681d07e1a183782c9ff6783ac077c155af23c69643b712a533f +ac830726544bfe7b5467339e5114c1a75f2a2a8d89453ce86115e6a789387e23551cd64620ead6283dfa4538eb313d86 +8445c135b7a48068d8ed3e011c6d818cfe462b445095e2fbf940301e50ded23f272d799eea47683fc027430ce14613ef +95785411715c9ae9d8293ce16a693a2aa83e3cb1b4aa9f76333d0da2bf00c55f65e21e42e50e6c5772ce213dd7b4f7a0 +b273b024fa18b7568c0d1c4d2f0c4e79ec509dafac8c5951f14192d63ddbcf2d8a7512c1c1b615cc38fa3e336618e0c5 +a78b9d3ea4b6a90572eb27956f411f1d105fdb577ee2ffeec9f221da9b45db84bfe866af1f29597220c75e0c37a628d8 +a4be2bf058c36699c41513c4d667681ce161a437c09d81383244fc55e1c44e8b1363439d0cce90a3e44581fb31d49493 +b6eef13040f17dd4eba22aaf284d2f988a4a0c4605db44b8d2f4bf9567ac794550b543cc513c5f3e2820242dd704152e +87eb00489071fa95d008c5244b88e317a3454652dcb1c441213aa16b28cd3ecaa9b22fec0bdd483c1df71c37119100b1 +92d388acdcb49793afca329cd06e645544d2269234e8b0b27d2818c809c21726bc9cf725651b951e358a63c83dedee24 +ae27e219277a73030da27ab5603c72c8bd81b6224b7e488d7193806a41343dff2456132274991a4722fdb0ef265d04cd +97583e08ecb82bbc27c0c8476d710389fa9ffbead5c43001bd36c1b018f29faa98de778644883e51870b69c5ffb558b5 +90a799a8ce73387599babf6b7da12767c0591cadd36c20a7990e7c05ea1aa2b9645654ec65308ee008816623a2757a6a +a1b47841a0a2b06efd9ab8c111309cc5fc9e1d5896b3e42ed531f6057e5ade8977c29831ce08dbda40348386b1dcc06d +b92b8ef59bbddb50c9457691bc023d63dfcc54e0fd88bd5d27a09e0d98ac290fc90e6a8f6b88492043bf7c87fac8f3e4 +a9d6240b07d62e22ec8ab9b1f6007c975a77b7320f02504fc7c468b4ee9cfcfd945456ff0128bc0ef2174d9e09333f8d +8e96534c94693226dc32bca79a595ca6de503af635f802e86442c67e77564829756961d9b701187fe91318da515bf0e6 +b6ba290623cd8dd5c2f50931c0045d1cfb0c30877bc8fe58cbc3ff61ee8da100045a39153916efa1936f4aee0892b473 +b43baa7717fac02d4294f5b3bb5e58a65b3557747e3188b482410388daac7a9c177f762d943fd5dcf871273921213da8 +b9cf00f8fb5e2ef2b836659fece15e735060b2ea39b8e901d3dcbdcf612be8bf82d013833718c04cd46ffaa70b85f42e +8017d0c57419e414cbba504368723e751ef990cc6f05dad7b3c2de6360adc774ad95512875ab8337d110bf39a42026fa +ae7401048b838c0dcd4b26bb6c56d79d51964a0daba780970b6c97daee4ea45854ea0ac0e4139b3fe60dac189f84df65 +887b237b0cd0f816b749b21db0b40072f9145f7896c36916296973f9e6990ede110f14e5976c906d08987c9836cca57f +a88c3d5770148aee59930561ca1223aceb2c832fb5417e188dca935905301fc4c6c2c9270bc1dff7add490a125eb81c6 +b6cf9b02c0cd91895ad209e38c54039523f137b5848b9d3ad33ae43af6c20c98434952db375fe378de7866f2d0e8b18a +84ef3d322ff580c8ad584b1fe4fe346c60866eb6a56e982ba2cf3b021ecb1fdb75ecc6c29747adda86d9264430b3f816 +a0561c27224baf0927ad144cb71e31e54a064c598373fcf0d66aebf98ab7af1d8e2f343f77baefff69a6da750a219e11 +aa5cc43f5b8162b016f5e1b61214c0c9d15b1078911c650b75e6cdfb49b85ee04c6739f5b1687d15908444f691f732de +ad4ac099b935589c7b8fdfdf3db332b7b82bb948e13a5beb121ebd7db81a87d278024a1434bcf0115c54ca5109585c3d +8a00466abf3f109a1dcd19e643b603d3af23d42794ef8ca2514dd507ecea44a031ac6dbc18bd02f99701168b25c1791e +b00b5900dfad79645f8bee4e5adc7b84eb22e5b1e67df77ccb505b7fc044a6c08a8ea5faca662414eb945f874f884cea +950e204e5f17112250b22ea6bb8423baf522fc0af494366f18fe0f949f51d6e6812074a80875cf1ed9c8e7420058d541 +91e5cbf8bb1a1d50c81608c9727b414d0dd2fb467ebc92f100882a3772e54f94979cfdf8e373fdef7c7fcdd60fec9e00 +a093f6a857b8caaff80599c2e89c962b415ecbaa70d8fd973155fa976a284c6b29a855f5f7a3521134d00d2972755188 +b4d55a3551b00da54cc010f80d99ddd2544bde9219a3173dfaadf3848edc7e4056ab532fb75ac26f5f7141e724267663 +a03ea050fc9b011d1b04041b5765d6f6453a93a1819cd9bd6328637d0b428f08526466912895dcc2e3008ee58822e9a7 +99b12b3665e473d01bc6985844f8994fb65cb15745024fb7af518398c4a37ff215da8f054e8fdf3286984ae36a73ca5e +9972c7e7a7fb12e15f78d55abcaf322c11249cd44a08f62c95288f34f66b51f146302bce750ff4d591707075d9123bd2 +a64b4a6d72354e596d87cda213c4fc2814009461570ccb27d455bbe131f8d948421a71925425b546d8cf63d5458cd64b +91c215c73b195795ede2228b7ed1f6e37892e0c6b0f4a0b5a16c57aa1100c84df9239054a173b6110d6c2b7f4bf1ce52 +88807198910ec1303480f76a3683870246a995e36adaeadc29c22f0bdba8152fe705bd070b75de657b04934f7d0ccf80 +b37c0026c7b32eb02cacac5b55cb5fe784b8e48b2945c64d3037af83ece556a117f0ff053a5968c2f5fa230e291c1238 +94c768384ce212bc2387e91ce8b45e4ff120987e42472888a317abc9dcdf3563b62e7a61c8e98d7cdcbe272167d91fc6 +a10c2564936e967a390cb14ef6e8f8b04ea9ece5214a38837eda09e79e0c7970b1f83adf017c10efd6faa8b7ffa2c567 +a5085eed3a95f9d4b1269182ea1e0d719b7809bf5009096557a0674bde4201b0ddc1f0f16a908fc468846b3721748ce3 +87468eb620b79a0a455a259a6b4dfbc297d0d53336537b771254dd956b145dc816b195b7002647ea218552e345818a3f +ace2b77ffb87366af0a9cb5d27d6fc4a14323dbbf1643f5f3c4559306330d86461bb008894054394cbfaefeaa0bc2745 +b27f56e840a54fbd793f0b7a7631aa4cee64b5947e4382b2dfb5eb1790270288884c2a19afebe5dc0c6ef335d4531c1c +876e438633931f7f895062ee16c4b9d10428875f7bc79a8e156a64d379a77a2c45bf5430c5ab94330f03da352f1e9006 +a2512a252587d200d2092b44c914df54e04ff8bcef36bf631f84bde0cf5a732e3dc7f00f662842cfd74b0b0f7f24180e +827f1bc8f54a35b7a4bd8154f79bcc055e45faed2e74adf7cf21cca95df44d96899e847bd70ead6bb27b9c0ed97bbd8b +a0c92cf5a9ed843714f3aea9fe7b880f622d0b4a3bf66de291d1b745279accf6ba35097849691370f41732ba64b5966b +a63f5c1e222775658421c487b1256b52626c6f79cb55a9b7deb2352622cedffb08502042d622eb3b02c97f9c09f9c957 +8cc093d52651e65fb390e186db6cc4de559176af4624d1c44cb9b0e836832419dacac7b8db0627b96288977b738d785d +aa7b6a17dfcec146134562d32a12f7bd7fe9522e300859202a02939e69dbd345ed7ff164a184296268f9984f9312e8fc +8ac76721f0d2b679f023d06cbd28c85ae5f4b43c614867ccee88651d4101d4fd352dbdb65bf36bfc3ebc0109e4b0c6f9 +8d350f7c05fc0dcd9a1170748846fb1f5d39453e4cb31e6d1457bed287d96fc393b2ecc53793ca729906a33e59c6834a +b9913510dfc5056d7ec5309f0b631d1ec53e3a776412ada9aefdaf033c90da9a49fdde6719e7c76340e86599b1f0eec2 +94955626bf4ce87612c5cfffcf73bf1c46a4c11a736602b9ba066328dc52ad6d51e6d4f53453d4ed55a51e0aad810271 +b0fcab384fd4016b2f1e53f1aafd160ae3b1a8865cd6c155d7073ecc1664e05b1d8bca1def39c158c7086c4e1103345e +827de3f03edfbde08570b72de6662c8bfa499b066a0a27ebad9b481c273097d17a5a0a67f01553da5392ec3f149b2a78 +ab7940384c25e9027c55c40df20bd2a0d479a165ced9b1046958353cd69015eeb1e44ed2fd64e407805ba42df10fc7bf +8ad456f6ff8cd58bd57567d931f923d0c99141978511b17e03cab7390a72b9f62498b2893e1b05c7c22dd274e9a31919 +ac75399e999effe564672db426faa17a839e57c5ef735985c70cd559a377adec23928382767b55ed5a52f7b11b54b756 +b17f975a00b817299ac7af5f2024ea820351805df58b43724393bfb3920a8cd747a3bbd4b8286e795521489db3657168 +a2bed800a6d95501674d9ee866e7314063407231491d794f8cf57d5be020452729c1c7cefd8c50dc1540181f5caab248 +9743f5473171271ffdd3cc59a3ae50545901a7b45cd4bc3570db487865f3b73c0595bebabbfe79268809ee1862e86e4a +b7eab77c2d4687b60d9d7b04e842b3880c7940140012583898d39fcc22d9b9b0a9be2c2e3788b3e6f30319b39c338f09 +8e2b8f797a436a1b661140e9569dcf3e1eea0a77c7ff2bc4ff0f3e49af04ed2de95e255df8765f1d0927fb456a9926b1 +8aefea201d4a1f4ff98ffce94e540bb313f2d4dfe7e9db484a41f13fc316ed02b282e1acc9bc6f56cad2dc2e393a44c9 +b950c17c0e5ca6607d182144aa7556bb0efe24c68f06d79d6413a973b493bfdf04fd147a4f1ab03033a32004cc3ea66f +b7b8dcbb179a07165f2dc6aa829fad09f582a71b05c3e3ea0396bf9e6fe73076f47035c031c2101e8e38e0d597eadd30 +a9d77ed89c77ec1bf8335d08d41c3c94dcca9fd1c54f22837b4e54506b212aa38d7440126c80648ab7723ff18e65ed72 +a819d6dfd4aef70e52b8402fe5d135f8082d40eb7d3bb5c4d7997395b621e2bb10682a1bad2c9caa33dd818550fc3ec6 +8f6ee34128fac8bbf13ce2d68b2bb363eb4fd65b297075f88e1446ddeac242500eeb4ef0735e105882ff5ba8c44c139b +b4440e48255c1644bcecf3a1e9958f1ec4901cb5b1122ee5b56ffd02cad1c29c4266999dbb85aa2605c1b125490074d4 +a43304a067bede5f347775d5811cf65a6380a8d552a652a0063580b5c5ef12a0867a39c7912fa219e184f4538eba1251 +a891ad67a790089ffc9f6d53e6a3d63d3556f5f693e0cd8a7d0131db06fd4520e719cfcc3934f0a8f62a95f90840f1d4 +aea6df8e9bb871081aa0fc5a9bafb00be7d54012c5baf653791907d5042a326aeee966fd9012a582cc16695f5baf7042 +8ffa2660dc52ed1cd4eff67d6a84a8404f358a5f713d04328922269bee1e75e9d49afeec0c8ad751620f22352a438e25 +87ec6108e2d63b06abed350f8b363b7489d642486f879a6c3aa90e5b0f335efc2ff2834eef9353951a42136f8e6a1b32 +865619436076c2760d9e87ddc905023c6de0a8d56eef12c98a98c87837f2ca3f27fd26a2ad752252dbcbe2b9f1d5a032 +980437dce55964293cb315c650c5586ffd97e7a944a83f6618af31c9d92c37b53ca7a21bb5bc557c151b9a9e217e7098 +95d128fc369df4ad8316b72aea0ca363cbc7b0620d6d7bb18f7076a8717a6a46956ff140948b0cc4f6d2ce33b5c10054 +8c7212d4a67b9ec70ebbca04358ad2d36494618d2859609163526d7b3acc2fc935ca98519380f55e6550f70a9bc76862 +893a2968819401bf355e85eee0f0ed0406a6d4a7d7f172d0017420f71e00bb0ba984f6020999a3cdf874d3cd8ebcd371 +9103c1af82dece25d87274e89ea0acd7e68c2921c4af3d8d7c82ab0ed9990a5811231b5b06113e7fa43a6bd492b4564f +99cfd87a94eab7d35466caa4ed7d7bb45e5c932b2ec094258fb14bf205659f83c209b83b2f2c9ccb175974b2a33e7746 +874b6b93e4ee61be3f00c32dd84c897ccd6855c4b6251eb0953b4023634490ed17753cd3223472873cbc6095b2945075 +84a32c0dc4ea60d33aac3e03e70d6d639cc9c4cc435c539eff915017be3b7bdaba33349562a87746291ebe9bc5671f24 +a7057b24208928ad67914e653f5ac1792c417f413d9176ba635502c3f9c688f7e2ee81800d7e3dc0a340c464da2fd9c5 +a03fb9ed8286aacfa69fbd5d953bec591c2ae4153400983d5dbb6cd9ea37fff46ca9e5cceb9d117f73e9992a6c055ad2 +863b2de04e89936c9a4a2b40380f42f20aefbae18d03750fd816c658aee9c4a03df7b12121f795c85d01f415baaeaa59 +8526eb9bd31790fe8292360d7a4c3eed23be23dd6b8b8f01d2309dbfdc0cfd33ad1568ddd7f8a610f3f85a9dfafc6a92 +b46ab8c5091a493d6d4d60490c40aa27950574a338ea5bbc045be3a114af87bdcb160a8c80435a9b7ad815f3cb56a3f3 +aeadc47b41a8d8b4176629557646202f868b1d728b2dda58a347d937e7ffc8303f20d26d6c00b34c851b8aeec547885d +aebb19fc424d72c1f1822aa7adc744cd0ef7e55727186f8df8771c784925058c248406ebeeaf3c1a9ee005a26e9a10c6 +8ff96e81c1a4a2ab1b4476c21018fae0a67e92129ee36120cae8699f2d7e57e891f5c624902cb1b845b944926a605cc3 +8251b8d2c43fadcaa049a9e7aff838dae4fb32884018d58d46403ac5f3beb5c518bfd45f03b8abb710369186075eb71c +a8b2a64f865f51a5e5e86a66455c093407933d9d255d6b61e1fd81ffafc9538d73caaf342338a66ba8ee166372a3d105 +aad915f31c6ba7fdc04e2aaac62e84ef434b7ee76a325f07dc430d12c84081999720181067b87d792efd0117d7ee1eab +a13db3bb60389883fd41d565c54fb5180d9c47ce2fe7a169ae96e01d17495f7f4fa928d7e556e7c74319c4c25d653eb2 +a4491b0198459b3f552855d680a59214eb74e6a4d6c5fa3b309887dc50ebea2ecf6d26c040550f7dc478b452481466fb +8f017f13d4b1e3f0c087843582b52d5f8d13240912254d826dd11f8703a99a2f3166dfbdfdffd9a3492979d77524276b +96c3d5dcd032660d50d7cd9db2914f117240a63439966162b10c8f1f3cf74bc83b0f15451a43b31dbd85e4a7ce0e4bb1 +b479ec4bb79573d32e0ec93b92bdd7ec8c26ddb5a2d3865e7d4209d119fd3499eaac527615ffac78c440e60ef3867ae0 +b2c49c4a33aa94b52b6410b599e81ff15490aafa7e43c8031c865a84e4676354a9c81eb4e7b8be6825fdcefd1e317d44 +906dc51d6a90c089b6704b47592805578a6eed106608eeb276832f127e1b8e858b72e448edcbefb497d152447e0e68ff +b0e81c63b764d7dfbe3f3fddc9905aef50f3633e5d6a4af6b340495124abedcff5700dfd1577bbbed7b6bf97d02719cb +9304c64701e3b4ed6d146e48a881f7d83a17f58357cca0c073b2bb593afd2d94f6e2a7a1ec511d0a67ad6ff4c3be5937 +b6fdbd12ba05aa598d80b83f70a15ef90e5cba7e6e75fa038540ee741b644cd1f408a6cecfd2a891ef8d902de586c6b5 +b80557871a6521b1b3c74a1ba083ae055b575df607f1f7b04c867ba8c8c181ea68f8d90be6031f4d25002cca27c44da2 +aa7285b8e9712e06b091f64163f1266926a36607f9d624af9996856ed2aaf03a580cb22ce407d1ade436c28b44ca173f +8148d72b975238b51e6ea389e5486940d22641b48637d7dfadfa603a605bfc6d74a016480023945d0b85935e396aea5d +8a014933a6aea2684b5762af43dcf4bdbb633cd0428d42d71167a2b6fc563ece5e618bff22f1db2ddb69b845b9a2db19 +990d91740041db770d0e0eb9d9d97d826f09fd354b91c41e0716c29f8420e0e8aac0d575231efba12fe831091ec38d5a +9454d0d32e7e308ddec57cf2522fb1b67a2706e33fb3895e9e1f18284129ab4f4c0b7e51af25681d248d7832c05eb698 +a5bd434e75bac105cb3e329665a35bce6a12f71dd90c15165777d64d4c13a82bceedb9b48e762bd24034e0fc9fbe45f4 +b09e3b95e41800d4dc29c6ffdaab2cd611a0050347f6414f154a47ee20ee59bf8cf7181454169d479ebce1eb5c777c46 +b193e341d6a047d15eea33766d656d807b89393665a783a316e9ba10518e5515c8e0ade3d6e15641d917a8a172a5a635 +ade435ec0671b3621dde69e07ead596014f6e1daa1152707a8c18877a8b067bde2895dd47444ffa69db2bbef1f1d8816 +a7fd3d6d87522dfc56fb47aef9ce781a1597c56a8bbfd796baba907afdc872f753d732bfda1d3402aee6c4e0c189f52d +a298cb4f4218d0464b2fab393e512bbc477c3225aa449743299b2c3572f065bc3a42d07e29546167ed9e1b6b3b3a3af3 +a9ee57540e1fd9c27f4f0430d194b91401d0c642456c18527127d1f95e2dba41c2c86d1990432eb38a692fda058fafde +81d6c1a5f93c04e6d8e5a7e0678c1fc89a1c47a5c920bcd36180125c49fcf7c114866b90e90a165823560b19898a7c16 +a4b7a1ec9e93c899b9fd9aaf264c50e42c36c0788d68296a471f7a3447af4dbc81e4fa96070139941564083ec5b5b5a1 +b3364e327d381f46940c0e11e29f9d994efc6978bf37a32586636c0070b03e4e23d00650c1440f448809e1018ef9f6d8 +8056e0913a60155348300e3a62e28b5e30629a90f7dd4fe11289097076708110a1d70f7855601782a3cdc5bdb1ca9626 +b4980fd3ea17bac0ba9ee1c470b17e575bb52e83ebdd7d40c93f4f87bebeaff1c8a679f9d3d09d635f068d37d5bd28bd +905a9299e7e1853648e398901dfcd437aa575c826551f83520df62984f5679cb5f0ea86aa45ed3e18b67ddc0dfafe809 +ab99553bf31a84f2e0264eb34a08e13d8d15e2484aa9352354becf9a15999c76cc568d68274b70a65e49703fc23540d0 +a43681597bc574d2dae8964c9a8dc1a07613d7a1272bdcb818d98c85d44e16d744250c33f3b5e4d552d97396b55e601f +a54e5a31716fccb50245898c99865644405b8dc920ded7a11f3d19bdc255996054b268e16f2e40273f11480e7145f41e +8134f3ad5ef2ad4ba12a8a4e4d8508d91394d2bcdc38b7c8c8c0b0a820357ac9f79d286c65220f471eb1adca1d98fc68 +94e2f755e60471578ab2c1adb9e9cea28d4eec9b0e92e0140770bca7002c365fcabfe1e5fb4fe6cfe79a0413712aa3ef +ad48f8d0ce7eb3cc6e2a3086ad96f562e5bed98a360721492ae2e74dc158586e77ec8c35d5fd5927376301b7741bad2b +8614f0630bdd7fbad3a31f55afd9789f1c605dc85e7dc67e2edfd77f5105f878bb79beded6e9f0b109e38ea7da67e8d5 +9804c284c4c5e77dabb73f655b12181534ca877c3e1e134aa3f47c23b7ec92277db34d2b0a5d38d2b69e5d1c3008a3e3 +a51b99c3088e473afdaa9e0a9f7e75a373530d3b04e44e1148da0726b95e9f5f0c7e571b2da000310817c36f84b19f7f +ac4ff909933b3b76c726b0a382157cdc74ab851a1ac6cef76953c6444441804cc43abb883363f416592e8f6cfbc4550b +ae7d915eb9fc928b65a29d6edbc75682d08584d0014f7bcf17d59118421ae07d26a02137d1e4de6938bcd1ab8ef48fad +852f7e453b1af89b754df6d11a40d5d41ea057376e8ecacd705aacd2f917457f4a093d6b9a8801837fa0f62986ad7149 +92c6bf5ada5d0c3d4dd8058483de36c215fa98edab9d75242f3eff9db07c734ad67337da6f0eefe23a487bf75a600dee +a2b42c09d0db615853763552a48d2e704542bbd786aae016eb58acbf6c0226c844f5fb31e428cb6450b9db855f8f2a6f +880cc07968266dbfdcfbc21815cd69e0eddfee239167ac693fb0413912d816f2578a74f7716eecd6deefa68c6eccd394 +b885b3ace736cd373e8098bf75ba66fa1c6943ca1bc4408cd98ac7074775c4478594f91154b8a743d9c697e1b29f5840 +a51ce78de512bd87bfa0835de819941dffbf18bec23221b61d8096fc9436af64e0693c335b54e7bfc763f287bdca2db6 +a3c76166a3bdb9b06ef696e57603b58871bc72883ee9d45171a30fe6e1d50e30bc9c51b4a0f5a7270e19a77b89733850 +acefc5c6f8a1e7c24d7b41e0fc7f6f3dc0ede6cf3115ffb9a6e54b1d954cbca9bda8ad7a084be9be245a1b8e9770d141 +b420ed079941842510e31cfad117fa11fb6b4f97dfbc6298cb840f27ebaceba23eeaf3f513bcffbf5e4aae946310182d +95c3bb5ef26c5ed2f035aa5d389c6b3c15a6705b9818a3fefaed28922158b35642b2e8e5a1a620fdad07e75ad4b43af4 +825149f9081ecf07a2a4e3e8b5d21bade86c1a882475d51c55ee909330b70c5a2ac63771c8600c6f38df716af61a3ea1 +873b935aae16d9f08adbc25353cee18af2f1b8d5f26dec6538d6bbddc515f2217ed7d235dcfea59ae61b428798b28637 +9294150843a2bedcedb3bb74c43eb28e759cf9499582c5430bccefb574a8ddd4f11f9929257ff4c153990f9970a2558f +b619563a811cc531da07f4f04e5c4c6423010ff9f8ed7e6ec9449162e3d501b269fb1c564c09c0429431879b0f45df02 +91b509b87eb09f007d839627514658c7341bc76d468920fe8a740a8cb96a7e7e631e0ea584a7e3dc1172266f641d0f5c +8b8aceace9a7b9b4317f1f01308c3904d7663856946afbcea141a1c615e21ccad06b71217413e832166e9dd915fbe098 +87b3b36e725833ea0b0f54753c3728c0dbc87c52d44d705ffc709f2d2394414c652d3283bab28dcce09799504996cee0 +b2670aad5691cbf308e4a6a77a075c4422e6cbe86fdba24e9f84a313e90b0696afb6a067eebb42ba2d10340d6a2f6e51 +876784a9aff3d54faa89b2bacd3ff5862f70195d0b2edc58e8d1068b3c9074c0da1cfa23671fe12f35e33b8a329c0ccd +8b48b9e758e8a8eae182f5cbec96f67d20cca6d3eee80a2d09208eb1d5d872e09ef23d0df8ebbb9b01c7449d0e3e3650 +b79303453100654c04a487bdcadc9e3578bc80930c489a7069a52e8ca1dba36c492c8c899ce025f8364599899baa287d +961b35a6111da54ece6494f24dacd5ea46181f55775b5f03df0e370c34a5046ac2b4082925855325bb42bc2a2c98381d +a31feb1be3f5a0247a1f7d487987eb622e34fca817832904c6ee3ee60277e5847945a6f6ea1ac24542c72e47bdf647df +a12a2aa3e7327e457e1aae30e9612715dd2cfed32892c1cd6dcda4e9a18203af8a44afb46d03b2eed89f6b9c5a2c0c23 +a08265a838e69a2ca2f80fead6ccf16f6366415b920c0b22ee359bcd8d4464ecf156f400a16a7918d52e6d733dd64211 +b723d6344e938d801cca1a00032af200e541d4471fd6cbd38fb9130daa83f6a1dffbbe7e67fc20f9577f884acd7594b2 +a6733d83ec78ba98e72ddd1e7ff79b7adb0e559e256760d0c590a986e742445e8cdf560d44b29439c26d87edd0b07c8c +a61c2c27d3f7b9ff4695a17afedf63818d4bfba390507e1f4d0d806ce8778d9418784430ce3d4199fd3bdbc2504d2af3 +8332f3b63a6dc985376e8b1b25eeae68be6160fbe40053ba7bcf6f073204f682da72321786e422d3482fd60c9e5aa034 +a280f44877583fbb6b860d500b1a3f572e3ee833ec8f06476b3d8002058e25964062feaa1e5bec1536d734a5cfa09145 +a4026a52d277fcea512440d2204f53047718ebfcae7b48ac57ea7f6bfbc5de9d7304db9a9a6cbb273612281049ddaec5 +95cdf69c831ab2fad6c2535ede9c07e663d2ddccc936b64e0843d2df2a7b1c31f1759c3c20f1e7a57b1c8f0dbb21b540 +95c96cec88806469c277ab567863c5209027cecc06c7012358e5f555689c0d9a5ffb219a464f086b45817e8536b86d2f +afe38d4684132a0f03d806a4c8df556bf589b25271fbc6fe2e1ed16de7962b341c5003755da758d0959d2e6499b06c68 +a9b77784fda64987f97c3a23c5e8f61b918be0f7c59ba285084116d60465c4a2aaafc8857eb16823282cc83143eb9126 +a830f05881ad3ce532a55685877f529d32a5dbe56cea57ffad52c4128ee0fad0eeaf0da4362b55075e77eda7babe70e5 +992b3ad190d6578033c13ed5abfee4ef49cbc492babb90061e3c51ee4b5790cdd4c8fc1abff1fa2c00183b6b64f0bbbe +b1015424d9364aeff75de191652dc66484fdbec3e98199a9eb9671ec57bec6a13ff4b38446e28e4d8aedb58dd619cd90 +a745304604075d60c9db36cada4063ac7558e7ec2835d7da8485e58d8422e817457b8da069f56511b02601289fbb8981 +a5ba4330bc5cb3dbe0486ddf995632a7260a46180a08f42ae51a2e47778142132463cc9f10021a9ad36986108fefa1a9 +b419e9fd4babcaf8180d5479db188bb3da232ae77a1c4ed65687c306e6262f8083070a9ac32220cddb3af2ec73114092 +a49e23dc5f3468f3bf3a0bb7e4a114a788b951ff6f23a3396ae9e12cbff0abd1240878a3d1892105413dbc38818e807c +b7ecc7b4831f650202987e85b86bc0053f40d983f252e9832ef503aea81c51221ce93279da4aa7466c026b2d2070e55d +96a8c35cb87f84fa84dcd6399cc2a0fd79cc9158ef4bdde4bae31a129616c8a9f2576cd19baa3f497ca34060979aed7d +8681b2c00aa62c2b519f664a95dcb8faef601a3b961bb4ce5d85a75030f40965e2983871d41ea394aee934e859581548 +85c229a07efa54a713d0790963a392400f55fbb1a43995a535dc6c929f20d6a65cf4efb434e0ad1cb61f689b8011a3bc +90856f7f3444e5ad44651c28e24cc085a5db4d2ffe79aa53228c26718cf53a6e44615f3c5cda5aa752d5f762c4623c66 +978999b7d8aa3f28a04076f74d11c41ef9c89fdfe514936c4238e0f13c38ec97e51a5c078ebc6409e517bfe7ccb42630 +a099914dd7ed934d8e0d363a648e9038eb7c1ec03fa04dbcaa40f7721c618c3ef947afef7a16b4d7ac8c12aa46637f03 +ab2a104fed3c83d16f2cda06878fa5f30c8c9411de71bfb67fd2fc9aa454dcbcf3d299d72f8cc12e919466a50fcf7426 +a4471d111db4418f56915689482f6144efc4664cfb0311727f36c864648d35734351becc48875df96f4abd3cfcf820f9 +83be11727cd30ea94ccc8fa31b09b81c9d6a9a5d3a4686af9da99587332fe78c1f94282f9755854bafd6033549afec91 +88020ff971dc1a01a9e993cd50a5d2131ffdcbb990c1a6aaa54b20d8f23f9546a70918ea57a21530dcc440c1509c24ad +ae24547623465e87905eaffa1fa5d52bb7c453a8dbd89614fa8819a2abcedaf455c2345099b7324ae36eb0ad7c8ef977 +b59b0c60997de1ee00b7c388bc7101d136c9803bf5437b1d589ba57c213f4f835a3e4125b54738e78abbc21b000f2016 +a584c434dfe194546526691b68fa968c831c31da42303a1d735d960901c74011d522246f37f299555416b8cf25c5a548 +80408ce3724f4837d4d52376d255e10f69eb8558399ae5ca6c11b78b98fe67d4b93157d2b9b639f1b5b64198bfe87713 +abb941e8d406c2606e0ddc35c113604fdd9d249eacc51cb64e2991e551b8639ce44d288cc92afa7a1e7fc599cfc84b22 +b223173f560cacb1c21dba0f1713839e348ad02cbfdef0626748604c86f89e0f4c919ed40b583343795bdd519ba952c8 +af1c70512ec3a19d98b8a1fc3ff7f7f5048a27d17d438d43f561974bbdd116fcd5d5c21040f3447af3f0266848d47a15 +8a44809568ebe50405bede19b4d2607199159b26a1b33e03d180e6840c5cf59d991a4fb150d111443235d75ecad085b7 +b06207cdca46b125a27b3221b5b50cf27af4c527dd7c80e2dbcebbb09778a96df3af67e50f07725239ce3583dad60660 +993352d9278814ec89b26a11c4a7c4941bf8f0e6781ae79559d14749ee5def672259792db4587f85f0100c7bb812f933 +9180b8a718b971fd27bc82c8582d19c4b4f012453e8c0ffeeeffe745581fc6c07875ab28be3af3fa3896d19f0c89ac5b +8b8e1263eb48d0fe304032dd5ea1f30e73f0121265f7458ba9054d3626894e8a5fef665340abd2ede9653045c2665938 +99a2beee4a10b7941c24b2092192faf52b819afd033e4a2de050fd6c7f56d364d0cf5f99764c3357cf32399e60fc5d74 +946a4aad7f8647ea60bee2c5fcdeb6f9a58fb2cfca70c4d10e458027a04846e13798c66506151be3df9454b1e417893f +a672a88847652d260b5472d6908d1d57e200f1e492d30dd1cecc441cdfc9b76e016d9bab560efd4d7f3c30801de884a9 +9414e1959c156cde1eb24e628395744db75fc24b9df4595350aaad0bc38e0246c9b4148f6443ef68b8e253a4a6bcf11c +9316e9e4ec5fab4f80d6540df0e3a4774db52f1d759d2e5b5bcd3d7b53597bb007eb1887cb7dc61f62497d51ffc8d996 +902d6d77bb49492c7a00bc4b70277bc28c8bf9888f4307bb017ac75a962decdedf3a4e2cf6c1ea9f9ba551f4610cbbd7 +b07025a18b0e32dd5e12ec6a85781aa3554329ea12c4cd0d3b2c22e43d777ef6f89876dd90a9c8fb097ddf61cf18adc5 +b355a849ad3227caa4476759137e813505ec523cbc2d4105bc7148a4630f9e81918d110479a2d5f5e4cd9ccec9d9d3e3 +b49532cfdf02ee760109881ad030b89c48ee3bb7f219ccafc13c93aead754d29bdafe345be54c482e9d5672bd4505080 +9477802410e263e4f938d57fa8f2a6cac7754c5d38505b73ee35ea3f057aad958cb9722ba6b7b3cfc4524e9ca93f9cdc +9148ea83b4436339580f3dbc9ba51509e9ab13c03063587a57e125432dd0915f5d2a8f456a68f8fff57d5f08c8f34d6e +b00b6b5392b1930b54352c02b1b3b4f6186d20bf21698689bbfc7d13e86538a4397b90e9d5c93fd2054640c4dbe52a4f +926a9702500441243cd446e7cbf15dde16400259726794694b1d9a40263a9fc9e12f7bcbf12a27cb9aaba9e2d5848ddc +a0c6155f42686cbe7684a1dc327100962e13bafcf3db97971fc116d9f5c0c8355377e3d70979cdbd58fd3ea52440901c +a277f899f99edb8791889d0817ea6a96c24a61acfda3ad8c3379e7c62b9d4facc4b965020b588651672fd261a77f1bfc +8f528cebb866b501f91afa50e995234bef5bf20bff13005de99cb51eaac7b4f0bf38580cfd0470de40f577ead5d9ba0f +963fc03a44e9d502cc1d23250efef44d299befd03b898d07ce63ca607bb474b5cf7c965a7b9b0f32198b04a8393821f7 +ab087438d0a51078c378bf4a93bd48ef933ff0f1fa68d02d4460820df564e6642a663b5e50a5fe509527d55cb510ae04 +b0592e1f2c54746bb076be0fa480e1c4bebc4225e1236bcda3b299aa3853e3afb401233bdbcfc4a007b0523a720fbf62 +851613517966de76c1c55a94dc4595f299398a9808f2d2f0a84330ba657ab1f357701d0895f658c18a44cb00547f6f57 +a2fe9a1dd251e72b0fe4db27be508bb55208f8f1616b13d8be288363ec722826b1a1fd729fc561c3369bf13950bf1fd6 +b896cb2bc2d0c77739853bc59b0f89b2e008ba1f701c9cbe3bef035f499e1baee8f0ff1e794854a48c320586a2dfc81a +a1b60f98e5e5106785a9b81a85423452ee9ef980fa7fa8464f4366e73f89c50435a0c37b2906052b8e58e212ebd366cf +a853b0ebd9609656636df2e6acd5d8839c0fda56f7bf9288a943b06f0b67901a32b95e016ca8bc99bd7b5eab31347e72 +b290fa4c1346963bd5225235e6bdf7c542174dab4c908ab483d1745b9b3a6015525e398e1761c90e4b49968d05e30eea +b0f65a33ad18f154f1351f07879a183ad62e5144ad9f3241c2d06533dad09cbb2253949daff1bb02d24d16a3569f7ef0 +a00db59b8d4218faf5aeafcd39231027324408f208ec1f54d55a1c41228b463b88304d909d16b718cfc784213917b71e +b8d695dd33dc2c3bc73d98248c535b2770ad7fa31aa726f0aa4b3299efb0295ba9b4a51c71d314a4a1bd5872307534d1 +b848057cca2ca837ee49c42b88422303e58ea7d2fc76535260eb5bd609255e430514e927cc188324faa8e657396d63ec +92677836061364685c2aaf0313fa32322746074ed5666fd5f142a7e8f87135f45cd10e78a17557a4067a51dfde890371 +a854b22c9056a3a24ab164a53e5c5cf388616c33e67d8ebb4590cb16b2e7d88b54b1393c93760d154208b5ca822dc68f +86fff174920388bfab841118fb076b2b0cdec3fdb6c3d9a476262f82689fb0ed3f1897f7be9dbf0932bb14d346815c63 +99661cf4c94a74e182752bcc4b98a8c2218a8f2765642025048e12e88ba776f14f7be73a2d79bd21a61def757f47f904 +8a8893144d771dca28760cba0f950a5d634195fd401ec8cf1145146286caffb0b1a6ba0c4c1828d0a5480ce49073c64c +938a59ae761359ee2688571e7b7d54692848eb5dde57ffc572b473001ea199786886f8c6346a226209484afb61d2e526 +923f68a6aa6616714cf077cf548aeb845bfdd78f2f6851d8148cba9e33a374017f2f3da186c39b82d14785a093313222 +ac923a93d7da7013e73ce8b4a2b14b8fd0cc93dc29d5de941a70285bdd19be4740fedfe0c56b046689252a3696e9c5bc +b49b32c76d4ec1a2c68d4989285a920a805993bc6fcce6dacd3d2ddae73373050a5c44ba8422a3781050682fa0ef6ba2 +8a367941c07c3bdca5712524a1411bad7945c7c48ffc7103b1d4dff2c25751b0624219d1ccde8c3f70c465f954be5445 +b838f029df455efb6c530d0e370bbbf7d87d61a9aea3d2fe5474c5fe0a39cf235ceecf9693c5c6c5820b1ba8f820bd31 +a8983b7c715eaac7f13a001d2abc462dfc1559dab4a6b554119c271aa8fe00ffcf6b6949a1121f324d6d26cb877bcbae +a2afb24ad95a6f14a6796315fbe0d8d7700d08f0cfaf7a2abe841f5f18d4fecf094406cbd54da7232a159f9c5b6e805e +87e8e95ad2d62f947b2766ff405a23f7a8afba14e7f718a691d95369c79955cdebe24c54662553c60a3f55e6322c0f6f +87c2cbcecb754e0cc96128e707e5c5005c9de07ffd899efa3437cadc23362f5a1d3fcdd30a1f5bdc72af3fb594398c2a +91afd6ee04f0496dc633db88b9370d41c428b04fd991002502da2e9a0ef051bcd7b760e860829a44fbe5539fa65f8525 +8c50e5d1a24515a9dd624fe08b12223a75ca55196f769f24748686315329b337efadca1c63f88bee0ac292dd0a587440 +8a07e8f912a38d94309f317c32068e87f68f51bdfa082d96026f5f5f8a2211621f8a3856dda8069386bf15fb2d28c18f +94ad1dbe341c44eeaf4dc133eed47d8dbfe752575e836c075745770a6679ff1f0e7883b6aa917462993a7f469d74cab5 +8745f8bd86c2bb30efa7efb7725489f2654f3e1ac4ea95bd7ad0f3cfa223055d06c187a16192d9d7bdaea7b050c6a324 +900d149c8d79418cda5955974c450a70845e02e5a4ecbcc584a3ca64d237df73987c303e3eeb79da1af83bf62d9e579f +8f652ab565f677fb1a7ba03b08004e3cda06b86c6f1b0b9ab932e0834acf1370abb2914c15b0d08327b5504e5990681c +9103097d088be1f75ab9d3da879106c2f597e2cc91ec31e73430647bdd5c33bcfd771530d5521e7e14df6acda44f38a6 +b0fec7791cfb0f96e60601e1aeced9a92446b61fedab832539d1d1037558612d78419efa87ff5f6b7aab8fd697d4d9de +b9d2945bdb188b98958854ba287eb0480ef614199c4235ce5f15fc670b8c5ffe8eeb120c09c53ea8a543a022e6a321ac +a9461bb7d5490973ebaa51afc0bb4a5e42acdccb80e2f939e88b77ac28a98870e103e1042899750f8667a8cc9123bae9 +a37fdf11d4bcb2aed74b9f460a30aa34afea93386fa4cdb690f0a71bc58f0b8df60bec56e7a24f225978b862626fa00e +a214420e183e03d531cf91661466ea2187d84b6e814b8b20b3730a9400a7d25cf23181bb85589ebc982cec414f5c2923 +ad09a45a698a6beb3e0915f540ef16e9af7087f53328972532d6b5dfe98ce4020555ece65c6cbad8bd6be8a4dfefe6fd +ab6742800b02728c92d806976764cb027413d6f86edd08ad8bb5922a2969ee9836878cd39db70db0bd9a2646862acc4f +974ca9305bd5ea1dc1755dff3b63e8bfe9f744321046c1395659bcea2a987b528e64d5aa96ac7b015650b2253b37888d +84eee9d6bce039c52c2ebc4fccc0ad70e20c82f47c558098da4be2f386a493cbc76adc795b5488c8d11b6518c2c4fab8 +875d7bda46efcb63944e1ccf760a20144df3b00d53282b781e95f12bfc8f8316dfe6492c2efbf796f1150e36e436e9df +b68a2208e0c587b5c31b5f6cb32d3e6058a9642e2d9855da4f85566e1412db528475892060bb932c55b3a80877ad7b4a +ba006368ecab5febb6ab348644d9b63de202293085ed468df8bc24d992ae8ce468470aa37f36a73630c789fb9c819b30 +90a196035150846cd2b482c7b17027471372a8ce7d914c4d82b6ea7fa705d8ed5817bd42d63886242585baf7d1397a1c +a223b4c85e0daa8434b015fd9170b5561fe676664b67064974a1e9325066ecf88fc81f97ab5011c59fad28cedd04b240 +82e8ec43139cf15c6bbeed484b62e06cded8a39b5ce0389e4cbe9c9e9c02f2f0275d8d8d4e8dfec8f69a191bef220408 +81a3fc07a7b68d92c6ee4b6d28f5653ee9ec85f7e2ee1c51c075c1b130a8c5097dc661cf10c5aff1c7114b1a6a19f11a +8ed2ef8331546d98819a5dd0e6c9f8cb2630d0847671314a28f277faf68da080b53891dd75c82cbcf7788b255490785d +acecabf84a6f9bbed6b2fc2e7e4b48f02ef2f15e597538a73aea8f98addc6badda15e4695a67ecdb505c1554e8f345ec +b8f51019b2aa575f8476e03dcadf86cc8391f007e5f922c2a36b2daa63f5a503646a468990cd5c65148d323942193051 +aaa595a84b403ec65729bc1c8055a94f874bf9adddc6c507b3e1f24f79d3ad359595a672b93aab3394db4e2d4a7d8970 +895144c55fcbd0f64d7dd69e6855cfb956e02b5658eadf0f026a70703f3643037268fdd673b0d21b288578a83c6338dd +a2e92ae6d0d237d1274259a8f99d4ea4912a299816350b876fba5ebc60b714490e198a916e1c38c6e020a792496fa23c +a45795fda3b5bb0ad1d3c628f6add5b2a4473a1414c1a232e80e70d1cfffd7f8a8d9861f8df2946999d7dbb56bf60113 +b6659bf7f6f2fef61c39923e8c23b8c70e9c903028d8f62516d16755cd3fba2fe41c285aa9432dc75ab08f8a1d8a81fc +a735609a6bc5bfd85e58234fc439ff1f58f1ff1dd966c5921d8b649e21f006bf2b8642ad8a75063c159aaf6935789293 +a3c622eb387c9d15e7bda2e3e84d007cb13a6d50d655c3f2f289758e49d3b37b9a35e4535d3cc53d8efd51f407281f19 +8afe147b53ad99220f5ef9d763bfc91f9c20caecbcf823564236fb0e6ede49414c57d71eec4772c8715cc65a81af0047 +b5f0203233cf71913951e9c9c4e10d9243e3e4a1f2cb235bf3f42009120ba96e04aa414c9938ea8873b63148478927e8 +93c52493361b458d196172d7ba982a90a4f79f03aa8008edc322950de3ce6acf4c3977807a2ffa9e924047e02072b229 +b9e72b805c8ac56503f4a86c82720afbd5c73654408a22a2ac0b2e5caccdfb0e20b59807433a6233bc97ae58cf14c70a +af0475779b5cee278cca14c82da2a9f9c8ef222eb885e8c50cca2315fea420de6e04146590ed0dd5a29c0e0812964df5 +b430ccab85690db02c2d0eb610f3197884ca12bc5f23c51e282bf3a6aa7e4a79222c3d8761454caf55d6c01a327595f9 +830032937418b26ee6da9b5206f3e24dc76acd98589e37937e963a8333e5430abd6ce3dd93ef4b8997bd41440eed75d6 +8820a6d73180f3fe255199f3f175c5eb770461ad5cfdde2fb11508041ed19b8c4ce66ad6ecebf7d7e836cc2318df47ca +aef1393e7d97278e77bbf52ef6e1c1d5db721ccf75fe753cf47a881fa034ca61eaa5098ee5a344c156d2b14ff9e284ad +8a4a26c07218948c1196c45d927ef4d2c42ade5e29fe7a91eaebe34a29900072ce5194cf28d51f746f4c4c649daf4396 +84011dc150b7177abdcb715efbd8c201f9cb39c36e6069af5c50a096021768ba40cef45b659c70915af209f904ede3b6 +b1bd90675411389bb66910b21a4bbb50edce5330850c5ab0b682393950124252766fc81f5ecfc72fb7184387238c402e +8dfdcd30583b696d2c7744655f79809f451a60c9ad5bf1226dc078b19f4585d7b3ef7fa9d54e1ac09520d95cbfd20928 +b351b4dc6d98f75b8e5a48eb7c6f6e4b78451991c9ba630e5a1b9874c15ac450cd409c1a024713bf2cf82dc400e025ef +a462b8bc97ac668b97b28b3ae24b9f5de60e098d7b23ecb600d2194cd35827fb79f77c3e50d358f5bd72ee83fef18fa0 +a183753265c5f7890270821880cce5f9b2965b115ba783c6dba9769536f57a04465d7da5049c7cf8b3fcf48146173c18 +a8a771b81ed0d09e0da4d79f990e58eabcd2be3a2680419502dd592783fe52f657fe55125b385c41d0ba3b9b9cf54a83 +a71ec577db46011689d073245e3b1c3222a9b1fe6aa5b83629adec5733dd48617ebea91346f0dd0e6cdaa86e4931b168 +a334b8b244f0d598a02da6ae0f918a7857a54dce928376c4c85df15f3b0f2ba3ac321296b8b7c9dd47d770daf16c8f8c +a29037f8ef925c417c90c4df4f9fb27fb977d04e2b3dd5e8547d33e92ab72e7a00f5461de21e28835319eae5db145eb7 +b91054108ae78b00e3298d667b913ebc44d8f26e531eae78a8fe26fdfb60271c97efb2dee5f47ef5a3c15c8228138927 +926c13efbe90604f6244be9315a34f72a1f8d1aab7572df431998949c378cddbf2fe393502c930fff614ff06ae98a0ce +995c758fd5600e6537089b1baa4fbe0376ab274ff3e82a17768b40df6f91c2e443411de9cafa1e65ea88fb8b87d504f4 +9245ba307a7a90847da75fca8d77ec03fdfc812c871e7a2529c56a0a79a6de16084258e7a9ac4ae8a3756f394336e21c +99e0cfa2bb57a7e624231317044c15e52196ecce020db567c8e8cb960354a0be9862ee0c128c60b44777e65ac315e59f +ad4f6b3d27bbbb744126601053c3dc98c07ff0eb0b38a898bd80dce778372846d67e5ab8fb34fb3ad0ef3f235d77ba7f +a0f12cae3722bbbca2e539eb9cc7614632a2aefe51410430070a12b5bc5314ecec5857b7ff8f41e9980cac23064f7c56 +b487f1bc59485848c98222fd3bc36c8c9bb3d2912e2911f4ceca32c840a7921477f9b1fe00877e05c96c75d3eecae061 +a6033db53925654e18ecb3ce715715c36165d7035db9397087ac3a0585e587998a53973d011ac6d48af439493029cee6 +a6b4d09cd01c70a3311fd131d3710ccf97bde3e7b80efd5a8c0eaeffeb48cca0f951ced905290267b115b06d46f2693b +a9dff1df0a8f4f218a98b6f818a693fb0d611fed0fc3143537cbd6578d479af13a653a8155e535548a2a0628ae24fa58 +a58e469f65d366b519f9a394cacb7edaddac214463b7b6d62c2dbc1316e11c6c5184ce45c16de2d77f990dcdd8b55430 +989e71734f8119103586dc9a3c5f5033ddc815a21018b34c1f876cdfc112efa868d5751bf6419323e4e59fa6a03ece1c +a2da00e05036c884369e04cf55f3de7d659cd5fa3f849092b2519dd263694efe0f051953d9d94b7e121f0aee8b6174d7 +968f3c029f57ee31c4e1adea89a7f92e28483af9a74f30fbdb995dc2d40e8e657dff8f8d340d4a92bf65f54440f2859f +932778df6f60ac1639c1453ef0cbd2bf67592759dcccb3e96dcc743ff01679e4c7dd0ef2b0833dda548d32cb4eba49e2 +a805a31139f8e0d6dae1ac87d454b23a3dc9fc653d4ca18d4f8ebab30fc189c16e73981c2cb7dd6f8c30454a5208109d +a9ba0991296caa2aaa4a1ceacfb205544c2a2ec97088eace1d84ee5e2767656a172f75d2f0c4e16a3640a0e0dec316e0 +b1e49055c968dced47ec95ae934cf45023836d180702e20e2df57e0f62fb85d7ac60d657ba3ae13b8560b67210449459 +a94e1da570a38809c71e37571066acabff7bf5632737c9ab6e4a32856924bf6211139ab3cedbf083850ff2d0e0c0fcfc +88ef1bb322000c5a5515b310c838c9af4c1cdbb32eab1c83ac3b2283191cd40e9573747d663763a28dad0d64adc13840 +a987ce205f923100df0fbd5a85f22c9b99b9b9cbe6ddfa8dfda1b8fe95b4f71ff01d6c5b64ca02eb24edb2b255a14ef0 +84fe8221a9e95d9178359918a108de4763ebfa7a6487facb9c963406882a08a9a93f492f8e77cf9e7ea41ae079c45993 +aa1cf3dc7c5dcfa15bbbc811a4bb6dbac4fba4f97fb1ed344ab60264d7051f6eef19ea9773441d89929ee942ed089319 +8f6a7d610d59d9f54689bbe6a41f92d9f6096cde919c1ab94c3c7fcecf0851423bc191e5612349e10f855121c0570f56 +b5af1fa7894428a53ea520f260f3dc3726da245026b6d5d240625380bfb9c7c186df0204bb604efac5e613a70af5106e +a5bce6055ff812e72ce105f147147c7d48d7a2313884dd1f488b1240ee320f13e8a33f5441953a8e7a3209f65b673ce1 +b9b55b4a1422677d95821e1d042ab81bbf0bf087496504021ec2e17e238c2ca6b44fb3b635a5c9eac0871a724b8d47c3 +941c38e533ce4a673a3830845b56786585e5fe49c427f2e5c279fc6db08530c8f91db3e6c7822ec6bb4f956940052d18 +a38e191d66c625f975313c7007bbe7431b5a06ed2da1290a7d5d0f2ec73770d476efd07b8e632de64597d47df175cbb0 +94ba76b667abf055621db4c4145d18743a368d951565632ed4e743dd50dd3333507c0c34f286a5c5fdbf38191a2255cd +a5ca38c60be5602f2bfa6e00c687ac96ac36d517145018ddbee6f12eb0faa63dd57909b9eeed26085fe5ac44e55d10ab +b00fea3b825e60c1ed1c5deb4b551aa65a340e5af36b17d5262c9cd2c508711e4dc50dc2521a2c16c7c901902266e64a +971b86fc4033485e235ccb0997a236206ba25c6859075edbcdf3c943116a5030b7f75ebca9753d863a522ba21a215a90 +b3b31f52370de246ee215400975b674f6da39b2f32514fe6bd54e747752eedca22bb840493b44a67df42a3639c5f901f +affbbfac9c1ba7cbfa1839d2ae271dd6149869b75790bf103230637da41857fc326ef3552ff31c15bda0694080198143 +a95d42aa7ef1962520845aa3688f2752d291926f7b0d73ea2ee24f0612c03b43f2b0fe3c9a9a99620ffc8d487b981bc2 +914a266065caf64985e8c5b1cb2e3f4e3fe94d7d085a1881b1fefa435afef4e1b39a98551d096a62e4f5cc1a7f0fdc2e +81a0b4a96e2b75bc1bf2dbd165d58d55cfd259000a35504d1ffb18bc346a3e6f07602c683723864ffb980f840836fd8d +91c1556631cddd4c00b65b67962b39e4a33429029d311c8acf73a18600e362304fb68bccb56fde40f49e95b7829e0b87 +8befbacc19e57f7c885d1b7a6028359eb3d80792fe13b92a8400df21ce48deb0bb60f2ddb50e3d74f39f85d7eab23adc +92f9458d674df6e990789690ec9ca73dacb67fc9255b58c417c555a8cc1208ace56e8e538f86ba0f3615573a0fbac00d +b4b1b3062512d6ae7417850c08c13f707d5838e43d48eb98dd4621baf62eee9e82348f80fe9b888a12874bfa538771f8 +a13c4a3ac642ede37d9c883f5319e748d2b938f708c9d779714108a449b343f7b71a6e3ef4080fee125b416762920273 +af44983d5fc8cceee0551ef934e6e653f2d3efa385e5c8a27a272463a6f333e290378cc307c2b664eb923c78994e706e +a389fd6c59fe2b4031cc244e22d3991e541bd203dd5b5e73a6159e72df1ab41d49994961500dcde7989e945213184778 +8d2141e4a17836c548de9598d7b298b03f0e6c73b7364979a411c464e0628e21cff6ac3d6decdba5d1c4909eff479761 +980b22ef53b7bdf188a3f14bc51b0dbfdf9c758826daa3cbc1e3986022406a8aa9a6a79e400567120b88c67faa35ce5f +a28882f0a055f96df3711de5d0aa69473e71245f4f3e9aa944e9d1fb166e02caa50832e46da6d3a03b4801735fd01b29 +8db106a37d7b88f5d995c126abb563934dd8de516af48e85695d02b1aea07f79217e3cdd03c6f5ca57421830186c772b +b5a7e50da0559a675c472f7dfaee456caab6695ab7870541b2be8c2b118c63752427184aad81f0e1afc61aef1f28c46f +9962118780e20fe291d10b64f28d09442a8e1b5cffd0f3dd68d980d0614050a626c616b44e9807fbee7accecae00686a +b38ddf33745e8d2ad6a991aefaf656a33c5f8cbe5d5b6b6fd03bd962153d8fd0e01b5f8f96d80ae53ab28d593ab1d4e7 +857dc12c0544ff2c0c703761d901aba636415dee45618aba2e3454ff9cbc634a85c8b05565e88520ff9be2d097c8b2b1 +a80d465c3f8cc63af6d74a6a5086b626c1cb4a8c0fee425964c3bd203d9d7094e299f81ce96d58afc20c8c9a029d9dae +89e1c8fbde8563763be483123a3ed702efac189c6d8ab4d16c85e74bbaf856048cc42d5d6e138633a38572ba5ec3f594 +893a594cf495535f6d216508f8d03c317dcf03446668cba688da90f52d0111ac83d76ad09bf5ea47056846585ee5c791 +aadbd8be0ae452f7f9450c7d2957598a20cbf10139a4023a78b4438172d62b18b0de39754dd2f8862dbd50a3a0815e53 +ae7d39670ecca3eb6db2095da2517a581b0e8853bdfef619b1fad9aacd443e7e6a40f18209fadd44038a55085c5fe8b2 +866ef241520eacb6331593cfcb206f7409d2f33d04542e6e52cba5447934e02d44c471f6c9a45963f9307e9809ab91d9 +b1a09911ad3864678f7be79a9c3c3eb5c84a0a45f8dcb52c67148f43439aeaaa9fd3ed3471276b7e588b49d6ebe3033a +add07b7f0dbb34049cd8feeb3c18da5944bf706871cfd9f14ff72f6c59ad217ebb1f0258b13b167851929387e4e34cfe +ae048892d5c328eefbdd4fba67d95901e3c14d974bfc0a1fc68155ca9f0d59e61d7ba17c6c9948b120cf35fd26e6fee9 +9185b4f3b7da0ddb4e0d0f09b8a9e0d6943a4611e43f13c3e2a767ed8592d31e0ba3ebe1914026a3627680274291f6e5 +a9c022d4e37b0802284ce3b7ee9258628ab4044f0db4de53d1c3efba9de19d15d65cc5e608dbe149c21c2af47d0b07b5 +b24dbd5852f8f24921a4e27013b6c3fa8885b973266cb839b9c388efad95821d5d746348179dcc07542bd0d0aefad1ce +b5fb4f279300876a539a27a441348764908bc0051ebd66dc51739807305e73db3d2f6f0f294ffb91b508ab150eaf8527 +ace50841e718265b290c3483ed4b0fdd1175338c5f1f7530ae9a0e75d5f80216f4de37536adcbc8d8c95982e88808cd0 +b19cadcde0f63bd1a9c24bd9c2806f53c14c0b9735bf351601498408ba503ddbd2037c891041cbba47f58b8c483f3b21 +b6061e63558d312eb891b97b39aa552fa218568d79ee26fe6dd5b864aea9e3216d8f2e2f3b093503be274766dac41426 +89730fdb2876ab6f0fe780d695f6e12090259027e789b819956d786e977518057e5d1d7f5ab24a3ae3d5d4c97773bd2b +b6fa841e81f9f2cad0163a02a63ae96dc341f7ae803b616efc6e1da2fbea551c1b96b11ad02c4afbdf6d0cc9f23da172 +8fb66187182629c861ddb6896d7ed3caf2ad050c3dba8ab8eb0d7a2c924c3d44c48d1a148f9e33fb1f061b86972f8d21 +86022ac339c1f84a7fa9e05358c1a5b316b4fc0b83dbe9c8c7225dc514f709d66490b539359b084ce776e301024345fa +b50b9c321468da950f01480bb62b6edafd42f83c0001d6e97f2bd523a1c49a0e8574fb66380ea28d23a7c4d54784f9f0 +a31c05f7032f30d1dac06678be64d0250a071fd655e557400e4a7f4c152be4d5c7aa32529baf3e5be7c4bd49820054f6 +b95ac0848cd322684772119f5b682d90a66bbf9dac411d9d86d2c34844bbd944dbaf8e47aa41380455abd51687931a78 +ae4a6a5ce9553b65a05f7935e61e496a4a0f6fd8203367a2c627394c9ce1e280750297b74cdc48fd1d9a31e93f97bef4 +a22daf35f6e9b05e52e0b07f7bd1dbbebd2c263033fb0e1b2c804e2d964e2f11bc0ece6aca6af079dd3a9939c9c80674 +902150e0cb1f16b9b59690db35281e28998ce275acb313900da8b2d8dfd29fa1795f8ca3ff820c31d0697de29df347c1 +b17b5104a5dc665cdd7d47e476153d715eb78c6e5199303e4b5445c21a7fa7cf85fe7cfd08d7570f4e84e579b005428c +a03f49b81c15433f121680aa02d734bb9e363af2156654a62bcb5b2ba2218398ccb0ff61104ea5d7df5b16ea18623b1e +802101abd5d3c88876e75a27ffc2f9ddcce75e6b24f23dba03e5201281a7bd5cc7530b6a003be92d225093ca17d3c3bb +a4d183f63c1b4521a6b52226fc19106158fc8ea402461a5cccdaa35fee93669df6a8661f45c1750cd01308149b7bf08e +8d17c22e0c8403b69736364d460b3014775c591032604413d20a5096a94d4030d7c50b9fe3240e31d0311efcf9816a47 +947225acfcce5992eab96276f668c3cbe5f298b90a59f2bb213be9997d8850919e8f496f182689b5cbd54084a7332482 +8df6f4ed216fc8d1905e06163ba1c90d336ab991a18564b0169623eb39b84e627fa267397da15d3ed754d1f3423bff07 +83480007a88f1a36dea464c32b849a3a999316044f12281e2e1c25f07d495f9b1710b4ba0d88e9560e72433addd50bc2 +b3019d6e591cf5b33eb972e49e06c6d0a82a73a75d78d383dd6f6a4269838289e6e07c245f54fed67f5c9bb0fd5e1c5f +92e8ce05e94927a9fb02debadb99cf30a26172b2705003a2c0c47b3d8002bf1060edb0f6a5750aad827c98a656b19199 +ac2aff801448dbbfc13cca7d603fd9c69e82100d997faf11f465323b97255504f10c0c77401e4d1890339d8b224f5803 +b0453d9903d08f508ee27e577445dc098baed6cde0ac984b42e0f0efed62760bd58d5816cf1e109d204607b7b175e30c +ae68dc4ba5067e825d46d2c7c67f1009ceb49d68e8d3e4c57f4bcd299eb2de3575d42ea45e8722f8f28497a6e14a1cfe +b22486c2f5b51d72335ce819bbafb7fa25eb1c28a378a658f13f9fc79cd20083a7e573248d911231b45a5cf23b561ca7 +89d1201d1dbd6921867341471488b4d2fd0fc773ae1d4d074c78ae2eb779a59b64c00452c2a0255826fca6b3d03be2b1 +a2998977c91c7a53dc6104f5bc0a5b675e5350f835e2f0af69825db8af4aeb68435bdbcc795f3dd1f55e1dd50bc0507f +b0be4937a925b3c05056ed621910d535ccabf5ab99fd3b9335080b0e51d9607d0fd36cb5781ff340018f6acfca4a9736 +aea145a0f6e0ba9df8e52e84bb9c9de2c2dc822f70d2724029b153eb68ee9c17de7d35063dcd6a39c37c59fdd12138f7 +91cb4545d7165ee8ffbc74c874baceca11fdebbc7387908d1a25877ca3c57f2c5def424dab24148826832f1e880bede0 +b3b579cb77573f19c571ad5eeeb21f65548d7dff9d298b8d7418c11f3e8cd3727c5b467f013cb87d6861cfaceee0d2e3 +b98a1eeec2b19fecc8378c876d73645aa52fb99e4819903735b2c7a885b242787a30d1269a04bfb8573d72d9bbc5f0f0 +940c1f01ed362bd588b950c27f8cc1d52276c71bb153d47f07ec85b038c11d9a8424b7904f424423e714454d5e80d1cd +aa343a8ecf09ce11599b8cf22f7279cf80f06dbf9f6d62cb05308dbbb39c46fd0a4a1240b032665fbb488a767379b91b +87c3ac72084aca5974599d3232e11d416348719e08443acaba2b328923af945031f86432e170dcdd103774ec92e988c9 +91d6486eb5e61d2b9a9e742c20ec974a47627c6096b3da56209c2b4e4757f007e793ebb63b2b246857c9839b64dc0233 +aebcd3257d295747dd6fc4ff910d839dd80c51c173ae59b8b2ec937747c2072fa85e3017f9060aa509af88dfc7529481 +b3075ba6668ca04eff19efbfa3356b92f0ab12632dcda99cf8c655f35b7928c304218e0f9799d68ef9f809a1492ff7db +93ba7468bb325639ec2abd4d55179c69fd04eaaf39fc5340709227bbaa4ad0a54ea8b480a1a3c8d44684e3be0f8d1980 +a6aef86c8c0d92839f38544d91b767c582568b391071228ff5a5a6b859c87bf4f81a7d926094a4ada1993ddbd677a920 +91dcd6d14207aa569194aa224d1e5037b999b69ade52843315ca61ba26abe9a76412c9e88259bc5cf5d7b95b97d9c3bc +b3b483d31c88f78d49bd065893bc1e3d2aa637e27dedb46d9a7d60be7660ce7a10aaaa7deead362284a52e6d14021178 +8e5730070acf8371461ef301cc4523e8e672aa0e3d945d438a0e0aa6bdf8cb9c685dcf38df429037b0c8aff3955c6f5b +b8c6d769890a8ee18dc4f9e917993315877c97549549b34785a92543cbeec96a08ae3a28d6e809c4aacd69de356c0012 +95ca86cd384eaceaa7c077c5615736ca31f36824bd6451a16142a1edc129fa42b50724aeed7c738f08d7b157f78b569e +94df609c6d71e8eee7ab74226e371ccc77e01738fe0ef1a6424435b4570fe1e5d15797b66ed0f64eb88d4a3a37631f0e +89057b9783212add6a0690d6bb99097b182738deff2bd9e147d7fd7d6c8eacb4c219923633e6309ad993c24572289901 +83a0f9f5f265c5a0e54defa87128240235e24498f20965009fef664f505a360b6fb4020f2742565dfc7746eb185bcec0 +91170da5306128931349bc3ed50d7df0e48a68b8cc8420975170723ac79d8773e4fa13c5f14dc6e3fafcad78379050b1 +b7178484d1b55f7e56a4cc250b6b2ec6040437d96bdfddfa7b35ed27435860f3855c2eb86c636f2911b012eb83b00db8 +ac0b00c4322d1e4208e09cd977b4e54d221133ff09551f75b32b0b55d0e2be80941dda26257b0e288c162e63c7e9cf68 +9690ed9e7e53ed37ff362930e4096b878b12234c332fd19d5d064824084245952eda9f979e0098110d6963e468cf513e +b6fa547bb0bb83e5c5be0ed462a8783fba119041c136a250045c09d0d2af330c604331e7de960df976ff76d67f8000cd +814603907c21463bcf4e59cfb43066dfe1a50344ae04ef03c87c0f61b30836c3f4dea0851d6fa358c620045b7f9214c8 +9495639e3939fad2a3df00a88603a5a180f3c3a0fe4d424c35060e2043e0921788003689887b1ed5be424d9a89bb18bb +aba4c02d8d57f2c92d5bc765885849e9ff8393d6554f5e5f3e907e5bfac041193a0d8716d7861104a4295d5a03c36b03 +8ead0b56c1ca49723f94a998ba113b9058059321da72d9e395a667e6a63d5a9dac0f5717cec343f021695e8ced1f72af +b43037f7e3852c34ed918c5854cd74e9d5799eeddfe457d4f93bb494801a064735e326a76e1f5e50a339844a2f4a8ec9 +99db8422bb7302199eb0ff3c3d08821f8c32f53a600c5b6fb43e41205d96adae72be5b460773d1280ad1acb806af9be8 +8a9be08eae0086c0f020838925984df345c5512ff32e37120b644512b1d9d4fecf0fd30639ca90fc6cf334a86770d536 +81b43614f1c28aa3713a309a88a782fb2bdfc4261dd52ddc204687791a40cf5fd6a263a8179388596582cccf0162efc2 +a9f3a8b76912deb61d966c75daf5ddb868702ebec91bd4033471c8e533183df548742a81a2671de5be63a502d827437d +902e2415077f063e638207dc7e14109652e42ab47caccd6204e2870115791c9defac5425fd360b37ac0f7bd8fe7011f8 +aa18e4fdc1381b59c18503ae6f6f2d6943445bd00dd7d4a2ad7e5adad7027f2263832690be30d456e6d772ad76f22350 +a348b40ba3ba7d81c5d4631f038186ebd5e5f314f1ea737259151b07c3cc8cf0c6ed4201e71bcc1c22fefda81a20cde6 +aa1306f7ac1acbfc47dc6f7a0cb6d03786cec8c8dc8060388ccda777bca24bdc634d03e53512c23dba79709ff64f8620 +818ccfe46e700567b7f3eb400e5a35f6a5e39b3db3aa8bc07f58ace35d9ae5a242faf8dbccd08d9a9175bbce15612155 +b7e3da2282b65dc8333592bb345a473f03bd6df69170055fec60222de9897184536bf22b9388b08160321144d0940279 +a4d976be0f0568f4e57de1460a1729129252b44c552a69fceec44e5b97c96c711763360d11f9e5bf6d86b4976bf40d69 +85d185f0397c24c2b875b09b6328a23b87982b84ee880f2677a22ff4c9a1ba9f0fea000bb3f7f66375a00d98ebafce17 +b4ccbb8c3a2606bd9b87ce022704663af71d418351575f3b350d294f4efc68c26f9a2ce49ff81e6ff29c3b63d746294e +93ffd3265fddb63724dfde261d1f9e22f15ecf39df28e4d89e9fea03221e8e88b5dd9b77628bacaa783c6f91802d47cc +b1fd0f8d7a01378e693da98d03a2d2fda6b099d03454b6f2b1fa6472ff6bb092751ce6290059826b74ac0361eab00e1e +a89f440c71c561641589796994dd2769616b9088766e983c873fae0716b95c386c8483ab8a4f367b6a68b72b7456dd32 +af4fe92b01d42d03dd5d1e7fa55e96d4bbcb7bf7d4c8c197acd16b3e0f3455807199f683dcd263d74547ef9c244b35cc +a8227f6e0a344dfe76bfbe7a1861be32c4f4bed587ccce09f9ce2cf481b2dda8ae4f566154bc663d15f962f2d41761bd +a7b361663f7495939ed7f518ba45ea9ff576c4e628995b7aea026480c17a71d63fc2c922319f0502eb7ef8f14a406882 +8ddcf382a9f39f75777160967c07012cfa89e67b19714a7191f0c68eaf263935e5504e1104aaabd0899348c972a8d3c6 +98c95b9f6f5c91f805fb185eedd06c6fc4457d37dd248d0be45a6a168a70031715165ea20606245cbdf8815dc0ac697f +805b44f96e001e5909834f70c09be3efcd3b43632bcac5b6b66b6d227a03a758e4b1768ce2a723045681a1d34562aaeb +b0e81b07cdc45b3dca60882676d9badb99f25c461b7efe56e3043b80100bb62d29e1873ae25eb83087273160ece72a55 +b0c53f0abe78ee86c7b78c82ae1f7c070bb0b9c45c563a8b3baa2c515d482d7507bb80771e60b38ac13f78b8af92b4a9 +a7838ef6696a9e4d2e5dfd581f6c8d6a700467e8fd4e85adabb5f7a56f514785dd4ab64f6f1b48366f7d94728359441b +88c76f7700a1d23c30366a1d8612a796da57b2500f97f88fdf2d76b045a9d24e7426a8ffa2f4e86d3046937a841dad58 +ad8964baf98c1f02e088d1d9fcb3af6b1dfa44cdfe0ed2eae684e7187c33d3a3c28c38e8f4e015f9c04d451ed6f85ff6 +90e9d00a098317ececaa9574da91fc149eda5b772dedb3e5a39636da6603aa007804fa86358550cfeff9be5a2cb7845e +a56ff4ddd73d9a6f5ab23bb77efa25977917df63571b269f6a999e1ad6681a88387fcc4ca3b26d57badf91b236503a29 +97ad839a6302c410a47e245df84c01fb9c4dfef86751af3f9340e86ff8fc3cd52fa5ff0b9a0bd1d9f453e02ca80658a6 +a4c8c44cbffa804129e123474854645107d1f0f463c45c30fd168848ebea94880f7c0c5a45183e9eb837f346270bdb35 +a72e53d0a1586d736e86427a93569f52edd2f42b01e78aee7e1961c2b63522423877ae3ac1227a2cf1e69f8e1ff15bc3 +8559f88a7ef13b4f09ac82ae458bbae6ab25671cfbf52dae7eac7280d6565dd3f0c3286aec1a56a8a16dc3b61d78ce47 +8221503f4cdbed550876c5dc118a3f2f17800c04e8be000266633c83777b039a432d576f3a36c8a01e8fd18289ebc10b +99bfbe5f3e46d4d898a578ba86ed26de7ed23914bd3bcdf3c791c0bcd49398a52419077354a5ab75cea63b6c871c6e96 +aa134416d8ff46f2acd866c1074af67566cfcf4e8be8d97329dfa0f603e1ff208488831ce5948ac8d75bfcba058ddcaa +b02609d65ebfe1fe8e52f21224a022ea4b5ea8c1bd6e7b9792eed8975fc387cdf9e3b419b8dd5bcce80703ab3a12a45f +a4f14798508698fa3852e5cac42a9db9797ecee7672a54988aa74037d334819aa7b2ac7b14efea6b81c509134a6b7ad2 +884f01afecbcb987cb3e7c489c43155c416ed41340f61ecb651d8cba884fb9274f6d9e7e4a46dd220253ae561614e44c +a05523c9e71dce1fe5307cc71bd721feb3e1a0f57a7d17c7d1c9fb080d44527b7dbaa1f817b1af1c0b4322e37bc4bb1e +8560aec176a4242b39f39433dd5a02d554248c9e49d3179530815f5031fee78ba9c71a35ceeb2b9d1f04c3617c13d8f0 +996aefd402748d8472477cae76d5a2b92e3f092fc834d5222ae50194dd884c9fb8b6ed8e5ccf8f6ed483ddbb4e80c747 +8fd09900320000cbabc40e16893e2fcf08815d288ec19345ad7b6bb22f7d78a52b6575a3ca1ca2f8bc252d2eafc928ec +939e51f73022bc5dc6862a0adf8fb8a3246b7bfb9943cbb4b27c73743926cc20f615a036c7e5b90c80840e7f1bfee0e7 +a0a6258700cadbb9e241f50766573bf9bdb7ad380b1079dc3afb4054363d838e177b869cad000314186936e40359b1f2 +972699a4131c8ed27a2d0e2104d54a65a7ff1c450ad9da3a325c662ab26869c21b0a84d0700b98c8b5f6ce3b746873d7 +a454c7fe870cb8aa6491eafbfb5f7872d6e696033f92e4991d057b59d70671f2acdabef533e229878b60c7fff8f748b1 +a167969477214201f09c79027b10221e4707662e0c0fde81a0f628249f2f8a859ce3d30a7dcc03b8ecca8f7828ad85c7 +8ff6b7265175beb8a63e1dbf18c9153fb2578c207c781282374f51b40d57a84fd2ef2ea2b9c6df4a54646788a62fd17f +a3d7ebeccde69d73d8b3e76af0da1a30884bb59729503ff0fb0c3bccf9221651b974a6e72ea33b7956fc3ae758226495 +b71ef144c9a98ce5935620cb86c1590bd4f48e5a2815d25c0cdb008fde628cf628c31450d3d4f67abbfeb16178a74cfd +b5e0a16d115134f4e2503990e3f2035ed66b9ccf767063fe6747870d97d73b10bc76ed668550cb82eedc9a2ca6f75524 +b30ffaaf94ee8cbc42aa2c413175b68afdb207dbf351fb20be3852cb7961b635c22838da97eaf43b103aff37e9e725cc +98aa7d52284f6c1f22e272fbddd8c8698cf8f5fbb702d5de96452141fafb559622815981e50b87a72c2b1190f59a7deb +81fbacda3905cfaf7780bb4850730c44166ed26a7c8d07197a5d4dcd969c09e94a0461638431476c16397dd7bdc449f9 +95e47021c1726eac2e5853f570d6225332c6e48e04c9738690d53e07c6b979283ebae31e2af1fc9c9b3e59f87e5195b1 +ac024a661ba568426bb8fce21780406537f518075c066276197300841e811860696f7588188bc01d90bace7bc73d56e3 +a4ebcaf668a888dd404988ab978594dee193dad2d0aec5cdc0ccaf4ec9a7a8228aa663db1da8ddc52ec8472178e40c32 +a20421b8eaf2199d93b083f2aff37fb662670bd18689d046ae976d1db1fedd2c2ff897985ecc6277b396db7da68bcb27 +8bc33d4b40197fd4d49d1de47489d10b90d9b346828f53a82256f3e9212b0cbc6930b895e879da9cec9fedf026aadb3e +aaafdd1bec8b757f55a0433eddc0a39f818591954fd4e982003437fcceb317423ad7ee74dbf17a2960380e7067a6b4e2 +aad34277ebaed81a6ec154d16736866f95832803af28aa5625bf0461a71d02b1faba02d9d9e002be51c8356425a56867 +976e9c8b150d08706079945bd0e84ab09a648ecc6f64ded9eb5329e57213149ae409ae93e8fbd8eda5b5c69f5212b883 +8097fae1653247d2aed4111533bc378171d6b2c6d09cbc7baa9b52f188d150d645941f46d19f7f5e27b7f073c1ebd079 +83905f93b250d3184eaba8ea7d727c4464b6bdb027e5cbe4f597d8b9dc741dcbea709630bd4fd59ce24023bec32fc0f3 +8095030b7045cff28f34271386e4752f9a9a0312f8df75de4f424366d78534be2b8e1720a19cb1f9a2d21105d790a225 +a7b7b73a6ae2ed1009c49960374b0790f93c74ee03b917642f33420498c188a169724945a975e5adec0a1e83e07fb1b2 +856a41c54df393b6660b7f6354572a4e71c8bfca9cabaffb3d4ef2632c015e7ee2bc10056f3eccb3dbed1ad17d939178 +a8f7a55cf04b38cd4e330394ee6589da3a07dc9673f74804fdf67b364e0b233f14aec42e783200a2e4666f7c5ff62490 +82c529f4e543c6bca60016dc93232c115b359eaee2798a9cf669a654b800aafe6ab4ba58ea8b9cdda2b371c8d62fa845 +8caab020c1baddce77a6794113ef1dfeafc5f5000f48e97f4351b588bf02f1f208101745463c480d37f588d5887e6d8c +8fa91b3cc400f48b77b6fd77f3b3fbfb3f10cdff408e1fd22d38f77e087b7683adad258804409ba099f1235b4b4d6fea +8aa02787663d6be9a35677d9d8188b725d5fcd770e61b11b64e3def8808ea5c71c0a9afd7f6630c48634546088fcd8e2 +b5635b7b972e195cab878b97dea62237c7f77eb57298538582a330b1082f6207a359f2923864630136d8b1f27c41b9aa +8257bb14583551a65975946980c714ecd6e5b629672bb950b9caacd886fbd22704bc9e3ba7d30778adab65dc74f0203a +ab5fe1cd12634bfa4e5c60d946e2005cbd38f1063ec9a5668994a2463c02449a0a185ef331bd86b68b6e23a8780cb3ba +a7d3487da56cda93570cc70215d438204f6a2709bfb5fda6c5df1e77e2efc80f4235c787e57fbf2c74aaff8cbb510a14 +b61cff7b4c49d010e133319fb828eb900f8a7e55114fc86b39c261a339c74f630e1a7d7e1350244ada566a0ff3d46c4b +8d4d1d55d321d278db7a85522ccceca09510374ca81d4d73e3bb5249ace7674b73900c35a531ec4fa6448fabf7ad00dc +966492248aee24f0f56c8cfca3c8ec6ba3b19abb69ae642041d4c3be8523d22c65c4dafcab4c58989ccc4e0bd2f77919 +b20c320a90cb220b86e1af651cdc1e21315cd215da69f6787e28157172f93fc8285dcd59b039c626ed8ca4633cba1a47 +aae9e6b22f018ceb5c0950210bb8182cb8cb61014b7e14581a09d36ebd1bbfebdb2b82afb7fdb0cf75e58a293d9c456d +875547fb67951ad37b02466b79f0c9b985ccbc500cfb431b17823457dc79fb9597ec42cd9f198e15523fcd88652e63a4 +92afce49773cb2e20fb21e4f86f18e0959ebb9c33361547ddb30454ee8e36b1e234019cbdca0e964cb292f7f77df6b90 +8af85343dfe1821464c76ba11c216cbef697b5afc69c4d821342e55afdac047081ec2e3f7b09fc14b518d9a23b78c003 +b7de4a1648fd63f3a918096ea669502af5357438e69dac77cb8102b6e6c15c76e033cfaa80dafc806e535ede5c1a20aa +ac80e9b545e8bd762951d96c9ce87f629d01ffcde07efc2ef7879ca011f1d0d8a745abf26c9d452541008871304fac00 +a4cf0f7ed724e481368016c38ea5816698a5f68eb21af4d3c422d2ba55f96a33e427c2aa40de1b56a7cfac7f7cf43ab0 +899b0a678bb2db2cae1b44e75a661284844ebcdd87abf308fedeb2e4dbe5c5920c07db4db7284a7af806a2382e8b111a +af0588a2a4afce2b1b13c1230816f59e8264177e774e4a341b289a101dcf6af813638fed14fb4d09cb45f35d5d032609 +a4b8df79e2be76e9f5fc5845f06fe745a724cf37c82fcdb72719b77bdebea3c0e763f37909373e3a94480cc5e875cba0 +83e42c46d88930c8f386b19fd999288f142d325e2ebc86a74907d6d77112cb0d449bc511c95422cc810574031a8cbba9 +b5e39534070de1e5f6e27efbdd3dc917d966c2a9b8cf2d893f964256e95e954330f2442027dc148c776d63a95bcde955 +958607569dc28c075e658cd4ae3927055c6bc456eef6212a6fea8205e48ed8777a8064f584cda38fe5639c371e2e7fba +812adf409fa63575113662966f5078a903212ffb65c9b0bbe62da0f13a133443a7062cb8fd70f5e5dd5559a32c26d2c8 +a679f673e5ce6a3cce7fa31f22ee3785e96bcb55e5a776e2dd3467bef7440e3555d1a9b87cb215e86ee9ed13a090344b +afedbb34508b159eb25eb2248d7fe328f86ef8c7d84c62d5b5607d74aae27cc2cc45ee148eb22153b09898a835c58df4 +b75505d4f6b67d31e665cfaf5e4acdb5838ae069166b7fbcd48937c0608a59e40a25302fcc1873d2e81c1782808c70f0 +b62515d539ec21a155d94fc00ea3c6b7e5f6636937bce18ed5b618c12257fb82571886287fd5d1da495296c663ebc512 +ab8e1a9446bbdd588d1690243b1549d230e6149c28f59662b66a8391a138d37ab594df38e7720fae53217e5c3573b5be +b31e8abf4212e03c3287bb2c0a153065a7290a16764a0bac8f112a72e632185a654bb4e88fdd6053e6c7515d9719fadb +b55165477fe15b6abd2d0f4fddaa9c411710dcc4dd712daba3d30e303c9a3ee5415c256f9dc917ecf18c725b4dbab059 +a0939d4f57cacaae549b78e87cc234de4ff6a35dc0d9cd5d7410abc30ebcd34c135e008651c756e5a9d2ca79c40ef42b +8cf10e50769f3443340844aad4d56ec790850fed5a41fcbd739abac4c3015f0a085a038fbe7fae9f5ad899cce5069f6b +924055e804d82a99ea4bb160041ea4dc14b568abf379010bc1922fde5d664718c31d103b8b807e3a1ae809390e708c73 +8ec0f9d26f71b0f2e60a179e4fd1778452e2ffb129d50815e5d7c7cb9415fa69ae5890578086e8ef6bfde35ad2a74661 +98c7f12b15ec4426b59f737f73bf5faea4572340f4550b7590dfb7f7ffedb2372e3e555977c63946d579544c53210ad0 +8a935f7a955c78f69d66f18eee0092e5e833fa621781c9581058e219af4d7ceee48b84e472e159dda6199715fb2f9acf +b78d4219f95a2dbfaa7d0c8a610c57c358754f4f43c2af312ab0fe8f10a5f0177e475332fb8fd23604e474fc2abeb051 +8d086a14803392b7318c28f1039a17e3cfdcece8abcaca3657ec3d0ac330842098a85c0212f889fabb296dfb133ce9aa +a53249f417aac82f2c2a50c244ce21d3e08a5e5a8bd33bec2a5ab0d6cd17793e34a17edfa3690899244ce201e2fb9986 +8619b0264f9182867a1425be514dc4f1ababc1093138a728a28bd7e4ecc99b9faaff68c23792264bc6e4dce5f52a5c52 +8c171edbbbde551ec19e31b2091eb6956107dd9b1f853e1df23bff3c10a3469ac77a58335eee2b79112502e8e163f3de +a9d19ec40f0ca07c238e9337c6d6a319190bdba2db76fb63902f3fb459aeeb50a1ac30db5b25ee1b4201f3ca7164a7f4 +b9c6ec14b1581a03520b8d2c1fbbc31fb8ceaef2c0f1a0d0080b6b96e18442f1734bea7ef7b635d787c691de4765d469 +8cb437beb4cfa013096f40ccc169a713dc17afee6daa229a398e45fd5c0645a9ad2795c3f0cd439531a7151945d7064d +a6e8740cc509126e146775157c2eb278003e5bb6c48465c160ed27888ca803fa12eee1f6a8dd7f444f571664ed87fdc1 +b75c1fecc85b2732e96b3f23aefb491dbd0206a21d682aee0225838dc057d7ed3b576176353e8e90ae55663f79e986e4 +ad8d249b0aea9597b08358bce6c77c1fd552ef3fbc197d6a1cfe44e5e6f89b628b12a6fb04d5dcfcbacc51f46e4ae7bb +b998b2269932cbd58d04b8e898d373ac4bb1a62e8567484f4f83e224061bc0f212459f1daae95abdbc63816ae6486a55 +827988ef6c1101cddc96b98f4a30365ff08eea2471dd949d2c0a9b35c3bbfa8c07054ad1f4c88c8fbf829b20bb5a9a4f +8692e638dd60babf7d9f2f2d2ce58e0ac689e1326d88311416357298c6a2bffbfebf55d5253563e7b3fbbf5072264146 +a685d75b91aea04dbc14ab3c1b1588e6de96dae414c8e37b8388766029631b28dd860688079b12d09cd27f2c5af11adf +b57eced93eec3371c56679c259b34ac0992286be4f4ff9489d81cf9712403509932e47404ddd86f89d7c1c3b6391b28c +a1c8b4e42ebcbd8927669a97f1b72e236fb19249325659e72be7ddaaa1d9e81ca2abb643295d41a8c04a2c01f9c0efd7 +877c33de20d4ed31674a671ba3e8f01a316581e32503136a70c9c15bf0b7cb7b1cba6cd4eb641fad165fb3c3c6c235fd +a2a469d84ec478da40838f775d11ad38f6596eb41caa139cc190d6a10b5108c09febae34ffdafac92271d2e73c143693 +972f817caedb254055d52e963ed28c206848b6c4cfdb69dbc961c891f8458eaf582a6d4403ce1177d87bc2ea410ef60a +accbd739e138007422f28536381decc54bb6bd71d93edf3890e54f9ef339f83d2821697d1a4ac1f5a98175f9a9ecb9b5 +8940f8772e05389f823b62b3adc3ed541f91647f0318d7a0d3f293aeeb421013de0d0a3664ea53dd24e5fbe02d7efef6 +8ecce20f3ef6212edef07ec4d6183fda8e0e8cad2c6ccd0b325e75c425ee1faba00b5c26b4d95204238931598d78f49d +97cc72c36335bd008afbed34a3b0c7225933faba87f7916d0a6d2161e6f82e0cdcda7959573a366f638ca75d30e9dab1 +9105f5de8699b5bdb6bd3bb6cc1992d1eac23929c29837985f83b22efdda92af64d9c574aa9640475087201bbbe5fd73 +8ffb33c4f6d05c413b9647eb6933526a350ed2e4278ca2ecc06b0e8026d8dbe829c476a40e45a6df63a633090a3f82ef +8bfc6421fdc9c2d2aaa68d2a69b1a2728c25b84944cc3e6a57ff0c94bfd210d1cbf4ff3f06702d2a8257024d8be7de63 +a80e1dc1dddfb41a70220939b96dc6935e00b32fb8be5dff4eed1f1c650002ff95e4af481c43292e3827363b7ec4768a +96f714ebd54617198bd636ba7f7a7f8995a61db20962f2165078d9ed8ee764d5946ef3cbdc7ebf8435bb8d5dd4c1deac +8cdb0890e33144d66391d2ae73f5c71f5a861f72bc93bff6cc399fc25dd1f9e17d8772592b44593429718784802ac377 +8ccf9a7f80800ee770b92add734ed45a73ecc31e2af0e04364eefc6056a8223834c7c0dc9dfc52495bdec6e74ce69994 +aa0875f423bd68b5f10ba978ddb79d3b96ec093bfbac9ff366323193e339ed7c4578760fb60f60e93598bdf1e5cc4995 +a9214f523957b59c7a4cb61a40251ad72aba0b57573163b0dc0f33e41d2df483fb9a1b85a5e7c080e9376c866790f8cb +b6224b605028c6673a536cc8ff9aeb94e7a22e686fda82cf16068d326469172f511219b68b2b3affb7933af0c1f80d07 +b6d58968d8a017c6a34e24c2c09852f736515a2c50f37232ac6b43a38f8faa7572cc31dade543b594b61b5761c4781d0 +8a97cefe5120020c38deeb861d394404e6c993c6cbd5989b6c9ebffe24f46ad11b4ba6348e2991cbf3949c28cfc3c99d +95bf046f8c3a9c0ce2634be4de3713024daec3fc4083e808903b25ce3ac971145af90686b451efcc72f6b22df0216667 +a6a4e2f71b8fa28801f553231eff2794c0f10d12e7e414276995e21195abc9c2983a8997e41af41e78d19ff6fbb2680b +8e5e62a7ca9c2f58ebaab63db2ff1fb1ff0877ae94b7f5e2897f273f684ae639dff44cc65718f78a9c894787602ab26a +8542784383eec4f565fcb8b9fc2ad8d7a644267d8d7612a0f476fc8df3aff458897a38003d506d24142ad18f93554f2b +b7db68ba4616ea072b37925ec4fb39096358c2832cc6d35169e032326b2d6614479f765ae98913c267105b84afcb9bf2 +8b31dbb9457d23d416c47542c786e07a489af35c4a87dadb8ee91bea5ac4a5315e65625d78dad2cf8f9561af31b45390 +a8545a1d91ac17257732033d89e6b7111db8242e9c6ebb0213a88906d5ef407a2c6fdb444e29504b06368b6efb4f4839 +b1bd85d29ebb28ccfb05779aad8674906b267c2bf8cdb1f9a0591dd621b53a4ee9f2942687ee3476740c0b4a7621a3ae +a2b54534e152e46c50d91fff03ae9cd019ff7cd9f4168b2fe7ac08ef8c3bbc134cadd3f9d6bd33d20ae476c2a8596c8a +b19b571ff4ae3e9f5d95acda133c455e72c9ea9973cae360732859836c0341c4c29ab039224dc5bc3deb824e031675d8 +940b5f80478648bac025a30f3efeb47023ce20ee98be833948a248bca6979f206bb28fc0f17b90acf3bb4abd3d14d731 +8f106b40588586ac11629b96d57808ad2808915d89539409c97414aded90b4ff23286a692608230a52bff696055ba5d6 +ae6bda03aa10da3d2abbc66d764ca6c8d0993e7304a1bdd413eb9622f3ca1913baa6da1e9f4f9e6cf847f14f44d6924d +a18e7796054a340ef826c4d6b5a117b80927afaf2ebd547794c400204ae2caf277692e2eabb55bc2f620763c9e9da66d +8d2d25180dc2c65a4844d3e66819ccfcf48858f0cc89e1c77553b463ec0f7feb9a4002ce26bc618d1142549b9850f232 +863f413a394de42cc8166c1c75d513b91d545fff1de6b359037a742c70b008d34bf8e587afa2d62c844d0c6f0ea753e7 +83cd0cf62d63475e7fcad18a2e74108499cdbf28af2113cfe005e3b5887794422da450b1944d0a986eb7e1f4c3b18f25 +b4f8b350a6d88fea5ab2e44715a292efb12eb52df738c9b2393da3f1ddee68d0a75b476733ccf93642154bceb208f2b8 +b3f52aaa4cd4221cb9fc45936cc67fd3864bf6d26bf3dd86aa85aa55ecfc05f5e392ecce5e7cf9406b4b1c4fce0398c8 +b33137084422fb643123f40a6df2b498065e65230fc65dc31791c330e898c51c3a65ff738930f32c63d78f3c9315f85b +91452bfa75019363976bb7337fe3a73f1c10f01637428c135536b0cdc7da5ce558dae3dfc792aa55022292600814a8ef +ad6ba94c787cd4361ca642c20793ea44f1f127d4de0bb4a77c7fbfebae0fcadbf28e2cb6f0c12c12a07324ec8c19761d +890aa6248b17f1501b0f869c556be7bf2b1d31a176f9978bb97ab7a6bd4138eed32467951c5ef1871944b7f620542f43 +82111db2052194ee7dd22ff1eafffac0443cf969d3762cceae046c9a11561c0fdce9c0711f88ac01d1bed165f8a7cee3 +b1527b71df2b42b55832f72e772a466e0fa05743aacc7814f4414e4bcc8d42a4010c9e0fd940e6f254cafedff3cd6543 +922370fa49903679fc565f09c16a5917f8125e72acfeb060fcdbadbd1644eb9f4016229756019c93c6d609cda5d5d174 +aa4c7d98a96cab138d2a53d4aee8ebff6ef903e3b629a92519608d88b3bbd94de5522291a1097e6acf830270e64c8ee1 +b3dc21608a389a72d3a752883a382baaafc61ecc44083b832610a237f6a2363f24195acce529eb4aed4ef0e27a12b66e +94619f5de05e07b32291e1d7ab1d8b7337a2235e49d4fb5f3055f090a65e932e829efa95db886b32b153bdd05a53ec8c +ade1e92722c2ffa85865d2426fb3d1654a16477d3abf580cfc45ea4b92d5668afc9d09275d3b79283e13e6b39e47424d +b7201589de7bed094911dd62fcd25c459a8e327ac447b69f541cdba30233063e5ddffad0b67e9c3e34adcffedfd0e13d +809d325310f862d6549e7cb40f7e5fc9b7544bd751dd28c4f363c724a0378c0e2adcb5e42ec8f912f5f49f18f3365c07 +a79c20aa533de7a5d671c99eb9eb454803ba54dd4f2efa3c8fec1a38f8308e9905c71e9282955225f686146388506ff6 +a85eeacb5e8fc9f3ed06a3fe2dc3108ab9f8c5877b148c73cf26e4e979bf5795edbe2e63a8d452565fd1176ed40402b2 +97ef55662f8a1ec0842b22ee21391227540adf7708f491436044f3a2eb18c471525e78e1e14fa292507c99d74d7437c6 +93110d64ed5886f3d16ce83b11425576a3a7a9bb831cd0de3f9a0b0f2270a730d68136b4ef7ff035ede004358f419b5c +ac9ed0a071517f0ae4f61ce95916a90ba9a77a3f84b0ec50ef7298acdcd44d1b94525d191c39d6bd1bb68f4471428760 +98abd6a02c7690f5a339adf292b8c9368dfc12e0f8069cf26a5e0ce54b4441638f5c66ea735142f3c28e00a0024267e6 +b51efb73ba6d44146f047d69b19c0722227a7748b0e8f644d0fc9551324cf034c041a2378c56ce8b58d06038fb8a78de +8f115af274ef75c1662b588b0896b97d71f8d67986ae846792702c4742ab855952865ce236b27e2321967ce36ff93357 +b3c4548f14d58b3ab03c222da09e4381a0afe47a72d18d50a94e0008797f78e39e99990e5b4757be62310d400746e35a +a9b1883bd5f31f909b8b1b6dcb48c1c60ed20aa7374b3ffa7f5b2ed036599b5bef33289d23c80a5e6420d191723b92f7 +85d38dffd99487ae5bb41ab4a44d80a46157bbbe8ef9497e68f061721f74e4da513ccc3422936b059575975f6787c936 +adf870fcb96e972c033ab7a35d28ae79ee795f82bc49c3bd69138f0e338103118d5529c53f2d72a9c0d947bf7d312af2 +ab4c7a44e2d9446c6ff303eb49aef0e367a58b22cc3bb27b4e69b55d1d9ee639c9234148d2ee95f9ca8079b1457d5a75 +a386420b738aba2d7145eb4cba6d643d96bda3f2ca55bb11980b318d43b289d55a108f4bc23a9606fb0bccdeb3b3bb30 +847020e0a440d9c4109773ecca5d8268b44d523389993b1f5e60e541187f7c597d79ebd6e318871815e26c96b4a4dbb1 +a530aa7e5ca86fcd1bec4b072b55cc793781f38a666c2033b510a69e110eeabb54c7d8cbcb9c61fee531a6f635ffa972 +87364a5ea1d270632a44269d686b2402da737948dac27f51b7a97af80b66728b0256547a5103d2227005541ca4b7ed04 +8816fc6e16ea277de93a6d793d0eb5c15e9e93eb958c5ef30adaf8241805adeb4da8ce19c3c2167f971f61e0b361077d +8836a72d301c42510367181bb091e4be377777aed57b73c29ef2ce1d475feedd7e0f31676284d9a94f6db01cc4de81a2 +b0d9d8b7116156d9dde138d28aa05a33e61f8a85839c1e9071ccd517b46a5b4b53acb32c2edd7150c15bc1b4bd8db9e3 +ae931b6eaeda790ba7f1cd674e53dc87f6306ff44951fa0df88d506316a5da240df9794ccbd7215a6470e6b31c5ea193 +8c6d5bdf87bd7f645419d7c6444e244fe054d437ed1ba0c122fde7800603a5fadc061e5b836cb22a6cfb2b466f20f013 +90d530c6d0cb654999fa771b8d11d723f54b8a8233d1052dc1e839ea6e314fbed3697084601f3e9bbb71d2b4eaa596df +b0d341a1422588c983f767b1ed36c18b141774f67ef6a43cff8e18b73a009da10fc12120938b8bba27f225bdfd3138f9 +a131b56f9537f460d304e9a1dd75702ace8abd68cb45419695cb8dee76998139058336c87b7afd6239dc20d7f8f940cc +aa6c51fa28975f709329adee1bbd35d49c6b878041841a94465e8218338e4371f5cb6c17f44a63ac93644bf28f15d20f +88440fb584a99ebd7f9ea04aaf622f6e44e2b43bbb49fb5de548d24a238dc8f26c8da2ccf03dd43102bda9f16623f609 +9777b8695b790e702159a4a750d5e7ff865425b95fa0a3c15495af385b91c90c00a6bd01d1b77bffe8c47d01baae846f +8b9d764ece7799079e63c7f01690c8eff00896a26a0d095773dea7a35967a8c40db7a6a74692f0118bf0460c26739af4 +85808c65c485520609c9e61fa1bb67b28f4611d3608a9f7a5030ee61c3aa3c7e7dc17fff48af76b4aecee2cb0dbd22ac +ad2783a76f5b3db008ef5f7e67391fda4e7e36abde6b3b089fc4835b5c339370287935af6bd53998bed4e399eda1136d +96f18ec03ae47c205cc4242ca58e2eff185c9dca86d5158817e2e5dc2207ab84aadda78725f8dc080a231efdc093b940 +97de1ab6c6cc646ae60cf7b86df73b9cf56cc0cd1f31b966951ebf79fc153531af55ca643b20b773daa7cab784b832f7 +870ba266a9bfa86ef644b1ef025a0f1b7609a60de170fe9508de8fd53170c0b48adb37f19397ee8019b041ce29a16576 +ad990e888d279ac4e8db90619d663d5ae027f994a3992c2fbc7d262b5990ae8a243e19157f3565671d1cb0de17fe6e55 +8d9d5adcdd94c5ba3be4d9a7428133b42e485f040a28d16ee2384758e87d35528f7f9868de9bd23d1a42a594ce50a567 +85a33ed75d514ece6ad78440e42f7fcdb59b6f4cff821188236d20edae9050b3a042ce9bc7d2054296e133d033e45022 +92afd2f49a124aaba90de59be85ff269457f982b54c91b06650c1b8055f9b4b0640fd378df02a00e4fc91f7d226ab980 +8c0ee09ec64bd831e544785e3d65418fe83ed9c920d9bb4d0bf6dd162c1264eb9d6652d2def0722e223915615931581c +8369bedfa17b24e9ad48ebd9c5afea4b66b3296d5770e09b00446c5b0a8a373d39d300780c01dcc1c6752792bccf5fd0 +8b9e960782576a59b2eb2250d346030daa50bbbec114e95cdb9e4b1ba18c3d34525ae388f859708131984976ca439d94 +b682bface862008fea2b5a07812ca6a28a58fd151a1d54c708fc2f8572916e0d678a9cb8dc1c10c0470025c8a605249e +a38d5e189bea540a824b36815fc41e3750760a52be0862c4cac68214febdc1a754fb194a7415a8fb7f96f6836196d82a +b9e7fbda650f18c7eb8b40e42cc42273a7298e65e8be524292369581861075c55299ce69309710e5b843cb884de171bd +b6657e5e31b3193874a1bace08f42faccbd3c502fb73ad87d15d18a1b6c2a146f1baa929e6f517db390a5a47b66c0acf +ae15487312f84ed6265e4c28327d24a8a0f4d2d17d4a5b7c29b974139cf93223435aaebe3af918f5b4bb20911799715f +8bb4608beb06bc394e1a70739b872ce5a2a3ffc98c7547bf2698c893ca399d6c13686f6663f483894bccaabc3b9c56ad +b58ac36bc6847077584308d952c5f3663e3001af5ecf2e19cb162e1c58bd6c49510205d453cffc876ca1dc6b8e04a578 +924f65ced61266a79a671ffb49b300f0ea44c50a0b4e3b02064faa99fcc3e4f6061ea8f38168ab118c5d47bd7804590e +8d67d43b8a06b0ff4fafd7f0483fa9ed1a9e3e658a03fb49d9d9b74e2e24858dc1bed065c12392037b467f255d4e5643 +b4d4f87813125a6b355e4519a81657fa97c43a6115817b819a6caf4823f1d6a1169683fd68f8d025cdfa40ebf3069acb +a7fd4d2c8e7b59b8eed3d4332ae94b77a89a2616347402f880bc81bde072220131e6dbec8a605be3a1c760b775375879 +8d4a7d8fa6f55a30df37bcf74952e2fa4fd6676a2e4606185cf154bdd84643fd01619f8fb8813a564f72e3f574f8ce30 +8086fb88e6260e9a9c42e9560fde76315ff5e5680ec7140f2a18438f15bc2cc7d7d43bfb5880b180b738c20a834e6134 +916c4c54721de03934fee6f43de50bb04c81f6f8dd4f6781e159e71c40c60408aa54251d457369d133d4ba3ed7c12cb4 +902e5bf468f11ed9954e2a4a595c27e34abe512f1d6dc08bbca1c2441063f9af3dc5a8075ab910a10ff6c05c1c644a35 +a1302953015e164bf4c15f7d4d35e3633425a78294406b861675667eec77765ff88472306531e5d3a4ec0a2ff0dd6a9e +87874461df3c9aa6c0fa91325576c0590f367075f2f0ecfeb34afe162c04c14f8ce9d608c37ac1adc8b9985bc036e366 +84b50a8a61d3cc609bfb0417348133e698fe09a6d37357ce3358de189efcf35773d78c57635c2d26c3542b13cc371752 +acaed2cff8633d12c1d12bb7270c54d65b0b0733ab084fd47f81d0a6e1e9b6f300e615e79538239e6160c566d8bb8d29 +889e6a0e136372ca4bac90d1ab220d4e1cad425a710e8cdd48b400b73bb8137291ceb36a39440fa84305783b1d42c72f +90952e5becec45b2b73719c228429a2c364991cf1d5a9d6845ae5b38018c2626f4308daa322cab1c72e0f6c621bb2b35 +8f5a97a801b6e9dcd66ccb80d337562c96f7914e7169e8ff0fda71534054c64bf2a9493bb830623d612cfe998789be65 +84f3df8b9847dcf1d63ca470dc623154898f83c25a6983e9b78c6d2d90a97bf5e622445be835f32c1e55e6a0a562ea78 +91d12095cd7a88e7f57f254f02fdb1a1ab18984871dead2f107404bcf8069fe68258c4e6f6ebd2477bddf738135400bb +b771a28bc04baef68604d4723791d3712f82b5e4fe316d7adc2fc01b935d8e644c06d59b83bcb542afc40ebafbee0683 +872f6341476e387604a7e93ae6d6117e72d164e38ebc2b825bc6df4fcce815004d7516423c190c1575946b5de438c08d +90d6b4aa7d40a020cdcd04e8b016d041795961a8e532a0e1f4041252131089114a251791bf57794cadb7d636342f5d1c +899023ba6096a181448d927fed7a0fe858be4eac4082a42e30b3050ee065278d72fa9b9d5ce3bc1372d4cbd30a2f2976 +a28f176571e1a9124f95973f414d5bdbf5794d41c3839d8b917100902ac4e2171eb940431236cec93928a60a77ede793 +838dbe5bcd29c4e465d02350270fa0036cd46f8730b13d91e77afb7f5ed16525d0021d3b2ae173a76c378516a903e0cb +8e105d012dd3f5d20f0f1c4a7e7f09f0fdd74ce554c3032e48da8cce0a77260d7d47a454851387770f5c256fa29bcb88 +8f4df0f9feeb7a487e1d138d13ea961459a6402fd8f8cabb226a92249a0d04ded5971f3242b9f90d08da5ff66da28af6 +ad1cfda4f2122a20935aa32fb17c536a3653a18617a65c6836700b5537122af5a8206befe9eaea781c1244c43778e7f1 +832c6f01d6571964ea383292efc8c8fa11e61c0634a25fa180737cc7ab57bc77f25e614aac9a2a03d98f27b3c1c29de2 +903f89cc13ec6685ac7728521898781fecb300e9094ef913d530bf875c18bcc3ceed7ed51e7b482d45619ab4b025c2e9 +a03c474bb915aad94f171e8d96f46abb2a19c9470601f4c915512ec8b9e743c3938450a2a5b077b4618b9df8809e1dc1 +83536c8456f306045a5f38ae4be2e350878fa7e164ea408d467f8c3bc4c2ee396bd5868008c089183868e4dfad7aa50b +88f26b4ea1b236cb326cd7ad7e2517ec8c4919598691474fe15d09cabcfc37a8d8b1b818f4d112432ee3a716b0f37871 +a44324e3fe96e9c12b40ded4f0f3397c8c7ee8ff5e96441118d8a6bfad712d3ac990b2a6a23231a8f691491ac1fd480f +b0de4693b4b9f932191a21ee88629964878680152a82996c0019ffc39f8d9369bbe2fe5844b68d6d9589ace54af947e4 +8e5d8ba948aea5fd26035351a960e87f0d23efddd8e13236cc8e4545a3dda2e9a85e6521efb8577e03772d3637d213d9 +93efc82d2017e9c57834a1246463e64774e56183bb247c8fc9dd98c56817e878d97b05f5c8d900acf1fbbbca6f146556 +8731176363ad7658a2862426ee47a5dce9434216cef60e6045fa57c40bb3ce1e78dac4510ae40f1f31db5967022ced32 +b10c9a96745722c85bdb1a693100104d560433d45b9ac4add54c7646a7310d8e9b3ca9abd1039d473ae768a18e489845 +a2ac374dfbb464bf850b4a2caf15b112634a6428e8395f9c9243baefd2452b4b4c61b0cb2836d8eae2d57d4900bf407e +b69fe3ded0c4f5d44a09a0e0f398221b6d1bf5dbb8bc4e338b93c64f1a3cac1e4b5f73c2b8117158030ec03787f4b452 +8852cdbaf7d0447a8c6f211b4830711b3b5c105c0f316e3a6a18dcfbb9be08bd6f4e5c8ae0c3692da08a2dfa532f9d5c +93bbf6d7432a7d98ade3f94b57bf9f4da9bc221a180a370b113066dd42601bb9e09edd79e2e6e04e00423399339eebda +a80941c391f1eeafc1451c59e4775d6a383946ff22997aeaadf806542ba451d3b0f0c6864eeba954174a296efe2c1550 +a045fe2bb011c2a2f71a0181a8f457a3078470fb74c628eab8b59aef69ffd0d649723bf74d6885af3f028bc5a104fb39 +b9d8c35911009c4c8cad64692139bf3fc16b78f5a19980790cb6a7aea650a25df4231a4437ae0c351676a7e42c16134f +94c79501ded0cfcbab99e1841abe4a00a0252b3870e20774c3da16c982d74c501916ec28304e71194845be6e3113c7ab +900a66418b082a24c6348d8644ddb1817df5b25cb33044a519ef47cc8e1f7f1e38d2465b7b96d32ed472d2d17f8414c6 +b26f45d393b8b2fcb29bdbb16323dc7f4b81c09618519ab3a39f8ee5bd148d0d9f3c0b5dfab55b5ce14a1cb9206d777b +aa1a87735fc493a80a96a9a57ca40a6d9c32702bfcaa9869ce1a116ae65d69cefe2f3e79a12454b4590353e96f8912b4 +a922b188d3d0b69b4e4ea2a2aa076566962844637da12c0832105d7b31dea4a309eee15d12b7a336be3ea36fcbd3e3b7 +8f3841fcf4105131d8c4d9885e6e11a46c448226401cf99356c291fadb864da9fa9d30f3a73c327f23f9fd99a11d633e +9791d1183fae270e226379af6c497e7da803ea854bb20afa74b253239b744c15f670ee808f708ede873e78d79a626c9a +a4cad52e3369491ada61bf28ada9e85de4516d21c882e5f1cd845bea9c06e0b2887b0c5527fcff6fc28acd3c04f0a796 +b9ac86a900899603452bd11a7892a9bfed8054970bfcbeaa8c9d1930db891169e38d6977f5258c25734f96c8462eee3b +a3a154c28e5580656a859f4efc2f5ebfa7eaa84ca40e3f134fa7865e8581586db74992dbfa4036aa252fba103773ddde +95cc2a0c1885a029e094f5d737e3ecf4d26b99036453a8773c77e360101f9f98676ee246f6f732a377a996702d55691f +842651bbe99720438d8d4b0218feb60481280c05beb17750e9ca0d8c0599a60f873b7fbdcc7d8835ba9a6d57b16eec03 +81ee54699da98f5620307893dcea8f64670609fa20e5622265d66283adeac122d458b3308c5898e6c57c298db2c8b24f +b97868b0b2bc98032d68352a535a1b341b9ff3c7af4e3a7f3ebc82d3419daa1b5859d6aedc39994939623c7cd878bd9b +b60325cd5d36461d07ef253d826f37f9ee6474a760f2fff80f9873d01fd2b57711543cdc8d7afa1c350aa753c2e33dea +8c205326c11d25a46717b780c639d89714c7736c974ae71287e3f4b02e6605ac2d9b4928967b1684f12be040b7bf2dd3 +95a392d82db51e26ade6c2ccd3396d7e40aff68fa570b5951466580d6e56dda51775dce5cf3a74a7f28c3cb2eb551c4d +8f2cc8071eb56dffb70bda6dd433b556221dc8bba21c53353c865f00e7d4d86c9e39f119ea9a8a12ef583e9a55d9a6b6 +9449a71af9672aaf8856896d7e3d788b22991a7103f75b08c0abbcc2bfe60fda4ed8ce502cea4511ff0ea52a93e81222 +857090ab9fdb7d59632d068f3cc8cf27e61f0d8322d30e6b38e780a1f05227199b4cd746aac1311c36c659ef20931f28 +98a891f4973e7d9aaf9ac70854608d4f7493dffc7e0987d7be9dd6029f6ea5636d24ef3a83205615ca1ff403750058e1 +a486e1365bbc278dd66a2a25d258dc82f46b911103cb16aab3945b9c95ae87b386313a12b566df5b22322ede0afe25ad +a9a1eb399ed95d396dccd8d1ac718043446f8b979ec62bdce51c617c97a312f01376ab7fb87d27034e5f5570797b3c33 +b7abc3858d7a74bb446218d2f5a037e0fae11871ed9caf44b29b69c500c1fa1dcfad64c9cdccc9d80d5e584f06213deb +8cfb09fe2e202faa4cebad932b1d35f5ca204e1c2a0c740a57812ac9a6792130d1312aabd9e9d4c58ca168bfebd4c177 +a90a305c2cd0f184787c6be596fa67f436afd1f9b93f30e875f817ac2aae8bdd2e6e656f6be809467e6b3ad84adb86b1 +80a9ef993c2b009ae172cc8f7ec036f5734cf4f4dfa06a7db4d54725e7fbfae5e3bc6f22687bdbb6961939d6f0c87537 +848ade1901931e72b955d7db1893f07003e1708ff5d93174bac5930b9a732640f0578839203e9b77eb27965c700032d3 +93fdf4697609c5ae9c33b9ca2f5f1af44abeb2b98dc4fdf732cf7388de086f410730dc384d9b7a7f447bb009653c8381 +89ce3fb805aea618b5715c0d22a9f46da696b6fa86794f56fdf1d44155a33d42daf1920bcbe36cbacf3cf4c92df9cbc7 +829ce2c342cf82aa469c65f724f308f7a750bd1494adc264609cd790c8718b8b25b5cab5858cf4ee2f8f651d569eea67 +af2f0cee7bf413204be8b9df59b9e4991bc9009e0d6dbe6815181df0ec2ca93ab8f4f3135b1c14d8f53d74bff0bd6f27 +b87998cecf7b88cde93d1779f10a521edd5574a2fbd240102978639ec57433ba08cdb53849038a329cebbe74657268d2 +a64542a1261a6ed3d720c2c3a802303aad8c4c110c95d0f12e05c1065e66f42da494792b6bfc5b9272363f3b1d457f58 +86a6fd042e4f282fadf07a4bfee03fc96a3aea49f7a00f52bf249a20f1ec892326855410e61f37fbb27d9305eb2fc713 +967ea5bc403b6db269682f7fd0df90659350d7e1aa66bc4fab4c9dfcd75ed0bba4b52f1cebc5f34dc8ba810793727629 +a52990f9f3b8616ce3cdc2c74cd195029e6a969753dcf2d1630438700e7d6ebde36538532b3525ac516f5f2ce9dd27a3 +a64f7ff870bab4a8bf0d4ef6f5c744e9bf1021ed08b4c80903c7ad318e80ba1817c3180cc45cb5a1cae1170f0241655f +b00f706fa4de1f663f021e8ad3d155e84ce6084a409374b6e6cd0f924a0a0b51bebaaaf1d228c77233a73b0a5a0df0e9 +8b882cc3bff3e42babdb96df95fb780faded84887a0a9bab896bef371cdcf169d909f5658649e93006aa3c6e1146d62e +9332663ef1d1dcf805c3d0e4ce7a07d9863fb1731172e766b3cde030bf81682cc011e26b773fb9c68e0477b4ae2cfb79 +a8aa8151348dbd4ef40aaeb699b71b4c4bfd3218560c120d85036d14f678f6736f0ec68e80ce1459d3d35feccc575164 +a16cd8b729768f51881c213434aa28301fa78fcb554ddd5f9012ee1e4eae7b5cb3dd88d269d53146dea92d10790faf0b +86844f0ef9d37142faf3b1e196e44fbe280a3ba4189aa05c356778cb9e3b388a2bff95eed305ada8769935c9974e4c57 +ae2eec6b328fccf3b47bcdac32901ac2744a51beb410b04c81dea34dee4912b619466a4f5e2780d87ecefaebbe77b46d +915df4c38d301c8a4eb2dc5b1ba0ffaad67cbb177e0a80095614e9c711f4ef24a4cef133f9d982a63d2a943ba6c8669d +ae6a2a4dedfc2d1811711a8946991fede972fdf2a389b282471280737536ffc0ac3a6d885b1f8bda0366eb0b229b9979 +a9b628c63d08b8aba6b1317f6e91c34b2382a6c85376e8ef2410a463c6796740ae936fc4e9e0737cb9455d1daa287bd8 +848e30bf7edf2546670b390d5cf9ab71f98fcb6add3c0b582cb34996c26a446dee5d1bde4fdcde4fc80c10936e117b29 +907d6096c7c8c087d1808dd995d5d2b9169b3768c3f433475b50c2e2bd4b082f4d543afd8b0b0ddffa9c66222a72d51d +a59970a2493b07339124d763ac9d793c60a03354539ecbcf6035bc43d1ea6e35718202ae6d7060b7d388f483d971573c +b9cfef2af9681b2318f119d8611ff6d9485a68d8044581b1959ab1840cbca576dbb53eec17863d2149966e9feb21122f +ad47271806161f61d3afa45cdfe2babceef5e90031a21779f83dc8562e6076680525b4970b2f11fe9b2b23c382768323 +8e425a99b71677b04fe044625d338811fbb8ee32368a424f6ab2381c52e86ee7a6cecedf777dc97181519d41c351bc22 +86b55b54d7adefc12954a9252ee23ae83efe8b5b4b9a7dc307904413e5d69868c7087a818b2833f9b004213d629be8ad +a14fda6b93923dd11e564ae4457a66f397741527166e0b16a8eb91c6701c244fd1c4b63f9dd3515193ec88fa6c266b35 +a9b17c36ae6cd85a0ed7f6cabc5b47dc8f80ced605db327c47826476dc1fb8f8669aa7a7dc679fbd4ee3d8e8b4bd6a6f +82a0829469c1458d959c821148f15dacae9ea94bf56c59a6ab2d4dd8b3d16d73e313b5a3912a6c1f131d73a8f06730c4 +b22d56d549a53eaef549595924bdb621ff807aa4513feedf3fdcbf7ba8b6b9cfa4481c2f67fc642db397a6b794a8b63a +974c59c24392e2cb9294006cbe3c52163e255f3bd0c2b457bdc68a6338e6d5b6f87f716854492f8d880a6b896ccf757c +b70d247ba7cad97c50b57f526c2ba915786e926a94e8f8c3eebc2e1be6f4255411b9670e382060049c8f4184302c40b2 +ad80201fe75ef21c3ddbd98cf23591e0d7a3ba1036dfe77785c32f44755a212c31f0ceb0a0b6f5ee9b6dc81f358d30c3 +8c656e841f9bb90b9a42d425251f3fdbc022a604d75f5845f479ed4be23e02aaf9e6e56cde351dd7449c50574818a199 +8b88dd3fa209d3063b7c5b058f7249ee9900fbc2287d16da61a0704a0a1d71e45d9c96e1cda7fdf9654534ec44558b22 +961da00cc8750bd84d253c08f011970ae1b1158ad6778e8ed943d547bceaf52d6d5a212a7de3bf2706688c4389b827d2 +a5dd379922549a956033e3d51a986a4b1508e575042b8eaa1df007aa77cf0b8c2ab23212f9c075702788fa9c53696133 +ac8fcfde3a349d1e93fc8cf450814e842005c545c4844c0401bc80e6b96cdb77f29285a14455e167c191d4f312e866cd +ac63d79c799783a8466617030c59dd5a8f92ee6c5204676fd8d881ce5f7f8663bdbeb0379e480ea9b6340ab0dc88e574 +805874fde19ce359041ae2bd52a39e2841acabfd31f965792f2737d7137f36d4e4722ede8340d8c95afa6af278af8acb +8d2f323a228aa8ba7b7dc1399138f9e6b41df1a16a7069003ab8104b8b68506a45141bc5fe66acf430e23e13a545190b +a1610c721a2d9af882bb6b39bea97cff1527a3aea041d25934de080214ae77c959e79957164440686d15ab301e897d4d +aba16d29a47fc36f12b654fde513896723e2c700c4190f11b26aa4011da57737ad717daa02794aa3246e4ae5f0b0cc3a +a406db2f15fdd135f346cc4846623c47edd195e80ba8c7cb447332095314d565e4040694ca924696bb5ee7f8996ea0ba +8b30e2cd9b47d75ba57b83630e40f832249af6c058d4f490416562af451993eec46f3e1f90bc4d389e4c06abd1b32a46 +aacf9eb7036e248e209adbfc3dd7ce386569ea9b312caa4b240726549db3c68c4f1c8cbf8ed5ea9ea60c7e57c9df3b8e +b20fcac63bf6f5ee638a42d7f89be847f348c085ddcbec3fa318f4323592d136c230495f188ef2022aa355cc2b0da6f9 +811eff750456a79ec1b1249d76d7c1547065b839d8d4aaad860f6d4528eb5b669473dcceeeea676cddbc3980b68461b7 +b52d14ae33f4ab422f953392ae76a19c618cc31afc96290bd3fe2fb44c954b5c92c4789f3f16e8793f2c0c1691ade444 +a7826dafeeba0db5b66c4dfcf2b17fd7b40507a5a53ac2e42942633a2cb30b95ba1739a6e9f3b7a0e0f1ec729bf274e2 +8acfd83ddf7c60dd7c8b20c706a3b972c65d336b8f9b3d907bdd8926ced271430479448100050b1ef17578a49c8fa616 +af0c69f65184bb06868029ad46f8465d75c36814c621ac20a5c0b06a900d59305584f5a6709683d9c0e4b6cd08d650a6 +b6cc8588191e00680ee6c3339bd0f0a17ad8fd7f4be57d5d7075bede0ea593a19e67f3d7c1a20114894ee5bfcab71063 +a82fd4f58635129dbb6cc3eb9391cf2d28400018b105fc41500fbbd12bd890b918f97d3d359c29dd3b4c4e34391dfab0 +92fc544ed65b4a3625cf03c41ddff7c039bc22d22c0d59dcc00efd5438401f2606adb125a1d5de294cca216ec8ac35a3 +906f67e4a32582b71f15940523c0c7ce370336935e2646bdaea16a06995256d25e99df57297e39d6c39535e180456407 +97510337ea5bbd5977287339197db55c60533b2ec35c94d0a460a416ae9f60e85cee39be82abeeacd5813cf54df05862 +87e6894643815c0ea48cb96c607266c5ee4f1f82ba5fe352fb77f9b6ed14bfc2b8e09e80a99ac9047dfcf62b2ae26795 +b6fd55dd156622ad7d5d51b7dde75e47bd052d4e542dd6449e72411f68275775c846dde301e84613312be8c7bce58b07 +b98461ac71f554b2f03a94e429b255af89eec917e208a8e60edf5fc43b65f1d17a20de3f31d2ce9f0cb573c25f2f4d98 +96f0dea40ca61cefbee41c4e1fe9a7d81fbe1f49bb153d083ab70f5d0488a1f717fd28cedcf6aa18d07cce2c62801898 +8d7c3ab310184f7dc34b6ce4684e4d29a31e77b09940448ea4daac730b7eb308063125d4dd229046cf11bfd521b771e0 +96f0564898fe96687918bbf0a6adead99cf72e3a35ea3347e124af9d006221f8e82e5a9d2fe80094d5e8d48e610f415e +ad50fcb92c2675a398cf07d4c40a579e44bf8d35f27cc330b57e54d5ea59f7d898af0f75dccfe3726e5471133d70f92b +828beed62020361689ae7481dd8f116902b522fb0c6c122678e7f949fdef70ead011e0e6bffd25678e388744e17cdb69 +8349decac1ca16599eee2efc95bcaabf67631107da1d34a2f917884bd70dfec9b4b08ab7bc4379d6c73b19c0b6e54fb8 +b2a6a2e50230c05613ace9e58bb2e98d94127f196f02d9dddc53c43fc68c184549ca12d713cb1b025d8260a41e947155 +94ff52181aadae832aed52fc3b7794536e2a31a21fc8be3ea312ca5c695750d37f08002f286b33f4023dba1e3253ecfa +a21d56153c7e5972ee9a319501be4faff199fdf09bb821ea9ce64aa815289676c00f105e6f00311b3a5b627091b0d0fc +a27a60d219f1f0c971db73a7f563b371b5c9fc3ed1f72883b2eac8a0df6698400c9954f4ca17d7e94e44bd4f95532afb +a2fc56fae99b1f18ba5e4fe838402164ce82f8a7f3193d0bbd360c2bac07c46f9330c4c7681ffb47074c6f81ee6e7ac6 +b748e530cd3afb96d879b83e89c9f1a444f54e55372ab1dcd46a0872f95ce8f49cf2363fc61be82259e04f555937ed16 +8bf8993e81080c7cbba1e14a798504af1e4950b2f186ab3335b771d6acaee4ffe92131ae9c53d74379d957cb6344d9cd +96774d0ef730d22d7ab6d9fb7f90b9ead44285219d076584a901960542756700a2a1603cdf72be4708b267200f6c36a9 +b47703c2ab17be1e823cc7bf3460db1d6760c0e33862c90ca058845b2ff234b0f9834ddba2efb2ee1770eb261e7d8ffd +84319e67c37a9581f8b09b5e4d4ae88d0a7fb4cbb6908971ab5be28070c3830f040b1de83ee663c573e0f2f6198640e4 +96811875fa83133e0b3c0e0290f9e0e28bca6178b77fdf5350eb19344d453dbd0d71e55a0ef749025a5a2ca0ad251e81 +81a423423e9438343879f2bfd7ee9f1c74ebebe7ce3cfffc8a11da6f040cc4145c3b527bd3cf63f9137e714dbcb474ef +b8c3535701ddbeec2db08e17a4fa99ba6752d32ece5331a0b8743676f421fcb14798afc7c783815484f14693d2f70db8 +81aee980c876949bf40782835eec8817d535f6f3f7e00bf402ddd61101fdcd60173961ae90a1cf7c5d060339a18c959d +87e67b928d97b62c49dac321ce6cb680233f3a394d4c9a899ac2e8db8ccd8e00418e66cdfd68691aa3cb8559723b580c +8eac204208d99a2b738648df96353bbb1b1065e33ee4f6bba174b540bbbd37d205855e1f1e69a6b7ff043ca377651126 +848e6e7a54ad64d18009300b93ea6f459ce855971dddb419b101f5ac4c159215626fadc20cc3b9ab1701d8f6dfaddd8b +88aa123d9e0cf309d46dddb6acf634b1ade3b090a2826d6e5e78669fa1220d6df9a6697d7778cd9b627db17eea846126 +9200c2a629b9144d88a61151b661b6c4256cc5dadfd1e59a8ce17a013c2d8f7e754aabe61663c3b30f1bc47784c1f8cf +b6e1a2827c3bdda91715b0e1b1f10dd363cef337e7c80cac1f34165fc0dea7c8b69747e310563db5818390146ce3e231 +92c333e694f89f0d306d54105b2a5dcc912dbe7654d9e733edab12e8537350815be472b063e56cfde5286df8922fdecb +a6fac04b6d86091158ebb286586ccfec2a95c9786e14d91a9c743f5f05546073e5e3cc717635a0c602cad8334e922346 +a581b4af77feebc1fb897d49b5b507c6ad513d8f09b273328efbb24ef0d91eb740d01b4d398f2738125dacfe550330cd +81c4860cccf76a34f8a2bc3f464b7bfd3e909e975cce0d28979f457738a56e60a4af8e68a3992cf273b5946e8d7f76e2 +8d1eaa09a3180d8af1cbaee673db5223363cc7229a69565f592fa38ba0f9d582cedf91e15dabd06ebbf2862fc0feba54 +9832f49b0147f4552402e54593cfa51f99540bffada12759b71fcb86734be8e500eea2d8b3d036710bdf04c901432de9 +8bdb0e8ec93b11e5718e8c13cb4f5de545d24829fd76161216340108098dfe5148ed25e3b57a89a516f09fa79043734d +ab96f06c4b9b0b2c0571740b24fca758e6976315053a7ecb20119150a9fa416db2d3a2e0f8168b390bb063f0c1caf785 +ab777f5c52acd62ecf4d1f168b9cc8e1a9b45d4ec6a8ff52c583e867c2239aba98d7d3af977289b367edce03d9c2dfb1 +a09d3ce5e748da84802436951acc3d3ea5d8ec1d6933505ed724d6b4b0d69973ab0930daec9c6606960f6e541e4a3ce2 +8ef94f7be4d85d5ad3d779a5cf4d7b2fc3e65c52fb8e1c3c112509a4af77a0b5be994f251e5e40fabeeb1f7d5615c22b +a7406a5bf5708d9e10922d3c5c45c03ef891b8d0d74ec9f28328a72be4cdc05b4f2703fa99366426659dfca25d007535 +b7f52709669bf92a2e070bfe740f422f0b7127392c5589c7f0af71bb5a8428697c762d3c0d74532899da24ea7d8695c2 +b9dfb0c8df84104dbf9239ccefa4672ef95ddabb8801b74997935d1b81a78a6a5669a3c553767ec19a1281f6e570f4ff +ae4d5c872156061ce9195ac640190d8d71dd406055ee43ffa6f9893eb24b870075b74c94d65bc1d5a07a6573282b5520 +afe6bd3eb72266d333f1807164900dcfa02a7eb5b1744bb3c86b34b3ee91e3f05e38fa52a50dc64eeb4bdb1dd62874b8 +948043cf1bc2ef3c01105f6a78dc06487f57548a3e6ef30e6ebc51c94b71e4bf3ff6d0058c72b6f3ecc37efd7c7fa8c0 +a22fd17c2f7ffe552bb0f23fa135584e8d2d8d75e3f742d94d04aded2a79e22a00dfe7acbb57d44e1cdb962fb22ae170 +8cd0f4e9e4fb4a37c02c1bde0f69359c43ab012eb662d346487be0c3758293f1ca560122b059b091fddce626383c3a8f +90499e45f5b9c81426f3d735a52a564cafbed72711d9279fdd88de8038e953bc48c57b58cba85c3b2e4ce56f1ddb0e11 +8c30e4c034c02958384564cac4f85022ef36ab5697a3d2feaf6bf105049675bbf23d01b4b6814711d3d9271abff04cac +81f7999e7eeea30f3e1075e6780bbf054f2fb6f27628a2afa4d41872a385b4216dd5f549da7ce6cf39049b2251f27fb7 +b36a7191f82fc39c283ffe53fc1f5a9a00b4c64eee7792a8443475da9a4d226cf257f226ea9d66e329af15d8f04984ec +aad4da528fdbb4db504f3041c747455baff5fcd459a2efd78f15bdf3aea0bdb808343e49df88fe7a7c8620009b7964a3 +99ebd8c6dd5dd299517fb6381cfc2a7f443e6e04a351440260dd7c2aee3f1d8ef06eb6c18820b394366ecdfd2a3ce264 +8873725b81871db72e4ec3643084b1cdce3cbf80b40b834b092767728605825c19b6847ad3dcf328438607e8f88b4410 +b008ee2f895daa6abd35bd39b6f7901ae4611a11a3271194e19da1cdcc7f1e1ea008fe5c5440e50d2c273784541ad9c5 +9036feafb4218d1f576ef89d0e99124e45dacaa6d816988e34d80f454d10e96809791d5b78f7fd65f569e90d4d7238c5 +92073c1d11b168e4fa50988b0288638b4868e48bbc668c5a6dddf5499875d53be23a285acb5e4bad60114f6cf6c556e9 +88c87dfcb8ba6cbfe7e1be081ccfadbd589301db2cb7c99f9ee5d7db90aa297ed1538d5a867678a763f2deede5fd219a +b42a562805c661a50f5dea63108002c0f27c0da113da6a9864c9feb5552225417c0356c4209e8e012d9bcc9d182c7611 +8e6317d00a504e3b79cd47feb4c60f9df186467fe9ca0f35b55c0364db30528f5ff071109dabb2fc80bb9cd4949f0c24 +b7b1ea6a88694f8d2f539e52a47466695e39e43a5eb9c6f23bca15305fe52939d8755cc3ac9d6725e60f82f994a3772f +a3cd55161befe795af93a38d33290fb642b8d80da8b786c6e6fb02d393ea308fbe87f486994039cbd7c7b390414594b6 +b416d2d45b44ead3b1424e92c73c2cf510801897b05d1724ff31cbd741920cd858282fb5d6040fe1f0aa97a65bc49424 +950ee01291754feace97c2e933e4681e7ddfbc4fcd079eb6ff830b0e481d929c93d0c7fb479c9939c28ca1945c40da09 +869bd916aee8d86efe362a49010382674825d49195b413b4b4018e88ce43fe091b475d0b863ff0ba2259400f280c2b23 +9782f38cd9c9d3385ec286ebbc7cba5b718d2e65a5890b0a5906b10a89dc8ed80d417d71d7c213bf52f2af1a1f513ea7 +91cd33bc2628d096269b23faf47ee15e14cb7fdc6a8e3a98b55e1031ea0b68d10ba30d97e660f7e967d24436d40fad73 +8becc978129cc96737034c577ae7225372dd855da8811ae4e46328e020c803833b5bdbc4a20a93270e2b8bd1a2feae52 +a36b1d8076783a9522476ce17f799d78008967728ce920531fdaf88303321bcaf97ecaa08e0c01f77bc32e53c5f09525 +b4720e744943f70467983aa34499e76de6d59aa6fadf86f6b787fdce32a2f5b535b55db38fe2da95825c51002cfe142d +91ad21fc502eda3945f6de874d1b6bf9a9a7711f4d61354f9e5634fc73f9c06ada848de15ab0a75811d3250be862827d +84f78e2ebf5fc077d78635f981712daf17e2475e14c2a96d187913006ad69e234746184a51a06ef510c9455b38acb0d7 +960aa7906e9a2f11db64a26b5892ac45f20d2ccb5480f4888d89973beb6fa0dfdc06d68d241ff5ffc7f1b82b1aac242d +a99365dcd1a00c66c9db6924b97c920f5c723380e823b250db85c07631b320ec4e92e586f7319e67a522a0578f7b6d6c +a25d92d7f70cf6a88ff317cfec071e13774516da664f5fac0d4ecaa65b8bf4eb87a64a4d5ef2bd97dfae98d388dbf5cc +a7af47cd0041295798f9779020a44653007444e8b4ef0712982b06d0dcdd434ec4e1f7c5f7a049326602cb605c9105b7 +aefe172eac5568369a05980931cc476bebd9dea573ba276d59b9d8c4420784299df5a910033b7e324a6c2dfc62e3ef05 +b69bc9d22ffa645baa55e3e02522e9892bb2daa7fff7c15846f13517d0799766883ee09ae0869df4139150c5b843ca8a +95a10856140e493354fdd12722c7fdded21b6a2ffbc78aa2697104af8ad0c8e2206f44b0bfee077ef3949d46bbf7c16b +891f2fcd2c47cbea36b7fa715968540c233313f05333f09d29aba23c193f462ed490dd4d00969656e89c53155fdfe710 +a6c33e18115e64e385c843dde34e8a228222795c7ca90bc2cc085705d609025f3351d9be61822c69035a49fb3e48f2d5 +b87fb12f12c0533b005adad0487f03393ff682e13575e3cb57280c3873b2c38ba96a63c49eef7a442753d26b7005230b +b905c02ba451bfd411c135036d92c27af3b0b1c9c2f1309d6948544a264b125f39dd41afeff4666b12146c545adc168a +8b29c513f43a78951cf742231cf5457a6d9d55edf45df5481a0f299a418d94effef561b15d2c1a01d1b8067e7153fda9 +b9941cccd51dc645920d2781c81a317e5a33cb7cf76427b60396735912cb6d2ca9292bb4d36b6392467d390d2c58d9f3 +a8546b627c76b6ef5c93c6a98538d8593dbe21cb7673fd383d5401b0c935eea0bdeeefeb1af6ad41bad8464fb87bbc48 +aa286b27de2812de63108a1aec29d171775b69538dc6198640ac1e96767c2b83a50391f49259195957d457b493b667c9 +a932fb229f641e9abbd8eb2bd874015d97b6658ab6d29769fc23b7db9e41dd4f850382d4c1f08af8f156c5937d524473 +a1412840fcc86e2aeec175526f2fb36e8b3b8d21a78412b7266daf81e51b3f68584ed8bd42a66a43afdd8c297b320520 +89c78be9efb624c97ebca4fe04c7704fa52311d183ffd87737f76b7dadc187c12c982bd8e9ed7cd8beb48cdaafd2fd01 +a3f5ddec412a5bec0ce15e3bcb41c6214c2b05d4e9135a0d33c8e50a78eaba71e0a5a6ea8b45854dec5c2ed300971fc2 +9721f9cec7a68b7758e3887548790de49fa6a442d0396739efa20c2f50352a7f91d300867556d11a703866def2d5f7b5 +a23764e140a87e5991573521af039630dd28128bf56eed2edbed130fd4278e090b60cf5a1dca9de2910603d44b9f6d45 +a1a6494a994215e48ab55c70efa8ffdddce6e92403c38ae7e8dd2f8288cad460c6c7db526bbdf578e96ca04d9fe12797 +b1705ea4cb7e074efe0405fc7b8ee2ec789af0426142f3ec81241cacd4f7edcd88e39435e4e4d8e7b1df64f3880d6613 +85595d061d677116089a6064418b93eb44ff79e68d12bd9625078d3bbc440a60d0b02944eff6054433ee34710ae6fbb4 +9978d5e30bedb7526734f9a1febd973a70bfa20890490e7cc6f2f9328feab1e24f991285dbc3711d892514e2d7d005ad +af30243c66ea43b9f87a061f947f7bce745f09194f6e95f379c7582b9fead920e5d6957eaf05c12ae1282ada4670652f +a1930efb473f88001e47aa0b2b2a7566848cccf295792e4544096ecd14ee5d7927c173a8576b405bfa2eec551cd67eb5 +b0446d1c590ee5a45f7e22d269c044f3848c97aec1d226b44bfd0e94d9729c28a38bccddc3a1006cc5fe4e3c24f001f2 +b8a8380172df3d84b06176df916cf557966d4f2f716d3e9437e415d75b646810f79f2b2b71d857181b7fc944018883a3 +a563afec25b7817bfa26e19dc9908bc00aa8fc3d19be7d6de23648701659009d10e3e4486c28e9c6b13d48231ae29ac5 +a5a8e80579de886fb7d6408f542791876885947b27ad6fa99a8a26e381f052598d7b4e647b0115d4b5c64297e00ce28e +8f87afcc7ad33c51ac719bade3cd92da671a37a82c14446b0a2073f4a0a23085e2c8d31913ed2d0be928f053297de8f6 +a43c455ce377e0bc434386c53c752880687e017b2f5ae7f8a15c044895b242dffde4c92fb8f8bb50b18470b17351b156 +8368f8b12a5bceb1dba25adb3a2e9c7dc9b1a77a1f328e5a693f5aec195cd1e06b0fe9476b554c1c25dac6c4a5b640a3 +919878b27f3671fc78396f11531c032f3e2bd132d04cc234fa4858676b15fb1db3051c0b1db9b4fc49038216f11321ce +b48cd67fb7f1242696c1f877da4bdf188eac676cd0e561fbac1a537f7b8229aff5a043922441d603a26aae56a15faee4 +a3e0fdfd4d29ea996517a16f0370b54787fefe543c2fe73bfc6f9e560c1fd30dad8409859e2d7fa2d44316f24746c712 +8bb156ade8faf149df7bea02c140c7e392a4742ae6d0394d880a849127943e6f26312033336d3b9fdc0092d71b5efe87 +8845e5d5cc555ca3e0523244300f2c8d7e4d02aaebcb5bd749d791208856c209a6f84dd99fd55968c9f0ab5f82916707 +a3e90bb5c97b07789c2f32dff1aec61d0a2220928202f5ad5355ae71f8249237799d6c8a22602e32e572cb12eabe0c17 +b150bcc391884c996149dc3779ce71f15dda63a759ee9cc05871f5a8379dcb62b047098922c0f26c7bd04deb394c33f9 +95cd4ad88d51f0f2efcfd0c2df802fe252bb9704d1afbf9c26a248df22d55da87bdfaf41d7bc6e5df38bd848f0b13f42 +a05a49a31e91dff6a52ac8b9c2cfdd646a43f0d488253f9e3cfbce52f26667166bbb9b608fc358763a65cbf066cd6d05 +a59c3c1227fdd7c2e81f5e11ef5c406da44662987bac33caed72314081e2eed66055d38137e01b2268e58ec85dd986c0 +b7020ec3bd73a99861f0f1d88cf5a19abab1cbe14b7de77c9868398c84bb8e18dbbe9831838a96b6d6ca06e82451c67b +98d1ff2525e9718ee59a21d8900621636fcd873d9a564b8dceb4be80a194a0148daf1232742730b3341514b2e5a5436c +886d97b635975fc638c1b6afc493e5998ca139edba131b75b65cfe5a8e814f11bb678e0eeee5e6e5cd913ad3f2fefdfc +8fb9fd928d38d5d813b671c924edd56601dd7163b686c13f158645c2f869d9250f3859aa5463a39258c90fef0f41190a +aac35e1cd655c94dec3580bb3800bd9c2946c4a9856f7d725af15fbea6a2d8ca51c8ad2772abed60ee0e3fb9cb24046b +b8d71fa0fa05ac9e443c9b4929df9e7f09a919be679692682e614d24227e04894bfc14a5c73a62fb927fedff4a0e4aa7 +a45a19f11fbbb531a704badbb813ed8088ab827c884ee4e4ebf363fa1132ff7cfa9d28be9c85b143e4f7cdbc94e7cf1a +82b54703a4f295f5471b255ab59dce00f0fe90c9fb6e06b9ee48b15c91d43f4e2ef4a96c3118aeb03b08767be58181bb +8283264c8e6d2a36558f0d145c18576b6600ff45ff99cc93eca54b6c6422993cf392668633e5df396b9331e873d457e5 +8c549c03131ead601bc30eb6b9537b5d3beb7472f5bb1bcbbfd1e9f3704477f7840ab3ab7f7dc13bbbbcdff886a462d4 +afbb0c520ac1b5486513587700ad53e314cb74bfbc12e0b5fbdcfdaac36d342e8b59856196a0d84a25cff6e6e1d17e76 +89e4c22ffb51f2829061b3c7c1983c5c750cad158e3a825d46f7cf875677da5d63f653d8a297022b5db5845c9271b32b +afb27a86c4c2373088c96b9adf4433f2ebfc78ac5c526e9f0510670b6e4e5e0057c0a4f75b185e1a30331b9e805c1c15 +a18e16b57445f88730fc5d3567bf5a176861dc14c7a08ed2996fe80eed27a0e7628501bcb78a1727c5e9ac55f29c12c4 +93d61bf88b192d6825cf4e1120af1c17aa0f994d158b405e25437eaeefae049f7b721a206e7cc8a04fdc29d3c42580a1 +a99f2995a2e3ed2fd1228d64166112038de2f516410aa439f4c507044e2017ea388604e2d0f7121256fadf7fbe7023d1 +914fd91cffc23c32f1c6d0e98bf660925090d873367d543034654389916f65f552e445b0300b71b61b721a72e9a5983c +b42a578a7787b71f924e7def425d849c1c777156b1d4170a8ee7709a4a914e816935131afd9a0412c4cb952957b20828 +82fb30590e84b9e45db1ec475a39971cf554dc01bcc7050bc89265740725c02e2be5a972168c5170c86ae83e5b0ad2c0 +b14f8d8e1e93a84976289e0cf0dfa6f3a1809e98da16ee5c4932d0e1ed6bf8a07697fdd4dd86a3df84fb0003353cdcc0 +85d7a2f4bda31aa2cb208b771fe03291a4ebdaf6f1dc944c27775af5caec412584c1f45bc741fca2a6a85acb3f26ad7d +af02e56ce886ff2253bc0a68faad76f25ead84b2144e5364f3fb9b648f03a50ee9dc0b2c33ebacf7c61e9e43201ef9ef +87e025558c8a0b0abd06dfc350016847ea5ced7af2d135a5c9eec9324a4858c4b21510fb0992ec52a73447f24945058e +80fff0bafcd058118f5e7a4d4f1ae0912efeb281d2cbe4d34ba8945cc3dbe5d8baf47fb077343b90b8d895c90b297aca +b6edcf3a40e7b1c3c0148f47a263cd819e585a51ef31c2e35a29ce6f04c53e413f743034c0d998d9c00a08ba00166f31 +abb87ed86098c0c70a76e557262a494ff51a30fb193f1c1a32f8e35eafa34a43fcc07aa93a3b7a077d9e35afa07b1a3d +a280214cd3bb0fb7ecd2d8bcf518cbd9078417f2b91d2533ec2717563f090fb84f2a5fcfdbbeb2a2a1f8a71cc5aa5941 +a63083ca7238ea2b57d15a475963cf1d4f550d8cd76db290014a0461b90351f1f26a67d674c837b0b773b330c7c3d534 +a8fa39064cb585ece5263e2f42f430206476bf261bd50f18d2b694889bd79d04d56410664cecad62690e5c5a20b3f6ff +85ba52ce9d700a5dcf6c5b00559acbe599d671ce5512467ff4b6179d7fad550567ce2a9c126a50964e3096458ea87920 +b913501e1008f076e5eac6d883105174f88b248e1c9801e568fefaffa1558e4909364fc6d9512aa4d125cbd7cc895f05 +8eb33b5266c8f2ed4725a6ad147a322e44c9264cf261c933cbbe230a43d47fca0f29ec39756b20561dabafadd5796494 +850ebc8b661a04318c9db5a0515066e6454fa73865aa4908767a837857ecd717387f614acb614a88e075d4edc53a2f5a +a08d6b92d866270f29f4ce23a3f5d99b36b1e241a01271ede02817c8ec3f552a5c562db400766c07b104a331835c0c64 +8131804c89bb3e74e9718bfc4afa547c1005ff676bd4db9604335032b203390cfa54478d45c6c78d1fe31a436ed4be9f +9106d94f23cc1eacec8316f16d6f0a1cc160967c886f51981fdb9f3f12ee1182407d2bb24e5b873de58cb1a3ee915a6b +a13806bfc3eae7a7000c9d9f1bd25e10218d4e67f59ae798b145b098bca3edad2b1040e3fc1e6310e612fb8818f459ac +8c69fbca502046cb5f6db99900a47b34117aef3f4b241690cdb3b84ca2a2fc7833e149361995dc41fa78892525bce746 +852c473150c91912d58ecb05769222fa18312800c3f56605ad29eec9e2d8667b0b81c379048d3d29100ed2773bb1f3c5 +b1767f6074426a00e01095dbb1795beb4e4050c6411792cbad6537bc444c3165d1058bafd1487451f9c5ddd209e0ae7e +80c600a5fe99354ce59ff0f84c760923dc8ff66a30bf47dc0a086181785ceb01f9b951c4e66df800ea6d705e8bc47055 +b5cf19002fbc88a0764865b82afcb4d64a50196ea361e5c71dff7de084f4dcbbc34ec94a45cc9e0247bd51da565981aa +93e67a254ea8ce25e112d93cc927fadaa814152a2c4ec7d9a56eaa1ed47aec99b7e9916b02e64452cc724a6641729bbb +ace70b32491bda18eee4a4d041c3bc9effae9340fe7e6c2f5ad975ee0874c17f1a7da7c96bd85fccff9312c518fac6e9 +ab4cfa02065017dd7f1aadc66f2c92f78f0f11b8597c03a5d69d82cb2eaf95a4476a836ac102908f137662472c8d914b +a40b8cd8deb8ae503d20364d64cab7c2801b7728a9646ed19c65edea6a842756a2f636283494299584ad57f4bb12cd0b +8594e11d5fc2396bcd9dbf5509ce4816dbb2b7305168021c426171fb444d111da5a152d6835ad8034542277011c26c0e +8024de98c26b4c994a66628dc304bb737f4b6859c86ded552c5abb81fd4c6c2e19d5a30beed398a694b9b2fdea1dd06a +8843f5872f33f54df8d0e06166c1857d733995f67bc54abb8dfa94ad92407cf0179bc91b0a50bbb56cdc2b350d950329 +b8bab44c7dd53ef9edf497dcb228e2a41282c90f00ba052fc52d57e87b5c8ab132d227af1fcdff9a12713d1f980bcaae +982b4d7b29aff22d527fd82d2a52601d95549bfb000429bb20789ed45e5abf1f4b7416c7b7c4b79431eb3574b29be658 +8eb1f571b6a1878e11e8c1c757e0bc084bab5e82e897ca9be9b7f4b47b91679a8190bf0fc8f799d9b487da5442415857 +a6e74b588e5af935c8b243e888582ef7718f8714569dd4992920740227518305eb35fab674d21a5551cca44b3e511ef2 +a30fc2f3a4cb4f50566e82307de73cd7bd8fe2c1184e9293c136a9b9e926a018d57c6e4f308c95b9eb8299e94d90a2a1 +a50c5869ca5d2b40722c056a32f918d47e0b65ca9d7863ca7d2fb4a7b64fe523fe9365cf0573733ceaadebf20b48fff8 +83bbdd32c04d17581418cf360749c7a169b55d54f2427390defd9f751f100897b2d800ce6636c5bbc046c47508d60c8c +a82904bdf614de5d8deaff688c8a5e7ac5b3431687acbcda8fa53960b7c417a39c8b2e462d7af91ce6d79260f412db8e +a4362e31ff4b05d278b033cf5eebea20de01714ae16d4115d04c1da4754269873afc8171a6f56c5104bfd7b0db93c3e7 +b5b8daa63a3735581e74a021b684a1038cea77168fdb7fdf83c670c2cfabcfc3ab2fc7359069b5f9048188351aef26b5 +b48d723894b7782d96ac8433c48faca1bdfa5238019c451a7f47d958097cce3ae599b876cf274269236b9d6ff8b6d7ca +98ffff6a61a3a6205c7820a91ca2e7176fab5dba02bc194c4d14942ac421cb254183c705506ab279e4f8db066f941c6c +ae7db24731da2eaa6efc4f7fcba2ecc26940ddd68038dce43acf2cee15b72dc4ef42a7bfdd32946d1ed78786dd7696b3 +a656db14f1de9a7eb84f6301b4acb2fbf78bfe867f48a270e416c974ab92821eb4df1cb881b2d600cfed0034ac784641 +aa315f8ecba85a5535e9a49e558b15f39520fce5d4bf43131bfbf2e2c9dfccc829074f9083e8d49f405fb221d0bc4c3c +90bffba5d9ff40a62f6c8e9fc402d5b95f6077ed58d030c93e321b8081b77d6b8dac3f63a92a7ddc01585cf2c127d66c +abdd733a36e0e0f05a570d0504e73801bf9b5a25ff2c78786f8b805704997acb2e6069af342538c581144d53149fa6d3 +b4a723bb19e8c18a01bd449b1bb3440ddb2017f10bb153da27deb7a6a60e9bb37619d6d5435fbb1ba617687838e01dd0 +870016b4678bab3375516db0187a2108b2e840bae4d264b9f4f27dbbc7cc9cac1d7dc582d7a04d6fd1ed588238e5e513 +80d33d2e20e8fc170aa3cb4f69fffb72aeafb3b5bb4ea0bc79ab55da14142ca19b2d8b617a6b24d537366e3b49cb67c3 +a7ee76aec273aaae03b3b87015789289551969fb175c11557da3ab77e39ab49d24634726f92affae9f4d24003050d974 +8415ea4ab69d779ebd42d0fe0c6aef531d6a465a5739e429b1fcf433ec45aa8296c527e965a20f0ec9f340c9273ea3cf +8c7662520794e8b4405d0b33b5cac839784bc86a5868766c06cbc1fa306dbe334978177417b31baf90ce7b0052a29c56 +902b2abecc053a3dbdea9897ee21e74821f3a1b98b2d560a514a35799f4680322550fd3a728d4f6d64e1de98033c32b8 +a05e84ed9ecab8d508d670c39f2db61ad6e08d2795ec32a3c9d0d3737ef3801618f4fc2a95f90ec2f068606131e076c5 +8b9208ff4d5af0c2e3f53c9375da666773ac57197dfabb0d25b1c8d0588ba7f3c15ee9661bb001297f322ea2fbf6928b +a3c827741b34a03254d4451b5ab74a96f2b9f7fb069e2f5adaf54fd97cc7a4d516d378db5ca07da87d8566d6eef13726 +8509d8a3f4a0ed378e0a1e28ea02f6bf1d7f6c819c6c2f5297c7df54c895b848f841653e32ba2a2c22c2ff739571acb8 +a0ce988b7d3c40b4e496aa83a09e4b5472a2d98679622f32bea23e6d607bc7de1a5374fb162bce0549a67dad948519be +aa8a3dd12bd60e3d2e05f9c683cdcb8eab17fc59134815f8d197681b1bcf65108cba63ac5c58ee632b1e5ed6bba5d474 +8b955f1d894b3aefd883fb4b65f14cd37fc2b9db77db79273f1700bef9973bf3fd123897ea2b7989f50003733f8f7f21 +ac79c00ddac47f5daf8d9418d798d8af89fc6f1682e7e451f71ea3a405b0d36af35388dd2a332af790bc83ca7b819328 +a0d44dd2a4438b809522b130d0938c3fe7c5c46379365dbd1810a170a9aa5818e1c783470dd5d0b6d4ac7edbb7330910 +a30b69e39ad43dd540a43c521f05b51b5f1b9c4eed54b8162374ae11eac25da4f5756e7b70ce9f3c92c2eeceee7431ed +ac43220b762c299c7951222ea19761ab938bf38e4972deef58ed84f4f9c68c230647cf7506d7cbfc08562fcca55f0485 +b28233b46a8fb424cfa386a845a3b5399d8489ceb83c8f3e05c22c934798d639c93718b7b68ab3ce24c5358339e41cbb +ac30d50ee8ce59a10d4b37a3a35e62cdb2273e5e52232e202ca7d7b8d09d28958ee667fae41a7bb6cdc6fe8f6e6c9c85 +b199842d9141ad169f35cc7ff782b274cbaa645fdb727761e0a89edbf0d781a15f8218b4bf4eead326f2903dd88a9cc1 +85e018c7ddcad34bb8285a737c578bf741ccd547e68c734bdb3808380e12c5d4ef60fc896b497a87d443ff9abd063b38 +8c856e6ba4a815bdb891e1276f93545b7072f6cb1a9aa6aa5cf240976f29f4dee01878638500a6bf1daf677b96b54343 +b8a47555fa8710534150e1a3f13eab33666017be6b41005397afa647ea49708565f2b86b77ad4964d140d9ced6b4d585 +8cd1f1db1b2f4c85a3f46211599caf512d5439e2d8e184663d7d50166fd3008f0e9253272f898d81007988435f715881 +b1f34b14612c973a3eceb716dc102b82ab18afef9de7630172c2780776679a7706a4874e1df3eaadf541fb009731807f +b25464af9cff883b55be2ff8daf610052c02df9a5e147a2cf4df6ce63edcdee6dc535c533590084cc177da85c5dc0baa +91c3c4b658b42d8d3448ae1415d4541d02379a40dc51e36a59bd6e7b9ba3ea51533f480c7c6e8405250ee9b96a466c29 +86dc027b95deb74c36a58a1333a03e63cb5ae22d3b29d114cfd2271badb05268c9d0c819a977f5e0c6014b00c1512e3a +ae0e6ff58eb5fa35da5107ebeacf222ab8f52a22bb1e13504247c1dfa65320f40d97b0e6b201cb6613476687cb2f0681 +8f13415d960b9d7a1d93ef28afc2223e926639b63bdefce0f85e945dfc81670a55df288893a0d8b3abe13c5708f82f91 +956f67ca49ad27c1e3a68c1faad5e7baf0160c459094bf6b7baf36b112de935fdfd79fa4a9ea87ea8de0ac07272969f4 +835e45e4a67df9fb51b645d37840b3a15c171d571a10b03a406dd69d3c2f22df3aa9c5cbe1e73f8d767ce01c4914ea9a +919b938e56d4b32e2667469d0bdccb95d9dda3341aa907683ee70a14bbbe623035014511c261f4f59b318b610ac90aa3 +96b48182121ccd9d689bf1dfdc228175564cd68dc904a99c808a7f0053a6f636c9d953e12198bdf2ea49ea92772f2e18 +ac5e5a941d567fa38fdbcfa8cf7f85bb304e3401c52d88752bcd516d1fa9bac4572534ea2205e38423c1df065990790f +ac0bd594fb85a8d4fc26d6df0fa81f11919401f1ecf9168b891ec7f061a2d9368af99f7fd8d9b43b2ce361e7b8482159 +83d92c69ca540d298fe80d8162a1c7af3fa9b49dfb69e85c1d136a3ec39fe419c9fa78e0bb6d96878771fbd37fe92e40 +b35443ae8aa66c763c2db9273f908552fe458e96696b90e41dd509c17a5c04ee178e3490d9c6ba2dc0b8f793c433c134 +923b2d25aa45b2e580ffd94cbb37dc8110f340f0f011217ee1bd81afb0714c0b1d5fb4db86006cdd2457563276f59c59 +96c9125d38fca1a61ac21257b696f8ac3dae78def50285e44d90ea293d591d1c58f703540a7e4e99e070afe4646bbe15 +b57946b2332077fbcdcb406b811779aefd54473b5559a163cd65cb8310679b7e2028aa55c12a1401fdcfcac0e6fae29a +845daedc5cf972883835d7e13c937b63753c2200324a3b8082a6c4abb4be06c5f7c629d4abe4bfaf1d80a1f073eb6ce6 +91a55dfd0efefcd03dc6dacc64ec93b8d296cb83c0ee72400a36f27246e7f2a60e73b7b70ba65819e9cfb73edb7bd297 +8874606b93266455fe8fdd25df9f8d2994e927460af06f2e97dd4d2d90db1e6b06d441b72c2e76504d753badca87fb37 +8ee99e6d231274ff9252c0f4e84549da173041299ad1230929c3e3d32399731c4f20a502b4a307642cac9306ccd49d3c +8836497714a525118e20849d6933bb8535fb6f72b96337d49e3133d936999c90a398a740f42e772353b5f1c63581df6d +a6916945e10628f7497a6cdc5e2de113d25f7ade3e41e74d3de48ccd4fce9f2fa9ab69645275002e6f49399b798c40af +9597706983107eb23883e0812e1a2c58af7f3499d50c6e29b455946cb9812fde1aa323d9ed30d1c0ffd455abe32303cd +a24ee89f7f515cc33bdbdb822e7d5c1877d337f3b2162303cfc2dae028011c3a267c5cb4194afa63a4856a6e1c213448 +8cd25315e4318801c2776824ae6e7d543cb85ed3bc2498ba5752df2e8142b37653cf9e60104d674be3aeb0a66912e97a +b5085ecbe793180b40dbeb879f4c976eaaccaca3a5246807dced5890e0ed24d35f3f86955e2460e14fb44ff5081c07ba +960188cc0b4f908633a6840963a6fa2205fc42c511c6c309685234911c5304ef4c304e3ae9c9c69daa2fb6a73560c256 +a32d0a70bf15d569b4cda5aebe3e41e03c28bf99cdd34ffa6c5d58a097f322772acca904b3a47addb6c7492a7126ebac +977f72d06ad72d4aa4765e0f1f9f4a3231d9f030501f320fe7714cc5d329d08112789fa918c60dd7fdb5837d56bb7fc6 +99fa038bb0470d45852bb871620d8d88520adb701712fcb1f278fed2882722b9e729e6cdce44c82caafad95e37d0e6f7 +b855e8f4fc7634ada07e83b6c719a1e37acb06394bc8c7dcab7747a8c54e5df3943915f021364bd019fdea103864e55f +88bc2cd7458532e98c596ef59ea2cf640d7cc31b4c33cef9ed065c078d1d4eb49677a67de8e6229cc17ea48bace8ee5a +aaa78a3feaa836d944d987d813f9b9741afb076e6aca1ffa42682ab06d46d66e0c07b8f40b9dbd63e75e81efa1ef7b08 +b7b080420cc4d808723b98b2a5b7b59c81e624ab568ecdfdeb8bf3aa151a581b6f56e983ef1b6f909661e25db40b0c69 +abee85c462ac9a2c58e54f06c91b3e5cd8c5f9ab5b5deb602b53763c54826ed6deb0d6db315a8d7ad88733407e8d35e2 +994d075c1527407547590df53e9d72dd31f037c763848d1662eebd4cefec93a24328c986802efa80e038cb760a5300f5 +ab8777640116dfb6678e8c7d5b36d01265dfb16321abbfc277da71556a34bb3be04bc4ae90124ed9c55386d2bfb3bda0 +967e3a828bc59409144463bcf883a3a276b5f24bf3cbfdd7a42343348cba91e00b46ac285835a9b91eef171202974204 +875a9f0c4ffe5bb1d8da5e3c8e41d0397aa6248422a628bd60bfae536a651417d4e8a7d2fb98e13f2dad3680f7bd86d3 +acaa330c3e8f95d46b1880126572b238dbb6d04484d2cd4f257ab9642d8c9fc7b212188b9c7ac9e0fd135c520d46b1bf +aceb762edbb0f0c43dfcdb01ea7a1ac5918ca3882b1e7ebc4373521742f1ed5250d8966b498c00b2b0f4d13212e6dd0b +81d072b4ad258b3646f52f399bced97c613b22e7ad76373453d80b1650c0ca87edb291a041f8253b649b6e5429bb4cff +980a47d27416ac39c7c3a0ebe50c492f8c776ea1de44d5159ac7d889b6d554357f0a77f0e5d9d0ff41aae4369eba1fc2 +8b4dfd5ef5573db1476d5e43aacfb5941e45d6297794508f29c454fe50ea622e6f068b28b3debe8635cf6036007de2e3 +a60831559d6305839515b68f8c3bc7abbd8212cc4083502e19dd682d56ca37c9780fc3ce4ec2eae81ab23b221452dc57 +951f6b2c1848ced9e8a2339c65918e00d3d22d3e59a0a660b1eca667d18f8430d737884e9805865ef3ed0fe1638a22d9 +b02e38fe790b492aa5e89257c4986c9033a8b67010fa2add9787de857d53759170fdd67715ca658220b4e14b0ca48124 +a51007e4346060746e6b0e4797fc08ef17f04a34fe24f307f6b6817edbb8ce2b176f40771d4ae8a60d6152cbebe62653 +a510005b05c0b305075b27b243c9d64bcdce85146b6ed0e75a3178b5ff9608213f08c8c9246f2ca6035a0c3e31619860 +aaff4ef27a7a23be3419d22197e13676d6e3810ceb06a9e920d38125745dc68a930f1741c9c2d9d5c875968e30f34ab5 +864522a9af9857de9814e61383bebad1ba9a881696925a0ea6bfc6eff520d42c506bbe5685a9946ed710e889765be4a0 +b63258c080d13f3b7d5b9f3ca9929f8982a6960bdb1b0f8676f4dca823971601672f15e653917bf5d3746bb220504913 +b51ce0cb10869121ae310c7159ee1f3e3a9f8ad498827f72c3d56864808c1f21fa2881788f19ece884d3f705cd7bd0c5 +95d9cecfc018c6ed510e441cf84c712d9909c778c16734706c93222257f64dcd2a9f1bd0b400ca271e22c9c487014274 +8beff4d7d0140b86380ff4842a9bda94c2d2be638e20ac68a4912cb47dbe01a261857536375208040c0554929ced1ddc +891ff49258749e2b57c1e9b8e04b12c77d79c3308b1fb615a081f2aacdfb4b39e32d53e069ed136fdbd43c53b87418fa +9625cad224e163d387738825982d1e40eeff35fe816d10d7541d15fdc4d3eee48009090f3faef4024b249205b0b28f72 +8f3947433d9bd01aa335895484b540a9025a19481a1c40b4f72dd676bfcf332713714fd4010bde936eaf9470fd239ed0 +a00ec2d67789a7054b53f0e858a8a232706ccc29a9f3e389df7455f1a51a2e75801fd78469a13dbc25d28399ae4c6182 +a3f65884506d4a62b8775a0ea0e3d78f5f46bc07910a93cd604022154eabdf1d73591e304d61edc869e91462951975e1 +a14eef4fd5dfac311713f0faa9a60415e3d30b95a4590cbf95f2033dffb4d16c02e7ceff3dcd42148a4e3bc49cce2dd4 +8afa11c0eef3c540e1e3460bc759bb2b6ea90743623f88e62950c94e370fe4fd01c22b6729beba4dcd4d581198d9358f +afb05548a69f0845ffcc5f5dc63e3cdb93cd270f5655173b9a950394b0583663f2b7164ba6df8d60c2e775c1d9f120af +97f179e01a947a906e1cbeafa083960bc9f1bade45742a3afee488dfb6011c1c6e2db09a355d77f5228a42ccaa7bdf8e +8447fca4d35f74b3efcbd96774f41874ca376bf85b79b6e66c92fa3f14bdd6e743a051f12a7fbfd87f319d1c6a5ce217 +a57ca39c23617cd2cf32ff93b02161bd7baf52c4effb4679d9d5166406e103bc8f3c6b5209e17c37dbb02deb8bc72ddd +9667c7300ff80f0140be002b0e36caab07aaee7cce72679197c64d355e20d96196acaf54e06e1382167d081fe6f739c1 +828126bb0559ce748809b622677267ca896fa2ee76360fd2c02990e6477e06a667241379ca7e65d61a5b64b96d7867de +8b8835dea6ba8cf61c91f01a4b3d2f8150b687a4ee09b45f2e5fc8f80f208ae5d142d8e3a18153f0722b90214e60c5a7 +a98e8ff02049b4da386e3ee93db23bbb13dfeb72f1cfde72587c7e6d962780b7671c63e8ac3fbaeb1a6605e8d79e2f29 +87a4892a0026d7e39ef3af632172b88337cb03669dea564bcdb70653b52d744730ebb5d642e20cb627acc9dbb547a26b +877352a22fc8052878a57effc159dac4d75fe08c84d3d5324c0bab6d564cdf868f33ceee515eee747e5856b62cfa0cc7 +8b801ba8e2ff019ee62f64b8cb8a5f601fc35423eb0f9494b401050103e1307dc584e4e4b21249cd2c686e32475e96c3 +a9e7338d6d4d9bfec91b2af28a8ed13b09415f57a3a00e5e777c93d768fdb3f8e4456ae48a2c6626b264226e911a0e28 +99c05fedf40ac4726ed585d7c1544c6e79619a0d3fb6bda75a08c7f3c0008e8d5e19ed4da48de3216135f34a15eba17c +a61cce8a1a8b13a4a650fdbec0eeea8297c352a8238fb7cac95a0df18ed16ee02a3daa2de108fa122aca733bd8ad7855 +b97f37da9005b440b4cb05870dd881bf8491fe735844f2d5c8281818583b38e02286e653d9f2e7fa5e74c3c3eb616540 +a72164a8554da8e103f692ac5ebb4aece55d5194302b9f74b6f2a05335b6e39beede0bf7bf8c5bfd4d324a784c5fb08c +b87e8221c5341cd9cc8bb99c10fe730bc105550f25ed4b96c0d45e6142193a1b2e72f1b3857373a659b8c09be17b3d91 +a41fb1f327ef91dcb7ac0787918376584890dd9a9675c297c45796e32d6e5985b12f9b80be47fc3a8596c245f419d395 +90dafa3592bdbb3465c92e2a54c2531822ba0459d45d3e7a7092fa6b823f55af28357cb51896d4ec2d66029c82f08e26 +a0a9adc872ebc396557f484f1dd21954d4f4a21c4aa5eec543f5fa386fe590839735c01f236574f7ff95407cd12de103 +b8c5c940d58be7538acf8672852b5da3af34f82405ef2ce8e4c923f1362f97fc50921568d0fd2fe846edfb0823e62979 +85aaf06a8b2d0dac89dafd00c28533f35dbd074978c2aaa5bef75db44a7b12aeb222e724f395513b9a535809a275e30b +81f3cbe82fbc7028c26a6c1808c604c63ba023a30c9f78a4c581340008dbda5ec07497ee849a2183fcd9124f7936af32 +a11ac738de75fd60f15a34209d3825d5e23385796a4c7fc5931822f3f380af977dd0f7b59fbd58eed7777a071e21b680 +85a279c493de03db6fa6c3e3c1b1b29adc9a8c4effc12400ae1128da8421954fa8b75ad19e5388fe4543b76fb0812813 +83a217b395d59ab20db6c4adb1e9713fc9267f5f31a6c936042fe051ce8b541f579442f3dcf0fa16b9e6de9fd3518191 +83a0b86e7d4ed8f9ccdc6dfc8ff1484509a6378fa6f09ed908e6ab9d1073f03011dc497e14304e4e3d181b57de06a5ab +a63ad69c9d25704ce1cc8e74f67818e5ed985f8f851afa8412248b2df5f833f83b95b27180e9e7273833ed0d07113d3b +99b1bc2021e63b561fe44ddd0af81fcc8627a91bfeecbbc989b642bc859abc0c8d636399701aad7bbaf6a385d5f27d61 +b53434adb66f4a807a6ad917c6e856321753e559b1add70824e5c1e88191bf6993fccb9b8b911fc0f473fb11743acacd +97ed3b9e6fb99bf5f945d4a41f198161294866aa23f2327818cdd55cb5dc4c1a8eff29dd8b8d04902d6cd43a71835c82 +b1e808260e368a18d9d10bdea5d60223ba1713b948c782285a27a99ae50cc5fc2c53d407de07155ecc16fb8a36d744a0 +a3eb4665f18f71833fec43802730e56b3ee5a357ea30a888ad482725b169d6f1f6ade6e208ee081b2e2633079b82ba7d +ab8beb2c8353fc9f571c18fdd02bdb977fc883313469e1277b0372fbbb33b80dcff354ca41de436d98d2ed710faa467e +aa9071cfa971e4a335a91ad634c98f2be51544cb21f040f2471d01bb97e1df2277ae1646e1ea8f55b7ba9f5c8c599b39 +80b7dbfdcaf40f0678012acc634eba44ea51181475180d9deb2050dc4f2de395289edd0223018c81057ec79b04b04c49 +89623d7f6cb17aa877af14de842c2d4ab7fd576d61ddd7518b5878620a01ded40b6010de0da3cdf31d837eecf30e9847 +a773bb024ae74dd24761f266d4fb27d6fd366a8634febe8235376b1ae9065c2fe12c769f1d0407867dfbe9f5272c352f +8455a561c3aaa6ba64c881a5e13921c592b3a02e968f4fb24a2243c36202795d0366d9cc1a24e916f84d6e158b7aeac7 +81d8bfc4b283cf702a40b87a2b96b275bdbf0def17e67d04842598610b67ea08c804d400c3e69fa09ea001eaf345b276 +b8f8f82cb11fea1c99467013d7e167ff03deb0c65a677fab76ded58826d1ba29aa7cf9fcd7763615735ea3ad38e28719 +89a6a04baf9cccc1db55179e1650b1a195dd91fb0aebc197a25143f0f393524d2589975e3fbfc2547126f0bced7fd6f2 +b81b2162df045390f04df07cbd0962e6b6ca94275a63edded58001a2f28b2ae2af2c7a6cba4ecd753869684e77e7e799 +a3757f722776e50de45c62d9c4a2ee0f5655a512344c4cbec542d8045332806568dd626a719ef21a4eb06792ca70f204 +8c5590df96ec22179a4e8786de41beb44f987a1dcc508eb341eecbc0b39236fdfad47f108f852e87179ccf4e10091e59 +87502f026ed4e10167419130b88c3737635c5b9074c364e1dd247cef5ef0fc064b4ae99b187e33301e438bbd2fe7d032 +af925a2165e980ced620ff12289129fe17670a90ae0f4db9d4b39bd887ccb1f5d2514ac9ecf910f6390a8fc66bd5be17 +857fca899828cf5c65d26e3e8a6e658542782fc72762b3b9c73514919f83259e0f849a9d4838b40dc905fe43024d0d23 +87ffebdbfb69a9e1007ebac4ffcb4090ff13705967b73937063719aa97908986effcb7262fdadc1ae0f95c3690e3245d +a9ff6c347ac6f4c6ab993b748802e96982eaf489dc69032269568412fc9a79e7c2850dfc991b28211b3522ee4454344b +a65b3159df4ec48bebb67cb3663cd744027ad98d970d620e05bf6c48f230fa45bf17527fe726fdf705419bb7a1bb913e +84b97b1e6408b6791831997b03cd91f027e7660fd492a93d95daafe61f02427371c0e237c75706412f442991dfdff989 +ab761c26527439b209af0ae6afccd9340bbed5fbe098734c3145b76c5d2cd7115d9227b2eb523882b7317fbb09180498 +a0479a8da06d7a69c0b0fee60df4e691c19c551f5e7da286dab430bfbcabf31726508e20d26ea48c53365a7f00a3ad34 +a732dfc9baa0f4f40b5756d2e8d8937742999623477458e0bc81431a7b633eefc6f53b3b7939fe0a020018549c954054 +901502436a1169ba51dc479a5abe7c8d84e0943b16bc3c6a627b49b92cd46263c0005bc324c67509edd693f28e612af1 +b627aee83474e7f84d1bab9b7f6b605e33b26297ac6bbf52d110d38ba10749032bd551641e73a383a303882367af429b +95108866745760baef4a46ef56f82da6de7e81c58b10126ebd2ba2cd13d339f91303bf2fb4dd104a6956aa3b13739503 +899ed2ade37236cec90056f3569bc50f984f2247792defafcceb49ad0ca5f6f8a2f06573705300e07f0de0c759289ff5 +a9f5eee196d608efe4bcef9bf71c646d27feb615e21252cf839a44a49fd89da8d26a758419e0085a05b1d59600e2dc42 +b36c6f68fed6e6c85f1f4a162485f24817f2843ec5cbee45a1ebfa367d44892e464949c6669f7972dc7167af08d55d25 +aaaede243a9a1b6162afbc8f571a52671a5a4519b4062e3f26777664e245ba873ed13b0492c5dbf0258c788c397a0e9e +972b4fb39c31cbe127bf9a32a5cc10d621ebdd9411df5e5da3d457f03b2ab2cd1f6372d8284a4a9400f0b06ecdbfd38e +8f6ca1e110e959a4b1d9a5ce5f212893cec21db40d64d5ac4d524f352d72198f923416a850bf845bc5a22a79c0ea2619 +a0f3c93b22134f66f04b2553a53b738644d1665ceb196b8494b315a4c28236fb492017e4a0de4224827c78e42f9908b7 +807fb5ee74f6c8735b0b5ca07e28506214fe4047dbeb00045d7c24f7849e98706aea79771241224939cb749cf1366c7d +915eb1ff034224c0b645442cdb7d669303fdc00ca464f91aaf0b6fde0b220a3a74ff0cb043c26c9f3a5667b3fdaa9420 +8fda6cef56ed33fefffa9e6ac8e6f76b1af379f89761945c63dd448801f7bb8ca970504a7105fac2f74f652ccff32327 +87380cffdcffb1d0820fa36b63cc081e72187f86d487315177d4d04da4533eb19a0e2ff6115ceab528887819c44a5164 +8cd89e03411a18e7f16f968b89fb500c36d47d229f6487b99e62403a980058db5925ce249206743333538adfad168330 +974451b1df33522ce7056de9f03e10c70bf302c44b0741a59df3d6877d53d61a7394dcee1dd46e013d7cb9d73419c092 +98c35ddf645940260c490f384a49496a7352bb8e3f686feed815b1d38f59ded17b1ad6e84a209e773ed08f7b8ff1e4c2 +963f386cf944bb9b2ddebb97171b64253ea0a2894ac40049bdd86cda392292315f3a3d490ca5d9628c890cfb669f0acb +8d507712152babd6d142ee682638da8495a6f3838136088df9424ef50d5ec28d815a198c9a4963610b22e49b4cdf95e9 +83d4bc6b0be87c8a4f1e9c53f257719de0c73d85b490a41f7420e777311640937320557ff2f1d9bafd1daaa54f932356 +82f5381c965b7a0718441131c4d13999f4cdce637698989a17ed97c8ea2e5bdb5d07719c5f7be8688edb081b23ede0f4 +a6ebecab0b72a49dfd01d69fa37a7f74d34fb1d4fef0aa10e3d6fceb9eccd671225c230af89f6eb514250e41a5f91f52 +846d185bdad6e11e604df7f753b7a08a28b643674221f0e750ebdb6b86ec584a29c869e131bca868972a507e61403f6a +85a98332292acb744bd1c0fd6fdcf1f889a78a2c9624d79413ffa194cc8dfa7821a4b60cde8081d4b5f71f51168dd67f +8f7d97c3b4597880d73200d074eb813d95432306e82dafc70b580b8e08cb8098b70f2d07b4b3ac6a4d77e92d57035031 +8185439c8751e595825d7053518cbe121f191846a38d4dbcb558c3f9d7a3104f3153401adaaaf27843bbe2edb504bfe3 +b3c00d8ece1518fca6b1215a139b0a0e26d9cba1b3a424f7ee59f30ce800a5db967279ed60958dd1f3ee69cf4dd1b204 +a2e6cb6978e883f9719c3c0d44cfe8de0cc6f644b98f98858433bea8bbe7b612c8aca5952fccce4f195f9d54f9722dc2 +99663087e3d5000abbec0fbda4e7342ec38846cc6a1505191fb3f1a337cb369455b7f8531a6eb8b0f7b2c4baf83cbe2b +ab0836c6377a4dbc7ca6a4d6cf021d4cd60013877314dd05f351706b128d4af6337711ed3443cb6ca976f40d74070a9a +87abfd5126152fd3bac3c56230579b489436755ea89e0566aa349490b36a5d7b85028e9fb0710907042bcde6a6f5d7e3 +974ba1033f75f60e0cf7c718a57ae1da3721cf9d0fb925714c46f027632bdd84cd9e6de4cf4d00bc55465b1c5ebb7384 +a607b49d73689ac64f25cec71221d30d53e781e1100d19a2114a21da6507a60166166369d860bd314acb226596525670 +a7c2b0b915d7beba94954f2aa7dd08ec075813661e2a3ecca5d28a0733e59583247fed9528eb28aba55b972cdbaf06eb +b8b3123e44128cc8efbe3270f2f94e50ca214a4294c71c3b851f8cbb70cb67fe9536cf07d04bf7fe380e5e3a29dd3c15 +a59a07e343b62ad6445a0859a32b58c21a593f9ddbfe52049650f59628c93715aa1f4e1f45b109321756d0eeec8a5429 +94f51f8a4ed18a6030d0aaa8899056744bd0e9dc9ac68f62b00355cddab11da5da16798db75f0bfbce0e5bdfe750c0b6 +97460a97ca1e1fa5ce243b81425edc0ec19b7448e93f0b55bc9785eedeeafe194a3c8b33a61a5c72990edf375f122777 +8fa859a089bc17d698a7ee381f37ce9beadf4e5b44fce5f6f29762bc04f96faff5d58c48c73631290325f05e9a1ecf49 +abdf38f3b20fc95eff31de5aa9ef1031abfa48f1305ee57e4d507594570401503476d3bcc493838fc24d6967a3082c7f +b8914bfb82815abb86da35c64d39ab838581bc0bf08967192697d9663877825f2b9d6fbdcf9b410463482b3731361aef +a8187f9d22b193a5f578999954d6ec9aa9b32338ccadb8a3e1ce5bad5ea361d69016e1cdfac44e9d6c54e49dd88561b9 +aac262cb7cba7fd62c14daa7b39677cabc1ef0947dd06dd89cac8570006a200f90d5f0353e84f5ff03179e3bebe14231 +a630ef5ece9733b8c46c0a2df14a0f37647a85e69c63148e79ffdcc145707053f9f9d305c3f1cf3c7915cb46d33abd07 +b102c237cb2e254588b6d53350dfda6901bd99493a3fbddb4121d45e0b475cf2663a40d7b9a75325eda83e4ba1e68cb3 +86a930dd1ddcc16d1dfa00aa292cb6c2607d42c367e470aa920964b7c17ab6232a7108d1c2c11fc40fb7496547d0bbf8 +a832fdc4500683e72a96cce61e62ac9ee812c37fe03527ad4cf893915ca1962cee80e72d4f82b20c8fc0b764376635a1 +88ad985f448dabb04f8808efd90f273f11f5e6d0468b5489a1a6a3d77de342992a73eb842d419034968d733f101ff683 +98a8538145f0d86f7fbf9a81c9140f6095c5bdd8960b1c6f3a1716428cd9cca1bf8322e6d0af24e6169abcf7df2b0ff6 +9048c6eba5e062519011e177e955a200b2c00b3a0b8615bdecdebc217559d41058d3315f6d05617be531ef0f6aef0e51 +833bf225ab6fc68cdcacf1ec1b50f9d05f5410e6cdcd8d56a3081dc2be8a8d07b81534d1ec93a25c2e270313dfb99e3b +a84bcd24c3da5e537e64a811b93c91bfc84d7729b9ead7f79078989a6eb76717d620c1fad17466a0519208651e92f5ff +b7cdd0a3fbd79aed93e1b5a44ca44a94e7af5ed911e4492f332e3a5ed146c7286bde01b52276a2fcc02780d2109874dd +8a19a09854e627cb95750d83c20c67442b66b35896a476358f993ba9ac114d32c59c1b3d0b8787ee3224cf3888b56c64 +a9abd5afb8659ee52ada8fa5d57e7dd355f0a7350276f6160bec5fbf70d5f99234dd179eb221c913e22a49ec6d267846 +8c13c4274c0d30d184e73eaf812200094bbbd57293780bdadbceb262e34dee5b453991e7f37c7333a654fc71c69d6445 +a4320d73296ff8176ce0127ca1921c450e2a9c06eff936681ebaffb5a0b05b17fded24e548454de89aca2dcf6d7a9de4 +b2b8b3e15c1f645f07783e5628aba614e60157889db41d8161d977606788842b67f83f361eae91815dc0abd84e09abd5 +ad26c3aa35ddfddc15719b8bb6c264aaec7065e88ac29ba820eb61f220fef451609a7bb037f3722d022e6c86e4f1dc88 +b8615bf43e13ae5d7b8dd903ce37190800cd490f441c09b22aa29d7a29ed2c0417b7a08ead417868f1de2589deaadd80 +8d3425e1482cd1e76750a76239d33c06b3554c3c3c87c15cb7ab58b1cee86a4c5c4178b44e23f36928365a1b484bde02 +806893a62e38c941a7dd6f249c83af16596f69877cc737d8f73f6b8cd93cbc01177a7a276b2b8c6b0e5f2ad864db5994 +86618f17fa4b0d65496b661bbb5ba3bc3a87129d30a4b7d4f515b904f4206ca5253a41f49fd52095861e5e065ec54f21 +9551915da1304051e55717f4c31db761dcdcf3a1366c89a4af800a9e99aca93a357bf928307f098e62b44a02cb689a46 +8f79c4ec0ec1146cb2a523b52fe33def90d7b5652a0cb9c2d1c8808a32293e00aec6969f5b1538e3a94cd1efa3937f86 +a0c03e329a707300081780f1e310671315b4c6a4cedcb29697aedfabb07a9d5df83f27b20e9c44cf6b16e39d9ded5b98 +86a7cfa7c8e7ce2c01dd0baec2139e97e8e090ad4e7b5f51518f83d564765003c65968f85481bbb97cb18f005ccc7d9f +a33811770c6dfda3f7f74e6ad0107a187fe622d61b444bbd84fd7ef6e03302e693b093df76f6ab39bb4e02afd84a575a +85480f5c10d4162a8e6702b5e04f801874d572a62a130be94b0c02b58c3c59bdcd48cd05f0a1c2839f88f06b6e3cd337 +8e181011564b17f7d787fe0e7f3c87f6b62da9083c54c74fd6c357a1f464c123c1d3d8ade3cf72475000b464b14e2be3 +8ee178937294b8c991337e0621ab37e9ffa4ca2bdb3284065c5e9c08aad6785d50cf156270ff9daf9a9127289710f55b +8bd1e8e2d37379d4b172f1aec96f2e41a6e1393158d7a3dbd9a95c8dd4f8e0b05336a42efc11a732e5f22b47fc5c271d +8f3da353cd487c13136a85677de8cedf306faae0edec733cf4f0046f82fa4639db4745b0095ff33a9766aba50de0cbcf +8d187c1e97638df0e4792b78e8c23967dac43d98ea268ca4aabea4e0fa06cb93183fd92d4c9df74118d7cc27bf54415e +a4c992f08c2f8bac0b74b3702fb0c75c9838d2ce90b28812019553d47613c14d8ce514d15443159d700b218c5a312c49 +a6fd1874034a34c3ea962a316c018d9493d2b3719bb0ec4edbc7c56b240802b2228ab49bee6f04c8a3e9f6f24a48c1c2 +b2efed8e799f8a15999020900dc2c58ece5a3641c90811b86a5198e593d7318b9d53b167818ccdfbe7df2414c9c34011 +995ff7de6181ddf95e3ead746089c6148da3508e4e7a2323c81785718b754d356789b902e7e78e2edc6b0cbd4ff22c78 +944073d24750a9068cbd020b834afc72d2dde87efac04482b3287b40678ad07588519a4176b10f2172a2c463d063a5cd +99db4b1bb76475a6fd75289986ef40367960279524378cc917525fb6ba02a145a218c1e9caeb99332332ab486a125ac0 +89fce4ecd420f8e477af4353b16faabb39e063f3f3c98fde2858b1f2d1ef6eed46f0975a7c08f233b97899bf60ccd60a +8c09a4f07a02b80654798bc63aada39fd638d3e3c4236ccd8a5ca280350c31e4a89e5f4c9aafb34116e71da18c1226b8 +85325cfa7ded346cc51a2894257eab56e7488dbff504f10f99f4cd2b630d913003761a50f175ed167e8073f1b6b63fb0 +b678b4fbec09a8cc794dcbca185f133578f29e354e99c05f6d07ac323be20aecb11f781d12898168e86f2e0f09aca15e +a249cfcbca4d9ba0a13b5f6aac72bf9b899adf582f9746bb2ad043742b28915607467eb794fca3704278f9136f7642be +9438e036c836a990c5e17af3d78367a75b23c37f807228362b4d13e3ddcb9e431348a7b552d09d11a2e9680704a4514f +925ab70450af28c21a488bfb5d38ac994f784cf249d7fd9ad251bb7fd897a23e23d2528308c03415074d43330dc37ef4 +a290563904d5a8c0058fc8330120365bdd2ba1fdbaef7a14bc65d4961bb4217acfaed11ab82669e359531f8bf589b8db +a7e07a7801b871fc9b981a71e195a3b4ba6b6313bc132b04796a125157e78fe5c11a3a46cf731a255ac2d78a4ae78cd0 +b26cd2501ee72718b0eebab6fb24d955a71f363f36e0f6dff0ab1d2d7836dab88474c0cef43a2cc32701fca7e82f7df3 +a1dc3b6c968f3de00f11275092290afab65b2200afbcfa8ddc70e751fa19dbbc300445d6d479a81bda3880729007e496 +a9bc213e28b630889476a095947d323b9ac6461dea726f2dc9084473ae8e196d66fb792a21905ad4ec52a6d757863e7d +b25d178df8c2df8051e7c888e9fa677fde5922e602a95e966db9e4a3d6b23ce043d7dc48a5b375c6b7c78e966893e8c3 +a1c8d88d72303692eaa7adf68ea41de4febec40cc14ae551bb4012afd786d7b6444a3196b5d9d5040655a3366d96b7cd +b22bd44f9235a47118a9bbe2ba5a2ba9ec62476061be2e8e57806c1a17a02f9a51403e849e2e589520b759abd0117683 +b8add766050c0d69fe81d8d9ea73e1ed05f0135d093ff01debd7247e42dbb86ad950aceb3b50b9af6cdc14ab443b238f +af2cf95f30ef478f018cf81d70d47d742120b09193d8bb77f0d41a5d2e1a80bfb467793d9e2471b4e0ad0cb2c3b42271 +8af5ef2107ad284e246bb56e20fef2a255954f72de791cbdfd3be09f825298d8466064f3c98a50496c7277af32b5c0bc +85dc19558572844c2849e729395a0c125096476388bd1b14fa7f54a7c38008fc93e578da3aac6a52ff1504d6ca82db05 +ae8c9b43c49572e2e166d704caf5b4b621a3b47827bb2a3bcd71cdc599bba90396fd9a405261b13e831bb5d44c0827d7 +a7ba7efede25f02e88f6f4cbf70643e76784a03d97e0fbd5d9437c2485283ad7ca3abb638a5f826cd9f6193e5dec0b6c +94a9d122f2f06ef709fd8016fd4b712d88052245a65a301f5f177ce22992f74ad05552b1f1af4e70d1eac62cef309752 +82d999b3e7cf563833b8bc028ff63a6b26eb357dfdb3fd5f10e33a1f80a9b2cfa7814d871b32a7ebfbaa09e753e37c02 +aec6edcde234df502a3268dd2c26f4a36a2e0db730afa83173f9c78fcb2b2f75510a02b80194327b792811caefda2725 +94c0bfa66c9f91d462e9194144fdd12d96f9bbe745737e73bab8130607ee6ea9d740e2cfcbbd00a195746edb6369ee61 +ab7573dab8c9d46d339e3f491cb2826cabe8b49f85f1ede78d845fc3995537d1b4ab85140b7d0238d9c24daf0e5e2a7e +87e8b16832843251fe952dadfd01d41890ed4bb4b8fa0254550d92c8cced44368225eca83a6c3ad47a7f81ff8a80c984 +9189d2d9a7c64791b19c0773ad4f0564ce6bea94aa275a917f78ad987f150fdb3e5e26e7fef9982ac184897ecc04683f +b3661bf19e2da41415396ae4dd051a9272e8a2580b06f1a1118f57b901fa237616a9f8075af1129af4eabfefedbe2f1c +af43c86661fb15daf5d910a4e06837225e100fb5680bd3e4b10f79a2144c6ec48b1f8d6e6b98e067d36609a5d038889a +82ac0c7acaa83ddc86c5b4249aae12f28155989c7c6b91e5137a4ce05113c6cbc16f6c44948b0efd8665362d3162f16a +8f268d1195ab465beeeb112cd7ffd5d5548559a8bc01261106d3555533fc1971081b25558d884d552df0db1cddda89d8 +8ef7caa5521f3e037586ce8ac872a4182ee20c7921c0065ed9986c047e3dda08294da1165f385d008b40d500f07d895f +8c2f98f6880550573fad46075d3eba26634b5b025ce25a0b4d6e0193352c8a1f0661064027a70fe8190b522405f9f4e3 +b7653f353564feb164f0f89ec7949da475b8dad4a4d396d252fc2a884f6932d027b7eb2dc4d280702c74569319ed701a +a026904f4066333befd9b87a8fad791d014096af60cdd668ef919c24dbe295ff31f7a790e1e721ba40cf5105abca67f4 +988f982004ada07a22dd345f2412a228d7a96b9cae2c487de42e392afe1e35c2655f829ce07a14629148ce7079a1f142 +9616add009067ed135295fb74d5b223b006b312bf14663e547a0d306694ff3a8a7bb9cfc466986707192a26c0bce599f +ad4c425de9855f6968a17ee9ae5b15e0a5b596411388cf976df62ecc6c847a6e2ddb2cea792a5f6e9113c2445dba3e5c +b698ac9d86afa3dc69ff8375061f88e3b0cff92ff6dfe747cebaf142e813c011851e7a2830c10993b715e7fd594604a9 +a386fa189847bb3b798efca917461e38ead61a08b101948def0f82cd258b945ed4d45b53774b400af500670149e601b7 +905c95abda2c68a6559d8a39b6db081c68cef1e1b4be63498004e1b2f408409be9350b5b5d86a30fd443e2b3e445640a +9116dade969e7ce8954afcdd43e5cab64dc15f6c1b8da9d2d69de3f02ba79e6c4f6c7f54d6bf586d30256ae405cd1e41 +a3084d173eacd08c9b5084a196719b57e47a0179826fda73466758235d7ecdb87cbcf097bd6b510517d163a85a7c7edd +85bb00415ad3c9be99ff9ba83672cc59fdd24356b661ab93713a3c8eab34e125d8867f628a3c3891b8dc056e69cd0e83 +8d58541f9f39ed2ee4478acce5d58d124031338ec11b0d55551f00a5a9a6351faa903a5d7c132dc5e4bb026e9cbd18e4 +a622adf72dc250e54f672e14e128c700166168dbe0474cecb340da175346e89917c400677b1bc1c11fcc4cc26591d9db +b3f865014754b688ca8372e8448114fff87bf3ca99856ab9168894d0c4679782c1ced703f5b74e851b370630f5e6ee86 +a7e490b2c40c2446fcd91861c020da9742c326a81180e38110558bb5d9f2341f1c1885e79b364e6419023d1cbdc47380 +b3748d472b1062e54572badbb8e87ac36534407f74932e7fc5b8392d008e8e89758f1671d1e4d30ab0fa40551b13bb5e +89898a5c5ec4313aabc607b0049fd1ebad0e0c074920cf503c9275b564d91916c2c446d3096491c950b7af3ac5e4b0ed +8eb8c83fef2c9dd30ea44e286e9599ec5c20aba983f702e5438afe2e5b921884327ad8d1566c72395587efac79ca7d56 +b92479599e806516ce21fb0bd422a1d1d925335ebe2b4a0a7e044dd275f30985a72b97292477053ac5f00e081430da80 +a34ae450a324fe8a3c25a4d653a654f9580ed56bbea213b8096987bbad0f5701d809a17076435e18017fea4d69f414bc +81381afe6433d62faf62ea488f39675e0091835892ecc238e02acf1662669c6d3962a71a3db652f6fe3bc5f42a0e5dc5 +a430d475bf8580c59111103316fe1aa79c523ea12f1d47a976bbfae76894717c20220e31cf259f08e84a693da6688d70 +b842814c359754ece614deb7d184d679d05d16f18a14b288a401cef5dad2cf0d5ee90bad487b80923fc5573779d4e4e8 +971d9a2627ff2a6d0dcf2af3d895dfbafca28b1c09610c466e4e2bff2746f8369de7f40d65b70aed135fe1d72564aa88 +8f4ce1c59e22b1ce7a0664caaa7e53735b154cfba8d2c5cc4159f2385843de82ab58ed901be876c6f7fce69cb4130950 +86cc9dc321b6264297987000d344fa297ef45bcc2a4df04e458fe2d907ad304c0ea2318e32c3179af639a9a56f3263cf +8229e0876dfe8f665c3fb19b250bd89d40f039bbf1b331468b403655be7be2e104c2fd07b9983580c742d5462ca39a43 +99299d73066e8eb128f698e56a9f8506dfe4bd014931e86b6b487d6195d2198c6c5bf15cccb40ccf1f8ddb57e9da44a2 +a3a3be37ac554c574b393b2f33d0a32a116c1a7cfeaf88c54299a4da2267149a5ecca71f94e6c0ef6e2f472b802f5189 +a91700d1a00387502cdba98c90f75fbc4066fefe7cc221c8f0e660994c936badd7d2695893fde2260c8c11d5bdcdd951 +8e03cae725b7f9562c5c5ab6361644b976a68bada3d7ca508abca8dfc80a469975689af1fba1abcf21bc2a190dab397d +b01461ad23b2a8fa8a6d241e1675855d23bc977dbf4714add8c4b4b7469ccf2375cec20e80cedfe49361d1a30414ac5b +a2673bf9bc621e3892c3d7dd4f1a9497f369add8cbaa3472409f4f86bd21ac67cfac357604828adfee6ada1835365029 +a042dff4bf0dfc33c178ba1b335e798e6308915128de91b12e5dbbab7c4ac8d60a01f6aea028c3a6d87b9b01e4e74c01 +86339e8a75293e4b3ae66b5630d375736b6e6b6b05c5cda5e73fbf7b2f2bd34c18a1d6cefede08625ce3046e77905cb8 +af2ebe1b7d073d03e3d98bc61af83bf26f7a8c130fd607aa92b75db22d14d016481b8aa231e2c9757695f55b7224a27f +a00ee882c9685e978041fd74a2c465f06e2a42ffd3db659053519925be5b454d6f401e3c12c746e49d910e4c5c9c5e8c +978a781c0e4e264e0dad57e438f1097d447d891a1e2aa0d5928f79a9d5c3faae6f258bc94fdc530b7b2fa6a9932bb193 +aa4b7ce2e0c2c9e9655bf21e3e5651c8503bce27483017b0bf476be743ba06db10228b3a4c721219c0779747f11ca282 +b003d1c459dacbcf1a715551311e45d7dbca83a185a65748ac74d1800bbeaba37765d9f5a1a221805c571910b34ebca8 +95b6e531b38648049f0d19de09b881baa1f7ea3b2130816b006ad5703901a05da57467d1a3d9d2e7c73fb3f2e409363c +a6cf9c06593432d8eba23a4f131bb7f72b9bd51ab6b4b772a749fe03ed72b5ced835a349c6d9920dba2a39669cb7c684 +aa3d59f6e2e96fbb66195bc58c8704e139fa76cd15e4d61035470bd6e305db9f98bcbf61ac1b95e95b69ba330454c1b3 +b57f97959c208361de6d7e86dff2b873068adb0f158066e646f42ae90e650079798f165b5cd713141cd3a2a90a961d9a +a76ee8ed9052f6a7a8c69774bb2597be182942f08115baba03bf8faaeaee526feba86120039fe8ca7b9354c3b6e0a8e6 +95689d78c867724823f564627d22d25010f278674c6d2d0cdb10329169a47580818995d1d727ce46c38a1e47943ebb89 +ab676d2256c6288a88e044b3d9ffd43eb9d5aaee00e8fc60ac921395fb835044c71a26ca948e557fed770f52d711e057 +96351c72785c32e5d004b6f4a1259fb8153d631f0c93fed172f18e8ba438fbc5585c1618deeabd0d6d0b82173c2e6170 +93dd8d3db576418e22536eba45ab7f56967c6c97c64260d6cddf38fb19c88f2ec5cd0e0156f50e70855eee8a2b879ffd +ad6ff16f40f6de3d7a737f8e6cebd8416920c4ff89dbdcd75eabab414af9a6087f83ceb9aff7680aa86bff98bd09c8cc +84de53b11671abc9c38710e19540c5c403817562aeb22a88404cdaff792c1180f717dbdfe8f54940c062c4d032897429 +872231b9efa1cdd447b312099a5c164c560440a9441d904e70f5abfc3b2a0d16be9a01aca5e0a2599a61e19407587e3d +88f44ac27094a2aa14e9dc40b099ee6d68f97385950f303969d889ee93d4635e34dff9239103bdf66a4b7cbba3e7eb7a +a59afebadf0260e832f6f44468443562f53fbaf7bcb5e46e1462d3f328ac437ce56edbca617659ac9883f9e13261fad7 +b1990e42743a88de4deeacfd55fafeab3bc380cb95de43ed623d021a4f2353530bcab9594389c1844b1c5ea6634c4555 +85051e841149a10e83f56764e042182208591396d0ce78c762c4a413e6836906df67f38c69793e158d64fef111407ba3 +9778172bbd9b1f2ec6bbdd61829d7b39a7df494a818e31c654bf7f6a30139899c4822c1bf418dd4f923243067759ce63 +9355005b4878c87804fc966e7d24f3e4b02bed35b4a77369d01f25a3dcbff7621b08306b1ac85b76fe7b4a3eb5f839b1 +8f9dc6a54fac052e236f8f0e1f571ac4b5308a43acbe4cc8183bce26262ddaf7994e41cf3034a4cbeca2c505a151e3b1 +8cc59c17307111723fe313046a09e0e32ea0cce62c13814ab7c6408c142d6a0311d801be4af53fc9240523f12045f9ef +8e6057975ed40a1932e47dd3ac778f72ee2a868d8540271301b1aa6858de1a5450f596466494a3e0488be4fbeb41c840 +812145efbd6559ae13325d56a15940ca4253b17e72a9728986b563bb5acc13ec86453796506ac1a8f12bd6f9e4a288c3 +911da0a6d6489eb3dab2ec4a16e36127e8a291ae68a6c2c9de33e97f3a9b1f00da57a94e270a0de79ecc5ecb45d19e83 +b72ea85973f4b2a7e6e71962b0502024e979a73c18a9111130e158541fa47bbaaf53940c8f846913a517dc69982ba9e1 +a7a56ad1dbdc55f177a7ad1d0af78447dc2673291e34e8ab74b26e2e2e7d8c5fe5dc89e7ef60f04a9508847b5b3a8188 +b52503f6e5411db5d1e70f5fb72ccd6463fa0f197b3e51ca79c7b5a8ab2e894f0030476ada72534fa4eb4e06c3880f90 +b51c7957a3d18c4e38f6358f2237b3904618d58b1de5dec53387d25a63772e675a5b714ad35a38185409931157d4b529 +b86b4266e719d29c043d7ec091547aa6f65bbf2d8d831d1515957c5c06513b72aa82113e9645ad38a7bc3f5383504fa6 +b95b547357e6601667b0f5f61f261800a44c2879cf94e879def6a105b1ad2bbf1795c3b98a90d588388e81789bd02681 +a58fd4c5ae4673fa350da6777e13313d5d37ed1dafeeb8f4f171549765b84c895875d9d3ae6a9741f3d51006ef81d962 +9398dc348d078a604aadc154e6eef2c0be1a93bb93ba7fe8976edc2840a3a318941338cc4d5f743310e539d9b46613d2 +902c9f0095014c4a2f0dccaaab543debba6f4cc82c345a10aaf4e72511725dbed7a34cd393a5f4e48a3e5142b7be84ed +a7c0447849bb44d04a0393a680f6cd390093484a79a147dd238f5d878030d1c26646d88211108e59fe08b58ad20c6fbd +80db045535d6e67a422519f5c89699e37098449d249698a7cc173a26ccd06f60238ae6cc7242eb780a340705c906790c +8e52b451a299f30124505de2e74d5341e1b5597bdd13301cc39b05536c96e4380e7f1b5c7ef076f5b3005a868657f17c +824499e89701036037571761e977654d2760b8ce21f184f2879fda55d3cda1e7a95306b8abacf1caa79d3cc075b9d27f +9049b956b77f8453d2070607610b79db795588c0cec12943a0f5fe76f358dea81e4f57a4692112afda0e2c05c142b26f +81911647d818a4b5f4990bfd4bc13bf7be7b0059afcf1b6839333e8569cdb0172fd2945410d88879349f677abaed5eb3 +ad4048f19b8194ed45b6317d9492b71a89a66928353072659f5ce6c816d8f21e69b9d1817d793effe49ca1874daa1096 +8d22f7b2ddb31458661abd34b65819a374a1f68c01fc6c9887edeba8b80c65bceadb8f57a3eb686374004b836261ef67 +92637280c259bc6842884db3d6e32602a62252811ae9b019b3c1df664e8809ffe86db88cfdeb8af9f46435c9ee790267 +a2f416379e52e3f5edc21641ea73dc76c99f7e29ea75b487e18bd233856f4c0183429f378d2bfc6cd736d29d6cadfa49 +882cb6b76dbdc188615dcf1a8439eba05ffca637dd25197508156e03c930b17b9fed2938506fdd7b77567cb488f96222 +b68b621bb198a763fb0634eddb93ed4b5156e59b96c88ca2246fd1aea3e6b77ed651e112ac41b30cd361fadc011d385e +a3cb22f6b675a29b2d1f827cacd30df14d463c93c3502ef965166f20d046af7f9ab7b2586a9c64f4eae4fad2d808a164 +8302d9ce4403f48ca217079762ce42cee8bc30168686bb8d3a945fbd5acd53b39f028dce757b825eb63af2d5ae41169d +b2eef1fbd1a176f1f4cd10f2988c7329abe4eb16c7405099fb92baa724ab397bc98734ef7d4b24c0f53dd90f57520d04 +a1bbef0bd684a3f0364a66bde9b29326bac7aa3dde4caed67f14fb84fed3de45c55e406702f1495a3e2864d4ee975030 +976acdb0efb73e3a3b65633197692dedc2adaed674291ae3df76b827fc866d214e9cac9ca46baefc4405ff13f953d936 +b9fbf71cc7b6690f601f0b1c74a19b7d14254183a2daaafec7dc3830cba5ae173d854bbfebeca985d1d908abe5ef0cda +90591d7b483598c94e38969c4dbb92710a1a894bcf147807f1bcbd8aa3ac210b9f2be65519aa829f8e1ccdc83ad9b8cf +a30568577c91866b9c40f0719d46b7b3b2e0b4a95e56196ac80898a2d89cc67880e1229933f2cd28ee3286f8d03414d7 +97589a88c3850556b359ec5e891f0937f922a751ac7c95949d3bbc7058c172c387611c0f4cb06351ef02e5178b3dd9e4 +98e7bbe27a1711f4545df742f17e3233fbcc63659d7419e1ca633f104cb02a32c84f2fac23ca2b84145c2672f68077ab +a7ddb91636e4506d8b7e92aa9f4720491bb71a72dadc47c7f4410e15f93e43d07d2b371951a0e6a18d1bd087aa96a5c4 +a7c006692227a06db40bceac3d5b1daae60b5692dd9b54772bedb5fea0bcc91cbcdb530cac31900ffc70c5b3ffadc969 +8d3ec6032778420dfa8be52066ba0e623467df33e4e1901dbadd586c5d750f4ccde499b5197e26b9ea43931214060f69 +8d9a8410518ea64f89df319bfd1fc97a0971cdb9ad9b11d1f8fe834042ea7f8dce4db56eeaf179ff8dda93b6db93e5ce +a3c533e9b3aa04df20b9ff635cb1154ce303e045278fcf3f10f609064a5445552a1f93989c52ce852fd0bbd6e2b6c22e +81934f3a7f8c1ae60ec6e4f212986bcc316118c760a74155d06ce0a8c00a9b9669ec4e143ca214e1b995e41271774fd9 +ab8e2d01a71192093ef8fafa7485e795567cc9db95a93fb7cc4cf63a391ef89af5e2bfad4b827fffe02b89271300407f +83064a1eaa937a84e392226f1a60b7cfad4efaa802f66de5df7498962f7b2649924f63cd9962d47906380b97b9fe80e1 +b4f5e64a15c6672e4b55417ee5dc292dcf93d7ea99965a888b1cc4f5474a11e5b6520eacbcf066840b343f4ceeb6bf33 +a63d278b842456ef15c278b37a6ea0f27c7b3ffffefca77c7a66d2ea06c33c4631eb242bbb064d730e70a8262a7b848a +83a41a83dbcdf0d22dc049de082296204e848c453c5ab1ba75aa4067984e053acf6f8b6909a2e1f0009ed051a828a73b +819485b036b7958508f15f3c19436da069cbe635b0318ebe8c014cf1ef9ab2df038c81161b7027475bcfa6fff8dd9faf +aa40e38172806e1e045e167f3d1677ef12d5dcdc89b43639a170f68054bd196c4fae34c675c1644d198907a03f76ba57 +969bae484883a9ed1fbed53b26b3d4ee4b0e39a6c93ece5b3a49daa01444a1c25727dabe62518546f36b047b311b177c +80a9e73a65da99664988b238096a090d313a0ee8e4235bc102fa79bb337b51bb08c4507814eb5baec22103ec512eaab0 +86604379aec5bddda6cbe3ef99c0ac3a3c285b0b1a15b50451c7242cd42ae6b6c8acb717dcca7917838432df93a28502 +a23407ee02a495bed06aa7e15f94cfb05c83e6d6fba64456a9bbabfa76b2b68c5c47de00ba169e710681f6a29bb41a22 +98cff5ecc73b366c6a01b34ac9066cb34f7eeaf4f38a5429bad2d07e84a237047e2a065c7e8a0a6581017dadb4695deb +8de9f68a938f441f3b7ab84bb1f473c5f9e5c9e139e42b7ccee1d254bd57d0e99c2ccda0f3198f1fc5737f6023dd204e +b0ce48d815c2768fb472a315cad86aa033d0e9ca506f146656e2941829e0acb735590b4fbc713c2d18d3676db0a954ac +82f485cdefd5642a6af58ac6817991c49fac9c10ace60f90b27f1788cc026c2fe8afc83cf499b3444118f9f0103598a8 +82c24550ed512a0d53fc56f64cc36b553823ae8766d75d772dacf038c460f16f108f87a39ceef7c66389790f799dbab3 +859ffcf1fe9166388316149b9acc35694c0ea534d43f09dae9b86f4aa00a23b27144dda6a352e74b9516e8c8d6fc809c +b8f7f353eec45da77fb27742405e5ad08d95ec0f5b6842025be9def3d9892f85eb5dd0921b41e6eff373618dba215bca +8ccca4436f9017e426229290f5cd05eac3f16571a4713141a7461acfe8ae99cd5a95bf5b6df129148693c533966145da +a2c67ecc19c0178b2994846fea4c34c327a5d786ac4b09d1d13549d5be5996d8a89021d63d65cb814923388f47cc3a03 +aa0ff87d676b418ec08f5cbf577ac7e744d1d0e9ebd14615b550eb86931eafd2a36d4732cc5d6fab1713fd7ab2f6f7c0 +8aef4730bb65e44efd6bb9441c0ae897363a2f3054867590a2c2ecf4f0224e578c7a67f10b40f8453d9f492ac15a9b2d +86a187e13d8fba5addcfdd5b0410cedd352016c930f913addd769ee09faa6be5ca3e4b1bdb417a965c643a99bd92be42 +a0a4e9632a7a094b14b29b78cd9c894218cdf6783e61671e0203865dc2a835350f465fbaf86168f28af7c478ca17bc89 +a8c7b02d8deff2cd657d8447689a9c5e2cd74ef57c1314ac4d69084ac24a7471954d9ff43fe0907d875dcb65fd0d3ce5 +97ded38760aa7be6b6960b5b50e83b618fe413cbf2bcc1da64c05140bcc32f5e0e709cd05bf8007949953fac5716bad9 +b0d293835a24d64c2ae48ce26e550b71a8c94a0883103757fb6b07e30747f1a871707d23389ba2b2065fa6bafe220095 +8f9e291bf849feaa575592e28e3c8d4b7283f733d41827262367ea1c40f298c7bcc16505255a906b62bf15d9f1ba85fb +998f4e2d12708b4fd85a61597ca2eddd750f73c9e0c9b3cf0825d8f8e01f1628fd19797dcaed3b16dc50331fc6b8b821 +b30d1f8c115d0e63bf48f595dd10908416774c78b3bbb3194192995154d80ea042d2e94d858de5f8aa0261b093c401fd +b5d9c75bb41f964cbff3f00e96d9f1480c91df8913f139f0d385d27a19f57a820f838eb728e46823cbff00e21c660996 +a6edec90b5d25350e2f5f0518777634f9e661ec9d30674cf5b156c4801746d62517751d90074830ac0f4b09911c262f1 +82f98da1264b6b75b8fbeb6a4d96d6a05b25c24db0d57ba3a38efe3a82d0d4e331b9fc4237d6494ccfe4727206457519 +b89511843453cf4ecd24669572d6371b1e529c8e284300c43e0d5bb6b3aaf35aeb634b3cb5c0a2868f0d5e959c1d0772 +a82bf065676583e5c1d3b81987aaae5542f522ba39538263a944bb33ea5b514c649344a96c0205a3b197a3f930fcda6c +a37b47ea527b7e06c460776aa662d9a49ff4149d3993f1a974b0dd165f7171770d189b0e2ea54fd5fccb6a14b116e68a +a1017677f97dda818274d47556d09d0e4ccacb23a252f82a6cfe78c630ad46fb9806307445a59fb61262182de3a2b29c +b01e9fcac239ba270e6877b79273ddd768bf8a51d2ed8a051b1c11e18eff3de5920e2fcbfbd26f06d381eddd3b1f1e1b +82fcd53d803b1c8e4ed76adc339b7f3a5962d37042b9683aabac7513ac68775d4a566a9460183926a6a95dbe7d551a1f +a763e78995d55cd21cdb7ef75d9642d6e1c72453945e346ab6690c20a4e1eeec61bb848ef830ae4b56182535e3c71d8f +b769f4db602251d4b0a1186782799bdcef66de33c110999a5775c50b349666ffd83d4c89714c4e376f2efe021a5cfdb2 +a59cbd1b785efcfa6e83fc3b1d8cf638820bc0c119726b5368f3fba9dce8e3414204fb1f1a88f6c1ff52e87961252f97 +95c8c458fd01aa23ecf120481a9c6332ebec2e8bb70a308d0576926a858457021c277958cf79017ddd86a56cacc2d7db +82eb41390800287ae56e77f2e87709de5b871c8bdb67c10a80fc65f3acb9f7c29e8fa43047436e8933f27449ea61d94d +b3ec25e3545eb83aed2a1f3558d1a31c7edde4be145ecc13b33802654b77dc049b4f0065069dd9047b051e52ab11dcdd +b78a0c715738f56f0dc459ab99e252e3b579b208142836b3c416b704ca1de640ca082f29ebbcee648c8c127df06f6b1e +a4083149432eaaf9520188ebf4607d09cf664acd1f471d4fb654476e77a9eaae2251424ffda78d09b6cb880df35c1219 +8c52857d68d6e9672df3db2df2dbf46b516a21a0e8a18eec09a6ae13c1ef8f369d03233320dd1c2c0bbe00abfc1ea18b +8c856089488803066bff3f8d8e09afb9baf20cecc33c8823c1c0836c3d45498c3de37e87c016b705207f60d2b00f8609 +831a3df39be959047b2aead06b4dcd3012d7b29417f642b83c9e8ce8de24a3dbbd29c6fdf55e2db3f7ea04636c94e403 +aed84d009f66544addabe404bf6d65af7779ce140dc561ff0c86a4078557b96b2053b7b8a43432ffb18cd814f143b9da +93282e4d72b0aa85212a77b336007d8ba071eea17492da19860f1ad16c1ea8867ccc27ef5c37c74b052465cc11ea4f52 +a7b78b8c8d057194e8d68767f1488363f77c77bddd56c3da2bc70b6354c7aa76247c86d51f7371aa38a4aa7f7e3c0bb7 +b1c77283d01dcd1bde649b5b044eac26befc98ff57cbee379fb5b8e420134a88f2fc7f0bf04d15e1fbd45d29e7590fe6 +a4aa8de70330a73b2c6458f20a1067eed4b3474829b36970a8df125d53bbdda4f4a2c60063b7cccb0c80fc155527652f +948a6c79ba1b8ad7e0bed2fae2f0481c4e41b4d9bbdd9b58164e28e9065700e83f210c8d5351d0212e0b0b68b345b3a5 +86a48c31dcbbf7b082c92d28e1f613a2378a910677d7db3a349dc089e4a1e24b12eee8e8206777a3a8c64748840b7387 +976adb1af21e0fc34148917cf43d933d7bfd3fd12ed6c37039dcd5a4520e3c6cf5868539ba5bf082326430deb8a4458d +b93e1a4476f2c51864bb4037e7145f0635eb2827ab91732b98d49b6c07f6ac443111aa1f1da76d1888665cb897c3834e +8afd46fb23bf869999fa19784b18a432a1f252d09506b8dbb756af900518d3f5f244989b3d7c823d9029218c655d3dc6 +83f1e59e3abeed18cdc632921672673f1cb6e330326e11c4e600e13e0d5bc11bdc970ae12952e15103a706fe720bf4d6 +90ce4cc660714b0b673d48010641c09c00fc92a2c596208f65c46073d7f349dd8e6e077ba7dcef9403084971c3295b76 +8b09b0f431a7c796561ecf1549b85048564de428dac0474522e9558b6065fede231886bc108539c104ce88ebd9b5d1b0 +85d6e742e2fb16a7b0ba0df64bc2c0dbff9549be691f46a6669bca05e89c884af16822b85faefefb604ec48c8705a309 +a87989ee231e468a712c66513746fcf03c14f103aadca0eac28e9732487deb56d7532e407953ab87a4bf8961588ef7b0 +b00da10efe1c29ee03c9d37d5918e391ae30e48304e294696b81b434f65cf8c8b95b9d1758c64c25e534d045ba28696f +91c0e1fb49afe46c7056400baa06dbb5f6e479db78ee37e2d76c1f4e88994357e257b83b78624c4ef6091a6c0eb8254d +883fb797c498297ccbf9411a3e727c3614af4eccde41619b773dc7f3259950835ee79453debf178e11dec4d3ada687a0 +a14703347e44eb5059070b2759297fcfcfc60e6893c0373eea069388eba3950aa06f1c57cd2c30984a2d6f9e9c92c79e +afebc7585b304ceba9a769634adff35940e89cd32682c78002822aab25eec3edc29342b7f5a42a56a1fec67821172ad5 +aea3ff3822d09dba1425084ca95fd359718d856f6c133c5fabe2b2eed8303b6e0ba0d8698b48b93136a673baac174fd9 +af2456a09aa777d9e67aa6c7c49a1845ea5cdda2e39f4c935c34a5f8280d69d4eec570446998cbbe31ede69a91e90b06 +82cada19fed16b891ef3442bafd49e1f07c00c2f57b2492dd4ee36af2bd6fd877d6cb41188a4d6ce9ec8d48e8133d697 +82a21034c832287f616619a37c122cee265cc34ae75e881fcaea4ea7f689f3c2bc8150bbf7dbcfd123522bfb7f7b1d68 +86877217105f5d0ec3eeff0289fc2a70d505c9fdf7862e8159553ef60908fb1a27bdaf899381356a4ef4649072a9796c +82b196e49c6e861089a427c0b4671d464e9d15555ffb90954cd0d630d7ae02eb3d98ceb529d00719c2526cd96481355a +a29b41d0d43d26ce76d4358e0db2b77df11f56e389f3b084d8af70a636218bd3ac86b36a9fe46ec9058c26a490f887f7 +a4311c4c20c4d7dd943765099c50f2fd423e203ccfe98ff00087d205467a7873762510cac5fdce7a308913ed07991ed7 +b1f040fc5cc51550cb2c25cf1fd418ecdd961635a11f365515f0cb4ffb31da71f48128c233e9cc7c0cf3978d757ec84e +a9ebae46f86d3bd543c5f207ed0d1aed94b8375dc991161d7a271f01592912072e083e2daf30c146430894e37325a1b9 +826418c8e17ad902b5fe88736323a47e0ca7a44bce4cbe27846ec8fe81de1e8942455dda6d30e192cdcc73e11df31256 +85199db563427c5edcbac21f3d39fec2357be91fb571982ddcdc4646b446ad5ced84410de008cb47b3477ee0d532daf8 +b7eed9cd400b2ca12bf1d9ae008214b8561fb09c8ad9ff959e626ffde00fee5ff2f5b6612e231f2a1a9b1646fcc575e3 +8b40bf12501dcbac78f5a314941326bfcddf7907c83d8d887d0bb149207f85d80cd4dfbd7935439ea7b14ea39a3fded7 +83e3041af302485399ba6cd5120e17af61043977083887e8d26b15feec4a6b11171ac5c06e6ad0971d4b58a81ff12af3 +8f5b9a0eecc589dbf8c35a65d5e996a659277ef6ea509739c0cb7b3e2da9895e8c8012de662e5b23c5fa85d4a8f48904 +835d71ed5e919d89d8e6455f234f3ff215462c4e3720c371ac8c75e83b19dfe3ae15a81547e4dc1138e5f5997f413cc9 +8b7d2e4614716b1db18e9370176ea483e6abe8acdcc3dcdf5fb1f4d22ca55d652feebdccc171c6de38398d9f7bfdec7a +93eace72036fe57d019676a02acf3d224cf376f166658c1bf705db4f24295881d477d6fdd7916efcfceff8c7a063deda +b1ac460b3d516879a84bc886c54f020a9d799e7c49af3e4d7de5bf0d2793c852254c5d8fe5616147e6659512e5ccb012 +acd0947a35cb167a48bcd9667620464b54ac0e78f9316b4aa92dcaab5422d7a732087e52e1c827faa847c6b2fe6e7766 +94ac33d21c3d12ff762d32557860e911cd94d666609ddcc42161b9c16f28d24a526e8b10bb03137257a92cec25ae637d +832e02058b6b994eadd8702921486241f9a19e68ed1406dad545e000a491ae510f525ccf9d10a4bba91c68f2c53a0f58 +9471035d14f78ff8f463b9901dd476b587bb07225c351161915c2e9c6114c3c78a501379ab6fb4eb03194c457cbd22bf +ab64593e034c6241d357fcbc32d8ea5593445a5e7c24cac81ad12bd2ef01843d477a36dc1ba21dbe63b440750d72096a +9850f3b30045e927ad3ec4123a32ed2eb4c911f572b6abb79121873f91016f0d80268de8b12e2093a4904f6e6cab7642 +987212c36b4722fe2e54fa30c52b1e54474439f9f35ca6ad33c5130cd305b8b54b532dd80ffd2c274105f20ce6d79f6e +8b4d0c6abcb239b5ed47bef63bc17efe558a27462c8208fa652b056e9eae9665787cd1aee34fbb55beb045c8bfdb882b +a9f3483c6fee2fe41312d89dd4355d5b2193ac413258993805c5cbbf0a59221f879386d3e7a28e73014f10e65dd503d9 +a2225da3119b9b7c83d514b9f3aeb9a6d9e32d9cbf9309cbb971fd53c4b2c001d10d880a8ad8a7c281b21d85ceca0b7c +a050be52e54e676c151f7a54453bbb707232f849beab4f3bf504b4d620f59ed214409d7c2bd3000f3ff13184ccda1c35 +adbccf681e15b3edb6455a68d292b0a1d0f5a4cb135613f5e6db9943f02181341d5755875db6ee474e19ace1c0634a28 +8b6eff675632a6fad0111ec72aacc61c7387380eb87933fd1d098856387d418bd38e77d897e65d6fe35951d0627c550b +aabe2328ddf90989b15e409b91ef055cb02757d34987849ae6d60bef2c902bf8251ed21ab30acf39e500d1d511e90845 +92ba4eb1f796bc3d8b03515f65c045b66e2734c2da3fc507fdd9d6b5d1e19ab3893726816a32141db7a31099ca817d96 +8a98b3cf353138a1810beb60e946183803ef1d39ac4ea92f5a1e03060d35a4774a6e52b14ead54f6794d5f4022b8685c +909f8a5c13ec4a59b649ed3bee9f5d13b21d7f3e2636fd2bb3413c0646573fdf9243d63083356f12f5147545339fcd55 +9359d914d1267633141328ed0790d81c695fea3ddd2d406c0df3d81d0c64931cf316fe4d92f4353c99ff63e2aefc4e34 +b88302031681b54415fe8fbfa161c032ea345c6af63d2fb8ad97615103fd4d4281c5a9cae5b0794c4657b97571a81d3b +992c80192a519038082446b1fb947323005b275e25f2c14c33cc7269e0ec038581cc43705894f94bad62ae33a8b7f965 +a78253e3e3eece124bef84a0a8807ce76573509f6861d0b6f70d0aa35a30a123a9da5e01e84969708c40b0669eb70aa6 +8d5724de45270ca91c94792e8584e676547d7ac1ac816a6bb9982ee854eb5df071d20545cdfd3771cd40f90e5ba04c8e +825a6f586726c68d45f00ad0f5a4436523317939a47713f78fd4fe81cd74236fdac1b04ecd97c2d0267d6f4981d7beb1 +93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 +b5bfd7dd8cdeb128843bc287230af38926187075cbfbefa81009a2ce615ac53d2914e5870cb452d2afaaab24f3499f72185cbfee53492714734429b7b38608e23926c911cceceac9a36851477ba4c60b087041de621000edc98edada20c1def2 +b5337ba0ce5d37224290916e268e2060e5c14f3f9fc9e1ec3af5a958e7a0303122500ce18f1a4640bf66525bd10e763501fe986d86649d8d45143c08c3209db3411802c226e9fe9a55716ac4a0c14f9dcef9e70b2bb309553880dc5025eab3cc +b3c1dcdc1f62046c786f0b82242ef283e7ed8f5626f72542aa2c7a40f14d9094dd1ebdbd7457ffdcdac45fd7da7e16c51200b06d791e5e43e257e45efdf0bd5b06cd2333beca2a3a84354eb48662d83aef5ecf4e67658c851c10b13d8d87c874 +954d91c7688983382609fca9e211e461f488a5971fd4e40d7e2892037268eacdfd495cfa0a7ed6eb0eb11ac3ae6f651716757e7526abe1e06c64649d80996fd3105c20c4c94bc2b22d97045356fe9d791f21ea6428ac48db6f9e68e30d875280 +88a6b6bb26c51cf9812260795523973bb90ce80f6820b6c9048ab366f0fb96e48437a7f7cb62aedf64b11eb4dfefebb0147608793133d32003cb1f2dc47b13b5ff45f1bb1b2408ea45770a08dbfaec60961acb8119c47b139a13b8641e2c9487 +85cd7be9728bd925d12f47fb04b32d9fad7cab88788b559f053e69ca18e463113ecc8bbb6dbfb024835f901b3a957d3108d6770fb26d4c8be0a9a619f6e3a4bf15cbfd48e61593490885f6cee30e4300c5f9cf5e1c08e60a2d5b023ee94fcad0 +80477dba360f04399821a48ca388c0fa81102dd15687fea792ee8c1114e00d1bc4839ad37ac58900a118d863723acfbe08126ea883be87f50e4eabe3b5e72f5d9e041db8d9b186409fd4df4a7dde38c0e0a3b1ae29b098e5697e7f110b6b27e4 +b7a6aec08715a9f8672a2b8c367e407be37e59514ac19dd4f0942a68007bba3923df22da48702c63c0d6b3efd3c2d04e0fe042d8b5a54d562f9f33afc4865dcbcc16e99029e25925580e87920c399e710d438ac1ce3a6dc9b0d76c064a01f6f7 +ac1b001edcea02c8258aeffbf9203114c1c874ad88dae1184fadd7d94cd09053649efd0ca413400e6e9b5fa4eac33261000af88b6bd0d2abf877a4f0355d2fb4d6007adb181695201c5432e50b850b51b3969f893bddf82126c5a71b042b7686 +90043fda4de53fb364fab2c04be5296c215599105ecff0c12e4917c549257125775c29f2507124d15f56e30447f367db0596c33237242c02d83dfd058735f1e3c1ff99069af55773b6d51d32a68bf75763f59ec4ee7267932ae426522b8aaab6 +a8660ce853e9dc08271bf882e29cd53397d63b739584dda5263da4c7cc1878d0cf6f3e403557885f557e184700575fee016ee8542dec22c97befe1d10f414d22e84560741cdb3e74c30dda9b42eeaaf53e27822de2ee06e24e912bf764a9a533 +8fe3921a96d0d065e8aa8fce9aa42c8e1461ca0470688c137be89396dd05103606dab6cdd2a4591efd6addf72026c12e065da7be276dee27a7e30afa2bd81c18f1516e7f068f324d0bad9570b95f6bd02c727cd2343e26db0887c3e4e26dceda +8ae1ad97dcb9c192c9a3933541b40447d1dc4eebf380151440bbaae1e120cc5cdf1bcea55180b128d8e180e3af623815191d063cc0d7a47d55fb7687b9d87040bf7bc1a7546b07c61db5ccf1841372d7c2fe4a5431ffff829f3c2eb590b0b710 +8c2fa96870a88150f7876c931e2d3cc2adeaaaf5c73ef5fa1cf9dfa0991ae4819f9321af7e916e5057d87338e630a2f21242c29d76963cf26035b548d2a63d8ad7bd6efefa01c1df502cbdfdfe0334fb21ceb9f686887440f713bf17a89b8081 +b9aa98e2f02bb616e22ee5dd74c7d1049321ac9214d093a738159850a1dbcc7138cb8d26ce09d8296368fd5b291d74fa17ac7cc1b80840fdd4ee35e111501e3fa8485b508baecda7c1ab7bd703872b7d64a2a40b3210b6a70e8a6ffe0e5127e3 +9292db67f8771cdc86854a3f614a73805bf3012b48f1541e704ea4015d2b6b9c9aaed36419769c87c49f9e3165f03edb159c23b3a49c4390951f78e1d9b0ad997129b17cdb57ea1a6638794c0cca7d239f229e589c5ae4f9fe6979f7f8cba1d7 +91cd9e86550f230d128664f7312591fee6a84c34f5fc7aed557bcf986a409a6de722c4330453a305f06911d2728626e611acfdf81284f77f60a3a1595053a9479964fd713117e27c0222cc679674b03bc8001501aaf9b506196c56de29429b46 +a9516b73f605cc31b89c68b7675dc451e6364595243d235339437f556cf22d745d4250c1376182273be2d99e02c10eee047410a43eff634d051aeb784e76cb3605d8e079b9eb6ad1957dfdf77e1cd32ce4a573c9dfcc207ca65af6eb187f6c3d +a9667271f7d191935cc8ad59ef3ec50229945faea85bfdfb0d582090f524436b348aaa0183b16a6231c00332fdac2826125b8c857a2ed9ec66821cfe02b3a2279be2412441bc2e369b255eb98614e4be8490799c4df22f18d47d24ec70bba5f7 +a4371144d2aa44d70d3cb9789096d3aa411149a6f800cb46f506461ee8363c8724667974252f28aea61b6030c05930ac039c1ee64bb4bd56532a685cae182bf2ab935eee34718cffcb46cae214c77aaca11dbb1320faf23c47247db1da04d8dc +89a7eb441892260b7e81168c386899cd84ffc4a2c5cad2eae0d1ab9e8b5524662e6f660fe3f8bfe4c92f60b060811bc605b14c5631d16709266886d7885a5eb5930097127ec6fb2ebbaf2df65909cf48f253b3d5e22ae48d3e9a2fd2b01f447e +9648c42ca97665b5eccb49580d8532df05eb5a68db07f391a2340769b55119eaf4c52fe4f650c09250fa78a76c3a1e271799b8333cc2628e3d4b4a6a3e03da1f771ecf6516dd63236574a7864ff07e319a6f11f153406280d63af9e2b5713283 +9663bf6dd446ea7a90658ee458578d4196dc0b175ef7fcfa75f44d41670850774c2e46c5a6be132a2c072a3c0180a24f0305d1acac49d2d79878e5cda80c57feda3d01a6af12e78b5874e2a4b3717f11c97503b41a4474e2e95b179113726199 +b212aeb4814e0915b432711b317923ed2b09e076aaf558c3ae8ef83f9e15a83f9ea3f47805b2750ab9e8106cb4dc6ad003522c84b03dc02829978a097899c773f6fb31f7fe6b8f2d836d96580f216fec20158f1590c3e0d7850622e15194db05 +925f005059bf07e9ceccbe66c711b048e236ade775720d0fe479aebe6e23e8af281225ad18e62458dc1b03b42ad4ca290d4aa176260604a7aad0d9791337006fbdebe23746f8060d42876f45e4c83c3643931392fde1cd13ff8bddf8111ef974 +9553edb22b4330c568e156a59ef03b26f5c326424f830fe3e8c0b602f08c124730ffc40bc745bec1a22417adb22a1a960243a10565c2be3066bfdb841d1cd14c624cd06e0008f4beb83f972ce6182a303bee3fcbcabc6cfe48ec5ae4b7941bfc +935f5a404f0a78bdcce709899eda0631169b366a669e9b58eacbbd86d7b5016d044b8dfc59ce7ed8de743ae16c2343b50e2f925e88ba6319e33c3fc76b314043abad7813677b4615c8a97eb83cc79de4fedf6ccbcfa4d4cbf759a5a84e4d9742 +a5b014ab936eb4be113204490e8b61cd38d71da0dec7215125bcd131bf3ab22d0a32ce645bca93e7b3637cf0c2db3d6601a0ddd330dc46f9fae82abe864ffc12d656c88eb50c20782e5bb6f75d18760666f43943abb644b881639083e122f557 +935b7298ae52862fa22bf03bfc1795b34c70b181679ae27de08a9f5b4b884f824ef1b276b7600efa0d2f1d79e4a470d51692fd565c5cf8343dd80e5d3336968fc21c09ba9348590f6206d4424eb229e767547daefa98bc3aa9f421158dee3f2a +9830f92446e708a8f6b091cc3c38b653505414f8b6507504010a96ffda3bcf763d5331eb749301e2a1437f00e2415efb01b799ad4c03f4b02de077569626255ac1165f96ea408915d4cf7955047620da573e5c439671d1fa5c833fb11de7afe6 +840dcc44f673fff3e387af2bb41e89640f2a70bcd2b92544876daa92143f67c7512faf5f90a04b7191de01f3e2b1bde00622a20dc62ca23bbbfaa6ad220613deff43908382642d4d6a86999f662efd64b1df448b68c847cfa87630a3ffd2ec76 +92950c895ed54f7f876b2fda17ecc9c41b7accfbdd42c210cc5b475e0737a7279f558148531b5c916e310604a1de25a80940c94fe5389ae5d6a5e9c371be67bceea1877f5401725a6595bcf77ece60905151b6dfcb68b75ed2e708c73632f4fd +8010246bf8e94c25fd029b346b5fbadb404ef6f44a58fd9dd75acf62433d8cc6db66974f139a76e0c26dddc1f329a88214dbb63276516cf325c7869e855d07e0852d622c332ac55609ba1ec9258c45746a2aeb1af0800141ee011da80af175d4 +b0f1bad257ebd187bdc3f37b23f33c6a5d6a8e1f2de586080d6ada19087b0e2bf23b79c1b6da1ee82271323f5bdf3e1b018586b54a5b92ab6a1a16bb3315190a3584a05e6c37d5ca1e05d702b9869e27f513472bcdd00f4d0502a107773097da +9636d24f1ede773ce919f309448dd7ce023f424afd6b4b69cb98c2a988d849a283646dc3e469879daa1b1edae91ae41f009887518e7eb5578f88469321117303cd3ac2d7aee4d9cb5f82ab9ae3458e796dfe7c24284b05815acfcaa270ff22e2 +b373feb5d7012fd60578d7d00834c5c81df2a23d42794fed91aa9535a4771fde0341c4da882261785e0caca40bf83405143085e7f17e55b64f6c5c809680c20b050409bf3702c574769127c854d27388b144b05624a0e24a1cbcc4d08467005b +b15680648949ce69f82526e9b67d9b55ce5c537dc6ab7f3089091a9a19a6b90df7656794f6edc87fb387d21573ffc847062623685931c2790a508cbc8c6b231dd2c34f4d37d4706237b1407673605a604bcf6a50cc0b1a2db20485e22b02c17e +8817e46672d40c8f748081567b038a3165f87994788ec77ee8daea8587f5540df3422f9e120e94339be67f186f50952504cb44f61e30a5241f1827e501b2de53c4c64473bcc79ab887dd277f282fbfe47997a930dd140ac08b03efac88d81075 +a6e4ef6c1d1098f95aae119905f87eb49b909d17f9c41bcfe51127aa25fee20782ea884a7fdf7d5e9c245b5a5b32230b07e0dbf7c6743bf52ee20e2acc0b269422bd6cf3c07115df4aa85b11b2c16630a07c974492d9cdd0ec325a3fabd95044 +8634aa7c3d00e7f17150009698ce440d8e1b0f13042b624a722ace68ead870c3d2212fbee549a2c190e384d7d6ac37ce14ab962c299ea1218ef1b1489c98906c91323b94c587f1d205a6edd5e9d05b42d591c26494a6f6a029a2aadb5f8b6f67 +821a58092900bdb73decf48e13e7a5012a3f88b06288a97b855ef51306406e7d867d613d9ec738ebacfa6db344b677d21509d93f3b55c2ebf3a2f2a6356f875150554c6fff52e62e3e46f7859be971bf7dd9d5b3e1d799749c8a97c2e04325df +8dba356577a3a388f782e90edb1a7f3619759f4de314ad5d95c7cc6e197211446819c4955f99c5fc67f79450d2934e3c09adefc91b724887e005c5190362245eec48ce117d0a94d6fa6db12eda4ba8dde608fbbd0051f54dcf3bb057adfb2493 +a32a690dc95c23ed9fb46443d9b7d4c2e27053a7fcc216d2b0020a8cf279729c46114d2cda5772fd60a97016a07d6c5a0a7eb085a18307d34194596f5b541cdf01b2ceb31d62d6b55515acfd2b9eec92b27d082fbc4dc59fc63b551eccdb8468 +a040f7f4be67eaf0a1d658a3175d65df21a7dbde99bfa893469b9b43b9d150fc2e333148b1cb88cfd0447d88fa1a501d126987e9fdccb2852ecf1ba907c2ca3d6f97b055e354a9789854a64ecc8c2e928382cf09dda9abde42bbdf92280cdd96 +864baff97fa60164f91f334e0c9be00a152a416556b462f96d7c43b59fe1ebaff42f0471d0bf264976f8aa6431176eb905bd875024cf4f76c13a70bede51dc3e47e10b9d5652d30d2663b3af3f08d5d11b9709a0321aba371d2ef13174dcfcaf +95a46f32c994133ecc22db49bad2c36a281d6b574c83cfee6680b8c8100466ca034b815cfaedfbf54f4e75188e661df901abd089524e1e0eb0bf48d48caa9dd97482d2e8c1253e7e8ac250a32fd066d5b5cb08a8641bdd64ecfa48289dca83a3 +a2cce2be4d12144138cb91066e0cd0542c80b478bf467867ebef9ddaf3bd64e918294043500bf5a9f45ee089a8d6ace917108d9ce9e4f41e7e860cbce19ac52e791db3b6dde1c4b0367377b581f999f340e1d6814d724edc94cb07f9c4730774 +b145f203eee1ac0a1a1731113ffa7a8b0b694ef2312dabc4d431660f5e0645ef5838e3e624cfe1228cfa248d48b5760501f93e6ab13d3159fc241427116c4b90359599a4cb0a86d0bb9190aa7fabff482c812db966fd2ce0a1b48cb8ac8b3bca +adabe5d215c608696e03861cbd5f7401869c756b3a5aadc55f41745ad9478145d44393fec8bb6dfc4ad9236dc62b9ada0f7ca57fe2bae1b71565dbf9536d33a68b8e2090b233422313cc96afc7f1f7e0907dc7787806671541d6de8ce47c4cd0 +ae7845fa6b06db53201c1080e01e629781817f421f28956589c6df3091ec33754f8a4bd4647a6bb1c141ac22731e3c1014865d13f3ed538dcb0f7b7576435133d9d03be655f8fbb4c9f7d83e06d1210aedd45128c2b0c9bab45a9ddde1c862a5 +9159eaa826a24adfa7adf6e8d2832120ebb6eccbeb3d0459ffdc338548813a2d239d22b26451fda98cc0c204d8e1ac69150b5498e0be3045300e789bcb4e210d5cd431da4bdd915a21f407ea296c20c96608ded0b70d07188e96e6c1a7b9b86b +a9fc6281e2d54b46458ef564ffaed6944bff71e389d0acc11fa35d3fcd8e10c1066e0dde5b9b6516f691bb478e81c6b20865281104dcb640e29dc116daae2e884f1fe6730d639dbe0e19a532be4fb337bf52ae8408446deb393d224eee7cfa50 +84291a42f991bfb36358eedead3699d9176a38f6f63757742fdbb7f631f2c70178b1aedef4912fed7b6cf27e88ddc7eb0e2a6aa4b999f3eb4b662b93f386c8d78e9ac9929e21f4c5e63b12991fcde93aa64a735b75b535e730ff8dd2abb16e04 +a1b7fcacae181495d91765dfddf26581e8e39421579c9cbd0dd27a40ea4c54af3444a36bf85a11dda2114246eaddbdd619397424bb1eb41b5a15004b902a590ede5742cd850cf312555be24d2df8becf48f5afba5a8cd087cb7be0a521728386 +92feaaf540dbd84719a4889a87cdd125b7e995a6782911931fef26da9afcfbe6f86aaf5328fe1f77631491ce6239c5470f44c7791506c6ef1626803a5794e76d2be0af92f7052c29ac6264b7b9b51f267ad820afc6f881460521428496c6a5f1 +a525c925bfae1b89320a5054acc1fa11820f73d0cf28d273092b305467b2831fab53b6daf75fb926f332782d50e2522a19edcd85be5eb72f1497193c952d8cd0bcc5d43b39363b206eae4cb1e61668bde28a3fb2fc1e0d3d113f6dfadb799717 +98752bb6f5a44213f40eda6aa4ff124057c1b13b6529ab42fe575b9afa66e59b9c0ed563fb20dff62130c436c3e905ee17dd8433ba02c445b1d67182ab6504a90bbe12c26a754bbf734665c622f76c62fe2e11dd43ce04fd2b91a8463679058b +a9aa9a84729f7c44219ff9e00e651e50ddea3735ef2a73fdf8ed8cd271961d8ed7af5cd724b713a89a097a3fe65a3c0202f69458a8b4c157c62a85668b12fc0d3957774bc9b35f86c184dd03bfefd5c325da717d74192cc9751c2073fe9d170e +b221c1fd335a4362eff504cd95145f122bf93ea02ae162a3fb39c75583fc13a932d26050e164da97cff3e91f9a7f6ff80302c19dd1916f24acf6b93b62f36e9665a8785413b0c7d930c7f1668549910f849bca319b00e59dd01e5dec8d2edacc +a71e2b1e0b16d754b848f05eda90f67bedab37709550171551050c94efba0bfc282f72aeaaa1f0330041461f5e6aa4d11537237e955e1609a469d38ed17f5c2a35a1752f546db89bfeff9eab78ec944266f1cb94c1db3334ab48df716ce408ef +b990ae72768779ba0b2e66df4dd29b3dbd00f901c23b2b4a53419226ef9232acedeb498b0d0687c463e3f1eead58b20b09efcefa566fbfdfe1c6e48d32367936142d0a734143e5e63cdf86be7457723535b787a9cfcfa32fe1d61ad5a2617220 +8d27e7fbff77d5b9b9bbc864d5231fecf817238a6433db668d5a62a2c1ee1e5694fdd90c3293c06cc0cb15f7cbeab44d0d42be632cb9ff41fc3f6628b4b62897797d7b56126d65b694dcf3e298e3561ac8813fbd7296593ced33850426df42db +a92039a08b5502d5b211a7744099c9f93fa8c90cedcb1d05e92f01886219dd464eb5fb0337496ad96ed09c987da4e5f019035c5b01cc09b2a18b8a8dd419bc5895388a07e26958f6bd26751929c25f89b8eb4a299d822e2d26fec9ef350e0d3c +92dcc5a1c8c3e1b28b1524e3dd6dbecd63017c9201da9dbe077f1b82adc08c50169f56fc7b5a3b28ec6b89254de3e2fd12838a761053437883c3e01ba616670cea843754548ef84bcc397de2369adcca2ab54cd73c55dc68d87aec3fc2fe4f10 +97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb +ad3eb50121139aa34db1d545093ac9374ab7bca2c0f3bf28e27c8dcd8fc7cb42d25926fc0c97b336e9f0fb35e5a04c81 +8029c8ce0d2dce761a7f29c2df2290850c85bdfaec2955626d7acc8864aeb01fe16c9e156863dc63b6c22553910e27c1 +b1386c995d3101d10639e49b9e5d39b9a280dcf0f135c2e6c6928bb3ab8309a9da7178f33925768c324f11c3762cfdd5 +9596d929610e6d2ed3502b1bb0f1ea010f6b6605c95d4859f5e53e09fa68dc71dfd5874905447b5ec6cd156a76d6b6e8 +851e3c3d4b5b7cdbba25d72abf9812cf3d7c5a9dbdec42b6635e2add706cbeea18f985afe5247459f6c908620322f434 +b10f4cf8ec6e02491bbe6d9084d88c16306fdaf399fef3cd1453f58a4f7633f80dc60b100f9236c3103eaf727468374f +ade11ec630127e04d17e70db0237d55f2ff2a2094881a483797e8cddb98b622245e1f608e5dcd1172b9870e733b4a32f +af58c8a2f58f904ce20db81005331bf2d251e227e7d1bef575d691bdca842e6233eb2e26c2e116a61a78594772b38d25 +b3c1313c31ec82da5a7a09e9cf6656ca598c243345fe8d4828e520ade91787ffb8b9867db789b34ad67cef47b26ff86d +a8ed8a235355948e0b04be080b7b3e145293accefb4704d1da9050796b2f6870516c1ebf77ae6a65359edcfd016c0f36 +80e792d5ba24b8058f6d7291a2ec5cb68aab1e16e96d793128e86815631baf42c56b6205c19e25ce9727bd1fd6f9defb +816288c5d726b094e3fdf95cb8882f442c4d9d1101b92c7938a7dfd49bc50636d73ea1b05f75eb731c908c8fd8dee717 +ae009128d128ba2e1519bfa7a0c01ed494a7d461c3aba60f8a301701fed61fe4e31d6c79ce189542ae51df91e73ce1b3 +96a866d60a9007d05825c332476a83e869e15b11d7257172a67690ea9bd3efea44bf9c8d42191454eb04fcf110b16396 +8b250a2a06419adb9b611e89f7f8f2990aa301949b533ad3bf17c4a61ab5f5be0b1d5e2b571864d13f1bb75805c7795d +8450f49facf2e620fa45ee90e1801178842d927a2a25fc6ed7ba99a4eec7ae40eebfee41028eaa84f107f4a777694976 +91049080cf659c0985a22d1366e59191bb89663f922e8168b9b7d85c8a73d74a6d9dceefd855d3d858b493670c750581 +a1e167aeb2008087f3195926f1985c0a459d6ec57237255b1473a96de4e2c1cf766127c862c7dc853a6909e67cb06cf7 +b667c0d4e26e20698b07567358625d5f003839c92de8088e12dbd74a6f6a3156b4ea8d252c9ad62af5f6c4fec1cf6cc7 +8e4b5e304c0b1b161ae3e4b68b5e3ac66c42acd7c1ee2458044f6527c508a93995e50894d72d57c1350f91afe72775ff +8c642640aa7915421cdc21fd639f88a42052b1cfa358ff7702e60793a92b7b5926dae15a0c8f8f59cd3013f01c159ba3 +a356f35e713cfc283056bf539de54a21731e61efb4c47319f20de4a4b723d76a33b65f4a67d298b9ec5c2a1579418657 +93ce204146ce95f484dc79c27919a16c9e3fc14a9111c6c63d44491158d5838117d20851cc3227a5e8ba6ccf79e77f39 +b585664cbb9a84b52f89114e1cf0cf1171bea78a136dc1404ac88a11210b2debc3b7a55e702da93ff629095c134a295e +b6dfd444ec7fdceb14c6328f26ca12c3f9fc4327d8d8c68948e92e7e61262b82d833a65a9e3af6353ffa832b6da25705 +b4d4b8eb9ecfffe3f0d48fb4149c7b31aec1da7041ec03bd0750c52a2a7cbc3a7cfbf09d5bfdc56e3860826a62d0bb91 +a4e248e3d61db52da9683fef188579c470d65e2df9064726847b1599fc774049ffdc6ef2ae578d5ed7874f1298ecdf69 +a68a0fffc2e37d3183feb01b42234c0f4e510f9dc29d09c571e6da00fecad9da224cd0f31550070148667e226c4ca413 +86adda2ffecb77236c18005051f31f9657a0d50fef2a1175dfda32e74d5d53df825c10f289eb0ad39df0c64fc9bc7729 +998266d5c9c3764ed97d66fa9ed176af043999652bae19f0657c8328629d30af453230e3681c5a38e2f01e389ed8d825 +a05261554d3c620af0c914cf27ab98f5d3593c33ab313c198e0c40d6c72022eb5943778cd4f73e9fe8383392a7004976 +ad243fb3631bf90fedb9d679fd71fc0cf06bda028591ded2bd4c634ea7b3c2bd22eca2ab318fcdaa6c2cda1e63e1c57b +89b9859a04f903c95e97fb2951f01cc6418a2505eee0b5bc7266b4d33e01b69b9fe7dc56fa9ebb5856095be0925a422d +a68d118343a5bbfbbab95ff9bfe53aeb7fdbaf16db983e6f4456366df2aa01fbdb6ee9901cb102fc7d2bd099be2f1f3e +b49301f25d5a9dd2ec60ddb0b4b477291958487efea9e54dc0e4ef388f03b8bbadd13259d191f7a0b7513876767d8282 +8b93df7fb4513f67749905fd43db78f7026589b704ebb9ea3255d0ad6415437799f40f02e07efccda1e6fd5e8cd0a721 +ad88769ace96455da37c3c9019a9f523c694643be3f6b37b1e9dcc5053d1fe8e463abebdb1b3ef2f2fb801528a01c47c +80f0eb5dcbfaaf421bf59a8b9bd5245c4823c94510093e23e0b0534647fb5525a25ea3aeea0a927a1ee20c057f2c9234 +b10ad82ea6a5aeabe345d00eb17910d6942b6862f7f3773c7d321194e67c9cced0b3310425662606634dcd7f8b976c04 +82f6fd91f87822f6cc977808eeac77889f4a32fb0d618e784b2331263d0ffa820b3f70b069d32e0319c9e033ab75d3b4 +9436d3dc6b5e25b1f695f8c6c1c553dab312ccace4dac3afddc141d3506467cd50cb04a49ea96ea7f5a8a7b0fc65ef37 +8e0a9491651d52be8ebf4315fbbb410272f9a74b965d33b79ff1b9e1be3be59e43d9566773560e43280549c348e48f01 +8809137e5d3a22400d6e645a9bd84e21c492371736c7e62c51cef50fee3aa7f2405724367a83fd051ff702d971167f67 +b536a24f31a346de7f9863fc351fa602158404d2f94747eebe43abf1f21bf8f95a64146c02a4bec27b503f546789a388 +b5cdf5a04fc12a0e0ef7545830061dff7fd8abea46e48fbe6235109e6c36ee6bffcb9529e2f3d0d701cf58bbfb6a4197 +ab15377525753467d042b7931f66f862cbbb77464212c9aa72d4e5c04375ef55f619b3a446091c1ba1a3b5d9f05e538f +905a75b943ad017ff78ea6ddd1d28a45c7273ee1c2e5e3353685813793ead3370c09cabd903fcab9d8b1c6961372d486 +8147df4324faddc02fb0896367a7647b719b6499a361aecfdd3a34296fa6768ad31c34f9e873fd1e683386c44651883e +ac91d08570dd91f89d2e01dca67cdc83b640e20f073ea9f0734759c92182bb66c5d645f15ebd91ed705b66486ed2088d +ac6295ef2513bbea7ef4cdcf37d280300c34e63c4b9704663d55891a61bf5c91b04cc1d202a3a0a7c4520c30edc277c7 +b604be776a012095c0d4ebc77797dd8dec62a54c0559fb2185d7bac6b50d4e5fd471ac2d7f4523206d5d8178eabd9a87 +80ead68def272ce3f57951145e71ed6dc26da98e5825ef439af577c0c5de766d4e39207f205d5d21db903d89f37bbb02 +9950b4a830388c897158c7fe3921e2fe24beedc7c84e2024e8b92b9775f8f99593b54a86b8870ec5087734295ba06032 +b89ba714adabf94e658a7d14ac8fc197376a416841c2a80e1a6dde4f438d5f747d1fb90b39e8ea435c59d6ecda13dea1 +b0c78e7cc60bd05be46d48fbb0421a678c7f14b8d93730deb66fbe1647613b2c62b5075126d917047820c57fc3509cb9 +a860c4acc5444e9ae987e8c93cb9a5f17d954d63c060cc616f724e26bc73d2c54cd36e0492d1fde173847278e55942ba +8fb8269c9d5c15428e8d45da1251e4c4a4b600d47da0caea29fef246854d8fb6acae86a8e6440d0c429d8dd9c2dfee0c +96c5d8eb6fd5c525b348ee4335d200139e437e4be83690af0f35b7f336a7cda8c6d2958647988b84da9f2dd7bbb7710b +a7f62141c4346cc14e9823dc38ac7d587b0427022afc1498d12ee2c43f6ac3a82167057e670dd524b74137f8c3ceb56d +956aac50d06b46a3e94397f163f593f5010d366aa2d816c2205c7d0f47f90cf0f36c169e964f9bcf698d49182d47d91f +b812899bcdc0e70d79ca729cb01104bf60e1357b9085a10f64f3ba9865d57e9abd0a505a502d4de07afb46f4d266be2f +abce02c7e1372e25d40944dc9ece2904a8f59c8854c5f2875fe63ace8ce37d97881f4f9ab4f7bad070ec8e0daee58d3f +8fb13c515b2d6abb4e14ed753fad5cc36c3631dfe21a23d0f603aad719423dd5423157eefcbd9a9c6074e155b79eb38d +a9ef67304dc297ab5af778cf8afa849eeac27db4b6978963e97b95ef7a8d3264d0d07775f728c298a2b6daed2ecf5053 +a9b975520adb066e2ff2a4cde53284c23bc84261a22dc43b1634d99eff8e7892e46bb6e6da7319c9e72788aa9ea7a1ea +a6eaea4ab4206294474d9b956d9d3188d558a5633de2bd05df0d3bac03dbcbe4ed85406349c1d2e660b77c6da1f5bf8c +af4a19f77290dddee762e1e0d4bc9945aacea3f75756ae46cd3e58a8f74d1b5db73e4834687946b0f39191e32f2fed0c +aafa6523f58f1a4cabc924c86d842816d606afeea21fa4b2b8b9573425810fdcc41c98888318e868f9c05e2be12178a3 +8ef38fba0a3fa4ebe985239c8b759c22aaef0c57e6f39050a651c869487803b0d1e389c3d958fb5a7f37740f050ac69e +b07dfc9f85913c608ca7596a2e361f05e4853fad00e796fd492d247de6414892ce160f627669b1ba933b6ad726415d4e +94da679ad1d78b2bff5283c938f17b2a7d6e9cbcdf59d340e6dfb652951c7a9e852ac0590f99cfee9631b9410f6f00ea +98a907c9c021a5b034d3720197c160a82c4b7146cb73d48efeed99b9d0c6b831812cf80ac7e19e85a676a8cd3ead72de +adb746595466a12929019d0048cea33236b05c1229d2eba73b259a18a786f2bc3f05fc0598d8ce253cecb80bdf679aaf +a2fbac016996d68f9027a157b0a3f6a336144a798d6113adfcda3a5d05b62c31f108f112aa915906aef22b7f83b9228b +81841dea1904406d1b6fa49b4b3f7f6cb40b7646cf44d36c9fa07e3dee29f8e47324b40d8356ddf653109673c3374e9b +a3edbb8aac5e60c775775cbdb19067341b2e2530de48738e84c2c07151241ee31f0d8333bf20c2bc9dcb7b2e638a6b5e +b8aa6890e22964828787ce86460d3a32f12a655bb5c28de500f2fcf6b61e3334640ec6ba96029a4912af0d18df4b4139 +8ca43169f04243ad0fdb0152de17c60d9e31ee0ab520970fccd98590e05508821a183b4b367967e60d53c2c826ec5dbd +b179fffd9df8c00486c5a8b9327d599f5a11745ef564f06e126849b06fe2f99273c81f65bc941efb0debaadfecbfec1c +acf068f1c2b1926279cc82750ce21b0d6b0bfd0406f0d8bbfa959bd83935932957c7f6b8de318315bf0b75f6ee41a0f2 +b97831da260919c856e9f71a41687f5979bc16f8a53b1037285b4a2f9ce93af5cfe70bf0ad484744827fb55c847b58eb +aff50b0bd907383b0c241727af364fe084d021221bfb1b09fb6c1a7752eeba45d662493d590f1f182764b90b25f17906 +aeeef044c14e3ad41e1235c9e816e1eb49087fd3abe877b89b3bade74459186126e160bb569bcd77779e701b19b5f71a +8483deb2b7001ca7c438fcdca8ca6aba96c9cbc4becfd9b16a6062705eae270011bcaedcae69bb54630d8c78129e57c7 +aeee8d24be4ac0d9784c029e239fb5e64316ce29b88f47394cfaaa8bb966a72061bff72f99d02dc51c9705854686e77f +90ae09525a16bb2422169e15d6831c87968a14ebc0d1d27e11a759839c73c655b9d33ee5b12f275d6f440688146fbd2f +a3a41fc7fefef101422465e506bea7f3ff23c26fe35f5732b86f5f2471fb93b37ebc339f84c6be1e8d22abc812c2e212 +86f4b5293e8aea4af1f1fb05dcf99714cb3aff1cfc849b1bb73524061c921c9da9ad92579a852e1889da29d952f02fe5 +8932ef39d4050a1e9dc0fd8afeaf159472d71c5c27f458c69d2730836606ea56e19c8c4febf2535f930d3260e9bc7637 +86307b9f3696bb21c20e4558e30310389e7367803c353d437e9b696039a0ff054d9a4953b75237ab1d1dd6f71118c189 +96e57730e683ef5b550c91de18b19ac73879f3e26234297db68d28747ed0953beb0f3913cfb720c602720bf9330685d8 +b04a19ee70123782e47b238abde55baf60ac0c66292a998af0d14afc8bbeb1134e557b94cd17a020084631c09a0d3c02 +829abc8718be8139569fcb2c398962f38f4201114d30e2b2fb23566f8a27a5c380f5605cec543415202a12ed859e33f6 +a0744fa488c8fa92a722c5fc4ef5a47dfe824eccd87d26c8bab9c174cbb151d44b1b29082c48652f03d3177e5ec86001 +81d4035ae9fd28bdcd78b135cb54955d3b685a527319df6ee7e904b8e6d796f5f5a5f5035ee1de750c4cb6050e452b9e +b205e8c2ec24d7104fa0106c09ad34b5a912c1adef553fb718838dd627355993c2ec01055c11d00b2c75b68e9516d44b +b12d09da7968fa7394e449624fc7174d1d76c069ccb03e140d4d87a2d3f6d1f7b9cfc930f0c80becc673406ebe63f08e +b23752c158695da85048fdf38b395681cc0e8998630af8a9ed41efbda08c9964c2dc8ae6e53377264be4467d702c0de4 +b0d84582fd73628d96b8c1ec96197697c41a963542451a2ade0890af0d33c7161d0f18e1a1ce2c168ca2dc1e9119d55e +8b877e618b469aa187632e410b125d2999d5738fd66d482000706b51fd904a0c7e7daa8c9b729fa33817bbc4154cba2a +b1cfc8a7551b601723b937d497d01dec3ee7614c2bf13d430b1058d5ebc1406045009ff02c2ac15bf8cf16f860193d1e +b6d9da84f97b21e13175bbb0b5cc8e79e88b470c87a3e115726c1bd98e0288526c58f3faaa8aa170ace0cd6a60852525 +ad2e773c2d527671ca5fab7085dde4da31cd35f45d4315dd95d8893ff5fb900494dca08eccfc1a2fc7bf7c7fd2fcab97 +8d5a79b34aeb761d4a0c73f09f02e9548e6d382c33ee6887a759ab05762b490b8a549ef2933c7e3a46415c154c0221c0 +b6f2cbe81bd0a7298403be392f8456bed30aed7ef30216959357698f789affd2942ae5fbaf3f48ecebeb7c273b20cb57 +b5b6c45d99cea7ce6a1dc134aff4a8f630f299b42bd59592a7592345f8cd35bcbee944e61b0723de732fcad6e4425b63 +8077d64dfcb2418974e956ea6dbf8a4c05b25d2a025333ad7e2a379f1976dc036771403383a51bfa3476c9c619ef8bef +ad2e0a9d479c77a5fb73b3613a177fdaad50dcb50fed50e756ba18164c153af30b07fb2565e80ff7469f1b0338b7b5de +81017d1d80a6b6df4e99d0d7f85a8180b5523e8fa2ea2672fddff604933f8a113cab27fce098dcb454d7d1f7ed266e04 +852355479d68e76c7febf6dfe2ef8e80d575c0d3bd52c983803592021cfa898c571c0b884412c21e66f0dbfe03167b53 +98e1bf8ad48421467c93b9f72b47dded7c41b4fcd36ea55ca43ab24b0d0b876f5a731f422579b7167c7138fad2121266 +803369314abd5422019ed4b0ef652b4dbe97ef5a87b0ea373eec9628b64a12120b2c3d4eb53db405131ff786d14c7ac6 +adf2613fc34f73e1160975c140e925ed84d254e03cc3bc7fc1d19957b499c9ba9d9e4c1639981b594a7095c0a52c6757 +a2f6a68efdff6e4173c00692abcfdfcdaf6f8b62369afad3dafaae4f2f38c4860780b4624d185e20e4f4498b75b5fe94 +8b1658aa0e119fb8401d486ed08d60240d26a8623ef9788e3b45ad09ae31259395b021bd16be395139cbb7149714e764 +a7dd8bf21121285e00672ee8bb84e0cb39b2496fb53a26e35dfbca7f2b04e9a9ff9db15f53fe63fcbeafeb2deeaf2ca4 +b6d8d709e44bc18f3b41d69608edce60c02bcba48d3b7e2fd420842657f0665a7343246dea149a25e8f3416284abae66 +aaf744ca5e9bcb63e3e2939b7a1e96e4a93c88c76bec0cf4294dd7db95cdd3f6a7d92196e352d08680e2328bc4592899 +84434b015a7c398d35f1ec71fce455d62ba4ed4f62da042ec31bb2b4db47073314354cd50bc322297a1cfe35138bf490 +8d70b3a3cd9d5dfefdacfa418c0b775a112a47ce538d33a560a519660009c3f141fd6221c18539129e9c0acdaceeeb80 +b8c6903412a800ec78a4c15f31c24385a267b0c0ece32fd31bbbb557fd70c3b2d60d8fc0f90fbd70f43baa1928ea30ba +8e391dd445ea06cabb433f057853f8159511b2f9bef41aed9ccd14e0a6fcd912bbaebd38fd5fb736cfde0fa34b7a4874 +a40cd988f70613df32babbd1bbc2f1b29ff1ab0147b01161555a81d56c9621657999bcdb1df38485f687afc51d5d0f23 +b6a008b4426b3d7b28ae04eee4698fc8ef6a35d89008ef5394da39ce582ce1a45dcfae9a33b90f6fa4237f3667803873 +8987280debfb175c3b44a2f152ea82548e4f680966f1fcbee9bf7d714e31bf8080c33f52705ef3aeee70544b22516aba +a78a51a2c11eea7680a5a0ae417a2981f8c69c396e06da621eadd7510a3664ade49d065617bec67b3de779548a4f4509 +a4d9163f0a1bc048385e94d5e0bcafeee1b18f28eb23505623b9e8ef16f3df76408254dfbe790e45f2884198060d388d +83dcae2568a0c518793c0f6e38b42f9ceb50673d100b556a17ec8bd9faeec84afe50b8d72422c6b2356959667bb8e2de +874731941be4474b4576226e5906b5dee89fc9b56a9870dcc7289c1a7d494d345ba6aba31f7546a16f9963283c05f744 +82c1cfab1f501189ac20147fc4631075dbf1abf9125b7d42fcb4f31cf73f3d6461b1bd08fdf6e45cc54bc08a7d5d51d1 +b978228286f5d4a10ce027b6bea3021affcaa805340ca4b5192c69e8c56db59f48e4a14a284ec015f53baf97389f62b2 +af125f4fdccd1c1b64fdffecb5ec7cf8c7392bbe476e1b89a5b5329c5ba4a526e58c11e72ab9de8a38d60af648d75adc +8411a41ec14295acab0d36389013535a80dfff6e024bffeb32fb3070762f61256419e8c51b2ad6de9dbe4f1e8e286912 +8ea67a91112a41f9c65515cd496f4b0cdefa1400fc06568eef000c9eae6dc250fb7622eb3f2deca10b37287cd96fa463 +8da99b6c55c31dee6a49aabb54da249d348a31d4416201a10c45a3b04b11e99d4ae9813632f0ee36c523b5cca62f6f49 +8b44656341e039e2bd83a19c3bb9a88f6209482e274f8cd4f8557b728e5948dd80b5745f621b96f4562928689314e8c2 +a02d424a615ba0dce8ed91f477e79852215a3a39d025059826fa278e7eebef19824b2a2844f5b3865a0f471b609a23f5 +a1f115cebc3fff3bcf233da27cef19eae791660f155d088003460f75567a550bef0722885010ddc384acdeac635939dc +b61a55ce9d143c17876776e064b58a10baf0ba13553c785c1e47f57b5f94c0cda8bc89d43d73386e57816c15b61a8ec8 +b4073f47041e20a8e548c7fb00e07ba3b9056c34eb4ab63bb0e7b48f8e338e8b56a17611a1b5f4c03b352450b86f1d69 +a7b1a07b213205b682fc5b6acb7e76fdf97b280c26621d8f3b76b7c1deb3511957da33a4e358c8e8f3d98b2a8855d67e +b797e67c2670fbd9844e8a68c585f404b035dc14bd4ec75c3f95f932c777f9db5d5f5df7629164af488fc1213035cc5f +99618200797b945f595794d6468e5c618649554ad9ba896330f1cc844090eb956ae9fc23132912f9047085c5f0c3bf7b +81194aa1319abf534cb3927af9adfb178a99d0e3e8c99ab1105f1d3b4fed40ec2971caf1d6647acb0c8d681eca53097b +80673f18e4978dbc226a6cd4b128a1259d9a7f833879c6e2fbe24d69fef2c3c23a51a4f3e8d88fa4533434bbb0723661 +8125bf6c7dbb2fb63aaa3f53283559f172c788223674adbeb6d5bd17cfe888e6b87a79aec774917f20ce911c1f85f8e7 +884bcdb1878b14fc38adc9fb8b4dd0b3afde404fbeb664f26ddfebc81736018551f23e75ce4cfe4865f610bcd454fbd7 +aec65c8d4be8316e98aa54888af01bc6703a0c5d04b69756ff39a0a947b66817ec59d76afe9f61a25749b5e890f03e02 +aa457aaa1b014a4c5a8992847a187a23321bb43452c98745987d038e3b04046102ae859b7a8e980eea978a39d76a88ef +a9832ee63b08e19123f719bfe2fe742125f32463efa966c7709a98ebfc65277670e9ea1fa2d2d78b96bdc7523b0c4c3e +a87b6b1b7858f96d55064274f29fbde56067064962cf3c3e2ba3110b22ea633bc037a74d23543ce3307a46208855d74f +897cbe4ab68a753020fec732dfcc052c7ed9905342b5a6fe0aa25c631f9ad9b659e0ee75d46f0df6507b6720675ee28c +97c3b5f0d54c1fc45e79445c3ff30458959e406a069f5bbf7979d684195b4fa0406b87c1c008f4075bc9e602ed863152 +921e65d582ea9322ddfad1c855331c3cac81f53c700b96db5305a643c084eb6793094e07944bfd41dc02c3b3cf671530 +8f23ef1aca02a260a3b65d25b110f28d3bafca44727448c8f2d03c5e77eda620c1721b06681bd816ee6027664d76352a +946a89b132ec0795aea9ff9dde7b77e7feafffe6e4a2f093042a7e6c71cd6ab87ce0ca914a1b5fabad4e1f96a795f163 +a01e2de9db33df6511172123ad6f7c64074237471df646b32dd9aff8c15278e2723108e4facaedca97e9f49503f8c792 +99dcdcde45b2ea3f15279936feede5f7d3b63ca4972f335b0559c2fa6f9faabd8127aa892a36deb114357ca906553ed8 +a3f8af37bfcf66b04d1896a4bd5d343f4733d4c3305369ac7e75a08f20f2004c10c642d2c7577f4e5c4d1f2cd851ac3b +b7294d15a3d674a56099f97a1adc9e82c15e90832eaf1722df110fc2abc8634c51515e5ad8522015498a3753b1fa8c49 +b4f27f5062ba7a04ea0048b3025b5e3d5b5d319a9e80310c808a5fb4e8e77b38c10a0f3172cb805cadbcc8bc66d36ec7 +aefe5decee0ae2dc372cc6cf4217daf97c4c908d145f100f0daf1ccdfdf641c78432c2e473e7e4b77dcdf2d4c2bb05f0 +acc84af7648a535ffd218c0cc95c8f7b092418c548815f1bafc286b1fe14f6ccb51b2044db3bff864d0bb70e88604084 +84d8e3dac0df6a22beb03742e1d4af684f139f07e2ea0f7fb27fc2d7d4f1e89b5e89f71af32ff115ed5e6092133535f0 +8ada001e1a03a823c4c056f636e77adc0f9dc08689d28de0d99e0feecab5db13abf37b41ec268dbdb42c75419a046c68 +87dac6c798d1744dff81d8bc3e0e04f3c9bf260e811685ddb9a9a8d6eda73927439b344f9a818d2103fad633de5a4a17 +ad9929a7d8a7d5d5954e48281a87e5c84f67e19110d73296b9989a09c76767a57a8115629239ffb4d99dfdf9c52ef6d9 +81ac7cbeef8ec35a5c3b61cc887080c29e6cd3e08af37e45830d17400dbacfb374dd07bf370b979828c3875b2027d5c6 +97f92c9182953b7e10f7a1bbb6b5b5c40b8275eb5a6eec1e29874c4712814749aa8c409651380216e1ff01d7b8511041 +a09794d0bbe7db013045d3fd857c1544fe6231d21afa3495fa300371f6301a3a0f4b8ea175b281503dd06078ff371ae4 +839bb58d320aa08116dd387a57a2b9bd9efc89c4cdfd82d0e47a00cabe644631d09be5436bd485df3b61b75ddf81a3ef +b1cdaa344f783757e8b9c1f84421da3c5be4c69f019a8fd4c1aa5bf1a63e8970c99e35c22cf3b48a0e6738bc6ba7ce8d +92af68e3216c78998208fb24b5ba0e645d0d3f5e28222b805668d7e9cdd6c033d3b22fd6df4c2d745d7f910d133cd226 +87640a4ea4e605e2204e5232b29a6c1c31152d83547eef14122cb76a0da52b8653801af48455a3ed713b9dcfee7b1ef1 +8147e5bf0c8f4731155ca0517ef3fae5a32b4d5d2d98ed0007b23893d8dbb7f8a1199c50c1750c2fa7c9cebe594b1bb0 +a76b4473c63c3ab6103c729afd2482822e4150f3155af39983b0ff0766c71cb622455ce6304e23853661eaa322219d18 +b3e2f05ca551bc3adec0067e4034aaffd72e0b64ac18ae25452c996927976c6727966e26d213b032521889be2170800d +a8414cd14cb3be658e9e0004ce511ef7063439b1cbc3166a11de030613fde4b59caad4e91d426927863c55382afbf476 +b2f0f8ab99f4d0ea785ac84fdbc00b20217b1df59b30b51d9d209d489d53b69dd5d82cdacc16fd1dd15c3a4001595f50 +8b2025d5fd658c9bbed619f3e3f6ac8efe7aeff8aa9401bd66a7ceb0062c44b353608ca073f95be99204f0a913bb77eb +94a46bc5a87291b42024b2137e623c70115b9c6b196604106bfbfa20f3f56ac7779763f56b580190d3cb2f1c648cada1 +aca9355545118d0769cacf69c4b23d6d68d229cd8f68f1bc0c847c05569c5af6bbbd8c4dceb637b4a6b3b5c83841bf5e +b0731992cab87c7116406b283a84707a34838bfa3284b0f6082dfabeaf41c5ac2b0ddc1b420547a1b0955aee92de2dc0 +b671f77588c0f69f6830a5b28e7d07ed161b81fa9791bb3a24aae6638e3aa5e186df74978a82549c370c18ebee04d4f0 +b5621ed841780f3e6681d880a76cf519cdd20d35197b112eeaa686764d57b5dfa78ffe1a294b6bc76b6e3949cd2a2369 +afeba2524659d00caecf089645611553187a6ed7102050f6dd20f5a19bed08ac7065912d88371ee06242897d58d652a4 +b78bfb83d44ced14a20135804aba3f00128c3ce1f302e95567ce4097b0d973414153fb305b9f156882a5a0554bf25973 +98510aede95d26b1adf214053eae051ffaf24894e2fa37961a91d0ff5392dd09388196648d95b73e90bd88f2587cc4bf +b35c682d49c295946b9f120fbc47b95abd9ee86d294abb003a92139fb825b509209562575015856a270eb3eea86397a7 +b9641bf685571dd9c478dd2033a1f1b11cd3a662b26502c78595863b8e536a189674a9a85f7a253453ebfd1b99fbd841 +b2ad37036a59b1c9b8457972665720a6868422ed8157b6810a9c0783006103be34ab732d7aeb8629653edd18fd0f1717 +af0920cff05179a3896ea6ea322c39adf91ada5bc40fe3f6fb1b1b4e121e907c904bbaa8ca00468b3749f3da144d71f3 +8e269672818ef1e2f9e0c8aa65c84442fcd9151d74bb8e870cee8c0e3fe24526e1a5388b430cef47b67f79b4e4056bcc +aa29a16fe00ea3d143b1032b1dd26b8ce638f37f95c085c7e777e8e2784bd724bd5c38b1583c61a6ec7c451dd78fd3fb +87452b7435911cc5f513b0c81b15aa04972ecbe3d7bbd0a5d676c96a8a311301c0e07fac925c53a350b46fbd3d4d0fc1 +869a81c351096f47748e41566ae7b77a454b1cdfaa41d34a5742f80df38fbf5cbb08924b6fdff58e3b18f05c62bbbbb1 +8b7bc1b0486300981147a40a449ada9a41afc06d735cce8bf0fab3ee94ba2e2ea57b1397e3cd31bc295352beb8334ef7 +93e93fc41adb2df279d95654921b4c2edf0d293dab58d0afefb221f777349ef88d0985b3447e3b935954a81f1580a92c +970fa7cdca8324faf3e62348bb50d78f580b4f43f2e1c11bd8382d48d0074a3c55c6407203a0c9cb1c5f2163ba421ef4 +924983929e608d27e4a36d4ed919297869e3c64de51aca794d32d6e90aea546bf898d98ceca28a0b2187734821b78504 +8d395332529c703d943d68415d443332b5c1342ca9d9a59bfa8bd4ab63e93358c4b0dde6ce1f2e8ea9dc8f52ad7ebd95 +80200dda853e588256599e7f905add5d5ee7c74272780317694fbae39318ae9be05d5bcd7b20cf460069743f3d4ef240 +a287d51d6359c9ef7c7ac1b20e479ce7d0146dba5606397bd04b7a622cec642508d5b45d51b31de71f9763595b6ac88e +a320396c075175d6599225cf2e1de8c7cab549f6316c07feb0f6eaa21f06b2dd29ab14fbdf2af4543b4890ec0fd08a4d +b1e9fe230418d20368691058adcbbe30011bab3000422f0371015ff8bd09c60fb5fa85d18550d35b1c900977ca48f58b +9718fc26a51783b971744933f20490e9b5cd9162f86b84788c4c5217f5409e37b5a39d628b18e5b35a757acf67596321 +a0cf81fdb161f4f1b419c5e4caa36d4bdca2325f0cd25b119a30178016f171bd6fb88403e4e3aec026c4089f180d540e +8ab1e36bd04625ee794ef04c4dcb8e004d61aceb2b62438377f49ad95dcf025ba25eb799280004941e555bf7172af6fe +9257b9e3d14d37fc7efae49b0c68d36eaac546035f4a2654d566b3ce1b2c4564cbb03dc8ec66efceb768559a8a507a18 +945d1123b839637ab5154a1972c3c83a0ff34a3b1a3465de6ef0416b1950f649869a3ef88d7f1036648ee385265ce2df +81449639d708860fc0229c94f754f7262e8a3c7f67960ff12dfd15df95f57a9ffcee2013e81978b7703dd42bd5d0816f +a865481deaae5a690fd53892791e5fa729db283b75a525a11cdfee1ce17e8e7f0b449d25f20b3c1b43da128dbdf98a8b +98766812a65fcd25b853546e3bba618a3edc9fd61510e4f8ab60c038a7fa50d197abeec8776109df0f2119be9445ad00 +b1b8dd5379d903dc41d74e999b1ab693607a0d2905692f4fb96adf08f738e5d31f9d00df28ccb8b5856145ca552c3e3c +99d20be7b511bec78a8ed03c207aa4aa9097ba39d85e18f1b8d52f65431ab7e9a773c7b9ac3e8d8b25458bc91bd00703 +b1b7c3563fe8cb33c7d3e0b89d00bdd13e86452ff507c2e69db7b3af06f247f139155396e9b0278753310dc63940a10b +b3dc9c08451b1de7c9969b1e47574bffff50490f4a16c51e12390195d9e9c72f794790caf7b0a835d64e01fec995d3ac +aaaa4761a00022ede0809d7063d3532b7bfae90ff16f45e17a340ad4ebaa2fbac40728ccc5fbe36a67ab0e707566c5dc +8319a1903314eab01f5442d2aee6ae9c3f6edfda0d9a88b416d0f874d7d1d05d08bb482102f8ca70a4fa34836d0840c1 +932949a6e9edfec344932a74d4f81eec3667ece1e8b8ca840ce07ffd4b5d6d8f01657c764d64ac1b9190f876b136490e +904db1568128487e312fe629dd8bb920cecafd3bb9cad8b63e269ae0129f2f5c80cd82f0d81e7feca9835c3945a72d28 +a17280693d30dcd43c85de8f6b02d5f30cb9097274ad680cede1ef105c903615b4c40f3c6aaca478642de324972514e0 +8d5f76e093aee71d0cdeb017fdfcb13bd068039746de90690ce150a0bfdbe7ddc4d539df0f82c2d2890a40b191900594 +96fa1f2196a3883cdd73c66d28403cbbb58f6a939a3697ee0d308d8a076393cbb4be86255af986869230ee410c01bcfa +a8b74438dc5cabd70a91bf25601af915c4418d074327a9b01e0190c27d3922c89bb9b41e0b366e82e313edda8f21983d +ac9fdc1a9b2e3ff379eb2370979372e13c4177bf4574f1490fadf05a7073e6d61e703e2d8eed9ce984aba317d411e219 +a45a6c9b958169f2f8df70143e6ac3e2f6f969a4eed6fd9f1c620711bc2454739bb69f0094079464790c5429c0d8aedd +8901cbdd1009864386577842c1e3d37835fddf834064d9613b4559ea9aef3084204e1f863c4306f874141f4374f449ff +b6c582161691e3635536686825be9c4d7399d668a7675738417e0363e064dfd28acdbd8dbc9e34c1dab8a1990f1f0eba +89e89ddaf3cacc78428f3168549c161283ca8337345750667c98212717b21e7d994eae4e45bbddacc832a18df1d79276 +84be275627eed8e1a73c7af8a20cee1ef5cc568cfeea7ec323d7f91b44e9653e9aeed47c1896a8240b99dde545f0e1fa +a779a54ab4f40228f6e2539595fb8d509b70aab7c19e1928c1be69ec1dc19285c3898cf15e5f8b8bc725e13af177fe17 +92e2a49d2b9b36349d442283b17d46f8f9bf5932c34223015ce62d2f285e7363b2c12232be4a838b5b6cf08e694c094c +8b4e28c6f3f36caa2cfb82ba88066c830f8017bd35608b077143dff236f3181230166f5a5c02fa0e5272297331726aed +85fd77d46162ffac4b8adb25baff0eb0512a53a3d01638b3a376ea34702279ce21c8e7d8884308c03e00c9bcc1a9fd29 +aad5e46916ff1be29009b595d1d8fa160cc7aa01c7fbf3a68f445c87615790dcab1fcdbdceda533d182b6541f09f2f73 +948df7654726250dae393325addd3c0a20431c81f00470962190335ea4b6d9f7463d6f308cda46b92084c1f24390b1da +8f577474dea132676504376c5542b730b6604fe3d965eaa194659fd11c52233bd0b11ab62e198c0f442327ff1c00e501 +ae2f1001546db3e0c19700adad997cd9f765fe7a51a502cbcd9a2a07a3a5db79c8f603e05cf96d80b688cb6c9b6cd3ae +953b68e5d9561088dd20406ea7fb6894cba33868a38ace38fc30b5813140cb15dd6dd2171befae5b4df2e4a9658889d8 +86c52901655ff11419b084a04da8fc3596eae59d81d3461601c0baff59ba59e3d1dd0b7ce719e741a3e97c013e898579 +b9a72dd5eff73f9912a28b55de073568efb3eb0241a10b77a2bfd4f30c2aa4fbfe0c89eb345c9f07fb725660873cb515 +8e7353f5f2932e4ffd95811caf46c9bd1a53643c27eb41a4ebd211f230955cd71a8b27e17cfe8aa708d8514c0de67a66 +a096b8e66312a92fb10839ebe60189a8d1bd34dff55f7dfae85e4d2f53a1a4a88211c19fc84494f066358ddce82be131 +931c5cd82719d76596832b007969b5f75d65cffabb41b9dac7910300db677c1309abe77eeb9837a68c760bb72013b73a +8ba10f5118d778085122065b55dd1918fddb650cce7854d15a8f0da747da44d7b12d44fc29ad7dc38f174be803db74c6 +8c971deec679372a328587d91fd24ab91043e936ca709c333453d7afd43ee256d08c71cb89f0ab0e89ae119831df6d86 +a2ac28a58034fbd8fd518f409221bad0efec52670880f202e09c0530e2aabc2171ed95e99891790596ffad163d86c110 +b3354e3dfa8068aba4f3741152b9204baa4e342c1cc77e6dd1419cbaf8da1d118be605846b8609e997d6a62a11f3423a +a12ab65a213c9d95c24865fddc2dffe0cf9fc527dd6bcdacc1bd7271e79929a4ab3427a231f4f49d0530474e6cbc88f9 +90afd65b7e6973f8aafbe74da0f42441840d3c93bd69bc1bec8fa56824e7ca97ad1b427c8a85da7d588469bd4ccc50c3 +a09175940c59489bac3d3da3a4091270d9118948cbbdd57f2bcc63fbf45b8010651c801d3e58dccf42733ce1d6b446a3 +a843bbf286e3cecc1fe370ff1bcf5f1001bc2e95b34246625ff50d48ee62343e82fba2d25b8a4bd5f7b5ffe90920efa2 +a3c4d1003219157fdbee2707ce07afa6c2a64ae8e450182c307ed7f070024071f30b12c4b0032960ff913c74e73a9976 +b24af3f68d66f825d06fc3ff94fcccebe28b1a0d4ba29c48d3a3c953b9bf7ae6707f193fef25e2dcbd2b74e483c774f0 +b0f657f7723184ef7d7e4381143f1ac8020d8c6c6f2dcbebb0eaf9870d61a81f2d452596503311e46d1b38f625d4756b +b90091004fc8f6205c51bec68547ac82dba0f5525631e7632cf6efe54eecd9020729fbee6105d1b8012402d3b79c54aa +8e3fa187713c60eb0a416d6900a894cdf81e6b6b69dae0bb64f6287f3c3f030cfa85c665f7aace1eab4937f380b8f728 +879bf0784ccf6725c9cd1ea8c49fde31c91c605de1ea664a33c2ce24c277ee45d20b66309f98d989acb2ff3b77e13101 +af3f3a3ddc4e11abd627d5aef8adffa91c25df5f0c68b4d2b5d51e7d9af3395ba4f6f7ae2325a6672847e1ecc6cad628 +973e667289e796d3a40f072e6fea575a9b371a9997cf8961677f8dd934619ddc47c1a3efe91bae9ef95acb11a8fe6d09 +afa81c5606de82f46b93f4bb6db3fc0670f4e0d1091388b138a66b3827322d95a56168c951c30831d59eeadc227500bd +b83eff77db5b4c18574662942eb36f6261c59f655f8a9c3d3731412d0f257c8e80aacc995c4b2303058a1ba32522a434 +912e5ac9234b9445be8260393ff08e4859a7a385e800b74d1534eeb971f58f74cfb518dfdb89f8705d89fbf721439129 +ab27c8ece4a51d23e22c2e22efa43487c941139b37ea1182e96efb54ca4809d8245eae0ebe8ba94f0ed4457896fe11b1 +a6630585d104a745bc79dba266d9292bbdad346449c8ee8140a5e6e8a6194411df9cdbf3d3ef83468a536d4f052e9335 +8b8c128244da48e7fec641a882d0005a2d05c7138d86a293e6a0a97c76bf632b44767d0ce44663c975e7f9f9679e25e3 +87dbcaca67351a4e7d2297d7cdba4796d12f58857e7ee4abd0645563577ff33544a44cd84e50b3a3b420d6998de9b57c +b859ba43df259d7f8e7fac70bfd7aae546d57a5dc90e107b174a95bf7fd3cf00f740c4434848e69b2a7e6061f66c1ef1 +99d6e20978fefc40c6d310187eb2ad3a39296f189ee122ed64d74f81033c3069d44f7a9d3988a1df635b609603a17272 +99a5ddf3420cc0c92b21f71a805245608d4995ead447d8f73a670d26d33e26920d5f07bfe1f6230bd5f15978055b4253 +b936ac0944d3c5e4b494f48f158000abb37b80b5c763f77fe856398c664b0f1ddbcc0a9a2a672db9278f08b4bafbe2ec +b4af85fbf4040e35a686dd016adec037c99b47cc2e4dfccaf7870ee9e8c97bff30f3035992def2a9d4af323c0b3af8ae +a5ee32b8bd5f8fa9000da4da0bf00565659a43285393d37080b555d0166bde64d87317b2eab2d48a0e7b287caa989be2 +894d4ad58ecb1c9ebc4f5a97407082e56cb7358d7a881ba7da72321c5027498454f2c7fa2bd5f67a4b11d38c7f14344a +965be9eeaa0d450dacc1b1cc2fbf0d5d4b0dd188f2c89aaa9260e7307a2a1eb22db6092fccb662269e9a1abfc547cabb +805893c424aec206260c1c2d2509d2cb9e67ee528bd5179a8417a667aa216a3f318ed118b50d28da18e36c01f0805e3f +972d7040d4963b35260ef0cc37cd01746f1a2a87cedc0dc7b0ee7e838c9e4573784ea743f563b5267eb3905d4fa961ba +8c7156991d4c2e561888feaecf501f721b4174e7d14109e9deeac5a9d748301c07e11fb2b04b09799f0d34ff42cb77d1 +894722ac35af3d507e81d737d21e16c5ba04686f8f004aa75934aae5e17acd3e065b96e229eb011c2f34096f4c62048b +81237937c247c88e8e31e2c72412189fe59c1daf65c5513489d86cf29ee922c0bb08e5f7890f09f4ada7e5262083d266 +8cf62cda2fe0d9a6b42aa2a1c483f4ad26378c7cc2c2d1510a76df7560b07dba8528b33aaacb15f7f20b9d4c7c9f61f6 +aaf0921fb3e1920eee5d0acb59dcc268b42f4b435d60d25d30357edd7dd758d035919691bd15311d85489dfa2e5ee696 +92cec07be2247ef42002ebcaf65ec855611b8e893a5675796f2225f55412201b0bf9f4761924d0c8377b9f131e09e39f +8e514a62ac1e91773d99588415426c97ad63e917c10d762fe06ace5277a5c3bf3730e4b9e5d116f8493b9ab8687b70e3 +83932df2d923a5052468a3ea87f7b55c6a80ede3594046ee4fe233046570921822bc16555b92ba6aeabaef9b1dc0805a +a2b5bfb249de3472113fd3f35bfabf3c21d5609da62a27ea6aab5f309c9068d94bc58ba03efb4ec11be06306d59e60e8 +8106cf3ebe6f0507be8c6e8d137987315fe3689ecb75bb27980f36ba5efac504baccea0e7603549b6d126beccc278804 +a73ee70b6fe8c082443972102c453fc0e386852476cf22224fc0bfe554735c12f96037fbf10922795f4502c4f052b5f4 +932b27e175440169958504f3ed6400e7d6dcd5e716c19dcd0f15c56c04503ed133d5a993e111c016f141e32d68b29886 +96f7ce4595318e0b4a6b368f788ff82226aac676aed4ace343867f751de414453a9aaaabef6e6224ce5aedc3d5cf77c4 +a950c1e3bc9a14484997013d44d876374b939af437ae7c821c131fb886063ee9fe7214a25a0c7084f0b07b99412eff75 +a9dba3886ed6855303106a1bdd26010f294218684e1c178afcfea3f37a2f04fd01724a31d82de3449046617e3507a115 +87a2f776b32a6b550cf3ceeaf78db02819be74968d228b1d14e0d74a1cdf994bb500b7abef6619455e98d728701fac5c +8cd887b07e335edc0b27e6a660cebb64d210741395be431d79d570139687b056557159407459799a8197b6079644f666 +b81a61fce00588909c13a90c1caa150f15788786af443ff60ce654b57147601f7e70b95659e01f470334a220b547611b +8aebc51141544c5f3d3b99422250424b9800031a8fdfbf22c430907a3a446fecaa2392105d66d64b1c8e847240da4a6a +90db7dc12baa02f3f86d3edadf9434e2b9318d4f6f0eca08276b765dbb38d8eb0d08be2fe70adf2bf16ceda5db08d3ca +aa1839894152d548cc6ad963de20fb6fcc843bc9af2a2bf967c63626b8ad19e900894d6106265f38f3afccca317c22f0 +848e27b741496988a582515c0c8847b2bfc6a001259396cdeea1e1b1d2828ca3a626693a1bf4adf3a3d7f8b1fa3d75fe +a0aa11754d4ee136ac3ca609b17bcae77758763b2016544ca7921dddedd8aafcc7ad5f2b337c8bf53084eb8e43ea41fb +b8713b7aa1c112178195fdcc9b7024f46e6bc04c4e76c41abe620aa265287809200d98eaed6c9703fa97e81d6964f0ec +8605b5b33309e9ea6823542b85383c496794b8481c577497aaf99ba90496e794dce405be615bf92c7b6361460e6b82e3 +826fa34faa7f83e063a7bf172addfc07badabada59cfc6604fdf481d29085251c0a67a1355b2cbd374e2975934b84cb6 +b45d131082dc16fa53af010d43eefb79200dc23d2f3ee26af95ac6a5cebc49c84a9ed293e534ed16ff3ef9a4a25456ec +91bd6ce3c5396a7a0de489e49f0cdf6dce1cd2d0be7a410326423c3185bd1125ce1e610768be7f15f4e44b62f8834fc3 +903ffbe3d33fbf106c01c727dc3a385201a67ded70d4df623934882f69a3a96c909b027a124f3d70cb072b0046a149e8 +b405359db9d9ef4821a181b440ef2918c240595141d861d19a85867a5afa74d2972d22c988775eab441e734700bae4a3 +8abb756d027233c83751910a832b0ef4d28d100077f1c5d656720c94906f91d85dd0ea94b1cc0ed95b692efee14c786e +a78ee77ab476a41a3454160ba7ca4085d8b1f7057c63e76db8b07cf20afdeddd2250cd00771a6329133bb4ad48ccc20a +a41810271d8c37197aa9b3dfcefe3498e42f5978d3f3d59defff4676d6402d8575b40683834f184f143b6cfbfc859b3a +90c24a0750242660bcc6d487358a3cc015730538a0a8beb00ad5ac2ef33cb8ca8a62121e50bec8f3d2f43900f8e3134a +8b96c39695d864ef5796941754978a1fd612b369f6b77fe5ae6587beac936ee28190af8f0a3822b63060af35e49a5c8b +acde2548883d0e63c0fc257bb9dadd919aba60a985b69ebcfa1bca78acca42fc1322ec30bcc8e7c188818f858d04ad33 +895c86ae9ff8d95f2707d4838a3bc8ddb05b2611f0476f014b9c150d0e8332bc73285037a747426f09ac8179ba4e19fc +821761fe406e18bd86fa9ca9db99d382cd3b5c70c456f471fa3706d57763d147706304c75d54f51ce8f3115aa26e59d9 +a803a80e3e8f47dc3c59ea23eafdec017458eac648b360cd42cbd075e0dde6f6f450b48c7646fb1e178c04f82ae51a12 +91f40e1b6f588bd592829ce937996452c40be0fd6c43793c607866701ac6a8c7227e0891d45c6e7b1599382b0a3fbdbb +9408246d996a634a58689337f2526dfb3ba9ffef1d3ff91c32aa8cbbed900861ef25d6477308b67d76491edfcc70d65e +a492325a427f3df1c9c690c5b553daa8ac41f62f5ae55f425539222bacf959e2f67afabbba1732e120d3e7a6dcdf7049 +8fd0c3e15477cae228613a171b6e9ec29ddc63ef74854d99b638adeffe39f89f34346a42851e8445e855a9f2bbef0f57 +b735ed01fafa051004dbaad5e8c9e2faca8f6049ef9b590f256ea4d75b04594af12764ad4e6031735eae36f83179db93 +a7d35f43fca06c86b3425dcb68a87186834ba9740664fd657915771beca4cdc0fa2fc9b4c2e9d9bdad8ec33543ddfa59 +a1156e71e2db1b17df5da28747c88e091bd687bfee59d89096437ab4dc9a543fe5c5272d5023d72adbaab397a6fc94d1 +ab06a58bd81b33a411bade8d8c5232d38fadc2e38507159edea6e2e104b8ebd65ca02b05335118f691d44197b847a4dd +848b67a10f1e6ff8f5c228f226ef2ffeb67fb8f50925fc94cbb588d61896d9dc79726959e649898fd3354fe3ff7b7ee3 +aa933397361f32b388edcf832f0db172a38e756b34d5f7a4a050fa7325058006c22cede26ee27917e8f1b0f301792bd7 +89e49e7f02cfaae4a4b9c4180c9f6559d76e3a45774955859d4147970b1470dac37bdc9aedca1c32a20b045049161590 +adc1825d5ab94fc719f25d8c9773f4d518134ed88eb13ac33cb910b2be3523ef9ef88d9e4aea2418b806e20108317bf6 +96c4b444c8a023da644f3a343ebeeed19a8392d2ce175992461451c318a54273b76c3574d8f2dceda2947ddd34d1a674 +8aa7e97e87c8c5b29bbd51a6d30396a6be1fb82b716ef83800f2c36d5b85467ade7e0f59d2db82c310fa92a9265f0b03 +9146c32d99f02c3a6f764dcd9b4807f1585f528ac69dc4f84e4380f6fda4f9d5057c375671d51e7aca2b2b4140e83da0 +a10760a533d9bc57536bcaf65f080302086aa50225437efd64e176841544711828c23a15c49c0dd1f357d3f10722ab72 +acb0811777e17f7ae7aaba5f6fce81b759c067a4908730916195a2505c7450d0e6e2194c2ef0f241090597d58e70de47 +b24f161e9bcdbad56665e2490b5e4c7768390d4668cd69a04ed74739062dbe832636dd33cda89e9b0afa8c77e93fc641 +96b4d01106b831868a88ef016500ef2fa42d0ce87a37ca8ca4194a92a22c113edfe04eb2ca037329f3c1acc635148f55 +aebbb95fb4f7adcc8e7a217aeb73f9e037cbb873d08c1cd9d68c6c6834511adf1af8b44567fee84327599bdcb734dedb +a9bd8b17300532fb94d028659bcafbe7bbdf32f8945baf5db4cfaa1bac09e57c94cad0ba046b4514044b8fe81ea8596d +a5557cbda599857c512533e7cadcf27bf8444daa0602aa7499cafc1cf1cf21f9d16429915db7485f0e9a1b5046cf01c5 +8810307c40bc661c478a9747ebf2a30e5a5ead942d1ac0418db36ba5db0709c476f7d19685cabe6959e33ec1f3bff914 +8829b741f41f2c32e10b252d9338deb486dba2f23996a44cf1dd888ad967a589d51329be34d764139f372a1043f6c2e5 +a6b4728d18857c5fa082fa67bfb3b1d801e76b251b1e211a19c87cea5fe7ce757f943c85071f7a03a718388cd5690e95 +86da7f397e2533cd487f962ae58e87bea2cd50af70ef2df9ea0f29f70b5843cde664d30ec207ab84fc817f3851277e02 +8085776ef4ac6d42ab85b9d9135ecc6380720efd274f966544eeedf4684028197de76ecab919fa5414302597e1962bca +b05a065c733033d223ba13d16baa7a97bd8c8b8b1f0e59a9bdd36ee17e9922d48eb39bd180c168b122088a77f0bf321a +a89343fe44a93023dcc7ef71bd3bcb6786f68e1885ad260edc56a52445d34757f476395ba7ad35437f89bc573c7618dc +a114a9cd6105b524f3969c69faa2e09afe21753a93361a296f9e0e3b4e3e63726ddf2e6bfd3ddc046043e50bd44e539e +8a5611fec539cf681c05636bb580f29acc06f628bb012649ffa41ea6c1521194a5643d5dd843f09b6eb2c3bdb4d41acd +ade247c4011ec73ec90b72f35afa59a999e64ba5a7e664a4b30874fea53ba6a14a76a41b58a5f891a20d019e5f091bdb +905b5d96df388160ade1ffe210d0c6d1979081bc3de3b8d93ac0d677cc2fc2dc1ef6dcd49d3947055514292a3fa2932e +a9520796ca9fccd11b7524d866507f731f0f88976f0de04286e68d7cf6dbd192d0d269f0cd60fd3d34011a9fe9e144c2 +989a1edf4d7dae811eb57a865c8e64297837ffeeaae6ee6ac3af0f1044f023f1ca552bf00f1642491f0f0f20e820632e +879c8e63713f4935ed6e020559e140ea3073ced79d3096c152c430141272117b4fd9a9fc3eef012e81262df02ea14bd7 +95074738ac1540c0312274333acd1ecad9c5509fee883c4d9295fa8d8200f6e637c363de395f9fa612f05c0dc58fae88 +a770e4fc595269eb806b113ab3187ea75c8f96b57bf9fcfaf535f3eedc1d4d7e6285a20990575de0ff09f62d06ed0692 +81283e5dfb6423439ff513eca1cc316941d196df8da2d1069d2d0b63f5289e630af2fd4119bc0144c002d33313372dab +abd1b108e743887b78f698f2aba9d5492f87a22868d1351d705d93a1084fd45be67170c68a6e18b07f400d9a01cda8c2 +8509c3f67b92908cea8144f4e2a71631a66a61ac3547601c788907e52e380e5fe8ae4110aed95d13c67d3bcdd5b55a61 +8fa5a790ec5cce6d4114128c295390120869aac5490a82feebd3c37a167120df2e7fdfaf2a4050a7dfebf48fb093212f +944753e1ea7d8bc727d46a7702077dc01dc0c6574e8263a16579b57ee155ca5901f71bb347a01a9a922b329d3ff75135 +b46bc1fd4590b7a6275e20036d247c5909fc549c78e95b64ae7ed96e3b05bb044840f19f7650ebfe7008ba09fa83c3c9 +b1e47e4d88e59a06c465348c6cc4181d40f45b91e5e883966d370c26622c328415c6144aa2f61ddb88ec752482c550ca +8bd4f8e293e3f1815c7e67167618fb3b0ea76424bc0985908957cfcede36109378e41b4d89555b8c2541b4c447e00461 +a70589a867b2bfb63d0106083d58475d506637148549ed35c83f14e5c8de996e1b1f3447ecc80cf5cd134ef4db9d2fb6 +8048b80ba6131d07370162724127b0f7cb17fa7f71855e55e5a75bd0a9e4fd71b0d0ea2d16ec98858e458528df8d06b5 +97326cb94bae7530f4ec3235770c5a7ba042759e789d91c31fedbd979e3c0e6a2c69e2af3c1979c6fe0094274dbd53ce +a18e9c1d3eabd62af4e31a4b8e08494f4167fd4598c95d0123f39c46c53f9e93f76615900246e81a286c782ac37c569f +80309c59d4522b15aba617cd3c6238663e8b1c7ad84456346082c8f281140fc0edf9caa19de411c7e7fb809ca4fa3f4d +8e450c0990e2f65923f252311623038899eeff7b5c2da85b3a224e0ef7132588b291b782d53c477ecb70f34501466178 +87843f96f41484e254e754c681a65681b9ae5c96c292140368743df9e60f7e2ada58ca2bb95fa39abe064b2ebf21eeba +858e8d5bf2a1cf26d8af5036b28b831d450a446026f58a1734b696c18f1f41482796b91cab0e5b443dd2f0b9cffa52b4 +99627dd6bad8c05c5904cd23aa667d664da846496dbbb8452705c4ec01e1480e9c7295504a5a8529e4a0c842306b038d +b64b33256c18b2c886a837a0c0730fdfe73befb0e2796207c4dc592c5a33cd51f8c2ef47c584dd5773abf9ce9c1b0082 +944f6da2a1546f0bfc4d98c3e73c79e935e33d208b6be26b0b5f8df6d0e3b74a5bda649853b99281bd3a3ec799a7dd04 +a266d165435784d4e884640155e35b2a911b3f89e1e715986de419b166a36a341ba724877d80583fa3da566f6a828971 +adff2698409d0756e78c534032ee926560c13d578cb178d5073172d049ebbce32a92692f7e2033ec781b9b0d894ddce0 +a91933f110756c699c28bf9e24fd405bf432002a28c4349e0ca995528e56a5a2d101b8d78afa90a178ff1a9bf2ba515c +8e77839c0eb4da2d01e4053912cd823eddffbdc6b9c42199fba707ca6ab49fc324288b57be959fbfb11d59085d49324a +aa124517c76692036c737e987f27c2660514e12a953e63ff4bcb269dd18fc44dae95e282de8444bed09639ef6577af88 +b285deae99688f1bd80f338772472fa2b35e68887c7eb52c4ef30fc733812444c5cd110050275ad999d5a9b57f782911 +8877b0fa85b44ef31f50bdb70b879fa6df5eb1940e2b304fd0c8f08abb65f3118fa3d97ff93919038c1e452fb1160334 +8a89f3b50dcbca655024542ca7d93df17deff5c7d01c7da2bdb69e76b3e0b4490d85c800fb3debb4b0b4d20c9527f7ad +b7e5dbe36e985354ac2f4ab7730fea01b850af00767a6c4d8ee72e884d0fe539bb81f2e34638fcf5d07b7c8d605f4c06 +a85a1d78f6d4f9d5d83ec0f2a426708342d4e4a5d15625554e8452f6a843d9aa4db0c7e68caebdaf767c5b3a6a6b2124 +a518078a9dac63c5bf511b21ed8e50d1ccede27ebfe9d240937be813f5ee56aef93dc3bf7c08606be1e6172f13f352ce +91144eedebda4d1ad801654ef4ecd46683489b177ba1de7259f7dd8242c8c1700e15938e06c5d29aa69f4660564209a0 +a16c4657bc29d1d3271f507847b5a4f6401cee4ad35583ad6b7a68e6c2b9b462d77b5dd359fd88ea91ce93bb99130173 +85b855778f4b506880a2833b8468871c700440a87112fa6a83fd3ddb7e294b3a232d045dc37dfc7100b36f910d93c2ae +8d86bb149d31bfbf1fabcae1b8183d19087fd601c3826a72a95d2f9cedb8bb0203d1136a754aa2dd61f84b7f515acfa9 +acfe7264eee24e14e9f95251cbcfdd7e7f7112955a1972058444df3c2d2a1070627baefada3574ebd39600f7f2ea7595 +906bd14ecca20ac4ae44bff77cc94eb5a4ecc61eba130de9838e066e8766ed3b58705f32c650e1e222b3100691b3806b +8f2cbc7b8593c4be941dd01b80dc406fe9dfdf813ef87df911763f644f6309d659ea9e3830ff9155e21b195fc3c01c57 +a68eb15ed78fae0060c6d20852db78f31bebb59d4ddc3c5bdd9a38dbe4efa99141b311473033ff8f8ea23af219bc8125 +a95cb76c9d23fc478c7e8a73161f2ff409c1e28a2624c7d5e026e3cee9e488f22225a0c5907264545a73e83260e3a4ec +b76f90e55fa37c9e2732fd6eba890dd9f1958c1a3e990bd0ce26055e22fe422d6f0bcc57a8a9890585717f0479180905 +b80cc95f365fabd9602ec370ca67aa4fb1219a46e44adf039d63c432e786835bb6b80756b38f80d0864ecb80e4acb453 +b753c86c82d98a5b04e89de8d005f513f5ea5ea5cf281a561d881ed9ad9d9a4be5febb6438e0dba3d377a7509d839df0 +a664733f3b902fac4d1a65ea0d479bb2b54a4f0e2140ed258570da2e5907746e2ac173ace9120d8de4a5e29657ae6e05 +9479722da1a53446e2559bb0e70c4e5bf3f86c0ce478eede6f686db23be97fcd496f00a9e174ceb89ab27f80621f9b80 +b707fd21b75a8d244d8d578f3302d1b32bb2d09f2bd5247dff638d8b8b678c87d4feab83fe275c5553720a059d403836 +93214c16831c6e1d6e5a1266f09f435bbed5030c3c4c96794b38d4a70871782002e558d960778e4465b1ff296ffedad8 +8648f84e18eb63dad624e5fa0e7a28af2ee6d47c28f191be0918c412bf24b5460c04bf2b7a127c472914a0741843f78b +b67f61e75d6b773a6b58b847d87084b94f3cdac3daa7bef75c2238903a84250355a986b158ff96ba276ca13a6035fdd6 +ae9b094b7b5359ee4239d0858d3755a51aba19fce8ad82b0936cca48017523319c3309409ea6e9883a41bece2077e4d8 +8d1d8e1fba8cebd7a0e1effea785a35e16b1a10842f43e2b161d75add11eccf8f942d2ae91c20eef6c1a0c813731ea9a +b82bd387458e3603782d5e2dec32ae03890a3fc156d7138d953f98eff4200de27c224f626e3648e80cd3dfc684c4790f +a6dd02a89ad1c84e25e91176c26355e21a01b126c1df4d22546159dab9d502dbc69bc0d793a017c1456516e4aa5fa53f +a9ab74a5c5459b8500beb0ad13e9cfe2656e966dc9b4f3f98bec7588023b4ddebf74e4fc722d30423f639f4ee1b2587f +b03e5f33ab7ecec12cbc547038d3fa4f7ea0437e571891c39660c38d148212d191be29e04eb2dc001b674219b7a15a9c +925df4fc6e898ca55090ad1a8f756cc5014167a042affda5b24896eeb6aac408545134920586a8e1a2b997de9758b78a +98c8580fb56ed329fad9665bdf5b1676934ddfb701a339cc52c2c051e006f8202e1b2b0f5de01127c2cacf3b84deb384 +afc3765d374c60fac209abd976fe2c6f03ce5cc5c392f664bb8fac01be6d5a6e6251ac5fb54cfcd73e3b2db6af587cbb +8e7e98fb5a0b5b50d1a64a411f216c6738baaca97e06d1eba1c561e5c52809b9dab1da9f378b5f7d56a01af077e4f8cf +b724bf90309651afb2c5babaa62dc6eac2b8a565701520fe0508cee937f4f7b6f483fc164b15d4be4e29414ce5d3c7d4 +9665160e7bf73c94f956ecb8ba8c46fe43ae55c354ce36da40ccc7594beae21d48d9c34d1af15228c42d062a84353a0c +8600ab3aa86b408ee6e477c55572573ed8cfb23689bbdadf9fccb00161b921ec66427d9988763a7009b823fa79f8a187 +b0d8d19fd1022e7bc628d456b9bd1a2584dce504eb0bf0802bdb1abd7a069abbeeccdb97ce688f3f84a229342dbc1c33 +8f447d5e5a65bb4b717d6939cbd06485b1d9870fe43d12f2da93ca3bb636133a96e49f46d2658b6c59f0436d4eede857 +b94e327d408d8553a54e263f6daa5f150f9067364ded7406dcb5c32db3c2dffd81d466ee65378db78d1c90bc20b08ab3 +b58c02781b74ef6f57f9d0714a96161d6bfa04aa758473fb4d67cc02094cd0c0f29d0527c37679a62b98771420cf638b +8cfa0a687ea51561713e928271c43324b938aa11bb90f7ffaa0e4a779b3e98899f2af59364ce67b73a46a88748c76efa +95d6d39c814c5362df69116558d81ce6f1c65fb400fc62de037f670d85f23f392c1451d43341c59bc342bc31842c8582 +af888b384c52d9e04e4db6c4e507c2037eb5857e9bcc33acf84fc3a02d93cbde8cce32141fce9f5fec715b5f24d56356 +a7822bbc3c236fd58bd978f0fc15fe0b60933a0c953db6436a233441219418090ae0c07c490a6548e319029771cdaba7 +8c53729f750922e5eb461774be8851a3f40fe42eed170881cc8024d590bf0a161d861f5c967144d15cdcdc3dc6b5cf88 +a052a25a4aeab0d5bb79bc92a6ae14b5ad07d1baca73f4f6684ccecfc7ea69bc21eadeb9510452fdba116c0502dd698f +923946b83d37f60555dbac99f141f5a232728c6eb819a37e568c8c6e4d9e97a4229fb75d1de7e9d81f3356f69e6d36f1 +8cab82cf7e415b64a63bd272fe514d8b1fa03ba29852ec8ef04e9c73d02a2b0d12092a8937756fdec02d27c8080fb125 +b1123314852495e8d2789260e7b3c6f3e38cb068a47bdf54ed05f963258d8bcabaa36ccbea095ba008e07a2678ec85a7 +a685b779514961e2652155af805996ceb15fb45c7af89c5896f161cac18e07b78c9776047c95b196362c9ad5430bcb22 +b734dd88f6cc6329c1cb0316c08ade03369a11dc33191086c6a177cf24540c7ceee8199b7afa86c344d78d513f828e81 +b0bf492fb136ecdb602c37636ed4deef44560ab752c0af5080a79c9f76a1f954eba60a0bf6ba8bd7b8cac21848c29741 +a5c74682323e85ac20f912ab9c1d6e1b9246c4c829dca40c8a7d58ec07ea0ad3524be30623f351269552f49b65a1245c +837403b9cf830fb33ecc11a7c8433e07745973c36acdeb3fc9ea8f7d8d690d462e1250b7410f79f2f4180fe8f3962a4f +b03d64b944d49c83608f2c5b9c14070c025f7568c4c33d4eeb1da31d07f0bc5897e498b35b50d557ee129f0c3c68e254 +827272aab8bf757e2483156e00fbebe1093a58070dd3af9855bbf946c7abfb9c8a850a6a8acda8c620902f391f968b8f +84c4eb863a865282d321302d06b362f8bd11c2bb0090f90ebffedd3eb3e7af704cff00d39a6d48cbea4262942e95200b +b044eb91653dc55dce75c8d636308a5a0dae1298de4382d318e934140a21ca90e8a210e06fdf93aadbbeab1c2ef3904a +a8c08955a4378522e09a351ecb21b54025a90f2936b974068e80862803e7da2b5380c4b83b4b4aad0409df8d6c8cc0cb +a763a5fb32bd6cb7d7c6199041f429782deacac22b6a8467077fab68824dd69343ebca63a11004c637b9cb3129dbf493 +8c44c8afa9a623f05c2e2aba12e381abdb6753bb494da81f238452f24c758c0a0d517982f3999d2537b7279d381625ed +8613f47fda577cd3bda7c99b80cf4b2dd40699edfd3df78acb5e456dd41fd0773bc8da6c5e8cbf726a519b9fb7646ccc +b21a30d49d7e1c52068482b837a4475568d0923d38e813cea429c1000b5f79b8905b08f6db237e2eccf7ef3e29848162 +b9bdf4915f3fbb8d84cdfd0deedf2c9dc5b14f52bf299ef5dca2f816988e66322df078da2c54b934b69728fd3bef40b5 +993b45f389f55eba8e5ba1042d9a87242c383a066cbf19bc871b090abe04de9ff6c1438cb091875d21b8c10fac51db58 +a85a95d14633d52d499727f3939979a498c154fd7ebb444b08f637b32c1caf5cca5e933a2f5d94f26851ae162707b77d +b9874c7c4be1c88a9646e0c2f467cd76bc21765b5ab85d551305f5ec0b4419e39d90703d4ac1bb01feb3b160517e97b7 +ad6771177fc78812904c90594712956357de1533a07fec3082ba707f19c5866596d624efc3e11773b3100547d8f6c202 +a79f31921134f7197f79c43a4b5d5b86736a8d3ad5af1bdf4ad8789c2bfe1c905199c5e9f21e9f446247224f82b334f8 +a7f1b6c45321222a350a86543162c6e4e3d2a7c2dce41aeb94c42c02418f0892dbd70c31700245d78c4d125163b2cd5e +92abafe3ec9dbe55c193fb69042500067eb8f776e9bf0f1cb5ab8eb12e3d34986d1204136856fb115c12784c3b8dea6e +89bc761238a4d989006ca5af5303c910c584fe7e6f22aa9f65f0718a1bc171e452c43695e9f5a591725e870770c0eceb +aa0e44c2b006a27d35e8087779411ba2f9f1966a0f5646ff6871bcf63a8b1a4a7638751b94c9b9798ccd491c940bc53f +8736fe82862b8106e7fdab7b5a964d87ec291a74b8eb1cb5a6c046a648c1b686064ef3d52297043b8940bfe870c712f8 +956a3def1942f05144d8e9c3a82fd2d3610064b53b9eefde3d5594a8f705bf8f6849eb2c22181796beffeba43cc74ee4 +af27416d00cf97d5a1f4a1b6b51c010884cceca294f1151c3b684a3f83c3c8a3c30771df1166d833cbddf6c873c400c3 +aac3b8dca2336fc4ffc63c362df461289e4bbd3418c621bde6c581d3ecedf66e2b3e523d4db39e3d8ba014577bf85efd +94c3a8167f62074e5b28c2bffe4b6ce645439a9a0c5da3ca1b3ee956590a465d6f84a8a4dbbe9070ffbd6bbc734e4d62 +95e23ba6986d25ed4451215da05bd72c5491528271726d79a94c8cb16aef1c85b190d6c5b8a3a1191c7cafbab1dccf0c +953e3dadb5ad68f7de31ac09692948655d174fe16d88b96930ef35b331da7f1dbc4c17863cd07b4ec3135b5205891a27 +915d018f18b5d63cb3301c2bb5c6e85e75a88ba80663c964d06575b6bacbbe59139d030b218ce0998271d5b28c00b26d +8c871ba3dd138a908b2f7effeea0e71df096b23e0dd47cab10b9762b250abfd1221da94a8ee884e05bdf02271fb85a04 +96bad5c6ebc3080ecbe337409ae398bbeada651221c42a43ea3b7c08c21841ddbcfde544c9b8d4772de6f2ce92c0b963 +b5dbcd0b1c44c62108841558ec0a48df4b327a741e208c38b1c052321eda6e6ad01af71d49dfcdd445ab6fa6f0c34e6d +97dba59219b69e8aef2659d1f10bbea98d74aefff1f6451de3f41be39acbac0122b8ff58b02e90554469e88911ec3547 +b7e5682ec306478be4858296f5d03364a61f3260636a4242f984d351a02e8723378496beb30c4ca22def9c9ca193ea70 +9656a7a3df4d11df3d8bc35930dff70a5e78a488ca57bba20bb06814fc390fc6c7cb3f39b22134992aad196cced577de +8b269695aa63eb56d0324ba984279dc4c88e565321f1d61d553622bd4f1910d5eff68393d3a830eb924472bd478c2aa3 +9177bcd04b28c87bc0440268b4c8995c6790cad6039594971b2c177f0e197055231e776927d3fa30d98fb897a2ba401f +ae0e943973482001c4f214b9da82e1c27e38aa254d0555e016095c537c835d3702bc2de5c67b234ab151e02b3b7a43a6 +82fc719a7d38bf4787fe1888019ad89fbf29beb951d2fece8686d2beb9119d0c8c6d13bc598748c72c70d73d488140ca +b716dc66f87eb16b95df8066877353962d91bf98cf7346a7f27056c2a4956fb65e55cb512af278783887ab269e91cd76 +81d58cd8bc6657362d724b966321cd29a1b5cdc4601a49fa06e07e1ad13b05e9f387ca4f053ed42396c508cd065c5219 +b32ad0280df6651c27bb6ddbdc61d5eb8246722140a2e29c02b8b52127de57a970e1ded5c2a67f9491ae9667349f4c46 +b68a2eb64cc43f423be8985b1a068e3814b0d6217837fb8fbfd9c786db9cca91885c86899c50a1242040b53bf304ced9 +85887515d4e371eabb81194cbc070e0c422179e01dbda050b359bd5870449c7950e6b3947b7a4a0eb68199341cc89fc3 +ac5fff3c27dfbab78eb8aad37ac31cc747a82401ebf3644a4f4f5aa98d37b8bf3b3f4bd8a3428b32a127c25c9e19d239 +86fceaa6fbf8913553a9e1e907fcb1f1986d5e401a7eafd353beefd1899d571454fea96ff5b2a21254d9fb693ec94951 +b6778bb296d3f0de2531b67d36fdbfa21475be0ca48b9dfcc38f396c41b557823735ed0b583e525a2bae1fe06e04058c +898088babeb5b9866537d6489f7514524c118704abd66b54210dc40a1c1ddb0a1edf7fe0b6e0db53b836f1828ecf939e +b27854364b97274765f0fb8d1f80d3660d469785d1b68da05e2bd1e4b8cbbe04304804d4c8aabb44cf030eba6c496510 +8c55bbf3603dc11cb78b6395ccbc01e08afcef13611f7c52956b7a65ccf9c70551bff3ae274367200be9fc2d5cb26506 +947726f73cd6281cd448d94f21d3b91b96de7ad3ff039f9153befbb5f172db9f53cacb4f88c80a3db26e6a0f7a846eb0 +a7b733a05e97528812d71cecb4f638a90d51acf6b8fcbc054787d6deb7e2595b7b8d1cbe1aa09d78375b5e684a2019bc +8d5ca6d161341461544c533314fe0a6655cde032c2d96f0e4ea7e41098b8b39fa075d38e2d8c74e2d0308f250d6cf353 +b960e9f081393e2260b41f988935285586a26657a3d00b0692ea85420373b9f279b2f1bb2da2caae72dd2e314045f1bd +852a49c7388c10821b387c6d51617add97ba72485f52be95d347bac44c638c92e9c6a44ba0d32afc4d59178a497d944a +8412162a65147e1334ad5af512982b2b48eef565682b3f3e0bbe93fbc5e1103db9375a0c486bdb1b2c57e4cb3a8e7851 +8f52c3eb5d4f1e1e82cfd2b291d4910195427603b796f6c311deb35ef14a01a57a9e6cad39619ad108f3e86f384f9e1c +88d221088f2bf0103c53e44d0d96cd7881ec2b0a965db9121a47481771a8b796edd5ac23c4f9c208a171dab301f7d3bb +b49c3235e8b3617ed08a1891b9e2bcb33dbdacceb94ca96330555b7e00904fe6a749ced9312b8634f88bcb4e76f91cb1 +a85834215e32f284d6dfb0cbfd97f6cffc7b9d354e8f8126d54598bb42d7f858a2b914cf84fa664069632db2ff89a332 +aa3d48eb483c6120c27d9b3e3d0178c1c942632ff54b69f5b3cfbc6ad4ff5b2b9ce6eb771fd1eea8edf4a74c97027265 +a446cfded353cdd9487783b45846402b973cdeddf87e2bf10cf4661610fff35743cc25e8d3b5771dcedfb46b018a5d18 +80998377b3b393ef3073f1a655ad9d1e34980750e9a5cfb95f53a221b053ddb4d6985747217e9c920735b0c851d7551f +a35ac469790fac6b8b07b486f36d0c02421a5f74ea2f0a20ffc5da8b622ac45dfccabfb737efa6e1689b4bd908234536 +8fb1f6d8e9c463b16ac1d0f36e04544320d5a482dd6ffaec90ea0f02b4611aaca984828bf67f84dcc3506b69af0a00a1 +b6e818d61aea62c5ed39c0a22ccbb327178feebdabda0c9927aa1549d2c5bb0637785c4aed2a6d9a7b4989fa8634c64a +b4e7208d16018bf67caafe996d436113eac619732e3f529a6efb7e6f094d8ebea55b7be0e122be075770f5957b6ea6f0 +b691d38b552befac61f6d367287c38d01fec73b7f2efdb6713ca30314a37fb7c177eb111fe6bee657f2681014e07630a +9817587e418e6e7e8e97ae27067f17b55d25dfb14e98f63f530620c855d9a348c9fa571c8508e2741f902f8b9fdc0c5c +b6a6e5ca779ba140bf1d84cd5394ede8262f7479637ec0087a4b152243a1774ba916d8115ce759a3bebd1b409de5f2fc +b53d1c84ad766ff794bf497db3228efd2cc8ed5fc1958d89c1126efdff361610ecb45ea8e329b39035ab00a66c1259c7 +adc31333c507c8e0f4aa2934fcdca57fd9c786722a50dbd5404e129541f7ac182cc7373bf14e1e4e06e6cf94b31b90eb +a82b7fde4642d982d95cec669efee140ad797a2442c7f6620580527d163accbf021b893446cbb8038ea82fe25b15d029 +91f7acf8a8903979afa281646fdecb54aa4d2ed905748e156e92f0910de268fa29d67107d40863935d677d1de8039be2 +86fea71c6d43a7d93216a92fc24dfce8521fd4534a9558b33762d002081247867a6eff54cad7116023277fb4049403ad +8ae5369a7f9f4c91f3be44b98089efd9c97c08f5bb4cd8b3150c115ecd86288fa0865a046a489c782973a111eb93966e +b6fb9e829aa2c81c2d9eac72bb2fd7f3a08e0cd763532c2ce3287444d33cf48b3621f205e9603ec58525934b61a795a9 +83e35ca808d84e41fc92115e9f6e283e928c3a614e6dfc48fe78c33b6411262e7bfa731eadb1e1937bc03cff60032e1d +832fca5196c95098ad47b7d24ba2f9d042e1c73ad2273edd1c2ce36386796ccc26e8567847697f3fcc2a0536a2a2087a +8fdb7038bc8f462ab2b76bf7053362f9c030019f1b6105cf42219a4e620ecc961e3eacb16a8e581a562a97f1418b0128 +8d3a5a404b51b1ad8ce3b23970e0d5cc57b573922341008e3a952a1dd24a135e19e55b79d86a70cfd82e1c0e9630f874 +ba00c025c1c21c57c03cdfc0bfd094b35422281ff0a64b68b240617aa58c6b18800af5f2047d3ff9068bbe987d6c7980 +b468f0dd51964b3806b0aa04f3fe28a035e8f5567fc7d27555be33d02701a838b8dbfe1348b6422c4eac46d2c75c40c7 +8a73a18c97da9958903c38584b08d0e7e26993a5d9b068a5e0e1ee0d8a873942745cf795f94f7a3d3ba88790a9fbb2f6 +953a0a40c2c8102723736854d13b228698c14a02d85c8d2e61db1a768019ac305faf0d5db62ac976430ce087a5b20f1e +8998219da6b34f657cb8a621c890a52cb98c2bc0f26f26e2af666eebeadadc5e8bdf4f830a91d04aca8ce186190152c8 +8941e08c3155ad432236ed05460420a05dd0aaab30477493ffb364b14c00ea5b9183d30d3442b6321d2d20c36e4f5c7e +93f293ff7fb56cf5b03aee6f3ad2ad78444398ed5b3be56d7bf5b56b5aa5a2b980d13895dd57a5726d1b067c20cc55e2 +84a16f313e3f75e31824f58d19ab24c6611fb4c75140a7cadc3c166f68819547c1d0ff7f7d13f5d8ae30dff1d80e2aa4 +b6e3e830b15039d3e28b08f5465bb089eade11ee3bd80afe39e010df7db1fcf0c56d698717677a41ddbc91eeaf6544d3 +95e928e6dfff51351281568ae72da7d1edeb6e9fe01f30af0499e7505ba35a22b5bb919d41bb809a432dce83f3977663 +aabeeb60ca46f9b0232ff82ea7766dcab8cc5aaf9d23539f30174f9486640bc9312868ca493b59b314519fc399973e47 +b393a11e957d0bbb3ecf617b075b5906a3450b348e62916c04791b366f0a7397cccd6648440ac544bc30526e1f95aad8 +abb5bfc3964a6d246da60bd809d0ea6daf4f8222efdc12ceb6730194e85f413ee7eb03bae300abf7ea900dbbc3d08971 +96c1bd1d1d216a4bfbcf000c123f296c0d31e1684e9e3884c14df23bf528c8d599f82bb98fcea491716b617216a8e0be +92d1e570a56f1741fd9f3d9f488cc336421c6256c14a08d340a63720be49b0029e3780e3e193a2e22bf66cc652fa22a3 +8769c08551e3a730e46f8e5d0db9cf38e565a001dfb50db3c30fa7fa0e98b19438edc23c6e03c8c144581b720d7b33a4 +b850bd67fdf5d77d9288680b2f6b3bc0f210580447fb6c404eb01139a43fccb7ed20051999ae2323ea5a58de9676bfb4 +80285da7a0aaf72c4528a137182d89a4db22a446e6c4a488cf3411937f4e83f7b00ec7549b0b4417682e283f91225dfe +80520368a80b97d80feb09dbc6908096c40ff7120f415702c1614d7112b0b57f6729581c71f4a3ce794ac959a46494ff +9817b4c27a490b1cd5a6337e7bc7e8005fa075dd980c6bf075ddfa46cd51cc307ad1d9f24e613b762a20fc6c877eab41 +ad66bda1a3034ec5e420b78107896ecf36126ce3ef9705163db259072dfa438c6107717a33572272062b9f60cb89557c +876114ef078c2915288e29c9abe6b0ad6a756b5ee2930ba1b8a17257f3f0557602d1225e8aa41ce8606af71ada2a971b +aa3d6cde4c3b9d3d5d0c77a33e67f182a3e1cf89b0921423b2024236171955b34afc52b1f25b1dad9da9b001371771d7 +984d3e3a72412d290e3459339757af7520d1739c7af0cbcf659c71999328db44f407d92e8a69fea11625612c49eac927 +ae890d0faf5bd3280dcad20a5f90e23a206661be8842375fea2ab22aadc500849ffbc52fe743b376d46bb926cedae6a6 +b1f231f3f4d710c3fe80099faeb56dac67c1baf53b8fe67a9920fe4f90e52cb9a4bf19211249a6456613b28efe337f18 +8caa54b418ba609d16520af3dff2e96d5f2eeb162c065a1763beb926547b2cfb3ae41d738db2c5681a9bc8bc9e6b9a1a +932157ff56c5ac29cf6cf44f450c882b3acfbb9f43d12d118da3d6256bde4e6eb3183aea304ab6967f37baa718ffec99 +9360bed8fc5b6aac36aa69473040689bfc30411d20ffb7275ef39b9ff5789f9055d149383ce9f0f7709a1f9d683adbfe +98b5b33209068335da72782179d0c7aeeabe94b5560a19d72088fe8323e56db7ce65debe37a97536b6b8a0ca3b840b61 +89a385c11be40064160b030a1bb28c3921fc8078522618a238c7ea0f86f34717ed9af9b4e2e20f5128e5f7fc66ad841e +b615703cbc64b4192990cc7e4903b74aed6a0076ce113b59ef7719197ffa46fb29eb78ca56b49873487432d0625c0faa +90f0d77abae9d3ad73a218e5ccec505ad108ea098451461567ae8ef9661606ca8e78df53b5d628b20b7037bd24622330 +92e0e7cc4dfadc5fa0ee6da0c8de0493030db6e54ba0317f52f232a6708b732068b6077bd13a17eb7eb40b88368085b5 +a24dad20094985bfccc6df1343506ed3bf9dcbdf4b2085a87627a5d71f7568db067304e465f8f380c5c88e8a27291a01 +8629a45a10619354c84bdc2f6c42f540eab5a46f53f2ae11970433d7a2aef007897590bf31dfba1c921614c6d6fe1687 +84ac64040d4206f82b08c771f375da4b7d752e41d2aa0da20ce845f6bc1b880a855d3ee966bca19b8ec327b4b43e7f0e +9608e6050c25996c052509f43f24a85cdf184135f46eaac520a9a6e78e0d44a6cee50ebc054048c708aefde8cd6651c2 +a32032b0e0d7cc35e480c328f315327f9385adb102a708c9ba637878deb74582ae26bb6d6e5f8c9e3a839b0e0154b82a +b7e3c78d63acc6564a49e9f00b0a820b56d4f37a2374af1f7f1d016268011df9e7af0670ed2b0eee961f15aa948328dd +8b88bfdd353acc91ad0d308a43e5fb40da22c228f2fe093c6d6904d70f69c6203f56636ed898b05df51d33f1095ef609 +b1d7a430c51fc857af55047683fc18c453b013527196c5e1bf776819a3dffca802217e9249ae03f084e2ea03ad67fcc2 +80558e28a819ddb5e72e97c54be0f57c173ccf78038d360d190b7f1350a19577b8e3f43fa2f7bf113a228cd3b965b2e4 +b4b2ec44e746c00dfc5661ba2514930934fc805cdc29adc531c02d28ce3cc754414b0485d4ee593232cd1175f357ad66 +b57cee5d32835f76572330f61ccd25a203f0e4a7e5053d32965db283aad92f287645533e8e615137208383ec51b1fd99 +930256086b419a8a6581c52590d0dbd9f8a3564c79424198fca3866b786df2f6098a18c50dc4abd20853a7184b1ce15d +8e75fd01181cffcd618a983492390f486e8c889972a46c1f34a4e1b38f384e8e4efc7e3c18533aa2057da9f9623e2238 +b375d927dd988429f9e2764e5943916131092c394fce13b311baa10f34b023dd3571da02553176091a0738cc23771b9a +b9e28e4c0d0477518034d000e32464852e6951c8db6f64ccdb1d2566f5094716213fbf2fc0e29ac88d0e79f725e3c926 +963981e99392afbd2b8318d5a6b2b0cc69c7f2f2f13f4b38dddbfedb2b0eaf0584aecfcbda20a4c60789c15d77970a58 +a7804e1977aa77c263c7c001afa6cf568032dea940e350d6a58ce4614f1a91c13ae1c78bfea740c229dce2444556976a +8787204177da3cde6d35cd3497fa8774d244f9faa9f4bd91b636a613a32ce2ea0326378cf9c4cf475e73ef751b355c4b +895aeef46a07152a04ec812f1aa1fd431389fa0ef6c6e96a5b833e70ea14073bc9984757a8ee456dbec9788e74e6f0ca +8d17f0e5826783440d1f0ec868003510a4d9952bfe4a638e44a36d94482ac18ba70ef7ff773bdf7a3b62d714dcf0fcba +810d5e36b31310b2e054a666d3b3f7ed16dfcb1765532d87ca2a3920316f0187303c27dd113db145d47e8961062a6c03 +b4e2fb48ae04cf8580bb6a28095076c9b95e5f13122b917328f334d4ac8a8648ce442919e28319a40148987350ab5303 +b85549a313544fa1eb3ceb78473b7d3d717fc85b808de7b79db7dbd0af838ebb020622a7503f1cbacab688dddb648f84 +80665adee057088eae827a5fe904ec3ad77d8843cdce0322d535e0659b4abc74a4d7ddd8a94c27f2def5c34ac2c038ee +ad72fc19c2ce99b5b717e35528fe7d3ac8add340b02ebeb4889d9a94c32f312a0b45ea84d21c54f84cc40ee4958b72e1 +99d530c843dff89a47a5ee8c87303ab18f8a82b0d5b808fca050354b35da5c5a5594d55921c6362d6cc917d75bdc18dc +99c7286c293e1be21c5b2a669dfdfcd5aa587105d2886fc5a8eaf8984da4e907f7d7b8c2362d64a4f1621b077a2a08a0 +b4a39e1a9ed5d80c9563c3ca3fadf76f5478c63a98f4346a61b930c9c733e002f3ff02bc16abfdb53d776184cc3f87ba +9378ea71b941979404c92d01fb70b33fa68d085bf15d60eb1c9fc2b5fcdee6379f5583389a3660a756a50019a2f19a69 +b68e17344a2bc45b8e2e19466b86dc139afefbf9bad2e2e28276a725099ebac7f5763f3cb52002261e3abe45ef51eb1a +819e64dc412b2d194d693b9b3157c1070a226af35c629837df145ea12ad52fa8eabd65b025a63c1fb0726207a58cdde8 +a5e8ff8748419466ff6df5d389125f3d46aedacf44eaf12cbfe2f68d218c7d5ab6de4a8279d13aecc25f3b1d98230894 +91560d54a9715cfda9cf7133ae51c432d0bf7fcbaeb468004994e6838bfc5ddcfa30e4e780667d0c4c0376780b083017 +ae8adb3309cc89d79a55ff74f129bb311fe4f5351a8b87600a87e0c3ba60825f71fccf67eadcf7e4b243c619417540fd +8d92cc1a6baa7bfa96fbce9940e7187b3d142f1888bdcb09bb5c8abf63355e9fb942ac4b4819d9be0e0e822d3e8e2e08 +a6e8b79fdd90c34735bb8fbef02165ccbe55ea726dc203b15e7a015bf311c9cac56efd84d221cc55eaa710ee749dbdfe +a409b151de37bddf39ce5f8aa3def60ee91d6f03ddd533fce9bf7bdbeac618cc982c4f1ffbf6e302b8353d8f28f8c479 +b9693975ef82171b3b9fc318ca296e4fe6110b26cbdfd653418f7754563fa7b6e22d64f8025ee4243483fa321572bfe4 +a039ebe0d9ee4a03ade08e2104ffd7169975b224061924cca2aae71464d250851e9f5f6f6cb288b5bf15df9e252712a6 +b27834db422395bd330e53736a001341ce02c9b148c277dabac67dc422741bfa983c28d47c27e8214cd861f2bad8c6f6 +a2bafaf4e2daf629fd27d7d5ac09fb5efc930ff2ae610f37519808683aa583fe1c6f37207daf73de1d8a164f79a0c981 +b856cee1cfcf5e50db9af4ab0aed3db2f43c936eaea369b5bba65582f61f383c285efbda97b1c068c5d230cbe94f7722 +a61ab205554c0550fa267e46a3d454cd1b0a631646b3df140623ff1bfffaa118e9abe6b62814968cc2a506e9c03ea9a0 +8c78edcd106377b9cbdfa2abd5278724aed0d9e4ae5869b5d2b568fdabb7804c953bae96294fcc70ef3cd52ba2cbe4ed +8570869a9bbf6cc84966545a36586a60be4d694839f367b73dfc40b5f623fc4e246b39b9a3090694aa2e17e652d07fd1 +a905b82c4da8d866a894da72315a95dc98faa3c7b3d809aef18f3b2be4801e736a1b79a406179e8cac8f74d27e71ac52 +a8eb8679ff1a64908515f6720ff69434cb33d63aeb22d565fde506618908b1d37585e3bd4d044fd0838b55787af06b42 +af4d86b2fbd1684a657dffe4210321a71e6ae560c144d44668d1f324dc9630e98348c3d444622a689327c1a59cc169dd +80359c6eab16954559ab0e6a1fee9a0526c45d3cae1a371159a2e3aa9b893afdc3a785c9559a5fd9cd8cd774234bf819 +8d4e5ff81eb5d17bbe8ae6416538ca51a9427ce142b311f5cbb14febbbbb9c1ffc6489fd625b9266264c366c12a9d997 +92e181c66489c5fa063ba2a1a354b6fd3439b8b4365a8c90e42e169bfaa1fb5766bf3e0fe804399d18bc8fbcafb5c3b1 +a9ddf229360a095393885083716cb69c819b2d7cfb100e459c2e6beb999ff04446d1e4a0534832ae3b178cbe29f4f1d3 +8e085ef7d919302a1cc797857b75cff194bdbc1c5216434fa808c3dea0cf666f39d9b00f6d12b409693d7a9bd50a912c +916dc4dc89e5e6acf69e4485a09fc66968f9b292eac61a146df1b750aa3da2425a0743d492179f90a543a0d4cd72c980 +b9cbf17e32c43d7863150d4811b974882da338cf0ed1313765b431b89457021dd1e421eeaa52840ef00551bb630962dc +a6fb875786daec1a91484481787093d8d691dd07e15c9c0c6ae0404bf9dc26083ed15d03c6d3fe03e29f28e20da21269 +a870fcb54b9a029e8086de9b08da8782c64ad2cc2e7fdf955b913d294038bb8136193256b85267e75a4ca205808a76b4 +99883f057e09b88bf0e316f9814c091837fd5c26eeb16fec108c9fed4b7a2bd1c783dac0e4242b5a906621ab606c1e50 +85d89069ca3190577dab39bbec43c16bf6dbca439ad3eebd8f5e9f507d84c3c43e77fd6323224582566a3aa2c8018951 +9363ba219e0003f6e8a9d8937b9e1449e4b2c5cd57194563b758bea39deab88778e8f8e4f7816970a617fb077e1e1d42 +820622f25553c035326145c1d2d537dc9cfd064c2f5bdf6d4ec97814de5fe9a0fbd443345fa2ea0a9d40d81d3936aa56 +87e31110aaf447e70c3316459250e4f7f8c24420c97828f9eb33b22107542c5535bdb48b0e58682dd842edea2886ff08 +95bf80cac6f42029d843d1246588acb40a74802f9e94b2bf69b1833936767e701ef7b0e099e22ab9f20f8c0c4a794b6c +a46ecf612b2763d099b27fb814bd8fdbaee51d6b9ac277ad6f28350b843ce91d701371adfaaf4509400dc11628089b58 +8604decf299fb17e073969708be5befeb1090ab688ad9f3f97a0847a40ea9a11bbcfc7a91e8dc27bc67a155123f3bd02 +8eb765c8dc509061825f3688cb2d78b6fef90cf44db33783d256f09be284bc7282205279725b78882688a514247c4976 +b5c30b2244fa109d66b3a5270b178960fdec47d31e63db0b374b80d2b626409eb76d2e8d1ebf47ef96c166743032fc5e +aab01e76290a7e936989530221646160bf8f64e61e79282e980c8c5dcaaa805ff096efd01d075a2c75917a3f4bf15041 +b9d79671debd0b83d0c7c7c3e64c0fb1274300564b262771f839b49218501e7f38ef80cae1f7e5a3c34acdc74c89dab6 +92c0eaceadf036b3b9dfd2712013aba3dd7c30b7760f501f52141618265baa31840fe77850a7014dc528f71f8cf39ce6 +b3cdd098059980455dd5b1c04182df1bd12fa844a866f02a9f8a86aab95b59945baa9af99f687410bffc5b07153cb23c +b361b73a62f71256b7f6ea8e0f6615e14fc5a06ee98b928ab3c9dd3eef9d9d30070e9855c82b7facb639cacb3401e01f +b9c85fc0f25a3271cf28b1ca900078eaaa66cbab0a3e677606e898ac32781a2dfce4d9cbd07404599e2c3c02fa161c9d +ac5b4fdac2a0b2e6430d9fc72bde4249d72183b197fc7347bb1546ae6f544426686bbe0caec3ee973b6836da5e831c44 +b675aebf24b92e398e166f171a6df442b3f5919b6bee192f31675a5e8eeb77d34c6590a6f0c0857417e0f78cfb085db8 +a9bef942044d8d62e6a40169f7dc7b49e40cd0d77f8678dd7c7bae6f46c46786f9b1e319a3fa408f22a54fd2a4d70804 +a20d19cd917d5102ae9ca0cf532127d2b953aa3303310e8a8c4b3da025dded993a47e3a28e6b02acfadb6d65dc2d41a3 +a47fdb04059b83b2afb86a47b2368bbd7247c337a36d3333b6e5ef2cc9476a92c4907e4c58a845c9ef9b497621e0b714 +94a9e9ffc14b411e11a4ffa59878d59460263589003dc7b6915247c549f67feede279bf3645fdd92379022fb21e3caeb +b92e1177dd9ecdaf1370c71b14954219cf0851f309bc216d5907a4e2e84e0df3457018224150c142cc6bf86644bb4b73 +8bc57fadd68a265b7df9b42227a9c0968db7b1bb50dc12f7d755505779f1ff2c408672b3091e903366acc9ce15d19fb6 +b6b5efbe1ac4e1bd2e8447c45000d09397b772ca5496acc447b881022608a41c4f60388814607a01890190105bee7be3 +95f7c85fd614df968f8ccf8d086579c9e1cec4644ecf06da26e3511cb39635a7326b3cec47bd51cf5646f1c660425e9c +b81765fb319bcdc74b4d608383ccb4af7dd84413b23af637be12e2827a75f7e4bcd14441cf979ed9038ae366fbb6f022 +a120ea76cda8c6c50c97035078f6648afe6537809bdba26e7c9e61de8f3070d2347160f9d34010effbf2ec7e94f5749f +92c1b8631953b40d3cc77eee2c72a064b999c09a9b92c11d8fa7b4072966273901c9dba25f9f79f384d9f11a56f3fc7a +a4b00dc0ab67b2300abc9c516e34daf444d6497b066a90cfe3381ed2812304ed37b14f3b948990443dc6c1cf1bed460c +a9e9f7e13c9f031bc7b9e6f1417c7abcc38894fe7d3f54869ee277afd2efa3e6fb50757dd36c8c94d591e0abdea322cc +84f3e98f831792b5ad14bcfe62a4c9f296476c6087c4c1ec7767fc642fbca141ff6a3deeb8b4d4106a9cda5a9937eea0 +8eb1a7931bbea9a714226fd74b0100ab88355287d9b0a349c095e9b5809b98f237ffd706bce7d67a770da355fb9cec7b +9738ef8739e1742c1f26b51a1621be0b89d37406a370c531e236f635c7064c661818817bb3858908986aa687b28b21be +a9cf3ce8501b003ccaf57552a4c4ec31081e44526d3aa3791d3dc4a7e438a357c0956f93c500356186d8fd4588ffac5e +a7af6a219cca59225839a9de5b19263cb23d75557d448bc7d677b62591a2e068c45e5f4457cceb3e9efa01d0601fc18a +972a24ece5eda7692cbb6fb727f92740451bc1281835e2a02931b2b05824a16b01dbe5edd03a0ed5b441ff25a5cc0188 +b21d1ec7597ce95a42f759c9a8d79c8275d7e29047a22e08150f0f65014702f10b7edce8c03f6e7ab578ce8c3b0ec665 +a13a1c7df341bd689e1f8116b7afc149c1ef39161e778aa7903e3df2569356ad31834fa58ceb191485585ce5ef6835c3 +a57bdb08119dc3bc089b5b2b5383455c4de0c2fcdac2dcfa21c7ac5071a61635ff83eceb7412f53fab42d1a01991de32 +b2968748fa4a6921ee752d97aa225d289f599a7db7a222450e69706533573ded450380c87f8cdd4a8b8c8db1b42b5c97 +8718ec04e0d5f38e3034ecd2f13dfde840add500f43a5e13457a1c73db0d18138f938690c8c315b5bcbeb51e8b9a2781 +82094789e26c4a04f2f30bdb97b9aecca9b756cbd28d22ab3c8bed8afc5b2963340ddfc5a5f505e679bf058cbc5dcbb8 +a35b8a566dd6ab67eddc2467906bffc76c345d508e52e9e4bb407b4f2b2c5f39b31d5a4bf5022f87bf7181dc6be2fe41 +a8c93b1e893d4777c0e3a1b4bef3be90c215781501407c4011457fc3240e13524b4d2bea64a6d0a3efe3f3b0dae9b8ab +877095ad18b1e5870818f7a606127ba1736a0b55b0dbcd281ec307c84b08afc0c9117e3a880fe48bfc225fbf37671a97 +84405ee0421ed2db1add3593df8426a9c1fcc8063e875f5311a917febc193748678dd63171d0c21665fb68b6d786c378 +a52cdc8209c3c310bed15a5db260c4f4d4857f19c10e4c4a4cfe9dfc324dfac851421bb801509cf8147f65068d21603c +8f8a028a70dda7285b664722387666274db92230b09b0672f1ead0d778cee79aae60688c3dfd3a8ed1efdeda5784c9d4 +a0be42fecc86f245a45a8ed132d6efc4a0c4e404e1880d14601f5dce3f1c087d8480bad850d18b61629cf0d7b98e0ae0 +83d157445fc45cb963b063f11085746e93ab40ece64648d3d05e33e686770c035022c14fdf3024b32b321abf498689ad +8a72bbf5a732e2d4f02e05f311027c509f228aef3561fc5edac3ef4f93313845d3a9f43c69f42e36f508efcc64a20be0 +b9ca29b0ec8e41c6a02f54d8c16aebf377982488cbe2ed1753090f2db4f804f6269af03e015d647a82ef06ffaa8cba6c +b4df3858d61bbb5ded1cf0be22a79df65ae956e961fbb56c883e1881c4c21fe642e3f5a0c108a882e553ac59595e3241 +86457d8890ac8858d7bab180ef66851247c2bf5e52bf69a4051d1d015252c389684fcc30bb4b664d42fbf670574ab3a3 +86d5576ea6dfa06d9ebce4cd885450f270c88a283e1e0d29cab27851c14ed2f00355e167b52e1539f1218ad11d8f13dd +883ad1364dc2a92388bfafaa9bc943c55b2f813525831e817a6208c666829a40455dde494eba054b2495a95f7ce69e8a +8942371e6925231c2c603b5f5a882d8404d39f0c7c4232557c2610b21c2c07f145466da798ea78b7932da2b774aa3128 +a799eb71496783cc7faf12c9d9804bf6180699a004b2f07fc5cc36840f63ce7eee7dde9275819a9aa3f8d92dc0d47557 +8eb3fb5c769548ee38c7882f51b959c5d5a42b5935269ccf987d6ddbb25a206e80c6000bcc328af149e0727c0b7c02c0 +8f3910d64e421a8f2d8db4c7b352ba5b3fc519d5663973fea5962efe4364fb74448770df944ef37ffe0382648fb56946 +b41413e0c26ff124cf334dab0dc8e538293d8d519d11cc2d10895a96b2064ac60c7da39f08589b38726cffa4c3f0bfef +b46ef2eb10abae0f35fa4c9c7ee2665e8044b8d9f91988a241da40fd5bbc63166925582151941b400006e28bbc5ba22a +b8baa8b4c420bb572a3b6b85479b67d994c49a7ebfe1274687d946a0d0b36dfed7630cfb897350fa166f5e2eff8f9809 +964b46d359c687e0dcfbdab0c2797fc2bd1042af79b7418795b43d32ffca4de89358cee97b9b30401392ff54c7834f9f +8410d0203d382ebf07f200fd02c89b80676957b31d561b76563e4412bebce42ca7cafe795039f46baf5e701171360a85 +b1a8d5d473c1a912ed88ea5cfa37c2aea5c459967546d8f2f5177e04e0813b8d875b525a79c29cb3009c20e7e7292626 +afaab9a1637429251d075e0ba883380043eaf668e001f16d36737028fded6faa6eeed6b5bb340f710961cee1f8801c41 +aef17650003b5185d28d1e2306b2f304279da50925f2704a6a3a68312f29fe5c2f2939f14e08b0ba9dee06ea950ad001 +97bcc442f370804aa4c48c2f8318d6f3452da8389af9335e187482d2e2b83b9382e5c297dce1a0f02935e227b74e09a3 +8a67a27b199f0bcd02d52a3e32f9b76a486b830ec481a49a4e11807e98408b7052b48581b5dd9f0b3e93052ec45dfb68 +b113bf15f430923c9805a5df2709082ab92dcdf686431bbad8c5888ca71cc749290fa4d4388a955c6d6ee3a3b9bc3c53 +8629ca24440740ce86c212afed406026f4ea077e7aa369c4151b6fa57bca7f33f9d026900e5e6e681ae669fd2bd6c186 +933a528371dcecc1ec6ded66b1c7b516bd691b3b8f127c13f948bfbcda3f2c774c7e4a8fbee72139c152064232103bdf +8568ddd01f81a4df34e5fa69c7f4bb8c3c04274147498156aec2e3bd98ea3e57c8a23503925de8fa3de4184563a2b79e +8160874ec030f30fda8f55bcf62613994ff7ed831e4901c7560eac647182b4a9b43bfaff74b916602b9d6ae3bfcaf929 +ae71c48d48cf9459800cdf9f8e96bc22e2d4e37259e5c92a2b24fbe2c6ca42675e312288603c81762f6ceb15400bc4c9 +b05f39bb83fda73e0559db1fd4a71423938a87ad9f060d616d4f4a6c64bf99472a2cbfb95f88b9257c9630fc21a0b81f +80c8479a640ed7a39e67f2db5ad8dfd28979f5443e8e6c23da8087fc24134d4b9e7c94320ffa4154163270f621188c27 +9969ba20ee29c64cb3285a3433a7e56a0fe4ddc6f3d93e147f49fe021bed4a9315266ebb2fb0eb3036bb02001ae015e6 +a198c89fef2ab88e498703b9021becc940a80e32eb897563d65db57cc714eaa0e79092b09dd3a84cfab199250186edcc +8df14a3db8fe558a54d6120bad87405ba9415a92b08c498812c20416c291b09fed33d1e2fcf698eb14471f451e396089 +81e245ef2649b8a5c8d4b27188dd7e985ef6639090bdc03462c081396cf7fc86ed7d01bfe7e649d2b399255e842bdc21 +8659f622c7ab7b40061bcf7a10144b51ad3ab5348567195924f2944e8c4ce137a37f1ba328e4716c10806f3fb7271689 +a575d610fc8fe09334ca619ecdadf02d468ca71dd158a5a913252ca55ea8d8f9ce4548937c239b9cb8ab752a4d5af24a +94744549cd9f29d99f4c8c663997bdfa90e975b31f1086214245de9c87b0c32209f515a0de64d72d5ef49c09b0a031fa +80a8677862b056df59e350c967a27436c671b65d58854e100115bac9824ba177e94c2a1bfcaa191a071b9cefdbee3989 +91be9a5504ec99922440f92a43fe97ddce2f21b9d94cd3a94c085a89b70c903696cec203bbab6d0a70693ba4e558fb01 +8c5a0087bcd370734d12d9b3ab7bc19e9a336d4b49fc42825b2bfedcd73bb85eb47bf8bb8552b9097cc0790e8134d08c +933aa9e6bd86df5d043e0577a48e17eea3352e23befdbb7d7dcac33b5703d5ace230443ac0a40e23bf95da4cc2313478 +984b7ee4bd081ee06c484db6114c2ce0ba356988efb90f4c46ff85ed2865fb37f56a730166c29ef0ae3345a39cdeae7a +ae830f908ea60276c6c949fb8813e2386cf8d1df26dcf8206aa8c849e4467243e074471380ed433465dc8925c138ea4c +874c1df98d45b510b4f22feff46a7e8ed22cfc3fad2ac4094b53b9e6477c8dfc604976ca3cee16c07906dece471aa6c6 +a603eb60d4c0fb90fa000d2913689126849c0261e6a8649218270e22a994902965a4e7f8c9462447259495fe17296093 +a7c73d759a8ad5e3a64c6d050740d444e8d6b6c9ade6fb31cb660fa93dc4a79091230baccb51c888da05c28cb26f6f3f +a4411b79b6a85c79ea173bd9c23d49d19e736475f3d7d53213c5349ebb94a266d510d12ba52b2ac7a62deaaaec7339b8 +943b84f8bbcee53b06266b5c4cd24d649d972593837fe82b0bf5d5e1bbc1a2bf148e1426c366d7c39ab566b10224cadc +8300012096a8b4cefecc080054bf3ceb0918162ba263c6848860423407796b5eb517170c0bad8e4905ac69a383055a21 +8244a1e3ad41908c6f037e2f8db052e81f281646141334829f36c707f307448b9ab79a7f382a1e8d86f877c90b59271c +8eca1b74687802ecc36a5d39e4516a9dee3de61a2047252d9ed737b49e0090c386e9d792ac004c96337681c7f29a16ad +b70fa47535f0524835039a20036c61e77f66146ad79d3d339214d8744742db41ceeb577c829d000011aeafbb12e09579 +84b3abbce48689f3adbb99889c7fd1f3e15ab455d477e34f5151c5c1c358ed77a5b6a581879f7e0f1f34106e0792e547 +ab45ecb58c0ef0dbce3d16afc6ac281e0d90ec48741ea96a141152647e98fcc87f3a3ff07ba81f3179118453ce123156 +90d231a145ba36a59087e259bbfc019fa369201fcfeaa4347d5fd0a22cd8a716e5a797f3cc357f2779edb08f3b666169 +a4f6074d23c6c97e00130bc05f25213ca4fa76c69ca1ace9dece904a2bdd9d987661f5d55023b50028c444af47ff7a08 +933af884939ad0241f3f1f8e8be65f91d77ac0fb234e1134d92713b7cfb927f1933f164aec39177daa13b39c1370fac8 +80d1db6933ce72091332ae47dc691acb2a9038f1239327b26d08ea9d40aa8f2e44410bbda64f2842a398cbe8f74f770f +a7a08605be2241ccc00151b00b3196d9c0717c4150909a2e9cd05538781231762b6cc6994bebbd4cddae7164d048e7b2 +96db0d839765a8fdbbac03430fa800519e11e06c9b402039e9ae8b6503840c7ecac44123df37e3d220ac03e77612f4e4 +96d70f8e9acd5a3151a8a9100ad94f16c289a31d61df681c23b17f21749c9062622d0a90f6d12c52397b609c6e997f76 +8cf8e22273f7459396ff674749ab7e24c94fe8ab36d45d8235e83be98d556f2b8668ba3a4ec1cb98fac3c0925335c295 +97b7e796a822262abc1a1f5a54cb72a1ea12c6c5824ac34cd1310be02d858a3c3aa56a80f340439b60d100e59c25097d +a48208328b08769737aa1a30482563a4a052aea736539eceab148fa6653a80cb6a80542e8b453f1f92a33d0480c20961 +b612184941413fd6c85ff6aa517b58303b9938958aa85a85911e53ed308778624d77eadb27ccf970573e25d3dfd83df7 +b3717068011648c7d03bbd1e2fc9521a86d2c3ae69113d732c2468880a3b932ebec93596957026477b02842ed71a331b +a0ad363e1352dcf035b03830fef4e27d5fd6481d29d5e8c9d51e851e3862d63cdcbaf8e330d61c1b90886921dac2c6fd +8db409fdacfa4bfdaf01cc87c8e97b53ca3a6e3a526d794eaad1c2023f3df4b888f1bf19fee9a990fe6d5c7c3063f30c +b34d6975310ab15938b75ef15020a165fc849949065d32d912554b51ffa1d3f428a6d1a396cb9329367670391de33842 +9117285e9e6762853fc074b8a92b3923864de2c88c13cea7bab574aaf8cdd324843455d2c3f83c00f91f27c7ecc5592a +b4b2e8f190ea0b60819894710c866bf8578dd1b231ae701d430797cc7ede6e216e8ca6a304f3af9484061563645bf2ab +8c493c6853ab135d96a464815dd06cad8b3e8b163849cdefc23d1f20211685753b3d3e147be43e61e92e35d35a0a0697 +9864d7880f778c42d33cf102c425e380d999d55a975a29c2774cad920dfddb80087a446c4f32ed9a6ab5f22ec6f82af0 +90f67fe26f11ca13e0c72b2c2798c0d0569ed6bc4ce5bbaf517c096e7296d5dd5685a25012f6c6d579af5b4f5d400b37 +a228872348966f26e28a962af32e8fa7388d04bc07cfc0224a12be10757ac7ab16a3387c0b8318fcb0c67384b0e8c1a4 +a9d9d64bba3c03b51acf70aeb746a2712ddafe3b3667ae3c25622df377c2b5504e7ab598263bec835ab972283c9a168b +932128971c9d333f32939a1b46c4f7cf7e9d8417bd08dc5bd4573ccbd6ec5b460ac8880fb7f142f7ef8a40eef76d0c6d +964115e7838f2f197d6f09c06fbb2301d6e27c0ecdf208350cf3b36c748436dac50f47f9f9ac651c09ab7ad7221c7e43 +a5941f619e5f55a9cf6e7f1499b1f1bcddcc7cf5e274efedaaad73a75bc71b1fc5c29cd903f6c69dc9a366a6933ca9d1 +a154bf5eaec096029e5fe7c8bf6c695ae51ace356bb1ad234747776c7e1b406dee2d58864c3f4af84ed69f310974125e +b504e6209d48b0338ab1e4bdab663bac343bb6e0433466b70e49dc4464c1ec05f4a98111fd4450393607510ae467c915 +813411918ea79bdde295393284dc378b9bdc6cfcb34678b9733ea8c041ac9a32c1e7906e814887469f2c1e39287e80f8 +8be0369f94e4d72c561e6edb891755368660208853988647c55a8eed60275f2dd6ee27db976de6ecf54ac5c66aaf0ae6 +a7e2701e55b1e7ea9294994c8ad1c080db06a6fc8710cd0c9f804195dce2a97661c566089c80652f27b39018f774f85e +956b537703133b6ddf620d873eac67af058805a8cc4beb70f9c16c6787bf3cc9765e430d57a84a4c3c9fbdd11a007257 +835ae5b3bb3ee5e52e048626e3ddaa49e28a65cb94b7ecdc2e272ff603b7058f1f90b4c75b4b9558f23851f1a5547a35 +85d67c371d1bf6dc72cca7887fa7c886ce988b5d77dc176d767be3205e80f6af2204d6530f7060b1f65d360a0eaeff30 +a84a6647a10fcef8353769ef5f55a701c53870054691a6e9d7e748cbe417b3b41dbb881bae67adc12cb6596c0d8be376 +87ffe271fc0964cb225551c7a61008d8bcb8b3d3942970dbcc2b9f4f9045a767971880368ea254e2038a3a0b94ecf236 +964bb721c51d43ee7dd67c1a2b7dd2cc672ce8fad78c22dcddb43e6aab48d9a4a7dc595d702aa54a6fb0ffabf01f2780 +a89b3f84bb7dcbe3741749776f5b78a269f6b1bebb8e95d3cc80b834fd2177c6be058d16cacfd0d5e1e35e85cde8b811 +b4314538e003a1587b5592ff07355ea03239f17e75c49d51f32babe8e048b90b046a73357bcb9ce382d3e8fbe2f8e68b +86daf4bf201ae5537b5d4f4d734ed2934b9cf74de30513e3280402078f1787871b6973aa60f75858bdf696f19935a0e2 +b1adf5d4f83f089dc4f5dae9dbd215322fa98c964e2eaa409bf8ca3fa5c627880a014ed209492c3894b3df1c117236c4 +b508d52382c5bac5749bc8c89f70c650bb2ed3ef9dc99619468c387c1b6c9ff530a906dfa393f78f34c4f2f31478508a +a8349a5865cb1f191bebb845dfbc25c747681d769dbffd40d8cedf9c9a62fa2cbc14b64bb6121120dab4e24bef8e6b37 +af0500d4af99c83db8890a25f0be1de267a382ec5e9835e2f3503e1bac9412acf9ff83a7b9385708ef8187a38a37bc77 +b76d57a1c1f85b8a8e1722a47057b4c572800957a6b48882d1fc21309c2e45f648a8db0fcff760d1dbc7732cf37c009b +b93c996cec0d3714667b5a5a5f7c05a7dc00bbc9f95ac8e310626b9e41ae4cc5707fac3e5bd86e1e1f2f6d9627b0da94 +93216fdb864217b4c761090a0921cf8d42649ab7c4da1e009ec5450432564cb5a06cb6e8678579202d3985bd9e941cef +8b8be41105186a339987ae3a5f075fbc91f34b9984d222dfed0f0f85d2f684b56a56ab5dc812a411570491743d6c8b18 +959b72782a6b2469e77fe4d492674cc51db148119b0671bd5d1765715f49fa8a87e907646671161586e84979ef16d631 +86b7fc72fb7e7904ea71d5e66ba0d5d898ace7850985c8cc4a1c4902c5bf94351d23ce62eed45e24321fb02adfa49fc8 +a2f244e7c9aa272cb0d067d81d25e5a3045b80b5a520b49fd5996ece267a7f1bea42e53147bbf153d9af215ea605fc9e +81aa2efa5520eebc894ce909ba5ce3250f2d96baa5f4f186a0637a1eea0080dd3a96c2f9fadf92262c1c5566ddb79bab +b607dd110cfe510d087bcff9a18480ba2912662256d0ab7b1d8120b22db4ad036b2266f46152754664c4e08d0fc583f6 +8f588d5f4837e41312744caac5eee9ddc3ad7085871041694f0b5813edf83dc13af7970f7c9b6d234a886e07fa676a04 +924921b903207783b31016cbec4e6c99e70f5244e775755c90d03a8b769738be3ba61577aca70f706a9c2b80040c9485 +ae0a42a222f1a71cd0d3c69ffb2f04c13e1940cce8efabe032629f650be3ceed6abb79651dbb81cb39a33286eb517639 +a07d7d76460f31f5f0e32e40a5ea908d9d2aebf111ac4fadee67ef6540b916733c35a777dcdc05f6417726ca1f2d57dd +88d7f8a31f8c99794291847d28745e5d0b5d3b9684ca4170b686ffbb5bb521a3ef6746c3c8db22e4250a0cdff7939d96 +849573071fd98c020dc9a8622a9eff221cb9f889bde259e7127a8886b73bef7ad430b87750915658918dcfb6b7b4d8d3 +b12d59f732fa47fad175d6263734da8db89230fd340a46ad1cdee51e577041a5c80bf24cd195593e637daf1a66ef5a98 +abbcfb8a4a6d5e269ee1ac5e277df84416c73ca55ec88317f73608201af25af0cb65b943c54684a5651df3a26e3daca2 +ab157f589bdbaf067a6a7ba7513df0492933855d39f3a081196cf2352e0ddc0162d476c433320366e3df601e0556278d +a86c0619b92e5ae4f7daa876a2abc5ba189156afc2fa05eef464dfa342ba37fc670d0dc308ad3822fcb461ab001bac30 +a3f292946476cfe8d5e544a5325439a00e0165a5f9bf3bb6a53f477baeac7697cc0377745536681aa116f326ce911390 +8aecbbfd442a6a0f01c1c09db5d9d50213eb6f1ff6fab674cde3da06a4edff3ed317e804f78300c22ef70c336123e05d +834ed4b58211fcd647d7bf7c0a3ba9085184c5c856b085e8a0fcd5215c661ef43d36f3f0f6329a9f1370501b4e73b6e4 +a114ea5ad2b402a0de6105e5730907f2f1e458d28ae35144cf49836e0ad21325fe3e755cfb67984ae0a32e65402aad1e +a005f12bed97d71cee288b59afe9affb4d256888727343944a99913980df2c963fe02f218e6ea992f88db693a4498066 +a010f286ab06b966e3b91ff8f1bdbe2fe9ab41a27bc392d5787aa02a46e5080e58c62c7d907818caae9f6a8b8123e381 +857bd6df2ddef04dbc7c4f923e0b1696d3016c8bfed07fdfa28a3a3bd62d89b0f9df49aae81cbb6883d5e7b4fadae280 +b3927030da445bc4756ac7230a5d87412a4f7510581fb422212ce2e8cf49689aca7ba71678743af06d4de4914c5aa4a0 +b86403182c98fcce558d995f86752af316b3b2d53ba32075f71c7da2596747b7284c34a1a87de604fcc71e7e117a8add +98dd19b5527733041689b2a4568edaf6aa0fe1a3dd800c290cda157b171e053648a5772c5d3d4c80e5a795bc49adf12e +88a3c227bb7c9bff383f9ad3f7762245939a718ab85ae6e5e13180b12bf724d42054d3852b421c1cd1b3670baddecb63 +b3cfd9ad66b52bbe57b5fff0fad723434d23761409b92c4893124a574acc1e6b1e14b4ec507661551cbbe05e16db362e +923e1bb482cf421dd77801f9780f49c3672b88508a389b94015fd907888dc647ee9ea8ec8d97131d235d066daf1f42b7 +8d5e16240f04f92aa948181d421006bdbc7b215648fb6554193224d00cf337ebbb958f7548cf01b4d828acffb9fbc452 +8b2b8f18ad0559746f6cda3acca294a1467fb1a3bc6b6371bc3a61a3bfe59418934fa8706f78b56005d85d9cb7f90454 +a9316e2a94d6e31426d2ae7312878ba6baaac40f43e2b8a2fa3ab5a774c6918551554b2dbb23dc82f70ba3e0f60b5b0d +9593116d92cf06b8cd6905a2ce569ee6e69a506c897911f43ae80fc66c4914da209fc9347962034eebbc6e3e0fe59517 +887d89d2b2d3c82b30e8f0acf15f0335532bd598b1861755498610cb2dd41ff5376b2a0bb757cb477add0ce8cfe7a9fc +b514cfe17875ecb790ad055271cc240ea4bda39b6cfa6a212908849c0875cb10c3a07826550b24c4b94ea68c6bb9e614 +a563d5187966d1257d2ed71d53c945308f709bcc98e3b13a2a07a1933dc17bcb34b30796bd68c156d91811fbd49da2cb +a7195ccc53b58e65d1088868aeeb9ee208103e8197ad4c317235bb2d0ad3dc56cb7d9a7186416e0b23c226078095d44c +a838e7a368e75b73b5c50fbfedde3481d82c977c3d5a95892ac1b1a3ea6234b3344ad9d9544b5a532ccdef166e861011 +9468ed6942e6b117d76d12d3a36138f5e5fb46e3b87cf6bb830c9b67d73e8176a1511780f55570f52d8cdb51dcf38e8c +8d2fc1899bc3483a77298de0e033085b195caf0e91c8be209fd4f27b60029cbe1f9a801fbd0458b4a686609762108560 +8f4e44f8ca752a56aa96f3602e9234ad905ad9582111daf96a8c4d6f203bf3948f7ce467c555360ad58376ee8effd2ba +8fb88640b656e8f1c7c966c729eb2ba5ccf780c49873f8b873c6971840db7d986bdf1332ba80f8a0bb4b4ee7401468fa +b72aa3235868186913fb5f1d324e748cd3ce1a17d3d6e6ea7639a5076430fe0b08841c95feb19bb94181fe59c483a9eb +b8b102690ebb94fc4148742e7e3fd00f807b745b02cbe92cd92992c9143b6db7bb23a70da64a8b2233e4a6e572fc2054 +8c9ae291f6cd744e2c6afe0719a7fc3e18d79307f781921fb848a0bf222e233879c1eca8236b4b1be217f9440859b6ce +a658ede47e14b3aad789e07f5374402f60e9cacb56b1b57a7c6044ca2418b82c98874e5c8c461898ebd69e38fecd5770 +89c0cb423580e333923eb66bda690f5aca6ec6cba2f92850e54afd882ba608465a7dbb5aa077cd0ca65d9d00909348ab +aed8e28d98d5508bd3818804cf20d296fe050b023db2ed32306f19a7a3f51c7aaafed9d0847a3d2cd5ba5b4dabbc5401 +96a0fcd6235f87568d24fb57269a94402c23d4aa5602572ad361f3f915a5f01be4e6945d576d51be0d37c24b8b0f3d72 +935d0c69edd5dfa8ed07c49661b3e725b50588f814eb38ea31bcc1d36b262fae40d038a90feff42329930f8310348a50 +900518288aa8ea824c7042f76710f2ea358c8bb7657f518a6e13de9123be891fa847c61569035df64605a459dad2ecc8 +947d743a570e84831b4fb5e786024bd752630429d0673bf12028eb4642beb452e133214aff1cfa578a8856c5ebcb1758 +a787266f34d48c13a01b44e02f34a0369c36f7ec0aae3ec92d27a5f4a15b3f7be9b30b8d9dd1217d4eeedff5fd71b2e5 +a24b797214707ccc9e7a7153e94521900c01a1acd7359d4c74b343bfa11ea2cdf96f149802f4669312cd58d5ab159c93 +97f5ee9c743b6845f15c7f0951221468b40e1edaef06328653a0882793f91e8146c26ac76dd613038c5fdcf5448e2948 +80abd843693aed1949b4ea93e0188e281334163a1de150c080e56ca1f655c53eb4e5d65a67bc3fc546ed4445a3c71d00 +908e499eb3d44836808dacff2f6815f883aeced9460913cf8f2fbbb8fe8f5428c6fc9875f60b9996445a032fd514c70f +ae1828ef674730066dc83da8d4dd5fa76fc6eb6fa2f9d91e3a6d03a9e61d7c3a74619f4483fe14cddf31941e5f65420a +a9f4dbe658cd213d77642e4d11385a8f432245b098fccd23587d7b168dbeebe1cca4f37ee8d1725adb0d60af85f8c12f +93e20ee8a314b7772b2439be9d15d0bf30cd612719b64aa2b4c3db48e6df46cea0a22db08ca65a36299a48d547e826a7 +a8746a3e24b08dffa57ae78e53825a9ddbbe12af6e675269d48bff4720babdc24f907fde5f1880a6b31c5d5a51fbb00e +b5e94dfab3c2f5d3aea74a098546aa6a465aa1e3f5989377d0759d1899babf543ad688bb84811d3e891c8713c45886c5 +a3929bada828bd0a72cda8417b0d057ecb2ddd8454086de235540a756e8032f2f47f52001eb1d7b1355339a128f0a53b +b684231711a1612866af1f0b7a9a185a3f8a9dac8bde75c101f3a1022947ceddc472beb95db9d9d42d9f6ccef315edbc +af7809309edbb8eb61ef9e4b62f02a474c04c7c1ffa89543d8c6bf2e4c3d3e5ecbd39ec2fc1a4943a3949b8a09d315a6 +b6f6e224247d9528ef0da4ad9700bee6e040bbf63e4d4c4b5989d0b29a0c17f7b003c60f74332fefa3c8ddbd83cd95c1 +adbcec190a6ac2ddd7c59c6933e5b4e8507ce5fd4e230effc0bd0892fc00e6ac1369a2115f3398dfc074987b3b005c77 +8a735b1bd7f2246d3fa1b729aecf2b1df8e8c3f86220a3a265c23444bdf540d9d6fe9b18ed8e6211fad2e1f25d23dd57 +96b1bf31f46766738c0c687af3893d098d4b798237524cb2c867ed3671775651d5852da6803d0ea7356a6546aa9b33f2 +8036e4c2b4576c9dcf98b810b5739051de4b5dde1e3e734a8e84ab52bc043e2e246a7f6046b07a9a95d8523ec5f7b851 +8a4f4c32ee2203618af3bb603bf10245be0f57f1cfec71037d327fa11c1283b833819cb83b6b522252c39de3ce599fa5 +ad06ed0742c9838e3abaaffdb0ac0a64bad85b058b5be150e4d97d0346ed64fd6e761018d51d4498599669e25a6e3148 +8d91cb427db262b6f912c693db3d0939b5df16bf7d2ab6a7e1bc47f5384371747db89c161b78ff9587259fdb3a49ad91 +ae0a3f84b5acb54729bcd7ef0fbfdcf9ed52da595636777897268d66db3de3f16a9cf237c9f8f6028412d37f73f2dfad +8f774109272dc387de0ca26f434e26bc5584754e71413e35fa4d517ee0f6e845b83d4f503f777fe31c9ec05796b3b4bc +a8670e0db2c537ad387cf8d75c6e42724fae0f16eca8b34018a59a6d539d3c0581e1066053a2ec8a5280ffabad2ca51f +ac4929ed4ecad8124f2a2a482ec72e0ef86d6a4c64ac330dab25d61d1a71e1ee1009d196586ce46293355146086cabba +845d222cb018207976cc2975a9aa3543e46c861486136d57952494eb18029a1ebb0d08b6d7c67c0f37ee82a5c754f26f +b99fa4a29090eac44299f0e4b5a1582eb89b26ed2d4988b36338b9f073851d024b4201cd39a2b176d324f12903c38bee +9138823bc45640b8f77a6464c171af2fe1700bdc2b7b88f4d66b1370b3eafe12f5fbb7b528a7e1d55d9a70ca2f9fc8e6 +8ac387dc4cf52bc48a240f2965ab2531ae3b518d4d1f99c0f520a3d6eb3d5123a35ef96bed8fa71ee2f46793fa5b33b3 +864adec6339d4c2ba2525621fceabd4c455902f6f690f31a26e55413e0722e5711c509dc47ce0bcc27bbdc7651768d2d +a0a52edb72268a15201a968dabc26a22909620bda824bd548fb8c26cc848f704166ed730d958f0173bd3b0a672f367bd +949e445b0459983abd399571a1a7150aab3dd79f4b52a1cd5d733e436c71c1d4b74287c6b0ce6cc90c6711ba4c541586 +858966355dac11369e3b6552f2b381665181693d5a32e596984da3314021710b25a37d8c548b08700eea13d86cb22f21 +974bcbb8d38c5e6518745cc03ad436e585b61f31d705e7e2e5085da9655d768ac4d800904f892c3dab65d6223e3f1fd6 +8092b6506b01308bf6187fde5ebd4fa7448c9a640961ba231be22ac5fa2c7635ef01e8b357722c7695d09b723101ea2a +a5b8ef360bf28533ee17d8cd131fff661d265f609db49599085c0c7d83b0af409a1b5c28e3a5e5d7f8459a368aa121e8 +b031b6d5e3ceab0f0c93314b3b675f55cf18cbc86f70444af266fe39cb22fd7dad75d8c84e07f1c1bfa2cb8283e1361a +93ad489e4f74658320c1cceed0137c023d3001a2c930ed87e6a21dbf02f2eb6ad1c1d8bcb3739c85dcfbecb040928707 +b15e4ec2cdab0d34aec8d6c50338812eb6ecd588cf123a3e9d22a7ca23b5a98662af18289f09e6cdd85a39a2863c945c +b304f71a9717cf40c22073f942618b44bf27cd5e2ed4a386ad45d75b0fcb5a8dafd35158211eaf639495c6f1a651cedb +b82d78d3eaaa7c5101b7a5aae02bd4f002cd5802d18c3abcda0dd53b036661c6d3c8b79e0abe591eab90b6fdc5fef5e3 +abbd1884243a35578b80914a5084449c237ee4e4660c279d1073a4d4217d1b55c6b7e9c087dfd08d94ac1416273d8d07 +92f4b61c62502745e3e198ec29bca2e18696c69dcb914d1f3a73f4998d012b90caf99df46e9bb59942e43cce377fe8fd +906e79df98185820c8208844e1ba6bd86cb96965814b01310bd62f22cbec9b5d379b2ef16772d6fc45a421b60cfd68fe +a0eae2784ef596e2eb270dd40c48d6c508e4394c7d6d08d4cc1b56fde42b604d10ba752b3a80f2c4a737e080ef51b44f +94c084985e276dc249b09029e49a4ef8a369cd1737b51c1772fbb458d61e3fe120d0f517976eba8ffa5711ba93e46976 +83619a0157eff3f480ab91d1d6225fead74c96a6fd685333f1e8e4d746f6273e226bad14232f1d1168a274e889f202f1 +a724fe6a83d05dbbf9bb3f626e96db2c10d6d5c650c0a909415fbda9b5711c8b26e377201fb9ce82e94fa2ab0bf99351 +a8a10c1b91a3a1fa2d7fd1f78a141191987270b13004600601d0f1f357042891010717319489f681aa8a1da79f7f00d5 +a398a2e95b944940b1f8a8e5d697c50e7aa03994a8a640dfad4ea65cfb199a4d97861a3ec62d1c7b2b8d6e26488ca909 +a2eedfe5452513b2a938fffd560798ef81379c5a5032d5b0da7b3bb812addbaad51f564c15d9acbbfc59bb7eddd0b798 +ab31c572f6f145a53e13b962f11320a1f4d411739c86c88989f8f21ab629639905b3eedb0628067942b0dc1814b678ca +ad032736dd0e25652d3566f6763b48b34ea1507922ed162890cd050b1125ec03b6d41d34fccba36ec90336f7cdf788ed +83028a558a5847293147c483b74173eca28578186137df220df747fccd7d769528d7277336ea03c5d9cdd0bc5ae3d666 +ab5d182cd1181de8e14d3ef615580217c165e470b7a094a276b78a3003089123db75c6e1650bf57d23e587c587cd7472 +a4793e089fbdb1597654f43b4f7e02d843d4ab99ee54099c3d9f0bd5c0c5657c90bb076379a055b00c01b12843415251 +98bdc52ee062035356fb2b5c3b41673198ddc60b2d1e546cb44e3bb36094ef3c9cf2e12bbc890feb7d9b15925439d1ea +a4f90cca6f48024a0341bd231797b03693b34e23d3e5b712eb24aba37a27827319b2c16188f97c0636a0c115381dc659 +8888e6c2e4a574d04ba5f4264e77abc24ccc195f1a7e3194169b8a2ceded493740c52db4f9833b3dbf4d67a3c5b252cb +83dc4e302b8b0a76dc0292366520b7d246d73c6aebe1bdd16a02f645c082197bcff24a4369deda60336172cefbcf09af +a4eb2741699febfeb793914da3054337cc05c6fa00d740e5f97cb749ae16802c6256c9d4f0f7297dcdbb8b9f22fc0afa +8b65557d5be273d1cb992a25cfce40d460c3f288d5cb0a54bdef25cbd17cdea5c32ec966e493addf5a74fd8e95b23e63 +97c6577e76c73837bcb398b947cb4d3323d511141e0ddd0b456f59fbb1e8f920a5c20d7827a24309145efddee786140f +abcc0849ffe2a6a72157de907907b0a52deece04cf8317bee6fe1d999444b96e461eac95b6afde3d4fe530344086a625 +9385c0115cb826a49df1917556efa47b5b5e4022b6a0d2082053d498ec9681da904ecf375368bb4e385833116ea61414 +8b868c1841f0cdc175c90a81e610b0652c181db06731f5c8e72f8fafa0191620742e61a00db8215a991d60567b6a81ca +a8df15406f31b8fcf81f8ff98c01f3df73bf9ec84544ddec396bdf7fafa6fe084b3237bf7ef08ad43b26517de8c3cd26 +a9943d21e35464ce54d4cc8b135731265a5d82f9ccf66133effa460ffdb443cdb694a25320506923eede88d972241bf2 +a1378ee107dd7a3abcf269fd828887c288363e9b9ca2711377f2e96d2ed5e7c5ec8d3f1da995a3dcbedf1752d9c088fc +8a230856f9227b834c75bdebc1a57c7298a8351874bf39805c3e0255d6fd0e846f7ad49709b65ec1fd1a309331a83935 +877bcf42549d42610e1780e721f5800972b51ba3b45c95c12b34cb35eeaf7eac8fa752edd7b342411820cf9093fea003 +84c7a0b63842e50905624f1d2662506b16d1f3ea201877dfc76c79181c338b498eceb7cad24c2142c08919120e62f915 +8e18b1bd04b1d65f6ed349b5d33a26fe349219043ead0e350b50ae7a65d6ff5f985dd9d318d3b807d29faa1a7de4fe42 +8ea7b5a7503e1f0b3c3cd01f8e50207044b0a9c50ed1697794048bbe8efd6659e65134d172fb22f95439e1644f662e23 +b1954a2818cad1dad6d343a7b23afa9aa8ad4463edc4eb51e26e087c2010927535020d045d97d44086d76acdb5818cbf +a5271ea85d0d21fa1ff59b027cf88847c0f999bbf578599083ff789a9b5228bc161e1c81deb97e74db1a82a0afd61c50 +aa2fa4c05af3387e2c799315781d1910f69977ec1cfea57a25f1a37c63c4daaa3f0ecd400884a1673e17dd5300853bcf +b1cd2a74ca0b8e6090da29787aef9b037b03b96607983a308b790133bd21297b21ca4e2edec890874096dbf54e9d04c3 +801931607ec66a81272feaa984f0b949ad12d75ecf324ba96627bd4dc5ddead8ebf088f78e836b6587c2b6c0b3366b6c +95d79504710bdf0ad9b9c3da79068c30665818c2f0cdbba02cc0a5e46e29d596032ac984441b429bd62e34535c8d55b0 +9857d41e25e67876510ff8dadf0162019590f902da1897da0ef6fc8556e3c98961edb1eb3a3a5c000f6c494413ded15e +8740c9ffe6bd179c19a400137c3bd3a593b85bd4c264e26b4dfb9e2e17ac73e5b52dfacc1dcb4033cfc0cd04785f4363 +977f98f29d948b4097a4abdf9345f4c1fb0aa94ba0c6bf6faa13b76f3a3efc8f688e1fe96099b71b3e1c05041118c8d1 +a364422b1239126e3e8d7b84953ce2181f9856319b0a29fcab81e17ac27d35798088859c1cfc9fc12b2dbbf54d4f70b3 +a0f6ba637f0db7a48e07439bb92ddb20d590ce9e2ed5bab08d73aa22d82c32a9a370fe934cbe9c08aeb84b11adcf2e0e +a2c548641bd5b677c7748327cca598a98a03a031945276be6d5c4357b6d04f8f40dd1c942ee6ec8499d56a1290ac134d +9863e9cc5fbcdbd105a41d9778d7c402686bfd2d81d9ed107b4fda15e728871c38647529693306855bee33a00d257a7e +a54173bf47b976290c88fd41f99300135de222f1f76293757a438450880e6f13dbde3d5fe7afc687bdfbcfc4fbc1fc47 +b8db413917c60907b73a997b5ab42939abd05552c56a13525e3253eb72b83f0d5cc52b695968a10005c2e2fe13290e61 +a1f8388ef21697c94ba90b1a1c157f0dc138e502379e6fc5dc47890d284563e5db7716266e1b91927e5adf3cde4c0a72 +9949013a59d890eb358eab12e623b2b5edb1acbee238dfad8b7253102abc6173922e188d5b89ec405aa377be8be5f16d +a00fdb7710db992041f6ddb3c00099e1ce311dea43c252c58f560c0d499983a89de67803a8e57baa01ee9d0ee6fa1e44 +a8b1bcbed1951c9cdb974b61078412881b830b48cd6b384db0c00fa68bcc3f4312f8e56c892ea99d3511857ef79d3db9 +8f3ee78404edc08af23b1a28c2012cee0bdf3599a6cb4ea689fc47df4a765ef519191819a72562b91a0fbcdb896a937e +8155bbb7fa8d386848b0a87caae4da3dec1f3dade95c750a64a8e3555166ccc8799f638bd80ed116c74e3a995541587a +abfe30adbc0a6f1fd95c630ed5dac891b85384fa9331e86b83217f29dff0bd7cad19d328485715a7e3df9a19069d4d2f +89d0783e496ee8dbb695764b87fb04cee14d4e96c4ba613a19736971c577d312079048142c12ce5b32b21e4d491d281b +856b8dbc9c5d8f56b6bb7d909f339ca6da9a8787bba91f09130a025ab6d29b64dbf728ba6ed26e160a23c1cdb9bc037b +8a30dd2ea24491141047a7dfe1a4af217661c693edf70b534d52ca547625c7397a0d721e568d5b8398595856e80e9730 +ae7e1412feb68c5721922ed9279fb05549b7ef6812a4fd33dbbbd7effab756ab74634f195d0c072143c9f1fd0e1ee483 +b7ce970e06fa9832b82eef572f2902c263fda29fdce9676f575860aae20863046243558ede2c92343616be5184944844 +85ed0531f0e5c1a5d0bfe819d1aa29d6d5ff7f64ad8a0555560f84b72dee78e66931a594c72e1c01b36a877d48e017ca +b8595be631dc5b7ea55b7eb8f2982c74544b1e5befc4984803b1c69727eac0079558182f109e755df3fd64bee00fcaa5 +99e15a66e5b32468ef8813e106271df4f8ba43a57629162832835b8b89402eb32169f3d2c8de1eb40201ce10e346a025 +844c6f5070a8c73fdfb3ed78d1eddca1be31192797ad53d47f98b10b74cc47a325d2bc07f6ee46f05e26cf46a6433efb +974059da7f13da3694ad33f95829eb1e95f3f3bfc35ef5ef0247547d3d8ee919926c3bd473ab8b877ff4faa07fcc8580 +b6f025aecc5698f6243cc531782b760f946efebe0c79b9a09fe99de1da9986d94fa0057003d0f3631c39783e6d84c7d5 +b0c5358bc9c6dfe181c5fdf853b16149536fbb70f82c3b00db8d854aefe4db26f87332c6117f017386af8b40288d08f9 +a3106be5e52b63119040b167ff9874e2670bd059b924b9817c78199317deb5905ae7bff24a8ff170de54a02c34ff40a4 +ad846eb8953a41c37bcd80ad543955942a47953cbc8fb4d766eac5307892d34e17e5549dc14467724205255bc14e9b39 +b16607e7f0f9d3636e659e907af4a086ad4731488f5703f0917c4ce71a696072a14a067db71a3d103530920e1ec50c16 +8ed820e27116e60c412c608582e9bb262eaaf197197c9b7df6d62b21a28b26d49ea6c8bb77dfde821869d9b58025f939 +97bc25201d98cde389dd5c0c223a6f844393b08f75d3b63326343073e467ac23aacef630ddc68545ea874299ba4a3b4f +b73c9695ad2eefd6cc989a251c433fab7d431f5e19f11d415a901762717d1004bb61e0cc4497af5a8abf2d567e59fef4 +adaabe331eea932533a7cc0cf642e2a5e9d60bbc92dd2924d9b429571cbf0d62d32c207b346607a40643c6909b8727e2 +a7b1bbfe2a5e9e8950c7cb4daab44a40c3ffab01dc012ed7fe445f4af47fa56d774a618fafe332ab99cac4dfb5cf4794 +b4a3c454dcd5af850212e8b9ba5fe5c0d958d6b1cabbf6c6cfe3ccbc4d4c943309c18b047256867daf359006a23f3667 +a5c0b32f6cef993834c1381ec57ad1b6f26ae7a8190dd26af0116e73dadc53bb0eeb1911419d609b79ce98b51fdc33bc +ac2f52de3ecf4c437c06c91f35f7ac7d171121d0b16d294a317897918679f3b9db1cef3dd0f43adb6b89fe3030728415 +94722ae6d328b1f8feaf6f0f78804e9b0219de85d6f14e8626c2845681841b2261d3e6a2c5b124086b7931bf89e26b46 +a841a0602385d17afabca3a1bb6039167d75e5ec870fea60cfcaec4863039b4d745f1a008b40ec07bca4e42cb73f0d21 +8c355f0a1886ffced584b4a002607e58ff3f130e9de827e36d38e57cb618c0cb0b2d2dea2966c461cb3a3887ede9aef1 +a6a9817b0fc2fd1786f5ba1a7b3d8595310987fb8d62f50a752c6bb0b2a95b67d03a4adfd13e10aa6190a280b7ee9a67 +a1d2e552581ecbafeaef08e389eaa0b600a139d446e7d0648ac5db8bbbf3c438d59497e3a2874fc692b4924b87ff2f83 +a1b271c55389f25639fe043e831e2c33a8ba045e07683d1468c6edd81fedb91684e4869becfb164330451cfe699c31a8 +8c263426e7f7e52f299d57d047a09b5eeb893644b86f4d149535a5046afd655a36d9e3fdb35f3201c2ccac2323a9582e +b41c242a7f7880c714241a97d56cce658ee6bcb795aec057a7b7c358d65f809eb901e0d51256826727dc0dc1d1887045 +93001b9445813c82f692f94c0dc1e55298f609936b743cf7aae5ebfa86204f38833d3a73f7b67314be67c06a1de5682d +82087536dc5e78422ad631af6c64c8d44f981c195ddea07d5af9bb0e014cdc949c6fa6e42fce823e0087fdb329d50a34 +8e071861ceba2737792741c031f57e0294c4892684506b7c4a0fc8b2f9a0a6b0a5635de3d1e8716c34df0194d789ae86 +b471c997e1e11774bd053f15609d58838a74073a6c089a7a32c37dd3f933badf98c7e5833263f3e77bc0d156a62dd750 +8d2d8686fb065b61714414bb6878fff3f9e1e303c8e02350fd79e2a7f0555ded05557628152c00166ce71c62c4d2feaa +ae4c75274d21c02380730e91de2056c0262ffcecf0cbdb519f0bdb0b5a10ae2d4996b3dc4b3e16dbaea7f0c63d497fef +97140d819e8ca6330e589c6debdee77041c5a9cedb9b8cbd9c541a49207eeb7f6e6b1c7e736ec8ba6b3ab10f7fcd443a +af6659f31f820291a160be452e64d1293aa68b5074b4c066dac169b8d01d0179139504df867dc56e2a6120354fc1f5be +a5e5d8088a368024617bfde6b731bf9eee35fc362bed3f5dfdd399e23a2495f97f17728fec99ca945b3282d1858aa338 +a59cfc79d15dbdde51ab8e5129c97d3baba5a0a09272e6d2f3862370fdbaf90994e522e8bd99d6b14b3bb2e9e5545c6f +a30499b068083b28d6c7ddcc22f6b39b5ec84c8ee31c5630822c50ea736bb9dca41c265cffc6239f1c9ef2fd21476286 +88ffe103eca84bbe7d1e39a1aa599a5c7c9d5533204d5c4e085402a51441bb8efb8971efe936efbbfa05e5cb0d4b8017 +b202356fbf95a4d699154639e8cb03d02112c3e0128aab54d604645d8510a9ba98936028349b661672c3a4b36b9cb45d +8b89bb6574bf3524473cff1ff743abcf1406bd11fb0a72070ccd7d8fce9493b0069fb0c6655252a5164aee9e446ea772 +93247b1038fa7e26667ee6446561d4882dc808d1015daafb705935ddc3598bb1433182c756465960480f7b2de391649e +b027f94d3358cbb8b6c8c227300293a0dee57bf2fee190a456ad82ecfb6c32f8090afa783e2ab16f8139805e1fb69534 +a18bb1849b2f06c1d2214371031d41c76ffa803ee3aa60920d29dbf3db5fbfac2b7383d5d0080ba29ce25c7baa7c306b +827bf9fd647e238d5ac961c661e5bbf694b4c80b3af8079f94a2484cb8fba2c8cf60e472ebcd0b0024d98ae80ad2ff5a +838e891218c626a7f39b8fd546b013587408e8e366ecc636b54f97fa76f0a758bc1effa1d0f9b6b3bc1a7fcc505970a0 +836523b5e8902d6e430c6a12cff01e417d2bd7b402e03904034e3b39755dee540d382778c1abe851d840d318ebedce7f +850a77dda9ac6c217e2ef00bf386a1adec18b7f462f52801c4f541215690502a77ef7519b690e22fdf54dc2109e0ca38 +a8265c6ae7b29fc2bda6a2f99ced0c1945dd514b1c6ca19da84b5269514f48a4f7b2ccbab65c9107cfd5b30b26e5462f +ab3d02ee1f1267e8d9d8f27cc388e218f3af728f1de811242b10e01de83471a1c8f623e282da5a284d77884d9b8cde0e +831edaf4397e22871ea5ddee1e7036bab9cc72f8d955c7d8a97f5e783f40532edbbb444d0520fefcffeab75677864644 +80484487977e4877738744d67b9a35b6c96be579a9faa4a263e692295bb6e01f6e5a059181f3dd0278e2c3c24d10a451 +aae65a18f28c8812617c11ecf30ad525421f31fb389b8b52d7892415e805a133f46d1feca89923f8f5b8234bd233486a +b3a36fd78979e94288b4cefed82f043a7e24a4a8025479cc7eb39591e34603048a41ee606ee03c0b5781ebe26a424399 +b748b3fc0d1e12e876d626a1ba8ad6ad0c1f41ea89c3948e9f7d2666e90173eb9438027fadcd741d3ae0696bd13840f1 +acdd252d7c216c470683a140a808e011c4d5f1b4e91aeb947f099c717b6a3bad6651142cde988330827eb7d19d5fb25c +b9a25556a6ca35db1ed59a1ec6f23343eab207a3146e4fc3324136e411c8dba77efd567938c63a39c2f1c676b07d8cdb +a8db6aef8f5680d2bdb415d7bcaae11de1458678dcb8c90c441d5986c44f83a9e5855662d0c1aace999172d8628d8fe1 +af58147108e9909c3a9710cc186eab598682dca4bfd22481e040b8c000593ecb22c4ede4253ac9504e964dfa95a9b150 +8dd8bb70f1c9aec0fcc9478f24dfc9c3c36c0bf5ff7a67c017fa4dab2ec633fbd7bc9d8aa41ea63e2696971ed7e375f5 +aa98d600b22aff993a4d7a3ccabd314e1825b200cb598f6b797d7e4d6a76d89e34a4d156c06bddfc62f2ef9b4c809d1d +8a8fc960d6c51294b8205d1dabe430bef59bda69824fa5c3c3105bef22ac77c36d2d0f38ffc95ce63731de5544ccbeff +b6d1020efe01dc8032bd1b35e622325d7b9af9dcd5c9c87c48d7d6ebc58644454294c59b7f4b209204b5b1f899f473bf +8a750dc9fe4891f2dfe5759fb985939810e4cdc0b4e243ff324b6143f87676d8cb4bcb9dfb01b550801cedcaaa5349e2 +98c13142d3a9c5f8d452245c40c6dae4327dd958e0fda85255ea0f87e0bcbaa42a3a0bd50407ed2b23f9f6317a8a4bc5 +99f2b83d9ec4fc46085a6d2a70fd0345df10f4a724c1ba4dee082a1fde9e642e3091992ebf5f90a731abcb6ec11f6d9b +b218546ab2db565b2489ea4205b79daa19ef2acbf772ccaaa5e40150e67ea466090d07198444b48e7109939aa2319148 +84f9d1d868e4b55e535f1016558f1789df0daa0ead2d13153e02f715fe8049b1ce79f5bc1b0bbbb0b7e4dd3c04783f3f +80d870d212fbddfdda943e90d35a5a8aa0509a7a1e7f8909f2fcb09c51c3026be47cc7a22620a3063406872105b4f81a +b5b15138ff6551fac535d4bbce2ea6adc516b6b7734b4601c66ec029da2615e3119dc9ad6a937344acfd7b50e4a1a2ae +95d2f97652086e7ceb54e1d32692b1c867ffba23c4325740c7f10d369283d1b389e8afa0df967831ade55696931e7934 +8a5b580403e1a99cd208f707e8ce0d3f658c8280417683f69008d09cc74d835a85f7380f391b36ead9ac66d9eedd1cbe +a8b0c90bff34c86720637b5a2081f0f144cfe2205c1176cacd87d348609bc67af68aed72414dc9aa6f44a82c92c2a890 +865abbdd96c496892c165a8de0f9e73348bf24fce361d7a9048710178a3625881afb0006e9f5ee39124866b87904c904 +ace67bb994adef4b6f841cdf349195608030044562780a7e9b00b58a4ff117268a03ff01e5a3a9d9d7eff1dd01f5f4bf +b9371d59185b3d2d320d3fefeadb06ba2aa7d164352fb8dc37571509509fa214d736d244ac625a09a033a10d51611e2e +a8ef992771422dcf2d6d84386fde9fe5dba88bfded3dfcd14074ca04331b4fd53a7f316615cdfaf10ed932cbb424a153 +868cbc75f8f789ea45eded2768a1dac0763347e0d8e8028d316a21005f17be179d26d5965903e51b037f2f57fe41765d +b607111bcdfd05fa144aa0281b13ee736079ebbbf384d938a60e5e3579639ed8ef8eb9ca184868cdb220a8e130d4a952 +aca55702af5cae4cae65576769effd98858307a71b011841c563b97c2aa5aeb5c4f8645d254f631ed1582df3dbbf17da +b9b5cbace76246e80c20dfcc6f1e2c757a22ab53f7fd9ff8a1d309538b55174e55e557a13bf68f095ff6a4fa637ef21a +8571b0a96871f254e2397c9be495c76379faf347801cb946b94e63212d6a0da61c80e5d7bebbabcd6eaa7f1029172fe5 +902540326281e6dc9c20d9c4deaaf6fbbbcc3d1869bd0cf7f081c0525bea33df5cfa24ead61430fda47fb964fcc7994b +841af09279d3536a666fa072278950fabf27c59fc15f79bd52acb078675f8087f657929c97b4bc761cbade0ecb955541 +a1f958b147ddf80ab2c0746ba11685c4bae37eb25bfa0442e7e1078a00d5311d25499da30f6d168cb9302ea1f2e35091 +863d939381db37d5a5866964be3392a70be460f0353af799d6b3ed6307176972686bd378f8ad457435a4094d27e8dfb7 +835cd4d7f36eff553d17483eb6c041b14280beb82c7c69bca115929658455a1931212976c619bafb8179aed9940a8cc6 +8d0770e3cb8225e39c454a1fc76954118491b59d97193c72c174ecc7613051e5aed48a534016a8cf0795c524f771a010 +91aa4edb82f6f40db2b7bd4789cc08786f6996ebed3cb6f06248e4884bc949793f04a4c5ea6eefe77984b1cc2a45d699 +8fb494ca2449f659ff4838833507a55500a016be9293e76598bbae0a7cb5687e4693757c2b6d76e62bd6c7f19ed080bb +b59b104449a880a282c1dd6a3d8debb1d8814ef35aab5673c1e500ee4cb0e840fb23e05fa5a0af92509c26b97f098f90 +aca908e3bad65e854ae6be6c5db441a06bcd47f5abafdfa8f5a83c8cd3c6e08c33cab139c45887887a478338e19ceb9f +806f5d802040313a31964fc3eb0ee18ac91b348685bed93c13440984ee46f3d2da7194af18c63dea4196549129660a4e +ae4b2dca75c28d8f23b3ab760b19d839f39ff5a3112e33cb44cff22492604a63c382b88ec67be4b0266924dd438c3183 +99d1c29c6bd8bf384e79cd46e30b8f79f9cbc7d3bf980e9d6ffba048f0fc487cac45c364a8a44bb6027ad90721475482 +a16e861c1af76d35528c25bf804bfc41c4e1e91b2927d07d8e96bffe3a781b4934e9d131ecf173be9399800b8269efac +a253303234fb74f5829060cdcef1d98652441ab6db7344b1e470d195a95722675988048d840201c3b98e794b1e8b037c +905ac8a0ea9ce0eb373fb0f83dd4cbe20afb45b9d21ae307846fd4757d4d891b26a6711924e081e2b8151e14a496da18 +b485315791e775b9856cc5a820b10f1fa5028d5b92c2f0e003ba55134e1eddb3eb25f985f2611a2257acf3e7cfdfab5e +b6189c0458b9a043ebc500abc4d88083a3487b7ac47ed5e13ab2a41e0a1bee50d54a406063f92bc96959f19e822a89a7 +a30e15f995fd099a223fc6dc30dad4b8d40bee00caa2bc3223ba6d53cd717c4968a3e90c4618c711ed37cc4cd4c56cf3 +a1b1ed07fcc350bb12a09cd343768d208fc51a6b3486f0ece8f5a52f8a5810b4bc7ab75582ec0bc2770aed52f68eace5 +88aa739fbae4bece147ba51a863e45d5f7203dbc3138975dc5aef1c32656feb35f014d626e0d5b3d8b1a2bda6f547509 +ab570f3c8eabfca325b3a2ea775ef6b0c6e6138c39d53c2310329e8fb162869fde22b0e55688de9eb63d65c37598fca3 +89d274762c02158e27cb37052e296a78f2b643eb7f9ae409f8dac5c587d8b4d82be4ef7c79344a08ebec16ac4a895714 +99c411d2ad531e64f06e604d44c71c7c384424498ecd0a567d31ec380727fb605af76643d0d5513dd0a8d018076dd087 +80d0777fa9f79f4a0f0f937d6de277eec22b3507e2e398f44b16e11e40edf5feff55b3b07a69e95e7e3a1621add5ed58 +b2430a460783f44feb6e4e342106571ef81ad36e3ddd908ec719febeb7acaf4b833de34998f83a1dab8f0137a3744c11 +b8f38ccfc7279e1e30ad7cefc3ea146b0e2dff62430c50a5c72649a4f38f2bac2996124b03af2079d942b47b078cc4f8 +a178a450a62f30ec2832ac13bbc48789549c64fc9d607b766f6d7998558a0e2fad007ae0148fc5747189b713f654e6ba +98c5ede296f3016f6597f7ccc5f82c88fd38ed6dc3d6da3e4a916bfd7c4c95928722a1d02534fe89387c201d70aa6fd2 +a8cc5e98573705d396576e022b2ba2c3e7c7ece45cd8605cb534b511763682582299e91b4bb4100c967019d9f15bbfaf +848480ea7b7d9536e469da721236d932870b7bbee31ccf7ae31b4d98d91413f59b94a1e0d1786ee7342295aa3734969c +b88ea38f9ee432f49e09e4e013b19dff5a50b65453e17caf612155fff6622198f3cba43b2ea493a87e160935aaaf20a9 +949376934a61e0ef8894339c8913b5f3b228fa0ae5c532ad99b8d783b9e4451e4588541f223d87273c0e96c0020d5372 +96f90bb65ca6b476527d32c415814b9e09061648d34993f72f28fae7dc9c197e04ef979f804076d107bb218dfd9cb299 +a4402da95d9942c8f26617e02a7cef0ebc4b757fac72f222a7958e554c82cc216444de93f659e4a1d643b3e55a95d526 +81179cbc26a33f6d339b05ea3e1d6b9e1190bd44e94161ae36357b9cdf1e37d745d45c61735feed64371fe5384102366 +ad4dc22bdbd60e147fdac57d98166de37c727f090059cfc33e5ee6cf85e23c2643996b75cf1b37c63f3dc9d3c57ffa18 +8a9b1b93dc56e078ce3bb61c2b0088fd6c3e303ba6b943231cc79d4a8e8572f4109bbde5f5aa7333aae3287909cb0fe2 +8876ef583bc1513322457a4807d03381ba1f4d13e179260eaa3bddfede8df677b02b176c6c9f74c8e6eab0e5edee6de6 +b6c67e228bf190fbaeb2b7ec34d4717ce710829c3e4964f56ebb7e64dc85058c30be08030fa87cc94f1734c5206aef5f +a00cb53b804ee9e85ce12c0103f12450d977bc54a41195819973c8a06dcb3f46f2bf83c3102db62c92c57ab4dd1e9218 +a7675a64772eefddf8e94636fb7d1d28f277074327c02eea8fae88989de0c5f2dc1efed010f4992d57b5f59a0ab40d69 +8d42bb915e0bf6a62bcdf2d9330eca9b64f9ec36c21ae14bf1d9b0805e5e0228b8a5872be61be8133ad06f11cb77c363 +a5b134de0d76df71af3001f70e65c6d78bed571bc06bfddf40d0baad7ea2767608b1777b7ef4c836a8445949877eeb34 +aeadbc771eaa5de3a353229d33ed8c66e85efbd498e5be467709cb7ff70d3f1a7640002568b0940e3abd7b2da81d2821 +8c28da8e57a388007bd2620106f6226b011ee716a795c5d9f041c810edf9cf7345b2e2e7d06d8a6b6afa1ee01a5badc1 +8ed070626a4d39ffd952ddb177bc68fd35b325312e7c11694c99b691f92a8ea7734aeb96cf9cc73e05b3c1b1dcad6978 +ada83e18e4842f3d8871881d5dbc81aed88a1328298bfdc9e28275094bd88d71b02e7b8501c380fa8d93096cbc62f4fb +8befc3bec82dcf000a94603b4a35c1950ba5d00d4bed12661e4237afa75062aa5dcef8eac0b9803136c76d2dd424a689 +97c6f36c91ca5ca9230bfcbf109d813728b965a29b62e5f54c8e602d14a52ac38fa1270de8bfe1ab365426f3fc3654c7 +b01d192af3d8dbce2fe2fece231449e70eb9ac194ec98e758da11ca53294a0fa8c29b1d23a5d9064b938b259ea3b4fb5 +819a2c20646178f2f02865340db1c3c6ebc18f4e6559dd93aa604388796a34bd9fed28ad3ccc8afc57a5b60bb5c4e4ec +a9ffc877470afc169fecf9ec2dc33253b677371938b0c4ffa10f77bb80089afa2b4488437be90bb1bcf7586a6f4286e3 +b533051c7ce7107176bcb34ad49fdb41fac32d145854d2fe0a561c200dcf242da484156177e2c8f411c3fdf1559ecf83 +8fe2caff2e4241d353110a3618832f1443f7afe171fd14607009a4a0aa18509a4f1367b67913e1235ac19de15e732eb1 +84705c6370619403b9f498059f9869fdf5f188d9d9231a0cb67b1da2e8c906ead51b934286497293698bba269c48aa59 +899dddf312a37e3b10bdaaacc1789d71d710994b6ee2928ac982ad3fd8a4f6167672bc8bf3419412711c591afe801c28 +b2f7916d946b903ded57b9d57025386143410a41a139b183b70aeca09cf43f5089ead1450fce4e6eb4fba2c8f5c5bbe5 +8d5f742fe27a41623b5820914c5ca59f82246010fa974304204839880e5d0db8bc45ebab2ad19287f0de4ac6af25c09e +b93d4a1f6f73ac34da5ffbd2a4199cf1d51888bc930dc3e481b78806f454fcb700b4021af7525b108d49ebbbaa936309 +8606f8d9121512e0217a70249937e5c7f35fbfe019f02248b035fa3a87d607bc23ae66d0443e26a4324f1f8e57fd6a25 +b21312cdec9c2c30dd7e06e9d3151f3c1aceeb0c2f47cf9800cce41521b9d835cb501f98b410dc1d49a310fdda9bc250 +a56420b64286bdddda1e212bba268e9d1ba6bdb7132484bf7f0b9e38099b94a540884079b07c501c519b0813c184f6b4 +80b2cf0e010118cb2260f9c793cef136f8fa7b5e2711703735524e71d43bce2d296c093be41f2f59118cac71f1c5a2ff +adcb12d65163804d2f66b53f313f97152841c3625dbbda765e889b9937195c6fcd55d45cc48ebffabb56a5e5fe041611 +8b8a42e50dc6b08ab2f69fc0f6d45e1ea3f11ba0c1008ee48448d79d1897356599e84f7f9d8a100329ed384d6787cfc4 +aaa9c74afa2dec7eccfbd8bb0fc6f24ed04e74c9e2566c0755a00afdfdf3c4c7c59e2a037ec89c2f20af3fae1dd83b46 +aa9f6e8fd59187171c6083ae433627d702eb78084f59010ff07aff8f821f7022ef5fbbe23d76814d811b720a8bfa6cc3 +a56a3ded501659ad006d679af3287080b7ee8449e579406c2cae9706ef8bf19c1fc2eb2a6f9eaf2d3c7582cded73e477 +81971e077c1da25845840222b4191e65f6d242b264af4e86800f80072d97d2a27a6adc87c3a1cb1b0dd63d233fbafa81 +a6fa5453c4aaad2947969ee856616bf6448224f7c5bf578f440bcfc85a55beb40bef79df8096c4db59d1bd8ef33293ea +87c545adbfaaf71e0ab4bac9ae4e1419718f52b0060e8bb16b33db6d71b7248ae259d8dd4795b36a4bbb17f8fae9fd86 +b4c7a9bc0910e905713291d549cec5309e2d6c9b5ea96954489b1dff2e490a6c8b1fa1e392232575f0a424ba94202f61 +802350b761bcaba21b7afe82c8c6d36ee892b4524ab67e2161a91bbfa1d8e92e7e771efb1f22c14126218dd2cb583957 +b4e7ddb9143d4d78ea8ea54f1c908879877d3c96ee8b5e1cb738949dcfceb3012a464506d8ae97aa99ea1de2abf34e3d +a49a214065c512ad5b7cc45154657a206ef3979aa753b352f8b334411f096d28fd42bca17e57d4baaafb014ac798fc10 +8a80c70a06792678a97fe307520c0bf8ed3669f2617308752a2ab3c76fdf3726b014335a9b4c9cbcfc1df3b9e983c56f +a34721d9e2a0e4d08995a9d986dc9c266c766296d8d85e7b954651ad2ca07e55abb1b215898ee300da9b67114b036e0d +8cfce4564a526d7dca31e013e0531a9510b63845bbbd868d5783875ed45f92c1c369ce4a01d9d541f55f83c2c0a94f03 +ab3f5f03a5afc727778eb3edf70e4249061810eba06dc3b96b718e194c89429c5bfbec4b06f8bce8a2118a2fdce67b59 +aa80c2529fc19d428342c894d4a30cb876169b1a2df81a723ab313a071cba28321de3511a4de7846207e916b395abcc9 +82b7828249bf535ef24547d6618164b3f72691c17ca1268a5ee9052dba0db2fdd9987c8e083307a54399eab11b0f76b1 +8fbcb56b687adad8655a6cf43364a18a434bf635e60512fad2c435cf046f914228fb314f7d8d24d7e5e774fb5ffb1735 +a3010a61a2642f5ebbce7b4bc5d6ecb3df98722a49eb1655fe43c1d4b08f11dfad4bcec3e3f162d4cc7af6a504f4d47c +b3dcc0fdf531478e7c9ef53190aa5607fd053a7d2af6c24a15d74c279dbb47e3c803a1c6517d7e45d6534bb59e3527f5 +8648f6316c898baaca534dff577c38e046b8dfa8f5a14ee7c7bc95d93ae42aa7794ba0f95688a13b554eeb58aeedf9ba +89fca6fc50407695e9315483b24f8b4e75936edf1475bcf609eed1c4370819abac0e6a7c3c44f669560367d805d9ba63 +a367a17db374f34cd50f66fb31ba5b7de9dbe040f23db2dcc1d6811c0e863606f6c51850af203956f3399000f284d05f +91030f9ca0fff3e2dbd5947dcf2eba95eb3dbca92ee2df0ed83a1f73dbf274611af7daf1bb0c5c2ee46893ab87013771 +84d56181f304ce94015ea575afeef1f84ea0c5dbb5d29fb41f25c7f26077b1a495aff74bd713b83bce48c62d7c36e42d +8fe2f84f178739c3e2a2f7dcac5351c52cbed5fa30255c29b9ae603ffd0c1a181da7fb5da40a4a39eec6ce971c328fcf +a6f9b77b2fdf0b9ee98cb6ff61073260b134eb7a428e14154b3aa34f57628e8980c03664c20f65becfe50d2bdd2751d4 +8c6760865445b9327c34d2a1247583694fbeb876055a6a0a9e5cb460e35d0b2c419e7b14768f1cc388a6468c94fd0a0f +af0350672488a96fe0089d633311ac308978a2b891b6dbb40a73882f1bda7381a1a24a03e115ead2937bf9dcd80572ad +a8e528ec2ee78389dd31d8280e07c3fdd84d49556a0969d9d5c134d9a55cd79e1d65463367b9512389f125ed956bc36a +942c66589b24f93e81fe3a3be3db0cd4d15a93fb75260b1f7419f58d66afaa57c8d2d8e6571536790e2b415eec348fd9 +83fe4184b4b277d8bf65fb747b3c944170824b5832751057e43465526560f60da6e5bbee2f183cb20b896a20197168c7 +88a71aada494e22c48db673d9e203eef7a4e551d25063b126017066c7c241ee82bedaa35741de4bd78a3dd8e21a8af44 +8c642a3186ca264aac16ee5e27bd8da7e40e9c67ae159b5d32daa87b7de394bf2d7e80e7efb1a5506c53bfd6edd8c2c3 +81855d6de9a59cef51bef12c72f07f1e0e8fe324fcc7ec3f850a532e96dcd434c247130610aaee413956f56b31cbb0dc +a01e61390dcd56a58ad2fcdb3275704ddfbedef3ba8b7c5fce4814a6cdd03d19d985dba6fd3383d4db089444ea9b9b4d +96494e89cbf3f9b69488a875434302000c2c49b5d07e5ff048a5b4a8147c98291ae222529b61bb66f1903b2e988e5425 +b9689b3e8dddc6ec9d5c42ba9877f02c1779b2c912bba5183778dc2f022b49aed21c61c8ec7e3c02d74fe3f020a15986 +a2a85e213b80b0511395da318cbb9935c87b82c305f717a264155a28a2ea204e9e726bae04ce6f012e331bd6730cbb9d +91b70f44c7d8c5980ce77e9033a34b05781cbe773854d3f49d2905cc711a3d87c20d5d496801ad6fd82438874ce732b8 +884596417ff741bb4d11925d73852ffeea7161c7f232be3bdce9e6bbe7884c3a784f8f1807356ae49d336b7b53a2b495 +ae2aed8ab6951d8d768789f5bc5d638838d290d33ccc152edfb123e88ba04c6272b44294b0c460880451ad7b3868cc6a +89d8ebfb9beebc77189d27de31c55f823da87798a50bca21622cbf871e5d9f1d3182cf32ee9b90f157e6ce298e9efccf +afd00a4db4c2ed93cf047378c9402914b6b3255779f3bb47ded4ab206acb7eaebba0fd7762928e681b1aebcfee994adc +a2e49b6cd32e95d141ebc29f8c0b398bb5e1a04945f09e7e30a4062142111cd7aa712ac0e3e6394cfb73dd854f41ad77 +ae8e714ab6e01812a4de5828d84060f626358bb2b955f6fb99ae887b0d5ce4f67ebc079ab9e27d189bf1d3f24f7c2014 +a3100c1eebf46d604e75ebf78569c25acf938d112b29ccbe1a91582f6bd8ef5548ae3961c808d3fb73936ac244e28dbc +a9a02dcff0e93d47ead9cdddc4759971c2d848580bf50e117eb100cafca6afeaa7b87208513d5f96b1e1440ffc1b0212 +894ab01462137e1b0db7b84920a3b677fbb46c52b6f4c15320ef64f985e0fc05cec84cd48f389ce039779d5376966ea3 +b1e40e8399ee793e5f501c9c43bde23538e3ce473c20a9f914f4a64f5b565748d13ab2406efe40a048965ee4476113e4 +a5a7d97a19e636238968670a916d007bf2ce6ae8e352345d274101d0bbe3ac9b898f5b85814a7e4c433dd22ac2e000ff +b6394c43b82923231d93fd0aa8124b757163ba62df369898b9481f0118cb85375d0caac979a198ece432dbb4eb7cc357 +82d522ae3ff4fe2c607b34b42af6f39c0cf96fcfe1f5b1812fca21c8d20cece78376da86dcbd6cdb140e23c93ae0bcb2 +b6e0d986383bc4955508d35af92f2993e7e89db745f4525948c5274cfd500880cb5a9d58a5b13d96f6368bb266a4433e +b0b4325772ec156571d740c404e1add233fb693579f653b0fae0042b03157d3b904838f05c321d2d30f2dbd27c4d08ad +ac41367250263a2099006ef80c30bac1d2f25731d4874be623b6e315c45b0dc9a65f530fce82fb3dc25bd0610008c760 +b6c0b1ed7df53da04a6f3e796d3bfa186f9551c523bc67898bc0ecfc6b4a4a22f8c4d3bfc740ebf7b9fa5b0ea9431808 +8e78fca17346601219d01e5cd6a4837161a7c8f86fe2a8d93574d8006da5f06ae7c48eea7d2b70992c2a69184619663c +a21f91f47e04fafbfafacf3185b6863766a2d0c324ccac2c3853a4748af5897dbbe31d91473b480f646121339c9bae2d +a464d68786ab1fc64bd8734fce0be6fbe8dc021d3e771ff492ada76eedff466577c25e282b7c8ab4c1fd95ef5ff3631e +829a24badc7714081e03509ccfb00818ce40430682c1c0e4a399cd10b690bda1f921aabcbf1edfb1d8a2e98e6c0cedd6 +87ccf7e4bbcb818ef525435e7a7f039ecbb9c6670b0af163173da38cbdb07f18bc0b40b7e0c771a74e5a4bc8f12dfe2c +94087bd2af9dbeb449eb7f014cfbf3ee4348c0f47cde7dc0ad401a3c18481a8a33b89322227dee0822244965ae5a2abb +896b83ed78724dac8a3d5a75a99de8e056a083690152c303326aa833618b93ef9ec19ab8c6ef0efe9da2dbcccac54431 +821e6a0d7ccf3c7bd6a6cc67cde6c5b92fb96542cb6b4e65a44bbc90bbc40c51ff9e04702cb69dd2452f39a2ff562898 +b35b2096cda729090663a49cb09656c019fef1fc69a88496028d3a258ad2b3fd6d91ab832163eaa0077989f647e85e7e +b7857ef62c56d8bce62476cdb2ab965eddff24d932e20fc992bd820598686defe6cc0a7232d2be342696c2990d80721a +b343d974dfda3f6589043acd25d53aecf7c34b1e980ae135a55cda554ff55e531bc7c2dfe89b0d2c30e523c7b065dad1 +8d139e16a73cd892b75f3f4e445a10d55d1118f8eeafc75b259d098338419e72e950df6ca49cb45677a3c4e16fb19cdc +817b8535bd759da392b2c5760c51b3952ecf663662a137c997f595c533cd561ed7e655673c11144242160e41d1f2dd71 +817ee0f0819b0ccb794df17982d5b4332abff5fec5e23b69579db2767855642156d9b9acccf6ceab43332ccc8d2744dc +9835d2b652aec9b0eba0c8e3b6169567e257a6a3f274ec705dbc250ee63f0f8e4b342e47b9e0c280c778208483d47af8 +b78c40177f54f0e6d03083a4f50d8e56b5aafdb90f1b047bb504777d6e27be5a58170330aee12fbaa5f1e9d4f944acfc +ab8eebacf3806fac7ab951f6a9f3695545e2e3b839ca399a4ef360a73e77f089bb53d3d31dbd84ddfde55e5f013626e0 +96c411fc6aecca39d07d2aff44d94b40814d8cfc4ee5a192fd23b54589b2801694d820a0dd217e44863ccff31dda891b +8249c424a0caf87d4f7ff255950bbc64064d4d1b093324bfe99583e8457c1f50e6996e3517bf281aa9b252c2a7c5a83a +acf6ed86121821a3dd63f3875b185c5ebe024bdb37878c8a8d558943d36db0616545a60db90789c0925295f45d021225 +a37f155621a789f774dd13e57016b8e91b3a2512b5c75377ec8871b22a66db99655d101f57acaecd93115297caabfc21 +92e60ee245bd4d349f1c656e034b1a7f0c6415a39ac4c54d383112734305488b3b90b0145024255735e0a32f38dba656 +acec614e562ccfc93366309cfdc78c7d7ee0a23e3a7782a4fc4807b8803e6ebfb894a489d03e9a3c817ff2ec14813eba +b912f9dd26ed552cb14b007b893e6ed2494d12517e5761dbeb88521270144f8c3eb9571a0ad444b30a8a65e80bd95996 +8375408dae79c547a29e9a9e5d4ec8241b36b82e45e4ca3b0c36d2227c02d17bb171528d3778eac3bbdc75d6c4e8a367 +8c2d0e6e4406836da112edbbb63996408bb3cda4a2712fd245e4bb29a0100fdc89a2746d859b84a94565bc1cfa681813 +a7431bf59e111c072d28c97626cd54fcdf018421d053a787d2aef454b91251ee8ff9d3702d06b088f92b9ad2bbebff15 +8f3659b0fbeb90b7f30b7a49233325e806551a32911a654dca86e290b314483bbb33fe6482387bc48c35d85c1dd0441c +8dca5ba23f0bb76f7dacabf12886053552ba829a72827b472a2f01e19a893155cdce65f1fb670000f43e8c75ba015a31 +8c1514c083c77624eeb5d995d60994a2866192e15c4474d0be4189fae0e9dbd62494ebb4c02fbc176b53be548abbc5a1 +80498d2ed153381baf3b0f81da839ed0eea6af5796c422b8e59be805dba48c4395bb97824ac308170bb4f14f319c5ddf +84f5ebc3bf96362457993e9fa31493c31c4283075e2403f63d581b6b0db8a3df294b2085643f2007f4de38cb5d627776 +958e6e38774da518193a98397978dbc73d1c3827b4996ec00b4183da2c305a187a0ada9aa306242814b229a395be83c9 +ab8b8fbf73845615e7fab3e09e96cc181159eab09f36b4c1239b3c03313c9aeb4bbb51e16316fe338b2319ed2571b810 +977e4e33b33bd53394e591eba4f9a183e13704c61e467d74b28f4ad0b69aa51501a5221cb1e0e42bcb548ca518caa619 +a9bb7ecb9846cc30d04aad56d253c3df7004cebb272f6adf7b40a84adef9f57291e0d08d64c961b9fc406cdb198aab9b +8d2b72dc36406a545a9da44e1fddfb953d4894710ca026d6421a4ac91e02d0373a599f2acfe41d8258bc9679cf6f43d3 +904192fc8fe250f61ecb8a36abbbccae85f592bbf00c10039c30b5a1c733d752a04e4fd8a1000c6578616f8a16aa83a3 +87f5fdfe20bbbf931b529ec9be77bbfcc398cad9d932d29f62c846e08a91d2f47ae56ad5345122d62a56f629f9a76c4d +84cc3a53b2e7b7e03015f796b6cb7c32d6ded95c5b49c233ac27fafa792994b43c93cda6e618b66fce381f3db69838ba +aab58da10d7bbe091788988d43d66a335644f3d0897bbc98df27dcc0c0fcee0ac72e24f1abdd77e25196a1d0d0728e98 +a10ea8677c2b7da563d84aa91a314a54cab27bb417c257826ebdd3b045d2a0f12729fe630bbbf785d04874f99f26bee8 +acc4970ef2a4435937a9b8a5a5a311226ca188d8f26af1adfcd6efb2376a59155b9a9ff1cff591bde4b684887d5da6e5 +8dc7cf6fcca483c44eb55e7fb924bf3f76cf79b411ae4b01c6c968910877ac9c166b71350f4d935f19bdffb056477961 +ac2dd1182ded2054c2f4dbf27b71a0b517fb57193733a4e4e56aca8a069cff5078ffd3fd033683d076c1c639a4de63c7 +932ec87c450cd0dc678daf8c63cd1bf46124fa472934e517fbbfb78199f288ff7f354b36e0cc6c8739d3f496cfe0913b +b0d631ced213e8492be60ea334dbe3b7799b86d85d5e8e70d02beef3ae87b1d76e1df3bdb5f7ba8a41904c96f6a64455 +929d7239ead7575867e26b536b8badf2e11ca37840034d0e5c77039f8cce122eff5a1bf6e0bcadde6b3858e9f483d475 +aaae5d372d02ee25b14de585af6fbc48f2c7cd2a6af4f08352951b45aa469599eff41e820df642ca1a0f881120e89dbe +b23c411741a6b059f04fa4f5fd9dd10e2a64915f2de6ea31e39c32f2f347a776a953320e5f7613fcb1167efe502f5c5c +a4581b0ae633fe29c6f09928e5efb16db019eeac57f79fef2fa1d3c9bee42ce0e852bc60b9d0133265373747e52a67a4 +81b33afffd7b2575d4a9a1c5dd6eee675c084f82e06b9b3a52a3c9f76e087f12dca6e0ffddc42fb81ce1adb559d47a38 +89cc890f06b424591556aabdfdbb36d7a23700425e90c9cfed7d3da226b4debe414ac5bdf175273828ce6c5355712514 +a4399438be75cfae2bf825496704da5ed9001bed8538d8ac346c8cf0d4407808e9ee67573eb95fe1c6872ac21f639aaa +ad537f7ce74a1ca9a46fc06f15c1c8a6c32363bd6ac78a3c579ed8f84252e38a914cac16709fe65360e822ef47896de4 +8e53b69f5e3e86b86299452e20ea8068b49565d0d0ab5d50ce00158a18403ae44e1b078a3cfd3f919aa81eb049a30c6e +a59f2542c67a430fd3526215c60c02353ee18af2ff87cb6231a2564fe59b8efec421f18d8b8cc7f084675ecf57b3fd05 +b8d9bac93ef56cb4026dd1c731d92260a608fd55b8321e39166678e1dab834d0efddb717685da87786caeb1aaf258089 +aa2df56f4c6fe9e0f899116c37302675f796a1608338700f05a13e779eb7cf278e01947864a8c2c74cc9d9a763804446 +b0108ff2e327dcb6982961232bf7a9a0356d4297902f4b38d380ff1b954bfbcae0093df0f133dd9e84d5966c7b1aada7 +b06b813b01fe7f8cf05b79dc95006f0c01d73101583d456278d71cd78638df2b1115897072b20947943fa263ddab0cd6 +aa41e6c4d50da8abf0ea3c3901412fe9c9dff885383e2c0c0c50ed2f770ada888a27ea08bbb5342b5ff402e7b1230f12 +a48635dbb7debac10cb93d422c2910e5358ba0c584b73f9845028af4a763fd20da8f928b54b27782b27ca47e631ebf38 +80a574c208e994799e4fa9ef895163f33153bc6487491d817c4049e376054c641c4717bda8efbeb09152fa421a7268a7 +b592bfd78ae228afc219c186589b9b0b5c571e314976d1ed5c1642db9159d577679a73c049cfc3dcfefcd5a4f174eeea +aa1f08af3918c61eadf567a5b1a3cdcdfb1b925f23f1f9e3c47889762f4d979d64686ce1ce990055ef8c1030d98daa3b +857df4cfd56d41c6d0c7fcc1c657e83c888253bae58d33b86e0803a37461be5a57140a77fb4b61108d1d8565091ada1c +8fae66a72361df509d253012a94160d84d0b2260822c788927d32fd3c89500500908c8f850ef70df68ddaeb077fd0820 +aa1dbefc9aef1e7b896ff7303837053c63cfb5c8a3d8204680d3228ac16c23636748fe59286468c99699ae668e769a0c +b64b1cb2ba28665ed10bad1dddc42f3f97383c39bad463c6615b527302e2aaf93eb6062946d2150bd41c329697d101be +b6d35e3b524186e9065cee73ea17c082feff1811b5ab5519dd7991cdff2f397e3a79655969755309bd08c7d5a66f5d78 +a4dae7f584270743bbba8bb633bdb8bc4dcc43580e53d3e9e509ff6c327e384f14104b5bdfe5c662dc6568806950da37 +aae84d3d9ad4e237b07c199813a42ed2af3bf641339c342d9abf7ebec29b5bd06249c4488ce5c9277d87f7b71b3ddd37 +b82a463cf643821618a058bddf9f2acb34ac86a8de42a0fa18c9626e51c20351d27a9575398a31227e21e291b0da183e +8b6c921e8707aded3ea693f490322971b1a7f64786ef071bc9826c73a06bd8ae6bf21bc980425769627b529d30b253ce +80724937b27fc50f033c11c50835c632369f0905f413b1713a2b0a2274bec5d7a30438e94193d479ba6679dbe09a65ef +a1d9b259a2ca9cff8af6678b3af0a290c2f51e9cf26d5fe3c6a4fa3d28cbf33cb709b7f78b4f61cb9419427983c61925 +96a3e69a5ed7a98ce59c4481f2ffb75be9542122ad0eb4952c84d4536760df217854d4ec561ce2f4a79d3793c22fa4f4 +990c4d9a4a22d63a8976d34833cafc35936b165f04aed3504e9b435f0de1be4c83b097bbaa062483cf3dee3833b4f5b6 +b9bf5e4b270aec4a0dc219457b5fed984b548892c4b700482525ba1a7df19284464f841dab94abfabcaa9a7b7a757484 +acaecf49cb4786d17cf867d7a93bd4ffee0781766e11b5c1b29089ae0024c859d11b45828fbff5330b888543264d74a9 +b0e1a0865b1e6f9e4a0e31d0c885526ac06678acc526fda5124742a2c303bd0e8871a0cb7951ec8ed9540fc247c8d844 +82b3d327b3d1a631758451e12870816956cd0cef91fcf313a90dd533d5291193a0ff3cc447054564ce68c9b027a7ffd7 +a2843602abb98f0f83e000f3415039788da1e9a096bfe8fed6b99bab96df948c814560424ffebe755cb72f40436fb590 +ab1c7b43cf838798d1e314bc26e04fc021e99a7bfbfc8ffde62fa8d7f92139de86a377289d5177021154229de01ede15 +95e5cf5dd87ae3aed41b03c6c55f9dfad38dc126b17e7e587c156f7745c8da0bd1d60acb718fc1a03b61344f01e3de4d +86f021a3762bb47167f80d4ef1b1c873a91fe83409f9704f192efeebbc3ece0729cd2f92f63419907ea38ae47bc907d2 +aaa1445dafbbcd645d4332d9806225e9346ee5ac6b22ad45e8922134fe12f3d433f567a6a4c19efdd9d5775a7de1e92f +8fd7e15688eef75df7b8bca3d61bc9fca4f56e047cdb6d0b864e7d1c4966eac27d6094b0c8482b49739f83ec51050198 +80aab8b4d394eb011d4ec6a4c2815617308c9b847c6fa6a3d7e6af1c79420ef6ff2a13934a398581c40ee4cf1cac02ac +8970b97ac076a1d8a321ce00eada0edf974a46bf3cc26f6854e4218cdfc8d2b0c32199d9658f254b4fbae5a2c5535f41 +a1aa2ec5b03df0a630e73dd048680ed6d3032c324941423f45cd1f16038789e5e75b876a13948732e9079a422f66a9fc +b5fe5f5e2f2ae2beeb8e95859a02fc45f01f9fb0ebb2bd8ec9ec976b3e806228821a9775096d341d662bc536c4d89452 +a2bc1f170b62d0d5788b02391337b2ab157c38e725694e80aeead7383e05599be0e2f0fa27ef05db007061809356e147 +a8a69701d4a8d0d972390e9f831fd8e9f424b2c2ef069e56bd763e9e835b3ce5f7cf5de5e5c297c06ace4aa74df1067c +b43d551af4ff3873557efe3f3fb98e5ede9008492f181f4796dd1a6bcda8b9445c155e8146966baa812afae1abe06b48 +b4b1dae44fd596813f30602ab20e9b1fb20cb1bd650daacc97b7e054e5c0178b8131d439a9e5b142ca483cc012a362b3 +b95b8a94c30a831eaaebea98c65cc5d0228c78afd6603d4aa426d8186aecc951f1a11c33951f51df04c7e6fa43ffb5ae +b100059624cf9db371bec80013a57a8f296d006c139a8766308f1ea821c7eccc26cad65bc640ab3f6cef9062653bf17d +8e5a2cb76716e0000d13bce5ef87acac307362a6096f090f5f64e5c5c71a10fddfdee8435e7166ba8c3ad8c3f540f3e4 +93d2c43e21588c1e83c4255c52604b4ac3f40e656352d1827e95dd5222a45aebff9674e34fbbe7ed21eca77bd9b8dcbc +8aeaed611546bb9073b07512a9a1f38a7f436ab45e11775a0f9754baaf63e9bcc7bb59b47546a5ded5e4ba2f698e3b5f +af9e6792e74a1163fe27612f999a2f3cfa9048914c5bef69e3b2a75162bb0ce6ece81af699ad7f0c5278a8df0ba000d2 +850bf2d5d34791c371a36404036ad6fdcd8fb62d1bb17a57e88bda7a78ea322397ce24d1abf4d0c89b9cf0b4cc42feb3 +87f7e2a1625e2b7861b11d593aaac933ed08a7c768aebd00a45d893ed295bbb6ed865037b152bb574d70be006ddc1791 +8dcce8f4ad163b29a2348ea15431c2c6ea1189ece88d2790e9f46b9125bd790b22503ec391bc2dee8f35419863b2c50c +b4bf5266c37f12421dd684b29517982d5e4b65dfdfba5fc7bd7479fd854aabf250627498f1e1188a51c0a88d848ec951 +8651623c690247f747af8fdffdc3e5f73d0662bc3279fa2423a3c654af9b6433b9e5e0155f1ce53857e67388e7e3401d +b155120f196d52760129dde2e2b1990039b99484cdc948fa98095cd23da87679850f522e5955eae34ac267d2144160d3 +aec8115e8d7b6601fbceeccf92e35845a06706d46acd188452c9f7d49abef14c6b3a9a9369a8bab2fd4eb9288e2aaca5 +998a8ca4dc0f145f67a8c456f1d6a7323c4836fe036dcbb0f27eb1c596d121eb97369638a9908cfaf218c7706f266245 +b235fbafac62802742ee3d26b1f4e887f7d2da4d711ba7f9bb6ca024de7beec1de66bb830ce96d69538f7dcb93c51b26 +9258d2ddc21ab4e3edcde7eb7f6a382a29f1b626003cc6fdd8858be90f4ad13240072d8a8d44ef8de51ca4f477fa6c45 +99d038487821c948142c678acd8c792960993dd8cb5e02cb229153a1ee9f88249f4ad9007f08e5d82e2a71fb96bb5f32 +a88ee9dbc73d3d8e0f447b76fdb3a27936bde479a58d5799176885583dc93830ac58bca9087075950ea75100cf51af23 +88b9b15816e5a0387153c1f4b90f613beb3ea4596037da01a81fdd2bcbd0baf5598db99f77e7694e5a0d35e822758108 +907ae4b637d06b15846ee27d08c9c9af42df261c5bdd10cf5bc71f8e5ca34b33ac2405307023c50bdb8dc7b98a2cd5fe +9393d6900e1d2d1a1e42412fefd99578d9ac1d855c90a3e7930a739085496448609d674ca9b34016ad91f22d1cac538e +a28ac56b216730b7dcdb5ab3fc22d424c21a677db99a9897a89ed253ea83acfd9d83125133f5be6d9cd92298df110af8 +b027590ee8766f1e352f831fda732adbaf77152485223ad5489ef3b0ce2d2e9f98d547c111fe133847ebb738987fb928 +a9cc08fbd5c3fee8f77cf6eb996a5cafa195df5134dab000e4d0312f970a5577942ee89794e618074f49841f1f933a42 +a8b3535c3df0b1a409d3fc740527ee7dd5ac21756115cde6f87f98cc7623f50cfcf16790689cab113ee7c35a5bd4879f +b61420227b97e5603ae8a716c6759b619f02b8fdc48acbf854352aa6519dad74b97bacc1723ca564cbf3ca48539ed773 +853762498de80eebf955a6c8ddd259af463e4e25f0b6ba7b6a27b19bdbf4c585de55760a16e2d9345cdba6b2a02610f3 +a711c1b13fc6c30745203c5d06390e6c82bd7c50f61734aa8d99c626faba30119bc910be63ec916c91ba53f8483c05a8 +b488c0a793f4481f46b5875d96eecd73e46209a91677769f0890c5e002ecd7d4b1c9f4ba68c47fbed40e3857b1d8717a +a651c5e812ae65b1c66d92c607e80be330737ea49c1dcfe019c0ecea0f41a320406935bb09206a4abff0d1c24599b9ad +85e34e7d96e4b97db98a43247b6c244383b11ca10bf4777364acf509a6faa618bc973e2136a4693fbc8ab597e308fd5a +99837214102b394fffa7f3883759554c6bb7a070f5c809303595a44195e02b9a169460dc6bbffb62bdc0e7ced5f0a5c1 +a952f89c0afb4bdae8c62b89cc3cfb60d0576ba4fe01a5d99534792f38d8848d919b3fc7577435d8443a044d2ee0bcfa +a1ac1f81acb29798acdfc493854663519e2d1b0e9d23d286ce33882c34b4c1c0bb43dd9638166d8026315a44d9ec92a8 +ac9c58aa38219ae659d23007cc7b97fd25b7b610b2d81a8f9f94ddb089efc49c049a8ea4c56e6eaf7b6498f422a97b3c +87e61d501c242b484fb9a937ef21d485f6678d75257fc8fe831b528979068cadbe7e12b49c34058ec96d70a9d179ab14 +aa45f6852f35cc8b65a4a8b5380641d2602a4fa4e3a035db9664df3ac2e170b1280c4a8b7b55161430063e54de4158a6 +a46975614ddde6d134753c8d82c381966f87203d6e5a5fb99a93b0d43aa461466b37f07b8d0973a1abd6ee2b40f24348 +8d35f97297773422351f4d99564c1359ef1a10cfb60aa0e6c8985a78f39b4268486312c8ebf9dd2ef50a771aa03158eb +8497c6242102d21e8b3ade9a9896c96308ab39171ab74cbd94e304c47598e2c2a7b0a0822492ac5c076ba91d4176481d +973f8fcb5f26915b3a3ef6fe58cc44bc7f4e115cd0ad9727d8d1b8113e126ae2e253a19922c5433be4ab2311a839c214 +ae3ee9f1d765a9baf54b4617a289c3b24930aa8d57658a6b0b113bbf9b000c4a78499296c6f428bbb64755dfd4f795d2 +a5be7a8e522ef3dcf9d2951220faf22bb865d050f4af2880b8483222ff7aad7c0866219fcc573df9d829c6efbb517f98 +a5f3c7fabd7853a57695c5ad6d5b99167d08b5414e35ed1068ae386e0cb1ee2afbbe4d2b9024379b6fc3b10c39024d36 +978d5592d4798c9e6baceff095413589461267d6a5b56cd558ec85011342da16f4365d879b905168256f61d36d891b1f +b7b6eaffa095ecbd76d6e1e88ceebabaf674d9ef7e331e875c6d9b9faa1762c800ff1ea597c214c28080f67a50a96c1e +8a1ab53ae5ceaa42e06e58dd8faf6c215fc09ba111ca9eeb800612334d30d5971448be90fec62ed194328aadd8c8eecc +a9ca532cac8ace9a9e845382f8a7840bf40cb426f2fcad8a2f40aadbb400b3a74021627cc9351b0966b841b30284962e +8dddeda8854c8e7ddc52676dd1d0fed1da610ed5415ddd7d25b835bd8420a6f83d7b67ec682270c9648b2e2186343591 +888906aac64fd41d5c518a832d4e044fdc430cfe142fd431caf4676cafc58853ce576f098910d729011be0a9d50d67b5 +96a3f886a2824e750b1e2ea5c587132f52a0c5e3ff192260d8783c666206bd8ebd539933816d7cdd97e4bc374e0b1edf +a150a29ffb2632cc7ec560983d9804cd6da3596c0c25956d27eb04776508eae809659fc883834269437871735de5f9ed +81f7ad4d2959d9d4009d1dfbc6fee38f930f163eb5eac11e98dc38bd2f7f224e3f5c767583f8e52d58d34f3417a6cf90 +97ccac905ea7d9c6349132dd0397b6a2de9e57fd2d70f55e50860e019de15c20171a50b28a5c00ef90d43b838253b3d1 +95694f00c21e8a205d6cbda09956b5b6ec9242ec8c799a91f515b07dcc7de3b6f573e2c0ba149f5a83700cda2d1df0f5 +82bbc3c4a3b3997584903db30fffd182a266c7d1df3e913f908d5a53122fa12cf5acd11d915d85d5bd110fcc43cee736 +8d3f24b4949aa1b4162c28dfbb9f813dd1d8b330f71325448dc45ea34d59b69ca95059402aae011e1b5aba6e536bc6ec +92c734c19752d24782331e74c9af97a8399ddfdd32954e91cda7363dba876aca4f730b451c50a8913950420682da8121 +8653d2c79f77b8c7dcdf7e8dee42433998aeedf1b583abfca686d47a854de1b75e9a4351580c96d1a2a9532659203361 +886f0e414cb558c1a534a1916d3531320a9b6024639712ffe18164ce6313993a553e2b9aafe9c0716318f81a5d0bb1da +b31b5efaba5a5020c3bcea0f54860e0688c2c3f27b9b0e44b45d745158f484e474d5d3b1a0044dd6753c7fb4bf8ace34 +b2d615bbdfdc042d6f67a6170127392d99f0e77ae17b0e1be6786ff2f281795f1bf11f83f2e0f8723b5cdd1db1856e09 +a6e014cca531e6ac2922239b5bee39d69d9ba6d0fa96a4b812217dd342657d35606f0b9c5a317efd423cdb1047815e3d +a8921736b69c9fbb29f443715174bac753e908251804620c542fad6cfbfda7bdfe287f2902f30b043a8a4b4818cfdeef +8d73a9949a042ec2dcefa476e454cd9877eee543b1a6b3b96a78ffcff87421e8b26dd54d5b3192ac32073cb36497acc3 +b936a71ee8df0e48867f3790adf55dc8efc6585024128de2495f8873bd00fd9fa0984472125e801ed9c3cdce6698f160 +82f69c06209c28f64874e850601dda56af44ffc864f42efa8f9c6a0758207bf0a00f583840982dec0a517ab899a98e5b +b7a0a14411101473406f30e82f14b13e6efc9699e7193c0be04bb43d1b49e8c54812ce0f9b39131a20379c4c39d3bbe3 +81159c969f38107af3b858d7582b22925a7ccced02fae3698482d7e9cdc6c568e959651991c6cf16c53a997442054b61 +8bf1116a206e0ce9199fcab6ed2b44a9e46e8143bff3ed3f1431f8d55508fe2728b8902670cfd8d9b316f575f288ed9d +a279b2149824b64144eb92f5a36b22036d34a52bd5a66e5da4b61fbc95af6eda8e485c7914f448abd8674fc14d268d9d +8b98279b5f3588d1a2f8589d2756458690a502728800f8d94b28e00df842a101c96ab9c5aee87c5bbe65552c0c383b80 +b4a27a351ec54420f94e0a0a79d7c7a7337940399646631baca93eeab5fd429d7fb39428be77dcbce64a13eaa3c8ca1d +90c08baa29ec8338ffce381eae3d23ce3f6ba54e5242dec21dc3caaed69cac13f2ab5e8d9d719bc95720fa182eee399c +85156d65bb4fef69ffd539ab918b3286105ca6f1c36a74351ab3310b339727483433e8f8784791f47b4ba35ca933c379 +923005013c27209d07c06a6b92b0cbb248a69c5e15c600bbcc643e8dcd2402adebd94dd4cafb44ec422a127e9780aaec +863b23eb5463a6ef5a12039edc2f8e18e3c97b244841bc50af02459b1bcc558367edf2f6e4fe69f45f37887469dd536d +87a4a7708a112724ff9b69ebb25d623b5cae362ae0946daed2ec80e917800dbfcd69f999c253542533242e7b9a5cc959 +8bf4347ceea7f94b53564f26b1a4749a16f13bf71a9e03a546f906f7c423089820ff217066159b0637d9d6824e9c101c +ab07eef925d264145971628a39e4dd93ff849767f68ed06065802cf22756fc6bf384cf6d9ab174bfc1a87bcc37b037aa +8e3f10a42fad43887d522dc76b1480063267991c2457c39f1e790e0c16c03e38a4c8e79a0b7622892464957bf517ebd8 +a8722fc7b1acf0be18f6ddf3ee97a5a9b02a98da5bc1126a8b7bf10d18ee415be9a85668eb604ef5a1f48659bc447eb5 +878d6b2a9c0aca8e2bc2a5eb7dd8d842aa839bbd7754860c396a641d5794eab88a55f8448de7dbddf9e201cbc54fe481 +ada881c167d39d368c1e9b283cf50491c6bfc66072815608ba23ab468cfbd31ca1bd7f140e158e0d9e4d7ebfa670bc2d +a2b48578fa899d77a7ee1b9cb1e228b40c20b303b3d403fd6612649c81e7db5a7313ba9702adc89627b5fd7439f8b754 +8e051280e10551558dcb5522120ac9216281c29071c0371aaa9bde52961fe26b21d78de3f98cb8cd63e65cff86d1b25c +a7c5022047930c958e499e8051056c5244ae03beb60d4ba9fe666ab77a913a067324dfb6debcb4da4694645145716c9d +95cff6ec03e38c5ab0f6f8dccde252d91856093d8429b7494efc7772996e7985d2d6965307c7fdfa484559c129cca9f9 +993eb550d5e8661791f63e2fa259ab1f78a0e3edad467eb419b076a70923fede2e00ddc48a961d20001aaae89fad11e8 +abb2826e4d4b381d64787a09934b9c4fe1d5f5742f90858228e484f3c546e16ee8a2a0b0a952d834a93154a8b18f3d16 +a922ca9f2061996e65ef38a7c5c7755e59d8d5ce27d577abcdd8165b23b4877398d735f9cb470a771335fc7d99ecb7fc +90f22862216f6bc1bbf5437740a47605d1ff5147b1f06f7b13fec446e4c5a4a4a84792cb244a1905f3478a36f8d7065b +87f3d9a86afef5b79ea1ca690ee1ee4bb9754b66f7c50a42ad6b99af7c222c853ca161f440a0a2a60b3b5a54e3493240 +80a9ca9a2d33b9cf61976b3860d79f5d00de89a06ef043d2a52931809018aeb4ce70423cbef375b29c2c750c2c8704c2 +b4e798ef1d615896108dae37ac50c1e859216ab6dbac11653e44d06ce5209057b4b0dd6d31dcfcda87664a23c8ef1cbd +aaed6d1e7c5b1db06f80dae6c24857daadfb0268f20e48a98fba4b76de1ebf65fb84c3be95fd6a418b498f8285ec63bd +aeceaa316c6369492c939f94809bc80e0857abac86c0d85be8066bbf61afbaaec67e28c572437a8d35c49dd596b3134f +b791c3d53ed34a7d1c8aa89b7953e3684c3cd529230824dc529739a5fbe74b58b87f01e56e7a169f61c508237ef67160 +9351f8c80634386c45c0050d2f813193f9d839173be941e2092d729be5403632a2f18dffdc323d69eb0dc31fa31c5866 +97693184d5c0056ae244dfb6709cafa23a795dc22d497a307a7f9cf442d7452024023c54a8d6bda5d90a355ba2c84f3a +85362daa003d23511ca174a8caafe83d52b6436dc4e43c4c049e5388d9211b5cbef3885896914d86d39be0dd1f910511 +a2511b5fa34b24eeb0e1bcbcf872a569d1ff5570fe7b0fb48f5542f7fe57bad808d34b50afa87580866a6cb0eba02f27 +b382e3327eb1401f2d378dbb56ac7250adde0961bd718575a64d264ffd44772c20752d4035c3ba60eb435e160b375e20 +afad8a5d40b536c0720556845a6b257ed42165c14fb4b4a874717d107752f49ed9380c5b048df3aca67287bb8fc411a8 +8fad0c98434ca5373c2d767868f679b76b4a8d04bca8240ea3f388558262c2d61b73b16fc1160932652b5688c25fffcf +83898008b5cbb6f08f8ef3ec179427869682bb4e8d38f6e6a687a214d4a307436afc64ee67d70a5a8ba9730bf839aecc +b85232e79913785fd82b06890706972b4ad7a309489930ae23390d51aa5189731f8a2df24800409a8c36b3dd6fc91275 +a24ff26ec792f3701da4c5638c1fca4fa4dae95b01827d6200d583c4caf17ea3171393ba2a8c23d1ee8b88402916f176 +adc5c7a7ff6b41d6cc386b7fc69d7bb04179bdf267864f9aa577f0f6a88438191fa81ebaf13055c2f2d7290be6421ace +a05e835abd502d31454d40a019010ff90b6b0b1f993075a35c9907aeab7a342ac0ba6144dc9379aada6119157970e9b2 +85ff07ba58463e7f153fc83f11302e9061e648a5cbd272bb0545030b20e11facd8b3ff90c9ac8c280a704fbda5c9d1b0 +a6c735ada8f4587da8cdad7ea3ada01650b5a3ecab8d81daa7a5f5de51ef4a6592b524692584306f06be3f6701f2870c +b138deee4e53ae8d677fae104f713ef1b8babfecec16b6a85785a66a72784eb09d44c3b63567222ade714e98f7d1604e +ae79c1a49dafcdd972acd95d8ad0a35c02adc7fd736d4c44c3cd13df5789d339b5ea16bddbbd43e486a061ab31baa5c0 +ab3cf2371a1d7dcd0ffe3869a0178230964b06694bf258b2073ea66a2afccd845b38485da83d02e1d607d4c5c36b78a8 +ab9609f28a325fd01cb39540e3a714506c44e52ef28ee640f361deb5760aadbb23e804663b0fa20a66e239c33f8d8bb8 +8ed95ea8e76e1b42823d7915a6aae77d93746f846bf602841dfce0e47543a36efb9ee7e5b42c73c3209d911225cc471b +a80b6162036d43811482323f0ce59eb18740e33a63d7c7bbbf3be206985919e5342d53a69df537d43e8b7d7f51e8892f +93c03d0a5083408ba00c125a8a9385213d4c860072f0297857b1235045819b904e07f2425c13a661d0a01d2e53347f4b +a6581200f00f96c461621e1d26b14a23687dd97eb9f7df4ba641a84340ee7306dc1796248fba4804f185947ad13b4385 +8be174018fa40f7e0cedc5ae68f38969eb7695f2205e9c573641e533d56f68c20abf38a23d2f0dcac371e60b21b18615 +857ad4ee3218c647c58f09b8ab22bcc8976f00a768ab1f708618e868e6143474be846422ce2710a0ed39b5155b6f13a1 +a490bec40f322d599f26bcefcdddd8f2ef6576aa737d5ce7e8d5d422741abe749e3e6a48489aed8c560633f72857e3c2 +a9c0ee339621f1c4a2410f9b4d2f03f1b558dae2973807b8bccd920e8feb7f65dfde3e79986b72ad21fcc4567240381d +8592251568e750a430f7d2c6ddbb3ec82a4dd9fd83efe389e69aa177fd97ac2c96c59a6e86db20d8e6f125d65b46c4d3 +a4e2f4aa6a682913b423b097c4069c4e46a1f3af9556b1bfd0580d0fc01e3991488458049e0735b2a629684a79271c8f +8c4f6a3e738cf74112b08b1680be08158013ef8a515a81215d8a36c9b756786d1b4cb4563923463f3329292f4b48bf6d +8bace547353c02ea00dd547eeda7259aa354d4772dd5e0c486c723cf88627b7112e196b879c3c92a9561b674d9fc486d +8d372f4901e25e8db64fa098148d4a4e709b0e9dcb756d0f90dad99dea393054193ae1a33d292a3dd772ff7ba05e4b71 +a8c7ea6a6a031ed23d65639f01f5423190775558f479700597df7ae7e338a6ae5e9b32f470aff20787ac8b7eec84df6c +b6e9dcba240fdbbf66033410a79a2dd3e9e1ffdf2eae949b3a9ed720e939d92339991dc3e70a5ac7d5253f317daf0b7d +974dec4cd61af75721071752c664d9c2a5121f06ff1515c56139a177a3ca825f763b69d431d4607e393fa74dcc91cc58 +958863e6ad583a9d370a6db3639066982e44766904e7afa849b132f6666b7d08ab931131b3bec7a506d6583e93d56767 +8b93a33b5da9b3300c20a96d80b894e3789c77041183c2cb21751579c8c96857f60cfc2f075201b64e95a78985c5b321 +b726cb9f7ef34ddbc2fad82b3b0af0b30cc913e26c5a614ae5c19cc9c55c8e6dae069db5315a8dcb6d987415bb550ca8 +a730f515398a71bddd66cab2ff996659d4e47dfbb08ce7958a41021f76d269b91c7498b708cd14b183a8ef469c772803 +a4eb3b18132eb0f5337f14e01d63ca0bec0db6a43870f800e5491db756c2f5fce519d8dba5528b4bcef550d06b33699c +b1ab6621eec1ee6784e632e214693f39a14f3715991996b883d66200963e065c86fa0667f7bc36b93b40b5d90ff708c2 +80486a26c3532ad6e19f76d8c9344e2626c07363fd495264927cb5935fa9565ece670dc98767afb04af6a9a5c9231075 +8ee20e0df3c84a1c6b0e21bcc325cf99235b747ffe47f17fdfba548a358ca75cbcc331dd50db2311b400ae882256a608 +aef4268959e5541e7ec69c921a1e81a8374d7e44bf1bb2debf4101cf3cd6b7d6ca7f441758b388de96b3e0edb5b97be9 +8793629bd29d689ec94b016de8886cac6e2ca6638911babb22db4a787661422da0639a4e4089ebeb689d173abfe75950 +b487b3551c20a29e9a5abbda8c50ff594826283e443c09e3ae09b914e46060b3f9abf70434444ce1487e2a74e562616b +8f11531cfc5997dd04b997cb87ba1831aa7041d5434fe72de66304e3f165d882fac891391fbb1eb955c65319e65293b6 +b195136875fd02a75676c33cb3e60504d5964f7a9e81f4c8c8fd38af62e2145c55f765b3158664566191188ac678f381 +b374174b0b3eb04fa49eb4ece45173f0db5d829eac370a20a62309566e0f98b18f72f3633626893c053b7be6bfbd2366 +b2a2f6b0cf652775679b2d677048f2ed8c31a3269e6cddcc7a10e3e6fee89e486b50d9d55fbe452b79c4157c0270fb77 +892177c364dc59032594e7a6fd032286ffdf4fa0b9e3baeb37ec839faebfd2fd46c57b2c9bfe9977b59c93a9cc0ead1d +8ab7c0038a7dbb2ef200dbbe9acbc875829ecad4883792d5c6ce283de67ccd9aa935a9cc7b30b2bd9de7fca7bf2a9a05 +83745cfc78ca709835aa6c6a233c2b86fb31e3f9f6a8becf63e501f2841c4366fb7d131b746c9d3291afda714ff05579 +a723dcb67925ef007e8339dc578d2622d9bb77cfda87cca0088854a59414c02338752c56116a6c1281917842e8467c38 +8a098142da0af2254c425fdbbd0d1b1a17b2bd781391ab37f181775524b8563c64ab8a1602aee2ac6c0a82ba11a8b1d1 +b13bd7529a9b351c5d395c794c28bcb0a3167f1c992e8c062eef47be9be27895945231d249c73a0b6949daa295e14944 +a20dcd2fc2222eaae467d9f5db861040f58bcb991a26e5663ac3aa5e1ff13d0010657c5af586cc4621757add2b905073 +b818f660c3cc4e9f273c25ceeabe562c8afa8ff88529c26f2cf45ae6b2813cca5f350e3cbd56f6257c4df41722dabd25 +b225d5987108b24411bc389276f12509a45e86d5ad6b6d929af5274df0be11109c0fed329669a0acafdf3b0beaa8f2ec +91fcb6d04576d3c6bae947bb7843b430e5fb0592ae49b0a65dfa5791f4eaa4bf2c7f436c8de7360f217001c2b4e5c67a +8821f7a1424ca3fdc5d4a5606ad10dfaba6094cf36669fa9f84cf7617e50425405d14980780e1e18a1ecea7913cda896 +990dcb7f38f56521a70cb71bf4522649fcd46ac052c7feabb0748dfcac9f9c0f95d29e070d32af3cd0adbf869535e17b +b0fac1029fe2c1100f24e2f4bf10c7672199fce53513c7dde2e8d9b00702edf0143e0e1dc7ceae7dcc6994edc2422b6f +a514ebb1a33451b4915c05114db0b10168393613744df848b24e43e09f0bda23baefd9d731075198aace586615ac7911 +8b77f7953c2e67049fdca3653b8d8cf3f799677f79b954da02bdad8cc4d6c855c1c7c16b4f6f9ba35f46426ec28b2d84 +875520cfbda16ec5b1d1d00f578a910d0fc052f17870ba093e22e310bb07648d34817cc2b8811b6f52de535f7046a0d0 +b8c77b4be0b430851c4ff69e91cb770db1935d848198601393810ef395efab52deb9d5c6525472bab720273d5e0e7a79 +b6d4d437146671bdea62fb6545395ea3df39f1cdef21b8476b68e7a25aa7354f847740576d6c9f187bbae9941f0ae450 +95c642f1bccdb62cd6a2212dcdd6ff8d49aee426ca08b7cf3a9d15249d24a9eed5533f92a70c84498c0797f8a57efa27 +b617978047ed0f748c305aa7f30c2dacd0db00baa67fe0c5ce346ef0e6991dc7e05f18dcb2702467421f8390f27aa815 +86411c7a00b3e8b43bf22fb061b1f54ad9bbf632cd74395a478218389c0f544668acf3dd7726532d080ca7da9a5f8608 +97bf684a8849626c4710a6992f6c11f6b5406fd4dfe9e6aa502425aaafe9827e2c435aaf9a5d3d2ba3a4c0e8aec79ba4 +8b178e2a125b461d3180906ffba0af3dce614c64058501fdd35243ababf892d6fcdea4834ce42c25d5569452b782a709 +8ebed2c8a25c61da6a6a8cb0d8f5ea179e28869753eacc728f2c076f7aed8598cd3aa0981f120f9e7ea55b3a689ae882 +a6f235b8e655ca3d634740b53d8c0a757ecc75d2b8838b7948997c1985473d01943d935f687b86cee56cd47c8e773443 +a7959c465a9646908b9d8032a589e41a7dd999f2ffc54bb42f22e5f8a4d8c493a31bcc7ea2cac6c8dbcc59acace7181b +96d0532df2e12da20a57cadb6cf5f6c4ee1aa4775629358c25f1d51677a3e96d1fe3b232532324b4f02f941952d4cc68 +90f493473d686b639a30d1ddc9c72eae6e983f1236e162e58e967a477c0654973ea2e1bdf4ba1a44d7247bc1befc2cab +8b2d87876d9c4085102a07ebb41c565ba69acab99ffc03efc18f20e48d3f3bbe4fc6ddab9c78fe479d9ada80504d85ba +829a0fb3200a28e09cacd6c5346000e7786116ddfd898f37dfd17bef454a8abc0fe939ed8735c00769f7f2f33cd4f906 +86194ec9e88ddb7150e8b03e7a535b6e99863fc6762835601efd03615aa97aaeb413cb210e86035086ed852b39c9d019 +b02efd116a7189cb317ceae392bc301ae55470f0489fa89934e182aeb8c67e280299b975786fe9a470bff46827defb9b +87d7c3903bd22b12d815506f150373f518d47dfc6e5fd74347d88b518124c9923d1e4c98defeb3a45d53d50b423e2175 +a1a430406b28254a7d6348bc98e697e9bab43839aa05d53faee97546f84541ea0b559162619b2045182938f69bf61cae +99d243c226c61c6697fb3d2594f3533fa5dfd7cfc87107908cacde337d7a077fa5a9dc702d26081b065edb1227498e65 +800ee5006ab6217161f42db0cfc552a81728bb4fbd7af6e4620ea099a65ef6664184af3f65a07fcec7e965529c5b49bf +91bfd307579cadc8f81009558605be3edbcb8dbba271475803484017f40130b2b216aef4f620d960193be681877d3a53 +96a060459dec458d19a6f8af6e49dc6c7c58c55dd18915c5fce5e0f4b4a422fce3b9632f6059388fe760289abf70f173 +9921a37f3e657222c7fda3588418a9071409711d9f1fccede7494429f02a45fbc52d79fbb64e9ccd518f60d06d0520d3 +81052b0d15773cb75975ca9230ebb2579700e489c7e3f07cd9cde206fef38b8139bd4976d2b4a7840495fc645f96df03 +88ac37ba66d1de5e23878c992e4d54023729e97e77351f50dc5918d738b5a73faf1dc6feec7e85784761836ba1c6f778 +ae1e6072c13060775f6086d1ae1f88b627ffcb810fc0e0e97deea1f3a15ef0aaa52a6dce2563e4beedadc131af2a8281 +8b60a340f5e4f90badf83001b495ac9f13974c3d2054ddcb3e6b8ca99dec5cd63a263e05c282454191ab2e087d5a2911 +832e2d56ba69dbf817b2b9dbd25c1538d5b8dbf5d9bc05e6be85054a423ebb66a71b157e166e0b9444ac171b34b7ccc9 +8586036fc7dde1e7e3ecb61663130c4529866ae9f5f5095b9fccd24a4c70eea899aae5f10ea1ba66d1665b2d83be35b0 +a77969453b5c083a207913272b5b69d4ccbd8718bdf54be8fbe11b4bd0a2168aae3ba8f9362afa69c0ffa28d7e5a2340 +b7fe9568c214baad0ac5f83745611b481f744ec1c4fa78a549b180dcf79633e5ba75dc20055012a13d849eb7a9be57d3 +b01cad1d2a6c51c0ce88243d1f52f95fb5ee315a905079688027511f0c4ecd0563a3a81846709d272fa5ccb9665e8043 +8eae0a21adfc569aa57237654021c2bdb2c6f0f52ccc90a126682c21a1f9413c63d285f92b2b2f8649150a9284bf70b7 +942acc947192b5f3cf60e92383e5d35f79e7a5904e8e9fd1c8a351676c83ad29b0afb6578d555457cf909f8f4d27adfd +a74e092f8628fba9abcabc27e2e9f3d5a9a941dfe50a2dfde2ad179aabc73afd196676925c2d98643ab8b3d02bdb66ad +896159daa2afd757cf3f9d34af248ad68bb3c62e4c9ac49919422727479cf669098f270b9e645607a7d11adad4c889b2 +a428d8370813d78e7a2a24eebd36e9da2f8bb3605e5a39b5fcda939b531c35a8ebaaa642ba556250a37bddeec90326fb +a5fa04eb60a1d5ee9820e78f42f7be15e1c02757b539aead995768c6209684d6c183c71d282e0c12a4c15c03f9a89d4d +93c77d5d220e40affa7269a6915c076c9aef4db552c643ae5d560a79c955b491c6346ca4cf11cbb7fe1894e28d47b065 +802e605d2de745eef6981d88e7a57ef4046a2062725e8080995374cea2b3273c27f35b7774d0dcba014710d8d6c501f2 +82f7169e6ec9b3e2bd450f35ea2e66d06bcf900acf5b73139677b48e078ce2e16599103027b2326770c99c0a690f2015 +b0c8581879439f9b997551233fe2de71aa03604f9cec37a7b18c5854342d9b67be468f3cac4bf6f64fe8a0066248c498 +a3f626848a4db6e9fb01cac90d3362ec521e969ebd5228af694ea3671061476149f13d652942ac1e39f65591fed740f9 +88a8e759b9cbe16a7c16e43f4afa2de6100d2eafa4dee75ccd653ec38c919013d0a6b35c1ee1eaee7c1985b58bcc9e92 +a3d5fc7aaea072798490616552d947e95f49cf02a420314307aafb555287ec607d75589ba24b009cd68299dc6f7942fa +a809cceeb84f9bcf3c3ddafde3041e7bc3b1d14df8830ab849002176a0725e6f16f70774d8962cb0b8ac0dc43c4ac66f +b8f2e46c031cc8fa160a08c2ebdfa85345ed14771b06daa9636b0e7792b7fddbc501dfc85cc626a01104a43a7d3230c3 +b5367e2a521c318b802ce16ceac80c4b8139f73ddb10ddf38433397cda70a86ea1f051cc55626a4e99d27f30f3975ff5 +96d963660121c1441cd13141279cd371a6a0aa18b6a20761b18df60aa9c14e13489afd83695a0921d5232efe72045f07 +80818d492fd85d666bd91aaf6257b86527fdd796773c793407df1d4a0f91d74649a6bab4d15155c36ed4c6e0a32c5636 +931e22918905fd6c230d3d867ea42861f3074d320d14e1929031924c8ac209a5c552b679b24563bb12f9749b4ee983bd +a4de2c333e74ed9bfa3c0bf6a0beb90427abd9aa4221294cda74331646b58ef46ed57cccc8798ba2b9309894b17cfd69 +883881554c1d88c0ed8d3b6dec3d200f6fea69a77ace3e4d6f86b41506a23724b4394ec8384075f9c75c3868ba8a8e8e +aa0539ecf6ec9bf06f24443027f8f24b6b3d8c5b2084248eecd4bcad3c9a69716e1a0d01057f09a65bff1006ac5e157a +856d74d44c943c9e809b42dc493dff20eca03cb0cf5ed45108c69b1f90d8592a53ae8100e99380a274fafad23e74cdfc +9188257446661c88da093b7c5ce998135913f63842d7c1586065377b169ee35b062d925367fb9b909ca971f1188667b1 +8d3aa57cdafbe998938787479f5d590c1484c6dbe94e6c487e57a746ef5252be0eaa5976d6270de7db64b6b92e57a0f7 +b8f4d6997240f9eda5aca0c43323a828d1563c491b3db2087f60ac4120a3fcd06075fb42bb19d0339ab5ee3fb7db25d2 +ad247ea94b8ae1e81eae4c9fd7b39e6601b53cff47b2547ff90a3cca87192eae28408082774a1fd14bf9ab459b7a4f1f +9598598070f8bdbcc49056c40971e673726cd8c1bc4baa0b5124dfb5fb750e7baa7a7df18eae2bd91955ddcb1ec67955 +b874131ab1608667fa60ea29092d090859eed1812e90c609afff96d79e82c5ba546f617f4c96fc32c9bba97431c1e9af +b00750a9cdc75c2a54f0d3cc99b0fe02300754f25166f7ac85ff41ab5e9cfcca33a29be76a480f12a2d410c7cd5032e5 +84b5bd1c90bb6c66755b28ba4af493ca1b0c3a4df9f436aac67d2e07289053f925cf6a149a84e74e1027dc8758150179 +99caf64bd9d193ff306e8ab5da3f1bb2a190a60c3a82099b8d03d17fa810dc53d176c21379f479e828f60d25beb3ffd0 +a8fd9de502f1c261d5733430e5a18d8b7892a98c9529a016fc2ee53892ae965dcd9c75850bcda4c7edb980b8d88e60ea +848c02cac636e047028a3fe8c1bf4066fb7591b96b0340f8fbd476ff01b35fa3e37d309333771a134f24800e5f3f9289 +a1eab1a06dcca3439f0166441e7e7f2f5b56f5f8aa9f45e411c561f556e0fb71c514c06c26ac53b49a576caca5faac3d +aa603f970dcbe953e700e61c151182c8d32cbbb53ceef572ac93383db33a4b098b5c7b267e42d514ca66b740c0925efe +b55fd5301bd700ddb0b4f72fabe9a91ad49759506101fa802ed1677e9553595aa4d2c66f7574e78d21ce882ce0120ae7 +829137bc4da7b4886d3d04d2c39cbf4b1dc40c813ac1adb425c7b9abf9142b516314cab79c68454df5d71994ce416144 +b83a3a22735001f783dd48a01c4fb3598a51ff3987e842b8045c71c035b9e43645a55254ca5911a5676ef4a8af12d056 +8ca8d463deb13f9eef5e533bc39efaeb0c15631282c5c0deee1673b0053a7cccd514af09801dd6c158caa159fe9351ac +a9ffb1427828f3c456b9c8cc50782de1ab0029b9233a0fd998bad0fd014d27e15c4a32d1e16ad41bff748378b5abdf49 +9627e29f725ddd86456aff813976bbc4a836f4deabf5ad9f73d1a260ceb30948824df9c8841e6b3c529652202be181b3 +b52c988647fe3d9276eed3c262e1044f57fbb116c64cf4f207235c205b3fda0f3d789bf90f5217401b468d85fdfda404 +833bbd6e2924f5c4446cb76b881d1434a5badce9eb9b003f85d076e297ad7ef45b822069fe54d17427a348c3263fb838 +a067a36352db6f82a116cb87d3db5f60b18576852409e2076cbbfc7843af78866313a4969385a40271051dd195d51116 +902b99545971f9a103f99d7399acc347ac46fe156166e51deefc0e92aebf5893460c69aeeae11f5af9f49418e289ce6c +9206a0e9ce9b9880f29ef0417c96931985f5d83bb17cebdbba4ff2af81a3d37155b04649426f698aed372e4f669599e6 +b54a5d7c976e45c0b1d44433595eae9d1ae9aeabfd58cd5ecb0c5804756a7b01c9a517754423b4714a3695533a3114c8 +91b612131e84580ece228b81ace83da0269b53f94d3c02a1a0879ebbd81bdc252064b3d03a7e140b43a90f237d9a45a0 +a6cead3b8607eaeafe37135bd6de8fbd16f806c131eb71c8d36bfbe295d45b070255e50dabf076e2c3f6b8699be71d6a +931da21e67b11ba6ce438546a24d063bcd51aebe39b4220a78d9c0aab88b2d37969b5ef3502d835507f9c8d6d006714c +8fda408caa9daf01122a2308b7b9d328f52e1e2f138a8bec30492488f4d710e5e52524a6455a3a2ae2818ec8a610b650 +ad8ad5c189644352d90c462731c46145410e5adf38682bb80f95495dd64d9d13782537d68690847bbb06c6be7175dbc7 +87bb5cc466ade60feb0961421c3fabdc8a7e20f11df8437bfff63d3f8bd25305002a396c9d0fa4fb9a9986d4717f12c4 +827cff72870ba00c29064a7d2b4973f322d6b6de7924c93d8bf8825e7a0e8478c7748f90f5c716bf83c55b2795d315d8 +a225895a8e94229776ceb51b05356291f2dce748be17a60d5aeb33ef8507c368bafe5d1d6eea927f28b9d1422b661b9a +8e011323ce670ff51c964241a6b72e0e0ffbb3ff9bb2762492323fc3a4abf4718091be0945287c7329850e4f74462cde +a2c03c2e5f4e9d3ef361f68b188451994ad1b24de9f323370559c8abfcdc7bffd289d92e78a5f6b104b0a12c84dab2ef +a22b4771116ce22276fab1fec6826610707ce8a342f9f60b079c4e0259dac3cc41c96c560dfd0ada6edd2828f7c0e8d6 +97c17441d0af9be83b42097aa8b7cec84a253b9a2b957214b8fa93c26d2add46144faffa7b8a55312059b10690f711f1 +94bdf348849f31a2737cbae5e5848aee711067bac85c11c2e68b44c398cfafbf3493a3226cd1ddf7a916e7613fc7b6f6 +838f59c6e8469a8ec6fd40b978a3607439aaebe1e50ff707eec72c0b8278af05b477bf12a384b56d03e3d4eb91e56f67 +a1940f0db58185e2b3aedd2b0bc2b73b4a65c68e09b046f38e9dcd4e13c94f5406bea92635190bf315e48ec64eceef2f +b2f4e0ae44e1f1210a91d8f280f17091fa994034ba8c991583f8182a323e9b3001a712e3584fc2d64ecbf2d319d076b2 +9342b89c721338d02c7854cd7466fb24d93d7313b6114ea591e6607439c8ddb911d1cf35f01898e9c557982bdff8f9b6 +8583fcab15be1dd14d5a415f4b14d706c8c62f058500f1344b37730c8be6741779691f87ded3cbcf6516468b373cafb0 +8fa9587c7989646571ad9032f34cedd353caee14f5be5cde1e9e0a1710f90c08faf6fa96a60e1f150f761c9c8ae7417d +8d9ff904cc08141f5a9879f5f77dc600e6edbe859082231a4d819953890199bcc5f940b730ea688332f07e5279d49e1c +b5f82b46e5ef9a2df8d144202d6e2e4f3bdae8e2048d2af5ea7deb3f722fbe6d370401954e74ff0d8cb1010ffb1f38d5 +a3b5b57d435b06ed70530e060002a8fea71746ad07d969ca23f22b5e52624527595b6a6d54b4e953fb7b7596bac378f0 +b90f89390df6d4b7879b915aa3c29b8d779d035033f8873bb7ac54a14ec98f0d08c0e3bf696e2ffa7b5730d736f571f8 +8e81e371b92887e43d95c0dbdcc9575282b26ccebdc8cbf46587e4f2a83b61e9bc0c6d7d1f114b9d21e04fd6c180b12a +8d682947c51dffc6e0fe0a486293c9ed121f441805168236393087cf62f2a429cca60bf0e472564844347d32c6bea27e +a8341ec7dd189fa7168759240224192c58209b53fc961c18082deba217928c399bde08ceae42bffd37c1135b4d14a845 +a94bb076dcc5ee5ec82fac57c5b384c690df12631882bd1b960e1eb8c04f787bc22b7bac315b9dc5a8a098f17f051a0b +ab64e1c6f01b87706c88a3bd974454a438722768de7340b834ccf93ea9880c14ee7c2181432acf51f980d56de73832ee +b7b0058bb724d879e5ad7aed6230297c54cb599ef659e86bf2cc84c38225899fb388391df9b2e6fdf063171937fd8c72 +ae856f4fb74c27cc98b67429186e7df4feb01278cd57bfd3170af6e52e0a23b9e926bf9565a890cfb4ae8f2d590b2cd5 +804b9c6702f0596d328f92fc1ed5a30a7ba17b9204524135001b569233fc4937035031d079f52fd04968f37c24013898 +84274ed1af6bd6a968583995622b4d18c6a2bc703ce0d0edce45bb736529b4836343dcd11911a94a134dca7877e6cab8 +88808098463f7505034c3b6328c8a08186b33f7a981c08376e429dd64b79b97753170531ed078dd265ded4ec0a1ed8d5 +92823bfb23a4eb84d3759e7d717f0c8641ece0927cd2ba8c728c26bb35df2629a838002f353c8d3d75eb19520aab5f25 +8db36bae4d960cdb9c51f419d7ddc81f372e56be605bc96a9d4072b829f05527c37c8f255cc6115300a2a0d2e6568d89 +a8fcdbd7f3b4d7ff04149a209feb75e97149e7efceaa42d66a6b8e432590fe7bd01f1a77fa8b47108f670b612e33fee9 +a9f4c53c62db7e5dbdea6918862d3c6d24b5bd8732a218edf0ba61e9d1861182323d8ecd7bef8f895b42970b492f6e40 +8b95bc7f07818f4d7b409aff8da0b2c2ae136cde386f53a71565cae9fd14c73c13cc1cfd79c0f97cd77839fb738c5b9a +adbd1d11adc756b51a571ddbcbf4392415231ddad93da09acfafee03a9e4f9e1ce3826110619e5271feadfaffce3e793 +95d327c8bb195cdf25fd79c98f9406a6b0316214b1630ebcce95bdaeffafa36fc1accc6882e0e5d13a8db5c0f3c0e61c +8cb2f1e2fb25558869afdacc7bb866544cfdd566cefcd048b48d458a886130bd086ecb7600a960a7f2563c61cb326510 +b3aa8c4bf5b933d89cd74ca7f7176d6624d562d7d58b041328b49d7562a30b489cb606abb3c49e85baf04c28e9cd1f44 +97f9053a85250c420599827297453c2cfde087065b823d9e43139e6a9cac3a2ec40a1b6e2f0726bdc870fff215462f0b +878d5dbe6b881389c2ca126ff66d87127c9aaa3f62f0d2c1ec0ea2b279ac95f8a06710dce166415db227655e2345a04d +b2c33a6b4203e3ca5247f0890e475518317ffc44cfbb1da9a1ba02114e8b752bea618050b876de5cf3b1906140a64471 +a56170c8313d2b5541a795bea9934d4425b185b5c409f0484df6f44f0e4bcbf50b860ff46b7245cd99c1cfa8fc1965b7 +96e2b658e2876a14147385fc423d2702a3cb76962b6b437222cf9cea39ebf4bdc03bbf434b747866d4bf72b4ceefa639 +89c4a74fa2f067e7ae49c84ef782c331bcc9245db7e941804e2e99d12e987b4d25cb827778ad4c3566c4fc68018650b6 +a01d30cea7d01c80ff26650020fab02e78fc3842e2398a81b44b21d58d4e9816166ff4ed2418831fa995a28ff35cb6f1 +b960c80b55a8845bbf24bc3f23b0110ca701f9544ab6a5bb7929330213cb471321e55c390ceca3e24bff69bdb0d331c0 +802c5b13f22be7be0e5db11eb3be0f0ea7f9182c932265060ba05fba20ea093dd2810d3b969ee3e387e60fe6ee834e8d +92478f88ef7435d15e39a97916c736abb28ea318394b88678fddbbaab3eaf31776110936abad116a8ff6ca632dd12043 +a6d3da0370c303001d5ed99d1db8bce1f26b0e442f0f042e36db9674e92dcd6e80465e772f1e669f99221caee3392fe9 +938f04f70a8f947d6df2f0c0e9af3cce0c06edbb3c131970dd60884fc0b0a0959c504a2a36c3ff76dfe919905671626a +a7117e55224230822e9983df2132347eb7208cb6798f291df926ab51e04b1a1f78d5568c9a8924ee6f57426134360f20 +b91074c77ad93fe48dc2b10c0c5a62ca3ab7d98345b919c52d84a9dc419b59fc1b267e1c2d4b2e120016ef84bbdb0cbe +aa175c6b6edf02fe8778762c9575581c0ee6efc9dbf99c291a41444a23a056b893be6c45333d907d0bbe9fb0eef84d08 +ad36dcb4e2ab425aa339ae464b038d550cb11186741dcf257f1b8b80ed4f32ffabbece45e2dc1525d4c3eeed819ea04f +91cb35c1ffa9cd5aebef523edb8325078da3eb5cf9e95c675a76446fc7692aaee6f949de064ca2f3e0f082cc3fa93e20 +82622f9410c143a86bc4d756b3c7b324dc295231ce865de020d61cc0868f2c150a473cea3a5b756b36771ce1032415a5 +a5c29996ad3a53468ece9356a5b4ccb68971ea1c89cf39644f1da2d4a477c2ea99bf791ef902b87c225d8c53d67c4c92 +92893eceed1af34fa92b23dcbab175b6a0188a27dbac9ad3317c4e39955a763cb383ab13fb1c519cde311d8a4d12e8b3 +8a093cb191b94b0200e38d31955f9d240e2be1edcd6810a2396a061f17c3ddc9c4f4d56766ddff4e121be7110e03b869 +93981473df0cb1f4b47c7d9b64e3123dcf1593845b401e619f5d7c70b5dbea375d1ca43fca65845fcf0a6b2e0af43791 +a6beb6b0697070f9562910add88d9ba91992f8da127b27be81868b1596d1012f09ea7ed601b4a6474c921a1a1a6d866c +92026b1ee30f2ed61c9f30337c3356844217926aabdff383c19ca3c21e0bc49811ca5b308012bee4ef250cfae1615800 +ac0ebaea6d35f84dac4ce648af096305ba68a7a0aea0a11ab2fbe3162075444a158433c98141bc92ef3b3400d6deb46a +83046f482dee24ac3ca83373f0d1b82ac1c4beda0f229a9011a81ec659ff5fc1fb105e219975b5c744308c77a24f71e4 +aa5a312c47ff7248dcb9c6ffbe5a0628ccd565c07365c4413734d415cd4fb35772622ed833862dddff520a67c509c6a5 +a02fb88805c34018ac33582e19ed0a7e4616acc3dd0867e5f21914c2031c05c6dca30b8b35b57c2b137750f3878a6f8c +a60528f1f14bf0c496491d46a0fbbd6c343e4eb3f1631e92f96a3c5e5c684091aabe5801df7a67f7c6dfd1b0d35269d4 +a1fd8e7fad8ca05a340c05a051bb0eb4197eed345f4104629a9e38e234b09d789cc5537024615feb4a6177d32d39e39e +8e70e36c1aa070815440e19443f1f04aae23b1b59fdbcba43b47b94a026c82c8f66c5dfe54f826f4d95ee1930cdb8008 +8234c1969fa7e9079661e4ca309b71b1aaa10f4372be0b963205c23a81f5a3d52ec08ba9ff65b37f832b52d631580d61 +a18cb4134127fb37c4abca328cd0047378a2e1423490af2bd3eba9ffcc99ca81a3c22404c0886f21f65c7b93c41d7981 +b46fa45fe538816de776eec086e040005706cb3eca097e290abfb6864e745c879868aac8361894f3c3564373ef9ad55c +b96ca43b96c59e95439f75d1e726a35a9362f0dbd34963b156e103e080a8126a8dc3501f9fd541ff3bcf4677f5c4a86b +a8e8c87c7301613818d57387009e601a7ab5cbdc2890f63d985c30c74f9cea2d0584c116baf0d9cd5594386ee93fc661 +b47e4f1b9153ef0981f813948150f283b47a7346fd9921d51fe8e4daedaef78ddeb4fd467c2ccb7cebd9816243da1c6e +a370c202a99c8441ffe96fad0f801086d4d7cc7b960f6e98cca29ceedf492afddfd0f351c9c4d29ac008bc255ec1a2a8 +8f5e6ce1655d1c059b006174e3f5a55c88e1821c97f9702ad8e8455d46c2a83ae4482f2d43edda74a835686ec45a8a15 +a30421e694930a3b65d397b2720d5f8e1eec2b6e2bb5a28d3f9b0a84db9aabd83850268bae64c2b10e313cccf120151b +8abe87163046f7a9b18e2a3c0b66e258facc1b31431420e0b70354b7a60ebd250a784634a76692e7d6f4330b62114945 +894f033cf077d4eb312e3258d9dca414356271abce1d6094ecce6d018c5fadb1c15d8d69451574ad0701a2876db191c5 +b0923d64f88ffc872654e1a294bb1af8681689c21cf08f39afe51448a68e60a9a0a74ccce9969276a932a52c07d095a3 +b9ca23b5be8725fae7fa710eefd45522889c50c29c26384e00b78a962384f0aeff9d15cb5910e9565da12a577eb7e5ba +b242ccf292757197a9f470f2d80ccddc48c7f1235ba026bc68a93be2738bc968e8a200aff3e2f4807216442eb3fc50dc +adc2c3b375b308524b79a024ff87d122055440643fea6fc0a651bdb312c7cbe6a456afa9d342bc76446d77d8daf08bc2 +ab645955356c2ebf2f3df9da275e01daf0b44a52afc309277d6d9ad1b05484e5ae0d9d41ad485fe481e5e362826a86ae +8de96ac587a4449fcc8b7fd0a51b4b5185d9c2eb3434f94cbadd092de1e26b0f6b3f7b15a37e8424b1429121ddca0ecd +94c70ad4e9b871566f3da98170b665a09788d421818299857cde0853789fb943cbcf7d4b2c95246ea7b72edc56a8e36c +b2574be63497843340700b701d5cc8be6d23125bd62058802ee67cce1f3b5f5602b27c93fea5611f27dc695ac563f042 +869ec89da7850cedd88bcb3a50a15cece233119b31b64a61bf6b2310892ce42d8b473b584b11e61db29ed24ce8033f83 +8fbaa269da8e28e9adf4c1b08f109da786dbe9cba871c32eecbfb10619b7a5d65a26f9bb33e201a8ed20b3de94003fbb +8bf7a059c37242caf7f821a6314e4e4adf799e0dd86b37892a7172598892c07272acebd05b534755c57b51556b2d610f +b4e72645fca459898cdd9214892ed08b5c99f82049c0a30d72bac0b9717caa9c6cc16c3dc7aa6ea4d42dcd2a6c175df6 +a39170da87a3495da55bbb9701c5461f3403447174ed6a4af75712f7ba4ac35f51a4234bc4b94da888a0959ee109c0c7 +b45675b2774ea7696089dbf7a0afe6c22e85fd0e4ef3db508fbaf96c9d07f700c991789206da9309fd291be696357c5f +b52899e3e3f6341eefcbe1291db6664bf3b6e8021d32fb9c3e37b6258a35c1da927747b2ce990937d6f4c6c3e7d020d2 +84e5bdb3dfe19700d79dd3fabb0159ccfa084f7288db836c855b827613ce8071067c8d7ac5cc2b4e88ed7f84b690f6e1 +801477d200b6d12fc6e0a9bab1c8211193ab06e44551e037a9b4c36fc2d4f67760b9ff4eba9a3bc7b6e177e891f64ff6 +b6b71a5116d3c22af26a7530f535e9b7851f25a84e562a8f17a125d55b9b3fc1bd8cfe65bdcbeeb328409521e802051c +8687e21c34d7804c12489d30680d131ce2133e2981bfa993afd8a8eeda958ebd5e6881d342d725338659882d9f21cf98 +a024e97a7c4de32b6383c34431994abc533ecdbd6be9bff836ec1af022f5a86773bf345c6f33273797a61fb70a8fd5d6 +83f784f095da20ce5b31f54d6cb14b32a8a12675f0029289c9cd036b7c87a8077be2d04a62618685720e6ee69c875e97 +b4e9dfe7cb9d9efd3fe00d99ae5e48769d4af4bf43d4e05c0b54c9cfd8bc854de96b8d3ebf4dcc06b9dac66b7471a0de +a08b79f9d4673afcf7f38b57f484f88feb7c908f597663a2417f92c348150c2be6b5603f914eba0d9d5bdd4e5c5572c1 +b0eaf919589988798cb01ba0610cd1b7fa3c08715675ece8ecd5f9ef6d5d7b2c4c8ae1ea7dfd202237171aa3e6f9de74 +abff99a98baae4dd0954052503ce81827781694a5ea8c1149f96a3adde75dc2d630e138598cd2ae7fdc7a654aa17df8f +83e369b8680d8b9d995222b033b4f4f3e3b20e782113c941325c7fa9c742feef8747e4a212d9aa23285a259cc4faef8d +b16d5855dd2716613697eba36e2fae0872aaea6999e91cf6552f93f9a0b85ed4f6ff922a91b50816bd6cf8e7a4513fc9 +848373db600e32e741aa1d37726bbb28956783f89ce2d781e95fb1ee1adf4359968a141678af268077eae4c25503204e +93a0dd0fdac18a31875564505b4e28f9e8bb2915faae666538597731ac56cd77f23f2456461e2f672983fb24ad91f6e0 +ab1ebbe49fa56524b564bc2e43784147073e6ea5d27a9540fbf2e04d0f87c645ed2fd28b3e4982cc4c0af1734ee47a6f +b3ee30b733839edab6f61f0738e3f4afaeccf700d8dc7415684f193b36d70d07acd5780cf539f12e0fbf8d4683be773a +88388f2cbdec47a6b3ae460b69eb0d2130ac14de950c22fd86de03e40d02292bb93cebe62432da39d509c1289f785fef +9370c41a54b68ff486b4cc6329c3a851716ebf1d088d77a6c56dec93a18b8a77b596cde74cc17d2adb2b2f411a2e4bbb +b9083b60dc16531f77b05a955b51a237a8f8c0173d72c352c5ca441b55abbc890b14937e457aaec4be5cbbf80cae0099 +aafff8f6c6ebaad952c65054dfc7c829453ec735331bf8135e06406b7a9f740c9a200dc48bb2175516b41f77dc160121 +b43d31fbbaf10526809e9e5bd8bb47a76e0fabd7852ee7744404559ab89f0f215ff518f3271a6aa972a459cab82ac558 +b581ede48c6ef34e678f91dc4b89507413e00e70712e3e8c32a80eed770ec8d8b98caee9702d068aeaca6f704be57bd8 +8cb0a137e68b001a5ccac61de27cac9fb78d4af7b2f5a00b8d95d33ac19cc50c69e760c5e0330a85c0ded1edce0fe6f9 +b947fca07c7aa6c2bf13048275402b00b77b28f1d0ba4b589fbcede13f93b5b931c588560ab8ceba23bb8e748031b55d +81753cced5ff819901740a9a584334e355b497cb699f0be5a52cd555a4c9f149535c7bb355b54407f7f0ec27de6c2e19 +b3d59273951ce97838c4853ec329782a255b5fc7c848e7992ded1be28a5ada7fa3254123afe32607b9991ec6e0659b08 +86b253de246f82be1cb0cef01e87c3d022ca1829d2cc7e6a160a5afbd3ca6b94d75739b122e3bb16f8bde28a8f3223ba +b728b659fa2d8487e061a37f7d14a4c2d70cc37497a8715695d8d332cb274deee2ce23b9b5f6a7408516c02c3d526a49 +81277b46d98848a45abfbe39842495659dcbb80dee985a4fc91d77d52b815487aa8bb455f411fcce4c3879c7a075a93f +b05b6f1fb4a6e654f0ee6b83e08b58b57059bb0b7c490405bc8d963c4a2d6be39c558917977e554e1e9e3169961cbf3e +88f75fa7d016fb6442551ec071cc1e2beeb3ccd213d16d744f573a82f5d70f41dd1b18af71d5f9e73d87f2f6b7dbe889 +81a46434f1bbd65a661a0ff45a0295b8fd8a42a7969c5953721bc98698b64bddee3f806876d1e9983063fdd0c11f99df +8b4f6d33c510a4c9c7d623d9ae0c9aa631fcb987704726b2a4d8519372123bce3c439202f25b5b47045ec14ce39a21a8 +8d5112b330fb63cf6ef3d2164b404c14ff9907d685015701399a260951912b19b8f270f869df317e9050a127763d7980 +aadab394e84dfb82db15ecd2427f39b62352c3e1647c3bcd14fb24ae830ad0116f0fed87ddb63963b424a4741961386e +81ca4e5600d00a3bda24cbdea7a532a4cbbd893c10e7ff10667c15ffa8138b91667abe5466b31a3dcdd60155c48538c1 +ad943af1b8a5fcfcf309ed8f2f916339f254cd555c71a407a47365a139306286a05a8314e1c70e20a65fccd75d36fa12 +b16597a0b437060a390467bbfab94c0bdd695ae898894f4689f939e30cc2119cc08ecb594546304adf876f4e275ebcd9 +a44a4e0a6693be356065891c27eefa040a1a79475be53d54d5fdcea7e0668ff9b35f850974000ed119f6865aa6faa721 +adef27d1b6e6921f4eaf69c79e2e01f5174f7033eaafdd33edcfa5119af23f3a834ffe1bdf19576581b797abd1865b34 +90c1e9202f3ffe28f8e1f58e9650dc4ff4dbc158005b6f2296ec36147e524b4f2f87f8aafc39db5b006fe0c491c92f45 +ac817cd54288b6f7fe6338415344fc9e7b669414051631ab2f27851c052c044be06bf7235d668e194bef695923256368 +ab14944ef653a14456d4ebc12e3196df3f1b4707c4e50b317b5ccc8ca3a0720f0330609f0e7e71793f6ca01583f38c70 +ad5353f2f380837e5ffdf079350b3d42935a0517861d03af98db5ed3ea8501abd68885c8c65f5a66e944b1874826a450 +8b5583863f84af8443ce8970b02e26cc5d959e47efbf8a66a54106ab165f1f76b36423aee74c7b5402fd1c4d7c1adfe6 +b3b46037eed9fc30e4f8f0da8bdbdcc40a38e22e876ce9fde981883017854aba82c18eb00887d92ad847d30082fe7271 +98a2b6fc90b7ad172e4368c1e54675b75c8bf2096d91c9f2b60b3397d3be3b705aed5389845dbd68f0f84438cd0f7687 +b155e800852a5f90a2eac69cc4483428da1dc2c31588a13c924e60a7616ce9baeb7d4b829c772b260277cadd8ed84719 +b8b92c520a1302b0cf7d993a52e1dacd7f27bda9868d59c55687d995ae676b7070af4c0792a9bc1c2635d44a4fee01bb +96dfe9bde526b8fc829eda825f55168b88e8f4e43d4d708cc3060df03437b46e12a8ac70d7788aa75760f6294d3e84d8 +a3fa66c54e2fa084ced3bd838614c6c33042f492a5745d167a723c60d5e7d6020ffd1747981a23f8b68df21ad8f0fa77 +b573ca10cc41fc04a642f6f62c355a4fda69b94b8e95dbb02fd1ccce4bce1191356e1fd66d372159944eb36a7071f005 +acd0a1c9abddfd0ea223eda1722aaada362d34234455bd1c6be115d41e535b16f12ca428da7820a757fa4c98884a385d +96f242eee99c4db383b8754fa7987c0c159652e1866faec905a8d3f010e0a1ad05bd77b9ea8dfd653738959180f58430 +9215a9b672a5d6e435e0e0a45156e0e20f75cbbdf1d14940fed3ddb63d433bef643796c7a4fff881829ebb2b2eba9460 +b8ad9bfceaf08dc5a874387219ddd1170bc3a5e25ed72d321d59ae713be5ddf9fdfbd3aa7ab163be28dfa0dd14614e19 +a19a1050590bc500b32c502f393e407abc3d8e683d6f6b978873aff3e3299b18b1f6b59e2b0fe237d819dbdfcfdc98ca +a6870fb11d4429686e52e1f44c8dcfc7ea24a020df9570c021578dbc1f9bdc8cf797cb3a72d7fc52805dba35d59f2cd0 +a7be733b64d5c06c127bd1c87250e42bfe30ca91ed8ce51e0b6e377f454e8f6fef7f99bff650695df2fd10c375da349b +a1b97145dab30330eea2cdc8739b2446a3704b64505fcea3dd8a9b4a72edf222e98d967d6fd7f76794acfd97aa091065 +b2127049907d2a3b654d1c940b740bfba3dbaf660f86ea79c2f909af7c9fe2a07a1caeb1be12370aeffaf8faa50f1582 +8a207701214bb28e99b0784e9228b1c34afa701966267fe7110f6f29f5bb41eaae6cdb98844d0400787978fabd224de8 +9925147a383b6f5f814520220ffdbf20b214225882c3ef49b1a1ca677709176ec82466fb9c4be2dfbe5640afb63b014a +8416ad93871623fb555b5390b80de99edaaf317350cc0c1ae9d54d59517074d40061f315cce8ba2026d9c1e6f6a1009f +a315f943deebbf0a2cdbcf3f8323e215a406e9cbfbcc3f6288714cb3a6befb1bf71b2a21ff7a2ec4731c65044c45b6b5 +8213e0c2539c24efd186ffa8b6dd401ad2233bc19166a0623b26dd1e93614bbf792823f5599ac116231e2efde9885709 +8e5cafd2f34a127a4a896f05e4d929eef06972a1826b3566446942198df26d62f7679b987db2b3765d9d8058b1cd85c2 +b5302b399c9cdf912fd59007ad4737255552663b1e56dbe64a7b2ddd88d2093c73ea319b45db2dd49d1e03f5bef1a0ae +a0c2bcfbed4b008e1a56e5d2f2419aa59d7dd0ebd990f1c18588de702ad0fa79f445d69965fa9381e700eda13b309378 +80a44eea1ffe24c26b16b8e2e70ee519258b9ad4b3e83cc4e5cca88ebc48d0160066f8b91d0581095b0de2428390c8b3 +84a90cb9c7d2f799f1c4ed060387a4b793ab41c5c3eaffd3b60face9b9c3bae93cd2017283bf3de1e3dac63d0d84dd42 +81d22febca276a05ba9bbc5591ee087b0491beb35b4d9f8fc0d041d642a574667ddc57660b20f5c568f7d61fdcb41bda +a3ac965ac27a28e102a439b74fbfc157e75fd57620e4c0750a466165f8aeecb2191dcf8e656f7525aa50d9c7c69b0b5c +913c17434ff0d9fc52e2ece4fec71b37d4474a18f3ea26925c1be2b250434d49759f58033ba0fce1c6862c6197930dc4 +ac430559c151a5e461f67b49c7786c97e1653fa8698e9759ddbdd99f5daf17fc5a012ae6330739440880728f24eba7c9 +b10d8e9f8aed9361b042d1398ec74364f7c7c1cc5c7f917060572761138bdbe89bf409389ee3879f93bc8032dd67b308 +937271005a4cc6a6ec134870c1b56471aa84ed4f4af1b3d5f334bc0c42762fae0c9a6a2828d3de6151a76dad7b72781c +a10e4dcf51889f69e6bd4c052f8d4036b9571ced98a3d7d779cbcb9fa5c3a82228566ea7cc1d012bf56dea0a40c5a64c +a0ed026528d9a8bb3201bc9dcd20598933e8c72fd315deea8da63d06e97392aa729d98a55a8a60fa4d5573513ba5c9fe +b723fcd04cddbd4c36feae827a03746ffef251c4f4c55a88beedaeeee194430a99f566f483668a0d88b13e7a4a37f1de +84a2cdceed44828c7c05a6a762edec0165e434e7029df617d6646aba48776e6c3b823f40689cee136536f8c93e08a629 +b786264e3a237ac3a1d56c9f4e87438dfed620c867100fd38b01287f5b755c7820937403bfb86644e082094d3e410a00 +92cc35b2065fca157c7bba54410f8bd85907a01c9f760aa0ddb7a82cb55811d24cb4dc6b725367a6a1c293b809a48ead +a12bbf22b117f00164a42515bc57cc9e6c43cc77fb737ee3d0c0cad94cb50cd3847d61cab469cf8ca76f7958bdcfc771 +85985b00de533bde2a757eddf53be79ea39091d16af3fc92327bcd1cd59bf2bf4411a334da29ad775e8ffaf3cea7d7b8 +af9eb24185b0d330d0ea1d0b0fa78af0dcf42ced81cb0128f16cafdea687a9c5582bb6d7c5744117b271cd0b3303f0b5 +8c8aaa1d85ed6327f85d579767c7a9158d209171b3efcb3e8a9d9e534c078e821b6aade255101d2c9ef6d67ba66f10be +a450518a03ffb40e1df89e0f88fd55b5b06f4872cdfb7ec55f40dc40d9424b3b289866336c195bdd54597d95569e0096 +81e61cc69f93c435bd77f155e80626a9c764dd92b6c76af15c41346527948d8a6ca87d6351a0fe7987e2ee3aa66a9625 +b615e0cebf4fdff4cb23a20c8389c370915ba26aa703b28efe4ab070b1603d1c5b6541684acf46b52a915f6aee447539 +a7f51885c7a71885cc84ef734ecd107e8bf5f7a25131415f671d143cc1de92859e65001125323c7985799993af6c410d +abfbf7a46f32066989c32f774edcc68163f085ca81e94fe8c9fb32f8d451bbb2c20ac45cd8d97f9e618ab40186933b1a +8cf35a522b5cac1934004aa9dd236bc77198d43272888afa860cfc79b4b28dabf7a3c74098f84510897566fdd609aa45 +86aa927df78f7a06a4985eb0a4f0b93529cef14f9fd2812d46abffbf25e618ead14d99c70e3c3bb2e17f3f7fabc9c264 +860f1b4f4a398e9a8bb4739587cf96979cfbbe1687b7e91e5bd1198db726391b09b1a261bf12e96698818f60b5bd3537 +8e7c4ee19ff115881051e8637dce1f5d6c65e865d0c757e8ce41b6d7bcd86c7070cce60649692bbf28c868c7e2e1e2f4 +acf7ba01b0220419f09169ac8d16e5cc13dce08e88c90b8fdfaa33aab417f011a20b79a178d8a9f7211589d2e0affd7d +b404bde8e715aefbb9f20a353b911b79173ef3e2cf0aba98b5ae6190b90597d65043b0b4e014ad9ea6c77da2d213ea12 +97e3615d1c77a402253bb55da2d1cdf82de316cefffe42b1022c94b4818d6dc4a313731db85321c537914bdf716a875c +940e950b96a4096a578c6874d747515936652b9b113a5f27f5a834a610867b05f9881e2679b0b289b8527baa0009b6dd +8de15a13ca236a3a285ce6e6826c502ae7365bbe468b6e8ac67b15b0bb49be0e996f1eec81ef69e4b7f54f8e4779a054 +a12244777eacb08ecd42b5676b3a51153022ab97e9353ace0f47c6054c22de9ba60d2a60f59a36841c2a791cb1b7c288 +94f7580203e39a2642ee2e7c969b9911f011d7f3a90c398e1302d26edb3df03df1d0c43baa1c6cf90dde95296d49e742 +82ead33144aaecab965faf63af384565992f38fc1066e71e33d53f43ac93892e27fe78c4eaca1cccbc53364e26ff31e9 +a0c129e9706d354249a7f8aa664ccd7ede89aa1445c5547410814b56d10dc086720953363ab1da8ff5f1ed5d8e575104 +93b3057bf3f74edc95237781ae012cc4b1d3fd0455565ceaac7110290aa518ac32478ba4eb9851555fa87270fcc84f1f +949c2fd0b94f31f7cbf00c679bd3f6ec1a2f4056654708d39edf1a450b4e19a6e251d0bb24eb765087e698f61d3fca2c +99fd2e50e211ccb66b895eb2fc42f260f3ad5767f04c2fe238b81dae98aa6e3977443a51f4fe7b43f499caabe45699a5 +84fe19626503218f327b5325bfd7c0c3d2614b47d34964aa0259d564e769c6c81502132cc1765b0b31fbe39852706927 +b43287ec29d9010bec4284de58fed48dd1e129bac79f09d45153c9949131782f77b11b0c9f8ee06a39e5e9bbaa8e2c6d +908902f3ed45482df2f94415fc8e5a308057a40c8905d7cbbd58ec4848e19276577b7f7e69e5e684a8b981738e10f7ef +85cc7d9c1eae372b4f88758cd6e21604b4bc9f0794e1e74b6d9de96347f81944d01331385fae7a38e5f6096c1dc23465 +af60288c702082fc258b3dbd6952c6b75c1641a623905f491b1e72f49b9d39b33d150a336450abd3911a4c128166acdf +a7d8ac7e589558c4014369ab6f4c1f2196205b03e4278152ec0dbbd7ba54e803c3369a71d364a773aac8dbbd117e4a13 +9833aed34e48c206e9328073597aee1123f5bec085339b4e6839a389a429bf3042798a31fac1464ce963204adface76b +84631a4f012bbb62133030224b57deb32dcf464cacc8ffde7775adbe68707263ab5527a1c75e597e03aa703ba658b889 +a686a61f6467858a2a4c13e70ad81b1901290d3e51bbc0c6e366f9e652f575e91b11c75f640ccef8b0c6c1b05a43c9a0 +b585f0ffd5144907703b41539bfad7f9f058f5985f63db911064ba6b07af8da2796b84b16db42b8d11135c3f846cd9e2 +b525539516c7bb25f1d7e165f269dc8c9eedbba74df44887e178ab8fd798e2a31f39812ca922d6b64d91564f14012a64 +91e480d7568fd2fae39c35b0a8d623e66a3160fee1dd4e9097255004938b11ac1cd3918dc6a1e5fbcb700c95a547e5e8 +936ef55c69b842b6177de71fa48dc5442bf5132116b214302f8f242ca36a273a6bbfbfaf373777104dadbe8e7da5e970 +8e950c0f6688abdff8a3b8bd77be6da6f2565c7b55711f5860ea62a3ab1d51aac31821c602bc11a45e33c69e7dde3ea4 +90eed4595104a0527f8db1e028ff622ff70db4eae99cf47f6c2a0246ec7b103570a6a9a877e32e9647cc74969006743d +b756344f6c4ea05b792e416d9bd9ce9dd4bd904e7622761f28a85628506bfc9d88a25e5f04db62fad30a92fb1d8d8556 +ad79ba76534c1a02ac3e9b7308d390792984cd75b7e1d0e5e4ff123642d99d4ea1825643091aa8117336333c40d5bd94 +832b08144887de0c0341d84f6945450af8d7a4eb32367d7703118186c1be525df9382ce61fed5f3b65a0bb3449185f7f +a322fb944e46d8e47994820890c94af423674716da810ea1da71e0a7733ad72c22114ca39a4b59c98ce4291a5684c154 +b982851a65140dbea79bd3b5487e236feccee051deddcc17c2853032efca289ddb6eaf64be3dd85a73012fdbe9d2d4f3 +8eed5e230e201830b44b9fadca4e156fe1a16bf840cf29da0f381ea0587b20c226de2465c67e6268973e776809af68e1 +81c8f1c04490f36e41a53ee1b5185cb8adbb37c258fd6c3be8c56835bf574c37183a94d55b6554fca35d6e6dd9af0133 +8c4928724107cc16d36f2976677eac0b852fc4c3c0bb2f9cd4d59cd24a113faf33b2faf405c3fcce25be51d41e42c2c4 +8e4ba842636fdfc4d71f0983538ea5037d420acd26abd12efca48c252eea85544b2fa9fccdfec4e7c2a6359baffa112d +b4315b84700e26dec26f3488d308430fdff4809c10d4c24309627911cbb769ffaad0d1ecccd622dd02194eaf5ba59f91 +ab888308f757faef32648c1db01650dbc9aea248b09d06e6efcc996d395f48ec96f2d54a02de441d753fe8737862d991 +805094cfd77e207d5c75f3cad99f41f763ec15443052cfd758c6a82ba422d831a1103a7f9b100da49c28198279c3d3dc +ad857f33243e4a2cd2a773700def21fc7f94939d1a6d2c2125ecd58fc206ccafb07a2c02a1cfce19857d3654aca2c70c +a4d12d40149953daa70b89a329e918e9d93efb4e8004a9357fe76682dab9662c8507e16db83e849340f05cdb4933a373 +a0dbac2ed4b5d03606524245e8a31080eb5bd3e9a0c51dad88c3b18e3e6bc5d64953a81c8e60425b80107ee6b62b1fb4 +86da05355900f327164a78901f6e3db857531b33b1e855df1a67a9ba222c6b05fdb6b0ffbacaeb1ba5b45ff8979b6b68 +932c9873aa3e226dd922b5a616c75153bd0390ce8f332a414b9c8cb6606c2501a37a2aa88097bc7d8e2c4261706eb38c +accd9cdf07ccdd42033ce3b105e00bfd39e2304b1e3d66f8b1128645634452c20f759ec45adcef2fdf04408f62c4cc04 +b75cfdfc1cb48918752eab17eb579820ee6e71e6667abdb64df834ffc8c1362fbbc23ca2c80dee248fe1fbb72d87dfc8 +88b998c73b00638fde7d3dd650a08c5ab996dac6ac34251337fbff3fb5ae4a25dd20c1a16c987ad7ded19eca23cea891 +8afef0956c942571a27f504553fb312cca9e50ce41b44e0466d0516c5abe4d8acf4594cdb03b1ccdbe3f2e6a9093b713 +9042cd83c5ff261e9ebda26398caa16cac2cb840d19062fa8ae50e044c27104972948318f4c866dc4d578798272d3e49 +ad536719a64570a2cd1d72b6590ea1d02c8c49f259a7867be26c8191445165954bcfad50ea12688ace3fdfb0e98143bd +97c86328d63d297b6bc9718dc1ad5a05b908a750d1c455c700d84315589128ce4eea958aef2bcf0fcf4adbd8e3ce58d1 +8e592cf0802e6a9541eeb654dc55055e11f3d757847285197132935ca35bbb1a9156829a39384dfa6f645ff89eb36738 +ac16c614998944f77590bf3913a010e13f2d3bbf6a172293baf5983506c1a2d89989fb72e598f5bba1ea10a691377c93 +ab8e6f5b46baa6632de3621497bcbdd584decb999fe7d8a3364843a1e0b76497600630b6a24dd30119d8bcbfca29f335 +abe1d3af5279e60122d9cea8cc6581c819d7a0e20e3715da0f6da7e02d13a7653db643bd946e2fa9ba338eca81fbe140 +8c33bd831ecfb18d1d0713e16beba768e9c42df62170c1f8a16764912be77f2ac5915623d1d25e8c462aa9c2f6669ca4 +903692becae4a6409f7bdb127d9b11de57a5739fe24218dcbaa0092648d5332dfeef29a908ee9e43e5e0a51a4c3639bc +92591e90347ae286acd365eba32cd9ad8f20f4c9cad2dc579b195147ff290adf0d776bcb3d4b04a25d68a941fc0c781b +b64bbccf860299aec16e1f95c768a1f337c740bde612e6ba260e393edb8b04540127194761c42597abb9bcb771c576c3 +9194f056ccfdfeb78a11c5347e2255d7a7ebd1251f9aebc0b58feb68d3e03a7dbbb74e3ef7309455853adfb4694bd01a +aa4f15f6d6a53ae65b7f6f91e8981d07a5919d2138679a561f7bb608dc4596e45ca06c9441d51fb678b2ad89ae7a17ae +90e3d18507beb30bde08c5001faf489a19ab545c177efb3f73fbf5605f9a0abcdc8bfbc44f832d6028e3e0a834bea98f +8f31dc0118c8c88a6e79e502d10e57652b7aba8409a5bf572ca63fed6b7cbad7f28bbc92ac2264f649792fc1d0715085 +a307d1067ea4c56437b6f8913aa8fcbf4a24580fc1e3336e7f6518f0f3adb9c4733090e459a3f737414ec0048179c30a +b7cc41fdf89595cd81a821669be712cd75f3a6c7a18f95da7d7a73de4f51bb0b44771c1f7cd3cd949e6f711313308716 +a9dc74e197fe60e8c0db06b18f8fe536381946edecdf31e9bd90e1ebfcad7f361544884e2fe83c23b5632912ec284faf +8b3e1e81326d611567e26ed29108f33ddb838c45bbd1355b3ae7e5d463612af64b63fff9fa8e6f2c14c8806021a5a080 +92f6537bca12778866335acc1eb4c3dfc2c8e7e5cf03399743dcea46aa66cac92ac2963b0892784263ad0ebe26ffdbf6 +b5cc0061f7a3e41513199c7dd91ac60d727366482a4c7328527f7bd4fc3509412f711bb722b4413b3736a219b843d15d +b3e9711d68d2c6f6e2cc27e385d5f603d9a1c9a96edeefa1ffdf390439954d19504d6aadc566b47e229ad4940ef020d2 +a09d0d3f0e5dc73a4a0827b72710b514bbfce4a7fcd5141d498a5aad6c38071077f50d3f91af897d9ab677b7041dedda +b177fe260f3b86e9ac21f1bfbe2682ae5dd8c9aecebb84f37054bdab6e39094e611ce582210ceeddde66adf759dadb6d +b0ac6595eba9f5dc4b2fd21856267cfbcfb5b12aa34ec69ca32b80071c5b652e85c25a224d80443d503bf25fbbfe07e9 +81f3c0e11b196bd4a2e8f07f8c037002566dc9037da81f3988add458a520c24dd1be3d43d851e28c0c6a85de4b57a542 +a44308c95615f7fedb2d2127012924468c015df9f48359cc2e36ab4223870b0bfc1e9040baabefdf5266f93afaad896b +8493ec4c32d5a13b81039f1b436eb83f259945dc950e3c6c2ccf5087ec56dd2f60890ed4edf01728b6a54950e19b35c6 +a1a439ec2a6a95bdac9aaa925ff337ba956c0d236ab5318354270e73ed6b73b4ae2d27b4c1686cf97b6526d04e65be81 +b4659b7b53c55a4b2bbe210b53520b392f893500e18990d843b72d7379d45fb44dd1dd2184348d6fd853d6b9ecc6b7c6 +afb2c68d75d00130b0e1b4f250001920213121791698ec04262db714cf7b1408d39f6cc10421f954845aad5b8250b77e +b22b843b40a97210f94043b552f348f66743055a3f274856a738e7d90a625b80e9bbb80cbbb450e1666eb56b8bd5c60f +800895ced82fe13d5fff65a93b0051c3df698bf1221b682accfdb63e3970f669ca37025750697f4e8ff2a3322ad57be4 +b21f598c50d7b9f4a584d548f85e42055ef8e24991906d973749090261584c7f4f5e984b528926f7e75375dd84d51af8 +849b1c68192d18274598dd6d0bf48fb5ee3b1ba25b331cff2d06f345bef3bed49760ca5690848cf33388f6a9a32cd646 +aeb6fd9478b10ef456f6bbb1e6dd19b14475e65497772d12cfc097948383d3fbd191bf95f046b8bf1989954118e483d0 +b1b5e0ea2835f7fc8b66e7731e392b43d16cbce04b52906b6751ab1b91978899db5fecbdabc23a19dabb253005468136 +91b6b1284770cf6f7ef35bc0b872b76c7763ffcfa68f9c8cfabcb2f264a66d47598bb9293f6a40f4c3dd33c265f45176 +b9ffed029846487c2cfb8a4bb61782bd8a878f3afdb73c377a0ebe63139fa070e3fcdc583eec3a53fdc5a421ff1fa877 +998007249d041b0b40ff546131cfc86d0b3598dcedf9a8778a223f7ed68ba4833b97324cbb1de91292b8ff51beab44b3 +8eb77ce9e0e406bf6f002870fb2fd1447646dd240df9bd485f8e0869298a1fc799d8a41b130c04370e9a9cc5c7540ca5 +853db8157462c46f2af7e8f94f2ed1c9b9a7ba2896b4973296898ff3d523d6e29e0b63a5d26cecd5e490b33c87a4cecf +b1436b6f3278768f0979ee852944258f2599977d255bea6fc912ba17c5dff5bdc850cf3e1fc52be9d6d188e868670f4f +a76acbc5832019b3b35667ab027feff49f01199a80016620f5c463dfcbfb51bf276ed17b7b683158ba450660cc7973eb +94540cdb051faf3ae8b8c52662868c2dab66bd02505c4f5f8eb4d6b2e2e5fd9a610890c5dcf8fd887eee796d2b5753a8 +aa35099666bceccf4eb3b65b13bba88e30a8be93693ab6761d8e5523343e8d6dd42d977e66499352fe4e9e9784a1dd0d +894471aad17be54319083c4b5e40adcfacf7c36c4aab0b671030b7ef321c53590a25eccd836efd20f32a93185fd315bb +8f52a9f705bb0dea958fcfbd52e2b6c08ad0f89a07a6b2942c1b4c37eead0d97a38a9e9aeb08d5d59b7fa2a9347f738b +9031c16b4f936c9cab55585dc5064739f696c3347ee2c0792320c9f749e760d120e396e8485ffc79d81c9f3337ad3d1c +82090a0d0d9b05459ec1c328ecd4707c333b784e3aaa0ef0072cee1eac83f9a653a75d83b9f63512a8c41200494826b4 +92c3a9553001f9ea4d67236b8ad1a33275378202cc1babc03f313895458f4b2549bfbbbdd37bfb8fbff0decb6b9f820a +88651868f4da37338a22bc553388df5dd1dd0cb78c4d7d07c637d8f6faef4bed72476fdcd4304d5bedf3514011135f08 +83fa0141bfebd88063f1d787719721b4c6b19ecf565b866de9d7d5d1a890e0e3d859b364bb65f8f8e688654456a40263 +90a7fab753e5d56dfc0e53a6b4e6ab14508220f3a62b3f3f30570c4c9ad225e74122635826c92e8e3227ec45e551432a +8fa375b0345bf6e5e062d108f9feaec91029345ecac67ccf1264eac77b8654cbfdda1f10579f481889c0e210254eadde +b83f06116da9daebdb013b26724523f077debaf6bc618b48a7a68858a98d275f7899c4ec73a0a827219b9248dd81c8c9 +8be1cada55e0c5ebb4fd460b2d209ae5326285a20c8bdd54ed9d1a87302f4063c8730bfda52d9d40e0d6fe43a0628465 +a68ad6f813743ec13a811f2ef3982c82d9d9ac1f7733936aa1e122f8dc7f4a305cc221579ab8fc170c3f123a1576f9ab +8878f1128214fdbbb8a0edd85223741e021508ab6d36c50d38680f2951ee713ea056ed03f62b9461897963d50ceefe0b +acc0d43d1b0260528b7425b260a5dea445b232b37240759fc65fe26f7c9d8e51569c5722bc33e94de6492f4ba1783504 +ad80b1dd717b076910ee5ceabcb762e75e4d094dc83b93b65c16de1f75bc712cef223c05d5579c1561829406c07a97d9 +a6fc9803f9c09d95fc326cc284f42ea5566255eb215dba8a9afb0be155ea11bcc55938b2d16f01cd2f2eda218c715efb +83ad733dbdfbaae8095a403dbf09130513f4ed4f08dcf8dd76ce83d1ea72999b7eea3a7b731da0d2bc80a83c6ee0e3e0 +8748912fbd08cb34a85416b0937d9c4327e9eed20d6e30aeb024a7253f14f1e0d774f3326e54738d71aae080e28da0fe +8997e78d8acf23051428af67183ae9b2c4aa42b503745ffe33df35a35103c589987e1473ab14dcd28ee78ebcb10d8e95 +a2f340502a7eb3c4a36412e6f028321372c4fa18a4743945607424e932af1271fa3e6598a162c872072529576eba6283 +868ccf19b5044ab93b45c9ed3ae34fcb504fe1453d6c4a1d12c325032cf01eb90356de82080ed897e97dba13cae33a02 +ac8867005fe4354d67aa37b866a7e581d2f94f7bd0b9f4efb5c2d1370ec13147a60692051b02fd00ae60b512bce9b1ff +8fd01886b046819c83c12bb779e432b25ba13713f9227be702074ec3abb2bba6be37220a0a26a4bd4171b99b14e32bc4 +a128981ed199f92b5959975c150a93a62fec50b61c80a3fa0634d90fc8058f76f5cbee77aae6889af12d296b30e613cd +81fe618552ff7a36c9235c6d4066cf2f930b5b38de4089e18166e4a06ca5723eadd1976d25e34b74b3ce942300b23e5b +ab1223ea049e6e0fbf9b611de7fd7c15e5e9637cbd73aa0e36aea08a7503ba6804f2aa807186fdc9aa7f4f9195f72e24 +b97285286981b2665f898abc13f3243b63005bef8db4cab3f658bf6167036b61af400f08db0fc3c640a9c623b760690d +ae3ddff7c1f0fbb6a13dbbc667a61e863c2c7c51c2051e33cd61620142e7e30a7e0c4c1f8fbb512aa3a8640267c6ac26 +99c2a89d5bef236060e51c4f952664094c20fbfca647e5d24a55c1fb8df2f3df58244fbbf3635db07b1c29ee3234fa6f +a5010764d4b9cd3b410638334d1f70c5f4843f45b4f4a9316aaea5fbb2c510a97449dd7a07b49f47334a69d37d9955d3 +86706d011dcdc9e9d165d01fea1df68dd74bedaf15a39f92893c030cafe96f4498c4c1fec2d2136354341b3f440a1462 +88fd57eb62bd7dc35722f3a0576c2138403a2f663a2603482e8974a895cf56ddbb02657dc6b89eb2cf5c1f9d1aff6426 +b0dfd4c68e3acb6bb8a776adaa421fc5e268ed4d5964bb90a727091e5113b55b3f9c6d33cedb3ee47ff7acc5df8b1749 +93b92bc942e1a636fc5c2dc1840de5faf158a113d640d5a475b48e2c56ccccaf9db0e37e90ce74c4b3f5c9ac3b2eb523 +b29a16fa1ea95cbfc1873c435ad40dc8495ba6341801b72bd95d908147dcffb1b4bb426dd635f3af4c88984f56594dd8 +b8f367105e1a2d554ac30200c66aeb579d3d30a8953d20fb6ebba2d876ec39c52ea5d654f1bb89b8ddf3d9d651f31cdf +b5fbc228c983d08adf8612eba5b3db3acff604439226f86aa133b02cce4ffde2f977c8dbb8b446b4375673f71634c89d +a399bea37d3056e0559f6644faa0af93063b4b545d504d7e228d3dbbc294af83d3c4cf37fe026b63899b4e7d50fd08f5 +928ef411a36414b24aea26fdbed4bdb1bb6bdc2d967e2553ce54c7c4e077e76869cea590257645c9129dd55ce025295c +9684a4adeed416a9ce82ad79b55c4a3adcfbd43950bc442ed8a340381caedb70f4baaaf821e3a152f483f965d8f56162 +92558a37f214d6f4cb6d72cd2f4ad24dff9d17611b9e4a41ee5c741a5d1ca9e4053b0584533ef4da206110b5dc3e2a35 +973bf0724d1785cc5e85d2a8ee8c354ad4cf557217ced0b7940f6f064024c20b2bfc5b144c820b5083da4bf70690de4d +adaf1389dfa528210ca9c2657c5ff10d51f7e3b18e93a59c37211be0506c3576cb2c04ec80cd0f82605e53c5a3556620 +85b58b223b09fda6f3ab674d75e780c49eb2167837243df049281e8f4fed653811138b398db9cdfe7405fdb8485602fe +849504d3db408d80745a07e850b0a804607b91a59922a5d3bc40da2748c029c029419cda38d2a4485cc0824c6b2504f0 +a3f4afcb353bc2582a02be758ebf0cd18752410ca2e64231176bfa23828423e0a450a65f241a9ed8eab36cae8d9c567b +ae362786cdf121206537af9590d330abbc6dc328b53cdd145dbed0e5df1364c816aae757c4c81f9d619e3698dd32bcdf +9024cfa5b0101eb02ab97866d5a3832944e5aa6888484cfba3d856576b920787b364fba5956bd7c68a305afedc958201 +8a116df09fed923acefb2aecf38a4fbc4b973ee964d67f03791d70bee6356af43ffca117d4e9463ffaf0e0d5d5e5a69f +9163016175c73f1bbc912ddfe03bd4e1db19c64951c8909ee6befe71a1249d838e0db49f03670bb4c5c9b2ab0fb4fef3 +8f6357318d8d16e7240a02b05ce5a4976b6079d49daa258789c6dbf4a47950ebe9de6411780fab06c7c1f35651433380 +8e63cbae8be7341892dbedee3111adf0307c4ee9e375181aa53478f5ba9cdce164d6ae890e5f480119a3a51c6e989165 +a9782f30674a4874d91bfba7eda63aeb5dbe66b040c768d6a925d8ee135f0655ea56276b105239cc0668fc91ddb68cd1 +8d9d94b61ab84ec08665cbe0244ea41756785df019e453ef078c19380bd44c39d2958e8465c72eacf41eed5696037805 +b1470e6f5d2e314474937cb5a3bc30c8bf5fc3f79014945f6ee895fe20028ffc272f9d3a7320aac93e36c96d8a5454e3 +a444911bbafc71179766594f3606b6eaff041826607fd3192f62dec05cd0f01b78598609a530f6930e8440db66f76713 +a9823d44e2638fca7bcc8796cc91c3eb17f46ad6db9f7f6510e093727614aa3a4f9b2c4011ef91dc1c2d224d08d8d05b +ab86020972c359ab98294212558b4b14862040139876c67fc494184b5c9bcea1dbe32fe0c8dd9e60be9daa304acd599a +b7e5cb685bbdcfdb1e48259a5d68d047846c8a35c5b3f90172fb183d1df40d22eaf0edaca2761a07c29c577000ccfed0 +8c88319dae4b28989817e79e6667fd891181e8d2ed91b9c6b614985bca14b12982462ec58b17be0463c24bbb79dd62a1 +8c1c6867e7107fb2178157c991b9c8b0f90c8d57a51220bf3650438ccabccf62da4db8a9916491e730ff3d0c106496e3 +a00a79bd58da6528b9af033087260f9f3d00519eafb4746b355204ee994e89481591b508eaa5402821083e250d38467b +8785abd7c37690f6aa870ee5c799eef72e398a7898b6767f698515be277b9c2fc1af12ea89b0620a848221343a3b5ec3 +8aadae68543db65cef71d0e230a09508d72061398ef2fabec0f856aacff2125b79c70e620744aaf331faf3dfc8afb9bc +8ff0cd437fcad9630b8a2333176a55e178db4142ec841581590594d74d5b53baeac5fb903fdf7bcf83e245b95b58285e +af274e8fad6b190be4e5dc92d2705ba6ac0d7e1ea29e958a5cdd4cb764de46a56d9eef62c999a16e7c50a50b2d9fe3a8 +865e6ec7d1aa848786d6a7a4e87a24d442311f0810b01ef5a74928ab59fdfd651e48880b49680047e5b0df6b3c7c2ecc +800706baaeb35bf3bc33bdea9a8b5cb00d82df407b3b7e1b781a9359cf44fb410ed311591080181b768aae223d9246aa +a9496389d0780b309c6998374ae159f58a8d0fe9a1c24c36cebcb45b27d818e653b51a8ee1f01e30a9b2c46a548126ef +b5fccf4fc3186661939fbee2e89c2aa0e3a6ad4907bcc98c7750520540c4c183b1bbfcdf47f2f1c5e75c3a30cdf30c75 +a90028e39081b736e628c2230cc1338f9210ed01309a40fdf08d39c10cced2cdf71271013bea6dba3a0444fe47963106 +a0815cbb325a8fecf2e1bcc5046644be32d43a8001bd5d8cf0022e4572cd0d481b3e717002f7ab21e16da5f5d16886d6 +b2024787fcda52abc4138150f15e81f4a5be442929b1651ddccbfd558029912be4d61c3c9b467605fff640edf7392494 +ab5aa60032304a584cc9245a33f528eae7157808dedd1ad83ebae00aadc25dbe1cd5917eb8b6b2c800df15e67bdd4c4d +866643847ef512c5119f2f6e4e3b8d3f4abb885f530bb16fcef0edb698a5b0768905e51536283925b6795a5e68b60ddc +806aa99c9a46ee11cc3ebf0db2344b7515db8c45b09a46a85f8b2082940a6f7263f3c9b12214116c88310e706f8e973a +a6eada8b9ff3cd010f3174f3d894eb8bb19efdbff4c6d88976514a5b9968b0f1827d8ac4fe510fb0ba92b64583734a1e +98480db817c3abbc8b7baedf9bf5674ec4afcfd0cd0fd670363510a426dad1bcf1b1cb3bf0f1860e54530deb99460291 +81ab480187af4a3dfbc87be29eca39b342a7e8e1d1df3fc61985e0e43d8d116b8eac2f1021bde4ae4e5e3606c1b67a21 +8a37df12dc997bf9b800f8fd581a614a1d5e32b843f067d63d1ca7fde2e229d24413d3a8308ec1e8389bf88154adb517 +b045a55ca0bb505bd5e8fcc4cfdd5e9af1a7d5fe7a797c7ede3f0b09712b37f493d3fcf6ef0e759d7e0157db1f583c95 +ad502e53a50691238323642e1d8b519b3c2c2f0fd6a0dd29de231f453be730cf1adc672887d97df42af0a300f7631087 +80597648f10c6d8fcd7421caf4e7f126179633078a1724817d2adc41b783723f302eabc947a7ba7767166dacf4ce8fa1 +aefb56427966c81081999dffbe89f8a0c402041929cd4e83d6612866cfbb97744f4ab802578349fbecc641fa9955e81b +a340e493fb3fb604eab864d4b18a6e40ba657003f1f88787e88e48b995da3d0ab4926ce438bdc8d100a41912a47dace0 +a6d777bfc0895eac541a092e14499ff8bf7156689d916a678b50a1460583b38e68158984bea113a0a8e970d8a6799a85 +90ce469410f0e8cfff40472817eb445770833cdcf2895a69bc32bcf959854d41712599ceb2b0422008d7300b05e62e02 +815c51be91d8516d5adc2fd61b6600957ed07cf5fdc809aa652b059bea8ed179638a19077a3f040334032f0e7900ac8b +b3ec6c0c3c007c49c6b7f7fc2ffd3d3a41cdff5ad3ac40831f53bfc0c799ffeed5f440a27acc5f64432e847cc17dd82e +823637abeab5fb19e4810b045254558d98828126e9a2d5895a34b9e4b4f49ab0a5b3ee2422f1f378995ea05df5516057 +ac05412bcf46c254f6548d8107a63928bba19ab6889de5d331eb68cf4d8ce206055b83af4cb7c6c23b50188391e93f84 +88514163c587068178302bc56e9a8b3ad2fa62afd405db92f2478bb730101358c99c0fe40020eeed818c4e251007de9c +b1e657d0f7772795b3f5a84317b889e8ded7a08ea5beb2ab437bebf56bcb508ae7215742819ed1e4ae3969995fe3b35d +a727d4f03027fe858656ca5c51240a65924915bd8bd7ffa3cfc8314a03594738234df717e78bb55a7add61a0a4501836 +b601682830fc4d48ece2bdc9f1a1d5b9a2879c40c46135f00c2c3ae1187c821412f0f0cfbc83d4e144ddd7b702ca8e78 +b5cfea436aa1f29c4446979272a8637cb277f282825674ddb3acac2c280662fb119e6b2bdd52c4b8dbf2c39b1d2070d6 +85c211645ff746669f60aa314093703b9045966604c6aa75aae28422621b256c0c2be835b87e87a00d3f144e8ab7b5f0 +867628d25bab4cb85d448fd50fdd117be1decdd57292e194a8baa0655978fae551912851660a1d5b9de7a2afbb88ef5c +a4e79c55d1b13c959ff93ddcf1747722c6312a7941a3b49f79006b3165334bab369e5469f1bddebadb12bfaff53806d5 +ac61f0973e84546487c5da7991209526c380e3731925b93228d93a93bce1283a3e0807152354f5fe7f3ea44fc447f8fe +a1aa676735a73a671a4e10de2078fd2725660052aa344ca2eb4d56ee0fd04552fe9873ee14a85b09c55708443182183a +8e2f13269f0a264ef2b772d24425bef5b9aa7ea5bbfbefbcc5fd2a5efd4927641c3d2374d0548439a9f6302d7e4ba149 +b0aacdaf27548d4f9de6e1ec3ad80e196761e3fb07c440909524a83880d78c93465aea13040e99de0e60340e5a5503cd +a41b25ae64f66de4726013538411d0ac10fdb974420352f2adb6ce2dcad7b762fd7982c8062a9bac85cdfcc4b577fd18 +b32d87d5d551f93a16ec983fd4ef9c0efcdae4f5e242ce558e77bcde8e472a0df666875af0aeec1a7c10daebebab76ea +b8515795775856e25899e487bf4e5c2b49e04b7fbe40cb3b5c25378bcccde11971da280e8b7ba44d72b8436e2066e20f +91769a608c9a32f39ca9d14d5451e10071de2fd6b0baec9a541c8fad22da75ed4946e7f8b081f79cc2a67bd2452066a9 +87b1e6dbca2b9dbc8ce67fd2f54ffe96dfcce9609210a674a4cb47dd71a8d95a5a24191d87ba4effa4a84d7db51f9ba0 +a95accf3dbcbf3798bab280cabe46e3e3688c5db29944dbe8f9bd8559d70352b0cfac023852adc67c73ce203cbb00a81 +a835f8ce7a8aa772c3d7cfe35971c33fc36aa3333b8fae5225787533a1e4839a36c84c0949410bb6aace6d4085588b1e +8ef7faa2cf93889e7a291713ab39b3a20875576a34a8072a133fed01046f8093ace6b858463e1e8a7f923d57e4e1bc38 +969ecd85643a16d937f148e15fb56c9550aefd68a638425de5058333e8c0f94b1df338eaab1bd683190bfde68460622b +8982f4c76b782b9b47a9c5aeb135278e5c991b1558e47b79328c4fae4b30b2b20c01204ff1afb62b7797879d9dee48e2 +b5098b7ba813178ced68f873c8c223e23a3283d9f1a061c95b68f37310bca4b2934a3a725fff1de1341c79bb3ba6007e +97b160787009f7b9649ed63db9387d48a669e17b2aba8656792eb4f5685bb8e6386f275476b4dfbb1b4cb0c2a69bc752 +88b69369c71daad6b84fa51a0f64a6962d8c77e555b13c035ad6fa1038e7190af455b1bd61ae328b65d6a14cf3d5f0d5 +af88b87801361f0de26bd2533554ee6f4d8067e3122b54161c313c52cc9eafea00661c5c43e2d533485d1f26da4e5510 +98ab18e3bbcb23ac1e34439849e56009bb765ab2f2558ebfd0a57cbe742169f114bceb930533fb911b22cb5a8fe172bc +9027507f1725d81e5ac0f0854c89ab627df3020fe928cb8745f887bf3310086c58fca1119fd5cd18a7d3561c042d58de +a676583f8a26e6f8991a0791916ce785b596ce372812f5eb7b4243ba9367ea95c797170fdac5b0c5e6b7f6519cc2b026 +b91b0ab32638aef3365035a41c6068e36d2303bfee8640565e16c9a56c21703270fd45946ce663238a72c053eb3f2230 +aaf4cd1ac0a30906dcd2b66b37848c6cc443da511e0b0367fd792887fdaf1500551590440e61d837dbee9d24c9801108 +a06f20a02d3cd76029baad5a12592f181738378a83a95e90470fa7cc82a5ae9d2ed824a20eeb1e96e6edc0619f298688 +a465d379c3481b294efc3f2f940b651c45579607cf72d143b99705eae42103a0279eb3595966453130e18935265e35d6 +892a8af7816a806295278027a956663ea1297118ede0f2a7e670483b81fb14dccacc7a652e12f160e531d806ca5f2861 +b480917c0e8b6e00de11b4416a20af6c48a343450a32ee43224559d30e1fecdece52cc699493e1754c0571b84f6c02c2 +b3182da84c81e5a52e22cebed985b0efc3056350ec59e8646e7fd984cdb32e6ac14e76609d0ffaca204a7a3c20e9f95d +a04ea6392f3b5a176fa797ddec3214946962b84a8f729ffbd01ca65767ff6237da8147fc9dc7dd88662ad0faefdb538c +95c0d10a9ba2b0eb1fd7aa60c743b6cf333bb7f3d7adedce055d6cd35b755d326bf9102afabb1634f209d8dacfd47f1a +a1a583d28b07601541fa666767f4f45c954431f8f3cc3f96380364c5044ff9f64114160e5002fb2bbc20812b8cbd36cb +a1a0708af5034545e8fcc771f41e14dff421eed08b4606f6d051f2d7799efd00d3a59a1b9a811fa4eddf5682e63102ea +ab27c7f54096483dd85c866cfb347166abe179dc5ffaca0c29cf3bfe5166864c7fa5f954c919b3ba00bdbab38e03407d +ac8c82271c8ca71125b380ed6c61b326c1cfe5664ccd7f52820e11f2bea334b6f60b1cf1d31599ed94d8218aa6fbf546 +a015ea84237d6aa2adb677ce1ff8a137ef48b460afaca20ae826a53d7e731320ebdd9ee836de7d812178bec010dd6799 +925418cda78a56c5b15d0f2dc66f720bda2885f15ffafb02ce9c9eed7167e68c04ad6ae5aa09c8c1c2f387aa39ad6d1b +87c00bba80a965b3742deacafb269ca94ead4eb57fdb3ed28e776b1d0989e1b1dba289019cfb1a0f849e58668a4f1552 +948d492db131ca194f4e6f9ae1ea6ebc46ebbed5d11f1f305d3d90d6b4995b1218b9606d114f48282a15661a8a8051ca +8179617d64306417d6865add8b7be8452f1759721f97d737ef8a3c90da6551034049af781b6686b2ea99f87d376bce64 +918e3da425b7c41e195ed7b726fa26b15a64299fe12a3c22f51a2a257e847611ac6cfcc99294317523fc491e1cbe60c4 +a339682a37844d15ca37f753599d0a71eedfbbf7b241f231dd93e5d349c6f7130e0d0b97e6abd2d894f8b701da37cb11 +8fc284f37bee79067f473bc8b6de4258930a21c28ac54aaf00b36f5ac28230474250f3aa6a703b6057f7fb79a203c2c1 +a2c474e3a52a48cd1928e755f610fefa52d557eb67974d02287dbb935c4b9aab7227a325424fed65f8f6d556d8a46812 +99b88390fa856aa1b8e615a53f19c83e083f9b50705d8a15922e7c3e8216f808a4cc80744ca12506b1661d31d8d962e4 +a1cbd03e4d4f58fc4d48fa165d824b77838c224765f35d976d3107d44a6cf41e13f661f0e86f87589292721f4de703fb +b3a5dde8a40e55d8d5532beaa5f734ee8e91eafad3696df92399ae10793a8a10319b6dc53495edcc9b5cfd50a389a086 +996e25e1df5c2203647b9a1744bd1b1811857f742aee0801508457a3575666fcc8fc0c047c2b4341d4b507008cd674c2 +93e0a66039e74e324ee6c38809b3608507c492ef752202fff0b2c0e1261ca28f1790b3af4fdb236f0ed7e963e05c1ec0 +b6084e5818d2d860ac1606d3858329fbad4708f79d51a6f072dc370a21fdb1e1b207b74bc265a8547658bfb6a9569bb3 +a5336126a99c0ecfc890584b2a167922a26cae652dfc96a96ab2faf0bf9842f166b39ceaf396cd3d300d0ebb2e6e0ebf +b8b6f13ce9201decaba76d4eca9b9fa2e7445f9bc7dc9f82c262f49b15a40d45d5335819b71ff2ee40465da47d015c47 +b45df257b40c68b7916b768092e91c72b37d3ed2a44b09bf23102a4f33348849026cb3f9fbb484adfea149e2d2a180ff +a50d38ee017e28021229c4bb7d83dd9cdad27ab3aa38980b2423b96aa3f7dc618e3b23895b0e1379ca20299ff1919bbf +97542cf600d34e4fdc07d074e8054e950708284ed99c96c7f15496937242365c66e323b0e09c49c9c38113096640a1b6 +822d198629697dcd663be9c95ff1b39419eae2463fa7e6d996b2c009d746bedc8333be241850153d16c5276749c10b20 +9217bc14974766ebdfbf6b434dd84b32b04658c8d8d3c31b5ff04199795d1cfad583782fd0c7438df865b81b2f116f9c +93477879fa28a89471a2c65ef6e253f30911da44260833dd51030b7a2130a923770ebd60b9120f551ab373f7d9ed80aa +87d89ff7373f795a3a798f03e58a0f0f0e7deab8db2802863fab84a7be64ae4dcf82ece18c4ddbefccd356262c2e8176 +a3ba26bd31d3cc53ceeced422eb9a63c0383cde9476b5f1902b7fe2b19e0bbf420a2172ac5c8c24f1f5c466eecc615d4 +a0fe061c76c90d84bd4353e52e1ef4b0561919769dbabe1679b08ef6c98dcfb6258f122bb440993d976c0ab38854386b +b3070aa470185cb574b3af6c94b4069068b89bb9f7ea7db0a668df0b5e6aabdfe784581f13f0cf35cd4c67726f139a8c +9365e4cdf25e116cbc4a55de89d609bba0eaf0df2a078e624765509f8f5a862e5da41b81883df086a0e5005ce1576223 +a9036081945e3072fa3b5f022df698a8f78e62ab1e9559c88f9c54e00bc091a547467d5e2c7cbf6bc7396acb96dd2c46 +8309890959fcc2a4b3d7232f9062ee51ece20c7e631a00ec151d6b4d5dfccf14c805ce5f9aa569d74fb13ae25f9a6bbe +b1dc43f07303634157f78e213c2fae99435661cc56a24be536ccbd345ef666798b3ac53c438209b47eb62b91d6fea90a +84eb451e0a74ef14a2c2266ff01bd33d9a91163c71f89d0a9c0b8edfcfe918fc549565509cd96eed5720a438ff55f7f2 +9863b85a10db32c4317b19cc9245492b9389b318cf128d9bbc7ec80a694fcbbd3c0d3189a8cad00cc9290e67e5b361ee +8a150ee474ebe48bdfcac1b29e46ac90dcded8abbe4807a165214e66f780f424be367df5ef1e94b09acf4a00cd2e614d +a6677a373130b83e30849af12475e192f817ba4f3226529a9cca8baaefb8811db376e4a044b42bf1481268c249b1a66e +b969cbf444c1297aa50d1dfa0894de4565161cb1fc59ba03af9655c5bf94775006fe8659d3445b546538a22a43be6b93 +8383167e5275e0707e391645dc9dea9e8a19640ecfa23387f7f6fcaddff5cde0b4090dfad7af3c36f8d5c7705568e8d8 +a353ddbc6b6837773e49bb1e33a3e00ca2fb5f7e1dba3a004b0de75f94a4e90860d082a455968851ef050ae5904452e0 +adeccf320d7d2831b495479b4db4aa0e25c5f3574f65a978c112e9981b2663f59de4c2fa88974fdcabb2eedb7adab452 +afa0eacc9fdbe27fb5e640ecad7ecc785df0daf00fc1325af716af61786719dd7f2d9e085a71d8dc059e54fd68a41f24 +a5b803a5bbe0ca77c8b95e1e7bacfd22feae9f053270a191b4fd9bca850ef21a2d4bd9bcd50ecfb971bb458ff2354840 +b023c9c95613d9692a301ef33176b655ba11769a364b787f02b42ceb72338642655ea7a3a55a3eec6e1e3b652c3a179e +8fa616aa7196fc2402f23a19e54620d4cf4cf48e1adfb7ea1f3711c69705481ddcc4c97236d47a92e974984d124589e5 +a49e11e30cb81cb7617935e8a30110b8d241b67df2d603e5acc66af53702cf1e9c3ef4a9b777be49a9f0f576c65dcc30 +8df70b0f19381752fe327c81cce15192389e695586050f26344f56e451df2be0b1cdf7ec0cba7ce5b911dcff2b9325ae +8fbbc21a59d5f5a14ff455ca78a9a393cab91deb61cf1c25117db2714d752e0054ed3e7e13dd36ad423815344140f443 +a9a03285488668ab97836a713c6e608986c571d6a6c21e1adbd99ae4009b3dde43721a705d751f1bd4ebf1ea7511dfed +b2f32b8e19e296e8402251df67bae6066aeefd89047586d887ffa2eacdf38e83d4f9dc32e553799024c7a41818945755 +942cf596b2278ad478be5c0ab6a2ad0ceafe110263cc93d15b9a3f420932104e462cf37586c374f10b1040cb83b862e0 +aaa077a55f501c875ceae0a27ef2b180be9de660ef3d6b2132eb17256771ce609d9bc8aaf687f2b56ae46af34ad12b30 +90ac74885be1448101cf3b957d4486e379673328a006ea42715c39916e9334ea77117ff4a60d858e2ccce9694547a14f +9256cdfc2339e89db56fd04bd9b0611be0eefc5ee30711bcece4aadf2efcc5a6dcc0cfd5f733e0e307e3a58055dff612 +a4c7384e208a0863f4c056248f595473dcde70f019ddaede45b8caf0752575c241bac6e436439f380ac88eee23a858e9 +a3aa67391781e0736dddc389f86b430b2fc293b7bd56bfd5a8ec01d1dd52ed940593c3ad4ce25905061936da062b0af6 +80299275ec322fbb66cc7dce4482ddd846534e92121186b6906c9a5d5834346b7de75909b22b98d73120caec964e7012 +aa3a6cd88e5f98a12738b6688f54478815e26778357bcc2bc9f2648db408d6076ef73cced92a0a6b8b486453c9379f18 +b07c444681dc87b08a7d7c86708b82e82f8f2dbd4001986027b82cfbed17b9043e1104ade612e8e7993a00a4f8128c93 +af40e01b68d908ac2a55dca9b07bb46378c969839c6c822d298a01bc91540ea7a0c07720a098be9a3cfe9c27918e80e8 +abd8947c3bbc3883c80d8c873f8e2dc9b878cbbb4fc4a753a68f5027de6d8c26aa8fbbafeb85519ac94e2db660f31f26 +a234f9d1a8f0cb5d017ccca30b591c95ec416c1cb906bd3e71b13627f27960f61f41ed603ffbcf043fd79974ec3169a8 +835aaf52a6af2bc7da4cf1586c1a27c72ad9de03c88922ad172dce7550d70f6f3efcc3820d38cd56ae3f7fc2f901f7a0 +ae75db982a45ad01f4aa7bc50d642ff188219652bb8d521d13a9877049425d57852f3c9e4d340ffec12a4d0c639e7062 +b88884aa9187c33dc784a96832c86a44d24e9ffe6315544d47fc25428f11337b9ffd56eb0a03ad709d1bf86175059096 +8492ca5afcc6c0187b06453f01ed45fd57eb56facbeea30c93686b9e1dab8eaabd89e0ccb24b5f35d3d19cd7a58b5338 +9350623b6e1592b7ea31b1349724114512c3cce1e5459cd5bddd3d0a9b2accc64ab2bf67a71382d81190c3ab7466ba08 +98e8bf9bed6ae33b7c7e0e49fc43de135bffdba12b5dcb9ff38cb2d2a5368bb570fe7ee8e7fbe68220084d1d3505d5be +ab56144393f55f4c6f80c67e0ab68f445568d68b5aa0118c0c666664a43ba6307ee6508ba0bb5eb17664817bc9749af0 +827d5717a41b8592cfd1b796a30d6b2c3ca2cdc92455f9f4294b051c4c97b7ad6373f692ddafda67884102e6c2a16113 +8445ce2bb81598067edaa2a9e356eda42fb6dc5dd936ccf3d1ff847139e6020310d43d0fec1fe70296e8f9e41a40eb20 +9405178d965ee51e8d76d29101933837a85710961bb61f743d563ef17263f3c2e161d57e133afac209cdb5c46b105e31 +b209f9ed324c0daa68f79800c0a1338bbaf6d37b539871cb7570f2c235caca238a2c4407961fcb7471a103545495ef2c +92ae6437af6bbd97e729b82f5b0d8fb081ca822f340e20fae1875bdc65694cd9b8c037a5a1d49aa9cae3d33f5bad414e +9445bdb666eae03449a38e00851629e29a7415c8274e93343dc0020f439a5df0009cd3c4f5b9ce5c0f79aefa53ceac99 +93fdab5f9f792eada28f75e9ac6042a2c7f3142ba416bfdb1f90aa8461dbe4af524eee6db4f421cb70c7bc204684d043 +a7f4dc949af4c3163953320898104a2b17161f7be5a5615da684f881633174fb0b712d0b7584b76302e811f3fac3c12f +a8ac84da817b3066ba9789bf2a566ccf84ab0a374210b8a215a9dcf493656a3fa0ecf07c4178920245fee0e46de7c3ec +8e6a0ae1273acda3aa50d07d293d580414110a63bc3fb6330bb2ee6f824aff0d8f42b7375a1a5ba85c05bfbe9da88cb5 +a5dea98852bd6f51a84fa06e331ea73a08d9d220cda437f694ad9ad02cf10657882242e20bdf21acbbaa545047da4ce5 +b13f410bf4cfce0827a5dfd1d6b5d8eabc60203b26f4c88238b8000f5b3aaf03242cdeadc2973b33109751da367069e1 +a334315a9d61b692ad919b616df0aa75a9f73e4ea6fc27d216f48964e7daebd84b796418580cf97d4f08d4a4b51037cd +8901ba9e963fcd2f7e08179b6d19c7a3b8193b78ca0e5cf0175916de873ca0d000cd7ac678c0473be371e0ac132f35a2 +b11a445433745f6cb14c9a65314bbf78b852f7b00786501b05d66092b871111cd7bee25f702d9e550d7dd91601620abb +8c2f7b8e7b906c71f2f154cc9f053e8394509c37c07b9d4f21b4495e80484fc5fc8ab4bdc525bd6cfa9518680ba0d1a2 +b9733cebe92b43b899d3d1bfbf4b71d12f40d1853b2c98e36e635fdd8a0603ab03119890a67127e6bc79afae35b0bef2 +a560f6692e88510d9ba940371e1ada344caf0c36440f492a3067ba38e9b7011caac37ba096a8a4accb1c8656d3c019b3 +ac18624339c1487b2626eef00d66b302bdb1526b6340d6847befe2fdfb2b410be5555f82939f8707f756db0e021ed398 +afd9a3b8866a7fe4f7bc13470c0169b9705fcd3073685f5a6dcff3bdbbc2be50ac6d9908f9a10c5104b0bffc2bc14dad +97f15c92fe1f10949ed9def5dd238bc1429706e5037a0e0afb71c2d0e5845e2fed95a171c393e372077a7c7059f8c0e0 +9453a1d4d09c309b70968ea527007d34df9c4cfd3048e5391aac5f9b64ca0c05dde5b8c949c481cfc83ef2e57b687595 +b80e4b7c379ad435c91b20b3706253b763cbc980db78f782f955d2516af44c07bbfa5888cbf3a8439dc3907320feb25a +8939f458d28fefe45320b95d75b006e98330254056d063e4a2f20f04bcb25936024efe8d436d491ed34b482f9b9ae49c +a9ead2e833f71f7e574c766440c4b3c9c3363698c7ade14499a56003a272832ee6d99440887fa43ccdf80265b9d56b97 +b6547a36934f05ce7b779e68049d61351cf229ae72dc211cc96a2a471b2724782f9355fdb415ea6f0ea1eb84fe00e785 +828bfb3099b7b650b29b0f21279f829391f64520a6ab916d1056f647088f1e50fac9253ef7464eceab5380035c5a59c4 +8d714b9ea650be4342ff06c0256189e85c5c125adf6c7aeca3dba9b21d5e01a28b688fc2116ce285a0714a8f1425c0b8 +8a82eda041b2e72a3d73d70d85a568e035fbd6dc32559b6c6cfdf6f4edcb59a6ba85b6294a721aa0a71b07714e0b99ae +af5665ebc83d027173b14ffb0e05af0a192b719177889fadc9ac8c082fda721e9a75d9ce3f5602dbfd516600ee3b6405 +a68fdddf03d77bebdb676e40d93e59bd854408793df2935d0a5600601f7691b879981a398d02658c2da39dbbf61ef96c +8c001ebc84fcf0470b837a08a7b6125126b73a2762db47bbdc38c0e7992b1c66bac7a64faa1bf1020d1c63b40adc3082 +8553889b49f9491109792db0a69347880a9cf2911b4f16f59f7f424e5e6b553687d51282e8f95be6a543635247e2e2c2 +a2c269d6370b541daf1f23cc6b5d2b03a5fa0c7538d53ae500ef875952fe215e74a5010329ff41461f4c58b32ad97b3d +a5dae097285392b4eba83a9fd24baa03d42d0a157a37fae4b6efc3f45be86024b1182e4a6b6eadcf5efe37704c0a1ae5 +89871a77d2032387d19369933cd50a26bda643e40cfd0ce73febe717a51b39fae981406fd41e50f4a837c02a99524ef9 +8a76d495e90093ec2ac22f53759dc1cf36fbb8370fb586acbd3895c56a90bbf3796bcc4fc422ca4058adf337ead1402e +ad4eb7576c4954d20623c1336c63662c2a6fb46ec6ef99b7f8e946aa47488dcb136eab60b35600f98c78c16c10c99013 +894c2b120cec539feb1d281baaadde1e44beafedeeec29b804473fe024e25c1db652f151c956e88d9081fb39d27e0b19 +9196bd5c100878792444c573d02b380a69e1b4b30cb59a48114852085058a5fd952df4afee3ecceb5c4ede21e1ed4a1a +a996fffc910764ea87a1eedc3a3d600e6e0ff70e6a999cb435c9b713a89600fc130d1850174efe9fc18244bb7c6c5936 +8591bb8826befa8bee9663230d9a864a5068589f059e37b450e8c85e15ce9a1992f0ce1ead1d9829b452997727edcf9d +9465e20bb22c41bf1fa728be8e069e25cda3f7c243381ca9973cbedad0c7b07d3dd3e85719d77cf80b1058ce60e16d68 +926b5ce39b6e60b94878ffeae9ff20178656c375fb9cfe160b82318ca500eb3e2e3144608b6c3f8d6c856b8fe1e2fbcf +a1ef29cbc83c45eb28ad468d0ce5d0fdd6b9d8191ba5ffa1a781c2b232ed23db6b7b04de06ef31763a6bfe377fa2f408 +9328e63a3c8acf457c9f1f28b32d90d0eeadb0f650b5d43486a61d7374757a7ada5fc1def2a1e600fa255d8b3f48036f +a9c64880fcb7654f4dd08f4c90baac95712dd6dd407e17ea60606e9a97dc8e54dd25cb72a9bf3fc61f8d0ad569fe369d +a908eb7b940c1963f73046d6b35d40e09013bfbfbeb2ccd64df441867e202b0f3b625fa32dd04987c3d7851360abdffc +b3947b5ed6d59e59e4472cdb1c3261de1b5278fb7cb9b5fca553f328b3b3e094596861ea526eca02395f7b7358155b7b +99da7f190d37bc58945f981cf484d40fcf0855cf8178e2ce8d057c7f0a9d9f77425fdbce9ef8366f44f671b20fd27d0b +913976d77d80e3657977df39571577fdf0be68ba846883705b454f8493578baa741cfaede53783e2c97cc08964395d83 +8d754a61e5164a80b5090c13f3e936056812d4ae8dc5cc649e6c7f37464777249bc4ae760a9806939131f39d92cca5bf +82ffd098480828a90cb221a8c28584e15904bad477c13b2e2d6ef0b96a861ce4a309a328fe44342365349456ad7c654f +89ae3ce4b0357044579ca17be85d8361bb1ce3941f87e82077dd67e43ec0f95edd4bd3426225c90994a81a99e79490b7 +a170892074016d57c9d8e5a529379d7e08d2c1158b9ac4487ac9b95266c4fd51cb18ae768a2f74840137eec05000dd5a +aafd8acd1071103c7af8828a7a08076324d41ea530df90f7d98fafb19735fc27ead91b50c2ca45851545b41d589d0f77 +8623c849e61d8f1696dc9752116a26c8503fd36e2cbbc9650feffdd3a083d8cdbb3b2a4e9743a84b9b2ad91ac33083f2 +ac7166ddd253bb22cdbd8f15b0933c001d1e8bc295e7c38dc1d2be30220e88e2155ecd2274e79848087c05e137e64d01 +a5276b216d3df3273bbfa46210b63b84cfe1e599e9e5d87c4e2e9d58666ecf1af66cb7ae65caebbe74b6806677215bd0 +88792f4aa3597bb0aebadb70f52ee8e9db0f7a9d74f398908024ddda4431221a7783e060e0a93bf1f6338af3d9b18f68 +8f5fafff3ecb3aad94787d1b358ab7d232ded49b15b3636b585aa54212f97dc1d6d567c180682cca895d9876cacb7833 +ab7cb1337290842b33e936162c781aa1093565e1a5b618d1c4d87dd866daea5cebbcc486aaa93d8b8542a27d2f8694c7 +88480a6827699da98642152ebc89941d54b4791fbc66110b7632fb57a5b7d7e79943c19a4b579177c6cf901769563f2f +a725ee6d201b3a610ede3459660658ee391803f770acc639cfc402d1667721089fb24e7598f00e49e81e50d9fd8c2423 +98924372da8aca0f67c8c5cad30fa5324519b014fae7849001dcd51b6286118f12b6c49061219c37714e11142b4d46de +a62c27360221b1a7c99697010dfe1fb31ceb17d3291cf2172624ebeff090cbaa3c3b01ec89fe106dace61d934711d42d +825173c3080be62cfdc50256c3f06fe190bc5f190d0eb827d0af5b99d80936e284a4155b46c0d462ee574fe31d60983d +a28980b97023f9595fadf404ed4aa36898d404fe611c32fd66b70252f01618896f5f3fda71aea5595591176aabf0c619 +a50f5f9def2114f6424ff298f3b128068438f40860c2b44e9a6666f43c438f1780be73cf3de884846f1ba67f9bef0802 +b1eee2d730da715543aeb87f104aff6122cb2bf11de15d2519ff082671330a746445777924521ec98568635f26988d0c +862f6994a1ff4adfd9fb021925cccf542fca4d4b0b80fb794f97e1eb2964ef355608a98eec6e07aadd4b45ee625b2a21 +8ce69a18df2f9b9f6e94a456a7d94842c61dea9b00892da7cf5c08144de9be39b8c304aeca8b2e4222f87ba367e61006 +b5f325b1cecd435f5346b6bc562d92f264f1a6d91be41d612df012684fdd69e86063db077bc11ea4e22c5f2a13ae7bee +85526870a911127835446cb83db8986b12d5637d59e0f139ad6501ac949a397a6c73bd2e7fba731b1bb357efe068242c +8552247d3f7778697f77389717def5a149fc20f677914048e1ed41553b039b5427badc930491c0bae663e67668038fd1 +a545640ee5e51f3fe5de7050e914cfe216202056cd9d642c90e89a166566f909ee575353cb43a331fde17f1c9021414e +8b51229b53cff887d4cab573ba32ec52668d197c084414a9ee5589b285481cea0c3604a50ec133105f661321c3ca50f5 +8cdc0b960522bed284d5c88b1532142863d97bbb7dc344a846dc120397570f7bd507ceb15ed97964d6a80eccfef0f28e +a40683961b0812d9d53906e795e6470addc1f30d09affebf5d4fbbd21ddfa88ce441ca5ea99c33fd121405be3f7a3757 +a527875eb2b99b4185998b5d4cf97dd0d4a937724b6ad170411fc8e2ec80f6cee2050f0dd2e6fee9a2b77252d98b9e64 +84f3a75f477c4bc4574f16ebc21aaa32924c41ced435703c4bf07c9119dd2b6e066e0c276ff902069887793378f779e0 +a3544bc22d1d0cab2d22d44ced8f7484bfe391b36991b87010394bfd5012f75d580596ffd4f42b00886749457bb6334b +b81f6eb26934b920285acc20ceef0220dd23081ba1b26e22b365d3165ce2fbae733bbc896bd0932f63dcc84f56428c68 +95e94d40a4f41090185a77bf760915a90b6a3e3ace5e53f0cb08386d438d3aa3479f0cd81081b47a9b718698817265cd +b69bd1625b3d6c17fd1f87ac6e86efa0d0d8abb69f8355a08739109831baeec03fd3cd4c765b5ff8b1e449d33d050504 +8448f4e4c043519d98552c2573b76eebf2483b82d32abb3e2bfc64a538e79e4f59c6ca92adff1e78b2f9d0a91f19e619 +8f11c42d6a221d1fda50887fb68b15acdb46979ab21d909ed529bcad6ae10a66228ff521a54a42aca0dad6547a528233 +a3adb18d7e4a882b13a067784cf80ea96a1d90f5edc61227d1f6e4da560c627688bdf6555d33fe54cab1bca242986871 +a24d333d807a48dc851932ed21cbdd7e255bad2699909234f1706ba55dea4bb6b6f8812ffc0be206755868ba8a4af3f9 +a322de66c22a606e189f7734dbb7fda5d75766d5e69ec04b4e1671d4477f5bcb9ff139ccc18879980ebc3b64ab4a2c49 +88f54b6b410a1edbf125db738d46ee1a507e69bc5a8f2f443eb787b9aa7dbd6e55014ec1e946aabeb3e27a788914fb04 +b32ee6da1dcd8d0a7fd7c1821bb1f1fe919c8922b4c1eeed56e5b068a5a6e68457c42b192cbaef5dc6d49b17fa45bc0f +8a44402da0b3a15c97b0f15db63e460506cb8bef56c457166aea5e8881087d8202724c539ef0feb97131919a73aefca8 +b967e3fead6171fa1d19fd976535d428b501baff59e118050f9901a54b12cc8e4606348454c8f0fc25bd6644e0a5532e +b7a0c9e9371c3efbbb2c6783ce2cc5f149135175f25b6d79b09c808bce74139020e77f0c616fa6dcb3d87a378532529d +a54207782ffc909cd1bb685a3aafabbc4407cda362d7b3c1b14608b6427e1696817aeb4f3f85304ac36e86d3d8caa65b +98c1da056813a7bfebc81d8db7206e3ef9b51f147d9948c088976755826cc5123c239ca5e3fe59bed18b5d0a982f3c3f +ae1c86174dfafa9c9546b17b8201719aecd359f5bbeb1900475041f2d5b8a9600d54d0000c43dd061cfda390585726ff +a8ee5a8be0bd1372a35675c87bfd64221c6696dc16e2d5e0996e481fec5cdbcb222df466c24740331d60f0521285f7d3 +8ddadbe3cf13af50d556ce8fc0dd77971ac83fad9985c3d089b1b02d1e3afc330628635a31707b32595626798ea22d45 +a5c80254baf8a1628dc77c2445ebe21fbda0de09dd458f603e6a9851071b2b7438fe74214df293dfa242c715d4375c95 +b9d83227ed2600a55cb74a7052003a317a85ca4bea50aa3e0570f4982b6fe678e464cc5156be1bd5e7bba722f95e92c5 +b56085f9f3a72bea9aa3a8dc143a96dd78513fa327b4b9ba26d475c088116cab13843c2bff80996bf3b43d3e2bddb1d6 +8fa9b39558c69a9757f1e7bc3f07295e4a433da3e6dd8c0282397d26f64c1ecd8eb3ba9824a7cacfb87496ebbb45d962 +879c6d0cb675812ed9dee68c3479a499f088068501e2677caeae035e6f538da91a49e245f5fcce135066169649872bee +91aa9fd3fed0c2a23d1edda8a6542188aeb8abee8772818769bdee4b512d431e4625a343af5d59767c468779222cf234 +a6be0bb2348c35c4143482c7ef6da9a93a5356f8545e8e9d791d6c08ed55f14d790d21ee61d3a56a2ae7f888a8fd46ca +808ee396a94e1b8755f2b13a6ffbedef9e0369e6c2e53627c9f60130c137299d0e4924d8ef367e0a7fad7f68a8c9193c +ad1086028fcdac94d5f1e7629071e7e47e30ad0190ae59aaebfb7a7ef6202ab91323a503c527e3226a23d7937af41a52 +9102bdaf79b907d1b25b2ec6b497e2d301c8eac305e848c6276b392f0ad734131a39cc02ed42989a53ca8da3d6839172 +8c976c48a45b6bc7cd7a7acea3c2d7c5f43042863b0661d5cd8763e8b50730552187a8eecf6b3d17be89110208808e77 +a2624c7e917e8297faa3af89b701953006bf02b7c95dfba00c9f3de77748bc0b13d6e15bb8d01377f4d98fb189538142 +a405f1e66783cdcfe20081bce34623ec3660950222d50b7255f8b3cc5d4369aeb366e265e5224c0204911539f0fa165e +8d69bdcaa5d883b5636ac8f8842026fcc58c5e2b71b7349844a3f5d6fbecf44443ef4f768eac376f57fb763606e92c9f +82fce0643017d16ec1c3543db95fb57bfa4855cc325f186d109539fcacf8ea15539be7c4855594d4f6dc628f5ad8a7b0 +8860e6ff58b3e8f9ae294ff2487f0d3ffae4cf54fd3e69931662dabc8efd5b237b26b3def3bcd4042869d5087d22afcf +88c80c442251e11c558771f0484f56dc0ed1b7340757893a49acbf96006aa73dfc3668208abea6f65375611278afb02a +8be3d18c6b4aa8e56fcd74a2aacb76f80b518a360814f71edb9ccf3d144bfd247c03f77500f728a62fca7a2e45e504c5 +8b8ebf0df95c3f9b1c9b80469dc0d323784fd4a53f5c5357bb3f250a135f4619498af5700fe54ad08744576588b3dfff +a8d88abdaadd9c2a66bc8db3072032f63ed8f928d64fdb5f810a65074efc7e830d56e0e738175579f6660738b92d0c65 +a0a10b5d1a525eb846b36357983c6b816b8c387d3890af62efb20f50b1cb6dd69549bbef14dab939f1213118a1ae8ec2 +8aadf9b895aeb8fdc9987daa937e25d6964cbd5ec5d176f5cdf2f0c73f6f145f0f9759e7560ab740bf623a3279736c37 +99aeda8a495031cc5bdf9b842a4d7647c55004576a0edc0bd9b985d60182608361ed5459a9d4b21aa8e2bd353d10a086 +832c8b3bfcd6e68eee4b100d58014522de9d4cefa99498bc06c6dca83741e4572e20778e0d846884b33439f160932bca +841f56ebefc0823ab484fc445d62f914e13957e47904419e42771aa605e33ab16c44f781f6f9aa42e3a1baf377f54b42 +a6e40271d419e295a182725d3a9b541ffd343f23e37549c51ecaa20d13cf0c8d282d6d15b24def5702bfee8ba10b12ac +8ac00925ac6187a4c5cde48ea2a4eaf99a607e58b2c617ee6f01df30d03fafada2f0469178dd960d9d64cbd33a0087d8 +b6b80916b540f8a0fe4f23b1a06e2b830008ad138271d5ba3cd16d6619e521fe2a7623c16c41cba48950793386eea942 +8412c0857b96a650e73af9d93087d4109dd092ddf82188e514f18fcac644f44d4d62550bfa63947f2d574a2e9d995bbb +b871395baa28b857e992a28ac7f6d95ec461934b120a688a387e78498eb26a15913b0228488c3e2360391c6b7260b504 +926e2d25c58c679be77d0e27ec3b580645956ba6f13adcbc2ea548ee1b7925c61fcf74c582337a3b999e5427b3f752f2 +a165fa43fecae9b913d5dcfc232568e3e7b8b320ce96b13800035d52844c38fd5dbf7c4d564241d860c023049de4bcbc +b4976d7572fd9cc0ee3f24888634433f725230a7a2159405946a79315bc19e2fc371448c1c9d52bf91539fd1fe39574b +a6b461eb72e07a9e859b9e16dfa5907f4ac92a5a7ca4368b518e4a508dc43f9b4be59db6849739f3ef4c44967b63b103 +b976606d3089345d0bc501a43525d9dca59cf0b25b50dfc8a61c5bd30fac2467331f0638fab2dc68838aa6ee8d2b6bc9 +b16ea61c855da96e180abf7647fa4d9dd6fd90adebadb4c5ed4d7cd24737e500212628fca69615d89cb40e9826e5a214 +95a3e3162eb5ea27a613f8c188f2e0dcc5cbd5b68c239858b989b004d87113e6aa3209fa9fad0ee6ecef42814ba9db1a +b6a026ab56d3224220e5bce8275d023c8d39d1bdf7eec3b0923429b7d5ef18cf613a3591d364be8727bb1fa0ba11eabb +949f117e2e141e25972ee9ccdd0b7a21150de7bbf92bbd89624a0c5f5a88da7b2b172ba2e9e94e1768081f260c2a2f8d +b7c5e9e6630287d2a20a2dfb783ffe6a6ff104ff627c6e4e4342acc2f3eb6e60e9c22f465f8a8dc58c42f49840eca435 +872be5a75c3b85de21447bb06ac9eb610f3a80759f516a2f99304930ddf921f34cbffc7727989cdd7181d5fc62483954 +a50976ea5297d797d220932856afdd214d1248230c9dcd840469ecc28ea9f305b6d7b38339fedb0c00b5251d77af8c95 +80b360f8b44914ff6f0ffbd8b5360e3cabe08639f6fe06d0c1526b1fe9fe9f18c497f1752580b30e950abd3e538ad416 +a2f98f9bf7fac78c9da6bb41de267742a9d31cf5a04b2fb74f551084ec329b376f651a59e1ae919b2928286fb566e495 +8b9d218a8a6c150631548e7f24bbd43f132431ae275c2b72676abbea752f554789c5ff4aac5c0eeee5529af7f2b509ef +aa21a243b07e9c7b169598bf0b102c3c280861780f83121b2ef543b780d47aaa4b1850430ee7927f33ece9847c4e0e1a +8a6f90f4ce58c8aa5d3656fe4e05acccf07a6ec188a5f3cde7bf59a8ae468e66f055ac6dfc50b6e8e98f2490d8deedc5 +8e39f77ca4b5149ffe9945ceac35d068760ba338d469d57c14f626dd8c96dbe993dd7011beff727c32117298c95ee854 +83bd641c76504222880183edd42267e0582642c4993fe2c7a20ce7168e4c3cbf7586e1d2d4b08c84d9b0bf2f6b8800b8 +a9d332993cf0c1c55130e5cf3a478eb5e0bfb49c25c07538accc692ef03d82b458750a7b991cc0b41b813d361a5d31e3 +a0fc60e6a6015df9bee04cea8f20f01d02b14b6f7aa03123ab8d65da071b2d0df5012c2a69e7290baae6ed6dd29ebe07 +a2949dde2e48788ceaac7ec7243f287ffe7c3e788cdba97a4ab0772202aeef2d50382bed8bf7eff5478243f7eabe0bda +a7879373ea18572dba6cf29868ca955ffa55b8af627f29862f6487ee398b81fe3771d8721ca8e06716c5d91b9ac587cb +b3c7081e2c5306303524fbe9fe5645111a57dffd4ec25b7384da12e56376a0150ab52f9d9cc6ca7bdd950695e39b766d +a634a6a19d52dcb9f823352b36c345d2de54b75197bcd90528d27830bd6606d1a9971170de0849ed5010afa9f031d5be +88f2062f405fa181cfdb8475eaf52906587382c666ca09a9522537cfebbc7de8337be12a7fd0db6d6f2f7ab5aefab892 +b1f0058c1f273191247b98783b2a6f5aa716cf799a8370627fc3456683f03a624d0523b63a154fe9243c0dfd5b37c460 +ae39a227cc05852437d87be6a446782c3d7fbe6282e25cf57b6b6e12b189bdc0d4a6e2c3a60b3979256b6b5baf8f1c5f +802a1af228ab0c053b940e695e7ef3338f5be7acf4e5ed01ac8498e55b492d3a9f07996b1700a84e22f0b589638909cd +a36490832f20e4b2f9e79ee358b66d413f034d6a387534b264cdeac2bca96e8b5bcbdd28d1e98c44498032a8e63d94d2 +8728c9a87db2d006855cb304bba54c3c704bf8f1228ae53a8da66ca93b2dac7e980a2a74f402f22b9bc40cd726e9c438 +a08f08ab0c0a1340e53b3592635e256d0025c4700559939aeb9010ed63f7047c8021b4210088f3605f5c14fb51d1c613 +9670fd7e2d90f241e8e05f9f0b475aa260a5fb99aa1c9e61cd023cbad8ed1270ae912f168e1170e62a0f6d319cf45f49 +a35e60f2dd04f098bf274d2999c3447730fe3e54a8aff703bc5a3c274d22f97db4104d61a37417d93d52276b27ef8f31 +859df7a21bc35daec5695201bd69333dc4f0f9e4328f2b75a223e6615b22b29d63b44d338413ca97eb74f15563628cb7 +b2b44ad3e93bc076548acdf2477803203108b89ecc1d0a19c3fb9814d6b342afc420c20f75e9c2188ad75fdb0d34bb2d +941173ee2c87765d10758746d103b667b1227301e1bcfecef2f38f9ab612496a9abd3050cef5537bf28cfecd2aacc449 +92b0bea30ebed20ac30648efb37bac2b865daaa514316e6f5470e1de6cb84651ff77c127aa7beed4521bda5e8fc81122 +af17bf813bb238cf8bb437433f816786612209180a6c0a1d5141292dc2d2c37164ef13bfc50c718bfcc6ce26369298a2 +8461fd951bdfda099318e05cc6f75698784b033f15a71bce26165f0ce421fd632d50df9eeced474838c0050b596e672c +83281aa18ae4b01e8201e1f64248cc6444c92ee846ae72adb178cef356531558597d84ff93a05abf76bfe313eb7dbe86 +b62b150f73999c341daa4d2f7328d2f6ca1ef3b549e01df58182e42927537fc7971c360fe8264af724f4c0247850ef12 +a7022a201f79c012f982b574c714d813064838a04f56964d1186691413757befeeaada063e7884297606e0eea1b1ed43 +a42ac9e8be88e143853fd8e6a9ff21a0461801f0ac76b69cca669597f9af17ecb62cccdcdcbe7f19b62ab93d7f838406 +80f1ca73b6ba3a2fbae6b79b39c0be8c39df81862d46c4990c87cbf45b87996db7859d833abc20af2fcb4faf059c436a +b355943e04132d5521d7bbe49aea26f6aa1c32f5d0853e77cc2400595325e923a82e0ff7601d1aee79f45fd8a254f6ae +87142c891d93e539b31d0b5ead9ea600b9c84db9be9369ff150a8312fe3d10513f4c5b4d483a82b42bc65c45dd9dd3bd +823c3d7f6dda98a9d8c42b3fee28d3154a95451402accadb6cf75fc45d2653c46a569be75a433094fa9e09c0d5cf1c90 +b3c3497fe7356525c1336435976e79ec59c5624c2fb6185ee09ca0510d58b1e392965e25df8a74d90d464c4e8bb1422b +88c48d83e8ddc0d7eea051f3d0e21bc0d3a0bb2b6a39ece76750c1c90c382a538c9a35dc9478b8ceb8157dcccbbf187a +93da81a8939f5f58b668fefdc6f5f7eca6dc1133054de4910b651f8b4a3267af1e44d5a1c9e5964dc7ab741eb146894b +8b396e64985451ac337f16be61105106e262e381ea04660add0b032409b986e1ac64da3bc2feae788e24e9cb431d8668 +9472068b6e331ea67e9b5fbf8057672da93c209d7ded51e2914dbb98dccd8c72b7079b51fd97a7190f8fc8712c431538 +ac47e1446cb92b0a7406f45c708567f520900dfa0070d5e91783139d1bfc946d6e242e2c7b3bf4020500b9f867139709 +896053706869fb26bb6f7933b3d9c7dd6db5c6bd1269c7a0e222b73039e2327d44bda7d7ae82bf5988808b9831d78bcd +a55e397fa7a02321a9fe686654c86083ecedb5757586d7c0250ec813ca6d37151a12061d5feca4691a0fd59d2f0fdd81 +ae23f08ac2b370d845036518f1bddb7fea8dc59371c288a6af310486effeb61963f2eef031ca90f9bdbcf0e475b67068 +b5462921597a79f66c0fec8d4c7cfd89f427692a7ce30d787e6fd6acd2377f238ec74689a0fdbe8ef3c9c9bd24b908dc +ae67e8ea7c46e29e6aae6005131c29472768326819aa294aaf5a280d877de377b44959adb1348fa3e929dcbc3ae1f2c0 +84962b4c66500a20c4424191bdfb619a46cda35bdb34c2d61edcb0b0494f7f61dd5bf8f743302842026b7b7d49edd4b5 +846f76286dc3cc59cb15e5dabb72a54a27c78190631df832d3649b2952fa0408ecde7d4dfdae7046c728efa29879fb51 +8f76c854eaee8b699547e07ad286f7dadfa6974c1328d12502bd7630ae619f6129272fdd15e2137ffef0143c42730977 +8007b163d4ea4ec6d79e7a2aa19d06f388da0b3a56f3ee121441584e22a246c0e792431655632bf6e5e02cb86914eebf +ac4d2cecc1f33e6fb73892980b61e62095ddff5fd6167f53ca93d507328b3c05440729a277dc3649302045b734398af1 +92d2a88f2e9c9875abaff0d42624ccb6d65401de7127b5d42c25e6adccd7a664504c5861618f9031ced8aeb08b779f06 +a832c1821c1b220eb003fc532af02c81196e98df058cdcc9c9748832558362915ea77526937f30a2f74f25073cb89afb +b6f947ab4cc2baec100ed8ec7739a2fd2f9504c982b39ab84a4516015ca56aea8eef5545cfc057dd44c69b42125fb718 +b24afacf2e90da067e5c050d2a63878ee17aaf8fd446536f2462da4f162de87b7544e92c410d35bf2172465940c19349 +b7a0aa92deac71eaab07be8fa43086e071e5580f5dbf9b624427bdd7764605d27303ae86e5165bed30229c0c11958c38 +b0d1d5bfa1823392c5cf6ed927c1b9e84a09a24b284c2cd8fcb5fda8e392c7c59412d8f74eb7c48c6851dff23ae66f58 +a24125ef03a92d2279fb384186ca0274373509cfec90b34a575490486098438932ee1be0334262d22d5f7d3db91efe67 +83e08e5fba9e8e11c164373794f4067b9b472d54f57f4dbe3c241cf7b5b7374102de9d458018a8c51ab3aed1dddf146f +9453101b77bb915ed40990e1e1d2c08ea8ec5deb5b571b0c50d45d1c55c2e2512ec0ceca616ff0376a65678a961d344d +92a0516e9eb6ad233d6b165a8d64a062ce189b25f95d1b3264d6b58da9c8d17da2cd1f534800c43efcf2be73556cd2ff +958d0b5d7d8faf25d2816aa6a2c5770592ad448db778dd9b374085baa66c755b129822632eaabcb65ee35f0bf4b73634 +90a749de8728b301ad2a6b044e8c5fd646ccd8d20220e125cba97667e0bb1d0a62f6e3143b28f3d93f69cdc6aa04122a +84bd34c8d8f74dec07595812058db24d62133c11afed5eb2a8320d3bfc28e442c7f0cfd51011b7b0bb3e5409cb7b6290 +aecc250b556115d97b553ad7b2153f1d69e543e087890000eaa60f4368b736921d0342ce5563124f129096f5d5e2ca9d +977f17ac82ed1fbf422f9b95feb3047a182a27b00960296d804fd74d54bb39ad2c055e665c1240d2ad2e06a3d7501b00 +af5be9846bd4879ebe0af5e7ad253a632f05aedfe306d31fe6debe701ba5aa4e33b65efc05043bc73aadb199f94baed4 +9199e12ec5f2aaaeed6db5561d2dcc1a8fe9c0854f1a069cba090d2dff5e5ba52b10c841ccbd49006a91d881f206150d +8f4a96a96ed8ceaf3beba026c89848c9ca4e6452ce23b7cf34d12f9cc532984a498e051de77745bdc17c7c44c31b7c30 +af3f2a3dbe8652c4bfca0d37fb723f0e66aab4f91b91a625114af1377ad923da8d36da83f75deb7a3219cd63135a3118 +a6d46963195df8962f7aa791d104c709c38caa438ddd192f7647a884282e81f748c94cdf0bb25d38a7b0dc1b1d7bbcf7 +86f3de4b22c42d3e4b24b16e6e8033e60120af341781ab70ae390cb7b5c5216f6e7945313c2e04261a51814a8cb5db92 +b9f86792e3922896cfd847d8ff123ff8d69ecf34968fb3de3f54532f6cd1112b5d34eeabdca46ae64ad9f6e7e5b55edc +83edfbcbc4968381d1e91ab813b3c74ab940eaf6358c226f79182f8b21148ec130685fd91b0ea65916b0a50bccf524ea +93b61daca7a8880b7926398760f50016f2558b0bab74c21181280a1baf3414fc539911bb0b79c4288d29d3c4ad0f4417 +ad541aeb83a47526d38f2e47a5ce7e23a9adabe5efeae03541026881e6d5ef07da3ac1a6ed466ca924fa8e7a91fcff88 +ac4bba31723875025640ed6426003ed8529215a44c9ffd44f37e928feef9fc4dfa889088131c9be3da87e8f3fdf55975 +88fa4d49096586bc9d29592909c38ea3def24629feacd378cc5335b70d13814d6dac415f8c699ee1bf4fe8b85eb89b38 +b67d0b76cbd0d79b71f4673b96e77b6cda516b8faa1510cfe58ff38cc19000bb5d73ff8418b3dab8c1c7960cb9c81e36 +98b4f8766810f0cfecf67bd59f8c58989eb66c07d3dfeee4f4bbce8fd1fce7cc4f69468372eaec7d690748543bd9691d +8445891af3c298b588dec443beacdf41536adb84c812c413a2b843fd398e484eb379075c64066b460839b5fe8f80177c +b603635c3ed6fdc013e2a091fc5164e09acf5f6a00347d87c6ebadb1f44e52ff1a5f0466b91f3f7ffc47d25753e44b75 +87ec2fc928174599a9dafe7538fec7dcf72e6873b17d953ed50708afff0da37653758b52b7cafa0bf50dfcf1eafbb46c +b9dbd0e704d047a457d60efe6822dc679e79846e4cbcb11fa6c02079d65673ee19bbf0d14e8b7b200b9205f4738df7c7 +9591ec7080f3f5ba11197a41f476f9ba17880f414d74f821a072ec5061eab040a2acba3d9856ff8555dfe5eaeb14ca19 +b34c9d1805b5f1ce38a42b800dec4e7f3eb8c38e7d2b0a525378e048426fed150dbfe9cc61f5db82b406d1b9ff2d10bf +a36fdc649dc08f059dfa361e3969d96b4cc4a1ebf10b0cd01a7dd708430979e8d870961fef85878f8779b8e23caafb18 +88dfc739a80c16c95d9d6f73c3357a92d82fa8c3c670c72bee0f1e4bac9ec338e1751eb786eda3e10f747dd7a686900f +84a535ad04f0961756c61c70001903a9adf13126983c11709430a18133c4b4040d17a33765b4a06968f5d536f4bfb5c5 +8c86d695052a2d2571c5ace744f2239840ef21bb88e742f050c7fa737cd925418ecef0971333eb89daa6b3ddfede268c +8e9a700157069dc91e08ddcbdde3a9ad570272ad225844238f1015004239c542fceb0acce6d116c292a55f0d55b6175e +84d659e7f94e4c1d15526f47bc5877a4ef761c2a5f76ec8b09c3a9a30992d41b0e2e38ed0c0106a6b6c86d670c4235f3 +a99253d45d7863db1d27c0ab561fb85da8c025ba578b4b165528d0f20c511a9ca9aff722f4ff7004843f618eb8fced95 +89a3cacb15b84b20e95cd6135550146bbe6c47632cc6d6e14d825a0c79b1e02b66f05d57d1260cb947dc4ae5b0283882 +8385b1555e794801226c44bd5e878cbe68aeac0a19315625a8e5ea0c3526b58cdd4f53f9a14a167a5e8a293b530d615a +b68c729e9df66c5cd22af4909fb3b0057b6a231c4a31cd6bf0fa0e53c5809419d15feb483de6e9408b052458e819b097 +924f56eda269ec7ec2fc20c5731bf7f521546ddf573ccbe145592f1c9fee5134747eb648d9335119a8066ca50a1f7e50 +b2100a26b9c3bec7ec5a53f0febbf56303f199be2f26b2d564cfee2adc65483b84192354f2865c2f4c035fa16252ae55 +8f64dbed62e638563967ec1605a83216aed17eb99aa618c0543d74771ea8f60bbb850c88608d4f8584f922e30a8a0a72 +b31b9e1ffe8d7260479c9413f8e680f3fe391ae8fcf44fcca3000d9b2473a40c1d32299f8f63865a57579a2d6c7e9f08 +a5b1d136142eb23e322c6c07cb838a3f58ab6925472352ebd0bb47041a0d8729e1074ca223922f3a7a672ced7a1e562d +8d9470a5a15d833a447b5f108333d50f30aa7659e331c3f8080b1e928a99922edc650466a2f54f3d48afdb34bff42142 +866368f5891564e5b2de37ad21ff0345c01129a14ea5667f9b64aad12d13ec034622872e414743af0bf20adb2041b497 +88ef9c2ebf25fd0c04b7cfa35fbac2e4156d2f1043fa9f98998b2aa402c8f9a4f1039e782451a46840f3e0e4b3fa47d3 +94ba04a4859273697e264a2d238dc5c9ff573ebc91e4796ea58eebe4080c1bf991255ab2ad8fb1e0301ce7b79cc6e69b +86b6bd0953309a086e526211bf1a99327269304aa74d8cdc994cee63c3a2d4b883e832b0635888dff2a13f1b02eb8df4 +843ea6ea5f2c7a1fd50be56a5765dcce3ea61c99b77c1a729ee0cd8ec706385ac7062e603479d4c8d3527f030762d049 +8d3675195a3b06f2d935d45becc59f9fa8fa440c8df80c029775e47fe9c90e20f7c8e4cc9a2542dd6bfe87536c428f0d +8978580b0c9b0aa3ab2d47e3cfd92fa891d3ddee57829ee4f9780e8e651900457d8e759d1a9b3e8f6ae366e4b57f2865 +890112ec81d0f24b0dfbb4d228e418eff02ae63dc691caf59c1d103e1d194e6e2550e1bec41c0bfdb74fed454f621d0c +97da00bd4b19d1e88caff7f95b8b9a7d29bc0afe85d0c6a163b4b9ef336f0e90e2c49ce6777024bb08df908cc04ea1ca +b458268d275a5211106ccaa8333ce796ef2939b1c4517e502b6462e1f904b41184a89c3954e7c4f933d68b87427a7bfd +aac9c043ba8ba9283e8428044e6459f982413380ee7005a996dc3cc468f6a21001ecaa3b845ce2e73644c2e721940033 +82145013c2155a1200246a1e8720adf8a1d1436b10d0854369d5b1b6208353e484dd16ce59280c6be84a223f2d45e5e2 +b301bafa041f9b203a46beab5f16160d463aa92117c77a3dc6a9261a35645991b9bafcc186c8891ca95021bd35f7f971 +a531b8d2ac3de09b92080a8d8857efa48fb6a048595279110e5104fee7db1dd7f3cfb8a9c45c0ed981cbad101082e335 +a22ac1d627d08a32a8abd41504b5222047c87d558ffae4232cefdeb6a3dc2a8671a4d8ddfba2ff9068a9a3ffb0fe99b1 +b8d9f0e383c35afb6d69be7ff04f31e25c74dd5751f0e51290c18814fbb49ee1486649e64355c80e93a3d9278bd21229 +8165babccd13033a3614c878be749dfa1087ecbeee8e95abcfffe3aa06695711122cb94477a4d55cffd2febf0c1173de +a4c1bc84ecb9d995d1d21c2804adf25621676d60334bd359dac3a2ec5dc8de567aa2831c10147034025fb3e3afb33c4b +b77307cab8e7cb21e4038493058fb6db9e2ec91dda9d7f96f25acbc90309daf7b6d8a205682143ee35d675e9800c3b08 +aaf7466083cd1f325ba860efe3faf4cebe6a5eecf52c3e8375d72043a5cfc8e6cb4b40f8e48f97266e84f0d488e8badf +9264a05a3abc2a5b4958f957f3a486a5eb3ddd10ff57aa6943c9430d0cfa01d63b72695b1ade50ac1b302d312175e702 +b3f9e4c589ad28b1eceed99dc9980fac832524cfcbe4a486dfeedb4b97c080e24bdb3967e9ca63d2240e77f9addfaefd +b2c1e253a78e7179e5d67204422e0debfa09c231970b1bfb70f31a8d77c7f5059a095ca79d2e9830f12c4a8f88881516 +81865a8a25913d1072cb5fd9505c73e0fde45e4c781ddd20fb0a7560d8b1cd5e1f63881c6efc05360e9204dfa6c3ce16 +ab71c2ea7fa7853469a2236dedb344a19a6130dc96d5fd6d87d42d3fffda172557d203b7688ce0f86acd913ce362e6cd +8aa2051bc3926c7bd63565f3782e6f77da824cb3b22bb056aa1c5bccfa274c0d9e49a91df62d0e88876e2bd7776e44b9 +b94e7074167745323d1d353efe7cfb71f40a390e0232354d5dfd041ef523ac8f118fb6dcc42bf16c796e3f61258f36f8 +8210fcf01267300cb1ccf650679cf6e1ee46df24ae4be5364c5ff715332746c113d680c9a8be3f17cacaeb3a7ba226ce +905ac223568eedc5acd8b54e892be05a21abbb4083c5dbec919129f9d9ffa2c4661d78d43bf5656d8d7aafa06f89d647 +a6e93da7e0c998e6ce2592d1aa87d12bf44e71bec12b825139d56682cdce8f0ba6dbfe9441a9989e10578479351a3d9d +acde928a5e2df0d65de595288f2b81838155d5673013100a49b0cb0eb3d633237af1378148539e33ccd1b9a897f0fec3 +a6e1a47e77f0114be6ae7acd2a51e6a9e38415cce7726373988153cdd5d4f86ef58f3309adc5681af4a159300ed4e5b5 +ad2b6a0d72f454054cb0c2ebc42cd59ff2da7990526bd4c9886003ba63b1302a8343628b8fe3295d3a15aa85150e0969 +b0bc3aea89428d7918c2ee0cc57f159fba134dad224d0e72d21a359ca75b08fbb4373542f57a6408352033e1769f72c6 +aad0497525163b572f135fad23fdd8763631f11deeaf61dea5c423f784fe1449c866040f303555920dc25e39cdb2e9b4 +8ce5d8310d2e17342bf881d517c9afc484d12e1f4b4b08ad026b023d98cba410cd9a7cc8e2c3c63456652a19278b6960 +8d9d57dbb24d68b6152337872bd5d422198da773174ade94b633f7c7f27670ff91969579583532ae7d8fe662c6d8a3b0 +855a1c2d83becb3f02a8f9a83519d1cb112102b61d4cdd396844b5206e606b3fefdbcc5aa8751da2b256d987d74d9506 +90eb7e6f938651f733cf81fcd2e7e8f611b627f8d94d4ac17ac00de6c2b841e4f80cada07f4063a13ae87b4a7736ca28 +8161459a21d55e7f5f1cecfc1595c7f468406a82080bfa46d7fb1af4b5ec0cd2064c2c851949483db2aa376e9df418e6 +8344ccd322b2072479f8db2ab3e46df89f536408cba0596f1e4ec6c1957ff0c73f3840990f9028ae0f21c1e9a729d7df +929be2190ddd54a5afe98c3b77591d1eae0ab2c9816dc6fe47508d9863d58f1ea029d503938c8d9e387c5e80047d6f1e +856e3d1f701688c650c258fecd78139ce68e19de5198cf1cd7bb11eba9d0f1c5af958884f58df10e3f9a08d8843f3406 +8490ae5221e27a45a37ca97d99a19a8867bcc026a94f08bdccfbb4b6fa09b83c96b37ec7e0fd6ee05f4ae6141b6b64a8 +b02dbd4d647a05ac248fda13708bba0d6a9cd00cae5634c1938b4c0abbb3a1e4f00f47aa416dcd00ffcdf166330bff9a +9076164bb99ca7b1a98d1e11cb2f965f5c22866658e8259445589b80e3cb3119c8710ede18f396ba902696785619079c +aacf016920936dae63778ad171386f996f65fe98e83cfcdd75e23774f189303e65cc8ad334a7a62f9230ed2c6b7f6fa4 +a8031d46c7f2474789123469ef42e81c9c35eb245d38d8f4796bba406c02b57053f5ec554d45373ab437869a0b1af3f0 +a4b76cd82dc1f305a0ee053e9a4212b67f5acc5e69962a8640d190a176b73fbc2b0644f896ff3927cd708d524668ed09 +b00b029c74e6fdf7fb94df95ef1ccad025c452c19cddb5dccfb91efdcb8a9a1c17847cfa4486eae4f510e8a6c1f0791a +9455e5235f29a73e9f1a707a97ddb104c55b9d6a92cc9952600d49f0447d38ea073ee5cf0d13f7f55f12b4a5132f4b10 +ae118847542ed1084d269e8f3b503d0b6571a2c077def116ad685dcca2fca3dcb3f86e3f244284bdcd5ae7ac968d08a5 +8dcb4965cd57e8b89cd71d6fc700d66caa805bfd29ab71357961527a7894e082d49145c2614b670dcb231ab9050d0663 +add6ed14f3183f4acc73feea19b22c9a330e431c674e5034924da31b69e8c02d79b570d12ef771a04215c4809e0f8a80 +96ae7e110412ee87d0478fdbdbaab290eb0b6edd741bb864961845e87fd44bcbe630371060b8104d8bf17c41f2e3fca0 +a20db17f384e9573ca0928af61affab6ff9dd244296b69b026d737f0c6cd28568846eca8dadf903ee0eecbb47368351d +937bfdf5feb0797863bc7c1be4dcc4f2423787952a3c77dfa3bfe7356f5dbcc4daebde976b84fc6bd97d5124fb8f85c9 +a7050cc780445c124e46bba1acc0347ddcfa09a85b35a52cc5808bf412c859c0c680c0a82218f15a6daeefe73f0d0309 +a9d9b93450e7630f1c018ea4e6a5ca4c19baa4b662eadfbe5c798fe798d8a3775ed1eb12bd96a458806b37ab82bdc10a +a52a4d5639e718380915daaefad7de60764d2d795443a3db7aeab5e16a1b8faa9441a4ccc6e809d8f78b0ac13eef3409 +8e6f72b6664a8433b032849b03af68f9376b3c16c0bc86842c43fc7bf31e40bc9fc105952d5c5780c4afa19d7b802caa +a107ae72f037000c6ee14093de8e9f2c92aa5f89a0a20007f4126419e5cb982469c32187e51a820f94805c9fccd51365 +9708218f9a984fe03abc4e699a4f3378a06530414a2e95e12ca657f031ef2e839c23fd83f96a4ba72f8203d54a1a1e82 +b9129770f4c5fcac999e98c171d67e148abd145e0bf2a36848eb18783bb98dff2c5cef8b7407f2af188de1fae9571b1c +88cc9db8ff27eb583871eeeb517db83039b85404d735517c0c850bdfa99ae1b57fd24cf661ab60b4726878c17e047f37 +a358c9aadc705a11722df49f90b17a2a6ba057b2e652246dc6131aaf23af66c1ca4ac0d5f11073a304f1a1b006bc0aa5 +ac79f25af6364a013ba9b82175ccee143309832df8f9c3f62c193660253679284624e38196733fb2af733488ab1a556e +82338e3ed162274d41a1783f44ae53329610134e6c62565353fbcc81131e88ce9f8a729d01e59e6d73695a378315111b +aa5ddcabf580fd43b6b0c3c8be45ffd26c9de8fa8d4546bb92d34f05469642b92a237d0806a1ad354f3046a4fcf14a92 +b308d2c292052a8e17862c52710140ffafa0b3dbedd6a1b6334934b059fe03e49883529d6baf8b361c6e67b3fbf70100 +96d870a15c833dddd8545b695139733d4a4c07d6206771a1524500c12607048731c49ec4ac26f5acc92dd9b974b2172c +8e99ee9ed51956d05faaf5038bffd48a2957917a76d9974a78df6c1ff3c5423c5d346778f55de07098b578ad623a390e +a19052d0b4b89b26172c292bbf6fd73e7486e7fd3a63c7a501bbd5cf7244e8e8ce3c1113624086b7cdf1a7693fdad8b5 +958957caf99dc4bb6d3c0bc4821be10e3a816bd0ba18094603b56d9d2d1383ccc3ee8bc36d2d0aea90c8a119d4457eb4 +8482589af6c3fc4aa0a07db201d8c0d750dd21ae5446ff7a2f44decf5bff50965fd6338745d179c67ea54095ecd3add4 +8a088cc12cf618761eaa93da12c9158b050c86f10cd9f865b451c69e076c7e5b5a023e2f91c2e1eed2b40746ca06a643 +85e81101590597d7671f606bd1d7d6220c80d3c62e9f20423e734482c94547714a6ac0307e86847cce91de46503c6a8a +b1bd39b481fc452d9abf0fcb73b48c501aaae1414c1c073499e079f719c4e034da1118da4ff5e0ce1c5a71d8af3f4279 +942ae5f64ac7a5353e1deb2213f68aa39daa16bff63eb5c69fc8d9260e59178c0452227b982005f720a3c858542246c8 +99fea18230e39df925f98e26ff03ab959cae7044d773de84647d105dfa75fd602b4f519c8e9d9f226ec0e0de0140e168 +97b9841af4efd2bfd56b9e7cd2275bc1b4ff5606728f1f2b6e24630dbe44bc96f4f2132f7103bca6c37057fc792aeaab +94cdad044a6ab29e646ed30022c6f9a30d259f38043afcea0feceef0edc5f45297770a30718cbfec5ae7d6137f55fe08 +a533a5efa74e67e429b736bb60f2ccab74d3919214351fe01f40a191e3ec321c61f54dd236f2d606c623ad556d9a8b63 +b7bd0bb72cd537660e081f420545f50a6751bb4dd25fde25e8218cab2885dd81ffe3b888d608a396dfcb78d75ba03f3f +b1479e7aa34594ec8a45a97611d377206597149ece991a8cef1399738e99c3fa124a40396a356ab2ea135550a9f6a89f +b75570fc94b491aef11f70ef82aeb00b351c17d216770f9f3bd87f3b5ac90893d70f319b8e0d2450dc8e21b57e26df94 +a5e3f3ab112530fe5c3b41167f7db5708e65479b765b941ce137d647adb4f03781f7821bb4de80c5dc282c6d2680a13d +b9b9c81b4cac7aca7e7c7baac2369d763dd9846c9821536d7467b1a7ec2e2a87b22637ab8bbeddb61879a64d111aa345 +b1e3ee2c4dd03a60b2991d116c372de18f18fe279f712829b61c904103a2bd66202083925bc816d07884982e52a03212 +a13f0593791dbbd360b4f34af42d5cc275816a8db4b82503fe7c2ff6acc22ae4bd9581a1c8c236f682d5c4c02cc274cc +86ba8238d3ed490abcc3f9ecc541305876315fb71bca8aaf87538012daab019992753bf1e10f8670e33bff0d36db0bf0 +b65fbb89fafb0e2a66fe547a60246d00b98fe2cb65db4922d9cef6668de7b2f4bb6c25970f1e112df06b4d1d953d3f34 +abb2d413e6f9e3c5f582e6020f879104473a829380b96a28123eb2bdd41a7a195f769b6ac70b35ba52a9fee9d6a289c3 +88ec764573e501c9d69098a11ea1ad20cdc171362f76eb215129cfcca43460140741ea06cee65a1f21b708afb6f9d5b0 +a7aaec27246a3337911b0201f4c5b746e45780598004dac15d9d15e5682b4c688158adffdef7179abb654f686e4c6adc +a1128589258f1fbfa33341604c3cb07f2a30c651086f90dce63ae48b4f01782e27c3829de5102f847cde140374567c58 +aaf2b149c1ca9352c94cc201125452b1ed7ca7c361ed022d626899426cb2d4cc915d76c58fa58b3ad4a6284a9ae1bc45 +aaf5c71b18b27cd8fe1a9028027f2293f0753d400481655c0d88b081f150d0292fb9bd3e6acabb343a6afb4afdb103b5 +947c0257d1fb29ecc26c4dc5eab977ebb47d698b48f9357ce8ff2d2ed461c5725228cc354a285d2331a60d20de09ff67 +b73e996fa30f581699052ed06054c474ebdf3ae662c4dc6f889e827b8b6263df67aeff7f2c7f2919df319a99bdfdceb1 +b696355d3f742dd1bf5f6fbb8eee234e74653131278861bf5a76db85768f0988a73084e1ae03c2100644a1fa86a49688 +b0abca296a8898ac5897f61c50402bd96b59a7932de61b6e3c073d880d39fc8e109998c9dba666b774415edddcff1997 +b7abe07643a82a7cb409ee4177616e4f91ec1cf733699bf24dec90da0617fe3b52622edec6e12f54897c4b288278e4f3 +8a3fae76993edbc81d7b47f049279f4dd5c408133436605d934dee0eadde187d03e6483409713db122a2a412cd631647 +82eb8e48becfdf06b2d1b93bf072c35df210cf64ed6086267033ad219bf130c55ee60718f28a0e1cad7bc0a39d940260 +a88f783e32944a82ea1ea4206e52c4bcf9962b4232e3c3b45bd72932ee1082527bf80864ce82497e5a8e40f2a60962d0 +830cf6b1e99430ae93a3f26fbfb92c741c895b017924dcd9e418c3dc4a5b21105850a8dd2536fa052667e508b90738f2 +990dce4c2c6f44bb6870328fba6aa2a26b0b8b2d57bfb24acf398b1edc0f3790665275f650884bd438d5403973469fa2 +a2e5b6232d81c94bcb7fed782e2d00ff70fc86a3abddbe4332cb0544b4e109ae9639a180ae4c1f416752ed668d918420 +b4cdf7c2b3753c8d96d92eb3d5fa984fef5d346a76dc5016552069e3f110356b82e9585b9c2f5313c76ffaecef3d6fd8 +83b23b87f91d8d602bff3a4aa1ead39fcc04b26cf113a9da6d2bd08ba7ea827f10b69a699c16911605b0126a9132140f +8aae7a2d9daa8a2b14f9168fe82933b35587a3e9ebf0f9c37bf1f8aa015f18fb116b7fba85a25c0b5e9f4b91ba1d350b +80d1163675145cc1fab9203d5581e4cd2bed26ad49f077a7927dec88814e0bed7912e6bbe6507613b8e393d5ee3be9be +93ddeb77b6a4c62f69b11cf36646ed089dcaa491590450456a525faf5659d810323b3effa0b908000887c20ac6b12c80 +9406360a2b105c44c45ba440055e40da5c41f64057e6b35a3786526869b853472e615e6beb957b62698a2e8a93608e13 +93bfc435ab9183d11e9ad17dac977a5b7e518db720e79a99072ce7e1b8fcb13a738806f414df5a3caa3e0b8a6ce38625 +8a12402c2509053500e8456d8b77470f1bbb9785dd7995ebbbe32fd7171406c7ce7bd89a96d0f41dbc6194e8f7442f42 +aab901e35bf17e6422722c52a9da8b7062d065169bf446ef0cbf8d68167a8b92dab57320c1470fee1f4fc6100269c6e2 +8cad277d9e2ba086378190d33f1116ba40071d2cb78d41012ec605c23f13009e187d094d785012b9c55038ec96324001 +85511c72e2894e75075436a163418279f660c417e1d7792edce5f95f2a52024d1b5677e2e150bf4339ad064f70420c60 +85549ca8dcbe49d16d4b3e2b8a30495f16c0de35711978ada1e2d88ad28e80872fca3fb02deb951b8bcb01b6555492e4 +8d379ab35194fe5edf98045a088db240a643509ddc2794c9900aa6b50535476daa92fd2b0a3d3d638c2069e535cd783b +b45cfebe529556b110392cb64059f4eb4d88aaf10f1000fdd986f7f140fdd878ce529c3c69dfd2c9d06f7b1e426e38f3 +ac009efd11f0c4cdd07dd4283a8181420a2ba6a4155b32c2fed6b9f913d98e057d0f5f85e6af82efc19eb4e2a97a82df +b2c2cdffa82f614e9cb5769b7c33c7d555e264e604e9b6138e19bcfc49284721180b0781ecbf321d7e60259174da9c3c +95789960f848797abbe1c66ef05d01d920228ca1f698130c7b1e6ca73bfda82cee672d30a9787688620554e8886554ee +98444018fa01b7273d3370eeb01adc8db902d5a69b9afc0aa9eadfeb43c4356863f19078d3c0d74e80f06ecf5a5223f4 +87d20b058050542f497c6645de59b8310f6eeec53acbc084e38b85414c3ea3016da3da690853498bde1c14de1db6f391 +a5c12b3a40e54bee82a315c503c1ce431309a862458030dde02376745ec1d6b9c1dbeea481ae6883425e9dae608e444e +b9daa3bf33f0a2979785067dcece83250e7bf6deb75bb1dbbab4af9e95ddfb3d38c288cbef3f80519a8916a77a43b56c +b682ec3118f71bde6c08f06ea53378ea404f8a1c4c273dd08989f2df39d6634f6463be1d172ac0e06f0fa19ac4a62366 +a4f94fd51ecf9d2065177593970854d3dce745eebb2a6d49c573cbf64a586ae949ddfa60466aaef0c0afb22bd92e0b57 +86cd5609efd570c51adbc606c1c63759c5f4f025fcbefab6bc3045b6ad2423628c68f5931ff56fdda985168ce993cc24 +981192e31e62e45572f933e86cdd5b1d28b1790b255c491c79bd9bb4964359b0e5f94f2ae0e00ef7fe7891b5c3904932 +9898f52b57472ebc7053f7bf7ab6695ce8df6213fc7f2d6f6ea68b5baad86ec1371a29304cae1baadf15083296958d27 +b676c4a8a791ae00a2405a0c88b9544878749a7235d3a5a9f53a3f822e0c5c1b147a7f3f0fc228049dc46e87aa6b6368 +9976e10beff544e5c1645c81a807739eff90449df58ffdd8d1aa45dd50b4c62f9370538b9855a00dd596480f38ebe7a5 +a0e91404894187ec23c16d39d647ada912a2c4febfd050a1ea433c4bfdc1568b4e97a78a89ba643aca3e2782033c3c58 +91a6ea9a80476ed137eb81558ff1d55b8581663cccd41db4fc286876226b6515fd38661557419e1e46b6a3bc9cda3741 +b9e8a1e23c60335a37a16f8085f80178a17d5e055d87ffe8cf63c532af923e5a5a2d76cf078164fb577996683796caa6 +ad8e151d87a37e8df438d0a6a7c02c3f511143efb93fde8aef334d218cb25932baf9e97c2f36c633620a024a5626af3d +978f942f210e8a482015e6fdc35a4c967c67b66e6e2a17a05cc7a0f2163aed227b775d4352b0c3cca6cbf4bd5bafaf75 +b5e2e3d8b2e871c07f5899e108e133f87479959b80cb8a103fbecde00ccdbfbd997540eef33079c5cc14b1c00c009fd1 +88a164b3fefd36857f429ab10002243b053f5d386466dbb9e5135ed3c72dd369a5a25e5e2aaa11f25488535e044e2f12 +a66091c0db4e7cf05a089ec2b9ff74744354d0196968201f5e201699144b52bb13b4e68e12502727163e6db96e3565f2 +8e65aff8e37240461b7374c20bfd1d58b73a525c28994a98f723daed9486130b3189f8efe5c5efcd7f5390cc366038da +8b37c21dd7304c3aa366959ba8c77ea8b22164a67e136808b6f8e48604297f7429a6c6ecf67b1d09b8b7ec083eacd7e0 +b689b1277ad050f53da91a702516a06d7406ff33a4714ea859b3b2b69f8d0aa8f983c7e039b19c0759a3815d841fa409 +b17f7a0a182ed4937f88489e4c4e6163dcf49fd2ea4d9efbba8126c743bea951cd769752acd02e921774dc8ebcfae33b +8b7fab4f90be825ac5d782a438e55c0a86be1c314a5dbc3cc6ed60760a8a94ef296391f1f6363652200cce4c188dae67 +ab8410c4eaa2bb43b0dd271aa2836061bc95cb600b0be331dada76ddb46711ff7a4ad8c466cc1078b9f9131f0dc9d879 +9194bd7b3cc218624459d51c4d6dbc13da5d3de313448f8175650fa4cfab7cc4afcda5427b6676c3c13897dc638b401e +980f61a0f01349acd8fc9fdc88fc2c5813610c07eecb6ab14af0845a980792a60dadf13bb4437b0169ae3eff8f5984ce +b783bee24acea9c99d16434195c6940cf01fc2db135e21f16acae45a509eca3af6b9232a8aa3a86f9715c5f6a85cb1c3 +a3079931c4b90966d1faa948db847741878b5828bc60325f5ebe554dcab4adcc19ee8bce645e48a8f4a9413bb3c6a093 +801f61ac9318f6e033a99071a46ae06ed249394638c19720831fff850226363a4ae8486dd00967746298ee9f1d65462f +b34dbbed4f3bb91f28285c40f64ce60c691737cc2b2d2be5c7d0210611cd58341bb5bda51bb642d3ee2d80882e642a13 +8750af19abfb915e63c81542b13d84526a0c809179bbcc1cd8a52b29f3aba3ae0f7cf6f4f01790bf64ef7db01d8ee887 +a6ea10000eb2dd4efc242ac95bc3b3873cdd882fbeb7c9538c87e3143a263ca3a2e192b2159316a625cfb5fb0b6cdcb3 +aa40ca54bc758a6c64cb932924917581062e088b3ad43976b28f2e11d8a7dea73f1fb50aeaa0e70182bb2dc07d805bb9 +a4779dfd25b5ec9d75dfb54a4bb030364899a5e75c1492403acb19f2adc782c7ac4daeb66d2f5aeb74135afe9f318e3f +b4551e2805d63ca453f4f38b1921ac87ff687e1d70575ad38f3469d6f0608ef76b7b1b98ae1e6b1e7d928773aaab6e3b +99490ee722f96aad2743b08dd37bfeb75a8c59efaee4c9b694eaa05eb8a6bb23861a4480544c7617d04d23fd5e2543b4 +8a7050d964d295fff98ae30d77ce730a055719313457e773fcce94c4d71a9b7cf63db67e54a8aab20fb1335b0130b5d5 +903144e6bbee0a4fec17ff80fef0d2103981140c3d41776cfb184ced17f480a687dd093f6b538584327e6142812e3cd5 +a5b30f7c6939bdc24a84ae784add927fec798b5a5ee3dd156c652df020728dd6d43898be364cf5ee181725fbcffc0964 +b43d97ec2bc66af92d921a5c5c20a03ef2be2bc2c9b345f46d8287409fcbfd88ebc49d4509d64468222cd1d2021bf236 +82dc23c7f5086c9ac6b4566359bfb830d203544b0d8332a210775670f899cd9ff48b94bfeba40040c25664ebdd5cfad8 +9294cd017fea581dabb73dcc8c619904d7e022b664b0a8502c9d30f3807668af279948e7e41030ae296d492225297e95 +8d6c9dc636c8e884f9a4299e5cff06d044ebc94ad783a4b71788347ea4a336d4d048b8a9ecabae789e8fcdc459723dfb +801a80bc49e882ec81b04e37407713f033f7bdac79252dfa3dc8c5bd0229fcbd4019890e402cf843b9378df08f72ab84 +b4313ca32569d973900f6196363c0b280ddfa1b47c88d019e5f399b805b444a777950fc21ae198fc23ece52674b94abf +96f06056fd255fdabf78986e315e7c4fdf5495cf850536b7976baa97a994cc6a99c34609c33a0f2facba5e6f1026dce6 +983ed80220a5545ffd70ef5e6ac10217d82ec9cd8f9a27ee77a5ff4074092308c0e6396fc4e9932a77ddd474e61f8b55 +872a059aa630af73c4abbd076e8b333a973ffc5bdecf5dcc0600b00162184213cb19d4f601795030033beb808d5810ce +b040f318d9d3b8833da854014a44296dbd6762dd17cab13f91987256c54353b7f0800547cb645a7cc231997454209fdd +a8c4731a555308e8ce0b8325eb7a4cbf6113d07e9f41932df04480b72628d313b941c7055f1cc2ac45c7353b56e96ca9 +8c24031440b77637e045a52e5ea3f488926ab0b426148975edf066c40a4581beecc1bfb18fc4cf5f9f96dc6681b4bd28 +b39254b475abf342f301298feaa17a4b3051f30ea23a18acf59e003e2704ac96fe40691f1da387913bdf7aee6389f9a8 +a1dbf938b604ccc6d60881cc71f38df568aa02752aa44d123514154017503f6c1c335ae43e359f1487bc8934073cd9c1 +8d52aa1be9f429ece0580498d8fe9fef46d4a11f49436a82b8927f9503dacc41245907f126594c1cd30701286f8c092c +b826f396486942c0326d16f30a01b00a682c30a75553dc6ac34fd5b3e96b13c33b94738f522eebaffb59ff8c571c76e9 +aa89f51cbf6e6c3e2aa2806187b69ab3361c84e89f393f3ed284fe84db46fc3944aa44f8928e3964f9c1a1ec27048f68 +a254df0efa4203fb92b42a1cd81ca955922e14bf408262c8f7cb7dc703da0ca2c71556bd2d05b22ce9a90ad77309833d +93263c507e4d5f4e5df88e85b3d85c46ea729fb542a718b196333e2d9fb8a2e62dc1347cf146466a54ba12d200ef09d9 +922e3c4a84246d89a07aa3e90f02e04b2cea9bebc0e68b742156f702aed31b28c6dfa7ac936ea2fc2e029adf68361f98 +9a00628eeeda4ccbed3ef7834149aec4c77aac1a14bc2491ba5d1a4a2c5d29afb82ceaa5aac1c5ce1e42cdcaf53e30ba +ab3a88df36d703920f6648a295a70ffa5316c96044f39ff132937bfda768937cb6a479e9ba4a4e66b377f3a9996a88c4 +966b11526ab099d550ab33c6a9667e5cfdedf255da17a80a519d09acd78d2ea24ec18bd1ea7d8d63cf0a408f1c1fe0b3 +b5c21b9817dc32f3df9d9988aa3560e1e840d586d01cd596bc0f850ab416b6013cbf7dbfd05ac981f26014c74bd2d2b2 +9040abef5e2523e7f139c9f744a64b98fea3a57952059ffe4d5ed77fa87068203c090ef4e7f52c88fb82ea8a6fdca33e +a0dcdaeb7d3f5d30d49c004c5f478818c470187f4b0b4856812dcd1b3a86de58a99acb8ceb44c6b80c3060cf967c43a4 +b5f4be9a69e4a6719ea91104820df8623b6d1073e8ee4168de10a7e49c8babea772bcbc6b0908185e98d607e49cd3609 +8634020a5a78650015763c06121c606d2dd7b324aa17387910513dd6480fb797df541fc15b70d269b2794ad190595084 +9504d1d0fb31ff1926c89040c04d51fd1f5cddf9d7ca3d036e7fd17e7a0f767ef33cee1d8bf7e17e2bc40949e7630417 +812c72846ef6d692cf11d8f8c3de8fa78cc287303315114492667b19c702cd24d462020f1276895df26e937c38f361f8 +8c97aa5e9ef2aa9a1435ef9ddfe62e850f0360864ed5fb82bf9fef4ef04d8fb4f827dc078bc911ee275e4501edd6617c +ac5f7af5e23c8e429aaa6b6825129922b59d25b4608f07b65f21388a9ac3aa89096712f320afe6d56e44e1f0d51a4eb9 +a8c84d9a8593a0cb5be1e450960f59878a4e6b70da54a7613dfc25911b7cc9e6d789d39401b0a0d6471ab9dcdc707976 +8c9d5fd89611392c0f085ffa4fa642a181f0b9b23593deb5e10fdd1642722ca75ef34a037e88a8d03f2888fe7461f27c +8c74b05f91fb95c85e7bd41f6d9a1e41e667e68f3d19b325c1f25df1767019919edab89b92af237896cbc4e6d6dc1854 +a3caecb91640821f0b2c4981b23f2069df8d2b98ce026c1538bc096b292f5f956a5d52c1c8d6a8165a1608083ba6494b +8ae8e0c36f8b79a69176ff29855df45d0fcd9e4d1dbaed8899f8fcdece676e418ec034a6c161e2a894f0c834aaecbfd1 +b88d18c67dc3b1b6ed60ee437c441c1ed14ecddebccf43683605716f30058b1aa4ba05ff10cd8171ee97d8f58d70c094 +94f43d84dcdfd9cd19115c7d8e9c1e856828eafbfdec93b876cf0007e317e30b2ad951dbabc186aa6ef90fdee4d91990 +b44e4723f41fc1d5b0057f371e3381ae02566590b3f964b6eb07b2104f66ff78410c407235fa98d04f635694f3baca09 +addd8390173d29ca0811534d389253831fed75fed135398617836b6e70767269eacb1560b39a58f02042ca3b97fe59c4 +80bdbdacc0c358c7ea52aeacdc5f9ceb6928bcf6e7dee7c17d8ae3bf7c2372aa7a0372363888968fc0921aaf4776d5d0 +a486e2b6f04f403f9e609d69dfb3cfb992af56ecad1683271df3e3faa3b86638b81e73b39978fb829ee7133d72901f2d +a19472da57457e10c6a6307895393ddaec8f523760d66937fe26a025817319e234eaf69756ffdf1b84c81733424a96d7 +ad6a195397cbc2d75171f5e82090441eed60bd1ba42c39ef565b8b5a8281b04400678625b1dc46d617f694a7652a8e5d +8f98e721c06cec432e2221f2e1b06bb1469d916a8d88d6973acf68d1e003441d00390dafcead8ecdbf9eae4509baf5aa +91d62a0f9d13c59adfe1376ed6d057eae244d13c6b3d99be49a49e0075cf20f4085cf127774644ac93615be9ac9e5db6 +af45dec199245e2b326a0d79c4899ed44b1c0219db42602a4a6184ace0ff831a3276297af28f92e8b008ba412318e33e +8754bde54e8d2d169e6a7d6f0eae6097bc0461c395192bd00dd6f105677ea56ab384c02553ea5eeac0a65adcb0df77ee +b676afd2f5afc37a314c943d496e31b4885efcbcc2061036e370a74cfde5642bb035622d78d693bfc3136fc036c7edb4 +aab6ffe6cc234397cf1822e02912bc282dfb314e92fb5a9e10d0c34ee9b5856d4b76e166bc2bb6fcdd66aabea35ec4ef +ada6e62f90ee6b852ec4b72b22367acac2896f0df2c105beda27096583ddbedddc710d171330569f111c6e44a5b57ae7 +802139dd15241a6de663d9b810121bdd9cf11f7f8c8ca6de63f4f8e731409e40d1fd3558b4f619ed42ee54929dff1c7e +ad8e70531cec21b4e6f55be1751c2d025bd2d7d8158269b054cfe57fa29252d052ce4478ec7db6ec705789e2118d63b3 +a8e4a4271769480e1b33a28c87a150ecc0b48bfe8a15ae04152197881de4ce4b03453aefe574842424edbbe4173e1a3a +b98c65726296610cef16c5b58da5491acd33bd5c5c5af4d934a9840649ef85730fbce8018dee09ded14e278009ed094a +8e213a7861223287b860f040e5caaa563daa0b681e4e09ec79ad00cc459238e70bbeaf7486bbe182fc12650700034ec5 +a2879f9e1a556cf89b9b5b3bd8646a8cce6b60bcbc8095df44637f66a2da5858eee2dc9091475a8f64bb5aff849389cd +8a17cdb4077b9b0bcf28b93294ac5ae4c8bba8839fce0f1012b53187ac008f9858b02925fbfc421f1123afcdbd8b7753 +86fd9c11528aa43946e4415ff64a3ca6409ee6f807368c68997b18605da65e415ccd85ad913820d450cb386593de666d +8ed55923b963c3d85a91aca11c40ff9c6c7f1e2b9bc199d1a270e5fb16aa62dec0136e97866145ae9d58a493e8b1cbbb +ae32af5b5d418668ae123c639b149e5eed602404e8516da4a61db944b537a3620545e8e3d38cf10cdaea980ab2f80973 +95cb8d9e9d6762d78dde0ad73869ffaca904a7d763a378b8cc11a7933d3e7d1c8aec4271a079b1b00f8887ee5b1ea21f +b5ea20b42a3ca247f00ab5328c05f0cf194973d5f7271c66c41c5055b1ffdca136be179709e0c1de209fbe07b9820bf3 +98682f7cce471c92a8d6d15fee4ddf4d43dd97c3e3811d2913618ecacc6440b737717c07736ae4558c910e11ee98104e +a67da2c7cbba48e929ca4e4b9a6299fe01ef79eff8cc5cd3fdbdc0721a68130e4079f30ae151a573a7dcca8ecf2e684e +a9981c9f9dcbb3b0f6996f664fb2acd7573189f203be37b2b714662aa273551396abfb1f612ccde4e4c8127a050dbe4b +92d55eff8da600f886da9bf68e8eecf482faa4b268f3f286b3b3e5cc91b19604081498d4905b201bb4ec68e32b5591d9 +963e3f1728de9d719c86d390f3eb9c3f99d1928347fab0abf10dbb37d76b59ddb64d4734c977863a6cd03ffece5ca895 +93480e2de83c921056b6d8628ac37cd5ef7555ba43b0308fc13386cb0515d42c12ecd06057137aa71a7931beaf90b9ce +8feae57ff0e6a162cc81c99f45c6187d268fc0bee8c2bffc92142ef76c253d201f0e932943cf2fa312982b281ce1066b +8f8f4bd4200fb87afcd743274480220d77571928000d4197410dbb75439d368df6a06d941a6152206371d2ca9cac99e4 +8ee7f11e79af4478e0a70eb424fe8078237ad99ba6d7e6bf1a8d5e44e40abd22d404bd39b718ad6fdf4c6601f2a47665 +a98acfcec612b574943195b9ba95bebcc9c0b945c9f6b3e8760b2a4635909246a9d73b0b095c27b4ecb3339704e389b7 +b520efd19f65e81dc285031ea3593f8c5dad793e4426beb9196ab46e45346f265fd71e50adb0da657977c60ed5724128 +a3d9d0b7415280ce4dfa2429d47b2b8e37604a5157280a72cc81d541ffe44612dbb3ef7d03693fc42a569169d5842dc3 +8c29e2d0b33801f6d9a9c065a76c5cad1fb0a001506b970307e21765ee97c732a4cbf1d7c1b72d95e0ad340b3b075224 +839e21f292892a6eb596b9b1e9c4bd7c22a6fe71d3d04487c77840028d48392c5cbe73140a4e742338e0c8475cd0c1ad +8bea5c68e7743998619185bb662e958f1b4d3ca81019d84ac43c88911aab3abe4ee9bcc73cb95aa3ae87c0138801bde3 +b8f262d21a94604049e008ce03dc857848168e1efca4522acb0ccc827ffb37f545e1947843a356563a76bc6489605b66 +a7bd0842b0bb38d9943b82aa883f36f4eb8a6e8a7790d4f87faf306608f51d250a19b73984f1156cef5dd2581664614b +a993e649bd953627a88a2539dac3a12ec7f37a4c65b01425d9d34edf7ee10a71aa98f65c9e013107f824faf8aee041a9 +8e07eced75c67cb4d2ec01857f6ac1408482e6b31cb2faa249e8cf99f180575587df530c7782a7539b5221121ef48aa0 +b2f4578f26c05ecb9e2669ca744eb19d4f737321ac7d04fafd18beb7866e0fec9dd063953ae1f077b44b9c6f54db1279 +b6b3788a6c7bcaf467d19daf6ab884d549aa866970c05a9181f544ff190d043192c84fe437a75a30b78b425461cca062 +a270684903c61544b85a7041e81f65e787e1c1e23e57538fa8a69836bed0ca1673861dd29f743a1280f2f38eddd3aa83 +a9c2397c4773dcad2821266dadfd2401d013d9f35de6744f2ec201f3507700adb1e6ec4f5a453be4764da8bf68543f26 +83a3025ed6fd5df9d98be32a74e10a0d9728b560942d33ba028536fb148fc34ae87e92be2df3e420a8dfec08da495982 +90dc70c183a90bab988b4a85b7b921c8070af0e5f220364fe11afa0722990b2c971e1e98eef62d3287fedfd9411f1df7 +82d940937a6c636224d04f8e2536f93dcf20dc97a5f188875ad76c21b804aef9af10839419b61143c1f88a695959a6b4 +8017f9473ce49d498d6f168137e77e62fe553e5a51e75b519cf2cbd1ab9afdafad80fd5e6fd0860e640b0d78ca8ed947 +80573a0ec049fe1f7b3013b2839e145cd87e07c0e43826a29ef8c92516f9a30896c2ffcf3ed77ed22a6cf3101b1789d5 +953349abd2559f9824db07cec857ad54f1a05018f3076425f8dbae37f8d92a46af2c04ab7c8ec0250449541187696e98 +ab7bd2c4f05ee9a9f252c4e16a20993a12c535c3809d124bae24642616521a9768d3f19eceaf8524583f47ae1f527684 +9883b77ee834ee0112ca2f366d2a6fc213e0cf454e061438c2901a5ba35b7378f64da8adf6a476eb1562991ef5b4a5bc +89291811db308637356dbf7ed22cf07bfce33eb977734ee346e8c15a231b35d8b4443574f3fa97a40867b3e23b0bbfa4 +93d753849d7d9588d39e38217500b123a6b628a873876612d9f98b5d611f52c89c573432d2176752b5d1cc2d94899b8b +a45add3c4844db3b7a237295fc85fddc788ac1ec395a0524d2fc90a539571a247146aea4aa10eec30a95e9617c85b98d +90f94578842db7a4de672da1e483858ece5e466c73c12f725a0fc71f42ff880c9447a33fa9096839bee817536f2591e2 +b2c1b6fb031bb30460f157356562b44b4de096a0a112eab4fb3cc500aad38bc770da1fc2e73caf687a0da5e8537049c0 +afb15e15fd930929c0e3c66482068a5afe0c7b7f82e216a76c5eb1113625bfa0b045a52259d472284cfbaf4796c71456 +ad222a9a3d907713418c151b8793d5e37634354322068f8206b9d0da1a3f53b0004193713d23ec35990639a1b6c2e075 +b44a128dce97e8c4b178cdbca0a5c1b3f6e164490fac0fd68dbfe0aafa89920bb4ea420a8527e06c80dd19c2f135e3ef +8596e993ef18b8d94e9c42a90cb7060affc586b8e9b526820d25124285de5590134e2e86592e9dc4dd45ccf5d578fa60 +b71bb0ad138141ed506b2253e84110d2db97cc2d24a3fd0d096b0022d9f38f87aa74e2f505074632d64e90bcc491aa30 +84841eafd357309de47b92ca5ec163dec094a2e5271bc65898c31932e0160bee165e4decb23af339cfe09c83e1cc5441 +8a2915ee39a6fd4a240b98533d7690ef1773ce578ed1fb05ed414ebe36f7ef289fa46f41768df57190438c356331e329 +90bb337165386f1990cbd8ed2e8321ef21bc18125b015b4da0c37e5fcc446b26005379ee4fad8ce9348ceb4ab49e82e2 +b707b50ea2ab05c6d183671587f25fe29eef23fe569d731459a1ac111a0b83a2cd65b88242876b34aeead3b05a15d745 +ae1f159f79b7996315c4f9acce7e21a6ed59d4ef76331196fc86911fda3035edd5c11d568b105175a36c948d0263b382 +922bc525bace05e5dff6b5cabde5469ddd2c1c601f7131abc04ecefdd35095e6ac015b1aec3c3b25c5dee8d139baf60d +a7b060405b2740f82db64683187b1bb89e5f40c8438663c7cbc8ef2513929fe5f92625667a7f2f599a72a96b1fc8f08a +b9dfe94a08651db5efefbb813269bce80d814e3089b80c0654491e438d820bf521f8a4a4477909344ba88f7683eebb43 +841817a9729465743576950b6e8eea32ebf39cca99ace86c4792f9f35926e2d6830c52854a3b2eaeb61694e6845008bd +934128034bde8fc7b93b952aa56e0ed28b36cfa04cfa1f0d5b38266dd40beedff5e0bab86e4717b0fb56c56be2eae26b +aee9d64caf28596308782cd8f3cf819506daf3378f86157ff775e618596411adf94efd0e9542787ca942066f02cbd332 +85871184db314411a49575fee088c52ed5dba4e916ee001ec24d90898a0154d9790a06aa8a707ca7a8b986c0293b8d89 +8d3d87edcc0187a099c97b581a598d357a41ac152303bb27c849eb78e72e15cb97cf9a0468fc36f245c3e152c76bb7dd +900475d165dec18b99eb7b5f9e9ad1d2d4f632e55fdcc4c5ecd7775fed462990e6aaafe9c669f40508f9b15f00bda31f +a25b5954edd57e7811a0d18532043d975c7b44b80f65cd630935d7b16ada05f30fe2b7be7ae8a2f54c25957faf3f1950 +a089019afa3a7a15f7e7874e73b6773c0a824e6d3379b4c928e173321fb165ad979a6be004d394c28d19d410b2655d3e +b28f46797dee0c538bd3de815df641a0ef718ad3e52b2764aec380d6905b38b50ad6f60d0f68e096ca39960ba7734355 +b0ac155d3d05851b04104e6b459f1a68e9e155437c92421a7c0e4dd511ef89cf71dfa3cc920769492ee283a65ebf029e +813c69a810745580d43d5b5480f0ba81000fbef0071e6b655c7346bef5ed774e9214a7816d40eb1774a5bd033767a046 +b176345ca75c64f10ec33daa0dcf1f282b66a862fcd3d8d66c913f9a02db4c9d283dadc02eff13aaab94bc932a42234e +92560f67e5b995db4a489bb86ee78b4aee0800143b3535ad557a53e9e08716bd0202d9f5714722c2a5e8310046e3f5b3 +8adb427bad9cc15fc6c457a96a6750dda8c46d859c5f69bf0e7ab8fc0964430b33967fd47cf0675b6ba1757f91255e6e +b120f723b80389a025b2daa891b140b3d7b8d520ae2a6a313f6e3d365a217af73292dcb249dca1f414ec05e865e3cdc7 +a61a5d261a8dfe5996c42ea0a5ae703a2adcfda80e86837074d868eee16f87d38da19596c48b55dbd7a7cbec1a9b4996 +99dc921eacc6bb867c5825ad4c83bc4af9dd78a18b3d0e1a60ad493e3805b8fb9b7922b577da1adb3d805edfc128d51d +85455fa165a07282aaab4a5bfb88027f47b9532e4af8195c048515f88b0db7e80f42e7a385fd4944faaa7f2a6544ad17 +96dff2d1c8a879d443fe576d46bcceaf5f4551d2e8aad9c1a30883637c91090de99ad5eec228eb5febf93911502d3cbb +a87eb7f439377fb26c6bfe779701f4aea78dd7980b452a386afec62905e75217a1996c5234853432a62ef8bab21c31c3 +b598278293823e9ccb638232a799211173b906444376337fdf044d0227d28fcc4c5867e6ecb3200e59ca0b139e71cac9 +aa6fe147edc95027654d68140f428ec53cede3552c5f49c09d18bc6f6ae8c739a63042eb7291d14d717a4e1f0778abcb +ae8ee18913d328b2fba71efe65526d3ee9c81beda53cf776baec4019ea30212010758cbb5dc85ed6620ce04b189f01f2 +ae9fb686777e88dffdd42805fe4114aa0da1b350d92a27ff3f8a817fb25af1fcfc9a06155affe0273bf13caad16a5351 +95d372ba3a2ee38371538f34aae91b4844488e273f70c02f1992370f89fc2343eff95692d52ce9f21206abbee4959958 +b15260376f0a34ca2827ff53acd7eaaef94c9acc2f244b36500423069cb1cdaa57ac8dd74adb5b53d0fd4265fcbb28ea +b0ffce6a8059537ef6affdbbc300547ef86e00109289239b0c6930456c562b4ed97f2e523963af17736dd71b46c44ac7 +b5499a1277d34f9892f7579731ff53f423f2ffffa9ea43a6e929df8c525e301396249a2324818a6a03daa0e71fcd47b3 +98dbfb8e97a377a25605a7665d4d53e66146204d8953afda661ae506858c5cd77ff7f21f5f10232e06dbc37378638948 +84177e27e6da0e900c51f17077f5991e0e61bff00ca62c1623e627c5aea1b743f86eef6d55b13219a1947515150bade6 +b50407bb5c61b057ab8935df94fd43ca04870015705b4f30ceac85c1035db0eb8293babc3d40e513b6fb6792ecbc27a9 +988699a16917514e37f41ab5c24f4835ed8a2ca85d99972646fcc47c7e2a83c2816011144a8968a119657c4cda78d517 +920c43fdcb738239ad542cb6504ab34498bce892311c781971d7db4dec70e288676de4d8697024b108cfa8757fa74035 +aaa106329aac882e8d46b523f126a86d3cee2d888035ce65c0be4eaae3e92fd862f6ac2da458a835539cccafaba9e626 +96e4c1562d14b7556f3d3e8a1b34ea4addc5a8170e1df541dc344728bcb74cd1630eb7ba4c70e9c68fd23c5c5d5a729b +a616ac5016d4e68e03074273cd3df9693ee0ce3458e8758b117a5c1bc6306dd2c7fad96b1bb37219c57ac62c78ad7a3e +8db7d9b20abfb1445babd484ae9e38ff9153ac8492230d7591e14e3fca7388a5ca6ef7d92ed445c8943cf5263e4a6ad7 +88464134221aa7134878eb10928f31c8bd752ab68c27c9061c1de3f145c85731a4b76acdc7e939b399b6e497f9e6c136 +a5f7c794f70b7c191c835dded21d442b6514bab5e4d19b56f630b6a2f1a84a1d69102d7a0dcca256aab5882d3f30f3ca +b96b6f98b6817b5fa6b1b1044e2411bdf08bf3ffaa9f38915d59e1d2b9bed8b3d645eee322ee611102ce308be19dbc15 +92c26ade2e57257f498ac4ff0672d60b7ea26dad3eb39ed9a265162ccd205c36b882dba3689758c675f29e20836b62d9 +8379a0299e75774930577071d258e89e471951642b98e5e664c148af584d80df4caa4bd370174dae258848c306f44be5 +a0e53beda02bd82bf3d24bd1b65b656238128e734b6c7a65e3e45d3658d934f909c86ca4c3f2d19e0ac3c7aae58b342e +8ca5ceaeaf139188afd48f9bf034d8baf77bbf9669791c7e56ebf783394d7fcdf2a25fa4bdfcddfde649aa0dc67ccccd +a8060e6448844e9db4e9fb4da1c04bcf88fda4542def5d223f62c161490cf1408a85b7c484341929c0f9ce2a1d63e84b +af6e1a5ecf50b754bb9eb2723096c9e9a8e82c29e9dcaa8856ab70074430534c5395534e1c0ed9ce98f4b84d4082fa67 +81c8dbbef98f1b561e531683d5ae0f9b27b7f45dc6b2f6d61119ca0d559bf4ceb676d320afc5aba1811eeef7547a59d8 +85b46cd64d605c7090a2faf1a2aadf22403b3692b3de1d83e38b2de0108d90ac56be35b0dca92c7a41c4b179a3567268 +8dd3cc3062ddbe17fd962c2452c2968c73739608f007ad81fa1788931c0e0dda65032f344a12249d743852eb1a6d52a9 +8630f1707aea9c90937b915f1f3d9d7ba6bda6d7fdef7a40877a40c1ee52471fd888f84c2b2c30b125451b2834f90d3b +b4a747e0bd4e1e0357861184dacec6714b2b7e4ee52fa227724369334cf54861d2f61724a4666dae249aa967d8e3972f +a72de682e6f9490b808d58f34a0d67f25db393c6941f9342a375de9ca560e4c5825c83797d7df6ed812b71a25e582fff +8d5ea7d5c01f1f41fffe282a334262cc4c31b5dcf31f42cc31d6c8e37c9bd2f1620a45519dab71e108fe21211c275b6c +8ccdc7e3642c2894acbf9367f3e99c85963cea46dc5473d175339a2391be57dd8815feacadec766e13645971213b9eb8 +858e9b5fc8c13b651ff8eb92324bdda281db4cf39f7e7bd0472908b3e50b761fa06687f3d46f4047643029dc3e0ceeaa +ae20d36c70cd754128c07cbc18dcb8d58b17d7e83416e84964b71ccff9701f63d93b2b44ec3fddc13bbe42ebdd66221e +860dbf7013da7709e24b491de198cb2fa2ffd49a392a7714ad2ab69a656ca23f6eafa90d6fdc2aa04a70f2c056af2703 +8f809e5119429840cb464ed0a1428762ba5e177a16c92581679d7a63f59e510fdc651c6cc84d11e3f663834fcafeafdd +8d8a8dce82c3c8ea7d1cb771865c618d1e3da2348e5d216c4cbbd0ac541107e19b8f8c826220ca631d6f0a329215a8d6 +86e3115c895ae965b819e9161511540445e887815502562930cedc040b162ecb1e8bdc1b6705f74d52bf3e927bc6b057 +b9833b81a14115865ca48c9c6a3855f985228e04cbc285f59bf163dca5e966d69579ea4dba530b1e53f20bd4dccdc919 +a71f5801838a6dbb162aa6f0be7beea56fadac1a4bcd8113a0a74ab14fc470a03775908c76822d64eb52a79b35530c05 +a77ab73ae94b6d3378884f57eee400eff4a2969aa26e76281f577a61257347de704794761ea1465dd22a6cc6304fbc4a +acd1c5df3c487c04cf27f002e81f2348a0119349b3691012526a7b0d3bf911cdd3accbc9883112ed2ba852145e57fe68 +8a28515a48832ac9eaf8a3fb3ad0829c46c944b4cb28acbcdbca1d0d4c3c623a36cda53a29291b8f2e0ea8ee056b1dee +846bafca11a7f45b674237359b2966b7bf5161916a18cf69f3ec42c855792d967d3bf3f3799b72d008766206bb7a1aa3 +b24b341675b1db9a72c3405bbe4a95ccdfd18fa96f876ec946ccb5108f73e8816019998218a036b005ef9a458e75aeb3 +b99c267b4a09193f3448bc8c323e91ef5b97e23aeff227033fe5f00e19bab5583f6e5fcb472ec84f12b13a54d5c0e286 +a088aa478dbe45973b04ecafbcbd7ee85c9a77f594046545cdb83697a0c2b01b22b1af0b97dd75d387bb889e17f17aa7 +a0c6b0cdff2d69964134a014e36c3709d9e63f6463c5cd7b01b6f0be673731b202d577539d89dd57a888326da1df95af +b4e6dc4ef11b2b41794ece70a8968e56705199d183366759568b6fa845d2cae127486e926b5b27ae9118bb21d1682c1d +a007804353f174098f02540a57e96227232444d5ae0a24232c244647148b6c049848cbd2b50d0a25af3ca9164bfff8ee +873fb034cc39c9cee553ece908fbf315f62efbc412b9afdde6a1889326b7f6f813e050b0601ba9921688e958cb75942e +b5676c90f0106c40d8683299e59d564f505ec990230cb076caef3ae33f2021e6aa5c9b27bb8fead05fc076df034c28f5 +b5a67fc4c5539ad1ddf946a063110f824f7f08d2e4d30762c9d437748c96c9147a88efc22260573803ab545c18b108f2 +817ff2b748a949973a91b69b0ec38efbd945aeb26a176d19f0fb76e261c7526c759e6f5516f9ed34de6eb1ac7838c9cb +99b76bda3526a5d841e059010fdb14eb2fa035a7d10463373a062a98c3c1a123e2da0848421dd7546d776438fd05e304 +aa0d363270f90d56bbee7ea577b0c358532bda36d9247af6c57d000044a97ba41e35bb0db438f4c94551c6350e4e0674 +acdae205d05f54b9544be96c9032350511895ccf413dbbc56d1f03053185df22a6d5b7ffcc3fbe96c3e2ce898ccfa73e +b091c220a1de18d384f50dd071dca4648ca4e708162c52a60e2cedc0188e77c54639f75bce9a468a64b2549119c07ded +878676133e5c700b1d4844564fa92a9930badb5293d882aa25ee6721a9f2cfab02088c31d62cf1342ae3edaea99a1ea0 +9756d0793e6aba3b4dff48100bb49a5ec08ec733f966cb438379b91caf52fc2a5930830ec3f49aa15a02c82c1914dc7a +9722f760184d3b2d67cb2cea7fa41b1ff920a63446006bd98c6347c03d224d2d8328fa20ccd057690093d284b9a80360 +b5a68489de4f253715a67f0879437bfe8f4dfc4e655ca344848980e6153b1d728acde028bb66fd626fa72eedd46ff683 +a8cfc900b34835d9fd3add08044636f69614eff9ae929eac616c39bd760fd275ee89bf24b0f275dd77a66e54fd6b94e5 +89967479bebf70b2893cad993bf7236a9efe4042d4408022fdbb47788fabedcec27d3bba99db778fcde41e43887e45af +889235938fcec60275c2cf0f19d73a44d03877d817b60bb26f4cbce09db0afae86d42d6847b21f07b650af9b9381fa82 +b7fc321fa94557d8fbdd9fff55ab5c8788764614c1300d5ef1024290b2dbb9216bce15cb125da541f47b411a2e7e3c2d +b11b0c4dc9477176b3cda6b17858dbd8c35a933ed31364801093f310af082cb5a61700f36851e94835c5d4625bf89e32 +9874e54d2939ee0600f4194f183877c30da26d7515e9e268fea8d24a675dd2945d1565d9016b62b1baab875ac892f4d2 +90df3a77280d6f1fa25a986309bba9d5b89c3cf13656c933069bc78e6c314058716b62eacfa7ab4aff43518b8b815698 +962b08299a287d77f28d3609f39fd31bc0069f7d478de17539e61fcc517045050644b0307c917208b300ce5d32affcca +b30eedca41afb6f083442aaa00f2e4d5dc0fda58e66aaf0f44e93d4af5c4bf8ea22afec888cacbf3fae26d88e8d344cc +847747a22fab3fe3c8cd67f3f1d54440f0b34ce7b513225dc8eb4fa789d7d9f3577631c0890a3d251e782a78418fecfa +8d1ef3cb5836e4039b34ee4e1b4820128eb1e8540e350309e4b8fea80f3ae803d1f25f4b9c115482b324adf7c8178bc7 +8f8a2b0b0f24f09920b58c76f7d99ec2eb2e780b5a66f2f30a9ed267dcaea0ec63b472282076c7bf8548211376c72f6e +831ee6dc8889bbf4d345eaeb2f425959c112d2190764abbbe33bc44e1d9698af87ff5a54d01fac00cfee5878dee7c0f6 +a7eb2479ac80d0ee23f2648fd46c5e819ad3a1f4752b613607ae712961b300e37f98704880ac0a75f700f87d67853c7a +aa4d1b9cec62db549833000d51e83b930db21af1d37c250fdc15d97bc98de7a5af60dbf7268c8ec9c194d5d5ccda3c1d +87396fd7e78c4bcf270369c23bc533b7fb363ca50d67262937dab40c7f15bd8448a8ba42e93cf35fb8b22af76740d5e1 +a958b2a9ffccbca13c0c408f41afcfc14d3c7a4d30ea496ce786927399baaf3514ff70970ef4b2a72740105b8a304509 +a5963a9dd3fe5507e3453b3b8ed4b593a4d2ced75293aee21bfed7280283348d9e08bf8244c1fce459aa2470211d41ea +8b06ddc3359827558b2bb57caf78b3e5a319504f8047735fcc8ec0becf099c0104a60d4d86773e7b841eb5b6b3c0cc03 +9437e7278283f6d4d1a53d976c3c2c85c5fe9b5aec7e29d54a5423e425b4be15400ed314f72e22e7c44ee4bacf0e681c +b56067ee26a485ed532c16ec622bb09135a36c29b0451949aa36fee0b0954d4bf012e30d7e3fc56e9f153616b19349bc +a5c72f7f5d9f5b35e789830a064a59c10175093a0ce17654da7048827d0b9709b443a947346b0e5d96b5ea89b8d7c575 +a8318d01182d4c9af2847a29a6b947feef5795fc12e487a30001cc1ec482b48450c77af4837edfa1aedf69f0642c7e5e +82ea421c091552d3dafa7da161420cb5601b819e861dd2ba1a788c3d1b5e8fa75cc3f2b0db125dde8742eb45b335efa2 +8679fd1c7771ea3b12006d4a972f4f2892e61f108107d4586f58ee7f2533d95d89b9695d369cdace665f19c6bc3bc85e +b5ab3e8adee4c950fce4d33a0e2f85d3d886e60a6e2f4454b57bc68725f0cf246372d863167482cce1ea10a7c67c3af2 +a85696927075ec188979180326c689016a0dc7a2f14ae02ea27c39ef91418cd44177d3fca5752cf6b298fd75fa012e26 +a44f87b7232f102cd092f86c952a88afb635484a984da90a41a57a3d883c9469064bf105b9026024090486b6c6baa939 +866ac91a437db945bbfdc11fcee583f3669fa0a78a7cecf50fbfa6ed1026d63ad6125deba8291452bf0c04f2a50e5981 +b780d5a1e278fd4eef6139982e093ceafea16cb71d930768dea07c9689369ff589d0c7f47d5821d75fe93b28c5f41575 +b025d0046e643506e66642c2c6a5397a8117bbfe086cee4175ff8b7120e4f1e6794e1e3f6ec11390993cca26d207ae43 +a04a22b6e28c959ab265c7f48cde42bb6a00832c6beb2595b5df2879080a9424890960417d7d7ceb013d697d0ebf7267 +81de9c656ac27f54d60d0252e33aff4e9e9e9c3363a50740baf15a2b9061f730a51ae1704e8c4a626153cf66d47f19b1 +a15fab90599df889df11fa60c752948b68fba54005491180dafb66c5775547976d0eef33945e55d4818653e0818c6f92 +b06f9be44ddb103a72fa4ebc242c8ee1975fe9bf9ef7124afeda9967ff3db644dbf31440151b824869406851a90984a2 +99abdfe6806ae5efa2d11577da17bd874d847c5f810460148bc045bcf38c4fd564917eacb6ed61bb9164ed58055cd684 +ac53231077f83f0ae5f25e52b70bb6105d561c0ba178040c11c3df8450c508ed5df34f067fdaacf716f90b4926f36df5 +99e3f509af44fc8d4ebc693d3682db45fd282971659f142c1b9c61592573a008fc00502c6af296c59c2e3e43ed31ec7a +98f2f5819670aff9a344e1c401f9faf5db83f5c0953d3244cfa760762560e1c3a3c7692bb7107ea6eaf5247ac6fd7cc8 +b5b9f90391cec935db8d2b142571650fcbb6f6eb65b89c9329e84b10bfa1c656026674d70280ade4ba87eeaf9333714d +b0696b77ca8a0cdbe86cad12f358880926906fb50e14f55b1afc1e08478ae6376215cbb79bc9035de2808c7cd2b13b85 +a51d746833062a65fd458a48a390631d5d59e98e2230b80d8f852cfc57d77f05eefcfd3c395ade1e86d4a39c2141365c +812d67654319f4ef3c9e4a2d4f027a4cb7768f1ea3f5fdde8d1b79187a4b874ff9a5c70f15b7efa079c2dc69d1b9b1fe +968978b653c6416bf810f6c2ffa3d1abbefbd06f66b6686e9a4fdce3f869e0ab1e43cce14dc83786596761c100ae17e1 +98e1e6ab562ca7743783b802faeb0a24f1341abfb9655f106920aef08964a3c0e8083e1acda7ae28fed7cdd5478decb6 +a91c0b982a0a7085a103600edf99e9d0bee4c4e7db6d9f8f376c215c7d42476218462a3765f2928e12c3dd49d688e4fd +8a43395b3124fab9e2438635bf88952e8e3084dad7ecb3a9927f9af0e0887bce4707084043671fc98ad03621e40a149e +b0b37626143d4a8c6f5693d5f1fe871525b4dd946c4239cde032b91f60a4d7a930d7ba28959737550d71c4a870a3a3be +b01c74acae1715c19df08d5f4a10e0c19d1356264eb17938d97127bf57e09ced05ba30d0fc1a9f32d6cff8b0d5f91c9a +b4c2328eb8a5a673406faed8f0aebb8540d2791646e37ce46e0e382506570ca276eb6f8e166dbbf9e0a84064873473b9 +85cb9f769a185e3538e4a4beda9a008694e1bf8dfeea9dc07c5c40a9ceb1d31fcb13cacfaa52849ba1894b5027cb8c30 +8742f91cddc9a115ddc73982f980f750d82d3760f2d46ee4490d5b17c6c3bb57c7d4c7b8d6311b7b41e59464c009b6a5 +948ef86d17128a061e1bdd3ea7fcc7348e3ec87ec35dc20a58dd757d5d18037fe5e052bb359e27ab4c2320d9a52a6a0b +a70f6a214097c271e0d2d95e30fce72d38c30a2f186271fdff0e38e005aff5baed53739b8c4f9501aa7f529c5cb2da59 +892a7574cf6704ad75b346c95ae6f2668904f1218c35b89b07a0c2dbf3c62173c348f6fd9473926eef56a37c0f635c04 +837e85a41f39b4ded1420aa8fc3be46a7adb99305e0928c6d7643b7c44434b72984cea08eb68f5f803661df0db78c87d +94e495329f2aab3eeb68f347961d1006e69d990095877a4dcc376546233adf29a14bf6b16a0c39aa477e15368e87014c +851860a8fdf76a97048396553262637dade27f1f63f926997e74c7c72b14b10293eae7824e8dedffad1aead57c124f79 +90481017a250972055ab1cf45ff17d2469517f10f18c9d4ef79a9bdc97a49093289bbacfefa8a1e491bbb75388b34ac0 +983db15f7463df28091c691608ca9c51095530fa6b1b7b5b099c612e673d29e16787cc9ae1c64370ba6560582ce623c0 +a477dab41014c778a1b78a7ce5936b7b842124509424e3bfc02cc58878c841c45f9e04ccc58b4f2ff8231488fff0b627 +868ebba1c85d1f2a3bf34c0ab18721ea725378b24f6b6785637ee4019e65d4850e051c8408fe94a995cc918c7b193089 +93cbf4238a37ccd4c8654f01a96af809a7d5b81b9e1eab04be2f861d9d2470996fb67367e5bf9dcd602dc11a3e4cf185 +83113f4e696030cca9fdc2efc96ba179cf26887c677f76cde13820940ad6891cb106bb5b436d6b0f8867f2fd03933f7d +90c709f4e3359a6d215d03f45ad5cf8067aedd4aab03512dd62229696485a41dcd64e2acce327fda390e0352152fce13 +9945cfced107a36f3cf028ba04c653360afc5013858b9a12fac48802efcbc198c9baf3a7f9b23dfdd5036e88bc7274c8 +832ae60192b47fc735a8ddeaf68314b16256c90ab68099f58e43073e249c6939895c544a02fa34e40805bc6b5db33461 +8b12c335818b643c1d22cbc2869606cf64e7ae54a7713617fc4dd3b2f052ebd6b920ca59ba2e9c7aa8cf71bb4f40f9e8 +a2033eb7a373931c65d66989644aa0892ac3778b9a811b2f413d8bf534e282c339717979f9aa742162abb3468c195f87 +aba2b4c37dea36bed6d39323e5f628ab607699c66767f9bf24ef5df1bfcad00c2664123c0d8d5bd782f1e14a06f4c769 +b71963777535b4d407286d08f6f55da8f50418486392a0018ee10f9ae007a377b8b8336f33386b0eb01c45695c3ed2da +88dc87826941340913b564a4f9b74985a311371c8e7b47881235d81c081f1682bef313c2f86561a038757fb7d6a1a8dc +869e13e3fcf91396750150f9dc9307460494c1d365f57893fd06fb8acf87ac7dddc24e4320d9cad0414119013ea739b8 +92194e292303d32b91ae9cecb8d6367c8799c2d928b2e2846dab1b901371a4e522fc4089aad8f4ee676f0614ff8b19d7 +aa589a3e512cb4f8589bc61e826a06d9f9cb9fdfd57cf5c8a5a63841435b0548e30a424ca3d9ef52bf82cc83c6cb1134 +81802e0194bc351b9a5e7a0a47911d3a0a331b280cf1936c6cf86b839d3a4ab64e800a3fe80ea6c72c3751356005a38b +88e5e9e3c802314ddd21cb86f2014948b7618502a70321c1caf72401654e361aac6990a674239afa1f46698545614c93 +abac1e0f85d5c3ff6d54ed94930c81716d0ac92be49e3d393bed858833f4796c2b80bf7c943e7110de7b2d148463bfbf +b7eb416004febd574aef281745464f93ef835fd65b77d460b6ad5d5a85a24b536b4dec800cfe80ae98489e54447e8bb6 +b3fd8ed1c30e7c15b0bc0baf0d9d1ecad266bafb281cd4e37c55edc76c202fb1e4ea315a91a2848f40f481793ae35058 +86ef674ddf4b7d303c68bbfb53db00b925ccbf11d7d775ca09e458f4ecd868ca828103e8e7cd9d99672a193e81b83923 +95ef414e9f7e93f0aaaeb63cd84eb37fc059eb8b6eced2f01b24835b043b1afb3458069c45218da790c44de7246860c9 +93ec8f84c20b7752bfc84bb88c11d5f76456136377272b9ac95d46c34fce6dcfc54c0e4f45186dd8df6e2f924f7726ab +95df5f3f677c03a238a76582d7cb22ed998b9f89aecf701475467616335c18e435283764fb733fb7099810fec35932ae +8cda640695c6bc1497d19b9edc5ff4ea94c1c135d86f573d744358758f6066c1458901f9367190dcd24432ae41684cf0 +b19aedf5569435ff62019d71baa5e0a970c6d95fe4758081604f16b8e6120e6b557209cdea0ccd2efec6ff9e902d6ce6 +b3041f21f07d52e6bd723068df610aa894dfdde88094897593e50c5694c23025e412ef87a9d16cadd1adbb1c6e89ced4 +a7f8d6ab0a7beb4f8d1cfef6960ebdaa364239eca949b535607dee5caeff8e5dfc2a9cfb880cc4466780c696cff2c3a6 +99a565b4796e2b990bfcb234772d93c5ffdbe10453b5aa94662272009a606ba6ea30cc0c3c26aa22982c1e90738418a5 +90c54b55ff19157c1e679d8d4f7f0687a70a27d88f123179a973c62565adfcc9347cfe31f54539038cf2f34556c86870 +8612f34bcd018d742202d77d7ce26cf9bc4e0d78e50ddf75250b9944583b2c6648f992b635ea13fdaae119764e7c28d5 +a04fb38e5529bf9c76ec2b5e3a1ef3c6f9effb6246c7f67301cfed707356ba1bf774f2867c77a5805933f0c8ad0ec644 +b4800e7b503da0164885d253135c3b989690794d145182572181995e6fa1989f3d0324993e871bbd5f48fadd869d8a18 +9981cd4f28ae7b7dadf454fb3aec29746dc2e0ca3bd371b2a57cd2135a7d93559e02132528ccd2d305b639d7ac51613d +a3ceec012dd1fbad3ef9f9f1d6fe7618e13d4d59e3f50540d2a57010d651092979c75442ec8b38a1ab678505e30b710d +8b97b8654d067fb4319a6e4ee439fb8de0f22fd9db5569ba0935a02235cb4edd40a4740836c303ec2394c59a0b96308b +b3d1bf4410fec669a269622c3ce63282c9ac864620d7b46c9dfcec52d8e79b90c4c90a69c32763136a7f2d148493524e +93174eba1e03f879e44921084aa0ee3562e48c2be49085de96ed7621c768ff52324d14c8cc81f17d7ed50c38ffb2c964 +aa2194cd0fb7aec3dac9a1bd8ea08be785926ed6812538be6d3c54218ea4b563646af1f5c5f95cb914f37edfae55137d +93f2c0dd59364f6061d3da189e04d6c64389a3563b062e8f969a982cd68cc55b4f38b21546c8a67c8df466ff4f61f9c5 +aa7dd497cc949c10209c7010ba4ce8a1efd3cd806a849971e3e01716ea06a62e9d5e122ad1d2b8e5a535fae0a01a7761 +ad402424b2a32bca775a66aa087580d7a81f0867f293f1c35580b9e87ccc5a2bab00c29a50fd0d7bd711085ae2248965 +96237843d8e29ac77fc6ebf4acc12946ad11697de8e5f152fe5776f2475b790226a7d156ac48968dd68b89512dc55943 +a45c25cdbb9fc327cc49a1666988af9ab4c5f79cea751437d576793a01c3eeea4c962c05c0947852fe0e4c63e1c84771 +93dcf834a614a6f5484cc4ba059e733ab5dcc54253229df65ff5ad57b447353ebbc930736a4c96322e264e65736948dc +b9a94f82a82c0c5a26f2c1d5381afec3645e8ee04c947dc3b7ad59a73018db1e9965ab3642f2bbf60f32c430b074fb22 +94eab29b3524ccbe0c4b928e5fa5dd8f684074b332fcf301c634d11083653ffee4f7e92ddbcb87ed038024954ad1747b +b8dca5f679931d6abef0674bad0639aefad64c2b80572d646aaab17adf5ca1ab2ebeecd5a526cadc230bec92ed933fc2 +944d394958e539251b475c4304f103a09f62448b7d8a8eaef2f58e7de4f6e2e657d58d5b38e8513474115f323f6ec601 +8a5ae1f13d433962d05df79d049b28e63fe72688fc3e6660aa28e0876a860c3dbc5fc889d79f5c4dec4b3a34cdf89277 +afa5278724998eced338bb5932ecf1043d2be5dd93f4d231d05d2ea05b4455f2ffdc0eadcb335dcace96dd8b2b4926fb +b91153a2f4647ae82fc4ee7396d2ca23270ec7f8884ce9eead7e9376270678edd42dd3d4d6c003dfc2dde9fd88cc6e7c +adc932f1c679bf7889cb1ff4a2d2897d7973483fa283979a0ea3640c80ed106ea0934c1961dd42d74b22504be49851f2 +a82e90761fae684d1415cee0649bb031bcb325ae0b28f128ab8e3650bccedd302a70de1a341ca8decfdda76f3349cad0 +8ae353188b4b98835f4ef0333cccb9e29e1ac3ec11d554bc96f5880c101cb3c84b8eefe72f2287b0812735339fe66cfa +b8b41135bb1a1ffb64afbd83e2189e755f2c350e1273cf47c38ae9b8c4800d831436a69458b8ef9fa8b95a148d8ec9fd +96f75a04d8752fa93dc1eaf85ad333cff4eeec902a345576139e16de3a88eeb71b6726224349bb9844065cc454d959e9 +ab82b05e3923ad4c26f5727c60dc0d23063c03f5a4fd8077da66aa87042cad1bd99586d4ab35aa5e4ce6f4da6fecf3c1 +a50c83db91c26ef7bf1720d8815b41bd056b49fd99710943679a162ccf46097a7a24585750ece886e38eb4fdb866fa37 +a719f667914a84f62350dcc6f4f30b9ab428eac6837b70318c3ac491c1e69d48af5e1656c021818f377d911fe947c113 +a148807aafddfa0a5624c7cb9e42468219e4bdb9994ec36bc19b6e6d7c4a54d3a0763d13ca80624af48bbd96d73afca5 +aa012f205daf22a03e9fb13a63783dda7666f788a237232598d02a4d4becec7a699ab493f78d722ce68519262924c708 +97fc15fab5952c5a2d698fd6f7ad48aff1c8aa589f7d3b14285fea5e858c471cf72f09a892e814104fa2b27eb9771e73 +8da8840236812667c4c51c8fc8ab96d20dae8e2025290b9cde0147570a03384370b0fcbe20339c6aff09cca5d63e726f +b477d85359a8e423fed73409f61417a806cb89c9a401967622aba32bf85b569e82bca1b3394c79e180114a0d60b97316 +b3d6ee2ed1e4c5cf8ba2c3a4f329832e41c7fdcbcda8a3fcbe8f60967fdb1717665610b7c1ac65582534d269d762aa09 +a0b3b30b1b830b8331ee19f96b4a4321a6b93a3395b95d3a895682c65ec6ea64774b878b93514eaf353f2e4be28617b8 +a2b88e9617f4d30ef4e686d1932ad43cd555fadcb5102e51bea19e6fca649284ccf4debb37b5cb2090ef386fa5bf5327 +8a4446f7e8463ea977a68d6217a9046ad4356d6fc1c18d46c5d2ab681ea977b8faff136d65abea6bbf8936369cb33117 +91e7464bc56e03f436228104939ddd50caace5a38f68817bb2991e193b57adf6835152bbf3dbcdebf0382ac9823f60c9 +961a441e6cdf8106c4f45e5b47190d35644faec701c9cfc41ced40cfdd1fa83752fd56c1ac49131a47f1970a8f825904 +94b7b165cc71c2ae82976b8f03c035fb70e90028992b853aa902c0467b384c7bcf01d56166bec5def4453e4d0c907e52 +a5d32cffabbf547f900026b34ef46f08075b7a244565f615370d2f04edf50b094c95088a4a139ce07caf55bcd99afa07 +b4e06e73660745f75ab2f34d9f6d2675b58f80f911ab6dd4c5a6ce1095f9a2b50d86f6ff9a05394190bdf96af0827920 +ad3fd8f83c0103b29d41319209dffca201d2b98094362da08da3fd6ff0ba96796b49d6bed525c9adb96c2954858e7f48 +b0c27430695f0fd20ae31e1ec621da090094f2203e17411db9384695ffcf5c7c6badf461ba49ba70164aacebd6f278ee +b9bc6e972fc3b532fd2b1eeafc4bceb77604885f32132af6a9a842fa2440df452f49ec0cd9d86da1180e8deb0723b260 +9729e22d6104b0174c136a854920f542b384d375040adcebe36acc253bdb55845eb43e34dc5a7cc27d22c417973c24d0 +a8b420b36d48786c9231d454468a6e855dd7f71dcfd095efc9855ee70dbece0f06ad277f7829c5813fc30524c3e40308 +8757dff5499668c93fc5d9cea0a8db61817b8ed407200d623030b5849a913d12f8371b667cfde8d8082026eda7407e8c +b859ad747ca5af661fbd03a1a282df6e84c224ecea645bc2d4ba5e35fa06cbf047387319fca0cbc76b712398c0798968 +8e3173c27875f1460297af0fa736c945dc842ec3e476a973d3d5f790bf183ad3ffe96ac13868c5101d8e299890791864 +a9d725e2b92c878be42b5eecc2c3081c63c7231ccc7e2dee17ca6a4caaeae22788fab1f1465fcbd7fc236613fc2bae4c +86f6c4f04a354cb2470ef91914816fd740f8d5795ce7ff981f55a2634695fde5951bbae7a4bbc4c63747040f8644170a +851773cb26f320f0c3f252d95ea7e058ffcc795dd0dc35e459aa1b6b448238909230d809e82022e64b7fca5d40b8324c +8962641e0306220d9892fe2d452caa286301a3c465185757be7bce2d9b2c9beb3040280099606cc86773e43941fd3439 +8beb6e08c440b0de5fb85251d39d9e72db4e556a2dfe3dae59efd8b359d08492064cebd8d8993254b43bde8bd67d969a +a7e047894466ffe3dec4ab8d5462f2b1d8ac0df006b1d2dd26caf499ea857d93a811cf42233f9e948c9cb903beec004c +92eedd95557a91691a5e2835170390ce2401e223da43b78615a804c49566f9d31cbb7f10c8a8390c4bdcf691544fdba9 +a5e5b5d8fa65824e958bbae98d146b4b332f97ed50e0bc2c58851dc2c174ab71bcbb1ae015cd2955c26b368487dd862f +853a494eafb308175629d581ed04bed71bbc3af9ca4c0dc483d03d27c993a2bbd88cea47c2085a6928d166fe6938fb77 +83f06b88d29afbfbe8f61811690322ac4fdd6abb9a23612162e7a2dd6bcbb5f14cee298ebebc1a382484f7346dc51e60 +8c9cf05735ea5a0e563490bdc7ed29a4426643711c651e35c8551ca6f855c8458ae8f0933a022d0bb9a952edfed411f6 +b906b48d807748a26cc2a8848455a76ce502261afe31f61777b71917bdf7de2fece419db636439478c7582058f626c29 +97efe1fa7c9b25d8bea79d74b6cdcf88f63f1e865f54b58512a2e60428630b0b40b8b6af1b5f71df47520507548c3cad +8ef5ca6e753818906bb3fc71405928d8e4108854ef0ef01c1009071b353bc2852e771fcb619d5fea45590e8f61003d7f +8e4d901661e2913740d70ba4d0745df5e8c9c0a260149d9362beadc7e669630ba909ff0e8a6cc85c54d6b7435d0d351e +b7c6ba3bebbd9592967954e3a480ee8df1d9f5965f04e7d78a5415b645128deae7ddaf6ed507c8877bfca91ce078e529 +840bedb0ad4e25acf6cd25dee4f98fea495b2312dc5cb7a8388c5ab00b2acb9cd25da08e9fbead145a3107972b1ccd5d +a8d4578dbafdb27f3911af59962d89e75dea74db55346720357790da677312c203107d9c7911535aa563446fde7d4c47 +86d3b77f231bfa09251b7fd2ce09c27ac520ec35d783e912476f9a4863f83d269eb175790d6e735da9260293d707f8ee +b34909f1cc033232652da0c34051a769dc76adb1aee00674a59dc1b860f6e610974c3b4bb69a69ccc73e01f042431242 +90799854d0cf34e1d91ff8e101bc7c5007423d34d2f3bd9adea2ecac57e83f3a65a506bb93d4caea49b29f6d18149957 +8ef94cde29b037e19a1ce7bf4418ad3c95cd9457412796ea385750c19a6690f13a3bb5bb6a9ee81e7a40face1e0a8bca +97053d21ae8d75972fb37f6fe516c38c32ab162fb56b9f510f954858f4e3ef6ac8c3a9557ed3f41b7b6aef05fe97f931 +90a9f9f0f40991f3bddc58b92d40382147db22cce50d092d4a05aad251b46b94e71ec9f7107a180243288059fcc5ce29 +a14265b1344ac2921b0f890d13bcfc432e4f648ce403e261fce4d3bb32ffee9e2794c02830346054f998e82784c77040 +91928402ae121e56a3e64cd6f390127e6e92fbfb1967ec6efa4f52f3e8058f1f41a0f4fe96b5bcc11641c1139e790b2b +921c8c92b6d40da6c5a7b592acc74fc0f577d93767b9aa4a1cd302a72dbf503a1ea5b2c29fa0d0359bff3b8f252246d1 +93ae0ebe0e8e133fd80cf67a499047e30ec4c4660ccec9d49098717ef57721a030f423e00c5e74af4ff4acf014a10497 +82c865e21905aebfe0496af1c6ac7e342b5f446a9edb4f7da0f2fb0340abfd8e6fc545da874459d9aabe6bce0dd9bfcb +aee3961d8d2687c0f134b9c28b920bdc4021d925fbe14323c84224a9fe161248789249fb85436a5891d0bbff42c2a3e9 +91aee420b98b6949482b8ff4be996b97245b4e8f583a6e085226539074f42aa89818395efd1a6699735a569bfe19d623 +a48eec22c192e495b01722d0016a54acc45ff837e2a95c4294ce81d5a4e43e0053a6f0ead8a4fb3ddd35faf6607275b0 +a26e15937c11faa30ffa64817f035e294cab0e839f73d29de8a244ad039be4e221eb47ea08d9a4658b0152fc3caf6110 +b84450f948aa7c8682fccb9cae84d8e3558adf2d0ca5fb81eb200415291158720f8f3470542ab5b88c6873ad08e7fa9a +a8e8ec27d0608d020169a85d6ecdb40eb402f006a3b97afe32cc01987721b3a68a92ec693aeb4d357e189e05fadf699e +ac87cd535ef5699312cc26f86adb71baa0be42e858bd5a2d94ac05737dac63430691e29b9a30d2559ad581a172519b2c +a4481e67b524f8cddf2046625efd3d75efee6aab87ddd2c1b22835647e918157e5e924ac760db2195c86d326f3db1615 +891f29ded231486ee826840c8895cb325f7e84a5a6d2eac246cb3573612cde274720233b1978318a57ed337a046330a6 +906b6e750e6178289012769807d2598925d7e51c260c14497d8af978b1695990e3352e6e809a752f376597a68083870c +b7a056898ee1e46f7f29702fb39232f678ec173eccd170303b3b0a30c8d8cf1a5321384e3513e3b03bb742c238deaa54 +8f2f035fd96c3a336354c89ec9b8222803bf42e95fb2412c28d4e75eec99c1d4d402501ccae17357b757db8bdb0bfeab +81228625ffcedf977fba9cfa13f6edead3985e2651d5974789c394a69401cd7face9e20ae6694be4c0d4bab5e99c61a8 +885a83eae25e61439ad809567a2ab148583402e01cfdd77b0e37ab4038935425c64b4e0886949bf06438c35e80aa13f4 +8926387f48752f6933899c48e038cf14e7941ec6a58bcc0a436614b396296a17aa53e6873803dd3041dae470bd493fcb +95d0d3fa061f4d856eca78a569aa132db14cede7646f97e2aceb6da0c8ea53195d3b7a566fe5ec8c41b95ecdd89a1c6b +a3c817f4062ed6aa94064ea695d76c1825f3bf77b310fe1db28b8bedc9aaacbf1019dbd128adfd53042fb943d863a2b7 +af1208417aa584052da309169854149ede38a3ad63c76cad6e43afb6f1a7b854edf8310a0b00088c039259cedf0f859b +8b713fc3196bad35dbf364089049ada5477e540d78d76a5f0a9df98f7ba4a0e65dd0644509c149f9b07887298bf74b04 +89c09c43c5b733c4a417cd9ebc0795cc3348b72778d31828a9171427779a82ef023c1a4fcfcdc919ae25056f9c826fde +a0759c850ed320c8c874435e90ace6edfb8e7b3f2a09d942b8ad8339c508044ee2ee26c70f1b626ec49a77971433b6a8 +b85cbc58d4fd52286e714ac4eaaa0b2743a1de06fa03ddf8f6668ec6f1d204acccce93b10620272afb8c0b49bc4b0a43 +814e0a87384e159892a8d23036985fa3f489c53bce192e107bd2d64f57b1bf5ea0acc1ef46c7a42bbc5cd0924d92b4a0 +aa6821da96ad89d7881b878e141076522f104ea9a5bbdd1fce9f641898f7d6232c518a87a0f666871d7e3165c26081e4 +a9041d714bfc067b5427252186fa3557bad598fc0067dc8521aa9bc1ae298f6e96113db5ac9f6bade9a85d5a950c9755 +b8669340f3064692625e1bf682d34fbe69a61689e3aa6d6a3e822c781d406b0300dba9c3f7b8152a8c2513f1310d4291 +a78c53316ce768a1dc5968030bf4fc885f4029b1ddb6a5d84a61c85af686c73727f62823891edfcb6ccf4545de366cff +ad1d3aa29ea28292ddd438c865e2b5d93f32cdf009e6d5f5dc726de996583925727e6348bf1c28c22dec0bd86aaf867f +ae1447a2062e9e28af5f38aecc60fe150cd10c2edeaf2110034aa144f6235ed7fbce432a58805d4fe1f6b12652d6e1cd +a32146634332d3303934550705353c6d4fae5fa5985105bba35041e74cd71e2aad67b45da171221f6ed80f36bf6dffa3 +a232e8286184196ea77427b53d8b52c44d758ecc42d22556529db3136379b4989dec61cff610cc6cf6700a450a847a94 +8a72c7255125a736da52dff5f77e44c3de29f88fc05f5ff9227c69df296930caaa11446595e6bea3bd946baac5ef957c +9688a981a9457678067f629f8efa6b522e7318b529f88d37ef56c5bf8f1c34fb9bb3a918ab73caab82bf5abb0c03518b +88286f3eabd71115fc3b17a6bf6981340a81cf7e5f96b0a1a016d4ec8c18fb486d46c70919123d0c189a6f5d6ff29a1e +b535e701b40d793c02ac0d625ca91620d3f4a512aa9741f71389e58381008b2f93d597586d06213c4e103d67d0ddf6c5 +80d0c9dd941e8d8d3700cc51a434a5aaa3308cf8ebfd14128ccfd258f826b27cc3cf5c3ad7851340393abb1eeab3a157 +87049225fa2380d93f18d3d90cb0697a56b373b66d7f24ab209966aed8b55a2790194d5885399db29dd5b1f189eda64f +a52df158ce8670e0290551e8878d63dd33b4759d6f50e448e63fc7fe6ea99dddb6f180be5fc0fc3918ce54c05f80b356 +8b2a728b39c465fb0f60b0c486e5dc8d5845ccec03d3dd93b393cedeeb3fe1b44518359f1ed55fc770a8f74bfeb9923d +91fc05419dba718fa4a910dcf256ebea356bbea00522d8d5ec3e7ba4271a26035aac15e8d9f707969df1d655d92dac55 +97c8779ae80c24c1f82d5a714762d6ee81069224e39515e41d8a71c9310dc5d1c55cc92bc5c6a4bd391ae4c321d1d4d2 +b5e5aedba378c4484e3a7a4ed41b75b0844f674261c2501497de6f91f7274b5a4c1be0e055f2e0c0cab843d891169fbf +8a26212f27211b295beea500abc8e9d430a8500d3a350cc62f895d39e8b4668aa638c17633804ba353010000165637ae +864a95118e5d394e00e99efebd505df0125525c9ebe165764c453b80ad3edc730feebde3d93850745dfd88a27bb8f20b +a092e0b78290e826cc1ae56afffdd08f7c10954f549a3ea6666f3db1b6cdaeb7df53db28dd2a92446342930fe60a27ce +a1720224c0626a081b6c637b2a6d37da85d9a82241e5efef3bc15699b02a69f6304e43d8ff3144d60c16e00225d6b39e +a7b3d098cebea9cf32e19c5195608182b6afe9d4af6b9df532c047eb7a941a971279b2ae6a4b80f2f9d9313a6d788ce3 +a3d2451e6788944802c5077a778d7b7299dbb9d1612676bb6baae78f39976e0fd879493cc4a4d737b8174b472a456850 +930121b73da844571b1411d56760e80923a4ee09917b3e9cff4d3dcb0bc27026ff2c4e2c44e7aca7d3f8383f129c7f9b +b4b0119d163ee00a2b74bdf188a5cdcf054daaa48c483b94bbb4d09ff615afb4a91347db6363bc7535e2af9054ec2214 +a5846decee706780201095a8cdd48fbf3d3a2eac8d089a818e5e22c29457494bbfb4399323b067f3d2be2197c33dbd98 +96ba600df10ee7af5a9df29c0ca31dbed275d647faf9c66c7342de927ceb25b5bdd852dd7aae0228b27897f90fdd5d62 +b6ac51ddc98edd9fb9f54ef84bf372a041d58dfdf0dfdbdc4b08ddc1a7ba93ddbb1413dda3c1545a3fd7386c6b85975c +b35f3efd91a0723e0d486188ea9675a3462106470455118392d7610470b623caca2fa33829721c05fbeb0fabcf570bfc +87f49e85df5f8055714a8ce7adf37f6a278e64e76ed74c60abe3edfc3611ef5b0426d4c6da45e5f3b74d30be1dc6f539 +8ff8bb06902a71b1e9177a77367318b2e3e0a88f5d74d6907ca9943f4f9f1ceb5f297132c2a025259d17a67e880d1bad +85eb6de6c70fe5c53ab0ab27aa0fec439f136c979c557d317337cafa6e6c5cb3169679c9169567dec5f6c72b3c057d83 +ac18715ed1080771d760cb7066c6328faf65d9b30517903f8a5cad8d66d5c6381156b521107d7cd75ebb8c30e250706c +b95b9eae4703727e4ac9ddf2ae675906487bb78905a5f9cba74a4cbfd118d96b7afb6ef3ed5edf14fd963b830d71338c +a3b47b52fda16b62b11c8aa4daa56b0b669c4d5c56a3059b7d063284d8a91f6fff9ccccab23d6ceb9650483b2d353039 +96a95b3f327df94c85e92f2e406f1649ac621533c256b062738f3c3ee137059a735a3e6072247acf57b1b0d8c219bd7f +b19b33cc04570be94eae8e943d5bb17bb0c96e9de4ca84f9f41b37320a1a03d397d53747dc13275fef1b356de557214f +a1faa3dcb931dd91507f3f12a17c43f6627fa2bc5c71fbdd27548e091eaaaba262477949cd51290e81196bffb954a492 +b060a16079dca1d28a1fb33cbc26f368630ee042d980ce305230005d5b9ab533a7a695281ab76e9214458303932d8bbc +b303783196a858fe45d67e0520c30576da605fd69964449c20009fbd5099cf1de52a32d326d7c3b864de07440195ef40 +aa550a4c20d1003d137ffd8fbdc1196d09ad53cfa0e202302093a80fa3bbc4c9aff83f34f2151785cc1ce5f30255693b +a7f8585f45566a351058e10c6f1ff4a7ba24811f1482a47202f581525615ca770da93f2f58878788b45b92cb446ef4ec +8206f63a9a5b59bd68e64a843e68fcdf706f4c13bbfcdfa9928298e5b9251006ae0bbd80c715aa3c9957d2c0148b5059 +ac9490abe1241319658f1c2c645cfa01296f5d4106020c7894b7ba4a65cdd52f6c5401bd3b3cf1c9863e088cd8c9a16f +85dd6d9c80a1b58c24c4d2cb7590d33d2454f381f58e820979948e5831972360cde67bbd56e1860077ef5192fcacb904 +8b0285944c676fe2519cb68da0973275fa29c0718d838d363ce46651b068d29f867cf9fe579ff8da0bb8b37d202bb23c +95147275da658d43a758b203b9ca1f1c1478853e9bf77b5218593142e2bd9c0bf46d2206ab64cef99295de6e9a268edc +b8efa187fdd3e1f46c15cd596e9567690c10e253b5beaa5be8074b6ea4e6d3d06e0f2b05323453239e419ae1e7128521 +8340464f52c92e31806fd3e8e65f56e27194d1f6daa4a0f0b3831e8102aba16f88bb5a621633ddb7dd0342e1d2d12343 +8615d87dcab85a78dc052f05a01e751176b756b5dc9985014347454ce5752f459dd6464e1c5aff36cb6c51b783fa2692 +80c6e35c0d3defbe4d3968792724a23f0b8830dd2fac58663583a49339ea20f1812cc4140e3ee867c7e716177319bbbe +a7aa63dbfc201dde8f29bb6e23d7aa5020dd35bd18a0cc93c8a10c35d695913fe25b9e8cf9b5fd1899e9657b22bc8863 +97c2a4ba80c4caba2e729a603d2faa0120915e3fe64cbb065f7ff33de5f877f1ec9461cf455e88ec9e9ded9393939dba +a54bd1419f0e2d2d87757870f37c476c7e3a13502f1ada82fd7394fd29f8a00c4986473d753034d0954a2550badbac0b +8d3e2bf900d0d2b9b46e6e2f37620f0cc90526dbbcfaad4e4a37ed53f39fdd23bd3a6f21aa7e800eaec937d9710dd6e3 +a88d2b1c7802b2dc216c2b6532406c091bfb12f29121b9a82c1154470e250188413ddd3e79f7e009ea987a4c45b332e5 +8c552c2101dfdc3f99c2da436115452e4d364eefe029b12946f05673c5ce1cfb48d39a579625849236dc6c8e7277dd30 +8415c252d52a26a6400c3189c928a98559bf24162ecf3eef1d10e439269c31d854b0b4f6ec7a2430e3f11b5d77de78d6 +8b38905bad93a8d42339dbdb5e510003c51fcaf05e04f88fd7083753353bc1c4c00a5dd4a67431cd4456d0669c7040e2 +b1d0ed8862250d0f0d9ef9dcf0cd16d84313d1a795dc0c08e0b150dadf9ce73d32d735e04632b289cafa69a6ee75dc89 +9434e18a5fb631b10edb02057f2d1fe16000ee55ada3c26a079c9fc3943e29d6de99e52829fe7b333e962270c712e51e +b1b9f3914007e6fca8ad3e7e848a1108988cb2318da36df24767d804e95d1272943fda948451135cc1b5052a3953b081 +8c02947a76d7b6c0a700a83dfb971dc105bfe996e18c521445f036310914b349ab28e57571e36ae08d13a46fb01c2f43 +893472fbc225f973a0ac6a0a0130b9cfb7ab6869dff80df71a62b1f6beb4afd069bbf35b4f327165bc31dff39e4fcaa4 +a7c176c0903175f3540d62f9afee994d5d9bf37081e094644b22f017e94c515afefde7bb07f638342abef7de657f8848 +860186c2b1d3b1e657729bc804275fb5f5ee89eaa60848fcabd3871289665ea9f0efc8a95792d884972bcfa2de96223b +865b38aea6386d0ac8f501a7d934e23d01dc50105324e354d4c4fa3cb1d4c29c26f4566df7b1a728e10cfaa9d24552e6 +b4eea5548de6969dada658df604b5d9c49002e2258352838003e0fdf7b299d81fb025807a7f37cf5b547cebd7f2c1f93 +8982de11ba68d63a649a3b296d4d56c71e3c3eec016db250d733ab7c3b9a620c09c5a5d0b64fd30d3bc03037ca4b17c9 +84d8b8a10d67eda4716673167c360fc9b95717cf36ef1d5bc6f2ef5b9d2624f0e76c2a704d016adf03e775ea8e28d83a +834d03ebd51aff4d777714783e750b84c16cb6627f8311bd8ff17c3b97fc4a5bba57d6c8f6d74f195d3030bcb5f07612 +aaf49e0def0c4d5f2c1e9c17b51e931d2f754b19e80070954980b6c160178349f6d3c8d4808801d362e77f41a0008918 +8ef4115edec841854e89f2bbd11498dac7396bca35dda554290d3db1c459ffc17be671f4a46d29fa78cbd6064cc2da20 +9641dc8a64f4acd38e343a3062787c48c312f1382f7e310ccea3e95e066ab6dc980f6ed90a633236a435e68bf6b3c625 +8a84cfc2cbeb18a11dd6c2a0aebb3f6fd58a33bb4b26101e826add03748595022e816afac79a4e7c20b3805252839dca +9770782d729017659844421e1639ffcda66a2044df9e19769b90292df87dcb146b20c6b9141bb2302029d84a5310665d +98c7ec9696454868ac52799d1c098c15ec4e08b34884dda186ebfe87d32840b81fd3282295df141c91137faf4cc02da8 +a3f6eb921247617292162dfc8eec5b830ddc294a0fb92f5b4828a541091ffdaff34c392c1d7168259d6204405d90ec72 +b185f77a468f07a54222d968a95635234e74fc942485604909308a9028ed2753b15902b9134749f381f7cd6b89cc8c3d +867608a682d53bd691dbc92eeb460d1c300b362ca49c11a280f6768ccec217f1145f9d59fe50d994f715ce89d38a74e1 +afaad630ad8827cd71aade80edf3d7aeb65a344878db12fa848759e6233f6fceca563aa437e506ea9e0f1e47b126d45b +a12afbc84e3441594aecf85d089423dd3bb8bb33a1a384ddf7cc14caa72284caaa56aa179c15e3140fd56bb532491a67 +98757b0b5e5837ddc156a4a01ce78f33bb1fce51e0c1254ee9b6d3942268d0feb50b93edbf6aa88f9ea7b3c0309830d8 +89573f4a4ae752e9f964e42bec77d28a41840c28e4bcdf86a98a131d0b85367b885077823a6f916972de6ac110821bd2 +a17f2745052de5de9c059307308fc49f56cb5230e7a41cb7e14a61c9efa742ee14c41023ce90c7f2261adc71e31045f8 +914b07c53a41c0d480083f41a61c10429ea42dafea9a0db93862d2269ff69c41db8b110b4768687b88089b5e095523cf +b380cc3e0d26370976fe891d24ea4eeb1b6be8cfce01f47fd68838a27190e644fd57b049d3aa0a9589370de20e276944 +906385fdfad60feec79eb1c303e750c659ceb22d9c16a95faaae093daadd53e7aa039a45d57e20951d6e1ca0dc899ef2 +b5211ceee31b194dba60b616bfd91536e71b9213a3aaaf5aaf9b2f4cbdeb05191861d78b97eec58e3c81abe4f0488c04 +97878e9e38c2f69d697800e7a2f132fc4babaacf471c79c26a757f771606e55fe696ece68a3163a0ffeb2f72274cf214 +959431c1f54c46500c05aaa9a2bc4230531dad97ae768fa92bb85436c0ecc6374cf20fb0ef82d122db116820a943b401 +b69e5a1c6798f30d33e42cb8d124f025d2c77c993c4c7107a539aacddf44d8d4d2239e802ece32e60ee4dbfdce201bdb +a8b09e5e9f802ad273b2efa02bcbc3d4a65ac68510510b9400a08d75b47b31c6f61ffdb3704abf535a3d6d9362fc6244 +a41ace7f1efa930564544af9aa7d42a9f50f8ba834badcaf64b0801aaed0f1616b295284e74ca00c29a1e10c3de68996 +a8f2aa0bbbc19420a7c7cec3e8d4229129b4eb08fff814d959300cd7a017ddb6548c9a6efebad567d5a6fde679a6ac6a +9683da74490a2161252d671d0bc16eb07110f7af171a1080dc4d9e4684854336a44c022efe3074eb29958ae8a1a14ace +8ef44d78d10795050c161b36afa9ab2f2f004ccf50fdeef42fe9cdc72ebb15a09389ca72a00001cd6d9b1d7b3bb766c3 +adca54f3b14fb18298098970b0267301b7312afb75894deea1b2afa3e85b7a3b4efac9971ab54c5cbecba2da9f18507e +ac5d4528f06fdccfc1370d5c3d03ed982fed0861a93a3f6453aa64e99360b124926d1892faaf72d89459e663721dfa99 +98aa1c801bd615b8cba728fa993021e181e0ad717ba01c0290e7355694155407083eb53cb70819c4775da39d33224db7 +8b3aea4c7c2bfe1020de3261ec085d79c7bf8a7903b825d2c70ebbb84af197bcc54e3653c5373a2045c3021526b63b66 +a29f3de4cb3d99afff1daf7d431b38a33a9804fedc41626618928ed059df6f6fe9f298a046b594ffee951ed4d4e1400f +803fd346be540c5242667c18ee41b26bc812456ab13ff117196ed69b90ee608c8cb6554396b64066a546ec87a71ed6a9 +a9c18d81ffd029c0339c72c499bb51685392253b996b6eabd8b76f05c6191ed8444a1397d63b9923743661a319517f7e +a048d5c390d08f07161faac71c5994baf152c883b205f3bb10d3501709d6516ae54d491b486303a11b751857a31f0052 +9156fb4803e40e28d8d57d928481a8de4373687288da44fe88c5676a8ae013ed1fcc09d56a31140bf74e7f767253810e +98e289c725b18e0085afdfaf2acbc674dae7b0a2ecc2537a7d0b87e20eb785404ab05973a787f0495d2adb3e5565c09b +8a7237b249325bd67cdc1f9fb278710069033c304afbf270b7ea24dbc10c8eabe559a484d3edc733c77b4384932deb41 +9056f2e5b02e5c2e04a69fa1323bbf1859d143761268d18e74632e43800a2a9c76fd681e924a19bc141de0e128d3e462 +b9f2bf9e4e7263014296a82b9ecbb05d3f1efa4b2e675e3b38d3eace59da06a89c859256e1b77847886d6aa15f98f649 +83b22949cca19030289bbf7cd2a0d8b84e1d468e78bc85271a6753241b89122627632723bc293cf904a5eb2b5dc6c3ae +a919aaf35dd0116168d2ee845122026416bec9633df113fbd913d8db5996221e234f98470d029a8ff182825b59fda20a +91726901f49d32b41afa15219073842278f60dcee223640903d871e318a1c2b541136b7b38a7b2ab7d31e4242fc29674 +942b77666545bc9a858d36cfe857ab1a787c9528f4a0b87918a06bf510793264dcafd12ae6bd3ee300179dab7f40aed0 +80adc1f2f9c47a96d416e44fcba41628abc0fae1f88f6a26aea4648419ab726f7fcc2187c7d5145e3d8f5a75c03937f4 +8041e0f66ba9dcee01e336dd4d16ae5e4e1618512fc147cc8230003aa2940848162dc2187d4130bf550dc1f3559849d4 +999e8adc51bab54386af1c5e8822986ad1b7ecaf1f8a4c2baa5bb2fe9d10710e49545c5a8bd89ed0e61a3d73a908e5ef +89272ffd39b6e9f99fafdd58bd9dc00f66f26a1d36b38a1ac6215e3546d966739eecda7fc236335479207cef95cce484 +b8e0b7532af13f15dc04a0eb4ea8abd67e58f1b1c6ad2e70c0ffa04a5c18ec2018b5d7f4be2f9f86db5e0b3986f639d9 +b96bd11b0f6ead4abd5fe1e4c6e995da7583b901afd01cc05e87d04663fb997997d6d39dd9fb067c62cb1b1cbb67516f +94ab08914088b973e8dbd5685decb95f3bf9e7e4700d50a05dbf5aaac9aea4be2c10c83096c02252e9238ceea1351d05 +a188de419b062af21275d976494c131ba18d2b2ead8bdbfa38a777832448e64d4d9725c6a1d530ffb6513f18d5b68d9d +8f73c8c118fa25c76a4ec5611351953c491452743056a819c8c82ba4737a37d88da0b55f837e7239a5f46d2c05a1bbba +894a44769e0be1c26648b0d89c4c9f46dbdeb3a71b90c493093bee372bb9f2d3f319850fd886d51f4f58db0de5641742 +87d239923b0db024a8d9b0281111d47b0761d81c50652268b074efa3ea70d793e30f874a91ce33a4acecd0cf38c01951 +b1b48b75a97f9fc2dc9530dc69f6268829dd0ddd574516e7eb1b9f5c3a90058889a7bcf3d378738e6d4b02f5fbfa44db +83e3ee9526ffcb60c6e75b75550fc017912ec0daf96d0a0d5f58c1b229cce90c684ac7c3e17fb998def8e7e2e155d750 +b9b7bba579e474b0abdc7775ff5f84c9f117c6ca17788cf5a5f01b2c35a14aa39036031c8d799fec2cfb371d9f7471fd +90d7faf4891fbc368a32f575dfb69f13e37161ab4f63a7139be103285a49490c2851a907f8d36e09e7d1a190dddbc6cd +968c8b9affe18fc34a4e21f0d8c5518341c566099e6b45b8721c9912bab3693c9cc343406fe90279692a1eef2a3f7311 +8735baaf4704207550f77df73fb701d9a63329993a8cb355ccc0d80daf950145f37e9b4b22be2aba29898e974f9fd552 +90f52b2dccf525b9191d836b205ffe966d9a94f6c5800f8f51f51f6c822619e5abdf1257ee523597858032d2e21014ec +831209f8f5257bb3eb452d3ee643d5f063299f8e4bfea91b47fc27453ac49fd0ba3cf9d493c24f2ca10d3c06d7c51cd6 +a5a4db4571f69b0f60fb3e63af37c3c2f99b2add4fc0e5baf1a22de24f456e6146c8dc66a2ecaafeb71dce970083cd68 +b63da69108fad437e48bd5c4fc6f7a06c4274afc904b77e3993db4575d3275fce6cffa1246de1346c10a617074b57c07 +a449448d4156b6b701b1fa6e0fe334d7d5dd758432a0f91d785b4d45fb8a78e29d42631bc22aaa4ea26f8669e531fed7 +aabe43de1350b6831ef03b0eef52c49ffb0ccd6189cce6f87f97c57a510ac0440806700ce2902e2e0b7a57b851405845 +91015f144fe12d5d0b0808c61fa03efe0249058e1829bb18770242f5fb3811e4c8b57ff9cb43deccfc70552e4993892f +8e9c570811ce44133ce3e0a208053acb2493ef18aade57c319276ad532578a60d939ed0bde92f98b0e6a8d8aabd60111 +8b21839b5dc1c9a38515c1076b45cedec245d1c185c0faac1d3d317f71f1bfebba57c2559bcdb413d9d7f0a2b07f3563 +90413bbd162be1b711e9355d83769e6aac52fdfa74802d628ff009325aa174c68f5329ddd552ef93e8fdcb9b03b34af3 +8b6b02e3f9dd1031ebd3df9a30432a3c86e64306062ef00a6d1243620d0cb66dc76f8d0d412eceff877ff8768c2696ce +9894b41d9fc715f8f6addace65451f41dc5ce7b983dd8cb33757b4d7259bef12f144e0077d0b662aa847d5a45f33c563 +a353a9740f6188d73aa4175a6c5f97898a05ed7aae9d2a365f15b91dfa7c28b921fdef0a32d90b6fb82718b33d3ddb8d +984eab8faed87c403c9979f2d2340fb090cc26d00cb4092aeb187c3f4ee1df3f57cb8363f7764073188790b16dfc464b +a5c5ae0ba435fb7f3ddd5ad962358da326239ff236fc3b51bd22e88296236b109951cee1b98f444302badc58d1b5bfbe +880be1006b0156f2788813432f450f613d235f41aba52a6000d2ad310408ad73d86b79f6081aef1e8c51010d404ba670 +937da751aae68f865c7a33fa38d718f20e2a1c65cb18c8e08f8441f0cdc77662789d2793794dd0a427cad30cd0b33f42 +9496fde66c834ff86f205897db12bbf9a9bb78d9ba8b5fb539cd0a2c927cc6b4120c017b0a652750b45edbe5f650e5dd +97a6f409ffeb593e149307a14bc47befb632412d70565c5f13d6b7d032acd2e3ed0f7b6af701b387f11d69ee4a8094d7 +97ed94934263dc0260f4f7513745ed3483cdddb9adb85dc33193c3a8b4d52affaf1ded23b59c34651afbffe80d40dc36 +b2b26378d44f916bcf999db218b9892e06de8075f205c7dafd6d37a252185c2d1b58e2e809c717963d25627e31f068e4 +b8f9fa1fb45fb19a45223f7be06c37d3a3501dd227c3e15999d1c34b605f888123026590697d0ae24d6c421df8112520 +997aa71e3b2e8c780f6855e94453c682bee1356b5ce804619ef14834475511105b1e4d01470fe4e2215dc72182d9909c +ac2cb2a7cf55aaf990cfada0218453853047e813d3f51f5a623d09f4714da79de6592671358a5edf938a67f905b6cb5b +8d8340d0c3081cd30d34f3ff6191e1ff6ad7994b4ebac19e5936f1157ca84e1813228b7605ee226366d6bab1e2bf62a2 +9693b17669086003cb46c75fed26ea83914a54901a145e18c799a777db1df9c9ca6b2ea3ee91e7b0ab848dc89cf77f19 +a6b6b2a6cd8c4922d78c8ba379373b375d66ac6ea04b830a23d5a496cf714a9439d81c865da92d52600aa4e2e43afcf1 +89cb665020abc3f5e11a03c7ba5ec9d890fa9ed2630f1443a8e45a28c32786ed980b5343ffffaea60eeff5b313bc0d66 +b37b989106594221bc6cf33a1a83c3e65ecdef279e90333a9e105b8139dc28384bb2277edd4b77c9e59d15e6afe074c5 +98ce5aee5918d18b2326b30c1ba41669cce20bc7a1d1b585363305fbdea66055164a7ac398ca0f0e670291a3061022eb +b57f472d5f34beb4cf430d7c0f8ac5bd1c0621a284633ed36e6f7804bc2b7847f54b469c7ea163a436510d9e3b32f97e +ae673a6579dbf0504c8fd0c8fc0252d2f7ae8da615a06f4d215c2f8a8f516201f24e5cc42967630c252905e5dbbd6377 +97c1501835a31091a5a83f0546e01c85ee847a0ca52fb3cc0653f6a826e13d25ddc623a5dea139108f7270a1fd7043ea +9376ee667f3834f6c0da4324fdcca5c04712e0649877ee19da79a2d23be24640c38758fce562470ce2134ca34148ffe3 +818af89c40379a10074cfaba6d5968ecf667f1a68a7edaa18e8977ccb34e0829f237c5634fbd079e7f22928b277f1096 +b8e0af0be0a252b28df25d4a509f31878bcddf702af0e5553393c3dfd4a1f1247ad8dc2668bc8dedc9b41f6ad8e71b15 +811667ffb60bc4316e44bd04573503f5b4dc44d1ec824393a699c950e5fa085b146537ddd6a08a3fede7700396a0df7d +ad834cbf850b2f61ce799c4a0f8ab0c57039d4e1113933c50b0c00175171aadee84894d1376cf325bfd434c3deb44315 +a8b7dfcdb40373ba4d55e751ccfb9070554434df9e359fc165284ee3dc35db6fb6055657ecf5a9e9b7b8e2e1abea4375 +b56a5b9fd41c9d3f65532aa58bf71a38fcf07782e1ae0084dc537862fa02e6d66658b19d6f71c39cd5dbfac418da1837 +a935af5ed224b9533b41a7e79f872f6851591da9e9d906050ccd1b2c772a1d6d010c5fc7160c4f8cd7d3aa14c3bcdc26 +a81e580fc98692567b28323fc746f70c3139d989fb6aabf3529504d42d0620f05327e3385c2bd5faea010d60dd5c8bdf +a8b352054cdcde8ddb24989329a249b71498a5593a13edad1e913c795dcad3d24789abca9c7ed1d57efcc9e3156da479 +b0de8a2bd7f93284b2bc700e442f52ada16a22ad8d86329591547411c23fff0333b2ab0c9edf82bf7903ebf69916eed1 +843e9781b653d1a427f3534b2e86add49d308ca247546f9fcf565f9e08df921e4d969e1b8ed83f3f849e98c0f63e39be +84a4098c5dca9f73e827d44025473096101affd7193c40a0307e3215e850e753e9a08e6e74a442d57626ff26df77faac +b463eaaa2f3315b511c22a97fad353014d840a6a95fe0d457d0677e63e571407d7f5268f8775381a5e7adc3b4163eb88 +ad0417edaa16cfddc288eef4173aa7057ca4f81e815541ac588ef5f24b98d56fed6845deb6ae1a9740a28bb1cd8780a7 +9271963b8fb2288a96e07eac13c0543ec41abdc6d978bd7c44ae08251ea49994412b542c77c8208cd71fd8e7852d4a70 +8b68b6db9044d8bafc155d69e0daba95cd59d6afebb085791e999afed4f33a2479c633d31d534ff767b8cd433d591a23 +a6a06a0e433e385437d9996ce823abda9848754aa9cdd25ec8701af35c9ec15df999825669bbc2e17cedb597a96e8eeb +94d414bff8b6b8597634b77a77d1060db8e1af0d0ddfb737a9bf1c66c8430e93a425510af2464bce4a7b29bc66cf325b +b6514049562af1c6fb7d0e8df6987b020f0b7a6e721f4862e36b1ba0e19af19414ede04b346be22d348b50875803d1bf +a42c7fb34f2fbee8aaccd1d86672d0acdf4e6bb083ff0456512d7e1e43be041cc0924322fcd986e6e1bce5d5ecce6f92 +867cbdd169a52440ae0a75d33a28c7d00aa92b4b65aaac5e62aa53a8fc367c08ab8828cc8fa18b6e7d1f908d158e3382 +a6fe0b768fff3e4a6153e59a7b7508eb2ee8165eaf5274d41ac2812bd4563c4ca2b132f0e27ea2f1c98759cc3589b61c +b3eb1dba43d10b9e17ffec8def053fc96f9883bacb49330a089a0ca5b9ab0182e8b5111ad4aa55c1ce1b6f4afa5c70a3 +a1531351098bdfcda566ff4d811301c0305626c77f954a38420c490e7c684f517eb1a4e4bd2c3904a10bac889cba314a +92278d106ad2f27eacdb86bdb1faa0a07a93765bb79dcff191873c52253af83480114b2299ffe5324f9c31d0abbdbbd1 +8900ba95a90c447fb6fa1f528af3d7a378aec25feb0620516b6b97e54b328fc31af42e46a8ad5e6e3029d83a6f2bbe5f +86053d481179c1ac910d5e7b9a5de82794b442f20e854583512ce1f9c3f09e71d1bf97d6700fe776debfe1527ab97a82 +a32a60de492fc4340336416bccbd2591b5e414fca0aead82281212e24490acc01747537b3da783684e27aeb987245cc8 +9820fe8e0338f21797143f368177e3669a1f3894b40ae9fa3b353125f7c8e85cc424dcf89878f2c7667f65db3b1e4165 +934d64711b4348ac5e1395cc6a3215e5643b540f591380d254165486b0ec2a1d0d21c7d2c6310f9e0eed3d08ecf4b57c +b9fd32d589432eddcb66dc30ad78981360915854cc44b2afeb826b5d48a08e377dc91be66f5bf1e783d1a8bb320f7ccb +98c972cf01efff4fc2e485b47572e2d8dde22461d127ef401b71a111b0603203971e3cde40912643affd7341cd27e57a +8db6c1620760063edabd376f4399b6e1355462e04f5c81cdcb3989fdc00f9a466bc85ed899e886c89c149adad69edbad +ad7b7fda0aa6e2aa66a27235ac5cc680aa04b85dce329fc4be84f75c9c961120a3d9e446aa44539aaac8ea203eecb4eb +8ccb01eaf41d816ce69ebd57754859e263530915e775c4e7d9dac37b2457a9099b9ae9b4c6cb09eb5ff246e3c9320c59 +b895b83b5f7ca46e02697dbaa6157df6c7571864c83e504a8c77d965bc2ba97bf9353a71c56a020df64498bd40e30b21 +8018c07a81c522fbc25f2cb14f2321c61b98bd8962ed8eb7d5823dbe5d1958a5ec2fb5622fd0868e991bcb6cae016ea1 +95b16364e94d01b3664812264d7185032722a4afc23bdd33bc16ae87ee61816c741657c37138d9312cebfb5fcfbb3b2d +94a709209990a8b09bfb4b9581ab471aae3a29526eae861108b28edb84aab6d28f1d7a25dddd8150b70af34bee4ca2e4 +ae06c80839c5a13269b984ff4d8a5938c6f4d8d647b1b1daa8cf7f6145340b76a286cd615ec251a65501e6290162da50 +875cbd0694eeb90d3567da9dc7f570d97b02bd9cf17bfa011efdd48f1d580608a3213bff4006603b8b4079fa66bded10 +b27f88c455f025e1cd902097d6a224d76bdf9c9195adee30bef4a0b0411fff980787285896e1943a62271d0aca531446 +8024880cde783cdb2b863e3dd856be92bacc5b2a1347e96e039fe34279ce528560d2df7d4d1624a4595dbafb40529697 +8883d02c2a5c0e026d941c785128d4ac6f7a9de625ea735b7d6ff27a5ba10fa4d6370d450d99a855d919f40d64f86afc +a1beb985c45fdc30ac536f1c385b40b6113ef6fabc2f76d255490fe529468847a776efa674ba8fed72180f07d3f701f1 +ab83bd9b007561695210e3276fde72e507456ba277ad4c348a2aec7a6e9ebdc2277cb4bd0bca73bd79bd2240a1fc4456 +8db27f516153812149854fd6bb1250e843a3ae1c9637df818b08bd016a769d0497ab6087fe3b2fd4080882713607bf46 +b3891dde4e00d60386aeff161b4a0fbc30bb31ee7918ce5fc0b49aac3238a000ced192c9c4c08d90de3a0ba973d7cfd6 +90a2049a15c02e59024a7a1cb0adea97501c60b1c7442fbbe560054c3d69264e69627ac57b7d9be01bef498bb2a60198 +87df67a4bd72444b5faa4f3b067204c4927c869dd3b29ad192d859589a9b2c1d6d35ed68310081e140add254a9463092 +8f80986a8dc8a0d6408ebbcb4f234e76413c11cb0d66067f9436bb232373100f20a4fded60f08dec3525315abfaa8523 +b061e10beb12ba3683688a4ae3a91600d14878ef78a308d01b93e4918efc666450e3f7b0e56283468e218934231df98c +86b9e55f3783d62e381659d3e06699d788b88aab1ff99848db328a83c97d223f602201bf2127c5ecf419752fed0a224d +858d878e29925c87243e010020007f96fa33264e89c8693af12857b362aee3fac2244057e159651c476ebe1dfbd67bcb +8fd47cdef87d7a569ffce806d2c2dad100692d6c53e5f5dfc6e274f897dccadcee30fc6c6e61373961bbc1f3ecbfa698 +892f2822daf3df3a759bef03168c1cb07408df62e024747a788e94d2da325f880bb9c6e136c7f6643f45b021c6ccb654 +8714e37ac24f5a198f219e7c88a92172fc3db129e044e914663ac708d8101851e7c53fce79d32d0e6da74f2ccd1d30ff +ae95e1dbba8b9e2c8dfbe1c202e9ccfd04fa396470035a699b902fbd86d5e6a31732a7c8cae00b9a4f6e51c8d560c7c3 +b0cd058e77498e860fa20c5f8d9bd09bb249add1badf84ba8d1bd49e704b9b4bcd67a5c3d211840a2c8fefab3fea639b +b78e468d3a7da0dd481f333ae56534e2ef97587be2e259a458e25aa37952aed1cc5f835640f812d8052f5bada8f57b12 +835de7965c6b26e7ad1b92eb6f0261d1f376fa12d61eb618d9b342b597c9c117a5a8f6a36269aeea88072b4641e6b5bf +b4d0eb99136b3643468c9c48a20fad62785a60fbdd3c054efac4bd1fa7979b4c9ca6c2c0b18069c0912bea2f19832790 +a00c47315dc0700a850966836a95f3cebfde04dd094bde0742dee77b89a05b5ad655921f86fafd1e902938ff34d4c58d +ab13fa0afaa92229a71ee91efae6d1b15f14b6eacefffb7401d41d0d6db24e24a8dbe8ee19b4680ecb69d2a0cb4e84e7 +aa56c0fb18401210062dbc653df8e3732aa8921a1280e9737e99b26a0100a13a9cba8ad0317a69bba16193362ee0f030 +8b410324a6406b345df0fa25f541ac20b7313fa55832752f70cf4c79f43b0bd3d5b4cdc447e6ba7bca08d0edffa8e29c +893362241ae412d9e5df46506407595c58ffbd7fb1fdaf0694c3432470599291238997abe118bf7737e56a4f5c9dc292 +921618194a756be81cb49d6357cb392b32cc62d96c8ffb7e16d9659a0f226a0436bd378da7b835054dbe0de2c6372ef2 +94a2904f10994928ff5367b777e1430047736fbece33442cf452018bfdeae62e84cd75cf80f8468285e347d504c94111 +b4b81545b767f380bfe10e0fea9c3cc62ca8db40b43c83ffb245259378731298e3eb6c3bdc3a16932f88f5d8a86edc4d +936203c2453ff01c6fc635e4d54320d69e60047d805daae3b75633c2259108497b778f011e5a057249f11b2b888ea76c +b90bf6378d29339443c3f2008b1e2b5f0345f86e393027f14a295e583bf6e6c2b10f54b6dcc42079ff0d356c405b03bb +916913f550d327de2d8d6c7723dcef2e3869efaf95fd963d95c8980b97748c61ad8e2e629cead8577266d93fe39203bd +a033c6f3d5ecbabeb83eb363e54e5faa7ed2d7f4fb771b161762c4f003eac4e1afb236806b784baf2222cad54e2d3cd9 +ab289d4a5771147e6c29ff9ac2bf65d70081ea6c6af2d9b728c3c144574a31b5fd8632af57c18c389aa2cd994938bb0b +9488da2019ff13e290eeac132b491df58b5b7b23c2898ff1a67bffd7e9c9464c39bc8177a57950fd28589e3d9ff9c6c4 +a5abe42b2e0891851440fb2aa6c1d8a86b571bce8b80c8e9e2692e5cb6d45a1b2f055c9fc4c74a7cd292871604129ea9 +90bfef698e83c2ba4dc9304aa01edd274169a978b7154bca518daef394f55857d0d1922ebef3d91fc5ecb3b895d9e0ec +92328f1372b6406ec80786041b6d57018b8507e3881a08727aadfecfdfcfb0824394cbb1150117ac5da5d71b89e895ae +9719751c5f7a65ae2bed8aff7b4b8c34539ff011b259b7ff54f63f9d987b3fbdce5c99534ed561aadaf07bb6e939e208 +a151816774aa9379fccec21cf212429a1c68cf91b055cbb9d931f461a8d5616c693331a11ac5c6fcfbd17d84ee0b44e4 +a72977b1285618a45943ad00f33f37102e2885eccd2f76785254eeca495068fb1d8d49865343e9e8313c6c2c3b2024da +a6f5ad2e023a1585d90625c9f7094f0e8851c79f0eede8ec582ee8e063407cc5b8298e5fdc4c786e4fbbcecaf33e787e +82901e008febcea0c0a14ae21d985a397630e18ee6e346f4a449f23be228e8f338df567d30211a11180b94fbc5204bec +b9b57fdb8d14d1be87a25f89553b3966eb7869e0519ffdf4cc4d51f4cec90d68f7b81cdc0450e04207276e9c63ace721 +a06eabcf43585a001448f3dc30411f3d5b74fd0a695c81eda9981842ba2bb0081d3f5a8360aa18b6d43ef13ea78b293d +926fe48a7e8f07559b7237beff9504476dd97b5b4d67acd01a3633358a6ba4c7abed5c87683a11209aa2ee759888e00e +a716cd3a84a963e2a5a46145b6ef4ebce705de52bf2945c374152a1e41c228a9c4eae0b6d1e222c1eea8b9c13c002177 +8a9b5985df6fb32cdb06ba1591a977545444478f2fe985ed1b10de61c630f0a4693c2185d63f0dc0256b208072c43b17 +a8eab26ae0ebcdf96a59fad1dc2d5e83b94abb2ea1774b607023f9d9e0fe065853b1e2242e794f989a80a47f550c0bd9 +84adbf38164cd04f3d770a7f4b8eae7a5d25b4a803fb63c02b95b71b33e454319c44e07a760d22bf5f58e7e372d09a16 +90f443a3ba1b9129a0bee400b5b29d42e50bb2aa56b0022bbfc3c6f8d69db40299871ec7c1b68421cc89e1af6b13a39a +81c5a94b379eb98c494a8d0067c748ba47e87a2ada0105202ed7651eb4e5111a0cd8569b06ae68d392c4fd74a37833d2 +8f92324b14a1549ee0b186073a26691088e41556d33b54258fc6e0b000e9624156db4e97861a0ec22960e6c47ca8a1dd +8b021cd0fffe055068cc460aec3cc455952e2ac32be5fa060e0d1b6cf30ed15381618f801249e893b1b9f10dd82077b0 +b3e9f0dcb3d6f0b138f589fa54dfb01f849890ab97016372d004aac55103f363a64bc0e606ddf75430f1534a30fc522d +8fdfe64af891db89b25daa859864d479cb7599486bd6f36e593f8f2f839f942261ffc3eed5001a93fde44cbcdc24c583 +a9e4554373c5073e135874e2bacbee69c65308eb0785532fec6a37834e8d0b437b77a2f11cc63c87d7183b82cd9b6bc9 +b4c47daca723ad7193ac5098cad4dcab654186ec5ea5c0fd014a3ac39726be954565a901694ba211820c011fa1c59e18 +8835427e86cdceb4c11cbea331ed724e4e78af15e3bab5be54f6b926bf66b5d99bcc40dbc456d86342c9fa83a033c2d5 +8ea84590a400cedba047c2661378921a42f5ca0421da58c1bcb37bc686a2aed98afab3fa5e6ba3a51029390ef3cdf4d4 +b48551170fc479d69fffb00fae4fba301e92e37cae08f596db6f6489c3b7020edc074f9e8d7465b84e9dcef1b6b3aecc +a6f318b1eaab00836a330710e88bfe400395b3081485f6a212e3cba9463f6fe7864ba4f71e57a411ecdf2bcb4d189f96 +848d5137a39999141a79f4bdf91150796ba36352d8525821bf3bd6e070b352792d79147341b8254dd60fa8c36e9e2618 +a8526f8904b1eac4ae2a25534aa91e8031e9aac7b8f58d8f49897e920c36c0232f4a30aa6eed305deb0f7793c115b267 +b8b6a727c44c37a8388383e959d195d1d0e51a657d4ba360633d219d43c5df645383e2406c25f1d418e72b862c3a6e9b +92e64adf65b42c978f36dd03ab22ba983bfbb61944efccdb45b337ceb486beda99818bf20d32a545503c4572bb0a4983 +9653bb83df66260a0bd059cd4244ef7c661b089e403d26ba777d2090783ff31f963f5d3a9c125b1ad1a1d19134f3fc8d +a74e72355e71ae5eb36dc75191643500ca3e67f18833ee981010e7e7e60a68e1b01b05901eff05014b9ef29aa4829f45 +8b2139a5da14524cf6acc593144db23db424b95b8c7041d8f6c7a14a6725dda1cd09c42bb3ae26a5a3650affaa742800 +a60ddff4300ca44a7c7a00a1f98441ad1438e07c30275bc46551cee1b681926d2c825cc8f90399ee5f36bb9fbd07d3dd +a04e5e9958867a5acc15fdea0d88951cfebd37c657102f6ba1dcdaa5e46cf1c823ad0d98718e88e436f260b770599102 +95e977abeb70d46fe8d7584204770f14c856a77680607304ce58077550152733758e7a8b98b11b378540542b1175fecd +8c9ec93ed35a25ce00d61609e92d567459a45e39922ccd1c64ab512e292787125bd4164c00af4cf89fd3cf9deddcd8bb +819819ad0338250d9c89aceda9e217df12ac54e940c77fb8420575caa3fa78930689d0377ba88f16d38179a807135dc6 +8baafb379d4150ac382b14a64788d819146480d7a1dccd3deef6889686ded375900f5df069843ef14d754ad3d7540401 +ab827236996bb79b447714c6993af941c5ae66248df4d9a6f3650d44b853badb5c0cb67804210e07a7b9d66ca43092f6 +927656c3eac8d2eb575e3daeb77f9605771170c325bee6aeade10c083d42bd8dcbf3bcc3d929ea437001c7cf9a95e2da +af22b212d5ee44fd4197966b9690487c38a119cd6536cfb8c181f38a94610dd9e057f95774047a446504dd96dd11e326 +a44bd94b9e01e3ba36340f2ac2201ecb477495d4f1fb6726a6b439302deabb5a35d237c6a6aeb7e3b0a65649f8656716 +af367aeeae3bba14fbdb05bcc1a521000dd9d37f5c34ae56fb306d3dfda201d0329a8b6e89d98e15825cb3c6bfdb1194 +abcc4fbdea43e50ded9e2fb01464f4e87fb136e960141e8d39214f92794cfab5634f22cd40b18d8c0e501f2307aad23e +920786cbd674348b9853689915dfcab02cce2a4596d117962bce36aadddf4bdd143891e22f2c8015517039a64e8aede3 +8cde63b9bd57cb3ef743f1f3e8250669eed739e5fbd68c500a3cc0c12f93862a69aebcdbc69dd8f476c2eb307f572a53 +b967e65a5f1cd8d5d570f5e87e7e186fba51b9504f8e466392a76d8a971fb91fd9b7565bcc1647f50d7d15e48b93bc95 +8d5a87b25fedf5edd57d870304bfd9081dc78c3e3e3b38b997260a92edac7feccdaf24feb51822d2edc223b70bb4ed5f +b6cd5d340a57f8ec73723c4f3ecd6601620dc8137a3e75a5d3c578bc79a9cae86b379950c644dee2ff99dad780d025c1 +b6f0a8e754b7f52a85a2a2e6512cfd017f7fb0418d19bb318308951c4e242d3c65bbcb9748da9cbc91a738f9ca577332 +a89dcf7d410bccec385400dd96b1cc6af89026a431d0f531aa992cbd7bc8bfd7c5f360bcb665bda1d72efa17bb982551 +97788e7522427a46c4b6258d15623ef7a565712812fa80d001e1de8dc1791392702f3fa3cce5a8cd1c5755625a0ad10a +b5338fb5e137ff625b27c5148298f27ce8f493e2527c5d0facaa49f29cae34580d0d6c3c1074a2e46cd8db3f56004ea9 +8962f006d7b1095dd0dd132ffe7e87e328510c95ad893cf3b2ab21c177c5cf2c27f47d8856f87e9762c547be009d25c0 +87fee9ce9c26aa476e67e0791a809e0a06a8a98facf3faea730d438d3e516cdf75d645fa75c906e4e44ab9237a22c016 +b75ab972e1a1214bab0b38cc3e973d44bb233acda5b4291f5e110b6fb78fdcab93dc63f01168debd898e165f615be1f7 +b5a0fb52bca279d3853761a94b206acaf313df33ae6303d9b71edae90b66fc507adbc60fb11e758888736c81d5d80c0a +849b8f0005010e684701cd3a4e59e8c89e5fec59af6d2de5b6332cde03b865ea84f07f0b80ec3404380b0e148fbd2c24 +96e2b0b6fe78408f9208f809f5c40398100b2dac202c8c5c33c2189560dea868270a598c419871a5a2b67783354f6014 +b234b81f996142d0df2c719760bf996544820a03195a6dc0ff6a72543692f5a369bf63d1f0b477ef2fe7b3234e41f685 +b85e39bcf40da1a12a535740176f4de749a93824079deb5fdaa004f3282fdefaf5275e3418c88c419bd42a3dd2ed2b3b +a27279304b89a18a4e2b443246f2368fb8b15f46a34533179b6bd2ef683f6e98e222b7a32880b39b8fac1afa90133803 +8923c22cf15c9c1964213d725b337ece9ea854775a06f75f232c4859c7142a3942f418354e33066298aedfba3cb27e62 +b109f714311fb9bc431ef57911e2cad6a3949455b9f23255cd7edea35be629e07f845fe53e2b12a32305ee2f4f264f27 +b51e82ae5c7d48050e405897d0053e9ea4b2714d002e88f78c9a307cd50b9c6b3ee7cb86f86527be9d964b01895fab20 +90db256931c7f98bcf3bffff4d496739185e7a20f329ee7bffd4e0850a37739948ec745285703967f4ca50ec370cf68b +a0485ac0445d88dafac56bfba2563b020cfc370f54c1606c89d12cfd8a4d1336d2ba50306e476155a6f5b0e0a1f2d092 +a00754c3462e74bda928da855bbf90f9077db395e32f03cce9b2955546d900b72330d247b7d607b65e130f5b0d883de0 +8547d56727c3ad8b5c8ce622ed9ad86fe8cd78e6e4848c9845914b5063b17330bd10b46d8d3f18f83ca09ecb28d1afb2 +95b937b2a979bce0e159ac75c7d5d659be8599c92305e73e942aab414793364a3ec28c7c1c8491a5750ba84a29828d8d +b011e150f0294e45a0f4c69409999d0c2e602449dbd67ab95e8258466687cd733a0329083a31b03722f4e2580ddc95e9 +924651a733ad5e5d9adadad3ea6a6babb8e455c8d5f2cb5bdc83fa422e7752592190ccedaa827b866861e73506a6968e +a4d5180122f8e31503ae027e54da50f72f5cfb910a6f7309bd882b5cd666f454672591f1f20e461e182a47d03b47052a +ab19ae659c4f73ea3d21895269dbec583c7029955a36469124ebe295027010faab56c4a475973497f28e9a77c03b8fd0 +ae7ea1a803d0f439e91494f8f35fc1167dae23834c0c699ffe65d3da8b09f8df5a53195a99ca7b8558242279e69578fa +b9d63cf0e30f9800101b43b980bcd2f229758e74b21ad5354866b4e684791c08a184330dc316228a0d67fe0210f2bc4d +8c41629744391ddb96dcbbf9cd99b13d36e57d65962e0aeb92ebccf1c4cc769626feb3ec0363def08eceb102b3dd4ad6 +b2848ff24faf9e667a8c19d050a93896e9e75b86595f7b762c7c74ccdfb9db126ae094961fee7f5d1192776c1ac1a524 +af013bc29206743ce934d5887b8d0fb3667c89bda465d2321835a3618513fba6a459dd7566268220ffce7e0c97e22b2c +8bb799e36db1132da8e8b028ea8487dd3266b4628c56dfae4ea275f3c47c78e3d7445ab8d0aaee4cbf42148b3a148175 +ae2b81fd47c038b5195a52ab8431f0d3cab4cf24c4237252d955aad2156adc16dda9d3270157e0bfe5a44022e5c051ef +8e0129213b1698d2ec6df132356805a8633ba79e672e586dfef664ffccca71834253ba14f296da962651fcba2c002622 +a1ae30b500ae77cd9bbb803d737b4a5991cc780618ac22b5cc179efd8fe10afb8c135457f2e7b86ded485ea12eae70e5 +8a39723077b7c0df6e3bf6548afa3910c214ee275951fbe5155a39473be98099626ea14d844630a6fa90292b9594665d +a628386c79b61aa7314b01d9814aeec20c2a66e3deda322a39957e7135c2e52b1da486d1b9cd61c87afb22c1d10f6462 +97867f469b01249820aadd9a54e12d4fdadd4555f2d530450e1f8f6d2dae57360578e2c2c8ba41e3b5950df596537a98 +97f192d0457c217affa5a24267dd16cb4c01de8fefde9df4884e1906d2f22e73382dcee6c7d910bf6430bb03f4a4f1e1 +86d5b5739de8442dc74d0d8dc78e49210fe11bf8c6ff0f0faecbc47b64812d6b28c8afddf6d9c0212f1988451d6ccb1c +8ff3312ce9693cd4a9f4b8e75bd805f65b0790ee43fd9e075fe4cebc87185bdf161335049819f22530f54fed2779a5b9 +8dc41d85548bee5d51941d55752a500bde3c5a8f3b362da4eec307a963968e26605048a111c9166d448b8dddf6f53892 +996bdfd004b534151e309ac925fa5ee7801c9da4f6b4c43e156d1158b134535a2a3956e1255e0dd72ac2af6bddaebcaf +aead652704b788bf4983c8f725c644c327a6e9f6683215f5c826c09f82fd2e40631791f51d14e6aded91fdc018d45501 +991ffab58a82b98ed8fc7b00c3faca153589fe09cebf6a137ad506387a1ca4dba475b0e4a1b9bdad829f1422facaec39 +9652e6c4ae084221d6bad855ec0bc11b5f855c6efba67f644e0902ab790a98861cecc6ce047c68273c3aa7eeb2f4c7d9 +b88b816507aaeea6dc92b861eabdc96988b74d7883f20a4b30ba249158acaff3c50d261742fc9ad2e9eba888a8d59065 +acd028a51e16c07a10d2073b9d03070457ac5f1246365295a1359d015c460b92b4861125fabe6f114de8197045df408d +806d3cd9d02d41c49179fe7dac5b05dcfc9a205a283135d4f008d0771c58e6f963d7ad0f6798606edda718eb5c7ff3ed +b9b71f1657a6b206fc40159a941e127f252a7b324dea864ecd804f48c0ed86da9778a925fb65491204a92bc2a26fef32 +80ed67bd0e74350c875abedc0e07fd42ce7cb926f0f3fb1949c6ac73f2300b5a14a5c6f6ff8aed99d5ea5029bb8e7ae6 +9875f67a7a473714e4dd75ee0c763ddf88101532d9680724b3848fef69e218b04a96b90f88e0f4409aa40b9a21507ecc +b4a2bb1b421e5243e5e7576a0672dc19f9f70315a03f6411c19f76616ffbb70fc5dc0e57fd4ab85e24ea2261b7ce38ab +879723002ce43e6c75ba2246f51436efe3376242beff987d025c3c4476495af32d52a54fad5d9ec329a442b93bcff1ce +a4121efbefd9c3eb143619afa52a916f199c75024908047763b29466cdfc837c2fcc894aca63044c33c41c777e529b5b +895f637b497a9766714a3d9e3c275a1f0c9ddab105bf4c8b7e663f36cd79492022415bb4938c1a4849bda73106ace77c +b119acb8b161ce4384a924645a248a656a831af526cd337d97e08405415b9dd22060849c76b88a4785eb5e7214961759 +802e712f4c0a17009c4be6c1e5ba2ca3b82adcb68793ec81f4489b7985babd8a3873d544de63d5e5de0cb4dc5048c030 +ab111051e4651b910c68ecfdc33f2d99e7bf4182df68cedbdbbcac219a543e04d93ecb2763fe32b40c095c7ca193c331 +855c73ef6afc6bcaab4c1e6388519fd5cbb682f91995bebd558167715db454f38012291beccea8186a3fb7045c685b67 +a29d02ec6d9baf84c19dfd0eb378307703bfafc0744b73335550f3cd1b647275e70215f02d1f4ab82a5df4d4e12dd938 +91510a45b8a50cac982d2db8faf8318352418c3f1c59bc6bc95eab0089d5d3a3a215533c415380e50b7928b9d388ff89 +8286e7a2751ca4e23ea7a15851ad96d2cadf5b47f39f43165dde40d38ddb33f63a07bc00600c22e41d68a66fd8a0fa51 +a413d4e619b63799dd0f42ac57e99628d338b676d52aec2bb0d1bb39155ad9344b50cdfe1fe643ff041f1bc9e2cec833 +85524e5bb43ae58784d7e0966a664717289e541c8fcaff651541718d79a718f040a70aa8daf735f6635dabfc85c00663 +97f0d48a4028ff4266faf1c6997b6ad27404daa50ca4420c00b90f0b3e2d82ef8134d0a04108a74955e61e8dfeac082c +8df6145c6cc39034c2f7331d488b8a411931c8faa25d99c5432831292637fd983d4f6b1a6f55522b4a42a462d63c6845 +98c2060f67a916991b391e67fcf23e5f305112807fe95bdddb8ce6c4084126557e4c5f003afb32e30bc6808b30d4b526 +8964246b3c2b8f7312f0a99647c38ef41daf70d2b99b112412356e680185da6810ab8ee0855ad7409d334173bcc4438f +b56c2c416a7069c14bdb3f2e208c5a6ad5aac1cbe5b1faf99dc89c7141d0259d1c6250be9d9195500c4a41182ad2ec3d +b7864583a4cae3b1083dcdcff7f123d24a69920a57d6594d0b7219e31bf0e236682442b6499a1f6795cfeb4f5f236695 +a064f94139bf1b70d476bde97099631b1284aa6b4d87f16bfc65c075e58b2f1b3c2d057605259f806e545674a1169881 +80d1bc4acf14c0f487cd57c5d6157b7f38917e93cb660f1c25e474fcdcac3c3dfda50f6bcccfd6676bae25c4b6b5014e +8ad9a4976c4e3e282843518149fcf5d454240740f4b91466f6310b7216d23d70b9b47c42870293252f29f092f330967a +914197593d2d99d784c704cad7ecd3f0b9f55dce03fc928d13e1a1034566c4de754f1c2a5ade047b0956415fe40399ec +8d77f5e29c572ec3c0ca39cbae2072ba4102403265b3d8c347a00386da9c0b8688d6e3280c96037c300d57b3545f3773 +abfdf79d935fd4f06a04938d6580a8cbf9735f0d498f49677f26e73d3b34b7075d525afcb4f14ef1632cb375bef7dd55 +a97a8c446e3edc86efac7bda5e2e5d0158c909552a3bf86151df20ece63b8d18b608f477286fb1c7f05605ab7e6a7c2c +8618d946c7fd62486551c35486fa466bdfcdc63c941e4cff5a01fbbe566b7ea9dc763cbe73e2acae063060b619a212a9 +8d03ee468070936004b06acf64b868963f721f37faa09887f8a82c155ad5c5732572a6855b531db58af03b1afe034a18 +8d3247f75966ea63935ef6049f7c889c1651374adb446f49499fc9191dbcde7ea33cbc1f1e2d3d1756b6e69870404643 +afc853c3a3facb4ba0267512b8242327cd88007cef3bf549184ee891b5ddc8c27267bae7700758ad5bc32753ebf55dae +80df863eaea289de5a2101f2288046fdbfaa64f2cf1d6419a0e0eb8c93e3880d3a3fdf4940f7524ea1514eef77fb514e +8434b5888c2b51d12d57da6fb7392fff29393c2e3bfee8e3f9d395e23ddc016f10ebe3e3182d9584fddbd93a6effcefc +b78cbb4c9e80e3808c8f006dc3148a59a9cace55bcbb20dd27597557f931e5df7eb3efd18d880fe63466636701a8925e +acb140e44098414ae513b6ef38480e4f6180c6d5f9d1ca40ae7fbadb8b046829f79c97fe2cc663cbccd5ccf3994180c6 +936cb8dc959e1fc574f6bb31f28b756499532ebb79b2c97ff58b720d1cd50dc24b1c17d3beb853ba76cb8334106ce807 +adda2116d9fab2c214ec10c0b75f7f1d75e0dd01e9c3e295a0a126af0ea2c66373d977f0aefdda2e569c0a25f4921d0e +89a5cefb80c92dcad7653b1545f11701d6312aef392986835d048f39d5bc062cabc8a9501c5439c2b922efc5f04954d0 +b9acb52747ce7f759b9cdc781f54938968c7eeacb27c1a080474e59394a55ae1d5734caf22d80289d3392aab76441e89 +8564f72ce60f15a4225f1a223d757ebd19300e341fd9c1fe5a8ece8776c69c601938fa2d5c21b0935bd2bb593293272b +a5567d7b277c4ebf80e09c7e200c20d6cb27acbaa118c66ef71cbccb33ee3ddce0e0f57b77277ae1db9c66ed6e2d8f30 +b82e9c2d8df1cdd3b2417bf316d53e9f3cb58473c4cb5383f521ef53e0af961ef916e4f6557a6d8b4655ec01415231cd +aa816dfd2814c8a25bd2cbaf66303ee49784df471bac4b3188074ea30816f00f425234454d40d8ad8035aa925d74da36 +9919f384df20faaa2d226b521cab207dd2b62420d25ebbda28c9b2ca76a2a52203b2ad7844c1a25f5c75f005c5a83149 +b24a6aa35c2d0f87e36598b36224c64427cd69642b6f9c1bd478a62c70f8ee69f85028648f6603b4f04fb21355f2afb1 +892e044bdb1276b455eac2204be105e1821f987c2570494b1f32aa09506caba7ed343cd09b1bc126fed5e0fda3d0eaad +af0e01a3ad954dc048de18bc46bb1c4971db2467e839698e4dd05cd1adcb9261013fe9fd0cafb946c0b586f6aad86d4e +ac152f0a9ace425378daf02510eb7923ff1ed2c0f8d1deb918e4efb63655de1ba58c96438e9aa23abdf2431dc771370d +ad8c7419c097709347e2394195924e09617b47ac5c7a84aeb9deab8975f22155de0f70cf20d8a976551b14e3a2683a2b +808f14f67ae801536fb70a5898ab86e50ad35340cffd0648daed2f2c4564c9ad538034b2a179a6a8bfa27e9d93b4cbe0 +80a74ab7ce4769db93cfa695a166db95f0a9c47885ff826ad5d93310f36d6b18b5351c67c858b9837b925e85a1995b63 +95b88c3cdd64401c345828f4e4754b1a88b4875a14c08a668b90acd499b3b858842669ecd73a46c5d9f1de32ec1a0120 +8ddbd770b7b18a5917eb43926fa05004e819f1d1ead05b915269e4a86b53e0633a90559007e59f6705a3769e2126ac56 +ab6db5fc220754f19948bef98844e6e38dd623565d1695e1198040c228ac4fd863c1f168cac1d036bbfb718d9d8dd036 +97bef628e977c069e60c395a17740e0e1bc1828f5607ae7f30ce5a0c95f02b53af2ad062700a75212e462aa22c3c5465 +b68d465e04fd17ca98501e61eccb0ce30401855e98046e0c1debba71c2153d6a7a704aa36a6f12454696e78e87181cdc +a79cfdd048f4181e005bd0fbac0a8424495474956b58ce858d2b700fb0f931c406282bd33bfa25c8991bc528d12a69c1 +843f55fa0a6a0969daf2b48080738f30b269b2e7ec123a799e5b203c0b3b4b956dc95d095bc6550b0013918cdff8a225 +b683cdf2823036827e5b454bfe04af9bec1850d25a7a7a44aee7696b6ff0468b7ed6885a41dde2b8f3ecc4aec880c3d2 +8b500796e82acdc89778e0c0f230f744fb05f762000fee877bcf57e8fb703d212dbc2374887bdc2e7b7a273d83a85798 +ac35a8ee87bafecb1a87f15abc7ccf4109aab4ac91d357821e417f9b1474d196c38cc41cd13667f68d1ffab5e79a6e92 +b6e517739390cfed5b395d33b14bce7cd7aaece57fe79a7eb3cbf150dc10765c3ea9fef7976a21a2243687e6eea38ef6 +b53901eeee26692273365b789f2a60afc9b5f0df229c6d21b07016cf4c0e7985beec748aeca52262f68084393ab038e1 +ac4804f33d8ba2b4854ca3537bd8bf2dda72d4e94ff7ecaaf9bd3b7f098343d74d765471ef80072ae34f860b052cbfb1 +8c6a30a93f1dde18039bbdd1ef294552bf79856e20bce863e4b8dd72d906be3ff22468ff3610e06b5a7d1745dde7ead9 +88f0607fa3b7cefe20a02115572b16fc3222be86bb19e592c86c48afbe7e0dd523492b0c29a3bceb9a20f5538bc3134c +a660b801bbddad725975ddf9a8f606f76ecef831f954be224d6178c368e1c72d346f00c4a4c95c289b62d36f2af323cf +a75b9a6aea9542b698938dcd6cc2f6fe0c43e29f64b2f54aeb05d35fac73d41aa7fd750af4fa9333644aab8db90775b9 +83e1b7129d963d1cd076c3baa5fe422148e939273db173e4d59d1858a7d841eacac7fe817d15ab8f8a493bf46c2045e6 +9060a2e9c24de11f9c70e039b5ffe9e6d32f1ae39f3dda263610df2265d917679e689898e4a8bd84ad34613dca5e3761 +b42fc8b863a2af15e04d1fe6693c09b46007c0b8298973fb4762b45b4590ad7fe0aa758918b2fe5ed1ed0359754fd955 +83e6de7860fb256ecf7b47506a5e557d0fb0aefe57fb513c7dee2bd9604712d08ca26adca7ba9a54b712372a7c585a26 +90586e9cbbf71475ecd3e7b5753b286804dcce61e165502a82b960099e79272de8b7494b8877b54ae838eb5d0f71af2f +b2e4b0d21208f73b7b75e08df80cde20c4578e117d37092a490af82354e2afd3a7dbab46fa2d12fcb731cdaece69c2ba +a010961239bb8809fc7fb4aa08fa30d33a130f9f417ee9ea60f587dcc5ef4e1b7abcdcbf8e848ecdcb7972ef6af46e78 +8f511fd58d1e3403a5eefdc0a4ba6b8af848c7efddbf9575ee84449facde05ae9a24aa41a5725416467f6fbd11369c52 +b24ebbd2d4482eb618cea1ac4fbfd9ed8c46c0988a27259300a7ce5ce1bb256aeca0357828cbbc4cf0dfafbf586040e1 +b3ea29e9cca55250e9b7b9bd854edae40f0f0cc65fe478cd468795d1288cc20d7b34ced33bd1356f1f54a4291faa877d +8a8b20f222d9e65bbde33638033972e7d44c6a310b92a9d9c5273b324c4ad1a94f2a10cbce8300c34dbd9beb618c877d +b2436a9a647dc3f12c550e4ddc5b010e6f9cb3f3504742d377384b625fc38f5b71710a49fb73ffaf95b9856047c98201 +a13f8b77c70621e421be94c7412454adc1937b9e09845c2853ef72cdbe500e5c1bf08e3c8b8d6b8eff4bce5b8dec9213 +b25de8780c80d779e6c2e3c4e839a5a107d55b9cccc3ad7c575f9fe37ef44b35db4c1b58f6114a5f2f9ca11e1eb9c5fa +96ba6ad4358c7a645e5edb07d23836cbd35c47d9a66937d09486570e68da3c8f72a578bd2e14188d3acc17e563a652d7 +a7f55989814051fda73f83b5f1a3d5385cd31dc34baf94b37c208b3eaca008ff696fd7f41e2ecffc2dd586de905bf613 +882d0c7c81e58eb9560349f35c35e4498dcde7af7be8d7974b79d262304c26ab67ffa5ed287bb193d5f0ab46b4096015 +a607158f0c1fd0377a8ee5e9715ac230abf97406c19b233d22f5911ebe716967cc10425546dc44e40c38bd6c2b4bca2e +87e8cde50e5d852d3f073a43d652f7186bac7354612517cfaecd4a1b942f06fef6f14546279c0dc0262e2997b835b2a4 +a1c93acc6db9d5ee426fb4a0b846bb7a7b8d5915bec777a9fe6907246b0beafb8938941c8c79ed6082155f75dbc1e332 +b1e4f61457b86f76cd93eafd7536f72baf239ce5a62bd5a8085a34e90576b1e118e25002d2de49b01d6e9a245ee7d3a2 +a0435fe9a4bd1031ec5973a103ec9396b2ce9fd982f6d9ed780fa80ac06a6e47a0a6eb2daf52df1dc9292db622ee9fa3 +b66d8e8a1717e4bfa42083b6ef4490e090a73168b2912f2111743e089027be0a4945a229ecf5d0b5eec11b23f0e11303 +8eb764f26904eea4f4169be6e75beaa6a39e4eb524625a15a78befe3d8e3cc82692d9b135590c20ed460d6e4ba630ef7 +b7e4aea6bb09829e53fe83e53f49a7a331a6d7bf76e0073d758577e6d6fbe63dab642b23657355cad48896ad8715119c +8f94207982373a99ffa282673f192aa98d0c4461fb77c31dc4549628bd9687a249f1b3c66b1840929341e42516c5c64a +a9c673cb247b13e17fa5e616f0399b7f5c7ad043e143e44ae68855a840870ab3d2aad737ebcf74c2cc9688d17ef3a794 +b02635104dd28c02068985256975c0af783899eb996e37d021d9a35238deeea9e836760db21869be7b6c82aa687ded29 +b33bc0966389710812b5f6698afa3e9c84839a1b85492ba11e6ded26695260abf66be6fb355d12d3a8524966f0f89e0f +a79c0dd09506951c33da3cbc23843fd02d641fc24c640a205e6e8150240372847312b9381fb03c5d301fe4dbee8d0da2 +b74de6f3a2c502b5b658ebe8a9b7edd78afd036f5a2736aa06502863b6865d131b9e3542e72a86fa2e1d2db4927661ed +99e365def1452ff9fb4b9eccd36ff4154d128469ba5bd73e83ae457ab53977cf6fc04a5d05bdcde357ab539e34bd9fe0 +b4f2bfb95abb47c67870aa6ca38ac8f3ae1b1a2bed064b1be7ff90865ea12e4930fcf66429c7ecd1183fae4a01539386 +ae4bde87f36b912e92398bf72e11d5389e93b2de1b277d7ed4b6fb5a9ab9f71a959ec3bcb734c11079440fe42b86fafd +b826459e568efdeeb66688482b67ef5020787275123fd3192f979b6175e3b0ed59e17cb734a0a052bf13f0afc7bd237c +a99dd735f4a7c85cb23dcc7f4835f9ab32026886909aaa95876b98029c37dc4d621726c872d3a9e50403443c958f4029 +99083545034768010988bf8a9f34486c2cd9da27a1d10db3ab86eb69a1dd9c8ee723e7da4ef2aced63c1dbd53ccc52cb +8ac3209349f0142546c714ef7e9d1b094aab5469b8f080c0a37cb0362da5349e108760f272fbba770aa468e48d9a34c4 +af5f48ed74b21e3f2c1430192adb4b804dc873cd7e8f07130c556c30e7b78df0ef5a14b205368848fa9185e5a68dee0d +b8b741b65d68df89443523ba74203226f1e0d13bab073d183662d124e83e76cd318b2bfff09879c04d81b577ac895638 +914abe4282d11176d4f2f08c6f15e6c2d0cde1ab4de00bbe888015c205f51929d97296a0a8d3ca5641f085a29ea89505 +83ec306b2a9a6780efafe799df90b1aebdbff7d47921a136ea8a5648b9708a97231245a1082fea38e47ecafbbe000528 +95d6b58d70b388dfcee4eda0c9805362ccfb60a87603add565b175b2c14ed92999dfdb0d3724ee3e5d30535f282641e9 +97eeb4de607c8306e1d4e494f0d5db126d53fd04983ab5674ec5996b971899e734fa4011f2c889da21154ea1e76dbd2f +84ff21977fbd873ea06bec444d4ec9ff0e3902edc29dfa25f3bed269b3709e3116e99dc06cc3e77f53c53b736bf8fc29 +8ecf483874a040a4a1c293af145094fedf203a5eb37c3e165857e108cce3e1210e0bfc0f26f4ae5e2194024929ba034d +97d9b92b2ef34609d69402167f81bce225ed3a95718a3b403f702b93e96a121a8f7f072d0ff47e8b25164e204d1576bf +ab87c39cca1803b4e84b32e40ff30289e3cbbcfbe16a70f9e025643824752359be1f10c3e5398df402b6fec64d5a3537 +af84ca57e6944332884b5c84750afe0d5950015e127acec161853d55d48fd864c7da8d59cc5aba4ceceac650b813fcc0 +b1d23d98edbe7089ce0a8432e0eb3b427c350fb4bb39eb2aca3c2bef68c432078cb9b4b2c4966255e00e734fa616638b +8e2b5252e0ea96d40835ebfb5693af49946509975682d68651396d6bb1463f09e75fd0afa04ccea49893b5b9c3e77e40 +8db25e762f1d4a89a9a1cbc61c01698e775906bc88a921b2905735457a35df9ab84bae12e1b1b8dafadd50212f1acda1 +b5f7cd163a801770a4034e2b837e00191b0ac63a2b91032ae9a99ec182d748798df48a14644935fabdbac9a43a26749a +998e7232e5906843d6272d4e04f3f00ca41a57e6dcc393c68b5b5899e6d3f23001913a24383ed00955d5ec823dbd3844 +ab2110a5174ae55ebb0a788f753597bd060ee8d6beafc5f7ce25046ea036dba939d67104bba91103d7838b50e36703d1 +a211972a4f6a0303bec6c86f5c23c0d25ab4df0ba25876cbaad66ae010b5a00aa0c5daded85e4326261a17a563508a25 +a49f53496a4041a01e07f2c2cf1e84e2ee726917bb103fd267451b9b7bb1331c0afde85a79a55409bfde27328b2a4745 +934e915c67c7fc47adeabdde49f63f04644fe234672003be2aa0a2454dc8d9288f94293478936a450f2e3f249d395b5b +b6e69e9d6808ff7f60a01b7aea6781495d7a20f5b547852d3f0af727a7434209d3015a9dd04cbe3e272918e32e345508 +b348d3462092b5c6fead7e515e09611438db8d69650876dd3b56226e303252bbeb9e9f3b888fb911445b0c87132a1d0e +8d6510334a905efe5a32001e167f1ba06f9bc4af7ffbf11b7f7bf3c0076b5cca373d8c47e98c1ba8755bb22632bfe0e7 +a2d5200f20985dcd473d119ee97e1c0fafafa0f191185bfed9cac429cef8198d17665dac4f70342eea66e6e4a7370d58 +8dd7eb6b1841b3f33425a158d33a172b79b2dc8a01378e4174e67a1a4c8f4b887f02c7c3a8f354ed9eac718155bcdf37 +b16ca19388642f71afcd9f7007b490d82f83210ac1a989da9d4bf4c419de07af8c048cd301ec7e01b9d06abda7c169d5 +93cb2d847d1a88de8c1c9d5b3c83efd0b7afb3682942bd2c8ab5ef35b33dc31a097a3e181daab8630d4e840b677216dc +a8b648c769e77a7b41c0c689fe2fba9bc585067e004bcb1732cb7b1618e97b317781c36c23a00680fc780b58c301a789 +918c321100d57712866bdae84edf7e42df30a32853af257e0cb4da028842a43b49e775f3cecb85cd817269c728de7319 +a7b0f6ce42e00c519e69b2c78fd9b75a2e7103e5892d3c1afd70c9b5b9e706180a4bf73dbb2d3eed52bfd521103ec5b3 +90041994af3322b010891356afd8115340bd7fd7ba328716fbc4fe458236c8cad8c7564ae473d6091ec3a54bdab524c0 +acb1ac83809573846231f9be2dc5f3e986cc36dd9574a620b1cced45bad0b11ea957ce8c6cbf964a0af916781c574f05 +ac54677dc002698fc4d454c7beb862ad085d0514f92576f3485a44c0cb47afb9db2c085058918a3508f9b3de0137d97c +8dea56e1bfa150e442f8484b2952b116781d08cfa3072d08657cc09b0217276efc4ab6f5fd726bfd826f6976ced8da29 +a2b09e25baf01d4364b5205fa0c4dea84ef8fe03709113b034f88a0f0a502a81bf92c1d4641e2ac9f3a6f4203d3645ee +b95fe37aa351b4292691a9c2e547224c37ec2751a31ecce59810cb2ae0993da6fbe5efe0ab82f164462fa3764b6eb20f +a3498947e91a3a540e86940be664fc82f1e83ff41a0d95eb84b925e820602a41b7393c8b458bd4ebbe574a754586787a +aa2516d3620c832e5728fefdb1af0be30c871cbad4b166a7a4565af676e73bddc2f2f51acc603b3a022056daad2b330e +a9251b56467fb55f64c70729e2ec77a59d7eac79cc0b4b25ee405ac02aea46bf1cbc858bc773934a6d9bea57cb528185 +ae8c0a4ca7ba6bdca8764bac98df0581f00358db904e57867e6ffdf15542e55f7bad2dedac152ef88038b466ed901934 +b0881e27e52cc6a57c4f3f278dffc7f63a9174b68bc867c16d8a151d9cc4d0aeb703d1074d1927faa9ffb43e10912c9a +b67138465d6654ded486d18e682f11a238d6a65d90f23d6b13eb6a1b7471efbac9ada6345dfb13e5432196d2a256829a +944c69a6f1126edd38f6eef60b8a5bd17147ab511e44e8e0a442e87244d8f35236ee0b8d3dac0631f8598f16486a5f74 +995679dbe03dec775da26708cb9200dabcad983825f1ba601eb9395f9da350ca71e8af61dbff4c668fd0eebac7e4e356 +89de362f02dc14de6995d43cdea3c854a0986c605ba5eb5dacf24e3a85983229bc99a2fcf50aba3df59f0fb20daffe29 +84607f0e2d078df22d0866285614f5d78cf7697c94a7d1b5e02b770101ceecbfd53806b377b124a7320d9fed65000b97 +93e3faab60050dac76ab44a29bcd521813e76ec8e4ae22712d77bb489bb49f98f9087acfd6a77016a09a42ddedab2d73 +b7d64a7a35f21747b8e6a874be31ba770c0d13cbd41448411994e8cebb59591295a26bacbf74ee91e248a5b111aacca0 +8dcad429a2b0d66b9eb8c1c3924d7a72979727db6a535526a3518bed2a9532d12aad1c5a778824ca4cb98e3e513f85f8 +980882895faa347bd2fd1dda7b8ee7ed49e69843afe646f677b371eecc7a10e0f4e40bb55f28995a40080df471876816 +89e8e7fb51df79971e2f7bf65783614abbb0d7f3f1b4a15d3f0d160deafa7ed1c446d9a5ae1a77160d4dd94ceed8af13 +93fda8d350392e9c4d4ffe6534f7e7be53f32483d9319093e8436fbb8166a3c01085dc858373e65c7f4d014e0dc2bab7 +897521a87b7ebf7152de5260c0875e3c7df1c53e734c672569219ee6f9bd196c5ecef159b6a1d3b7cd95e91b9b8803ff +b59affa408a0f7bd7930fa3b88750fd043ce672c10a3adeba95a12f23f0dda1793f761a86f7409ce1e6fd3b3b7195381 +b4422ccc12f4fe99c530cda610053af9ffe635b633d52492fd81271d1f6f91b87171d572d5bd0e46ff63e221fb2fc4a5 +a4542cdf3346ee0867c08d630c2aefc57442f1c05c0eba52d223bfdca5e9d0bb80775cff6ce2e28aa2730231fd7b1bb1 +a7d297bb09118b914d286e5d1e87bdf13f7d174b988e38fb5427902e8e8c674072f36b19055a1070abcf357f8668f35b +9213b0ae24b7cb43ae95e25c09fead8bdbac55141694137d67eb5eab5e90a348a13d4d4d2cbc6436fc4f4f9f7334ced2 +8aed71a0d116d832a372b42a0bb92a1980f3edf8189bdbaed7cde89fc0418b3ab21a04f5c6e1d3b8edf73f1f62bd6b15 +a6c47d77d714c285c84c6b9458cbec5e3b191c0502dffd10ce049cf1ea27ddf868ef0cff13a2377289fa6c932b8e4f28 +92f45622ec02483f2c1e07075a6695416d3768c8984856f284f40734346d56cb5b3322f20c2c9f0ef8e58ddc294a309a +af6450d02b79ac9fc79f35655b58fd3619cd5d38c5317564b453f5f2d79d7a030bf767e399fe01b658a72fbd2cac2356 +a3c01fed5240eb8a61ffa8ff4a120dbcebb53b8e19845949c77fb4f9b2c3dd52c7001df6219ad2f76c785a4ee0f64a2a +af3136bfe8f774187bdf87555a1ac505322a956229a285d28bab1c88d4f4d12245af8dff35914a62e90e49f3dce6acb0 +b20e21d28444fc96737958cd951858fda324b924b4d3d08932540fd4b87150f053db6985b96903906ce83dde0578cbb2 +b7978101071268d1f485134b4dfd1e35f89b82c7d99ae91f58b6745f5e0273b7e06f3b23009033ecc3e41b2e9e85219b +9104b7d75245b784187175912cc0ad869e12f1983b98e052710fb33663224362bffd69ceed43e7d4ad7f998c0a699eb7 +a7624cd71b92699ce3fde0e747976ee04ee820032ac45dd27d769edf3b3379a4b8db358e50c9d057c63b5a9b13d76bcd +9354a76f294005de8c59db10e638ae6e8c6d6b86a699d8da93143da8478d36116211c788d8285d8e01ea6647dfcaa1aa +b85935c04cae14af9848db5339ab6420122c041075ec1549314e3c9c5a610d9b794ea3617c50ca7af6b4aec8b06bc7dd +ad6835a62311c84b30ce90e86c91c0f31c4a44bf0a1db65bf331b7cf530cca0488efaac009ab9ed14c1d487da9e88feb +80339f0245cc37a42bd14cd58d2a8d50c554364d3a8485d0520ea6d2c83db3597bf51a858b10c838bfc8b6bc35619638 +b370420ac1a011f6d8f930511b788708ccf2fe23ca7b775b65faa5f5a15c112a4667ed6496ae452baf2204e9ce0dbf09 +8ceab3dadca807a1c8de58ac5788313419c37bc89603692c7a4d96e2311b7fe9e813cc691a7e25a242828cdf98f8bbcd +ac1526ebc6bd4ac92ee1b239f915e494d0279fbd065e4cab1f1b8a1663f67daa89560f6c99bbc3e63fa845520316d2e6 +8240ab0bc36a29d43ec3059c7e6355ff39567e135f93b243145d3ada97fd1c970743819e0d58bd5171967daec144e7a1 +a99743192a6f1967511b2d3038cc73edacb7e85f84b2926d8880d932d2fa12f5215592311a7548494b68a87ec70c93eb +8ffffc31c235997e59ab33c2f79f468399eb52b776fd7968f37a73e41949111957434f2c0a27645ab34c741eb627cd1f +8949d955309415d6d2cf6ee682ccd0427565142c1bfe43b17c38de05cd7185c48549a35b67665a0380f51aef10b62a8e +9614f727a9dac8ecd22b5b81b6e14d34f516db23a1a7d81771ddaa11f516ed04d4e78b78fda5dc9c276a55372f44c4d4 +aa85d3ef157407bd8aa74032f66bc375fddaff90c612470b5ff5d93659f8c3523b2d1b6937b3cc4201c2aa339621180e +86f8fe8bf4c262dc6a04620a848e3844f5e39a2e1700c960f20ee66d4a559a90141ef4e5091d0f32acb1e915af1e0472 +b3af2eb785b00588371beb3b49536b7919a3f2175d4817de5dcbf7fcc20c512852ef0f313327fd0589b10173f77b92e0 +8388703c512eea59190351f3bd2cce83ff8bcb3c5aefc114cccf9e9b3f78200d8034c3ebe60448aaf6c912f0ff8f0cc4 +95d0dbbbf08ec1ed3975fe7dd542be0a05156a2b3db5092825d918a849411ee536ed958201f74a5513e9743674d6658d +8d1a48802f1a2db247e633ddf61d3ef7a2c062c48dda59bf858916e04f56651a7d51e367d6535964ebf3ae6d2b21b421 +971436871bfe868f25247145a55802945409b3150008535b372c949760d7949dd2fdb40d9b96ae7473bc8f6e9b83ecdb +8ca431728ac0f156763090828a7b6d860bf591e5b9dd3bb3b7f3ba0ca74191f9710ee55efd32db7d18eab5b479cee8a4 +81e28f1a506e84c2b9aba1df720cb50e0b597b2c22f98acc34e710c934cc6f97dcaf33d589e845c2c1f6d8716d05ccac +8f43b11d3f00c41d16c9bc9bc0c44227c056bd77de4f1ca9a799418c5601e744f99066bef47da2d9088ae88eb259327c +8d330aa52744c08ef98cc5599eec8b9b4dd18aa01b803f1d1ca0e29b74f1aa2886ed0224390fc377af25852851fbee03 +a06f5b203b67134c685039ec2bdbcc787353e2575ce73a415db24a517c0c31b59d1de89f12b97cbef0219fb6a1e90a20 +9269a5f49bbb8fec1a387b5d105df88a027de615d5ca6afae20fe89b11746f8d23880db78dac238c955fc8bb3de18046 +af5074b3bc0656421c314547b45b5abd3045ca1b17f5e34ba39d8c1f7928a55d4ca5ea9c2ab59a55909b25255233e04e +8e7ee5d733c8e08f3fb7d85f0628de3de6835121672c65374905dc6d19e02fa2df14c13d5e9835dacd609a4df09abd26 +a9b9aaf83d31e879dfb8e73a0708801b4dbdb5d7c8654b27d2c0f5797ebcacc8d00a82143e2060f0917c9d41f1a03de6 +904872aa1c093cb00e1c8e369a3bdae6931c5b1ed705dd3bffba243dc4f42df3e7d7cf70303d513b34d2245743d765cf +8a4d6b3b1d6afe67383c66693f70b397e510be28e3d97dbc8ec543d699b6cbb0e72eb90a7f65e83cf9f7ef50fb18b128 +a914de13916e6a0dc0e0fefecb3a443cca80d83276513b70c22c6e566a2d41acbd33a0e2836ee09abeffd3a4894e437e +b9c408f5f05934b0aefab301ba22f8254c5ebbf5405b6aa788f76e4b328c150b395f441e3566015a0deb3eca89afe9ff +8d32aa2c81b2a8b89f347c2e0b6567b2117ddbb778fda8a3f19004b7f5aa9dd814b9b3ad35f9223715d2447b2d12f159 +8230e8b9c84cada1bf14ea6aa9ecdadd978d893cf5962fee6c7167ed21239210ea491987f2c8f2e8cfea8c140704ca28 +a5d7b6285fea51c6f21d0976a7c3a97baa3d733a201bfaac0994db6c65611d91c5fc0ebc2a7724ee02b371e575573649 +a54f00a9530f6930069f5e3a8b8b1d52ee1def0aad1763e3c609ec07f25410969b43d5943a94c235ed5eb207b33a402e +a8dc6e96399b81397734c61c3a8154e55a670fa25fa5854b3c66734cbb4ec0d8f6ba650ee3c71da3773ffc9e37abf8bd +8841fbfae1af4d400d49f74495f864804f043416c09c64705251d021b3ab7881f134a00b0241e61010617d04979d747d +95acea7ff4861cc969c1d8cc8775c5eae014ad6e2e0e2d0a911dd916c34ae69f53eef779cc24ff1eac18c2b478d3ba2b +a5dce74abcfb8c68031b47364bd9baf71a91db01e45514ab6216f5eb582ef8fe9b06aaa02f17be8b93392d9b19ab9c06 +89e111169e4ae2f4016c07c574a3bdacd8d2f359561fbbdaa3474de9bc24ef8936784dfe6fe0e29a13cac85a3e622b61 +a4c511af6bdf3892939aab651828259e4ef6ebecfdd503ecc14e61001575b313a89e209cb55a77ec19a64d29ada066ef +923c62156fbf3a44926ffb5dc71f7cef602dbe941a98c61f019a27a18a50c16b6135b6099fe04a2e1dc88a6cad989fb7 +afb9191c541b61afa0ef14652e563cc5a557842ce2afea13e21507dde0ebbe6da5233af949c998c00865c79bb3d45ec8 +8a1f0ad65cb2b225931f41dc53547d756111ecbf5bc57c5ee2cc1ffd61b126d0389d311ffe26cf06eaead95af09c5ca3 +9040b20b5ac2e1a9d30abf7a4eea1ec2db8f3077cb2cfc8736b37222d8d3937f5d9f421167086dc5551e9f0bd2522d07 +b6d888b8c6bd448dccaf99c3f690d47f802e134709ce102fb6f6fc68156943c0762be6f386338163e01eed2d1dd5f734 +b94f0e27bbcda793e4a272603b3dcc739d3bf3207798df7319f8dc9d37cbd850e3724bdd30498c929debad971950223c +9769827767be9d7bacba1b687289e0794c6fe630d33c9b607da1f6a65e3f34cb8bd65327d9287c8c5f3c8b5f6d3d133e +aaac72c993aa2356c9a6a030950441de42b2d746bace29865382f0ef54835bc96958b2f00237d805ee6a69ca82117c1b +a2b1f027d80c1b0e79bfc7dd252e095b436fba23a97a1b2b16cdd39fd39a49e06a1ca9a1345c4dbb3d601ffa99f42bdc +b3fa0ad1478ca571e8aa230921f95d81aed7eca00275a51b33aadabd5cb9c530030691d1242a6ff24e2d4cfd72a47203 +a43ed4368e78daad51b9bf1a685b1e1bfe05bed7340d4a00df718133f686690c99198b60031513328fc353c6825a5f2f +965e145711ecf998b01a18843cbb8db6b91ff46f668229281d4ca52236c4d40804ebc54276e9c168d2a2bfc299bcf397 +ae18e6efc6f54c1d9230210ac859c2f19180f31d2e37a94da2983a4264dbb58ad328ab3cbc6884ce4637c8c2390f7fc1 +83a9200486d4d85f5671643b6daf3d0290b2e41520fb7ea7030e7e342d7789023da6a293a3984308b27eb55f879ad99d +b925fb6ca83479355a44abbcdf182bfac8a3c7cce6cfc7962be277ce34460eb837c561257569be3cb28023208dea80dd +9583dd991b62ae4bd5f379ccd3cec72cfae1c08137ddfbacc659a9641e7d5a82083de60005f74fc807bd2acd218d0789 +ae73bc32e9ff5926e1e06c07a3963080881b976c9875777f8e4cf96af91bf41bdbed4bd77e91253b8ec3c15b4a6d3977 +b2a3ea90aa398717ba7d8c46743e4c487b63c5abb140555d8d20e5115df2f70d3c84a2cb9a5e0536b2d93d24f271b38d +91d119d3bf1d34cd839eb69c6de998b78482ab66bc93fa97e31fb9592f36cdfcd673f52366f8c8e8877e313b92d4a2ad +a1907e20120902cf68912cc3046f8806cabbd7673e80218814cb088e080dd93b5dccba395b13e0025f5755c183276c3a +b2e2011df72504065ec4c12cbc2137b95cfcd1355509671feb7b00dbf7f8d500476a49754cb7fb9219cb5cba7c8afe01 +a48589fb7a74a3dfd782cb3503e6294a81dbb6adb412887569f9408e9079371edbd9822388e0b7ec8d3297ba270f53ef +a203909bfe196ac65ed3e6800d577b6ca5c8fe1d40f7f925a43852951e38883f2ffd250a9e16fab3ed3dc1249650247b +997ac293722a8b98f7e819f8e6c2d4c5bd1103b82d489d8b8aabeb905e95450b9b75bd61442cf68cc957212ec1c55617 +9895a3de62395c33509b153b7820bd94fd2b011f0cac135fcf916482f1eda272ecc79f83a61837e99c3a3c4ab2c5c2a2 +98c2ece4d49a64ec8e06407a0585081003bcef88af35210e22eab91169f8f0c044d611494b755e5bd915804b1d857747 +8bc6dd083b36d076ddf0e0bb1bb87cfd059283ddabb3886f02eb7e27f1f0539b2819527b56b5c13436523c4603ac1d12 +85ab8b7a696333c82dd5e179e12b2e127e67d911de609ff9a03cab95cbeedb1f364aa1f2b5e59353e4ba0d177f996151 +a9478e214afa68c395aa2c7daf8ba1627feb71ad6d8bc7339734cdcdd5a42838e032736c28e6251c808d5a4875ef0d06 +8c53f62cf06a35321c8af3871ee4459768d0745ebf48942b9f464206309f42fc7b2c50f196ae1e43b664f0e2e718a23a +8ba80662f6642d8866e832ec8082a4204ebc993fc304c4b794666856de0407620131a18dc053597bb40a3de0bf8aca22 +8c8fac6b911785d1561a985580c03fb2ebc613ae33e486a92638aa7d4493374118d9a6d9d99121e29c68c3d67ee4e3f3 +90f2c793eee07ad90157040b30558bb3b0164e8ddf856389d6742cf5bd1c712e4c6a8e5678da70a8e9e242ec7864117e +954abed8f6d58896b7f6438c9780236c1c83b02d60a29fa7361559e619e5bc9d67b3646ee39ffafe2b3019bb3357fb50 +b79874f757a33085e1e751544de8fe3afbea92e0234f9c00254c2b36115a16ee46f085f22aa66e0c9177e5106f51b03b +aa148b287cf4f60c64f774282b421aae075f0eaa93a45aab4927750f47e2ef0b811d1846bbb15eeb2f293c80a7612e83 +a588d8825e7b0168d45499dcff6faf0dfe1ba4f090fdc7c06d50344960c0121f10ad109b0b9d13b06ef22de5a04eef87 +8f61ec93d14ebfa9c31731f9ef0fb8907505fedc79378e9a3f65c27bed4d74b41e129c97672ce5f567d897befbceec8c +a008218633f1da10efd01c155f7ed739faec902da6dc48e9f19ccbc8d32bb318d71806285cf2003de2c907bbdd4f8b22 +88ad82c66f7085632d7e348d69da84200c53594553acf5432b50dd1e87f410c802dfea91be3cf804e3117ce13103f23e +8498dba17de0318af227a3f9ed86df37a5c33f9a538be9823f8dce4efc3579e8296cb3b7200cee7c5e0bfd9da23a4b69 +b3c0342231dffe4c9bc7d9265597bc8cc4a82e2980ac6d1407108db5b00349dc91d5116fab51cf2802d58f05f653861d +b3f2730455f9bf5a058598bc60f47740117ba51f6a767e1134516a4e42338b513f377027acf8825da5c4d047a62984fd +816360914fbc9d8b865157bfab07aeb7b90bb5a7c5cd64847b1c3184a52266cd3f8f8f3ef99309ba2edc4622304bacc0 +8fd21b2315b44a52d60b39ebc45970a47b9495f42b88217ae057bebcd3ea0e2476c0c3d13de7f72016ae12ae966a008d +b62014485bc217a0fe892ef1aef0e59604ad5a868face7a93f77a70ba3d7413443fbe7a44552a784d8eae1acb1d1c52b +a905822507e431b35f56724f6c8d2e93b0607ed7a4533073a99cce2b7c1c35367382447073a53036dfdb0d04978ccf2a +81672e39c2b31845142963351de3d9cd04c67c806fdfe77467867463dbbd8a9b0e2400ccc55016e57cbedb02d83a0544 +90919c970ec668de8ec48a2a73bb75cb94f0f8380c79a7909fd8084df61ecd631476ddd474b27103c6817c8f3f260db9 +8fbe37dfb04bf1d3029f8070fd988fc5e4b585e61eab6a8b66caf0ffef979d3ed6a662cd99468ce98ec802e985da5fad +950939aabb90b57a3d667f9820880eb0c4fee5c27fe211ce8ecd34663c21b5543c810b3676111d079ac98644c75ee0ae +b06201ec3c3cfdaf864a66af128effee8ec42d25f1e173c1edf9207979fa52c871757000c591d71a9b6cde40f5001a06 +a79054e8febd0450c96ac7a5fd6bf419c4b17a5926f3bc23a8616f0cfbc2849d97470174cd1baa7c739b12615334b6b7 +81c7391b2a1844ed26a84f054b5f03865b442b7a8d614cd44805b5705fe6a356ac182b66a3c8d415132e389efac5f6b2 +825af1563d0fe53925ec9ac0df65d8211b333474e59359bf1bde8861eecd03f2ac74534d34b7e61031227c2fa7a74e1e +b60dd9bf036f1825295cd2014ef1f6d520cf729b4d6cee0b42cb871b60ae539b27c83aa3f96ee3d490ec27ce7e915115 +89ca43d5b7f3622b42df7887572297a7f52d5204d85e2e1ac6e5d7aa7f8aaea5e3a07280477d910db025d17cd2e7373b +b93a2bc9b1b597f0e514fde76ce5bfb6e61eee39cbf1971ea6db38c3ecb055e7913ec8cd07fb0b0ffae3ca345883101c +8d45546bc30266b20c6c59fc4339eb633155aa58f115a8f976d13789eaae20a95b064fedead247c46665cc13ba856663 +aa8eacfe00e8a4d9815de3f7619d9c420629ada6489933ca66a571bf6c044d08b391e0d9eec7d1cbebe8def1e7523f1e +b32fefc59a0d0319ccb1946b351ed70445d78d9fbb536fa710d3162b9659f10288f12d82b32ecc026d55f16cbad55441 +99c7c45c34044c056b24e8f57123ba5e2c2c039e9f038a66899362840cffe021733e078866a8708504cdc35816cb335d +80def162c134540d5ec071b25ccc3eef4efe158be453af41a310b7916c49ec0ce06bb43dfee96b6d77339e11587de448 +b5f2fa4f68f6a26bcb70d8eab62ad73509c08ee7aa622a14b3d16973ffff508ce6f1aff9ced77b8dcfef7319245cf2de +b4d0436019e779c789464716e1741c189e8945dab7f3072720bd9aa89882fa5b085a1755c48da21541f3cd70a41b0a71 +931e798ef672e1472f4f84c727a101e70d77b3a9f0c0803a5220958d6bbeb8aeeb56c769ab472a3d6451249a13a3f56e +918c10a84de268aa8f1ba24b38fe55ff907be07b1e86b4a4adbf305c0d705c1cf5f65ce99e03e11676cedc89f1a4f331 +8e55a8413b823715ccd92daee357cedd797e69a0e78b6fcdacb7318646b9903dfe05e5501f47b3c52e74055b9eb619a4 +8b329bb63e6c985d7d072dff4680b3f8b1217ed20543277386bd30ec25240d9dc378837dcd5cf4fd9548658635f4c537 +8c2be5386052b22986b33dbc63c5afacb6d0095495564ba4aa28fc8c880a3c78242fb083248d788ed928deb1e30a82c2 +83a2b7bdfcbd25d6b059f27218e009ecb5ecc4da68ead885e00216411d8222062ca42f21c4d9cfa19c31522080af677b +9620334d2633e85646b2e2fc48dc6c3f09c64ef1706ed78a3bb6ce1f6b274a727364df71e97531dfdcb392f70f27f536 +b6c84970ec04545121ec3b79376f4e45053c97e8bf2b11922cc2490a429c38735466097ecb81cc9d9692c74d2fb8abc8 +8e55d707dcf265c5ae29a32c27ce66f200fddb724faa5bbf145ef42280ef645fa2f0cc3cfe2db8599b26c83b91e077df +b910b96b763966402bbebd68a32c15a225ec21e1357fa298478c5981a4310e556103fef0c73bd8903e11c4ed2c065647 +a8fd933a0e9fe8c459809bd93b8ce153e2af55df94b61a1490736b19c89469954da8b72dbd072d798fc06fc3d7a3d60a +811b279c113828e114fd82c2070caa7eb089a46c8cabf865f9c77354a77ebebe0c4c6400dda0e66dd017cfc44d76851d +8ed03e91c331afb3ad6e42767e1b3e8d3a35fb831805ff1b5fd3e91878e04027ff5af1165a3ac295f1578faf2c83b581 +95bf53683d64a0621bf1ca6ee17446783f6c535b7a54d6ea57723487a215759a54f886597a55dfdd560424e368ab2759 +a9bea378768fb1d7ba365a16531c51fc1975f1c73caf2a0891da28509805fa84e2a8db7c6ccfbc620e9002317abf174c +b8308250891015deaf851c4e5a4cf4704d104f94064418488d7e3076d49f36240dcf6fdcf83f45fe8a1d97fb02e3db59 +adcda6b63da21f4074f142f8e7f3a2274f624c733e3a4001054a1809711529c61356aa087f73aed877a58ccb41d38d12 +b80e7869239ae26d1da2e6683f064d1dc93cf4a2b66e9439b3ad9b25324e969bf98014760d29e6b8de7ff152ef498d0f +8e9bf968911df3bb5e3a7655e9d8143e91ee87f14464d7ba9c86e1e31b03ab31b91eda121281b79cd974d9ed2657e33e +9007277e8335a43e6bc3c2f5f98c0ba7024a679b7156aeefe964f1a962e5ac82154ac39d1ffbad85a8f2440f3c1e354b +9422b9d670e997b7c919a429499f38e863c69c6a4d2bb28d85e36ae0895c620f68b71e39eba785e3d39a45be91507757 +926094e01132938000d82dd9a571fef5ef104cd25b4015a25e3442af0329e585aaad5472f0e7a69899ba2d6f734b40aa +95552d8057f7e32c24d69e4d6c51c98403f198a20c5be8826254d19cab2f84d5758e2220cea7e38b7c8a7a23178fd564 +8abcf8dcc8488bcc9ab23c51b9e7a0d91dfc7bebe88b7ed370ee68eceba643e939c5eae66a4aa5fe85120751780e351c +a91bf8198f029e6a4cf6f0cc39b629e9aeff1c77b8739e1d5c73d8c1d3fb5c8f6f23e27b435bf10b5b4ec1cf6a7249ed +b932d87ee3a4b81341511f90fe5aa36c571e8b914f25abcc33dd40ca67a3f6444fe9362c1434744e4af18d6e045c54a3 +a8e960c2be9b1d805d387b3ebe2134d421a65f1fd4c1b4cccdce78f9926f139eea78e3afb449b3d6dd19b5d16ace48fe +a7e2f57cce509fe66707eaba9b4c042c1be93fd6034a9b51d1d30c45c4363eac79d54663d525c9873ab0eec0b1cc4ed3 +aa162a31c2078f4b080199debf24494a8dfdfb9d8fc85b198a861b12a629c73128c55a883e4c2de3dfed6e0e1b83eeab +b5a4d075433eaf4115717a84b4dc37f843d44bba0bf820c92ecdedd5afb61be60f7708c8a151a678d9d5c0ae531bffb7 +b56ab96f7a463c0079e05dc766f3a6a31cae5c5044947734ebe0a26e01367c6763cc8de6c2ee2f3b8218f05bef217474 +b60792ac506b901065a8bc0180a86e028fe34b62ceae1ad640c759538ebf3a2ad9c8c927d662deed6f489ff3ff7813c4 +8c8c2cdf075504d12d441a58542e1f8e4bdf92b3ee4775e836b2734c5ec1e3df919b931386417d04489a1dca806c87d2 +8ed78e91e5c4a68894cefc2f7fa71f02e5e12d40f1bb74332139bc7be4d92c24e07d5ece0e82150ed474aa1337af4c18 +87119c22ff8aa31150bde537d863cad661cc5159b12f084cc319224c533f0deb28526ed8568d00a1441e7d8bb4f05673 +83a60ba5a9cccf22cebadf7318b706c9f29abd25db0e2fc1c802965351b53cbf316df72ee3e9b2d3ae7f3c4494cfdff1 +b73b6a9fdd3e7463fbdaabc9a885b7c82201ad867d1bced1c2484300a01cbbb3f1e21afa95d4c7cbb6cb983416b63b90 +b1d89ad16981ff9217708090d4017662d8838f21f3a3296cffe14590b533905fa06a20e40dd497bd291fa4dfd1bfc511 +8abde560083e071a402e3c7bf31930f537f67d2a7bbc734a7480b1b760aa712ebd1cbcb65b00e11e384e980222fe14a9 +89c731d8f31afea8bdc9c32527bdca257f2a840764d40f6e49403b8e75ae51017d505ea4fff91bf28b6f3a1bc65b8bbc +80e9ac8e077e86ad050ee73dfce268a69564ff1b8419e9c236d981fe7a5f0c2bc756e8603ec604b3b9e36da8fe10a49c +b4f1eea0f304898b1323c6382732e6f40e556bfc68af9ce73f6d54e92f5f23cc4f78eb3f43d578d81e7627fb40f092b3 +a0e3a8d1348f8f153e08ac4839232d75d1d6e81b5de184ec4724f8213baf98d3fe739a96f6b39d79a053b628c3a09981 +a6915ba0b52ffe4a381bbb8ff3791d9d3b848bf89b3bacbb2a7d2e5ae21f1353cdc304b3cb6e82416f7e604035c27d7e +b2c4c9cdfdd2fc9a340ba3ade9423344b9f429e8c7e20a8abbf26400376e312f3ae35d1c456be99dfb5c02fc8a36cbfa +9657d57ca0641825a0aa5687f3f87659d893f33aee819bafa5b1ca1db554811c1c844f971e278606e3a2f096defdc67c +a4ad24d0a557704ada24d8e27a15604bca28679e260b2c69ccc8e6cae5499866724b700605a90df7dfb35130756939b9 +b18d9ea6682f73a1f99a9a4fc98c38fcda02c1a18e8c5fc080cf935a2ac877dc5223fca273dcde190b906178d0fd05bc +8ea5fefad0799c885f50ff10d94bd0af5b99b0a446cd1f367ae5ff529cc47e09f3018115f3c0ccac2fa05bb65b84945e +92450d52e6c7d13ebfcdf5674d6761bbae2fc5aabc865d35d031b588c383e0a64cf69a73dc93948632e2b98f74a5ed86 +a356f171a98df4ec5a96d556eaccc6ad34b4238aafcf0e94ece27cdbb491749fc9692e78b84dfe80bdef2914079d34b5 +b918703a4d3507d266414712ba8eb7ad17da07cc5f952b5c62ef130cc6ed1ae3bf01237fc8848c179725bdddd465b301 +ad2b0554570bfc9d97510cf59bc38e10ca54a93649c30ac9919bd0255e43bf525ab11b74f78a51ac0973cd0c5a5dcb54 +a7ecaf4b631d179d32ac1632390d95196a0035e00da6c0e6e13b5c09ae44b15ae6c21538b5a31b73bc5f650ecd979b59 +a37704eb4d728df2a367e59fcb6c26023136230e37f3b8a2f3ceeb1467f5cd30186fc0116f98b64a8146fd2c5903e8d9 +b09373ce92314678299ae10ec1f93c702911beb4115c6b5ba6efbcab9c7afb599f59793912df70a98868bce6545a33dd +b52a878a1393094fd2b93f2d1eccabf2830ab10800ba4cc24dcc7849cd0978733263aef2fcb766a7cb575a7a99383db8 +8dac097e006fda4fb9d6d7ae52adabd9448ebc8d5bd5b38ac0c4ed38ceb510763174f7adfb0b473c38e52147ccab4239 +86b19c41efb949937d74a7875549ee5e997f9fdac7f7198085afda233cf74341a38d0ca3767c76cd35f875b89a35f78c +99f0d927e5ad25cd134f1c70b72631cc6b5cb4ddb86c0642b900464e33d971213a5239dddaf71f7a42f2d6d02a12dcc6 +8355c38806c335d747d4e97f0083fb96585677da18b409a85175ec35dc3f74671817b34203eb18c2f729717ce083ede8 +abb3603adb061a036eae0afa5f23d79c3b62442e0e3bcdeef896f88995585c1105cd3065410368456a4d36b5b0485a83 +9051c5c0011784885187d04749f774b9b4f6bc594b0e4e18226de79dedc4d7aefa3529c3d2c728e180f96f3e204d578b +91888213e7d321d0bfac884edbd5cb756b280753bb5f8bc6acfc208f525757beca24bdf86fc68d3d8736ef176a960b49 +91258bd7ce6e3b7516fe2f5391a368d826da299e0e99b1f82eaa44b62b110ab696adc92debab8ba098a52f38dfb3c5d8 +96e3907340dffa9da3602d3b94bacff7e1bb8649edd3b9bbd06e1bc6781e78f91ababab12c0b9be7c66dfedc7001b66e +9513555688fcfb12ba63952ab36a67b36affdd71f7b843e8eb99ccbd45421698024608233efbdc905eaeb26b334b33af +9913ca9bcf11eeb408da02e4317c5ca0010fb2f4490b282ddb758001c08b438c3b35351a8cbe10b7fffc1293ccd22d4b +85dc2471860ebca88e5a2766161fdd77f926d2a34825d1134a30418f91a741759668e32fd1e37c415d07ab5824338e8a +8b128917e828a0b5eb6fa8ed72b52fae2dfaf74febee69a2e2f87e8df702f0c5bc0fb620c8d1d2a07f35a15ec9c0f5a8 +964c39e7840c130b01bb481ae7bfc92682b0f124c9c383f9dbf3027f2249151925f4faf36905af476a54778d69da3f48 +80671ece658cf850e522d46d25678f934ce6df043f25f8707235125765d40c2eaaf39eda6092f75039b22cb58bf2c29d +ad4bb0e79fdaa340b1347a46b0f64e801c72a89770dda0a6e4bfd35f2df5146fce9934e4baecb1c2671077c771eb8089 +80b3bd3adc6cf198fcd997f8867d2839a2eb28f57390352ec423b8a14cc1f2ab21c6e286505d6a21fb134dcd8d8f11cf +a26d46a6b8a75748895a1d599e7fd120d896340e79813167a400b2fe463452532a4cab419074663fe1d29fa716b76a33 +82b1f3a8a1df29207d7ff020809113ab06080a7f0c631f76ad33f47cdfb6a567143144df97b4ed7f676d929195b04bba +ad96633a3744648ff0a2e4491e8219c9c6ba6e655cb058c36320a8f72cd5f72c00bddf97083d07650ea9ddc005fc1ff4 +91d0783788626c91662359dc3ff36a8bcc6831e3f4114f85c99910256b1d8f88a8612f53c7c417d55581dea486f38926 +84edd9e87ff3d193ebb25f43474c33fe502a1e2100fd3f93fda6520f5e42214cc12e9f8045f99aa2423a0ee35e671854 +b55e06a4b1fc3ff9a5520e0b7c8b5ac11b28385cce78d91ce93b82f1bd7f7afdd4195d0c13a76e80d0ed5a4f12325fa7 +b0b15c7ddede2b81d9c835ecaa887650622e75d0d85f81b8bbec7ef24e9a31a9c9e3de1f382d8c76d878d1b01373f6c8 +b1adb47c20f29784116b80f3670182d01b17612d5d91bd6502b0dcecdcf072541f582aafc5e7dd9a765cad52151684f4 +8efd1018df9c9e9814a9c48f68c168551b999914a6719229f0c5bf0f20a288a2f5ba4a48ba966c5bffb0fbd346a4fcc6 +b34ea2bd3269a4ddb2fbf2514401d2712fc46c22642f3557e3b9c7acbce9b454dcf789573ede9aa14f39605fdd03f8c4 +a9e1428ce24eacfc460aec2e787c053327ba612f50d93510d58b2cb0f13291ca3d16358325ab3e86693fe686e4f526f7 +91eac7361af4c66f725c153da665a3c55aca9ae73ead84ca2662cf736fe6a348a301be1954723206dda4a2120202954b +a6f02db89739c686407825fa7e84000ceedb9bd943e8a0908fef6f0d35dbc33c336072ba65e33e15ecfcd5714d01c2f0 +a25666faa12e843a80365c0fef7d328a480c6e3cb7f224763c11d8cbabd0e7e91a5b647585ee905cc036afca14842bae +b4348576439cd2e48c01cb9cded7cc4a0ea364ab936dd679ddc7d58b48807e7fab070f2f1ea88595b11af4500849026a +a8c6c731e0d0464ef7e4fc1b049065eb4ce100c01e1a376365c636a0b23851022bf55805963bc15eb57434a837e81167 +b0952937b154e3a4c206f96cd96c76ba37624956b0e4d43470bdd97b4af878326b589e3eaee82fc192437123096799a2 +97d07ec31ecc9923192e48d37df2cf08750050fb452dcfbdb350fbc43e146bae3590c5b732b31ebfa1ce5d884ad5ad57 +a69359aebbfe4cbc4d39d178150039fbf284cbc0edc68a6bd635ee3a1c76569a4a575c907fff691b2a4d82a384c2945f +b321c2c0f6b5902ee9056cce7404d858da9a573d27348c1a6bfea29b2746f2aee7abcb6192504e5a583b0caeaba117d7 +a74e738aa6eb4eea58855ae6f422af22812fb388c83aacca5bd5fa4a88d4c01463174a229aea2830c348dd9ab9307854 +94306a3b106bc1644346bc45c05cdc8287811d5c86cad691bde0c65d6a686eb9c0ce79ad91baa4547e5d058ae8bf7310 +b64140fd77a07633e4ca8d60786452311dcdb8ce7095ba51dad8486f57c3bf4e69bced92603f71da992a48ad817ab275 +affe7f4310f1dc68e5e3cd640bedf864f51bfb46bb752063bfc18e95930021f784e509261ff9c560f53000c361b142d1 +b0d2fee222c6f963ba3385547f921a48964da031d737892604f8f2677d4905dbf615046db57eae6c6dd756709ae6932a +81700c66aad7c2e51168e028b0fe086dea75d3b17d93a4dc1f47a6a0f025df0bae1c8c997901837ad859a84197e7bb00 +aa4ac5fdd602f8b79cace18690e67bad557a93d00c0e295074185e8c6b4059a65495d9971685de2fc01d2171ac8b706a +a8becb3a64fdf35d65d2857898dcf8053b5057a73ab8c5bb5324af1a8015cff47efb85dc3eae7364cd5c850b7962bedf +b72ea09bd0b72f8cde3466f359ea69b194ede93dced534efba1b9ebc6f3bd53942fe2965e992e82edb6050cac4ed88dd +85bb8dd7eef023a251fb6f220af54687747f4c91983ff728163c4618ffac40ee6edc29a0aa6d455276bbe017f63757c2 +85a485254a11b4c4a943d9ec509c0dd1cbfc0ff5273a00cf5c9f0babec973efb15348e5d9451b548293d778e3a2b62a5 +b109f3ac809391e772b589c196b013db69a9b2b10ac3898feb70b986973731f30722b573cd0c9324158ec20416825385 +8a4eb579a840d438bed008644f373ea9ba2f28470d50cf1d70af38ba0e17326c948527b1719dd1bd9ac656ebd5aedd10 +a52e9d66ead5ee1e02ce6108e4ded790d8ec83164a0fa275ab1f89a32200726c8e988d66df131df9e62dd80203c13dce +b541cee9febf15d252475507e11d65c4b7819c26cf6d90352f5e8a8f5c63e254eddf22df0c35a7be5b244233e8e4ee5e +8153c297772adf4603c39349142f98cc15baeccaeae10c3230ee87d62255f6814d88d6ed208c368d2c02332426589748 +970dc9782f1828474e9fab7dcdec19aa106725465a5844caed948eef5c9e48199c1b6bc1a637ed7864116927e84bc65a +a975a920624967f4ecc77ea5d9869c434caa64c330024194615a8d0640c5d4d4fb139ea11a0c73a5c6ae6dd3fbf0ab5d +811f0f9e0c12acfb4b9dca359eaef3bed18083bad96188befc036ad3143b121fff4777ca6dc70a835bbc4921bd25f5ff +82341c6ebdb97c8b72910da95c7eebccd1308b6a92999886aab552f0642882d5c7cc60931577d200efd6066530c998dd +860f7162c2f5fd1c0953c6ce75bd8c52eaa48032b914410681b8cc05e00b64130d1f96ec5a52df66a04c78a9f9f42981 +8a578e674875571fe1a0459843495a5ee1d9fb6cd684b244feb9488f999a46f43363938cd0542879ea18ed14fba10a6e +8df217aba4da6781f0f5139aced472025523ed6e17e504511c04b677ca8197488e237d8bb5dff7b6b3898cd5a6393dd5 +b2c9230ad35d7b471d3aee6f771517cf3145ad26200bd6fe9c7cf28120e2945fed402e212d2330a692f97bb9ac4dcf12 +b78b89e29e8b782603b222cc8724eeb83b2d9d56bc02f59a3c899ab76429dc721358b07dcdaf422f59520b7e7ab4fb55 +82682a5617843c4ac8d4efb4c3ce715c76c1da2c3bab1ede387db503f3489c1bfdfc07d9231d96f955df84fd225bc81b +b0f53725cc610e78b8e8a4e6823a2ffe44dd15a9a5bc8151ab7a3787ddd97e1d7f2f0e6efd2876e5f96417157143e3bf +92c5a93233085e2b244519078770c7192af62f3562113abc8902f9d72591eacf52bd15ce78653ab9170d5067606287f8 +a43ef97dcd9b6ad288846bf31fccf78df72f94bc7ad768baf5bf0d5dfa27bd74ffcc6b6c6ed1d1f09e09be3afa5eaedf +817d43bd684a261fb30f709f7926cc4e1a31fd3a1a5e7e53ba4d664856827b340d7867e23d55617ab3514c8a26a7040d +a599e22d3286b32fafaaf79bd5b0c5b72f6bf266ec68948478f055391336d756b58f9afea0167b961fd94234989f0f02 +b70db7d8e8356df2e2070f8d658e560081442f3f3b95e20f4bf30106835d76161101163659d5d12cc0f335fb042dc66e +b8f725b70c957aa3cd6b4bef0d9647393f7c9e0b7343e92439372f0e9aa3ceddd0cb9c30be331742b87c53f2eb030593 +b2fb5e7762f26036e7e966f4454f886758804d1f4c2da17f3d13b0b67ca337f1fd89fd3cc798b07da6e05e8582c9537b +a377f944dccc300921e238ed67989872338137fe57f04cb5a913c787842e08b8a1adcfb4d2200abdc911fc1c766a7092 +b82e98a606071c2a33f2ad44e7ace6d9471d5434500de8307b5d4e0083e3a5cbc67f0609ca8055f0ea0ee7501b9ed916 +8e58f9a04d33a41ace4944615041662dc35057e645f63e127cf0d70f96ac307d33a62ce98f164d6eed8536c1a747dcbe +b5b11388071ffbf57ac47fc195736613b964ebb91cc8e2c17b32646f91d64ea506282b881897fca96c317364d3290de2 +a40ee9b7551133856cfb3904837f9949a9558e59a418898affb78adf1500fd6ef6328fc4422161909aea2c79ad08c14b +81f9eb4ef28aacdb43e11dfc9aa92ba990be4d3c14b484fa677edad3a3fbfeaa859a7f9322b5e95818240d7326215abf +84939b2b6bc859437d1a7a8d6ec9a357c6b716c4b4cc22abc274af872655940cfc72c99f5d0283d90e05191fcdb1c232 +b78a5b74a90a805410b6225fb9576d6d73752520f25cc3fd1edf8ea9f6559d3080f9acaa2246809b6a66879cd2ae446b +8d0a92baa88bf38dce5385ccf15d345b28e2e5d0a2d469e689353d80eaed8e8408933816d70ad752f226c59a0d5b5f0c +a7e15f8a8c1655b7b346c9488cff278c793505379b781b31b273b4bf09b3bdfca1c8ab2334746075d636b2e05859f215 +b70daf14f2adce03c7b92d6aa181f0c507a80a37493d8dd12419d5ed5f943a98099fefb46ac827d6e4efb9b8233c99d6 +8c2480814661744d116fba7355bc6b1914975e44cf0e976d50b6a20092bb1c636b7b44ed3fe8d63b5555ffc89fa759d6 +a6059528a4fed36abb74ab992b22a4f9bf1d05c5de2bfe6837b9af1adfed98bc37ed7481b5a99675d432743021fcfdb3 +b7e19f1b25bc159e5a769811e773c3a8ffe8be8ac77ed0b711540915e5c6e7bafdb407cf9b85c551f67fd621ce8142a5 +a2f66d4f7d16ed3e7ef5fc90b42676c61a98ff18bd26ccce91de03b6a0130c1db17a6bc57be135e410a76d2255b15813 +a139c916927dc3d3fb83598da9217ca64f0ae127215332e9a7ed82be923b89a801c44580d5617297175f9dafb1c4eaf3 +af08e1e1b04ec95366a12d99c80a9a9ac40ac984a575dd0230cdf4eb346a7686da55ef0a276f3356f814af31f9cbf1aa +98840aefe287369221c0721cd7c1b15b1d670c3cbbfda191cdb5434bcad757e59c30ec82b2d8c75947405888d44da435 +b7c61c8d42daf2e278a12d8f6eed76090b71c82275f8b33504aba75d95103840e8acd083e97a5a5aa79897876a68940d +a0264048d2a2061d32eee4f661957ff351e78436bf49ef973c059612874ce9c91970869d011dc13a5b7c754476880a68 +897199a4d8db8aa2db5d9be3d4f4312e41fa0739eb06c62e2e046c4b9be829a447e5d47227e2d96195d3b7b66eb59da6 +b512a9082881f5dc90b02f8bc4f38b133348c2e933813852f6a8e7d8c270c9ce68a5524af7d1d3123e53b2d02a53d465 +80b332469254a96f53c95ec79bb5a8bb1c387d40e58b73d72f84384c696ba0d3c81d6ac90be2979c364c44294e90432e +ab680c2e547ea5cbf95bf813020beb461d50ee4341dea944eb48f6a8584d35682d20186e3b190b849a1ba25625a7f499 +9070581993a0531d6be372d370c2e4ab2ee53f30e04a75ae61ea0fc2c320914506c4d2d4b4487c1f8fa88356fc45c895 +8424303dad6b4051ab633ad27ee51783b2ead61c5a6dae1eb3ed72fc1f36e2a9b1f315504a4bd90f9664091f2f403d4c +82225611eee626556553b9316dab4043aff241a81826a33aebd9864a91e299b765ba1fb43eea2c2047e6b75b6d7fe3de +8a3fb221c616ad55c352dd5e0c09ee892022013d6965aef40d4f277a42e9fa01226fe973cb99aaf6ffe4f4f348fb54d1 +b07c07679aa51713e8a7d7bc304dc15ed5664b66bd371877023f3b110b3927e09e259ef22895c4001421a69c6c013cc6 +83556c76bdac0dd8db6da231b863c335be076e7299802eebc259e0818c369f933a4a4b18e2df8ca07e82f60767b462e0 +a516f659b7915d2f7cd0f0f5ea2491b15f0c84dcb191e7671b28adf7cf14a56d42cfc0da94b3c269b45c535f6eeded49 +80d7cc6f26066f753041b17ff1bd27f6d4b5603a43729d33d596e21a67356db84ca9710158089def425f6afaf3207f9e +b802a47f9009dbd48851209ea1e2739020e717f0ae80671d9f97a0e43de923273f66b7fcc136a064c8467372a5b02d28 +ac92fec1864a8a911633f377df87aab56713876316d48240fefeee49ab97f7406c22e70f4938b5912c5c4e766146b7a5 +89224225b9835d04428b0a74edbff53dee2be285ddd1e5a3a8c37307c0500578155f0c4052e4bc8be04c56862fac099d +b1d3c8492fbf22ea60732745edd3b0163ba5a20d1a3315e3773f2540ee38cf308d42ec72cbb3e3dcea457d1d132c3904 +8bd00e38ec30ee6c44a0e5b222f1f737c9ed2a4bb9225f1741d6334df966318c8a0fd2fbb109557fe8c9479694b8d8dc +a930ce5454efc0b247dc148aff869963fc5c240241d5590415cbd36634801a04d3873d93635911bb9c0c42ecb005cc63 +b83d4f80e9e0fa47b42175df74935ba8aad2e559b80e84478ab1685bc3eb65d51b93e5738d5ca968cc055ca0c552a03c +b3ae21258f98051f13af3878b8103bc541fe6f20b1c3f8fb4689ddb8800b3c25cca9b55f0a4104bdf15dc4d5844abb8c +831ef8684c1cd446c58c59d0152aeade5cc305bca6aa296b92162615f052ba280fe289edd62fda6d9f0667c186445f52 +97bf9659b14f133885916733b7d4ac7e215495953caba970fa259f7bf6b79e661090ec8d79e1c9ce8dfb17e8552f93af +84d5a89cc2332baaaf3d19627a65f4b107f8dd9228a1434b327732f59883bb54fb8ce60d6acd026ed4b0e94e545d1c33 +8e66cb743f95ca5486400b0d89d02e20b98044be1e3a12983ff9fe086179e5a0ebf4dcd5098703191552e9aa660a6de5 +87b4cfb35bacec805f8148786788db84eb8f4bcecdd0570ecb592c705450ce1a90b6d183d37ef58780ede3995be67497 +a72a4fece5478011973afa543f6d8a8ea06a64b241cf7d8bd81fa3740ac2a4cf10e5120abcc1c1101f94da89507a40ca +89dc6001a96adcd2679916f43dd19ea00508c8d5dd6b0090eab7982fd2f3571b62f3029588a0649e73f49124525407ea +8ca75edf1259599e873530eff6151c822a4018e71a340534219ef8641cb6683215891df41d4e3c0ca2560e57a7aa913e +9282d32f868e5ee6f7fc229dda5b94b603476de30cec0a44a30edf396b52dc0ebd472b8f726d4b67d76179fecc1666a1 +afa24704223707db89690bcf9761f07a093f6009ca9fc945e0a8801fc29f9f51292bf95243e466fe736088af36c55ca6 +b51332508ddd9a2610edd2b0ad120272ca342e96c28baae37a2c4f07e689303a46c237712d07e446b1d67c75aa8ce32f +9219249f3799dfa4eb4770ee323f821e559e7406bb11b1f1889286221b22c8b40ccacbd9ac50ea3fa9ed754860bc24f0 +993515270c128ede64fe6f06755259105d0ec74947b7eb05924a375fa5c6d14822f3d7d41dd04fa5df8aa2aa205a1dec +a83be4c2511bae430034ab15b194ac719d7b7041f9c0e321317f513a97db39e97b9ee1df92a1962f265b7a3e98cdd753 +8ac7feaecd26f7b99fda3ed0b8a08bd6dd33ed5ba687c913ec0ffc64bbbefcda6f265072add4d944f2005634601ce68b +b4e3ac6b09299db9e1a469f3a0b2d8d724ee47a417a517bebc4c2ac3efc5cde086b57b9aa4efccdef2bcf8f456d973f6 +9262a24a84fb7b2a84d700f98dcf3fefab8b47293778c20bfc356860cb84e0bf102bae9facd9986d92d1762e0a955836 +97be2041c42bd25e5eb519279163b0857f8bef627492c27b1182f8bf0033769246be5886422cbd2409c08a2615352465 +b0b87d059a00e3effa2e5e4925da913b245785f2932ac3ed364ad19a064d3561b8aa6afea22c951316074f0df179af36 +891644b7b3321b06a2a40cd96c2b8b29d81cde5b48546483fdda439000982a9cbf1f6333fb6c089d39da6492cdfaefe9 +8da9149b7f4783a24240b7b9c7e6df4abf8d699d3834e31ee591489bf4744141ab199c173db64397c1f9bd5f9c862ca1 +8ad7f9fb2742654aa2964fd468e7645436cefd1308b064fd63fdf0d3adb4caf6cfe5426354f6cc284f208b03d6b2d918 +8435e4668f7aeb027100d21e4e0b6ee22b401d21966a3736b95610de86c7e2f2c9ee5d0f901353675eee5ff458dad69e +9010895f045538bd11b47bb8996f27198c8d6cffd3220569e6b7407f68f35c47d1efdbcecbf9b5e241c3c2879a4f6936 +92a9aa443b5ee7bf13b6f43f2d8d8db7f6f33fd4073a606ec5772421a55f464831419726130dd97829a7d4bfeb1ab078 +843f3266560be6dcbe0258c3c7d7e332330e10630c069892954290288eda301e247f479505a8a1bf7e59c99ccafd104f +915bd1dad808f8a568725bd243f80b5476a2999d0ef60ea3ef6e754155bc4121b2b879d01570725b510c5a3f09cd83ef +97250d781815b1825be192714884630e9f564b9bd737d55b8ac79ab48d0fb3ca53bd21ead7b2fa82a05f24083f25645d +81e2d52333391ff2faab39611689a62d6ead77039e8703f4e012d53eea17a4d46f2e3342e44b6edbe73a542b461bda45 +89c9f9fd5f638156b018831c1bb70c91215f4a2f5a73c84b1208bdf6ad652a55df7213336ce12bd910a0e1a726474f95 +92bd02984d090ea7e2f3eb7d36d1e7b9d731b6b047e3cdd4af7cc4ee177415fea7a145205e484b366d84191f06af85c9 +85a86fc61d5d916ccbb219db52953e1495230aaaca63237e9165276405f07ad9644e253ae394f1ccdd231944e7143313 +a2ca5b3fbc9f3530f88c0ed7071ec3d89b272174c366eedb5d15d2b648c65d23c0faa4e92c776357e7c6883a0084d03c +ad171f5badcc99c8ffc9d8b707d792046f86cd0aa478e0e2fbb32fe095f96cd134ca548d1f7713057694dc6b26465315 +96bd15d57da9980870fbadc98c68db76824407dff2700c45b859bb70d98374d4a4ba99e3ed0b0c17f480fe08f16c6b8a +8300bac69ca088c3ff35749b437215e9e35a16393e9dc094f520516ba57a485def7029d30adfc72bca36eeb285c19301 +8a09e20be64f346668fcc7b07fee9c0ea8094c935cbf4f3a4cdbb613d4b936c1edb9256b7c884efb72393d97c0da00e1 +b1f85827ee6f041f93ab174d847a55710824fa131c9ade9561168c3962a25c617475ebc4105eba6e738961a754442bc8 +a131558f92e215969f41b6a57d1e2f424149eea531723821dd4cf8c54325cbe66b002de2c8287de6b41ab4b5c35f060a +81ba492b8956f73557f361a856c6c884ebb300d828287d5699e22e0cfa75c8e77a61616551d0be5178263898c461d6f7 +b2608f44d3c22fac8e13cb59e4ade8b9a98c4eb1ec0959ea400c97eb937ae3f66837e91917057148befade8389af2f6a +a6ff0323b5a18a4becb2cc6b376086b47cb2baffbfd1b0f2229ef2286fb4a34c5cd83a5faed5def7bbad519fcab8a856 +857d879cb9eff22501d883071382832730704bfcc5cd5b07cdce7ab8dc41c565a1eb0e7e4befce8e0e03a4975d3f11ef +a2879a20c0360c516811c490289be7dfbf7dbd41d2f172c9239f99e3d091957e0446854f9d0f753d90384a80feb6fa56 +83518624f33f19f87096a47d7b8e5f2d019b927e935a9021823fac6564c4f2328dcb172e25bb052748191e75ac682bd0 +817ec79132faa4e2950665712b2c503d7fb542aa57b7b36e324f77cda79f8b77bde12314e2df65c5b5296a6bca9bb0b4 +b2abf8fb7c3690816fa133d5b4aa509cd5a6e3257cfeb7513d1408b12371c4d58c44d123ac07360be0d0dd378e5bcf99 +a9fe1e4fb1574c1affac5560939face1af6657f5d6abce08d32fc9d98ef03186dbb2dbb9fd1decd6d8f4e4687afecce9 +89b2f41e51f33c3ca3e44b692e8a6681eb42a7f90b81c9e0a0bc538341df9e2039ee61f26d2ebe9e68df5ed1bccf8cdf +8b35aa7b1d9e2135b35a1d801f6c9f47c08a80e48603f3850b425f64e7fb9860d1adda04f92a1ba22d00dd0a26e781ca +960574978cadedbd4cd9f764bee92f94e08b7af65403de36b21bffc9424bcee845b3b028af2e9e545dd77cf1e69a6a7d +840aa0f34b5b6c39471f54d9e85f1eb946468c4fc01963a9027cd7864df01f73c2e864f1f07aeed4b1b1af72808dfa07 +834464a84a11200e3c60f816044c254a7d9baed64aed45a17325cef7fd62338e0a26da78d199d30ac3411714dc813223 +b4ac6fe2f5059546f4ad9a361426ead33237b6b9030b129bf0122085c85fe4ccb33cf90f5a7f23c5b708a5ac64b487f6 +a12aa9035464795f2a67f3eaba478d5ebc838ed9e997c7dfa241e1ed60a94b367d3f969ccf0ef02028c35215698b309f +ac8d926492ec2bb68c6d8aa9bce49085d3d266f3d5f1f924032b87c42b44e41da7c047eeb01e4618f9d0f123dcaa537d +a5142425825d813ed8ce1849d81aa40b11f1cc3daa89a9f798dd83065c74820b4da6122b3308f528b074531df66e1a5e +87ff55c9f5aae079e7bf24084dd9c6b3bc260727d942d79cbe8dc13341d98525b4ece3ed8169994b56a387642f09134a +88e680f148ef2ecdcfed33b61f9e0224790fddc9069bd6999e9bede1791e761637c0fd60b52990b6c93e6e5429e483ce +94bc20bf5aac6e9f1060d02eacd06c42aeac9a1c5635b15a83985dfb03938ddb4999a822e865635201489c7f75601b29 +849221cab7599f25f0b114df092bd5e8c2430503ae959bef1543a101de0790a78245db6a145e26f40b5f9bcf533219a3 +88b6f2c2e7a7954fad11009d839ce50780921f80292320868d481e38d26aecd80fa607e82219a99532d88cf33b39f562 +b0d82947dc23c0b88b86c321b582c15decdb825ed909a731b42d46bc895009515a3dc646c98dbec7d71b0722df82392e +a2cfb9f7c1a76c8073363c1c3bebe5dc29fa76533caea41046c51ea9bbdc693a121b957cd96be5b6da18704d1865cff7 +8f0ffab9a83355a22683a9d998d1c1089449eb308711eaad4265f05927ec6d0d1ca39217082a0b372e02234e78dbaaad +ab024661e2b2937ad374c8cf2e3669f1dc55558a3a881e9ec4d461f27e0fa92e2bc88230f038bfb051cf2145ca747a07 +b98d9b9ec9eefa56d38cca959ce1aee7b6d4b41a8dbbd34b3f50c0a5f97f84ed2502ded1ce8cdb5895872360d4ba6d61 +851244158b3184a62d2c98d148e2b1102cf0d5500906bbc2deda95acc5e3bc4b4a3344febbb31ce05a56dfee86a74913 +860d9e2cb886bd3620b5d7499d14b415532482569bd45fd76e3e8052d78a73ae4b2b41f139f9cfb136564108cd93c0f3 +8305a052a0fb2bcd41f3aca075c5f7f233bd8f861451d03f3a6e6e31f7d08dd89fe1eb4dd7b238a78b12ddceaad9768c +adb703e4778c7e14fb83541ab00b5fc344108243ec6827c5d9b302ee68321aa569da1718424e6a57979ab7536d5eb43b +b1a754b87b9e21aeb86217ec5b4fadb7535344567f1bd15e88ec12a833fed68e26bfbe03b7709ce24ba6c925ea0a0e07 +8c1e2f6bf820e1653f3b8213e9d959d8649196223c2aab57b7ebda094f4919f88d883bcc6a0cd0be335f26f5a2a9c962 +a082deb9865fe8668e91db0e4fd7fb50fb3fdae3e7bf1217ce0aa6f286a624624cf936d762bb2b6c3fead6826694f846 +a10540ca05fbcccdd0a2a66aabab3b36e9bb525794cbae68bc3dace6116f58942218e9d5e9af10d67b5f6fb6c774fdd4 +b81d22c4ab0ccaf447cc5fc2ff3bd21746617e6773bf43257c0d80331be2e8437b88c9c45309ee46402b38d3d4911caf +84c7c6e924713cab3b149f641dabf63ad5abbc17c1d8ee7802a6630507aa1137f7e034ba1d12ec13f1e31efbab79bf13 +8773b9d236e5fcfa8c32e471b555264692006bf9a869a3c327aed33da22dfbf5780ecea7158904d4d6ac4acfe9789388 +a4c2c1bb7290eb7af2013f7dde78282148593f066b09faf42e61a3fcf81297caa5a00fdbf6b93609c8c5782a0f25341a +a7bfa6e3f273da3dcfac7cb9906bbe9fa4fc2872b184d79813ee273e6cc4d7f37f46164362707a1976f5b6a2c5d7ed1a +8b71502019e4263fcda354a0fd10aaa7da47f4abb7a0c715c7b017e9eea14f2b64009b29b467394668c7ca995adedf82 +ad7460fba7deccc3f9a7d204233de47ce30ffa55e1e164975cdf06480a6108720bc397b93ca8c959df77d44a1e1f05f4 +a5b8df96ccb7b078a3918e74b1b10da21df982538d2c9313f5129b2797c8a6db9ff8707241ff72d3e9d5983397321736 +aa6cfa6386660c01879656da6c4e72497690708bae6c5cd1d088f443cb5bbbe75561d6eec256a72b9728377eb83ef973 +b9699ce7c5c878e44114ab7a598646c6c7616b8e08a9ef8ec291189ef9945c1a538d2abf1ce3b0da0f8eecb303b81b43 +b8d0fd1d278f53c455de92ec4357885fc6648dc5f276930263da7dc885b4a9628a2113e28b66b1e64fd08189427c614f +84ad8d262f6ef5d93e82ff6f4af995148eedf6d8e079124daee9b99f506e2968922eac2c7d4aea741fceb7733f20b2d2 +ab5e30ab54641e3a44450118b8235554e0fcfffdfbe1430ceb3f7ef33325725741995fbbbb0c16f0875aef0f1e0c98ec +80e2cf8bf386ebda46045852751611f2af80eca2e910d9ec5f6e2c7376611534604ceafa639272b3d503b02bd66525a6 +aaac69af8fbb87da1c1b7c1b9e59942887ae839a91f0c1d191c40fe8163d7f1dbe984e4fd33619c73e63abfa7058f1e3 +a6194224ad838ab86e84dc80e9b8abb121ae6c3c7fddc476463d81f14168131e429a9757e18219b3896a667edda2c751 +b68f36aa57aedc7d65752b74761e49127afa65466005a42556230dd608ecc8f5efdb2ce90bb445a8466e1fc780eea8c3 +886c3fa235d6977822846b3d6eccb77f1e2cd8ba3dc04780666cf070cae208b7513dc4525d19a3fb6385cb55f5048e2a +a9801273ef850b99eb28f3dee84ba4c4017c95398730c447efe8c1146b0719f252709d3397ce60509e05da74ed0f373f +a58c2a5dd13e08ffa26a6c5e5eb18bd8f761ab64a711e928e6101512401ef2b1c41f67ba6d0823e16e89395d6b03ebb7 +91318b564ec8b2d8c347ca827d4d3a060272aec585e1acd693b2bafa750565c72fec6a52c73bb3ae964fdaa479700532 +a058db5d76f329c7e6873e80c7b6a088974522390ccaf171896066f0476742fd87a12fe9606c20d80920786a88d42cec +9838e07f9ed8b3fbca701be0ef32a3f90752bbe325aca4eaea5150d99eb2243332745c9e544fd1bb17e7e917202edab9 +85a9ae7dd354f36e73baa5ecf8465d03f0c53b24caf510036b3e796e4764a2bc17f0373013af5b9f1b8973226eb58cd1 +896a4ff4508d069a7da6ef7bed66e1080991daee8b227f3c959b4f47feaf75fd1b9e03d0917b247c2db11e105395d685 +a36d9a6a037bf498dfc0e535f2034e6cd433c7b52e520469811eb2e9f04499a6ce40257d2905300df7d81f38d1bba075 +97aac3c5492aca879b4c06db1834b30b8850a244d29296046a84c637d9580c8521ab4752ef814c96f255a139660d7639 +8552bf592a84ab4b356d01643c90347377ebf1f2b38a8c2e55a3f34537b8c7dcbd62e6776d6c2114f2bc2d4344d1567c +84474ad163db8e590943ccd1dc50b4f444beb8275919b33f53d42cba89831e9d42ce2de52b26f4412e2a0676ce913277 +900799dfaf5eafeb297c7b4f892438bf2a65ce04034d66f8e5cc3836e4eaffe782fba4f4455a0fcab49102a240d1780e +817176415e35ad4a204b9fd5771bae6cc270f6ff050996cec89efbe461b2940ae5dd3c6c7d7e31b1da5285b207efed27 +965e5791c927d47569bc54ec9b4c5305788aecd87a26e402aabeaeccc03480df46f0586ca2e2a9918885cd03332af166 +b96d9ada4b5a04a94807d71726bd557de94fbd44042d7dba40560eebe8658d1da49eba54499360619f3b2c38e8b5ed6a +a07b6d641a43e02e7868f30db4dd5069a2f221b4f122ce9b11eac04abadc4f25f3207f1d2d86c7935b1a3d9992ea9814 +8250d4d8ccac846a4b1a9fa392d9279b5bf2283c8b95d8164c3c0d199fec8849eab85755f2a2a99d584a0407742e3200 +8324cf49f56fc14162f9a9ebda1ebda0388d09d8688f1938aef7dbf9505fc119069efc552f68cc7cd9213f96fda2c6de +a98e6f1e85268dccbe3bf4e92c9f455c58dcb53de1dba3b78589adf2e50e79f8e245f956e0d098eb46f5d3746826c6dd +b103ec12f266b4153d67b54d8fc079357ee342cbe5008adc3e0689a7f788534c4601e60e939731f49e4a1e24fd589f82 +b2d7681e866420413cc98eae67614d383943e3762d5742cb3c57e26157633c20880eea1209feaf68402d5d33dd699708 +99fed0ae4112ec9ed74baac70d202a885aa51cb555a3886b49016744dd4017640dd5dd564998c4d842a9f38f3e004e68 +95c35401314467219c8bfb1ccd1f1eae6ef4fa9e48fbea14f70d5315e67b16c46cd03554471840e4a5030b077d2a3856 +8d029380e0c294400d6b8673a23aed43697cb6460fc1bcf217aca3b47cf240886644ed09521d6a05f6abf56f99722d84 +8ef54d1dc0b84575d3a01ecba8a249739edfd25513714dd4d1941fbde99dbbc392f7eb9fb96690d7052609af23aa57f7 +b8ad2b7af4812417aa8de8f33a26547f84bb84f39501d4b7c484cc8bb54c7e166c849b95240fbe459a4719a6e3bf1651 +9858545de898721d19930d8b360cacc5ce262c8e004867a050f849f7a2f2aba968c28d51f24a9af56aaba23a9ded4349 +94ea5043b70df1db63f9b66b4f9d8082776f721b559f27d37b45e0a84faf47f948d7c4532dfd854a4bac49fb2ec8e69e +a2fd88d7b15e3c2778f6c74470d0f9e1a1f979a4d58bd205361eacadab9973d585a6508e685e640b272d6f8a448eae05 +88defd6bccd55db8ca84e3c8d0fc55a3456b41788f1e209d0aec19c9c70febebf3ae32cacaa1dbbf796d7ddea4b17995 +88b8cde2449d5ee7de2ee2f32e845d27e171a51ef64f1d3d8a5fd7dbb9f898ea70eb7f6410cddfd7b7ae70ea8073cc2e +8e044fff6ec557824866ac76301b6d93ed19b7177aa6baa95046330f5d69b572b59200e3653cf2f2b559455e782e8960 +b5446b4d6741c824885790d2d26258729dc0ba2f469c85a47d38886d933b785a4f38a951d37f3ef4bd5091c03fa3a071 +956c8afa8056e9a71ab2e8be5241ddbb3a8b3cff2110cb0e7389493d9fa45e6c4b769ebef540a952db6dcd8bd55baf64 +925950cae25615246e29d594ebf34fa7d52f78a9867338648158f2131e6eb4dc17e18f9db8a5fdd76d017b3a9798b3a7 +a17ea4b43211ba990270c21562690b3ef154a46c3d669c4674c80bd424cdfa95d8850c8e882b8d06504f929cba3d93af +b315ec723973a138508afc387ef651fd8a8804f93975fc36c2eeb796a304eeb1508518d8703e666a74d14318253f526f +a995742d7433b3f230e622de23cb2d81cac76de54831491cc29768eb4a56da60a5cbd573e1da81fddc359b489a98f85c +adb2e89f0d15294d7118fc06d4fdbd9c51d3ecbcc23c69797e5b8197eea0d6cd1240910cf22fcab4ef1e2dc2dd99da91 +b5ec9f9fcd0b5d176b643df989bb4c4c1c167112373d662fb414875662d1a93160dc0b5cdf540e8a30e5fcbe6cfbbd49 +b1291b53f90aed275df8b540c74a1f9c6f582e16c5df9f5393a453a3e95624ab7552e93d6e2999784e164046e92ef219 +8bc7b7b1a584a12d5ae63d0bbe4dc1b63c9df9c89bdd1095ff4b8e7c822bf8c1994c92310a3644033c7c9689f4b7d2b0 +ad7fc45506a10ca48f991714ecc055cea376c0cbe667f3b40ee8dad8446218835439ae59bccc474cf47b053748ceba6d +b134756828a5f5725c0b95109e09ca450e3834b127163a0aeeb544e63cc0cdcdf66f8ed98c331c7c98758f46af369a84 +94535bf1636be0974b112fcec480ed8eafc529933f3065c40e417e608e43a392206cfde8bb5a87b720263446c90de663 +a4df4f6efbc3701000fb072e5cbed2754b9ef5618386c51ff12f95d281d1b700fea81fc1365f4afc66a7c83bd0228fbf +b0336b3552b721087c7e2194976a9119aee13ebed9f1c3c494353707fffde52d004a712965f460062ec9443620716302 +99a39d1d1ee4283b75fa8c1fa42b6a3836b734be48bdd48050f9b05e48db6354fef509623c6ec8d447d630a9b3352b77 +8e3dc3583d40956f9e784e8bbd0b5e65671d2ff2a7c387b20fcb7da9b969f2d122aaf7f054d450dc611737604548c03a +b5068ec5b7bcb5d8583d51cb25345990f50d1f7b82fe535a6a6b17756355885047916f466ea3ab09eef5516bbf2dda90 +a8284ec1eb1d21e693f31a6c074199ee85d8a8da2167bffab5fe240defa2773971c8437e358a18f7e58d1e2954f57f6f +aa7415639d29081acbaac3e9c6b059d68e8702db3f430b86bb6e220d476fa74841c875e9d471c8a5423c58b6fee3cb54 +8afcfe6f65fa6e07c2cb3e1756c0ef2c589830be96edd50c3c248e3b17f51a4b08ba92ef7eed7991d81667ddfbf2bf7f +83b9c8dec8ca8f9b85f0e36c08c5523cfeafb15a544398e6f93b48b5fc4b15a0bd05c0f176a9c2469664acab8dffb0a8 +82a128a89ea46b9debe5c903b950c0ab30cd7570b979ca911500b5c2cca5c4ee6b2c2fa414b5f28e367f4671ffce60f4 +b79fd0ccd2629a361cd6f9307c02ecd4d1f07e4ee03ce4b542997e055b07a026cbc0ba05fe3da309efc58db2e401a8fe +b190751141093823b4b5324cc26c4f3258552f7893241201f2fca1ae9b1a1d4d4964a9abdde8642cf308ded61ce5ef09 +935fd48b95aa6f9eada0cf9a25a573f0ffe039888b3410788c41d173747bf384c0ec40371bb4383ddcc7d9f2db3d386b +b9affe100d878491ff345636ffd874ce1f27852a92417694afce4163e6a80c78b2f28d78102fd06c3283ef273ad37642 +a877670276d49ec1d16c9f1671e43ade11c0c1a1413755f6b92be9ad56bc283e4bd2ad860367c675d5b32ff567301fc4 +8c660d16464878590761bd1990fd0fc30766e7e49e97b82ec24346937856f43990e45aa8ad37283cb83fa16080d4a818 +ae1412087da5a88f3ccc45b1483096aeb4dcf4f519ff3dbe613f63712f484bdd8b2c98a152a9db54cf1a239ae808f075 +ad83cead97a9c3d26a141604268f8a627a100c3db7e5eefaf55a1787ddc1dd5ffc7544e4947784cb73b90d1729003c8f +97c3140ce435512a509e6ff3150da385fdf9e0883a5dc7cb83d616ec8d0a0014e4e0fa57a4d12c7997cd84e07d49a303 +a353773ff68f1615454555bf658eabdcca40a9c7bced8537ea6fa8d54764fd1f032889e910d2a2a342835513352e2d2e +89e8df0c17a36ffe08149c2ef8b27306d04cdf437135aaeba697abc65e3c8e91bcf1817919a8a826acdbbe7dce79a18a +9928c2da15ac6cb20b15859c22508cfcd452c5643cd22eb84abf5f0a1a694fdefcd8fc329c9b40babc52630743d6b65a +99d837b556f8d13108eef6c26333a183f59383b39958dd807b10590c3d37f62ade6c4a320ca2e70567e0218b0ad5807d +9272da080e4aa18720b634640b01bf1fe506c7c8a89dee8759a53e2ca5cdbbd4a4f3aca54924c46b935362cf1eca066e +b4d39752c882de1c1daf3854202c1d58c2bcf35c882006eb640fe54a97be2655281cdb91c30d1a41c698617c2cf64b01 +8bf827f4a7d47e07374d338a3d8b5c2cc3183015b5a474b64b6086fcf0cdcf4852046c9e34d7917d69caa65a9f80346c +901bffc7db9c9416e06f593a76d14f6d9e5dea1c5f9557bd8c93b9e70aa4782bab3518775c2a5b285739323579f7cf0a +af7e204388568627ca23e517bcf95112ca8afd4c6056b7f2c77c4da4b838c48791191565fd38398587761c8047d11c47 +ab2576b5366e6bd88b347703f9549da7947520d4e9de95d7e49966d98249406ed9270fe69347c7752dad47e42c4ea2f4 +b12e3b228b761dedd99d02928105494ded6d4fea3026d73d65ebffa2e85e2cd75b6d091135d418dd95ac102c22b5ee31 +a20b4a752685d5e31ee7e2353c8a1b9a5265f12bb775004d282a3ecd9deda44831bac1ac5151646428b66909b2a423f5 +91a1d4bc0062a86cc6786a96fd3eb4436d8a4a187b7cbba02190d1cd6ed3c3797d9ae7d6ddc413f1c94a21f62bd04ef5 +977f18da1a5df5cfdd0276f583cfba2b2a0fc6139520664e20068f8dfdde33e29d179abfd722f142448f4677aa47be6c +abc3ece90f0f7b1d80fd917de27ab0d88cca584ef959da520825e54cb5a71336b15f8b348532d08d47a6fa600527ef25 +888d36a2c7cc13a1c1aa338a183a74a1f57713e76cb825f9837f43279ce4741999b76a16928147537bcc20f2e0195b0f +af3f5dfdc2dcfe19de893f385f39f550cb1dab67c2e97f1d5fa735e5ec96d6680066803e8a0eb010dd4399f654195513 +a0fb4e08ff56530a940a86c28830956eb6dec2f020f7faaea7566faf0a4fafe0cffe01480e87763ec22f201be51a6451 +92343c5b107910b203c64a79c93d354f7ee5b7d1e62e56732386776e275285561cb887019cc00d3fdbe3b5d54460bec1 +acfe7df83c4624188a1011ad88c1e1490d31a8a8c8016b40aebcdd7590d9c0793e80d2d7ce6a7048876621c252a06a5e +a7da001dc1e33e0e129c192d469d2bd6e5d2982eb38f3ba78bae0670690c8e70f40e8114a57bd0718c870ca5dd25b648 +a903de5ff97dc83628290d781e206ef9d7c6b6d00cadc5bacffb31dc8935623ab96ade616413cb196a50f533e63641d6 +8f9658d42ad14a60bbf7263f6bd516cfee6b37b91a8f53715d69f718a090ad92484061c2cef999816760a78552fae45b +8c15b72b3d5fcb9ffd377fd67d9dfbdd706593fba9629002639973db12aac987bd1db70250ded31c88e19efff612cdb8 +88a2a4034decd854fb557960194ff3404e239953818a8a891bf72a0b26a8e570a65c4a630884de991ae7452b3234f31a +a09cae5c4c190537bf1dd75bd7bce56f7b799762af865bb9d1ee970f6a133c27cce0dd0f14a0e0516ceac41054e6998f +9760ebb1b40f9a97530c3b940d4ef772a225e5b63bf18283f8e302b9436c5209f6294980fd37058060e429fb7fdc3a56 +adaa9400eb86d857dc591b25dbe3bc8f207b69e77b03cb5ee01f7e4b006b5c8f6ba2b51b5a45687479885708509363de +949efe6b00b3248846747a9ad4a934d6e4255994c2b540a59fbbde395fe96d69bb67908441cfadd8c8bbb561fe52da03 +a19a45504b6b1dc3a0fe0e6a1384734a3dcd5a7cb8fb59eb70e49426c4fc44946547443d558e5719a04884ab3a2811ca +8934c9ee21e8d1435426fd0f64232a0670a7946ec524c054cd4f2cc8b1be9f89cc11002ca8aebae646a2050d91716b10 +b1150ff8ffb34ffdcf7d603348c0aed61e5f90ee0a1b814079fc2a41325c75f2f9ee81542797ede3f947884266a772e0 +86ce8cc7c1f92af68de2bca96ccb732f9b3374dad6657dfd523a95e8a931a0af2a80df74098514a06174406a40c16ba5 +90faabb9ace9e13fd9584932846ab28a618f50958d2ce0d50310a50c3bc6b0da4338288e06e5fcbaa499f24a42c000d5 +af4a935c2d8df73332a16dc6da490075cf93365bd0e53e2374ef397514c30c250bcac569b6df443985cf3720a4534889 +b7f948ee90f394789eb0644d9f5ad0b700c8e44e5e9ed0e49da4cc18483676d25740710b1c15a557965da635f425b62e +a917913091245beed6a997ff7043ecf60c4d655c4db0b1ef1c704fd9b0e1ea1335ce8b9f45d6e120f81805ce31555e30 +a48099da8406399bfb1ba834f6f7d864111d0036969a5cb64089947a63dd9467d3857b605e9f57f5ad5f4ec915088d9b +9784c3f9be42eed354542b1446d734521f8e3f01cd9d495ae98f2e4a3a16767fe2ad909e0def5d9a6267f3fc6a172cd2 +8d9afaa323847a3226ad7d7b60d87322ffcda2e4a8df89f58a076f7972d896588de685a2e155e243bcf9456b0a0d6d1f +994413faf0b843f4ec1842c706c45ea5f24351c68674a27887bc8b182eda756856e507a4e8bbfd937e2c4c581b629ee6 +b3e72d9d1ddaa00c7d22f25462d6e9f2faf55e30d138dce8bb1517eb0b67132db758668aac26164fd934d732633bdea5 +8e95875e338f714e9e293df104f0ad66833bbd7a49d53a4f7f5fd5b18a66a61aa0a0f65cc31d55e0c075e0d3e412cb90 +b980091862b1a9f9334b428eae14bbf1cecb4849e3a5809773b0d071d609727270f6ad97f329eca896c178ce65883db9 +915d7ae5ae780bdba27ba51a9788a8852a15355b569581d1f18f0d94bcdfed2c1ed5a4f58e049e9825cda11f92b2c2d4 +83e581058edf9259d0b06128282327cacbb6afc939578223cbf93544599f799a8dce1fb21d52464f990a877086f42506 +803612a38b6f6efb97941997e101ac1878e192456f8fbddb3359aa7f3023434ed8fa92e60ec8e7b4473b1948850e4311 +864a1bf4ac046161617dde282e44ab3cc1843da01a09ca58aa00ed00eaea9351a07a9ec16d910819e7dcc28b8d2c8ada +922eb142845975d5f6f7dcfee6cac8c299b3730400e6bf82cc0bdd9888de21de9d9f1530640f702c003e1ed63b140cc7 +a7db03c5be647dce1385ebc02f4825a654447fa8c4c8d4b22e635dbdd2b3ccdf219384e49a80cfb1e9e6182b6e4227ed +a167289ff0f0967bbab6479e4a8a6f508b001bbe0d16cad36ab4c105ad44f3f180e39a6694e6cd53bc300fe64dac1e8c +b7766431f6379ce62cba22ab938cdbb1b0c7903dfb43980a417e0ee96c10b86b447241e9dd4722fa716283061b847fb3 +90cda18c5d66f5945c07c8c7dc453dee1370217ccb851bbea32578599aa669b4dd245dd8a9711b27c5df918eadf9746c +ac690cd2af39932874385fbf73c22b5d0162f371c2d818ec8a83761e0a57d2db2fca1d757343e141e1a0348016d5fc44 +abac820f170ae9daa820661f32a603ed81013c6130d1ca1659137d94835e1546c39a2be898b187108662cdcbb99d24fe +b2ea5a5950096772f2b210d9f562f1a4cfacc021c2e3801ac3a935f2120d537471307d27b13d538dcbf877a35ff79a2e +ad94af4d0699cd49ba8ca3f15945bd09f3f7d20c3aa282a3113cdf89f943d7793e59468386b067e3c1d53425dfe84db4 +83788367ec97cc4bbc18241cbed465b19baa76fab51759355d5618067009298c79d0a62a22e2a1e6dc63c7b90f21a4a5 +a3e142d879096d90b1e0a778e726351fa71996466c39ee58a964e6b5a29855123d4a8af47e159027e8e6be0ca93d9955 +860831f8d3edaabd41be5d4d79c94921625252aaec806251fb508e364e39fde8808d38b10d557e487603a1b274c9bc3a +88da39f334bd656a73c414ec17dda532059183664bbbac44eb4686c2601629ef8ff9da992c337a842e3885b684dd0032 +b50addbdf7164e8303f33de5ce854d6f023d39c1c1984b214d9e5fb6f6001cd5bdda816f048a438ff3d696872672f805 +999e58c4c69a912b84561cb09610e415b43832beeb95897eca8c403ef4754f4277754d492eef3673afd4362f50060fc9 +b88ea0f60f8119c5a1fd9294796d387472dfad22442b29659713d1d88e7d854cb7cf5c9ef773627781188626bb2fb573 +a068b3844e9dbcf74b54fd55904d56af754d8ce4c619fead7a07f9bfb9d02118db7c512ccec2489d2a84374ec1d1fb6d +871dee023768636003c799e6f6fd8d31315a4c0da7286345cd64264a016693b3485e0732be1bbd34dd5fa04dfa58a983 +8021e8f508680df12e4a5a1bd49f2d7142df65158b0a7198ffa83abd16053a542fb93ffc33e5279020ba8c6a26feacf2 +b5d3cd64df5bc965228b0bd4ce9e5797c409f7b64a172ba165e44a8e4b38e3d5fabc3e0b9a19afbfe427f887c40a315d +a54fdebbb594bafcefb1a03697711e0091c072e1cc24fb441fefd4e0a0518675a1d7b0966cb8294051d7ec0ac175d0cd +93922202337f72969d6d6e14a29c9c75e0420dfba712029941d1504b9f6f9761d706cbc0652cd09a1aa5d22aec766af1 +9711ebf1c7c7426190d4afd5dd03b014a456bbd9d90ed101623866a280550df26a629dde400c03ee3699f7d827dc0bb9 +b4d686d8bc5c1e822a50124c1cc23c6bc3a1577a3d0b8d4b70d1797418aaa763283c09e8a0d31ae6d4e6115f39e713c4 +a533ea2ac683e4ba07e320501a5d82a1cfc4fa1d65451000c3043f0fdac0a765cc1125d6cc14fe69975f3b346be0fdde +94ee563134fe233a4a48cf1380df55ead2a8ec3bf58313c208659003fb615a71477e5c994dc4dcfb2a8c6f2d0cb27594 +93e97d3f3f70664d0925be7aee3a358e95ae7da394220928ae48da7251e287a6dfbd3e04003a31fab771c874328ae005 +b57440d34615e2e7b1f676f2a8e379e1d961209fe00a0cf6798f42b7c28dbd03172fce689305e5b83e54424bc3f4a47c +97644084c6f7b4162bc098bed781dd3af6e49e7661db510975528f1dea8154f3d87e979bcae90c3df3a7752eb0752889 +a923b27b225b2a6dd5bdc2e3d295b101cac5b629a86c483577e073cea1c7d942c457d7ff66b42fcf33e26c510b180bc2 +86698d3b3873ed3f8ab3269556f03ac8d53c6e2c47e5174ec5d14b3ed5c939750245441c00e2e9bb4d6f604179f255ef +87946826d3aa6c7d53435c78005509b178fdb9befc191c107aee0b48fbe4c88a54cebf1aae08c32c3df103c678bad0ca +860864896c32b5d4cb075176f4755ea87fea6b9cb541c255a83d56c0a4092f92396a3e2b357c71833979b23508865457 +b78fa75d687349e28b4ddfe9e2d32bb6a3be13220b8f3ff1ded712088bd0643da9b72778bcca9e3b103b80097f48bdd0 +8a188b940446598d1f0e8c6d81d3cada34c4c1ae0118ec7e0eacc70d1bced28ae34b99667d5793d9d315a414601c3b22 +842ac6f7dc14191ab6dddffcbc7cb9effba42700a77584aa6a8e17a855cd444c5d138f9d61bf55f43c6ffbcc83f92bc9 +b6742902c3d145a6af9738c01cf9880dd05c85f0d0ef7dbe93c06fdd6493333d218339ebc2a02be1895436a2f734a866 +98bf18488483c627b7181b049d3e6f849fce1f15794de59dcde6e5a9b0d76fd484a46e48822a6a93001d3aa12f48bc6d +8769cac10bda8c53a1c19419ef073a5998f73dcf2ba1b849561615a17cbc0a49bfe3eb4ff8801dd36a22fa34b9a3a7e2 +b45c084d58028fdfae792210fcd183abc4ffddeb4cf52ebf3f8a50e4c4eec2a2758f1241b0920bebcb24b757c778577c +85c1216eec8e1fbc1af9b36b93c5d073a81d5fba86a6daae38748ec1573eacc6bef209e76c87a6efbd7a3f80e11d4c3c +b8007e34bb3f927ec06a050b51e633d7eb9e9a44715d5b39712e69c36177a03cd68391090cc3293098e54f6cf65f6caf +8e85527b27c9152b1ba3fdd532a76a79064ab097570508f233e09978761dfe3012d537411b47d0e4b65265eb32cea2ae +899779f3c31a20b76068ec8d59d97a64d2249588ddfd69dcbaac6bfaee8ce0ff3c5afc4e17c934ae7cd041b760eb555d +a5dac3d8f5fbef018509612e25d179f60d2a62451c76426bf546e9666fcdc73263d34aa6fa7e2bfd4c9947bbf5095eff +896900eeef9be2b2e755128e7b1c436af6fb3984f1e66c444bc15fcf3959013b4902c381f0eab1247f878a6ebd1f4ee0 +8cb17f4b0af2e9b2cbb56f46e6a5d6874ea0daf147aae77303020b4e592ddc92e0dd058def7da96258b3a68b223bf22d +a1b6d3f09a9fa7ecc021ab7c5396541895da6e9bf1f9a156c08fc6f2b815a57f18c337ccfe540b62d79e0d261facb2be +ae70888811434ef93da60aeee44f113510069fd21161e5bb787295492eb8df85103794663fc9305f04adcbcf11ff0c5e +a84bbc8624100acfae080ba8cfb48fd4d0229a60b62d070bd08fade709efc6914dc232d3f7bed76a59204f9252321aad +aea47d54652abd8ca213cfc623c8e30780f37b095b59ac4795252a29c2b6bc703a5203acff8831314478b8ee8771d4d7 +8dd438eb8be14935f759aa93021c2b24e1d588f7a162c42c90ec3a647b0ff857f60e24c0a8953eb7bb04e04be70f11ce +922b07b5469680a10e7532766e099896f4dc3d70c522d8add18f5f7765d4ddb840df109146607b51ceddd2189fa7b9c0 +83ef6ebd0ae6c569d580093e8b0b78daa964760556272d202d343e824c38eccb424262e5b7809d3c586f9e2e9c5c5f22 +97f98bd357db6e093e967fe180cf67ed09fa711580a5ad48f07cf095b2e8fabbe6319f97d1f15d62c0ec2227569d8dbf +a1953a4a22fe6c2beaf2a5e39666b0eb53018af6976e3a7aab5515550ff2efa89400605a43fb2c4ac1e51961dbd271d8 +a5cbd67f4c0bc98e20aa74c09e6f5fb6f42c08e59aaa477b4b4e61434c8884bc14f17cf11faecf46dc4b6c055affbad2 +87d96818f2c4f12fd7705cf4060a97bd28037c5ac0f0cc38f71189ec49361e438ce863e6617651977708094d5336d1da +85e7c2daae5fe59f8a1541c94df50402a671a17dbb8838113fa4b7aaff6114cf2bb5969410cf21e6a162857f2f7a83a8 +a19575083e1731bb04bb4a49414e97aaadb36d883aa993d1f6847db50007315444814740e67e10177a14e0e074fd4c7d +a00ebfb5bcc3a6da835078189038a1e56b7dab6be74332b5ff7440e53b0f9e1eb9973effecbbf37000021fcf50c7c1ff +8969d7943abd3b1375fdfc7d6124dde82b0f7193068ed6ec83bcf908734daf3487a6a30f7b322e54a4818ae5f86d91c0 +b959c8d210fa43af9b20d1fe0ea8c4921280eb4544ef6ea913309ff9d61c9327096707e84dc1662960519be8e7d080a4 +9011d8ac651c42e0cb03931a9e960f58e02524c6b666047525e3b9097e9f35fb2b4b278efcce2bd5ad463c6d7fd56694 +937e3b22ed0fcdbd9ea5a1b97b84bbe86b7f5b2de3866a930611112f2217f4ee7d9822c4ab1253823f77bceeae0c8e10 +828997e5d121f4c305e018a0a0ba338bd6a34a7b4dc3c5ceab098ee57490311c130e2c045b9238a83908d07098d9fc32 +8d114808eac0f2e1a942d80dad16756ec24f0276763cd6771acb6049472e05a9bb1d3bbd5957f092936b415d25c746b0 +a063c5c26267ae12887387cbebbe51fd31bc604630b3a6e8e177e71d4f26263be89112cd12d139dd4c39f55f0e496be0 +ab1e1582c8d67196d10f969eeb44e6e16214f1316aa4a2a821f65ba5834326da6cba04373eabfd3b3072e79e5c9717e6 +a17b1dbaa11d41457e71a9d45d032448091df7a006c1a7836557923ab1a8d7290ec92a7a02b7e2a29fcea8f8e374c096 +a1ed7198da3591771c7c6802a1d547cf4fcd055ca9010756d2a89a49a3581dfe9886e02ee08c4a2f00b2688d0600509a +af09aa60c0a185e19b3d99ffdc8c6196d8806169086c8ff577bf3801c8ab371e74165ba0f7329981e9252bfe965be617 +98c04cc8bb26ffce187fa0051d068977c8f09303a08a575175072744e0a5fb61191b1769f663a426c30d405515329986 +a542bf1c9c3262d488ea896f973d62923be982e572172e2461e0146190f2a531f62acd44a5e955a9f1e242b3e46d63ae +aef7b7f30efd50e4a66c87482386f39f095bff6108e68f74fd3bb92156c71c75757912b111060cdee46a6b3452eed657 +8afe1e0ccd00079702f16ab364a23bbbd3da1889d07c4f8cb04fd994bf9353216360dbd364492932bfe20b8b69ae8028 +9896c690999db3c08cd7b25efb1b912c3e0f976db98a3e830f086aef93222d06ce570a7b2babcd7c81d8f9955169669c +ac7bcab6a281468907ef1ea8a6c1cd624159c88839131bef6aa0c22f331fc87ec6128a2c2a333fb79df549e4587e1a12 +987935c08a30b099d19f96901315a2e60591baf898581c40bf5eddcda806ff24a4536e30ed1e6c0b128a83fc77b6e81d +a0a6945bbede3bb09a4a09ef27baa20619d3e15af5673b9350601bcebe952597c989870746cf75767ffb73b32c6c9c6f +b0f5590079f0a0302b08a0cc1b7a5f39cc6900c2a5cdc7baa333d8328a731b2df5dbb67e27a154d3c44ed1a795fc4adb +a7294bdeea210e528f277f3d50e89e6d79950494478998181ecb38de675020130256f2f2a075899170be964d478458b0 +8ab3041b895a631869b439d5599a66facba919226ca9b39d915f19d59f9fc82393ea781377e9bd3bcc5a310e41376914 +8da399b59151fd48b2579948bb82698e3c9804d70ec7d6f3cc7e82901f9f2de5ee850349a7d6f43e5e9ebd47bd78620f +80e8c32de83d1083916d768b11a982955614a345d26d85b457f2280ff6c52bb776958add7c1c8878f7d520d815b8e014 +81bbec7bd99d2917d2dcd8a288722fb33ad5a4bf5416fba8609fa215fb80e0f873535349e7dc287f892aa56eb9e39c4a +9665796fe04c8519206fba58496bc84a8b9113e7ea8e152b65f7f732e88beea271dc97b1ea420dbc8257cc4b18a77463 +a97e342aaaf693ddc87e02790278e4bb50117af4413cd703bdf3b7cad2d1facf31fde1303b43ab2e0265467474f97a8a +925549ebebed348886e37773b05cd8ad04906eca4536bfed951d1ee41b3d362ddc6e1a302c21ff3a2d1e70e95117922c +818fdf74d7903502101551bbf48d3c7819786b04b192d9e94362d2fcb85760d8b6f45165a5443aa5221bef400525ddb4 +a9d29de7e8fd31b59f4a087168d062a478b1329cd3c81c31e56de4fb40de7a5be9a5269ef0be452c487443a0b097dd50 +a85286ad573db4c9aa56221135da1e31d742e0f6ff01d6b159086d7258f78b08dad55ec8eb5c91ee9d3404b2eeb67e1e +92a79b37db5e777f9ebbebde24a95430a199e866e56597c7d0b0e7fb54c7b092c2f6cf61fb24470ddf250cf609898281 +8d79f5ca67ed67d52c82949af342a9fc60fb793c47c76d84b4863c550796fcae2dd59e285897c6fb96fe31cee1efa62c +8ad2e0bda03415ab86324992bb62dfa3612d2d003765bcad1468087c27971d08bdbae5252681f0115a184f4885d444e4 +a08815af979286538c31b4aa5ec805053790af1ca58a8c4341be51136d094a8a05e569d876a079033298ad355ccb7ca8 +b96c2978d0165d619d08281d295e90df78bc2375d0afbc3142ebff9c2cd4b0f0aa97a9a0e3740bc4dce0ff8a9fac8252 +b7752cd0e582f35ab0d0036ca9c0a9fe893a6ad325164d78d865a604a85d3d23729e0362553e8b8a3d51816beeaa30cf +99cef1fafc29e7adfe247c753c475ad4bda7a5f9558b79c86e8a65968ede67adb38dc30071925c9d66a13860027a6735 +b9f6c65af178c791b6137d71980651fb09cb5b42f268999c728c6e129985a9c7d77b3dc3b50751bd29ec9ee0b3111dfc +8d73ae61fff5be883a281782698075c5650083f00399992688738856d76d159803be0059fbd9dec48f4f0432f0590bbb +a8a4a2865226de9bbf19e12c7e75318439fa6cf1cbf344d5e79a8f363439d3bc5bcf4df91b54581e7866e46db04eaf0d +894582aeff222e145f092ba15c60d3207340c38f2c6792ee2ab4d82d50fb544ae366c2985cc2b6c2f970bcc5f4b46385 +956014ba2d20a056fd86cb8c7ceeab9a2c6f905dae24fc1c5278fa5b84335148ebdefec5dcde8eb9b084700724fc93d7 +af217fe2b654eff6d11a2a79fe0339a1d4cb3708b7be9f09d852158b5a44b4f9b04406d6d67c4f144fb6b69a41ae9d0f +a90752a784bc00df94d960e523f5596695d16a534fc806179e0f878fc0e82a91b25e758e91a165debd815dd1af5f1028 +a697606fb32979549ad822b31df8eaaf50de4ead984439a0a33e955937d326519bb9f62c8243ad37f764655f8d32cc80 +a3ad4a30922e45a3e665551e5611384f1c2d414f6fa806184b0c826af05f014dc872585e255543794ee41e43cdadd856 +b29c255843a82ea74a013bac6c36a694646e61e6b9cefc4c130e2ee261e3bb5da3e0fe3ee7e6fbb009deed0530bc1c82 +87e1cc7febefa829cf050aa2aea59385d1048f8617abba691f7ea9ef58eb90ad12eeb9c439af228b0e34897ba1cf1b47 +994d3222f89e9c8c154362190be7167c8c2662f0cfa9d50eb4d8175b255ff0de09dc548ee312fc8226963c8c16f43e8b +8f1a980be640820f2d1e953264ca4c30330878971669852be3d5d6b41c488be1628b935388bfa2bd4de484acb0fe661d +854d90d0721579c8c88e147a4aa83553c960617b18075f8224b975562dccb30b0e02e81fa9df7070f356a0eeffc3b14f +8e156da9d4330a03e32a25a2f0b861fd3ea5c719fa4f834119baab6e5fa5236a9baaf0d44147bf0841418900037f6eac +96586fc49e53a6799242ddf617000db5a0ad20c6cb1686af2102623d64a71aaddb8e468b15fa6d100d0384e448548db4 +b44d8d85c8df95d504f82d597f8c515866d4d4a326fa1b816dcc5bb0cc4ef1a52647aa5d2e84c62e194c01cae0885d21 +b75c43e676a7efd199f8b32ae31f176ec667e714df355e9eecee97246f72af5bef9c5b04c11e7e90fc37bb9163f957ec +a49835ac0565a79f6a9078cf0443c5be20561a68b448289589721fded55188583f1d301925a34eea647f90a6e66c6774 +b47c17ff6824a00b8f29df0adb7f06223208d062bd703b0f763c6eee4ae62d4217eef2da4f4dde33f0b469c2f2db9e42 +957cf039cea6f6d41e368e2bd0cf77315938a0738f15ed9ca342f0a28658b763659ac1d1a85ecb362f13de12b77bb582 +903a52f8d2439fa63f59e1e9aba864d87b0464ded63814474947112375236a6f84e8fa003cc4433c8208d80e05fbd1b0 +8afd524209ff08d1eb6312b078f7afeb8e1155af649e930ab711dedda226dc2db6b0354aab9652eea7f433f90015bf7b +a95c3c9277b11bc8fe191773bf567641be57c0549913b973fb18740ff9cd7b3f7ce198fa4dc1086b2b8a446012459193 +9455ce8163fce04aeff61e7808ef3aac4725e51404f0858fe5d39d7344f55dcc7871ca332aa5cb1a63a4399529e48907 +809fa35b6958f94e781f2c584438b33f5ed528a6b492d08960cf22ecf63ea3aa1e2d29bc879e17296e0a6cc495439cb6 +b0f50774de212dd33e5837f6b496556215c665437e657f674fc5117e5c07dadbd0d057e6ac4c42d50a8eb81edfebf315 +844c65e263891d0b2fea7db6934cc4b7fb6bee2c1d0b9ab4c47f2eb3e9c5d7197dad828d38c54139123740151420280b +b13c78c9efcbb3b28eb3fe0b971380b7d5151c80948a99cd93c78b4c3ab0e86df6226a64d91e0a2ea4a1c0a46bc0404e +90300a541decad460c348b8f4257f7a29687b2362ebee8d92fd03cc0e85b285ccb0ab1cb2ff5e29c5cc5295e351017cd +ac49b409ded770c6d74f6e70104c2cdc95b7b90609da0743c9923179e8e5201ead03becc0ab10d65b3d91a5be0d52371 +a257b815bd8289dfdfc21af218aaba12ccfd84ebf77642cc4cf744d9b0174ca0b0d7ab2a545c2a314fd5f63c140f41ab +a34778d8446e4d74d8fe33de64b2694ef1e50bc140e252af6eff3ce7b57acf8b6577a02ba94b74a8ae32e5113cf0a29b +ab9e935bcf0d8607e3d66f013d9bce7909962cb7a81174923db02dc89e485c2b1c33d6065bdc7bbbe0450b5c49fbe640 +94d2c5c5c309c9eac04be4636f61bc47fd9579b47aded57cc6c736fefb8dfd8f8a5de32210f7baf2052d04c0219d3b4b +b8dda9046ae265214086355101be3460421f7cd0ed01bde9c1621da510941d42bc93cd8060fd73f374fb1b0a5f38d45e +a6674649dab5f92ab9fa811d9da1d342cf89ff6eff13ad49f4d81de45438e81a384098d3ae5ccce4c67bda5dbe246d95 +8d619f7564677bacba29c346c4ef67c211f7a3a14c73433dd1a7692e16a7e2562f1d0532454af62fc04c2fd2bb1789b0 +a2b93d2fd4c707f5908f624a0fc889e20164d3c61850af9125f47a1719757a6ce6375aa1910eafa4c1e8b6e20c312775 +a07d5585447654d82817ef4d199984542328b238157976eb9a267f0bdb2229acc25aee510be68f65a312b68fdd9e0447 +8ef55cf95e2b24d8ec88e4136399a7763bd1b73d5e90ea45e9845123e9d39a625cc336e9b67988374b8ebcbc75f2ed21 +b62c1fc32e27c767c461411b02fe9aa44a86586e1427406f4ef0b346d077db91952abce79318b382ec75b7be23058cac +b252900345f5fa15a4b77fb6af6a2d04db16e878b7bd98005333f7f6e3c8e6e46cf38fc5d1b2bc399c5c2ff4af730dc6 +a4ab5ac0cc15d3d17b1747c6e3133d586870eae0a0d9c8fa7fd990ebd4fbb62e9090557ca2792a6bc6271856aa3c9a05 +8e706b3f2e902faee10b22742c6c33bea6f670a8937c243db96885143c1db5c979e33ab73a38359b52b8d668ccd092a9 +8a6792190ee6c959d79f60c22980ca140c638d88d75660adaf9bcbe6dc4692ab5f01e0c460170f09f74d5e582e85ff1f +97ffeedfc94c98ec85ea937e064d7b290a326838e62cebd407facd1ab4f08d9c0c109d79af7cb6170fccfa6c8243c127 +b79970b67c09453614ffd83a0c923c17f857c6ce3c87a356298f8351cab0def7ed83efd4f6638f48df67e07bef4ad9d8 +b90f1931c7cf1822cc0a97401119910cdfd0482daf09a4d7612e4e05046295cfb4cc50d5214b31676bb1a1c9d15f9c7f +922921ad813c01fb5d12fa7fb7ed8e0b0abbf7b19affa190b36013c55b88fe3c7df0ae663c970eec7725ba37b95a7cb7 +a124f33e7f28feabb4089a063a08d52b7395d24eecd06857a720439dd9414b7073bb86fbd0b04e7bfac62d3dc0fdb2f2 +b252fe50bc6677c004550f240fe670974a33ffe7191ed7675da6ac36c780c2f8d02be7da5d92cbe2d0ce90147847f8b1 +ae5f8c9c56070f919f3df2d2284348fa4b2e39881f7bc42c9b2f5b7cb1ebeef8ecac000f37329bbe04cc1680cefc7f4e +b432a4575caf7337f11eecfcbd34a6705d0f82c216301725ceae2b3c9df20fa53d1ebef65513e305013d1e0c2df522b6 +b7c016fbbc4614cdbb12db1c9ac41f9a45d5e5ce82594d568a30cd2c66c3cc9d91a2c959697b67c582a0913de661505d +8f6f3e5e0347dddc1b2a34ec0dbbbb7cafbf976f19c9c902efb5c1427d1bbd4b71abd9f3fba20dda75c35a39393c989f +b0042a1d33a1ee9fdf3fad2299b8d70c4f1862d8393b5ebe3ac2189a2c5a58bb826128cd7a39b70d524a6dd976097e26 +85297c4e8ae8d9b44c3fe51aa926c77d55db766c2a9f91b659040de36e34c9a4fc6f44380f8d61704498f6fd52395a49 +8c61a988b6a00fe5a277450f30bf6daa932e42a2eae844568e3babf8815e09311f3c352dae6eb2d57a98d16b7beb2d22 +990be28aaecd932e7edb2a97b9be2789a3905cb88737b1c79881302585801c69a3dd5fb230808b39db1352fc06e0b4a8 +82fd14bdb335aa46f022dfe0ed4d631911e6b6f5eefb10d11e9e2e02a7df55012ed8162249d10b58eb76ced5a7b06cda +ac39cb058df764e161db9c39b185f09aa210bddbd66f681f1697ddbe6b305735612d5dd321d3ffbb4876771bdb321e2f +858a3f7e57ccb81387caf8e89f9b6039e9aadeab06886d8688fe6427151a59ab2e77e85ba850c67d099965426c97779a +b57fb9ea623cec432946819937c6bded0b5d03c8c67b52b44a4b67d34adfb055e6cabca67a48e4d859b4be45162c5083 +b84d2990b563d6d7fe1f4c1894989db25b81745090b94b1fe2ef708ac3b2110ef93d647820b2a51fcf78e3f00fef5412 +817d85b9f5e1521733d2b1fa6d4f4957ac445dc803f97fc495e20b819b14e651332f9e0573d684b854fd47824c53f0e8 +b09e18e97e93a8523101af594422fb71afc5b8826002314269016fcc1b44002d91bcb7c90d923d460f0cc03bddfe9af1 +b867cbede82102de7cf6cd0dae68506869576eaa66c3fc806e73585310602682fc912dc37adf5ff6f0f34a07831735b1 +b1126255798368b692f2796a3470ed16e5ffdee2d8c9e0f7ee3d2e92950c3e6365c32895171c3494aff2a6d6356f7e25 +b05f0a0996dec16335c770a5df3f0b08e20020c838c2caaa1d3a4a2490ede98552f5de349de2ce6e4c4a839731d80919 +98c512bb91c8fa191120ddf5d63c88076581cf41e15eec3c168822f12b3dd0ce4d6df74a7e3093d3e35cad1cb3135421 +84ce38fd97f7f90012c2c1e59a67bf9f465a7ccfb6f308bdd0446cc82b8a26ff7c30e5c7cc375011718cad1b31adaa9f +93139db52c9fb96dee97a0825f21e34c5d6d36838e1e42f4d12d01eacbe94426c85a811fe16ca78e89e08f1c27383d28 +81454037b1e7a1765f67e4288b8742eebf6d864d9b0f508ab44fa3243168ce0ed30cb5f33dfcdb995cd2c2710ff97a6d +828deb2a26efb2ff1842f735e2cc27162360f619b6e3e27a85bedf384912d4726bb2759a3016937973092ece1bf90540 +87e5a7d4e7bd301078f625d9a99b99e6e8e1207c9f8a679f8ebbbfb467bfa0b5f7ef4a4d577c7d2670efa88221153012 +b9dc9d0ea48deee201e34379447bec789c8924aecd030eeb93db159af77eff230976ef60ea9f4b4a9e9e95c1f9f4284e +aa6528268d46bf0627d87d58e243d3ac34b863513c725908a2617e4c6a46ccb1d8c8334bd6dd0eea7ffebec44259dae5 +8d26c9ce07293f6a32a664d31e6df9a7ace47e6c38001635918efd9872aceab62de7757b13b783d422eb67bd28ce7bbb +b0d3ca88d9829a7459b89b0dcbdb8bbb5180b00d750bd959bd110f53c2dd5d4db554b6005c4765fbe7ec5903669e5ebc +a94d1c72bf3b2dc6bfebc9dee40f6a89a516b252bd9f4fad96f156e3dbfc151a9b8a02324d764c7656d59230a18eb61f +88996e79171e30b16505638d8ecb25afd875e5f3cc3e29860937f2b5e751c66e78dc77f744a0cc454a8a655142a93ffb +af4d94f342665fe7ecda318de6cf1bc1c40c37dd83d060fedaf827459728152b5f0e280286ff5e6a0012036f6715f53f +96beaa7a2d565ec14a4e5cb895d33624c69da56b75c8d06ac729cb6d0cb64470ed4f9b0387083cd827b1609c8cabde8c +96b773fa2fcb7377bf71a7e286f37f1f24ee42cba5b4f33903c4566e5e5bcc501ea360e3c8435749107c3de84e272d8e +a69ac6218454c3f40ad0beb48821a218fb0a4f33ebade986d2fffd9a3900d8cfa613bc71676c46cfeaa5f644d1f239a9 +857f139c08fcc45370f448ce3e4915bcb30f23daa4134407fc6d78efac7d718b2cd89e9a743eec7bf2cc0eccf55eb907 +adeeba36af137fd3c371a2adbefea614c3ae3a69f8755ce892d0dd7102fb60717f5245d30119c69c582804e7e56f1626 +afa97ca3548b35aeda6bfed7fbb39af907ed82a09348004d5705b4bb000173270ce44eb5d181819088aa5a2f20a547a2 +8423bd2d07073b0e87819b4e81997e4d3188b0a5592621a30981dc0a5a9d0578fde1638a364f015078a001afb00891c2 +b92e9d4ec3966981ee574695d6e4865810b8e75313e48c1e4bc5eebae77eb28740e97ecc3e5c42040f9eb1ee4b13b0ea +b07b218321d54cecfcd2ed54a5fd588a6be8d7a5b6a66dff7facfe061222c40553e076e57cbdfa0bdb08e0a009c94ba5 +a71e1ae4d6096eac9ea4c21f621c875423de7c620544e520fb6ec3cb41a78554aedd79493cbd2c2ba4f0387f902ddd2a +807cdac291246a02f60c8937532c8969e689b1cfe811f239bfdee0791e7aa0545e9686cfb9ed0c1df84748e5efa5e3da +a1faeb4504c057304d27d54fb3ec681462384a354a4f0b6c759d4fa313253a789250c6b0f44f751b0718592637438a19 +996bcd3215182d49f1cd15a05e1e0a4bf57e264400bf14f7253c6611d2571de7130cce81fd28e0411e0a80e9054f4f98 +89d15b38f14bcd46f4b2dcae82b0e7bf9a35e40bf57aa947e9c4a8f87a440b5cea95229708de08ca596762062c34aaa0 +8d8ddcaf79374c750b8b0b3d196acb6bb921e51b4619876a29d09161ba82a42271066187211ef746f9f40a5ca17b75f7 +a3dc7f70f3a6c7edc483e712770abbaa94bfa3174cfee872b2cc011b267e0ef9baa1ab49e4a6c6c30dbba0e0a1237117 +aa9e958bbdcb192b19c43fc6fd34afcd754949fdada98e9f4848e8db0e23acb27d19dd073c951a8819000f2356aa22e1 +a4714e45ec853eadfe5c3bee7f683b81f97857bbd7833192a48936dd1460aee68f700a21658658b74b737c4fecf90c7f +a1ecab4215c1892e4a8ff3405d710163875e5dfef8a8cb84f5cac4e317d89c7696e3f496ed1747ca6f52b304190f4ba1 +b9b48943eca3686219575026d395b969e6ff8159dc5317005df090e79d26901984e40ae4b1af060ed3ff6f42e0417d76 +9644b9f90a66edb0396abd8c00066886f978ebf56fc22081031fbc9ce371bf9b04aa5a4ef59e59319b3a05bb7fb88b43 +b2bb14f1c055a78596488e4e2d4135a6470c1ee43961952160b8498f674a4d23040606e937c02c1fc23dbd47e9bd4633 +8c61f2fce9a42b94a389c7e52d7d093fc011099d0f4914f6d6f05b631df7b88182826edf9bbb1225971a080ca5c0d15a +aa6a7b8499cc7d256043eacad18528d38bf3be970bea4c6d4cb886690280bdb373688ceba3e506471e1d9493dc76f3f4 +8127703363b3b35b06762c2353d4de82b7b85bb860db1028d3640f46bdb78f2d104fa77ee3e0d9db83833d2b12a966f8 +b7b01f5909f2c66ae0fab156be5d79954e3a304615e1fe55945049dd4bd95f973bb3821117eb54db7e9ed1ee9a527652 +8be47ba5dfe212420649193490838670c40540e0ea24adbab18c4a66e7ac3dcf94f068dec2533b60e08c1f64e7533e54 +905a6c7e24b86aa54a05c329a6b4616d335bb0b1f1e9987562eee0acf82ad302c7c44981a1dd6b24c6121ca12fb92996 +86969ccfd91deed93b355a2c21319e3bb08cc652b741463bf68c626b7ba2afce3f7cc397f2fb74588c2893477c948ae2 +b5a9d20eb12c331d0d300fd4b85b0ac0bb74573178a5fac8ec9dce5e95acba07fab444260355ece442a846737a2dcd1c +a13497c11df21b11fc1a63b0ffdcf7f432da4dc2c98f8d07d36da4fa68aceb57af2158088e5b05e334fe0f264aeb7a97 +882e4597cc66498a45e86a2ed9ee24652da4699af00ad35f73b5e74fde6ac3cee70630962d5ddd86162d4aaf11bbc11c +b748858c2bafa4a14ce44af35195e9c52aa75e109719243bbe278095acbfd6a7ae7e084caf8dae6939039b5a4e8fd675 +83a2e0524507e74f51fe976441108f8226ba1b3a33f4e16ec45c5661ce80cb1840a93d17122cb8ca9e0f80d14f69877d +846cd2946c93ee5f24243d9ebc69936b3a1a6d59f45fec6c79b1eddf15ce30a8e73ad03cf606ee66baea3d8ff115f70f +8d98d0a3a94f6efe158f8423c041b546416145c5c2254bfa157efea0d1c99fe58acc7df6424ef29f75960b18d664ea4e +a39fa47e4b79f54dbf59d0b1726f1e78bc219fcfc56ad238c84b4b610e7892ff1e65d537baf5118a32f5e2eb80d5ee0c +8c30969a4519131de5e30121c84c04f67b98c8ad109fa4710dd3149cae303d51778add3f258f0482f1c89c169824dffc +af7f80d141ceb78b4762015de17fef49d7ff6202d292e9604deb508272ee7569f7fd5be3b2438da1dfecf0c26533ef86 +97cf82f70128251944d79b8845506975405bd720e150d836205b048ff36ba8801eb74cdcc6425f28f6bc0acec0a81463 +8c276c876eb88688957d1868bf3a1462375e608ff72b49870a5dac82cbf6584e00e3f36f236f732348a47502ccf9539d +964765f1a5c8a41d8025ddf56dc01b78424703d8a64a4e5539e477cb2445cb541c70127c561e717256d13f91a830ba83 +a2aacd9e21b8c8efaf2319611addea1b9f41430aee42e7f2a640cc693aa395287cc8fdc2806b76b577d84fbd05378ead +ab11eabbf5be4345a77323a3b75f9ee93b011fd2a9d0154e88183cafe47f82a7888666af16b40d3cb677c94bcc755ff7 +a0bfe715a7af5a29b1b6148b8cbee585d2b49fa6ce59bcd173ea3bbc60d71a62f9da27ffcbbd5a6da75502112fe44d70 +902e6cc38ee42245103d90b65028a471bc7a48b825599d361aa81d8c56e0fcf9fbe8d4c13802040d2cfb85b7e022eea1 +8832e2b5014fdef4003bdbb87e3298fdbdbbe49673f6b66e2373f1cb2605f9c4af2cdf9bfd45d1993208681d29ee1c9d +a7d39d3fa1ec1e0c87730fa43d4900e91932d1cafb36c76b2934907becf7d15a1d84d7234591ad4c322b5a24673bba8d +836ed5f09d99624204aa3aa7ac601980fda223f3b4b96b4a8fb235c574a3545d518787c12f81bd5851987f2860d41886 +94235e94445e6086f6e9331923262070a4c2ed930ec519eabb8a30133bd4fc6debb99185f4b668431fae1b485c5c81b7 +9828ffe20b9405f117dac044159be2d3c6e2b50ecdd1651d6a73f7633e6e2a7ba3d783ae939973604446d3a1ef0fb20f +92f03dc365dfe9154743ca70e6dd2758f064e3286fc543cf8c50f68effdf7c554bd17b3507c6ff4127046d9bbb5522ef +91ed07df479d8eb3d31292a0e987672a7f3d45ecafe72935b7abbc3f23493605134ce573f309e226c9efe830b6868220 +93bee582661e6d6cefeff29002afc2f36dd2c13dbf33f0574c35b290ddc426170a5f7f196369ad592efcd72cfb6f8fc0 +89a51467d966f48fed15dea5a12dda54d0015f69e2169b5e34f44c7b5a5d4c282d6f138116a0cd06a8476980e420f8d8 +b8ccebc14b6679ba2399370848864f15f63512fd6139df7359b7b93e82c1007fd85137ecb0597294b46643e1a9e7ab5e +841fa301567fc57b2cd09508ce75326684e12bfb8add671dc208f579b2500b93d5b641e9f59bba798ed4ed1259757f7d +b3cb45c15eb00b4ccb7013299f761cb8fefc17adf6db50e9ecb8abe927a3bc7f28e359e64693813e078e1dac800ad55b +96e55d3b9f445f5679e34fa5425b3e87cb221cfbdd07f8353868c7f7f4ba388ee3841cb9a1d638583bc20d03a9d071f2 +a7dee9377de740270c5b57cf86699004ba8dc2766af56b388b5cb0814ec71bb99ecf43ee3d82a552733854ecc7def0fe +b129dfff23b3c1c95ddb214c4711961fcb129efe2b6557ec9e116ada909593d0d2eec2c628434493393c58c52aa86847 +aed2670e201cb3e38a8be3c86735a4d76255e1e5a4c67b91df6ed262d09c8d10b0a3891da3e6ab934058cc9a7178931b +b20b8921ae52e5b3c94fa3a8b46489044174f7b897779e7763d6eb419e808d76705b7e7ba5131576f425aa81b6b0de53 +a7e45bbc3ba1bc36617291ba7663806e247f1b57a89e31520c64a90cbf8d426cac2e2f381338baf78c8f92fdbbcb7026 +a99e651e73a507e9e663e2364fcc193ec77e8afdc08c2bed6ad864e49b537ec31e9114ee72291a7657899f2033a849e2 +af966033636c2e9e8280d173f556fe07f8b6940bbcf6b2df7e2165c30bea66cced2596f6c17ca7c1aa0e614174953ba9 +b69ca7a79e3d55ef21e0ebdc6f0c4bd17182d30cf6290cccca7d2551c91c12b966020d8e40e4ee4179488c9809c03ae4 +b981cd36244e035fef043f70b1d7188d7cd045b4de0581c459fc5730e10eb7f3d5893b54cc4243849c0855e4e621167a +b20fea858a36921b35a3051ce787b73f70fdecd3fef283c15a2eb1bffb1dcba5991eee4a047ce4e87802da923fd9457b +b040e6f2e56dc1860274c263d4045837456f74b354a679f6b5ea70919835ebe5d32bf1f519e218730096c98ff396dc9d +8d2dd60e702c923a7204b530e7d6c193c6f93ca648c4f7bb38f4edbeb0aaed84184213afafb8db6aeb9197c24364276c +95dfa7348709e43d71285b28a0bfad3ca805b6ed4ae99753e9f736c79d58a35a3a50b42760ccdd03eda50f6e59494968 +b8585632a13f18c139a411bb2f02df809591834d127cd1ff081e26d0abfe0e3fbb54abea26538b25a0dcb4d7e969590e +b46ba47858a29c6d523c9982660949567666daf2582b93393a4802a9e077eedbc0d49d454731696bc8e46ca50c7caa40 +84b756b901b98a4404e58d70f39f6ccac877146c866732ae65e7e82727448d1550343bf7cdff1bfd4ee1ed73793db255 +83e5be888eaf877a2c755897410865f64a6d1169a8ccf0336092f3932abab915e542ab75a35ffe016042340d581ee987 +8cb274fc39285aed451a7def72cfbf73168ee10be02affe355a2bf87cf361a81ad284e9334cf00c5bf99a13d9f75e116 +91ff6220924b94ae13f50eeac16a159232e4f16a73fbd5c22c0e185cd1998403904d36bad203baa82b85819ee4a8ac10 +87f46e08e09aea2ab37b55fc300689d9b58ff3e72f1cffe023386035888f714fac4673c7c5193d3f3f3c568c640694f0 +835d7d84ca7641e1b15095830114aa6072fe12260d2202456cafe2308c22651af9ffbcf6b7e56af97167dd0c4e2a4cf2 +91202183f79794f114fd9e3b9bd05553c0e8985919965101a57d97ef666b028863e6cea9735af016dc1864f1542dee51 +81ab2b02a9b0a490a74ae615ddd4fe560734c1bfdde6b8dd13303c1481ba0e8ab14473535a93cfe4e824a0ab29445f8c +8a32d73f4fc006551d4e2c61eec6130355ec9b8c39a65c24ec1edc00e80155ca83a8ef2455e892521a3d47634d82a987 +af70d7b8f13bc90193cc1cfb0c400c4224cf10f1887848aa93e6380f7087782fc41a159926ab53c53eb95c2383b1a849 +989bf42f9d357c51774f1c7c0f7c0c46a8cb7398a74497141c32685be098e38b4230ffe833a6d880ec391a35b1a747b6 +94cb6715ee95700020c630b8c19e35f231de970219bd7e6ba7ced01899197da473b6c45cacfab0d652ddaf547b4ea58c +b12e3331f1f7d7458393a785e22e9a5e1d1daea521b4e78c0ee8ca59b41ade1735a29820e18f6afb2f2c3c56fecc16b6 +ad4b7cf654349d136fb41fb0dd65b588199f68b462b05f5c4e5c2b468bfaa6c26329033e3c3f7873dc8ace89cf873ea5 +a3279969e1ab596df0559ffc5ac7a6dc849680354e01c3f4fd34c6413a3f9f046f89c1e1be0b315d8b6dfab3d23d5c14 +ac74cc5562836ed89d09a9ae6a3644c936d64bdda9e77659d9982f1be29541b03ef2723236d5465e398373ea19a4ccc6 +98138ebce1af531dd8b631b3e74c84f0c700355a2a9bde31e5e51bb10c8bbd766559c63f6041f4002568803fe08438e0 +9006445da131349fe5714e0777a4f82a82da343612589a0c1596393e8b6894ce1cf42784f95ff67a8384ffe1f1a4ad76 +88502a84a85e4ce54cfed297b5d355867cc770a8ffd0714a6f23b1ab320a9903c6e42809e034bb67dbf94c4fc0d9c790 +aa8b4bf123d1a6ccaa44b86be8f980005f2a0a388a76cb111b0e85cd072ef64167fb0c097c7b23c4bca64c0260f6cce0 +ad49eb35dfea9feabb513a78dd1152ad7eba22fbb02a80cefc494a7037699c8df81202dfec12acc1b9e33ad680cb72d2 +8694da730231b29afd5196371ddcb15b4dcc499574bdd063f4864ab80749833ea38ab8b0ca1629a367fe378e87a60a86 +8eca7b488e810c479e7e32e24b8afcd837f7df183fe4f621a0336b53a9ed77603c84bdc365d8be68179a32b71a1deb7e +8875cd3e23c7e1af55af1b091025a08255743984186770bcd43f30b4a58d175cfdf1984bad97a15e08dac2da27198c3d +abdafcf58ec72997e494d4714645f40d09dcd0fbd0733e640eca44eeea67c25bb0c270299c459991f2fae59d13b4f4d5 +8f040970141e61489284f3efd907705eae6ec757fe8e1d284eac123d313e9ac1e8dc14ae3f04d281e1effc49d5d2f51d +a7ff115f0d2dbf66c0e8770b3d05157b37357b9e33e9a447f0f3fa9da69ad04e371fd1e4848cfb9e8d05e3165bd969d8 +a39b1a8c39d317fcc97bf6c396e6ed4a85640aeeadbf45166bd02bc3bdfb6266509159c03afd492e642384c635b824c0 +a2e1b90f3dd2d0038eaa5be52127844ccf35d997143179d95ffd3749c0896398b130094d01eb1bb31ffe80ef34b42b48 +a2bbe31f89b0c3c375ffaf63c8b7831860a921d5e388eb7907dbf61f2601ea40db86bb3952ecaa26a5eca4317a848ff9 +87d885bb0f2ce04b40ce94d2557c15f1698dc652e938f9a2d69a73ccf4899e08eafa1a59a20cae92823795f5b94f04b9 +8f7746370f8a24a2889d351f3e36b8a7d60e75e50e8f5abeea7dafc75441e95915721654e61ceac51bb6f112780d352c +a7272847526ed3d9e0d0fea1d8685b07b5b908971490bf8a46748c8b1783c629b8644feb5bac772ae615daae383d5e72 +978c9aa2996d8bd6fda7e0393fa8b38747f8f99712427705c00f6e9a12c36f8d8b4cedb03fcb9867155cbddb5200e6e1 +a4dec4a2354b2b32434c5bcdc380bf84580c6f9940f94dc0498a5bfe89c675a0921e66b807a3d859a6059a464cb2a9ac +99459ddecc7abce437f68722dae556d8ffaf8ed974f459e52e6d4a64f176caa4d42c2f2ec57e8a5b5f2034638e8acb0a +928c68c0c9213fe6258ab5bb0c693d97203d15da359784de7824dec143212da57d062a1fc70a79172cee31adc7aff382 +aad3f318f1622ea87e12541dfd982d71629b8f1ded4c301f9f6b6af9432716ad057773c33bdaa6f15dc151b0ee4505ea +8eb8e978f149a983fd6ad01773f9aacf57bd0cc622d8a301e404184b37e610123dd081faeda571a0ab1f149a3960af10 +851e7191d7b94bd422bcece5b92609fc1b1c8556229bc53e32963b2d2fd1cacd8ce5da9040b599eca6e610540f8a7987 +9414157fe9d50e5a0b5a7397417681bcb3a651eec1cab63f2a88d5df68ab1fef6e4c1d7ba657cbaf241a7cb790297633 +b5cb2dafdc5408959780754a58b2da55b2a9136672ebca42f34da4e329ddc89360e7218cde3efdbf784ddb390deacc57 +ac6b70f65503a8e94b773fda3e72615745824930114fe72b6d833484285462392617c1b2eea4a250fedbee88f503f3ba +b0829a5312f9ac6c06fddee2f835a3452fe994f6d42c9edfc390d7d5b3240ca544433b544cbbddd6516b38a6d5d7c21d +95f8e2c59905957e34d53be3d6fb85732f834e2cb9ab4c333fea2f502452a87ccd035fc9075d7c0bd8530bb0a0c96527 +b93f279b7045f2d97c674495f6e69a3e352f32f43cc60300193b936c2850b2805c15457251f7e3f633f435cb2b60405c +915abf16cba1a0b655b92a8a70c03e7fb306b86f3bbfb66967ca63e64c003b59c7a5953675efa4fa0bce9bed536b6700 +ac2047f50a319d09df1ec44d71afdcec5ac3bd2765dc98aba347734aa780863545df9f6d71214d443e3f37edc0dae45a +ad49c74ddb24c8a26b14ec08bc807313c77c5967fbb36237f55994d7511bbac8d7e7b9b8ec53eb1b3b066989f078dbd9 +961483105f605e959213fe9e8a52b76dac62d7efd2319ec71fc4e92d68fbe44cd2f65d7adefb2eb64d591b91648b8085 +b67fcafc97d8df2b3075bbff7b3d7471dbf1f3048f309e55d5e2c5bcbc7a73aebcb0697859be9f387cbc7ce98041e154 +8da70ac16468cab6066992389cb37c79ff5e0babbe67d76878aef9408b9597a3dc2eb5de87428bc761a0d78957b0eb28 +aec0ce89770d299b631f15ae12f94b1e1014ac57d38fcf037c2c7712d770d074affa06e97c60691bad8733874b6ad2ed +8b702c85fa4c915a09fc86507f44d7aeda0993b77af87780d70cc98d580c6e996b64b7c16cdb4dd4562cb0f75da36ee7 +aaeb43aa472aac2253e211fd1066c3a5422ea041cef20168702d0618a1a742a44f7fb30a76677640fea1a24e7fae1996 +a8820e92825d6e02b9b4ad5ebc86161d3244cddd3d244333ba1576b6ae10948145b68d9e926bf6b7a2c25dab4cf43f3e +8ffdae28a1f1d15d7ffa473628a66ee9a739073f59ba781248286b39cb8f7255f66d62337064246713cbb5017e615174 +adfc5dd142b7911326d8424881d5d92006f3b17de4cce91674d6ea37f00fbb266c791ac13f6c7a0f61d04f2a952e6a04 +87f98982444bf661f539bec73a10256f079a4baa88a1cea0351ae3de929e1c500485b2d1b5d933063cd7d9123d5050e4 +8f217ba4dd404c5ee384f0c9a126686db001ff0344c01c82174c5e5ef89d1a241b146008c534b13a0da6c8afe7450fbb +afc85476dddaf1cbb4ba8b22186789f3818c7964f9f613e55010278800cd95422702248bdf9c73760702ef24854795ec +a59e0f6ac2ccdfbd01f002008034390c0ea78716f5e0de4e474e3558755705c9c7afb6e3c5c4370e7bbc85958a9c7a63 +97c0695c58d792ec31d9b86d3b2fc1382f0855057b24d5f6a54c41f76f9e2f52882cadc89a8b2f121530e7f1393faa95 +8e49112de0b2649c08a96cf737af68fa8055f1af594846a2d0534c94df6f926f200405edaa6e6ac9db7e380707a2571d +99a1bd83a7ac5f8d77ddf044c80ebfc5745b998714696d67b94d185c97e9d6db989bacac646d9def463127a8b2febc00 +aba80725f9f9f7abe10760eca73ba427ca8df864a157122eb9af828a05b0199de3add02019a297750bdab5380e505c58 +ae18f62573275c1eb268f74c5e54e8958547f9e7d1d36a05b084eb53e5704fafe2200b8aff95cc7e9af5be2391c42b7c +908b8031d09d22b2aefeaa876a998e0a97c7a1070aad9e9c97836cc5aa6d2d5ef94230e1222074837b5e21b4e6490f01 +b3132282e8b41ca6789ec5c43c1fecf3a65b8eefbc2f3d10f746a843b9ba4ce6db664678e75e424f7b11a00c1440de15 +a1eb49440cc106ebc09cf198c93e8070271eb5a936d31c04858a2b311a037350100c7957d5545c9653f396aa968b91f4 +81df6ad1bdd5eee4cc2f94318467b8602d15cc1be2b48b09ade12cc46ee05cbaaf77a20397e5015030b1f1db5dd9dac0 +87236c68a2a93c8442d15d7f1d1dc01d1fd123439c183e1d843f4ddd2bcf638c128f66f1ef9b710e5d1f64a52726007a +84f2e7f85563bb2f61b10a712c7605d63f79af5be0dba056814fd3efebc20e9c53227c56577b72c68d185571b775eff6 +a36d4ae06688ece2927aeb2c7f058a3cd2aa1de1601282d4e688e1d76ef20728b892928deda2314eba41675eba3912f1 +b8326dcbcdcfce017b263c456c47692fb476c4225c95981666fff0b7d4522fc23b7f12273f0f47cf0442662124e6648f +84c66463ab277cda2cc7007d0509269e89cdd41c5e0d3773a92615f0fc5da63811186b05d7a11088048a5d4834a7e0df +b20d3571d970712ef4699b0e7034fd269c361f53e1572e2ea2676b4245e992d43b8b5931a801439a44d977a988cc360b +94dba6007e6d4998ca1eb84aa8e2a7e9f5c164b9d80df2825f2208ce5640a05aacac2e4f08918268990f43ae1ccab69a +a1c25f0b3ef9d1982153207570d9ce8d692e1b6963b509958dc4d9bcd80074bb221c46804a6d9a29e76149cc7787c282 +8857748fcdab1199fc96084323a81d3bd8b5a7f0b1abc5bc3b5252a19268344e2e7d2d086c90fc9b5fa4b92feedb93a4 +8b9c1d841447354b6c086549e4d1d435ab64c13933488c34bc30f0f6eb36c5c5b838b7b6bb018542247edd1ada091045 +8f5b655416da0e719a204fc567e93792c301acb4374cf7bbabc6ce51dbeaaadfd75c2db0e16ce073ab8e91fd3d7ea9d4 +90f2846b19be46a75c5cd0cafefcf9192e6fd80c479e8d6320c4b8d8d7d96703c9e77ff31a67afa9858e6b7bde1f7cce +a53e383947fd98aa1a55ac956214b46b20a52758461e8ba41341a23a835ebb713038bf048edb1202bbfd0b56a96bf292 +9542d7debbcfb9cda6fa279c699a7b655c03b9a9b456a5d3cfc41a826c94eafa43e01155a29e39ff0bcd965f4c0c512d +a43792864ec5fc549f7afc02622454afc0e425c310c4039ba615067243ebb26a4c7ebfd19bd4d57ff412a4bb2a7958a0 +b85123950e30c048465bf32365d24a5d4b21fffc6183cdbf71643a07b87463989b72dd9a6a47f134856f704909a6b38f +944ea689aec1376f855c0bc9c51378ad06ff758a2c075b95a60b535b88b36eca0be11e4edb5152e98cb2137d6e749f27 +a6bef52cda22325e4c62d323e2a0e3fa91c5552fcfce951edfd52ad6f652bfdcc2341f1cd349e6b5d447924dc569bfe2 +b56bff8ffe981bfcb30791836da10b87f2ccbe17ed969e7f7a650af07d27ae0223805b1264d985148208483be50578a6 +8b209cac898dd580c82d854a553e2517497ad1a4cd198e1360b8b50639b380aee70ee4b87625d9b2278228ff644cd25c +877cce233fec74c7158b3c5bf108365e98238418b8a71f058f1aca44a0fd3a1021e3e9025bd11fe244d9fe0f5034ce7f +b1b871aeedb03d6f6accc99816b89f5958178738d8d8cd9717527d04363c80fdb5f6848122ae19fdbc450cfa11e753c8 +858aca51b9e5b0a724e88688d5124eb24c9faf01a3d465e74d31de6da315f311143f22f60201ea09f62c92f61f09d889 +8521d409615dfc8c8289e00f6aaa6297c2c4e1439b25952afd76aac641b81c70b9cef07cd58c1c0198382bddd2bd8544 +88647c3e41666b88acca42505f1f5da226937e0522b538fe0cebb724e9a99730ca2522989e94a96cac94109aef675c0f +b417fdaf719caf38854e89ce52031b30ce61a632e6c3135adec9002280e022d82ab0ea4ac5ebdb21f1f0169e4c37bcda +9367a6feb5e23ea2eab8ddd5e7bdf32b4d2419fad1c71a1ed327b77362d8942dad971a1c2e6f7073885149cdf0a0c339 +a71c5c08d50c57d094d6a4f02e97d3799bada92f238ffc07bd223bbe8379507b7310d20b28f5bbbf331e5e153515e491 +9630a9a3bcb044b51299c4d3d3388a4ff47308dd27be3229601985478c0f6b55faa7e20815d8694f910611396a9d0d45 +b0bfaf56a5aa59b48960aa7c1617e832e65c823523fb2a5cd44ba606800501cf873e8db1d0dda64065285743dc40786e \ No newline at end of file From a6c44c5551226ce5dbc05611f2c578f85e50319f Mon Sep 17 00:00:00 2001 From: textml <37575478+textml@users.noreply.github.com> Date: Mon, 10 Mar 2025 19:13:47 +0800 Subject: [PATCH 1168/1197] feat(crypto): change ckzg4844 path --- .../tron/core/vm/PrecompiledContracts.java | 2 +- .../common/crypto}/ckzg4844/CKZG4844JNI.java | 2 +- .../crypto}/ckzg4844/CKZGException.java | 2 +- .../crypto}/ckzg4844/CellsAndProofs.java | 2 +- .../common/crypto}/ckzg4844/ProofAndY.java | 2 +- .../lib/aarch64/libckzg4844jni.dylib | Bin 259496 -> 0 bytes .../resources/lib/aarch64/libckzg4844jni.so | Bin 251848 -> 0 bytes .../main/resources/lib/amd64/ckzg4844jni.dll | Bin 288032 -> 0 bytes .../resources/lib/amd64/libckzg4844jni.so | Bin 293960 -> 0 bytes .../resources/lib/x86_64/libckzg4844jni.dylib | Bin 275232 -> 279944 bytes .../zen/KZGPointEvaluationInitService.java | 2 +- 11 files changed, 6 insertions(+), 6 deletions(-) rename crypto/src/main/java/{ethereum => org/tron/common/crypto}/ckzg4844/CKZG4844JNI.java (99%) rename crypto/src/main/java/{ethereum => org/tron/common/crypto}/ckzg4844/CKZGException.java (96%) rename crypto/src/main/java/{ethereum => org/tron/common/crypto}/ckzg4844/CellsAndProofs.java (91%) rename crypto/src/main/java/{ethereum => org/tron/common/crypto}/ckzg4844/ProofAndY.java (89%) delete mode 100755 crypto/src/main/resources/lib/aarch64/libckzg4844jni.dylib delete mode 100755 crypto/src/main/resources/lib/aarch64/libckzg4844jni.so delete mode 100755 crypto/src/main/resources/lib/amd64/ckzg4844jni.dll delete mode 100755 crypto/src/main/resources/lib/amd64/libckzg4844jni.so diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 1245bc23718..d3050b911c4 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -32,7 +32,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import ethereum.ckzg4844.CKZG4844JNI; +import org.tron.common.crypto.ckzg4844.CKZG4844JNI; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; diff --git a/crypto/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java b/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CKZG4844JNI.java similarity index 99% rename from crypto/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java rename to crypto/src/main/java/org/tron/common/crypto/ckzg4844/CKZG4844JNI.java index 782e8e3710f..6f819650a81 100644 --- a/crypto/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java +++ b/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CKZG4844JNI.java @@ -1,4 +1,4 @@ -package ethereum.ckzg4844; +package org.tron.common.crypto.ckzg4844; import java.io.IOException; import java.io.InputStream; diff --git a/crypto/src/main/java/ethereum/ckzg4844/CKZGException.java b/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CKZGException.java similarity index 96% rename from crypto/src/main/java/ethereum/ckzg4844/CKZGException.java rename to crypto/src/main/java/org/tron/common/crypto/ckzg4844/CKZGException.java index cbf087364d2..8ea9edf4548 100644 --- a/crypto/src/main/java/ethereum/ckzg4844/CKZGException.java +++ b/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CKZGException.java @@ -1,4 +1,4 @@ -package ethereum.ckzg4844; +package org.tron.common.crypto.ckzg4844; import java.util.Arrays; diff --git a/crypto/src/main/java/ethereum/ckzg4844/CellsAndProofs.java b/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CellsAndProofs.java similarity index 91% rename from crypto/src/main/java/ethereum/ckzg4844/CellsAndProofs.java rename to crypto/src/main/java/org/tron/common/crypto/ckzg4844/CellsAndProofs.java index 7f57431acab..5d47538d73a 100644 --- a/crypto/src/main/java/ethereum/ckzg4844/CellsAndProofs.java +++ b/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CellsAndProofs.java @@ -1,4 +1,4 @@ -package ethereum.ckzg4844; +package org.tron.common.crypto.ckzg4844; public class CellsAndProofs { private final byte[] cells; diff --git a/crypto/src/main/java/ethereum/ckzg4844/ProofAndY.java b/crypto/src/main/java/org/tron/common/crypto/ckzg4844/ProofAndY.java similarity index 89% rename from crypto/src/main/java/ethereum/ckzg4844/ProofAndY.java rename to crypto/src/main/java/org/tron/common/crypto/ckzg4844/ProofAndY.java index ada1034ee4e..fdb093c1232 100644 --- a/crypto/src/main/java/ethereum/ckzg4844/ProofAndY.java +++ b/crypto/src/main/java/org/tron/common/crypto/ckzg4844/ProofAndY.java @@ -1,4 +1,4 @@ -package ethereum.ckzg4844; +package org.tron.common.crypto.ckzg4844; public class ProofAndY { private final byte[] proof; diff --git a/crypto/src/main/resources/lib/aarch64/libckzg4844jni.dylib b/crypto/src/main/resources/lib/aarch64/libckzg4844jni.dylib deleted file mode 100755 index 733aca4f74782cff6d4e47dadc4b99d37ebfd713..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 259496 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 pR`B~~GbooT0jA9(Mh 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±2@DOFMH$!0ihhALUl}dIEU;{qtSZRE%7v0I z6&Cpqi-zUS&$T?chRlL*p5cuIH85k=EG(XIc|uz(YasM{@^gOLkCmchRHfQLqYC(t zwNdPxcC2a74^tCR>Rf7CEpRS1fyLxRzn29ai9szizFP9{{xuxSMu zi+ud_N1lOMoL7K+yf7SzKTwaA7dXT8B>_-fHY=|nTSw8>80cQN^2RI5R5C41GxKRf z3Nh;`@amG(PVakZWc&+&E;%ExRHLGXUnw zaNGO7z(1Q+l$JTu2*feF^2-|Z#4ighO2=vrELD?0)@gm zu8=X`Bq%?yV_v{;O<=x%Pvv{>E5mOX(=oK*?O(nOOS~0ijKZlr77wJ9sb>|t%=CH% zmA6)E7)YndC+zZwcw+=VbYqJ-PW6&?8O;{S-H8o z>v~}&0IGx|%^$j8e(s%qCPV^!9#>|unuqCfc2UNH#n>P)CUp4u1K))0#%srw#VPfu#%Ml$cSbTX#MnP82upxvF6k{fgOG!-|)PLZW zYD-1fg$?Q4|7`db2;Vy!O8x);{yzu)UvWSQBe7qEy>RYRCLpbLKZYGlhqxLrUVPtO zzh_>(w|n1Pzx(3Q8>yAkSW1YM`uANdc*(5_{&)ad5A2;CE z*#K6nG~hTA;Jr2&a2#3jUK%fLp)C!b&a!KGcf^zd2;Uag@k=O)}tvy->)% z0XOYlx&i;*D4%1%HyH4I18#i-$k&Sv_(Y?8i2?t}fG;!P-x%PZ;nx1AfSWCm3-47Lj%J zHQ?V`K->oy@RJ67xB=&HMp&22fWK=2aUW~I8x8m*1K!KPGtGd%XOvGj;DZc!jsbTW z@O%T#vy9fY*nnH#^7CDZ0Uux$#(kLqx6W$v^-2T&sZsuM1D<5SD-HNH27H47Pd4Bi z4LHA{vaT%#97i|3SB(M3(KYY2(|})Q;Mr}!ab(VWeQdz_yH(azYrsFTfVkHi@D~jD z5d&_WW##Mm1jj$mEP1`^j6=Aevx!w_mTcWn<4E(mvLkpGX%{OyogLE@SvSg^V2}Th zb*zMU8#~!uO}NWX6Om6b^8Jy|H1dOxFEjGPkY8`)uR?yCk-rA{IwPNgyxs0=|2pJ*8Ts+Z zrx^JgkplaVho^0y$r-pEf!ew&fM1Nk~5pNYKP;cI^;^1Y1wY~)jn{CwmyjeG&} zWk!A>^6QQK-NFae!Y?Z6!~pN{@=*g8TmTo?V-N*ze2v3 zkw1idijn^h@|i~dd*sWE{0ZdO8~IbnZ!_{|k*_oI_GGm0^tB&?d@my(j(m!d?|^)! zk?)LrnURk{e!Y?JhWs`oe~Y_6T45Gm-CQ34cXI$ojgA40Ryxpt0cyDsM(u$tV z$&YMBc{|!lIWVRvQ`WV6>ndOQH|Z;nMu?^^z?E*FFv4ZS&!LjOnlVi!s3U2*C%Nf% z^zq}CmemR9N4mY;h@%m%rZY>nN&jm3&(F}8GfVzfMSSE7aIP%;a7i6Y!^)?4%Rz1(I)9}3Rlxn^b^1Dxbm1oczOz_+u7CCBy6KTT!#Al0IPLGdFmWp zJjW&`S2;!~TGB=Qhi8`jwd%yJ3eT~L_A25!=CCCa*HMSv({rxVjo-WRSok&o-wBB? z+OrS%oWDzv?GTQ&hLwolQBQbMzHz#e-XZuiA!gYTLxBA2W`}d~{`V%Gl!*Z%W z3f3FreE|Kn`os6CKWG#EAPOO99EM`N0t z4p$RCW!cnLTWrVbPs*ln*%oE#*u+$fQwngitsNWEF;1laIL6}`#%34#L7Dk)`w`<1 zkfAOf)i&ig-sAkek~{K*xO>(_xSvNmC-E%MkJX`K(>_Nm%0_!W1)Oy;j)}y>v8#hT zI;#|pT9o@O%4~MxCuLBVy7vb1e2$0g#G`#LPg;>5(jfINvVEH}L>kXmhW0z6p%b7_ z>x9K~(r)rv>BSDI7o_=dP4oA-TQs-UUvFQ2NS1a+xR=2`neB0GDXT5pZO}o;QL1n^ z=h>@H&2nJugCGOJkg1TWu3Dx>P^Mr{`hkzjAy?!R^^W$5bWujlzEQr8O}ws(vUTFt zYk_k#aHm!^=cPcdl-)wxZpxRlIz`IFKFHTeM=<0p$U}KMfxLw`>>k%6s{hbOls_0M zq+YO1-@7RF4r9!E-B5?JdjWWO`u{>^ulAGK7$vj&l)SNh;Sxf6pJHG4J7S?5t=m`1PHS>QJ)zvVAUAE5;rl>4 ze9R_}tb#vYhVkl)7^c?Y^t_I~mmuF2eP0WoY}!}KdQa4$eA9-TKF0C^z3`rOQa1H) zn|`=uyU(vRra94%Fz8Zv)p3+3uFar>_^Z%%RhZah%0F!^WjDUWb!SGnm`eFlW9%2N_J-o85cpp5 zs1-X(xU{2}bvVb4l5hB3?IZt<9mSe%6mhp^dx%&1PK*cpZ~4y4QO9aC7&ajV@kCZF z?7NOBMvKbH&8L;Vwbh@t;tC7zPm%lci7QUPFV@0u9Gf^E@-q(hbF7RrAX`$lTT&g~ z*r_?s3ELWmGT|s20aIU_K^pKWe=b;;6t(Ey0dad;*2;+X)|FHfro}%xt_-WZ>D=x2v+#H)Y0s3$~^kO{p zV;o`+twX5}sYBjz+0@ZHF0~G^iF~*8nsXi*>pc@G$7!F@W(~@6zCc=(Y(+zMqCAZE zNSA1Ck+HtCDXqk3UVHV+PVO~`&sgpU?OLBmxBGm`?TB>Wk8&*zpN%**%LzV&fgj

eb3FKa*a? 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 (obfG_sY7Z^vvK%e{PpegF7DyBD5>IZGo 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 diff --git a/crypto/src/main/resources/lib/amd64/ckzg4844jni.dll b/crypto/src/main/resources/lib/amd64/ckzg4844jni.dll deleted file mode 100755 index 7be02e81985a87c7970cbc5805aeea3ff67eb624..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 288032 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

)@ks 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 z¬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ñ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 MMKuBFySz1^9(oot~ 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 diff --git a/crypto/src/main/resources/lib/x86_64/libckzg4844jni.dylib b/crypto/src/main/resources/lib/x86_64/libckzg4844jni.dylib index 7ab7c008aa9a8eda14deb34c7503033a19a798da..9b8a05c4ed7714badc55998d0ce0c8ee0996b979 100755 GIT binary patch delta 54549 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 delta 51406 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 Date: Mon, 10 Mar 2025 21:21:50 +0800 Subject: [PATCH 1169/1197] feat(crypto): add ckzg jni files and tests --- .../lib/aarch64/libckzg4844jni.dylib | Bin 0 -> 259976 bytes .../resources/lib/aarch64/libckzg4844jni.so | Bin 0 -> 359168 bytes .../main/resources/lib/amd64/ckzg4844jni.dll | Bin 0 -> 299844 bytes .../runtime/vm/PrecompiledContractsTest.java | 2 +- .../core/zksnark/KZGPointEvaluationTest.java | 27 ++++++++++++++---- 5 files changed, 23 insertions(+), 6 deletions(-) create mode 100755 crypto/src/main/resources/lib/aarch64/libckzg4844jni.dylib create mode 100644 crypto/src/main/resources/lib/aarch64/libckzg4844jni.so create mode 100644 crypto/src/main/resources/lib/amd64/ckzg4844jni.dll diff --git a/crypto/src/main/resources/lib/aarch64/libckzg4844jni.dylib b/crypto/src/main/resources/lib/aarch64/libckzg4844jni.dylib new file mode 100755 index 0000000000000000000000000000000000000000..ad11c215f34bf5e7706d9bb8308351a9d8315c84 GIT binary patch literal 259976 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�O71r%HE6S8RdBQXNdn`&B=!ghl1bTP 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

5>{~YQ2 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 V;?Q@=>ZkwfqNG1JkRWhr{vBp4BEA3s literal 0 HcmV?d00001 diff --git a/crypto/src/main/resources/lib/amd64/ckzg4844jni.dll b/crypto/src/main/resources/lib/amd64/ckzg4844jni.dll new file mode 100644 index 0000000000000000000000000000000000000000..5dd62ba322aa903663b9865a28644468ef487f2b GIT binary patch literal 299844 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

`-al2-bxjL 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%0A5RIOzn6YqJ?+C(z>i>dZu(=0=Jx{Tlo7kA}C2B znagHJQWSc9q>{>-<^6=r2N)t2*BjAD`tY~~I*&wO7Cj?sj8x;fc4P<9Pc?@J*6Bbo zFY;bnxzMe*f(^u@9KA~%57u(+L(%JSTNm?%?0!7|F+?{qvh?&muVJbzd|yYoP`IKQ zXP&uu69%9JDoAy2+P&u3cy$7A-$j#Gjl?kmdFpX501pSeUuRn|8?-AT-Xhm#3KrC@ zaMzfpA>aZS9$3&?W^PdY8c!Mz<G;Y=!r=?R;;doY@o?jl5W8*e>w zKd4?+#1SsL(<_racIj|?Ji2#=K%Hd;dAe+6O2i`{qtSp;{CyF(<;bpz+*GXjVqBzm z3Ox-N!z5n5^0X~_tE<3S2P@YtyJ#1lS?@Rboj&0RKMII@`YH>E1<>m z=k26b4?|6CB#ZNM?;w-4f>3^#LPtTGrrvE0J@Ru9GlziHx5-$OABvi(Vex*{9{FU0 z-xrVW##_OjF%}Paq$&sL)El*g_gP`d`|>J^jklQP;HT=Gf=j;R?>J_ECtI;qUo)4K zH*XaLvZS5~l0BB{v6`WwZ{;(g&3Mc(8K?G2J(9|$tns~leMtlq%FbWPVEV;sSvPJ7$jJibi@ygpb3J*QtMo;I8nDKEjOh$B(|8}= zmX$yCF5hA=-tg23nFf@YFe=$U#84dA!^I4m?U46OAH~?G+#^fASAA(5Ju;ut zczR?$T<|<1!$?CtkqWj-**g?$`=0(m=2kDkJm9yAm|E`I)R{+@u?pVRMW;)o#KY9u}a#} zy-HY|itz%8;6c~KKPIL^$vYN^hANDk=N;&W#O vXKltzg@0&Q=N&Ig$aov@T?zSNpT%QjKKdF8;Nv= literal 0 HcmV?d00001 diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index 0f1b8754fd5..4a7b63c8aba 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -1171,7 +1171,7 @@ private static byte[] encodeMultiWord(byte[]... words) { } @Test - public void ckzgPointEvaluationTest() { + public void kzgPointEvaluationTest() { VMConfig.initAllowTvmBlob(1); PrecompiledContract contract = diff --git a/framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java b/framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java index 24e2f9f0f1c..2aa90c602a0 100644 --- a/framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java @@ -1,21 +1,38 @@ package org.tron.core.zksnark; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import org.junit.Test; -import org.tron.common.BaseTest; +import org.tron.common.crypto.ckzg4844.CKZG4844JNI; import org.tron.core.zen.KZGPointEvaluationInitService; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertTrue; + @Slf4j -public class KZGPointEvaluationTest extends BaseTest { +public class KZGPointEvaluationTest { @Test - public void testKZGPointEvaluation() { - KZGPointEvaluationInitService.freeSetup(); - + public void testVerifyBlobKzgProof() { KZGPointEvaluationInitService.initCKZG4844(); + byte[] blob = new byte[131072]; + blob[0] = 0x01; + byte[] commitment = CKZG4844JNI.blobToKzgCommitment(blob); + byte[] expectedCommitment = + Hex.decode("a70477b56251e8770969c83eaed665d3ab99b96b72270a41009f27" + + "52b5c06a06bd089ad48952c12b1dbf83dccd9d373f"); + assertArrayEquals(expectedCommitment, commitment); + byte[] proof = CKZG4844JNI.computeBlobKzgProof(blob, commitment); + byte[] expectedProof = + Hex.decode("b7f576f2442febaa035d3c6f34bbdad6acebcaec70236ff40b3373b" + + "d2ca00547d3ca7bb1d0ed3e728ca9dab610a4cfa4"); + assertArrayEquals(expectedProof, proof); + boolean isValidProof = CKZG4844JNI.verifyBlobKzgProof(blob, commitment, proof); + assertTrue(isValidProof); + KZGPointEvaluationInitService.freeSetup(); } } From ca576307c942de20bc97ede8dd1fe4b0d33e05b1 Mon Sep 17 00:00:00 2001 From: Liulei Date: Mon, 10 Mar 2025 21:42:23 +0800 Subject: [PATCH 1170/1197] feat(crypto): add linux jni file --- .../main/resources/lib/amd64/libckzg4844jni.so | Bin 0 -> 287584 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 crypto/src/main/resources/lib/amd64/libckzg4844jni.so diff --git a/crypto/src/main/resources/lib/amd64/libckzg4844jni.so b/crypto/src/main/resources/lib/amd64/libckzg4844jni.so new file mode 100644 index 0000000000000000000000000000000000000000..047cbd6daab82aeb2b95862575ae1fce22325dec GIT binary patch literal 287584 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 Date: Tue, 11 Mar 2025 00:00:58 +0800 Subject: [PATCH 1171/1197] opt(crypto): opt blob precompiled return value --- .../main/java/org/tron/core/vm/PrecompiledContracts.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index d3050b911c4..8a1e7535754 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -1,6 +1,8 @@ package org.tron.core.vm; import static java.util.Arrays.copyOfRange; +import static org.tron.common.crypto.ckzg4844.CKZG4844JNI.BLS_MODULUS; +import static org.tron.common.crypto.ckzg4844.CKZG4844JNI.FIELD_ELEMENTS_PER_BLOB; import static org.tron.common.math.Maths.max; import static org.tron.common.math.Maths.min; import static org.tron.common.runtime.vm.DataWord.WORD_SIZE; @@ -40,7 +42,6 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Triple; -import org.bouncycastle.util.encoders.Hex; import org.tron.common.crypto.Blake2bfMessageDigest; import org.tron.common.crypto.Hash; import org.tron.common.crypto.SignUtils; @@ -2204,9 +2205,9 @@ public static class KZGPointEvaluation extends PrecompiledContract { private static final int BLOB_VERIFY_INPUT_LENGTH = 192; private static final byte BLOB_COMMITMENT_VERSION_KZG = 0x01; - private static final byte[] BLOB_PRECOMPILED_RETURN_VALUE = Hex.decode( - "0000000000000000000000000000000000000000000000000000000000001000" + - "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); + private static final byte[] BLOB_PRECOMPILED_RETURN_VALUE = + ByteUtil.merge(ByteUtil.longTo32Bytes(FIELD_ELEMENTS_PER_BLOB), + ByteUtil.bigIntegerToBytes(BLS_MODULUS, 32)); @Override public long getEnergyForData(byte[] data) { From c9b7fbc47eaacff5526c77ec369cba88856ac0b0 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Sun, 9 Mar 2025 19:15:07 +0800 Subject: [PATCH 1172/1197] feat(service): exit when params init failed 1. The node is witness, but no private key is configured 2. The configured rate limiter is not working as expected. 3. Configured auto-stop block time parsing error --- .../org/tron/core/exception/TronError.java | 2 + .../java/org/tron/core/config/args/Args.java | 5 +- .../services/http/RateLimiterServlet.java | 21 +++++--- .../vm/BandWidthRuntimeOutOfTimeTest.java | 1 - ...andWidthRuntimeOutOfTimeWithCheckTest.java | 1 - .../runtime/vm/BandWidthRuntimeTest.java | 1 - .../vm/BandWidthRuntimeWithCheckTest.java | 1 - .../leveldb/LevelDbDataSourceImplTest.java | 11 ++-- .../leveldb/RocksDbDataSourceImplTest.java | 11 ++-- .../org/tron/core/ForkControllerTest.java | 2 +- .../tron/core/capsule/AccountCapsuleTest.java | 2 +- .../core/capsule/utils/AssetUtilTest.java | 2 +- .../org/tron/core/config/args/ArgsTest.java | 6 +-- .../tron/core/consensus/DposServiceTest.java | 10 +++- .../java/org/tron/core/db/ManagerTest.java | 16 +++--- .../tron/core/db/TransactionStoreTest.java | 2 +- .../tron/core/db/TransactionTraceTest.java | 1 - .../java/org/tron/core/db/TxCacheDBTest.java | 2 +- .../core/db/api/AssetUpdateHelperTest.java | 2 +- .../tron/core/db2/SnapshotManagerTest.java | 12 ++--- .../tron/core/event/BlockEventGetTest.java | 2 +- .../tron/core/exception/TronErrorTest.java | 50 +++++++++++++++++++ .../prometheus/PrometheusApiServiceTest.java | 2 +- .../tron/core/net/TronNetDelegateTest.java | 2 +- .../InventoryMsgHandlerTest.java | 2 +- .../java/org/tron/core/pbft/PbftApiTest.java | 2 +- .../tron/core/services/ComputeRewardTest.java | 10 ++-- .../http/TriggerSmartContractServletTest.java | 2 +- .../services/stop/ConditionallyStopTest.java | 2 +- .../tron/core/zksnark/LibrustzcashTest.java | 1 - .../org/tron/core/zksnark/MerkleTreeTest.java | 1 - 31 files changed, 112 insertions(+), 75 deletions(-) diff --git a/common/src/main/java/org/tron/core/exception/TronError.java b/common/src/main/java/org/tron/core/exception/TronError.java index 8946a6528b3..9d11d249476 100644 --- a/common/src/main/java/org/tron/core/exception/TronError.java +++ b/common/src/main/java/org/tron/core/exception/TronError.java @@ -45,6 +45,8 @@ public enum ErrCode { TRON_NET_SERVICE_INIT(1), ZCASH_INIT(1), LOG_LOAD(1), + WITNESS_INIT(1), + RATE_LIMITER_INIT(1), SOLID_NODE_INIT(0); private final int code; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index aebff31e95d..1b19b68a23c 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -450,7 +450,8 @@ public static void setParam(final Config config) { if (PARAMETER.isWitness() && CollectionUtils.isEmpty(localWitnesses.getPrivateKeys())) { - logger.warn("This is a witness node, but localWitnesses is null"); + throw new TronError("This is a witness node, but localWitnesses is null", + TronError.ErrCode.WITNESS_INIT); } if (config.hasPath(Constant.VM_SUPPORT_CONSTANT)) { @@ -1141,7 +1142,7 @@ public static void setParam(final Config config) { PARAMETER.shutdownBlockTime = new CronExpression(config.getString( Constant.NODE_SHUTDOWN_BLOCK_TIME)); } catch (ParseException e) { - logger.error(e.getMessage(), e); + throw new TronError(e, TronError.ErrCode.AUTO_STOP_PARAMS); } } diff --git a/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java b/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java index 805fa2785b1..fa59a72303d 100644 --- a/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java +++ b/framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java @@ -16,6 +16,7 @@ import org.tron.common.prometheus.MetricLabels; import org.tron.common.prometheus.Metrics; import org.tron.core.config.args.Args; +import org.tron.core.exception.TronError; import org.tron.core.services.ratelimiter.GlobalRateLimiter; import org.tron.core.services.ratelimiter.RateLimiterContainer; import org.tron.core.services.ratelimiter.RuntimeData; @@ -40,6 +41,7 @@ private void addRateContainer() { RateLimiterInitialization.HttpRateLimiterItem item = Args.getInstance() .getRateLimiterInitialization().getHttpMap().get(getClass().getSimpleName()); boolean success = false; + final String name = getClass().getSimpleName(); if (item != null) { String cName = ""; String params = ""; @@ -54,17 +56,15 @@ private void addRateContainer() { || c == IPQPSRateLimiterAdapter.class) { constructor = c.getConstructor(String.class); obj = constructor.newInstance(params); - container.add(KEY_PREFIX_HTTP, getClass().getSimpleName(), (IRateLimiter) obj); + container.add(KEY_PREFIX_HTTP, name, (IRateLimiter) obj); } else { constructor = c.getConstructor(); obj = constructor.newInstance(QpsStrategy.DEFAULT_QPS_PARAM); - container.add(KEY_PREFIX_HTTP, getClass().getSimpleName(), (IRateLimiter) obj); + container.add(KEY_PREFIX_HTTP, name, (IRateLimiter) obj); } success = true; } catch (Exception e) { - logger.warn("failure to add the rate limiter strategy. servlet = {}, " - + "strategy name = {}, params = \"{}\".", - getClass().getSimpleName(), cName, params); + this.throwTronError(cName, params, name, e); } } if (!success) { @@ -72,14 +72,19 @@ private void addRateContainer() { // then add a default Strategy. try { IRateLimiter rateLimiter = new DefaultBaseQqsAdapter(QpsStrategy.DEFAULT_QPS_PARAM); - container.add(KEY_PREFIX_HTTP, getClass().getSimpleName(), rateLimiter); + container.add(KEY_PREFIX_HTTP, name, rateLimiter); } catch (Exception e) { - logger.warn("failure to add the default rate limiter strategy. servlet = {}.", - getClass().getSimpleName()); + this.throwTronError("DefaultBaseQqsAdapter", QpsStrategy.DEFAULT_QPS_PARAM, name, e); } } } + private void throwTronError(String strategy, String params, String servlet, Exception e) { + throw new TronError("failure to add the rate limiter strategy. servlet = " + servlet + + ", strategy name = " + strategy + ", params = \"" + params + "\".", + e, TronError.ErrCode.RATE_LIMITER_INIT); + } + @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java index 30bba35b43c..582f5157b27 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java @@ -73,7 +73,6 @@ public class BandWidthRuntimeOutOfTimeTest extends BaseTest { "--output-directory", dbPath(), "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory, - "-w", "--debug" }, "config-test-mainnet.conf" diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java index 0eef2266f9d..7e75f2b31d1 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java @@ -74,7 +74,6 @@ public class BandWidthRuntimeOutOfTimeWithCheckTest extends BaseTest { "--output-directory", dbPath(), "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory, - "-w", "--debug" }, "config-test-mainnet.conf" diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java index 698ba5f2923..40a4003f625 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java @@ -69,7 +69,6 @@ public static void init() { "--output-directory", dbPath(), "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory, - "-w" }, "config-test-mainnet.conf" ); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java index 4b3331187e2..aae8cb5702d 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java @@ -76,7 +76,6 @@ public class BandWidthRuntimeWithCheckTest extends BaseTest { "--output-directory", dbPath(), "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory, - "-w" }, "config-test-mainnet.conf" ); diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java index 03bf7b21956..bf18b988f19 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; import com.google.common.collect.Maps; import com.google.common.collect.Sets; @@ -41,9 +42,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.ClassRule; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; @@ -74,9 +73,6 @@ public class LevelDbDataSourceImplTest { private byte[] key5 = "00000005aa".getBytes(); private byte[] key6 = "00000006aa".getBytes(); - @Rule - public final ExpectedException exception = ExpectedException.none(); - /** * Release resources. */ @@ -351,12 +347,11 @@ public void prefixQueryTest() { @Test public void initDbTest() { - exception.expect(TronError.class); makeExceptionDb("test_initDb"); LevelDbDataSourceImpl dataSource = new LevelDbDataSourceImpl( Args.getInstance().getOutputDirectory(), "test_initDb"); - dataSource.initDB(); - dataSource.closeDB(); + TronError thrown = assertThrows(TronError.class, dataSource::initDB); + assertEquals(TronError.ErrCode.LEVELDB_INIT, thrown.getErrCode()); } private void makeExceptionDb(String dbName) { diff --git a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java index b7846ac2d70..c6fce30e3af 100644 --- a/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java +++ b/framework/src/test/java/org/tron/common/storage/leveldb/RocksDbDataSourceImplTest.java @@ -4,6 +4,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; import com.google.common.collect.Maps; import com.google.common.collect.Sets; @@ -23,9 +24,7 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.ClassRule; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.tron.common.storage.rocksdb.RocksDbDataSourceImpl; import org.tron.common.utils.ByteArray; @@ -56,9 +55,6 @@ public class RocksDbDataSourceImplTest { private byte[] key5 = "00000005aa".getBytes(); private byte[] key6 = "00000006aa".getBytes(); - @Rule - public final ExpectedException exception = ExpectedException.none(); - /** * Release resources. */ @@ -393,12 +389,11 @@ public void prefixQueryTest() { @Test public void initDbTest() { - exception.expect(TronError.class); makeExceptionDb("test_initDb"); RocksDbDataSourceImpl dataSource = new RocksDbDataSourceImpl( Args.getInstance().getOutputDirectory(), "test_initDb"); - dataSource.initDB(); - dataSource.closeDB(); + TronError thrown = assertThrows(TronError.class, dataSource::initDB); + assertEquals(TronError.ErrCode.ROCKSDB_INIT, thrown.getErrCode()); } private void makeExceptionDb(String dbName) { diff --git a/framework/src/test/java/org/tron/core/ForkControllerTest.java b/framework/src/test/java/org/tron/core/ForkControllerTest.java index 74e651b3c1d..0b43db3e534 100644 --- a/framework/src/test/java/org/tron/core/ForkControllerTest.java +++ b/framework/src/test/java/org/tron/core/ForkControllerTest.java @@ -31,7 +31,7 @@ public class ForkControllerTest { @Before public void init() throws IOException { Args.setParam(new String[]{"-d", - temporaryFolder.newFolder().toString(), "-w"}, Constant.TEST_CONF); + temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); context = new TronApplicationContext(DefaultConfig.class); dynamicPropertiesStore = context.getBean(DynamicPropertiesStore.class); chainBaseManager = context.getBean(ChainBaseManager.class); diff --git a/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java index 0ee0faa550a..7a217dfd787 100644 --- a/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java @@ -36,7 +36,7 @@ public class AccountCapsuleTest extends BaseTest { static AccountCapsule accountCapsule; static { - Args.setParam(new String[]{"-d", dbPath(), "-w"}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); OWNER_ADDRESS = Wallet.getAddressPreFixString() + "a06a17a49648a8ad32055c06f60fa14ae46df91234"; } diff --git a/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java b/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java index 2b07d7d7952..b966b26a299 100644 --- a/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java +++ b/framework/src/test/java/org/tron/core/capsule/utils/AssetUtilTest.java @@ -24,7 +24,7 @@ public class AssetUtilTest extends BaseTest { static { - Args.setParam(new String[] {"-d", dbPath(), "-w"}, Constant.TEST_CONF); + Args.setParam(new String[] {"-d", dbPath()}, Constant.TEST_CONF); } public static byte[] randomBytes(int length) { diff --git a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java index 196941328b4..845f70a38a4 100644 --- a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java @@ -57,7 +57,7 @@ public void destroy() { @Test public void get() { - Args.setParam(new String[] {"-w", "-c", Constant.TEST_CONF}, Constant.TESTNET_CONF); + Args.setParam(new String[] {"-c", Constant.TEST_CONF}, Constant.TESTNET_CONF); CommonParameter parameter = Args.getInstance(); @@ -132,7 +132,7 @@ public void get() { @Test public void testIpFromLibP2p() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Args.setParam(new String[] {"-w"}, Constant.TEST_CONF); + Args.setParam(new String[] {}, Constant.TEST_CONF); CommonParameter parameter = Args.getInstance(); String configuredExternalIp = parameter.getNodeExternalIp(); @@ -153,7 +153,7 @@ public void testIpFromLibP2p() @Test public void testOldRewardOpt() { thrown.expect(IllegalArgumentException.class); - Args.setParam(new String[] {"-w", "-c", "args-test.conf"}, Constant.TESTNET_CONF); + Args.setParam(new String[] {"-c", "args-test.conf"}, Constant.TESTNET_CONF); } @Test diff --git a/framework/src/test/java/org/tron/core/consensus/DposServiceTest.java b/framework/src/test/java/org/tron/core/consensus/DposServiceTest.java index ce66db2ab96..dc6802d71d5 100644 --- a/framework/src/test/java/org/tron/core/consensus/DposServiceTest.java +++ b/framework/src/test/java/org/tron/core/consensus/DposServiceTest.java @@ -4,6 +4,7 @@ import com.google.protobuf.ByteString; import java.lang.reflect.Field; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; @@ -21,6 +22,12 @@ public class DposServiceTest { DposService service = new DposService(); + + @AfterClass + public static void destroy() { + Args.clearParam(); + } + @Test public void testValidBlockTime() throws Exception { long headTime = 1724036757000L; @@ -53,8 +60,7 @@ public void testValidBlockTime() throws Exception { @Test public void testValidSlot() throws Exception { - Args.setParam(new String[] {"-w"}, Constant.TEST_CONF); - CommonParameter parameter = Args.getInstance(); + Args.setParam(new String[] {}, Constant.TEST_CONF); long headTime = 1724036757000L; ByteString witness = ByteString.copyFrom(NetUtil.getNodeId()); ByteString witness2 = ByteString.copyFrom(NetUtil.getNodeId()); diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index a9cf1087c2a..db219377b74 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -32,7 +32,6 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; import org.tron.common.crypto.ECKey; @@ -115,8 +114,6 @@ public class ManagerTest extends BlockGenerate { private static BlockCapsule blockCapsule2; @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); - @Rule - public final ExpectedException exception = ExpectedException.none(); private static AtomicInteger port = new AtomicInteger(0); private static String accountAddress = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; @@ -126,7 +123,7 @@ public class ManagerTest extends BlockGenerate { @Before public void init() throws IOException { Args.setParam(new String[]{"-d", - temporaryFolder.newFolder().toString(), "-w"}, Constant.TEST_CONF); + temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); Args.getInstance().setNodeListenPort(10000 + port.incrementAndGet()); context = new TronApplicationContext(DefaultConfig.class); @@ -726,7 +723,7 @@ public void fork() BadBlockException, TaposException, BadNumberBlockException, NonCommonBlockException, ReceiptCheckErrException, VMIllegalException, TooBigTransactionResultException, ZksnarkException, EventBloomException { - Args.setParam(new String[]{"--witness"}, Constant.TEST_CONF); + Args.setParam(new String[]{}, Constant.TEST_CONF); long size = chainManager.getBlockStore().size(); // System.out.print("block store size:" + size + "\n"); String key = PublicMethod.getRandomPrivateKey(); @@ -873,7 +870,7 @@ public void doNotSwitch() TaposException, BadNumberBlockException, NonCommonBlockException, ReceiptCheckErrException, VMIllegalException, TooBigTransactionResultException, ZksnarkException, EventBloomException { - Args.setParam(new String[]{"--witness"}, Constant.TEST_CONF); + Args.setParam(new String[]{}, Constant.TEST_CONF); long size = chainManager.getBlockStore().size(); System.out.print("block store size:" + size + "\n"); String key = PublicMethod.getRandomPrivateKey(); @@ -985,7 +982,7 @@ public void switchBack() BadBlockException, TaposException, BadNumberBlockException, NonCommonBlockException, ReceiptCheckErrException, VMIllegalException, TooBigTransactionResultException, ZksnarkException, EventBloomException { - Args.setParam(new String[]{"--witness"}, Constant.TEST_CONF); + Args.setParam(new String[]{}, Constant.TEST_CONF); long size = chainManager.getBlockStore().size(); System.out.print("block store size:" + size + "\n"); String key = PublicMethod.getRandomPrivateKey();; @@ -1238,10 +1235,11 @@ public void testExpiration() { @Test public void blockTrigger() { - exception.expect(TronError.class); Manager manager = spy(new Manager()); doThrow(new RuntimeException("postBlockTrigger mock")).when(manager).postBlockTrigger(any()); - manager.blockTrigger(new BlockCapsule(Block.newBuilder().build()), 1, 1); + TronError thrown = Assert.assertThrows(TronError.class, () -> + manager.blockTrigger(new BlockCapsule(Block.newBuilder().build()), 1, 1)); + Assert.assertEquals(TronError.ErrCode.EVENT_SUBSCRIBE_ERROR, thrown.getErrCode()); } public void adjustBalance(AccountStore accountStore, byte[] accountAddress, long amount) diff --git a/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java b/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java index deeb135373f..21d34fb7a69 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java @@ -50,7 +50,7 @@ public class TransactionStoreTest extends BaseTest { */ @BeforeClass public static void init() { - Args.setParam(new String[]{"--output-directory", dbPath(), "-w"}, Constant.TEST_CONF); + Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); } /** diff --git a/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java b/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java index 161fbea9569..08848fc9da1 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionTraceTest.java @@ -65,7 +65,6 @@ public class TransactionTraceTest extends BaseTest { "--output-directory", dbPath(), "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory, - "-w", "--debug" }, "config-test-mainnet.conf" diff --git a/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java b/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java index 55557cf51b5..4d223e726ca 100644 --- a/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java +++ b/framework/src/test/java/org/tron/core/db/TxCacheDBTest.java @@ -20,7 +20,7 @@ public static void init() { String dbDirectory = "db_TransactionCache_test"; String indexDirectory = "index_TransactionCache_test"; Args.setParam(new String[]{"--output-directory", dbPath(), "--storage-db-directory", - dbDirectory, "--storage-index-directory", indexDirectory, "-w"}, Constant.TEST_CONF); + dbDirectory, "--storage-index-directory", indexDirectory}, Constant.TEST_CONF); } @Test diff --git a/framework/src/test/java/org/tron/core/db/api/AssetUpdateHelperTest.java b/framework/src/test/java/org/tron/core/db/api/AssetUpdateHelperTest.java index ed18b1be97d..d1edd92c109 100644 --- a/framework/src/test/java/org/tron/core/db/api/AssetUpdateHelperTest.java +++ b/framework/src/test/java/org/tron/core/db/api/AssetUpdateHelperTest.java @@ -27,7 +27,7 @@ public class AssetUpdateHelperTest extends BaseTest { private static boolean init; static { - Args.setParam(new String[]{"-d", dbPath(), "-w"}, "config-test-index.conf"); + Args.setParam(new String[]{"-d", dbPath()}, "config-test-index.conf"); Args.getInstance().setSolidityNode(true); } diff --git a/framework/src/test/java/org/tron/core/db2/SnapshotManagerTest.java b/framework/src/test/java/org/tron/core/db2/SnapshotManagerTest.java index 87834246fba..134dc99e51c 100644 --- a/framework/src/test/java/org/tron/core/db2/SnapshotManagerTest.java +++ b/framework/src/test/java/org/tron/core/db2/SnapshotManagerTest.java @@ -15,9 +15,7 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; @@ -43,8 +41,6 @@ public class SnapshotManagerTest { private Application appT; private TestRevokingTronStore tronDatabase; - @Rule - public ExpectedException thrown = ExpectedException.none(); @Before public void init() { @@ -122,19 +118,19 @@ public synchronized void testClose() { @Test public void testCheckError() { - thrown.expect(TronError.class); SnapshotManager manager = spy(new SnapshotManager("")); when(manager.getCheckpointList()).thenReturn(Arrays.asList("check1", "check2")); - manager.check(); + TronError thrown = Assert.assertThrows(TronError.class, manager::check); + Assert.assertEquals(TronError.ErrCode.CHECKPOINT_VERSION, thrown.getErrCode()); } @Test public void testFlushError() { - thrown.expect(TronError.class); SnapshotManager manager = spy(new SnapshotManager("")); manager.setUnChecked(false); when(manager.getCheckpointList()).thenReturn(Arrays.asList("check1", "check2")); when(manager.shouldBeRefreshed()).thenReturn(true); - manager.flush(); + TronError thrown = Assert.assertThrows(TronError.class, manager::flush); + Assert.assertEquals(TronError.ErrCode.DB_FLUSH, thrown.getErrCode()); } } diff --git a/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java b/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java index 14479566815..704dc9ddc49 100644 --- a/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java +++ b/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java @@ -78,7 +78,7 @@ protected void initDbPath() throws IOException { public void before() throws IOException { initDbPath(); logger.info("Full node running."); - Args.setParam(new String[] {"-d", dbPath, "-w"}, Constant.TEST_CONF); + Args.setParam(new String[] {"-d", dbPath}, Constant.TEST_CONF); Args.getInstance().setNodeListenPort(10000 + port.incrementAndGet()); context = new TronApplicationContext(DefaultConfig.class); diff --git a/framework/src/test/java/org/tron/core/exception/TronErrorTest.java b/framework/src/test/java/org/tron/core/exception/TronErrorTest.java index 3176a62f56c..b4c3dc4b07f 100644 --- a/framework/src/test/java/org/tron/core/exception/TronErrorTest.java +++ b/framework/src/test/java/org/tron/core/exception/TronErrorTest.java @@ -5,8 +5,14 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mockStatic; +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; +import com.typesafe.config.ConfigObject; import java.io.IOException; import java.nio.file.Path; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import org.junit.After; import org.junit.Assert; import org.junit.Rule; @@ -17,7 +23,13 @@ import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import org.tron.common.log.LogService; +import org.tron.common.parameter.RateLimiterInitialization; +import org.tron.common.utils.ReflectUtils; import org.tron.common.zksnark.JLibrustzcash; +import org.tron.core.Constant; +import org.tron.core.config.args.Args; +import org.tron.core.services.http.GetBlockServlet; +import org.tron.core.services.http.RateLimiterServlet; import org.tron.core.zen.ZksnarkInitService; @RunWith(MockitoJUnitRunner.class) @@ -29,6 +41,7 @@ public class TronErrorTest { @After public void clearMocks() { Mockito.clearAllCaches(); + Args.clearParam(); } @Test @@ -64,4 +77,41 @@ public void LogLoadTest() throws IOException { TronError thrown = assertThrows(TronError.class, () -> LogService.load(path.toString())); assertEquals(TronError.ErrCode.LOG_LOAD, thrown.getErrCode()); } + + @Test + public void witnessInitTest() { + TronError thrown = assertThrows(TronError.class, () -> { + Args.setParam(new String[]{"--witness"}, Constant.TEST_CONF); + }); + assertEquals(TronError.ErrCode.WITNESS_INIT, thrown.getErrCode()); + } + + @Test + public void rateLimiterServletInitTest() { + Args.setParam(new String[]{}, Constant.TEST_CONF); + RateLimiterInitialization rateLimiter = new RateLimiterInitialization(); + Args.getInstance().setRateLimiterInitialization(rateLimiter); + Map item = new HashMap<>(); + item.put("strategy", "strategy"); + item.put("paramString", "params"); + item.put("component", "GetBlockServlet"); + ConfigObject config = ConfigFactory.parseMap(item).root(); + rateLimiter.setHttpMap( + Collections.singletonList(new RateLimiterInitialization.HttpRateLimiterItem(config))); + RateLimiterServlet servlet = new GetBlockServlet(); + TronError thrown = assertThrows(TronError.class, () -> + ReflectUtils.invokeMethod(servlet, "addRateContainer")); + assertEquals(TronError.ErrCode.RATE_LIMITER_INIT, thrown.getErrCode()); + } + + @Test + public void shutdownBlockTimeInitTest() { + Map params = new HashMap<>(); + params.put(Constant.NODE_SHUTDOWN_BLOCK_TIME, "0"); + params.put("storage.db.directory", "database"); + Config config = ConfigFactory.defaultOverrides().withFallback( + ConfigFactory.parseMap(params)); + TronError thrown = assertThrows(TronError.class, () -> Args.setParam(config)); + assertEquals(TronError.ErrCode.AUTO_STOP_PARAMS, thrown.getErrCode()); + } } diff --git a/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java b/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java index 1c6e56cbbbe..195e4749209 100644 --- a/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java +++ b/framework/src/test/java/org/tron/core/metrics/prometheus/PrometheusApiServiceTest.java @@ -55,7 +55,7 @@ public class PrometheusApiServiceTest extends BaseTest { private ChainBaseManager chainManager; static { - Args.setParam(new String[] {"-d", dbPath(), "-w"}, Constant.TEST_CONF); + Args.setParam(new String[] {"-d", dbPath()}, Constant.TEST_CONF); Args.getInstance().setNodeListenPort(10000 + port.incrementAndGet()); initParameter(Args.getInstance()); Metrics.init(); diff --git a/framework/src/test/java/org/tron/core/net/TronNetDelegateTest.java b/framework/src/test/java/org/tron/core/net/TronNetDelegateTest.java index 727aad9dccb..6550766d702 100644 --- a/framework/src/test/java/org/tron/core/net/TronNetDelegateTest.java +++ b/framework/src/test/java/org/tron/core/net/TronNetDelegateTest.java @@ -17,7 +17,7 @@ public class TronNetDelegateTest { @Test public void test() throws Exception { - Args.setParam(new String[] {"-w"}, Constant.TEST_CONF); + Args.setParam(new String[] {}, Constant.TEST_CONF); CommonParameter parameter = Args.getInstance(); Args.logConfig(); parameter.setUnsolidifiedBlockCheck(true); diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/InventoryMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/InventoryMsgHandlerTest.java index 7aba0251708..0864c872bc3 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/InventoryMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/InventoryMsgHandlerTest.java @@ -21,7 +21,7 @@ public class InventoryMsgHandlerTest { @Test public void testProcessMessage() throws Exception { InventoryMsgHandler handler = new InventoryMsgHandler(); - Args.setParam(new String[] {"-w"}, Constant.TEST_CONF); + Args.setParam(new String[] {}, Constant.TEST_CONF); Args.logConfig(); InventoryMessage msg = new InventoryMessage(new ArrayList<>(), InventoryType.TRX); diff --git a/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java b/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java index a7fb2644495..3d5096a5702 100755 --- a/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java +++ b/framework/src/test/java/org/tron/core/pbft/PbftApiTest.java @@ -37,7 +37,7 @@ public class PbftApiTest extends BaseTest { @BeforeClass public static void init() { - Args.setParam(new String[]{"-d", dbPath(), "-w"}, Constant.TEST_CONF); + Args.setParam(new String[]{"-d", dbPath()}, Constant.TEST_CONF); CommonParameter.getInstance().setPBFTHttpEnable(true); CommonParameter.getInstance().setPBFTHttpPort(PublicMethod.chooseRandomPort()); } diff --git a/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java b/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java index 8ff6b62d7ef..c2caafd393c 100644 --- a/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java +++ b/framework/src/test/java/org/tron/core/services/ComputeRewardTest.java @@ -17,7 +17,6 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.tron.common.application.TronApplicationContext; import org.tron.common.error.TronDBException; @@ -115,9 +114,6 @@ public class ComputeRewardTest { @Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder(); - @Rule - public final ExpectedException exception = ExpectedException.none(); - @After public void destroy() { context.destroy(); @@ -264,7 +260,6 @@ private void setUp() { @Test public void query() { - exception.expect(TronError.class); Assert.assertEquals(3189, mortgageService.queryReward(OWNER_ADDRESS)); // mock root is error rewardViStore.put("test".getBytes(), "test".getBytes()); @@ -288,8 +283,9 @@ public void query() { propertiesStore.saveNewRewardAlgorithmEffectiveCycle(); propertiesStore.saveCurrentCycleNumber(5); rewardViStore.close(); - ReflectUtils.invokeMethod(rewardViCalService,"maybeRun"); - + TronError thrown = Assert.assertThrows(TronError.class, () -> + ReflectUtils.invokeMethod(rewardViCalService,"maybeRun")); + Assert.assertEquals(TronError.ErrCode.REWARD_VI_CALCULATOR, thrown.getErrCode()); } static class Vote { diff --git a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java index 4cbb729a787..c6fa5da76e4 100644 --- a/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java +++ b/framework/src/test/java/org/tron/core/services/http/TriggerSmartContractServletTest.java @@ -31,7 +31,7 @@ public class TriggerSmartContractServletTest extends BaseTest { @BeforeClass public static void init() throws Exception { Args.setParam( - new String[]{"--output-directory", dbPath(), "--debug", "--witness"}, Constant.TEST_CONF); + new String[]{"--output-directory", dbPath(), "--debug"}, Constant.TEST_CONF); Args.getInstance().needSyncCheck = false; Args.getInstance().setFullNodeHttpEnable(true); Args.getInstance().setFullNodeHttpPort(PublicMethod.chooseRandomPort()); diff --git a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java index dc3d02e7ced..b417b27b380 100644 --- a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java @@ -82,7 +82,7 @@ public void init() throws Exception { initDbPath(); logger.info("Full node running."); - Args.setParam(new String[] {"-d", dbPath, "-w"}, Constant.TEST_CONF); + Args.setParam(new String[] {"-d", dbPath}, Constant.TEST_CONF); Args.getInstance().setNodeListenPort(10000 + port.incrementAndGet()); initParameter(Args.getInstance()); diff --git a/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java b/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java index 915742d3f0d..049fb2528b1 100644 --- a/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java @@ -80,7 +80,6 @@ public static void init() { "--output-directory", dbPath(), "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory, - "-w", "--debug" }, "config-test-mainnet.conf" diff --git a/framework/src/test/java/org/tron/core/zksnark/MerkleTreeTest.java b/framework/src/test/java/org/tron/core/zksnark/MerkleTreeTest.java index cb70adb35a2..faea3780135 100644 --- a/framework/src/test/java/org/tron/core/zksnark/MerkleTreeTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/MerkleTreeTest.java @@ -36,7 +36,6 @@ public class MerkleTreeTest extends BaseTest { "--output-directory", dbPath(), "--storage-db-directory", dbDirectory, "--storage-index-directory", indexDirectory, - "-w", "--debug" }, "config-test-mainnet.conf" From a6bf35cc3a4ba22c9a866883418c2084784b83e6 Mon Sep 17 00:00:00 2001 From: Liulei Date: Tue, 11 Mar 2025 10:48:08 +0800 Subject: [PATCH 1173/1197] feat(test): refactor codes --- .../zen/KZGPointEvaluationInitService.java | 22 +- .../runtime/vm/PrecompiledContractsTest.java | 17 +- .../core/actuator/utils/ProposalUtilTest.java | 108 + .../core/zksnark/KZGPointEvaluationTest.java | 57 +- .../resources/kzg-trusted-setups/test.txt | 8259 +++++++++++++++++ 5 files changed, 8440 insertions(+), 23 deletions(-) create mode 100644 framework/src/test/resources/kzg-trusted-setups/test.txt diff --git a/framework/src/main/java/org/tron/core/zen/KZGPointEvaluationInitService.java b/framework/src/main/java/org/tron/core/zen/KZGPointEvaluationInitService.java index bb3710f9673..cc37b79757c 100644 --- a/framework/src/main/java/org/tron/core/zen/KZGPointEvaluationInitService.java +++ b/framework/src/main/java/org/tron/core/zen/KZGPointEvaluationInitService.java @@ -3,36 +3,42 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.util.concurrent.atomic.AtomicBoolean; import javax.annotation.PostConstruct; - -import org.tron.common.crypto.ckzg4844.CKZG4844JNI; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import org.springframework.stereotype.Component; +import org.tron.common.crypto.ckzg4844.CKZG4844JNI; @Slf4j @Component public class KZGPointEvaluationInitService { + private static final AtomicBoolean loaded = new AtomicBoolean(false); + @PostConstruct private void init() { initCKZG4844(); } public static void freeSetup() { - CKZG4844JNI.freeTrustedSetup(); + if (loaded.compareAndSet(true, false)) { + CKZG4844JNI.freeTrustedSetup(); + } } public static void initCKZG4844() { - logger.info("init ckzg 4844 begin"); + if (loaded.compareAndSet(false, true)) { + logger.info("init ckzg 4844 begin"); - CKZG4844JNI.loadNativeLibrary(); + CKZG4844JNI.loadNativeLibrary(); - String setupFile = getSetupFile("trusted_setup.txt"); + String setupFile = getSetupFile("trusted_setup.txt"); - CKZG4844JNI.loadTrustedSetup(setupFile, 0); + CKZG4844JNI.loadTrustedSetup(setupFile, 0); - logger.info("init ckzg 4844 done"); + logger.info("init ckzg 4844 done"); + } } private static String getSetupFile(String fileName) { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index 4a7b63c8aba..b419809795c 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -40,8 +40,6 @@ import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.repository.Repository; import org.tron.core.vm.repository.RepositoryImpl; -import org.tron.core.zen.KZGPointEvaluationInitService; -import org.tron.core.zen.ZksnarkInitService; import org.tron.protos.Protocol; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Proposal.State; @@ -1179,13 +1177,14 @@ public void kzgPointEvaluationTest() { Repository tempRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); contract.setRepository(tempRepository); - byte[] versionedHash = Hex.decode("015a4cab4911426699ed34483de6640cf55a568afc5c5edffdcbd8bcd4452f68"); + byte[] versionedHash = + Hex.decode("015a4cab4911426699ed34483de6640cf55a568afc5c5edffdcbd8bcd4452f68"); byte[] z = Hex.decode("0000000000000000000000000000000000000000000000000000000000000065"); byte[] y = Hex.decode("60f557194475973322b33dc989896381844508234bfa6fbeefe5fa165ae15a0a"); - byte[] commitment = Hex.decode("a70477b56251e8770969c83eaed665d3ab99b96b72270a4" + - "1009f2752b5c06a06bd089ad48952c12b1dbf83dccd9d373f"); - byte[] proof = Hex.decode("879f9a41956deae578bc65e7133f164394b8677bc2e7b1356be61" + - "d47720ed2a3326bfddebc67cd37ee9e7537d7814afe"); + byte[] commitment = Hex.decode("a70477b56251e8770969c83eaed665d3ab99b96b72270a4" + + "1009f2752b5c06a06bd089ad48952c12b1dbf83dccd9d373f"); + byte[] proof = Hex.decode("879f9a41956deae578bc65e7133f164394b8677bc2e7b1356be61" + + "d47720ed2a3326bfddebc67cd37ee9e7537d7814afe"); byte[] data = new byte[192]; System.arraycopy(versionedHash, 0, data, 0, 32); @@ -1213,8 +1212,8 @@ public void kzgPointEvaluationTest() { res = contract.execute(data); byte[] expected = Hex.decode( - "0000000000000000000000000000000000000000000000000000000000001000" + - "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); + "0000000000000000000000000000000000000000000000000000000000001000" + + "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); Assert.assertTrue(res.getLeft()); Assert.assertArrayEquals(expected, res.getRight()); VMConfig.initAllowTvmBlob(0); diff --git a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java index 1cfc4d1887f..e8a1e862f54 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java @@ -435,6 +435,10 @@ public void validateCheck() { testConsensusLogicOptimizationProposal(); + testAllowTvmCancunProposal(); + + testAllowTvmBlobProposal(); + forkUtils.getManager().getDynamicPropertiesStore() .statsByVersion(ForkBlockVersionEnum.ENERGY_LIMIT.getValue(), stats); forkUtils.reset(); @@ -551,6 +555,110 @@ private void testConsensusLogicOptimizationProposal() { } + private void testAllowTvmCancunProposal() { + byte[] stats = new byte[27]; + forkUtils.getManager().getDynamicPropertiesStore() + .statsByVersion(ForkBlockVersionEnum.VERSION_4_8_0.getValue(), stats); + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_TVM_CANCUN.getCode(), 1); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "Bad chain parameter id [ALLOW_TVM_CANCUN]", + e.getMessage()); + } + + long maintenanceTimeInterval = forkUtils.getManager().getDynamicPropertiesStore() + .getMaintenanceTimeInterval(); + + long hardForkTime = + ((ForkBlockVersionEnum.VERSION_4_8_0.getHardForkTime() - 1) / maintenanceTimeInterval + 1) + * maintenanceTimeInterval; + forkUtils.getManager().getDynamicPropertiesStore() + .saveLatestBlockHeaderTimestamp(hardForkTime + 1); + + stats = new byte[27]; + Arrays.fill(stats, (byte) 1); + forkUtils.getManager().getDynamicPropertiesStore() + .statsByVersion(ForkBlockVersionEnum.VERSION_4_8_0.getValue(), stats); + + // Should fail because the proposal value is invalid + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_TVM_CANCUN.getCode(), 2); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "This value[ALLOW_TVM_CANCUN] is only allowed to be 1", + e.getMessage()); + } + + dynamicPropertiesStore.saveAllowTvmCancun(1); + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_TVM_CANCUN.getCode(), 1); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "[ALLOW_TVM_CANCUN] has been valid, no need to propose again", + e.getMessage()); + } + + } + + private void testAllowTvmBlobProposal() { + byte[] stats = new byte[27]; + forkUtils.getManager().getDynamicPropertiesStore() + .statsByVersion(ForkBlockVersionEnum.VERSION_4_8_0.getValue(), stats); + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_TVM_BLOB.getCode(), 1); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "Bad chain parameter id [ALLOW_TVM_BLOB]", + e.getMessage()); + } + + long maintenanceTimeInterval = forkUtils.getManager().getDynamicPropertiesStore() + .getMaintenanceTimeInterval(); + + long hardForkTime = + ((ForkBlockVersionEnum.VERSION_4_8_0.getHardForkTime() - 1) / maintenanceTimeInterval + 1) + * maintenanceTimeInterval; + forkUtils.getManager().getDynamicPropertiesStore() + .saveLatestBlockHeaderTimestamp(hardForkTime + 1); + + stats = new byte[27]; + Arrays.fill(stats, (byte) 1); + forkUtils.getManager().getDynamicPropertiesStore() + .statsByVersion(ForkBlockVersionEnum.VERSION_4_8_0.getValue(), stats); + + // Should fail because the proposal value is invalid + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_TVM_BLOB.getCode(), 2); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "This value[ALLOW_TVM_BLOB] is only allowed to be 1", + e.getMessage()); + } + + dynamicPropertiesStore.saveAllowTvmBlob(1); + try { + ProposalUtil.validator(dynamicPropertiesStore, forkUtils, + ProposalType.ALLOW_TVM_BLOB.getCode(), 1); + Assert.fail(); + } catch (ContractValidateException e) { + Assert.assertEquals( + "[ALLOW_TVM_BLOB] has been valid, no need to propose again", + e.getMessage()); + } + + } + @Test public void blockVersionCheck() { for (ForkBlockVersionEnum forkVersion : ForkBlockVersionEnum.values()) { diff --git a/framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java b/framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java index 2aa90c602a0..5f732520d48 100644 --- a/framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java @@ -1,14 +1,16 @@ package org.tron.core.zksnark; +import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Test; import org.tron.common.crypto.ckzg4844.CKZG4844JNI; +import org.tron.common.crypto.ckzg4844.CKZGException; +import org.tron.common.crypto.ckzg4844.CellsAndProofs; +import org.tron.common.crypto.ckzg4844.ProofAndY; import org.tron.core.zen.KZGPointEvaluationInitService; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertTrue; - @Slf4j public class KZGPointEvaluationTest { @@ -22,16 +24,59 @@ public void testVerifyBlobKzgProof() { byte[] expectedCommitment = Hex.decode("a70477b56251e8770969c83eaed665d3ab99b96b72270a41009f27" + "52b5c06a06bd089ad48952c12b1dbf83dccd9d373f"); - assertArrayEquals(expectedCommitment, commitment); + Assert.assertArrayEquals(expectedCommitment, commitment); byte[] proof = CKZG4844JNI.computeBlobKzgProof(blob, commitment); byte[] expectedProof = Hex.decode("b7f576f2442febaa035d3c6f34bbdad6acebcaec70236ff40b3373b" + "d2ca00547d3ca7bb1d0ed3e728ca9dab610a4cfa4"); - assertArrayEquals(expectedProof, proof); + Assert.assertArrayEquals(expectedProof, proof); boolean isValidProof = CKZG4844JNI.verifyBlobKzgProof(blob, commitment, proof); - assertTrue(isValidProof); + Assert.assertTrue(isValidProof); + + byte[] z = + Hex.decode("0000000000000000000000000000000000000000000000000000000000000065"); + byte[] y = + Hex.decode("60f557194475973322b33dc989896381844508234bfa6fbeefe5fa165ae15a0a"); + ProofAndY proofAndY = CKZG4844JNI.computeKzgProof(blob, z); + byte[] expectedZProof = + Hex.decode("879f9a41956deae578bc65e7133f164394b8677bc2e7b1356be61" + + "d47720ed2a3326bfddebc67cd37ee9e7537d7814afe"); + Assert.assertArrayEquals(y, proofAndY.getY()); + Assert.assertArrayEquals(expectedZProof, proofAndY.getProof()); + + CellsAndProofs cellsAndProofs = CKZG4844JNI.computeCellsAndKzgProofs(blob); + byte[] blockCells = Arrays.copyOfRange(cellsAndProofs.getCells(), 0, 2048); + byte[] blockProof = Arrays.copyOfRange(cellsAndProofs.getProofs(), 0, 48); + long[] cellIndices = new long[1]; + boolean isValid = + CKZG4844JNI.verifyCellKzgProofBatch(commitment, cellIndices, blockCells, blockProof); + Assert.assertTrue(isValid); + + long[] errorCellIndices = new long[2]; + errorCellIndices[1] = 1; + CKZGException expectedE = new CKZGException(1, + "Invalid cellIndices size. Expected 1 bytes but got 2."); + try { + CKZG4844JNI.verifyCellKzgProofBatch(commitment, errorCellIndices, blockCells, blockProof); + } catch (Exception e) { + Assert.assertEquals(CKZGException.class, e.getClass()); + CKZGException exception = (CKZGException) e; + Assert.assertEquals(expectedE.getError(), exception.getError()); + Assert.assertEquals(expectedE.getErrorMessage(), exception.getErrorMessage()); + } + + try { + String testSetupResource = "/kzg-trusted-setups/test.txt"; + CKZG4844JNI.loadTrustedSetupFromResource( + testSetupResource, KZGPointEvaluationTest.class, 0); + } catch (Exception e) { + Assert.assertEquals(RuntimeException.class, e.getClass()); + Assert.assertEquals( + "Trusted Setup is already loaded. Free it before loading a new one.", + e.getMessage()); + } KZGPointEvaluationInitService.freeSetup(); } diff --git a/framework/src/test/resources/kzg-trusted-setups/test.txt b/framework/src/test/resources/kzg-trusted-setups/test.txt new file mode 100644 index 00000000000..5ecccf5e5e5 --- /dev/null +++ b/framework/src/test/resources/kzg-trusted-setups/test.txt @@ -0,0 +1,8259 @@ +4096 +65 +a0413c0dcafec6dbc9f47d66785cf1e8c981044f7d13cfe3e4fcbb71b5408dfde6312493cb3c1d30516cb3ca88c03654 +8b997fb25730d661918371bb41f2a6e899cac23f04fc5365800b75433c0a953250e15e7a98fb5ca5cc56a8cd34c20c57 +83302852db89424d5699f3f157e79e91dc1380f8d5895c5a772bb4ea3a5928e7c26c07db6775203ce33e62a114adaa99 +a759c48b7e4a685e735c01e5aa6ef9c248705001f470f9ad856cd87806983e917a8742a3bd5ee27db8d76080269b7c83 +967f8dc45ebc3be14c8705f43249a30ff48e96205fb02ae28daeab47b72eb3f45df0625928582aa1eb4368381c33e127 +a418eb1e9fb84cb32b370610f56f3cb470706a40ac5a47c411c464299c45c91f25b63ae3fcd623172aa0f273c0526c13 +8f44e3f0387293bc7931e978165abbaed08f53acd72a0a23ac85f6da0091196b886233bcee5b4a194db02f3d5a9b3f78 +97173434b336be73c89412a6d70d416e170ea355bf1956c32d464090b107c090ef2d4e1a467a5632fbc332eeb679bf2d +a24052ad8d55ad04bc5d951f78e14213435681594110fd18173482609d5019105b8045182d53ffce4fc29fc8810516c1 +b950768136b260277590b5bec3f56bbc2f7a8bc383d44ce8600e85bf8cf19f479898bcc999d96dfbd2001ede01d94949 +92ab8077871037bd3b57b95cbb9fb10eb11efde9191690dcac655356986fd02841d8fdb25396faa0feadfe3f50baf56d +a79b096dff98038ac30f91112dd14b78f8ad428268af36d20c292e2b3b6d9ed4fb28480bb04e465071cc67d05786b6d1 +b9ff71461328f370ce68bf591aa7fb13027044f42a575517f3319e2be4aa4843fa281e756d0aa5645428d6dfa857cef2 +8d765808c00b3543ff182e2d159c38ae174b12d1314da88ea08e13bd9d1c37184cb515e6bf6420531b5d41767987d7ce +b8c9a837d20c3b53e6f578e4a257bb7ef8fc43178614ec2a154915b267ad2be135981d01ed2ee1b5fbd9d9bb27f0800a +a9773d92cf23f65f98ef68f6cf95c72b53d0683af2f9bf886bb9036e4a38184b1131b26fd24397910b494fbef856f3aa +b41ebe38962d112da4a01bf101cb248d808fbd50aaf749fc7c151cf332032eb3e3bdbd716db899724b734d392f26c412 +90fbb030167fb47dcc13d604a726c0339418567c1d287d1d87423fa0cb92eec3455fbb46bcbe2e697144a2d3972142e4 +b11d298bd167464b35fb923520d14832bd9ed50ed841bf6d7618424fd6f3699190af21759e351b89142d355952149da1 +8bc36066f69dc89f7c4d1e58d67497675050c6aa002244cebd9fc957ec5e364c46bab4735ea3db02b73b3ca43c96e019 +ab7ab92c5d4d773068e485aa5831941ebd63db7118674ca38089635f3b4186833af2455a6fb9ed2b745df53b3ce96727 +af191ca3089892cb943cd97cf11a51f38e38bd9be50844a4e8da99f27e305e876f9ed4ab0628e8ae3939066b7d34a15f +a3204c1747feabc2c11339a542195e7cb6628fd3964f846e71e2e3f2d6bb379a5e51700682ea1844eba12756adb13216 +903a29883846b7c50c15968b20e30c471aeac07b872c40a4d19eb1a42da18b649d5bbfde4b4cf6225d215a461b0deb6d +8e6e9c15ffbf1e16e5865a5fef7ed751dc81957a9757b535cb38b649e1098cda25d42381dc4f776778573cdf90c3e6e0 +a8f6dd26100b512a8c96c52e00715c4b2cb9ac457f17aed8ffe1cf1ea524068fe5a1ddf218149845fc1417b789ecfc98 +a5b0ffc819451ea639cfd1c18cbc9365cc79368d3b2e736c0ae54eba2f0801e6eb0ee14a5f373f4a70ca463bdb696c09 +879f91ccd56a1b9736fbfd20d8747354da743fb121f0e308a0d298ff0d9344431890e41da66b5009af3f442c636b4f43 +81bf3a2d9755e206b515a508ac4d1109bf933c282a46a4ae4a1b4cb4a94e1d23642fad6bd452428845afa155742ade7e +8de778d4742f945df40004964e165592f9c6b1946263adcdd5a88b00244bda46c7bb49098c8eb6b3d97a0dd46148a8ca +b7a57b21d13121907ee28c5c1f80ee2e3e83a3135a8101e933cf57171209a96173ff5037f5af606e9fd6d066de6ed693 +b0877d1963fd9200414a38753dffd9f23a10eb3198912790d7eddbc9f6b477019d52ddd4ebdcb9f60818db076938a5a9 +88da2d7a6611bc16adc55fc1c377480c828aba4496c645e3efe0e1a67f333c05a0307f7f1d2df8ac013602c655c6e209 +95719eb02e8a9dede1a888c656a778b1c69b7716fbe3d1538fe8afd4a1bc972183c7d32aa7d6073376f7701df80116d8 +8e8a1ca971f2444b35af3376e85dccda3abb8e8e11d095d0a4c37628dfe5d3e043a377c3de68289ef142e4308e9941a0 +b720caaff02f6d798ac84c4f527203e823ff685869e3943c979e388e1c34c3f77f5c242c6daa7e3b30e511aab917b866 +86040d55809afeec10e315d1ad950d269d37cfee8c144cd8dd4126459e3b15a53b3e68df5981df3c2346d23c7b4baaf4 +82d8cabf13ab853db0377504f0aec00dba3a5cd3119787e8ad378ddf2c40b022ecfc67c642b7acc8c1e3dd03ab50993e +b8d873927936719d2484cd03a6687d65697e17dcf4f0d5aed6f5e4750f52ef2133d4645894e7ebfc4ef6ce6788d404c8 +b1235594dbb15b674a419ff2b2deb644ad2a93791ca05af402823f87114483d6aa1689b7a9bea0f547ad12fe270e4344 +a53fda86571b0651f5affb74312551a082fffc0385cfd24c1d779985b72a5b1cf7c78b42b4f7e51e77055f8e5e915b00 +b579adcfd9c6ef916a5a999e77a0cb21d378c4ea67e13b7c58709d5da23a56c2e54218691fc4ac39a4a3d74f88cc31f7 +ab79e584011713e8a2f583e483a91a0c2a40771b77d91475825b5acbea82db4262132901cb3e4a108c46d7c9ee217a4e +a0fe58ea9eb982d7654c8aaf9366230578fc1362f6faae0594f8b9e659bcb405dff4aac0c7888bbe07f614ecf0d800a6 +867e50e74281f28ecd4925560e2e7a6f8911b135557b688254623acce0dbc41e23ac3e706a184a45d54c586edc416eb0 +89f81b61adda20ea9d0b387a36d0ab073dc7c7cbff518501962038be19867042f11fcc7ff78096e5d3b68c6d8dc04d9b +a58ee91bb556d43cf01f1398c5811f76dc0f11efdd569eed9ef178b3b0715e122060ec8f945b4dbf6eebfa2b90af6fa6 +ac460be540f4c840def2eef19fc754a9af34608d107cbadb53334cf194cc91138d53b9538fcd0ec970b5d4aa455b224a +b09b91f929de52c09d48ca0893be6eb44e2f5210a6c394689dc1f7729d4be4e11d0474b178e80cea8c2ac0d081f0e811 +8d37a442a76b06a02a4e64c2504aea72c8b9b020ab7bcc94580fe2b9603c7c50d7b1e9d70d2a7daea19c68667e8f8c31 +a9838d4c4e3f3a0075a952cf7dd623307ec633fcc81a7cf9e52e66c31780de33dbb3d74c320dc7f0a4b72f7a49949515 +a44766b6251af458fe4f5f9ed1e02950f35703520b8656f09fc42d9a2d38a700c11a7c8a0436ac2e5e9f053d0bb8ff91 +ad78d9481c840f5202546bea0d13c776826feb8b1b7c72e83d99a947622f0bf38a4208551c4c41beb1270d7792075457 +b619ffa8733b470039451e224b777845021e8dc1125f247a4ff2476cc774657d0ff9c5279da841fc1236047de9d81c60 +af760b0a30a1d6af3bc5cd6686f396bd41779aeeb6e0d70a09349bd5da17ca2e7965afc5c8ec22744198fbe3f02fb331 +a0cc209abdb768b589fcb7b376b6e1cac07743288c95a1cf1a0354b47f0cf91fca78a75c1fcafa6f5926d6c379116608 +864add673c89c41c754eeb3cd8dcff5cdde1d739fce65c30e474a082bb5d813cba6412e61154ce88fdb6c12c5d9be35b +b091443b0ce279327dc37cb484e9a5b69b257a714ce21895d67539172f95ffa326903747b64a3649e99aea7bb10d03f7 +a8c452b8c4ca8e0a61942a8e08e28f17fb0ef4c5b018b4e6d1a64038280afa2bf1169202f05f14af24a06ca72f448ccd +a23c24721d18bc48d5dcf70effcbef89a7ae24e67158d70ae1d8169ee75d9a051d34b14e9cf06488bac324fe58549f26 +92a730e30eb5f3231feb85f6720489dbb1afd42c43f05a1610c6b3c67bb949ec8fde507e924498f4ffc646f7b07d9123 +8dbe5abf4031ec9ba6bb06d1a47dd1121fb9e03b652804069250967fd5e9577d0039e233441b7f837a7c9d67ba18c28e +aa456bcfef6a21bb88181482b279df260297b3778e84594ebddbdf337e85d9e3d46ca1d0b516622fb0b103df8ec519b7 +a3b31ae621bd210a2b767e0e6f22eb28fe3c4943498a7e91753225426168b9a26da0e02f1dc5264da53a5ad240d9f51b +aa8d66857127e6e71874ce2202923385a7d2818b84cb73a6c42d71afe70972a70c6bdd2aad1a6e8c5e4ca728382a8ea8 +ac7e8e7a82f439127a5e40558d90d17990f8229852d21c13d753c2e97facf077cf59582b603984c3dd3faebd80aff4f5 +93a8bcf4159f455d1baa73d2ef2450dcd4100420de84169bbe28b8b7a5d1746273f870091a87a057e834f754f34204b1 +89d0ebb287c3613cdcae7f5acc43f17f09c0213fc40c074660120b755d664109ffb9902ed981ede79e018ddb0c845698 +a87ccbfad431406aadbee878d9cf7d91b13649d5f7e19938b7dfd32645a43b114eef64ff3a13201398bd9b0337832e5a +833c51d0d0048f70c3eefb4e70e4ff66d0809c41838e8d2c21c288dd3ae9d9dfaf26d1742bf4976dab83a2b381677011 +8bcd6b1c3b02fffead432e8b1680bad0a1ac5a712d4225e220690ee18df3e7406e2769e1f309e2e803b850bc96f0e768 +b61e3dbd88aaf4ff1401521781e2eea9ef8b66d1fac5387c83b1da9e65c2aa2a56c262dea9eceeb4ad86c90211672db0 +866d3090db944ecf190dd0651abf67659caafd31ae861bab9992c1e3915cb0952da7c561cc7e203560a610f48fae633b +a5e8971543c14274a8dc892b0be188c1b4fbc75c692ed29f166e0ea80874bc5520c2791342b7c1d2fb5dd454b03b8a5b +8f2f9fc50471bae9ea87487ebd1bc8576ef844cc42d606af5c4c0969670fdf2189afd643e4de3145864e7773d215f37f +b1bb0f2527db6d51f42b9224383c0f96048bbc03d469bf01fe1383173ef8b1cc9455d9dd8ba04d46057f46949bfc92b5 +aa7c99d906b4d7922296cfe2520473fc50137c03d68b7865c5bfb8adbc316b1034310ec4b5670c47295f4a80fb8d61e9 +a5d1da4d6aba555919df44cbaa8ff79378a1c9e2cfdfbf9d39c63a4a00f284c5a5724e28ecbc2d9dba27fe4ee5018bd5 +a8db53224f70af4d991b9aae4ffe92d2aa5b618ad9137784b55843e9f16cefbfd25ada355d308e9bbf55f6d2f7976fb3 +b6536c4232bb20e22af1a8bb12de76d5fec2ad9a3b48af1f38fa67e0f8504ef60f305a73d19385095bb6a9603fe29889 +87f7e371a1817a63d6838a8cf4ab3a8473d19ce0d4f40fd013c03d5ddd5f4985df2956531cc9f187928ef54c68f4f9a9 +ae13530b1dbc5e4dced9d909ea61286ec09e25c12f37a1ed2f309b0eb99863d236c3b25ed3484acc8c076ad2fa8cd430 +98928d850247c6f7606190e687d5c94a627550198dbdbea0161ef9515eacdb1a0f195cae3bb293112179082daccf8b35 +918528bb8e6a055ad4db6230d3a405e9e55866da15c4721f5ddd1f1f37962d4904aad7a419218fe6d906fe191a991806 +b71e31a06afe065773dd3f4a6e9ef81c3292e27a3b7fdfdd452d03e05af3b6dd654c355f7516b2a93553360c6681a73a +8870b83ab78a98820866f91ac643af9f3ff792a2b7fda34185a9456a63abdce42bfe8ad4dc67f08a6392f250d4062df4 +91eea1b668e52f7a7a5087fabf1cab803b0316f78d9fff469fbfde2162f660c250e4336a9eea4cb0450bd30ac067bc8b +8b74990946de7b72a92147ceac1bd9d55999a8b576e8df68639e40ed5dc2062cfcd727903133de482b6dca19d0aaed82 +8ebad537fece090ebbab662bdf2618e21ca30cf6329c50935e8346d1217dcbe3c1fe1ea28efca369c6003ce0a94703c1 +a8640479556fb59ebd1c40c5f368fbd960932fdbb782665e4a0e24e2bdb598fc0164ce8c0726d7759cfc59e60a62e182 +a9a52a6bf98ee4d749f6d38be2c60a6d54b64d5cbe4e67266633dc096cf28c97fe998596707d31968cbe2064b72256bf +847953c48a4ce6032780e9b39d0ed4384e0be202c2bbe2dfda3910f5d87aa5cd3c2ffbfcfae4dddce16d6ab657599b95 +b6f6e1485d3ec2a06abaecd23028b200b2e4a0096c16144d07403e1720ff8f9ba9d919016b5eb8dc5103880a7a77a1d3 +98dfc2065b1622f596dbe27131ea60bef7a193b12922cecb27f8c571404f483014f8014572e86ae2e341ab738e4887ef +acb0d205566bacc87bbe2e25d10793f63f7a1f27fd9e58f4f653ceae3ffeba511eaf658e068fad289eeb28f9edbeb35b +ae4411ed5b263673cee894c11fe4abc72a4bf642d94022a5c0f3369380fcdfc1c21e277f2902972252503f91ada3029a +ac4a7a27ba390a75d0a247d93d4a8ef1f0485f8d373a4af4e1139369ec274b91b3464d9738eeaceb19cd6f509e2f8262 +87379c3bf231fdafcf6472a79e9e55a938d851d4dd662ab6e0d95fd47a478ed99e2ad1e6e39be3c0fc4f6d996a7dd833 +81316904b035a8bcc2041199a789a2e6879486ba9fddcba0a82c745cc8dd8374a39e523b91792170cd30be7aa3005b85 +b8206809c6cd027ed019f472581b45f7e12288f89047928ba32b4856b6560ad30395830d71e5e30c556f6f182b1fe690 +88d76c028f534a62e019b4a52967bb8642ede6becfa3807be68fdd36d366fc84a4ac8dc176e80a68bc59eb62caf5dff9 +8c3b8be685b0f8aad131ee7544d0e12f223f08a6f8edaf464b385ac644e0ddc9eff7cc7cb5c1b50ab5d71ea0f41d2213 +8d91410e004f76c50fdc05784157b4d839cb5090022c629c7c97a5e0c3536eeafee17a527b54b1165c3cd81774bb54ce +b25c2863bc28ec5281ce800ddf91a7e1a53f4c6d5da1e6c86ef4616e93bcf55ed49e297216d01379f5c6e7b3c1e46728 +865f7b09ac3ca03f20be90c48f6975dd2588838c2536c7a3532a6aa5187ed0b709cd03d91ff4048061c10d0aa72b69ce +b3f7477c90c11596eb4f8bbf34adbcb832638c4ff3cdd090d4d477ee50472ac9ddaf5be9ad7eca3f148960d362bbd098 +8db35fd53fca04faecd1c76a8227160b3ab46ac1af070f2492445a19d8ff7c25bbaef6c9fa0c8c088444561e9f7e4eb2 +a478b6e9d058a2e01d2fc053b739092e113c23a6a2770a16afbef044a3709a9e32f425ace9ba7981325f02667c3f9609 +98caa6bd38916c08cf221722a675a4f7577f33452623de801d2b3429595f988090907a7e99960fff7c076d6d8e877b31 +b79aaaacefc49c3038a14d2ac468cfec8c2161e88bdae91798d63552cdbe39e0e02f9225717436b9b8a40a022c633c6e +845a31006c680ee6a0cc41d3dc6c0c95d833fcf426f2e7c573fa15b2c4c641fbd6fe5ebb0e23720cc3467d6ee1d80dc4 +a1bc287e272cf8b74dbf6405b3a5190883195806aa351f1dc8e525aa342283f0a35ff687e3b434324dedee74946dd185 +a4fd2dc8db75d3783a020856e2b3aa266dc6926e84f5c491ef739a3bddd46dc8e9e0fc1177937839ef1b18d062ffbb9e +acbf0d3c697f57c202bb8c5dc4f3fc341b8fc509a455d44bd86acc67cad2a04495d5537bcd3e98680185e8aa286f2587 +a5caf423a917352e1b8e844f5968a6da4fdeae467d10c6f4bbd82b5eea46a660b82d2f5440d3641c717b2c3c9ed0be52 +8a39d763c08b926599ab1233219c49c825368fad14d9afc7c0c039224d37c00d8743293fd21645bf0b91eaf579a99867 +b2b53a496def0ba06e80b28f36530fbe0fb5d70a601a2f10722e59abee529369c1ae8fd0f2db9184dd4a2519bb832d94 +a73980fcef053f1b60ebbb5d78ba6332a475e0b96a0c724741a3abf3b59dd344772527f07203cf4c9cb5155ebed81fa0 +a070d20acce42518ece322c9db096f16aed620303a39d8d5735a0df6e70fbeceb940e8d9f5cc38f3314b2240394ec47b +a50cf591f522f19ca337b73089557f75929d9f645f3e57d4f241e14cdd1ea3fb48d84bcf05e4f0377afbb789fbdb5d20 +82a5ffce451096aca8eeb0cd2ae9d83db3ed76da3f531a80d9a70a346359bf05d74863ce6a7c848522b526156a5e20cd +88e0e84d358cbb93755a906f329db1537c3894845f32b9b0b691c29cbb455373d9452fadd1e77e20a623f6eaf624de6f +aa07ac7b84a6d6838826e0b9e350d8ec75e398a52e9824e6b0da6ae4010e5943fec4f00239e96433f291fef9d1d1e609 +ac8887bf39366034bc63f6cc5db0c26fd27307cbc3d6cce47894a8a019c22dd51322fb5096edc018227edfafc053a8f6 +b7d26c26c5b33f77422191dca94977588ab1d4b9ce7d0e19c4a3b4cd1c25211b78c328dbf81e755e78cd7d1d622ad23e +99a676d5af49f0ba44047009298d8474cabf2d5bca1a76ba21eff7ee3c4691a102fdefea27bc948ccad8894a658abd02 +b0d09a91909ab3620c183bdf1d53d43d39eb750dc7a722c661c3de3a1a5d383ad221f71bae374f8a71867505958a3f76 +84681a883de8e4b93d68ac10e91899c2bbb815ce2de74bb48a11a6113b2a3f4df8aceabda1f5f67bc5aacac8c9da7221 +9470259957780fa9b43521fab3644f555f5343281c72582b56d2efd11991d897b3b481cafa48681c5aeb80c9663b68f7 +ab1b29f7ece686e6fa968a4815da1d64f3579fed3bc92e1f3e51cd13a3c076b6cf695ed269d373300a62463dc98a4234 +8ab415bfcd5f1061f7687597024c96dd9c7cb4942b5989379a7a3b5742f7d394337886317659cbeacaf030234a24f972 +b9b524aad924f9acc63d002d617488f31b0016e0f0548f050cada285ce7491b74a125621638f19e9c96eabb091d945be +8c4c373e79415061837dd0def4f28a2d5d74d21cb13a76c9049ad678ca40228405ab0c3941df49249847ecdefc1a5b78 +a8edf4710b5ab2929d3db6c1c0e3e242261bbaa8bcec56908ddadd7d2dad2dca9d6eb9de630b960b122ebeea41040421 +8d66bb3b50b9df8f373163629f9221b3d4b6980a05ea81dc3741bfe9519cf3ebba7ab98e98390bae475e8ede5821bd5c +8d3c21bae7f0cfb97c56952bb22084b58e7bb718890935b73103f33adf5e4d99cd262f929c6eeab96209814f0dbae50a +a5c66cfab3d9ebf733c4af24bebc97070e7989fe3c73e79ac85fb0e4d40ae44fb571e0fad4ad72560e13ed453900d14f +9362e6b50b43dbefbc3254471372297b5dcce809cd3b60bf74a1268ab68bdb50e46e462cbd78f0d6c056330e982846af +854630d08e3f0243d570cc2e856234cb4c1a158d9c1883bf028a76525aaa34be897fe918d5f6da9764a3735fa9ebd24a +8c7d246985469ff252c3f4df6c7c9196fc79f05c1c66a609d84725c78001d0837c7a7049394ba5cf7e863e2d58af8417 +ae050271e01b528925302e71903f785b782f7bf4e4e7a7f537140219bc352dc7540c657ed03d3a297ad36798ecdb98cd +8d2ae9179fcf2b0c69850554580b52c1f4a5bd865af5f3028f222f4acad9c1ad69a8ef6c7dc7b03715ee5c506b74325e +b8ef8de6ce6369a8851cd36db0ccf00a85077e816c14c4e601f533330af9e3acf0743a95d28962ed8bfcfc2520ef3cfe +a6ecad6fdfb851b40356a8b1060f38235407a0f2706e7b8bb4a13465ca3f81d4f5b99466ac2565c60af15f022d26732e +819ff14cdea3ab89d98e133cd2d0379361e2e2c67ad94eeddcdb9232efd509f51d12f4f03ebd4dd953bd262a886281f7 +8561cd0f7a6dbcddd83fcd7f472d7dbcba95b2d4fb98276f48fccf69f76d284e626d7e41314b633352df8e6333fd52a1 +b42557ccce32d9a894d538c48712cb3e212d06ac05cd5e0527ccd2db1078ee6ae399bf6a601ffdab1f5913d35fc0b20c +89b4008d767aad3c6f93c349d3b956e28307311a5b1cec237e8d74bb0dee7e972c24f347fd56afd915a2342bd7bc32f0 +877487384b207e53f5492f4e36c832c2227f92d1bb60542cfeb35e025a4a7afc2b885fae2528b33b40ab09510398f83e +8c411050b63c9053dd0cd81dacb48753c3d7f162028098e024d17cd6348482703a69df31ad6256e3d25a8bbf7783de39 +a8506b54a88d17ac10fb1b0d1fe4aa40eae7553a064863d7f6b52ccc4236dd4b82d01dca6ba87da9a239e3069ba879fb +b1a24caef9df64750c1350789bb8d8a0db0f39474a1c74ea9ba064b1516db6923f00af8d57c632d58844fb8786c3d47a +959d6e255f212b0708c58a2f75cb1fe932248c9d93424612c1b8d1e640149656059737e4db2139afd5556bcdacf3eda2 +84525af21a8d78748680b6535bbc9dc2f0cf9a1d1740d12f382f6ecb2e73811d6c1da2ad9956070b1a617c61fcff9fe5 +b74417d84597a485d0a8e1be07bf78f17ebb2e7b3521b748f73935b9afbbd82f34b710fb7749e7d4ab55b0c7f9de127d +a4a9aecb19a6bab167af96d8b9d9aa5308eab19e6bfb78f5a580f9bf89bdf250a7b52a09b75f715d651cb73febd08e84 +9777b30be2c5ffe7d29cc2803a562a32fb43b59d8c3f05a707ab60ec05b28293716230a7d264d7cd9dd358fc031cc13e +95dce7a3d4f23ac0050c510999f5fbf8042f771e8f8f94192e17bcbfa213470802ebdbe33a876cb621cf42e275cbfc8b +b0b963ebcbbee847ab8ae740478544350b3ac7e86887e4dfb2299ee5096247cd2b03c1de74c774d9bde94ae2ee2dcd59 +a4ab20bafa316030264e13f7ef5891a2c3b29ab62e1668fcb5881f50a9acac6adbe3d706c07e62f2539715db768f6c43 +901478a297669d608e406fe4989be75264b6c8be12169aa9e0ad5234f459ca377f78484ffd2099a2fe2db5e457826427 +88c76e5c250810c057004a03408b85cd918e0c8903dc55a0dd8bb9b4fc2b25c87f9b8cf5943eb19fbbe99d36490050c5 +91607322bbad4a4f03fc0012d0821eff5f8c516fda45d1ec1133bface6f858bf04b25547be24159cab931a7aa08344d4 +843203e07fce3c6c81f84bc6dc5fb5e9d1c50c8811ace522dc66e8658433a0ef9784c947e6a62c11bf705307ef05212e +91dd8813a5d6dddcda7b0f87f672b83198cd0959d8311b2b26fb1fae745185c01f796fbd03aad9db9b58482483fdadd8 +8d15911aacf76c8bcd7136e958febd6963104addcd751ce5c06b6c37213f9c4fb0ffd4e0d12c8e40c36d658999724bfd +8a36c5732d3f1b497ebe9250610605ee62a78eaa9e1a45f329d09aaa1061131cf1d9df00f3a7d0fe8ad614a1ff9caaae +a407d06affae03660881ce20dab5e2d2d6cddc23cd09b95502a9181c465e57597841144cb34d22889902aff23a76d049 +b5fd856d0578620a7e25674d9503be7d97a2222900e1b4738c1d81ff6483b144e19e46802e91161e246271f90270e6cf +91b7708869cdb5a7317f88c0312d103f8ce90be14fb4f219c2e074045a2a83636fdc3e69e862049fc7c1ef000e832541 +b64719cc5480709d1dae958f1d3082b32a43376da446c8f9f64cb02a301effc9c34d9102051733315a8179aed94d53cc +94347a9542ff9d18f7d9eaa2f4d9b832d0e535fe49d52aa2de08aa8192400eddabdb6444a2a78883e27c779eed7fdf5a +840ef44a733ff1376466698cd26f82cf56bb44811e196340467f932efa3ae1ef9958a0701b3b032f50fd9c1d2aed9ab5 +90ab3f6f67688888a31ffc2a882bb37adab32d1a4b278951a21646f90d03385fc976715fc639a785d015751171016f10 +b56f35d164c24b557dbcbc8a4bfa681ec916f8741ffcb27fb389c164f4e3ed2be325210ef5bdaeae7a172ca9599ab442 +a7921a5a80d7cf6ae81ba9ee05e0579b18c20cd2852762c89d6496aa4c8ca9d1ca2434a67b2c16d333ea8e382cdab1e3 +a506bcfbd7e7e5a92f68a1bd87d07ad5fe3b97aeee40af2bf2cae4efcd77fff03f872732c5b7883aa6584bee65d6f8cb +a8c46cff58931a1ce9cbe1501e1da90b174cddd6d50f3dfdfb759d1d4ad4673c0a8feed6c1f24c7af32865a7d6c984e5 +b45686265a83bff69e312c5149db7bb70ac3ec790dc92e392b54d9c85a656e2bf58596ce269f014a906eafc97461aa5f +8d4009a75ccb2f29f54a5f16684b93202c570d7a56ec1a8b20173269c5f7115894f210c26b41e8d54d4072de2d1c75d0 +aef8810af4fc676bf84a0d57b189760ddc3375c64e982539107422e3de2580b89bd27aa6da44e827b56db1b5555e4ee8 +888f0e1e4a34f48eb9a18ef4de334c27564d72f2cf8073e3d46d881853ac1424d79e88d8ddb251914890588937c8f711 +b64b0aa7b3a8f6e0d4b3499fe54e751b8c3e946377c0d5a6dbb677be23736b86a7e8a6be022411601dd75012012c3555 +8d57776f519f0dd912ea14f79fbab53a30624e102f9575c0bad08d2dc754e6be54f39b11278c290977d9b9c7c0e1e0ad +a018fc00d532ceb2e4de908a15606db9b6e0665dd77190e2338da7c87a1713e6b9b61554e7c1462f0f6d4934b960b15c +8c932be83ace46f65c78e145b384f58e41546dc0395270c1397874d88626fdeda395c8a289d602b4c312fe98c1311856 +89174838e21639d6bdd91a0621f04dc056907b88e305dd66e46a08f6d65f731dea72ae87ca5e3042d609e8de8de9aa26 +b7b7f508bb74f7a827ac8189daa855598ff1d96fa3a02394891fd105d8f0816224cd50ac4bf2ed1cf469ace516c48184 +b31877ad682583283baadd68dc1bebd83f5748b165aadd7fe9ef61a343773b88bcd3a022f36d6c92f339b7bfd72820a9 +b79d77260b25daf9126dab7a193df2d7d30542786fa1733ffaf6261734770275d3ca8bae1d9915d1181a78510b3439db +91894fb94cd4c1dd2ceaf9c53a7020c5799ba1217cf2d251ea5bc91ed26e1159dd758e98282ebe35a0395ef9f1ed15a0 +ab59895cdafd33934ceedfc3f0d5d89880482cba6c99a6db93245f9e41987efd76e0640e80aef31782c9a8c7a83fccec +aa22ea63654315e033e09d4d4432331904a6fc5fb1732557987846e3c564668ca67c60a324b4af01663a23af11a9ce4b +b53ba3ef342601467e1f71aa280e100fbabbd38518fa0193e0099505036ee517c1ac78e96e9baeb549bb6879bb698fb0 +943fd69fd656f37487cca3605dc7e5a215fddd811caf228595ec428751fc1de484a0cb84c667fe4d7c35599bfa0e5e34 +9353128b5ebe0dddc555093cf3e5942754f938173541033e8788d7331fafc56f68d9f97b4131e37963ab7f1c8946f5f1 +a76cd3c566691f65cfb86453b5b31dbaf3cab8f84fe1f795dd1e570784b9b01bdd5f0b3c1e233942b1b5838290e00598 +983d84b2e53ffa4ae7f3ba29ef2345247ea2377686b74a10479a0ef105ecf90427bf53b74c96dfa346d0f842b6ffb25b +92e0fe9063306894a2c6970c001781cff416c87e87cb5fbac927a3192655c3da4063e6fa93539f6ff58efac6adcc5514 +b00a81f03c2b8703acd4e2e4c21e06973aba696415d0ea1a648ace2b0ea19b242fede10e4f9d7dcd61c546ab878bc8f9 +b0d08d880f3b456a10bf65cff983f754f545c840c413aea90ce7101a66eb0a0b9b1549d6c4d57725315828607963f15a +90cb64d03534f913b411375cce88a9e8b1329ce67a9f89ca5df8a22b8c1c97707fec727dbcbb9737f20c4cf751359277 +8327c2d42590dfcdb78477fc18dcf71608686ad66c49bce64d7ee874668be7e1c17cc1042a754bbc77c9daf50b2dae07 +8532171ea13aa7e37178e51a6c775da469d2e26ec854eb16e60f3307db4acec110d2155832c202e9ba525fc99174e3b0 +83ca44b15393d021de2a511fa5511c5bd4e0ac7d67259dce5a5328f38a3cce9c3a269405959a2486016bc27bb140f9ff +b1d36e8ca812be545505c8214943b36cabee48112cf0de369957afa796d37f86bf7249d9f36e8e990f26f1076f292b13 +9803abf45be5271e2f3164c328d449efc4b8fc92dfc1225d38e09630909fe92e90a5c77618daa5f592d23fc3ad667094 +b268ad68c7bf432a01039cd889afae815c3e120f57930d463aece10af4fd330b5bd7d8869ef1bcf6b2e78e4229922edc +a4c91a0d6f16b1553264592b4cbbbf3ca5da32ab053ffbdd3dbb1aed1afb650fb6e0dc5274f71a51d7160856477228db +ad89d043c2f0f17806277ffdf3ecf007448e93968663f8a0b674254f36170447b7527d5906035e5e56f4146b89b5af56 +8b6964f757a72a22a642e4d69102951897e20c21449184e44717bd0681d75f7c5bfa5ee5397f6e53febf85a1810d6ed1 +b08f5cdaabec910856920cd6e836c830b863eb578423edf0b32529488f71fe8257d90aed4a127448204df498b6815d79 +af26bb3358be9d280d39b21d831bb53145c4527a642446073fee5a86215c4c89ff49a3877a7a549486262f6f57a0f476 +b4010b37ec4d7c2af20800e272539200a6b623ae4636ecbd0e619484f4ab9240d02bc5541ace3a3fb955dc0a3d774212 +82752ab52bdcc3cc2fc405cb05a2e694d3df4a3a68f2179ec0652536d067b43660b96f85f573f26fbd664a9ef899f650 +96d392dde067473a81faf2d1fea55b6429126b88b160e39b4210d31d0a82833ffd3a80e07d24d495aea2d96be7251547 +a76d8236d6671204d440c33ac5b8deb71fa389f6563d80e73be8b043ec77d4c9b06f9a586117c7f957f4af0331cbc871 +b6c90961f68b5e385d85c9830ec765d22a425f506904c4d506b87d8944c2b2c09615e740ed351df0f9321a7b93979cae +a6ec5ea80c7558403485b3b1869cdc63bde239bafdf936d9b62a37031628402a36a2cfa5cfbb8e26ac922cb0a209b3ba +8c3195bbdbf9bc0fc95fa7e3d7f739353c947f7767d1e3cb24d8c8602d8ea0a1790ac30b815be2a2ba26caa5227891e2 +a7f8a63d809f1155722c57f375ea00412b00147776ae4444f342550279ef4415450d6f400000a326bf11fea6c77bf941 +97fa404df48433a00c85793440e89bb1af44c7267588ae937a1f5d53e01e1c4d4fc8e4a6d517f3978bfdd6c2dfde012f +a984a0a3836de3d8d909c4629a2636aacb85393f6f214a2ef68860081e9db05ad608024762db0dc35e895dc00e2d4cdd +9526cf088ab90335add1db4d3a4ac631b58cbfbe88fa0845a877d33247d1cfeb85994522e1eb8f8874651bfb1df03e2a +ac83443fd0afe99ad49de9bf8230158c118e2814c9c89db5ac951c240d6c2ce45e7677221279d9e97848ec466b99aafe +aeeefdbaba612e971697798ceaf63b247949dc823a0ad771ae5b988a5e882b338a98d3d0796230f49d533ec5ba411b39 +ae3f248b5a7b0f92b7820a6c5ae21e5bd8f4265d4f6e21a22512079b8ee9be06393fd3133ce8ebac0faf23f4f8517e36 +a64a831b908eee784b8388b45447d2885ec0551b26b0c2b15e5f417d0a12c79e867fb7bd3d008d0af98b44336f8ec1ad +b242238cd8362b6e440ba21806905714dd55172db25ec7195f3fc4937b2aba146d5cbf3cf691a1384b4752dc3b54d627 +819f97f337eea1ffb2a678cc25f556f1aab751c6b048993a1d430fe1a3ddd8bb411c152e12ca60ec6e057c190cd1db9a +b9d7d187407380df54ee9fef224c54eec1bfabf17dc8abf60765b7951f538f59aa26fffd5846cfe05546c35f59b573f4 +aa6e3c14efa6a5962812e3f94f8ce673a433f4a82d07a67577285ea0eaa07f8be7115853122d12d6d4e1fdf64c504be1 +82268bee9c1662d3ddb5fb785abfae6fb8b774190f30267f1d47091d2cd4b3874db4372625aa36c32f27b0eee986269b +b236459565b7b966166c4a35b2fa71030b40321821b8e96879d95f0e83a0baf33fa25721f30af4a631df209e25b96061 +8708d752632d2435d2d5b1db4ad1fa2558d776a013655f88e9a3556d86b71976e7dfe5b8834fdec97682cd94560d0d0d +ae1424a68ae2dbfb0f01211f11773732a50510b5585c1fb005cb892b2c6a58f4a55490b5c5b4483c6fce40e9d3236a52 +b3f5f722af9dddb07293c871ce97abbccba0093ca98c8d74b1318fa21396fc1b45b69c15084f63d728f9908442024506 +9606f3ce5e63886853ca476dc0949e7f1051889d529365c0cb0296fdc02abd088f0f0318ecd2cf36740a3634132d36f6 +b11a833a49fa138db46b25ff8cdda665295226595bc212c0931b4931d0a55c99da972c12b4ef753f7e37c6332356e350 +afede34e7dab0a9e074bc19a7daddb27df65735581ca24ad70c891c98b1349fcebbcf3ba6b32c2617fe06a5818dabc2d +97993d456e459e66322d01f8eb13918979761c3e8590910453944bdff90b24091bb018ac6499792515c9923be289f99f +977e3e967eff19290a192cd11df3667d511b398fb3ac9a5114a0f3707e25a0edcb56105648b1b85a8b7519fc529fc6f6 +b873a7c88bf58731fe1bf61ff6828bf114cf5228f254083304a4570e854e83748fc98683ddba62d978fff7909f2c5c47 +ad4b2691f6f19da1d123aaa23cca3e876247ed9a4ab23c599afdbc0d3aa49776442a7ceaa996ac550d0313d9b9a36cee +b9210713c78e19685608c6475bfa974b57ac276808a443f8b280945c5d5f9c39da43effa294bfb1a6c6f7b6b9f85bf6c +a65152f376113e61a0e468759de38d742caa260291b4753391ee408dea55927af08a4d4a9918600a3bdf1df462dffe76 +8bf8c27ad5140dde7f3d2280fd4cc6b29ab76537e8d7aa7011a9d2796ee3e56e9a60c27b5c2da6c5e14fc866301dc195 +92fde8effc9f61393a2771155812b863cff2a0c5423d7d40aa04d621d396b44af94ddd376c28e7d2f53c930aea947484 +97a01d1dd9ee30553ce676011aea97fa93d55038ada95f0057d2362ae9437f3ed13de8290e2ff21e3167dd7ba10b9c3f +89affffaa63cb2df3490f76f0d1e1d6ca35c221dd34057176ba739fa18d492355e6d2a5a5ad93a136d3b1fed0bb8aa19 +928b8e255a77e1f0495c86d3c63b83677b4561a5fcbbe5d3210f1e0fc947496e426d6bf3b49394a5df796c9f25673fc4 +842a0af91799c9b533e79ee081efe2a634cac6c584c2f054fb7d1db67dde90ae36de36cbf712ec9cd1a0c7ee79e151ea +a65b946cf637e090baf2107c9a42f354b390e7316beb8913638130dbc67c918926eb87bec3b1fe92ef72bc77a170fa3b +aafc0f19bfd71ab5ae4a8510c7861458b70ad062a44107b1b1dbacbfa44ba3217028c2824bd7058e2fa32455f624040b +95269dc787653814e0be899c95dba8cfa384f575a25e671c0806fd80816ad6797dc819d30ae06e1d0ed9cb01c3950d47 +a1e760f7fa5775a1b2964b719ff961a92083c5c617f637fc46e0c9c20ab233f8686f7f38c3cb27d825c54dd95e93a59b +ac3b8a7c2317ea967f229eddc3e23e279427f665c4705c7532ed33443f1243d33453c1088f57088d2ab1e3df690a9cc9 +b787beeddfbfe36dd51ec4efd9cf83e59e84d354c3353cc9c447be53ae53d366ed1c59b686e52a92f002142c8652bfe0 +b7a64198300cb6716aa7ac6b25621f8bdec46ad5c07a27e165b3f774cdf65bcfdbf31e9bae0c16b44de4b00ada7a4244 +b8ae9f1452909e0c412c7a7fe075027691ea8df1347f65a5507bc8848f1d2c833d69748076db1129e5b4fb912f65c86c +9682e41872456b9fa67def89e71f06d362d6c8ca85c9c48536615bc401442711e1c9803f10ab7f8ab5feaec0f9df20a6 +88889ff4e271dc1c7e21989cc39f73cde2f0475acd98078281591ff6c944fadeb9954e72334319050205d745d4df73df +8f79b5b8159e7fd0d93b0645f3c416464f39aec353b57d99ecf24f96272df8a068ad67a6c90c78d82c63b40bb73989bb +838c01a009a3d8558a3f0bdd5e22de21af71ca1aefc8423c91dc577d50920e9516880e87dce3e6d086e11cd45c9052d9 +b97f1c6eee8a78f137c840667cc288256e39294268a3009419298a04a1d0087c9c9077b33c917c65caf76637702dda8a +972284ce72f96a61c899260203dfa06fc3268981732bef74060641c1a5068ead723e3399431c247ca034b0dae861e8df +945a8d52d6d3db6663dbd3110c6587f9e9c44132045eeffba15621576d178315cb52870fa5861669f84f0bee646183fe +a0a547b5f0967b1c3e5ec6c6a9a99f0578521489180dfdfbb5561f4d166baac43a2f06f950f645ce991664e167537eed +a0592cda5cdddf1340033a745fd13a6eff2021f2e26587116c61c60edead067e0f217bc2bef4172a3c9839b0b978ab35 +b9c223b65a3281587fa44ec829e609154b32f801fd1de6950e01eafb07a8324243b960d5735288d0f89f0078b2c42b5b +99ebfc3b8f9f98249f4d37a0023149ed85edd7a5abe062c8fb30c8c84555258b998bdcdd1d400bc0fa2a4aaa8b224466 +955b68526e6cb3937b26843270f4e60f9c6c8ece2fa9308fe3e23afa433309c068c66a4bc16ee2cf04220f095e9afce4 +b766caeafcc00378135ae53397f8a67ed586f5e30795462c4a35853de6681b1f17401a1c40958de32b197c083b7279c1 +921bf87cad947c2c33fa596d819423c10337a76fe5a63813c0a9dc78a728207ae7b339407a402fc4d0f7cba3af6da6fc +a74ba1f3bc3e6c025db411308f49b347ec91da1c916bda9da61e510ec8d71d25e0ac0f124811b7860e5204f93099af27 +a29b4d144e0bf17a7e8353f2824cef0ce85621396babe8a0b873ca1e8a5f8d508b87866cf86da348470649fceefd735c +a8040e12ffc3480dd83a349d06741d1572ef91932c46f5cf03aee8454254156ee95786fd013d5654725e674c920cec32 +8c4cf34ca60afd33923f219ffed054f90cd3f253ffeb2204a3b61b0183417e366c16c07fae860e362b0f2bfe3e1a1d35 +8195eede4ddb1c950459df6c396b2e99d83059f282b420acc34220cadeed16ab65c856f2c52568d86d3c682818ed7b37 +91fff19e54c15932260aa990c7fcb3c3c3da94845cc5aa8740ef56cf9f58d19b4c3c55596f8d6c877f9f4d22921d93aa +a3e0bf7e5d02a80b75cf75f2db7e66cb625250c45436e3c136d86297d652590ec97c2311bafe407ad357c79ab29d107b +81917ff87e5ed2ae4656b481a63ced9e6e5ff653b8aa6b7986911b8bc1ee5b8ef4f4d7882c3f250f2238e141b227e510 +915fdbe5e7de09c66c0416ae14a8750db9412e11dc576cf6158755fdcaf67abdbf0fa79b554cac4fe91c4ec245be073f +8df27eafb5c3996ba4dc5773c1a45ca77e626b52e454dc1c4058aa94c2067c18332280630cc3d364821ee53bf2b8c130 +934f8a17c5cbb827d7868f5c8ca00cb027728a841000a16a3428ab16aa28733f16b52f58c9c4fbf75ccc45df72d9c4df +b83f4da811f9183c25de8958bc73b504cf790e0f357cbe74ef696efa7aca97ad3b7ead1faf76e9f982c65b6a4d888fc2 +87188213c8b5c268dc2b6da413f0501c95749e953791b727450af3e43714149c115b596b33b63a2f006a1a271b87efd0 +83e9e888ab9c3e30761de635d9aabd31248cdd92f7675fc43e4b21fd96a03ec1dc4ad2ec94fec857ffb52683ac98e360 +b4b9a1823fe2d983dc4ec4e3aaea297e581c3fc5ab4b4af5fa1370caa37af2d1cc7fc6bfc5e7da60ad8fdce27dfe4b24 +856388bc78aef465dbcdd1f559252e028c9e9a2225c37d645c138e78f008f764124522705822a61326a6d1c79781e189 +a6431b36db93c3b47353ba22e7c9592c9cdfb9cbdd052ecf2cc3793f5b60c1e89bc96e6bae117bfd047f2308da00dd2f +b619972d48e7e4291542dcde08f7a9cdc883c892986ded2f23ccb216e245cd8d9ad1d285347b0f9d7611d63bf4cee2bc +8845cca6ff8595955f37440232f8e61d5351500bd016dfadd182b9d39544db77a62f4e0102ff74dd4173ae2c181d24ef +b2f5f7fa26dcd3b6550879520172db2d64ee6aaa213cbef1a12befbce03f0973a22eb4e5d7b977f466ac2bf8323dcedd +858b7f7e2d44bdf5235841164aa8b4f3d33934e8cb122794d90e0c1cac726417b220529e4f896d7b77902ab0ccd35b3a +80b0408a092dae2b287a5e32ea1ad52b78b10e9c12f49282976cd738f5d834e03d1ad59b09c5ccaccc39818b87d06092 +b996b0a9c6a2d14d984edcd6ab56bc941674102980d65b3ad9733455f49473d3f587c8cbf661228a7e125ddbe07e3198 +90224fcebb36865293bd63af786e0c5ade6b67c4938d77eb0cbae730d514fdd0fe2d6632788e858afd29d46310cf86df +b71351fdfff7168b0a5ec48397ecc27ac36657a8033d9981e97002dcca0303e3715ce6dd3f39423bc8ef286fa2e9e669 +ae2a3f078b89fb753ce4ed87e0c1a58bb19b4f0cfb6586dedb9fcab99d097d659a489fb40e14651741e1375cfc4b6c5f +8ef476b118e0b868caed297c161f4231bbeb863cdfa5e2eaa0fc6b6669425ce7af50dc374abceac154c287de50c22307 +92e46ab472c56cfc6458955270d3c72b7bde563bb32f7d4ab4d959db6f885764a3d864e1aa19802fefaa5e16b0cb0b54 +96a3f68323d1c94e73d5938a18a377af31b782f56212de3f489d22bc289cf24793a95b37f1d6776edf88114b5c1fa695 +962cc068cfce6faaa27213c4e43e44eeff0dfbb6d25b814e82c7da981fb81d7d91868fa2344f05fb552362f98cfd4a72 +895d4e4c4ad670abf66d43d59675b1add7afad7438ada8f42a0360c704cee2060f9ac15b4d27e9b9d0996bb801276fe3 +b3ad18d7ece71f89f2ef749b853c45dc56bf1c796250024b39a1e91ed11ca32713864049c9aaaea60cde309b47486bbf +8f05404e0c0258fdbae50e97ccb9b72ee17e0bd2400d9102c0dad981dac8c4c71585f03e9b5d50086d0a2d3334cb55d1 +8bd877e9d4591d02c63c6f9fc9976c109de2d0d2df2bfa5f6a3232bab5b0b8b46e255679520480c2d7a318545efa1245 +8d4c16b5d98957c9da13d3f36c46f176e64e5be879f22be3179a2c0e624fe4758a82bf8c8027410002f973a3b84cd55a +86e2a8dea86427b424fa8eada881bdff896907084a495546e66556cbdf070b78ba312bf441eb1be6a80006d25d5097a3 +8608b0c117fd8652fdab0495b08fadbeba95d9c37068e570de6fddfef1ba4a1773b42ac2be212836141d1bdcdef11a17 +a13d6febf5fb993ae76cae08423ca28da8b818d6ef0fde32976a4db57839cd45b085026b28ee5795f10a9a8e3098c683 +8e261967fa6de96f00bc94a199d7f72896a6ad8a7bbb1d6187cca8fad824e522880e20f766620f4f7e191c53321d70f9 +8b8e8972ac0218d7e3d922c734302803878ad508ca19f5f012bc047babd8a5c5a53deb5fe7c15a4c00fd6d1cb9b1dbd0 +b5616b233fb3574a2717d125a434a2682ff68546dccf116dd8a3b750a096982f185614b9fb6c7678107ff40a451f56fa +aa6adf9b0c3334b0d0663f583a4914523b2ac2e7adffdb026ab9109295ff6af003ef8357026dbcf789896d2afded8d73 +acb72df56a0b65496cd534448ed4f62950bb1e11e50873b6ed349c088ee364441821294ce0f7c61bd7d38105bea3b442 +abae12df83e01ec947249fedd0115dc501d2b03ff7232092979eda531dbbca29ace1d46923427c7dde4c17bdf3fd7708 +820b4fc2b63a9fda7964acf5caf19a2fc4965007cb6d6b511fcafcb1f71c3f673a1c0791d3f86e3a9a1eb6955b191cc0 +af277259d78c6b0f4f030a10c53577555df5e83319ddbad91afbd7c30bc58e7671c56d00d66ec3ab5ef56470cd910cee +ad4a861c59f1f5ca1beedd488fb3d131dea924fffd8e038741a1a7371fad7370ca5cf80dc01f177fbb9576713bb9a5b3 +b67a5162982ce6a55ccfb2f177b1ec26b110043cf18abd6a6c451cf140b5af2d634591eb4f28ad92177d8c7e5cd0a5e8 +96176d0a83816330187798072d449cbfccff682561e668faf6b1220c9a6535b32a6e4f852e8abb00f79abb87493df16b +b0afe6e7cb672e18f0206e4423f51f8bd0017bf464c4b186d46332c5a5847647f89ff7fa4801a41c1b0b42f6135bcc92 +8fc5e7a95ef20c1278c645892811f6fe3f15c431ebc998a32ec0da44e7213ea934ed2be65239f3f49b8ec471e9914160 +b7793e41adda6c82ba1f2a31f656f6205f65bf8a3d50d836ee631bc7ce77c153345a2d0fc5c60edf8b37457c3729c4ec +a504dd7e4d6b2f4379f22cc867c65535079c75ccc575955f961677fa63ecb9f74026fa2f60c9fb6323c1699259e5e9c8 +ab899d00ae693649cc1afdf30fb80d728973d2177c006e428bf61c7be01e183866614e05410041bc82cb14a33330e69c +8a3bd8b0b1be570b65c4432a0f6dc42f48a2000e30ab089cf781d38f4090467b54f79c0d472fcbf18ef6a00df69cc6f3 +b4d7028f7f76a96a3d7803fca7f507ae11a77c5346e9cdfccb120a833a59bda1f4264e425aa588e7a16f8e7638061d84 +b9c7511a76ea5fb105de905d44b02edb17008335766ee357ed386b7b3cf19640a98b38785cb14603c1192bee5886c9b6 +8563afb12e53aed71ac7103ab8602bfa8371ae095207cb0d59e8fd389b6ad1aff0641147e53cb6a7ca16c7f37c9c5e6b +8e108be614604e09974a9ed90960c28c4ea330a3d9a0cb4af6dd6f193f84ab282b243ecdf549b3131036bebc8905690c +b794d127fbedb9c5b58e31822361706ffac55ce023fbfe55716c3c48c2fd2f2c7660a67346864dfe588812d369cb50b6 +b797a3442fc3b44f41baefd30346f9ac7f96e770d010d53c146ce74ce424c10fb62758b7e108b8abfdc5fafd89d745cb +993bb71e031e8096442e6205625e1bfddfe6dd6a83a81f3e2f84fafa9e5082ab4cad80a099f21eff2e81c83457c725c3 +8711ab833fc03e37acf2e1e74cfd9133b101ff4144fe30260654398ae48912ab46549d552eb9d15d2ea57760d35ac62e +b21321fd2a12083863a1576c5930e1aecb330391ef83326d9d92e1f6f0d066d1394519284ddab55b2cb77417d4b0292f +877d98f731ffe3ee94b0b5b72d127630fa8a96f6ca4f913d2aa581f67732df6709493693053b3e22b0181632ac6c1e3b +ae391c12e0eb8c145103c62ea64f41345973311c3bf7281fa6bf9b7faafac87bcf0998e5649b9ef81e288c369c827e07 +b83a2842f36998890492ab1cd5a088d9423d192681b9a3a90ec518d4c541bce63e6c5f4df0f734f31fbfdd87785a2463 +a21b6a790011396e1569ec5b2a423857b9bec16f543e63af28024e116c1ea24a3b96e8e4c75c6537c3e4611fd265e896 +b4251a9c4aab3a495da7a42e684ba4860dbcf940ad1da4b6d5ec46050cbe8dab0ab9ae6b63b5879de97b905723a41576 +8222f70aebfe6ac037f8543a08498f4cadb3edaac00336fc00437eb09f2cba758f6c38e887cc634b4d5b7112b6334836 +86f05038e060594c46b5d94621a1d9620aa8ba59a6995baf448734e21f58e23c1ea2993d3002ad5250d6edd5ba59b34f +a7c0c749baef811ab31b973c39ceb1d94750e2bc559c90dc5eeb20d8bb6b78586a2b363c599ba2107d6be65cd435f24e +861d46a5d70b38d6c1cd72817a2813803d9f34c00320c8b62f8b9deb67f5b5687bc0b37c16d28fd017367b92e05da9ca +b3365d3dab639bffbe38e35383686a435c8c88b397b717cd4aeced2772ea1053ceb670f811f883f4e02975e5f1c4ac58 +a5750285f61ab8f64cd771f6466e2c0395e01b692fd878f2ef2d5c78bdd8212a73a3b1dfa5e4c8d9e1afda7c84857d3b +835a10809ccf939bc46cf950a33b36d71be418774f51861f1cd98a016ade30f289114a88225a2c11e771b8b346cbe6ef +a4f59473a037077181a0a62f1856ec271028546ca9452b45cedfcb229d0f4d1aabfc13062b07e536cc8a0d4b113156a2 +95cd14802180b224d44a73cc1ed599d6c4ca62ddcaa503513ccdc80aaa8be050cc98bd4b4f3b639549beb4587ac6caf9 +973b731992a3e69996253d7f36dd7a0af1982b5ed21624b77a7965d69e9a377b010d6dabf88a8a97eec2a476259859cc +af8a1655d6f9c78c8eb9a95051aa3baaf9c811adf0ae8c944a8d3fcba87b15f61021f3baf6996fa0aa51c81b3cb69de1 +835aad5c56872d2a2d6c252507b85dd742bf9b8c211ccb6b25b52d15c07245b6d89b2a40f722aeb5083a47cca159c947 +abf4e970b02bef8a102df983e22e97e2541dd3650b46e26be9ee394a3ea8b577019331857241d3d12b41d4eacd29a3ac +a13c32449dbedf158721c13db9539ae076a6ce5aeaf68491e90e6ad4e20e20d1cdcc4a89ed9fd49cb8c0dd50c17633c1 +8c8f78f88b7e22dd7e9150ab1c000f10c28e696e21d85d6469a6fe315254740f32e73d81ab1f3c1cf8f544c86df506e8 +b4b77f2acfe945abf81f2605f906c10b88fb4d28628487fb4feb3a09f17f28e9780445dfcee4878349d4c6387a9d17d4 +8d255c235f3812c6ecc646f855fa3832be5cb4dbb9c9e544989fafdf3f69f05bfd370732eaf954012f0044aa013fc9c6 +b982efd3f34b47df37c910148ac56a84e8116647bea24145a49e34e0a6c0176e3284d838dae6230cb40d0be91c078b85 +983f365aa09bd85df2a6a2ad8e4318996b1e27d02090755391d4486144e40d80b1fbfe1c798d626db92f52e33aa634da +95fd1981271f3ea3a41d654cf497e6696730d9ff7369f26bc4d7d15c7adb4823dd0c42e4a005a810af12d234065e5390 +a9f5219bd4b913c186ef30c02f995a08f0f6f1462614ea5f236964e02bdaa33db9d9b816c4aee5829947840a9a07ba60 +9210e6ceb05c09b46fd09d036287ca33c45124ab86315e5d6911ff89054f1101faaa3e83d123b7805056d388bcec6664 +8ed9cbf69c6ff3a5c62dd9fe0d7264578c0f826a29e614bc2fb4d621d90c8c9992438accdd7a614b1dca5d1bb73dc315 +85cf2a8cca93e00da459e3cecd22c342d697eee13c74d5851634844fc215f60053cf84b0e03c327cb395f48d1c71a8a4 +8818a18e9a2ec90a271b784400c1903089ffb0e0b40bc5abbbe12fbebe0f731f91959d98c5519ef1694543e31e2016d4 +8dabc130f296fa7a82870bf9a8405aaf542b222ed9276bba9bd3c3555a0f473acb97d655ee7280baff766a827a8993f0 +ac7952b84b0dc60c4d858f034093b4d322c35959605a3dad2b806af9813a4680cb038c6d7f4485b4d6b2ff502aaeca25 +ad65cb6d57b48a2602568d2ec8010baed0eb440eec7638c5ec8f02687d764e9de5b5d42ad5582934e592b48471c22d26 +a02ab8bd4c3d114ea23aebdd880952f9495912817da8c0c08eabc4e6755439899d635034413d51134c72a6320f807f1c +8319567764b8295402ec1ebef4c2930a138480b37e6d7d01c8b4c9cd1f2fc3f6e9a44ae6e380a0c469b25b06db23305f +afec53b2301dc0caa8034cd9daef78c48905e6068d692ca23d589b84a6fa9ddc2ed24a39480597e19cb3e83eec213b3f +ac0b4ffdb5ae08e586a9cdb98f9fe56f4712af3a97065e89e274feacfb52b53c839565aee93c4cfaaccfe51432c4fab0 +8972cbf07a738549205b1094c5987818124144bf187bc0a85287c94fdb22ce038c0f11df1aa16ec5992e91b44d1af793 +b7267aa6f9e3de864179b7da30319f1d4cb2a3560f2ea980254775963f1523b44c680f917095879bebfa3dc2b603efcf +80f68f4bfc337952e29504ee5149f15093824ea7ab02507efd1317a670f6cbc3611201848560312e3e52e9d9af72eccf +8897fee93ce8fc1e1122e46b6d640bba309384dbd92e46e185e6364aa8210ebf5f9ee7e5e604b6ffba99aa80a10dd7d0 +b58ea6c02f2360be60595223d692e82ee64874fda41a9f75930f7d28586f89be34b1083e03bbc1575bbfdda2d30db1ea +85a523a33d903280d70ac5938770453a58293480170c84926457ac2df45c10d5ff34322ab130ef4a38c916e70d81af53 +a2cbf045e1bed38937492c1f2f93a5ba41875f1f262291914bc1fc40c60bd0740fb3fea428faf6da38b7c180fe8ac109 +8c09328770ed8eb17afc6ac7ddd87bb476de18ed63cab80027234a605806895959990c47bd10d259d7f3e2ecb50074c9 +b4b9e19edb4a33bde8b7289956568a5b6b6557404e0a34584b5721fe6f564821091013fbb158e2858c6d398293bb4b59 +8a47377df61733a2aa5a0e945fce00267f8e950f37e109d4487d92d878fb8b573317bb382d902de515b544e9e233458d +b5804c9d97efeff5ca94f3689b8088c62422d92a1506fd1d8d3b1b30e8a866ad0d6dad4abfa051dfc4471250cac4c5d9 +9084a6ee8ec22d4881e9dcc8a9eb3c2513523d8bc141942370fd191ad2601bf9537a0b1e84316f3209b3d8a54368051e +85447eea2fa26656a649f8519fa67279183044791d61cf8563d0783d46d747d96af31d0a93507bbb2242666aa87d3720 +97566a84481027b60116c751aec552adfff2d9038e68d48c4db9811fb0cbfdb3f1d91fc176a0b0d988a765f8a020bce1 +ae87e5c1b9e86c49a23dceda4ecfd1dcf08567f1db8e5b6ec752ebd45433c11e7da4988573cdaebbb6f4135814fc059e +abee05cf9abdbc52897ac1ce9ed157f5466ed6c383d6497de28616238d60409e5e92619e528af8b62cc552bf09970dc2 +ae6d31cd7bf9599e5ee0828bab00ceb4856d829bba967278a73706b5f388465367aa8a6c7da24b5e5f1fdd3256ef8e63 +ac33e7b1ee47e1ee4af472e37ab9e9175260e506a4e5ce449788075da1b53c44cb035f3792d1eea2aa24b1f688cc6ed3 +80f65b205666b0e089bb62152251c48c380a831e5f277f11f3ef4f0d52533f0851c1b612267042802f019ec900dc0e8f +858520ad7aa1c9fed738e3b583c84168f2927837ad0e1d326afe9935c26e9b473d7f8c382e82ef1fe37d2b39bb40a1ee +b842dd4af8befe00a97c2d0f0c33c93974761e2cb9e5ab8331b25170318ddd5e4bdbc02d8f90cbfdd5f348f4f371c1f7 +8bf2cb79bc783cb57088aae7363320cbeaabd078ffdec9d41bc74ff49e0043d0dad0086a30e5112b689fd2f5a606365d +982eb03bbe563e8850847cd37e6a3306d298ab08c4d63ab6334e6b8c1fa13fce80cf2693b09714c7621d74261a0ff306 +b143edb113dec9f1e5105d4a93fbe502b859e587640d3db2f628c09a17060e6aec9e900e2c8c411cda99bc301ff96625 +af472d9befa750dcebc5428fe1a024f18ec1c07bca0f95643ce6b5f4189892a910285afb03fd7ed7068fbe614e80d33c +a97e3bc57ede73ecd1bbf02de8f51b4e7c1a067da68a3cd719f4ba26a0156cbf1cef2169fd35a18c5a4cced50d475998 +a862253c937cf3d75d7183e5f5be6a4385d526aeda5171c1c60a8381fea79f88f5f52a4fab244ecc70765d5765e6dfd5 +90cb776f8e5a108f1719df4a355bebb04bf023349356382cae55991b31720f0fd03206b895fa10c56c98f52453be8778 +a7614e8d0769dccd520ea4b46f7646e12489951efaef5176bc889e9eb65f6e31758df136b5bf1e9107e68472fa9b46ec +ac3a9b80a3254c42e5ed3a090a0dd7aee2352f480de96ad187027a3bb6c791eddfc3074b6ffd74eea825188f107cda4d +82a01d0168238ef04180d4b6e0a0e39024c02c2d75b065017c2928039e154d093e1af4503f4d1f3d8a948917abb5d09f +8fab000a2b0eef851a483aec8d2dd85fe60504794411a2f73ed82e116960547ac58766cb73df71aea71079302630258d +872451a35c6db61c63e9b8bb9f16b217f985c20be4451c14282c814adb29d7fb13f201367c664435c7f1d4d9375d7a58 +887d9ff54cc96b35d562df4a537ff972d7c4b3fd91ab06354969a4cfede0b9fc68bbffb61d0dbf1a58948dc701e54f5a +8cb5c2a6bd956875d88f41ae24574434f1308514d44057b55c9c70f13a3366ed054150eed0955a38fda3f757be73d55f +89ad0163cad93e24129d63f8e38422b7674632a8d0a9016ee8636184cab177659a676c4ee7efba3abe1a68807c656d60 +b9ec01c7cab6d00359b5a0b4a1573467d09476e05ca51a9227cd16b589a9943d161eef62dcc73f0de2ec504d81f4d252 +8031d17635d39dfe9705c485d2c94830b6fc9bc67b91300d9d2591b51e36a782e77ab5904662effa9382d9cca201f525 +8be5a5f6bc8d680e5092d6f9a6585acbaaaa2ddc671da560dcf5cfa4472f4f184b9597b5b539438accd40dda885687cc +b1fc0f052fae038a2e3de3b3a96b0a1024b009de8457b8b3adb2d315ae68a89af905720108a30038e5ab8d0d97087785 +8b8bdc77bd3a6bc7ca5492b6f8c614852c39a70d6c8a74916eaca0aeb4533b11898b8820a4c2620a97bf35e275480029 +af35f4dc538d4ad5cdf710caa38fd1eb496c3fa890a047b6a659619c5ad3054158371d1e88e0894428282eed9f47f76b +8166454a7089cc07758ad78724654f4e7a1a13e305bbf88ddb86f1a4b2904c4fc8ab872d7da364cdd6a6c0365239e2ad +ab287c7d3addce74ce40491871c768abe01daaa0833481276ff2e56926b38a7c6d2681ffe837d2cc323045ad1a4414f9 +b90317f4505793094d89365beb35537f55a6b5618904236258dd04ca61f21476837624a2f45fef8168acf732cab65579 +98ae5ea27448e236b6657ab5ef7b1cccb5372f92ab25f5fa651fbac97d08353a1dae1b280b1cd42b17d2c6a70a63ab9d +adcf54e752d32cbaa6cb98fbca48d8cd087b1db1d131d465705a0d8042c8393c8f4d26b59006eb50129b21e6240f0c06 +b591a3e4db18a7345fa935a8dd7994bbac5cc270b8ebd84c8304c44484c7a74afb45471fdbe4ab22156a30fae1149b40 +806b53ac049a42f1dcc1d6335505371da0bf27c614f441b03bbf2e356be7b2fb4eed7117eabcce9e427a542eaa2bf7d8 +800482e7a772d49210b81c4a907f5ce97f270b959e745621ee293cf8c71e8989363d61f66a98f2d16914439544ca84c7 +99de9eafdad3617445312341644f2bb888680ff01ce95ca9276b1d2e5ef83fa02dab5e948ebf66c17df0752f1bd37b70 +961ee30810aa4c93ae157fbe9009b8e443c082192bd36a73a6764ff9b2ad8b0948fe9a73344556e01399dd77badb4257 +ae0a361067c52efbe56c8adf982c00432cd478929459fc7f74052c8ee9531cd031fe1335418fde53f7c2ef34254eb7ac +a3503d16b6b27eb20c1b177bcf90d13706169220523a6271b85b2ce35a9a2b9c5bed088540031c0a4ebfdae3a4c6ab04 +909420122c3e723289ca4e7b81c2df5aff312972a2203f4c45821b176e7c862bf9cac7f7df3adf1d59278f02694d06e7 +989f42380ae904b982f85d0c6186c1aef5d6bcba29bcfbb658e811b587eb2749c65c6e4a8cc6409c229a107499a4f5d7 +8037a6337195c8e26a27ea4ef218c6e7d79a9720aaab43932d343192abc2320fe72955f5e431c109093bda074103330a +b312e168663842099b88445e940249cc508f080ab0c94331f672e7760258dbd86be5267e4cf25ea25facb80bff82a7e9 +aaa3ff8639496864fcdbfdda1ac97edc4f08e3c9288b768f6c8073038c9fbbf7e1c4bea169b4d45c31935cdf0680d45e +97dbd3df37f0b481a311dfc5f40e59227720f367912200d71908ef6650f32cc985cb05b981e3eea38958f7e48d10a15d +a89d49d1e267bb452d6cb621b9a90826fe55e9b489c0427b94442d02a16f390eed758e209991687f73f6b5a032321f42 +9530dea4e0e19d6496f536f2e75cf7d814d65fde567055eb20db48fd8d20d501cd2a22fb506db566b94c9ee10f413d43 +81a7009b9e67f1965fa7da6a57591c307de91bf0cd35ab4348dc4a98a4961e096d004d7e7ad318000011dc4342c1b809 +83440a9402b766045d7aca61a58bba2aa29cac1cf718199e472ba086f5d48093d9dda4d135292ba51d049a23964eceae +a06c9ce5e802df14f6b064a3d1a0735d429b452f0e2e276042800b0a4f16df988fd94cf3945921d5dd3802ab2636f867 +b1359e358b89936dee9e678a187aad3e9ab14ac40e96a0a68f70ee2583cdcf467ae03bef4215e92893f4e12f902adec8 +835304f8619188b4d14674d803103d5a3fa594d48e96d9699e653115dd05fdc2dda6ba3641cf7ad53994d448da155f02 +8327cba5a9ff0d3f5cd0ae55e77167448926d5fcf76550c0ad978092a14122723090c51c415e88e42a2b62eb07cc3981 +b373dcdaea85f85ce9978b1426a7ef4945f65f2d3467a9f1cc551a99766aac95df4a09e2251d3f89ca8c9d1a7cfd7b0e +ab1422dc41af2a227b973a6fd124dfcb2367e2a11a21faa1d381d404f51b7257e5bc82e9cf20cd7fe37d7ae761a2ab37 +a93774a03519d2f20fdf2ef46547b0a5b77c137d6a3434b48d56a2cbef9e77120d1b85d0092cf8842909213826699477 +8eb967a495a38130ea28711580b7e61bcd1d051cd9e4f2dbf62f1380bd86e0d60e978d72f6f31e909eb97b3b9a2b867c +ae8213378da1287ba1fe4242e1acaec19b877b6fe872400013c6eac1084b8d03156792fa3020201725b08228a1e80f49 +b143daf6893d674d607772b3b02d8ac48f294237e2f2c87963c0d4e26d9227d94a2a13512457c3d5883544bbc259f0ef +b343bd2aca8973888e42542218924e2dda2e938fd1150d06878af76f777546213912b7c7a34a0f94186817d80ffa185c +b188ebc6a8c3007001aa347ae72cc0b15d09bc6c19a80e386ee4b334734ec0cc2fe8b493c2422f38d1e6d133cc3db6fe +b795f6a8b9b826aaeee18ccd6baf6c5adeeec85f95eb5b6d19450085ec7217e95a2d9e221d77f583b297d0872073ba0e +b1c7dbd998ad32ae57bfa95deafa147024afd57389e98992c36b6e52df915d3d5a39db585141ec2423173e85d212fed8 +812bcdeb9fe5f12d0e1df9964798056e1f1c3de3b17b6bd2919b6356c4b86d8e763c01933efbe0224c86a96d5198a4be +b19ebeda61c23d255cbf472ef0b8a441f4c55b70f0d8ed47078c248b1d3c7c62e076b43b95c00a958ec8b16d5a7cb0d7 +b02adc9aaa20e0368a989c2af14ff48b67233d28ebee44ff3418bb0473592e6b681af1cc45450bd4b175df9051df63d9 +8d87f0714acee522eb58cec00360e762adc411901dba46adc9227124fa70ee679f9a47e91a6306d6030dd4eb8de2f3c1 +8be54cec21e74bcc71de29dc621444263737db15f16d0bb13670f64e42f818154e04b484593d19ef95f2ee17e4b3fe21 +ab8e20546c1db38d31493b5d5f535758afb17e459645c1b70813b1cf7d242fd5d1f4354a7c929e8f7259f6a25302e351 +89f035a1ed8a1e302ac893349ba8ddf967580fcb6e73d44af09e3929cde445e97ff60c87dafe489e2c0ab9c9986cfa00 +8b2b0851a795c19191a692af55f7e72ad2474efdc5401bc3733cfdd910e34c918aaebe69d5ea951bdddf3c01cabbfc67 +a4edb52c2b51495ccd1ee6450fc14b7b3ede8b3d106808929d02fb31475bacb403e112ba9c818d2857651e508b3a7dd1 +9569341fded45d19f00bcf3cbf3f20eb2b4d82ef92aba3c8abd95866398438a2387437e580d8b646f17cf6fde8c5af23 +aa4b671c6d20f72f2f18a939a6ff21cc37e0084b44b4a717f1be859a80b39fb1be026b3205adec2a66a608ec2bcd578f +94902e980de23c4de394ad8aec91b46f888d18f045753541492bfbb92c59d3daa8de37ae755a6853744af8472ba7b72b +af651ef1b2a0d30a7884557edfad95b6b5d445a7561caebdc46a485aedd25932c62c0798465c340a76f6feaa196dd712 +b7b669b8e5a763452128846dd46b530dca4893ace5cc5881c7ddcd3d45969d7e73fbebdb0e78aa81686e5f7b22ec5759 +82507fd4ebe9fa656a7f2e084d64a1fa6777a2b0bc106d686e2d9d2edafc58997e58cb6bfd0453b2bf415704aa82ae62 +b40bce2b42b88678400ecd52955bbdadd15f8b9e1b3751a1a3375dc0efb5ca3ee258cf201e1140b3c09ad41217d1d49e +b0210d0cbb3fbf3b8cdb39e862f036b0ff941cd838e7aaf3a8354e24246e64778d22f3de34572e6b2a580614fb6425be +876693cba4301b251523c7d034108831df3ce133d8be5a514e7a2ca494c268ca0556fa2ad8310a1d92a16b55bcd99ea9 +8660281406d22a4950f5ef050bf71dd3090edb16eff27fa29ef600cdea628315e2054211ed2cc6eaf8f2a1771ef689fd +a610e7e41e41ab66955b809ba4ade0330b8e9057d8efc9144753caed81995edeb1a42a53f93ce93540feca1fae708dac +a49e2c176a350251daef1218efaccc07a1e06203386ede59c136699d25ca5cb2ac1b800c25b28dd05678f14e78e51891 +83e0915aa2b09359604566080d411874af8c993beba97d4547782fdbe1a68e59324b800ff1f07b8db30c71adcbd102a8 +a19e84e3541fb6498e9bb8a099c495cbfcad113330e0262a7e4c6544495bb8a754b2208d0c2d895c93463558013a5a32 +87f2bd49859a364912023aca7b19a592c60214b8d6239e2be887ae80b69ebdeb59742bdebcfa73a586ab23b2c945586c +b8e8fdddae934a14b57bc274b8dcd0d45ebb95ddbaabef4454e0f6ce7d3a5a61c86181929546b3d60c447a15134d08e1 +87e0c31dcb736ea4604727e92dc1d9a3cf00adcff79df3546e02108355260f3dd171531c3c0f57be78d8b28058fcc8c0 +9617d74e8f808a4165a8ac2e30878c349e1c3d40972006f0787b31ea62d248c2d9f3fc3da83181c6e57e95feedfd0e8c +8949e2cee582a2f8db86e89785a6e46bc1565c2d8627d5b6bf43ba71ffadfab7e3c5710f88dcb5fb2fc6edf6f4fae216 +ad3fa7b0edceb83118972a2935a09f409d09a8db3869f30be3a76f67aa9fb379cabb3a3aff805ba023a331cad7d7eb64 +8c95718a4112512c4efbd496be38bf3ca6cdcaad8a0d128f32a3f9aae57f3a57bdf295a3b372a8c549fda8f4707cffed +88f3261d1e28a58b2dee3fcc799777ad1c0eb68b3560f9b4410d134672d9533532a91ea7be28a041784872632d3c9d80 +b47472a41d72dd2e8b72f5c4f8ad626737dde3717f63d6bc776639ab299e564cbad0a2ad5452a07f02ff49a359c437e5 +9896d21dc2e8aad87b76d6df1654f10cd7bceed4884159d50a818bea391f8e473e01e14684814c7780235f28e69dca6e +82d47c332bbd31bbe83b5eb44a23da76d4a7a06c45d7f80f395035822bc27f62f59281d5174e6f8e77cc9b5c3193d6f0 +95c74cd46206e7f70c9766117c34c0ec45c2b0f927a15ea167901a160e1530d8522943c29b61e03568aa0f9c55926c53 +a89d7757825ae73a6e81829ff788ea7b3d7409857b378ebccd7df73fdbe62c8d9073741cf038314971b39af6c29c9030 +8c1cd212d0b010905d560688cfc036ae6535bc334fa8b812519d810b7e7dcf1bb7c5f43deaa40f097158358987324a7f +b86993c383c015ed8d847c6b795164114dd3e9efd25143f509da318bfba89389ea72a420699e339423afd68b6512fafb +8d06bd379c6d87c6ed841d8c6e9d2d0de21653a073725ff74be1934301cc3a79b81ef6dd0aad4e7a9dc6eac9b73019bc +81af4d2d87219985b9b1202d724fe39ef988f14fef07dfe3c3b11714e90ffba2a97250838e8535eb63f107abfe645e96 +8c5e0af6330a8becb787e4b502f34f528ef5756e298a77dc0c7467433454347f3a2e0bd2641fbc2a45b95e231c6e1c02 +8e2a8f0f04562820dc8e7da681d5cad9fe2e85dd11c785fb6fba6786c57a857e0b3bd838fb849b0376c34ce1665e4837 +a39be8269449bfdfc61b1f62077033649f18dae9bef7c6163b9314ca8923691fb832f42776f0160b9e8abd4d143aa4e1 +8c154e665706355e1cc98e0a4cabf294ab019545ba9c4c399d666e6ec5c869ca9e1faf8fb06cd9c0a5c2f51a7d51b70a +a046a7d4de879d3ebd4284f08f24398e9e3bf006cd4e25b5c67273ade248689c69affff92ae810c07941e4904296a563 +afd94c1cb48758e5917804df03fb38a6da0e48cd9b6262413ea13b26973f9e266690a1b7d9d24bbaf7e82718e0e594b0 +859e21080310c8d6a38e12e2ac9f90a156578cdeb4bb2e324700e97d9a5511cd6045dc39d1d0de3f94aeed043a24119d +a219fb0303c379d0ab50893264919f598e753aac9065e1f23ef2949abc992577ab43c636a1d2c089203ec9ddb941e27d +b0fdb639d449588a2ca730afcba59334e7c387342d56defdfb7ef79c493f7fd0e5277eff18e7203e756c7bdda5803047 +87f9c3b7ed01f54368aca6dbcf2f6e06bff96e183c4b2c65f8baa23b377988863a0a125d5cdd41a072da8462ced4c070 +99ef7a5d5ac2f1c567160e1f8c95f2f38d41881850f30c461a205f7b1b9fb181277311333839b13fb3ae203447e17727 +aeaca9b1c2afd24e443326cc68de67b4d9cedb22ad7b501a799d30d39c85bb2ea910d4672673e39e154d699e12d9b3dc +a11675a1721a4ba24dd3d0e4c3c33a6edf4cd1b9f6b471070b4386c61f77452266eae6e3f566a40cfc885eada9a29f23 +b228334445e37b9b49cb4f2cc56b454575e92173ddb01370a553bba665adadd52df353ad74470d512561c2c3473c7bb9 +a18177087c996572d76f81178d18ed1ceebc8362a396348ce289f1d8bd708b9e99539be6fccd4acb1112381cfc5749b4 +8e7b8bf460f0d3c99abb19803b9e43422e91507a1c0c22b29ee8b2c52d1a384da4b87c292e28eff040db5be7b1f8641f +b03d038d813e29688b6e6f444eb56fec3abba64c3d6f890a6bcf2e916507091cdb2b9d2c7484617be6b26552ed1c56cb +a1c88ccd30e934adfc5494b72655f8afe1865a84196abfb376968f22ddc07761210b6a9fb7638f1413d1b4073d430290 +961b714faebf172ad2dbc11902461e286e4f24a99a939152a53406117767682a571057044decbeb3d3feef81f4488497 +a03dc4059b46effdd786a0a03cc17cfee8585683faa35bb07936ded3fa3f3a097f518c0b8e2db92fd700149db1937789 +adf60180c99ca574191cbcc23e8d025b2f931f98ca7dfcebfc380226239b6329347100fcb8b0fcb12db108c6ad101c07 +805d4f5ef24d46911cbf942f62cb84b0346e5e712284f82b0db223db26d51aabf43204755eb19519b00e665c7719fcaa +8dea7243e9c139662a7fe3526c6c601eee72fd8847c54c8e1f2ad93ef7f9e1826b170afe58817dac212427164a88e87f +a2ba42356606d651b077983de1ad643650997bb2babb188c9a3b27245bb65d2036e46667c37d4ce02cb1be5ae8547abe +af2ae50b392bdc013db2d12ce2544883472d72424fc767d3f5cb0ca2d973fc7d1f425880101e61970e1a988d0670c81b +98e6bec0568d3939b31d00eb1040e9b8b2a35db46ddf4369bdaee41bbb63cc84423d29ee510a170fb5b0e2df434ba589 +822ff3cd12fbef4f508f3ca813c04a2e0b9b799c99848e5ad3563265979e753ee61a48f6adc2984a850f1b46c1a43d35 +891e8b8b92a394f36653d55725ef514bd2e2a46840a0a2975c76c2a935577f85289026aaa74384da0afe26775cbddfb9 +b2a3131a5d2fe7c8967047aa66e4524babae941d90552171cc109527f345f42aa0df06dcbb2fa01b33d0043917bbed69 +80c869469900431f3eeefafdbe07b8afd8cee7739e659e6d0109b397cacff85a88247698f87dc4e2fe39a592f250ac64 +9091594f488b38f9d2bb5df49fd8b4f8829d9c2f11a197dd1431ed5abbc5c954bbde3387088f9ee3a5a834beb7619bce +b472e241e6956146cca57b97a8a204668d050423b4e76f857bad5b47f43b203a04c8391ba9d9c3e95093c071f9d376a1 +b7dd2de0284844392f7dfb56fe7ca3ede41e27519753ffc579a0a8d2d65ceb8108d06b6b0d4c3c1a2588951297bd1a1e +902116ce70d0a079ac190321c1f48701318c05f8e69ee09694754885d33a835a849cafe56f499a2f49f6cda413ddf9a7 +b18105cc736787fafaf7c3c11c448bce9466e683159dff52723b7951dff429565e466e4841d982e3aaa9ee2066838666 +97ab9911f3f659691762d568ae0b7faa1047b0aed1009c319fa79d15d0db8db9f808fc385dc9a68fa388c10224985379 +b2a2cba65f5b927e64d2904ba412e2bac1cf18c9c3eda9c72fb70262497ecf505b640827e2afebecf10eebbcf48ccd3e +b36a3fd677baa0d3ef0dac4f1548ff50a1730286b8c99d276a0a45d576e17b39b3cbadd2fe55e003796d370d4be43ce3 +a5dfec96ca3c272566e89dc453a458909247e3895d3e44831528130bc47cc9d0a0dac78dd3cad680a4351d399d241967 +8029382113909af6340959c3e61db27392531d62d90f92370a432aec3eb1e4c36ae1d4ef2ba8ec6edb4d7320c7a453f6 +971d85121ea108e6769d54f9c51299b0381ece8b51d46d49c89f65bedc123bab4d5a8bc14d6f67f4f680077529cbae4c +98ff6afc01d0bec80a278f25912e1b1ebff80117adae72e31d5b9fa4d9624db4ba2065b444df49b489b0607c45e26c4c +8fa29be10fb3ab30ce25920fec0187e6e91e458947009dabb869aade7136c8ba23602682b71e390c251f3743164cbdaa +b3345c89eb1653418fe3940cf3e56a9a9c66526389b98f45ca02dd62bfb37baa69a4baaa7132d7320695f8ea6ad1fd94 +b72c7f5541c9ac6b60a7ec9f5415e7fb14da03f7164ea529952a29399f3a071576608dbbcc0d45994f21f92ddbeb1e19 +aa3450bb155a5f9043d0ef95f546a2e6ade167280bfb75c9f09c6f9cdb1fffb7ce8181436161a538433afa3681c7a141 +92a18fecaded7854b349f441e7102b638ababa75b1b0281dd0bded6541abe7aa37d96693595be0b01fe0a2e2133d50f9 +980756ddf9d2253cfe6c94960b516c94889d09e612810935150892627d2ecee9a2517e04968eea295d0106850c04ca44 +ae68c6ccc454318cdd92f32b11d89116a3b8350207a36d22a0f626718cad671d960090e054c0c77ac3162ae180ecfd4b +99f31f66eaaa551749ad91d48a0d4e3ff4d82ef0e8b28f3184c54e852422ba1bdafd53b1e753f3a070f3b55f3c23b6a2 +a44eaeaa6589206069e9c0a45ff9fc51c68da38d4edff1d15529b7932e6f403d12b9387019c44a1488a5d5f27782a51f +b80b5d54d4b344840e45b79e621bd77a3f83fb4ce6d8796b7d6915107b3f3c34d2e7d95bdafd120f285669e5acf2437a +b36c069ec085a612b5908314d6b84c00a83031780261d1c77a0384c406867c9847d5b0845deddfa512cc04a8df2046fb +b09dbe501583220f640d201acea7ee3e39bf9eda8b91aa07b5c50b7641d86d71acb619b38d27835ce97c3759787f08e9 +87403d46a2bf63170fff0b857acacf42ee801afe9ccba8e5b4aea967b68eac73a499a65ca46906c2eb4c8f27bc739faa +82b93669f42a0a2aa5e250ffe6097269da06a9c02fcd1801abbad415a7729a64f830754bafc702e64600ba47671c2208 +8e3a3029be7edb8dd3ab1f8216664c8dc50d395f603736061d802cef77627db7b859ef287ed850382c13b4d22d6a2d80 +968e9ec7194ff424409d182ce0259acd950c384c163c04463bc8700a40b79beba6146d22b7fa7016875a249b7b31c602 +8b42c984bbe4996e0c20862059167c6bdc5164b1ffcd928f29512664459212d263e89f0f0e30eed4e672ffa5ed0b01b5 +96bac54062110dada905363211133f1f15dc7e4fd80a4c6e4a83bc9a0bcbbaba11cd2c7a13debcf0985e1a954c1da66b +a16dc8a653d67a7cd7ae90b2fffac0bf1ca587005430fe5ba9403edd70ca33e38ba5661d2ed6e9d2864400d997626a62 +a68ab11a570a27853c8d67e491591dcba746bfbee08a2e75ae0790399130d027ed387f41ef1d7de8df38b472df309161 +92532b74886874447c0300d07eda9bbe4b41ed25349a3da2e072a93fe32c89d280f740d8ff70d5816793d7f2b97373cc +88e35711b471e89218fd5f4d0eadea8a29405af1cd81974427bc4a5fb26ed60798daaf94f726c96e779b403a2cd82820 +b5c72aa4147c19f8c4f3a0a62d32315b0f4606e0a7025edc5445571eaf4daff64f4b7a585464821574dd50dbe1b49d08 +9305d9b4095258e79744338683fd93f9e657367b3ab32d78080e51d54eec331edbc224fad5093ebf8ee4bd4286757eb8 +b2a17abb3f6a05bcb14dc7b98321fa8b46d299626c73d7c6eb12140bf4c3f8e1795250870947af817834f033c88a59d6 +b3477004837dbd8ba594e4296f960fc91ab3f13551458445e6c232eb04b326da803c4d93e2e8dcd268b4413305ff84da +924b4b2ebaafdcfdfedb2829a8bf46cd32e1407d8d725a5bd28bdc821f1bafb3614f030ea4352c671076a63494275a3f +8b81b9ef6125c82a9bece6fdcb9888a767ac16e70527753428cc87c56a1236e437da8be4f7ecfe57b9296dc3ae7ba807 +906e19ec8b8edd58bdf9ae05610a86e4ea2282b1bbc1e8b00b7021d093194e0837d74cf27ac9916bdb8ec308b00da3da +b41c5185869071760ac786078a57a2ab4e2af60a890037ac0c0c28d6826f15c2cf028fddd42a9b6de632c3d550bfbc14 +a646e5dec1b713ae9dfdf7bdc6cd474d5731a320403c7dfcfd666ffc9ae0cff4b5a79530e8df3f4aa9cb80568cb138e9 +b0efad22827e562bd3c3e925acbd0d9425d19057868608d78c2209a531cccd0f2c43dc5673acf9822247428ffa2bb821 +a94c19468d14b6f99002fc52ac06bbe59e5c472e4a0cdb225144a62f8870b3f10593749df7a2de0bd3c9476ce682e148 +803864a91162f0273d49271dafaab632d93d494d1af935aefa522768af058fce52165018512e8d6774976d52bd797e22 +a08711c2f7d45c68fb340ac23597332e1bcaec9198f72967b9921204b9d48a7843561ff318f87908c05a44fc35e3cc9d +91c3cad94a11a3197ae4f9461faab91a669e0dddb0371d3cab3ed9aeb1267badc797d8375181130e461eadd05099b2a2 +81bdaaf48aae4f7b480fc13f1e7f4dd3023a41439ba231760409ce9292c11128ab2b0bdbbf28b98af4f97b3551f363af +8d60f9df9fd303f625af90e8272c4ecb95bb94e6efc5da17b8ab663ee3b3f673e9f6420d890ccc94acf4d2cae7a860d8 +a7b75901520c06e9495ab983f70b61483504c7ff2a0980c51115d11e0744683ce022d76e3e09f4e99e698cbd21432a0d +82956072df0586562fda7e7738226f694e1c73518dd86e0799d2e820d7f79233667192c9236dcb27637e4c65ef19d493 +a586beb9b6ffd06ad200957490803a7cd8c9bf76e782734e0f55e04a3dc38949de75dc607822ec405736c576cf83bca3 +a179a30d00def9b34a7e85607a447eea0401e32ab5abeee1a281f2acd1cf6ec81a178020666f641d9492b1bdf66f05a3 +83e129705c538787ed8e0fdc1275e6466a3f4ee21a1e6abedd239393b1df72244723b92f9d9d9339a0cab6ebf28f5a16 +811bd8d1e3722b64cd2f5b431167e7f91456e8bba2cc669d3fbbce7d553e29c3c19f629fcedd2498bc26d33a24891d17 +a243c030c858f1f60cccd26b45b024698cc6d9d9e6198c1ed4964a235d9f8d0baf9cde10c8e63dfaa47f8e74e51a6e85 +ab839eb82e23ca52663281f863b55b0a3d6d4425c33ffb4eeb1d7979488ab068bf99e2a60e82cea4dc42c56c26cbfebe +8b896f9bb21d49343e67aec6ad175b58c0c81a3ca73d44d113ae4354a0065d98eb1a5cafedaf232a2bb9cdc62152f309 +af6230340cc0b66f5bf845540ed4fc3e7d6077f361d60762e488d57834c3e7eb7eacc1b0ed73a7d134f174a01410e50c +88975e1b1af678d1b5179f72300a30900736af580dd748fd9461ef7afccc91ccd9bed33f9da55c8711a7635b800e831f +a97486bb9047391661718a54b8dd5a5e363964e495eae6c692730264478c927cf3e66dd3602413189a3699fbeae26e15 +a5973c161ab38732885d1d2785fd74bf156ba34881980cba27fe239caef06b24a533ffe6dbbbeca5e6566682cc00300a +a24776e9a840afda0003fa73b415d5bd6ecd9b5c2cc842b643ee51b8c6087f4eead4d0bfbd987eb174c489a7b952ff2a +a8a6ee06e3af053b705a12b59777267c546f33ba8a0f49493af8e6df4e15cf8dd2d4fb4daf7e84c6b5d3a7363118ff03 +a28e59ce6ad02c2ce725067c0123117e12ac5a52c8f5af13eec75f4a9efc4f696777db18a374fa33bcae82e0734ebd16 +86dfc3b78e841c708aff677baa8ee654c808e5d257158715097c1025d46ece94993efe12c9d188252ad98a1e0e331fec +a88d0275510f242eab11fdb0410ff6e1b9d7a3cbd3658333539815f1b450a84816e6613d15aa8a8eb15d87cdad4b27a2 +8440acea2931118a5b481268ff9f180ee4ede85d14a52c026adc882410825b8275caa44aff0b50c2b88d39f21b1a0696 +a7c3182eab25bd6785bacf12079d0afb0a9b165d6ed327814e2177148539f249eb9b5b2554538f54f3c882d37c0a8abe +85291fbe10538d7da38efdd55a7acebf03b1848428a2f664c3ce55367aece60039f4f320b1771c9c89a35941797f717c +a2c6414eeb1234728ab0de94aa98fc06433a58efa646ca3fcbd97dbfb8d98ae59f7ce6d528f669c8149e1e13266f69c9 +840c8462785591ee93aee2538d9f1ec44ba2ca61a569ab51d335ac873f5d48099ae8d7a7efa0725d9ff8f9475bfa4f56 +a7065a9d02fb3673acf7702a488fbc01aa69580964932f6f40b6c2d1c386b19e50b0e104fcac24ea26c4e723611d0238 +b72db6d141267438279e032c95e6106c2ccb3164b842ba857a2018f3a35f4b040da92680881eb17cd61d0920d5b8f006 +a8005d6c5960e090374747307ef0be2871a7a43fa4e76a16c35d2baab808e9777b496e9f57a4218b23390887c33a0b55 +8e152cea1e00a451ca47c20a1e8875873419700af15a5f38ee2268d3fbc974d4bd5f4be38008fa6f404dbdedd6e6e710 +a3391aed1fcd68761f06a7d1008ec62a09b1cb3d0203cd04e300a0c91adfed1812d8bc1e4a3fd7976dc0aae0e99f52f1 +967eb57bf2aa503ee0c6e67438098149eac305089c155f1762cf5e84e31f0fbf27c34a9af05621e34645c1ec96afaec8 +88af97ddc4937a95ec0dcd25e4173127260f91c8db2f6eac84afb789b363705fb3196235af631c70cafd09411d233589 +a32df75b3f2c921b8767638fd289bcfc61e08597170186637a7128ffedd52c798c434485ac2c7de07014f9e895c2c3d8 +b0a783832153650aa0d766a3a73ec208b6ce5caeb40b87177ffc035ab03c7705ecdd1090b6456a29f5fb7e90e2fa8930 +b59c8e803b4c3486777d15fc2311b97f9ded1602fa570c7b0200bada36a49ee9ef4d4c1474265af8e1c38a93eb66b18b +982f2c85f83e852022998ff91bafbb6ff093ef22cf9d5063e083a48b29175ccbd51b9c6557151409e439096300981a6c +939e3b5989fefebb9d272a954659a4eb125b98c9da6953f5e628d26266bd0525ec38304b8d56f08d65abc4d6da4a8dbb +8898212fe05bc8de7d18503cb84a1c1337cc2c09d1eeef2b475aa79185b7322bf1f8e065f1bf871c0c927dd19faf1f6d +94b0393a41cd00f724aee2d4bc72103d626a5aecb4b5486dd1ef8ac27528398edf56df9db5c3d238d8579af368afeb09 +96ac564450d998e7445dd2ea8e3fc7974d575508fa19e1c60c308d83b645864c029f2f6b7396d4ff4c1b24e92e3bac37 +8adf6638e18aff3eb3b47617da696eb6c4bdfbecbbc3c45d3d0ab0b12cbad00e462fdfbe0c35780d21aa973fc150285e +b53f94612f818571b5565bbb295e74bada9b5f9794b3b91125915e44d6ddcc4da25510eab718e251a09c99534d6042d9 +8b96462508d77ee083c376cd90807aebad8de96bca43983c84a4a6f196d5faf6619a2351f43bfeec101864c3bf255519 +aeadf34657083fc71df33bd44af73bf5281c9ca6d906b9c745536e1819ea90b56107c55e2178ebad08f3ba75b3f81c86 +9784ba29b2f0057b5af1d3ab2796d439b8753f1f749c73e791037461bdfc3f7097394283105b8ab01788ea5255a96710 +8756241bda159d4a33bf74faba0d4594d963c370fb6a18431f279b4a865b070b0547a6d1613cf45b8cfb5f9236bbf831 +b03ebfd6b71421dfd49a30460f9f57063eebfe31b9ceaa2a05c37c61522b35bdc09d7db3ad75c76c253c00ba282d3cd2 +b34e7e6341fa9d854b2d3153bdda0c4ae2b2f442ab7af6f99a0975d45725aa48e36ae5f7011edd249862e91f499687d4 +b462ee09dc3963a14354244313e3444de5cc37ea5ccfbf14cd9aca8027b59c4cb2a949bc30474497cab8123e768460e6 +aea753290e51e2f6a21a9a0ee67d3a2713f95c2a5c17fe41116c87d3aa77b1683761264d704df1ac34f8b873bc88ef7b +98430592afd414394f98ddfff9f280fcb1c322dbe3510f45e1e9c4bb8ee306b3e0cf0282c0ee73ebb8ba087d4d9e0858 +b95d3b5aaf54ffca11f4be8d57f76e14afdb20afc859dc7c7471e0b42031e8f3d461b726ecb979bdb2f353498dfe95ea +984d17f9b11a683132e0b5a9ee5945e3ff7054c2d5c716be73b29078db1d36f54c6e652fd2f52a19da313112e97ade07 +ab232f756b3fff3262be418a1af61a7e0c95ceebbc775389622a8e10610508cd6784ab7960441917a83cc191c58829ea +a28f41678d6e60de76b0e36ab10e4516e53e02e9c77d2b5af3cfeee3ce94cfa30c5797bd1daab20c98e1cad83ad0f633 +b55395fca84dd3ccc05dd480cb9b430bf8631ff06e24cb51d54519703d667268c2f8afcde4ba4ed16bece8cc7bc8c6e0 +8a8a5392a0e2ea3c7a8c51328fab11156004e84a9c63483b64e8f8ebf18a58b6ffa8fe8b9d95af0a2f655f601d096396 +ab480000fe194d23f08a7a9ec1c392334e9c687e06851f083845121ce502c06b54dda8c43092bcc1035df45cc752fe9b +b265644c29f628d1c7e8e25a5e845cabb21799371814730a41a363e1bda8a7be50fee7c3996a365b7fcba4642add10db +b8a915a3c685c2d4728f6931c4d29487cad764c5ce23c25e64b1a3259ac27235e41b23bfe7ae982921b4cb84463097df +8efa7338442a4b6318145a5440fc213b97869647eeae41b9aa3c0a27ee51285b73e3ae3b4a9423df255e6add58864aa9 +9106d65444f74d217f4187dfc8fcf3810b916d1e4275f94f6a86d1c4f3565b131fd6cde1fa708bc05fe183c49f14941a +948252dac8026bbbdb0a06b3c9d66ec4cf9532163bab68076fda1bd2357b69e4b514729c15aaa83b5618b1977bbc60c4 +ae6596ccfdf5cbbc5782efe3bb0b101bb132dbe1d568854ca24cacc0b2e0e9fabcb2ca7ab42aecec412efd15cf8cb7a2 +84a0b6c198ff64fd7958dfd1b40eac9638e8e0b2c4cd8cf5d8cdf80419baee76a05184bce6c5b635f6bf2d30055476a7 +8893118be4a055c2b3da593dbca51b1ae2ea2469911acfb27ee42faf3e6c3ad0693d3914c508c0b05b36a88c8b312b76 +b097479e967504deb6734785db7e60d1d8034d6ca5ba9552887e937f5e17bb413fccac2c1d1082154ed76609127860ad +a0294e6b9958f244d29943debf24b00b538b3da1116269b6e452bb12dc742226712fd1a15b9c88195afeb5d2415f505c +b3cc15f635080bc038f61b615f62b5b5c6f2870586191f59476e8368a73641d6ac2f7d0c1f54621982defdb318020230 +99856f49b9fe1604d917c94d09cc0ed753d13d015d30587a94e6631ffd964b214e607deb8a69a8b5e349a7edf4309206 +a8571e113ea22b4b4fce41a094da8c70de37830ae32e62c65c2fa5ad06a9bc29e884b945e73d448c72b176d6ecebfb58 +a9e9c6e52beb0013273c29844956b3ce291023678107cdc785f7b44eff5003462841ad8780761b86aefc6b734adde7cf +80a784b0b27edb51ef2bad3aee80e51778dcaa0f3f5d3dcb5dc5d4f4b2cf7ae35b08de6680ea9dac53f8438b92eb09ef +827b543e609ea328e97e373f70ad72d4915a2d1daae0c60d44ac637231070e164c43a2a58db80a64df1c624a042b38f9 +b449c65e8195202efdcb9bdb4e869a437313b118fef8b510cbbf8b79a4e99376adb749b37e9c20b51b31ed3310169e27 +8ea3028f4548a79a94c717e1ed28ad4d8725b8d6ab18b021063ce46f665c79da3c49440c6577319dab2d036b7e08f387 +897798431cfb17fe39f08f5f854005dc37b1c1ec1edba6c24bc8acb3b88838d0534a75475325a5ea98b326ad47dbad75 +89cf232e6303b0751561960fd4dea5754a28c594daf930326b4541274ffb03c7dd75938e411eb9a375006a70ce38097f +9727c6ae7f0840f0b6c8bfb3a1a5582ceee705e0b5c59b97def7a7a2283edd4d3f47b7971e902a3a2079e40b53ff69b8 +b76ed72b122c48679d221072efc0eeea063cb205cbf5f9ef0101fd10cb1075b8628166c83577cced654e1c001c7882f7 +ae908c42d208759da5ee9b405df85a6532ea35c6f0f6a1288d22870f59d98edc896841b8ac890a538e6c8d1e8b02d359 +809d12fe4039a0ec80dc9be6a89acaab7797e5f7f9b163378f52f9a75a1d73b2e9ae6e3dd49e32ced439783c1cabbef5 +a4149530b7f85d1098ba534d69548c6c612c416e8d35992fc1f64f4deeb41e09e49c6cf7aadbed7e846b91299358fe2d +a49342eacd1ec1148b8df1e253b1c015f603c39de11fa0a364ccb86ea32d69c34fd7aa6980a1fadcd8e785a57fa46f60 +87d43eff5a006dc4dddcf76cc96c656a1f3a68f19f124181feab86c6cc9a52cb9189cdbb423414defdd9bb0ca8ff1ddc +861367e87a9aa2f0f68296ba50aa5dbc5713008d260cc2c7e62d407c2063064749324c4e8156dc21b749656cfebce26b +b5303c2f72e84e170e66ae1b0fbd51b8c7a6f27476eaf5694b64e8737d5c84b51fe90100b256465a4c4156dd873cddb0 +b62849a4f891415d74f434cdc1d23c4a69074487659ca96e1762466b2b7a5d8525b056b891d0feea6fe6845cba8bc7fb +923dd9e0d6590a9307e8c4c23f13bae3306b580e297a937711a8b13e8de85e41a61462f25b7d352b682e8437bf2b4ab3 +9147379860cd713cd46c94b8cdf75125d36c37517fbecf81ace9680b98ce6291cd1c3e472f84249cc3b2b445e314b1b6 +a808a4f17ac21e3fb5cfef404e61fae3693ca3e688d375f99b6116779696059a146c27b06de3ac36da349b0649befd56 +87787e9322e1b75e66c1f0d9ea0915722a232770930c2d2a95e9478c4b950d15ab767e30cea128f9ed65893bfc2d0743 +9036a6ee2577223be105defe1081c48ea7319e112fff9110eb9f61110c319da25a6cea0464ce65e858635b079691ef1f +af5548c7c24e1088c23b57ee14d26c12a83484c9fd9296edf1012d8dcf88243f20039b43c8c548c265ef9a1ffe9c1c88 +a0fff520045e14065965fb8accd17e878d3fcaf9e0af2962c8954e50be6683d31fa0bf4816ab68f08630dbac6bfce52a +b4c1b249e079f6ae1781af1d97a60b15855f49864c50496c09c91fe1946266915b799f0406084d7783f5b1039116dd8b +8b0ffa5e7c498cb3879dddca34743b41eee8e2dea3d4317a6e961b58adb699ef0c92400c068d5228881a2b08121226bf +852ae8b19a1d80aa8ae5382e7ee5c8e7670ceb16640871c56b20b96b66b3b60e00015a3dde039446972e57b49a999ddd +a49942f04234a7d8492169da232cfff8051df86e8e1ba3db46aede02422c689c87dc1d99699c25f96cb763f5ca0983e5 +b04b597b7760cf5dcf411ef896d1661e6d5b0db3257ac2cf64b20b60c6cc18fa10523bb958a48d010b55bac7b02ab3b1 +a494591b51ea8285daecc194b5e5bd45ae35767d0246ac94fae204d674ee180c8e97ff15f71f28b7aeb175b8aea59710 +97d2624919e78406e7460730680dea8e71c8571cf988e11441aeea54512b95bd820e78562c99372d535d96f7e200d20d +ac693ddb00e48f76e667243b9b6a7008424043fb779e4f2252330285232c3fccac4da25cbd6d95fe9ad959ff305a91f6 +8d20ca0a71a64a3f702a0825bb46bd810d03bebfb227683680d474a52f965716ff99e19a165ebaf6567987f4f9ee3c94 +a5c516a438f916d1d68ca76996404792e0a66e97b7f18fc54c917bf10cf3211b62387932756e39e67e47b0bd6e88385a +b089614d830abc0afa435034cec7f851f2f095d479cacf1a3fb57272da826c499a52e7dcbc0eb85f4166fb94778e18e9 +a8dacc943765d930848288192f4c69e2461c4b9bc6e79e30eeef9a543318cf9ae9569d6986c65c5668a89d49993f8e07 +ab5a9361fa339eec8c621bdad0a58078983abd8942d4282b22835d7a3a47e132d42414b7c359694986f7db39386c2e19 +94230517fb57bd8eb26c6f64129b8b2abd0282323bf7b94b8bac7fab27b4ecc2c4290c294275e1a759de19f2216134f3 +b8f158ea5006bc3b90b285246625faaa6ac9b5f5030dc69701b12f3b79a53ec7e92eeb5a63bbd1f9509a0a3469ff3ffc +8b6944fd8cb8540957a91a142fdcda827762aa777a31e8810ca6d026e50370ee1636fc351724767e817ca38804ebe005 +82d1ee40fe1569c29644f79fa6c4033b7ed45cd2c3b343881f6eb0de2e79548fded4787fae19bed6ee76ed76ff9f2f11 +a8924c7035e99eaed244ca165607e7e568b6c8085510dcdbaf6ebdbed405af2e6c14ee27d94ffef10d30aa52a60bf66d +956f82a6c2ae044635e85812581e4866c5fa2f427b01942047d81f6d79a14192f66fbbe77c9ffeaef4e6147097fdd2b5 +b1100255a1bcf5e05b6aff1dfeb6e1d55b5d68d43a7457ba10cc76b61885f67f4d0d5179abda786e037ae95deb8eea45 +99510799025e3e5e8fbf06dedb14c060c6548ba2bda824f687d3999dc395e794b1fb6514b9013f3892b6cf65cb0d65aa +8f9091cebf5e9c809aab415942172258f894e66e625d7388a05289183f01b8d994d52e05a8e69f784fba41db9ea357f0 +a13d2eeb0776bdee9820ecb6693536720232848c51936bb4ef4fe65588d3f920d08a21907e1fdb881c1ad70b3725e726 +a68b8f18922d550284c5e5dc2dda771f24c21965a6a4d5e7a71678178f46df4d8a421497aad8fcb4c7e241aba26378a0 +8b7601f0a3c6ad27f03f2d23e785c81c1460d60100f91ea9d1cab978aa03b523150206c6d52ce7c7769c71d2c8228e9e +a8e02926430813caa851bb2b46de7f0420f0a64eb5f6b805401c11c9091d3b6d67d841b5674fa2b1dce0867714124cd8 +b7968ecba568b8193b3058400af02c183f0a6df995a744450b3f7e0af7a772454677c3857f99c140bbdb2a09e832e8e0 +8f20b1e9ba87d0a3f35309b985f3c18d2e8800f1ca7f0c52cadef773f1496b6070c936eea48c4a1cae83fd2524e9d233 +88aef260042db0d641a51f40639dbeeefa9e9811df30bee695f3791f88a2f84d318f04e8926b7f47bf25956cb9e3754f +9725345893b647e9ba4e6a29e12f96751f1ae25fcaec2173e9a259921a1a7edb7a47159b3c8767e44d9e2689f5aa0f72 +8c281e6f72752cb11e239e4df9341c45106eb7993c160e54423c2bffe10bc39d42624b45a1f673936ef2e1a02fc92f1a +90aba2f68bddb2fcce6c51430dacdfeec43ea8dc379660c99095df11017691ccf5faa27665cf4b9f0eea7728ae53c327 +b7022695c16521c5704f49b7ddbdbec9b5f57ce0ceebe537bc0ebb0906d8196cc855a9afeb8950a1710f6a654464d93f +8fe1b9dd3c6a258116415d36e08374e094b22f0afb104385a5da48be17123e86fb8327baacc4f0d9ebae923d55d99bb5 +817e85d8e3d19a4cbc1dec31597142c2daa4871bda89c2177fa719c00eda3344eb08b82eb92d4aa91a9eaacb3fc09783 +b59053e1081d2603f1ca0ba553804d6fa696e1fd996631db8f62087b26a40dfef02098b0326bb75f99ec83b9267ca738 +990a173d857d3ba81ff3789b931bfc9f5609cde0169b7f055fa3cb56451748d593d62d46ba33f80f9cafffe02b68dd14 +b0c538dbba4954b809ab26f9f94a3cf1dcb77ce289eaec1d19f556c0ae4be1fa03af4a9b7057837541c3cc0a80538736 +ac3ba42f5f44f9e1fc453ce49c4ab79d0e1d5c42d3b30b1e098f3ab3f414c4c262fa12fb2be249f52d4aaf3c5224beb9 +af47467eb152e59870e21f0d4da2f43e093daf40180ab01438030684b114d025326928eaab12c41b81a066d94fce8436 +98d1b58ba22e7289b1c45c79a24624f19b1d89e00f778eef327ec4856a9a897278e6f1a9a7e673844b31dde949153000 +97ccb15dfadc7c59dca08cfe0d22df2e52c684cf97de1d94bc00d7ba24e020025130b0a39c0f4d46e4fc872771ee7875 +b699e4ed9a000ff96ca296b2f09dce278832bc8ac96851ff3cff99ed3f6f752cfc0fea8571be28cd9b5a7ec36f1a08ee +b9f49f0edb7941cc296435ff0a912e3ad16848ee8765ab5f60a050b280d6ea585e5b34051b15f6b8934ef01ceb85f648 +ac3893df7b4ceab23c6b9054e48e8ba40d6e5beda8fbe90b814f992f52494186969b35d8c4cdc3c99890a222c9c09008 +a41293ad22fae81dea94467bc1488c3707f3d4765059173980be93995fa4fcc3c9340796e3eed0beeb0ba0d9bb4fa3aa +a0543e77acd2aeecde13d18d258aeb2c7397b77f17c35a1992e8666ea7abcd8a38ec6c2741bd929abba2f766138618cc +92e79b22bc40e69f6527c969500ca543899105837b6b1075fa1796755c723462059b3d1b028e0b3df2559fa440e09175 +a1fa1eac8f41a5197a6fb4aa1eae1a031c89f9c13ff9448338b222780cf9022e0b0925d930c37501a0ef7b2b00fdaf83 +b3cb29ff73229f0637335f28a08ad8c5f166066f27c6c175164d0f26766a927f843b987ee9b309ed71cbf0a65d483831 +84d4ab787f0ac00f104f4a734dc693d62d48c2aeb03913153da62c2ae2c27d11b1110dcef8980368dd84682ea2c1a308 +ab6a8e4bbc78d4a7b291ad3e9a8fe2d65f640524ba3181123b09d2d18a9e300e2509ccf7000fe47e75b65f3e992a2e7e +b7805ebe4f1a4df414003dc10bca805f2ab86ca75820012653e8f9b79c405196b0e2cab099f2ab953d67f0d60d31a0f9 +b12c582454148338ea605d22bd00a754109063e22617f1f8ac8ddf5502c22a181c50c216c3617b9852aa5f26af56b323 +86333ad9f898947e31ce747728dc8c887479e18d36ff3013f69ebef807d82c6981543b5c3788af93c4d912ba084d3cba +b514efa310dc4ad1258add138891e540d8c87142a881b5f46563cc58ecd1488e6d3a2fca54c0b72a929f3364ca8c333e +aa0a30f92843cf2f484066a783a1d75a7aa6f41f00b421d4baf20a6ac7886c468d0eea7ca8b17dd22f4f74631b62b640 +b3b7dc63baec9a752e8433c0cdee4d0f9bc41f66f2b8d132faf925eef9cf89aae756fc132c45910f057122462605dc10 +b9b8190dac5bfdeb59fd44f4da41a57e7f1e7d2c21faba9da91fa45cbeca06dcf299c9ae22f0c89ece11ac46352d619f +89f8cf36501ad8bdfeab863752a9090e3bfda57cf8fdeca2944864dc05925f501e252c048221bcc57136ab09a64b64b2 +b0cbfaf317f05f97be47fc9d69eda2dd82500e00d42612f271a1fe24626408c28881f171e855bd5bd67409f9847502b4 +a7c21a8fcede581bfd9847b6835eda62ba250bea81f1bb17372c800a19c732abe03064e64a2f865d974fb636cab4b859 +95f9df524ba7a4667351696c4176b505d8ea3659f5ff2701173064acc624af69a0fad4970963736383b979830cb32260 +856a74fe8b37a2e3afeac858c8632200485d438422a16ae3b29f359e470e8244995c63ad79c7e007ed063f178d0306fd +b37faa4d78fdc0bb9d403674dbea0176c2014a171c7be8527b54f7d1a32a76883d3422a3e7a5f5fcc5e9b31b57822eeb +8d37234d8594ec3fe75670b5c9cc1ec3537564d4739b2682a75b18b08401869a4264c0f264354219d8d896cded715db4 +b5289ee5737f0e0bde485d32096d23387d68dab8f01f47821ab4f06cc79a967afe7355e72dc0c751d96b2747b26f6255 +9085e1fdf9f813e9c3b8232d3c8863cd84ab30d45e8e0d3d6a0abd9ebc6fd70cdf749ff4d04390000e14c7d8c6655fc7 +93a388c83630331eca4da37ea4a97b3b453238af474817cc0a0727fd3138dcb4a22de38c04783ec829c22cb459cb4e8e +a5377116027c5d061dbe24c240b891c08cdd8cd3f0899e848d682c873aff5b8132c1e7cfe76d2e5ed97ee0eb1d42cb68 +a274c84b04338ed28d74683e2a7519c2591a3ce37c294d6f6e678f7d628be2db8eff253ede21823e2df7183e6552f622 +8bc201147a842453a50bec3ac97671397bc086d6dfc9377fa38c2124cdc286abda69b7324f47d64da094ae011d98d9d9 +9842d0c066c524592b76fbec5132bc628e5e1d21c424bec4555efca8619cc1fd8ea3161febcb8b9e8ab54702f4e815e2 +a19191b713a07efe85c266f839d14e25660ee74452e6c691cd9997d85ae4f732052d802d3deb018bdd847caa298a894b +a24f71fc0db504da4e287dd118a4a74301cbcd16033937ba2abc8417956fcb4ae19b8e63b931795544a978137eff51cb +a90eec4a6a3a4b8f9a5b93d978b5026fcf812fe65585b008d7e08c4aaf21195a1d0699f12fc16f79b6a18a369af45771 +8b551cf89737d7d06d9b3b9c4c1c73b41f2ea0af4540999c70b82dabff8580797cf0a3caf34c86c59a7069eb2e38f087 +b8d312e6c635e7a216a1cda075ae77ba3e1d2fd501dc31e83496e6e81ed5d9c7799f8e578869c2e0e256fb29f5de10a7 +8d144bdb8cae0b2cdb5b33d44bbc96984a5925202506a8cc65eb67ac904b466f5a7fe3e1cbf04aa785bbb7348c4bb73c +a101b3d58b7a98659244b88de0b478b3fb87dc5fc6031f6e689b99edf498abd43e151fd32bd4bbd240e0b3e59c440359 +907453abca7d8e7151a05cc3d506c988007692fe7401395dc93177d0d07d114ab6cca0cc658eb94c0223fe8658295cad +825329ffbe2147ddb68f63a0a67f32d7f309657b8e5d9ab5bb34b3730bfa2c77a23eaaadb05def7d9f94a9e08fdc1e96 +88ee923c95c1dac99ae7ed6067906d734d793c5dc5d26339c1bb3314abe201c5dccb33b9007351885eb2754e9a8ea06c +98bc9798543f5f1adc9f2cfcfa72331989420e9c3f6598c45269f0dc9b7c8607bbeaf03faa0aea2ddde2b8f17fdceff5 +8ee87877702a79aef923ab970db6fa81561b3c07d5bf1a072af0a7bad765b4cbaec910afe1a91703feacc7822fa38a94 +8060b9584aa294fe8adc2b22f67e988bc6da768eae91e429dcc43ddc53cfcc5d6753fdc1b420b268c7eb2fb50736a970 +b344a5524d80a2f051870c7001f74fcf348a70fcf78dbd20c6ff9ca85d81567d2318c8b8089f2c4f195d6aec9fc15fa6 +8f5a5d893e1936ed062149d20eb73d98b62b7f50ab5d93a6429c03656b36688d1c80cb5010e4977491e51fa0d7dd35d5 +86fa32ebbf97328c5f5f15564e1238297e289ec3219b9a741724e9f3ae8d5c15277008f555863a478b247ba5dc601d44 +9557e55377e279f4b6b5e0ffe01eca037cc13aac242d67dfcd0374a1e775c5ed5cb30c25fe21143fee54e3302d34a3ea +8cb6bcbc39372d23464a416ea7039f57ba8413cf3f00d9a7a5b356ab20dcb8ed11b3561f7bce372b8534d2870c7ee270 +b5d59075cb5abde5391f64b6c3b8b50adc6e1f654e2a580b6d6d6eff3f4fbdd8fffc92e06809c393f5c8eab37f774c4b +afcfb6903ef13e493a1f7308675582f15af0403b6553e8c37afb8b2808ad21b88b347dc139464367dc260df075fea1ad +810fbbe808375735dd22d5bc7fc3828dc49fdd22cc2d7661604e7ac9c4535c1df578780affb3b895a0831640a945bcad +8056b0c678803b416f924e09a6299a33cf9ad7da6fe1ad7accefe95c179e0077da36815fde3716711c394e2c5ea7127f +8b67403702d06979be19f1d6dc3ec73cc2e81254d6b7d0cc49cd4fdda8cd51ab0835c1d2d26fc0ecab5df90585c2f351 +87f97f9e6d4be07e8db250e5dd2bffdf1390665bc5709f2b631a6fa69a7fca958f19bd7cc617183da1f50ee63e9352b5 +ae151310985940471e6803fcf37600d7fa98830613e381e00dab943aec32c14162d51c4598e8847148148000d6e5af5c +81eb537b35b7602c45441cfc61b27fa9a30d3998fad35a064e05bc9479e9f10b62eba2b234b348219eea3cadcaac64bb +8a441434934180ab6f5bc541f86ebd06eadbee01f438836d797e930fa803a51510e005c9248cecc231a775b74d12b5e9 +81f3c250a27ba14d8496a5092b145629eb2c2e6a5298438670375363f57e2798207832c8027c3e9238ad94ecdadfc4df +a6217c311f2f3db02ceaa5b6096849fe92b6f4b6f1491535ef8525f6ccee6130bed2809e625073ecbaddd4a3eb3df186 +82d1c396f0388b942cf22b119d7ef1ad03d3dad49a74d9d01649ee284f377c8daddd095d596871669e16160299a210db +a40ddf7043c5d72a7246bd727b07f7fff1549f0e443d611de6f9976c37448b21664c5089c57f20105102d935ab82f27b +b6c03c1c97adf0c4bf4447ec71366c6c1bff401ba46236cd4a33d39291e7a1f0bb34bd078ba3a18d15c98993b153a279 +8a94f5f632068399c359c4b3a3653cb6df2b207379b3d0cdace51afdf70d6d5cce6b89a2b0fee66744eba86c98fb21c2 +b2f19e78ee85073f680c3bba1f07fd31b057c00b97040357d97855b54a0b5accb0d3b05b2a294568fcd6a4be6f266950 +a74632d13bbe2d64b51d7a9c3ae0a5a971c19f51cf7596a807cea053e6a0f3719700976d4e394b356c0329a2dced9aa2 +afef616d341a9bc94393b8dfba68ff0581436aa3a3adb7c26a1bbf2cf19fa877066191681f71f17f3cd6f9cf6bf70b5a +8ce96d93ae217408acf7eb0f9cbb9563363e5c7002e19bbe1e80760bc9d449daee2118f3878b955163ed664516b97294 +8414f79b496176bc8b8e25f8e4cfee28f4f1c2ddab099d63d2aca1b6403d26a571152fc3edb97794767a7c4686ad557c +b6c61d01fd8ce087ef9f079bf25bf10090db483dd4f88c4a786d31c1bdf52065651c1f5523f20c21e75cea17df69ab73 +a5790fd629be70545093631efadddc136661f63b65ec682609c38ef7d3d7fa4e56bdf94f06e263bc055b90cb1c6bcefe +b515a767e95704fb7597bca9e46f1753abacdc0e56e867ee3c6f4cd382643c2a28e65312c05ad040eaa3a8cbe7217a65 +8135806a02ead6aa92e9adb6fefb91349837ab73105aaa7be488ef966aa8dfaafdfa64bbae30fcbfa55dd135a036a863 +8f22435702716d76b1369750694540742d909d5e72b54d0878245fab7c269953b1c6f2b29c66f08d5e0263ca3a731771 +8e0f8a8e8753e077dac95848212aeffd51c23d9b6d611df8b102f654089401954413ecbedc6367561ca599512ae5dda7 +815a9084e3e2345f24c5fa559deec21ee1352fb60f4025c0779be65057f2d528a3d91593bd30d3a185f5ec53a9950676 +967e6555ccba395b2cc1605f8484c5112c7b263f41ce8439a99fd1c71c5ed14ad02684d6f636364199ca48afbbde13be +8cd0ccf17682950b34c796a41e2ea7dd5367aba5e80a907e01f4cdc611e4a411918215e5aebf4292f8b24765d73314a6 +a58bf1bbb377e4b3915df6f058a0f53b8fb8130fdec8c391f6bc82065694d0be59bb67ffb540e6c42cc8b380c6e36359 +92af3151d9e6bfb3383d85433e953c0160859f759b0988431ec5893542ba40288f65db43c78a904325ef8d324988f09d +8011bbb05705167afb47d4425065630f54cb86cd462095e83b81dfebf348f846e4d8fbcf1c13208f5de1931f81da40b9 +81c743c104fc3cb047885c9fa0fb9705c3a83ee24f690f539f4985509c3dafd507af3f6a2128276f45d5939ef70c167f +a2c9679b151c041aaf5efeac5a737a8f70d1631d931609fca16be1905682f35e291292874cb3b03f14994f98573c6f44 +a4949b86c4e5b1d5c82a337e5ce6b2718b1f7c215148c8bfb7e7c44ec86c5c9476048fc5c01f57cb0920876478c41ad6 +86c2495088bd1772152e527a1da0ef473f924ea9ab0e5b8077df859c28078f73c4e22e3a906b507fdf217c3c80808b5c +892e0a910dcf162bcea379763c3e2349349e4cda9402949255ac4a78dd5a47e0bf42f5bd0913951576b1d206dc1e536a +a7009b2c6b396138afe4754b7cc10dee557c51c7f1a357a11486b3253818531f781ea8107360c8d4c3b1cd96282353c0 +911763ef439c086065cc7b4e57484ed6d693ea44acee4b18c9fd998116da55fbe7dcb8d2a0f0f9b32132fca82d73dff6 +a722000b95a4a2d40bed81870793f15ba2af633f9892df507f2842e52452e02b5ea8dea6a043c2b2611d82376e33742a +9387ac49477bd719c2f92240d0bdfcf9767aad247ca93dc51e56106463206bc343a8ec855eb803471629a66fffb565d6 +92819a1fa48ab4902939bb72a0a4e6143c058ea42b42f9bc6cea5df45f49724e2530daf3fc4f097cceefa2a8b9db0076 +98eac7b04537653bc0f4941aae732e4b1f84bd276c992c64a219b8715eb1fb829b5cbd997d57feb15c7694c468f95f70 +b275e7ba848ce21bf7996e12dbeb8dadb5d0e4f1cb5a0248a4f8f9c9fe6c74e3c93f4b61edbcb0a51af5a141e1c14bc7 +97243189285aba4d49c53770c242f2faf5fd3914451da4931472e3290164f7663c726cf86020f8f181e568c72fd172d1 +839b0b3c25dd412bee3dc24653b873cc65454f8f16186bb707bcd58259c0b6765fa4c195403209179192a4455c95f3b8 +8689d1a870514568a074a38232e2ceb4d7df30fabeb76cff0aed5b42bf7f02baea12c5fadf69f4713464dbd52aafa55f +8958ae7b290f0b00d17c3e9fdb4dbf168432b457c7676829299dd428984aba892de1966fc106cfc58a772862ecce3976 +a422bc6bd68b8870cfa5bc4ce71781fd7f4368b564d7f1e0917f6013c8bbb5b240a257f89ecfdbecb40fe0f3aa31d310 +aa61f78130cebe09bc9a2c0a37f0dd57ed2d702962e37d38b1df7f17dc554b1d4b7a39a44182a452ce4c5eb31fa4cfcc +b7918bd114f37869bf1a459023386825821bfadce545201929d13ac3256d92a431e34f690a55d944f77d0b652cefeffc +819bba35fb6ace1510920d4dcff30aa682a3c9af9022e287751a6a6649b00c5402f14b6309f0aeef8fce312a0402915e +8b7c9ad446c6f63c11e1c24e24014bd570862b65d53684e107ba9ad381e81a2eaa96731b4b33536efd55e0f055071274 +8fe79b53f06d33386c0ec7d6d521183c13199498594a46d44a8a716932c3ec480c60be398650bbfa044fa791c4e99b65 +9558e10fb81250b9844c99648cf38fa05ec1e65d0ccbb18aa17f2d1f503144baf59d802c25be8cc0879fff82ed5034ad +b538a7b97fbd702ba84645ca0a63725be1e2891c784b1d599e54e3480e4670d0025526674ef5cf2f87dddf2290ba09f0 +92eafe2e869a3dd8519bbbceb630585c6eb21712b2f31e1b63067c0acb5f9bdbbcbdb612db4ea7f9cc4e7be83d31973f +b40d21390bb813ab7b70a010dff64c57178418c62685761784e37d327ba3cb9ef62df87ecb84277c325a637fe3709732 +b349e6fbf778c4af35fbed33130bd8a7216ed3ba0a79163ebb556e8eb8e1a7dad3456ddd700dad9d08d202491c51b939 +a8fdaedecb251f892b66c669e34137f2650509ade5d38fbe8a05d9b9184bb3b2d416186a3640429bd1f3e4b903c159dd +ac6167ebfee1dbab338eff7642f5e785fc21ef0b4ddd6660333fe398068cbd6c42585f62e81e4edbb72161ce852a1a4f +874b1fbf2ebe140c683bd7e4e0ab017afa5d4ad38055aaa83ee6bbef77dbc88a6ce8eb0dcc48f0155244af6f86f34c2d +903c58e57ddd9c446afab8256a6bb6c911121e6ccfb4f9b4ed3e2ed922a0e500a5cb7fa379d5285bc16e11dac90d1fda +8dae7a0cffa2fd166859cd1bf10ff82dd1932e488af377366b7efc0d5dec85f85fe5e8150ff86a79a39cefc29631733a +aa047857a47cc4dfc08585f28640420fcf105b881fd59a6cf7890a36516af0644d143b73f3515ab48faaa621168f8c31 +864508f7077c266cc0cb3f7f001cb6e27125ebfe79ab57a123a8195f2e27d3799ff98413e8483c533b46a816a3557f1f +8bcd45ab1f9cbab36937a27e724af819838f66dfeb15923f8113654ff877bd8667c54f6307aaf0c35027ca11b6229bfd +b21aa34da9ab0a48fcfdd291df224697ce0c1ebc0e9b022fdee8750a1a4b5ba421c419541ed5c98b461eecf363047471 +a9a18a2ab2fae14542dc336269fe612e9c1af6cf0c9ac933679a2f2cb77d3c304114f4d219ca66fe288adde30716775b +b5205989b92c58bdda71817f9a897e84100b5c4e708de1fced5c286f7a6f01ae96b1c8d845f3a320d77c8e2703c0e8b1 +a364059412bbcc17b8907d43ac8e5df90bc87fd1724b5f99832d0d24559fae6fa76a74cff1d1eac8cbac6ec80b44af20 +ae709f2c339886b31450834cf29a38b26eb3b0779bd77c9ac269a8a925d1d78ea3837876c654b61a8fe834b3b6940808 +8802581bba66e1952ac4dab36af371f66778958f4612901d95e5cac17f59165e6064371d02de8fb6fccf89c6dc8bd118 +a313252df653e29c672cbcfd2d4f775089cb77be1077381cf4dc9533790e88af6cedc8a119158e7da5bf6806ad9b91a1 +992a065b4152c7ef11515cd54ba9d191fda44032a01aed954acff3443377ee16680c7248d530b746b8c6dee2d634e68c +b627b683ee2b32c1ab4ccd27b9f6cce2fe097d96386fa0e5c182ad997c4c422ab8dfc03870cd830b8c774feb66537282 +b823cf8a9aee03dadd013eb9efe40a201b4b57ef67efaae9f99683005f5d1bf55e950bf4af0774f50859d743642d3fea +b8a7449ffac0a3f206677097baf7ce00ca07a4d2bd9b5356fbcb83f3649b0fda07cfebad220c1066afba89e5a52abf4b +b2dd1a2f986395bb4e3e960fbbe823dbb154f823284ebc9068502c19a7609790ec0073d08bfa63f71e30c7161b6ef966 +98e5236de4281245234f5d40a25b503505af140b503a035fc25a26159a9074ec81512b28f324c56ea2c9a5aa7ce90805 +89070847dc8bbf5bc4ed073aa2e2a1f699cf0c2ca226f185a0671cecc54e7d3e14cd475c7752314a7a8e7476829da4bc +a9402dc9117fdb39c4734c0688254f23aed3dce94f5f53f5b7ef2b4bf1b71a67f85ab1a38ec224a59691f3bee050aeb3 +957288f9866a4bf56a4204218ccc583f717d7ce45c01ea27142a7e245ad04a07f289cc044f8cf1f21d35e67e39299e9c +b2fb31ccb4e69113763d7247d0fc8edaae69b550c5c56aecacfd780c7217dc672f9fb7496edf4aba65dacf3361268e5b +b44a4526b2f1d6eb2aa8dba23bfa385ff7634572ab2afddd0546c3beb630fbfe85a32f42dd287a7fec069041411537f7 +8db5a6660c3ac7fd7a093573940f068ee79a82bc17312af900b51c8c439336bc86ca646c6b7ab13aaaa008a24ca508ab +8f9899a6d7e8eb4367beb5c060a1f8e94d8a21099033ae582118477265155ba9e72176a67f7f25d7bad75a152b56e21a +a67de0e91ade8d69a0e00c9ff33ee2909b8a609357095fa12319e6158570c232e5b6f4647522efb7345ce0052aa9d489 +82eb2414898e9c3023d57907a2b17de8e7eea5269029d05a94bfd7bf5685ac4a799110fbb375eb5e0e2bd16acf6458ae +94451fc7fea3c5a89ba701004a9693bab555cb622caf0896b678faba040409fdfd14a978979038b2a81e8f0abc4994d2 +ac879a5bb433998e289809a4a966bd02b4bf6a9c1cc276454e39c886efcf4fc68baebed575826bde577ab5aa71d735a9 +880c0f8f49c875dfd62b4ddedde0f5c8b19f5687e693717f7e5c031bc580e58e13ab497d48b4874130a18743c59fdce3 +b582af8d8ff0bf76f0a3934775e0b54c0e8fed893245d7d89cae65b03c8125b7237edc29dc45b4fe1a3fe6db45d280ee +89f337882ed3ae060aaee98efa20d79b6822bde9708c1c5fcee365d0ec9297f694cae37d38fd8e3d49717c1e86f078e7 +826d2c1faea54061848b484e288a5f4de0d221258178cf87f72e14baaa4acc21322f8c9eab5dde612ef497f2d2e1d60b +a5333d4f227543e9cd741ccf3b81db79f2f03ca9e649e40d6a6e8ff9073e06da83683566d3b3c8d7b258c62970fb24d1 +a28f08c473db06aaf4c043a2fae82b3c8cfaa160bce793a4c208e4e168fb1c65115ff8139dea06453c5963d95e922b94 +8162546135cc5e124e9683bdfaa45833c18553ff06a0861c887dc84a5b12ae8cd4697f6794c7ef6230492c32faba7014 +b23f0d05b74c08d6a7df1760792be83a761b36e3f8ae360f3c363fb196e2a9dd2de2e492e49d36561366e14daa77155c +b6f70d6c546722d3907c708d630dbe289771d2c8bf059c2e32b77f224696d750b4dda9b3a014debda38e7d02c9a77585 +83bf4c4a9f3ca022c631017e7a30ea205ba97f7f5927cba8fc8489a4646eac6712cb821c5668c9ffe94d69d524374a27 +b0371475425a8076d0dd5f733f55aabbe42d20a7c8ea7da352e736d4d35a327b2beb370dfcb05284e22cfd69c5f6c4cc +a0031ba7522c79211416c2cca3aa5450f96f8fee711552a30889910970ba13608646538781a2c08b834b140aadd7166f +99d273c80c7f2dc6045d4ed355d9fc6f74e93549d961f4a3b73cd38683f905934d359058cd1fc4da8083c7d75070487f +b0e4b0efa3237793e9dcce86d75aafe9879c5fa23f0d628649aef2130454dcf72578f9bf227b9d2b9e05617468e82588 +a5ab076fa2e1c5c51f3ae101afdd596ad9d106bba7882b359c43d8548b64f528af19afa76cd6f40da1e6c5fca4def3fa +8ce2299e570331d60f6a6eff1b271097cd5f1c0e1113fc69b89c6a0f685dabea3e5bc2ac6bd789aa492ab189f89be494 +91b829068874d911a310a5f9dee001021f97471307b5a3de9ec336870ec597413e1d92010ce320b619f38bed7c4f7910 +b14fe91f4b07bf33b046e9285b66cb07927f3a8da0af548ac2569b4c4fb1309d3ced76d733051a20814e90dd5b75ffd1 +abaab92ea6152d40f82940277c725aa768a631ee0b37f5961667f82fb990fc11e6d3a6a2752b0c6f94563ed9bb28265c +b7fe28543eca2a716859a76ab9092f135337e28109544f6bd2727728d0a7650428af5713171ea60bfc273d1c821d992c +8a4917b2ab749fc7343fc64bdf51b6c0698ff15d740cc7baf248c030475c097097d5a473bcc00d8c25817563fe0447b4 +aa96156d1379553256350a0a3250166add75948fb9cde62aa555a0a9dc0a9cb7f2f7b8428aff66097bf6bfedaf14bbe2 +ae4ffeb9bdc76830d3eca2b705f30c1bdede6412fa064260a21562c8850c7fb611ec62bc68479fe48f692833e6f66d8d +b96543caaba9d051600a14997765d49e4ab10b07c7a92cccf0c90b309e6da334fdd6d18c96806cbb67a7801024fbd3c7 +97b2b9ad76f19f500fcc94ca8e434176249f542ac66e5881a3dccd07354bdab6a2157018b19f8459437a68d8b86ba8e0 +a8d206f6c5a14c80005849474fde44b1e7bcf0b2d52068f5f97504c3c035b09e65e56d1cf4b5322791ae2c2fdbd61859 +936bad397ad577a70cf99bf9056584a61bd7f02d2d5a6cf219c05d770ae30a5cd902ba38366ce636067fc1dd10108d31 +a77e30195ee402b84f3882e2286bf5380c0ed374a112dbd11e16cef6b6b61ab209d4635e6f35cdaaa72c1a1981d5dabe +a46ba4d3947188590a43c180757886a453a0503f79cc435322d92490446f37419c7b999fdf868a023601078070e03346 +80d8d4c5542f223d48240b445d4d8cf6a75d120b060bc08c45e99a13028b809d910b534d2ac47fb7068930c54efd8da9 +803be9c68c91b42b68e1f55e58917a477a9a6265e679ca44ee30d3eb92453f8c89c64eafc04c970d6831edd33d066902 +b14b2b3d0dfe2bb57cee4cd72765b60ac33c1056580950be005790176543826c1d4fbd737f6cfeada6c735543244ab57 +a9e480188bba1b8fb7105ff12215706665fd35bf1117bacfb6ab6985f4dbc181229873b82e5e18323c2b8f5de03258e0 +a66a0f0779436a9a3999996d1e6d3000f22c2cac8e0b29cddef9636393c7f1457fb188a293b6c875b05d68d138a7cc4a +848397366300ab40c52d0dbbdafbafef6cd3dadf1503bb14b430f52bb9724188928ac26f6292a2412bc7d7aa620763c8 +95466cc1a78c9f33a9aaa3829a4c8a690af074916b56f43ae46a67a12bb537a5ac6dbe61590344a25b44e8512355a4a7 +8b5f7a959f818e3baf0887f140f4575cac093d0aece27e23b823cf421f34d6e4ff4bb8384426e33e8ec7b5eed51f6b5c +8d5e1368ec7e3c65640d216bcc5d076f3d9845924c734a34f3558ac0f16e40597c1a775a25bf38b187213fbdba17c93b +b4647c1b823516880f60d20c5cc38c7f80b363c19d191e8992226799718ee26b522a12ecb66556ed3d483aa4824f3326 +ac3abaea9cd283eb347efda4ed9086ea3acf495043e08d0d19945876329e8675224b685612a6badf8fd72fb6274902b1 +8eae1ce292d317aaa71bcf6e77e654914edd5090e2e1ebab78b18bb41b9b1bc2e697439f54a44c0c8aa0d436ebe6e1a9 +94dc7d1aec2c28eb43d93b111fa59aaa0d77d5a09501220bd411768c3e52208806abf973c6a452fd8292ff6490e0c9e2 +8fd8967f8e506fef27d17b435d6b86b232ec71c1036351f12e6fb8a2e12daf01d0ee04451fb944d0f1bf7fd20e714d02 +824e6865be55d43032f0fec65b3480ea89b0a2bf860872237a19a54bc186a85d2f8f9989cc837fbb325b7c72d9babe2c +8bd361f5adb27fd6f4e3f5de866e2befda6a8454efeb704aacc606f528c03f0faae888f60310e49440496abd84083ce2 +b098a3c49f2aaa28b6b3e85bc40ce6a9cdd02134ee522ae73771e667ad7629c8d82c393fba9f27f5416986af4c261438 +b385f5ca285ff2cfe64dcaa32dcde869c28996ed091542600a0b46f65f3f5a38428cca46029ede72b6cf43e12279e3d3 +8196b03d011e5be5288196ef7d47137d6f9237a635ab913acdf9c595fa521d9e2df722090ec7eb0203544ee88178fc5f +8ed1270211ef928db18e502271b7edf24d0bbd11d97f2786aee772d70c2029e28095cf8f650b0328cc8a4c38d045316d +a52ab60e28d69b333d597a445884d44fd2a7e1923dd60f763951e1e45f83e27a4dac745f3b9eff75977b3280e132c15d +91e9fe78cdac578f4a4687f71b800b35da54b824b1886dafec073a3c977ce7a25038a2f3a5b1e35c2c8c9d1a7312417c +a42832173f9d9491c7bd93b21497fbfa4121687cd4d2ab572e80753d7edcbb42cfa49f460026fbde52f420786751a138 +97b947126d84dcc70c97be3c04b3de3f239b1c4914342fa643b1a4bb8c4fe45c0fcb585700d13a7ed50784790c54bef9 +860e407d353eac070e2418ef6cb80b96fc5f6661d6333e634f6f306779651588037be4c2419562c89c61f9aa2c4947f5 +b2c9d93c3ba4e511b0560b55d3501bf28a510745fd666b3cb532db051e6a8617841ea2f071dda6c9f15619c7bfd2737f +8596f4d239aeeac78311207904d1bd863ef68e769629cc379db60e019aaf05a9d5cd31dc8e630b31e106a3a93e47cbc5 +8b26e14e2e136b65c5e9e5c2022cee8c255834ea427552f780a6ca130a6446102f2a6f334c3f9a0308c53df09e3dba7e +b54724354eb515a3c8bed0d0677ff1db94ac0a07043459b4358cb90e3e1aa38ac23f2caa3072cf9647275d7cd61d0e80 +b7ce9fe0e515e7a6b2d7ddcb92bc0196416ff04199326aea57996eef8c5b1548bd8569012210da317f7c0074691d01b7 +a1a13549c82c877253ddefa36a29ea6a23695ee401fdd48e65f6f61e5ebd956d5e0edeff99484e9075cb35071fec41e2 +838ba0c1e5bd1a6da05611ff1822b8622457ebd019cb065ece36a2d176bd2d889511328120b8a357e44569e7f640c1e6 +b916eccff2a95519400bbf76b5f576cbe53cf200410370a19d77734dc04c05b585cfe382e8864e67142d548cd3c4c2f4 +a610447cb7ca6eea53a6ff1f5fe562377dcb7f4aaa7300f755a4f5e8eba61e863c51dc2aa9a29b35525b550fbc32a0fe +9620e8f0f0ee9a4719aa9685eeb1049c5c77659ba6149ec4c158f999cfd09514794b23388879931fe26fea03fa471fd3 +a9dcf8b679e276583cf5b9360702a185470d09aea463dc474ee9c8aee91ef089dacb073e334e47fbc78ec5417c90465c +8c9adee8410bdd99e5b285744cee61e2593b6300ff31a8a83b0ec28da59475a5c6fb9346fe43aadea2e6c3dad2a8e30a +97d5afe9b3897d7b8bb628b7220cf02d8ee4e9d0b78f5000d500aaf4c1df9251aaaabfd1601626519f9d66f00a821d4e +8a382418157b601ce4c3501d3b8409ca98136a4ef6abcbf62885e16e215b76b035c94d149cc41ff92e42ccd7c43b9b3d +b64b8d11fb3b01abb2646ac99fdb9c02b804ce15d98f9fe0fbf1c9df8440c71417487feb6cdf51e3e81d37104b19e012 +849d7d044f9d8f0aab346a9374f0b3a5d14a9d1faa83dbacccbdc629ad1ef903a990940255564770537f8567521d17f0 +829dbb0c76b996c2a91b4cbbe93ba455ca0d5729755e5f0c92aaee37dff7f36fcdc06f33aca41f1b609c784127b67d88 +85a7c0069047b978422d264d831ab816435f63938015d2e977222b6b5746066c0071b7f89267027f8a975206ed25c1b0 +84b9fbc1cfb302df1acdcf3dc5d66fd1edfe7839f7a3b2fb3a0d5548656249dd556104d7c32b73967bccf0f5bdcf9e3b +972220ac5b807f53eac37dccfc2ad355d8b21ea6a9c9b011c09fe440ddcdf7513e0b43d7692c09ded80d7040e26aa28f +855885ed0b21350baeca890811f344c553cf9c21024649c722453138ba29193c6b02c4b4994cd414035486f923472e28 +841874783ae6d9d0e59daea03e96a01cbbe4ecaced91ae4f2c8386e0d87b3128e6d893c98d17c59e4de1098e1ad519dd +827e50fc9ce56f97a4c3f2f4cbaf0b22f1c3ce6f844ff0ef93a9c57a09b8bf91ebfbd2ba9c7f83c442920bffdaf288cc +a441f9136c7aa4c08d5b3534921b730e41ee91ab506313e1ba5f7c6f19fd2d2e1594e88c219834e92e6fb95356385aa7 +97d75b144471bf580099dd6842b823ec0e6c1fb86dd0da0db195e65524129ea8b6fd4a7a9bbf37146269e938a6956596 +a4b6fa87f09d5a29252efb2b3aaab6b3b6ea9fab343132a651630206254a25378e3e9d6c96c3d14c150d01817d375a8e +a31a671876d5d1e95fe2b8858dc69967231190880529d57d3cab7f9f4a2b9b458ac9ee5bdaa3289158141bf18f559efb +90bee6fff4338ba825974021b3b2a84e36d617e53857321f13d2b3d4a28954e6de3b3c0e629d61823d18a9763313b3bf +96b622a63153f393bb419bfcf88272ea8b3560dbd46b0aa07ada3a6223990d0abdd6c2adb356ef4be5641688c8d83941 +84c202adeaff9293698022bc0381adba2cd959f9a35a4e8472288fd68f96f6de8be9da314c526d88e291c96b1f3d6db9 +8ca01a143b8d13809e5a8024d03e6bc9492e22226073ef6e327edf1328ef4aff82d0bcccee92cb8e212831fa35fe1204 +b2f970dbad15bfbefb38903c9bcc043d1367055c55dc1100a850f5eb816a4252c8c194b3132c929105511e14ea10a67d +a5e36556472a95ad57eb90c3b6623671b03eafd842238f01a081997ffc6e2401f76e781d049bb4aa94d899313577a9cf +8d1057071051772f7c8bedce53a862af6fd530dd56ae6321eaf2b9fc6a68beff5ed745e1c429ad09d5a118650bfd420a +8aadc4f70ace4fcb8d93a78610779748dcffc36182d45b932c226dc90e48238ea5daa91f137c65ed532352c4c4d57416 +a2ea05ae37e673b4343232ae685ee14e6b88b867aef6dfac35db3589cbcd76f99540fed5c2641d5bb5a4a9f808e9bf0d +947f1abad982d65648ae4978e094332b4ecb90f482c9be5741d5d1cf5a28acf4680f1977bf6e49dd2174c37f11e01296 +a27b144f1565e4047ba0e3f4840ef19b5095d1e281eaa463c5358f932114cbd018aa6dcf97546465cf2946d014d8e6d6 +8574e1fc3acade47cd4539df578ce9205e745e161b91e59e4d088711a7ab5aa3b410d517d7304b92109924d9e2af8895 +a48ee6b86b88015d6f0d282c1ae01d2a5b9e8c7aa3d0c18b35943dceb1af580d08a65f54dc6903cde82fd0d73ce94722 +8875650cec543a7bf02ea4f2848a61d167a66c91ffaefe31a9e38dc8511c6a25bde431007eefe27a62af3655aca208dc +999b0a6e040372e61937bf0d68374e230346b654b5a0f591a59d33a4f95bdb2f3581db7c7ccb420cd7699ed709c50713 +878c9e56c7100c5e47bbe77dc8da5c5fe706cec94d37fa729633bca63cace7c40102eee780fcdabb655f5fa47a99600e +865006fb5b475ada5e935f27b96f9425fc2d5449a3c106aa366e55ebed3b4ee42adc3c3f0ac19fd129b40bc7d6bc4f63 +b7a7da847f1202e7bc1672553e68904715e84fd897d529243e3ecda59faa4e17ba99c649a802d53f6b8dfdd51f01fb74 +8b2fb4432c05653303d8c8436473682933a5cb604da10c118ecfcd2c8a0e3132e125afef562bdbcc3df936164e5ce4f2 +808d95762d33ddfa5d0ee3d7d9f327de21a994d681a5f372e2e3632963ea974da7f1f9e5bac8ccce24293509d1f54d27 +932946532e3c397990a1df0e94c90e1e45133e347a39b6714c695be21aeb2d309504cb6b1dde7228ff6f6353f73e1ca2 +9705e7c93f0cdfaa3fa96821f830fe53402ad0806036cd1b48adc2f022d8e781c1fbdab60215ce85c653203d98426da3 +aa180819531c3ec1feb829d789cb2092964c069974ae4faad60e04a6afcce5c3a59aec9f11291e6d110a788d22532bc6 +88f755097f7e25cb7dd3c449520c89b83ae9e119778efabb54fbd5c5714b6f37c5f9e0346c58c6ab09c1aef2483f895d +99fc03ab7810e94104c494f7e40b900f475fde65bdec853e60807ffd3f531d74de43335c3b2646b5b8c26804a7448898 +af2dea9683086bed1a179110efb227c9c00e76cd00a2015b089ccbcee46d1134aa18bda5d6cab6f82ae4c5cd2461ac21 +a500f87ba9744787fdbb8e750702a3fd229de6b8817594348dec9a723b3c4240ddfa066262d002844b9e38240ce55658 +924d0e45c780f5bc1c1f35d15dfc3da28036bdb59e4c5440606750ecc991b85be18bc9a240b6c983bc5430baa4c68287 +865b11e0157b8bf4c5f336024b016a0162fc093069d44ac494723f56648bc4ded13dfb3896e924959ea11c96321afefc +93672d8607d4143a8f7894f1dcca83fb84906dc8d6dd7dd063bb0049cfc20c1efd933e06ca7bd03ea4cb5a5037990bfe +826891efbdff0360446825a61cd1fa04326dd90dae8c33dfb1ed97b045e165766dd070bd7105560994d0b2044bdea418 +93c4a4a8bcbc8b190485cc3bc04175b7c0ed002c28c98a540919effd6ed908e540e6594f6db95cd65823017258fb3b1c +aeb2a0af2d2239fda9aa6b8234b019708e8f792834ff0dd9c487fa09d29800ddceddd6d7929faa9a3edcb9e1b3aa0d6b +87f11de7236d387863ec660d2b04db9ac08143a9a2c4dfff87727c95b4b1477e3bc473a91e5797313c58754905079643 +80dc1db20067a844fe8baceca77f80db171a5ca967acb24e2d480eae9ceb91a3343c31ad1c95b721f390829084f0eae6 +9825c31f1c18da0de3fa84399c8b40f8002c3cae211fb6a0623c76b097b4d39f5c50058f57a16362f7a575909d0a44a2 +a99fc8de0c38dbf7b9e946de83943a6b46a762167bafe2a603fb9b86f094da30d6de7ed55d639aafc91936923ee414b3 +ad594678b407db5d6ea2e90528121f84f2b96a4113a252a30d359a721429857c204c1c1c4ff71d8bb5768c833f82e80e +b33d985e847b54510b9b007e31053732c8a495e43be158bd2ffcea25c6765bcbc7ca815f7c60b36ad088b955dd6e9350 +815f8dfc6f90b3342ca3fbd968c67f324dae8f74245cbf8bc3bef10e9440c65d3a2151f951e8d18959ba01c1b50b0ec1 +94c608a362dd732a1abc56e338637c900d59013db8668e49398b3c7a0cae3f7e2f1d1bf94c0299eeafe6af7f76c88618 +8ebd8446b23e5adfcc393adc5c52fe172f030a73e63cd2d515245ca0dd02782ceed5bcdd9ccd9c1b4c5953dfac9c340c +820437f3f6f9ad0f5d7502815b221b83755eb8dc56cd92c29e9535eb0b48fb8d08c9e4fcc26945f9c8cca60d89c44710 +8910e4e8a56bf4be9cc3bbf0bf6b1182a2f48837a2ed3c2aaec7099bfd7f0c83e14e608876b17893a98021ff4ab2f20d +9633918fde348573eec15ce0ad53ac7e1823aac86429710a376ad661002ae6d049ded879383faaa139435122f64047c6 +a1f5e3fa558a9e89318ca87978492f0fb4f6e54a9735c1b8d2ecfb1d1c57194ded6e0dd82d077b2d54251f3bee1279e1 +b208e22d04896abfd515a95c429ff318e87ff81a5d534c8ac2c33c052d6ffb73ef1dccd39c0bbe0734b596c384014766 +986d5d7d2b5bde6d16336f378bd13d0e671ad23a8ec8a10b3fc09036faeeb069f60662138d7a6df3dfb8e0d36180f770 +a2d4e6c5f5569e9cef1cddb569515d4b6ace38c8aed594f06da7434ba6b24477392cc67ba867c2b079545ca0c625c457 +b5ac32b1d231957d91c8b7fc43115ce3c5c0d8c13ca633374402fa8000b6d9fb19499f9181844f0c10b47357f3f757ce +96b8bf2504b4d28fa34a4ec378e0e0b684890c5f44b7a6bb6e19d7b3db2ab27b1e2686389d1de9fbd981962833a313ea +953bfd7f6c3a0469ad432072b9679a25486f5f4828092401eff494cfb46656c958641a4e6d0d97d400bc59d92dba0030 +876ab3cea7484bbfd0db621ec085b9ac885d94ab55c4bb671168d82b92e609754b86aaf472c55df3d81421d768fd108a +885ff4e67d9ece646d02dd425aa5a087e485c3f280c3471b77532b0db6145b69b0fbefb18aa2e3fa5b64928b43a94e57 +b91931d93f806d0b0e6cc62a53c718c099526140f50f45d94b8bbb57d71e78647e06ee7b42aa5714aed9a5c05ac8533f +a0313eeadd39c720c9c27b3d671215331ab8d0a794e71e7e690f06bcd87722b531d6525060c358f35f5705dbb7109ccb +874c0944b7fedc6701e53344100612ddcb495351e29305c00ec40a7276ea5455465ffb7bded898886c1853139dfb1fc7 +8dc31701a01ee8137059ca1874a015130d3024823c0576aa9243e6942ec99d377e7715ed1444cd9b750a64b85dcaa3e5 +836d2a757405e922ec9a2dfdcf489a58bd48b5f9683dd46bf6047688f778c8dee9bc456de806f70464df0b25f3f3d238 +b30b0a1e454a503ea3e2efdec7483eaf20b0a5c3cefc42069e891952b35d4b2c955cf615f3066285ed8fafd9fcfbb8f6 +8e6d4044b55ab747e83ec8762ea86845f1785cc7be0279c075dadf08aca3ccc5a096c015bb3c3f738f647a4eadea3ba5 +ad7735d16ab03cbe09c029610aa625133a6daecfc990b297205b6da98eda8c136a7c50db90f426d35069708510d5ae9c +8d62d858bbb59ec3c8cc9acda002e08addab4d3ad143b3812098f3d9087a1b4a1bb255dcb1635da2402487d8d0249161 +805beec33238b832e8530645a3254aeef957e8f7ea24bcfc1054f8b9c69421145ebb8f9d893237e8a001c857fedfc77e +b1005644be4b085e3f5775aa9bd3e09a283e87ddada3082c04e7a62d303dcef3b8cf8f92944c200c7ae6bb6bdf63f832 +b4ba0e0790dc29063e577474ffe3b61f5ea2508169f5adc1e394934ebb473e356239413a17962bc3e5d3762d72cce8c2 +a157ba9169c9e3e6748d9f1dd67fbe08b9114ade4c5d8fc475f87a764fb7e6f1d21f66d7905cd730f28a1c2d8378682a +913e52b5c93989b5d15e0d91aa0f19f78d592bc28bcfdfddc885a9980c732b1f4debb8166a7c4083c42aeda93a702898 +90fbfc1567e7cd4e096a38433704d3f96a2de2f6ed3371515ccc30bc4dd0721a704487d25a97f3c3d7e4344472702d8d +89646043028ffee4b69d346907586fd12c2c0730f024acb1481abea478e61031966e72072ff1d5e65cb8c64a69ad4eb1 +b125a45e86117ee11d2fb42f680ab4a7894edd67ff927ae2c808920c66c3e55f6a9d4588eee906f33a05d592e5ec3c04 +aad47f5b41eae9be55fb4f67674ff1e4ae2482897676f964a4d2dcb6982252ee4ff56aac49578b23f72d1fced707525e +b9ddff8986145e33851b4de54d3e81faa3352e8385895f357734085a1616ef61c692d925fe62a5ed3be8ca49f5d66306 +b3cb0963387ed28c0c0adf7fe645f02606e6e1780a24d6cecef5b7c642499109974c81a7c2a198b19862eedcea2c2d8c +ac9c53c885457aaf5cb36c717a6f4077af701e0098eebd7aa600f5e4b14e6c1067255b3a0bc40e4a552025231be7de60 +8e1a8d823c4603f6648ec21d064101094f2a762a4ed37dd2f0a2d9aa97b2d850ce1e76f4a4b8cae58819b058180f7031 +b268b73bf7a179b6d22bd37e5e8cb514e9f5f8968c78e14e4f6d5700ca0d0ca5081d0344bb73b028970eebde3cb4124e +a7f57d71940f0edbd29ed8473d0149cae71d921dd15d1ff589774003e816b54b24de2620871108cec1ab9fa956ad6ce6 +8053e6416c8b120e2b999cc2fc420a6a55094c61ac7f2a6c6f0a2c108a320890e389af96cbe378936132363c0d551277 +b3823f4511125e5aa0f4269e991b435a0d6ceb523ebd91c04d7add5534e3df5fc951c504b4fd412a309fd3726b7f940b +ae6eb04674d04e982ca9a6add30370ab90e303c71486f43ed3efbe431af1b0e43e9d06c11c3412651f304c473e7dbf39 +96ab55e641ed2e677591f7379a3cd126449614181fce403e93e89b1645d82c4af524381ff986cae7f9cebe676878646d +b52423b4a8c37d3c3e2eca8f0ddbf7abe0938855f33a0af50f117fab26415fb0a3da5405908ec5fdc22a2c1f2ca64892 +82a69ce1ee92a09cc709d0e3cd22116c9f69d28ea507fe5901f5676000b5179b9abe4c1875d052b0dd42d39925e186bb +a84c8cb84b9d5cfb69a5414f0a5283a5f2e90739e9362a1e8c784b96381b59ac6c18723a4aa45988ee8ef5c1f45cc97d +afd7efce6b36813082eb98257aae22a4c1ae97d51cac7ea9c852d4a66d05ef2732116137d8432e3f117119725a817d24 +a0f5fe25af3ce021b706fcff05f3d825384a272284d04735574ce5fb256bf27100fad0b1f1ba0e54ae9dcbb9570ecad3 +8751786cb80e2e1ff819fc7fa31c2833d25086534eb12b373d31f826382430acfd87023d2a688c65b5e983927e146336 +8cf5c4b17fa4f3d35c78ce41e1dc86988fd1135cd5e6b2bb0c108ee13538d0d09ae7102609c6070f39f937b439b31e33 +a9108967a2fedd7c322711eca8159c533dd561bedcb181b646de98bf5c3079449478eab579731bee8d215ae8852c7e21 +b54c5171704f42a6f0f4e70767cdb3d96ffc4888c842eece343a01557da405961d53ffdc34d2f902ea25d3e1ed867cad +ae8d4b764a7a25330ba205bf77e9f46182cd60f94a336bbd96773cf8064e3d39caf04c310680943dc89ed1fbad2c6e0d +aa5150e911a8e1346868e1b71c5a01e2a4bb8632c195861fb6c3038a0e9b85f0e09b3822e9283654a4d7bb17db2fc5f4 +9685d3756ce9069bf8bb716cf7d5063ebfafe37e15b137fc8c3159633c4e006ff4887ddd0ae90360767a25c3f90cba7f +82155fd70f107ab3c8e414eadf226c797e07b65911508c76c554445422325e71af8c9a8e77fd52d94412a6fc29417cd3 +abfae52f53a4b6e00760468d973a267f29321997c3dbb5aee36dc1f20619551229c0c45b9d9749f410e7f531b73378e8 +81a76d921f8ef88e774fd985e786a4a330d779b93fad7def718c014685ca0247379e2e2a007ad63ee7f729cd9ed6ce1b +81947c84bc5e28e26e2e533af5ae8fe10407a7b77436dbf8f1d5b0bbe86fc659eae10f974659dc7c826c6dabd03e3a4b +92b8c07050d635b8dd4fd09df9054efe4edae6b86a63c292e73cc819a12a21dd7d104ce51fa56af6539dedf6dbe6f7b6 +b44c579e3881f32b32d20c82c207307eca08e44995dd2aac3b2692d2c8eb2a325626c80ac81c26eeb38c4137ff95add5 +97efab8941c90c30860926dea69a841f2dcd02980bf5413b9fd78d85904588bf0c1021798dbc16c8bbb32cce66c82621 +913363012528b50698e904de0588bf55c8ec5cf6f0367cfd42095c4468fcc64954fbf784508073e542fee242d0743867 +8ed203cf215148296454012bd10fddaf119203db1919a7b3d2cdc9f80e66729464fdfae42f1f2fc5af1ed53a42b40024 +ab84312db7b87d711e9a60824f4fe50e7a6190bf92e1628688dfcb38930fe87b2d53f9e14dd4de509b2216856d8d9188 +880726def069c160278b12d2258eac8fa63f729cd351a710d28b7e601c6712903c3ac1e7bbd0d21e4a15f13ca49db5aa +980699cd51bac6283959765f5174e543ed1e5f5584b5127980cbc2ef18d984ecabba45042c6773b447b8e694db066028 +aeb019cb80dc4cb4207430d0f2cd24c9888998b6f21d9bf286cc638449668d2eec0018a4cf3fe6448673cd6729335e2b +b29852f6aa6c60effdffe96ae88590c88abae732561d35cc19e82d3a51e26cb35ea00986193e07f90060756240f5346e +a0fa855adc5ba469f35800c48414b8921455950a5c0a49945d1ef6e8f2a1881f2e2dfae47de6417270a6bf49deeb091d +b6c7332e3b14813641e7272d4f69ecc7e09081df0037d6dab97ce13a9e58510f5c930d300633f208181d9205c5534001 +85a6c050f42fce560b5a8d54a11c3bbb8407abbadd859647a7b0c21c4b579ec65671098b74f10a16245dc779dff7838e +8f3eb34bb68759d53c6677de4de78a6c24dd32c8962a7fb355ed362572ef8253733e6b52bc21c9f92ecd875020a9b8de +a17dd44181e5dab4dbc128e1af93ec22624b57a448ca65d2d9e246797e4af7d079e09c6e0dfb62db3a9957ce92f098d5 +a56a1b854c3183082543a8685bb34cae1289f86cfa8123a579049dbd059e77982886bfeb61bf6e05b4b1fe4e620932e7 +aedae3033cb2fb7628cb4803435bdd7757370a86f808ae4cecb9a268ad0e875f308c048c80cbcac523de16b609683887 +9344905376aa3982b1179497fac5a1d74b14b7038fd15e3b002db4c11c8bfc7c39430db492cdaf58b9c47996c9901f28 +a3bfafdae011a19f030c749c3b071f83580dee97dd6f949e790366f95618ca9f828f1daaeabad6dcd664fcef81b6556d +81c03d8429129e7e04434dee2c529194ddb01b414feda3adee2271eb680f6c85ec872a55c9fa9d2096f517e13ed5abcc +98205ef3a72dff54c5a9c82d293c3e45d908946fa74bb749c3aabe1ab994ea93c269bcce1a266d2fe67a8f02133c5985 +85a70aeed09fda24412fadbafbbbf5ba1e00ac92885df329e147bfafa97b57629a3582115b780d8549d07d19b7867715 +b0fbe81c719f89a57d9ea3397705f898175808c5f75f8eb81c2193a0b555869ba7bd2e6bc54ee8a60cea11735e21c68c +b03a0bd160495ee626ff3a5c7d95bc79d7da7e5a96f6d10116600c8fa20bedd1132f5170f25a22371a34a2d763f2d6d0 +a90ab04091fbca9f433b885e6c1d60ab45f6f1daf4b35ec22b09909d493a6aab65ce41a6f30c98239cbca27022f61a8b +b66f92aa3bf2549f9b60b86f99a0bd19cbdd97036d4ae71ca4b83d669607f275260a497208f6476cde1931d9712c2402 +b08e1fdf20e6a9b0b4942f14fa339551c3175c1ffc5d0ab5b226b6e6a322e9eb0ba96adc5c8d59ca4259e2bdd04a7eb0 +a2812231e92c1ce74d4f5ac3ab6698520288db6a38398bb38a914ac9326519580af17ae3e27cde26607e698294022c81 +abfcbbcf1d3b9e84c02499003e490a1d5d9a2841a9e50c7babbef0b2dd20d7483371d4dc629ba07faf46db659459d296 +b0fe9f98c3da70927c23f2975a9dc4789194d81932d2ad0f3b00843dd9cbd7fb60747a1da8fe5a79f136a601becf279d +b130a6dba7645165348cb90f023713bed0eefbd90a976b313521c60a36d34f02032e69a2bdcf5361e343ed46911297ec +862f0cffe3020cea7a5fd4703353aa1eb1be335e3b712b29d079ff9f7090d1d8b12013011e1bdcbaa80c44641fd37c9f +8c6f11123b26633e1abb9ed857e0bce845b2b3df91cc7b013b2fc77b477eee445da0285fc6fc793e29d5912977f40916 +91381846126ea819d40f84d3005e9fb233dc80071d1f9bb07f102bf015f813f61e5884ffffb4f5cd333c1b1e38a05a58 +8add7d908de6e1775adbd39c29a391f06692b936518db1f8fde74eb4f533fc510673a59afb86e3a9b52ade96e3004c57 +8780e086a244a092206edcde625cafb87c9ab1f89cc3e0d378bc9ee776313836160960a82ec397bc3800c0a0ec3da283 +a6cb4cd9481e22870fdd757fae0785edf4635e7aacb18072fe8dc5876d0bab53fb99ce40964a7d3e8bcfff6f0ab1332f +af30ff47ecc5b543efba1ba4706921066ca8bb625f40e530fb668aea0551c7647a9d126e8aba282fbcce168c3e7e0130 +91b0bcf408ce3c11555dcb80c4410b5bc2386d3c05caec0b653352377efdcb6bab4827f2018671fc8e4a0e90d772acc1 +a9430b975ef138b6b2944c7baded8fe102d31da4cfe3bd3d8778bda79189c99d38176a19c848a19e2d1ee0bddd9a13c1 +aa5a4eef849d7c9d2f4b018bd01271c1dd83f771de860c4261f385d3bdcc130218495860a1de298f14b703ec32fa235f +b0ce79e7f9ae57abe4ff366146c3b9bfb38b0dee09c28c28f5981a5d234c6810ad4d582751948affb480d6ae1c8c31c4 +b75122748560f73d15c01a8907d36d06dc068e82ce22b84b322ac1f727034493572f7907dec34ebc3ddcc976f2f89ed7 +b0fc7836369a3e4411d34792d6bd5617c14f61d9bba023dda64e89dc5fb0f423244e9b48ee64869258931daa9753a56f +8956d7455ae9009d70c6e4a0bcd7610e55f37494cf9897a8f9e1b904cc8febc3fd2d642ebd09025cfff4609ad7e3bc52 +ad741efe9e472026aa49ae3d9914cb9c1a6f37a54f1a6fe6419bebd8c7d68dca105a751c7859f4389505ede40a0de786 +b52f418797d719f0d0d0ffb0846788b5cba5d0454a69a2925de4b0b80fa4dd7e8c445e5eac40afd92897ed28ca650566 +a0ab65fb9d42dd966cd93b1de01d7c822694669dd2b7a0c04d99cd0f3c3de795f387b9c92da11353412f33af5c950e9a +a0052f44a31e5741a331f7cac515a08b3325666d388880162d9a7b97598fde8b61f9ff35ff220df224eb5c4e40ef0567 +a0101cfdc94e42b2b976c0d89612a720e55d145a5ef6ef6f1f78cf6de084a49973d9b5d45915349c34ce712512191e3c +a0dd99fcf3f5cead5aaf08e82212df3a8bb543c407a4d6fab88dc5130c1769df3f147e934a46f291d6c1a55d92b86917 +a5939153f0d1931bbda5cf6bdf20562519ea55fbfa978d6dbc6828d298260c0da7a50c37c34f386e59431301a96c2232 +9568269f3f5257200f9ca44afe1174a5d3cf92950a7f553e50e279c239e156a9faaa2a67f288e3d5100b4142efe64856 +b746b0832866c23288e07f24991bbf687cad794e7b794d3d3b79367566ca617d38af586cdc8d6f4a85a34835be41d54f +a871ce28e39ab467706e32fec1669fda5a4abba2f8c209c6745df9f7a0fa36bbf1919cf14cb89ea26fa214c4c907ae03 +a08dacdd758e523cb8484f6bd070642c0c20e184abdf8e2a601f61507e93952d5b8b0c723c34fcbdd70a8485eec29db2 +85bdb78d501382bb95f1166b8d032941005661aefd17a5ac32df9a3a18e9df2fc5dc2c1f07075f9641af10353cecc0c9 +98d730c28f6fa692a389e97e368b58f4d95382fad8f0baa58e71a3d7baaea1988ead47b13742ce587456f083636fa98e +a557198c6f3d5382be9fb363feb02e2e243b0c3c61337b3f1801c4a0943f18e38ce1a1c36b5c289c8fa2aa9d58742bab +89174f79201742220ac689c403fc7b243eed4f8e3f2f8aba0bf183e6f5d4907cb55ade3e238e3623d9885f03155c4d2b +b891d600132a86709e06f3381158db300975f73ea4c1f7c100358e14e98c5fbe792a9af666b85c4e402707c3f2db321e +b9e5b2529ef1043278c939373fc0dbafe446def52ddd0a8edecd3e4b736de87e63e187df853c54c28d865de18a358bb6 +8589b2e9770340c64679062c5badb7bbef68f55476289b19511a158a9a721f197da03ece3309e059fc4468b15ac33aa3 +aad8c6cd01d785a881b446f06f1e9cd71bca74ba98674c2dcddc8af01c40aa7a6d469037498b5602e76e9c91a58d3dbd +abaccb1bd918a8465f1bf8dbe2c9ad4775c620b055550b949a399f30cf0d9eb909f3851f5b55e38f9e461e762f88f499 +ae62339d26db46e85f157c0151bd29916d5cc619bd4b832814b3fd2f00af8f38e7f0f09932ffe5bba692005dab2d9a74 +93a6ff30a5c0edf8058c89aba8c3259e0f1b1be1b80e67682de651e5346f7e1b4b4ac3d87cbaebf198cf779524aff6bf +8980a2b1d8f574af45b459193c952400b10a86122b71fca2acb75ee0dbd492e7e1ef5b959baf609a5172115e371f3177 +8c2f49f3666faee6940c75e8c7f6f8edc3f704cca7a858bbb7ee5e96bba3b0cf0993996f781ba6be3b0821ef4cb75039 +b14b9e348215b278696018330f63c38db100b0542cfc5be11dc33046e3bca6a13034c4ae40d9cef9ea8b34fef0910c4e +b59bc3d0a30d66c16e6a411cb641f348cb1135186d5f69fda8b0a0934a5a2e7f6199095ba319ec87d3fe8f1ec4a06368 +8874aca2a3767aa198e4c3fec2d9c62d496bc41ff71ce242e9e082b7f38cdf356089295f80a301a3cf1182bde5308c97 +b1820ebd61376d91232423fc20bf008b2ba37e761199f4ef0648ea2bd70282766799b4de814846d2f4d516d525c8daa7 +a6b202e5dedc16a4073e04a11af3a8509b23dfe5a1952f899adeb240e75c3f5bde0c424f811a81ea48d343591faffe46 +a69becee9c93734805523b92150a59a62eed4934f66056b645728740d42223f2925a1ad38359ba644da24d9414f4cdda +ad72f0f1305e37c7e6b48c272323ee883320994cb2e0d850905d6655fafc9f361389bcb9c66b3ff8d2051dbb58c8aa96 +b563600bd56fad7c8853af21c6a02a16ed9d8a8bbeea2c31731d63b976d83cb05b9779372d898233e8fd597a75424797 +b0abb78ce465bf7051f563c62e8be9c57a2cc997f47c82819300f36e301fefd908894bb2053a9d27ce2d0f8c46d88b5b +a071a85fb8274bac2202e0cb8e0e2028a5e138a82d6e0374d39ca1884a549c7c401312f00071b91f455c3a2afcfe0cda +b931c271513a0f267b9f41444a5650b1918100b8f1a64959c552aff4e2193cc1b9927906c6fa7b8a8c68ef13d79aaa52 +a6a1bb9c7d32cb0ca44d8b75af7e40479fbce67d216b48a2bb680d3f3a772003a49d3cd675fc64e9e0f8fabeb86d6d61 +b98d609858671543e1c3b8564162ad828808bb50ded261a9f8690ded5b665ed8368c58f947365ed6e84e5a12e27b423d +b3dca58cd69ec855e2701a1d66cad86717ff103ef862c490399c771ad28f675680f9500cb97be48de34bcdc1e4503ffd +b34867c6735d3c49865e246ddf6c3b33baf8e6f164db3406a64ebce4768cb46b0309635e11be985fee09ab7a31d81402 +acb966c554188c5b266624208f31fab250b3aa197adbdd14aee5ab27d7fb886eb4350985c553b20fdf66d5d332bfd3fe +943c36a18223d6c870d54c3b051ef08d802b85e9dd6de37a51c932f90191890656c06adfa883c87b906557ae32d09da0 +81bca7954d0b9b6c3d4528aadf83e4bc2ef9ea143d6209bc45ae9e7ae9787dbcd8333c41f12c0b6deee8dcb6805e826a +aba176b92256efb68f574e543479e5cf0376889fb48e3db4ebfb7cba91e4d9bcf19dcfec444c6622d9398f06de29e2b9 +b9f743691448053216f6ece7cd699871fff4217a1409ceb8ab7bdf3312d11696d62c74b0664ba0a631b1e0237a8a0361 +a383c2b6276fa9af346b21609326b53fb14fdf6f61676683076e80f375b603645f2051985706d0401e6fbed7eb0666b6 +a9ef2f63ec6d9beb8f3d04e36807d84bda87bdd6b351a3e4a9bf7edcb5618c46c1f58cfbf89e64b40f550915c6988447 +a141b2d7a82f5005eaea7ae7d112c6788b9b95121e5b70b7168d971812f3381de8b0082ac1f0a82c7d365922ebd2d26a +b1b76ef8120e66e1535c17038b75255a07849935d3128e3e99e56567b842fb1e8d56ef932d508d2fb18b82f7868fe1a9 +8e2e234684c81f21099f5c54f6bbe2dd01e3b172623836c77668a0c49ce1fe218786c3827e4d9ae2ea25c50a8924fb3c +a5caf5ff948bfd3c4ca3ffbdfcd91eec83214a6c6017235f309a0bbf7061d3b0b466307c00b44a1009cf575163898b43 +986415a82ca16ebb107b4c50b0c023c28714281db0bcdab589f6cb13d80e473a3034b7081b3c358e725833f6d845cb14 +b94836bf406ac2cbacb10e6df5bcdfcc9d9124ae1062767ca4e322d287fd5e353fdcebd0e52407cb3cd68571258a8900 +83c6d70a640b33087454a4788dfd9ef3ed00272da084a8d36be817296f71c086b23b576f98178ab8ca6a74f04524b46b +ad4115182ad784cfe11bcfc5ce21fd56229cc2ce77ac82746e91a2f0aa53ca6593a22efd2dc4ed8d00f84542643d9c58 +ab1434c5e5065da826d10c2a2dba0facccab0e52b506ce0ce42fbe47ced5a741797151d9ecc99dc7d6373cfa1779bbf6 +8a8b591d82358d55e6938f67ea87a89097ab5f5496f7260adb9f649abb289da12b498c5b2539c2f9614fb4e21b1f66b0 +964f355d603264bc1f44c64d6d64debca66f37dff39c971d9fc924f2bc68e6c187b48564a6dc82660a98b035f8addb5d +b66235eaaf47456bc1dc4bde454a028e2ce494ece6b713a94cd6bf27cf18c717fd0c57a5681caaa2ad73a473593cdd7a +9103e3bb74304186fa4e3e355a02da77da4aca9b7e702982fc2082af67127ebb23a455098313c88465bc9b7d26820dd5 +b6a42ff407c9dd132670cdb83cbad4b20871716e44133b59a932cd1c3f97c7ac8ff7f61acfaf8628372508d8dc8cad7c +883a9c21c16a167a4171b0f084565c13b6f28ba7c4977a0de69f0a25911f64099e7bbb4da8858f2e93068f4155d04e18 +8dbb3220abc6a43220adf0331e3903d3bfd1d5213aadfbd8dfcdf4b2864ce2e96a71f35ecfb7a07c3bbabf0372b50271 +b4ad08aee48e176bda390b7d9acf2f8d5eb008f30d20994707b757dc6a3974b2902d29cd9b4d85e032810ad25ac49e97 +865bb0f33f7636ec501bb634e5b65751c8a230ae1fa807a961a8289bbf9c7fe8c59e01fbc4c04f8d59b7f539cf79ddd5 +86a54d4c12ad1e3605b9f93d4a37082fd26e888d2329847d89afa7802e815f33f38185c5b7292293d788ad7d7da1df97 +b26c8615c5e47691c9ff3deca3021714662d236c4d8401c5d27b50152ce7e566266b9d512d14eb63e65bc1d38a16f914 +827639d5ce7db43ba40152c8a0eaad443af21dc92636cc8cc2b35f10647da7d475a1e408901cd220552fddad79db74df +a2b79a582191a85dbe22dc384c9ca3de345e69f6aa370aa6d3ff1e1c3de513e30b72df9555b15a46586bd27ea2854d9d +ae0d74644aba9a49521d3e9553813bcb9e18f0b43515e4c74366e503c52f47236be92dfbd99c7285b3248c267b1de5a0 +80fb0c116e0fd6822a04b9c25f456bdca704e2be7bdc5d141dbf5d1c5eeb0a2c4f5d80db583b03ef3e47517e4f9a1b10 +ac3a1fa3b4a2f30ea7e0a114cdc479eb51773573804c2a158d603ad9902ae8e39ffe95df09c0d871725a5d7f9ba71a57 +b56b2b0d601cba7f817fa76102c68c2e518c6f20ff693aad3ff2e07d6c4c76203753f7f91686b1801e8c4659e4d45c48 +89d50c1fc56e656fb9d3915964ebce703cb723fe411ab3c9eaa88ccc5d2b155a9b2e515363d9c600d3c0cee782c43f41 +b24207e61462f6230f3cd8ccf6828357d03e725769f7d1de35099ef9ee4dca57dbce699bb49ed994462bee17059d25ce +b886f17fcbcbfcd08ac07f04bb9543ef58510189decaccea4b4158c9174a067cb67d14b6be3c934e6e2a18c77efa9c9c +b9c050ad9cafd41c6e2e192b70d080076eed59ed38ea19a12bd92fa17b5d8947d58d5546aaf5e8e27e1d3b5481a6ce51 +aaf7a34d3267e3b1ddbc54c641e3922e89303f7c86ebebc7347ebca4cffad5b76117dac0cbae1a133053492799cd936f +a9ee604ada50adef82e29e893070649d2d4b7136cc24fa20e281ce1a07bd736bf0de7c420369676bcbcecff26fb6e900 +9855315a12a4b4cf80ab90b8bd13003223ba25206e52fd4fe6a409232fbed938f30120a3db23eab9c53f308bd8b9db81 +8cd488dd7a24f548a3cf03c54dec7ff61d0685cb0f6e5c46c2d728e3500d8c7bd6bba0156f4bf600466fda53e5b20444 +890ad4942ebac8f5b16c777701ab80c68f56fa542002b0786f8fea0fb073154369920ac3dbfc07ea598b82f4985b8ced +8de0cf9ddc84c9b92c59b9b044387597799246b30b9f4d7626fc12c51f6e423e08ee4cbfe9289984983c1f9521c3e19d +b474dfb5b5f4231d7775b3c3a8744956b3f0c7a871d835d7e4fd9cc895222c7b868d6c6ce250de568a65851151fac860 +86433b6135d9ed9b5ee8cb7a6c40e5c9d30a68774cec04988117302b8a02a11a71a1e03fd8e0264ef6611d219f103007 +80b9ed4adbe9538fb1ef69dd44ec0ec5b57cbfea820054d8d445b4261962624b4c70ac330480594bc5168184378379c3 +8b2e83562ccd23b7ad2d17f55b1ab7ef5fbef64b3a284e6725b800f3222b8bdf49937f4a873917ada9c4ddfb090938c2 +abe78cebc0f5a45d754140d1f685e387489acbfa46d297a8592aaa0d676a470654f417a4f7d666fc0b2508fab37d908e +a9c5f8ff1f8568e252b06d10e1558326db9901840e6b3c26bbd0cd5e850cb5fb3af3f117dbb0f282740276f6fd84126f +975f8dc4fb55032a5df3b42b96c8c0ffecb75456f01d4aef66f973cb7270d4eff32c71520ceefc1adcf38d77b6b80c67 +b043306ed2c3d8a5b9a056565afd8b5e354c8c4569fda66b0d797a50a3ce2c08cffbae9bbe292da69f39e89d5dc7911e +8d2afc36b1e44386ba350c14a6c1bb31ff6ea77128a0c5287584ac3584282d18516901ce402b4644a53db1ed8e7fa581 +8c294058bed53d7290325c363fe243f6ec4f4ea2343692f4bac8f0cb86f115c069ccb8334b53d2e42c067691ad110dba +b92157b926751aaf7ef82c1aa8c654907dccab6376187ee8b3e8c0c82811eae01242832de953faa13ebaff7da8698b3e +a780c4bdd9e4ba57254b09d745075cecab87feda78c88ffee489625c5a3cf96aa6b3c9503a374a37927d9b78de9bd22b +811f548ef3a2e6a654f7dcb28ac9378de9515ed61e5a428515d9594a83e80b35c60f96a5cf743e6fab0d3cb526149f49 +85a4dccf6d90ee8e094731eec53bd00b3887aec6bd81a0740efddf812fd35e3e4fe4f983afb49a8588691c202dabf942 +b152c2da6f2e01c8913079ae2b40a09b1f361a80f5408a0237a8131b429677c3157295e11b365b1b1841924b9efb922e +849b9efee8742502ffd981c4517c88ed33e4dd518a330802caff168abae3cd09956a5ee5eda15900243bc2e829016b74 +955a933f3c18ec0f1c0e38fa931e4427a5372c46a3906ebe95082bcf878c35246523c23f0266644ace1fa590ffa6d119 +911989e9f43e580c886656377c6f856cdd4ff1bd001b6db3bbd86e590a821d34a5c6688a29b8d90f28680e9fdf03ba69 +b73b8b4f1fd6049fb68d47cd96a18fcba3f716e0a1061aa5a2596302795354e0c39dea04d91d232aec86b0bf2ba10522 +90f87456d9156e6a1f029a833bf3c7dbed98ca2f2f147a8564922c25ae197a55f7ea9b2ee1f81bf7383197c4bad2e20c +903cba8b1e088574cb04a05ca1899ab00d8960580c884bd3c8a4c98d680c2ad11410f2b75739d6050f91d7208cac33a5 +9329987d42529c261bd15ecedd360be0ea8966e7838f32896522c965adfc4febf187db392bd441fb43bbd10c38fdf68b +8178ee93acf5353baa349285067b20e9bb41aa32d77b5aeb7384fe5220c1fe64a2461bd7a83142694fe673e8bbf61b7c +a06a8e53abcff271b1394bcc647440f81fb1c1a5f29c27a226e08f961c3353f4891620f2d59b9d1902bf2f5cc07a4553 +aaf5fe493b337810889e777980e6bbea6cac39ac66bc0875c680c4208807ac866e9fda9b5952aa1d04539b9f4a4bec57 +aa058abb1953eceac14ccfa7c0cc482a146e1232905dcecc86dd27f75575285f06bbae16a8c9fe8e35d8713717f5f19f +8f15dd732799c879ca46d2763453b359ff483ca33adb1d0e0a57262352e0476c235987dc3a8a243c74bc768f93d3014c +a61cc8263e9bc03cce985f1663b8a72928a607121005a301b28a278e9654727fd1b22bc8a949af73929c56d9d3d4a273 +98d6dc78502d19eb9f921225475a6ebcc7b44f01a2df6f55ccf6908d65b27af1891be2a37735f0315b6e0f1576c1f8d8 +8bd258b883f3b3793ec5be9472ad1ff3dc4b51bc5a58e9f944acfb927349ead8231a523cc2175c1f98e7e1e2b9f363b8 +aeacc2ecb6e807ad09bedd99654b097a6f39840e932873ace02eabd64ccfbb475abdcb62939a698abf17572d2034c51e +b8ccf78c08ccd8df59fd6eda2e01de328bc6d8a65824d6f1fc0537654e9bc6bf6f89c422dd3a295cce628749da85c864 +8f91fd8cb253ba2e71cc6f13da5e05f62c2c3b485c24f5d68397d04665673167fce1fc1aec6085c69e87e66ec555d3fd +a254baa10cb26d04136886073bb4c159af8a8532e3fd36b1e9c3a2e41b5b2b6a86c4ebc14dbe624ee07b7ccdaf59f9ab +94e3286fe5cd68c4c7b9a7d33ae3d714a7f265cf77cd0e9bc19fc51015b1d1c34ad7e3a5221c459e89f5a043ee84e3a9 +a279da8878af8d449a9539bec4b17cea94f0242911f66fab275b5143ab040825f78c89cb32a793930609415cfa3a1078 +ac846ceb89c9e5d43a2991c8443079dc32298cd63e370e64149cec98cf48a6351c09c856f2632fd2f2b3d685a18bbf8b +a847b27995c8a2e2454aaeb983879fb5d3a23105c33175839f7300b7e1e8ec3efd6450e9fa3f10323609dee7b98c6fd5 +a2f432d147d904d185ff4b2de8c6b82fbea278a2956bc406855b44c18041854c4f0ecccd472d1d0dff1d8aa8e281cb1d +94a48ad40326f95bd63dff4755f863a1b79e1df771a1173b17937f9baba57b39e651e7695be9f66a472f098b339364fc +a12a0ccd8f96e96e1bc6494341f7ebce959899341b3a084aa1aa87d1c0d489ac908552b7770b887bb47e7b8cbc3d8e66 +81a1f1681bda923bd274bfe0fbb9181d6d164fe738e54e25e8d4849193d311e2c4253614ed673c98af2c798f19a93468 +abf71106a05d501e84cc54610d349d7d5eae21a70bd0250f1bebbf412a130414d1c8dbe673ffdb80208fd72f1defa4d4 +96266dc2e0df18d8136d79f5b59e489978eee0e6b04926687fe389d4293c14f36f055c550657a8e27be4118b64254901 +8df5dcbefbfb4810ae3a413ca6b4bf08619ca53cd50eb1dde2a1c035efffc7b7ac7dff18d403253fd80104bd83dc029e +9610b87ff02e391a43324a7122736876d5b3af2a137d749c52f75d07b17f19900b151b7f439d564f4529e77aa057ad12 +a90a5572198b40fe2fcf47c422274ff36c9624df7db7a89c0eb47eb48a73a03c985f4ac5016161c76ca317f64339bce1 +98e5e61a6ab6462ba692124dba7794b6c6bde4249ab4fcc98c9edd631592d5bc2fb5e38466691a0970a38e48d87c2e43 +918cefb8f292f78d4db81462c633daf73b395e772f47b3a7d2cea598025b1d8c3ec0cbff46cdb23597e74929981cde40 +a98918a5dc7cf610fe55f725e4fd24ce581d594cb957bb9b4e888672e9c0137003e1041f83e3f1d7b9caab06462c87d4 +b92b74ac015262ca66c33f2d950221e19d940ba3bf4cf17845f961dc1729ae227aa9e1f2017829f2135b489064565c29 +a053ee339f359665feb178b4e7ee30a85df37debd17cacc5a27d6b3369d170b0114e67ad1712ed26d828f1df641bcd99 +8c3c8bad510b35da5ce5bd84b35c958797fbea024ad1c97091d2ff71d9b962e9222f65a9b776e5b3cc29c36e1063d2ee +af99dc7330fe7c37e850283eb47cc3257888e7c197cb0d102edf94439e1e02267b6a56306d246c326c4c79f9dc8c6986 +afecb2dc34d57a725efbd7eb93d61eb29dbe8409b668ab9ea040791f5b796d9be6d4fc10d7f627bf693452f330cf0435 +93334fedf19a3727a81a6b6f2459db859186227b96fe7a391263f69f1a0884e4235de64d29edebc7b99c44d19e7c7d7a +89579c51ac405ad7e9df13c904061670ce4b38372492764170e4d3d667ed52e5d15c7cd5c5991bbfa3a5e4e3fa16363e +9778f3e8639030f7ef1c344014f124e375acb8045bd13d8e97a92c5265c52de9d1ffebaa5bc3e1ad2719da0083222991 +88f77f34ee92b3d36791bdf3326532524a67d544297dcf1a47ff00b47c1b8219ff11e34034eab7d23b507caa2fd3c6b9 +a699c1e654e7c484431d81d90657892efeb4adcf72c43618e71ca7bd7c7a7ebbb1db7e06e75b75dc4c74efd306b5df3f +81d13153baebb2ef672b5bdb069d3cd669ce0be96b742c94e04038f689ff92a61376341366b286eee6bf3ae85156f694 +81efb17de94400fdacc1deec2550cbe3eecb27c7af99d8207e2f9be397e26be24a40446d2a09536bb5172c28959318d9 +989b21ebe9ceab02488992673dc071d4d5edec24bff0e17a4306c8cb4b3c83df53a2063d1827edd8ed16d6e837f0d222 +8d6005d6536825661b13c5fdce177cb37c04e8b109b7eb2b6d82ea1cb70efecf6a0022b64f84d753d165edc2bba784a3 +a32607360a71d5e34af2271211652d73d7756d393161f4cf0da000c2d66a84c6826e09e759bd787d4fd0305e2439d342 +aaad8d6f6e260db45d51b2da723be6fa832e76f5fbcb77a9a31e7f090dd38446d3b631b96230d78208cae408c288ac4e +abcfe425255fd3c5cffd3a818af7650190c957b6b07b632443f9e33e970a8a4c3bf79ac9b71f4d45f238a04d1c049857 +aeabf026d4c783adc4414b5923dbd0be4b039cc7201219f7260d321f55e9a5b166d7b5875af6129c034d0108fdc5d666 +af49e740c752d7b6f17048014851f437ffd17413c59797e5078eaaa36f73f0017c3e7da020310cfe7d3c85f94a99f203 +8854ca600d842566e3090040cd66bb0b3c46dae6962a13946f0024c4a8aca447e2ccf6f240045f1ceee799a88cb9210c +b6c03b93b1ab1b88ded8edfa1b487a1ed8bdce8535244dddb558ffb78f89b1c74058f80f4db2320ad060d0c2a9c351cc +b5bd7d17372faff4898a7517009b61a7c8f6f0e7ed4192c555db264618e3f6e57fb30a472d169fea01bf2bf0362a19a8 +96eb1d38319dc74afe7e7eb076fcd230d19983f645abd14a71e6103545c01301b31c47ae931e025f3ecc01fb3d2f31fa +b55a8d30d4403067def9b65e16f867299f8f64c9b391d0846d4780bc196569622e7e5b64ce799b5aefac8f965b2a7a7b +8356d199a991e5cbbff608752b6291731b6b6771aed292f8948b1f41c6543e4ab1bedc82dd26d10206c907c03508df06 +97f4137445c2d98b0d1d478049de952610ad698c91c9d0f0e7227d2aae690e9935e914ec4a2ea1fbf3fc1dddfeeacebb +af5621707e0938320b15ddfc87584ab325fbdfd85c30efea36f8f9bd0707d7ec12c344eff3ec21761189518d192df035 +8ac7817e71ea0825b292687928e349da7140285d035e1e1abff0c3704fa8453faaae343a441b7143a74ec56539687cc4 +8a5e0a9e4758449489df10f3386029ada828d1762e4fb0a8ffe6b79e5b6d5d713cb64ed95960e126398b0cdb89002bc9 +81324be4a71208bbb9bca74b77177f8f1abb9d3d5d9db195d1854651f2cf333cd618d35400da0f060f3e1b025124e4b2 +849971d9d095ae067525b3cbc4a7dfae81f739537ade6d6cec1b42fb692d923176197a8770907c58069754b8882822d6 +89f830825416802477cc81fdf11084885865ee6607aa15aa4eb28e351c569c49b8a1b9b5e95ddc04fa0ebafe20071313 +9240aeeaff37a91af55f860b9badd466e8243af9e8c96a7aa8cf348cd270685ab6301bc135b246dca9eda696f8b0e350 +acf74db78cc33138273127599eba35b0fb4e7b9a69fe02dae18fc6692d748ca332bd00b22afa8e654ed587aab11833f3 +b091e6d37b157b50d76bd297ad752220cd5c9390fac16dc838f8557aed6d9833fc920b61519df21265406216315e883f +a6446c429ebf1c7793c622250e23594c836b2fbcaf6c5b3d0995e1595a37f50ea643f3e549b0be8bbdadd69044d72ab9 +93e675353bd60e996bf1c914d5267eeaa8a52fc3077987ccc796710ef9becc6b7a00e3d82671a6bdfb8145ee3c80245a +a2f731e43251d04ed3364aa2f072d05355f299626f2d71a8a38b6f76cf08c544133f7d72dd0ab4162814b674b9fc7fa6 +97a8b791a5a8f6e1d0de192d78615d73d0c38f1e557e4e15d15adc663d649e655bc8da3bcc499ef70112eafe7fb45c7a +98cd624cbbd6c53a94469be4643c13130916b91143425bcb7d7028adbbfede38eff7a21092af43b12d4fab703c116359 +995783ce38fd5f6f9433027f122d4cf1e1ff3caf2d196ce591877f4a544ce9113ead60de2de1827eaff4dd31a20d79a8 +8cf251d6f5229183b7f3fe2f607a90b4e4b6f020fb4ba2459d28eb8872426e7be8761a93d5413640a661d73e34a5b81f +b9232d99620652a3aa7880cad0876f153ff881c4ed4c0c2e7b4ea81d5d42b70daf1a56b869d752c3743c6d4c947e6641 +849716f938f9d37250cccb1bf77f5f9fde53096cdfc6f2a25536a6187029a8f1331cdbed08909184b201f8d9f04b792f +80c7c4de098cbf9c6d17b14eba1805e433b5bc905f6096f8f63d34b94734f2e4ebf4bce8a177efd1186842a61204a062 +b790f410cf06b9b8daadceeb4fd5ff40a2deda820c8df2537e0a7554613ae3948e149504e3e79aa84889df50c8678eeb +813aab8bd000299cd37485b73cd7cba06e205f8efb87f1efc0bae8b70f6db2bc7702eb39510ad734854fb65515fe9d0f +94f0ab7388ac71cdb67f6b85dfd5945748afb2e5abb622f0b5ad104be1d4d0062b651f134ba22385c9e32c2dfdcccce1 +ab6223dca8bd6a4f969e21ccd9f8106fc5251d321f9e90cc42cea2424b3a9c4e5060a47eeef6b23c7976109b548498e8 +859c56b71343fce4d5c5b87814c47bf55d581c50fd1871a17e77b5e1742f5af639d0e94d19d909ec7dfe27919e954e0c +aae0d632b6191b8ad71b027791735f1578e1b89890b6c22e37de0e4a6074886126988fe8319ae228ac9ef3b3bcccb730 +8ca9f32a27a024c3d595ecfaf96b0461de57befa3b331ab71dc110ec3be5824fed783d9516597537683e77a11d334338 +a061df379fb3f4b24816c9f6cd8a94ecb89b4c6dc6cd81e4b8096fa9784b7f97ab3540259d1de9c02eb91d9945af4823 +998603102ac63001d63eb7347a4bb2bf4cf33b28079bb48a169076a65c20d511ccd3ef696d159e54cc8e772fb5d65d50 +94444d96d39450872ac69e44088c252c71f46be8333a608a475147752dbb99db0e36acfc5198f158509401959c12b709 +ac1b51b6c09fe055c1d7c9176eea9adc33f710818c83a1fbfa073c8dc3a7eb3513cbdd3f5960b7845e31e3e83181e6ba +803d530523fc9e1e0f11040d2412d02baef3f07eeb9b177fa9bfa396af42eea898a4276d56e1db998dc96ae47b644cb2 +85a3c9fc7638f5bf2c3e15ba8c2fa1ae87eb1ceb44c6598c67a2948667a9dfa41e61f66d535b4e7fda62f013a5a8b885 +a961cf5654c46a1a22c29baf7a4e77837a26b7f138f410e9d1883480ed5fa42411d522aba32040b577046c11f007388e +ad1154142344f494e3061ef45a34fab1aaacf5fdf7d1b26adbb5fbc3d795655fa743444e39d9a4119b4a4f82a6f30441 +b1d6c30771130c77806e7ab893b73d4deb590b2ff8f2f8b5e54c2040c1f3e060e2bd99afc668cf706a2df666a508bbf6 +a00361fd440f9decabd98d96c575cd251dc94c60611025095d1201ef2dedde51cb4de7c2ece47732e5ed9b3526c2012c +a85c5ab4d17d328bda5e6d839a9a6adcc92ff844ec25f84981e4f44a0e8419247c081530f8d9aa629c7eb4ca21affba6 +a4ddd3eab4527a2672cf9463db38bc29f61460e2a162f426b7852b7a7645fbd62084fd39a8e4d60e1958cce436dd8f57 +811648140080fe55b8618f4cf17f3c5a250adb0cd53d885f2ddba835d2b4433188e41fc0661faac88e4ff910b16278c0 +b85c7f1cfb0ed29addccf7546023a79249e8f15ac2d14a20accbfef4dd9dc11355d599815fa09d2b6b4e966e6ea8cff1 +a10b5d8c260b159043b020d5dd62b3467df2671afea6d480ca9087b7e60ed170c82b121819d088315902842d66c8fb45 +917e191df1bcf3f5715419c1e2191da6b8680543b1ba41fe84ed07ef570376e072c081beb67b375fca3565a2565bcabb +881fd967407390bfd7badc9ab494e8a287559a01eb07861f527207c127eadea626e9bcc5aa9cca2c5112fbac3b3f0e9c +959fd71149af82cc733619e0e5bf71760ca2650448c82984b3db74030d0e10f8ab1ce1609a6de6f470fe8b5bd90df5b3 +a3370898a1c5f33d15adb4238df9a6c945f18b9ada4ce2624fc32a844f9ece4c916a64e9442225b6592afa06d2e015f2 +817efb8a791435e4236f7d7b278181a5fa34587578c629dbc14fbf9a5c26772290611395eecd20222a4c58649fc256d8 +a04c9876acf2cfdc8ef96de4879742709270fa1d03fe4c8511fbef2d59eb0aaf0336fa2c7dfe41a651157377fa217813 +81e15875d7ea7f123e418edf14099f2e109d4f3a6ce0eb65f67fe9fb10d2f809a864a29f60ad3fc949f89e2596b21783 +b49f529975c09e436e6bc202fdc16e3fdcbe056db45178016ad6fdece9faad4446343e83aed096209690b21a6910724f +879e8eda589e1a279f7f49f6dd0580788c040d973748ec4942dbe51ea8fbd05983cc919b78f0c6b92ef3292ae29db875 +81a2b74b2118923f34139a102f3d95e7eee11c4c2929c2576dee200a5abfd364606158535a6c9e4178a6a83dbb65f3c4 +8913f281d8927f2b45fc815d0f7104631cb7f5f7278a316f1327d670d15868daadd2a64e3eb98e1f53fe7e300338cc80 +a6f815fba7ef9af7fbf45f93bc952e8b351f5de6568a27c7c47a00cb39a254c6b31753794f67940fc7d2e9cc581529f4 +b3722a15c66a0014ce4d082de118def8d39190c15678a472b846225585f3a83756ae1b255b2e3f86a26168878e4773b2 +817ae61ab3d0dd5b6e24846b5a5364b1a7dc2e77432d9fed587727520ae2f307264ea0948c91ad29f0aea3a11ff38624 +b3db467464415fcad36dc1de2d6ba7686772a577cc2619242ac040d6734881a45d3b40ed4588db124e4289cfeec4bbf6 +ad66a14f5a54ac69603b16e5f1529851183da77d3cc60867f10aea41339dd5e06a5257982e9e90a352cdd32750f42ee4 +adafa3681ef45d685555601a25a55cf23358319a17f61e2179e704f63df83a73bdd298d12cf6cef86db89bd17119e11d +a379dc44cb6dd3b9d378c07b2ec654fec7ca2f272de6ba895e3d00d20c9e4c5550498a843c8ac67e4221db2115bedc1c +b7bf81c267a78efc6b9e5a904574445a6487678d7ef70054e3e93ea6a23f966c2b68787f9164918e3b16d2175459ed92 +b41d66a13a4afafd5760062b77f79de7e6ab8ccacde9c6c5116a6d886912fb491dc027af435b1b44aacc6af7b3c887f2 +9904d23a7c1c1d2e4bab85d69f283eb0a8e26d46e8b7b30224438015c936729b2f0af7c7c54c03509bb0500acb42d8a4 +ae30d65e9e20c3bfd603994ae2b175ff691d51f3e24b2d058b3b8556d12ca4c75087809062dddd4aaac81c94d15d8a17 +9245162fab42ac01527424f6013310c3eb462982518debef6c127f46ba8a06c705d7dc9f0a41e796ba8d35d60ae6cc64 +87fab853638d7a29a20f3ba2b1a7919d023e9415bfa78ebb27973d8cbc7626f584dc5665d2e7ad71f1d760eba9700d88 +85aac46ecd330608e5272430970e6081ff02a571e8ea444f1e11785ea798769634a22a142d0237f67b75369d3c484a8a +938c85ab14894cc5dfce3d80456f189a2e98eddbc8828f4ff6b1df1dcb7b42b17ca2ff40226a8a1390a95d63dca698dd +a18ce1f846e3e3c4d846822f60271eecf0f5d7d9f986385ac53c5ace9589dc7c0188910448c19b91341a1ef556652fa9 +8611608a9d844f0e9d7584ad6ccf62a5087a64f764caf108db648a776b5390feb51e5120f0ef0e9e11301af3987dd7dc +8106333ba4b4de8d1ae43bc9735d3fea047392e88efd6a2fa6f7b924a18a7a265ca6123c3edc0f36307dd7fb7fe89257 +a91426fa500951ff1b051a248c050b7139ca30dde8768690432d597d2b3c4357b11a577be6b455a1c5d145264dcf81fc +b7f9f90e0e450f37b081297f7f651bad0496a8b9afd2a4cf4120a2671aaaa8536dce1af301258bfbfdb122afa44c5048 +84126da6435699b0c09fa4032dec73d1fca21d2d19f5214e8b0bea43267e9a8dd1fc44f8132d8315e734c8e2e04d7291 +aff064708103884cb4f1a3c1718b3fc40a238d35cf0a7dc24bdf9823693b407c70da50df585bf5bc4e9c07d1c2d203e8 +a8b40fc6533752983a5329c31d376c7a5c13ce6879cc7faee648200075d9cd273537001fb4c86e8576350eaac6ba60c2 +a02db682bdc117a84dcb9312eb28fcbde12d49f4ce915cc92c610bb6965ec3cc38290f8c5b5ec70afe153956692cda95 +86decd22b25d300508472c9ce75d3e465b737e7ce13bc0fcce32835e54646fe12322ba5bc457be18bfd926a1a6ca4a38 +a18666ef65b8c2904fd598791f5627207165315a85ee01d5fb0e6b2e10bdd9b00babc447da5bd63445e3337de33b9b89 +89bb0c06effadefdaf34ffe4b123e1678a90d4451ee856c863df1e752eef41fd984689ded8f0f878bf8916d5dd8e8024 +97cfcba08ebec05d0073992a66b1d7d6fb9d95871f2cdc36db301f78bf8069294d1c259efef5c93d20dc937eedae3a1a +ac2643b14ece79dcb2e289c96776a47e2bebd40dd6dc74fd035df5bb727b5596f40e3dd2d2202141e69b0993717ede09 +a5e6fd88a2f9174d9bd4c6a55d9c30974be414992f22aa852f552c7648f722ed8077acf5aba030abd47939bb451b2c60 +8ad40a612824a7994487731a40b311b7349038c841145865539c6ada75c56de6ac547a1c23df190e0caaafecddd80ccc +953a7cea1d857e09202c438c6108060961f195f88c32f0e012236d7a4b39d840c61b162ec86436e8c38567328bea0246 +80d8b47a46dae1868a7b8ccfe7029445bbe1009dad4a6c31f9ef081be32e8e1ac1178c3c8fb68d3e536c84990cc035b1 +81ecd99f22b3766ce0aca08a0a9191793f68c754fdec78b82a4c3bdc2db122bbb9ebfd02fc2dcc6e1567a7d42d0cc16a +b1dd0446bccc25846fb95d08c1c9cc52fb51c72c4c5d169ffde56ecfe800f108dc1106d65d5c5bd1087c656de3940b63 +b87547f0931e164e96de5c550ca5aa81273648fe34f6e193cd9d69cf729cb432e17aa02e25b1c27a8a0d20a3b795e94e +820a94e69a927e077082aae66f6b292cfbe4589d932edf9e68e268c9bd3d71ef76cf7d169dd445b93967c25db11f58f1 +b0d07ddf2595270c39adfa0c8cf2ab1322979b0546aa4d918f641be53cd97f36c879bb75d205e457c011aca3bbd9f731 +8700b876b35b4b10a8a9372c5230acecd39539c1bb87515640293ad4464a9e02929d7d6a6a11112e8a29564815ac0de4 +a61a601c5bb27dcb97e37c8e2b9ce479c6b192a5e04d9ed5e065833c5a1017ee5f237b77d1a17be5d48f8e7cc0bcacf6 +92fb88fe774c1ba1d4a08cae3c0e05467ad610e7a3f1d2423fd47751759235fe0a3036db4095bd6404716aa03820f484 +b274f140d77a3ce0796f5e09094b516537ccaf27ae1907099bff172e6368ba85e7c3ef8ea2a07457cac48ae334da95b3 +b2292d9181f16581a9a9142490b2bdcdfb218ca6315d1effc8592100d792eb89d5356996c890441f04f2b4a95763503e +8897e73f576d86bc354baa3bd96e553107c48cf5889dcc23c5ba68ab8bcd4e81f27767be2233fdfa13d39f885087e668 +a29eac6f0829791c728d71abc49569df95a4446ecbfc534b39f24f56c88fe70301838dfc1c19751e7f3c5c1b8c6af6a0 +9346dc3720adc5df500a8df27fd9c75ef38dc5c8f4e8ed66983304750e66d502c3c59b8e955be781b670a0afc70a2167 +9566d534e0e30a5c5f1428665590617e95fd05d45f573715f58157854ad596ece3a3cfec61356aee342308d623e029d5 +a464fb8bffe6bd65f71938c1715c6e296cc6d0311a83858e4e7eb5873b7f2cf0c584d2101e3407b85b64ca78b2ac93ce +b54088f7217987c87e9498a747569ac5b2f8afd5348f9c45bf3fd9fbf713a20f495f49c8572d087efe778ac7313ad6d3 +91fa9f5f8000fe050f5b224d90b59fcce13c77e903cbf98ded752e5b3db16adb2bc1f8c94be48b69f65f1f1ad81d6264 +92d04a5b0ac5d8c8e313709b432c9434ecd3e73231f01e9b4e7952b87df60cbfa97b5dedd2200bd033b4b9ea8ba45cc1 +a94b90ad3c3d6c4bbe169f8661a790c40645b40f0a9d1c7220f01cf7fc176e04d80bab0ced9323fcafb93643f12b2760 +94d86149b9c8443b46196f7e5a3738206dd6f3be7762df488bcbb9f9ee285a64c997ed875b7b16b26604fa59020a8199 +82efe4ae2c50a2d7645240c173a047f238536598c04a2c0b69c96e96bd18e075a99110f1206bc213f39edca42ba00cc1 +ab8667685f831bc14d4610f84a5da27b4ea5b133b4d991741a9e64dceb22cb64a3ce8f1b6e101d52af6296df7127c9ad +83ba433661c05dcc5d562f4a9a261c8110dac44b8d833ae1514b1fc60d8b4ee395b18804baea04cb10adb428faf713c3 +b5748f6f660cc5277f1211d2b8649493ed8a11085b871cd33a5aea630abd960a740f08c08be5f9c21574600ac9bf5737 +a5c8dd12af48fb710642ad65ebb97ca489e8206741807f7acfc334f8035d3c80593b1ff2090c9bb7bd138f0c48714ca8 +a2b382fd5744e3babf454b1d806cc8783efeb4761bc42b6914ea48a46a2eae835efbe0a18262b6bc034379e03cf1262b +b3145ffaf603f69f15a64936d32e3219eea5ed49fdfd2f5bf40ea0dfd974b36fb6ff12164d4c2282d892db4cf3ff3ce1 +87a316fb213f4c5e30c5e3face049db66be4f28821bd96034714ec23d3e97849d7b301930f90a4323c7ccf53de23050c +b9de09a919455070fed6220fc179c8b7a4c753062bcd27acf28f5b9947a659c0b364298daf7c85c4ca6fca7f945add1f +806fbd98d411b76979464c40ad88bc07a151628a27fcc1012ba1dfbaf5b5cc9d962fb9b3386008978a12515edce934bc +a15268877fae0d21610ae6a31061ed7c20814723385955fac09fdc9693a94c33dea11db98bb89fdfe68f933490f5c381 +8d633fb0c4da86b2e0b37d8fad5972d62bff2ac663c5ec815d095cd4b7e1fe66ebef2a2590995b57eaf941983c7ad7a4 +8139e5dd9cf405e8ef65f11164f0440827d98389ce1b418b0c9628be983a9ddd6cf4863036ccb1483b40b8a527acd9ed +88b15fa94a08eac291d2b94a2b30eb851ff24addf2cc30b678e72e32cfcb3424cf4b33aa395d741803f3e578ddf524de +b5eaf0c8506e101f1646bcf049ee38d99ea1c60169730da893fd6020fd00a289eb2f415947e44677af49e43454a7b1be +8489822ad0647a7e06aa2aa5595960811858ddd4542acca419dd2308a8c5477648f4dd969a6740bb78aa26db9bfcc555 +b1e9a7b9f3423c220330d45f69e45fa03d7671897cf077f913c252e3e99c7b1b1cf6d30caad65e4228d5d7b80eb86e5e +b28fe9629592b9e6a55a1406903be76250b1c50c65296c10c5e48c64b539fb08fe11f68cf462a6edcbba71b0cee3feb2 +a41acf96a02c96cd8744ff6577c244fc923810d17ade133587e4c223beb7b4d99fa56eae311a500d7151979267d0895c +880798938fe4ba70721be90e666dfb62fcab4f3556fdb7b0dc8ec5bc34f6b4513df965eae78527136eb391889fe2caf9 +98d4d89d358e0fb7e212498c73447d94a83c1b66e98fc81427ab13acddb17a20f52308983f3a5a8e0aaacec432359604 +81430b6d2998fc78ba937a1639c6020199c52da499f68109da227882dc26d005b73d54c5bdcac1a04e8356a8ca0f7017 +a8d906a4786455eb74613aba4ce1c963c60095ffb8658d368df9266fdd01e30269ce10bf984e7465f34b4fd83beba26a +af54167ac1f954d10131d44a8e0045df00d581dd9e93596a28d157543fbe5fb25d213806ed7fb3cba6b8f5b5423562db +8511e373a978a12d81266b9afbd55035d7bc736835cfa921903a92969eeba3624437d1346b55382e61415726ab84a448 +8cf43eea93508ae586fa9a0f1354a1e16af659782479c2040874a46317f9e8d572a23238efa318fdfb87cc63932602b7 +b0bdd3bacff077173d302e3a9678d1d37936188c7ecc34950185af6b462b7c679815176f3cce5db19aac8b282f2d60ad +a355e9b87f2f2672052f5d4d65b8c1c827d24d89b0d8594641fccfb69aef1b94009105f3242058bb31c8bf51caae5a41 +b8baa9e4b950b72ff6b88a6509e8ed1304bc6fd955748b2e59a523a1e0c5e99f52aec3da7fa9ff407a7adf259652466c +840bc3dbb300ea6f27d1d6dd861f15680bd098be5174f45d6b75b094d0635aced539fa03ddbccb453879de77fb5d1fe9 +b4bc7e7e30686303856472bae07e581a0c0bfc815657c479f9f5931cff208d5c12930d2fd1ff413ebd8424bcd7a9b571 +89b5d514155d7999408334a50822508b9d689add55d44a240ff2bdde2eee419d117031f85e924e2a2c1ca77db9b91eea +a8604b6196f87a04e1350302e8aa745bba8dc162115d22657b37a1d1a98cb14876ddf7f65840b5dbd77e80cd22b4256c +83cb7acdb9e03247515bb2ce0227486ccf803426717a14510f0d59d45e998b245797d356f10abca94f7a14e1a2f0d552 +aeb3266a9f16649210ab2df0e1908ac259f34ce1f01162c22b56cf1019096ee4ea5854c36e30bb2feb06c21a71e8a45c +89e72e86edf2aa032a0fc9acf4d876a40865fbb2c8f87cb7e4d88856295c4ac14583e874142fd0c314a49aba68c0aa3c +8c3576eba0583c2a7884976b4ed11fe1fda4f6c32f6385d96c47b0e776afa287503b397fa516a455b4b8c3afeedc76db +a31e5b633bda9ffa174654fee98b5d5930a691c3c42fcf55673d927dbc8d91c58c4e42e615353145431baa646e8bbb30 +89f2f3f7a8da1544f24682f41c68114a8f78c86bd36b066e27da13acb70f18d9f548773a16bd8e24789420e17183f137 +ada27fa4e90a086240c9164544d2528621a415a5497badb79f8019dc3dce4d12eb6b599597e47ec6ac39c81efda43520 +90dc1eb21bf21c0187f359566fc4bf5386abea52799306a0e5a1151c0817c5f5bc60c86e76b1929c092c0f3ff48cedd2 +b702a53ebcc17ae35d2e735a347d2c700e9cbef8eadbece33cac83df483b2054c126593e1f462cfc00a3ce9d737e2af5 +9891b06455ec925a6f8eafffba05af6a38cc5e193acaaf74ffbf199df912c5197106c5e06d72942bbb032ce277b6417f +8c0ee71eb01197b019275bcf96cae94e81d2cdc3115dbf2d8e3080074260318bc9303597e8f72b18f965ad601d31ec43 +8aaf580aaf75c1b7a5f99ccf60503506e62058ef43b28b02f79b8536a96be3f019c9f71caf327b4e6730134730d1bef5 +ae6f9fc21dd7dfa672b25a87eb0a41644f7609fab5026d5cedb6e43a06dbbfd6d6e30322a2598c8dedde88c52eaed626 +8159b953ffece5693edadb2e906ebf76ff080ee1ad22698950d2d3bfc36ac5ea78f58284b2ca180664452d55bd54716c +ab7647c32ca5e9856ac283a2f86768d68de75ceeba9e58b74c5324f8298319e52183739aba4340be901699d66ac9eb3f +a4d85a5701d89bcfaf1572db83258d86a1a0717603d6f24ac2963ffcf80f1265e5ab376a4529ca504f4396498791253c +816080c0cdbfe61b4d726c305747a9eb58ac26d9a35f501dd32ba43c098082d20faf3ccd41aad24600aa73bfa453dfac +84f3afac024f576b0fd9acc6f2349c2fcefc3f77dbe5a2d4964d14b861b88e9b1810334b908cf3427d9b67a8aee74b18 +94b390655557b1a09110018e9b5a14490681ade275bdc83510b6465a1218465260d9a7e2a6e4ec700f58c31dc3659962 +a8c66826b1c04a2dd4c682543242e7a57acae37278bd09888a3d17747c5b5fec43548101e6f46d703638337e2fd3277b +86e6f4608a00007fa533c36a5b054c5768ccafe41ad52521d772dcae4c8a4bcaff8f7609be30d8fab62c5988cbbb6830 +837da4cf09ae8aa0bceb16f8b3bfcc3b3367aecac9eed6b4b56d7b65f55981ef066490764fb4c108792623ecf8cad383 +941ff3011462f9b5bf97d8cbdb0b6f5d37a1b1295b622f5485b7d69f2cb2bcabc83630dae427f0259d0d9539a77d8424 +b99e5d6d82aa9cf7d5970e7f710f4039ac32c2077530e4c2779250c6b9b373bc380adb0a03b892b652f649720672fc8c +a791c78464b2d65a15440b699e1e30ebd08501d6f2720adbc8255d989a82fcded2f79819b5f8f201bed84a255211b141 +84af7ad4a0e31fcbb3276ab1ad6171429cf39adcf78dc03750dc5deaa46536d15591e26d53e953dfb31e1622bc0743ab +a833e62fe97e1086fae1d4917fbaf09c345feb6bf1975b5cb863d8b66e8d621c7989ab3dbecda36bc9eaffc5eaa6fa66 +b4ef79a46a2126f53e2ebe62770feb57fd94600be29459d70a77c5e9cc260fa892be06cd60f886bf48459e48eb50d063 +b43b8f61919ea380bf151c294e54d3a3ff98e20d1ee5efbfe38aa2b66fafbc6a49739793bd5cb1c809f8b30466277c3a +ab37735af2412d2550e62df9d8b3b5e6f467f20de3890bf56faf1abf2bf3bd1d98dc3fa0ad5e7ab3fce0fa20409eb392 +82416b74b1551d484250d85bb151fabb67e29cce93d516125533df585bc80779ab057ea6992801a3d7d5c6dcff87a018 +8145d0787f0e3b5325190ae10c1d6bee713e6765fb6a0e9214132c6f78f4582bb2771aaeae40d3dad4bafb56bf7e36d8 +b6935886349ecbdd5774e12196f4275c97ec8279fdf28ccf940f6a022ebb6de8e97d6d2173c3fe402cbe9643bed3883b +87ef9b4d3dc71ac86369f8ed17e0dd3b91d16d14ae694bc21a35b5ae37211b043d0e36d8ff07dcc513fb9e6481a1f37f +ae1d0ded32f7e6f1dc8fef495879c1d9e01826f449f903c1e5034aeeabc5479a9e323b162b688317d46d35a42d570d86 +a40d16497004db4104c6794e2f4428d75bdf70352685944f3fbe17526df333e46a4ca6de55a4a48c02ecf0bde8ba03c0 +8d45121efba8cc308a498e8ee39ea6fa5cae9fb2e4aab1c2ff9d448aa8494ccbec9a078f978a86fcd97b5d5e7be7522a +a8173865c64634ba4ac2fa432740f5c05056a9deaf6427cb9b4b8da94ca5ddbc8c0c5d3185a89b8b28878194de9cdfcd +b6ec06a74d690f6545f0f0efba236e63d1fdfba54639ca2617408e185177ece28901c457d02b849fd00f1a53ae319d0a +b69a12df293c014a40070e3e760169b6f3c627caf9e50b35a93f11ecf8df98b2bc481b410eecb7ab210bf213bbe944de +97e7dc121795a533d4224803e591eef3e9008bab16f12472210b73aaf77890cf6e3877e0139403a0d3003c12c8f45636 +acdfa6fdd4a5acb7738cc8768f7cba84dbb95c639399b291ae8e4e63df37d2d4096900a84d2f0606bf534a9ccaa4993f +86ee253f3a9446a33e4d1169719b7d513c6b50730988415382faaf751988c10a421020609f7bcdef91be136704b906e2 +aac9438382a856caf84c5a8a234282f71b5fc5f65219103b147e7e6cf565522285fbfd7417b513bdad8277a00f652ca1 +83f3799d8e5772527930f5dc071a2e0a65471618993ec8990a96ccdeee65270e490bda9d26bb877612475268711ffd80 +93f28a81ac8c0ec9450b9d762fae9c7f8feaace87a6ee6bd141ef1d2d0697ef1bbd159fe6e1de640dbdab2b0361fca8a +a0825c95ba69999b90eac3a31a3fd830ea4f4b2b7409bde5f202b61d741d6326852ce790f41de5cb0eccec7af4db30c1 +83924b0e66233edd603c3b813d698daa05751fc34367120e3cf384ea7432e256ccee4d4daf13858950549d75a377107d +956fd9fa58345277e06ba2ec72f49ed230b8d3d4ff658555c52d6cddeb84dd4e36f1a614f5242d5ca0192e8daf0543c2 +944869912476baae0b114cced4ff65c0e4c90136f73ece5656460626599051b78802df67d7201c55d52725a97f5f29fe +865cb25b64b4531fb6fe4814d7c8cd26b017a6c6b72232ff53defc18a80fe3b39511b23f9e4c6c7249d06e03b2282ed2 +81e09ff55214960775e1e7f2758b9a6c4e4cd39edf7ec1adfaad51c52141182b79fe2176b23ddc7df9fd153e5f82d668 +b31006896f02bc90641121083f43c3172b1039334501fbaf1672f7bf5d174ddd185f945adf1a9c6cf77be34c5501483d +88b92f6f42ae45e9f05b16e52852826e933efd0c68b0f2418ac90957fd018df661bc47c8d43c2a7d7bfcf669dab98c3c +92fc68f595853ee8683930751789b799f397135d002eda244fe63ecef2754e15849edde3ba2f0cc8b865c9777230b712 +99ca06a49c5cd0bb097c447793fcdd809869b216a34c66c78c7e41e8c22f05d09168d46b8b1f3390db9452d91bc96dea +b48b9490a5d65296802431852d548d81047bbefc74fa7dc1d4e2a2878faacdfcb365ae59209cb0ade01901a283cbd15d +aff0fdbef7c188b120a02bc9085d7b808e88f73973773fef54707bf2cd772cd066740b1b6f4127b5c349f657bd97e738 +966fd4463b4f43dd8ccba7ad50baa42292f9f8b2e70da23bb6780e14155d9346e275ef03ddaf79e47020dcf43f3738bd +9330c3e1fadd9e08ac85f4839121ae20bbeb0a5103d84fa5aadbd1213805bdcda67bf2fb75fc301349cbc851b5559d20 +993bb99867bd9041a71a55ad5d397755cfa7ab6a4618fc526179bfc10b7dc8b26e4372fe9a9b4a15d64f2b63c1052dda +a29b59bcfab51f9b3c490a3b96f0bf1934265c315349b236012adbd64a56d7f6941b2c8cc272b412044bc7731f71e1dc +a65c9cefe1fc35d089fe8580c2e7671ebefdb43014ac291528ff4deefd4883fd4df274af83711dad610dad0d615f9d65 +944c78c56fb227ae632805d448ca3884cd3d2a89181cead3d2b7835e63297e6d740aa79a112edb1d4727824991636df5 +a73d782da1db7e4e65d7b26717a76e16dd9fab4df65063310b8e917dc0bc24e0d6755df5546c58504d04d9e68c3b474a +af80f0b87811ae3124f68108b4ca1937009403f87928bbc53480e7c5408d072053ace5eeaf5a5aba814dab8a45502085 +88aaf1acfc6e2e19b8387c97da707cb171c69812fefdd4650468e9b2c627bd5ccfb459f4d8e56bdfd84b09ddf87e128f +92c97276ff6f72bab6e9423d02ad6dc127962dbce15a0dd1e4a393b4510c555df6aa27be0f697c0d847033a9ca8b8dfd +a0e07d43d96e2d85b6276b3c60aadb48f0aedf2de8c415756dc597249ea64d2093731d8735231dadc961e5682ac59479 +adc9e6718a8f9298957d1da3842a7751c5399bbdf56f8de6c1c4bc39428f4aee6f1ba6613d37bf46b9403345e9d6fc81 +951da434da4b20d949b509ceeba02e24da7ed2da964c2fcdf426ec787779c696b385822c7dbea4df3e4a35921f1e912c +a04cbce0d2b2e87bbf038c798a12ec828423ca6aca08dc8d481cf6466e3c9c73d4d4a7fa47df9a7e2e15aae9e9f67208 +8f855cca2e440d248121c0469de1f94c2a71b8ee2682bbad3a78243a9e03da31d1925e6760dbc48a1957e040fae9abe8 +b642e5b17c1df4a4e101772d73851180b3a92e9e8b26c918050f51e6dd3592f102d20b0a1e96f0e25752c292f4c903ff +a92454c300781f8ae1766dbbb50a96192da7d48ef4cbdd72dd8cbb44c6eb5913c112cc38e9144615fdc03684deb99420 +8b74f7e6c2304f8e780df4649ef8221795dfe85fdbdaa477a1542d135b75c8be45bf89adbbb6f3ddf54ca40f02e733e9 +85cf66292cbb30cec5fd835ab10c9fcb3aea95e093aebf123e9a83c26f322d76ebc89c4e914524f6c5f6ee7d74fc917d +ae0bfe0cdc97c09542a7431820015f2d16067b30dca56288013876025e81daa8c519e5e347268e19aa1a85fa1dc28793 +921322fc6a47dc091afa0ad6df18ed14cde38e48c6e71550aa513918b056044983aee402de21051235eecf4ce8040fbe +96c030381e97050a45a318d307dcb3c8377b79b4dd5daf6337cded114de26eb725c14171b9b8e1b3c08fe1f5ea6b49e0 +90c23b86b6111818c8baaf53a13eaee1c89203b50e7f9a994bf0edf851919b48edbac7ceef14ac9414cf70c486174a77 +8bf6c301240d2d1c8d84c71d33a6dfc6d9e8f1cfae66d4d0f7a256d98ae12b0bcebfa94a667735ee89f810bcd7170cff +a41a4ffbbea0e36874d65c009ee4c3feffff322f6fc0e30d26ee4dbc1f46040d05e25d9d0ecb378cef0d24a7c2c4b850 +a8d4cdd423986bb392a0a92c12a8bd4da3437eec6ef6af34cf5310944899287452a2eb92eb5386086d5063381189d10e +a81dd26ec057c4032a4ed7ad54d926165273ed51d09a1267b2e477535cf6966835a257c209e4e92d165d74fa75695fa3 +8d7f708c3ee8449515d94fc26b547303b53d8dd55f177bc3b25d3da2768accd9bc8e9f09546090ebb7f15c66e6c9c723 +839ba65cffcd24cfffa7ab3b21faabe3c66d4c06324f07b2729c92f15cad34e474b0f0ddb16cd652870b26a756b731d3 +87f1a3968afec354d92d77e2726b702847c6afcabb8438634f9c6f7766de4c1504317dc4fa9a4a735acdbf985e119564 +91a8a7fd6542f3e0673f07f510d850864b34ac087eb7eef8845a1d14b2b1b651cbdc27fa4049bdbf3fea54221c5c8549 +aef3cf5f5e3a2385ead115728d7059e622146c3457d266c612e778324b6e06fbfb8f98e076624d2f3ce1035d65389a07 +819915d6232e95ccd7693fdd78d00492299b1983bc8f96a08dcb50f9c0a813ed93ae53c0238345d5bea0beda2855a913 +8e9ba68ded0e94935131b392b28218315a185f63bf5e3c1a9a9dd470944509ca0ba8f6122265f8da851b5cc2abce68f1 +b28468e9b04ee9d69003399a3cf4457c9bf9d59f36ab6ceeb8e964672433d06b58beeea198fedc7edbaa1948577e9fa2 +a633005e2c9f2fd94c8bce2dd5bb708fe946b25f1ec561ae65e54e15cdd88dc339f1a083e01f0d39610c8fe24151aaf0 +841d0031e22723f9328dd993805abd13e0c99b0f59435d2426246996b08d00ce73ab906f66c4eab423473b409e972ce0 +85758d1b084263992070ec8943f33073a2d9b86a8606672550c17545507a5b3c88d87382b41916a87ee96ff55a7aa535 +8581b06b0fc41466ef94a76a1d9fb8ae0edca6d018063acf6a8ca5f4b02d76021902feba58972415691b4bdbc33ae3b4 +83539597ff5e327357ee62bc6bf8c0bcaec2f227c55c7c385a4806f0d37fb461f1690bad5066b8a5370950af32fafbef +aee3557290d2dc10827e4791d00e0259006911f3f3fce4179ed3c514b779160613eca70f720bff7804752715a1266ffa +b48d2f0c4e90fc307d5995464e3f611a9b0ef5fe426a289071f4168ed5cc4f8770c9332960c2ca5c8c427f40e6bb389f +847af8973b4e300bb06be69b71b96183fd1a0b9d51b91701bef6fcfde465068f1eb2b1503b07afda380f18d69de5c9e1 +a70a6a80ce407f07804c0051ac21dc24d794b387be94eb24e1db94b58a78e1bcfb48cd0006db8fc1f9bedaece7a44fbe +b40e942b8fa5336910ff0098347df716bff9d1fa236a1950c16eeb966b3bc1a50b8f7b0980469d42e75ae13ced53cead +b208fabaa742d7db3148515330eb7a3577487845abdb7bd9ed169d0e081db0a5816595c33d375e56aeac5b51e60e49d3 +b7c8194b30d3d6ef5ab66ec88ad7ebbc732a3b8a41731b153e6f63759a93f3f4a537eab9ad369705bd730184bdbbdc34 +9280096445fe7394d04aa1bc4620c8f9296e991cc4d6c131bd703cb1cc317510e6e5855ac763f4d958c5edfe7eebeed7 +abc2aa4616a521400af1a12440dc544e3c821313d0ab936c86af28468ef8bbe534837e364598396a81cf8d06274ed5a6 +b18ca8a3325adb0c8c18a666d4859535397a1c3fe08f95eebfac916a7a99bbd40b3c37b919e8a8ae91da38bc00fa56c0 +8a40c33109ecea2a8b3558565877082f79121a432c45ec2c5a5e0ec4d1c203a6788e6b69cb37f1fd5b8c9a661bc5476d +88c47301dd30998e903c84e0b0f2c9af2e1ce6b9f187dab03528d44f834dc991e4c86d0c474a2c63468cf4020a1e24a0 +920c832853e6ab4c851eecfa9c11d3acc7da37c823be7aa1ab15e14dfd8beb5d0b91d62a30cec94763bd8e4594b66600 +98e1addbe2a6b8edc7f12ecb9be81c3250aeeca54a1c6a7225772ca66549827c15f3950d01b8eb44aecb56fe0fff901a +8cfb0fa1068be0ec088402f5950c4679a2eb9218c729da67050b0d1b2d7079f3ddf4bf0f57d95fe2a8db04bc6bcdb20c +b70f381aafe336b024120453813aeab70baac85b9c4c0f86918797b6aee206e6ed93244a49950f3d8ec9f81f4ac15808 +a4c8edf4aa33b709a91e1062939512419711c1757084e46f8f4b7ed64f8e682f4e78b7135920c12f0eb0422fe9f87a6a +b4817e85fd0752d7ebb662d3a51a03367a84bac74ebddfba0e5af5e636a979500f72b148052d333b3dedf9edd2b4031b +a87430169c6195f5d3e314ff2d1c2f050e766fd5d2de88f5207d72dba4a7745bb86d0baca6e9ae156582d0d89e5838c7 +991b00f8b104566b63a12af4826b61ce7aa40f4e5b8fff3085e7a99815bdb4471b6214da1e480214fac83f86a0b93cc5 +b39966e3076482079de0678477df98578377a094054960ee518ef99504d6851f8bcd3203e8da5e1d4f6f96776e1fe6eb +a448846d9dc2ab7a0995fa44b8527e27f6b3b74c6e03e95edb64e6baa4f1b866103f0addb97c84bef1d72487b2e21796 +894bec21a453ae84b592286e696c35bc30e820e9c2fd3e63dd4fbe629e07df16439c891056070faa490155f255bf7187 +a9ec652a491b11f6a692064e955f3f3287e7d2764527e58938571469a1e29b5225b9415bd602a45074dfbfe9c131d6ca +b39d37822e6cbe28244b5f42ce467c65a23765bd16eb6447c5b3e942278069793763483dafd8c4dd864f8917aad357fe +88dba51133f2019cb266641c56101e3e5987d3b77647a2e608b5ff9113dfc5f85e2b7c365118723131fbc0c9ca833c9c +b566579d904b54ecf798018efcb824dccbebfc6753a0fd2128ac3b4bd3b038c2284a7c782b5ca6f310eb7ea4d26a3f0a +a97a55c0a492e53c047e7d6f9d5f3e86fb96f3dddc68389c0561515343b66b4bc02a9c0d5722dff1e3445308240b27f7 +a044028ab4bcb9e1a2b9b4ca4efbf04c5da9e4bf2fff0e8bd57aa1fc12a71e897999c25d9117413faf2f45395dee0f13 +a78dc461decbeaeed8ebd0909369b491a5e764d6a5645a7dac61d3140d7dc0062526f777b0eb866bff27608429ebbdde +b2c2a8991f94c39ca35fea59f01a92cb3393e0eccb2476dfbf57261d406a68bd34a6cff33ed80209991688c183609ef4 +84189eefb521aff730a4fd3fd5b10ddfd29f0d365664caef63bb015d07e689989e54c33c2141dd64427805d37a7e546e +85ac80bd734a52235da288ff042dea9a62e085928954e8eacd2c751013f61904ed110e5b3afe1ab770a7e6485efb7b5e +9183a560393dcb22d0d5063e71182020d0fbabb39e32493eeffeb808df084aa243eb397027f150b55a247d1ed0c8513e +81c940944df7ecc58d3c43c34996852c3c7915ed185d7654627f7af62abae7e0048dd444a6c09961756455000bd96d09 +aa8c34e164019743fd8284b84f06c3b449aae7996e892f419ee55d82ad548cb300fd651de329da0384243954c0ef6a60 +89a7b7bdfc7e300d06a14d463e573d6296d8e66197491900cc9ae49504c4809ff6e61b758579e9091c61085ba1237b83 +878d21809ba540f50bd11f4c4d9590fb6f3ab9de5692606e6e2ef4ed9d18520119e385be5e1f4b3f2e2b09c319f0e8fc +8eb248390193189cf0355365e630b782cd15751e672dc478b39d75dc681234dcd9309df0d11f4610dbb249c1e6be7ef9 +a1d7fb3aecb896df3a52d6bd0943838b13f1bd039c936d76d03de2044c371d48865694b6f532393b27fd10a4cf642061 +a34bca58a24979be442238cbb5ece5bee51ae8c0794dd3efb3983d4db713bc6f28a96e976ac3bd9a551d3ed9ba6b3e22 +817c608fc8cacdd178665320b5a7587ca21df8bdd761833c3018b967575d25e3951cf3d498a63619a3cd2ad4406f5f28 +86c95707db0495689afd0c2e39e97f445f7ca0edffad5c8b4cacd1421f2f3cc55049dfd504f728f91534e20383955582 +99c3b0bb15942c301137765d4e19502f65806f3b126dc01a5b7820c87e8979bce6a37289a8f6a4c1e4637227ad5bf3bf +8aa1518a80ea8b074505a9b3f96829f5d4afa55a30efe7b4de4e5dbf666897fdd2cf31728ca45921e21a78a80f0e0f10 +8d74f46361c79e15128ac399e958a91067ef4cec8983408775a87eca1eed5b7dcbf0ddf30e66f51780457413496c7f07 +a41cde4a786b55387458a1db95171aca4fd146507b81c4da1e6d6e495527c3ec83fc42fad1dfe3d92744084a664fd431 +8c352852c906fae99413a84ad11701f93f292fbf7bd14738814f4c4ceab32db02feb5eb70bc73898b0bc724a39d5d017 +a5993046e8f23b71ba87b7caa7ace2d9023fb48ce4c51838813174880d918e9b4d2b0dc21a2b9c6f612338c31a289df8 +83576d3324bf2d8afbfb6eaecdc5d767c8e22e7d25160414924f0645491df60541948a05e1f4202e612368e78675de8a +b43749b8df4b15bc9a3697e0f1c518e6b04114171739ef1a0c9c65185d8ec18e40e6954d125cbc14ebc652cf41ad3109 +b4eebd5d80a7327a040cafb9ccdb12b2dfe1aa86e6bc6d3ac8a57fadfb95a5b1a7332c66318ff72ba459f525668af056 +9198be7f1d413c5029b0e1c617bcbc082d21abe2c60ec8ce9b54ca1a85d3dba637b72fda39dae0c0ae40d047eab9f55a +8d96a0232832e24d45092653e781e7a9c9520766c3989e67bbe86b3a820c4bf621ea911e7cd5270a4bfea78b618411f6 +8d7160d0ea98161a2d14d46ef01dff72d566c330cd4fabd27654d300e1bc7644c68dc8eabf2a20a59bfe7ba276545f9b +abb60fce29dec7ba37e3056e412e0ec3e05538a1fc0e2c68877378c867605966108bc5742585ab6a405ce0c962b285b6 +8fabffa3ed792f05e414f5839386f6449fd9f7b41a47595c5d71074bd1bb3784cc7a1a7e1ad6b041b455035957e5b2dc +90ff017b4804c2d0533b72461436b10603ab13a55f86fd4ec11b06a70ef8166f958c110519ca1b4cc7beba440729fe2d +b340cfd120f6a4623e3a74cf8c32bfd7cd61a280b59dfd17b15ca8fae4d82f64a6f15fbde4c02f424debc72b7db5fe67 +871311c9c7220c932e738d59f0ecc67a34356d1429fe570ca503d340c9996cb5ee2cd188fad0e3bd16e4c468ec1dbebd +a772470262186e7b94239ba921b29f2412c148d6f97c4412e96d21e55f3be73f992f1ad53c71008f0558ec3f84e2b5a7 +b2a897dcb7ffd6257f3f2947ec966f2077d57d5191a88840b1d4f67effebe8c436641be85524d0a21be734c63ab5965d +a044f6eacc48a4a061fa149500d96b48cbf14853469aa4d045faf3dca973be1bd4b4ce01646d83e2f24f7c486d03205d +981af5dc2daa73f7fa9eae35a93d81eb6edba4a7f673b55d41f6ecd87a37685d31bb40ef4f1c469b3d72f2f18b925a17 +912d2597a07864de9020ac77083eff2f15ceb07600f15755aba61251e8ce3c905a758453b417f04d9c38db040954eb65 +9642b7f6f09394ba5e0805734ef6702c3eddf9eea187ba98c676d5bbaec0e360e3e51dc58433aaa1e2da6060c8659cb7 +8ab3836e0a8ac492d5e707d056310c4c8e0489ca85eb771bff35ba1d658360084e836a6f51bb990f9e3d2d9aeb18fbb5 +879e058e72b73bb1f4642c21ffdb90544b846868139c6511f299aafe59c2d0f0b944dffc7990491b7c4edcd6a9889250 +b9e60b737023f61479a4a8fd253ed0d2a944ea6ba0439bbc0a0d3abf09b0ad1f18d75555e4a50405470ae4990626f390 +b9c2535d362796dcd673640a9fa2ebdaec274e6f8b850b023153b0a7a30fffc87f96e0b72696f647ebe7ab63099a6963 +94aeff145386a087b0e91e68a84a5ede01f978f9dd9fe7bebca78941938469495dc30a96bba9508c0d017873aeea9610 +98b179f8a3d9f0d0a983c30682dd425a2ddc7803be59bd626c623c8951a5179117d1d2a68254c95c9952989877d0ee55 +889ecf5f0ee56938273f74eb3e9ecfb5617f04fb58e83fe4c0e4aef51615cf345bc56f3f61b17f6eed3249d4afd54451 +a0f2b2c39bcea4b50883e2587d16559e246248a66ecb4a4b7d9ab3b51fb39fe98d83765e087eee37a0f86b0ba4144c02 +b2a61e247ed595e8a3830f7973b07079cbda510f28ad8c78c220b26cb6acde4fbb5ee90c14a665f329168ee951b08cf0 +95bd0fcfb42f0d6d8a8e73d7458498a85bcddd2fb132fd7989265648d82ac2707d6d203fac045504977af4f0a2aca4b7 +843e5a537c298666e6cf50fcc044f13506499ef83c802e719ff2c90e85003c132024e04711be7234c04d4b0125512d5d +a46d1797c5959dcd3a5cfc857488f4d96f74277c3d13b98b133620192f79944abcb3a361d939a100187f1b0856eae875 +a1c7786736d6707a48515c38660615fcec67eb8a2598f46657855215f804fd72ab122d17f94fcffad8893f3be658dca7 +b23dc9e610abc7d8bd21d147e22509a0fa49db5be6ea7057b51aae38e31654b3aa044df05b94b718153361371ba2f622 +b00cc8f257d659c22d30e6d641f79166b1e752ea8606f558e4cad6fc01532e8319ea4ee12265ba4140ac45aa4613c004 +ac7019af65221b0cc736287b32d7f1a3561405715ba9a6a122342e04e51637ba911c41573de53e4781f2230fdcb2475f +81a630bc41b3da8b3eb4bf56cba10cd9f93153c3667f009dc332287baeb707d505fb537e6233c8e53d299ec0f013290c +a6b7aea5c545bb76df0f230548539db92bc26642572cb7dd3d5a30edca2b4c386f44fc8466f056b42de2a452b81aff5b +8271624ff736b7b238e43943c81de80a1612207d32036d820c11fc830c737972ccc9c60d3c2359922b06652311e3c994 +8a684106458cb6f4db478170b9ad595d4b54c18bf63b9058f095a2fa1b928c15101472c70c648873d5887880059ed402 +a5cc3c35228122f410184e4326cf61a37637206e589fcd245cb5d0cec91031f8f7586b80503070840fdfd8ce75d3c88b +9443fc631aed8866a7ed220890911057a1f56b0afe0ba15f0a0e295ab97f604b134b1ed9a4245e46ee5f9a93aa74f731 +984b6f7d79835dffde9558c6bb912d992ca1180a2361757bdba4a7b69dc74b056e303adc69fe67414495dd9c2dd91e64 +b15a5c8cba5de080224c274d31c68ed72d2a7126d347796569aef0c4e97ed084afe3da4d4b590b9dda1a07f0c2ff3dfb +991708fe9650a1f9a4e43938b91d45dc68c230e05ee999c95dbff3bf79b1c1b2bb0e7977de454237c355a73b8438b1d9 +b4f7edc7468b176a4a7c0273700c444fa95c726af6697028bed4f77eee887e3400f9c42ee15b782c0ca861c4c3b8c98a +8c60dcc16c51087eb477c13e837031d6c6a3dc2b8bf8cb43c23f48006bc7173151807e866ead2234b460c2de93b31956 +83ad63e9c910d1fc44bc114accfb0d4d333b7ebe032f73f62d25d3e172c029d5e34a1c9d547273bf6c0fead5c8801007 +85de73213cc236f00777560756bdbf2b16841ba4b55902cf2cad9742ecaf5d28209b012ceb41f337456dfeca93010cd7 +a7561f8827ccd75b6686ba5398bb8fc3083351c55a589b18984e186820af7e275af04bcd4c28e1dc11be1e8617a0610b +88c0a4febd4068850557f497ea888035c7fc9f404f6cc7794e7cc8722f048ad2f249e7dc62743e7a339eb7473ad3b0cd +932b22b1d3e6d5a6409c34980d176feb85ada1bf94332ef5c9fc4d42b907dabea608ceef9b5595ef3feee195151f18d8 +a2867bb3f5ab88fbdae3a16c9143ab8a8f4f476a2643c505bb9f37e5b1fd34d216cab2204c9a017a5a67b7ad2dda10e8 +b573d5f38e4e9e8a3a6fd82f0880dc049efa492a946d00283019bf1d5e5516464cf87039e80aef667cb86fdea5075904 +b948f1b5ab755f3f5f36af27d94f503b070696d793b1240c1bdfd2e8e56890d69e6904688b5f8ff5a4bdf5a6abfe195f +917eae95ebc4109a2e99ddd8fec7881d2f7aaa0e25fda44dec7ce37458c2ee832f1829db7d2dcfa4ca0f06381c7fe91d +95751d17ed00a3030bce909333799bb7f4ab641acf585807f355b51d6976dceee410798026a1a004ef4dcdff7ec0f5b8 +b9b7bd266f449a79bbfe075e429613e76c5a42ac61f01c8f0bbbd34669650682efe01ff9dbbc400a1e995616af6aa278 +ac1722d097ce9cd7617161f8ec8c23d68f1fb1c9ca533e2a8b4f78516c2fd8fb38f23f834e2b9a03bb06a9d655693ca9 +a7ad9e96ffd98db2ecdb6340c5d592614f3c159abfd832fe27ee9293519d213a578e6246aae51672ee353e3296858873 +989b8814d5de7937c4acafd000eec2b4cd58ba395d7b25f98cafd021e8efa37029b29ad8303a1f6867923f5852a220eb +a5bfe6282c771bc9e453e964042d44eff4098decacb89aecd3be662ea5b74506e1357ab26f3527110ba377711f3c9f41 +8900a7470b656639721d2abbb7b06af0ac4222ab85a1976386e2a62eb4b88bfb5b72cf7921ddb3cf3a395d7eeb192a2e +95a71b55cd1f35a438cf5e75f8ff11c5ec6a2ebf2e4dba172f50bfad7d6d5dca5de1b1afc541662c81c858f7604c1163 +82b5d62fea8db8d85c5bc3a76d68dedd25794cf14d4a7bc368938ffca9e09f7e598fdad2a5aac614e0e52f8112ae62b9 +997173f07c729202afcde3028fa7f52cefc90fda2d0c8ac2b58154a5073140683e54c49ed1f254481070d119ce0ce02a +aeffb91ccc7a72bbd6ffe0f9b99c9e66e67d59cec2e02440465e9636a613ab3017278cfa72ea8bc4aba9a8dc728cb367 +952743b06e8645894aeb6440fc7a5f62dd3acf96dab70a51e20176762c9751ea5f2ba0b9497ccf0114dc4892dc606031 +874c63baeddc56fbbca2ff6031f8634b745f6e34ea6791d7c439201aee8f08ef5ee75f7778700a647f3b21068513fce6 +85128fec9c750c1071edfb15586435cc2f317e3e9a175bb8a9697bcda1eb9375478cf25d01e7fed113483b28f625122d +85522c9576fd9763e32af8495ae3928ed7116fb70d4378448926bc9790e8a8d08f98cf47648d7da1b6e40d6a210c7924 +97d0f37a13cfb723b848099ca1c14d83e9aaf2f7aeb71829180e664b7968632a08f6a85f557d74b55afe6242f2a36e7c +abaa472d6ad61a5fccd1a57c01aa1bc081253f95abbcba7f73923f1f11c4e79b904263890eeb66926de3e2652f5d1c70 +b3c04945ba727a141e5e8aec2bf9aa3772b64d8fd0e2a2b07f3a91106a95cbcb249adcd074cbe498caf76fffac20d4ef +82c46781a3d730d9931bcabd7434a9171372dde57171b6180e5516d4e68db8b23495c8ac3ab96994c17ddb1cf249b9fb +a202d8b65613c42d01738ccd68ed8c2dbc021631f602d53f751966e04182743ebc8e0747d600b8a8676b1da9ae7f11ab +ae73e7256e9459db04667a899e0d3ea5255211fb486d084e6550b6dd64ca44af6c6b2d59d7aa152de9f96ce9b58d940d +b67d87b176a9722945ec7593777ee461809861c6cfd1b945dde9ee4ff009ca4f19cf88f4bbb5c80c9cbab2fe25b23ac8 +8f0b7a317a076758b0dac79959ee4a06c08b07d0f10538a4b53d3da2eda16e2af26922feb32c090330dc4d969cf69bd3 +90b36bf56adbd8c4b6cb32febc3a8d5f714370c2ac3305c10fa6d168dffb2a026804517215f9a2d4ec8310cdb6bb459b +aa80c19b0682ead69934bf18cf476291a0beddd8ef4ed75975d0a472e2ab5c70f119722a8574ae4973aceb733d312e57 +a3fc9abb12574e5c28dcb51750b4339b794b8e558675eef7d26126edf1de920c35e992333bcbffcbf6a5f5c0d383ce62 +a1573ff23ab972acdcd08818853b111fc757fdd35aa070186d3e11e56b172fb49d840bf297ac0dd222e072fc09f26a81 +98306f2be4caa92c2b4392212d0cbf430b409b19ff7d5b899986613bd0e762c909fc01999aa94be3bd529d67f0113d7f +8c1fc42482a0819074241746d17dc89c0304a2acdae8ed91b5009e9e3e70ff725ba063b4a3e68fdce05b74f5180c545e +a6c6113ebf72d8cf3163b2b8d7f3fa24303b13f55752522c660a98cd834d85d8c79214d900fa649499365e2e7641f77a +ab95eea424f8a2cfd9fb1c78bb724e5b1d71a0d0d1e4217c5d0f98b0d8bbd3f8400a2002abc0a0e4576d1f93f46fefad +823c5a4fd8cf4a75fdc71d5f2dd511b6c0f189b82affeacd2b7cfcad8ad1a5551227dcc9bfdb2e34b2097eaa00efbb51 +b97314dfff36d80c46b53d87a61b0e124dc94018a0bb680c32765b9a2d457f833a7c42bbc90b3b1520c33a182580398d +b17566ee3dcc6bb3b004afe4c0136dfe7dd27df9045ae896dca49fb36987501ae069eb745af81ba3fc19ff037e7b1406 +b0bdc0f55cfd98d331e3a0c4fbb776a131936c3c47c6bffdc3aaf7d8c9fa6803fbc122c2fefbb532e634228687d52174 +aa5d9e60cc9f0598559c28bb9bdd52aa46605ab4ffe3d192ba982398e72cec9a2a44c0d0d938ce69935693cabc0887ea +802b6459d2354fa1d56c592ac1346c428dadea6b6c0a87bf7d309bab55c94e1cf31dd98a7a86bd92a840dd51f218b91b +a526914efdc190381bf1a73dd33f392ecf01350b9d3f4ae96b1b1c3d1d064721c7d6eec5788162c933245a3943f5ee51 +b3b8fcf637d8d6628620a1a99dbe619eabb3e5c7ce930d6efd2197e261bf394b74d4e5c26b96c4b8009c7e523ccfd082 +8f7510c732502a93e095aba744535f3928f893f188adc5b16008385fb9e80f695d0435bfc5b91cdad4537e87e9d2551c +97b90beaa56aa936c3ca45698f79273a68dd3ccd0076eab48d2a4db01782665e63f33c25751c1f2e070f4d1a8525bf96 +b9fb798324b1d1283fdc3e48288e3861a5449b2ab5e884b34ebb8f740225324af86e4711da6b5cc8361c1db15466602f +b6d52b53cea98f1d1d4c9a759c25bf9d8a50b604b144e4912acbdbdc32aab8b9dbb10d64a29aa33a4f502121a6fb481c +9174ffff0f2930fc228f0e539f5cfd82c9368d26b074467f39c07a774367ff6cccb5039ac63f107677d77706cd431680 +a33b6250d4ac9e66ec51c063d1a6a31f253eb29bbaed12a0d67e2eccfffb0f3a52750fbf52a1c2aaba8c7692346426e7 +a97025fd5cbcebe8ef865afc39cd3ea707b89d4e765ec817fd021d6438e02fa51e3544b1fd45470c58007a08efac6edd +b32a78480edd9ff6ba2f1eec4088db5d6ceb2d62d7e59e904ecaef7bb4a2e983a4588e51692b3be76e6ffbc0b5f911a5 +b5ab590ef0bb77191f00495b33d11c53c65a819f7d0c1f9dc4a2caa147a69c77a4fff7366a602d743ee1f395ce934c1e +b3fb0842f9441fb1d0ee0293b6efbc70a8f58d12d6f769b12872db726b19e16f0f65efbc891cf27a28a248b0ef9c7e75 +9372ad12856fefb928ccb0d34e198df99e2f8973b07e9d417a3134d5f69e12e79ff572c4e03ccd65415d70639bc7c73e +aa8d6e83d09ce216bfe2009a6b07d0110d98cf305364d5529c170a23e693aabb768b2016befb5ada8dabdd92b4d012bb +a954a75791eeb0ce41c85200c3763a508ed8214b5945a42c79bfdcfb1ec4f86ad1dd7b2862474a368d4ac31911a2b718 +8e2081cfd1d062fe3ab4dab01f68062bac802795545fede9a188f6c9f802cb5f884e60dbe866710baadbf55dc77c11a4 +a2f06003b9713e7dd5929501ed485436b49d43de80ea5b15170763fd6346badf8da6de8261828913ee0dacd8ff23c0e1 +98eecc34b838e6ffd1931ca65eec27bcdb2fdcb61f33e7e5673a93028c5865e0d1bf6d3bec040c5e96f9bd08089a53a4 +88cc16019741b341060b95498747db4377100d2a5bf0a5f516f7dec71b62bcb6e779de2c269c946d39040e03b3ae12b7 +ad1135ccbc3019d5b2faf59a688eef2500697642be8cfbdf211a1ab59abcc1f24483e50d653b55ff1834675ac7b4978f +a946f05ed9972f71dfde0020bbb086020fa35b482cce8a4cc36dd94355b2d10497d7f2580541bb3e81b71ac8bba3c49f +a83aeed488f9a19d8cfd743aa9aa1982ab3723560b1cd337fc2f91ad82f07afa412b3993afb845f68d47e91ba4869840 +95eebe006bfc316810cb71da919e5d62c2cebb4ac99d8e8ef67be420302320465f8b69873470982de13a7c2e23516be9 +a55f8961295a11e91d1e5deadc0c06c15dacbfc67f04ccba1d069cba89d72aa3b3d64045579c3ea8991b150ac29366ae +b321991d12f6ac07a5de3c492841d1a27b0d3446082fbce93e7e1f9e8d8fe3b45d41253556261c21b70f5e189e1a7a6f +a0b0822f15f652ce7962a4f130104b97bf9529797c13d6bd8e24701c213cc37f18157bd07f3d0f3eae6b7cd1cb40401f +96e2fa4da378aa782cc2d5e6e465fc9e49b5c805ed01d560e9b98abb5c0de8b74a2e7bec3aa5e2887d25cccb12c66f0c +97e4ab610d414f9210ed6f35300285eb3ccff5b0b6a95ed33425100d7725e159708ea78704497624ca0a2dcabce3a2f9 +960a375b17bdb325761e01e88a3ea57026b2393e1d887b34b8fa5d2532928079ce88dc9fd06a728b26d2bb41b12b9032 +8328a1647398e832aadc05bd717487a2b6fcdaa0d4850d2c4da230c6a2ed44c3e78ec4837b6094f3813f1ee99414713f +aa283834ebd18e6c99229ce4b401eda83f01d904f250fedd4e24f1006f8fa0712a6a89a7296a9bf2ce8de30e28d1408e +b29e097f2caadae3e0f0ae3473c072b0cd0206cf6d2e9b22c1a5ad3e07d433e32bd09ed1f4e4276a2da4268633357b7f +9539c5cbba14538b2fe077ecf67694ef240da5249950baaabea0340718b882a966f66d97f08556b08a4320ceb2cc2629 +b4529f25e9b42ae8cf8338d2eface6ba5cd4b4d8da73af502d081388135c654c0b3afb3aa779ffc80b8c4c8f4425dd2b +95be0739c4330619fbe7ee2249c133c91d6c07eab846c18c5d6c85fc21ac5528c5d56dcb0145af68ed0c6a79f68f2ccd +ac0c83ea802227bfc23814a24655c9ff13f729619bcffdb487ccbbf029b8eaee709f8bddb98232ef33cd70e30e45ca47 +b503becb90acc93b1901e939059f93e671900ca52c6f64ae701d11ac891d3a050b505d89324ce267bc43ab8275da6ffe +98e3811b55b1bacb70aa409100abb1b870f67e6d059475d9f278c751b6e1e2e2d6f2e586c81a9fb6597fda06e7923274 +b0b0f61a44053fa6c715dbb0731e35d48dba257d134f851ee1b81fd49a5c51a90ebf5459ec6e489fce25da4f184fbdb1 +b1d2117fe811720bb997c7c93fe9e4260dc50fca8881b245b5e34f724aaf37ed970cdad4e8fcb68e05ac8cf55a274a53 +a10f502051968f14b02895393271776dee7a06db9de14effa0b3471825ba94c3f805302bdddac4d397d08456f620999d +a3dbad2ef060ae0bb7b02eaa4a13594f3f900450faa1854fc09620b01ac94ab896321dfb1157cf2374c27e5718e8026a +b550fdec503195ecb9e079dcdf0cad559d64d3c30818ef369b4907e813e689da316a74ad2422e391b4a8c2a2bef25fc0 +a25ba865e2ac8f28186cea497294c8649a201732ecb4620c4e77b8e887403119910423df061117e5f03fc5ba39042db1 +b3f88174e03fdb443dd6addd01303cf88a4369352520187c739fc5ae6b22fa99629c63c985b4383219dab6acc5f6f532 +97a7503248e31e81b10eb621ba8f5210c537ad11b539c96dfb7cf72b846c7fe81bd7532c5136095652a9618000b7f8d3 +a8bcdc1ce5aa8bfa683a2fc65c1e79de8ff5446695dcb8620f7350c26d2972a23da22889f9e2b1cacb3f688c6a2953dc +8458c111df2a37f5dd91a9bee6c6f4b79f4f161c93fe78075b24a35f9817da8dde71763218d627917a9f1f0c4709c1ed +ac5f061a0541152b876cbc10640f26f1cc923c9d4ae1b6621e4bb3bf2cec59bbf87363a4eb72fb0e5b6d4e1c269b52d5 +a9a25ca87006e8a9203cbb78a93f50a36694aa4aad468b8d80d3feff9194455ca559fcc63838128a0ab75ad78c07c13a +a450b85f5dfffa8b34dfd8bc985f921318efacf8857cf7948f93884ba09fb831482ee90a44224b1a41e859e19b74962f +8ed91e7f92f5c6d7a71708b6132f157ac226ecaf8662af7d7468a4fa25627302efe31e4620ad28719318923e3a59bf82 +ab524165fd4c71b1fd395467a14272bd2b568592deafa039d8492e9ef36c6d3f96927c95c72d410a768dc0b6d1fbbc9b +b662144505aa8432c75ffb8d10318526b6d5777ac7af9ebfad87d9b0866c364f7905a6352743bd8fd79ffd9d5dd4f3e6 +a48f1677550a5cd40663bb3ba8f84caaf8454f332d0ceb1d94dbea52d0412fe69c94997f7749929712fd3995298572f7 +8391cd6e2f6b0c242de1117a612be99776c3dc95cb800b187685ea5bf7e2722275eddb79fd7dfc8be8e389c4524cdf70 +875d3acb9af47833b72900bc0a2448999d638f153c5e97e8a14ec02d0c76f6264353a7e275e1f1a5855daced523d243b +91f1823657d30b59b2f627880a9a9cb530f5aca28a9fd217fe6f2f5133690dfe7ad5a897872e400512db2e788b3f7628 +ad3564332aa56cea84123fc7ca79ea70bb4fef2009fa131cb44e4b15e8613bd11ca1d83b9d9bf456e4b7fee9f2e8b017 +8c530b84001936d5ab366c84c0b105241a26d1fb163669f17c8f2e94776895c2870edf3e1bc8ccd04d5e65531471f695 +932d01fa174fdb0c366f1230cffde2571cc47485f37f23ba5a1825532190cc3b722aeb1f15aed62cf83ccae9403ba713 +88b28c20585aca50d10752e84b901b5c2d58efef5131479fbbe53de7bce2029e1423a494c0298e1497669bd55be97a5d +b914148ca717721144ebb3d3bf3fcea2cd44c30c5f7051b89d8001502f3856fef30ec167174d5b76265b55d70f8716b5 +81d0173821c6ddd2a068d70766d9103d1ee961c475156e0cbd67d54e668a796310474ef698c7ab55abe6f2cf76c14679 +8f28e8d78e2fe7fa66340c53718e0db4b84823c8cfb159c76eac032a62fb53da0a5d7e24ca656cf9d2a890cb2a216542 +8a26360335c73d1ab51cec3166c3cf23b9ea51e44a0ad631b0b0329ef55aaae555420348a544e18d5760969281759b61 +94f326a32ed287545b0515be9e08149eb0a565025074796d72387cc3a237e87979776410d78339e23ef3172ca43b2544 +a785d2961a2fa5e70bffa137858a92c48fe749fee91b02599a252b0cd50d311991a08efd7fa5e96b78d07e6e66ffe746 +94af9030b5ac792dd1ce517eaadcec1482206848bea4e09e55cc7f40fd64d4c2b3e9197027c5636b70d6122c51d2235d +9722869f7d1a3992850fe7be405ec93aa17dc4d35e9e257d2e469f46d2c5a59dbd504056c85ab83d541ad8c13e8bcd54 +b13c4088b61a06e2c03ac9813a75ff1f68ffdfee9df6a8f65095179a475e29cc49119cad2ce05862c3b1ac217f3aace9 +8c64d51774753623666b10ca1b0fe63ae42f82ed6aa26b81dc1d48c86937c5772eb1402624c52a154b86031854e1fb9f +b47e4df18002b7dac3fee945bf9c0503159e1b8aafcce2138818e140753011b6d09ef1b20894e08ba3006b093559061b +93cb5970076522c5a0483693f6a35ffd4ea2aa7aaf3730c4eccd6af6d1bebfc1122fc4c67d53898ae13eb6db647be7e2 +a68873ef80986795ea5ed1a597d1cd99ed978ec25e0abb57fdcc96e89ef0f50aeb779ff46e3dce21dc83ada3157a8498 +8cab67f50949cc8eee6710e27358aea373aae3c92849f8f0b5531c080a6300cdf2c2094fe6fecfef6148de0d28446919 +993e932bcb616dbaa7ad18a4439e0565211d31071ef1b85a0627db74a05d978c60d507695eaeea5c7bd9868a21d06923 +acdadff26e3132d9478a818ef770e9fa0d2b56c6f5f48bd3bd674436ccce9bdfc34db884a73a30c04c5f5e9764cb2218 +a0d3e64c9c71f84c0eef9d7a9cb4fa184224b969db5514d678e93e00f98b41595588ca802643ea225512a4a272f5f534 +91c9140c9e1ba6e330cb08f6b2ce4809cd0d5a0f0516f70032bf30e912b0ed684d07b413b326ab531ee7e5b4668c799b +87bc2ee7a0c21ba8334cd098e35cb703f9af57f35e091b8151b9b63c3a5b0f89bd7701dbd44f644ea475901fa6d9ef08 +9325ccbf64bf5d71b303e31ee85d486298f9802c5e55b2c3d75427097bf8f60fa2ab4fcaffa9b60bf922c3e24fbd4b19 +95d0506e898318f3dc8d28d16dfd9f0038b54798838b3c9be2a2ae3c2bf204eb496166353fc042220b0bd4f6673b9285 +811de529416331fe9c416726d45df9434c29dcd7e949045eb15740f47e97dde8f31489242200e19922cac2a8b7c6fd1f +ade632d04a4c8bbab6ca7df370b2213cb9225023e7973f0e29f4f5e52e8aeaabc65171306bbdd12a67b195dfbb96d48f +88b7f029e079b6ae956042c0ea75d53088c5d0efd750dd018adaeacf46be21bf990897c58578c491f41afd3978d08073 +91f477802de507ffd2be3f4319903119225b277ad24f74eb50f28b66c14d32fae53c7edb8c7590704741af7f7f3e3654 +809838b32bb4f4d0237e98108320d4b079ee16ed80c567e7548bd37e4d7915b1192880f4812ac0e00476d246aec1dbc8 +84183b5fc4a7997a8ae5afedb4d21dce69c480d5966b5cbdafd6dd10d29a9a6377f3b90ce44da0eb8b176ac3af0253bb +8508abbf6d3739a16b9165caf0f95afb3b3ac1b8c38d6d374cf0c91296e2c1809a99772492b539cda184510bce8a0271 +8722054e59bab2062e6419a6e45fc803af77fde912ef2cd23055ad0484963de65a816a2debe1693d93c18218d2b8e81a +8e895f80e485a7c4f56827bf53d34b956281cdc74856c21eb3b51f6288c01cc3d08565a11cc6f3e2604775885490e8c5 +afc92714771b7aa6e60f3aee12efd9c2595e9659797452f0c1e99519f67c8bc3ac567119c1ddfe82a3e961ee9defea9a +818ff0fd9cefd32db87b259e5fa32967201016fc02ef44116cdca3c63ce5e637756f60477a408709928444a8ad69c471 +8251e29af4c61ae806fc5d032347fb332a94d472038149225298389495139ce5678fae739d02dfe53a231598a992e728 +a0ea39574b26643f6f1f48f99f276a8a64b5481989cfb2936f9432a3f8ef5075abfe5c067dc5512143ce8bf933984097 +af67a73911b372bf04e57e21f289fc6c3dfac366c6a01409b6e76fea4769bdb07a6940e52e8d7d3078f235c6d2f632c6 +b5291484ef336024dd2b9b4cf4d3a6b751133a40656d0a0825bcc6d41c21b1c79cb50b0e8f4693f90c29c8f4358641f9 +8bc0d9754d70f2cb9c63f991902165a87c6535a763d5eece43143b5064ae0bcdce7c7a8f398f2c1c29167b2d5a3e6867 +8d7faff53579ec8f6c92f661c399614cc35276971752ce0623270f88be937c414eddcb0997e14724a783905a026c8883 +9310b5f6e675fdf60796f814dbaa5a6e7e9029a61c395761e330d9348a7efab992e4e115c8be3a43d08e90d21290c892 +b5eb4f3eb646038ad2a020f0a42202532d4932e766da82b2c1002bf9c9c2e5336b54c8c0ffcc0e02d19dde2e6a35b6cc +91dabfd30a66710f1f37a891136c9be1e23af4abf8cb751f512a40c022a35f8e0a4fb05b17ec36d4208de02d56f0d53a +b3ded14e82d62ac7a5a036122a62f00ff8308498f3feae57d861babaff5a6628d43f0a0c5fc903f10936bcf4e2758ceb +a88e8348fed2b26acca6784d19ef27c75963450d99651d11a950ea81d4b93acd2c43e0ecce100eaf7e78508263d5baf3 +b1f5bbf7c4756877b87bb42163ac570e08c6667c4528bf68b5976680e19beeff7c5effd17009b0718797077e2955457a +ad2e7b516243f915d4d1415326e98b1a7390ae88897d0b03b66c2d9bd8c3fba283d7e8fe44ed3333296a736454cef6d8 +8f82eae096d5b11f995de6724a9af895f5e1c58d593845ad16ce8fcae8507e0d8e2b2348a0f50a1f66a17fd6fac51a5c +890e4404d0657c6c1ee14e1aac132ecf7a568bb3e04137b85ac0f84f1d333bd94993e8750f88eee033a33fb00f85dcc7 +82ac7d3385e035115f1d39a99fc73e5919de44f5e6424579776d118d711c8120b8e5916372c6f27bed4cc64cac170b6c +85ee16d8901c272cfbbe966e724b7a891c1bd5e68efd5d863043ad8520fc409080af61fd726adc680b3f1186fe0ac8b8 +86dc564c9b545567483b43a38f24c41c6551a49cabeebb58ce86404662a12dbfafd0778d30d26e1c93ce222e547e3898 +a29f5b4522db26d88f5f95f18d459f8feefab02e380c2edb65aa0617a82a3c1a89474727a951cef5f15050bcf7b380fb +a1ce039c8f6cac53352899edb0e3a72c76da143564ad1a44858bd7ee88552e2fe6858d1593bbd74aeee5a6f8034b9b9d +97f10d77983f088286bd7ef3e7fdd8fa275a56bec19919adf33cf939a90c8f2967d2b1b6fc51195cb45ad561202a3ed7 +a25e2772e8c911aaf8712bdac1dd40ee061c84d3d224c466cfaae8e5c99604053f940cde259bd1c3b8b69595781dbfec +b31bb95a0388595149409c48781174c340960d59032ab2b47689911d03c68f77a2273576fbe0c2bf4553e330656058c7 +b8b2e9287ad803fb185a13f0d7456b397d4e3c8ad5078f57f49e8beb2e85f661356a3392dbd7bcf6a900baa5582b86a1 +a3d0893923455eb6e96cc414341cac33d2dbc88fba821ac672708cce131761d85a0e08286663a32828244febfcae6451 +82310cb42f647d99a136014a9f881eb0b9791efd2e01fc1841907ad3fc8a9654d3d1dab6689c3607214b4dc2aca01cee +874022d99c16f60c22de1b094532a0bc6d4de700ad01a31798fac1d5088b9a42ad02bef8a7339af7ed9c0d4f16b186ee +94981369e120265aed40910eebc37eded481e90f4596b8d57c3bec790ab7f929784bd33ddd05b7870aad6c02e869603b +a4f1f50e1e2a73f07095e0dd31cb45154f24968dae967e38962341c1241bcd473102fff1ff668b20c6547e9732d11701 +ae2328f3b0ad79fcda807e69a1b5278145225083f150f67511dafc97e079f860c3392675f1752ae7e864c056e592205b +875d8c971e593ca79552c43d55c8c73b17cd20c81ff2c2fed1eb19b1b91e4a3a83d32df150dbfd5db1092d0aebde1e1f +add2e80aa46aae95da73a11f130f4bda339db028e24c9b11e5316e75ba5e63bc991d2a1da172c7c8e8fee038baae3433 +b46dbe1cb3424002aa7de51e82f600852248e251465c440695d52538d3f36828ff46c90ed77fc1d11534fe3c487df8ef +a5e5045d28b4e83d0055863c30c056628c58d4657e6176fd0536f5933f723d60e851bb726d5bf3c546b8ce4ac4a57ef8 +91fec01e86dd1537e498fff7536ea3ca012058b145f29d9ada49370cd7b7193ac380e116989515df1b94b74a55c45df3 +a7428176d6918cd916a310bdc75483c72de660df48cac4e6e7478eef03205f1827ea55afc0df5d5fa7567d14bbea7fc9 +851d89bef45d9761fe5fdb62972209335193610015e16a675149519f9911373bac0919add226ef118d9f3669cfdf4734 +b74acf5c149d0042021cb2422ea022be4c4f72a77855f42393e71ffd12ebb3eec16bdf16f812159b67b79a9706e7156d +99f35dce64ec99aa595e7894b55ce7b5a435851b396e79036ffb249c28206087db4c85379df666c4d95857db02e21ff9 +b6b9a384f70db9e298415b8ab394ee625dafff04be2886476e59df8d052ca832d11ac68a9b93fba7ab055b7bc36948a4 +898ee4aefa923ffec9e79f2219c7389663eb11eb5b49014e04ed4a336399f6ea1691051d86991f4c46ca65bcd4fdf359 +b0f948217b0d65df7599a0ba4654a5e43c84db477936276e6f11c8981efc6eaf14c90d3650107ed4c09af4cc8ec11137 +aa6286e27ac54f73e63dbf6f41865dd94d24bc0cf732262fcaff67319d162bb43af909f6f8ee27b1971939cfbba08141 +8bca7cdf730cf56c7b2c8a2c4879d61361a6e1dba5a3681a1a16c17a56e168ace0e99cf0d15826a1f5e67e6b8a8a049a +a746d876e8b1ce225fcafca603b099b36504846961526589af977a88c60d31ba2cc56e66a3dec8a77b3f3531bf7524c9 +a11e2e1927e6704cdb8874c75e4f1842cef84d7d43d7a38e339e61dc8ba90e61bbb20dd3c12e0b11d2471d58eed245be +a36395e22bc1d1ba8b0459a235203177737397da5643ce54ded3459d0869ff6d8d89f50c73cb62394bf66a959cde9b90 +8b49f12ba2fdf9aca7e5f81d45c07d47f9302a2655610e7634d1e4bd16048381a45ef2c95a8dd5b0715e4b7cf42273af +91cffa2a17e64eb7f76bccbe4e87280ee1dd244e04a3c9eac12e15d2d04845d876eb24fe2ec6d6d266cce9efb281077f +a6b8afabf65f2dee01788114e33a2f3ce25376fb47a50b74da7c3c25ff1fdc8aa9f41307534abbf48acb6f7466068f69 +8d13db896ccfea403bd6441191995c1a65365cab7d0b97fbe9526da3f45a877bd1f4ef2edef160e8a56838cd1586330e +98c717de9e01bef8842c162a5e757fe8552d53269c84862f4d451e7c656ae6f2ae473767b04290b134773f63be6fdb9d +8c2036ace1920bd13cf018e82848c49eb511fad65fd0ff51f4e4b50cf3bfc294afb63cba682c16f52fb595a98fa84970 +a3520fdff05dbad9e12551b0896922e375f9e5589368bcb2cc303bde252743b74460cb5caf99629325d3620f13adc796 +8d4f83a5bfec05caf5910e0ce538ee9816ee18d0bd44c1d0da2a87715a23cd2733ad4d47552c6dc0eb397687d611dd19 +a7b39a0a6a02823452d376533f39d35029867b3c9a6ad6bca181f18c54132d675613a700f9db2440fb1b4fa13c8bf18a +80bcb114b2544b80f404a200fc36860ed5e1ad31fe551acd4661d09730c452831751baa9b19d7d311600d267086a70bc +90dcce03c6f88fc2b08f2b42771eedde90cc5330fe0336e46c1a7d1b5a6c1641e5fcc4e7b3d5db00bd8afca9ec66ed81 +aec15f40805065c98e2965b1ae12a6c9020cfdb094c2d0549acfc7ea2401a5fb48d3ea7d41133cf37c4e096e7ff53eb9 +80e129b735dba49fa627a615d6c273119acec8e219b2f2c4373a332b5f98d66cbbdd688dfbe72a8f8bfefaccc02c50c1 +a9b596da3bdfe23e6799ece5f7975bf7a1979a75f4f546deeaf8b34dfe3e0d623217cb4cf4ccd504cfa3625b88cd53f1 +abcbbb70b16f6e517c0ab4363ab76b46e4ff58576b5f8340e5c0e8cc0e02621b6e23d742d73b015822a238b17cfd7665 +a046937cc6ea6a2e1adae543353a9fe929c1ae4ad655be1cc051378482cf88b041e28b1e9a577e6ccff2d3570f55e200 +831279437282f315e65a60184ef158f0a3dddc15a648dc552bdc88b3e6fe8288d3cfe9f0031846d81350f5e7874b4b33 +993d7916fa213c6d66e7c4cafafc1eaec9a2a86981f91c31eb8a69c5df076c789cbf498a24c84e0ee77af95b42145026 +823907a3b6719f8d49b3a4b7c181bd9bb29fcf842d7c70660c4f351852a1e197ca46cf5e879b47fa55f616fa2b87ce5e +8d228244e26132b234930ee14c75d88df0943cdb9c276a8faf167d259b7efc1beec2a87c112a6c608ad1600a239e9aae +ab6e55766e5bfb0cf0764ed909a8473ab5047d3388b4f46faeba2d1425c4754c55c6daf6ad4751e634c618b53e549529 +ab0cab6860e55a84c5ad2948a7e0989e2b4b1fd637605634b118361497332df32d9549cb854b2327ca54f2bcb85eed8f +b086b349ae03ef34f4b25a57bcaa5d1b29bd94f9ebf87e22be475adfe475c51a1230c1ebe13506cb72c4186192451658 +8a0b49d8a254ca6d91500f449cbbfbb69bb516c6948ac06808c65595e46773e346f97a5ce0ef7e5a5e0de278af22709c +ac49de11edaaf04302c73c578cc0824bdd165c0d6321be1c421c1950e68e4f3589aa3995448c9699e93c6ebae8803e27 +884f02d841cb5d8f4c60d1402469216b114ab4e93550b5bc1431756e365c4f870a9853449285384a6fa49e12ce6dc654 +b75f3a28fa2cc8d36b49130cb7448a23d73a7311d0185ba803ad55c8219741d451c110f48b786e96c728bc525903a54f +80ae04dbd41f4a35e33f9de413b6ad518af0919e5a30cb0fa1b061b260420780bb674f828d37fd3b52b5a31673cbd803 +b9a8011eb5fcea766907029bf743b45262db3e49d24f84503687e838651ed11cb64c66281e20a0ae9f6aa51acc552263 +90bfdd75e2dc9cf013e22a5d55d2d2b8a754c96103a17524488e01206e67f8b6d52b1be8c4e3d5307d4fe06d0e51f54c +b4af353a19b06203a815ec43e79a88578cc678c46f5a954b85bc5c53b84059dddba731f3d463c23bfd5273885c7c56a4 +aa125e96d4553b64f7140e5453ff5d2330318b69d74d37d283e84c26ad672fa00e3f71e530eb7e28be1e94afb9c4612e +a18e060aee3d49cde2389b10888696436bb7949a79ca7d728be6456a356ea5541b55492b2138da90108bd1ce0e6f5524 +93e55f92bdbccc2de655d14b1526836ea2e52dba65eb3f87823dd458a4cb5079bf22ce6ef625cb6d6bfdd0995ab9a874 +89f5a683526b90c1c3ceebbb8dc824b21cff851ce3531b164f6626e326d98b27d3e1d50982e507d84a99b1e04e86a915 +83d1c38800361633a3f742b1cb2bfc528129496e80232611682ddbe403e92c2ac5373aea0bca93ecb5128b0b2b7a719e +8ecba560ac94905e19ce8d9c7af217bf0a145d8c8bd38e2db82f5e94cc3f2f26f55819176376b51f154b4aab22056059 +a7e2a4a002b60291924850642e703232994acb4cfb90f07c94d1e0ecd2257bb583443283c20fc6017c37e6bfe85b7366 +93ed7316fa50b528f1636fc6507683a672f4f4403e55e94663f91221cc198199595bd02eef43d609f451acc9d9b36a24 +a1220a8ebc5c50ceed76a74bc3b7e0aa77f6884c71b64b67c4310ac29ce5526cb8992d6abc13ef6c8413ce62486a6795 +b2f6eac5c869ad7f4a25161d3347093e2f70e66cd925032747e901189355022fab3038bca4d610d2f68feb7e719c110b +b703fa11a4d511ca01c7462979a94acb40b5d933759199af42670eb48f83df202fa0c943f6ab3b4e1cc54673ea3aab1e +b5422912afbfcb901f84791b04f1ddb3c3fbdc76d961ee2a00c5c320e06d3cc5b5909c3bb805df66c5f10c47a292b13d +ad0934368da823302e1ac08e3ede74b05dfdbfffca203e97ffb0282c226814b65c142e6e15ec1e754518f221f01b30f7 +a1dd302a02e37df15bf2f1147efe0e3c06933a5a767d2d030e1132f5c3ce6b98e216b6145eb39e1e2f74e76a83165b8d +a346aab07564432f802ae44738049a36f7ca4056df2d8f110dbe7fef4a3e047684dea609b2d03dc6bf917c9c2a47608f +b96c5f682a5f5d02123568e50f5d0d186e4b2c4c9b956ec7aabac1b3e4a766d78d19bd111adb5176b898e916e49be2aa +8a96676d56876fc85538db2e806e1cba20fd01aeb9fa3cb43ca6ca94a2c102639f65660db330e5d74a029bb72d6a0b39 +ab0048336bd5c3def1a4064eadd49e66480c1f2abb4df46e03afbd8a3342c2c9d74ee35d79f08f4768c1646681440984 +888427bdf76caec90814c57ee1c3210a97d107dd88f7256f14f883ad0f392334b82be11e36dd8bfec2b37935177c7831 +b622b282becf0094a1916fa658429a5292ba30fb48a4c8066ce1ddcefb71037948262a01c95bab6929ed3a76ba5db9fe +b5b9e005c1f456b6a368a3097634fb455723abe95433a186e8278dceb79d4ca2fbe21f8002e80027b3c531e5bf494629 +a3c6707117a1e48697ed41062897f55d8119403eea6c2ee88f60180f6526f45172664bfee96bf61d6ec0b7fbae6aa058 +b02a9567386a4fbbdb772d8a27057b0be210447348efe6feb935ceec81f361ed2c0c211e54787dc617cdffed6b4a6652 +a9b8364e40ef15c3b5902e5534998997b8493064fa2bea99600def58279bb0f64574c09ba11e9f6f669a8354dd79dc85 +9998a2e553a9aa9a206518fae2bc8b90329ee59ab23005b10972712389f2ec0ee746033c733092ffe43d73d33abbb8ef +843a4b34d9039bf79df96d79f2d15e8d755affb4d83d61872daf540b68c0a3888cf8fc00d5b8b247b38524bcb3b5a856 +84f7128920c1b0bb40eee95701d30e6fc3a83b7bb3709f16d97e72acbb6057004ee7ac8e8f575936ca9dcb7866ab45f7 +918d3e2222e10e05edb34728162a899ad5ada0aaa491aeb7c81572a9c0d506e31d5390e1803a91ff3bd8e2bb15d47f31 +9442d18e2489613a7d47bb1cb803c8d6f3259d088cd079460976d87f7905ee07dea8f371b2537f6e1d792d36d7e42723 +b491976970fe091995b2ed86d629126523ccf3e9daf8145302faca71b5a71a5da92e0e05b62d7139d3efac5c4e367584 +aa628006235dc77c14cef4c04a308d66b07ac92d377df3de1a2e6ecfe3144f2219ad6d7795e671e1cb37a3641910b940 +99d386adaea5d4981d7306feecac9a555b74ffdc218c907c5aa7ac04abaead0ec2a8237300d42a3fbc464673e417ceed +8f78e8b1556f9d739648ea3cab9606f8328b52877fe72f9305545a73b74d49884044ba9c1f1c6db7d9b7c7b7c661caba +8fb357ae49932d0babdf74fc7aa7464a65d3b6a2b3acf4f550b99601d3c0215900cfd67f2b6651ef94cfc323bac79fae +9906f2fa25c0290775aa001fb6198113d53804262454ae8b83ef371b5271bde189c0460a645829cb6c59f9ee3a55ce4d +8f4379b3ebb50e052325b27655ca6a82e6f00b87bf0d2b680d205dd2c7afdc9ff32a9047ae71a1cdf0d0ce6b9474d878 +a85534e88c2bd43c043792eaa75e50914b21741a566635e0e107ae857aed0412035f7576cf04488ade16fd3f35fdbb87 +b4ce93199966d3c23251ca7f28ec5af7efea1763d376b0385352ffb2e0a462ef95c69940950278cf0e3dafd638b7bd36 +b10cb3d0317dd570aa73129f4acf63c256816f007607c19b423fb42f65133ce21f2f517e0afb41a5378cccf893ae14d0 +a9b231c9f739f7f914e5d943ed9bff7eba9e2c333fbd7c34eb1648a362ee01a01af6e2f7c35c9fe962b11152cddf35de +99ff6a899e156732937fb81c0cced80ae13d2d44c40ba99ac183aa246103b31ec084594b1b7feb96da58f4be2dd5c0ed +8748d15d18b75ff2596f50d6a9c4ce82f61ecbcee123a6ceae0e43cab3012a29b6f83cf67b48c22f6f9d757c6caf76b2 +b88ab05e4248b7fb634cf640a4e6a945d13e331237410f7217d3d17e3e384ddd48897e7a91e4516f1b9cbd30f35f238b +8d826deaeeb84a3b2d2c04c2300ca592501f992810582d6ae993e0d52f6283a839dba66c6c72278cff5871802b71173b +b36fed027c2f05a5ef625ca00b0364b930901e9e4420975b111858d0941f60e205546474bb25d6bfa6928d37305ae95f +af2fcfc6b87967567e8b8a13a4ed914478185705724e56ce68fb2df6d1576a0cf34a61e880997a0d35dc2c3276ff7501 +ac351b919cd1fbf106feb8af2c67692bfcddc84762d18cea681cfa7470a5644839caace27efee5f38c87d3df306f4211 +8d6665fb1d4d8d1fa23bd9b8a86e043b8555663519caac214d1e3e3effbc6bee7f2bcf21e645f77de0ced279d69a8a8b +a9fc1c2061756b2a1a169c1b149f212ff7f0d2488acd1c5a0197eba793cffa593fc6d1d1b40718aa75ca3ec77eff10e1 +aff64f0fa009c7a6cf0b8d7a22ddb2c8170c3cb3eec082e60d5aadb00b0040443be8936d728d99581e33c22178c41c87 +82e0b181adc5e3b1c87ff8598447260e839d53debfae941ebea38265575546c3a74a14b4325a030833a62ff6c52d9365 +b7ad43cbb22f6f892c2a1548a41dc120ab1f4e1b8dea0cb6272dd9cb02054c542ecabc582f7e16de709d48f5166cae86 +985e0c61094281532c4afb788ecb2dfcba998e974b5d4257a22040a161883908cdd068fe80f8eb49b8953cfd11acf43a +ae46895c6d67ea6d469b6c9c07b9e5d295d9ae73b22e30da4ba2c973ba83a130d7eef39717ec9d0f36e81d56bf742671 +8600177ea1f7e7ef90514b38b219a37dedfc39cb83297e4c7a5b479817ef56479d48cf6314820960c751183f6edf8b0e +b9208ec1c1d7a1e99b59c62d3e4e61dfb706b0e940d09d3abfc3454c19749083260614d89cfd7e822596c3cdbcc6bb95 +a1e94042c796c2b48bc724352d2e9f3a22291d9a34705993357ddb6adabd76da6fc25dac200a8cb0b5bbd99ecddb7af6 +b29c3adedd0bcad8a930625bc4dfdc3552a9afd5ca6dd9c0d758f978068c7982b50b711aa0eb5b97f2b84ee784637835 +af0632a238bb1f413c7ea8e9b4c3d68f2827bd2e38cd56024391fba6446ac5d19a780d0cfd4a78fe497d537b766a591a +aaf6e7f7d54f8ef5e2e45dd59774ecbeecf8683aa70483b2a75be6a6071b5981bbaf1627512a65d212817acdfab2e428 +8c751496065da2e927cf492aa5ca9013b24f861d5e6c24b30bbf52ec5aaf1905f40f9a28175faef283dd4ed4f2182a09 +8952377d8e80a85cf67d6b45499f3bad5fd452ea7bcd99efc1b066c4720d8e5bff1214cea90fd1f972a7f0baac3d29be +a1946ee543d1a6e21f380453be4d446e4130950c5fc3d075794eb8260f6f52d0a795c1ff91d028a648dc1ce7d9ab6b47 +89f3fefe37af31e0c17533d2ca1ce0884cc1dc97c15cbfab9c331b8debd94781c9396abef4bb2f163d09277a08d6adf0 +a2753f1e6e1a154fb117100a5bd9052137add85961f8158830ac20541ab12227d83887d10acf7fd36dcaf7c2596d8d23 +814955b4198933ee11c3883863b06ff98c7eceb21fc3e09df5f916107827ccf3323141983e74b025f46ae00284c9513b +8cc5c6bb429073bfef47cae7b3bfccb0ffa076514d91a1862c6bda4d581e0df87db53cc6c130bf8a7826304960f5a34e +909f22c1f1cdc87f7be7439c831a73484a49acbf8f23d47087d7cf867c64ef61da3bde85dc57d705682b4c3fc710d36e +8048fee7f276fcd504aed91284f28e73693615e0eb3858fa44bcf79d7285a9001c373b3ef71d9a3054817ba293ebe28c +94400e5cf5d2700ca608c5fe35ce14623f71cc24959f2bc27ca3684092850f76b67fb1f07ca9e5b2ca3062cf8ad17bd4 +81c2ae7d4d1b17f8b6de6a0430acc0d58260993980fe48dc2129c4948269cdc74f9dbfbf9c26b19360823fd913083d48 +8c41fe765128e63f6889d6a979f6a4342300327c8b245a8cfe3ecfbcac1e09c3da30e2a1045b24b78efc6d6d50c8c6ac +a5dd4ae51ae48c8be4b218c312ade226cffce671cf121cb77810f6c0990768d6dd767badecb5c69921d5574d5e8433d3 +b7642e325f4ba97ae2a39c1c9d97b35aafd49d53dba36aed3f3cb0ca816480b3394079f46a48252d46596559c90f4d58 +ae87375b40f35519e7bd4b1b2f73cd0b329b0c2cb9d616629342a71c6c304338445eda069b78ea0fbe44087f3de91e09 +b08918cb6f736855e11d3daca1ddfbdd61c9589b203b5493143227bf48e2c77c2e8c94b0d1aa2fab2226e0eae83f2681 +ac36b84a4ac2ebd4d6591923a449c564e3be8a664c46092c09e875c2998eba16b5d32bfd0882fd3851762868e669f0b1 +a44800a3bb192066fa17a3f29029a23697240467053b5aa49b9839fb9b9b8b12bcdcbfc557f024b61f4f51a9aacdefcb +9064c688fec23441a274cdf2075e5a449caf5c7363cc5e8a5dc9747183d2e00a0c69f2e6b3f6a7057079c46014c93b3b +aa367b021469af9f5b764a79bb3afbe2d87fe1e51862221672d1a66f954b165778b7c27a705e0f93841fab4c8468344d +a1a8bfc593d4ab71f91640bc824de5c1380ab2591cfdafcbc78a14b32de3c0e15f9d1b461d85c504baa3d4232c16bb53 +97df48da1799430f528184d30b6baa90c2a2f88f34cdfb342d715339c5ebd6d019aa693cea7c4993daafc9849063a3aa +abd923831fbb427e06e0dd335253178a9e5791395c84d0ab1433c07c53c1209161097e9582fb8736f8a60bde62d8693e +84cd1a43f1a438b43dc60ffc775f646937c4f6871438163905a3cebf1115f814ccd38a6ccb134130bff226306e412f32 +91426065996b0743c5f689eb3ca68a9f7b9e4d01f6c5a2652b57fa9a03d8dc7cd4bdbdab0ca5a891fee1e97a7f00cf02 +a4bee50249db3df7fd75162b28f04e57c678ba142ce4d3def2bc17bcb29e4670284a45f218dad3969af466c62a903757 +83141ebcc94d4681404e8b67a12a46374fded6df92b506aff3490d875919631408b369823a08b271d006d5b93136f317 +a0ea1c8883d58d5a784da3d8c8a880061adea796d7505c1f903d07c287c5467f71e4563fc0faafbc15b5a5538b0a7559 +89d9d480574f201a87269d26fb114278ed2c446328df431dc3556e3500e80e4cd01fcac196a2459d8646361ebda840df +8bf302978973632dd464bec819bdb91304712a3ec859be071e662040620422c6e75eba6f864f764cffa2799272efec39 +922f666bc0fd58b6d7d815c0ae4f66d193d32fc8382c631037f59eeaeae9a8ca6c72d08e72944cf9e800b8d639094e77 +81ad8714f491cdff7fe4399f2eb20e32650cff2999dd45b9b3d996d54a4aba24cc6c451212e78c9e5550368a1a38fb3f +b58fcf4659d73edb73175bd9139d18254e94c3e32031b5d4b026f2ed37aa19dca17ec2eb54c14340231615277a9d347e +b365ac9c2bfe409b710928c646ea2fb15b28557e0f089d39878e365589b9d1c34baf5566d20bb28b33bb60fa133f6eff +8fcae1d75b53ab470be805f39630d204853ca1629a14158bac2f52632277d77458dec204ff84b7b2d77e641c2045be65 +a03efa6bebe84f4f958a56e2d76b5ba4f95dd9ed7eb479edc7cc5e646c8d4792e5b0dfc66cc86aa4b4afe2f7a4850760 +af1c823930a3638975fb0cc5c59651771b2719119c3cd08404fbd4ce77a74d708cefbe3c56ea08c48f5f10e6907f338f +8260c8299b17898032c761c325ac9cabb4c5b7e735de81eacf244f647a45fb385012f4f8df743128888c29aefcaaad16 +ab2f37a573c82e96a8d46198691cd694dfa860615625f477e41f91b879bc58a745784fccd8ffa13065834ffd150d881d +986c746c9b4249352d8e5c629e8d7d05e716b3c7aab5e529ca969dd1e984a14b5be41528baef4c85d2369a42d7209216 +b25e32da1a8adddf2a6080725818b75bc67240728ad1853d90738485d8924ea1e202df0a3034a60ffae6f965ec55cf63 +a266e627afcebcefea6b6b44cbc50f5c508f7187e87d047b0450871c2a030042c9e376f3ede0afcf9d1952f089582f71 +86c3bbca4c0300606071c0a80dbdec21ce1dd4d8d4309648151c420854032dff1241a1677d1cd5de4e4de4385efda986 +b9a21a1fe2d1f3273a8e4a9185abf2ff86448cc98bfa435e3d68306a2b8b4a6a3ea33a155be3cb62a2170a86f77679a5 +b117b1ea381adce87d8b342cba3a15d492ff2d644afa28f22424cb9cbc820d4f7693dfc1a4d1b3697046c300e1c9b4c8 +9004c425a2e68870d6c69b658c344e3aa3a86a8914ee08d72b2f95c2e2d8a4c7bb0c6e7e271460c0e637cec11117bf8e +86a18aa4783b9ebd9131580c8b17994825f27f4ac427b0929a1e0236907732a1c8139e98112c605488ee95f48bbefbfc +84042243b955286482ab6f0b5df4c2d73571ada00716d2f737ca05a0d2e88c6349e8ee9e67934cfee4a1775dbf7f4800 +92c2153a4733a62e4e1d5b60369f3c26777c7d01cd3c8679212660d572bd3bac9b8a8a64e1f10f7dbf5eaa7579c4e423 +918454b6bb8e44a2afa144695ba8d48ae08d0cdfef4ad078f67709eddf3bb31191e8b006f04e82ea45a54715ef4d5817 +acf0b54f6bf34cf6ed6c2b39cf43194a40d68de6bcf1e4b82c34c15a1343e9ac3737885e1a30b78d01fa3a5125463db8 +a7d60dbe4b6a7b054f7afe9ee5cbbfeca0d05dc619e6041fa2296b549322529faddb8a11e949562309aecefb842ac380 +91ffb53e6d7e5f11159eaf13e783d6dbdfdb1698ed1e6dbf3413c6ea23492bbb9e0932230a9e2caac8fe899a17682795 +b6e8d7be5076ee3565d5765a710c5ecf17921dd3cf555c375d01e958a365ae087d4a88da492a5fb81838b7b92bf01143 +a8c6b763de2d4b2ed42102ef64eccfef31e2fb2a8a2776241c82912fa50fc9f77f175b6d109a97ede331307c016a4b1a +99839f86cb700c297c58bc33e28d46b92931961548deac29ba8df91d3e11721b10ea956c8e16984f9e4acf1298a79b37 +8c2e2c338f25ea5c25756b7131cde0d9a2b35abf5d90781180a00fe4b8e64e62590dc63fe10a57fba3a31c76d784eb01 +9687d7df2f41319ca5469d91978fed0565a5f11f829ebadaa83db92b221755f76c6eacd7700735e75c91e257087512e3 +8795fdfb7ff8439c58b9bf58ed53873d2780d3939b902b9ddaaa4c99447224ced9206c3039a23c2c44bcc461e2bb637f +a803697b744d2d087f4e2307218d48fa88620cf25529db9ce71e2e3bbcc65bac5e8bb9be04777ef7bfb5ed1a5b8e6170 +80f3d3efbbb9346ddd413f0a8e36b269eb5d7ff6809d5525ff9a47c4bcab2c01b70018b117f6fe05253775612ff70c6b +9050e0e45bcc83930d4c505af35e5e4d7ca01cd8681cba92eb55821aececcebe32bb692ebe1a4daac4e7472975671067 +8d206812aac42742dbaf233e0c080b3d1b30943b54b60283515da005de05ea5caa90f91fedcfcba72e922f64d7040189 +a2d44faaeb2eff7915c83f32b13ca6f31a6847b1c1ce114ea240bac3595eded89f09b2313b7915ad882292e2b586d5b4 +961776c8576030c39f214ea6e0a3e8b3d32f023d2600958c098c95c8a4e374deeb2b9dc522adfbd6bda5949bdc09e2a2 +993fa7d8447407af0fbcd9e6d77f815fa5233ab00674efbcf74a1f51c37481445ae291cc7b76db7c178f9cb0e570e0fc +abd5b1c78e05f9d7c8cc99bdaef8b0b6a57f2daf0f02bf492bec48ea4a27a8f1e38b5854da96efff11973326ff980f92 +8f15af4764bc275e6ccb892b3a4362cacb4e175b1526a9a99944e692fe6ccb1b4fc19abf312bb2a089cb1f344d91a779 +a09b27ccd71855512aba1d0c30a79ffbe7f6707a55978f3ced50e674b511a79a446dbc6d7946add421ce111135a460af +94b2f98ce86a9271fbd4153e1fc37de48421fe3490fb3840c00f2d5a4d0ba8810c6a32880b002f6374b59e0a7952518b +8650ac644f93bbcb88a6a0f49fee2663297fd4bc6fd47b6a89b9d8038d32370438ab3a4775ec9b58cb10aea8a95ef7b6 +95e5c2f2e84eed88c6980bbba5a1c0bb375d5a628bff006f7516d45bb7d723da676add4fdd45956f312e7bab0f052644 +b3278a3fa377ac93af7cfc9453f8cb594aae04269bbc99d2e0e45472ff4b6a2f97a26c4c57bf675b9d86f5e77a5d55d1 +b4bcbe6eb666a206e2ea2f877912c1d3b5bdbd08a989fc4490eb06013e1a69ad1ba08bcdac048bf29192312be399077b +a76d70b78c99fffcbf9bb9886eab40f1ea4f99a309710b660b64cbf86057cbcb644d243f6e341711bb7ef0fedf0435a7 +b2093c1ee945dca7ac76ad5aed08eae23af31dd5a77c903fd7b6f051f4ab84425d33a03c3d45bf2907bc93c02d1f3ad8 +904b1f7534e053a265b22d20be859912b9c9ccb303af9a8d6f1d8f6ccdc5c53eb4a45a1762b880d8444d9be0cd55e7f9 +8f664a965d65bc730c9ef1ec7467be984d4b8eb46bd9b0d64e38e48f94e6e55dda19aeac82cbcf4e1473440e64c4ca18 +8bcee65c4cc7a7799353d07b114c718a2aae0cd10a3f22b7eead5185d159dafd64852cb63924bf87627d176228878bce +8c78f2e3675096fef7ebaa898d2615cd50d39ca3d8f02b9bdfb07e67da648ae4be3da64838dffc5935fd72962c4b96c7 +8c40afd3701629421fec1df1aac4e849384ef2e80472c0e28d36cb1327acdf2826f99b357f3d7afdbc58a6347fc40b3c +a197813b1c65a8ea5754ef782522a57d63433ef752215ecda1e7da76b0412ee619f58d904abd2e07e0c097048b6ae1dd +a670542629e4333884ad7410f9ea3bd6f988df4a8f8a424ca74b9add2312586900cf9ae8bd50411f9146e82626b4af56 +a19875cc07ab84e569d98b8b67fb1dbbdfb59093c7b748fae008c8904a6fd931a63ca8d03ab5fea9bc8d263568125a9b +b57e7f68e4eb1bd04aafa917b1db1bdab759a02aa8a9cdb1cba34ba8852b5890f655645c9b4e15d5f19bf37e9f2ffe9f +8abe4e2a4f6462b6c64b3f10e45db2a53c2b0d3c5d5443d3f00a453e193df771eda635b098b6c8604ace3557514027af +8459e4fb378189b22b870a6ef20183deb816cefbf66eca1dc7e86d36a2e011537db893729f500dc154f14ce24633ba47 +930851df4bc7913c0d8c0f7bd3b071a83668987ed7c397d3d042fdc0d9765945a39a3bae83da9c88cb6b686ed8aeeb26 +8078c9e5cd05e1a8c932f8a1d835f61a248b6e7133fcbb3de406bf4ffc0e584f6f9f95062740ba6008d98348886cf76b +addff62bb29430983fe578e3709b0949cdc0d47a13a29bc3f50371a2cb5c822ce53e2448cfaa01bcb6e0aa850d5a380e +9433add687b5a1e12066721789b1db2edf9b6558c3bdc0f452ba33b1da67426abe326e9a34d207bfb1c491c18811bde1 +822beda3389963428cccc4a2918fa9a8a51cf0919640350293af70821967108cded5997adae86b33cb917780b097f1ca +a7a9f52bda45e4148ed56dd176df7bd672e9b5ed18888ccdb405f47920fdb0844355f8565cefb17010b38324edd8315f +b35c3a872e18e607b2555c51f9696a17fa18da1f924d503b163b4ec9fe22ed0c110925275cb6c93ce2d013e88f173d6a +adf34b002b2b26ab84fc1bf94e05bd8616a1d06664799ab149363c56a6e0c807fdc473327d25632416e952ea327fcd95 +ae4a6b9d22a4a3183fac29e2551e1124a8ce4a561a9a2afa9b23032b58d444e6155bb2b48f85c7b6d70393274e230db7 +a2ea3be4fc17e9b7ce3110284038d46a09e88a247b6971167a7878d9dcf36925d613c382b400cfa4f37a3ebea3699897 +8e5863786b641ce3140fbfe37124d7ad3925472e924f814ebfc45959aaf3f61dc554a597610b5defaecc85b59a99b50f +aefde3193d0f700d0f515ab2aaa43e2ef1d7831c4f7859f48e52693d57f97fa9e520090f3ed700e1c966f4b76048e57f +841a50f772956622798e5cd208dc7534d4e39eddee30d8ce133383d66e5f267e389254a0cdae01b770ecd0a9ca421929 +8fbc2bfd28238c7d47d4c03b1b910946c0d94274a199575e5b23242619b1de3497784e646a92aa03e3e24123ae4fcaba +926999579c8eec1cc47d7330112586bdca20b4149c8b2d066f527c8b9f609e61ce27feb69db67eea382649c6905efcf9 +b09f31f305efcc65589adf5d3690a76cf339efd67cd43a4e3ced7b839507466e4be72dd91f04e89e4bbef629d46e68c0 +b917361f6b95f759642638e0b1d2b3a29c3bdef0b94faa30de562e6078c7e2d25976159df3edbacbf43614635c2640b4 +8e7e8a1253bbda0e134d62bfe003a2669d471b47bd2b5cde0ff60d385d8e62279d54022f5ac12053b1e2d3aaa6910b4c +b69671a3c64e0a99d90b0ed108ce1912ff8ed983e4bddd75a370e9babde25ee1f5efb59ec707edddd46793207a8b1fe7 +910b2f4ebd37b7ae94108922b233d0920b4aba0bd94202c70f1314418b548d11d8e9caa91f2cd95aff51b9432d122b7f +82f645c90dfb52d195c1020346287c43a80233d3538954548604d09fbab7421241cde8593dbc4acc4986e0ea39a27dd9 +8fee895f0a140d88104ce442fed3966f58ff9d275e7373483f6b4249d64a25fb5374bbdc6bce6b5ab0270c2847066f83 +84f5bd7aab27b2509397aeb86510dd5ac0a53f2c8f73799bf720f2f87a52277f8d6b0f77f17bc80739c6a7119b7eb062 +9903ceced81099d7e146e661bcf01cbaccab5ba54366b85e2177f07e2d8621e19d9c9c3eee14b9266de6b3f9b6ea75ae +b9c16ea2a07afa32dd6c7c06df0dec39bca2067a9339e45475c98917f47e2320f6f235da353fd5e15b477de97ddc68dd +9820a9bbf8b826bec61ebf886de2c4f404c1ebdc8bab82ee1fea816d9de29127ce1852448ff717a3fe8bbfe9e92012e5 +817224d9359f5da6f2158c2c7bf9165501424f063e67ba9859a07ab72ee2ee62eb00ca6da821cfa19065c3282ca72c74 +94b95c465e6cb00da400558a3c60cfec4b79b27e602ca67cbc91aead08de4b6872d8ea096b0dc06dca4525c8992b8547 +a2b539a5bccd43fa347ba9c15f249b417997c6a38c63517ca38394976baa08e20be384a360969ff54e7e721db536b3e5 +96caf707e34f62811ee8d32ccf28d8d6ec579bc33e424d0473529af5315c456fd026aa910c1fed70c91982d51df7d3ca +8a77b73e890b644c6a142bdbac59b22d6a676f3b63ddafb52d914bb9d395b8bf5aedcbcc90429337df431ebd758a07a6 +8857830a7351025617a08bc44caec28d2fae07ebf5ffc9f01d979ce2a53839a670e61ae2783e138313929129790a51a1 +aa3e420321ed6f0aa326d28d1a10f13facec6f605b6218a6eb9cbc074801f3467bf013a456d1415a5536f12599efa3d3 +824aed0951957b00ea2f3d423e30328a3527bf6714cf9abbae84cf27e58e5c35452ba89ccc011de7c68c75d6e021d8f1 +a2e87cc06bf202e953fb1081933d8b4445527dde20e38ed1a4f440144fd8fa464a2b73e068b140562e9045e0f4bd3144 +ae3b8f06ad97d7ae3a5e5ca839efff3e4824dc238c0c03fc1a8d2fc8aa546cdfd165b784a31bb4dec7c77e9305b99a4b +b30c3e12395b1fb8b776f3ec9f87c70e35763a7b2ddc68f0f60a4982a84017f27c891a98561c830038deb033698ed7fc +874e507757cd1177d0dff0b0c62ce90130324442a33da3b2c8ee09dbca5d543e3ecfe707e9f1361e7c7db641c72794bb +b53012dd10b5e7460b57c092eaa06d6502720df9edbbe3e3f61a9998a272bf5baaac4a5a732ad4efe35d6fac6feca744 +85e6509d711515534d394e6cacbed6c81da710074d16ef3f4950bf2f578d662a494d835674f79c4d6315bced4defc5f0 +b6132b2a34b0905dcadc6119fd215419a7971fe545e52f48b768006944b4a9d7db1a74b149e2951ea48c083b752d0804 +989867da6415036d19b4bacc926ce6f4df7a556f50a1ba5f3c48eea9cefbb1c09da81481c8009331ee83f0859185e164 +960a6c36542876174d3fbc1505413e29f053ed87b8d38fef3af180491c7eff25200b45dd5fe5d4d8e63c7e8c9c00f4c8 +9040b59bd739d9cc2e8f6e894683429e4e876a8106238689ff4c22770ae5fdae1f32d962b30301fa0634ee163b524f35 +af3fcd0a45fe9e8fe256dc7eab242ef7f582dd832d147444483c62787ac820fafc6ca55d639a73f76bfa5e7f5462ab8f +b934c799d0736953a73d91e761767fdb78454355c4b15c680ce08accb57ccf941b13a1236980001f9e6195801cffd692 +8871e8e741157c2c326b22cf09551e78da3c1ec0fc0543136f581f1550f8bab03b0a7b80525c1e99812cdbf3a9698f96 +a8a977f51473a91d178ee8cfa45ffef8d6fd93ab1d6e428f96a3c79816d9c6a93cd70f94d4deda0125fd6816e30f3bea +a7688b3b0a4fc1dd16e8ba6dc758d3cfe1b7cf401c31739484c7fa253cce0967df1b290769bcefc9d23d3e0cb19e6218 +8ae84322662a57c6d729e6ff9d2737698cc2da2daeb1f39e506618750ed23442a6740955f299e4a15dda6db3e534d2c6 +a04a961cdccfa4b7ef83ced17ab221d6a043b2c718a0d6cc8e6f798507a31f10bf70361f70a049bc8058303fa7f96864 +b463e39732a7d9daec8a456fb58e54b30a6e160aa522a18b9a9e836488cce3342bcbb2e1deab0f5e6ec0a8796d77197d +b1434a11c6750f14018a2d3bcf94390e2948f4f187e93bb22070ca3e5393d339dc328cbfc3e48815f51929465ffe7d81 +84ff81d73f3828340623d7e3345553610aa22a5432217ef0ebd193cbf4a24234b190c65ca0873c22d10ea7b63bd1fbed +b6fe2723f0c47757932c2ddde7a4f8434f665612f7b87b4009c2635d56b6e16b200859a8ade49276de0ef27a2b6c970a +9742884ed7cd52b4a4a068a43d3faa02551a424136c85a9313f7cb58ea54c04aa83b0728fd741d1fe39621e931e88f8f +b7d2d65ea4d1ad07a5dee39e40d6c03a61264a56b1585b4d76fc5b2a68d80a93a42a0181d432528582bf08d144c2d6a9 +88c0f66bada89f8a43e5a6ead2915088173d106c76f724f4a97b0f6758aed6ae5c37c373c6b92cdd4aea8f6261f3a374 +81f9c43582cb42db3900747eb49ec94edb2284999a499d1527f03315fd330e5a509afa3bff659853570e9886aab5b28b +821f9d27d6beb416abf9aa5c79afb65a50ed276dbda6060103bc808bcd34426b82da5f23e38e88a55e172f5c294b4d40 +8ba307b9e7cb63a6c4f3851b321aebfdb6af34a5a4c3bd949ff7d96603e59b27ff4dc4970715d35f7758260ff942c9e9 +b142eb6c5f846de33227d0bda61d445a7c33c98f0a8365fe6ab4c1fabdc130849be597ef734305894a424ea715372d08 +a732730ae4512e86a741c8e4c87fee8a05ee840fec0e23b2e037d58dba8dde8d10a9bc5191d34d00598941becbbe467f +adce6f7c30fd221f6b10a0413cc76435c4bb36c2d60bca821e5c67409fe9dbb2f4c36ef85eb3d734695e4be4827e9fd3 +a74f00e0f9b23aff7b2527ce69852f8906dab9d6abe62ecd497498ab21e57542e12af9918d4fd610bb09e10b0929c510 +a593b6b0ef26448ce4eb3ab07e84238fc020b3cb10d542ff4b16d4e2be1bcde3797e45c9cf753b8dc3b0ffdb63984232 +aed3913afccf1aa1ac0eb4980eb8426d0baccebd836d44651fd72af00d09fac488a870223c42aca3ceb39752070405ae +b2c44c66a5ea7fde626548ba4cef8c8710191343d3dadfd3bb653ce715c0e03056a5303a581d47dde66e70ea5a2d2779 +8e5029b2ccf5128a12327b5103f7532db599846e422531869560ceaff392236434d87159f597937dbf4054f810c114f4 +82beed1a2c4477e5eb39fc5b0e773b30cfec77ef2b1bf17eadaf60eb35b6d0dd9d8cf06315c48d3546badb3f21cd0cca +90077bd6cc0e4be5fff08e5d07a5a158d36cebd1d1363125bc4fae0866ffe825b26f933d4ee5427ba5cd0c33c19a7b06 +a7ec0d8f079970e8e34f0ef3a53d3e0e45428ddcef9cc776ead5e542ef06f3c86981644f61c5a637e4faf001fb8c6b3e +ae6d4add6d1a6f90b22792bc9d40723ee6850c27d0b97eefafd5b7fd98e424aa97868b5287cc41b4fbd7023bca6a322c +831aa917533d077da07c01417feaa1408846363ba2b8d22c6116bb858a95801547dd88b7d7fa1d2e3f0a02bdeb2e103d +96511b860b07c8a5ed773f36d4aa9d02fb5e7882753bf56303595bcb57e37ccc60288887eb83bef08c657ec261a021a2 +921d2a3e7e9790f74068623de327443666b634c8443aba80120a45bba450df920b2374d96df1ce3fb1b06dd06f8cf6e3 +aa74451d51fe82b4581ead8e506ec6cd881010f7e7dd51fc388eb9a557db5d3c6721f81c151d08ebd9c2591689fbc13e +a972bfbcf4033d5742d08716c927c442119bdae336bf5dff914523b285ccf31953da2733759aacaa246a9af9f698342c +ad1fcd0cae0e76840194ce4150cb8a56ebed728ec9272035f52a799d480dfc85840a4d52d994a18b6edb31e79be6e8ad +a2c69fe1d36f235215432dad48d75887a44c99dfa0d78149acc74087da215a44bdb5f04e6eef88ff7eff80a5a7decc77 +a94ab2af2b6ee1bc6e0d4e689ca45380d9fbd3c5a65b9bd249d266a4d4c07bf5d5f7ef2ae6000623aee64027892bf8fe +881ec1fc514e926cdc66480ac59e139148ff8a2a7895a49f0dff45910c90cdda97b66441a25f357d6dd2471cddd99bb3 +884e6d3b894a914c8cef946a76d5a0c8351843b2bffa2d1e56c6b5b99c84104381dd1320c451d551c0b966f4086e60f9 +817c6c10ce2677b9fc5223500322e2b880583254d0bb0d247d728f8716f5e05c9ff39f135854342a1afecd9fbdcf7c46 +aaf4a9cb686a14619aa1fc1ac285dd3843ac3dd99f2b2331c711ec87b03491c02f49101046f3c5c538dc9f8dba2a0ac2 +97ecea5ce53ca720b5d845227ae61d70269a2f53540089305c86af35f0898bfd57356e74a8a5e083fa6e1ea70080bd31 +a22d811e1a20a75feac0157c418a4bfe745ccb5d29466ffa854dca03e395b6c3504a734341746b2846d76583a780b32e +940cbaa0d2b2db94ae96b6b9cf2deefbfd059e3e5745de9aec4a25f0991b9721e5cd37ef71c631575d1a0c280b01cd5b +ae33cb4951191258a11044682de861bf8d92d90ce751b354932dd9f3913f542b6a0f8a4dc228b3cd9244ac32c4582832 +a580df5e58c4274fe0f52ac2da1837e32f5c9db92be16c170187db4c358f43e5cfdda7c5911dcc79d77a5764e32325f5 +81798178cb9d8affa424f8d3be67576ba94d108a28ccc01d330c51d5a63ca45bb8ca63a2f569b5c5fe1303cecd2d777f +89975b91b94c25c9c3660e4af4047a8bacf964783010820dbc91ff8281509379cb3b24c25080d5a01174dd9a049118d5 +a7327fcb3710ed3273b048650bde40a32732ef40a7e58cf7f2f400979c177944c8bc54117ba6c80d5d4260801dddab79 +92b475dc8cb5be4b90c482f122a51bcb3b6c70593817e7e2459c28ea54a7845c50272af38119406eaadb9bcb993368d0 +9645173e9ecefc4f2eae8363504f7c0b81d85f8949a9f8a6c01f2d49e0a0764f4eacecf3e94016dd407fc14494fce9f9 +9215fd8983d7de6ae94d35e6698226fc1454977ae58d42d294be9aad13ac821562ad37d5e7ee5cdfe6e87031d45cd197 +810360a1c9b88a9e36f520ab5a1eb8bed93f52deefbe1312a69225c0a08edb10f87cc43b794aced9c74220cefcc57e7d +ad7e810efd61ed4684aeda9ed8bb02fb9ae4b4b63fda8217d37012b94ff1b91c0087043bfa4e376f961fff030c729f3b +8b07c95c6a06db8738d10bb03ec11b89375c08e77f0cab7e672ce70b2685667ca19c7e1c8b092821d31108ea18dfd4c7 +968825d025ded899ff7c57245250535c732836f7565eab1ae23ee7e513201d413c16e1ba3f5166e7ac6cf74de8ceef4f +908243370c5788200703ade8164943ad5f8c458219186432e74dbc9904a701ea307fd9b94976c866e6c58595fd891c4b +959969d16680bc535cdc6339e6186355d0d6c0d53d7bbfb411641b9bf4b770fd5f575beef5deec5c4fa4d192d455c350 +ad177f4f826a961adeac76da40e2d930748effff731756c797eddc4e5aa23c91f070fb69b19221748130b0961e68a6bb +82f8462bcc25448ef7e0739425378e9bb8a05e283ce54aae9dbebaf7a3469f57833c9171672ad43a79778366c72a5e37 +a28fb275b1845706c2814d9638573e9bc32ff552ebaed761fe96fdbce70395891ca41c400ae438369264e31a2713b15f +8a9c613996b5e51dadb587a787253d6081ea446bf5c71096980bf6bd3c4b69905062a8e8a3792de2d2ece3b177a71089 +8d5aefef9f60cb27c1db2c649221204dda48bb9bf8bf48f965741da051340e8e4cab88b9d15c69f3f84f4c854709f48a +93ebf2ca6ad85ab6deace6de1a458706285b31877b1b4d7dcb9d126b63047efaf8c06d580115ec9acee30c8a7212fa55 +b3ee46ce189956ca298057fa8223b7fd1128cf52f39159a58bca03c71dd25161ac13f1472301f72aef3e1993fe1ab269 +a24d7a8d066504fc3f5027ccb13120e2f22896860e02c45b5eba1dbd512d6a17c28f39155ea581619f9d33db43a96f92 +ae9ceacbfe12137db2c1a271e1b34b8f92e4816bad1b3b9b6feecc34df0f8b3b0f7ed0133acdf59c537d43d33fc8d429 +83967e69bf2b361f86361bd705dce0e1ad26df06da6c52b48176fe8dfcbeb03c462c1a4c9e649eff8c654b18c876fdef +9148e6b814a7d779c19c31e33a068e97b597de1f8100513db3c581190513edc4d544801ce3dd2cf6b19e0cd6daedd28a +94ccdafc84920d320ed22de1e754adea072935d3c5f8c2d1378ebe53d140ea29853f056fb3fb1e375846061a038cc9bc +afb43348498c38b0fa5f971b8cdd3a62c844f0eb52bc33daf2f67850af0880fce84ecfb96201b308d9e6168a0d443ae3 +86d5736520a83538d4cd058cc4b4e84213ed00ebd6e7af79ae787adc17a92ba5359e28ba6c91936d967b4b28d24c3070 +b5210c1ff212c5b1e9ef9126e08fe120a41e386bb12c22266f7538c6d69c7fd8774f11c02b81fd4e88f9137b020801fe +b78cfd19f94d24e529d0f52e18ce6185cb238edc6bd43086270fd51dd99f664f43dd4c7d2fe506762fbd859028e13fcf +a6e7220598c554abdcc3fdc587b988617b32c7bb0f82c06205467dbedb58276cc07cae317a190f19d19078773f4c2bbb +b88862809487ee430368dccd85a5d72fa4d163ca4aad15c78800e19c1a95be2192719801e315d86cff7795e0544a77e4 +87ecb13a03921296f8c42ceb252d04716f10e09c93962239fcaa0a7fef93f19ab3f2680bc406170108bc583e9ff2e721 +a810cd473832b6581c36ec4cb403f2849357ba2d0b54df98ef3004b8a530c078032922a81d40158f5fb0043d56477f6e +a247b45dd85ca7fbb718b328f30a03f03c84aef2c583fbdc9fcc9eb8b52b34529e8c8f535505c10598b1b4dac3d7c647 +96ee0b91313c68bac4aa9e065ce9e1d77e51ca4cff31d6a438718c58264dee87674bd97fc5c6b8008be709521e4fd008 +837567ad073e42266951a9a54750919280a2ac835a73c158407c3a2b1904cf0d17b7195a393c71a18ad029cbd9cf79ee +a6a469c44b67ebf02196213e7a63ad0423aab9a6e54acc6fcbdbb915bc043586993454dc3cd9e4be8f27d67c1050879b +8712d380a843b08b7b294f1f06e2f11f4ad6bcc655fdde86a4d8bc739c23916f6fad2b902fe47d6212f03607907e9f0e +920adfb644b534789943cdae1bdd6e42828dda1696a440af2f54e6b97f4f97470a1c6ea9fa6a2705d8f04911d055acd1 +a161c73adf584a0061e963b062f59d90faac65c9b3a936b837a10d817f02fcabfa748824607be45a183dd40f991fe83f +874f4ecd408c76e625ea50bc59c53c2d930ee25baf4b4eca2440bfbffb3b8bc294db579caa7c68629f4d9ec24187c1ba +8bff18087f112be7f4aa654e85c71fef70eee8ae480f61d0383ff6f5ab1a0508f966183bb3fc4d6f29cb7ca234aa50d3 +b03b46a3ca3bc743a173cbc008f92ab1aedd7466b35a6d1ca11e894b9482ea9dc75f8d6db2ddd1add99bfbe7657518b7 +8b4f3691403c3a8ad9e097f02d130769628feddfa8c2b3dfe8cff64e2bed7d6e5d192c1e2ba0ac348b8585e94acd5fa1 +a0d9ca4a212301f97591bf65d5ef2b2664766b427c9dd342e23cb468426e6a56be66b1cb41fea1889ac5d11a8e3c50a5 +8c93ed74188ca23b3df29e5396974b9cc135c91fdefdea6c0df694c8116410e93509559af55533a3776ac11b228d69b1 +82dd331fb3f9e344ebdeeb557769b86a2cc8cc38f6c298d7572a33aea87c261afa9dbd898989139b9fc16bc1e880a099 +a65faedf326bcfd8ef98a51410c78b021d39206704e8291cd1f09e096a66b9b0486be65ff185ca224c45918ac337ddeb +a188b37d363ac072a766fd5d6fa27df07363feff1342217b19e3c37385e42ffde55e4be8355aceaa2f267b6d66b4ac41 +810fa3ba3e96d843e3bafd3f2995727f223d3567c8ba77d684c993ba1773c66551eb5009897c51b3fe9b37196984f5ec +87631537541852da323b4353af45a164f68b304d24c01183bf271782e11687f3fcf528394e1566c2a26cb527b3148e64 +b721cb2b37b3c477a48e3cc0044167d51ff568a5fd2fb606e5aec7a267000f1ddc07d3db919926ae12761a8e017c767c +904dfad4ba2cc1f6e60d1b708438a70b1743b400164cd981f13c064b8328d5973987d4fb9cf894068f29d3deaf624dfb +a70491538893552c20939fae6be2f07bfa84d97e2534a6bbcc0f1729246b831103505e9f60e97a8fa7d2e6c1c2384579 +8726cf1b26b41f443ff7485adcfddc39ace2e62f4d65dd0bb927d933e262b66f1a9b367ded5fbdd6f3b0932553ac1735 +ae8a11cfdf7aa54c08f80cb645e3339187ab3886babe9fae5239ba507bb3dd1c0d161ca474a2df081dcd3d63e8fe445e +92328719e97ce60e56110f30a00ac5d9c7a2baaf5f8d22355d53c1c77941e3a1fec7d1405e6fbf8959665fe2ba7a8cad +8d9d6255b65798d0018a8cccb0b6343efd41dc14ff2058d3eed9451ceaad681e4a0fa6af67b0a04318aa628024e5553d +b70209090055459296006742d946a513f0cba6d83a05249ee8e7a51052b29c0ca9722dc4af5f9816a1b7938a5dac7f79 +aab7b766b9bf91786dfa801fcef6d575dc6f12b77ecc662eb4498f0312e54d0de9ea820e61508fc8aeee5ab5db529349 +a8104b462337748b7f086a135d0c3f87f8e51b7165ca6611264b8fb639d9a2f519926cb311fa2055b5fadf03da70c678 +b0d2460747d5d8b30fc6c6bd0a87cb343ddb05d90a51b465e8f67d499cfc5e3a9e365da05ae233bbee792cdf90ec67d5 +aa55f5bf3815266b4a149f85ed18e451c93de9163575e3ec75dd610381cc0805bb0a4d7c4af5b1f94d10231255436d2c +8d4c6a1944ff94426151909eb5b99cfd92167b967dabe2bf3aa66bb3c26c449c13097de881b2cfc1bf052862c1ef7b03 +8862296162451b9b6b77f03bf32e6df71325e8d7485cf3335d66fd48b74c2a8334c241db8263033724f26269ad95b395 +901aa96deb26cda5d9321190ae6624d357a41729d72ef1abfd71bebf6139af6d690798daba53b7bc5923462115ff748a +96c195ec4992728a1eb38cdde42d89a7bce150db43adbc9e61e279ea839e538deec71326b618dd39c50d589f78fc0614 +b6ff8b8aa0837b99a1a8b46fb37f20ad4aecc6a98381b1308697829a59b8442ffc748637a88cb30c9b1f0f28a926c4f6 +8d807e3dca9e7bef277db1d2cfb372408dd587364e8048b304eff00eacde2c723bfc84be9b98553f83cba5c7b3cba248 +8800c96adb0195c4fc5b24511450dee503c32bf47044f5e2e25bd6651f514d79a2dd9b01cd8c09f3c9d3859338490f57 +89fe366096097e38ec28dd1148887112efa5306cc0c3da09562aafa56f4eb000bf46ff79bf0bdd270cbde6bf0e1c8957 +af409a90c2776e1e7e3760b2042507b8709e943424606e31e791d42f17873a2710797f5baaab4cc4a19998ef648556b0 +8d761863c9b6edbd232d35ab853d944f5c950c2b643f84a1a1327ebb947290800710ff01dcfa26dc8e9828481240e8b1 +90b95e9be1e55c463ed857c4e0617d6dc3674e99b6aa62ed33c8e79d6dfcf7d122f4f4cc2ee3e7c5a49170cb617d2e2e +b3ff381efefabc4db38cc4727432e0301949ae4f16f8d1dea9b4f4de611cf5a36d84290a0bef160dac4e1955e516b3b0 +a8a84564b56a9003adcadb3565dc512239fc79572762cda7b5901a255bc82656bb9c01212ad33d6bef4fbbce18dacc87 +90a081890364b222eef54bf0075417f85e340d2fec8b7375995f598aeb33f26b44143ebf56fca7d8b4ebb36b5747b0eb +ade6ee49e1293224ddf2d8ab7f14bb5be6bc6284f60fd5b3a1e0cf147b73cff57cf19763b8a36c5083badc79c606b103 +b2fa99806dd2fa3de09320b615a2570c416c9bcdb052e592b0aead748bbe407ec9475a3d932ae48b71c2627eb81986a6 +91f3b7b73c8ccc9392542711c45fe6f236057e6efad587d661ad5cb4d6e88265f86b807bb1151736b1009ab74fd7acb4 +8800e2a46af96696dfbdcbf2ca2918b3dcf28ad970170d2d1783b52b8d945a9167d052beeb55f56c126da7ffa7059baa +9862267a1311c385956b977c9aa08548c28d758d7ba82d43dbc3d0a0fd1b7a221d39e8399997fea9014ac509ff510ac4 +b7d24f78886fd3e2d283e18d9ad5a25c1a904e7d9b9104bf47da469d74f34162e27e531380dbbe0a9d051e6ffd51d6e7 +b0f445f9d143e28b9df36b0f2c052da87ee2ca374d9d0fbe2eff66ca6fe5fe0d2c1951b428d58f7314b7e74e45d445ea +b63fc4083eabb8437dafeb6a904120691dcb53ce2938b820bb553da0e1eecd476f72495aacb72600cf9cad18698fd3db +b9ffd8108eaebd582d665f8690fe8bb207fd85185e6dd9f0b355a09bac1bbff26e0fdb172bc0498df025414e88fe2eda +967ed453e1f1a4c5b7b6834cc9f75c13f6889edc0cc91dc445727e9f408487bbf05c337103f61397a10011dfbe25d61d +98ceb673aff36e1987d5521a3984a07079c3c6155974bb8b413e8ae1ce84095fe4f7862fba7aefa14753eb26f2a5805f +85f01d28603a8fdf6ce6a50cb5c44f8a36b95b91302e3f4cd95c108ce8f4d212e73aec1b8d936520d9226802a2bd9136 +88118e9703200ca07910345fbb789e7a8f92bd80bbc79f0a9e040e8767d33df39f6eded403a9b636eabf9101e588482a +90833a51eef1b10ed74e8f9bbd6197e29c5292e469c854eed10b0da663e2bceb92539710b1858bbb21887bd538d28d89 +b513b905ec19191167c6193067b5cfdf5a3d3828375360df1c7e2ced5815437dfd37f0c4c8f009d7fb29ff3c8793f560 +b1b6d405d2d18f9554b8a358cc7e2d78a3b34269737d561992c8de83392ac9a2857be4bf15de5a6c74e0c9d0f31f393c +b828bd3e452b797323b798186607849f85d1fb20c616833c0619360dfd6b3e3aa000fd09dafe4b62d74abc41072ff1a9 +8efde67d0cca56bb2c464731879c9ac46a52e75bac702a63200a5e192b4f81c641f855ca6747752b84fe469cb7113b6c +b2762ba1c89ac3c9a983c242e4d1c2610ff0528585ed5c0dfc8a2c0253551142af9b59f43158e8915a1da7cc26b9df67 +8a3f1157fb820d1497ef6b25cd70b7e16bb8b961b0063ad340d82a79ee76eb2359ca9e15e6d42987ed7f154f5eeaa2da +a75e29f29d38f09c879f971c11beb5368affa084313474a5ecafa2896180b9e47ea1995c2733ec46f421e395a1d9cffe +8e8c3dd3e7196ef0b4996b531ec79e4a1f211db5d5635e48ceb80ff7568b2ff587e845f97ee703bb23a60945ad64314a +8e7f32f4a3e3c584af5e3d406924a0aa34024c42eca74ef6cc2a358fd3c9efaf25f1c03aa1e66bb94b023a2ee2a1cace +ab7dce05d59c10a84feb524fcb62478906b3fa045135b23afbede3bb32e0c678d8ebe59feabccb5c8f3550ea76cae44b +b38bb4b44d827f6fd3bd34e31f9186c59e312dbfadd4a7a88e588da10146a78b1f8716c91ad8b806beb8da65cab80c4c +9490ce9442bbbd05438c7f5c4dea789f74a7e92b1886a730544b55ba377840740a3ae4f2f146ee73f47c9278b0e233bc +83c003fab22a7178eed1a668e0f65d4fe38ef3900044e9ec63070c23f2827d36a1e73e5c2b883ec6a2afe2450171b3b3 +9982f02405978ddc4fca9063ebbdb152f524c84e79398955e66fe51bc7c1660ec1afc3a86ec49f58d7b7dde03505731c +ab337bd83ccdd2322088ffa8d005f450ced6b35790f37ab4534313315ee84312adc25e99cce052863a8bedee991729ed +8312ce4bec94366d88f16127a17419ef64285cd5bf9e5eda010319b48085966ed1252ed2f5a9fd3e0259b91bb65f1827 +a60d5a6327c4041b0c00a1aa2f0af056520f83c9ce9d9ccd03a0bd4d9e6a1511f26a422ea86bd858a1f77438adf07e6c +b84a0a0b030bdad83cf5202aa9afe58c9820e52483ab41f835f8c582c129ee3f34aa096d11c1cd922eda02ea1196a882 +8077d105317f4a8a8f1aadeb05e0722bb55f11abcb490c36c0904401107eb3372875b0ac233144829e734f0c538d8c1d +9202503bd29a6ec198823a1e4e098f9cfe359ed51eb5174d1ca41368821bfeebcbd49debfd02952c41359d1c7c06d2b1 +abc28c155e09365cb77ffead8dc8f602335ef93b2f44e4ef767ce8fc8ef9dd707400f3a722e92776c2e0b40192c06354 +b0f6d1442533ca45c9399e0a63a11f85ff288d242cea6cb3b68c02e77bd7d158047cae2d25b3bcd9606f8f66d9b32855 +b01c3d56a0db84dc94575f4b6ee2de4beca3230e86bed63e2066beb22768b0a8efb08ebaf8ac3dedb5fe46708b084807 +8c8634b0432159f66feaabb165842d1c8ac378f79565b1b90c381aa8450eb4231c3dad11ec9317b9fc2b155c3a771e32 +8e67f623d69ecd430c9ee0888520b6038f13a2b6140525b056dc0951f0cfed2822e62cf11d952a483107c5c5acac4826 +9590bb1cba816dd6acd5ac5fba5142c0a19d53573e422c74005e0bcf34993a8138c83124cad35a3df65879dba6134edd +801cd96cde0749021a253027118d3ea135f3fcdbe895db08a6c145641f95ebd368dd6a1568d995e1d0084146aebe224a +848b5d196427f6fc1f762ee3d36e832b64a76ec1033cfedc8b985dea93932a7892b8ef1035c653fb9dcd9ab2d9a44ac8 +a1017eb83d5c4e2477e7bd2241b2b98c4951a3b391081cae7d75965cadc1acaec755cf350f1f3d29741b0828e36fedea +8d6d2785e30f3c29aad17bd677914a752f831e96d46caf54446d967cb2432be2c849e26f0d193a60bee161ea5c6fe90a +935c0ba4290d4595428e034b5c8001cbd400040d89ab00861108e8f8f4af4258e41f34a7e6b93b04bc253d3b9ffc13bf +aac02257146246998477921cef2e9892228590d323b839f3e64ea893b991b463bc2f47e1e5092ddb47e70b2f5bce7622 +b921fde9412970a5d4c9a908ae8ce65861d06c7679af577cf0ad0d5344c421166986bee471fd6a6cecb7d591f06ec985 +8ef4c37487b139d6756003060600bb6ebac7ea810b9c4364fc978e842f13ac196d1264fbe5af60d76ff6d9203d8e7d3f +94b65e14022b5cf6a9b95f94be5ace2711957c96f4211c3f7bb36206bd39cfbd0ea82186cab5ad0577a23214a5c86e9e +a31c166d2a2ca1d5a75a5920fef7532681f62191a50d8555fdaa63ba4581c3391cc94a536fc09aac89f64eafceec3f90 +919a8cc128de01e9e10f5d83b08b52293fdd41bde2b5ae070f3d95842d4a16e5331cf2f3d61c765570c8022403610fa4 +b23d6f8331eef100152d60483cfa14232a85ee712c8538c9b6417a5a7c5b353c2ac401390c6c215cb101f5cee6b5f43e +ab357160c08a18319510a571eafff154298ce1020de8e1dc6138a09fcb0fcbcdd8359f7e9386bda00b7b9cdea745ffdc +ab55079aea34afa5c0bd1124b9cdfe01f325b402fdfa017301bf87812eaa811ea5798c3aaf818074d420d1c782b10ada +ade616010dc5009e7fc4f8d8b00dc716686a5fa0a7816ad9e503e15839d3b909b69d9dd929b7575376434ffec0d2bea8 +863997b97ed46898a8a014599508fa3079f414b1f4a0c4fdc6d74ae8b444afa350f327f8bfc2a85d27f9e2d049c50135 +8d602ff596334efd4925549ed95f2aa762b0629189f0df6dbb162581657cf3ea6863cd2287b4d9c8ad52813d87fcd235 +b70f68c596dcdeed92ad5c6c348578b26862a51eb5364237b1221e840c47a8702f0fbc56eb520a22c0eed99795d3903e +9628088f8e0853cefadee305a8bf47fa990c50fa96a82511bbe6e5dc81ef4b794e7918a109070f92fc8384d77ace226f +97e26a46e068b605ce96007197ecd943c9a23881862f4797a12a3e96ba2b8d07806ad9e2a0646796b1889c6b7d75188c +b1edf467c068cc163e2d6413cc22b16751e78b3312fe47b7ea82b08a1206d64415b2c8f2a677fa89171e82cc49797150 +a44d15ef18745b251429703e3cab188420e2d974de07251501799b016617f9630643fcd06f895634d8ecdd579e1bf000 +abd126df3917ba48c618ee4dbdf87df506193462f792874439043fa1b844466f6f4e0ff2e42516e63b5b23c0892b2695 +a2a67f57c4aa3c2aa1eeddbfd5009a89c26c2ce8fa3c96a64626aba19514beb125f27df8559506f737de3eae0f1fc18f +a633e0132197e6038197304b296ab171f1d8e0d0f34dcf66fe9146ac385b0239232a8470b9205a4802ab432389f4836d +a914b3a28509a906c3821463b936455d58ff45dcbe158922f9efb2037f2eb0ce8e92532d29b5d5a3fcd0d23fa773f272 +a0e1412ce4505daf1a2e59ce4f0fc0e0023e335b50d2b204422f57cd65744cc7a8ed35d5ef131a42c70b27111d3115b7 +a2339e2f2b6072e88816224fdd612c04d64e7967a492b9f8829db15367f565745325d361fd0607b0def1be384d010d9e +a7309fc41203cb99382e8193a1dcf03ac190a7ce04835304eb7e341d78634e83ea47cb15b885601956736d04cdfcaa01 +81f3ccd6c7f5b39e4e873365f8c37b214e8ab122d04a606fbb7339dc3298c427e922ec7418002561d4106505b5c399ee +92c121cf914ca549130e352eb297872a63200e99b148d88fbc9506ad882bec9d0203d65f280fb5b0ba92e336b7f932e8 +a4b330cf3f064f5b131578626ad7043ce2a433b6f175feb0b52d36134a454ca219373fd30d5e5796410e005b69082e47 +86fe5774112403ad83f9c55d58317eeb17ad8e1176d9f2f69c2afb7ed83bc718ed4e0245ceab4b377f5f062dcd4c00e7 +809d152a7e2654c7fd175b57f7928365a521be92e1ed06c05188a95864ddb25f7cab4c71db7d61bbf4cae46f3a1d96ce +b82d663e55c2a5ada7e169e9b1a87bc1c0177baf1ec1c96559b4cb1c5214ce1ddf2ab8d345014cab6402f3774235cf5a +86580af86df1bd2c385adb8f9a079e925981b7184db66fc5fe5b14cddb82e7d836b06eaeef14924ac529487b23dae111 +b5f5f4c5c94944ecc804df6ab8687d64e27d988cbfeae1ba7394e0f6adbf778c5881ead7cd8082dd7d68542b9bb4ecd5 +a6016916146c2685c46e8fdd24186394e2d5496e77e08c0c6a709d4cd7dfa97f1efcef94922b89196819076a91ad37b5 +b778e7367ded3b6eab53d5fc257f7a87e8faf74a593900f2f517220add2125be3f6142022660d8181df8d164ad9441ce +8581b2d36abe6f553add4d24be761bec1b8efaa2929519114346615380b3c55b59e6ad86990e312f7e234d0203bdf59b +9917e74fd45c3f71a829ff5498a7f6b5599b48c098dda2339bf04352bfc7f368ccf1a407f5835901240e76452ae807d7 +afd196ce6f9335069138fd2e3d133134da253978b4ce373152c0f26affe77a336505787594022e610f8feb722f7cc1fb +a477491a1562e329764645e8f24d8e228e5ef28c9f74c6b5b3abc4b6a562c15ffb0f680d372aed04d9e1bf944dece7be +9767440d58c57d3077319d3a330e5322b9ba16981ec74a5a14d53462eab59ae7fd2b14025bfc63b268862094acb444e6 +80986d921be3513ef69264423f351a61cb48390c1be8673aee0f089076086aaebea7ebe268fd0aa7182695606116f679 +a9554c5c921c07b450ee04e34ec58e054ac1541b26ce2ce5a393367a97348ba0089f53db6660ad76b60278b66fd12e3e +95097e7d2999b3e84bf052c775581cf361325325f4a50192521d8f4693c830bed667d88f482dc1e3f833aa2bd22d2cbf +9014c91d0f85aefd28436b5228c12f6353c055a9326c7efbf5e071e089e2ee7c070fcbc84c5fafc336cbb8fa6fec1ca1 +90f57ba36ee1066b55d37384942d8b57ae00f3cf9a3c1d6a3dfee1d1af42d4b5fa9baeb0cd7e46687d1d6d090ddb931d +8e4b1db12fd760a17214c9e47f1fce6e43c0dbb4589a827a13ac61aaae93759345697bb438a00edab92e0b7b62414683 +8022a959a513cdc0e9c705e0fc04eafd05ff37c867ae0f31f6d01cddd5df86138a426cab2ff0ac8ff03a62e20f7e8f51 +914e9a38829834c7360443b8ed86137e6f936389488eccf05b4b4db7c9425611705076ecb3f27105d24b85c852be7511 +957fb10783e2bd0db1ba66b18e794df710bc3b2b05776be146fa5863c15b1ebdd39747b1a95d9564e1772cdfc4f37b8a +b6307028444daed8ed785ac9d0de76bc3fe23ff2cc7e48102553613bbfb5afe0ebe45e4212a27021c8eb870721e62a1f +8f76143597777d940b15a01b39c5e1b045464d146d9a30a6abe8b5d3907250e6c7f858ff2308f8591e8b0a7b3f3c568a +96163138ac0ce5fd00ae9a289648fd9300a0ca0f63a88481d703ecd281c06a52a3b5178e849e331f9c85ca4ba398f4cc +a63ef47c3e18245b0482596a09f488a716df3cbd0f9e5cfabed0d742843e65db8961c556f45f49762f3a6ac8b627b3ef +8cb595466552e7c4d42909f232d4063e0a663a8ef6f6c9b7ce3a0542b2459cde04e0e54c7623d404acb5b82775ac04f6 +b47fe69960eb45f399368807cff16d941a5a4ebad1f5ec46e3dc8a2e4d598a7e6114d8f0ca791e9720fd786070524e2b +89eb5ff83eea9df490e5beca1a1fbbbbcf7184a37e2c8c91ede7a1e654c81e8cd41eceece4042ea7918a4f4646b67fd6 +a84f5d155ed08b9054eecb15f689ba81e44589e6e7207a99790c598962837ca99ec12344105b16641ca91165672f7153 +a6cc8f25c2d5b2d2f220ec359e6a37a52b95fa6af6e173c65e7cd55299eff4aa9e6d9e6f2769e6459313f1f2aecb0fab +afcde944411f017a9f7979755294981e941cc41f03df5e10522ef7c7505e5f1babdd67b3bf5258e8623150062eb41d9b +8fab39f39c0f40182fcd996ade2012643fe7731808afbc53f9b26900b4d4d1f0f5312d9d40b3df8baa4739970a49c732 +ae193af9726da0ebe7df1f9ee1c4846a5b2a7621403baf8e66c66b60f523e719c30c6b4f897bb14b27d3ff3da8392eeb +8ac5adb82d852eba255764029f42e6da92dcdd0e224d387d1ef94174038db9709ac558d90d7e7c57ad4ce7f89bbfc38c +a2066b3458fdf678ee487a55dd5bfb74fde03b54620cb0e25412a89ee28ad0d685e309a51e3e4694be2fa6f1593a344c +88d031745dd0ae07d61a15b594be5d4b2e2a29e715d081649ad63605e3404b0c3a5353f0fd9fad9c05c18e93ce674fa1 +8283cfb0ef743a043f2b77ecaeba3005e2ca50435585b5dd24777ee6bce12332f85e21b446b536da38508807f0f07563 +b376de22d5f6b0af0b59f7d9764561f4244cf8ffe22890ecd3dcf2ff1832130c9b821e068c9d8773136f4796721e5963 +ae3afc50c764f406353965363840bf28ee85e7064eb9d5f0bb3c31c64ab10f48c853e942ee2c9b51bae59651eaa08c2f +948b204d103917461a01a6c57a88f2d66b476eae5b00be20ec8c747650e864bc8a83aee0aff59cb7584b7a3387e0ee48 +81ab098a082b07f896c5ffd1e4446cb7fb44804cbbf38d125208b233fc82f8ec9a6a8d8dd1c9a1162dc28ffeec0dde50 +a149c6f1312821ced2969268789a3151bdda213451760b397139a028da609c4134ac083169feb0ee423a0acafd10eceb +b0ac9e27a5dadaf523010f730b28f0ebac01f460d3bbbe277dc9d44218abb5686f4fac89ae462682fef9edbba663520a +8d0e0073cca273daaaa61b6fc54bfe5a009bc3e20ae820f6c93ba77b19eca517d457e948a2de5e77678e4241807157cb +ad61d3a2edf7c7533a04964b97499503fd8374ca64286dba80465e68fe932e96749b476f458c6fc57cb1a7ca85764d11 +90eb5e121ae46bc01a30881eaa556f46bd8457a4e80787cf634aab355082de34ac57d7f497446468225f7721e68e2a47 +8cdac557de7c42d1f3780e33dec1b81889f6352279be81c65566cdd4952d4c15d79e656cbd46035ab090b385e90245ef +82b67e61b88b84f4f4d4f65df37b3e3dcf8ec91ea1b5c008fdccd52da643adbe6468a1cfdb999e87d195afe2883a3b46 +8503b467e8f5d6048a4a9b78496c58493a462852cab54a70594ae3fd064cfd0deb4b8f336a262155d9fedcaa67d2f6fd +8db56c5ac763a57b6ce6832930c57117058e3e5a81532b7d19346346205e2ec614eb1a2ee836ef621de50a7bc9b7f040 +ad344699198f3c6e8c0a3470f92aaffc805b76266734414c298e10b5b3797ca53578de7ccb2f458f5e0448203f55282b +80602032c43c9e2a09154cc88b83238343b7a139f566d64cb482d87436b288a98f1ea244fd3bff8da3c398686a900c14 +a6385bd50ecd548cfb37174cdbb89e10025b5cadaf3cff164c95d7aef5a33e3d6a9bf0c681b9e11db9ef54ebeee2a0c1 +abf2d95f4aa34b0581eb9257a0cc8462b2213941a5deb8ba014283293e8b36613951b61261cc67bbd09526a54cbbff76 +a3d5de52f48df72c289ff713e445991f142390798cd42bd9d9dbefaee4af4f5faf09042d126b975cf6b98711c3072553 +8e627302ff3d686cff8872a1b7c2a57b35f45bf2fc9aa42b049d8b4d6996a662b8e7cbac6597f0cb79b0cc4e29fbf133 +8510702e101b39a1efbf4e504e6123540c34b5689645e70d0bac1ecc1baf47d86c05cef6c4317a4e99b4edaeb53f2d00 +aa173f0ecbcc6088f878f8726d317748c81ebf501bba461f163b55d66099b191ec7c55f7702f351a9c8eb42cfa3280e2 +b560a697eafab695bcef1416648a0a664a71e311ecbe5823ae903bd0ed2057b9d7574b9a86d3fe22aa3e6ddce38ea513 +8df6304a3d9cf40100f3f687575419c998cd77e5cc27d579cf4f8e98642de3609af384a0337d145dd7c5635172d26a71 +8105c7f3e4d30a29151849673853b457c1885c186c132d0a98e63096c3774bc9deb956cf957367e633d0913680bda307 +95373fc22c0917c3c2044ac688c4f29a63ed858a45c0d6d2d0fe97afd6f532dcb648670594290c1c89010ecc69259bef +8c2fae9bcadab341f49b55230310df93cac46be42d4caa0d42e45104148a91e527af1b4209c0d972448162aed28fab64 +b05a77baab70683f76209626eaefdda2d36a0b66c780a20142d23c55bd479ddd4ad95b24579384b6cf62c8eb4c92d021 +8e6bc6a7ea2755b4aaa19c1c1dee93811fcde514f03485fdc3252f0ab7f032c315614f6336e57cea25dcfb8fb6084eeb +b656a27d06aade55eadae2ad2a1059198918ea6cc3fd22c0ed881294d34d5ac7b5e4700cc24350e27d76646263b223aa +a296469f24f6f56da92d713afcd4dd606e7da1f79dc4e434593c53695847eefc81c7c446486c4b3b8c8d00c90c166f14 +87a326f57713ac2c9dffeb3af44b9f3c613a8f952676fc46343299122b47ee0f8d792abaa4b5db6451ced5dd153aabd0 +b689e554ba9293b9c1f6344a3c8fcb6951d9f9eac4a2e2df13de021aade7c186be27500e81388e5b8bcab4c80f220a31 +87ae0aa0aa48eac53d1ca5a7b93917de12db9e40ceabf8fdb40884ae771cfdf095411deef7c9f821af0b7070454a2608 +a71ffa7eae8ace94e6c3581d4cb2ad25d48cbd27edc9ec45baa2c8eb932a4773c3272b2ffaf077b40f76942a1f3af7f2 +94c218c91a9b73da6b7a495b3728f3028df8ad9133312fc0c03e8c5253b7ccb83ed14688fd4602e2fd41f29a0bc698bd +ae1e77b90ca33728af07a4c03fb2ef71cd92e2618e7bf8ed4d785ce90097fc4866c29999eb84a6cf1819d75285a03af2 +b7a5945b277dab9993cf761e838b0ac6eaa903d7111fca79f9fde3d4285af7a89bf6634a71909d095d7619d913972c9c +8c43b37be02f39b22029b20aca31bff661abce4471dca88aa3bddefd9c92304a088b2dfc8c4795acc301ca3160656af2 +b32e5d0fba024554bd5fe8a793ebe8003335ddd7f585876df2048dcf759a01285fecb53daae4950ba57f3a282a4d8495 +85ea7fd5e10c7b659df5289b2978b2c89e244f269e061b9a15fcab7983fc1962b63546e82d5731c97ec74b6804be63ef +96b89f39181141a7e32986ac02d7586088c5a9662cec39843f397f3178714d02f929af70630c12cbaba0268f8ba2d4fa +929ab1a2a009b1eb37a2817c89696a06426529ebe3f306c586ab717bd34c35a53eca2d7ddcdef36117872db660024af9 +a696dccf439e9ca41511e16bf3042d7ec0e2f86c099e4fc8879d778a5ea79e33aa7ce96b23dc4332b7ba26859d8e674d +a8fe69a678f9a194b8670a41e941f0460f6e2dbc60470ab4d6ae2679cc9c6ce2c3a39df2303bee486dbfde6844e6b31a +95f58f5c82de2f2a927ca99bf63c9fc02e9030c7e46d0bf6b67fe83a448d0ae1c99541b59caf0e1ccab8326231af09a5 +a57badb2c56ca2c45953bd569caf22968f76ed46b9bac389163d6fe22a715c83d5e94ae8759b0e6e8c2f27bff7748f3f +868726fd49963b24acb5333364dffea147e98f33aa19c7919dc9aca0fd26661cfaded74ede7418a5fadbe7f5ae67b67b +a8d8550dcc64d9f1dd7bcdab236c4122f2b65ea404bb483256d712c7518f08bb028ff8801f1da6aed6cbfc5c7062e33b +97e25a87dae23155809476232178538d4bc05d4ff0882916eb29ae515f2a62bfce73083466cc0010ca956aca200aeacc +b4ea26be3f4bd04aa82d7c4b0913b97bcdf5e88b76c57eb1a336cbd0a3eb29de751e1bc47c0e8258adec3f17426d0c71 +99ee555a4d9b3cf2eb420b2af8e3bc99046880536116d0ce7193464ac40685ef14e0e3c442f604e32f8338cb0ef92558 +8c64efa1da63cd08f319103c5c7a761221080e74227bbc58b8fb35d08aa42078810d7af3e60446cbaff160c319535648 +8d9fd88040076c28420e3395cbdfea402e4077a3808a97b7939d49ecbcf1418fe50a0460e1c1b22ac3f6e7771d65169a +ae3c19882d7a9875d439265a0c7003c8d410367627d21575a864b9cb4918de7dbdb58a364af40c5e045f3df40f95d337 +b4f7bfacab7b2cafe393f1322d6dcc6f21ffe69cd31edc8db18c06f1a2b512c27bd0618091fd207ba8df1808e9d45914 +94f134acd0007c623fb7934bcb65ef853313eb283a889a3ffa79a37a5c8f3665f3d5b4876bc66223610c21dc9b919d37 +aa15f74051171daacdc1f1093d3f8e2d13da2833624b80a934afec86fc02208b8f55d24b7d66076444e7633f46375c6a +a32d6bb47ef9c836d9d2371807bafbbbbb1ae719530c19d6013f1d1f813c49a60e4fa51d83693586cba3a840b23c0404 +b61b3599145ea8680011aa2366dc511a358b7d67672d5b0c5be6db03b0efb8ca5a8294cf220ea7409621f1664e00e631 +859cafc3ee90b7ececa1ed8ef2b2fc17567126ff10ca712d5ffdd16aa411a5a7d8d32c9cab1fbf63e87dce1c6e2f5f53 +a2fef1b0b2874387010e9ae425f3a9676d01a095d017493648bcdf3b31304b087ccddb5cf76abc4e1548b88919663b6b +939e18c73befc1ba2932a65ede34c70e4b91e74cc2129d57ace43ed2b3af2a9cc22a40fbf50d79a63681b6d98852866d +b3b4259d37b1b14aee5b676c9a0dd2d7f679ab95c120cb5f09f9fbf10b0a920cb613655ddb7b9e2ba5af4a221f31303c +997255fe51aaca6e5a9cb3359bcbf25b2bb9e30649bbd53a8a7c556df07e441c4e27328b38934f09c09d9500b5fabf66 +abb91be2a2d860fd662ed4f1c6edeefd4da8dc10e79251cf87f06029906e7f0be9b486462718f0525d5e049472692cb7 +b2398e593bf340a15f7801e1d1fbda69d93f2a32a889ec7c6ae5e8a37567ac3e5227213c1392ee86cfb3b56ec2787839 +8ddf10ccdd72922bed36829a36073a460c2118fc7a56ff9c1ac72581c799b15c762cb56cb78e3d118bb9f6a7e56cb25e +93e6bc0a4708d16387cacd44cf59363b994dc67d7ada7b6d6dbd831c606d975247541b42b2a309f814c1bfe205681fc6 +b93fc35c05998cffda2978e12e75812122831523041f10d52f810d34ff71944979054b04de0117e81ddf5b0b4b3e13c0 +92221631c44d60d68c6bc7b287509f37ee44cbe5fdb6935cee36b58b17c7325098f98f7910d2c3ca5dc885ad1d6dabc7 +a230124424a57fad3b1671f404a94d7c05f4c67b7a8fbacfccea28887b78d7c1ed40b92a58348e4d61328891cd2f6cee +a6a230edb8518a0f49d7231bc3e0bceb5c2ac427f045819f8584ba6f3ae3d63ed107a9a62aad543d7e1fcf1f20605706 +845be1fe94223c7f1f97d74c49d682472585d8f772762baad8a9d341d9c3015534cc83d102113c51a9dea2ab10d8d27b +b44262515e34f2db597c8128c7614d33858740310a49cdbdf9c8677c5343884b42c1292759f55b8b4abc4c86e4728033 +805592e4a3cd07c1844bc23783408310accfdb769cca882ad4d07d608e590a288b7370c2cb327f5336e72b7083a0e30f +95153e8b1140df34ee864f4ca601cb873cdd3efa634af0c4093fbaede36f51b55571ab271e6a133020cd34db8411241f +82878c1285cfa5ea1d32175c9401f3cc99f6bb224d622d3fd98cc7b0a27372f13f7ab463ce3a33ec96f9be38dbe2dfe3 +b7588748f55783077c27fc47d33e20c5c0f5a53fc0ac10194c003aa09b9f055d08ec971effa4b7f760553997a56967b3 +b36b4de6d1883b6951f59cfae381581f9c6352fcfcf1524fccdab1571a20f80441d9152dc6b48bcbbf00371337ca0bd5 +89c5523f2574e1c340a955cbed9c2f7b5fbceb260cb1133160dabb7d41c2f613ec3f6e74bbfab3c4a0a6f0626dbe068f +a52f58cc39f968a9813b1a8ddc4e83f4219e4dd82c7aa1dd083bea7edf967151d635aa9597457f879771759b876774e4 +8300a67c2e2e123f89704abfde095463045dbd97e20d4c1157bab35e9e1d3d18f1f4aaba9cbe6aa2d544e92578eaa1b6 +ac6a7f2918768eb6a43df9d3a8a04f8f72ee52f2e91c064c1c7d75cad1a3e83e5aba9fe55bb94f818099ac91ccf2e961 +8d64a2b0991cf164e29835c8ddef6069993a71ec2a7de8157bbfa2e00f6367be646ed74cbaf524f0e9fe13fb09fa15fd +8b2ffe5a545f9f680b49d0a9797a4a11700a2e2e348c34a7a985fc278f0f12def6e06710f40f9d48e4b7fbb71e072229 +8ab8f71cd337fa19178924e961958653abf7a598e3f022138b55c228440a2bac4176cea3aea393549c03cd38a13eb3fc +8419d28318c19ea4a179b7abb43669fe96347426ef3ac06b158d79c0acf777a09e8e770c2fb10e14b3a0421705990b23 +8bacdac310e1e49660359d0a7a17fe3d334eb820e61ae25e84cb52f863a2f74cbe89c2e9fc3283745d93a99b79132354 +b57ace3fa2b9f6b2db60c0d861ace7d7e657c5d35d992588aeed588c6ce3a80b6f0d49f8a26607f0b17167ab21b675e4 +83e265cde477f2ecc164f49ddc7fb255bb05ff6adc347408353b7336dc3a14fdedc86d5a7fb23f36b8423248a7a67ed1 +a60ada971f9f2d79d436de5d3d045f5ab05308cae3098acaf5521115134b2a40d664828bb89895840db7f7fb499edbc5 +a63eea12efd89b62d3952bf0542a73890b104dd1d7ff360d4755ebfa148fd62de668edac9eeb20507967ea37fb220202 +a0275767a270289adc991cc4571eff205b58ad6d3e93778ddbf95b75146d82517e8921bd0d0564e5b75fa0ccdab8e624 +b9b03fd3bf07201ba3a039176a965d736b4ef7912dd9e9bf69fe1b57c330a6aa170e5521fe8be62505f3af81b41d7806 +a95f640e26fb1106ced1729d6053e41a16e4896acac54992279ff873e5a969aad1dcfa10311e28b8f409ac1dab7f03bb +b144778921742418053cb3c70516c63162c187f00db2062193bb2c14031075dbe055d020cde761b26e8c58d0ea6df2c1 +8432fbb799e0435ef428d4fefc309a05dd589bce74d7a87faf659823e8c9ed51d3e42603d878e80f439a38be4321c2fa +b08ddef14e42d4fd5d8bf39feb7485848f0060d43b51ed5bdda39c05fe154fb111d29719ee61a23c392141358c0cfcff +8ae3c5329a5e025b86b5370e06f5e61177df4bda075856fade20a17bfef79c92f54ed495f310130021ba94fb7c33632b +92b6d3c9444100b4d7391febfc1dddaa224651677c3695c47a289a40d7a96d200b83b64e6d9df51f534564f272a2c6c6 +b432bc2a3f93d28b5e506d68527f1efeb2e2570f6be0794576e2a6ef9138926fdad8dd2eabfa979b79ab7266370e86bc +8bc315eacedbcfc462ece66a29662ca3dcd451f83de5c7626ef8712c196208fb3d8a0faf80b2e80384f0dd9772f61a23 +a72375b797283f0f4266dec188678e2b2c060dfed5880fc6bb0c996b06e91a5343ea2b695adaab0a6fd183b040b46b56 +a43445036fbaa414621918d6a897d3692fdae7b2961d87e2a03741360e45ebb19fcb1703d23f1e15bb1e2babcafc56ac +b9636b2ffe305e63a1a84bd44fb402442b1799bd5272638287aa87ca548649b23ce8ce7f67be077caed6aa2dbc454b78 +99a30bf0921d854c282b83d438a79f615424f28c2f99d26a05201c93d10378ab2cd94a792b571ddae5d4e0c0013f4006 +8648e3c2f93d70b392443be116b48a863e4b75991bab5db656a4ef3c1e7f645e8d536771dfe4e8d1ceda3be8d32978b0 +ab50dc9e6924c1d2e9d2e335b2d679fc7d1a7632e84964d3bac0c9fe57e85aa5906ec2e7b0399d98ddd022e9b19b5904 +ab729328d98d295f8f3272afaf5d8345ff54d58ff9884da14f17ecbdb7371857fdf2f3ef58080054e9874cc919b46224 +83fa5da7592bd451cad3ad7702b4006332b3aae23beab4c4cb887fa6348317d234bf62a359e665b28818e5410c278a09 +8bdbff566ae9d368f114858ef1f009439b3e9f4649f73efa946e678d6c781d52c69af195df0a68170f5f191b2eac286b +91245e59b4425fd4edb2a61d0d47c1ccc83d3ced8180de34887b9655b5dcda033d48cde0bdc3b7de846d246c053a02e8 +a2cb00721e68f1cad8933947456f07144dc69653f96ceed845bd577d599521ba99cdc02421118971d56d7603ed118cbf +af8cd66d303e808b22ec57860dd909ca64c27ec2c60e26ffecfdc1179d8762ffd2739d87b43959496e9fee4108df71df +9954136812dffcd5d3f167a500e7ab339c15cfc9b3398d83f64b0daa3dd5b9a851204f424a3493b4e326d3de81e50a62 +93252254d12511955f1aa464883ad0da793f84d900fea83e1df8bca0f2f4cf5b5f9acbaec06a24160d33f908ab5fea38 +997cb55c26996586ba436a95566bd535e9c22452ca5d2a0ded2bd175376557fa895f9f4def4519241ff386a063f2e526 +a12c78ad451e0ac911260ade2927a768b50cb4125343025d43474e7f465cdc446e9f52a84609c5e7e87ae6c9b3f56cda +a789d4ca55cbba327086563831b34487d63d0980ba8cf55197c016702ed6da9b102b1f0709ce3da3c53ff925793a3d73 +a5d76acbb76741ce85be0e655b99baa04f7f587347947c0a30d27f8a49ae78cce06e1cde770a8b618d3db402be1c0c4b +873c0366668c8faddb0eb7c86f485718d65f8c4734020f1a18efd5fa123d3ea8a990977fe13592cd01d17e60809cb5ff +b659b71fe70f37573ff7c5970cc095a1dc0da3973979778f80a71a347ef25ad5746b2b9608bad4ab9a4a53a4d7df42d7 +a34cbe05888e5e5f024a2db14cb6dcdc401a9cbd13d73d3c37b348f68688f87c24ca790030b8f84fef9e74b4eab5e412 +94ce8010f85875c045b0f014db93ef5ab9f1f6842e9a5743dce9e4cb872c94affd9e77c1f1d1ab8b8660b52345d9acb9 +adefa9b27a62edc0c5b019ddd3ebf45e4de846165256cf6329331def2e088c5232456d3de470fdce3fa758bfdd387512 +a6b83821ba7c1f83cc9e4529cf4903adb93b26108e3d1f20a753070db072ad5a3689643144bdd9c5ea06bb9a7a515cd0 +a3a9ddedc2a1b183eb1d52de26718151744db6050f86f3580790c51d09226bf05f15111691926151ecdbef683baa992c +a64bac89e7686932cdc5670d07f0b50830e69bfb8c93791c87c7ffa4913f8da881a9d8a8ce8c1a9ce5b6079358c54136 +a77b5a63452cb1320b61ab6c7c2ef9cfbcade5fd4727583751fb2bf3ea330b5ca67757ec1f517bf4d503ec924fe32fbd +8746fd8d8eb99639d8cd0ca34c0d9c3230ed5a312aab1d3d925953a17973ee5aeb66e68667e93caf9cb817c868ea8f3d +88a2462a26558fc1fbd6e31aa8abdc706190a17c27fdc4217ffd2297d1b1f3321016e5c4b2384c5454d5717dc732ed03 +b78893a97e93d730c8201af2e0d3b31cb923d38dc594ffa98a714e627c473d42ea82e0c4d2eeb06862ee22a9b2c54588 +920cc8b5f1297cf215a43f6fc843e379146b4229411c44c0231f6749793d40f07b9af7699fd5d21fd69400b97febe027 +a0f0eafce1e098a6b58c7ad8945e297cd93aaf10bc55e32e2e32503f02e59fc1d5776936577d77c0b1162cb93b88518b +98480ba0064e97a2e7a6c4769b4d8c2a322cfc9a3b2ca2e67e9317e2ce04c6e1108169a20bd97692e1cb1f1423b14908 +83dbbb2fda7e287288011764a00b8357753a6a44794cc8245a2275237f11affdc38977214e463ad67aec032f3dfa37e9 +86442fff37598ce2b12015ff19b01bb8a780b40ad353d143a0f30a06f6d23afd5c2b0a1253716c855dbf445cc5dd6865 +b8a4c60c5171189414887847b9ed9501bff4e4c107240f063e2d254820d2906b69ef70406c585918c4d24f1dd052142b +919f33a98e84015b2034b57b5ffe9340220926b2c6e45f86fd79ec879dbe06a148ae68b77b73bf7d01bd638a81165617 +95c13e78d89474a47fbc0664f6f806744b75dede95a479bbf844db4a7f4c3ae410ec721cb6ffcd9fa9c323da5740d5ae +ab7151acc41fffd8ec6e90387700bcd7e1cde291ea669567295bea1b9dd3f1df2e0f31f3588cd1a1c08af8120aca4921 +80e74c5c47414bd6eeef24b6793fb1fa2d8fb397467045fcff887c52476741d5bc4ff8b6d3387cb53ad285485630537f +a296ad23995268276aa351a7764d36df3a5a3cffd7dbeddbcea6b1f77adc112629fdeffa0918b3242b3ccd5e7587e946 +813d2506a28a2b01cb60f49d6bd5e63c9b056aa56946faf2f33bd4f28a8d947569cfead3ae53166fc65285740b210f86 +924b265385e1646287d8c09f6c855b094daaee74b9e64a0dddcf9ad88c6979f8280ba30c8597b911ef58ddb6c67e9fe3 +8d531513c70c2d3566039f7ca47cd2352fd2d55b25675a65250bdb8b06c3843db7b2d29c626eed6391c238fc651cf350 +82b338181b62fdc81ceb558a6843df767b6a6e3ceedc5485664b4ea2f555904b1a45fbb35f6cf5d96f27da10df82a325 +92e62faaedea83a37f314e1d3cb4faaa200178371d917938e59ac35090be1db4b4f4e0edb78b9c991de202efe4f313d8 +99d645e1b642c2dc065bac9aaa0621bc648c9a8351efb6891559c3a41ba737bd155fb32d7731950514e3ecf4d75980e4 +b34a13968b9e414172fb5d5ece9a39cf2eb656128c3f2f6cc7a9f0c69c6bae34f555ecc8f8837dc34b5e470e29055c78 +a2a0bb7f3a0b23a2cbc6585d59f87cd7e56b2bbcb0ae48f828685edd9f7af0f5edb4c8e9718a0aaf6ef04553ba71f3b7 +8e1a94bec053ed378e524b6685152d2b52d428266f2b6eadd4bcb7c4e162ed21ab3e1364879673442ee2162635b7a4d8 +9944adaff14a85eab81c73f38f386701713b52513c4d4b838d58d4ffa1d17260a6d056b02334850ea9a31677c4b078bd +a450067c7eceb0854b3eca3db6cf38669d72cb7143c3a68787833cbca44f02c0be9bfbe082896f8a57debb13deb2afb1 +8be4ad3ac9ef02f7df09254d569939757101ee2eda8586fefcd8c847adc1efe5bdcb963a0cafa17651befaafb376a531 +90f6de91ea50255f148ac435e08cf2ac00c772a466e38155bd7e8acf9197af55662c7b5227f88589b71abe9dcf7ba343 +86e5a24f0748b106dee2d4d54e14a3b0af45a96cbee69cac811a4196403ebbee17fd24946d7e7e1b962ac7f66dbaf610 +afdd96fbcda7aa73bf9eeb2292e036c25753d249caee3b9c013009cc22e10d3ec29e2aa6ddbb21c4e949b0c0bccaa7f4 +b5a4e7436d5473647c002120a2cb436b9b28e27ad4ebdd7c5f122b91597c507d256d0cbd889d65b3a908531936e53053 +b632414c3da704d80ac2f3e5e0e9f18a3637cdc2ebeb613c29300745582427138819c4e7b0bec3099c1b8739dac1807b +a28df1464d3372ce9f37ef1db33cc010f752156afae6f76949d98cd799c0cf225c20228ae86a4da592d65f0cffe3951b +898b93d0a31f7d3f11f253cb7a102db54b669fd150da302d8354d8e02b1739a47cb9bd88015f3baf12b00b879442464e +96fb88d89a12049091070cb0048a381902965e67a8493e3991eaabe5d3b7ff7eecd5c94493a93b174df3d9b2c9511755 +b899cb2176f59a5cfba3e3d346813da7a82b03417cad6342f19cc8f12f28985b03bf031e856a4743fd7ebe16324805b0 +a60e2d31bc48e0c0579db15516718a03b73f5138f15037491f4dae336c904e312eda82d50862f4debd1622bb0e56d866 +979fc8b987b5cef7d4f4b58b53a2c278bd25a5c0ea6f41c715142ea5ff224c707de38451b0ad3aa5e749aa219256650a +b2a75bff18e1a6b9cf2a4079572e41205741979f57e7631654a3c0fcec57c876c6df44733c9da3d863db8dff392b44a3 +b7a0f0e811222c91e3df98ff7f286b750bc3b20d2083966d713a84a2281744199e664879401e77470d44e5a90f3e5181 +82b74ba21c9d147fbc338730e8f1f8a6e7fc847c3110944eb17a48bea5e06eecded84595d485506d15a3e675fd0e5e62 +a7f44eef817d5556f0d1abcf420301217d23c69dd2988f44d91ea1f1a16c322263cbacd0f190b9ba22b0f141b9267b4f +aadb68164ede84fc1cb3334b3194d84ba868d5a88e4c9a27519eef4923bc4abf81aab8114449496c073c2a6a0eb24114 +b5378605fabe9a8c12a5dc55ef2b1de7f51aedb61960735c08767a565793cea1922a603a6983dc25f7cea738d0f7c40d +a97a4a5cd8d51302e5e670aee78fe6b5723f6cc892902bbb4f131e82ca1dfd5de820731e7e3367fb0c4c1922a02196e3 +8bdfeb15c29244d4a28896f2b2cb211243cd6a1984a3f5e3b0ebe5341c419beeab3304b390a009ffb47588018034b0ea +a9af3022727f2aa2fca3b096968e97edad3f08edcbd0dbca107b892ae8f746a9c0485e0d6eb5f267999b23a845923ed0 +8e7594034feef412f055590fbb15b6322dc4c6ab7a4baef4685bd13d71a83f7d682b5781bdfa0d1c659489ce9c2b8000 +84977ca6c865ebee021c58106c1a4ad0c745949ecc5332948002fd09bd9b890524878d0c29da96fd11207621136421fe +8687551a79158e56b2375a271136756313122132a6670fa51f99a1b5c229ed8eea1655a734abae13228b3ebfd2a825dd +a0227d6708979d99edfc10f7d9d3719fd3fc68b0d815a7185b60307e4c9146ad2f9be2b8b4f242e320d4288ceeb9504c +89f75583a16735f9dd8b7782a130437805b34280ccea8dac6ecaee4b83fe96947e7b53598b06fecfffdf57ffc12cc445 +a0056c3353227f6dd9cfc8e3399aa5a8f1d71edf25d3d64c982910f50786b1e395c508d3e3727ac360e3e040c64b5298 +b070e61a6d813626144b312ded1788a6d0c7cec650a762b2f8df6e4743941dd82a2511cd956a3f141fc81e15f4e092da +b4e6db232e028a1f989bb5fc13416711f42d389f63564d60851f009dcffac01acfd54efa307aa6d4c0f932892d4e62b0 +89b5991a67db90024ddd844e5e1a03ef9b943ad54194ae0a97df775dde1addf31561874f4e40fbc37a896630f3bbda58 +ad0e8442cb8c77d891df49cdb9efcf2b0d15ac93ec9be1ad5c3b3cca1f4647b675e79c075335c1f681d56f14dc250d76 +b5d55a6ae65bb34dd8306806cb49b5ccb1c83a282ee47085cf26c4e648e19a52d9c422f65c1cd7e03ca63e926c5e92ea +b749501347e5ec07e13a79f0cb112f1b6534393458b3678a77f02ca89dca973fa7b30e55f0b25d8b92b97f6cb0120056 +94144b4a3ffc5eec6ba35ce9c245c148b39372d19a928e236a60e27d7bc227d18a8cac9983851071935d8ffb64b3a34f +92bb4f9f85bc8c028a3391306603151c6896673135f8a7aefedd27acb322c04ef5dac982fc47b455d6740023e0dd3ea3 +b9633a4a101461a782fc2aa092e9dbe4e2ad00987578f18cd7cf0021a909951d60fe79654eb7897806795f93c8ff4d1c +809f0196753024821b48a016eca5dbb449a7c55750f25981bb7a4b4c0e0846c09b8f6128137905055fc43a3f0deb4a74 +a27dc9cdd1e78737a443570194a03d89285576d3d7f3a3cf15cc55b3013e42635d4723e2e8fe1d0b274428604b630db9 +861f60f0462e04cd84924c36a28163def63e777318d00884ab8cb64c8df1df0bce5900342163edb60449296484a6c5bf +b7bc23fb4e14af4c4704a944253e760adefeca8caee0882b6bbd572c84434042236f39ae07a8f21a560f486b15d82819 +b9a6eb492d6dd448654214bd01d6dc5ff12067a11537ab82023fc16167507ee25eed2c91693912f4155d1c07ed9650b3 +97678af29c68f9a5e213bf0fb85c265303714482cfc4c2c00b4a1e8a76ed08834ee6af52357b143a1ca590fb0265ea5a +8a15b499e9eca5b6cac3070b5409e8296778222018ad8b53a5d1f6b70ad9bb10c68a015d105c941ed657bf3499299e33 +b487fefede2e8091f2c7bfe85770db2edff1db83d4effe7f7d87bff5ab1ace35e9b823a71adfec6737fede8d67b3c467 +8b51b916402aa2c437fce3bcad6dad3be8301a1a7eab9d163085b322ffb6c62abf28637636fe6114573950117fc92898 +b06a2106d031a45a494adec0881cb2f82275dff9dcdd2bc16807e76f3bec28a6734edd3d54f0be8199799a78cd6228ad +af0a185391bbe2315eb97feac98ad6dd2e5d931d012c621abd6e404a31cc188b286fef14871762190acf086482b2b5e2 +8e78ee8206506dd06eb7729e32fceda3bebd8924a64e4d8621c72e36758fda3d0001af42443851d6c0aea58562870b43 +a1ba52a569f0461aaf90b49b92be976c0e73ec4a2c884752ee52ffb62dd137770c985123d405dfb5de70692db454b54a +8d51b692fa1543c51f6b62b9acb8625ed94b746ef96c944ca02859a4133a5629da2e2ce84e111a7af8d9a5b836401c64 +a7a20d45044cf6492e0531d0b8b26ffbae6232fa05a96ed7f06bdb64c2b0f5ca7ec59d5477038096a02579e633c7a3ff +84df867b98c53c1fcd4620fef133ee18849c78d3809d6aca0fb6f50ff993a053a455993f216c42ab6090fa5356b8d564 +a7227c439f14c48e2577d5713c97a5205feb69acb0b449152842e278fa71e8046adfab468089c8b2288af1fc51fa945b +855189b3a105670779997690876dfaa512b4a25a24931a912c2f0f1936971d2882fb4d9f0b3d9daba77eaf660e9d05d5 +b5696bd6706de51c502f40385f87f43040a5abf99df705d6aac74d88c913b8ecf7a99a63d7a37d9bdf3a941b9e432ff5 +ab997beb0d6df9c98d5b49864ef0b41a2a2f407e1687dfd6089959757ba30ed02228940b0e841afe6911990c74d536c4 +b36b65f85546ebfdbe98823d5555144f96b4ab39279facd19c0de3b8919f105ba0315a0784dce4344b1bc62d8bb4a5a3 +b8371f0e4450788720ac5e0f6cd3ecc5413d33895083b2c168d961ec2b5c3de411a4cc0712481cbe8df8c2fa1a7af006 +98325d8026b810a8b7a114171ae59a57e8bbc9848e7c3df992efc523621729fd8c9f52114ce01d7730541a1ada6f1df1 +8d0e76dbd37806259486cd9a31bc8b2306c2b95452dc395546a1042d1d17863ef7a74c636b782e214d3aa0e8d717f94a +a4e15ead76da0214d702c859fb4a8accdcdad75ed08b865842bd203391ec4cba2dcc916455e685f662923b96ee0c023f +8618190972086ebb0c4c1b4a6c94421a13f378bc961cc8267a301de7390c5e73c3333864b3b7696d81148f9d4843fd02 +85369d6cc7342e1aa15b59141517d8db8baaaeb7ab9670f3ba3905353948d575923d283b7e5a05b13a30e7baf1208a86 +87c51ef42233c24a6da901f28c9a075d9ba3c625687c387ad6757b72ca6b5a8885e6902a3082da7281611728b1e45f26 +aa6348a4f71927a3106ad0ea8b02fc8d8c65531e4ab0bd0a17243e66f35afe252e40ab8eef9f13ae55a72566ffdaff5c +96a3bc976e9d03765cc3fee275fa05b4a84c94fed6b767e23ca689394501e96f56f7a97cffddc579a6abff632bf153be +97dbf96c6176379fdb2b888be4e757b2bca54e74124bd068d3fa1dbd82a011bbeb75079da38e0cd22a761fe208ecad9b +b70cf0a1d14089a4129ec4e295313863a59da8c7e26bf74cc0e704ed7f0ee4d7760090d0ddf7728180f1bf2c5ac64955 +882d664714cc0ffe53cbc9bef21f23f3649824f423c4dbad1f893d22c4687ab29583688699efc4d5101aa08b0c3e267a +80ecb7cc963e677ccaddbe3320831dd6ee41209acf4ed41b16dc4817121a3d86a1aac9c4db3d8c08a55d28257088af32 +a25ba667d832b145f9ce18c3f9b1bd00737aa36db020e1b99752c8ef7d27c6c448982bd8d352e1b6df266b8d8358a8d5 +83734841c13dee12759d40bdd209b277e743b0d08cc0dd1e0b7afd2d65bfa640400eefcf6be4a52e463e5b3d885eeac6 +848d16505b04804afc773aebabb51b36fd8aacfbb0e09b36c0d5d57df3c0a3b92f33e7d5ad0a7006ec46ebb91df42b8c +909a8d793f599e33bb9f1dc4792a507a97169c87cd5c087310bc05f30afcd247470b4b56dec59894c0fb1d48d39bb54e +8e558a8559df84a1ba8b244ece667f858095c50bb33a5381e60fcc6ba586b69693566d8819b4246a27287f16846c1dfa +84d6b69729f5aaa000cd710c2352087592cfbdf20d5e1166977e195818e593fa1a50d1e04566be23163a2523dc1612f1 +9536d262b7a42125d89f4f32b407d737ba8d9242acfc99d965913ab3e043dcac9f7072a43708553562cac4cba841df30 +9598548923ca119d6a15fd10861596601dd1dedbcccca97bb208cdc1153cf82991ea8cc17686fbaa867921065265970c +b87f2d4af6d026e4d2836bc3d390a4a18e98a6e386282ce96744603bab74974272e97ac2da281afa21885e2cbb3a8001 +991ece62bf07d1a348dd22191868372904b9f8cf065ae7aa4e44fd24a53faf6d851842e35fb472895963aa1992894918 +a8c53dea4c665b30e51d22ca6bc1bc78aaf172b0a48e64a1d4b93439b053877ec26cb5221c55efd64fa841bbf7d5aff4 +93487ec939ed8e740f15335b58617c3f917f72d07b7a369befd479ae2554d04deb240d4a14394b26192efae4d2f4f35d +a44793ab4035443f8f2968a40e043b4555960193ffa3358d22112093aadfe2c136587e4139ffd46d91ed4107f61ea5e0 +b13fe033da5f0d227c75927d3dacb06dbaf3e1322f9d5c7c009de75cdcba5e308232838785ab69a70f0bedea755e003f +970a29b075faccd0700fe60d1f726bdebf82d2cc8252f4a84543ebd3b16f91be42a75c9719a39c4096139f0f31393d58 +a4c3eb1f7160f8216fc176fb244df53008ff32f2892363d85254002e66e2de21ccfe1f3b1047589abee50f29b9d507e3 +8c552885eab04ba40922a8f0c3c38c96089c95ff1405258d3f1efe8d179e39e1295cbf67677894c607ae986e4e6b1fb0 +b3671746fa7f848c4e2ae6946894defadd815230b906b419143523cc0597bc1d6c0a4c1e09d49b66b4a2c11cde3a4de3 +937a249a95813a5e2ef428e355efd202e15a37d73e56cfb7e57ea9f943f2ce5ca8026f2f1fd25bf164ba89d07077d858 +83646bdf6053a04aa9e2f112499769e5bd5d0d10f2e13db3ca89bd45c0b3b7a2d752b7d137fb3909f9c62b78166c9339 +b4eac4b91e763666696811b7ed45e97fd78310377ebea1674b58a2250973f80492ac35110ed1240cd9bb2d17493d708c +82db43a99bc6573e9d92a3fd6635dbbb249ac66ba53099c3c0c8c8080b121dd8243cd5c6e36ba0a4d2525bae57f5c89c +a64d6a264a681b49d134c655d5fc7756127f1ee7c93d328820f32bca68869f53115c0d27fef35fe71f7bc4fdaed97348 +8739b7a9e2b4bc1831e7f04517771bc7cde683a5e74e052542517f8375a2f64e53e0d5ac925ef722327e7bb195b4d1d9 +8f337cdd29918a2493515ebb5cf702bbe8ecb23b53c6d18920cc22f519e276ca9b991d3313e2d38ae17ae8bdfa4f8b7e +b0edeab9850e193a61f138ef2739fc42ceec98f25e7e8403bfd5fa34a7bc956b9d0898250d18a69fa4625a9b3d6129da +a9920f26fe0a6d51044e623665d998745c9eca5bce12051198b88a77d728c8238f97d4196f26e43b24f8841500b998d0 +86e655d61502b979eeeeb6f9a7e1d0074f936451d0a1b0d2fa4fb3225b439a3770767b649256fe481361f481a8dbc276 +84d3b32fa62096831cc3bf013488a9f3f481dfe293ae209ed19585a03f7db8d961a7a9dd0db82bd7f62d612707575d9c +81c827826ec9346995ffccf62a241e3b2d32f7357acd1b1f8f7a7dbc97022d3eb51b8a1230e23ce0b401d2e535e8cd78 +94a1e40c151191c5b055b21e86f32e69cbc751dcbdf759a48580951834b96a1eed75914c0d19a38aefd21fb6c8d43d0c +ab890222b44bc21b71f7c75e15b6c6e16bb03371acce4f8d4353ff3b8fcd42a14026589c5ed19555a3e15e4d18bfc3a3 +accb0be851e93c6c8cc64724cdb86887eea284194b10e7a43c90528ed97e9ec71ca69c6fac13899530593756dd49eab2 +b630220aa9e1829c233331413ee28c5efe94ea8ea08d0c6bfd781955078b43a4f92915257187d8526873e6c919c6a1de +add389a4d358c585f1274b73f6c3c45b58ef8df11f9d11221f620e241bf3579fba07427b288c0c682885a700cc1fa28d +a9fe6ca8bf2961a3386e8b8dcecc29c0567b5c0b3bcf3b0f9169f88e372b80151af883871fc5229815f94f43a6f5b2b0 +ad839ae003b92b37ea431fa35998b46a0afc3f9c0dd54c3b3bf7a262467b13ff3c323ada1c1ae02ac7716528bdf39e3e +9356d3fd0edcbbb65713c0f2a214394f831b26f792124b08c5f26e7f734b8711a87b7c4623408da6a091c9aef1f6af3c +896b25b083c35ac67f0af3784a6a82435b0e27433d4d74cd6d1eafe11e6827827799490fb1c77c11de25f0d75f14e047 +8bfa019391c9627e8e5f05c213db625f0f1e51ec68816455f876c7e55b8f17a4f13e5aae9e3fb9e1cf920b1402ee2b40 +8ba3a6faa6a860a8f3ce1e884aa8769ceded86380a86520ab177ab83043d380a4f535fe13884346c5e51bee68da6ab41 +a8292d0844084e4e3bb7af92b1989f841a46640288c5b220fecfad063ee94e86e13d3d08038ec2ac82f41c96a3bfe14d +8229bb030b2fc566e11fd33c7eab7a1bb7b49fed872ea1f815004f7398cb03b85ea14e310ec19e1f23e0bdaf60f8f76c +8cfbf869ade3ec551562ff7f63c2745cc3a1f4d4dc853a0cd42dd5f6fe54228f86195ea8fe217643b32e9f513f34a545 +ac52a3c8d3270ddfe1b5630159da9290a5ccf9ccbdef43b58fc0a191a6c03b8a5974cf6e2bbc7bd98d4a40a3581482d7 +ab13decb9e2669e33a7049b8eca3ca327c40dea15ad6e0e7fa63ed506db1d258bc36ac88b35f65cae0984e937eb6575d +b5e748eb1a7a1e274ff0cc56311c198f2c076fe4b7e73e5f80396fe85358549df906584e6bb2c8195b3e2be7736850a5 +b5cb911325d8f963c41f691a60c37831c7d3bbd92736efa33d1f77a22b3fde7f283127256c2f47e197571e6fe0b46149 +8a01dc6ed1b55f26427a014faa347130738b191a06b800e32042a46c13f60b49534520214359d68eb2e170c31e2b8672 +a72fa874866e19b2efb8e069328362bf7921ec375e3bcd6b1619384c3f7ee980f6cf686f3544e9374ff54b4d17a1629c +8db21092f7c5f110fba63650b119e82f4b42a997095d65f08f8237b02dd66fdf959f788df2c35124db1dbd330a235671 +8c65d50433d9954fe28a09fa7ba91a70a590fe7ba6b3060f5e4be0f6cef860b9897fa935fb4ebc42133524eb071dd169 +b4614058e8fa21138fc5e4592623e78b8982ed72aa35ee4391b164f00c68d277fa9f9eba2eeefc890b4e86eba5124591 +ab2ad3a1bce2fbd55ca6b7c23786171fe1440a97d99d6df4d80d07dd56ac2d7203c294b32fc9e10a6c259381a73f24a1 +812ae3315fdc18774a8da3713a4679e8ed10b9405edc548c00cacbe25a587d32040566676f135e4723c5dc25df5a22e9 +a464b75f95d01e5655b54730334f443c8ff27c3cb79ec7af4b2f9da3c2039c609908cd128572e1fd0552eb597e8cef8d +a0db3172e93ca5138fe419e1c49a1925140999f6eff7c593e5681951ee0ec1c7e454c851782cbd2b8c9bc90d466e90e0 +806db23ba7d00b87d544eed926b3443f5f9c60da6b41b1c489fba8f73593b6e3b46ebfcab671ee009396cd77d5e68aa1 +8bfdf2c0044cc80260994e1c0374588b6653947b178e8b312be5c2a05e05767e98ea15077278506aee7df4fee1aaf89e +827f6558c16841b5592ff089c9c31e31eb03097623524394813a2e4093ad2d3f8f845504e2af92195aaa8a1679d8d692 +925c4f8eab2531135cd71a4ec88e7035b5eea34ba9d799c5898856080256b4a15ed1a746e002552e2a86c9c157e22e83 +a9f9a368f0e0b24d00a35b325964c85b69533013f9c2cfad9708be5fb87ff455210f8cb8d2ce3ba58ca3f27495552899 +8ac0d3bebc1cae534024187e7c71f8927ba8fcc6a1926cb61c2b6c8f26bb7831019e635a376146c29872a506784a4aaa +97c577be2cbbfdb37ad754fae9df2ada5fc5889869efc7e18a13f8e502fbf3f4067a509efbd46fd990ab47ce9a70f5a8 +935e7d82bca19f16614aa43b4a3474e4d20d064e4bfdf1cea2909e5c9ab72cfe3e54dc50030e41ee84f3588cebc524e9 +941aafc08f7c0d94cebfbb1f0aad5202c02e6e37f2c12614f57e727efa275f3926348f567107ee6d8914dd71e6060271 +af0fbc1ba05b4b5b63399686df3619968be5d40073de0313cbf5f913d3d4b518d4c249cdd2176468ccaa36040a484f58 +a0c414f23f46ca6d69ce74c6f8a00c036cb0edd098af0c1a7d39c802b52cfb2d5dbdf93fb0295453d4646e2af7954d45 +909cf39e11b3875bb63b39687ae1b5d1f5a15445e39bf164a0b14691b4ddb39a8e4363f584ef42213616abc4785b5d66 +a92bac085d1194fbd1c88299f07a061d0bdd3f980b663e81e6254dbb288bf11478c0ee880e28e01560f12c5ccb3c0103 +841705cd5cd76b943e2b7c5e845b9dd3c8defe8ef67e93078d6d5e67ade33ad4b0fd413bc196f93b0a4073c855cd97d4 +8e7eb8364f384a9161e81d3f1d52ceca9b65536ae49cc35b48c3e2236322ba4ae9973e0840802d9fa4f4d82ea833544f +aed3ab927548bc8bec31467ba80689c71a168e34f50dcb6892f19a33a099f5aa6b3f9cb79f5c0699e837b9a8c7f27efe +b8fbf7696210a36e20edabd77839f4dfdf50d6d015cdf81d587f90284a9bcef7d2a1ff520728d7cc69a4843d6c20dedd +a9d533769ce6830211c884ae50a82a7bf259b44ac71f9fb11f0296fdb3981e6b4c1753fe744647b247ebc433a5a61436 +8b4bdf90d33360b7f428c71cde0a49fb733badba8c726876945f58c620ce7768ae0e98fc8c31fa59d8955a4823336bb1 +808d42238e440e6571c59e52a35ae32547d502dc24fd1759d8ea70a7231a95859baf30b490a4ba55fa2f3aaa11204597 +85594701f1d2fee6dc1956bc44c7b31db93bdeec2f3a7d622c1a08b26994760773e3d57521a44cfd7e407ac3fd430429 +a66de045ce7173043a6825e9dc440ac957e2efb6df0a337f4f8003eb0c719d873a52e6eba3cb0d69d977ca37d9187674 +87a1c6a1fdff993fa51efa5c3ba034c079c0928a7d599b906336af7c2dcab9721ceaf3108c646490af9dff9a754f54b3 +926424223e462ceb75aed7c22ade8a7911a903b7e5dd4bc49746ddce8657f4616325cd12667d4393ac52cdd866396d0e +b5dc96106593b42b30f06f0b0a1e0c1aafc70432e31807252d3674f0b1ea5e58eac8424879d655c9488d85a879a3e572 +997ca0987735cc716507cb0124b1d266d218b40c9d8e0ecbf26a1d65719c82a637ce7e8be4b4815d307df717bde7c72a +92994d3f57a569b7760324bb5ae4e8e14e1633d175dab06aa57b8e391540e05f662fdc08b8830f489a063f59b689a688 +a8087fcc6aa4642cb998bea11facfe87eb33b90a9aa428ab86a4124ad032fc7d2e57795311a54ec9f55cc120ebe42df1 +a9bd7d1de6c0706052ca0b362e2e70e8c8f70f1f026ea189b4f87a08ce810297ebfe781cc8004430776c54c1a05ae90c +856d33282e8a8e33a3d237fb0a0cbabaf77ba9edf2fa35a831fdafcadf620561846aa6cbb6bdc5e681118e1245834165 +9524a7aa8e97a31a6958439c5f3339b19370f03e86b89b1d02d87e4887309dbbe9a3a8d2befd3b7ed5143c8da7e0a8ad +824fdf433e090f8acbd258ac7429b21f36f9f3b337c6d0b71d1416a5c88a767883e255b2888b7c906dd2e9560c4af24c +88c7fee662ca7844f42ed5527996b35723abffd0d22d4ca203b9452c639a5066031207a5ae763dbc0865b3299d19b1ec +919dca5c5595082c221d5ab3a5bc230f45da7f6dec4eb389371e142c1b9c6a2c919074842479c2844b72c0d806170c0c +b939be8175715e55a684578d8be3ceff3087f60fa875fff48e52a6e6e9979c955efef8ff67cfa2b79499ea23778e33b0 +873b6db725e7397d11bc9bed9ac4468e36619135be686790a79bc6ed4249058f1387c9a802ea86499f692cf635851066 +aeae06db3ec47e9e5647323fa02fac44e06e59b885ad8506bf71b184ab3895510c82f78b6b22a5d978e8218e7f761e9f +b99c0a8359c72ab88448bae45d4bf98797a26bca48b0d4460cd6cf65a4e8c3dd823970ac3eb774ae5d0cea4e7fadf33e +8f10c8ec41cdfb986a1647463076a533e6b0eec08520c1562401b36bb063ac972aa6b28a0b6ce717254e35940b900e3c +a106d9be199636d7add43b942290269351578500d8245d4aae4c083954e4f27f64740a3138a66230391f2d0e6043a8de +a469997908244578e8909ff57cffc070f1dbd86f0098df3cfeb46b7a085cfecc93dc69ee7cad90ff1dc5a34d50fe580c +a4ef087bea9c20eb0afc0ee4caba7a9d29dfa872137828c721391273e402fb6714afc80c40e98bbd8276d3836bffa080 +b07a013f73cd5b98dae0d0f9c1c0f35bff8a9f019975c4e1499e9bee736ca6fcd504f9bc32df1655ff333062382cff04 +b0a77188673e87cc83348c4cc5db1eecf6b5184e236220c8eeed7585e4b928db849944a76ec60ef7708ef6dac02d5592 +b1284b37e59b529f0084c0dacf0af6c0b91fc0f387bf649a8c74819debf606f7b07fc3e572500016fb145ec2b24e9f17 +97b20b5b4d6b9129da185adfbf0d3d0b0faeba5b9715f10299e48ea0521709a8296a9264ce77c275a59c012b50b6519a +b9d37e946fae5e4d65c1fbfacc8a62e445a1c9d0f882e60cca649125af303b3b23af53c81d7bac544fb7fcfc7a314665 +8e5acaac379f4bb0127efbef26180f91ff60e4c525bc9b798fc50dfaf4fe8a5aa84f18f3d3cfb8baead7d1e0499af753 +b0c0b8ab1235bf1cda43d4152e71efc1a06c548edb964eb4afceb201c8af24240bf8ab5cae30a08604e77432b0a5faf0 +8cc28d75d5c8d062d649cbc218e31c4d327e067e6dbd737ec0a35c91db44fbbd0d40ec424f5ed79814add16947417572 +95ae6219e9fd47efaa9cb088753df06bc101405ba50a179d7c9f7c85679e182d3033f35b00dbba71fdcd186cd775c52e +b5d28fa09f186ebc5aa37453c9b4d9474a7997b8ae92748ecb940c14868792292ac7d10ade01e2f8069242b308cf97e5 +8c922a0faa14cc6b7221f302df3342f38fc8521ec6c653f2587890192732c6da289777a6cd310747ea7b7d104af95995 +b9ad5f660b65230de54de535d4c0fcae5bc6b59db21dea5500fdc12eea4470fb8ea003690fdd16d052523418d5e01e8c +a39a9dd41a0ff78c82979483731f1cd68d3921c3e9965869662c22e02dde3877802e180ba93f06e7346f96d9fa9261d2 +8b32875977ec372c583b24234c27ed73aef00cdff61eb3c3776e073afbdeade548de9497c32ec6d703ff8ad0a5cb7fe4 +9644cbe755a5642fe9d26cfecf170d3164f1848c2c2e271d5b6574a01755f3980b3fc870b98cf8528fef6ecef4210c16 +81ea9d1fdd9dd66d60f40ce0712764b99da9448ae0b300f8324e1c52f154e472a086dda840cb2e0b9813dc8ce8afd4b5 +906aaa4a7a7cdf01909c5cfbc7ded2abc4b869213cbf7c922d4171a4f2e637e56f17020b852ad339d83b8ac92f111666 +939b5f11acbdeff998f2a080393033c9b9d8d5c70912ea651c53815c572d36ee822a98d6dfffb2e339f29201264f2cf4 +aba4898bf1ccea9b9e2df1ff19001e05891581659c1cbbde7ee76c349c7fc7857261d9785823c9463a8aea3f40e86b38 +83ca1a56b8a0be4820bdb5a9346357c68f9772e43f0b887729a50d2eb2a326bbcede676c8bf2e51d7c89bbd8fdb778a6 +94e86e9fe6addfe2c3ee3a547267ed921f4230d877a85bb4442c2d9350c2fa9a9c54e6fe662de82d1a2407e4ab1691c2 +a0cc3bdef671a59d77c6984338b023fa2b431b32e9ed2abe80484d73edc6540979d6f10812ecc06d4d0c5d4eaca7183c +b5343413c1b5776b55ea3c7cdd1f3af1f6bd802ea95effe3f2b91a523817719d2ecc3f8d5f3cc2623ace7e35f99ca967 +92085d1ed0ed28d8cabe3e7ff1905ed52c7ceb1eac5503760c52fb5ee3a726aba7c90b483c032acc3f166b083d7ec370 +8ec679520455275cd957fca8122724d287db5df7d29f1702a322879b127bff215e5b71d9c191901465d19c86c8d8d404 +b65eb2c63d8a30332eb24ee8a0c70156fc89325ebbb38bacac7cf3f8636ad8a472d81ccca80423772abc00192d886d8a +a9fe1c060b974bee4d590f2873b28635b61bfcf614e61ff88b1be3eee4320f4874e21e8d666d8ac8c9aba672efc6ecae +b3fe2a9a389c006a831dea7e777062df84b5c2803f9574d7fbe10b7e1c125817986af8b6454d6be9d931a5ac94cfe963 +95418ad13b734b6f0d33822d9912c4c49b558f68d08c1b34a0127fcfa666bcae8e6fda8832d2c75bb9170794a20e4d7c +a9a7df761e7f18b79494bf429572140c8c6e9d456c4d4e336184f3f51525a65eb9582bea1e601bdb6ef8150b7ca736a5 +a0de03b1e75edf7998c8c1ac69b4a1544a6fa675a1941950297917366682e5644a4bda9cdeedfaf9473d7fccd9080b0c +a61838af8d95c95edf32663a68f007d95167bf6e41b0c784a30b22d8300cfdd5703bd6d16e86396638f6db6ae7e42a85 +8866d62084d905c145ff2d41025299d8b702ac1814a7dec4e277412c161bc9a62fed735536789cb43c88693c6b423882 +91da22c378c81497fe363e7f695c0268443abee50f8a6625b8a41e865638a643f07b157ee566de09ba09846934b4e2d7 +941d21dd57c9496aa68f0c0c05507405fdd413acb59bc668ce7e92e1936c68ec4b065c3c30123319884149e88228f0b2 +a77af9b094bc26966ddf2bf9e1520c898194a5ccb694915950dadc204facbe3066d3d89f50972642d76b14884cfbaa21 +8e76162932346869f4618bde744647f7ab52ab498ad654bdf2a4feeb986ac6e51370841e5acbb589e38b6e7142bb3049 +b60979ace17d6937ece72e4f015da4657a443dd01cebc7143ef11c09e42d4aa8855999a65a79e2ea0067f31c9fc2ab0f +b3e2ffdd5ee6fd110b982fd4fad4b93d0fca65478f986d086eeccb0804960bfaa1919afa743c2239973ea65091fe57d2 +8ce0ce05e7d7160d44574011da687454dbd3c8b8290aa671731b066e2c82f8cf2d63cb8e932d78c6122ec610e44660e6 +ab005dd8d297045c39e2f72fb1c48edb501ccf3575d3d04b9817b3afee3f0bb0f3f53f64bda37d1d9cde545aae999bae +95bd7edb4c4cd60e3cb8a72558845a3cce6bb7032ccdf33d5a49ebb6ddf203bc3c79e7b7e550735d2d75b04c8b2441e8 +889953ee256206284094e4735dbbb17975bafc7c3cb94c9fbfee4c3e653857bfd49e818f64a47567f721b98411a3b454 +b188423e707640ab0e75a061e0b62830cde8afab8e1ad3dae30db69ffae4e2fc005bababbdcbd7213b918ed4f70e0c14 +a97e0fafe011abd70d4f99a0b36638b3d6e7354284588f17a88970ed48f348f88392779e9a038c6cbc9208d998485072 +87db11014a91cb9b63e8dfaa82cdebca98272d89eb445ee1e3ff9dbaf2b3fad1a03b888cffc128e4fe208ed0dddece0f +aad2e40364edd905d66ea4ac9d51f9640d6fda9a54957d26ba233809851529b32c85660fa401dbee3679ec54fa6dd966 +863e99336ca6edf03a5a259e59a2d0f308206e8a2fb320cfc0be06057366df8e0f94b33a28f574092736b3c5ada84270 +b34bcc56a057589f34939a1adc51de4ff6a9f4fee9c7fa9aa131e28d0cf0759a0c871b640162acdfbf91f3f1b59a3703 +935dd28f2896092995c5eff1618e5b6efe7a40178888d7826da9b0503c2d6e68a28e7fac1a334e166d0205f0695ef614 +b842cd5f8f5de5ca6c68cb4a5c1d7b451984930eb4cc18fd0934d52fdc9c3d2d451b1c395594d73bc3451432bfba653f +9014537885ce2debad736bc1926b25fdab9f69b216bf024f589c49dc7e6478c71d595c3647c9f65ff980b14f4bb2283b +8e827ccca1dd4cd21707140d10703177d722be0bbe5cac578db26f1ef8ad2909103af3c601a53795435b27bf95d0c9ed +8a0b8ad4d466c09d4f1e9167410dbe2edc6e0e6229d4b3036d30f85eb6a333a18b1c968f6ca6d6889bb08fecde017ef4 +9241ee66c0191b06266332dc9161dede384c4bb4e116dbd0890f3c3790ec5566da4568243665c4725b718ac0f6b5c179 +aeb4d5fad81d2b505d47958a08262b6f1b1de9373c2c9ba6362594194dea3e002ab03b8cbb43f867be83065d3d370f19 +8781bc83bb73f7760628629fe19e4714b494dbed444c4e4e4729b7f6a8d12ee347841a199888794c2234f51fa26fc2b9 +b58864f0acd1c2afa29367e637cbde1968d18589245d9936c9a489c6c495f54f0113ecdcbe4680ac085dd3c397c4d0c3 +94a24284afaeead61e70f3e30f87248d76e9726759445ca18cdb9360586c60cc9f0ec1c397f9675083e0b56459784e2e +aed358853f2b54dcbddf865e1816c2e89be12e940e1abfa661e2ee63ffc24a8c8096be2072fa83556482c0d89e975124 +b95374e6b4fc0765708e370bc881e271abf2e35c08b056a03b847e089831ef4fe3124b9c5849d9c276eb2e35b3daf264 +b834cdbcfb24c8f84bfa4c552e7fadc0028a140952fd69ed13a516e1314a4cd35d4b954a77d51a1b93e1f5d657d0315d +8fb6d09d23bfa90e7443753d45a918d91d75d8e12ec7d016c0dfe94e5c592ba6aaf483d2f16108d190822d955ad9cdc3 +aa315cd3c60247a6ad4b04f26c5404c2713b95972843e4b87b5a36a89f201667d70f0adf20757ebe1de1b29ae27dda50 +a116862dca409db8beff5b1ccd6301cdd0c92ca29a3d6d20eb8b87f25965f42699ca66974dd1a355200157476b998f3b +b4c2f5fe173c4dc8311b60d04a65ce1be87f070ac42e13cd19c6559a2931c6ee104859cc2520edebbc66a13dc7d30693 +8d4a02bf99b2260c334e7d81775c5cf582b00b0c982ce7745e5a90624919028278f5e9b098573bad5515ce7fa92a80c8 +8543493bf564ce6d97bd23be9bff1aba08bd5821ca834f311a26c9139c92a48f0c2d9dfe645afa95fec07d675d1fd53b +9344239d13fde08f98cb48f1f87d34cf6abe8faecd0b682955382a975e6eed64e863fa19043290c0736261622e00045c +aa49d0518f343005ca72b9e6c7dcaa97225ce6bb8b908ebbe7b1a22884ff8bfb090890364e325a0d414ad180b8f161d1 +907d7fd3e009355ab326847c4a2431f688627faa698c13c03ffdd476ecf988678407f029b8543a475dcb3dafdf2e7a9c +845f1f10c6c5dad2adc7935f5cd2e2b32f169a99091d4f1b05babe7317b9b1cdce29b5e62f947dc621b9acbfe517a258 +8f3be8e3b380ea6cdf9e9c237f5e88fd5a357e5ded80ea1fc2019810814de82501273b4da38916881125b6fa0cfd4459 +b9c7f487c089bf1d20c822e579628db91ed9c82d6ca652983aa16d98b4270c4da19757f216a71b9c13ddee3e6e43705f +8ba2d8c88ad2b872db104ea8ddbb006ec2f3749fd0e19298a804bb3a5d94de19285cc7fb19fee58a66f7851d1a66c39f +9375ecd3ed16786fe161af5d5c908f56eeb467a144d3bbddfc767e90065b7c94fc53431adebecba2b6c9b5821184d36e +a49e069bfadb1e2e8bff6a4286872e2a9765d62f0eaa4fcb0e5af4bbbed8be3510fb19849125a40a8a81d1e33e81c3eb +9522cc66757b386aa6b88619525c8ce47a5c346d590bb3647d12f991e6c65c3ab3c0cfc28f0726b6756c892eae1672be +a9a0f1f51ff877406fa83a807aeb17b92a283879f447b8a2159653db577848cc451cbadd01f70441e351e9ed433c18bc +8ff7533dcff6be8714df573e33f82cf8e9f2bcaaa43e939c4759d52b754e502717950de4b4252fb904560fc31dce94a4 +959724671e265a28d67c29d95210e97b894b360da55e4cf16e6682e7912491ed8ca14bfaa4dce9c25a25b16af580494f +92566730c3002f4046c737032487d0833c971e775de59fe02d9835c9858e2e3bc37f157424a69764596c625c482a2219 +a84b47ceff13ed9c3e5e9cdf6739a66d3e7c2bd8a6ba318fefb1a9aecf653bb2981da6733ddb33c4b0a4523acc429d23 +b4ddf571317e44f859386d6140828a42cf94994e2f1dcbcc9777f4eebbfc64fc1e160b49379acc27c4672b8e41835c5d +8ab95c94072b853d1603fdd0a43b30db617d13c1d1255b99075198e1947bfa5f59aed2b1147548a1b5e986cd9173d15c +89511f2eab33894fd4b3753d24249f410ff7263052c1fef6166fc63a79816656b0d24c529e45ccce6be28de6e375d916 +a0866160ca63d4f2be1b4ea050dac6b59db554e2ebb4e5b592859d8df339b46fd7cb89aaed0951c3ee540aee982c238a +8fcc5cbba1b94970f5ff2eb1922322f5b0aa7d918d4b380c9e7abfd57afd8b247c346bff7b87af82efbce3052511cd1b +99aeb2a5e846b0a2874cca02c66ed40d5569eb65ab2495bc3f964a092e91e1517941f2688e79f8cca49cd3674c4e06dc +b7a096dc3bad5ca49bee94efd884aa3ff5615cf3825cf95fbe0ce132e35f46581d6482fa82666c7ef5f1643eaee8f1ca +94393b1da6eaac2ffd186b7725eca582f1ddc8cdd916004657f8a564a7c588175cb443fc6943b39029f5bbe0add3fad8 +884b85fe012ccbcd849cb68c3ad832d83b3ef1c40c3954ffdc97f103b1ed582c801e1a41d9950f6bddc1d11f19d5ec76 +b00061c00131eded8305a7ce76362163deb33596569afb46fe499a7c9d7a0734c084d336b38d168024c2bb42b58e7660 +a439153ac8e6ca037381e3240e7ba08d056c83d7090f16ed538df25901835e09e27de2073646e7d7f3c65056af6e4ce7 +830fc9ca099097d1f38b90e6843dc86f702be9d20bdacc3e52cae659dc41df5b8d2c970effa6f83a5229b0244a86fe22 +b81ea2ffaaff2bb00dd59a9ab825ba5eed4db0d8ac9c8ed1a632ce8f086328a1cddd045fbe1ace289083c1325881b7e7 +b51ea03c58daf2db32c99b9c4789b183365168cb5019c72c4cc91ac30b5fb7311d3db76e6fa41b7cd4a8c81e2f6cdc94 +a4170b2c6d09ca5beb08318730419b6f19215ce6c631c854116f904be3bc30dd85a80c946a8ab054d3e307afaa3f8fbc +897cc42ff28971ff54d2a55dd6b35cfb8610ac902f3c06e3a5cea0e0a257e870c471236a8e84709211c742a09c5601a6 +a18f2e98d389dace36641621488664ecbb422088ab03b74e67009b8b8acacaaa24fdcf42093935f355207d934adc52a8 +92adcfb678cc2ba19c866f3f2b988fdcb4610567f3ab436cc0cb9acaf5a88414848d71133ebdbec1983e38e6190f1b5f +a86d43c2ce01b366330d3b36b3ca85f000c3548b8297e48478da1ee7d70d8576d4650cba7852ed125c0d7cb6109aa7f3 +8ed31ceed9445437d7732dce78a762d72ff32a7636bfb3fd7974b7ae15db414d8184a1766915244355deb354fbc5803b +9268f70032584f416e92225d65af9ea18c466ebc7ae30952d56a4e36fd9ea811dde0a126da9220ba3c596ec54d8a335e +9433b99ee94f2d3fbdd63b163a2bdf440379334c52308bd24537f7defd807145a062ff255a50d119a7f29f4b85d250e3 +90ce664f5e4628a02278f5cf5060d1a34f123854634b1870906e5723ac9afd044d48289be283b267d45fcbf3f4656aaf +aaf21c4d59378bb835d42ae5c5e5ab7a3c8c36a59e75997989313197752b79a472d866a23683b329ea69b048b87fa13e +b83c0589b304cec9ede549fde54f8a7c2a468c6657da8c02169a6351605261202610b2055c639b9ed2d5b8c401fb8f56 +9370f326ea0f170c2c05fe2c5a49189f20aec93b6b18a5572a818cd4c2a6adb359e68975557b349fb54f065d572f4c92 +ac3232fa5ce6f03fca238bef1ce902432a90b8afce1c85457a6bee5571c033d4bceefafc863af04d4e85ac72a4d94d51 +80d9ea168ff821b22c30e93e4c7960ce3ad3c1e6deeebedd342a36d01bd942419b187e2f382dbfd8caa34cca08d06a48 +a387a3c61676fb3381eefa2a45d82625635a666e999aba30e3b037ec9e040f414f9e1ad9652abd3bcad63f95d85038db +a1b229fe32121e0b391b0f6e0180670b9dc89d79f7337de4c77ea7ad0073e9593846f06797c20e923092a08263204416 +92164a9d841a2b828cedf2511213268b698520f8d1285852186644e9a0c97512cafa4bfbe29af892c929ebccd102e998 +82ee2fa56308a67c7db4fd7ef539b5a9f26a1c2cc36da8c3206ba4b08258fbb3cec6fe5cdbd111433fb1ba2a1e275927 +8c77bfe9e191f190a49d46f05600603fa42345592539b82923388d72392404e0b29a493a15e75e8b068dddcd444c2928 +80b927f93ccf79dcf5c5b20bcf5a7d91d7a17bc0401bb7cc9b53a6797feac31026eb114257621f5a64a52876e4474cc1 +b6b68b6501c37804d4833d5a063dd108a46310b1400549074e3cac84acc6d88f73948b7ad48d686de89c1ec043ae8c1a +ab3da00f9bdc13e3f77624f58a3a18fc3728956f84b5b549d62f1033ae4b300538e53896e2d943f160618e05af265117 +b6830e87233b8eace65327fdc764159645b75d2fd4024bf8f313b2dd5f45617d7ecfb4a0b53ccafb5429815a9a1adde6 +b9251cfe32a6dc0440615aadcd98b6b1b46e3f4e44324e8f5142912b597ee3526bea2431e2b0282bb58f71be5b63f65e +af8d70711e81cdddfb39e67a1b76643292652584c1ce7ce4feb1641431ad596e75c9120e85f1a341e7a4da920a9cdd94 +98cd4e996594e89495c078bfd52a4586b932c50a449a7c8dfdd16043ca4cda94dafbaa8ad1b44249c99bbcc52152506e +b9fc6d1c24f48404a4a64fbe3e43342738797905db46e4132aee5f086aaa4c704918ad508aaefa455cfe1b36572e6242 +a365e871d30ba9291cedaba1be7b04e968905d003e9e1af7e3b55c5eb048818ae5b913514fb08b24fb4fbdccbb35d0b8 +93bf99510971ea9af9f1e364f1234c898380677c8e8de9b0dd24432760164e46c787bc9ec42a7ad450500706cf247b2d +b872f825a5b6e7b9c7a9ddfeded3516f0b1449acc9b4fd29fc6eba162051c17416a31e5be6d3563f424d28e65bab8b8f +b06b780e5a5e8eb4f4c9dc040f749cf9709c8a4c9ef15e925f442b696e41e5095db0778a6c73bcd329b265f2c6955c8b +848f1a981f5fc6cd9180cdddb8d032ad32cdfa614fc750d690dbae36cc0cd355cbf1574af9b3ffc8b878f1b2fafb9544 +a03f48cbff3e9e8a3a655578051a5ae37567433093ac500ed0021c6250a51b767afac9bdb194ee1e3eac38a08c0eaf45 +b5be78ce638ff8c4aa84352b536628231d3f7558c5be3bf010b28feac3022e64691fa672f358c8b663904aebe24a54ed +a9d4da70ff676fa55d1728ba6ab03b471fa38b08854d99e985d88c2d050102d8ccffbe1c90249a5607fa7520b15fe791 +8fe9f7092ffb0b69862c8e972fb1ecf54308c96d41354ed0569638bb0364f1749838d6d32051fff1599112978c6e229c +ae6083e95f37770ecae0df1e010456f165d96cfe9a7278c85c15cffd61034081ce5723e25e2bede719dc9341ec8ed481 +a260891891103089a7afbd9081ea116cfd596fd1015f5b65e10b0961eb37fab7d09c69b7ce4be8bf35e4131848fb3fe4 +8d729fa32f6eb9fd2f6a140bef34e8299a2f3111bffd0fe463aa8622c9d98bfd31a1df3f3e87cd5abc52a595f96b970e +a30ec6047ae4bc7da4daa7f4c28c93aedb1112cfe240e681d07e1a183782c9ff6783ac077c155af23c69643b712a533f +ac830726544bfe7b5467339e5114c1a75f2a2a8d89453ce86115e6a789387e23551cd64620ead6283dfa4538eb313d86 +8445c135b7a48068d8ed3e011c6d818cfe462b445095e2fbf940301e50ded23f272d799eea47683fc027430ce14613ef +95785411715c9ae9d8293ce16a693a2aa83e3cb1b4aa9f76333d0da2bf00c55f65e21e42e50e6c5772ce213dd7b4f7a0 +b273b024fa18b7568c0d1c4d2f0c4e79ec509dafac8c5951f14192d63ddbcf2d8a7512c1c1b615cc38fa3e336618e0c5 +a78b9d3ea4b6a90572eb27956f411f1d105fdb577ee2ffeec9f221da9b45db84bfe866af1f29597220c75e0c37a628d8 +a4be2bf058c36699c41513c4d667681ce161a437c09d81383244fc55e1c44e8b1363439d0cce90a3e44581fb31d49493 +b6eef13040f17dd4eba22aaf284d2f988a4a0c4605db44b8d2f4bf9567ac794550b543cc513c5f3e2820242dd704152e +87eb00489071fa95d008c5244b88e317a3454652dcb1c441213aa16b28cd3ecaa9b22fec0bdd483c1df71c37119100b1 +92d388acdcb49793afca329cd06e645544d2269234e8b0b27d2818c809c21726bc9cf725651b951e358a63c83dedee24 +ae27e219277a73030da27ab5603c72c8bd81b6224b7e488d7193806a41343dff2456132274991a4722fdb0ef265d04cd +97583e08ecb82bbc27c0c8476d710389fa9ffbead5c43001bd36c1b018f29faa98de778644883e51870b69c5ffb558b5 +90a799a8ce73387599babf6b7da12767c0591cadd36c20a7990e7c05ea1aa2b9645654ec65308ee008816623a2757a6a +a1b47841a0a2b06efd9ab8c111309cc5fc9e1d5896b3e42ed531f6057e5ade8977c29831ce08dbda40348386b1dcc06d +b92b8ef59bbddb50c9457691bc023d63dfcc54e0fd88bd5d27a09e0d98ac290fc90e6a8f6b88492043bf7c87fac8f3e4 +a9d6240b07d62e22ec8ab9b1f6007c975a77b7320f02504fc7c468b4ee9cfcfd945456ff0128bc0ef2174d9e09333f8d +8e96534c94693226dc32bca79a595ca6de503af635f802e86442c67e77564829756961d9b701187fe91318da515bf0e6 +b6ba290623cd8dd5c2f50931c0045d1cfb0c30877bc8fe58cbc3ff61ee8da100045a39153916efa1936f4aee0892b473 +b43baa7717fac02d4294f5b3bb5e58a65b3557747e3188b482410388daac7a9c177f762d943fd5dcf871273921213da8 +b9cf00f8fb5e2ef2b836659fece15e735060b2ea39b8e901d3dcbdcf612be8bf82d013833718c04cd46ffaa70b85f42e +8017d0c57419e414cbba504368723e751ef990cc6f05dad7b3c2de6360adc774ad95512875ab8337d110bf39a42026fa +ae7401048b838c0dcd4b26bb6c56d79d51964a0daba780970b6c97daee4ea45854ea0ac0e4139b3fe60dac189f84df65 +887b237b0cd0f816b749b21db0b40072f9145f7896c36916296973f9e6990ede110f14e5976c906d08987c9836cca57f +a88c3d5770148aee59930561ca1223aceb2c832fb5417e188dca935905301fc4c6c2c9270bc1dff7add490a125eb81c6 +b6cf9b02c0cd91895ad209e38c54039523f137b5848b9d3ad33ae43af6c20c98434952db375fe378de7866f2d0e8b18a +84ef3d322ff580c8ad584b1fe4fe346c60866eb6a56e982ba2cf3b021ecb1fdb75ecc6c29747adda86d9264430b3f816 +a0561c27224baf0927ad144cb71e31e54a064c598373fcf0d66aebf98ab7af1d8e2f343f77baefff69a6da750a219e11 +aa5cc43f5b8162b016f5e1b61214c0c9d15b1078911c650b75e6cdfb49b85ee04c6739f5b1687d15908444f691f732de +ad4ac099b935589c7b8fdfdf3db332b7b82bb948e13a5beb121ebd7db81a87d278024a1434bcf0115c54ca5109585c3d +8a00466abf3f109a1dcd19e643b603d3af23d42794ef8ca2514dd507ecea44a031ac6dbc18bd02f99701168b25c1791e +b00b5900dfad79645f8bee4e5adc7b84eb22e5b1e67df77ccb505b7fc044a6c08a8ea5faca662414eb945f874f884cea +950e204e5f17112250b22ea6bb8423baf522fc0af494366f18fe0f949f51d6e6812074a80875cf1ed9c8e7420058d541 +91e5cbf8bb1a1d50c81608c9727b414d0dd2fb467ebc92f100882a3772e54f94979cfdf8e373fdef7c7fcdd60fec9e00 +a093f6a857b8caaff80599c2e89c962b415ecbaa70d8fd973155fa976a284c6b29a855f5f7a3521134d00d2972755188 +b4d55a3551b00da54cc010f80d99ddd2544bde9219a3173dfaadf3848edc7e4056ab532fb75ac26f5f7141e724267663 +a03ea050fc9b011d1b04041b5765d6f6453a93a1819cd9bd6328637d0b428f08526466912895dcc2e3008ee58822e9a7 +99b12b3665e473d01bc6985844f8994fb65cb15745024fb7af518398c4a37ff215da8f054e8fdf3286984ae36a73ca5e +9972c7e7a7fb12e15f78d55abcaf322c11249cd44a08f62c95288f34f66b51f146302bce750ff4d591707075d9123bd2 +a64b4a6d72354e596d87cda213c4fc2814009461570ccb27d455bbe131f8d948421a71925425b546d8cf63d5458cd64b +91c215c73b195795ede2228b7ed1f6e37892e0c6b0f4a0b5a16c57aa1100c84df9239054a173b6110d6c2b7f4bf1ce52 +88807198910ec1303480f76a3683870246a995e36adaeadc29c22f0bdba8152fe705bd070b75de657b04934f7d0ccf80 +b37c0026c7b32eb02cacac5b55cb5fe784b8e48b2945c64d3037af83ece556a117f0ff053a5968c2f5fa230e291c1238 +94c768384ce212bc2387e91ce8b45e4ff120987e42472888a317abc9dcdf3563b62e7a61c8e98d7cdcbe272167d91fc6 +a10c2564936e967a390cb14ef6e8f8b04ea9ece5214a38837eda09e79e0c7970b1f83adf017c10efd6faa8b7ffa2c567 +a5085eed3a95f9d4b1269182ea1e0d719b7809bf5009096557a0674bde4201b0ddc1f0f16a908fc468846b3721748ce3 +87468eb620b79a0a455a259a6b4dfbc297d0d53336537b771254dd956b145dc816b195b7002647ea218552e345818a3f +ace2b77ffb87366af0a9cb5d27d6fc4a14323dbbf1643f5f3c4559306330d86461bb008894054394cbfaefeaa0bc2745 +b27f56e840a54fbd793f0b7a7631aa4cee64b5947e4382b2dfb5eb1790270288884c2a19afebe5dc0c6ef335d4531c1c +876e438633931f7f895062ee16c4b9d10428875f7bc79a8e156a64d379a77a2c45bf5430c5ab94330f03da352f1e9006 +a2512a252587d200d2092b44c914df54e04ff8bcef36bf631f84bde0cf5a732e3dc7f00f662842cfd74b0b0f7f24180e +827f1bc8f54a35b7a4bd8154f79bcc055e45faed2e74adf7cf21cca95df44d96899e847bd70ead6bb27b9c0ed97bbd8b +a0c92cf5a9ed843714f3aea9fe7b880f622d0b4a3bf66de291d1b745279accf6ba35097849691370f41732ba64b5966b +a63f5c1e222775658421c487b1256b52626c6f79cb55a9b7deb2352622cedffb08502042d622eb3b02c97f9c09f9c957 +8cc093d52651e65fb390e186db6cc4de559176af4624d1c44cb9b0e836832419dacac7b8db0627b96288977b738d785d +aa7b6a17dfcec146134562d32a12f7bd7fe9522e300859202a02939e69dbd345ed7ff164a184296268f9984f9312e8fc +8ac76721f0d2b679f023d06cbd28c85ae5f4b43c614867ccee88651d4101d4fd352dbdb65bf36bfc3ebc0109e4b0c6f9 +8d350f7c05fc0dcd9a1170748846fb1f5d39453e4cb31e6d1457bed287d96fc393b2ecc53793ca729906a33e59c6834a +b9913510dfc5056d7ec5309f0b631d1ec53e3a776412ada9aefdaf033c90da9a49fdde6719e7c76340e86599b1f0eec2 +94955626bf4ce87612c5cfffcf73bf1c46a4c11a736602b9ba066328dc52ad6d51e6d4f53453d4ed55a51e0aad810271 +b0fcab384fd4016b2f1e53f1aafd160ae3b1a8865cd6c155d7073ecc1664e05b1d8bca1def39c158c7086c4e1103345e +827de3f03edfbde08570b72de6662c8bfa499b066a0a27ebad9b481c273097d17a5a0a67f01553da5392ec3f149b2a78 +ab7940384c25e9027c55c40df20bd2a0d479a165ced9b1046958353cd69015eeb1e44ed2fd64e407805ba42df10fc7bf +8ad456f6ff8cd58bd57567d931f923d0c99141978511b17e03cab7390a72b9f62498b2893e1b05c7c22dd274e9a31919 +ac75399e999effe564672db426faa17a839e57c5ef735985c70cd559a377adec23928382767b55ed5a52f7b11b54b756 +b17f975a00b817299ac7af5f2024ea820351805df58b43724393bfb3920a8cd747a3bbd4b8286e795521489db3657168 +a2bed800a6d95501674d9ee866e7314063407231491d794f8cf57d5be020452729c1c7cefd8c50dc1540181f5caab248 +9743f5473171271ffdd3cc59a3ae50545901a7b45cd4bc3570db487865f3b73c0595bebabbfe79268809ee1862e86e4a +b7eab77c2d4687b60d9d7b04e842b3880c7940140012583898d39fcc22d9b9b0a9be2c2e3788b3e6f30319b39c338f09 +8e2b8f797a436a1b661140e9569dcf3e1eea0a77c7ff2bc4ff0f3e49af04ed2de95e255df8765f1d0927fb456a9926b1 +8aefea201d4a1f4ff98ffce94e540bb313f2d4dfe7e9db484a41f13fc316ed02b282e1acc9bc6f56cad2dc2e393a44c9 +b950c17c0e5ca6607d182144aa7556bb0efe24c68f06d79d6413a973b493bfdf04fd147a4f1ab03033a32004cc3ea66f +b7b8dcbb179a07165f2dc6aa829fad09f582a71b05c3e3ea0396bf9e6fe73076f47035c031c2101e8e38e0d597eadd30 +a9d77ed89c77ec1bf8335d08d41c3c94dcca9fd1c54f22837b4e54506b212aa38d7440126c80648ab7723ff18e65ed72 +a819d6dfd4aef70e52b8402fe5d135f8082d40eb7d3bb5c4d7997395b621e2bb10682a1bad2c9caa33dd818550fc3ec6 +8f6ee34128fac8bbf13ce2d68b2bb363eb4fd65b297075f88e1446ddeac242500eeb4ef0735e105882ff5ba8c44c139b +b4440e48255c1644bcecf3a1e9958f1ec4901cb5b1122ee5b56ffd02cad1c29c4266999dbb85aa2605c1b125490074d4 +a43304a067bede5f347775d5811cf65a6380a8d552a652a0063580b5c5ef12a0867a39c7912fa219e184f4538eba1251 +a891ad67a790089ffc9f6d53e6a3d63d3556f5f693e0cd8a7d0131db06fd4520e719cfcc3934f0a8f62a95f90840f1d4 +aea6df8e9bb871081aa0fc5a9bafb00be7d54012c5baf653791907d5042a326aeee966fd9012a582cc16695f5baf7042 +8ffa2660dc52ed1cd4eff67d6a84a8404f358a5f713d04328922269bee1e75e9d49afeec0c8ad751620f22352a438e25 +87ec6108e2d63b06abed350f8b363b7489d642486f879a6c3aa90e5b0f335efc2ff2834eef9353951a42136f8e6a1b32 +865619436076c2760d9e87ddc905023c6de0a8d56eef12c98a98c87837f2ca3f27fd26a2ad752252dbcbe2b9f1d5a032 +980437dce55964293cb315c650c5586ffd97e7a944a83f6618af31c9d92c37b53ca7a21bb5bc557c151b9a9e217e7098 +95d128fc369df4ad8316b72aea0ca363cbc7b0620d6d7bb18f7076a8717a6a46956ff140948b0cc4f6d2ce33b5c10054 +8c7212d4a67b9ec70ebbca04358ad2d36494618d2859609163526d7b3acc2fc935ca98519380f55e6550f70a9bc76862 +893a2968819401bf355e85eee0f0ed0406a6d4a7d7f172d0017420f71e00bb0ba984f6020999a3cdf874d3cd8ebcd371 +9103c1af82dece25d87274e89ea0acd7e68c2921c4af3d8d7c82ab0ed9990a5811231b5b06113e7fa43a6bd492b4564f +99cfd87a94eab7d35466caa4ed7d7bb45e5c932b2ec094258fb14bf205659f83c209b83b2f2c9ccb175974b2a33e7746 +874b6b93e4ee61be3f00c32dd84c897ccd6855c4b6251eb0953b4023634490ed17753cd3223472873cbc6095b2945075 +84a32c0dc4ea60d33aac3e03e70d6d639cc9c4cc435c539eff915017be3b7bdaba33349562a87746291ebe9bc5671f24 +a7057b24208928ad67914e653f5ac1792c417f413d9176ba635502c3f9c688f7e2ee81800d7e3dc0a340c464da2fd9c5 +a03fb9ed8286aacfa69fbd5d953bec591c2ae4153400983d5dbb6cd9ea37fff46ca9e5cceb9d117f73e9992a6c055ad2 +863b2de04e89936c9a4a2b40380f42f20aefbae18d03750fd816c658aee9c4a03df7b12121f795c85d01f415baaeaa59 +8526eb9bd31790fe8292360d7a4c3eed23be23dd6b8b8f01d2309dbfdc0cfd33ad1568ddd7f8a610f3f85a9dfafc6a92 +b46ab8c5091a493d6d4d60490c40aa27950574a338ea5bbc045be3a114af87bdcb160a8c80435a9b7ad815f3cb56a3f3 +aeadc47b41a8d8b4176629557646202f868b1d728b2dda58a347d937e7ffc8303f20d26d6c00b34c851b8aeec547885d +aebb19fc424d72c1f1822aa7adc744cd0ef7e55727186f8df8771c784925058c248406ebeeaf3c1a9ee005a26e9a10c6 +8ff96e81c1a4a2ab1b4476c21018fae0a67e92129ee36120cae8699f2d7e57e891f5c624902cb1b845b944926a605cc3 +8251b8d2c43fadcaa049a9e7aff838dae4fb32884018d58d46403ac5f3beb5c518bfd45f03b8abb710369186075eb71c +a8b2a64f865f51a5e5e86a66455c093407933d9d255d6b61e1fd81ffafc9538d73caaf342338a66ba8ee166372a3d105 +aad915f31c6ba7fdc04e2aaac62e84ef434b7ee76a325f07dc430d12c84081999720181067b87d792efd0117d7ee1eab +a13db3bb60389883fd41d565c54fb5180d9c47ce2fe7a169ae96e01d17495f7f4fa928d7e556e7c74319c4c25d653eb2 +a4491b0198459b3f552855d680a59214eb74e6a4d6c5fa3b309887dc50ebea2ecf6d26c040550f7dc478b452481466fb +8f017f13d4b1e3f0c087843582b52d5f8d13240912254d826dd11f8703a99a2f3166dfbdfdffd9a3492979d77524276b +96c3d5dcd032660d50d7cd9db2914f117240a63439966162b10c8f1f3cf74bc83b0f15451a43b31dbd85e4a7ce0e4bb1 +b479ec4bb79573d32e0ec93b92bdd7ec8c26ddb5a2d3865e7d4209d119fd3499eaac527615ffac78c440e60ef3867ae0 +b2c49c4a33aa94b52b6410b599e81ff15490aafa7e43c8031c865a84e4676354a9c81eb4e7b8be6825fdcefd1e317d44 +906dc51d6a90c089b6704b47592805578a6eed106608eeb276832f127e1b8e858b72e448edcbefb497d152447e0e68ff +b0e81c63b764d7dfbe3f3fddc9905aef50f3633e5d6a4af6b340495124abedcff5700dfd1577bbbed7b6bf97d02719cb +9304c64701e3b4ed6d146e48a881f7d83a17f58357cca0c073b2bb593afd2d94f6e2a7a1ec511d0a67ad6ff4c3be5937 +b6fdbd12ba05aa598d80b83f70a15ef90e5cba7e6e75fa038540ee741b644cd1f408a6cecfd2a891ef8d902de586c6b5 +b80557871a6521b1b3c74a1ba083ae055b575df607f1f7b04c867ba8c8c181ea68f8d90be6031f4d25002cca27c44da2 +aa7285b8e9712e06b091f64163f1266926a36607f9d624af9996856ed2aaf03a580cb22ce407d1ade436c28b44ca173f +8148d72b975238b51e6ea389e5486940d22641b48637d7dfadfa603a605bfc6d74a016480023945d0b85935e396aea5d +8a014933a6aea2684b5762af43dcf4bdbb633cd0428d42d71167a2b6fc563ece5e618bff22f1db2ddb69b845b9a2db19 +990d91740041db770d0e0eb9d9d97d826f09fd354b91c41e0716c29f8420e0e8aac0d575231efba12fe831091ec38d5a +9454d0d32e7e308ddec57cf2522fb1b67a2706e33fb3895e9e1f18284129ab4f4c0b7e51af25681d248d7832c05eb698 +a5bd434e75bac105cb3e329665a35bce6a12f71dd90c15165777d64d4c13a82bceedb9b48e762bd24034e0fc9fbe45f4 +b09e3b95e41800d4dc29c6ffdaab2cd611a0050347f6414f154a47ee20ee59bf8cf7181454169d479ebce1eb5c777c46 +b193e341d6a047d15eea33766d656d807b89393665a783a316e9ba10518e5515c8e0ade3d6e15641d917a8a172a5a635 +ade435ec0671b3621dde69e07ead596014f6e1daa1152707a8c18877a8b067bde2895dd47444ffa69db2bbef1f1d8816 +a7fd3d6d87522dfc56fb47aef9ce781a1597c56a8bbfd796baba907afdc872f753d732bfda1d3402aee6c4e0c189f52d +a298cb4f4218d0464b2fab393e512bbc477c3225aa449743299b2c3572f065bc3a42d07e29546167ed9e1b6b3b3a3af3 +a9ee57540e1fd9c27f4f0430d194b91401d0c642456c18527127d1f95e2dba41c2c86d1990432eb38a692fda058fafde +81d6c1a5f93c04e6d8e5a7e0678c1fc89a1c47a5c920bcd36180125c49fcf7c114866b90e90a165823560b19898a7c16 +a4b7a1ec9e93c899b9fd9aaf264c50e42c36c0788d68296a471f7a3447af4dbc81e4fa96070139941564083ec5b5b5a1 +b3364e327d381f46940c0e11e29f9d994efc6978bf37a32586636c0070b03e4e23d00650c1440f448809e1018ef9f6d8 +8056e0913a60155348300e3a62e28b5e30629a90f7dd4fe11289097076708110a1d70f7855601782a3cdc5bdb1ca9626 +b4980fd3ea17bac0ba9ee1c470b17e575bb52e83ebdd7d40c93f4f87bebeaff1c8a679f9d3d09d635f068d37d5bd28bd +905a9299e7e1853648e398901dfcd437aa575c826551f83520df62984f5679cb5f0ea86aa45ed3e18b67ddc0dfafe809 +ab99553bf31a84f2e0264eb34a08e13d8d15e2484aa9352354becf9a15999c76cc568d68274b70a65e49703fc23540d0 +a43681597bc574d2dae8964c9a8dc1a07613d7a1272bdcb818d98c85d44e16d744250c33f3b5e4d552d97396b55e601f +a54e5a31716fccb50245898c99865644405b8dc920ded7a11f3d19bdc255996054b268e16f2e40273f11480e7145f41e +8134f3ad5ef2ad4ba12a8a4e4d8508d91394d2bcdc38b7c8c8c0b0a820357ac9f79d286c65220f471eb1adca1d98fc68 +94e2f755e60471578ab2c1adb9e9cea28d4eec9b0e92e0140770bca7002c365fcabfe1e5fb4fe6cfe79a0413712aa3ef +ad48f8d0ce7eb3cc6e2a3086ad96f562e5bed98a360721492ae2e74dc158586e77ec8c35d5fd5927376301b7741bad2b +8614f0630bdd7fbad3a31f55afd9789f1c605dc85e7dc67e2edfd77f5105f878bb79beded6e9f0b109e38ea7da67e8d5 +9804c284c4c5e77dabb73f655b12181534ca877c3e1e134aa3f47c23b7ec92277db34d2b0a5d38d2b69e5d1c3008a3e3 +a51b99c3088e473afdaa9e0a9f7e75a373530d3b04e44e1148da0726b95e9f5f0c7e571b2da000310817c36f84b19f7f +ac4ff909933b3b76c726b0a382157cdc74ab851a1ac6cef76953c6444441804cc43abb883363f416592e8f6cfbc4550b +ae7d915eb9fc928b65a29d6edbc75682d08584d0014f7bcf17d59118421ae07d26a02137d1e4de6938bcd1ab8ef48fad +852f7e453b1af89b754df6d11a40d5d41ea057376e8ecacd705aacd2f917457f4a093d6b9a8801837fa0f62986ad7149 +92c6bf5ada5d0c3d4dd8058483de36c215fa98edab9d75242f3eff9db07c734ad67337da6f0eefe23a487bf75a600dee +a2b42c09d0db615853763552a48d2e704542bbd786aae016eb58acbf6c0226c844f5fb31e428cb6450b9db855f8f2a6f +880cc07968266dbfdcfbc21815cd69e0eddfee239167ac693fb0413912d816f2578a74f7716eecd6deefa68c6eccd394 +b885b3ace736cd373e8098bf75ba66fa1c6943ca1bc4408cd98ac7074775c4478594f91154b8a743d9c697e1b29f5840 +a51ce78de512bd87bfa0835de819941dffbf18bec23221b61d8096fc9436af64e0693c335b54e7bfc763f287bdca2db6 +a3c76166a3bdb9b06ef696e57603b58871bc72883ee9d45171a30fe6e1d50e30bc9c51b4a0f5a7270e19a77b89733850 +acefc5c6f8a1e7c24d7b41e0fc7f6f3dc0ede6cf3115ffb9a6e54b1d954cbca9bda8ad7a084be9be245a1b8e9770d141 +b420ed079941842510e31cfad117fa11fb6b4f97dfbc6298cb840f27ebaceba23eeaf3f513bcffbf5e4aae946310182d +95c3bb5ef26c5ed2f035aa5d389c6b3c15a6705b9818a3fefaed28922158b35642b2e8e5a1a620fdad07e75ad4b43af4 +825149f9081ecf07a2a4e3e8b5d21bade86c1a882475d51c55ee909330b70c5a2ac63771c8600c6f38df716af61a3ea1 +873b935aae16d9f08adbc25353cee18af2f1b8d5f26dec6538d6bbddc515f2217ed7d235dcfea59ae61b428798b28637 +9294150843a2bedcedb3bb74c43eb28e759cf9499582c5430bccefb574a8ddd4f11f9929257ff4c153990f9970a2558f +b619563a811cc531da07f4f04e5c4c6423010ff9f8ed7e6ec9449162e3d501b269fb1c564c09c0429431879b0f45df02 +91b509b87eb09f007d839627514658c7341bc76d468920fe8a740a8cb96a7e7e631e0ea584a7e3dc1172266f641d0f5c +8b8aceace9a7b9b4317f1f01308c3904d7663856946afbcea141a1c615e21ccad06b71217413e832166e9dd915fbe098 +87b3b36e725833ea0b0f54753c3728c0dbc87c52d44d705ffc709f2d2394414c652d3283bab28dcce09799504996cee0 +b2670aad5691cbf308e4a6a77a075c4422e6cbe86fdba24e9f84a313e90b0696afb6a067eebb42ba2d10340d6a2f6e51 +876784a9aff3d54faa89b2bacd3ff5862f70195d0b2edc58e8d1068b3c9074c0da1cfa23671fe12f35e33b8a329c0ccd +8b48b9e758e8a8eae182f5cbec96f67d20cca6d3eee80a2d09208eb1d5d872e09ef23d0df8ebbb9b01c7449d0e3e3650 +b79303453100654c04a487bdcadc9e3578bc80930c489a7069a52e8ca1dba36c492c8c899ce025f8364599899baa287d +961b35a6111da54ece6494f24dacd5ea46181f55775b5f03df0e370c34a5046ac2b4082925855325bb42bc2a2c98381d +a31feb1be3f5a0247a1f7d487987eb622e34fca817832904c6ee3ee60277e5847945a6f6ea1ac24542c72e47bdf647df +a12a2aa3e7327e457e1aae30e9612715dd2cfed32892c1cd6dcda4e9a18203af8a44afb46d03b2eed89f6b9c5a2c0c23 +a08265a838e69a2ca2f80fead6ccf16f6366415b920c0b22ee359bcd8d4464ecf156f400a16a7918d52e6d733dd64211 +b723d6344e938d801cca1a00032af200e541d4471fd6cbd38fb9130daa83f6a1dffbbe7e67fc20f9577f884acd7594b2 +a6733d83ec78ba98e72ddd1e7ff79b7adb0e559e256760d0c590a986e742445e8cdf560d44b29439c26d87edd0b07c8c +a61c2c27d3f7b9ff4695a17afedf63818d4bfba390507e1f4d0d806ce8778d9418784430ce3d4199fd3bdbc2504d2af3 +8332f3b63a6dc985376e8b1b25eeae68be6160fbe40053ba7bcf6f073204f682da72321786e422d3482fd60c9e5aa034 +a280f44877583fbb6b860d500b1a3f572e3ee833ec8f06476b3d8002058e25964062feaa1e5bec1536d734a5cfa09145 +a4026a52d277fcea512440d2204f53047718ebfcae7b48ac57ea7f6bfbc5de9d7304db9a9a6cbb273612281049ddaec5 +95cdf69c831ab2fad6c2535ede9c07e663d2ddccc936b64e0843d2df2a7b1c31f1759c3c20f1e7a57b1c8f0dbb21b540 +95c96cec88806469c277ab567863c5209027cecc06c7012358e5f555689c0d9a5ffb219a464f086b45817e8536b86d2f +afe38d4684132a0f03d806a4c8df556bf589b25271fbc6fe2e1ed16de7962b341c5003755da758d0959d2e6499b06c68 +a9b77784fda64987f97c3a23c5e8f61b918be0f7c59ba285084116d60465c4a2aaafc8857eb16823282cc83143eb9126 +a830f05881ad3ce532a55685877f529d32a5dbe56cea57ffad52c4128ee0fad0eeaf0da4362b55075e77eda7babe70e5 +992b3ad190d6578033c13ed5abfee4ef49cbc492babb90061e3c51ee4b5790cdd4c8fc1abff1fa2c00183b6b64f0bbbe +b1015424d9364aeff75de191652dc66484fdbec3e98199a9eb9671ec57bec6a13ff4b38446e28e4d8aedb58dd619cd90 +a745304604075d60c9db36cada4063ac7558e7ec2835d7da8485e58d8422e817457b8da069f56511b02601289fbb8981 +a5ba4330bc5cb3dbe0486ddf995632a7260a46180a08f42ae51a2e47778142132463cc9f10021a9ad36986108fefa1a9 +b419e9fd4babcaf8180d5479db188bb3da232ae77a1c4ed65687c306e6262f8083070a9ac32220cddb3af2ec73114092 +a49e23dc5f3468f3bf3a0bb7e4a114a788b951ff6f23a3396ae9e12cbff0abd1240878a3d1892105413dbc38818e807c +b7ecc7b4831f650202987e85b86bc0053f40d983f252e9832ef503aea81c51221ce93279da4aa7466c026b2d2070e55d +96a8c35cb87f84fa84dcd6399cc2a0fd79cc9158ef4bdde4bae31a129616c8a9f2576cd19baa3f497ca34060979aed7d +8681b2c00aa62c2b519f664a95dcb8faef601a3b961bb4ce5d85a75030f40965e2983871d41ea394aee934e859581548 +85c229a07efa54a713d0790963a392400f55fbb1a43995a535dc6c929f20d6a65cf4efb434e0ad1cb61f689b8011a3bc +90856f7f3444e5ad44651c28e24cc085a5db4d2ffe79aa53228c26718cf53a6e44615f3c5cda5aa752d5f762c4623c66 +978999b7d8aa3f28a04076f74d11c41ef9c89fdfe514936c4238e0f13c38ec97e51a5c078ebc6409e517bfe7ccb42630 +a099914dd7ed934d8e0d363a648e9038eb7c1ec03fa04dbcaa40f7721c618c3ef947afef7a16b4d7ac8c12aa46637f03 +ab2a104fed3c83d16f2cda06878fa5f30c8c9411de71bfb67fd2fc9aa454dcbcf3d299d72f8cc12e919466a50fcf7426 +a4471d111db4418f56915689482f6144efc4664cfb0311727f36c864648d35734351becc48875df96f4abd3cfcf820f9 +83be11727cd30ea94ccc8fa31b09b81c9d6a9a5d3a4686af9da99587332fe78c1f94282f9755854bafd6033549afec91 +88020ff971dc1a01a9e993cd50a5d2131ffdcbb990c1a6aaa54b20d8f23f9546a70918ea57a21530dcc440c1509c24ad +ae24547623465e87905eaffa1fa5d52bb7c453a8dbd89614fa8819a2abcedaf455c2345099b7324ae36eb0ad7c8ef977 +b59b0c60997de1ee00b7c388bc7101d136c9803bf5437b1d589ba57c213f4f835a3e4125b54738e78abbc21b000f2016 +a584c434dfe194546526691b68fa968c831c31da42303a1d735d960901c74011d522246f37f299555416b8cf25c5a548 +80408ce3724f4837d4d52376d255e10f69eb8558399ae5ca6c11b78b98fe67d4b93157d2b9b639f1b5b64198bfe87713 +abb941e8d406c2606e0ddc35c113604fdd9d249eacc51cb64e2991e551b8639ce44d288cc92afa7a1e7fc599cfc84b22 +b223173f560cacb1c21dba0f1713839e348ad02cbfdef0626748604c86f89e0f4c919ed40b583343795bdd519ba952c8 +af1c70512ec3a19d98b8a1fc3ff7f7f5048a27d17d438d43f561974bbdd116fcd5d5c21040f3447af3f0266848d47a15 +8a44809568ebe50405bede19b4d2607199159b26a1b33e03d180e6840c5cf59d991a4fb150d111443235d75ecad085b7 +b06207cdca46b125a27b3221b5b50cf27af4c527dd7c80e2dbcebbb09778a96df3af67e50f07725239ce3583dad60660 +993352d9278814ec89b26a11c4a7c4941bf8f0e6781ae79559d14749ee5def672259792db4587f85f0100c7bb812f933 +9180b8a718b971fd27bc82c8582d19c4b4f012453e8c0ffeeeffe745581fc6c07875ab28be3af3fa3896d19f0c89ac5b +8b8e1263eb48d0fe304032dd5ea1f30e73f0121265f7458ba9054d3626894e8a5fef665340abd2ede9653045c2665938 +99a2beee4a10b7941c24b2092192faf52b819afd033e4a2de050fd6c7f56d364d0cf5f99764c3357cf32399e60fc5d74 +946a4aad7f8647ea60bee2c5fcdeb6f9a58fb2cfca70c4d10e458027a04846e13798c66506151be3df9454b1e417893f +a672a88847652d260b5472d6908d1d57e200f1e492d30dd1cecc441cdfc9b76e016d9bab560efd4d7f3c30801de884a9 +9414e1959c156cde1eb24e628395744db75fc24b9df4595350aaad0bc38e0246c9b4148f6443ef68b8e253a4a6bcf11c +9316e9e4ec5fab4f80d6540df0e3a4774db52f1d759d2e5b5bcd3d7b53597bb007eb1887cb7dc61f62497d51ffc8d996 +902d6d77bb49492c7a00bc4b70277bc28c8bf9888f4307bb017ac75a962decdedf3a4e2cf6c1ea9f9ba551f4610cbbd7 +b07025a18b0e32dd5e12ec6a85781aa3554329ea12c4cd0d3b2c22e43d777ef6f89876dd90a9c8fb097ddf61cf18adc5 +b355a849ad3227caa4476759137e813505ec523cbc2d4105bc7148a4630f9e81918d110479a2d5f5e4cd9ccec9d9d3e3 +b49532cfdf02ee760109881ad030b89c48ee3bb7f219ccafc13c93aead754d29bdafe345be54c482e9d5672bd4505080 +9477802410e263e4f938d57fa8f2a6cac7754c5d38505b73ee35ea3f057aad958cb9722ba6b7b3cfc4524e9ca93f9cdc +9148ea83b4436339580f3dbc9ba51509e9ab13c03063587a57e125432dd0915f5d2a8f456a68f8fff57d5f08c8f34d6e +b00b6b5392b1930b54352c02b1b3b4f6186d20bf21698689bbfc7d13e86538a4397b90e9d5c93fd2054640c4dbe52a4f +926a9702500441243cd446e7cbf15dde16400259726794694b1d9a40263a9fc9e12f7bcbf12a27cb9aaba9e2d5848ddc +a0c6155f42686cbe7684a1dc327100962e13bafcf3db97971fc116d9f5c0c8355377e3d70979cdbd58fd3ea52440901c +a277f899f99edb8791889d0817ea6a96c24a61acfda3ad8c3379e7c62b9d4facc4b965020b588651672fd261a77f1bfc +8f528cebb866b501f91afa50e995234bef5bf20bff13005de99cb51eaac7b4f0bf38580cfd0470de40f577ead5d9ba0f +963fc03a44e9d502cc1d23250efef44d299befd03b898d07ce63ca607bb474b5cf7c965a7b9b0f32198b04a8393821f7 +ab087438d0a51078c378bf4a93bd48ef933ff0f1fa68d02d4460820df564e6642a663b5e50a5fe509527d55cb510ae04 +b0592e1f2c54746bb076be0fa480e1c4bebc4225e1236bcda3b299aa3853e3afb401233bdbcfc4a007b0523a720fbf62 +851613517966de76c1c55a94dc4595f299398a9808f2d2f0a84330ba657ab1f357701d0895f658c18a44cb00547f6f57 +a2fe9a1dd251e72b0fe4db27be508bb55208f8f1616b13d8be288363ec722826b1a1fd729fc561c3369bf13950bf1fd6 +b896cb2bc2d0c77739853bc59b0f89b2e008ba1f701c9cbe3bef035f499e1baee8f0ff1e794854a48c320586a2dfc81a +a1b60f98e5e5106785a9b81a85423452ee9ef980fa7fa8464f4366e73f89c50435a0c37b2906052b8e58e212ebd366cf +a853b0ebd9609656636df2e6acd5d8839c0fda56f7bf9288a943b06f0b67901a32b95e016ca8bc99bd7b5eab31347e72 +b290fa4c1346963bd5225235e6bdf7c542174dab4c908ab483d1745b9b3a6015525e398e1761c90e4b49968d05e30eea +b0f65a33ad18f154f1351f07879a183ad62e5144ad9f3241c2d06533dad09cbb2253949daff1bb02d24d16a3569f7ef0 +a00db59b8d4218faf5aeafcd39231027324408f208ec1f54d55a1c41228b463b88304d909d16b718cfc784213917b71e +b8d695dd33dc2c3bc73d98248c535b2770ad7fa31aa726f0aa4b3299efb0295ba9b4a51c71d314a4a1bd5872307534d1 +b848057cca2ca837ee49c42b88422303e58ea7d2fc76535260eb5bd609255e430514e927cc188324faa8e657396d63ec +92677836061364685c2aaf0313fa32322746074ed5666fd5f142a7e8f87135f45cd10e78a17557a4067a51dfde890371 +a854b22c9056a3a24ab164a53e5c5cf388616c33e67d8ebb4590cb16b2e7d88b54b1393c93760d154208b5ca822dc68f +86fff174920388bfab841118fb076b2b0cdec3fdb6c3d9a476262f82689fb0ed3f1897f7be9dbf0932bb14d346815c63 +99661cf4c94a74e182752bcc4b98a8c2218a8f2765642025048e12e88ba776f14f7be73a2d79bd21a61def757f47f904 +8a8893144d771dca28760cba0f950a5d634195fd401ec8cf1145146286caffb0b1a6ba0c4c1828d0a5480ce49073c64c +938a59ae761359ee2688571e7b7d54692848eb5dde57ffc572b473001ea199786886f8c6346a226209484afb61d2e526 +923f68a6aa6616714cf077cf548aeb845bfdd78f2f6851d8148cba9e33a374017f2f3da186c39b82d14785a093313222 +ac923a93d7da7013e73ce8b4a2b14b8fd0cc93dc29d5de941a70285bdd19be4740fedfe0c56b046689252a3696e9c5bc +b49b32c76d4ec1a2c68d4989285a920a805993bc6fcce6dacd3d2ddae73373050a5c44ba8422a3781050682fa0ef6ba2 +8a367941c07c3bdca5712524a1411bad7945c7c48ffc7103b1d4dff2c25751b0624219d1ccde8c3f70c465f954be5445 +b838f029df455efb6c530d0e370bbbf7d87d61a9aea3d2fe5474c5fe0a39cf235ceecf9693c5c6c5820b1ba8f820bd31 +a8983b7c715eaac7f13a001d2abc462dfc1559dab4a6b554119c271aa8fe00ffcf6b6949a1121f324d6d26cb877bcbae +a2afb24ad95a6f14a6796315fbe0d8d7700d08f0cfaf7a2abe841f5f18d4fecf094406cbd54da7232a159f9c5b6e805e +87e8e95ad2d62f947b2766ff405a23f7a8afba14e7f718a691d95369c79955cdebe24c54662553c60a3f55e6322c0f6f +87c2cbcecb754e0cc96128e707e5c5005c9de07ffd899efa3437cadc23362f5a1d3fcdd30a1f5bdc72af3fb594398c2a +91afd6ee04f0496dc633db88b9370d41c428b04fd991002502da2e9a0ef051bcd7b760e860829a44fbe5539fa65f8525 +8c50e5d1a24515a9dd624fe08b12223a75ca55196f769f24748686315329b337efadca1c63f88bee0ac292dd0a587440 +8a07e8f912a38d94309f317c32068e87f68f51bdfa082d96026f5f5f8a2211621f8a3856dda8069386bf15fb2d28c18f +94ad1dbe341c44eeaf4dc133eed47d8dbfe752575e836c075745770a6679ff1f0e7883b6aa917462993a7f469d74cab5 +8745f8bd86c2bb30efa7efb7725489f2654f3e1ac4ea95bd7ad0f3cfa223055d06c187a16192d9d7bdaea7b050c6a324 +900d149c8d79418cda5955974c450a70845e02e5a4ecbcc584a3ca64d237df73987c303e3eeb79da1af83bf62d9e579f +8f652ab565f677fb1a7ba03b08004e3cda06b86c6f1b0b9ab932e0834acf1370abb2914c15b0d08327b5504e5990681c +9103097d088be1f75ab9d3da879106c2f597e2cc91ec31e73430647bdd5c33bcfd771530d5521e7e14df6acda44f38a6 +b0fec7791cfb0f96e60601e1aeced9a92446b61fedab832539d1d1037558612d78419efa87ff5f6b7aab8fd697d4d9de +b9d2945bdb188b98958854ba287eb0480ef614199c4235ce5f15fc670b8c5ffe8eeb120c09c53ea8a543a022e6a321ac +a9461bb7d5490973ebaa51afc0bb4a5e42acdccb80e2f939e88b77ac28a98870e103e1042899750f8667a8cc9123bae9 +a37fdf11d4bcb2aed74b9f460a30aa34afea93386fa4cdb690f0a71bc58f0b8df60bec56e7a24f225978b862626fa00e +a214420e183e03d531cf91661466ea2187d84b6e814b8b20b3730a9400a7d25cf23181bb85589ebc982cec414f5c2923 +ad09a45a698a6beb3e0915f540ef16e9af7087f53328972532d6b5dfe98ce4020555ece65c6cbad8bd6be8a4dfefe6fd +ab6742800b02728c92d806976764cb027413d6f86edd08ad8bb5922a2969ee9836878cd39db70db0bd9a2646862acc4f +974ca9305bd5ea1dc1755dff3b63e8bfe9f744321046c1395659bcea2a987b528e64d5aa96ac7b015650b2253b37888d +84eee9d6bce039c52c2ebc4fccc0ad70e20c82f47c558098da4be2f386a493cbc76adc795b5488c8d11b6518c2c4fab8 +875d7bda46efcb63944e1ccf760a20144df3b00d53282b781e95f12bfc8f8316dfe6492c2efbf796f1150e36e436e9df +b68a2208e0c587b5c31b5f6cb32d3e6058a9642e2d9855da4f85566e1412db528475892060bb932c55b3a80877ad7b4a +ba006368ecab5febb6ab348644d9b63de202293085ed468df8bc24d992ae8ce468470aa37f36a73630c789fb9c819b30 +90a196035150846cd2b482c7b17027471372a8ce7d914c4d82b6ea7fa705d8ed5817bd42d63886242585baf7d1397a1c +a223b4c85e0daa8434b015fd9170b5561fe676664b67064974a1e9325066ecf88fc81f97ab5011c59fad28cedd04b240 +82e8ec43139cf15c6bbeed484b62e06cded8a39b5ce0389e4cbe9c9e9c02f2f0275d8d8d4e8dfec8f69a191bef220408 +81a3fc07a7b68d92c6ee4b6d28f5653ee9ec85f7e2ee1c51c075c1b130a8c5097dc661cf10c5aff1c7114b1a6a19f11a +8ed2ef8331546d98819a5dd0e6c9f8cb2630d0847671314a28f277faf68da080b53891dd75c82cbcf7788b255490785d +acecabf84a6f9bbed6b2fc2e7e4b48f02ef2f15e597538a73aea8f98addc6badda15e4695a67ecdb505c1554e8f345ec +b8f51019b2aa575f8476e03dcadf86cc8391f007e5f922c2a36b2daa63f5a503646a468990cd5c65148d323942193051 +aaa595a84b403ec65729bc1c8055a94f874bf9adddc6c507b3e1f24f79d3ad359595a672b93aab3394db4e2d4a7d8970 +895144c55fcbd0f64d7dd69e6855cfb956e02b5658eadf0f026a70703f3643037268fdd673b0d21b288578a83c6338dd +a2e92ae6d0d237d1274259a8f99d4ea4912a299816350b876fba5ebc60b714490e198a916e1c38c6e020a792496fa23c +a45795fda3b5bb0ad1d3c628f6add5b2a4473a1414c1a232e80e70d1cfffd7f8a8d9861f8df2946999d7dbb56bf60113 +b6659bf7f6f2fef61c39923e8c23b8c70e9c903028d8f62516d16755cd3fba2fe41c285aa9432dc75ab08f8a1d8a81fc +a735609a6bc5bfd85e58234fc439ff1f58f1ff1dd966c5921d8b649e21f006bf2b8642ad8a75063c159aaf6935789293 +a3c622eb387c9d15e7bda2e3e84d007cb13a6d50d655c3f2f289758e49d3b37b9a35e4535d3cc53d8efd51f407281f19 +8afe147b53ad99220f5ef9d763bfc91f9c20caecbcf823564236fb0e6ede49414c57d71eec4772c8715cc65a81af0047 +b5f0203233cf71913951e9c9c4e10d9243e3e4a1f2cb235bf3f42009120ba96e04aa414c9938ea8873b63148478927e8 +93c52493361b458d196172d7ba982a90a4f79f03aa8008edc322950de3ce6acf4c3977807a2ffa9e924047e02072b229 +b9e72b805c8ac56503f4a86c82720afbd5c73654408a22a2ac0b2e5caccdfb0e20b59807433a6233bc97ae58cf14c70a +af0475779b5cee278cca14c82da2a9f9c8ef222eb885e8c50cca2315fea420de6e04146590ed0dd5a29c0e0812964df5 +b430ccab85690db02c2d0eb610f3197884ca12bc5f23c51e282bf3a6aa7e4a79222c3d8761454caf55d6c01a327595f9 +830032937418b26ee6da9b5206f3e24dc76acd98589e37937e963a8333e5430abd6ce3dd93ef4b8997bd41440eed75d6 +8820a6d73180f3fe255199f3f175c5eb770461ad5cfdde2fb11508041ed19b8c4ce66ad6ecebf7d7e836cc2318df47ca +aef1393e7d97278e77bbf52ef6e1c1d5db721ccf75fe753cf47a881fa034ca61eaa5098ee5a344c156d2b14ff9e284ad +8a4a26c07218948c1196c45d927ef4d2c42ade5e29fe7a91eaebe34a29900072ce5194cf28d51f746f4c4c649daf4396 +84011dc150b7177abdcb715efbd8c201f9cb39c36e6069af5c50a096021768ba40cef45b659c70915af209f904ede3b6 +b1bd90675411389bb66910b21a4bbb50edce5330850c5ab0b682393950124252766fc81f5ecfc72fb7184387238c402e +8dfdcd30583b696d2c7744655f79809f451a60c9ad5bf1226dc078b19f4585d7b3ef7fa9d54e1ac09520d95cbfd20928 +b351b4dc6d98f75b8e5a48eb7c6f6e4b78451991c9ba630e5a1b9874c15ac450cd409c1a024713bf2cf82dc400e025ef +a462b8bc97ac668b97b28b3ae24b9f5de60e098d7b23ecb600d2194cd35827fb79f77c3e50d358f5bd72ee83fef18fa0 +a183753265c5f7890270821880cce5f9b2965b115ba783c6dba9769536f57a04465d7da5049c7cf8b3fcf48146173c18 +a8a771b81ed0d09e0da4d79f990e58eabcd2be3a2680419502dd592783fe52f657fe55125b385c41d0ba3b9b9cf54a83 +a71ec577db46011689d073245e3b1c3222a9b1fe6aa5b83629adec5733dd48617ebea91346f0dd0e6cdaa86e4931b168 +a334b8b244f0d598a02da6ae0f918a7857a54dce928376c4c85df15f3b0f2ba3ac321296b8b7c9dd47d770daf16c8f8c +a29037f8ef925c417c90c4df4f9fb27fb977d04e2b3dd5e8547d33e92ab72e7a00f5461de21e28835319eae5db145eb7 +b91054108ae78b00e3298d667b913ebc44d8f26e531eae78a8fe26fdfb60271c97efb2dee5f47ef5a3c15c8228138927 +926c13efbe90604f6244be9315a34f72a1f8d1aab7572df431998949c378cddbf2fe393502c930fff614ff06ae98a0ce +995c758fd5600e6537089b1baa4fbe0376ab274ff3e82a17768b40df6f91c2e443411de9cafa1e65ea88fb8b87d504f4 +9245ba307a7a90847da75fca8d77ec03fdfc812c871e7a2529c56a0a79a6de16084258e7a9ac4ae8a3756f394336e21c +99e0cfa2bb57a7e624231317044c15e52196ecce020db567c8e8cb960354a0be9862ee0c128c60b44777e65ac315e59f +ad4f6b3d27bbbb744126601053c3dc98c07ff0eb0b38a898bd80dce778372846d67e5ab8fb34fb3ad0ef3f235d77ba7f +a0f12cae3722bbbca2e539eb9cc7614632a2aefe51410430070a12b5bc5314ecec5857b7ff8f41e9980cac23064f7c56 +b487f1bc59485848c98222fd3bc36c8c9bb3d2912e2911f4ceca32c840a7921477f9b1fe00877e05c96c75d3eecae061 +a6033db53925654e18ecb3ce715715c36165d7035db9397087ac3a0585e587998a53973d011ac6d48af439493029cee6 +a6b4d09cd01c70a3311fd131d3710ccf97bde3e7b80efd5a8c0eaeffeb48cca0f951ced905290267b115b06d46f2693b +a9dff1df0a8f4f218a98b6f818a693fb0d611fed0fc3143537cbd6578d479af13a653a8155e535548a2a0628ae24fa58 +a58e469f65d366b519f9a394cacb7edaddac214463b7b6d62c2dbc1316e11c6c5184ce45c16de2d77f990dcdd8b55430 +989e71734f8119103586dc9a3c5f5033ddc815a21018b34c1f876cdfc112efa868d5751bf6419323e4e59fa6a03ece1c +a2da00e05036c884369e04cf55f3de7d659cd5fa3f849092b2519dd263694efe0f051953d9d94b7e121f0aee8b6174d7 +968f3c029f57ee31c4e1adea89a7f92e28483af9a74f30fbdb995dc2d40e8e657dff8f8d340d4a92bf65f54440f2859f +932778df6f60ac1639c1453ef0cbd2bf67592759dcccb3e96dcc743ff01679e4c7dd0ef2b0833dda548d32cb4eba49e2 +a805a31139f8e0d6dae1ac87d454b23a3dc9fc653d4ca18d4f8ebab30fc189c16e73981c2cb7dd6f8c30454a5208109d +a9ba0991296caa2aaa4a1ceacfb205544c2a2ec97088eace1d84ee5e2767656a172f75d2f0c4e16a3640a0e0dec316e0 +b1e49055c968dced47ec95ae934cf45023836d180702e20e2df57e0f62fb85d7ac60d657ba3ae13b8560b67210449459 +a94e1da570a38809c71e37571066acabff7bf5632737c9ab6e4a32856924bf6211139ab3cedbf083850ff2d0e0c0fcfc +88ef1bb322000c5a5515b310c838c9af4c1cdbb32eab1c83ac3b2283191cd40e9573747d663763a28dad0d64adc13840 +a987ce205f923100df0fbd5a85f22c9b99b9b9cbe6ddfa8dfda1b8fe95b4f71ff01d6c5b64ca02eb24edb2b255a14ef0 +84fe8221a9e95d9178359918a108de4763ebfa7a6487facb9c963406882a08a9a93f492f8e77cf9e7ea41ae079c45993 +aa1cf3dc7c5dcfa15bbbc811a4bb6dbac4fba4f97fb1ed344ab60264d7051f6eef19ea9773441d89929ee942ed089319 +8f6a7d610d59d9f54689bbe6a41f92d9f6096cde919c1ab94c3c7fcecf0851423bc191e5612349e10f855121c0570f56 +b5af1fa7894428a53ea520f260f3dc3726da245026b6d5d240625380bfb9c7c186df0204bb604efac5e613a70af5106e +a5bce6055ff812e72ce105f147147c7d48d7a2313884dd1f488b1240ee320f13e8a33f5441953a8e7a3209f65b673ce1 +b9b55b4a1422677d95821e1d042ab81bbf0bf087496504021ec2e17e238c2ca6b44fb3b635a5c9eac0871a724b8d47c3 +941c38e533ce4a673a3830845b56786585e5fe49c427f2e5c279fc6db08530c8f91db3e6c7822ec6bb4f956940052d18 +a38e191d66c625f975313c7007bbe7431b5a06ed2da1290a7d5d0f2ec73770d476efd07b8e632de64597d47df175cbb0 +94ba76b667abf055621db4c4145d18743a368d951565632ed4e743dd50dd3333507c0c34f286a5c5fdbf38191a2255cd +a5ca38c60be5602f2bfa6e00c687ac96ac36d517145018ddbee6f12eb0faa63dd57909b9eeed26085fe5ac44e55d10ab +b00fea3b825e60c1ed1c5deb4b551aa65a340e5af36b17d5262c9cd2c508711e4dc50dc2521a2c16c7c901902266e64a +971b86fc4033485e235ccb0997a236206ba25c6859075edbcdf3c943116a5030b7f75ebca9753d863a522ba21a215a90 +b3b31f52370de246ee215400975b674f6da39b2f32514fe6bd54e747752eedca22bb840493b44a67df42a3639c5f901f +affbbfac9c1ba7cbfa1839d2ae271dd6149869b75790bf103230637da41857fc326ef3552ff31c15bda0694080198143 +a95d42aa7ef1962520845aa3688f2752d291926f7b0d73ea2ee24f0612c03b43f2b0fe3c9a9a99620ffc8d487b981bc2 +914a266065caf64985e8c5b1cb2e3f4e3fe94d7d085a1881b1fefa435afef4e1b39a98551d096a62e4f5cc1a7f0fdc2e +81a0b4a96e2b75bc1bf2dbd165d58d55cfd259000a35504d1ffb18bc346a3e6f07602c683723864ffb980f840836fd8d +91c1556631cddd4c00b65b67962b39e4a33429029d311c8acf73a18600e362304fb68bccb56fde40f49e95b7829e0b87 +8befbacc19e57f7c885d1b7a6028359eb3d80792fe13b92a8400df21ce48deb0bb60f2ddb50e3d74f39f85d7eab23adc +92f9458d674df6e990789690ec9ca73dacb67fc9255b58c417c555a8cc1208ace56e8e538f86ba0f3615573a0fbac00d +b4b1b3062512d6ae7417850c08c13f707d5838e43d48eb98dd4621baf62eee9e82348f80fe9b888a12874bfa538771f8 +a13c4a3ac642ede37d9c883f5319e748d2b938f708c9d779714108a449b343f7b71a6e3ef4080fee125b416762920273 +af44983d5fc8cceee0551ef934e6e653f2d3efa385e5c8a27a272463a6f333e290378cc307c2b664eb923c78994e706e +a389fd6c59fe2b4031cc244e22d3991e541bd203dd5b5e73a6159e72df1ab41d49994961500dcde7989e945213184778 +8d2141e4a17836c548de9598d7b298b03f0e6c73b7364979a411c464e0628e21cff6ac3d6decdba5d1c4909eff479761 +980b22ef53b7bdf188a3f14bc51b0dbfdf9c758826daa3cbc1e3986022406a8aa9a6a79e400567120b88c67faa35ce5f +a28882f0a055f96df3711de5d0aa69473e71245f4f3e9aa944e9d1fb166e02caa50832e46da6d3a03b4801735fd01b29 +8db106a37d7b88f5d995c126abb563934dd8de516af48e85695d02b1aea07f79217e3cdd03c6f5ca57421830186c772b +b5a7e50da0559a675c472f7dfaee456caab6695ab7870541b2be8c2b118c63752427184aad81f0e1afc61aef1f28c46f +9962118780e20fe291d10b64f28d09442a8e1b5cffd0f3dd68d980d0614050a626c616b44e9807fbee7accecae00686a +b38ddf33745e8d2ad6a991aefaf656a33c5f8cbe5d5b6b6fd03bd962153d8fd0e01b5f8f96d80ae53ab28d593ab1d4e7 +857dc12c0544ff2c0c703761d901aba636415dee45618aba2e3454ff9cbc634a85c8b05565e88520ff9be2d097c8b2b1 +a80d465c3f8cc63af6d74a6a5086b626c1cb4a8c0fee425964c3bd203d9d7094e299f81ce96d58afc20c8c9a029d9dae +89e1c8fbde8563763be483123a3ed702efac189c6d8ab4d16c85e74bbaf856048cc42d5d6e138633a38572ba5ec3f594 +893a594cf495535f6d216508f8d03c317dcf03446668cba688da90f52d0111ac83d76ad09bf5ea47056846585ee5c791 +aadbd8be0ae452f7f9450c7d2957598a20cbf10139a4023a78b4438172d62b18b0de39754dd2f8862dbd50a3a0815e53 +ae7d39670ecca3eb6db2095da2517a581b0e8853bdfef619b1fad9aacd443e7e6a40f18209fadd44038a55085c5fe8b2 +866ef241520eacb6331593cfcb206f7409d2f33d04542e6e52cba5447934e02d44c471f6c9a45963f9307e9809ab91d9 +b1a09911ad3864678f7be79a9c3c3eb5c84a0a45f8dcb52c67148f43439aeaaa9fd3ed3471276b7e588b49d6ebe3033a +add07b7f0dbb34049cd8feeb3c18da5944bf706871cfd9f14ff72f6c59ad217ebb1f0258b13b167851929387e4e34cfe +ae048892d5c328eefbdd4fba67d95901e3c14d974bfc0a1fc68155ca9f0d59e61d7ba17c6c9948b120cf35fd26e6fee9 +9185b4f3b7da0ddb4e0d0f09b8a9e0d6943a4611e43f13c3e2a767ed8592d31e0ba3ebe1914026a3627680274291f6e5 +a9c022d4e37b0802284ce3b7ee9258628ab4044f0db4de53d1c3efba9de19d15d65cc5e608dbe149c21c2af47d0b07b5 +b24dbd5852f8f24921a4e27013b6c3fa8885b973266cb839b9c388efad95821d5d746348179dcc07542bd0d0aefad1ce +b5fb4f279300876a539a27a441348764908bc0051ebd66dc51739807305e73db3d2f6f0f294ffb91b508ab150eaf8527 +ace50841e718265b290c3483ed4b0fdd1175338c5f1f7530ae9a0e75d5f80216f4de37536adcbc8d8c95982e88808cd0 +b19cadcde0f63bd1a9c24bd9c2806f53c14c0b9735bf351601498408ba503ddbd2037c891041cbba47f58b8c483f3b21 +b6061e63558d312eb891b97b39aa552fa218568d79ee26fe6dd5b864aea9e3216d8f2e2f3b093503be274766dac41426 +89730fdb2876ab6f0fe780d695f6e12090259027e789b819956d786e977518057e5d1d7f5ab24a3ae3d5d4c97773bd2b +b6fa841e81f9f2cad0163a02a63ae96dc341f7ae803b616efc6e1da2fbea551c1b96b11ad02c4afbdf6d0cc9f23da172 +8fb66187182629c861ddb6896d7ed3caf2ad050c3dba8ab8eb0d7a2c924c3d44c48d1a148f9e33fb1f061b86972f8d21 +86022ac339c1f84a7fa9e05358c1a5b316b4fc0b83dbe9c8c7225dc514f709d66490b539359b084ce776e301024345fa +b50b9c321468da950f01480bb62b6edafd42f83c0001d6e97f2bd523a1c49a0e8574fb66380ea28d23a7c4d54784f9f0 +a31c05f7032f30d1dac06678be64d0250a071fd655e557400e4a7f4c152be4d5c7aa32529baf3e5be7c4bd49820054f6 +b95ac0848cd322684772119f5b682d90a66bbf9dac411d9d86d2c34844bbd944dbaf8e47aa41380455abd51687931a78 +ae4a6a5ce9553b65a05f7935e61e496a4a0f6fd8203367a2c627394c9ce1e280750297b74cdc48fd1d9a31e93f97bef4 +a22daf35f6e9b05e52e0b07f7bd1dbbebd2c263033fb0e1b2c804e2d964e2f11bc0ece6aca6af079dd3a9939c9c80674 +902150e0cb1f16b9b59690db35281e28998ce275acb313900da8b2d8dfd29fa1795f8ca3ff820c31d0697de29df347c1 +b17b5104a5dc665cdd7d47e476153d715eb78c6e5199303e4b5445c21a7fa7cf85fe7cfd08d7570f4e84e579b005428c +a03f49b81c15433f121680aa02d734bb9e363af2156654a62bcb5b2ba2218398ccb0ff61104ea5d7df5b16ea18623b1e +802101abd5d3c88876e75a27ffc2f9ddcce75e6b24f23dba03e5201281a7bd5cc7530b6a003be92d225093ca17d3c3bb +a4d183f63c1b4521a6b52226fc19106158fc8ea402461a5cccdaa35fee93669df6a8661f45c1750cd01308149b7bf08e +8d17c22e0c8403b69736364d460b3014775c591032604413d20a5096a94d4030d7c50b9fe3240e31d0311efcf9816a47 +947225acfcce5992eab96276f668c3cbe5f298b90a59f2bb213be9997d8850919e8f496f182689b5cbd54084a7332482 +8df6f4ed216fc8d1905e06163ba1c90d336ab991a18564b0169623eb39b84e627fa267397da15d3ed754d1f3423bff07 +83480007a88f1a36dea464c32b849a3a999316044f12281e2e1c25f07d495f9b1710b4ba0d88e9560e72433addd50bc2 +b3019d6e591cf5b33eb972e49e06c6d0a82a73a75d78d383dd6f6a4269838289e6e07c245f54fed67f5c9bb0fd5e1c5f +92e8ce05e94927a9fb02debadb99cf30a26172b2705003a2c0c47b3d8002bf1060edb0f6a5750aad827c98a656b19199 +ac2aff801448dbbfc13cca7d603fd9c69e82100d997faf11f465323b97255504f10c0c77401e4d1890339d8b224f5803 +b0453d9903d08f508ee27e577445dc098baed6cde0ac984b42e0f0efed62760bd58d5816cf1e109d204607b7b175e30c +ae68dc4ba5067e825d46d2c7c67f1009ceb49d68e8d3e4c57f4bcd299eb2de3575d42ea45e8722f8f28497a6e14a1cfe +b22486c2f5b51d72335ce819bbafb7fa25eb1c28a378a658f13f9fc79cd20083a7e573248d911231b45a5cf23b561ca7 +89d1201d1dbd6921867341471488b4d2fd0fc773ae1d4d074c78ae2eb779a59b64c00452c2a0255826fca6b3d03be2b1 +a2998977c91c7a53dc6104f5bc0a5b675e5350f835e2f0af69825db8af4aeb68435bdbcc795f3dd1f55e1dd50bc0507f +b0be4937a925b3c05056ed621910d535ccabf5ab99fd3b9335080b0e51d9607d0fd36cb5781ff340018f6acfca4a9736 +aea145a0f6e0ba9df8e52e84bb9c9de2c2dc822f70d2724029b153eb68ee9c17de7d35063dcd6a39c37c59fdd12138f7 +91cb4545d7165ee8ffbc74c874baceca11fdebbc7387908d1a25877ca3c57f2c5def424dab24148826832f1e880bede0 +b3b579cb77573f19c571ad5eeeb21f65548d7dff9d298b8d7418c11f3e8cd3727c5b467f013cb87d6861cfaceee0d2e3 +b98a1eeec2b19fecc8378c876d73645aa52fb99e4819903735b2c7a885b242787a30d1269a04bfb8573d72d9bbc5f0f0 +940c1f01ed362bd588b950c27f8cc1d52276c71bb153d47f07ec85b038c11d9a8424b7904f424423e714454d5e80d1cd +aa343a8ecf09ce11599b8cf22f7279cf80f06dbf9f6d62cb05308dbbb39c46fd0a4a1240b032665fbb488a767379b91b +87c3ac72084aca5974599d3232e11d416348719e08443acaba2b328923af945031f86432e170dcdd103774ec92e988c9 +91d6486eb5e61d2b9a9e742c20ec974a47627c6096b3da56209c2b4e4757f007e793ebb63b2b246857c9839b64dc0233 +aebcd3257d295747dd6fc4ff910d839dd80c51c173ae59b8b2ec937747c2072fa85e3017f9060aa509af88dfc7529481 +b3075ba6668ca04eff19efbfa3356b92f0ab12632dcda99cf8c655f35b7928c304218e0f9799d68ef9f809a1492ff7db +93ba7468bb325639ec2abd4d55179c69fd04eaaf39fc5340709227bbaa4ad0a54ea8b480a1a3c8d44684e3be0f8d1980 +a6aef86c8c0d92839f38544d91b767c582568b391071228ff5a5a6b859c87bf4f81a7d926094a4ada1993ddbd677a920 +91dcd6d14207aa569194aa224d1e5037b999b69ade52843315ca61ba26abe9a76412c9e88259bc5cf5d7b95b97d9c3bc +b3b483d31c88f78d49bd065893bc1e3d2aa637e27dedb46d9a7d60be7660ce7a10aaaa7deead362284a52e6d14021178 +8e5730070acf8371461ef301cc4523e8e672aa0e3d945d438a0e0aa6bdf8cb9c685dcf38df429037b0c8aff3955c6f5b +b8c6d769890a8ee18dc4f9e917993315877c97549549b34785a92543cbeec96a08ae3a28d6e809c4aacd69de356c0012 +95ca86cd384eaceaa7c077c5615736ca31f36824bd6451a16142a1edc129fa42b50724aeed7c738f08d7b157f78b569e +94df609c6d71e8eee7ab74226e371ccc77e01738fe0ef1a6424435b4570fe1e5d15797b66ed0f64eb88d4a3a37631f0e +89057b9783212add6a0690d6bb99097b182738deff2bd9e147d7fd7d6c8eacb4c219923633e6309ad993c24572289901 +83a0f9f5f265c5a0e54defa87128240235e24498f20965009fef664f505a360b6fb4020f2742565dfc7746eb185bcec0 +91170da5306128931349bc3ed50d7df0e48a68b8cc8420975170723ac79d8773e4fa13c5f14dc6e3fafcad78379050b1 +b7178484d1b55f7e56a4cc250b6b2ec6040437d96bdfddfa7b35ed27435860f3855c2eb86c636f2911b012eb83b00db8 +ac0b00c4322d1e4208e09cd977b4e54d221133ff09551f75b32b0b55d0e2be80941dda26257b0e288c162e63c7e9cf68 +9690ed9e7e53ed37ff362930e4096b878b12234c332fd19d5d064824084245952eda9f979e0098110d6963e468cf513e +b6fa547bb0bb83e5c5be0ed462a8783fba119041c136a250045c09d0d2af330c604331e7de960df976ff76d67f8000cd +814603907c21463bcf4e59cfb43066dfe1a50344ae04ef03c87c0f61b30836c3f4dea0851d6fa358c620045b7f9214c8 +9495639e3939fad2a3df00a88603a5a180f3c3a0fe4d424c35060e2043e0921788003689887b1ed5be424d9a89bb18bb +aba4c02d8d57f2c92d5bc765885849e9ff8393d6554f5e5f3e907e5bfac041193a0d8716d7861104a4295d5a03c36b03 +8ead0b56c1ca49723f94a998ba113b9058059321da72d9e395a667e6a63d5a9dac0f5717cec343f021695e8ced1f72af +b43037f7e3852c34ed918c5854cd74e9d5799eeddfe457d4f93bb494801a064735e326a76e1f5e50a339844a2f4a8ec9 +99db8422bb7302199eb0ff3c3d08821f8c32f53a600c5b6fb43e41205d96adae72be5b460773d1280ad1acb806af9be8 +8a9be08eae0086c0f020838925984df345c5512ff32e37120b644512b1d9d4fecf0fd30639ca90fc6cf334a86770d536 +81b43614f1c28aa3713a309a88a782fb2bdfc4261dd52ddc204687791a40cf5fd6a263a8179388596582cccf0162efc2 +a9f3a8b76912deb61d966c75daf5ddb868702ebec91bd4033471c8e533183df548742a81a2671de5be63a502d827437d +902e2415077f063e638207dc7e14109652e42ab47caccd6204e2870115791c9defac5425fd360b37ac0f7bd8fe7011f8 +aa18e4fdc1381b59c18503ae6f6f2d6943445bd00dd7d4a2ad7e5adad7027f2263832690be30d456e6d772ad76f22350 +a348b40ba3ba7d81c5d4631f038186ebd5e5f314f1ea737259151b07c3cc8cf0c6ed4201e71bcc1c22fefda81a20cde6 +aa1306f7ac1acbfc47dc6f7a0cb6d03786cec8c8dc8060388ccda777bca24bdc634d03e53512c23dba79709ff64f8620 +818ccfe46e700567b7f3eb400e5a35f6a5e39b3db3aa8bc07f58ace35d9ae5a242faf8dbccd08d9a9175bbce15612155 +b7e3da2282b65dc8333592bb345a473f03bd6df69170055fec60222de9897184536bf22b9388b08160321144d0940279 +a4d976be0f0568f4e57de1460a1729129252b44c552a69fceec44e5b97c96c711763360d11f9e5bf6d86b4976bf40d69 +85d185f0397c24c2b875b09b6328a23b87982b84ee880f2677a22ff4c9a1ba9f0fea000bb3f7f66375a00d98ebafce17 +b4ccbb8c3a2606bd9b87ce022704663af71d418351575f3b350d294f4efc68c26f9a2ce49ff81e6ff29c3b63d746294e +93ffd3265fddb63724dfde261d1f9e22f15ecf39df28e4d89e9fea03221e8e88b5dd9b77628bacaa783c6f91802d47cc +b1fd0f8d7a01378e693da98d03a2d2fda6b099d03454b6f2b1fa6472ff6bb092751ce6290059826b74ac0361eab00e1e +a89f440c71c561641589796994dd2769616b9088766e983c873fae0716b95c386c8483ab8a4f367b6a68b72b7456dd32 +af4fe92b01d42d03dd5d1e7fa55e96d4bbcb7bf7d4c8c197acd16b3e0f3455807199f683dcd263d74547ef9c244b35cc +a8227f6e0a344dfe76bfbe7a1861be32c4f4bed587ccce09f9ce2cf481b2dda8ae4f566154bc663d15f962f2d41761bd +a7b361663f7495939ed7f518ba45ea9ff576c4e628995b7aea026480c17a71d63fc2c922319f0502eb7ef8f14a406882 +8ddcf382a9f39f75777160967c07012cfa89e67b19714a7191f0c68eaf263935e5504e1104aaabd0899348c972a8d3c6 +98c95b9f6f5c91f805fb185eedd06c6fc4457d37dd248d0be45a6a168a70031715165ea20606245cbdf8815dc0ac697f +805b44f96e001e5909834f70c09be3efcd3b43632bcac5b6b66b6d227a03a758e4b1768ce2a723045681a1d34562aaeb +b0e81b07cdc45b3dca60882676d9badb99f25c461b7efe56e3043b80100bb62d29e1873ae25eb83087273160ece72a55 +b0c53f0abe78ee86c7b78c82ae1f7c070bb0b9c45c563a8b3baa2c515d482d7507bb80771e60b38ac13f78b8af92b4a9 +a7838ef6696a9e4d2e5dfd581f6c8d6a700467e8fd4e85adabb5f7a56f514785dd4ab64f6f1b48366f7d94728359441b +88c76f7700a1d23c30366a1d8612a796da57b2500f97f88fdf2d76b045a9d24e7426a8ffa2f4e86d3046937a841dad58 +ad8964baf98c1f02e088d1d9fcb3af6b1dfa44cdfe0ed2eae684e7187c33d3a3c28c38e8f4e015f9c04d451ed6f85ff6 +90e9d00a098317ececaa9574da91fc149eda5b772dedb3e5a39636da6603aa007804fa86358550cfeff9be5a2cb7845e +a56ff4ddd73d9a6f5ab23bb77efa25977917df63571b269f6a999e1ad6681a88387fcc4ca3b26d57badf91b236503a29 +97ad839a6302c410a47e245df84c01fb9c4dfef86751af3f9340e86ff8fc3cd52fa5ff0b9a0bd1d9f453e02ca80658a6 +a4c8c44cbffa804129e123474854645107d1f0f463c45c30fd168848ebea94880f7c0c5a45183e9eb837f346270bdb35 +a72e53d0a1586d736e86427a93569f52edd2f42b01e78aee7e1961c2b63522423877ae3ac1227a2cf1e69f8e1ff15bc3 +8559f88a7ef13b4f09ac82ae458bbae6ab25671cfbf52dae7eac7280d6565dd3f0c3286aec1a56a8a16dc3b61d78ce47 +8221503f4cdbed550876c5dc118a3f2f17800c04e8be000266633c83777b039a432d576f3a36c8a01e8fd18289ebc10b +99bfbe5f3e46d4d898a578ba86ed26de7ed23914bd3bcdf3c791c0bcd49398a52419077354a5ab75cea63b6c871c6e96 +aa134416d8ff46f2acd866c1074af67566cfcf4e8be8d97329dfa0f603e1ff208488831ce5948ac8d75bfcba058ddcaa +b02609d65ebfe1fe8e52f21224a022ea4b5ea8c1bd6e7b9792eed8975fc387cdf9e3b419b8dd5bcce80703ab3a12a45f +a4f14798508698fa3852e5cac42a9db9797ecee7672a54988aa74037d334819aa7b2ac7b14efea6b81c509134a6b7ad2 +884f01afecbcb987cb3e7c489c43155c416ed41340f61ecb651d8cba884fb9274f6d9e7e4a46dd220253ae561614e44c +a05523c9e71dce1fe5307cc71bd721feb3e1a0f57a7d17c7d1c9fb080d44527b7dbaa1f817b1af1c0b4322e37bc4bb1e +8560aec176a4242b39f39433dd5a02d554248c9e49d3179530815f5031fee78ba9c71a35ceeb2b9d1f04c3617c13d8f0 +996aefd402748d8472477cae76d5a2b92e3f092fc834d5222ae50194dd884c9fb8b6ed8e5ccf8f6ed483ddbb4e80c747 +8fd09900320000cbabc40e16893e2fcf08815d288ec19345ad7b6bb22f7d78a52b6575a3ca1ca2f8bc252d2eafc928ec +939e51f73022bc5dc6862a0adf8fb8a3246b7bfb9943cbb4b27c73743926cc20f615a036c7e5b90c80840e7f1bfee0e7 +a0a6258700cadbb9e241f50766573bf9bdb7ad380b1079dc3afb4054363d838e177b869cad000314186936e40359b1f2 +972699a4131c8ed27a2d0e2104d54a65a7ff1c450ad9da3a325c662ab26869c21b0a84d0700b98c8b5f6ce3b746873d7 +a454c7fe870cb8aa6491eafbfb5f7872d6e696033f92e4991d057b59d70671f2acdabef533e229878b60c7fff8f748b1 +a167969477214201f09c79027b10221e4707662e0c0fde81a0f628249f2f8a859ce3d30a7dcc03b8ecca8f7828ad85c7 +8ff6b7265175beb8a63e1dbf18c9153fb2578c207c781282374f51b40d57a84fd2ef2ea2b9c6df4a54646788a62fd17f +a3d7ebeccde69d73d8b3e76af0da1a30884bb59729503ff0fb0c3bccf9221651b974a6e72ea33b7956fc3ae758226495 +b71ef144c9a98ce5935620cb86c1590bd4f48e5a2815d25c0cdb008fde628cf628c31450d3d4f67abbfeb16178a74cfd +b5e0a16d115134f4e2503990e3f2035ed66b9ccf767063fe6747870d97d73b10bc76ed668550cb82eedc9a2ca6f75524 +b30ffaaf94ee8cbc42aa2c413175b68afdb207dbf351fb20be3852cb7961b635c22838da97eaf43b103aff37e9e725cc +98aa7d52284f6c1f22e272fbddd8c8698cf8f5fbb702d5de96452141fafb559622815981e50b87a72c2b1190f59a7deb +81fbacda3905cfaf7780bb4850730c44166ed26a7c8d07197a5d4dcd969c09e94a0461638431476c16397dd7bdc449f9 +95e47021c1726eac2e5853f570d6225332c6e48e04c9738690d53e07c6b979283ebae31e2af1fc9c9b3e59f87e5195b1 +ac024a661ba568426bb8fce21780406537f518075c066276197300841e811860696f7588188bc01d90bace7bc73d56e3 +a4ebcaf668a888dd404988ab978594dee193dad2d0aec5cdc0ccaf4ec9a7a8228aa663db1da8ddc52ec8472178e40c32 +a20421b8eaf2199d93b083f2aff37fb662670bd18689d046ae976d1db1fedd2c2ff897985ecc6277b396db7da68bcb27 +8bc33d4b40197fd4d49d1de47489d10b90d9b346828f53a82256f3e9212b0cbc6930b895e879da9cec9fedf026aadb3e +aaafdd1bec8b757f55a0433eddc0a39f818591954fd4e982003437fcceb317423ad7ee74dbf17a2960380e7067a6b4e2 +aad34277ebaed81a6ec154d16736866f95832803af28aa5625bf0461a71d02b1faba02d9d9e002be51c8356425a56867 +976e9c8b150d08706079945bd0e84ab09a648ecc6f64ded9eb5329e57213149ae409ae93e8fbd8eda5b5c69f5212b883 +8097fae1653247d2aed4111533bc378171d6b2c6d09cbc7baa9b52f188d150d645941f46d19f7f5e27b7f073c1ebd079 +83905f93b250d3184eaba8ea7d727c4464b6bdb027e5cbe4f597d8b9dc741dcbea709630bd4fd59ce24023bec32fc0f3 +8095030b7045cff28f34271386e4752f9a9a0312f8df75de4f424366d78534be2b8e1720a19cb1f9a2d21105d790a225 +a7b7b73a6ae2ed1009c49960374b0790f93c74ee03b917642f33420498c188a169724945a975e5adec0a1e83e07fb1b2 +856a41c54df393b6660b7f6354572a4e71c8bfca9cabaffb3d4ef2632c015e7ee2bc10056f3eccb3dbed1ad17d939178 +a8f7a55cf04b38cd4e330394ee6589da3a07dc9673f74804fdf67b364e0b233f14aec42e783200a2e4666f7c5ff62490 +82c529f4e543c6bca60016dc93232c115b359eaee2798a9cf669a654b800aafe6ab4ba58ea8b9cdda2b371c8d62fa845 +8caab020c1baddce77a6794113ef1dfeafc5f5000f48e97f4351b588bf02f1f208101745463c480d37f588d5887e6d8c +8fa91b3cc400f48b77b6fd77f3b3fbfb3f10cdff408e1fd22d38f77e087b7683adad258804409ba099f1235b4b4d6fea +8aa02787663d6be9a35677d9d8188b725d5fcd770e61b11b64e3def8808ea5c71c0a9afd7f6630c48634546088fcd8e2 +b5635b7b972e195cab878b97dea62237c7f77eb57298538582a330b1082f6207a359f2923864630136d8b1f27c41b9aa +8257bb14583551a65975946980c714ecd6e5b629672bb950b9caacd886fbd22704bc9e3ba7d30778adab65dc74f0203a +ab5fe1cd12634bfa4e5c60d946e2005cbd38f1063ec9a5668994a2463c02449a0a185ef331bd86b68b6e23a8780cb3ba +a7d3487da56cda93570cc70215d438204f6a2709bfb5fda6c5df1e77e2efc80f4235c787e57fbf2c74aaff8cbb510a14 +b61cff7b4c49d010e133319fb828eb900f8a7e55114fc86b39c261a339c74f630e1a7d7e1350244ada566a0ff3d46c4b +8d4d1d55d321d278db7a85522ccceca09510374ca81d4d73e3bb5249ace7674b73900c35a531ec4fa6448fabf7ad00dc +966492248aee24f0f56c8cfca3c8ec6ba3b19abb69ae642041d4c3be8523d22c65c4dafcab4c58989ccc4e0bd2f77919 +b20c320a90cb220b86e1af651cdc1e21315cd215da69f6787e28157172f93fc8285dcd59b039c626ed8ca4633cba1a47 +aae9e6b22f018ceb5c0950210bb8182cb8cb61014b7e14581a09d36ebd1bbfebdb2b82afb7fdb0cf75e58a293d9c456d +875547fb67951ad37b02466b79f0c9b985ccbc500cfb431b17823457dc79fb9597ec42cd9f198e15523fcd88652e63a4 +92afce49773cb2e20fb21e4f86f18e0959ebb9c33361547ddb30454ee8e36b1e234019cbdca0e964cb292f7f77df6b90 +8af85343dfe1821464c76ba11c216cbef697b5afc69c4d821342e55afdac047081ec2e3f7b09fc14b518d9a23b78c003 +b7de4a1648fd63f3a918096ea669502af5357438e69dac77cb8102b6e6c15c76e033cfaa80dafc806e535ede5c1a20aa +ac80e9b545e8bd762951d96c9ce87f629d01ffcde07efc2ef7879ca011f1d0d8a745abf26c9d452541008871304fac00 +a4cf0f7ed724e481368016c38ea5816698a5f68eb21af4d3c422d2ba55f96a33e427c2aa40de1b56a7cfac7f7cf43ab0 +899b0a678bb2db2cae1b44e75a661284844ebcdd87abf308fedeb2e4dbe5c5920c07db4db7284a7af806a2382e8b111a +af0588a2a4afce2b1b13c1230816f59e8264177e774e4a341b289a101dcf6af813638fed14fb4d09cb45f35d5d032609 +a4b8df79e2be76e9f5fc5845f06fe745a724cf37c82fcdb72719b77bdebea3c0e763f37909373e3a94480cc5e875cba0 +83e42c46d88930c8f386b19fd999288f142d325e2ebc86a74907d6d77112cb0d449bc511c95422cc810574031a8cbba9 +b5e39534070de1e5f6e27efbdd3dc917d966c2a9b8cf2d893f964256e95e954330f2442027dc148c776d63a95bcde955 +958607569dc28c075e658cd4ae3927055c6bc456eef6212a6fea8205e48ed8777a8064f584cda38fe5639c371e2e7fba +812adf409fa63575113662966f5078a903212ffb65c9b0bbe62da0f13a133443a7062cb8fd70f5e5dd5559a32c26d2c8 +a679f673e5ce6a3cce7fa31f22ee3785e96bcb55e5a776e2dd3467bef7440e3555d1a9b87cb215e86ee9ed13a090344b +afedbb34508b159eb25eb2248d7fe328f86ef8c7d84c62d5b5607d74aae27cc2cc45ee148eb22153b09898a835c58df4 +b75505d4f6b67d31e665cfaf5e4acdb5838ae069166b7fbcd48937c0608a59e40a25302fcc1873d2e81c1782808c70f0 +b62515d539ec21a155d94fc00ea3c6b7e5f6636937bce18ed5b618c12257fb82571886287fd5d1da495296c663ebc512 +ab8e1a9446bbdd588d1690243b1549d230e6149c28f59662b66a8391a138d37ab594df38e7720fae53217e5c3573b5be +b31e8abf4212e03c3287bb2c0a153065a7290a16764a0bac8f112a72e632185a654bb4e88fdd6053e6c7515d9719fadb +b55165477fe15b6abd2d0f4fddaa9c411710dcc4dd712daba3d30e303c9a3ee5415c256f9dc917ecf18c725b4dbab059 +a0939d4f57cacaae549b78e87cc234de4ff6a35dc0d9cd5d7410abc30ebcd34c135e008651c756e5a9d2ca79c40ef42b +8cf10e50769f3443340844aad4d56ec790850fed5a41fcbd739abac4c3015f0a085a038fbe7fae9f5ad899cce5069f6b +924055e804d82a99ea4bb160041ea4dc14b568abf379010bc1922fde5d664718c31d103b8b807e3a1ae809390e708c73 +8ec0f9d26f71b0f2e60a179e4fd1778452e2ffb129d50815e5d7c7cb9415fa69ae5890578086e8ef6bfde35ad2a74661 +98c7f12b15ec4426b59f737f73bf5faea4572340f4550b7590dfb7f7ffedb2372e3e555977c63946d579544c53210ad0 +8a935f7a955c78f69d66f18eee0092e5e833fa621781c9581058e219af4d7ceee48b84e472e159dda6199715fb2f9acf +b78d4219f95a2dbfaa7d0c8a610c57c358754f4f43c2af312ab0fe8f10a5f0177e475332fb8fd23604e474fc2abeb051 +8d086a14803392b7318c28f1039a17e3cfdcece8abcaca3657ec3d0ac330842098a85c0212f889fabb296dfb133ce9aa +a53249f417aac82f2c2a50c244ce21d3e08a5e5a8bd33bec2a5ab0d6cd17793e34a17edfa3690899244ce201e2fb9986 +8619b0264f9182867a1425be514dc4f1ababc1093138a728a28bd7e4ecc99b9faaff68c23792264bc6e4dce5f52a5c52 +8c171edbbbde551ec19e31b2091eb6956107dd9b1f853e1df23bff3c10a3469ac77a58335eee2b79112502e8e163f3de +a9d19ec40f0ca07c238e9337c6d6a319190bdba2db76fb63902f3fb459aeeb50a1ac30db5b25ee1b4201f3ca7164a7f4 +b9c6ec14b1581a03520b8d2c1fbbc31fb8ceaef2c0f1a0d0080b6b96e18442f1734bea7ef7b635d787c691de4765d469 +8cb437beb4cfa013096f40ccc169a713dc17afee6daa229a398e45fd5c0645a9ad2795c3f0cd439531a7151945d7064d +a6e8740cc509126e146775157c2eb278003e5bb6c48465c160ed27888ca803fa12eee1f6a8dd7f444f571664ed87fdc1 +b75c1fecc85b2732e96b3f23aefb491dbd0206a21d682aee0225838dc057d7ed3b576176353e8e90ae55663f79e986e4 +ad8d249b0aea9597b08358bce6c77c1fd552ef3fbc197d6a1cfe44e5e6f89b628b12a6fb04d5dcfcbacc51f46e4ae7bb +b998b2269932cbd58d04b8e898d373ac4bb1a62e8567484f4f83e224061bc0f212459f1daae95abdbc63816ae6486a55 +827988ef6c1101cddc96b98f4a30365ff08eea2471dd949d2c0a9b35c3bbfa8c07054ad1f4c88c8fbf829b20bb5a9a4f +8692e638dd60babf7d9f2f2d2ce58e0ac689e1326d88311416357298c6a2bffbfebf55d5253563e7b3fbbf5072264146 +a685d75b91aea04dbc14ab3c1b1588e6de96dae414c8e37b8388766029631b28dd860688079b12d09cd27f2c5af11adf +b57eced93eec3371c56679c259b34ac0992286be4f4ff9489d81cf9712403509932e47404ddd86f89d7c1c3b6391b28c +a1c8b4e42ebcbd8927669a97f1b72e236fb19249325659e72be7ddaaa1d9e81ca2abb643295d41a8c04a2c01f9c0efd7 +877c33de20d4ed31674a671ba3e8f01a316581e32503136a70c9c15bf0b7cb7b1cba6cd4eb641fad165fb3c3c6c235fd +a2a469d84ec478da40838f775d11ad38f6596eb41caa139cc190d6a10b5108c09febae34ffdafac92271d2e73c143693 +972f817caedb254055d52e963ed28c206848b6c4cfdb69dbc961c891f8458eaf582a6d4403ce1177d87bc2ea410ef60a +accbd739e138007422f28536381decc54bb6bd71d93edf3890e54f9ef339f83d2821697d1a4ac1f5a98175f9a9ecb9b5 +8940f8772e05389f823b62b3adc3ed541f91647f0318d7a0d3f293aeeb421013de0d0a3664ea53dd24e5fbe02d7efef6 +8ecce20f3ef6212edef07ec4d6183fda8e0e8cad2c6ccd0b325e75c425ee1faba00b5c26b4d95204238931598d78f49d +97cc72c36335bd008afbed34a3b0c7225933faba87f7916d0a6d2161e6f82e0cdcda7959573a366f638ca75d30e9dab1 +9105f5de8699b5bdb6bd3bb6cc1992d1eac23929c29837985f83b22efdda92af64d9c574aa9640475087201bbbe5fd73 +8ffb33c4f6d05c413b9647eb6933526a350ed2e4278ca2ecc06b0e8026d8dbe829c476a40e45a6df63a633090a3f82ef +8bfc6421fdc9c2d2aaa68d2a69b1a2728c25b84944cc3e6a57ff0c94bfd210d1cbf4ff3f06702d2a8257024d8be7de63 +a80e1dc1dddfb41a70220939b96dc6935e00b32fb8be5dff4eed1f1c650002ff95e4af481c43292e3827363b7ec4768a +96f714ebd54617198bd636ba7f7a7f8995a61db20962f2165078d9ed8ee764d5946ef3cbdc7ebf8435bb8d5dd4c1deac +8cdb0890e33144d66391d2ae73f5c71f5a861f72bc93bff6cc399fc25dd1f9e17d8772592b44593429718784802ac377 +8ccf9a7f80800ee770b92add734ed45a73ecc31e2af0e04364eefc6056a8223834c7c0dc9dfc52495bdec6e74ce69994 +aa0875f423bd68b5f10ba978ddb79d3b96ec093bfbac9ff366323193e339ed7c4578760fb60f60e93598bdf1e5cc4995 +a9214f523957b59c7a4cb61a40251ad72aba0b57573163b0dc0f33e41d2df483fb9a1b85a5e7c080e9376c866790f8cb +b6224b605028c6673a536cc8ff9aeb94e7a22e686fda82cf16068d326469172f511219b68b2b3affb7933af0c1f80d07 +b6d58968d8a017c6a34e24c2c09852f736515a2c50f37232ac6b43a38f8faa7572cc31dade543b594b61b5761c4781d0 +8a97cefe5120020c38deeb861d394404e6c993c6cbd5989b6c9ebffe24f46ad11b4ba6348e2991cbf3949c28cfc3c99d +95bf046f8c3a9c0ce2634be4de3713024daec3fc4083e808903b25ce3ac971145af90686b451efcc72f6b22df0216667 +a6a4e2f71b8fa28801f553231eff2794c0f10d12e7e414276995e21195abc9c2983a8997e41af41e78d19ff6fbb2680b +8e5e62a7ca9c2f58ebaab63db2ff1fb1ff0877ae94b7f5e2897f273f684ae639dff44cc65718f78a9c894787602ab26a +8542784383eec4f565fcb8b9fc2ad8d7a644267d8d7612a0f476fc8df3aff458897a38003d506d24142ad18f93554f2b +b7db68ba4616ea072b37925ec4fb39096358c2832cc6d35169e032326b2d6614479f765ae98913c267105b84afcb9bf2 +8b31dbb9457d23d416c47542c786e07a489af35c4a87dadb8ee91bea5ac4a5315e65625d78dad2cf8f9561af31b45390 +a8545a1d91ac17257732033d89e6b7111db8242e9c6ebb0213a88906d5ef407a2c6fdb444e29504b06368b6efb4f4839 +b1bd85d29ebb28ccfb05779aad8674906b267c2bf8cdb1f9a0591dd621b53a4ee9f2942687ee3476740c0b4a7621a3ae +a2b54534e152e46c50d91fff03ae9cd019ff7cd9f4168b2fe7ac08ef8c3bbc134cadd3f9d6bd33d20ae476c2a8596c8a +b19b571ff4ae3e9f5d95acda133c455e72c9ea9973cae360732859836c0341c4c29ab039224dc5bc3deb824e031675d8 +940b5f80478648bac025a30f3efeb47023ce20ee98be833948a248bca6979f206bb28fc0f17b90acf3bb4abd3d14d731 +8f106b40588586ac11629b96d57808ad2808915d89539409c97414aded90b4ff23286a692608230a52bff696055ba5d6 +ae6bda03aa10da3d2abbc66d764ca6c8d0993e7304a1bdd413eb9622f3ca1913baa6da1e9f4f9e6cf847f14f44d6924d +a18e7796054a340ef826c4d6b5a117b80927afaf2ebd547794c400204ae2caf277692e2eabb55bc2f620763c9e9da66d +8d2d25180dc2c65a4844d3e66819ccfcf48858f0cc89e1c77553b463ec0f7feb9a4002ce26bc618d1142549b9850f232 +863f413a394de42cc8166c1c75d513b91d545fff1de6b359037a742c70b008d34bf8e587afa2d62c844d0c6f0ea753e7 +83cd0cf62d63475e7fcad18a2e74108499cdbf28af2113cfe005e3b5887794422da450b1944d0a986eb7e1f4c3b18f25 +b4f8b350a6d88fea5ab2e44715a292efb12eb52df738c9b2393da3f1ddee68d0a75b476733ccf93642154bceb208f2b8 +b3f52aaa4cd4221cb9fc45936cc67fd3864bf6d26bf3dd86aa85aa55ecfc05f5e392ecce5e7cf9406b4b1c4fce0398c8 +b33137084422fb643123f40a6df2b498065e65230fc65dc31791c330e898c51c3a65ff738930f32c63d78f3c9315f85b +91452bfa75019363976bb7337fe3a73f1c10f01637428c135536b0cdc7da5ce558dae3dfc792aa55022292600814a8ef +ad6ba94c787cd4361ca642c20793ea44f1f127d4de0bb4a77c7fbfebae0fcadbf28e2cb6f0c12c12a07324ec8c19761d +890aa6248b17f1501b0f869c556be7bf2b1d31a176f9978bb97ab7a6bd4138eed32467951c5ef1871944b7f620542f43 +82111db2052194ee7dd22ff1eafffac0443cf969d3762cceae046c9a11561c0fdce9c0711f88ac01d1bed165f8a7cee3 +b1527b71df2b42b55832f72e772a466e0fa05743aacc7814f4414e4bcc8d42a4010c9e0fd940e6f254cafedff3cd6543 +922370fa49903679fc565f09c16a5917f8125e72acfeb060fcdbadbd1644eb9f4016229756019c93c6d609cda5d5d174 +aa4c7d98a96cab138d2a53d4aee8ebff6ef903e3b629a92519608d88b3bbd94de5522291a1097e6acf830270e64c8ee1 +b3dc21608a389a72d3a752883a382baaafc61ecc44083b832610a237f6a2363f24195acce529eb4aed4ef0e27a12b66e +94619f5de05e07b32291e1d7ab1d8b7337a2235e49d4fb5f3055f090a65e932e829efa95db886b32b153bdd05a53ec8c +ade1e92722c2ffa85865d2426fb3d1654a16477d3abf580cfc45ea4b92d5668afc9d09275d3b79283e13e6b39e47424d +b7201589de7bed094911dd62fcd25c459a8e327ac447b69f541cdba30233063e5ddffad0b67e9c3e34adcffedfd0e13d +809d325310f862d6549e7cb40f7e5fc9b7544bd751dd28c4f363c724a0378c0e2adcb5e42ec8f912f5f49f18f3365c07 +a79c20aa533de7a5d671c99eb9eb454803ba54dd4f2efa3c8fec1a38f8308e9905c71e9282955225f686146388506ff6 +a85eeacb5e8fc9f3ed06a3fe2dc3108ab9f8c5877b148c73cf26e4e979bf5795edbe2e63a8d452565fd1176ed40402b2 +97ef55662f8a1ec0842b22ee21391227540adf7708f491436044f3a2eb18c471525e78e1e14fa292507c99d74d7437c6 +93110d64ed5886f3d16ce83b11425576a3a7a9bb831cd0de3f9a0b0f2270a730d68136b4ef7ff035ede004358f419b5c +ac9ed0a071517f0ae4f61ce95916a90ba9a77a3f84b0ec50ef7298acdcd44d1b94525d191c39d6bd1bb68f4471428760 +98abd6a02c7690f5a339adf292b8c9368dfc12e0f8069cf26a5e0ce54b4441638f5c66ea735142f3c28e00a0024267e6 +b51efb73ba6d44146f047d69b19c0722227a7748b0e8f644d0fc9551324cf034c041a2378c56ce8b58d06038fb8a78de +8f115af274ef75c1662b588b0896b97d71f8d67986ae846792702c4742ab855952865ce236b27e2321967ce36ff93357 +b3c4548f14d58b3ab03c222da09e4381a0afe47a72d18d50a94e0008797f78e39e99990e5b4757be62310d400746e35a +a9b1883bd5f31f909b8b1b6dcb48c1c60ed20aa7374b3ffa7f5b2ed036599b5bef33289d23c80a5e6420d191723b92f7 +85d38dffd99487ae5bb41ab4a44d80a46157bbbe8ef9497e68f061721f74e4da513ccc3422936b059575975f6787c936 +adf870fcb96e972c033ab7a35d28ae79ee795f82bc49c3bd69138f0e338103118d5529c53f2d72a9c0d947bf7d312af2 +ab4c7a44e2d9446c6ff303eb49aef0e367a58b22cc3bb27b4e69b55d1d9ee639c9234148d2ee95f9ca8079b1457d5a75 +a386420b738aba2d7145eb4cba6d643d96bda3f2ca55bb11980b318d43b289d55a108f4bc23a9606fb0bccdeb3b3bb30 +847020e0a440d9c4109773ecca5d8268b44d523389993b1f5e60e541187f7c597d79ebd6e318871815e26c96b4a4dbb1 +a530aa7e5ca86fcd1bec4b072b55cc793781f38a666c2033b510a69e110eeabb54c7d8cbcb9c61fee531a6f635ffa972 +87364a5ea1d270632a44269d686b2402da737948dac27f51b7a97af80b66728b0256547a5103d2227005541ca4b7ed04 +8816fc6e16ea277de93a6d793d0eb5c15e9e93eb958c5ef30adaf8241805adeb4da8ce19c3c2167f971f61e0b361077d +8836a72d301c42510367181bb091e4be377777aed57b73c29ef2ce1d475feedd7e0f31676284d9a94f6db01cc4de81a2 +b0d9d8b7116156d9dde138d28aa05a33e61f8a85839c1e9071ccd517b46a5b4b53acb32c2edd7150c15bc1b4bd8db9e3 +ae931b6eaeda790ba7f1cd674e53dc87f6306ff44951fa0df88d506316a5da240df9794ccbd7215a6470e6b31c5ea193 +8c6d5bdf87bd7f645419d7c6444e244fe054d437ed1ba0c122fde7800603a5fadc061e5b836cb22a6cfb2b466f20f013 +90d530c6d0cb654999fa771b8d11d723f54b8a8233d1052dc1e839ea6e314fbed3697084601f3e9bbb71d2b4eaa596df +b0d341a1422588c983f767b1ed36c18b141774f67ef6a43cff8e18b73a009da10fc12120938b8bba27f225bdfd3138f9 +a131b56f9537f460d304e9a1dd75702ace8abd68cb45419695cb8dee76998139058336c87b7afd6239dc20d7f8f940cc +aa6c51fa28975f709329adee1bbd35d49c6b878041841a94465e8218338e4371f5cb6c17f44a63ac93644bf28f15d20f +88440fb584a99ebd7f9ea04aaf622f6e44e2b43bbb49fb5de548d24a238dc8f26c8da2ccf03dd43102bda9f16623f609 +9777b8695b790e702159a4a750d5e7ff865425b95fa0a3c15495af385b91c90c00a6bd01d1b77bffe8c47d01baae846f +8b9d764ece7799079e63c7f01690c8eff00896a26a0d095773dea7a35967a8c40db7a6a74692f0118bf0460c26739af4 +85808c65c485520609c9e61fa1bb67b28f4611d3608a9f7a5030ee61c3aa3c7e7dc17fff48af76b4aecee2cb0dbd22ac +ad2783a76f5b3db008ef5f7e67391fda4e7e36abde6b3b089fc4835b5c339370287935af6bd53998bed4e399eda1136d +96f18ec03ae47c205cc4242ca58e2eff185c9dca86d5158817e2e5dc2207ab84aadda78725f8dc080a231efdc093b940 +97de1ab6c6cc646ae60cf7b86df73b9cf56cc0cd1f31b966951ebf79fc153531af55ca643b20b773daa7cab784b832f7 +870ba266a9bfa86ef644b1ef025a0f1b7609a60de170fe9508de8fd53170c0b48adb37f19397ee8019b041ce29a16576 +ad990e888d279ac4e8db90619d663d5ae027f994a3992c2fbc7d262b5990ae8a243e19157f3565671d1cb0de17fe6e55 +8d9d5adcdd94c5ba3be4d9a7428133b42e485f040a28d16ee2384758e87d35528f7f9868de9bd23d1a42a594ce50a567 +85a33ed75d514ece6ad78440e42f7fcdb59b6f4cff821188236d20edae9050b3a042ce9bc7d2054296e133d033e45022 +92afd2f49a124aaba90de59be85ff269457f982b54c91b06650c1b8055f9b4b0640fd378df02a00e4fc91f7d226ab980 +8c0ee09ec64bd831e544785e3d65418fe83ed9c920d9bb4d0bf6dd162c1264eb9d6652d2def0722e223915615931581c +8369bedfa17b24e9ad48ebd9c5afea4b66b3296d5770e09b00446c5b0a8a373d39d300780c01dcc1c6752792bccf5fd0 +8b9e960782576a59b2eb2250d346030daa50bbbec114e95cdb9e4b1ba18c3d34525ae388f859708131984976ca439d94 +b682bface862008fea2b5a07812ca6a28a58fd151a1d54c708fc2f8572916e0d678a9cb8dc1c10c0470025c8a605249e +a38d5e189bea540a824b36815fc41e3750760a52be0862c4cac68214febdc1a754fb194a7415a8fb7f96f6836196d82a +b9e7fbda650f18c7eb8b40e42cc42273a7298e65e8be524292369581861075c55299ce69309710e5b843cb884de171bd +b6657e5e31b3193874a1bace08f42faccbd3c502fb73ad87d15d18a1b6c2a146f1baa929e6f517db390a5a47b66c0acf +ae15487312f84ed6265e4c28327d24a8a0f4d2d17d4a5b7c29b974139cf93223435aaebe3af918f5b4bb20911799715f +8bb4608beb06bc394e1a70739b872ce5a2a3ffc98c7547bf2698c893ca399d6c13686f6663f483894bccaabc3b9c56ad +b58ac36bc6847077584308d952c5f3663e3001af5ecf2e19cb162e1c58bd6c49510205d453cffc876ca1dc6b8e04a578 +924f65ced61266a79a671ffb49b300f0ea44c50a0b4e3b02064faa99fcc3e4f6061ea8f38168ab118c5d47bd7804590e +8d67d43b8a06b0ff4fafd7f0483fa9ed1a9e3e658a03fb49d9d9b74e2e24858dc1bed065c12392037b467f255d4e5643 +b4d4f87813125a6b355e4519a81657fa97c43a6115817b819a6caf4823f1d6a1169683fd68f8d025cdfa40ebf3069acb +a7fd4d2c8e7b59b8eed3d4332ae94b77a89a2616347402f880bc81bde072220131e6dbec8a605be3a1c760b775375879 +8d4a7d8fa6f55a30df37bcf74952e2fa4fd6676a2e4606185cf154bdd84643fd01619f8fb8813a564f72e3f574f8ce30 +8086fb88e6260e9a9c42e9560fde76315ff5e5680ec7140f2a18438f15bc2cc7d7d43bfb5880b180b738c20a834e6134 +916c4c54721de03934fee6f43de50bb04c81f6f8dd4f6781e159e71c40c60408aa54251d457369d133d4ba3ed7c12cb4 +902e5bf468f11ed9954e2a4a595c27e34abe512f1d6dc08bbca1c2441063f9af3dc5a8075ab910a10ff6c05c1c644a35 +a1302953015e164bf4c15f7d4d35e3633425a78294406b861675667eec77765ff88472306531e5d3a4ec0a2ff0dd6a9e +87874461df3c9aa6c0fa91325576c0590f367075f2f0ecfeb34afe162c04c14f8ce9d608c37ac1adc8b9985bc036e366 +84b50a8a61d3cc609bfb0417348133e698fe09a6d37357ce3358de189efcf35773d78c57635c2d26c3542b13cc371752 +acaed2cff8633d12c1d12bb7270c54d65b0b0733ab084fd47f81d0a6e1e9b6f300e615e79538239e6160c566d8bb8d29 +889e6a0e136372ca4bac90d1ab220d4e1cad425a710e8cdd48b400b73bb8137291ceb36a39440fa84305783b1d42c72f +90952e5becec45b2b73719c228429a2c364991cf1d5a9d6845ae5b38018c2626f4308daa322cab1c72e0f6c621bb2b35 +8f5a97a801b6e9dcd66ccb80d337562c96f7914e7169e8ff0fda71534054c64bf2a9493bb830623d612cfe998789be65 +84f3df8b9847dcf1d63ca470dc623154898f83c25a6983e9b78c6d2d90a97bf5e622445be835f32c1e55e6a0a562ea78 +91d12095cd7a88e7f57f254f02fdb1a1ab18984871dead2f107404bcf8069fe68258c4e6f6ebd2477bddf738135400bb +b771a28bc04baef68604d4723791d3712f82b5e4fe316d7adc2fc01b935d8e644c06d59b83bcb542afc40ebafbee0683 +872f6341476e387604a7e93ae6d6117e72d164e38ebc2b825bc6df4fcce815004d7516423c190c1575946b5de438c08d +90d6b4aa7d40a020cdcd04e8b016d041795961a8e532a0e1f4041252131089114a251791bf57794cadb7d636342f5d1c +899023ba6096a181448d927fed7a0fe858be4eac4082a42e30b3050ee065278d72fa9b9d5ce3bc1372d4cbd30a2f2976 +a28f176571e1a9124f95973f414d5bdbf5794d41c3839d8b917100902ac4e2171eb940431236cec93928a60a77ede793 +838dbe5bcd29c4e465d02350270fa0036cd46f8730b13d91e77afb7f5ed16525d0021d3b2ae173a76c378516a903e0cb +8e105d012dd3f5d20f0f1c4a7e7f09f0fdd74ce554c3032e48da8cce0a77260d7d47a454851387770f5c256fa29bcb88 +8f4df0f9feeb7a487e1d138d13ea961459a6402fd8f8cabb226a92249a0d04ded5971f3242b9f90d08da5ff66da28af6 +ad1cfda4f2122a20935aa32fb17c536a3653a18617a65c6836700b5537122af5a8206befe9eaea781c1244c43778e7f1 +832c6f01d6571964ea383292efc8c8fa11e61c0634a25fa180737cc7ab57bc77f25e614aac9a2a03d98f27b3c1c29de2 +903f89cc13ec6685ac7728521898781fecb300e9094ef913d530bf875c18bcc3ceed7ed51e7b482d45619ab4b025c2e9 +a03c474bb915aad94f171e8d96f46abb2a19c9470601f4c915512ec8b9e743c3938450a2a5b077b4618b9df8809e1dc1 +83536c8456f306045a5f38ae4be2e350878fa7e164ea408d467f8c3bc4c2ee396bd5868008c089183868e4dfad7aa50b +88f26b4ea1b236cb326cd7ad7e2517ec8c4919598691474fe15d09cabcfc37a8d8b1b818f4d112432ee3a716b0f37871 +a44324e3fe96e9c12b40ded4f0f3397c8c7ee8ff5e96441118d8a6bfad712d3ac990b2a6a23231a8f691491ac1fd480f +b0de4693b4b9f932191a21ee88629964878680152a82996c0019ffc39f8d9369bbe2fe5844b68d6d9589ace54af947e4 +8e5d8ba948aea5fd26035351a960e87f0d23efddd8e13236cc8e4545a3dda2e9a85e6521efb8577e03772d3637d213d9 +93efc82d2017e9c57834a1246463e64774e56183bb247c8fc9dd98c56817e878d97b05f5c8d900acf1fbbbca6f146556 +8731176363ad7658a2862426ee47a5dce9434216cef60e6045fa57c40bb3ce1e78dac4510ae40f1f31db5967022ced32 +b10c9a96745722c85bdb1a693100104d560433d45b9ac4add54c7646a7310d8e9b3ca9abd1039d473ae768a18e489845 +a2ac374dfbb464bf850b4a2caf15b112634a6428e8395f9c9243baefd2452b4b4c61b0cb2836d8eae2d57d4900bf407e +b69fe3ded0c4f5d44a09a0e0f398221b6d1bf5dbb8bc4e338b93c64f1a3cac1e4b5f73c2b8117158030ec03787f4b452 +8852cdbaf7d0447a8c6f211b4830711b3b5c105c0f316e3a6a18dcfbb9be08bd6f4e5c8ae0c3692da08a2dfa532f9d5c +93bbf6d7432a7d98ade3f94b57bf9f4da9bc221a180a370b113066dd42601bb9e09edd79e2e6e04e00423399339eebda +a80941c391f1eeafc1451c59e4775d6a383946ff22997aeaadf806542ba451d3b0f0c6864eeba954174a296efe2c1550 +a045fe2bb011c2a2f71a0181a8f457a3078470fb74c628eab8b59aef69ffd0d649723bf74d6885af3f028bc5a104fb39 +b9d8c35911009c4c8cad64692139bf3fc16b78f5a19980790cb6a7aea650a25df4231a4437ae0c351676a7e42c16134f +94c79501ded0cfcbab99e1841abe4a00a0252b3870e20774c3da16c982d74c501916ec28304e71194845be6e3113c7ab +900a66418b082a24c6348d8644ddb1817df5b25cb33044a519ef47cc8e1f7f1e38d2465b7b96d32ed472d2d17f8414c6 +b26f45d393b8b2fcb29bdbb16323dc7f4b81c09618519ab3a39f8ee5bd148d0d9f3c0b5dfab55b5ce14a1cb9206d777b +aa1a87735fc493a80a96a9a57ca40a6d9c32702bfcaa9869ce1a116ae65d69cefe2f3e79a12454b4590353e96f8912b4 +a922b188d3d0b69b4e4ea2a2aa076566962844637da12c0832105d7b31dea4a309eee15d12b7a336be3ea36fcbd3e3b7 +8f3841fcf4105131d8c4d9885e6e11a46c448226401cf99356c291fadb864da9fa9d30f3a73c327f23f9fd99a11d633e +9791d1183fae270e226379af6c497e7da803ea854bb20afa74b253239b744c15f670ee808f708ede873e78d79a626c9a +a4cad52e3369491ada61bf28ada9e85de4516d21c882e5f1cd845bea9c06e0b2887b0c5527fcff6fc28acd3c04f0a796 +b9ac86a900899603452bd11a7892a9bfed8054970bfcbeaa8c9d1930db891169e38d6977f5258c25734f96c8462eee3b +a3a154c28e5580656a859f4efc2f5ebfa7eaa84ca40e3f134fa7865e8581586db74992dbfa4036aa252fba103773ddde +95cc2a0c1885a029e094f5d737e3ecf4d26b99036453a8773c77e360101f9f98676ee246f6f732a377a996702d55691f +842651bbe99720438d8d4b0218feb60481280c05beb17750e9ca0d8c0599a60f873b7fbdcc7d8835ba9a6d57b16eec03 +81ee54699da98f5620307893dcea8f64670609fa20e5622265d66283adeac122d458b3308c5898e6c57c298db2c8b24f +b97868b0b2bc98032d68352a535a1b341b9ff3c7af4e3a7f3ebc82d3419daa1b5859d6aedc39994939623c7cd878bd9b +b60325cd5d36461d07ef253d826f37f9ee6474a760f2fff80f9873d01fd2b57711543cdc8d7afa1c350aa753c2e33dea +8c205326c11d25a46717b780c639d89714c7736c974ae71287e3f4b02e6605ac2d9b4928967b1684f12be040b7bf2dd3 +95a392d82db51e26ade6c2ccd3396d7e40aff68fa570b5951466580d6e56dda51775dce5cf3a74a7f28c3cb2eb551c4d +8f2cc8071eb56dffb70bda6dd433b556221dc8bba21c53353c865f00e7d4d86c9e39f119ea9a8a12ef583e9a55d9a6b6 +9449a71af9672aaf8856896d7e3d788b22991a7103f75b08c0abbcc2bfe60fda4ed8ce502cea4511ff0ea52a93e81222 +857090ab9fdb7d59632d068f3cc8cf27e61f0d8322d30e6b38e780a1f05227199b4cd746aac1311c36c659ef20931f28 +98a891f4973e7d9aaf9ac70854608d4f7493dffc7e0987d7be9dd6029f6ea5636d24ef3a83205615ca1ff403750058e1 +a486e1365bbc278dd66a2a25d258dc82f46b911103cb16aab3945b9c95ae87b386313a12b566df5b22322ede0afe25ad +a9a1eb399ed95d396dccd8d1ac718043446f8b979ec62bdce51c617c97a312f01376ab7fb87d27034e5f5570797b3c33 +b7abc3858d7a74bb446218d2f5a037e0fae11871ed9caf44b29b69c500c1fa1dcfad64c9cdccc9d80d5e584f06213deb +8cfb09fe2e202faa4cebad932b1d35f5ca204e1c2a0c740a57812ac9a6792130d1312aabd9e9d4c58ca168bfebd4c177 +a90a305c2cd0f184787c6be596fa67f436afd1f9b93f30e875f817ac2aae8bdd2e6e656f6be809467e6b3ad84adb86b1 +80a9ef993c2b009ae172cc8f7ec036f5734cf4f4dfa06a7db4d54725e7fbfae5e3bc6f22687bdbb6961939d6f0c87537 +848ade1901931e72b955d7db1893f07003e1708ff5d93174bac5930b9a732640f0578839203e9b77eb27965c700032d3 +93fdf4697609c5ae9c33b9ca2f5f1af44abeb2b98dc4fdf732cf7388de086f410730dc384d9b7a7f447bb009653c8381 +89ce3fb805aea618b5715c0d22a9f46da696b6fa86794f56fdf1d44155a33d42daf1920bcbe36cbacf3cf4c92df9cbc7 +829ce2c342cf82aa469c65f724f308f7a750bd1494adc264609cd790c8718b8b25b5cab5858cf4ee2f8f651d569eea67 +af2f0cee7bf413204be8b9df59b9e4991bc9009e0d6dbe6815181df0ec2ca93ab8f4f3135b1c14d8f53d74bff0bd6f27 +b87998cecf7b88cde93d1779f10a521edd5574a2fbd240102978639ec57433ba08cdb53849038a329cebbe74657268d2 +a64542a1261a6ed3d720c2c3a802303aad8c4c110c95d0f12e05c1065e66f42da494792b6bfc5b9272363f3b1d457f58 +86a6fd042e4f282fadf07a4bfee03fc96a3aea49f7a00f52bf249a20f1ec892326855410e61f37fbb27d9305eb2fc713 +967ea5bc403b6db269682f7fd0df90659350d7e1aa66bc4fab4c9dfcd75ed0bba4b52f1cebc5f34dc8ba810793727629 +a52990f9f3b8616ce3cdc2c74cd195029e6a969753dcf2d1630438700e7d6ebde36538532b3525ac516f5f2ce9dd27a3 +a64f7ff870bab4a8bf0d4ef6f5c744e9bf1021ed08b4c80903c7ad318e80ba1817c3180cc45cb5a1cae1170f0241655f +b00f706fa4de1f663f021e8ad3d155e84ce6084a409374b6e6cd0f924a0a0b51bebaaaf1d228c77233a73b0a5a0df0e9 +8b882cc3bff3e42babdb96df95fb780faded84887a0a9bab896bef371cdcf169d909f5658649e93006aa3c6e1146d62e +9332663ef1d1dcf805c3d0e4ce7a07d9863fb1731172e766b3cde030bf81682cc011e26b773fb9c68e0477b4ae2cfb79 +a8aa8151348dbd4ef40aaeb699b71b4c4bfd3218560c120d85036d14f678f6736f0ec68e80ce1459d3d35feccc575164 +a16cd8b729768f51881c213434aa28301fa78fcb554ddd5f9012ee1e4eae7b5cb3dd88d269d53146dea92d10790faf0b +86844f0ef9d37142faf3b1e196e44fbe280a3ba4189aa05c356778cb9e3b388a2bff95eed305ada8769935c9974e4c57 +ae2eec6b328fccf3b47bcdac32901ac2744a51beb410b04c81dea34dee4912b619466a4f5e2780d87ecefaebbe77b46d +915df4c38d301c8a4eb2dc5b1ba0ffaad67cbb177e0a80095614e9c711f4ef24a4cef133f9d982a63d2a943ba6c8669d +ae6a2a4dedfc2d1811711a8946991fede972fdf2a389b282471280737536ffc0ac3a6d885b1f8bda0366eb0b229b9979 +a9b628c63d08b8aba6b1317f6e91c34b2382a6c85376e8ef2410a463c6796740ae936fc4e9e0737cb9455d1daa287bd8 +848e30bf7edf2546670b390d5cf9ab71f98fcb6add3c0b582cb34996c26a446dee5d1bde4fdcde4fc80c10936e117b29 +907d6096c7c8c087d1808dd995d5d2b9169b3768c3f433475b50c2e2bd4b082f4d543afd8b0b0ddffa9c66222a72d51d +a59970a2493b07339124d763ac9d793c60a03354539ecbcf6035bc43d1ea6e35718202ae6d7060b7d388f483d971573c +b9cfef2af9681b2318f119d8611ff6d9485a68d8044581b1959ab1840cbca576dbb53eec17863d2149966e9feb21122f +ad47271806161f61d3afa45cdfe2babceef5e90031a21779f83dc8562e6076680525b4970b2f11fe9b2b23c382768323 +8e425a99b71677b04fe044625d338811fbb8ee32368a424f6ab2381c52e86ee7a6cecedf777dc97181519d41c351bc22 +86b55b54d7adefc12954a9252ee23ae83efe8b5b4b9a7dc307904413e5d69868c7087a818b2833f9b004213d629be8ad +a14fda6b93923dd11e564ae4457a66f397741527166e0b16a8eb91c6701c244fd1c4b63f9dd3515193ec88fa6c266b35 +a9b17c36ae6cd85a0ed7f6cabc5b47dc8f80ced605db327c47826476dc1fb8f8669aa7a7dc679fbd4ee3d8e8b4bd6a6f +82a0829469c1458d959c821148f15dacae9ea94bf56c59a6ab2d4dd8b3d16d73e313b5a3912a6c1f131d73a8f06730c4 +b22d56d549a53eaef549595924bdb621ff807aa4513feedf3fdcbf7ba8b6b9cfa4481c2f67fc642db397a6b794a8b63a +974c59c24392e2cb9294006cbe3c52163e255f3bd0c2b457bdc68a6338e6d5b6f87f716854492f8d880a6b896ccf757c +b70d247ba7cad97c50b57f526c2ba915786e926a94e8f8c3eebc2e1be6f4255411b9670e382060049c8f4184302c40b2 +ad80201fe75ef21c3ddbd98cf23591e0d7a3ba1036dfe77785c32f44755a212c31f0ceb0a0b6f5ee9b6dc81f358d30c3 +8c656e841f9bb90b9a42d425251f3fdbc022a604d75f5845f479ed4be23e02aaf9e6e56cde351dd7449c50574818a199 +8b88dd3fa209d3063b7c5b058f7249ee9900fbc2287d16da61a0704a0a1d71e45d9c96e1cda7fdf9654534ec44558b22 +961da00cc8750bd84d253c08f011970ae1b1158ad6778e8ed943d547bceaf52d6d5a212a7de3bf2706688c4389b827d2 +a5dd379922549a956033e3d51a986a4b1508e575042b8eaa1df007aa77cf0b8c2ab23212f9c075702788fa9c53696133 +ac8fcfde3a349d1e93fc8cf450814e842005c545c4844c0401bc80e6b96cdb77f29285a14455e167c191d4f312e866cd +ac63d79c799783a8466617030c59dd5a8f92ee6c5204676fd8d881ce5f7f8663bdbeb0379e480ea9b6340ab0dc88e574 +805874fde19ce359041ae2bd52a39e2841acabfd31f965792f2737d7137f36d4e4722ede8340d8c95afa6af278af8acb +8d2f323a228aa8ba7b7dc1399138f9e6b41df1a16a7069003ab8104b8b68506a45141bc5fe66acf430e23e13a545190b +a1610c721a2d9af882bb6b39bea97cff1527a3aea041d25934de080214ae77c959e79957164440686d15ab301e897d4d +aba16d29a47fc36f12b654fde513896723e2c700c4190f11b26aa4011da57737ad717daa02794aa3246e4ae5f0b0cc3a +a406db2f15fdd135f346cc4846623c47edd195e80ba8c7cb447332095314d565e4040694ca924696bb5ee7f8996ea0ba +8b30e2cd9b47d75ba57b83630e40f832249af6c058d4f490416562af451993eec46f3e1f90bc4d389e4c06abd1b32a46 +aacf9eb7036e248e209adbfc3dd7ce386569ea9b312caa4b240726549db3c68c4f1c8cbf8ed5ea9ea60c7e57c9df3b8e +b20fcac63bf6f5ee638a42d7f89be847f348c085ddcbec3fa318f4323592d136c230495f188ef2022aa355cc2b0da6f9 +811eff750456a79ec1b1249d76d7c1547065b839d8d4aaad860f6d4528eb5b669473dcceeeea676cddbc3980b68461b7 +b52d14ae33f4ab422f953392ae76a19c618cc31afc96290bd3fe2fb44c954b5c92c4789f3f16e8793f2c0c1691ade444 +a7826dafeeba0db5b66c4dfcf2b17fd7b40507a5a53ac2e42942633a2cb30b95ba1739a6e9f3b7a0e0f1ec729bf274e2 +8acfd83ddf7c60dd7c8b20c706a3b972c65d336b8f9b3d907bdd8926ced271430479448100050b1ef17578a49c8fa616 +af0c69f65184bb06868029ad46f8465d75c36814c621ac20a5c0b06a900d59305584f5a6709683d9c0e4b6cd08d650a6 +b6cc8588191e00680ee6c3339bd0f0a17ad8fd7f4be57d5d7075bede0ea593a19e67f3d7c1a20114894ee5bfcab71063 +a82fd4f58635129dbb6cc3eb9391cf2d28400018b105fc41500fbbd12bd890b918f97d3d359c29dd3b4c4e34391dfab0 +92fc544ed65b4a3625cf03c41ddff7c039bc22d22c0d59dcc00efd5438401f2606adb125a1d5de294cca216ec8ac35a3 +906f67e4a32582b71f15940523c0c7ce370336935e2646bdaea16a06995256d25e99df57297e39d6c39535e180456407 +97510337ea5bbd5977287339197db55c60533b2ec35c94d0a460a416ae9f60e85cee39be82abeeacd5813cf54df05862 +87e6894643815c0ea48cb96c607266c5ee4f1f82ba5fe352fb77f9b6ed14bfc2b8e09e80a99ac9047dfcf62b2ae26795 +b6fd55dd156622ad7d5d51b7dde75e47bd052d4e542dd6449e72411f68275775c846dde301e84613312be8c7bce58b07 +b98461ac71f554b2f03a94e429b255af89eec917e208a8e60edf5fc43b65f1d17a20de3f31d2ce9f0cb573c25f2f4d98 +96f0dea40ca61cefbee41c4e1fe9a7d81fbe1f49bb153d083ab70f5d0488a1f717fd28cedcf6aa18d07cce2c62801898 +8d7c3ab310184f7dc34b6ce4684e4d29a31e77b09940448ea4daac730b7eb308063125d4dd229046cf11bfd521b771e0 +96f0564898fe96687918bbf0a6adead99cf72e3a35ea3347e124af9d006221f8e82e5a9d2fe80094d5e8d48e610f415e +ad50fcb92c2675a398cf07d4c40a579e44bf8d35f27cc330b57e54d5ea59f7d898af0f75dccfe3726e5471133d70f92b +828beed62020361689ae7481dd8f116902b522fb0c6c122678e7f949fdef70ead011e0e6bffd25678e388744e17cdb69 +8349decac1ca16599eee2efc95bcaabf67631107da1d34a2f917884bd70dfec9b4b08ab7bc4379d6c73b19c0b6e54fb8 +b2a6a2e50230c05613ace9e58bb2e98d94127f196f02d9dddc53c43fc68c184549ca12d713cb1b025d8260a41e947155 +94ff52181aadae832aed52fc3b7794536e2a31a21fc8be3ea312ca5c695750d37f08002f286b33f4023dba1e3253ecfa +a21d56153c7e5972ee9a319501be4faff199fdf09bb821ea9ce64aa815289676c00f105e6f00311b3a5b627091b0d0fc +a27a60d219f1f0c971db73a7f563b371b5c9fc3ed1f72883b2eac8a0df6698400c9954f4ca17d7e94e44bd4f95532afb +a2fc56fae99b1f18ba5e4fe838402164ce82f8a7f3193d0bbd360c2bac07c46f9330c4c7681ffb47074c6f81ee6e7ac6 +b748e530cd3afb96d879b83e89c9f1a444f54e55372ab1dcd46a0872f95ce8f49cf2363fc61be82259e04f555937ed16 +8bf8993e81080c7cbba1e14a798504af1e4950b2f186ab3335b771d6acaee4ffe92131ae9c53d74379d957cb6344d9cd +96774d0ef730d22d7ab6d9fb7f90b9ead44285219d076584a901960542756700a2a1603cdf72be4708b267200f6c36a9 +b47703c2ab17be1e823cc7bf3460db1d6760c0e33862c90ca058845b2ff234b0f9834ddba2efb2ee1770eb261e7d8ffd +84319e67c37a9581f8b09b5e4d4ae88d0a7fb4cbb6908971ab5be28070c3830f040b1de83ee663c573e0f2f6198640e4 +96811875fa83133e0b3c0e0290f9e0e28bca6178b77fdf5350eb19344d453dbd0d71e55a0ef749025a5a2ca0ad251e81 +81a423423e9438343879f2bfd7ee9f1c74ebebe7ce3cfffc8a11da6f040cc4145c3b527bd3cf63f9137e714dbcb474ef +b8c3535701ddbeec2db08e17a4fa99ba6752d32ece5331a0b8743676f421fcb14798afc7c783815484f14693d2f70db8 +81aee980c876949bf40782835eec8817d535f6f3f7e00bf402ddd61101fdcd60173961ae90a1cf7c5d060339a18c959d +87e67b928d97b62c49dac321ce6cb680233f3a394d4c9a899ac2e8db8ccd8e00418e66cdfd68691aa3cb8559723b580c +8eac204208d99a2b738648df96353bbb1b1065e33ee4f6bba174b540bbbd37d205855e1f1e69a6b7ff043ca377651126 +848e6e7a54ad64d18009300b93ea6f459ce855971dddb419b101f5ac4c159215626fadc20cc3b9ab1701d8f6dfaddd8b +88aa123d9e0cf309d46dddb6acf634b1ade3b090a2826d6e5e78669fa1220d6df9a6697d7778cd9b627db17eea846126 +9200c2a629b9144d88a61151b661b6c4256cc5dadfd1e59a8ce17a013c2d8f7e754aabe61663c3b30f1bc47784c1f8cf +b6e1a2827c3bdda91715b0e1b1f10dd363cef337e7c80cac1f34165fc0dea7c8b69747e310563db5818390146ce3e231 +92c333e694f89f0d306d54105b2a5dcc912dbe7654d9e733edab12e8537350815be472b063e56cfde5286df8922fdecb +a6fac04b6d86091158ebb286586ccfec2a95c9786e14d91a9c743f5f05546073e5e3cc717635a0c602cad8334e922346 +a581b4af77feebc1fb897d49b5b507c6ad513d8f09b273328efbb24ef0d91eb740d01b4d398f2738125dacfe550330cd +81c4860cccf76a34f8a2bc3f464b7bfd3e909e975cce0d28979f457738a56e60a4af8e68a3992cf273b5946e8d7f76e2 +8d1eaa09a3180d8af1cbaee673db5223363cc7229a69565f592fa38ba0f9d582cedf91e15dabd06ebbf2862fc0feba54 +9832f49b0147f4552402e54593cfa51f99540bffada12759b71fcb86734be8e500eea2d8b3d036710bdf04c901432de9 +8bdb0e8ec93b11e5718e8c13cb4f5de545d24829fd76161216340108098dfe5148ed25e3b57a89a516f09fa79043734d +ab96f06c4b9b0b2c0571740b24fca758e6976315053a7ecb20119150a9fa416db2d3a2e0f8168b390bb063f0c1caf785 +ab777f5c52acd62ecf4d1f168b9cc8e1a9b45d4ec6a8ff52c583e867c2239aba98d7d3af977289b367edce03d9c2dfb1 +a09d3ce5e748da84802436951acc3d3ea5d8ec1d6933505ed724d6b4b0d69973ab0930daec9c6606960f6e541e4a3ce2 +8ef94f7be4d85d5ad3d779a5cf4d7b2fc3e65c52fb8e1c3c112509a4af77a0b5be994f251e5e40fabeeb1f7d5615c22b +a7406a5bf5708d9e10922d3c5c45c03ef891b8d0d74ec9f28328a72be4cdc05b4f2703fa99366426659dfca25d007535 +b7f52709669bf92a2e070bfe740f422f0b7127392c5589c7f0af71bb5a8428697c762d3c0d74532899da24ea7d8695c2 +b9dfb0c8df84104dbf9239ccefa4672ef95ddabb8801b74997935d1b81a78a6a5669a3c553767ec19a1281f6e570f4ff +ae4d5c872156061ce9195ac640190d8d71dd406055ee43ffa6f9893eb24b870075b74c94d65bc1d5a07a6573282b5520 +afe6bd3eb72266d333f1807164900dcfa02a7eb5b1744bb3c86b34b3ee91e3f05e38fa52a50dc64eeb4bdb1dd62874b8 +948043cf1bc2ef3c01105f6a78dc06487f57548a3e6ef30e6ebc51c94b71e4bf3ff6d0058c72b6f3ecc37efd7c7fa8c0 +a22fd17c2f7ffe552bb0f23fa135584e8d2d8d75e3f742d94d04aded2a79e22a00dfe7acbb57d44e1cdb962fb22ae170 +8cd0f4e9e4fb4a37c02c1bde0f69359c43ab012eb662d346487be0c3758293f1ca560122b059b091fddce626383c3a8f +90499e45f5b9c81426f3d735a52a564cafbed72711d9279fdd88de8038e953bc48c57b58cba85c3b2e4ce56f1ddb0e11 +8c30e4c034c02958384564cac4f85022ef36ab5697a3d2feaf6bf105049675bbf23d01b4b6814711d3d9271abff04cac +81f7999e7eeea30f3e1075e6780bbf054f2fb6f27628a2afa4d41872a385b4216dd5f549da7ce6cf39049b2251f27fb7 +b36a7191f82fc39c283ffe53fc1f5a9a00b4c64eee7792a8443475da9a4d226cf257f226ea9d66e329af15d8f04984ec +aad4da528fdbb4db504f3041c747455baff5fcd459a2efd78f15bdf3aea0bdb808343e49df88fe7a7c8620009b7964a3 +99ebd8c6dd5dd299517fb6381cfc2a7f443e6e04a351440260dd7c2aee3f1d8ef06eb6c18820b394366ecdfd2a3ce264 +8873725b81871db72e4ec3643084b1cdce3cbf80b40b834b092767728605825c19b6847ad3dcf328438607e8f88b4410 +b008ee2f895daa6abd35bd39b6f7901ae4611a11a3271194e19da1cdcc7f1e1ea008fe5c5440e50d2c273784541ad9c5 +9036feafb4218d1f576ef89d0e99124e45dacaa6d816988e34d80f454d10e96809791d5b78f7fd65f569e90d4d7238c5 +92073c1d11b168e4fa50988b0288638b4868e48bbc668c5a6dddf5499875d53be23a285acb5e4bad60114f6cf6c556e9 +88c87dfcb8ba6cbfe7e1be081ccfadbd589301db2cb7c99f9ee5d7db90aa297ed1538d5a867678a763f2deede5fd219a +b42a562805c661a50f5dea63108002c0f27c0da113da6a9864c9feb5552225417c0356c4209e8e012d9bcc9d182c7611 +8e6317d00a504e3b79cd47feb4c60f9df186467fe9ca0f35b55c0364db30528f5ff071109dabb2fc80bb9cd4949f0c24 +b7b1ea6a88694f8d2f539e52a47466695e39e43a5eb9c6f23bca15305fe52939d8755cc3ac9d6725e60f82f994a3772f +a3cd55161befe795af93a38d33290fb642b8d80da8b786c6e6fb02d393ea308fbe87f486994039cbd7c7b390414594b6 +b416d2d45b44ead3b1424e92c73c2cf510801897b05d1724ff31cbd741920cd858282fb5d6040fe1f0aa97a65bc49424 +950ee01291754feace97c2e933e4681e7ddfbc4fcd079eb6ff830b0e481d929c93d0c7fb479c9939c28ca1945c40da09 +869bd916aee8d86efe362a49010382674825d49195b413b4b4018e88ce43fe091b475d0b863ff0ba2259400f280c2b23 +9782f38cd9c9d3385ec286ebbc7cba5b718d2e65a5890b0a5906b10a89dc8ed80d417d71d7c213bf52f2af1a1f513ea7 +91cd33bc2628d096269b23faf47ee15e14cb7fdc6a8e3a98b55e1031ea0b68d10ba30d97e660f7e967d24436d40fad73 +8becc978129cc96737034c577ae7225372dd855da8811ae4e46328e020c803833b5bdbc4a20a93270e2b8bd1a2feae52 +a36b1d8076783a9522476ce17f799d78008967728ce920531fdaf88303321bcaf97ecaa08e0c01f77bc32e53c5f09525 +b4720e744943f70467983aa34499e76de6d59aa6fadf86f6b787fdce32a2f5b535b55db38fe2da95825c51002cfe142d +91ad21fc502eda3945f6de874d1b6bf9a9a7711f4d61354f9e5634fc73f9c06ada848de15ab0a75811d3250be862827d +84f78e2ebf5fc077d78635f981712daf17e2475e14c2a96d187913006ad69e234746184a51a06ef510c9455b38acb0d7 +960aa7906e9a2f11db64a26b5892ac45f20d2ccb5480f4888d89973beb6fa0dfdc06d68d241ff5ffc7f1b82b1aac242d +a99365dcd1a00c66c9db6924b97c920f5c723380e823b250db85c07631b320ec4e92e586f7319e67a522a0578f7b6d6c +a25d92d7f70cf6a88ff317cfec071e13774516da664f5fac0d4ecaa65b8bf4eb87a64a4d5ef2bd97dfae98d388dbf5cc +a7af47cd0041295798f9779020a44653007444e8b4ef0712982b06d0dcdd434ec4e1f7c5f7a049326602cb605c9105b7 +aefe172eac5568369a05980931cc476bebd9dea573ba276d59b9d8c4420784299df5a910033b7e324a6c2dfc62e3ef05 +b69bc9d22ffa645baa55e3e02522e9892bb2daa7fff7c15846f13517d0799766883ee09ae0869df4139150c5b843ca8a +95a10856140e493354fdd12722c7fdded21b6a2ffbc78aa2697104af8ad0c8e2206f44b0bfee077ef3949d46bbf7c16b +891f2fcd2c47cbea36b7fa715968540c233313f05333f09d29aba23c193f462ed490dd4d00969656e89c53155fdfe710 +a6c33e18115e64e385c843dde34e8a228222795c7ca90bc2cc085705d609025f3351d9be61822c69035a49fb3e48f2d5 +b87fb12f12c0533b005adad0487f03393ff682e13575e3cb57280c3873b2c38ba96a63c49eef7a442753d26b7005230b +b905c02ba451bfd411c135036d92c27af3b0b1c9c2f1309d6948544a264b125f39dd41afeff4666b12146c545adc168a +8b29c513f43a78951cf742231cf5457a6d9d55edf45df5481a0f299a418d94effef561b15d2c1a01d1b8067e7153fda9 +b9941cccd51dc645920d2781c81a317e5a33cb7cf76427b60396735912cb6d2ca9292bb4d36b6392467d390d2c58d9f3 +a8546b627c76b6ef5c93c6a98538d8593dbe21cb7673fd383d5401b0c935eea0bdeeefeb1af6ad41bad8464fb87bbc48 +aa286b27de2812de63108a1aec29d171775b69538dc6198640ac1e96767c2b83a50391f49259195957d457b493b667c9 +a932fb229f641e9abbd8eb2bd874015d97b6658ab6d29769fc23b7db9e41dd4f850382d4c1f08af8f156c5937d524473 +a1412840fcc86e2aeec175526f2fb36e8b3b8d21a78412b7266daf81e51b3f68584ed8bd42a66a43afdd8c297b320520 +89c78be9efb624c97ebca4fe04c7704fa52311d183ffd87737f76b7dadc187c12c982bd8e9ed7cd8beb48cdaafd2fd01 +a3f5ddec412a5bec0ce15e3bcb41c6214c2b05d4e9135a0d33c8e50a78eaba71e0a5a6ea8b45854dec5c2ed300971fc2 +9721f9cec7a68b7758e3887548790de49fa6a442d0396739efa20c2f50352a7f91d300867556d11a703866def2d5f7b5 +a23764e140a87e5991573521af039630dd28128bf56eed2edbed130fd4278e090b60cf5a1dca9de2910603d44b9f6d45 +a1a6494a994215e48ab55c70efa8ffdddce6e92403c38ae7e8dd2f8288cad460c6c7db526bbdf578e96ca04d9fe12797 +b1705ea4cb7e074efe0405fc7b8ee2ec789af0426142f3ec81241cacd4f7edcd88e39435e4e4d8e7b1df64f3880d6613 +85595d061d677116089a6064418b93eb44ff79e68d12bd9625078d3bbc440a60d0b02944eff6054433ee34710ae6fbb4 +9978d5e30bedb7526734f9a1febd973a70bfa20890490e7cc6f2f9328feab1e24f991285dbc3711d892514e2d7d005ad +af30243c66ea43b9f87a061f947f7bce745f09194f6e95f379c7582b9fead920e5d6957eaf05c12ae1282ada4670652f +a1930efb473f88001e47aa0b2b2a7566848cccf295792e4544096ecd14ee5d7927c173a8576b405bfa2eec551cd67eb5 +b0446d1c590ee5a45f7e22d269c044f3848c97aec1d226b44bfd0e94d9729c28a38bccddc3a1006cc5fe4e3c24f001f2 +b8a8380172df3d84b06176df916cf557966d4f2f716d3e9437e415d75b646810f79f2b2b71d857181b7fc944018883a3 +a563afec25b7817bfa26e19dc9908bc00aa8fc3d19be7d6de23648701659009d10e3e4486c28e9c6b13d48231ae29ac5 +a5a8e80579de886fb7d6408f542791876885947b27ad6fa99a8a26e381f052598d7b4e647b0115d4b5c64297e00ce28e +8f87afcc7ad33c51ac719bade3cd92da671a37a82c14446b0a2073f4a0a23085e2c8d31913ed2d0be928f053297de8f6 +a43c455ce377e0bc434386c53c752880687e017b2f5ae7f8a15c044895b242dffde4c92fb8f8bb50b18470b17351b156 +8368f8b12a5bceb1dba25adb3a2e9c7dc9b1a77a1f328e5a693f5aec195cd1e06b0fe9476b554c1c25dac6c4a5b640a3 +919878b27f3671fc78396f11531c032f3e2bd132d04cc234fa4858676b15fb1db3051c0b1db9b4fc49038216f11321ce +b48cd67fb7f1242696c1f877da4bdf188eac676cd0e561fbac1a537f7b8229aff5a043922441d603a26aae56a15faee4 +a3e0fdfd4d29ea996517a16f0370b54787fefe543c2fe73bfc6f9e560c1fd30dad8409859e2d7fa2d44316f24746c712 +8bb156ade8faf149df7bea02c140c7e392a4742ae6d0394d880a849127943e6f26312033336d3b9fdc0092d71b5efe87 +8845e5d5cc555ca3e0523244300f2c8d7e4d02aaebcb5bd749d791208856c209a6f84dd99fd55968c9f0ab5f82916707 +a3e90bb5c97b07789c2f32dff1aec61d0a2220928202f5ad5355ae71f8249237799d6c8a22602e32e572cb12eabe0c17 +b150bcc391884c996149dc3779ce71f15dda63a759ee9cc05871f5a8379dcb62b047098922c0f26c7bd04deb394c33f9 +95cd4ad88d51f0f2efcfd0c2df802fe252bb9704d1afbf9c26a248df22d55da87bdfaf41d7bc6e5df38bd848f0b13f42 +a05a49a31e91dff6a52ac8b9c2cfdd646a43f0d488253f9e3cfbce52f26667166bbb9b608fc358763a65cbf066cd6d05 +a59c3c1227fdd7c2e81f5e11ef5c406da44662987bac33caed72314081e2eed66055d38137e01b2268e58ec85dd986c0 +b7020ec3bd73a99861f0f1d88cf5a19abab1cbe14b7de77c9868398c84bb8e18dbbe9831838a96b6d6ca06e82451c67b +98d1ff2525e9718ee59a21d8900621636fcd873d9a564b8dceb4be80a194a0148daf1232742730b3341514b2e5a5436c +886d97b635975fc638c1b6afc493e5998ca139edba131b75b65cfe5a8e814f11bb678e0eeee5e6e5cd913ad3f2fefdfc +8fb9fd928d38d5d813b671c924edd56601dd7163b686c13f158645c2f869d9250f3859aa5463a39258c90fef0f41190a +aac35e1cd655c94dec3580bb3800bd9c2946c4a9856f7d725af15fbea6a2d8ca51c8ad2772abed60ee0e3fb9cb24046b +b8d71fa0fa05ac9e443c9b4929df9e7f09a919be679692682e614d24227e04894bfc14a5c73a62fb927fedff4a0e4aa7 +a45a19f11fbbb531a704badbb813ed8088ab827c884ee4e4ebf363fa1132ff7cfa9d28be9c85b143e4f7cdbc94e7cf1a +82b54703a4f295f5471b255ab59dce00f0fe90c9fb6e06b9ee48b15c91d43f4e2ef4a96c3118aeb03b08767be58181bb +8283264c8e6d2a36558f0d145c18576b6600ff45ff99cc93eca54b6c6422993cf392668633e5df396b9331e873d457e5 +8c549c03131ead601bc30eb6b9537b5d3beb7472f5bb1bcbbfd1e9f3704477f7840ab3ab7f7dc13bbbbcdff886a462d4 +afbb0c520ac1b5486513587700ad53e314cb74bfbc12e0b5fbdcfdaac36d342e8b59856196a0d84a25cff6e6e1d17e76 +89e4c22ffb51f2829061b3c7c1983c5c750cad158e3a825d46f7cf875677da5d63f653d8a297022b5db5845c9271b32b +afb27a86c4c2373088c96b9adf4433f2ebfc78ac5c526e9f0510670b6e4e5e0057c0a4f75b185e1a30331b9e805c1c15 +a18e16b57445f88730fc5d3567bf5a176861dc14c7a08ed2996fe80eed27a0e7628501bcb78a1727c5e9ac55f29c12c4 +93d61bf88b192d6825cf4e1120af1c17aa0f994d158b405e25437eaeefae049f7b721a206e7cc8a04fdc29d3c42580a1 +a99f2995a2e3ed2fd1228d64166112038de2f516410aa439f4c507044e2017ea388604e2d0f7121256fadf7fbe7023d1 +914fd91cffc23c32f1c6d0e98bf660925090d873367d543034654389916f65f552e445b0300b71b61b721a72e9a5983c +b42a578a7787b71f924e7def425d849c1c777156b1d4170a8ee7709a4a914e816935131afd9a0412c4cb952957b20828 +82fb30590e84b9e45db1ec475a39971cf554dc01bcc7050bc89265740725c02e2be5a972168c5170c86ae83e5b0ad2c0 +b14f8d8e1e93a84976289e0cf0dfa6f3a1809e98da16ee5c4932d0e1ed6bf8a07697fdd4dd86a3df84fb0003353cdcc0 +85d7a2f4bda31aa2cb208b771fe03291a4ebdaf6f1dc944c27775af5caec412584c1f45bc741fca2a6a85acb3f26ad7d +af02e56ce886ff2253bc0a68faad76f25ead84b2144e5364f3fb9b648f03a50ee9dc0b2c33ebacf7c61e9e43201ef9ef +87e025558c8a0b0abd06dfc350016847ea5ced7af2d135a5c9eec9324a4858c4b21510fb0992ec52a73447f24945058e +80fff0bafcd058118f5e7a4d4f1ae0912efeb281d2cbe4d34ba8945cc3dbe5d8baf47fb077343b90b8d895c90b297aca +b6edcf3a40e7b1c3c0148f47a263cd819e585a51ef31c2e35a29ce6f04c53e413f743034c0d998d9c00a08ba00166f31 +abb87ed86098c0c70a76e557262a494ff51a30fb193f1c1a32f8e35eafa34a43fcc07aa93a3b7a077d9e35afa07b1a3d +a280214cd3bb0fb7ecd2d8bcf518cbd9078417f2b91d2533ec2717563f090fb84f2a5fcfdbbeb2a2a1f8a71cc5aa5941 +a63083ca7238ea2b57d15a475963cf1d4f550d8cd76db290014a0461b90351f1f26a67d674c837b0b773b330c7c3d534 +a8fa39064cb585ece5263e2f42f430206476bf261bd50f18d2b694889bd79d04d56410664cecad62690e5c5a20b3f6ff +85ba52ce9d700a5dcf6c5b00559acbe599d671ce5512467ff4b6179d7fad550567ce2a9c126a50964e3096458ea87920 +b913501e1008f076e5eac6d883105174f88b248e1c9801e568fefaffa1558e4909364fc6d9512aa4d125cbd7cc895f05 +8eb33b5266c8f2ed4725a6ad147a322e44c9264cf261c933cbbe230a43d47fca0f29ec39756b20561dabafadd5796494 +850ebc8b661a04318c9db5a0515066e6454fa73865aa4908767a837857ecd717387f614acb614a88e075d4edc53a2f5a +a08d6b92d866270f29f4ce23a3f5d99b36b1e241a01271ede02817c8ec3f552a5c562db400766c07b104a331835c0c64 +8131804c89bb3e74e9718bfc4afa547c1005ff676bd4db9604335032b203390cfa54478d45c6c78d1fe31a436ed4be9f +9106d94f23cc1eacec8316f16d6f0a1cc160967c886f51981fdb9f3f12ee1182407d2bb24e5b873de58cb1a3ee915a6b +a13806bfc3eae7a7000c9d9f1bd25e10218d4e67f59ae798b145b098bca3edad2b1040e3fc1e6310e612fb8818f459ac +8c69fbca502046cb5f6db99900a47b34117aef3f4b241690cdb3b84ca2a2fc7833e149361995dc41fa78892525bce746 +852c473150c91912d58ecb05769222fa18312800c3f56605ad29eec9e2d8667b0b81c379048d3d29100ed2773bb1f3c5 +b1767f6074426a00e01095dbb1795beb4e4050c6411792cbad6537bc444c3165d1058bafd1487451f9c5ddd209e0ae7e +80c600a5fe99354ce59ff0f84c760923dc8ff66a30bf47dc0a086181785ceb01f9b951c4e66df800ea6d705e8bc47055 +b5cf19002fbc88a0764865b82afcb4d64a50196ea361e5c71dff7de084f4dcbbc34ec94a45cc9e0247bd51da565981aa +93e67a254ea8ce25e112d93cc927fadaa814152a2c4ec7d9a56eaa1ed47aec99b7e9916b02e64452cc724a6641729bbb +ace70b32491bda18eee4a4d041c3bc9effae9340fe7e6c2f5ad975ee0874c17f1a7da7c96bd85fccff9312c518fac6e9 +ab4cfa02065017dd7f1aadc66f2c92f78f0f11b8597c03a5d69d82cb2eaf95a4476a836ac102908f137662472c8d914b +a40b8cd8deb8ae503d20364d64cab7c2801b7728a9646ed19c65edea6a842756a2f636283494299584ad57f4bb12cd0b +8594e11d5fc2396bcd9dbf5509ce4816dbb2b7305168021c426171fb444d111da5a152d6835ad8034542277011c26c0e +8024de98c26b4c994a66628dc304bb737f4b6859c86ded552c5abb81fd4c6c2e19d5a30beed398a694b9b2fdea1dd06a +8843f5872f33f54df8d0e06166c1857d733995f67bc54abb8dfa94ad92407cf0179bc91b0a50bbb56cdc2b350d950329 +b8bab44c7dd53ef9edf497dcb228e2a41282c90f00ba052fc52d57e87b5c8ab132d227af1fcdff9a12713d1f980bcaae +982b4d7b29aff22d527fd82d2a52601d95549bfb000429bb20789ed45e5abf1f4b7416c7b7c4b79431eb3574b29be658 +8eb1f571b6a1878e11e8c1c757e0bc084bab5e82e897ca9be9b7f4b47b91679a8190bf0fc8f799d9b487da5442415857 +a6e74b588e5af935c8b243e888582ef7718f8714569dd4992920740227518305eb35fab674d21a5551cca44b3e511ef2 +a30fc2f3a4cb4f50566e82307de73cd7bd8fe2c1184e9293c136a9b9e926a018d57c6e4f308c95b9eb8299e94d90a2a1 +a50c5869ca5d2b40722c056a32f918d47e0b65ca9d7863ca7d2fb4a7b64fe523fe9365cf0573733ceaadebf20b48fff8 +83bbdd32c04d17581418cf360749c7a169b55d54f2427390defd9f751f100897b2d800ce6636c5bbc046c47508d60c8c +a82904bdf614de5d8deaff688c8a5e7ac5b3431687acbcda8fa53960b7c417a39c8b2e462d7af91ce6d79260f412db8e +a4362e31ff4b05d278b033cf5eebea20de01714ae16d4115d04c1da4754269873afc8171a6f56c5104bfd7b0db93c3e7 +b5b8daa63a3735581e74a021b684a1038cea77168fdb7fdf83c670c2cfabcfc3ab2fc7359069b5f9048188351aef26b5 +b48d723894b7782d96ac8433c48faca1bdfa5238019c451a7f47d958097cce3ae599b876cf274269236b9d6ff8b6d7ca +98ffff6a61a3a6205c7820a91ca2e7176fab5dba02bc194c4d14942ac421cb254183c705506ab279e4f8db066f941c6c +ae7db24731da2eaa6efc4f7fcba2ecc26940ddd68038dce43acf2cee15b72dc4ef42a7bfdd32946d1ed78786dd7696b3 +a656db14f1de9a7eb84f6301b4acb2fbf78bfe867f48a270e416c974ab92821eb4df1cb881b2d600cfed0034ac784641 +aa315f8ecba85a5535e9a49e558b15f39520fce5d4bf43131bfbf2e2c9dfccc829074f9083e8d49f405fb221d0bc4c3c +90bffba5d9ff40a62f6c8e9fc402d5b95f6077ed58d030c93e321b8081b77d6b8dac3f63a92a7ddc01585cf2c127d66c +abdd733a36e0e0f05a570d0504e73801bf9b5a25ff2c78786f8b805704997acb2e6069af342538c581144d53149fa6d3 +b4a723bb19e8c18a01bd449b1bb3440ddb2017f10bb153da27deb7a6a60e9bb37619d6d5435fbb1ba617687838e01dd0 +870016b4678bab3375516db0187a2108b2e840bae4d264b9f4f27dbbc7cc9cac1d7dc582d7a04d6fd1ed588238e5e513 +80d33d2e20e8fc170aa3cb4f69fffb72aeafb3b5bb4ea0bc79ab55da14142ca19b2d8b617a6b24d537366e3b49cb67c3 +a7ee76aec273aaae03b3b87015789289551969fb175c11557da3ab77e39ab49d24634726f92affae9f4d24003050d974 +8415ea4ab69d779ebd42d0fe0c6aef531d6a465a5739e429b1fcf433ec45aa8296c527e965a20f0ec9f340c9273ea3cf +8c7662520794e8b4405d0b33b5cac839784bc86a5868766c06cbc1fa306dbe334978177417b31baf90ce7b0052a29c56 +902b2abecc053a3dbdea9897ee21e74821f3a1b98b2d560a514a35799f4680322550fd3a728d4f6d64e1de98033c32b8 +a05e84ed9ecab8d508d670c39f2db61ad6e08d2795ec32a3c9d0d3737ef3801618f4fc2a95f90ec2f068606131e076c5 +8b9208ff4d5af0c2e3f53c9375da666773ac57197dfabb0d25b1c8d0588ba7f3c15ee9661bb001297f322ea2fbf6928b +a3c827741b34a03254d4451b5ab74a96f2b9f7fb069e2f5adaf54fd97cc7a4d516d378db5ca07da87d8566d6eef13726 +8509d8a3f4a0ed378e0a1e28ea02f6bf1d7f6c819c6c2f5297c7df54c895b848f841653e32ba2a2c22c2ff739571acb8 +a0ce988b7d3c40b4e496aa83a09e4b5472a2d98679622f32bea23e6d607bc7de1a5374fb162bce0549a67dad948519be +aa8a3dd12bd60e3d2e05f9c683cdcb8eab17fc59134815f8d197681b1bcf65108cba63ac5c58ee632b1e5ed6bba5d474 +8b955f1d894b3aefd883fb4b65f14cd37fc2b9db77db79273f1700bef9973bf3fd123897ea2b7989f50003733f8f7f21 +ac79c00ddac47f5daf8d9418d798d8af89fc6f1682e7e451f71ea3a405b0d36af35388dd2a332af790bc83ca7b819328 +a0d44dd2a4438b809522b130d0938c3fe7c5c46379365dbd1810a170a9aa5818e1c783470dd5d0b6d4ac7edbb7330910 +a30b69e39ad43dd540a43c521f05b51b5f1b9c4eed54b8162374ae11eac25da4f5756e7b70ce9f3c92c2eeceee7431ed +ac43220b762c299c7951222ea19761ab938bf38e4972deef58ed84f4f9c68c230647cf7506d7cbfc08562fcca55f0485 +b28233b46a8fb424cfa386a845a3b5399d8489ceb83c8f3e05c22c934798d639c93718b7b68ab3ce24c5358339e41cbb +ac30d50ee8ce59a10d4b37a3a35e62cdb2273e5e52232e202ca7d7b8d09d28958ee667fae41a7bb6cdc6fe8f6e6c9c85 +b199842d9141ad169f35cc7ff782b274cbaa645fdb727761e0a89edbf0d781a15f8218b4bf4eead326f2903dd88a9cc1 +85e018c7ddcad34bb8285a737c578bf741ccd547e68c734bdb3808380e12c5d4ef60fc896b497a87d443ff9abd063b38 +8c856e6ba4a815bdb891e1276f93545b7072f6cb1a9aa6aa5cf240976f29f4dee01878638500a6bf1daf677b96b54343 +b8a47555fa8710534150e1a3f13eab33666017be6b41005397afa647ea49708565f2b86b77ad4964d140d9ced6b4d585 +8cd1f1db1b2f4c85a3f46211599caf512d5439e2d8e184663d7d50166fd3008f0e9253272f898d81007988435f715881 +b1f34b14612c973a3eceb716dc102b82ab18afef9de7630172c2780776679a7706a4874e1df3eaadf541fb009731807f +b25464af9cff883b55be2ff8daf610052c02df9a5e147a2cf4df6ce63edcdee6dc535c533590084cc177da85c5dc0baa +91c3c4b658b42d8d3448ae1415d4541d02379a40dc51e36a59bd6e7b9ba3ea51533f480c7c6e8405250ee9b96a466c29 +86dc027b95deb74c36a58a1333a03e63cb5ae22d3b29d114cfd2271badb05268c9d0c819a977f5e0c6014b00c1512e3a +ae0e6ff58eb5fa35da5107ebeacf222ab8f52a22bb1e13504247c1dfa65320f40d97b0e6b201cb6613476687cb2f0681 +8f13415d960b9d7a1d93ef28afc2223e926639b63bdefce0f85e945dfc81670a55df288893a0d8b3abe13c5708f82f91 +956f67ca49ad27c1e3a68c1faad5e7baf0160c459094bf6b7baf36b112de935fdfd79fa4a9ea87ea8de0ac07272969f4 +835e45e4a67df9fb51b645d37840b3a15c171d571a10b03a406dd69d3c2f22df3aa9c5cbe1e73f8d767ce01c4914ea9a +919b938e56d4b32e2667469d0bdccb95d9dda3341aa907683ee70a14bbbe623035014511c261f4f59b318b610ac90aa3 +96b48182121ccd9d689bf1dfdc228175564cd68dc904a99c808a7f0053a6f636c9d953e12198bdf2ea49ea92772f2e18 +ac5e5a941d567fa38fdbcfa8cf7f85bb304e3401c52d88752bcd516d1fa9bac4572534ea2205e38423c1df065990790f +ac0bd594fb85a8d4fc26d6df0fa81f11919401f1ecf9168b891ec7f061a2d9368af99f7fd8d9b43b2ce361e7b8482159 +83d92c69ca540d298fe80d8162a1c7af3fa9b49dfb69e85c1d136a3ec39fe419c9fa78e0bb6d96878771fbd37fe92e40 +b35443ae8aa66c763c2db9273f908552fe458e96696b90e41dd509c17a5c04ee178e3490d9c6ba2dc0b8f793c433c134 +923b2d25aa45b2e580ffd94cbb37dc8110f340f0f011217ee1bd81afb0714c0b1d5fb4db86006cdd2457563276f59c59 +96c9125d38fca1a61ac21257b696f8ac3dae78def50285e44d90ea293d591d1c58f703540a7e4e99e070afe4646bbe15 +b57946b2332077fbcdcb406b811779aefd54473b5559a163cd65cb8310679b7e2028aa55c12a1401fdcfcac0e6fae29a +845daedc5cf972883835d7e13c937b63753c2200324a3b8082a6c4abb4be06c5f7c629d4abe4bfaf1d80a1f073eb6ce6 +91a55dfd0efefcd03dc6dacc64ec93b8d296cb83c0ee72400a36f27246e7f2a60e73b7b70ba65819e9cfb73edb7bd297 +8874606b93266455fe8fdd25df9f8d2994e927460af06f2e97dd4d2d90db1e6b06d441b72c2e76504d753badca87fb37 +8ee99e6d231274ff9252c0f4e84549da173041299ad1230929c3e3d32399731c4f20a502b4a307642cac9306ccd49d3c +8836497714a525118e20849d6933bb8535fb6f72b96337d49e3133d936999c90a398a740f42e772353b5f1c63581df6d +a6916945e10628f7497a6cdc5e2de113d25f7ade3e41e74d3de48ccd4fce9f2fa9ab69645275002e6f49399b798c40af +9597706983107eb23883e0812e1a2c58af7f3499d50c6e29b455946cb9812fde1aa323d9ed30d1c0ffd455abe32303cd +a24ee89f7f515cc33bdbdb822e7d5c1877d337f3b2162303cfc2dae028011c3a267c5cb4194afa63a4856a6e1c213448 +8cd25315e4318801c2776824ae6e7d543cb85ed3bc2498ba5752df2e8142b37653cf9e60104d674be3aeb0a66912e97a +b5085ecbe793180b40dbeb879f4c976eaaccaca3a5246807dced5890e0ed24d35f3f86955e2460e14fb44ff5081c07ba +960188cc0b4f908633a6840963a6fa2205fc42c511c6c309685234911c5304ef4c304e3ae9c9c69daa2fb6a73560c256 +a32d0a70bf15d569b4cda5aebe3e41e03c28bf99cdd34ffa6c5d58a097f322772acca904b3a47addb6c7492a7126ebac +977f72d06ad72d4aa4765e0f1f9f4a3231d9f030501f320fe7714cc5d329d08112789fa918c60dd7fdb5837d56bb7fc6 +99fa038bb0470d45852bb871620d8d88520adb701712fcb1f278fed2882722b9e729e6cdce44c82caafad95e37d0e6f7 +b855e8f4fc7634ada07e83b6c719a1e37acb06394bc8c7dcab7747a8c54e5df3943915f021364bd019fdea103864e55f +88bc2cd7458532e98c596ef59ea2cf640d7cc31b4c33cef9ed065c078d1d4eb49677a67de8e6229cc17ea48bace8ee5a +aaa78a3feaa836d944d987d813f9b9741afb076e6aca1ffa42682ab06d46d66e0c07b8f40b9dbd63e75e81efa1ef7b08 +b7b080420cc4d808723b98b2a5b7b59c81e624ab568ecdfdeb8bf3aa151a581b6f56e983ef1b6f909661e25db40b0c69 +abee85c462ac9a2c58e54f06c91b3e5cd8c5f9ab5b5deb602b53763c54826ed6deb0d6db315a8d7ad88733407e8d35e2 +994d075c1527407547590df53e9d72dd31f037c763848d1662eebd4cefec93a24328c986802efa80e038cb760a5300f5 +ab8777640116dfb6678e8c7d5b36d01265dfb16321abbfc277da71556a34bb3be04bc4ae90124ed9c55386d2bfb3bda0 +967e3a828bc59409144463bcf883a3a276b5f24bf3cbfdd7a42343348cba91e00b46ac285835a9b91eef171202974204 +875a9f0c4ffe5bb1d8da5e3c8e41d0397aa6248422a628bd60bfae536a651417d4e8a7d2fb98e13f2dad3680f7bd86d3 +acaa330c3e8f95d46b1880126572b238dbb6d04484d2cd4f257ab9642d8c9fc7b212188b9c7ac9e0fd135c520d46b1bf +aceb762edbb0f0c43dfcdb01ea7a1ac5918ca3882b1e7ebc4373521742f1ed5250d8966b498c00b2b0f4d13212e6dd0b +81d072b4ad258b3646f52f399bced97c613b22e7ad76373453d80b1650c0ca87edb291a041f8253b649b6e5429bb4cff +980a47d27416ac39c7c3a0ebe50c492f8c776ea1de44d5159ac7d889b6d554357f0a77f0e5d9d0ff41aae4369eba1fc2 +8b4dfd5ef5573db1476d5e43aacfb5941e45d6297794508f29c454fe50ea622e6f068b28b3debe8635cf6036007de2e3 +a60831559d6305839515b68f8c3bc7abbd8212cc4083502e19dd682d56ca37c9780fc3ce4ec2eae81ab23b221452dc57 +951f6b2c1848ced9e8a2339c65918e00d3d22d3e59a0a660b1eca667d18f8430d737884e9805865ef3ed0fe1638a22d9 +b02e38fe790b492aa5e89257c4986c9033a8b67010fa2add9787de857d53759170fdd67715ca658220b4e14b0ca48124 +a51007e4346060746e6b0e4797fc08ef17f04a34fe24f307f6b6817edbb8ce2b176f40771d4ae8a60d6152cbebe62653 +a510005b05c0b305075b27b243c9d64bcdce85146b6ed0e75a3178b5ff9608213f08c8c9246f2ca6035a0c3e31619860 +aaff4ef27a7a23be3419d22197e13676d6e3810ceb06a9e920d38125745dc68a930f1741c9c2d9d5c875968e30f34ab5 +864522a9af9857de9814e61383bebad1ba9a881696925a0ea6bfc6eff520d42c506bbe5685a9946ed710e889765be4a0 +b63258c080d13f3b7d5b9f3ca9929f8982a6960bdb1b0f8676f4dca823971601672f15e653917bf5d3746bb220504913 +b51ce0cb10869121ae310c7159ee1f3e3a9f8ad498827f72c3d56864808c1f21fa2881788f19ece884d3f705cd7bd0c5 +95d9cecfc018c6ed510e441cf84c712d9909c778c16734706c93222257f64dcd2a9f1bd0b400ca271e22c9c487014274 +8beff4d7d0140b86380ff4842a9bda94c2d2be638e20ac68a4912cb47dbe01a261857536375208040c0554929ced1ddc +891ff49258749e2b57c1e9b8e04b12c77d79c3308b1fb615a081f2aacdfb4b39e32d53e069ed136fdbd43c53b87418fa +9625cad224e163d387738825982d1e40eeff35fe816d10d7541d15fdc4d3eee48009090f3faef4024b249205b0b28f72 +8f3947433d9bd01aa335895484b540a9025a19481a1c40b4f72dd676bfcf332713714fd4010bde936eaf9470fd239ed0 +a00ec2d67789a7054b53f0e858a8a232706ccc29a9f3e389df7455f1a51a2e75801fd78469a13dbc25d28399ae4c6182 +a3f65884506d4a62b8775a0ea0e3d78f5f46bc07910a93cd604022154eabdf1d73591e304d61edc869e91462951975e1 +a14eef4fd5dfac311713f0faa9a60415e3d30b95a4590cbf95f2033dffb4d16c02e7ceff3dcd42148a4e3bc49cce2dd4 +8afa11c0eef3c540e1e3460bc759bb2b6ea90743623f88e62950c94e370fe4fd01c22b6729beba4dcd4d581198d9358f +afb05548a69f0845ffcc5f5dc63e3cdb93cd270f5655173b9a950394b0583663f2b7164ba6df8d60c2e775c1d9f120af +97f179e01a947a906e1cbeafa083960bc9f1bade45742a3afee488dfb6011c1c6e2db09a355d77f5228a42ccaa7bdf8e +8447fca4d35f74b3efcbd96774f41874ca376bf85b79b6e66c92fa3f14bdd6e743a051f12a7fbfd87f319d1c6a5ce217 +a57ca39c23617cd2cf32ff93b02161bd7baf52c4effb4679d9d5166406e103bc8f3c6b5209e17c37dbb02deb8bc72ddd +9667c7300ff80f0140be002b0e36caab07aaee7cce72679197c64d355e20d96196acaf54e06e1382167d081fe6f739c1 +828126bb0559ce748809b622677267ca896fa2ee76360fd2c02990e6477e06a667241379ca7e65d61a5b64b96d7867de +8b8835dea6ba8cf61c91f01a4b3d2f8150b687a4ee09b45f2e5fc8f80f208ae5d142d8e3a18153f0722b90214e60c5a7 +a98e8ff02049b4da386e3ee93db23bbb13dfeb72f1cfde72587c7e6d962780b7671c63e8ac3fbaeb1a6605e8d79e2f29 +87a4892a0026d7e39ef3af632172b88337cb03669dea564bcdb70653b52d744730ebb5d642e20cb627acc9dbb547a26b +877352a22fc8052878a57effc159dac4d75fe08c84d3d5324c0bab6d564cdf868f33ceee515eee747e5856b62cfa0cc7 +8b801ba8e2ff019ee62f64b8cb8a5f601fc35423eb0f9494b401050103e1307dc584e4e4b21249cd2c686e32475e96c3 +a9e7338d6d4d9bfec91b2af28a8ed13b09415f57a3a00e5e777c93d768fdb3f8e4456ae48a2c6626b264226e911a0e28 +99c05fedf40ac4726ed585d7c1544c6e79619a0d3fb6bda75a08c7f3c0008e8d5e19ed4da48de3216135f34a15eba17c +a61cce8a1a8b13a4a650fdbec0eeea8297c352a8238fb7cac95a0df18ed16ee02a3daa2de108fa122aca733bd8ad7855 +b97f37da9005b440b4cb05870dd881bf8491fe735844f2d5c8281818583b38e02286e653d9f2e7fa5e74c3c3eb616540 +a72164a8554da8e103f692ac5ebb4aece55d5194302b9f74b6f2a05335b6e39beede0bf7bf8c5bfd4d324a784c5fb08c +b87e8221c5341cd9cc8bb99c10fe730bc105550f25ed4b96c0d45e6142193a1b2e72f1b3857373a659b8c09be17b3d91 +a41fb1f327ef91dcb7ac0787918376584890dd9a9675c297c45796e32d6e5985b12f9b80be47fc3a8596c245f419d395 +90dafa3592bdbb3465c92e2a54c2531822ba0459d45d3e7a7092fa6b823f55af28357cb51896d4ec2d66029c82f08e26 +a0a9adc872ebc396557f484f1dd21954d4f4a21c4aa5eec543f5fa386fe590839735c01f236574f7ff95407cd12de103 +b8c5c940d58be7538acf8672852b5da3af34f82405ef2ce8e4c923f1362f97fc50921568d0fd2fe846edfb0823e62979 +85aaf06a8b2d0dac89dafd00c28533f35dbd074978c2aaa5bef75db44a7b12aeb222e724f395513b9a535809a275e30b +81f3cbe82fbc7028c26a6c1808c604c63ba023a30c9f78a4c581340008dbda5ec07497ee849a2183fcd9124f7936af32 +a11ac738de75fd60f15a34209d3825d5e23385796a4c7fc5931822f3f380af977dd0f7b59fbd58eed7777a071e21b680 +85a279c493de03db6fa6c3e3c1b1b29adc9a8c4effc12400ae1128da8421954fa8b75ad19e5388fe4543b76fb0812813 +83a217b395d59ab20db6c4adb1e9713fc9267f5f31a6c936042fe051ce8b541f579442f3dcf0fa16b9e6de9fd3518191 +83a0b86e7d4ed8f9ccdc6dfc8ff1484509a6378fa6f09ed908e6ab9d1073f03011dc497e14304e4e3d181b57de06a5ab +a63ad69c9d25704ce1cc8e74f67818e5ed985f8f851afa8412248b2df5f833f83b95b27180e9e7273833ed0d07113d3b +99b1bc2021e63b561fe44ddd0af81fcc8627a91bfeecbbc989b642bc859abc0c8d636399701aad7bbaf6a385d5f27d61 +b53434adb66f4a807a6ad917c6e856321753e559b1add70824e5c1e88191bf6993fccb9b8b911fc0f473fb11743acacd +97ed3b9e6fb99bf5f945d4a41f198161294866aa23f2327818cdd55cb5dc4c1a8eff29dd8b8d04902d6cd43a71835c82 +b1e808260e368a18d9d10bdea5d60223ba1713b948c782285a27a99ae50cc5fc2c53d407de07155ecc16fb8a36d744a0 +a3eb4665f18f71833fec43802730e56b3ee5a357ea30a888ad482725b169d6f1f6ade6e208ee081b2e2633079b82ba7d +ab8beb2c8353fc9f571c18fdd02bdb977fc883313469e1277b0372fbbb33b80dcff354ca41de436d98d2ed710faa467e +aa9071cfa971e4a335a91ad634c98f2be51544cb21f040f2471d01bb97e1df2277ae1646e1ea8f55b7ba9f5c8c599b39 +80b7dbfdcaf40f0678012acc634eba44ea51181475180d9deb2050dc4f2de395289edd0223018c81057ec79b04b04c49 +89623d7f6cb17aa877af14de842c2d4ab7fd576d61ddd7518b5878620a01ded40b6010de0da3cdf31d837eecf30e9847 +a773bb024ae74dd24761f266d4fb27d6fd366a8634febe8235376b1ae9065c2fe12c769f1d0407867dfbe9f5272c352f +8455a561c3aaa6ba64c881a5e13921c592b3a02e968f4fb24a2243c36202795d0366d9cc1a24e916f84d6e158b7aeac7 +81d8bfc4b283cf702a40b87a2b96b275bdbf0def17e67d04842598610b67ea08c804d400c3e69fa09ea001eaf345b276 +b8f8f82cb11fea1c99467013d7e167ff03deb0c65a677fab76ded58826d1ba29aa7cf9fcd7763615735ea3ad38e28719 +89a6a04baf9cccc1db55179e1650b1a195dd91fb0aebc197a25143f0f393524d2589975e3fbfc2547126f0bced7fd6f2 +b81b2162df045390f04df07cbd0962e6b6ca94275a63edded58001a2f28b2ae2af2c7a6cba4ecd753869684e77e7e799 +a3757f722776e50de45c62d9c4a2ee0f5655a512344c4cbec542d8045332806568dd626a719ef21a4eb06792ca70f204 +8c5590df96ec22179a4e8786de41beb44f987a1dcc508eb341eecbc0b39236fdfad47f108f852e87179ccf4e10091e59 +87502f026ed4e10167419130b88c3737635c5b9074c364e1dd247cef5ef0fc064b4ae99b187e33301e438bbd2fe7d032 +af925a2165e980ced620ff12289129fe17670a90ae0f4db9d4b39bd887ccb1f5d2514ac9ecf910f6390a8fc66bd5be17 +857fca899828cf5c65d26e3e8a6e658542782fc72762b3b9c73514919f83259e0f849a9d4838b40dc905fe43024d0d23 +87ffebdbfb69a9e1007ebac4ffcb4090ff13705967b73937063719aa97908986effcb7262fdadc1ae0f95c3690e3245d +a9ff6c347ac6f4c6ab993b748802e96982eaf489dc69032269568412fc9a79e7c2850dfc991b28211b3522ee4454344b +a65b3159df4ec48bebb67cb3663cd744027ad98d970d620e05bf6c48f230fa45bf17527fe726fdf705419bb7a1bb913e +84b97b1e6408b6791831997b03cd91f027e7660fd492a93d95daafe61f02427371c0e237c75706412f442991dfdff989 +ab761c26527439b209af0ae6afccd9340bbed5fbe098734c3145b76c5d2cd7115d9227b2eb523882b7317fbb09180498 +a0479a8da06d7a69c0b0fee60df4e691c19c551f5e7da286dab430bfbcabf31726508e20d26ea48c53365a7f00a3ad34 +a732dfc9baa0f4f40b5756d2e8d8937742999623477458e0bc81431a7b633eefc6f53b3b7939fe0a020018549c954054 +901502436a1169ba51dc479a5abe7c8d84e0943b16bc3c6a627b49b92cd46263c0005bc324c67509edd693f28e612af1 +b627aee83474e7f84d1bab9b7f6b605e33b26297ac6bbf52d110d38ba10749032bd551641e73a383a303882367af429b +95108866745760baef4a46ef56f82da6de7e81c58b10126ebd2ba2cd13d339f91303bf2fb4dd104a6956aa3b13739503 +899ed2ade37236cec90056f3569bc50f984f2247792defafcceb49ad0ca5f6f8a2f06573705300e07f0de0c759289ff5 +a9f5eee196d608efe4bcef9bf71c646d27feb615e21252cf839a44a49fd89da8d26a758419e0085a05b1d59600e2dc42 +b36c6f68fed6e6c85f1f4a162485f24817f2843ec5cbee45a1ebfa367d44892e464949c6669f7972dc7167af08d55d25 +aaaede243a9a1b6162afbc8f571a52671a5a4519b4062e3f26777664e245ba873ed13b0492c5dbf0258c788c397a0e9e +972b4fb39c31cbe127bf9a32a5cc10d621ebdd9411df5e5da3d457f03b2ab2cd1f6372d8284a4a9400f0b06ecdbfd38e +8f6ca1e110e959a4b1d9a5ce5f212893cec21db40d64d5ac4d524f352d72198f923416a850bf845bc5a22a79c0ea2619 +a0f3c93b22134f66f04b2553a53b738644d1665ceb196b8494b315a4c28236fb492017e4a0de4224827c78e42f9908b7 +807fb5ee74f6c8735b0b5ca07e28506214fe4047dbeb00045d7c24f7849e98706aea79771241224939cb749cf1366c7d +915eb1ff034224c0b645442cdb7d669303fdc00ca464f91aaf0b6fde0b220a3a74ff0cb043c26c9f3a5667b3fdaa9420 +8fda6cef56ed33fefffa9e6ac8e6f76b1af379f89761945c63dd448801f7bb8ca970504a7105fac2f74f652ccff32327 +87380cffdcffb1d0820fa36b63cc081e72187f86d487315177d4d04da4533eb19a0e2ff6115ceab528887819c44a5164 +8cd89e03411a18e7f16f968b89fb500c36d47d229f6487b99e62403a980058db5925ce249206743333538adfad168330 +974451b1df33522ce7056de9f03e10c70bf302c44b0741a59df3d6877d53d61a7394dcee1dd46e013d7cb9d73419c092 +98c35ddf645940260c490f384a49496a7352bb8e3f686feed815b1d38f59ded17b1ad6e84a209e773ed08f7b8ff1e4c2 +963f386cf944bb9b2ddebb97171b64253ea0a2894ac40049bdd86cda392292315f3a3d490ca5d9628c890cfb669f0acb +8d507712152babd6d142ee682638da8495a6f3838136088df9424ef50d5ec28d815a198c9a4963610b22e49b4cdf95e9 +83d4bc6b0be87c8a4f1e9c53f257719de0c73d85b490a41f7420e777311640937320557ff2f1d9bafd1daaa54f932356 +82f5381c965b7a0718441131c4d13999f4cdce637698989a17ed97c8ea2e5bdb5d07719c5f7be8688edb081b23ede0f4 +a6ebecab0b72a49dfd01d69fa37a7f74d34fb1d4fef0aa10e3d6fceb9eccd671225c230af89f6eb514250e41a5f91f52 +846d185bdad6e11e604df7f753b7a08a28b643674221f0e750ebdb6b86ec584a29c869e131bca868972a507e61403f6a +85a98332292acb744bd1c0fd6fdcf1f889a78a2c9624d79413ffa194cc8dfa7821a4b60cde8081d4b5f71f51168dd67f +8f7d97c3b4597880d73200d074eb813d95432306e82dafc70b580b8e08cb8098b70f2d07b4b3ac6a4d77e92d57035031 +8185439c8751e595825d7053518cbe121f191846a38d4dbcb558c3f9d7a3104f3153401adaaaf27843bbe2edb504bfe3 +b3c00d8ece1518fca6b1215a139b0a0e26d9cba1b3a424f7ee59f30ce800a5db967279ed60958dd1f3ee69cf4dd1b204 +a2e6cb6978e883f9719c3c0d44cfe8de0cc6f644b98f98858433bea8bbe7b612c8aca5952fccce4f195f9d54f9722dc2 +99663087e3d5000abbec0fbda4e7342ec38846cc6a1505191fb3f1a337cb369455b7f8531a6eb8b0f7b2c4baf83cbe2b +ab0836c6377a4dbc7ca6a4d6cf021d4cd60013877314dd05f351706b128d4af6337711ed3443cb6ca976f40d74070a9a +87abfd5126152fd3bac3c56230579b489436755ea89e0566aa349490b36a5d7b85028e9fb0710907042bcde6a6f5d7e3 +974ba1033f75f60e0cf7c718a57ae1da3721cf9d0fb925714c46f027632bdd84cd9e6de4cf4d00bc55465b1c5ebb7384 +a607b49d73689ac64f25cec71221d30d53e781e1100d19a2114a21da6507a60166166369d860bd314acb226596525670 +a7c2b0b915d7beba94954f2aa7dd08ec075813661e2a3ecca5d28a0733e59583247fed9528eb28aba55b972cdbaf06eb +b8b3123e44128cc8efbe3270f2f94e50ca214a4294c71c3b851f8cbb70cb67fe9536cf07d04bf7fe380e5e3a29dd3c15 +a59a07e343b62ad6445a0859a32b58c21a593f9ddbfe52049650f59628c93715aa1f4e1f45b109321756d0eeec8a5429 +94f51f8a4ed18a6030d0aaa8899056744bd0e9dc9ac68f62b00355cddab11da5da16798db75f0bfbce0e5bdfe750c0b6 +97460a97ca1e1fa5ce243b81425edc0ec19b7448e93f0b55bc9785eedeeafe194a3c8b33a61a5c72990edf375f122777 +8fa859a089bc17d698a7ee381f37ce9beadf4e5b44fce5f6f29762bc04f96faff5d58c48c73631290325f05e9a1ecf49 +abdf38f3b20fc95eff31de5aa9ef1031abfa48f1305ee57e4d507594570401503476d3bcc493838fc24d6967a3082c7f +b8914bfb82815abb86da35c64d39ab838581bc0bf08967192697d9663877825f2b9d6fbdcf9b410463482b3731361aef +a8187f9d22b193a5f578999954d6ec9aa9b32338ccadb8a3e1ce5bad5ea361d69016e1cdfac44e9d6c54e49dd88561b9 +aac262cb7cba7fd62c14daa7b39677cabc1ef0947dd06dd89cac8570006a200f90d5f0353e84f5ff03179e3bebe14231 +a630ef5ece9733b8c46c0a2df14a0f37647a85e69c63148e79ffdcc145707053f9f9d305c3f1cf3c7915cb46d33abd07 +b102c237cb2e254588b6d53350dfda6901bd99493a3fbddb4121d45e0b475cf2663a40d7b9a75325eda83e4ba1e68cb3 +86a930dd1ddcc16d1dfa00aa292cb6c2607d42c367e470aa920964b7c17ab6232a7108d1c2c11fc40fb7496547d0bbf8 +a832fdc4500683e72a96cce61e62ac9ee812c37fe03527ad4cf893915ca1962cee80e72d4f82b20c8fc0b764376635a1 +88ad985f448dabb04f8808efd90f273f11f5e6d0468b5489a1a6a3d77de342992a73eb842d419034968d733f101ff683 +98a8538145f0d86f7fbf9a81c9140f6095c5bdd8960b1c6f3a1716428cd9cca1bf8322e6d0af24e6169abcf7df2b0ff6 +9048c6eba5e062519011e177e955a200b2c00b3a0b8615bdecdebc217559d41058d3315f6d05617be531ef0f6aef0e51 +833bf225ab6fc68cdcacf1ec1b50f9d05f5410e6cdcd8d56a3081dc2be8a8d07b81534d1ec93a25c2e270313dfb99e3b +a84bcd24c3da5e537e64a811b93c91bfc84d7729b9ead7f79078989a6eb76717d620c1fad17466a0519208651e92f5ff +b7cdd0a3fbd79aed93e1b5a44ca44a94e7af5ed911e4492f332e3a5ed146c7286bde01b52276a2fcc02780d2109874dd +8a19a09854e627cb95750d83c20c67442b66b35896a476358f993ba9ac114d32c59c1b3d0b8787ee3224cf3888b56c64 +a9abd5afb8659ee52ada8fa5d57e7dd355f0a7350276f6160bec5fbf70d5f99234dd179eb221c913e22a49ec6d267846 +8c13c4274c0d30d184e73eaf812200094bbbd57293780bdadbceb262e34dee5b453991e7f37c7333a654fc71c69d6445 +a4320d73296ff8176ce0127ca1921c450e2a9c06eff936681ebaffb5a0b05b17fded24e548454de89aca2dcf6d7a9de4 +b2b8b3e15c1f645f07783e5628aba614e60157889db41d8161d977606788842b67f83f361eae91815dc0abd84e09abd5 +ad26c3aa35ddfddc15719b8bb6c264aaec7065e88ac29ba820eb61f220fef451609a7bb037f3722d022e6c86e4f1dc88 +b8615bf43e13ae5d7b8dd903ce37190800cd490f441c09b22aa29d7a29ed2c0417b7a08ead417868f1de2589deaadd80 +8d3425e1482cd1e76750a76239d33c06b3554c3c3c87c15cb7ab58b1cee86a4c5c4178b44e23f36928365a1b484bde02 +806893a62e38c941a7dd6f249c83af16596f69877cc737d8f73f6b8cd93cbc01177a7a276b2b8c6b0e5f2ad864db5994 +86618f17fa4b0d65496b661bbb5ba3bc3a87129d30a4b7d4f515b904f4206ca5253a41f49fd52095861e5e065ec54f21 +9551915da1304051e55717f4c31db761dcdcf3a1366c89a4af800a9e99aca93a357bf928307f098e62b44a02cb689a46 +8f79c4ec0ec1146cb2a523b52fe33def90d7b5652a0cb9c2d1c8808a32293e00aec6969f5b1538e3a94cd1efa3937f86 +a0c03e329a707300081780f1e310671315b4c6a4cedcb29697aedfabb07a9d5df83f27b20e9c44cf6b16e39d9ded5b98 +86a7cfa7c8e7ce2c01dd0baec2139e97e8e090ad4e7b5f51518f83d564765003c65968f85481bbb97cb18f005ccc7d9f +a33811770c6dfda3f7f74e6ad0107a187fe622d61b444bbd84fd7ef6e03302e693b093df76f6ab39bb4e02afd84a575a +85480f5c10d4162a8e6702b5e04f801874d572a62a130be94b0c02b58c3c59bdcd48cd05f0a1c2839f88f06b6e3cd337 +8e181011564b17f7d787fe0e7f3c87f6b62da9083c54c74fd6c357a1f464c123c1d3d8ade3cf72475000b464b14e2be3 +8ee178937294b8c991337e0621ab37e9ffa4ca2bdb3284065c5e9c08aad6785d50cf156270ff9daf9a9127289710f55b +8bd1e8e2d37379d4b172f1aec96f2e41a6e1393158d7a3dbd9a95c8dd4f8e0b05336a42efc11a732e5f22b47fc5c271d +8f3da353cd487c13136a85677de8cedf306faae0edec733cf4f0046f82fa4639db4745b0095ff33a9766aba50de0cbcf +8d187c1e97638df0e4792b78e8c23967dac43d98ea268ca4aabea4e0fa06cb93183fd92d4c9df74118d7cc27bf54415e +a4c992f08c2f8bac0b74b3702fb0c75c9838d2ce90b28812019553d47613c14d8ce514d15443159d700b218c5a312c49 +a6fd1874034a34c3ea962a316c018d9493d2b3719bb0ec4edbc7c56b240802b2228ab49bee6f04c8a3e9f6f24a48c1c2 +b2efed8e799f8a15999020900dc2c58ece5a3641c90811b86a5198e593d7318b9d53b167818ccdfbe7df2414c9c34011 +995ff7de6181ddf95e3ead746089c6148da3508e4e7a2323c81785718b754d356789b902e7e78e2edc6b0cbd4ff22c78 +944073d24750a9068cbd020b834afc72d2dde87efac04482b3287b40678ad07588519a4176b10f2172a2c463d063a5cd +99db4b1bb76475a6fd75289986ef40367960279524378cc917525fb6ba02a145a218c1e9caeb99332332ab486a125ac0 +89fce4ecd420f8e477af4353b16faabb39e063f3f3c98fde2858b1f2d1ef6eed46f0975a7c08f233b97899bf60ccd60a +8c09a4f07a02b80654798bc63aada39fd638d3e3c4236ccd8a5ca280350c31e4a89e5f4c9aafb34116e71da18c1226b8 +85325cfa7ded346cc51a2894257eab56e7488dbff504f10f99f4cd2b630d913003761a50f175ed167e8073f1b6b63fb0 +b678b4fbec09a8cc794dcbca185f133578f29e354e99c05f6d07ac323be20aecb11f781d12898168e86f2e0f09aca15e +a249cfcbca4d9ba0a13b5f6aac72bf9b899adf582f9746bb2ad043742b28915607467eb794fca3704278f9136f7642be +9438e036c836a990c5e17af3d78367a75b23c37f807228362b4d13e3ddcb9e431348a7b552d09d11a2e9680704a4514f +925ab70450af28c21a488bfb5d38ac994f784cf249d7fd9ad251bb7fd897a23e23d2528308c03415074d43330dc37ef4 +a290563904d5a8c0058fc8330120365bdd2ba1fdbaef7a14bc65d4961bb4217acfaed11ab82669e359531f8bf589b8db +a7e07a7801b871fc9b981a71e195a3b4ba6b6313bc132b04796a125157e78fe5c11a3a46cf731a255ac2d78a4ae78cd0 +b26cd2501ee72718b0eebab6fb24d955a71f363f36e0f6dff0ab1d2d7836dab88474c0cef43a2cc32701fca7e82f7df3 +a1dc3b6c968f3de00f11275092290afab65b2200afbcfa8ddc70e751fa19dbbc300445d6d479a81bda3880729007e496 +a9bc213e28b630889476a095947d323b9ac6461dea726f2dc9084473ae8e196d66fb792a21905ad4ec52a6d757863e7d +b25d178df8c2df8051e7c888e9fa677fde5922e602a95e966db9e4a3d6b23ce043d7dc48a5b375c6b7c78e966893e8c3 +a1c8d88d72303692eaa7adf68ea41de4febec40cc14ae551bb4012afd786d7b6444a3196b5d9d5040655a3366d96b7cd +b22bd44f9235a47118a9bbe2ba5a2ba9ec62476061be2e8e57806c1a17a02f9a51403e849e2e589520b759abd0117683 +b8add766050c0d69fe81d8d9ea73e1ed05f0135d093ff01debd7247e42dbb86ad950aceb3b50b9af6cdc14ab443b238f +af2cf95f30ef478f018cf81d70d47d742120b09193d8bb77f0d41a5d2e1a80bfb467793d9e2471b4e0ad0cb2c3b42271 +8af5ef2107ad284e246bb56e20fef2a255954f72de791cbdfd3be09f825298d8466064f3c98a50496c7277af32b5c0bc +85dc19558572844c2849e729395a0c125096476388bd1b14fa7f54a7c38008fc93e578da3aac6a52ff1504d6ca82db05 +ae8c9b43c49572e2e166d704caf5b4b621a3b47827bb2a3bcd71cdc599bba90396fd9a405261b13e831bb5d44c0827d7 +a7ba7efede25f02e88f6f4cbf70643e76784a03d97e0fbd5d9437c2485283ad7ca3abb638a5f826cd9f6193e5dec0b6c +94a9d122f2f06ef709fd8016fd4b712d88052245a65a301f5f177ce22992f74ad05552b1f1af4e70d1eac62cef309752 +82d999b3e7cf563833b8bc028ff63a6b26eb357dfdb3fd5f10e33a1f80a9b2cfa7814d871b32a7ebfbaa09e753e37c02 +aec6edcde234df502a3268dd2c26f4a36a2e0db730afa83173f9c78fcb2b2f75510a02b80194327b792811caefda2725 +94c0bfa66c9f91d462e9194144fdd12d96f9bbe745737e73bab8130607ee6ea9d740e2cfcbbd00a195746edb6369ee61 +ab7573dab8c9d46d339e3f491cb2826cabe8b49f85f1ede78d845fc3995537d1b4ab85140b7d0238d9c24daf0e5e2a7e +87e8b16832843251fe952dadfd01d41890ed4bb4b8fa0254550d92c8cced44368225eca83a6c3ad47a7f81ff8a80c984 +9189d2d9a7c64791b19c0773ad4f0564ce6bea94aa275a917f78ad987f150fdb3e5e26e7fef9982ac184897ecc04683f +b3661bf19e2da41415396ae4dd051a9272e8a2580b06f1a1118f57b901fa237616a9f8075af1129af4eabfefedbe2f1c +af43c86661fb15daf5d910a4e06837225e100fb5680bd3e4b10f79a2144c6ec48b1f8d6e6b98e067d36609a5d038889a +82ac0c7acaa83ddc86c5b4249aae12f28155989c7c6b91e5137a4ce05113c6cbc16f6c44948b0efd8665362d3162f16a +8f268d1195ab465beeeb112cd7ffd5d5548559a8bc01261106d3555533fc1971081b25558d884d552df0db1cddda89d8 +8ef7caa5521f3e037586ce8ac872a4182ee20c7921c0065ed9986c047e3dda08294da1165f385d008b40d500f07d895f +8c2f98f6880550573fad46075d3eba26634b5b025ce25a0b4d6e0193352c8a1f0661064027a70fe8190b522405f9f4e3 +b7653f353564feb164f0f89ec7949da475b8dad4a4d396d252fc2a884f6932d027b7eb2dc4d280702c74569319ed701a +a026904f4066333befd9b87a8fad791d014096af60cdd668ef919c24dbe295ff31f7a790e1e721ba40cf5105abca67f4 +988f982004ada07a22dd345f2412a228d7a96b9cae2c487de42e392afe1e35c2655f829ce07a14629148ce7079a1f142 +9616add009067ed135295fb74d5b223b006b312bf14663e547a0d306694ff3a8a7bb9cfc466986707192a26c0bce599f +ad4c425de9855f6968a17ee9ae5b15e0a5b596411388cf976df62ecc6c847a6e2ddb2cea792a5f6e9113c2445dba3e5c +b698ac9d86afa3dc69ff8375061f88e3b0cff92ff6dfe747cebaf142e813c011851e7a2830c10993b715e7fd594604a9 +a386fa189847bb3b798efca917461e38ead61a08b101948def0f82cd258b945ed4d45b53774b400af500670149e601b7 +905c95abda2c68a6559d8a39b6db081c68cef1e1b4be63498004e1b2f408409be9350b5b5d86a30fd443e2b3e445640a +9116dade969e7ce8954afcdd43e5cab64dc15f6c1b8da9d2d69de3f02ba79e6c4f6c7f54d6bf586d30256ae405cd1e41 +a3084d173eacd08c9b5084a196719b57e47a0179826fda73466758235d7ecdb87cbcf097bd6b510517d163a85a7c7edd +85bb00415ad3c9be99ff9ba83672cc59fdd24356b661ab93713a3c8eab34e125d8867f628a3c3891b8dc056e69cd0e83 +8d58541f9f39ed2ee4478acce5d58d124031338ec11b0d55551f00a5a9a6351faa903a5d7c132dc5e4bb026e9cbd18e4 +a622adf72dc250e54f672e14e128c700166168dbe0474cecb340da175346e89917c400677b1bc1c11fcc4cc26591d9db +b3f865014754b688ca8372e8448114fff87bf3ca99856ab9168894d0c4679782c1ced703f5b74e851b370630f5e6ee86 +a7e490b2c40c2446fcd91861c020da9742c326a81180e38110558bb5d9f2341f1c1885e79b364e6419023d1cbdc47380 +b3748d472b1062e54572badbb8e87ac36534407f74932e7fc5b8392d008e8e89758f1671d1e4d30ab0fa40551b13bb5e +89898a5c5ec4313aabc607b0049fd1ebad0e0c074920cf503c9275b564d91916c2c446d3096491c950b7af3ac5e4b0ed +8eb8c83fef2c9dd30ea44e286e9599ec5c20aba983f702e5438afe2e5b921884327ad8d1566c72395587efac79ca7d56 +b92479599e806516ce21fb0bd422a1d1d925335ebe2b4a0a7e044dd275f30985a72b97292477053ac5f00e081430da80 +a34ae450a324fe8a3c25a4d653a654f9580ed56bbea213b8096987bbad0f5701d809a17076435e18017fea4d69f414bc +81381afe6433d62faf62ea488f39675e0091835892ecc238e02acf1662669c6d3962a71a3db652f6fe3bc5f42a0e5dc5 +a430d475bf8580c59111103316fe1aa79c523ea12f1d47a976bbfae76894717c20220e31cf259f08e84a693da6688d70 +b842814c359754ece614deb7d184d679d05d16f18a14b288a401cef5dad2cf0d5ee90bad487b80923fc5573779d4e4e8 +971d9a2627ff2a6d0dcf2af3d895dfbafca28b1c09610c466e4e2bff2746f8369de7f40d65b70aed135fe1d72564aa88 +8f4ce1c59e22b1ce7a0664caaa7e53735b154cfba8d2c5cc4159f2385843de82ab58ed901be876c6f7fce69cb4130950 +86cc9dc321b6264297987000d344fa297ef45bcc2a4df04e458fe2d907ad304c0ea2318e32c3179af639a9a56f3263cf +8229e0876dfe8f665c3fb19b250bd89d40f039bbf1b331468b403655be7be2e104c2fd07b9983580c742d5462ca39a43 +99299d73066e8eb128f698e56a9f8506dfe4bd014931e86b6b487d6195d2198c6c5bf15cccb40ccf1f8ddb57e9da44a2 +a3a3be37ac554c574b393b2f33d0a32a116c1a7cfeaf88c54299a4da2267149a5ecca71f94e6c0ef6e2f472b802f5189 +a91700d1a00387502cdba98c90f75fbc4066fefe7cc221c8f0e660994c936badd7d2695893fde2260c8c11d5bdcdd951 +8e03cae725b7f9562c5c5ab6361644b976a68bada3d7ca508abca8dfc80a469975689af1fba1abcf21bc2a190dab397d +b01461ad23b2a8fa8a6d241e1675855d23bc977dbf4714add8c4b4b7469ccf2375cec20e80cedfe49361d1a30414ac5b +a2673bf9bc621e3892c3d7dd4f1a9497f369add8cbaa3472409f4f86bd21ac67cfac357604828adfee6ada1835365029 +a042dff4bf0dfc33c178ba1b335e798e6308915128de91b12e5dbbab7c4ac8d60a01f6aea028c3a6d87b9b01e4e74c01 +86339e8a75293e4b3ae66b5630d375736b6e6b6b05c5cda5e73fbf7b2f2bd34c18a1d6cefede08625ce3046e77905cb8 +af2ebe1b7d073d03e3d98bc61af83bf26f7a8c130fd607aa92b75db22d14d016481b8aa231e2c9757695f55b7224a27f +a00ee882c9685e978041fd74a2c465f06e2a42ffd3db659053519925be5b454d6f401e3c12c746e49d910e4c5c9c5e8c +978a781c0e4e264e0dad57e438f1097d447d891a1e2aa0d5928f79a9d5c3faae6f258bc94fdc530b7b2fa6a9932bb193 +aa4b7ce2e0c2c9e9655bf21e3e5651c8503bce27483017b0bf476be743ba06db10228b3a4c721219c0779747f11ca282 +b003d1c459dacbcf1a715551311e45d7dbca83a185a65748ac74d1800bbeaba37765d9f5a1a221805c571910b34ebca8 +95b6e531b38648049f0d19de09b881baa1f7ea3b2130816b006ad5703901a05da57467d1a3d9d2e7c73fb3f2e409363c +a6cf9c06593432d8eba23a4f131bb7f72b9bd51ab6b4b772a749fe03ed72b5ced835a349c6d9920dba2a39669cb7c684 +aa3d59f6e2e96fbb66195bc58c8704e139fa76cd15e4d61035470bd6e305db9f98bcbf61ac1b95e95b69ba330454c1b3 +b57f97959c208361de6d7e86dff2b873068adb0f158066e646f42ae90e650079798f165b5cd713141cd3a2a90a961d9a +a76ee8ed9052f6a7a8c69774bb2597be182942f08115baba03bf8faaeaee526feba86120039fe8ca7b9354c3b6e0a8e6 +95689d78c867724823f564627d22d25010f278674c6d2d0cdb10329169a47580818995d1d727ce46c38a1e47943ebb89 +ab676d2256c6288a88e044b3d9ffd43eb9d5aaee00e8fc60ac921395fb835044c71a26ca948e557fed770f52d711e057 +96351c72785c32e5d004b6f4a1259fb8153d631f0c93fed172f18e8ba438fbc5585c1618deeabd0d6d0b82173c2e6170 +93dd8d3db576418e22536eba45ab7f56967c6c97c64260d6cddf38fb19c88f2ec5cd0e0156f50e70855eee8a2b879ffd +ad6ff16f40f6de3d7a737f8e6cebd8416920c4ff89dbdcd75eabab414af9a6087f83ceb9aff7680aa86bff98bd09c8cc +84de53b11671abc9c38710e19540c5c403817562aeb22a88404cdaff792c1180f717dbdfe8f54940c062c4d032897429 +872231b9efa1cdd447b312099a5c164c560440a9441d904e70f5abfc3b2a0d16be9a01aca5e0a2599a61e19407587e3d +88f44ac27094a2aa14e9dc40b099ee6d68f97385950f303969d889ee93d4635e34dff9239103bdf66a4b7cbba3e7eb7a +a59afebadf0260e832f6f44468443562f53fbaf7bcb5e46e1462d3f328ac437ce56edbca617659ac9883f9e13261fad7 +b1990e42743a88de4deeacfd55fafeab3bc380cb95de43ed623d021a4f2353530bcab9594389c1844b1c5ea6634c4555 +85051e841149a10e83f56764e042182208591396d0ce78c762c4a413e6836906df67f38c69793e158d64fef111407ba3 +9778172bbd9b1f2ec6bbdd61829d7b39a7df494a818e31c654bf7f6a30139899c4822c1bf418dd4f923243067759ce63 +9355005b4878c87804fc966e7d24f3e4b02bed35b4a77369d01f25a3dcbff7621b08306b1ac85b76fe7b4a3eb5f839b1 +8f9dc6a54fac052e236f8f0e1f571ac4b5308a43acbe4cc8183bce26262ddaf7994e41cf3034a4cbeca2c505a151e3b1 +8cc59c17307111723fe313046a09e0e32ea0cce62c13814ab7c6408c142d6a0311d801be4af53fc9240523f12045f9ef +8e6057975ed40a1932e47dd3ac778f72ee2a868d8540271301b1aa6858de1a5450f596466494a3e0488be4fbeb41c840 +812145efbd6559ae13325d56a15940ca4253b17e72a9728986b563bb5acc13ec86453796506ac1a8f12bd6f9e4a288c3 +911da0a6d6489eb3dab2ec4a16e36127e8a291ae68a6c2c9de33e97f3a9b1f00da57a94e270a0de79ecc5ecb45d19e83 +b72ea85973f4b2a7e6e71962b0502024e979a73c18a9111130e158541fa47bbaaf53940c8f846913a517dc69982ba9e1 +a7a56ad1dbdc55f177a7ad1d0af78447dc2673291e34e8ab74b26e2e2e7d8c5fe5dc89e7ef60f04a9508847b5b3a8188 +b52503f6e5411db5d1e70f5fb72ccd6463fa0f197b3e51ca79c7b5a8ab2e894f0030476ada72534fa4eb4e06c3880f90 +b51c7957a3d18c4e38f6358f2237b3904618d58b1de5dec53387d25a63772e675a5b714ad35a38185409931157d4b529 +b86b4266e719d29c043d7ec091547aa6f65bbf2d8d831d1515957c5c06513b72aa82113e9645ad38a7bc3f5383504fa6 +b95b547357e6601667b0f5f61f261800a44c2879cf94e879def6a105b1ad2bbf1795c3b98a90d588388e81789bd02681 +a58fd4c5ae4673fa350da6777e13313d5d37ed1dafeeb8f4f171549765b84c895875d9d3ae6a9741f3d51006ef81d962 +9398dc348d078a604aadc154e6eef2c0be1a93bb93ba7fe8976edc2840a3a318941338cc4d5f743310e539d9b46613d2 +902c9f0095014c4a2f0dccaaab543debba6f4cc82c345a10aaf4e72511725dbed7a34cd393a5f4e48a3e5142b7be84ed +a7c0447849bb44d04a0393a680f6cd390093484a79a147dd238f5d878030d1c26646d88211108e59fe08b58ad20c6fbd +80db045535d6e67a422519f5c89699e37098449d249698a7cc173a26ccd06f60238ae6cc7242eb780a340705c906790c +8e52b451a299f30124505de2e74d5341e1b5597bdd13301cc39b05536c96e4380e7f1b5c7ef076f5b3005a868657f17c +824499e89701036037571761e977654d2760b8ce21f184f2879fda55d3cda1e7a95306b8abacf1caa79d3cc075b9d27f +9049b956b77f8453d2070607610b79db795588c0cec12943a0f5fe76f358dea81e4f57a4692112afda0e2c05c142b26f +81911647d818a4b5f4990bfd4bc13bf7be7b0059afcf1b6839333e8569cdb0172fd2945410d88879349f677abaed5eb3 +ad4048f19b8194ed45b6317d9492b71a89a66928353072659f5ce6c816d8f21e69b9d1817d793effe49ca1874daa1096 +8d22f7b2ddb31458661abd34b65819a374a1f68c01fc6c9887edeba8b80c65bceadb8f57a3eb686374004b836261ef67 +92637280c259bc6842884db3d6e32602a62252811ae9b019b3c1df664e8809ffe86db88cfdeb8af9f46435c9ee790267 +a2f416379e52e3f5edc21641ea73dc76c99f7e29ea75b487e18bd233856f4c0183429f378d2bfc6cd736d29d6cadfa49 +882cb6b76dbdc188615dcf1a8439eba05ffca637dd25197508156e03c930b17b9fed2938506fdd7b77567cb488f96222 +b68b621bb198a763fb0634eddb93ed4b5156e59b96c88ca2246fd1aea3e6b77ed651e112ac41b30cd361fadc011d385e +a3cb22f6b675a29b2d1f827cacd30df14d463c93c3502ef965166f20d046af7f9ab7b2586a9c64f4eae4fad2d808a164 +8302d9ce4403f48ca217079762ce42cee8bc30168686bb8d3a945fbd5acd53b39f028dce757b825eb63af2d5ae41169d +b2eef1fbd1a176f1f4cd10f2988c7329abe4eb16c7405099fb92baa724ab397bc98734ef7d4b24c0f53dd90f57520d04 +a1bbef0bd684a3f0364a66bde9b29326bac7aa3dde4caed67f14fb84fed3de45c55e406702f1495a3e2864d4ee975030 +976acdb0efb73e3a3b65633197692dedc2adaed674291ae3df76b827fc866d214e9cac9ca46baefc4405ff13f953d936 +b9fbf71cc7b6690f601f0b1c74a19b7d14254183a2daaafec7dc3830cba5ae173d854bbfebeca985d1d908abe5ef0cda +90591d7b483598c94e38969c4dbb92710a1a894bcf147807f1bcbd8aa3ac210b9f2be65519aa829f8e1ccdc83ad9b8cf +a30568577c91866b9c40f0719d46b7b3b2e0b4a95e56196ac80898a2d89cc67880e1229933f2cd28ee3286f8d03414d7 +97589a88c3850556b359ec5e891f0937f922a751ac7c95949d3bbc7058c172c387611c0f4cb06351ef02e5178b3dd9e4 +98e7bbe27a1711f4545df742f17e3233fbcc63659d7419e1ca633f104cb02a32c84f2fac23ca2b84145c2672f68077ab +a7ddb91636e4506d8b7e92aa9f4720491bb71a72dadc47c7f4410e15f93e43d07d2b371951a0e6a18d1bd087aa96a5c4 +a7c006692227a06db40bceac3d5b1daae60b5692dd9b54772bedb5fea0bcc91cbcdb530cac31900ffc70c5b3ffadc969 +8d3ec6032778420dfa8be52066ba0e623467df33e4e1901dbadd586c5d750f4ccde499b5197e26b9ea43931214060f69 +8d9a8410518ea64f89df319bfd1fc97a0971cdb9ad9b11d1f8fe834042ea7f8dce4db56eeaf179ff8dda93b6db93e5ce +a3c533e9b3aa04df20b9ff635cb1154ce303e045278fcf3f10f609064a5445552a1f93989c52ce852fd0bbd6e2b6c22e +81934f3a7f8c1ae60ec6e4f212986bcc316118c760a74155d06ce0a8c00a9b9669ec4e143ca214e1b995e41271774fd9 +ab8e2d01a71192093ef8fafa7485e795567cc9db95a93fb7cc4cf63a391ef89af5e2bfad4b827fffe02b89271300407f +83064a1eaa937a84e392226f1a60b7cfad4efaa802f66de5df7498962f7b2649924f63cd9962d47906380b97b9fe80e1 +b4f5e64a15c6672e4b55417ee5dc292dcf93d7ea99965a888b1cc4f5474a11e5b6520eacbcf066840b343f4ceeb6bf33 +a63d278b842456ef15c278b37a6ea0f27c7b3ffffefca77c7a66d2ea06c33c4631eb242bbb064d730e70a8262a7b848a +83a41a83dbcdf0d22dc049de082296204e848c453c5ab1ba75aa4067984e053acf6f8b6909a2e1f0009ed051a828a73b +819485b036b7958508f15f3c19436da069cbe635b0318ebe8c014cf1ef9ab2df038c81161b7027475bcfa6fff8dd9faf +aa40e38172806e1e045e167f3d1677ef12d5dcdc89b43639a170f68054bd196c4fae34c675c1644d198907a03f76ba57 +969bae484883a9ed1fbed53b26b3d4ee4b0e39a6c93ece5b3a49daa01444a1c25727dabe62518546f36b047b311b177c +80a9e73a65da99664988b238096a090d313a0ee8e4235bc102fa79bb337b51bb08c4507814eb5baec22103ec512eaab0 +86604379aec5bddda6cbe3ef99c0ac3a3c285b0b1a15b50451c7242cd42ae6b6c8acb717dcca7917838432df93a28502 +a23407ee02a495bed06aa7e15f94cfb05c83e6d6fba64456a9bbabfa76b2b68c5c47de00ba169e710681f6a29bb41a22 +98cff5ecc73b366c6a01b34ac9066cb34f7eeaf4f38a5429bad2d07e84a237047e2a065c7e8a0a6581017dadb4695deb +8de9f68a938f441f3b7ab84bb1f473c5f9e5c9e139e42b7ccee1d254bd57d0e99c2ccda0f3198f1fc5737f6023dd204e +b0ce48d815c2768fb472a315cad86aa033d0e9ca506f146656e2941829e0acb735590b4fbc713c2d18d3676db0a954ac +82f485cdefd5642a6af58ac6817991c49fac9c10ace60f90b27f1788cc026c2fe8afc83cf499b3444118f9f0103598a8 +82c24550ed512a0d53fc56f64cc36b553823ae8766d75d772dacf038c460f16f108f87a39ceef7c66389790f799dbab3 +859ffcf1fe9166388316149b9acc35694c0ea534d43f09dae9b86f4aa00a23b27144dda6a352e74b9516e8c8d6fc809c +b8f7f353eec45da77fb27742405e5ad08d95ec0f5b6842025be9def3d9892f85eb5dd0921b41e6eff373618dba215bca +8ccca4436f9017e426229290f5cd05eac3f16571a4713141a7461acfe8ae99cd5a95bf5b6df129148693c533966145da +a2c67ecc19c0178b2994846fea4c34c327a5d786ac4b09d1d13549d5be5996d8a89021d63d65cb814923388f47cc3a03 +aa0ff87d676b418ec08f5cbf577ac7e744d1d0e9ebd14615b550eb86931eafd2a36d4732cc5d6fab1713fd7ab2f6f7c0 +8aef4730bb65e44efd6bb9441c0ae897363a2f3054867590a2c2ecf4f0224e578c7a67f10b40f8453d9f492ac15a9b2d +86a187e13d8fba5addcfdd5b0410cedd352016c930f913addd769ee09faa6be5ca3e4b1bdb417a965c643a99bd92be42 +a0a4e9632a7a094b14b29b78cd9c894218cdf6783e61671e0203865dc2a835350f465fbaf86168f28af7c478ca17bc89 +a8c7b02d8deff2cd657d8447689a9c5e2cd74ef57c1314ac4d69084ac24a7471954d9ff43fe0907d875dcb65fd0d3ce5 +97ded38760aa7be6b6960b5b50e83b618fe413cbf2bcc1da64c05140bcc32f5e0e709cd05bf8007949953fac5716bad9 +b0d293835a24d64c2ae48ce26e550b71a8c94a0883103757fb6b07e30747f1a871707d23389ba2b2065fa6bafe220095 +8f9e291bf849feaa575592e28e3c8d4b7283f733d41827262367ea1c40f298c7bcc16505255a906b62bf15d9f1ba85fb +998f4e2d12708b4fd85a61597ca2eddd750f73c9e0c9b3cf0825d8f8e01f1628fd19797dcaed3b16dc50331fc6b8b821 +b30d1f8c115d0e63bf48f595dd10908416774c78b3bbb3194192995154d80ea042d2e94d858de5f8aa0261b093c401fd +b5d9c75bb41f964cbff3f00e96d9f1480c91df8913f139f0d385d27a19f57a820f838eb728e46823cbff00e21c660996 +a6edec90b5d25350e2f5f0518777634f9e661ec9d30674cf5b156c4801746d62517751d90074830ac0f4b09911c262f1 +82f98da1264b6b75b8fbeb6a4d96d6a05b25c24db0d57ba3a38efe3a82d0d4e331b9fc4237d6494ccfe4727206457519 +b89511843453cf4ecd24669572d6371b1e529c8e284300c43e0d5bb6b3aaf35aeb634b3cb5c0a2868f0d5e959c1d0772 +a82bf065676583e5c1d3b81987aaae5542f522ba39538263a944bb33ea5b514c649344a96c0205a3b197a3f930fcda6c +a37b47ea527b7e06c460776aa662d9a49ff4149d3993f1a974b0dd165f7171770d189b0e2ea54fd5fccb6a14b116e68a +a1017677f97dda818274d47556d09d0e4ccacb23a252f82a6cfe78c630ad46fb9806307445a59fb61262182de3a2b29c +b01e9fcac239ba270e6877b79273ddd768bf8a51d2ed8a051b1c11e18eff3de5920e2fcbfbd26f06d381eddd3b1f1e1b +82fcd53d803b1c8e4ed76adc339b7f3a5962d37042b9683aabac7513ac68775d4a566a9460183926a6a95dbe7d551a1f +a763e78995d55cd21cdb7ef75d9642d6e1c72453945e346ab6690c20a4e1eeec61bb848ef830ae4b56182535e3c71d8f +b769f4db602251d4b0a1186782799bdcef66de33c110999a5775c50b349666ffd83d4c89714c4e376f2efe021a5cfdb2 +a59cbd1b785efcfa6e83fc3b1d8cf638820bc0c119726b5368f3fba9dce8e3414204fb1f1a88f6c1ff52e87961252f97 +95c8c458fd01aa23ecf120481a9c6332ebec2e8bb70a308d0576926a858457021c277958cf79017ddd86a56cacc2d7db +82eb41390800287ae56e77f2e87709de5b871c8bdb67c10a80fc65f3acb9f7c29e8fa43047436e8933f27449ea61d94d +b3ec25e3545eb83aed2a1f3558d1a31c7edde4be145ecc13b33802654b77dc049b4f0065069dd9047b051e52ab11dcdd +b78a0c715738f56f0dc459ab99e252e3b579b208142836b3c416b704ca1de640ca082f29ebbcee648c8c127df06f6b1e +a4083149432eaaf9520188ebf4607d09cf664acd1f471d4fb654476e77a9eaae2251424ffda78d09b6cb880df35c1219 +8c52857d68d6e9672df3db2df2dbf46b516a21a0e8a18eec09a6ae13c1ef8f369d03233320dd1c2c0bbe00abfc1ea18b +8c856089488803066bff3f8d8e09afb9baf20cecc33c8823c1c0836c3d45498c3de37e87c016b705207f60d2b00f8609 +831a3df39be959047b2aead06b4dcd3012d7b29417f642b83c9e8ce8de24a3dbbd29c6fdf55e2db3f7ea04636c94e403 +aed84d009f66544addabe404bf6d65af7779ce140dc561ff0c86a4078557b96b2053b7b8a43432ffb18cd814f143b9da +93282e4d72b0aa85212a77b336007d8ba071eea17492da19860f1ad16c1ea8867ccc27ef5c37c74b052465cc11ea4f52 +a7b78b8c8d057194e8d68767f1488363f77c77bddd56c3da2bc70b6354c7aa76247c86d51f7371aa38a4aa7f7e3c0bb7 +b1c77283d01dcd1bde649b5b044eac26befc98ff57cbee379fb5b8e420134a88f2fc7f0bf04d15e1fbd45d29e7590fe6 +a4aa8de70330a73b2c6458f20a1067eed4b3474829b36970a8df125d53bbdda4f4a2c60063b7cccb0c80fc155527652f +948a6c79ba1b8ad7e0bed2fae2f0481c4e41b4d9bbdd9b58164e28e9065700e83f210c8d5351d0212e0b0b68b345b3a5 +86a48c31dcbbf7b082c92d28e1f613a2378a910677d7db3a349dc089e4a1e24b12eee8e8206777a3a8c64748840b7387 +976adb1af21e0fc34148917cf43d933d7bfd3fd12ed6c37039dcd5a4520e3c6cf5868539ba5bf082326430deb8a4458d +b93e1a4476f2c51864bb4037e7145f0635eb2827ab91732b98d49b6c07f6ac443111aa1f1da76d1888665cb897c3834e +8afd46fb23bf869999fa19784b18a432a1f252d09506b8dbb756af900518d3f5f244989b3d7c823d9029218c655d3dc6 +83f1e59e3abeed18cdc632921672673f1cb6e330326e11c4e600e13e0d5bc11bdc970ae12952e15103a706fe720bf4d6 +90ce4cc660714b0b673d48010641c09c00fc92a2c596208f65c46073d7f349dd8e6e077ba7dcef9403084971c3295b76 +8b09b0f431a7c796561ecf1549b85048564de428dac0474522e9558b6065fede231886bc108539c104ce88ebd9b5d1b0 +85d6e742e2fb16a7b0ba0df64bc2c0dbff9549be691f46a6669bca05e89c884af16822b85faefefb604ec48c8705a309 +a87989ee231e468a712c66513746fcf03c14f103aadca0eac28e9732487deb56d7532e407953ab87a4bf8961588ef7b0 +b00da10efe1c29ee03c9d37d5918e391ae30e48304e294696b81b434f65cf8c8b95b9d1758c64c25e534d045ba28696f +91c0e1fb49afe46c7056400baa06dbb5f6e479db78ee37e2d76c1f4e88994357e257b83b78624c4ef6091a6c0eb8254d +883fb797c498297ccbf9411a3e727c3614af4eccde41619b773dc7f3259950835ee79453debf178e11dec4d3ada687a0 +a14703347e44eb5059070b2759297fcfcfc60e6893c0373eea069388eba3950aa06f1c57cd2c30984a2d6f9e9c92c79e +afebc7585b304ceba9a769634adff35940e89cd32682c78002822aab25eec3edc29342b7f5a42a56a1fec67821172ad5 +aea3ff3822d09dba1425084ca95fd359718d856f6c133c5fabe2b2eed8303b6e0ba0d8698b48b93136a673baac174fd9 +af2456a09aa777d9e67aa6c7c49a1845ea5cdda2e39f4c935c34a5f8280d69d4eec570446998cbbe31ede69a91e90b06 +82cada19fed16b891ef3442bafd49e1f07c00c2f57b2492dd4ee36af2bd6fd877d6cb41188a4d6ce9ec8d48e8133d697 +82a21034c832287f616619a37c122cee265cc34ae75e881fcaea4ea7f689f3c2bc8150bbf7dbcfd123522bfb7f7b1d68 +86877217105f5d0ec3eeff0289fc2a70d505c9fdf7862e8159553ef60908fb1a27bdaf899381356a4ef4649072a9796c +82b196e49c6e861089a427c0b4671d464e9d15555ffb90954cd0d630d7ae02eb3d98ceb529d00719c2526cd96481355a +a29b41d0d43d26ce76d4358e0db2b77df11f56e389f3b084d8af70a636218bd3ac86b36a9fe46ec9058c26a490f887f7 +a4311c4c20c4d7dd943765099c50f2fd423e203ccfe98ff00087d205467a7873762510cac5fdce7a308913ed07991ed7 +b1f040fc5cc51550cb2c25cf1fd418ecdd961635a11f365515f0cb4ffb31da71f48128c233e9cc7c0cf3978d757ec84e +a9ebae46f86d3bd543c5f207ed0d1aed94b8375dc991161d7a271f01592912072e083e2daf30c146430894e37325a1b9 +826418c8e17ad902b5fe88736323a47e0ca7a44bce4cbe27846ec8fe81de1e8942455dda6d30e192cdcc73e11df31256 +85199db563427c5edcbac21f3d39fec2357be91fb571982ddcdc4646b446ad5ced84410de008cb47b3477ee0d532daf8 +b7eed9cd400b2ca12bf1d9ae008214b8561fb09c8ad9ff959e626ffde00fee5ff2f5b6612e231f2a1a9b1646fcc575e3 +8b40bf12501dcbac78f5a314941326bfcddf7907c83d8d887d0bb149207f85d80cd4dfbd7935439ea7b14ea39a3fded7 +83e3041af302485399ba6cd5120e17af61043977083887e8d26b15feec4a6b11171ac5c06e6ad0971d4b58a81ff12af3 +8f5b9a0eecc589dbf8c35a65d5e996a659277ef6ea509739c0cb7b3e2da9895e8c8012de662e5b23c5fa85d4a8f48904 +835d71ed5e919d89d8e6455f234f3ff215462c4e3720c371ac8c75e83b19dfe3ae15a81547e4dc1138e5f5997f413cc9 +8b7d2e4614716b1db18e9370176ea483e6abe8acdcc3dcdf5fb1f4d22ca55d652feebdccc171c6de38398d9f7bfdec7a +93eace72036fe57d019676a02acf3d224cf376f166658c1bf705db4f24295881d477d6fdd7916efcfceff8c7a063deda +b1ac460b3d516879a84bc886c54f020a9d799e7c49af3e4d7de5bf0d2793c852254c5d8fe5616147e6659512e5ccb012 +acd0947a35cb167a48bcd9667620464b54ac0e78f9316b4aa92dcaab5422d7a732087e52e1c827faa847c6b2fe6e7766 +94ac33d21c3d12ff762d32557860e911cd94d666609ddcc42161b9c16f28d24a526e8b10bb03137257a92cec25ae637d +832e02058b6b994eadd8702921486241f9a19e68ed1406dad545e000a491ae510f525ccf9d10a4bba91c68f2c53a0f58 +9471035d14f78ff8f463b9901dd476b587bb07225c351161915c2e9c6114c3c78a501379ab6fb4eb03194c457cbd22bf +ab64593e034c6241d357fcbc32d8ea5593445a5e7c24cac81ad12bd2ef01843d477a36dc1ba21dbe63b440750d72096a +9850f3b30045e927ad3ec4123a32ed2eb4c911f572b6abb79121873f91016f0d80268de8b12e2093a4904f6e6cab7642 +987212c36b4722fe2e54fa30c52b1e54474439f9f35ca6ad33c5130cd305b8b54b532dd80ffd2c274105f20ce6d79f6e +8b4d0c6abcb239b5ed47bef63bc17efe558a27462c8208fa652b056e9eae9665787cd1aee34fbb55beb045c8bfdb882b +a9f3483c6fee2fe41312d89dd4355d5b2193ac413258993805c5cbbf0a59221f879386d3e7a28e73014f10e65dd503d9 +a2225da3119b9b7c83d514b9f3aeb9a6d9e32d9cbf9309cbb971fd53c4b2c001d10d880a8ad8a7c281b21d85ceca0b7c +a050be52e54e676c151f7a54453bbb707232f849beab4f3bf504b4d620f59ed214409d7c2bd3000f3ff13184ccda1c35 +adbccf681e15b3edb6455a68d292b0a1d0f5a4cb135613f5e6db9943f02181341d5755875db6ee474e19ace1c0634a28 +8b6eff675632a6fad0111ec72aacc61c7387380eb87933fd1d098856387d418bd38e77d897e65d6fe35951d0627c550b +aabe2328ddf90989b15e409b91ef055cb02757d34987849ae6d60bef2c902bf8251ed21ab30acf39e500d1d511e90845 +92ba4eb1f796bc3d8b03515f65c045b66e2734c2da3fc507fdd9d6b5d1e19ab3893726816a32141db7a31099ca817d96 +8a98b3cf353138a1810beb60e946183803ef1d39ac4ea92f5a1e03060d35a4774a6e52b14ead54f6794d5f4022b8685c +909f8a5c13ec4a59b649ed3bee9f5d13b21d7f3e2636fd2bb3413c0646573fdf9243d63083356f12f5147545339fcd55 +9359d914d1267633141328ed0790d81c695fea3ddd2d406c0df3d81d0c64931cf316fe4d92f4353c99ff63e2aefc4e34 +b88302031681b54415fe8fbfa161c032ea345c6af63d2fb8ad97615103fd4d4281c5a9cae5b0794c4657b97571a81d3b +992c80192a519038082446b1fb947323005b275e25f2c14c33cc7269e0ec038581cc43705894f94bad62ae33a8b7f965 +a78253e3e3eece124bef84a0a8807ce76573509f6861d0b6f70d0aa35a30a123a9da5e01e84969708c40b0669eb70aa6 +8d5724de45270ca91c94792e8584e676547d7ac1ac816a6bb9982ee854eb5df071d20545cdfd3771cd40f90e5ba04c8e +825a6f586726c68d45f00ad0f5a4436523317939a47713f78fd4fe81cd74236fdac1b04ecd97c2d0267d6f4981d7beb1 +93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 +b5bfd7dd8cdeb128843bc287230af38926187075cbfbefa81009a2ce615ac53d2914e5870cb452d2afaaab24f3499f72185cbfee53492714734429b7b38608e23926c911cceceac9a36851477ba4c60b087041de621000edc98edada20c1def2 +b5337ba0ce5d37224290916e268e2060e5c14f3f9fc9e1ec3af5a958e7a0303122500ce18f1a4640bf66525bd10e763501fe986d86649d8d45143c08c3209db3411802c226e9fe9a55716ac4a0c14f9dcef9e70b2bb309553880dc5025eab3cc +b3c1dcdc1f62046c786f0b82242ef283e7ed8f5626f72542aa2c7a40f14d9094dd1ebdbd7457ffdcdac45fd7da7e16c51200b06d791e5e43e257e45efdf0bd5b06cd2333beca2a3a84354eb48662d83aef5ecf4e67658c851c10b13d8d87c874 +954d91c7688983382609fca9e211e461f488a5971fd4e40d7e2892037268eacdfd495cfa0a7ed6eb0eb11ac3ae6f651716757e7526abe1e06c64649d80996fd3105c20c4c94bc2b22d97045356fe9d791f21ea6428ac48db6f9e68e30d875280 +88a6b6bb26c51cf9812260795523973bb90ce80f6820b6c9048ab366f0fb96e48437a7f7cb62aedf64b11eb4dfefebb0147608793133d32003cb1f2dc47b13b5ff45f1bb1b2408ea45770a08dbfaec60961acb8119c47b139a13b8641e2c9487 +85cd7be9728bd925d12f47fb04b32d9fad7cab88788b559f053e69ca18e463113ecc8bbb6dbfb024835f901b3a957d3108d6770fb26d4c8be0a9a619f6e3a4bf15cbfd48e61593490885f6cee30e4300c5f9cf5e1c08e60a2d5b023ee94fcad0 +80477dba360f04399821a48ca388c0fa81102dd15687fea792ee8c1114e00d1bc4839ad37ac58900a118d863723acfbe08126ea883be87f50e4eabe3b5e72f5d9e041db8d9b186409fd4df4a7dde38c0e0a3b1ae29b098e5697e7f110b6b27e4 +b7a6aec08715a9f8672a2b8c367e407be37e59514ac19dd4f0942a68007bba3923df22da48702c63c0d6b3efd3c2d04e0fe042d8b5a54d562f9f33afc4865dcbcc16e99029e25925580e87920c399e710d438ac1ce3a6dc9b0d76c064a01f6f7 +ac1b001edcea02c8258aeffbf9203114c1c874ad88dae1184fadd7d94cd09053649efd0ca413400e6e9b5fa4eac33261000af88b6bd0d2abf877a4f0355d2fb4d6007adb181695201c5432e50b850b51b3969f893bddf82126c5a71b042b7686 +90043fda4de53fb364fab2c04be5296c215599105ecff0c12e4917c549257125775c29f2507124d15f56e30447f367db0596c33237242c02d83dfd058735f1e3c1ff99069af55773b6d51d32a68bf75763f59ec4ee7267932ae426522b8aaab6 +a8660ce853e9dc08271bf882e29cd53397d63b739584dda5263da4c7cc1878d0cf6f3e403557885f557e184700575fee016ee8542dec22c97befe1d10f414d22e84560741cdb3e74c30dda9b42eeaaf53e27822de2ee06e24e912bf764a9a533 +8fe3921a96d0d065e8aa8fce9aa42c8e1461ca0470688c137be89396dd05103606dab6cdd2a4591efd6addf72026c12e065da7be276dee27a7e30afa2bd81c18f1516e7f068f324d0bad9570b95f6bd02c727cd2343e26db0887c3e4e26dceda +8ae1ad97dcb9c192c9a3933541b40447d1dc4eebf380151440bbaae1e120cc5cdf1bcea55180b128d8e180e3af623815191d063cc0d7a47d55fb7687b9d87040bf7bc1a7546b07c61db5ccf1841372d7c2fe4a5431ffff829f3c2eb590b0b710 +8c2fa96870a88150f7876c931e2d3cc2adeaaaf5c73ef5fa1cf9dfa0991ae4819f9321af7e916e5057d87338e630a2f21242c29d76963cf26035b548d2a63d8ad7bd6efefa01c1df502cbdfdfe0334fb21ceb9f686887440f713bf17a89b8081 +b9aa98e2f02bb616e22ee5dd74c7d1049321ac9214d093a738159850a1dbcc7138cb8d26ce09d8296368fd5b291d74fa17ac7cc1b80840fdd4ee35e111501e3fa8485b508baecda7c1ab7bd703872b7d64a2a40b3210b6a70e8a6ffe0e5127e3 +9292db67f8771cdc86854a3f614a73805bf3012b48f1541e704ea4015d2b6b9c9aaed36419769c87c49f9e3165f03edb159c23b3a49c4390951f78e1d9b0ad997129b17cdb57ea1a6638794c0cca7d239f229e589c5ae4f9fe6979f7f8cba1d7 +91cd9e86550f230d128664f7312591fee6a84c34f5fc7aed557bcf986a409a6de722c4330453a305f06911d2728626e611acfdf81284f77f60a3a1595053a9479964fd713117e27c0222cc679674b03bc8001501aaf9b506196c56de29429b46 +a9516b73f605cc31b89c68b7675dc451e6364595243d235339437f556cf22d745d4250c1376182273be2d99e02c10eee047410a43eff634d051aeb784e76cb3605d8e079b9eb6ad1957dfdf77e1cd32ce4a573c9dfcc207ca65af6eb187f6c3d +a9667271f7d191935cc8ad59ef3ec50229945faea85bfdfb0d582090f524436b348aaa0183b16a6231c00332fdac2826125b8c857a2ed9ec66821cfe02b3a2279be2412441bc2e369b255eb98614e4be8490799c4df22f18d47d24ec70bba5f7 +a4371144d2aa44d70d3cb9789096d3aa411149a6f800cb46f506461ee8363c8724667974252f28aea61b6030c05930ac039c1ee64bb4bd56532a685cae182bf2ab935eee34718cffcb46cae214c77aaca11dbb1320faf23c47247db1da04d8dc +89a7eb441892260b7e81168c386899cd84ffc4a2c5cad2eae0d1ab9e8b5524662e6f660fe3f8bfe4c92f60b060811bc605b14c5631d16709266886d7885a5eb5930097127ec6fb2ebbaf2df65909cf48f253b3d5e22ae48d3e9a2fd2b01f447e +9648c42ca97665b5eccb49580d8532df05eb5a68db07f391a2340769b55119eaf4c52fe4f650c09250fa78a76c3a1e271799b8333cc2628e3d4b4a6a3e03da1f771ecf6516dd63236574a7864ff07e319a6f11f153406280d63af9e2b5713283 +9663bf6dd446ea7a90658ee458578d4196dc0b175ef7fcfa75f44d41670850774c2e46c5a6be132a2c072a3c0180a24f0305d1acac49d2d79878e5cda80c57feda3d01a6af12e78b5874e2a4b3717f11c97503b41a4474e2e95b179113726199 +b212aeb4814e0915b432711b317923ed2b09e076aaf558c3ae8ef83f9e15a83f9ea3f47805b2750ab9e8106cb4dc6ad003522c84b03dc02829978a097899c773f6fb31f7fe6b8f2d836d96580f216fec20158f1590c3e0d7850622e15194db05 +925f005059bf07e9ceccbe66c711b048e236ade775720d0fe479aebe6e23e8af281225ad18e62458dc1b03b42ad4ca290d4aa176260604a7aad0d9791337006fbdebe23746f8060d42876f45e4c83c3643931392fde1cd13ff8bddf8111ef974 +9553edb22b4330c568e156a59ef03b26f5c326424f830fe3e8c0b602f08c124730ffc40bc745bec1a22417adb22a1a960243a10565c2be3066bfdb841d1cd14c624cd06e0008f4beb83f972ce6182a303bee3fcbcabc6cfe48ec5ae4b7941bfc +935f5a404f0a78bdcce709899eda0631169b366a669e9b58eacbbd86d7b5016d044b8dfc59ce7ed8de743ae16c2343b50e2f925e88ba6319e33c3fc76b314043abad7813677b4615c8a97eb83cc79de4fedf6ccbcfa4d4cbf759a5a84e4d9742 +a5b014ab936eb4be113204490e8b61cd38d71da0dec7215125bcd131bf3ab22d0a32ce645bca93e7b3637cf0c2db3d6601a0ddd330dc46f9fae82abe864ffc12d656c88eb50c20782e5bb6f75d18760666f43943abb644b881639083e122f557 +935b7298ae52862fa22bf03bfc1795b34c70b181679ae27de08a9f5b4b884f824ef1b276b7600efa0d2f1d79e4a470d51692fd565c5cf8343dd80e5d3336968fc21c09ba9348590f6206d4424eb229e767547daefa98bc3aa9f421158dee3f2a +9830f92446e708a8f6b091cc3c38b653505414f8b6507504010a96ffda3bcf763d5331eb749301e2a1437f00e2415efb01b799ad4c03f4b02de077569626255ac1165f96ea408915d4cf7955047620da573e5c439671d1fa5c833fb11de7afe6 +840dcc44f673fff3e387af2bb41e89640f2a70bcd2b92544876daa92143f67c7512faf5f90a04b7191de01f3e2b1bde00622a20dc62ca23bbbfaa6ad220613deff43908382642d4d6a86999f662efd64b1df448b68c847cfa87630a3ffd2ec76 +92950c895ed54f7f876b2fda17ecc9c41b7accfbdd42c210cc5b475e0737a7279f558148531b5c916e310604a1de25a80940c94fe5389ae5d6a5e9c371be67bceea1877f5401725a6595bcf77ece60905151b6dfcb68b75ed2e708c73632f4fd +8010246bf8e94c25fd029b346b5fbadb404ef6f44a58fd9dd75acf62433d8cc6db66974f139a76e0c26dddc1f329a88214dbb63276516cf325c7869e855d07e0852d622c332ac55609ba1ec9258c45746a2aeb1af0800141ee011da80af175d4 +b0f1bad257ebd187bdc3f37b23f33c6a5d6a8e1f2de586080d6ada19087b0e2bf23b79c1b6da1ee82271323f5bdf3e1b018586b54a5b92ab6a1a16bb3315190a3584a05e6c37d5ca1e05d702b9869e27f513472bcdd00f4d0502a107773097da +9636d24f1ede773ce919f309448dd7ce023f424afd6b4b69cb98c2a988d849a283646dc3e469879daa1b1edae91ae41f009887518e7eb5578f88469321117303cd3ac2d7aee4d9cb5f82ab9ae3458e796dfe7c24284b05815acfcaa270ff22e2 +b373feb5d7012fd60578d7d00834c5c81df2a23d42794fed91aa9535a4771fde0341c4da882261785e0caca40bf83405143085e7f17e55b64f6c5c809680c20b050409bf3702c574769127c854d27388b144b05624a0e24a1cbcc4d08467005b +b15680648949ce69f82526e9b67d9b55ce5c537dc6ab7f3089091a9a19a6b90df7656794f6edc87fb387d21573ffc847062623685931c2790a508cbc8c6b231dd2c34f4d37d4706237b1407673605a604bcf6a50cc0b1a2db20485e22b02c17e +8817e46672d40c8f748081567b038a3165f87994788ec77ee8daea8587f5540df3422f9e120e94339be67f186f50952504cb44f61e30a5241f1827e501b2de53c4c64473bcc79ab887dd277f282fbfe47997a930dd140ac08b03efac88d81075 +a6e4ef6c1d1098f95aae119905f87eb49b909d17f9c41bcfe51127aa25fee20782ea884a7fdf7d5e9c245b5a5b32230b07e0dbf7c6743bf52ee20e2acc0b269422bd6cf3c07115df4aa85b11b2c16630a07c974492d9cdd0ec325a3fabd95044 +8634aa7c3d00e7f17150009698ce440d8e1b0f13042b624a722ace68ead870c3d2212fbee549a2c190e384d7d6ac37ce14ab962c299ea1218ef1b1489c98906c91323b94c587f1d205a6edd5e9d05b42d591c26494a6f6a029a2aadb5f8b6f67 +821a58092900bdb73decf48e13e7a5012a3f88b06288a97b855ef51306406e7d867d613d9ec738ebacfa6db344b677d21509d93f3b55c2ebf3a2f2a6356f875150554c6fff52e62e3e46f7859be971bf7dd9d5b3e1d799749c8a97c2e04325df +8dba356577a3a388f782e90edb1a7f3619759f4de314ad5d95c7cc6e197211446819c4955f99c5fc67f79450d2934e3c09adefc91b724887e005c5190362245eec48ce117d0a94d6fa6db12eda4ba8dde608fbbd0051f54dcf3bb057adfb2493 +a32a690dc95c23ed9fb46443d9b7d4c2e27053a7fcc216d2b0020a8cf279729c46114d2cda5772fd60a97016a07d6c5a0a7eb085a18307d34194596f5b541cdf01b2ceb31d62d6b55515acfd2b9eec92b27d082fbc4dc59fc63b551eccdb8468 +a040f7f4be67eaf0a1d658a3175d65df21a7dbde99bfa893469b9b43b9d150fc2e333148b1cb88cfd0447d88fa1a501d126987e9fdccb2852ecf1ba907c2ca3d6f97b055e354a9789854a64ecc8c2e928382cf09dda9abde42bbdf92280cdd96 +864baff97fa60164f91f334e0c9be00a152a416556b462f96d7c43b59fe1ebaff42f0471d0bf264976f8aa6431176eb905bd875024cf4f76c13a70bede51dc3e47e10b9d5652d30d2663b3af3f08d5d11b9709a0321aba371d2ef13174dcfcaf +95a46f32c994133ecc22db49bad2c36a281d6b574c83cfee6680b8c8100466ca034b815cfaedfbf54f4e75188e661df901abd089524e1e0eb0bf48d48caa9dd97482d2e8c1253e7e8ac250a32fd066d5b5cb08a8641bdd64ecfa48289dca83a3 +a2cce2be4d12144138cb91066e0cd0542c80b478bf467867ebef9ddaf3bd64e918294043500bf5a9f45ee089a8d6ace917108d9ce9e4f41e7e860cbce19ac52e791db3b6dde1c4b0367377b581f999f340e1d6814d724edc94cb07f9c4730774 +b145f203eee1ac0a1a1731113ffa7a8b0b694ef2312dabc4d431660f5e0645ef5838e3e624cfe1228cfa248d48b5760501f93e6ab13d3159fc241427116c4b90359599a4cb0a86d0bb9190aa7fabff482c812db966fd2ce0a1b48cb8ac8b3bca +adabe5d215c608696e03861cbd5f7401869c756b3a5aadc55f41745ad9478145d44393fec8bb6dfc4ad9236dc62b9ada0f7ca57fe2bae1b71565dbf9536d33a68b8e2090b233422313cc96afc7f1f7e0907dc7787806671541d6de8ce47c4cd0 +ae7845fa6b06db53201c1080e01e629781817f421f28956589c6df3091ec33754f8a4bd4647a6bb1c141ac22731e3c1014865d13f3ed538dcb0f7b7576435133d9d03be655f8fbb4c9f7d83e06d1210aedd45128c2b0c9bab45a9ddde1c862a5 +9159eaa826a24adfa7adf6e8d2832120ebb6eccbeb3d0459ffdc338548813a2d239d22b26451fda98cc0c204d8e1ac69150b5498e0be3045300e789bcb4e210d5cd431da4bdd915a21f407ea296c20c96608ded0b70d07188e96e6c1a7b9b86b +a9fc6281e2d54b46458ef564ffaed6944bff71e389d0acc11fa35d3fcd8e10c1066e0dde5b9b6516f691bb478e81c6b20865281104dcb640e29dc116daae2e884f1fe6730d639dbe0e19a532be4fb337bf52ae8408446deb393d224eee7cfa50 +84291a42f991bfb36358eedead3699d9176a38f6f63757742fdbb7f631f2c70178b1aedef4912fed7b6cf27e88ddc7eb0e2a6aa4b999f3eb4b662b93f386c8d78e9ac9929e21f4c5e63b12991fcde93aa64a735b75b535e730ff8dd2abb16e04 +a1b7fcacae181495d91765dfddf26581e8e39421579c9cbd0dd27a40ea4c54af3444a36bf85a11dda2114246eaddbdd619397424bb1eb41b5a15004b902a590ede5742cd850cf312555be24d2df8becf48f5afba5a8cd087cb7be0a521728386 +92feaaf540dbd84719a4889a87cdd125b7e995a6782911931fef26da9afcfbe6f86aaf5328fe1f77631491ce6239c5470f44c7791506c6ef1626803a5794e76d2be0af92f7052c29ac6264b7b9b51f267ad820afc6f881460521428496c6a5f1 +a525c925bfae1b89320a5054acc1fa11820f73d0cf28d273092b305467b2831fab53b6daf75fb926f332782d50e2522a19edcd85be5eb72f1497193c952d8cd0bcc5d43b39363b206eae4cb1e61668bde28a3fb2fc1e0d3d113f6dfadb799717 +98752bb6f5a44213f40eda6aa4ff124057c1b13b6529ab42fe575b9afa66e59b9c0ed563fb20dff62130c436c3e905ee17dd8433ba02c445b1d67182ab6504a90bbe12c26a754bbf734665c622f76c62fe2e11dd43ce04fd2b91a8463679058b +a9aa9a84729f7c44219ff9e00e651e50ddea3735ef2a73fdf8ed8cd271961d8ed7af5cd724b713a89a097a3fe65a3c0202f69458a8b4c157c62a85668b12fc0d3957774bc9b35f86c184dd03bfefd5c325da717d74192cc9751c2073fe9d170e +b221c1fd335a4362eff504cd95145f122bf93ea02ae162a3fb39c75583fc13a932d26050e164da97cff3e91f9a7f6ff80302c19dd1916f24acf6b93b62f36e9665a8785413b0c7d930c7f1668549910f849bca319b00e59dd01e5dec8d2edacc +a71e2b1e0b16d754b848f05eda90f67bedab37709550171551050c94efba0bfc282f72aeaaa1f0330041461f5e6aa4d11537237e955e1609a469d38ed17f5c2a35a1752f546db89bfeff9eab78ec944266f1cb94c1db3334ab48df716ce408ef +b990ae72768779ba0b2e66df4dd29b3dbd00f901c23b2b4a53419226ef9232acedeb498b0d0687c463e3f1eead58b20b09efcefa566fbfdfe1c6e48d32367936142d0a734143e5e63cdf86be7457723535b787a9cfcfa32fe1d61ad5a2617220 +8d27e7fbff77d5b9b9bbc864d5231fecf817238a6433db668d5a62a2c1ee1e5694fdd90c3293c06cc0cb15f7cbeab44d0d42be632cb9ff41fc3f6628b4b62897797d7b56126d65b694dcf3e298e3561ac8813fbd7296593ced33850426df42db +a92039a08b5502d5b211a7744099c9f93fa8c90cedcb1d05e92f01886219dd464eb5fb0337496ad96ed09c987da4e5f019035c5b01cc09b2a18b8a8dd419bc5895388a07e26958f6bd26751929c25f89b8eb4a299d822e2d26fec9ef350e0d3c +92dcc5a1c8c3e1b28b1524e3dd6dbecd63017c9201da9dbe077f1b82adc08c50169f56fc7b5a3b28ec6b89254de3e2fd12838a761053437883c3e01ba616670cea843754548ef84bcc397de2369adcca2ab54cd73c55dc68d87aec3fc2fe4f10 +97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb +ad3eb50121139aa34db1d545093ac9374ab7bca2c0f3bf28e27c8dcd8fc7cb42d25926fc0c97b336e9f0fb35e5a04c81 +8029c8ce0d2dce761a7f29c2df2290850c85bdfaec2955626d7acc8864aeb01fe16c9e156863dc63b6c22553910e27c1 +b1386c995d3101d10639e49b9e5d39b9a280dcf0f135c2e6c6928bb3ab8309a9da7178f33925768c324f11c3762cfdd5 +9596d929610e6d2ed3502b1bb0f1ea010f6b6605c95d4859f5e53e09fa68dc71dfd5874905447b5ec6cd156a76d6b6e8 +851e3c3d4b5b7cdbba25d72abf9812cf3d7c5a9dbdec42b6635e2add706cbeea18f985afe5247459f6c908620322f434 +b10f4cf8ec6e02491bbe6d9084d88c16306fdaf399fef3cd1453f58a4f7633f80dc60b100f9236c3103eaf727468374f +ade11ec630127e04d17e70db0237d55f2ff2a2094881a483797e8cddb98b622245e1f608e5dcd1172b9870e733b4a32f +af58c8a2f58f904ce20db81005331bf2d251e227e7d1bef575d691bdca842e6233eb2e26c2e116a61a78594772b38d25 +b3c1313c31ec82da5a7a09e9cf6656ca598c243345fe8d4828e520ade91787ffb8b9867db789b34ad67cef47b26ff86d +a8ed8a235355948e0b04be080b7b3e145293accefb4704d1da9050796b2f6870516c1ebf77ae6a65359edcfd016c0f36 +80e792d5ba24b8058f6d7291a2ec5cb68aab1e16e96d793128e86815631baf42c56b6205c19e25ce9727bd1fd6f9defb +816288c5d726b094e3fdf95cb8882f442c4d9d1101b92c7938a7dfd49bc50636d73ea1b05f75eb731c908c8fd8dee717 +ae009128d128ba2e1519bfa7a0c01ed494a7d461c3aba60f8a301701fed61fe4e31d6c79ce189542ae51df91e73ce1b3 +96a866d60a9007d05825c332476a83e869e15b11d7257172a67690ea9bd3efea44bf9c8d42191454eb04fcf110b16396 +8b250a2a06419adb9b611e89f7f8f2990aa301949b533ad3bf17c4a61ab5f5be0b1d5e2b571864d13f1bb75805c7795d +8450f49facf2e620fa45ee90e1801178842d927a2a25fc6ed7ba99a4eec7ae40eebfee41028eaa84f107f4a777694976 +91049080cf659c0985a22d1366e59191bb89663f922e8168b9b7d85c8a73d74a6d9dceefd855d3d858b493670c750581 +a1e167aeb2008087f3195926f1985c0a459d6ec57237255b1473a96de4e2c1cf766127c862c7dc853a6909e67cb06cf7 +b667c0d4e26e20698b07567358625d5f003839c92de8088e12dbd74a6f6a3156b4ea8d252c9ad62af5f6c4fec1cf6cc7 +8e4b5e304c0b1b161ae3e4b68b5e3ac66c42acd7c1ee2458044f6527c508a93995e50894d72d57c1350f91afe72775ff +8c642640aa7915421cdc21fd639f88a42052b1cfa358ff7702e60793a92b7b5926dae15a0c8f8f59cd3013f01c159ba3 +a356f35e713cfc283056bf539de54a21731e61efb4c47319f20de4a4b723d76a33b65f4a67d298b9ec5c2a1579418657 +93ce204146ce95f484dc79c27919a16c9e3fc14a9111c6c63d44491158d5838117d20851cc3227a5e8ba6ccf79e77f39 +b585664cbb9a84b52f89114e1cf0cf1171bea78a136dc1404ac88a11210b2debc3b7a55e702da93ff629095c134a295e +b6dfd444ec7fdceb14c6328f26ca12c3f9fc4327d8d8c68948e92e7e61262b82d833a65a9e3af6353ffa832b6da25705 +b4d4b8eb9ecfffe3f0d48fb4149c7b31aec1da7041ec03bd0750c52a2a7cbc3a7cfbf09d5bfdc56e3860826a62d0bb91 +a4e248e3d61db52da9683fef188579c470d65e2df9064726847b1599fc774049ffdc6ef2ae578d5ed7874f1298ecdf69 +a68a0fffc2e37d3183feb01b42234c0f4e510f9dc29d09c571e6da00fecad9da224cd0f31550070148667e226c4ca413 +86adda2ffecb77236c18005051f31f9657a0d50fef2a1175dfda32e74d5d53df825c10f289eb0ad39df0c64fc9bc7729 +998266d5c9c3764ed97d66fa9ed176af043999652bae19f0657c8328629d30af453230e3681c5a38e2f01e389ed8d825 +a05261554d3c620af0c914cf27ab98f5d3593c33ab313c198e0c40d6c72022eb5943778cd4f73e9fe8383392a7004976 +ad243fb3631bf90fedb9d679fd71fc0cf06bda028591ded2bd4c634ea7b3c2bd22eca2ab318fcdaa6c2cda1e63e1c57b +89b9859a04f903c95e97fb2951f01cc6418a2505eee0b5bc7266b4d33e01b69b9fe7dc56fa9ebb5856095be0925a422d +a68d118343a5bbfbbab95ff9bfe53aeb7fdbaf16db983e6f4456366df2aa01fbdb6ee9901cb102fc7d2bd099be2f1f3e +b49301f25d5a9dd2ec60ddb0b4b477291958487efea9e54dc0e4ef388f03b8bbadd13259d191f7a0b7513876767d8282 +8b93df7fb4513f67749905fd43db78f7026589b704ebb9ea3255d0ad6415437799f40f02e07efccda1e6fd5e8cd0a721 +ad88769ace96455da37c3c9019a9f523c694643be3f6b37b1e9dcc5053d1fe8e463abebdb1b3ef2f2fb801528a01c47c +80f0eb5dcbfaaf421bf59a8b9bd5245c4823c94510093e23e0b0534647fb5525a25ea3aeea0a927a1ee20c057f2c9234 +b10ad82ea6a5aeabe345d00eb17910d6942b6862f7f3773c7d321194e67c9cced0b3310425662606634dcd7f8b976c04 +82f6fd91f87822f6cc977808eeac77889f4a32fb0d618e784b2331263d0ffa820b3f70b069d32e0319c9e033ab75d3b4 +9436d3dc6b5e25b1f695f8c6c1c553dab312ccace4dac3afddc141d3506467cd50cb04a49ea96ea7f5a8a7b0fc65ef37 +8e0a9491651d52be8ebf4315fbbb410272f9a74b965d33b79ff1b9e1be3be59e43d9566773560e43280549c348e48f01 +8809137e5d3a22400d6e645a9bd84e21c492371736c7e62c51cef50fee3aa7f2405724367a83fd051ff702d971167f67 +b536a24f31a346de7f9863fc351fa602158404d2f94747eebe43abf1f21bf8f95a64146c02a4bec27b503f546789a388 +b5cdf5a04fc12a0e0ef7545830061dff7fd8abea46e48fbe6235109e6c36ee6bffcb9529e2f3d0d701cf58bbfb6a4197 +ab15377525753467d042b7931f66f862cbbb77464212c9aa72d4e5c04375ef55f619b3a446091c1ba1a3b5d9f05e538f +905a75b943ad017ff78ea6ddd1d28a45c7273ee1c2e5e3353685813793ead3370c09cabd903fcab9d8b1c6961372d486 +8147df4324faddc02fb0896367a7647b719b6499a361aecfdd3a34296fa6768ad31c34f9e873fd1e683386c44651883e +ac91d08570dd91f89d2e01dca67cdc83b640e20f073ea9f0734759c92182bb66c5d645f15ebd91ed705b66486ed2088d +ac6295ef2513bbea7ef4cdcf37d280300c34e63c4b9704663d55891a61bf5c91b04cc1d202a3a0a7c4520c30edc277c7 +b604be776a012095c0d4ebc77797dd8dec62a54c0559fb2185d7bac6b50d4e5fd471ac2d7f4523206d5d8178eabd9a87 +80ead68def272ce3f57951145e71ed6dc26da98e5825ef439af577c0c5de766d4e39207f205d5d21db903d89f37bbb02 +9950b4a830388c897158c7fe3921e2fe24beedc7c84e2024e8b92b9775f8f99593b54a86b8870ec5087734295ba06032 +b89ba714adabf94e658a7d14ac8fc197376a416841c2a80e1a6dde4f438d5f747d1fb90b39e8ea435c59d6ecda13dea1 +b0c78e7cc60bd05be46d48fbb0421a678c7f14b8d93730deb66fbe1647613b2c62b5075126d917047820c57fc3509cb9 +a860c4acc5444e9ae987e8c93cb9a5f17d954d63c060cc616f724e26bc73d2c54cd36e0492d1fde173847278e55942ba +8fb8269c9d5c15428e8d45da1251e4c4a4b600d47da0caea29fef246854d8fb6acae86a8e6440d0c429d8dd9c2dfee0c +96c5d8eb6fd5c525b348ee4335d200139e437e4be83690af0f35b7f336a7cda8c6d2958647988b84da9f2dd7bbb7710b +a7f62141c4346cc14e9823dc38ac7d587b0427022afc1498d12ee2c43f6ac3a82167057e670dd524b74137f8c3ceb56d +956aac50d06b46a3e94397f163f593f5010d366aa2d816c2205c7d0f47f90cf0f36c169e964f9bcf698d49182d47d91f +b812899bcdc0e70d79ca729cb01104bf60e1357b9085a10f64f3ba9865d57e9abd0a505a502d4de07afb46f4d266be2f +abce02c7e1372e25d40944dc9ece2904a8f59c8854c5f2875fe63ace8ce37d97881f4f9ab4f7bad070ec8e0daee58d3f +8fb13c515b2d6abb4e14ed753fad5cc36c3631dfe21a23d0f603aad719423dd5423157eefcbd9a9c6074e155b79eb38d +a9ef67304dc297ab5af778cf8afa849eeac27db4b6978963e97b95ef7a8d3264d0d07775f728c298a2b6daed2ecf5053 +a9b975520adb066e2ff2a4cde53284c23bc84261a22dc43b1634d99eff8e7892e46bb6e6da7319c9e72788aa9ea7a1ea +a6eaea4ab4206294474d9b956d9d3188d558a5633de2bd05df0d3bac03dbcbe4ed85406349c1d2e660b77c6da1f5bf8c +af4a19f77290dddee762e1e0d4bc9945aacea3f75756ae46cd3e58a8f74d1b5db73e4834687946b0f39191e32f2fed0c +aafa6523f58f1a4cabc924c86d842816d606afeea21fa4b2b8b9573425810fdcc41c98888318e868f9c05e2be12178a3 +8ef38fba0a3fa4ebe985239c8b759c22aaef0c57e6f39050a651c869487803b0d1e389c3d958fb5a7f37740f050ac69e +b07dfc9f85913c608ca7596a2e361f05e4853fad00e796fd492d247de6414892ce160f627669b1ba933b6ad726415d4e +94da679ad1d78b2bff5283c938f17b2a7d6e9cbcdf59d340e6dfb652951c7a9e852ac0590f99cfee9631b9410f6f00ea +98a907c9c021a5b034d3720197c160a82c4b7146cb73d48efeed99b9d0c6b831812cf80ac7e19e85a676a8cd3ead72de +adb746595466a12929019d0048cea33236b05c1229d2eba73b259a18a786f2bc3f05fc0598d8ce253cecb80bdf679aaf +a2fbac016996d68f9027a157b0a3f6a336144a798d6113adfcda3a5d05b62c31f108f112aa915906aef22b7f83b9228b +81841dea1904406d1b6fa49b4b3f7f6cb40b7646cf44d36c9fa07e3dee29f8e47324b40d8356ddf653109673c3374e9b +a3edbb8aac5e60c775775cbdb19067341b2e2530de48738e84c2c07151241ee31f0d8333bf20c2bc9dcb7b2e638a6b5e +b8aa6890e22964828787ce86460d3a32f12a655bb5c28de500f2fcf6b61e3334640ec6ba96029a4912af0d18df4b4139 +8ca43169f04243ad0fdb0152de17c60d9e31ee0ab520970fccd98590e05508821a183b4b367967e60d53c2c826ec5dbd +b179fffd9df8c00486c5a8b9327d599f5a11745ef564f06e126849b06fe2f99273c81f65bc941efb0debaadfecbfec1c +acf068f1c2b1926279cc82750ce21b0d6b0bfd0406f0d8bbfa959bd83935932957c7f6b8de318315bf0b75f6ee41a0f2 +b97831da260919c856e9f71a41687f5979bc16f8a53b1037285b4a2f9ce93af5cfe70bf0ad484744827fb55c847b58eb +aff50b0bd907383b0c241727af364fe084d021221bfb1b09fb6c1a7752eeba45d662493d590f1f182764b90b25f17906 +aeeef044c14e3ad41e1235c9e816e1eb49087fd3abe877b89b3bade74459186126e160bb569bcd77779e701b19b5f71a +8483deb2b7001ca7c438fcdca8ca6aba96c9cbc4becfd9b16a6062705eae270011bcaedcae69bb54630d8c78129e57c7 +aeee8d24be4ac0d9784c029e239fb5e64316ce29b88f47394cfaaa8bb966a72061bff72f99d02dc51c9705854686e77f +90ae09525a16bb2422169e15d6831c87968a14ebc0d1d27e11a759839c73c655b9d33ee5b12f275d6f440688146fbd2f +a3a41fc7fefef101422465e506bea7f3ff23c26fe35f5732b86f5f2471fb93b37ebc339f84c6be1e8d22abc812c2e212 +86f4b5293e8aea4af1f1fb05dcf99714cb3aff1cfc849b1bb73524061c921c9da9ad92579a852e1889da29d952f02fe5 +8932ef39d4050a1e9dc0fd8afeaf159472d71c5c27f458c69d2730836606ea56e19c8c4febf2535f930d3260e9bc7637 +86307b9f3696bb21c20e4558e30310389e7367803c353d437e9b696039a0ff054d9a4953b75237ab1d1dd6f71118c189 +96e57730e683ef5b550c91de18b19ac73879f3e26234297db68d28747ed0953beb0f3913cfb720c602720bf9330685d8 +b04a19ee70123782e47b238abde55baf60ac0c66292a998af0d14afc8bbeb1134e557b94cd17a020084631c09a0d3c02 +829abc8718be8139569fcb2c398962f38f4201114d30e2b2fb23566f8a27a5c380f5605cec543415202a12ed859e33f6 +a0744fa488c8fa92a722c5fc4ef5a47dfe824eccd87d26c8bab9c174cbb151d44b1b29082c48652f03d3177e5ec86001 +81d4035ae9fd28bdcd78b135cb54955d3b685a527319df6ee7e904b8e6d796f5f5a5f5035ee1de750c4cb6050e452b9e +b205e8c2ec24d7104fa0106c09ad34b5a912c1adef553fb718838dd627355993c2ec01055c11d00b2c75b68e9516d44b +b12d09da7968fa7394e449624fc7174d1d76c069ccb03e140d4d87a2d3f6d1f7b9cfc930f0c80becc673406ebe63f08e +b23752c158695da85048fdf38b395681cc0e8998630af8a9ed41efbda08c9964c2dc8ae6e53377264be4467d702c0de4 +b0d84582fd73628d96b8c1ec96197697c41a963542451a2ade0890af0d33c7161d0f18e1a1ce2c168ca2dc1e9119d55e +8b877e618b469aa187632e410b125d2999d5738fd66d482000706b51fd904a0c7e7daa8c9b729fa33817bbc4154cba2a +b1cfc8a7551b601723b937d497d01dec3ee7614c2bf13d430b1058d5ebc1406045009ff02c2ac15bf8cf16f860193d1e +b6d9da84f97b21e13175bbb0b5cc8e79e88b470c87a3e115726c1bd98e0288526c58f3faaa8aa170ace0cd6a60852525 +ad2e773c2d527671ca5fab7085dde4da31cd35f45d4315dd95d8893ff5fb900494dca08eccfc1a2fc7bf7c7fd2fcab97 +8d5a79b34aeb761d4a0c73f09f02e9548e6d382c33ee6887a759ab05762b490b8a549ef2933c7e3a46415c154c0221c0 +b6f2cbe81bd0a7298403be392f8456bed30aed7ef30216959357698f789affd2942ae5fbaf3f48ecebeb7c273b20cb57 +b5b6c45d99cea7ce6a1dc134aff4a8f630f299b42bd59592a7592345f8cd35bcbee944e61b0723de732fcad6e4425b63 +8077d64dfcb2418974e956ea6dbf8a4c05b25d2a025333ad7e2a379f1976dc036771403383a51bfa3476c9c619ef8bef +ad2e0a9d479c77a5fb73b3613a177fdaad50dcb50fed50e756ba18164c153af30b07fb2565e80ff7469f1b0338b7b5de +81017d1d80a6b6df4e99d0d7f85a8180b5523e8fa2ea2672fddff604933f8a113cab27fce098dcb454d7d1f7ed266e04 +852355479d68e76c7febf6dfe2ef8e80d575c0d3bd52c983803592021cfa898c571c0b884412c21e66f0dbfe03167b53 +98e1bf8ad48421467c93b9f72b47dded7c41b4fcd36ea55ca43ab24b0d0b876f5a731f422579b7167c7138fad2121266 +803369314abd5422019ed4b0ef652b4dbe97ef5a87b0ea373eec9628b64a12120b2c3d4eb53db405131ff786d14c7ac6 +adf2613fc34f73e1160975c140e925ed84d254e03cc3bc7fc1d19957b499c9ba9d9e4c1639981b594a7095c0a52c6757 +a2f6a68efdff6e4173c00692abcfdfcdaf6f8b62369afad3dafaae4f2f38c4860780b4624d185e20e4f4498b75b5fe94 +8b1658aa0e119fb8401d486ed08d60240d26a8623ef9788e3b45ad09ae31259395b021bd16be395139cbb7149714e764 +a7dd8bf21121285e00672ee8bb84e0cb39b2496fb53a26e35dfbca7f2b04e9a9ff9db15f53fe63fcbeafeb2deeaf2ca4 +b6d8d709e44bc18f3b41d69608edce60c02bcba48d3b7e2fd420842657f0665a7343246dea149a25e8f3416284abae66 +aaf744ca5e9bcb63e3e2939b7a1e96e4a93c88c76bec0cf4294dd7db95cdd3f6a7d92196e352d08680e2328bc4592899 +84434b015a7c398d35f1ec71fce455d62ba4ed4f62da042ec31bb2b4db47073314354cd50bc322297a1cfe35138bf490 +8d70b3a3cd9d5dfefdacfa418c0b775a112a47ce538d33a560a519660009c3f141fd6221c18539129e9c0acdaceeeb80 +b8c6903412a800ec78a4c15f31c24385a267b0c0ece32fd31bbbb557fd70c3b2d60d8fc0f90fbd70f43baa1928ea30ba +8e391dd445ea06cabb433f057853f8159511b2f9bef41aed9ccd14e0a6fcd912bbaebd38fd5fb736cfde0fa34b7a4874 +a40cd988f70613df32babbd1bbc2f1b29ff1ab0147b01161555a81d56c9621657999bcdb1df38485f687afc51d5d0f23 +b6a008b4426b3d7b28ae04eee4698fc8ef6a35d89008ef5394da39ce582ce1a45dcfae9a33b90f6fa4237f3667803873 +8987280debfb175c3b44a2f152ea82548e4f680966f1fcbee9bf7d714e31bf8080c33f52705ef3aeee70544b22516aba +a78a51a2c11eea7680a5a0ae417a2981f8c69c396e06da621eadd7510a3664ade49d065617bec67b3de779548a4f4509 +a4d9163f0a1bc048385e94d5e0bcafeee1b18f28eb23505623b9e8ef16f3df76408254dfbe790e45f2884198060d388d +83dcae2568a0c518793c0f6e38b42f9ceb50673d100b556a17ec8bd9faeec84afe50b8d72422c6b2356959667bb8e2de +874731941be4474b4576226e5906b5dee89fc9b56a9870dcc7289c1a7d494d345ba6aba31f7546a16f9963283c05f744 +82c1cfab1f501189ac20147fc4631075dbf1abf9125b7d42fcb4f31cf73f3d6461b1bd08fdf6e45cc54bc08a7d5d51d1 +b978228286f5d4a10ce027b6bea3021affcaa805340ca4b5192c69e8c56db59f48e4a14a284ec015f53baf97389f62b2 +af125f4fdccd1c1b64fdffecb5ec7cf8c7392bbe476e1b89a5b5329c5ba4a526e58c11e72ab9de8a38d60af648d75adc +8411a41ec14295acab0d36389013535a80dfff6e024bffeb32fb3070762f61256419e8c51b2ad6de9dbe4f1e8e286912 +8ea67a91112a41f9c65515cd496f4b0cdefa1400fc06568eef000c9eae6dc250fb7622eb3f2deca10b37287cd96fa463 +8da99b6c55c31dee6a49aabb54da249d348a31d4416201a10c45a3b04b11e99d4ae9813632f0ee36c523b5cca62f6f49 +8b44656341e039e2bd83a19c3bb9a88f6209482e274f8cd4f8557b728e5948dd80b5745f621b96f4562928689314e8c2 +a02d424a615ba0dce8ed91f477e79852215a3a39d025059826fa278e7eebef19824b2a2844f5b3865a0f471b609a23f5 +a1f115cebc3fff3bcf233da27cef19eae791660f155d088003460f75567a550bef0722885010ddc384acdeac635939dc +b61a55ce9d143c17876776e064b58a10baf0ba13553c785c1e47f57b5f94c0cda8bc89d43d73386e57816c15b61a8ec8 +b4073f47041e20a8e548c7fb00e07ba3b9056c34eb4ab63bb0e7b48f8e338e8b56a17611a1b5f4c03b352450b86f1d69 +a7b1a07b213205b682fc5b6acb7e76fdf97b280c26621d8f3b76b7c1deb3511957da33a4e358c8e8f3d98b2a8855d67e +b797e67c2670fbd9844e8a68c585f404b035dc14bd4ec75c3f95f932c777f9db5d5f5df7629164af488fc1213035cc5f +99618200797b945f595794d6468e5c618649554ad9ba896330f1cc844090eb956ae9fc23132912f9047085c5f0c3bf7b +81194aa1319abf534cb3927af9adfb178a99d0e3e8c99ab1105f1d3b4fed40ec2971caf1d6647acb0c8d681eca53097b +80673f18e4978dbc226a6cd4b128a1259d9a7f833879c6e2fbe24d69fef2c3c23a51a4f3e8d88fa4533434bbb0723661 +8125bf6c7dbb2fb63aaa3f53283559f172c788223674adbeb6d5bd17cfe888e6b87a79aec774917f20ce911c1f85f8e7 +884bcdb1878b14fc38adc9fb8b4dd0b3afde404fbeb664f26ddfebc81736018551f23e75ce4cfe4865f610bcd454fbd7 +aec65c8d4be8316e98aa54888af01bc6703a0c5d04b69756ff39a0a947b66817ec59d76afe9f61a25749b5e890f03e02 +aa457aaa1b014a4c5a8992847a187a23321bb43452c98745987d038e3b04046102ae859b7a8e980eea978a39d76a88ef +a9832ee63b08e19123f719bfe2fe742125f32463efa966c7709a98ebfc65277670e9ea1fa2d2d78b96bdc7523b0c4c3e +a87b6b1b7858f96d55064274f29fbde56067064962cf3c3e2ba3110b22ea633bc037a74d23543ce3307a46208855d74f +897cbe4ab68a753020fec732dfcc052c7ed9905342b5a6fe0aa25c631f9ad9b659e0ee75d46f0df6507b6720675ee28c +97c3b5f0d54c1fc45e79445c3ff30458959e406a069f5bbf7979d684195b4fa0406b87c1c008f4075bc9e602ed863152 +921e65d582ea9322ddfad1c855331c3cac81f53c700b96db5305a643c084eb6793094e07944bfd41dc02c3b3cf671530 +8f23ef1aca02a260a3b65d25b110f28d3bafca44727448c8f2d03c5e77eda620c1721b06681bd816ee6027664d76352a +946a89b132ec0795aea9ff9dde7b77e7feafffe6e4a2f093042a7e6c71cd6ab87ce0ca914a1b5fabad4e1f96a795f163 +a01e2de9db33df6511172123ad6f7c64074237471df646b32dd9aff8c15278e2723108e4facaedca97e9f49503f8c792 +99dcdcde45b2ea3f15279936feede5f7d3b63ca4972f335b0559c2fa6f9faabd8127aa892a36deb114357ca906553ed8 +a3f8af37bfcf66b04d1896a4bd5d343f4733d4c3305369ac7e75a08f20f2004c10c642d2c7577f4e5c4d1f2cd851ac3b +b7294d15a3d674a56099f97a1adc9e82c15e90832eaf1722df110fc2abc8634c51515e5ad8522015498a3753b1fa8c49 +b4f27f5062ba7a04ea0048b3025b5e3d5b5d319a9e80310c808a5fb4e8e77b38c10a0f3172cb805cadbcc8bc66d36ec7 +aefe5decee0ae2dc372cc6cf4217daf97c4c908d145f100f0daf1ccdfdf641c78432c2e473e7e4b77dcdf2d4c2bb05f0 +acc84af7648a535ffd218c0cc95c8f7b092418c548815f1bafc286b1fe14f6ccb51b2044db3bff864d0bb70e88604084 +84d8e3dac0df6a22beb03742e1d4af684f139f07e2ea0f7fb27fc2d7d4f1e89b5e89f71af32ff115ed5e6092133535f0 +8ada001e1a03a823c4c056f636e77adc0f9dc08689d28de0d99e0feecab5db13abf37b41ec268dbdb42c75419a046c68 +87dac6c798d1744dff81d8bc3e0e04f3c9bf260e811685ddb9a9a8d6eda73927439b344f9a818d2103fad633de5a4a17 +ad9929a7d8a7d5d5954e48281a87e5c84f67e19110d73296b9989a09c76767a57a8115629239ffb4d99dfdf9c52ef6d9 +81ac7cbeef8ec35a5c3b61cc887080c29e6cd3e08af37e45830d17400dbacfb374dd07bf370b979828c3875b2027d5c6 +97f92c9182953b7e10f7a1bbb6b5b5c40b8275eb5a6eec1e29874c4712814749aa8c409651380216e1ff01d7b8511041 +a09794d0bbe7db013045d3fd857c1544fe6231d21afa3495fa300371f6301a3a0f4b8ea175b281503dd06078ff371ae4 +839bb58d320aa08116dd387a57a2b9bd9efc89c4cdfd82d0e47a00cabe644631d09be5436bd485df3b61b75ddf81a3ef +b1cdaa344f783757e8b9c1f84421da3c5be4c69f019a8fd4c1aa5bf1a63e8970c99e35c22cf3b48a0e6738bc6ba7ce8d +92af68e3216c78998208fb24b5ba0e645d0d3f5e28222b805668d7e9cdd6c033d3b22fd6df4c2d745d7f910d133cd226 +87640a4ea4e605e2204e5232b29a6c1c31152d83547eef14122cb76a0da52b8653801af48455a3ed713b9dcfee7b1ef1 +8147e5bf0c8f4731155ca0517ef3fae5a32b4d5d2d98ed0007b23893d8dbb7f8a1199c50c1750c2fa7c9cebe594b1bb0 +a76b4473c63c3ab6103c729afd2482822e4150f3155af39983b0ff0766c71cb622455ce6304e23853661eaa322219d18 +b3e2f05ca551bc3adec0067e4034aaffd72e0b64ac18ae25452c996927976c6727966e26d213b032521889be2170800d +a8414cd14cb3be658e9e0004ce511ef7063439b1cbc3166a11de030613fde4b59caad4e91d426927863c55382afbf476 +b2f0f8ab99f4d0ea785ac84fdbc00b20217b1df59b30b51d9d209d489d53b69dd5d82cdacc16fd1dd15c3a4001595f50 +8b2025d5fd658c9bbed619f3e3f6ac8efe7aeff8aa9401bd66a7ceb0062c44b353608ca073f95be99204f0a913bb77eb +94a46bc5a87291b42024b2137e623c70115b9c6b196604106bfbfa20f3f56ac7779763f56b580190d3cb2f1c648cada1 +aca9355545118d0769cacf69c4b23d6d68d229cd8f68f1bc0c847c05569c5af6bbbd8c4dceb637b4a6b3b5c83841bf5e +b0731992cab87c7116406b283a84707a34838bfa3284b0f6082dfabeaf41c5ac2b0ddc1b420547a1b0955aee92de2dc0 +b671f77588c0f69f6830a5b28e7d07ed161b81fa9791bb3a24aae6638e3aa5e186df74978a82549c370c18ebee04d4f0 +b5621ed841780f3e6681d880a76cf519cdd20d35197b112eeaa686764d57b5dfa78ffe1a294b6bc76b6e3949cd2a2369 +afeba2524659d00caecf089645611553187a6ed7102050f6dd20f5a19bed08ac7065912d88371ee06242897d58d652a4 +b78bfb83d44ced14a20135804aba3f00128c3ce1f302e95567ce4097b0d973414153fb305b9f156882a5a0554bf25973 +98510aede95d26b1adf214053eae051ffaf24894e2fa37961a91d0ff5392dd09388196648d95b73e90bd88f2587cc4bf +b35c682d49c295946b9f120fbc47b95abd9ee86d294abb003a92139fb825b509209562575015856a270eb3eea86397a7 +b9641bf685571dd9c478dd2033a1f1b11cd3a662b26502c78595863b8e536a189674a9a85f7a253453ebfd1b99fbd841 +b2ad37036a59b1c9b8457972665720a6868422ed8157b6810a9c0783006103be34ab732d7aeb8629653edd18fd0f1717 +af0920cff05179a3896ea6ea322c39adf91ada5bc40fe3f6fb1b1b4e121e907c904bbaa8ca00468b3749f3da144d71f3 +8e269672818ef1e2f9e0c8aa65c84442fcd9151d74bb8e870cee8c0e3fe24526e1a5388b430cef47b67f79b4e4056bcc +aa29a16fe00ea3d143b1032b1dd26b8ce638f37f95c085c7e777e8e2784bd724bd5c38b1583c61a6ec7c451dd78fd3fb +87452b7435911cc5f513b0c81b15aa04972ecbe3d7bbd0a5d676c96a8a311301c0e07fac925c53a350b46fbd3d4d0fc1 +869a81c351096f47748e41566ae7b77a454b1cdfaa41d34a5742f80df38fbf5cbb08924b6fdff58e3b18f05c62bbbbb1 +8b7bc1b0486300981147a40a449ada9a41afc06d735cce8bf0fab3ee94ba2e2ea57b1397e3cd31bc295352beb8334ef7 +93e93fc41adb2df279d95654921b4c2edf0d293dab58d0afefb221f777349ef88d0985b3447e3b935954a81f1580a92c +970fa7cdca8324faf3e62348bb50d78f580b4f43f2e1c11bd8382d48d0074a3c55c6407203a0c9cb1c5f2163ba421ef4 +924983929e608d27e4a36d4ed919297869e3c64de51aca794d32d6e90aea546bf898d98ceca28a0b2187734821b78504 +8d395332529c703d943d68415d443332b5c1342ca9d9a59bfa8bd4ab63e93358c4b0dde6ce1f2e8ea9dc8f52ad7ebd95 +80200dda853e588256599e7f905add5d5ee7c74272780317694fbae39318ae9be05d5bcd7b20cf460069743f3d4ef240 +a287d51d6359c9ef7c7ac1b20e479ce7d0146dba5606397bd04b7a622cec642508d5b45d51b31de71f9763595b6ac88e +a320396c075175d6599225cf2e1de8c7cab549f6316c07feb0f6eaa21f06b2dd29ab14fbdf2af4543b4890ec0fd08a4d +b1e9fe230418d20368691058adcbbe30011bab3000422f0371015ff8bd09c60fb5fa85d18550d35b1c900977ca48f58b +9718fc26a51783b971744933f20490e9b5cd9162f86b84788c4c5217f5409e37b5a39d628b18e5b35a757acf67596321 +a0cf81fdb161f4f1b419c5e4caa36d4bdca2325f0cd25b119a30178016f171bd6fb88403e4e3aec026c4089f180d540e +8ab1e36bd04625ee794ef04c4dcb8e004d61aceb2b62438377f49ad95dcf025ba25eb799280004941e555bf7172af6fe +9257b9e3d14d37fc7efae49b0c68d36eaac546035f4a2654d566b3ce1b2c4564cbb03dc8ec66efceb768559a8a507a18 +945d1123b839637ab5154a1972c3c83a0ff34a3b1a3465de6ef0416b1950f649869a3ef88d7f1036648ee385265ce2df +81449639d708860fc0229c94f754f7262e8a3c7f67960ff12dfd15df95f57a9ffcee2013e81978b7703dd42bd5d0816f +a865481deaae5a690fd53892791e5fa729db283b75a525a11cdfee1ce17e8e7f0b449d25f20b3c1b43da128dbdf98a8b +98766812a65fcd25b853546e3bba618a3edc9fd61510e4f8ab60c038a7fa50d197abeec8776109df0f2119be9445ad00 +b1b8dd5379d903dc41d74e999b1ab693607a0d2905692f4fb96adf08f738e5d31f9d00df28ccb8b5856145ca552c3e3c +99d20be7b511bec78a8ed03c207aa4aa9097ba39d85e18f1b8d52f65431ab7e9a773c7b9ac3e8d8b25458bc91bd00703 +b1b7c3563fe8cb33c7d3e0b89d00bdd13e86452ff507c2e69db7b3af06f247f139155396e9b0278753310dc63940a10b +b3dc9c08451b1de7c9969b1e47574bffff50490f4a16c51e12390195d9e9c72f794790caf7b0a835d64e01fec995d3ac +aaaa4761a00022ede0809d7063d3532b7bfae90ff16f45e17a340ad4ebaa2fbac40728ccc5fbe36a67ab0e707566c5dc +8319a1903314eab01f5442d2aee6ae9c3f6edfda0d9a88b416d0f874d7d1d05d08bb482102f8ca70a4fa34836d0840c1 +932949a6e9edfec344932a74d4f81eec3667ece1e8b8ca840ce07ffd4b5d6d8f01657c764d64ac1b9190f876b136490e +904db1568128487e312fe629dd8bb920cecafd3bb9cad8b63e269ae0129f2f5c80cd82f0d81e7feca9835c3945a72d28 +a17280693d30dcd43c85de8f6b02d5f30cb9097274ad680cede1ef105c903615b4c40f3c6aaca478642de324972514e0 +8d5f76e093aee71d0cdeb017fdfcb13bd068039746de90690ce150a0bfdbe7ddc4d539df0f82c2d2890a40b191900594 +96fa1f2196a3883cdd73c66d28403cbbb58f6a939a3697ee0d308d8a076393cbb4be86255af986869230ee410c01bcfa +a8b74438dc5cabd70a91bf25601af915c4418d074327a9b01e0190c27d3922c89bb9b41e0b366e82e313edda8f21983d +ac9fdc1a9b2e3ff379eb2370979372e13c4177bf4574f1490fadf05a7073e6d61e703e2d8eed9ce984aba317d411e219 +a45a6c9b958169f2f8df70143e6ac3e2f6f969a4eed6fd9f1c620711bc2454739bb69f0094079464790c5429c0d8aedd +8901cbdd1009864386577842c1e3d37835fddf834064d9613b4559ea9aef3084204e1f863c4306f874141f4374f449ff +b6c582161691e3635536686825be9c4d7399d668a7675738417e0363e064dfd28acdbd8dbc9e34c1dab8a1990f1f0eba +89e89ddaf3cacc78428f3168549c161283ca8337345750667c98212717b21e7d994eae4e45bbddacc832a18df1d79276 +84be275627eed8e1a73c7af8a20cee1ef5cc568cfeea7ec323d7f91b44e9653e9aeed47c1896a8240b99dde545f0e1fa +a779a54ab4f40228f6e2539595fb8d509b70aab7c19e1928c1be69ec1dc19285c3898cf15e5f8b8bc725e13af177fe17 +92e2a49d2b9b36349d442283b17d46f8f9bf5932c34223015ce62d2f285e7363b2c12232be4a838b5b6cf08e694c094c +8b4e28c6f3f36caa2cfb82ba88066c830f8017bd35608b077143dff236f3181230166f5a5c02fa0e5272297331726aed +85fd77d46162ffac4b8adb25baff0eb0512a53a3d01638b3a376ea34702279ce21c8e7d8884308c03e00c9bcc1a9fd29 +aad5e46916ff1be29009b595d1d8fa160cc7aa01c7fbf3a68f445c87615790dcab1fcdbdceda533d182b6541f09f2f73 +948df7654726250dae393325addd3c0a20431c81f00470962190335ea4b6d9f7463d6f308cda46b92084c1f24390b1da +8f577474dea132676504376c5542b730b6604fe3d965eaa194659fd11c52233bd0b11ab62e198c0f442327ff1c00e501 +ae2f1001546db3e0c19700adad997cd9f765fe7a51a502cbcd9a2a07a3a5db79c8f603e05cf96d80b688cb6c9b6cd3ae +953b68e5d9561088dd20406ea7fb6894cba33868a38ace38fc30b5813140cb15dd6dd2171befae5b4df2e4a9658889d8 +86c52901655ff11419b084a04da8fc3596eae59d81d3461601c0baff59ba59e3d1dd0b7ce719e741a3e97c013e898579 +b9a72dd5eff73f9912a28b55de073568efb3eb0241a10b77a2bfd4f30c2aa4fbfe0c89eb345c9f07fb725660873cb515 +8e7353f5f2932e4ffd95811caf46c9bd1a53643c27eb41a4ebd211f230955cd71a8b27e17cfe8aa708d8514c0de67a66 +a096b8e66312a92fb10839ebe60189a8d1bd34dff55f7dfae85e4d2f53a1a4a88211c19fc84494f066358ddce82be131 +931c5cd82719d76596832b007969b5f75d65cffabb41b9dac7910300db677c1309abe77eeb9837a68c760bb72013b73a +8ba10f5118d778085122065b55dd1918fddb650cce7854d15a8f0da747da44d7b12d44fc29ad7dc38f174be803db74c6 +8c971deec679372a328587d91fd24ab91043e936ca709c333453d7afd43ee256d08c71cb89f0ab0e89ae119831df6d86 +a2ac28a58034fbd8fd518f409221bad0efec52670880f202e09c0530e2aabc2171ed95e99891790596ffad163d86c110 +b3354e3dfa8068aba4f3741152b9204baa4e342c1cc77e6dd1419cbaf8da1d118be605846b8609e997d6a62a11f3423a +a12ab65a213c9d95c24865fddc2dffe0cf9fc527dd6bcdacc1bd7271e79929a4ab3427a231f4f49d0530474e6cbc88f9 +90afd65b7e6973f8aafbe74da0f42441840d3c93bd69bc1bec8fa56824e7ca97ad1b427c8a85da7d588469bd4ccc50c3 +a09175940c59489bac3d3da3a4091270d9118948cbbdd57f2bcc63fbf45b8010651c801d3e58dccf42733ce1d6b446a3 +a843bbf286e3cecc1fe370ff1bcf5f1001bc2e95b34246625ff50d48ee62343e82fba2d25b8a4bd5f7b5ffe90920efa2 +a3c4d1003219157fdbee2707ce07afa6c2a64ae8e450182c307ed7f070024071f30b12c4b0032960ff913c74e73a9976 +b24af3f68d66f825d06fc3ff94fcccebe28b1a0d4ba29c48d3a3c953b9bf7ae6707f193fef25e2dcbd2b74e483c774f0 +b0f657f7723184ef7d7e4381143f1ac8020d8c6c6f2dcbebb0eaf9870d61a81f2d452596503311e46d1b38f625d4756b +b90091004fc8f6205c51bec68547ac82dba0f5525631e7632cf6efe54eecd9020729fbee6105d1b8012402d3b79c54aa +8e3fa187713c60eb0a416d6900a894cdf81e6b6b69dae0bb64f6287f3c3f030cfa85c665f7aace1eab4937f380b8f728 +879bf0784ccf6725c9cd1ea8c49fde31c91c605de1ea664a33c2ce24c277ee45d20b66309f98d989acb2ff3b77e13101 +af3f3a3ddc4e11abd627d5aef8adffa91c25df5f0c68b4d2b5d51e7d9af3395ba4f6f7ae2325a6672847e1ecc6cad628 +973e667289e796d3a40f072e6fea575a9b371a9997cf8961677f8dd934619ddc47c1a3efe91bae9ef95acb11a8fe6d09 +afa81c5606de82f46b93f4bb6db3fc0670f4e0d1091388b138a66b3827322d95a56168c951c30831d59eeadc227500bd +b83eff77db5b4c18574662942eb36f6261c59f655f8a9c3d3731412d0f257c8e80aacc995c4b2303058a1ba32522a434 +912e5ac9234b9445be8260393ff08e4859a7a385e800b74d1534eeb971f58f74cfb518dfdb89f8705d89fbf721439129 +ab27c8ece4a51d23e22c2e22efa43487c941139b37ea1182e96efb54ca4809d8245eae0ebe8ba94f0ed4457896fe11b1 +a6630585d104a745bc79dba266d9292bbdad346449c8ee8140a5e6e8a6194411df9cdbf3d3ef83468a536d4f052e9335 +8b8c128244da48e7fec641a882d0005a2d05c7138d86a293e6a0a97c76bf632b44767d0ce44663c975e7f9f9679e25e3 +87dbcaca67351a4e7d2297d7cdba4796d12f58857e7ee4abd0645563577ff33544a44cd84e50b3a3b420d6998de9b57c +b859ba43df259d7f8e7fac70bfd7aae546d57a5dc90e107b174a95bf7fd3cf00f740c4434848e69b2a7e6061f66c1ef1 +99d6e20978fefc40c6d310187eb2ad3a39296f189ee122ed64d74f81033c3069d44f7a9d3988a1df635b609603a17272 +99a5ddf3420cc0c92b21f71a805245608d4995ead447d8f73a670d26d33e26920d5f07bfe1f6230bd5f15978055b4253 +b936ac0944d3c5e4b494f48f158000abb37b80b5c763f77fe856398c664b0f1ddbcc0a9a2a672db9278f08b4bafbe2ec +b4af85fbf4040e35a686dd016adec037c99b47cc2e4dfccaf7870ee9e8c97bff30f3035992def2a9d4af323c0b3af8ae +a5ee32b8bd5f8fa9000da4da0bf00565659a43285393d37080b555d0166bde64d87317b2eab2d48a0e7b287caa989be2 +894d4ad58ecb1c9ebc4f5a97407082e56cb7358d7a881ba7da72321c5027498454f2c7fa2bd5f67a4b11d38c7f14344a +965be9eeaa0d450dacc1b1cc2fbf0d5d4b0dd188f2c89aaa9260e7307a2a1eb22db6092fccb662269e9a1abfc547cabb +805893c424aec206260c1c2d2509d2cb9e67ee528bd5179a8417a667aa216a3f318ed118b50d28da18e36c01f0805e3f +972d7040d4963b35260ef0cc37cd01746f1a2a87cedc0dc7b0ee7e838c9e4573784ea743f563b5267eb3905d4fa961ba +8c7156991d4c2e561888feaecf501f721b4174e7d14109e9deeac5a9d748301c07e11fb2b04b09799f0d34ff42cb77d1 +894722ac35af3d507e81d737d21e16c5ba04686f8f004aa75934aae5e17acd3e065b96e229eb011c2f34096f4c62048b +81237937c247c88e8e31e2c72412189fe59c1daf65c5513489d86cf29ee922c0bb08e5f7890f09f4ada7e5262083d266 +8cf62cda2fe0d9a6b42aa2a1c483f4ad26378c7cc2c2d1510a76df7560b07dba8528b33aaacb15f7f20b9d4c7c9f61f6 +aaf0921fb3e1920eee5d0acb59dcc268b42f4b435d60d25d30357edd7dd758d035919691bd15311d85489dfa2e5ee696 +92cec07be2247ef42002ebcaf65ec855611b8e893a5675796f2225f55412201b0bf9f4761924d0c8377b9f131e09e39f +8e514a62ac1e91773d99588415426c97ad63e917c10d762fe06ace5277a5c3bf3730e4b9e5d116f8493b9ab8687b70e3 +83932df2d923a5052468a3ea87f7b55c6a80ede3594046ee4fe233046570921822bc16555b92ba6aeabaef9b1dc0805a +a2b5bfb249de3472113fd3f35bfabf3c21d5609da62a27ea6aab5f309c9068d94bc58ba03efb4ec11be06306d59e60e8 +8106cf3ebe6f0507be8c6e8d137987315fe3689ecb75bb27980f36ba5efac504baccea0e7603549b6d126beccc278804 +a73ee70b6fe8c082443972102c453fc0e386852476cf22224fc0bfe554735c12f96037fbf10922795f4502c4f052b5f4 +932b27e175440169958504f3ed6400e7d6dcd5e716c19dcd0f15c56c04503ed133d5a993e111c016f141e32d68b29886 +96f7ce4595318e0b4a6b368f788ff82226aac676aed4ace343867f751de414453a9aaaabef6e6224ce5aedc3d5cf77c4 +a950c1e3bc9a14484997013d44d876374b939af437ae7c821c131fb886063ee9fe7214a25a0c7084f0b07b99412eff75 +a9dba3886ed6855303106a1bdd26010f294218684e1c178afcfea3f37a2f04fd01724a31d82de3449046617e3507a115 +87a2f776b32a6b550cf3ceeaf78db02819be74968d228b1d14e0d74a1cdf994bb500b7abef6619455e98d728701fac5c +8cd887b07e335edc0b27e6a660cebb64d210741395be431d79d570139687b056557159407459799a8197b6079644f666 +b81a61fce00588909c13a90c1caa150f15788786af443ff60ce654b57147601f7e70b95659e01f470334a220b547611b +8aebc51141544c5f3d3b99422250424b9800031a8fdfbf22c430907a3a446fecaa2392105d66d64b1c8e847240da4a6a +90db7dc12baa02f3f86d3edadf9434e2b9318d4f6f0eca08276b765dbb38d8eb0d08be2fe70adf2bf16ceda5db08d3ca +aa1839894152d548cc6ad963de20fb6fcc843bc9af2a2bf967c63626b8ad19e900894d6106265f38f3afccca317c22f0 +848e27b741496988a582515c0c8847b2bfc6a001259396cdeea1e1b1d2828ca3a626693a1bf4adf3a3d7f8b1fa3d75fe +a0aa11754d4ee136ac3ca609b17bcae77758763b2016544ca7921dddedd8aafcc7ad5f2b337c8bf53084eb8e43ea41fb +b8713b7aa1c112178195fdcc9b7024f46e6bc04c4e76c41abe620aa265287809200d98eaed6c9703fa97e81d6964f0ec +8605b5b33309e9ea6823542b85383c496794b8481c577497aaf99ba90496e794dce405be615bf92c7b6361460e6b82e3 +826fa34faa7f83e063a7bf172addfc07badabada59cfc6604fdf481d29085251c0a67a1355b2cbd374e2975934b84cb6 +b45d131082dc16fa53af010d43eefb79200dc23d2f3ee26af95ac6a5cebc49c84a9ed293e534ed16ff3ef9a4a25456ec +91bd6ce3c5396a7a0de489e49f0cdf6dce1cd2d0be7a410326423c3185bd1125ce1e610768be7f15f4e44b62f8834fc3 +903ffbe3d33fbf106c01c727dc3a385201a67ded70d4df623934882f69a3a96c909b027a124f3d70cb072b0046a149e8 +b405359db9d9ef4821a181b440ef2918c240595141d861d19a85867a5afa74d2972d22c988775eab441e734700bae4a3 +8abb756d027233c83751910a832b0ef4d28d100077f1c5d656720c94906f91d85dd0ea94b1cc0ed95b692efee14c786e +a78ee77ab476a41a3454160ba7ca4085d8b1f7057c63e76db8b07cf20afdeddd2250cd00771a6329133bb4ad48ccc20a +a41810271d8c37197aa9b3dfcefe3498e42f5978d3f3d59defff4676d6402d8575b40683834f184f143b6cfbfc859b3a +90c24a0750242660bcc6d487358a3cc015730538a0a8beb00ad5ac2ef33cb8ca8a62121e50bec8f3d2f43900f8e3134a +8b96c39695d864ef5796941754978a1fd612b369f6b77fe5ae6587beac936ee28190af8f0a3822b63060af35e49a5c8b +acde2548883d0e63c0fc257bb9dadd919aba60a985b69ebcfa1bca78acca42fc1322ec30bcc8e7c188818f858d04ad33 +895c86ae9ff8d95f2707d4838a3bc8ddb05b2611f0476f014b9c150d0e8332bc73285037a747426f09ac8179ba4e19fc +821761fe406e18bd86fa9ca9db99d382cd3b5c70c456f471fa3706d57763d147706304c75d54f51ce8f3115aa26e59d9 +a803a80e3e8f47dc3c59ea23eafdec017458eac648b360cd42cbd075e0dde6f6f450b48c7646fb1e178c04f82ae51a12 +91f40e1b6f588bd592829ce937996452c40be0fd6c43793c607866701ac6a8c7227e0891d45c6e7b1599382b0a3fbdbb +9408246d996a634a58689337f2526dfb3ba9ffef1d3ff91c32aa8cbbed900861ef25d6477308b67d76491edfcc70d65e +a492325a427f3df1c9c690c5b553daa8ac41f62f5ae55f425539222bacf959e2f67afabbba1732e120d3e7a6dcdf7049 +8fd0c3e15477cae228613a171b6e9ec29ddc63ef74854d99b638adeffe39f89f34346a42851e8445e855a9f2bbef0f57 +b735ed01fafa051004dbaad5e8c9e2faca8f6049ef9b590f256ea4d75b04594af12764ad4e6031735eae36f83179db93 +a7d35f43fca06c86b3425dcb68a87186834ba9740664fd657915771beca4cdc0fa2fc9b4c2e9d9bdad8ec33543ddfa59 +a1156e71e2db1b17df5da28747c88e091bd687bfee59d89096437ab4dc9a543fe5c5272d5023d72adbaab397a6fc94d1 +ab06a58bd81b33a411bade8d8c5232d38fadc2e38507159edea6e2e104b8ebd65ca02b05335118f691d44197b847a4dd +848b67a10f1e6ff8f5c228f226ef2ffeb67fb8f50925fc94cbb588d61896d9dc79726959e649898fd3354fe3ff7b7ee3 +aa933397361f32b388edcf832f0db172a38e756b34d5f7a4a050fa7325058006c22cede26ee27917e8f1b0f301792bd7 +89e49e7f02cfaae4a4b9c4180c9f6559d76e3a45774955859d4147970b1470dac37bdc9aedca1c32a20b045049161590 +adc1825d5ab94fc719f25d8c9773f4d518134ed88eb13ac33cb910b2be3523ef9ef88d9e4aea2418b806e20108317bf6 +96c4b444c8a023da644f3a343ebeeed19a8392d2ce175992461451c318a54273b76c3574d8f2dceda2947ddd34d1a674 +8aa7e97e87c8c5b29bbd51a6d30396a6be1fb82b716ef83800f2c36d5b85467ade7e0f59d2db82c310fa92a9265f0b03 +9146c32d99f02c3a6f764dcd9b4807f1585f528ac69dc4f84e4380f6fda4f9d5057c375671d51e7aca2b2b4140e83da0 +a10760a533d9bc57536bcaf65f080302086aa50225437efd64e176841544711828c23a15c49c0dd1f357d3f10722ab72 +acb0811777e17f7ae7aaba5f6fce81b759c067a4908730916195a2505c7450d0e6e2194c2ef0f241090597d58e70de47 +b24f161e9bcdbad56665e2490b5e4c7768390d4668cd69a04ed74739062dbe832636dd33cda89e9b0afa8c77e93fc641 +96b4d01106b831868a88ef016500ef2fa42d0ce87a37ca8ca4194a92a22c113edfe04eb2ca037329f3c1acc635148f55 +aebbb95fb4f7adcc8e7a217aeb73f9e037cbb873d08c1cd9d68c6c6834511adf1af8b44567fee84327599bdcb734dedb +a9bd8b17300532fb94d028659bcafbe7bbdf32f8945baf5db4cfaa1bac09e57c94cad0ba046b4514044b8fe81ea8596d +a5557cbda599857c512533e7cadcf27bf8444daa0602aa7499cafc1cf1cf21f9d16429915db7485f0e9a1b5046cf01c5 +8810307c40bc661c478a9747ebf2a30e5a5ead942d1ac0418db36ba5db0709c476f7d19685cabe6959e33ec1f3bff914 +8829b741f41f2c32e10b252d9338deb486dba2f23996a44cf1dd888ad967a589d51329be34d764139f372a1043f6c2e5 +a6b4728d18857c5fa082fa67bfb3b1d801e76b251b1e211a19c87cea5fe7ce757f943c85071f7a03a718388cd5690e95 +86da7f397e2533cd487f962ae58e87bea2cd50af70ef2df9ea0f29f70b5843cde664d30ec207ab84fc817f3851277e02 +8085776ef4ac6d42ab85b9d9135ecc6380720efd274f966544eeedf4684028197de76ecab919fa5414302597e1962bca +b05a065c733033d223ba13d16baa7a97bd8c8b8b1f0e59a9bdd36ee17e9922d48eb39bd180c168b122088a77f0bf321a +a89343fe44a93023dcc7ef71bd3bcb6786f68e1885ad260edc56a52445d34757f476395ba7ad35437f89bc573c7618dc +a114a9cd6105b524f3969c69faa2e09afe21753a93361a296f9e0e3b4e3e63726ddf2e6bfd3ddc046043e50bd44e539e +8a5611fec539cf681c05636bb580f29acc06f628bb012649ffa41ea6c1521194a5643d5dd843f09b6eb2c3bdb4d41acd +ade247c4011ec73ec90b72f35afa59a999e64ba5a7e664a4b30874fea53ba6a14a76a41b58a5f891a20d019e5f091bdb +905b5d96df388160ade1ffe210d0c6d1979081bc3de3b8d93ac0d677cc2fc2dc1ef6dcd49d3947055514292a3fa2932e +a9520796ca9fccd11b7524d866507f731f0f88976f0de04286e68d7cf6dbd192d0d269f0cd60fd3d34011a9fe9e144c2 +989a1edf4d7dae811eb57a865c8e64297837ffeeaae6ee6ac3af0f1044f023f1ca552bf00f1642491f0f0f20e820632e +879c8e63713f4935ed6e020559e140ea3073ced79d3096c152c430141272117b4fd9a9fc3eef012e81262df02ea14bd7 +95074738ac1540c0312274333acd1ecad9c5509fee883c4d9295fa8d8200f6e637c363de395f9fa612f05c0dc58fae88 +a770e4fc595269eb806b113ab3187ea75c8f96b57bf9fcfaf535f3eedc1d4d7e6285a20990575de0ff09f62d06ed0692 +81283e5dfb6423439ff513eca1cc316941d196df8da2d1069d2d0b63f5289e630af2fd4119bc0144c002d33313372dab +abd1b108e743887b78f698f2aba9d5492f87a22868d1351d705d93a1084fd45be67170c68a6e18b07f400d9a01cda8c2 +8509c3f67b92908cea8144f4e2a71631a66a61ac3547601c788907e52e380e5fe8ae4110aed95d13c67d3bcdd5b55a61 +8fa5a790ec5cce6d4114128c295390120869aac5490a82feebd3c37a167120df2e7fdfaf2a4050a7dfebf48fb093212f +944753e1ea7d8bc727d46a7702077dc01dc0c6574e8263a16579b57ee155ca5901f71bb347a01a9a922b329d3ff75135 +b46bc1fd4590b7a6275e20036d247c5909fc549c78e95b64ae7ed96e3b05bb044840f19f7650ebfe7008ba09fa83c3c9 +b1e47e4d88e59a06c465348c6cc4181d40f45b91e5e883966d370c26622c328415c6144aa2f61ddb88ec752482c550ca +8bd4f8e293e3f1815c7e67167618fb3b0ea76424bc0985908957cfcede36109378e41b4d89555b8c2541b4c447e00461 +a70589a867b2bfb63d0106083d58475d506637148549ed35c83f14e5c8de996e1b1f3447ecc80cf5cd134ef4db9d2fb6 +8048b80ba6131d07370162724127b0f7cb17fa7f71855e55e5a75bd0a9e4fd71b0d0ea2d16ec98858e458528df8d06b5 +97326cb94bae7530f4ec3235770c5a7ba042759e789d91c31fedbd979e3c0e6a2c69e2af3c1979c6fe0094274dbd53ce +a18e9c1d3eabd62af4e31a4b8e08494f4167fd4598c95d0123f39c46c53f9e93f76615900246e81a286c782ac37c569f +80309c59d4522b15aba617cd3c6238663e8b1c7ad84456346082c8f281140fc0edf9caa19de411c7e7fb809ca4fa3f4d +8e450c0990e2f65923f252311623038899eeff7b5c2da85b3a224e0ef7132588b291b782d53c477ecb70f34501466178 +87843f96f41484e254e754c681a65681b9ae5c96c292140368743df9e60f7e2ada58ca2bb95fa39abe064b2ebf21eeba +858e8d5bf2a1cf26d8af5036b28b831d450a446026f58a1734b696c18f1f41482796b91cab0e5b443dd2f0b9cffa52b4 +99627dd6bad8c05c5904cd23aa667d664da846496dbbb8452705c4ec01e1480e9c7295504a5a8529e4a0c842306b038d +b64b33256c18b2c886a837a0c0730fdfe73befb0e2796207c4dc592c5a33cd51f8c2ef47c584dd5773abf9ce9c1b0082 +944f6da2a1546f0bfc4d98c3e73c79e935e33d208b6be26b0b5f8df6d0e3b74a5bda649853b99281bd3a3ec799a7dd04 +a266d165435784d4e884640155e35b2a911b3f89e1e715986de419b166a36a341ba724877d80583fa3da566f6a828971 +adff2698409d0756e78c534032ee926560c13d578cb178d5073172d049ebbce32a92692f7e2033ec781b9b0d894ddce0 +a91933f110756c699c28bf9e24fd405bf432002a28c4349e0ca995528e56a5a2d101b8d78afa90a178ff1a9bf2ba515c +8e77839c0eb4da2d01e4053912cd823eddffbdc6b9c42199fba707ca6ab49fc324288b57be959fbfb11d59085d49324a +aa124517c76692036c737e987f27c2660514e12a953e63ff4bcb269dd18fc44dae95e282de8444bed09639ef6577af88 +b285deae99688f1bd80f338772472fa2b35e68887c7eb52c4ef30fc733812444c5cd110050275ad999d5a9b57f782911 +8877b0fa85b44ef31f50bdb70b879fa6df5eb1940e2b304fd0c8f08abb65f3118fa3d97ff93919038c1e452fb1160334 +8a89f3b50dcbca655024542ca7d93df17deff5c7d01c7da2bdb69e76b3e0b4490d85c800fb3debb4b0b4d20c9527f7ad +b7e5dbe36e985354ac2f4ab7730fea01b850af00767a6c4d8ee72e884d0fe539bb81f2e34638fcf5d07b7c8d605f4c06 +a85a1d78f6d4f9d5d83ec0f2a426708342d4e4a5d15625554e8452f6a843d9aa4db0c7e68caebdaf767c5b3a6a6b2124 +a518078a9dac63c5bf511b21ed8e50d1ccede27ebfe9d240937be813f5ee56aef93dc3bf7c08606be1e6172f13f352ce +91144eedebda4d1ad801654ef4ecd46683489b177ba1de7259f7dd8242c8c1700e15938e06c5d29aa69f4660564209a0 +a16c4657bc29d1d3271f507847b5a4f6401cee4ad35583ad6b7a68e6c2b9b462d77b5dd359fd88ea91ce93bb99130173 +85b855778f4b506880a2833b8468871c700440a87112fa6a83fd3ddb7e294b3a232d045dc37dfc7100b36f910d93c2ae +8d86bb149d31bfbf1fabcae1b8183d19087fd601c3826a72a95d2f9cedb8bb0203d1136a754aa2dd61f84b7f515acfa9 +acfe7264eee24e14e9f95251cbcfdd7e7f7112955a1972058444df3c2d2a1070627baefada3574ebd39600f7f2ea7595 +906bd14ecca20ac4ae44bff77cc94eb5a4ecc61eba130de9838e066e8766ed3b58705f32c650e1e222b3100691b3806b +8f2cbc7b8593c4be941dd01b80dc406fe9dfdf813ef87df911763f644f6309d659ea9e3830ff9155e21b195fc3c01c57 +a68eb15ed78fae0060c6d20852db78f31bebb59d4ddc3c5bdd9a38dbe4efa99141b311473033ff8f8ea23af219bc8125 +a95cb76c9d23fc478c7e8a73161f2ff409c1e28a2624c7d5e026e3cee9e488f22225a0c5907264545a73e83260e3a4ec +b76f90e55fa37c9e2732fd6eba890dd9f1958c1a3e990bd0ce26055e22fe422d6f0bcc57a8a9890585717f0479180905 +b80cc95f365fabd9602ec370ca67aa4fb1219a46e44adf039d63c432e786835bb6b80756b38f80d0864ecb80e4acb453 +b753c86c82d98a5b04e89de8d005f513f5ea5ea5cf281a561d881ed9ad9d9a4be5febb6438e0dba3d377a7509d839df0 +a664733f3b902fac4d1a65ea0d479bb2b54a4f0e2140ed258570da2e5907746e2ac173ace9120d8de4a5e29657ae6e05 +9479722da1a53446e2559bb0e70c4e5bf3f86c0ce478eede6f686db23be97fcd496f00a9e174ceb89ab27f80621f9b80 +b707fd21b75a8d244d8d578f3302d1b32bb2d09f2bd5247dff638d8b8b678c87d4feab83fe275c5553720a059d403836 +93214c16831c6e1d6e5a1266f09f435bbed5030c3c4c96794b38d4a70871782002e558d960778e4465b1ff296ffedad8 +8648f84e18eb63dad624e5fa0e7a28af2ee6d47c28f191be0918c412bf24b5460c04bf2b7a127c472914a0741843f78b +b67f61e75d6b773a6b58b847d87084b94f3cdac3daa7bef75c2238903a84250355a986b158ff96ba276ca13a6035fdd6 +ae9b094b7b5359ee4239d0858d3755a51aba19fce8ad82b0936cca48017523319c3309409ea6e9883a41bece2077e4d8 +8d1d8e1fba8cebd7a0e1effea785a35e16b1a10842f43e2b161d75add11eccf8f942d2ae91c20eef6c1a0c813731ea9a +b82bd387458e3603782d5e2dec32ae03890a3fc156d7138d953f98eff4200de27c224f626e3648e80cd3dfc684c4790f +a6dd02a89ad1c84e25e91176c26355e21a01b126c1df4d22546159dab9d502dbc69bc0d793a017c1456516e4aa5fa53f +a9ab74a5c5459b8500beb0ad13e9cfe2656e966dc9b4f3f98bec7588023b4ddebf74e4fc722d30423f639f4ee1b2587f +b03e5f33ab7ecec12cbc547038d3fa4f7ea0437e571891c39660c38d148212d191be29e04eb2dc001b674219b7a15a9c +925df4fc6e898ca55090ad1a8f756cc5014167a042affda5b24896eeb6aac408545134920586a8e1a2b997de9758b78a +98c8580fb56ed329fad9665bdf5b1676934ddfb701a339cc52c2c051e006f8202e1b2b0f5de01127c2cacf3b84deb384 +afc3765d374c60fac209abd976fe2c6f03ce5cc5c392f664bb8fac01be6d5a6e6251ac5fb54cfcd73e3b2db6af587cbb +8e7e98fb5a0b5b50d1a64a411f216c6738baaca97e06d1eba1c561e5c52809b9dab1da9f378b5f7d56a01af077e4f8cf +b724bf90309651afb2c5babaa62dc6eac2b8a565701520fe0508cee937f4f7b6f483fc164b15d4be4e29414ce5d3c7d4 +9665160e7bf73c94f956ecb8ba8c46fe43ae55c354ce36da40ccc7594beae21d48d9c34d1af15228c42d062a84353a0c +8600ab3aa86b408ee6e477c55572573ed8cfb23689bbdadf9fccb00161b921ec66427d9988763a7009b823fa79f8a187 +b0d8d19fd1022e7bc628d456b9bd1a2584dce504eb0bf0802bdb1abd7a069abbeeccdb97ce688f3f84a229342dbc1c33 +8f447d5e5a65bb4b717d6939cbd06485b1d9870fe43d12f2da93ca3bb636133a96e49f46d2658b6c59f0436d4eede857 +b94e327d408d8553a54e263f6daa5f150f9067364ded7406dcb5c32db3c2dffd81d466ee65378db78d1c90bc20b08ab3 +b58c02781b74ef6f57f9d0714a96161d6bfa04aa758473fb4d67cc02094cd0c0f29d0527c37679a62b98771420cf638b +8cfa0a687ea51561713e928271c43324b938aa11bb90f7ffaa0e4a779b3e98899f2af59364ce67b73a46a88748c76efa +95d6d39c814c5362df69116558d81ce6f1c65fb400fc62de037f670d85f23f392c1451d43341c59bc342bc31842c8582 +af888b384c52d9e04e4db6c4e507c2037eb5857e9bcc33acf84fc3a02d93cbde8cce32141fce9f5fec715b5f24d56356 +a7822bbc3c236fd58bd978f0fc15fe0b60933a0c953db6436a233441219418090ae0c07c490a6548e319029771cdaba7 +8c53729f750922e5eb461774be8851a3f40fe42eed170881cc8024d590bf0a161d861f5c967144d15cdcdc3dc6b5cf88 +a052a25a4aeab0d5bb79bc92a6ae14b5ad07d1baca73f4f6684ccecfc7ea69bc21eadeb9510452fdba116c0502dd698f +923946b83d37f60555dbac99f141f5a232728c6eb819a37e568c8c6e4d9e97a4229fb75d1de7e9d81f3356f69e6d36f1 +8cab82cf7e415b64a63bd272fe514d8b1fa03ba29852ec8ef04e9c73d02a2b0d12092a8937756fdec02d27c8080fb125 +b1123314852495e8d2789260e7b3c6f3e38cb068a47bdf54ed05f963258d8bcabaa36ccbea095ba008e07a2678ec85a7 +a685b779514961e2652155af805996ceb15fb45c7af89c5896f161cac18e07b78c9776047c95b196362c9ad5430bcb22 +b734dd88f6cc6329c1cb0316c08ade03369a11dc33191086c6a177cf24540c7ceee8199b7afa86c344d78d513f828e81 +b0bf492fb136ecdb602c37636ed4deef44560ab752c0af5080a79c9f76a1f954eba60a0bf6ba8bd7b8cac21848c29741 +a5c74682323e85ac20f912ab9c1d6e1b9246c4c829dca40c8a7d58ec07ea0ad3524be30623f351269552f49b65a1245c +837403b9cf830fb33ecc11a7c8433e07745973c36acdeb3fc9ea8f7d8d690d462e1250b7410f79f2f4180fe8f3962a4f +b03d64b944d49c83608f2c5b9c14070c025f7568c4c33d4eeb1da31d07f0bc5897e498b35b50d557ee129f0c3c68e254 +827272aab8bf757e2483156e00fbebe1093a58070dd3af9855bbf946c7abfb9c8a850a6a8acda8c620902f391f968b8f +84c4eb863a865282d321302d06b362f8bd11c2bb0090f90ebffedd3eb3e7af704cff00d39a6d48cbea4262942e95200b +b044eb91653dc55dce75c8d636308a5a0dae1298de4382d318e934140a21ca90e8a210e06fdf93aadbbeab1c2ef3904a +a8c08955a4378522e09a351ecb21b54025a90f2936b974068e80862803e7da2b5380c4b83b4b4aad0409df8d6c8cc0cb +a763a5fb32bd6cb7d7c6199041f429782deacac22b6a8467077fab68824dd69343ebca63a11004c637b9cb3129dbf493 +8c44c8afa9a623f05c2e2aba12e381abdb6753bb494da81f238452f24c758c0a0d517982f3999d2537b7279d381625ed +8613f47fda577cd3bda7c99b80cf4b2dd40699edfd3df78acb5e456dd41fd0773bc8da6c5e8cbf726a519b9fb7646ccc +b21a30d49d7e1c52068482b837a4475568d0923d38e813cea429c1000b5f79b8905b08f6db237e2eccf7ef3e29848162 +b9bdf4915f3fbb8d84cdfd0deedf2c9dc5b14f52bf299ef5dca2f816988e66322df078da2c54b934b69728fd3bef40b5 +993b45f389f55eba8e5ba1042d9a87242c383a066cbf19bc871b090abe04de9ff6c1438cb091875d21b8c10fac51db58 +a85a95d14633d52d499727f3939979a498c154fd7ebb444b08f637b32c1caf5cca5e933a2f5d94f26851ae162707b77d +b9874c7c4be1c88a9646e0c2f467cd76bc21765b5ab85d551305f5ec0b4419e39d90703d4ac1bb01feb3b160517e97b7 +ad6771177fc78812904c90594712956357de1533a07fec3082ba707f19c5866596d624efc3e11773b3100547d8f6c202 +a79f31921134f7197f79c43a4b5d5b86736a8d3ad5af1bdf4ad8789c2bfe1c905199c5e9f21e9f446247224f82b334f8 +a7f1b6c45321222a350a86543162c6e4e3d2a7c2dce41aeb94c42c02418f0892dbd70c31700245d78c4d125163b2cd5e +92abafe3ec9dbe55c193fb69042500067eb8f776e9bf0f1cb5ab8eb12e3d34986d1204136856fb115c12784c3b8dea6e +89bc761238a4d989006ca5af5303c910c584fe7e6f22aa9f65f0718a1bc171e452c43695e9f5a591725e870770c0eceb +aa0e44c2b006a27d35e8087779411ba2f9f1966a0f5646ff6871bcf63a8b1a4a7638751b94c9b9798ccd491c940bc53f +8736fe82862b8106e7fdab7b5a964d87ec291a74b8eb1cb5a6c046a648c1b686064ef3d52297043b8940bfe870c712f8 +956a3def1942f05144d8e9c3a82fd2d3610064b53b9eefde3d5594a8f705bf8f6849eb2c22181796beffeba43cc74ee4 +af27416d00cf97d5a1f4a1b6b51c010884cceca294f1151c3b684a3f83c3c8a3c30771df1166d833cbddf6c873c400c3 +aac3b8dca2336fc4ffc63c362df461289e4bbd3418c621bde6c581d3ecedf66e2b3e523d4db39e3d8ba014577bf85efd +94c3a8167f62074e5b28c2bffe4b6ce645439a9a0c5da3ca1b3ee956590a465d6f84a8a4dbbe9070ffbd6bbc734e4d62 +95e23ba6986d25ed4451215da05bd72c5491528271726d79a94c8cb16aef1c85b190d6c5b8a3a1191c7cafbab1dccf0c +953e3dadb5ad68f7de31ac09692948655d174fe16d88b96930ef35b331da7f1dbc4c17863cd07b4ec3135b5205891a27 +915d018f18b5d63cb3301c2bb5c6e85e75a88ba80663c964d06575b6bacbbe59139d030b218ce0998271d5b28c00b26d +8c871ba3dd138a908b2f7effeea0e71df096b23e0dd47cab10b9762b250abfd1221da94a8ee884e05bdf02271fb85a04 +96bad5c6ebc3080ecbe337409ae398bbeada651221c42a43ea3b7c08c21841ddbcfde544c9b8d4772de6f2ce92c0b963 +b5dbcd0b1c44c62108841558ec0a48df4b327a741e208c38b1c052321eda6e6ad01af71d49dfcdd445ab6fa6f0c34e6d +97dba59219b69e8aef2659d1f10bbea98d74aefff1f6451de3f41be39acbac0122b8ff58b02e90554469e88911ec3547 +b7e5682ec306478be4858296f5d03364a61f3260636a4242f984d351a02e8723378496beb30c4ca22def9c9ca193ea70 +9656a7a3df4d11df3d8bc35930dff70a5e78a488ca57bba20bb06814fc390fc6c7cb3f39b22134992aad196cced577de +8b269695aa63eb56d0324ba984279dc4c88e565321f1d61d553622bd4f1910d5eff68393d3a830eb924472bd478c2aa3 +9177bcd04b28c87bc0440268b4c8995c6790cad6039594971b2c177f0e197055231e776927d3fa30d98fb897a2ba401f +ae0e943973482001c4f214b9da82e1c27e38aa254d0555e016095c537c835d3702bc2de5c67b234ab151e02b3b7a43a6 +82fc719a7d38bf4787fe1888019ad89fbf29beb951d2fece8686d2beb9119d0c8c6d13bc598748c72c70d73d488140ca +b716dc66f87eb16b95df8066877353962d91bf98cf7346a7f27056c2a4956fb65e55cb512af278783887ab269e91cd76 +81d58cd8bc6657362d724b966321cd29a1b5cdc4601a49fa06e07e1ad13b05e9f387ca4f053ed42396c508cd065c5219 +b32ad0280df6651c27bb6ddbdc61d5eb8246722140a2e29c02b8b52127de57a970e1ded5c2a67f9491ae9667349f4c46 +b68a2eb64cc43f423be8985b1a068e3814b0d6217837fb8fbfd9c786db9cca91885c86899c50a1242040b53bf304ced9 +85887515d4e371eabb81194cbc070e0c422179e01dbda050b359bd5870449c7950e6b3947b7a4a0eb68199341cc89fc3 +ac5fff3c27dfbab78eb8aad37ac31cc747a82401ebf3644a4f4f5aa98d37b8bf3b3f4bd8a3428b32a127c25c9e19d239 +86fceaa6fbf8913553a9e1e907fcb1f1986d5e401a7eafd353beefd1899d571454fea96ff5b2a21254d9fb693ec94951 +b6778bb296d3f0de2531b67d36fdbfa21475be0ca48b9dfcc38f396c41b557823735ed0b583e525a2bae1fe06e04058c +898088babeb5b9866537d6489f7514524c118704abd66b54210dc40a1c1ddb0a1edf7fe0b6e0db53b836f1828ecf939e +b27854364b97274765f0fb8d1f80d3660d469785d1b68da05e2bd1e4b8cbbe04304804d4c8aabb44cf030eba6c496510 +8c55bbf3603dc11cb78b6395ccbc01e08afcef13611f7c52956b7a65ccf9c70551bff3ae274367200be9fc2d5cb26506 +947726f73cd6281cd448d94f21d3b91b96de7ad3ff039f9153befbb5f172db9f53cacb4f88c80a3db26e6a0f7a846eb0 +a7b733a05e97528812d71cecb4f638a90d51acf6b8fcbc054787d6deb7e2595b7b8d1cbe1aa09d78375b5e684a2019bc +8d5ca6d161341461544c533314fe0a6655cde032c2d96f0e4ea7e41098b8b39fa075d38e2d8c74e2d0308f250d6cf353 +b960e9f081393e2260b41f988935285586a26657a3d00b0692ea85420373b9f279b2f1bb2da2caae72dd2e314045f1bd +852a49c7388c10821b387c6d51617add97ba72485f52be95d347bac44c638c92e9c6a44ba0d32afc4d59178a497d944a +8412162a65147e1334ad5af512982b2b48eef565682b3f3e0bbe93fbc5e1103db9375a0c486bdb1b2c57e4cb3a8e7851 +8f52c3eb5d4f1e1e82cfd2b291d4910195427603b796f6c311deb35ef14a01a57a9e6cad39619ad108f3e86f384f9e1c +88d221088f2bf0103c53e44d0d96cd7881ec2b0a965db9121a47481771a8b796edd5ac23c4f9c208a171dab301f7d3bb +b49c3235e8b3617ed08a1891b9e2bcb33dbdacceb94ca96330555b7e00904fe6a749ced9312b8634f88bcb4e76f91cb1 +a85834215e32f284d6dfb0cbfd97f6cffc7b9d354e8f8126d54598bb42d7f858a2b914cf84fa664069632db2ff89a332 +aa3d48eb483c6120c27d9b3e3d0178c1c942632ff54b69f5b3cfbc6ad4ff5b2b9ce6eb771fd1eea8edf4a74c97027265 +a446cfded353cdd9487783b45846402b973cdeddf87e2bf10cf4661610fff35743cc25e8d3b5771dcedfb46b018a5d18 +80998377b3b393ef3073f1a655ad9d1e34980750e9a5cfb95f53a221b053ddb4d6985747217e9c920735b0c851d7551f +a35ac469790fac6b8b07b486f36d0c02421a5f74ea2f0a20ffc5da8b622ac45dfccabfb737efa6e1689b4bd908234536 +8fb1f6d8e9c463b16ac1d0f36e04544320d5a482dd6ffaec90ea0f02b4611aaca984828bf67f84dcc3506b69af0a00a1 +b6e818d61aea62c5ed39c0a22ccbb327178feebdabda0c9927aa1549d2c5bb0637785c4aed2a6d9a7b4989fa8634c64a +b4e7208d16018bf67caafe996d436113eac619732e3f529a6efb7e6f094d8ebea55b7be0e122be075770f5957b6ea6f0 +b691d38b552befac61f6d367287c38d01fec73b7f2efdb6713ca30314a37fb7c177eb111fe6bee657f2681014e07630a +9817587e418e6e7e8e97ae27067f17b55d25dfb14e98f63f530620c855d9a348c9fa571c8508e2741f902f8b9fdc0c5c +b6a6e5ca779ba140bf1d84cd5394ede8262f7479637ec0087a4b152243a1774ba916d8115ce759a3bebd1b409de5f2fc +b53d1c84ad766ff794bf497db3228efd2cc8ed5fc1958d89c1126efdff361610ecb45ea8e329b39035ab00a66c1259c7 +adc31333c507c8e0f4aa2934fcdca57fd9c786722a50dbd5404e129541f7ac182cc7373bf14e1e4e06e6cf94b31b90eb +a82b7fde4642d982d95cec669efee140ad797a2442c7f6620580527d163accbf021b893446cbb8038ea82fe25b15d029 +91f7acf8a8903979afa281646fdecb54aa4d2ed905748e156e92f0910de268fa29d67107d40863935d677d1de8039be2 +86fea71c6d43a7d93216a92fc24dfce8521fd4534a9558b33762d002081247867a6eff54cad7116023277fb4049403ad +8ae5369a7f9f4c91f3be44b98089efd9c97c08f5bb4cd8b3150c115ecd86288fa0865a046a489c782973a111eb93966e +b6fb9e829aa2c81c2d9eac72bb2fd7f3a08e0cd763532c2ce3287444d33cf48b3621f205e9603ec58525934b61a795a9 +83e35ca808d84e41fc92115e9f6e283e928c3a614e6dfc48fe78c33b6411262e7bfa731eadb1e1937bc03cff60032e1d +832fca5196c95098ad47b7d24ba2f9d042e1c73ad2273edd1c2ce36386796ccc26e8567847697f3fcc2a0536a2a2087a +8fdb7038bc8f462ab2b76bf7053362f9c030019f1b6105cf42219a4e620ecc961e3eacb16a8e581a562a97f1418b0128 +8d3a5a404b51b1ad8ce3b23970e0d5cc57b573922341008e3a952a1dd24a135e19e55b79d86a70cfd82e1c0e9630f874 +ba00c025c1c21c57c03cdfc0bfd094b35422281ff0a64b68b240617aa58c6b18800af5f2047d3ff9068bbe987d6c7980 +b468f0dd51964b3806b0aa04f3fe28a035e8f5567fc7d27555be33d02701a838b8dbfe1348b6422c4eac46d2c75c40c7 +8a73a18c97da9958903c38584b08d0e7e26993a5d9b068a5e0e1ee0d8a873942745cf795f94f7a3d3ba88790a9fbb2f6 +953a0a40c2c8102723736854d13b228698c14a02d85c8d2e61db1a768019ac305faf0d5db62ac976430ce087a5b20f1e +8998219da6b34f657cb8a621c890a52cb98c2bc0f26f26e2af666eebeadadc5e8bdf4f830a91d04aca8ce186190152c8 +8941e08c3155ad432236ed05460420a05dd0aaab30477493ffb364b14c00ea5b9183d30d3442b6321d2d20c36e4f5c7e +93f293ff7fb56cf5b03aee6f3ad2ad78444398ed5b3be56d7bf5b56b5aa5a2b980d13895dd57a5726d1b067c20cc55e2 +84a16f313e3f75e31824f58d19ab24c6611fb4c75140a7cadc3c166f68819547c1d0ff7f7d13f5d8ae30dff1d80e2aa4 +b6e3e830b15039d3e28b08f5465bb089eade11ee3bd80afe39e010df7db1fcf0c56d698717677a41ddbc91eeaf6544d3 +95e928e6dfff51351281568ae72da7d1edeb6e9fe01f30af0499e7505ba35a22b5bb919d41bb809a432dce83f3977663 +aabeeb60ca46f9b0232ff82ea7766dcab8cc5aaf9d23539f30174f9486640bc9312868ca493b59b314519fc399973e47 +b393a11e957d0bbb3ecf617b075b5906a3450b348e62916c04791b366f0a7397cccd6648440ac544bc30526e1f95aad8 +abb5bfc3964a6d246da60bd809d0ea6daf4f8222efdc12ceb6730194e85f413ee7eb03bae300abf7ea900dbbc3d08971 +96c1bd1d1d216a4bfbcf000c123f296c0d31e1684e9e3884c14df23bf528c8d599f82bb98fcea491716b617216a8e0be +92d1e570a56f1741fd9f3d9f488cc336421c6256c14a08d340a63720be49b0029e3780e3e193a2e22bf66cc652fa22a3 +8769c08551e3a730e46f8e5d0db9cf38e565a001dfb50db3c30fa7fa0e98b19438edc23c6e03c8c144581b720d7b33a4 +b850bd67fdf5d77d9288680b2f6b3bc0f210580447fb6c404eb01139a43fccb7ed20051999ae2323ea5a58de9676bfb4 +80285da7a0aaf72c4528a137182d89a4db22a446e6c4a488cf3411937f4e83f7b00ec7549b0b4417682e283f91225dfe +80520368a80b97d80feb09dbc6908096c40ff7120f415702c1614d7112b0b57f6729581c71f4a3ce794ac959a46494ff +9817b4c27a490b1cd5a6337e7bc7e8005fa075dd980c6bf075ddfa46cd51cc307ad1d9f24e613b762a20fc6c877eab41 +ad66bda1a3034ec5e420b78107896ecf36126ce3ef9705163db259072dfa438c6107717a33572272062b9f60cb89557c +876114ef078c2915288e29c9abe6b0ad6a756b5ee2930ba1b8a17257f3f0557602d1225e8aa41ce8606af71ada2a971b +aa3d6cde4c3b9d3d5d0c77a33e67f182a3e1cf89b0921423b2024236171955b34afc52b1f25b1dad9da9b001371771d7 +984d3e3a72412d290e3459339757af7520d1739c7af0cbcf659c71999328db44f407d92e8a69fea11625612c49eac927 +ae890d0faf5bd3280dcad20a5f90e23a206661be8842375fea2ab22aadc500849ffbc52fe743b376d46bb926cedae6a6 +b1f231f3f4d710c3fe80099faeb56dac67c1baf53b8fe67a9920fe4f90e52cb9a4bf19211249a6456613b28efe337f18 +8caa54b418ba609d16520af3dff2e96d5f2eeb162c065a1763beb926547b2cfb3ae41d738db2c5681a9bc8bc9e6b9a1a +932157ff56c5ac29cf6cf44f450c882b3acfbb9f43d12d118da3d6256bde4e6eb3183aea304ab6967f37baa718ffec99 +9360bed8fc5b6aac36aa69473040689bfc30411d20ffb7275ef39b9ff5789f9055d149383ce9f0f7709a1f9d683adbfe +98b5b33209068335da72782179d0c7aeeabe94b5560a19d72088fe8323e56db7ce65debe37a97536b6b8a0ca3b840b61 +89a385c11be40064160b030a1bb28c3921fc8078522618a238c7ea0f86f34717ed9af9b4e2e20f5128e5f7fc66ad841e +b615703cbc64b4192990cc7e4903b74aed6a0076ce113b59ef7719197ffa46fb29eb78ca56b49873487432d0625c0faa +90f0d77abae9d3ad73a218e5ccec505ad108ea098451461567ae8ef9661606ca8e78df53b5d628b20b7037bd24622330 +92e0e7cc4dfadc5fa0ee6da0c8de0493030db6e54ba0317f52f232a6708b732068b6077bd13a17eb7eb40b88368085b5 +a24dad20094985bfccc6df1343506ed3bf9dcbdf4b2085a87627a5d71f7568db067304e465f8f380c5c88e8a27291a01 +8629a45a10619354c84bdc2f6c42f540eab5a46f53f2ae11970433d7a2aef007897590bf31dfba1c921614c6d6fe1687 +84ac64040d4206f82b08c771f375da4b7d752e41d2aa0da20ce845f6bc1b880a855d3ee966bca19b8ec327b4b43e7f0e +9608e6050c25996c052509f43f24a85cdf184135f46eaac520a9a6e78e0d44a6cee50ebc054048c708aefde8cd6651c2 +a32032b0e0d7cc35e480c328f315327f9385adb102a708c9ba637878deb74582ae26bb6d6e5f8c9e3a839b0e0154b82a +b7e3c78d63acc6564a49e9f00b0a820b56d4f37a2374af1f7f1d016268011df9e7af0670ed2b0eee961f15aa948328dd +8b88bfdd353acc91ad0d308a43e5fb40da22c228f2fe093c6d6904d70f69c6203f56636ed898b05df51d33f1095ef609 +b1d7a430c51fc857af55047683fc18c453b013527196c5e1bf776819a3dffca802217e9249ae03f084e2ea03ad67fcc2 +80558e28a819ddb5e72e97c54be0f57c173ccf78038d360d190b7f1350a19577b8e3f43fa2f7bf113a228cd3b965b2e4 +b4b2ec44e746c00dfc5661ba2514930934fc805cdc29adc531c02d28ce3cc754414b0485d4ee593232cd1175f357ad66 +b57cee5d32835f76572330f61ccd25a203f0e4a7e5053d32965db283aad92f287645533e8e615137208383ec51b1fd99 +930256086b419a8a6581c52590d0dbd9f8a3564c79424198fca3866b786df2f6098a18c50dc4abd20853a7184b1ce15d +8e75fd01181cffcd618a983492390f486e8c889972a46c1f34a4e1b38f384e8e4efc7e3c18533aa2057da9f9623e2238 +b375d927dd988429f9e2764e5943916131092c394fce13b311baa10f34b023dd3571da02553176091a0738cc23771b9a +b9e28e4c0d0477518034d000e32464852e6951c8db6f64ccdb1d2566f5094716213fbf2fc0e29ac88d0e79f725e3c926 +963981e99392afbd2b8318d5a6b2b0cc69c7f2f2f13f4b38dddbfedb2b0eaf0584aecfcbda20a4c60789c15d77970a58 +a7804e1977aa77c263c7c001afa6cf568032dea940e350d6a58ce4614f1a91c13ae1c78bfea740c229dce2444556976a +8787204177da3cde6d35cd3497fa8774d244f9faa9f4bd91b636a613a32ce2ea0326378cf9c4cf475e73ef751b355c4b +895aeef46a07152a04ec812f1aa1fd431389fa0ef6c6e96a5b833e70ea14073bc9984757a8ee456dbec9788e74e6f0ca +8d17f0e5826783440d1f0ec868003510a4d9952bfe4a638e44a36d94482ac18ba70ef7ff773bdf7a3b62d714dcf0fcba +810d5e36b31310b2e054a666d3b3f7ed16dfcb1765532d87ca2a3920316f0187303c27dd113db145d47e8961062a6c03 +b4e2fb48ae04cf8580bb6a28095076c9b95e5f13122b917328f334d4ac8a8648ce442919e28319a40148987350ab5303 +b85549a313544fa1eb3ceb78473b7d3d717fc85b808de7b79db7dbd0af838ebb020622a7503f1cbacab688dddb648f84 +80665adee057088eae827a5fe904ec3ad77d8843cdce0322d535e0659b4abc74a4d7ddd8a94c27f2def5c34ac2c038ee +ad72fc19c2ce99b5b717e35528fe7d3ac8add340b02ebeb4889d9a94c32f312a0b45ea84d21c54f84cc40ee4958b72e1 +99d530c843dff89a47a5ee8c87303ab18f8a82b0d5b808fca050354b35da5c5a5594d55921c6362d6cc917d75bdc18dc +99c7286c293e1be21c5b2a669dfdfcd5aa587105d2886fc5a8eaf8984da4e907f7d7b8c2362d64a4f1621b077a2a08a0 +b4a39e1a9ed5d80c9563c3ca3fadf76f5478c63a98f4346a61b930c9c733e002f3ff02bc16abfdb53d776184cc3f87ba +9378ea71b941979404c92d01fb70b33fa68d085bf15d60eb1c9fc2b5fcdee6379f5583389a3660a756a50019a2f19a69 +b68e17344a2bc45b8e2e19466b86dc139afefbf9bad2e2e28276a725099ebac7f5763f3cb52002261e3abe45ef51eb1a +819e64dc412b2d194d693b9b3157c1070a226af35c629837df145ea12ad52fa8eabd65b025a63c1fb0726207a58cdde8 +a5e8ff8748419466ff6df5d389125f3d46aedacf44eaf12cbfe2f68d218c7d5ab6de4a8279d13aecc25f3b1d98230894 +91560d54a9715cfda9cf7133ae51c432d0bf7fcbaeb468004994e6838bfc5ddcfa30e4e780667d0c4c0376780b083017 +ae8adb3309cc89d79a55ff74f129bb311fe4f5351a8b87600a87e0c3ba60825f71fccf67eadcf7e4b243c619417540fd +8d92cc1a6baa7bfa96fbce9940e7187b3d142f1888bdcb09bb5c8abf63355e9fb942ac4b4819d9be0e0e822d3e8e2e08 +a6e8b79fdd90c34735bb8fbef02165ccbe55ea726dc203b15e7a015bf311c9cac56efd84d221cc55eaa710ee749dbdfe +a409b151de37bddf39ce5f8aa3def60ee91d6f03ddd533fce9bf7bdbeac618cc982c4f1ffbf6e302b8353d8f28f8c479 +b9693975ef82171b3b9fc318ca296e4fe6110b26cbdfd653418f7754563fa7b6e22d64f8025ee4243483fa321572bfe4 +a039ebe0d9ee4a03ade08e2104ffd7169975b224061924cca2aae71464d250851e9f5f6f6cb288b5bf15df9e252712a6 +b27834db422395bd330e53736a001341ce02c9b148c277dabac67dc422741bfa983c28d47c27e8214cd861f2bad8c6f6 +a2bafaf4e2daf629fd27d7d5ac09fb5efc930ff2ae610f37519808683aa583fe1c6f37207daf73de1d8a164f79a0c981 +b856cee1cfcf5e50db9af4ab0aed3db2f43c936eaea369b5bba65582f61f383c285efbda97b1c068c5d230cbe94f7722 +a61ab205554c0550fa267e46a3d454cd1b0a631646b3df140623ff1bfffaa118e9abe6b62814968cc2a506e9c03ea9a0 +8c78edcd106377b9cbdfa2abd5278724aed0d9e4ae5869b5d2b568fdabb7804c953bae96294fcc70ef3cd52ba2cbe4ed +8570869a9bbf6cc84966545a36586a60be4d694839f367b73dfc40b5f623fc4e246b39b9a3090694aa2e17e652d07fd1 +a905b82c4da8d866a894da72315a95dc98faa3c7b3d809aef18f3b2be4801e736a1b79a406179e8cac8f74d27e71ac52 +a8eb8679ff1a64908515f6720ff69434cb33d63aeb22d565fde506618908b1d37585e3bd4d044fd0838b55787af06b42 +af4d86b2fbd1684a657dffe4210321a71e6ae560c144d44668d1f324dc9630e98348c3d444622a689327c1a59cc169dd +80359c6eab16954559ab0e6a1fee9a0526c45d3cae1a371159a2e3aa9b893afdc3a785c9559a5fd9cd8cd774234bf819 +8d4e5ff81eb5d17bbe8ae6416538ca51a9427ce142b311f5cbb14febbbbb9c1ffc6489fd625b9266264c366c12a9d997 +92e181c66489c5fa063ba2a1a354b6fd3439b8b4365a8c90e42e169bfaa1fb5766bf3e0fe804399d18bc8fbcafb5c3b1 +a9ddf229360a095393885083716cb69c819b2d7cfb100e459c2e6beb999ff04446d1e4a0534832ae3b178cbe29f4f1d3 +8e085ef7d919302a1cc797857b75cff194bdbc1c5216434fa808c3dea0cf666f39d9b00f6d12b409693d7a9bd50a912c +916dc4dc89e5e6acf69e4485a09fc66968f9b292eac61a146df1b750aa3da2425a0743d492179f90a543a0d4cd72c980 +b9cbf17e32c43d7863150d4811b974882da338cf0ed1313765b431b89457021dd1e421eeaa52840ef00551bb630962dc +a6fb875786daec1a91484481787093d8d691dd07e15c9c0c6ae0404bf9dc26083ed15d03c6d3fe03e29f28e20da21269 +a870fcb54b9a029e8086de9b08da8782c64ad2cc2e7fdf955b913d294038bb8136193256b85267e75a4ca205808a76b4 +99883f057e09b88bf0e316f9814c091837fd5c26eeb16fec108c9fed4b7a2bd1c783dac0e4242b5a906621ab606c1e50 +85d89069ca3190577dab39bbec43c16bf6dbca439ad3eebd8f5e9f507d84c3c43e77fd6323224582566a3aa2c8018951 +9363ba219e0003f6e8a9d8937b9e1449e4b2c5cd57194563b758bea39deab88778e8f8e4f7816970a617fb077e1e1d42 +820622f25553c035326145c1d2d537dc9cfd064c2f5bdf6d4ec97814de5fe9a0fbd443345fa2ea0a9d40d81d3936aa56 +87e31110aaf447e70c3316459250e4f7f8c24420c97828f9eb33b22107542c5535bdb48b0e58682dd842edea2886ff08 +95bf80cac6f42029d843d1246588acb40a74802f9e94b2bf69b1833936767e701ef7b0e099e22ab9f20f8c0c4a794b6c +a46ecf612b2763d099b27fb814bd8fdbaee51d6b9ac277ad6f28350b843ce91d701371adfaaf4509400dc11628089b58 +8604decf299fb17e073969708be5befeb1090ab688ad9f3f97a0847a40ea9a11bbcfc7a91e8dc27bc67a155123f3bd02 +8eb765c8dc509061825f3688cb2d78b6fef90cf44db33783d256f09be284bc7282205279725b78882688a514247c4976 +b5c30b2244fa109d66b3a5270b178960fdec47d31e63db0b374b80d2b626409eb76d2e8d1ebf47ef96c166743032fc5e +aab01e76290a7e936989530221646160bf8f64e61e79282e980c8c5dcaaa805ff096efd01d075a2c75917a3f4bf15041 +b9d79671debd0b83d0c7c7c3e64c0fb1274300564b262771f839b49218501e7f38ef80cae1f7e5a3c34acdc74c89dab6 +92c0eaceadf036b3b9dfd2712013aba3dd7c30b7760f501f52141618265baa31840fe77850a7014dc528f71f8cf39ce6 +b3cdd098059980455dd5b1c04182df1bd12fa844a866f02a9f8a86aab95b59945baa9af99f687410bffc5b07153cb23c +b361b73a62f71256b7f6ea8e0f6615e14fc5a06ee98b928ab3c9dd3eef9d9d30070e9855c82b7facb639cacb3401e01f +b9c85fc0f25a3271cf28b1ca900078eaaa66cbab0a3e677606e898ac32781a2dfce4d9cbd07404599e2c3c02fa161c9d +ac5b4fdac2a0b2e6430d9fc72bde4249d72183b197fc7347bb1546ae6f544426686bbe0caec3ee973b6836da5e831c44 +b675aebf24b92e398e166f171a6df442b3f5919b6bee192f31675a5e8eeb77d34c6590a6f0c0857417e0f78cfb085db8 +a9bef942044d8d62e6a40169f7dc7b49e40cd0d77f8678dd7c7bae6f46c46786f9b1e319a3fa408f22a54fd2a4d70804 +a20d19cd917d5102ae9ca0cf532127d2b953aa3303310e8a8c4b3da025dded993a47e3a28e6b02acfadb6d65dc2d41a3 +a47fdb04059b83b2afb86a47b2368bbd7247c337a36d3333b6e5ef2cc9476a92c4907e4c58a845c9ef9b497621e0b714 +94a9e9ffc14b411e11a4ffa59878d59460263589003dc7b6915247c549f67feede279bf3645fdd92379022fb21e3caeb +b92e1177dd9ecdaf1370c71b14954219cf0851f309bc216d5907a4e2e84e0df3457018224150c142cc6bf86644bb4b73 +8bc57fadd68a265b7df9b42227a9c0968db7b1bb50dc12f7d755505779f1ff2c408672b3091e903366acc9ce15d19fb6 +b6b5efbe1ac4e1bd2e8447c45000d09397b772ca5496acc447b881022608a41c4f60388814607a01890190105bee7be3 +95f7c85fd614df968f8ccf8d086579c9e1cec4644ecf06da26e3511cb39635a7326b3cec47bd51cf5646f1c660425e9c +b81765fb319bcdc74b4d608383ccb4af7dd84413b23af637be12e2827a75f7e4bcd14441cf979ed9038ae366fbb6f022 +a120ea76cda8c6c50c97035078f6648afe6537809bdba26e7c9e61de8f3070d2347160f9d34010effbf2ec7e94f5749f +92c1b8631953b40d3cc77eee2c72a064b999c09a9b92c11d8fa7b4072966273901c9dba25f9f79f384d9f11a56f3fc7a +a4b00dc0ab67b2300abc9c516e34daf444d6497b066a90cfe3381ed2812304ed37b14f3b948990443dc6c1cf1bed460c +a9e9f7e13c9f031bc7b9e6f1417c7abcc38894fe7d3f54869ee277afd2efa3e6fb50757dd36c8c94d591e0abdea322cc +84f3e98f831792b5ad14bcfe62a4c9f296476c6087c4c1ec7767fc642fbca141ff6a3deeb8b4d4106a9cda5a9937eea0 +8eb1a7931bbea9a714226fd74b0100ab88355287d9b0a349c095e9b5809b98f237ffd706bce7d67a770da355fb9cec7b +9738ef8739e1742c1f26b51a1621be0b89d37406a370c531e236f635c7064c661818817bb3858908986aa687b28b21be +a9cf3ce8501b003ccaf57552a4c4ec31081e44526d3aa3791d3dc4a7e438a357c0956f93c500356186d8fd4588ffac5e +a7af6a219cca59225839a9de5b19263cb23d75557d448bc7d677b62591a2e068c45e5f4457cceb3e9efa01d0601fc18a +972a24ece5eda7692cbb6fb727f92740451bc1281835e2a02931b2b05824a16b01dbe5edd03a0ed5b441ff25a5cc0188 +b21d1ec7597ce95a42f759c9a8d79c8275d7e29047a22e08150f0f65014702f10b7edce8c03f6e7ab578ce8c3b0ec665 +a13a1c7df341bd689e1f8116b7afc149c1ef39161e778aa7903e3df2569356ad31834fa58ceb191485585ce5ef6835c3 +a57bdb08119dc3bc089b5b2b5383455c4de0c2fcdac2dcfa21c7ac5071a61635ff83eceb7412f53fab42d1a01991de32 +b2968748fa4a6921ee752d97aa225d289f599a7db7a222450e69706533573ded450380c87f8cdd4a8b8c8db1b42b5c97 +8718ec04e0d5f38e3034ecd2f13dfde840add500f43a5e13457a1c73db0d18138f938690c8c315b5bcbeb51e8b9a2781 +82094789e26c4a04f2f30bdb97b9aecca9b756cbd28d22ab3c8bed8afc5b2963340ddfc5a5f505e679bf058cbc5dcbb8 +a35b8a566dd6ab67eddc2467906bffc76c345d508e52e9e4bb407b4f2b2c5f39b31d5a4bf5022f87bf7181dc6be2fe41 +a8c93b1e893d4777c0e3a1b4bef3be90c215781501407c4011457fc3240e13524b4d2bea64a6d0a3efe3f3b0dae9b8ab +877095ad18b1e5870818f7a606127ba1736a0b55b0dbcd281ec307c84b08afc0c9117e3a880fe48bfc225fbf37671a97 +84405ee0421ed2db1add3593df8426a9c1fcc8063e875f5311a917febc193748678dd63171d0c21665fb68b6d786c378 +a52cdc8209c3c310bed15a5db260c4f4d4857f19c10e4c4a4cfe9dfc324dfac851421bb801509cf8147f65068d21603c +8f8a028a70dda7285b664722387666274db92230b09b0672f1ead0d778cee79aae60688c3dfd3a8ed1efdeda5784c9d4 +a0be42fecc86f245a45a8ed132d6efc4a0c4e404e1880d14601f5dce3f1c087d8480bad850d18b61629cf0d7b98e0ae0 +83d157445fc45cb963b063f11085746e93ab40ece64648d3d05e33e686770c035022c14fdf3024b32b321abf498689ad +8a72bbf5a732e2d4f02e05f311027c509f228aef3561fc5edac3ef4f93313845d3a9f43c69f42e36f508efcc64a20be0 +b9ca29b0ec8e41c6a02f54d8c16aebf377982488cbe2ed1753090f2db4f804f6269af03e015d647a82ef06ffaa8cba6c +b4df3858d61bbb5ded1cf0be22a79df65ae956e961fbb56c883e1881c4c21fe642e3f5a0c108a882e553ac59595e3241 +86457d8890ac8858d7bab180ef66851247c2bf5e52bf69a4051d1d015252c389684fcc30bb4b664d42fbf670574ab3a3 +86d5576ea6dfa06d9ebce4cd885450f270c88a283e1e0d29cab27851c14ed2f00355e167b52e1539f1218ad11d8f13dd +883ad1364dc2a92388bfafaa9bc943c55b2f813525831e817a6208c666829a40455dde494eba054b2495a95f7ce69e8a +8942371e6925231c2c603b5f5a882d8404d39f0c7c4232557c2610b21c2c07f145466da798ea78b7932da2b774aa3128 +a799eb71496783cc7faf12c9d9804bf6180699a004b2f07fc5cc36840f63ce7eee7dde9275819a9aa3f8d92dc0d47557 +8eb3fb5c769548ee38c7882f51b959c5d5a42b5935269ccf987d6ddbb25a206e80c6000bcc328af149e0727c0b7c02c0 +8f3910d64e421a8f2d8db4c7b352ba5b3fc519d5663973fea5962efe4364fb74448770df944ef37ffe0382648fb56946 +b41413e0c26ff124cf334dab0dc8e538293d8d519d11cc2d10895a96b2064ac60c7da39f08589b38726cffa4c3f0bfef +b46ef2eb10abae0f35fa4c9c7ee2665e8044b8d9f91988a241da40fd5bbc63166925582151941b400006e28bbc5ba22a +b8baa8b4c420bb572a3b6b85479b67d994c49a7ebfe1274687d946a0d0b36dfed7630cfb897350fa166f5e2eff8f9809 +964b46d359c687e0dcfbdab0c2797fc2bd1042af79b7418795b43d32ffca4de89358cee97b9b30401392ff54c7834f9f +8410d0203d382ebf07f200fd02c89b80676957b31d561b76563e4412bebce42ca7cafe795039f46baf5e701171360a85 +b1a8d5d473c1a912ed88ea5cfa37c2aea5c459967546d8f2f5177e04e0813b8d875b525a79c29cb3009c20e7e7292626 +afaab9a1637429251d075e0ba883380043eaf668e001f16d36737028fded6faa6eeed6b5bb340f710961cee1f8801c41 +aef17650003b5185d28d1e2306b2f304279da50925f2704a6a3a68312f29fe5c2f2939f14e08b0ba9dee06ea950ad001 +97bcc442f370804aa4c48c2f8318d6f3452da8389af9335e187482d2e2b83b9382e5c297dce1a0f02935e227b74e09a3 +8a67a27b199f0bcd02d52a3e32f9b76a486b830ec481a49a4e11807e98408b7052b48581b5dd9f0b3e93052ec45dfb68 +b113bf15f430923c9805a5df2709082ab92dcdf686431bbad8c5888ca71cc749290fa4d4388a955c6d6ee3a3b9bc3c53 +8629ca24440740ce86c212afed406026f4ea077e7aa369c4151b6fa57bca7f33f9d026900e5e6e681ae669fd2bd6c186 +933a528371dcecc1ec6ded66b1c7b516bd691b3b8f127c13f948bfbcda3f2c774c7e4a8fbee72139c152064232103bdf +8568ddd01f81a4df34e5fa69c7f4bb8c3c04274147498156aec2e3bd98ea3e57c8a23503925de8fa3de4184563a2b79e +8160874ec030f30fda8f55bcf62613994ff7ed831e4901c7560eac647182b4a9b43bfaff74b916602b9d6ae3bfcaf929 +ae71c48d48cf9459800cdf9f8e96bc22e2d4e37259e5c92a2b24fbe2c6ca42675e312288603c81762f6ceb15400bc4c9 +b05f39bb83fda73e0559db1fd4a71423938a87ad9f060d616d4f4a6c64bf99472a2cbfb95f88b9257c9630fc21a0b81f +80c8479a640ed7a39e67f2db5ad8dfd28979f5443e8e6c23da8087fc24134d4b9e7c94320ffa4154163270f621188c27 +9969ba20ee29c64cb3285a3433a7e56a0fe4ddc6f3d93e147f49fe021bed4a9315266ebb2fb0eb3036bb02001ae015e6 +a198c89fef2ab88e498703b9021becc940a80e32eb897563d65db57cc714eaa0e79092b09dd3a84cfab199250186edcc +8df14a3db8fe558a54d6120bad87405ba9415a92b08c498812c20416c291b09fed33d1e2fcf698eb14471f451e396089 +81e245ef2649b8a5c8d4b27188dd7e985ef6639090bdc03462c081396cf7fc86ed7d01bfe7e649d2b399255e842bdc21 +8659f622c7ab7b40061bcf7a10144b51ad3ab5348567195924f2944e8c4ce137a37f1ba328e4716c10806f3fb7271689 +a575d610fc8fe09334ca619ecdadf02d468ca71dd158a5a913252ca55ea8d8f9ce4548937c239b9cb8ab752a4d5af24a +94744549cd9f29d99f4c8c663997bdfa90e975b31f1086214245de9c87b0c32209f515a0de64d72d5ef49c09b0a031fa +80a8677862b056df59e350c967a27436c671b65d58854e100115bac9824ba177e94c2a1bfcaa191a071b9cefdbee3989 +91be9a5504ec99922440f92a43fe97ddce2f21b9d94cd3a94c085a89b70c903696cec203bbab6d0a70693ba4e558fb01 +8c5a0087bcd370734d12d9b3ab7bc19e9a336d4b49fc42825b2bfedcd73bb85eb47bf8bb8552b9097cc0790e8134d08c +933aa9e6bd86df5d043e0577a48e17eea3352e23befdbb7d7dcac33b5703d5ace230443ac0a40e23bf95da4cc2313478 +984b7ee4bd081ee06c484db6114c2ce0ba356988efb90f4c46ff85ed2865fb37f56a730166c29ef0ae3345a39cdeae7a +ae830f908ea60276c6c949fb8813e2386cf8d1df26dcf8206aa8c849e4467243e074471380ed433465dc8925c138ea4c +874c1df98d45b510b4f22feff46a7e8ed22cfc3fad2ac4094b53b9e6477c8dfc604976ca3cee16c07906dece471aa6c6 +a603eb60d4c0fb90fa000d2913689126849c0261e6a8649218270e22a994902965a4e7f8c9462447259495fe17296093 +a7c73d759a8ad5e3a64c6d050740d444e8d6b6c9ade6fb31cb660fa93dc4a79091230baccb51c888da05c28cb26f6f3f +a4411b79b6a85c79ea173bd9c23d49d19e736475f3d7d53213c5349ebb94a266d510d12ba52b2ac7a62deaaaec7339b8 +943b84f8bbcee53b06266b5c4cd24d649d972593837fe82b0bf5d5e1bbc1a2bf148e1426c366d7c39ab566b10224cadc +8300012096a8b4cefecc080054bf3ceb0918162ba263c6848860423407796b5eb517170c0bad8e4905ac69a383055a21 +8244a1e3ad41908c6f037e2f8db052e81f281646141334829f36c707f307448b9ab79a7f382a1e8d86f877c90b59271c +8eca1b74687802ecc36a5d39e4516a9dee3de61a2047252d9ed737b49e0090c386e9d792ac004c96337681c7f29a16ad +b70fa47535f0524835039a20036c61e77f66146ad79d3d339214d8744742db41ceeb577c829d000011aeafbb12e09579 +84b3abbce48689f3adbb99889c7fd1f3e15ab455d477e34f5151c5c1c358ed77a5b6a581879f7e0f1f34106e0792e547 +ab45ecb58c0ef0dbce3d16afc6ac281e0d90ec48741ea96a141152647e98fcc87f3a3ff07ba81f3179118453ce123156 +90d231a145ba36a59087e259bbfc019fa369201fcfeaa4347d5fd0a22cd8a716e5a797f3cc357f2779edb08f3b666169 +a4f6074d23c6c97e00130bc05f25213ca4fa76c69ca1ace9dece904a2bdd9d987661f5d55023b50028c444af47ff7a08 +933af884939ad0241f3f1f8e8be65f91d77ac0fb234e1134d92713b7cfb927f1933f164aec39177daa13b39c1370fac8 +80d1db6933ce72091332ae47dc691acb2a9038f1239327b26d08ea9d40aa8f2e44410bbda64f2842a398cbe8f74f770f +a7a08605be2241ccc00151b00b3196d9c0717c4150909a2e9cd05538781231762b6cc6994bebbd4cddae7164d048e7b2 +96db0d839765a8fdbbac03430fa800519e11e06c9b402039e9ae8b6503840c7ecac44123df37e3d220ac03e77612f4e4 +96d70f8e9acd5a3151a8a9100ad94f16c289a31d61df681c23b17f21749c9062622d0a90f6d12c52397b609c6e997f76 +8cf8e22273f7459396ff674749ab7e24c94fe8ab36d45d8235e83be98d556f2b8668ba3a4ec1cb98fac3c0925335c295 +97b7e796a822262abc1a1f5a54cb72a1ea12c6c5824ac34cd1310be02d858a3c3aa56a80f340439b60d100e59c25097d +a48208328b08769737aa1a30482563a4a052aea736539eceab148fa6653a80cb6a80542e8b453f1f92a33d0480c20961 +b612184941413fd6c85ff6aa517b58303b9938958aa85a85911e53ed308778624d77eadb27ccf970573e25d3dfd83df7 +b3717068011648c7d03bbd1e2fc9521a86d2c3ae69113d732c2468880a3b932ebec93596957026477b02842ed71a331b +a0ad363e1352dcf035b03830fef4e27d5fd6481d29d5e8c9d51e851e3862d63cdcbaf8e330d61c1b90886921dac2c6fd +8db409fdacfa4bfdaf01cc87c8e97b53ca3a6e3a526d794eaad1c2023f3df4b888f1bf19fee9a990fe6d5c7c3063f30c +b34d6975310ab15938b75ef15020a165fc849949065d32d912554b51ffa1d3f428a6d1a396cb9329367670391de33842 +9117285e9e6762853fc074b8a92b3923864de2c88c13cea7bab574aaf8cdd324843455d2c3f83c00f91f27c7ecc5592a +b4b2e8f190ea0b60819894710c866bf8578dd1b231ae701d430797cc7ede6e216e8ca6a304f3af9484061563645bf2ab +8c493c6853ab135d96a464815dd06cad8b3e8b163849cdefc23d1f20211685753b3d3e147be43e61e92e35d35a0a0697 +9864d7880f778c42d33cf102c425e380d999d55a975a29c2774cad920dfddb80087a446c4f32ed9a6ab5f22ec6f82af0 +90f67fe26f11ca13e0c72b2c2798c0d0569ed6bc4ce5bbaf517c096e7296d5dd5685a25012f6c6d579af5b4f5d400b37 +a228872348966f26e28a962af32e8fa7388d04bc07cfc0224a12be10757ac7ab16a3387c0b8318fcb0c67384b0e8c1a4 +a9d9d64bba3c03b51acf70aeb746a2712ddafe3b3667ae3c25622df377c2b5504e7ab598263bec835ab972283c9a168b +932128971c9d333f32939a1b46c4f7cf7e9d8417bd08dc5bd4573ccbd6ec5b460ac8880fb7f142f7ef8a40eef76d0c6d +964115e7838f2f197d6f09c06fbb2301d6e27c0ecdf208350cf3b36c748436dac50f47f9f9ac651c09ab7ad7221c7e43 +a5941f619e5f55a9cf6e7f1499b1f1bcddcc7cf5e274efedaaad73a75bc71b1fc5c29cd903f6c69dc9a366a6933ca9d1 +a154bf5eaec096029e5fe7c8bf6c695ae51ace356bb1ad234747776c7e1b406dee2d58864c3f4af84ed69f310974125e +b504e6209d48b0338ab1e4bdab663bac343bb6e0433466b70e49dc4464c1ec05f4a98111fd4450393607510ae467c915 +813411918ea79bdde295393284dc378b9bdc6cfcb34678b9733ea8c041ac9a32c1e7906e814887469f2c1e39287e80f8 +8be0369f94e4d72c561e6edb891755368660208853988647c55a8eed60275f2dd6ee27db976de6ecf54ac5c66aaf0ae6 +a7e2701e55b1e7ea9294994c8ad1c080db06a6fc8710cd0c9f804195dce2a97661c566089c80652f27b39018f774f85e +956b537703133b6ddf620d873eac67af058805a8cc4beb70f9c16c6787bf3cc9765e430d57a84a4c3c9fbdd11a007257 +835ae5b3bb3ee5e52e048626e3ddaa49e28a65cb94b7ecdc2e272ff603b7058f1f90b4c75b4b9558f23851f1a5547a35 +85d67c371d1bf6dc72cca7887fa7c886ce988b5d77dc176d767be3205e80f6af2204d6530f7060b1f65d360a0eaeff30 +a84a6647a10fcef8353769ef5f55a701c53870054691a6e9d7e748cbe417b3b41dbb881bae67adc12cb6596c0d8be376 +87ffe271fc0964cb225551c7a61008d8bcb8b3d3942970dbcc2b9f4f9045a767971880368ea254e2038a3a0b94ecf236 +964bb721c51d43ee7dd67c1a2b7dd2cc672ce8fad78c22dcddb43e6aab48d9a4a7dc595d702aa54a6fb0ffabf01f2780 +a89b3f84bb7dcbe3741749776f5b78a269f6b1bebb8e95d3cc80b834fd2177c6be058d16cacfd0d5e1e35e85cde8b811 +b4314538e003a1587b5592ff07355ea03239f17e75c49d51f32babe8e048b90b046a73357bcb9ce382d3e8fbe2f8e68b +86daf4bf201ae5537b5d4f4d734ed2934b9cf74de30513e3280402078f1787871b6973aa60f75858bdf696f19935a0e2 +b1adf5d4f83f089dc4f5dae9dbd215322fa98c964e2eaa409bf8ca3fa5c627880a014ed209492c3894b3df1c117236c4 +b508d52382c5bac5749bc8c89f70c650bb2ed3ef9dc99619468c387c1b6c9ff530a906dfa393f78f34c4f2f31478508a +a8349a5865cb1f191bebb845dfbc25c747681d769dbffd40d8cedf9c9a62fa2cbc14b64bb6121120dab4e24bef8e6b37 +af0500d4af99c83db8890a25f0be1de267a382ec5e9835e2f3503e1bac9412acf9ff83a7b9385708ef8187a38a37bc77 +b76d57a1c1f85b8a8e1722a47057b4c572800957a6b48882d1fc21309c2e45f648a8db0fcff760d1dbc7732cf37c009b +b93c996cec0d3714667b5a5a5f7c05a7dc00bbc9f95ac8e310626b9e41ae4cc5707fac3e5bd86e1e1f2f6d9627b0da94 +93216fdb864217b4c761090a0921cf8d42649ab7c4da1e009ec5450432564cb5a06cb6e8678579202d3985bd9e941cef +8b8be41105186a339987ae3a5f075fbc91f34b9984d222dfed0f0f85d2f684b56a56ab5dc812a411570491743d6c8b18 +959b72782a6b2469e77fe4d492674cc51db148119b0671bd5d1765715f49fa8a87e907646671161586e84979ef16d631 +86b7fc72fb7e7904ea71d5e66ba0d5d898ace7850985c8cc4a1c4902c5bf94351d23ce62eed45e24321fb02adfa49fc8 +a2f244e7c9aa272cb0d067d81d25e5a3045b80b5a520b49fd5996ece267a7f1bea42e53147bbf153d9af215ea605fc9e +81aa2efa5520eebc894ce909ba5ce3250f2d96baa5f4f186a0637a1eea0080dd3a96c2f9fadf92262c1c5566ddb79bab +b607dd110cfe510d087bcff9a18480ba2912662256d0ab7b1d8120b22db4ad036b2266f46152754664c4e08d0fc583f6 +8f588d5f4837e41312744caac5eee9ddc3ad7085871041694f0b5813edf83dc13af7970f7c9b6d234a886e07fa676a04 +924921b903207783b31016cbec4e6c99e70f5244e775755c90d03a8b769738be3ba61577aca70f706a9c2b80040c9485 +ae0a42a222f1a71cd0d3c69ffb2f04c13e1940cce8efabe032629f650be3ceed6abb79651dbb81cb39a33286eb517639 +a07d7d76460f31f5f0e32e40a5ea908d9d2aebf111ac4fadee67ef6540b916733c35a777dcdc05f6417726ca1f2d57dd +88d7f8a31f8c99794291847d28745e5d0b5d3b9684ca4170b686ffbb5bb521a3ef6746c3c8db22e4250a0cdff7939d96 +849573071fd98c020dc9a8622a9eff221cb9f889bde259e7127a8886b73bef7ad430b87750915658918dcfb6b7b4d8d3 +b12d59f732fa47fad175d6263734da8db89230fd340a46ad1cdee51e577041a5c80bf24cd195593e637daf1a66ef5a98 +abbcfb8a4a6d5e269ee1ac5e277df84416c73ca55ec88317f73608201af25af0cb65b943c54684a5651df3a26e3daca2 +ab157f589bdbaf067a6a7ba7513df0492933855d39f3a081196cf2352e0ddc0162d476c433320366e3df601e0556278d +a86c0619b92e5ae4f7daa876a2abc5ba189156afc2fa05eef464dfa342ba37fc670d0dc308ad3822fcb461ab001bac30 +a3f292946476cfe8d5e544a5325439a00e0165a5f9bf3bb6a53f477baeac7697cc0377745536681aa116f326ce911390 +8aecbbfd442a6a0f01c1c09db5d9d50213eb6f1ff6fab674cde3da06a4edff3ed317e804f78300c22ef70c336123e05d +834ed4b58211fcd647d7bf7c0a3ba9085184c5c856b085e8a0fcd5215c661ef43d36f3f0f6329a9f1370501b4e73b6e4 +a114ea5ad2b402a0de6105e5730907f2f1e458d28ae35144cf49836e0ad21325fe3e755cfb67984ae0a32e65402aad1e +a005f12bed97d71cee288b59afe9affb4d256888727343944a99913980df2c963fe02f218e6ea992f88db693a4498066 +a010f286ab06b966e3b91ff8f1bdbe2fe9ab41a27bc392d5787aa02a46e5080e58c62c7d907818caae9f6a8b8123e381 +857bd6df2ddef04dbc7c4f923e0b1696d3016c8bfed07fdfa28a3a3bd62d89b0f9df49aae81cbb6883d5e7b4fadae280 +b3927030da445bc4756ac7230a5d87412a4f7510581fb422212ce2e8cf49689aca7ba71678743af06d4de4914c5aa4a0 +b86403182c98fcce558d995f86752af316b3b2d53ba32075f71c7da2596747b7284c34a1a87de604fcc71e7e117a8add +98dd19b5527733041689b2a4568edaf6aa0fe1a3dd800c290cda157b171e053648a5772c5d3d4c80e5a795bc49adf12e +88a3c227bb7c9bff383f9ad3f7762245939a718ab85ae6e5e13180b12bf724d42054d3852b421c1cd1b3670baddecb63 +b3cfd9ad66b52bbe57b5fff0fad723434d23761409b92c4893124a574acc1e6b1e14b4ec507661551cbbe05e16db362e +923e1bb482cf421dd77801f9780f49c3672b88508a389b94015fd907888dc647ee9ea8ec8d97131d235d066daf1f42b7 +8d5e16240f04f92aa948181d421006bdbc7b215648fb6554193224d00cf337ebbb958f7548cf01b4d828acffb9fbc452 +8b2b8f18ad0559746f6cda3acca294a1467fb1a3bc6b6371bc3a61a3bfe59418934fa8706f78b56005d85d9cb7f90454 +a9316e2a94d6e31426d2ae7312878ba6baaac40f43e2b8a2fa3ab5a774c6918551554b2dbb23dc82f70ba3e0f60b5b0d +9593116d92cf06b8cd6905a2ce569ee6e69a506c897911f43ae80fc66c4914da209fc9347962034eebbc6e3e0fe59517 +887d89d2b2d3c82b30e8f0acf15f0335532bd598b1861755498610cb2dd41ff5376b2a0bb757cb477add0ce8cfe7a9fc +b514cfe17875ecb790ad055271cc240ea4bda39b6cfa6a212908849c0875cb10c3a07826550b24c4b94ea68c6bb9e614 +a563d5187966d1257d2ed71d53c945308f709bcc98e3b13a2a07a1933dc17bcb34b30796bd68c156d91811fbd49da2cb +a7195ccc53b58e65d1088868aeeb9ee208103e8197ad4c317235bb2d0ad3dc56cb7d9a7186416e0b23c226078095d44c +a838e7a368e75b73b5c50fbfedde3481d82c977c3d5a95892ac1b1a3ea6234b3344ad9d9544b5a532ccdef166e861011 +9468ed6942e6b117d76d12d3a36138f5e5fb46e3b87cf6bb830c9b67d73e8176a1511780f55570f52d8cdb51dcf38e8c +8d2fc1899bc3483a77298de0e033085b195caf0e91c8be209fd4f27b60029cbe1f9a801fbd0458b4a686609762108560 +8f4e44f8ca752a56aa96f3602e9234ad905ad9582111daf96a8c4d6f203bf3948f7ce467c555360ad58376ee8effd2ba +8fb88640b656e8f1c7c966c729eb2ba5ccf780c49873f8b873c6971840db7d986bdf1332ba80f8a0bb4b4ee7401468fa +b72aa3235868186913fb5f1d324e748cd3ce1a17d3d6e6ea7639a5076430fe0b08841c95feb19bb94181fe59c483a9eb +b8b102690ebb94fc4148742e7e3fd00f807b745b02cbe92cd92992c9143b6db7bb23a70da64a8b2233e4a6e572fc2054 +8c9ae291f6cd744e2c6afe0719a7fc3e18d79307f781921fb848a0bf222e233879c1eca8236b4b1be217f9440859b6ce +a658ede47e14b3aad789e07f5374402f60e9cacb56b1b57a7c6044ca2418b82c98874e5c8c461898ebd69e38fecd5770 +89c0cb423580e333923eb66bda690f5aca6ec6cba2f92850e54afd882ba608465a7dbb5aa077cd0ca65d9d00909348ab +aed8e28d98d5508bd3818804cf20d296fe050b023db2ed32306f19a7a3f51c7aaafed9d0847a3d2cd5ba5b4dabbc5401 +96a0fcd6235f87568d24fb57269a94402c23d4aa5602572ad361f3f915a5f01be4e6945d576d51be0d37c24b8b0f3d72 +935d0c69edd5dfa8ed07c49661b3e725b50588f814eb38ea31bcc1d36b262fae40d038a90feff42329930f8310348a50 +900518288aa8ea824c7042f76710f2ea358c8bb7657f518a6e13de9123be891fa847c61569035df64605a459dad2ecc8 +947d743a570e84831b4fb5e786024bd752630429d0673bf12028eb4642beb452e133214aff1cfa578a8856c5ebcb1758 +a787266f34d48c13a01b44e02f34a0369c36f7ec0aae3ec92d27a5f4a15b3f7be9b30b8d9dd1217d4eeedff5fd71b2e5 +a24b797214707ccc9e7a7153e94521900c01a1acd7359d4c74b343bfa11ea2cdf96f149802f4669312cd58d5ab159c93 +97f5ee9c743b6845f15c7f0951221468b40e1edaef06328653a0882793f91e8146c26ac76dd613038c5fdcf5448e2948 +80abd843693aed1949b4ea93e0188e281334163a1de150c080e56ca1f655c53eb4e5d65a67bc3fc546ed4445a3c71d00 +908e499eb3d44836808dacff2f6815f883aeced9460913cf8f2fbbb8fe8f5428c6fc9875f60b9996445a032fd514c70f +ae1828ef674730066dc83da8d4dd5fa76fc6eb6fa2f9d91e3a6d03a9e61d7c3a74619f4483fe14cddf31941e5f65420a +a9f4dbe658cd213d77642e4d11385a8f432245b098fccd23587d7b168dbeebe1cca4f37ee8d1725adb0d60af85f8c12f +93e20ee8a314b7772b2439be9d15d0bf30cd612719b64aa2b4c3db48e6df46cea0a22db08ca65a36299a48d547e826a7 +a8746a3e24b08dffa57ae78e53825a9ddbbe12af6e675269d48bff4720babdc24f907fde5f1880a6b31c5d5a51fbb00e +b5e94dfab3c2f5d3aea74a098546aa6a465aa1e3f5989377d0759d1899babf543ad688bb84811d3e891c8713c45886c5 +a3929bada828bd0a72cda8417b0d057ecb2ddd8454086de235540a756e8032f2f47f52001eb1d7b1355339a128f0a53b +b684231711a1612866af1f0b7a9a185a3f8a9dac8bde75c101f3a1022947ceddc472beb95db9d9d42d9f6ccef315edbc +af7809309edbb8eb61ef9e4b62f02a474c04c7c1ffa89543d8c6bf2e4c3d3e5ecbd39ec2fc1a4943a3949b8a09d315a6 +b6f6e224247d9528ef0da4ad9700bee6e040bbf63e4d4c4b5989d0b29a0c17f7b003c60f74332fefa3c8ddbd83cd95c1 +adbcec190a6ac2ddd7c59c6933e5b4e8507ce5fd4e230effc0bd0892fc00e6ac1369a2115f3398dfc074987b3b005c77 +8a735b1bd7f2246d3fa1b729aecf2b1df8e8c3f86220a3a265c23444bdf540d9d6fe9b18ed8e6211fad2e1f25d23dd57 +96b1bf31f46766738c0c687af3893d098d4b798237524cb2c867ed3671775651d5852da6803d0ea7356a6546aa9b33f2 +8036e4c2b4576c9dcf98b810b5739051de4b5dde1e3e734a8e84ab52bc043e2e246a7f6046b07a9a95d8523ec5f7b851 +8a4f4c32ee2203618af3bb603bf10245be0f57f1cfec71037d327fa11c1283b833819cb83b6b522252c39de3ce599fa5 +ad06ed0742c9838e3abaaffdb0ac0a64bad85b058b5be150e4d97d0346ed64fd6e761018d51d4498599669e25a6e3148 +8d91cb427db262b6f912c693db3d0939b5df16bf7d2ab6a7e1bc47f5384371747db89c161b78ff9587259fdb3a49ad91 +ae0a3f84b5acb54729bcd7ef0fbfdcf9ed52da595636777897268d66db3de3f16a9cf237c9f8f6028412d37f73f2dfad +8f774109272dc387de0ca26f434e26bc5584754e71413e35fa4d517ee0f6e845b83d4f503f777fe31c9ec05796b3b4bc +a8670e0db2c537ad387cf8d75c6e42724fae0f16eca8b34018a59a6d539d3c0581e1066053a2ec8a5280ffabad2ca51f +ac4929ed4ecad8124f2a2a482ec72e0ef86d6a4c64ac330dab25d61d1a71e1ee1009d196586ce46293355146086cabba +845d222cb018207976cc2975a9aa3543e46c861486136d57952494eb18029a1ebb0d08b6d7c67c0f37ee82a5c754f26f +b99fa4a29090eac44299f0e4b5a1582eb89b26ed2d4988b36338b9f073851d024b4201cd39a2b176d324f12903c38bee +9138823bc45640b8f77a6464c171af2fe1700bdc2b7b88f4d66b1370b3eafe12f5fbb7b528a7e1d55d9a70ca2f9fc8e6 +8ac387dc4cf52bc48a240f2965ab2531ae3b518d4d1f99c0f520a3d6eb3d5123a35ef96bed8fa71ee2f46793fa5b33b3 +864adec6339d4c2ba2525621fceabd4c455902f6f690f31a26e55413e0722e5711c509dc47ce0bcc27bbdc7651768d2d +a0a52edb72268a15201a968dabc26a22909620bda824bd548fb8c26cc848f704166ed730d958f0173bd3b0a672f367bd +949e445b0459983abd399571a1a7150aab3dd79f4b52a1cd5d733e436c71c1d4b74287c6b0ce6cc90c6711ba4c541586 +858966355dac11369e3b6552f2b381665181693d5a32e596984da3314021710b25a37d8c548b08700eea13d86cb22f21 +974bcbb8d38c5e6518745cc03ad436e585b61f31d705e7e2e5085da9655d768ac4d800904f892c3dab65d6223e3f1fd6 +8092b6506b01308bf6187fde5ebd4fa7448c9a640961ba231be22ac5fa2c7635ef01e8b357722c7695d09b723101ea2a +a5b8ef360bf28533ee17d8cd131fff661d265f609db49599085c0c7d83b0af409a1b5c28e3a5e5d7f8459a368aa121e8 +b031b6d5e3ceab0f0c93314b3b675f55cf18cbc86f70444af266fe39cb22fd7dad75d8c84e07f1c1bfa2cb8283e1361a +93ad489e4f74658320c1cceed0137c023d3001a2c930ed87e6a21dbf02f2eb6ad1c1d8bcb3739c85dcfbecb040928707 +b15e4ec2cdab0d34aec8d6c50338812eb6ecd588cf123a3e9d22a7ca23b5a98662af18289f09e6cdd85a39a2863c945c +b304f71a9717cf40c22073f942618b44bf27cd5e2ed4a386ad45d75b0fcb5a8dafd35158211eaf639495c6f1a651cedb +b82d78d3eaaa7c5101b7a5aae02bd4f002cd5802d18c3abcda0dd53b036661c6d3c8b79e0abe591eab90b6fdc5fef5e3 +abbd1884243a35578b80914a5084449c237ee4e4660c279d1073a4d4217d1b55c6b7e9c087dfd08d94ac1416273d8d07 +92f4b61c62502745e3e198ec29bca2e18696c69dcb914d1f3a73f4998d012b90caf99df46e9bb59942e43cce377fe8fd +906e79df98185820c8208844e1ba6bd86cb96965814b01310bd62f22cbec9b5d379b2ef16772d6fc45a421b60cfd68fe +a0eae2784ef596e2eb270dd40c48d6c508e4394c7d6d08d4cc1b56fde42b604d10ba752b3a80f2c4a737e080ef51b44f +94c084985e276dc249b09029e49a4ef8a369cd1737b51c1772fbb458d61e3fe120d0f517976eba8ffa5711ba93e46976 +83619a0157eff3f480ab91d1d6225fead74c96a6fd685333f1e8e4d746f6273e226bad14232f1d1168a274e889f202f1 +a724fe6a83d05dbbf9bb3f626e96db2c10d6d5c650c0a909415fbda9b5711c8b26e377201fb9ce82e94fa2ab0bf99351 +a8a10c1b91a3a1fa2d7fd1f78a141191987270b13004600601d0f1f357042891010717319489f681aa8a1da79f7f00d5 +a398a2e95b944940b1f8a8e5d697c50e7aa03994a8a640dfad4ea65cfb199a4d97861a3ec62d1c7b2b8d6e26488ca909 +a2eedfe5452513b2a938fffd560798ef81379c5a5032d5b0da7b3bb812addbaad51f564c15d9acbbfc59bb7eddd0b798 +ab31c572f6f145a53e13b962f11320a1f4d411739c86c88989f8f21ab629639905b3eedb0628067942b0dc1814b678ca +ad032736dd0e25652d3566f6763b48b34ea1507922ed162890cd050b1125ec03b6d41d34fccba36ec90336f7cdf788ed +83028a558a5847293147c483b74173eca28578186137df220df747fccd7d769528d7277336ea03c5d9cdd0bc5ae3d666 +ab5d182cd1181de8e14d3ef615580217c165e470b7a094a276b78a3003089123db75c6e1650bf57d23e587c587cd7472 +a4793e089fbdb1597654f43b4f7e02d843d4ab99ee54099c3d9f0bd5c0c5657c90bb076379a055b00c01b12843415251 +98bdc52ee062035356fb2b5c3b41673198ddc60b2d1e546cb44e3bb36094ef3c9cf2e12bbc890feb7d9b15925439d1ea +a4f90cca6f48024a0341bd231797b03693b34e23d3e5b712eb24aba37a27827319b2c16188f97c0636a0c115381dc659 +8888e6c2e4a574d04ba5f4264e77abc24ccc195f1a7e3194169b8a2ceded493740c52db4f9833b3dbf4d67a3c5b252cb +83dc4e302b8b0a76dc0292366520b7d246d73c6aebe1bdd16a02f645c082197bcff24a4369deda60336172cefbcf09af +a4eb2741699febfeb793914da3054337cc05c6fa00d740e5f97cb749ae16802c6256c9d4f0f7297dcdbb8b9f22fc0afa +8b65557d5be273d1cb992a25cfce40d460c3f288d5cb0a54bdef25cbd17cdea5c32ec966e493addf5a74fd8e95b23e63 +97c6577e76c73837bcb398b947cb4d3323d511141e0ddd0b456f59fbb1e8f920a5c20d7827a24309145efddee786140f +abcc0849ffe2a6a72157de907907b0a52deece04cf8317bee6fe1d999444b96e461eac95b6afde3d4fe530344086a625 +9385c0115cb826a49df1917556efa47b5b5e4022b6a0d2082053d498ec9681da904ecf375368bb4e385833116ea61414 +8b868c1841f0cdc175c90a81e610b0652c181db06731f5c8e72f8fafa0191620742e61a00db8215a991d60567b6a81ca +a8df15406f31b8fcf81f8ff98c01f3df73bf9ec84544ddec396bdf7fafa6fe084b3237bf7ef08ad43b26517de8c3cd26 +a9943d21e35464ce54d4cc8b135731265a5d82f9ccf66133effa460ffdb443cdb694a25320506923eede88d972241bf2 +a1378ee107dd7a3abcf269fd828887c288363e9b9ca2711377f2e96d2ed5e7c5ec8d3f1da995a3dcbedf1752d9c088fc +8a230856f9227b834c75bdebc1a57c7298a8351874bf39805c3e0255d6fd0e846f7ad49709b65ec1fd1a309331a83935 +877bcf42549d42610e1780e721f5800972b51ba3b45c95c12b34cb35eeaf7eac8fa752edd7b342411820cf9093fea003 +84c7a0b63842e50905624f1d2662506b16d1f3ea201877dfc76c79181c338b498eceb7cad24c2142c08919120e62f915 +8e18b1bd04b1d65f6ed349b5d33a26fe349219043ead0e350b50ae7a65d6ff5f985dd9d318d3b807d29faa1a7de4fe42 +8ea7b5a7503e1f0b3c3cd01f8e50207044b0a9c50ed1697794048bbe8efd6659e65134d172fb22f95439e1644f662e23 +b1954a2818cad1dad6d343a7b23afa9aa8ad4463edc4eb51e26e087c2010927535020d045d97d44086d76acdb5818cbf +a5271ea85d0d21fa1ff59b027cf88847c0f999bbf578599083ff789a9b5228bc161e1c81deb97e74db1a82a0afd61c50 +aa2fa4c05af3387e2c799315781d1910f69977ec1cfea57a25f1a37c63c4daaa3f0ecd400884a1673e17dd5300853bcf +b1cd2a74ca0b8e6090da29787aef9b037b03b96607983a308b790133bd21297b21ca4e2edec890874096dbf54e9d04c3 +801931607ec66a81272feaa984f0b949ad12d75ecf324ba96627bd4dc5ddead8ebf088f78e836b6587c2b6c0b3366b6c +95d79504710bdf0ad9b9c3da79068c30665818c2f0cdbba02cc0a5e46e29d596032ac984441b429bd62e34535c8d55b0 +9857d41e25e67876510ff8dadf0162019590f902da1897da0ef6fc8556e3c98961edb1eb3a3a5c000f6c494413ded15e +8740c9ffe6bd179c19a400137c3bd3a593b85bd4c264e26b4dfb9e2e17ac73e5b52dfacc1dcb4033cfc0cd04785f4363 +977f98f29d948b4097a4abdf9345f4c1fb0aa94ba0c6bf6faa13b76f3a3efc8f688e1fe96099b71b3e1c05041118c8d1 +a364422b1239126e3e8d7b84953ce2181f9856319b0a29fcab81e17ac27d35798088859c1cfc9fc12b2dbbf54d4f70b3 +a0f6ba637f0db7a48e07439bb92ddb20d590ce9e2ed5bab08d73aa22d82c32a9a370fe934cbe9c08aeb84b11adcf2e0e +a2c548641bd5b677c7748327cca598a98a03a031945276be6d5c4357b6d04f8f40dd1c942ee6ec8499d56a1290ac134d +9863e9cc5fbcdbd105a41d9778d7c402686bfd2d81d9ed107b4fda15e728871c38647529693306855bee33a00d257a7e +a54173bf47b976290c88fd41f99300135de222f1f76293757a438450880e6f13dbde3d5fe7afc687bdfbcfc4fbc1fc47 +b8db413917c60907b73a997b5ab42939abd05552c56a13525e3253eb72b83f0d5cc52b695968a10005c2e2fe13290e61 +a1f8388ef21697c94ba90b1a1c157f0dc138e502379e6fc5dc47890d284563e5db7716266e1b91927e5adf3cde4c0a72 +9949013a59d890eb358eab12e623b2b5edb1acbee238dfad8b7253102abc6173922e188d5b89ec405aa377be8be5f16d +a00fdb7710db992041f6ddb3c00099e1ce311dea43c252c58f560c0d499983a89de67803a8e57baa01ee9d0ee6fa1e44 +a8b1bcbed1951c9cdb974b61078412881b830b48cd6b384db0c00fa68bcc3f4312f8e56c892ea99d3511857ef79d3db9 +8f3ee78404edc08af23b1a28c2012cee0bdf3599a6cb4ea689fc47df4a765ef519191819a72562b91a0fbcdb896a937e +8155bbb7fa8d386848b0a87caae4da3dec1f3dade95c750a64a8e3555166ccc8799f638bd80ed116c74e3a995541587a +abfe30adbc0a6f1fd95c630ed5dac891b85384fa9331e86b83217f29dff0bd7cad19d328485715a7e3df9a19069d4d2f +89d0783e496ee8dbb695764b87fb04cee14d4e96c4ba613a19736971c577d312079048142c12ce5b32b21e4d491d281b +856b8dbc9c5d8f56b6bb7d909f339ca6da9a8787bba91f09130a025ab6d29b64dbf728ba6ed26e160a23c1cdb9bc037b +8a30dd2ea24491141047a7dfe1a4af217661c693edf70b534d52ca547625c7397a0d721e568d5b8398595856e80e9730 +ae7e1412feb68c5721922ed9279fb05549b7ef6812a4fd33dbbbd7effab756ab74634f195d0c072143c9f1fd0e1ee483 +b7ce970e06fa9832b82eef572f2902c263fda29fdce9676f575860aae20863046243558ede2c92343616be5184944844 +85ed0531f0e5c1a5d0bfe819d1aa29d6d5ff7f64ad8a0555560f84b72dee78e66931a594c72e1c01b36a877d48e017ca +b8595be631dc5b7ea55b7eb8f2982c74544b1e5befc4984803b1c69727eac0079558182f109e755df3fd64bee00fcaa5 +99e15a66e5b32468ef8813e106271df4f8ba43a57629162832835b8b89402eb32169f3d2c8de1eb40201ce10e346a025 +844c6f5070a8c73fdfb3ed78d1eddca1be31192797ad53d47f98b10b74cc47a325d2bc07f6ee46f05e26cf46a6433efb +974059da7f13da3694ad33f95829eb1e95f3f3bfc35ef5ef0247547d3d8ee919926c3bd473ab8b877ff4faa07fcc8580 +b6f025aecc5698f6243cc531782b760f946efebe0c79b9a09fe99de1da9986d94fa0057003d0f3631c39783e6d84c7d5 +b0c5358bc9c6dfe181c5fdf853b16149536fbb70f82c3b00db8d854aefe4db26f87332c6117f017386af8b40288d08f9 +a3106be5e52b63119040b167ff9874e2670bd059b924b9817c78199317deb5905ae7bff24a8ff170de54a02c34ff40a4 +ad846eb8953a41c37bcd80ad543955942a47953cbc8fb4d766eac5307892d34e17e5549dc14467724205255bc14e9b39 +b16607e7f0f9d3636e659e907af4a086ad4731488f5703f0917c4ce71a696072a14a067db71a3d103530920e1ec50c16 +8ed820e27116e60c412c608582e9bb262eaaf197197c9b7df6d62b21a28b26d49ea6c8bb77dfde821869d9b58025f939 +97bc25201d98cde389dd5c0c223a6f844393b08f75d3b63326343073e467ac23aacef630ddc68545ea874299ba4a3b4f +b73c9695ad2eefd6cc989a251c433fab7d431f5e19f11d415a901762717d1004bb61e0cc4497af5a8abf2d567e59fef4 +adaabe331eea932533a7cc0cf642e2a5e9d60bbc92dd2924d9b429571cbf0d62d32c207b346607a40643c6909b8727e2 +a7b1bbfe2a5e9e8950c7cb4daab44a40c3ffab01dc012ed7fe445f4af47fa56d774a618fafe332ab99cac4dfb5cf4794 +b4a3c454dcd5af850212e8b9ba5fe5c0d958d6b1cabbf6c6cfe3ccbc4d4c943309c18b047256867daf359006a23f3667 +a5c0b32f6cef993834c1381ec57ad1b6f26ae7a8190dd26af0116e73dadc53bb0eeb1911419d609b79ce98b51fdc33bc +ac2f52de3ecf4c437c06c91f35f7ac7d171121d0b16d294a317897918679f3b9db1cef3dd0f43adb6b89fe3030728415 +94722ae6d328b1f8feaf6f0f78804e9b0219de85d6f14e8626c2845681841b2261d3e6a2c5b124086b7931bf89e26b46 +a841a0602385d17afabca3a1bb6039167d75e5ec870fea60cfcaec4863039b4d745f1a008b40ec07bca4e42cb73f0d21 +8c355f0a1886ffced584b4a002607e58ff3f130e9de827e36d38e57cb618c0cb0b2d2dea2966c461cb3a3887ede9aef1 +a6a9817b0fc2fd1786f5ba1a7b3d8595310987fb8d62f50a752c6bb0b2a95b67d03a4adfd13e10aa6190a280b7ee9a67 +a1d2e552581ecbafeaef08e389eaa0b600a139d446e7d0648ac5db8bbbf3c438d59497e3a2874fc692b4924b87ff2f83 +a1b271c55389f25639fe043e831e2c33a8ba045e07683d1468c6edd81fedb91684e4869becfb164330451cfe699c31a8 +8c263426e7f7e52f299d57d047a09b5eeb893644b86f4d149535a5046afd655a36d9e3fdb35f3201c2ccac2323a9582e +b41c242a7f7880c714241a97d56cce658ee6bcb795aec057a7b7c358d65f809eb901e0d51256826727dc0dc1d1887045 +93001b9445813c82f692f94c0dc1e55298f609936b743cf7aae5ebfa86204f38833d3a73f7b67314be67c06a1de5682d +82087536dc5e78422ad631af6c64c8d44f981c195ddea07d5af9bb0e014cdc949c6fa6e42fce823e0087fdb329d50a34 +8e071861ceba2737792741c031f57e0294c4892684506b7c4a0fc8b2f9a0a6b0a5635de3d1e8716c34df0194d789ae86 +b471c997e1e11774bd053f15609d58838a74073a6c089a7a32c37dd3f933badf98c7e5833263f3e77bc0d156a62dd750 +8d2d8686fb065b61714414bb6878fff3f9e1e303c8e02350fd79e2a7f0555ded05557628152c00166ce71c62c4d2feaa +ae4c75274d21c02380730e91de2056c0262ffcecf0cbdb519f0bdb0b5a10ae2d4996b3dc4b3e16dbaea7f0c63d497fef +97140d819e8ca6330e589c6debdee77041c5a9cedb9b8cbd9c541a49207eeb7f6e6b1c7e736ec8ba6b3ab10f7fcd443a +af6659f31f820291a160be452e64d1293aa68b5074b4c066dac169b8d01d0179139504df867dc56e2a6120354fc1f5be +a5e5d8088a368024617bfde6b731bf9eee35fc362bed3f5dfdd399e23a2495f97f17728fec99ca945b3282d1858aa338 +a59cfc79d15dbdde51ab8e5129c97d3baba5a0a09272e6d2f3862370fdbaf90994e522e8bd99d6b14b3bb2e9e5545c6f +a30499b068083b28d6c7ddcc22f6b39b5ec84c8ee31c5630822c50ea736bb9dca41c265cffc6239f1c9ef2fd21476286 +88ffe103eca84bbe7d1e39a1aa599a5c7c9d5533204d5c4e085402a51441bb8efb8971efe936efbbfa05e5cb0d4b8017 +b202356fbf95a4d699154639e8cb03d02112c3e0128aab54d604645d8510a9ba98936028349b661672c3a4b36b9cb45d +8b89bb6574bf3524473cff1ff743abcf1406bd11fb0a72070ccd7d8fce9493b0069fb0c6655252a5164aee9e446ea772 +93247b1038fa7e26667ee6446561d4882dc808d1015daafb705935ddc3598bb1433182c756465960480f7b2de391649e +b027f94d3358cbb8b6c8c227300293a0dee57bf2fee190a456ad82ecfb6c32f8090afa783e2ab16f8139805e1fb69534 +a18bb1849b2f06c1d2214371031d41c76ffa803ee3aa60920d29dbf3db5fbfac2b7383d5d0080ba29ce25c7baa7c306b +827bf9fd647e238d5ac961c661e5bbf694b4c80b3af8079f94a2484cb8fba2c8cf60e472ebcd0b0024d98ae80ad2ff5a +838e891218c626a7f39b8fd546b013587408e8e366ecc636b54f97fa76f0a758bc1effa1d0f9b6b3bc1a7fcc505970a0 +836523b5e8902d6e430c6a12cff01e417d2bd7b402e03904034e3b39755dee540d382778c1abe851d840d318ebedce7f +850a77dda9ac6c217e2ef00bf386a1adec18b7f462f52801c4f541215690502a77ef7519b690e22fdf54dc2109e0ca38 +a8265c6ae7b29fc2bda6a2f99ced0c1945dd514b1c6ca19da84b5269514f48a4f7b2ccbab65c9107cfd5b30b26e5462f +ab3d02ee1f1267e8d9d8f27cc388e218f3af728f1de811242b10e01de83471a1c8f623e282da5a284d77884d9b8cde0e +831edaf4397e22871ea5ddee1e7036bab9cc72f8d955c7d8a97f5e783f40532edbbb444d0520fefcffeab75677864644 +80484487977e4877738744d67b9a35b6c96be579a9faa4a263e692295bb6e01f6e5a059181f3dd0278e2c3c24d10a451 +aae65a18f28c8812617c11ecf30ad525421f31fb389b8b52d7892415e805a133f46d1feca89923f8f5b8234bd233486a +b3a36fd78979e94288b4cefed82f043a7e24a4a8025479cc7eb39591e34603048a41ee606ee03c0b5781ebe26a424399 +b748b3fc0d1e12e876d626a1ba8ad6ad0c1f41ea89c3948e9f7d2666e90173eb9438027fadcd741d3ae0696bd13840f1 +acdd252d7c216c470683a140a808e011c4d5f1b4e91aeb947f099c717b6a3bad6651142cde988330827eb7d19d5fb25c +b9a25556a6ca35db1ed59a1ec6f23343eab207a3146e4fc3324136e411c8dba77efd567938c63a39c2f1c676b07d8cdb +a8db6aef8f5680d2bdb415d7bcaae11de1458678dcb8c90c441d5986c44f83a9e5855662d0c1aace999172d8628d8fe1 +af58147108e9909c3a9710cc186eab598682dca4bfd22481e040b8c000593ecb22c4ede4253ac9504e964dfa95a9b150 +8dd8bb70f1c9aec0fcc9478f24dfc9c3c36c0bf5ff7a67c017fa4dab2ec633fbd7bc9d8aa41ea63e2696971ed7e375f5 +aa98d600b22aff993a4d7a3ccabd314e1825b200cb598f6b797d7e4d6a76d89e34a4d156c06bddfc62f2ef9b4c809d1d +8a8fc960d6c51294b8205d1dabe430bef59bda69824fa5c3c3105bef22ac77c36d2d0f38ffc95ce63731de5544ccbeff +b6d1020efe01dc8032bd1b35e622325d7b9af9dcd5c9c87c48d7d6ebc58644454294c59b7f4b209204b5b1f899f473bf +8a750dc9fe4891f2dfe5759fb985939810e4cdc0b4e243ff324b6143f87676d8cb4bcb9dfb01b550801cedcaaa5349e2 +98c13142d3a9c5f8d452245c40c6dae4327dd958e0fda85255ea0f87e0bcbaa42a3a0bd50407ed2b23f9f6317a8a4bc5 +99f2b83d9ec4fc46085a6d2a70fd0345df10f4a724c1ba4dee082a1fde9e642e3091992ebf5f90a731abcb6ec11f6d9b +b218546ab2db565b2489ea4205b79daa19ef2acbf772ccaaa5e40150e67ea466090d07198444b48e7109939aa2319148 +84f9d1d868e4b55e535f1016558f1789df0daa0ead2d13153e02f715fe8049b1ce79f5bc1b0bbbb0b7e4dd3c04783f3f +80d870d212fbddfdda943e90d35a5a8aa0509a7a1e7f8909f2fcb09c51c3026be47cc7a22620a3063406872105b4f81a +b5b15138ff6551fac535d4bbce2ea6adc516b6b7734b4601c66ec029da2615e3119dc9ad6a937344acfd7b50e4a1a2ae +95d2f97652086e7ceb54e1d32692b1c867ffba23c4325740c7f10d369283d1b389e8afa0df967831ade55696931e7934 +8a5b580403e1a99cd208f707e8ce0d3f658c8280417683f69008d09cc74d835a85f7380f391b36ead9ac66d9eedd1cbe +a8b0c90bff34c86720637b5a2081f0f144cfe2205c1176cacd87d348609bc67af68aed72414dc9aa6f44a82c92c2a890 +865abbdd96c496892c165a8de0f9e73348bf24fce361d7a9048710178a3625881afb0006e9f5ee39124866b87904c904 +ace67bb994adef4b6f841cdf349195608030044562780a7e9b00b58a4ff117268a03ff01e5a3a9d9d7eff1dd01f5f4bf +b9371d59185b3d2d320d3fefeadb06ba2aa7d164352fb8dc37571509509fa214d736d244ac625a09a033a10d51611e2e +a8ef992771422dcf2d6d84386fde9fe5dba88bfded3dfcd14074ca04331b4fd53a7f316615cdfaf10ed932cbb424a153 +868cbc75f8f789ea45eded2768a1dac0763347e0d8e8028d316a21005f17be179d26d5965903e51b037f2f57fe41765d +b607111bcdfd05fa144aa0281b13ee736079ebbbf384d938a60e5e3579639ed8ef8eb9ca184868cdb220a8e130d4a952 +aca55702af5cae4cae65576769effd98858307a71b011841c563b97c2aa5aeb5c4f8645d254f631ed1582df3dbbf17da +b9b5cbace76246e80c20dfcc6f1e2c757a22ab53f7fd9ff8a1d309538b55174e55e557a13bf68f095ff6a4fa637ef21a +8571b0a96871f254e2397c9be495c76379faf347801cb946b94e63212d6a0da61c80e5d7bebbabcd6eaa7f1029172fe5 +902540326281e6dc9c20d9c4deaaf6fbbbcc3d1869bd0cf7f081c0525bea33df5cfa24ead61430fda47fb964fcc7994b +841af09279d3536a666fa072278950fabf27c59fc15f79bd52acb078675f8087f657929c97b4bc761cbade0ecb955541 +a1f958b147ddf80ab2c0746ba11685c4bae37eb25bfa0442e7e1078a00d5311d25499da30f6d168cb9302ea1f2e35091 +863d939381db37d5a5866964be3392a70be460f0353af799d6b3ed6307176972686bd378f8ad457435a4094d27e8dfb7 +835cd4d7f36eff553d17483eb6c041b14280beb82c7c69bca115929658455a1931212976c619bafb8179aed9940a8cc6 +8d0770e3cb8225e39c454a1fc76954118491b59d97193c72c174ecc7613051e5aed48a534016a8cf0795c524f771a010 +91aa4edb82f6f40db2b7bd4789cc08786f6996ebed3cb6f06248e4884bc949793f04a4c5ea6eefe77984b1cc2a45d699 +8fb494ca2449f659ff4838833507a55500a016be9293e76598bbae0a7cb5687e4693757c2b6d76e62bd6c7f19ed080bb +b59b104449a880a282c1dd6a3d8debb1d8814ef35aab5673c1e500ee4cb0e840fb23e05fa5a0af92509c26b97f098f90 +aca908e3bad65e854ae6be6c5db441a06bcd47f5abafdfa8f5a83c8cd3c6e08c33cab139c45887887a478338e19ceb9f +806f5d802040313a31964fc3eb0ee18ac91b348685bed93c13440984ee46f3d2da7194af18c63dea4196549129660a4e +ae4b2dca75c28d8f23b3ab760b19d839f39ff5a3112e33cb44cff22492604a63c382b88ec67be4b0266924dd438c3183 +99d1c29c6bd8bf384e79cd46e30b8f79f9cbc7d3bf980e9d6ffba048f0fc487cac45c364a8a44bb6027ad90721475482 +a16e861c1af76d35528c25bf804bfc41c4e1e91b2927d07d8e96bffe3a781b4934e9d131ecf173be9399800b8269efac +a253303234fb74f5829060cdcef1d98652441ab6db7344b1e470d195a95722675988048d840201c3b98e794b1e8b037c +905ac8a0ea9ce0eb373fb0f83dd4cbe20afb45b9d21ae307846fd4757d4d891b26a6711924e081e2b8151e14a496da18 +b485315791e775b9856cc5a820b10f1fa5028d5b92c2f0e003ba55134e1eddb3eb25f985f2611a2257acf3e7cfdfab5e +b6189c0458b9a043ebc500abc4d88083a3487b7ac47ed5e13ab2a41e0a1bee50d54a406063f92bc96959f19e822a89a7 +a30e15f995fd099a223fc6dc30dad4b8d40bee00caa2bc3223ba6d53cd717c4968a3e90c4618c711ed37cc4cd4c56cf3 +a1b1ed07fcc350bb12a09cd343768d208fc51a6b3486f0ece8f5a52f8a5810b4bc7ab75582ec0bc2770aed52f68eace5 +88aa739fbae4bece147ba51a863e45d5f7203dbc3138975dc5aef1c32656feb35f014d626e0d5b3d8b1a2bda6f547509 +ab570f3c8eabfca325b3a2ea775ef6b0c6e6138c39d53c2310329e8fb162869fde22b0e55688de9eb63d65c37598fca3 +89d274762c02158e27cb37052e296a78f2b643eb7f9ae409f8dac5c587d8b4d82be4ef7c79344a08ebec16ac4a895714 +99c411d2ad531e64f06e604d44c71c7c384424498ecd0a567d31ec380727fb605af76643d0d5513dd0a8d018076dd087 +80d0777fa9f79f4a0f0f937d6de277eec22b3507e2e398f44b16e11e40edf5feff55b3b07a69e95e7e3a1621add5ed58 +b2430a460783f44feb6e4e342106571ef81ad36e3ddd908ec719febeb7acaf4b833de34998f83a1dab8f0137a3744c11 +b8f38ccfc7279e1e30ad7cefc3ea146b0e2dff62430c50a5c72649a4f38f2bac2996124b03af2079d942b47b078cc4f8 +a178a450a62f30ec2832ac13bbc48789549c64fc9d607b766f6d7998558a0e2fad007ae0148fc5747189b713f654e6ba +98c5ede296f3016f6597f7ccc5f82c88fd38ed6dc3d6da3e4a916bfd7c4c95928722a1d02534fe89387c201d70aa6fd2 +a8cc5e98573705d396576e022b2ba2c3e7c7ece45cd8605cb534b511763682582299e91b4bb4100c967019d9f15bbfaf +848480ea7b7d9536e469da721236d932870b7bbee31ccf7ae31b4d98d91413f59b94a1e0d1786ee7342295aa3734969c +b88ea38f9ee432f49e09e4e013b19dff5a50b65453e17caf612155fff6622198f3cba43b2ea493a87e160935aaaf20a9 +949376934a61e0ef8894339c8913b5f3b228fa0ae5c532ad99b8d783b9e4451e4588541f223d87273c0e96c0020d5372 +96f90bb65ca6b476527d32c415814b9e09061648d34993f72f28fae7dc9c197e04ef979f804076d107bb218dfd9cb299 +a4402da95d9942c8f26617e02a7cef0ebc4b757fac72f222a7958e554c82cc216444de93f659e4a1d643b3e55a95d526 +81179cbc26a33f6d339b05ea3e1d6b9e1190bd44e94161ae36357b9cdf1e37d745d45c61735feed64371fe5384102366 +ad4dc22bdbd60e147fdac57d98166de37c727f090059cfc33e5ee6cf85e23c2643996b75cf1b37c63f3dc9d3c57ffa18 +8a9b1b93dc56e078ce3bb61c2b0088fd6c3e303ba6b943231cc79d4a8e8572f4109bbde5f5aa7333aae3287909cb0fe2 +8876ef583bc1513322457a4807d03381ba1f4d13e179260eaa3bddfede8df677b02b176c6c9f74c8e6eab0e5edee6de6 +b6c67e228bf190fbaeb2b7ec34d4717ce710829c3e4964f56ebb7e64dc85058c30be08030fa87cc94f1734c5206aef5f +a00cb53b804ee9e85ce12c0103f12450d977bc54a41195819973c8a06dcb3f46f2bf83c3102db62c92c57ab4dd1e9218 +a7675a64772eefddf8e94636fb7d1d28f277074327c02eea8fae88989de0c5f2dc1efed010f4992d57b5f59a0ab40d69 +8d42bb915e0bf6a62bcdf2d9330eca9b64f9ec36c21ae14bf1d9b0805e5e0228b8a5872be61be8133ad06f11cb77c363 +a5b134de0d76df71af3001f70e65c6d78bed571bc06bfddf40d0baad7ea2767608b1777b7ef4c836a8445949877eeb34 +aeadbc771eaa5de3a353229d33ed8c66e85efbd498e5be467709cb7ff70d3f1a7640002568b0940e3abd7b2da81d2821 +8c28da8e57a388007bd2620106f6226b011ee716a795c5d9f041c810edf9cf7345b2e2e7d06d8a6b6afa1ee01a5badc1 +8ed070626a4d39ffd952ddb177bc68fd35b325312e7c11694c99b691f92a8ea7734aeb96cf9cc73e05b3c1b1dcad6978 +ada83e18e4842f3d8871881d5dbc81aed88a1328298bfdc9e28275094bd88d71b02e7b8501c380fa8d93096cbc62f4fb +8befc3bec82dcf000a94603b4a35c1950ba5d00d4bed12661e4237afa75062aa5dcef8eac0b9803136c76d2dd424a689 +97c6f36c91ca5ca9230bfcbf109d813728b965a29b62e5f54c8e602d14a52ac38fa1270de8bfe1ab365426f3fc3654c7 +b01d192af3d8dbce2fe2fece231449e70eb9ac194ec98e758da11ca53294a0fa8c29b1d23a5d9064b938b259ea3b4fb5 +819a2c20646178f2f02865340db1c3c6ebc18f4e6559dd93aa604388796a34bd9fed28ad3ccc8afc57a5b60bb5c4e4ec +a9ffc877470afc169fecf9ec2dc33253b677371938b0c4ffa10f77bb80089afa2b4488437be90bb1bcf7586a6f4286e3 +b533051c7ce7107176bcb34ad49fdb41fac32d145854d2fe0a561c200dcf242da484156177e2c8f411c3fdf1559ecf83 +8fe2caff2e4241d353110a3618832f1443f7afe171fd14607009a4a0aa18509a4f1367b67913e1235ac19de15e732eb1 +84705c6370619403b9f498059f9869fdf5f188d9d9231a0cb67b1da2e8c906ead51b934286497293698bba269c48aa59 +899dddf312a37e3b10bdaaacc1789d71d710994b6ee2928ac982ad3fd8a4f6167672bc8bf3419412711c591afe801c28 +b2f7916d946b903ded57b9d57025386143410a41a139b183b70aeca09cf43f5089ead1450fce4e6eb4fba2c8f5c5bbe5 +8d5f742fe27a41623b5820914c5ca59f82246010fa974304204839880e5d0db8bc45ebab2ad19287f0de4ac6af25c09e +b93d4a1f6f73ac34da5ffbd2a4199cf1d51888bc930dc3e481b78806f454fcb700b4021af7525b108d49ebbbaa936309 +8606f8d9121512e0217a70249937e5c7f35fbfe019f02248b035fa3a87d607bc23ae66d0443e26a4324f1f8e57fd6a25 +b21312cdec9c2c30dd7e06e9d3151f3c1aceeb0c2f47cf9800cce41521b9d835cb501f98b410dc1d49a310fdda9bc250 +a56420b64286bdddda1e212bba268e9d1ba6bdb7132484bf7f0b9e38099b94a540884079b07c501c519b0813c184f6b4 +80b2cf0e010118cb2260f9c793cef136f8fa7b5e2711703735524e71d43bce2d296c093be41f2f59118cac71f1c5a2ff +adcb12d65163804d2f66b53f313f97152841c3625dbbda765e889b9937195c6fcd55d45cc48ebffabb56a5e5fe041611 +8b8a42e50dc6b08ab2f69fc0f6d45e1ea3f11ba0c1008ee48448d79d1897356599e84f7f9d8a100329ed384d6787cfc4 +aaa9c74afa2dec7eccfbd8bb0fc6f24ed04e74c9e2566c0755a00afdfdf3c4c7c59e2a037ec89c2f20af3fae1dd83b46 +aa9f6e8fd59187171c6083ae433627d702eb78084f59010ff07aff8f821f7022ef5fbbe23d76814d811b720a8bfa6cc3 +a56a3ded501659ad006d679af3287080b7ee8449e579406c2cae9706ef8bf19c1fc2eb2a6f9eaf2d3c7582cded73e477 +81971e077c1da25845840222b4191e65f6d242b264af4e86800f80072d97d2a27a6adc87c3a1cb1b0dd63d233fbafa81 +a6fa5453c4aaad2947969ee856616bf6448224f7c5bf578f440bcfc85a55beb40bef79df8096c4db59d1bd8ef33293ea +87c545adbfaaf71e0ab4bac9ae4e1419718f52b0060e8bb16b33db6d71b7248ae259d8dd4795b36a4bbb17f8fae9fd86 +b4c7a9bc0910e905713291d549cec5309e2d6c9b5ea96954489b1dff2e490a6c8b1fa1e392232575f0a424ba94202f61 +802350b761bcaba21b7afe82c8c6d36ee892b4524ab67e2161a91bbfa1d8e92e7e771efb1f22c14126218dd2cb583957 +b4e7ddb9143d4d78ea8ea54f1c908879877d3c96ee8b5e1cb738949dcfceb3012a464506d8ae97aa99ea1de2abf34e3d +a49a214065c512ad5b7cc45154657a206ef3979aa753b352f8b334411f096d28fd42bca17e57d4baaafb014ac798fc10 +8a80c70a06792678a97fe307520c0bf8ed3669f2617308752a2ab3c76fdf3726b014335a9b4c9cbcfc1df3b9e983c56f +a34721d9e2a0e4d08995a9d986dc9c266c766296d8d85e7b954651ad2ca07e55abb1b215898ee300da9b67114b036e0d +8cfce4564a526d7dca31e013e0531a9510b63845bbbd868d5783875ed45f92c1c369ce4a01d9d541f55f83c2c0a94f03 +ab3f5f03a5afc727778eb3edf70e4249061810eba06dc3b96b718e194c89429c5bfbec4b06f8bce8a2118a2fdce67b59 +aa80c2529fc19d428342c894d4a30cb876169b1a2df81a723ab313a071cba28321de3511a4de7846207e916b395abcc9 +82b7828249bf535ef24547d6618164b3f72691c17ca1268a5ee9052dba0db2fdd9987c8e083307a54399eab11b0f76b1 +8fbcb56b687adad8655a6cf43364a18a434bf635e60512fad2c435cf046f914228fb314f7d8d24d7e5e774fb5ffb1735 +a3010a61a2642f5ebbce7b4bc5d6ecb3df98722a49eb1655fe43c1d4b08f11dfad4bcec3e3f162d4cc7af6a504f4d47c +b3dcc0fdf531478e7c9ef53190aa5607fd053a7d2af6c24a15d74c279dbb47e3c803a1c6517d7e45d6534bb59e3527f5 +8648f6316c898baaca534dff577c38e046b8dfa8f5a14ee7c7bc95d93ae42aa7794ba0f95688a13b554eeb58aeedf9ba +89fca6fc50407695e9315483b24f8b4e75936edf1475bcf609eed1c4370819abac0e6a7c3c44f669560367d805d9ba63 +a367a17db374f34cd50f66fb31ba5b7de9dbe040f23db2dcc1d6811c0e863606f6c51850af203956f3399000f284d05f +91030f9ca0fff3e2dbd5947dcf2eba95eb3dbca92ee2df0ed83a1f73dbf274611af7daf1bb0c5c2ee46893ab87013771 +84d56181f304ce94015ea575afeef1f84ea0c5dbb5d29fb41f25c7f26077b1a495aff74bd713b83bce48c62d7c36e42d +8fe2f84f178739c3e2a2f7dcac5351c52cbed5fa30255c29b9ae603ffd0c1a181da7fb5da40a4a39eec6ce971c328fcf +a6f9b77b2fdf0b9ee98cb6ff61073260b134eb7a428e14154b3aa34f57628e8980c03664c20f65becfe50d2bdd2751d4 +8c6760865445b9327c34d2a1247583694fbeb876055a6a0a9e5cb460e35d0b2c419e7b14768f1cc388a6468c94fd0a0f +af0350672488a96fe0089d633311ac308978a2b891b6dbb40a73882f1bda7381a1a24a03e115ead2937bf9dcd80572ad +a8e528ec2ee78389dd31d8280e07c3fdd84d49556a0969d9d5c134d9a55cd79e1d65463367b9512389f125ed956bc36a +942c66589b24f93e81fe3a3be3db0cd4d15a93fb75260b1f7419f58d66afaa57c8d2d8e6571536790e2b415eec348fd9 +83fe4184b4b277d8bf65fb747b3c944170824b5832751057e43465526560f60da6e5bbee2f183cb20b896a20197168c7 +88a71aada494e22c48db673d9e203eef7a4e551d25063b126017066c7c241ee82bedaa35741de4bd78a3dd8e21a8af44 +8c642a3186ca264aac16ee5e27bd8da7e40e9c67ae159b5d32daa87b7de394bf2d7e80e7efb1a5506c53bfd6edd8c2c3 +81855d6de9a59cef51bef12c72f07f1e0e8fe324fcc7ec3f850a532e96dcd434c247130610aaee413956f56b31cbb0dc +a01e61390dcd56a58ad2fcdb3275704ddfbedef3ba8b7c5fce4814a6cdd03d19d985dba6fd3383d4db089444ea9b9b4d +96494e89cbf3f9b69488a875434302000c2c49b5d07e5ff048a5b4a8147c98291ae222529b61bb66f1903b2e988e5425 +b9689b3e8dddc6ec9d5c42ba9877f02c1779b2c912bba5183778dc2f022b49aed21c61c8ec7e3c02d74fe3f020a15986 +a2a85e213b80b0511395da318cbb9935c87b82c305f717a264155a28a2ea204e9e726bae04ce6f012e331bd6730cbb9d +91b70f44c7d8c5980ce77e9033a34b05781cbe773854d3f49d2905cc711a3d87c20d5d496801ad6fd82438874ce732b8 +884596417ff741bb4d11925d73852ffeea7161c7f232be3bdce9e6bbe7884c3a784f8f1807356ae49d336b7b53a2b495 +ae2aed8ab6951d8d768789f5bc5d638838d290d33ccc152edfb123e88ba04c6272b44294b0c460880451ad7b3868cc6a +89d8ebfb9beebc77189d27de31c55f823da87798a50bca21622cbf871e5d9f1d3182cf32ee9b90f157e6ce298e9efccf +afd00a4db4c2ed93cf047378c9402914b6b3255779f3bb47ded4ab206acb7eaebba0fd7762928e681b1aebcfee994adc +a2e49b6cd32e95d141ebc29f8c0b398bb5e1a04945f09e7e30a4062142111cd7aa712ac0e3e6394cfb73dd854f41ad77 +ae8e714ab6e01812a4de5828d84060f626358bb2b955f6fb99ae887b0d5ce4f67ebc079ab9e27d189bf1d3f24f7c2014 +a3100c1eebf46d604e75ebf78569c25acf938d112b29ccbe1a91582f6bd8ef5548ae3961c808d3fb73936ac244e28dbc +a9a02dcff0e93d47ead9cdddc4759971c2d848580bf50e117eb100cafca6afeaa7b87208513d5f96b1e1440ffc1b0212 +894ab01462137e1b0db7b84920a3b677fbb46c52b6f4c15320ef64f985e0fc05cec84cd48f389ce039779d5376966ea3 +b1e40e8399ee793e5f501c9c43bde23538e3ce473c20a9f914f4a64f5b565748d13ab2406efe40a048965ee4476113e4 +a5a7d97a19e636238968670a916d007bf2ce6ae8e352345d274101d0bbe3ac9b898f5b85814a7e4c433dd22ac2e000ff +b6394c43b82923231d93fd0aa8124b757163ba62df369898b9481f0118cb85375d0caac979a198ece432dbb4eb7cc357 +82d522ae3ff4fe2c607b34b42af6f39c0cf96fcfe1f5b1812fca21c8d20cece78376da86dcbd6cdb140e23c93ae0bcb2 +b6e0d986383bc4955508d35af92f2993e7e89db745f4525948c5274cfd500880cb5a9d58a5b13d96f6368bb266a4433e +b0b4325772ec156571d740c404e1add233fb693579f653b0fae0042b03157d3b904838f05c321d2d30f2dbd27c4d08ad +ac41367250263a2099006ef80c30bac1d2f25731d4874be623b6e315c45b0dc9a65f530fce82fb3dc25bd0610008c760 +b6c0b1ed7df53da04a6f3e796d3bfa186f9551c523bc67898bc0ecfc6b4a4a22f8c4d3bfc740ebf7b9fa5b0ea9431808 +8e78fca17346601219d01e5cd6a4837161a7c8f86fe2a8d93574d8006da5f06ae7c48eea7d2b70992c2a69184619663c +a21f91f47e04fafbfafacf3185b6863766a2d0c324ccac2c3853a4748af5897dbbe31d91473b480f646121339c9bae2d +a464d68786ab1fc64bd8734fce0be6fbe8dc021d3e771ff492ada76eedff466577c25e282b7c8ab4c1fd95ef5ff3631e +829a24badc7714081e03509ccfb00818ce40430682c1c0e4a399cd10b690bda1f921aabcbf1edfb1d8a2e98e6c0cedd6 +87ccf7e4bbcb818ef525435e7a7f039ecbb9c6670b0af163173da38cbdb07f18bc0b40b7e0c771a74e5a4bc8f12dfe2c +94087bd2af9dbeb449eb7f014cfbf3ee4348c0f47cde7dc0ad401a3c18481a8a33b89322227dee0822244965ae5a2abb +896b83ed78724dac8a3d5a75a99de8e056a083690152c303326aa833618b93ef9ec19ab8c6ef0efe9da2dbcccac54431 +821e6a0d7ccf3c7bd6a6cc67cde6c5b92fb96542cb6b4e65a44bbc90bbc40c51ff9e04702cb69dd2452f39a2ff562898 +b35b2096cda729090663a49cb09656c019fef1fc69a88496028d3a258ad2b3fd6d91ab832163eaa0077989f647e85e7e +b7857ef62c56d8bce62476cdb2ab965eddff24d932e20fc992bd820598686defe6cc0a7232d2be342696c2990d80721a +b343d974dfda3f6589043acd25d53aecf7c34b1e980ae135a55cda554ff55e531bc7c2dfe89b0d2c30e523c7b065dad1 +8d139e16a73cd892b75f3f4e445a10d55d1118f8eeafc75b259d098338419e72e950df6ca49cb45677a3c4e16fb19cdc +817b8535bd759da392b2c5760c51b3952ecf663662a137c997f595c533cd561ed7e655673c11144242160e41d1f2dd71 +817ee0f0819b0ccb794df17982d5b4332abff5fec5e23b69579db2767855642156d9b9acccf6ceab43332ccc8d2744dc +9835d2b652aec9b0eba0c8e3b6169567e257a6a3f274ec705dbc250ee63f0f8e4b342e47b9e0c280c778208483d47af8 +b78c40177f54f0e6d03083a4f50d8e56b5aafdb90f1b047bb504777d6e27be5a58170330aee12fbaa5f1e9d4f944acfc +ab8eebacf3806fac7ab951f6a9f3695545e2e3b839ca399a4ef360a73e77f089bb53d3d31dbd84ddfde55e5f013626e0 +96c411fc6aecca39d07d2aff44d94b40814d8cfc4ee5a192fd23b54589b2801694d820a0dd217e44863ccff31dda891b +8249c424a0caf87d4f7ff255950bbc64064d4d1b093324bfe99583e8457c1f50e6996e3517bf281aa9b252c2a7c5a83a +acf6ed86121821a3dd63f3875b185c5ebe024bdb37878c8a8d558943d36db0616545a60db90789c0925295f45d021225 +a37f155621a789f774dd13e57016b8e91b3a2512b5c75377ec8871b22a66db99655d101f57acaecd93115297caabfc21 +92e60ee245bd4d349f1c656e034b1a7f0c6415a39ac4c54d383112734305488b3b90b0145024255735e0a32f38dba656 +acec614e562ccfc93366309cfdc78c7d7ee0a23e3a7782a4fc4807b8803e6ebfb894a489d03e9a3c817ff2ec14813eba +b912f9dd26ed552cb14b007b893e6ed2494d12517e5761dbeb88521270144f8c3eb9571a0ad444b30a8a65e80bd95996 +8375408dae79c547a29e9a9e5d4ec8241b36b82e45e4ca3b0c36d2227c02d17bb171528d3778eac3bbdc75d6c4e8a367 +8c2d0e6e4406836da112edbbb63996408bb3cda4a2712fd245e4bb29a0100fdc89a2746d859b84a94565bc1cfa681813 +a7431bf59e111c072d28c97626cd54fcdf018421d053a787d2aef454b91251ee8ff9d3702d06b088f92b9ad2bbebff15 +8f3659b0fbeb90b7f30b7a49233325e806551a32911a654dca86e290b314483bbb33fe6482387bc48c35d85c1dd0441c +8dca5ba23f0bb76f7dacabf12886053552ba829a72827b472a2f01e19a893155cdce65f1fb670000f43e8c75ba015a31 +8c1514c083c77624eeb5d995d60994a2866192e15c4474d0be4189fae0e9dbd62494ebb4c02fbc176b53be548abbc5a1 +80498d2ed153381baf3b0f81da839ed0eea6af5796c422b8e59be805dba48c4395bb97824ac308170bb4f14f319c5ddf +84f5ebc3bf96362457993e9fa31493c31c4283075e2403f63d581b6b0db8a3df294b2085643f2007f4de38cb5d627776 +958e6e38774da518193a98397978dbc73d1c3827b4996ec00b4183da2c305a187a0ada9aa306242814b229a395be83c9 +ab8b8fbf73845615e7fab3e09e96cc181159eab09f36b4c1239b3c03313c9aeb4bbb51e16316fe338b2319ed2571b810 +977e4e33b33bd53394e591eba4f9a183e13704c61e467d74b28f4ad0b69aa51501a5221cb1e0e42bcb548ca518caa619 +a9bb7ecb9846cc30d04aad56d253c3df7004cebb272f6adf7b40a84adef9f57291e0d08d64c961b9fc406cdb198aab9b +8d2b72dc36406a545a9da44e1fddfb953d4894710ca026d6421a4ac91e02d0373a599f2acfe41d8258bc9679cf6f43d3 +904192fc8fe250f61ecb8a36abbbccae85f592bbf00c10039c30b5a1c733d752a04e4fd8a1000c6578616f8a16aa83a3 +87f5fdfe20bbbf931b529ec9be77bbfcc398cad9d932d29f62c846e08a91d2f47ae56ad5345122d62a56f629f9a76c4d +84cc3a53b2e7b7e03015f796b6cb7c32d6ded95c5b49c233ac27fafa792994b43c93cda6e618b66fce381f3db69838ba +aab58da10d7bbe091788988d43d66a335644f3d0897bbc98df27dcc0c0fcee0ac72e24f1abdd77e25196a1d0d0728e98 +a10ea8677c2b7da563d84aa91a314a54cab27bb417c257826ebdd3b045d2a0f12729fe630bbbf785d04874f99f26bee8 +acc4970ef2a4435937a9b8a5a5a311226ca188d8f26af1adfcd6efb2376a59155b9a9ff1cff591bde4b684887d5da6e5 +8dc7cf6fcca483c44eb55e7fb924bf3f76cf79b411ae4b01c6c968910877ac9c166b71350f4d935f19bdffb056477961 +ac2dd1182ded2054c2f4dbf27b71a0b517fb57193733a4e4e56aca8a069cff5078ffd3fd033683d076c1c639a4de63c7 +932ec87c450cd0dc678daf8c63cd1bf46124fa472934e517fbbfb78199f288ff7f354b36e0cc6c8739d3f496cfe0913b +b0d631ced213e8492be60ea334dbe3b7799b86d85d5e8e70d02beef3ae87b1d76e1df3bdb5f7ba8a41904c96f6a64455 +929d7239ead7575867e26b536b8badf2e11ca37840034d0e5c77039f8cce122eff5a1bf6e0bcadde6b3858e9f483d475 +aaae5d372d02ee25b14de585af6fbc48f2c7cd2a6af4f08352951b45aa469599eff41e820df642ca1a0f881120e89dbe +b23c411741a6b059f04fa4f5fd9dd10e2a64915f2de6ea31e39c32f2f347a776a953320e5f7613fcb1167efe502f5c5c +a4581b0ae633fe29c6f09928e5efb16db019eeac57f79fef2fa1d3c9bee42ce0e852bc60b9d0133265373747e52a67a4 +81b33afffd7b2575d4a9a1c5dd6eee675c084f82e06b9b3a52a3c9f76e087f12dca6e0ffddc42fb81ce1adb559d47a38 +89cc890f06b424591556aabdfdbb36d7a23700425e90c9cfed7d3da226b4debe414ac5bdf175273828ce6c5355712514 +a4399438be75cfae2bf825496704da5ed9001bed8538d8ac346c8cf0d4407808e9ee67573eb95fe1c6872ac21f639aaa +ad537f7ce74a1ca9a46fc06f15c1c8a6c32363bd6ac78a3c579ed8f84252e38a914cac16709fe65360e822ef47896de4 +8e53b69f5e3e86b86299452e20ea8068b49565d0d0ab5d50ce00158a18403ae44e1b078a3cfd3f919aa81eb049a30c6e +a59f2542c67a430fd3526215c60c02353ee18af2ff87cb6231a2564fe59b8efec421f18d8b8cc7f084675ecf57b3fd05 +b8d9bac93ef56cb4026dd1c731d92260a608fd55b8321e39166678e1dab834d0efddb717685da87786caeb1aaf258089 +aa2df56f4c6fe9e0f899116c37302675f796a1608338700f05a13e779eb7cf278e01947864a8c2c74cc9d9a763804446 +b0108ff2e327dcb6982961232bf7a9a0356d4297902f4b38d380ff1b954bfbcae0093df0f133dd9e84d5966c7b1aada7 +b06b813b01fe7f8cf05b79dc95006f0c01d73101583d456278d71cd78638df2b1115897072b20947943fa263ddab0cd6 +aa41e6c4d50da8abf0ea3c3901412fe9c9dff885383e2c0c0c50ed2f770ada888a27ea08bbb5342b5ff402e7b1230f12 +a48635dbb7debac10cb93d422c2910e5358ba0c584b73f9845028af4a763fd20da8f928b54b27782b27ca47e631ebf38 +80a574c208e994799e4fa9ef895163f33153bc6487491d817c4049e376054c641c4717bda8efbeb09152fa421a7268a7 +b592bfd78ae228afc219c186589b9b0b5c571e314976d1ed5c1642db9159d577679a73c049cfc3dcfefcd5a4f174eeea +aa1f08af3918c61eadf567a5b1a3cdcdfb1b925f23f1f9e3c47889762f4d979d64686ce1ce990055ef8c1030d98daa3b +857df4cfd56d41c6d0c7fcc1c657e83c888253bae58d33b86e0803a37461be5a57140a77fb4b61108d1d8565091ada1c +8fae66a72361df509d253012a94160d84d0b2260822c788927d32fd3c89500500908c8f850ef70df68ddaeb077fd0820 +aa1dbefc9aef1e7b896ff7303837053c63cfb5c8a3d8204680d3228ac16c23636748fe59286468c99699ae668e769a0c +b64b1cb2ba28665ed10bad1dddc42f3f97383c39bad463c6615b527302e2aaf93eb6062946d2150bd41c329697d101be +b6d35e3b524186e9065cee73ea17c082feff1811b5ab5519dd7991cdff2f397e3a79655969755309bd08c7d5a66f5d78 +a4dae7f584270743bbba8bb633bdb8bc4dcc43580e53d3e9e509ff6c327e384f14104b5bdfe5c662dc6568806950da37 +aae84d3d9ad4e237b07c199813a42ed2af3bf641339c342d9abf7ebec29b5bd06249c4488ce5c9277d87f7b71b3ddd37 +b82a463cf643821618a058bddf9f2acb34ac86a8de42a0fa18c9626e51c20351d27a9575398a31227e21e291b0da183e +8b6c921e8707aded3ea693f490322971b1a7f64786ef071bc9826c73a06bd8ae6bf21bc980425769627b529d30b253ce +80724937b27fc50f033c11c50835c632369f0905f413b1713a2b0a2274bec5d7a30438e94193d479ba6679dbe09a65ef +a1d9b259a2ca9cff8af6678b3af0a290c2f51e9cf26d5fe3c6a4fa3d28cbf33cb709b7f78b4f61cb9419427983c61925 +96a3e69a5ed7a98ce59c4481f2ffb75be9542122ad0eb4952c84d4536760df217854d4ec561ce2f4a79d3793c22fa4f4 +990c4d9a4a22d63a8976d34833cafc35936b165f04aed3504e9b435f0de1be4c83b097bbaa062483cf3dee3833b4f5b6 +b9bf5e4b270aec4a0dc219457b5fed984b548892c4b700482525ba1a7df19284464f841dab94abfabcaa9a7b7a757484 +acaecf49cb4786d17cf867d7a93bd4ffee0781766e11b5c1b29089ae0024c859d11b45828fbff5330b888543264d74a9 +b0e1a0865b1e6f9e4a0e31d0c885526ac06678acc526fda5124742a2c303bd0e8871a0cb7951ec8ed9540fc247c8d844 +82b3d327b3d1a631758451e12870816956cd0cef91fcf313a90dd533d5291193a0ff3cc447054564ce68c9b027a7ffd7 +a2843602abb98f0f83e000f3415039788da1e9a096bfe8fed6b99bab96df948c814560424ffebe755cb72f40436fb590 +ab1c7b43cf838798d1e314bc26e04fc021e99a7bfbfc8ffde62fa8d7f92139de86a377289d5177021154229de01ede15 +95e5cf5dd87ae3aed41b03c6c55f9dfad38dc126b17e7e587c156f7745c8da0bd1d60acb718fc1a03b61344f01e3de4d +86f021a3762bb47167f80d4ef1b1c873a91fe83409f9704f192efeebbc3ece0729cd2f92f63419907ea38ae47bc907d2 +aaa1445dafbbcd645d4332d9806225e9346ee5ac6b22ad45e8922134fe12f3d433f567a6a4c19efdd9d5775a7de1e92f +8fd7e15688eef75df7b8bca3d61bc9fca4f56e047cdb6d0b864e7d1c4966eac27d6094b0c8482b49739f83ec51050198 +80aab8b4d394eb011d4ec6a4c2815617308c9b847c6fa6a3d7e6af1c79420ef6ff2a13934a398581c40ee4cf1cac02ac +8970b97ac076a1d8a321ce00eada0edf974a46bf3cc26f6854e4218cdfc8d2b0c32199d9658f254b4fbae5a2c5535f41 +a1aa2ec5b03df0a630e73dd048680ed6d3032c324941423f45cd1f16038789e5e75b876a13948732e9079a422f66a9fc +b5fe5f5e2f2ae2beeb8e95859a02fc45f01f9fb0ebb2bd8ec9ec976b3e806228821a9775096d341d662bc536c4d89452 +a2bc1f170b62d0d5788b02391337b2ab157c38e725694e80aeead7383e05599be0e2f0fa27ef05db007061809356e147 +a8a69701d4a8d0d972390e9f831fd8e9f424b2c2ef069e56bd763e9e835b3ce5f7cf5de5e5c297c06ace4aa74df1067c +b43d551af4ff3873557efe3f3fb98e5ede9008492f181f4796dd1a6bcda8b9445c155e8146966baa812afae1abe06b48 +b4b1dae44fd596813f30602ab20e9b1fb20cb1bd650daacc97b7e054e5c0178b8131d439a9e5b142ca483cc012a362b3 +b95b8a94c30a831eaaebea98c65cc5d0228c78afd6603d4aa426d8186aecc951f1a11c33951f51df04c7e6fa43ffb5ae +b100059624cf9db371bec80013a57a8f296d006c139a8766308f1ea821c7eccc26cad65bc640ab3f6cef9062653bf17d +8e5a2cb76716e0000d13bce5ef87acac307362a6096f090f5f64e5c5c71a10fddfdee8435e7166ba8c3ad8c3f540f3e4 +93d2c43e21588c1e83c4255c52604b4ac3f40e656352d1827e95dd5222a45aebff9674e34fbbe7ed21eca77bd9b8dcbc +8aeaed611546bb9073b07512a9a1f38a7f436ab45e11775a0f9754baaf63e9bcc7bb59b47546a5ded5e4ba2f698e3b5f +af9e6792e74a1163fe27612f999a2f3cfa9048914c5bef69e3b2a75162bb0ce6ece81af699ad7f0c5278a8df0ba000d2 +850bf2d5d34791c371a36404036ad6fdcd8fb62d1bb17a57e88bda7a78ea322397ce24d1abf4d0c89b9cf0b4cc42feb3 +87f7e2a1625e2b7861b11d593aaac933ed08a7c768aebd00a45d893ed295bbb6ed865037b152bb574d70be006ddc1791 +8dcce8f4ad163b29a2348ea15431c2c6ea1189ece88d2790e9f46b9125bd790b22503ec391bc2dee8f35419863b2c50c +b4bf5266c37f12421dd684b29517982d5e4b65dfdfba5fc7bd7479fd854aabf250627498f1e1188a51c0a88d848ec951 +8651623c690247f747af8fdffdc3e5f73d0662bc3279fa2423a3c654af9b6433b9e5e0155f1ce53857e67388e7e3401d +b155120f196d52760129dde2e2b1990039b99484cdc948fa98095cd23da87679850f522e5955eae34ac267d2144160d3 +aec8115e8d7b6601fbceeccf92e35845a06706d46acd188452c9f7d49abef14c6b3a9a9369a8bab2fd4eb9288e2aaca5 +998a8ca4dc0f145f67a8c456f1d6a7323c4836fe036dcbb0f27eb1c596d121eb97369638a9908cfaf218c7706f266245 +b235fbafac62802742ee3d26b1f4e887f7d2da4d711ba7f9bb6ca024de7beec1de66bb830ce96d69538f7dcb93c51b26 +9258d2ddc21ab4e3edcde7eb7f6a382a29f1b626003cc6fdd8858be90f4ad13240072d8a8d44ef8de51ca4f477fa6c45 +99d038487821c948142c678acd8c792960993dd8cb5e02cb229153a1ee9f88249f4ad9007f08e5d82e2a71fb96bb5f32 +a88ee9dbc73d3d8e0f447b76fdb3a27936bde479a58d5799176885583dc93830ac58bca9087075950ea75100cf51af23 +88b9b15816e5a0387153c1f4b90f613beb3ea4596037da01a81fdd2bcbd0baf5598db99f77e7694e5a0d35e822758108 +907ae4b637d06b15846ee27d08c9c9af42df261c5bdd10cf5bc71f8e5ca34b33ac2405307023c50bdb8dc7b98a2cd5fe +9393d6900e1d2d1a1e42412fefd99578d9ac1d855c90a3e7930a739085496448609d674ca9b34016ad91f22d1cac538e +a28ac56b216730b7dcdb5ab3fc22d424c21a677db99a9897a89ed253ea83acfd9d83125133f5be6d9cd92298df110af8 +b027590ee8766f1e352f831fda732adbaf77152485223ad5489ef3b0ce2d2e9f98d547c111fe133847ebb738987fb928 +a9cc08fbd5c3fee8f77cf6eb996a5cafa195df5134dab000e4d0312f970a5577942ee89794e618074f49841f1f933a42 +a8b3535c3df0b1a409d3fc740527ee7dd5ac21756115cde6f87f98cc7623f50cfcf16790689cab113ee7c35a5bd4879f +b61420227b97e5603ae8a716c6759b619f02b8fdc48acbf854352aa6519dad74b97bacc1723ca564cbf3ca48539ed773 +853762498de80eebf955a6c8ddd259af463e4e25f0b6ba7b6a27b19bdbf4c585de55760a16e2d9345cdba6b2a02610f3 +a711c1b13fc6c30745203c5d06390e6c82bd7c50f61734aa8d99c626faba30119bc910be63ec916c91ba53f8483c05a8 +b488c0a793f4481f46b5875d96eecd73e46209a91677769f0890c5e002ecd7d4b1c9f4ba68c47fbed40e3857b1d8717a +a651c5e812ae65b1c66d92c607e80be330737ea49c1dcfe019c0ecea0f41a320406935bb09206a4abff0d1c24599b9ad +85e34e7d96e4b97db98a43247b6c244383b11ca10bf4777364acf509a6faa618bc973e2136a4693fbc8ab597e308fd5a +99837214102b394fffa7f3883759554c6bb7a070f5c809303595a44195e02b9a169460dc6bbffb62bdc0e7ced5f0a5c1 +a952f89c0afb4bdae8c62b89cc3cfb60d0576ba4fe01a5d99534792f38d8848d919b3fc7577435d8443a044d2ee0bcfa +a1ac1f81acb29798acdfc493854663519e2d1b0e9d23d286ce33882c34b4c1c0bb43dd9638166d8026315a44d9ec92a8 +ac9c58aa38219ae659d23007cc7b97fd25b7b610b2d81a8f9f94ddb089efc49c049a8ea4c56e6eaf7b6498f422a97b3c +87e61d501c242b484fb9a937ef21d485f6678d75257fc8fe831b528979068cadbe7e12b49c34058ec96d70a9d179ab14 +aa45f6852f35cc8b65a4a8b5380641d2602a4fa4e3a035db9664df3ac2e170b1280c4a8b7b55161430063e54de4158a6 +a46975614ddde6d134753c8d82c381966f87203d6e5a5fb99a93b0d43aa461466b37f07b8d0973a1abd6ee2b40f24348 +8d35f97297773422351f4d99564c1359ef1a10cfb60aa0e6c8985a78f39b4268486312c8ebf9dd2ef50a771aa03158eb +8497c6242102d21e8b3ade9a9896c96308ab39171ab74cbd94e304c47598e2c2a7b0a0822492ac5c076ba91d4176481d +973f8fcb5f26915b3a3ef6fe58cc44bc7f4e115cd0ad9727d8d1b8113e126ae2e253a19922c5433be4ab2311a839c214 +ae3ee9f1d765a9baf54b4617a289c3b24930aa8d57658a6b0b113bbf9b000c4a78499296c6f428bbb64755dfd4f795d2 +a5be7a8e522ef3dcf9d2951220faf22bb865d050f4af2880b8483222ff7aad7c0866219fcc573df9d829c6efbb517f98 +a5f3c7fabd7853a57695c5ad6d5b99167d08b5414e35ed1068ae386e0cb1ee2afbbe4d2b9024379b6fc3b10c39024d36 +978d5592d4798c9e6baceff095413589461267d6a5b56cd558ec85011342da16f4365d879b905168256f61d36d891b1f +b7b6eaffa095ecbd76d6e1e88ceebabaf674d9ef7e331e875c6d9b9faa1762c800ff1ea597c214c28080f67a50a96c1e +8a1ab53ae5ceaa42e06e58dd8faf6c215fc09ba111ca9eeb800612334d30d5971448be90fec62ed194328aadd8c8eecc +a9ca532cac8ace9a9e845382f8a7840bf40cb426f2fcad8a2f40aadbb400b3a74021627cc9351b0966b841b30284962e +8dddeda8854c8e7ddc52676dd1d0fed1da610ed5415ddd7d25b835bd8420a6f83d7b67ec682270c9648b2e2186343591 +888906aac64fd41d5c518a832d4e044fdc430cfe142fd431caf4676cafc58853ce576f098910d729011be0a9d50d67b5 +96a3f886a2824e750b1e2ea5c587132f52a0c5e3ff192260d8783c666206bd8ebd539933816d7cdd97e4bc374e0b1edf +a150a29ffb2632cc7ec560983d9804cd6da3596c0c25956d27eb04776508eae809659fc883834269437871735de5f9ed +81f7ad4d2959d9d4009d1dfbc6fee38f930f163eb5eac11e98dc38bd2f7f224e3f5c767583f8e52d58d34f3417a6cf90 +97ccac905ea7d9c6349132dd0397b6a2de9e57fd2d70f55e50860e019de15c20171a50b28a5c00ef90d43b838253b3d1 +95694f00c21e8a205d6cbda09956b5b6ec9242ec8c799a91f515b07dcc7de3b6f573e2c0ba149f5a83700cda2d1df0f5 +82bbc3c4a3b3997584903db30fffd182a266c7d1df3e913f908d5a53122fa12cf5acd11d915d85d5bd110fcc43cee736 +8d3f24b4949aa1b4162c28dfbb9f813dd1d8b330f71325448dc45ea34d59b69ca95059402aae011e1b5aba6e536bc6ec +92c734c19752d24782331e74c9af97a8399ddfdd32954e91cda7363dba876aca4f730b451c50a8913950420682da8121 +8653d2c79f77b8c7dcdf7e8dee42433998aeedf1b583abfca686d47a854de1b75e9a4351580c96d1a2a9532659203361 +886f0e414cb558c1a534a1916d3531320a9b6024639712ffe18164ce6313993a553e2b9aafe9c0716318f81a5d0bb1da +b31b5efaba5a5020c3bcea0f54860e0688c2c3f27b9b0e44b45d745158f484e474d5d3b1a0044dd6753c7fb4bf8ace34 +b2d615bbdfdc042d6f67a6170127392d99f0e77ae17b0e1be6786ff2f281795f1bf11f83f2e0f8723b5cdd1db1856e09 +a6e014cca531e6ac2922239b5bee39d69d9ba6d0fa96a4b812217dd342657d35606f0b9c5a317efd423cdb1047815e3d +a8921736b69c9fbb29f443715174bac753e908251804620c542fad6cfbfda7bdfe287f2902f30b043a8a4b4818cfdeef +8d73a9949a042ec2dcefa476e454cd9877eee543b1a6b3b96a78ffcff87421e8b26dd54d5b3192ac32073cb36497acc3 +b936a71ee8df0e48867f3790adf55dc8efc6585024128de2495f8873bd00fd9fa0984472125e801ed9c3cdce6698f160 +82f69c06209c28f64874e850601dda56af44ffc864f42efa8f9c6a0758207bf0a00f583840982dec0a517ab899a98e5b +b7a0a14411101473406f30e82f14b13e6efc9699e7193c0be04bb43d1b49e8c54812ce0f9b39131a20379c4c39d3bbe3 +81159c969f38107af3b858d7582b22925a7ccced02fae3698482d7e9cdc6c568e959651991c6cf16c53a997442054b61 +8bf1116a206e0ce9199fcab6ed2b44a9e46e8143bff3ed3f1431f8d55508fe2728b8902670cfd8d9b316f575f288ed9d +a279b2149824b64144eb92f5a36b22036d34a52bd5a66e5da4b61fbc95af6eda8e485c7914f448abd8674fc14d268d9d +8b98279b5f3588d1a2f8589d2756458690a502728800f8d94b28e00df842a101c96ab9c5aee87c5bbe65552c0c383b80 +b4a27a351ec54420f94e0a0a79d7c7a7337940399646631baca93eeab5fd429d7fb39428be77dcbce64a13eaa3c8ca1d +90c08baa29ec8338ffce381eae3d23ce3f6ba54e5242dec21dc3caaed69cac13f2ab5e8d9d719bc95720fa182eee399c +85156d65bb4fef69ffd539ab918b3286105ca6f1c36a74351ab3310b339727483433e8f8784791f47b4ba35ca933c379 +923005013c27209d07c06a6b92b0cbb248a69c5e15c600bbcc643e8dcd2402adebd94dd4cafb44ec422a127e9780aaec +863b23eb5463a6ef5a12039edc2f8e18e3c97b244841bc50af02459b1bcc558367edf2f6e4fe69f45f37887469dd536d +87a4a7708a112724ff9b69ebb25d623b5cae362ae0946daed2ec80e917800dbfcd69f999c253542533242e7b9a5cc959 +8bf4347ceea7f94b53564f26b1a4749a16f13bf71a9e03a546f906f7c423089820ff217066159b0637d9d6824e9c101c +ab07eef925d264145971628a39e4dd93ff849767f68ed06065802cf22756fc6bf384cf6d9ab174bfc1a87bcc37b037aa +8e3f10a42fad43887d522dc76b1480063267991c2457c39f1e790e0c16c03e38a4c8e79a0b7622892464957bf517ebd8 +a8722fc7b1acf0be18f6ddf3ee97a5a9b02a98da5bc1126a8b7bf10d18ee415be9a85668eb604ef5a1f48659bc447eb5 +878d6b2a9c0aca8e2bc2a5eb7dd8d842aa839bbd7754860c396a641d5794eab88a55f8448de7dbddf9e201cbc54fe481 +ada881c167d39d368c1e9b283cf50491c6bfc66072815608ba23ab468cfbd31ca1bd7f140e158e0d9e4d7ebfa670bc2d +a2b48578fa899d77a7ee1b9cb1e228b40c20b303b3d403fd6612649c81e7db5a7313ba9702adc89627b5fd7439f8b754 +8e051280e10551558dcb5522120ac9216281c29071c0371aaa9bde52961fe26b21d78de3f98cb8cd63e65cff86d1b25c +a7c5022047930c958e499e8051056c5244ae03beb60d4ba9fe666ab77a913a067324dfb6debcb4da4694645145716c9d +95cff6ec03e38c5ab0f6f8dccde252d91856093d8429b7494efc7772996e7985d2d6965307c7fdfa484559c129cca9f9 +993eb550d5e8661791f63e2fa259ab1f78a0e3edad467eb419b076a70923fede2e00ddc48a961d20001aaae89fad11e8 +abb2826e4d4b381d64787a09934b9c4fe1d5f5742f90858228e484f3c546e16ee8a2a0b0a952d834a93154a8b18f3d16 +a922ca9f2061996e65ef38a7c5c7755e59d8d5ce27d577abcdd8165b23b4877398d735f9cb470a771335fc7d99ecb7fc +90f22862216f6bc1bbf5437740a47605d1ff5147b1f06f7b13fec446e4c5a4a4a84792cb244a1905f3478a36f8d7065b +87f3d9a86afef5b79ea1ca690ee1ee4bb9754b66f7c50a42ad6b99af7c222c853ca161f440a0a2a60b3b5a54e3493240 +80a9ca9a2d33b9cf61976b3860d79f5d00de89a06ef043d2a52931809018aeb4ce70423cbef375b29c2c750c2c8704c2 +b4e798ef1d615896108dae37ac50c1e859216ab6dbac11653e44d06ce5209057b4b0dd6d31dcfcda87664a23c8ef1cbd +aaed6d1e7c5b1db06f80dae6c24857daadfb0268f20e48a98fba4b76de1ebf65fb84c3be95fd6a418b498f8285ec63bd +aeceaa316c6369492c939f94809bc80e0857abac86c0d85be8066bbf61afbaaec67e28c572437a8d35c49dd596b3134f +b791c3d53ed34a7d1c8aa89b7953e3684c3cd529230824dc529739a5fbe74b58b87f01e56e7a169f61c508237ef67160 +9351f8c80634386c45c0050d2f813193f9d839173be941e2092d729be5403632a2f18dffdc323d69eb0dc31fa31c5866 +97693184d5c0056ae244dfb6709cafa23a795dc22d497a307a7f9cf442d7452024023c54a8d6bda5d90a355ba2c84f3a +85362daa003d23511ca174a8caafe83d52b6436dc4e43c4c049e5388d9211b5cbef3885896914d86d39be0dd1f910511 +a2511b5fa34b24eeb0e1bcbcf872a569d1ff5570fe7b0fb48f5542f7fe57bad808d34b50afa87580866a6cb0eba02f27 +b382e3327eb1401f2d378dbb56ac7250adde0961bd718575a64d264ffd44772c20752d4035c3ba60eb435e160b375e20 +afad8a5d40b536c0720556845a6b257ed42165c14fb4b4a874717d107752f49ed9380c5b048df3aca67287bb8fc411a8 +8fad0c98434ca5373c2d767868f679b76b4a8d04bca8240ea3f388558262c2d61b73b16fc1160932652b5688c25fffcf +83898008b5cbb6f08f8ef3ec179427869682bb4e8d38f6e6a687a214d4a307436afc64ee67d70a5a8ba9730bf839aecc +b85232e79913785fd82b06890706972b4ad7a309489930ae23390d51aa5189731f8a2df24800409a8c36b3dd6fc91275 +a24ff26ec792f3701da4c5638c1fca4fa4dae95b01827d6200d583c4caf17ea3171393ba2a8c23d1ee8b88402916f176 +adc5c7a7ff6b41d6cc386b7fc69d7bb04179bdf267864f9aa577f0f6a88438191fa81ebaf13055c2f2d7290be6421ace +a05e835abd502d31454d40a019010ff90b6b0b1f993075a35c9907aeab7a342ac0ba6144dc9379aada6119157970e9b2 +85ff07ba58463e7f153fc83f11302e9061e648a5cbd272bb0545030b20e11facd8b3ff90c9ac8c280a704fbda5c9d1b0 +a6c735ada8f4587da8cdad7ea3ada01650b5a3ecab8d81daa7a5f5de51ef4a6592b524692584306f06be3f6701f2870c +b138deee4e53ae8d677fae104f713ef1b8babfecec16b6a85785a66a72784eb09d44c3b63567222ade714e98f7d1604e +ae79c1a49dafcdd972acd95d8ad0a35c02adc7fd736d4c44c3cd13df5789d339b5ea16bddbbd43e486a061ab31baa5c0 +ab3cf2371a1d7dcd0ffe3869a0178230964b06694bf258b2073ea66a2afccd845b38485da83d02e1d607d4c5c36b78a8 +ab9609f28a325fd01cb39540e3a714506c44e52ef28ee640f361deb5760aadbb23e804663b0fa20a66e239c33f8d8bb8 +8ed95ea8e76e1b42823d7915a6aae77d93746f846bf602841dfce0e47543a36efb9ee7e5b42c73c3209d911225cc471b +a80b6162036d43811482323f0ce59eb18740e33a63d7c7bbbf3be206985919e5342d53a69df537d43e8b7d7f51e8892f +93c03d0a5083408ba00c125a8a9385213d4c860072f0297857b1235045819b904e07f2425c13a661d0a01d2e53347f4b +a6581200f00f96c461621e1d26b14a23687dd97eb9f7df4ba641a84340ee7306dc1796248fba4804f185947ad13b4385 +8be174018fa40f7e0cedc5ae68f38969eb7695f2205e9c573641e533d56f68c20abf38a23d2f0dcac371e60b21b18615 +857ad4ee3218c647c58f09b8ab22bcc8976f00a768ab1f708618e868e6143474be846422ce2710a0ed39b5155b6f13a1 +a490bec40f322d599f26bcefcdddd8f2ef6576aa737d5ce7e8d5d422741abe749e3e6a48489aed8c560633f72857e3c2 +a9c0ee339621f1c4a2410f9b4d2f03f1b558dae2973807b8bccd920e8feb7f65dfde3e79986b72ad21fcc4567240381d +8592251568e750a430f7d2c6ddbb3ec82a4dd9fd83efe389e69aa177fd97ac2c96c59a6e86db20d8e6f125d65b46c4d3 +a4e2f4aa6a682913b423b097c4069c4e46a1f3af9556b1bfd0580d0fc01e3991488458049e0735b2a629684a79271c8f +8c4f6a3e738cf74112b08b1680be08158013ef8a515a81215d8a36c9b756786d1b4cb4563923463f3329292f4b48bf6d +8bace547353c02ea00dd547eeda7259aa354d4772dd5e0c486c723cf88627b7112e196b879c3c92a9561b674d9fc486d +8d372f4901e25e8db64fa098148d4a4e709b0e9dcb756d0f90dad99dea393054193ae1a33d292a3dd772ff7ba05e4b71 +a8c7ea6a6a031ed23d65639f01f5423190775558f479700597df7ae7e338a6ae5e9b32f470aff20787ac8b7eec84df6c +b6e9dcba240fdbbf66033410a79a2dd3e9e1ffdf2eae949b3a9ed720e939d92339991dc3e70a5ac7d5253f317daf0b7d +974dec4cd61af75721071752c664d9c2a5121f06ff1515c56139a177a3ca825f763b69d431d4607e393fa74dcc91cc58 +958863e6ad583a9d370a6db3639066982e44766904e7afa849b132f6666b7d08ab931131b3bec7a506d6583e93d56767 +8b93a33b5da9b3300c20a96d80b894e3789c77041183c2cb21751579c8c96857f60cfc2f075201b64e95a78985c5b321 +b726cb9f7ef34ddbc2fad82b3b0af0b30cc913e26c5a614ae5c19cc9c55c8e6dae069db5315a8dcb6d987415bb550ca8 +a730f515398a71bddd66cab2ff996659d4e47dfbb08ce7958a41021f76d269b91c7498b708cd14b183a8ef469c772803 +a4eb3b18132eb0f5337f14e01d63ca0bec0db6a43870f800e5491db756c2f5fce519d8dba5528b4bcef550d06b33699c +b1ab6621eec1ee6784e632e214693f39a14f3715991996b883d66200963e065c86fa0667f7bc36b93b40b5d90ff708c2 +80486a26c3532ad6e19f76d8c9344e2626c07363fd495264927cb5935fa9565ece670dc98767afb04af6a9a5c9231075 +8ee20e0df3c84a1c6b0e21bcc325cf99235b747ffe47f17fdfba548a358ca75cbcc331dd50db2311b400ae882256a608 +aef4268959e5541e7ec69c921a1e81a8374d7e44bf1bb2debf4101cf3cd6b7d6ca7f441758b388de96b3e0edb5b97be9 +8793629bd29d689ec94b016de8886cac6e2ca6638911babb22db4a787661422da0639a4e4089ebeb689d173abfe75950 +b487b3551c20a29e9a5abbda8c50ff594826283e443c09e3ae09b914e46060b3f9abf70434444ce1487e2a74e562616b +8f11531cfc5997dd04b997cb87ba1831aa7041d5434fe72de66304e3f165d882fac891391fbb1eb955c65319e65293b6 +b195136875fd02a75676c33cb3e60504d5964f7a9e81f4c8c8fd38af62e2145c55f765b3158664566191188ac678f381 +b374174b0b3eb04fa49eb4ece45173f0db5d829eac370a20a62309566e0f98b18f72f3633626893c053b7be6bfbd2366 +b2a2f6b0cf652775679b2d677048f2ed8c31a3269e6cddcc7a10e3e6fee89e486b50d9d55fbe452b79c4157c0270fb77 +892177c364dc59032594e7a6fd032286ffdf4fa0b9e3baeb37ec839faebfd2fd46c57b2c9bfe9977b59c93a9cc0ead1d +8ab7c0038a7dbb2ef200dbbe9acbc875829ecad4883792d5c6ce283de67ccd9aa935a9cc7b30b2bd9de7fca7bf2a9a05 +83745cfc78ca709835aa6c6a233c2b86fb31e3f9f6a8becf63e501f2841c4366fb7d131b746c9d3291afda714ff05579 +a723dcb67925ef007e8339dc578d2622d9bb77cfda87cca0088854a59414c02338752c56116a6c1281917842e8467c38 +8a098142da0af2254c425fdbbd0d1b1a17b2bd781391ab37f181775524b8563c64ab8a1602aee2ac6c0a82ba11a8b1d1 +b13bd7529a9b351c5d395c794c28bcb0a3167f1c992e8c062eef47be9be27895945231d249c73a0b6949daa295e14944 +a20dcd2fc2222eaae467d9f5db861040f58bcb991a26e5663ac3aa5e1ff13d0010657c5af586cc4621757add2b905073 +b818f660c3cc4e9f273c25ceeabe562c8afa8ff88529c26f2cf45ae6b2813cca5f350e3cbd56f6257c4df41722dabd25 +b225d5987108b24411bc389276f12509a45e86d5ad6b6d929af5274df0be11109c0fed329669a0acafdf3b0beaa8f2ec +91fcb6d04576d3c6bae947bb7843b430e5fb0592ae49b0a65dfa5791f4eaa4bf2c7f436c8de7360f217001c2b4e5c67a +8821f7a1424ca3fdc5d4a5606ad10dfaba6094cf36669fa9f84cf7617e50425405d14980780e1e18a1ecea7913cda896 +990dcb7f38f56521a70cb71bf4522649fcd46ac052c7feabb0748dfcac9f9c0f95d29e070d32af3cd0adbf869535e17b +b0fac1029fe2c1100f24e2f4bf10c7672199fce53513c7dde2e8d9b00702edf0143e0e1dc7ceae7dcc6994edc2422b6f +a514ebb1a33451b4915c05114db0b10168393613744df848b24e43e09f0bda23baefd9d731075198aace586615ac7911 +8b77f7953c2e67049fdca3653b8d8cf3f799677f79b954da02bdad8cc4d6c855c1c7c16b4f6f9ba35f46426ec28b2d84 +875520cfbda16ec5b1d1d00f578a910d0fc052f17870ba093e22e310bb07648d34817cc2b8811b6f52de535f7046a0d0 +b8c77b4be0b430851c4ff69e91cb770db1935d848198601393810ef395efab52deb9d5c6525472bab720273d5e0e7a79 +b6d4d437146671bdea62fb6545395ea3df39f1cdef21b8476b68e7a25aa7354f847740576d6c9f187bbae9941f0ae450 +95c642f1bccdb62cd6a2212dcdd6ff8d49aee426ca08b7cf3a9d15249d24a9eed5533f92a70c84498c0797f8a57efa27 +b617978047ed0f748c305aa7f30c2dacd0db00baa67fe0c5ce346ef0e6991dc7e05f18dcb2702467421f8390f27aa815 +86411c7a00b3e8b43bf22fb061b1f54ad9bbf632cd74395a478218389c0f544668acf3dd7726532d080ca7da9a5f8608 +97bf684a8849626c4710a6992f6c11f6b5406fd4dfe9e6aa502425aaafe9827e2c435aaf9a5d3d2ba3a4c0e8aec79ba4 +8b178e2a125b461d3180906ffba0af3dce614c64058501fdd35243ababf892d6fcdea4834ce42c25d5569452b782a709 +8ebed2c8a25c61da6a6a8cb0d8f5ea179e28869753eacc728f2c076f7aed8598cd3aa0981f120f9e7ea55b3a689ae882 +a6f235b8e655ca3d634740b53d8c0a757ecc75d2b8838b7948997c1985473d01943d935f687b86cee56cd47c8e773443 +a7959c465a9646908b9d8032a589e41a7dd999f2ffc54bb42f22e5f8a4d8c493a31bcc7ea2cac6c8dbcc59acace7181b +96d0532df2e12da20a57cadb6cf5f6c4ee1aa4775629358c25f1d51677a3e96d1fe3b232532324b4f02f941952d4cc68 +90f493473d686b639a30d1ddc9c72eae6e983f1236e162e58e967a477c0654973ea2e1bdf4ba1a44d7247bc1befc2cab +8b2d87876d9c4085102a07ebb41c565ba69acab99ffc03efc18f20e48d3f3bbe4fc6ddab9c78fe479d9ada80504d85ba +829a0fb3200a28e09cacd6c5346000e7786116ddfd898f37dfd17bef454a8abc0fe939ed8735c00769f7f2f33cd4f906 +86194ec9e88ddb7150e8b03e7a535b6e99863fc6762835601efd03615aa97aaeb413cb210e86035086ed852b39c9d019 +b02efd116a7189cb317ceae392bc301ae55470f0489fa89934e182aeb8c67e280299b975786fe9a470bff46827defb9b +87d7c3903bd22b12d815506f150373f518d47dfc6e5fd74347d88b518124c9923d1e4c98defeb3a45d53d50b423e2175 +a1a430406b28254a7d6348bc98e697e9bab43839aa05d53faee97546f84541ea0b559162619b2045182938f69bf61cae +99d243c226c61c6697fb3d2594f3533fa5dfd7cfc87107908cacde337d7a077fa5a9dc702d26081b065edb1227498e65 +800ee5006ab6217161f42db0cfc552a81728bb4fbd7af6e4620ea099a65ef6664184af3f65a07fcec7e965529c5b49bf +91bfd307579cadc8f81009558605be3edbcb8dbba271475803484017f40130b2b216aef4f620d960193be681877d3a53 +96a060459dec458d19a6f8af6e49dc6c7c58c55dd18915c5fce5e0f4b4a422fce3b9632f6059388fe760289abf70f173 +9921a37f3e657222c7fda3588418a9071409711d9f1fccede7494429f02a45fbc52d79fbb64e9ccd518f60d06d0520d3 +81052b0d15773cb75975ca9230ebb2579700e489c7e3f07cd9cde206fef38b8139bd4976d2b4a7840495fc645f96df03 +88ac37ba66d1de5e23878c992e4d54023729e97e77351f50dc5918d738b5a73faf1dc6feec7e85784761836ba1c6f778 +ae1e6072c13060775f6086d1ae1f88b627ffcb810fc0e0e97deea1f3a15ef0aaa52a6dce2563e4beedadc131af2a8281 +8b60a340f5e4f90badf83001b495ac9f13974c3d2054ddcb3e6b8ca99dec5cd63a263e05c282454191ab2e087d5a2911 +832e2d56ba69dbf817b2b9dbd25c1538d5b8dbf5d9bc05e6be85054a423ebb66a71b157e166e0b9444ac171b34b7ccc9 +8586036fc7dde1e7e3ecb61663130c4529866ae9f5f5095b9fccd24a4c70eea899aae5f10ea1ba66d1665b2d83be35b0 +a77969453b5c083a207913272b5b69d4ccbd8718bdf54be8fbe11b4bd0a2168aae3ba8f9362afa69c0ffa28d7e5a2340 +b7fe9568c214baad0ac5f83745611b481f744ec1c4fa78a549b180dcf79633e5ba75dc20055012a13d849eb7a9be57d3 +b01cad1d2a6c51c0ce88243d1f52f95fb5ee315a905079688027511f0c4ecd0563a3a81846709d272fa5ccb9665e8043 +8eae0a21adfc569aa57237654021c2bdb2c6f0f52ccc90a126682c21a1f9413c63d285f92b2b2f8649150a9284bf70b7 +942acc947192b5f3cf60e92383e5d35f79e7a5904e8e9fd1c8a351676c83ad29b0afb6578d555457cf909f8f4d27adfd +a74e092f8628fba9abcabc27e2e9f3d5a9a941dfe50a2dfde2ad179aabc73afd196676925c2d98643ab8b3d02bdb66ad +896159daa2afd757cf3f9d34af248ad68bb3c62e4c9ac49919422727479cf669098f270b9e645607a7d11adad4c889b2 +a428d8370813d78e7a2a24eebd36e9da2f8bb3605e5a39b5fcda939b531c35a8ebaaa642ba556250a37bddeec90326fb +a5fa04eb60a1d5ee9820e78f42f7be15e1c02757b539aead995768c6209684d6c183c71d282e0c12a4c15c03f9a89d4d +93c77d5d220e40affa7269a6915c076c9aef4db552c643ae5d560a79c955b491c6346ca4cf11cbb7fe1894e28d47b065 +802e605d2de745eef6981d88e7a57ef4046a2062725e8080995374cea2b3273c27f35b7774d0dcba014710d8d6c501f2 +82f7169e6ec9b3e2bd450f35ea2e66d06bcf900acf5b73139677b48e078ce2e16599103027b2326770c99c0a690f2015 +b0c8581879439f9b997551233fe2de71aa03604f9cec37a7b18c5854342d9b67be468f3cac4bf6f64fe8a0066248c498 +a3f626848a4db6e9fb01cac90d3362ec521e969ebd5228af694ea3671061476149f13d652942ac1e39f65591fed740f9 +88a8e759b9cbe16a7c16e43f4afa2de6100d2eafa4dee75ccd653ec38c919013d0a6b35c1ee1eaee7c1985b58bcc9e92 +a3d5fc7aaea072798490616552d947e95f49cf02a420314307aafb555287ec607d75589ba24b009cd68299dc6f7942fa +a809cceeb84f9bcf3c3ddafde3041e7bc3b1d14df8830ab849002176a0725e6f16f70774d8962cb0b8ac0dc43c4ac66f +b8f2e46c031cc8fa160a08c2ebdfa85345ed14771b06daa9636b0e7792b7fddbc501dfc85cc626a01104a43a7d3230c3 +b5367e2a521c318b802ce16ceac80c4b8139f73ddb10ddf38433397cda70a86ea1f051cc55626a4e99d27f30f3975ff5 +96d963660121c1441cd13141279cd371a6a0aa18b6a20761b18df60aa9c14e13489afd83695a0921d5232efe72045f07 +80818d492fd85d666bd91aaf6257b86527fdd796773c793407df1d4a0f91d74649a6bab4d15155c36ed4c6e0a32c5636 +931e22918905fd6c230d3d867ea42861f3074d320d14e1929031924c8ac209a5c552b679b24563bb12f9749b4ee983bd +a4de2c333e74ed9bfa3c0bf6a0beb90427abd9aa4221294cda74331646b58ef46ed57cccc8798ba2b9309894b17cfd69 +883881554c1d88c0ed8d3b6dec3d200f6fea69a77ace3e4d6f86b41506a23724b4394ec8384075f9c75c3868ba8a8e8e +aa0539ecf6ec9bf06f24443027f8f24b6b3d8c5b2084248eecd4bcad3c9a69716e1a0d01057f09a65bff1006ac5e157a +856d74d44c943c9e809b42dc493dff20eca03cb0cf5ed45108c69b1f90d8592a53ae8100e99380a274fafad23e74cdfc +9188257446661c88da093b7c5ce998135913f63842d7c1586065377b169ee35b062d925367fb9b909ca971f1188667b1 +8d3aa57cdafbe998938787479f5d590c1484c6dbe94e6c487e57a746ef5252be0eaa5976d6270de7db64b6b92e57a0f7 +b8f4d6997240f9eda5aca0c43323a828d1563c491b3db2087f60ac4120a3fcd06075fb42bb19d0339ab5ee3fb7db25d2 +ad247ea94b8ae1e81eae4c9fd7b39e6601b53cff47b2547ff90a3cca87192eae28408082774a1fd14bf9ab459b7a4f1f +9598598070f8bdbcc49056c40971e673726cd8c1bc4baa0b5124dfb5fb750e7baa7a7df18eae2bd91955ddcb1ec67955 +b874131ab1608667fa60ea29092d090859eed1812e90c609afff96d79e82c5ba546f617f4c96fc32c9bba97431c1e9af +b00750a9cdc75c2a54f0d3cc99b0fe02300754f25166f7ac85ff41ab5e9cfcca33a29be76a480f12a2d410c7cd5032e5 +84b5bd1c90bb6c66755b28ba4af493ca1b0c3a4df9f436aac67d2e07289053f925cf6a149a84e74e1027dc8758150179 +99caf64bd9d193ff306e8ab5da3f1bb2a190a60c3a82099b8d03d17fa810dc53d176c21379f479e828f60d25beb3ffd0 +a8fd9de502f1c261d5733430e5a18d8b7892a98c9529a016fc2ee53892ae965dcd9c75850bcda4c7edb980b8d88e60ea +848c02cac636e047028a3fe8c1bf4066fb7591b96b0340f8fbd476ff01b35fa3e37d309333771a134f24800e5f3f9289 +a1eab1a06dcca3439f0166441e7e7f2f5b56f5f8aa9f45e411c561f556e0fb71c514c06c26ac53b49a576caca5faac3d +aa603f970dcbe953e700e61c151182c8d32cbbb53ceef572ac93383db33a4b098b5c7b267e42d514ca66b740c0925efe +b55fd5301bd700ddb0b4f72fabe9a91ad49759506101fa802ed1677e9553595aa4d2c66f7574e78d21ce882ce0120ae7 +829137bc4da7b4886d3d04d2c39cbf4b1dc40c813ac1adb425c7b9abf9142b516314cab79c68454df5d71994ce416144 +b83a3a22735001f783dd48a01c4fb3598a51ff3987e842b8045c71c035b9e43645a55254ca5911a5676ef4a8af12d056 +8ca8d463deb13f9eef5e533bc39efaeb0c15631282c5c0deee1673b0053a7cccd514af09801dd6c158caa159fe9351ac +a9ffb1427828f3c456b9c8cc50782de1ab0029b9233a0fd998bad0fd014d27e15c4a32d1e16ad41bff748378b5abdf49 +9627e29f725ddd86456aff813976bbc4a836f4deabf5ad9f73d1a260ceb30948824df9c8841e6b3c529652202be181b3 +b52c988647fe3d9276eed3c262e1044f57fbb116c64cf4f207235c205b3fda0f3d789bf90f5217401b468d85fdfda404 +833bbd6e2924f5c4446cb76b881d1434a5badce9eb9b003f85d076e297ad7ef45b822069fe54d17427a348c3263fb838 +a067a36352db6f82a116cb87d3db5f60b18576852409e2076cbbfc7843af78866313a4969385a40271051dd195d51116 +902b99545971f9a103f99d7399acc347ac46fe156166e51deefc0e92aebf5893460c69aeeae11f5af9f49418e289ce6c +9206a0e9ce9b9880f29ef0417c96931985f5d83bb17cebdbba4ff2af81a3d37155b04649426f698aed372e4f669599e6 +b54a5d7c976e45c0b1d44433595eae9d1ae9aeabfd58cd5ecb0c5804756a7b01c9a517754423b4714a3695533a3114c8 +91b612131e84580ece228b81ace83da0269b53f94d3c02a1a0879ebbd81bdc252064b3d03a7e140b43a90f237d9a45a0 +a6cead3b8607eaeafe37135bd6de8fbd16f806c131eb71c8d36bfbe295d45b070255e50dabf076e2c3f6b8699be71d6a +931da21e67b11ba6ce438546a24d063bcd51aebe39b4220a78d9c0aab88b2d37969b5ef3502d835507f9c8d6d006714c +8fda408caa9daf01122a2308b7b9d328f52e1e2f138a8bec30492488f4d710e5e52524a6455a3a2ae2818ec8a610b650 +ad8ad5c189644352d90c462731c46145410e5adf38682bb80f95495dd64d9d13782537d68690847bbb06c6be7175dbc7 +87bb5cc466ade60feb0961421c3fabdc8a7e20f11df8437bfff63d3f8bd25305002a396c9d0fa4fb9a9986d4717f12c4 +827cff72870ba00c29064a7d2b4973f322d6b6de7924c93d8bf8825e7a0e8478c7748f90f5c716bf83c55b2795d315d8 +a225895a8e94229776ceb51b05356291f2dce748be17a60d5aeb33ef8507c368bafe5d1d6eea927f28b9d1422b661b9a +8e011323ce670ff51c964241a6b72e0e0ffbb3ff9bb2762492323fc3a4abf4718091be0945287c7329850e4f74462cde +a2c03c2e5f4e9d3ef361f68b188451994ad1b24de9f323370559c8abfcdc7bffd289d92e78a5f6b104b0a12c84dab2ef +a22b4771116ce22276fab1fec6826610707ce8a342f9f60b079c4e0259dac3cc41c96c560dfd0ada6edd2828f7c0e8d6 +97c17441d0af9be83b42097aa8b7cec84a253b9a2b957214b8fa93c26d2add46144faffa7b8a55312059b10690f711f1 +94bdf348849f31a2737cbae5e5848aee711067bac85c11c2e68b44c398cfafbf3493a3226cd1ddf7a916e7613fc7b6f6 +838f59c6e8469a8ec6fd40b978a3607439aaebe1e50ff707eec72c0b8278af05b477bf12a384b56d03e3d4eb91e56f67 +a1940f0db58185e2b3aedd2b0bc2b73b4a65c68e09b046f38e9dcd4e13c94f5406bea92635190bf315e48ec64eceef2f +b2f4e0ae44e1f1210a91d8f280f17091fa994034ba8c991583f8182a323e9b3001a712e3584fc2d64ecbf2d319d076b2 +9342b89c721338d02c7854cd7466fb24d93d7313b6114ea591e6607439c8ddb911d1cf35f01898e9c557982bdff8f9b6 +8583fcab15be1dd14d5a415f4b14d706c8c62f058500f1344b37730c8be6741779691f87ded3cbcf6516468b373cafb0 +8fa9587c7989646571ad9032f34cedd353caee14f5be5cde1e9e0a1710f90c08faf6fa96a60e1f150f761c9c8ae7417d +8d9ff904cc08141f5a9879f5f77dc600e6edbe859082231a4d819953890199bcc5f940b730ea688332f07e5279d49e1c +b5f82b46e5ef9a2df8d144202d6e2e4f3bdae8e2048d2af5ea7deb3f722fbe6d370401954e74ff0d8cb1010ffb1f38d5 +a3b5b57d435b06ed70530e060002a8fea71746ad07d969ca23f22b5e52624527595b6a6d54b4e953fb7b7596bac378f0 +b90f89390df6d4b7879b915aa3c29b8d779d035033f8873bb7ac54a14ec98f0d08c0e3bf696e2ffa7b5730d736f571f8 +8e81e371b92887e43d95c0dbdcc9575282b26ccebdc8cbf46587e4f2a83b61e9bc0c6d7d1f114b9d21e04fd6c180b12a +8d682947c51dffc6e0fe0a486293c9ed121f441805168236393087cf62f2a429cca60bf0e472564844347d32c6bea27e +a8341ec7dd189fa7168759240224192c58209b53fc961c18082deba217928c399bde08ceae42bffd37c1135b4d14a845 +a94bb076dcc5ee5ec82fac57c5b384c690df12631882bd1b960e1eb8c04f787bc22b7bac315b9dc5a8a098f17f051a0b +ab64e1c6f01b87706c88a3bd974454a438722768de7340b834ccf93ea9880c14ee7c2181432acf51f980d56de73832ee +b7b0058bb724d879e5ad7aed6230297c54cb599ef659e86bf2cc84c38225899fb388391df9b2e6fdf063171937fd8c72 +ae856f4fb74c27cc98b67429186e7df4feb01278cd57bfd3170af6e52e0a23b9e926bf9565a890cfb4ae8f2d590b2cd5 +804b9c6702f0596d328f92fc1ed5a30a7ba17b9204524135001b569233fc4937035031d079f52fd04968f37c24013898 +84274ed1af6bd6a968583995622b4d18c6a2bc703ce0d0edce45bb736529b4836343dcd11911a94a134dca7877e6cab8 +88808098463f7505034c3b6328c8a08186b33f7a981c08376e429dd64b79b97753170531ed078dd265ded4ec0a1ed8d5 +92823bfb23a4eb84d3759e7d717f0c8641ece0927cd2ba8c728c26bb35df2629a838002f353c8d3d75eb19520aab5f25 +8db36bae4d960cdb9c51f419d7ddc81f372e56be605bc96a9d4072b829f05527c37c8f255cc6115300a2a0d2e6568d89 +a8fcdbd7f3b4d7ff04149a209feb75e97149e7efceaa42d66a6b8e432590fe7bd01f1a77fa8b47108f670b612e33fee9 +a9f4c53c62db7e5dbdea6918862d3c6d24b5bd8732a218edf0ba61e9d1861182323d8ecd7bef8f895b42970b492f6e40 +8b95bc7f07818f4d7b409aff8da0b2c2ae136cde386f53a71565cae9fd14c73c13cc1cfd79c0f97cd77839fb738c5b9a +adbd1d11adc756b51a571ddbcbf4392415231ddad93da09acfafee03a9e4f9e1ce3826110619e5271feadfaffce3e793 +95d327c8bb195cdf25fd79c98f9406a6b0316214b1630ebcce95bdaeffafa36fc1accc6882e0e5d13a8db5c0f3c0e61c +8cb2f1e2fb25558869afdacc7bb866544cfdd566cefcd048b48d458a886130bd086ecb7600a960a7f2563c61cb326510 +b3aa8c4bf5b933d89cd74ca7f7176d6624d562d7d58b041328b49d7562a30b489cb606abb3c49e85baf04c28e9cd1f44 +97f9053a85250c420599827297453c2cfde087065b823d9e43139e6a9cac3a2ec40a1b6e2f0726bdc870fff215462f0b +878d5dbe6b881389c2ca126ff66d87127c9aaa3f62f0d2c1ec0ea2b279ac95f8a06710dce166415db227655e2345a04d +b2c33a6b4203e3ca5247f0890e475518317ffc44cfbb1da9a1ba02114e8b752bea618050b876de5cf3b1906140a64471 +a56170c8313d2b5541a795bea9934d4425b185b5c409f0484df6f44f0e4bcbf50b860ff46b7245cd99c1cfa8fc1965b7 +96e2b658e2876a14147385fc423d2702a3cb76962b6b437222cf9cea39ebf4bdc03bbf434b747866d4bf72b4ceefa639 +89c4a74fa2f067e7ae49c84ef782c331bcc9245db7e941804e2e99d12e987b4d25cb827778ad4c3566c4fc68018650b6 +a01d30cea7d01c80ff26650020fab02e78fc3842e2398a81b44b21d58d4e9816166ff4ed2418831fa995a28ff35cb6f1 +b960c80b55a8845bbf24bc3f23b0110ca701f9544ab6a5bb7929330213cb471321e55c390ceca3e24bff69bdb0d331c0 +802c5b13f22be7be0e5db11eb3be0f0ea7f9182c932265060ba05fba20ea093dd2810d3b969ee3e387e60fe6ee834e8d +92478f88ef7435d15e39a97916c736abb28ea318394b88678fddbbaab3eaf31776110936abad116a8ff6ca632dd12043 +a6d3da0370c303001d5ed99d1db8bce1f26b0e442f0f042e36db9674e92dcd6e80465e772f1e669f99221caee3392fe9 +938f04f70a8f947d6df2f0c0e9af3cce0c06edbb3c131970dd60884fc0b0a0959c504a2a36c3ff76dfe919905671626a +a7117e55224230822e9983df2132347eb7208cb6798f291df926ab51e04b1a1f78d5568c9a8924ee6f57426134360f20 +b91074c77ad93fe48dc2b10c0c5a62ca3ab7d98345b919c52d84a9dc419b59fc1b267e1c2d4b2e120016ef84bbdb0cbe +aa175c6b6edf02fe8778762c9575581c0ee6efc9dbf99c291a41444a23a056b893be6c45333d907d0bbe9fb0eef84d08 +ad36dcb4e2ab425aa339ae464b038d550cb11186741dcf257f1b8b80ed4f32ffabbece45e2dc1525d4c3eeed819ea04f +91cb35c1ffa9cd5aebef523edb8325078da3eb5cf9e95c675a76446fc7692aaee6f949de064ca2f3e0f082cc3fa93e20 +82622f9410c143a86bc4d756b3c7b324dc295231ce865de020d61cc0868f2c150a473cea3a5b756b36771ce1032415a5 +a5c29996ad3a53468ece9356a5b4ccb68971ea1c89cf39644f1da2d4a477c2ea99bf791ef902b87c225d8c53d67c4c92 +92893eceed1af34fa92b23dcbab175b6a0188a27dbac9ad3317c4e39955a763cb383ab13fb1c519cde311d8a4d12e8b3 +8a093cb191b94b0200e38d31955f9d240e2be1edcd6810a2396a061f17c3ddc9c4f4d56766ddff4e121be7110e03b869 +93981473df0cb1f4b47c7d9b64e3123dcf1593845b401e619f5d7c70b5dbea375d1ca43fca65845fcf0a6b2e0af43791 +a6beb6b0697070f9562910add88d9ba91992f8da127b27be81868b1596d1012f09ea7ed601b4a6474c921a1a1a6d866c +92026b1ee30f2ed61c9f30337c3356844217926aabdff383c19ca3c21e0bc49811ca5b308012bee4ef250cfae1615800 +ac0ebaea6d35f84dac4ce648af096305ba68a7a0aea0a11ab2fbe3162075444a158433c98141bc92ef3b3400d6deb46a +83046f482dee24ac3ca83373f0d1b82ac1c4beda0f229a9011a81ec659ff5fc1fb105e219975b5c744308c77a24f71e4 +aa5a312c47ff7248dcb9c6ffbe5a0628ccd565c07365c4413734d415cd4fb35772622ed833862dddff520a67c509c6a5 +a02fb88805c34018ac33582e19ed0a7e4616acc3dd0867e5f21914c2031c05c6dca30b8b35b57c2b137750f3878a6f8c +a60528f1f14bf0c496491d46a0fbbd6c343e4eb3f1631e92f96a3c5e5c684091aabe5801df7a67f7c6dfd1b0d35269d4 +a1fd8e7fad8ca05a340c05a051bb0eb4197eed345f4104629a9e38e234b09d789cc5537024615feb4a6177d32d39e39e +8e70e36c1aa070815440e19443f1f04aae23b1b59fdbcba43b47b94a026c82c8f66c5dfe54f826f4d95ee1930cdb8008 +8234c1969fa7e9079661e4ca309b71b1aaa10f4372be0b963205c23a81f5a3d52ec08ba9ff65b37f832b52d631580d61 +a18cb4134127fb37c4abca328cd0047378a2e1423490af2bd3eba9ffcc99ca81a3c22404c0886f21f65c7b93c41d7981 +b46fa45fe538816de776eec086e040005706cb3eca097e290abfb6864e745c879868aac8361894f3c3564373ef9ad55c +b96ca43b96c59e95439f75d1e726a35a9362f0dbd34963b156e103e080a8126a8dc3501f9fd541ff3bcf4677f5c4a86b +a8e8c87c7301613818d57387009e601a7ab5cbdc2890f63d985c30c74f9cea2d0584c116baf0d9cd5594386ee93fc661 +b47e4f1b9153ef0981f813948150f283b47a7346fd9921d51fe8e4daedaef78ddeb4fd467c2ccb7cebd9816243da1c6e +a370c202a99c8441ffe96fad0f801086d4d7cc7b960f6e98cca29ceedf492afddfd0f351c9c4d29ac008bc255ec1a2a8 +8f5e6ce1655d1c059b006174e3f5a55c88e1821c97f9702ad8e8455d46c2a83ae4482f2d43edda74a835686ec45a8a15 +a30421e694930a3b65d397b2720d5f8e1eec2b6e2bb5a28d3f9b0a84db9aabd83850268bae64c2b10e313cccf120151b +8abe87163046f7a9b18e2a3c0b66e258facc1b31431420e0b70354b7a60ebd250a784634a76692e7d6f4330b62114945 +894f033cf077d4eb312e3258d9dca414356271abce1d6094ecce6d018c5fadb1c15d8d69451574ad0701a2876db191c5 +b0923d64f88ffc872654e1a294bb1af8681689c21cf08f39afe51448a68e60a9a0a74ccce9969276a932a52c07d095a3 +b9ca23b5be8725fae7fa710eefd45522889c50c29c26384e00b78a962384f0aeff9d15cb5910e9565da12a577eb7e5ba +b242ccf292757197a9f470f2d80ccddc48c7f1235ba026bc68a93be2738bc968e8a200aff3e2f4807216442eb3fc50dc +adc2c3b375b308524b79a024ff87d122055440643fea6fc0a651bdb312c7cbe6a456afa9d342bc76446d77d8daf08bc2 +ab645955356c2ebf2f3df9da275e01daf0b44a52afc309277d6d9ad1b05484e5ae0d9d41ad485fe481e5e362826a86ae +8de96ac587a4449fcc8b7fd0a51b4b5185d9c2eb3434f94cbadd092de1e26b0f6b3f7b15a37e8424b1429121ddca0ecd +94c70ad4e9b871566f3da98170b665a09788d421818299857cde0853789fb943cbcf7d4b2c95246ea7b72edc56a8e36c +b2574be63497843340700b701d5cc8be6d23125bd62058802ee67cce1f3b5f5602b27c93fea5611f27dc695ac563f042 +869ec89da7850cedd88bcb3a50a15cece233119b31b64a61bf6b2310892ce42d8b473b584b11e61db29ed24ce8033f83 +8fbaa269da8e28e9adf4c1b08f109da786dbe9cba871c32eecbfb10619b7a5d65a26f9bb33e201a8ed20b3de94003fbb +8bf7a059c37242caf7f821a6314e4e4adf799e0dd86b37892a7172598892c07272acebd05b534755c57b51556b2d610f +b4e72645fca459898cdd9214892ed08b5c99f82049c0a30d72bac0b9717caa9c6cc16c3dc7aa6ea4d42dcd2a6c175df6 +a39170da87a3495da55bbb9701c5461f3403447174ed6a4af75712f7ba4ac35f51a4234bc4b94da888a0959ee109c0c7 +b45675b2774ea7696089dbf7a0afe6c22e85fd0e4ef3db508fbaf96c9d07f700c991789206da9309fd291be696357c5f +b52899e3e3f6341eefcbe1291db6664bf3b6e8021d32fb9c3e37b6258a35c1da927747b2ce990937d6f4c6c3e7d020d2 +84e5bdb3dfe19700d79dd3fabb0159ccfa084f7288db836c855b827613ce8071067c8d7ac5cc2b4e88ed7f84b690f6e1 +801477d200b6d12fc6e0a9bab1c8211193ab06e44551e037a9b4c36fc2d4f67760b9ff4eba9a3bc7b6e177e891f64ff6 +b6b71a5116d3c22af26a7530f535e9b7851f25a84e562a8f17a125d55b9b3fc1bd8cfe65bdcbeeb328409521e802051c +8687e21c34d7804c12489d30680d131ce2133e2981bfa993afd8a8eeda958ebd5e6881d342d725338659882d9f21cf98 +a024e97a7c4de32b6383c34431994abc533ecdbd6be9bff836ec1af022f5a86773bf345c6f33273797a61fb70a8fd5d6 +83f784f095da20ce5b31f54d6cb14b32a8a12675f0029289c9cd036b7c87a8077be2d04a62618685720e6ee69c875e97 +b4e9dfe7cb9d9efd3fe00d99ae5e48769d4af4bf43d4e05c0b54c9cfd8bc854de96b8d3ebf4dcc06b9dac66b7471a0de +a08b79f9d4673afcf7f38b57f484f88feb7c908f597663a2417f92c348150c2be6b5603f914eba0d9d5bdd4e5c5572c1 +b0eaf919589988798cb01ba0610cd1b7fa3c08715675ece8ecd5f9ef6d5d7b2c4c8ae1ea7dfd202237171aa3e6f9de74 +abff99a98baae4dd0954052503ce81827781694a5ea8c1149f96a3adde75dc2d630e138598cd2ae7fdc7a654aa17df8f +83e369b8680d8b9d995222b033b4f4f3e3b20e782113c941325c7fa9c742feef8747e4a212d9aa23285a259cc4faef8d +b16d5855dd2716613697eba36e2fae0872aaea6999e91cf6552f93f9a0b85ed4f6ff922a91b50816bd6cf8e7a4513fc9 +848373db600e32e741aa1d37726bbb28956783f89ce2d781e95fb1ee1adf4359968a141678af268077eae4c25503204e +93a0dd0fdac18a31875564505b4e28f9e8bb2915faae666538597731ac56cd77f23f2456461e2f672983fb24ad91f6e0 +ab1ebbe49fa56524b564bc2e43784147073e6ea5d27a9540fbf2e04d0f87c645ed2fd28b3e4982cc4c0af1734ee47a6f +b3ee30b733839edab6f61f0738e3f4afaeccf700d8dc7415684f193b36d70d07acd5780cf539f12e0fbf8d4683be773a +88388f2cbdec47a6b3ae460b69eb0d2130ac14de950c22fd86de03e40d02292bb93cebe62432da39d509c1289f785fef +9370c41a54b68ff486b4cc6329c3a851716ebf1d088d77a6c56dec93a18b8a77b596cde74cc17d2adb2b2f411a2e4bbb +b9083b60dc16531f77b05a955b51a237a8f8c0173d72c352c5ca441b55abbc890b14937e457aaec4be5cbbf80cae0099 +aafff8f6c6ebaad952c65054dfc7c829453ec735331bf8135e06406b7a9f740c9a200dc48bb2175516b41f77dc160121 +b43d31fbbaf10526809e9e5bd8bb47a76e0fabd7852ee7744404559ab89f0f215ff518f3271a6aa972a459cab82ac558 +b581ede48c6ef34e678f91dc4b89507413e00e70712e3e8c32a80eed770ec8d8b98caee9702d068aeaca6f704be57bd8 +8cb0a137e68b001a5ccac61de27cac9fb78d4af7b2f5a00b8d95d33ac19cc50c69e760c5e0330a85c0ded1edce0fe6f9 +b947fca07c7aa6c2bf13048275402b00b77b28f1d0ba4b589fbcede13f93b5b931c588560ab8ceba23bb8e748031b55d +81753cced5ff819901740a9a584334e355b497cb699f0be5a52cd555a4c9f149535c7bb355b54407f7f0ec27de6c2e19 +b3d59273951ce97838c4853ec329782a255b5fc7c848e7992ded1be28a5ada7fa3254123afe32607b9991ec6e0659b08 +86b253de246f82be1cb0cef01e87c3d022ca1829d2cc7e6a160a5afbd3ca6b94d75739b122e3bb16f8bde28a8f3223ba +b728b659fa2d8487e061a37f7d14a4c2d70cc37497a8715695d8d332cb274deee2ce23b9b5f6a7408516c02c3d526a49 +81277b46d98848a45abfbe39842495659dcbb80dee985a4fc91d77d52b815487aa8bb455f411fcce4c3879c7a075a93f +b05b6f1fb4a6e654f0ee6b83e08b58b57059bb0b7c490405bc8d963c4a2d6be39c558917977e554e1e9e3169961cbf3e +88f75fa7d016fb6442551ec071cc1e2beeb3ccd213d16d744f573a82f5d70f41dd1b18af71d5f9e73d87f2f6b7dbe889 +81a46434f1bbd65a661a0ff45a0295b8fd8a42a7969c5953721bc98698b64bddee3f806876d1e9983063fdd0c11f99df +8b4f6d33c510a4c9c7d623d9ae0c9aa631fcb987704726b2a4d8519372123bce3c439202f25b5b47045ec14ce39a21a8 +8d5112b330fb63cf6ef3d2164b404c14ff9907d685015701399a260951912b19b8f270f869df317e9050a127763d7980 +aadab394e84dfb82db15ecd2427f39b62352c3e1647c3bcd14fb24ae830ad0116f0fed87ddb63963b424a4741961386e +81ca4e5600d00a3bda24cbdea7a532a4cbbd893c10e7ff10667c15ffa8138b91667abe5466b31a3dcdd60155c48538c1 +ad943af1b8a5fcfcf309ed8f2f916339f254cd555c71a407a47365a139306286a05a8314e1c70e20a65fccd75d36fa12 +b16597a0b437060a390467bbfab94c0bdd695ae898894f4689f939e30cc2119cc08ecb594546304adf876f4e275ebcd9 +a44a4e0a6693be356065891c27eefa040a1a79475be53d54d5fdcea7e0668ff9b35f850974000ed119f6865aa6faa721 +adef27d1b6e6921f4eaf69c79e2e01f5174f7033eaafdd33edcfa5119af23f3a834ffe1bdf19576581b797abd1865b34 +90c1e9202f3ffe28f8e1f58e9650dc4ff4dbc158005b6f2296ec36147e524b4f2f87f8aafc39db5b006fe0c491c92f45 +ac817cd54288b6f7fe6338415344fc9e7b669414051631ab2f27851c052c044be06bf7235d668e194bef695923256368 +ab14944ef653a14456d4ebc12e3196df3f1b4707c4e50b317b5ccc8ca3a0720f0330609f0e7e71793f6ca01583f38c70 +ad5353f2f380837e5ffdf079350b3d42935a0517861d03af98db5ed3ea8501abd68885c8c65f5a66e944b1874826a450 +8b5583863f84af8443ce8970b02e26cc5d959e47efbf8a66a54106ab165f1f76b36423aee74c7b5402fd1c4d7c1adfe6 +b3b46037eed9fc30e4f8f0da8bdbdcc40a38e22e876ce9fde981883017854aba82c18eb00887d92ad847d30082fe7271 +98a2b6fc90b7ad172e4368c1e54675b75c8bf2096d91c9f2b60b3397d3be3b705aed5389845dbd68f0f84438cd0f7687 +b155e800852a5f90a2eac69cc4483428da1dc2c31588a13c924e60a7616ce9baeb7d4b829c772b260277cadd8ed84719 +b8b92c520a1302b0cf7d993a52e1dacd7f27bda9868d59c55687d995ae676b7070af4c0792a9bc1c2635d44a4fee01bb +96dfe9bde526b8fc829eda825f55168b88e8f4e43d4d708cc3060df03437b46e12a8ac70d7788aa75760f6294d3e84d8 +a3fa66c54e2fa084ced3bd838614c6c33042f492a5745d167a723c60d5e7d6020ffd1747981a23f8b68df21ad8f0fa77 +b573ca10cc41fc04a642f6f62c355a4fda69b94b8e95dbb02fd1ccce4bce1191356e1fd66d372159944eb36a7071f005 +acd0a1c9abddfd0ea223eda1722aaada362d34234455bd1c6be115d41e535b16f12ca428da7820a757fa4c98884a385d +96f242eee99c4db383b8754fa7987c0c159652e1866faec905a8d3f010e0a1ad05bd77b9ea8dfd653738959180f58430 +9215a9b672a5d6e435e0e0a45156e0e20f75cbbdf1d14940fed3ddb63d433bef643796c7a4fff881829ebb2b2eba9460 +b8ad9bfceaf08dc5a874387219ddd1170bc3a5e25ed72d321d59ae713be5ddf9fdfbd3aa7ab163be28dfa0dd14614e19 +a19a1050590bc500b32c502f393e407abc3d8e683d6f6b978873aff3e3299b18b1f6b59e2b0fe237d819dbdfcfdc98ca +a6870fb11d4429686e52e1f44c8dcfc7ea24a020df9570c021578dbc1f9bdc8cf797cb3a72d7fc52805dba35d59f2cd0 +a7be733b64d5c06c127bd1c87250e42bfe30ca91ed8ce51e0b6e377f454e8f6fef7f99bff650695df2fd10c375da349b +a1b97145dab30330eea2cdc8739b2446a3704b64505fcea3dd8a9b4a72edf222e98d967d6fd7f76794acfd97aa091065 +b2127049907d2a3b654d1c940b740bfba3dbaf660f86ea79c2f909af7c9fe2a07a1caeb1be12370aeffaf8faa50f1582 +8a207701214bb28e99b0784e9228b1c34afa701966267fe7110f6f29f5bb41eaae6cdb98844d0400787978fabd224de8 +9925147a383b6f5f814520220ffdbf20b214225882c3ef49b1a1ca677709176ec82466fb9c4be2dfbe5640afb63b014a +8416ad93871623fb555b5390b80de99edaaf317350cc0c1ae9d54d59517074d40061f315cce8ba2026d9c1e6f6a1009f +a315f943deebbf0a2cdbcf3f8323e215a406e9cbfbcc3f6288714cb3a6befb1bf71b2a21ff7a2ec4731c65044c45b6b5 +8213e0c2539c24efd186ffa8b6dd401ad2233bc19166a0623b26dd1e93614bbf792823f5599ac116231e2efde9885709 +8e5cafd2f34a127a4a896f05e4d929eef06972a1826b3566446942198df26d62f7679b987db2b3765d9d8058b1cd85c2 +b5302b399c9cdf912fd59007ad4737255552663b1e56dbe64a7b2ddd88d2093c73ea319b45db2dd49d1e03f5bef1a0ae +a0c2bcfbed4b008e1a56e5d2f2419aa59d7dd0ebd990f1c18588de702ad0fa79f445d69965fa9381e700eda13b309378 +80a44eea1ffe24c26b16b8e2e70ee519258b9ad4b3e83cc4e5cca88ebc48d0160066f8b91d0581095b0de2428390c8b3 +84a90cb9c7d2f799f1c4ed060387a4b793ab41c5c3eaffd3b60face9b9c3bae93cd2017283bf3de1e3dac63d0d84dd42 +81d22febca276a05ba9bbc5591ee087b0491beb35b4d9f8fc0d041d642a574667ddc57660b20f5c568f7d61fdcb41bda +a3ac965ac27a28e102a439b74fbfc157e75fd57620e4c0750a466165f8aeecb2191dcf8e656f7525aa50d9c7c69b0b5c +913c17434ff0d9fc52e2ece4fec71b37d4474a18f3ea26925c1be2b250434d49759f58033ba0fce1c6862c6197930dc4 +ac430559c151a5e461f67b49c7786c97e1653fa8698e9759ddbdd99f5daf17fc5a012ae6330739440880728f24eba7c9 +b10d8e9f8aed9361b042d1398ec74364f7c7c1cc5c7f917060572761138bdbe89bf409389ee3879f93bc8032dd67b308 +937271005a4cc6a6ec134870c1b56471aa84ed4f4af1b3d5f334bc0c42762fae0c9a6a2828d3de6151a76dad7b72781c +a10e4dcf51889f69e6bd4c052f8d4036b9571ced98a3d7d779cbcb9fa5c3a82228566ea7cc1d012bf56dea0a40c5a64c +a0ed026528d9a8bb3201bc9dcd20598933e8c72fd315deea8da63d06e97392aa729d98a55a8a60fa4d5573513ba5c9fe +b723fcd04cddbd4c36feae827a03746ffef251c4f4c55a88beedaeeee194430a99f566f483668a0d88b13e7a4a37f1de +84a2cdceed44828c7c05a6a762edec0165e434e7029df617d6646aba48776e6c3b823f40689cee136536f8c93e08a629 +b786264e3a237ac3a1d56c9f4e87438dfed620c867100fd38b01287f5b755c7820937403bfb86644e082094d3e410a00 +92cc35b2065fca157c7bba54410f8bd85907a01c9f760aa0ddb7a82cb55811d24cb4dc6b725367a6a1c293b809a48ead +a12bbf22b117f00164a42515bc57cc9e6c43cc77fb737ee3d0c0cad94cb50cd3847d61cab469cf8ca76f7958bdcfc771 +85985b00de533bde2a757eddf53be79ea39091d16af3fc92327bcd1cd59bf2bf4411a334da29ad775e8ffaf3cea7d7b8 +af9eb24185b0d330d0ea1d0b0fa78af0dcf42ced81cb0128f16cafdea687a9c5582bb6d7c5744117b271cd0b3303f0b5 +8c8aaa1d85ed6327f85d579767c7a9158d209171b3efcb3e8a9d9e534c078e821b6aade255101d2c9ef6d67ba66f10be +a450518a03ffb40e1df89e0f88fd55b5b06f4872cdfb7ec55f40dc40d9424b3b289866336c195bdd54597d95569e0096 +81e61cc69f93c435bd77f155e80626a9c764dd92b6c76af15c41346527948d8a6ca87d6351a0fe7987e2ee3aa66a9625 +b615e0cebf4fdff4cb23a20c8389c370915ba26aa703b28efe4ab070b1603d1c5b6541684acf46b52a915f6aee447539 +a7f51885c7a71885cc84ef734ecd107e8bf5f7a25131415f671d143cc1de92859e65001125323c7985799993af6c410d +abfbf7a46f32066989c32f774edcc68163f085ca81e94fe8c9fb32f8d451bbb2c20ac45cd8d97f9e618ab40186933b1a +8cf35a522b5cac1934004aa9dd236bc77198d43272888afa860cfc79b4b28dabf7a3c74098f84510897566fdd609aa45 +86aa927df78f7a06a4985eb0a4f0b93529cef14f9fd2812d46abffbf25e618ead14d99c70e3c3bb2e17f3f7fabc9c264 +860f1b4f4a398e9a8bb4739587cf96979cfbbe1687b7e91e5bd1198db726391b09b1a261bf12e96698818f60b5bd3537 +8e7c4ee19ff115881051e8637dce1f5d6c65e865d0c757e8ce41b6d7bcd86c7070cce60649692bbf28c868c7e2e1e2f4 +acf7ba01b0220419f09169ac8d16e5cc13dce08e88c90b8fdfaa33aab417f011a20b79a178d8a9f7211589d2e0affd7d +b404bde8e715aefbb9f20a353b911b79173ef3e2cf0aba98b5ae6190b90597d65043b0b4e014ad9ea6c77da2d213ea12 +97e3615d1c77a402253bb55da2d1cdf82de316cefffe42b1022c94b4818d6dc4a313731db85321c537914bdf716a875c +940e950b96a4096a578c6874d747515936652b9b113a5f27f5a834a610867b05f9881e2679b0b289b8527baa0009b6dd +8de15a13ca236a3a285ce6e6826c502ae7365bbe468b6e8ac67b15b0bb49be0e996f1eec81ef69e4b7f54f8e4779a054 +a12244777eacb08ecd42b5676b3a51153022ab97e9353ace0f47c6054c22de9ba60d2a60f59a36841c2a791cb1b7c288 +94f7580203e39a2642ee2e7c969b9911f011d7f3a90c398e1302d26edb3df03df1d0c43baa1c6cf90dde95296d49e742 +82ead33144aaecab965faf63af384565992f38fc1066e71e33d53f43ac93892e27fe78c4eaca1cccbc53364e26ff31e9 +a0c129e9706d354249a7f8aa664ccd7ede89aa1445c5547410814b56d10dc086720953363ab1da8ff5f1ed5d8e575104 +93b3057bf3f74edc95237781ae012cc4b1d3fd0455565ceaac7110290aa518ac32478ba4eb9851555fa87270fcc84f1f +949c2fd0b94f31f7cbf00c679bd3f6ec1a2f4056654708d39edf1a450b4e19a6e251d0bb24eb765087e698f61d3fca2c +99fd2e50e211ccb66b895eb2fc42f260f3ad5767f04c2fe238b81dae98aa6e3977443a51f4fe7b43f499caabe45699a5 +84fe19626503218f327b5325bfd7c0c3d2614b47d34964aa0259d564e769c6c81502132cc1765b0b31fbe39852706927 +b43287ec29d9010bec4284de58fed48dd1e129bac79f09d45153c9949131782f77b11b0c9f8ee06a39e5e9bbaa8e2c6d +908902f3ed45482df2f94415fc8e5a308057a40c8905d7cbbd58ec4848e19276577b7f7e69e5e684a8b981738e10f7ef +85cc7d9c1eae372b4f88758cd6e21604b4bc9f0794e1e74b6d9de96347f81944d01331385fae7a38e5f6096c1dc23465 +af60288c702082fc258b3dbd6952c6b75c1641a623905f491b1e72f49b9d39b33d150a336450abd3911a4c128166acdf +a7d8ac7e589558c4014369ab6f4c1f2196205b03e4278152ec0dbbd7ba54e803c3369a71d364a773aac8dbbd117e4a13 +9833aed34e48c206e9328073597aee1123f5bec085339b4e6839a389a429bf3042798a31fac1464ce963204adface76b +84631a4f012bbb62133030224b57deb32dcf464cacc8ffde7775adbe68707263ab5527a1c75e597e03aa703ba658b889 +a686a61f6467858a2a4c13e70ad81b1901290d3e51bbc0c6e366f9e652f575e91b11c75f640ccef8b0c6c1b05a43c9a0 +b585f0ffd5144907703b41539bfad7f9f058f5985f63db911064ba6b07af8da2796b84b16db42b8d11135c3f846cd9e2 +b525539516c7bb25f1d7e165f269dc8c9eedbba74df44887e178ab8fd798e2a31f39812ca922d6b64d91564f14012a64 +91e480d7568fd2fae39c35b0a8d623e66a3160fee1dd4e9097255004938b11ac1cd3918dc6a1e5fbcb700c95a547e5e8 +936ef55c69b842b6177de71fa48dc5442bf5132116b214302f8f242ca36a273a6bbfbfaf373777104dadbe8e7da5e970 +8e950c0f6688abdff8a3b8bd77be6da6f2565c7b55711f5860ea62a3ab1d51aac31821c602bc11a45e33c69e7dde3ea4 +90eed4595104a0527f8db1e028ff622ff70db4eae99cf47f6c2a0246ec7b103570a6a9a877e32e9647cc74969006743d +b756344f6c4ea05b792e416d9bd9ce9dd4bd904e7622761f28a85628506bfc9d88a25e5f04db62fad30a92fb1d8d8556 +ad79ba76534c1a02ac3e9b7308d390792984cd75b7e1d0e5e4ff123642d99d4ea1825643091aa8117336333c40d5bd94 +832b08144887de0c0341d84f6945450af8d7a4eb32367d7703118186c1be525df9382ce61fed5f3b65a0bb3449185f7f +a322fb944e46d8e47994820890c94af423674716da810ea1da71e0a7733ad72c22114ca39a4b59c98ce4291a5684c154 +b982851a65140dbea79bd3b5487e236feccee051deddcc17c2853032efca289ddb6eaf64be3dd85a73012fdbe9d2d4f3 +8eed5e230e201830b44b9fadca4e156fe1a16bf840cf29da0f381ea0587b20c226de2465c67e6268973e776809af68e1 +81c8f1c04490f36e41a53ee1b5185cb8adbb37c258fd6c3be8c56835bf574c37183a94d55b6554fca35d6e6dd9af0133 +8c4928724107cc16d36f2976677eac0b852fc4c3c0bb2f9cd4d59cd24a113faf33b2faf405c3fcce25be51d41e42c2c4 +8e4ba842636fdfc4d71f0983538ea5037d420acd26abd12efca48c252eea85544b2fa9fccdfec4e7c2a6359baffa112d +b4315b84700e26dec26f3488d308430fdff4809c10d4c24309627911cbb769ffaad0d1ecccd622dd02194eaf5ba59f91 +ab888308f757faef32648c1db01650dbc9aea248b09d06e6efcc996d395f48ec96f2d54a02de441d753fe8737862d991 +805094cfd77e207d5c75f3cad99f41f763ec15443052cfd758c6a82ba422d831a1103a7f9b100da49c28198279c3d3dc +ad857f33243e4a2cd2a773700def21fc7f94939d1a6d2c2125ecd58fc206ccafb07a2c02a1cfce19857d3654aca2c70c +a4d12d40149953daa70b89a329e918e9d93efb4e8004a9357fe76682dab9662c8507e16db83e849340f05cdb4933a373 +a0dbac2ed4b5d03606524245e8a31080eb5bd3e9a0c51dad88c3b18e3e6bc5d64953a81c8e60425b80107ee6b62b1fb4 +86da05355900f327164a78901f6e3db857531b33b1e855df1a67a9ba222c6b05fdb6b0ffbacaeb1ba5b45ff8979b6b68 +932c9873aa3e226dd922b5a616c75153bd0390ce8f332a414b9c8cb6606c2501a37a2aa88097bc7d8e2c4261706eb38c +accd9cdf07ccdd42033ce3b105e00bfd39e2304b1e3d66f8b1128645634452c20f759ec45adcef2fdf04408f62c4cc04 +b75cfdfc1cb48918752eab17eb579820ee6e71e6667abdb64df834ffc8c1362fbbc23ca2c80dee248fe1fbb72d87dfc8 +88b998c73b00638fde7d3dd650a08c5ab996dac6ac34251337fbff3fb5ae4a25dd20c1a16c987ad7ded19eca23cea891 +8afef0956c942571a27f504553fb312cca9e50ce41b44e0466d0516c5abe4d8acf4594cdb03b1ccdbe3f2e6a9093b713 +9042cd83c5ff261e9ebda26398caa16cac2cb840d19062fa8ae50e044c27104972948318f4c866dc4d578798272d3e49 +ad536719a64570a2cd1d72b6590ea1d02c8c49f259a7867be26c8191445165954bcfad50ea12688ace3fdfb0e98143bd +97c86328d63d297b6bc9718dc1ad5a05b908a750d1c455c700d84315589128ce4eea958aef2bcf0fcf4adbd8e3ce58d1 +8e592cf0802e6a9541eeb654dc55055e11f3d757847285197132935ca35bbb1a9156829a39384dfa6f645ff89eb36738 +ac16c614998944f77590bf3913a010e13f2d3bbf6a172293baf5983506c1a2d89989fb72e598f5bba1ea10a691377c93 +ab8e6f5b46baa6632de3621497bcbdd584decb999fe7d8a3364843a1e0b76497600630b6a24dd30119d8bcbfca29f335 +abe1d3af5279e60122d9cea8cc6581c819d7a0e20e3715da0f6da7e02d13a7653db643bd946e2fa9ba338eca81fbe140 +8c33bd831ecfb18d1d0713e16beba768e9c42df62170c1f8a16764912be77f2ac5915623d1d25e8c462aa9c2f6669ca4 +903692becae4a6409f7bdb127d9b11de57a5739fe24218dcbaa0092648d5332dfeef29a908ee9e43e5e0a51a4c3639bc +92591e90347ae286acd365eba32cd9ad8f20f4c9cad2dc579b195147ff290adf0d776bcb3d4b04a25d68a941fc0c781b +b64bbccf860299aec16e1f95c768a1f337c740bde612e6ba260e393edb8b04540127194761c42597abb9bcb771c576c3 +9194f056ccfdfeb78a11c5347e2255d7a7ebd1251f9aebc0b58feb68d3e03a7dbbb74e3ef7309455853adfb4694bd01a +aa4f15f6d6a53ae65b7f6f91e8981d07a5919d2138679a561f7bb608dc4596e45ca06c9441d51fb678b2ad89ae7a17ae +90e3d18507beb30bde08c5001faf489a19ab545c177efb3f73fbf5605f9a0abcdc8bfbc44f832d6028e3e0a834bea98f +8f31dc0118c8c88a6e79e502d10e57652b7aba8409a5bf572ca63fed6b7cbad7f28bbc92ac2264f649792fc1d0715085 +a307d1067ea4c56437b6f8913aa8fcbf4a24580fc1e3336e7f6518f0f3adb9c4733090e459a3f737414ec0048179c30a +b7cc41fdf89595cd81a821669be712cd75f3a6c7a18f95da7d7a73de4f51bb0b44771c1f7cd3cd949e6f711313308716 +a9dc74e197fe60e8c0db06b18f8fe536381946edecdf31e9bd90e1ebfcad7f361544884e2fe83c23b5632912ec284faf +8b3e1e81326d611567e26ed29108f33ddb838c45bbd1355b3ae7e5d463612af64b63fff9fa8e6f2c14c8806021a5a080 +92f6537bca12778866335acc1eb4c3dfc2c8e7e5cf03399743dcea46aa66cac92ac2963b0892784263ad0ebe26ffdbf6 +b5cc0061f7a3e41513199c7dd91ac60d727366482a4c7328527f7bd4fc3509412f711bb722b4413b3736a219b843d15d +b3e9711d68d2c6f6e2cc27e385d5f603d9a1c9a96edeefa1ffdf390439954d19504d6aadc566b47e229ad4940ef020d2 +a09d0d3f0e5dc73a4a0827b72710b514bbfce4a7fcd5141d498a5aad6c38071077f50d3f91af897d9ab677b7041dedda +b177fe260f3b86e9ac21f1bfbe2682ae5dd8c9aecebb84f37054bdab6e39094e611ce582210ceeddde66adf759dadb6d +b0ac6595eba9f5dc4b2fd21856267cfbcfb5b12aa34ec69ca32b80071c5b652e85c25a224d80443d503bf25fbbfe07e9 +81f3c0e11b196bd4a2e8f07f8c037002566dc9037da81f3988add458a520c24dd1be3d43d851e28c0c6a85de4b57a542 +a44308c95615f7fedb2d2127012924468c015df9f48359cc2e36ab4223870b0bfc1e9040baabefdf5266f93afaad896b +8493ec4c32d5a13b81039f1b436eb83f259945dc950e3c6c2ccf5087ec56dd2f60890ed4edf01728b6a54950e19b35c6 +a1a439ec2a6a95bdac9aaa925ff337ba956c0d236ab5318354270e73ed6b73b4ae2d27b4c1686cf97b6526d04e65be81 +b4659b7b53c55a4b2bbe210b53520b392f893500e18990d843b72d7379d45fb44dd1dd2184348d6fd853d6b9ecc6b7c6 +afb2c68d75d00130b0e1b4f250001920213121791698ec04262db714cf7b1408d39f6cc10421f954845aad5b8250b77e +b22b843b40a97210f94043b552f348f66743055a3f274856a738e7d90a625b80e9bbb80cbbb450e1666eb56b8bd5c60f +800895ced82fe13d5fff65a93b0051c3df698bf1221b682accfdb63e3970f669ca37025750697f4e8ff2a3322ad57be4 +b21f598c50d7b9f4a584d548f85e42055ef8e24991906d973749090261584c7f4f5e984b528926f7e75375dd84d51af8 +849b1c68192d18274598dd6d0bf48fb5ee3b1ba25b331cff2d06f345bef3bed49760ca5690848cf33388f6a9a32cd646 +aeb6fd9478b10ef456f6bbb1e6dd19b14475e65497772d12cfc097948383d3fbd191bf95f046b8bf1989954118e483d0 +b1b5e0ea2835f7fc8b66e7731e392b43d16cbce04b52906b6751ab1b91978899db5fecbdabc23a19dabb253005468136 +91b6b1284770cf6f7ef35bc0b872b76c7763ffcfa68f9c8cfabcb2f264a66d47598bb9293f6a40f4c3dd33c265f45176 +b9ffed029846487c2cfb8a4bb61782bd8a878f3afdb73c377a0ebe63139fa070e3fcdc583eec3a53fdc5a421ff1fa877 +998007249d041b0b40ff546131cfc86d0b3598dcedf9a8778a223f7ed68ba4833b97324cbb1de91292b8ff51beab44b3 +8eb77ce9e0e406bf6f002870fb2fd1447646dd240df9bd485f8e0869298a1fc799d8a41b130c04370e9a9cc5c7540ca5 +853db8157462c46f2af7e8f94f2ed1c9b9a7ba2896b4973296898ff3d523d6e29e0b63a5d26cecd5e490b33c87a4cecf +b1436b6f3278768f0979ee852944258f2599977d255bea6fc912ba17c5dff5bdc850cf3e1fc52be9d6d188e868670f4f +a76acbc5832019b3b35667ab027feff49f01199a80016620f5c463dfcbfb51bf276ed17b7b683158ba450660cc7973eb +94540cdb051faf3ae8b8c52662868c2dab66bd02505c4f5f8eb4d6b2e2e5fd9a610890c5dcf8fd887eee796d2b5753a8 +aa35099666bceccf4eb3b65b13bba88e30a8be93693ab6761d8e5523343e8d6dd42d977e66499352fe4e9e9784a1dd0d +894471aad17be54319083c4b5e40adcfacf7c36c4aab0b671030b7ef321c53590a25eccd836efd20f32a93185fd315bb +8f52a9f705bb0dea958fcfbd52e2b6c08ad0f89a07a6b2942c1b4c37eead0d97a38a9e9aeb08d5d59b7fa2a9347f738b +9031c16b4f936c9cab55585dc5064739f696c3347ee2c0792320c9f749e760d120e396e8485ffc79d81c9f3337ad3d1c +82090a0d0d9b05459ec1c328ecd4707c333b784e3aaa0ef0072cee1eac83f9a653a75d83b9f63512a8c41200494826b4 +92c3a9553001f9ea4d67236b8ad1a33275378202cc1babc03f313895458f4b2549bfbbbdd37bfb8fbff0decb6b9f820a +88651868f4da37338a22bc553388df5dd1dd0cb78c4d7d07c637d8f6faef4bed72476fdcd4304d5bedf3514011135f08 +83fa0141bfebd88063f1d787719721b4c6b19ecf565b866de9d7d5d1a890e0e3d859b364bb65f8f8e688654456a40263 +90a7fab753e5d56dfc0e53a6b4e6ab14508220f3a62b3f3f30570c4c9ad225e74122635826c92e8e3227ec45e551432a +8fa375b0345bf6e5e062d108f9feaec91029345ecac67ccf1264eac77b8654cbfdda1f10579f481889c0e210254eadde +b83f06116da9daebdb013b26724523f077debaf6bc618b48a7a68858a98d275f7899c4ec73a0a827219b9248dd81c8c9 +8be1cada55e0c5ebb4fd460b2d209ae5326285a20c8bdd54ed9d1a87302f4063c8730bfda52d9d40e0d6fe43a0628465 +a68ad6f813743ec13a811f2ef3982c82d9d9ac1f7733936aa1e122f8dc7f4a305cc221579ab8fc170c3f123a1576f9ab +8878f1128214fdbbb8a0edd85223741e021508ab6d36c50d38680f2951ee713ea056ed03f62b9461897963d50ceefe0b +acc0d43d1b0260528b7425b260a5dea445b232b37240759fc65fe26f7c9d8e51569c5722bc33e94de6492f4ba1783504 +ad80b1dd717b076910ee5ceabcb762e75e4d094dc83b93b65c16de1f75bc712cef223c05d5579c1561829406c07a97d9 +a6fc9803f9c09d95fc326cc284f42ea5566255eb215dba8a9afb0be155ea11bcc55938b2d16f01cd2f2eda218c715efb +83ad733dbdfbaae8095a403dbf09130513f4ed4f08dcf8dd76ce83d1ea72999b7eea3a7b731da0d2bc80a83c6ee0e3e0 +8748912fbd08cb34a85416b0937d9c4327e9eed20d6e30aeb024a7253f14f1e0d774f3326e54738d71aae080e28da0fe +8997e78d8acf23051428af67183ae9b2c4aa42b503745ffe33df35a35103c589987e1473ab14dcd28ee78ebcb10d8e95 +a2f340502a7eb3c4a36412e6f028321372c4fa18a4743945607424e932af1271fa3e6598a162c872072529576eba6283 +868ccf19b5044ab93b45c9ed3ae34fcb504fe1453d6c4a1d12c325032cf01eb90356de82080ed897e97dba13cae33a02 +ac8867005fe4354d67aa37b866a7e581d2f94f7bd0b9f4efb5c2d1370ec13147a60692051b02fd00ae60b512bce9b1ff +8fd01886b046819c83c12bb779e432b25ba13713f9227be702074ec3abb2bba6be37220a0a26a4bd4171b99b14e32bc4 +a128981ed199f92b5959975c150a93a62fec50b61c80a3fa0634d90fc8058f76f5cbee77aae6889af12d296b30e613cd +81fe618552ff7a36c9235c6d4066cf2f930b5b38de4089e18166e4a06ca5723eadd1976d25e34b74b3ce942300b23e5b +ab1223ea049e6e0fbf9b611de7fd7c15e5e9637cbd73aa0e36aea08a7503ba6804f2aa807186fdc9aa7f4f9195f72e24 +b97285286981b2665f898abc13f3243b63005bef8db4cab3f658bf6167036b61af400f08db0fc3c640a9c623b760690d +ae3ddff7c1f0fbb6a13dbbc667a61e863c2c7c51c2051e33cd61620142e7e30a7e0c4c1f8fbb512aa3a8640267c6ac26 +99c2a89d5bef236060e51c4f952664094c20fbfca647e5d24a55c1fb8df2f3df58244fbbf3635db07b1c29ee3234fa6f +a5010764d4b9cd3b410638334d1f70c5f4843f45b4f4a9316aaea5fbb2c510a97449dd7a07b49f47334a69d37d9955d3 +86706d011dcdc9e9d165d01fea1df68dd74bedaf15a39f92893c030cafe96f4498c4c1fec2d2136354341b3f440a1462 +88fd57eb62bd7dc35722f3a0576c2138403a2f663a2603482e8974a895cf56ddbb02657dc6b89eb2cf5c1f9d1aff6426 +b0dfd4c68e3acb6bb8a776adaa421fc5e268ed4d5964bb90a727091e5113b55b3f9c6d33cedb3ee47ff7acc5df8b1749 +93b92bc942e1a636fc5c2dc1840de5faf158a113d640d5a475b48e2c56ccccaf9db0e37e90ce74c4b3f5c9ac3b2eb523 +b29a16fa1ea95cbfc1873c435ad40dc8495ba6341801b72bd95d908147dcffb1b4bb426dd635f3af4c88984f56594dd8 +b8f367105e1a2d554ac30200c66aeb579d3d30a8953d20fb6ebba2d876ec39c52ea5d654f1bb89b8ddf3d9d651f31cdf +b5fbc228c983d08adf8612eba5b3db3acff604439226f86aa133b02cce4ffde2f977c8dbb8b446b4375673f71634c89d +a399bea37d3056e0559f6644faa0af93063b4b545d504d7e228d3dbbc294af83d3c4cf37fe026b63899b4e7d50fd08f5 +928ef411a36414b24aea26fdbed4bdb1bb6bdc2d967e2553ce54c7c4e077e76869cea590257645c9129dd55ce025295c +9684a4adeed416a9ce82ad79b55c4a3adcfbd43950bc442ed8a340381caedb70f4baaaf821e3a152f483f965d8f56162 +92558a37f214d6f4cb6d72cd2f4ad24dff9d17611b9e4a41ee5c741a5d1ca9e4053b0584533ef4da206110b5dc3e2a35 +973bf0724d1785cc5e85d2a8ee8c354ad4cf557217ced0b7940f6f064024c20b2bfc5b144c820b5083da4bf70690de4d +adaf1389dfa528210ca9c2657c5ff10d51f7e3b18e93a59c37211be0506c3576cb2c04ec80cd0f82605e53c5a3556620 +85b58b223b09fda6f3ab674d75e780c49eb2167837243df049281e8f4fed653811138b398db9cdfe7405fdb8485602fe +849504d3db408d80745a07e850b0a804607b91a59922a5d3bc40da2748c029c029419cda38d2a4485cc0824c6b2504f0 +a3f4afcb353bc2582a02be758ebf0cd18752410ca2e64231176bfa23828423e0a450a65f241a9ed8eab36cae8d9c567b +ae362786cdf121206537af9590d330abbc6dc328b53cdd145dbed0e5df1364c816aae757c4c81f9d619e3698dd32bcdf +9024cfa5b0101eb02ab97866d5a3832944e5aa6888484cfba3d856576b920787b364fba5956bd7c68a305afedc958201 +8a116df09fed923acefb2aecf38a4fbc4b973ee964d67f03791d70bee6356af43ffca117d4e9463ffaf0e0d5d5e5a69f +9163016175c73f1bbc912ddfe03bd4e1db19c64951c8909ee6befe71a1249d838e0db49f03670bb4c5c9b2ab0fb4fef3 +8f6357318d8d16e7240a02b05ce5a4976b6079d49daa258789c6dbf4a47950ebe9de6411780fab06c7c1f35651433380 +8e63cbae8be7341892dbedee3111adf0307c4ee9e375181aa53478f5ba9cdce164d6ae890e5f480119a3a51c6e989165 +a9782f30674a4874d91bfba7eda63aeb5dbe66b040c768d6a925d8ee135f0655ea56276b105239cc0668fc91ddb68cd1 +8d9d94b61ab84ec08665cbe0244ea41756785df019e453ef078c19380bd44c39d2958e8465c72eacf41eed5696037805 +b1470e6f5d2e314474937cb5a3bc30c8bf5fc3f79014945f6ee895fe20028ffc272f9d3a7320aac93e36c96d8a5454e3 +a444911bbafc71179766594f3606b6eaff041826607fd3192f62dec05cd0f01b78598609a530f6930e8440db66f76713 +a9823d44e2638fca7bcc8796cc91c3eb17f46ad6db9f7f6510e093727614aa3a4f9b2c4011ef91dc1c2d224d08d8d05b +ab86020972c359ab98294212558b4b14862040139876c67fc494184b5c9bcea1dbe32fe0c8dd9e60be9daa304acd599a +b7e5cb685bbdcfdb1e48259a5d68d047846c8a35c5b3f90172fb183d1df40d22eaf0edaca2761a07c29c577000ccfed0 +8c88319dae4b28989817e79e6667fd891181e8d2ed91b9c6b614985bca14b12982462ec58b17be0463c24bbb79dd62a1 +8c1c6867e7107fb2178157c991b9c8b0f90c8d57a51220bf3650438ccabccf62da4db8a9916491e730ff3d0c106496e3 +a00a79bd58da6528b9af033087260f9f3d00519eafb4746b355204ee994e89481591b508eaa5402821083e250d38467b +8785abd7c37690f6aa870ee5c799eef72e398a7898b6767f698515be277b9c2fc1af12ea89b0620a848221343a3b5ec3 +8aadae68543db65cef71d0e230a09508d72061398ef2fabec0f856aacff2125b79c70e620744aaf331faf3dfc8afb9bc +8ff0cd437fcad9630b8a2333176a55e178db4142ec841581590594d74d5b53baeac5fb903fdf7bcf83e245b95b58285e +af274e8fad6b190be4e5dc92d2705ba6ac0d7e1ea29e958a5cdd4cb764de46a56d9eef62c999a16e7c50a50b2d9fe3a8 +865e6ec7d1aa848786d6a7a4e87a24d442311f0810b01ef5a74928ab59fdfd651e48880b49680047e5b0df6b3c7c2ecc +800706baaeb35bf3bc33bdea9a8b5cb00d82df407b3b7e1b781a9359cf44fb410ed311591080181b768aae223d9246aa +a9496389d0780b309c6998374ae159f58a8d0fe9a1c24c36cebcb45b27d818e653b51a8ee1f01e30a9b2c46a548126ef +b5fccf4fc3186661939fbee2e89c2aa0e3a6ad4907bcc98c7750520540c4c183b1bbfcdf47f2f1c5e75c3a30cdf30c75 +a90028e39081b736e628c2230cc1338f9210ed01309a40fdf08d39c10cced2cdf71271013bea6dba3a0444fe47963106 +a0815cbb325a8fecf2e1bcc5046644be32d43a8001bd5d8cf0022e4572cd0d481b3e717002f7ab21e16da5f5d16886d6 +b2024787fcda52abc4138150f15e81f4a5be442929b1651ddccbfd558029912be4d61c3c9b467605fff640edf7392494 +ab5aa60032304a584cc9245a33f528eae7157808dedd1ad83ebae00aadc25dbe1cd5917eb8b6b2c800df15e67bdd4c4d +866643847ef512c5119f2f6e4e3b8d3f4abb885f530bb16fcef0edb698a5b0768905e51536283925b6795a5e68b60ddc +806aa99c9a46ee11cc3ebf0db2344b7515db8c45b09a46a85f8b2082940a6f7263f3c9b12214116c88310e706f8e973a +a6eada8b9ff3cd010f3174f3d894eb8bb19efdbff4c6d88976514a5b9968b0f1827d8ac4fe510fb0ba92b64583734a1e +98480db817c3abbc8b7baedf9bf5674ec4afcfd0cd0fd670363510a426dad1bcf1b1cb3bf0f1860e54530deb99460291 +81ab480187af4a3dfbc87be29eca39b342a7e8e1d1df3fc61985e0e43d8d116b8eac2f1021bde4ae4e5e3606c1b67a21 +8a37df12dc997bf9b800f8fd581a614a1d5e32b843f067d63d1ca7fde2e229d24413d3a8308ec1e8389bf88154adb517 +b045a55ca0bb505bd5e8fcc4cfdd5e9af1a7d5fe7a797c7ede3f0b09712b37f493d3fcf6ef0e759d7e0157db1f583c95 +ad502e53a50691238323642e1d8b519b3c2c2f0fd6a0dd29de231f453be730cf1adc672887d97df42af0a300f7631087 +80597648f10c6d8fcd7421caf4e7f126179633078a1724817d2adc41b783723f302eabc947a7ba7767166dacf4ce8fa1 +aefb56427966c81081999dffbe89f8a0c402041929cd4e83d6612866cfbb97744f4ab802578349fbecc641fa9955e81b +a340e493fb3fb604eab864d4b18a6e40ba657003f1f88787e88e48b995da3d0ab4926ce438bdc8d100a41912a47dace0 +a6d777bfc0895eac541a092e14499ff8bf7156689d916a678b50a1460583b38e68158984bea113a0a8e970d8a6799a85 +90ce469410f0e8cfff40472817eb445770833cdcf2895a69bc32bcf959854d41712599ceb2b0422008d7300b05e62e02 +815c51be91d8516d5adc2fd61b6600957ed07cf5fdc809aa652b059bea8ed179638a19077a3f040334032f0e7900ac8b +b3ec6c0c3c007c49c6b7f7fc2ffd3d3a41cdff5ad3ac40831f53bfc0c799ffeed5f440a27acc5f64432e847cc17dd82e +823637abeab5fb19e4810b045254558d98828126e9a2d5895a34b9e4b4f49ab0a5b3ee2422f1f378995ea05df5516057 +ac05412bcf46c254f6548d8107a63928bba19ab6889de5d331eb68cf4d8ce206055b83af4cb7c6c23b50188391e93f84 +88514163c587068178302bc56e9a8b3ad2fa62afd405db92f2478bb730101358c99c0fe40020eeed818c4e251007de9c +b1e657d0f7772795b3f5a84317b889e8ded7a08ea5beb2ab437bebf56bcb508ae7215742819ed1e4ae3969995fe3b35d +a727d4f03027fe858656ca5c51240a65924915bd8bd7ffa3cfc8314a03594738234df717e78bb55a7add61a0a4501836 +b601682830fc4d48ece2bdc9f1a1d5b9a2879c40c46135f00c2c3ae1187c821412f0f0cfbc83d4e144ddd7b702ca8e78 +b5cfea436aa1f29c4446979272a8637cb277f282825674ddb3acac2c280662fb119e6b2bdd52c4b8dbf2c39b1d2070d6 +85c211645ff746669f60aa314093703b9045966604c6aa75aae28422621b256c0c2be835b87e87a00d3f144e8ab7b5f0 +867628d25bab4cb85d448fd50fdd117be1decdd57292e194a8baa0655978fae551912851660a1d5b9de7a2afbb88ef5c +a4e79c55d1b13c959ff93ddcf1747722c6312a7941a3b49f79006b3165334bab369e5469f1bddebadb12bfaff53806d5 +ac61f0973e84546487c5da7991209526c380e3731925b93228d93a93bce1283a3e0807152354f5fe7f3ea44fc447f8fe +a1aa676735a73a671a4e10de2078fd2725660052aa344ca2eb4d56ee0fd04552fe9873ee14a85b09c55708443182183a +8e2f13269f0a264ef2b772d24425bef5b9aa7ea5bbfbefbcc5fd2a5efd4927641c3d2374d0548439a9f6302d7e4ba149 +b0aacdaf27548d4f9de6e1ec3ad80e196761e3fb07c440909524a83880d78c93465aea13040e99de0e60340e5a5503cd +a41b25ae64f66de4726013538411d0ac10fdb974420352f2adb6ce2dcad7b762fd7982c8062a9bac85cdfcc4b577fd18 +b32d87d5d551f93a16ec983fd4ef9c0efcdae4f5e242ce558e77bcde8e472a0df666875af0aeec1a7c10daebebab76ea +b8515795775856e25899e487bf4e5c2b49e04b7fbe40cb3b5c25378bcccde11971da280e8b7ba44d72b8436e2066e20f +91769a608c9a32f39ca9d14d5451e10071de2fd6b0baec9a541c8fad22da75ed4946e7f8b081f79cc2a67bd2452066a9 +87b1e6dbca2b9dbc8ce67fd2f54ffe96dfcce9609210a674a4cb47dd71a8d95a5a24191d87ba4effa4a84d7db51f9ba0 +a95accf3dbcbf3798bab280cabe46e3e3688c5db29944dbe8f9bd8559d70352b0cfac023852adc67c73ce203cbb00a81 +a835f8ce7a8aa772c3d7cfe35971c33fc36aa3333b8fae5225787533a1e4839a36c84c0949410bb6aace6d4085588b1e +8ef7faa2cf93889e7a291713ab39b3a20875576a34a8072a133fed01046f8093ace6b858463e1e8a7f923d57e4e1bc38 +969ecd85643a16d937f148e15fb56c9550aefd68a638425de5058333e8c0f94b1df338eaab1bd683190bfde68460622b +8982f4c76b782b9b47a9c5aeb135278e5c991b1558e47b79328c4fae4b30b2b20c01204ff1afb62b7797879d9dee48e2 +b5098b7ba813178ced68f873c8c223e23a3283d9f1a061c95b68f37310bca4b2934a3a725fff1de1341c79bb3ba6007e +97b160787009f7b9649ed63db9387d48a669e17b2aba8656792eb4f5685bb8e6386f275476b4dfbb1b4cb0c2a69bc752 +88b69369c71daad6b84fa51a0f64a6962d8c77e555b13c035ad6fa1038e7190af455b1bd61ae328b65d6a14cf3d5f0d5 +af88b87801361f0de26bd2533554ee6f4d8067e3122b54161c313c52cc9eafea00661c5c43e2d533485d1f26da4e5510 +98ab18e3bbcb23ac1e34439849e56009bb765ab2f2558ebfd0a57cbe742169f114bceb930533fb911b22cb5a8fe172bc +9027507f1725d81e5ac0f0854c89ab627df3020fe928cb8745f887bf3310086c58fca1119fd5cd18a7d3561c042d58de +a676583f8a26e6f8991a0791916ce785b596ce372812f5eb7b4243ba9367ea95c797170fdac5b0c5e6b7f6519cc2b026 +b91b0ab32638aef3365035a41c6068e36d2303bfee8640565e16c9a56c21703270fd45946ce663238a72c053eb3f2230 +aaf4cd1ac0a30906dcd2b66b37848c6cc443da511e0b0367fd792887fdaf1500551590440e61d837dbee9d24c9801108 +a06f20a02d3cd76029baad5a12592f181738378a83a95e90470fa7cc82a5ae9d2ed824a20eeb1e96e6edc0619f298688 +a465d379c3481b294efc3f2f940b651c45579607cf72d143b99705eae42103a0279eb3595966453130e18935265e35d6 +892a8af7816a806295278027a956663ea1297118ede0f2a7e670483b81fb14dccacc7a652e12f160e531d806ca5f2861 +b480917c0e8b6e00de11b4416a20af6c48a343450a32ee43224559d30e1fecdece52cc699493e1754c0571b84f6c02c2 +b3182da84c81e5a52e22cebed985b0efc3056350ec59e8646e7fd984cdb32e6ac14e76609d0ffaca204a7a3c20e9f95d +a04ea6392f3b5a176fa797ddec3214946962b84a8f729ffbd01ca65767ff6237da8147fc9dc7dd88662ad0faefdb538c +95c0d10a9ba2b0eb1fd7aa60c743b6cf333bb7f3d7adedce055d6cd35b755d326bf9102afabb1634f209d8dacfd47f1a +a1a583d28b07601541fa666767f4f45c954431f8f3cc3f96380364c5044ff9f64114160e5002fb2bbc20812b8cbd36cb +a1a0708af5034545e8fcc771f41e14dff421eed08b4606f6d051f2d7799efd00d3a59a1b9a811fa4eddf5682e63102ea +ab27c7f54096483dd85c866cfb347166abe179dc5ffaca0c29cf3bfe5166864c7fa5f954c919b3ba00bdbab38e03407d +ac8c82271c8ca71125b380ed6c61b326c1cfe5664ccd7f52820e11f2bea334b6f60b1cf1d31599ed94d8218aa6fbf546 +a015ea84237d6aa2adb677ce1ff8a137ef48b460afaca20ae826a53d7e731320ebdd9ee836de7d812178bec010dd6799 +925418cda78a56c5b15d0f2dc66f720bda2885f15ffafb02ce9c9eed7167e68c04ad6ae5aa09c8c1c2f387aa39ad6d1b +87c00bba80a965b3742deacafb269ca94ead4eb57fdb3ed28e776b1d0989e1b1dba289019cfb1a0f849e58668a4f1552 +948d492db131ca194f4e6f9ae1ea6ebc46ebbed5d11f1f305d3d90d6b4995b1218b9606d114f48282a15661a8a8051ca +8179617d64306417d6865add8b7be8452f1759721f97d737ef8a3c90da6551034049af781b6686b2ea99f87d376bce64 +918e3da425b7c41e195ed7b726fa26b15a64299fe12a3c22f51a2a257e847611ac6cfcc99294317523fc491e1cbe60c4 +a339682a37844d15ca37f753599d0a71eedfbbf7b241f231dd93e5d349c6f7130e0d0b97e6abd2d894f8b701da37cb11 +8fc284f37bee79067f473bc8b6de4258930a21c28ac54aaf00b36f5ac28230474250f3aa6a703b6057f7fb79a203c2c1 +a2c474e3a52a48cd1928e755f610fefa52d557eb67974d02287dbb935c4b9aab7227a325424fed65f8f6d556d8a46812 +99b88390fa856aa1b8e615a53f19c83e083f9b50705d8a15922e7c3e8216f808a4cc80744ca12506b1661d31d8d962e4 +a1cbd03e4d4f58fc4d48fa165d824b77838c224765f35d976d3107d44a6cf41e13f661f0e86f87589292721f4de703fb +b3a5dde8a40e55d8d5532beaa5f734ee8e91eafad3696df92399ae10793a8a10319b6dc53495edcc9b5cfd50a389a086 +996e25e1df5c2203647b9a1744bd1b1811857f742aee0801508457a3575666fcc8fc0c047c2b4341d4b507008cd674c2 +93e0a66039e74e324ee6c38809b3608507c492ef752202fff0b2c0e1261ca28f1790b3af4fdb236f0ed7e963e05c1ec0 +b6084e5818d2d860ac1606d3858329fbad4708f79d51a6f072dc370a21fdb1e1b207b74bc265a8547658bfb6a9569bb3 +a5336126a99c0ecfc890584b2a167922a26cae652dfc96a96ab2faf0bf9842f166b39ceaf396cd3d300d0ebb2e6e0ebf +b8b6f13ce9201decaba76d4eca9b9fa2e7445f9bc7dc9f82c262f49b15a40d45d5335819b71ff2ee40465da47d015c47 +b45df257b40c68b7916b768092e91c72b37d3ed2a44b09bf23102a4f33348849026cb3f9fbb484adfea149e2d2a180ff +a50d38ee017e28021229c4bb7d83dd9cdad27ab3aa38980b2423b96aa3f7dc618e3b23895b0e1379ca20299ff1919bbf +97542cf600d34e4fdc07d074e8054e950708284ed99c96c7f15496937242365c66e323b0e09c49c9c38113096640a1b6 +822d198629697dcd663be9c95ff1b39419eae2463fa7e6d996b2c009d746bedc8333be241850153d16c5276749c10b20 +9217bc14974766ebdfbf6b434dd84b32b04658c8d8d3c31b5ff04199795d1cfad583782fd0c7438df865b81b2f116f9c +93477879fa28a89471a2c65ef6e253f30911da44260833dd51030b7a2130a923770ebd60b9120f551ab373f7d9ed80aa +87d89ff7373f795a3a798f03e58a0f0f0e7deab8db2802863fab84a7be64ae4dcf82ece18c4ddbefccd356262c2e8176 +a3ba26bd31d3cc53ceeced422eb9a63c0383cde9476b5f1902b7fe2b19e0bbf420a2172ac5c8c24f1f5c466eecc615d4 +a0fe061c76c90d84bd4353e52e1ef4b0561919769dbabe1679b08ef6c98dcfb6258f122bb440993d976c0ab38854386b +b3070aa470185cb574b3af6c94b4069068b89bb9f7ea7db0a668df0b5e6aabdfe784581f13f0cf35cd4c67726f139a8c +9365e4cdf25e116cbc4a55de89d609bba0eaf0df2a078e624765509f8f5a862e5da41b81883df086a0e5005ce1576223 +a9036081945e3072fa3b5f022df698a8f78e62ab1e9559c88f9c54e00bc091a547467d5e2c7cbf6bc7396acb96dd2c46 +8309890959fcc2a4b3d7232f9062ee51ece20c7e631a00ec151d6b4d5dfccf14c805ce5f9aa569d74fb13ae25f9a6bbe +b1dc43f07303634157f78e213c2fae99435661cc56a24be536ccbd345ef666798b3ac53c438209b47eb62b91d6fea90a +84eb451e0a74ef14a2c2266ff01bd33d9a91163c71f89d0a9c0b8edfcfe918fc549565509cd96eed5720a438ff55f7f2 +9863b85a10db32c4317b19cc9245492b9389b318cf128d9bbc7ec80a694fcbbd3c0d3189a8cad00cc9290e67e5b361ee +8a150ee474ebe48bdfcac1b29e46ac90dcded8abbe4807a165214e66f780f424be367df5ef1e94b09acf4a00cd2e614d +a6677a373130b83e30849af12475e192f817ba4f3226529a9cca8baaefb8811db376e4a044b42bf1481268c249b1a66e +b969cbf444c1297aa50d1dfa0894de4565161cb1fc59ba03af9655c5bf94775006fe8659d3445b546538a22a43be6b93 +8383167e5275e0707e391645dc9dea9e8a19640ecfa23387f7f6fcaddff5cde0b4090dfad7af3c36f8d5c7705568e8d8 +a353ddbc6b6837773e49bb1e33a3e00ca2fb5f7e1dba3a004b0de75f94a4e90860d082a455968851ef050ae5904452e0 +adeccf320d7d2831b495479b4db4aa0e25c5f3574f65a978c112e9981b2663f59de4c2fa88974fdcabb2eedb7adab452 +afa0eacc9fdbe27fb5e640ecad7ecc785df0daf00fc1325af716af61786719dd7f2d9e085a71d8dc059e54fd68a41f24 +a5b803a5bbe0ca77c8b95e1e7bacfd22feae9f053270a191b4fd9bca850ef21a2d4bd9bcd50ecfb971bb458ff2354840 +b023c9c95613d9692a301ef33176b655ba11769a364b787f02b42ceb72338642655ea7a3a55a3eec6e1e3b652c3a179e +8fa616aa7196fc2402f23a19e54620d4cf4cf48e1adfb7ea1f3711c69705481ddcc4c97236d47a92e974984d124589e5 +a49e11e30cb81cb7617935e8a30110b8d241b67df2d603e5acc66af53702cf1e9c3ef4a9b777be49a9f0f576c65dcc30 +8df70b0f19381752fe327c81cce15192389e695586050f26344f56e451df2be0b1cdf7ec0cba7ce5b911dcff2b9325ae +8fbbc21a59d5f5a14ff455ca78a9a393cab91deb61cf1c25117db2714d752e0054ed3e7e13dd36ad423815344140f443 +a9a03285488668ab97836a713c6e608986c571d6a6c21e1adbd99ae4009b3dde43721a705d751f1bd4ebf1ea7511dfed +b2f32b8e19e296e8402251df67bae6066aeefd89047586d887ffa2eacdf38e83d4f9dc32e553799024c7a41818945755 +942cf596b2278ad478be5c0ab6a2ad0ceafe110263cc93d15b9a3f420932104e462cf37586c374f10b1040cb83b862e0 +aaa077a55f501c875ceae0a27ef2b180be9de660ef3d6b2132eb17256771ce609d9bc8aaf687f2b56ae46af34ad12b30 +90ac74885be1448101cf3b957d4486e379673328a006ea42715c39916e9334ea77117ff4a60d858e2ccce9694547a14f +9256cdfc2339e89db56fd04bd9b0611be0eefc5ee30711bcece4aadf2efcc5a6dcc0cfd5f733e0e307e3a58055dff612 +a4c7384e208a0863f4c056248f595473dcde70f019ddaede45b8caf0752575c241bac6e436439f380ac88eee23a858e9 +a3aa67391781e0736dddc389f86b430b2fc293b7bd56bfd5a8ec01d1dd52ed940593c3ad4ce25905061936da062b0af6 +80299275ec322fbb66cc7dce4482ddd846534e92121186b6906c9a5d5834346b7de75909b22b98d73120caec964e7012 +aa3a6cd88e5f98a12738b6688f54478815e26778357bcc2bc9f2648db408d6076ef73cced92a0a6b8b486453c9379f18 +b07c444681dc87b08a7d7c86708b82e82f8f2dbd4001986027b82cfbed17b9043e1104ade612e8e7993a00a4f8128c93 +af40e01b68d908ac2a55dca9b07bb46378c969839c6c822d298a01bc91540ea7a0c07720a098be9a3cfe9c27918e80e8 +abd8947c3bbc3883c80d8c873f8e2dc9b878cbbb4fc4a753a68f5027de6d8c26aa8fbbafeb85519ac94e2db660f31f26 +a234f9d1a8f0cb5d017ccca30b591c95ec416c1cb906bd3e71b13627f27960f61f41ed603ffbcf043fd79974ec3169a8 +835aaf52a6af2bc7da4cf1586c1a27c72ad9de03c88922ad172dce7550d70f6f3efcc3820d38cd56ae3f7fc2f901f7a0 +ae75db982a45ad01f4aa7bc50d642ff188219652bb8d521d13a9877049425d57852f3c9e4d340ffec12a4d0c639e7062 +b88884aa9187c33dc784a96832c86a44d24e9ffe6315544d47fc25428f11337b9ffd56eb0a03ad709d1bf86175059096 +8492ca5afcc6c0187b06453f01ed45fd57eb56facbeea30c93686b9e1dab8eaabd89e0ccb24b5f35d3d19cd7a58b5338 +9350623b6e1592b7ea31b1349724114512c3cce1e5459cd5bddd3d0a9b2accc64ab2bf67a71382d81190c3ab7466ba08 +98e8bf9bed6ae33b7c7e0e49fc43de135bffdba12b5dcb9ff38cb2d2a5368bb570fe7ee8e7fbe68220084d1d3505d5be +ab56144393f55f4c6f80c67e0ab68f445568d68b5aa0118c0c666664a43ba6307ee6508ba0bb5eb17664817bc9749af0 +827d5717a41b8592cfd1b796a30d6b2c3ca2cdc92455f9f4294b051c4c97b7ad6373f692ddafda67884102e6c2a16113 +8445ce2bb81598067edaa2a9e356eda42fb6dc5dd936ccf3d1ff847139e6020310d43d0fec1fe70296e8f9e41a40eb20 +9405178d965ee51e8d76d29101933837a85710961bb61f743d563ef17263f3c2e161d57e133afac209cdb5c46b105e31 +b209f9ed324c0daa68f79800c0a1338bbaf6d37b539871cb7570f2c235caca238a2c4407961fcb7471a103545495ef2c +92ae6437af6bbd97e729b82f5b0d8fb081ca822f340e20fae1875bdc65694cd9b8c037a5a1d49aa9cae3d33f5bad414e +9445bdb666eae03449a38e00851629e29a7415c8274e93343dc0020f439a5df0009cd3c4f5b9ce5c0f79aefa53ceac99 +93fdab5f9f792eada28f75e9ac6042a2c7f3142ba416bfdb1f90aa8461dbe4af524eee6db4f421cb70c7bc204684d043 +a7f4dc949af4c3163953320898104a2b17161f7be5a5615da684f881633174fb0b712d0b7584b76302e811f3fac3c12f +a8ac84da817b3066ba9789bf2a566ccf84ab0a374210b8a215a9dcf493656a3fa0ecf07c4178920245fee0e46de7c3ec +8e6a0ae1273acda3aa50d07d293d580414110a63bc3fb6330bb2ee6f824aff0d8f42b7375a1a5ba85c05bfbe9da88cb5 +a5dea98852bd6f51a84fa06e331ea73a08d9d220cda437f694ad9ad02cf10657882242e20bdf21acbbaa545047da4ce5 +b13f410bf4cfce0827a5dfd1d6b5d8eabc60203b26f4c88238b8000f5b3aaf03242cdeadc2973b33109751da367069e1 +a334315a9d61b692ad919b616df0aa75a9f73e4ea6fc27d216f48964e7daebd84b796418580cf97d4f08d4a4b51037cd +8901ba9e963fcd2f7e08179b6d19c7a3b8193b78ca0e5cf0175916de873ca0d000cd7ac678c0473be371e0ac132f35a2 +b11a445433745f6cb14c9a65314bbf78b852f7b00786501b05d66092b871111cd7bee25f702d9e550d7dd91601620abb +8c2f7b8e7b906c71f2f154cc9f053e8394509c37c07b9d4f21b4495e80484fc5fc8ab4bdc525bd6cfa9518680ba0d1a2 +b9733cebe92b43b899d3d1bfbf4b71d12f40d1853b2c98e36e635fdd8a0603ab03119890a67127e6bc79afae35b0bef2 +a560f6692e88510d9ba940371e1ada344caf0c36440f492a3067ba38e9b7011caac37ba096a8a4accb1c8656d3c019b3 +ac18624339c1487b2626eef00d66b302bdb1526b6340d6847befe2fdfb2b410be5555f82939f8707f756db0e021ed398 +afd9a3b8866a7fe4f7bc13470c0169b9705fcd3073685f5a6dcff3bdbbc2be50ac6d9908f9a10c5104b0bffc2bc14dad +97f15c92fe1f10949ed9def5dd238bc1429706e5037a0e0afb71c2d0e5845e2fed95a171c393e372077a7c7059f8c0e0 +9453a1d4d09c309b70968ea527007d34df9c4cfd3048e5391aac5f9b64ca0c05dde5b8c949c481cfc83ef2e57b687595 +b80e4b7c379ad435c91b20b3706253b763cbc980db78f782f955d2516af44c07bbfa5888cbf3a8439dc3907320feb25a +8939f458d28fefe45320b95d75b006e98330254056d063e4a2f20f04bcb25936024efe8d436d491ed34b482f9b9ae49c +a9ead2e833f71f7e574c766440c4b3c9c3363698c7ade14499a56003a272832ee6d99440887fa43ccdf80265b9d56b97 +b6547a36934f05ce7b779e68049d61351cf229ae72dc211cc96a2a471b2724782f9355fdb415ea6f0ea1eb84fe00e785 +828bfb3099b7b650b29b0f21279f829391f64520a6ab916d1056f647088f1e50fac9253ef7464eceab5380035c5a59c4 +8d714b9ea650be4342ff06c0256189e85c5c125adf6c7aeca3dba9b21d5e01a28b688fc2116ce285a0714a8f1425c0b8 +8a82eda041b2e72a3d73d70d85a568e035fbd6dc32559b6c6cfdf6f4edcb59a6ba85b6294a721aa0a71b07714e0b99ae +af5665ebc83d027173b14ffb0e05af0a192b719177889fadc9ac8c082fda721e9a75d9ce3f5602dbfd516600ee3b6405 +a68fdddf03d77bebdb676e40d93e59bd854408793df2935d0a5600601f7691b879981a398d02658c2da39dbbf61ef96c +8c001ebc84fcf0470b837a08a7b6125126b73a2762db47bbdc38c0e7992b1c66bac7a64faa1bf1020d1c63b40adc3082 +8553889b49f9491109792db0a69347880a9cf2911b4f16f59f7f424e5e6b553687d51282e8f95be6a543635247e2e2c2 +a2c269d6370b541daf1f23cc6b5d2b03a5fa0c7538d53ae500ef875952fe215e74a5010329ff41461f4c58b32ad97b3d +a5dae097285392b4eba83a9fd24baa03d42d0a157a37fae4b6efc3f45be86024b1182e4a6b6eadcf5efe37704c0a1ae5 +89871a77d2032387d19369933cd50a26bda643e40cfd0ce73febe717a51b39fae981406fd41e50f4a837c02a99524ef9 +8a76d495e90093ec2ac22f53759dc1cf36fbb8370fb586acbd3895c56a90bbf3796bcc4fc422ca4058adf337ead1402e +ad4eb7576c4954d20623c1336c63662c2a6fb46ec6ef99b7f8e946aa47488dcb136eab60b35600f98c78c16c10c99013 +894c2b120cec539feb1d281baaadde1e44beafedeeec29b804473fe024e25c1db652f151c956e88d9081fb39d27e0b19 +9196bd5c100878792444c573d02b380a69e1b4b30cb59a48114852085058a5fd952df4afee3ecceb5c4ede21e1ed4a1a +a996fffc910764ea87a1eedc3a3d600e6e0ff70e6a999cb435c9b713a89600fc130d1850174efe9fc18244bb7c6c5936 +8591bb8826befa8bee9663230d9a864a5068589f059e37b450e8c85e15ce9a1992f0ce1ead1d9829b452997727edcf9d +9465e20bb22c41bf1fa728be8e069e25cda3f7c243381ca9973cbedad0c7b07d3dd3e85719d77cf80b1058ce60e16d68 +926b5ce39b6e60b94878ffeae9ff20178656c375fb9cfe160b82318ca500eb3e2e3144608b6c3f8d6c856b8fe1e2fbcf +a1ef29cbc83c45eb28ad468d0ce5d0fdd6b9d8191ba5ffa1a781c2b232ed23db6b7b04de06ef31763a6bfe377fa2f408 +9328e63a3c8acf457c9f1f28b32d90d0eeadb0f650b5d43486a61d7374757a7ada5fc1def2a1e600fa255d8b3f48036f +a9c64880fcb7654f4dd08f4c90baac95712dd6dd407e17ea60606e9a97dc8e54dd25cb72a9bf3fc61f8d0ad569fe369d +a908eb7b940c1963f73046d6b35d40e09013bfbfbeb2ccd64df441867e202b0f3b625fa32dd04987c3d7851360abdffc +b3947b5ed6d59e59e4472cdb1c3261de1b5278fb7cb9b5fca553f328b3b3e094596861ea526eca02395f7b7358155b7b +99da7f190d37bc58945f981cf484d40fcf0855cf8178e2ce8d057c7f0a9d9f77425fdbce9ef8366f44f671b20fd27d0b +913976d77d80e3657977df39571577fdf0be68ba846883705b454f8493578baa741cfaede53783e2c97cc08964395d83 +8d754a61e5164a80b5090c13f3e936056812d4ae8dc5cc649e6c7f37464777249bc4ae760a9806939131f39d92cca5bf +82ffd098480828a90cb221a8c28584e15904bad477c13b2e2d6ef0b96a861ce4a309a328fe44342365349456ad7c654f +89ae3ce4b0357044579ca17be85d8361bb1ce3941f87e82077dd67e43ec0f95edd4bd3426225c90994a81a99e79490b7 +a170892074016d57c9d8e5a529379d7e08d2c1158b9ac4487ac9b95266c4fd51cb18ae768a2f74840137eec05000dd5a +aafd8acd1071103c7af8828a7a08076324d41ea530df90f7d98fafb19735fc27ead91b50c2ca45851545b41d589d0f77 +8623c849e61d8f1696dc9752116a26c8503fd36e2cbbc9650feffdd3a083d8cdbb3b2a4e9743a84b9b2ad91ac33083f2 +ac7166ddd253bb22cdbd8f15b0933c001d1e8bc295e7c38dc1d2be30220e88e2155ecd2274e79848087c05e137e64d01 +a5276b216d3df3273bbfa46210b63b84cfe1e599e9e5d87c4e2e9d58666ecf1af66cb7ae65caebbe74b6806677215bd0 +88792f4aa3597bb0aebadb70f52ee8e9db0f7a9d74f398908024ddda4431221a7783e060e0a93bf1f6338af3d9b18f68 +8f5fafff3ecb3aad94787d1b358ab7d232ded49b15b3636b585aa54212f97dc1d6d567c180682cca895d9876cacb7833 +ab7cb1337290842b33e936162c781aa1093565e1a5b618d1c4d87dd866daea5cebbcc486aaa93d8b8542a27d2f8694c7 +88480a6827699da98642152ebc89941d54b4791fbc66110b7632fb57a5b7d7e79943c19a4b579177c6cf901769563f2f +a725ee6d201b3a610ede3459660658ee391803f770acc639cfc402d1667721089fb24e7598f00e49e81e50d9fd8c2423 +98924372da8aca0f67c8c5cad30fa5324519b014fae7849001dcd51b6286118f12b6c49061219c37714e11142b4d46de +a62c27360221b1a7c99697010dfe1fb31ceb17d3291cf2172624ebeff090cbaa3c3b01ec89fe106dace61d934711d42d +825173c3080be62cfdc50256c3f06fe190bc5f190d0eb827d0af5b99d80936e284a4155b46c0d462ee574fe31d60983d +a28980b97023f9595fadf404ed4aa36898d404fe611c32fd66b70252f01618896f5f3fda71aea5595591176aabf0c619 +a50f5f9def2114f6424ff298f3b128068438f40860c2b44e9a6666f43c438f1780be73cf3de884846f1ba67f9bef0802 +b1eee2d730da715543aeb87f104aff6122cb2bf11de15d2519ff082671330a746445777924521ec98568635f26988d0c +862f6994a1ff4adfd9fb021925cccf542fca4d4b0b80fb794f97e1eb2964ef355608a98eec6e07aadd4b45ee625b2a21 +8ce69a18df2f9b9f6e94a456a7d94842c61dea9b00892da7cf5c08144de9be39b8c304aeca8b2e4222f87ba367e61006 +b5f325b1cecd435f5346b6bc562d92f264f1a6d91be41d612df012684fdd69e86063db077bc11ea4e22c5f2a13ae7bee +85526870a911127835446cb83db8986b12d5637d59e0f139ad6501ac949a397a6c73bd2e7fba731b1bb357efe068242c +8552247d3f7778697f77389717def5a149fc20f677914048e1ed41553b039b5427badc930491c0bae663e67668038fd1 +a545640ee5e51f3fe5de7050e914cfe216202056cd9d642c90e89a166566f909ee575353cb43a331fde17f1c9021414e +8b51229b53cff887d4cab573ba32ec52668d197c084414a9ee5589b285481cea0c3604a50ec133105f661321c3ca50f5 +8cdc0b960522bed284d5c88b1532142863d97bbb7dc344a846dc120397570f7bd507ceb15ed97964d6a80eccfef0f28e +a40683961b0812d9d53906e795e6470addc1f30d09affebf5d4fbbd21ddfa88ce441ca5ea99c33fd121405be3f7a3757 +a527875eb2b99b4185998b5d4cf97dd0d4a937724b6ad170411fc8e2ec80f6cee2050f0dd2e6fee9a2b77252d98b9e64 +84f3a75f477c4bc4574f16ebc21aaa32924c41ced435703c4bf07c9119dd2b6e066e0c276ff902069887793378f779e0 +a3544bc22d1d0cab2d22d44ced8f7484bfe391b36991b87010394bfd5012f75d580596ffd4f42b00886749457bb6334b +b81f6eb26934b920285acc20ceef0220dd23081ba1b26e22b365d3165ce2fbae733bbc896bd0932f63dcc84f56428c68 +95e94d40a4f41090185a77bf760915a90b6a3e3ace5e53f0cb08386d438d3aa3479f0cd81081b47a9b718698817265cd +b69bd1625b3d6c17fd1f87ac6e86efa0d0d8abb69f8355a08739109831baeec03fd3cd4c765b5ff8b1e449d33d050504 +8448f4e4c043519d98552c2573b76eebf2483b82d32abb3e2bfc64a538e79e4f59c6ca92adff1e78b2f9d0a91f19e619 +8f11c42d6a221d1fda50887fb68b15acdb46979ab21d909ed529bcad6ae10a66228ff521a54a42aca0dad6547a528233 +a3adb18d7e4a882b13a067784cf80ea96a1d90f5edc61227d1f6e4da560c627688bdf6555d33fe54cab1bca242986871 +a24d333d807a48dc851932ed21cbdd7e255bad2699909234f1706ba55dea4bb6b6f8812ffc0be206755868ba8a4af3f9 +a322de66c22a606e189f7734dbb7fda5d75766d5e69ec04b4e1671d4477f5bcb9ff139ccc18879980ebc3b64ab4a2c49 +88f54b6b410a1edbf125db738d46ee1a507e69bc5a8f2f443eb787b9aa7dbd6e55014ec1e946aabeb3e27a788914fb04 +b32ee6da1dcd8d0a7fd7c1821bb1f1fe919c8922b4c1eeed56e5b068a5a6e68457c42b192cbaef5dc6d49b17fa45bc0f +8a44402da0b3a15c97b0f15db63e460506cb8bef56c457166aea5e8881087d8202724c539ef0feb97131919a73aefca8 +b967e3fead6171fa1d19fd976535d428b501baff59e118050f9901a54b12cc8e4606348454c8f0fc25bd6644e0a5532e +b7a0c9e9371c3efbbb2c6783ce2cc5f149135175f25b6d79b09c808bce74139020e77f0c616fa6dcb3d87a378532529d +a54207782ffc909cd1bb685a3aafabbc4407cda362d7b3c1b14608b6427e1696817aeb4f3f85304ac36e86d3d8caa65b +98c1da056813a7bfebc81d8db7206e3ef9b51f147d9948c088976755826cc5123c239ca5e3fe59bed18b5d0a982f3c3f +ae1c86174dfafa9c9546b17b8201719aecd359f5bbeb1900475041f2d5b8a9600d54d0000c43dd061cfda390585726ff +a8ee5a8be0bd1372a35675c87bfd64221c6696dc16e2d5e0996e481fec5cdbcb222df466c24740331d60f0521285f7d3 +8ddadbe3cf13af50d556ce8fc0dd77971ac83fad9985c3d089b1b02d1e3afc330628635a31707b32595626798ea22d45 +a5c80254baf8a1628dc77c2445ebe21fbda0de09dd458f603e6a9851071b2b7438fe74214df293dfa242c715d4375c95 +b9d83227ed2600a55cb74a7052003a317a85ca4bea50aa3e0570f4982b6fe678e464cc5156be1bd5e7bba722f95e92c5 +b56085f9f3a72bea9aa3a8dc143a96dd78513fa327b4b9ba26d475c088116cab13843c2bff80996bf3b43d3e2bddb1d6 +8fa9b39558c69a9757f1e7bc3f07295e4a433da3e6dd8c0282397d26f64c1ecd8eb3ba9824a7cacfb87496ebbb45d962 +879c6d0cb675812ed9dee68c3479a499f088068501e2677caeae035e6f538da91a49e245f5fcce135066169649872bee +91aa9fd3fed0c2a23d1edda8a6542188aeb8abee8772818769bdee4b512d431e4625a343af5d59767c468779222cf234 +a6be0bb2348c35c4143482c7ef6da9a93a5356f8545e8e9d791d6c08ed55f14d790d21ee61d3a56a2ae7f888a8fd46ca +808ee396a94e1b8755f2b13a6ffbedef9e0369e6c2e53627c9f60130c137299d0e4924d8ef367e0a7fad7f68a8c9193c +ad1086028fcdac94d5f1e7629071e7e47e30ad0190ae59aaebfb7a7ef6202ab91323a503c527e3226a23d7937af41a52 +9102bdaf79b907d1b25b2ec6b497e2d301c8eac305e848c6276b392f0ad734131a39cc02ed42989a53ca8da3d6839172 +8c976c48a45b6bc7cd7a7acea3c2d7c5f43042863b0661d5cd8763e8b50730552187a8eecf6b3d17be89110208808e77 +a2624c7e917e8297faa3af89b701953006bf02b7c95dfba00c9f3de77748bc0b13d6e15bb8d01377f4d98fb189538142 +a405f1e66783cdcfe20081bce34623ec3660950222d50b7255f8b3cc5d4369aeb366e265e5224c0204911539f0fa165e +8d69bdcaa5d883b5636ac8f8842026fcc58c5e2b71b7349844a3f5d6fbecf44443ef4f768eac376f57fb763606e92c9f +82fce0643017d16ec1c3543db95fb57bfa4855cc325f186d109539fcacf8ea15539be7c4855594d4f6dc628f5ad8a7b0 +8860e6ff58b3e8f9ae294ff2487f0d3ffae4cf54fd3e69931662dabc8efd5b237b26b3def3bcd4042869d5087d22afcf +88c80c442251e11c558771f0484f56dc0ed1b7340757893a49acbf96006aa73dfc3668208abea6f65375611278afb02a +8be3d18c6b4aa8e56fcd74a2aacb76f80b518a360814f71edb9ccf3d144bfd247c03f77500f728a62fca7a2e45e504c5 +8b8ebf0df95c3f9b1c9b80469dc0d323784fd4a53f5c5357bb3f250a135f4619498af5700fe54ad08744576588b3dfff +a8d88abdaadd9c2a66bc8db3072032f63ed8f928d64fdb5f810a65074efc7e830d56e0e738175579f6660738b92d0c65 +a0a10b5d1a525eb846b36357983c6b816b8c387d3890af62efb20f50b1cb6dd69549bbef14dab939f1213118a1ae8ec2 +8aadf9b895aeb8fdc9987daa937e25d6964cbd5ec5d176f5cdf2f0c73f6f145f0f9759e7560ab740bf623a3279736c37 +99aeda8a495031cc5bdf9b842a4d7647c55004576a0edc0bd9b985d60182608361ed5459a9d4b21aa8e2bd353d10a086 +832c8b3bfcd6e68eee4b100d58014522de9d4cefa99498bc06c6dca83741e4572e20778e0d846884b33439f160932bca +841f56ebefc0823ab484fc445d62f914e13957e47904419e42771aa605e33ab16c44f781f6f9aa42e3a1baf377f54b42 +a6e40271d419e295a182725d3a9b541ffd343f23e37549c51ecaa20d13cf0c8d282d6d15b24def5702bfee8ba10b12ac +8ac00925ac6187a4c5cde48ea2a4eaf99a607e58b2c617ee6f01df30d03fafada2f0469178dd960d9d64cbd33a0087d8 +b6b80916b540f8a0fe4f23b1a06e2b830008ad138271d5ba3cd16d6619e521fe2a7623c16c41cba48950793386eea942 +8412c0857b96a650e73af9d93087d4109dd092ddf82188e514f18fcac644f44d4d62550bfa63947f2d574a2e9d995bbb +b871395baa28b857e992a28ac7f6d95ec461934b120a688a387e78498eb26a15913b0228488c3e2360391c6b7260b504 +926e2d25c58c679be77d0e27ec3b580645956ba6f13adcbc2ea548ee1b7925c61fcf74c582337a3b999e5427b3f752f2 +a165fa43fecae9b913d5dcfc232568e3e7b8b320ce96b13800035d52844c38fd5dbf7c4d564241d860c023049de4bcbc +b4976d7572fd9cc0ee3f24888634433f725230a7a2159405946a79315bc19e2fc371448c1c9d52bf91539fd1fe39574b +a6b461eb72e07a9e859b9e16dfa5907f4ac92a5a7ca4368b518e4a508dc43f9b4be59db6849739f3ef4c44967b63b103 +b976606d3089345d0bc501a43525d9dca59cf0b25b50dfc8a61c5bd30fac2467331f0638fab2dc68838aa6ee8d2b6bc9 +b16ea61c855da96e180abf7647fa4d9dd6fd90adebadb4c5ed4d7cd24737e500212628fca69615d89cb40e9826e5a214 +95a3e3162eb5ea27a613f8c188f2e0dcc5cbd5b68c239858b989b004d87113e6aa3209fa9fad0ee6ecef42814ba9db1a +b6a026ab56d3224220e5bce8275d023c8d39d1bdf7eec3b0923429b7d5ef18cf613a3591d364be8727bb1fa0ba11eabb +949f117e2e141e25972ee9ccdd0b7a21150de7bbf92bbd89624a0c5f5a88da7b2b172ba2e9e94e1768081f260c2a2f8d +b7c5e9e6630287d2a20a2dfb783ffe6a6ff104ff627c6e4e4342acc2f3eb6e60e9c22f465f8a8dc58c42f49840eca435 +872be5a75c3b85de21447bb06ac9eb610f3a80759f516a2f99304930ddf921f34cbffc7727989cdd7181d5fc62483954 +a50976ea5297d797d220932856afdd214d1248230c9dcd840469ecc28ea9f305b6d7b38339fedb0c00b5251d77af8c95 +80b360f8b44914ff6f0ffbd8b5360e3cabe08639f6fe06d0c1526b1fe9fe9f18c497f1752580b30e950abd3e538ad416 +a2f98f9bf7fac78c9da6bb41de267742a9d31cf5a04b2fb74f551084ec329b376f651a59e1ae919b2928286fb566e495 +8b9d218a8a6c150631548e7f24bbd43f132431ae275c2b72676abbea752f554789c5ff4aac5c0eeee5529af7f2b509ef +aa21a243b07e9c7b169598bf0b102c3c280861780f83121b2ef543b780d47aaa4b1850430ee7927f33ece9847c4e0e1a +8a6f90f4ce58c8aa5d3656fe4e05acccf07a6ec188a5f3cde7bf59a8ae468e66f055ac6dfc50b6e8e98f2490d8deedc5 +8e39f77ca4b5149ffe9945ceac35d068760ba338d469d57c14f626dd8c96dbe993dd7011beff727c32117298c95ee854 +83bd641c76504222880183edd42267e0582642c4993fe2c7a20ce7168e4c3cbf7586e1d2d4b08c84d9b0bf2f6b8800b8 +a9d332993cf0c1c55130e5cf3a478eb5e0bfb49c25c07538accc692ef03d82b458750a7b991cc0b41b813d361a5d31e3 +a0fc60e6a6015df9bee04cea8f20f01d02b14b6f7aa03123ab8d65da071b2d0df5012c2a69e7290baae6ed6dd29ebe07 +a2949dde2e48788ceaac7ec7243f287ffe7c3e788cdba97a4ab0772202aeef2d50382bed8bf7eff5478243f7eabe0bda +a7879373ea18572dba6cf29868ca955ffa55b8af627f29862f6487ee398b81fe3771d8721ca8e06716c5d91b9ac587cb +b3c7081e2c5306303524fbe9fe5645111a57dffd4ec25b7384da12e56376a0150ab52f9d9cc6ca7bdd950695e39b766d +a634a6a19d52dcb9f823352b36c345d2de54b75197bcd90528d27830bd6606d1a9971170de0849ed5010afa9f031d5be +88f2062f405fa181cfdb8475eaf52906587382c666ca09a9522537cfebbc7de8337be12a7fd0db6d6f2f7ab5aefab892 +b1f0058c1f273191247b98783b2a6f5aa716cf799a8370627fc3456683f03a624d0523b63a154fe9243c0dfd5b37c460 +ae39a227cc05852437d87be6a446782c3d7fbe6282e25cf57b6b6e12b189bdc0d4a6e2c3a60b3979256b6b5baf8f1c5f +802a1af228ab0c053b940e695e7ef3338f5be7acf4e5ed01ac8498e55b492d3a9f07996b1700a84e22f0b589638909cd +a36490832f20e4b2f9e79ee358b66d413f034d6a387534b264cdeac2bca96e8b5bcbdd28d1e98c44498032a8e63d94d2 +8728c9a87db2d006855cb304bba54c3c704bf8f1228ae53a8da66ca93b2dac7e980a2a74f402f22b9bc40cd726e9c438 +a08f08ab0c0a1340e53b3592635e256d0025c4700559939aeb9010ed63f7047c8021b4210088f3605f5c14fb51d1c613 +9670fd7e2d90f241e8e05f9f0b475aa260a5fb99aa1c9e61cd023cbad8ed1270ae912f168e1170e62a0f6d319cf45f49 +a35e60f2dd04f098bf274d2999c3447730fe3e54a8aff703bc5a3c274d22f97db4104d61a37417d93d52276b27ef8f31 +859df7a21bc35daec5695201bd69333dc4f0f9e4328f2b75a223e6615b22b29d63b44d338413ca97eb74f15563628cb7 +b2b44ad3e93bc076548acdf2477803203108b89ecc1d0a19c3fb9814d6b342afc420c20f75e9c2188ad75fdb0d34bb2d +941173ee2c87765d10758746d103b667b1227301e1bcfecef2f38f9ab612496a9abd3050cef5537bf28cfecd2aacc449 +92b0bea30ebed20ac30648efb37bac2b865daaa514316e6f5470e1de6cb84651ff77c127aa7beed4521bda5e8fc81122 +af17bf813bb238cf8bb437433f816786612209180a6c0a1d5141292dc2d2c37164ef13bfc50c718bfcc6ce26369298a2 +8461fd951bdfda099318e05cc6f75698784b033f15a71bce26165f0ce421fd632d50df9eeced474838c0050b596e672c +83281aa18ae4b01e8201e1f64248cc6444c92ee846ae72adb178cef356531558597d84ff93a05abf76bfe313eb7dbe86 +b62b150f73999c341daa4d2f7328d2f6ca1ef3b549e01df58182e42927537fc7971c360fe8264af724f4c0247850ef12 +a7022a201f79c012f982b574c714d813064838a04f56964d1186691413757befeeaada063e7884297606e0eea1b1ed43 +a42ac9e8be88e143853fd8e6a9ff21a0461801f0ac76b69cca669597f9af17ecb62cccdcdcbe7f19b62ab93d7f838406 +80f1ca73b6ba3a2fbae6b79b39c0be8c39df81862d46c4990c87cbf45b87996db7859d833abc20af2fcb4faf059c436a +b355943e04132d5521d7bbe49aea26f6aa1c32f5d0853e77cc2400595325e923a82e0ff7601d1aee79f45fd8a254f6ae +87142c891d93e539b31d0b5ead9ea600b9c84db9be9369ff150a8312fe3d10513f4c5b4d483a82b42bc65c45dd9dd3bd +823c3d7f6dda98a9d8c42b3fee28d3154a95451402accadb6cf75fc45d2653c46a569be75a433094fa9e09c0d5cf1c90 +b3c3497fe7356525c1336435976e79ec59c5624c2fb6185ee09ca0510d58b1e392965e25df8a74d90d464c4e8bb1422b +88c48d83e8ddc0d7eea051f3d0e21bc0d3a0bb2b6a39ece76750c1c90c382a538c9a35dc9478b8ceb8157dcccbbf187a +93da81a8939f5f58b668fefdc6f5f7eca6dc1133054de4910b651f8b4a3267af1e44d5a1c9e5964dc7ab741eb146894b +8b396e64985451ac337f16be61105106e262e381ea04660add0b032409b986e1ac64da3bc2feae788e24e9cb431d8668 +9472068b6e331ea67e9b5fbf8057672da93c209d7ded51e2914dbb98dccd8c72b7079b51fd97a7190f8fc8712c431538 +ac47e1446cb92b0a7406f45c708567f520900dfa0070d5e91783139d1bfc946d6e242e2c7b3bf4020500b9f867139709 +896053706869fb26bb6f7933b3d9c7dd6db5c6bd1269c7a0e222b73039e2327d44bda7d7ae82bf5988808b9831d78bcd +a55e397fa7a02321a9fe686654c86083ecedb5757586d7c0250ec813ca6d37151a12061d5feca4691a0fd59d2f0fdd81 +ae23f08ac2b370d845036518f1bddb7fea8dc59371c288a6af310486effeb61963f2eef031ca90f9bdbcf0e475b67068 +b5462921597a79f66c0fec8d4c7cfd89f427692a7ce30d787e6fd6acd2377f238ec74689a0fdbe8ef3c9c9bd24b908dc +ae67e8ea7c46e29e6aae6005131c29472768326819aa294aaf5a280d877de377b44959adb1348fa3e929dcbc3ae1f2c0 +84962b4c66500a20c4424191bdfb619a46cda35bdb34c2d61edcb0b0494f7f61dd5bf8f743302842026b7b7d49edd4b5 +846f76286dc3cc59cb15e5dabb72a54a27c78190631df832d3649b2952fa0408ecde7d4dfdae7046c728efa29879fb51 +8f76c854eaee8b699547e07ad286f7dadfa6974c1328d12502bd7630ae619f6129272fdd15e2137ffef0143c42730977 +8007b163d4ea4ec6d79e7a2aa19d06f388da0b3a56f3ee121441584e22a246c0e792431655632bf6e5e02cb86914eebf +ac4d2cecc1f33e6fb73892980b61e62095ddff5fd6167f53ca93d507328b3c05440729a277dc3649302045b734398af1 +92d2a88f2e9c9875abaff0d42624ccb6d65401de7127b5d42c25e6adccd7a664504c5861618f9031ced8aeb08b779f06 +a832c1821c1b220eb003fc532af02c81196e98df058cdcc9c9748832558362915ea77526937f30a2f74f25073cb89afb +b6f947ab4cc2baec100ed8ec7739a2fd2f9504c982b39ab84a4516015ca56aea8eef5545cfc057dd44c69b42125fb718 +b24afacf2e90da067e5c050d2a63878ee17aaf8fd446536f2462da4f162de87b7544e92c410d35bf2172465940c19349 +b7a0aa92deac71eaab07be8fa43086e071e5580f5dbf9b624427bdd7764605d27303ae86e5165bed30229c0c11958c38 +b0d1d5bfa1823392c5cf6ed927c1b9e84a09a24b284c2cd8fcb5fda8e392c7c59412d8f74eb7c48c6851dff23ae66f58 +a24125ef03a92d2279fb384186ca0274373509cfec90b34a575490486098438932ee1be0334262d22d5f7d3db91efe67 +83e08e5fba9e8e11c164373794f4067b9b472d54f57f4dbe3c241cf7b5b7374102de9d458018a8c51ab3aed1dddf146f +9453101b77bb915ed40990e1e1d2c08ea8ec5deb5b571b0c50d45d1c55c2e2512ec0ceca616ff0376a65678a961d344d +92a0516e9eb6ad233d6b165a8d64a062ce189b25f95d1b3264d6b58da9c8d17da2cd1f534800c43efcf2be73556cd2ff +958d0b5d7d8faf25d2816aa6a2c5770592ad448db778dd9b374085baa66c755b129822632eaabcb65ee35f0bf4b73634 +90a749de8728b301ad2a6b044e8c5fd646ccd8d20220e125cba97667e0bb1d0a62f6e3143b28f3d93f69cdc6aa04122a +84bd34c8d8f74dec07595812058db24d62133c11afed5eb2a8320d3bfc28e442c7f0cfd51011b7b0bb3e5409cb7b6290 +aecc250b556115d97b553ad7b2153f1d69e543e087890000eaa60f4368b736921d0342ce5563124f129096f5d5e2ca9d +977f17ac82ed1fbf422f9b95feb3047a182a27b00960296d804fd74d54bb39ad2c055e665c1240d2ad2e06a3d7501b00 +af5be9846bd4879ebe0af5e7ad253a632f05aedfe306d31fe6debe701ba5aa4e33b65efc05043bc73aadb199f94baed4 +9199e12ec5f2aaaeed6db5561d2dcc1a8fe9c0854f1a069cba090d2dff5e5ba52b10c841ccbd49006a91d881f206150d +8f4a96a96ed8ceaf3beba026c89848c9ca4e6452ce23b7cf34d12f9cc532984a498e051de77745bdc17c7c44c31b7c30 +af3f2a3dbe8652c4bfca0d37fb723f0e66aab4f91b91a625114af1377ad923da8d36da83f75deb7a3219cd63135a3118 +a6d46963195df8962f7aa791d104c709c38caa438ddd192f7647a884282e81f748c94cdf0bb25d38a7b0dc1b1d7bbcf7 +86f3de4b22c42d3e4b24b16e6e8033e60120af341781ab70ae390cb7b5c5216f6e7945313c2e04261a51814a8cb5db92 +b9f86792e3922896cfd847d8ff123ff8d69ecf34968fb3de3f54532f6cd1112b5d34eeabdca46ae64ad9f6e7e5b55edc +83edfbcbc4968381d1e91ab813b3c74ab940eaf6358c226f79182f8b21148ec130685fd91b0ea65916b0a50bccf524ea +93b61daca7a8880b7926398760f50016f2558b0bab74c21181280a1baf3414fc539911bb0b79c4288d29d3c4ad0f4417 +ad541aeb83a47526d38f2e47a5ce7e23a9adabe5efeae03541026881e6d5ef07da3ac1a6ed466ca924fa8e7a91fcff88 +ac4bba31723875025640ed6426003ed8529215a44c9ffd44f37e928feef9fc4dfa889088131c9be3da87e8f3fdf55975 +88fa4d49096586bc9d29592909c38ea3def24629feacd378cc5335b70d13814d6dac415f8c699ee1bf4fe8b85eb89b38 +b67d0b76cbd0d79b71f4673b96e77b6cda516b8faa1510cfe58ff38cc19000bb5d73ff8418b3dab8c1c7960cb9c81e36 +98b4f8766810f0cfecf67bd59f8c58989eb66c07d3dfeee4f4bbce8fd1fce7cc4f69468372eaec7d690748543bd9691d +8445891af3c298b588dec443beacdf41536adb84c812c413a2b843fd398e484eb379075c64066b460839b5fe8f80177c +b603635c3ed6fdc013e2a091fc5164e09acf5f6a00347d87c6ebadb1f44e52ff1a5f0466b91f3f7ffc47d25753e44b75 +87ec2fc928174599a9dafe7538fec7dcf72e6873b17d953ed50708afff0da37653758b52b7cafa0bf50dfcf1eafbb46c +b9dbd0e704d047a457d60efe6822dc679e79846e4cbcb11fa6c02079d65673ee19bbf0d14e8b7b200b9205f4738df7c7 +9591ec7080f3f5ba11197a41f476f9ba17880f414d74f821a072ec5061eab040a2acba3d9856ff8555dfe5eaeb14ca19 +b34c9d1805b5f1ce38a42b800dec4e7f3eb8c38e7d2b0a525378e048426fed150dbfe9cc61f5db82b406d1b9ff2d10bf +a36fdc649dc08f059dfa361e3969d96b4cc4a1ebf10b0cd01a7dd708430979e8d870961fef85878f8779b8e23caafb18 +88dfc739a80c16c95d9d6f73c3357a92d82fa8c3c670c72bee0f1e4bac9ec338e1751eb786eda3e10f747dd7a686900f +84a535ad04f0961756c61c70001903a9adf13126983c11709430a18133c4b4040d17a33765b4a06968f5d536f4bfb5c5 +8c86d695052a2d2571c5ace744f2239840ef21bb88e742f050c7fa737cd925418ecef0971333eb89daa6b3ddfede268c +8e9a700157069dc91e08ddcbdde3a9ad570272ad225844238f1015004239c542fceb0acce6d116c292a55f0d55b6175e +84d659e7f94e4c1d15526f47bc5877a4ef761c2a5f76ec8b09c3a9a30992d41b0e2e38ed0c0106a6b6c86d670c4235f3 +a99253d45d7863db1d27c0ab561fb85da8c025ba578b4b165528d0f20c511a9ca9aff722f4ff7004843f618eb8fced95 +89a3cacb15b84b20e95cd6135550146bbe6c47632cc6d6e14d825a0c79b1e02b66f05d57d1260cb947dc4ae5b0283882 +8385b1555e794801226c44bd5e878cbe68aeac0a19315625a8e5ea0c3526b58cdd4f53f9a14a167a5e8a293b530d615a +b68c729e9df66c5cd22af4909fb3b0057b6a231c4a31cd6bf0fa0e53c5809419d15feb483de6e9408b052458e819b097 +924f56eda269ec7ec2fc20c5731bf7f521546ddf573ccbe145592f1c9fee5134747eb648d9335119a8066ca50a1f7e50 +b2100a26b9c3bec7ec5a53f0febbf56303f199be2f26b2d564cfee2adc65483b84192354f2865c2f4c035fa16252ae55 +8f64dbed62e638563967ec1605a83216aed17eb99aa618c0543d74771ea8f60bbb850c88608d4f8584f922e30a8a0a72 +b31b9e1ffe8d7260479c9413f8e680f3fe391ae8fcf44fcca3000d9b2473a40c1d32299f8f63865a57579a2d6c7e9f08 +a5b1d136142eb23e322c6c07cb838a3f58ab6925472352ebd0bb47041a0d8729e1074ca223922f3a7a672ced7a1e562d +8d9470a5a15d833a447b5f108333d50f30aa7659e331c3f8080b1e928a99922edc650466a2f54f3d48afdb34bff42142 +866368f5891564e5b2de37ad21ff0345c01129a14ea5667f9b64aad12d13ec034622872e414743af0bf20adb2041b497 +88ef9c2ebf25fd0c04b7cfa35fbac2e4156d2f1043fa9f98998b2aa402c8f9a4f1039e782451a46840f3e0e4b3fa47d3 +94ba04a4859273697e264a2d238dc5c9ff573ebc91e4796ea58eebe4080c1bf991255ab2ad8fb1e0301ce7b79cc6e69b +86b6bd0953309a086e526211bf1a99327269304aa74d8cdc994cee63c3a2d4b883e832b0635888dff2a13f1b02eb8df4 +843ea6ea5f2c7a1fd50be56a5765dcce3ea61c99b77c1a729ee0cd8ec706385ac7062e603479d4c8d3527f030762d049 +8d3675195a3b06f2d935d45becc59f9fa8fa440c8df80c029775e47fe9c90e20f7c8e4cc9a2542dd6bfe87536c428f0d +8978580b0c9b0aa3ab2d47e3cfd92fa891d3ddee57829ee4f9780e8e651900457d8e759d1a9b3e8f6ae366e4b57f2865 +890112ec81d0f24b0dfbb4d228e418eff02ae63dc691caf59c1d103e1d194e6e2550e1bec41c0bfdb74fed454f621d0c +97da00bd4b19d1e88caff7f95b8b9a7d29bc0afe85d0c6a163b4b9ef336f0e90e2c49ce6777024bb08df908cc04ea1ca +b458268d275a5211106ccaa8333ce796ef2939b1c4517e502b6462e1f904b41184a89c3954e7c4f933d68b87427a7bfd +aac9c043ba8ba9283e8428044e6459f982413380ee7005a996dc3cc468f6a21001ecaa3b845ce2e73644c2e721940033 +82145013c2155a1200246a1e8720adf8a1d1436b10d0854369d5b1b6208353e484dd16ce59280c6be84a223f2d45e5e2 +b301bafa041f9b203a46beab5f16160d463aa92117c77a3dc6a9261a35645991b9bafcc186c8891ca95021bd35f7f971 +a531b8d2ac3de09b92080a8d8857efa48fb6a048595279110e5104fee7db1dd7f3cfb8a9c45c0ed981cbad101082e335 +a22ac1d627d08a32a8abd41504b5222047c87d558ffae4232cefdeb6a3dc2a8671a4d8ddfba2ff9068a9a3ffb0fe99b1 +b8d9f0e383c35afb6d69be7ff04f31e25c74dd5751f0e51290c18814fbb49ee1486649e64355c80e93a3d9278bd21229 +8165babccd13033a3614c878be749dfa1087ecbeee8e95abcfffe3aa06695711122cb94477a4d55cffd2febf0c1173de +a4c1bc84ecb9d995d1d21c2804adf25621676d60334bd359dac3a2ec5dc8de567aa2831c10147034025fb3e3afb33c4b +b77307cab8e7cb21e4038493058fb6db9e2ec91dda9d7f96f25acbc90309daf7b6d8a205682143ee35d675e9800c3b08 +aaf7466083cd1f325ba860efe3faf4cebe6a5eecf52c3e8375d72043a5cfc8e6cb4b40f8e48f97266e84f0d488e8badf +9264a05a3abc2a5b4958f957f3a486a5eb3ddd10ff57aa6943c9430d0cfa01d63b72695b1ade50ac1b302d312175e702 +b3f9e4c589ad28b1eceed99dc9980fac832524cfcbe4a486dfeedb4b97c080e24bdb3967e9ca63d2240e77f9addfaefd +b2c1e253a78e7179e5d67204422e0debfa09c231970b1bfb70f31a8d77c7f5059a095ca79d2e9830f12c4a8f88881516 +81865a8a25913d1072cb5fd9505c73e0fde45e4c781ddd20fb0a7560d8b1cd5e1f63881c6efc05360e9204dfa6c3ce16 +ab71c2ea7fa7853469a2236dedb344a19a6130dc96d5fd6d87d42d3fffda172557d203b7688ce0f86acd913ce362e6cd +8aa2051bc3926c7bd63565f3782e6f77da824cb3b22bb056aa1c5bccfa274c0d9e49a91df62d0e88876e2bd7776e44b9 +b94e7074167745323d1d353efe7cfb71f40a390e0232354d5dfd041ef523ac8f118fb6dcc42bf16c796e3f61258f36f8 +8210fcf01267300cb1ccf650679cf6e1ee46df24ae4be5364c5ff715332746c113d680c9a8be3f17cacaeb3a7ba226ce +905ac223568eedc5acd8b54e892be05a21abbb4083c5dbec919129f9d9ffa2c4661d78d43bf5656d8d7aafa06f89d647 +a6e93da7e0c998e6ce2592d1aa87d12bf44e71bec12b825139d56682cdce8f0ba6dbfe9441a9989e10578479351a3d9d +acde928a5e2df0d65de595288f2b81838155d5673013100a49b0cb0eb3d633237af1378148539e33ccd1b9a897f0fec3 +a6e1a47e77f0114be6ae7acd2a51e6a9e38415cce7726373988153cdd5d4f86ef58f3309adc5681af4a159300ed4e5b5 +ad2b6a0d72f454054cb0c2ebc42cd59ff2da7990526bd4c9886003ba63b1302a8343628b8fe3295d3a15aa85150e0969 +b0bc3aea89428d7918c2ee0cc57f159fba134dad224d0e72d21a359ca75b08fbb4373542f57a6408352033e1769f72c6 +aad0497525163b572f135fad23fdd8763631f11deeaf61dea5c423f784fe1449c866040f303555920dc25e39cdb2e9b4 +8ce5d8310d2e17342bf881d517c9afc484d12e1f4b4b08ad026b023d98cba410cd9a7cc8e2c3c63456652a19278b6960 +8d9d57dbb24d68b6152337872bd5d422198da773174ade94b633f7c7f27670ff91969579583532ae7d8fe662c6d8a3b0 +855a1c2d83becb3f02a8f9a83519d1cb112102b61d4cdd396844b5206e606b3fefdbcc5aa8751da2b256d987d74d9506 +90eb7e6f938651f733cf81fcd2e7e8f611b627f8d94d4ac17ac00de6c2b841e4f80cada07f4063a13ae87b4a7736ca28 +8161459a21d55e7f5f1cecfc1595c7f468406a82080bfa46d7fb1af4b5ec0cd2064c2c851949483db2aa376e9df418e6 +8344ccd322b2072479f8db2ab3e46df89f536408cba0596f1e4ec6c1957ff0c73f3840990f9028ae0f21c1e9a729d7df +929be2190ddd54a5afe98c3b77591d1eae0ab2c9816dc6fe47508d9863d58f1ea029d503938c8d9e387c5e80047d6f1e +856e3d1f701688c650c258fecd78139ce68e19de5198cf1cd7bb11eba9d0f1c5af958884f58df10e3f9a08d8843f3406 +8490ae5221e27a45a37ca97d99a19a8867bcc026a94f08bdccfbb4b6fa09b83c96b37ec7e0fd6ee05f4ae6141b6b64a8 +b02dbd4d647a05ac248fda13708bba0d6a9cd00cae5634c1938b4c0abbb3a1e4f00f47aa416dcd00ffcdf166330bff9a +9076164bb99ca7b1a98d1e11cb2f965f5c22866658e8259445589b80e3cb3119c8710ede18f396ba902696785619079c +aacf016920936dae63778ad171386f996f65fe98e83cfcdd75e23774f189303e65cc8ad334a7a62f9230ed2c6b7f6fa4 +a8031d46c7f2474789123469ef42e81c9c35eb245d38d8f4796bba406c02b57053f5ec554d45373ab437869a0b1af3f0 +a4b76cd82dc1f305a0ee053e9a4212b67f5acc5e69962a8640d190a176b73fbc2b0644f896ff3927cd708d524668ed09 +b00b029c74e6fdf7fb94df95ef1ccad025c452c19cddb5dccfb91efdcb8a9a1c17847cfa4486eae4f510e8a6c1f0791a +9455e5235f29a73e9f1a707a97ddb104c55b9d6a92cc9952600d49f0447d38ea073ee5cf0d13f7f55f12b4a5132f4b10 +ae118847542ed1084d269e8f3b503d0b6571a2c077def116ad685dcca2fca3dcb3f86e3f244284bdcd5ae7ac968d08a5 +8dcb4965cd57e8b89cd71d6fc700d66caa805bfd29ab71357961527a7894e082d49145c2614b670dcb231ab9050d0663 +add6ed14f3183f4acc73feea19b22c9a330e431c674e5034924da31b69e8c02d79b570d12ef771a04215c4809e0f8a80 +96ae7e110412ee87d0478fdbdbaab290eb0b6edd741bb864961845e87fd44bcbe630371060b8104d8bf17c41f2e3fca0 +a20db17f384e9573ca0928af61affab6ff9dd244296b69b026d737f0c6cd28568846eca8dadf903ee0eecbb47368351d +937bfdf5feb0797863bc7c1be4dcc4f2423787952a3c77dfa3bfe7356f5dbcc4daebde976b84fc6bd97d5124fb8f85c9 +a7050cc780445c124e46bba1acc0347ddcfa09a85b35a52cc5808bf412c859c0c680c0a82218f15a6daeefe73f0d0309 +a9d9b93450e7630f1c018ea4e6a5ca4c19baa4b662eadfbe5c798fe798d8a3775ed1eb12bd96a458806b37ab82bdc10a +a52a4d5639e718380915daaefad7de60764d2d795443a3db7aeab5e16a1b8faa9441a4ccc6e809d8f78b0ac13eef3409 +8e6f72b6664a8433b032849b03af68f9376b3c16c0bc86842c43fc7bf31e40bc9fc105952d5c5780c4afa19d7b802caa +a107ae72f037000c6ee14093de8e9f2c92aa5f89a0a20007f4126419e5cb982469c32187e51a820f94805c9fccd51365 +9708218f9a984fe03abc4e699a4f3378a06530414a2e95e12ca657f031ef2e839c23fd83f96a4ba72f8203d54a1a1e82 +b9129770f4c5fcac999e98c171d67e148abd145e0bf2a36848eb18783bb98dff2c5cef8b7407f2af188de1fae9571b1c +88cc9db8ff27eb583871eeeb517db83039b85404d735517c0c850bdfa99ae1b57fd24cf661ab60b4726878c17e047f37 +a358c9aadc705a11722df49f90b17a2a6ba057b2e652246dc6131aaf23af66c1ca4ac0d5f11073a304f1a1b006bc0aa5 +ac79f25af6364a013ba9b82175ccee143309832df8f9c3f62c193660253679284624e38196733fb2af733488ab1a556e +82338e3ed162274d41a1783f44ae53329610134e6c62565353fbcc81131e88ce9f8a729d01e59e6d73695a378315111b +aa5ddcabf580fd43b6b0c3c8be45ffd26c9de8fa8d4546bb92d34f05469642b92a237d0806a1ad354f3046a4fcf14a92 +b308d2c292052a8e17862c52710140ffafa0b3dbedd6a1b6334934b059fe03e49883529d6baf8b361c6e67b3fbf70100 +96d870a15c833dddd8545b695139733d4a4c07d6206771a1524500c12607048731c49ec4ac26f5acc92dd9b974b2172c +8e99ee9ed51956d05faaf5038bffd48a2957917a76d9974a78df6c1ff3c5423c5d346778f55de07098b578ad623a390e +a19052d0b4b89b26172c292bbf6fd73e7486e7fd3a63c7a501bbd5cf7244e8e8ce3c1113624086b7cdf1a7693fdad8b5 +958957caf99dc4bb6d3c0bc4821be10e3a816bd0ba18094603b56d9d2d1383ccc3ee8bc36d2d0aea90c8a119d4457eb4 +8482589af6c3fc4aa0a07db201d8c0d750dd21ae5446ff7a2f44decf5bff50965fd6338745d179c67ea54095ecd3add4 +8a088cc12cf618761eaa93da12c9158b050c86f10cd9f865b451c69e076c7e5b5a023e2f91c2e1eed2b40746ca06a643 +85e81101590597d7671f606bd1d7d6220c80d3c62e9f20423e734482c94547714a6ac0307e86847cce91de46503c6a8a +b1bd39b481fc452d9abf0fcb73b48c501aaae1414c1c073499e079f719c4e034da1118da4ff5e0ce1c5a71d8af3f4279 +942ae5f64ac7a5353e1deb2213f68aa39daa16bff63eb5c69fc8d9260e59178c0452227b982005f720a3c858542246c8 +99fea18230e39df925f98e26ff03ab959cae7044d773de84647d105dfa75fd602b4f519c8e9d9f226ec0e0de0140e168 +97b9841af4efd2bfd56b9e7cd2275bc1b4ff5606728f1f2b6e24630dbe44bc96f4f2132f7103bca6c37057fc792aeaab +94cdad044a6ab29e646ed30022c6f9a30d259f38043afcea0feceef0edc5f45297770a30718cbfec5ae7d6137f55fe08 +a533a5efa74e67e429b736bb60f2ccab74d3919214351fe01f40a191e3ec321c61f54dd236f2d606c623ad556d9a8b63 +b7bd0bb72cd537660e081f420545f50a6751bb4dd25fde25e8218cab2885dd81ffe3b888d608a396dfcb78d75ba03f3f +b1479e7aa34594ec8a45a97611d377206597149ece991a8cef1399738e99c3fa124a40396a356ab2ea135550a9f6a89f +b75570fc94b491aef11f70ef82aeb00b351c17d216770f9f3bd87f3b5ac90893d70f319b8e0d2450dc8e21b57e26df94 +a5e3f3ab112530fe5c3b41167f7db5708e65479b765b941ce137d647adb4f03781f7821bb4de80c5dc282c6d2680a13d +b9b9c81b4cac7aca7e7c7baac2369d763dd9846c9821536d7467b1a7ec2e2a87b22637ab8bbeddb61879a64d111aa345 +b1e3ee2c4dd03a60b2991d116c372de18f18fe279f712829b61c904103a2bd66202083925bc816d07884982e52a03212 +a13f0593791dbbd360b4f34af42d5cc275816a8db4b82503fe7c2ff6acc22ae4bd9581a1c8c236f682d5c4c02cc274cc +86ba8238d3ed490abcc3f9ecc541305876315fb71bca8aaf87538012daab019992753bf1e10f8670e33bff0d36db0bf0 +b65fbb89fafb0e2a66fe547a60246d00b98fe2cb65db4922d9cef6668de7b2f4bb6c25970f1e112df06b4d1d953d3f34 +abb2d413e6f9e3c5f582e6020f879104473a829380b96a28123eb2bdd41a7a195f769b6ac70b35ba52a9fee9d6a289c3 +88ec764573e501c9d69098a11ea1ad20cdc171362f76eb215129cfcca43460140741ea06cee65a1f21b708afb6f9d5b0 +a7aaec27246a3337911b0201f4c5b746e45780598004dac15d9d15e5682b4c688158adffdef7179abb654f686e4c6adc +a1128589258f1fbfa33341604c3cb07f2a30c651086f90dce63ae48b4f01782e27c3829de5102f847cde140374567c58 +aaf2b149c1ca9352c94cc201125452b1ed7ca7c361ed022d626899426cb2d4cc915d76c58fa58b3ad4a6284a9ae1bc45 +aaf5c71b18b27cd8fe1a9028027f2293f0753d400481655c0d88b081f150d0292fb9bd3e6acabb343a6afb4afdb103b5 +947c0257d1fb29ecc26c4dc5eab977ebb47d698b48f9357ce8ff2d2ed461c5725228cc354a285d2331a60d20de09ff67 +b73e996fa30f581699052ed06054c474ebdf3ae662c4dc6f889e827b8b6263df67aeff7f2c7f2919df319a99bdfdceb1 +b696355d3f742dd1bf5f6fbb8eee234e74653131278861bf5a76db85768f0988a73084e1ae03c2100644a1fa86a49688 +b0abca296a8898ac5897f61c50402bd96b59a7932de61b6e3c073d880d39fc8e109998c9dba666b774415edddcff1997 +b7abe07643a82a7cb409ee4177616e4f91ec1cf733699bf24dec90da0617fe3b52622edec6e12f54897c4b288278e4f3 +8a3fae76993edbc81d7b47f049279f4dd5c408133436605d934dee0eadde187d03e6483409713db122a2a412cd631647 +82eb8e48becfdf06b2d1b93bf072c35df210cf64ed6086267033ad219bf130c55ee60718f28a0e1cad7bc0a39d940260 +a88f783e32944a82ea1ea4206e52c4bcf9962b4232e3c3b45bd72932ee1082527bf80864ce82497e5a8e40f2a60962d0 +830cf6b1e99430ae93a3f26fbfb92c741c895b017924dcd9e418c3dc4a5b21105850a8dd2536fa052667e508b90738f2 +990dce4c2c6f44bb6870328fba6aa2a26b0b8b2d57bfb24acf398b1edc0f3790665275f650884bd438d5403973469fa2 +a2e5b6232d81c94bcb7fed782e2d00ff70fc86a3abddbe4332cb0544b4e109ae9639a180ae4c1f416752ed668d918420 +b4cdf7c2b3753c8d96d92eb3d5fa984fef5d346a76dc5016552069e3f110356b82e9585b9c2f5313c76ffaecef3d6fd8 +83b23b87f91d8d602bff3a4aa1ead39fcc04b26cf113a9da6d2bd08ba7ea827f10b69a699c16911605b0126a9132140f +8aae7a2d9daa8a2b14f9168fe82933b35587a3e9ebf0f9c37bf1f8aa015f18fb116b7fba85a25c0b5e9f4b91ba1d350b +80d1163675145cc1fab9203d5581e4cd2bed26ad49f077a7927dec88814e0bed7912e6bbe6507613b8e393d5ee3be9be +93ddeb77b6a4c62f69b11cf36646ed089dcaa491590450456a525faf5659d810323b3effa0b908000887c20ac6b12c80 +9406360a2b105c44c45ba440055e40da5c41f64057e6b35a3786526869b853472e615e6beb957b62698a2e8a93608e13 +93bfc435ab9183d11e9ad17dac977a5b7e518db720e79a99072ce7e1b8fcb13a738806f414df5a3caa3e0b8a6ce38625 +8a12402c2509053500e8456d8b77470f1bbb9785dd7995ebbbe32fd7171406c7ce7bd89a96d0f41dbc6194e8f7442f42 +aab901e35bf17e6422722c52a9da8b7062d065169bf446ef0cbf8d68167a8b92dab57320c1470fee1f4fc6100269c6e2 +8cad277d9e2ba086378190d33f1116ba40071d2cb78d41012ec605c23f13009e187d094d785012b9c55038ec96324001 +85511c72e2894e75075436a163418279f660c417e1d7792edce5f95f2a52024d1b5677e2e150bf4339ad064f70420c60 +85549ca8dcbe49d16d4b3e2b8a30495f16c0de35711978ada1e2d88ad28e80872fca3fb02deb951b8bcb01b6555492e4 +8d379ab35194fe5edf98045a088db240a643509ddc2794c9900aa6b50535476daa92fd2b0a3d3d638c2069e535cd783b +b45cfebe529556b110392cb64059f4eb4d88aaf10f1000fdd986f7f140fdd878ce529c3c69dfd2c9d06f7b1e426e38f3 +ac009efd11f0c4cdd07dd4283a8181420a2ba6a4155b32c2fed6b9f913d98e057d0f5f85e6af82efc19eb4e2a97a82df +b2c2cdffa82f614e9cb5769b7c33c7d555e264e604e9b6138e19bcfc49284721180b0781ecbf321d7e60259174da9c3c +95789960f848797abbe1c66ef05d01d920228ca1f698130c7b1e6ca73bfda82cee672d30a9787688620554e8886554ee +98444018fa01b7273d3370eeb01adc8db902d5a69b9afc0aa9eadfeb43c4356863f19078d3c0d74e80f06ecf5a5223f4 +87d20b058050542f497c6645de59b8310f6eeec53acbc084e38b85414c3ea3016da3da690853498bde1c14de1db6f391 +a5c12b3a40e54bee82a315c503c1ce431309a862458030dde02376745ec1d6b9c1dbeea481ae6883425e9dae608e444e +b9daa3bf33f0a2979785067dcece83250e7bf6deb75bb1dbbab4af9e95ddfb3d38c288cbef3f80519a8916a77a43b56c +b682ec3118f71bde6c08f06ea53378ea404f8a1c4c273dd08989f2df39d6634f6463be1d172ac0e06f0fa19ac4a62366 +a4f94fd51ecf9d2065177593970854d3dce745eebb2a6d49c573cbf64a586ae949ddfa60466aaef0c0afb22bd92e0b57 +86cd5609efd570c51adbc606c1c63759c5f4f025fcbefab6bc3045b6ad2423628c68f5931ff56fdda985168ce993cc24 +981192e31e62e45572f933e86cdd5b1d28b1790b255c491c79bd9bb4964359b0e5f94f2ae0e00ef7fe7891b5c3904932 +9898f52b57472ebc7053f7bf7ab6695ce8df6213fc7f2d6f6ea68b5baad86ec1371a29304cae1baadf15083296958d27 +b676c4a8a791ae00a2405a0c88b9544878749a7235d3a5a9f53a3f822e0c5c1b147a7f3f0fc228049dc46e87aa6b6368 +9976e10beff544e5c1645c81a807739eff90449df58ffdd8d1aa45dd50b4c62f9370538b9855a00dd596480f38ebe7a5 +a0e91404894187ec23c16d39d647ada912a2c4febfd050a1ea433c4bfdc1568b4e97a78a89ba643aca3e2782033c3c58 +91a6ea9a80476ed137eb81558ff1d55b8581663cccd41db4fc286876226b6515fd38661557419e1e46b6a3bc9cda3741 +b9e8a1e23c60335a37a16f8085f80178a17d5e055d87ffe8cf63c532af923e5a5a2d76cf078164fb577996683796caa6 +ad8e151d87a37e8df438d0a6a7c02c3f511143efb93fde8aef334d218cb25932baf9e97c2f36c633620a024a5626af3d +978f942f210e8a482015e6fdc35a4c967c67b66e6e2a17a05cc7a0f2163aed227b775d4352b0c3cca6cbf4bd5bafaf75 +b5e2e3d8b2e871c07f5899e108e133f87479959b80cb8a103fbecde00ccdbfbd997540eef33079c5cc14b1c00c009fd1 +88a164b3fefd36857f429ab10002243b053f5d386466dbb9e5135ed3c72dd369a5a25e5e2aaa11f25488535e044e2f12 +a66091c0db4e7cf05a089ec2b9ff74744354d0196968201f5e201699144b52bb13b4e68e12502727163e6db96e3565f2 +8e65aff8e37240461b7374c20bfd1d58b73a525c28994a98f723daed9486130b3189f8efe5c5efcd7f5390cc366038da +8b37c21dd7304c3aa366959ba8c77ea8b22164a67e136808b6f8e48604297f7429a6c6ecf67b1d09b8b7ec083eacd7e0 +b689b1277ad050f53da91a702516a06d7406ff33a4714ea859b3b2b69f8d0aa8f983c7e039b19c0759a3815d841fa409 +b17f7a0a182ed4937f88489e4c4e6163dcf49fd2ea4d9efbba8126c743bea951cd769752acd02e921774dc8ebcfae33b +8b7fab4f90be825ac5d782a438e55c0a86be1c314a5dbc3cc6ed60760a8a94ef296391f1f6363652200cce4c188dae67 +ab8410c4eaa2bb43b0dd271aa2836061bc95cb600b0be331dada76ddb46711ff7a4ad8c466cc1078b9f9131f0dc9d879 +9194bd7b3cc218624459d51c4d6dbc13da5d3de313448f8175650fa4cfab7cc4afcda5427b6676c3c13897dc638b401e +980f61a0f01349acd8fc9fdc88fc2c5813610c07eecb6ab14af0845a980792a60dadf13bb4437b0169ae3eff8f5984ce +b783bee24acea9c99d16434195c6940cf01fc2db135e21f16acae45a509eca3af6b9232a8aa3a86f9715c5f6a85cb1c3 +a3079931c4b90966d1faa948db847741878b5828bc60325f5ebe554dcab4adcc19ee8bce645e48a8f4a9413bb3c6a093 +801f61ac9318f6e033a99071a46ae06ed249394638c19720831fff850226363a4ae8486dd00967746298ee9f1d65462f +b34dbbed4f3bb91f28285c40f64ce60c691737cc2b2d2be5c7d0210611cd58341bb5bda51bb642d3ee2d80882e642a13 +8750af19abfb915e63c81542b13d84526a0c809179bbcc1cd8a52b29f3aba3ae0f7cf6f4f01790bf64ef7db01d8ee887 +a6ea10000eb2dd4efc242ac95bc3b3873cdd882fbeb7c9538c87e3143a263ca3a2e192b2159316a625cfb5fb0b6cdcb3 +aa40ca54bc758a6c64cb932924917581062e088b3ad43976b28f2e11d8a7dea73f1fb50aeaa0e70182bb2dc07d805bb9 +a4779dfd25b5ec9d75dfb54a4bb030364899a5e75c1492403acb19f2adc782c7ac4daeb66d2f5aeb74135afe9f318e3f +b4551e2805d63ca453f4f38b1921ac87ff687e1d70575ad38f3469d6f0608ef76b7b1b98ae1e6b1e7d928773aaab6e3b +99490ee722f96aad2743b08dd37bfeb75a8c59efaee4c9b694eaa05eb8a6bb23861a4480544c7617d04d23fd5e2543b4 +8a7050d964d295fff98ae30d77ce730a055719313457e773fcce94c4d71a9b7cf63db67e54a8aab20fb1335b0130b5d5 +903144e6bbee0a4fec17ff80fef0d2103981140c3d41776cfb184ced17f480a687dd093f6b538584327e6142812e3cd5 +a5b30f7c6939bdc24a84ae784add927fec798b5a5ee3dd156c652df020728dd6d43898be364cf5ee181725fbcffc0964 +b43d97ec2bc66af92d921a5c5c20a03ef2be2bc2c9b345f46d8287409fcbfd88ebc49d4509d64468222cd1d2021bf236 +82dc23c7f5086c9ac6b4566359bfb830d203544b0d8332a210775670f899cd9ff48b94bfeba40040c25664ebdd5cfad8 +9294cd017fea581dabb73dcc8c619904d7e022b664b0a8502c9d30f3807668af279948e7e41030ae296d492225297e95 +8d6c9dc636c8e884f9a4299e5cff06d044ebc94ad783a4b71788347ea4a336d4d048b8a9ecabae789e8fcdc459723dfb +801a80bc49e882ec81b04e37407713f033f7bdac79252dfa3dc8c5bd0229fcbd4019890e402cf843b9378df08f72ab84 +b4313ca32569d973900f6196363c0b280ddfa1b47c88d019e5f399b805b444a777950fc21ae198fc23ece52674b94abf +96f06056fd255fdabf78986e315e7c4fdf5495cf850536b7976baa97a994cc6a99c34609c33a0f2facba5e6f1026dce6 +983ed80220a5545ffd70ef5e6ac10217d82ec9cd8f9a27ee77a5ff4074092308c0e6396fc4e9932a77ddd474e61f8b55 +872a059aa630af73c4abbd076e8b333a973ffc5bdecf5dcc0600b00162184213cb19d4f601795030033beb808d5810ce +b040f318d9d3b8833da854014a44296dbd6762dd17cab13f91987256c54353b7f0800547cb645a7cc231997454209fdd +a8c4731a555308e8ce0b8325eb7a4cbf6113d07e9f41932df04480b72628d313b941c7055f1cc2ac45c7353b56e96ca9 +8c24031440b77637e045a52e5ea3f488926ab0b426148975edf066c40a4581beecc1bfb18fc4cf5f9f96dc6681b4bd28 +b39254b475abf342f301298feaa17a4b3051f30ea23a18acf59e003e2704ac96fe40691f1da387913bdf7aee6389f9a8 +a1dbf938b604ccc6d60881cc71f38df568aa02752aa44d123514154017503f6c1c335ae43e359f1487bc8934073cd9c1 +8d52aa1be9f429ece0580498d8fe9fef46d4a11f49436a82b8927f9503dacc41245907f126594c1cd30701286f8c092c +b826f396486942c0326d16f30a01b00a682c30a75553dc6ac34fd5b3e96b13c33b94738f522eebaffb59ff8c571c76e9 +aa89f51cbf6e6c3e2aa2806187b69ab3361c84e89f393f3ed284fe84db46fc3944aa44f8928e3964f9c1a1ec27048f68 +a254df0efa4203fb92b42a1cd81ca955922e14bf408262c8f7cb7dc703da0ca2c71556bd2d05b22ce9a90ad77309833d +93263c507e4d5f4e5df88e85b3d85c46ea729fb542a718b196333e2d9fb8a2e62dc1347cf146466a54ba12d200ef09d9 +922e3c4a84246d89a07aa3e90f02e04b2cea9bebc0e68b742156f702aed31b28c6dfa7ac936ea2fc2e029adf68361f98 +9a00628eeeda4ccbed3ef7834149aec4c77aac1a14bc2491ba5d1a4a2c5d29afb82ceaa5aac1c5ce1e42cdcaf53e30ba +ab3a88df36d703920f6648a295a70ffa5316c96044f39ff132937bfda768937cb6a479e9ba4a4e66b377f3a9996a88c4 +966b11526ab099d550ab33c6a9667e5cfdedf255da17a80a519d09acd78d2ea24ec18bd1ea7d8d63cf0a408f1c1fe0b3 +b5c21b9817dc32f3df9d9988aa3560e1e840d586d01cd596bc0f850ab416b6013cbf7dbfd05ac981f26014c74bd2d2b2 +9040abef5e2523e7f139c9f744a64b98fea3a57952059ffe4d5ed77fa87068203c090ef4e7f52c88fb82ea8a6fdca33e +a0dcdaeb7d3f5d30d49c004c5f478818c470187f4b0b4856812dcd1b3a86de58a99acb8ceb44c6b80c3060cf967c43a4 +b5f4be9a69e4a6719ea91104820df8623b6d1073e8ee4168de10a7e49c8babea772bcbc6b0908185e98d607e49cd3609 +8634020a5a78650015763c06121c606d2dd7b324aa17387910513dd6480fb797df541fc15b70d269b2794ad190595084 +9504d1d0fb31ff1926c89040c04d51fd1f5cddf9d7ca3d036e7fd17e7a0f767ef33cee1d8bf7e17e2bc40949e7630417 +812c72846ef6d692cf11d8f8c3de8fa78cc287303315114492667b19c702cd24d462020f1276895df26e937c38f361f8 +8c97aa5e9ef2aa9a1435ef9ddfe62e850f0360864ed5fb82bf9fef4ef04d8fb4f827dc078bc911ee275e4501edd6617c +ac5f7af5e23c8e429aaa6b6825129922b59d25b4608f07b65f21388a9ac3aa89096712f320afe6d56e44e1f0d51a4eb9 +a8c84d9a8593a0cb5be1e450960f59878a4e6b70da54a7613dfc25911b7cc9e6d789d39401b0a0d6471ab9dcdc707976 +8c9d5fd89611392c0f085ffa4fa642a181f0b9b23593deb5e10fdd1642722ca75ef34a037e88a8d03f2888fe7461f27c +8c74b05f91fb95c85e7bd41f6d9a1e41e667e68f3d19b325c1f25df1767019919edab89b92af237896cbc4e6d6dc1854 +a3caecb91640821f0b2c4981b23f2069df8d2b98ce026c1538bc096b292f5f956a5d52c1c8d6a8165a1608083ba6494b +8ae8e0c36f8b79a69176ff29855df45d0fcd9e4d1dbaed8899f8fcdece676e418ec034a6c161e2a894f0c834aaecbfd1 +b88d18c67dc3b1b6ed60ee437c441c1ed14ecddebccf43683605716f30058b1aa4ba05ff10cd8171ee97d8f58d70c094 +94f43d84dcdfd9cd19115c7d8e9c1e856828eafbfdec93b876cf0007e317e30b2ad951dbabc186aa6ef90fdee4d91990 +b44e4723f41fc1d5b0057f371e3381ae02566590b3f964b6eb07b2104f66ff78410c407235fa98d04f635694f3baca09 +addd8390173d29ca0811534d389253831fed75fed135398617836b6e70767269eacb1560b39a58f02042ca3b97fe59c4 +80bdbdacc0c358c7ea52aeacdc5f9ceb6928bcf6e7dee7c17d8ae3bf7c2372aa7a0372363888968fc0921aaf4776d5d0 +a486e2b6f04f403f9e609d69dfb3cfb992af56ecad1683271df3e3faa3b86638b81e73b39978fb829ee7133d72901f2d +a19472da57457e10c6a6307895393ddaec8f523760d66937fe26a025817319e234eaf69756ffdf1b84c81733424a96d7 +ad6a195397cbc2d75171f5e82090441eed60bd1ba42c39ef565b8b5a8281b04400678625b1dc46d617f694a7652a8e5d +8f98e721c06cec432e2221f2e1b06bb1469d916a8d88d6973acf68d1e003441d00390dafcead8ecdbf9eae4509baf5aa +91d62a0f9d13c59adfe1376ed6d057eae244d13c6b3d99be49a49e0075cf20f4085cf127774644ac93615be9ac9e5db6 +af45dec199245e2b326a0d79c4899ed44b1c0219db42602a4a6184ace0ff831a3276297af28f92e8b008ba412318e33e +8754bde54e8d2d169e6a7d6f0eae6097bc0461c395192bd00dd6f105677ea56ab384c02553ea5eeac0a65adcb0df77ee +b676afd2f5afc37a314c943d496e31b4885efcbcc2061036e370a74cfde5642bb035622d78d693bfc3136fc036c7edb4 +aab6ffe6cc234397cf1822e02912bc282dfb314e92fb5a9e10d0c34ee9b5856d4b76e166bc2bb6fcdd66aabea35ec4ef +ada6e62f90ee6b852ec4b72b22367acac2896f0df2c105beda27096583ddbedddc710d171330569f111c6e44a5b57ae7 +802139dd15241a6de663d9b810121bdd9cf11f7f8c8ca6de63f4f8e731409e40d1fd3558b4f619ed42ee54929dff1c7e +ad8e70531cec21b4e6f55be1751c2d025bd2d7d8158269b054cfe57fa29252d052ce4478ec7db6ec705789e2118d63b3 +a8e4a4271769480e1b33a28c87a150ecc0b48bfe8a15ae04152197881de4ce4b03453aefe574842424edbbe4173e1a3a +b98c65726296610cef16c5b58da5491acd33bd5c5c5af4d934a9840649ef85730fbce8018dee09ded14e278009ed094a +8e213a7861223287b860f040e5caaa563daa0b681e4e09ec79ad00cc459238e70bbeaf7486bbe182fc12650700034ec5 +a2879f9e1a556cf89b9b5b3bd8646a8cce6b60bcbc8095df44637f66a2da5858eee2dc9091475a8f64bb5aff849389cd +8a17cdb4077b9b0bcf28b93294ac5ae4c8bba8839fce0f1012b53187ac008f9858b02925fbfc421f1123afcdbd8b7753 +86fd9c11528aa43946e4415ff64a3ca6409ee6f807368c68997b18605da65e415ccd85ad913820d450cb386593de666d +8ed55923b963c3d85a91aca11c40ff9c6c7f1e2b9bc199d1a270e5fb16aa62dec0136e97866145ae9d58a493e8b1cbbb +ae32af5b5d418668ae123c639b149e5eed602404e8516da4a61db944b537a3620545e8e3d38cf10cdaea980ab2f80973 +95cb8d9e9d6762d78dde0ad73869ffaca904a7d763a378b8cc11a7933d3e7d1c8aec4271a079b1b00f8887ee5b1ea21f +b5ea20b42a3ca247f00ab5328c05f0cf194973d5f7271c66c41c5055b1ffdca136be179709e0c1de209fbe07b9820bf3 +98682f7cce471c92a8d6d15fee4ddf4d43dd97c3e3811d2913618ecacc6440b737717c07736ae4558c910e11ee98104e +a67da2c7cbba48e929ca4e4b9a6299fe01ef79eff8cc5cd3fdbdc0721a68130e4079f30ae151a573a7dcca8ecf2e684e +a9981c9f9dcbb3b0f6996f664fb2acd7573189f203be37b2b714662aa273551396abfb1f612ccde4e4c8127a050dbe4b +92d55eff8da600f886da9bf68e8eecf482faa4b268f3f286b3b3e5cc91b19604081498d4905b201bb4ec68e32b5591d9 +963e3f1728de9d719c86d390f3eb9c3f99d1928347fab0abf10dbb37d76b59ddb64d4734c977863a6cd03ffece5ca895 +93480e2de83c921056b6d8628ac37cd5ef7555ba43b0308fc13386cb0515d42c12ecd06057137aa71a7931beaf90b9ce +8feae57ff0e6a162cc81c99f45c6187d268fc0bee8c2bffc92142ef76c253d201f0e932943cf2fa312982b281ce1066b +8f8f4bd4200fb87afcd743274480220d77571928000d4197410dbb75439d368df6a06d941a6152206371d2ca9cac99e4 +8ee7f11e79af4478e0a70eb424fe8078237ad99ba6d7e6bf1a8d5e44e40abd22d404bd39b718ad6fdf4c6601f2a47665 +a98acfcec612b574943195b9ba95bebcc9c0b945c9f6b3e8760b2a4635909246a9d73b0b095c27b4ecb3339704e389b7 +b520efd19f65e81dc285031ea3593f8c5dad793e4426beb9196ab46e45346f265fd71e50adb0da657977c60ed5724128 +a3d9d0b7415280ce4dfa2429d47b2b8e37604a5157280a72cc81d541ffe44612dbb3ef7d03693fc42a569169d5842dc3 +8c29e2d0b33801f6d9a9c065a76c5cad1fb0a001506b970307e21765ee97c732a4cbf1d7c1b72d95e0ad340b3b075224 +839e21f292892a6eb596b9b1e9c4bd7c22a6fe71d3d04487c77840028d48392c5cbe73140a4e742338e0c8475cd0c1ad +8bea5c68e7743998619185bb662e958f1b4d3ca81019d84ac43c88911aab3abe4ee9bcc73cb95aa3ae87c0138801bde3 +b8f262d21a94604049e008ce03dc857848168e1efca4522acb0ccc827ffb37f545e1947843a356563a76bc6489605b66 +a7bd0842b0bb38d9943b82aa883f36f4eb8a6e8a7790d4f87faf306608f51d250a19b73984f1156cef5dd2581664614b +a993e649bd953627a88a2539dac3a12ec7f37a4c65b01425d9d34edf7ee10a71aa98f65c9e013107f824faf8aee041a9 +8e07eced75c67cb4d2ec01857f6ac1408482e6b31cb2faa249e8cf99f180575587df530c7782a7539b5221121ef48aa0 +b2f4578f26c05ecb9e2669ca744eb19d4f737321ac7d04fafd18beb7866e0fec9dd063953ae1f077b44b9c6f54db1279 +b6b3788a6c7bcaf467d19daf6ab884d549aa866970c05a9181f544ff190d043192c84fe437a75a30b78b425461cca062 +a270684903c61544b85a7041e81f65e787e1c1e23e57538fa8a69836bed0ca1673861dd29f743a1280f2f38eddd3aa83 +a9c2397c4773dcad2821266dadfd2401d013d9f35de6744f2ec201f3507700adb1e6ec4f5a453be4764da8bf68543f26 +83a3025ed6fd5df9d98be32a74e10a0d9728b560942d33ba028536fb148fc34ae87e92be2df3e420a8dfec08da495982 +90dc70c183a90bab988b4a85b7b921c8070af0e5f220364fe11afa0722990b2c971e1e98eef62d3287fedfd9411f1df7 +82d940937a6c636224d04f8e2536f93dcf20dc97a5f188875ad76c21b804aef9af10839419b61143c1f88a695959a6b4 +8017f9473ce49d498d6f168137e77e62fe553e5a51e75b519cf2cbd1ab9afdafad80fd5e6fd0860e640b0d78ca8ed947 +80573a0ec049fe1f7b3013b2839e145cd87e07c0e43826a29ef8c92516f9a30896c2ffcf3ed77ed22a6cf3101b1789d5 +953349abd2559f9824db07cec857ad54f1a05018f3076425f8dbae37f8d92a46af2c04ab7c8ec0250449541187696e98 +ab7bd2c4f05ee9a9f252c4e16a20993a12c535c3809d124bae24642616521a9768d3f19eceaf8524583f47ae1f527684 +9883b77ee834ee0112ca2f366d2a6fc213e0cf454e061438c2901a5ba35b7378f64da8adf6a476eb1562991ef5b4a5bc +89291811db308637356dbf7ed22cf07bfce33eb977734ee346e8c15a231b35d8b4443574f3fa97a40867b3e23b0bbfa4 +93d753849d7d9588d39e38217500b123a6b628a873876612d9f98b5d611f52c89c573432d2176752b5d1cc2d94899b8b +a45add3c4844db3b7a237295fc85fddc788ac1ec395a0524d2fc90a539571a247146aea4aa10eec30a95e9617c85b98d +90f94578842db7a4de672da1e483858ece5e466c73c12f725a0fc71f42ff880c9447a33fa9096839bee817536f2591e2 +b2c1b6fb031bb30460f157356562b44b4de096a0a112eab4fb3cc500aad38bc770da1fc2e73caf687a0da5e8537049c0 +afb15e15fd930929c0e3c66482068a5afe0c7b7f82e216a76c5eb1113625bfa0b045a52259d472284cfbaf4796c71456 +ad222a9a3d907713418c151b8793d5e37634354322068f8206b9d0da1a3f53b0004193713d23ec35990639a1b6c2e075 +b44a128dce97e8c4b178cdbca0a5c1b3f6e164490fac0fd68dbfe0aafa89920bb4ea420a8527e06c80dd19c2f135e3ef +8596e993ef18b8d94e9c42a90cb7060affc586b8e9b526820d25124285de5590134e2e86592e9dc4dd45ccf5d578fa60 +b71bb0ad138141ed506b2253e84110d2db97cc2d24a3fd0d096b0022d9f38f87aa74e2f505074632d64e90bcc491aa30 +84841eafd357309de47b92ca5ec163dec094a2e5271bc65898c31932e0160bee165e4decb23af339cfe09c83e1cc5441 +8a2915ee39a6fd4a240b98533d7690ef1773ce578ed1fb05ed414ebe36f7ef289fa46f41768df57190438c356331e329 +90bb337165386f1990cbd8ed2e8321ef21bc18125b015b4da0c37e5fcc446b26005379ee4fad8ce9348ceb4ab49e82e2 +b707b50ea2ab05c6d183671587f25fe29eef23fe569d731459a1ac111a0b83a2cd65b88242876b34aeead3b05a15d745 +ae1f159f79b7996315c4f9acce7e21a6ed59d4ef76331196fc86911fda3035edd5c11d568b105175a36c948d0263b382 +922bc525bace05e5dff6b5cabde5469ddd2c1c601f7131abc04ecefdd35095e6ac015b1aec3c3b25c5dee8d139baf60d +a7b060405b2740f82db64683187b1bb89e5f40c8438663c7cbc8ef2513929fe5f92625667a7f2f599a72a96b1fc8f08a +b9dfe94a08651db5efefbb813269bce80d814e3089b80c0654491e438d820bf521f8a4a4477909344ba88f7683eebb43 +841817a9729465743576950b6e8eea32ebf39cca99ace86c4792f9f35926e2d6830c52854a3b2eaeb61694e6845008bd +934128034bde8fc7b93b952aa56e0ed28b36cfa04cfa1f0d5b38266dd40beedff5e0bab86e4717b0fb56c56be2eae26b +aee9d64caf28596308782cd8f3cf819506daf3378f86157ff775e618596411adf94efd0e9542787ca942066f02cbd332 +85871184db314411a49575fee088c52ed5dba4e916ee001ec24d90898a0154d9790a06aa8a707ca7a8b986c0293b8d89 +8d3d87edcc0187a099c97b581a598d357a41ac152303bb27c849eb78e72e15cb97cf9a0468fc36f245c3e152c76bb7dd +900475d165dec18b99eb7b5f9e9ad1d2d4f632e55fdcc4c5ecd7775fed462990e6aaafe9c669f40508f9b15f00bda31f +a25b5954edd57e7811a0d18532043d975c7b44b80f65cd630935d7b16ada05f30fe2b7be7ae8a2f54c25957faf3f1950 +a089019afa3a7a15f7e7874e73b6773c0a824e6d3379b4c928e173321fb165ad979a6be004d394c28d19d410b2655d3e +b28f46797dee0c538bd3de815df641a0ef718ad3e52b2764aec380d6905b38b50ad6f60d0f68e096ca39960ba7734355 +b0ac155d3d05851b04104e6b459f1a68e9e155437c92421a7c0e4dd511ef89cf71dfa3cc920769492ee283a65ebf029e +813c69a810745580d43d5b5480f0ba81000fbef0071e6b655c7346bef5ed774e9214a7816d40eb1774a5bd033767a046 +b176345ca75c64f10ec33daa0dcf1f282b66a862fcd3d8d66c913f9a02db4c9d283dadc02eff13aaab94bc932a42234e +92560f67e5b995db4a489bb86ee78b4aee0800143b3535ad557a53e9e08716bd0202d9f5714722c2a5e8310046e3f5b3 +8adb427bad9cc15fc6c457a96a6750dda8c46d859c5f69bf0e7ab8fc0964430b33967fd47cf0675b6ba1757f91255e6e +b120f723b80389a025b2daa891b140b3d7b8d520ae2a6a313f6e3d365a217af73292dcb249dca1f414ec05e865e3cdc7 +a61a5d261a8dfe5996c42ea0a5ae703a2adcfda80e86837074d868eee16f87d38da19596c48b55dbd7a7cbec1a9b4996 +99dc921eacc6bb867c5825ad4c83bc4af9dd78a18b3d0e1a60ad493e3805b8fb9b7922b577da1adb3d805edfc128d51d +85455fa165a07282aaab4a5bfb88027f47b9532e4af8195c048515f88b0db7e80f42e7a385fd4944faaa7f2a6544ad17 +96dff2d1c8a879d443fe576d46bcceaf5f4551d2e8aad9c1a30883637c91090de99ad5eec228eb5febf93911502d3cbb +a87eb7f439377fb26c6bfe779701f4aea78dd7980b452a386afec62905e75217a1996c5234853432a62ef8bab21c31c3 +b598278293823e9ccb638232a799211173b906444376337fdf044d0227d28fcc4c5867e6ecb3200e59ca0b139e71cac9 +aa6fe147edc95027654d68140f428ec53cede3552c5f49c09d18bc6f6ae8c739a63042eb7291d14d717a4e1f0778abcb +ae8ee18913d328b2fba71efe65526d3ee9c81beda53cf776baec4019ea30212010758cbb5dc85ed6620ce04b189f01f2 +ae9fb686777e88dffdd42805fe4114aa0da1b350d92a27ff3f8a817fb25af1fcfc9a06155affe0273bf13caad16a5351 +95d372ba3a2ee38371538f34aae91b4844488e273f70c02f1992370f89fc2343eff95692d52ce9f21206abbee4959958 +b15260376f0a34ca2827ff53acd7eaaef94c9acc2f244b36500423069cb1cdaa57ac8dd74adb5b53d0fd4265fcbb28ea +b0ffce6a8059537ef6affdbbc300547ef86e00109289239b0c6930456c562b4ed97f2e523963af17736dd71b46c44ac7 +b5499a1277d34f9892f7579731ff53f423f2ffffa9ea43a6e929df8c525e301396249a2324818a6a03daa0e71fcd47b3 +98dbfb8e97a377a25605a7665d4d53e66146204d8953afda661ae506858c5cd77ff7f21f5f10232e06dbc37378638948 +84177e27e6da0e900c51f17077f5991e0e61bff00ca62c1623e627c5aea1b743f86eef6d55b13219a1947515150bade6 +b50407bb5c61b057ab8935df94fd43ca04870015705b4f30ceac85c1035db0eb8293babc3d40e513b6fb6792ecbc27a9 +988699a16917514e37f41ab5c24f4835ed8a2ca85d99972646fcc47c7e2a83c2816011144a8968a119657c4cda78d517 +920c43fdcb738239ad542cb6504ab34498bce892311c781971d7db4dec70e288676de4d8697024b108cfa8757fa74035 +aaa106329aac882e8d46b523f126a86d3cee2d888035ce65c0be4eaae3e92fd862f6ac2da458a835539cccafaba9e626 +96e4c1562d14b7556f3d3e8a1b34ea4addc5a8170e1df541dc344728bcb74cd1630eb7ba4c70e9c68fd23c5c5d5a729b +a616ac5016d4e68e03074273cd3df9693ee0ce3458e8758b117a5c1bc6306dd2c7fad96b1bb37219c57ac62c78ad7a3e +8db7d9b20abfb1445babd484ae9e38ff9153ac8492230d7591e14e3fca7388a5ca6ef7d92ed445c8943cf5263e4a6ad7 +88464134221aa7134878eb10928f31c8bd752ab68c27c9061c1de3f145c85731a4b76acdc7e939b399b6e497f9e6c136 +a5f7c794f70b7c191c835dded21d442b6514bab5e4d19b56f630b6a2f1a84a1d69102d7a0dcca256aab5882d3f30f3ca +b96b6f98b6817b5fa6b1b1044e2411bdf08bf3ffaa9f38915d59e1d2b9bed8b3d645eee322ee611102ce308be19dbc15 +92c26ade2e57257f498ac4ff0672d60b7ea26dad3eb39ed9a265162ccd205c36b882dba3689758c675f29e20836b62d9 +8379a0299e75774930577071d258e89e471951642b98e5e664c148af584d80df4caa4bd370174dae258848c306f44be5 +a0e53beda02bd82bf3d24bd1b65b656238128e734b6c7a65e3e45d3658d934f909c86ca4c3f2d19e0ac3c7aae58b342e +8ca5ceaeaf139188afd48f9bf034d8baf77bbf9669791c7e56ebf783394d7fcdf2a25fa4bdfcddfde649aa0dc67ccccd +a8060e6448844e9db4e9fb4da1c04bcf88fda4542def5d223f62c161490cf1408a85b7c484341929c0f9ce2a1d63e84b +af6e1a5ecf50b754bb9eb2723096c9e9a8e82c29e9dcaa8856ab70074430534c5395534e1c0ed9ce98f4b84d4082fa67 +81c8dbbef98f1b561e531683d5ae0f9b27b7f45dc6b2f6d61119ca0d559bf4ceb676d320afc5aba1811eeef7547a59d8 +85b46cd64d605c7090a2faf1a2aadf22403b3692b3de1d83e38b2de0108d90ac56be35b0dca92c7a41c4b179a3567268 +8dd3cc3062ddbe17fd962c2452c2968c73739608f007ad81fa1788931c0e0dda65032f344a12249d743852eb1a6d52a9 +8630f1707aea9c90937b915f1f3d9d7ba6bda6d7fdef7a40877a40c1ee52471fd888f84c2b2c30b125451b2834f90d3b +b4a747e0bd4e1e0357861184dacec6714b2b7e4ee52fa227724369334cf54861d2f61724a4666dae249aa967d8e3972f +a72de682e6f9490b808d58f34a0d67f25db393c6941f9342a375de9ca560e4c5825c83797d7df6ed812b71a25e582fff +8d5ea7d5c01f1f41fffe282a334262cc4c31b5dcf31f42cc31d6c8e37c9bd2f1620a45519dab71e108fe21211c275b6c +8ccdc7e3642c2894acbf9367f3e99c85963cea46dc5473d175339a2391be57dd8815feacadec766e13645971213b9eb8 +858e9b5fc8c13b651ff8eb92324bdda281db4cf39f7e7bd0472908b3e50b761fa06687f3d46f4047643029dc3e0ceeaa +ae20d36c70cd754128c07cbc18dcb8d58b17d7e83416e84964b71ccff9701f63d93b2b44ec3fddc13bbe42ebdd66221e +860dbf7013da7709e24b491de198cb2fa2ffd49a392a7714ad2ab69a656ca23f6eafa90d6fdc2aa04a70f2c056af2703 +8f809e5119429840cb464ed0a1428762ba5e177a16c92581679d7a63f59e510fdc651c6cc84d11e3f663834fcafeafdd +8d8a8dce82c3c8ea7d1cb771865c618d1e3da2348e5d216c4cbbd0ac541107e19b8f8c826220ca631d6f0a329215a8d6 +86e3115c895ae965b819e9161511540445e887815502562930cedc040b162ecb1e8bdc1b6705f74d52bf3e927bc6b057 +b9833b81a14115865ca48c9c6a3855f985228e04cbc285f59bf163dca5e966d69579ea4dba530b1e53f20bd4dccdc919 +a71f5801838a6dbb162aa6f0be7beea56fadac1a4bcd8113a0a74ab14fc470a03775908c76822d64eb52a79b35530c05 +a77ab73ae94b6d3378884f57eee400eff4a2969aa26e76281f577a61257347de704794761ea1465dd22a6cc6304fbc4a +acd1c5df3c487c04cf27f002e81f2348a0119349b3691012526a7b0d3bf911cdd3accbc9883112ed2ba852145e57fe68 +8a28515a48832ac9eaf8a3fb3ad0829c46c944b4cb28acbcdbca1d0d4c3c623a36cda53a29291b8f2e0ea8ee056b1dee +846bafca11a7f45b674237359b2966b7bf5161916a18cf69f3ec42c855792d967d3bf3f3799b72d008766206bb7a1aa3 +b24b341675b1db9a72c3405bbe4a95ccdfd18fa96f876ec946ccb5108f73e8816019998218a036b005ef9a458e75aeb3 +b99c267b4a09193f3448bc8c323e91ef5b97e23aeff227033fe5f00e19bab5583f6e5fcb472ec84f12b13a54d5c0e286 +a088aa478dbe45973b04ecafbcbd7ee85c9a77f594046545cdb83697a0c2b01b22b1af0b97dd75d387bb889e17f17aa7 +a0c6b0cdff2d69964134a014e36c3709d9e63f6463c5cd7b01b6f0be673731b202d577539d89dd57a888326da1df95af +b4e6dc4ef11b2b41794ece70a8968e56705199d183366759568b6fa845d2cae127486e926b5b27ae9118bb21d1682c1d +a007804353f174098f02540a57e96227232444d5ae0a24232c244647148b6c049848cbd2b50d0a25af3ca9164bfff8ee +873fb034cc39c9cee553ece908fbf315f62efbc412b9afdde6a1889326b7f6f813e050b0601ba9921688e958cb75942e +b5676c90f0106c40d8683299e59d564f505ec990230cb076caef3ae33f2021e6aa5c9b27bb8fead05fc076df034c28f5 +b5a67fc4c5539ad1ddf946a063110f824f7f08d2e4d30762c9d437748c96c9147a88efc22260573803ab545c18b108f2 +817ff2b748a949973a91b69b0ec38efbd945aeb26a176d19f0fb76e261c7526c759e6f5516f9ed34de6eb1ac7838c9cb +99b76bda3526a5d841e059010fdb14eb2fa035a7d10463373a062a98c3c1a123e2da0848421dd7546d776438fd05e304 +aa0d363270f90d56bbee7ea577b0c358532bda36d9247af6c57d000044a97ba41e35bb0db438f4c94551c6350e4e0674 +acdae205d05f54b9544be96c9032350511895ccf413dbbc56d1f03053185df22a6d5b7ffcc3fbe96c3e2ce898ccfa73e +b091c220a1de18d384f50dd071dca4648ca4e708162c52a60e2cedc0188e77c54639f75bce9a468a64b2549119c07ded +878676133e5c700b1d4844564fa92a9930badb5293d882aa25ee6721a9f2cfab02088c31d62cf1342ae3edaea99a1ea0 +9756d0793e6aba3b4dff48100bb49a5ec08ec733f966cb438379b91caf52fc2a5930830ec3f49aa15a02c82c1914dc7a +9722f760184d3b2d67cb2cea7fa41b1ff920a63446006bd98c6347c03d224d2d8328fa20ccd057690093d284b9a80360 +b5a68489de4f253715a67f0879437bfe8f4dfc4e655ca344848980e6153b1d728acde028bb66fd626fa72eedd46ff683 +a8cfc900b34835d9fd3add08044636f69614eff9ae929eac616c39bd760fd275ee89bf24b0f275dd77a66e54fd6b94e5 +89967479bebf70b2893cad993bf7236a9efe4042d4408022fdbb47788fabedcec27d3bba99db778fcde41e43887e45af +889235938fcec60275c2cf0f19d73a44d03877d817b60bb26f4cbce09db0afae86d42d6847b21f07b650af9b9381fa82 +b7fc321fa94557d8fbdd9fff55ab5c8788764614c1300d5ef1024290b2dbb9216bce15cb125da541f47b411a2e7e3c2d +b11b0c4dc9477176b3cda6b17858dbd8c35a933ed31364801093f310af082cb5a61700f36851e94835c5d4625bf89e32 +9874e54d2939ee0600f4194f183877c30da26d7515e9e268fea8d24a675dd2945d1565d9016b62b1baab875ac892f4d2 +90df3a77280d6f1fa25a986309bba9d5b89c3cf13656c933069bc78e6c314058716b62eacfa7ab4aff43518b8b815698 +962b08299a287d77f28d3609f39fd31bc0069f7d478de17539e61fcc517045050644b0307c917208b300ce5d32affcca +b30eedca41afb6f083442aaa00f2e4d5dc0fda58e66aaf0f44e93d4af5c4bf8ea22afec888cacbf3fae26d88e8d344cc +847747a22fab3fe3c8cd67f3f1d54440f0b34ce7b513225dc8eb4fa789d7d9f3577631c0890a3d251e782a78418fecfa +8d1ef3cb5836e4039b34ee4e1b4820128eb1e8540e350309e4b8fea80f3ae803d1f25f4b9c115482b324adf7c8178bc7 +8f8a2b0b0f24f09920b58c76f7d99ec2eb2e780b5a66f2f30a9ed267dcaea0ec63b472282076c7bf8548211376c72f6e +831ee6dc8889bbf4d345eaeb2f425959c112d2190764abbbe33bc44e1d9698af87ff5a54d01fac00cfee5878dee7c0f6 +a7eb2479ac80d0ee23f2648fd46c5e819ad3a1f4752b613607ae712961b300e37f98704880ac0a75f700f87d67853c7a +aa4d1b9cec62db549833000d51e83b930db21af1d37c250fdc15d97bc98de7a5af60dbf7268c8ec9c194d5d5ccda3c1d +87396fd7e78c4bcf270369c23bc533b7fb363ca50d67262937dab40c7f15bd8448a8ba42e93cf35fb8b22af76740d5e1 +a958b2a9ffccbca13c0c408f41afcfc14d3c7a4d30ea496ce786927399baaf3514ff70970ef4b2a72740105b8a304509 +a5963a9dd3fe5507e3453b3b8ed4b593a4d2ced75293aee21bfed7280283348d9e08bf8244c1fce459aa2470211d41ea +8b06ddc3359827558b2bb57caf78b3e5a319504f8047735fcc8ec0becf099c0104a60d4d86773e7b841eb5b6b3c0cc03 +9437e7278283f6d4d1a53d976c3c2c85c5fe9b5aec7e29d54a5423e425b4be15400ed314f72e22e7c44ee4bacf0e681c +b56067ee26a485ed532c16ec622bb09135a36c29b0451949aa36fee0b0954d4bf012e30d7e3fc56e9f153616b19349bc +a5c72f7f5d9f5b35e789830a064a59c10175093a0ce17654da7048827d0b9709b443a947346b0e5d96b5ea89b8d7c575 +a8318d01182d4c9af2847a29a6b947feef5795fc12e487a30001cc1ec482b48450c77af4837edfa1aedf69f0642c7e5e +82ea421c091552d3dafa7da161420cb5601b819e861dd2ba1a788c3d1b5e8fa75cc3f2b0db125dde8742eb45b335efa2 +8679fd1c7771ea3b12006d4a972f4f2892e61f108107d4586f58ee7f2533d95d89b9695d369cdace665f19c6bc3bc85e +b5ab3e8adee4c950fce4d33a0e2f85d3d886e60a6e2f4454b57bc68725f0cf246372d863167482cce1ea10a7c67c3af2 +a85696927075ec188979180326c689016a0dc7a2f14ae02ea27c39ef91418cd44177d3fca5752cf6b298fd75fa012e26 +a44f87b7232f102cd092f86c952a88afb635484a984da90a41a57a3d883c9469064bf105b9026024090486b6c6baa939 +866ac91a437db945bbfdc11fcee583f3669fa0a78a7cecf50fbfa6ed1026d63ad6125deba8291452bf0c04f2a50e5981 +b780d5a1e278fd4eef6139982e093ceafea16cb71d930768dea07c9689369ff589d0c7f47d5821d75fe93b28c5f41575 +b025d0046e643506e66642c2c6a5397a8117bbfe086cee4175ff8b7120e4f1e6794e1e3f6ec11390993cca26d207ae43 +a04a22b6e28c959ab265c7f48cde42bb6a00832c6beb2595b5df2879080a9424890960417d7d7ceb013d697d0ebf7267 +81de9c656ac27f54d60d0252e33aff4e9e9e9c3363a50740baf15a2b9061f730a51ae1704e8c4a626153cf66d47f19b1 +a15fab90599df889df11fa60c752948b68fba54005491180dafb66c5775547976d0eef33945e55d4818653e0818c6f92 +b06f9be44ddb103a72fa4ebc242c8ee1975fe9bf9ef7124afeda9967ff3db644dbf31440151b824869406851a90984a2 +99abdfe6806ae5efa2d11577da17bd874d847c5f810460148bc045bcf38c4fd564917eacb6ed61bb9164ed58055cd684 +ac53231077f83f0ae5f25e52b70bb6105d561c0ba178040c11c3df8450c508ed5df34f067fdaacf716f90b4926f36df5 +99e3f509af44fc8d4ebc693d3682db45fd282971659f142c1b9c61592573a008fc00502c6af296c59c2e3e43ed31ec7a +98f2f5819670aff9a344e1c401f9faf5db83f5c0953d3244cfa760762560e1c3a3c7692bb7107ea6eaf5247ac6fd7cc8 +b5b9f90391cec935db8d2b142571650fcbb6f6eb65b89c9329e84b10bfa1c656026674d70280ade4ba87eeaf9333714d +b0696b77ca8a0cdbe86cad12f358880926906fb50e14f55b1afc1e08478ae6376215cbb79bc9035de2808c7cd2b13b85 +a51d746833062a65fd458a48a390631d5d59e98e2230b80d8f852cfc57d77f05eefcfd3c395ade1e86d4a39c2141365c +812d67654319f4ef3c9e4a2d4f027a4cb7768f1ea3f5fdde8d1b79187a4b874ff9a5c70f15b7efa079c2dc69d1b9b1fe +968978b653c6416bf810f6c2ffa3d1abbefbd06f66b6686e9a4fdce3f869e0ab1e43cce14dc83786596761c100ae17e1 +98e1e6ab562ca7743783b802faeb0a24f1341abfb9655f106920aef08964a3c0e8083e1acda7ae28fed7cdd5478decb6 +a91c0b982a0a7085a103600edf99e9d0bee4c4e7db6d9f8f376c215c7d42476218462a3765f2928e12c3dd49d688e4fd +8a43395b3124fab9e2438635bf88952e8e3084dad7ecb3a9927f9af0e0887bce4707084043671fc98ad03621e40a149e +b0b37626143d4a8c6f5693d5f1fe871525b4dd946c4239cde032b91f60a4d7a930d7ba28959737550d71c4a870a3a3be +b01c74acae1715c19df08d5f4a10e0c19d1356264eb17938d97127bf57e09ced05ba30d0fc1a9f32d6cff8b0d5f91c9a +b4c2328eb8a5a673406faed8f0aebb8540d2791646e37ce46e0e382506570ca276eb6f8e166dbbf9e0a84064873473b9 +85cb9f769a185e3538e4a4beda9a008694e1bf8dfeea9dc07c5c40a9ceb1d31fcb13cacfaa52849ba1894b5027cb8c30 +8742f91cddc9a115ddc73982f980f750d82d3760f2d46ee4490d5b17c6c3bb57c7d4c7b8d6311b7b41e59464c009b6a5 +948ef86d17128a061e1bdd3ea7fcc7348e3ec87ec35dc20a58dd757d5d18037fe5e052bb359e27ab4c2320d9a52a6a0b +a70f6a214097c271e0d2d95e30fce72d38c30a2f186271fdff0e38e005aff5baed53739b8c4f9501aa7f529c5cb2da59 +892a7574cf6704ad75b346c95ae6f2668904f1218c35b89b07a0c2dbf3c62173c348f6fd9473926eef56a37c0f635c04 +837e85a41f39b4ded1420aa8fc3be46a7adb99305e0928c6d7643b7c44434b72984cea08eb68f5f803661df0db78c87d +94e495329f2aab3eeb68f347961d1006e69d990095877a4dcc376546233adf29a14bf6b16a0c39aa477e15368e87014c +851860a8fdf76a97048396553262637dade27f1f63f926997e74c7c72b14b10293eae7824e8dedffad1aead57c124f79 +90481017a250972055ab1cf45ff17d2469517f10f18c9d4ef79a9bdc97a49093289bbacfefa8a1e491bbb75388b34ac0 +983db15f7463df28091c691608ca9c51095530fa6b1b7b5b099c612e673d29e16787cc9ae1c64370ba6560582ce623c0 +a477dab41014c778a1b78a7ce5936b7b842124509424e3bfc02cc58878c841c45f9e04ccc58b4f2ff8231488fff0b627 +868ebba1c85d1f2a3bf34c0ab18721ea725378b24f6b6785637ee4019e65d4850e051c8408fe94a995cc918c7b193089 +93cbf4238a37ccd4c8654f01a96af809a7d5b81b9e1eab04be2f861d9d2470996fb67367e5bf9dcd602dc11a3e4cf185 +83113f4e696030cca9fdc2efc96ba179cf26887c677f76cde13820940ad6891cb106bb5b436d6b0f8867f2fd03933f7d +90c709f4e3359a6d215d03f45ad5cf8067aedd4aab03512dd62229696485a41dcd64e2acce327fda390e0352152fce13 +9945cfced107a36f3cf028ba04c653360afc5013858b9a12fac48802efcbc198c9baf3a7f9b23dfdd5036e88bc7274c8 +832ae60192b47fc735a8ddeaf68314b16256c90ab68099f58e43073e249c6939895c544a02fa34e40805bc6b5db33461 +8b12c335818b643c1d22cbc2869606cf64e7ae54a7713617fc4dd3b2f052ebd6b920ca59ba2e9c7aa8cf71bb4f40f9e8 +a2033eb7a373931c65d66989644aa0892ac3778b9a811b2f413d8bf534e282c339717979f9aa742162abb3468c195f87 +aba2b4c37dea36bed6d39323e5f628ab607699c66767f9bf24ef5df1bfcad00c2664123c0d8d5bd782f1e14a06f4c769 +b71963777535b4d407286d08f6f55da8f50418486392a0018ee10f9ae007a377b8b8336f33386b0eb01c45695c3ed2da +88dc87826941340913b564a4f9b74985a311371c8e7b47881235d81c081f1682bef313c2f86561a038757fb7d6a1a8dc +869e13e3fcf91396750150f9dc9307460494c1d365f57893fd06fb8acf87ac7dddc24e4320d9cad0414119013ea739b8 +92194e292303d32b91ae9cecb8d6367c8799c2d928b2e2846dab1b901371a4e522fc4089aad8f4ee676f0614ff8b19d7 +aa589a3e512cb4f8589bc61e826a06d9f9cb9fdfd57cf5c8a5a63841435b0548e30a424ca3d9ef52bf82cc83c6cb1134 +81802e0194bc351b9a5e7a0a47911d3a0a331b280cf1936c6cf86b839d3a4ab64e800a3fe80ea6c72c3751356005a38b +88e5e9e3c802314ddd21cb86f2014948b7618502a70321c1caf72401654e361aac6990a674239afa1f46698545614c93 +abac1e0f85d5c3ff6d54ed94930c81716d0ac92be49e3d393bed858833f4796c2b80bf7c943e7110de7b2d148463bfbf +b7eb416004febd574aef281745464f93ef835fd65b77d460b6ad5d5a85a24b536b4dec800cfe80ae98489e54447e8bb6 +b3fd8ed1c30e7c15b0bc0baf0d9d1ecad266bafb281cd4e37c55edc76c202fb1e4ea315a91a2848f40f481793ae35058 +86ef674ddf4b7d303c68bbfb53db00b925ccbf11d7d775ca09e458f4ecd868ca828103e8e7cd9d99672a193e81b83923 +95ef414e9f7e93f0aaaeb63cd84eb37fc059eb8b6eced2f01b24835b043b1afb3458069c45218da790c44de7246860c9 +93ec8f84c20b7752bfc84bb88c11d5f76456136377272b9ac95d46c34fce6dcfc54c0e4f45186dd8df6e2f924f7726ab +95df5f3f677c03a238a76582d7cb22ed998b9f89aecf701475467616335c18e435283764fb733fb7099810fec35932ae +8cda640695c6bc1497d19b9edc5ff4ea94c1c135d86f573d744358758f6066c1458901f9367190dcd24432ae41684cf0 +b19aedf5569435ff62019d71baa5e0a970c6d95fe4758081604f16b8e6120e6b557209cdea0ccd2efec6ff9e902d6ce6 +b3041f21f07d52e6bd723068df610aa894dfdde88094897593e50c5694c23025e412ef87a9d16cadd1adbb1c6e89ced4 +a7f8d6ab0a7beb4f8d1cfef6960ebdaa364239eca949b535607dee5caeff8e5dfc2a9cfb880cc4466780c696cff2c3a6 +99a565b4796e2b990bfcb234772d93c5ffdbe10453b5aa94662272009a606ba6ea30cc0c3c26aa22982c1e90738418a5 +90c54b55ff19157c1e679d8d4f7f0687a70a27d88f123179a973c62565adfcc9347cfe31f54539038cf2f34556c86870 +8612f34bcd018d742202d77d7ce26cf9bc4e0d78e50ddf75250b9944583b2c6648f992b635ea13fdaae119764e7c28d5 +a04fb38e5529bf9c76ec2b5e3a1ef3c6f9effb6246c7f67301cfed707356ba1bf774f2867c77a5805933f0c8ad0ec644 +b4800e7b503da0164885d253135c3b989690794d145182572181995e6fa1989f3d0324993e871bbd5f48fadd869d8a18 +9981cd4f28ae7b7dadf454fb3aec29746dc2e0ca3bd371b2a57cd2135a7d93559e02132528ccd2d305b639d7ac51613d +a3ceec012dd1fbad3ef9f9f1d6fe7618e13d4d59e3f50540d2a57010d651092979c75442ec8b38a1ab678505e30b710d +8b97b8654d067fb4319a6e4ee439fb8de0f22fd9db5569ba0935a02235cb4edd40a4740836c303ec2394c59a0b96308b +b3d1bf4410fec669a269622c3ce63282c9ac864620d7b46c9dfcec52d8e79b90c4c90a69c32763136a7f2d148493524e +93174eba1e03f879e44921084aa0ee3562e48c2be49085de96ed7621c768ff52324d14c8cc81f17d7ed50c38ffb2c964 +aa2194cd0fb7aec3dac9a1bd8ea08be785926ed6812538be6d3c54218ea4b563646af1f5c5f95cb914f37edfae55137d +93f2c0dd59364f6061d3da189e04d6c64389a3563b062e8f969a982cd68cc55b4f38b21546c8a67c8df466ff4f61f9c5 +aa7dd497cc949c10209c7010ba4ce8a1efd3cd806a849971e3e01716ea06a62e9d5e122ad1d2b8e5a535fae0a01a7761 +ad402424b2a32bca775a66aa087580d7a81f0867f293f1c35580b9e87ccc5a2bab00c29a50fd0d7bd711085ae2248965 +96237843d8e29ac77fc6ebf4acc12946ad11697de8e5f152fe5776f2475b790226a7d156ac48968dd68b89512dc55943 +a45c25cdbb9fc327cc49a1666988af9ab4c5f79cea751437d576793a01c3eeea4c962c05c0947852fe0e4c63e1c84771 +93dcf834a614a6f5484cc4ba059e733ab5dcc54253229df65ff5ad57b447353ebbc930736a4c96322e264e65736948dc +b9a94f82a82c0c5a26f2c1d5381afec3645e8ee04c947dc3b7ad59a73018db1e9965ab3642f2bbf60f32c430b074fb22 +94eab29b3524ccbe0c4b928e5fa5dd8f684074b332fcf301c634d11083653ffee4f7e92ddbcb87ed038024954ad1747b +b8dca5f679931d6abef0674bad0639aefad64c2b80572d646aaab17adf5ca1ab2ebeecd5a526cadc230bec92ed933fc2 +944d394958e539251b475c4304f103a09f62448b7d8a8eaef2f58e7de4f6e2e657d58d5b38e8513474115f323f6ec601 +8a5ae1f13d433962d05df79d049b28e63fe72688fc3e6660aa28e0876a860c3dbc5fc889d79f5c4dec4b3a34cdf89277 +afa5278724998eced338bb5932ecf1043d2be5dd93f4d231d05d2ea05b4455f2ffdc0eadcb335dcace96dd8b2b4926fb +b91153a2f4647ae82fc4ee7396d2ca23270ec7f8884ce9eead7e9376270678edd42dd3d4d6c003dfc2dde9fd88cc6e7c +adc932f1c679bf7889cb1ff4a2d2897d7973483fa283979a0ea3640c80ed106ea0934c1961dd42d74b22504be49851f2 +a82e90761fae684d1415cee0649bb031bcb325ae0b28f128ab8e3650bccedd302a70de1a341ca8decfdda76f3349cad0 +8ae353188b4b98835f4ef0333cccb9e29e1ac3ec11d554bc96f5880c101cb3c84b8eefe72f2287b0812735339fe66cfa +b8b41135bb1a1ffb64afbd83e2189e755f2c350e1273cf47c38ae9b8c4800d831436a69458b8ef9fa8b95a148d8ec9fd +96f75a04d8752fa93dc1eaf85ad333cff4eeec902a345576139e16de3a88eeb71b6726224349bb9844065cc454d959e9 +ab82b05e3923ad4c26f5727c60dc0d23063c03f5a4fd8077da66aa87042cad1bd99586d4ab35aa5e4ce6f4da6fecf3c1 +a50c83db91c26ef7bf1720d8815b41bd056b49fd99710943679a162ccf46097a7a24585750ece886e38eb4fdb866fa37 +a719f667914a84f62350dcc6f4f30b9ab428eac6837b70318c3ac491c1e69d48af5e1656c021818f377d911fe947c113 +a148807aafddfa0a5624c7cb9e42468219e4bdb9994ec36bc19b6e6d7c4a54d3a0763d13ca80624af48bbd96d73afca5 +aa012f205daf22a03e9fb13a63783dda7666f788a237232598d02a4d4becec7a699ab493f78d722ce68519262924c708 +97fc15fab5952c5a2d698fd6f7ad48aff1c8aa589f7d3b14285fea5e858c471cf72f09a892e814104fa2b27eb9771e73 +8da8840236812667c4c51c8fc8ab96d20dae8e2025290b9cde0147570a03384370b0fcbe20339c6aff09cca5d63e726f +b477d85359a8e423fed73409f61417a806cb89c9a401967622aba32bf85b569e82bca1b3394c79e180114a0d60b97316 +b3d6ee2ed1e4c5cf8ba2c3a4f329832e41c7fdcbcda8a3fcbe8f60967fdb1717665610b7c1ac65582534d269d762aa09 +a0b3b30b1b830b8331ee19f96b4a4321a6b93a3395b95d3a895682c65ec6ea64774b878b93514eaf353f2e4be28617b8 +a2b88e9617f4d30ef4e686d1932ad43cd555fadcb5102e51bea19e6fca649284ccf4debb37b5cb2090ef386fa5bf5327 +8a4446f7e8463ea977a68d6217a9046ad4356d6fc1c18d46c5d2ab681ea977b8faff136d65abea6bbf8936369cb33117 +91e7464bc56e03f436228104939ddd50caace5a38f68817bb2991e193b57adf6835152bbf3dbcdebf0382ac9823f60c9 +961a441e6cdf8106c4f45e5b47190d35644faec701c9cfc41ced40cfdd1fa83752fd56c1ac49131a47f1970a8f825904 +94b7b165cc71c2ae82976b8f03c035fb70e90028992b853aa902c0467b384c7bcf01d56166bec5def4453e4d0c907e52 +a5d32cffabbf547f900026b34ef46f08075b7a244565f615370d2f04edf50b094c95088a4a139ce07caf55bcd99afa07 +b4e06e73660745f75ab2f34d9f6d2675b58f80f911ab6dd4c5a6ce1095f9a2b50d86f6ff9a05394190bdf96af0827920 +ad3fd8f83c0103b29d41319209dffca201d2b98094362da08da3fd6ff0ba96796b49d6bed525c9adb96c2954858e7f48 +b0c27430695f0fd20ae31e1ec621da090094f2203e17411db9384695ffcf5c7c6badf461ba49ba70164aacebd6f278ee +b9bc6e972fc3b532fd2b1eeafc4bceb77604885f32132af6a9a842fa2440df452f49ec0cd9d86da1180e8deb0723b260 +9729e22d6104b0174c136a854920f542b384d375040adcebe36acc253bdb55845eb43e34dc5a7cc27d22c417973c24d0 +a8b420b36d48786c9231d454468a6e855dd7f71dcfd095efc9855ee70dbece0f06ad277f7829c5813fc30524c3e40308 +8757dff5499668c93fc5d9cea0a8db61817b8ed407200d623030b5849a913d12f8371b667cfde8d8082026eda7407e8c +b859ad747ca5af661fbd03a1a282df6e84c224ecea645bc2d4ba5e35fa06cbf047387319fca0cbc76b712398c0798968 +8e3173c27875f1460297af0fa736c945dc842ec3e476a973d3d5f790bf183ad3ffe96ac13868c5101d8e299890791864 +a9d725e2b92c878be42b5eecc2c3081c63c7231ccc7e2dee17ca6a4caaeae22788fab1f1465fcbd7fc236613fc2bae4c +86f6c4f04a354cb2470ef91914816fd740f8d5795ce7ff981f55a2634695fde5951bbae7a4bbc4c63747040f8644170a +851773cb26f320f0c3f252d95ea7e058ffcc795dd0dc35e459aa1b6b448238909230d809e82022e64b7fca5d40b8324c +8962641e0306220d9892fe2d452caa286301a3c465185757be7bce2d9b2c9beb3040280099606cc86773e43941fd3439 +8beb6e08c440b0de5fb85251d39d9e72db4e556a2dfe3dae59efd8b359d08492064cebd8d8993254b43bde8bd67d969a +a7e047894466ffe3dec4ab8d5462f2b1d8ac0df006b1d2dd26caf499ea857d93a811cf42233f9e948c9cb903beec004c +92eedd95557a91691a5e2835170390ce2401e223da43b78615a804c49566f9d31cbb7f10c8a8390c4bdcf691544fdba9 +a5e5b5d8fa65824e958bbae98d146b4b332f97ed50e0bc2c58851dc2c174ab71bcbb1ae015cd2955c26b368487dd862f +853a494eafb308175629d581ed04bed71bbc3af9ca4c0dc483d03d27c993a2bbd88cea47c2085a6928d166fe6938fb77 +83f06b88d29afbfbe8f61811690322ac4fdd6abb9a23612162e7a2dd6bcbb5f14cee298ebebc1a382484f7346dc51e60 +8c9cf05735ea5a0e563490bdc7ed29a4426643711c651e35c8551ca6f855c8458ae8f0933a022d0bb9a952edfed411f6 +b906b48d807748a26cc2a8848455a76ce502261afe31f61777b71917bdf7de2fece419db636439478c7582058f626c29 +97efe1fa7c9b25d8bea79d74b6cdcf88f63f1e865f54b58512a2e60428630b0b40b8b6af1b5f71df47520507548c3cad +8ef5ca6e753818906bb3fc71405928d8e4108854ef0ef01c1009071b353bc2852e771fcb619d5fea45590e8f61003d7f +8e4d901661e2913740d70ba4d0745df5e8c9c0a260149d9362beadc7e669630ba909ff0e8a6cc85c54d6b7435d0d351e +b7c6ba3bebbd9592967954e3a480ee8df1d9f5965f04e7d78a5415b645128deae7ddaf6ed507c8877bfca91ce078e529 +840bedb0ad4e25acf6cd25dee4f98fea495b2312dc5cb7a8388c5ab00b2acb9cd25da08e9fbead145a3107972b1ccd5d +a8d4578dbafdb27f3911af59962d89e75dea74db55346720357790da677312c203107d9c7911535aa563446fde7d4c47 +86d3b77f231bfa09251b7fd2ce09c27ac520ec35d783e912476f9a4863f83d269eb175790d6e735da9260293d707f8ee +b34909f1cc033232652da0c34051a769dc76adb1aee00674a59dc1b860f6e610974c3b4bb69a69ccc73e01f042431242 +90799854d0cf34e1d91ff8e101bc7c5007423d34d2f3bd9adea2ecac57e83f3a65a506bb93d4caea49b29f6d18149957 +8ef94cde29b037e19a1ce7bf4418ad3c95cd9457412796ea385750c19a6690f13a3bb5bb6a9ee81e7a40face1e0a8bca +97053d21ae8d75972fb37f6fe516c38c32ab162fb56b9f510f954858f4e3ef6ac8c3a9557ed3f41b7b6aef05fe97f931 +90a9f9f0f40991f3bddc58b92d40382147db22cce50d092d4a05aad251b46b94e71ec9f7107a180243288059fcc5ce29 +a14265b1344ac2921b0f890d13bcfc432e4f648ce403e261fce4d3bb32ffee9e2794c02830346054f998e82784c77040 +91928402ae121e56a3e64cd6f390127e6e92fbfb1967ec6efa4f52f3e8058f1f41a0f4fe96b5bcc11641c1139e790b2b +921c8c92b6d40da6c5a7b592acc74fc0f577d93767b9aa4a1cd302a72dbf503a1ea5b2c29fa0d0359bff3b8f252246d1 +93ae0ebe0e8e133fd80cf67a499047e30ec4c4660ccec9d49098717ef57721a030f423e00c5e74af4ff4acf014a10497 +82c865e21905aebfe0496af1c6ac7e342b5f446a9edb4f7da0f2fb0340abfd8e6fc545da874459d9aabe6bce0dd9bfcb +aee3961d8d2687c0f134b9c28b920bdc4021d925fbe14323c84224a9fe161248789249fb85436a5891d0bbff42c2a3e9 +91aee420b98b6949482b8ff4be996b97245b4e8f583a6e085226539074f42aa89818395efd1a6699735a569bfe19d623 +a48eec22c192e495b01722d0016a54acc45ff837e2a95c4294ce81d5a4e43e0053a6f0ead8a4fb3ddd35faf6607275b0 +a26e15937c11faa30ffa64817f035e294cab0e839f73d29de8a244ad039be4e221eb47ea08d9a4658b0152fc3caf6110 +b84450f948aa7c8682fccb9cae84d8e3558adf2d0ca5fb81eb200415291158720f8f3470542ab5b88c6873ad08e7fa9a +a8e8ec27d0608d020169a85d6ecdb40eb402f006a3b97afe32cc01987721b3a68a92ec693aeb4d357e189e05fadf699e +ac87cd535ef5699312cc26f86adb71baa0be42e858bd5a2d94ac05737dac63430691e29b9a30d2559ad581a172519b2c +a4481e67b524f8cddf2046625efd3d75efee6aab87ddd2c1b22835647e918157e5e924ac760db2195c86d326f3db1615 +891f29ded231486ee826840c8895cb325f7e84a5a6d2eac246cb3573612cde274720233b1978318a57ed337a046330a6 +906b6e750e6178289012769807d2598925d7e51c260c14497d8af978b1695990e3352e6e809a752f376597a68083870c +b7a056898ee1e46f7f29702fb39232f678ec173eccd170303b3b0a30c8d8cf1a5321384e3513e3b03bb742c238deaa54 +8f2f035fd96c3a336354c89ec9b8222803bf42e95fb2412c28d4e75eec99c1d4d402501ccae17357b757db8bdb0bfeab +81228625ffcedf977fba9cfa13f6edead3985e2651d5974789c394a69401cd7face9e20ae6694be4c0d4bab5e99c61a8 +885a83eae25e61439ad809567a2ab148583402e01cfdd77b0e37ab4038935425c64b4e0886949bf06438c35e80aa13f4 +8926387f48752f6933899c48e038cf14e7941ec6a58bcc0a436614b396296a17aa53e6873803dd3041dae470bd493fcb +95d0d3fa061f4d856eca78a569aa132db14cede7646f97e2aceb6da0c8ea53195d3b7a566fe5ec8c41b95ecdd89a1c6b +a3c817f4062ed6aa94064ea695d76c1825f3bf77b310fe1db28b8bedc9aaacbf1019dbd128adfd53042fb943d863a2b7 +af1208417aa584052da309169854149ede38a3ad63c76cad6e43afb6f1a7b854edf8310a0b00088c039259cedf0f859b +8b713fc3196bad35dbf364089049ada5477e540d78d76a5f0a9df98f7ba4a0e65dd0644509c149f9b07887298bf74b04 +89c09c43c5b733c4a417cd9ebc0795cc3348b72778d31828a9171427779a82ef023c1a4fcfcdc919ae25056f9c826fde +a0759c850ed320c8c874435e90ace6edfb8e7b3f2a09d942b8ad8339c508044ee2ee26c70f1b626ec49a77971433b6a8 +b85cbc58d4fd52286e714ac4eaaa0b2743a1de06fa03ddf8f6668ec6f1d204acccce93b10620272afb8c0b49bc4b0a43 +814e0a87384e159892a8d23036985fa3f489c53bce192e107bd2d64f57b1bf5ea0acc1ef46c7a42bbc5cd0924d92b4a0 +aa6821da96ad89d7881b878e141076522f104ea9a5bbdd1fce9f641898f7d6232c518a87a0f666871d7e3165c26081e4 +a9041d714bfc067b5427252186fa3557bad598fc0067dc8521aa9bc1ae298f6e96113db5ac9f6bade9a85d5a950c9755 +b8669340f3064692625e1bf682d34fbe69a61689e3aa6d6a3e822c781d406b0300dba9c3f7b8152a8c2513f1310d4291 +a78c53316ce768a1dc5968030bf4fc885f4029b1ddb6a5d84a61c85af686c73727f62823891edfcb6ccf4545de366cff +ad1d3aa29ea28292ddd438c865e2b5d93f32cdf009e6d5f5dc726de996583925727e6348bf1c28c22dec0bd86aaf867f +ae1447a2062e9e28af5f38aecc60fe150cd10c2edeaf2110034aa144f6235ed7fbce432a58805d4fe1f6b12652d6e1cd +a32146634332d3303934550705353c6d4fae5fa5985105bba35041e74cd71e2aad67b45da171221f6ed80f36bf6dffa3 +a232e8286184196ea77427b53d8b52c44d758ecc42d22556529db3136379b4989dec61cff610cc6cf6700a450a847a94 +8a72c7255125a736da52dff5f77e44c3de29f88fc05f5ff9227c69df296930caaa11446595e6bea3bd946baac5ef957c +9688a981a9457678067f629f8efa6b522e7318b529f88d37ef56c5bf8f1c34fb9bb3a918ab73caab82bf5abb0c03518b +88286f3eabd71115fc3b17a6bf6981340a81cf7e5f96b0a1a016d4ec8c18fb486d46c70919123d0c189a6f5d6ff29a1e +b535e701b40d793c02ac0d625ca91620d3f4a512aa9741f71389e58381008b2f93d597586d06213c4e103d67d0ddf6c5 +80d0c9dd941e8d8d3700cc51a434a5aaa3308cf8ebfd14128ccfd258f826b27cc3cf5c3ad7851340393abb1eeab3a157 +87049225fa2380d93f18d3d90cb0697a56b373b66d7f24ab209966aed8b55a2790194d5885399db29dd5b1f189eda64f +a52df158ce8670e0290551e8878d63dd33b4759d6f50e448e63fc7fe6ea99dddb6f180be5fc0fc3918ce54c05f80b356 +8b2a728b39c465fb0f60b0c486e5dc8d5845ccec03d3dd93b393cedeeb3fe1b44518359f1ed55fc770a8f74bfeb9923d +91fc05419dba718fa4a910dcf256ebea356bbea00522d8d5ec3e7ba4271a26035aac15e8d9f707969df1d655d92dac55 +97c8779ae80c24c1f82d5a714762d6ee81069224e39515e41d8a71c9310dc5d1c55cc92bc5c6a4bd391ae4c321d1d4d2 +b5e5aedba378c4484e3a7a4ed41b75b0844f674261c2501497de6f91f7274b5a4c1be0e055f2e0c0cab843d891169fbf +8a26212f27211b295beea500abc8e9d430a8500d3a350cc62f895d39e8b4668aa638c17633804ba353010000165637ae +864a95118e5d394e00e99efebd505df0125525c9ebe165764c453b80ad3edc730feebde3d93850745dfd88a27bb8f20b +a092e0b78290e826cc1ae56afffdd08f7c10954f549a3ea6666f3db1b6cdaeb7df53db28dd2a92446342930fe60a27ce +a1720224c0626a081b6c637b2a6d37da85d9a82241e5efef3bc15699b02a69f6304e43d8ff3144d60c16e00225d6b39e +a7b3d098cebea9cf32e19c5195608182b6afe9d4af6b9df532c047eb7a941a971279b2ae6a4b80f2f9d9313a6d788ce3 +a3d2451e6788944802c5077a778d7b7299dbb9d1612676bb6baae78f39976e0fd879493cc4a4d737b8174b472a456850 +930121b73da844571b1411d56760e80923a4ee09917b3e9cff4d3dcb0bc27026ff2c4e2c44e7aca7d3f8383f129c7f9b +b4b0119d163ee00a2b74bdf188a5cdcf054daaa48c483b94bbb4d09ff615afb4a91347db6363bc7535e2af9054ec2214 +a5846decee706780201095a8cdd48fbf3d3a2eac8d089a818e5e22c29457494bbfb4399323b067f3d2be2197c33dbd98 +96ba600df10ee7af5a9df29c0ca31dbed275d647faf9c66c7342de927ceb25b5bdd852dd7aae0228b27897f90fdd5d62 +b6ac51ddc98edd9fb9f54ef84bf372a041d58dfdf0dfdbdc4b08ddc1a7ba93ddbb1413dda3c1545a3fd7386c6b85975c +b35f3efd91a0723e0d486188ea9675a3462106470455118392d7610470b623caca2fa33829721c05fbeb0fabcf570bfc +87f49e85df5f8055714a8ce7adf37f6a278e64e76ed74c60abe3edfc3611ef5b0426d4c6da45e5f3b74d30be1dc6f539 +8ff8bb06902a71b1e9177a77367318b2e3e0a88f5d74d6907ca9943f4f9f1ceb5f297132c2a025259d17a67e880d1bad +85eb6de6c70fe5c53ab0ab27aa0fec439f136c979c557d317337cafa6e6c5cb3169679c9169567dec5f6c72b3c057d83 +ac18715ed1080771d760cb7066c6328faf65d9b30517903f8a5cad8d66d5c6381156b521107d7cd75ebb8c30e250706c +b95b9eae4703727e4ac9ddf2ae675906487bb78905a5f9cba74a4cbfd118d96b7afb6ef3ed5edf14fd963b830d71338c +a3b47b52fda16b62b11c8aa4daa56b0b669c4d5c56a3059b7d063284d8a91f6fff9ccccab23d6ceb9650483b2d353039 +96a95b3f327df94c85e92f2e406f1649ac621533c256b062738f3c3ee137059a735a3e6072247acf57b1b0d8c219bd7f +b19b33cc04570be94eae8e943d5bb17bb0c96e9de4ca84f9f41b37320a1a03d397d53747dc13275fef1b356de557214f +a1faa3dcb931dd91507f3f12a17c43f6627fa2bc5c71fbdd27548e091eaaaba262477949cd51290e81196bffb954a492 +b060a16079dca1d28a1fb33cbc26f368630ee042d980ce305230005d5b9ab533a7a695281ab76e9214458303932d8bbc +b303783196a858fe45d67e0520c30576da605fd69964449c20009fbd5099cf1de52a32d326d7c3b864de07440195ef40 +aa550a4c20d1003d137ffd8fbdc1196d09ad53cfa0e202302093a80fa3bbc4c9aff83f34f2151785cc1ce5f30255693b +a7f8585f45566a351058e10c6f1ff4a7ba24811f1482a47202f581525615ca770da93f2f58878788b45b92cb446ef4ec +8206f63a9a5b59bd68e64a843e68fcdf706f4c13bbfcdfa9928298e5b9251006ae0bbd80c715aa3c9957d2c0148b5059 +ac9490abe1241319658f1c2c645cfa01296f5d4106020c7894b7ba4a65cdd52f6c5401bd3b3cf1c9863e088cd8c9a16f +85dd6d9c80a1b58c24c4d2cb7590d33d2454f381f58e820979948e5831972360cde67bbd56e1860077ef5192fcacb904 +8b0285944c676fe2519cb68da0973275fa29c0718d838d363ce46651b068d29f867cf9fe579ff8da0bb8b37d202bb23c +95147275da658d43a758b203b9ca1f1c1478853e9bf77b5218593142e2bd9c0bf46d2206ab64cef99295de6e9a268edc +b8efa187fdd3e1f46c15cd596e9567690c10e253b5beaa5be8074b6ea4e6d3d06e0f2b05323453239e419ae1e7128521 +8340464f52c92e31806fd3e8e65f56e27194d1f6daa4a0f0b3831e8102aba16f88bb5a621633ddb7dd0342e1d2d12343 +8615d87dcab85a78dc052f05a01e751176b756b5dc9985014347454ce5752f459dd6464e1c5aff36cb6c51b783fa2692 +80c6e35c0d3defbe4d3968792724a23f0b8830dd2fac58663583a49339ea20f1812cc4140e3ee867c7e716177319bbbe +a7aa63dbfc201dde8f29bb6e23d7aa5020dd35bd18a0cc93c8a10c35d695913fe25b9e8cf9b5fd1899e9657b22bc8863 +97c2a4ba80c4caba2e729a603d2faa0120915e3fe64cbb065f7ff33de5f877f1ec9461cf455e88ec9e9ded9393939dba +a54bd1419f0e2d2d87757870f37c476c7e3a13502f1ada82fd7394fd29f8a00c4986473d753034d0954a2550badbac0b +8d3e2bf900d0d2b9b46e6e2f37620f0cc90526dbbcfaad4e4a37ed53f39fdd23bd3a6f21aa7e800eaec937d9710dd6e3 +a88d2b1c7802b2dc216c2b6532406c091bfb12f29121b9a82c1154470e250188413ddd3e79f7e009ea987a4c45b332e5 +8c552c2101dfdc3f99c2da436115452e4d364eefe029b12946f05673c5ce1cfb48d39a579625849236dc6c8e7277dd30 +8415c252d52a26a6400c3189c928a98559bf24162ecf3eef1d10e439269c31d854b0b4f6ec7a2430e3f11b5d77de78d6 +8b38905bad93a8d42339dbdb5e510003c51fcaf05e04f88fd7083753353bc1c4c00a5dd4a67431cd4456d0669c7040e2 +b1d0ed8862250d0f0d9ef9dcf0cd16d84313d1a795dc0c08e0b150dadf9ce73d32d735e04632b289cafa69a6ee75dc89 +9434e18a5fb631b10edb02057f2d1fe16000ee55ada3c26a079c9fc3943e29d6de99e52829fe7b333e962270c712e51e +b1b9f3914007e6fca8ad3e7e848a1108988cb2318da36df24767d804e95d1272943fda948451135cc1b5052a3953b081 +8c02947a76d7b6c0a700a83dfb971dc105bfe996e18c521445f036310914b349ab28e57571e36ae08d13a46fb01c2f43 +893472fbc225f973a0ac6a0a0130b9cfb7ab6869dff80df71a62b1f6beb4afd069bbf35b4f327165bc31dff39e4fcaa4 +a7c176c0903175f3540d62f9afee994d5d9bf37081e094644b22f017e94c515afefde7bb07f638342abef7de657f8848 +860186c2b1d3b1e657729bc804275fb5f5ee89eaa60848fcabd3871289665ea9f0efc8a95792d884972bcfa2de96223b +865b38aea6386d0ac8f501a7d934e23d01dc50105324e354d4c4fa3cb1d4c29c26f4566df7b1a728e10cfaa9d24552e6 +b4eea5548de6969dada658df604b5d9c49002e2258352838003e0fdf7b299d81fb025807a7f37cf5b547cebd7f2c1f93 +8982de11ba68d63a649a3b296d4d56c71e3c3eec016db250d733ab7c3b9a620c09c5a5d0b64fd30d3bc03037ca4b17c9 +84d8b8a10d67eda4716673167c360fc9b95717cf36ef1d5bc6f2ef5b9d2624f0e76c2a704d016adf03e775ea8e28d83a +834d03ebd51aff4d777714783e750b84c16cb6627f8311bd8ff17c3b97fc4a5bba57d6c8f6d74f195d3030bcb5f07612 +aaf49e0def0c4d5f2c1e9c17b51e931d2f754b19e80070954980b6c160178349f6d3c8d4808801d362e77f41a0008918 +8ef4115edec841854e89f2bbd11498dac7396bca35dda554290d3db1c459ffc17be671f4a46d29fa78cbd6064cc2da20 +9641dc8a64f4acd38e343a3062787c48c312f1382f7e310ccea3e95e066ab6dc980f6ed90a633236a435e68bf6b3c625 +8a84cfc2cbeb18a11dd6c2a0aebb3f6fd58a33bb4b26101e826add03748595022e816afac79a4e7c20b3805252839dca +9770782d729017659844421e1639ffcda66a2044df9e19769b90292df87dcb146b20c6b9141bb2302029d84a5310665d +98c7ec9696454868ac52799d1c098c15ec4e08b34884dda186ebfe87d32840b81fd3282295df141c91137faf4cc02da8 +a3f6eb921247617292162dfc8eec5b830ddc294a0fb92f5b4828a541091ffdaff34c392c1d7168259d6204405d90ec72 +b185f77a468f07a54222d968a95635234e74fc942485604909308a9028ed2753b15902b9134749f381f7cd6b89cc8c3d +867608a682d53bd691dbc92eeb460d1c300b362ca49c11a280f6768ccec217f1145f9d59fe50d994f715ce89d38a74e1 +afaad630ad8827cd71aade80edf3d7aeb65a344878db12fa848759e6233f6fceca563aa437e506ea9e0f1e47b126d45b +a12afbc84e3441594aecf85d089423dd3bb8bb33a1a384ddf7cc14caa72284caaa56aa179c15e3140fd56bb532491a67 +98757b0b5e5837ddc156a4a01ce78f33bb1fce51e0c1254ee9b6d3942268d0feb50b93edbf6aa88f9ea7b3c0309830d8 +89573f4a4ae752e9f964e42bec77d28a41840c28e4bcdf86a98a131d0b85367b885077823a6f916972de6ac110821bd2 +a17f2745052de5de9c059307308fc49f56cb5230e7a41cb7e14a61c9efa742ee14c41023ce90c7f2261adc71e31045f8 +914b07c53a41c0d480083f41a61c10429ea42dafea9a0db93862d2269ff69c41db8b110b4768687b88089b5e095523cf +b380cc3e0d26370976fe891d24ea4eeb1b6be8cfce01f47fd68838a27190e644fd57b049d3aa0a9589370de20e276944 +906385fdfad60feec79eb1c303e750c659ceb22d9c16a95faaae093daadd53e7aa039a45d57e20951d6e1ca0dc899ef2 +b5211ceee31b194dba60b616bfd91536e71b9213a3aaaf5aaf9b2f4cbdeb05191861d78b97eec58e3c81abe4f0488c04 +97878e9e38c2f69d697800e7a2f132fc4babaacf471c79c26a757f771606e55fe696ece68a3163a0ffeb2f72274cf214 +959431c1f54c46500c05aaa9a2bc4230531dad97ae768fa92bb85436c0ecc6374cf20fb0ef82d122db116820a943b401 +b69e5a1c6798f30d33e42cb8d124f025d2c77c993c4c7107a539aacddf44d8d4d2239e802ece32e60ee4dbfdce201bdb +a8b09e5e9f802ad273b2efa02bcbc3d4a65ac68510510b9400a08d75b47b31c6f61ffdb3704abf535a3d6d9362fc6244 +a41ace7f1efa930564544af9aa7d42a9f50f8ba834badcaf64b0801aaed0f1616b295284e74ca00c29a1e10c3de68996 +a8f2aa0bbbc19420a7c7cec3e8d4229129b4eb08fff814d959300cd7a017ddb6548c9a6efebad567d5a6fde679a6ac6a +9683da74490a2161252d671d0bc16eb07110f7af171a1080dc4d9e4684854336a44c022efe3074eb29958ae8a1a14ace +8ef44d78d10795050c161b36afa9ab2f2f004ccf50fdeef42fe9cdc72ebb15a09389ca72a00001cd6d9b1d7b3bb766c3 +adca54f3b14fb18298098970b0267301b7312afb75894deea1b2afa3e85b7a3b4efac9971ab54c5cbecba2da9f18507e +ac5d4528f06fdccfc1370d5c3d03ed982fed0861a93a3f6453aa64e99360b124926d1892faaf72d89459e663721dfa99 +98aa1c801bd615b8cba728fa993021e181e0ad717ba01c0290e7355694155407083eb53cb70819c4775da39d33224db7 +8b3aea4c7c2bfe1020de3261ec085d79c7bf8a7903b825d2c70ebbb84af197bcc54e3653c5373a2045c3021526b63b66 +a29f3de4cb3d99afff1daf7d431b38a33a9804fedc41626618928ed059df6f6fe9f298a046b594ffee951ed4d4e1400f +803fd346be540c5242667c18ee41b26bc812456ab13ff117196ed69b90ee608c8cb6554396b64066a546ec87a71ed6a9 +a9c18d81ffd029c0339c72c499bb51685392253b996b6eabd8b76f05c6191ed8444a1397d63b9923743661a319517f7e +a048d5c390d08f07161faac71c5994baf152c883b205f3bb10d3501709d6516ae54d491b486303a11b751857a31f0052 +9156fb4803e40e28d8d57d928481a8de4373687288da44fe88c5676a8ae013ed1fcc09d56a31140bf74e7f767253810e +98e289c725b18e0085afdfaf2acbc674dae7b0a2ecc2537a7d0b87e20eb785404ab05973a787f0495d2adb3e5565c09b +8a7237b249325bd67cdc1f9fb278710069033c304afbf270b7ea24dbc10c8eabe559a484d3edc733c77b4384932deb41 +9056f2e5b02e5c2e04a69fa1323bbf1859d143761268d18e74632e43800a2a9c76fd681e924a19bc141de0e128d3e462 +b9f2bf9e4e7263014296a82b9ecbb05d3f1efa4b2e675e3b38d3eace59da06a89c859256e1b77847886d6aa15f98f649 +83b22949cca19030289bbf7cd2a0d8b84e1d468e78bc85271a6753241b89122627632723bc293cf904a5eb2b5dc6c3ae +a919aaf35dd0116168d2ee845122026416bec9633df113fbd913d8db5996221e234f98470d029a8ff182825b59fda20a +91726901f49d32b41afa15219073842278f60dcee223640903d871e318a1c2b541136b7b38a7b2ab7d31e4242fc29674 +942b77666545bc9a858d36cfe857ab1a787c9528f4a0b87918a06bf510793264dcafd12ae6bd3ee300179dab7f40aed0 +80adc1f2f9c47a96d416e44fcba41628abc0fae1f88f6a26aea4648419ab726f7fcc2187c7d5145e3d8f5a75c03937f4 +8041e0f66ba9dcee01e336dd4d16ae5e4e1618512fc147cc8230003aa2940848162dc2187d4130bf550dc1f3559849d4 +999e8adc51bab54386af1c5e8822986ad1b7ecaf1f8a4c2baa5bb2fe9d10710e49545c5a8bd89ed0e61a3d73a908e5ef +89272ffd39b6e9f99fafdd58bd9dc00f66f26a1d36b38a1ac6215e3546d966739eecda7fc236335479207cef95cce484 +b8e0b7532af13f15dc04a0eb4ea8abd67e58f1b1c6ad2e70c0ffa04a5c18ec2018b5d7f4be2f9f86db5e0b3986f639d9 +b96bd11b0f6ead4abd5fe1e4c6e995da7583b901afd01cc05e87d04663fb997997d6d39dd9fb067c62cb1b1cbb67516f +94ab08914088b973e8dbd5685decb95f3bf9e7e4700d50a05dbf5aaac9aea4be2c10c83096c02252e9238ceea1351d05 +a188de419b062af21275d976494c131ba18d2b2ead8bdbfa38a777832448e64d4d9725c6a1d530ffb6513f18d5b68d9d +8f73c8c118fa25c76a4ec5611351953c491452743056a819c8c82ba4737a37d88da0b55f837e7239a5f46d2c05a1bbba +894a44769e0be1c26648b0d89c4c9f46dbdeb3a71b90c493093bee372bb9f2d3f319850fd886d51f4f58db0de5641742 +87d239923b0db024a8d9b0281111d47b0761d81c50652268b074efa3ea70d793e30f874a91ce33a4acecd0cf38c01951 +b1b48b75a97f9fc2dc9530dc69f6268829dd0ddd574516e7eb1b9f5c3a90058889a7bcf3d378738e6d4b02f5fbfa44db +83e3ee9526ffcb60c6e75b75550fc017912ec0daf96d0a0d5f58c1b229cce90c684ac7c3e17fb998def8e7e2e155d750 +b9b7bba579e474b0abdc7775ff5f84c9f117c6ca17788cf5a5f01b2c35a14aa39036031c8d799fec2cfb371d9f7471fd +90d7faf4891fbc368a32f575dfb69f13e37161ab4f63a7139be103285a49490c2851a907f8d36e09e7d1a190dddbc6cd +968c8b9affe18fc34a4e21f0d8c5518341c566099e6b45b8721c9912bab3693c9cc343406fe90279692a1eef2a3f7311 +8735baaf4704207550f77df73fb701d9a63329993a8cb355ccc0d80daf950145f37e9b4b22be2aba29898e974f9fd552 +90f52b2dccf525b9191d836b205ffe966d9a94f6c5800f8f51f51f6c822619e5abdf1257ee523597858032d2e21014ec +831209f8f5257bb3eb452d3ee643d5f063299f8e4bfea91b47fc27453ac49fd0ba3cf9d493c24f2ca10d3c06d7c51cd6 +a5a4db4571f69b0f60fb3e63af37c3c2f99b2add4fc0e5baf1a22de24f456e6146c8dc66a2ecaafeb71dce970083cd68 +b63da69108fad437e48bd5c4fc6f7a06c4274afc904b77e3993db4575d3275fce6cffa1246de1346c10a617074b57c07 +a449448d4156b6b701b1fa6e0fe334d7d5dd758432a0f91d785b4d45fb8a78e29d42631bc22aaa4ea26f8669e531fed7 +aabe43de1350b6831ef03b0eef52c49ffb0ccd6189cce6f87f97c57a510ac0440806700ce2902e2e0b7a57b851405845 +91015f144fe12d5d0b0808c61fa03efe0249058e1829bb18770242f5fb3811e4c8b57ff9cb43deccfc70552e4993892f +8e9c570811ce44133ce3e0a208053acb2493ef18aade57c319276ad532578a60d939ed0bde92f98b0e6a8d8aabd60111 +8b21839b5dc1c9a38515c1076b45cedec245d1c185c0faac1d3d317f71f1bfebba57c2559bcdb413d9d7f0a2b07f3563 +90413bbd162be1b711e9355d83769e6aac52fdfa74802d628ff009325aa174c68f5329ddd552ef93e8fdcb9b03b34af3 +8b6b02e3f9dd1031ebd3df9a30432a3c86e64306062ef00a6d1243620d0cb66dc76f8d0d412eceff877ff8768c2696ce +9894b41d9fc715f8f6addace65451f41dc5ce7b983dd8cb33757b4d7259bef12f144e0077d0b662aa847d5a45f33c563 +a353a9740f6188d73aa4175a6c5f97898a05ed7aae9d2a365f15b91dfa7c28b921fdef0a32d90b6fb82718b33d3ddb8d +984eab8faed87c403c9979f2d2340fb090cc26d00cb4092aeb187c3f4ee1df3f57cb8363f7764073188790b16dfc464b +a5c5ae0ba435fb7f3ddd5ad962358da326239ff236fc3b51bd22e88296236b109951cee1b98f444302badc58d1b5bfbe +880be1006b0156f2788813432f450f613d235f41aba52a6000d2ad310408ad73d86b79f6081aef1e8c51010d404ba670 +937da751aae68f865c7a33fa38d718f20e2a1c65cb18c8e08f8441f0cdc77662789d2793794dd0a427cad30cd0b33f42 +9496fde66c834ff86f205897db12bbf9a9bb78d9ba8b5fb539cd0a2c927cc6b4120c017b0a652750b45edbe5f650e5dd +97a6f409ffeb593e149307a14bc47befb632412d70565c5f13d6b7d032acd2e3ed0f7b6af701b387f11d69ee4a8094d7 +97ed94934263dc0260f4f7513745ed3483cdddb9adb85dc33193c3a8b4d52affaf1ded23b59c34651afbffe80d40dc36 +b2b26378d44f916bcf999db218b9892e06de8075f205c7dafd6d37a252185c2d1b58e2e809c717963d25627e31f068e4 +b8f9fa1fb45fb19a45223f7be06c37d3a3501dd227c3e15999d1c34b605f888123026590697d0ae24d6c421df8112520 +997aa71e3b2e8c780f6855e94453c682bee1356b5ce804619ef14834475511105b1e4d01470fe4e2215dc72182d9909c +ac2cb2a7cf55aaf990cfada0218453853047e813d3f51f5a623d09f4714da79de6592671358a5edf938a67f905b6cb5b +8d8340d0c3081cd30d34f3ff6191e1ff6ad7994b4ebac19e5936f1157ca84e1813228b7605ee226366d6bab1e2bf62a2 +9693b17669086003cb46c75fed26ea83914a54901a145e18c799a777db1df9c9ca6b2ea3ee91e7b0ab848dc89cf77f19 +a6b6b2a6cd8c4922d78c8ba379373b375d66ac6ea04b830a23d5a496cf714a9439d81c865da92d52600aa4e2e43afcf1 +89cb665020abc3f5e11a03c7ba5ec9d890fa9ed2630f1443a8e45a28c32786ed980b5343ffffaea60eeff5b313bc0d66 +b37b989106594221bc6cf33a1a83c3e65ecdef279e90333a9e105b8139dc28384bb2277edd4b77c9e59d15e6afe074c5 +98ce5aee5918d18b2326b30c1ba41669cce20bc7a1d1b585363305fbdea66055164a7ac398ca0f0e670291a3061022eb +b57f472d5f34beb4cf430d7c0f8ac5bd1c0621a284633ed36e6f7804bc2b7847f54b469c7ea163a436510d9e3b32f97e +ae673a6579dbf0504c8fd0c8fc0252d2f7ae8da615a06f4d215c2f8a8f516201f24e5cc42967630c252905e5dbbd6377 +97c1501835a31091a5a83f0546e01c85ee847a0ca52fb3cc0653f6a826e13d25ddc623a5dea139108f7270a1fd7043ea +9376ee667f3834f6c0da4324fdcca5c04712e0649877ee19da79a2d23be24640c38758fce562470ce2134ca34148ffe3 +818af89c40379a10074cfaba6d5968ecf667f1a68a7edaa18e8977ccb34e0829f237c5634fbd079e7f22928b277f1096 +b8e0af0be0a252b28df25d4a509f31878bcddf702af0e5553393c3dfd4a1f1247ad8dc2668bc8dedc9b41f6ad8e71b15 +811667ffb60bc4316e44bd04573503f5b4dc44d1ec824393a699c950e5fa085b146537ddd6a08a3fede7700396a0df7d +ad834cbf850b2f61ce799c4a0f8ab0c57039d4e1113933c50b0c00175171aadee84894d1376cf325bfd434c3deb44315 +a8b7dfcdb40373ba4d55e751ccfb9070554434df9e359fc165284ee3dc35db6fb6055657ecf5a9e9b7b8e2e1abea4375 +b56a5b9fd41c9d3f65532aa58bf71a38fcf07782e1ae0084dc537862fa02e6d66658b19d6f71c39cd5dbfac418da1837 +a935af5ed224b9533b41a7e79f872f6851591da9e9d906050ccd1b2c772a1d6d010c5fc7160c4f8cd7d3aa14c3bcdc26 +a81e580fc98692567b28323fc746f70c3139d989fb6aabf3529504d42d0620f05327e3385c2bd5faea010d60dd5c8bdf +a8b352054cdcde8ddb24989329a249b71498a5593a13edad1e913c795dcad3d24789abca9c7ed1d57efcc9e3156da479 +b0de8a2bd7f93284b2bc700e442f52ada16a22ad8d86329591547411c23fff0333b2ab0c9edf82bf7903ebf69916eed1 +843e9781b653d1a427f3534b2e86add49d308ca247546f9fcf565f9e08df921e4d969e1b8ed83f3f849e98c0f63e39be +84a4098c5dca9f73e827d44025473096101affd7193c40a0307e3215e850e753e9a08e6e74a442d57626ff26df77faac +b463eaaa2f3315b511c22a97fad353014d840a6a95fe0d457d0677e63e571407d7f5268f8775381a5e7adc3b4163eb88 +ad0417edaa16cfddc288eef4173aa7057ca4f81e815541ac588ef5f24b98d56fed6845deb6ae1a9740a28bb1cd8780a7 +9271963b8fb2288a96e07eac13c0543ec41abdc6d978bd7c44ae08251ea49994412b542c77c8208cd71fd8e7852d4a70 +8b68b6db9044d8bafc155d69e0daba95cd59d6afebb085791e999afed4f33a2479c633d31d534ff767b8cd433d591a23 +a6a06a0e433e385437d9996ce823abda9848754aa9cdd25ec8701af35c9ec15df999825669bbc2e17cedb597a96e8eeb +94d414bff8b6b8597634b77a77d1060db8e1af0d0ddfb737a9bf1c66c8430e93a425510af2464bce4a7b29bc66cf325b +b6514049562af1c6fb7d0e8df6987b020f0b7a6e721f4862e36b1ba0e19af19414ede04b346be22d348b50875803d1bf +a42c7fb34f2fbee8aaccd1d86672d0acdf4e6bb083ff0456512d7e1e43be041cc0924322fcd986e6e1bce5d5ecce6f92 +867cbdd169a52440ae0a75d33a28c7d00aa92b4b65aaac5e62aa53a8fc367c08ab8828cc8fa18b6e7d1f908d158e3382 +a6fe0b768fff3e4a6153e59a7b7508eb2ee8165eaf5274d41ac2812bd4563c4ca2b132f0e27ea2f1c98759cc3589b61c +b3eb1dba43d10b9e17ffec8def053fc96f9883bacb49330a089a0ca5b9ab0182e8b5111ad4aa55c1ce1b6f4afa5c70a3 +a1531351098bdfcda566ff4d811301c0305626c77f954a38420c490e7c684f517eb1a4e4bd2c3904a10bac889cba314a +92278d106ad2f27eacdb86bdb1faa0a07a93765bb79dcff191873c52253af83480114b2299ffe5324f9c31d0abbdbbd1 +8900ba95a90c447fb6fa1f528af3d7a378aec25feb0620516b6b97e54b328fc31af42e46a8ad5e6e3029d83a6f2bbe5f +86053d481179c1ac910d5e7b9a5de82794b442f20e854583512ce1f9c3f09e71d1bf97d6700fe776debfe1527ab97a82 +a32a60de492fc4340336416bccbd2591b5e414fca0aead82281212e24490acc01747537b3da783684e27aeb987245cc8 +9820fe8e0338f21797143f368177e3669a1f3894b40ae9fa3b353125f7c8e85cc424dcf89878f2c7667f65db3b1e4165 +934d64711b4348ac5e1395cc6a3215e5643b540f591380d254165486b0ec2a1d0d21c7d2c6310f9e0eed3d08ecf4b57c +b9fd32d589432eddcb66dc30ad78981360915854cc44b2afeb826b5d48a08e377dc91be66f5bf1e783d1a8bb320f7ccb +98c972cf01efff4fc2e485b47572e2d8dde22461d127ef401b71a111b0603203971e3cde40912643affd7341cd27e57a +8db6c1620760063edabd376f4399b6e1355462e04f5c81cdcb3989fdc00f9a466bc85ed899e886c89c149adad69edbad +ad7b7fda0aa6e2aa66a27235ac5cc680aa04b85dce329fc4be84f75c9c961120a3d9e446aa44539aaac8ea203eecb4eb +8ccb01eaf41d816ce69ebd57754859e263530915e775c4e7d9dac37b2457a9099b9ae9b4c6cb09eb5ff246e3c9320c59 +b895b83b5f7ca46e02697dbaa6157df6c7571864c83e504a8c77d965bc2ba97bf9353a71c56a020df64498bd40e30b21 +8018c07a81c522fbc25f2cb14f2321c61b98bd8962ed8eb7d5823dbe5d1958a5ec2fb5622fd0868e991bcb6cae016ea1 +95b16364e94d01b3664812264d7185032722a4afc23bdd33bc16ae87ee61816c741657c37138d9312cebfb5fcfbb3b2d +94a709209990a8b09bfb4b9581ab471aae3a29526eae861108b28edb84aab6d28f1d7a25dddd8150b70af34bee4ca2e4 +ae06c80839c5a13269b984ff4d8a5938c6f4d8d647b1b1daa8cf7f6145340b76a286cd615ec251a65501e6290162da50 +875cbd0694eeb90d3567da9dc7f570d97b02bd9cf17bfa011efdd48f1d580608a3213bff4006603b8b4079fa66bded10 +b27f88c455f025e1cd902097d6a224d76bdf9c9195adee30bef4a0b0411fff980787285896e1943a62271d0aca531446 +8024880cde783cdb2b863e3dd856be92bacc5b2a1347e96e039fe34279ce528560d2df7d4d1624a4595dbafb40529697 +8883d02c2a5c0e026d941c785128d4ac6f7a9de625ea735b7d6ff27a5ba10fa4d6370d450d99a855d919f40d64f86afc +a1beb985c45fdc30ac536f1c385b40b6113ef6fabc2f76d255490fe529468847a776efa674ba8fed72180f07d3f701f1 +ab83bd9b007561695210e3276fde72e507456ba277ad4c348a2aec7a6e9ebdc2277cb4bd0bca73bd79bd2240a1fc4456 +8db27f516153812149854fd6bb1250e843a3ae1c9637df818b08bd016a769d0497ab6087fe3b2fd4080882713607bf46 +b3891dde4e00d60386aeff161b4a0fbc30bb31ee7918ce5fc0b49aac3238a000ced192c9c4c08d90de3a0ba973d7cfd6 +90a2049a15c02e59024a7a1cb0adea97501c60b1c7442fbbe560054c3d69264e69627ac57b7d9be01bef498bb2a60198 +87df67a4bd72444b5faa4f3b067204c4927c869dd3b29ad192d859589a9b2c1d6d35ed68310081e140add254a9463092 +8f80986a8dc8a0d6408ebbcb4f234e76413c11cb0d66067f9436bb232373100f20a4fded60f08dec3525315abfaa8523 +b061e10beb12ba3683688a4ae3a91600d14878ef78a308d01b93e4918efc666450e3f7b0e56283468e218934231df98c +86b9e55f3783d62e381659d3e06699d788b88aab1ff99848db328a83c97d223f602201bf2127c5ecf419752fed0a224d +858d878e29925c87243e010020007f96fa33264e89c8693af12857b362aee3fac2244057e159651c476ebe1dfbd67bcb +8fd47cdef87d7a569ffce806d2c2dad100692d6c53e5f5dfc6e274f897dccadcee30fc6c6e61373961bbc1f3ecbfa698 +892f2822daf3df3a759bef03168c1cb07408df62e024747a788e94d2da325f880bb9c6e136c7f6643f45b021c6ccb654 +8714e37ac24f5a198f219e7c88a92172fc3db129e044e914663ac708d8101851e7c53fce79d32d0e6da74f2ccd1d30ff +ae95e1dbba8b9e2c8dfbe1c202e9ccfd04fa396470035a699b902fbd86d5e6a31732a7c8cae00b9a4f6e51c8d560c7c3 +b0cd058e77498e860fa20c5f8d9bd09bb249add1badf84ba8d1bd49e704b9b4bcd67a5c3d211840a2c8fefab3fea639b +b78e468d3a7da0dd481f333ae56534e2ef97587be2e259a458e25aa37952aed1cc5f835640f812d8052f5bada8f57b12 +835de7965c6b26e7ad1b92eb6f0261d1f376fa12d61eb618d9b342b597c9c117a5a8f6a36269aeea88072b4641e6b5bf +b4d0eb99136b3643468c9c48a20fad62785a60fbdd3c054efac4bd1fa7979b4c9ca6c2c0b18069c0912bea2f19832790 +a00c47315dc0700a850966836a95f3cebfde04dd094bde0742dee77b89a05b5ad655921f86fafd1e902938ff34d4c58d +ab13fa0afaa92229a71ee91efae6d1b15f14b6eacefffb7401d41d0d6db24e24a8dbe8ee19b4680ecb69d2a0cb4e84e7 +aa56c0fb18401210062dbc653df8e3732aa8921a1280e9737e99b26a0100a13a9cba8ad0317a69bba16193362ee0f030 +8b410324a6406b345df0fa25f541ac20b7313fa55832752f70cf4c79f43b0bd3d5b4cdc447e6ba7bca08d0edffa8e29c +893362241ae412d9e5df46506407595c58ffbd7fb1fdaf0694c3432470599291238997abe118bf7737e56a4f5c9dc292 +921618194a756be81cb49d6357cb392b32cc62d96c8ffb7e16d9659a0f226a0436bd378da7b835054dbe0de2c6372ef2 +94a2904f10994928ff5367b777e1430047736fbece33442cf452018bfdeae62e84cd75cf80f8468285e347d504c94111 +b4b81545b767f380bfe10e0fea9c3cc62ca8db40b43c83ffb245259378731298e3eb6c3bdc3a16932f88f5d8a86edc4d +936203c2453ff01c6fc635e4d54320d69e60047d805daae3b75633c2259108497b778f011e5a057249f11b2b888ea76c +b90bf6378d29339443c3f2008b1e2b5f0345f86e393027f14a295e583bf6e6c2b10f54b6dcc42079ff0d356c405b03bb +916913f550d327de2d8d6c7723dcef2e3869efaf95fd963d95c8980b97748c61ad8e2e629cead8577266d93fe39203bd +a033c6f3d5ecbabeb83eb363e54e5faa7ed2d7f4fb771b161762c4f003eac4e1afb236806b784baf2222cad54e2d3cd9 +ab289d4a5771147e6c29ff9ac2bf65d70081ea6c6af2d9b728c3c144574a31b5fd8632af57c18c389aa2cd994938bb0b +9488da2019ff13e290eeac132b491df58b5b7b23c2898ff1a67bffd7e9c9464c39bc8177a57950fd28589e3d9ff9c6c4 +a5abe42b2e0891851440fb2aa6c1d8a86b571bce8b80c8e9e2692e5cb6d45a1b2f055c9fc4c74a7cd292871604129ea9 +90bfef698e83c2ba4dc9304aa01edd274169a978b7154bca518daef394f55857d0d1922ebef3d91fc5ecb3b895d9e0ec +92328f1372b6406ec80786041b6d57018b8507e3881a08727aadfecfdfcfb0824394cbb1150117ac5da5d71b89e895ae +9719751c5f7a65ae2bed8aff7b4b8c34539ff011b259b7ff54f63f9d987b3fbdce5c99534ed561aadaf07bb6e939e208 +a151816774aa9379fccec21cf212429a1c68cf91b055cbb9d931f461a8d5616c693331a11ac5c6fcfbd17d84ee0b44e4 +a72977b1285618a45943ad00f33f37102e2885eccd2f76785254eeca495068fb1d8d49865343e9e8313c6c2c3b2024da +a6f5ad2e023a1585d90625c9f7094f0e8851c79f0eede8ec582ee8e063407cc5b8298e5fdc4c786e4fbbcecaf33e787e +82901e008febcea0c0a14ae21d985a397630e18ee6e346f4a449f23be228e8f338df567d30211a11180b94fbc5204bec +b9b57fdb8d14d1be87a25f89553b3966eb7869e0519ffdf4cc4d51f4cec90d68f7b81cdc0450e04207276e9c63ace721 +a06eabcf43585a001448f3dc30411f3d5b74fd0a695c81eda9981842ba2bb0081d3f5a8360aa18b6d43ef13ea78b293d +926fe48a7e8f07559b7237beff9504476dd97b5b4d67acd01a3633358a6ba4c7abed5c87683a11209aa2ee759888e00e +a716cd3a84a963e2a5a46145b6ef4ebce705de52bf2945c374152a1e41c228a9c4eae0b6d1e222c1eea8b9c13c002177 +8a9b5985df6fb32cdb06ba1591a977545444478f2fe985ed1b10de61c630f0a4693c2185d63f0dc0256b208072c43b17 +a8eab26ae0ebcdf96a59fad1dc2d5e83b94abb2ea1774b607023f9d9e0fe065853b1e2242e794f989a80a47f550c0bd9 +84adbf38164cd04f3d770a7f4b8eae7a5d25b4a803fb63c02b95b71b33e454319c44e07a760d22bf5f58e7e372d09a16 +90f443a3ba1b9129a0bee400b5b29d42e50bb2aa56b0022bbfc3c6f8d69db40299871ec7c1b68421cc89e1af6b13a39a +81c5a94b379eb98c494a8d0067c748ba47e87a2ada0105202ed7651eb4e5111a0cd8569b06ae68d392c4fd74a37833d2 +8f92324b14a1549ee0b186073a26691088e41556d33b54258fc6e0b000e9624156db4e97861a0ec22960e6c47ca8a1dd +8b021cd0fffe055068cc460aec3cc455952e2ac32be5fa060e0d1b6cf30ed15381618f801249e893b1b9f10dd82077b0 +b3e9f0dcb3d6f0b138f589fa54dfb01f849890ab97016372d004aac55103f363a64bc0e606ddf75430f1534a30fc522d +8fdfe64af891db89b25daa859864d479cb7599486bd6f36e593f8f2f839f942261ffc3eed5001a93fde44cbcdc24c583 +a9e4554373c5073e135874e2bacbee69c65308eb0785532fec6a37834e8d0b437b77a2f11cc63c87d7183b82cd9b6bc9 +b4c47daca723ad7193ac5098cad4dcab654186ec5ea5c0fd014a3ac39726be954565a901694ba211820c011fa1c59e18 +8835427e86cdceb4c11cbea331ed724e4e78af15e3bab5be54f6b926bf66b5d99bcc40dbc456d86342c9fa83a033c2d5 +8ea84590a400cedba047c2661378921a42f5ca0421da58c1bcb37bc686a2aed98afab3fa5e6ba3a51029390ef3cdf4d4 +b48551170fc479d69fffb00fae4fba301e92e37cae08f596db6f6489c3b7020edc074f9e8d7465b84e9dcef1b6b3aecc +a6f318b1eaab00836a330710e88bfe400395b3081485f6a212e3cba9463f6fe7864ba4f71e57a411ecdf2bcb4d189f96 +848d5137a39999141a79f4bdf91150796ba36352d8525821bf3bd6e070b352792d79147341b8254dd60fa8c36e9e2618 +a8526f8904b1eac4ae2a25534aa91e8031e9aac7b8f58d8f49897e920c36c0232f4a30aa6eed305deb0f7793c115b267 +b8b6a727c44c37a8388383e959d195d1d0e51a657d4ba360633d219d43c5df645383e2406c25f1d418e72b862c3a6e9b +92e64adf65b42c978f36dd03ab22ba983bfbb61944efccdb45b337ceb486beda99818bf20d32a545503c4572bb0a4983 +9653bb83df66260a0bd059cd4244ef7c661b089e403d26ba777d2090783ff31f963f5d3a9c125b1ad1a1d19134f3fc8d +a74e72355e71ae5eb36dc75191643500ca3e67f18833ee981010e7e7e60a68e1b01b05901eff05014b9ef29aa4829f45 +8b2139a5da14524cf6acc593144db23db424b95b8c7041d8f6c7a14a6725dda1cd09c42bb3ae26a5a3650affaa742800 +a60ddff4300ca44a7c7a00a1f98441ad1438e07c30275bc46551cee1b681926d2c825cc8f90399ee5f36bb9fbd07d3dd +a04e5e9958867a5acc15fdea0d88951cfebd37c657102f6ba1dcdaa5e46cf1c823ad0d98718e88e436f260b770599102 +95e977abeb70d46fe8d7584204770f14c856a77680607304ce58077550152733758e7a8b98b11b378540542b1175fecd +8c9ec93ed35a25ce00d61609e92d567459a45e39922ccd1c64ab512e292787125bd4164c00af4cf89fd3cf9deddcd8bb +819819ad0338250d9c89aceda9e217df12ac54e940c77fb8420575caa3fa78930689d0377ba88f16d38179a807135dc6 +8baafb379d4150ac382b14a64788d819146480d7a1dccd3deef6889686ded375900f5df069843ef14d754ad3d7540401 +ab827236996bb79b447714c6993af941c5ae66248df4d9a6f3650d44b853badb5c0cb67804210e07a7b9d66ca43092f6 +927656c3eac8d2eb575e3daeb77f9605771170c325bee6aeade10c083d42bd8dcbf3bcc3d929ea437001c7cf9a95e2da +af22b212d5ee44fd4197966b9690487c38a119cd6536cfb8c181f38a94610dd9e057f95774047a446504dd96dd11e326 +a44bd94b9e01e3ba36340f2ac2201ecb477495d4f1fb6726a6b439302deabb5a35d237c6a6aeb7e3b0a65649f8656716 +af367aeeae3bba14fbdb05bcc1a521000dd9d37f5c34ae56fb306d3dfda201d0329a8b6e89d98e15825cb3c6bfdb1194 +abcc4fbdea43e50ded9e2fb01464f4e87fb136e960141e8d39214f92794cfab5634f22cd40b18d8c0e501f2307aad23e +920786cbd674348b9853689915dfcab02cce2a4596d117962bce36aadddf4bdd143891e22f2c8015517039a64e8aede3 +8cde63b9bd57cb3ef743f1f3e8250669eed739e5fbd68c500a3cc0c12f93862a69aebcdbc69dd8f476c2eb307f572a53 +b967e65a5f1cd8d5d570f5e87e7e186fba51b9504f8e466392a76d8a971fb91fd9b7565bcc1647f50d7d15e48b93bc95 +8d5a87b25fedf5edd57d870304bfd9081dc78c3e3e3b38b997260a92edac7feccdaf24feb51822d2edc223b70bb4ed5f +b6cd5d340a57f8ec73723c4f3ecd6601620dc8137a3e75a5d3c578bc79a9cae86b379950c644dee2ff99dad780d025c1 +b6f0a8e754b7f52a85a2a2e6512cfd017f7fb0418d19bb318308951c4e242d3c65bbcb9748da9cbc91a738f9ca577332 +a89dcf7d410bccec385400dd96b1cc6af89026a431d0f531aa992cbd7bc8bfd7c5f360bcb665bda1d72efa17bb982551 +97788e7522427a46c4b6258d15623ef7a565712812fa80d001e1de8dc1791392702f3fa3cce5a8cd1c5755625a0ad10a +b5338fb5e137ff625b27c5148298f27ce8f493e2527c5d0facaa49f29cae34580d0d6c3c1074a2e46cd8db3f56004ea9 +8962f006d7b1095dd0dd132ffe7e87e328510c95ad893cf3b2ab21c177c5cf2c27f47d8856f87e9762c547be009d25c0 +87fee9ce9c26aa476e67e0791a809e0a06a8a98facf3faea730d438d3e516cdf75d645fa75c906e4e44ab9237a22c016 +b75ab972e1a1214bab0b38cc3e973d44bb233acda5b4291f5e110b6fb78fdcab93dc63f01168debd898e165f615be1f7 +b5a0fb52bca279d3853761a94b206acaf313df33ae6303d9b71edae90b66fc507adbc60fb11e758888736c81d5d80c0a +849b8f0005010e684701cd3a4e59e8c89e5fec59af6d2de5b6332cde03b865ea84f07f0b80ec3404380b0e148fbd2c24 +96e2b0b6fe78408f9208f809f5c40398100b2dac202c8c5c33c2189560dea868270a598c419871a5a2b67783354f6014 +b234b81f996142d0df2c719760bf996544820a03195a6dc0ff6a72543692f5a369bf63d1f0b477ef2fe7b3234e41f685 +b85e39bcf40da1a12a535740176f4de749a93824079deb5fdaa004f3282fdefaf5275e3418c88c419bd42a3dd2ed2b3b +a27279304b89a18a4e2b443246f2368fb8b15f46a34533179b6bd2ef683f6e98e222b7a32880b39b8fac1afa90133803 +8923c22cf15c9c1964213d725b337ece9ea854775a06f75f232c4859c7142a3942f418354e33066298aedfba3cb27e62 +b109f714311fb9bc431ef57911e2cad6a3949455b9f23255cd7edea35be629e07f845fe53e2b12a32305ee2f4f264f27 +b51e82ae5c7d48050e405897d0053e9ea4b2714d002e88f78c9a307cd50b9c6b3ee7cb86f86527be9d964b01895fab20 +90db256931c7f98bcf3bffff4d496739185e7a20f329ee7bffd4e0850a37739948ec745285703967f4ca50ec370cf68b +a0485ac0445d88dafac56bfba2563b020cfc370f54c1606c89d12cfd8a4d1336d2ba50306e476155a6f5b0e0a1f2d092 +a00754c3462e74bda928da855bbf90f9077db395e32f03cce9b2955546d900b72330d247b7d607b65e130f5b0d883de0 +8547d56727c3ad8b5c8ce622ed9ad86fe8cd78e6e4848c9845914b5063b17330bd10b46d8d3f18f83ca09ecb28d1afb2 +95b937b2a979bce0e159ac75c7d5d659be8599c92305e73e942aab414793364a3ec28c7c1c8491a5750ba84a29828d8d +b011e150f0294e45a0f4c69409999d0c2e602449dbd67ab95e8258466687cd733a0329083a31b03722f4e2580ddc95e9 +924651a733ad5e5d9adadad3ea6a6babb8e455c8d5f2cb5bdc83fa422e7752592190ccedaa827b866861e73506a6968e +a4d5180122f8e31503ae027e54da50f72f5cfb910a6f7309bd882b5cd666f454672591f1f20e461e182a47d03b47052a +ab19ae659c4f73ea3d21895269dbec583c7029955a36469124ebe295027010faab56c4a475973497f28e9a77c03b8fd0 +ae7ea1a803d0f439e91494f8f35fc1167dae23834c0c699ffe65d3da8b09f8df5a53195a99ca7b8558242279e69578fa +b9d63cf0e30f9800101b43b980bcd2f229758e74b21ad5354866b4e684791c08a184330dc316228a0d67fe0210f2bc4d +8c41629744391ddb96dcbbf9cd99b13d36e57d65962e0aeb92ebccf1c4cc769626feb3ec0363def08eceb102b3dd4ad6 +b2848ff24faf9e667a8c19d050a93896e9e75b86595f7b762c7c74ccdfb9db126ae094961fee7f5d1192776c1ac1a524 +af013bc29206743ce934d5887b8d0fb3667c89bda465d2321835a3618513fba6a459dd7566268220ffce7e0c97e22b2c +8bb799e36db1132da8e8b028ea8487dd3266b4628c56dfae4ea275f3c47c78e3d7445ab8d0aaee4cbf42148b3a148175 +ae2b81fd47c038b5195a52ab8431f0d3cab4cf24c4237252d955aad2156adc16dda9d3270157e0bfe5a44022e5c051ef +8e0129213b1698d2ec6df132356805a8633ba79e672e586dfef664ffccca71834253ba14f296da962651fcba2c002622 +a1ae30b500ae77cd9bbb803d737b4a5991cc780618ac22b5cc179efd8fe10afb8c135457f2e7b86ded485ea12eae70e5 +8a39723077b7c0df6e3bf6548afa3910c214ee275951fbe5155a39473be98099626ea14d844630a6fa90292b9594665d +a628386c79b61aa7314b01d9814aeec20c2a66e3deda322a39957e7135c2e52b1da486d1b9cd61c87afb22c1d10f6462 +97867f469b01249820aadd9a54e12d4fdadd4555f2d530450e1f8f6d2dae57360578e2c2c8ba41e3b5950df596537a98 +97f192d0457c217affa5a24267dd16cb4c01de8fefde9df4884e1906d2f22e73382dcee6c7d910bf6430bb03f4a4f1e1 +86d5b5739de8442dc74d0d8dc78e49210fe11bf8c6ff0f0faecbc47b64812d6b28c8afddf6d9c0212f1988451d6ccb1c +8ff3312ce9693cd4a9f4b8e75bd805f65b0790ee43fd9e075fe4cebc87185bdf161335049819f22530f54fed2779a5b9 +8dc41d85548bee5d51941d55752a500bde3c5a8f3b362da4eec307a963968e26605048a111c9166d448b8dddf6f53892 +996bdfd004b534151e309ac925fa5ee7801c9da4f6b4c43e156d1158b134535a2a3956e1255e0dd72ac2af6bddaebcaf +aead652704b788bf4983c8f725c644c327a6e9f6683215f5c826c09f82fd2e40631791f51d14e6aded91fdc018d45501 +991ffab58a82b98ed8fc7b00c3faca153589fe09cebf6a137ad506387a1ca4dba475b0e4a1b9bdad829f1422facaec39 +9652e6c4ae084221d6bad855ec0bc11b5f855c6efba67f644e0902ab790a98861cecc6ce047c68273c3aa7eeb2f4c7d9 +b88b816507aaeea6dc92b861eabdc96988b74d7883f20a4b30ba249158acaff3c50d261742fc9ad2e9eba888a8d59065 +acd028a51e16c07a10d2073b9d03070457ac5f1246365295a1359d015c460b92b4861125fabe6f114de8197045df408d +806d3cd9d02d41c49179fe7dac5b05dcfc9a205a283135d4f008d0771c58e6f963d7ad0f6798606edda718eb5c7ff3ed +b9b71f1657a6b206fc40159a941e127f252a7b324dea864ecd804f48c0ed86da9778a925fb65491204a92bc2a26fef32 +80ed67bd0e74350c875abedc0e07fd42ce7cb926f0f3fb1949c6ac73f2300b5a14a5c6f6ff8aed99d5ea5029bb8e7ae6 +9875f67a7a473714e4dd75ee0c763ddf88101532d9680724b3848fef69e218b04a96b90f88e0f4409aa40b9a21507ecc +b4a2bb1b421e5243e5e7576a0672dc19f9f70315a03f6411c19f76616ffbb70fc5dc0e57fd4ab85e24ea2261b7ce38ab +879723002ce43e6c75ba2246f51436efe3376242beff987d025c3c4476495af32d52a54fad5d9ec329a442b93bcff1ce +a4121efbefd9c3eb143619afa52a916f199c75024908047763b29466cdfc837c2fcc894aca63044c33c41c777e529b5b +895f637b497a9766714a3d9e3c275a1f0c9ddab105bf4c8b7e663f36cd79492022415bb4938c1a4849bda73106ace77c +b119acb8b161ce4384a924645a248a656a831af526cd337d97e08405415b9dd22060849c76b88a4785eb5e7214961759 +802e712f4c0a17009c4be6c1e5ba2ca3b82adcb68793ec81f4489b7985babd8a3873d544de63d5e5de0cb4dc5048c030 +ab111051e4651b910c68ecfdc33f2d99e7bf4182df68cedbdbbcac219a543e04d93ecb2763fe32b40c095c7ca193c331 +855c73ef6afc6bcaab4c1e6388519fd5cbb682f91995bebd558167715db454f38012291beccea8186a3fb7045c685b67 +a29d02ec6d9baf84c19dfd0eb378307703bfafc0744b73335550f3cd1b647275e70215f02d1f4ab82a5df4d4e12dd938 +91510a45b8a50cac982d2db8faf8318352418c3f1c59bc6bc95eab0089d5d3a3a215533c415380e50b7928b9d388ff89 +8286e7a2751ca4e23ea7a15851ad96d2cadf5b47f39f43165dde40d38ddb33f63a07bc00600c22e41d68a66fd8a0fa51 +a413d4e619b63799dd0f42ac57e99628d338b676d52aec2bb0d1bb39155ad9344b50cdfe1fe643ff041f1bc9e2cec833 +85524e5bb43ae58784d7e0966a664717289e541c8fcaff651541718d79a718f040a70aa8daf735f6635dabfc85c00663 +97f0d48a4028ff4266faf1c6997b6ad27404daa50ca4420c00b90f0b3e2d82ef8134d0a04108a74955e61e8dfeac082c +8df6145c6cc39034c2f7331d488b8a411931c8faa25d99c5432831292637fd983d4f6b1a6f55522b4a42a462d63c6845 +98c2060f67a916991b391e67fcf23e5f305112807fe95bdddb8ce6c4084126557e4c5f003afb32e30bc6808b30d4b526 +8964246b3c2b8f7312f0a99647c38ef41daf70d2b99b112412356e680185da6810ab8ee0855ad7409d334173bcc4438f +b56c2c416a7069c14bdb3f2e208c5a6ad5aac1cbe5b1faf99dc89c7141d0259d1c6250be9d9195500c4a41182ad2ec3d +b7864583a4cae3b1083dcdcff7f123d24a69920a57d6594d0b7219e31bf0e236682442b6499a1f6795cfeb4f5f236695 +a064f94139bf1b70d476bde97099631b1284aa6b4d87f16bfc65c075e58b2f1b3c2d057605259f806e545674a1169881 +80d1bc4acf14c0f487cd57c5d6157b7f38917e93cb660f1c25e474fcdcac3c3dfda50f6bcccfd6676bae25c4b6b5014e +8ad9a4976c4e3e282843518149fcf5d454240740f4b91466f6310b7216d23d70b9b47c42870293252f29f092f330967a +914197593d2d99d784c704cad7ecd3f0b9f55dce03fc928d13e1a1034566c4de754f1c2a5ade047b0956415fe40399ec +8d77f5e29c572ec3c0ca39cbae2072ba4102403265b3d8c347a00386da9c0b8688d6e3280c96037c300d57b3545f3773 +abfdf79d935fd4f06a04938d6580a8cbf9735f0d498f49677f26e73d3b34b7075d525afcb4f14ef1632cb375bef7dd55 +a97a8c446e3edc86efac7bda5e2e5d0158c909552a3bf86151df20ece63b8d18b608f477286fb1c7f05605ab7e6a7c2c +8618d946c7fd62486551c35486fa466bdfcdc63c941e4cff5a01fbbe566b7ea9dc763cbe73e2acae063060b619a212a9 +8d03ee468070936004b06acf64b868963f721f37faa09887f8a82c155ad5c5732572a6855b531db58af03b1afe034a18 +8d3247f75966ea63935ef6049f7c889c1651374adb446f49499fc9191dbcde7ea33cbc1f1e2d3d1756b6e69870404643 +afc853c3a3facb4ba0267512b8242327cd88007cef3bf549184ee891b5ddc8c27267bae7700758ad5bc32753ebf55dae +80df863eaea289de5a2101f2288046fdbfaa64f2cf1d6419a0e0eb8c93e3880d3a3fdf4940f7524ea1514eef77fb514e +8434b5888c2b51d12d57da6fb7392fff29393c2e3bfee8e3f9d395e23ddc016f10ebe3e3182d9584fddbd93a6effcefc +b78cbb4c9e80e3808c8f006dc3148a59a9cace55bcbb20dd27597557f931e5df7eb3efd18d880fe63466636701a8925e +acb140e44098414ae513b6ef38480e4f6180c6d5f9d1ca40ae7fbadb8b046829f79c97fe2cc663cbccd5ccf3994180c6 +936cb8dc959e1fc574f6bb31f28b756499532ebb79b2c97ff58b720d1cd50dc24b1c17d3beb853ba76cb8334106ce807 +adda2116d9fab2c214ec10c0b75f7f1d75e0dd01e9c3e295a0a126af0ea2c66373d977f0aefdda2e569c0a25f4921d0e +89a5cefb80c92dcad7653b1545f11701d6312aef392986835d048f39d5bc062cabc8a9501c5439c2b922efc5f04954d0 +b9acb52747ce7f759b9cdc781f54938968c7eeacb27c1a080474e59394a55ae1d5734caf22d80289d3392aab76441e89 +8564f72ce60f15a4225f1a223d757ebd19300e341fd9c1fe5a8ece8776c69c601938fa2d5c21b0935bd2bb593293272b +a5567d7b277c4ebf80e09c7e200c20d6cb27acbaa118c66ef71cbccb33ee3ddce0e0f57b77277ae1db9c66ed6e2d8f30 +b82e9c2d8df1cdd3b2417bf316d53e9f3cb58473c4cb5383f521ef53e0af961ef916e4f6557a6d8b4655ec01415231cd +aa816dfd2814c8a25bd2cbaf66303ee49784df471bac4b3188074ea30816f00f425234454d40d8ad8035aa925d74da36 +9919f384df20faaa2d226b521cab207dd2b62420d25ebbda28c9b2ca76a2a52203b2ad7844c1a25f5c75f005c5a83149 +b24a6aa35c2d0f87e36598b36224c64427cd69642b6f9c1bd478a62c70f8ee69f85028648f6603b4f04fb21355f2afb1 +892e044bdb1276b455eac2204be105e1821f987c2570494b1f32aa09506caba7ed343cd09b1bc126fed5e0fda3d0eaad +af0e01a3ad954dc048de18bc46bb1c4971db2467e839698e4dd05cd1adcb9261013fe9fd0cafb946c0b586f6aad86d4e +ac152f0a9ace425378daf02510eb7923ff1ed2c0f8d1deb918e4efb63655de1ba58c96438e9aa23abdf2431dc771370d +ad8c7419c097709347e2394195924e09617b47ac5c7a84aeb9deab8975f22155de0f70cf20d8a976551b14e3a2683a2b +808f14f67ae801536fb70a5898ab86e50ad35340cffd0648daed2f2c4564c9ad538034b2a179a6a8bfa27e9d93b4cbe0 +80a74ab7ce4769db93cfa695a166db95f0a9c47885ff826ad5d93310f36d6b18b5351c67c858b9837b925e85a1995b63 +95b88c3cdd64401c345828f4e4754b1a88b4875a14c08a668b90acd499b3b858842669ecd73a46c5d9f1de32ec1a0120 +8ddbd770b7b18a5917eb43926fa05004e819f1d1ead05b915269e4a86b53e0633a90559007e59f6705a3769e2126ac56 +ab6db5fc220754f19948bef98844e6e38dd623565d1695e1198040c228ac4fd863c1f168cac1d036bbfb718d9d8dd036 +97bef628e977c069e60c395a17740e0e1bc1828f5607ae7f30ce5a0c95f02b53af2ad062700a75212e462aa22c3c5465 +b68d465e04fd17ca98501e61eccb0ce30401855e98046e0c1debba71c2153d6a7a704aa36a6f12454696e78e87181cdc +a79cfdd048f4181e005bd0fbac0a8424495474956b58ce858d2b700fb0f931c406282bd33bfa25c8991bc528d12a69c1 +843f55fa0a6a0969daf2b48080738f30b269b2e7ec123a799e5b203c0b3b4b956dc95d095bc6550b0013918cdff8a225 +b683cdf2823036827e5b454bfe04af9bec1850d25a7a7a44aee7696b6ff0468b7ed6885a41dde2b8f3ecc4aec880c3d2 +8b500796e82acdc89778e0c0f230f744fb05f762000fee877bcf57e8fb703d212dbc2374887bdc2e7b7a273d83a85798 +ac35a8ee87bafecb1a87f15abc7ccf4109aab4ac91d357821e417f9b1474d196c38cc41cd13667f68d1ffab5e79a6e92 +b6e517739390cfed5b395d33b14bce7cd7aaece57fe79a7eb3cbf150dc10765c3ea9fef7976a21a2243687e6eea38ef6 +b53901eeee26692273365b789f2a60afc9b5f0df229c6d21b07016cf4c0e7985beec748aeca52262f68084393ab038e1 +ac4804f33d8ba2b4854ca3537bd8bf2dda72d4e94ff7ecaaf9bd3b7f098343d74d765471ef80072ae34f860b052cbfb1 +8c6a30a93f1dde18039bbdd1ef294552bf79856e20bce863e4b8dd72d906be3ff22468ff3610e06b5a7d1745dde7ead9 +88f0607fa3b7cefe20a02115572b16fc3222be86bb19e592c86c48afbe7e0dd523492b0c29a3bceb9a20f5538bc3134c +a660b801bbddad725975ddf9a8f606f76ecef831f954be224d6178c368e1c72d346f00c4a4c95c289b62d36f2af323cf +a75b9a6aea9542b698938dcd6cc2f6fe0c43e29f64b2f54aeb05d35fac73d41aa7fd750af4fa9333644aab8db90775b9 +83e1b7129d963d1cd076c3baa5fe422148e939273db173e4d59d1858a7d841eacac7fe817d15ab8f8a493bf46c2045e6 +9060a2e9c24de11f9c70e039b5ffe9e6d32f1ae39f3dda263610df2265d917679e689898e4a8bd84ad34613dca5e3761 +b42fc8b863a2af15e04d1fe6693c09b46007c0b8298973fb4762b45b4590ad7fe0aa758918b2fe5ed1ed0359754fd955 +83e6de7860fb256ecf7b47506a5e557d0fb0aefe57fb513c7dee2bd9604712d08ca26adca7ba9a54b712372a7c585a26 +90586e9cbbf71475ecd3e7b5753b286804dcce61e165502a82b960099e79272de8b7494b8877b54ae838eb5d0f71af2f +b2e4b0d21208f73b7b75e08df80cde20c4578e117d37092a490af82354e2afd3a7dbab46fa2d12fcb731cdaece69c2ba +a010961239bb8809fc7fb4aa08fa30d33a130f9f417ee9ea60f587dcc5ef4e1b7abcdcbf8e848ecdcb7972ef6af46e78 +8f511fd58d1e3403a5eefdc0a4ba6b8af848c7efddbf9575ee84449facde05ae9a24aa41a5725416467f6fbd11369c52 +b24ebbd2d4482eb618cea1ac4fbfd9ed8c46c0988a27259300a7ce5ce1bb256aeca0357828cbbc4cf0dfafbf586040e1 +b3ea29e9cca55250e9b7b9bd854edae40f0f0cc65fe478cd468795d1288cc20d7b34ced33bd1356f1f54a4291faa877d +8a8b20f222d9e65bbde33638033972e7d44c6a310b92a9d9c5273b324c4ad1a94f2a10cbce8300c34dbd9beb618c877d +b2436a9a647dc3f12c550e4ddc5b010e6f9cb3f3504742d377384b625fc38f5b71710a49fb73ffaf95b9856047c98201 +a13f8b77c70621e421be94c7412454adc1937b9e09845c2853ef72cdbe500e5c1bf08e3c8b8d6b8eff4bce5b8dec9213 +b25de8780c80d779e6c2e3c4e839a5a107d55b9cccc3ad7c575f9fe37ef44b35db4c1b58f6114a5f2f9ca11e1eb9c5fa +96ba6ad4358c7a645e5edb07d23836cbd35c47d9a66937d09486570e68da3c8f72a578bd2e14188d3acc17e563a652d7 +a7f55989814051fda73f83b5f1a3d5385cd31dc34baf94b37c208b3eaca008ff696fd7f41e2ecffc2dd586de905bf613 +882d0c7c81e58eb9560349f35c35e4498dcde7af7be8d7974b79d262304c26ab67ffa5ed287bb193d5f0ab46b4096015 +a607158f0c1fd0377a8ee5e9715ac230abf97406c19b233d22f5911ebe716967cc10425546dc44e40c38bd6c2b4bca2e +87e8cde50e5d852d3f073a43d652f7186bac7354612517cfaecd4a1b942f06fef6f14546279c0dc0262e2997b835b2a4 +a1c93acc6db9d5ee426fb4a0b846bb7a7b8d5915bec777a9fe6907246b0beafb8938941c8c79ed6082155f75dbc1e332 +b1e4f61457b86f76cd93eafd7536f72baf239ce5a62bd5a8085a34e90576b1e118e25002d2de49b01d6e9a245ee7d3a2 +a0435fe9a4bd1031ec5973a103ec9396b2ce9fd982f6d9ed780fa80ac06a6e47a0a6eb2daf52df1dc9292db622ee9fa3 +b66d8e8a1717e4bfa42083b6ef4490e090a73168b2912f2111743e089027be0a4945a229ecf5d0b5eec11b23f0e11303 +8eb764f26904eea4f4169be6e75beaa6a39e4eb524625a15a78befe3d8e3cc82692d9b135590c20ed460d6e4ba630ef7 +b7e4aea6bb09829e53fe83e53f49a7a331a6d7bf76e0073d758577e6d6fbe63dab642b23657355cad48896ad8715119c +8f94207982373a99ffa282673f192aa98d0c4461fb77c31dc4549628bd9687a249f1b3c66b1840929341e42516c5c64a +a9c673cb247b13e17fa5e616f0399b7f5c7ad043e143e44ae68855a840870ab3d2aad737ebcf74c2cc9688d17ef3a794 +b02635104dd28c02068985256975c0af783899eb996e37d021d9a35238deeea9e836760db21869be7b6c82aa687ded29 +b33bc0966389710812b5f6698afa3e9c84839a1b85492ba11e6ded26695260abf66be6fb355d12d3a8524966f0f89e0f +a79c0dd09506951c33da3cbc23843fd02d641fc24c640a205e6e8150240372847312b9381fb03c5d301fe4dbee8d0da2 +b74de6f3a2c502b5b658ebe8a9b7edd78afd036f5a2736aa06502863b6865d131b9e3542e72a86fa2e1d2db4927661ed +99e365def1452ff9fb4b9eccd36ff4154d128469ba5bd73e83ae457ab53977cf6fc04a5d05bdcde357ab539e34bd9fe0 +b4f2bfb95abb47c67870aa6ca38ac8f3ae1b1a2bed064b1be7ff90865ea12e4930fcf66429c7ecd1183fae4a01539386 +ae4bde87f36b912e92398bf72e11d5389e93b2de1b277d7ed4b6fb5a9ab9f71a959ec3bcb734c11079440fe42b86fafd +b826459e568efdeeb66688482b67ef5020787275123fd3192f979b6175e3b0ed59e17cb734a0a052bf13f0afc7bd237c +a99dd735f4a7c85cb23dcc7f4835f9ab32026886909aaa95876b98029c37dc4d621726c872d3a9e50403443c958f4029 +99083545034768010988bf8a9f34486c2cd9da27a1d10db3ab86eb69a1dd9c8ee723e7da4ef2aced63c1dbd53ccc52cb +8ac3209349f0142546c714ef7e9d1b094aab5469b8f080c0a37cb0362da5349e108760f272fbba770aa468e48d9a34c4 +af5f48ed74b21e3f2c1430192adb4b804dc873cd7e8f07130c556c30e7b78df0ef5a14b205368848fa9185e5a68dee0d +b8b741b65d68df89443523ba74203226f1e0d13bab073d183662d124e83e76cd318b2bfff09879c04d81b577ac895638 +914abe4282d11176d4f2f08c6f15e6c2d0cde1ab4de00bbe888015c205f51929d97296a0a8d3ca5641f085a29ea89505 +83ec306b2a9a6780efafe799df90b1aebdbff7d47921a136ea8a5648b9708a97231245a1082fea38e47ecafbbe000528 +95d6b58d70b388dfcee4eda0c9805362ccfb60a87603add565b175b2c14ed92999dfdb0d3724ee3e5d30535f282641e9 +97eeb4de607c8306e1d4e494f0d5db126d53fd04983ab5674ec5996b971899e734fa4011f2c889da21154ea1e76dbd2f +84ff21977fbd873ea06bec444d4ec9ff0e3902edc29dfa25f3bed269b3709e3116e99dc06cc3e77f53c53b736bf8fc29 +8ecf483874a040a4a1c293af145094fedf203a5eb37c3e165857e108cce3e1210e0bfc0f26f4ae5e2194024929ba034d +97d9b92b2ef34609d69402167f81bce225ed3a95718a3b403f702b93e96a121a8f7f072d0ff47e8b25164e204d1576bf +ab87c39cca1803b4e84b32e40ff30289e3cbbcfbe16a70f9e025643824752359be1f10c3e5398df402b6fec64d5a3537 +af84ca57e6944332884b5c84750afe0d5950015e127acec161853d55d48fd864c7da8d59cc5aba4ceceac650b813fcc0 +b1d23d98edbe7089ce0a8432e0eb3b427c350fb4bb39eb2aca3c2bef68c432078cb9b4b2c4966255e00e734fa616638b +8e2b5252e0ea96d40835ebfb5693af49946509975682d68651396d6bb1463f09e75fd0afa04ccea49893b5b9c3e77e40 +8db25e762f1d4a89a9a1cbc61c01698e775906bc88a921b2905735457a35df9ab84bae12e1b1b8dafadd50212f1acda1 +b5f7cd163a801770a4034e2b837e00191b0ac63a2b91032ae9a99ec182d748798df48a14644935fabdbac9a43a26749a +998e7232e5906843d6272d4e04f3f00ca41a57e6dcc393c68b5b5899e6d3f23001913a24383ed00955d5ec823dbd3844 +ab2110a5174ae55ebb0a788f753597bd060ee8d6beafc5f7ce25046ea036dba939d67104bba91103d7838b50e36703d1 +a211972a4f6a0303bec6c86f5c23c0d25ab4df0ba25876cbaad66ae010b5a00aa0c5daded85e4326261a17a563508a25 +a49f53496a4041a01e07f2c2cf1e84e2ee726917bb103fd267451b9b7bb1331c0afde85a79a55409bfde27328b2a4745 +934e915c67c7fc47adeabdde49f63f04644fe234672003be2aa0a2454dc8d9288f94293478936a450f2e3f249d395b5b +b6e69e9d6808ff7f60a01b7aea6781495d7a20f5b547852d3f0af727a7434209d3015a9dd04cbe3e272918e32e345508 +b348d3462092b5c6fead7e515e09611438db8d69650876dd3b56226e303252bbeb9e9f3b888fb911445b0c87132a1d0e +8d6510334a905efe5a32001e167f1ba06f9bc4af7ffbf11b7f7bf3c0076b5cca373d8c47e98c1ba8755bb22632bfe0e7 +a2d5200f20985dcd473d119ee97e1c0fafafa0f191185bfed9cac429cef8198d17665dac4f70342eea66e6e4a7370d58 +8dd7eb6b1841b3f33425a158d33a172b79b2dc8a01378e4174e67a1a4c8f4b887f02c7c3a8f354ed9eac718155bcdf37 +b16ca19388642f71afcd9f7007b490d82f83210ac1a989da9d4bf4c419de07af8c048cd301ec7e01b9d06abda7c169d5 +93cb2d847d1a88de8c1c9d5b3c83efd0b7afb3682942bd2c8ab5ef35b33dc31a097a3e181daab8630d4e840b677216dc +a8b648c769e77a7b41c0c689fe2fba9bc585067e004bcb1732cb7b1618e97b317781c36c23a00680fc780b58c301a789 +918c321100d57712866bdae84edf7e42df30a32853af257e0cb4da028842a43b49e775f3cecb85cd817269c728de7319 +a7b0f6ce42e00c519e69b2c78fd9b75a2e7103e5892d3c1afd70c9b5b9e706180a4bf73dbb2d3eed52bfd521103ec5b3 +90041994af3322b010891356afd8115340bd7fd7ba328716fbc4fe458236c8cad8c7564ae473d6091ec3a54bdab524c0 +acb1ac83809573846231f9be2dc5f3e986cc36dd9574a620b1cced45bad0b11ea957ce8c6cbf964a0af916781c574f05 +ac54677dc002698fc4d454c7beb862ad085d0514f92576f3485a44c0cb47afb9db2c085058918a3508f9b3de0137d97c +8dea56e1bfa150e442f8484b2952b116781d08cfa3072d08657cc09b0217276efc4ab6f5fd726bfd826f6976ced8da29 +a2b09e25baf01d4364b5205fa0c4dea84ef8fe03709113b034f88a0f0a502a81bf92c1d4641e2ac9f3a6f4203d3645ee +b95fe37aa351b4292691a9c2e547224c37ec2751a31ecce59810cb2ae0993da6fbe5efe0ab82f164462fa3764b6eb20f +a3498947e91a3a540e86940be664fc82f1e83ff41a0d95eb84b925e820602a41b7393c8b458bd4ebbe574a754586787a +aa2516d3620c832e5728fefdb1af0be30c871cbad4b166a7a4565af676e73bddc2f2f51acc603b3a022056daad2b330e +a9251b56467fb55f64c70729e2ec77a59d7eac79cc0b4b25ee405ac02aea46bf1cbc858bc773934a6d9bea57cb528185 +ae8c0a4ca7ba6bdca8764bac98df0581f00358db904e57867e6ffdf15542e55f7bad2dedac152ef88038b466ed901934 +b0881e27e52cc6a57c4f3f278dffc7f63a9174b68bc867c16d8a151d9cc4d0aeb703d1074d1927faa9ffb43e10912c9a +b67138465d6654ded486d18e682f11a238d6a65d90f23d6b13eb6a1b7471efbac9ada6345dfb13e5432196d2a256829a +944c69a6f1126edd38f6eef60b8a5bd17147ab511e44e8e0a442e87244d8f35236ee0b8d3dac0631f8598f16486a5f74 +995679dbe03dec775da26708cb9200dabcad983825f1ba601eb9395f9da350ca71e8af61dbff4c668fd0eebac7e4e356 +89de362f02dc14de6995d43cdea3c854a0986c605ba5eb5dacf24e3a85983229bc99a2fcf50aba3df59f0fb20daffe29 +84607f0e2d078df22d0866285614f5d78cf7697c94a7d1b5e02b770101ceecbfd53806b377b124a7320d9fed65000b97 +93e3faab60050dac76ab44a29bcd521813e76ec8e4ae22712d77bb489bb49f98f9087acfd6a77016a09a42ddedab2d73 +b7d64a7a35f21747b8e6a874be31ba770c0d13cbd41448411994e8cebb59591295a26bacbf74ee91e248a5b111aacca0 +8dcad429a2b0d66b9eb8c1c3924d7a72979727db6a535526a3518bed2a9532d12aad1c5a778824ca4cb98e3e513f85f8 +980882895faa347bd2fd1dda7b8ee7ed49e69843afe646f677b371eecc7a10e0f4e40bb55f28995a40080df471876816 +89e8e7fb51df79971e2f7bf65783614abbb0d7f3f1b4a15d3f0d160deafa7ed1c446d9a5ae1a77160d4dd94ceed8af13 +93fda8d350392e9c4d4ffe6534f7e7be53f32483d9319093e8436fbb8166a3c01085dc858373e65c7f4d014e0dc2bab7 +897521a87b7ebf7152de5260c0875e3c7df1c53e734c672569219ee6f9bd196c5ecef159b6a1d3b7cd95e91b9b8803ff +b59affa408a0f7bd7930fa3b88750fd043ce672c10a3adeba95a12f23f0dda1793f761a86f7409ce1e6fd3b3b7195381 +b4422ccc12f4fe99c530cda610053af9ffe635b633d52492fd81271d1f6f91b87171d572d5bd0e46ff63e221fb2fc4a5 +a4542cdf3346ee0867c08d630c2aefc57442f1c05c0eba52d223bfdca5e9d0bb80775cff6ce2e28aa2730231fd7b1bb1 +a7d297bb09118b914d286e5d1e87bdf13f7d174b988e38fb5427902e8e8c674072f36b19055a1070abcf357f8668f35b +9213b0ae24b7cb43ae95e25c09fead8bdbac55141694137d67eb5eab5e90a348a13d4d4d2cbc6436fc4f4f9f7334ced2 +8aed71a0d116d832a372b42a0bb92a1980f3edf8189bdbaed7cde89fc0418b3ab21a04f5c6e1d3b8edf73f1f62bd6b15 +a6c47d77d714c285c84c6b9458cbec5e3b191c0502dffd10ce049cf1ea27ddf868ef0cff13a2377289fa6c932b8e4f28 +92f45622ec02483f2c1e07075a6695416d3768c8984856f284f40734346d56cb5b3322f20c2c9f0ef8e58ddc294a309a +af6450d02b79ac9fc79f35655b58fd3619cd5d38c5317564b453f5f2d79d7a030bf767e399fe01b658a72fbd2cac2356 +a3c01fed5240eb8a61ffa8ff4a120dbcebb53b8e19845949c77fb4f9b2c3dd52c7001df6219ad2f76c785a4ee0f64a2a +af3136bfe8f774187bdf87555a1ac505322a956229a285d28bab1c88d4f4d12245af8dff35914a62e90e49f3dce6acb0 +b20e21d28444fc96737958cd951858fda324b924b4d3d08932540fd4b87150f053db6985b96903906ce83dde0578cbb2 +b7978101071268d1f485134b4dfd1e35f89b82c7d99ae91f58b6745f5e0273b7e06f3b23009033ecc3e41b2e9e85219b +9104b7d75245b784187175912cc0ad869e12f1983b98e052710fb33663224362bffd69ceed43e7d4ad7f998c0a699eb7 +a7624cd71b92699ce3fde0e747976ee04ee820032ac45dd27d769edf3b3379a4b8db358e50c9d057c63b5a9b13d76bcd +9354a76f294005de8c59db10e638ae6e8c6d6b86a699d8da93143da8478d36116211c788d8285d8e01ea6647dfcaa1aa +b85935c04cae14af9848db5339ab6420122c041075ec1549314e3c9c5a610d9b794ea3617c50ca7af6b4aec8b06bc7dd +ad6835a62311c84b30ce90e86c91c0f31c4a44bf0a1db65bf331b7cf530cca0488efaac009ab9ed14c1d487da9e88feb +80339f0245cc37a42bd14cd58d2a8d50c554364d3a8485d0520ea6d2c83db3597bf51a858b10c838bfc8b6bc35619638 +b370420ac1a011f6d8f930511b788708ccf2fe23ca7b775b65faa5f5a15c112a4667ed6496ae452baf2204e9ce0dbf09 +8ceab3dadca807a1c8de58ac5788313419c37bc89603692c7a4d96e2311b7fe9e813cc691a7e25a242828cdf98f8bbcd +ac1526ebc6bd4ac92ee1b239f915e494d0279fbd065e4cab1f1b8a1663f67daa89560f6c99bbc3e63fa845520316d2e6 +8240ab0bc36a29d43ec3059c7e6355ff39567e135f93b243145d3ada97fd1c970743819e0d58bd5171967daec144e7a1 +a99743192a6f1967511b2d3038cc73edacb7e85f84b2926d8880d932d2fa12f5215592311a7548494b68a87ec70c93eb +8ffffc31c235997e59ab33c2f79f468399eb52b776fd7968f37a73e41949111957434f2c0a27645ab34c741eb627cd1f +8949d955309415d6d2cf6ee682ccd0427565142c1bfe43b17c38de05cd7185c48549a35b67665a0380f51aef10b62a8e +9614f727a9dac8ecd22b5b81b6e14d34f516db23a1a7d81771ddaa11f516ed04d4e78b78fda5dc9c276a55372f44c4d4 +aa85d3ef157407bd8aa74032f66bc375fddaff90c612470b5ff5d93659f8c3523b2d1b6937b3cc4201c2aa339621180e +86f8fe8bf4c262dc6a04620a848e3844f5e39a2e1700c960f20ee66d4a559a90141ef4e5091d0f32acb1e915af1e0472 +b3af2eb785b00588371beb3b49536b7919a3f2175d4817de5dcbf7fcc20c512852ef0f313327fd0589b10173f77b92e0 +8388703c512eea59190351f3bd2cce83ff8bcb3c5aefc114cccf9e9b3f78200d8034c3ebe60448aaf6c912f0ff8f0cc4 +95d0dbbbf08ec1ed3975fe7dd542be0a05156a2b3db5092825d918a849411ee536ed958201f74a5513e9743674d6658d +8d1a48802f1a2db247e633ddf61d3ef7a2c062c48dda59bf858916e04f56651a7d51e367d6535964ebf3ae6d2b21b421 +971436871bfe868f25247145a55802945409b3150008535b372c949760d7949dd2fdb40d9b96ae7473bc8f6e9b83ecdb +8ca431728ac0f156763090828a7b6d860bf591e5b9dd3bb3b7f3ba0ca74191f9710ee55efd32db7d18eab5b479cee8a4 +81e28f1a506e84c2b9aba1df720cb50e0b597b2c22f98acc34e710c934cc6f97dcaf33d589e845c2c1f6d8716d05ccac +8f43b11d3f00c41d16c9bc9bc0c44227c056bd77de4f1ca9a799418c5601e744f99066bef47da2d9088ae88eb259327c +8d330aa52744c08ef98cc5599eec8b9b4dd18aa01b803f1d1ca0e29b74f1aa2886ed0224390fc377af25852851fbee03 +a06f5b203b67134c685039ec2bdbcc787353e2575ce73a415db24a517c0c31b59d1de89f12b97cbef0219fb6a1e90a20 +9269a5f49bbb8fec1a387b5d105df88a027de615d5ca6afae20fe89b11746f8d23880db78dac238c955fc8bb3de18046 +af5074b3bc0656421c314547b45b5abd3045ca1b17f5e34ba39d8c1f7928a55d4ca5ea9c2ab59a55909b25255233e04e +8e7ee5d733c8e08f3fb7d85f0628de3de6835121672c65374905dc6d19e02fa2df14c13d5e9835dacd609a4df09abd26 +a9b9aaf83d31e879dfb8e73a0708801b4dbdb5d7c8654b27d2c0f5797ebcacc8d00a82143e2060f0917c9d41f1a03de6 +904872aa1c093cb00e1c8e369a3bdae6931c5b1ed705dd3bffba243dc4f42df3e7d7cf70303d513b34d2245743d765cf +8a4d6b3b1d6afe67383c66693f70b397e510be28e3d97dbc8ec543d699b6cbb0e72eb90a7f65e83cf9f7ef50fb18b128 +a914de13916e6a0dc0e0fefecb3a443cca80d83276513b70c22c6e566a2d41acbd33a0e2836ee09abeffd3a4894e437e +b9c408f5f05934b0aefab301ba22f8254c5ebbf5405b6aa788f76e4b328c150b395f441e3566015a0deb3eca89afe9ff +8d32aa2c81b2a8b89f347c2e0b6567b2117ddbb778fda8a3f19004b7f5aa9dd814b9b3ad35f9223715d2447b2d12f159 +8230e8b9c84cada1bf14ea6aa9ecdadd978d893cf5962fee6c7167ed21239210ea491987f2c8f2e8cfea8c140704ca28 +a5d7b6285fea51c6f21d0976a7c3a97baa3d733a201bfaac0994db6c65611d91c5fc0ebc2a7724ee02b371e575573649 +a54f00a9530f6930069f5e3a8b8b1d52ee1def0aad1763e3c609ec07f25410969b43d5943a94c235ed5eb207b33a402e +a8dc6e96399b81397734c61c3a8154e55a670fa25fa5854b3c66734cbb4ec0d8f6ba650ee3c71da3773ffc9e37abf8bd +8841fbfae1af4d400d49f74495f864804f043416c09c64705251d021b3ab7881f134a00b0241e61010617d04979d747d +95acea7ff4861cc969c1d8cc8775c5eae014ad6e2e0e2d0a911dd916c34ae69f53eef779cc24ff1eac18c2b478d3ba2b +a5dce74abcfb8c68031b47364bd9baf71a91db01e45514ab6216f5eb582ef8fe9b06aaa02f17be8b93392d9b19ab9c06 +89e111169e4ae2f4016c07c574a3bdacd8d2f359561fbbdaa3474de9bc24ef8936784dfe6fe0e29a13cac85a3e622b61 +a4c511af6bdf3892939aab651828259e4ef6ebecfdd503ecc14e61001575b313a89e209cb55a77ec19a64d29ada066ef +923c62156fbf3a44926ffb5dc71f7cef602dbe941a98c61f019a27a18a50c16b6135b6099fe04a2e1dc88a6cad989fb7 +afb9191c541b61afa0ef14652e563cc5a557842ce2afea13e21507dde0ebbe6da5233af949c998c00865c79bb3d45ec8 +8a1f0ad65cb2b225931f41dc53547d756111ecbf5bc57c5ee2cc1ffd61b126d0389d311ffe26cf06eaead95af09c5ca3 +9040b20b5ac2e1a9d30abf7a4eea1ec2db8f3077cb2cfc8736b37222d8d3937f5d9f421167086dc5551e9f0bd2522d07 +b6d888b8c6bd448dccaf99c3f690d47f802e134709ce102fb6f6fc68156943c0762be6f386338163e01eed2d1dd5f734 +b94f0e27bbcda793e4a272603b3dcc739d3bf3207798df7319f8dc9d37cbd850e3724bdd30498c929debad971950223c +9769827767be9d7bacba1b687289e0794c6fe630d33c9b607da1f6a65e3f34cb8bd65327d9287c8c5f3c8b5f6d3d133e +aaac72c993aa2356c9a6a030950441de42b2d746bace29865382f0ef54835bc96958b2f00237d805ee6a69ca82117c1b +a2b1f027d80c1b0e79bfc7dd252e095b436fba23a97a1b2b16cdd39fd39a49e06a1ca9a1345c4dbb3d601ffa99f42bdc +b3fa0ad1478ca571e8aa230921f95d81aed7eca00275a51b33aadabd5cb9c530030691d1242a6ff24e2d4cfd72a47203 +a43ed4368e78daad51b9bf1a685b1e1bfe05bed7340d4a00df718133f686690c99198b60031513328fc353c6825a5f2f +965e145711ecf998b01a18843cbb8db6b91ff46f668229281d4ca52236c4d40804ebc54276e9c168d2a2bfc299bcf397 +ae18e6efc6f54c1d9230210ac859c2f19180f31d2e37a94da2983a4264dbb58ad328ab3cbc6884ce4637c8c2390f7fc1 +83a9200486d4d85f5671643b6daf3d0290b2e41520fb7ea7030e7e342d7789023da6a293a3984308b27eb55f879ad99d +b925fb6ca83479355a44abbcdf182bfac8a3c7cce6cfc7962be277ce34460eb837c561257569be3cb28023208dea80dd +9583dd991b62ae4bd5f379ccd3cec72cfae1c08137ddfbacc659a9641e7d5a82083de60005f74fc807bd2acd218d0789 +ae73bc32e9ff5926e1e06c07a3963080881b976c9875777f8e4cf96af91bf41bdbed4bd77e91253b8ec3c15b4a6d3977 +b2a3ea90aa398717ba7d8c46743e4c487b63c5abb140555d8d20e5115df2f70d3c84a2cb9a5e0536b2d93d24f271b38d +91d119d3bf1d34cd839eb69c6de998b78482ab66bc93fa97e31fb9592f36cdfcd673f52366f8c8e8877e313b92d4a2ad +a1907e20120902cf68912cc3046f8806cabbd7673e80218814cb088e080dd93b5dccba395b13e0025f5755c183276c3a +b2e2011df72504065ec4c12cbc2137b95cfcd1355509671feb7b00dbf7f8d500476a49754cb7fb9219cb5cba7c8afe01 +a48589fb7a74a3dfd782cb3503e6294a81dbb6adb412887569f9408e9079371edbd9822388e0b7ec8d3297ba270f53ef +a203909bfe196ac65ed3e6800d577b6ca5c8fe1d40f7f925a43852951e38883f2ffd250a9e16fab3ed3dc1249650247b +997ac293722a8b98f7e819f8e6c2d4c5bd1103b82d489d8b8aabeb905e95450b9b75bd61442cf68cc957212ec1c55617 +9895a3de62395c33509b153b7820bd94fd2b011f0cac135fcf916482f1eda272ecc79f83a61837e99c3a3c4ab2c5c2a2 +98c2ece4d49a64ec8e06407a0585081003bcef88af35210e22eab91169f8f0c044d611494b755e5bd915804b1d857747 +8bc6dd083b36d076ddf0e0bb1bb87cfd059283ddabb3886f02eb7e27f1f0539b2819527b56b5c13436523c4603ac1d12 +85ab8b7a696333c82dd5e179e12b2e127e67d911de609ff9a03cab95cbeedb1f364aa1f2b5e59353e4ba0d177f996151 +a9478e214afa68c395aa2c7daf8ba1627feb71ad6d8bc7339734cdcdd5a42838e032736c28e6251c808d5a4875ef0d06 +8c53f62cf06a35321c8af3871ee4459768d0745ebf48942b9f464206309f42fc7b2c50f196ae1e43b664f0e2e718a23a +8ba80662f6642d8866e832ec8082a4204ebc993fc304c4b794666856de0407620131a18dc053597bb40a3de0bf8aca22 +8c8fac6b911785d1561a985580c03fb2ebc613ae33e486a92638aa7d4493374118d9a6d9d99121e29c68c3d67ee4e3f3 +90f2c793eee07ad90157040b30558bb3b0164e8ddf856389d6742cf5bd1c712e4c6a8e5678da70a8e9e242ec7864117e +954abed8f6d58896b7f6438c9780236c1c83b02d60a29fa7361559e619e5bc9d67b3646ee39ffafe2b3019bb3357fb50 +b79874f757a33085e1e751544de8fe3afbea92e0234f9c00254c2b36115a16ee46f085f22aa66e0c9177e5106f51b03b +aa148b287cf4f60c64f774282b421aae075f0eaa93a45aab4927750f47e2ef0b811d1846bbb15eeb2f293c80a7612e83 +a588d8825e7b0168d45499dcff6faf0dfe1ba4f090fdc7c06d50344960c0121f10ad109b0b9d13b06ef22de5a04eef87 +8f61ec93d14ebfa9c31731f9ef0fb8907505fedc79378e9a3f65c27bed4d74b41e129c97672ce5f567d897befbceec8c +a008218633f1da10efd01c155f7ed739faec902da6dc48e9f19ccbc8d32bb318d71806285cf2003de2c907bbdd4f8b22 +88ad82c66f7085632d7e348d69da84200c53594553acf5432b50dd1e87f410c802dfea91be3cf804e3117ce13103f23e +8498dba17de0318af227a3f9ed86df37a5c33f9a538be9823f8dce4efc3579e8296cb3b7200cee7c5e0bfd9da23a4b69 +b3c0342231dffe4c9bc7d9265597bc8cc4a82e2980ac6d1407108db5b00349dc91d5116fab51cf2802d58f05f653861d +b3f2730455f9bf5a058598bc60f47740117ba51f6a767e1134516a4e42338b513f377027acf8825da5c4d047a62984fd +816360914fbc9d8b865157bfab07aeb7b90bb5a7c5cd64847b1c3184a52266cd3f8f8f3ef99309ba2edc4622304bacc0 +8fd21b2315b44a52d60b39ebc45970a47b9495f42b88217ae057bebcd3ea0e2476c0c3d13de7f72016ae12ae966a008d +b62014485bc217a0fe892ef1aef0e59604ad5a868face7a93f77a70ba3d7413443fbe7a44552a784d8eae1acb1d1c52b +a905822507e431b35f56724f6c8d2e93b0607ed7a4533073a99cce2b7c1c35367382447073a53036dfdb0d04978ccf2a +81672e39c2b31845142963351de3d9cd04c67c806fdfe77467867463dbbd8a9b0e2400ccc55016e57cbedb02d83a0544 +90919c970ec668de8ec48a2a73bb75cb94f0f8380c79a7909fd8084df61ecd631476ddd474b27103c6817c8f3f260db9 +8fbe37dfb04bf1d3029f8070fd988fc5e4b585e61eab6a8b66caf0ffef979d3ed6a662cd99468ce98ec802e985da5fad +950939aabb90b57a3d667f9820880eb0c4fee5c27fe211ce8ecd34663c21b5543c810b3676111d079ac98644c75ee0ae +b06201ec3c3cfdaf864a66af128effee8ec42d25f1e173c1edf9207979fa52c871757000c591d71a9b6cde40f5001a06 +a79054e8febd0450c96ac7a5fd6bf419c4b17a5926f3bc23a8616f0cfbc2849d97470174cd1baa7c739b12615334b6b7 +81c7391b2a1844ed26a84f054b5f03865b442b7a8d614cd44805b5705fe6a356ac182b66a3c8d415132e389efac5f6b2 +825af1563d0fe53925ec9ac0df65d8211b333474e59359bf1bde8861eecd03f2ac74534d34b7e61031227c2fa7a74e1e +b60dd9bf036f1825295cd2014ef1f6d520cf729b4d6cee0b42cb871b60ae539b27c83aa3f96ee3d490ec27ce7e915115 +89ca43d5b7f3622b42df7887572297a7f52d5204d85e2e1ac6e5d7aa7f8aaea5e3a07280477d910db025d17cd2e7373b +b93a2bc9b1b597f0e514fde76ce5bfb6e61eee39cbf1971ea6db38c3ecb055e7913ec8cd07fb0b0ffae3ca345883101c +8d45546bc30266b20c6c59fc4339eb633155aa58f115a8f976d13789eaae20a95b064fedead247c46665cc13ba856663 +aa8eacfe00e8a4d9815de3f7619d9c420629ada6489933ca66a571bf6c044d08b391e0d9eec7d1cbebe8def1e7523f1e +b32fefc59a0d0319ccb1946b351ed70445d78d9fbb536fa710d3162b9659f10288f12d82b32ecc026d55f16cbad55441 +99c7c45c34044c056b24e8f57123ba5e2c2c039e9f038a66899362840cffe021733e078866a8708504cdc35816cb335d +80def162c134540d5ec071b25ccc3eef4efe158be453af41a310b7916c49ec0ce06bb43dfee96b6d77339e11587de448 +b5f2fa4f68f6a26bcb70d8eab62ad73509c08ee7aa622a14b3d16973ffff508ce6f1aff9ced77b8dcfef7319245cf2de +b4d0436019e779c789464716e1741c189e8945dab7f3072720bd9aa89882fa5b085a1755c48da21541f3cd70a41b0a71 +931e798ef672e1472f4f84c727a101e70d77b3a9f0c0803a5220958d6bbeb8aeeb56c769ab472a3d6451249a13a3f56e +918c10a84de268aa8f1ba24b38fe55ff907be07b1e86b4a4adbf305c0d705c1cf5f65ce99e03e11676cedc89f1a4f331 +8e55a8413b823715ccd92daee357cedd797e69a0e78b6fcdacb7318646b9903dfe05e5501f47b3c52e74055b9eb619a4 +8b329bb63e6c985d7d072dff4680b3f8b1217ed20543277386bd30ec25240d9dc378837dcd5cf4fd9548658635f4c537 +8c2be5386052b22986b33dbc63c5afacb6d0095495564ba4aa28fc8c880a3c78242fb083248d788ed928deb1e30a82c2 +83a2b7bdfcbd25d6b059f27218e009ecb5ecc4da68ead885e00216411d8222062ca42f21c4d9cfa19c31522080af677b +9620334d2633e85646b2e2fc48dc6c3f09c64ef1706ed78a3bb6ce1f6b274a727364df71e97531dfdcb392f70f27f536 +b6c84970ec04545121ec3b79376f4e45053c97e8bf2b11922cc2490a429c38735466097ecb81cc9d9692c74d2fb8abc8 +8e55d707dcf265c5ae29a32c27ce66f200fddb724faa5bbf145ef42280ef645fa2f0cc3cfe2db8599b26c83b91e077df +b910b96b763966402bbebd68a32c15a225ec21e1357fa298478c5981a4310e556103fef0c73bd8903e11c4ed2c065647 +a8fd933a0e9fe8c459809bd93b8ce153e2af55df94b61a1490736b19c89469954da8b72dbd072d798fc06fc3d7a3d60a +811b279c113828e114fd82c2070caa7eb089a46c8cabf865f9c77354a77ebebe0c4c6400dda0e66dd017cfc44d76851d +8ed03e91c331afb3ad6e42767e1b3e8d3a35fb831805ff1b5fd3e91878e04027ff5af1165a3ac295f1578faf2c83b581 +95bf53683d64a0621bf1ca6ee17446783f6c535b7a54d6ea57723487a215759a54f886597a55dfdd560424e368ab2759 +a9bea378768fb1d7ba365a16531c51fc1975f1c73caf2a0891da28509805fa84e2a8db7c6ccfbc620e9002317abf174c +b8308250891015deaf851c4e5a4cf4704d104f94064418488d7e3076d49f36240dcf6fdcf83f45fe8a1d97fb02e3db59 +adcda6b63da21f4074f142f8e7f3a2274f624c733e3a4001054a1809711529c61356aa087f73aed877a58ccb41d38d12 +b80e7869239ae26d1da2e6683f064d1dc93cf4a2b66e9439b3ad9b25324e969bf98014760d29e6b8de7ff152ef498d0f +8e9bf968911df3bb5e3a7655e9d8143e91ee87f14464d7ba9c86e1e31b03ab31b91eda121281b79cd974d9ed2657e33e +9007277e8335a43e6bc3c2f5f98c0ba7024a679b7156aeefe964f1a962e5ac82154ac39d1ffbad85a8f2440f3c1e354b +9422b9d670e997b7c919a429499f38e863c69c6a4d2bb28d85e36ae0895c620f68b71e39eba785e3d39a45be91507757 +926094e01132938000d82dd9a571fef5ef104cd25b4015a25e3442af0329e585aaad5472f0e7a69899ba2d6f734b40aa +95552d8057f7e32c24d69e4d6c51c98403f198a20c5be8826254d19cab2f84d5758e2220cea7e38b7c8a7a23178fd564 +8abcf8dcc8488bcc9ab23c51b9e7a0d91dfc7bebe88b7ed370ee68eceba643e939c5eae66a4aa5fe85120751780e351c +a91bf8198f029e6a4cf6f0cc39b629e9aeff1c77b8739e1d5c73d8c1d3fb5c8f6f23e27b435bf10b5b4ec1cf6a7249ed +b932d87ee3a4b81341511f90fe5aa36c571e8b914f25abcc33dd40ca67a3f6444fe9362c1434744e4af18d6e045c54a3 +a8e960c2be9b1d805d387b3ebe2134d421a65f1fd4c1b4cccdce78f9926f139eea78e3afb449b3d6dd19b5d16ace48fe +a7e2f57cce509fe66707eaba9b4c042c1be93fd6034a9b51d1d30c45c4363eac79d54663d525c9873ab0eec0b1cc4ed3 +aa162a31c2078f4b080199debf24494a8dfdfb9d8fc85b198a861b12a629c73128c55a883e4c2de3dfed6e0e1b83eeab +b5a4d075433eaf4115717a84b4dc37f843d44bba0bf820c92ecdedd5afb61be60f7708c8a151a678d9d5c0ae531bffb7 +b56ab96f7a463c0079e05dc766f3a6a31cae5c5044947734ebe0a26e01367c6763cc8de6c2ee2f3b8218f05bef217474 +b60792ac506b901065a8bc0180a86e028fe34b62ceae1ad640c759538ebf3a2ad9c8c927d662deed6f489ff3ff7813c4 +8c8c2cdf075504d12d441a58542e1f8e4bdf92b3ee4775e836b2734c5ec1e3df919b931386417d04489a1dca806c87d2 +8ed78e91e5c4a68894cefc2f7fa71f02e5e12d40f1bb74332139bc7be4d92c24e07d5ece0e82150ed474aa1337af4c18 +87119c22ff8aa31150bde537d863cad661cc5159b12f084cc319224c533f0deb28526ed8568d00a1441e7d8bb4f05673 +83a60ba5a9cccf22cebadf7318b706c9f29abd25db0e2fc1c802965351b53cbf316df72ee3e9b2d3ae7f3c4494cfdff1 +b73b6a9fdd3e7463fbdaabc9a885b7c82201ad867d1bced1c2484300a01cbbb3f1e21afa95d4c7cbb6cb983416b63b90 +b1d89ad16981ff9217708090d4017662d8838f21f3a3296cffe14590b533905fa06a20e40dd497bd291fa4dfd1bfc511 +8abde560083e071a402e3c7bf31930f537f67d2a7bbc734a7480b1b760aa712ebd1cbcb65b00e11e384e980222fe14a9 +89c731d8f31afea8bdc9c32527bdca257f2a840764d40f6e49403b8e75ae51017d505ea4fff91bf28b6f3a1bc65b8bbc +80e9ac8e077e86ad050ee73dfce268a69564ff1b8419e9c236d981fe7a5f0c2bc756e8603ec604b3b9e36da8fe10a49c +b4f1eea0f304898b1323c6382732e6f40e556bfc68af9ce73f6d54e92f5f23cc4f78eb3f43d578d81e7627fb40f092b3 +a0e3a8d1348f8f153e08ac4839232d75d1d6e81b5de184ec4724f8213baf98d3fe739a96f6b39d79a053b628c3a09981 +a6915ba0b52ffe4a381bbb8ff3791d9d3b848bf89b3bacbb2a7d2e5ae21f1353cdc304b3cb6e82416f7e604035c27d7e +b2c4c9cdfdd2fc9a340ba3ade9423344b9f429e8c7e20a8abbf26400376e312f3ae35d1c456be99dfb5c02fc8a36cbfa +9657d57ca0641825a0aa5687f3f87659d893f33aee819bafa5b1ca1db554811c1c844f971e278606e3a2f096defdc67c +a4ad24d0a557704ada24d8e27a15604bca28679e260b2c69ccc8e6cae5499866724b700605a90df7dfb35130756939b9 +b18d9ea6682f73a1f99a9a4fc98c38fcda02c1a18e8c5fc080cf935a2ac877dc5223fca273dcde190b906178d0fd05bc +8ea5fefad0799c885f50ff10d94bd0af5b99b0a446cd1f367ae5ff529cc47e09f3018115f3c0ccac2fa05bb65b84945e +92450d52e6c7d13ebfcdf5674d6761bbae2fc5aabc865d35d031b588c383e0a64cf69a73dc93948632e2b98f74a5ed86 +a356f171a98df4ec5a96d556eaccc6ad34b4238aafcf0e94ece27cdbb491749fc9692e78b84dfe80bdef2914079d34b5 +b918703a4d3507d266414712ba8eb7ad17da07cc5f952b5c62ef130cc6ed1ae3bf01237fc8848c179725bdddd465b301 +ad2b0554570bfc9d97510cf59bc38e10ca54a93649c30ac9919bd0255e43bf525ab11b74f78a51ac0973cd0c5a5dcb54 +a7ecaf4b631d179d32ac1632390d95196a0035e00da6c0e6e13b5c09ae44b15ae6c21538b5a31b73bc5f650ecd979b59 +a37704eb4d728df2a367e59fcb6c26023136230e37f3b8a2f3ceeb1467f5cd30186fc0116f98b64a8146fd2c5903e8d9 +b09373ce92314678299ae10ec1f93c702911beb4115c6b5ba6efbcab9c7afb599f59793912df70a98868bce6545a33dd +b52a878a1393094fd2b93f2d1eccabf2830ab10800ba4cc24dcc7849cd0978733263aef2fcb766a7cb575a7a99383db8 +8dac097e006fda4fb9d6d7ae52adabd9448ebc8d5bd5b38ac0c4ed38ceb510763174f7adfb0b473c38e52147ccab4239 +86b19c41efb949937d74a7875549ee5e997f9fdac7f7198085afda233cf74341a38d0ca3767c76cd35f875b89a35f78c +99f0d927e5ad25cd134f1c70b72631cc6b5cb4ddb86c0642b900464e33d971213a5239dddaf71f7a42f2d6d02a12dcc6 +8355c38806c335d747d4e97f0083fb96585677da18b409a85175ec35dc3f74671817b34203eb18c2f729717ce083ede8 +abb3603adb061a036eae0afa5f23d79c3b62442e0e3bcdeef896f88995585c1105cd3065410368456a4d36b5b0485a83 +9051c5c0011784885187d04749f774b9b4f6bc594b0e4e18226de79dedc4d7aefa3529c3d2c728e180f96f3e204d578b +91888213e7d321d0bfac884edbd5cb756b280753bb5f8bc6acfc208f525757beca24bdf86fc68d3d8736ef176a960b49 +91258bd7ce6e3b7516fe2f5391a368d826da299e0e99b1f82eaa44b62b110ab696adc92debab8ba098a52f38dfb3c5d8 +96e3907340dffa9da3602d3b94bacff7e1bb8649edd3b9bbd06e1bc6781e78f91ababab12c0b9be7c66dfedc7001b66e +9513555688fcfb12ba63952ab36a67b36affdd71f7b843e8eb99ccbd45421698024608233efbdc905eaeb26b334b33af +9913ca9bcf11eeb408da02e4317c5ca0010fb2f4490b282ddb758001c08b438c3b35351a8cbe10b7fffc1293ccd22d4b +85dc2471860ebca88e5a2766161fdd77f926d2a34825d1134a30418f91a741759668e32fd1e37c415d07ab5824338e8a +8b128917e828a0b5eb6fa8ed72b52fae2dfaf74febee69a2e2f87e8df702f0c5bc0fb620c8d1d2a07f35a15ec9c0f5a8 +964c39e7840c130b01bb481ae7bfc92682b0f124c9c383f9dbf3027f2249151925f4faf36905af476a54778d69da3f48 +80671ece658cf850e522d46d25678f934ce6df043f25f8707235125765d40c2eaaf39eda6092f75039b22cb58bf2c29d +ad4bb0e79fdaa340b1347a46b0f64e801c72a89770dda0a6e4bfd35f2df5146fce9934e4baecb1c2671077c771eb8089 +80b3bd3adc6cf198fcd997f8867d2839a2eb28f57390352ec423b8a14cc1f2ab21c6e286505d6a21fb134dcd8d8f11cf +a26d46a6b8a75748895a1d599e7fd120d896340e79813167a400b2fe463452532a4cab419074663fe1d29fa716b76a33 +82b1f3a8a1df29207d7ff020809113ab06080a7f0c631f76ad33f47cdfb6a567143144df97b4ed7f676d929195b04bba +ad96633a3744648ff0a2e4491e8219c9c6ba6e655cb058c36320a8f72cd5f72c00bddf97083d07650ea9ddc005fc1ff4 +91d0783788626c91662359dc3ff36a8bcc6831e3f4114f85c99910256b1d8f88a8612f53c7c417d55581dea486f38926 +84edd9e87ff3d193ebb25f43474c33fe502a1e2100fd3f93fda6520f5e42214cc12e9f8045f99aa2423a0ee35e671854 +b55e06a4b1fc3ff9a5520e0b7c8b5ac11b28385cce78d91ce93b82f1bd7f7afdd4195d0c13a76e80d0ed5a4f12325fa7 +b0b15c7ddede2b81d9c835ecaa887650622e75d0d85f81b8bbec7ef24e9a31a9c9e3de1f382d8c76d878d1b01373f6c8 +b1adb47c20f29784116b80f3670182d01b17612d5d91bd6502b0dcecdcf072541f582aafc5e7dd9a765cad52151684f4 +8efd1018df9c9e9814a9c48f68c168551b999914a6719229f0c5bf0f20a288a2f5ba4a48ba966c5bffb0fbd346a4fcc6 +b34ea2bd3269a4ddb2fbf2514401d2712fc46c22642f3557e3b9c7acbce9b454dcf789573ede9aa14f39605fdd03f8c4 +a9e1428ce24eacfc460aec2e787c053327ba612f50d93510d58b2cb0f13291ca3d16358325ab3e86693fe686e4f526f7 +91eac7361af4c66f725c153da665a3c55aca9ae73ead84ca2662cf736fe6a348a301be1954723206dda4a2120202954b +a6f02db89739c686407825fa7e84000ceedb9bd943e8a0908fef6f0d35dbc33c336072ba65e33e15ecfcd5714d01c2f0 +a25666faa12e843a80365c0fef7d328a480c6e3cb7f224763c11d8cbabd0e7e91a5b647585ee905cc036afca14842bae +b4348576439cd2e48c01cb9cded7cc4a0ea364ab936dd679ddc7d58b48807e7fab070f2f1ea88595b11af4500849026a +a8c6c731e0d0464ef7e4fc1b049065eb4ce100c01e1a376365c636a0b23851022bf55805963bc15eb57434a837e81167 +b0952937b154e3a4c206f96cd96c76ba37624956b0e4d43470bdd97b4af878326b589e3eaee82fc192437123096799a2 +97d07ec31ecc9923192e48d37df2cf08750050fb452dcfbdb350fbc43e146bae3590c5b732b31ebfa1ce5d884ad5ad57 +a69359aebbfe4cbc4d39d178150039fbf284cbc0edc68a6bd635ee3a1c76569a4a575c907fff691b2a4d82a384c2945f +b321c2c0f6b5902ee9056cce7404d858da9a573d27348c1a6bfea29b2746f2aee7abcb6192504e5a583b0caeaba117d7 +a74e738aa6eb4eea58855ae6f422af22812fb388c83aacca5bd5fa4a88d4c01463174a229aea2830c348dd9ab9307854 +94306a3b106bc1644346bc45c05cdc8287811d5c86cad691bde0c65d6a686eb9c0ce79ad91baa4547e5d058ae8bf7310 +b64140fd77a07633e4ca8d60786452311dcdb8ce7095ba51dad8486f57c3bf4e69bced92603f71da992a48ad817ab275 +affe7f4310f1dc68e5e3cd640bedf864f51bfb46bb752063bfc18e95930021f784e509261ff9c560f53000c361b142d1 +b0d2fee222c6f963ba3385547f921a48964da031d737892604f8f2677d4905dbf615046db57eae6c6dd756709ae6932a +81700c66aad7c2e51168e028b0fe086dea75d3b17d93a4dc1f47a6a0f025df0bae1c8c997901837ad859a84197e7bb00 +aa4ac5fdd602f8b79cace18690e67bad557a93d00c0e295074185e8c6b4059a65495d9971685de2fc01d2171ac8b706a +a8becb3a64fdf35d65d2857898dcf8053b5057a73ab8c5bb5324af1a8015cff47efb85dc3eae7364cd5c850b7962bedf +b72ea09bd0b72f8cde3466f359ea69b194ede93dced534efba1b9ebc6f3bd53942fe2965e992e82edb6050cac4ed88dd +85bb8dd7eef023a251fb6f220af54687747f4c91983ff728163c4618ffac40ee6edc29a0aa6d455276bbe017f63757c2 +85a485254a11b4c4a943d9ec509c0dd1cbfc0ff5273a00cf5c9f0babec973efb15348e5d9451b548293d778e3a2b62a5 +b109f3ac809391e772b589c196b013db69a9b2b10ac3898feb70b986973731f30722b573cd0c9324158ec20416825385 +8a4eb579a840d438bed008644f373ea9ba2f28470d50cf1d70af38ba0e17326c948527b1719dd1bd9ac656ebd5aedd10 +a52e9d66ead5ee1e02ce6108e4ded790d8ec83164a0fa275ab1f89a32200726c8e988d66df131df9e62dd80203c13dce +b541cee9febf15d252475507e11d65c4b7819c26cf6d90352f5e8a8f5c63e254eddf22df0c35a7be5b244233e8e4ee5e +8153c297772adf4603c39349142f98cc15baeccaeae10c3230ee87d62255f6814d88d6ed208c368d2c02332426589748 +970dc9782f1828474e9fab7dcdec19aa106725465a5844caed948eef5c9e48199c1b6bc1a637ed7864116927e84bc65a +a975a920624967f4ecc77ea5d9869c434caa64c330024194615a8d0640c5d4d4fb139ea11a0c73a5c6ae6dd3fbf0ab5d +811f0f9e0c12acfb4b9dca359eaef3bed18083bad96188befc036ad3143b121fff4777ca6dc70a835bbc4921bd25f5ff +82341c6ebdb97c8b72910da95c7eebccd1308b6a92999886aab552f0642882d5c7cc60931577d200efd6066530c998dd +860f7162c2f5fd1c0953c6ce75bd8c52eaa48032b914410681b8cc05e00b64130d1f96ec5a52df66a04c78a9f9f42981 +8a578e674875571fe1a0459843495a5ee1d9fb6cd684b244feb9488f999a46f43363938cd0542879ea18ed14fba10a6e +8df217aba4da6781f0f5139aced472025523ed6e17e504511c04b677ca8197488e237d8bb5dff7b6b3898cd5a6393dd5 +b2c9230ad35d7b471d3aee6f771517cf3145ad26200bd6fe9c7cf28120e2945fed402e212d2330a692f97bb9ac4dcf12 +b78b89e29e8b782603b222cc8724eeb83b2d9d56bc02f59a3c899ab76429dc721358b07dcdaf422f59520b7e7ab4fb55 +82682a5617843c4ac8d4efb4c3ce715c76c1da2c3bab1ede387db503f3489c1bfdfc07d9231d96f955df84fd225bc81b +b0f53725cc610e78b8e8a4e6823a2ffe44dd15a9a5bc8151ab7a3787ddd97e1d7f2f0e6efd2876e5f96417157143e3bf +92c5a93233085e2b244519078770c7192af62f3562113abc8902f9d72591eacf52bd15ce78653ab9170d5067606287f8 +a43ef97dcd9b6ad288846bf31fccf78df72f94bc7ad768baf5bf0d5dfa27bd74ffcc6b6c6ed1d1f09e09be3afa5eaedf +817d43bd684a261fb30f709f7926cc4e1a31fd3a1a5e7e53ba4d664856827b340d7867e23d55617ab3514c8a26a7040d +a599e22d3286b32fafaaf79bd5b0c5b72f6bf266ec68948478f055391336d756b58f9afea0167b961fd94234989f0f02 +b70db7d8e8356df2e2070f8d658e560081442f3f3b95e20f4bf30106835d76161101163659d5d12cc0f335fb042dc66e +b8f725b70c957aa3cd6b4bef0d9647393f7c9e0b7343e92439372f0e9aa3ceddd0cb9c30be331742b87c53f2eb030593 +b2fb5e7762f26036e7e966f4454f886758804d1f4c2da17f3d13b0b67ca337f1fd89fd3cc798b07da6e05e8582c9537b +a377f944dccc300921e238ed67989872338137fe57f04cb5a913c787842e08b8a1adcfb4d2200abdc911fc1c766a7092 +b82e98a606071c2a33f2ad44e7ace6d9471d5434500de8307b5d4e0083e3a5cbc67f0609ca8055f0ea0ee7501b9ed916 +8e58f9a04d33a41ace4944615041662dc35057e645f63e127cf0d70f96ac307d33a62ce98f164d6eed8536c1a747dcbe +b5b11388071ffbf57ac47fc195736613b964ebb91cc8e2c17b32646f91d64ea506282b881897fca96c317364d3290de2 +a40ee9b7551133856cfb3904837f9949a9558e59a418898affb78adf1500fd6ef6328fc4422161909aea2c79ad08c14b +81f9eb4ef28aacdb43e11dfc9aa92ba990be4d3c14b484fa677edad3a3fbfeaa859a7f9322b5e95818240d7326215abf +84939b2b6bc859437d1a7a8d6ec9a357c6b716c4b4cc22abc274af872655940cfc72c99f5d0283d90e05191fcdb1c232 +b78a5b74a90a805410b6225fb9576d6d73752520f25cc3fd1edf8ea9f6559d3080f9acaa2246809b6a66879cd2ae446b +8d0a92baa88bf38dce5385ccf15d345b28e2e5d0a2d469e689353d80eaed8e8408933816d70ad752f226c59a0d5b5f0c +a7e15f8a8c1655b7b346c9488cff278c793505379b781b31b273b4bf09b3bdfca1c8ab2334746075d636b2e05859f215 +b70daf14f2adce03c7b92d6aa181f0c507a80a37493d8dd12419d5ed5f943a98099fefb46ac827d6e4efb9b8233c99d6 +8c2480814661744d116fba7355bc6b1914975e44cf0e976d50b6a20092bb1c636b7b44ed3fe8d63b5555ffc89fa759d6 +a6059528a4fed36abb74ab992b22a4f9bf1d05c5de2bfe6837b9af1adfed98bc37ed7481b5a99675d432743021fcfdb3 +b7e19f1b25bc159e5a769811e773c3a8ffe8be8ac77ed0b711540915e5c6e7bafdb407cf9b85c551f67fd621ce8142a5 +a2f66d4f7d16ed3e7ef5fc90b42676c61a98ff18bd26ccce91de03b6a0130c1db17a6bc57be135e410a76d2255b15813 +a139c916927dc3d3fb83598da9217ca64f0ae127215332e9a7ed82be923b89a801c44580d5617297175f9dafb1c4eaf3 +af08e1e1b04ec95366a12d99c80a9a9ac40ac984a575dd0230cdf4eb346a7686da55ef0a276f3356f814af31f9cbf1aa +98840aefe287369221c0721cd7c1b15b1d670c3cbbfda191cdb5434bcad757e59c30ec82b2d8c75947405888d44da435 +b7c61c8d42daf2e278a12d8f6eed76090b71c82275f8b33504aba75d95103840e8acd083e97a5a5aa79897876a68940d +a0264048d2a2061d32eee4f661957ff351e78436bf49ef973c059612874ce9c91970869d011dc13a5b7c754476880a68 +897199a4d8db8aa2db5d9be3d4f4312e41fa0739eb06c62e2e046c4b9be829a447e5d47227e2d96195d3b7b66eb59da6 +b512a9082881f5dc90b02f8bc4f38b133348c2e933813852f6a8e7d8c270c9ce68a5524af7d1d3123e53b2d02a53d465 +80b332469254a96f53c95ec79bb5a8bb1c387d40e58b73d72f84384c696ba0d3c81d6ac90be2979c364c44294e90432e +ab680c2e547ea5cbf95bf813020beb461d50ee4341dea944eb48f6a8584d35682d20186e3b190b849a1ba25625a7f499 +9070581993a0531d6be372d370c2e4ab2ee53f30e04a75ae61ea0fc2c320914506c4d2d4b4487c1f8fa88356fc45c895 +8424303dad6b4051ab633ad27ee51783b2ead61c5a6dae1eb3ed72fc1f36e2a9b1f315504a4bd90f9664091f2f403d4c +82225611eee626556553b9316dab4043aff241a81826a33aebd9864a91e299b765ba1fb43eea2c2047e6b75b6d7fe3de +8a3fb221c616ad55c352dd5e0c09ee892022013d6965aef40d4f277a42e9fa01226fe973cb99aaf6ffe4f4f348fb54d1 +b07c07679aa51713e8a7d7bc304dc15ed5664b66bd371877023f3b110b3927e09e259ef22895c4001421a69c6c013cc6 +83556c76bdac0dd8db6da231b863c335be076e7299802eebc259e0818c369f933a4a4b18e2df8ca07e82f60767b462e0 +a516f659b7915d2f7cd0f0f5ea2491b15f0c84dcb191e7671b28adf7cf14a56d42cfc0da94b3c269b45c535f6eeded49 +80d7cc6f26066f753041b17ff1bd27f6d4b5603a43729d33d596e21a67356db84ca9710158089def425f6afaf3207f9e +b802a47f9009dbd48851209ea1e2739020e717f0ae80671d9f97a0e43de923273f66b7fcc136a064c8467372a5b02d28 +ac92fec1864a8a911633f377df87aab56713876316d48240fefeee49ab97f7406c22e70f4938b5912c5c4e766146b7a5 +89224225b9835d04428b0a74edbff53dee2be285ddd1e5a3a8c37307c0500578155f0c4052e4bc8be04c56862fac099d +b1d3c8492fbf22ea60732745edd3b0163ba5a20d1a3315e3773f2540ee38cf308d42ec72cbb3e3dcea457d1d132c3904 +8bd00e38ec30ee6c44a0e5b222f1f737c9ed2a4bb9225f1741d6334df966318c8a0fd2fbb109557fe8c9479694b8d8dc +a930ce5454efc0b247dc148aff869963fc5c240241d5590415cbd36634801a04d3873d93635911bb9c0c42ecb005cc63 +b83d4f80e9e0fa47b42175df74935ba8aad2e559b80e84478ab1685bc3eb65d51b93e5738d5ca968cc055ca0c552a03c +b3ae21258f98051f13af3878b8103bc541fe6f20b1c3f8fb4689ddb8800b3c25cca9b55f0a4104bdf15dc4d5844abb8c +831ef8684c1cd446c58c59d0152aeade5cc305bca6aa296b92162615f052ba280fe289edd62fda6d9f0667c186445f52 +97bf9659b14f133885916733b7d4ac7e215495953caba970fa259f7bf6b79e661090ec8d79e1c9ce8dfb17e8552f93af +84d5a89cc2332baaaf3d19627a65f4b107f8dd9228a1434b327732f59883bb54fb8ce60d6acd026ed4b0e94e545d1c33 +8e66cb743f95ca5486400b0d89d02e20b98044be1e3a12983ff9fe086179e5a0ebf4dcd5098703191552e9aa660a6de5 +87b4cfb35bacec805f8148786788db84eb8f4bcecdd0570ecb592c705450ce1a90b6d183d37ef58780ede3995be67497 +a72a4fece5478011973afa543f6d8a8ea06a64b241cf7d8bd81fa3740ac2a4cf10e5120abcc1c1101f94da89507a40ca +89dc6001a96adcd2679916f43dd19ea00508c8d5dd6b0090eab7982fd2f3571b62f3029588a0649e73f49124525407ea +8ca75edf1259599e873530eff6151c822a4018e71a340534219ef8641cb6683215891df41d4e3c0ca2560e57a7aa913e +9282d32f868e5ee6f7fc229dda5b94b603476de30cec0a44a30edf396b52dc0ebd472b8f726d4b67d76179fecc1666a1 +afa24704223707db89690bcf9761f07a093f6009ca9fc945e0a8801fc29f9f51292bf95243e466fe736088af36c55ca6 +b51332508ddd9a2610edd2b0ad120272ca342e96c28baae37a2c4f07e689303a46c237712d07e446b1d67c75aa8ce32f +9219249f3799dfa4eb4770ee323f821e559e7406bb11b1f1889286221b22c8b40ccacbd9ac50ea3fa9ed754860bc24f0 +993515270c128ede64fe6f06755259105d0ec74947b7eb05924a375fa5c6d14822f3d7d41dd04fa5df8aa2aa205a1dec +a83be4c2511bae430034ab15b194ac719d7b7041f9c0e321317f513a97db39e97b9ee1df92a1962f265b7a3e98cdd753 +8ac7feaecd26f7b99fda3ed0b8a08bd6dd33ed5ba687c913ec0ffc64bbbefcda6f265072add4d944f2005634601ce68b +b4e3ac6b09299db9e1a469f3a0b2d8d724ee47a417a517bebc4c2ac3efc5cde086b57b9aa4efccdef2bcf8f456d973f6 +9262a24a84fb7b2a84d700f98dcf3fefab8b47293778c20bfc356860cb84e0bf102bae9facd9986d92d1762e0a955836 +97be2041c42bd25e5eb519279163b0857f8bef627492c27b1182f8bf0033769246be5886422cbd2409c08a2615352465 +b0b87d059a00e3effa2e5e4925da913b245785f2932ac3ed364ad19a064d3561b8aa6afea22c951316074f0df179af36 +891644b7b3321b06a2a40cd96c2b8b29d81cde5b48546483fdda439000982a9cbf1f6333fb6c089d39da6492cdfaefe9 +8da9149b7f4783a24240b7b9c7e6df4abf8d699d3834e31ee591489bf4744141ab199c173db64397c1f9bd5f9c862ca1 +8ad7f9fb2742654aa2964fd468e7645436cefd1308b064fd63fdf0d3adb4caf6cfe5426354f6cc284f208b03d6b2d918 +8435e4668f7aeb027100d21e4e0b6ee22b401d21966a3736b95610de86c7e2f2c9ee5d0f901353675eee5ff458dad69e +9010895f045538bd11b47bb8996f27198c8d6cffd3220569e6b7407f68f35c47d1efdbcecbf9b5e241c3c2879a4f6936 +92a9aa443b5ee7bf13b6f43f2d8d8db7f6f33fd4073a606ec5772421a55f464831419726130dd97829a7d4bfeb1ab078 +843f3266560be6dcbe0258c3c7d7e332330e10630c069892954290288eda301e247f479505a8a1bf7e59c99ccafd104f +915bd1dad808f8a568725bd243f80b5476a2999d0ef60ea3ef6e754155bc4121b2b879d01570725b510c5a3f09cd83ef +97250d781815b1825be192714884630e9f564b9bd737d55b8ac79ab48d0fb3ca53bd21ead7b2fa82a05f24083f25645d +81e2d52333391ff2faab39611689a62d6ead77039e8703f4e012d53eea17a4d46f2e3342e44b6edbe73a542b461bda45 +89c9f9fd5f638156b018831c1bb70c91215f4a2f5a73c84b1208bdf6ad652a55df7213336ce12bd910a0e1a726474f95 +92bd02984d090ea7e2f3eb7d36d1e7b9d731b6b047e3cdd4af7cc4ee177415fea7a145205e484b366d84191f06af85c9 +85a86fc61d5d916ccbb219db52953e1495230aaaca63237e9165276405f07ad9644e253ae394f1ccdd231944e7143313 +a2ca5b3fbc9f3530f88c0ed7071ec3d89b272174c366eedb5d15d2b648c65d23c0faa4e92c776357e7c6883a0084d03c +ad171f5badcc99c8ffc9d8b707d792046f86cd0aa478e0e2fbb32fe095f96cd134ca548d1f7713057694dc6b26465315 +96bd15d57da9980870fbadc98c68db76824407dff2700c45b859bb70d98374d4a4ba99e3ed0b0c17f480fe08f16c6b8a +8300bac69ca088c3ff35749b437215e9e35a16393e9dc094f520516ba57a485def7029d30adfc72bca36eeb285c19301 +8a09e20be64f346668fcc7b07fee9c0ea8094c935cbf4f3a4cdbb613d4b936c1edb9256b7c884efb72393d97c0da00e1 +b1f85827ee6f041f93ab174d847a55710824fa131c9ade9561168c3962a25c617475ebc4105eba6e738961a754442bc8 +a131558f92e215969f41b6a57d1e2f424149eea531723821dd4cf8c54325cbe66b002de2c8287de6b41ab4b5c35f060a +81ba492b8956f73557f361a856c6c884ebb300d828287d5699e22e0cfa75c8e77a61616551d0be5178263898c461d6f7 +b2608f44d3c22fac8e13cb59e4ade8b9a98c4eb1ec0959ea400c97eb937ae3f66837e91917057148befade8389af2f6a +a6ff0323b5a18a4becb2cc6b376086b47cb2baffbfd1b0f2229ef2286fb4a34c5cd83a5faed5def7bbad519fcab8a856 +857d879cb9eff22501d883071382832730704bfcc5cd5b07cdce7ab8dc41c565a1eb0e7e4befce8e0e03a4975d3f11ef +a2879a20c0360c516811c490289be7dfbf7dbd41d2f172c9239f99e3d091957e0446854f9d0f753d90384a80feb6fa56 +83518624f33f19f87096a47d7b8e5f2d019b927e935a9021823fac6564c4f2328dcb172e25bb052748191e75ac682bd0 +817ec79132faa4e2950665712b2c503d7fb542aa57b7b36e324f77cda79f8b77bde12314e2df65c5b5296a6bca9bb0b4 +b2abf8fb7c3690816fa133d5b4aa509cd5a6e3257cfeb7513d1408b12371c4d58c44d123ac07360be0d0dd378e5bcf99 +a9fe1e4fb1574c1affac5560939face1af6657f5d6abce08d32fc9d98ef03186dbb2dbb9fd1decd6d8f4e4687afecce9 +89b2f41e51f33c3ca3e44b692e8a6681eb42a7f90b81c9e0a0bc538341df9e2039ee61f26d2ebe9e68df5ed1bccf8cdf +8b35aa7b1d9e2135b35a1d801f6c9f47c08a80e48603f3850b425f64e7fb9860d1adda04f92a1ba22d00dd0a26e781ca +960574978cadedbd4cd9f764bee92f94e08b7af65403de36b21bffc9424bcee845b3b028af2e9e545dd77cf1e69a6a7d +840aa0f34b5b6c39471f54d9e85f1eb946468c4fc01963a9027cd7864df01f73c2e864f1f07aeed4b1b1af72808dfa07 +834464a84a11200e3c60f816044c254a7d9baed64aed45a17325cef7fd62338e0a26da78d199d30ac3411714dc813223 +b4ac6fe2f5059546f4ad9a361426ead33237b6b9030b129bf0122085c85fe4ccb33cf90f5a7f23c5b708a5ac64b487f6 +a12aa9035464795f2a67f3eaba478d5ebc838ed9e997c7dfa241e1ed60a94b367d3f969ccf0ef02028c35215698b309f +ac8d926492ec2bb68c6d8aa9bce49085d3d266f3d5f1f924032b87c42b44e41da7c047eeb01e4618f9d0f123dcaa537d +a5142425825d813ed8ce1849d81aa40b11f1cc3daa89a9f798dd83065c74820b4da6122b3308f528b074531df66e1a5e +87ff55c9f5aae079e7bf24084dd9c6b3bc260727d942d79cbe8dc13341d98525b4ece3ed8169994b56a387642f09134a +88e680f148ef2ecdcfed33b61f9e0224790fddc9069bd6999e9bede1791e761637c0fd60b52990b6c93e6e5429e483ce +94bc20bf5aac6e9f1060d02eacd06c42aeac9a1c5635b15a83985dfb03938ddb4999a822e865635201489c7f75601b29 +849221cab7599f25f0b114df092bd5e8c2430503ae959bef1543a101de0790a78245db6a145e26f40b5f9bcf533219a3 +88b6f2c2e7a7954fad11009d839ce50780921f80292320868d481e38d26aecd80fa607e82219a99532d88cf33b39f562 +b0d82947dc23c0b88b86c321b582c15decdb825ed909a731b42d46bc895009515a3dc646c98dbec7d71b0722df82392e +a2cfb9f7c1a76c8073363c1c3bebe5dc29fa76533caea41046c51ea9bbdc693a121b957cd96be5b6da18704d1865cff7 +8f0ffab9a83355a22683a9d998d1c1089449eb308711eaad4265f05927ec6d0d1ca39217082a0b372e02234e78dbaaad +ab024661e2b2937ad374c8cf2e3669f1dc55558a3a881e9ec4d461f27e0fa92e2bc88230f038bfb051cf2145ca747a07 +b98d9b9ec9eefa56d38cca959ce1aee7b6d4b41a8dbbd34b3f50c0a5f97f84ed2502ded1ce8cdb5895872360d4ba6d61 +851244158b3184a62d2c98d148e2b1102cf0d5500906bbc2deda95acc5e3bc4b4a3344febbb31ce05a56dfee86a74913 +860d9e2cb886bd3620b5d7499d14b415532482569bd45fd76e3e8052d78a73ae4b2b41f139f9cfb136564108cd93c0f3 +8305a052a0fb2bcd41f3aca075c5f7f233bd8f861451d03f3a6e6e31f7d08dd89fe1eb4dd7b238a78b12ddceaad9768c +adb703e4778c7e14fb83541ab00b5fc344108243ec6827c5d9b302ee68321aa569da1718424e6a57979ab7536d5eb43b +b1a754b87b9e21aeb86217ec5b4fadb7535344567f1bd15e88ec12a833fed68e26bfbe03b7709ce24ba6c925ea0a0e07 +8c1e2f6bf820e1653f3b8213e9d959d8649196223c2aab57b7ebda094f4919f88d883bcc6a0cd0be335f26f5a2a9c962 +a082deb9865fe8668e91db0e4fd7fb50fb3fdae3e7bf1217ce0aa6f286a624624cf936d762bb2b6c3fead6826694f846 +a10540ca05fbcccdd0a2a66aabab3b36e9bb525794cbae68bc3dace6116f58942218e9d5e9af10d67b5f6fb6c774fdd4 +b81d22c4ab0ccaf447cc5fc2ff3bd21746617e6773bf43257c0d80331be2e8437b88c9c45309ee46402b38d3d4911caf +84c7c6e924713cab3b149f641dabf63ad5abbc17c1d8ee7802a6630507aa1137f7e034ba1d12ec13f1e31efbab79bf13 +8773b9d236e5fcfa8c32e471b555264692006bf9a869a3c327aed33da22dfbf5780ecea7158904d4d6ac4acfe9789388 +a4c2c1bb7290eb7af2013f7dde78282148593f066b09faf42e61a3fcf81297caa5a00fdbf6b93609c8c5782a0f25341a +a7bfa6e3f273da3dcfac7cb9906bbe9fa4fc2872b184d79813ee273e6cc4d7f37f46164362707a1976f5b6a2c5d7ed1a +8b71502019e4263fcda354a0fd10aaa7da47f4abb7a0c715c7b017e9eea14f2b64009b29b467394668c7ca995adedf82 +ad7460fba7deccc3f9a7d204233de47ce30ffa55e1e164975cdf06480a6108720bc397b93ca8c959df77d44a1e1f05f4 +a5b8df96ccb7b078a3918e74b1b10da21df982538d2c9313f5129b2797c8a6db9ff8707241ff72d3e9d5983397321736 +aa6cfa6386660c01879656da6c4e72497690708bae6c5cd1d088f443cb5bbbe75561d6eec256a72b9728377eb83ef973 +b9699ce7c5c878e44114ab7a598646c6c7616b8e08a9ef8ec291189ef9945c1a538d2abf1ce3b0da0f8eecb303b81b43 +b8d0fd1d278f53c455de92ec4357885fc6648dc5f276930263da7dc885b4a9628a2113e28b66b1e64fd08189427c614f +84ad8d262f6ef5d93e82ff6f4af995148eedf6d8e079124daee9b99f506e2968922eac2c7d4aea741fceb7733f20b2d2 +ab5e30ab54641e3a44450118b8235554e0fcfffdfbe1430ceb3f7ef33325725741995fbbbb0c16f0875aef0f1e0c98ec +80e2cf8bf386ebda46045852751611f2af80eca2e910d9ec5f6e2c7376611534604ceafa639272b3d503b02bd66525a6 +aaac69af8fbb87da1c1b7c1b9e59942887ae839a91f0c1d191c40fe8163d7f1dbe984e4fd33619c73e63abfa7058f1e3 +a6194224ad838ab86e84dc80e9b8abb121ae6c3c7fddc476463d81f14168131e429a9757e18219b3896a667edda2c751 +b68f36aa57aedc7d65752b74761e49127afa65466005a42556230dd608ecc8f5efdb2ce90bb445a8466e1fc780eea8c3 +886c3fa235d6977822846b3d6eccb77f1e2cd8ba3dc04780666cf070cae208b7513dc4525d19a3fb6385cb55f5048e2a +a9801273ef850b99eb28f3dee84ba4c4017c95398730c447efe8c1146b0719f252709d3397ce60509e05da74ed0f373f +a58c2a5dd13e08ffa26a6c5e5eb18bd8f761ab64a711e928e6101512401ef2b1c41f67ba6d0823e16e89395d6b03ebb7 +91318b564ec8b2d8c347ca827d4d3a060272aec585e1acd693b2bafa750565c72fec6a52c73bb3ae964fdaa479700532 +a058db5d76f329c7e6873e80c7b6a088974522390ccaf171896066f0476742fd87a12fe9606c20d80920786a88d42cec +9838e07f9ed8b3fbca701be0ef32a3f90752bbe325aca4eaea5150d99eb2243332745c9e544fd1bb17e7e917202edab9 +85a9ae7dd354f36e73baa5ecf8465d03f0c53b24caf510036b3e796e4764a2bc17f0373013af5b9f1b8973226eb58cd1 +896a4ff4508d069a7da6ef7bed66e1080991daee8b227f3c959b4f47feaf75fd1b9e03d0917b247c2db11e105395d685 +a36d9a6a037bf498dfc0e535f2034e6cd433c7b52e520469811eb2e9f04499a6ce40257d2905300df7d81f38d1bba075 +97aac3c5492aca879b4c06db1834b30b8850a244d29296046a84c637d9580c8521ab4752ef814c96f255a139660d7639 +8552bf592a84ab4b356d01643c90347377ebf1f2b38a8c2e55a3f34537b8c7dcbd62e6776d6c2114f2bc2d4344d1567c +84474ad163db8e590943ccd1dc50b4f444beb8275919b33f53d42cba89831e9d42ce2de52b26f4412e2a0676ce913277 +900799dfaf5eafeb297c7b4f892438bf2a65ce04034d66f8e5cc3836e4eaffe782fba4f4455a0fcab49102a240d1780e +817176415e35ad4a204b9fd5771bae6cc270f6ff050996cec89efbe461b2940ae5dd3c6c7d7e31b1da5285b207efed27 +965e5791c927d47569bc54ec9b4c5305788aecd87a26e402aabeaeccc03480df46f0586ca2e2a9918885cd03332af166 +b96d9ada4b5a04a94807d71726bd557de94fbd44042d7dba40560eebe8658d1da49eba54499360619f3b2c38e8b5ed6a +a07b6d641a43e02e7868f30db4dd5069a2f221b4f122ce9b11eac04abadc4f25f3207f1d2d86c7935b1a3d9992ea9814 +8250d4d8ccac846a4b1a9fa392d9279b5bf2283c8b95d8164c3c0d199fec8849eab85755f2a2a99d584a0407742e3200 +8324cf49f56fc14162f9a9ebda1ebda0388d09d8688f1938aef7dbf9505fc119069efc552f68cc7cd9213f96fda2c6de +a98e6f1e85268dccbe3bf4e92c9f455c58dcb53de1dba3b78589adf2e50e79f8e245f956e0d098eb46f5d3746826c6dd +b103ec12f266b4153d67b54d8fc079357ee342cbe5008adc3e0689a7f788534c4601e60e939731f49e4a1e24fd589f82 +b2d7681e866420413cc98eae67614d383943e3762d5742cb3c57e26157633c20880eea1209feaf68402d5d33dd699708 +99fed0ae4112ec9ed74baac70d202a885aa51cb555a3886b49016744dd4017640dd5dd564998c4d842a9f38f3e004e68 +95c35401314467219c8bfb1ccd1f1eae6ef4fa9e48fbea14f70d5315e67b16c46cd03554471840e4a5030b077d2a3856 +8d029380e0c294400d6b8673a23aed43697cb6460fc1bcf217aca3b47cf240886644ed09521d6a05f6abf56f99722d84 +8ef54d1dc0b84575d3a01ecba8a249739edfd25513714dd4d1941fbde99dbbc392f7eb9fb96690d7052609af23aa57f7 +b8ad2b7af4812417aa8de8f33a26547f84bb84f39501d4b7c484cc8bb54c7e166c849b95240fbe459a4719a6e3bf1651 +9858545de898721d19930d8b360cacc5ce262c8e004867a050f849f7a2f2aba968c28d51f24a9af56aaba23a9ded4349 +94ea5043b70df1db63f9b66b4f9d8082776f721b559f27d37b45e0a84faf47f948d7c4532dfd854a4bac49fb2ec8e69e +a2fd88d7b15e3c2778f6c74470d0f9e1a1f979a4d58bd205361eacadab9973d585a6508e685e640b272d6f8a448eae05 +88defd6bccd55db8ca84e3c8d0fc55a3456b41788f1e209d0aec19c9c70febebf3ae32cacaa1dbbf796d7ddea4b17995 +88b8cde2449d5ee7de2ee2f32e845d27e171a51ef64f1d3d8a5fd7dbb9f898ea70eb7f6410cddfd7b7ae70ea8073cc2e +8e044fff6ec557824866ac76301b6d93ed19b7177aa6baa95046330f5d69b572b59200e3653cf2f2b559455e782e8960 +b5446b4d6741c824885790d2d26258729dc0ba2f469c85a47d38886d933b785a4f38a951d37f3ef4bd5091c03fa3a071 +956c8afa8056e9a71ab2e8be5241ddbb3a8b3cff2110cb0e7389493d9fa45e6c4b769ebef540a952db6dcd8bd55baf64 +925950cae25615246e29d594ebf34fa7d52f78a9867338648158f2131e6eb4dc17e18f9db8a5fdd76d017b3a9798b3a7 +a17ea4b43211ba990270c21562690b3ef154a46c3d669c4674c80bd424cdfa95d8850c8e882b8d06504f929cba3d93af +b315ec723973a138508afc387ef651fd8a8804f93975fc36c2eeb796a304eeb1508518d8703e666a74d14318253f526f +a995742d7433b3f230e622de23cb2d81cac76de54831491cc29768eb4a56da60a5cbd573e1da81fddc359b489a98f85c +adb2e89f0d15294d7118fc06d4fdbd9c51d3ecbcc23c69797e5b8197eea0d6cd1240910cf22fcab4ef1e2dc2dd99da91 +b5ec9f9fcd0b5d176b643df989bb4c4c1c167112373d662fb414875662d1a93160dc0b5cdf540e8a30e5fcbe6cfbbd49 +b1291b53f90aed275df8b540c74a1f9c6f582e16c5df9f5393a453a3e95624ab7552e93d6e2999784e164046e92ef219 +8bc7b7b1a584a12d5ae63d0bbe4dc1b63c9df9c89bdd1095ff4b8e7c822bf8c1994c92310a3644033c7c9689f4b7d2b0 +ad7fc45506a10ca48f991714ecc055cea376c0cbe667f3b40ee8dad8446218835439ae59bccc474cf47b053748ceba6d +b134756828a5f5725c0b95109e09ca450e3834b127163a0aeeb544e63cc0cdcdf66f8ed98c331c7c98758f46af369a84 +94535bf1636be0974b112fcec480ed8eafc529933f3065c40e417e608e43a392206cfde8bb5a87b720263446c90de663 +a4df4f6efbc3701000fb072e5cbed2754b9ef5618386c51ff12f95d281d1b700fea81fc1365f4afc66a7c83bd0228fbf +b0336b3552b721087c7e2194976a9119aee13ebed9f1c3c494353707fffde52d004a712965f460062ec9443620716302 +99a39d1d1ee4283b75fa8c1fa42b6a3836b734be48bdd48050f9b05e48db6354fef509623c6ec8d447d630a9b3352b77 +8e3dc3583d40956f9e784e8bbd0b5e65671d2ff2a7c387b20fcb7da9b969f2d122aaf7f054d450dc611737604548c03a +b5068ec5b7bcb5d8583d51cb25345990f50d1f7b82fe535a6a6b17756355885047916f466ea3ab09eef5516bbf2dda90 +a8284ec1eb1d21e693f31a6c074199ee85d8a8da2167bffab5fe240defa2773971c8437e358a18f7e58d1e2954f57f6f +aa7415639d29081acbaac3e9c6b059d68e8702db3f430b86bb6e220d476fa74841c875e9d471c8a5423c58b6fee3cb54 +8afcfe6f65fa6e07c2cb3e1756c0ef2c589830be96edd50c3c248e3b17f51a4b08ba92ef7eed7991d81667ddfbf2bf7f +83b9c8dec8ca8f9b85f0e36c08c5523cfeafb15a544398e6f93b48b5fc4b15a0bd05c0f176a9c2469664acab8dffb0a8 +82a128a89ea46b9debe5c903b950c0ab30cd7570b979ca911500b5c2cca5c4ee6b2c2fa414b5f28e367f4671ffce60f4 +b79fd0ccd2629a361cd6f9307c02ecd4d1f07e4ee03ce4b542997e055b07a026cbc0ba05fe3da309efc58db2e401a8fe +b190751141093823b4b5324cc26c4f3258552f7893241201f2fca1ae9b1a1d4d4964a9abdde8642cf308ded61ce5ef09 +935fd48b95aa6f9eada0cf9a25a573f0ffe039888b3410788c41d173747bf384c0ec40371bb4383ddcc7d9f2db3d386b +b9affe100d878491ff345636ffd874ce1f27852a92417694afce4163e6a80c78b2f28d78102fd06c3283ef273ad37642 +a877670276d49ec1d16c9f1671e43ade11c0c1a1413755f6b92be9ad56bc283e4bd2ad860367c675d5b32ff567301fc4 +8c660d16464878590761bd1990fd0fc30766e7e49e97b82ec24346937856f43990e45aa8ad37283cb83fa16080d4a818 +ae1412087da5a88f3ccc45b1483096aeb4dcf4f519ff3dbe613f63712f484bdd8b2c98a152a9db54cf1a239ae808f075 +ad83cead97a9c3d26a141604268f8a627a100c3db7e5eefaf55a1787ddc1dd5ffc7544e4947784cb73b90d1729003c8f +97c3140ce435512a509e6ff3150da385fdf9e0883a5dc7cb83d616ec8d0a0014e4e0fa57a4d12c7997cd84e07d49a303 +a353773ff68f1615454555bf658eabdcca40a9c7bced8537ea6fa8d54764fd1f032889e910d2a2a342835513352e2d2e +89e8df0c17a36ffe08149c2ef8b27306d04cdf437135aaeba697abc65e3c8e91bcf1817919a8a826acdbbe7dce79a18a +9928c2da15ac6cb20b15859c22508cfcd452c5643cd22eb84abf5f0a1a694fdefcd8fc329c9b40babc52630743d6b65a +99d837b556f8d13108eef6c26333a183f59383b39958dd807b10590c3d37f62ade6c4a320ca2e70567e0218b0ad5807d +9272da080e4aa18720b634640b01bf1fe506c7c8a89dee8759a53e2ca5cdbbd4a4f3aca54924c46b935362cf1eca066e +b4d39752c882de1c1daf3854202c1d58c2bcf35c882006eb640fe54a97be2655281cdb91c30d1a41c698617c2cf64b01 +8bf827f4a7d47e07374d338a3d8b5c2cc3183015b5a474b64b6086fcf0cdcf4852046c9e34d7917d69caa65a9f80346c +901bffc7db9c9416e06f593a76d14f6d9e5dea1c5f9557bd8c93b9e70aa4782bab3518775c2a5b285739323579f7cf0a +af7e204388568627ca23e517bcf95112ca8afd4c6056b7f2c77c4da4b838c48791191565fd38398587761c8047d11c47 +ab2576b5366e6bd88b347703f9549da7947520d4e9de95d7e49966d98249406ed9270fe69347c7752dad47e42c4ea2f4 +b12e3b228b761dedd99d02928105494ded6d4fea3026d73d65ebffa2e85e2cd75b6d091135d418dd95ac102c22b5ee31 +a20b4a752685d5e31ee7e2353c8a1b9a5265f12bb775004d282a3ecd9deda44831bac1ac5151646428b66909b2a423f5 +91a1d4bc0062a86cc6786a96fd3eb4436d8a4a187b7cbba02190d1cd6ed3c3797d9ae7d6ddc413f1c94a21f62bd04ef5 +977f18da1a5df5cfdd0276f583cfba2b2a0fc6139520664e20068f8dfdde33e29d179abfd722f142448f4677aa47be6c +abc3ece90f0f7b1d80fd917de27ab0d88cca584ef959da520825e54cb5a71336b15f8b348532d08d47a6fa600527ef25 +888d36a2c7cc13a1c1aa338a183a74a1f57713e76cb825f9837f43279ce4741999b76a16928147537bcc20f2e0195b0f +af3f5dfdc2dcfe19de893f385f39f550cb1dab67c2e97f1d5fa735e5ec96d6680066803e8a0eb010dd4399f654195513 +a0fb4e08ff56530a940a86c28830956eb6dec2f020f7faaea7566faf0a4fafe0cffe01480e87763ec22f201be51a6451 +92343c5b107910b203c64a79c93d354f7ee5b7d1e62e56732386776e275285561cb887019cc00d3fdbe3b5d54460bec1 +acfe7df83c4624188a1011ad88c1e1490d31a8a8c8016b40aebcdd7590d9c0793e80d2d7ce6a7048876621c252a06a5e +a7da001dc1e33e0e129c192d469d2bd6e5d2982eb38f3ba78bae0670690c8e70f40e8114a57bd0718c870ca5dd25b648 +a903de5ff97dc83628290d781e206ef9d7c6b6d00cadc5bacffb31dc8935623ab96ade616413cb196a50f533e63641d6 +8f9658d42ad14a60bbf7263f6bd516cfee6b37b91a8f53715d69f718a090ad92484061c2cef999816760a78552fae45b +8c15b72b3d5fcb9ffd377fd67d9dfbdd706593fba9629002639973db12aac987bd1db70250ded31c88e19efff612cdb8 +88a2a4034decd854fb557960194ff3404e239953818a8a891bf72a0b26a8e570a65c4a630884de991ae7452b3234f31a +a09cae5c4c190537bf1dd75bd7bce56f7b799762af865bb9d1ee970f6a133c27cce0dd0f14a0e0516ceac41054e6998f +9760ebb1b40f9a97530c3b940d4ef772a225e5b63bf18283f8e302b9436c5209f6294980fd37058060e429fb7fdc3a56 +adaa9400eb86d857dc591b25dbe3bc8f207b69e77b03cb5ee01f7e4b006b5c8f6ba2b51b5a45687479885708509363de +949efe6b00b3248846747a9ad4a934d6e4255994c2b540a59fbbde395fe96d69bb67908441cfadd8c8bbb561fe52da03 +a19a45504b6b1dc3a0fe0e6a1384734a3dcd5a7cb8fb59eb70e49426c4fc44946547443d558e5719a04884ab3a2811ca +8934c9ee21e8d1435426fd0f64232a0670a7946ec524c054cd4f2cc8b1be9f89cc11002ca8aebae646a2050d91716b10 +b1150ff8ffb34ffdcf7d603348c0aed61e5f90ee0a1b814079fc2a41325c75f2f9ee81542797ede3f947884266a772e0 +86ce8cc7c1f92af68de2bca96ccb732f9b3374dad6657dfd523a95e8a931a0af2a80df74098514a06174406a40c16ba5 +90faabb9ace9e13fd9584932846ab28a618f50958d2ce0d50310a50c3bc6b0da4338288e06e5fcbaa499f24a42c000d5 +af4a935c2d8df73332a16dc6da490075cf93365bd0e53e2374ef397514c30c250bcac569b6df443985cf3720a4534889 +b7f948ee90f394789eb0644d9f5ad0b700c8e44e5e9ed0e49da4cc18483676d25740710b1c15a557965da635f425b62e +a917913091245beed6a997ff7043ecf60c4d655c4db0b1ef1c704fd9b0e1ea1335ce8b9f45d6e120f81805ce31555e30 +a48099da8406399bfb1ba834f6f7d864111d0036969a5cb64089947a63dd9467d3857b605e9f57f5ad5f4ec915088d9b +9784c3f9be42eed354542b1446d734521f8e3f01cd9d495ae98f2e4a3a16767fe2ad909e0def5d9a6267f3fc6a172cd2 +8d9afaa323847a3226ad7d7b60d87322ffcda2e4a8df89f58a076f7972d896588de685a2e155e243bcf9456b0a0d6d1f +994413faf0b843f4ec1842c706c45ea5f24351c68674a27887bc8b182eda756856e507a4e8bbfd937e2c4c581b629ee6 +b3e72d9d1ddaa00c7d22f25462d6e9f2faf55e30d138dce8bb1517eb0b67132db758668aac26164fd934d732633bdea5 +8e95875e338f714e9e293df104f0ad66833bbd7a49d53a4f7f5fd5b18a66a61aa0a0f65cc31d55e0c075e0d3e412cb90 +b980091862b1a9f9334b428eae14bbf1cecb4849e3a5809773b0d071d609727270f6ad97f329eca896c178ce65883db9 +915d7ae5ae780bdba27ba51a9788a8852a15355b569581d1f18f0d94bcdfed2c1ed5a4f58e049e9825cda11f92b2c2d4 +83e581058edf9259d0b06128282327cacbb6afc939578223cbf93544599f799a8dce1fb21d52464f990a877086f42506 +803612a38b6f6efb97941997e101ac1878e192456f8fbddb3359aa7f3023434ed8fa92e60ec8e7b4473b1948850e4311 +864a1bf4ac046161617dde282e44ab3cc1843da01a09ca58aa00ed00eaea9351a07a9ec16d910819e7dcc28b8d2c8ada +922eb142845975d5f6f7dcfee6cac8c299b3730400e6bf82cc0bdd9888de21de9d9f1530640f702c003e1ed63b140cc7 +a7db03c5be647dce1385ebc02f4825a654447fa8c4c8d4b22e635dbdd2b3ccdf219384e49a80cfb1e9e6182b6e4227ed +a167289ff0f0967bbab6479e4a8a6f508b001bbe0d16cad36ab4c105ad44f3f180e39a6694e6cd53bc300fe64dac1e8c +b7766431f6379ce62cba22ab938cdbb1b0c7903dfb43980a417e0ee96c10b86b447241e9dd4722fa716283061b847fb3 +90cda18c5d66f5945c07c8c7dc453dee1370217ccb851bbea32578599aa669b4dd245dd8a9711b27c5df918eadf9746c +ac690cd2af39932874385fbf73c22b5d0162f371c2d818ec8a83761e0a57d2db2fca1d757343e141e1a0348016d5fc44 +abac820f170ae9daa820661f32a603ed81013c6130d1ca1659137d94835e1546c39a2be898b187108662cdcbb99d24fe +b2ea5a5950096772f2b210d9f562f1a4cfacc021c2e3801ac3a935f2120d537471307d27b13d538dcbf877a35ff79a2e +ad94af4d0699cd49ba8ca3f15945bd09f3f7d20c3aa282a3113cdf89f943d7793e59468386b067e3c1d53425dfe84db4 +83788367ec97cc4bbc18241cbed465b19baa76fab51759355d5618067009298c79d0a62a22e2a1e6dc63c7b90f21a4a5 +a3e142d879096d90b1e0a778e726351fa71996466c39ee58a964e6b5a29855123d4a8af47e159027e8e6be0ca93d9955 +860831f8d3edaabd41be5d4d79c94921625252aaec806251fb508e364e39fde8808d38b10d557e487603a1b274c9bc3a +88da39f334bd656a73c414ec17dda532059183664bbbac44eb4686c2601629ef8ff9da992c337a842e3885b684dd0032 +b50addbdf7164e8303f33de5ce854d6f023d39c1c1984b214d9e5fb6f6001cd5bdda816f048a438ff3d696872672f805 +999e58c4c69a912b84561cb09610e415b43832beeb95897eca8c403ef4754f4277754d492eef3673afd4362f50060fc9 +b88ea0f60f8119c5a1fd9294796d387472dfad22442b29659713d1d88e7d854cb7cf5c9ef773627781188626bb2fb573 +a068b3844e9dbcf74b54fd55904d56af754d8ce4c619fead7a07f9bfb9d02118db7c512ccec2489d2a84374ec1d1fb6d +871dee023768636003c799e6f6fd8d31315a4c0da7286345cd64264a016693b3485e0732be1bbd34dd5fa04dfa58a983 +8021e8f508680df12e4a5a1bd49f2d7142df65158b0a7198ffa83abd16053a542fb93ffc33e5279020ba8c6a26feacf2 +b5d3cd64df5bc965228b0bd4ce9e5797c409f7b64a172ba165e44a8e4b38e3d5fabc3e0b9a19afbfe427f887c40a315d +a54fdebbb594bafcefb1a03697711e0091c072e1cc24fb441fefd4e0a0518675a1d7b0966cb8294051d7ec0ac175d0cd +93922202337f72969d6d6e14a29c9c75e0420dfba712029941d1504b9f6f9761d706cbc0652cd09a1aa5d22aec766af1 +9711ebf1c7c7426190d4afd5dd03b014a456bbd9d90ed101623866a280550df26a629dde400c03ee3699f7d827dc0bb9 +b4d686d8bc5c1e822a50124c1cc23c6bc3a1577a3d0b8d4b70d1797418aaa763283c09e8a0d31ae6d4e6115f39e713c4 +a533ea2ac683e4ba07e320501a5d82a1cfc4fa1d65451000c3043f0fdac0a765cc1125d6cc14fe69975f3b346be0fdde +94ee563134fe233a4a48cf1380df55ead2a8ec3bf58313c208659003fb615a71477e5c994dc4dcfb2a8c6f2d0cb27594 +93e97d3f3f70664d0925be7aee3a358e95ae7da394220928ae48da7251e287a6dfbd3e04003a31fab771c874328ae005 +b57440d34615e2e7b1f676f2a8e379e1d961209fe00a0cf6798f42b7c28dbd03172fce689305e5b83e54424bc3f4a47c +97644084c6f7b4162bc098bed781dd3af6e49e7661db510975528f1dea8154f3d87e979bcae90c3df3a7752eb0752889 +a923b27b225b2a6dd5bdc2e3d295b101cac5b629a86c483577e073cea1c7d942c457d7ff66b42fcf33e26c510b180bc2 +86698d3b3873ed3f8ab3269556f03ac8d53c6e2c47e5174ec5d14b3ed5c939750245441c00e2e9bb4d6f604179f255ef +87946826d3aa6c7d53435c78005509b178fdb9befc191c107aee0b48fbe4c88a54cebf1aae08c32c3df103c678bad0ca +860864896c32b5d4cb075176f4755ea87fea6b9cb541c255a83d56c0a4092f92396a3e2b357c71833979b23508865457 +b78fa75d687349e28b4ddfe9e2d32bb6a3be13220b8f3ff1ded712088bd0643da9b72778bcca9e3b103b80097f48bdd0 +8a188b940446598d1f0e8c6d81d3cada34c4c1ae0118ec7e0eacc70d1bced28ae34b99667d5793d9d315a414601c3b22 +842ac6f7dc14191ab6dddffcbc7cb9effba42700a77584aa6a8e17a855cd444c5d138f9d61bf55f43c6ffbcc83f92bc9 +b6742902c3d145a6af9738c01cf9880dd05c85f0d0ef7dbe93c06fdd6493333d218339ebc2a02be1895436a2f734a866 +98bf18488483c627b7181b049d3e6f849fce1f15794de59dcde6e5a9b0d76fd484a46e48822a6a93001d3aa12f48bc6d +8769cac10bda8c53a1c19419ef073a5998f73dcf2ba1b849561615a17cbc0a49bfe3eb4ff8801dd36a22fa34b9a3a7e2 +b45c084d58028fdfae792210fcd183abc4ffddeb4cf52ebf3f8a50e4c4eec2a2758f1241b0920bebcb24b757c778577c +85c1216eec8e1fbc1af9b36b93c5d073a81d5fba86a6daae38748ec1573eacc6bef209e76c87a6efbd7a3f80e11d4c3c +b8007e34bb3f927ec06a050b51e633d7eb9e9a44715d5b39712e69c36177a03cd68391090cc3293098e54f6cf65f6caf +8e85527b27c9152b1ba3fdd532a76a79064ab097570508f233e09978761dfe3012d537411b47d0e4b65265eb32cea2ae +899779f3c31a20b76068ec8d59d97a64d2249588ddfd69dcbaac6bfaee8ce0ff3c5afc4e17c934ae7cd041b760eb555d +a5dac3d8f5fbef018509612e25d179f60d2a62451c76426bf546e9666fcdc73263d34aa6fa7e2bfd4c9947bbf5095eff +896900eeef9be2b2e755128e7b1c436af6fb3984f1e66c444bc15fcf3959013b4902c381f0eab1247f878a6ebd1f4ee0 +8cb17f4b0af2e9b2cbb56f46e6a5d6874ea0daf147aae77303020b4e592ddc92e0dd058def7da96258b3a68b223bf22d +a1b6d3f09a9fa7ecc021ab7c5396541895da6e9bf1f9a156c08fc6f2b815a57f18c337ccfe540b62d79e0d261facb2be +ae70888811434ef93da60aeee44f113510069fd21161e5bb787295492eb8df85103794663fc9305f04adcbcf11ff0c5e +a84bbc8624100acfae080ba8cfb48fd4d0229a60b62d070bd08fade709efc6914dc232d3f7bed76a59204f9252321aad +aea47d54652abd8ca213cfc623c8e30780f37b095b59ac4795252a29c2b6bc703a5203acff8831314478b8ee8771d4d7 +8dd438eb8be14935f759aa93021c2b24e1d588f7a162c42c90ec3a647b0ff857f60e24c0a8953eb7bb04e04be70f11ce +922b07b5469680a10e7532766e099896f4dc3d70c522d8add18f5f7765d4ddb840df109146607b51ceddd2189fa7b9c0 +83ef6ebd0ae6c569d580093e8b0b78daa964760556272d202d343e824c38eccb424262e5b7809d3c586f9e2e9c5c5f22 +97f98bd357db6e093e967fe180cf67ed09fa711580a5ad48f07cf095b2e8fabbe6319f97d1f15d62c0ec2227569d8dbf +a1953a4a22fe6c2beaf2a5e39666b0eb53018af6976e3a7aab5515550ff2efa89400605a43fb2c4ac1e51961dbd271d8 +a5cbd67f4c0bc98e20aa74c09e6f5fb6f42c08e59aaa477b4b4e61434c8884bc14f17cf11faecf46dc4b6c055affbad2 +87d96818f2c4f12fd7705cf4060a97bd28037c5ac0f0cc38f71189ec49361e438ce863e6617651977708094d5336d1da +85e7c2daae5fe59f8a1541c94df50402a671a17dbb8838113fa4b7aaff6114cf2bb5969410cf21e6a162857f2f7a83a8 +a19575083e1731bb04bb4a49414e97aaadb36d883aa993d1f6847db50007315444814740e67e10177a14e0e074fd4c7d +a00ebfb5bcc3a6da835078189038a1e56b7dab6be74332b5ff7440e53b0f9e1eb9973effecbbf37000021fcf50c7c1ff +8969d7943abd3b1375fdfc7d6124dde82b0f7193068ed6ec83bcf908734daf3487a6a30f7b322e54a4818ae5f86d91c0 +b959c8d210fa43af9b20d1fe0ea8c4921280eb4544ef6ea913309ff9d61c9327096707e84dc1662960519be8e7d080a4 +9011d8ac651c42e0cb03931a9e960f58e02524c6b666047525e3b9097e9f35fb2b4b278efcce2bd5ad463c6d7fd56694 +937e3b22ed0fcdbd9ea5a1b97b84bbe86b7f5b2de3866a930611112f2217f4ee7d9822c4ab1253823f77bceeae0c8e10 +828997e5d121f4c305e018a0a0ba338bd6a34a7b4dc3c5ceab098ee57490311c130e2c045b9238a83908d07098d9fc32 +8d114808eac0f2e1a942d80dad16756ec24f0276763cd6771acb6049472e05a9bb1d3bbd5957f092936b415d25c746b0 +a063c5c26267ae12887387cbebbe51fd31bc604630b3a6e8e177e71d4f26263be89112cd12d139dd4c39f55f0e496be0 +ab1e1582c8d67196d10f969eeb44e6e16214f1316aa4a2a821f65ba5834326da6cba04373eabfd3b3072e79e5c9717e6 +a17b1dbaa11d41457e71a9d45d032448091df7a006c1a7836557923ab1a8d7290ec92a7a02b7e2a29fcea8f8e374c096 +a1ed7198da3591771c7c6802a1d547cf4fcd055ca9010756d2a89a49a3581dfe9886e02ee08c4a2f00b2688d0600509a +af09aa60c0a185e19b3d99ffdc8c6196d8806169086c8ff577bf3801c8ab371e74165ba0f7329981e9252bfe965be617 +98c04cc8bb26ffce187fa0051d068977c8f09303a08a575175072744e0a5fb61191b1769f663a426c30d405515329986 +a542bf1c9c3262d488ea896f973d62923be982e572172e2461e0146190f2a531f62acd44a5e955a9f1e242b3e46d63ae +aef7b7f30efd50e4a66c87482386f39f095bff6108e68f74fd3bb92156c71c75757912b111060cdee46a6b3452eed657 +8afe1e0ccd00079702f16ab364a23bbbd3da1889d07c4f8cb04fd994bf9353216360dbd364492932bfe20b8b69ae8028 +9896c690999db3c08cd7b25efb1b912c3e0f976db98a3e830f086aef93222d06ce570a7b2babcd7c81d8f9955169669c +ac7bcab6a281468907ef1ea8a6c1cd624159c88839131bef6aa0c22f331fc87ec6128a2c2a333fb79df549e4587e1a12 +987935c08a30b099d19f96901315a2e60591baf898581c40bf5eddcda806ff24a4536e30ed1e6c0b128a83fc77b6e81d +a0a6945bbede3bb09a4a09ef27baa20619d3e15af5673b9350601bcebe952597c989870746cf75767ffb73b32c6c9c6f +b0f5590079f0a0302b08a0cc1b7a5f39cc6900c2a5cdc7baa333d8328a731b2df5dbb67e27a154d3c44ed1a795fc4adb +a7294bdeea210e528f277f3d50e89e6d79950494478998181ecb38de675020130256f2f2a075899170be964d478458b0 +8ab3041b895a631869b439d5599a66facba919226ca9b39d915f19d59f9fc82393ea781377e9bd3bcc5a310e41376914 +8da399b59151fd48b2579948bb82698e3c9804d70ec7d6f3cc7e82901f9f2de5ee850349a7d6f43e5e9ebd47bd78620f +80e8c32de83d1083916d768b11a982955614a345d26d85b457f2280ff6c52bb776958add7c1c8878f7d520d815b8e014 +81bbec7bd99d2917d2dcd8a288722fb33ad5a4bf5416fba8609fa215fb80e0f873535349e7dc287f892aa56eb9e39c4a +9665796fe04c8519206fba58496bc84a8b9113e7ea8e152b65f7f732e88beea271dc97b1ea420dbc8257cc4b18a77463 +a97e342aaaf693ddc87e02790278e4bb50117af4413cd703bdf3b7cad2d1facf31fde1303b43ab2e0265467474f97a8a +925549ebebed348886e37773b05cd8ad04906eca4536bfed951d1ee41b3d362ddc6e1a302c21ff3a2d1e70e95117922c +818fdf74d7903502101551bbf48d3c7819786b04b192d9e94362d2fcb85760d8b6f45165a5443aa5221bef400525ddb4 +a9d29de7e8fd31b59f4a087168d062a478b1329cd3c81c31e56de4fb40de7a5be9a5269ef0be452c487443a0b097dd50 +a85286ad573db4c9aa56221135da1e31d742e0f6ff01d6b159086d7258f78b08dad55ec8eb5c91ee9d3404b2eeb67e1e +92a79b37db5e777f9ebbebde24a95430a199e866e56597c7d0b0e7fb54c7b092c2f6cf61fb24470ddf250cf609898281 +8d79f5ca67ed67d52c82949af342a9fc60fb793c47c76d84b4863c550796fcae2dd59e285897c6fb96fe31cee1efa62c +8ad2e0bda03415ab86324992bb62dfa3612d2d003765bcad1468087c27971d08bdbae5252681f0115a184f4885d444e4 +a08815af979286538c31b4aa5ec805053790af1ca58a8c4341be51136d094a8a05e569d876a079033298ad355ccb7ca8 +b96c2978d0165d619d08281d295e90df78bc2375d0afbc3142ebff9c2cd4b0f0aa97a9a0e3740bc4dce0ff8a9fac8252 +b7752cd0e582f35ab0d0036ca9c0a9fe893a6ad325164d78d865a604a85d3d23729e0362553e8b8a3d51816beeaa30cf +99cef1fafc29e7adfe247c753c475ad4bda7a5f9558b79c86e8a65968ede67adb38dc30071925c9d66a13860027a6735 +b9f6c65af178c791b6137d71980651fb09cb5b42f268999c728c6e129985a9c7d77b3dc3b50751bd29ec9ee0b3111dfc +8d73ae61fff5be883a281782698075c5650083f00399992688738856d76d159803be0059fbd9dec48f4f0432f0590bbb +a8a4a2865226de9bbf19e12c7e75318439fa6cf1cbf344d5e79a8f363439d3bc5bcf4df91b54581e7866e46db04eaf0d +894582aeff222e145f092ba15c60d3207340c38f2c6792ee2ab4d82d50fb544ae366c2985cc2b6c2f970bcc5f4b46385 +956014ba2d20a056fd86cb8c7ceeab9a2c6f905dae24fc1c5278fa5b84335148ebdefec5dcde8eb9b084700724fc93d7 +af217fe2b654eff6d11a2a79fe0339a1d4cb3708b7be9f09d852158b5a44b4f9b04406d6d67c4f144fb6b69a41ae9d0f +a90752a784bc00df94d960e523f5596695d16a534fc806179e0f878fc0e82a91b25e758e91a165debd815dd1af5f1028 +a697606fb32979549ad822b31df8eaaf50de4ead984439a0a33e955937d326519bb9f62c8243ad37f764655f8d32cc80 +a3ad4a30922e45a3e665551e5611384f1c2d414f6fa806184b0c826af05f014dc872585e255543794ee41e43cdadd856 +b29c255843a82ea74a013bac6c36a694646e61e6b9cefc4c130e2ee261e3bb5da3e0fe3ee7e6fbb009deed0530bc1c82 +87e1cc7febefa829cf050aa2aea59385d1048f8617abba691f7ea9ef58eb90ad12eeb9c439af228b0e34897ba1cf1b47 +994d3222f89e9c8c154362190be7167c8c2662f0cfa9d50eb4d8175b255ff0de09dc548ee312fc8226963c8c16f43e8b +8f1a980be640820f2d1e953264ca4c30330878971669852be3d5d6b41c488be1628b935388bfa2bd4de484acb0fe661d +854d90d0721579c8c88e147a4aa83553c960617b18075f8224b975562dccb30b0e02e81fa9df7070f356a0eeffc3b14f +8e156da9d4330a03e32a25a2f0b861fd3ea5c719fa4f834119baab6e5fa5236a9baaf0d44147bf0841418900037f6eac +96586fc49e53a6799242ddf617000db5a0ad20c6cb1686af2102623d64a71aaddb8e468b15fa6d100d0384e448548db4 +b44d8d85c8df95d504f82d597f8c515866d4d4a326fa1b816dcc5bb0cc4ef1a52647aa5d2e84c62e194c01cae0885d21 +b75c43e676a7efd199f8b32ae31f176ec667e714df355e9eecee97246f72af5bef9c5b04c11e7e90fc37bb9163f957ec +a49835ac0565a79f6a9078cf0443c5be20561a68b448289589721fded55188583f1d301925a34eea647f90a6e66c6774 +b47c17ff6824a00b8f29df0adb7f06223208d062bd703b0f763c6eee4ae62d4217eef2da4f4dde33f0b469c2f2db9e42 +957cf039cea6f6d41e368e2bd0cf77315938a0738f15ed9ca342f0a28658b763659ac1d1a85ecb362f13de12b77bb582 +903a52f8d2439fa63f59e1e9aba864d87b0464ded63814474947112375236a6f84e8fa003cc4433c8208d80e05fbd1b0 +8afd524209ff08d1eb6312b078f7afeb8e1155af649e930ab711dedda226dc2db6b0354aab9652eea7f433f90015bf7b +a95c3c9277b11bc8fe191773bf567641be57c0549913b973fb18740ff9cd7b3f7ce198fa4dc1086b2b8a446012459193 +9455ce8163fce04aeff61e7808ef3aac4725e51404f0858fe5d39d7344f55dcc7871ca332aa5cb1a63a4399529e48907 +809fa35b6958f94e781f2c584438b33f5ed528a6b492d08960cf22ecf63ea3aa1e2d29bc879e17296e0a6cc495439cb6 +b0f50774de212dd33e5837f6b496556215c665437e657f674fc5117e5c07dadbd0d057e6ac4c42d50a8eb81edfebf315 +844c65e263891d0b2fea7db6934cc4b7fb6bee2c1d0b9ab4c47f2eb3e9c5d7197dad828d38c54139123740151420280b +b13c78c9efcbb3b28eb3fe0b971380b7d5151c80948a99cd93c78b4c3ab0e86df6226a64d91e0a2ea4a1c0a46bc0404e +90300a541decad460c348b8f4257f7a29687b2362ebee8d92fd03cc0e85b285ccb0ab1cb2ff5e29c5cc5295e351017cd +ac49b409ded770c6d74f6e70104c2cdc95b7b90609da0743c9923179e8e5201ead03becc0ab10d65b3d91a5be0d52371 +a257b815bd8289dfdfc21af218aaba12ccfd84ebf77642cc4cf744d9b0174ca0b0d7ab2a545c2a314fd5f63c140f41ab +a34778d8446e4d74d8fe33de64b2694ef1e50bc140e252af6eff3ce7b57acf8b6577a02ba94b74a8ae32e5113cf0a29b +ab9e935bcf0d8607e3d66f013d9bce7909962cb7a81174923db02dc89e485c2b1c33d6065bdc7bbbe0450b5c49fbe640 +94d2c5c5c309c9eac04be4636f61bc47fd9579b47aded57cc6c736fefb8dfd8f8a5de32210f7baf2052d04c0219d3b4b +b8dda9046ae265214086355101be3460421f7cd0ed01bde9c1621da510941d42bc93cd8060fd73f374fb1b0a5f38d45e +a6674649dab5f92ab9fa811d9da1d342cf89ff6eff13ad49f4d81de45438e81a384098d3ae5ccce4c67bda5dbe246d95 +8d619f7564677bacba29c346c4ef67c211f7a3a14c73433dd1a7692e16a7e2562f1d0532454af62fc04c2fd2bb1789b0 +a2b93d2fd4c707f5908f624a0fc889e20164d3c61850af9125f47a1719757a6ce6375aa1910eafa4c1e8b6e20c312775 +a07d5585447654d82817ef4d199984542328b238157976eb9a267f0bdb2229acc25aee510be68f65a312b68fdd9e0447 +8ef55cf95e2b24d8ec88e4136399a7763bd1b73d5e90ea45e9845123e9d39a625cc336e9b67988374b8ebcbc75f2ed21 +b62c1fc32e27c767c461411b02fe9aa44a86586e1427406f4ef0b346d077db91952abce79318b382ec75b7be23058cac +b252900345f5fa15a4b77fb6af6a2d04db16e878b7bd98005333f7f6e3c8e6e46cf38fc5d1b2bc399c5c2ff4af730dc6 +a4ab5ac0cc15d3d17b1747c6e3133d586870eae0a0d9c8fa7fd990ebd4fbb62e9090557ca2792a6bc6271856aa3c9a05 +8e706b3f2e902faee10b22742c6c33bea6f670a8937c243db96885143c1db5c979e33ab73a38359b52b8d668ccd092a9 +8a6792190ee6c959d79f60c22980ca140c638d88d75660adaf9bcbe6dc4692ab5f01e0c460170f09f74d5e582e85ff1f +97ffeedfc94c98ec85ea937e064d7b290a326838e62cebd407facd1ab4f08d9c0c109d79af7cb6170fccfa6c8243c127 +b79970b67c09453614ffd83a0c923c17f857c6ce3c87a356298f8351cab0def7ed83efd4f6638f48df67e07bef4ad9d8 +b90f1931c7cf1822cc0a97401119910cdfd0482daf09a4d7612e4e05046295cfb4cc50d5214b31676bb1a1c9d15f9c7f +922921ad813c01fb5d12fa7fb7ed8e0b0abbf7b19affa190b36013c55b88fe3c7df0ae663c970eec7725ba37b95a7cb7 +a124f33e7f28feabb4089a063a08d52b7395d24eecd06857a720439dd9414b7073bb86fbd0b04e7bfac62d3dc0fdb2f2 +b252fe50bc6677c004550f240fe670974a33ffe7191ed7675da6ac36c780c2f8d02be7da5d92cbe2d0ce90147847f8b1 +ae5f8c9c56070f919f3df2d2284348fa4b2e39881f7bc42c9b2f5b7cb1ebeef8ecac000f37329bbe04cc1680cefc7f4e +b432a4575caf7337f11eecfcbd34a6705d0f82c216301725ceae2b3c9df20fa53d1ebef65513e305013d1e0c2df522b6 +b7c016fbbc4614cdbb12db1c9ac41f9a45d5e5ce82594d568a30cd2c66c3cc9d91a2c959697b67c582a0913de661505d +8f6f3e5e0347dddc1b2a34ec0dbbbb7cafbf976f19c9c902efb5c1427d1bbd4b71abd9f3fba20dda75c35a39393c989f +b0042a1d33a1ee9fdf3fad2299b8d70c4f1862d8393b5ebe3ac2189a2c5a58bb826128cd7a39b70d524a6dd976097e26 +85297c4e8ae8d9b44c3fe51aa926c77d55db766c2a9f91b659040de36e34c9a4fc6f44380f8d61704498f6fd52395a49 +8c61a988b6a00fe5a277450f30bf6daa932e42a2eae844568e3babf8815e09311f3c352dae6eb2d57a98d16b7beb2d22 +990be28aaecd932e7edb2a97b9be2789a3905cb88737b1c79881302585801c69a3dd5fb230808b39db1352fc06e0b4a8 +82fd14bdb335aa46f022dfe0ed4d631911e6b6f5eefb10d11e9e2e02a7df55012ed8162249d10b58eb76ced5a7b06cda +ac39cb058df764e161db9c39b185f09aa210bddbd66f681f1697ddbe6b305735612d5dd321d3ffbb4876771bdb321e2f +858a3f7e57ccb81387caf8e89f9b6039e9aadeab06886d8688fe6427151a59ab2e77e85ba850c67d099965426c97779a +b57fb9ea623cec432946819937c6bded0b5d03c8c67b52b44a4b67d34adfb055e6cabca67a48e4d859b4be45162c5083 +b84d2990b563d6d7fe1f4c1894989db25b81745090b94b1fe2ef708ac3b2110ef93d647820b2a51fcf78e3f00fef5412 +817d85b9f5e1521733d2b1fa6d4f4957ac445dc803f97fc495e20b819b14e651332f9e0573d684b854fd47824c53f0e8 +b09e18e97e93a8523101af594422fb71afc5b8826002314269016fcc1b44002d91bcb7c90d923d460f0cc03bddfe9af1 +b867cbede82102de7cf6cd0dae68506869576eaa66c3fc806e73585310602682fc912dc37adf5ff6f0f34a07831735b1 +b1126255798368b692f2796a3470ed16e5ffdee2d8c9e0f7ee3d2e92950c3e6365c32895171c3494aff2a6d6356f7e25 +b05f0a0996dec16335c770a5df3f0b08e20020c838c2caaa1d3a4a2490ede98552f5de349de2ce6e4c4a839731d80919 +98c512bb91c8fa191120ddf5d63c88076581cf41e15eec3c168822f12b3dd0ce4d6df74a7e3093d3e35cad1cb3135421 +84ce38fd97f7f90012c2c1e59a67bf9f465a7ccfb6f308bdd0446cc82b8a26ff7c30e5c7cc375011718cad1b31adaa9f +93139db52c9fb96dee97a0825f21e34c5d6d36838e1e42f4d12d01eacbe94426c85a811fe16ca78e89e08f1c27383d28 +81454037b1e7a1765f67e4288b8742eebf6d864d9b0f508ab44fa3243168ce0ed30cb5f33dfcdb995cd2c2710ff97a6d +828deb2a26efb2ff1842f735e2cc27162360f619b6e3e27a85bedf384912d4726bb2759a3016937973092ece1bf90540 +87e5a7d4e7bd301078f625d9a99b99e6e8e1207c9f8a679f8ebbbfb467bfa0b5f7ef4a4d577c7d2670efa88221153012 +b9dc9d0ea48deee201e34379447bec789c8924aecd030eeb93db159af77eff230976ef60ea9f4b4a9e9e95c1f9f4284e +aa6528268d46bf0627d87d58e243d3ac34b863513c725908a2617e4c6a46ccb1d8c8334bd6dd0eea7ffebec44259dae5 +8d26c9ce07293f6a32a664d31e6df9a7ace47e6c38001635918efd9872aceab62de7757b13b783d422eb67bd28ce7bbb +b0d3ca88d9829a7459b89b0dcbdb8bbb5180b00d750bd959bd110f53c2dd5d4db554b6005c4765fbe7ec5903669e5ebc +a94d1c72bf3b2dc6bfebc9dee40f6a89a516b252bd9f4fad96f156e3dbfc151a9b8a02324d764c7656d59230a18eb61f +88996e79171e30b16505638d8ecb25afd875e5f3cc3e29860937f2b5e751c66e78dc77f744a0cc454a8a655142a93ffb +af4d94f342665fe7ecda318de6cf1bc1c40c37dd83d060fedaf827459728152b5f0e280286ff5e6a0012036f6715f53f +96beaa7a2d565ec14a4e5cb895d33624c69da56b75c8d06ac729cb6d0cb64470ed4f9b0387083cd827b1609c8cabde8c +96b773fa2fcb7377bf71a7e286f37f1f24ee42cba5b4f33903c4566e5e5bcc501ea360e3c8435749107c3de84e272d8e +a69ac6218454c3f40ad0beb48821a218fb0a4f33ebade986d2fffd9a3900d8cfa613bc71676c46cfeaa5f644d1f239a9 +857f139c08fcc45370f448ce3e4915bcb30f23daa4134407fc6d78efac7d718b2cd89e9a743eec7bf2cc0eccf55eb907 +adeeba36af137fd3c371a2adbefea614c3ae3a69f8755ce892d0dd7102fb60717f5245d30119c69c582804e7e56f1626 +afa97ca3548b35aeda6bfed7fbb39af907ed82a09348004d5705b4bb000173270ce44eb5d181819088aa5a2f20a547a2 +8423bd2d07073b0e87819b4e81997e4d3188b0a5592621a30981dc0a5a9d0578fde1638a364f015078a001afb00891c2 +b92e9d4ec3966981ee574695d6e4865810b8e75313e48c1e4bc5eebae77eb28740e97ecc3e5c42040f9eb1ee4b13b0ea +b07b218321d54cecfcd2ed54a5fd588a6be8d7a5b6a66dff7facfe061222c40553e076e57cbdfa0bdb08e0a009c94ba5 +a71e1ae4d6096eac9ea4c21f621c875423de7c620544e520fb6ec3cb41a78554aedd79493cbd2c2ba4f0387f902ddd2a +807cdac291246a02f60c8937532c8969e689b1cfe811f239bfdee0791e7aa0545e9686cfb9ed0c1df84748e5efa5e3da +a1faeb4504c057304d27d54fb3ec681462384a354a4f0b6c759d4fa313253a789250c6b0f44f751b0718592637438a19 +996bcd3215182d49f1cd15a05e1e0a4bf57e264400bf14f7253c6611d2571de7130cce81fd28e0411e0a80e9054f4f98 +89d15b38f14bcd46f4b2dcae82b0e7bf9a35e40bf57aa947e9c4a8f87a440b5cea95229708de08ca596762062c34aaa0 +8d8ddcaf79374c750b8b0b3d196acb6bb921e51b4619876a29d09161ba82a42271066187211ef746f9f40a5ca17b75f7 +a3dc7f70f3a6c7edc483e712770abbaa94bfa3174cfee872b2cc011b267e0ef9baa1ab49e4a6c6c30dbba0e0a1237117 +aa9e958bbdcb192b19c43fc6fd34afcd754949fdada98e9f4848e8db0e23acb27d19dd073c951a8819000f2356aa22e1 +a4714e45ec853eadfe5c3bee7f683b81f97857bbd7833192a48936dd1460aee68f700a21658658b74b737c4fecf90c7f +a1ecab4215c1892e4a8ff3405d710163875e5dfef8a8cb84f5cac4e317d89c7696e3f496ed1747ca6f52b304190f4ba1 +b9b48943eca3686219575026d395b969e6ff8159dc5317005df090e79d26901984e40ae4b1af060ed3ff6f42e0417d76 +9644b9f90a66edb0396abd8c00066886f978ebf56fc22081031fbc9ce371bf9b04aa5a4ef59e59319b3a05bb7fb88b43 +b2bb14f1c055a78596488e4e2d4135a6470c1ee43961952160b8498f674a4d23040606e937c02c1fc23dbd47e9bd4633 +8c61f2fce9a42b94a389c7e52d7d093fc011099d0f4914f6d6f05b631df7b88182826edf9bbb1225971a080ca5c0d15a +aa6a7b8499cc7d256043eacad18528d38bf3be970bea4c6d4cb886690280bdb373688ceba3e506471e1d9493dc76f3f4 +8127703363b3b35b06762c2353d4de82b7b85bb860db1028d3640f46bdb78f2d104fa77ee3e0d9db83833d2b12a966f8 +b7b01f5909f2c66ae0fab156be5d79954e3a304615e1fe55945049dd4bd95f973bb3821117eb54db7e9ed1ee9a527652 +8be47ba5dfe212420649193490838670c40540e0ea24adbab18c4a66e7ac3dcf94f068dec2533b60e08c1f64e7533e54 +905a6c7e24b86aa54a05c329a6b4616d335bb0b1f1e9987562eee0acf82ad302c7c44981a1dd6b24c6121ca12fb92996 +86969ccfd91deed93b355a2c21319e3bb08cc652b741463bf68c626b7ba2afce3f7cc397f2fb74588c2893477c948ae2 +b5a9d20eb12c331d0d300fd4b85b0ac0bb74573178a5fac8ec9dce5e95acba07fab444260355ece442a846737a2dcd1c +a13497c11df21b11fc1a63b0ffdcf7f432da4dc2c98f8d07d36da4fa68aceb57af2158088e5b05e334fe0f264aeb7a97 +882e4597cc66498a45e86a2ed9ee24652da4699af00ad35f73b5e74fde6ac3cee70630962d5ddd86162d4aaf11bbc11c +b748858c2bafa4a14ce44af35195e9c52aa75e109719243bbe278095acbfd6a7ae7e084caf8dae6939039b5a4e8fd675 +83a2e0524507e74f51fe976441108f8226ba1b3a33f4e16ec45c5661ce80cb1840a93d17122cb8ca9e0f80d14f69877d +846cd2946c93ee5f24243d9ebc69936b3a1a6d59f45fec6c79b1eddf15ce30a8e73ad03cf606ee66baea3d8ff115f70f +8d98d0a3a94f6efe158f8423c041b546416145c5c2254bfa157efea0d1c99fe58acc7df6424ef29f75960b18d664ea4e +a39fa47e4b79f54dbf59d0b1726f1e78bc219fcfc56ad238c84b4b610e7892ff1e65d537baf5118a32f5e2eb80d5ee0c +8c30969a4519131de5e30121c84c04f67b98c8ad109fa4710dd3149cae303d51778add3f258f0482f1c89c169824dffc +af7f80d141ceb78b4762015de17fef49d7ff6202d292e9604deb508272ee7569f7fd5be3b2438da1dfecf0c26533ef86 +97cf82f70128251944d79b8845506975405bd720e150d836205b048ff36ba8801eb74cdcc6425f28f6bc0acec0a81463 +8c276c876eb88688957d1868bf3a1462375e608ff72b49870a5dac82cbf6584e00e3f36f236f732348a47502ccf9539d +964765f1a5c8a41d8025ddf56dc01b78424703d8a64a4e5539e477cb2445cb541c70127c561e717256d13f91a830ba83 +a2aacd9e21b8c8efaf2319611addea1b9f41430aee42e7f2a640cc693aa395287cc8fdc2806b76b577d84fbd05378ead +ab11eabbf5be4345a77323a3b75f9ee93b011fd2a9d0154e88183cafe47f82a7888666af16b40d3cb677c94bcc755ff7 +a0bfe715a7af5a29b1b6148b8cbee585d2b49fa6ce59bcd173ea3bbc60d71a62f9da27ffcbbd5a6da75502112fe44d70 +902e6cc38ee42245103d90b65028a471bc7a48b825599d361aa81d8c56e0fcf9fbe8d4c13802040d2cfb85b7e022eea1 +8832e2b5014fdef4003bdbb87e3298fdbdbbe49673f6b66e2373f1cb2605f9c4af2cdf9bfd45d1993208681d29ee1c9d +a7d39d3fa1ec1e0c87730fa43d4900e91932d1cafb36c76b2934907becf7d15a1d84d7234591ad4c322b5a24673bba8d +836ed5f09d99624204aa3aa7ac601980fda223f3b4b96b4a8fb235c574a3545d518787c12f81bd5851987f2860d41886 +94235e94445e6086f6e9331923262070a4c2ed930ec519eabb8a30133bd4fc6debb99185f4b668431fae1b485c5c81b7 +9828ffe20b9405f117dac044159be2d3c6e2b50ecdd1651d6a73f7633e6e2a7ba3d783ae939973604446d3a1ef0fb20f +92f03dc365dfe9154743ca70e6dd2758f064e3286fc543cf8c50f68effdf7c554bd17b3507c6ff4127046d9bbb5522ef +91ed07df479d8eb3d31292a0e987672a7f3d45ecafe72935b7abbc3f23493605134ce573f309e226c9efe830b6868220 +93bee582661e6d6cefeff29002afc2f36dd2c13dbf33f0574c35b290ddc426170a5f7f196369ad592efcd72cfb6f8fc0 +89a51467d966f48fed15dea5a12dda54d0015f69e2169b5e34f44c7b5a5d4c282d6f138116a0cd06a8476980e420f8d8 +b8ccebc14b6679ba2399370848864f15f63512fd6139df7359b7b93e82c1007fd85137ecb0597294b46643e1a9e7ab5e +841fa301567fc57b2cd09508ce75326684e12bfb8add671dc208f579b2500b93d5b641e9f59bba798ed4ed1259757f7d +b3cb45c15eb00b4ccb7013299f761cb8fefc17adf6db50e9ecb8abe927a3bc7f28e359e64693813e078e1dac800ad55b +96e55d3b9f445f5679e34fa5425b3e87cb221cfbdd07f8353868c7f7f4ba388ee3841cb9a1d638583bc20d03a9d071f2 +a7dee9377de740270c5b57cf86699004ba8dc2766af56b388b5cb0814ec71bb99ecf43ee3d82a552733854ecc7def0fe +b129dfff23b3c1c95ddb214c4711961fcb129efe2b6557ec9e116ada909593d0d2eec2c628434493393c58c52aa86847 +aed2670e201cb3e38a8be3c86735a4d76255e1e5a4c67b91df6ed262d09c8d10b0a3891da3e6ab934058cc9a7178931b +b20b8921ae52e5b3c94fa3a8b46489044174f7b897779e7763d6eb419e808d76705b7e7ba5131576f425aa81b6b0de53 +a7e45bbc3ba1bc36617291ba7663806e247f1b57a89e31520c64a90cbf8d426cac2e2f381338baf78c8f92fdbbcb7026 +a99e651e73a507e9e663e2364fcc193ec77e8afdc08c2bed6ad864e49b537ec31e9114ee72291a7657899f2033a849e2 +af966033636c2e9e8280d173f556fe07f8b6940bbcf6b2df7e2165c30bea66cced2596f6c17ca7c1aa0e614174953ba9 +b69ca7a79e3d55ef21e0ebdc6f0c4bd17182d30cf6290cccca7d2551c91c12b966020d8e40e4ee4179488c9809c03ae4 +b981cd36244e035fef043f70b1d7188d7cd045b4de0581c459fc5730e10eb7f3d5893b54cc4243849c0855e4e621167a +b20fea858a36921b35a3051ce787b73f70fdecd3fef283c15a2eb1bffb1dcba5991eee4a047ce4e87802da923fd9457b +b040e6f2e56dc1860274c263d4045837456f74b354a679f6b5ea70919835ebe5d32bf1f519e218730096c98ff396dc9d +8d2dd60e702c923a7204b530e7d6c193c6f93ca648c4f7bb38f4edbeb0aaed84184213afafb8db6aeb9197c24364276c +95dfa7348709e43d71285b28a0bfad3ca805b6ed4ae99753e9f736c79d58a35a3a50b42760ccdd03eda50f6e59494968 +b8585632a13f18c139a411bb2f02df809591834d127cd1ff081e26d0abfe0e3fbb54abea26538b25a0dcb4d7e969590e +b46ba47858a29c6d523c9982660949567666daf2582b93393a4802a9e077eedbc0d49d454731696bc8e46ca50c7caa40 +84b756b901b98a4404e58d70f39f6ccac877146c866732ae65e7e82727448d1550343bf7cdff1bfd4ee1ed73793db255 +83e5be888eaf877a2c755897410865f64a6d1169a8ccf0336092f3932abab915e542ab75a35ffe016042340d581ee987 +8cb274fc39285aed451a7def72cfbf73168ee10be02affe355a2bf87cf361a81ad284e9334cf00c5bf99a13d9f75e116 +91ff6220924b94ae13f50eeac16a159232e4f16a73fbd5c22c0e185cd1998403904d36bad203baa82b85819ee4a8ac10 +87f46e08e09aea2ab37b55fc300689d9b58ff3e72f1cffe023386035888f714fac4673c7c5193d3f3f3c568c640694f0 +835d7d84ca7641e1b15095830114aa6072fe12260d2202456cafe2308c22651af9ffbcf6b7e56af97167dd0c4e2a4cf2 +91202183f79794f114fd9e3b9bd05553c0e8985919965101a57d97ef666b028863e6cea9735af016dc1864f1542dee51 +81ab2b02a9b0a490a74ae615ddd4fe560734c1bfdde6b8dd13303c1481ba0e8ab14473535a93cfe4e824a0ab29445f8c +8a32d73f4fc006551d4e2c61eec6130355ec9b8c39a65c24ec1edc00e80155ca83a8ef2455e892521a3d47634d82a987 +af70d7b8f13bc90193cc1cfb0c400c4224cf10f1887848aa93e6380f7087782fc41a159926ab53c53eb95c2383b1a849 +989bf42f9d357c51774f1c7c0f7c0c46a8cb7398a74497141c32685be098e38b4230ffe833a6d880ec391a35b1a747b6 +94cb6715ee95700020c630b8c19e35f231de970219bd7e6ba7ced01899197da473b6c45cacfab0d652ddaf547b4ea58c +b12e3331f1f7d7458393a785e22e9a5e1d1daea521b4e78c0ee8ca59b41ade1735a29820e18f6afb2f2c3c56fecc16b6 +ad4b7cf654349d136fb41fb0dd65b588199f68b462b05f5c4e5c2b468bfaa6c26329033e3c3f7873dc8ace89cf873ea5 +a3279969e1ab596df0559ffc5ac7a6dc849680354e01c3f4fd34c6413a3f9f046f89c1e1be0b315d8b6dfab3d23d5c14 +ac74cc5562836ed89d09a9ae6a3644c936d64bdda9e77659d9982f1be29541b03ef2723236d5465e398373ea19a4ccc6 +98138ebce1af531dd8b631b3e74c84f0c700355a2a9bde31e5e51bb10c8bbd766559c63f6041f4002568803fe08438e0 +9006445da131349fe5714e0777a4f82a82da343612589a0c1596393e8b6894ce1cf42784f95ff67a8384ffe1f1a4ad76 +88502a84a85e4ce54cfed297b5d355867cc770a8ffd0714a6f23b1ab320a9903c6e42809e034bb67dbf94c4fc0d9c790 +aa8b4bf123d1a6ccaa44b86be8f980005f2a0a388a76cb111b0e85cd072ef64167fb0c097c7b23c4bca64c0260f6cce0 +ad49eb35dfea9feabb513a78dd1152ad7eba22fbb02a80cefc494a7037699c8df81202dfec12acc1b9e33ad680cb72d2 +8694da730231b29afd5196371ddcb15b4dcc499574bdd063f4864ab80749833ea38ab8b0ca1629a367fe378e87a60a86 +8eca7b488e810c479e7e32e24b8afcd837f7df183fe4f621a0336b53a9ed77603c84bdc365d8be68179a32b71a1deb7e +8875cd3e23c7e1af55af1b091025a08255743984186770bcd43f30b4a58d175cfdf1984bad97a15e08dac2da27198c3d +abdafcf58ec72997e494d4714645f40d09dcd0fbd0733e640eca44eeea67c25bb0c270299c459991f2fae59d13b4f4d5 +8f040970141e61489284f3efd907705eae6ec757fe8e1d284eac123d313e9ac1e8dc14ae3f04d281e1effc49d5d2f51d +a7ff115f0d2dbf66c0e8770b3d05157b37357b9e33e9a447f0f3fa9da69ad04e371fd1e4848cfb9e8d05e3165bd969d8 +a39b1a8c39d317fcc97bf6c396e6ed4a85640aeeadbf45166bd02bc3bdfb6266509159c03afd492e642384c635b824c0 +a2e1b90f3dd2d0038eaa5be52127844ccf35d997143179d95ffd3749c0896398b130094d01eb1bb31ffe80ef34b42b48 +a2bbe31f89b0c3c375ffaf63c8b7831860a921d5e388eb7907dbf61f2601ea40db86bb3952ecaa26a5eca4317a848ff9 +87d885bb0f2ce04b40ce94d2557c15f1698dc652e938f9a2d69a73ccf4899e08eafa1a59a20cae92823795f5b94f04b9 +8f7746370f8a24a2889d351f3e36b8a7d60e75e50e8f5abeea7dafc75441e95915721654e61ceac51bb6f112780d352c +a7272847526ed3d9e0d0fea1d8685b07b5b908971490bf8a46748c8b1783c629b8644feb5bac772ae615daae383d5e72 +978c9aa2996d8bd6fda7e0393fa8b38747f8f99712427705c00f6e9a12c36f8d8b4cedb03fcb9867155cbddb5200e6e1 +a4dec4a2354b2b32434c5bcdc380bf84580c6f9940f94dc0498a5bfe89c675a0921e66b807a3d859a6059a464cb2a9ac +99459ddecc7abce437f68722dae556d8ffaf8ed974f459e52e6d4a64f176caa4d42c2f2ec57e8a5b5f2034638e8acb0a +928c68c0c9213fe6258ab5bb0c693d97203d15da359784de7824dec143212da57d062a1fc70a79172cee31adc7aff382 +aad3f318f1622ea87e12541dfd982d71629b8f1ded4c301f9f6b6af9432716ad057773c33bdaa6f15dc151b0ee4505ea +8eb8e978f149a983fd6ad01773f9aacf57bd0cc622d8a301e404184b37e610123dd081faeda571a0ab1f149a3960af10 +851e7191d7b94bd422bcece5b92609fc1b1c8556229bc53e32963b2d2fd1cacd8ce5da9040b599eca6e610540f8a7987 +9414157fe9d50e5a0b5a7397417681bcb3a651eec1cab63f2a88d5df68ab1fef6e4c1d7ba657cbaf241a7cb790297633 +b5cb2dafdc5408959780754a58b2da55b2a9136672ebca42f34da4e329ddc89360e7218cde3efdbf784ddb390deacc57 +ac6b70f65503a8e94b773fda3e72615745824930114fe72b6d833484285462392617c1b2eea4a250fedbee88f503f3ba +b0829a5312f9ac6c06fddee2f835a3452fe994f6d42c9edfc390d7d5b3240ca544433b544cbbddd6516b38a6d5d7c21d +95f8e2c59905957e34d53be3d6fb85732f834e2cb9ab4c333fea2f502452a87ccd035fc9075d7c0bd8530bb0a0c96527 +b93f279b7045f2d97c674495f6e69a3e352f32f43cc60300193b936c2850b2805c15457251f7e3f633f435cb2b60405c +915abf16cba1a0b655b92a8a70c03e7fb306b86f3bbfb66967ca63e64c003b59c7a5953675efa4fa0bce9bed536b6700 +ac2047f50a319d09df1ec44d71afdcec5ac3bd2765dc98aba347734aa780863545df9f6d71214d443e3f37edc0dae45a +ad49c74ddb24c8a26b14ec08bc807313c77c5967fbb36237f55994d7511bbac8d7e7b9b8ec53eb1b3b066989f078dbd9 +961483105f605e959213fe9e8a52b76dac62d7efd2319ec71fc4e92d68fbe44cd2f65d7adefb2eb64d591b91648b8085 +b67fcafc97d8df2b3075bbff7b3d7471dbf1f3048f309e55d5e2c5bcbc7a73aebcb0697859be9f387cbc7ce98041e154 +8da70ac16468cab6066992389cb37c79ff5e0babbe67d76878aef9408b9597a3dc2eb5de87428bc761a0d78957b0eb28 +aec0ce89770d299b631f15ae12f94b1e1014ac57d38fcf037c2c7712d770d074affa06e97c60691bad8733874b6ad2ed +8b702c85fa4c915a09fc86507f44d7aeda0993b77af87780d70cc98d580c6e996b64b7c16cdb4dd4562cb0f75da36ee7 +aaeb43aa472aac2253e211fd1066c3a5422ea041cef20168702d0618a1a742a44f7fb30a76677640fea1a24e7fae1996 +a8820e92825d6e02b9b4ad5ebc86161d3244cddd3d244333ba1576b6ae10948145b68d9e926bf6b7a2c25dab4cf43f3e +8ffdae28a1f1d15d7ffa473628a66ee9a739073f59ba781248286b39cb8f7255f66d62337064246713cbb5017e615174 +adfc5dd142b7911326d8424881d5d92006f3b17de4cce91674d6ea37f00fbb266c791ac13f6c7a0f61d04f2a952e6a04 +87f98982444bf661f539bec73a10256f079a4baa88a1cea0351ae3de929e1c500485b2d1b5d933063cd7d9123d5050e4 +8f217ba4dd404c5ee384f0c9a126686db001ff0344c01c82174c5e5ef89d1a241b146008c534b13a0da6c8afe7450fbb +afc85476dddaf1cbb4ba8b22186789f3818c7964f9f613e55010278800cd95422702248bdf9c73760702ef24854795ec +a59e0f6ac2ccdfbd01f002008034390c0ea78716f5e0de4e474e3558755705c9c7afb6e3c5c4370e7bbc85958a9c7a63 +97c0695c58d792ec31d9b86d3b2fc1382f0855057b24d5f6a54c41f76f9e2f52882cadc89a8b2f121530e7f1393faa95 +8e49112de0b2649c08a96cf737af68fa8055f1af594846a2d0534c94df6f926f200405edaa6e6ac9db7e380707a2571d +99a1bd83a7ac5f8d77ddf044c80ebfc5745b998714696d67b94d185c97e9d6db989bacac646d9def463127a8b2febc00 +aba80725f9f9f7abe10760eca73ba427ca8df864a157122eb9af828a05b0199de3add02019a297750bdab5380e505c58 +ae18f62573275c1eb268f74c5e54e8958547f9e7d1d36a05b084eb53e5704fafe2200b8aff95cc7e9af5be2391c42b7c +908b8031d09d22b2aefeaa876a998e0a97c7a1070aad9e9c97836cc5aa6d2d5ef94230e1222074837b5e21b4e6490f01 +b3132282e8b41ca6789ec5c43c1fecf3a65b8eefbc2f3d10f746a843b9ba4ce6db664678e75e424f7b11a00c1440de15 +a1eb49440cc106ebc09cf198c93e8070271eb5a936d31c04858a2b311a037350100c7957d5545c9653f396aa968b91f4 +81df6ad1bdd5eee4cc2f94318467b8602d15cc1be2b48b09ade12cc46ee05cbaaf77a20397e5015030b1f1db5dd9dac0 +87236c68a2a93c8442d15d7f1d1dc01d1fd123439c183e1d843f4ddd2bcf638c128f66f1ef9b710e5d1f64a52726007a +84f2e7f85563bb2f61b10a712c7605d63f79af5be0dba056814fd3efebc20e9c53227c56577b72c68d185571b775eff6 +a36d4ae06688ece2927aeb2c7f058a3cd2aa1de1601282d4e688e1d76ef20728b892928deda2314eba41675eba3912f1 +b8326dcbcdcfce017b263c456c47692fb476c4225c95981666fff0b7d4522fc23b7f12273f0f47cf0442662124e6648f +84c66463ab277cda2cc7007d0509269e89cdd41c5e0d3773a92615f0fc5da63811186b05d7a11088048a5d4834a7e0df +b20d3571d970712ef4699b0e7034fd269c361f53e1572e2ea2676b4245e992d43b8b5931a801439a44d977a988cc360b +94dba6007e6d4998ca1eb84aa8e2a7e9f5c164b9d80df2825f2208ce5640a05aacac2e4f08918268990f43ae1ccab69a +a1c25f0b3ef9d1982153207570d9ce8d692e1b6963b509958dc4d9bcd80074bb221c46804a6d9a29e76149cc7787c282 +8857748fcdab1199fc96084323a81d3bd8b5a7f0b1abc5bc3b5252a19268344e2e7d2d086c90fc9b5fa4b92feedb93a4 +8b9c1d841447354b6c086549e4d1d435ab64c13933488c34bc30f0f6eb36c5c5b838b7b6bb018542247edd1ada091045 +8f5b655416da0e719a204fc567e93792c301acb4374cf7bbabc6ce51dbeaaadfd75c2db0e16ce073ab8e91fd3d7ea9d4 +90f2846b19be46a75c5cd0cafefcf9192e6fd80c479e8d6320c4b8d8d7d96703c9e77ff31a67afa9858e6b7bde1f7cce +a53e383947fd98aa1a55ac956214b46b20a52758461e8ba41341a23a835ebb713038bf048edb1202bbfd0b56a96bf292 +9542d7debbcfb9cda6fa279c699a7b655c03b9a9b456a5d3cfc41a826c94eafa43e01155a29e39ff0bcd965f4c0c512d +a43792864ec5fc549f7afc02622454afc0e425c310c4039ba615067243ebb26a4c7ebfd19bd4d57ff412a4bb2a7958a0 +b85123950e30c048465bf32365d24a5d4b21fffc6183cdbf71643a07b87463989b72dd9a6a47f134856f704909a6b38f +944ea689aec1376f855c0bc9c51378ad06ff758a2c075b95a60b535b88b36eca0be11e4edb5152e98cb2137d6e749f27 +a6bef52cda22325e4c62d323e2a0e3fa91c5552fcfce951edfd52ad6f652bfdcc2341f1cd349e6b5d447924dc569bfe2 +b56bff8ffe981bfcb30791836da10b87f2ccbe17ed969e7f7a650af07d27ae0223805b1264d985148208483be50578a6 +8b209cac898dd580c82d854a553e2517497ad1a4cd198e1360b8b50639b380aee70ee4b87625d9b2278228ff644cd25c +877cce233fec74c7158b3c5bf108365e98238418b8a71f058f1aca44a0fd3a1021e3e9025bd11fe244d9fe0f5034ce7f +b1b871aeedb03d6f6accc99816b89f5958178738d8d8cd9717527d04363c80fdb5f6848122ae19fdbc450cfa11e753c8 +858aca51b9e5b0a724e88688d5124eb24c9faf01a3d465e74d31de6da315f311143f22f60201ea09f62c92f61f09d889 +8521d409615dfc8c8289e00f6aaa6297c2c4e1439b25952afd76aac641b81c70b9cef07cd58c1c0198382bddd2bd8544 +88647c3e41666b88acca42505f1f5da226937e0522b538fe0cebb724e9a99730ca2522989e94a96cac94109aef675c0f +b417fdaf719caf38854e89ce52031b30ce61a632e6c3135adec9002280e022d82ab0ea4ac5ebdb21f1f0169e4c37bcda +9367a6feb5e23ea2eab8ddd5e7bdf32b4d2419fad1c71a1ed327b77362d8942dad971a1c2e6f7073885149cdf0a0c339 +a71c5c08d50c57d094d6a4f02e97d3799bada92f238ffc07bd223bbe8379507b7310d20b28f5bbbf331e5e153515e491 +9630a9a3bcb044b51299c4d3d3388a4ff47308dd27be3229601985478c0f6b55faa7e20815d8694f910611396a9d0d45 +b0bfaf56a5aa59b48960aa7c1617e832e65c823523fb2a5cd44ba606800501cf873e8db1d0dda64065285743dc40786e \ No newline at end of file From 0570b6084b25b9489b921bc5fe977b56ce4c6c33 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Tue, 11 Mar 2025 17:07:20 +0800 Subject: [PATCH 1174/1197] feat(event): optimize history event service close logic --- .../core/services/event/EventService.java | 35 +++++++++++-------- .../services/event/HistoryEventService.java | 14 ++++---- .../org/tron/core/event/EventServiceTest.java | 6 ++++ .../core/event/HistoryEventServiceTest.java | 4 +-- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/event/EventService.java b/framework/src/main/java/org/tron/core/services/event/EventService.java index 0dc61a7809c..d4ec52c7730 100644 --- a/framework/src/main/java/org/tron/core/services/event/EventService.java +++ b/framework/src/main/java/org/tron/core/services/event/EventService.java @@ -24,32 +24,34 @@ public class EventService { @Autowired private Manager manager; + private EventPluginLoader instance = EventPluginLoader.getInstance(); + public void init() { logger.info("Start to load eventPlugin. {}, {}, {} " + "block: {}, {} trx: {}, {}, {} event: {}, {} log: {}, {}, {}, {} solid: {}", manager.isEventPluginLoaded(), - EventPluginLoader.getInstance().getVersion(), - EventPluginLoader.getInstance().getStartSyncBlockNum(), + instance.getVersion(), + instance.getStartSyncBlockNum(), - EventPluginLoader.getInstance().isBlockLogTriggerEnable(), - EventPluginLoader.getInstance().isBlockLogTriggerSolidified(), + instance.isBlockLogTriggerEnable(), + instance.isBlockLogTriggerSolidified(), - EventPluginLoader.getInstance().isTransactionLogTriggerEnable(), - EventPluginLoader.getInstance().isTransactionLogTriggerSolidified(), - EventPluginLoader.getInstance().isTransactionLogTriggerEthCompatible(), + instance.isTransactionLogTriggerEnable(), + instance.isTransactionLogTriggerSolidified(), + instance.isTransactionLogTriggerEthCompatible(), - EventPluginLoader.getInstance().isContractEventTriggerEnable(), - EventPluginLoader.getInstance().isSolidityEventTriggerEnable(), + instance.isContractEventTriggerEnable(), + instance.isSolidityEventTriggerEnable(), - EventPluginLoader.getInstance().isContractLogTriggerEnable(), - EventPluginLoader.getInstance().isContractLogTriggerRedundancy(), - EventPluginLoader.getInstance().isSolidityLogTriggerEnable(), - EventPluginLoader.getInstance().isSolidityLogTriggerRedundancy(), + instance.isContractLogTriggerEnable(), + instance.isContractLogTriggerRedundancy(), + instance.isSolidityLogTriggerEnable(), + instance.isSolidityLogTriggerRedundancy(), - EventPluginLoader.getInstance().isSolidityTriggerEnable()); + instance.isSolidityTriggerEnable()); - if (!manager.isEventPluginLoaded() || EventPluginLoader.getInstance().getVersion() != 1) { + if (!manager.isEventPluginLoaded() || instance.getVersion() != 1) { return; } @@ -57,6 +59,9 @@ public void init() { } public void close() { + if (!manager.isEventPluginLoaded() || instance.getVersion() != 1) { + return; + } historyEventService.close(); blockEventLoad.close(); realtimeEventService.close(); diff --git a/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java b/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java index fb202734b22..12bdbcc3c15 100644 --- a/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java +++ b/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java @@ -29,7 +29,7 @@ public class HistoryEventService { @Autowired private Manager manager; - private volatile boolean isRunning; + private volatile Thread thread; public void init() { if (instance.getStartSyncBlockNum() <= 0) { @@ -37,22 +37,24 @@ public void init() { return; } - isRunning = true; - - new Thread(() -> syncEvent(), "history-event").start(); + thread = new Thread(() -> syncEvent(), "history-event"); + thread.start(); logger.info("History event service start."); } public void close() { - isRunning = false; + if (thread != null) { + thread.interrupt(); + } + logger.info("History event service close."); } private void syncEvent() { try { long tmp = instance.getStartSyncBlockNum(); long endNum = manager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); - while (tmp <= endNum && isRunning) { + while (tmp <= endNum) { BlockEvent blockEvent = blockEventGet.getBlockEvent(tmp); realtimeEventService.flush(blockEvent, false); solidEventService.flush(blockEvent); diff --git a/framework/src/test/java/org/tron/core/event/EventServiceTest.java b/framework/src/test/java/org/tron/core/event/EventServiceTest.java index 373bfe7d3ec..ff7aafb1d1a 100644 --- a/framework/src/test/java/org/tron/core/event/EventServiceTest.java +++ b/framework/src/test/java/org/tron/core/event/EventServiceTest.java @@ -4,6 +4,7 @@ import org.junit.Test; import org.mockito.Mockito; +import org.tron.common.logsfilter.EventPluginLoader; import org.tron.common.utils.ReflectUtils; import org.tron.core.capsule.BlockCapsule; import org.tron.core.db.Manager; @@ -38,5 +39,10 @@ public void test() { eventService.init(); eventService.close(); + + EventPluginLoader instance = mock(EventPluginLoader.class); + Mockito.when(instance.getVersion()).thenReturn(1); + ReflectUtils.setFieldValue(eventService, "instance", instance); + eventService.close(); } } diff --git a/framework/src/test/java/org/tron/core/event/HistoryEventServiceTest.java b/framework/src/test/java/org/tron/core/event/HistoryEventServiceTest.java index f51d2dbe490..b34d2a5f338 100644 --- a/framework/src/test/java/org/tron/core/event/HistoryEventServiceTest.java +++ b/framework/src/test/java/org/tron/core/event/HistoryEventServiceTest.java @@ -44,6 +44,7 @@ public void test() throws Exception { ReflectUtils.setFieldValue(historyEventService, "realtimeEventService", realtimeEventService); ReflectUtils.setFieldValue(historyEventService, "blockEventLoad", blockEventLoad); historyEventService.init(); + historyEventService.close(); solidEventService.close(); realtimeEventService.close(); blockEventLoad.close(); @@ -71,7 +72,6 @@ public void test() throws Exception { Mockito.when(blockEventGet.getBlockEvent(1)).thenReturn(be2); Mockito.when(instance.getStartSyncBlockNum()).thenReturn(1L); - ReflectUtils.setFieldValue(historyEventService, "isRunning", true); Mockito.when(dynamicPropertiesStore.getLatestSolidifiedBlockNum()).thenReturn(1L); Mockito.when(chainBaseManager.getBlockIdByNum(1L)) @@ -80,6 +80,6 @@ public void test() throws Exception { Method method1 = historyEventService.getClass().getDeclaredMethod("syncEvent"); method1.setAccessible(true); method1.invoke(historyEventService); - + historyEventService.close(); } } From 2519294ec84eace7905b9490ad77de87ed1c994a Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Tue, 11 Mar 2025 18:20:28 +0800 Subject: [PATCH 1175/1197] feat(event): improve HistoryEventService unit test --- .../test/java/org/tron/core/event/HistoryEventServiceTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/framework/src/test/java/org/tron/core/event/HistoryEventServiceTest.java b/framework/src/test/java/org/tron/core/event/HistoryEventServiceTest.java index b34d2a5f338..7a50c8a0c35 100644 --- a/framework/src/test/java/org/tron/core/event/HistoryEventServiceTest.java +++ b/framework/src/test/java/org/tron/core/event/HistoryEventServiceTest.java @@ -80,6 +80,8 @@ public void test() throws Exception { Method method1 = historyEventService.getClass().getDeclaredMethod("syncEvent"); method1.setAccessible(true); method1.invoke(historyEventService); + + historyEventService.init(); historyEventService.close(); } } From b753741f1afeded93d4609b67132d4ca58de6df1 Mon Sep 17 00:00:00 2001 From: waynercheung Date: Thu, 13 Mar 2025 22:26:10 +0800 Subject: [PATCH 1176/1197] feat(jsonrpc): eth_newFilter not supports finalized as block parameter --- .../services/jsonrpc/TronJsonRpcImpl.java | 12 +++ .../jsonrpc/filters/LogFilterWrapper.java | 3 +- .../tron/core/jsonrpc/JsonrpcServiceTest.java | 83 ++++++++++++++++++- 3 files changed, 96 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 5ff915dbdc9..8be1f6a5faa 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -138,6 +138,7 @@ public enum RequestSource { public static final String LATEST_STR = "latest"; public static final String FINALIZED_STR = "finalized"; public static final String TAG_PENDING_SUPPORT_ERROR = "TAG pending not supported"; + public static final String INVALID_BLOCK_RANGE = "invalid block range params"; private static final String JSON_ERROR = "invalid json request"; private static final String BLOCK_NUM_ERROR = "invalid block number"; @@ -1114,6 +1115,14 @@ public void disableInPBFT(String method) throws JsonRpcMethodNotFoundException { } } + public void disableFinalizedBlock(FilterRequest fr) throws JsonRpcInvalidParamsException { + // not supports finalized as block parameter + if (FINALIZED_STR.equalsIgnoreCase(fr.getFromBlock()) + || FINALIZED_STR.equalsIgnoreCase(fr.getToBlock())) { + throw new JsonRpcInvalidParamsException(INVALID_BLOCK_RANGE); + } + } + @Override public TransactionJson buildTransaction(BuildArguments args) throws JsonRpcInvalidParamsException, JsonRpcInvalidRequestException, @@ -1234,6 +1243,9 @@ public String newFilter(FilterRequest fr) throws JsonRpcInvalidParamsException, JsonRpcMethodNotFoundException { disableInPBFT("eth_newFilter"); + // not supports finalized as block parameter + disableFinalizedBlock(fr); + Map eventFilter2Result; if (getSource() == RequestSource.FULLNODE) { eventFilter2Result = eventFilter2ResultFull; diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java index 7fcbab33ee3..e1d448b00d7 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java @@ -1,6 +1,7 @@ package org.tron.core.services.jsonrpc.filters; import static org.tron.common.math.Maths.min; +import static org.tron.core.services.jsonrpc.TronJsonRpcImpl.INVALID_BLOCK_RANGE; import com.google.protobuf.ByteString; import lombok.Getter; @@ -83,7 +84,7 @@ public LogFilterWrapper(FilterRequest fr, long currentMaxBlockNum, Wallet wallet toBlockSrc = Long.MAX_VALUE; } if (fromBlockSrc > toBlockSrc) { - throw new JsonRpcInvalidParamsException("please verify: fromBlock <= toBlock"); + throw new JsonRpcInvalidParamsException(INVALID_BLOCK_RANGE); } } } diff --git a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java index 8ab6611dfdd..4cbae5ff931 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java @@ -605,7 +605,7 @@ public void testLogFilterWrapper() { LogFilterWrapper logFilterWrapper = new LogFilterWrapper(new FilterRequest("0x78", "0x14", null, null, null), 100, null); } catch (JsonRpcInvalidParamsException e) { - Assert.assertEquals("please verify: fromBlock <= toBlock", e.getMessage()); + Assert.assertEquals("invalid block range params", e.getMessage()); } //fromBlock or toBlock is not hex num @@ -644,4 +644,85 @@ public void testLogFilterWrapper() { Assert.assertEquals("Incorrect hex syntax", e.getMessage()); } } + + @Test + public void testDisableFinalizedBlock() { + + try { + tronJsonRpc.disableFinalizedBlock(new FilterRequest(null, null, null, null, null)); + } catch (Exception e) { + Assert.fail(); + } + + try { + tronJsonRpc.disableFinalizedBlock(new FilterRequest("finalized", null, null, null, null)); + } catch (Exception e) { + Assert.assertEquals("invalid block range params", e.getMessage()); + } + + try { + tronJsonRpc.disableFinalizedBlock(new FilterRequest(null, "finalized", null, null, null)); + } catch (Exception e) { + Assert.assertEquals("invalid block range params", e.getMessage()); + } + + try { + tronJsonRpc.disableFinalizedBlock(new FilterRequest("finalized", "latest", null, null, null)); + } catch (Exception e) { + Assert.assertEquals("invalid block range params", e.getMessage()); + } + + try { + tronJsonRpc.disableFinalizedBlock(new FilterRequest("0x1", "finalized", null, null, null)); + } catch (Exception e) { + Assert.assertEquals("invalid block range params", e.getMessage()); + } + + try { + tronJsonRpc.disableFinalizedBlock( + new FilterRequest("finalized", "finalized", null, null, null)); + } catch (Exception e) { + Assert.assertEquals("invalid block range params", e.getMessage()); + } + } + + @Test + public void testNewFilterFinalizedBlock() { + + try { + tronJsonRpc.newFilter(new FilterRequest(null, null, null, null, null)); + } catch (Exception e) { + Assert.fail(); + } + + try { + tronJsonRpc.newFilter(new FilterRequest("finalized", null, null, null, null)); + } catch (Exception e) { + Assert.assertEquals("invalid block range params", e.getMessage()); + } + + try { + tronJsonRpc.newFilter(new FilterRequest(null, "finalized", null, null, null)); + } catch (Exception e) { + Assert.assertEquals("invalid block range params", e.getMessage()); + } + + try { + tronJsonRpc.newFilter(new FilterRequest("finalized", "latest", null, null, null)); + } catch (Exception e) { + Assert.assertEquals("invalid block range params", e.getMessage()); + } + + try { + tronJsonRpc.newFilter(new FilterRequest("0x1", "finalized", null, null, null)); + } catch (Exception e) { + Assert.assertEquals("invalid block range params", e.getMessage()); + } + + try { + tronJsonRpc.newFilter(new FilterRequest("finalized", "finalized", null, null, null)); + } catch (Exception e) { + Assert.assertEquals("invalid block range params", e.getMessage()); + } + } } From 4e404ece6f197f4e525aa937f49b1c6b62865a82 Mon Sep 17 00:00:00 2001 From: waynercheung Date: Fri, 14 Mar 2025 09:46:24 +0800 Subject: [PATCH 1177/1197] refactor(jsonrpc): check finalized in newFilter, not as a function --- .../services/jsonrpc/TronJsonRpcImpl.java | 13 ++---- .../tron/core/jsonrpc/JsonrpcServiceTest.java | 41 ------------------- 2 files changed, 4 insertions(+), 50 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 8be1f6a5faa..6b90ec92283 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -1115,14 +1115,6 @@ public void disableInPBFT(String method) throws JsonRpcMethodNotFoundException { } } - public void disableFinalizedBlock(FilterRequest fr) throws JsonRpcInvalidParamsException { - // not supports finalized as block parameter - if (FINALIZED_STR.equalsIgnoreCase(fr.getFromBlock()) - || FINALIZED_STR.equalsIgnoreCase(fr.getToBlock())) { - throw new JsonRpcInvalidParamsException(INVALID_BLOCK_RANGE); - } - } - @Override public TransactionJson buildTransaction(BuildArguments args) throws JsonRpcInvalidParamsException, JsonRpcInvalidRequestException, @@ -1244,7 +1236,10 @@ public String newFilter(FilterRequest fr) throws JsonRpcInvalidParamsException, disableInPBFT("eth_newFilter"); // not supports finalized as block parameter - disableFinalizedBlock(fr); + if (FINALIZED_STR.equalsIgnoreCase(fr.getFromBlock()) + || FINALIZED_STR.equalsIgnoreCase(fr.getToBlock())) { + throw new JsonRpcInvalidParamsException(INVALID_BLOCK_RANGE); + } Map eventFilter2Result; if (getSource() == RequestSource.FULLNODE) { diff --git a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java index 4cbae5ff931..6a0ab4a3745 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java @@ -645,47 +645,6 @@ public void testLogFilterWrapper() { } } - @Test - public void testDisableFinalizedBlock() { - - try { - tronJsonRpc.disableFinalizedBlock(new FilterRequest(null, null, null, null, null)); - } catch (Exception e) { - Assert.fail(); - } - - try { - tronJsonRpc.disableFinalizedBlock(new FilterRequest("finalized", null, null, null, null)); - } catch (Exception e) { - Assert.assertEquals("invalid block range params", e.getMessage()); - } - - try { - tronJsonRpc.disableFinalizedBlock(new FilterRequest(null, "finalized", null, null, null)); - } catch (Exception e) { - Assert.assertEquals("invalid block range params", e.getMessage()); - } - - try { - tronJsonRpc.disableFinalizedBlock(new FilterRequest("finalized", "latest", null, null, null)); - } catch (Exception e) { - Assert.assertEquals("invalid block range params", e.getMessage()); - } - - try { - tronJsonRpc.disableFinalizedBlock(new FilterRequest("0x1", "finalized", null, null, null)); - } catch (Exception e) { - Assert.assertEquals("invalid block range params", e.getMessage()); - } - - try { - tronJsonRpc.disableFinalizedBlock( - new FilterRequest("finalized", "finalized", null, null, null)); - } catch (Exception e) { - Assert.assertEquals("invalid block range params", e.getMessage()); - } - } - @Test public void testNewFilterFinalizedBlock() { From 8841b5e2cf1f3aa949b8e6d8a439696a6162baac Mon Sep 17 00:00:00 2001 From: waynercheung Date: Fri, 14 Mar 2025 11:49:40 +0800 Subject: [PATCH 1178/1197] feat(jsonrpc): keep old version err_msg when block range is invalid(from > to) for eth_getLogs and eth_newFilter --- .../tron/core/services/jsonrpc/filters/LogFilterWrapper.java | 3 +-- .../test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java index e1d448b00d7..7fcbab33ee3 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java @@ -1,7 +1,6 @@ package org.tron.core.services.jsonrpc.filters; import static org.tron.common.math.Maths.min; -import static org.tron.core.services.jsonrpc.TronJsonRpcImpl.INVALID_BLOCK_RANGE; import com.google.protobuf.ByteString; import lombok.Getter; @@ -84,7 +83,7 @@ public LogFilterWrapper(FilterRequest fr, long currentMaxBlockNum, Wallet wallet toBlockSrc = Long.MAX_VALUE; } if (fromBlockSrc > toBlockSrc) { - throw new JsonRpcInvalidParamsException(INVALID_BLOCK_RANGE); + throw new JsonRpcInvalidParamsException("please verify: fromBlock <= toBlock"); } } } diff --git a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java index 6a0ab4a3745..7af59f28ace 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java @@ -605,7 +605,7 @@ public void testLogFilterWrapper() { LogFilterWrapper logFilterWrapper = new LogFilterWrapper(new FilterRequest("0x78", "0x14", null, null, null), 100, null); } catch (JsonRpcInvalidParamsException e) { - Assert.assertEquals("invalid block range params", e.getMessage()); + Assert.assertEquals("please verify: fromBlock <= toBlock", e.getMessage()); } //fromBlock or toBlock is not hex num From 97213d996ff954361c910e128c90ed0f297e9b77 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Fri, 14 Mar 2025 14:10:51 +0800 Subject: [PATCH 1179/1197] feat(version): update version to 4.8.0 --- framework/src/main/java/org/tron/program/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index ec0e14d786a..feff4d0f92f 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -4,7 +4,7 @@ public class Version { public static final String VERSION_NAME = "GreatVoyage-v4.7.6-12-gf4da4fafb1"; public static final String VERSION_CODE = "18386"; - private static final String VERSION = "4.7.7"; + private static final String VERSION = "4.8.0"; public static String getVersion() { return VERSION; From 4aa4a98944c71ef39006cca6bb4fd0a8b937115a Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Wed, 19 Mar 2025 17:06:03 +0800 Subject: [PATCH 1180/1197] feat(event): set internalTransactionList to null in the new event service --- .../main/java/org/tron/core/services/event/BlockEventGet.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java b/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java index fd34a1fe50f..be15a499d3f 100644 --- a/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java +++ b/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java @@ -65,7 +65,9 @@ public BlockEvent getBlockEvent(long blockNum) throws Exception { } if (instance.isTransactionLogTriggerEnable()) { - blockEvent.setTransactionLogTriggerCapsules(getTransactionLogTrigger(block, solidNum)); + List list = getTransactionLogTrigger(block, solidNum); + list.forEach(t -> t.getTransactionLogTrigger().setInternalTransactionList(null)); + blockEvent.setTransactionLogTriggerCapsules(list); } if (instance.isContractLogTriggerEnable() From 716af38ed4428c7f5c8ed32e0d822a81f08138e8 Mon Sep 17 00:00:00 2001 From: Liulei Date: Thu, 20 Mar 2025 10:45:37 +0800 Subject: [PATCH 1181/1197] opt(tvm): kzg precompile contract log --- .../src/main/java/org/tron/core/vm/PrecompiledContracts.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 8a1e7535754..5fbbdde3b21 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -2239,8 +2239,8 @@ public Pair execute(byte[] data) { } else { return Pair.of(false, DataWord.ZERO().getData()); } - } catch (RuntimeException exception) { - logger.warn("KZG point evaluation precompile contract failed", exception); + } catch (RuntimeException e) { + logger.warn("KZG point evaluation precompile contract failed {}", e.getMessage()); return Pair.of(false, DataWord.ZERO().getData()); } } From c1ecb3cbbce672e8b75de908826e409b5e43a804 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Fri, 21 Mar 2025 17:31:27 +0800 Subject: [PATCH 1182/1197] feat(event): limite block loading speed --- .../common/logsfilter/EventPluginLoader.java | 20 +++++++++ .../logsfilter/IPluginEventListener.java | 2 + .../core/services/event/BlockEventLoad.java | 10 ++++- .../services/event/HistoryEventService.java | 7 ++- .../core/event/EventPluginLoaderTest.java | 43 +++++++++++++++++++ .../core/event/HistoryEventServiceTest.java | 9 ++++ 6 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/event/EventPluginLoaderTest.java diff --git a/framework/src/main/java/org/tron/common/logsfilter/EventPluginLoader.java b/framework/src/main/java/org/tron/common/logsfilter/EventPluginLoader.java index 7896eeffae4..0a7a5ac3a76 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/EventPluginLoader.java +++ b/framework/src/main/java/org/tron/common/logsfilter/EventPluginLoader.java @@ -9,6 +9,8 @@ import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; + +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.pf4j.CompoundPluginDescriptorFinder; @@ -31,6 +33,8 @@ public class EventPluginLoader { private static EventPluginLoader instance; + private long MAX_PENDING_SIZE = 50000; + private PluginManager pluginManager = null; private List eventListeners; @@ -73,6 +77,7 @@ public class EventPluginLoader { private FilterQuery filterQuery; + @Getter private boolean useNativeQueue = false; public static EventPluginLoader getInstance() { @@ -537,6 +542,21 @@ public void postContractEventTrigger(ContractEventTrigger trigger) { } } + public boolean isBusy() { + if (useNativeQueue) { + return false; + } + int queueSize = 0; + for (IPluginEventListener listener : eventListeners) { + try { + queueSize += listener.getPendingSize(); + } catch (AbstractMethodError error) { + break; + } + } + return queueSize >= MAX_PENDING_SIZE; + } + private String toJsonString(Object data) { String jsonData = ""; diff --git a/framework/src/main/java/org/tron/common/logsfilter/IPluginEventListener.java b/framework/src/main/java/org/tron/common/logsfilter/IPluginEventListener.java index e1ef5b59536..63e23d18842 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/IPluginEventListener.java +++ b/framework/src/main/java/org/tron/common/logsfilter/IPluginEventListener.java @@ -13,6 +13,8 @@ public interface IPluginEventListener extends ExtensionPoint { // start should be called after setServerAddress, setTopic, setDBConfig void start(); + int getPendingSize(); + void handleBlockEvent(Object trigger); void handleTransactionTrigger(Object trigger); diff --git a/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java b/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java index 382973ccfa5..577190333b0 100644 --- a/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java +++ b/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java @@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.tron.common.es.ExecutorServiceManager; +import org.tron.common.logsfilter.EventPluginLoader; import org.tron.core.db.Manager; import org.tron.core.services.event.bo.BlockEvent; import org.tron.core.services.event.bo.Event; @@ -26,13 +27,19 @@ public class BlockEventLoad { @Autowired private BlockEventGet blockEventGet; + private EventPluginLoader instance = EventPluginLoader.getInstance(); + private final ScheduledExecutorService executor = ExecutorServiceManager .newSingleThreadScheduledExecutor("event-load"); + private long MAX_LOAD_NUM = 100; + public void init() { executor.scheduleWithFixedDelay(() -> { try { - load(); + if (!instance.isBusy()) { + load(); + } } catch (Exception e) { close(); logger.error("Event load service fail.", e); @@ -62,6 +69,7 @@ public synchronized void load() throws Exception { if (cacheHeadNum >= tmpNum) { return; } + tmpNum = Math.min(tmpNum, cacheHeadNum + MAX_LOAD_NUM); List l1 = new ArrayList<>(); List l2 = new ArrayList<>(); BlockEvent tmp = BlockEventCache.getHead(); diff --git a/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java b/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java index 12bdbcc3c15..8f79ee47a3c 100644 --- a/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java +++ b/framework/src/main/java/org/tron/core/services/event/HistoryEventService.java @@ -55,12 +55,17 @@ private void syncEvent() { long tmp = instance.getStartSyncBlockNum(); long endNum = manager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); while (tmp <= endNum) { + if (instance.isUseNativeQueue()) { + Thread.sleep(20); + } else if (instance.isBusy()) { + Thread.sleep(100); + continue; + } BlockEvent blockEvent = blockEventGet.getBlockEvent(tmp); realtimeEventService.flush(blockEvent, false); solidEventService.flush(blockEvent); tmp++; endNum = manager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); - Thread.sleep(30); } initEventService(manager.getChainBaseManager().getBlockIdByNum(endNum)); } catch (InterruptedException e1) { diff --git a/framework/src/test/java/org/tron/core/event/EventPluginLoaderTest.java b/framework/src/test/java/org/tron/core/event/EventPluginLoaderTest.java new file mode 100644 index 00000000000..658d42f38d9 --- /dev/null +++ b/framework/src/test/java/org/tron/core/event/EventPluginLoaderTest.java @@ -0,0 +1,43 @@ +package org.tron.core.event; + +import static org.mockito.Mockito.mock; + +import java.util.ArrayList; +import java.util.List; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; +import org.tron.common.logsfilter.EventPluginLoader; +import org.tron.common.logsfilter.IPluginEventListener; +import org.tron.common.utils.ReflectUtils; + +public class EventPluginLoaderTest { + + @Test + public void testIsBusy() { + + EventPluginLoader eventPluginLoader = EventPluginLoader.getInstance(); + ReflectUtils.setFieldValue(eventPluginLoader, "useNativeQueue", true); + boolean flag = eventPluginLoader.isBusy(); + Assert.assertFalse(flag); + + ReflectUtils.setFieldValue(eventPluginLoader, "useNativeQueue", false); + + IPluginEventListener p1 = mock(IPluginEventListener.class); + List list = new ArrayList<>(); + list.add(p1); + ReflectUtils.setFieldValue(eventPluginLoader, "eventListeners", list); + + Mockito.when(p1.getPendingSize()).thenReturn(100); + flag = eventPluginLoader.isBusy(); + Assert.assertFalse(flag); + + Mockito.when(p1.getPendingSize()).thenReturn(60000); + flag = eventPluginLoader.isBusy(); + Assert.assertTrue(flag); + + Mockito.when(p1.getPendingSize()).thenThrow(new AbstractMethodError()); + flag = eventPluginLoader.isBusy(); + Assert.assertFalse(flag); + } +} diff --git a/framework/src/test/java/org/tron/core/event/HistoryEventServiceTest.java b/framework/src/test/java/org/tron/core/event/HistoryEventServiceTest.java index 7a50c8a0c35..49f77ccf597 100644 --- a/framework/src/test/java/org/tron/core/event/HistoryEventServiceTest.java +++ b/framework/src/test/java/org/tron/core/event/HistoryEventServiceTest.java @@ -26,6 +26,9 @@ public class HistoryEventServiceTest { @Test public void test() throws Exception { EventPluginLoader instance = mock(EventPluginLoader.class); + Mockito.when(instance.isUseNativeQueue()).thenReturn(true); + Mockito.when(instance.isUseNativeQueue()).thenReturn(false); + ReflectUtils.setFieldValue(historyEventService, "instance", instance); DynamicPropertiesStore dynamicPropertiesStore = mock(DynamicPropertiesStore.class); @@ -39,6 +42,7 @@ public void test() throws Exception { SolidEventService solidEventService = new SolidEventService(); RealtimeEventService realtimeEventService = new RealtimeEventService(); BlockEventLoad blockEventLoad = new BlockEventLoad(); + ReflectUtils.setFieldValue(blockEventLoad, "instance", instance); ReflectUtils.setFieldValue(historyEventService, "solidEventService", solidEventService); ReflectUtils.setFieldValue(historyEventService, "realtimeEventService", realtimeEventService); @@ -77,11 +81,16 @@ public void test() throws Exception { Mockito.when(chainBaseManager.getBlockIdByNum(1L)) .thenReturn(new BlockCapsule.BlockId(Sha256Hash.ZERO_HASH, 1)); + Mockito.when(instance.isUseNativeQueue()).thenReturn(true); + Method method1 = historyEventService.getClass().getDeclaredMethod("syncEvent"); method1.setAccessible(true); method1.invoke(historyEventService); + Mockito.when(instance.isUseNativeQueue()).thenReturn(false); + Mockito.when(instance.isBusy()).thenReturn(true); historyEventService.init(); + Thread.sleep(1000); historyEventService.close(); } } From f22c18a9c5e78c9d119256298f8d0ead41fc1915 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Mon, 24 Mar 2025 13:28:33 +0800 Subject: [PATCH 1183/1197] use if instead of math methods --- .../java/org/tron/core/services/event/BlockEventLoad.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java b/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java index 577190333b0..75829bf0e5e 100644 --- a/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java +++ b/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java @@ -69,7 +69,9 @@ public synchronized void load() throws Exception { if (cacheHeadNum >= tmpNum) { return; } - tmpNum = Math.min(tmpNum, cacheHeadNum + MAX_LOAD_NUM); + if (tmpNum > cacheHeadNum + MAX_LOAD_NUM) { + tmpNum = cacheHeadNum + MAX_LOAD_NUM; + } List l1 = new ArrayList<>(); List l2 = new ArrayList<>(); BlockEvent tmp = BlockEventCache.getHead(); From ab4b70ba78858bbc5b9b2d7925c62f1a5533bb7f Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 24 Mar 2025 16:13:35 +0800 Subject: [PATCH 1184/1197] feat(dependencies): remove org.quartz-scheduler:quartz --- common/build.gradle | 2 - .../org/tron/common/cron/CronExpression.java | 1669 +++++++++++++++++ .../java/org/tron/common/cron/ValueSet.java | 7 + .../common/parameter/CommonParameter.java | 2 +- .../java/org/tron/core/config/args/Args.java | 2 +- .../main/java/org/tron/core/db/Manager.java | 2 +- .../tron/common/utils/ByteArrayMapTest.java | 32 +- .../org/tron/core/db/ManagerMockTest.java | 2 +- .../core/services/stop/BlockTimeStopTest.java | 18 +- gradle/verification-metadata.xml | 13 - 10 files changed, 1727 insertions(+), 22 deletions(-) create mode 100644 common/src/main/java/org/tron/common/cron/CronExpression.java create mode 100644 common/src/main/java/org/tron/common/cron/ValueSet.java diff --git a/common/build.gradle b/common/build.gradle index 25709c9b7a6..c6ce8cf44f9 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -38,8 +38,6 @@ dependencies { api group: 'com.typesafe', name: 'config', version: '1.3.2' api group: leveldbGroup, name: leveldbName, version: leveldbVersion api group: 'org.rocksdb', name: 'rocksdbjni', version: '5.15.10' - // https://mvnrepository.com/artifact/org.quartz-scheduler/quartz - api group: 'org.quartz-scheduler', name: 'quartz', version: '2.3.2' api group: 'io.prometheus', name: 'simpleclient', version: '0.15.0' api group: 'io.prometheus', name: 'simpleclient_httpserver', version: '0.15.0' api group: 'io.prometheus', name: 'simpleclient_hotspot', version: '0.15.0' diff --git a/common/src/main/java/org/tron/common/cron/CronExpression.java b/common/src/main/java/org/tron/common/cron/CronExpression.java new file mode 100644 index 00000000000..b656bdafb33 --- /dev/null +++ b/common/src/main/java/org/tron/common/cron/CronExpression.java @@ -0,0 +1,1669 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +package org.tron.common.cron; + +import java.io.Serializable; +import java.text.ParseException; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.SortedSet; +import java.util.StringTokenizer; +import java.util.TimeZone; +import java.util.TreeSet; + +/** + * Provides a parser and evaluator for unix-like cron expressions. Cron + * expressions provide the ability to specify complex time combinations such as + * "At 8:00am every Monday through Friday" or "At 1:30am every + * last Friday of the month". + *

    + * Cron expressions are comprised of 6 required fields and one optional field + * separated by white space. The fields respectively are described as follows: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Field Name Allowed Values Allowed Special Characters
    Seconds  + * 0-59  + * , - * /
    Minutes  + * 0-59  + * , - * /
    Hours  + * 0-23  + * , - * /
    Day-of-month  + * 1-31  + * , - * ? / L W
    Month  + * 0-11 or JAN-DEC  + * , - * /
    Day-of-Week  + * 1-7 or SUN-SAT  + * , - * ? / L #
    Year (Optional)  + * empty, 1970-2199  + * , - * /
    + *

    + * The '*' character is used to specify all values. For example, "*" + * in the minute field means "every minute". + *

    + * The '?' character is allowed for the day-of-month and day-of-week fields. It + * is used to specify 'no specific value'. This is useful when you need to + * specify something in one of the two fields, but not the other. + *

    + * The '-' character is used to specify ranges For example "10-12" in + * the hour field means "the hours 10, 11 and 12". + *

    + * The ',' character is used to specify additional values. For example + * "MON,WED,FRI" in the day-of-week field means "the days Monday, + * Wednesday, and Friday". + *

    + * The '/' character is used to specify increments. For example "0/15" + * in the seconds field means "the seconds 0, 15, 30, and 45". And + * "5/15" in the seconds field means "the seconds 5, 20, 35, and + * 50". Specifying '*' before the '/' is equivalent to specifying 0 is + * the value to start with. Essentially, for each field in the expression, there + * is a set of numbers that can be turned on or off. For seconds and minutes, + * the numbers range from 0 to 59. For hours 0 to 23, for days of the month 0 to + * 31, and for months 0 to 11 (JAN to DEC). The "/" character simply helps you turn + * on every "nth" value in the given set. Thus "7/6" in the + * month field only turns on month "7", it does NOT mean every 6th + * month, please note that subtlety. + *

    + * The 'L' character is allowed for the day-of-month and day-of-week fields. + * This character is short-hand for "last", but it has different + * meaning in each of the two fields. For example, the value "L" in + * the day-of-month field means "the last day of the month" - day 31 + * for January, day 28 for February on non-leap years. If used in the + * day-of-week field by itself, it simply means "7" or + * "SAT". But if used in the day-of-week field after another value, it + * means "the last xxx day of the month" - for example "6L" + * means "the last friday of the month". You can also specify an offset + * from the last day of the month, such as "L-3" which would mean the third-to-last + * day of the calendar month. When using the 'L' option, it is important not to + * specify lists, or ranges of values, as you'll get confusing/unexpected results. + *

    + * The 'W' character is allowed for the day-of-month field. This character + * is used to specify the weekday (Monday-Friday) nearest the given day. As an + * example, if you were to specify "15W" as the value for the + * day-of-month field, the meaning is: "the nearest weekday to the 15th of + * the month". So if the 15th is a Saturday, the trigger will fire on + * Friday the 14th. If the 15th is a Sunday, the trigger will fire on Monday the + * 16th. If the 15th is a Tuesday, then it will fire on Tuesday the 15th. + * However if you specify "1W" as the value for day-of-month, and the + * 1st is a Saturday, the trigger will fire on Monday the 3rd, as it will not + * 'jump' over the boundary of a month's days. The 'W' character can only be + * specified when the day-of-month is a single day, not a range or list of days. + *

    + * The 'L' and 'W' characters can also be combined for the day-of-month + * expression to yield 'LW', which translates to "last weekday of the + * month". + *

    + * The '#' character is allowed for the day-of-week field. This character is + * used to specify "the nth" XXX day of the month. For example, the + * value of "6#3" in the day-of-week field means the third Friday of + * the month (day 6 = Friday and "#3" = the 3rd one in the month). + * Other examples: "2#1" = the first Monday of the month and + * "4#5" = the fifth Wednesday of the month. Note that if you specify + * "#5" and there is not 5 of the given day-of-week in the month, then + * no firing will occur that month. If the '#' character is used, there can + * only be one expression in the day-of-week field ("3#1,6#3" is + * not valid, since there are two expressions). + *

    + * + *

    + * The legal characters and the names of months and days of the week are not + * case sensitive. + * + *

    + * NOTES: + *

      + *
    • Support for specifying both a day-of-week and a day-of-month value is + * not complete (you'll need to use the '?' character in one of these fields). + *
    • + *
    • Overflowing ranges is supported - that is, having a larger number on + * the left hand side than the right. You might do 22-2 to catch 10 o'clock + * at night until 2 o'clock in the morning, or you might have NOV-FEB. It is + * very important to note that overuse of overflowing ranges creates ranges + * that don't make sense and no effort has been made to determine which + * interpretation CronExpression chooses. An example would be + * "0 0 14-6 ? * FRI-MON".
    • + *
    + *

    + * + * @author Sharada Jambula, James House + * @author Contributions from Mads Henderson + * @author Refactoring from CronTrigger to CronExpression by Aaron Craven + */ +public final class CronExpression implements Serializable, Cloneable { + + public static final int MAX_YEAR = Calendar.getInstance().get(Calendar.YEAR) + 100; + protected static final int SECOND = 0; + protected static final int MINUTE = 1; + protected static final int HOUR = 2; + protected static final int DAY_OF_MONTH = 3; + protected static final int MONTH = 4; + protected static final int DAY_OF_WEEK = 5; + protected static final int YEAR = 6; + protected static final int ALL_SPEC_INT = 99; // '*' + protected static final int NO_SPEC_INT = 98; // '?' + protected static final Integer ALL_SPEC = ALL_SPEC_INT; + protected static final Integer NO_SPEC = NO_SPEC_INT; + + protected static final Map monthMap = new HashMap(20); + protected static final Map dayMap = new HashMap(60); + private static final long serialVersionUID = 12423409423L; + + static { + monthMap.put("JAN", 0); + monthMap.put("FEB", 1); + monthMap.put("MAR", 2); + monthMap.put("APR", 3); + monthMap.put("MAY", 4); + monthMap.put("JUN", 5); + monthMap.put("JUL", 6); + monthMap.put("AUG", 7); + monthMap.put("SEP", 8); + monthMap.put("OCT", 9); + monthMap.put("NOV", 10); + monthMap.put("DEC", 11); + + dayMap.put("SUN", 1); + dayMap.put("MON", 2); + dayMap.put("TUE", 3); + dayMap.put("WED", 4); + dayMap.put("THU", 5); + dayMap.put("FRI", 6); + dayMap.put("SAT", 7); + } + + private final String cronExpression; + protected transient TreeSet seconds; + protected transient TreeSet minutes; + protected transient TreeSet hours; + protected transient TreeSet daysOfMonth; + protected transient TreeSet months; + protected transient TreeSet daysOfWeek; + protected transient TreeSet years; + + protected transient boolean lastdayOfWeek = false; + protected transient int nthdayOfWeek = 0; + protected transient boolean lastdayOfMonth = false; + protected transient boolean nearestWeekday = false; + protected transient int lastdayOffset = 0; + protected transient boolean expressionParsed = false; + private TimeZone timeZone = null; + + /** + * Constructs a new CronExpression based on the specified + * parameter. + * + * @param cronExpression String representation of the cron expression the + * new object should represent + * @throws java.text.ParseException if the string expression cannot be parsed into a valid + * CronExpression + */ + public CronExpression(String cronExpression) throws ParseException { + if (cronExpression == null) { + throw new IllegalArgumentException("cronExpression cannot be null"); + } + + this.cronExpression = cronExpression.toUpperCase(Locale.US); + + buildExpression(this.cronExpression); + } + + /** + * Constructs a new {@code CronExpression} as a copy of an existing + * instance. + * + * @param expression The existing cron expression to be copied + */ + public CronExpression(CronExpression expression) { + /* + * We don't call the other constructor here since we need to swallow the + * ParseException. We also elide some of the sanity checking as it is + * not logically trippable. + */ + this.cronExpression = expression.getCronExpression(); + try { + buildExpression(cronExpression); + } catch (ParseException ex) { + throw new AssertionError(); + } + if (expression.getTimeZone() != null) { + setTimeZone((TimeZone) expression.getTimeZone().clone()); + } + } + + /** + * Indicates whether the specified cron expression can be parsed into a + * valid cron expression + * + * @param cronExpression the expression to evaluate + * @return a boolean indicating whether the given expression is a valid cron + * expression + */ + public static boolean isValidExpression(String cronExpression) { + + try { + new CronExpression(cronExpression); + } catch (ParseException pe) { + return false; + } + + return true; + } + + public static void validateExpression(String cronExpression) throws ParseException { + + new CronExpression(cronExpression); + } + + /** + * Indicates whether the given date satisfies the cron expression. Note that + * milliseconds are ignored, so two Dates falling on different milliseconds + * of the same second will always have the same result here. + * + * @param date the date to evaluate + * @return a boolean indicating whether the given date satisfies the cron + * expression + */ + public boolean isSatisfiedBy(Date date) { + Calendar testDateCal = Calendar.getInstance(getTimeZone()); + testDateCal.setTime(date); + testDateCal.set(Calendar.MILLISECOND, 0); + Date originalDate = testDateCal.getTime(); + + testDateCal.add(Calendar.SECOND, -1); + + Date timeAfter = getTimeAfter(testDateCal.getTime()); + + return ((timeAfter != null) && (timeAfter.equals(originalDate))); + } + + /** + * Returns the next date/time after the given date/time which + * satisfies the cron expression. + * + * @param date the date/time at which to begin the search for the next valid + * date/time + * @return the next valid date/time + */ + public Date getNextValidTimeAfter(Date date) { + return getTimeAfter(date); + } + + /** + * Returns the next date/time after the given date/time which does + * not satisfy the expression + * + * @param date the date/time at which to begin the search for the next + * invalid date/time + * @return the next valid date/time + */ + public Date getNextInvalidTimeAfter(Date date) { + long difference = 1000; + + //move back to the nearest second so differences will be accurate + Calendar adjustCal = Calendar.getInstance(getTimeZone()); + adjustCal.setTime(date); + adjustCal.set(Calendar.MILLISECOND, 0); + Date lastDate = adjustCal.getTime(); + + Date newDate; + + //FUTURE_TODO: (QUARTZ-481) IMPROVE THIS! The following is a BAD solution to this problem. Performance will be very bad here, depending on the cron expression. It is, however A solution. + + //keep getting the next included time until it's farther than one second + // apart. At that point, lastDate is the last valid fire time. We return + // the second immediately following it. + while (difference == 1000) { + newDate = getTimeAfter(lastDate); + if (newDate == null) + break; + + difference = newDate.getTime() - lastDate.getTime(); + + if (difference == 1000) { + lastDate = newDate; + } + } + + return new Date(lastDate.getTime() + 1000); + } + + /** + * Returns the time zone for which this CronExpression + * will be resolved. + */ + public TimeZone getTimeZone() { + if (timeZone == null) { + timeZone = TimeZone.getDefault(); + } + + return timeZone; + } + + /** + * Sets the time zone for which this CronExpression + * will be resolved. + */ + public void setTimeZone(TimeZone timeZone) { + this.timeZone = timeZone; + } + + /** + * Returns the string representation of the CronExpression + * + * @return a string representation of the CronExpression + */ + @Override + public String toString() { + return cronExpression; + } + + + //////////////////////////////////////////////////////////////////////////// + // + // Expression Parsing Functions + // + //////////////////////////////////////////////////////////////////////////// + + protected void buildExpression(String expression) throws ParseException { + expressionParsed = true; + + try { + + if (seconds == null) { + seconds = new TreeSet(); + } + if (minutes == null) { + minutes = new TreeSet(); + } + if (hours == null) { + hours = new TreeSet(); + } + if (daysOfMonth == null) { + daysOfMonth = new TreeSet(); + } + if (months == null) { + months = new TreeSet(); + } + if (daysOfWeek == null) { + daysOfWeek = new TreeSet(); + } + if (years == null) { + years = new TreeSet(); + } + + int exprOn = SECOND; + + StringTokenizer exprsTok = new StringTokenizer(expression, " \t", + false); + + while (exprsTok.hasMoreTokens() && exprOn <= YEAR) { + String expr = exprsTok.nextToken().trim(); + + // throw an exception if L is used with other days of the month + if (exprOn == DAY_OF_MONTH && expr.indexOf('L') != -1 && expr.length() > 1 && expr.contains(",")) { + throw new ParseException("Support for specifying 'L' and 'LW' with other days of the month is not implemented", -1); + } + // throw an exception if L is used with other days of the week + if (exprOn == DAY_OF_WEEK && expr.indexOf('L') != -1 && expr.length() > 1 && expr.contains(",")) { + throw new ParseException("Support for specifying 'L' with other days of the week is not implemented", -1); + } + if (exprOn == DAY_OF_WEEK && expr.indexOf('#') != -1 && expr.indexOf('#', expr.indexOf('#') + 1) != -1) { + throw new ParseException("Support for specifying multiple \"nth\" days is not implemented.", -1); + } + + StringTokenizer vTok = new StringTokenizer(expr, ","); + while (vTok.hasMoreTokens()) { + String v = vTok.nextToken(); + storeExpressionVals(0, v, exprOn); + } + + exprOn++; + } + + if (exprOn <= DAY_OF_WEEK) { + throw new ParseException("Unexpected end of expression.", + expression.length()); + } + + if (exprOn <= YEAR) { + storeExpressionVals(0, "*", YEAR); + } + + TreeSet dow = getSet(DAY_OF_WEEK); + TreeSet dom = getSet(DAY_OF_MONTH); + + // Copying the logic from the UnsupportedOperationException below + boolean dayOfMSpec = !dom.contains(NO_SPEC); + boolean dayOfWSpec = !dow.contains(NO_SPEC); + + if (!dayOfMSpec || dayOfWSpec) { + if (!dayOfWSpec || dayOfMSpec) { + throw new ParseException( + "Support for specifying both a day-of-week AND a day-of-month parameter is not implemented.", 0); + } + } + } catch (ParseException pe) { + throw pe; + } catch (Exception e) { + throw new ParseException("Illegal cron expression format (" + + e.toString() + ")", 0); + } + } + + protected int storeExpressionVals(int pos, String s, int type) + throws ParseException { + + int incr = 0; + int i = skipWhiteSpace(pos, s); + if (i >= s.length()) { + return i; + } + char c = s.charAt(i); + if ((c >= 'A') && (c <= 'Z') && (!s.equals("L")) && (!s.equals("LW")) && (!s.matches("^L-[0-9]*[W]?"))) { + String sub = s.substring(i, i + 3); + int sval = -1; + int eval = -1; + if (type == MONTH) { + sval = getMonthNumber(sub) + 1; + if (sval <= 0) { + throw new ParseException("Invalid Month value: '" + sub + "'", i); + } + if (s.length() > i + 3) { + c = s.charAt(i + 3); + if (c == '-') { + i += 4; + sub = s.substring(i, i + 3); + eval = getMonthNumber(sub) + 1; + if (eval <= 0) { + throw new ParseException("Invalid Month value: '" + sub + "'", i); + } + } + } + } else if (type == DAY_OF_WEEK) { + sval = getDayOfWeekNumber(sub); + if (sval < 0) { + throw new ParseException("Invalid Day-of-Week value: '" + + sub + "'", i); + } + if (s.length() > i + 3) { + c = s.charAt(i + 3); + if (c == '-') { + i += 4; + sub = s.substring(i, i + 3); + eval = getDayOfWeekNumber(sub); + if (eval < 0) { + throw new ParseException( + "Invalid Day-of-Week value: '" + sub + + "'", i); + } + } else if (c == '#') { + try { + i += 4; + nthdayOfWeek = Integer.parseInt(s.substring(i)); + if (nthdayOfWeek < 1 || nthdayOfWeek > 5) { + throw new Exception(); + } + } catch (Exception e) { + throw new ParseException( + "A numeric value between 1 and 5 must follow the '#' option", + i); + } + } else if (c == 'L') { + lastdayOfWeek = true; + i++; + } + } + + } else { + throw new ParseException( + "Illegal characters for this position: '" + sub + "'", + i); + } + if (eval != -1) { + incr = 1; + } + addToSet(sval, eval, incr, type); + return (i + 3); + } + + if (c == '?') { + i++; + if ((i + 1) < s.length() + && (s.charAt(i) != ' ' && s.charAt(i + 1) != '\t')) { + throw new ParseException("Illegal character after '?': " + + s.charAt(i), i); + } + if (type != DAY_OF_WEEK && type != DAY_OF_MONTH) { + throw new ParseException( + "'?' can only be specified for Day-of-Month or Day-of-Week.", + i); + } + if (type == DAY_OF_WEEK && !lastdayOfMonth) { + int val = daysOfMonth.last(); + if (val == NO_SPEC_INT) { + throw new ParseException( + "'?' can only be specified for Day-of-Month -OR- Day-of-Week.", + i); + } + } + + addToSet(NO_SPEC_INT, -1, 0, type); + return i; + } + + if (c == '*' || c == '/') { + if (c == '*' && (i + 1) >= s.length()) { + addToSet(ALL_SPEC_INT, -1, incr, type); + return i + 1; + } else if (c == '/' + && ((i + 1) >= s.length() || s.charAt(i + 1) == ' ' || s + .charAt(i + 1) == '\t')) { + throw new ParseException("'/' must be followed by an integer.", i); + } else if (c == '*') { + i++; + } + c = s.charAt(i); + if (c == '/') { // is an increment specified? + i++; + if (i >= s.length()) { + throw new ParseException("Unexpected end of string.", i); + } + + incr = getNumericValue(s, i); + + i++; + if (incr > 10) { + i++; + } + checkIncrementRange(incr, type, i); + } else { + incr = 1; + } + + addToSet(ALL_SPEC_INT, -1, incr, type); + return i; + } else if (c == 'L') { + i++; + if (type == DAY_OF_MONTH) { + lastdayOfMonth = true; + } + if (type == DAY_OF_WEEK) { + addToSet(7, 7, 0, type); + } + if (type == DAY_OF_MONTH && s.length() > i) { + c = s.charAt(i); + if (c == '-') { + ValueSet vs = getValue(0, s, i + 1); + lastdayOffset = vs.value; + if (lastdayOffset > 30) + throw new ParseException("Offset from last day must be <= 30", i + 1); + i = vs.pos; + } + if (s.length() > i) { + c = s.charAt(i); + if (c == 'W') { + nearestWeekday = true; + i++; + } + } + } + return i; + } else if (c >= '0' && c <= '9') { + int val = Integer.parseInt(String.valueOf(c)); + i++; + if (i >= s.length()) { + addToSet(val, -1, -1, type); + } else { + c = s.charAt(i); + if (c >= '0' && c <= '9') { + ValueSet vs = getValue(val, s, i); + val = vs.value; + i = vs.pos; + } + i = checkNext(i, s, val, type); + return i; + } + } else { + throw new ParseException("Unexpected character: " + c, i); + } + + return i; + } + + private void checkIncrementRange(int incr, int type, int idxPos) throws ParseException { + if (incr > 59 && (type == SECOND || type == MINUTE)) { + throw new ParseException("Increment > 60 : " + incr, idxPos); + } else if (incr > 23 && (type == HOUR)) { + throw new ParseException("Increment > 24 : " + incr, idxPos); + } else if (incr > 31 && (type == DAY_OF_MONTH)) { + throw new ParseException("Increment > 31 : " + incr, idxPos); + } else if (incr > 7 && (type == DAY_OF_WEEK)) { + throw new ParseException("Increment > 7 : " + incr, idxPos); + } else if (incr > 12 && (type == MONTH)) { + throw new ParseException("Increment > 12 : " + incr, idxPos); + } + } + + protected int checkNext(int pos, String s, int val, int type) + throws ParseException { + + int end = -1; + int i = pos; + + if (i >= s.length()) { + addToSet(val, end, -1, type); + return i; + } + + char c = s.charAt(pos); + + if (c == 'L') { + if (type == DAY_OF_WEEK) { + if (val < 1 || val > 7) + throw new ParseException("Day-of-Week values must be between 1 and 7", -1); + lastdayOfWeek = true; + } else { + throw new ParseException("'L' option is not valid here. (pos=" + i + ")", i); + } + TreeSet set = getSet(type); + set.add(val); + i++; + return i; + } + + if (c == 'W') { + if (type == DAY_OF_MONTH) { + nearestWeekday = true; + } else { + throw new ParseException("'W' option is not valid here. (pos=" + i + ")", i); + } + if (val > 31) + throw new ParseException("The 'W' option does not make sense with values larger than 31 (max number of days in a month)", i); + TreeSet set = getSet(type); + set.add(val); + i++; + return i; + } + + if (c == '#') { + if (type != DAY_OF_WEEK) { + throw new ParseException("'#' option is not valid here. (pos=" + i + ")", i); + } + i++; + try { + nthdayOfWeek = Integer.parseInt(s.substring(i)); + if (nthdayOfWeek < 1 || nthdayOfWeek > 5) { + throw new Exception(); + } + } catch (Exception e) { + throw new ParseException( + "A numeric value between 1 and 5 must follow the '#' option", + i); + } + + TreeSet set = getSet(type); + set.add(val); + i++; + return i; + } + + if (c == '-') { + i++; + c = s.charAt(i); + int v = Integer.parseInt(String.valueOf(c)); + end = v; + i++; + if (i >= s.length()) { + addToSet(val, end, 1, type); + return i; + } + c = s.charAt(i); + if (c >= '0' && c <= '9') { + ValueSet vs = getValue(v, s, i); + end = vs.value; + i = vs.pos; + } + if (i < s.length() && ((c = s.charAt(i)) == '/')) { + i++; + c = s.charAt(i); + int v2 = Integer.parseInt(String.valueOf(c)); + i++; + if (i >= s.length()) { + addToSet(val, end, v2, type); + return i; + } + c = s.charAt(i); + if (c >= '0' && c <= '9') { + ValueSet vs = getValue(v2, s, i); + int v3 = vs.value; + addToSet(val, end, v3, type); + i = vs.pos; + return i; + } else { + addToSet(val, end, v2, type); + return i; + } + } else { + addToSet(val, end, 1, type); + return i; + } + } + + if (c == '/') { + if ((i + 1) >= s.length() || s.charAt(i + 1) == ' ' || s.charAt(i + 1) == '\t') { + throw new ParseException("'/' must be followed by an integer.", i); + } + + i++; + c = s.charAt(i); + int v2 = Integer.parseInt(String.valueOf(c)); + i++; + if (i >= s.length()) { + checkIncrementRange(v2, type, i); + addToSet(val, end, v2, type); + return i; + } + c = s.charAt(i); + if (c >= '0' && c <= '9') { + ValueSet vs = getValue(v2, s, i); + int v3 = vs.value; + checkIncrementRange(v3, type, i); + addToSet(val, end, v3, type); + i = vs.pos; + return i; + } else { + throw new ParseException("Unexpected character '" + c + "' after '/'", i); + } + } + + addToSet(val, end, 0, type); + i++; + return i; + } + + public String getCronExpression() { + return cronExpression; + } + + public String getExpressionSummary() { + StringBuilder buf = new StringBuilder(); + + buf.append("seconds: "); + buf.append(getExpressionSetSummary(seconds)); + buf.append("\n"); + buf.append("minutes: "); + buf.append(getExpressionSetSummary(minutes)); + buf.append("\n"); + buf.append("hours: "); + buf.append(getExpressionSetSummary(hours)); + buf.append("\n"); + buf.append("daysOfMonth: "); + buf.append(getExpressionSetSummary(daysOfMonth)); + buf.append("\n"); + buf.append("months: "); + buf.append(getExpressionSetSummary(months)); + buf.append("\n"); + buf.append("daysOfWeek: "); + buf.append(getExpressionSetSummary(daysOfWeek)); + buf.append("\n"); + buf.append("lastdayOfWeek: "); + buf.append(lastdayOfWeek); + buf.append("\n"); + buf.append("nearestWeekday: "); + buf.append(nearestWeekday); + buf.append("\n"); + buf.append("NthDayOfWeek: "); + buf.append(nthdayOfWeek); + buf.append("\n"); + buf.append("lastdayOfMonth: "); + buf.append(lastdayOfMonth); + buf.append("\n"); + buf.append("years: "); + buf.append(getExpressionSetSummary(years)); + buf.append("\n"); + + return buf.toString(); + } + + protected String getExpressionSetSummary(java.util.Set set) { + + if (set.contains(NO_SPEC)) { + return "?"; + } + if (set.contains(ALL_SPEC)) { + return "*"; + } + + StringBuilder buf = new StringBuilder(); + + Iterator itr = set.iterator(); + boolean first = true; + while (itr.hasNext()) { + Integer iVal = itr.next(); + String val = iVal.toString(); + if (!first) { + buf.append(","); + } + buf.append(val); + first = false; + } + + return buf.toString(); + } + + protected String getExpressionSetSummary(java.util.ArrayList list) { + + if (list.contains(NO_SPEC)) { + return "?"; + } + if (list.contains(ALL_SPEC)) { + return "*"; + } + + StringBuilder buf = new StringBuilder(); + + Iterator itr = list.iterator(); + boolean first = true; + while (itr.hasNext()) { + Integer iVal = itr.next(); + String val = iVal.toString(); + if (!first) { + buf.append(","); + } + buf.append(val); + first = false; + } + + return buf.toString(); + } + + protected int skipWhiteSpace(int i, String s) { + for (; i < s.length() && (s.charAt(i) == ' ' || s.charAt(i) == '\t'); i++) { + ; + } + + return i; + } + + protected int findNextWhiteSpace(int i, String s) { + for (; i < s.length() && (s.charAt(i) != ' ' || s.charAt(i) != '\t'); i++) { + ; + } + + return i; + } + + protected void addToSet(int val, int end, int incr, int type) + throws ParseException { + + TreeSet set = getSet(type); + + if (type == SECOND || type == MINUTE) { + if ((val < 0 || val > 59 || end > 59) && (val != ALL_SPEC_INT)) { + throw new ParseException( + "Minute and Second values must be between 0 and 59", + -1); + } + } else if (type == HOUR) { + if ((val < 0 || val > 23 || end > 23) && (val != ALL_SPEC_INT)) { + throw new ParseException( + "Hour values must be between 0 and 23", -1); + } + } else if (type == DAY_OF_MONTH) { + if ((val < 1 || val > 31 || end > 31) && (val != ALL_SPEC_INT) + && (val != NO_SPEC_INT)) { + throw new ParseException( + "Day of month values must be between 1 and 31", -1); + } + } else if (type == MONTH) { + if ((val < 1 || val > 12 || end > 12) && (val != ALL_SPEC_INT)) { + throw new ParseException( + "Month values must be between 1 and 12", -1); + } + } else if (type == DAY_OF_WEEK) { + if ((val == 0 || val > 7 || end > 7) && (val != ALL_SPEC_INT) + && (val != NO_SPEC_INT)) { + throw new ParseException( + "Day-of-Week values must be between 1 and 7", -1); + } + } + + if ((incr == 0 || incr == -1) && val != ALL_SPEC_INT) { + if (val != -1) { + set.add(val); + } else { + set.add(NO_SPEC); + } + + return; + } + + int startAt = val; + int stopAt = end; + + if (val == ALL_SPEC_INT && incr <= 0) { + incr = 1; + set.add(ALL_SPEC); // put in a marker, but also fill values + } + + if (type == SECOND || type == MINUTE) { + if (stopAt == -1) { + stopAt = 59; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 0; + } + } else if (type == HOUR) { + if (stopAt == -1) { + stopAt = 23; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 0; + } + } else if (type == DAY_OF_MONTH) { + if (stopAt == -1) { + stopAt = 31; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1; + } + } else if (type == MONTH) { + if (stopAt == -1) { + stopAt = 12; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1; + } + } else if (type == DAY_OF_WEEK) { + if (stopAt == -1) { + stopAt = 7; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1; + } + } else if (type == YEAR) { + if (stopAt == -1) { + stopAt = MAX_YEAR; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1970; + } + } + + // if the end of the range is before the start, then we need to overflow into + // the next day, month etc. This is done by adding the maximum amount for that + // type, and using modulus max to determine the value being added. + int max = -1; + if (stopAt < startAt) { + switch (type) { + case SECOND: + max = 60; + break; + case MINUTE: + max = 60; + break; + case HOUR: + max = 24; + break; + case MONTH: + max = 12; + break; + case DAY_OF_WEEK: + max = 7; + break; + case DAY_OF_MONTH: + max = 31; + break; + case YEAR: + throw new IllegalArgumentException("Start year must be less than stop year"); + default: + throw new IllegalArgumentException("Unexpected type encountered"); + } + stopAt += max; + } + + for (int i = startAt; i <= stopAt; i += incr) { + if (max == -1) { + // ie: there's no max to overflow over + set.add(i); + } else { + // take the modulus to get the real value + int i2 = i % max; + + // 1-indexed ranges should not include 0, and should include their max + if (i2 == 0 && (type == MONTH || type == DAY_OF_WEEK || type == DAY_OF_MONTH)) { + i2 = max; + } + + set.add(i2); + } + } + } + + TreeSet getSet(int type) { + switch (type) { + case SECOND: + return seconds; + case MINUTE: + return minutes; + case HOUR: + return hours; + case DAY_OF_MONTH: + return daysOfMonth; + case MONTH: + return months; + case DAY_OF_WEEK: + return daysOfWeek; + case YEAR: + return years; + default: + return null; + } + } + + protected ValueSet getValue(int v, String s, int i) { + char c = s.charAt(i); + StringBuilder s1 = new StringBuilder(String.valueOf(v)); + while (c >= '0' && c <= '9') { + s1.append(c); + i++; + if (i >= s.length()) { + break; + } + c = s.charAt(i); + } + ValueSet val = new ValueSet(); + + val.pos = (i < s.length()) ? i : i + 1; + val.value = Integer.parseInt(s1.toString()); + return val; + } + + protected int getNumericValue(String s, int i) { + int endOfVal = findNextWhiteSpace(i, s); + String val = s.substring(i, endOfVal); + return Integer.parseInt(val); + } + + protected int getMonthNumber(String s) { + Integer integer = monthMap.get(s); + + if (integer == null) { + return -1; + } + + return integer; + } + + protected int getDayOfWeekNumber(String s) { + Integer integer = dayMap.get(s); + + if (integer == null) { + return -1; + } + + return integer; + } + + //////////////////////////////////////////////////////////////////////////// + // + // Computation Functions + // + //////////////////////////////////////////////////////////////////////////// + + public Date getTimeAfter(Date afterTime) { + + // Computation is based on Gregorian year only. + Calendar cl = new java.util.GregorianCalendar(getTimeZone()); + + // move ahead one second, since we're computing the time *after* the + // given time + afterTime = new Date(afterTime.getTime() + 1000); + // CronTrigger does not deal with milliseconds + cl.setTime(afterTime); + cl.set(Calendar.MILLISECOND, 0); + + boolean gotOne = false; + // loop until we've computed the next time, or we've past the endTime + while (!gotOne) { + + //if (endTime != null && cl.getTime().after(endTime)) return null; + if (cl.get(Calendar.YEAR) > 2999) { // prevent endless loop... + return null; + } + + SortedSet st = null; + int t = 0; + + int sec = cl.get(Calendar.SECOND); + int min = cl.get(Calendar.MINUTE); + + // get second................................................. + st = seconds.tailSet(sec); + if (st != null && st.size() != 0) { + sec = st.first(); + } else { + sec = seconds.first(); + min++; + cl.set(Calendar.MINUTE, min); + } + cl.set(Calendar.SECOND, sec); + + min = cl.get(Calendar.MINUTE); + int hr = cl.get(Calendar.HOUR_OF_DAY); + t = -1; + + // get minute................................................. + st = minutes.tailSet(min); + if (st != null && st.size() != 0) { + t = min; + min = st.first(); + } else { + min = minutes.first(); + hr++; + } + if (min != t) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, min); + setCalendarHour(cl, hr); + continue; + } + cl.set(Calendar.MINUTE, min); + + hr = cl.get(Calendar.HOUR_OF_DAY); + int day = cl.get(Calendar.DAY_OF_MONTH); + t = -1; + + // get hour................................................... + st = hours.tailSet(hr); + if (st != null && st.size() != 0) { + t = hr; + hr = st.first(); + } else { + hr = hours.first(); + day++; + } + if (hr != t) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.DAY_OF_MONTH, day); + setCalendarHour(cl, hr); + continue; + } + cl.set(Calendar.HOUR_OF_DAY, hr); + + day = cl.get(Calendar.DAY_OF_MONTH); + int mon = cl.get(Calendar.MONTH) + 1; + // '+ 1' because calendar is 0-based for this field, and we are + // 1-based + t = -1; + int tmon = mon; + + // get day................................................... + boolean dayOfMSpec = !daysOfMonth.contains(NO_SPEC); + boolean dayOfWSpec = !daysOfWeek.contains(NO_SPEC); + if (dayOfMSpec && !dayOfWSpec) { // get day by day of month rule + st = daysOfMonth.tailSet(day); + if (lastdayOfMonth) { + if (!nearestWeekday) { + t = day; + day = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + day -= lastdayOffset; + if (t > day) { + mon++; + if (mon > 12) { + mon = 1; + tmon = 3333; // ensure test of mon != tmon further below fails + cl.add(Calendar.YEAR, 1); + } + day = 1; + } + } else { + t = day; + day = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + day -= lastdayOffset; + + java.util.Calendar tcal = java.util.Calendar.getInstance(getTimeZone()); + tcal.set(Calendar.SECOND, 0); + tcal.set(Calendar.MINUTE, 0); + tcal.set(Calendar.HOUR_OF_DAY, 0); + tcal.set(Calendar.DAY_OF_MONTH, day); + tcal.set(Calendar.MONTH, mon - 1); + tcal.set(Calendar.YEAR, cl.get(Calendar.YEAR)); + + int ldom = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + int dow = tcal.get(Calendar.DAY_OF_WEEK); + + if (dow == Calendar.SATURDAY && day == 1) { + day += 2; + } else if (dow == Calendar.SATURDAY) { + day -= 1; + } else if (dow == Calendar.SUNDAY && day == ldom) { + day -= 2; + } else if (dow == Calendar.SUNDAY) { + day += 1; + } + + tcal.set(Calendar.SECOND, sec); + tcal.set(Calendar.MINUTE, min); + tcal.set(Calendar.HOUR_OF_DAY, hr); + tcal.set(Calendar.DAY_OF_MONTH, day); + tcal.set(Calendar.MONTH, mon - 1); + Date nTime = tcal.getTime(); + if (nTime.before(afterTime)) { + day = 1; + mon++; + } + } + } else if (nearestWeekday) { + t = day; + day = daysOfMonth.first(); + + java.util.Calendar tcal = java.util.Calendar.getInstance(getTimeZone()); + tcal.set(Calendar.SECOND, 0); + tcal.set(Calendar.MINUTE, 0); + tcal.set(Calendar.HOUR_OF_DAY, 0); + tcal.set(Calendar.DAY_OF_MONTH, day); + tcal.set(Calendar.MONTH, mon - 1); + tcal.set(Calendar.YEAR, cl.get(Calendar.YEAR)); + + int ldom = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + int dow = tcal.get(Calendar.DAY_OF_WEEK); + + if (dow == Calendar.SATURDAY && day == 1) { + day += 2; + } else if (dow == Calendar.SATURDAY) { + day -= 1; + } else if (dow == Calendar.SUNDAY && day == ldom) { + day -= 2; + } else if (dow == Calendar.SUNDAY) { + day += 1; + } + + + tcal.set(Calendar.SECOND, sec); + tcal.set(Calendar.MINUTE, min); + tcal.set(Calendar.HOUR_OF_DAY, hr); + tcal.set(Calendar.DAY_OF_MONTH, day); + tcal.set(Calendar.MONTH, mon - 1); + Date nTime = tcal.getTime(); + if (nTime.before(afterTime)) { + day = daysOfMonth.first(); + mon++; + } + } else if (st != null && st.size() != 0) { + t = day; + day = st.first(); + // make sure we don't over-run a short month, such as february + int lastDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + if (day > lastDay) { + day = daysOfMonth.first(); + mon++; + } + } else { + day = daysOfMonth.first(); + mon++; + } + + if (day != t || mon != tmon) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, day); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' because calendar is 0-based for this field, and we + // are 1-based + continue; + } + } else if (dayOfWSpec && !dayOfMSpec) { // get day by day of week rule + if (lastdayOfWeek) { // are we looking for the last XXX day of + // the month? + int dow = daysOfWeek.first(); // desired + // d-o-w + int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w + int daysToAdd = 0; + if (cDow < dow) { + daysToAdd = dow - cDow; + } + if (cDow > dow) { + daysToAdd = dow + (7 - cDow); + } + + int lDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + + if (day + daysToAdd > lDay) { // did we already miss the + // last one? + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, mon); + // no '- 1' here because we are promoting the month + continue; + } + + // find date of last occurrence of this day in this month... + while ((day + daysToAdd + 7) <= lDay) { + daysToAdd += 7; + } + + day += daysToAdd; + + if (daysToAdd > 0) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, day); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' here because we are not promoting the month + continue; + } + + } else if (nthdayOfWeek != 0) { + // are we looking for the Nth XXX day in the month? + int dow = daysOfWeek.first(); // desired + // d-o-w + int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w + int daysToAdd = 0; + if (cDow < dow) { + daysToAdd = dow - cDow; + } else if (cDow > dow) { + daysToAdd = dow + (7 - cDow); + } + + boolean dayShifted = false; + if (daysToAdd > 0) { + dayShifted = true; + } + + day += daysToAdd; + int weekOfMonth = day / 7; + if (day % 7 > 0) { + weekOfMonth++; + } + + daysToAdd = (nthdayOfWeek - weekOfMonth) * 7; + day += daysToAdd; + if (daysToAdd < 0 + || day > getLastDayOfMonth(mon, cl + .get(Calendar.YEAR))) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, mon); + // no '- 1' here because we are promoting the month + continue; + } else if (daysToAdd > 0 || dayShifted) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, day); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' here because we are NOT promoting the month + continue; + } + } else { + int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w + int dow = daysOfWeek.first(); // desired + // d-o-w + st = daysOfWeek.tailSet(cDow); + if (st != null && st.size() > 0) { + dow = st.first(); + } + + int daysToAdd = 0; + if (cDow < dow) { + daysToAdd = dow - cDow; + } + if (cDow > dow) { + daysToAdd = dow + (7 - cDow); + } + + int lDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + + if (day + daysToAdd > lDay) { // will we pass the end of + // the month? + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, mon); + // no '- 1' here because we are promoting the month + continue; + } else if (daysToAdd > 0) { // are we swithing days? + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, day + daysToAdd); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' because calendar is 0-based for this field, + // and we are 1-based + continue; + } + } + } else { // dayOfWSpec && !dayOfMSpec + throw new UnsupportedOperationException( + "Support for specifying both a day-of-week AND a day-of-month parameter is not implemented."); + } + cl.set(Calendar.DAY_OF_MONTH, day); + + mon = cl.get(Calendar.MONTH) + 1; + // '+ 1' because calendar is 0-based for this field, and we are + // 1-based + int year = cl.get(Calendar.YEAR); + t = -1; + + // test for expressions that never generate a valid fire date, + // but keep looping... + if (year > MAX_YEAR) { + return null; + } + + // get month................................................... + st = months.tailSet(mon); + if (st != null && st.size() != 0) { + t = mon; + mon = st.first(); + } else { + mon = months.first(); + year++; + } + if (mon != t) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' because calendar is 0-based for this field, and we are + // 1-based + cl.set(Calendar.YEAR, year); + continue; + } + cl.set(Calendar.MONTH, mon - 1); + // '- 1' because calendar is 0-based for this field, and we are + // 1-based + + year = cl.get(Calendar.YEAR); + t = -1; + + // get year................................................... + st = years.tailSet(year); + if (st != null && st.size() != 0) { + t = year; + year = st.first(); + } else { + return null; // ran out of years... + } + + if (year != t) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, 0); + // '- 1' because calendar is 0-based for this field, and we are + // 1-based + cl.set(Calendar.YEAR, year); + continue; + } + cl.set(Calendar.YEAR, year); + + gotOne = true; + } // while( !done ) + + return cl.getTime(); + } + + /** + * Advance the calendar to the particular hour paying particular attention + * to daylight saving problems. + * + * @param cal the calendar to operate on + * @param hour the hour to set + */ + protected void setCalendarHour(Calendar cal, int hour) { + cal.set(java.util.Calendar.HOUR_OF_DAY, hour); + if (cal.get(java.util.Calendar.HOUR_OF_DAY) != hour && hour != 24) { + cal.set(java.util.Calendar.HOUR_OF_DAY, hour + 1); + } + } + + /** + * NOT YET IMPLEMENTED: Returns the time before the given time + * that the CronExpression matches. + */ + public Date getTimeBefore(Date endTime) { + // FUTURE_TODO: implement QUARTZ-423 + return null; + } + + /** + * NOT YET IMPLEMENTED: Returns the final time that the + * CronExpression will match. + */ + public Date getFinalFireTime() { + // FUTURE_TODO: implement QUARTZ-423 + return null; + } + + protected boolean isLeapYear(int year) { + return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)); + } + + protected int getLastDayOfMonth(int monthNum, int year) { + + switch (monthNum) { + case 1: + return 31; + case 2: + return (isLeapYear(year)) ? 29 : 28; + case 3: + return 31; + case 4: + return 30; + case 5: + return 31; + case 6: + return 30; + case 7: + return 31; + case 8: + return 31; + case 9: + return 30; + case 10: + return 31; + case 11: + return 30; + case 12: + return 31; + default: + throw new IllegalArgumentException("Illegal month number: " + + monthNum); + } + } + + + private void readObject(java.io.ObjectInputStream stream) + throws java.io.IOException, ClassNotFoundException { + + stream.defaultReadObject(); + try { + buildExpression(cronExpression); + } catch (Exception ignore) { + } // never happens + } + + @Override + @Deprecated + public Object clone() { + return new CronExpression(this); + } +} diff --git a/common/src/main/java/org/tron/common/cron/ValueSet.java b/common/src/main/java/org/tron/common/cron/ValueSet.java new file mode 100644 index 00000000000..74469a62b48 --- /dev/null +++ b/common/src/main/java/org/tron/common/cron/ValueSet.java @@ -0,0 +1,7 @@ +package org.tron.common.cron; + +class ValueSet { + public int value; + + public int pos; +} diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 16fb752d82a..23974183fdc 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -8,7 +8,7 @@ import java.util.Set; import lombok.Getter; import lombok.Setter; -import org.quartz.CronExpression; +import org.tron.common.cron.CronExpression; import org.tron.common.args.GenesisBlock; import org.tron.common.config.DbBackupConfig; import org.tron.common.logsfilter.EventPluginConfig; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index edf82c3068c..b09b3b8c847 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -42,7 +42,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.quartz.CronExpression; +import org.tron.common.cron.CronExpression; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.common.args.Account; diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 3635f38d9ad..d856ccb8a11 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -46,7 +46,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.bouncycastle.util.encoders.Hex; -import org.quartz.CronExpression; +import org.tron.common.cron.CronExpression; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.api.GrpcAPI.TransactionInfoList; diff --git a/framework/src/test/java/org/tron/common/utils/ByteArrayMapTest.java b/framework/src/test/java/org/tron/common/utils/ByteArrayMapTest.java index 8abdc3e3def..b367ade7e4f 100644 --- a/framework/src/test/java/org/tron/common/utils/ByteArrayMapTest.java +++ b/framework/src/test/java/org/tron/common/utils/ByteArrayMapTest.java @@ -8,14 +8,14 @@ import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; -import com.mchange.v2.collection.MapEntry; import java.util.Collection; import java.util.HashSet; import java.util.Map; +import java.util.Objects; import java.util.Set; +import lombok.Getter; import org.junit.Before; import org.junit.Test; -import org.tron.core.db.ByteArrayWrapper; public class ByteArrayMapTest { @@ -142,4 +142,32 @@ public void test() { assertTrue(testMap.hashCode() <= 0); assertNotNull(testMap.toString()); } + + + @Getter + static class MapEntry implements Map.Entry { + K key; + V value; + + public MapEntry(K key, V value) { + this.key = key; + this.value = value; + } + + public V setValue(V o) { + throw new UnsupportedOperationException(); + } + + public boolean equals(Object o) { + if (o instanceof Map.Entry) { + Map.Entry other = (Map.Entry) o; + return Objects.equals(key, other.getKey()) && Objects.equals(value, other.getValue()); + } + return false; + } + + public int hashCode() { + return Objects.hashCode(key) ^ Objects.hashCode(value); + } + } } diff --git a/framework/src/test/java/org/tron/core/db/ManagerMockTest.java b/framework/src/test/java/org/tron/core/db/ManagerMockTest.java index 65726857809..364b86c82b4 100644 --- a/framework/src/test/java/org/tron/core/db/ManagerMockTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerMockTest.java @@ -31,7 +31,7 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import org.quartz.CronExpression; +import org.tron.common.cron.CronExpression; import org.tron.common.parameter.CommonParameter; import org.tron.common.runtime.ProgramResult; import org.tron.common.utils.Sha256Hash; diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java index 86c32e66507..c529cafbba9 100644 --- a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java @@ -5,7 +5,8 @@ import java.util.Date; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; -import org.quartz.CronExpression; +import org.junit.Test; +import org.tron.common.cron.CronExpression; import org.tron.common.parameter.CommonParameter; @Slf4j @@ -25,6 +26,21 @@ public class BlockTimeStopTest extends ConditionallyStopTest { } } + @Test + public void isValidExpression() { + Assert.assertTrue(CronExpression.isValidExpression(cronExpression.getCronExpression())); + ParseException err = Assert.assertThrows(ParseException.class, () -> + CronExpression.validateExpression("invalid expression")); + Assert.assertEquals("Illegal characters for this position: 'INV'", err.getMessage()); + } + + @Test + public void getNextTime() { + Date date = cronExpression.getNextValidTimeAfter(new Date()); + Date invalidDate = cronExpression.getNextInvalidTimeAfter(new Date()); + Assert.assertNotEquals(date, invalidDate); + } + protected void initParameter(CommonParameter parameter) { parameter.setShutdownBlockTime(cronExpression); diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 34ab41b748a..b3c879f6b40 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2088,19 +2088,6 @@ - - - - - - - - - - - - - From ee58884a50fabe0654e41edef6b642d57c26d9f2 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Tue, 25 Mar 2025 22:31:27 +0800 Subject: [PATCH 1185/1197] feat(CI): fix Sonar Check & CheckStyle --- .../org/tron/common/cron/CronExpression.java | 762 ++++++------------ .../java/org/tron/common/cron/ValueSet.java | 4 +- .../java/org/tron/core/config/args/Args.java | 2 +- .../main/java/org/tron/core/db/Manager.java | 2 +- .../tron/common/cron/CronExpressionTest.java | 450 +++++++++++ .../core/services/stop/BlockTimeStopTest.java | 16 - 6 files changed, 706 insertions(+), 530 deletions(-) create mode 100644 framework/src/test/java/org/tron/common/cron/CronExpressionTest.java diff --git a/common/src/main/java/org/tron/common/cron/CronExpression.java b/common/src/main/java/org/tron/common/cron/CronExpression.java index b656bdafb33..0445ec2ce5b 100644 --- a/common/src/main/java/org/tron/common/cron/CronExpression.java +++ b/common/src/main/java/org/tron/common/cron/CronExpression.java @@ -1,5 +1,6 @@ /* * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * Copyright IBM Corp. 2024, 2025 * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -22,9 +23,9 @@ import java.util.Calendar; import java.util.Date; import java.util.HashMap; -import java.util.Iterator; import java.util.Locale; import java.util.Map; +import java.util.Optional; import java.util.SortedSet; import java.util.StringTokenizer; import java.util.TimeZone; @@ -35,83 +36,86 @@ * expressions provide the ability to specify complex time combinations such as * "At 8:00am every Monday through Friday" or "At 1:30am every * last Friday of the month". - *

    + *

    * Cron expressions are comprised of 6 required fields and one optional field * separated by white space. The fields respectively are described as follows: - * - * + *

    + *
    + * * - * - * - * - * - * + * + * + * + * + * * * - * - * - * + * + * + * + * + * * * - * - * - * + * + * + * + * + * * * - * - * - * + * + * + * + * + * * * - * - * - * + * + * + * + * + * * * - * - * - * + * + * + * + * + * * * - * - * - * + * + * + * + * + * * * - * - * - * + * + * + * + * + * * *
    Examples of cron expressions and their meanings.
    Field Name Allowed Values Allowed Special CharactersField Name Allowed Values Allowed Special Characters
    Seconds  - * 0-59  - * , - * /Seconds 0-59 , - * /
    Minutes  - * 0-59  - * , - * /Minutes 0-59 , - * /
    Hours  - * 0-23  - * , - * /Hours 0-23 , - * /
    Day-of-month  - * 1-31  - * , - * ? / L WDay-of-month 1-31 , - * ? / L W
    Month  - * 0-11 or JAN-DEC  - * , - * /Month 0-11 or JAN-DEC , - * /
    Day-of-Week  - * 1-7 or SUN-SAT  - * , - * ? / L #Day-of-Week 1-7 or SUN-SAT , - * ? / L #
    Year (Optional)  - * empty, 1970-2199  - * , - * /Year (Optional) empty, 1970-2199 , - * /
    - *

    + *

    * The '*' character is used to specify all values. For example, "*" * in the minute field means "every minute". - *

    + *

    + *

    * The '?' character is allowed for the day-of-month and day-of-week fields. It * is used to specify 'no specific value'. This is useful when you need to * specify something in one of the two fields, but not the other. - *

    + *

    * The '-' character is used to specify ranges For example "10-12" in * the hour field means "the hours 10, 11 and 12". - *

    + *

    * The ',' character is used to specify additional values. For example * "MON,WED,FRI" in the day-of-week field means "the days Monday, * Wednesday, and Friday". - *

    + *

    + *

    * The '/' character is used to specify increments. For example "0/15" * in the seconds field means "the seconds 0, 15, 30, and 45". And * "5/15" in the seconds field means "the seconds 5, 20, 35, and @@ -123,7 +127,8 @@ * on every "nth" value in the given set. Thus "7/6" in the * month field only turns on month "7", it does NOT mean every 6th * month, please note that subtlety. - *

    + *

    + *

    * The 'L' character is allowed for the day-of-month and day-of-week fields. * This character is short-hand for "last", but it has different * meaning in each of the two fields. For example, the value "L" in @@ -136,7 +141,8 @@ * from the last day of the month, such as "L-3" which would mean the third-to-last * day of the calendar month. When using the 'L' option, it is important not to * specify lists, or ranges of values, as you'll get confusing/unexpected results. - *

    + *

    + *

    * The 'W' character is allowed for the day-of-month field. This character * is used to specify the weekday (Monday-Friday) nearest the given day. As an * example, if you were to specify "15W" as the value for the @@ -148,11 +154,13 @@ * 1st is a Saturday, the trigger will fire on Monday the 3rd, as it will not * 'jump' over the boundary of a month's days. The 'W' character can only be * specified when the day-of-month is a single day, not a range or list of days. - *

    + *

    + *

    * The 'L' and 'W' characters can also be combined for the day-of-month * expression to yield 'LW', which translates to "last weekday of the * month". - *

    + *

    + *

    * The '#' character is allowed for the day-of-week field. This character is * used to specify "the nth" XXX day of the month. For example, the * value of "6#3" in the day-of-week field means the third Friday of @@ -163,7 +171,7 @@ * no firing will occur that month. If the '#' character is used, there can * only be one expression in the day-of-week field ("3#1,6#3" is * not valid, since there are two expressions). - *

    + *

    * - *

    + *

    * The legal characters and the names of months and days of the week are not * case sensitive. * *

    * NOTES: + *

    *
      *
    • Support for specifying both a day-of-week and a day-of-month value is * not complete (you'll need to use the '?' character in one of these fields). @@ -189,29 +198,30 @@ * interpretation CronExpression chooses. An example would be * "0 0 14-6 ? * FRI-MON".
    • *
    - *

    * * @author Sharada Jambula, James House * @author Contributions from Mads Henderson * @author Refactoring from CronTrigger to CronExpression by Aaron Craven */ -public final class CronExpression implements Serializable, Cloneable { +public final class CronExpression implements Serializable { public static final int MAX_YEAR = Calendar.getInstance().get(Calendar.YEAR) + 100; - protected static final int SECOND = 0; - protected static final int MINUTE = 1; - protected static final int HOUR = 2; - protected static final int DAY_OF_MONTH = 3; - protected static final int MONTH = 4; - protected static final int DAY_OF_WEEK = 5; - protected static final int YEAR = 6; - protected static final int ALL_SPEC_INT = 99; // '*' - protected static final int NO_SPEC_INT = 98; // '?' - protected static final Integer ALL_SPEC = ALL_SPEC_INT; - protected static final Integer NO_SPEC = NO_SPEC_INT; - - protected static final Map monthMap = new HashMap(20); - protected static final Map dayMap = new HashMap(60); + private static final int SECOND = 0; + private static final int MINUTE = 1; + private static final int HOUR = 2; + private static final int DAY_OF_MONTH = 3; + private static final int MONTH = 4; + private static final int DAY_OF_WEEK = 5; + private static final int YEAR = 6; + private static final int ALL_SPEC_INT = 99; // '*' + private static final int NO_SPEC_INT = 98; // '?' + private static final int MAX_LAST_DAY_OFFSET = 30; + private static final int LAST_DAY_OFFSET_START = 32; // "L-30" + private static final int LAST_DAY_OFFSET_END = LAST_DAY_OFFSET_START + MAX_LAST_DAY_OFFSET; // 'L' + private static final Integer ALL_SPEC = ALL_SPEC_INT; + private static final Integer NO_SPEC = NO_SPEC_INT; + private static final Map monthMap = new HashMap<>(20); + private static final Map dayMap = new HashMap<>(60); private static final long serialVersionUID = 12423409423L; static { @@ -238,21 +248,17 @@ public final class CronExpression implements Serializable, Cloneable { } private final String cronExpression; - protected transient TreeSet seconds; - protected transient TreeSet minutes; - protected transient TreeSet hours; - protected transient TreeSet daysOfMonth; - protected transient TreeSet months; - protected transient TreeSet daysOfWeek; - protected transient TreeSet years; - - protected transient boolean lastdayOfWeek = false; - protected transient int nthdayOfWeek = 0; - protected transient boolean lastdayOfMonth = false; - protected transient boolean nearestWeekday = false; - protected transient int lastdayOffset = 0; - protected transient boolean expressionParsed = false; private TimeZone timeZone = null; + private transient TreeSet seconds; + private transient TreeSet minutes; + private transient TreeSet hours; + private transient TreeSet daysOfMonth; + private transient TreeSet nearestWeekdays; + private transient TreeSet months; + private transient TreeSet daysOfWeek; + private transient TreeSet years; + private transient boolean lastDayOfWeek = false; + private transient int nthDayOfWeek = 0; /** * Constructs a new CronExpression based on the specified @@ -261,7 +267,7 @@ public final class CronExpression implements Serializable, Cloneable { * @param cronExpression String representation of the cron expression the * new object should represent * @throws java.text.ParseException if the string expression cannot be parsed into a valid - * CronExpression + * CronExpression */ public CronExpression(String cronExpression) throws ParseException { if (cronExpression == null) { @@ -273,29 +279,6 @@ public CronExpression(String cronExpression) throws ParseException { buildExpression(this.cronExpression); } - /** - * Constructs a new {@code CronExpression} as a copy of an existing - * instance. - * - * @param expression The existing cron expression to be copied - */ - public CronExpression(CronExpression expression) { - /* - * We don't call the other constructor here since we need to swallow the - * ParseException. We also elide some of the sanity checking as it is - * not logically trippable. - */ - this.cronExpression = expression.getCronExpression(); - try { - buildExpression(cronExpression); - } catch (ParseException ex) { - throw new AssertionError(); - } - if (expression.getTimeZone() != null) { - setTimeZone((TimeZone) expression.getTimeZone().clone()); - } - } - /** * Indicates whether the specified cron expression can be parsed into a * valid cron expression @@ -305,18 +288,15 @@ public CronExpression(CronExpression expression) { * expression */ public static boolean isValidExpression(String cronExpression) { - try { - new CronExpression(cronExpression); + validateExpression(cronExpression); } catch (ParseException pe) { return false; } - return true; - } + } public static void validateExpression(String cronExpression) throws ParseException { - new CronExpression(cronExpression); } @@ -327,7 +307,7 @@ public static void validateExpression(String cronExpression) throws ParseExcepti * * @param date the date to evaluate * @return a boolean indicating whether the given date satisfies the cron - * expression + * expression */ public boolean isSatisfiedBy(Date date) { Calendar testDateCal = Calendar.getInstance(getTimeZone()); @@ -354,45 +334,6 @@ public Date getNextValidTimeAfter(Date date) { return getTimeAfter(date); } - /** - * Returns the next date/time after the given date/time which does - * not satisfy the expression - * - * @param date the date/time at which to begin the search for the next - * invalid date/time - * @return the next valid date/time - */ - public Date getNextInvalidTimeAfter(Date date) { - long difference = 1000; - - //move back to the nearest second so differences will be accurate - Calendar adjustCal = Calendar.getInstance(getTimeZone()); - adjustCal.setTime(date); - adjustCal.set(Calendar.MILLISECOND, 0); - Date lastDate = adjustCal.getTime(); - - Date newDate; - - //FUTURE_TODO: (QUARTZ-481) IMPROVE THIS! The following is a BAD solution to this problem. Performance will be very bad here, depending on the cron expression. It is, however A solution. - - //keep getting the next included time until it's farther than one second - // apart. At that point, lastDate is the last valid fire time. We return - // the second immediately following it. - while (difference == 1000) { - newDate = getTimeAfter(lastDate); - if (newDate == null) - break; - - difference = newDate.getTime() - lastDate.getTime(); - - if (difference == 1000) { - lastDate = newDate; - } - } - - return new Date(lastDate.getTime() + 1000); - } - /** * Returns the time zone for which this CronExpression * will be resolved. @@ -423,38 +364,32 @@ public String toString() { return cronExpression; } - - //////////////////////////////////////////////////////////////////////////// - // - // Expression Parsing Functions - // - //////////////////////////////////////////////////////////////////////////// - - protected void buildExpression(String expression) throws ParseException { - expressionParsed = true; - + private void buildExpression(String expression) throws ParseException { try { if (seconds == null) { - seconds = new TreeSet(); + seconds = new TreeSet<>(); } if (minutes == null) { - minutes = new TreeSet(); + minutes = new TreeSet<>(); } if (hours == null) { - hours = new TreeSet(); + hours = new TreeSet<>(); } if (daysOfMonth == null) { - daysOfMonth = new TreeSet(); + daysOfMonth = new TreeSet<>(); + } + if (nearestWeekdays == null) { + nearestWeekdays = new TreeSet<>(); } if (months == null) { - months = new TreeSet(); + months = new TreeSet<>(); } if (daysOfWeek == null) { - daysOfWeek = new TreeSet(); + daysOfWeek = new TreeSet<>(); } if (years == null) { - years = new TreeSet(); + years = new TreeSet<>(); } int exprOn = SECOND; @@ -462,19 +397,23 @@ protected void buildExpression(String expression) throws ParseException { StringTokenizer exprsTok = new StringTokenizer(expression, " \t", false); + if(exprsTok.countTokens() > 7) { + throw new ParseException("Invalid expression has too many terms: " + expression, -1); + } + while (exprsTok.hasMoreTokens() && exprOn <= YEAR) { String expr = exprsTok.nextToken().trim(); - // throw an exception if L is used with other days of the month - if (exprOn == DAY_OF_MONTH && expr.indexOf('L') != -1 && expr.length() > 1 && expr.contains(",")) { - throw new ParseException("Support for specifying 'L' and 'LW' with other days of the month is not implemented", -1); - } // throw an exception if L is used with other days of the week - if (exprOn == DAY_OF_WEEK && expr.indexOf('L') != -1 && expr.length() > 1 && expr.contains(",")) { - throw new ParseException("Support for specifying 'L' with other days of the week is not implemented", -1); + if (exprOn == DAY_OF_WEEK && expr.indexOf('L') != -1 && expr.length() > 1 + && expr.contains(",")) { + throw new ParseException("Support for specifying 'L' " + + "with other days of the week is not implemented", -1); } - if (exprOn == DAY_OF_WEEK && expr.indexOf('#') != -1 && expr.indexOf('#', expr.indexOf('#') + 1) != -1) { - throw new ParseException("Support for specifying multiple \"nth\" days is not implemented.", -1); + if (exprOn == DAY_OF_WEEK && expr.indexOf('#') != -1 + && expr.indexOf('#', expr.indexOf('#') +1) != -1) { + throw new ParseException( + "Support for specifying multiple \"nth\" days is not implemented.", -1); } StringTokenizer vTok = new StringTokenizer(expr, ","); @@ -487,8 +426,7 @@ protected void buildExpression(String expression) throws ParseException { } if (exprOn <= DAY_OF_WEEK) { - throw new ParseException("Unexpected end of expression.", - expression.length()); + throw new ParseException("Unexpected end of expression.", expression.length()); } if (exprOn <= YEAR) { @@ -502,21 +440,19 @@ protected void buildExpression(String expression) throws ParseException { boolean dayOfMSpec = !dom.contains(NO_SPEC); boolean dayOfWSpec = !dow.contains(NO_SPEC); - if (!dayOfMSpec || dayOfWSpec) { - if (!dayOfWSpec || dayOfMSpec) { - throw new ParseException( - "Support for specifying both a day-of-week AND a day-of-month parameter is not implemented.", 0); - } + if ((!dayOfMSpec || dayOfWSpec) && (!dayOfWSpec || dayOfMSpec)) { + throw new ParseException( + "Support for specifying both a day-of-week AND a day-of-month" + + " parameter is not implemented.", 0); } } catch (ParseException pe) { throw pe; } catch (Exception e) { - throw new ParseException("Illegal cron expression format (" - + e.toString() + ")", 0); + throw new ParseException("Illegal cron expression format (" + e + ")", 0); } } - protected int storeExpressionVals(int pos, String s, int type) + private int storeExpressionVals(int pos, String s, int type) throws ParseException { int incr = 0; @@ -525,9 +461,10 @@ protected int storeExpressionVals(int pos, String s, int type) return i; } char c = s.charAt(i); - if ((c >= 'A') && (c <= 'Z') && (!s.equals("L")) && (!s.equals("LW")) && (!s.matches("^L-[0-9]*[W]?"))) { + if ((c >= 'A') && (c <= 'Z') && (!"L".equals(s)) && (!"LW".equals(s)) + && (!s.matches("^L-[0-9]*[W]?"))) { String sub = s.substring(i, i + 3); - int sval = -1; + int sval; int eval = -1; if (type == MONTH) { sval = getMonthNumber(sub) + 1; @@ -548,8 +485,7 @@ protected int storeExpressionVals(int pos, String s, int type) } else if (type == DAY_OF_WEEK) { sval = getDayOfWeekNumber(sub); if (sval < 0) { - throw new ParseException("Invalid Day-of-Week value: '" - + sub + "'", i); + throw new ParseException("Invalid Day-of-Week value: '" + sub + "'", i); } if (s.length() > i + 3) { c = s.charAt(i + 3); @@ -558,32 +494,27 @@ protected int storeExpressionVals(int pos, String s, int type) sub = s.substring(i, i + 3); eval = getDayOfWeekNumber(sub); if (eval < 0) { - throw new ParseException( - "Invalid Day-of-Week value: '" + sub - + "'", i); + throw new ParseException("Invalid Day-of-Week value: '" + sub + "'", i); } } else if (c == '#') { try { i += 4; - nthdayOfWeek = Integer.parseInt(s.substring(i)); - if (nthdayOfWeek < 1 || nthdayOfWeek > 5) { + nthDayOfWeek = Integer.parseInt(s.substring(i)); + if (nthDayOfWeek < 1 || nthDayOfWeek > 5) { throw new Exception(); } } catch (Exception e) { throw new ParseException( - "A numeric value between 1 and 5 must follow the '#' option", - i); + "A numeric value between 1 and 5 must follow the '#' option", i); } } else if (c == 'L') { - lastdayOfWeek = true; + lastDayOfWeek = true; i++; } } } else { - throw new ParseException( - "Illegal characters for this position: '" + sub + "'", - i); + throw new ParseException("Illegal characters for this position: '" + sub + "'", i); } if (eval != -1) { incr = 1; @@ -596,21 +527,14 @@ protected int storeExpressionVals(int pos, String s, int type) i++; if ((i + 1) < s.length() && (s.charAt(i) != ' ' && s.charAt(i + 1) != '\t')) { - throw new ParseException("Illegal character after '?': " - + s.charAt(i), i); + throw new ParseException("Illegal character after '?': " + s.charAt(i), i); } if (type != DAY_OF_WEEK && type != DAY_OF_MONTH) { throw new ParseException( - "'?' can only be specified for Day-of-Month or Day-of-Week.", - i); + "'?' can only be specified for Day-of-Month or Day-of-Week.", i); } - if (type == DAY_OF_WEEK && !lastdayOfMonth) { - int val = daysOfMonth.last(); - if (val == NO_SPEC_INT) { - throw new ParseException( - "'?' can only be specified for Day-of-Month -OR- Day-of-Week.", - i); - } + if ((type == DAY_OF_WEEK) && (!daysOfMonth.isEmpty() && daysOfMonth.last() == NO_SPEC_INT)) { + throw new ParseException("'?' can only be specified for Day-of-Month -OR- Day-of-Week.", i); } addToSet(NO_SPEC_INT, -1, 0, type); @@ -650,27 +574,36 @@ protected int storeExpressionVals(int pos, String s, int type) return i; } else if (c == 'L') { i++; - if (type == DAY_OF_MONTH) { - lastdayOfMonth = true; - } if (type == DAY_OF_WEEK) { addToSet(7, 7, 0, type); } - if (type == DAY_OF_MONTH && s.length() > i) { - c = s.charAt(i); - if (c == '-') { - ValueSet vs = getValue(0, s, i + 1); - lastdayOffset = vs.value; - if (lastdayOffset > 30) - throw new ParseException("Offset from last day must be <= 30", i + 1); - i = vs.pos; - } + if (type == DAY_OF_MONTH) { + int dom = LAST_DAY_OFFSET_END; + boolean nearestWeekday = false; if (s.length() > i) { c = s.charAt(i); - if (c == 'W') { - nearestWeekday = true; - i++; + if (c == '-') { + ValueSet vs = getValue(0, s, i + 1); + int offset = vs.value; + if (offset > MAX_LAST_DAY_OFFSET) { + throw new ParseException( + "Offset from last day must be <= " + MAX_LAST_DAY_OFFSET, i + 1); + } + dom -= offset; + i = vs.pos; } + if (s.length() > i) { + c = s.charAt(i); + if (c == 'W') { + nearestWeekday = true; + i++; + } + } + } + if (nearestWeekday) { + nearestWeekdays.add(dom); + } else { + daysOfMonth.add(dom); } } return i; @@ -710,7 +643,7 @@ private void checkIncrementRange(int incr, int type, int idxPos) throws ParseExc } } - protected int checkNext(int pos, String s, int val, int type) + private int checkNext(int pos, String s, int val, int type) throws ParseException { int end = -1; @@ -725,9 +658,9 @@ protected int checkNext(int pos, String s, int val, int type) if (c == 'L') { if (type == DAY_OF_WEEK) { - if (val < 1 || val > 7) + if(val < 1 || val > 7) throw new ParseException("Day-of-Week values must be between 1 and 7", -1); - lastdayOfWeek = true; + lastDayOfWeek = true; } else { throw new ParseException("'L' option is not valid here. (pos=" + i + ")", i); } @@ -738,15 +671,15 @@ protected int checkNext(int pos, String s, int val, int type) } if (c == 'W') { - if (type == DAY_OF_MONTH) { - nearestWeekday = true; - } else { + if (type != DAY_OF_MONTH) { throw new ParseException("'W' option is not valid here. (pos=" + i + ")", i); } - if (val > 31) - throw new ParseException("The 'W' option does not make sense with values larger than 31 (max number of days in a month)", i); - TreeSet set = getSet(type); - set.add(val); + if (val > 31) { + throw new ParseException("The 'W' option does not make sense with values larger than" + + " 31 (max number of days in a month)", i); + } + + nearestWeekdays.add(val); i++; return i; } @@ -757,8 +690,8 @@ protected int checkNext(int pos, String s, int val, int type) } i++; try { - nthdayOfWeek = Integer.parseInt(s.substring(i)); - if (nthdayOfWeek < 1 || nthdayOfWeek > 5) { + nthDayOfWeek = Integer.parseInt(s.substring(i)); + if (nthDayOfWeek < 1 || nthDayOfWeek > 5) { throw new Exception(); } } catch (Exception e) { @@ -789,7 +722,7 @@ protected int checkNext(int pos, String s, int val, int type) end = vs.value; i = vs.pos; } - if (i < s.length() && ((c = s.charAt(i)) == '/')) { + if (i < s.length() && (s.charAt(i) == '/')) { i++; c = s.charAt(i); int v2 = Integer.parseInt(String.valueOf(c)); @@ -851,147 +784,45 @@ public String getCronExpression() { return cronExpression; } - public String getExpressionSummary() { - StringBuilder buf = new StringBuilder(); - - buf.append("seconds: "); - buf.append(getExpressionSetSummary(seconds)); - buf.append("\n"); - buf.append("minutes: "); - buf.append(getExpressionSetSummary(minutes)); - buf.append("\n"); - buf.append("hours: "); - buf.append(getExpressionSetSummary(hours)); - buf.append("\n"); - buf.append("daysOfMonth: "); - buf.append(getExpressionSetSummary(daysOfMonth)); - buf.append("\n"); - buf.append("months: "); - buf.append(getExpressionSetSummary(months)); - buf.append("\n"); - buf.append("daysOfWeek: "); - buf.append(getExpressionSetSummary(daysOfWeek)); - buf.append("\n"); - buf.append("lastdayOfWeek: "); - buf.append(lastdayOfWeek); - buf.append("\n"); - buf.append("nearestWeekday: "); - buf.append(nearestWeekday); - buf.append("\n"); - buf.append("NthDayOfWeek: "); - buf.append(nthdayOfWeek); - buf.append("\n"); - buf.append("lastdayOfMonth: "); - buf.append(lastdayOfMonth); - buf.append("\n"); - buf.append("years: "); - buf.append(getExpressionSetSummary(years)); - buf.append("\n"); - - return buf.toString(); - } - - protected String getExpressionSetSummary(java.util.Set set) { - - if (set.contains(NO_SPEC)) { - return "?"; - } - if (set.contains(ALL_SPEC)) { - return "*"; - } - - StringBuilder buf = new StringBuilder(); - - Iterator itr = set.iterator(); - boolean first = true; - while (itr.hasNext()) { - Integer iVal = itr.next(); - String val = iVal.toString(); - if (!first) { - buf.append(","); - } - buf.append(val); - first = false; - } - - return buf.toString(); - } - - protected String getExpressionSetSummary(java.util.ArrayList list) { - - if (list.contains(NO_SPEC)) { - return "?"; - } - if (list.contains(ALL_SPEC)) { - return "*"; - } - - StringBuilder buf = new StringBuilder(); - - Iterator itr = list.iterator(); - boolean first = true; - while (itr.hasNext()) { - Integer iVal = itr.next(); - String val = iVal.toString(); - if (!first) { - buf.append(","); - } - buf.append(val); - first = false; - } - - return buf.toString(); - } - - protected int skipWhiteSpace(int i, String s) { + private int skipWhiteSpace(int i, String s) { for (; i < s.length() && (s.charAt(i) == ' ' || s.charAt(i) == '\t'); i++) { - ; } return i; } - protected int findNextWhiteSpace(int i, String s) { + private int findNextWhiteSpace(int i, String s) { for (; i < s.length() && (s.charAt(i) != ' ' || s.charAt(i) != '\t'); i++) { - ; } return i; } - protected void addToSet(int val, int end, int incr, int type) + private void addToSet(int val, int end, int incr, int type) throws ParseException { TreeSet set = getSet(type); if (type == SECOND || type == MINUTE) { if ((val < 0 || val > 59 || end > 59) && (val != ALL_SPEC_INT)) { - throw new ParseException( - "Minute and Second values must be between 0 and 59", - -1); + throw new ParseException("Minute and Second values must be between 0 and 59", -1); } } else if (type == HOUR) { if ((val < 0 || val > 23 || end > 23) && (val != ALL_SPEC_INT)) { - throw new ParseException( - "Hour values must be between 0 and 23", -1); + throw new ParseException("Hour values must be between 0 and 23", -1); } } else if (type == DAY_OF_MONTH) { if ((val < 1 || val > 31 || end > 31) && (val != ALL_SPEC_INT) && (val != NO_SPEC_INT)) { - throw new ParseException( - "Day of month values must be between 1 and 31", -1); + throw new ParseException("Day of month values must be between 1 and 31", -1); } } else if (type == MONTH) { if ((val < 1 || val > 12 || end > 12) && (val != ALL_SPEC_INT)) { - throw new ParseException( - "Month values must be between 1 and 12", -1); - } - } else if (type == DAY_OF_WEEK) { - if ((val == 0 || val > 7 || end > 7) && (val != ALL_SPEC_INT) - && (val != NO_SPEC_INT)) { - throw new ParseException( - "Day-of-Week values must be between 1 and 7", -1); + throw new ParseException("Month values must be between 1 and 12", -1); } + } else if (type == DAY_OF_WEEK && ((val == 0 || val > 7 || end > 7) && (val != ALL_SPEC_INT) + && (val != NO_SPEC_INT))) { + throw new ParseException("Day-of-Week values must be between 1 and 7", -1); } if ((incr == 0 || incr == -1) && val != ALL_SPEC_INT) { @@ -1063,8 +894,6 @@ protected void addToSet(int val, int end, int incr, int type) if (stopAt < startAt) { switch (type) { case SECOND: - max = 60; - break; case MINUTE: max = 60; break; @@ -1123,11 +952,11 @@ TreeSet getSet(int type) { case YEAR: return years; default: - return null; + throw new IllegalArgumentException("Invalid type encountered: " + type); } } - protected ValueSet getValue(int v, String s, int i) { + private ValueSet getValue(int v, String s, int i) { char c = s.charAt(i); StringBuilder s1 = new StringBuilder(String.valueOf(v)); while (c >= '0' && c <= '9') { @@ -1145,13 +974,13 @@ protected ValueSet getValue(int v, String s, int i) { return val; } - protected int getNumericValue(String s, int i) { + private int getNumericValue(String s, int i) { int endOfVal = findNextWhiteSpace(i, s); String val = s.substring(i, endOfVal); return Integer.parseInt(val); } - protected int getMonthNumber(String s) { + private int getMonthNumber(String s) { Integer integer = monthMap.get(s); if (integer == null) { @@ -1161,7 +990,7 @@ protected int getMonthNumber(String s) { return integer; } - protected int getDayOfWeekNumber(String s) { + private int getDayOfWeekNumber(String s) { Integer integer = dayMap.get(s); if (integer == null) { @@ -1171,11 +1000,6 @@ protected int getDayOfWeekNumber(String s) { return integer; } - //////////////////////////////////////////////////////////////////////////// - // - // Computation Functions - // - //////////////////////////////////////////////////////////////////////////// public Date getTimeAfter(Date afterTime) { @@ -1193,20 +1017,18 @@ public Date getTimeAfter(Date afterTime) { // loop until we've computed the next time, or we've past the endTime while (!gotOne) { - //if (endTime != null && cl.getTime().after(endTime)) return null; - if (cl.get(Calendar.YEAR) > 2999) { // prevent endless loop... + + if(cl.get(Calendar.YEAR) > 2999) { // prevent endless loop... return null; } - SortedSet st = null; - int t = 0; int sec = cl.get(Calendar.SECOND); int min = cl.get(Calendar.MINUTE); // get second................................................. - st = seconds.tailSet(sec); - if (st != null && st.size() != 0) { + SortedSet st = seconds.tailSet(sec); + if (!st.isEmpty()) { sec = st.first(); } else { sec = seconds.first(); @@ -1217,11 +1039,11 @@ public Date getTimeAfter(Date afterTime) { min = cl.get(Calendar.MINUTE); int hr = cl.get(Calendar.HOUR_OF_DAY); - t = -1; + int t = -1; // get minute................................................. st = minutes.tailSet(min); - if (st != null && st.size() != 0) { + if (!st.isEmpty()) { t = min; min = st.first(); } else { @@ -1242,7 +1064,7 @@ public Date getTimeAfter(Date afterTime) { // get hour................................................... st = hours.tailSet(hr); - if (st != null && st.size() != 0) { + if (!st.isEmpty()) { t = hr; hr = st.first(); } else { @@ -1262,68 +1084,20 @@ public Date getTimeAfter(Date afterTime) { int mon = cl.get(Calendar.MONTH) + 1; // '+ 1' because calendar is 0-based for this field, and we are // 1-based - t = -1; int tmon = mon; // get day................................................... boolean dayOfMSpec = !daysOfMonth.contains(NO_SPEC); boolean dayOfWSpec = !daysOfWeek.contains(NO_SPEC); if (dayOfMSpec && !dayOfWSpec) { // get day by day of month rule - st = daysOfMonth.tailSet(day); - if (lastdayOfMonth) { - if (!nearestWeekday) { - t = day; - day = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); - day -= lastdayOffset; - if (t > day) { - mon++; - if (mon > 12) { - mon = 1; - tmon = 3333; // ensure test of mon != tmon further below fails - cl.add(Calendar.YEAR, 1); - } - day = 1; - } - } else { - t = day; - day = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); - day -= lastdayOffset; - - java.util.Calendar tcal = java.util.Calendar.getInstance(getTimeZone()); - tcal.set(Calendar.SECOND, 0); - tcal.set(Calendar.MINUTE, 0); - tcal.set(Calendar.HOUR_OF_DAY, 0); - tcal.set(Calendar.DAY_OF_MONTH, day); - tcal.set(Calendar.MONTH, mon - 1); - tcal.set(Calendar.YEAR, cl.get(Calendar.YEAR)); - - int ldom = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); - int dow = tcal.get(Calendar.DAY_OF_WEEK); - - if (dow == Calendar.SATURDAY && day == 1) { - day += 2; - } else if (dow == Calendar.SATURDAY) { - day -= 1; - } else if (dow == Calendar.SUNDAY && day == ldom) { - day -= 2; - } else if (dow == Calendar.SUNDAY) { - day += 1; - } - - tcal.set(Calendar.SECOND, sec); - tcal.set(Calendar.MINUTE, min); - tcal.set(Calendar.HOUR_OF_DAY, hr); - tcal.set(Calendar.DAY_OF_MONTH, day); - tcal.set(Calendar.MONTH, mon - 1); - Date nTime = tcal.getTime(); - if (nTime.before(afterTime)) { - day = 1; - mon++; - } - } - } else if (nearestWeekday) { - t = day; - day = daysOfMonth.first(); + final Optional smallestDay = findSmallestDay(day, mon, cl.get(Calendar.YEAR), + daysOfMonth); + Optional smallestDayForWeekday = findSmallestDay(day, mon, cl.get(Calendar.YEAR), + nearestWeekdays); + t = day; + day = -1; + if (smallestDayForWeekday.isPresent()) { + day = smallestDayForWeekday.get(); java.util.Calendar tcal = java.util.Calendar.getInstance(getTimeZone()); tcal.set(Calendar.SECOND, 0); @@ -1354,23 +1128,17 @@ public Date getTimeAfter(Date afterTime) { tcal.set(Calendar.MONTH, mon - 1); Date nTime = tcal.getTime(); if (nTime.before(afterTime)) { - day = daysOfMonth.first(); - mon++; + day = -1; } - } else if (st != null && st.size() != 0) { - t = day; - day = st.first(); - // make sure we don't over-run a short month, such as february - int lastDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); - if (day > lastDay) { - day = daysOfMonth.first(); - mon++; + } + if (smallestDay.isPresent()) { + if (day == -1 || smallestDay.get() < day) { + day = smallestDay.get(); } - } else { - day = daysOfMonth.first(); + } else if (day == -1) { + day = 1; mon++; } - if (day != t || mon != tmon) { cl.set(Calendar.SECOND, 0); cl.set(Calendar.MINUTE, 0); @@ -1382,7 +1150,7 @@ public Date getTimeAfter(Date afterTime) { continue; } } else if (dayOfWSpec && !dayOfMSpec) { // get day by day of week rule - if (lastdayOfWeek) { // are we looking for the last XXX day of + if (lastDayOfWeek) { // are we looking for the last XXX day of // the month? int dow = daysOfWeek.first(); // desired // d-o-w @@ -1425,7 +1193,7 @@ public Date getTimeAfter(Date afterTime) { continue; } - } else if (nthdayOfWeek != 0) { + } else if (nthDayOfWeek != 0) { // are we looking for the Nth XXX day in the month? int dow = daysOfWeek.first(); // desired // d-o-w @@ -1437,10 +1205,7 @@ public Date getTimeAfter(Date afterTime) { daysToAdd = dow + (7 - cDow); } - boolean dayShifted = false; - if (daysToAdd > 0) { - dayShifted = true; - } + final boolean dayShifted = daysToAdd > 0; day += daysToAdd; int weekOfMonth = day / 7; @@ -1448,7 +1213,7 @@ public Date getTimeAfter(Date afterTime) { weekOfMonth++; } - daysToAdd = (nthdayOfWeek - weekOfMonth) * 7; + daysToAdd = (nthDayOfWeek - weekOfMonth) * 7; day += daysToAdd; if (daysToAdd < 0 || day > getLastDayOfMonth(mon, cl @@ -1474,7 +1239,7 @@ public Date getTimeAfter(Date afterTime) { int dow = daysOfWeek.first(); // desired // d-o-w st = daysOfWeek.tailSet(cDow); - if (st != null && st.size() > 0) { + if (!st.isEmpty()) { dow = st.first(); } @@ -1497,7 +1262,7 @@ public Date getTimeAfter(Date afterTime) { cl.set(Calendar.MONTH, mon); // no '- 1' here because we are promoting the month continue; - } else if (daysToAdd > 0) { // are we swithing days? + } else if (daysToAdd > 0) { // are we switching days? cl.set(Calendar.SECOND, 0); cl.set(Calendar.MINUTE, 0); cl.set(Calendar.HOUR_OF_DAY, 0); @@ -1510,7 +1275,8 @@ public Date getTimeAfter(Date afterTime) { } } else { // dayOfWSpec && !dayOfMSpec throw new UnsupportedOperationException( - "Support for specifying both a day-of-week AND a day-of-month parameter is not implemented."); + "Support for specifying both a day-of-week" + + " AND a day-of-month parameter is not implemented."); } cl.set(Calendar.DAY_OF_MONTH, day); @@ -1528,7 +1294,7 @@ public Date getTimeAfter(Date afterTime) { // get month................................................... st = months.tailSet(mon); - if (st != null && st.size() != 0) { + if (!st.isEmpty()) { t = mon; mon = st.first(); } else { @@ -1551,11 +1317,10 @@ public Date getTimeAfter(Date afterTime) { // 1-based year = cl.get(Calendar.YEAR); - t = -1; // get year................................................... st = years.tailSet(year); - if (st != null && st.size() != 0) { + if (!st.isEmpty()) { t = year; year = st.first(); } else { @@ -1576,7 +1341,7 @@ public Date getTimeAfter(Date afterTime) { cl.set(Calendar.YEAR, year); gotOne = true; - } // while( !done ) + } return cl.getTime(); } @@ -1585,65 +1350,37 @@ public Date getTimeAfter(Date afterTime) { * Advance the calendar to the particular hour paying particular attention * to daylight saving problems. * - * @param cal the calendar to operate on + * @param cal the calendar to operate on * @param hour the hour to set */ - protected void setCalendarHour(Calendar cal, int hour) { + private void setCalendarHour(Calendar cal, int hour) { cal.set(java.util.Calendar.HOUR_OF_DAY, hour); if (cal.get(java.util.Calendar.HOUR_OF_DAY) != hour && hour != 24) { cal.set(java.util.Calendar.HOUR_OF_DAY, hour + 1); } } - /** - * NOT YET IMPLEMENTED: Returns the time before the given time - * that the CronExpression matches. - */ - public Date getTimeBefore(Date endTime) { - // FUTURE_TODO: implement QUARTZ-423 - return null; - } - - /** - * NOT YET IMPLEMENTED: Returns the final time that the - * CronExpression will match. - */ - public Date getFinalFireTime() { - // FUTURE_TODO: implement QUARTZ-423 - return null; - } - - protected boolean isLeapYear(int year) { + private boolean isLeapYear(int year) { return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)); } - protected int getLastDayOfMonth(int monthNum, int year) { - + private int getLastDayOfMonth(int monthNum, int year) { switch (monthNum) { case 1: - return 31; - case 2: - return (isLeapYear(year)) ? 29 : 28; case 3: - return 31; - case 4: - return 30; case 5: - return 31; - case 6: - return 30; case 7: - return 31; case 8: - return 31; - case 9: - return 30; case 10: + case 12: return 31; + case 2: + return (isLeapYear(year)) ? 29 : 28; + case 4: + case 6: + case 9: case 11: return 30; - case 12: - return 31; default: throw new IllegalArgumentException("Illegal month number: " + monthNum); @@ -1651,19 +1388,24 @@ protected int getLastDayOfMonth(int monthNum, int year) { } - private void readObject(java.io.ObjectInputStream stream) - throws java.io.IOException, ClassNotFoundException { + private Optional findSmallestDay(int day, int mon, int year, TreeSet set) { + if (set.isEmpty()) { + return Optional.empty(); + } + + final int lastDay = getLastDayOfMonth(mon, year); + // For "L", "L-1", etc. + int smallestDay = Optional.ofNullable(set.ceiling(LAST_DAY_OFFSET_END - (lastDay - day))) + .map(d -> d - LAST_DAY_OFFSET_START + 1) + .orElse(Integer.MAX_VALUE); + + // For "1", "2", etc. + SortedSet st = set.subSet(day, LAST_DAY_OFFSET_START); + // make sure we don't over-run a short month, such as february + if (!st.isEmpty() && st.first() < smallestDay && st.first() <= lastDay) { + smallestDay = st.first(); + } - stream.defaultReadObject(); - try { - buildExpression(cronExpression); - } catch (Exception ignore) { - } // never happens + return smallestDay == Integer.MAX_VALUE ? Optional.empty() : Optional.of(smallestDay); } - - @Override - @Deprecated - public Object clone() { - return new CronExpression(this); } -} diff --git a/common/src/main/java/org/tron/common/cron/ValueSet.java b/common/src/main/java/org/tron/common/cron/ValueSet.java index 74469a62b48..e8ffa73b1e2 100644 --- a/common/src/main/java/org/tron/common/cron/ValueSet.java +++ b/common/src/main/java/org/tron/common/cron/ValueSet.java @@ -1,7 +1,7 @@ package org.tron.common.cron; class ValueSet { - public int value; + protected int value; - public int pos; + protected int pos; } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index b09b3b8c847..50ba7eb83e8 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -42,13 +42,13 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.tron.common.cron.CronExpression; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.common.args.Account; import org.tron.common.args.GenesisBlock; import org.tron.common.args.Witness; import org.tron.common.config.DbBackupConfig; +import org.tron.common.cron.CronExpression; import org.tron.common.crypto.SignInterface; import org.tron.common.logsfilter.EventPluginConfig; import org.tron.common.logsfilter.FilterQuery; diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index d856ccb8a11..4542b96a737 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -46,12 +46,12 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.bouncycastle.util.encoders.Hex; -import org.tron.common.cron.CronExpression; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.api.GrpcAPI.TransactionInfoList; import org.tron.common.args.GenesisBlock; import org.tron.common.bloom.Bloom; +import org.tron.common.cron.CronExpression; import org.tron.common.es.ExecutorServiceManager; import org.tron.common.exit.ExitManager; import org.tron.common.logsfilter.EventPluginLoader; diff --git a/framework/src/test/java/org/tron/common/cron/CronExpressionTest.java b/framework/src/test/java/org/tron/common/cron/CronExpressionTest.java new file mode 100644 index 00000000000..5e41670763c --- /dev/null +++ b/framework/src/test/java/org/tron/common/cron/CronExpressionTest.java @@ -0,0 +1,450 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * Copyright IBM Corp. 2024, 2025 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package org.tron.common.cron; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.fail; + +import java.text.ParseException; +import java.util.Calendar; +import java.util.Date; +import org.junit.Test; + +public class CronExpressionTest { + + private static void assertTrue(boolean condition, String message) { + if (!condition) { + fail(message); + } + } + + private static void assertTrue(boolean condition) { + if (!condition) { + fail(); + } + } + + @Test + public void testTooManyTokens() { + try { + new CronExpression("0 15 10 * * ? 2005 *"); // too many tokens/terms in expression + fail("Expected ParseException did not occur for invalid expression"); + } catch (ParseException pe) { + assertTrue(pe.getMessage().contains("too many"), + "Incorrect ParseException thrown"); + } + + } + + @Test + public void testIsSatisfiedBy() throws Exception { + CronExpression cronExpression = new CronExpression("0 15 10 * * ? 2005"); + + Calendar cal = Calendar.getInstance(); + + cal.set(2005, Calendar.JUNE, 1, 10, 15, 0); + assertTrue(cronExpression.isSatisfiedBy(cal.getTime())); + + cal.set(Calendar.YEAR, 2006); + assertFalse(cronExpression.isSatisfiedBy(cal.getTime())); + + cal = Calendar.getInstance(); + cal.set(2005, Calendar.JUNE, 1, 10, 16, 0); + assertFalse(cronExpression.isSatisfiedBy(cal.getTime())); + + cal = Calendar.getInstance(); + cal.set(2005, Calendar.JUNE, 1, 10, 14, 0); + assertFalse(cronExpression.isSatisfiedBy(cal.getTime())); + } + + @Test + public void testIsValidExpression() { + assertTrue(CronExpression.isValidExpression("0 0 0 L-2 * ? *")); + assertTrue(CronExpression.isValidExpression("0 0 0 LW * ? *")); + assertFalse(CronExpression.isValidExpression("0 0 0 Foo * ? *")); + assertFalse(CronExpression.isValidExpression("61 15 10 L-2 * ? 2010")); + assertFalse(CronExpression.isValidExpression("0 61 10 L-2 * ? 2010")); + assertFalse(CronExpression.isValidExpression("0 15 25 L-2 * ? 2010")); + assertTrue(CronExpression.isValidExpression("0/5 * * * * ?")); + assertTrue(CronExpression.isValidExpression("0 0 2 * * ?")); + assertTrue(CronExpression.isValidExpression("0 15 8 ? * MON-FRI")); + assertTrue(CronExpression.isValidExpression("0 45 15 1,15 * ? 2005")); + assertTrue(CronExpression.isValidExpression("0 10 * * * ?")); + assertTrue(CronExpression.isValidExpression("0 0 12 L 3,6,9,12 ?")); + assertTrue(CronExpression.isValidExpression("0 0 6 ? DEC,JAN SUN,SAT")); + assertTrue(CronExpression.isValidExpression("0 0 12 1/5 * ?")); + assertTrue(CronExpression.isValidExpression("0 0 8-18 ? * MON,WED,FRI")); + assertTrue(CronExpression.isValidExpression("0 10,44 14 ? 3 WED 2022/2")); + assertTrue(CronExpression.isValidExpression("0 0/30 9-17 * * ? 2022-2025")); + assertTrue(CronExpression.isValidExpression("0 15 10 ? * 6#3 2022,2023")); + assertTrue(CronExpression.isValidExpression("0 10,44 14 ? 3 WED 2022/2")); + assertTrue(CronExpression.isValidExpression("0 0/5 14,18 * * ?")); + assertTrue(CronExpression.isValidExpression("0 15 10 ? * 6#3")); + assertFalse(CronExpression.isValidExpression(" 0 15 10 ? * 6#3 2014-2012")); + assertTrue(CronExpression.isValidExpression("0 0 20-18 ? * MON,WED,FRI")); + assertTrue(CronExpression.isValidExpression("0 0/30 17-9 * 10-9 ? 2022")); + + } + + @Test + public void testLastDayOffset() throws Exception { + CronExpression cronExpression = new CronExpression("0 15 10 L-2 * ? 2010"); + cronExpression.setTimeZone(Calendar.getInstance().getTimeZone()); + + Calendar cal = Calendar.getInstance(); + // last day - 2 + cal.set(2010, Calendar.OCTOBER, 29, 10, 15, 0); + assertTrue(cronExpression.isSatisfiedBy(cal.getTime())); + + cal.set(2010, Calendar.OCTOBER, 28, 10, 15, 0); + assertFalse(cronExpression.isSatisfiedBy(cal.getTime())); + + cronExpression = new CronExpression("0 15 10 L-5W * ? 2010"); + // last day - 5 + cal.set(2010, Calendar.OCTOBER, 26, 10, 15, 0); + assertTrue(cronExpression.isSatisfiedBy(cal.getTime())); + + cronExpression = new CronExpression("0 15 10 L-1 * ? 2010"); + // last day - 1 + cal.set(2010, Calendar.OCTOBER, 30, 10, 15, 0); + assertTrue(cronExpression.isSatisfiedBy(cal.getTime())); + + cronExpression = new CronExpression("0 15 10 L-1W * ? 2010"); + // nearest weekday to last day - 1 (29th is a friday in 2010) + cal.set(2010, Calendar.OCTOBER, 29, 10, 15, 0); + assertTrue(cronExpression.isSatisfiedBy(cal.getTime())); + + cronExpression = new CronExpression("0 15 10 1,L * ? 2010"); + + cal.set(2010, Calendar.OCTOBER, 1, 10, 15, 0); + assertTrue(cronExpression.isSatisfiedBy(cal.getTime())); + + cal.set(2010, Calendar.OCTOBER, 31, 10, 15, 0); + assertTrue(cronExpression.isSatisfiedBy(cal.getTime())); + + cal.set(2010, Calendar.OCTOBER, 30, 10, 15, 0); + assertFalse(cronExpression.isSatisfiedBy(cal.getTime())); + + cronExpression = new CronExpression("0 15 10 L-1W,L-1 * ? 2010"); + // nearest weekday to last day - 1 (29th is a friday in 2010) + cal.set(2010, Calendar.OCTOBER, 29, 10, 15, 0); + assertTrue(cronExpression.isSatisfiedBy(cal.getTime())); + // last day - 1 + cal.set(2010, Calendar.OCTOBER, 30, 10, 15, 0); + + cronExpression = new CronExpression("0 15 10 2W,16 * ? 2010"); + // nearest weekday to the 2nd of the month (1st is a friday in 2010) + cal.set(2010, Calendar.OCTOBER, 1, 10, 15, 0); + assertTrue(cronExpression.isSatisfiedBy(cal.getTime())); + + cal.set(2010, Calendar.OCTOBER, 2, 10, 15, 0); + assertFalse(cronExpression.isSatisfiedBy(cal.getTime())); + + cal.set(2010, Calendar.OCTOBER, 16, 10, 15, 0); + assertTrue(cronExpression.isSatisfiedBy(cal.getTime())); + + } + + @Test + public void testQuartz() throws Exception { + CronExpression cronExpression = new CronExpression("19 15 10 4 Apr ? "); + assertEquals("19 15 10 4 Apr ? ".toUpperCase(), cronExpression.getCronExpression()); + assertEquals("19 15 10 4 Apr ? ".toUpperCase(), cronExpression.toString()); + + // if broken, this will throw an exception + cronExpression.getNextValidTimeAfter(new Date()); + + try { + new CronExpression(null); + fail("Expected ParseException did not fire for null "); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().equals("cronExpression cannot be null"), + "Incorrect ParseException thrown"); + } + + try { + new CronExpression("* * * * Foo ? "); + fail("Expected ParseException did not fire for nonexistent month"); + } catch (ParseException pe) { + assertTrue(pe.getMessage().startsWith("Invalid Month value:"), + "Incorrect ParseException thrown"); + } + + try { + new CronExpression("* * * * Jan-Foo ? "); + fail("Expected ParseException did not fire for nonexistent month"); + } catch (ParseException pe) { + assertTrue(pe.getMessage().startsWith("Invalid Month value:"), + "Incorrect ParseException thrown"); + } + + try { + new CronExpression("0 0 * * * *"); + fail("Expected ParseException did not fire for wildcard day-of-month and day-of-week"); + } catch (ParseException pe) { + assertTrue(pe.getMessage().startsWith( + "Support for specifying both a day-of-week AND" + + " a day-of-month parameter is not implemented."), + "Incorrect ParseException thrown"); + } + try { + new CronExpression("0 0 * 4 * *"); + fail("Expected ParseException did not fire for specified day-of-month and" + + " wildcard day-of-week"); + } catch (ParseException pe) { + assertTrue(pe.getMessage().startsWith( + "Support for specifying both a day-of-week AND a day-of-month" + + " parameter is not implemented."), "Incorrect ParseException thrown"); + } + try { + new CronExpression("0 0 * * * 4"); + fail("Expected ParseException did not fire for wildcard day-of-month" + + " and specified day-of-week"); + } catch (ParseException pe) { + assertTrue(pe.getMessage().startsWith( + "Support for specifying both a day-of-week AND a day-of-month" + + " parameter is not implemented."), "Incorrect ParseException thrown"); + } + + try { + new CronExpression("0 43 9 ? * SAT,SUN,L"); + fail("Expected ParseException did not fire for L combined with other days of the week"); + } catch (ParseException pe) { + assertTrue(pe.getMessage().startsWith( + "Support for specifying 'L' with other days of the week is not implemented"), + "Incorrect ParseException thrown"); + } + try { + new CronExpression("0 43 9 ? * 6,7,L"); + fail("Expected ParseException did not fire for L combined with other days of the week"); + } catch (ParseException pe) { + assertTrue(pe.getMessage().startsWith( + "Support for specifying 'L' with other days of the week is not implemented"), + "Incorrect ParseException thrown"); + } + try { + new CronExpression("0 43 9 ? * 5L"); + } catch (ParseException pe) { + fail("Unexpected ParseException thrown for supported '5L' expression."); + } + } + + @Test + public void testQtz96() throws ParseException { + try { + new CronExpression("0/5 * * 32W 1 ?"); + fail("Expected ParseException did not fire for W with value larger than 31"); + } catch (ParseException pe) { + assertTrue(pe.getMessage().startsWith( + "The 'W' option does not make sense with values larger than"), + "Incorrect ParseException thrown"); + } + + // Test case 1 + try { + new CronExpression("/120 0 8-18 ? * 2-6"); + fail("Cron did not validate bad range interval in '_blank/xxx' form"); + } catch (ParseException e) { + assertEquals("Increment > 60 : 120", e.getMessage()); + } + + // Test case 2 + try { + new CronExpression("0/120 0 8-18 ? * 2-6"); + fail("Cron did not validate bad range interval in in '0/xxx' form"); + } catch (ParseException e) { + assertEquals("Increment > 60 : 120", e.getMessage()); + } + + // Test case 3 + try { + new CronExpression("/ 0 8-18 ? * 2-6"); + fail("Cron did not validate bad range interval in '_blank/_blank'"); + } catch (ParseException e) { + assertEquals("'/' must be followed by an integer.", e.getMessage()); + } + + // Test case 4 + try { + new CronExpression("0/ 0 8-18 ? * 2-6"); + fail("Cron did not validate bad range interval in '0/_blank'"); + } catch (ParseException e) { + assertEquals("'/' must be followed by an integer.", e.getMessage()); + } + + // Test case 1 + try { + new CronExpression("0 /120 8-18 ? * 2-6"); + fail("Cron did not validate bad range interval in '_blank/xxx' form"); + } catch (ParseException e) { + assertEquals("Increment > 60 : 120", e.getMessage()); + } + + // Test case 2 + try { + new CronExpression("0 0/120 8-18 ? * 2-6"); + fail("Cron did not validate bad range interval in in '0/xxx' form"); + } catch (ParseException e) { + assertEquals("Increment > 60 : 120", e.getMessage()); + } + + // Test case 3 + try { + new CronExpression("0 / 8-18 ? * 2-6"); + fail("Cron did not validate bad range interval in '_blank/_blank'"); + } catch (ParseException e) { + assertEquals("'/' must be followed by an integer.", e.getMessage()); + } + + // Test case 4 + try { + new CronExpression("0 0/ 8-18 ? * 2-6"); + fail("Cron did not validate bad range interval in '0/_blank'"); + } catch (ParseException e) { + assertEquals("'/' must be followed by an integer.", e.getMessage()); + } + + // Test case 1 + try { + new CronExpression("0 0 /120 ? * 2-6"); + fail("Cron did not validate bad range interval in '_blank/xxx' form"); + } catch (ParseException e) { + assertEquals("Increment > 24 : 120", e.getMessage()); + } + + // Test case 2 + try { + new CronExpression("0 0 0/120 ? * 2-6"); + fail("Cron did not validate bad range interval in in '0/xxx' form"); + } catch (ParseException e) { + assertEquals("Increment > 24 : 120", e.getMessage()); + } + + // Test case 3 + try { + new CronExpression("0 0 / ? * 2-6"); + fail("Cron did not validate bad range interval in '_blank/_blank'"); + } catch (ParseException e) { + assertEquals("'/' must be followed by an integer.", e.getMessage()); + } + + // Test case 4 + try { + new CronExpression("0 0 0/ ? * 2-6"); + fail("Cron did not validate bad range interval in '0/_blank'"); + } catch (ParseException e) { + assertEquals("'/' must be followed by an integer.", e.getMessage()); + } + + // Test case 1 + try { + new CronExpression("0 0 0 /120 * 2-6"); + fail("Cron did not validate bad range interval in '_blank/xxx' form"); + } catch (ParseException e) { + assertEquals("Increment > 31 : 120", e.getMessage()); + } + + // Test case 2 + try { + new CronExpression("0 0 0 0/120 * 2-6"); + fail("Cron did not validate bad range interval in in '0/xxx' form"); + } catch (ParseException e) { + assertEquals("Increment > 31 : 120", e.getMessage()); + } + + // Test case 3 + try { + new CronExpression("0 0 0 / * 2-6"); + fail("Cron did not validate bad range interval in '_blank/_blank'"); + } catch (ParseException e) { + assertEquals("'/' must be followed by an integer.", e.getMessage()); + } + + // Test case 4 + try { + new CronExpression("0 0 0 0/ * 2-6"); + fail("Cron did not validate bad range interval in '0/_blank'"); + } catch (ParseException e) { + assertEquals("'/' must be followed by an integer.", e.getMessage()); + } + // Test case 1 + try { + new CronExpression("0 0 0 ? /120 2-6"); + fail("Cron did not validate bad range interval in '_blank/xxx' form"); + } catch (ParseException e) { + assertEquals("Increment > 12 : 120", e.getMessage()); + } + + // Test case 2 + try { + new CronExpression("0 0 0 ? 0/120 2-6"); + fail("Cron did not validate bad range interval in in '0/xxx' form"); + } catch (ParseException e) { + assertEquals("Increment > 12 : 120", e.getMessage()); + } + + // Test case 3 + try { + new CronExpression("0 0 0 ? / 2-6"); + fail("Cron did not validate bad range interval in '_blank/_blank'"); + } catch (ParseException e) { + assertEquals("'/' must be followed by an integer.", e.getMessage()); + } + + // Test case 4 + try { + new CronExpression("0 0 0 ? 0/ 2-6"); + fail("Cron did not validate bad range interval in '0/_blank'"); + } catch (ParseException e) { + assertEquals("'/' must be followed by an integer.", e.getMessage()); + } + // Test case 1 + try { + new CronExpression("0 0 0 ? * /120"); + fail("Cron did not validate bad range interval in '_blank/xxx' form"); + } catch (ParseException e) { + assertEquals("Increment > 7 : 120", e.getMessage()); + } + + // Test case 2 + try { + new CronExpression("0 0 0 ? * 0/120"); + fail("Cron did not validate bad range interval in in '0/xxx' form"); + } catch (ParseException e) { + assertEquals("Increment > 7 : 120", e.getMessage()); + } + + // Test case 3 + try { + new CronExpression("0 0 0 ? * /"); + fail("Cron did not validate bad range interval in '_blank/_blank'"); + } catch (ParseException e) { + assertEquals("'/' must be followed by an integer.", e.getMessage()); + } + + // Test case 4 + try { + new CronExpression("0 0 0 ? * 0/"); + fail("Cron did not validate bad range interval in '0/_blank'"); + } catch (ParseException e) { + assertEquals("'/' must be followed by an integer.", e.getMessage()); + } + } + +} diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java index c529cafbba9..1e16ad6c3b0 100644 --- a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java @@ -5,7 +5,6 @@ import java.util.Date; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; -import org.junit.Test; import org.tron.common.cron.CronExpression; import org.tron.common.parameter.CommonParameter; @@ -26,21 +25,6 @@ public class BlockTimeStopTest extends ConditionallyStopTest { } } - @Test - public void isValidExpression() { - Assert.assertTrue(CronExpression.isValidExpression(cronExpression.getCronExpression())); - ParseException err = Assert.assertThrows(ParseException.class, () -> - CronExpression.validateExpression("invalid expression")); - Assert.assertEquals("Illegal characters for this position: 'INV'", err.getMessage()); - } - - @Test - public void getNextTime() { - Date date = cronExpression.getNextValidTimeAfter(new Date()); - Date invalidDate = cronExpression.getNextInvalidTimeAfter(new Date()); - Assert.assertNotEquals(date, invalidDate); - } - protected void initParameter(CommonParameter parameter) { parameter.setShutdownBlockTime(cronExpression); From 25e10c77a57e673780ac54375f7562d890ba02bf Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Wed, 26 Mar 2025 16:22:02 +0800 Subject: [PATCH 1186/1197] fix(config): restore maxFastForwardNum to correct default value --- framework/src/main/java/org/tron/core/config/args/Args.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index b09b3b8c847..bb36942fe00 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -129,7 +129,7 @@ public static void clearParam() { PARAMETER.activeNodes = new ArrayList<>(); PARAMETER.passiveNodes = new ArrayList<>(); PARAMETER.fastForwardNodes = new ArrayList<>(); - PARAMETER.maxFastForwardNum = 3; + PARAMETER.maxFastForwardNum = 4; PARAMETER.nodeChannelReadTimeout = 0; PARAMETER.maxConnections = 30; PARAMETER.minConnections = 8; From 44967fb3e6d05fd36b24f2df3bd7ef0f326773b8 Mon Sep 17 00:00:00 2001 From: zeusoo001 Date: Thu, 27 Mar 2025 10:30:53 +0800 Subject: [PATCH 1187/1197] feat(log): optimize log information --- .../capsule/TransactionLogTriggerCapsule.java | 4 ++-- framework/src/main/java/org/tron/core/Wallet.java | 4 ++-- .../main/java/org/tron/core/config/args/Args.java | 2 +- .../tron/core/services/event/BlockEventLoad.java | 14 +++++++------- .../test/java/org/tron/core/ShieldWalletTest.java | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java b/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java index ace19060b1f..958b3c0fd78 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java +++ b/framework/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java @@ -65,7 +65,7 @@ public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule blockCapsule, int txIndex, long preCumulativeEnergyUsed, long preCumulativeLogCount, - TransactionInfo transactionInfo, long energyUnitPrice, boolean flag) { + TransactionInfo transactionInfo, long energyUnitPrice, boolean isNewEventService) { transactionLogTrigger = new TransactionLogTrigger(); String blockHash = ""; @@ -309,7 +309,7 @@ public TransactionLogTriggerCapsule(TransactionCapsule trxCapsule, BlockCapsule getInternalTransactionList(programResult.getInternalTransactions())); } - if (Objects.isNull(trxTrace) && Objects.nonNull(transactionInfo) && flag) { + if (Objects.isNull(trxTrace) && Objects.nonNull(transactionInfo) && isNewEventService) { Protocol.ResourceReceipt receipt = transactionInfo.getReceipt(); energyUsageTotal = receipt.getEnergyUsageTotal(); transactionLogTrigger.setEnergyFee(receipt.getEnergyFee()); diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 24978304fba..8dfb18331ff 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -3484,7 +3484,7 @@ private void checkShieldedTRC20NoteValue( throw new ContractValidateException("The value in SpendNoteTRC20 must >= 0"); } if (StringUtils.isEmpty(spendNote.getNote().getPaymentAddress())) { - throw new ContractValidateException("Payment Address in SpendNote should not be empty"); + throw new ContractValidateException("PaymentAddress in SpendNote should not be empty"); } } } @@ -3495,7 +3495,7 @@ private void checkShieldedTRC20NoteValue( throw new ContractValidateException("The value in ReceiveNote must >= 0"); } if (StringUtils.isEmpty(receiveNote.getNote().getPaymentAddress())) { - throw new ContractValidateException("Payment Address in ReceiveNote should not be empty"); + throw new ContractValidateException("PaymentAddress in ReceiveNote should not be empty"); } } } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 50ba7eb83e8..2fd30f73d51 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -129,7 +129,7 @@ public static void clearParam() { PARAMETER.activeNodes = new ArrayList<>(); PARAMETER.passiveNodes = new ArrayList<>(); PARAMETER.fastForwardNodes = new ArrayList<>(); - PARAMETER.maxFastForwardNum = 3; + PARAMETER.maxFastForwardNum = 4; PARAMETER.nodeChannelReadTimeout = 0; PARAMETER.maxConnections = 30; PARAMETER.minConnections = 8; diff --git a/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java b/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java index 75829bf0e5e..7efc10a8ed5 100644 --- a/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java +++ b/framework/src/main/java/org/tron/core/services/event/BlockEventLoad.java @@ -72,25 +72,25 @@ public synchronized void load() throws Exception { if (tmpNum > cacheHeadNum + MAX_LOAD_NUM) { tmpNum = cacheHeadNum + MAX_LOAD_NUM; } - List l1 = new ArrayList<>(); - List l2 = new ArrayList<>(); + List blockEvents = new ArrayList<>(); + List rollbackBlockEvents = new ArrayList<>(); BlockEvent tmp = BlockEventCache.getHead(); BlockEvent blockEvent = blockEventGet.getBlockEvent(tmpNum); - l1.add(blockEvent); + blockEvents.add(blockEvent); while (!blockEvent.getParentId().equals(tmp.getBlockId())) { tmpNum--; if (tmpNum == tmp.getBlockId().getNum()) { - l2.add(tmp); + rollbackBlockEvents.add(tmp); tmp = BlockEventCache.getBlockEvent(tmp.getParentId()); } blockEvent = blockEventGet.getBlockEvent(tmpNum); - l1.add(blockEvent); + blockEvents.add(blockEvent); } - l2.forEach(e -> realtimeEventService.add(new Event(e, true))); + rollbackBlockEvents.forEach(e -> realtimeEventService.add(new Event(e, true))); - List l = Lists.reverse(l1); + List l = Lists.reverse(blockEvents); for (BlockEvent e: l) { BlockEventCache.add(e); realtimeEventService.add(new Event(e, false)); diff --git a/framework/src/test/java/org/tron/core/ShieldWalletTest.java b/framework/src/test/java/org/tron/core/ShieldWalletTest.java index 7eed5273586..f8d5db1a44c 100644 --- a/framework/src/test/java/org/tron/core/ShieldWalletTest.java +++ b/framework/src/test/java/org/tron/core/ShieldWalletTest.java @@ -376,7 +376,7 @@ public void testCreateShieldedContractParameters2() throws ContractExeException Assert.fail(); } catch (Exception e) { Assert.assertTrue(e instanceof ContractValidateException); - Assert.assertEquals("Payment Address in ReceiveNote should not be empty", + Assert.assertEquals("PaymentAddress in ReceiveNote should not be empty", e.getMessage()); } @@ -409,7 +409,7 @@ public void testCreateShieldedContractParameters2() throws ContractExeException Assert.fail(); } catch (Exception e) { Assert.assertTrue(e instanceof ContractValidateException); - Assert.assertEquals("Payment Address in SpendNote should not be empty", + Assert.assertEquals("PaymentAddress in SpendNote should not be empty", e.getMessage()); } } From e3ad0cacc382d0f1d8ea48901f271a9a65a0a0ec Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Wed, 26 Mar 2025 18:41:28 +0800 Subject: [PATCH 1188/1197] reactor(*): rename allowStrictMath2 to disableJavaLangMath --- .../tron/core/actuator/AbstractActuator.java | 2 +- .../actuator/DelegateResourceActuator.java | 4 ++-- .../actuator/MarketSellAssetActuator.java | 7 +++--- .../org/tron/core/actuator/VMActuator.java | 6 ++--- .../tron/core/vm/PrecompiledContracts.java | 7 +++--- .../DelegateResourceProcessor.java | 7 +++--- .../java/org/tron/core/vm/program/Memory.java | 10 ++++----- .../org/tron/core/vm/program/Program.java | 9 ++++---- .../org/tron/core/vm/utils/FreezeV2Util.java | 17 +++++++------- .../org/tron/core/capsule/AccountCapsule.java | 20 ++++++++--------- .../org/tron/core/capsule/ReceiptCapsule.java | 15 ++++++++----- .../org/tron/core/db/EnergyProcessor.java | 7 +++--- .../org/tron/core/db/ResourceProcessor.java | 22 +++++++++++-------- .../org/tron/core/db/TransactionTrace.java | 6 ++--- .../main/java/org/tron/core/db/Manager.java | 12 +++++----- 15 files changed, 77 insertions(+), 74 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/actuator/AbstractActuator.java b/actuator/src/main/java/org/tron/core/actuator/AbstractActuator.java index b5bdb9bcafc..c9f83c520bd 100644 --- a/actuator/src/main/java/org/tron/core/actuator/AbstractActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/AbstractActuator.java @@ -122,7 +122,7 @@ public void adjustBalance(AccountStore accountStore, AccountCapsule account, lon Commons.adjustBalance(accountStore, account, amount, this.disableJavaLangMath()); } - private boolean disableJavaLangMath() { + boolean disableJavaLangMath() { return chainBaseManager.getDynamicPropertiesStore().disableJavaLangMath(); } } diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 547171486ee..9e7b0efa5ce 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -162,7 +162,7 @@ public boolean validate() throws ContractValidateException { long netUsage = (long) (accountNetUsage * TRX_PRECISION * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage, - dynamicStore.disableJavaLangMath()); + this.disableJavaLangMath()); if (ownerCapsule.getFrozenV2BalanceForBandwidth() - v2NetUsage < delegateBalance) { throw new ContractValidateException( "delegateBalance must be less than or equal to available FreezeBandwidthV2 balance"); @@ -176,7 +176,7 @@ public boolean validate() throws ContractValidateException { long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage, - dynamicStore.disableJavaLangMath()); + this.disableJavaLangMath()); if (ownerCapsule.getFrozenV2BalanceForEnergy() - v2EnergyUsage < delegateBalance) { throw new ContractValidateException( "delegateBalance must be less than or equal to available FreezeEnergyV2 balance"); diff --git a/actuator/src/main/java/org/tron/core/actuator/MarketSellAssetActuator.java b/actuator/src/main/java/org/tron/core/actuator/MarketSellAssetActuator.java index b5b375ee391..d196cdef06f 100644 --- a/actuator/src/main/java/org/tron/core/actuator/MarketSellAssetActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/MarketSellAssetActuator.java @@ -400,10 +400,9 @@ private void matchSingleOrder(MarketOrderCapsule takerOrderCapsule, // => takerBuyTokenQuantityCurrent_A = takerSellTokenQuantityRemain_TRX * // makerSellTokenQuantity_A/makerBuyTokenQuantity_TRX - boolean disableMath = dynamicStore.disableJavaLangMath(); long takerBuyTokenQuantityRemain = MarketUtils .multiplyAndDivide(takerSellRemainQuantity, makerSellQuantity, makerBuyQuantity, - disableMath); + this.disableJavaLangMath()); if (takerBuyTokenQuantityRemain == 0) { // quantity too small, return sellToken to user @@ -427,7 +426,7 @@ private void matchSingleOrder(MarketOrderCapsule takerOrderCapsule, makerBuyTokenQuantityReceive = MarketUtils .multiplyAndDivide(makerSellRemainQuantity, makerBuyQuantity, makerSellQuantity, - chainBaseManager.getDynamicPropertiesStore().disableJavaLangMath()); + this.disableJavaLangMath()); takerBuyTokenQuantityReceive = makerOrderCapsule.getSellTokenQuantityRemain(); long takerSellTokenLeft = @@ -462,7 +461,7 @@ private void matchSingleOrder(MarketOrderCapsule takerOrderCapsule, // makerSellTokenQuantity_A/makerBuyTokenQuantity_TRX makerBuyTokenQuantityReceive = MarketUtils .multiplyAndDivide(makerSellRemainQuantity, makerBuyQuantity, makerSellQuantity, - chainBaseManager.getDynamicPropertiesStore().disableJavaLangMath()); + this.disableJavaLangMath()); MarketUtils.updateOrderState(makerOrderCapsule, State.INACTIVE, marketAccountStore); if (makerBuyTokenQuantityReceive == 0) { diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index bd34c96a9d9..9da41574ff0 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -603,10 +603,10 @@ private long getAccountEnergyLimitWithFloatRatio(AccountCapsule account, long fe } // can change the calc way long leftEnergyFromFreeze = rootRepository.getAccountLeftEnergyFromFreeze(account); - boolean isStrict2 = VMConfig.disableJavaLangMath(); - callValue = max(callValue, 0, isStrict2); + callValue = max(callValue, 0, VMConfig.disableJavaLangMath()); long energyFromBalance = floorDiv(max( - account.getBalance() - callValue, 0, isStrict2), sunPerEnergy, isStrict2); + account.getBalance() - callValue, 0, VMConfig.disableJavaLangMath()), sunPerEnergy, + VMConfig.disableJavaLangMath()); long energyFromFeeLimit; long totalBalanceForEnergyFreeze = account.getAllFrozenBalanceForEnergy(); diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 5fbbdde3b21..3f72e717f86 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -636,17 +636,16 @@ public long getEnergyForData(byte[] data) { int expLen = parseLen(data, 1); int modLen = parseLen(data, 2); - boolean allowStrictMath2 = VMConfig.disableJavaLangMath(); byte[] expHighBytes = parseBytes(data, addSafely(ARGS_OFFSET, baseLen), min(expLen, 32, - allowStrictMath2)); + VMConfig.disableJavaLangMath())); - long multComplexity = getMultComplexity(max(baseLen, modLen, allowStrictMath2)); + long multComplexity = getMultComplexity(max(baseLen, modLen, VMConfig.disableJavaLangMath())); long adjExpLen = getAdjustedExponentLength(expHighBytes, expLen); // use big numbers to stay safe in case of overflow BigInteger energy = BigInteger.valueOf(multComplexity) - .multiply(BigInteger.valueOf(max(adjExpLen, 1, allowStrictMath2))) + .multiply(BigInteger.valueOf(max(adjExpLen, 1, VMConfig.disableJavaLangMath()))) .divide(GQUAD_DIVISOR); return isLessThan(energy, BigInteger.valueOf(Long.MAX_VALUE)) ? energy.longValueExact() diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index b711eb427d1..d03af04aaf3 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -22,6 +22,7 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.store.DelegatedResourceAccountIndexStore; import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.nativecontract.param.DelegateResourceParam; import org.tron.core.vm.repository.Repository; import org.tron.protos.Protocol; @@ -53,7 +54,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra throw new ContractValidateException("delegateBalance must be greater than or equal to 1 TRX"); } - boolean allowStrictMath2 = dynamicStore.disableJavaLangMath(); + boolean disableJavaLangMath = VMConfig.disableJavaLangMath(); switch (param.getResourceType()) { case BANDWIDTH: { BandwidthProcessor processor = new BandwidthProcessor(ChainBaseManager.getInstance()); @@ -62,7 +63,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra long netUsage = (long) (ownerCapsule.getNetUsage() * TRX_PRECISION * ((double) (repo.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); - long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage, allowStrictMath2); + long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage, disableJavaLangMath); if (ownerCapsule.getFrozenV2BalanceForBandwidth() - v2NetUsage < delegateBalance) { throw new ContractValidateException( @@ -78,7 +79,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) (repo.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); - long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage, allowStrictMath2); + long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage, disableJavaLangMath); if (ownerCapsule.getFrozenV2BalanceForEnergy() - v2EnergyUsage < delegateBalance) { throw new ContractValidateException( diff --git a/actuator/src/main/java/org/tron/core/vm/program/Memory.java b/actuator/src/main/java/org/tron/core/vm/program/Memory.java index 4811bfb6e12..4249a7e2634 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Memory.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Memory.java @@ -105,17 +105,17 @@ public void extend(int address, int size) { if (size <= 0) { return; } - boolean allowStrictMath2 = VMConfig.disableJavaLangMath(); - final int newSize = addExact(address, size, allowStrictMath2); + final int newSize = addExact(address, size, VMConfig.disableJavaLangMath()); int toAllocate = newSize - internalSize(); if (toAllocate > 0) { - addChunks((int) ceil((double) toAllocate / CHUNK_SIZE, allowStrictMath2)); + addChunks((int) ceil((double) toAllocate / CHUNK_SIZE, VMConfig.disableJavaLangMath())); } toAllocate = newSize - softSize; if (toAllocate > 0) { - toAllocate = (int) ceil((double) toAllocate / WORD_SIZE, allowStrictMath2) * WORD_SIZE; - softSize = addExact(softSize, toAllocate, allowStrictMath2); + toAllocate = (int) ceil((double) toAllocate / WORD_SIZE, + VMConfig.disableJavaLangMath()) * WORD_SIZE; + softSize = addExact(softSize, toAllocate, VMConfig.disableJavaLangMath()); if (programListener != null) { programListener.onMemoryExtend(toAllocate); diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 024acb670a0..5da0b02ecb7 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -2170,13 +2170,12 @@ public boolean voteWitness(int witnessArrayOffset, int witnessArrayLength, try { VoteWitnessParam param = new VoteWitnessParam(); param.setVoterAddress(owner); - boolean allowStrictMath2 = VMConfig.disableJavaLangMath(); byte[] witnessArrayData = memoryChunk( - addExact(witnessArrayOffset, DataWord.WORD_SIZE, allowStrictMath2), - multiplyExact(witnessArrayLength, DataWord.WORD_SIZE, allowStrictMath2)); + addExact(witnessArrayOffset, DataWord.WORD_SIZE, VMConfig.disableJavaLangMath()), + multiplyExact(witnessArrayLength, DataWord.WORD_SIZE, VMConfig.disableJavaLangMath())); byte[] amountArrayData = memoryChunk( - addExact(amountArrayOffset, DataWord.WORD_SIZE, allowStrictMath2), - multiplyExact(amountArrayLength, DataWord.WORD_SIZE, allowStrictMath2)); + addExact(amountArrayOffset, DataWord.WORD_SIZE, VMConfig.disableJavaLangMath()), + multiplyExact(amountArrayLength, DataWord.WORD_SIZE, VMConfig.disableJavaLangMath())); for (int i = 0; i < witnessArrayLength; i++) { DataWord witness = new DataWord(Arrays.copyOfRange(witnessArrayData, diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index 28c190e2e7e..762d9318e7b 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -144,7 +144,6 @@ public static long queryDelegatableResource(byte[] address, long type, Repositor return 0L; } - boolean allowStrictMath2 = VMConfig.disableJavaLangMath(); AccountCapsule accountCapsule = repository.getAccount(address); if (accountCapsule == null) { return 0L; @@ -166,8 +165,8 @@ public static long queryDelegatableResource(byte[] address, long type, Repositor return frozenV2Resource; } - long v2NetUsage = getV2NetUsage(accountCapsule, usage, allowStrictMath2); - return max(0L, frozenV2Resource - v2NetUsage, allowStrictMath2); + long v2NetUsage = getV2NetUsage(accountCapsule, usage, VMConfig.disableJavaLangMath()); + return max(0L, frozenV2Resource - v2NetUsage, VMConfig.disableJavaLangMath()); } if (type == 1) { @@ -186,8 +185,8 @@ public static long queryDelegatableResource(byte[] address, long type, Repositor return frozenV2Resource; } - long v2EnergyUsage = getV2EnergyUsage(accountCapsule, usage, allowStrictMath2); - return max(0L, frozenV2Resource - v2EnergyUsage, allowStrictMath2); + long v2EnergyUsage = getV2EnergyUsage(accountCapsule, usage, VMConfig.disableJavaLangMath()); + return max(0L, frozenV2Resource - v2EnergyUsage, VMConfig.disableJavaLangMath()); } return 0L; @@ -244,21 +243,21 @@ private static List getTotalWithdrawList(List assetMap = this.account.getAssetMap(); @@ -745,8 +745,8 @@ public boolean addAssetAmountV2(byte[] key, long amount, currentAmount = 0L; } this.account = this.account.toBuilder() - .putAsset(nameKey, addExact(currentAmount, amount, useStrict2)) - .putAssetV2(tokenID, addExact(currentAmount, amount, useStrict2)) + .putAsset(nameKey, addExact(currentAmount, amount, disableJavaLangMath)) + .putAssetV2(tokenID, addExact(currentAmount, amount, disableJavaLangMath)) .build(); } //key is token id @@ -758,19 +758,19 @@ public boolean addAssetAmountV2(byte[] key, long amount, currentAmount = 0L; } this.account = this.account.toBuilder() - .putAssetV2(tokenIDStr, addExact(currentAmount, amount, useStrict2)) + .putAssetV2(tokenIDStr, addExact(currentAmount, amount, disableJavaLangMath)) .build(); } return true; } - public boolean reduceAssetAmount(byte[] key, long amount, boolean useStrict2) { + public boolean reduceAssetAmount(byte[] key, long amount, boolean disableJavaLangMath) { Map assetMap = this.account.getAssetMap(); String nameKey = ByteArray.toStr(key); Long currentAmount = assetMap.get(nameKey); if (amount > 0 && null != currentAmount && amount <= currentAmount) { this.account = this.account.toBuilder() - .putAsset(nameKey, subtractExact(currentAmount, amount, useStrict2)).build(); + .putAsset(nameKey, subtractExact(currentAmount, amount, disableJavaLangMath)).build(); return true; } @@ -781,7 +781,7 @@ public boolean reduceAssetAmountV2(byte[] key, long amount, DynamicPropertiesStore dynamicPropertiesStore, AssetIssueStore assetIssueStore) { importAsset(key); //key is token name - boolean useStrict2 = dynamicPropertiesStore.disableJavaLangMath(); + boolean disableJavaLangMath = dynamicPropertiesStore.disableJavaLangMath(); if (dynamicPropertiesStore.getAllowSameTokenName() == 0) { Map assetMap = this.account.getAssetMap(); AssetIssueCapsule assetIssueCapsule = assetIssueStore.get(key); @@ -790,8 +790,8 @@ public boolean reduceAssetAmountV2(byte[] key, long amount, Long currentAmount = assetMap.get(nameKey); if (amount > 0 && null != currentAmount && amount <= currentAmount) { this.account = this.account.toBuilder() - .putAsset(nameKey, subtractExact(currentAmount, amount, useStrict2)) - .putAssetV2(tokenID, subtractExact(currentAmount, amount, useStrict2)) + .putAsset(nameKey, subtractExact(currentAmount, amount, disableJavaLangMath)) + .putAssetV2(tokenID, subtractExact(currentAmount, amount, disableJavaLangMath)) .build(); return true; } @@ -803,7 +803,7 @@ public boolean reduceAssetAmountV2(byte[] key, long amount, Long currentAmount = assetMapV2.get(tokenID); if (amount > 0 && null != currentAmount && amount <= currentAmount) { this.account = this.account.toBuilder() - .putAssetV2(tokenID, subtractExact(currentAmount, amount, useStrict2)) + .putAssetV2(tokenID, subtractExact(currentAmount, amount, disableJavaLangMath)) .build(); return true; } diff --git a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index 73c852805a2..06513a0edc7 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -218,13 +218,14 @@ public void payEnergyBill(DynamicPropertiesStore dynamicPropertiesStore, receipt.getEnergyUsageTotal(), receipt.getResult(), energyProcessor, now); return; } - boolean useStrict2 = dynamicPropertiesStore.disableJavaLangMath(); + boolean disableJavaLangMath = dynamicPropertiesStore.disableJavaLangMath(); if ((!Objects.isNull(origin)) && caller.getAddress().equals(origin.getAddress())) { payEnergyBill(dynamicPropertiesStore, accountStore, forkController, caller, receipt.getEnergyUsageTotal(), receipt.getResult(), energyProcessor, now); } else { - long originUsage = multiplyExact(receipt.getEnergyUsageTotal(), percent, useStrict2) / 100; + long originUsage = multiplyExact(receipt.getEnergyUsageTotal(), percent, disableJavaLangMath) + / 100; originUsage = getOriginUsage(dynamicPropertiesStore, origin, originEnergyLimit, energyProcessor, originUsage); @@ -240,18 +241,20 @@ public void payEnergyBill(DynamicPropertiesStore dynamicPropertiesStore, private long getOriginUsage(DynamicPropertiesStore dynamicPropertiesStore, AccountCapsule origin, long originEnergyLimit, EnergyProcessor energyProcessor, long originUsage) { - boolean useStrict2 = dynamicPropertiesStore.disableJavaLangMath(); + boolean disableJavaLangMath = dynamicPropertiesStore.disableJavaLangMath(); if (dynamicPropertiesStore.getAllowTvmFreeze() == 1 || dynamicPropertiesStore.supportUnfreezeDelay()) { - return min(originUsage, min(originEnergyLeft, originEnergyLimit, useStrict2), useStrict2); + return min(originUsage, min(originEnergyLeft, originEnergyLimit, disableJavaLangMath), + disableJavaLangMath); } if (checkForEnergyLimit(dynamicPropertiesStore)) { return min(originUsage, min(energyProcessor.getAccountLeftEnergyFromFreeze(origin), originEnergyLimit, - useStrict2), useStrict2); + disableJavaLangMath), disableJavaLangMath); } - return min(originUsage, energyProcessor.getAccountLeftEnergyFromFreeze(origin), useStrict2); + return min(originUsage, energyProcessor.getAccountLeftEnergyFromFreeze(origin), + disableJavaLangMath); } private void payEnergyBill( diff --git a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java index b7c6354af37..30d778d0990 100644 --- a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java @@ -79,10 +79,9 @@ public void updateAdaptiveTotalEnergyLimit() { / AdaptiveResourceLimitConstants.EXPAND_RATE_DENOMINATOR; // logger.info(totalEnergyAverageUsage + "<" + targetTotalEnergyLimit + "\n" + result); } - boolean useStrict2 = dynamicPropertiesStore.disableJavaLangMath(); - result = min(max(result, totalEnergyLimit, useStrict2), + result = min(max(result, totalEnergyLimit, this.disableJavaLangMath()), totalEnergyLimit * dynamicPropertiesStore.getAdaptiveResourceLimitMultiplier(), - useStrict2); + this.disableJavaLangMath()); dynamicPropertiesStore.saveTotalEnergyCurrentLimit(result); logger.debug("Adjust totalEnergyCurrentLimit, old: {}, new: {}.", @@ -178,7 +177,7 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { long newEnergyUsage = recovery(accountCapsule, ENERGY, energyUsage, latestConsumeTime, now); - return max(energyLimit - newEnergyUsage, 0, dynamicPropertiesStore.disableJavaLangMath()); // us + return max(energyLimit - newEnergyUsage, 0, this.disableJavaLangMath()); // us } private long getHeadSlot() { diff --git a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java index 1d6cd1c7415..7e170f9dab5 100644 --- a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java @@ -54,7 +54,7 @@ protected long increase(long lastUsage, long usage, long lastTime, long now, lon long delta = now - lastTime; double decay = (windowSize - delta) / (double) windowSize; averageLastUsage = round(averageLastUsage * decay, - dynamicPropertiesStore.disableJavaLangMath()); + this.disableJavaLangMath()); } else { averageLastUsage = 0; } @@ -83,7 +83,7 @@ public long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, long delta = now - lastTime; double decay = (oldWindowSize - delta) / (double) oldWindowSize; averageLastUsage = round(averageLastUsage * decay, - dynamicPropertiesStore.disableJavaLangMath()); + this.disableJavaLangMath()); } else { averageLastUsage = 0; } @@ -116,7 +116,7 @@ public long increaseV2(AccountCapsule accountCapsule, ResourceCode resourceCode, long delta = now - lastTime; double decay = (oldWindowSize - delta) / (double) oldWindowSize; averageLastUsage = round(averageLastUsage * decay, - dynamicPropertiesStore.disableJavaLangMath()); + this.disableJavaLangMath()); } else { averageLastUsage = 0; } @@ -133,7 +133,7 @@ public long increaseV2(AccountCapsule accountCapsule, ResourceCode resourceCode, long newWindowSize = divideCeil( remainUsage * remainWindowSize + usage * this.windowSize * WINDOW_SIZE_PRECISION, newUsage); newWindowSize = min(newWindowSize, this.windowSize * WINDOW_SIZE_PRECISION, - dynamicPropertiesStore.disableJavaLangMath()); + this.disableJavaLangMath()); accountCapsule.setNewWindowSizeV2(resourceCode, newWindowSize); return newUsage; } @@ -196,7 +196,7 @@ public void unDelegateIncreaseV2(AccountCapsule owner, final AccountCapsule rece ownerUsage * remainOwnerWindowSizeV2 + transferUsage * remainReceiverWindowSizeV2, newOwnerUsage); newOwnerWindowSize = min(newOwnerWindowSize, this.windowSize * WINDOW_SIZE_PRECISION, - dynamicPropertiesStore.disableJavaLangMath()); + this.disableJavaLangMath()); owner.setNewWindowSizeV2(resourceCode, newOwnerWindowSize); owner.setUsage(resourceCode, newOwnerUsage); owner.setLatestTime(resourceCode, now); @@ -224,14 +224,14 @@ protected boolean consumeFeeForBandwidth(AccountCapsule accountCapsule, long fee long latestOperationTime = dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); accountCapsule.setLatestOperationTime(latestOperationTime); Commons.adjustBalance(accountStore, accountCapsule, -fee, - dynamicPropertiesStore.disableJavaLangMath()); + this.disableJavaLangMath()); if (dynamicPropertiesStore.supportTransactionFeePool()) { dynamicPropertiesStore.addTransactionFeePool(fee); } else if (dynamicPropertiesStore.supportBlackHoleOptimization()) { dynamicPropertiesStore.burnTrx(fee); } else { Commons.adjustBalance(accountStore, accountStore.getBlackhole().createDbKey(), +fee, - dynamicPropertiesStore.disableJavaLangMath()); + this.disableJavaLangMath()); } return true; @@ -245,12 +245,12 @@ protected boolean consumeFeeForNewAccount(AccountCapsule accountCapsule, long fe long latestOperationTime = dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); accountCapsule.setLatestOperationTime(latestOperationTime); Commons.adjustBalance(accountStore, accountCapsule, -fee, - dynamicPropertiesStore.disableJavaLangMath()); + this.disableJavaLangMath()); if (dynamicPropertiesStore.supportBlackHoleOptimization()) { dynamicPropertiesStore.burnTrx(fee); } else { Commons.adjustBalance(accountStore, accountStore.getBlackhole().createDbKey(), +fee, - dynamicPropertiesStore.disableJavaLangMath()); + this.disableJavaLangMath()); } return true; @@ -258,4 +258,8 @@ protected boolean consumeFeeForNewAccount(AccountCapsule accountCapsule, long fe return false; } } + + protected boolean disableJavaLangMath() { + return dynamicPropertiesStore.disableJavaLangMath(); + } } diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java index a65c814246d..c3776921244 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java @@ -244,11 +244,11 @@ public void pay() throws BalanceInsufficientException { callerAccount = callContract.getOwnerAddress().toByteArray(); originAccount = contractCapsule.getOriginAddress(); - boolean disableMath = dynamicPropertiesStore.disableJavaLangMath(); + boolean disableJavaLangMath = dynamicPropertiesStore.disableJavaLangMath(); percent = max(Constant.ONE_HUNDRED - contractCapsule.getConsumeUserResourcePercent( - disableMath), 0, disableMath); + disableJavaLangMath), 0, disableJavaLangMath); percent = min(percent, Constant.ONE_HUNDRED, - disableMath); + disableJavaLangMath); originEnergyLimit = contractCapsule.getOriginEnergyLimit(); break; default: diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 4542b96a737..1eecc103874 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -931,20 +931,20 @@ public void consumeMultiSignFee(TransactionCapsule trx, TransactionTrace trace) throws AccountResourceInsufficientException { if (trx.getInstance().getSignatureCount() > 1) { long fee = getDynamicPropertiesStore().getMultiSignFee(); - boolean disableMath = getDynamicPropertiesStore().disableJavaLangMath(); + boolean disableJavaLangMath = getDynamicPropertiesStore().disableJavaLangMath(); List contracts = trx.getInstance().getRawData().getContractList(); for (Contract contract : contracts) { byte[] address = TransactionCapsule.getOwner(contract); AccountCapsule accountCapsule = getAccountStore().get(address); try { if (accountCapsule != null) { - adjustBalance(getAccountStore(), accountCapsule, -fee, disableMath); + adjustBalance(getAccountStore(), accountCapsule, -fee, disableJavaLangMath); if (getDynamicPropertiesStore().supportBlackHoleOptimization()) { getDynamicPropertiesStore().burnTrx(fee); } else { adjustBalance(getAccountStore(), this.getAccountStore().getBlackhole(), +fee, - disableMath); + disableJavaLangMath); } } } catch (BalanceInsufficientException e) { @@ -969,20 +969,20 @@ public void consumeMemoFee(TransactionCapsule trx, TransactionTrace trace) if (fee == 0) { return; } - boolean disableMath = getDynamicPropertiesStore().disableJavaLangMath(); + boolean disableJavaLangMath = getDynamicPropertiesStore().disableJavaLangMath(); List contracts = trx.getInstance().getRawData().getContractList(); for (Contract contract : contracts) { byte[] address = TransactionCapsule.getOwner(contract); AccountCapsule accountCapsule = getAccountStore().get(address); try { if (accountCapsule != null) { - adjustBalance(getAccountStore(), accountCapsule, -fee, disableMath); + adjustBalance(getAccountStore(), accountCapsule, -fee, disableJavaLangMath); if (getDynamicPropertiesStore().supportBlackHoleOptimization()) { getDynamicPropertiesStore().burnTrx(fee); } else { adjustBalance(getAccountStore(), this.getAccountStore().getBlackhole(), +fee, - disableMath); + disableJavaLangMath); } } } catch (BalanceInsufficientException e) { From 0eaf62ea21e74bfbd21a02207e811d2e8602c524 Mon Sep 17 00:00:00 2001 From: ramonliu Date: Sun, 30 Mar 2025 21:34:43 +0800 Subject: [PATCH 1189/1197] opt(tvm): opt kzg jni links --- .../org/tron/core/exception/TronError.java | 1 + .../common/crypto/ckzg4844/CKZG4844JNI.java | 21 ------------------ .../lib/aarch64/libckzg4844jni.dylib | Bin 259976 -> 259656 bytes .../resources/lib/aarch64/libckzg4844jni.so | Bin 359168 -> 358928 bytes .../main/resources/lib/amd64/ckzg4844jni.dll | Bin 299844 -> 297542 bytes .../resources/lib/amd64/libckzg4844jni.so | Bin 287584 -> 287424 bytes .../resources/lib/x86_64/libckzg4844jni.dylib | Bin 279944 -> 275416 bytes .../zen/KZGPointEvaluationInitService.java | 11 ++++++--- .../core/zksnark/KZGPointEvaluationTest.java | 13 +++++++++++ 9 files changed, 22 insertions(+), 24 deletions(-) mode change 100755 => 100644 crypto/src/main/resources/lib/x86_64/libckzg4844jni.dylib diff --git a/common/src/main/java/org/tron/core/exception/TronError.java b/common/src/main/java/org/tron/core/exception/TronError.java index 9d11d249476..6950e7a0cf4 100644 --- a/common/src/main/java/org/tron/core/exception/TronError.java +++ b/common/src/main/java/org/tron/core/exception/TronError.java @@ -44,6 +44,7 @@ public enum ErrCode { PROMETHEUS_INIT(1), TRON_NET_SERVICE_INIT(1), ZCASH_INIT(1), + CKZG_INIT(1), LOG_LOAD(1), WITNESS_INIT(1), RATE_LIMITER_INIT(1), diff --git a/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CKZG4844JNI.java b/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CKZG4844JNI.java index 6f819650a81..83d12b380a0 100644 --- a/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CKZG4844JNI.java +++ b/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CKZG4844JNI.java @@ -47,40 +47,28 @@ public static void loadNativeLibrary() { public static final BigInteger BLS_MODULUS = new BigInteger( "52435875175126190479447740508185965837690552500527637822603658699938581184513"); - /** The number of bytes in a g1 point. */ protected static final int BYTES_PER_G1 = 48; - /** The number of bytes in a g2 point. */ protected static final int BYTES_PER_G2 = 96; - /** The number of bytes in a BLS scalar field element. */ public static final int BYTES_PER_FIELD_ELEMENT = 32; - /** The number of bits in a BLS scalar field element. */ protected static final int BITS_PER_FIELD_ELEMENT = 255; - /** The number of field elements in a blob. */ public static final int FIELD_ELEMENTS_PER_BLOB = 4096; - /** The number of field elements in an extended blob. */ protected static final int FIELD_ELEMENTS_PER_EXT_BLOB = FIELD_ELEMENTS_PER_BLOB * 2; - /** The number of field elements in a cell. */ public static final int FIELD_ELEMENTS_PER_CELL = 64; - /** The number of bytes in a KZG commitment. */ public static final int BYTES_PER_COMMITMENT = 48; - /** The number of bytes in a KZG proof. */ public static final int BYTES_PER_PROOF = 48; - /** The number of bytes in a blob. */ public static final int BYTES_PER_BLOB = FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT; - /** The number of bytes in a single cell. */ public static final int BYTES_PER_CELL = BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_CELL; - /** The number of cells in an extended blob. */ public static final int CELLS_PER_EXT_BLOB = FIELD_ELEMENTS_PER_EXT_BLOB / FIELD_ELEMENTS_PER_CELL; @@ -214,15 +202,6 @@ public static native boolean verifyBlobKzgProof( public static native boolean verifyBlobKzgProofBatch( byte[] blobs, byte[] commitmentsBytes, byte[] proofsBytes, long count); - /** - * Get the cells for a given blob. - * - * @param blob the blob to get cells for - * @return the cells - * @throws CKZGException if there is a crypto error - */ - public static native byte[] computeCells(byte[] blob); - /** * Get the cells and proofs for a given blob. * diff --git a/crypto/src/main/resources/lib/aarch64/libckzg4844jni.dylib b/crypto/src/main/resources/lib/aarch64/libckzg4844jni.dylib index ad11c215f34bf5e7706d9bb8308351a9d8315c84..965485287527713798cb3c18b136d2a778c132dc 100755 GIT binary patch delta 41768 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 Ob}OyrLvXR?Iq$#g5Uq~@ delta 43322 zcmbTf30zgx`aitZ+6Oo&4$QM0#0h5+9CA8nL~hxiXtGOIb`Q3S}3L*H@Z!| z2@WYIEi~=ea0}7O$_j^T!_Nwb%BdTc1DMMH`|Q0Bpmp!(zVG?SS<|zg^{i(-(;C3z z*IVTO)}k=qtGq2!KOwt?nwGbs)pOfv<_86l-V+0p~pD|k` zHVB2X4<(k>jj^Uwr*&o$XX;NEq}}CZhA?iHOAKKx-QAM+vmP-!{?YoqG3#=k`cSSk zWVP$FNn!yKW0C0GQb$a9LiMugH;K(MzBSKfl4*UH5cg57SW%KN*H+4HyF?i(!>eNC z$z8@EGqRWbW|z($m2rmNws_7eQ%t?(U%FULm2uDawpGc@w#>ttu(p&H%|dTupt&{{ zK-4R9U{sSveMUzI%9W3GkPY2B_Z$fDo1;G{y}yK)-j8RtKO|;nO{@u{s2=%p&JI0< z4%GY>6(o#(WJ|X(CZf((C3)K!A9VIS;0adhYp#vM&~YdF$iH=q3=RaY+y5Qc=cb>f`w&@}WsB&bb{+cF zQ$r)FAS-oh9^pW7FM~Y1M<4fS9j!xN)uVH(|2CbfzVhiF!=o$vMlf3>2w5fA!Fo3T zw~pY$=%|&!vqAWu|D6v_doJbIuNP1`Q{yXXI?op=8d>P3+ z$#2q_uJY#IQNn-sTVM8mjEll%a+AI*4P~m53=0z72gqTuPS(`-y56@1Ky(qtgj);@ z8C(_#dR!UvF+OjWFE?eiMuRnB1ZQQDH~QPIM6goOSk_p>Y_B~;qdH{fz`vof^0Ap1 z?Zg1NU%wEah8f%(sB-VT>r#UH|ihJIL1u z_7~<|@|V4bzLhn|$VHQ;@?!H#y5xu|{&z%8iPeQ9NMKP4Vnd=UBSDMTe^?Zczt&eq zj^*kUZ2WJhP`dMfoI+MyPhKYPjO!zw+6k^k85FF(>=S>6m&mchCd-2ddphT`Q2cc+ zp)JfroMw9)OWKcvTNxl{9&(R?J|dR=H(I~j@juhrRsMaTmwbIl2eEPoSl-L9g{U1f zw3`14YG)e?o$AopAb*(PREI)RqThyfKr>VU@|AF+X}v=C0R2~>1*!&wOE$PmpBiU* zp5)|iVPlPG{xHSrsH72vy4I=#lGbL$ndOiXJ^a6wY?q<^#~{2_vbpayqzAUMBH0`h z)~c|v0ouq};aQloPsyV(b8V@-G$z=P+=Pu=|73T5N4_y4tjkffRZ0GK&a9^{NCEcy z%`|tT8h;*-Hg7wW&3*wel6<6Rgm&Lm=1kB;=WoPj^?>x&8O$(vG>hDk@l3P-{U58}paoU?INn85udBTH|N zexmgD(~p%V^48HU>PLo~tH;#^6kOiTN>x$6VzlWF>7fODsrY}M zcy|LWoLn@fH;nM#%|BH389R!+A({05%z^yBa=^33y`JjV(R^*2oH44G;T0OslrVgd z`wsUlBiz|R)qT0@?(07&Yt^>@aYhiy7R~;;ND??G7si?1%6iJgc>xx|I;N$@)br53 zoLhCuT98Tk25Vh|H z>WexpnDDmeMzf+1UD*v&Q#MYC7q;X)W-A8#898>Ex95wGK&Q(4ll}QeYTI*L(qQgMzKURH3dx?^d@!O#~*=? zluM@hw_WwnTs1!Rdjv8_{(f2nwii6byUVUEtf&TiSgR{LNHGbAB`!uCofVkifv8T& z2LF&Rm19$ad6GOer8n;+Z%CQhCKr$ts%5KbfIUl1ee4-X_ehg!;EAhc)AU?ELEbPu z!u_2bR`fFbL9~2i`srau+}OdJlCUQl*^Lx8HqI($zRD(=nzKILyBb-$R$(se#vWHT z?v}*uwE3?>>ITGgq*3ky=jdi#e?{_9ev1))UGFp7p!@8`aWFOzdU01WeoiL7uN&$m zpKDgI&>i(gqc!206ezct5&ZObo5Q5QYa<@ijq5$xcZ((n{)j4l?Z0ehMFDD^KLjg4 zt-FA_D&$Fr2<8WrFJdnKa3(lZ@_7y^;rL2kHY3cCiB`FIMj)xjdo#L-Qw!v)Gcqjk zU4Z1MyQ&%MDIae{-p9U9&ATA)YcGM9s)7X4K(DI#P}})<7uyB&bAOuJd{7p)3+U^j zmYbp+in5RG!B}dia#P#9Nm|}-0xPPEZ)byTlE0og!2RAL)JHH|iX1x2KlJJX$k^RM zH>xNmMJ-YDn+`ES9y{x49wV2|3J&qTSEm#$XSQw2%{Q<|9e008EG%8c9*S2L^B^8% z5m+Q{C%HkG@X)CPW6Kjru3CX9>Uop|xl+gSvmesO3V9BPL4rktou|%XoFw62a2_x_ zKwk~YVR_~oR?v6^_0)H_-mf|O-NCY0;~&(;#9$35!kLd0r+YpnUf4+h_ySldfru~e z*D1F^pp~&0LQZz}_pV?E+8M2wdA4tOeQ-Vs6C8=){0Ri-kC)cvX~Fr$SLA=E4dp3v z%l3XRh^IX0T~+?l#fJnvnkr zU;!5nhSp(TRe1)zpP&7Y!K^44L#wK(;_|omCfp>OYT1u)O9@wc$q(j4MS66maj_U` zo3H&n1X>qHB9tQ9P=AqdVB0_JlSma9Tp4t!)(NT91ES4byjB`2l(7@gv&j65Jhqc;(gTumh74AEsx1)Y59d~kux1(dV?cA z_@S6$BnCd`isMFIZI5FV;%JhQ9dyRt|oF+Ky|A~5KoA-B@j13s&m~ zoTQasUtMy#80yO<|AGrrpvC@0E^!NbE(L=#LH18kKI_VCKf0Q4m)7Jt72^121r?Dy%usY+hO5?CvPnF)wOh7c`szyV^ zqhjG#upB?65NnAQFnd43+{VJ(-gYzBUT%RyT)63A!1}welY9L93)m%=$vE40S*6L_`YAp0DZ@4*G~qfLK)%ftUn%xfG=0#e&+$1J823Ot`1!PC$jw0I1>_09-&y z9HE6AiZY!Q9U(gnnPEilmZ`Q?}M}1XOb8QGr?RLNhgTHdstUyagY>QcO z_82&umL#oW(Al~?^U1n+myjv08d6OxmsieakIX&IjBH5jm*T;^5Z5UXYbC(BNXeKn zaRl@W@B;TmfXVJbI=6$LEJ6Kv8c<@k5|oEyP=dRNGR23QRr9fbiopG*qX7^46RVhAbf4_&5)+xcC1LGLq*88ENn-|4B~580+h_Y*T==URERu z)dK7niAu;yFI`p^=&~}2W|KErPD%G{aUL5AGX1KEHRvP zUk!BADIkQ)LSe~X&~C1+i=jm&WL6>u`En;Q$d3Xsrkc8FtW;&aP(1~q0(^r|`PK_n zDCS)+RG18N3Kig;LiOB2Hlbdswh)!@`?REMF&m=p0?K5CE@Ejt;3p}*NFqZ3gw%Es zFqc3aN#0L@nTVin3k2?G*?qw<{+&E_fj9q`oVp+^@-p@MFx!Vz)<>i0e6O7LTtv5a)LX^GY~N1@1oA`= zLA;J0<*w#^Rc?Hr$~f8rJQw&(G3x8|9r7L8Aya?+{D%6kAGr0d#T;6L(Q#Hk;36uS z?WIRXUxzYWg}Twm*hn+*v8T&j7WOkdiIOtq2saJCExD);{~pxtPZ+>E;NLa_yHSOm zc`bx~uwaMa<`X*L=dxgZvtZS(WNZWKrap{^>J)fOXQs7VxXlDw3H z5!wgbq9CD&0)9-BHtxIb)G5rJ#oP*GwKX8|b};+~QX+jTe1_G?VlMleYkj#l`p|Mv zVBupQ55siX8$JT{wD{y_Zj=7vr$t?zf@md%yes1rj0D+tVw{`sIaRI}7BlH6yk4BJ z<-m$Aft}xq@~tp)?ID~Ngd>uuf`_DCQ%z!ADP2hr(m#Og5@h%%aPDUe*in!7@RGsD zIXlv1a{IJdQ75>8*3;Ymqni5Lzo*n2$o@~Q@Uwrbrr3^SVNCrgG$b0`fs%Y29Xk;T zzd(%CGTNLW9!rDyNO{!KZfy;~NPR8< zmdqHP1HB!EzQA!FKiko^K`vPu5qT;`lfcUn=335!3aHnwz)YhMl(Y9X`PZfWBFoz& zyg;p{34!)ZgaMb^lSl+1U=1p`j1?EiN6KSg7{ou6Z7+Cx&ZBXO4jtnd`Opi)+U~>{ zDuoj5?X?q_2?QCBI3GVWN{k$C32WVj#=x%27rU;6;W$nJ(`g3>zP}5-hA-UA@gpiA5`>Y_IBYRpy1|JpJ1GpfnbcGDKA<8sDk=(HdXi|DVPuPaz z7SVYNcey=o#2L5GV(d^~$PnFx-KKa+o@e#8%*Pn2m%|pFu@&mJJqvZD_DQsD-$91S z-|m(Rnvl=HWEngl?WpcRL9Dc+LjA3*h8L-;b6otFk~pg z>>)Uh6>6BR9rF0t1%k|r(93k_Wic)fXn*V+u?h zkvI5Bar~bE4nZ0yg%l*?hZf-|7Ks*%ICog?yF9`&p2%ovO(1Lki>#Re>+f|i4bFov zKl@AI8Ad|j5TKe10r;;lI{b^u$5j}aD1b;Lyomf};0Xi_8C=aM``JJ3fb9)z!J!If z!x5dj#aU8UC;X4e-!E^4OQ3tpJ47BvM^zT_>}5Ijj@sh++mE51@-%m{?j`c5yqV*+ zy1>2GNu@XIM5($=m{>>Wl0{(IlHsP2I^Fb}nXKp#B(?}l6hB9rg?s~IYdXYhEMcaOo7ScS52O8HwN7OR4r|J2b zNU1+D5h!s)t2H7sxElV(Rzt8jijo6i&_a(WqeX772mL=R>59Nb6yBn7!%ogryyBRz8 zNNi<{++-W%qV1U@EO>6Eg$|nX7{CP=u=kchU9?kI;OaZBG}k=t>sL@9j0MTuybm`Z z`;0&o1|&orokzg1o%~Vo8_DqYM5I61UIWEObm~(+!GB8!DE_CvFFnoE(rV)7q}50m zXUFY2#ex%)81+Cyh#OTn$)*@2|3TeBVp)^$x6^<{y3Sr1ckJH_D&@IDm*I z5^$>Ja}O)8!3Enl0y~|OUAC-PPX`rOz++SR`T?d;`~>317eAi(X@(zn{J7wUuODEH z75htYEFVGZ*VOzZ!YhB(`Z*V{IR*_;=NN2Xib3weQqsbh=PamMgmNOJ%qd~XSi~wi zaRFsG@ljWCJ`Qs_ju2m_1JyA#YrkKK0(n2hA*Y$F%)lYi9mksa~ zX2a=Q8QqULK`3c{N0 z&Vad9K?3Yst^jpvSZ`>kdr>~J#yfBsTB>joXhk4@7uxK^vPAxMjeq2P zw35+*7GTD7`V(Sb4kxSjLRt4?3D3%1UhX}72H`^JG+j;o?9*0q@gj|FkUb7Y_G6wpB3+RtT0PKQlN@bz!E@1x+35tvU9D19*Nx zl;r_wK_T{d6uMiQpS&%(VyRu=UJUkH{do7Te%y83hqeW)5;%7+AgQI3{CCjzL+tka zu>f#br`(s!su^^j-!Q@~8C{sIP8hFgs)C>bFHW`qUfmdA@zp>B)_o)DR3Wio^)I{n z7l>b<*S&I(y#$SQ@TJK>NN1$Z=wub@NiIyPtOGf;Y6aENW|20Mh?tymPFwyhLa!OgW0q|#be0R@iO@?S~VDkQ;SssyzMzO5RlGO zQ$+P@8e*TTra^Y4uz;J~37b3S+)o~B^A4Xq+I>sxDz?wetpm0!?ohJ?SBS)+Fz$a1 zhauzMlULfFuvnxf*EnnxMT@He^)piE$hDZ#MvH|Fei5q?>&Yfv33qCC55Hes6j}LOBU5^@((Of zx*`-)kLtK>P6noz$8D$Put`P5t}Ggl0I=WYw#k@}b^^z7Z4h9;J{x6RHPA^M&G}oD z)w4f@R3+G8(L;bGlF4@WqPcXC6m)GFu6Al6@^?XGqP%ERMBv*XkvMr!O?~YL)YQ+8 z7io&WkvG$Jn6hbvsaanz|1uag{LTyO-DUntm!?727@WcgygD$-eP0Q&fWqK#W(#2} z)WB>KMo*N)4HM$3S+f`S!IQw~J5b0?U2!4_>Q!qG_DzT4VwN$rSh0&u$c4}$R)7}# zz`?r!2Jv~3#llK0U>iMWxZD$lROiY)Vi)o_;pMisrm!Lk+Ud^i0s#>J!4?vOI-y0H z(5ONq_qQ1rEw0H2^^ssn2VY|WM<{$=lJ;H5qYFvMIR?58g(iIEz_%Sggm3C2_&x?# z!dsX_YpdV@FTj*g*xD4bMLTSI^4=3%m8*N0ECxuzEy$Sj9G`h()FlE3Zp;w3ftaAL-v7M~7tH{X~A4J*aV;Rfp2z9a}lI3$S*l@Tx6&FP597eEzD#eF zz3o59qqf8k0GF$s=P!HmTGdR$e4Mu;CJaGaO1udhm-II;U^>X*+rs#3a_lzm&}drT z2naZSu1$9CXDOWVvA-jSZtWMa^yUA&S>DfDAIkEU55~ZM; z5Ai6cHAt!wm}cX5&Ltj7 zP^f5ap(|**lB4VUL-%4&KT~5ly%|5w4L!N7OE8Q-LD0UyaqOPvz6HSuEs{iVK?n>i zPYl_jxi$(9G`ORHqiqzu*?I^5^*bC8+y=vMA*^T*8~HW*R^jLitg+btja4DXa6zrm z4h@St(k{~1UiDJ^KL1f6TdLfQ`>NXG((DOL_N7=H-@EQRpBD!$a6?Mk;IfYpk{>)0 z1}-D7ZHD~pS#aJLfZzELEgj_m$Qq7_ZD->w!d3)9B#+N-BVy2~vi}1S<>mH|mtLKW zBOyF>GP#@Yn(-5Rw{G0!L_CkbTX*O(q6VX6Ecg_&F}cL=t9nV=X9@?A?XB1?fykHm zzHkmA^8`{5naB2>fR_EZ2Eo`-e)8sMm(u%#m$>2-kZZTyxVbdq89GVfg};$P(xShU z!ab@KCXo~dCW3IM6#795=_rXLvOu1<&6^L9S8nUacgjb$^^4d7GF1JAk!^f}vm5oQ z<)O!e#er@6K&J!pe8E4}c&i5ejalF+${LUT?RI%;v40SPzQ27ZcA3j-i(7{-z(xrs zO0~Jp^f{DC(z4`}#l78}!?q}i^vtavLQ|nEc|=L?whw7SUT94m+#Nkrqlq|`^|)M; z>d%exJ0)RlI%CW_3l5$vIC!E7y2`$OFe>Q|hFo)Am4f zG#F4MaPNb@)Sm*j&O{yZ&JAJ*l<5wF?j4RG@+3W`YfsWTdByfNvDXT;MZY^!;P6wz zA*ca|p%4Il{f9GgGVDIzza1ArjYEpbP?s90Cthafd0Wl_i@Ih_*uiqhFS(|#QKx!& z#Op>Vojbh5Rj~Bh;#oDFx-``fPL}PZF!@JpBxrih{VSbX4g={w;_B-tq>Gf6{3qR8 zXzQyn|EHPQV7W1ijSfNvNq*OoV10UDTXH&Cy#Qi1LKFi;Rw}!h_b~(8*V~PqT#jcD z=dm^)1HoO`^XKl@9aJb1kQ#*NOSE0UDUMT^-a{FVK;PN$~Qs2xw&>e<(ngqmk`;M_d*_51DW#uoxyyT9Js3+p2LpV72Iq* zwFaTJmAN)Sp0}&O(hfCAz+a9PGcoPVKAh?>j;T>y2-RUcD^^jx)rM)s3zDKFj9cZr zl0%&r)nR-y>P&Fo9NWicROhE%(@_kd3AdkJHZiXvhF58L(XL;gG20CJ<=4V|Uo@c$ zUXkE!J6hCdEw*RmBdBB4F% zDFoukw^%JdX%A|$9giak#A~&jZJ+J??^T#zD;$B)!3i-Czs7q-zG3&~MY7B55rNlX z5pLJ9(s!_ggXZ+9ap-&OOLFY%!M=G2+X5o!FtFtfdf7x6jPktK!#qC&UJ|h5YU*eI zST1?}DZ_S@D58=B_WJm4Mu8?;45HOF#JAxR#x??(dW{PJY;J7Jz|9-U5pl4`sWL9fvD%9-=7EhzD8*|ty5=drST{~qLVb9OsU-%g zf2Y)x-YL1Aq?P*fD4kk^h+-dpqZwg$vkth-SRq^Lc-5Ep5`35AU;g|wH*`nzr&J!} zt(4CK`7jrN@}-Jj5bq~Kd>l^&@n?BtB_lKWuaz3n&`;D+Z zD#~RQDr&w``7W5Ra|a5l2Ab>;{v98tj0)u@Uan+>@P7L;$~$+D?U)%N>_r0 z@JQvuR@{#lD`#8ro`6_8ga;{Y!uULZZ4BcJxS}*O@j9mU5zDI_S;M`Ry(ZpXDvL`}&YJjmB`=VBD*eN`4Vc)@lZu? zCDC03DrMpPYo&JpZ>Cg!&kf3^);xg!TiM^5w+8r`*1V5KK)EuhE$HhU!Hb*~A4l-* zEzbj2csYoOV77>Bb&AqGfcq$gf!rXsoa)2pDZAS67l5fvTi)H-5t!ZtXPUI*6NH$f z@uHv|e+<0%xLpG;eA@GQf#yyKJ8|&~i*Vv9HWV19g0bqja^=G_L7`Dz*WRkC9E5PnqYxSY3goQdJMHm`7e*@w#lyqeaJXYkjQll}M@)VA)=zoy!| z1NjmZ7YyS2IWJQ>#PSZb{INU^CHzuKZ>jPQaK!R(YOaps{hNQ4Lg68|AAv51mn)CO zqpeJt63=@|m6-DSc)l#OG7c-D#UXV5@oMsXKINSVrbSP=@2E+Qg}`ms*=7g%zrwL!T!mOo>_R0|bz0v7vzqWUT> zh<8weALpTtvIKsdD_JACpR#rw58_!$={UYtDr4a0cpk21o*mC~gvmuYJswh5;dn5f zdken9;Wd$;miTtZ&y)FNNwf}9;uCq4ds185X;rqwP1Qh1D^EC+1(C58XP75Ya8Y4voT z;3VO~bUqb0%&FYe>}xcW*sF1c(&MP`c34w+TT-~!WIc4^7T{5m6DsocQ>t$gVoxhS*>=tyzN636LNXG z=IY|Z0=->tftI_eYXEL}&*xK!21oXMK2-3%j(48pEjgJlpsa);Jhf1>W_nR9dZ-xn zaB&)n-aEL>fxhYzN?PEsu_q*=Y!Tmu1#&#Sn5POpNBQUTdAp(3gxq9d@9vAV8?CTA*HUVHEg&-Lovs@WygERhAnKu$rP#wlYcwc3ujYs$$ zhd4K^WN3|!>H`}eC6z%gny-id`Bd3&5Z;P)J@+x(8V#z}*m#J6x+;g)^F$ReNPZZQ zA5cnUz8!65$Iv2vRpM)v9-CDA^xY=@G~cd7y#gCn;rRU(zFaa47^Rw=07v0J_(bB< zm2LcV$6^e@%Dbu$a_%qru=GAwj0ac~BEG0o=p6+ePH8a8&&6;h)k^0Q-bpHhWK1gI zty~e@&o?r(^h2sZ1pCE~5Ba{!G z=WUcpZ}6F@tayX(;>s_(VYn8R@i0T~a9sfYS%#`l>`=vXWuP41+|gt|KO$+c-yg*K z!CD;Ty)+>6AvjqAntg~rYk+|H*}#2le}qR!fN;EVg#S~J z^n0q;`>k_u8N-Hahl2S)Vm#8-Hi)qsoG;s~m6Z>U@gbp&++I-4EDx!`cxB1yD|qx$ zM()(~5s$zqgFoUUd{W2_O!rY9!n^$=p4bIV#nLPN)haX>OPjR3jq*x= zI{3Z`PrVskpnF|E=A$_{@xmwk4Zcq4a-1Iv1cs_kR&@Xd3{^M^(+6nsDHQFfDEGhO-3)t3*t=KqK~fnwmtD!fmCCjr zRh~QvqiraM1dTZbum3=qcS;9#>^#LK=pLZ$r}-CBwK3MQ_zeF_;&G10zu`eb@PW#V z@Ayoe1%<={I!OeDh0Nx-@Eva=@i67r@1f}xj;J5_2#GwOr&87rBXv{uorj~XR=zpU zNBdL;91XI)f{uNULjAGt!&#=1c!B#m#$4dRylLg3xIi1OM+*avDhn=h8zJ&mf-WIw zUgPL{iI0&m#OhxlLlEbTD|`nMud9&iqmH3hxj*ss*=sxxp~i)4*ue03$JAeWB>{K+ zjrRttX8guW;5CXJO{zKPlvA4DfaR=)TTi&bm!Zb&ID3OX!JgneJ&u-)V$4HB;V3;;V+w6tMZ(r@mdM zBm)9=a6&DRmn#b>sZci7a)k)J%O@CW@z7J-7rl0ue-65{|5O{B+~bq@GDqq?XtxNB zQEuPouZmmI%9q2iDJXluS3OLNbZ8ZZ>sbm(HG;d^BH%XIwETk}v>G#}_N@{)Sd`ovst3sL3MEtVZ~^W3GotARaIqO^2NmQser_oSDw{lD?_xZKzf$fYl9auk;v8S4xz4g? zB1By8hCjH|S~=$>JPf3*%5^U>+^~vreY}N2hQV>lTiBre0Y@D(d_`04tCQ6F&3ck5 z!_CTzej*|Oao#0I^8-8Uw*5YR;Emt6gSt)FXIxc|_zBwjc=?O9f=4MOfnp?z{|*%J zNKZHhgo=KGzppF`6Wd`2U{rk^-Ay8x2SW!szzX=;=j^Rh-p&iGDX+lq@PfRQa>tBt z@h^BbXvx3`5#*}ZJ{uuc@-VgEi?8EB0OaR9whD9`?7;bi2BnC$VytF@JdVQz^>wUl zOC;DGN7{=sJkZ<`gZkUk?3m(mZX^5rG&qm#*c*`|UQqk#Qmsux9$+7bb{NPeoy9c+ zELWTo-bsWh0bRr{h|vdK1RlghDrO+Z&bgpQNE%+ue6RAkqw%7*`L*pCk>8Mo{bl=(BR^D(T0~Q zAH|Dy4}(nr*x5McLA)5DgEg^$ByDJA!C(>IUZri3Mh}8=VRO>hhLx``*z2TI`CzaJ z1&(ur#UP5+op4IKAtDm>V}^+KO5XF_Gg3vawU^PnX-x^&{Uw8Omw>ZKwzUuzjd_3dw_^BG`aF;R+w7*7q7FUU$c+ zUYF~RoJlpY=aD74Rn;*6tU+t(Lr|U>Dxe=E2 zBgJEUrt-x|(HY3@juc-SIslns9w{P~Tcd=j5p1g`0c&u=zWAh=-Sr2Y&O0ah?W+wF z9@>ZzTfi&`1no3hjTY^pTSG^SZh?=Ow#@DIP-{nHW)+T8qeWM4fNB*ghOr`D&B-mF z4MDtX8!NokvSZI!Sa}27f1y&A0G0pQaWX-)62XB#hUOq@^LYatCK`0>{RP1Xf;JV zU=wj9-5=Reu!AEt^pya!dnlf*#Z>V}t?Am()WLPlb$+ zXc3}xohIV^U<3*=zrsWVzmbRQv+~6i14>>{UYsW0a!0mGvZCmSOM#DszZg7SbZ{l` zLlutf>Ec#XI=aK|Buij-5&-Ei<%j^s!7PD|P&EkqV4nC@%_(o>h_O8@8%PVT=?Svb zqgqLVlf^3`xU(H_XDM)JL$}l^u^1-2Sc%FNV}n%-eLkLU#3^v|w)fjmr-0*ycP=Qe z=8B=NDsYu@HCJ?XQ}ZUH5;k9q&Ei<|R>jiQv^u##BU@AAcK{4ocbh9j_be6||4JPgfbz_i0LfBWph zI;Axk?(&|hy;3Su5#xuv4BH5?d0E_ngh#E#I#ej{t`!t*ezz72i7<1W@D~+>lx?{p zRGGd`bTOJK7;&{#Dd8_8aN4_01Omm!>%=G{{B18_cU9^Ng|DM~q1X-29A{R(vx#sC zA-&^)ja>Z*#S>e8C3yqJc}!WhL0~_ie7r%7rl7O~IOp6sP@V$hjiMihn6Xhz23-{! z#b}hg6p_u}ajaCtLE_J2TSRL~NX?XIUloH;e)Ux`pDWTPP}r_m1o72MY_W(^+HVnF zXnnC*EJNV_Dh@#cw}T1~YBed(Y!}Uyf>%Wocf10L#^Bg7F5WI~2xXWenknY*xT}(3 z#U7)l@{e6$Hnyp|#2mLHp|WM)}t`x*yrjn%ij_>b-RN| z2(HDMT^6En;Z7(NEnEF@r1Np#9L3Z;PW3HMyzisi~bq zbOYBXI7AAPcOBv@@ObrM#EYVZtJ3vd@p)e`Ndg{ncp9_to3bnF6eA8<@@IC~;*K^G z#-%iz=C{(YPpz{lQSU*pjw;LF6R%?>y1oyK3hW#IDPHB`3xo3DE8f~M@k8OQo}(xk z<>Fs--0m291fiyONM9j-;@aT?ZJrIu5@t(pmWA=8GUi2*!;;LS14CM z620}AmJzd)T-}KYWteHNkHyoVV(rHWG(p9wdBTma8h#(a8q*)@K|%(c9S&$zhC|^ z!poiyBgDY1`&kowABC&-dKhlHw{6fgL+gwKK*zu!Uwbj~E8rENKWyB}OA>JHs* zi7=Rnu(N6&PZH|$bZ76Zr(1ewKB!S1x7YRctsCXr>3OiLuw}q)tzqmX@2Co|<9mKfu(hCrink zn>9Z-H8CYMJv}EeIb(X_oW(N}v$8WYXXLQdw5;ASeWTHLMs{NAy!pxL9ol7OrY}mI zo0*Y0H!V4Ra@y3+rglRU5+@Bw7#+#7Q&Tb*q-JZ#oF&5|^jE^a5#C{4Oc*$EZdy)G zTEFEsTx4IMFL#9qlt%Puu9}bUpRaQ*0j9 z4?K_h$<1;j4FFL88NqYL2o-U@8_>VtHt$v2;DSj7R{mjr)KRrdnr+#|r z=>k1%uBT7xX;(eX(9>3WieHjYKLhpj1*GcwL+RBI;xF|RuBXX*>Zzw=^|Xhc&eK!4 z2=y~UPhsZNPnwgh9j+E-5(>Eq)$jP@C#r)~8#RZn5&)DHq!^%J9~^Ys+J<)MB? z>8Vrj=jvtp`}_2nswE6|UHvT8=8wPduUBCIpnf9sG(}In_4Fw{g#}YTIeJR}V*q`g z&=S^3Pv_`qu%6;Yo%-pgr%RmrhuOl-|%F30CH$@&~~!5>bO`YdLy#Y-7qu^dF?u_k*jF?Q?{ zkX>fXbcOLv*D=7q8E^SJV|{*St`q-YZk0DN&}}Bof(tuV%cM4cGPkVzjOE^EMs#JD z88>>kaMsd=^K*EfbID@lJh~ZYeVTDzgtt7KT5^8R8!F|)U48txp@SdxU;Zcua48^= zvyeb8&INL}!VoUTgmS686?d7A=L>z>bC>i;&dMXX;U-enksAU!0&hp)>%~PtA8zQ} zhf9XOTx9j-(wV-Tebbk_SoZeg?$i5oJjdp)xr2aw5H@bZIJ-HFyFEXWGwVq1W*y7f zim{xJ8PD0o@tp5@hO@oTaBiH+na5PlvywQ=P2#Tk)3{;lG|s0_M|nDT8$N@xku$gy zGMl^HOb3zK++}YrXT#@n!}Iew%b(9JhGJyO=Yt*3b5XODyHB)mHpRku&2rA}E$19} zp)6@7uFO|)c5D^rYu0knW*ui8)?sEvTspjg8!9(&(Gq_HJY*y1Nw08L_zJkX8?)cd zd51T-vFrd~4|8$+eGvRlZW#Vg&P^5EP+Wn*4kA-s!FikG+_3XFXNQk-QS~|4_&H|q z6%d@{#>1z$*m?$t&T@9QvITrHJdg_Pb6zlYvkh??$#^P!fz%0dA@pC*bIX7h%TaI~_Z>IX| zFr!jjdgioxv@eNxgp|&r245tcWwu#)Zn2g}o}ZJOI{m5C-1%AT6P})# zJiT#MVj?@Ml;h8%S?+O!muWK=v28+PH%DWdCyvl$Pe7)@y^moO#2m!0h-&Ai<<3pT z-vRqXqKH)sSJ@X5xc0jnV9(uzLjm{ykfIp=v=6JUq1qL-TJ0)B6kBItA~7u^aVD#i zrfV6?1_OHH@3>*CweGw}6gz;5qD^q`Vn!A_Y{*GTPEXEeN2wO5@cpNT@LM4K5w%tS zFrfB0zL`jwm6kp|5ixdD&z?QmZ-%+aU;^T7z2X+Y-+#vi;9EaJ00dfJwYWsFoh}CU z%}(l{k&-z*H8D366xv-DW>M@uH#H|Gd1h+j!nxDgK>*%-g@`zDnJ7MdlCWfE%$`3p zIX9JEbXk;=o|%gH9K=!YDU_8OHSh4+ny%HBtF&21X85UgTC-8is+xn^dhvj1}h-K@ejCy|{8 znDs{j+j`cOCr(?GxNuST?u)y#duXUsnOyvUnm2u>(z7@<(=vl?aRaR-ZVWdyzq!m{ zn_Sb_4cEEz)7f%2!oR^ShwXO5#Mir{XK@jI?_6cXci~I){Y{<`6lG|H{_K{6sn1W& zPG#58XQxciYt-*e_-3LfTWiE$pff@|WOtBgS(L~&qg3;NCZAvA&U4v*l&vZ>2y+`TK^Hb6xK-!>HZfWdyw{&$Y!}5(p`c7jG`vhn%ts(*{ zSF2>G+Wf6c@v#Io0<@N4mQbQUpL9kWEb(|U+NK+$li9t*J)!Sy8^^jcWD~d2lT!7 zPjz|0^&?Gl6Q|8cU&KCXYG7y9P~*+L#JS@t;PqEQja1L6OHFmnz1ox*1(sH$+u;XB zu!41v|A(gP^f!3S%+cuH=HZl>T^>3+UblDA43LRFz%gGi=J=yhU(TOqa_hvDy z1`yYa3_NiGdw}dY8?miwD;Q=WEB8usombnMgQwdF|Gl?0{D+!HvG-70T}IMSwvr?( zJuM?Ohkf2WgPlano(E8M_H}b6lCw0^b)ZxEuF}&qIKsN)cXD()S8+DSEr4>+*6yXCEpW5rczl0JYb^6nq8i=lT$LMk@~+5 zh=b~kzj=>lf94Kh+|+3Hr#)%*-+Jn^|H2cq|B>*%sKPr4e$NLgl@Ie^m6wH>FoUi0 z0>%RbvG-N#Q}!{@GAlJ@4vv=~p}DNg%Q>sJy&&@JOv@Bj-Eulx>q%0c$o6|SFzyr2 zH1?aP+U>q)J^%8&a@YnhI5&NYcCYyvDHirVhOT~D)vuHEee-+hUrq{^AZ1o!jz*r{ z8&S!d)OzMkYSn6wqxRlgq?1@X{nU$n>HSFG9{^Q!kktN?Hz3opvQjf=Z;)#;hYXczZtT+JTx{>6p@DhC={{up4c|=;* z24d06sd;O8gQV|8?XhEzNcw@mNBUL(>fAAs^y7hzCA}z+Bt3^+M*Ago=$(6Ch7Tsnxy|8h`${cM3Vk)064xs2r^bl4&lT{S}wx(M7aINHP zITw_ZI3o+u^v|f=dyYW&paXfV)xlA$Fc_4mwN-j;F=}56hE&X)nVpz5M+?q324ncd zjKqg3_o8nN`eM=MppCs9tnLihIn)_RXcRejWaGk7MBtf%MXvb(`)8ELu9 z8Zwt{56Mn`P9-r_jlz$G=;rA&!dMDih92y^PZawoC^;<~r{syOGNj&KC2G!eqa_ri zE+@DA{&xDV-bm3F;*eap+T)>G%=aaL4&oOU!BRVY7j2{OGn*TM{-J}`0@S*Jnm4JK z5Ld2mg&=4X&aI}UvNNGGve_@8_0iI=mQeWJx==Nye6sBjJ#00eA==SWx-`vjfJ{-oNS_|tS$`!#C6Z@~UVn1=mg7;}YfhCpb9?+DY< z(lBSt^=6nROj`Y+u$=kR>Y?8Yvp`$3=CEJGm_gm}C4xU+w3?M171N9T&?;?a2DKK3 z%}Hcd6VzCZ*iV4J>Mrq$Nspg?L)#uTz+Zu-fex~j;n}Pp9P?CHVFvzamJYfloPvD} zLkzxUn${~?&zAst&3`TA=fE|*w~R&?qiAER@=7Ul4K}^tdJE#5*tER zQ7-Fu&gcD_$Ns+_|Htol9*^lU&vV}Ae9q@GpUe4tnmKOGuc&{wrimZ2W{c@0i>_cz z3wj|Di-k|U=`17BdXBKwIzqU_ZVoOHZm}3uG4FGLaL+oFjZo0&P5|pF8zuO_id&Ac z2`YugTt3|*_H9S}5<=`A8v+py*esaMwmIRb4U7Cm>=gSe=<#{qZX+%NwGG=7vh^Pn zAmrMxPpVL2!#<(HMOH(d&1>w`@V|BJHA@*J=A{EesM;ZN=UAep}WH z+Sb^jVdo*oS+H&p`z=?8t-!4L9W7&~ySd6gV4mWh! zb^1?sY>M7&D6wT6`@`;Nu!)G#&#_K_1XMj#~0zhA6C@bVE^yuP?hl@Lpoe}RU&@; z*?1Y>dU>y7gd%B>u)&HAKlNs7Ai*Y#-J!l}qunX~yYp$biHPCb6T7rsI42->$wJ|S zP2@shhhjnKk^rGz5hc{yvVo_nKI}TjE;c-x-P9I}>}UlB2BXt^Dr718c?Jdg<@%X=8HY2ab`v#{@M`v-h%RZ8GD(f3TC!8WLRzhpty`npsQXdo zlB{1P2`M+I(^bDya7YCCHSB}?sJiSX9*>`b+n)BY74E}&!YejX{l#$6 zPvjk<`Te%dlu>~Ic^dh()?3N{!0ZPG#AL*7W%CYr>>@kEjeE)C;J|(4P}nn@9K+m= z-7b-64pT-7&tT3uO6I>l!>u_%E`m)9$yZ?~xE2nC-!iifN`%uCuWLyT)Q~$eD|vwY z3}rYWpyDifG#p<-p2o~OB$SeaQ632Y0LQ@_5nluEfIZGp{UerwQtY7`8AS*X&Qri2 za3Fl2nRi$Nze2hE0>$gFd+WS|YPbU|lu^00wjBPZ8(aUpg8U){j6r|~p293Hp-WUA zq-_9>f`!Xez5$MhcWTSasrtuEG!XbFxmsJ{F8LW8SWW&1@$!3QnVgn@=04dBmOmiN;ds$XLFmge#C2Rl z0V82`E!mG*+(sUeXEXEoczB++{0WsWf&>2|D`8DNc@s0QANY)!O<&m0GWY}nUoo(h zFUJHMMGBYUz}Ms&SZE?Q!ye6K-5yk54R>G`XYehR+o0Uz9Uk~_(NDe^2pQu=>3?|AJ7c4fsF-e=zeN*9badMl~!*$gf~EEbEDQ zDV6txqjbpw;YN5Yv$(|d*#4KN>B!KqM+tZeh2{F>XxIZzW)>Hz0hRBCD`ez+Sk;Dn z0d_JZ-y#c1N@P4hhP^ojyn$VMk&SwZ6BM$o$yRU$dnAD;XL!FOc_iG@pZp!{H;^0! zD>dx71)f$Tqu!024ztG?#PS31&SB(YINp@;(Rw0TY9-E)QfOe$ zJn&>r8A4_N*#X`eO7@2H=95EUk7)8r*mDUv1-4jD-U&xymFJ3PpTF|e6mSs%E^Enm zVgF?ED{c7(@@Kf3Jv+fu``)yQ@>0pxa7zaH8#sOk*^`@hrYpPH=z}(B`#NsRtnX~ z@Y_oPPvFe`aDseZ+W`BTZl0=Ot8?TAxb!l)Z6E4z18fhQv+)A)_%{g|?mUB~ zFgOHO!zpkXoCn|I))fT#O{)I{_JCi(fv~bc7-3o;joN7>cp2ob{)k#z{yX@ zzFI#eFM<6U*mwN##D2z3Y#_OTyb-R4x516@Vc6#d#h-+8;PbHQODbnSKqs~z1;2+Y zl*s7hKmks#sDdl3f+xX^us`h6NbyVI9C!z8`kKm1;3&8rRyO`k0c{T z-3-{2Jfz|Tc@(?NE=1j-cvCp%E}308v2wosA;Sp)71b0l0&cuVo(PBIQ}8{kxKHKt zU^%=LR-yg1a3<>WVFeTMWQ5HrPy7PMgdL1(Tto^z*n4g(-V>Gr;UZ5mKP}+pD&BLJ zUckw0-SXtb`o+ur*dCOp^>7Z`AMjMgtmFY@UX;;`Ejezr8#x@V8cNQEJ;syS?;VKo z4TH!-*y85(o7h2$Cm*;xP^2&y_6{MhW;Z#-3O>PD>rscQPf~d|*xZ}SUG>=d=RHnC1CtSu_K7MifNS_k0!!=R zGB^t^@~83wcqbdh<>@l)*PdJlH{pz{Nr?<^oWr%zrw$e19IzKGV}r9i4Tg&f$&+EH zYH}D{hxV4iaaaPIU=^%XBcm%$GLOUY$EiVfuU}k36{v6vmg6LoKaxxzi?1rcqpkfc}@-!5#(joh5E1J{T1%(_CG3yW>{Qqs_4%VB;v$FH(XD z;shEo0ewSs0OcKEIXc)K_QJ)j6RhC(byym%t*^cQpMVTCb}X~t0yqlR!0~W3--uXB zhXW^&b71x}onkrra$Io+R_q{Gz)A%^$F<0as-l4RaL!qBJ0ohK90Lwr;3f<(^o4gi zQv7Im3I-fP;H2(UzLKmIs?fs>1eDIAfMakx%Fn|Z_#Rx}nd0BVE|z3dW9o1N;%(px z{?8vQ4G_(?|2jEkj6uMD46*pbMHnH8gjJYe0^EWIGvPc;@CaOmZJ-dYbff8&b1T{V zOjM{wfaypIc&4q;h5Qj#U=faD#$;3^wmfJ_}dka=jMTz-`)52S0YAcn8?SmOQ#0j{lx!lrcjafH9mfIGisg zmX^b&%gL#58HR9jVE+gzzX%6ntA7N$@2B$Cc5MBdu=g?qv^ODp!M1Q(5LFlfyI@et zAC5(Q4D1v@@d<2N$4me@ZsQ|XZ1h2qpXs}M(04B(OqeZM=fE|lI zJI&=Yi3s{bL1#Gp6I;0$kjQC*6@PdoN$ur?dG%!!=*;Kwt>+R%pI0wUYhv5}Q zw2BMhvTsByg=@$##TZR1?BA0rv@@eQ>MAEY!ZLU&?1}iLa0uESl z{{k|~YiSPZ;kXv^Kd}8vvb;TYNFg>L2qWMSl+T3&QJxCNq5L4M=A&l(_QK#JWN*0sEjb)cMtdu@<&`>g{7*xM`EXi9hhg_g z`g+fOB%m{W(+aCq(mPZ>|;o^bqF9RI&Zh6N_D7_RiC3W?hCjWkD@ zu+IqcF<6#DJ_A<`CEtWoFoVzFsNp#Nw<1G6k|t>Q70p2@Ds+dlVHda>6Br8{qXU6( z&JgOrBG?LJ#~a{}N}NLNK}I>wQVZa0oC98gldwo@VNWcv4{!=jGL62b8Hk51;WXF* zR>t{?+mJ948L_Z091e%V)$mf-Z!*FKVdEh30N8&!*#j1KlD)O@Gssg!v&Q57C}S1^Trj~oa49M*hP$Ry zyb@0Sj{GBR45!0BsJ|OF-9z!Y-2A}Sf(8o_5Veg0N?>YpFtg>Ae zIR00!qzM)vz#@cP3MXL>ZoqldsJs?dFC)Ly*2fZRfg7+yB%Nppc&(*)vrcSX^TTCG zB4zYNfTlOu6ZQ`z`@%_ZI5)c*l3~y(8s*75D1H^}VNKo&x1jw4N@O%4pcJ-WNEPnF zc`@V`*n9)|tIjk7fuUp@W;Q>x*I`)$zVPTTJjw5ijCo%;`U@}n!mGb9`>MubXgamvUN#AagG3>5Xl~H>`+Asg&UFk+i z5B@~({DmO_&aN(T>?H&Qe36sEzT~z;e)xUqa>I;$B~l9m$KZvLA&&hr9@a~Hbj9TU zzu%;i(ONI{`#(G6^;BwOfG<cCCE(i$p5KlfH95d{gm?a)r_!Oi88t7Y z1NC3=TW-eedrEqHNDi{+iYP@!1O>Cl*j!v)T;?u_a12?>GK9me#-#_Url%Bdt?41} zsn=%kk&>gjD(j`xw3z~zFTZ`*o2?c%eU>aa_F^NSaaaoxkneB zip+LQIx{4#SK8G5rI&|T|NZ8|mHaVt`>pC8Rc^mzlk7k*m8{~0W!k&8OHX&KOI&|t z`1_xKF`Q)7LFZxj-{zK2cs^#%`G@Xixmo+Y+;tl^Je`qcR&V%n&?5Vm+&P<8O)U#H zzB+SjeyeirsN)0wOrFrC?wI4u4=&+)!GaCPAG=A4OP3d`>v zESPOn>Rd$?F%k*-mcWFnt$Ic^pKJB@++N}Jy6awN-RG=BKX4}gCCSt zzCYlqUy<`UUAlYR`=uQ|M(;L@sUnhSjtQc1x~5q@K3EqTp4+op*}$FMJ-UyLmV+kxfb+_O!M&{;f`ke1OIx zXK%;UtGC9r8Ya3~3P$^al+OF@PFQOi=LD7Ib)6i$;_il+8^z-{JJhuXZHO;X&zpAB zH(vi)*#V71!NHD~&d%9*>+jE-|Lp5lxi8MW;hf&jyZ`8sTX3yx-Rx}FE>@SvCnR({ znUuKYrygUjjj8<8q-g9|hlKw7-TMW&ZLT;rGj&7Mx-03|RwnLnRSpVovoA=uTzT_T z>h;Cb>eu+2JY1VU!}QLFja5DMPRU*`f2ex##Mq?aME-Jv{ws@%zB>5p?D}`tT>ptl zHhHpQj^)~7MMTcWy?Sp3U3xWH5@ES=j%h<&#o_v`!+yE&ETw4srPM6O$H&Q%Fy!b7Ja)-voy#R3X9Zk{%=RklXO@#Ldc&r(Xl+KxqX3RSnm7;|C}x7 zL+3iy=&VZ%-|BEf5*<8a-}&9|!*j$!;4LJegj*Zdzow z`Zi;hdqnq(SoQU(im~q=#OQltkrWS=-#VB~sUmu8MGz&;{Ek{P5d?_;I(L zdMhV)S@y8JY~teu=ViWX!?wkTU;g@bqHE|#|B;hVrrix5UOnQ|n&C$eh26d#XBrs# z@tfAsqg>yYw!doUfA@Tsy~7P=sAc_{2EM46|J%9e4aJtbA4%H9^%=5srsM36$DU3f z;q$dwpVZ1;$L?9pPwX>Oy5YwC>W{t^i_ShaGH`M36k?}b^Z2K-?N5dcuo&C+&bL*A zt&SbNm2@}y`0}EIs-HId4vH#`xqYSEASYSNcOg^X?7A7N^v=B+zivgp!>4~-tavzg zlR;+REk3;$^*C?;^N^pCXXUvWn@+$ zy4Z8Yhq)7?(v4D{Cm$N|V%*rT_dI_1ve%!34R-DPb$4~%8>hi5>wlYZI!GfcT=%Mu{$A%E={1>6!>_f!dF;o}Nw&)GHheWTyLnw&Zo~0D&wrGaM&w)N z7VY!eoO@8$O*Qk)@ljc+-=Ff_yX{!<&zL59Kg%7; z-j|Gf@0VFMD(ZyZoUXo`PK9qjf1__=lkTVUd%j-fHs5}JkFM$WhRsc#J^oj{yW?|D pEjhZq#&E3hP4{k=J>;9lO#beas{HHs`F1khmc+l_eZn#Ce*nj3osj?l diff --git a/crypto/src/main/resources/lib/aarch64/libckzg4844jni.so b/crypto/src/main/resources/lib/aarch64/libckzg4844jni.so index ca6464068a44dbda7d72d9855b9445c3caa355a3..0bc9409d8bead4d7e8c92edc2cafe6589d3d7009 100644 GIT binary patch delta 53302 zcmaHU3tUvy_W#*u4lp1n%J39rP*lVhK0^Z;gcRS1sAv@9t1!(-u`IpKC{&hIOhayO zc@xd<#Yu}2!@5@ZsB1SXOf&Dz3XqHx3ltR+nE!X3vyT$L`}vc5{29j(5rBNihCOFAo31IizsCJ2?)P!WI)705``wMw5x9fE8R7Kv2!1#m6kRKE zm*QTHyFc!aaYx{e!u`3N(-fP;N_)aWhhl^)FfeVN!u5WY#*tb);>4Lu)*vC28SiuH4Ym7tsB#Ass;6#B_ zkuOPgnCd{qd4~BrGrj%UU~qz+cJE9!#`z!bxooU+n9m><=bY#BY@`__=!y~&x@nKn zv%oUk{hgaU1DwWgA@T&~?Axs$o8(ODHpN-Z6z7(1{gmahyvzA^w|FI8F7kK&)~#=( zq$tv(L+xg1Xu&weKiM})+GUm{sq$w5CGC6y83m8oGk&jW| zkT2;zLVZLRWr)E&)cLJ%cG6^G;hKV*8cV)UMw)?}M(=Fgb8u5nlBdu}&<#!FXVHOm ze);lXy>qEg`iPbzRWf&?={b^GZ=;SU`%o|$gqy-e=Sz3BA%Z_tAh|pRoe{Xl;HF?g z7lnd2+!Mqz4LWily%%Ya(-5IvMj&w>@Q-w!^S3CD^^yN}hV;x*_B~(H-u};blW8QYW$osjbEpxN>YbW~AMOhR*Lkg&8Xm#7Nkcbi3H74D=c0mwceR|kg8v!<9|^Kw(D)64f4HZ{Z}_*y zj~4ut5RG5ZsPV0WpCjZSre2e5S^%fC?*p^~Ro`d@iba7}dT9L0N{xSB@c-ta@ugU; z0cnDNS}3}&PRkENs@Gy+p_cxdg)Eee`lail;$^4*T=5f_O{v9}LmK~_CP(_OXj#b( zjekP$zeUie{KqeAe6!%E;F0*bV)D_ua+(44Q$hwgD=t04<%<@i3RA}kL9(cz@n@|9 z=%HS5Xqj5UEsgIlmH`2xVJA;&{9>&dDPG8t>Sb!b7C#6*grKOO{#?NhJW>UvlQap! z;?go$lK8&!G=8a8ObRz?eDfKNq0fPBUK+nZ$j?#jkBWzj0v1sKkLopB@TG4xL0ZpA z(k4-HF@+RdDI(zvjVma$Pt2aW7ZW+7-D#S9csDl|cQ zi@y*pPQ71~a9B&0mWjT!{;Dy~i3(;3g*K|gOj{~Y73VPTllRW8&d zY!M05L;*=Sk)HpY7?$Q^TE%)FKO`CuwO*5B5(-sz*DAJutmU_>4Tk@v3R4#fQ!i5! zB(`Am4v#f{H}`Y5rOTg+ie$!T(;!kELk?SFzxy&?vLP6b-@~b!S;6 z1f_@&t2?7b_=-{Zif)NLB2L&p)D+T(5^1vaYH zNYZ*?y0WpFhB<=&iir8XBIchH{0>n;{7fysKH0o2y38#4-YW8k`k?%eDy1>G|KRP8<=1D|p~Bhs*u0m@b?`u<@d$oifpXp9iF zN?5}B(VzL7#4y|UxF%q|$nO@z^+cE9`ZkJ_rCS2E{PmhRn{-uZY7vu)T?pzYEK%Q} z<%|;i!@}E7cJcPtMgE50wEX(Cdqgy>N?52($ZdOE}j3h@Cn~8lT)4;P2sd|#Wh3yKX$Id($%$^92!mP{F^6QU=fi{H{C%|f&F`} zz((Qi)ATuFu~tEy;OB~XV5!pb>s^*FED<6snj#eXz=->r zYt`)ri}5#Kv{({-qYL^QZ}C~Jf@UqdbT1ys5@&j9J`p8ac1(n1 zTa}2((V{?Kkzf>ksRx!EVF^V99Nj`sqbXEDiC8!2E1Xu*$0c2MJY$6X6m7L_lTt;+ z{}F;DQL$dZ5fN~)^&RZuA9EJ-1=fdeqh0}!#{t@b8TK}hrwOEcw z*eAxZQ8-to;Qs_v`;v~jaiwZqEqx_goFRNAPED1hzX@lo?lKp=EflgtA=UqN(|L

    U^vtIBE1;6TNO(C=34;5Wt6+U*4qVpGMWqC3|* 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 T&2%5%=uAs}d5wE$qciE>i-9I1 delta 54719 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

    K0rL8 zz2-MKPIw2?=uL{Eh^Vw8@RZRZX_)(Klw+i|EE|1lK}_vb^He>C7b^8Um9?KT(-dZ& z)cqxouW5gMpW5{EWf}YHC)(5NpUT{S-eBB+zRbG6-q#nj&;F%kW|W~N1|1jv3$p67 zC>m?uYMg0pDf!*|X5+m$ zZzL?jo9q_vo5#@u$p?*m%CKLKt4)`J(6B!CblE3!zvp?j-@wqYr{w*Oh{*V)V!z2? z+DtE`uTPl;6BfdhGhxyhdjndRPsfo)0Z!44{2wb>cx3(ma6=kdnj2QDZkVz3f4Jc# zG+lSYhe^3`QF{OLBIyCNw$R410z1>CeAXIvZ?8>AQb#vtfR4vMSI()k@Bx~Izh1+7 zroEDg;+i-L*P}@!o;6kDz!lH5OrikvAqKU66oiF=I0}**86Woui|_dtyc0nnOrm|T zj&y=VuJ=qmf94T3iatpD&m*jFSLJp!+F+76Tg!$=WMa)r-_udc^?`ca$dezzhtu=c zVy`fTZ(NH>EFZ=7R(}Wj2CBFT@4FKV!rdp)Q<_2bQzxuFsMn62SSw37u<-c8mgvP_ z@X-Lhg(*OKReWEEs$3|Q)@iknp($94Cr9uMC*$TvS-kBi!w{BXYXfYq!1g{EzD9f> zBsp>$~yttmAUvUR5<>i-3MoTyDlFyb1bK$W|?eH9qET2c>-k9tACWABKZ1 zw;$Gpzo4%d*OfH;VDaw2-$OjgVr`3{gR|(@QFs%LP&x?qLtP!?l^wF^tT__x8)JyL zNMmF8MLHOiaK>xiOvkI!NUy%u{dPPL$BSZG7H*<1ITUGs0@8kmhdk2eJ;X5&bnuc{ z?j;ajk3$;WZK9AFlR*=?%vlVM2~aM5)S{kLpn*^0!;5=DY5!h2wV+cYmeGWT z@cxZh?i_~#=wOI@*0D%+Rn>77^(JZ~pFgM~y}ud<^^b)avSE%ajJiyG#lmsj}pbyTV+az;xnkMNfDtSmg5Sg6zj<5|SkKAbx?u+a1n zN&;^PG^p^3t zb3FJl)-(LCNV6M|hAwGo5t}#ijK^57@U=*)#crbnJ=BuIH!tRoKE`6BCnCwkq+v9~ z={ppC?7r>cZ#>3EvcdfFV=T=dR#b<|?h*X%$5}>jDT--hF~a?_hi`hE4Z|PXy!|+v z75$2^$Yd<$8~r#Eu8 ziFFU}iR8#$a8*M{6Mfr73+PFF&?XjZJ_n)XlV??oaDT6&Sv}a}6`NQNdxD?b#6kzz zkw9H`kz0^W(W3R>(W0DO1uLG)xKll_r=utw>CWTfWy}%?PCaTS&RCvN#u7q)?%|*h zn6zb96kdrvEV#QnaQpGSC{20k4WOPkmVZ;mh7b7i2ldlTHDZ%%(;+mysGx}bfZF~r zcZrJO?)!OqIm@E}{(L#UDE{^b{(d=&U?%=$IqTP(RC;4z_rZ2KTn!9xE%z}di-M}A>F)e`(NvoJ_M z{42X0P9pxM$R>XjJrFGKMA5u1@*qDH?aSVCiDLcpp?;kRWc4eD{D?A%LZ!3 z>4EYSkUqMm=x+HTB`;y5RCOMk&FHN?oRsPrl>b`8l?Rjyj~h=>6a- zm7()x+KSLI%!}T$S3g1;x1`Fs*0$Rc=+scl)qI;rE3hz>#PRNJ9@Vbp`xU&JeW~&a zgVGfwx1`CDk^fBne>dqp@OWOD9H!I|Rgxyp>HqWXd{i;LBa3v`-{#TK*DCp*N?d_t z0vgdwj#A4|8}Z&4oO;?bel)@Y8}YA z&7)3fQnGIIs0CWS(ctmYF>+2$zdxnoa}ebCVYpQF<0vdbRcmTe>aoc?4gSx=b-pI4 z-r(#09DLq7Mo!E2hqQ*f^&Ipi4EcfLK7t%~{7I8obDMXk{cn(@4OaP7Lv_4~RiT+cxpLLsuFLu!$I-kK>wd$uanly5Wb2x|f;QlE~YMCVR zYi-tAk#n0z*3)Xw0j6kG>LZx{J$tQ52*$3i&V`!sXI~bx51-PrMH84rMIP!jkU0` z_%@IB7n*(NgU65DBNrjL%{p__9)WFpRYT4 zD1Xi@$MC;SkgqC(k%@1gC`YFC19kcKaMf&HZwPWSxA-M=NL7?uaK=UgTc$b7JwaGyHd+SRWJU6n!9TL)iIT|Wl*&k}r+VBg^ z-ZBJ|?U1ZA5#`E->3$*V2=VHPI+H8!u^k5W<4fcAQr)yHs>g7`ccShGz;9Tfd!_E@ zihCjWzhYmlwUxY*LPW58F8G&kj|&Pwq}CvJA^4YscazsBIAa1OedIz(bsTPLGs z6OfC?5S0b0CUvs>s!1*zU2}GZ{J9U!ng{2|y@55~&5?V^0k!zyf<2f4eZVmk$@!RR zN7u|OmczRERQ?MKk(w3DI{6`a*XFy z`DZNhm2Qyd7?fXnBK3q#KCK)is@g8sDw~KZ-3V$bsG5{b@~cLgcMa(C1kc{leUvu-&AQy`<*ldMtM$-hPVG$h=|h z-Plr5+Nmdb&jvZVrnEtRLRJ2?3-V8@@_)hPKB;nnXM9UPKPfC0KSw|}nxyjZqv&Bc z*{aM$`o#|EIuE~D6xO!>J)DL~j%(A{UMKSMwBO{3tddv!CdUG*f0MJYD7y5U{B(f) zZRS&t{2|vo@`u6Ca7bw|aEC#OtT}B^_AqYuQSP!myzJpsixw8mU$VNWbkQUBz$^`=#EMK~G`LclzuU=BRDtUpFRWxz-_@ex=1r{o>a?zSaD_70KkGw2e zx%A=H^HwiezASOg@+Au`N&PLWmaJP;v|7i$()}xo7CrRvywb$pE0&i&S_G-fmoAyt zrS#q<_w~2*9+zJ&gKO#f)g5}Frt+r&AE}wtr z3F*@otzNxk+2U1}q`p$t*xcM{MR{ZMi^dif6lLa4$+Qfxpld}-m#kWaOqS8fXakmaQH(gmkENyHiIcTwYv!tVs#wc_zigXPT5a{HH=J ze62~bYQM~cOjgQ?%cA}(NyP#~1m+1$5r_|M)C+IA)GJ3|qQDY?c*Ut+g#uFruGR3) ze;FWKBqRu2C@@T5fxsaGR|~|uTJ_2m*k53&K>fFt=7{Gsfg4mr|FK_JuS|jQ0_O|F zXGZFkFL1EHl>+?*P7s(R@BxAN;zYe>3mhqM9Ug=?W{Bru z0@nz{4~VJPWPy0`t6s|l_7sQ%ZuJ^1@NuAOeP2*eLHsh9o(OZcl0^?Fp)j{^qn8Y>X*$JJ|*K>WF#dQBHNRN%t`@rP*YHA&zA zflCGI|IMrW#B;j9$F%TLvuecS2{LnG&$Y4xrKrk({KcmSAy7!y|C>Mag|IZ}UW_0q2l zS}wGDuK*8RYW1eU0gwF#!NAt5Xb5oO4Kx5lGp(i7n*+4BwR)?74N{xe1MH7)V@)vI zT3`zB7_bl+BDZ<%z&XHbU^TD~*bHn4g*jS5;O`%#A%-@u1;M8rm;<~7Tn#Kx+Pp5{ z7T|H<5F_#f?Z8Ah>Lp+yaENc4w;Z?)cnD}Rp<%#6ApNIwYJn+0#jnjf2e=kkfx}YC z1>ykkH1IUA)W6Le2>T}lLojd%uoSouXa{ZqRsl}|tAYJP+Ps&5Rlpd8-_`iVpFCh- zH{=Ief%J3gX`yZ2MqpuBn>PVNv@*QSYg-87R0IS8PeiqOuLBo$Z}SeJC>GP^Ede(7 zfB;~BOPlu!aC*mGV4JrVSTPuy zz|dSV4CR5BMzqF1Ogj@3xOx*!bHHp zr7$U_FN0|?(Uojy^A-d9Ki1~01lHOfZ}Xl4VMjw0M8V^mpmJbs87cr;%b@{aBT< zQTYTa0_Hr4ihwCk!8w7oPow9EA(kz0KA`J)^c0xqZ1bjJir%vo4F{g!ZQf(RE!$xV zgl${HPV^AO!dKe7hk=#V@KVfZ#jnA(z`B26xB&OO4%;HiCAa$xOYj0&LX2uwuJz{mmU*!xHyfbs7FQ2|DEEqV$x{Sz%qM#g`^ z`+=5^&=6q4Cm2q^+)vTdfl%!i&=hdtS8z^X!#5C|f^uge4`@9HrvqBfL$ia>0bqY% zc>^j2uJ{QW9%O^_TtLgfuw2CWAB>g*^MK0bHtz;t!mk(|K+A8iCGZMRxf}VeKvTfn zCfF2McNI1VTCYLHz>pg-0nl>`8XE%JH>1J83NJJbv`FpV1{;W45P?IXa(oDYeX?Z1 zpDC08JxaTGA5ijb_qGDdP3>OmFsRtC-Mbnn1+;q)1MNXb2bOk0`fxn!cwJwQ)fyVrICgtd3OH)aF`CANF#02d~=d#mYrXuB7O znUZA$1dl{R)7rfiz{WA{-qS!+M!Po>Gh1<1ySEr9Ww(1>z{;`h-bP?;PP^BV2Kf`) zy(+>2T75cAK}Hh#3$F+*8=@?LQh`dM{cCv=p^_bH_k+^B@>ly`bHD z9cW$B?k%+)=!{fVB(YQ-nGCw-~r$X+f&F0;tD>rP8bIPPon~$0?Y-PfW^QN;A)@+ zSOH7`ZU-g;4*;#eI$$2K0ay%dCjK*!J09gWw|nz|Ia^>_pdEMwXmf!$1ELn#3OoS} z$$`@VQ-D{1*+A*pc5flj1S|yx0_{K-a37^V*X}(9v;eOID}gchfd4$o0~KH)&;%?6 z76U8qq45vm5E!+w=mItX_W+xL z)xf}s@Oq#HSPQfQ>wpD753pn+#((V#?cQx*xSZ|Y0pk)#U$5!|NuozeZtOHisKzKmx0X6^+0~>)S zfR}(Cpv0k4paL{ah6;f(KnpMpSPU!%mI7A;%eO(Jz%9Vzz*^uLptKz(m;yP#QlJTF zvx5i(Q3Y%Oo&sJ1HUcd#!zX}NU`QT%2uuMU1Lgsx9T?X@1y~Nu2JQh?0FMEW0ULnF zfz7}Zz`&_!unU?1+Fcm`B_J%jpbDUMH^wV)A+Uimyn=X;57X>H&w#bS3Sb>@J8{jJ@*0jK~gfhOP{VBp^{{ttr)0pkR)0(c!LRYS!E zz`alzp&J?k+V`U;^!z#^<#bdCTmeh~mIJN8ZNO~cK43Ah7Pt_23TOv50?UD|z)Lm| zAu}N04X76AIfO_D%y|@JJ4DK zA0R%knfSoKLJVu51!yxJhL?k|0CRw~z*1oG+fWrf0}lZ`z*9i!9cTz>0fx;&zIQRK zfY$dg=>T(qF5&|Z0ZW0$fp*{-;1=K&U^P&gjq!gBMC5EZAFw~r^gaXv6MzN4a$pIt z5x4~y_yH;aCISxuw*XH8rCRh5SOSc^7peuO0i_S&tiV9vLZAh>7T6!S8ffp8s1Cm)JXqwCOhb!?(2_Ln3Q;C2*16KlWEAEny_>SR9Z@KCt{%^w7AMsxa%Rk}~sY;UU`iN(yDud;ikNFzH z+K;)L_{|^luTqt{fu0lC{>c!O9lV0?vMN3JeIt~Ka?WSmJwh2Nmw(280{ZMbiCrB( zIZElxCyrF&cf6hWX+N}jQ;FY$&mX1q3`#`}hYaY( zxmIrpzc51S5t}Lp#vWkUVt#Sz%dfsZ{loWaf36@?;rUkYY0gF|@%$g7lqlm61-il? zK8#W_`GN6@Vzh(N@C%PlQ!@QY5hw86dYM0vroYMl*L}!EE(!}dWE4_^?Kvy^M;4$F4K%Z&iqsM@M0<`5Se_#x00Cdh({sPf4CiL_w ze~0qqfOcKwKM_s;-Oanm?+kc}9eDU&OS%GHj^J5=Rp2GuYV{WK{h3M>pPZo>jHuK#XXk!}am=^vO_`ao}%UfD`_pwS` z7&+WFFt*?{p_MAm4zA-@MkwJuaIPO)_b0!TDDx>~&i$P)%T$ILL#Wn2xI0rB*)0!r zLTjrxo2fz$utJ`mp+xozL|gHoyDv2s8K{p{R04+=&DyZKBJ+nPD6u}s4|3{AB{YZz zG5#t-AO%|j5m*?1D@#fCD*#=I(~o8<8XNB~ zFYH+88&OIfPTP<*+rX2vm674a5OW64Lwv9&*4pM`>X`2-=LE*O*ql3^`A!w$Z>U78 zT|95362|MsDT==}2qVfD8!v_bFiuI}zh^7a#tJYG2k_{zO79RlTB;4eP7UK2I!D>D zN-w5~z^f`;!7xfNwrZL_?W`cMht(-pDSt6;HSxe5!7qo%t%0%Ni`GD|G~7~A&fW!^ zVv@0fe>+x*?uswOq$A*M(<-Y}d()Fu@yZEGjNd+_nnJM`-nsEfss1b=8esw%}}ZUPPn7=M4f62pHTrI=(Hzj!=WF$bsx z4kJg*UHqN#$~dFa6#?xoZp=}72d99}>wUY^BXiK{Lh!bLcSTd6%b=PtXe|t7$PO^9 zRxS2?juLLHM$Z0;+zm;7r$E;xLhblw&Q=?sOI^?vIX!bi)p-FYk5_2ALIf zb6=hbI-J~fHJ(r7_@_>*b%izxdTc{&9R$%JAW4UiyQDvVpCmPawhZ9E-h+W<355$L z^P~x&=YTFq;rCBa#)Z(iT>}n}bm`QkaDEcQ#-E)33X)5Q@ZTpWN%_!}v^@-7I22wC znywh!2f*77-X&sW1c$sV?_dx4|L}dVlo3E>>X2SK3u*G*J<8cpGd z0jYe)L}j+I1a#F1-aZk{-v(M4$&+(I9|yf*B%e!kGw762{JC6Zv@tCLioS<`4%*KS zItIs6iQJJ3XBj<7iSRoHo`e&oWBlYKM7uSUlwjj^@Tv;=Gm}t0)r_{x;-5}}+!D~M zXY=++%3R|K(1rK$`IDh8QzZO#F5fX(iT6tZT{;)17JSfLC7Pd~taLRl1kW><|2`Q} zaU1A@BAz^j+6?+k5uZB+GL$HIb1{E$it@Oz0(8}U-ZM{m#uyomxp5(XEe~y(1KPEi zUnSZFI`Bb0Y%1sm&@s#SI-(Q1qd&{}`$U(5-mr?x`JfMgu3W>%xZgz5crZT~J z1avXy`7@D6ibGv5@~uQ?gHGGQza_c?v}GsnSqSdBAuHbjm;Yrdi5hV?r;4sRR6-S;$`kI_wSJJ_~)R1ij)7O((UWEeH9G+0cmz z!SUE3zGF7>=Yp=S;q|j2ryO+iVIF<2lH_*?bj8~^R^z+o;iX~my-J9m2R!>bI1$r$ zTfj30-UZ)#m+wXyV;X4d5&rqT&4Tv9F@J;j zIiQF9m;Z1d`o046zW;LLT+rJZU| zzXx>M=X_)l@}CBM{Bypn2>h77=-(;+2GPZ!H+;o!61@j>!f8IT7@_zI=#=mHlf{r} zO+p;-@UMy?XEo>(9_~L6`45B6Yv7aTA&;pa$~N*H^U%%|(192Dzlm=L9dnsS%vVMl zYl;4i&zKMSfryoduJhgVl?lFdmTLc_jgMNOr1O*oisHKmoYU$Y~O3*8!dGE!@ zZyE%5?7?>|R(2Z?fIbn+$CV(DGWh>#>kQzdDz5!MguNkP!~_sRKv*$g)EELHq!wkt z06{|u7;B0M3ol@RAS*-&6y3$9zSKrv)U-ENw5z6Vo zwy~x*rP1=9RFVFF=bqol=6;;dC)wHWoO5R8%$b?H_ujn=`3v3eNxmHU){EQ|m5}d7 z{z$I7X*1k6?h5P_m$^@EMmyIapK-bS(Pp&&0P>NU?(8jS!vON7v)sG4$n=$L50t z!O}b_l`ExOGOGYfOVSNOz6LD)8h7+IY$LcO&E#I=&fXT7o8N8zy`qr zWSE6$Hs}WLtjbQm3Q=B!^9^DMNh%D2briYzci@Os zPIe>z738zSULL0cJV}+U20Q4xx1-@1Uq)CIxj(!e!(WJe&SLROc51oiPY918U$xjBzaua$zXkb&I0J9( zNn1L=nv+-%tQ)LxvAbypLg^&(U5h1@rle-gNBxW4XAxFTq2%3#w*@X9CBCY}+i^=I zs&L?ge9;m&e<$)?$Tu!=*CHQ1B`QmXR-b+~HcKB1f_3_sTogD6mh7@(vgGcp0c-Z@ zM!*`E_@YQIF4UsIpGQ$MKn*mLqo^IMI?0;!^axmFiMyd1y*rJ3aH;#C7_ zA@NjN2&;~dO$N*Hu>!DhK2`)4088#vIhk#&)KLX?ve-9%F~B}`(WoGV;&^|&*qysO zFeSSa`BO>WLfn}iFm&X$-GQs}vlb$zQE{^8^1wR4WR6Ly!CwgM_%ipc-GN<;I*^Z- z4DEb3Sc8xCfyI)T)O`vpQsUlU6S!(o;UYL~`Ovycz)nNQ)-9b5gH49qIOHWsSX6`M zE_d(RgE`)aeDQMkG07i9zG}JqGVUH#P`&(O$N&2QL?06K|$-3s^Ky_gm`MX0;fJ-ip|N3rJr zuoqi!1M(#+-5FmGEXwaeK4;b0zDnH#U=Sce!}qenC4G+Y{rLZ3%qiW0S#3l9;r&0BrsZ?umVDZ#mxAd+)I>BY*q`cl@33V+Zo_ zGRe;#6^5Q%o~yXgz5h;p`dG6R@l@`9gnTrC`~h45wJ{;>I|kMQmfYrkuqLo9luHsh zxq=t>$;s8c2A{ngFwsr6R|r;j^O-LXF<3(7WWg|449b;WwG3LYV>i3cMzLK7qgZMh z0S0b%FO3GaWCxaENm)BoAq%X2tte!t79!ug);$^xToQos6#x8EEsD2P9~o>>z1WZbR$afZl@>v_)tL_dgi4G#)`fo$M8z_PI zeJtw>SRU8`pIqn*m|QDugq+MzN#dMJm5UC6`v9flphzK!U;|him`p55!kWPnK7;LG zU0`7mLJH#V2-vs^T;&n4XmshLqaGW%_@T7M5i8+aZ}JylcYshCgpw-=ESK{eXIm^S z&jPE$Igf9MmyvI)aF2c?FeSPMd9#tRyikX)Tuvh)1@X5J<;5tk6_DHrEJAh#ibJLa zGU+0NB%M6?1*{7!K2&a!IqriJyn|p(8{K z+=^?lQAd+)&r2TIZCt?u_EpM(7It?psu7Zo8Ns2Vy__)t#fh-@8QtC+D1Y+UQ(89Ji-m=r#tNITLMviLGG-|z-4weQj(`}ft{UMiNr9`r zH^Rw}nt!+cRt1@iB5rwvb|j94M<_o)UP2zOQ#)nktH~4Ob5gWmGr9S;Cy$>6Vg0*V z5Uf|=?MPtXB2SRF;JqYS(xgF^_o;lJM{%DFdCC3CLzvZ)9>$-@*B?+`;Jrj~HwFt5 zk7_|K6^@bjKdrnI?mlqM%sr zct#rZ{u?tEZ$%;W6Xh{-X|eDGx%C8|(BSdPgDP)%1$oBv%G+t@F7hsL^dHCSED%ph z1#K^=LIcOFnLPAU?ZN zG@iVZyoq)$vGVULkYJW{IeDmGdDKQ@2@C4}ss%P!HdzI>u$mR@Ay52GLD(~I%zpCV z3FT?%kfa9k+(F9gOVm8fg1Qft*kJh)dFX$YBUrrDK^{M)JiwUvZ}R5T%54lCBR}$) zavMW`@^};rfxZXkiUQ`FQpi1S< zdMX?tuVuwi^3rKTb(Cr>S95^tRzT5 z9;|H3(F)RLDzB&fuPGlVZzTUad8k0;50HOM-b@!;wth^@;2+yYHR2!Rj6jgb>v3YP9z(250ejEqukD# z$H|KpDbGPqCCNQQ(xA$v%1adVRLrd&AuFSkZXD$CNA_T8cia#xci{Opd`1G7>20XB3BdAxEc z$J2^D`B0VeT*}X(eC2lK-fWWbU&xB;?@;4)VqTfc+D|p1$k_z@&*?L29@ zY@0{{7C%p(Qz!c`l68^X7$yxW`L;^RrX;D4Jbu4&h72Ayt@8a1%0sLmElqjuLkb!= z#M8(VP0Ek4elwp1@kg|Po0Qo=-tegMxW1VE3km_v(d5?I%5zHs%A$t zW1X4NxUXR!qkI?|Yq*2$9?=xax-SA z{C&csaCO*M@B|eSKK>GUaO_Y+o#Zic8!|`9 zs3w@6hh9B@EH<(X)4tM8$#U|Ch22?MIOSnatx(>K#Q6nTvK!p>SYwdDZPIPACv99|kIur1yu7@W&OEa5%!Ux^;6P>Bi ziURhLM&jPdDXdt|P}?thEf{UOMk)_d{%7R6tM%k{A24wK7rIJjg5_pqR3zXI<&0x17J z4OMct3W^fa4=`l19VgrmC*e$6*GPBNWM{_2XCN*i?~k}2yUQjc;u8O)V?+w+CDt0w z)P=2ut$B+)W32LK6*mLqq4Sg%Q~ne3c!qNO(feGSh>`$GsGX>Z(a;4fh>uf+D)P&` zGgs-Rot)S#rF`%CDsRux;htKr0yAMK-%K9PR$l2DLd5N6LGVH?ILI2lMIM@_yp8-3 zTfs%jYsjA>kC9iC|CBs&h052_;Xe~D5f?7d0v>Xk-%_D>wsPx<0rL0^WTPO$_E*tlgPtMc&f^V^h_4?u2O~hG*nC;EMo=i*#^s3Dz}S4ggit$ zb(H@GdBKe;k0F5nkz5wEv4WUK@u8nQ<7=v5hvrrC@J-5Xkp7-L!qeXKY3Bp-ZrW)i ze=;p7xpec{Cqrj}Zn{_!K6US&iqq8{_tAG$`~(JvVN!M6=l)`mM^98x>pP9{6LTsi|KE!p!%FE6FGL)qp zvT;-xPaeKbE3PKL6kI=WUZ4fmMTJ!8%~Bqt!gbaVU0OnZvz6zCwau@>JzjRnE>VqFiS#QTB$d~p!6nnzZ3Xm1ITenRhp$(Kc5YgKci+fyCPYu!`ne_8*b9u+kq9kQ zHQT>T@-Qb!1*@4x9$%>PJa=N|f*bt6o&S2{GL^@7<2gbJ8j|nC3^U_R7h{arRC@fw zf7Sep9bmy-YRL3*GK9(Rvz!aCI?9-DbL4uxqm4Y=BtV5ns1Rq5tpk5V9=pK(WV$nB z+Vj>hXSc2JHS)wHchL-IhVv%gkHJOXvC;P=C!5o6bSZ6Qjq*eu;gu(p=a8q5Q$8-F z!O%-SnS9_&%G=e|CXc*lp7Kh{&jZgiqoXFAAMlV}x#ZD5QgQ6>TCr8Qg*@J=d@>DH zk@tQ$w4t@+Ij<_$T8w$z%J&M#;%EypF4Brm@$*kED@ahG?tL|cEyGK{BF{Lfyos~p zee!;GpqBEd$=mTWFOr(XL$WxZkDCaj$6>bgxRfGYN?t~V3dLp?dChD!WIM2cJoj(f zAnT#)$>Z!m6YZ=69~ShY;Oi7=ZdX-n@?P?iL(1)Sl1IoJK2mN6PoBFZUFoA>52N4= zc{+Vk#U_j$@5x6^5!)POK~M`!>k92-MC&o~RW7NZeYA3We0>+W@s0Ka{pI8?=Pyr`E9;K zg{qI0x3EEvllOV^2)FW(caq0?RQ@FS8{{3_;EULUNl=s#O*<;`H{o7RD$Hj=s7nnM zGL}|Y1#jri&fm4<1HK+_2cITUzOj}PRs6hfXZUx?gFn-n>>4a`PV$oH^!ZExif0kG0Il) zEP|Z^?~(7D#yZuD<|6mieB47MPd*dxR&Z^}qtz1f{^wM_kG#TDi|%4^1B>BNFFimW z|GBD#$e$n&aU$4>{w#Sdw}EQPKX2_ERy#IGUQ>?eYWh}&x2RCUF>2J_n!k|OaZJ-# z!N15`*a6$niIdbHrCbpjDSrid+}rprGR7)g&w?Y|DXk~gyDMj6h1rK_APTW$Qws$BZ}3wxr@AgpYnd%d4T+gZ!vgOIWEF795@fm(^N2*tDy?c z*puWTE{k~Ur4(Fxl!n&*Qd?r}Oe8n#eG%mskmq{Wt+CyUAk-ZBPt0B-N1@`9k13);`eJ@Xp5{~iot5V?XsOo#oPibOpGqUco#KRJ(c=Q9h3iwX4yMuvj@pD7-n{!e4jjhj&`ht9(@K}I?#WacEF1o)Nc+`A?DlbkCF!uYJ=>?^A5T3 z;`r<_z(2?XKT-LJ(d1mn6^koh7I_vpem@F#Wj?P8VHV7yLKi2Z?eQ}5UN*Fc@@vTx zJc!Z$8MA}jysh@_O_Sdwum2@)O0b5SSP-T`6>B?`_{ zQxz#{@d5HG-=g>!c|Bdyz?QX<$9&sUCwYiRF-4UBrShmL=D|T83;sxjjz!uadrbQe zTLI;5)SQC@4hfomZY!2gCGVrW9lJvE&?_mZ5%C^o#Vc7*z#8q9obOl#9`$z#4_pEt<|>FTi=(&3{w*F!__@$9PaTj-GgyJPKcXqD@qgM|H@qP;-fzE+Bt{3US|>I%qjN zV7JGV8R}8v3&w2nUR?^KW)3Tu&4N1iz#3XWKAD%)D=5E&JjM!atjKdjWENCaYggMS zFAqr;UUrT0a_Rp+=fAw3I;c71$K97r+k95 z!^VU>&}58US&jJ&y-kJkG&R)227N*v;psCwznzP<;yNDw*_aqde$aPlbTN4XyO*p# zCd3MsvLNOQ#xn9aW5ov1cJd=XRu9?Pv5&mUx8VE-`Kbc!Scx8W;yw%(47{g??DS|M z@AG})e2qNf8~ZoNTb@@tE$rBz$iu!_bNXWRU&ibhTUtnk(ddfs0)EP~K^G*CaTeI= zx`e!rdqFwvtR}a2%oLN~N}ds2tga~17qbTiGW`a9C!_DNhS+24q3@H&v(!MtaIN7T z@;u*ybAmj~Z8~bFS;{5a<4!J(Ic(`9@><`);Kk%IoyR6j`7e_jek!XXUqn90T`^60 z)U0Gdx^Ld!Vhu4S259IGE6+n68ZzG|Z|2b0+3_s6=TRQ!+6C>fCyy^796v{0cU)t} zq+P0>XgwRHUe)K5cXC%OVuQX+9`c=*UrKI#drBGkNjb48^RJ19Ze>9!4F$>NDMAvA z%{;ztV?*o7Ykj-l6XX^2s2$2@$YV)|bepA)!z{?*0#eM1<#F#)amh0EP?Nrx_sL7w zDPU-rz-20b@Ji(+v@-@=Pw(eZBJPW(WtQ`R+Rm%Bi|dn|C=%!9Y2U;A zRAzm60l0);3-{9y2k%nK$9|{4?iN>*x1X;);7J#AxALed^|iNw3hCU}Y{fqyZ{TN< z8usIP^2ATI;vVwd_MU*Krcd4R`W-b9!AvXliOPOLBu-DoR#LwjK3ehYaoeOX5NDEaZPs;ljh$i3u2 z--oG3!M`G7S;(;r($LdXNaLq9>*@r!$d~)%<<|{lUd3NJw4=z`kUpM2ZzVs1wFy7> zv}yg$YIEx>_pMTA%cR{KH{V)Wjo;wfdB?VO+c)8Np|)+?T)l1MZPh#7c`KbO3jiW_ zh=5-*B0r0@)BDA%b<4g|wCvi&H>_K=sN~S@mClCY4@H(|xwqZyq&_rb!GuGgMMzoC5TE@w$fY^J+omy@4qug%-n1MYLXoS9>SyhYZ&#!C-TepWEZiOL=aG`@tS(#{UPFzste^ diff --git a/crypto/src/main/resources/lib/amd64/ckzg4844jni.dll b/crypto/src/main/resources/lib/amd64/ckzg4844jni.dll index 5dd62ba322aa903663b9865a28644468ef487f2b..5388053e5c49f4134eac2bb9993f24298cf2dcb3 100644 GIT binary patch delta 65681 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 delta 67809 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

    LR;H!Y{K>2iYf
    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 diff --git a/crypto/src/main/resources/lib/amd64/libckzg4844jni.so b/crypto/src/main/resources/lib/amd64/libckzg4844jni.so index 047cbd6daab82aeb2b95862575ae1fce22325dec..6e2278edb3393166c3ebaa00a6ca95a42b2ee15d 100644 GIT binary patch delta 71039 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 LEH(LB-^l+5It&Q< delta 71837 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


    |s~F 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%0ARq_g3wAW2E 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 diff --git a/framework/src/main/java/org/tron/core/zen/KZGPointEvaluationInitService.java b/framework/src/main/java/org/tron/core/zen/KZGPointEvaluationInitService.java index cc37b79757c..6a7bbe7ea7c 100644 --- a/framework/src/main/java/org/tron/core/zen/KZGPointEvaluationInitService.java +++ b/framework/src/main/java/org/tron/core/zen/KZGPointEvaluationInitService.java @@ -9,6 +9,7 @@ import org.apache.commons.io.FileUtils; import org.springframework.stereotype.Component; import org.tron.common.crypto.ckzg4844.CKZG4844JNI; +import org.tron.core.exception.TronError; @Slf4j @Component @@ -31,11 +32,15 @@ public static void initCKZG4844() { if (loaded.compareAndSet(false, true)) { logger.info("init ckzg 4844 begin"); - CKZG4844JNI.loadNativeLibrary(); + try { + CKZG4844JNI.loadNativeLibrary(); - String setupFile = getSetupFile("trusted_setup.txt"); + String setupFile = getSetupFile("trusted_setup.txt"); - CKZG4844JNI.loadTrustedSetup(setupFile, 0); + CKZG4844JNI.loadTrustedSetup(setupFile, 0); + } catch (Exception e) { + throw new TronError(e, TronError.ErrCode.CKZG_INIT); + } logger.info("init ckzg 4844 done"); } diff --git a/framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java b/framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java index 5f732520d48..8cabd7825ef 100644 --- a/framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java @@ -1,14 +1,20 @@ package org.tron.core.zksnark; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.mockito.Mockito.mockStatic; + import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.junit.Assert; import org.junit.Test; +import org.mockito.MockedStatic; import org.tron.common.crypto.ckzg4844.CKZG4844JNI; import org.tron.common.crypto.ckzg4844.CKZGException; import org.tron.common.crypto.ckzg4844.CellsAndProofs; import org.tron.common.crypto.ckzg4844.ProofAndY; +import org.tron.core.exception.TronError; import org.tron.core.zen.KZGPointEvaluationInitService; @Slf4j @@ -79,5 +85,12 @@ public void testVerifyBlobKzgProof() { } KZGPointEvaluationInitService.freeSetup(); + + try (MockedStatic mock = mockStatic(CKZG4844JNI.class)) { + mock.when(CKZG4844JNI::loadNativeLibrary).thenThrow(new RuntimeException()); + TronError thrown = assertThrows(TronError.class, + KZGPointEvaluationInitService::initCKZG4844); + assertEquals(TronError.ErrCode.CKZG_INIT, thrown.getErrCode()); + } } } From 0e4652d233a466ab8262b6bb111445a31b3663ea Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 31 Mar 2025 10:51:19 +0800 Subject: [PATCH 1190/1197] func(cfg): revert reprioritize for old internal tx switches --- .../nativecontract/UnfreezeBalanceV2Processor.java | 2 +- .../main/java/org/tron/core/config/args/Args.java | 14 ++++++-------- .../org/tron/common/runtime/vm/Create2Test.java | 7 +++++++ 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java index c8199651a7f..af2cbf63a43 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceV2Processor.java @@ -84,7 +84,7 @@ public void validate(UnfreezeBalanceV2Param param, Repository repo) if (!checkUnfreezeBalance(accountCapsule, param.getUnfreezeBalance(), param.getResourceType())) { throw new ContractValidateException( - "Invalid unfreeze_balance, [" + param.getUnfreezeBalance() + "] is too large"); + "Invalid unfreeze_balance, [" + param.getUnfreezeBalance() + "] is invalid"); } } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 2fd30f73d51..f9e6610930f 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -917,15 +917,13 @@ public static void setParam(final Config config) { PARAMETER.vmTrace = config.hasPath(Constant.VM_TRACE) && config.getBoolean(Constant.VM_TRACE); - if (!PARAMETER.saveInternalTx - && config.hasPath(Constant.VM_SAVE_INTERNAL_TX)) { - PARAMETER.saveInternalTx = config.getBoolean(Constant.VM_SAVE_INTERNAL_TX); - } + PARAMETER.saveInternalTx = + config.hasPath(Constant.VM_SAVE_INTERNAL_TX) + && config.getBoolean(Constant.VM_SAVE_INTERNAL_TX); - if (!PARAMETER.saveFeaturedInternalTx - && config.hasPath(Constant.VM_SAVE_FEATURED_INTERNAL_TX)) { - PARAMETER.saveFeaturedInternalTx = config.getBoolean(Constant.VM_SAVE_FEATURED_INTERNAL_TX); - } + PARAMETER.saveFeaturedInternalTx = + config.hasPath(Constant.VM_SAVE_FEATURED_INTERNAL_TX) + && config.getBoolean(Constant.VM_SAVE_FEATURED_INTERNAL_TX); if (!PARAMETER.saveCancelAllUnfreezeV2Details && config.hasPath(Constant.VM_SAVE_CANCEL_ALL_UNFREEZE_V2_DETAILS)) { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java index b1ed4f7af70..f400b3215ee 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/Create2Test.java @@ -8,6 +8,7 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.tron.common.runtime.TVMTestResult; import org.tron.common.runtime.TvmTestUtils; @@ -23,6 +24,7 @@ import org.tron.core.exception.VMIllegalException; import org.tron.core.services.NodeInfoService; import org.tron.core.services.jsonrpc.TronJsonRpcImpl; +import org.tron.core.vm.config.ConfigLoader; import org.tron.protos.Protocol.Transaction; @@ -103,6 +105,11 @@ triggercontract Txxxxxxxxxxx deploy(bytes,uint256) bytes,uint256 false 100000000 */ + @Before + public void before() { + ConfigLoader.disable = false; + } + @Test public void testCreate2() throws ContractExeException, ReceiptCheckErrException, From 9965edcd1120c007c911dec0a419cf6e920aa774 Mon Sep 17 00:00:00 2001 From: waynercheung Date: Tue, 1 Apr 2025 11:24:17 +0800 Subject: [PATCH 1191/1197] feat(jsonrpc): check maxSubTopics and maxBlockRange to be consistent with eth --- .../common/parameter/CommonParameter.java | 9 +- .../java/org/tron/common/utils/ByteUtil.java | 47 ++--- .../src/main/java/org/tron/core/Constant.java | 2 + .../java/org/tron/core/config/args/Args.java | 12 ++ .../services/jsonrpc/TronJsonRpcImpl.java | 2 +- .../services/jsonrpc/filters/LogFilter.java | 9 +- .../jsonrpc/filters/LogFilterAndResult.java | 3 +- .../jsonrpc/filters/LogFilterWrapper.java | 11 +- .../src/main/resources/config-localtest.conf | 2 + framework/src/main/resources/config.conf | 8 + .../org/tron/core/config/args/ArgsTest.java | 14 ++ .../org/tron/core/jsonrpc/JsonRpcTest.java | 6 +- .../tron/core/jsonrpc/JsonrpcServiceTest.java | 178 ++++++++++++++++-- .../core/jsonrpc/SectionBloomStoreTest.java | 12 +- .../src/test/resources/config-localtest.conf | 11 +- .../src/test/resources/config-test-index.conf | 2 + .../test/resources/config-test-mainnet.conf | 2 + framework/src/test/resources/config-test.conf | 2 + 18 files changed, 269 insertions(+), 63 deletions(-) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 23974183fdc..45893970fb0 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -8,9 +8,9 @@ import java.util.Set; import lombok.Getter; import lombok.Setter; -import org.tron.common.cron.CronExpression; import org.tron.common.args.GenesisBlock; import org.tron.common.config.DbBackupConfig; +import org.tron.common.cron.CronExpression; import org.tron.common.logsfilter.EventPluginConfig; import org.tron.common.logsfilter.FilterQuery; import org.tron.common.setting.RocksDbSettings; @@ -495,6 +495,13 @@ public class CommonParameter { @Getter @Setter public boolean jsonRpcHttpPBFTNodeEnable = false; + @Getter + @Setter + public int jsonRpcMaxBlockRange = 5000; + @Getter + @Setter + public int jsonRpcMaxSubTopics = 1000; + @Getter @Setter public int maxTransactionPendingSize; diff --git a/common/src/main/java/org/tron/common/utils/ByteUtil.java b/common/src/main/java/org/tron/common/utils/ByteUtil.java index 88d4cfdf90b..a7f7abd8fa8 100644 --- a/common/src/main/java/org/tron/common/utils/ByteUtil.java +++ b/common/src/main/java/org/tron/common/utils/ByteUtil.java @@ -479,40 +479,41 @@ public static byte[] setBit(byte[] data, int pos, int val) { public static byte[] compress(byte[] data) throws EventBloomException { Deflater deflater = new Deflater(); - deflater.setInput(data); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length); + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length)) { + deflater.setInput(data); + deflater.finish(); + byte[] buffer = new byte[1024]; - deflater.finish(); - byte[] buffer = new byte[1024]; - while (!deflater.finished()) { - int count = deflater.deflate(buffer); // returns the generated code... index - outputStream.write(buffer, 0, count); - } - try { - outputStream.close(); + while (!deflater.finished()) { + int count = deflater.deflate(buffer); // returns the generated code... index + outputStream.write(buffer, 0, count); + } + + return outputStream.toByteArray(); } catch (IOException e) { throw new EventBloomException("compress data failed"); + } finally { + deflater.end(); } - byte[] output = outputStream.toByteArray(); - - return output; } public static byte[] decompress(byte[] data) throws IOException, DataFormatException { Inflater inflater = new Inflater(); - inflater.setInput(data); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length); - byte[] buffer = new byte[1024]; - while (!inflater.finished()) { - int count = inflater.inflate(buffer); - outputStream.write(buffer, 0, count); - } - outputStream.close(); - byte[] output = outputStream.toByteArray(); + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length)) { + inflater.setInput(data); + byte[] buffer = new byte[1024]; + + while (!inflater.finished()) { + int count = inflater.inflate(buffer); + outputStream.write(buffer, 0, count); + } - return output; + return outputStream.toByteArray(); + } finally { + inflater.end(); + } } } diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index bb35b207795..c5a8a02fb4e 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -145,6 +145,8 @@ public class Constant { public static final String NODE_JSONRPC_HTTP_SOLIDITY_PORT = "node.jsonrpc.httpSolidityPort"; public static final String NODE_JSONRPC_HTTP_PBFT_ENABLE = "node.jsonrpc.httpPBFTEnable"; public static final String NODE_JSONRPC_HTTP_PBFT_PORT = "node.jsonrpc.httpPBFTPort"; + public static final String NODE_JSONRPC_MAX_BLOCK_RANGE = "node.jsonrpc.maxBlockRange"; + public static final String NODE_JSONRPC_MAX_SUB_TOPICS = "node.jsonrpc.maxSubTopics"; public static final String NODE_DISABLED_API_LIST = "node.disabledApi"; diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index f9e6610930f..3162360bbb9 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -202,6 +202,8 @@ public static void clearParam() { PARAMETER.jsonRpcHttpFullNodeEnable = false; PARAMETER.jsonRpcHttpSolidityNodeEnable = false; PARAMETER.jsonRpcHttpPBFTNodeEnable = false; + PARAMETER.jsonRpcMaxBlockRange = 5000; + PARAMETER.jsonRpcMaxSubTopics = 1000; PARAMETER.nodeMetricsEnable = false; PARAMETER.metricsStorageEnable = false; PARAMETER.metricsPrometheusEnable = false; @@ -507,6 +509,16 @@ public static void setParam(final Config config) { config.getBoolean(Constant.NODE_JSONRPC_HTTP_PBFT_ENABLE); } + if (config.hasPath(Constant.NODE_JSONRPC_MAX_BLOCK_RANGE)) { + PARAMETER.jsonRpcMaxBlockRange = + config.getInt(Constant.NODE_JSONRPC_MAX_BLOCK_RANGE); + } + + if (config.hasPath(Constant.NODE_JSONRPC_MAX_SUB_TOPICS)) { + PARAMETER.jsonRpcMaxSubTopics = + config.getInt(Constant.NODE_JSONRPC_MAX_SUB_TOPICS); + } + if (config.hasPath(Constant.VM_MIN_TIME_RATIO)) { PARAMETER.minTimeRatio = config.getDouble(Constant.VM_MIN_TIME_RATIO); } diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 6b90ec92283..eb432432a1c 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -1327,7 +1327,7 @@ public LogFilterElement[] getLogs(FilterRequest fr) throws JsonRpcInvalidParamsE long currentMaxBlockNum = wallet.getNowBlock().getBlockHeader().getRawData().getNumber(); //convert FilterRequest to LogFilterWrapper - LogFilterWrapper logFilterWrapper = new LogFilterWrapper(fr, currentMaxBlockNum, wallet); + LogFilterWrapper logFilterWrapper = new LogFilterWrapper(fr, currentMaxBlockNum, wallet, true); return getLogsByLogFilterWrapper(logFilterWrapper, currentMaxBlockNum); } diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilter.java b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilter.java index 01be54538b2..9826b4e94dd 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilter.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilter.java @@ -13,6 +13,7 @@ import org.tron.common.bloom.Bloom; import org.tron.common.crypto.Hash; import org.tron.common.runtime.vm.DataWord; +import org.tron.core.config.args.Args; import org.tron.core.exception.JsonRpcInvalidParamsException; import org.tron.core.services.jsonrpc.TronJsonRpc.FilterRequest; import org.tron.protos.Protocol.TransactionInfo.Log; @@ -35,6 +36,8 @@ public class LogFilter { @Setter private Bloom[][] filterBlooms; + // The maximum number of topic criteria allowed, vm.LOG4 - vm.LOG0 + private final int maxTopics = 4; public LogFilter() { } @@ -66,7 +69,7 @@ public LogFilter(FilterRequest fr) throws JsonRpcInvalidParamsException { if (fr.getTopics() != null) { //restrict depth of topics, because event has a signature and most 3 indexed parameters - if (fr.getTopics().length > 4) { + if (fr.getTopics().length > maxTopics) { throw new JsonRpcInvalidParamsException("topics size should be <= 4"); } for (Object topic : fr.getTopics()) { @@ -79,6 +82,10 @@ public LogFilter(FilterRequest fr) throws JsonRpcInvalidParamsException { throw new JsonRpcInvalidParamsException("invalid topic(s): " + topic); } } else if (topic instanceof ArrayList) { + int maxSubTopics = Args.getInstance().getJsonRpcMaxSubTopics(); + if (maxSubTopics > 0 && ((ArrayList) topic).size() > maxSubTopics) { + throw new JsonRpcInvalidParamsException("exceed max topics: " + maxSubTopics); + } List t = new ArrayList<>(); for (Object s : ((ArrayList) topic)) { diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterAndResult.java b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterAndResult.java index 5ed6c3e3841..3b893aec4cf 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterAndResult.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterAndResult.java @@ -16,7 +16,8 @@ public class LogFilterAndResult extends FilterResult { public LogFilterAndResult(FilterRequest fr, long currentMaxBlockNum, Wallet wallet) throws JsonRpcInvalidParamsException { - this.logFilterWrapper = new LogFilterWrapper(fr, currentMaxBlockNum, wallet); + // eth_newFilter, no need to check block range + this.logFilterWrapper = new LogFilterWrapper(fr, currentMaxBlockNum, wallet, false); result = new LinkedBlockingQueue<>(); this.updateExpireTime(); } diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java index 7fcbab33ee3..ec5c4640a16 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java @@ -7,6 +7,7 @@ import org.apache.commons.lang3.StringUtils; import org.tron.common.utils.ByteArray; import org.tron.core.Wallet; +import org.tron.core.config.args.Args; import org.tron.core.exception.JsonRpcInvalidParamsException; import org.tron.core.services.jsonrpc.JsonRpcApiUtil; import org.tron.core.services.jsonrpc.TronJsonRpc.FilterRequest; @@ -23,8 +24,8 @@ public class LogFilterWrapper { @Getter private final long toBlock; - public LogFilterWrapper(FilterRequest fr, long currentMaxBlockNum, Wallet wallet) - throws JsonRpcInvalidParamsException { + public LogFilterWrapper(FilterRequest fr, long currentMaxBlockNum, Wallet wallet, + boolean checkBlockRange) throws JsonRpcInvalidParamsException { // 1.convert FilterRequest to LogFilter this.logFilter = new LogFilter(fr); @@ -86,6 +87,12 @@ public LogFilterWrapper(FilterRequest fr, long currentMaxBlockNum, Wallet wallet throw new JsonRpcInvalidParamsException("please verify: fromBlock <= toBlock"); } } + + // till now, it needs to check block range for eth_getLogs + int maxBlockRange = Args.getInstance().getJsonRpcMaxBlockRange(); + if (checkBlockRange && maxBlockRange > 0 && (toBlockSrc - fromBlockSrc) > maxBlockRange) { + throw new JsonRpcInvalidParamsException("exceed max block range: " + maxBlockRange); + } } this.fromBlock = fromBlockSrc; diff --git a/framework/src/main/resources/config-localtest.conf b/framework/src/main/resources/config-localtest.conf index 50e7539c1d0..405a0f92b2d 100644 --- a/framework/src/main/resources/config-localtest.conf +++ b/framework/src/main/resources/config-localtest.conf @@ -161,6 +161,8 @@ node { # httpSolidityPort = 8555 # httpPBFTEnable = true # httpPBFTPort = 8565 + # maxBlockRange = 5000 + # maxSubTopics = 1000 } } diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index a89d6fd094e..bd985a595ea 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -291,6 +291,14 @@ node { # httpSolidityPort = 8555 # httpPBFTEnable = true # httpPBFTPort = 8565 + + # The maximum blocks range to retrieve logs for eth_getLogs, default value is 5000, + # should be >= 0, 0 means no limit. + # maxBlockRange = 5000 + + # The maximum number of allowed topics within a topic criteria, default value is 1000, + # should be >= 0, 0 means no limit. + # maxSubTopics = 1000 } # Disabled api list, it will work for http, rpc and pbft, both fullnode and soliditynode, diff --git a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java index 845f70a38a4..c3c9f24ef6b 100644 --- a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java @@ -173,6 +173,8 @@ public void testInitService() { Assert.assertFalse(Args.getInstance().isJsonRpcHttpFullNodeEnable()); Assert.assertFalse(Args.getInstance().isJsonRpcHttpSolidityNodeEnable()); Assert.assertFalse(Args.getInstance().isJsonRpcHttpPBFTNodeEnable()); + Assert.assertEquals(5000, Args.getInstance().getJsonRpcMaxBlockRange()); + Assert.assertEquals(1000, Args.getInstance().getJsonRpcMaxSubTopics()); Args.clearParam(); // test set all true value storage.put("node.rpc.enable", "true"); @@ -184,6 +186,8 @@ public void testInitService() { storage.put("node.jsonrpc.httpFullNodeEnable", "true"); storage.put("node.jsonrpc.httpSolidityEnable", "true"); storage.put("node.jsonrpc.httpPBFTEnable", "true"); + storage.put("node.jsonrpc.maxBlockRange", "10"); + storage.put("node.jsonrpc.maxSubTopics", "20"); config = ConfigFactory.defaultOverrides().withFallback(ConfigFactory.parseMap(storage)); // test value Args.setParam(config); @@ -196,6 +200,8 @@ public void testInitService() { Assert.assertTrue(Args.getInstance().isJsonRpcHttpFullNodeEnable()); Assert.assertTrue(Args.getInstance().isJsonRpcHttpSolidityNodeEnable()); Assert.assertTrue(Args.getInstance().isJsonRpcHttpPBFTNodeEnable()); + Assert.assertEquals(10, Args.getInstance().getJsonRpcMaxBlockRange()); + Assert.assertEquals(20, Args.getInstance().getJsonRpcMaxSubTopics()); Args.clearParam(); // test set all false value storage.put("node.rpc.enable", "false"); @@ -207,6 +213,8 @@ public void testInitService() { storage.put("node.jsonrpc.httpFullNodeEnable", "false"); storage.put("node.jsonrpc.httpSolidityEnable", "false"); storage.put("node.jsonrpc.httpPBFTEnable", "false"); + storage.put("node.jsonrpc.maxBlockRange", "5000"); + storage.put("node.jsonrpc.maxSubTopics", "1000"); config = ConfigFactory.defaultOverrides().withFallback(ConfigFactory.parseMap(storage)); // test value Args.setParam(config); @@ -219,6 +227,8 @@ public void testInitService() { Assert.assertFalse(Args.getInstance().isJsonRpcHttpFullNodeEnable()); Assert.assertFalse(Args.getInstance().isJsonRpcHttpSolidityNodeEnable()); Assert.assertFalse(Args.getInstance().isJsonRpcHttpPBFTNodeEnable()); + Assert.assertEquals(5000, Args.getInstance().getJsonRpcMaxBlockRange()); + Assert.assertEquals(1000, Args.getInstance().getJsonRpcMaxSubTopics()); Args.clearParam(); // test set random value storage.put("node.rpc.enable", "false"); @@ -230,6 +240,8 @@ public void testInitService() { storage.put("node.jsonrpc.httpFullNodeEnable", "true"); storage.put("node.jsonrpc.httpSolidityEnable", "false"); storage.put("node.jsonrpc.httpPBFTEnable", "true"); + storage.put("node.jsonrpc.maxBlockRange", "30"); + storage.put("node.jsonrpc.maxSubTopics", "40"); config = ConfigFactory.defaultOverrides().withFallback(ConfigFactory.parseMap(storage)); // test value Args.setParam(config); @@ -242,6 +254,8 @@ public void testInitService() { Assert.assertTrue(Args.getInstance().isJsonRpcHttpFullNodeEnable()); Assert.assertFalse(Args.getInstance().isJsonRpcHttpSolidityNodeEnable()); Assert.assertTrue(Args.getInstance().isJsonRpcHttpPBFTNodeEnable()); + Assert.assertEquals(30, Args.getInstance().getJsonRpcMaxBlockRange()); + Assert.assertEquals(40, Args.getInstance().getJsonRpcMaxSubTopics()); Args.clearParam(); } } diff --git a/framework/src/test/java/org/tron/core/jsonrpc/JsonRpcTest.java b/framework/src/test/java/org/tron/core/jsonrpc/JsonRpcTest.java index c9e6d6a2330..bef0b5a1593 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/JsonRpcTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/JsonRpcTest.java @@ -284,7 +284,8 @@ public void testGetConditions() { topics, null), 100, - null); + null, + false); LogBlockQuery logBlockQuery = new LogBlockQuery(logFilterWrapper, null, 100, null); int[][][] conditions = logBlockQuery.getConditions(); @@ -331,7 +332,8 @@ public void testGetConditionWithHashCollision() { topics, null), 100, - null); + null, + false); LogBlockQuery logBlockQuery = new LogBlockQuery(logFilterWrapper, null, 100, null); int[][][] conditions = logBlockQuery.getConditions(); diff --git a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java index 7af59f28ace..0b724b9d7d0 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java @@ -7,6 +7,9 @@ import com.google.gson.JsonObject; import com.google.protobuf.ByteString; import io.prometheus.client.CollectorRegistry; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.apache.http.client.methods.CloseableHttpResponse; @@ -545,7 +548,7 @@ public void testLogFilterWrapper() { // fromBlock and toBlock are both empty try { LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest(null, null, null, null, null), 100, null); + new LogFilterWrapper(new FilterRequest(null, null, null, null, null), 100, null, false); Assert.assertEquals(100, logFilterWrapper.getFromBlock()); Assert.assertEquals(Long.MAX_VALUE, logFilterWrapper.getToBlock()); } catch (JsonRpcInvalidParamsException e) { @@ -555,7 +558,7 @@ public void testLogFilterWrapper() { // fromBlock is not empty and smaller than currentMaxBlockNum, toBlock is empty try { LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest("0x14", null, null, null, null), 100, null); + new LogFilterWrapper(new FilterRequest("0x14", null, null, null, null), 100, null, false); Assert.assertEquals(20, logFilterWrapper.getFromBlock()); Assert.assertEquals(Long.MAX_VALUE, logFilterWrapper.getToBlock()); } catch (JsonRpcInvalidParamsException e) { @@ -565,7 +568,7 @@ public void testLogFilterWrapper() { // fromBlock is not empty and bigger than currentMaxBlockNum, toBlock is empty try { LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest("0x78", null, null, null, null), 100, null); + new LogFilterWrapper(new FilterRequest("0x78", null, null, null, null), 100, null, false); Assert.assertEquals(120, logFilterWrapper.getFromBlock()); Assert.assertEquals(Long.MAX_VALUE, logFilterWrapper.getToBlock()); } catch (JsonRpcInvalidParamsException e) { @@ -575,7 +578,7 @@ public void testLogFilterWrapper() { // fromBlock is empty, toBlock is not empty and smaller than currentMaxBlockNum try { LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest(null, "0x14", null, null, null), 100, null); + new LogFilterWrapper(new FilterRequest(null, "0x14", null, null, null), 100, null, false); Assert.assertEquals(20, logFilterWrapper.getFromBlock()); Assert.assertEquals(20, logFilterWrapper.getToBlock()); } catch (JsonRpcInvalidParamsException e) { @@ -585,7 +588,7 @@ public void testLogFilterWrapper() { // fromBlock is empty, toBlock is not empty and bigger than currentMaxBlockNum try { LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest(null, "0x78", null, null, null), 100, null); + new LogFilterWrapper(new FilterRequest(null, "0x78", null, null, null), 100, null, false); Assert.assertEquals(100, logFilterWrapper.getFromBlock()); Assert.assertEquals(120, logFilterWrapper.getToBlock()); } catch (JsonRpcInvalidParamsException e) { @@ -594,55 +597,196 @@ public void testLogFilterWrapper() { // fromBlock is not empty, toBlock is not empty try { - LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest("0x14", "0x78", null, null, null), 100, null); + LogFilterWrapper logFilterWrapper = new LogFilterWrapper(new FilterRequest("0x14", "0x78", + null, null, null), 100, null, false); Assert.assertEquals(20, logFilterWrapper.getFromBlock()); Assert.assertEquals(120, logFilterWrapper.getToBlock()); } catch (JsonRpcInvalidParamsException e) { Assert.fail(); } try { - LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest("0x78", "0x14", null, null, null), 100, null); + new LogFilterWrapper(new FilterRequest("0x78", "0x14", + null, null, null), 100, null, false); } catch (JsonRpcInvalidParamsException e) { Assert.assertEquals("please verify: fromBlock <= toBlock", e.getMessage()); } //fromBlock or toBlock is not hex num try { - LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest("earliest", null, null, null, null), 100, null); + LogFilterWrapper logFilterWrapper = new LogFilterWrapper(new FilterRequest("earliest", null, + null, null, null), 100, null, false); Assert.assertEquals(0, logFilterWrapper.getFromBlock()); Assert.assertEquals(Long.MAX_VALUE, logFilterWrapper.getToBlock()); } catch (JsonRpcInvalidParamsException e) { Assert.fail(); } try { - LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest("latest", null, null, null, null), 100, null); + LogFilterWrapper logFilterWrapper = new LogFilterWrapper(new FilterRequest("latest", null, + null, null, null), 100, null, false); Assert.assertEquals(100, logFilterWrapper.getFromBlock()); Assert.assertEquals(Long.MAX_VALUE, logFilterWrapper.getToBlock()); } catch (JsonRpcInvalidParamsException e) { Assert.fail(); } try { - new LogFilterWrapper(new FilterRequest("pending", null, null, null, null), 100, null); + new LogFilterWrapper(new FilterRequest("pending", null, null, null, null), + 100, null, false); } catch (JsonRpcInvalidParamsException e) { Assert.assertEquals("TAG pending not supported", e.getMessage()); } try { - LogFilterWrapper logFilterWrapper = - new LogFilterWrapper(new FilterRequest("finalized", null, null, null, null), 100, wallet); + LogFilterWrapper logFilterWrapper = new LogFilterWrapper(new FilterRequest("finalized", null, + null, null, null), 100, wallet, false); Assert.assertEquals(LATEST_SOLIDIFIED_BLOCK_NUM, logFilterWrapper.getFromBlock()); Assert.assertEquals(Long.MAX_VALUE, logFilterWrapper.getToBlock()); } catch (JsonRpcInvalidParamsException e) { Assert.fail(); } try { - new LogFilterWrapper(new FilterRequest("test", null, null, null, null), 100, null); + new LogFilterWrapper(new FilterRequest("test", null, null, null, null), + 100, null, false); } catch (JsonRpcInvalidParamsException e) { Assert.assertEquals("Incorrect hex syntax", e.getMessage()); } + + try { + new LogFilterWrapper(new FilterRequest("0x0", "0x1f40", null, + null, null), 10_000, null, false); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + + try { + new LogFilterWrapper(new FilterRequest("0x0", "0x1f40", null, + null, null), 10_000, null, true); + } catch (JsonRpcInvalidParamsException e) { + Assert.assertEquals( + "exceed max block range: " + Args.getInstance().jsonRpcMaxBlockRange, + e.getMessage()); + } + + int oldMaxBlockRange = Args.getInstance().getJsonRpcMaxBlockRange(); + Args.getInstance().setJsonRpcMaxBlockRange(10_000); + try { + new LogFilterWrapper(new FilterRequest("0x0", "0x1f40", null, + null, null), 10_000, null, true); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + try { + new LogFilterWrapper(new FilterRequest("0x0", "0x1f40", null, + null, null), 10_000, null, false); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + + Args.getInstance().setJsonRpcMaxBlockRange(0); + try { + new LogFilterWrapper(new FilterRequest("0x0", "0x1f40", null, + null, null), 10_000, null, true); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + try { + new LogFilterWrapper(new FilterRequest("0x0", "0x1f40", null, + null, null), 10_000, null, false); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + + // reset + Args.getInstance().setJsonRpcMaxBlockRange(oldMaxBlockRange); + } + + @Test + public void testMaxSubTopics() { + List topics = new ArrayList<>(); + topics.add(new ArrayList<>(Collections.singletonList( + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"))); + topics.add(new ArrayList<>(Collections.EMPTY_LIST)); + List subTopics = new ArrayList<>(); + for (int i = 0; i < Args.getInstance().getJsonRpcMaxSubTopics() + 1; i++) { + subTopics.add("0x0000000000000000000000414de17123a3c706ab197957e131350b2537dd4883"); + } + topics.add(subTopics); + + try { + new LogFilterWrapper(new FilterRequest("0xbb8", "0x1f40", + null, topics.toArray(), null), 10_000, null, false); + } catch (JsonRpcInvalidParamsException e) { + Assert.assertEquals( + "exceed max topics: " + Args.getInstance().getJsonRpcMaxSubTopics(), + e.getMessage()); + } + + try { + tronJsonRpc.getLogs(new FilterRequest("0xbb8", "0x1f40", + null, topics.toArray(), null)); + } catch (JsonRpcInvalidParamsException e) { + Assert.assertEquals( + "exceed max topics: " + Args.getInstance().getJsonRpcMaxSubTopics(), + e.getMessage()); + } catch (Exception e) { + Assert.fail(); + } + + try { + tronJsonRpc.newFilter(new FilterRequest("0xbb8", "0x1f40", + null, topics.toArray(), null)); + } catch (JsonRpcInvalidParamsException e) { + Assert.assertEquals( + "exceed max topics: " + Args.getInstance().getJsonRpcMaxSubTopics(), + e.getMessage()); + } catch (Exception e) { + Assert.fail(); + } + + int oldMaxSubTopics = Args.getInstance().getJsonRpcMaxSubTopics(); + Args.getInstance().setJsonRpcMaxSubTopics(2_000); + try { + new LogFilterWrapper(new FilterRequest("0xbb8", "0x1f40", + null, topics.toArray(), null), 10_000, null, false); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + + Args.getInstance().setJsonRpcMaxSubTopics(0); + try { + new LogFilterWrapper(new FilterRequest("0xbb8", "0x1f40", + null, topics.toArray(), null), 10_000, null, false); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + + Args.getInstance().setJsonRpcMaxSubTopics(oldMaxSubTopics); + } + + @Test + public void testMethodBlockRange() { + try { + tronJsonRpc.getLogs(new FilterRequest("0x0", "0x1f40", null, + null, null)); + } catch (JsonRpcInvalidParamsException e) { + Assert.assertEquals( + "exceed max block range: " + Args.getInstance().jsonRpcMaxBlockRange, + e.getMessage()); + } catch (Exception e) { + Assert.fail(); + } + + try { + tronJsonRpc.newFilter(new FilterRequest("0x0", "0x1f40", null, + null, null)); + } catch (Exception e) { + Assert.fail(); + } + + try { + tronJsonRpc.getLogs(new FilterRequest("0x0", "0x1", null, + null, null)); + } catch (Exception e) { + Assert.fail(); + } } @Test diff --git a/framework/src/test/java/org/tron/core/jsonrpc/SectionBloomStoreTest.java b/framework/src/test/java/org/tron/core/jsonrpc/SectionBloomStoreTest.java index 6e350a38999..111370bfffd 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/SectionBloomStoreTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/SectionBloomStoreTest.java @@ -132,7 +132,7 @@ public void testWriteAndQuery() { try { LogFilterWrapper logFilterWrapper = new LogFilterWrapper( new FilterRequest("earliest", "latest", ByteArray.toJsonHex(address1), null, null), - currentMaxBlockNum, null); + currentMaxBlockNum, null, false); LogBlockQuery logBlockQuery = new LogBlockQuery(logFilterWrapper, sectionBloomStore, currentMaxBlockNum, sectionExecutor); @@ -149,7 +149,7 @@ public void testWriteAndQuery() { try { LogFilterWrapper logFilterWrapper = new LogFilterWrapper( new FilterRequest("earliest", "latest", addressList, null, null), - currentMaxBlockNum, null); + currentMaxBlockNum, null, false); LogBlockQuery logBlockQuery = new LogBlockQuery(logFilterWrapper, sectionBloomStore, currentMaxBlockNum, sectionExecutor); @@ -165,7 +165,7 @@ public void testWriteAndQuery() { LogFilterWrapper logFilterWrapper = new LogFilterWrapper( new FilterRequest("earliest", "latest", null, new String[] {ByteArray.toHexString(topic1)}, null), - currentMaxBlockNum, null); + currentMaxBlockNum, null, false); LogBlockQuery logBlockQuery = new LogBlockQuery(logFilterWrapper, sectionBloomStore, currentMaxBlockNum, sectionExecutor); @@ -181,7 +181,7 @@ public void testWriteAndQuery() { LogFilterWrapper logFilterWrapper = new LogFilterWrapper( new FilterRequest("earliest", "latest", null, new String[] {ByteArray.toHexString(topic2)}, null), - currentMaxBlockNum, null); + currentMaxBlockNum, null, false); LogBlockQuery logBlockQuery = new LogBlockQuery(logFilterWrapper, sectionBloomStore, currentMaxBlockNum, sectionExecutor); @@ -199,7 +199,7 @@ public void testWriteAndQuery() { LogFilterWrapper logFilterWrapper = new LogFilterWrapper( new FilterRequest("earliest", "latest", null, new Object[] {topicList}, null), - currentMaxBlockNum, null); + currentMaxBlockNum, null, false); LogBlockQuery logBlockQuery = new LogBlockQuery(logFilterWrapper, sectionBloomStore, currentMaxBlockNum, sectionExecutor); @@ -226,7 +226,7 @@ public void testWriteAndQuery() { LogFilterWrapper logFilterWrapper = new LogFilterWrapper( new FilterRequest("earliest", "latest", null, new Object[] {ByteArray.toJsonHex(topic1), ByteArray.toJsonHex(topic2)}, null), - currentMaxBlockNum, null); + currentMaxBlockNum, null, false); LogBlockQuery logBlockQuery = new LogBlockQuery(logFilterWrapper, sectionBloomStore, currentMaxBlockNum, sectionExecutor); diff --git a/framework/src/test/resources/config-localtest.conf b/framework/src/test/resources/config-localtest.conf index b6c1f41154a..ff31369a915 100644 --- a/framework/src/test/resources/config-localtest.conf +++ b/framework/src/test/resources/config-localtest.conf @@ -125,15 +125,6 @@ node { PBFTPort = 8092 } - jsonrpc { - httpFullNodeEnable = false - httpFullNodePort = 8545 - httpSolidityEnable = false - httpSolidityPort = 8555 - httpPBFTEnable = false - httpPBFTPort = 8565 - } - rpc { enable = false port = 50051 @@ -174,6 +165,8 @@ node { # httpSolidityPort = 8555 # httpPBFTEnable = true # httpPBFTPort = 8565 + # maxBlockRange = 5000 + # maxSubTopics = 1000 } } diff --git a/framework/src/test/resources/config-test-index.conf b/framework/src/test/resources/config-test-index.conf index cff08fd3abb..faa2f93dc5e 100644 --- a/framework/src/test/resources/config-test-index.conf +++ b/framework/src/test/resources/config-test-index.conf @@ -86,6 +86,8 @@ node { httpFullNodeEnable = false httpSolidityEnable = false httpPBFTEnable = false + # maxBlockRange = 5000 + # maxSubTopics = 1000 } rpc { diff --git a/framework/src/test/resources/config-test-mainnet.conf b/framework/src/test/resources/config-test-mainnet.conf index de9170a0ec4..12acad64d8d 100644 --- a/framework/src/test/resources/config-test-mainnet.conf +++ b/framework/src/test/resources/config-test-mainnet.conf @@ -92,6 +92,8 @@ node { httpFullNodeEnable = false httpSolidityEnable = false httpPBFTEnable = false + # maxBlockRange = 5000 + # maxSubTopics = 1000 } rpc { diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index 795f9df9162..eaa6659a8c4 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -116,6 +116,8 @@ node { httpFullNodeEnable = false httpSolidityEnable = false httpPBFTEnable = false + # maxBlockRange = 5000 + # maxSubTopics = 1000 } # use your ipv6 address for node discovery and tcp connection, default false From fd89088eee2a21648274a8c289dd9952341c252c Mon Sep 17 00:00:00 2001 From: waynercheung Date: Tue, 1 Apr 2025 12:05:55 +0800 Subject: [PATCH 1192/1197] feat(jsonrpc): refactor to set min and max section --- .../services/jsonrpc/filters/LogBlockQuery.java | 8 +++----- .../core/services/jsonrpc/filters/LogFilter.java | 2 +- framework/src/main/resources/config.conf | 4 ++-- .../org/tron/core/jsonrpc/JsonrpcServiceTest.java | 14 ++++++++++++++ 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogBlockQuery.java b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogBlockQuery.java index 7ee6ce74c10..7665c51106f 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogBlockQuery.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogBlockQuery.java @@ -39,23 +39,21 @@ public LogBlockQuery(LogFilterWrapper logFilterWrapper, SectionBloomStore sectio this.currentMaxBlockNum = currentMaxBlockNum; if (logFilterWrapper.getFromBlock() == Long.MAX_VALUE) { - minSection = (int) (currentMaxBlockNum / Bloom.BLOOM_BIT_SIZE); minBlock = currentMaxBlockNum; } else { - minSection = (int) (logFilterWrapper.getFromBlock() / Bloom.BLOOM_BIT_SIZE); minBlock = logFilterWrapper.getFromBlock(); } + minSection = (int) (minBlock / Bloom.BLOOM_BIT_SIZE); if (logFilterWrapper.getToBlock() == Long.MAX_VALUE) { - maxSection = (int) (currentMaxBlockNum / Bloom.BLOOM_BIT_SIZE); maxBlock = currentMaxBlockNum; } else { - maxSection = (int) (logFilterWrapper.getToBlock() / Bloom.BLOOM_BIT_SIZE); maxBlock = logFilterWrapper.getToBlock(); if (maxBlock > currentMaxBlockNum) { maxBlock = currentMaxBlockNum; } } + maxSection = (int) (maxBlock / Bloom.BLOOM_BIT_SIZE); } public List getPossibleBlock() throws ExecutionException, InterruptedException, @@ -71,7 +69,7 @@ public List getPossibleBlock() throws ExecutionException, InterruptedExcep BitSet blockNumBitSet = new BitSet(capacity); blockNumBitSet.set(0, capacity); - //works serial + // works serial for (int[][] conditionsIndex : allConditionsIndex) { BitSet bitSet = subMatch(conditionsIndex); blockNumBitSet.and(bitSet); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilter.java b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilter.java index 9826b4e94dd..ce315e506d2 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilter.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilter.java @@ -70,7 +70,7 @@ public LogFilter(FilterRequest fr) throws JsonRpcInvalidParamsException { if (fr.getTopics() != null) { //restrict depth of topics, because event has a signature and most 3 indexed parameters if (fr.getTopics().length > maxTopics) { - throw new JsonRpcInvalidParamsException("topics size should be <= 4"); + throw new JsonRpcInvalidParamsException("topics size should be <= " + maxTopics); } for (Object topic : fr.getTopics()) { if (topic == null) { diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index bd985a595ea..3236573a889 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -293,11 +293,11 @@ node { # httpPBFTPort = 8565 # The maximum blocks range to retrieve logs for eth_getLogs, default value is 5000, - # should be >= 0, 0 means no limit. + # should be > 0, otherwise means no limit. # maxBlockRange = 5000 # The maximum number of allowed topics within a topic criteria, default value is 1000, - # should be >= 0, 0 means no limit. + # should be > 0, otherwise means no limit. # maxSubTopics = 1000 } diff --git a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java index 0b724b9d7d0..3da7072c216 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java @@ -694,6 +694,20 @@ public void testLogFilterWrapper() { Assert.fail(); } + Args.getInstance().setJsonRpcMaxBlockRange(-2); + try { + new LogFilterWrapper(new FilterRequest("0x0", "0x1f40", null, + null, null), 10_000, null, true); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + try { + new LogFilterWrapper(new FilterRequest("0x0", "0x1f40", null, + null, null), 10_000, null, false); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + // reset Args.getInstance().setJsonRpcMaxBlockRange(oldMaxBlockRange); } From cb1837267d449abdc7ff009a30450816cf60e04c Mon Sep 17 00:00:00 2001 From: Asuka Date: Wed, 2 Apr 2025 17:54:20 +0800 Subject: [PATCH 1193/1197] func(event): optimize energy price querying method --- .../tron/core/services/event/BlockEventGet.java | 15 ++------------- .../org/tron/core/event/BlockEventGetTest.java | 11 +++++++++++ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java b/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java index be15a499d3f..bf668a3e0b6 100644 --- a/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java +++ b/framework/src/main/java/org/tron/core/services/event/BlockEventGet.java @@ -39,6 +39,7 @@ import org.tron.core.exception.BadItemException; import org.tron.core.services.event.bo.BlockEvent; import org.tron.core.services.event.bo.SmartContractTrigger; +import org.tron.core.services.jsonrpc.JsonRpcApiUtil; import org.tron.core.store.StoreFactory; import org.tron.protos.Protocol; import org.tron.protos.contract.SmartContractOuterClass; @@ -373,19 +374,7 @@ public List getTransactionLogTrigger(BlockCapsule public long getEnergyPrice(long blockTime) { String energyPriceHistory = manager.getDynamicPropertiesStore().getEnergyPriceHistory(); - - String[] energyPrices = energyPriceHistory.split(","); - String[] lastPrice = energyPrices[energyPrices.length - 1].split(":"); - long energyPrice = Long.parseLong(lastPrice[1]); - - for (int i = 1; i < energyPrices.length; i++) { - long effectiveTime = Long.parseLong(energyPrices[i].split(":")[0]); - if (blockTime < effectiveTime) { - energyPrice = Long.parseLong(energyPrices[i - 1].split(":")[1]); - break; - } - } - return energyPrice; + return JsonRpcApiUtil.parseEnergyFee(blockTime, energyPriceHistory); } public List getTransactionTriggers(BlockCapsule block, diff --git a/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java b/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java index 704dc9ddc49..b6835cfcf82 100644 --- a/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java +++ b/framework/src/test/java/org/tron/core/event/BlockEventGetTest.java @@ -150,6 +150,11 @@ public void test() throws Exception { }); manager.pushBlock(blockCapsule); + // Set energy price history to test boundary cases + manager.getDynamicPropertiesStore().saveEnergyPriceHistory( + manager.getDynamicPropertiesStore().getEnergyPriceHistory() + + "," + time + ":210"); + EventPluginConfig config = new EventPluginConfig(); config.setSendQueueLength(1000); config.setBindPort(5555); @@ -187,6 +192,12 @@ public void test() throws Exception { try { BlockEvent blockEvent = blockEventGet.getBlockEvent(1); Assert.assertNotNull(blockEvent); + Assert.assertEquals(1, blockEvent.getTransactionLogTriggerCapsules().size()); + + // Here energy unit price should be 100 not 210, + // cause block time is equal to 210`s effective time + Assert.assertEquals(100, blockEvent.getTransactionLogTriggerCapsules() + .get(0).getTransactionLogTrigger().getEnergyUnitPrice()); } catch (Exception e) { Assert.fail(); } From 95082c2c399e39d1d23cea182e0ce5695d33c254 Mon Sep 17 00:00:00 2001 From: waynercheung Date: Wed, 2 Apr 2025 17:58:59 +0800 Subject: [PATCH 1194/1197] fix(jsonrpc): use min(to, currentMaxBlock) to compare with maxBlockRange --- .../jsonrpc/filters/LogFilterWrapper.java | 7 +- .../org/tron/core/config/args/ArgsTest.java | 19 +++ .../tron/core/jsonrpc/JsonrpcServiceTest.java | 150 ++++++++++++++++-- 3 files changed, 161 insertions(+), 15 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java index ec5c4640a16..c0cd1ff12df 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java @@ -1,6 +1,6 @@ package org.tron.core.services.jsonrpc.filters; -import static org.tron.common.math.Maths.min; +import static org.tron.common.math.StrictMathWrapper.min; import com.google.protobuf.ByteString; import lombok.Getter; @@ -58,7 +58,7 @@ public LogFilterWrapper(FilterRequest fr, long currentMaxBlockNum, Wallet wallet if (toBlockSrc == -1) { toBlockSrc = Long.MAX_VALUE; } - fromBlockSrc = min(toBlockSrc, currentMaxBlockNum, true); + fromBlockSrc = min(toBlockSrc, currentMaxBlockNum); } else if (StringUtils.isNotEmpty(fr.getFromBlock()) && StringUtils.isEmpty(fr.getToBlock())) { @@ -90,7 +90,8 @@ public LogFilterWrapper(FilterRequest fr, long currentMaxBlockNum, Wallet wallet // till now, it needs to check block range for eth_getLogs int maxBlockRange = Args.getInstance().getJsonRpcMaxBlockRange(); - if (checkBlockRange && maxBlockRange > 0 && (toBlockSrc - fromBlockSrc) > maxBlockRange) { + if (checkBlockRange && maxBlockRange > 0 + && min(toBlockSrc, currentMaxBlockNum) - fromBlockSrc > maxBlockRange) { throw new JsonRpcInvalidParamsException("exceed max block range: " + maxBlockRange); } } diff --git a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java index c3c9f24ef6b..4bb8e7e4909 100644 --- a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java @@ -256,6 +256,25 @@ public void testInitService() { Assert.assertTrue(Args.getInstance().isJsonRpcHttpPBFTNodeEnable()); Assert.assertEquals(30, Args.getInstance().getJsonRpcMaxBlockRange()); Assert.assertEquals(40, Args.getInstance().getJsonRpcMaxSubTopics()); + + // test set invalid value + storage.put("node.jsonrpc.maxBlockRange", "0"); + storage.put("node.jsonrpc.maxSubTopics", "0"); + config = ConfigFactory.defaultOverrides().withFallback(ConfigFactory.parseMap(storage)); + // check value + Args.setParam(config); + Assert.assertEquals(0, Args.getInstance().getJsonRpcMaxBlockRange()); + Assert.assertEquals(0, Args.getInstance().getJsonRpcMaxSubTopics()); + + // test set invalid value + storage.put("node.jsonrpc.maxBlockRange", "-2"); + storage.put("node.jsonrpc.maxSubTopics", "-4"); + config = ConfigFactory.defaultOverrides().withFallback(ConfigFactory.parseMap(storage)); + // check value + Args.setParam(config); + Assert.assertEquals(-2, Args.getInstance().getJsonRpcMaxBlockRange()); + Assert.assertEquals(-4, Args.getInstance().getJsonRpcMaxSubTopics()); + Args.clearParam(); } } diff --git a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java index 3da7072c216..0f2214c5c9c 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java @@ -55,7 +55,7 @@ public class JsonrpcServiceTest extends BaseTest { private static final String OWNER_ADDRESS; private static final String OWNER_ADDRESS_ACCOUNT_NAME = "first"; - private static final long LATEST_BLOCK_NUM = 10L; + private static final long LATEST_BLOCK_NUM = 10_000L; private static final long LATEST_SOLIDIFIED_BLOCK_NUM = 4L; private static TronJsonRpcImpl tronJsonRpc; @@ -303,6 +303,7 @@ public void testGetBlockByNumber() { // pending try { tronJsonRpc.ethGetBlockByNumber("pending", false); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("TAG pending not supported", e.getMessage()); } @@ -310,6 +311,7 @@ public void testGetBlockByNumber() { // invalid try { tronJsonRpc.ethGetBlockByNumber("0x", false); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("invalid block number", e.getMessage()); } @@ -388,6 +390,7 @@ public void testGetByJsonBlockId() { try { getByJsonBlockId("pending", wallet); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("TAG pending not supported", e.getMessage()); } @@ -422,12 +425,14 @@ public void testGetByJsonBlockId() { try { getByJsonBlockId("abc", wallet); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("Incorrect hex syntax", e.getMessage()); } try { getByJsonBlockId("0xxabc", wallet); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("For input string: \"xabc\"", e.getMessage()); } @@ -439,6 +444,7 @@ public void testGetTrxBalance() { try { tronJsonRpc.getTrxBalance("", "earliest"); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("TAG [earliest | pending | finalized] not supported", e.getMessage()); @@ -446,6 +452,7 @@ public void testGetTrxBalance() { try { tronJsonRpc.getTrxBalance("", "pending"); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("TAG [earliest | pending | finalized] not supported", e.getMessage()); @@ -453,6 +460,7 @@ public void testGetTrxBalance() { try { tronJsonRpc.getTrxBalance("", "finalized"); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("TAG [earliest | pending | finalized] not supported", e.getMessage()); @@ -471,6 +479,7 @@ public void testGetTrxBalance() { public void testGetStorageAt() { try { tronJsonRpc.getStorageAt("", "", "earliest"); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("TAG [earliest | pending | finalized] not supported", e.getMessage()); @@ -478,6 +487,7 @@ public void testGetStorageAt() { try { tronJsonRpc.getStorageAt("", "", "pending"); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("TAG [earliest | pending | finalized] not supported", e.getMessage()); @@ -485,6 +495,7 @@ public void testGetStorageAt() { try { tronJsonRpc.getStorageAt("", "", "finalized"); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("TAG [earliest | pending | finalized] not supported", e.getMessage()); @@ -495,6 +506,7 @@ public void testGetStorageAt() { public void testGetABIOfSmartContract() { try { tronJsonRpc.getABIOfSmartContract("", "earliest"); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("TAG [earliest | pending | finalized] not supported", e.getMessage()); @@ -502,6 +514,7 @@ public void testGetABIOfSmartContract() { try { tronJsonRpc.getABIOfSmartContract("", "pending"); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("TAG [earliest | pending | finalized] not supported", e.getMessage()); @@ -509,6 +522,7 @@ public void testGetABIOfSmartContract() { try { tronJsonRpc.getABIOfSmartContract("", "finalized"); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("TAG [earliest | pending | finalized] not supported", e.getMessage()); @@ -519,6 +533,7 @@ public void testGetABIOfSmartContract() { public void testGetCall() { try { tronJsonRpc.getCall(null, "earliest"); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("TAG [earliest | pending | finalized] not supported", e.getMessage()); @@ -526,6 +541,7 @@ public void testGetCall() { try { tronJsonRpc.getCall(null, "pending"); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("TAG [earliest | pending | finalized] not supported", e.getMessage()); @@ -533,6 +549,7 @@ public void testGetCall() { try { tronJsonRpc.getCall(null, "finalized"); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("TAG [earliest | pending | finalized] not supported", e.getMessage()); @@ -607,6 +624,7 @@ public void testLogFilterWrapper() { try { new LogFilterWrapper(new FilterRequest("0x78", "0x14", null, null, null), 100, null, false); + Assert.fail("Expected to be thrown"); } catch (JsonRpcInvalidParamsException e) { Assert.assertEquals("please verify: fromBlock <= toBlock", e.getMessage()); } @@ -631,6 +649,7 @@ public void testLogFilterWrapper() { try { new LogFilterWrapper(new FilterRequest("pending", null, null, null, null), 100, null, false); + Assert.fail("Expected to be thrown"); } catch (JsonRpcInvalidParamsException e) { Assert.assertEquals("TAG pending not supported", e.getMessage()); } @@ -645,37 +664,115 @@ public void testLogFilterWrapper() { try { new LogFilterWrapper(new FilterRequest("test", null, null, null, null), 100, null, false); + Assert.fail("Expected to be thrown"); } catch (JsonRpcInvalidParamsException e) { Assert.assertEquals("Incorrect hex syntax", e.getMessage()); } + // to = 8000 try { new LogFilterWrapper(new FilterRequest("0x0", "0x1f40", null, - null, null), 10_000, null, false); + null, null), LATEST_BLOCK_NUM, null, false); } catch (JsonRpcInvalidParamsException e) { Assert.fail(); } try { new LogFilterWrapper(new FilterRequest("0x0", "0x1f40", null, - null, null), 10_000, null, true); + null, null), LATEST_BLOCK_NUM, null, true); + Assert.fail("Expected to be thrown"); } catch (JsonRpcInvalidParamsException e) { Assert.assertEquals( "exceed max block range: " + Args.getInstance().jsonRpcMaxBlockRange, e.getMessage()); } + try { + new LogFilterWrapper(new FilterRequest("0x0", "latest", null, + null, null), LATEST_BLOCK_NUM, null, false); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + + try { + new LogFilterWrapper(new FilterRequest("0x0", "latest", null, + null, null), LATEST_BLOCK_NUM, null, true); + Assert.fail("Expected to be thrown"); + } catch (JsonRpcInvalidParamsException e) { + Assert.assertEquals( + "exceed max block range: " + Args.getInstance().jsonRpcMaxBlockRange, + e.getMessage()); + } + + // from = 100, current = 5_000, to = Long.MAX_VALUE + try { + new LogFilterWrapper(new FilterRequest("0x64", "latest", null, + null, null), 5_000, null, true); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + try { + new LogFilterWrapper(new FilterRequest("0x64", "latest", null, + null, null), LATEST_BLOCK_NUM, null, false); + } catch (Exception e) { + Assert.fail(); + } + + // from = 100 + try { + new LogFilterWrapper(new FilterRequest("0x64", "latest", null, + null, null), LATEST_BLOCK_NUM, null, true); + Assert.fail("Expected to be thrown"); + } catch (JsonRpcInvalidParamsException e) { + Assert.assertEquals( + "exceed max block range: " + Args.getInstance().jsonRpcMaxBlockRange, + e.getMessage()); + } + try { + new LogFilterWrapper(new FilterRequest("0x64", "latest", null, + null, null), LATEST_BLOCK_NUM, null, false); + } catch (Exception e) { + Assert.fail(); + } + + // from = 9_000 + try { + new LogFilterWrapper(new FilterRequest("0x2328", "latest", null, + null, null), LATEST_BLOCK_NUM, null, true); + } catch (Exception e) { + Assert.fail(); + } + try { + new LogFilterWrapper(new FilterRequest("0x2328", "latest", null, + null, null), LATEST_BLOCK_NUM, null, false); + } catch (Exception e) { + Assert.fail(); + } + + try { + new LogFilterWrapper(new FilterRequest("latest", "latest", null, + null, null), LATEST_BLOCK_NUM, null, true); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + try { + new LogFilterWrapper(new FilterRequest("latest", "latest", null, + null, null), LATEST_BLOCK_NUM, null, false); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + int oldMaxBlockRange = Args.getInstance().getJsonRpcMaxBlockRange(); Args.getInstance().setJsonRpcMaxBlockRange(10_000); try { new LogFilterWrapper(new FilterRequest("0x0", "0x1f40", null, - null, null), 10_000, null, true); + null, null), LATEST_BLOCK_NUM, null, true); } catch (JsonRpcInvalidParamsException e) { Assert.fail(); } try { new LogFilterWrapper(new FilterRequest("0x0", "0x1f40", null, - null, null), 10_000, null, false); + null, null), LATEST_BLOCK_NUM, null, false); } catch (JsonRpcInvalidParamsException e) { Assert.fail(); } @@ -683,13 +780,13 @@ public void testLogFilterWrapper() { Args.getInstance().setJsonRpcMaxBlockRange(0); try { new LogFilterWrapper(new FilterRequest("0x0", "0x1f40", null, - null, null), 10_000, null, true); + null, null), LATEST_BLOCK_NUM, null, true); } catch (JsonRpcInvalidParamsException e) { Assert.fail(); } try { new LogFilterWrapper(new FilterRequest("0x0", "0x1f40", null, - null, null), 10_000, null, false); + null, null), LATEST_BLOCK_NUM, null, false); } catch (JsonRpcInvalidParamsException e) { Assert.fail(); } @@ -697,13 +794,13 @@ public void testLogFilterWrapper() { Args.getInstance().setJsonRpcMaxBlockRange(-2); try { new LogFilterWrapper(new FilterRequest("0x0", "0x1f40", null, - null, null), 10_000, null, true); + null, null), LATEST_BLOCK_NUM, null, true); } catch (JsonRpcInvalidParamsException e) { Assert.fail(); } try { new LogFilterWrapper(new FilterRequest("0x0", "0x1f40", null, - null, null), 10_000, null, false); + null, null), LATEST_BLOCK_NUM, null, false); } catch (JsonRpcInvalidParamsException e) { Assert.fail(); } @@ -726,7 +823,8 @@ public void testMaxSubTopics() { try { new LogFilterWrapper(new FilterRequest("0xbb8", "0x1f40", - null, topics.toArray(), null), 10_000, null, false); + null, topics.toArray(), null), LATEST_BLOCK_NUM, null, false); + Assert.fail("Expected to be thrown"); } catch (JsonRpcInvalidParamsException e) { Assert.assertEquals( "exceed max topics: " + Args.getInstance().getJsonRpcMaxSubTopics(), @@ -736,6 +834,7 @@ public void testMaxSubTopics() { try { tronJsonRpc.getLogs(new FilterRequest("0xbb8", "0x1f40", null, topics.toArray(), null)); + Assert.fail("Expected to be thrown"); } catch (JsonRpcInvalidParamsException e) { Assert.assertEquals( "exceed max topics: " + Args.getInstance().getJsonRpcMaxSubTopics(), @@ -747,6 +846,7 @@ public void testMaxSubTopics() { try { tronJsonRpc.newFilter(new FilterRequest("0xbb8", "0x1f40", null, topics.toArray(), null)); + Assert.fail("Expected to be thrown"); } catch (JsonRpcInvalidParamsException e) { Assert.assertEquals( "exceed max topics: " + Args.getInstance().getJsonRpcMaxSubTopics(), @@ -759,7 +859,7 @@ public void testMaxSubTopics() { Args.getInstance().setJsonRpcMaxSubTopics(2_000); try { new LogFilterWrapper(new FilterRequest("0xbb8", "0x1f40", - null, topics.toArray(), null), 10_000, null, false); + null, topics.toArray(), null), LATEST_BLOCK_NUM, null, false); } catch (JsonRpcInvalidParamsException e) { Assert.fail(); } @@ -767,10 +867,30 @@ public void testMaxSubTopics() { Args.getInstance().setJsonRpcMaxSubTopics(0); try { new LogFilterWrapper(new FilterRequest("0xbb8", "0x1f40", - null, topics.toArray(), null), 10_000, null, false); + null, topics.toArray(), null), LATEST_BLOCK_NUM, null, false); + } catch (JsonRpcInvalidParamsException e) { + Assert.fail(); + } + try { + tronJsonRpc.newFilter(new FilterRequest("0xbb8", "0x1f40", + null, topics.toArray(), null)); + } catch (Exception e) { + Assert.fail(); + } + + Args.getInstance().setJsonRpcMaxSubTopics(-2); + try { + new LogFilterWrapper(new FilterRequest("0xbb8", "0x1f40", + null, topics.toArray(), null), LATEST_BLOCK_NUM, null, false); } catch (JsonRpcInvalidParamsException e) { Assert.fail(); } + try { + tronJsonRpc.newFilter(new FilterRequest("0xbb8", "0x1f40", + null, topics.toArray(), null)); + } catch (Exception e) { + Assert.fail(); + } Args.getInstance().setJsonRpcMaxSubTopics(oldMaxSubTopics); } @@ -780,6 +900,7 @@ public void testMethodBlockRange() { try { tronJsonRpc.getLogs(new FilterRequest("0x0", "0x1f40", null, null, null)); + Assert.fail("Expected to be thrown"); } catch (JsonRpcInvalidParamsException e) { Assert.assertEquals( "exceed max block range: " + Args.getInstance().jsonRpcMaxBlockRange, @@ -814,30 +935,35 @@ public void testNewFilterFinalizedBlock() { try { tronJsonRpc.newFilter(new FilterRequest("finalized", null, null, null, null)); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("invalid block range params", e.getMessage()); } try { tronJsonRpc.newFilter(new FilterRequest(null, "finalized", null, null, null)); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("invalid block range params", e.getMessage()); } try { tronJsonRpc.newFilter(new FilterRequest("finalized", "latest", null, null, null)); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("invalid block range params", e.getMessage()); } try { tronJsonRpc.newFilter(new FilterRequest("0x1", "finalized", null, null, null)); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("invalid block range params", e.getMessage()); } try { tronJsonRpc.newFilter(new FilterRequest("finalized", "finalized", null, null, null)); + Assert.fail("Expected to be thrown"); } catch (Exception e) { Assert.assertEquals("invalid block range params", e.getMessage()); } From 37800882a86597096946d8bf34eece2a4c2af01e Mon Sep 17 00:00:00 2001 From: Asuka Date: Wed, 2 Apr 2025 19:31:25 +0800 Subject: [PATCH 1195/1197] func(cfg): add saveCancelAllUnfreezeV2Details switch description to the configuration file --- framework/src/main/resources/config.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/framework/src/main/resources/config.conf b/framework/src/main/resources/config.conf index 3236573a889..d434d9c7203 100644 --- a/framework/src/main/resources/config.conf +++ b/framework/src/main/resources/config.conf @@ -611,6 +611,9 @@ vm = { # Indicates whether the node stores featured internal transactions, such as freeze, vote and so on # saveFeaturedInternalTx = false + # Indicates whether the node stores the details of the internal transactions generated by the CANCELALLUNFREEZEV2 opcode, such as bandwidth/energy/tronpower cancel amount. + # saveCancelAllUnfreezeV2Details = false + # In rare cases, transactions that will be within the specified maximum execution time (default 10(ms)) are re-executed and packaged # longRunningTime = 10 From 4fff5402c8a595761ec4c567e5b63da8fd7c3d6a Mon Sep 17 00:00:00 2001 From: ramonliu Date: Thu, 10 Apr 2025 11:21:01 +0800 Subject: [PATCH 1196/1197] feat(tvm): remove kzg precompile --- .../tron/core/vm/PrecompiledContracts.java | 55 - .../org/tron/core/exception/TronError.java | 1 - .../common/crypto/ckzg4844/CKZG4844JNI.java | 236 - .../common/crypto/ckzg4844/CKZGException.java | 45 - .../crypto/ckzg4844/CellsAndProofs.java | 23 - .../common/crypto/ckzg4844/ProofAndY.java | 23 - .../lib/aarch64/libckzg4844jni.dylib | Bin 259656 -> 0 bytes .../resources/lib/aarch64/libckzg4844jni.so | Bin 358928 -> 0 bytes .../main/resources/lib/amd64/ckzg4844jni.dll | Bin 297542 -> 0 bytes .../resources/lib/amd64/libckzg4844jni.so | Bin 287424 -> 0 bytes .../resources/lib/x86_64/libckzg4844jni.dylib | Bin 275416 -> 0 bytes .../zen/KZGPointEvaluationInitService.java | 64 - .../kzg-trusted-setups/trusted_setup.txt | 8259 ----------------- .../runtime/vm/PrecompiledContractsTest.java | 53 - .../core/zksnark/KZGPointEvaluationTest.java | 96 - .../resources/kzg-trusted-setups/test.txt | 8259 ----------------- 16 files changed, 17114 deletions(-) delete mode 100644 crypto/src/main/java/org/tron/common/crypto/ckzg4844/CKZG4844JNI.java delete mode 100644 crypto/src/main/java/org/tron/common/crypto/ckzg4844/CKZGException.java delete mode 100644 crypto/src/main/java/org/tron/common/crypto/ckzg4844/CellsAndProofs.java delete mode 100644 crypto/src/main/java/org/tron/common/crypto/ckzg4844/ProofAndY.java delete mode 100755 crypto/src/main/resources/lib/aarch64/libckzg4844jni.dylib delete mode 100644 crypto/src/main/resources/lib/aarch64/libckzg4844jni.so delete mode 100644 crypto/src/main/resources/lib/amd64/ckzg4844jni.dll delete mode 100644 crypto/src/main/resources/lib/amd64/libckzg4844jni.so delete mode 100644 crypto/src/main/resources/lib/x86_64/libckzg4844jni.dylib delete mode 100644 framework/src/main/java/org/tron/core/zen/KZGPointEvaluationInitService.java delete mode 100644 framework/src/main/resources/kzg-trusted-setups/trusted_setup.txt delete mode 100644 framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java delete mode 100644 framework/src/test/resources/kzg-trusted-setups/test.txt diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java index 3f72e717f86..7913d7928fa 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -1,8 +1,6 @@ package org.tron.core.vm; import static java.util.Arrays.copyOfRange; -import static org.tron.common.crypto.ckzg4844.CKZG4844JNI.BLS_MODULUS; -import static org.tron.common.crypto.ckzg4844.CKZG4844JNI.FIELD_ELEMENTS_PER_BLOB; import static org.tron.common.math.Maths.max; import static org.tron.common.math.Maths.min; import static org.tron.common.runtime.vm.DataWord.WORD_SIZE; @@ -34,7 +32,6 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import org.tron.common.crypto.ckzg4844.CKZG4844JNI; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; @@ -107,7 +104,6 @@ public class PrecompiledContracts { private static final EthRipemd160 ethRipemd160 = new EthRipemd160(); private static final Blake2F blake2F = new Blake2F(); - private static final KZGPointEvaluation kzgPointEvaluation = new KZGPointEvaluation(); // FreezeV2 PrecompileContracts private static final GetChainParameter getChainParameter = new GetChainParameter(); @@ -202,9 +198,6 @@ public class PrecompiledContracts { private static final DataWord blake2FAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000000020009"); - private static final DataWord kzgPointEvaluationAddr = new DataWord( - "000000000000000000000000000000000000000000000000000000000002000a"); - public static PrecompiledContract getOptimizedContractForConstant(PrecompiledContract contract) { try { Constructor constructor = contract.getClass().getDeclaredConstructor(); @@ -286,9 +279,6 @@ public static PrecompiledContract getContractForAddress(DataWord address) { if (VMConfig.allowTvmCompatibleEvm() && address.equals(blake2FAddr)) { return blake2F; } - if (VMConfig.allowTvmBlob() && address.equals(kzgPointEvaluationAddr)) { - return kzgPointEvaluation; - } if (VMConfig.allowTvmFreezeV2()) { if (address.equals(getChainParameterAddr)) { @@ -2200,49 +2190,4 @@ public Pair execute(byte[] data) { } } - public static class KZGPointEvaluation extends PrecompiledContract { - - private static final int BLOB_VERIFY_INPUT_LENGTH = 192; - private static final byte BLOB_COMMITMENT_VERSION_KZG = 0x01; - private static final byte[] BLOB_PRECOMPILED_RETURN_VALUE = - ByteUtil.merge(ByteUtil.longTo32Bytes(FIELD_ELEMENTS_PER_BLOB), - ByteUtil.bigIntegerToBytes(BLS_MODULUS, 32)); - - @Override - public long getEnergyForData(byte[] data) { - return 50000; - } - - @Override - public Pair execute(byte[] data) { - if (data == null || data.length != BLOB_VERIFY_INPUT_LENGTH) { - return Pair.of(false, DataWord.ZERO().getData()); - } - - byte[] versionedHash = parseBytes(data, 0, 32); - byte[] z = parseBytes(data, 32, 32); - byte[] y = parseBytes(data, 64, 32); - byte[] commitment = parseBytes(data, 96, 48); - byte[] proof = parseBytes(data, 144, 48); - - byte[] hash = Sha256Hash.hash( - CommonParameter.getInstance().isECKeyCryptoEngine(), commitment); - hash[0] = BLOB_COMMITMENT_VERSION_KZG; - if (!Arrays.equals(versionedHash, hash)) { - return Pair.of(false, DataWord.ZERO().getData()); - } - - try { - if (CKZG4844JNI.verifyKzgProof(commitment, z, y, proof)) { - return Pair.of(true, BLOB_PRECOMPILED_RETURN_VALUE); - } else { - return Pair.of(false, DataWord.ZERO().getData()); - } - } catch (RuntimeException e) { - logger.warn("KZG point evaluation precompile contract failed {}", e.getMessage()); - return Pair.of(false, DataWord.ZERO().getData()); - } - } - } - } diff --git a/common/src/main/java/org/tron/core/exception/TronError.java b/common/src/main/java/org/tron/core/exception/TronError.java index 6950e7a0cf4..9d11d249476 100644 --- a/common/src/main/java/org/tron/core/exception/TronError.java +++ b/common/src/main/java/org/tron/core/exception/TronError.java @@ -44,7 +44,6 @@ public enum ErrCode { PROMETHEUS_INIT(1), TRON_NET_SERVICE_INIT(1), ZCASH_INIT(1), - CKZG_INIT(1), LOG_LOAD(1), WITNESS_INIT(1), RATE_LIMITER_INIT(1), diff --git a/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CKZG4844JNI.java b/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CKZG4844JNI.java deleted file mode 100644 index 83d12b380a0..00000000000 --- a/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CKZG4844JNI.java +++ /dev/null @@ -1,236 +0,0 @@ -package org.tron.common.crypto.ckzg4844; - -import java.io.IOException; -import java.io.InputStream; -import java.io.UncheckedIOException; -import java.math.BigInteger; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; - -public class CKZG4844JNI { - - private static final String LIBRARY_NAME = "ckzg4844jni"; - private static final String PLATFORM_NATIVE_LIBRARY_NAME = System.mapLibraryName(LIBRARY_NAME); - - /** Loads the appropriate native library based on your platform. */ - public static void loadNativeLibrary() { - String libraryResourcePath = - "/lib/" + System.getProperty("os.arch") + "/" + PLATFORM_NATIVE_LIBRARY_NAME; - InputStream libraryResource = CKZG4844JNI.class.getResourceAsStream(libraryResourcePath); - if (libraryResource == null) { - try { - System.loadLibrary(LIBRARY_NAME); - } catch (UnsatisfiedLinkError __) { - String exceptionMessage = - String.format( - "Couldn't load native library (%s). It wasn't available at %s or the library path.", - LIBRARY_NAME, libraryResourcePath); - throw new RuntimeException(exceptionMessage); - } - } else { - try { - Path tempDir = Files.createTempDirectory(LIBRARY_NAME + "@"); - tempDir.toFile().deleteOnExit(); - Path tempDll = tempDir.resolve(PLATFORM_NATIVE_LIBRARY_NAME); - tempDll.toFile().deleteOnExit(); - Files.copy(libraryResource, tempDll, StandardCopyOption.REPLACE_EXISTING); - libraryResource.close(); - System.load(tempDll.toString()); - } catch (IOException ex) { - throw new UncheckedIOException(ex); - } - } - } - - /** Scalar field modulus of BLS12-381. */ - public static final BigInteger BLS_MODULUS = - new BigInteger( - "52435875175126190479447740508185965837690552500527637822603658699938581184513"); - /** The number of bytes in a g1 point. */ - protected static final int BYTES_PER_G1 = 48; - /** The number of bytes in a g2 point. */ - protected static final int BYTES_PER_G2 = 96; - /** The number of bytes in a BLS scalar field element. */ - public static final int BYTES_PER_FIELD_ELEMENT = 32; - /** The number of bits in a BLS scalar field element. */ - protected static final int BITS_PER_FIELD_ELEMENT = 255; - /** The number of field elements in a blob. */ - public static final int FIELD_ELEMENTS_PER_BLOB = 4096; - /** The number of field elements in an extended blob. */ - protected static final int FIELD_ELEMENTS_PER_EXT_BLOB = FIELD_ELEMENTS_PER_BLOB * 2; - /** The number of field elements in a cell. */ - public static final int FIELD_ELEMENTS_PER_CELL = 64; - /** The number of bytes in a KZG commitment. */ - public static final int BYTES_PER_COMMITMENT = 48; - /** The number of bytes in a KZG proof. */ - public static final int BYTES_PER_PROOF = 48; - /** The number of bytes in a blob. */ - public static final int BYTES_PER_BLOB = FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT; - /** The number of bytes in a single cell. */ - public static final int BYTES_PER_CELL = BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_CELL; - /** The number of cells in an extended blob. */ - public static final int CELLS_PER_EXT_BLOB = - FIELD_ELEMENTS_PER_EXT_BLOB / FIELD_ELEMENTS_PER_CELL; - - private CKZG4844JNI() {} - - /** - * Loads the trusted setup from a file. Once loaded, the same setup will be used for all the - * crypto native calls. To load a new setup, free the current one by calling {@link - * #freeTrustedSetup()} and then load the new one. If no trusted setup has been loaded, all the - * crypto native calls will throw a {@link RuntimeException}. - * - * @param file a path to a trusted setup file - * @param precompute configurable value between 0-15 - * @throws CKZGException if there is a crypto error - */ - public static native void loadTrustedSetup(String file, long precompute); - - /** - * An alternative to {@link #loadTrustedSetup(String,long)}. Loads the trusted setup from method - * parameters instead of a file. - * - * @param g1MonomialBytes g1 values in monomial form as bytes - * @param g1LagrangeBytes g1 values in Lagrange form as bytes - * @param g2MonomialBytes g2 values in monomial form as bytes - * @param precompute configurable value between 0-15 - * @throws CKZGException if there is a crypto error - */ - public static native void loadTrustedSetup( - byte[] g1MonomialBytes, byte[] g1LagrangeBytes, byte[] g2MonomialBytes, long precompute); - - /** - * An alternative to {@link #loadTrustedSetup(String,long)}. Loads the trusted setup from a - * resource. - * - * @param clazz the class to use to get the resource - * @param resource the resource name that contains the trusted setup - * @param precompute configurable value between 0-15 - * @param the type of the class - * @throws CKZGException if there is a crypto error - * @throws IllegalArgumentException if the resource does not exist - */ - public static void loadTrustedSetupFromResource( - String resource, Class clazz, long precompute) { - InputStream is = clazz.getResourceAsStream(resource); - if (is == null) { - throw new IllegalArgumentException("Resource " + resource + " does not exist."); - } - - try (InputStream closableIs = is) { - Path jniWillLoadFrom = Files.createTempFile("kzg-trusted-setup", ".txt"); - jniWillLoadFrom.toFile().deleteOnExit(); - Files.copy(closableIs, jniWillLoadFrom, StandardCopyOption.REPLACE_EXISTING); - loadTrustedSetup(jniWillLoadFrom.toString(), precompute); - } catch (IOException ex) { - throw new UncheckedIOException("Error loading trusted setup from resource " + resource, ex); - } - } - - /** - * Free the current trusted setup. This method will throw an exception if no trusted setup has - * been loaded. - */ - public static native void freeTrustedSetup(); - - /** - * Calculates commitment for a given blob - * - * @param blob blob bytes - * @return the commitment - * @throws CKZGException if there is a crypto error - */ - public static native byte[] blobToKzgCommitment(byte[] blob); - - /** - * Compute proof at point z for the polynomial represented by blob. - * - * @param blob blob bytes - * @param zBytes a point - * @return an instance of {@link ProofAndY} holding the proof and the value y = f(z) - * @throws CKZGException if there is a crypto error - */ - public static native ProofAndY computeKzgProof(byte[] blob, byte[] zBytes); - - /** - * Given a blob, return the KZG proof that is used to verify it against the commitment - * - * @param blob blob bytes - * @param commitmentBytes commitment bytes - * @return the proof - * @throws CKZGException if there is a crypto error - */ - public static native byte[] computeBlobKzgProof(byte[] blob, byte[] commitmentBytes); - - /** - * Verify the proof by point evaluation for the given commitment - * - * @param commitmentBytes commitment bytes - * @param zBytes Z - * @param yBytes Y - * @param proofBytes the proof that needs verifying - * @return true if the proof is valid and false otherwise - * @throws CKZGException if there is a crypto error - */ - public static native boolean verifyKzgProof( - byte[] commitmentBytes, byte[] zBytes, byte[] yBytes, byte[] proofBytes); - - /** - * Given a blob and a KZG proof, verify that the blob data corresponds to the provided commitment. - * - * @param blob blob bytes - * @param commitmentBytes commitment bytes - * @param proofBytes proof bytes - * @return true if the proof is valid and false otherwise - * @throws CKZGException if there is a crypto error - */ - public static native boolean verifyBlobKzgProof( - byte[] blob, byte[] commitmentBytes, byte[] proofBytes); - - /** - * Given a list of blobs and blob KZG proofs, verify that they correspond to the provided - * commitments. - * - * @param blobs flattened blobs bytes - * @param commitmentsBytes flattened commitments bytes - * @param proofsBytes flattened proofs bytes - * @param count the number of blobs (should be same as the number of proofs and commitments) - * @return true if the proof is valid and false otherwise - * @throws CKZGException if there is a crypto error - */ - public static native boolean verifyBlobKzgProofBatch( - byte[] blobs, byte[] commitmentsBytes, byte[] proofsBytes, long count); - - /** - * Get the cells and proofs for a given blob. - * - * @param blob the blob to get cells/proofs for - * @return a CellsAndProofs object - * @throws CKZGException if there is a crypto error - */ - public static native CellsAndProofs computeCellsAndKzgProofs(byte[] blob); - - /** - * Given at least 50% of cells, reconstruct the missing cells/proofs. - * - * @param cellIndices the identifiers for the cells you have - * @param cells the cells you have - * @return all cells/proofs for that blob - * @throws CKZGException if there is a crypto error - */ - public static native CellsAndProofs recoverCellsAndKzgProofs(long[] cellIndices, byte[] cells); - - /** - * Verify that multiple cells' proofs are valid. - * - * @param commitmentsBytes the commitments for each cell - * @param cellIndices the column index for each cell - * @param cells the cells to verify - * @param proofsBytes the proof for each cell - * @return true if the cells are valid with respect to the given commitments - * @throws CKZGException if there is a crypto error - */ - public static native boolean verifyCellKzgProofBatch( - byte[] commitmentsBytes, long[] cellIndices, byte[] cells, byte[] proofsBytes); -} diff --git a/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CKZGException.java b/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CKZGException.java deleted file mode 100644 index 8ea9edf4548..00000000000 --- a/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CKZGException.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.tron.common.crypto.ckzg4844; - - -import java.util.Arrays; - -/** Thrown when there is an error in the underlying c-kzg library. */ -public class CKZGException extends RuntimeException { - - private final CKZGError error; - private final String errorMessage; - - public CKZGException(int errorCode, String errorMessage) { - super(String.format("%s (%s)", errorMessage, CKZGError.fromErrorCode(errorCode))); - this.error = CKZGError.fromErrorCode(errorCode); - this.errorMessage = errorMessage; - } - - public CKZGError getError() { - return error; - } - - public String getErrorMessage() { - return errorMessage; - } - - public enum CKZGError { - UNKNOWN(0), - C_KZG_BADARGS(1), - C_KZG_ERROR(2), - C_KZG_MALLOC(3); - - public final int errorCode; - - CKZGError(int errorCode) { - this.errorCode = errorCode; - } - - public static CKZGError fromErrorCode(int errorCode) { - return Arrays.stream(CKZGError.values()) - .filter(error -> error.errorCode == errorCode) - .findFirst() - .orElse(UNKNOWN); - } - } -} diff --git a/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CellsAndProofs.java b/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CellsAndProofs.java deleted file mode 100644 index 5d47538d73a..00000000000 --- a/crypto/src/main/java/org/tron/common/crypto/ckzg4844/CellsAndProofs.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.tron.common.crypto.ckzg4844; - -public class CellsAndProofs { - private final byte[] cells; - private final byte[] proofs; - - public CellsAndProofs(final byte[] cells, final byte[] proofs) { - this.cells = cells; - this.proofs = proofs; - } - - public byte[] getCells() { - return cells; - } - - public byte[] getProofs() { - return proofs; - } - - public static CellsAndProofs of(final byte[] cells, final byte[] proofs) { - return new CellsAndProofs(cells, proofs); - } -} diff --git a/crypto/src/main/java/org/tron/common/crypto/ckzg4844/ProofAndY.java b/crypto/src/main/java/org/tron/common/crypto/ckzg4844/ProofAndY.java deleted file mode 100644 index fdb093c1232..00000000000 --- a/crypto/src/main/java/org/tron/common/crypto/ckzg4844/ProofAndY.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.tron.common.crypto.ckzg4844; - -public class ProofAndY { - private final byte[] proof; - private final byte[] y; - - public ProofAndY(byte[] proof, byte[] y) { - this.proof = proof; - this.y = y; - } - - public byte[] getProof() { - return proof; - } - - public byte[] getY() { - return y; - } - - public static ProofAndY of(byte[] proof, byte[] y) { - return new ProofAndY(proof, y); - } -} diff --git a/crypto/src/main/resources/lib/aarch64/libckzg4844jni.dylib b/crypto/src/main/resources/lib/aarch64/libckzg4844jni.dylib deleted file mode 100755 index 965485287527713798cb3c18b136d2a778c132dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 259656 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ö-Y|A(tnY0$~~XU}$LoyHmOnYgoX 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ʫrslSgt{KFxkvtnzVOR<7Pj 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≶PorzbUgEt6*kWJq}AD2;jI=_ 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

    lywdrx_@|%Pn$GGtsdG?LSnU!1Fy|d| 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

    hFt0Q5xfW59L4u_L_WY-K#ybi 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 Z?#<+DFzH@?={r{I^yYo diff --git a/crypto/src/main/resources/lib/x86_64/libckzg4844jni.dylib b/crypto/src/main/resources/lib/x86_64/libckzg4844jni.dylib deleted file mode 100644 index b15fe5ec7521dc5fca44ce512136d43e98d2e398..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 275416 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

    -g8Ihs3+8b!^g1Ffi-+dJ)wra z>IpSu2O=|aF?XU>V1}N}mp7&&q?tA=%d;j%fM27H9`iuu_{;Zx>RAJUqGhINnWI1j zw`OD7X&f&>PC)q(kQ<(dqyi)rF^QL80h91~_+%s%YnjiMqDFk1XWfIv%z(tF$bDMo ze=m^Rvx{&;N+rMI9^q#e<9CRRC~h$6(y-lwkA5C9DE=|{DS)t#pQ_I9UN0jP>0ZFt z2jf<(Br~lm*HLx_)R|+uW~0`z>AVKg@dXoXs5qLZ52*=l^1I=B?a(U`A)hl>tKeKE z2q=>gbBQm>`iZbOyLvcnD^>vc4Id(?a0&)T;pZrR_n*I&_b=^kN67fMoo{JbfLL8Es$z0u9gEyFe&E5zhxgmF!!da?{SB+S<*446@c;t zdK1L|+DcmG(fbzkLG9^M6`u#L1T;`+*3TFC;KL6sDERwMwoF{?ezjHg1>>^UFm zcA;3IOAC;Ln1B4A${3PB3@k%EtYgG<*7kVjNI zLUes0X2ha9Xg-Hd1 z9AJ$c6_;mNQQ61dSUB024B#GU`1!I;TWSp#_ZDm*kV?_Q;~VZ?g0X}x(pA}Pn0pB= zj9mq@!yMlTk&5_w+xVTX!gl`hlPR-$LENj;c`RufTLy%{+K>R>X8(o*w786MupoU6 zL3b3lD8@{9c$fKtz#x-)IwO0LVX2fJK{x)>9{&|7?M~R1QSKMvWGc@jQqEye8}YGT zGo>LNGJZa(*?|xAv>Ha666_4%n)?f7Sj9@)ZQg}9F{WU%?KZ#0HwgVe>YN4&ejfCo zJ6O^&Um@pH6oHu^`#aIC3X;{~yHC0hUh?P^{qn6q_Ny4Uz5_ zLdoZXm=VSR8LG)*nQ8#x$X@W1I4ObR7%Ndo_!Hwyk_O8h+*3(eNnSxr9x`KZTEI

    6?5d^0ClNtKe*%{NHT^E^u~WVzJpG6ci&DOUfa^ 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 diff --git a/framework/src/main/java/org/tron/core/zen/KZGPointEvaluationInitService.java b/framework/src/main/java/org/tron/core/zen/KZGPointEvaluationInitService.java deleted file mode 100644 index 6a7bbe7ea7c..00000000000 --- a/framework/src/main/java/org/tron/core/zen/KZGPointEvaluationInitService.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.tron.core.zen; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.concurrent.atomic.AtomicBoolean; -import javax.annotation.PostConstruct; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.io.FileUtils; -import org.springframework.stereotype.Component; -import org.tron.common.crypto.ckzg4844.CKZG4844JNI; -import org.tron.core.exception.TronError; - -@Slf4j -@Component -public class KZGPointEvaluationInitService { - - private static final AtomicBoolean loaded = new AtomicBoolean(false); - - @PostConstruct - private void init() { - initCKZG4844(); - } - - public static void freeSetup() { - if (loaded.compareAndSet(true, false)) { - CKZG4844JNI.freeTrustedSetup(); - } - } - - public static void initCKZG4844() { - if (loaded.compareAndSet(false, true)) { - logger.info("init ckzg 4844 begin"); - - try { - CKZG4844JNI.loadNativeLibrary(); - - String setupFile = getSetupFile("trusted_setup.txt"); - - CKZG4844JNI.loadTrustedSetup(setupFile, 0); - } catch (Exception e) { - throw new TronError(e, TronError.ErrCode.CKZG_INIT); - } - - logger.info("init ckzg 4844 done"); - } - } - - private static String getSetupFile(String fileName) { - InputStream in = Thread.currentThread().getContextClassLoader() - .getResourceAsStream("kzg-trusted-setups" + File.separator + fileName); - File fileOut = new File(System.getProperty("java.io.tmpdir") - + File.separator + fileName + "." + System.currentTimeMillis()); - try { - FileUtils.copyToFile(in, fileOut); - } catch (IOException e) { - logger.error(e.getMessage(), e); - } - if (fileOut.exists()) { - fileOut.deleteOnExit(); - } - return fileOut.getAbsolutePath(); - } -} \ No newline at end of file diff --git a/framework/src/main/resources/kzg-trusted-setups/trusted_setup.txt b/framework/src/main/resources/kzg-trusted-setups/trusted_setup.txt deleted file mode 100644 index 5ecccf5e5e5..00000000000 --- a/framework/src/main/resources/kzg-trusted-setups/trusted_setup.txt +++ /dev/null @@ -1,8259 +0,0 @@ -4096 -65 -a0413c0dcafec6dbc9f47d66785cf1e8c981044f7d13cfe3e4fcbb71b5408dfde6312493cb3c1d30516cb3ca88c03654 -8b997fb25730d661918371bb41f2a6e899cac23f04fc5365800b75433c0a953250e15e7a98fb5ca5cc56a8cd34c20c57 -83302852db89424d5699f3f157e79e91dc1380f8d5895c5a772bb4ea3a5928e7c26c07db6775203ce33e62a114adaa99 -a759c48b7e4a685e735c01e5aa6ef9c248705001f470f9ad856cd87806983e917a8742a3bd5ee27db8d76080269b7c83 -967f8dc45ebc3be14c8705f43249a30ff48e96205fb02ae28daeab47b72eb3f45df0625928582aa1eb4368381c33e127 -a418eb1e9fb84cb32b370610f56f3cb470706a40ac5a47c411c464299c45c91f25b63ae3fcd623172aa0f273c0526c13 -8f44e3f0387293bc7931e978165abbaed08f53acd72a0a23ac85f6da0091196b886233bcee5b4a194db02f3d5a9b3f78 -97173434b336be73c89412a6d70d416e170ea355bf1956c32d464090b107c090ef2d4e1a467a5632fbc332eeb679bf2d -a24052ad8d55ad04bc5d951f78e14213435681594110fd18173482609d5019105b8045182d53ffce4fc29fc8810516c1 -b950768136b260277590b5bec3f56bbc2f7a8bc383d44ce8600e85bf8cf19f479898bcc999d96dfbd2001ede01d94949 -92ab8077871037bd3b57b95cbb9fb10eb11efde9191690dcac655356986fd02841d8fdb25396faa0feadfe3f50baf56d -a79b096dff98038ac30f91112dd14b78f8ad428268af36d20c292e2b3b6d9ed4fb28480bb04e465071cc67d05786b6d1 -b9ff71461328f370ce68bf591aa7fb13027044f42a575517f3319e2be4aa4843fa281e756d0aa5645428d6dfa857cef2 -8d765808c00b3543ff182e2d159c38ae174b12d1314da88ea08e13bd9d1c37184cb515e6bf6420531b5d41767987d7ce -b8c9a837d20c3b53e6f578e4a257bb7ef8fc43178614ec2a154915b267ad2be135981d01ed2ee1b5fbd9d9bb27f0800a -a9773d92cf23f65f98ef68f6cf95c72b53d0683af2f9bf886bb9036e4a38184b1131b26fd24397910b494fbef856f3aa -b41ebe38962d112da4a01bf101cb248d808fbd50aaf749fc7c151cf332032eb3e3bdbd716db899724b734d392f26c412 -90fbb030167fb47dcc13d604a726c0339418567c1d287d1d87423fa0cb92eec3455fbb46bcbe2e697144a2d3972142e4 -b11d298bd167464b35fb923520d14832bd9ed50ed841bf6d7618424fd6f3699190af21759e351b89142d355952149da1 -8bc36066f69dc89f7c4d1e58d67497675050c6aa002244cebd9fc957ec5e364c46bab4735ea3db02b73b3ca43c96e019 -ab7ab92c5d4d773068e485aa5831941ebd63db7118674ca38089635f3b4186833af2455a6fb9ed2b745df53b3ce96727 -af191ca3089892cb943cd97cf11a51f38e38bd9be50844a4e8da99f27e305e876f9ed4ab0628e8ae3939066b7d34a15f -a3204c1747feabc2c11339a542195e7cb6628fd3964f846e71e2e3f2d6bb379a5e51700682ea1844eba12756adb13216 -903a29883846b7c50c15968b20e30c471aeac07b872c40a4d19eb1a42da18b649d5bbfde4b4cf6225d215a461b0deb6d -8e6e9c15ffbf1e16e5865a5fef7ed751dc81957a9757b535cb38b649e1098cda25d42381dc4f776778573cdf90c3e6e0 -a8f6dd26100b512a8c96c52e00715c4b2cb9ac457f17aed8ffe1cf1ea524068fe5a1ddf218149845fc1417b789ecfc98 -a5b0ffc819451ea639cfd1c18cbc9365cc79368d3b2e736c0ae54eba2f0801e6eb0ee14a5f373f4a70ca463bdb696c09 -879f91ccd56a1b9736fbfd20d8747354da743fb121f0e308a0d298ff0d9344431890e41da66b5009af3f442c636b4f43 -81bf3a2d9755e206b515a508ac4d1109bf933c282a46a4ae4a1b4cb4a94e1d23642fad6bd452428845afa155742ade7e -8de778d4742f945df40004964e165592f9c6b1946263adcdd5a88b00244bda46c7bb49098c8eb6b3d97a0dd46148a8ca -b7a57b21d13121907ee28c5c1f80ee2e3e83a3135a8101e933cf57171209a96173ff5037f5af606e9fd6d066de6ed693 -b0877d1963fd9200414a38753dffd9f23a10eb3198912790d7eddbc9f6b477019d52ddd4ebdcb9f60818db076938a5a9 -88da2d7a6611bc16adc55fc1c377480c828aba4496c645e3efe0e1a67f333c05a0307f7f1d2df8ac013602c655c6e209 -95719eb02e8a9dede1a888c656a778b1c69b7716fbe3d1538fe8afd4a1bc972183c7d32aa7d6073376f7701df80116d8 -8e8a1ca971f2444b35af3376e85dccda3abb8e8e11d095d0a4c37628dfe5d3e043a377c3de68289ef142e4308e9941a0 -b720caaff02f6d798ac84c4f527203e823ff685869e3943c979e388e1c34c3f77f5c242c6daa7e3b30e511aab917b866 -86040d55809afeec10e315d1ad950d269d37cfee8c144cd8dd4126459e3b15a53b3e68df5981df3c2346d23c7b4baaf4 -82d8cabf13ab853db0377504f0aec00dba3a5cd3119787e8ad378ddf2c40b022ecfc67c642b7acc8c1e3dd03ab50993e -b8d873927936719d2484cd03a6687d65697e17dcf4f0d5aed6f5e4750f52ef2133d4645894e7ebfc4ef6ce6788d404c8 -b1235594dbb15b674a419ff2b2deb644ad2a93791ca05af402823f87114483d6aa1689b7a9bea0f547ad12fe270e4344 -a53fda86571b0651f5affb74312551a082fffc0385cfd24c1d779985b72a5b1cf7c78b42b4f7e51e77055f8e5e915b00 -b579adcfd9c6ef916a5a999e77a0cb21d378c4ea67e13b7c58709d5da23a56c2e54218691fc4ac39a4a3d74f88cc31f7 -ab79e584011713e8a2f583e483a91a0c2a40771b77d91475825b5acbea82db4262132901cb3e4a108c46d7c9ee217a4e -a0fe58ea9eb982d7654c8aaf9366230578fc1362f6faae0594f8b9e659bcb405dff4aac0c7888bbe07f614ecf0d800a6 -867e50e74281f28ecd4925560e2e7a6f8911b135557b688254623acce0dbc41e23ac3e706a184a45d54c586edc416eb0 -89f81b61adda20ea9d0b387a36d0ab073dc7c7cbff518501962038be19867042f11fcc7ff78096e5d3b68c6d8dc04d9b -a58ee91bb556d43cf01f1398c5811f76dc0f11efdd569eed9ef178b3b0715e122060ec8f945b4dbf6eebfa2b90af6fa6 -ac460be540f4c840def2eef19fc754a9af34608d107cbadb53334cf194cc91138d53b9538fcd0ec970b5d4aa455b224a -b09b91f929de52c09d48ca0893be6eb44e2f5210a6c394689dc1f7729d4be4e11d0474b178e80cea8c2ac0d081f0e811 -8d37a442a76b06a02a4e64c2504aea72c8b9b020ab7bcc94580fe2b9603c7c50d7b1e9d70d2a7daea19c68667e8f8c31 -a9838d4c4e3f3a0075a952cf7dd623307ec633fcc81a7cf9e52e66c31780de33dbb3d74c320dc7f0a4b72f7a49949515 -a44766b6251af458fe4f5f9ed1e02950f35703520b8656f09fc42d9a2d38a700c11a7c8a0436ac2e5e9f053d0bb8ff91 -ad78d9481c840f5202546bea0d13c776826feb8b1b7c72e83d99a947622f0bf38a4208551c4c41beb1270d7792075457 -b619ffa8733b470039451e224b777845021e8dc1125f247a4ff2476cc774657d0ff9c5279da841fc1236047de9d81c60 -af760b0a30a1d6af3bc5cd6686f396bd41779aeeb6e0d70a09349bd5da17ca2e7965afc5c8ec22744198fbe3f02fb331 -a0cc209abdb768b589fcb7b376b6e1cac07743288c95a1cf1a0354b47f0cf91fca78a75c1fcafa6f5926d6c379116608 -864add673c89c41c754eeb3cd8dcff5cdde1d739fce65c30e474a082bb5d813cba6412e61154ce88fdb6c12c5d9be35b -b091443b0ce279327dc37cb484e9a5b69b257a714ce21895d67539172f95ffa326903747b64a3649e99aea7bb10d03f7 -a8c452b8c4ca8e0a61942a8e08e28f17fb0ef4c5b018b4e6d1a64038280afa2bf1169202f05f14af24a06ca72f448ccd -a23c24721d18bc48d5dcf70effcbef89a7ae24e67158d70ae1d8169ee75d9a051d34b14e9cf06488bac324fe58549f26 -92a730e30eb5f3231feb85f6720489dbb1afd42c43f05a1610c6b3c67bb949ec8fde507e924498f4ffc646f7b07d9123 -8dbe5abf4031ec9ba6bb06d1a47dd1121fb9e03b652804069250967fd5e9577d0039e233441b7f837a7c9d67ba18c28e -aa456bcfef6a21bb88181482b279df260297b3778e84594ebddbdf337e85d9e3d46ca1d0b516622fb0b103df8ec519b7 -a3b31ae621bd210a2b767e0e6f22eb28fe3c4943498a7e91753225426168b9a26da0e02f1dc5264da53a5ad240d9f51b -aa8d66857127e6e71874ce2202923385a7d2818b84cb73a6c42d71afe70972a70c6bdd2aad1a6e8c5e4ca728382a8ea8 -ac7e8e7a82f439127a5e40558d90d17990f8229852d21c13d753c2e97facf077cf59582b603984c3dd3faebd80aff4f5 -93a8bcf4159f455d1baa73d2ef2450dcd4100420de84169bbe28b8b7a5d1746273f870091a87a057e834f754f34204b1 -89d0ebb287c3613cdcae7f5acc43f17f09c0213fc40c074660120b755d664109ffb9902ed981ede79e018ddb0c845698 -a87ccbfad431406aadbee878d9cf7d91b13649d5f7e19938b7dfd32645a43b114eef64ff3a13201398bd9b0337832e5a -833c51d0d0048f70c3eefb4e70e4ff66d0809c41838e8d2c21c288dd3ae9d9dfaf26d1742bf4976dab83a2b381677011 -8bcd6b1c3b02fffead432e8b1680bad0a1ac5a712d4225e220690ee18df3e7406e2769e1f309e2e803b850bc96f0e768 -b61e3dbd88aaf4ff1401521781e2eea9ef8b66d1fac5387c83b1da9e65c2aa2a56c262dea9eceeb4ad86c90211672db0 -866d3090db944ecf190dd0651abf67659caafd31ae861bab9992c1e3915cb0952da7c561cc7e203560a610f48fae633b -a5e8971543c14274a8dc892b0be188c1b4fbc75c692ed29f166e0ea80874bc5520c2791342b7c1d2fb5dd454b03b8a5b -8f2f9fc50471bae9ea87487ebd1bc8576ef844cc42d606af5c4c0969670fdf2189afd643e4de3145864e7773d215f37f -b1bb0f2527db6d51f42b9224383c0f96048bbc03d469bf01fe1383173ef8b1cc9455d9dd8ba04d46057f46949bfc92b5 -aa7c99d906b4d7922296cfe2520473fc50137c03d68b7865c5bfb8adbc316b1034310ec4b5670c47295f4a80fb8d61e9 -a5d1da4d6aba555919df44cbaa8ff79378a1c9e2cfdfbf9d39c63a4a00f284c5a5724e28ecbc2d9dba27fe4ee5018bd5 -a8db53224f70af4d991b9aae4ffe92d2aa5b618ad9137784b55843e9f16cefbfd25ada355d308e9bbf55f6d2f7976fb3 -b6536c4232bb20e22af1a8bb12de76d5fec2ad9a3b48af1f38fa67e0f8504ef60f305a73d19385095bb6a9603fe29889 -87f7e371a1817a63d6838a8cf4ab3a8473d19ce0d4f40fd013c03d5ddd5f4985df2956531cc9f187928ef54c68f4f9a9 -ae13530b1dbc5e4dced9d909ea61286ec09e25c12f37a1ed2f309b0eb99863d236c3b25ed3484acc8c076ad2fa8cd430 -98928d850247c6f7606190e687d5c94a627550198dbdbea0161ef9515eacdb1a0f195cae3bb293112179082daccf8b35 -918528bb8e6a055ad4db6230d3a405e9e55866da15c4721f5ddd1f1f37962d4904aad7a419218fe6d906fe191a991806 -b71e31a06afe065773dd3f4a6e9ef81c3292e27a3b7fdfdd452d03e05af3b6dd654c355f7516b2a93553360c6681a73a -8870b83ab78a98820866f91ac643af9f3ff792a2b7fda34185a9456a63abdce42bfe8ad4dc67f08a6392f250d4062df4 -91eea1b668e52f7a7a5087fabf1cab803b0316f78d9fff469fbfde2162f660c250e4336a9eea4cb0450bd30ac067bc8b -8b74990946de7b72a92147ceac1bd9d55999a8b576e8df68639e40ed5dc2062cfcd727903133de482b6dca19d0aaed82 -8ebad537fece090ebbab662bdf2618e21ca30cf6329c50935e8346d1217dcbe3c1fe1ea28efca369c6003ce0a94703c1 -a8640479556fb59ebd1c40c5f368fbd960932fdbb782665e4a0e24e2bdb598fc0164ce8c0726d7759cfc59e60a62e182 -a9a52a6bf98ee4d749f6d38be2c60a6d54b64d5cbe4e67266633dc096cf28c97fe998596707d31968cbe2064b72256bf -847953c48a4ce6032780e9b39d0ed4384e0be202c2bbe2dfda3910f5d87aa5cd3c2ffbfcfae4dddce16d6ab657599b95 -b6f6e1485d3ec2a06abaecd23028b200b2e4a0096c16144d07403e1720ff8f9ba9d919016b5eb8dc5103880a7a77a1d3 -98dfc2065b1622f596dbe27131ea60bef7a193b12922cecb27f8c571404f483014f8014572e86ae2e341ab738e4887ef -acb0d205566bacc87bbe2e25d10793f63f7a1f27fd9e58f4f653ceae3ffeba511eaf658e068fad289eeb28f9edbeb35b -ae4411ed5b263673cee894c11fe4abc72a4bf642d94022a5c0f3369380fcdfc1c21e277f2902972252503f91ada3029a -ac4a7a27ba390a75d0a247d93d4a8ef1f0485f8d373a4af4e1139369ec274b91b3464d9738eeaceb19cd6f509e2f8262 -87379c3bf231fdafcf6472a79e9e55a938d851d4dd662ab6e0d95fd47a478ed99e2ad1e6e39be3c0fc4f6d996a7dd833 -81316904b035a8bcc2041199a789a2e6879486ba9fddcba0a82c745cc8dd8374a39e523b91792170cd30be7aa3005b85 -b8206809c6cd027ed019f472581b45f7e12288f89047928ba32b4856b6560ad30395830d71e5e30c556f6f182b1fe690 -88d76c028f534a62e019b4a52967bb8642ede6becfa3807be68fdd36d366fc84a4ac8dc176e80a68bc59eb62caf5dff9 -8c3b8be685b0f8aad131ee7544d0e12f223f08a6f8edaf464b385ac644e0ddc9eff7cc7cb5c1b50ab5d71ea0f41d2213 -8d91410e004f76c50fdc05784157b4d839cb5090022c629c7c97a5e0c3536eeafee17a527b54b1165c3cd81774bb54ce -b25c2863bc28ec5281ce800ddf91a7e1a53f4c6d5da1e6c86ef4616e93bcf55ed49e297216d01379f5c6e7b3c1e46728 -865f7b09ac3ca03f20be90c48f6975dd2588838c2536c7a3532a6aa5187ed0b709cd03d91ff4048061c10d0aa72b69ce -b3f7477c90c11596eb4f8bbf34adbcb832638c4ff3cdd090d4d477ee50472ac9ddaf5be9ad7eca3f148960d362bbd098 -8db35fd53fca04faecd1c76a8227160b3ab46ac1af070f2492445a19d8ff7c25bbaef6c9fa0c8c088444561e9f7e4eb2 -a478b6e9d058a2e01d2fc053b739092e113c23a6a2770a16afbef044a3709a9e32f425ace9ba7981325f02667c3f9609 -98caa6bd38916c08cf221722a675a4f7577f33452623de801d2b3429595f988090907a7e99960fff7c076d6d8e877b31 -b79aaaacefc49c3038a14d2ac468cfec8c2161e88bdae91798d63552cdbe39e0e02f9225717436b9b8a40a022c633c6e -845a31006c680ee6a0cc41d3dc6c0c95d833fcf426f2e7c573fa15b2c4c641fbd6fe5ebb0e23720cc3467d6ee1d80dc4 -a1bc287e272cf8b74dbf6405b3a5190883195806aa351f1dc8e525aa342283f0a35ff687e3b434324dedee74946dd185 -a4fd2dc8db75d3783a020856e2b3aa266dc6926e84f5c491ef739a3bddd46dc8e9e0fc1177937839ef1b18d062ffbb9e -acbf0d3c697f57c202bb8c5dc4f3fc341b8fc509a455d44bd86acc67cad2a04495d5537bcd3e98680185e8aa286f2587 -a5caf423a917352e1b8e844f5968a6da4fdeae467d10c6f4bbd82b5eea46a660b82d2f5440d3641c717b2c3c9ed0be52 -8a39d763c08b926599ab1233219c49c825368fad14d9afc7c0c039224d37c00d8743293fd21645bf0b91eaf579a99867 -b2b53a496def0ba06e80b28f36530fbe0fb5d70a601a2f10722e59abee529369c1ae8fd0f2db9184dd4a2519bb832d94 -a73980fcef053f1b60ebbb5d78ba6332a475e0b96a0c724741a3abf3b59dd344772527f07203cf4c9cb5155ebed81fa0 -a070d20acce42518ece322c9db096f16aed620303a39d8d5735a0df6e70fbeceb940e8d9f5cc38f3314b2240394ec47b -a50cf591f522f19ca337b73089557f75929d9f645f3e57d4f241e14cdd1ea3fb48d84bcf05e4f0377afbb789fbdb5d20 -82a5ffce451096aca8eeb0cd2ae9d83db3ed76da3f531a80d9a70a346359bf05d74863ce6a7c848522b526156a5e20cd -88e0e84d358cbb93755a906f329db1537c3894845f32b9b0b691c29cbb455373d9452fadd1e77e20a623f6eaf624de6f -aa07ac7b84a6d6838826e0b9e350d8ec75e398a52e9824e6b0da6ae4010e5943fec4f00239e96433f291fef9d1d1e609 -ac8887bf39366034bc63f6cc5db0c26fd27307cbc3d6cce47894a8a019c22dd51322fb5096edc018227edfafc053a8f6 -b7d26c26c5b33f77422191dca94977588ab1d4b9ce7d0e19c4a3b4cd1c25211b78c328dbf81e755e78cd7d1d622ad23e -99a676d5af49f0ba44047009298d8474cabf2d5bca1a76ba21eff7ee3c4691a102fdefea27bc948ccad8894a658abd02 -b0d09a91909ab3620c183bdf1d53d43d39eb750dc7a722c661c3de3a1a5d383ad221f71bae374f8a71867505958a3f76 -84681a883de8e4b93d68ac10e91899c2bbb815ce2de74bb48a11a6113b2a3f4df8aceabda1f5f67bc5aacac8c9da7221 -9470259957780fa9b43521fab3644f555f5343281c72582b56d2efd11991d897b3b481cafa48681c5aeb80c9663b68f7 -ab1b29f7ece686e6fa968a4815da1d64f3579fed3bc92e1f3e51cd13a3c076b6cf695ed269d373300a62463dc98a4234 -8ab415bfcd5f1061f7687597024c96dd9c7cb4942b5989379a7a3b5742f7d394337886317659cbeacaf030234a24f972 -b9b524aad924f9acc63d002d617488f31b0016e0f0548f050cada285ce7491b74a125621638f19e9c96eabb091d945be -8c4c373e79415061837dd0def4f28a2d5d74d21cb13a76c9049ad678ca40228405ab0c3941df49249847ecdefc1a5b78 -a8edf4710b5ab2929d3db6c1c0e3e242261bbaa8bcec56908ddadd7d2dad2dca9d6eb9de630b960b122ebeea41040421 -8d66bb3b50b9df8f373163629f9221b3d4b6980a05ea81dc3741bfe9519cf3ebba7ab98e98390bae475e8ede5821bd5c -8d3c21bae7f0cfb97c56952bb22084b58e7bb718890935b73103f33adf5e4d99cd262f929c6eeab96209814f0dbae50a -a5c66cfab3d9ebf733c4af24bebc97070e7989fe3c73e79ac85fb0e4d40ae44fb571e0fad4ad72560e13ed453900d14f -9362e6b50b43dbefbc3254471372297b5dcce809cd3b60bf74a1268ab68bdb50e46e462cbd78f0d6c056330e982846af -854630d08e3f0243d570cc2e856234cb4c1a158d9c1883bf028a76525aaa34be897fe918d5f6da9764a3735fa9ebd24a -8c7d246985469ff252c3f4df6c7c9196fc79f05c1c66a609d84725c78001d0837c7a7049394ba5cf7e863e2d58af8417 -ae050271e01b528925302e71903f785b782f7bf4e4e7a7f537140219bc352dc7540c657ed03d3a297ad36798ecdb98cd -8d2ae9179fcf2b0c69850554580b52c1f4a5bd865af5f3028f222f4acad9c1ad69a8ef6c7dc7b03715ee5c506b74325e -b8ef8de6ce6369a8851cd36db0ccf00a85077e816c14c4e601f533330af9e3acf0743a95d28962ed8bfcfc2520ef3cfe -a6ecad6fdfb851b40356a8b1060f38235407a0f2706e7b8bb4a13465ca3f81d4f5b99466ac2565c60af15f022d26732e -819ff14cdea3ab89d98e133cd2d0379361e2e2c67ad94eeddcdb9232efd509f51d12f4f03ebd4dd953bd262a886281f7 -8561cd0f7a6dbcddd83fcd7f472d7dbcba95b2d4fb98276f48fccf69f76d284e626d7e41314b633352df8e6333fd52a1 -b42557ccce32d9a894d538c48712cb3e212d06ac05cd5e0527ccd2db1078ee6ae399bf6a601ffdab1f5913d35fc0b20c -89b4008d767aad3c6f93c349d3b956e28307311a5b1cec237e8d74bb0dee7e972c24f347fd56afd915a2342bd7bc32f0 -877487384b207e53f5492f4e36c832c2227f92d1bb60542cfeb35e025a4a7afc2b885fae2528b33b40ab09510398f83e -8c411050b63c9053dd0cd81dacb48753c3d7f162028098e024d17cd6348482703a69df31ad6256e3d25a8bbf7783de39 -a8506b54a88d17ac10fb1b0d1fe4aa40eae7553a064863d7f6b52ccc4236dd4b82d01dca6ba87da9a239e3069ba879fb -b1a24caef9df64750c1350789bb8d8a0db0f39474a1c74ea9ba064b1516db6923f00af8d57c632d58844fb8786c3d47a -959d6e255f212b0708c58a2f75cb1fe932248c9d93424612c1b8d1e640149656059737e4db2139afd5556bcdacf3eda2 -84525af21a8d78748680b6535bbc9dc2f0cf9a1d1740d12f382f6ecb2e73811d6c1da2ad9956070b1a617c61fcff9fe5 -b74417d84597a485d0a8e1be07bf78f17ebb2e7b3521b748f73935b9afbbd82f34b710fb7749e7d4ab55b0c7f9de127d -a4a9aecb19a6bab167af96d8b9d9aa5308eab19e6bfb78f5a580f9bf89bdf250a7b52a09b75f715d651cb73febd08e84 -9777b30be2c5ffe7d29cc2803a562a32fb43b59d8c3f05a707ab60ec05b28293716230a7d264d7cd9dd358fc031cc13e -95dce7a3d4f23ac0050c510999f5fbf8042f771e8f8f94192e17bcbfa213470802ebdbe33a876cb621cf42e275cbfc8b -b0b963ebcbbee847ab8ae740478544350b3ac7e86887e4dfb2299ee5096247cd2b03c1de74c774d9bde94ae2ee2dcd59 -a4ab20bafa316030264e13f7ef5891a2c3b29ab62e1668fcb5881f50a9acac6adbe3d706c07e62f2539715db768f6c43 -901478a297669d608e406fe4989be75264b6c8be12169aa9e0ad5234f459ca377f78484ffd2099a2fe2db5e457826427 -88c76e5c250810c057004a03408b85cd918e0c8903dc55a0dd8bb9b4fc2b25c87f9b8cf5943eb19fbbe99d36490050c5 -91607322bbad4a4f03fc0012d0821eff5f8c516fda45d1ec1133bface6f858bf04b25547be24159cab931a7aa08344d4 -843203e07fce3c6c81f84bc6dc5fb5e9d1c50c8811ace522dc66e8658433a0ef9784c947e6a62c11bf705307ef05212e -91dd8813a5d6dddcda7b0f87f672b83198cd0959d8311b2b26fb1fae745185c01f796fbd03aad9db9b58482483fdadd8 -8d15911aacf76c8bcd7136e958febd6963104addcd751ce5c06b6c37213f9c4fb0ffd4e0d12c8e40c36d658999724bfd -8a36c5732d3f1b497ebe9250610605ee62a78eaa9e1a45f329d09aaa1061131cf1d9df00f3a7d0fe8ad614a1ff9caaae -a407d06affae03660881ce20dab5e2d2d6cddc23cd09b95502a9181c465e57597841144cb34d22889902aff23a76d049 -b5fd856d0578620a7e25674d9503be7d97a2222900e1b4738c1d81ff6483b144e19e46802e91161e246271f90270e6cf -91b7708869cdb5a7317f88c0312d103f8ce90be14fb4f219c2e074045a2a83636fdc3e69e862049fc7c1ef000e832541 -b64719cc5480709d1dae958f1d3082b32a43376da446c8f9f64cb02a301effc9c34d9102051733315a8179aed94d53cc -94347a9542ff9d18f7d9eaa2f4d9b832d0e535fe49d52aa2de08aa8192400eddabdb6444a2a78883e27c779eed7fdf5a -840ef44a733ff1376466698cd26f82cf56bb44811e196340467f932efa3ae1ef9958a0701b3b032f50fd9c1d2aed9ab5 -90ab3f6f67688888a31ffc2a882bb37adab32d1a4b278951a21646f90d03385fc976715fc639a785d015751171016f10 -b56f35d164c24b557dbcbc8a4bfa681ec916f8741ffcb27fb389c164f4e3ed2be325210ef5bdaeae7a172ca9599ab442 -a7921a5a80d7cf6ae81ba9ee05e0579b18c20cd2852762c89d6496aa4c8ca9d1ca2434a67b2c16d333ea8e382cdab1e3 -a506bcfbd7e7e5a92f68a1bd87d07ad5fe3b97aeee40af2bf2cae4efcd77fff03f872732c5b7883aa6584bee65d6f8cb -a8c46cff58931a1ce9cbe1501e1da90b174cddd6d50f3dfdfb759d1d4ad4673c0a8feed6c1f24c7af32865a7d6c984e5 -b45686265a83bff69e312c5149db7bb70ac3ec790dc92e392b54d9c85a656e2bf58596ce269f014a906eafc97461aa5f -8d4009a75ccb2f29f54a5f16684b93202c570d7a56ec1a8b20173269c5f7115894f210c26b41e8d54d4072de2d1c75d0 -aef8810af4fc676bf84a0d57b189760ddc3375c64e982539107422e3de2580b89bd27aa6da44e827b56db1b5555e4ee8 -888f0e1e4a34f48eb9a18ef4de334c27564d72f2cf8073e3d46d881853ac1424d79e88d8ddb251914890588937c8f711 -b64b0aa7b3a8f6e0d4b3499fe54e751b8c3e946377c0d5a6dbb677be23736b86a7e8a6be022411601dd75012012c3555 -8d57776f519f0dd912ea14f79fbab53a30624e102f9575c0bad08d2dc754e6be54f39b11278c290977d9b9c7c0e1e0ad -a018fc00d532ceb2e4de908a15606db9b6e0665dd77190e2338da7c87a1713e6b9b61554e7c1462f0f6d4934b960b15c -8c932be83ace46f65c78e145b384f58e41546dc0395270c1397874d88626fdeda395c8a289d602b4c312fe98c1311856 -89174838e21639d6bdd91a0621f04dc056907b88e305dd66e46a08f6d65f731dea72ae87ca5e3042d609e8de8de9aa26 -b7b7f508bb74f7a827ac8189daa855598ff1d96fa3a02394891fd105d8f0816224cd50ac4bf2ed1cf469ace516c48184 -b31877ad682583283baadd68dc1bebd83f5748b165aadd7fe9ef61a343773b88bcd3a022f36d6c92f339b7bfd72820a9 -b79d77260b25daf9126dab7a193df2d7d30542786fa1733ffaf6261734770275d3ca8bae1d9915d1181a78510b3439db -91894fb94cd4c1dd2ceaf9c53a7020c5799ba1217cf2d251ea5bc91ed26e1159dd758e98282ebe35a0395ef9f1ed15a0 -ab59895cdafd33934ceedfc3f0d5d89880482cba6c99a6db93245f9e41987efd76e0640e80aef31782c9a8c7a83fccec -aa22ea63654315e033e09d4d4432331904a6fc5fb1732557987846e3c564668ca67c60a324b4af01663a23af11a9ce4b -b53ba3ef342601467e1f71aa280e100fbabbd38518fa0193e0099505036ee517c1ac78e96e9baeb549bb6879bb698fb0 -943fd69fd656f37487cca3605dc7e5a215fddd811caf228595ec428751fc1de484a0cb84c667fe4d7c35599bfa0e5e34 -9353128b5ebe0dddc555093cf3e5942754f938173541033e8788d7331fafc56f68d9f97b4131e37963ab7f1c8946f5f1 -a76cd3c566691f65cfb86453b5b31dbaf3cab8f84fe1f795dd1e570784b9b01bdd5f0b3c1e233942b1b5838290e00598 -983d84b2e53ffa4ae7f3ba29ef2345247ea2377686b74a10479a0ef105ecf90427bf53b74c96dfa346d0f842b6ffb25b -92e0fe9063306894a2c6970c001781cff416c87e87cb5fbac927a3192655c3da4063e6fa93539f6ff58efac6adcc5514 -b00a81f03c2b8703acd4e2e4c21e06973aba696415d0ea1a648ace2b0ea19b242fede10e4f9d7dcd61c546ab878bc8f9 -b0d08d880f3b456a10bf65cff983f754f545c840c413aea90ce7101a66eb0a0b9b1549d6c4d57725315828607963f15a -90cb64d03534f913b411375cce88a9e8b1329ce67a9f89ca5df8a22b8c1c97707fec727dbcbb9737f20c4cf751359277 -8327c2d42590dfcdb78477fc18dcf71608686ad66c49bce64d7ee874668be7e1c17cc1042a754bbc77c9daf50b2dae07 -8532171ea13aa7e37178e51a6c775da469d2e26ec854eb16e60f3307db4acec110d2155832c202e9ba525fc99174e3b0 -83ca44b15393d021de2a511fa5511c5bd4e0ac7d67259dce5a5328f38a3cce9c3a269405959a2486016bc27bb140f9ff -b1d36e8ca812be545505c8214943b36cabee48112cf0de369957afa796d37f86bf7249d9f36e8e990f26f1076f292b13 -9803abf45be5271e2f3164c328d449efc4b8fc92dfc1225d38e09630909fe92e90a5c77618daa5f592d23fc3ad667094 -b268ad68c7bf432a01039cd889afae815c3e120f57930d463aece10af4fd330b5bd7d8869ef1bcf6b2e78e4229922edc -a4c91a0d6f16b1553264592b4cbbbf3ca5da32ab053ffbdd3dbb1aed1afb650fb6e0dc5274f71a51d7160856477228db -ad89d043c2f0f17806277ffdf3ecf007448e93968663f8a0b674254f36170447b7527d5906035e5e56f4146b89b5af56 -8b6964f757a72a22a642e4d69102951897e20c21449184e44717bd0681d75f7c5bfa5ee5397f6e53febf85a1810d6ed1 -b08f5cdaabec910856920cd6e836c830b863eb578423edf0b32529488f71fe8257d90aed4a127448204df498b6815d79 -af26bb3358be9d280d39b21d831bb53145c4527a642446073fee5a86215c4c89ff49a3877a7a549486262f6f57a0f476 -b4010b37ec4d7c2af20800e272539200a6b623ae4636ecbd0e619484f4ab9240d02bc5541ace3a3fb955dc0a3d774212 -82752ab52bdcc3cc2fc405cb05a2e694d3df4a3a68f2179ec0652536d067b43660b96f85f573f26fbd664a9ef899f650 -96d392dde067473a81faf2d1fea55b6429126b88b160e39b4210d31d0a82833ffd3a80e07d24d495aea2d96be7251547 -a76d8236d6671204d440c33ac5b8deb71fa389f6563d80e73be8b043ec77d4c9b06f9a586117c7f957f4af0331cbc871 -b6c90961f68b5e385d85c9830ec765d22a425f506904c4d506b87d8944c2b2c09615e740ed351df0f9321a7b93979cae -a6ec5ea80c7558403485b3b1869cdc63bde239bafdf936d9b62a37031628402a36a2cfa5cfbb8e26ac922cb0a209b3ba -8c3195bbdbf9bc0fc95fa7e3d7f739353c947f7767d1e3cb24d8c8602d8ea0a1790ac30b815be2a2ba26caa5227891e2 -a7f8a63d809f1155722c57f375ea00412b00147776ae4444f342550279ef4415450d6f400000a326bf11fea6c77bf941 -97fa404df48433a00c85793440e89bb1af44c7267588ae937a1f5d53e01e1c4d4fc8e4a6d517f3978bfdd6c2dfde012f -a984a0a3836de3d8d909c4629a2636aacb85393f6f214a2ef68860081e9db05ad608024762db0dc35e895dc00e2d4cdd -9526cf088ab90335add1db4d3a4ac631b58cbfbe88fa0845a877d33247d1cfeb85994522e1eb8f8874651bfb1df03e2a -ac83443fd0afe99ad49de9bf8230158c118e2814c9c89db5ac951c240d6c2ce45e7677221279d9e97848ec466b99aafe -aeeefdbaba612e971697798ceaf63b247949dc823a0ad771ae5b988a5e882b338a98d3d0796230f49d533ec5ba411b39 -ae3f248b5a7b0f92b7820a6c5ae21e5bd8f4265d4f6e21a22512079b8ee9be06393fd3133ce8ebac0faf23f4f8517e36 -a64a831b908eee784b8388b45447d2885ec0551b26b0c2b15e5f417d0a12c79e867fb7bd3d008d0af98b44336f8ec1ad -b242238cd8362b6e440ba21806905714dd55172db25ec7195f3fc4937b2aba146d5cbf3cf691a1384b4752dc3b54d627 -819f97f337eea1ffb2a678cc25f556f1aab751c6b048993a1d430fe1a3ddd8bb411c152e12ca60ec6e057c190cd1db9a -b9d7d187407380df54ee9fef224c54eec1bfabf17dc8abf60765b7951f538f59aa26fffd5846cfe05546c35f59b573f4 -aa6e3c14efa6a5962812e3f94f8ce673a433f4a82d07a67577285ea0eaa07f8be7115853122d12d6d4e1fdf64c504be1 -82268bee9c1662d3ddb5fb785abfae6fb8b774190f30267f1d47091d2cd4b3874db4372625aa36c32f27b0eee986269b -b236459565b7b966166c4a35b2fa71030b40321821b8e96879d95f0e83a0baf33fa25721f30af4a631df209e25b96061 -8708d752632d2435d2d5b1db4ad1fa2558d776a013655f88e9a3556d86b71976e7dfe5b8834fdec97682cd94560d0d0d -ae1424a68ae2dbfb0f01211f11773732a50510b5585c1fb005cb892b2c6a58f4a55490b5c5b4483c6fce40e9d3236a52 -b3f5f722af9dddb07293c871ce97abbccba0093ca98c8d74b1318fa21396fc1b45b69c15084f63d728f9908442024506 -9606f3ce5e63886853ca476dc0949e7f1051889d529365c0cb0296fdc02abd088f0f0318ecd2cf36740a3634132d36f6 -b11a833a49fa138db46b25ff8cdda665295226595bc212c0931b4931d0a55c99da972c12b4ef753f7e37c6332356e350 -afede34e7dab0a9e074bc19a7daddb27df65735581ca24ad70c891c98b1349fcebbcf3ba6b32c2617fe06a5818dabc2d -97993d456e459e66322d01f8eb13918979761c3e8590910453944bdff90b24091bb018ac6499792515c9923be289f99f -977e3e967eff19290a192cd11df3667d511b398fb3ac9a5114a0f3707e25a0edcb56105648b1b85a8b7519fc529fc6f6 -b873a7c88bf58731fe1bf61ff6828bf114cf5228f254083304a4570e854e83748fc98683ddba62d978fff7909f2c5c47 -ad4b2691f6f19da1d123aaa23cca3e876247ed9a4ab23c599afdbc0d3aa49776442a7ceaa996ac550d0313d9b9a36cee -b9210713c78e19685608c6475bfa974b57ac276808a443f8b280945c5d5f9c39da43effa294bfb1a6c6f7b6b9f85bf6c -a65152f376113e61a0e468759de38d742caa260291b4753391ee408dea55927af08a4d4a9918600a3bdf1df462dffe76 -8bf8c27ad5140dde7f3d2280fd4cc6b29ab76537e8d7aa7011a9d2796ee3e56e9a60c27b5c2da6c5e14fc866301dc195 -92fde8effc9f61393a2771155812b863cff2a0c5423d7d40aa04d621d396b44af94ddd376c28e7d2f53c930aea947484 -97a01d1dd9ee30553ce676011aea97fa93d55038ada95f0057d2362ae9437f3ed13de8290e2ff21e3167dd7ba10b9c3f -89affffaa63cb2df3490f76f0d1e1d6ca35c221dd34057176ba739fa18d492355e6d2a5a5ad93a136d3b1fed0bb8aa19 -928b8e255a77e1f0495c86d3c63b83677b4561a5fcbbe5d3210f1e0fc947496e426d6bf3b49394a5df796c9f25673fc4 -842a0af91799c9b533e79ee081efe2a634cac6c584c2f054fb7d1db67dde90ae36de36cbf712ec9cd1a0c7ee79e151ea -a65b946cf637e090baf2107c9a42f354b390e7316beb8913638130dbc67c918926eb87bec3b1fe92ef72bc77a170fa3b -aafc0f19bfd71ab5ae4a8510c7861458b70ad062a44107b1b1dbacbfa44ba3217028c2824bd7058e2fa32455f624040b -95269dc787653814e0be899c95dba8cfa384f575a25e671c0806fd80816ad6797dc819d30ae06e1d0ed9cb01c3950d47 -a1e760f7fa5775a1b2964b719ff961a92083c5c617f637fc46e0c9c20ab233f8686f7f38c3cb27d825c54dd95e93a59b -ac3b8a7c2317ea967f229eddc3e23e279427f665c4705c7532ed33443f1243d33453c1088f57088d2ab1e3df690a9cc9 -b787beeddfbfe36dd51ec4efd9cf83e59e84d354c3353cc9c447be53ae53d366ed1c59b686e52a92f002142c8652bfe0 -b7a64198300cb6716aa7ac6b25621f8bdec46ad5c07a27e165b3f774cdf65bcfdbf31e9bae0c16b44de4b00ada7a4244 -b8ae9f1452909e0c412c7a7fe075027691ea8df1347f65a5507bc8848f1d2c833d69748076db1129e5b4fb912f65c86c -9682e41872456b9fa67def89e71f06d362d6c8ca85c9c48536615bc401442711e1c9803f10ab7f8ab5feaec0f9df20a6 -88889ff4e271dc1c7e21989cc39f73cde2f0475acd98078281591ff6c944fadeb9954e72334319050205d745d4df73df -8f79b5b8159e7fd0d93b0645f3c416464f39aec353b57d99ecf24f96272df8a068ad67a6c90c78d82c63b40bb73989bb -838c01a009a3d8558a3f0bdd5e22de21af71ca1aefc8423c91dc577d50920e9516880e87dce3e6d086e11cd45c9052d9 -b97f1c6eee8a78f137c840667cc288256e39294268a3009419298a04a1d0087c9c9077b33c917c65caf76637702dda8a -972284ce72f96a61c899260203dfa06fc3268981732bef74060641c1a5068ead723e3399431c247ca034b0dae861e8df -945a8d52d6d3db6663dbd3110c6587f9e9c44132045eeffba15621576d178315cb52870fa5861669f84f0bee646183fe -a0a547b5f0967b1c3e5ec6c6a9a99f0578521489180dfdfbb5561f4d166baac43a2f06f950f645ce991664e167537eed -a0592cda5cdddf1340033a745fd13a6eff2021f2e26587116c61c60edead067e0f217bc2bef4172a3c9839b0b978ab35 -b9c223b65a3281587fa44ec829e609154b32f801fd1de6950e01eafb07a8324243b960d5735288d0f89f0078b2c42b5b -99ebfc3b8f9f98249f4d37a0023149ed85edd7a5abe062c8fb30c8c84555258b998bdcdd1d400bc0fa2a4aaa8b224466 -955b68526e6cb3937b26843270f4e60f9c6c8ece2fa9308fe3e23afa433309c068c66a4bc16ee2cf04220f095e9afce4 -b766caeafcc00378135ae53397f8a67ed586f5e30795462c4a35853de6681b1f17401a1c40958de32b197c083b7279c1 -921bf87cad947c2c33fa596d819423c10337a76fe5a63813c0a9dc78a728207ae7b339407a402fc4d0f7cba3af6da6fc -a74ba1f3bc3e6c025db411308f49b347ec91da1c916bda9da61e510ec8d71d25e0ac0f124811b7860e5204f93099af27 -a29b4d144e0bf17a7e8353f2824cef0ce85621396babe8a0b873ca1e8a5f8d508b87866cf86da348470649fceefd735c -a8040e12ffc3480dd83a349d06741d1572ef91932c46f5cf03aee8454254156ee95786fd013d5654725e674c920cec32 -8c4cf34ca60afd33923f219ffed054f90cd3f253ffeb2204a3b61b0183417e366c16c07fae860e362b0f2bfe3e1a1d35 -8195eede4ddb1c950459df6c396b2e99d83059f282b420acc34220cadeed16ab65c856f2c52568d86d3c682818ed7b37 -91fff19e54c15932260aa990c7fcb3c3c3da94845cc5aa8740ef56cf9f58d19b4c3c55596f8d6c877f9f4d22921d93aa -a3e0bf7e5d02a80b75cf75f2db7e66cb625250c45436e3c136d86297d652590ec97c2311bafe407ad357c79ab29d107b -81917ff87e5ed2ae4656b481a63ced9e6e5ff653b8aa6b7986911b8bc1ee5b8ef4f4d7882c3f250f2238e141b227e510 -915fdbe5e7de09c66c0416ae14a8750db9412e11dc576cf6158755fdcaf67abdbf0fa79b554cac4fe91c4ec245be073f -8df27eafb5c3996ba4dc5773c1a45ca77e626b52e454dc1c4058aa94c2067c18332280630cc3d364821ee53bf2b8c130 -934f8a17c5cbb827d7868f5c8ca00cb027728a841000a16a3428ab16aa28733f16b52f58c9c4fbf75ccc45df72d9c4df -b83f4da811f9183c25de8958bc73b504cf790e0f357cbe74ef696efa7aca97ad3b7ead1faf76e9f982c65b6a4d888fc2 -87188213c8b5c268dc2b6da413f0501c95749e953791b727450af3e43714149c115b596b33b63a2f006a1a271b87efd0 -83e9e888ab9c3e30761de635d9aabd31248cdd92f7675fc43e4b21fd96a03ec1dc4ad2ec94fec857ffb52683ac98e360 -b4b9a1823fe2d983dc4ec4e3aaea297e581c3fc5ab4b4af5fa1370caa37af2d1cc7fc6bfc5e7da60ad8fdce27dfe4b24 -856388bc78aef465dbcdd1f559252e028c9e9a2225c37d645c138e78f008f764124522705822a61326a6d1c79781e189 -a6431b36db93c3b47353ba22e7c9592c9cdfb9cbdd052ecf2cc3793f5b60c1e89bc96e6bae117bfd047f2308da00dd2f -b619972d48e7e4291542dcde08f7a9cdc883c892986ded2f23ccb216e245cd8d9ad1d285347b0f9d7611d63bf4cee2bc -8845cca6ff8595955f37440232f8e61d5351500bd016dfadd182b9d39544db77a62f4e0102ff74dd4173ae2c181d24ef -b2f5f7fa26dcd3b6550879520172db2d64ee6aaa213cbef1a12befbce03f0973a22eb4e5d7b977f466ac2bf8323dcedd -858b7f7e2d44bdf5235841164aa8b4f3d33934e8cb122794d90e0c1cac726417b220529e4f896d7b77902ab0ccd35b3a -80b0408a092dae2b287a5e32ea1ad52b78b10e9c12f49282976cd738f5d834e03d1ad59b09c5ccaccc39818b87d06092 -b996b0a9c6a2d14d984edcd6ab56bc941674102980d65b3ad9733455f49473d3f587c8cbf661228a7e125ddbe07e3198 -90224fcebb36865293bd63af786e0c5ade6b67c4938d77eb0cbae730d514fdd0fe2d6632788e858afd29d46310cf86df -b71351fdfff7168b0a5ec48397ecc27ac36657a8033d9981e97002dcca0303e3715ce6dd3f39423bc8ef286fa2e9e669 -ae2a3f078b89fb753ce4ed87e0c1a58bb19b4f0cfb6586dedb9fcab99d097d659a489fb40e14651741e1375cfc4b6c5f -8ef476b118e0b868caed297c161f4231bbeb863cdfa5e2eaa0fc6b6669425ce7af50dc374abceac154c287de50c22307 -92e46ab472c56cfc6458955270d3c72b7bde563bb32f7d4ab4d959db6f885764a3d864e1aa19802fefaa5e16b0cb0b54 -96a3f68323d1c94e73d5938a18a377af31b782f56212de3f489d22bc289cf24793a95b37f1d6776edf88114b5c1fa695 -962cc068cfce6faaa27213c4e43e44eeff0dfbb6d25b814e82c7da981fb81d7d91868fa2344f05fb552362f98cfd4a72 -895d4e4c4ad670abf66d43d59675b1add7afad7438ada8f42a0360c704cee2060f9ac15b4d27e9b9d0996bb801276fe3 -b3ad18d7ece71f89f2ef749b853c45dc56bf1c796250024b39a1e91ed11ca32713864049c9aaaea60cde309b47486bbf -8f05404e0c0258fdbae50e97ccb9b72ee17e0bd2400d9102c0dad981dac8c4c71585f03e9b5d50086d0a2d3334cb55d1 -8bd877e9d4591d02c63c6f9fc9976c109de2d0d2df2bfa5f6a3232bab5b0b8b46e255679520480c2d7a318545efa1245 -8d4c16b5d98957c9da13d3f36c46f176e64e5be879f22be3179a2c0e624fe4758a82bf8c8027410002f973a3b84cd55a -86e2a8dea86427b424fa8eada881bdff896907084a495546e66556cbdf070b78ba312bf441eb1be6a80006d25d5097a3 -8608b0c117fd8652fdab0495b08fadbeba95d9c37068e570de6fddfef1ba4a1773b42ac2be212836141d1bdcdef11a17 -a13d6febf5fb993ae76cae08423ca28da8b818d6ef0fde32976a4db57839cd45b085026b28ee5795f10a9a8e3098c683 -8e261967fa6de96f00bc94a199d7f72896a6ad8a7bbb1d6187cca8fad824e522880e20f766620f4f7e191c53321d70f9 -8b8e8972ac0218d7e3d922c734302803878ad508ca19f5f012bc047babd8a5c5a53deb5fe7c15a4c00fd6d1cb9b1dbd0 -b5616b233fb3574a2717d125a434a2682ff68546dccf116dd8a3b750a096982f185614b9fb6c7678107ff40a451f56fa -aa6adf9b0c3334b0d0663f583a4914523b2ac2e7adffdb026ab9109295ff6af003ef8357026dbcf789896d2afded8d73 -acb72df56a0b65496cd534448ed4f62950bb1e11e50873b6ed349c088ee364441821294ce0f7c61bd7d38105bea3b442 -abae12df83e01ec947249fedd0115dc501d2b03ff7232092979eda531dbbca29ace1d46923427c7dde4c17bdf3fd7708 -820b4fc2b63a9fda7964acf5caf19a2fc4965007cb6d6b511fcafcb1f71c3f673a1c0791d3f86e3a9a1eb6955b191cc0 -af277259d78c6b0f4f030a10c53577555df5e83319ddbad91afbd7c30bc58e7671c56d00d66ec3ab5ef56470cd910cee -ad4a861c59f1f5ca1beedd488fb3d131dea924fffd8e038741a1a7371fad7370ca5cf80dc01f177fbb9576713bb9a5b3 -b67a5162982ce6a55ccfb2f177b1ec26b110043cf18abd6a6c451cf140b5af2d634591eb4f28ad92177d8c7e5cd0a5e8 -96176d0a83816330187798072d449cbfccff682561e668faf6b1220c9a6535b32a6e4f852e8abb00f79abb87493df16b -b0afe6e7cb672e18f0206e4423f51f8bd0017bf464c4b186d46332c5a5847647f89ff7fa4801a41c1b0b42f6135bcc92 -8fc5e7a95ef20c1278c645892811f6fe3f15c431ebc998a32ec0da44e7213ea934ed2be65239f3f49b8ec471e9914160 -b7793e41adda6c82ba1f2a31f656f6205f65bf8a3d50d836ee631bc7ce77c153345a2d0fc5c60edf8b37457c3729c4ec -a504dd7e4d6b2f4379f22cc867c65535079c75ccc575955f961677fa63ecb9f74026fa2f60c9fb6323c1699259e5e9c8 -ab899d00ae693649cc1afdf30fb80d728973d2177c006e428bf61c7be01e183866614e05410041bc82cb14a33330e69c -8a3bd8b0b1be570b65c4432a0f6dc42f48a2000e30ab089cf781d38f4090467b54f79c0d472fcbf18ef6a00df69cc6f3 -b4d7028f7f76a96a3d7803fca7f507ae11a77c5346e9cdfccb120a833a59bda1f4264e425aa588e7a16f8e7638061d84 -b9c7511a76ea5fb105de905d44b02edb17008335766ee357ed386b7b3cf19640a98b38785cb14603c1192bee5886c9b6 -8563afb12e53aed71ac7103ab8602bfa8371ae095207cb0d59e8fd389b6ad1aff0641147e53cb6a7ca16c7f37c9c5e6b -8e108be614604e09974a9ed90960c28c4ea330a3d9a0cb4af6dd6f193f84ab282b243ecdf549b3131036bebc8905690c -b794d127fbedb9c5b58e31822361706ffac55ce023fbfe55716c3c48c2fd2f2c7660a67346864dfe588812d369cb50b6 -b797a3442fc3b44f41baefd30346f9ac7f96e770d010d53c146ce74ce424c10fb62758b7e108b8abfdc5fafd89d745cb -993bb71e031e8096442e6205625e1bfddfe6dd6a83a81f3e2f84fafa9e5082ab4cad80a099f21eff2e81c83457c725c3 -8711ab833fc03e37acf2e1e74cfd9133b101ff4144fe30260654398ae48912ab46549d552eb9d15d2ea57760d35ac62e -b21321fd2a12083863a1576c5930e1aecb330391ef83326d9d92e1f6f0d066d1394519284ddab55b2cb77417d4b0292f -877d98f731ffe3ee94b0b5b72d127630fa8a96f6ca4f913d2aa581f67732df6709493693053b3e22b0181632ac6c1e3b -ae391c12e0eb8c145103c62ea64f41345973311c3bf7281fa6bf9b7faafac87bcf0998e5649b9ef81e288c369c827e07 -b83a2842f36998890492ab1cd5a088d9423d192681b9a3a90ec518d4c541bce63e6c5f4df0f734f31fbfdd87785a2463 -a21b6a790011396e1569ec5b2a423857b9bec16f543e63af28024e116c1ea24a3b96e8e4c75c6537c3e4611fd265e896 -b4251a9c4aab3a495da7a42e684ba4860dbcf940ad1da4b6d5ec46050cbe8dab0ab9ae6b63b5879de97b905723a41576 -8222f70aebfe6ac037f8543a08498f4cadb3edaac00336fc00437eb09f2cba758f6c38e887cc634b4d5b7112b6334836 -86f05038e060594c46b5d94621a1d9620aa8ba59a6995baf448734e21f58e23c1ea2993d3002ad5250d6edd5ba59b34f -a7c0c749baef811ab31b973c39ceb1d94750e2bc559c90dc5eeb20d8bb6b78586a2b363c599ba2107d6be65cd435f24e -861d46a5d70b38d6c1cd72817a2813803d9f34c00320c8b62f8b9deb67f5b5687bc0b37c16d28fd017367b92e05da9ca -b3365d3dab639bffbe38e35383686a435c8c88b397b717cd4aeced2772ea1053ceb670f811f883f4e02975e5f1c4ac58 -a5750285f61ab8f64cd771f6466e2c0395e01b692fd878f2ef2d5c78bdd8212a73a3b1dfa5e4c8d9e1afda7c84857d3b -835a10809ccf939bc46cf950a33b36d71be418774f51861f1cd98a016ade30f289114a88225a2c11e771b8b346cbe6ef -a4f59473a037077181a0a62f1856ec271028546ca9452b45cedfcb229d0f4d1aabfc13062b07e536cc8a0d4b113156a2 -95cd14802180b224d44a73cc1ed599d6c4ca62ddcaa503513ccdc80aaa8be050cc98bd4b4f3b639549beb4587ac6caf9 -973b731992a3e69996253d7f36dd7a0af1982b5ed21624b77a7965d69e9a377b010d6dabf88a8a97eec2a476259859cc -af8a1655d6f9c78c8eb9a95051aa3baaf9c811adf0ae8c944a8d3fcba87b15f61021f3baf6996fa0aa51c81b3cb69de1 -835aad5c56872d2a2d6c252507b85dd742bf9b8c211ccb6b25b52d15c07245b6d89b2a40f722aeb5083a47cca159c947 -abf4e970b02bef8a102df983e22e97e2541dd3650b46e26be9ee394a3ea8b577019331857241d3d12b41d4eacd29a3ac -a13c32449dbedf158721c13db9539ae076a6ce5aeaf68491e90e6ad4e20e20d1cdcc4a89ed9fd49cb8c0dd50c17633c1 -8c8f78f88b7e22dd7e9150ab1c000f10c28e696e21d85d6469a6fe315254740f32e73d81ab1f3c1cf8f544c86df506e8 -b4b77f2acfe945abf81f2605f906c10b88fb4d28628487fb4feb3a09f17f28e9780445dfcee4878349d4c6387a9d17d4 -8d255c235f3812c6ecc646f855fa3832be5cb4dbb9c9e544989fafdf3f69f05bfd370732eaf954012f0044aa013fc9c6 -b982efd3f34b47df37c910148ac56a84e8116647bea24145a49e34e0a6c0176e3284d838dae6230cb40d0be91c078b85 -983f365aa09bd85df2a6a2ad8e4318996b1e27d02090755391d4486144e40d80b1fbfe1c798d626db92f52e33aa634da -95fd1981271f3ea3a41d654cf497e6696730d9ff7369f26bc4d7d15c7adb4823dd0c42e4a005a810af12d234065e5390 -a9f5219bd4b913c186ef30c02f995a08f0f6f1462614ea5f236964e02bdaa33db9d9b816c4aee5829947840a9a07ba60 -9210e6ceb05c09b46fd09d036287ca33c45124ab86315e5d6911ff89054f1101faaa3e83d123b7805056d388bcec6664 -8ed9cbf69c6ff3a5c62dd9fe0d7264578c0f826a29e614bc2fb4d621d90c8c9992438accdd7a614b1dca5d1bb73dc315 -85cf2a8cca93e00da459e3cecd22c342d697eee13c74d5851634844fc215f60053cf84b0e03c327cb395f48d1c71a8a4 -8818a18e9a2ec90a271b784400c1903089ffb0e0b40bc5abbbe12fbebe0f731f91959d98c5519ef1694543e31e2016d4 -8dabc130f296fa7a82870bf9a8405aaf542b222ed9276bba9bd3c3555a0f473acb97d655ee7280baff766a827a8993f0 -ac7952b84b0dc60c4d858f034093b4d322c35959605a3dad2b806af9813a4680cb038c6d7f4485b4d6b2ff502aaeca25 -ad65cb6d57b48a2602568d2ec8010baed0eb440eec7638c5ec8f02687d764e9de5b5d42ad5582934e592b48471c22d26 -a02ab8bd4c3d114ea23aebdd880952f9495912817da8c0c08eabc4e6755439899d635034413d51134c72a6320f807f1c -8319567764b8295402ec1ebef4c2930a138480b37e6d7d01c8b4c9cd1f2fc3f6e9a44ae6e380a0c469b25b06db23305f -afec53b2301dc0caa8034cd9daef78c48905e6068d692ca23d589b84a6fa9ddc2ed24a39480597e19cb3e83eec213b3f -ac0b4ffdb5ae08e586a9cdb98f9fe56f4712af3a97065e89e274feacfb52b53c839565aee93c4cfaaccfe51432c4fab0 -8972cbf07a738549205b1094c5987818124144bf187bc0a85287c94fdb22ce038c0f11df1aa16ec5992e91b44d1af793 -b7267aa6f9e3de864179b7da30319f1d4cb2a3560f2ea980254775963f1523b44c680f917095879bebfa3dc2b603efcf -80f68f4bfc337952e29504ee5149f15093824ea7ab02507efd1317a670f6cbc3611201848560312e3e52e9d9af72eccf -8897fee93ce8fc1e1122e46b6d640bba309384dbd92e46e185e6364aa8210ebf5f9ee7e5e604b6ffba99aa80a10dd7d0 -b58ea6c02f2360be60595223d692e82ee64874fda41a9f75930f7d28586f89be34b1083e03bbc1575bbfdda2d30db1ea -85a523a33d903280d70ac5938770453a58293480170c84926457ac2df45c10d5ff34322ab130ef4a38c916e70d81af53 -a2cbf045e1bed38937492c1f2f93a5ba41875f1f262291914bc1fc40c60bd0740fb3fea428faf6da38b7c180fe8ac109 -8c09328770ed8eb17afc6ac7ddd87bb476de18ed63cab80027234a605806895959990c47bd10d259d7f3e2ecb50074c9 -b4b9e19edb4a33bde8b7289956568a5b6b6557404e0a34584b5721fe6f564821091013fbb158e2858c6d398293bb4b59 -8a47377df61733a2aa5a0e945fce00267f8e950f37e109d4487d92d878fb8b573317bb382d902de515b544e9e233458d -b5804c9d97efeff5ca94f3689b8088c62422d92a1506fd1d8d3b1b30e8a866ad0d6dad4abfa051dfc4471250cac4c5d9 -9084a6ee8ec22d4881e9dcc8a9eb3c2513523d8bc141942370fd191ad2601bf9537a0b1e84316f3209b3d8a54368051e -85447eea2fa26656a649f8519fa67279183044791d61cf8563d0783d46d747d96af31d0a93507bbb2242666aa87d3720 -97566a84481027b60116c751aec552adfff2d9038e68d48c4db9811fb0cbfdb3f1d91fc176a0b0d988a765f8a020bce1 -ae87e5c1b9e86c49a23dceda4ecfd1dcf08567f1db8e5b6ec752ebd45433c11e7da4988573cdaebbb6f4135814fc059e -abee05cf9abdbc52897ac1ce9ed157f5466ed6c383d6497de28616238d60409e5e92619e528af8b62cc552bf09970dc2 -ae6d31cd7bf9599e5ee0828bab00ceb4856d829bba967278a73706b5f388465367aa8a6c7da24b5e5f1fdd3256ef8e63 -ac33e7b1ee47e1ee4af472e37ab9e9175260e506a4e5ce449788075da1b53c44cb035f3792d1eea2aa24b1f688cc6ed3 -80f65b205666b0e089bb62152251c48c380a831e5f277f11f3ef4f0d52533f0851c1b612267042802f019ec900dc0e8f -858520ad7aa1c9fed738e3b583c84168f2927837ad0e1d326afe9935c26e9b473d7f8c382e82ef1fe37d2b39bb40a1ee -b842dd4af8befe00a97c2d0f0c33c93974761e2cb9e5ab8331b25170318ddd5e4bdbc02d8f90cbfdd5f348f4f371c1f7 -8bf2cb79bc783cb57088aae7363320cbeaabd078ffdec9d41bc74ff49e0043d0dad0086a30e5112b689fd2f5a606365d -982eb03bbe563e8850847cd37e6a3306d298ab08c4d63ab6334e6b8c1fa13fce80cf2693b09714c7621d74261a0ff306 -b143edb113dec9f1e5105d4a93fbe502b859e587640d3db2f628c09a17060e6aec9e900e2c8c411cda99bc301ff96625 -af472d9befa750dcebc5428fe1a024f18ec1c07bca0f95643ce6b5f4189892a910285afb03fd7ed7068fbe614e80d33c -a97e3bc57ede73ecd1bbf02de8f51b4e7c1a067da68a3cd719f4ba26a0156cbf1cef2169fd35a18c5a4cced50d475998 -a862253c937cf3d75d7183e5f5be6a4385d526aeda5171c1c60a8381fea79f88f5f52a4fab244ecc70765d5765e6dfd5 -90cb776f8e5a108f1719df4a355bebb04bf023349356382cae55991b31720f0fd03206b895fa10c56c98f52453be8778 -a7614e8d0769dccd520ea4b46f7646e12489951efaef5176bc889e9eb65f6e31758df136b5bf1e9107e68472fa9b46ec -ac3a9b80a3254c42e5ed3a090a0dd7aee2352f480de96ad187027a3bb6c791eddfc3074b6ffd74eea825188f107cda4d -82a01d0168238ef04180d4b6e0a0e39024c02c2d75b065017c2928039e154d093e1af4503f4d1f3d8a948917abb5d09f -8fab000a2b0eef851a483aec8d2dd85fe60504794411a2f73ed82e116960547ac58766cb73df71aea71079302630258d -872451a35c6db61c63e9b8bb9f16b217f985c20be4451c14282c814adb29d7fb13f201367c664435c7f1d4d9375d7a58 -887d9ff54cc96b35d562df4a537ff972d7c4b3fd91ab06354969a4cfede0b9fc68bbffb61d0dbf1a58948dc701e54f5a -8cb5c2a6bd956875d88f41ae24574434f1308514d44057b55c9c70f13a3366ed054150eed0955a38fda3f757be73d55f -89ad0163cad93e24129d63f8e38422b7674632a8d0a9016ee8636184cab177659a676c4ee7efba3abe1a68807c656d60 -b9ec01c7cab6d00359b5a0b4a1573467d09476e05ca51a9227cd16b589a9943d161eef62dcc73f0de2ec504d81f4d252 -8031d17635d39dfe9705c485d2c94830b6fc9bc67b91300d9d2591b51e36a782e77ab5904662effa9382d9cca201f525 -8be5a5f6bc8d680e5092d6f9a6585acbaaaa2ddc671da560dcf5cfa4472f4f184b9597b5b539438accd40dda885687cc -b1fc0f052fae038a2e3de3b3a96b0a1024b009de8457b8b3adb2d315ae68a89af905720108a30038e5ab8d0d97087785 -8b8bdc77bd3a6bc7ca5492b6f8c614852c39a70d6c8a74916eaca0aeb4533b11898b8820a4c2620a97bf35e275480029 -af35f4dc538d4ad5cdf710caa38fd1eb496c3fa890a047b6a659619c5ad3054158371d1e88e0894428282eed9f47f76b -8166454a7089cc07758ad78724654f4e7a1a13e305bbf88ddb86f1a4b2904c4fc8ab872d7da364cdd6a6c0365239e2ad -ab287c7d3addce74ce40491871c768abe01daaa0833481276ff2e56926b38a7c6d2681ffe837d2cc323045ad1a4414f9 -b90317f4505793094d89365beb35537f55a6b5618904236258dd04ca61f21476837624a2f45fef8168acf732cab65579 -98ae5ea27448e236b6657ab5ef7b1cccb5372f92ab25f5fa651fbac97d08353a1dae1b280b1cd42b17d2c6a70a63ab9d -adcf54e752d32cbaa6cb98fbca48d8cd087b1db1d131d465705a0d8042c8393c8f4d26b59006eb50129b21e6240f0c06 -b591a3e4db18a7345fa935a8dd7994bbac5cc270b8ebd84c8304c44484c7a74afb45471fdbe4ab22156a30fae1149b40 -806b53ac049a42f1dcc1d6335505371da0bf27c614f441b03bbf2e356be7b2fb4eed7117eabcce9e427a542eaa2bf7d8 -800482e7a772d49210b81c4a907f5ce97f270b959e745621ee293cf8c71e8989363d61f66a98f2d16914439544ca84c7 -99de9eafdad3617445312341644f2bb888680ff01ce95ca9276b1d2e5ef83fa02dab5e948ebf66c17df0752f1bd37b70 -961ee30810aa4c93ae157fbe9009b8e443c082192bd36a73a6764ff9b2ad8b0948fe9a73344556e01399dd77badb4257 -ae0a361067c52efbe56c8adf982c00432cd478929459fc7f74052c8ee9531cd031fe1335418fde53f7c2ef34254eb7ac -a3503d16b6b27eb20c1b177bcf90d13706169220523a6271b85b2ce35a9a2b9c5bed088540031c0a4ebfdae3a4c6ab04 -909420122c3e723289ca4e7b81c2df5aff312972a2203f4c45821b176e7c862bf9cac7f7df3adf1d59278f02694d06e7 -989f42380ae904b982f85d0c6186c1aef5d6bcba29bcfbb658e811b587eb2749c65c6e4a8cc6409c229a107499a4f5d7 -8037a6337195c8e26a27ea4ef218c6e7d79a9720aaab43932d343192abc2320fe72955f5e431c109093bda074103330a -b312e168663842099b88445e940249cc508f080ab0c94331f672e7760258dbd86be5267e4cf25ea25facb80bff82a7e9 -aaa3ff8639496864fcdbfdda1ac97edc4f08e3c9288b768f6c8073038c9fbbf7e1c4bea169b4d45c31935cdf0680d45e -97dbd3df37f0b481a311dfc5f40e59227720f367912200d71908ef6650f32cc985cb05b981e3eea38958f7e48d10a15d -a89d49d1e267bb452d6cb621b9a90826fe55e9b489c0427b94442d02a16f390eed758e209991687f73f6b5a032321f42 -9530dea4e0e19d6496f536f2e75cf7d814d65fde567055eb20db48fd8d20d501cd2a22fb506db566b94c9ee10f413d43 -81a7009b9e67f1965fa7da6a57591c307de91bf0cd35ab4348dc4a98a4961e096d004d7e7ad318000011dc4342c1b809 -83440a9402b766045d7aca61a58bba2aa29cac1cf718199e472ba086f5d48093d9dda4d135292ba51d049a23964eceae -a06c9ce5e802df14f6b064a3d1a0735d429b452f0e2e276042800b0a4f16df988fd94cf3945921d5dd3802ab2636f867 -b1359e358b89936dee9e678a187aad3e9ab14ac40e96a0a68f70ee2583cdcf467ae03bef4215e92893f4e12f902adec8 -835304f8619188b4d14674d803103d5a3fa594d48e96d9699e653115dd05fdc2dda6ba3641cf7ad53994d448da155f02 -8327cba5a9ff0d3f5cd0ae55e77167448926d5fcf76550c0ad978092a14122723090c51c415e88e42a2b62eb07cc3981 -b373dcdaea85f85ce9978b1426a7ef4945f65f2d3467a9f1cc551a99766aac95df4a09e2251d3f89ca8c9d1a7cfd7b0e -ab1422dc41af2a227b973a6fd124dfcb2367e2a11a21faa1d381d404f51b7257e5bc82e9cf20cd7fe37d7ae761a2ab37 -a93774a03519d2f20fdf2ef46547b0a5b77c137d6a3434b48d56a2cbef9e77120d1b85d0092cf8842909213826699477 -8eb967a495a38130ea28711580b7e61bcd1d051cd9e4f2dbf62f1380bd86e0d60e978d72f6f31e909eb97b3b9a2b867c -ae8213378da1287ba1fe4242e1acaec19b877b6fe872400013c6eac1084b8d03156792fa3020201725b08228a1e80f49 -b143daf6893d674d607772b3b02d8ac48f294237e2f2c87963c0d4e26d9227d94a2a13512457c3d5883544bbc259f0ef -b343bd2aca8973888e42542218924e2dda2e938fd1150d06878af76f777546213912b7c7a34a0f94186817d80ffa185c -b188ebc6a8c3007001aa347ae72cc0b15d09bc6c19a80e386ee4b334734ec0cc2fe8b493c2422f38d1e6d133cc3db6fe -b795f6a8b9b826aaeee18ccd6baf6c5adeeec85f95eb5b6d19450085ec7217e95a2d9e221d77f583b297d0872073ba0e -b1c7dbd998ad32ae57bfa95deafa147024afd57389e98992c36b6e52df915d3d5a39db585141ec2423173e85d212fed8 -812bcdeb9fe5f12d0e1df9964798056e1f1c3de3b17b6bd2919b6356c4b86d8e763c01933efbe0224c86a96d5198a4be -b19ebeda61c23d255cbf472ef0b8a441f4c55b70f0d8ed47078c248b1d3c7c62e076b43b95c00a958ec8b16d5a7cb0d7 -b02adc9aaa20e0368a989c2af14ff48b67233d28ebee44ff3418bb0473592e6b681af1cc45450bd4b175df9051df63d9 -8d87f0714acee522eb58cec00360e762adc411901dba46adc9227124fa70ee679f9a47e91a6306d6030dd4eb8de2f3c1 -8be54cec21e74bcc71de29dc621444263737db15f16d0bb13670f64e42f818154e04b484593d19ef95f2ee17e4b3fe21 -ab8e20546c1db38d31493b5d5f535758afb17e459645c1b70813b1cf7d242fd5d1f4354a7c929e8f7259f6a25302e351 -89f035a1ed8a1e302ac893349ba8ddf967580fcb6e73d44af09e3929cde445e97ff60c87dafe489e2c0ab9c9986cfa00 -8b2b0851a795c19191a692af55f7e72ad2474efdc5401bc3733cfdd910e34c918aaebe69d5ea951bdddf3c01cabbfc67 -a4edb52c2b51495ccd1ee6450fc14b7b3ede8b3d106808929d02fb31475bacb403e112ba9c818d2857651e508b3a7dd1 -9569341fded45d19f00bcf3cbf3f20eb2b4d82ef92aba3c8abd95866398438a2387437e580d8b646f17cf6fde8c5af23 -aa4b671c6d20f72f2f18a939a6ff21cc37e0084b44b4a717f1be859a80b39fb1be026b3205adec2a66a608ec2bcd578f -94902e980de23c4de394ad8aec91b46f888d18f045753541492bfbb92c59d3daa8de37ae755a6853744af8472ba7b72b -af651ef1b2a0d30a7884557edfad95b6b5d445a7561caebdc46a485aedd25932c62c0798465c340a76f6feaa196dd712 -b7b669b8e5a763452128846dd46b530dca4893ace5cc5881c7ddcd3d45969d7e73fbebdb0e78aa81686e5f7b22ec5759 -82507fd4ebe9fa656a7f2e084d64a1fa6777a2b0bc106d686e2d9d2edafc58997e58cb6bfd0453b2bf415704aa82ae62 -b40bce2b42b88678400ecd52955bbdadd15f8b9e1b3751a1a3375dc0efb5ca3ee258cf201e1140b3c09ad41217d1d49e -b0210d0cbb3fbf3b8cdb39e862f036b0ff941cd838e7aaf3a8354e24246e64778d22f3de34572e6b2a580614fb6425be -876693cba4301b251523c7d034108831df3ce133d8be5a514e7a2ca494c268ca0556fa2ad8310a1d92a16b55bcd99ea9 -8660281406d22a4950f5ef050bf71dd3090edb16eff27fa29ef600cdea628315e2054211ed2cc6eaf8f2a1771ef689fd -a610e7e41e41ab66955b809ba4ade0330b8e9057d8efc9144753caed81995edeb1a42a53f93ce93540feca1fae708dac -a49e2c176a350251daef1218efaccc07a1e06203386ede59c136699d25ca5cb2ac1b800c25b28dd05678f14e78e51891 -83e0915aa2b09359604566080d411874af8c993beba97d4547782fdbe1a68e59324b800ff1f07b8db30c71adcbd102a8 -a19e84e3541fb6498e9bb8a099c495cbfcad113330e0262a7e4c6544495bb8a754b2208d0c2d895c93463558013a5a32 -87f2bd49859a364912023aca7b19a592c60214b8d6239e2be887ae80b69ebdeb59742bdebcfa73a586ab23b2c945586c -b8e8fdddae934a14b57bc274b8dcd0d45ebb95ddbaabef4454e0f6ce7d3a5a61c86181929546b3d60c447a15134d08e1 -87e0c31dcb736ea4604727e92dc1d9a3cf00adcff79df3546e02108355260f3dd171531c3c0f57be78d8b28058fcc8c0 -9617d74e8f808a4165a8ac2e30878c349e1c3d40972006f0787b31ea62d248c2d9f3fc3da83181c6e57e95feedfd0e8c -8949e2cee582a2f8db86e89785a6e46bc1565c2d8627d5b6bf43ba71ffadfab7e3c5710f88dcb5fb2fc6edf6f4fae216 -ad3fa7b0edceb83118972a2935a09f409d09a8db3869f30be3a76f67aa9fb379cabb3a3aff805ba023a331cad7d7eb64 -8c95718a4112512c4efbd496be38bf3ca6cdcaad8a0d128f32a3f9aae57f3a57bdf295a3b372a8c549fda8f4707cffed -88f3261d1e28a58b2dee3fcc799777ad1c0eb68b3560f9b4410d134672d9533532a91ea7be28a041784872632d3c9d80 -b47472a41d72dd2e8b72f5c4f8ad626737dde3717f63d6bc776639ab299e564cbad0a2ad5452a07f02ff49a359c437e5 -9896d21dc2e8aad87b76d6df1654f10cd7bceed4884159d50a818bea391f8e473e01e14684814c7780235f28e69dca6e -82d47c332bbd31bbe83b5eb44a23da76d4a7a06c45d7f80f395035822bc27f62f59281d5174e6f8e77cc9b5c3193d6f0 -95c74cd46206e7f70c9766117c34c0ec45c2b0f927a15ea167901a160e1530d8522943c29b61e03568aa0f9c55926c53 -a89d7757825ae73a6e81829ff788ea7b3d7409857b378ebccd7df73fdbe62c8d9073741cf038314971b39af6c29c9030 -8c1cd212d0b010905d560688cfc036ae6535bc334fa8b812519d810b7e7dcf1bb7c5f43deaa40f097158358987324a7f -b86993c383c015ed8d847c6b795164114dd3e9efd25143f509da318bfba89389ea72a420699e339423afd68b6512fafb -8d06bd379c6d87c6ed841d8c6e9d2d0de21653a073725ff74be1934301cc3a79b81ef6dd0aad4e7a9dc6eac9b73019bc -81af4d2d87219985b9b1202d724fe39ef988f14fef07dfe3c3b11714e90ffba2a97250838e8535eb63f107abfe645e96 -8c5e0af6330a8becb787e4b502f34f528ef5756e298a77dc0c7467433454347f3a2e0bd2641fbc2a45b95e231c6e1c02 -8e2a8f0f04562820dc8e7da681d5cad9fe2e85dd11c785fb6fba6786c57a857e0b3bd838fb849b0376c34ce1665e4837 -a39be8269449bfdfc61b1f62077033649f18dae9bef7c6163b9314ca8923691fb832f42776f0160b9e8abd4d143aa4e1 -8c154e665706355e1cc98e0a4cabf294ab019545ba9c4c399d666e6ec5c869ca9e1faf8fb06cd9c0a5c2f51a7d51b70a -a046a7d4de879d3ebd4284f08f24398e9e3bf006cd4e25b5c67273ade248689c69affff92ae810c07941e4904296a563 -afd94c1cb48758e5917804df03fb38a6da0e48cd9b6262413ea13b26973f9e266690a1b7d9d24bbaf7e82718e0e594b0 -859e21080310c8d6a38e12e2ac9f90a156578cdeb4bb2e324700e97d9a5511cd6045dc39d1d0de3f94aeed043a24119d -a219fb0303c379d0ab50893264919f598e753aac9065e1f23ef2949abc992577ab43c636a1d2c089203ec9ddb941e27d -b0fdb639d449588a2ca730afcba59334e7c387342d56defdfb7ef79c493f7fd0e5277eff18e7203e756c7bdda5803047 -87f9c3b7ed01f54368aca6dbcf2f6e06bff96e183c4b2c65f8baa23b377988863a0a125d5cdd41a072da8462ced4c070 -99ef7a5d5ac2f1c567160e1f8c95f2f38d41881850f30c461a205f7b1b9fb181277311333839b13fb3ae203447e17727 -aeaca9b1c2afd24e443326cc68de67b4d9cedb22ad7b501a799d30d39c85bb2ea910d4672673e39e154d699e12d9b3dc -a11675a1721a4ba24dd3d0e4c3c33a6edf4cd1b9f6b471070b4386c61f77452266eae6e3f566a40cfc885eada9a29f23 -b228334445e37b9b49cb4f2cc56b454575e92173ddb01370a553bba665adadd52df353ad74470d512561c2c3473c7bb9 -a18177087c996572d76f81178d18ed1ceebc8362a396348ce289f1d8bd708b9e99539be6fccd4acb1112381cfc5749b4 -8e7b8bf460f0d3c99abb19803b9e43422e91507a1c0c22b29ee8b2c52d1a384da4b87c292e28eff040db5be7b1f8641f -b03d038d813e29688b6e6f444eb56fec3abba64c3d6f890a6bcf2e916507091cdb2b9d2c7484617be6b26552ed1c56cb -a1c88ccd30e934adfc5494b72655f8afe1865a84196abfb376968f22ddc07761210b6a9fb7638f1413d1b4073d430290 -961b714faebf172ad2dbc11902461e286e4f24a99a939152a53406117767682a571057044decbeb3d3feef81f4488497 -a03dc4059b46effdd786a0a03cc17cfee8585683faa35bb07936ded3fa3f3a097f518c0b8e2db92fd700149db1937789 -adf60180c99ca574191cbcc23e8d025b2f931f98ca7dfcebfc380226239b6329347100fcb8b0fcb12db108c6ad101c07 -805d4f5ef24d46911cbf942f62cb84b0346e5e712284f82b0db223db26d51aabf43204755eb19519b00e665c7719fcaa -8dea7243e9c139662a7fe3526c6c601eee72fd8847c54c8e1f2ad93ef7f9e1826b170afe58817dac212427164a88e87f -a2ba42356606d651b077983de1ad643650997bb2babb188c9a3b27245bb65d2036e46667c37d4ce02cb1be5ae8547abe -af2ae50b392bdc013db2d12ce2544883472d72424fc767d3f5cb0ca2d973fc7d1f425880101e61970e1a988d0670c81b -98e6bec0568d3939b31d00eb1040e9b8b2a35db46ddf4369bdaee41bbb63cc84423d29ee510a170fb5b0e2df434ba589 -822ff3cd12fbef4f508f3ca813c04a2e0b9b799c99848e5ad3563265979e753ee61a48f6adc2984a850f1b46c1a43d35 -891e8b8b92a394f36653d55725ef514bd2e2a46840a0a2975c76c2a935577f85289026aaa74384da0afe26775cbddfb9 -b2a3131a5d2fe7c8967047aa66e4524babae941d90552171cc109527f345f42aa0df06dcbb2fa01b33d0043917bbed69 -80c869469900431f3eeefafdbe07b8afd8cee7739e659e6d0109b397cacff85a88247698f87dc4e2fe39a592f250ac64 -9091594f488b38f9d2bb5df49fd8b4f8829d9c2f11a197dd1431ed5abbc5c954bbde3387088f9ee3a5a834beb7619bce -b472e241e6956146cca57b97a8a204668d050423b4e76f857bad5b47f43b203a04c8391ba9d9c3e95093c071f9d376a1 -b7dd2de0284844392f7dfb56fe7ca3ede41e27519753ffc579a0a8d2d65ceb8108d06b6b0d4c3c1a2588951297bd1a1e -902116ce70d0a079ac190321c1f48701318c05f8e69ee09694754885d33a835a849cafe56f499a2f49f6cda413ddf9a7 -b18105cc736787fafaf7c3c11c448bce9466e683159dff52723b7951dff429565e466e4841d982e3aaa9ee2066838666 -97ab9911f3f659691762d568ae0b7faa1047b0aed1009c319fa79d15d0db8db9f808fc385dc9a68fa388c10224985379 -b2a2cba65f5b927e64d2904ba412e2bac1cf18c9c3eda9c72fb70262497ecf505b640827e2afebecf10eebbcf48ccd3e -b36a3fd677baa0d3ef0dac4f1548ff50a1730286b8c99d276a0a45d576e17b39b3cbadd2fe55e003796d370d4be43ce3 -a5dfec96ca3c272566e89dc453a458909247e3895d3e44831528130bc47cc9d0a0dac78dd3cad680a4351d399d241967 -8029382113909af6340959c3e61db27392531d62d90f92370a432aec3eb1e4c36ae1d4ef2ba8ec6edb4d7320c7a453f6 -971d85121ea108e6769d54f9c51299b0381ece8b51d46d49c89f65bedc123bab4d5a8bc14d6f67f4f680077529cbae4c -98ff6afc01d0bec80a278f25912e1b1ebff80117adae72e31d5b9fa4d9624db4ba2065b444df49b489b0607c45e26c4c -8fa29be10fb3ab30ce25920fec0187e6e91e458947009dabb869aade7136c8ba23602682b71e390c251f3743164cbdaa -b3345c89eb1653418fe3940cf3e56a9a9c66526389b98f45ca02dd62bfb37baa69a4baaa7132d7320695f8ea6ad1fd94 -b72c7f5541c9ac6b60a7ec9f5415e7fb14da03f7164ea529952a29399f3a071576608dbbcc0d45994f21f92ddbeb1e19 -aa3450bb155a5f9043d0ef95f546a2e6ade167280bfb75c9f09c6f9cdb1fffb7ce8181436161a538433afa3681c7a141 -92a18fecaded7854b349f441e7102b638ababa75b1b0281dd0bded6541abe7aa37d96693595be0b01fe0a2e2133d50f9 -980756ddf9d2253cfe6c94960b516c94889d09e612810935150892627d2ecee9a2517e04968eea295d0106850c04ca44 -ae68c6ccc454318cdd92f32b11d89116a3b8350207a36d22a0f626718cad671d960090e054c0c77ac3162ae180ecfd4b -99f31f66eaaa551749ad91d48a0d4e3ff4d82ef0e8b28f3184c54e852422ba1bdafd53b1e753f3a070f3b55f3c23b6a2 -a44eaeaa6589206069e9c0a45ff9fc51c68da38d4edff1d15529b7932e6f403d12b9387019c44a1488a5d5f27782a51f -b80b5d54d4b344840e45b79e621bd77a3f83fb4ce6d8796b7d6915107b3f3c34d2e7d95bdafd120f285669e5acf2437a -b36c069ec085a612b5908314d6b84c00a83031780261d1c77a0384c406867c9847d5b0845deddfa512cc04a8df2046fb -b09dbe501583220f640d201acea7ee3e39bf9eda8b91aa07b5c50b7641d86d71acb619b38d27835ce97c3759787f08e9 -87403d46a2bf63170fff0b857acacf42ee801afe9ccba8e5b4aea967b68eac73a499a65ca46906c2eb4c8f27bc739faa -82b93669f42a0a2aa5e250ffe6097269da06a9c02fcd1801abbad415a7729a64f830754bafc702e64600ba47671c2208 -8e3a3029be7edb8dd3ab1f8216664c8dc50d395f603736061d802cef77627db7b859ef287ed850382c13b4d22d6a2d80 -968e9ec7194ff424409d182ce0259acd950c384c163c04463bc8700a40b79beba6146d22b7fa7016875a249b7b31c602 -8b42c984bbe4996e0c20862059167c6bdc5164b1ffcd928f29512664459212d263e89f0f0e30eed4e672ffa5ed0b01b5 -96bac54062110dada905363211133f1f15dc7e4fd80a4c6e4a83bc9a0bcbbaba11cd2c7a13debcf0985e1a954c1da66b -a16dc8a653d67a7cd7ae90b2fffac0bf1ca587005430fe5ba9403edd70ca33e38ba5661d2ed6e9d2864400d997626a62 -a68ab11a570a27853c8d67e491591dcba746bfbee08a2e75ae0790399130d027ed387f41ef1d7de8df38b472df309161 -92532b74886874447c0300d07eda9bbe4b41ed25349a3da2e072a93fe32c89d280f740d8ff70d5816793d7f2b97373cc -88e35711b471e89218fd5f4d0eadea8a29405af1cd81974427bc4a5fb26ed60798daaf94f726c96e779b403a2cd82820 -b5c72aa4147c19f8c4f3a0a62d32315b0f4606e0a7025edc5445571eaf4daff64f4b7a585464821574dd50dbe1b49d08 -9305d9b4095258e79744338683fd93f9e657367b3ab32d78080e51d54eec331edbc224fad5093ebf8ee4bd4286757eb8 -b2a17abb3f6a05bcb14dc7b98321fa8b46d299626c73d7c6eb12140bf4c3f8e1795250870947af817834f033c88a59d6 -b3477004837dbd8ba594e4296f960fc91ab3f13551458445e6c232eb04b326da803c4d93e2e8dcd268b4413305ff84da -924b4b2ebaafdcfdfedb2829a8bf46cd32e1407d8d725a5bd28bdc821f1bafb3614f030ea4352c671076a63494275a3f -8b81b9ef6125c82a9bece6fdcb9888a767ac16e70527753428cc87c56a1236e437da8be4f7ecfe57b9296dc3ae7ba807 -906e19ec8b8edd58bdf9ae05610a86e4ea2282b1bbc1e8b00b7021d093194e0837d74cf27ac9916bdb8ec308b00da3da -b41c5185869071760ac786078a57a2ab4e2af60a890037ac0c0c28d6826f15c2cf028fddd42a9b6de632c3d550bfbc14 -a646e5dec1b713ae9dfdf7bdc6cd474d5731a320403c7dfcfd666ffc9ae0cff4b5a79530e8df3f4aa9cb80568cb138e9 -b0efad22827e562bd3c3e925acbd0d9425d19057868608d78c2209a531cccd0f2c43dc5673acf9822247428ffa2bb821 -a94c19468d14b6f99002fc52ac06bbe59e5c472e4a0cdb225144a62f8870b3f10593749df7a2de0bd3c9476ce682e148 -803864a91162f0273d49271dafaab632d93d494d1af935aefa522768af058fce52165018512e8d6774976d52bd797e22 -a08711c2f7d45c68fb340ac23597332e1bcaec9198f72967b9921204b9d48a7843561ff318f87908c05a44fc35e3cc9d -91c3cad94a11a3197ae4f9461faab91a669e0dddb0371d3cab3ed9aeb1267badc797d8375181130e461eadd05099b2a2 -81bdaaf48aae4f7b480fc13f1e7f4dd3023a41439ba231760409ce9292c11128ab2b0bdbbf28b98af4f97b3551f363af -8d60f9df9fd303f625af90e8272c4ecb95bb94e6efc5da17b8ab663ee3b3f673e9f6420d890ccc94acf4d2cae7a860d8 -a7b75901520c06e9495ab983f70b61483504c7ff2a0980c51115d11e0744683ce022d76e3e09f4e99e698cbd21432a0d -82956072df0586562fda7e7738226f694e1c73518dd86e0799d2e820d7f79233667192c9236dcb27637e4c65ef19d493 -a586beb9b6ffd06ad200957490803a7cd8c9bf76e782734e0f55e04a3dc38949de75dc607822ec405736c576cf83bca3 -a179a30d00def9b34a7e85607a447eea0401e32ab5abeee1a281f2acd1cf6ec81a178020666f641d9492b1bdf66f05a3 -83e129705c538787ed8e0fdc1275e6466a3f4ee21a1e6abedd239393b1df72244723b92f9d9d9339a0cab6ebf28f5a16 -811bd8d1e3722b64cd2f5b431167e7f91456e8bba2cc669d3fbbce7d553e29c3c19f629fcedd2498bc26d33a24891d17 -a243c030c858f1f60cccd26b45b024698cc6d9d9e6198c1ed4964a235d9f8d0baf9cde10c8e63dfaa47f8e74e51a6e85 -ab839eb82e23ca52663281f863b55b0a3d6d4425c33ffb4eeb1d7979488ab068bf99e2a60e82cea4dc42c56c26cbfebe -8b896f9bb21d49343e67aec6ad175b58c0c81a3ca73d44d113ae4354a0065d98eb1a5cafedaf232a2bb9cdc62152f309 -af6230340cc0b66f5bf845540ed4fc3e7d6077f361d60762e488d57834c3e7eb7eacc1b0ed73a7d134f174a01410e50c -88975e1b1af678d1b5179f72300a30900736af580dd748fd9461ef7afccc91ccd9bed33f9da55c8711a7635b800e831f -a97486bb9047391661718a54b8dd5a5e363964e495eae6c692730264478c927cf3e66dd3602413189a3699fbeae26e15 -a5973c161ab38732885d1d2785fd74bf156ba34881980cba27fe239caef06b24a533ffe6dbbbeca5e6566682cc00300a -a24776e9a840afda0003fa73b415d5bd6ecd9b5c2cc842b643ee51b8c6087f4eead4d0bfbd987eb174c489a7b952ff2a -a8a6ee06e3af053b705a12b59777267c546f33ba8a0f49493af8e6df4e15cf8dd2d4fb4daf7e84c6b5d3a7363118ff03 -a28e59ce6ad02c2ce725067c0123117e12ac5a52c8f5af13eec75f4a9efc4f696777db18a374fa33bcae82e0734ebd16 -86dfc3b78e841c708aff677baa8ee654c808e5d257158715097c1025d46ece94993efe12c9d188252ad98a1e0e331fec -a88d0275510f242eab11fdb0410ff6e1b9d7a3cbd3658333539815f1b450a84816e6613d15aa8a8eb15d87cdad4b27a2 -8440acea2931118a5b481268ff9f180ee4ede85d14a52c026adc882410825b8275caa44aff0b50c2b88d39f21b1a0696 -a7c3182eab25bd6785bacf12079d0afb0a9b165d6ed327814e2177148539f249eb9b5b2554538f54f3c882d37c0a8abe -85291fbe10538d7da38efdd55a7acebf03b1848428a2f664c3ce55367aece60039f4f320b1771c9c89a35941797f717c -a2c6414eeb1234728ab0de94aa98fc06433a58efa646ca3fcbd97dbfb8d98ae59f7ce6d528f669c8149e1e13266f69c9 -840c8462785591ee93aee2538d9f1ec44ba2ca61a569ab51d335ac873f5d48099ae8d7a7efa0725d9ff8f9475bfa4f56 -a7065a9d02fb3673acf7702a488fbc01aa69580964932f6f40b6c2d1c386b19e50b0e104fcac24ea26c4e723611d0238 -b72db6d141267438279e032c95e6106c2ccb3164b842ba857a2018f3a35f4b040da92680881eb17cd61d0920d5b8f006 -a8005d6c5960e090374747307ef0be2871a7a43fa4e76a16c35d2baab808e9777b496e9f57a4218b23390887c33a0b55 -8e152cea1e00a451ca47c20a1e8875873419700af15a5f38ee2268d3fbc974d4bd5f4be38008fa6f404dbdedd6e6e710 -a3391aed1fcd68761f06a7d1008ec62a09b1cb3d0203cd04e300a0c91adfed1812d8bc1e4a3fd7976dc0aae0e99f52f1 -967eb57bf2aa503ee0c6e67438098149eac305089c155f1762cf5e84e31f0fbf27c34a9af05621e34645c1ec96afaec8 -88af97ddc4937a95ec0dcd25e4173127260f91c8db2f6eac84afb789b363705fb3196235af631c70cafd09411d233589 -a32df75b3f2c921b8767638fd289bcfc61e08597170186637a7128ffedd52c798c434485ac2c7de07014f9e895c2c3d8 -b0a783832153650aa0d766a3a73ec208b6ce5caeb40b87177ffc035ab03c7705ecdd1090b6456a29f5fb7e90e2fa8930 -b59c8e803b4c3486777d15fc2311b97f9ded1602fa570c7b0200bada36a49ee9ef4d4c1474265af8e1c38a93eb66b18b -982f2c85f83e852022998ff91bafbb6ff093ef22cf9d5063e083a48b29175ccbd51b9c6557151409e439096300981a6c -939e3b5989fefebb9d272a954659a4eb125b98c9da6953f5e628d26266bd0525ec38304b8d56f08d65abc4d6da4a8dbb -8898212fe05bc8de7d18503cb84a1c1337cc2c09d1eeef2b475aa79185b7322bf1f8e065f1bf871c0c927dd19faf1f6d -94b0393a41cd00f724aee2d4bc72103d626a5aecb4b5486dd1ef8ac27528398edf56df9db5c3d238d8579af368afeb09 -96ac564450d998e7445dd2ea8e3fc7974d575508fa19e1c60c308d83b645864c029f2f6b7396d4ff4c1b24e92e3bac37 -8adf6638e18aff3eb3b47617da696eb6c4bdfbecbbc3c45d3d0ab0b12cbad00e462fdfbe0c35780d21aa973fc150285e -b53f94612f818571b5565bbb295e74bada9b5f9794b3b91125915e44d6ddcc4da25510eab718e251a09c99534d6042d9 -8b96462508d77ee083c376cd90807aebad8de96bca43983c84a4a6f196d5faf6619a2351f43bfeec101864c3bf255519 -aeadf34657083fc71df33bd44af73bf5281c9ca6d906b9c745536e1819ea90b56107c55e2178ebad08f3ba75b3f81c86 -9784ba29b2f0057b5af1d3ab2796d439b8753f1f749c73e791037461bdfc3f7097394283105b8ab01788ea5255a96710 -8756241bda159d4a33bf74faba0d4594d963c370fb6a18431f279b4a865b070b0547a6d1613cf45b8cfb5f9236bbf831 -b03ebfd6b71421dfd49a30460f9f57063eebfe31b9ceaa2a05c37c61522b35bdc09d7db3ad75c76c253c00ba282d3cd2 -b34e7e6341fa9d854b2d3153bdda0c4ae2b2f442ab7af6f99a0975d45725aa48e36ae5f7011edd249862e91f499687d4 -b462ee09dc3963a14354244313e3444de5cc37ea5ccfbf14cd9aca8027b59c4cb2a949bc30474497cab8123e768460e6 -aea753290e51e2f6a21a9a0ee67d3a2713f95c2a5c17fe41116c87d3aa77b1683761264d704df1ac34f8b873bc88ef7b -98430592afd414394f98ddfff9f280fcb1c322dbe3510f45e1e9c4bb8ee306b3e0cf0282c0ee73ebb8ba087d4d9e0858 -b95d3b5aaf54ffca11f4be8d57f76e14afdb20afc859dc7c7471e0b42031e8f3d461b726ecb979bdb2f353498dfe95ea -984d17f9b11a683132e0b5a9ee5945e3ff7054c2d5c716be73b29078db1d36f54c6e652fd2f52a19da313112e97ade07 -ab232f756b3fff3262be418a1af61a7e0c95ceebbc775389622a8e10610508cd6784ab7960441917a83cc191c58829ea -a28f41678d6e60de76b0e36ab10e4516e53e02e9c77d2b5af3cfeee3ce94cfa30c5797bd1daab20c98e1cad83ad0f633 -b55395fca84dd3ccc05dd480cb9b430bf8631ff06e24cb51d54519703d667268c2f8afcde4ba4ed16bece8cc7bc8c6e0 -8a8a5392a0e2ea3c7a8c51328fab11156004e84a9c63483b64e8f8ebf18a58b6ffa8fe8b9d95af0a2f655f601d096396 -ab480000fe194d23f08a7a9ec1c392334e9c687e06851f083845121ce502c06b54dda8c43092bcc1035df45cc752fe9b -b265644c29f628d1c7e8e25a5e845cabb21799371814730a41a363e1bda8a7be50fee7c3996a365b7fcba4642add10db -b8a915a3c685c2d4728f6931c4d29487cad764c5ce23c25e64b1a3259ac27235e41b23bfe7ae982921b4cb84463097df -8efa7338442a4b6318145a5440fc213b97869647eeae41b9aa3c0a27ee51285b73e3ae3b4a9423df255e6add58864aa9 -9106d65444f74d217f4187dfc8fcf3810b916d1e4275f94f6a86d1c4f3565b131fd6cde1fa708bc05fe183c49f14941a -948252dac8026bbbdb0a06b3c9d66ec4cf9532163bab68076fda1bd2357b69e4b514729c15aaa83b5618b1977bbc60c4 -ae6596ccfdf5cbbc5782efe3bb0b101bb132dbe1d568854ca24cacc0b2e0e9fabcb2ca7ab42aecec412efd15cf8cb7a2 -84a0b6c198ff64fd7958dfd1b40eac9638e8e0b2c4cd8cf5d8cdf80419baee76a05184bce6c5b635f6bf2d30055476a7 -8893118be4a055c2b3da593dbca51b1ae2ea2469911acfb27ee42faf3e6c3ad0693d3914c508c0b05b36a88c8b312b76 -b097479e967504deb6734785db7e60d1d8034d6ca5ba9552887e937f5e17bb413fccac2c1d1082154ed76609127860ad -a0294e6b9958f244d29943debf24b00b538b3da1116269b6e452bb12dc742226712fd1a15b9c88195afeb5d2415f505c -b3cc15f635080bc038f61b615f62b5b5c6f2870586191f59476e8368a73641d6ac2f7d0c1f54621982defdb318020230 -99856f49b9fe1604d917c94d09cc0ed753d13d015d30587a94e6631ffd964b214e607deb8a69a8b5e349a7edf4309206 -a8571e113ea22b4b4fce41a094da8c70de37830ae32e62c65c2fa5ad06a9bc29e884b945e73d448c72b176d6ecebfb58 -a9e9c6e52beb0013273c29844956b3ce291023678107cdc785f7b44eff5003462841ad8780761b86aefc6b734adde7cf -80a784b0b27edb51ef2bad3aee80e51778dcaa0f3f5d3dcb5dc5d4f4b2cf7ae35b08de6680ea9dac53f8438b92eb09ef -827b543e609ea328e97e373f70ad72d4915a2d1daae0c60d44ac637231070e164c43a2a58db80a64df1c624a042b38f9 -b449c65e8195202efdcb9bdb4e869a437313b118fef8b510cbbf8b79a4e99376adb749b37e9c20b51b31ed3310169e27 -8ea3028f4548a79a94c717e1ed28ad4d8725b8d6ab18b021063ce46f665c79da3c49440c6577319dab2d036b7e08f387 -897798431cfb17fe39f08f5f854005dc37b1c1ec1edba6c24bc8acb3b88838d0534a75475325a5ea98b326ad47dbad75 -89cf232e6303b0751561960fd4dea5754a28c594daf930326b4541274ffb03c7dd75938e411eb9a375006a70ce38097f -9727c6ae7f0840f0b6c8bfb3a1a5582ceee705e0b5c59b97def7a7a2283edd4d3f47b7971e902a3a2079e40b53ff69b8 -b76ed72b122c48679d221072efc0eeea063cb205cbf5f9ef0101fd10cb1075b8628166c83577cced654e1c001c7882f7 -ae908c42d208759da5ee9b405df85a6532ea35c6f0f6a1288d22870f59d98edc896841b8ac890a538e6c8d1e8b02d359 -809d12fe4039a0ec80dc9be6a89acaab7797e5f7f9b163378f52f9a75a1d73b2e9ae6e3dd49e32ced439783c1cabbef5 -a4149530b7f85d1098ba534d69548c6c612c416e8d35992fc1f64f4deeb41e09e49c6cf7aadbed7e846b91299358fe2d -a49342eacd1ec1148b8df1e253b1c015f603c39de11fa0a364ccb86ea32d69c34fd7aa6980a1fadcd8e785a57fa46f60 -87d43eff5a006dc4dddcf76cc96c656a1f3a68f19f124181feab86c6cc9a52cb9189cdbb423414defdd9bb0ca8ff1ddc -861367e87a9aa2f0f68296ba50aa5dbc5713008d260cc2c7e62d407c2063064749324c4e8156dc21b749656cfebce26b -b5303c2f72e84e170e66ae1b0fbd51b8c7a6f27476eaf5694b64e8737d5c84b51fe90100b256465a4c4156dd873cddb0 -b62849a4f891415d74f434cdc1d23c4a69074487659ca96e1762466b2b7a5d8525b056b891d0feea6fe6845cba8bc7fb -923dd9e0d6590a9307e8c4c23f13bae3306b580e297a937711a8b13e8de85e41a61462f25b7d352b682e8437bf2b4ab3 -9147379860cd713cd46c94b8cdf75125d36c37517fbecf81ace9680b98ce6291cd1c3e472f84249cc3b2b445e314b1b6 -a808a4f17ac21e3fb5cfef404e61fae3693ca3e688d375f99b6116779696059a146c27b06de3ac36da349b0649befd56 -87787e9322e1b75e66c1f0d9ea0915722a232770930c2d2a95e9478c4b950d15ab767e30cea128f9ed65893bfc2d0743 -9036a6ee2577223be105defe1081c48ea7319e112fff9110eb9f61110c319da25a6cea0464ce65e858635b079691ef1f -af5548c7c24e1088c23b57ee14d26c12a83484c9fd9296edf1012d8dcf88243f20039b43c8c548c265ef9a1ffe9c1c88 -a0fff520045e14065965fb8accd17e878d3fcaf9e0af2962c8954e50be6683d31fa0bf4816ab68f08630dbac6bfce52a -b4c1b249e079f6ae1781af1d97a60b15855f49864c50496c09c91fe1946266915b799f0406084d7783f5b1039116dd8b -8b0ffa5e7c498cb3879dddca34743b41eee8e2dea3d4317a6e961b58adb699ef0c92400c068d5228881a2b08121226bf -852ae8b19a1d80aa8ae5382e7ee5c8e7670ceb16640871c56b20b96b66b3b60e00015a3dde039446972e57b49a999ddd -a49942f04234a7d8492169da232cfff8051df86e8e1ba3db46aede02422c689c87dc1d99699c25f96cb763f5ca0983e5 -b04b597b7760cf5dcf411ef896d1661e6d5b0db3257ac2cf64b20b60c6cc18fa10523bb958a48d010b55bac7b02ab3b1 -a494591b51ea8285daecc194b5e5bd45ae35767d0246ac94fae204d674ee180c8e97ff15f71f28b7aeb175b8aea59710 -97d2624919e78406e7460730680dea8e71c8571cf988e11441aeea54512b95bd820e78562c99372d535d96f7e200d20d -ac693ddb00e48f76e667243b9b6a7008424043fb779e4f2252330285232c3fccac4da25cbd6d95fe9ad959ff305a91f6 -8d20ca0a71a64a3f702a0825bb46bd810d03bebfb227683680d474a52f965716ff99e19a165ebaf6567987f4f9ee3c94 -a5c516a438f916d1d68ca76996404792e0a66e97b7f18fc54c917bf10cf3211b62387932756e39e67e47b0bd6e88385a -b089614d830abc0afa435034cec7f851f2f095d479cacf1a3fb57272da826c499a52e7dcbc0eb85f4166fb94778e18e9 -a8dacc943765d930848288192f4c69e2461c4b9bc6e79e30eeef9a543318cf9ae9569d6986c65c5668a89d49993f8e07 -ab5a9361fa339eec8c621bdad0a58078983abd8942d4282b22835d7a3a47e132d42414b7c359694986f7db39386c2e19 -94230517fb57bd8eb26c6f64129b8b2abd0282323bf7b94b8bac7fab27b4ecc2c4290c294275e1a759de19f2216134f3 -b8f158ea5006bc3b90b285246625faaa6ac9b5f5030dc69701b12f3b79a53ec7e92eeb5a63bbd1f9509a0a3469ff3ffc -8b6944fd8cb8540957a91a142fdcda827762aa777a31e8810ca6d026e50370ee1636fc351724767e817ca38804ebe005 -82d1ee40fe1569c29644f79fa6c4033b7ed45cd2c3b343881f6eb0de2e79548fded4787fae19bed6ee76ed76ff9f2f11 -a8924c7035e99eaed244ca165607e7e568b6c8085510dcdbaf6ebdbed405af2e6c14ee27d94ffef10d30aa52a60bf66d -956f82a6c2ae044635e85812581e4866c5fa2f427b01942047d81f6d79a14192f66fbbe77c9ffeaef4e6147097fdd2b5 -b1100255a1bcf5e05b6aff1dfeb6e1d55b5d68d43a7457ba10cc76b61885f67f4d0d5179abda786e037ae95deb8eea45 -99510799025e3e5e8fbf06dedb14c060c6548ba2bda824f687d3999dc395e794b1fb6514b9013f3892b6cf65cb0d65aa -8f9091cebf5e9c809aab415942172258f894e66e625d7388a05289183f01b8d994d52e05a8e69f784fba41db9ea357f0 -a13d2eeb0776bdee9820ecb6693536720232848c51936bb4ef4fe65588d3f920d08a21907e1fdb881c1ad70b3725e726 -a68b8f18922d550284c5e5dc2dda771f24c21965a6a4d5e7a71678178f46df4d8a421497aad8fcb4c7e241aba26378a0 -8b7601f0a3c6ad27f03f2d23e785c81c1460d60100f91ea9d1cab978aa03b523150206c6d52ce7c7769c71d2c8228e9e -a8e02926430813caa851bb2b46de7f0420f0a64eb5f6b805401c11c9091d3b6d67d841b5674fa2b1dce0867714124cd8 -b7968ecba568b8193b3058400af02c183f0a6df995a744450b3f7e0af7a772454677c3857f99c140bbdb2a09e832e8e0 -8f20b1e9ba87d0a3f35309b985f3c18d2e8800f1ca7f0c52cadef773f1496b6070c936eea48c4a1cae83fd2524e9d233 -88aef260042db0d641a51f40639dbeeefa9e9811df30bee695f3791f88a2f84d318f04e8926b7f47bf25956cb9e3754f -9725345893b647e9ba4e6a29e12f96751f1ae25fcaec2173e9a259921a1a7edb7a47159b3c8767e44d9e2689f5aa0f72 -8c281e6f72752cb11e239e4df9341c45106eb7993c160e54423c2bffe10bc39d42624b45a1f673936ef2e1a02fc92f1a -90aba2f68bddb2fcce6c51430dacdfeec43ea8dc379660c99095df11017691ccf5faa27665cf4b9f0eea7728ae53c327 -b7022695c16521c5704f49b7ddbdbec9b5f57ce0ceebe537bc0ebb0906d8196cc855a9afeb8950a1710f6a654464d93f -8fe1b9dd3c6a258116415d36e08374e094b22f0afb104385a5da48be17123e86fb8327baacc4f0d9ebae923d55d99bb5 -817e85d8e3d19a4cbc1dec31597142c2daa4871bda89c2177fa719c00eda3344eb08b82eb92d4aa91a9eaacb3fc09783 -b59053e1081d2603f1ca0ba553804d6fa696e1fd996631db8f62087b26a40dfef02098b0326bb75f99ec83b9267ca738 -990a173d857d3ba81ff3789b931bfc9f5609cde0169b7f055fa3cb56451748d593d62d46ba33f80f9cafffe02b68dd14 -b0c538dbba4954b809ab26f9f94a3cf1dcb77ce289eaec1d19f556c0ae4be1fa03af4a9b7057837541c3cc0a80538736 -ac3ba42f5f44f9e1fc453ce49c4ab79d0e1d5c42d3b30b1e098f3ab3f414c4c262fa12fb2be249f52d4aaf3c5224beb9 -af47467eb152e59870e21f0d4da2f43e093daf40180ab01438030684b114d025326928eaab12c41b81a066d94fce8436 -98d1b58ba22e7289b1c45c79a24624f19b1d89e00f778eef327ec4856a9a897278e6f1a9a7e673844b31dde949153000 -97ccb15dfadc7c59dca08cfe0d22df2e52c684cf97de1d94bc00d7ba24e020025130b0a39c0f4d46e4fc872771ee7875 -b699e4ed9a000ff96ca296b2f09dce278832bc8ac96851ff3cff99ed3f6f752cfc0fea8571be28cd9b5a7ec36f1a08ee -b9f49f0edb7941cc296435ff0a912e3ad16848ee8765ab5f60a050b280d6ea585e5b34051b15f6b8934ef01ceb85f648 -ac3893df7b4ceab23c6b9054e48e8ba40d6e5beda8fbe90b814f992f52494186969b35d8c4cdc3c99890a222c9c09008 -a41293ad22fae81dea94467bc1488c3707f3d4765059173980be93995fa4fcc3c9340796e3eed0beeb0ba0d9bb4fa3aa -a0543e77acd2aeecde13d18d258aeb2c7397b77f17c35a1992e8666ea7abcd8a38ec6c2741bd929abba2f766138618cc -92e79b22bc40e69f6527c969500ca543899105837b6b1075fa1796755c723462059b3d1b028e0b3df2559fa440e09175 -a1fa1eac8f41a5197a6fb4aa1eae1a031c89f9c13ff9448338b222780cf9022e0b0925d930c37501a0ef7b2b00fdaf83 -b3cb29ff73229f0637335f28a08ad8c5f166066f27c6c175164d0f26766a927f843b987ee9b309ed71cbf0a65d483831 -84d4ab787f0ac00f104f4a734dc693d62d48c2aeb03913153da62c2ae2c27d11b1110dcef8980368dd84682ea2c1a308 -ab6a8e4bbc78d4a7b291ad3e9a8fe2d65f640524ba3181123b09d2d18a9e300e2509ccf7000fe47e75b65f3e992a2e7e -b7805ebe4f1a4df414003dc10bca805f2ab86ca75820012653e8f9b79c405196b0e2cab099f2ab953d67f0d60d31a0f9 -b12c582454148338ea605d22bd00a754109063e22617f1f8ac8ddf5502c22a181c50c216c3617b9852aa5f26af56b323 -86333ad9f898947e31ce747728dc8c887479e18d36ff3013f69ebef807d82c6981543b5c3788af93c4d912ba084d3cba -b514efa310dc4ad1258add138891e540d8c87142a881b5f46563cc58ecd1488e6d3a2fca54c0b72a929f3364ca8c333e -aa0a30f92843cf2f484066a783a1d75a7aa6f41f00b421d4baf20a6ac7886c468d0eea7ca8b17dd22f4f74631b62b640 -b3b7dc63baec9a752e8433c0cdee4d0f9bc41f66f2b8d132faf925eef9cf89aae756fc132c45910f057122462605dc10 -b9b8190dac5bfdeb59fd44f4da41a57e7f1e7d2c21faba9da91fa45cbeca06dcf299c9ae22f0c89ece11ac46352d619f -89f8cf36501ad8bdfeab863752a9090e3bfda57cf8fdeca2944864dc05925f501e252c048221bcc57136ab09a64b64b2 -b0cbfaf317f05f97be47fc9d69eda2dd82500e00d42612f271a1fe24626408c28881f171e855bd5bd67409f9847502b4 -a7c21a8fcede581bfd9847b6835eda62ba250bea81f1bb17372c800a19c732abe03064e64a2f865d974fb636cab4b859 -95f9df524ba7a4667351696c4176b505d8ea3659f5ff2701173064acc624af69a0fad4970963736383b979830cb32260 -856a74fe8b37a2e3afeac858c8632200485d438422a16ae3b29f359e470e8244995c63ad79c7e007ed063f178d0306fd -b37faa4d78fdc0bb9d403674dbea0176c2014a171c7be8527b54f7d1a32a76883d3422a3e7a5f5fcc5e9b31b57822eeb -8d37234d8594ec3fe75670b5c9cc1ec3537564d4739b2682a75b18b08401869a4264c0f264354219d8d896cded715db4 -b5289ee5737f0e0bde485d32096d23387d68dab8f01f47821ab4f06cc79a967afe7355e72dc0c751d96b2747b26f6255 -9085e1fdf9f813e9c3b8232d3c8863cd84ab30d45e8e0d3d6a0abd9ebc6fd70cdf749ff4d04390000e14c7d8c6655fc7 -93a388c83630331eca4da37ea4a97b3b453238af474817cc0a0727fd3138dcb4a22de38c04783ec829c22cb459cb4e8e -a5377116027c5d061dbe24c240b891c08cdd8cd3f0899e848d682c873aff5b8132c1e7cfe76d2e5ed97ee0eb1d42cb68 -a274c84b04338ed28d74683e2a7519c2591a3ce37c294d6f6e678f7d628be2db8eff253ede21823e2df7183e6552f622 -8bc201147a842453a50bec3ac97671397bc086d6dfc9377fa38c2124cdc286abda69b7324f47d64da094ae011d98d9d9 -9842d0c066c524592b76fbec5132bc628e5e1d21c424bec4555efca8619cc1fd8ea3161febcb8b9e8ab54702f4e815e2 -a19191b713a07efe85c266f839d14e25660ee74452e6c691cd9997d85ae4f732052d802d3deb018bdd847caa298a894b -a24f71fc0db504da4e287dd118a4a74301cbcd16033937ba2abc8417956fcb4ae19b8e63b931795544a978137eff51cb -a90eec4a6a3a4b8f9a5b93d978b5026fcf812fe65585b008d7e08c4aaf21195a1d0699f12fc16f79b6a18a369af45771 -8b551cf89737d7d06d9b3b9c4c1c73b41f2ea0af4540999c70b82dabff8580797cf0a3caf34c86c59a7069eb2e38f087 -b8d312e6c635e7a216a1cda075ae77ba3e1d2fd501dc31e83496e6e81ed5d9c7799f8e578869c2e0e256fb29f5de10a7 -8d144bdb8cae0b2cdb5b33d44bbc96984a5925202506a8cc65eb67ac904b466f5a7fe3e1cbf04aa785bbb7348c4bb73c -a101b3d58b7a98659244b88de0b478b3fb87dc5fc6031f6e689b99edf498abd43e151fd32bd4bbd240e0b3e59c440359 -907453abca7d8e7151a05cc3d506c988007692fe7401395dc93177d0d07d114ab6cca0cc658eb94c0223fe8658295cad -825329ffbe2147ddb68f63a0a67f32d7f309657b8e5d9ab5bb34b3730bfa2c77a23eaaadb05def7d9f94a9e08fdc1e96 -88ee923c95c1dac99ae7ed6067906d734d793c5dc5d26339c1bb3314abe201c5dccb33b9007351885eb2754e9a8ea06c -98bc9798543f5f1adc9f2cfcfa72331989420e9c3f6598c45269f0dc9b7c8607bbeaf03faa0aea2ddde2b8f17fdceff5 -8ee87877702a79aef923ab970db6fa81561b3c07d5bf1a072af0a7bad765b4cbaec910afe1a91703feacc7822fa38a94 -8060b9584aa294fe8adc2b22f67e988bc6da768eae91e429dcc43ddc53cfcc5d6753fdc1b420b268c7eb2fb50736a970 -b344a5524d80a2f051870c7001f74fcf348a70fcf78dbd20c6ff9ca85d81567d2318c8b8089f2c4f195d6aec9fc15fa6 -8f5a5d893e1936ed062149d20eb73d98b62b7f50ab5d93a6429c03656b36688d1c80cb5010e4977491e51fa0d7dd35d5 -86fa32ebbf97328c5f5f15564e1238297e289ec3219b9a741724e9f3ae8d5c15277008f555863a478b247ba5dc601d44 -9557e55377e279f4b6b5e0ffe01eca037cc13aac242d67dfcd0374a1e775c5ed5cb30c25fe21143fee54e3302d34a3ea -8cb6bcbc39372d23464a416ea7039f57ba8413cf3f00d9a7a5b356ab20dcb8ed11b3561f7bce372b8534d2870c7ee270 -b5d59075cb5abde5391f64b6c3b8b50adc6e1f654e2a580b6d6d6eff3f4fbdd8fffc92e06809c393f5c8eab37f774c4b -afcfb6903ef13e493a1f7308675582f15af0403b6553e8c37afb8b2808ad21b88b347dc139464367dc260df075fea1ad -810fbbe808375735dd22d5bc7fc3828dc49fdd22cc2d7661604e7ac9c4535c1df578780affb3b895a0831640a945bcad -8056b0c678803b416f924e09a6299a33cf9ad7da6fe1ad7accefe95c179e0077da36815fde3716711c394e2c5ea7127f -8b67403702d06979be19f1d6dc3ec73cc2e81254d6b7d0cc49cd4fdda8cd51ab0835c1d2d26fc0ecab5df90585c2f351 -87f97f9e6d4be07e8db250e5dd2bffdf1390665bc5709f2b631a6fa69a7fca958f19bd7cc617183da1f50ee63e9352b5 -ae151310985940471e6803fcf37600d7fa98830613e381e00dab943aec32c14162d51c4598e8847148148000d6e5af5c -81eb537b35b7602c45441cfc61b27fa9a30d3998fad35a064e05bc9479e9f10b62eba2b234b348219eea3cadcaac64bb -8a441434934180ab6f5bc541f86ebd06eadbee01f438836d797e930fa803a51510e005c9248cecc231a775b74d12b5e9 -81f3c250a27ba14d8496a5092b145629eb2c2e6a5298438670375363f57e2798207832c8027c3e9238ad94ecdadfc4df -a6217c311f2f3db02ceaa5b6096849fe92b6f4b6f1491535ef8525f6ccee6130bed2809e625073ecbaddd4a3eb3df186 -82d1c396f0388b942cf22b119d7ef1ad03d3dad49a74d9d01649ee284f377c8daddd095d596871669e16160299a210db -a40ddf7043c5d72a7246bd727b07f7fff1549f0e443d611de6f9976c37448b21664c5089c57f20105102d935ab82f27b -b6c03c1c97adf0c4bf4447ec71366c6c1bff401ba46236cd4a33d39291e7a1f0bb34bd078ba3a18d15c98993b153a279 -8a94f5f632068399c359c4b3a3653cb6df2b207379b3d0cdace51afdf70d6d5cce6b89a2b0fee66744eba86c98fb21c2 -b2f19e78ee85073f680c3bba1f07fd31b057c00b97040357d97855b54a0b5accb0d3b05b2a294568fcd6a4be6f266950 -a74632d13bbe2d64b51d7a9c3ae0a5a971c19f51cf7596a807cea053e6a0f3719700976d4e394b356c0329a2dced9aa2 -afef616d341a9bc94393b8dfba68ff0581436aa3a3adb7c26a1bbf2cf19fa877066191681f71f17f3cd6f9cf6bf70b5a -8ce96d93ae217408acf7eb0f9cbb9563363e5c7002e19bbe1e80760bc9d449daee2118f3878b955163ed664516b97294 -8414f79b496176bc8b8e25f8e4cfee28f4f1c2ddab099d63d2aca1b6403d26a571152fc3edb97794767a7c4686ad557c -b6c61d01fd8ce087ef9f079bf25bf10090db483dd4f88c4a786d31c1bdf52065651c1f5523f20c21e75cea17df69ab73 -a5790fd629be70545093631efadddc136661f63b65ec682609c38ef7d3d7fa4e56bdf94f06e263bc055b90cb1c6bcefe -b515a767e95704fb7597bca9e46f1753abacdc0e56e867ee3c6f4cd382643c2a28e65312c05ad040eaa3a8cbe7217a65 -8135806a02ead6aa92e9adb6fefb91349837ab73105aaa7be488ef966aa8dfaafdfa64bbae30fcbfa55dd135a036a863 -8f22435702716d76b1369750694540742d909d5e72b54d0878245fab7c269953b1c6f2b29c66f08d5e0263ca3a731771 -8e0f8a8e8753e077dac95848212aeffd51c23d9b6d611df8b102f654089401954413ecbedc6367561ca599512ae5dda7 -815a9084e3e2345f24c5fa559deec21ee1352fb60f4025c0779be65057f2d528a3d91593bd30d3a185f5ec53a9950676 -967e6555ccba395b2cc1605f8484c5112c7b263f41ce8439a99fd1c71c5ed14ad02684d6f636364199ca48afbbde13be -8cd0ccf17682950b34c796a41e2ea7dd5367aba5e80a907e01f4cdc611e4a411918215e5aebf4292f8b24765d73314a6 -a58bf1bbb377e4b3915df6f058a0f53b8fb8130fdec8c391f6bc82065694d0be59bb67ffb540e6c42cc8b380c6e36359 -92af3151d9e6bfb3383d85433e953c0160859f759b0988431ec5893542ba40288f65db43c78a904325ef8d324988f09d -8011bbb05705167afb47d4425065630f54cb86cd462095e83b81dfebf348f846e4d8fbcf1c13208f5de1931f81da40b9 -81c743c104fc3cb047885c9fa0fb9705c3a83ee24f690f539f4985509c3dafd507af3f6a2128276f45d5939ef70c167f -a2c9679b151c041aaf5efeac5a737a8f70d1631d931609fca16be1905682f35e291292874cb3b03f14994f98573c6f44 -a4949b86c4e5b1d5c82a337e5ce6b2718b1f7c215148c8bfb7e7c44ec86c5c9476048fc5c01f57cb0920876478c41ad6 -86c2495088bd1772152e527a1da0ef473f924ea9ab0e5b8077df859c28078f73c4e22e3a906b507fdf217c3c80808b5c -892e0a910dcf162bcea379763c3e2349349e4cda9402949255ac4a78dd5a47e0bf42f5bd0913951576b1d206dc1e536a -a7009b2c6b396138afe4754b7cc10dee557c51c7f1a357a11486b3253818531f781ea8107360c8d4c3b1cd96282353c0 -911763ef439c086065cc7b4e57484ed6d693ea44acee4b18c9fd998116da55fbe7dcb8d2a0f0f9b32132fca82d73dff6 -a722000b95a4a2d40bed81870793f15ba2af633f9892df507f2842e52452e02b5ea8dea6a043c2b2611d82376e33742a -9387ac49477bd719c2f92240d0bdfcf9767aad247ca93dc51e56106463206bc343a8ec855eb803471629a66fffb565d6 -92819a1fa48ab4902939bb72a0a4e6143c058ea42b42f9bc6cea5df45f49724e2530daf3fc4f097cceefa2a8b9db0076 -98eac7b04537653bc0f4941aae732e4b1f84bd276c992c64a219b8715eb1fb829b5cbd997d57feb15c7694c468f95f70 -b275e7ba848ce21bf7996e12dbeb8dadb5d0e4f1cb5a0248a4f8f9c9fe6c74e3c93f4b61edbcb0a51af5a141e1c14bc7 -97243189285aba4d49c53770c242f2faf5fd3914451da4931472e3290164f7663c726cf86020f8f181e568c72fd172d1 -839b0b3c25dd412bee3dc24653b873cc65454f8f16186bb707bcd58259c0b6765fa4c195403209179192a4455c95f3b8 -8689d1a870514568a074a38232e2ceb4d7df30fabeb76cff0aed5b42bf7f02baea12c5fadf69f4713464dbd52aafa55f -8958ae7b290f0b00d17c3e9fdb4dbf168432b457c7676829299dd428984aba892de1966fc106cfc58a772862ecce3976 -a422bc6bd68b8870cfa5bc4ce71781fd7f4368b564d7f1e0917f6013c8bbb5b240a257f89ecfdbecb40fe0f3aa31d310 -aa61f78130cebe09bc9a2c0a37f0dd57ed2d702962e37d38b1df7f17dc554b1d4b7a39a44182a452ce4c5eb31fa4cfcc -b7918bd114f37869bf1a459023386825821bfadce545201929d13ac3256d92a431e34f690a55d944f77d0b652cefeffc -819bba35fb6ace1510920d4dcff30aa682a3c9af9022e287751a6a6649b00c5402f14b6309f0aeef8fce312a0402915e -8b7c9ad446c6f63c11e1c24e24014bd570862b65d53684e107ba9ad381e81a2eaa96731b4b33536efd55e0f055071274 -8fe79b53f06d33386c0ec7d6d521183c13199498594a46d44a8a716932c3ec480c60be398650bbfa044fa791c4e99b65 -9558e10fb81250b9844c99648cf38fa05ec1e65d0ccbb18aa17f2d1f503144baf59d802c25be8cc0879fff82ed5034ad -b538a7b97fbd702ba84645ca0a63725be1e2891c784b1d599e54e3480e4670d0025526674ef5cf2f87dddf2290ba09f0 -92eafe2e869a3dd8519bbbceb630585c6eb21712b2f31e1b63067c0acb5f9bdbbcbdb612db4ea7f9cc4e7be83d31973f -b40d21390bb813ab7b70a010dff64c57178418c62685761784e37d327ba3cb9ef62df87ecb84277c325a637fe3709732 -b349e6fbf778c4af35fbed33130bd8a7216ed3ba0a79163ebb556e8eb8e1a7dad3456ddd700dad9d08d202491c51b939 -a8fdaedecb251f892b66c669e34137f2650509ade5d38fbe8a05d9b9184bb3b2d416186a3640429bd1f3e4b903c159dd -ac6167ebfee1dbab338eff7642f5e785fc21ef0b4ddd6660333fe398068cbd6c42585f62e81e4edbb72161ce852a1a4f -874b1fbf2ebe140c683bd7e4e0ab017afa5d4ad38055aaa83ee6bbef77dbc88a6ce8eb0dcc48f0155244af6f86f34c2d -903c58e57ddd9c446afab8256a6bb6c911121e6ccfb4f9b4ed3e2ed922a0e500a5cb7fa379d5285bc16e11dac90d1fda -8dae7a0cffa2fd166859cd1bf10ff82dd1932e488af377366b7efc0d5dec85f85fe5e8150ff86a79a39cefc29631733a -aa047857a47cc4dfc08585f28640420fcf105b881fd59a6cf7890a36516af0644d143b73f3515ab48faaa621168f8c31 -864508f7077c266cc0cb3f7f001cb6e27125ebfe79ab57a123a8195f2e27d3799ff98413e8483c533b46a816a3557f1f -8bcd45ab1f9cbab36937a27e724af819838f66dfeb15923f8113654ff877bd8667c54f6307aaf0c35027ca11b6229bfd -b21aa34da9ab0a48fcfdd291df224697ce0c1ebc0e9b022fdee8750a1a4b5ba421c419541ed5c98b461eecf363047471 -a9a18a2ab2fae14542dc336269fe612e9c1af6cf0c9ac933679a2f2cb77d3c304114f4d219ca66fe288adde30716775b -b5205989b92c58bdda71817f9a897e84100b5c4e708de1fced5c286f7a6f01ae96b1c8d845f3a320d77c8e2703c0e8b1 -a364059412bbcc17b8907d43ac8e5df90bc87fd1724b5f99832d0d24559fae6fa76a74cff1d1eac8cbac6ec80b44af20 -ae709f2c339886b31450834cf29a38b26eb3b0779bd77c9ac269a8a925d1d78ea3837876c654b61a8fe834b3b6940808 -8802581bba66e1952ac4dab36af371f66778958f4612901d95e5cac17f59165e6064371d02de8fb6fccf89c6dc8bd118 -a313252df653e29c672cbcfd2d4f775089cb77be1077381cf4dc9533790e88af6cedc8a119158e7da5bf6806ad9b91a1 -992a065b4152c7ef11515cd54ba9d191fda44032a01aed954acff3443377ee16680c7248d530b746b8c6dee2d634e68c -b627b683ee2b32c1ab4ccd27b9f6cce2fe097d96386fa0e5c182ad997c4c422ab8dfc03870cd830b8c774feb66537282 -b823cf8a9aee03dadd013eb9efe40a201b4b57ef67efaae9f99683005f5d1bf55e950bf4af0774f50859d743642d3fea -b8a7449ffac0a3f206677097baf7ce00ca07a4d2bd9b5356fbcb83f3649b0fda07cfebad220c1066afba89e5a52abf4b -b2dd1a2f986395bb4e3e960fbbe823dbb154f823284ebc9068502c19a7609790ec0073d08bfa63f71e30c7161b6ef966 -98e5236de4281245234f5d40a25b503505af140b503a035fc25a26159a9074ec81512b28f324c56ea2c9a5aa7ce90805 -89070847dc8bbf5bc4ed073aa2e2a1f699cf0c2ca226f185a0671cecc54e7d3e14cd475c7752314a7a8e7476829da4bc -a9402dc9117fdb39c4734c0688254f23aed3dce94f5f53f5b7ef2b4bf1b71a67f85ab1a38ec224a59691f3bee050aeb3 -957288f9866a4bf56a4204218ccc583f717d7ce45c01ea27142a7e245ad04a07f289cc044f8cf1f21d35e67e39299e9c -b2fb31ccb4e69113763d7247d0fc8edaae69b550c5c56aecacfd780c7217dc672f9fb7496edf4aba65dacf3361268e5b -b44a4526b2f1d6eb2aa8dba23bfa385ff7634572ab2afddd0546c3beb630fbfe85a32f42dd287a7fec069041411537f7 -8db5a6660c3ac7fd7a093573940f068ee79a82bc17312af900b51c8c439336bc86ca646c6b7ab13aaaa008a24ca508ab -8f9899a6d7e8eb4367beb5c060a1f8e94d8a21099033ae582118477265155ba9e72176a67f7f25d7bad75a152b56e21a -a67de0e91ade8d69a0e00c9ff33ee2909b8a609357095fa12319e6158570c232e5b6f4647522efb7345ce0052aa9d489 -82eb2414898e9c3023d57907a2b17de8e7eea5269029d05a94bfd7bf5685ac4a799110fbb375eb5e0e2bd16acf6458ae -94451fc7fea3c5a89ba701004a9693bab555cb622caf0896b678faba040409fdfd14a978979038b2a81e8f0abc4994d2 -ac879a5bb433998e289809a4a966bd02b4bf6a9c1cc276454e39c886efcf4fc68baebed575826bde577ab5aa71d735a9 -880c0f8f49c875dfd62b4ddedde0f5c8b19f5687e693717f7e5c031bc580e58e13ab497d48b4874130a18743c59fdce3 -b582af8d8ff0bf76f0a3934775e0b54c0e8fed893245d7d89cae65b03c8125b7237edc29dc45b4fe1a3fe6db45d280ee -89f337882ed3ae060aaee98efa20d79b6822bde9708c1c5fcee365d0ec9297f694cae37d38fd8e3d49717c1e86f078e7 -826d2c1faea54061848b484e288a5f4de0d221258178cf87f72e14baaa4acc21322f8c9eab5dde612ef497f2d2e1d60b -a5333d4f227543e9cd741ccf3b81db79f2f03ca9e649e40d6a6e8ff9073e06da83683566d3b3c8d7b258c62970fb24d1 -a28f08c473db06aaf4c043a2fae82b3c8cfaa160bce793a4c208e4e168fb1c65115ff8139dea06453c5963d95e922b94 -8162546135cc5e124e9683bdfaa45833c18553ff06a0861c887dc84a5b12ae8cd4697f6794c7ef6230492c32faba7014 -b23f0d05b74c08d6a7df1760792be83a761b36e3f8ae360f3c363fb196e2a9dd2de2e492e49d36561366e14daa77155c -b6f70d6c546722d3907c708d630dbe289771d2c8bf059c2e32b77f224696d750b4dda9b3a014debda38e7d02c9a77585 -83bf4c4a9f3ca022c631017e7a30ea205ba97f7f5927cba8fc8489a4646eac6712cb821c5668c9ffe94d69d524374a27 -b0371475425a8076d0dd5f733f55aabbe42d20a7c8ea7da352e736d4d35a327b2beb370dfcb05284e22cfd69c5f6c4cc -a0031ba7522c79211416c2cca3aa5450f96f8fee711552a30889910970ba13608646538781a2c08b834b140aadd7166f -99d273c80c7f2dc6045d4ed355d9fc6f74e93549d961f4a3b73cd38683f905934d359058cd1fc4da8083c7d75070487f -b0e4b0efa3237793e9dcce86d75aafe9879c5fa23f0d628649aef2130454dcf72578f9bf227b9d2b9e05617468e82588 -a5ab076fa2e1c5c51f3ae101afdd596ad9d106bba7882b359c43d8548b64f528af19afa76cd6f40da1e6c5fca4def3fa -8ce2299e570331d60f6a6eff1b271097cd5f1c0e1113fc69b89c6a0f685dabea3e5bc2ac6bd789aa492ab189f89be494 -91b829068874d911a310a5f9dee001021f97471307b5a3de9ec336870ec597413e1d92010ce320b619f38bed7c4f7910 -b14fe91f4b07bf33b046e9285b66cb07927f3a8da0af548ac2569b4c4fb1309d3ced76d733051a20814e90dd5b75ffd1 -abaab92ea6152d40f82940277c725aa768a631ee0b37f5961667f82fb990fc11e6d3a6a2752b0c6f94563ed9bb28265c -b7fe28543eca2a716859a76ab9092f135337e28109544f6bd2727728d0a7650428af5713171ea60bfc273d1c821d992c -8a4917b2ab749fc7343fc64bdf51b6c0698ff15d740cc7baf248c030475c097097d5a473bcc00d8c25817563fe0447b4 -aa96156d1379553256350a0a3250166add75948fb9cde62aa555a0a9dc0a9cb7f2f7b8428aff66097bf6bfedaf14bbe2 -ae4ffeb9bdc76830d3eca2b705f30c1bdede6412fa064260a21562c8850c7fb611ec62bc68479fe48f692833e6f66d8d -b96543caaba9d051600a14997765d49e4ab10b07c7a92cccf0c90b309e6da334fdd6d18c96806cbb67a7801024fbd3c7 -97b2b9ad76f19f500fcc94ca8e434176249f542ac66e5881a3dccd07354bdab6a2157018b19f8459437a68d8b86ba8e0 -a8d206f6c5a14c80005849474fde44b1e7bcf0b2d52068f5f97504c3c035b09e65e56d1cf4b5322791ae2c2fdbd61859 -936bad397ad577a70cf99bf9056584a61bd7f02d2d5a6cf219c05d770ae30a5cd902ba38366ce636067fc1dd10108d31 -a77e30195ee402b84f3882e2286bf5380c0ed374a112dbd11e16cef6b6b61ab209d4635e6f35cdaaa72c1a1981d5dabe -a46ba4d3947188590a43c180757886a453a0503f79cc435322d92490446f37419c7b999fdf868a023601078070e03346 -80d8d4c5542f223d48240b445d4d8cf6a75d120b060bc08c45e99a13028b809d910b534d2ac47fb7068930c54efd8da9 -803be9c68c91b42b68e1f55e58917a477a9a6265e679ca44ee30d3eb92453f8c89c64eafc04c970d6831edd33d066902 -b14b2b3d0dfe2bb57cee4cd72765b60ac33c1056580950be005790176543826c1d4fbd737f6cfeada6c735543244ab57 -a9e480188bba1b8fb7105ff12215706665fd35bf1117bacfb6ab6985f4dbc181229873b82e5e18323c2b8f5de03258e0 -a66a0f0779436a9a3999996d1e6d3000f22c2cac8e0b29cddef9636393c7f1457fb188a293b6c875b05d68d138a7cc4a -848397366300ab40c52d0dbbdafbafef6cd3dadf1503bb14b430f52bb9724188928ac26f6292a2412bc7d7aa620763c8 -95466cc1a78c9f33a9aaa3829a4c8a690af074916b56f43ae46a67a12bb537a5ac6dbe61590344a25b44e8512355a4a7 -8b5f7a959f818e3baf0887f140f4575cac093d0aece27e23b823cf421f34d6e4ff4bb8384426e33e8ec7b5eed51f6b5c -8d5e1368ec7e3c65640d216bcc5d076f3d9845924c734a34f3558ac0f16e40597c1a775a25bf38b187213fbdba17c93b -b4647c1b823516880f60d20c5cc38c7f80b363c19d191e8992226799718ee26b522a12ecb66556ed3d483aa4824f3326 -ac3abaea9cd283eb347efda4ed9086ea3acf495043e08d0d19945876329e8675224b685612a6badf8fd72fb6274902b1 -8eae1ce292d317aaa71bcf6e77e654914edd5090e2e1ebab78b18bb41b9b1bc2e697439f54a44c0c8aa0d436ebe6e1a9 -94dc7d1aec2c28eb43d93b111fa59aaa0d77d5a09501220bd411768c3e52208806abf973c6a452fd8292ff6490e0c9e2 -8fd8967f8e506fef27d17b435d6b86b232ec71c1036351f12e6fb8a2e12daf01d0ee04451fb944d0f1bf7fd20e714d02 -824e6865be55d43032f0fec65b3480ea89b0a2bf860872237a19a54bc186a85d2f8f9989cc837fbb325b7c72d9babe2c -8bd361f5adb27fd6f4e3f5de866e2befda6a8454efeb704aacc606f528c03f0faae888f60310e49440496abd84083ce2 -b098a3c49f2aaa28b6b3e85bc40ce6a9cdd02134ee522ae73771e667ad7629c8d82c393fba9f27f5416986af4c261438 -b385f5ca285ff2cfe64dcaa32dcde869c28996ed091542600a0b46f65f3f5a38428cca46029ede72b6cf43e12279e3d3 -8196b03d011e5be5288196ef7d47137d6f9237a635ab913acdf9c595fa521d9e2df722090ec7eb0203544ee88178fc5f -8ed1270211ef928db18e502271b7edf24d0bbd11d97f2786aee772d70c2029e28095cf8f650b0328cc8a4c38d045316d -a52ab60e28d69b333d597a445884d44fd2a7e1923dd60f763951e1e45f83e27a4dac745f3b9eff75977b3280e132c15d -91e9fe78cdac578f4a4687f71b800b35da54b824b1886dafec073a3c977ce7a25038a2f3a5b1e35c2c8c9d1a7312417c -a42832173f9d9491c7bd93b21497fbfa4121687cd4d2ab572e80753d7edcbb42cfa49f460026fbde52f420786751a138 -97b947126d84dcc70c97be3c04b3de3f239b1c4914342fa643b1a4bb8c4fe45c0fcb585700d13a7ed50784790c54bef9 -860e407d353eac070e2418ef6cb80b96fc5f6661d6333e634f6f306779651588037be4c2419562c89c61f9aa2c4947f5 -b2c9d93c3ba4e511b0560b55d3501bf28a510745fd666b3cb532db051e6a8617841ea2f071dda6c9f15619c7bfd2737f -8596f4d239aeeac78311207904d1bd863ef68e769629cc379db60e019aaf05a9d5cd31dc8e630b31e106a3a93e47cbc5 -8b26e14e2e136b65c5e9e5c2022cee8c255834ea427552f780a6ca130a6446102f2a6f334c3f9a0308c53df09e3dba7e -b54724354eb515a3c8bed0d0677ff1db94ac0a07043459b4358cb90e3e1aa38ac23f2caa3072cf9647275d7cd61d0e80 -b7ce9fe0e515e7a6b2d7ddcb92bc0196416ff04199326aea57996eef8c5b1548bd8569012210da317f7c0074691d01b7 -a1a13549c82c877253ddefa36a29ea6a23695ee401fdd48e65f6f61e5ebd956d5e0edeff99484e9075cb35071fec41e2 -838ba0c1e5bd1a6da05611ff1822b8622457ebd019cb065ece36a2d176bd2d889511328120b8a357e44569e7f640c1e6 -b916eccff2a95519400bbf76b5f576cbe53cf200410370a19d77734dc04c05b585cfe382e8864e67142d548cd3c4c2f4 -a610447cb7ca6eea53a6ff1f5fe562377dcb7f4aaa7300f755a4f5e8eba61e863c51dc2aa9a29b35525b550fbc32a0fe -9620e8f0f0ee9a4719aa9685eeb1049c5c77659ba6149ec4c158f999cfd09514794b23388879931fe26fea03fa471fd3 -a9dcf8b679e276583cf5b9360702a185470d09aea463dc474ee9c8aee91ef089dacb073e334e47fbc78ec5417c90465c -8c9adee8410bdd99e5b285744cee61e2593b6300ff31a8a83b0ec28da59475a5c6fb9346fe43aadea2e6c3dad2a8e30a -97d5afe9b3897d7b8bb628b7220cf02d8ee4e9d0b78f5000d500aaf4c1df9251aaaabfd1601626519f9d66f00a821d4e -8a382418157b601ce4c3501d3b8409ca98136a4ef6abcbf62885e16e215b76b035c94d149cc41ff92e42ccd7c43b9b3d -b64b8d11fb3b01abb2646ac99fdb9c02b804ce15d98f9fe0fbf1c9df8440c71417487feb6cdf51e3e81d37104b19e012 -849d7d044f9d8f0aab346a9374f0b3a5d14a9d1faa83dbacccbdc629ad1ef903a990940255564770537f8567521d17f0 -829dbb0c76b996c2a91b4cbbe93ba455ca0d5729755e5f0c92aaee37dff7f36fcdc06f33aca41f1b609c784127b67d88 -85a7c0069047b978422d264d831ab816435f63938015d2e977222b6b5746066c0071b7f89267027f8a975206ed25c1b0 -84b9fbc1cfb302df1acdcf3dc5d66fd1edfe7839f7a3b2fb3a0d5548656249dd556104d7c32b73967bccf0f5bdcf9e3b -972220ac5b807f53eac37dccfc2ad355d8b21ea6a9c9b011c09fe440ddcdf7513e0b43d7692c09ded80d7040e26aa28f -855885ed0b21350baeca890811f344c553cf9c21024649c722453138ba29193c6b02c4b4994cd414035486f923472e28 -841874783ae6d9d0e59daea03e96a01cbbe4ecaced91ae4f2c8386e0d87b3128e6d893c98d17c59e4de1098e1ad519dd -827e50fc9ce56f97a4c3f2f4cbaf0b22f1c3ce6f844ff0ef93a9c57a09b8bf91ebfbd2ba9c7f83c442920bffdaf288cc -a441f9136c7aa4c08d5b3534921b730e41ee91ab506313e1ba5f7c6f19fd2d2e1594e88c219834e92e6fb95356385aa7 -97d75b144471bf580099dd6842b823ec0e6c1fb86dd0da0db195e65524129ea8b6fd4a7a9bbf37146269e938a6956596 -a4b6fa87f09d5a29252efb2b3aaab6b3b6ea9fab343132a651630206254a25378e3e9d6c96c3d14c150d01817d375a8e -a31a671876d5d1e95fe2b8858dc69967231190880529d57d3cab7f9f4a2b9b458ac9ee5bdaa3289158141bf18f559efb -90bee6fff4338ba825974021b3b2a84e36d617e53857321f13d2b3d4a28954e6de3b3c0e629d61823d18a9763313b3bf -96b622a63153f393bb419bfcf88272ea8b3560dbd46b0aa07ada3a6223990d0abdd6c2adb356ef4be5641688c8d83941 -84c202adeaff9293698022bc0381adba2cd959f9a35a4e8472288fd68f96f6de8be9da314c526d88e291c96b1f3d6db9 -8ca01a143b8d13809e5a8024d03e6bc9492e22226073ef6e327edf1328ef4aff82d0bcccee92cb8e212831fa35fe1204 -b2f970dbad15bfbefb38903c9bcc043d1367055c55dc1100a850f5eb816a4252c8c194b3132c929105511e14ea10a67d -a5e36556472a95ad57eb90c3b6623671b03eafd842238f01a081997ffc6e2401f76e781d049bb4aa94d899313577a9cf -8d1057071051772f7c8bedce53a862af6fd530dd56ae6321eaf2b9fc6a68beff5ed745e1c429ad09d5a118650bfd420a -8aadc4f70ace4fcb8d93a78610779748dcffc36182d45b932c226dc90e48238ea5daa91f137c65ed532352c4c4d57416 -a2ea05ae37e673b4343232ae685ee14e6b88b867aef6dfac35db3589cbcd76f99540fed5c2641d5bb5a4a9f808e9bf0d -947f1abad982d65648ae4978e094332b4ecb90f482c9be5741d5d1cf5a28acf4680f1977bf6e49dd2174c37f11e01296 -a27b144f1565e4047ba0e3f4840ef19b5095d1e281eaa463c5358f932114cbd018aa6dcf97546465cf2946d014d8e6d6 -8574e1fc3acade47cd4539df578ce9205e745e161b91e59e4d088711a7ab5aa3b410d517d7304b92109924d9e2af8895 -a48ee6b86b88015d6f0d282c1ae01d2a5b9e8c7aa3d0c18b35943dceb1af580d08a65f54dc6903cde82fd0d73ce94722 -8875650cec543a7bf02ea4f2848a61d167a66c91ffaefe31a9e38dc8511c6a25bde431007eefe27a62af3655aca208dc -999b0a6e040372e61937bf0d68374e230346b654b5a0f591a59d33a4f95bdb2f3581db7c7ccb420cd7699ed709c50713 -878c9e56c7100c5e47bbe77dc8da5c5fe706cec94d37fa729633bca63cace7c40102eee780fcdabb655f5fa47a99600e -865006fb5b475ada5e935f27b96f9425fc2d5449a3c106aa366e55ebed3b4ee42adc3c3f0ac19fd129b40bc7d6bc4f63 -b7a7da847f1202e7bc1672553e68904715e84fd897d529243e3ecda59faa4e17ba99c649a802d53f6b8dfdd51f01fb74 -8b2fb4432c05653303d8c8436473682933a5cb604da10c118ecfcd2c8a0e3132e125afef562bdbcc3df936164e5ce4f2 -808d95762d33ddfa5d0ee3d7d9f327de21a994d681a5f372e2e3632963ea974da7f1f9e5bac8ccce24293509d1f54d27 -932946532e3c397990a1df0e94c90e1e45133e347a39b6714c695be21aeb2d309504cb6b1dde7228ff6f6353f73e1ca2 -9705e7c93f0cdfaa3fa96821f830fe53402ad0806036cd1b48adc2f022d8e781c1fbdab60215ce85c653203d98426da3 -aa180819531c3ec1feb829d789cb2092964c069974ae4faad60e04a6afcce5c3a59aec9f11291e6d110a788d22532bc6 -88f755097f7e25cb7dd3c449520c89b83ae9e119778efabb54fbd5c5714b6f37c5f9e0346c58c6ab09c1aef2483f895d -99fc03ab7810e94104c494f7e40b900f475fde65bdec853e60807ffd3f531d74de43335c3b2646b5b8c26804a7448898 -af2dea9683086bed1a179110efb227c9c00e76cd00a2015b089ccbcee46d1134aa18bda5d6cab6f82ae4c5cd2461ac21 -a500f87ba9744787fdbb8e750702a3fd229de6b8817594348dec9a723b3c4240ddfa066262d002844b9e38240ce55658 -924d0e45c780f5bc1c1f35d15dfc3da28036bdb59e4c5440606750ecc991b85be18bc9a240b6c983bc5430baa4c68287 -865b11e0157b8bf4c5f336024b016a0162fc093069d44ac494723f56648bc4ded13dfb3896e924959ea11c96321afefc -93672d8607d4143a8f7894f1dcca83fb84906dc8d6dd7dd063bb0049cfc20c1efd933e06ca7bd03ea4cb5a5037990bfe -826891efbdff0360446825a61cd1fa04326dd90dae8c33dfb1ed97b045e165766dd070bd7105560994d0b2044bdea418 -93c4a4a8bcbc8b190485cc3bc04175b7c0ed002c28c98a540919effd6ed908e540e6594f6db95cd65823017258fb3b1c -aeb2a0af2d2239fda9aa6b8234b019708e8f792834ff0dd9c487fa09d29800ddceddd6d7929faa9a3edcb9e1b3aa0d6b -87f11de7236d387863ec660d2b04db9ac08143a9a2c4dfff87727c95b4b1477e3bc473a91e5797313c58754905079643 -80dc1db20067a844fe8baceca77f80db171a5ca967acb24e2d480eae9ceb91a3343c31ad1c95b721f390829084f0eae6 -9825c31f1c18da0de3fa84399c8b40f8002c3cae211fb6a0623c76b097b4d39f5c50058f57a16362f7a575909d0a44a2 -a99fc8de0c38dbf7b9e946de83943a6b46a762167bafe2a603fb9b86f094da30d6de7ed55d639aafc91936923ee414b3 -ad594678b407db5d6ea2e90528121f84f2b96a4113a252a30d359a721429857c204c1c1c4ff71d8bb5768c833f82e80e -b33d985e847b54510b9b007e31053732c8a495e43be158bd2ffcea25c6765bcbc7ca815f7c60b36ad088b955dd6e9350 -815f8dfc6f90b3342ca3fbd968c67f324dae8f74245cbf8bc3bef10e9440c65d3a2151f951e8d18959ba01c1b50b0ec1 -94c608a362dd732a1abc56e338637c900d59013db8668e49398b3c7a0cae3f7e2f1d1bf94c0299eeafe6af7f76c88618 -8ebd8446b23e5adfcc393adc5c52fe172f030a73e63cd2d515245ca0dd02782ceed5bcdd9ccd9c1b4c5953dfac9c340c -820437f3f6f9ad0f5d7502815b221b83755eb8dc56cd92c29e9535eb0b48fb8d08c9e4fcc26945f9c8cca60d89c44710 -8910e4e8a56bf4be9cc3bbf0bf6b1182a2f48837a2ed3c2aaec7099bfd7f0c83e14e608876b17893a98021ff4ab2f20d -9633918fde348573eec15ce0ad53ac7e1823aac86429710a376ad661002ae6d049ded879383faaa139435122f64047c6 -a1f5e3fa558a9e89318ca87978492f0fb4f6e54a9735c1b8d2ecfb1d1c57194ded6e0dd82d077b2d54251f3bee1279e1 -b208e22d04896abfd515a95c429ff318e87ff81a5d534c8ac2c33c052d6ffb73ef1dccd39c0bbe0734b596c384014766 -986d5d7d2b5bde6d16336f378bd13d0e671ad23a8ec8a10b3fc09036faeeb069f60662138d7a6df3dfb8e0d36180f770 -a2d4e6c5f5569e9cef1cddb569515d4b6ace38c8aed594f06da7434ba6b24477392cc67ba867c2b079545ca0c625c457 -b5ac32b1d231957d91c8b7fc43115ce3c5c0d8c13ca633374402fa8000b6d9fb19499f9181844f0c10b47357f3f757ce -96b8bf2504b4d28fa34a4ec378e0e0b684890c5f44b7a6bb6e19d7b3db2ab27b1e2686389d1de9fbd981962833a313ea -953bfd7f6c3a0469ad432072b9679a25486f5f4828092401eff494cfb46656c958641a4e6d0d97d400bc59d92dba0030 -876ab3cea7484bbfd0db621ec085b9ac885d94ab55c4bb671168d82b92e609754b86aaf472c55df3d81421d768fd108a -885ff4e67d9ece646d02dd425aa5a087e485c3f280c3471b77532b0db6145b69b0fbefb18aa2e3fa5b64928b43a94e57 -b91931d93f806d0b0e6cc62a53c718c099526140f50f45d94b8bbb57d71e78647e06ee7b42aa5714aed9a5c05ac8533f -a0313eeadd39c720c9c27b3d671215331ab8d0a794e71e7e690f06bcd87722b531d6525060c358f35f5705dbb7109ccb -874c0944b7fedc6701e53344100612ddcb495351e29305c00ec40a7276ea5455465ffb7bded898886c1853139dfb1fc7 -8dc31701a01ee8137059ca1874a015130d3024823c0576aa9243e6942ec99d377e7715ed1444cd9b750a64b85dcaa3e5 -836d2a757405e922ec9a2dfdcf489a58bd48b5f9683dd46bf6047688f778c8dee9bc456de806f70464df0b25f3f3d238 -b30b0a1e454a503ea3e2efdec7483eaf20b0a5c3cefc42069e891952b35d4b2c955cf615f3066285ed8fafd9fcfbb8f6 -8e6d4044b55ab747e83ec8762ea86845f1785cc7be0279c075dadf08aca3ccc5a096c015bb3c3f738f647a4eadea3ba5 -ad7735d16ab03cbe09c029610aa625133a6daecfc990b297205b6da98eda8c136a7c50db90f426d35069708510d5ae9c -8d62d858bbb59ec3c8cc9acda002e08addab4d3ad143b3812098f3d9087a1b4a1bb255dcb1635da2402487d8d0249161 -805beec33238b832e8530645a3254aeef957e8f7ea24bcfc1054f8b9c69421145ebb8f9d893237e8a001c857fedfc77e -b1005644be4b085e3f5775aa9bd3e09a283e87ddada3082c04e7a62d303dcef3b8cf8f92944c200c7ae6bb6bdf63f832 -b4ba0e0790dc29063e577474ffe3b61f5ea2508169f5adc1e394934ebb473e356239413a17962bc3e5d3762d72cce8c2 -a157ba9169c9e3e6748d9f1dd67fbe08b9114ade4c5d8fc475f87a764fb7e6f1d21f66d7905cd730f28a1c2d8378682a -913e52b5c93989b5d15e0d91aa0f19f78d592bc28bcfdfddc885a9980c732b1f4debb8166a7c4083c42aeda93a702898 -90fbfc1567e7cd4e096a38433704d3f96a2de2f6ed3371515ccc30bc4dd0721a704487d25a97f3c3d7e4344472702d8d -89646043028ffee4b69d346907586fd12c2c0730f024acb1481abea478e61031966e72072ff1d5e65cb8c64a69ad4eb1 -b125a45e86117ee11d2fb42f680ab4a7894edd67ff927ae2c808920c66c3e55f6a9d4588eee906f33a05d592e5ec3c04 -aad47f5b41eae9be55fb4f67674ff1e4ae2482897676f964a4d2dcb6982252ee4ff56aac49578b23f72d1fced707525e -b9ddff8986145e33851b4de54d3e81faa3352e8385895f357734085a1616ef61c692d925fe62a5ed3be8ca49f5d66306 -b3cb0963387ed28c0c0adf7fe645f02606e6e1780a24d6cecef5b7c642499109974c81a7c2a198b19862eedcea2c2d8c -ac9c53c885457aaf5cb36c717a6f4077af701e0098eebd7aa600f5e4b14e6c1067255b3a0bc40e4a552025231be7de60 -8e1a8d823c4603f6648ec21d064101094f2a762a4ed37dd2f0a2d9aa97b2d850ce1e76f4a4b8cae58819b058180f7031 -b268b73bf7a179b6d22bd37e5e8cb514e9f5f8968c78e14e4f6d5700ca0d0ca5081d0344bb73b028970eebde3cb4124e -a7f57d71940f0edbd29ed8473d0149cae71d921dd15d1ff589774003e816b54b24de2620871108cec1ab9fa956ad6ce6 -8053e6416c8b120e2b999cc2fc420a6a55094c61ac7f2a6c6f0a2c108a320890e389af96cbe378936132363c0d551277 -b3823f4511125e5aa0f4269e991b435a0d6ceb523ebd91c04d7add5534e3df5fc951c504b4fd412a309fd3726b7f940b -ae6eb04674d04e982ca9a6add30370ab90e303c71486f43ed3efbe431af1b0e43e9d06c11c3412651f304c473e7dbf39 -96ab55e641ed2e677591f7379a3cd126449614181fce403e93e89b1645d82c4af524381ff986cae7f9cebe676878646d -b52423b4a8c37d3c3e2eca8f0ddbf7abe0938855f33a0af50f117fab26415fb0a3da5405908ec5fdc22a2c1f2ca64892 -82a69ce1ee92a09cc709d0e3cd22116c9f69d28ea507fe5901f5676000b5179b9abe4c1875d052b0dd42d39925e186bb -a84c8cb84b9d5cfb69a5414f0a5283a5f2e90739e9362a1e8c784b96381b59ac6c18723a4aa45988ee8ef5c1f45cc97d -afd7efce6b36813082eb98257aae22a4c1ae97d51cac7ea9c852d4a66d05ef2732116137d8432e3f117119725a817d24 -a0f5fe25af3ce021b706fcff05f3d825384a272284d04735574ce5fb256bf27100fad0b1f1ba0e54ae9dcbb9570ecad3 -8751786cb80e2e1ff819fc7fa31c2833d25086534eb12b373d31f826382430acfd87023d2a688c65b5e983927e146336 -8cf5c4b17fa4f3d35c78ce41e1dc86988fd1135cd5e6b2bb0c108ee13538d0d09ae7102609c6070f39f937b439b31e33 -a9108967a2fedd7c322711eca8159c533dd561bedcb181b646de98bf5c3079449478eab579731bee8d215ae8852c7e21 -b54c5171704f42a6f0f4e70767cdb3d96ffc4888c842eece343a01557da405961d53ffdc34d2f902ea25d3e1ed867cad -ae8d4b764a7a25330ba205bf77e9f46182cd60f94a336bbd96773cf8064e3d39caf04c310680943dc89ed1fbad2c6e0d -aa5150e911a8e1346868e1b71c5a01e2a4bb8632c195861fb6c3038a0e9b85f0e09b3822e9283654a4d7bb17db2fc5f4 -9685d3756ce9069bf8bb716cf7d5063ebfafe37e15b137fc8c3159633c4e006ff4887ddd0ae90360767a25c3f90cba7f -82155fd70f107ab3c8e414eadf226c797e07b65911508c76c554445422325e71af8c9a8e77fd52d94412a6fc29417cd3 -abfae52f53a4b6e00760468d973a267f29321997c3dbb5aee36dc1f20619551229c0c45b9d9749f410e7f531b73378e8 -81a76d921f8ef88e774fd985e786a4a330d779b93fad7def718c014685ca0247379e2e2a007ad63ee7f729cd9ed6ce1b -81947c84bc5e28e26e2e533af5ae8fe10407a7b77436dbf8f1d5b0bbe86fc659eae10f974659dc7c826c6dabd03e3a4b -92b8c07050d635b8dd4fd09df9054efe4edae6b86a63c292e73cc819a12a21dd7d104ce51fa56af6539dedf6dbe6f7b6 -b44c579e3881f32b32d20c82c207307eca08e44995dd2aac3b2692d2c8eb2a325626c80ac81c26eeb38c4137ff95add5 -97efab8941c90c30860926dea69a841f2dcd02980bf5413b9fd78d85904588bf0c1021798dbc16c8bbb32cce66c82621 -913363012528b50698e904de0588bf55c8ec5cf6f0367cfd42095c4468fcc64954fbf784508073e542fee242d0743867 -8ed203cf215148296454012bd10fddaf119203db1919a7b3d2cdc9f80e66729464fdfae42f1f2fc5af1ed53a42b40024 -ab84312db7b87d711e9a60824f4fe50e7a6190bf92e1628688dfcb38930fe87b2d53f9e14dd4de509b2216856d8d9188 -880726def069c160278b12d2258eac8fa63f729cd351a710d28b7e601c6712903c3ac1e7bbd0d21e4a15f13ca49db5aa -980699cd51bac6283959765f5174e543ed1e5f5584b5127980cbc2ef18d984ecabba45042c6773b447b8e694db066028 -aeb019cb80dc4cb4207430d0f2cd24c9888998b6f21d9bf286cc638449668d2eec0018a4cf3fe6448673cd6729335e2b -b29852f6aa6c60effdffe96ae88590c88abae732561d35cc19e82d3a51e26cb35ea00986193e07f90060756240f5346e -a0fa855adc5ba469f35800c48414b8921455950a5c0a49945d1ef6e8f2a1881f2e2dfae47de6417270a6bf49deeb091d -b6c7332e3b14813641e7272d4f69ecc7e09081df0037d6dab97ce13a9e58510f5c930d300633f208181d9205c5534001 -85a6c050f42fce560b5a8d54a11c3bbb8407abbadd859647a7b0c21c4b579ec65671098b74f10a16245dc779dff7838e -8f3eb34bb68759d53c6677de4de78a6c24dd32c8962a7fb355ed362572ef8253733e6b52bc21c9f92ecd875020a9b8de -a17dd44181e5dab4dbc128e1af93ec22624b57a448ca65d2d9e246797e4af7d079e09c6e0dfb62db3a9957ce92f098d5 -a56a1b854c3183082543a8685bb34cae1289f86cfa8123a579049dbd059e77982886bfeb61bf6e05b4b1fe4e620932e7 -aedae3033cb2fb7628cb4803435bdd7757370a86f808ae4cecb9a268ad0e875f308c048c80cbcac523de16b609683887 -9344905376aa3982b1179497fac5a1d74b14b7038fd15e3b002db4c11c8bfc7c39430db492cdaf58b9c47996c9901f28 -a3bfafdae011a19f030c749c3b071f83580dee97dd6f949e790366f95618ca9f828f1daaeabad6dcd664fcef81b6556d -81c03d8429129e7e04434dee2c529194ddb01b414feda3adee2271eb680f6c85ec872a55c9fa9d2096f517e13ed5abcc -98205ef3a72dff54c5a9c82d293c3e45d908946fa74bb749c3aabe1ab994ea93c269bcce1a266d2fe67a8f02133c5985 -85a70aeed09fda24412fadbafbbbf5ba1e00ac92885df329e147bfafa97b57629a3582115b780d8549d07d19b7867715 -b0fbe81c719f89a57d9ea3397705f898175808c5f75f8eb81c2193a0b555869ba7bd2e6bc54ee8a60cea11735e21c68c -b03a0bd160495ee626ff3a5c7d95bc79d7da7e5a96f6d10116600c8fa20bedd1132f5170f25a22371a34a2d763f2d6d0 -a90ab04091fbca9f433b885e6c1d60ab45f6f1daf4b35ec22b09909d493a6aab65ce41a6f30c98239cbca27022f61a8b -b66f92aa3bf2549f9b60b86f99a0bd19cbdd97036d4ae71ca4b83d669607f275260a497208f6476cde1931d9712c2402 -b08e1fdf20e6a9b0b4942f14fa339551c3175c1ffc5d0ab5b226b6e6a322e9eb0ba96adc5c8d59ca4259e2bdd04a7eb0 -a2812231e92c1ce74d4f5ac3ab6698520288db6a38398bb38a914ac9326519580af17ae3e27cde26607e698294022c81 -abfcbbcf1d3b9e84c02499003e490a1d5d9a2841a9e50c7babbef0b2dd20d7483371d4dc629ba07faf46db659459d296 -b0fe9f98c3da70927c23f2975a9dc4789194d81932d2ad0f3b00843dd9cbd7fb60747a1da8fe5a79f136a601becf279d -b130a6dba7645165348cb90f023713bed0eefbd90a976b313521c60a36d34f02032e69a2bdcf5361e343ed46911297ec -862f0cffe3020cea7a5fd4703353aa1eb1be335e3b712b29d079ff9f7090d1d8b12013011e1bdcbaa80c44641fd37c9f -8c6f11123b26633e1abb9ed857e0bce845b2b3df91cc7b013b2fc77b477eee445da0285fc6fc793e29d5912977f40916 -91381846126ea819d40f84d3005e9fb233dc80071d1f9bb07f102bf015f813f61e5884ffffb4f5cd333c1b1e38a05a58 -8add7d908de6e1775adbd39c29a391f06692b936518db1f8fde74eb4f533fc510673a59afb86e3a9b52ade96e3004c57 -8780e086a244a092206edcde625cafb87c9ab1f89cc3e0d378bc9ee776313836160960a82ec397bc3800c0a0ec3da283 -a6cb4cd9481e22870fdd757fae0785edf4635e7aacb18072fe8dc5876d0bab53fb99ce40964a7d3e8bcfff6f0ab1332f -af30ff47ecc5b543efba1ba4706921066ca8bb625f40e530fb668aea0551c7647a9d126e8aba282fbcce168c3e7e0130 -91b0bcf408ce3c11555dcb80c4410b5bc2386d3c05caec0b653352377efdcb6bab4827f2018671fc8e4a0e90d772acc1 -a9430b975ef138b6b2944c7baded8fe102d31da4cfe3bd3d8778bda79189c99d38176a19c848a19e2d1ee0bddd9a13c1 -aa5a4eef849d7c9d2f4b018bd01271c1dd83f771de860c4261f385d3bdcc130218495860a1de298f14b703ec32fa235f -b0ce79e7f9ae57abe4ff366146c3b9bfb38b0dee09c28c28f5981a5d234c6810ad4d582751948affb480d6ae1c8c31c4 -b75122748560f73d15c01a8907d36d06dc068e82ce22b84b322ac1f727034493572f7907dec34ebc3ddcc976f2f89ed7 -b0fc7836369a3e4411d34792d6bd5617c14f61d9bba023dda64e89dc5fb0f423244e9b48ee64869258931daa9753a56f -8956d7455ae9009d70c6e4a0bcd7610e55f37494cf9897a8f9e1b904cc8febc3fd2d642ebd09025cfff4609ad7e3bc52 -ad741efe9e472026aa49ae3d9914cb9c1a6f37a54f1a6fe6419bebd8c7d68dca105a751c7859f4389505ede40a0de786 -b52f418797d719f0d0d0ffb0846788b5cba5d0454a69a2925de4b0b80fa4dd7e8c445e5eac40afd92897ed28ca650566 -a0ab65fb9d42dd966cd93b1de01d7c822694669dd2b7a0c04d99cd0f3c3de795f387b9c92da11353412f33af5c950e9a -a0052f44a31e5741a331f7cac515a08b3325666d388880162d9a7b97598fde8b61f9ff35ff220df224eb5c4e40ef0567 -a0101cfdc94e42b2b976c0d89612a720e55d145a5ef6ef6f1f78cf6de084a49973d9b5d45915349c34ce712512191e3c -a0dd99fcf3f5cead5aaf08e82212df3a8bb543c407a4d6fab88dc5130c1769df3f147e934a46f291d6c1a55d92b86917 -a5939153f0d1931bbda5cf6bdf20562519ea55fbfa978d6dbc6828d298260c0da7a50c37c34f386e59431301a96c2232 -9568269f3f5257200f9ca44afe1174a5d3cf92950a7f553e50e279c239e156a9faaa2a67f288e3d5100b4142efe64856 -b746b0832866c23288e07f24991bbf687cad794e7b794d3d3b79367566ca617d38af586cdc8d6f4a85a34835be41d54f -a871ce28e39ab467706e32fec1669fda5a4abba2f8c209c6745df9f7a0fa36bbf1919cf14cb89ea26fa214c4c907ae03 -a08dacdd758e523cb8484f6bd070642c0c20e184abdf8e2a601f61507e93952d5b8b0c723c34fcbdd70a8485eec29db2 -85bdb78d501382bb95f1166b8d032941005661aefd17a5ac32df9a3a18e9df2fc5dc2c1f07075f9641af10353cecc0c9 -98d730c28f6fa692a389e97e368b58f4d95382fad8f0baa58e71a3d7baaea1988ead47b13742ce587456f083636fa98e -a557198c6f3d5382be9fb363feb02e2e243b0c3c61337b3f1801c4a0943f18e38ce1a1c36b5c289c8fa2aa9d58742bab -89174f79201742220ac689c403fc7b243eed4f8e3f2f8aba0bf183e6f5d4907cb55ade3e238e3623d9885f03155c4d2b -b891d600132a86709e06f3381158db300975f73ea4c1f7c100358e14e98c5fbe792a9af666b85c4e402707c3f2db321e -b9e5b2529ef1043278c939373fc0dbafe446def52ddd0a8edecd3e4b736de87e63e187df853c54c28d865de18a358bb6 -8589b2e9770340c64679062c5badb7bbef68f55476289b19511a158a9a721f197da03ece3309e059fc4468b15ac33aa3 -aad8c6cd01d785a881b446f06f1e9cd71bca74ba98674c2dcddc8af01c40aa7a6d469037498b5602e76e9c91a58d3dbd -abaccb1bd918a8465f1bf8dbe2c9ad4775c620b055550b949a399f30cf0d9eb909f3851f5b55e38f9e461e762f88f499 -ae62339d26db46e85f157c0151bd29916d5cc619bd4b832814b3fd2f00af8f38e7f0f09932ffe5bba692005dab2d9a74 -93a6ff30a5c0edf8058c89aba8c3259e0f1b1be1b80e67682de651e5346f7e1b4b4ac3d87cbaebf198cf779524aff6bf -8980a2b1d8f574af45b459193c952400b10a86122b71fca2acb75ee0dbd492e7e1ef5b959baf609a5172115e371f3177 -8c2f49f3666faee6940c75e8c7f6f8edc3f704cca7a858bbb7ee5e96bba3b0cf0993996f781ba6be3b0821ef4cb75039 -b14b9e348215b278696018330f63c38db100b0542cfc5be11dc33046e3bca6a13034c4ae40d9cef9ea8b34fef0910c4e -b59bc3d0a30d66c16e6a411cb641f348cb1135186d5f69fda8b0a0934a5a2e7f6199095ba319ec87d3fe8f1ec4a06368 -8874aca2a3767aa198e4c3fec2d9c62d496bc41ff71ce242e9e082b7f38cdf356089295f80a301a3cf1182bde5308c97 -b1820ebd61376d91232423fc20bf008b2ba37e761199f4ef0648ea2bd70282766799b4de814846d2f4d516d525c8daa7 -a6b202e5dedc16a4073e04a11af3a8509b23dfe5a1952f899adeb240e75c3f5bde0c424f811a81ea48d343591faffe46 -a69becee9c93734805523b92150a59a62eed4934f66056b645728740d42223f2925a1ad38359ba644da24d9414f4cdda -ad72f0f1305e37c7e6b48c272323ee883320994cb2e0d850905d6655fafc9f361389bcb9c66b3ff8d2051dbb58c8aa96 -b563600bd56fad7c8853af21c6a02a16ed9d8a8bbeea2c31731d63b976d83cb05b9779372d898233e8fd597a75424797 -b0abb78ce465bf7051f563c62e8be9c57a2cc997f47c82819300f36e301fefd908894bb2053a9d27ce2d0f8c46d88b5b -a071a85fb8274bac2202e0cb8e0e2028a5e138a82d6e0374d39ca1884a549c7c401312f00071b91f455c3a2afcfe0cda -b931c271513a0f267b9f41444a5650b1918100b8f1a64959c552aff4e2193cc1b9927906c6fa7b8a8c68ef13d79aaa52 -a6a1bb9c7d32cb0ca44d8b75af7e40479fbce67d216b48a2bb680d3f3a772003a49d3cd675fc64e9e0f8fabeb86d6d61 -b98d609858671543e1c3b8564162ad828808bb50ded261a9f8690ded5b665ed8368c58f947365ed6e84e5a12e27b423d -b3dca58cd69ec855e2701a1d66cad86717ff103ef862c490399c771ad28f675680f9500cb97be48de34bcdc1e4503ffd -b34867c6735d3c49865e246ddf6c3b33baf8e6f164db3406a64ebce4768cb46b0309635e11be985fee09ab7a31d81402 -acb966c554188c5b266624208f31fab250b3aa197adbdd14aee5ab27d7fb886eb4350985c553b20fdf66d5d332bfd3fe -943c36a18223d6c870d54c3b051ef08d802b85e9dd6de37a51c932f90191890656c06adfa883c87b906557ae32d09da0 -81bca7954d0b9b6c3d4528aadf83e4bc2ef9ea143d6209bc45ae9e7ae9787dbcd8333c41f12c0b6deee8dcb6805e826a -aba176b92256efb68f574e543479e5cf0376889fb48e3db4ebfb7cba91e4d9bcf19dcfec444c6622d9398f06de29e2b9 -b9f743691448053216f6ece7cd699871fff4217a1409ceb8ab7bdf3312d11696d62c74b0664ba0a631b1e0237a8a0361 -a383c2b6276fa9af346b21609326b53fb14fdf6f61676683076e80f375b603645f2051985706d0401e6fbed7eb0666b6 -a9ef2f63ec6d9beb8f3d04e36807d84bda87bdd6b351a3e4a9bf7edcb5618c46c1f58cfbf89e64b40f550915c6988447 -a141b2d7a82f5005eaea7ae7d112c6788b9b95121e5b70b7168d971812f3381de8b0082ac1f0a82c7d365922ebd2d26a -b1b76ef8120e66e1535c17038b75255a07849935d3128e3e99e56567b842fb1e8d56ef932d508d2fb18b82f7868fe1a9 -8e2e234684c81f21099f5c54f6bbe2dd01e3b172623836c77668a0c49ce1fe218786c3827e4d9ae2ea25c50a8924fb3c -a5caf5ff948bfd3c4ca3ffbdfcd91eec83214a6c6017235f309a0bbf7061d3b0b466307c00b44a1009cf575163898b43 -986415a82ca16ebb107b4c50b0c023c28714281db0bcdab589f6cb13d80e473a3034b7081b3c358e725833f6d845cb14 -b94836bf406ac2cbacb10e6df5bcdfcc9d9124ae1062767ca4e322d287fd5e353fdcebd0e52407cb3cd68571258a8900 -83c6d70a640b33087454a4788dfd9ef3ed00272da084a8d36be817296f71c086b23b576f98178ab8ca6a74f04524b46b -ad4115182ad784cfe11bcfc5ce21fd56229cc2ce77ac82746e91a2f0aa53ca6593a22efd2dc4ed8d00f84542643d9c58 -ab1434c5e5065da826d10c2a2dba0facccab0e52b506ce0ce42fbe47ced5a741797151d9ecc99dc7d6373cfa1779bbf6 -8a8b591d82358d55e6938f67ea87a89097ab5f5496f7260adb9f649abb289da12b498c5b2539c2f9614fb4e21b1f66b0 -964f355d603264bc1f44c64d6d64debca66f37dff39c971d9fc924f2bc68e6c187b48564a6dc82660a98b035f8addb5d -b66235eaaf47456bc1dc4bde454a028e2ce494ece6b713a94cd6bf27cf18c717fd0c57a5681caaa2ad73a473593cdd7a -9103e3bb74304186fa4e3e355a02da77da4aca9b7e702982fc2082af67127ebb23a455098313c88465bc9b7d26820dd5 -b6a42ff407c9dd132670cdb83cbad4b20871716e44133b59a932cd1c3f97c7ac8ff7f61acfaf8628372508d8dc8cad7c -883a9c21c16a167a4171b0f084565c13b6f28ba7c4977a0de69f0a25911f64099e7bbb4da8858f2e93068f4155d04e18 -8dbb3220abc6a43220adf0331e3903d3bfd1d5213aadfbd8dfcdf4b2864ce2e96a71f35ecfb7a07c3bbabf0372b50271 -b4ad08aee48e176bda390b7d9acf2f8d5eb008f30d20994707b757dc6a3974b2902d29cd9b4d85e032810ad25ac49e97 -865bb0f33f7636ec501bb634e5b65751c8a230ae1fa807a961a8289bbf9c7fe8c59e01fbc4c04f8d59b7f539cf79ddd5 -86a54d4c12ad1e3605b9f93d4a37082fd26e888d2329847d89afa7802e815f33f38185c5b7292293d788ad7d7da1df97 -b26c8615c5e47691c9ff3deca3021714662d236c4d8401c5d27b50152ce7e566266b9d512d14eb63e65bc1d38a16f914 -827639d5ce7db43ba40152c8a0eaad443af21dc92636cc8cc2b35f10647da7d475a1e408901cd220552fddad79db74df -a2b79a582191a85dbe22dc384c9ca3de345e69f6aa370aa6d3ff1e1c3de513e30b72df9555b15a46586bd27ea2854d9d -ae0d74644aba9a49521d3e9553813bcb9e18f0b43515e4c74366e503c52f47236be92dfbd99c7285b3248c267b1de5a0 -80fb0c116e0fd6822a04b9c25f456bdca704e2be7bdc5d141dbf5d1c5eeb0a2c4f5d80db583b03ef3e47517e4f9a1b10 -ac3a1fa3b4a2f30ea7e0a114cdc479eb51773573804c2a158d603ad9902ae8e39ffe95df09c0d871725a5d7f9ba71a57 -b56b2b0d601cba7f817fa76102c68c2e518c6f20ff693aad3ff2e07d6c4c76203753f7f91686b1801e8c4659e4d45c48 -89d50c1fc56e656fb9d3915964ebce703cb723fe411ab3c9eaa88ccc5d2b155a9b2e515363d9c600d3c0cee782c43f41 -b24207e61462f6230f3cd8ccf6828357d03e725769f7d1de35099ef9ee4dca57dbce699bb49ed994462bee17059d25ce -b886f17fcbcbfcd08ac07f04bb9543ef58510189decaccea4b4158c9174a067cb67d14b6be3c934e6e2a18c77efa9c9c -b9c050ad9cafd41c6e2e192b70d080076eed59ed38ea19a12bd92fa17b5d8947d58d5546aaf5e8e27e1d3b5481a6ce51 -aaf7a34d3267e3b1ddbc54c641e3922e89303f7c86ebebc7347ebca4cffad5b76117dac0cbae1a133053492799cd936f -a9ee604ada50adef82e29e893070649d2d4b7136cc24fa20e281ce1a07bd736bf0de7c420369676bcbcecff26fb6e900 -9855315a12a4b4cf80ab90b8bd13003223ba25206e52fd4fe6a409232fbed938f30120a3db23eab9c53f308bd8b9db81 -8cd488dd7a24f548a3cf03c54dec7ff61d0685cb0f6e5c46c2d728e3500d8c7bd6bba0156f4bf600466fda53e5b20444 -890ad4942ebac8f5b16c777701ab80c68f56fa542002b0786f8fea0fb073154369920ac3dbfc07ea598b82f4985b8ced -8de0cf9ddc84c9b92c59b9b044387597799246b30b9f4d7626fc12c51f6e423e08ee4cbfe9289984983c1f9521c3e19d -b474dfb5b5f4231d7775b3c3a8744956b3f0c7a871d835d7e4fd9cc895222c7b868d6c6ce250de568a65851151fac860 -86433b6135d9ed9b5ee8cb7a6c40e5c9d30a68774cec04988117302b8a02a11a71a1e03fd8e0264ef6611d219f103007 -80b9ed4adbe9538fb1ef69dd44ec0ec5b57cbfea820054d8d445b4261962624b4c70ac330480594bc5168184378379c3 -8b2e83562ccd23b7ad2d17f55b1ab7ef5fbef64b3a284e6725b800f3222b8bdf49937f4a873917ada9c4ddfb090938c2 -abe78cebc0f5a45d754140d1f685e387489acbfa46d297a8592aaa0d676a470654f417a4f7d666fc0b2508fab37d908e -a9c5f8ff1f8568e252b06d10e1558326db9901840e6b3c26bbd0cd5e850cb5fb3af3f117dbb0f282740276f6fd84126f -975f8dc4fb55032a5df3b42b96c8c0ffecb75456f01d4aef66f973cb7270d4eff32c71520ceefc1adcf38d77b6b80c67 -b043306ed2c3d8a5b9a056565afd8b5e354c8c4569fda66b0d797a50a3ce2c08cffbae9bbe292da69f39e89d5dc7911e -8d2afc36b1e44386ba350c14a6c1bb31ff6ea77128a0c5287584ac3584282d18516901ce402b4644a53db1ed8e7fa581 -8c294058bed53d7290325c363fe243f6ec4f4ea2343692f4bac8f0cb86f115c069ccb8334b53d2e42c067691ad110dba -b92157b926751aaf7ef82c1aa8c654907dccab6376187ee8b3e8c0c82811eae01242832de953faa13ebaff7da8698b3e -a780c4bdd9e4ba57254b09d745075cecab87feda78c88ffee489625c5a3cf96aa6b3c9503a374a37927d9b78de9bd22b -811f548ef3a2e6a654f7dcb28ac9378de9515ed61e5a428515d9594a83e80b35c60f96a5cf743e6fab0d3cb526149f49 -85a4dccf6d90ee8e094731eec53bd00b3887aec6bd81a0740efddf812fd35e3e4fe4f983afb49a8588691c202dabf942 -b152c2da6f2e01c8913079ae2b40a09b1f361a80f5408a0237a8131b429677c3157295e11b365b1b1841924b9efb922e -849b9efee8742502ffd981c4517c88ed33e4dd518a330802caff168abae3cd09956a5ee5eda15900243bc2e829016b74 -955a933f3c18ec0f1c0e38fa931e4427a5372c46a3906ebe95082bcf878c35246523c23f0266644ace1fa590ffa6d119 -911989e9f43e580c886656377c6f856cdd4ff1bd001b6db3bbd86e590a821d34a5c6688a29b8d90f28680e9fdf03ba69 -b73b8b4f1fd6049fb68d47cd96a18fcba3f716e0a1061aa5a2596302795354e0c39dea04d91d232aec86b0bf2ba10522 -90f87456d9156e6a1f029a833bf3c7dbed98ca2f2f147a8564922c25ae197a55f7ea9b2ee1f81bf7383197c4bad2e20c -903cba8b1e088574cb04a05ca1899ab00d8960580c884bd3c8a4c98d680c2ad11410f2b75739d6050f91d7208cac33a5 -9329987d42529c261bd15ecedd360be0ea8966e7838f32896522c965adfc4febf187db392bd441fb43bbd10c38fdf68b -8178ee93acf5353baa349285067b20e9bb41aa32d77b5aeb7384fe5220c1fe64a2461bd7a83142694fe673e8bbf61b7c -a06a8e53abcff271b1394bcc647440f81fb1c1a5f29c27a226e08f961c3353f4891620f2d59b9d1902bf2f5cc07a4553 -aaf5fe493b337810889e777980e6bbea6cac39ac66bc0875c680c4208807ac866e9fda9b5952aa1d04539b9f4a4bec57 -aa058abb1953eceac14ccfa7c0cc482a146e1232905dcecc86dd27f75575285f06bbae16a8c9fe8e35d8713717f5f19f -8f15dd732799c879ca46d2763453b359ff483ca33adb1d0e0a57262352e0476c235987dc3a8a243c74bc768f93d3014c -a61cc8263e9bc03cce985f1663b8a72928a607121005a301b28a278e9654727fd1b22bc8a949af73929c56d9d3d4a273 -98d6dc78502d19eb9f921225475a6ebcc7b44f01a2df6f55ccf6908d65b27af1891be2a37735f0315b6e0f1576c1f8d8 -8bd258b883f3b3793ec5be9472ad1ff3dc4b51bc5a58e9f944acfb927349ead8231a523cc2175c1f98e7e1e2b9f363b8 -aeacc2ecb6e807ad09bedd99654b097a6f39840e932873ace02eabd64ccfbb475abdcb62939a698abf17572d2034c51e -b8ccf78c08ccd8df59fd6eda2e01de328bc6d8a65824d6f1fc0537654e9bc6bf6f89c422dd3a295cce628749da85c864 -8f91fd8cb253ba2e71cc6f13da5e05f62c2c3b485c24f5d68397d04665673167fce1fc1aec6085c69e87e66ec555d3fd -a254baa10cb26d04136886073bb4c159af8a8532e3fd36b1e9c3a2e41b5b2b6a86c4ebc14dbe624ee07b7ccdaf59f9ab -94e3286fe5cd68c4c7b9a7d33ae3d714a7f265cf77cd0e9bc19fc51015b1d1c34ad7e3a5221c459e89f5a043ee84e3a9 -a279da8878af8d449a9539bec4b17cea94f0242911f66fab275b5143ab040825f78c89cb32a793930609415cfa3a1078 -ac846ceb89c9e5d43a2991c8443079dc32298cd63e370e64149cec98cf48a6351c09c856f2632fd2f2b3d685a18bbf8b -a847b27995c8a2e2454aaeb983879fb5d3a23105c33175839f7300b7e1e8ec3efd6450e9fa3f10323609dee7b98c6fd5 -a2f432d147d904d185ff4b2de8c6b82fbea278a2956bc406855b44c18041854c4f0ecccd472d1d0dff1d8aa8e281cb1d -94a48ad40326f95bd63dff4755f863a1b79e1df771a1173b17937f9baba57b39e651e7695be9f66a472f098b339364fc -a12a0ccd8f96e96e1bc6494341f7ebce959899341b3a084aa1aa87d1c0d489ac908552b7770b887bb47e7b8cbc3d8e66 -81a1f1681bda923bd274bfe0fbb9181d6d164fe738e54e25e8d4849193d311e2c4253614ed673c98af2c798f19a93468 -abf71106a05d501e84cc54610d349d7d5eae21a70bd0250f1bebbf412a130414d1c8dbe673ffdb80208fd72f1defa4d4 -96266dc2e0df18d8136d79f5b59e489978eee0e6b04926687fe389d4293c14f36f055c550657a8e27be4118b64254901 -8df5dcbefbfb4810ae3a413ca6b4bf08619ca53cd50eb1dde2a1c035efffc7b7ac7dff18d403253fd80104bd83dc029e -9610b87ff02e391a43324a7122736876d5b3af2a137d749c52f75d07b17f19900b151b7f439d564f4529e77aa057ad12 -a90a5572198b40fe2fcf47c422274ff36c9624df7db7a89c0eb47eb48a73a03c985f4ac5016161c76ca317f64339bce1 -98e5e61a6ab6462ba692124dba7794b6c6bde4249ab4fcc98c9edd631592d5bc2fb5e38466691a0970a38e48d87c2e43 -918cefb8f292f78d4db81462c633daf73b395e772f47b3a7d2cea598025b1d8c3ec0cbff46cdb23597e74929981cde40 -a98918a5dc7cf610fe55f725e4fd24ce581d594cb957bb9b4e888672e9c0137003e1041f83e3f1d7b9caab06462c87d4 -b92b74ac015262ca66c33f2d950221e19d940ba3bf4cf17845f961dc1729ae227aa9e1f2017829f2135b489064565c29 -a053ee339f359665feb178b4e7ee30a85df37debd17cacc5a27d6b3369d170b0114e67ad1712ed26d828f1df641bcd99 -8c3c8bad510b35da5ce5bd84b35c958797fbea024ad1c97091d2ff71d9b962e9222f65a9b776e5b3cc29c36e1063d2ee -af99dc7330fe7c37e850283eb47cc3257888e7c197cb0d102edf94439e1e02267b6a56306d246c326c4c79f9dc8c6986 -afecb2dc34d57a725efbd7eb93d61eb29dbe8409b668ab9ea040791f5b796d9be6d4fc10d7f627bf693452f330cf0435 -93334fedf19a3727a81a6b6f2459db859186227b96fe7a391263f69f1a0884e4235de64d29edebc7b99c44d19e7c7d7a -89579c51ac405ad7e9df13c904061670ce4b38372492764170e4d3d667ed52e5d15c7cd5c5991bbfa3a5e4e3fa16363e -9778f3e8639030f7ef1c344014f124e375acb8045bd13d8e97a92c5265c52de9d1ffebaa5bc3e1ad2719da0083222991 -88f77f34ee92b3d36791bdf3326532524a67d544297dcf1a47ff00b47c1b8219ff11e34034eab7d23b507caa2fd3c6b9 -a699c1e654e7c484431d81d90657892efeb4adcf72c43618e71ca7bd7c7a7ebbb1db7e06e75b75dc4c74efd306b5df3f -81d13153baebb2ef672b5bdb069d3cd669ce0be96b742c94e04038f689ff92a61376341366b286eee6bf3ae85156f694 -81efb17de94400fdacc1deec2550cbe3eecb27c7af99d8207e2f9be397e26be24a40446d2a09536bb5172c28959318d9 -989b21ebe9ceab02488992673dc071d4d5edec24bff0e17a4306c8cb4b3c83df53a2063d1827edd8ed16d6e837f0d222 -8d6005d6536825661b13c5fdce177cb37c04e8b109b7eb2b6d82ea1cb70efecf6a0022b64f84d753d165edc2bba784a3 -a32607360a71d5e34af2271211652d73d7756d393161f4cf0da000c2d66a84c6826e09e759bd787d4fd0305e2439d342 -aaad8d6f6e260db45d51b2da723be6fa832e76f5fbcb77a9a31e7f090dd38446d3b631b96230d78208cae408c288ac4e -abcfe425255fd3c5cffd3a818af7650190c957b6b07b632443f9e33e970a8a4c3bf79ac9b71f4d45f238a04d1c049857 -aeabf026d4c783adc4414b5923dbd0be4b039cc7201219f7260d321f55e9a5b166d7b5875af6129c034d0108fdc5d666 -af49e740c752d7b6f17048014851f437ffd17413c59797e5078eaaa36f73f0017c3e7da020310cfe7d3c85f94a99f203 -8854ca600d842566e3090040cd66bb0b3c46dae6962a13946f0024c4a8aca447e2ccf6f240045f1ceee799a88cb9210c -b6c03b93b1ab1b88ded8edfa1b487a1ed8bdce8535244dddb558ffb78f89b1c74058f80f4db2320ad060d0c2a9c351cc -b5bd7d17372faff4898a7517009b61a7c8f6f0e7ed4192c555db264618e3f6e57fb30a472d169fea01bf2bf0362a19a8 -96eb1d38319dc74afe7e7eb076fcd230d19983f645abd14a71e6103545c01301b31c47ae931e025f3ecc01fb3d2f31fa -b55a8d30d4403067def9b65e16f867299f8f64c9b391d0846d4780bc196569622e7e5b64ce799b5aefac8f965b2a7a7b -8356d199a991e5cbbff608752b6291731b6b6771aed292f8948b1f41c6543e4ab1bedc82dd26d10206c907c03508df06 -97f4137445c2d98b0d1d478049de952610ad698c91c9d0f0e7227d2aae690e9935e914ec4a2ea1fbf3fc1dddfeeacebb -af5621707e0938320b15ddfc87584ab325fbdfd85c30efea36f8f9bd0707d7ec12c344eff3ec21761189518d192df035 -8ac7817e71ea0825b292687928e349da7140285d035e1e1abff0c3704fa8453faaae343a441b7143a74ec56539687cc4 -8a5e0a9e4758449489df10f3386029ada828d1762e4fb0a8ffe6b79e5b6d5d713cb64ed95960e126398b0cdb89002bc9 -81324be4a71208bbb9bca74b77177f8f1abb9d3d5d9db195d1854651f2cf333cd618d35400da0f060f3e1b025124e4b2 -849971d9d095ae067525b3cbc4a7dfae81f739537ade6d6cec1b42fb692d923176197a8770907c58069754b8882822d6 -89f830825416802477cc81fdf11084885865ee6607aa15aa4eb28e351c569c49b8a1b9b5e95ddc04fa0ebafe20071313 -9240aeeaff37a91af55f860b9badd466e8243af9e8c96a7aa8cf348cd270685ab6301bc135b246dca9eda696f8b0e350 -acf74db78cc33138273127599eba35b0fb4e7b9a69fe02dae18fc6692d748ca332bd00b22afa8e654ed587aab11833f3 -b091e6d37b157b50d76bd297ad752220cd5c9390fac16dc838f8557aed6d9833fc920b61519df21265406216315e883f -a6446c429ebf1c7793c622250e23594c836b2fbcaf6c5b3d0995e1595a37f50ea643f3e549b0be8bbdadd69044d72ab9 -93e675353bd60e996bf1c914d5267eeaa8a52fc3077987ccc796710ef9becc6b7a00e3d82671a6bdfb8145ee3c80245a -a2f731e43251d04ed3364aa2f072d05355f299626f2d71a8a38b6f76cf08c544133f7d72dd0ab4162814b674b9fc7fa6 -97a8b791a5a8f6e1d0de192d78615d73d0c38f1e557e4e15d15adc663d649e655bc8da3bcc499ef70112eafe7fb45c7a -98cd624cbbd6c53a94469be4643c13130916b91143425bcb7d7028adbbfede38eff7a21092af43b12d4fab703c116359 -995783ce38fd5f6f9433027f122d4cf1e1ff3caf2d196ce591877f4a544ce9113ead60de2de1827eaff4dd31a20d79a8 -8cf251d6f5229183b7f3fe2f607a90b4e4b6f020fb4ba2459d28eb8872426e7be8761a93d5413640a661d73e34a5b81f -b9232d99620652a3aa7880cad0876f153ff881c4ed4c0c2e7b4ea81d5d42b70daf1a56b869d752c3743c6d4c947e6641 -849716f938f9d37250cccb1bf77f5f9fde53096cdfc6f2a25536a6187029a8f1331cdbed08909184b201f8d9f04b792f -80c7c4de098cbf9c6d17b14eba1805e433b5bc905f6096f8f63d34b94734f2e4ebf4bce8a177efd1186842a61204a062 -b790f410cf06b9b8daadceeb4fd5ff40a2deda820c8df2537e0a7554613ae3948e149504e3e79aa84889df50c8678eeb -813aab8bd000299cd37485b73cd7cba06e205f8efb87f1efc0bae8b70f6db2bc7702eb39510ad734854fb65515fe9d0f -94f0ab7388ac71cdb67f6b85dfd5945748afb2e5abb622f0b5ad104be1d4d0062b651f134ba22385c9e32c2dfdcccce1 -ab6223dca8bd6a4f969e21ccd9f8106fc5251d321f9e90cc42cea2424b3a9c4e5060a47eeef6b23c7976109b548498e8 -859c56b71343fce4d5c5b87814c47bf55d581c50fd1871a17e77b5e1742f5af639d0e94d19d909ec7dfe27919e954e0c -aae0d632b6191b8ad71b027791735f1578e1b89890b6c22e37de0e4a6074886126988fe8319ae228ac9ef3b3bcccb730 -8ca9f32a27a024c3d595ecfaf96b0461de57befa3b331ab71dc110ec3be5824fed783d9516597537683e77a11d334338 -a061df379fb3f4b24816c9f6cd8a94ecb89b4c6dc6cd81e4b8096fa9784b7f97ab3540259d1de9c02eb91d9945af4823 -998603102ac63001d63eb7347a4bb2bf4cf33b28079bb48a169076a65c20d511ccd3ef696d159e54cc8e772fb5d65d50 -94444d96d39450872ac69e44088c252c71f46be8333a608a475147752dbb99db0e36acfc5198f158509401959c12b709 -ac1b51b6c09fe055c1d7c9176eea9adc33f710818c83a1fbfa073c8dc3a7eb3513cbdd3f5960b7845e31e3e83181e6ba -803d530523fc9e1e0f11040d2412d02baef3f07eeb9b177fa9bfa396af42eea898a4276d56e1db998dc96ae47b644cb2 -85a3c9fc7638f5bf2c3e15ba8c2fa1ae87eb1ceb44c6598c67a2948667a9dfa41e61f66d535b4e7fda62f013a5a8b885 -a961cf5654c46a1a22c29baf7a4e77837a26b7f138f410e9d1883480ed5fa42411d522aba32040b577046c11f007388e -ad1154142344f494e3061ef45a34fab1aaacf5fdf7d1b26adbb5fbc3d795655fa743444e39d9a4119b4a4f82a6f30441 -b1d6c30771130c77806e7ab893b73d4deb590b2ff8f2f8b5e54c2040c1f3e060e2bd99afc668cf706a2df666a508bbf6 -a00361fd440f9decabd98d96c575cd251dc94c60611025095d1201ef2dedde51cb4de7c2ece47732e5ed9b3526c2012c -a85c5ab4d17d328bda5e6d839a9a6adcc92ff844ec25f84981e4f44a0e8419247c081530f8d9aa629c7eb4ca21affba6 -a4ddd3eab4527a2672cf9463db38bc29f61460e2a162f426b7852b7a7645fbd62084fd39a8e4d60e1958cce436dd8f57 -811648140080fe55b8618f4cf17f3c5a250adb0cd53d885f2ddba835d2b4433188e41fc0661faac88e4ff910b16278c0 -b85c7f1cfb0ed29addccf7546023a79249e8f15ac2d14a20accbfef4dd9dc11355d599815fa09d2b6b4e966e6ea8cff1 -a10b5d8c260b159043b020d5dd62b3467df2671afea6d480ca9087b7e60ed170c82b121819d088315902842d66c8fb45 -917e191df1bcf3f5715419c1e2191da6b8680543b1ba41fe84ed07ef570376e072c081beb67b375fca3565a2565bcabb -881fd967407390bfd7badc9ab494e8a287559a01eb07861f527207c127eadea626e9bcc5aa9cca2c5112fbac3b3f0e9c -959fd71149af82cc733619e0e5bf71760ca2650448c82984b3db74030d0e10f8ab1ce1609a6de6f470fe8b5bd90df5b3 -a3370898a1c5f33d15adb4238df9a6c945f18b9ada4ce2624fc32a844f9ece4c916a64e9442225b6592afa06d2e015f2 -817efb8a791435e4236f7d7b278181a5fa34587578c629dbc14fbf9a5c26772290611395eecd20222a4c58649fc256d8 -a04c9876acf2cfdc8ef96de4879742709270fa1d03fe4c8511fbef2d59eb0aaf0336fa2c7dfe41a651157377fa217813 -81e15875d7ea7f123e418edf14099f2e109d4f3a6ce0eb65f67fe9fb10d2f809a864a29f60ad3fc949f89e2596b21783 -b49f529975c09e436e6bc202fdc16e3fdcbe056db45178016ad6fdece9faad4446343e83aed096209690b21a6910724f -879e8eda589e1a279f7f49f6dd0580788c040d973748ec4942dbe51ea8fbd05983cc919b78f0c6b92ef3292ae29db875 -81a2b74b2118923f34139a102f3d95e7eee11c4c2929c2576dee200a5abfd364606158535a6c9e4178a6a83dbb65f3c4 -8913f281d8927f2b45fc815d0f7104631cb7f5f7278a316f1327d670d15868daadd2a64e3eb98e1f53fe7e300338cc80 -a6f815fba7ef9af7fbf45f93bc952e8b351f5de6568a27c7c47a00cb39a254c6b31753794f67940fc7d2e9cc581529f4 -b3722a15c66a0014ce4d082de118def8d39190c15678a472b846225585f3a83756ae1b255b2e3f86a26168878e4773b2 -817ae61ab3d0dd5b6e24846b5a5364b1a7dc2e77432d9fed587727520ae2f307264ea0948c91ad29f0aea3a11ff38624 -b3db467464415fcad36dc1de2d6ba7686772a577cc2619242ac040d6734881a45d3b40ed4588db124e4289cfeec4bbf6 -ad66a14f5a54ac69603b16e5f1529851183da77d3cc60867f10aea41339dd5e06a5257982e9e90a352cdd32750f42ee4 -adafa3681ef45d685555601a25a55cf23358319a17f61e2179e704f63df83a73bdd298d12cf6cef86db89bd17119e11d -a379dc44cb6dd3b9d378c07b2ec654fec7ca2f272de6ba895e3d00d20c9e4c5550498a843c8ac67e4221db2115bedc1c -b7bf81c267a78efc6b9e5a904574445a6487678d7ef70054e3e93ea6a23f966c2b68787f9164918e3b16d2175459ed92 -b41d66a13a4afafd5760062b77f79de7e6ab8ccacde9c6c5116a6d886912fb491dc027af435b1b44aacc6af7b3c887f2 -9904d23a7c1c1d2e4bab85d69f283eb0a8e26d46e8b7b30224438015c936729b2f0af7c7c54c03509bb0500acb42d8a4 -ae30d65e9e20c3bfd603994ae2b175ff691d51f3e24b2d058b3b8556d12ca4c75087809062dddd4aaac81c94d15d8a17 -9245162fab42ac01527424f6013310c3eb462982518debef6c127f46ba8a06c705d7dc9f0a41e796ba8d35d60ae6cc64 -87fab853638d7a29a20f3ba2b1a7919d023e9415bfa78ebb27973d8cbc7626f584dc5665d2e7ad71f1d760eba9700d88 -85aac46ecd330608e5272430970e6081ff02a571e8ea444f1e11785ea798769634a22a142d0237f67b75369d3c484a8a -938c85ab14894cc5dfce3d80456f189a2e98eddbc8828f4ff6b1df1dcb7b42b17ca2ff40226a8a1390a95d63dca698dd -a18ce1f846e3e3c4d846822f60271eecf0f5d7d9f986385ac53c5ace9589dc7c0188910448c19b91341a1ef556652fa9 -8611608a9d844f0e9d7584ad6ccf62a5087a64f764caf108db648a776b5390feb51e5120f0ef0e9e11301af3987dd7dc -8106333ba4b4de8d1ae43bc9735d3fea047392e88efd6a2fa6f7b924a18a7a265ca6123c3edc0f36307dd7fb7fe89257 -a91426fa500951ff1b051a248c050b7139ca30dde8768690432d597d2b3c4357b11a577be6b455a1c5d145264dcf81fc -b7f9f90e0e450f37b081297f7f651bad0496a8b9afd2a4cf4120a2671aaaa8536dce1af301258bfbfdb122afa44c5048 -84126da6435699b0c09fa4032dec73d1fca21d2d19f5214e8b0bea43267e9a8dd1fc44f8132d8315e734c8e2e04d7291 -aff064708103884cb4f1a3c1718b3fc40a238d35cf0a7dc24bdf9823693b407c70da50df585bf5bc4e9c07d1c2d203e8 -a8b40fc6533752983a5329c31d376c7a5c13ce6879cc7faee648200075d9cd273537001fb4c86e8576350eaac6ba60c2 -a02db682bdc117a84dcb9312eb28fcbde12d49f4ce915cc92c610bb6965ec3cc38290f8c5b5ec70afe153956692cda95 -86decd22b25d300508472c9ce75d3e465b737e7ce13bc0fcce32835e54646fe12322ba5bc457be18bfd926a1a6ca4a38 -a18666ef65b8c2904fd598791f5627207165315a85ee01d5fb0e6b2e10bdd9b00babc447da5bd63445e3337de33b9b89 -89bb0c06effadefdaf34ffe4b123e1678a90d4451ee856c863df1e752eef41fd984689ded8f0f878bf8916d5dd8e8024 -97cfcba08ebec05d0073992a66b1d7d6fb9d95871f2cdc36db301f78bf8069294d1c259efef5c93d20dc937eedae3a1a -ac2643b14ece79dcb2e289c96776a47e2bebd40dd6dc74fd035df5bb727b5596f40e3dd2d2202141e69b0993717ede09 -a5e6fd88a2f9174d9bd4c6a55d9c30974be414992f22aa852f552c7648f722ed8077acf5aba030abd47939bb451b2c60 -8ad40a612824a7994487731a40b311b7349038c841145865539c6ada75c56de6ac547a1c23df190e0caaafecddd80ccc -953a7cea1d857e09202c438c6108060961f195f88c32f0e012236d7a4b39d840c61b162ec86436e8c38567328bea0246 -80d8b47a46dae1868a7b8ccfe7029445bbe1009dad4a6c31f9ef081be32e8e1ac1178c3c8fb68d3e536c84990cc035b1 -81ecd99f22b3766ce0aca08a0a9191793f68c754fdec78b82a4c3bdc2db122bbb9ebfd02fc2dcc6e1567a7d42d0cc16a -b1dd0446bccc25846fb95d08c1c9cc52fb51c72c4c5d169ffde56ecfe800f108dc1106d65d5c5bd1087c656de3940b63 -b87547f0931e164e96de5c550ca5aa81273648fe34f6e193cd9d69cf729cb432e17aa02e25b1c27a8a0d20a3b795e94e -820a94e69a927e077082aae66f6b292cfbe4589d932edf9e68e268c9bd3d71ef76cf7d169dd445b93967c25db11f58f1 -b0d07ddf2595270c39adfa0c8cf2ab1322979b0546aa4d918f641be53cd97f36c879bb75d205e457c011aca3bbd9f731 -8700b876b35b4b10a8a9372c5230acecd39539c1bb87515640293ad4464a9e02929d7d6a6a11112e8a29564815ac0de4 -a61a601c5bb27dcb97e37c8e2b9ce479c6b192a5e04d9ed5e065833c5a1017ee5f237b77d1a17be5d48f8e7cc0bcacf6 -92fb88fe774c1ba1d4a08cae3c0e05467ad610e7a3f1d2423fd47751759235fe0a3036db4095bd6404716aa03820f484 -b274f140d77a3ce0796f5e09094b516537ccaf27ae1907099bff172e6368ba85e7c3ef8ea2a07457cac48ae334da95b3 -b2292d9181f16581a9a9142490b2bdcdfb218ca6315d1effc8592100d792eb89d5356996c890441f04f2b4a95763503e -8897e73f576d86bc354baa3bd96e553107c48cf5889dcc23c5ba68ab8bcd4e81f27767be2233fdfa13d39f885087e668 -a29eac6f0829791c728d71abc49569df95a4446ecbfc534b39f24f56c88fe70301838dfc1c19751e7f3c5c1b8c6af6a0 -9346dc3720adc5df500a8df27fd9c75ef38dc5c8f4e8ed66983304750e66d502c3c59b8e955be781b670a0afc70a2167 -9566d534e0e30a5c5f1428665590617e95fd05d45f573715f58157854ad596ece3a3cfec61356aee342308d623e029d5 -a464fb8bffe6bd65f71938c1715c6e296cc6d0311a83858e4e7eb5873b7f2cf0c584d2101e3407b85b64ca78b2ac93ce -b54088f7217987c87e9498a747569ac5b2f8afd5348f9c45bf3fd9fbf713a20f495f49c8572d087efe778ac7313ad6d3 -91fa9f5f8000fe050f5b224d90b59fcce13c77e903cbf98ded752e5b3db16adb2bc1f8c94be48b69f65f1f1ad81d6264 -92d04a5b0ac5d8c8e313709b432c9434ecd3e73231f01e9b4e7952b87df60cbfa97b5dedd2200bd033b4b9ea8ba45cc1 -a94b90ad3c3d6c4bbe169f8661a790c40645b40f0a9d1c7220f01cf7fc176e04d80bab0ced9323fcafb93643f12b2760 -94d86149b9c8443b46196f7e5a3738206dd6f3be7762df488bcbb9f9ee285a64c997ed875b7b16b26604fa59020a8199 -82efe4ae2c50a2d7645240c173a047f238536598c04a2c0b69c96e96bd18e075a99110f1206bc213f39edca42ba00cc1 -ab8667685f831bc14d4610f84a5da27b4ea5b133b4d991741a9e64dceb22cb64a3ce8f1b6e101d52af6296df7127c9ad -83ba433661c05dcc5d562f4a9a261c8110dac44b8d833ae1514b1fc60d8b4ee395b18804baea04cb10adb428faf713c3 -b5748f6f660cc5277f1211d2b8649493ed8a11085b871cd33a5aea630abd960a740f08c08be5f9c21574600ac9bf5737 -a5c8dd12af48fb710642ad65ebb97ca489e8206741807f7acfc334f8035d3c80593b1ff2090c9bb7bd138f0c48714ca8 -a2b382fd5744e3babf454b1d806cc8783efeb4761bc42b6914ea48a46a2eae835efbe0a18262b6bc034379e03cf1262b -b3145ffaf603f69f15a64936d32e3219eea5ed49fdfd2f5bf40ea0dfd974b36fb6ff12164d4c2282d892db4cf3ff3ce1 -87a316fb213f4c5e30c5e3face049db66be4f28821bd96034714ec23d3e97849d7b301930f90a4323c7ccf53de23050c -b9de09a919455070fed6220fc179c8b7a4c753062bcd27acf28f5b9947a659c0b364298daf7c85c4ca6fca7f945add1f -806fbd98d411b76979464c40ad88bc07a151628a27fcc1012ba1dfbaf5b5cc9d962fb9b3386008978a12515edce934bc -a15268877fae0d21610ae6a31061ed7c20814723385955fac09fdc9693a94c33dea11db98bb89fdfe68f933490f5c381 -8d633fb0c4da86b2e0b37d8fad5972d62bff2ac663c5ec815d095cd4b7e1fe66ebef2a2590995b57eaf941983c7ad7a4 -8139e5dd9cf405e8ef65f11164f0440827d98389ce1b418b0c9628be983a9ddd6cf4863036ccb1483b40b8a527acd9ed -88b15fa94a08eac291d2b94a2b30eb851ff24addf2cc30b678e72e32cfcb3424cf4b33aa395d741803f3e578ddf524de -b5eaf0c8506e101f1646bcf049ee38d99ea1c60169730da893fd6020fd00a289eb2f415947e44677af49e43454a7b1be -8489822ad0647a7e06aa2aa5595960811858ddd4542acca419dd2308a8c5477648f4dd969a6740bb78aa26db9bfcc555 -b1e9a7b9f3423c220330d45f69e45fa03d7671897cf077f913c252e3e99c7b1b1cf6d30caad65e4228d5d7b80eb86e5e -b28fe9629592b9e6a55a1406903be76250b1c50c65296c10c5e48c64b539fb08fe11f68cf462a6edcbba71b0cee3feb2 -a41acf96a02c96cd8744ff6577c244fc923810d17ade133587e4c223beb7b4d99fa56eae311a500d7151979267d0895c -880798938fe4ba70721be90e666dfb62fcab4f3556fdb7b0dc8ec5bc34f6b4513df965eae78527136eb391889fe2caf9 -98d4d89d358e0fb7e212498c73447d94a83c1b66e98fc81427ab13acddb17a20f52308983f3a5a8e0aaacec432359604 -81430b6d2998fc78ba937a1639c6020199c52da499f68109da227882dc26d005b73d54c5bdcac1a04e8356a8ca0f7017 -a8d906a4786455eb74613aba4ce1c963c60095ffb8658d368df9266fdd01e30269ce10bf984e7465f34b4fd83beba26a -af54167ac1f954d10131d44a8e0045df00d581dd9e93596a28d157543fbe5fb25d213806ed7fb3cba6b8f5b5423562db -8511e373a978a12d81266b9afbd55035d7bc736835cfa921903a92969eeba3624437d1346b55382e61415726ab84a448 -8cf43eea93508ae586fa9a0f1354a1e16af659782479c2040874a46317f9e8d572a23238efa318fdfb87cc63932602b7 -b0bdd3bacff077173d302e3a9678d1d37936188c7ecc34950185af6b462b7c679815176f3cce5db19aac8b282f2d60ad -a355e9b87f2f2672052f5d4d65b8c1c827d24d89b0d8594641fccfb69aef1b94009105f3242058bb31c8bf51caae5a41 -b8baa9e4b950b72ff6b88a6509e8ed1304bc6fd955748b2e59a523a1e0c5e99f52aec3da7fa9ff407a7adf259652466c -840bc3dbb300ea6f27d1d6dd861f15680bd098be5174f45d6b75b094d0635aced539fa03ddbccb453879de77fb5d1fe9 -b4bc7e7e30686303856472bae07e581a0c0bfc815657c479f9f5931cff208d5c12930d2fd1ff413ebd8424bcd7a9b571 -89b5d514155d7999408334a50822508b9d689add55d44a240ff2bdde2eee419d117031f85e924e2a2c1ca77db9b91eea -a8604b6196f87a04e1350302e8aa745bba8dc162115d22657b37a1d1a98cb14876ddf7f65840b5dbd77e80cd22b4256c -83cb7acdb9e03247515bb2ce0227486ccf803426717a14510f0d59d45e998b245797d356f10abca94f7a14e1a2f0d552 -aeb3266a9f16649210ab2df0e1908ac259f34ce1f01162c22b56cf1019096ee4ea5854c36e30bb2feb06c21a71e8a45c -89e72e86edf2aa032a0fc9acf4d876a40865fbb2c8f87cb7e4d88856295c4ac14583e874142fd0c314a49aba68c0aa3c -8c3576eba0583c2a7884976b4ed11fe1fda4f6c32f6385d96c47b0e776afa287503b397fa516a455b4b8c3afeedc76db -a31e5b633bda9ffa174654fee98b5d5930a691c3c42fcf55673d927dbc8d91c58c4e42e615353145431baa646e8bbb30 -89f2f3f7a8da1544f24682f41c68114a8f78c86bd36b066e27da13acb70f18d9f548773a16bd8e24789420e17183f137 -ada27fa4e90a086240c9164544d2528621a415a5497badb79f8019dc3dce4d12eb6b599597e47ec6ac39c81efda43520 -90dc1eb21bf21c0187f359566fc4bf5386abea52799306a0e5a1151c0817c5f5bc60c86e76b1929c092c0f3ff48cedd2 -b702a53ebcc17ae35d2e735a347d2c700e9cbef8eadbece33cac83df483b2054c126593e1f462cfc00a3ce9d737e2af5 -9891b06455ec925a6f8eafffba05af6a38cc5e193acaaf74ffbf199df912c5197106c5e06d72942bbb032ce277b6417f -8c0ee71eb01197b019275bcf96cae94e81d2cdc3115dbf2d8e3080074260318bc9303597e8f72b18f965ad601d31ec43 -8aaf580aaf75c1b7a5f99ccf60503506e62058ef43b28b02f79b8536a96be3f019c9f71caf327b4e6730134730d1bef5 -ae6f9fc21dd7dfa672b25a87eb0a41644f7609fab5026d5cedb6e43a06dbbfd6d6e30322a2598c8dedde88c52eaed626 -8159b953ffece5693edadb2e906ebf76ff080ee1ad22698950d2d3bfc36ac5ea78f58284b2ca180664452d55bd54716c -ab7647c32ca5e9856ac283a2f86768d68de75ceeba9e58b74c5324f8298319e52183739aba4340be901699d66ac9eb3f -a4d85a5701d89bcfaf1572db83258d86a1a0717603d6f24ac2963ffcf80f1265e5ab376a4529ca504f4396498791253c -816080c0cdbfe61b4d726c305747a9eb58ac26d9a35f501dd32ba43c098082d20faf3ccd41aad24600aa73bfa453dfac -84f3afac024f576b0fd9acc6f2349c2fcefc3f77dbe5a2d4964d14b861b88e9b1810334b908cf3427d9b67a8aee74b18 -94b390655557b1a09110018e9b5a14490681ade275bdc83510b6465a1218465260d9a7e2a6e4ec700f58c31dc3659962 -a8c66826b1c04a2dd4c682543242e7a57acae37278bd09888a3d17747c5b5fec43548101e6f46d703638337e2fd3277b -86e6f4608a00007fa533c36a5b054c5768ccafe41ad52521d772dcae4c8a4bcaff8f7609be30d8fab62c5988cbbb6830 -837da4cf09ae8aa0bceb16f8b3bfcc3b3367aecac9eed6b4b56d7b65f55981ef066490764fb4c108792623ecf8cad383 -941ff3011462f9b5bf97d8cbdb0b6f5d37a1b1295b622f5485b7d69f2cb2bcabc83630dae427f0259d0d9539a77d8424 -b99e5d6d82aa9cf7d5970e7f710f4039ac32c2077530e4c2779250c6b9b373bc380adb0a03b892b652f649720672fc8c -a791c78464b2d65a15440b699e1e30ebd08501d6f2720adbc8255d989a82fcded2f79819b5f8f201bed84a255211b141 -84af7ad4a0e31fcbb3276ab1ad6171429cf39adcf78dc03750dc5deaa46536d15591e26d53e953dfb31e1622bc0743ab -a833e62fe97e1086fae1d4917fbaf09c345feb6bf1975b5cb863d8b66e8d621c7989ab3dbecda36bc9eaffc5eaa6fa66 -b4ef79a46a2126f53e2ebe62770feb57fd94600be29459d70a77c5e9cc260fa892be06cd60f886bf48459e48eb50d063 -b43b8f61919ea380bf151c294e54d3a3ff98e20d1ee5efbfe38aa2b66fafbc6a49739793bd5cb1c809f8b30466277c3a -ab37735af2412d2550e62df9d8b3b5e6f467f20de3890bf56faf1abf2bf3bd1d98dc3fa0ad5e7ab3fce0fa20409eb392 -82416b74b1551d484250d85bb151fabb67e29cce93d516125533df585bc80779ab057ea6992801a3d7d5c6dcff87a018 -8145d0787f0e3b5325190ae10c1d6bee713e6765fb6a0e9214132c6f78f4582bb2771aaeae40d3dad4bafb56bf7e36d8 -b6935886349ecbdd5774e12196f4275c97ec8279fdf28ccf940f6a022ebb6de8e97d6d2173c3fe402cbe9643bed3883b -87ef9b4d3dc71ac86369f8ed17e0dd3b91d16d14ae694bc21a35b5ae37211b043d0e36d8ff07dcc513fb9e6481a1f37f -ae1d0ded32f7e6f1dc8fef495879c1d9e01826f449f903c1e5034aeeabc5479a9e323b162b688317d46d35a42d570d86 -a40d16497004db4104c6794e2f4428d75bdf70352685944f3fbe17526df333e46a4ca6de55a4a48c02ecf0bde8ba03c0 -8d45121efba8cc308a498e8ee39ea6fa5cae9fb2e4aab1c2ff9d448aa8494ccbec9a078f978a86fcd97b5d5e7be7522a -a8173865c64634ba4ac2fa432740f5c05056a9deaf6427cb9b4b8da94ca5ddbc8c0c5d3185a89b8b28878194de9cdfcd -b6ec06a74d690f6545f0f0efba236e63d1fdfba54639ca2617408e185177ece28901c457d02b849fd00f1a53ae319d0a -b69a12df293c014a40070e3e760169b6f3c627caf9e50b35a93f11ecf8df98b2bc481b410eecb7ab210bf213bbe944de -97e7dc121795a533d4224803e591eef3e9008bab16f12472210b73aaf77890cf6e3877e0139403a0d3003c12c8f45636 -acdfa6fdd4a5acb7738cc8768f7cba84dbb95c639399b291ae8e4e63df37d2d4096900a84d2f0606bf534a9ccaa4993f -86ee253f3a9446a33e4d1169719b7d513c6b50730988415382faaf751988c10a421020609f7bcdef91be136704b906e2 -aac9438382a856caf84c5a8a234282f71b5fc5f65219103b147e7e6cf565522285fbfd7417b513bdad8277a00f652ca1 -83f3799d8e5772527930f5dc071a2e0a65471618993ec8990a96ccdeee65270e490bda9d26bb877612475268711ffd80 -93f28a81ac8c0ec9450b9d762fae9c7f8feaace87a6ee6bd141ef1d2d0697ef1bbd159fe6e1de640dbdab2b0361fca8a -a0825c95ba69999b90eac3a31a3fd830ea4f4b2b7409bde5f202b61d741d6326852ce790f41de5cb0eccec7af4db30c1 -83924b0e66233edd603c3b813d698daa05751fc34367120e3cf384ea7432e256ccee4d4daf13858950549d75a377107d -956fd9fa58345277e06ba2ec72f49ed230b8d3d4ff658555c52d6cddeb84dd4e36f1a614f5242d5ca0192e8daf0543c2 -944869912476baae0b114cced4ff65c0e4c90136f73ece5656460626599051b78802df67d7201c55d52725a97f5f29fe -865cb25b64b4531fb6fe4814d7c8cd26b017a6c6b72232ff53defc18a80fe3b39511b23f9e4c6c7249d06e03b2282ed2 -81e09ff55214960775e1e7f2758b9a6c4e4cd39edf7ec1adfaad51c52141182b79fe2176b23ddc7df9fd153e5f82d668 -b31006896f02bc90641121083f43c3172b1039334501fbaf1672f7bf5d174ddd185f945adf1a9c6cf77be34c5501483d -88b92f6f42ae45e9f05b16e52852826e933efd0c68b0f2418ac90957fd018df661bc47c8d43c2a7d7bfcf669dab98c3c -92fc68f595853ee8683930751789b799f397135d002eda244fe63ecef2754e15849edde3ba2f0cc8b865c9777230b712 -99ca06a49c5cd0bb097c447793fcdd809869b216a34c66c78c7e41e8c22f05d09168d46b8b1f3390db9452d91bc96dea -b48b9490a5d65296802431852d548d81047bbefc74fa7dc1d4e2a2878faacdfcb365ae59209cb0ade01901a283cbd15d -aff0fdbef7c188b120a02bc9085d7b808e88f73973773fef54707bf2cd772cd066740b1b6f4127b5c349f657bd97e738 -966fd4463b4f43dd8ccba7ad50baa42292f9f8b2e70da23bb6780e14155d9346e275ef03ddaf79e47020dcf43f3738bd -9330c3e1fadd9e08ac85f4839121ae20bbeb0a5103d84fa5aadbd1213805bdcda67bf2fb75fc301349cbc851b5559d20 -993bb99867bd9041a71a55ad5d397755cfa7ab6a4618fc526179bfc10b7dc8b26e4372fe9a9b4a15d64f2b63c1052dda -a29b59bcfab51f9b3c490a3b96f0bf1934265c315349b236012adbd64a56d7f6941b2c8cc272b412044bc7731f71e1dc -a65c9cefe1fc35d089fe8580c2e7671ebefdb43014ac291528ff4deefd4883fd4df274af83711dad610dad0d615f9d65 -944c78c56fb227ae632805d448ca3884cd3d2a89181cead3d2b7835e63297e6d740aa79a112edb1d4727824991636df5 -a73d782da1db7e4e65d7b26717a76e16dd9fab4df65063310b8e917dc0bc24e0d6755df5546c58504d04d9e68c3b474a -af80f0b87811ae3124f68108b4ca1937009403f87928bbc53480e7c5408d072053ace5eeaf5a5aba814dab8a45502085 -88aaf1acfc6e2e19b8387c97da707cb171c69812fefdd4650468e9b2c627bd5ccfb459f4d8e56bdfd84b09ddf87e128f -92c97276ff6f72bab6e9423d02ad6dc127962dbce15a0dd1e4a393b4510c555df6aa27be0f697c0d847033a9ca8b8dfd -a0e07d43d96e2d85b6276b3c60aadb48f0aedf2de8c415756dc597249ea64d2093731d8735231dadc961e5682ac59479 -adc9e6718a8f9298957d1da3842a7751c5399bbdf56f8de6c1c4bc39428f4aee6f1ba6613d37bf46b9403345e9d6fc81 -951da434da4b20d949b509ceeba02e24da7ed2da964c2fcdf426ec787779c696b385822c7dbea4df3e4a35921f1e912c -a04cbce0d2b2e87bbf038c798a12ec828423ca6aca08dc8d481cf6466e3c9c73d4d4a7fa47df9a7e2e15aae9e9f67208 -8f855cca2e440d248121c0469de1f94c2a71b8ee2682bbad3a78243a9e03da31d1925e6760dbc48a1957e040fae9abe8 -b642e5b17c1df4a4e101772d73851180b3a92e9e8b26c918050f51e6dd3592f102d20b0a1e96f0e25752c292f4c903ff -a92454c300781f8ae1766dbbb50a96192da7d48ef4cbdd72dd8cbb44c6eb5913c112cc38e9144615fdc03684deb99420 -8b74f7e6c2304f8e780df4649ef8221795dfe85fdbdaa477a1542d135b75c8be45bf89adbbb6f3ddf54ca40f02e733e9 -85cf66292cbb30cec5fd835ab10c9fcb3aea95e093aebf123e9a83c26f322d76ebc89c4e914524f6c5f6ee7d74fc917d -ae0bfe0cdc97c09542a7431820015f2d16067b30dca56288013876025e81daa8c519e5e347268e19aa1a85fa1dc28793 -921322fc6a47dc091afa0ad6df18ed14cde38e48c6e71550aa513918b056044983aee402de21051235eecf4ce8040fbe -96c030381e97050a45a318d307dcb3c8377b79b4dd5daf6337cded114de26eb725c14171b9b8e1b3c08fe1f5ea6b49e0 -90c23b86b6111818c8baaf53a13eaee1c89203b50e7f9a994bf0edf851919b48edbac7ceef14ac9414cf70c486174a77 -8bf6c301240d2d1c8d84c71d33a6dfc6d9e8f1cfae66d4d0f7a256d98ae12b0bcebfa94a667735ee89f810bcd7170cff -a41a4ffbbea0e36874d65c009ee4c3feffff322f6fc0e30d26ee4dbc1f46040d05e25d9d0ecb378cef0d24a7c2c4b850 -a8d4cdd423986bb392a0a92c12a8bd4da3437eec6ef6af34cf5310944899287452a2eb92eb5386086d5063381189d10e -a81dd26ec057c4032a4ed7ad54d926165273ed51d09a1267b2e477535cf6966835a257c209e4e92d165d74fa75695fa3 -8d7f708c3ee8449515d94fc26b547303b53d8dd55f177bc3b25d3da2768accd9bc8e9f09546090ebb7f15c66e6c9c723 -839ba65cffcd24cfffa7ab3b21faabe3c66d4c06324f07b2729c92f15cad34e474b0f0ddb16cd652870b26a756b731d3 -87f1a3968afec354d92d77e2726b702847c6afcabb8438634f9c6f7766de4c1504317dc4fa9a4a735acdbf985e119564 -91a8a7fd6542f3e0673f07f510d850864b34ac087eb7eef8845a1d14b2b1b651cbdc27fa4049bdbf3fea54221c5c8549 -aef3cf5f5e3a2385ead115728d7059e622146c3457d266c612e778324b6e06fbfb8f98e076624d2f3ce1035d65389a07 -819915d6232e95ccd7693fdd78d00492299b1983bc8f96a08dcb50f9c0a813ed93ae53c0238345d5bea0beda2855a913 -8e9ba68ded0e94935131b392b28218315a185f63bf5e3c1a9a9dd470944509ca0ba8f6122265f8da851b5cc2abce68f1 -b28468e9b04ee9d69003399a3cf4457c9bf9d59f36ab6ceeb8e964672433d06b58beeea198fedc7edbaa1948577e9fa2 -a633005e2c9f2fd94c8bce2dd5bb708fe946b25f1ec561ae65e54e15cdd88dc339f1a083e01f0d39610c8fe24151aaf0 -841d0031e22723f9328dd993805abd13e0c99b0f59435d2426246996b08d00ce73ab906f66c4eab423473b409e972ce0 -85758d1b084263992070ec8943f33073a2d9b86a8606672550c17545507a5b3c88d87382b41916a87ee96ff55a7aa535 -8581b06b0fc41466ef94a76a1d9fb8ae0edca6d018063acf6a8ca5f4b02d76021902feba58972415691b4bdbc33ae3b4 -83539597ff5e327357ee62bc6bf8c0bcaec2f227c55c7c385a4806f0d37fb461f1690bad5066b8a5370950af32fafbef -aee3557290d2dc10827e4791d00e0259006911f3f3fce4179ed3c514b779160613eca70f720bff7804752715a1266ffa -b48d2f0c4e90fc307d5995464e3f611a9b0ef5fe426a289071f4168ed5cc4f8770c9332960c2ca5c8c427f40e6bb389f -847af8973b4e300bb06be69b71b96183fd1a0b9d51b91701bef6fcfde465068f1eb2b1503b07afda380f18d69de5c9e1 -a70a6a80ce407f07804c0051ac21dc24d794b387be94eb24e1db94b58a78e1bcfb48cd0006db8fc1f9bedaece7a44fbe -b40e942b8fa5336910ff0098347df716bff9d1fa236a1950c16eeb966b3bc1a50b8f7b0980469d42e75ae13ced53cead -b208fabaa742d7db3148515330eb7a3577487845abdb7bd9ed169d0e081db0a5816595c33d375e56aeac5b51e60e49d3 -b7c8194b30d3d6ef5ab66ec88ad7ebbc732a3b8a41731b153e6f63759a93f3f4a537eab9ad369705bd730184bdbbdc34 -9280096445fe7394d04aa1bc4620c8f9296e991cc4d6c131bd703cb1cc317510e6e5855ac763f4d958c5edfe7eebeed7 -abc2aa4616a521400af1a12440dc544e3c821313d0ab936c86af28468ef8bbe534837e364598396a81cf8d06274ed5a6 -b18ca8a3325adb0c8c18a666d4859535397a1c3fe08f95eebfac916a7a99bbd40b3c37b919e8a8ae91da38bc00fa56c0 -8a40c33109ecea2a8b3558565877082f79121a432c45ec2c5a5e0ec4d1c203a6788e6b69cb37f1fd5b8c9a661bc5476d -88c47301dd30998e903c84e0b0f2c9af2e1ce6b9f187dab03528d44f834dc991e4c86d0c474a2c63468cf4020a1e24a0 -920c832853e6ab4c851eecfa9c11d3acc7da37c823be7aa1ab15e14dfd8beb5d0b91d62a30cec94763bd8e4594b66600 -98e1addbe2a6b8edc7f12ecb9be81c3250aeeca54a1c6a7225772ca66549827c15f3950d01b8eb44aecb56fe0fff901a -8cfb0fa1068be0ec088402f5950c4679a2eb9218c729da67050b0d1b2d7079f3ddf4bf0f57d95fe2a8db04bc6bcdb20c -b70f381aafe336b024120453813aeab70baac85b9c4c0f86918797b6aee206e6ed93244a49950f3d8ec9f81f4ac15808 -a4c8edf4aa33b709a91e1062939512419711c1757084e46f8f4b7ed64f8e682f4e78b7135920c12f0eb0422fe9f87a6a -b4817e85fd0752d7ebb662d3a51a03367a84bac74ebddfba0e5af5e636a979500f72b148052d333b3dedf9edd2b4031b -a87430169c6195f5d3e314ff2d1c2f050e766fd5d2de88f5207d72dba4a7745bb86d0baca6e9ae156582d0d89e5838c7 -991b00f8b104566b63a12af4826b61ce7aa40f4e5b8fff3085e7a99815bdb4471b6214da1e480214fac83f86a0b93cc5 -b39966e3076482079de0678477df98578377a094054960ee518ef99504d6851f8bcd3203e8da5e1d4f6f96776e1fe6eb -a448846d9dc2ab7a0995fa44b8527e27f6b3b74c6e03e95edb64e6baa4f1b866103f0addb97c84bef1d72487b2e21796 -894bec21a453ae84b592286e696c35bc30e820e9c2fd3e63dd4fbe629e07df16439c891056070faa490155f255bf7187 -a9ec652a491b11f6a692064e955f3f3287e7d2764527e58938571469a1e29b5225b9415bd602a45074dfbfe9c131d6ca -b39d37822e6cbe28244b5f42ce467c65a23765bd16eb6447c5b3e942278069793763483dafd8c4dd864f8917aad357fe -88dba51133f2019cb266641c56101e3e5987d3b77647a2e608b5ff9113dfc5f85e2b7c365118723131fbc0c9ca833c9c -b566579d904b54ecf798018efcb824dccbebfc6753a0fd2128ac3b4bd3b038c2284a7c782b5ca6f310eb7ea4d26a3f0a -a97a55c0a492e53c047e7d6f9d5f3e86fb96f3dddc68389c0561515343b66b4bc02a9c0d5722dff1e3445308240b27f7 -a044028ab4bcb9e1a2b9b4ca4efbf04c5da9e4bf2fff0e8bd57aa1fc12a71e897999c25d9117413faf2f45395dee0f13 -a78dc461decbeaeed8ebd0909369b491a5e764d6a5645a7dac61d3140d7dc0062526f777b0eb866bff27608429ebbdde -b2c2a8991f94c39ca35fea59f01a92cb3393e0eccb2476dfbf57261d406a68bd34a6cff33ed80209991688c183609ef4 -84189eefb521aff730a4fd3fd5b10ddfd29f0d365664caef63bb015d07e689989e54c33c2141dd64427805d37a7e546e -85ac80bd734a52235da288ff042dea9a62e085928954e8eacd2c751013f61904ed110e5b3afe1ab770a7e6485efb7b5e -9183a560393dcb22d0d5063e71182020d0fbabb39e32493eeffeb808df084aa243eb397027f150b55a247d1ed0c8513e -81c940944df7ecc58d3c43c34996852c3c7915ed185d7654627f7af62abae7e0048dd444a6c09961756455000bd96d09 -aa8c34e164019743fd8284b84f06c3b449aae7996e892f419ee55d82ad548cb300fd651de329da0384243954c0ef6a60 -89a7b7bdfc7e300d06a14d463e573d6296d8e66197491900cc9ae49504c4809ff6e61b758579e9091c61085ba1237b83 -878d21809ba540f50bd11f4c4d9590fb6f3ab9de5692606e6e2ef4ed9d18520119e385be5e1f4b3f2e2b09c319f0e8fc -8eb248390193189cf0355365e630b782cd15751e672dc478b39d75dc681234dcd9309df0d11f4610dbb249c1e6be7ef9 -a1d7fb3aecb896df3a52d6bd0943838b13f1bd039c936d76d03de2044c371d48865694b6f532393b27fd10a4cf642061 -a34bca58a24979be442238cbb5ece5bee51ae8c0794dd3efb3983d4db713bc6f28a96e976ac3bd9a551d3ed9ba6b3e22 -817c608fc8cacdd178665320b5a7587ca21df8bdd761833c3018b967575d25e3951cf3d498a63619a3cd2ad4406f5f28 -86c95707db0495689afd0c2e39e97f445f7ca0edffad5c8b4cacd1421f2f3cc55049dfd504f728f91534e20383955582 -99c3b0bb15942c301137765d4e19502f65806f3b126dc01a5b7820c87e8979bce6a37289a8f6a4c1e4637227ad5bf3bf -8aa1518a80ea8b074505a9b3f96829f5d4afa55a30efe7b4de4e5dbf666897fdd2cf31728ca45921e21a78a80f0e0f10 -8d74f46361c79e15128ac399e958a91067ef4cec8983408775a87eca1eed5b7dcbf0ddf30e66f51780457413496c7f07 -a41cde4a786b55387458a1db95171aca4fd146507b81c4da1e6d6e495527c3ec83fc42fad1dfe3d92744084a664fd431 -8c352852c906fae99413a84ad11701f93f292fbf7bd14738814f4c4ceab32db02feb5eb70bc73898b0bc724a39d5d017 -a5993046e8f23b71ba87b7caa7ace2d9023fb48ce4c51838813174880d918e9b4d2b0dc21a2b9c6f612338c31a289df8 -83576d3324bf2d8afbfb6eaecdc5d767c8e22e7d25160414924f0645491df60541948a05e1f4202e612368e78675de8a -b43749b8df4b15bc9a3697e0f1c518e6b04114171739ef1a0c9c65185d8ec18e40e6954d125cbc14ebc652cf41ad3109 -b4eebd5d80a7327a040cafb9ccdb12b2dfe1aa86e6bc6d3ac8a57fadfb95a5b1a7332c66318ff72ba459f525668af056 -9198be7f1d413c5029b0e1c617bcbc082d21abe2c60ec8ce9b54ca1a85d3dba637b72fda39dae0c0ae40d047eab9f55a -8d96a0232832e24d45092653e781e7a9c9520766c3989e67bbe86b3a820c4bf621ea911e7cd5270a4bfea78b618411f6 -8d7160d0ea98161a2d14d46ef01dff72d566c330cd4fabd27654d300e1bc7644c68dc8eabf2a20a59bfe7ba276545f9b -abb60fce29dec7ba37e3056e412e0ec3e05538a1fc0e2c68877378c867605966108bc5742585ab6a405ce0c962b285b6 -8fabffa3ed792f05e414f5839386f6449fd9f7b41a47595c5d71074bd1bb3784cc7a1a7e1ad6b041b455035957e5b2dc -90ff017b4804c2d0533b72461436b10603ab13a55f86fd4ec11b06a70ef8166f958c110519ca1b4cc7beba440729fe2d -b340cfd120f6a4623e3a74cf8c32bfd7cd61a280b59dfd17b15ca8fae4d82f64a6f15fbde4c02f424debc72b7db5fe67 -871311c9c7220c932e738d59f0ecc67a34356d1429fe570ca503d340c9996cb5ee2cd188fad0e3bd16e4c468ec1dbebd -a772470262186e7b94239ba921b29f2412c148d6f97c4412e96d21e55f3be73f992f1ad53c71008f0558ec3f84e2b5a7 -b2a897dcb7ffd6257f3f2947ec966f2077d57d5191a88840b1d4f67effebe8c436641be85524d0a21be734c63ab5965d -a044f6eacc48a4a061fa149500d96b48cbf14853469aa4d045faf3dca973be1bd4b4ce01646d83e2f24f7c486d03205d -981af5dc2daa73f7fa9eae35a93d81eb6edba4a7f673b55d41f6ecd87a37685d31bb40ef4f1c469b3d72f2f18b925a17 -912d2597a07864de9020ac77083eff2f15ceb07600f15755aba61251e8ce3c905a758453b417f04d9c38db040954eb65 -9642b7f6f09394ba5e0805734ef6702c3eddf9eea187ba98c676d5bbaec0e360e3e51dc58433aaa1e2da6060c8659cb7 -8ab3836e0a8ac492d5e707d056310c4c8e0489ca85eb771bff35ba1d658360084e836a6f51bb990f9e3d2d9aeb18fbb5 -879e058e72b73bb1f4642c21ffdb90544b846868139c6511f299aafe59c2d0f0b944dffc7990491b7c4edcd6a9889250 -b9e60b737023f61479a4a8fd253ed0d2a944ea6ba0439bbc0a0d3abf09b0ad1f18d75555e4a50405470ae4990626f390 -b9c2535d362796dcd673640a9fa2ebdaec274e6f8b850b023153b0a7a30fffc87f96e0b72696f647ebe7ab63099a6963 -94aeff145386a087b0e91e68a84a5ede01f978f9dd9fe7bebca78941938469495dc30a96bba9508c0d017873aeea9610 -98b179f8a3d9f0d0a983c30682dd425a2ddc7803be59bd626c623c8951a5179117d1d2a68254c95c9952989877d0ee55 -889ecf5f0ee56938273f74eb3e9ecfb5617f04fb58e83fe4c0e4aef51615cf345bc56f3f61b17f6eed3249d4afd54451 -a0f2b2c39bcea4b50883e2587d16559e246248a66ecb4a4b7d9ab3b51fb39fe98d83765e087eee37a0f86b0ba4144c02 -b2a61e247ed595e8a3830f7973b07079cbda510f28ad8c78c220b26cb6acde4fbb5ee90c14a665f329168ee951b08cf0 -95bd0fcfb42f0d6d8a8e73d7458498a85bcddd2fb132fd7989265648d82ac2707d6d203fac045504977af4f0a2aca4b7 -843e5a537c298666e6cf50fcc044f13506499ef83c802e719ff2c90e85003c132024e04711be7234c04d4b0125512d5d -a46d1797c5959dcd3a5cfc857488f4d96f74277c3d13b98b133620192f79944abcb3a361d939a100187f1b0856eae875 -a1c7786736d6707a48515c38660615fcec67eb8a2598f46657855215f804fd72ab122d17f94fcffad8893f3be658dca7 -b23dc9e610abc7d8bd21d147e22509a0fa49db5be6ea7057b51aae38e31654b3aa044df05b94b718153361371ba2f622 -b00cc8f257d659c22d30e6d641f79166b1e752ea8606f558e4cad6fc01532e8319ea4ee12265ba4140ac45aa4613c004 -ac7019af65221b0cc736287b32d7f1a3561405715ba9a6a122342e04e51637ba911c41573de53e4781f2230fdcb2475f -81a630bc41b3da8b3eb4bf56cba10cd9f93153c3667f009dc332287baeb707d505fb537e6233c8e53d299ec0f013290c -a6b7aea5c545bb76df0f230548539db92bc26642572cb7dd3d5a30edca2b4c386f44fc8466f056b42de2a452b81aff5b -8271624ff736b7b238e43943c81de80a1612207d32036d820c11fc830c737972ccc9c60d3c2359922b06652311e3c994 -8a684106458cb6f4db478170b9ad595d4b54c18bf63b9058f095a2fa1b928c15101472c70c648873d5887880059ed402 -a5cc3c35228122f410184e4326cf61a37637206e589fcd245cb5d0cec91031f8f7586b80503070840fdfd8ce75d3c88b -9443fc631aed8866a7ed220890911057a1f56b0afe0ba15f0a0e295ab97f604b134b1ed9a4245e46ee5f9a93aa74f731 -984b6f7d79835dffde9558c6bb912d992ca1180a2361757bdba4a7b69dc74b056e303adc69fe67414495dd9c2dd91e64 -b15a5c8cba5de080224c274d31c68ed72d2a7126d347796569aef0c4e97ed084afe3da4d4b590b9dda1a07f0c2ff3dfb -991708fe9650a1f9a4e43938b91d45dc68c230e05ee999c95dbff3bf79b1c1b2bb0e7977de454237c355a73b8438b1d9 -b4f7edc7468b176a4a7c0273700c444fa95c726af6697028bed4f77eee887e3400f9c42ee15b782c0ca861c4c3b8c98a -8c60dcc16c51087eb477c13e837031d6c6a3dc2b8bf8cb43c23f48006bc7173151807e866ead2234b460c2de93b31956 -83ad63e9c910d1fc44bc114accfb0d4d333b7ebe032f73f62d25d3e172c029d5e34a1c9d547273bf6c0fead5c8801007 -85de73213cc236f00777560756bdbf2b16841ba4b55902cf2cad9742ecaf5d28209b012ceb41f337456dfeca93010cd7 -a7561f8827ccd75b6686ba5398bb8fc3083351c55a589b18984e186820af7e275af04bcd4c28e1dc11be1e8617a0610b -88c0a4febd4068850557f497ea888035c7fc9f404f6cc7794e7cc8722f048ad2f249e7dc62743e7a339eb7473ad3b0cd -932b22b1d3e6d5a6409c34980d176feb85ada1bf94332ef5c9fc4d42b907dabea608ceef9b5595ef3feee195151f18d8 -a2867bb3f5ab88fbdae3a16c9143ab8a8f4f476a2643c505bb9f37e5b1fd34d216cab2204c9a017a5a67b7ad2dda10e8 -b573d5f38e4e9e8a3a6fd82f0880dc049efa492a946d00283019bf1d5e5516464cf87039e80aef667cb86fdea5075904 -b948f1b5ab755f3f5f36af27d94f503b070696d793b1240c1bdfd2e8e56890d69e6904688b5f8ff5a4bdf5a6abfe195f -917eae95ebc4109a2e99ddd8fec7881d2f7aaa0e25fda44dec7ce37458c2ee832f1829db7d2dcfa4ca0f06381c7fe91d -95751d17ed00a3030bce909333799bb7f4ab641acf585807f355b51d6976dceee410798026a1a004ef4dcdff7ec0f5b8 -b9b7bd266f449a79bbfe075e429613e76c5a42ac61f01c8f0bbbd34669650682efe01ff9dbbc400a1e995616af6aa278 -ac1722d097ce9cd7617161f8ec8c23d68f1fb1c9ca533e2a8b4f78516c2fd8fb38f23f834e2b9a03bb06a9d655693ca9 -a7ad9e96ffd98db2ecdb6340c5d592614f3c159abfd832fe27ee9293519d213a578e6246aae51672ee353e3296858873 -989b8814d5de7937c4acafd000eec2b4cd58ba395d7b25f98cafd021e8efa37029b29ad8303a1f6867923f5852a220eb -a5bfe6282c771bc9e453e964042d44eff4098decacb89aecd3be662ea5b74506e1357ab26f3527110ba377711f3c9f41 -8900a7470b656639721d2abbb7b06af0ac4222ab85a1976386e2a62eb4b88bfb5b72cf7921ddb3cf3a395d7eeb192a2e -95a71b55cd1f35a438cf5e75f8ff11c5ec6a2ebf2e4dba172f50bfad7d6d5dca5de1b1afc541662c81c858f7604c1163 -82b5d62fea8db8d85c5bc3a76d68dedd25794cf14d4a7bc368938ffca9e09f7e598fdad2a5aac614e0e52f8112ae62b9 -997173f07c729202afcde3028fa7f52cefc90fda2d0c8ac2b58154a5073140683e54c49ed1f254481070d119ce0ce02a -aeffb91ccc7a72bbd6ffe0f9b99c9e66e67d59cec2e02440465e9636a613ab3017278cfa72ea8bc4aba9a8dc728cb367 -952743b06e8645894aeb6440fc7a5f62dd3acf96dab70a51e20176762c9751ea5f2ba0b9497ccf0114dc4892dc606031 -874c63baeddc56fbbca2ff6031f8634b745f6e34ea6791d7c439201aee8f08ef5ee75f7778700a647f3b21068513fce6 -85128fec9c750c1071edfb15586435cc2f317e3e9a175bb8a9697bcda1eb9375478cf25d01e7fed113483b28f625122d -85522c9576fd9763e32af8495ae3928ed7116fb70d4378448926bc9790e8a8d08f98cf47648d7da1b6e40d6a210c7924 -97d0f37a13cfb723b848099ca1c14d83e9aaf2f7aeb71829180e664b7968632a08f6a85f557d74b55afe6242f2a36e7c -abaa472d6ad61a5fccd1a57c01aa1bc081253f95abbcba7f73923f1f11c4e79b904263890eeb66926de3e2652f5d1c70 -b3c04945ba727a141e5e8aec2bf9aa3772b64d8fd0e2a2b07f3a91106a95cbcb249adcd074cbe498caf76fffac20d4ef -82c46781a3d730d9931bcabd7434a9171372dde57171b6180e5516d4e68db8b23495c8ac3ab96994c17ddb1cf249b9fb -a202d8b65613c42d01738ccd68ed8c2dbc021631f602d53f751966e04182743ebc8e0747d600b8a8676b1da9ae7f11ab -ae73e7256e9459db04667a899e0d3ea5255211fb486d084e6550b6dd64ca44af6c6b2d59d7aa152de9f96ce9b58d940d -b67d87b176a9722945ec7593777ee461809861c6cfd1b945dde9ee4ff009ca4f19cf88f4bbb5c80c9cbab2fe25b23ac8 -8f0b7a317a076758b0dac79959ee4a06c08b07d0f10538a4b53d3da2eda16e2af26922feb32c090330dc4d969cf69bd3 -90b36bf56adbd8c4b6cb32febc3a8d5f714370c2ac3305c10fa6d168dffb2a026804517215f9a2d4ec8310cdb6bb459b -aa80c19b0682ead69934bf18cf476291a0beddd8ef4ed75975d0a472e2ab5c70f119722a8574ae4973aceb733d312e57 -a3fc9abb12574e5c28dcb51750b4339b794b8e558675eef7d26126edf1de920c35e992333bcbffcbf6a5f5c0d383ce62 -a1573ff23ab972acdcd08818853b111fc757fdd35aa070186d3e11e56b172fb49d840bf297ac0dd222e072fc09f26a81 -98306f2be4caa92c2b4392212d0cbf430b409b19ff7d5b899986613bd0e762c909fc01999aa94be3bd529d67f0113d7f -8c1fc42482a0819074241746d17dc89c0304a2acdae8ed91b5009e9e3e70ff725ba063b4a3e68fdce05b74f5180c545e -a6c6113ebf72d8cf3163b2b8d7f3fa24303b13f55752522c660a98cd834d85d8c79214d900fa649499365e2e7641f77a -ab95eea424f8a2cfd9fb1c78bb724e5b1d71a0d0d1e4217c5d0f98b0d8bbd3f8400a2002abc0a0e4576d1f93f46fefad -823c5a4fd8cf4a75fdc71d5f2dd511b6c0f189b82affeacd2b7cfcad8ad1a5551227dcc9bfdb2e34b2097eaa00efbb51 -b97314dfff36d80c46b53d87a61b0e124dc94018a0bb680c32765b9a2d457f833a7c42bbc90b3b1520c33a182580398d -b17566ee3dcc6bb3b004afe4c0136dfe7dd27df9045ae896dca49fb36987501ae069eb745af81ba3fc19ff037e7b1406 -b0bdc0f55cfd98d331e3a0c4fbb776a131936c3c47c6bffdc3aaf7d8c9fa6803fbc122c2fefbb532e634228687d52174 -aa5d9e60cc9f0598559c28bb9bdd52aa46605ab4ffe3d192ba982398e72cec9a2a44c0d0d938ce69935693cabc0887ea -802b6459d2354fa1d56c592ac1346c428dadea6b6c0a87bf7d309bab55c94e1cf31dd98a7a86bd92a840dd51f218b91b -a526914efdc190381bf1a73dd33f392ecf01350b9d3f4ae96b1b1c3d1d064721c7d6eec5788162c933245a3943f5ee51 -b3b8fcf637d8d6628620a1a99dbe619eabb3e5c7ce930d6efd2197e261bf394b74d4e5c26b96c4b8009c7e523ccfd082 -8f7510c732502a93e095aba744535f3928f893f188adc5b16008385fb9e80f695d0435bfc5b91cdad4537e87e9d2551c -97b90beaa56aa936c3ca45698f79273a68dd3ccd0076eab48d2a4db01782665e63f33c25751c1f2e070f4d1a8525bf96 -b9fb798324b1d1283fdc3e48288e3861a5449b2ab5e884b34ebb8f740225324af86e4711da6b5cc8361c1db15466602f -b6d52b53cea98f1d1d4c9a759c25bf9d8a50b604b144e4912acbdbdc32aab8b9dbb10d64a29aa33a4f502121a6fb481c -9174ffff0f2930fc228f0e539f5cfd82c9368d26b074467f39c07a774367ff6cccb5039ac63f107677d77706cd431680 -a33b6250d4ac9e66ec51c063d1a6a31f253eb29bbaed12a0d67e2eccfffb0f3a52750fbf52a1c2aaba8c7692346426e7 -a97025fd5cbcebe8ef865afc39cd3ea707b89d4e765ec817fd021d6438e02fa51e3544b1fd45470c58007a08efac6edd -b32a78480edd9ff6ba2f1eec4088db5d6ceb2d62d7e59e904ecaef7bb4a2e983a4588e51692b3be76e6ffbc0b5f911a5 -b5ab590ef0bb77191f00495b33d11c53c65a819f7d0c1f9dc4a2caa147a69c77a4fff7366a602d743ee1f395ce934c1e -b3fb0842f9441fb1d0ee0293b6efbc70a8f58d12d6f769b12872db726b19e16f0f65efbc891cf27a28a248b0ef9c7e75 -9372ad12856fefb928ccb0d34e198df99e2f8973b07e9d417a3134d5f69e12e79ff572c4e03ccd65415d70639bc7c73e -aa8d6e83d09ce216bfe2009a6b07d0110d98cf305364d5529c170a23e693aabb768b2016befb5ada8dabdd92b4d012bb -a954a75791eeb0ce41c85200c3763a508ed8214b5945a42c79bfdcfb1ec4f86ad1dd7b2862474a368d4ac31911a2b718 -8e2081cfd1d062fe3ab4dab01f68062bac802795545fede9a188f6c9f802cb5f884e60dbe866710baadbf55dc77c11a4 -a2f06003b9713e7dd5929501ed485436b49d43de80ea5b15170763fd6346badf8da6de8261828913ee0dacd8ff23c0e1 -98eecc34b838e6ffd1931ca65eec27bcdb2fdcb61f33e7e5673a93028c5865e0d1bf6d3bec040c5e96f9bd08089a53a4 -88cc16019741b341060b95498747db4377100d2a5bf0a5f516f7dec71b62bcb6e779de2c269c946d39040e03b3ae12b7 -ad1135ccbc3019d5b2faf59a688eef2500697642be8cfbdf211a1ab59abcc1f24483e50d653b55ff1834675ac7b4978f -a946f05ed9972f71dfde0020bbb086020fa35b482cce8a4cc36dd94355b2d10497d7f2580541bb3e81b71ac8bba3c49f -a83aeed488f9a19d8cfd743aa9aa1982ab3723560b1cd337fc2f91ad82f07afa412b3993afb845f68d47e91ba4869840 -95eebe006bfc316810cb71da919e5d62c2cebb4ac99d8e8ef67be420302320465f8b69873470982de13a7c2e23516be9 -a55f8961295a11e91d1e5deadc0c06c15dacbfc67f04ccba1d069cba89d72aa3b3d64045579c3ea8991b150ac29366ae -b321991d12f6ac07a5de3c492841d1a27b0d3446082fbce93e7e1f9e8d8fe3b45d41253556261c21b70f5e189e1a7a6f -a0b0822f15f652ce7962a4f130104b97bf9529797c13d6bd8e24701c213cc37f18157bd07f3d0f3eae6b7cd1cb40401f -96e2fa4da378aa782cc2d5e6e465fc9e49b5c805ed01d560e9b98abb5c0de8b74a2e7bec3aa5e2887d25cccb12c66f0c -97e4ab610d414f9210ed6f35300285eb3ccff5b0b6a95ed33425100d7725e159708ea78704497624ca0a2dcabce3a2f9 -960a375b17bdb325761e01e88a3ea57026b2393e1d887b34b8fa5d2532928079ce88dc9fd06a728b26d2bb41b12b9032 -8328a1647398e832aadc05bd717487a2b6fcdaa0d4850d2c4da230c6a2ed44c3e78ec4837b6094f3813f1ee99414713f -aa283834ebd18e6c99229ce4b401eda83f01d904f250fedd4e24f1006f8fa0712a6a89a7296a9bf2ce8de30e28d1408e -b29e097f2caadae3e0f0ae3473c072b0cd0206cf6d2e9b22c1a5ad3e07d433e32bd09ed1f4e4276a2da4268633357b7f -9539c5cbba14538b2fe077ecf67694ef240da5249950baaabea0340718b882a966f66d97f08556b08a4320ceb2cc2629 -b4529f25e9b42ae8cf8338d2eface6ba5cd4b4d8da73af502d081388135c654c0b3afb3aa779ffc80b8c4c8f4425dd2b -95be0739c4330619fbe7ee2249c133c91d6c07eab846c18c5d6c85fc21ac5528c5d56dcb0145af68ed0c6a79f68f2ccd -ac0c83ea802227bfc23814a24655c9ff13f729619bcffdb487ccbbf029b8eaee709f8bddb98232ef33cd70e30e45ca47 -b503becb90acc93b1901e939059f93e671900ca52c6f64ae701d11ac891d3a050b505d89324ce267bc43ab8275da6ffe -98e3811b55b1bacb70aa409100abb1b870f67e6d059475d9f278c751b6e1e2e2d6f2e586c81a9fb6597fda06e7923274 -b0b0f61a44053fa6c715dbb0731e35d48dba257d134f851ee1b81fd49a5c51a90ebf5459ec6e489fce25da4f184fbdb1 -b1d2117fe811720bb997c7c93fe9e4260dc50fca8881b245b5e34f724aaf37ed970cdad4e8fcb68e05ac8cf55a274a53 -a10f502051968f14b02895393271776dee7a06db9de14effa0b3471825ba94c3f805302bdddac4d397d08456f620999d -a3dbad2ef060ae0bb7b02eaa4a13594f3f900450faa1854fc09620b01ac94ab896321dfb1157cf2374c27e5718e8026a -b550fdec503195ecb9e079dcdf0cad559d64d3c30818ef369b4907e813e689da316a74ad2422e391b4a8c2a2bef25fc0 -a25ba865e2ac8f28186cea497294c8649a201732ecb4620c4e77b8e887403119910423df061117e5f03fc5ba39042db1 -b3f88174e03fdb443dd6addd01303cf88a4369352520187c739fc5ae6b22fa99629c63c985b4383219dab6acc5f6f532 -97a7503248e31e81b10eb621ba8f5210c537ad11b539c96dfb7cf72b846c7fe81bd7532c5136095652a9618000b7f8d3 -a8bcdc1ce5aa8bfa683a2fc65c1e79de8ff5446695dcb8620f7350c26d2972a23da22889f9e2b1cacb3f688c6a2953dc -8458c111df2a37f5dd91a9bee6c6f4b79f4f161c93fe78075b24a35f9817da8dde71763218d627917a9f1f0c4709c1ed -ac5f061a0541152b876cbc10640f26f1cc923c9d4ae1b6621e4bb3bf2cec59bbf87363a4eb72fb0e5b6d4e1c269b52d5 -a9a25ca87006e8a9203cbb78a93f50a36694aa4aad468b8d80d3feff9194455ca559fcc63838128a0ab75ad78c07c13a -a450b85f5dfffa8b34dfd8bc985f921318efacf8857cf7948f93884ba09fb831482ee90a44224b1a41e859e19b74962f -8ed91e7f92f5c6d7a71708b6132f157ac226ecaf8662af7d7468a4fa25627302efe31e4620ad28719318923e3a59bf82 -ab524165fd4c71b1fd395467a14272bd2b568592deafa039d8492e9ef36c6d3f96927c95c72d410a768dc0b6d1fbbc9b -b662144505aa8432c75ffb8d10318526b6d5777ac7af9ebfad87d9b0866c364f7905a6352743bd8fd79ffd9d5dd4f3e6 -a48f1677550a5cd40663bb3ba8f84caaf8454f332d0ceb1d94dbea52d0412fe69c94997f7749929712fd3995298572f7 -8391cd6e2f6b0c242de1117a612be99776c3dc95cb800b187685ea5bf7e2722275eddb79fd7dfc8be8e389c4524cdf70 -875d3acb9af47833b72900bc0a2448999d638f153c5e97e8a14ec02d0c76f6264353a7e275e1f1a5855daced523d243b -91f1823657d30b59b2f627880a9a9cb530f5aca28a9fd217fe6f2f5133690dfe7ad5a897872e400512db2e788b3f7628 -ad3564332aa56cea84123fc7ca79ea70bb4fef2009fa131cb44e4b15e8613bd11ca1d83b9d9bf456e4b7fee9f2e8b017 -8c530b84001936d5ab366c84c0b105241a26d1fb163669f17c8f2e94776895c2870edf3e1bc8ccd04d5e65531471f695 -932d01fa174fdb0c366f1230cffde2571cc47485f37f23ba5a1825532190cc3b722aeb1f15aed62cf83ccae9403ba713 -88b28c20585aca50d10752e84b901b5c2d58efef5131479fbbe53de7bce2029e1423a494c0298e1497669bd55be97a5d -b914148ca717721144ebb3d3bf3fcea2cd44c30c5f7051b89d8001502f3856fef30ec167174d5b76265b55d70f8716b5 -81d0173821c6ddd2a068d70766d9103d1ee961c475156e0cbd67d54e668a796310474ef698c7ab55abe6f2cf76c14679 -8f28e8d78e2fe7fa66340c53718e0db4b84823c8cfb159c76eac032a62fb53da0a5d7e24ca656cf9d2a890cb2a216542 -8a26360335c73d1ab51cec3166c3cf23b9ea51e44a0ad631b0b0329ef55aaae555420348a544e18d5760969281759b61 -94f326a32ed287545b0515be9e08149eb0a565025074796d72387cc3a237e87979776410d78339e23ef3172ca43b2544 -a785d2961a2fa5e70bffa137858a92c48fe749fee91b02599a252b0cd50d311991a08efd7fa5e96b78d07e6e66ffe746 -94af9030b5ac792dd1ce517eaadcec1482206848bea4e09e55cc7f40fd64d4c2b3e9197027c5636b70d6122c51d2235d -9722869f7d1a3992850fe7be405ec93aa17dc4d35e9e257d2e469f46d2c5a59dbd504056c85ab83d541ad8c13e8bcd54 -b13c4088b61a06e2c03ac9813a75ff1f68ffdfee9df6a8f65095179a475e29cc49119cad2ce05862c3b1ac217f3aace9 -8c64d51774753623666b10ca1b0fe63ae42f82ed6aa26b81dc1d48c86937c5772eb1402624c52a154b86031854e1fb9f -b47e4df18002b7dac3fee945bf9c0503159e1b8aafcce2138818e140753011b6d09ef1b20894e08ba3006b093559061b -93cb5970076522c5a0483693f6a35ffd4ea2aa7aaf3730c4eccd6af6d1bebfc1122fc4c67d53898ae13eb6db647be7e2 -a68873ef80986795ea5ed1a597d1cd99ed978ec25e0abb57fdcc96e89ef0f50aeb779ff46e3dce21dc83ada3157a8498 -8cab67f50949cc8eee6710e27358aea373aae3c92849f8f0b5531c080a6300cdf2c2094fe6fecfef6148de0d28446919 -993e932bcb616dbaa7ad18a4439e0565211d31071ef1b85a0627db74a05d978c60d507695eaeea5c7bd9868a21d06923 -acdadff26e3132d9478a818ef770e9fa0d2b56c6f5f48bd3bd674436ccce9bdfc34db884a73a30c04c5f5e9764cb2218 -a0d3e64c9c71f84c0eef9d7a9cb4fa184224b969db5514d678e93e00f98b41595588ca802643ea225512a4a272f5f534 -91c9140c9e1ba6e330cb08f6b2ce4809cd0d5a0f0516f70032bf30e912b0ed684d07b413b326ab531ee7e5b4668c799b -87bc2ee7a0c21ba8334cd098e35cb703f9af57f35e091b8151b9b63c3a5b0f89bd7701dbd44f644ea475901fa6d9ef08 -9325ccbf64bf5d71b303e31ee85d486298f9802c5e55b2c3d75427097bf8f60fa2ab4fcaffa9b60bf922c3e24fbd4b19 -95d0506e898318f3dc8d28d16dfd9f0038b54798838b3c9be2a2ae3c2bf204eb496166353fc042220b0bd4f6673b9285 -811de529416331fe9c416726d45df9434c29dcd7e949045eb15740f47e97dde8f31489242200e19922cac2a8b7c6fd1f -ade632d04a4c8bbab6ca7df370b2213cb9225023e7973f0e29f4f5e52e8aeaabc65171306bbdd12a67b195dfbb96d48f -88b7f029e079b6ae956042c0ea75d53088c5d0efd750dd018adaeacf46be21bf990897c58578c491f41afd3978d08073 -91f477802de507ffd2be3f4319903119225b277ad24f74eb50f28b66c14d32fae53c7edb8c7590704741af7f7f3e3654 -809838b32bb4f4d0237e98108320d4b079ee16ed80c567e7548bd37e4d7915b1192880f4812ac0e00476d246aec1dbc8 -84183b5fc4a7997a8ae5afedb4d21dce69c480d5966b5cbdafd6dd10d29a9a6377f3b90ce44da0eb8b176ac3af0253bb -8508abbf6d3739a16b9165caf0f95afb3b3ac1b8c38d6d374cf0c91296e2c1809a99772492b539cda184510bce8a0271 -8722054e59bab2062e6419a6e45fc803af77fde912ef2cd23055ad0484963de65a816a2debe1693d93c18218d2b8e81a -8e895f80e485a7c4f56827bf53d34b956281cdc74856c21eb3b51f6288c01cc3d08565a11cc6f3e2604775885490e8c5 -afc92714771b7aa6e60f3aee12efd9c2595e9659797452f0c1e99519f67c8bc3ac567119c1ddfe82a3e961ee9defea9a -818ff0fd9cefd32db87b259e5fa32967201016fc02ef44116cdca3c63ce5e637756f60477a408709928444a8ad69c471 -8251e29af4c61ae806fc5d032347fb332a94d472038149225298389495139ce5678fae739d02dfe53a231598a992e728 -a0ea39574b26643f6f1f48f99f276a8a64b5481989cfb2936f9432a3f8ef5075abfe5c067dc5512143ce8bf933984097 -af67a73911b372bf04e57e21f289fc6c3dfac366c6a01409b6e76fea4769bdb07a6940e52e8d7d3078f235c6d2f632c6 -b5291484ef336024dd2b9b4cf4d3a6b751133a40656d0a0825bcc6d41c21b1c79cb50b0e8f4693f90c29c8f4358641f9 -8bc0d9754d70f2cb9c63f991902165a87c6535a763d5eece43143b5064ae0bcdce7c7a8f398f2c1c29167b2d5a3e6867 -8d7faff53579ec8f6c92f661c399614cc35276971752ce0623270f88be937c414eddcb0997e14724a783905a026c8883 -9310b5f6e675fdf60796f814dbaa5a6e7e9029a61c395761e330d9348a7efab992e4e115c8be3a43d08e90d21290c892 -b5eb4f3eb646038ad2a020f0a42202532d4932e766da82b2c1002bf9c9c2e5336b54c8c0ffcc0e02d19dde2e6a35b6cc -91dabfd30a66710f1f37a891136c9be1e23af4abf8cb751f512a40c022a35f8e0a4fb05b17ec36d4208de02d56f0d53a -b3ded14e82d62ac7a5a036122a62f00ff8308498f3feae57d861babaff5a6628d43f0a0c5fc903f10936bcf4e2758ceb -a88e8348fed2b26acca6784d19ef27c75963450d99651d11a950ea81d4b93acd2c43e0ecce100eaf7e78508263d5baf3 -b1f5bbf7c4756877b87bb42163ac570e08c6667c4528bf68b5976680e19beeff7c5effd17009b0718797077e2955457a -ad2e7b516243f915d4d1415326e98b1a7390ae88897d0b03b66c2d9bd8c3fba283d7e8fe44ed3333296a736454cef6d8 -8f82eae096d5b11f995de6724a9af895f5e1c58d593845ad16ce8fcae8507e0d8e2b2348a0f50a1f66a17fd6fac51a5c -890e4404d0657c6c1ee14e1aac132ecf7a568bb3e04137b85ac0f84f1d333bd94993e8750f88eee033a33fb00f85dcc7 -82ac7d3385e035115f1d39a99fc73e5919de44f5e6424579776d118d711c8120b8e5916372c6f27bed4cc64cac170b6c -85ee16d8901c272cfbbe966e724b7a891c1bd5e68efd5d863043ad8520fc409080af61fd726adc680b3f1186fe0ac8b8 -86dc564c9b545567483b43a38f24c41c6551a49cabeebb58ce86404662a12dbfafd0778d30d26e1c93ce222e547e3898 -a29f5b4522db26d88f5f95f18d459f8feefab02e380c2edb65aa0617a82a3c1a89474727a951cef5f15050bcf7b380fb -a1ce039c8f6cac53352899edb0e3a72c76da143564ad1a44858bd7ee88552e2fe6858d1593bbd74aeee5a6f8034b9b9d -97f10d77983f088286bd7ef3e7fdd8fa275a56bec19919adf33cf939a90c8f2967d2b1b6fc51195cb45ad561202a3ed7 -a25e2772e8c911aaf8712bdac1dd40ee061c84d3d224c466cfaae8e5c99604053f940cde259bd1c3b8b69595781dbfec -b31bb95a0388595149409c48781174c340960d59032ab2b47689911d03c68f77a2273576fbe0c2bf4553e330656058c7 -b8b2e9287ad803fb185a13f0d7456b397d4e3c8ad5078f57f49e8beb2e85f661356a3392dbd7bcf6a900baa5582b86a1 -a3d0893923455eb6e96cc414341cac33d2dbc88fba821ac672708cce131761d85a0e08286663a32828244febfcae6451 -82310cb42f647d99a136014a9f881eb0b9791efd2e01fc1841907ad3fc8a9654d3d1dab6689c3607214b4dc2aca01cee -874022d99c16f60c22de1b094532a0bc6d4de700ad01a31798fac1d5088b9a42ad02bef8a7339af7ed9c0d4f16b186ee -94981369e120265aed40910eebc37eded481e90f4596b8d57c3bec790ab7f929784bd33ddd05b7870aad6c02e869603b -a4f1f50e1e2a73f07095e0dd31cb45154f24968dae967e38962341c1241bcd473102fff1ff668b20c6547e9732d11701 -ae2328f3b0ad79fcda807e69a1b5278145225083f150f67511dafc97e079f860c3392675f1752ae7e864c056e592205b -875d8c971e593ca79552c43d55c8c73b17cd20c81ff2c2fed1eb19b1b91e4a3a83d32df150dbfd5db1092d0aebde1e1f -add2e80aa46aae95da73a11f130f4bda339db028e24c9b11e5316e75ba5e63bc991d2a1da172c7c8e8fee038baae3433 -b46dbe1cb3424002aa7de51e82f600852248e251465c440695d52538d3f36828ff46c90ed77fc1d11534fe3c487df8ef -a5e5045d28b4e83d0055863c30c056628c58d4657e6176fd0536f5933f723d60e851bb726d5bf3c546b8ce4ac4a57ef8 -91fec01e86dd1537e498fff7536ea3ca012058b145f29d9ada49370cd7b7193ac380e116989515df1b94b74a55c45df3 -a7428176d6918cd916a310bdc75483c72de660df48cac4e6e7478eef03205f1827ea55afc0df5d5fa7567d14bbea7fc9 -851d89bef45d9761fe5fdb62972209335193610015e16a675149519f9911373bac0919add226ef118d9f3669cfdf4734 -b74acf5c149d0042021cb2422ea022be4c4f72a77855f42393e71ffd12ebb3eec16bdf16f812159b67b79a9706e7156d -99f35dce64ec99aa595e7894b55ce7b5a435851b396e79036ffb249c28206087db4c85379df666c4d95857db02e21ff9 -b6b9a384f70db9e298415b8ab394ee625dafff04be2886476e59df8d052ca832d11ac68a9b93fba7ab055b7bc36948a4 -898ee4aefa923ffec9e79f2219c7389663eb11eb5b49014e04ed4a336399f6ea1691051d86991f4c46ca65bcd4fdf359 -b0f948217b0d65df7599a0ba4654a5e43c84db477936276e6f11c8981efc6eaf14c90d3650107ed4c09af4cc8ec11137 -aa6286e27ac54f73e63dbf6f41865dd94d24bc0cf732262fcaff67319d162bb43af909f6f8ee27b1971939cfbba08141 -8bca7cdf730cf56c7b2c8a2c4879d61361a6e1dba5a3681a1a16c17a56e168ace0e99cf0d15826a1f5e67e6b8a8a049a -a746d876e8b1ce225fcafca603b099b36504846961526589af977a88c60d31ba2cc56e66a3dec8a77b3f3531bf7524c9 -a11e2e1927e6704cdb8874c75e4f1842cef84d7d43d7a38e339e61dc8ba90e61bbb20dd3c12e0b11d2471d58eed245be -a36395e22bc1d1ba8b0459a235203177737397da5643ce54ded3459d0869ff6d8d89f50c73cb62394bf66a959cde9b90 -8b49f12ba2fdf9aca7e5f81d45c07d47f9302a2655610e7634d1e4bd16048381a45ef2c95a8dd5b0715e4b7cf42273af -91cffa2a17e64eb7f76bccbe4e87280ee1dd244e04a3c9eac12e15d2d04845d876eb24fe2ec6d6d266cce9efb281077f -a6b8afabf65f2dee01788114e33a2f3ce25376fb47a50b74da7c3c25ff1fdc8aa9f41307534abbf48acb6f7466068f69 -8d13db896ccfea403bd6441191995c1a65365cab7d0b97fbe9526da3f45a877bd1f4ef2edef160e8a56838cd1586330e -98c717de9e01bef8842c162a5e757fe8552d53269c84862f4d451e7c656ae6f2ae473767b04290b134773f63be6fdb9d -8c2036ace1920bd13cf018e82848c49eb511fad65fd0ff51f4e4b50cf3bfc294afb63cba682c16f52fb595a98fa84970 -a3520fdff05dbad9e12551b0896922e375f9e5589368bcb2cc303bde252743b74460cb5caf99629325d3620f13adc796 -8d4f83a5bfec05caf5910e0ce538ee9816ee18d0bd44c1d0da2a87715a23cd2733ad4d47552c6dc0eb397687d611dd19 -a7b39a0a6a02823452d376533f39d35029867b3c9a6ad6bca181f18c54132d675613a700f9db2440fb1b4fa13c8bf18a -80bcb114b2544b80f404a200fc36860ed5e1ad31fe551acd4661d09730c452831751baa9b19d7d311600d267086a70bc -90dcce03c6f88fc2b08f2b42771eedde90cc5330fe0336e46c1a7d1b5a6c1641e5fcc4e7b3d5db00bd8afca9ec66ed81 -aec15f40805065c98e2965b1ae12a6c9020cfdb094c2d0549acfc7ea2401a5fb48d3ea7d41133cf37c4e096e7ff53eb9 -80e129b735dba49fa627a615d6c273119acec8e219b2f2c4373a332b5f98d66cbbdd688dfbe72a8f8bfefaccc02c50c1 -a9b596da3bdfe23e6799ece5f7975bf7a1979a75f4f546deeaf8b34dfe3e0d623217cb4cf4ccd504cfa3625b88cd53f1 -abcbbb70b16f6e517c0ab4363ab76b46e4ff58576b5f8340e5c0e8cc0e02621b6e23d742d73b015822a238b17cfd7665 -a046937cc6ea6a2e1adae543353a9fe929c1ae4ad655be1cc051378482cf88b041e28b1e9a577e6ccff2d3570f55e200 -831279437282f315e65a60184ef158f0a3dddc15a648dc552bdc88b3e6fe8288d3cfe9f0031846d81350f5e7874b4b33 -993d7916fa213c6d66e7c4cafafc1eaec9a2a86981f91c31eb8a69c5df076c789cbf498a24c84e0ee77af95b42145026 -823907a3b6719f8d49b3a4b7c181bd9bb29fcf842d7c70660c4f351852a1e197ca46cf5e879b47fa55f616fa2b87ce5e -8d228244e26132b234930ee14c75d88df0943cdb9c276a8faf167d259b7efc1beec2a87c112a6c608ad1600a239e9aae -ab6e55766e5bfb0cf0764ed909a8473ab5047d3388b4f46faeba2d1425c4754c55c6daf6ad4751e634c618b53e549529 -ab0cab6860e55a84c5ad2948a7e0989e2b4b1fd637605634b118361497332df32d9549cb854b2327ca54f2bcb85eed8f -b086b349ae03ef34f4b25a57bcaa5d1b29bd94f9ebf87e22be475adfe475c51a1230c1ebe13506cb72c4186192451658 -8a0b49d8a254ca6d91500f449cbbfbb69bb516c6948ac06808c65595e46773e346f97a5ce0ef7e5a5e0de278af22709c -ac49de11edaaf04302c73c578cc0824bdd165c0d6321be1c421c1950e68e4f3589aa3995448c9699e93c6ebae8803e27 -884f02d841cb5d8f4c60d1402469216b114ab4e93550b5bc1431756e365c4f870a9853449285384a6fa49e12ce6dc654 -b75f3a28fa2cc8d36b49130cb7448a23d73a7311d0185ba803ad55c8219741d451c110f48b786e96c728bc525903a54f -80ae04dbd41f4a35e33f9de413b6ad518af0919e5a30cb0fa1b061b260420780bb674f828d37fd3b52b5a31673cbd803 -b9a8011eb5fcea766907029bf743b45262db3e49d24f84503687e838651ed11cb64c66281e20a0ae9f6aa51acc552263 -90bfdd75e2dc9cf013e22a5d55d2d2b8a754c96103a17524488e01206e67f8b6d52b1be8c4e3d5307d4fe06d0e51f54c -b4af353a19b06203a815ec43e79a88578cc678c46f5a954b85bc5c53b84059dddba731f3d463c23bfd5273885c7c56a4 -aa125e96d4553b64f7140e5453ff5d2330318b69d74d37d283e84c26ad672fa00e3f71e530eb7e28be1e94afb9c4612e -a18e060aee3d49cde2389b10888696436bb7949a79ca7d728be6456a356ea5541b55492b2138da90108bd1ce0e6f5524 -93e55f92bdbccc2de655d14b1526836ea2e52dba65eb3f87823dd458a4cb5079bf22ce6ef625cb6d6bfdd0995ab9a874 -89f5a683526b90c1c3ceebbb8dc824b21cff851ce3531b164f6626e326d98b27d3e1d50982e507d84a99b1e04e86a915 -83d1c38800361633a3f742b1cb2bfc528129496e80232611682ddbe403e92c2ac5373aea0bca93ecb5128b0b2b7a719e -8ecba560ac94905e19ce8d9c7af217bf0a145d8c8bd38e2db82f5e94cc3f2f26f55819176376b51f154b4aab22056059 -a7e2a4a002b60291924850642e703232994acb4cfb90f07c94d1e0ecd2257bb583443283c20fc6017c37e6bfe85b7366 -93ed7316fa50b528f1636fc6507683a672f4f4403e55e94663f91221cc198199595bd02eef43d609f451acc9d9b36a24 -a1220a8ebc5c50ceed76a74bc3b7e0aa77f6884c71b64b67c4310ac29ce5526cb8992d6abc13ef6c8413ce62486a6795 -b2f6eac5c869ad7f4a25161d3347093e2f70e66cd925032747e901189355022fab3038bca4d610d2f68feb7e719c110b -b703fa11a4d511ca01c7462979a94acb40b5d933759199af42670eb48f83df202fa0c943f6ab3b4e1cc54673ea3aab1e -b5422912afbfcb901f84791b04f1ddb3c3fbdc76d961ee2a00c5c320e06d3cc5b5909c3bb805df66c5f10c47a292b13d -ad0934368da823302e1ac08e3ede74b05dfdbfffca203e97ffb0282c226814b65c142e6e15ec1e754518f221f01b30f7 -a1dd302a02e37df15bf2f1147efe0e3c06933a5a767d2d030e1132f5c3ce6b98e216b6145eb39e1e2f74e76a83165b8d -a346aab07564432f802ae44738049a36f7ca4056df2d8f110dbe7fef4a3e047684dea609b2d03dc6bf917c9c2a47608f -b96c5f682a5f5d02123568e50f5d0d186e4b2c4c9b956ec7aabac1b3e4a766d78d19bd111adb5176b898e916e49be2aa -8a96676d56876fc85538db2e806e1cba20fd01aeb9fa3cb43ca6ca94a2c102639f65660db330e5d74a029bb72d6a0b39 -ab0048336bd5c3def1a4064eadd49e66480c1f2abb4df46e03afbd8a3342c2c9d74ee35d79f08f4768c1646681440984 -888427bdf76caec90814c57ee1c3210a97d107dd88f7256f14f883ad0f392334b82be11e36dd8bfec2b37935177c7831 -b622b282becf0094a1916fa658429a5292ba30fb48a4c8066ce1ddcefb71037948262a01c95bab6929ed3a76ba5db9fe -b5b9e005c1f456b6a368a3097634fb455723abe95433a186e8278dceb79d4ca2fbe21f8002e80027b3c531e5bf494629 -a3c6707117a1e48697ed41062897f55d8119403eea6c2ee88f60180f6526f45172664bfee96bf61d6ec0b7fbae6aa058 -b02a9567386a4fbbdb772d8a27057b0be210447348efe6feb935ceec81f361ed2c0c211e54787dc617cdffed6b4a6652 -a9b8364e40ef15c3b5902e5534998997b8493064fa2bea99600def58279bb0f64574c09ba11e9f6f669a8354dd79dc85 -9998a2e553a9aa9a206518fae2bc8b90329ee59ab23005b10972712389f2ec0ee746033c733092ffe43d73d33abbb8ef -843a4b34d9039bf79df96d79f2d15e8d755affb4d83d61872daf540b68c0a3888cf8fc00d5b8b247b38524bcb3b5a856 -84f7128920c1b0bb40eee95701d30e6fc3a83b7bb3709f16d97e72acbb6057004ee7ac8e8f575936ca9dcb7866ab45f7 -918d3e2222e10e05edb34728162a899ad5ada0aaa491aeb7c81572a9c0d506e31d5390e1803a91ff3bd8e2bb15d47f31 -9442d18e2489613a7d47bb1cb803c8d6f3259d088cd079460976d87f7905ee07dea8f371b2537f6e1d792d36d7e42723 -b491976970fe091995b2ed86d629126523ccf3e9daf8145302faca71b5a71a5da92e0e05b62d7139d3efac5c4e367584 -aa628006235dc77c14cef4c04a308d66b07ac92d377df3de1a2e6ecfe3144f2219ad6d7795e671e1cb37a3641910b940 -99d386adaea5d4981d7306feecac9a555b74ffdc218c907c5aa7ac04abaead0ec2a8237300d42a3fbc464673e417ceed -8f78e8b1556f9d739648ea3cab9606f8328b52877fe72f9305545a73b74d49884044ba9c1f1c6db7d9b7c7b7c661caba -8fb357ae49932d0babdf74fc7aa7464a65d3b6a2b3acf4f550b99601d3c0215900cfd67f2b6651ef94cfc323bac79fae -9906f2fa25c0290775aa001fb6198113d53804262454ae8b83ef371b5271bde189c0460a645829cb6c59f9ee3a55ce4d -8f4379b3ebb50e052325b27655ca6a82e6f00b87bf0d2b680d205dd2c7afdc9ff32a9047ae71a1cdf0d0ce6b9474d878 -a85534e88c2bd43c043792eaa75e50914b21741a566635e0e107ae857aed0412035f7576cf04488ade16fd3f35fdbb87 -b4ce93199966d3c23251ca7f28ec5af7efea1763d376b0385352ffb2e0a462ef95c69940950278cf0e3dafd638b7bd36 -b10cb3d0317dd570aa73129f4acf63c256816f007607c19b423fb42f65133ce21f2f517e0afb41a5378cccf893ae14d0 -a9b231c9f739f7f914e5d943ed9bff7eba9e2c333fbd7c34eb1648a362ee01a01af6e2f7c35c9fe962b11152cddf35de -99ff6a899e156732937fb81c0cced80ae13d2d44c40ba99ac183aa246103b31ec084594b1b7feb96da58f4be2dd5c0ed -8748d15d18b75ff2596f50d6a9c4ce82f61ecbcee123a6ceae0e43cab3012a29b6f83cf67b48c22f6f9d757c6caf76b2 -b88ab05e4248b7fb634cf640a4e6a945d13e331237410f7217d3d17e3e384ddd48897e7a91e4516f1b9cbd30f35f238b -8d826deaeeb84a3b2d2c04c2300ca592501f992810582d6ae993e0d52f6283a839dba66c6c72278cff5871802b71173b -b36fed027c2f05a5ef625ca00b0364b930901e9e4420975b111858d0941f60e205546474bb25d6bfa6928d37305ae95f -af2fcfc6b87967567e8b8a13a4ed914478185705724e56ce68fb2df6d1576a0cf34a61e880997a0d35dc2c3276ff7501 -ac351b919cd1fbf106feb8af2c67692bfcddc84762d18cea681cfa7470a5644839caace27efee5f38c87d3df306f4211 -8d6665fb1d4d8d1fa23bd9b8a86e043b8555663519caac214d1e3e3effbc6bee7f2bcf21e645f77de0ced279d69a8a8b -a9fc1c2061756b2a1a169c1b149f212ff7f0d2488acd1c5a0197eba793cffa593fc6d1d1b40718aa75ca3ec77eff10e1 -aff64f0fa009c7a6cf0b8d7a22ddb2c8170c3cb3eec082e60d5aadb00b0040443be8936d728d99581e33c22178c41c87 -82e0b181adc5e3b1c87ff8598447260e839d53debfae941ebea38265575546c3a74a14b4325a030833a62ff6c52d9365 -b7ad43cbb22f6f892c2a1548a41dc120ab1f4e1b8dea0cb6272dd9cb02054c542ecabc582f7e16de709d48f5166cae86 -985e0c61094281532c4afb788ecb2dfcba998e974b5d4257a22040a161883908cdd068fe80f8eb49b8953cfd11acf43a -ae46895c6d67ea6d469b6c9c07b9e5d295d9ae73b22e30da4ba2c973ba83a130d7eef39717ec9d0f36e81d56bf742671 -8600177ea1f7e7ef90514b38b219a37dedfc39cb83297e4c7a5b479817ef56479d48cf6314820960c751183f6edf8b0e -b9208ec1c1d7a1e99b59c62d3e4e61dfb706b0e940d09d3abfc3454c19749083260614d89cfd7e822596c3cdbcc6bb95 -a1e94042c796c2b48bc724352d2e9f3a22291d9a34705993357ddb6adabd76da6fc25dac200a8cb0b5bbd99ecddb7af6 -b29c3adedd0bcad8a930625bc4dfdc3552a9afd5ca6dd9c0d758f978068c7982b50b711aa0eb5b97f2b84ee784637835 -af0632a238bb1f413c7ea8e9b4c3d68f2827bd2e38cd56024391fba6446ac5d19a780d0cfd4a78fe497d537b766a591a -aaf6e7f7d54f8ef5e2e45dd59774ecbeecf8683aa70483b2a75be6a6071b5981bbaf1627512a65d212817acdfab2e428 -8c751496065da2e927cf492aa5ca9013b24f861d5e6c24b30bbf52ec5aaf1905f40f9a28175faef283dd4ed4f2182a09 -8952377d8e80a85cf67d6b45499f3bad5fd452ea7bcd99efc1b066c4720d8e5bff1214cea90fd1f972a7f0baac3d29be -a1946ee543d1a6e21f380453be4d446e4130950c5fc3d075794eb8260f6f52d0a795c1ff91d028a648dc1ce7d9ab6b47 -89f3fefe37af31e0c17533d2ca1ce0884cc1dc97c15cbfab9c331b8debd94781c9396abef4bb2f163d09277a08d6adf0 -a2753f1e6e1a154fb117100a5bd9052137add85961f8158830ac20541ab12227d83887d10acf7fd36dcaf7c2596d8d23 -814955b4198933ee11c3883863b06ff98c7eceb21fc3e09df5f916107827ccf3323141983e74b025f46ae00284c9513b -8cc5c6bb429073bfef47cae7b3bfccb0ffa076514d91a1862c6bda4d581e0df87db53cc6c130bf8a7826304960f5a34e -909f22c1f1cdc87f7be7439c831a73484a49acbf8f23d47087d7cf867c64ef61da3bde85dc57d705682b4c3fc710d36e -8048fee7f276fcd504aed91284f28e73693615e0eb3858fa44bcf79d7285a9001c373b3ef71d9a3054817ba293ebe28c -94400e5cf5d2700ca608c5fe35ce14623f71cc24959f2bc27ca3684092850f76b67fb1f07ca9e5b2ca3062cf8ad17bd4 -81c2ae7d4d1b17f8b6de6a0430acc0d58260993980fe48dc2129c4948269cdc74f9dbfbf9c26b19360823fd913083d48 -8c41fe765128e63f6889d6a979f6a4342300327c8b245a8cfe3ecfbcac1e09c3da30e2a1045b24b78efc6d6d50c8c6ac -a5dd4ae51ae48c8be4b218c312ade226cffce671cf121cb77810f6c0990768d6dd767badecb5c69921d5574d5e8433d3 -b7642e325f4ba97ae2a39c1c9d97b35aafd49d53dba36aed3f3cb0ca816480b3394079f46a48252d46596559c90f4d58 -ae87375b40f35519e7bd4b1b2f73cd0b329b0c2cb9d616629342a71c6c304338445eda069b78ea0fbe44087f3de91e09 -b08918cb6f736855e11d3daca1ddfbdd61c9589b203b5493143227bf48e2c77c2e8c94b0d1aa2fab2226e0eae83f2681 -ac36b84a4ac2ebd4d6591923a449c564e3be8a664c46092c09e875c2998eba16b5d32bfd0882fd3851762868e669f0b1 -a44800a3bb192066fa17a3f29029a23697240467053b5aa49b9839fb9b9b8b12bcdcbfc557f024b61f4f51a9aacdefcb -9064c688fec23441a274cdf2075e5a449caf5c7363cc5e8a5dc9747183d2e00a0c69f2e6b3f6a7057079c46014c93b3b -aa367b021469af9f5b764a79bb3afbe2d87fe1e51862221672d1a66f954b165778b7c27a705e0f93841fab4c8468344d -a1a8bfc593d4ab71f91640bc824de5c1380ab2591cfdafcbc78a14b32de3c0e15f9d1b461d85c504baa3d4232c16bb53 -97df48da1799430f528184d30b6baa90c2a2f88f34cdfb342d715339c5ebd6d019aa693cea7c4993daafc9849063a3aa -abd923831fbb427e06e0dd335253178a9e5791395c84d0ab1433c07c53c1209161097e9582fb8736f8a60bde62d8693e -84cd1a43f1a438b43dc60ffc775f646937c4f6871438163905a3cebf1115f814ccd38a6ccb134130bff226306e412f32 -91426065996b0743c5f689eb3ca68a9f7b9e4d01f6c5a2652b57fa9a03d8dc7cd4bdbdab0ca5a891fee1e97a7f00cf02 -a4bee50249db3df7fd75162b28f04e57c678ba142ce4d3def2bc17bcb29e4670284a45f218dad3969af466c62a903757 -83141ebcc94d4681404e8b67a12a46374fded6df92b506aff3490d875919631408b369823a08b271d006d5b93136f317 -a0ea1c8883d58d5a784da3d8c8a880061adea796d7505c1f903d07c287c5467f71e4563fc0faafbc15b5a5538b0a7559 -89d9d480574f201a87269d26fb114278ed2c446328df431dc3556e3500e80e4cd01fcac196a2459d8646361ebda840df -8bf302978973632dd464bec819bdb91304712a3ec859be071e662040620422c6e75eba6f864f764cffa2799272efec39 -922f666bc0fd58b6d7d815c0ae4f66d193d32fc8382c631037f59eeaeae9a8ca6c72d08e72944cf9e800b8d639094e77 -81ad8714f491cdff7fe4399f2eb20e32650cff2999dd45b9b3d996d54a4aba24cc6c451212e78c9e5550368a1a38fb3f -b58fcf4659d73edb73175bd9139d18254e94c3e32031b5d4b026f2ed37aa19dca17ec2eb54c14340231615277a9d347e -b365ac9c2bfe409b710928c646ea2fb15b28557e0f089d39878e365589b9d1c34baf5566d20bb28b33bb60fa133f6eff -8fcae1d75b53ab470be805f39630d204853ca1629a14158bac2f52632277d77458dec204ff84b7b2d77e641c2045be65 -a03efa6bebe84f4f958a56e2d76b5ba4f95dd9ed7eb479edc7cc5e646c8d4792e5b0dfc66cc86aa4b4afe2f7a4850760 -af1c823930a3638975fb0cc5c59651771b2719119c3cd08404fbd4ce77a74d708cefbe3c56ea08c48f5f10e6907f338f -8260c8299b17898032c761c325ac9cabb4c5b7e735de81eacf244f647a45fb385012f4f8df743128888c29aefcaaad16 -ab2f37a573c82e96a8d46198691cd694dfa860615625f477e41f91b879bc58a745784fccd8ffa13065834ffd150d881d -986c746c9b4249352d8e5c629e8d7d05e716b3c7aab5e529ca969dd1e984a14b5be41528baef4c85d2369a42d7209216 -b25e32da1a8adddf2a6080725818b75bc67240728ad1853d90738485d8924ea1e202df0a3034a60ffae6f965ec55cf63 -a266e627afcebcefea6b6b44cbc50f5c508f7187e87d047b0450871c2a030042c9e376f3ede0afcf9d1952f089582f71 -86c3bbca4c0300606071c0a80dbdec21ce1dd4d8d4309648151c420854032dff1241a1677d1cd5de4e4de4385efda986 -b9a21a1fe2d1f3273a8e4a9185abf2ff86448cc98bfa435e3d68306a2b8b4a6a3ea33a155be3cb62a2170a86f77679a5 -b117b1ea381adce87d8b342cba3a15d492ff2d644afa28f22424cb9cbc820d4f7693dfc1a4d1b3697046c300e1c9b4c8 -9004c425a2e68870d6c69b658c344e3aa3a86a8914ee08d72b2f95c2e2d8a4c7bb0c6e7e271460c0e637cec11117bf8e -86a18aa4783b9ebd9131580c8b17994825f27f4ac427b0929a1e0236907732a1c8139e98112c605488ee95f48bbefbfc -84042243b955286482ab6f0b5df4c2d73571ada00716d2f737ca05a0d2e88c6349e8ee9e67934cfee4a1775dbf7f4800 -92c2153a4733a62e4e1d5b60369f3c26777c7d01cd3c8679212660d572bd3bac9b8a8a64e1f10f7dbf5eaa7579c4e423 -918454b6bb8e44a2afa144695ba8d48ae08d0cdfef4ad078f67709eddf3bb31191e8b006f04e82ea45a54715ef4d5817 -acf0b54f6bf34cf6ed6c2b39cf43194a40d68de6bcf1e4b82c34c15a1343e9ac3737885e1a30b78d01fa3a5125463db8 -a7d60dbe4b6a7b054f7afe9ee5cbbfeca0d05dc619e6041fa2296b549322529faddb8a11e949562309aecefb842ac380 -91ffb53e6d7e5f11159eaf13e783d6dbdfdb1698ed1e6dbf3413c6ea23492bbb9e0932230a9e2caac8fe899a17682795 -b6e8d7be5076ee3565d5765a710c5ecf17921dd3cf555c375d01e958a365ae087d4a88da492a5fb81838b7b92bf01143 -a8c6b763de2d4b2ed42102ef64eccfef31e2fb2a8a2776241c82912fa50fc9f77f175b6d109a97ede331307c016a4b1a -99839f86cb700c297c58bc33e28d46b92931961548deac29ba8df91d3e11721b10ea956c8e16984f9e4acf1298a79b37 -8c2e2c338f25ea5c25756b7131cde0d9a2b35abf5d90781180a00fe4b8e64e62590dc63fe10a57fba3a31c76d784eb01 -9687d7df2f41319ca5469d91978fed0565a5f11f829ebadaa83db92b221755f76c6eacd7700735e75c91e257087512e3 -8795fdfb7ff8439c58b9bf58ed53873d2780d3939b902b9ddaaa4c99447224ced9206c3039a23c2c44bcc461e2bb637f -a803697b744d2d087f4e2307218d48fa88620cf25529db9ce71e2e3bbcc65bac5e8bb9be04777ef7bfb5ed1a5b8e6170 -80f3d3efbbb9346ddd413f0a8e36b269eb5d7ff6809d5525ff9a47c4bcab2c01b70018b117f6fe05253775612ff70c6b -9050e0e45bcc83930d4c505af35e5e4d7ca01cd8681cba92eb55821aececcebe32bb692ebe1a4daac4e7472975671067 -8d206812aac42742dbaf233e0c080b3d1b30943b54b60283515da005de05ea5caa90f91fedcfcba72e922f64d7040189 -a2d44faaeb2eff7915c83f32b13ca6f31a6847b1c1ce114ea240bac3595eded89f09b2313b7915ad882292e2b586d5b4 -961776c8576030c39f214ea6e0a3e8b3d32f023d2600958c098c95c8a4e374deeb2b9dc522adfbd6bda5949bdc09e2a2 -993fa7d8447407af0fbcd9e6d77f815fa5233ab00674efbcf74a1f51c37481445ae291cc7b76db7c178f9cb0e570e0fc -abd5b1c78e05f9d7c8cc99bdaef8b0b6a57f2daf0f02bf492bec48ea4a27a8f1e38b5854da96efff11973326ff980f92 -8f15af4764bc275e6ccb892b3a4362cacb4e175b1526a9a99944e692fe6ccb1b4fc19abf312bb2a089cb1f344d91a779 -a09b27ccd71855512aba1d0c30a79ffbe7f6707a55978f3ced50e674b511a79a446dbc6d7946add421ce111135a460af -94b2f98ce86a9271fbd4153e1fc37de48421fe3490fb3840c00f2d5a4d0ba8810c6a32880b002f6374b59e0a7952518b -8650ac644f93bbcb88a6a0f49fee2663297fd4bc6fd47b6a89b9d8038d32370438ab3a4775ec9b58cb10aea8a95ef7b6 -95e5c2f2e84eed88c6980bbba5a1c0bb375d5a628bff006f7516d45bb7d723da676add4fdd45956f312e7bab0f052644 -b3278a3fa377ac93af7cfc9453f8cb594aae04269bbc99d2e0e45472ff4b6a2f97a26c4c57bf675b9d86f5e77a5d55d1 -b4bcbe6eb666a206e2ea2f877912c1d3b5bdbd08a989fc4490eb06013e1a69ad1ba08bcdac048bf29192312be399077b -a76d70b78c99fffcbf9bb9886eab40f1ea4f99a309710b660b64cbf86057cbcb644d243f6e341711bb7ef0fedf0435a7 -b2093c1ee945dca7ac76ad5aed08eae23af31dd5a77c903fd7b6f051f4ab84425d33a03c3d45bf2907bc93c02d1f3ad8 -904b1f7534e053a265b22d20be859912b9c9ccb303af9a8d6f1d8f6ccdc5c53eb4a45a1762b880d8444d9be0cd55e7f9 -8f664a965d65bc730c9ef1ec7467be984d4b8eb46bd9b0d64e38e48f94e6e55dda19aeac82cbcf4e1473440e64c4ca18 -8bcee65c4cc7a7799353d07b114c718a2aae0cd10a3f22b7eead5185d159dafd64852cb63924bf87627d176228878bce -8c78f2e3675096fef7ebaa898d2615cd50d39ca3d8f02b9bdfb07e67da648ae4be3da64838dffc5935fd72962c4b96c7 -8c40afd3701629421fec1df1aac4e849384ef2e80472c0e28d36cb1327acdf2826f99b357f3d7afdbc58a6347fc40b3c -a197813b1c65a8ea5754ef782522a57d63433ef752215ecda1e7da76b0412ee619f58d904abd2e07e0c097048b6ae1dd -a670542629e4333884ad7410f9ea3bd6f988df4a8f8a424ca74b9add2312586900cf9ae8bd50411f9146e82626b4af56 -a19875cc07ab84e569d98b8b67fb1dbbdfb59093c7b748fae008c8904a6fd931a63ca8d03ab5fea9bc8d263568125a9b -b57e7f68e4eb1bd04aafa917b1db1bdab759a02aa8a9cdb1cba34ba8852b5890f655645c9b4e15d5f19bf37e9f2ffe9f -8abe4e2a4f6462b6c64b3f10e45db2a53c2b0d3c5d5443d3f00a453e193df771eda635b098b6c8604ace3557514027af -8459e4fb378189b22b870a6ef20183deb816cefbf66eca1dc7e86d36a2e011537db893729f500dc154f14ce24633ba47 -930851df4bc7913c0d8c0f7bd3b071a83668987ed7c397d3d042fdc0d9765945a39a3bae83da9c88cb6b686ed8aeeb26 -8078c9e5cd05e1a8c932f8a1d835f61a248b6e7133fcbb3de406bf4ffc0e584f6f9f95062740ba6008d98348886cf76b -addff62bb29430983fe578e3709b0949cdc0d47a13a29bc3f50371a2cb5c822ce53e2448cfaa01bcb6e0aa850d5a380e -9433add687b5a1e12066721789b1db2edf9b6558c3bdc0f452ba33b1da67426abe326e9a34d207bfb1c491c18811bde1 -822beda3389963428cccc4a2918fa9a8a51cf0919640350293af70821967108cded5997adae86b33cb917780b097f1ca -a7a9f52bda45e4148ed56dd176df7bd672e9b5ed18888ccdb405f47920fdb0844355f8565cefb17010b38324edd8315f -b35c3a872e18e607b2555c51f9696a17fa18da1f924d503b163b4ec9fe22ed0c110925275cb6c93ce2d013e88f173d6a -adf34b002b2b26ab84fc1bf94e05bd8616a1d06664799ab149363c56a6e0c807fdc473327d25632416e952ea327fcd95 -ae4a6b9d22a4a3183fac29e2551e1124a8ce4a561a9a2afa9b23032b58d444e6155bb2b48f85c7b6d70393274e230db7 -a2ea3be4fc17e9b7ce3110284038d46a09e88a247b6971167a7878d9dcf36925d613c382b400cfa4f37a3ebea3699897 -8e5863786b641ce3140fbfe37124d7ad3925472e924f814ebfc45959aaf3f61dc554a597610b5defaecc85b59a99b50f -aefde3193d0f700d0f515ab2aaa43e2ef1d7831c4f7859f48e52693d57f97fa9e520090f3ed700e1c966f4b76048e57f -841a50f772956622798e5cd208dc7534d4e39eddee30d8ce133383d66e5f267e389254a0cdae01b770ecd0a9ca421929 -8fbc2bfd28238c7d47d4c03b1b910946c0d94274a199575e5b23242619b1de3497784e646a92aa03e3e24123ae4fcaba -926999579c8eec1cc47d7330112586bdca20b4149c8b2d066f527c8b9f609e61ce27feb69db67eea382649c6905efcf9 -b09f31f305efcc65589adf5d3690a76cf339efd67cd43a4e3ced7b839507466e4be72dd91f04e89e4bbef629d46e68c0 -b917361f6b95f759642638e0b1d2b3a29c3bdef0b94faa30de562e6078c7e2d25976159df3edbacbf43614635c2640b4 -8e7e8a1253bbda0e134d62bfe003a2669d471b47bd2b5cde0ff60d385d8e62279d54022f5ac12053b1e2d3aaa6910b4c -b69671a3c64e0a99d90b0ed108ce1912ff8ed983e4bddd75a370e9babde25ee1f5efb59ec707edddd46793207a8b1fe7 -910b2f4ebd37b7ae94108922b233d0920b4aba0bd94202c70f1314418b548d11d8e9caa91f2cd95aff51b9432d122b7f -82f645c90dfb52d195c1020346287c43a80233d3538954548604d09fbab7421241cde8593dbc4acc4986e0ea39a27dd9 -8fee895f0a140d88104ce442fed3966f58ff9d275e7373483f6b4249d64a25fb5374bbdc6bce6b5ab0270c2847066f83 -84f5bd7aab27b2509397aeb86510dd5ac0a53f2c8f73799bf720f2f87a52277f8d6b0f77f17bc80739c6a7119b7eb062 -9903ceced81099d7e146e661bcf01cbaccab5ba54366b85e2177f07e2d8621e19d9c9c3eee14b9266de6b3f9b6ea75ae -b9c16ea2a07afa32dd6c7c06df0dec39bca2067a9339e45475c98917f47e2320f6f235da353fd5e15b477de97ddc68dd -9820a9bbf8b826bec61ebf886de2c4f404c1ebdc8bab82ee1fea816d9de29127ce1852448ff717a3fe8bbfe9e92012e5 -817224d9359f5da6f2158c2c7bf9165501424f063e67ba9859a07ab72ee2ee62eb00ca6da821cfa19065c3282ca72c74 -94b95c465e6cb00da400558a3c60cfec4b79b27e602ca67cbc91aead08de4b6872d8ea096b0dc06dca4525c8992b8547 -a2b539a5bccd43fa347ba9c15f249b417997c6a38c63517ca38394976baa08e20be384a360969ff54e7e721db536b3e5 -96caf707e34f62811ee8d32ccf28d8d6ec579bc33e424d0473529af5315c456fd026aa910c1fed70c91982d51df7d3ca -8a77b73e890b644c6a142bdbac59b22d6a676f3b63ddafb52d914bb9d395b8bf5aedcbcc90429337df431ebd758a07a6 -8857830a7351025617a08bc44caec28d2fae07ebf5ffc9f01d979ce2a53839a670e61ae2783e138313929129790a51a1 -aa3e420321ed6f0aa326d28d1a10f13facec6f605b6218a6eb9cbc074801f3467bf013a456d1415a5536f12599efa3d3 -824aed0951957b00ea2f3d423e30328a3527bf6714cf9abbae84cf27e58e5c35452ba89ccc011de7c68c75d6e021d8f1 -a2e87cc06bf202e953fb1081933d8b4445527dde20e38ed1a4f440144fd8fa464a2b73e068b140562e9045e0f4bd3144 -ae3b8f06ad97d7ae3a5e5ca839efff3e4824dc238c0c03fc1a8d2fc8aa546cdfd165b784a31bb4dec7c77e9305b99a4b -b30c3e12395b1fb8b776f3ec9f87c70e35763a7b2ddc68f0f60a4982a84017f27c891a98561c830038deb033698ed7fc -874e507757cd1177d0dff0b0c62ce90130324442a33da3b2c8ee09dbca5d543e3ecfe707e9f1361e7c7db641c72794bb -b53012dd10b5e7460b57c092eaa06d6502720df9edbbe3e3f61a9998a272bf5baaac4a5a732ad4efe35d6fac6feca744 -85e6509d711515534d394e6cacbed6c81da710074d16ef3f4950bf2f578d662a494d835674f79c4d6315bced4defc5f0 -b6132b2a34b0905dcadc6119fd215419a7971fe545e52f48b768006944b4a9d7db1a74b149e2951ea48c083b752d0804 -989867da6415036d19b4bacc926ce6f4df7a556f50a1ba5f3c48eea9cefbb1c09da81481c8009331ee83f0859185e164 -960a6c36542876174d3fbc1505413e29f053ed87b8d38fef3af180491c7eff25200b45dd5fe5d4d8e63c7e8c9c00f4c8 -9040b59bd739d9cc2e8f6e894683429e4e876a8106238689ff4c22770ae5fdae1f32d962b30301fa0634ee163b524f35 -af3fcd0a45fe9e8fe256dc7eab242ef7f582dd832d147444483c62787ac820fafc6ca55d639a73f76bfa5e7f5462ab8f -b934c799d0736953a73d91e761767fdb78454355c4b15c680ce08accb57ccf941b13a1236980001f9e6195801cffd692 -8871e8e741157c2c326b22cf09551e78da3c1ec0fc0543136f581f1550f8bab03b0a7b80525c1e99812cdbf3a9698f96 -a8a977f51473a91d178ee8cfa45ffef8d6fd93ab1d6e428f96a3c79816d9c6a93cd70f94d4deda0125fd6816e30f3bea -a7688b3b0a4fc1dd16e8ba6dc758d3cfe1b7cf401c31739484c7fa253cce0967df1b290769bcefc9d23d3e0cb19e6218 -8ae84322662a57c6d729e6ff9d2737698cc2da2daeb1f39e506618750ed23442a6740955f299e4a15dda6db3e534d2c6 -a04a961cdccfa4b7ef83ced17ab221d6a043b2c718a0d6cc8e6f798507a31f10bf70361f70a049bc8058303fa7f96864 -b463e39732a7d9daec8a456fb58e54b30a6e160aa522a18b9a9e836488cce3342bcbb2e1deab0f5e6ec0a8796d77197d -b1434a11c6750f14018a2d3bcf94390e2948f4f187e93bb22070ca3e5393d339dc328cbfc3e48815f51929465ffe7d81 -84ff81d73f3828340623d7e3345553610aa22a5432217ef0ebd193cbf4a24234b190c65ca0873c22d10ea7b63bd1fbed -b6fe2723f0c47757932c2ddde7a4f8434f665612f7b87b4009c2635d56b6e16b200859a8ade49276de0ef27a2b6c970a -9742884ed7cd52b4a4a068a43d3faa02551a424136c85a9313f7cb58ea54c04aa83b0728fd741d1fe39621e931e88f8f -b7d2d65ea4d1ad07a5dee39e40d6c03a61264a56b1585b4d76fc5b2a68d80a93a42a0181d432528582bf08d144c2d6a9 -88c0f66bada89f8a43e5a6ead2915088173d106c76f724f4a97b0f6758aed6ae5c37c373c6b92cdd4aea8f6261f3a374 -81f9c43582cb42db3900747eb49ec94edb2284999a499d1527f03315fd330e5a509afa3bff659853570e9886aab5b28b -821f9d27d6beb416abf9aa5c79afb65a50ed276dbda6060103bc808bcd34426b82da5f23e38e88a55e172f5c294b4d40 -8ba307b9e7cb63a6c4f3851b321aebfdb6af34a5a4c3bd949ff7d96603e59b27ff4dc4970715d35f7758260ff942c9e9 -b142eb6c5f846de33227d0bda61d445a7c33c98f0a8365fe6ab4c1fabdc130849be597ef734305894a424ea715372d08 -a732730ae4512e86a741c8e4c87fee8a05ee840fec0e23b2e037d58dba8dde8d10a9bc5191d34d00598941becbbe467f -adce6f7c30fd221f6b10a0413cc76435c4bb36c2d60bca821e5c67409fe9dbb2f4c36ef85eb3d734695e4be4827e9fd3 -a74f00e0f9b23aff7b2527ce69852f8906dab9d6abe62ecd497498ab21e57542e12af9918d4fd610bb09e10b0929c510 -a593b6b0ef26448ce4eb3ab07e84238fc020b3cb10d542ff4b16d4e2be1bcde3797e45c9cf753b8dc3b0ffdb63984232 -aed3913afccf1aa1ac0eb4980eb8426d0baccebd836d44651fd72af00d09fac488a870223c42aca3ceb39752070405ae -b2c44c66a5ea7fde626548ba4cef8c8710191343d3dadfd3bb653ce715c0e03056a5303a581d47dde66e70ea5a2d2779 -8e5029b2ccf5128a12327b5103f7532db599846e422531869560ceaff392236434d87159f597937dbf4054f810c114f4 -82beed1a2c4477e5eb39fc5b0e773b30cfec77ef2b1bf17eadaf60eb35b6d0dd9d8cf06315c48d3546badb3f21cd0cca -90077bd6cc0e4be5fff08e5d07a5a158d36cebd1d1363125bc4fae0866ffe825b26f933d4ee5427ba5cd0c33c19a7b06 -a7ec0d8f079970e8e34f0ef3a53d3e0e45428ddcef9cc776ead5e542ef06f3c86981644f61c5a637e4faf001fb8c6b3e -ae6d4add6d1a6f90b22792bc9d40723ee6850c27d0b97eefafd5b7fd98e424aa97868b5287cc41b4fbd7023bca6a322c -831aa917533d077da07c01417feaa1408846363ba2b8d22c6116bb858a95801547dd88b7d7fa1d2e3f0a02bdeb2e103d -96511b860b07c8a5ed773f36d4aa9d02fb5e7882753bf56303595bcb57e37ccc60288887eb83bef08c657ec261a021a2 -921d2a3e7e9790f74068623de327443666b634c8443aba80120a45bba450df920b2374d96df1ce3fb1b06dd06f8cf6e3 -aa74451d51fe82b4581ead8e506ec6cd881010f7e7dd51fc388eb9a557db5d3c6721f81c151d08ebd9c2591689fbc13e -a972bfbcf4033d5742d08716c927c442119bdae336bf5dff914523b285ccf31953da2733759aacaa246a9af9f698342c -ad1fcd0cae0e76840194ce4150cb8a56ebed728ec9272035f52a799d480dfc85840a4d52d994a18b6edb31e79be6e8ad -a2c69fe1d36f235215432dad48d75887a44c99dfa0d78149acc74087da215a44bdb5f04e6eef88ff7eff80a5a7decc77 -a94ab2af2b6ee1bc6e0d4e689ca45380d9fbd3c5a65b9bd249d266a4d4c07bf5d5f7ef2ae6000623aee64027892bf8fe -881ec1fc514e926cdc66480ac59e139148ff8a2a7895a49f0dff45910c90cdda97b66441a25f357d6dd2471cddd99bb3 -884e6d3b894a914c8cef946a76d5a0c8351843b2bffa2d1e56c6b5b99c84104381dd1320c451d551c0b966f4086e60f9 -817c6c10ce2677b9fc5223500322e2b880583254d0bb0d247d728f8716f5e05c9ff39f135854342a1afecd9fbdcf7c46 -aaf4a9cb686a14619aa1fc1ac285dd3843ac3dd99f2b2331c711ec87b03491c02f49101046f3c5c538dc9f8dba2a0ac2 -97ecea5ce53ca720b5d845227ae61d70269a2f53540089305c86af35f0898bfd57356e74a8a5e083fa6e1ea70080bd31 -a22d811e1a20a75feac0157c418a4bfe745ccb5d29466ffa854dca03e395b6c3504a734341746b2846d76583a780b32e -940cbaa0d2b2db94ae96b6b9cf2deefbfd059e3e5745de9aec4a25f0991b9721e5cd37ef71c631575d1a0c280b01cd5b -ae33cb4951191258a11044682de861bf8d92d90ce751b354932dd9f3913f542b6a0f8a4dc228b3cd9244ac32c4582832 -a580df5e58c4274fe0f52ac2da1837e32f5c9db92be16c170187db4c358f43e5cfdda7c5911dcc79d77a5764e32325f5 -81798178cb9d8affa424f8d3be67576ba94d108a28ccc01d330c51d5a63ca45bb8ca63a2f569b5c5fe1303cecd2d777f -89975b91b94c25c9c3660e4af4047a8bacf964783010820dbc91ff8281509379cb3b24c25080d5a01174dd9a049118d5 -a7327fcb3710ed3273b048650bde40a32732ef40a7e58cf7f2f400979c177944c8bc54117ba6c80d5d4260801dddab79 -92b475dc8cb5be4b90c482f122a51bcb3b6c70593817e7e2459c28ea54a7845c50272af38119406eaadb9bcb993368d0 -9645173e9ecefc4f2eae8363504f7c0b81d85f8949a9f8a6c01f2d49e0a0764f4eacecf3e94016dd407fc14494fce9f9 -9215fd8983d7de6ae94d35e6698226fc1454977ae58d42d294be9aad13ac821562ad37d5e7ee5cdfe6e87031d45cd197 -810360a1c9b88a9e36f520ab5a1eb8bed93f52deefbe1312a69225c0a08edb10f87cc43b794aced9c74220cefcc57e7d -ad7e810efd61ed4684aeda9ed8bb02fb9ae4b4b63fda8217d37012b94ff1b91c0087043bfa4e376f961fff030c729f3b -8b07c95c6a06db8738d10bb03ec11b89375c08e77f0cab7e672ce70b2685667ca19c7e1c8b092821d31108ea18dfd4c7 -968825d025ded899ff7c57245250535c732836f7565eab1ae23ee7e513201d413c16e1ba3f5166e7ac6cf74de8ceef4f -908243370c5788200703ade8164943ad5f8c458219186432e74dbc9904a701ea307fd9b94976c866e6c58595fd891c4b -959969d16680bc535cdc6339e6186355d0d6c0d53d7bbfb411641b9bf4b770fd5f575beef5deec5c4fa4d192d455c350 -ad177f4f826a961adeac76da40e2d930748effff731756c797eddc4e5aa23c91f070fb69b19221748130b0961e68a6bb -82f8462bcc25448ef7e0739425378e9bb8a05e283ce54aae9dbebaf7a3469f57833c9171672ad43a79778366c72a5e37 -a28fb275b1845706c2814d9638573e9bc32ff552ebaed761fe96fdbce70395891ca41c400ae438369264e31a2713b15f -8a9c613996b5e51dadb587a787253d6081ea446bf5c71096980bf6bd3c4b69905062a8e8a3792de2d2ece3b177a71089 -8d5aefef9f60cb27c1db2c649221204dda48bb9bf8bf48f965741da051340e8e4cab88b9d15c69f3f84f4c854709f48a -93ebf2ca6ad85ab6deace6de1a458706285b31877b1b4d7dcb9d126b63047efaf8c06d580115ec9acee30c8a7212fa55 -b3ee46ce189956ca298057fa8223b7fd1128cf52f39159a58bca03c71dd25161ac13f1472301f72aef3e1993fe1ab269 -a24d7a8d066504fc3f5027ccb13120e2f22896860e02c45b5eba1dbd512d6a17c28f39155ea581619f9d33db43a96f92 -ae9ceacbfe12137db2c1a271e1b34b8f92e4816bad1b3b9b6feecc34df0f8b3b0f7ed0133acdf59c537d43d33fc8d429 -83967e69bf2b361f86361bd705dce0e1ad26df06da6c52b48176fe8dfcbeb03c462c1a4c9e649eff8c654b18c876fdef -9148e6b814a7d779c19c31e33a068e97b597de1f8100513db3c581190513edc4d544801ce3dd2cf6b19e0cd6daedd28a -94ccdafc84920d320ed22de1e754adea072935d3c5f8c2d1378ebe53d140ea29853f056fb3fb1e375846061a038cc9bc -afb43348498c38b0fa5f971b8cdd3a62c844f0eb52bc33daf2f67850af0880fce84ecfb96201b308d9e6168a0d443ae3 -86d5736520a83538d4cd058cc4b4e84213ed00ebd6e7af79ae787adc17a92ba5359e28ba6c91936d967b4b28d24c3070 -b5210c1ff212c5b1e9ef9126e08fe120a41e386bb12c22266f7538c6d69c7fd8774f11c02b81fd4e88f9137b020801fe -b78cfd19f94d24e529d0f52e18ce6185cb238edc6bd43086270fd51dd99f664f43dd4c7d2fe506762fbd859028e13fcf -a6e7220598c554abdcc3fdc587b988617b32c7bb0f82c06205467dbedb58276cc07cae317a190f19d19078773f4c2bbb -b88862809487ee430368dccd85a5d72fa4d163ca4aad15c78800e19c1a95be2192719801e315d86cff7795e0544a77e4 -87ecb13a03921296f8c42ceb252d04716f10e09c93962239fcaa0a7fef93f19ab3f2680bc406170108bc583e9ff2e721 -a810cd473832b6581c36ec4cb403f2849357ba2d0b54df98ef3004b8a530c078032922a81d40158f5fb0043d56477f6e -a247b45dd85ca7fbb718b328f30a03f03c84aef2c583fbdc9fcc9eb8b52b34529e8c8f535505c10598b1b4dac3d7c647 -96ee0b91313c68bac4aa9e065ce9e1d77e51ca4cff31d6a438718c58264dee87674bd97fc5c6b8008be709521e4fd008 -837567ad073e42266951a9a54750919280a2ac835a73c158407c3a2b1904cf0d17b7195a393c71a18ad029cbd9cf79ee -a6a469c44b67ebf02196213e7a63ad0423aab9a6e54acc6fcbdbb915bc043586993454dc3cd9e4be8f27d67c1050879b -8712d380a843b08b7b294f1f06e2f11f4ad6bcc655fdde86a4d8bc739c23916f6fad2b902fe47d6212f03607907e9f0e -920adfb644b534789943cdae1bdd6e42828dda1696a440af2f54e6b97f4f97470a1c6ea9fa6a2705d8f04911d055acd1 -a161c73adf584a0061e963b062f59d90faac65c9b3a936b837a10d817f02fcabfa748824607be45a183dd40f991fe83f -874f4ecd408c76e625ea50bc59c53c2d930ee25baf4b4eca2440bfbffb3b8bc294db579caa7c68629f4d9ec24187c1ba -8bff18087f112be7f4aa654e85c71fef70eee8ae480f61d0383ff6f5ab1a0508f966183bb3fc4d6f29cb7ca234aa50d3 -b03b46a3ca3bc743a173cbc008f92ab1aedd7466b35a6d1ca11e894b9482ea9dc75f8d6db2ddd1add99bfbe7657518b7 -8b4f3691403c3a8ad9e097f02d130769628feddfa8c2b3dfe8cff64e2bed7d6e5d192c1e2ba0ac348b8585e94acd5fa1 -a0d9ca4a212301f97591bf65d5ef2b2664766b427c9dd342e23cb468426e6a56be66b1cb41fea1889ac5d11a8e3c50a5 -8c93ed74188ca23b3df29e5396974b9cc135c91fdefdea6c0df694c8116410e93509559af55533a3776ac11b228d69b1 -82dd331fb3f9e344ebdeeb557769b86a2cc8cc38f6c298d7572a33aea87c261afa9dbd898989139b9fc16bc1e880a099 -a65faedf326bcfd8ef98a51410c78b021d39206704e8291cd1f09e096a66b9b0486be65ff185ca224c45918ac337ddeb -a188b37d363ac072a766fd5d6fa27df07363feff1342217b19e3c37385e42ffde55e4be8355aceaa2f267b6d66b4ac41 -810fa3ba3e96d843e3bafd3f2995727f223d3567c8ba77d684c993ba1773c66551eb5009897c51b3fe9b37196984f5ec -87631537541852da323b4353af45a164f68b304d24c01183bf271782e11687f3fcf528394e1566c2a26cb527b3148e64 -b721cb2b37b3c477a48e3cc0044167d51ff568a5fd2fb606e5aec7a267000f1ddc07d3db919926ae12761a8e017c767c -904dfad4ba2cc1f6e60d1b708438a70b1743b400164cd981f13c064b8328d5973987d4fb9cf894068f29d3deaf624dfb -a70491538893552c20939fae6be2f07bfa84d97e2534a6bbcc0f1729246b831103505e9f60e97a8fa7d2e6c1c2384579 -8726cf1b26b41f443ff7485adcfddc39ace2e62f4d65dd0bb927d933e262b66f1a9b367ded5fbdd6f3b0932553ac1735 -ae8a11cfdf7aa54c08f80cb645e3339187ab3886babe9fae5239ba507bb3dd1c0d161ca474a2df081dcd3d63e8fe445e -92328719e97ce60e56110f30a00ac5d9c7a2baaf5f8d22355d53c1c77941e3a1fec7d1405e6fbf8959665fe2ba7a8cad -8d9d6255b65798d0018a8cccb0b6343efd41dc14ff2058d3eed9451ceaad681e4a0fa6af67b0a04318aa628024e5553d -b70209090055459296006742d946a513f0cba6d83a05249ee8e7a51052b29c0ca9722dc4af5f9816a1b7938a5dac7f79 -aab7b766b9bf91786dfa801fcef6d575dc6f12b77ecc662eb4498f0312e54d0de9ea820e61508fc8aeee5ab5db529349 -a8104b462337748b7f086a135d0c3f87f8e51b7165ca6611264b8fb639d9a2f519926cb311fa2055b5fadf03da70c678 -b0d2460747d5d8b30fc6c6bd0a87cb343ddb05d90a51b465e8f67d499cfc5e3a9e365da05ae233bbee792cdf90ec67d5 -aa55f5bf3815266b4a149f85ed18e451c93de9163575e3ec75dd610381cc0805bb0a4d7c4af5b1f94d10231255436d2c -8d4c6a1944ff94426151909eb5b99cfd92167b967dabe2bf3aa66bb3c26c449c13097de881b2cfc1bf052862c1ef7b03 -8862296162451b9b6b77f03bf32e6df71325e8d7485cf3335d66fd48b74c2a8334c241db8263033724f26269ad95b395 -901aa96deb26cda5d9321190ae6624d357a41729d72ef1abfd71bebf6139af6d690798daba53b7bc5923462115ff748a -96c195ec4992728a1eb38cdde42d89a7bce150db43adbc9e61e279ea839e538deec71326b618dd39c50d589f78fc0614 -b6ff8b8aa0837b99a1a8b46fb37f20ad4aecc6a98381b1308697829a59b8442ffc748637a88cb30c9b1f0f28a926c4f6 -8d807e3dca9e7bef277db1d2cfb372408dd587364e8048b304eff00eacde2c723bfc84be9b98553f83cba5c7b3cba248 -8800c96adb0195c4fc5b24511450dee503c32bf47044f5e2e25bd6651f514d79a2dd9b01cd8c09f3c9d3859338490f57 -89fe366096097e38ec28dd1148887112efa5306cc0c3da09562aafa56f4eb000bf46ff79bf0bdd270cbde6bf0e1c8957 -af409a90c2776e1e7e3760b2042507b8709e943424606e31e791d42f17873a2710797f5baaab4cc4a19998ef648556b0 -8d761863c9b6edbd232d35ab853d944f5c950c2b643f84a1a1327ebb947290800710ff01dcfa26dc8e9828481240e8b1 -90b95e9be1e55c463ed857c4e0617d6dc3674e99b6aa62ed33c8e79d6dfcf7d122f4f4cc2ee3e7c5a49170cb617d2e2e -b3ff381efefabc4db38cc4727432e0301949ae4f16f8d1dea9b4f4de611cf5a36d84290a0bef160dac4e1955e516b3b0 -a8a84564b56a9003adcadb3565dc512239fc79572762cda7b5901a255bc82656bb9c01212ad33d6bef4fbbce18dacc87 -90a081890364b222eef54bf0075417f85e340d2fec8b7375995f598aeb33f26b44143ebf56fca7d8b4ebb36b5747b0eb -ade6ee49e1293224ddf2d8ab7f14bb5be6bc6284f60fd5b3a1e0cf147b73cff57cf19763b8a36c5083badc79c606b103 -b2fa99806dd2fa3de09320b615a2570c416c9bcdb052e592b0aead748bbe407ec9475a3d932ae48b71c2627eb81986a6 -91f3b7b73c8ccc9392542711c45fe6f236057e6efad587d661ad5cb4d6e88265f86b807bb1151736b1009ab74fd7acb4 -8800e2a46af96696dfbdcbf2ca2918b3dcf28ad970170d2d1783b52b8d945a9167d052beeb55f56c126da7ffa7059baa -9862267a1311c385956b977c9aa08548c28d758d7ba82d43dbc3d0a0fd1b7a221d39e8399997fea9014ac509ff510ac4 -b7d24f78886fd3e2d283e18d9ad5a25c1a904e7d9b9104bf47da469d74f34162e27e531380dbbe0a9d051e6ffd51d6e7 -b0f445f9d143e28b9df36b0f2c052da87ee2ca374d9d0fbe2eff66ca6fe5fe0d2c1951b428d58f7314b7e74e45d445ea -b63fc4083eabb8437dafeb6a904120691dcb53ce2938b820bb553da0e1eecd476f72495aacb72600cf9cad18698fd3db -b9ffd8108eaebd582d665f8690fe8bb207fd85185e6dd9f0b355a09bac1bbff26e0fdb172bc0498df025414e88fe2eda -967ed453e1f1a4c5b7b6834cc9f75c13f6889edc0cc91dc445727e9f408487bbf05c337103f61397a10011dfbe25d61d -98ceb673aff36e1987d5521a3984a07079c3c6155974bb8b413e8ae1ce84095fe4f7862fba7aefa14753eb26f2a5805f -85f01d28603a8fdf6ce6a50cb5c44f8a36b95b91302e3f4cd95c108ce8f4d212e73aec1b8d936520d9226802a2bd9136 -88118e9703200ca07910345fbb789e7a8f92bd80bbc79f0a9e040e8767d33df39f6eded403a9b636eabf9101e588482a -90833a51eef1b10ed74e8f9bbd6197e29c5292e469c854eed10b0da663e2bceb92539710b1858bbb21887bd538d28d89 -b513b905ec19191167c6193067b5cfdf5a3d3828375360df1c7e2ced5815437dfd37f0c4c8f009d7fb29ff3c8793f560 -b1b6d405d2d18f9554b8a358cc7e2d78a3b34269737d561992c8de83392ac9a2857be4bf15de5a6c74e0c9d0f31f393c -b828bd3e452b797323b798186607849f85d1fb20c616833c0619360dfd6b3e3aa000fd09dafe4b62d74abc41072ff1a9 -8efde67d0cca56bb2c464731879c9ac46a52e75bac702a63200a5e192b4f81c641f855ca6747752b84fe469cb7113b6c -b2762ba1c89ac3c9a983c242e4d1c2610ff0528585ed5c0dfc8a2c0253551142af9b59f43158e8915a1da7cc26b9df67 -8a3f1157fb820d1497ef6b25cd70b7e16bb8b961b0063ad340d82a79ee76eb2359ca9e15e6d42987ed7f154f5eeaa2da -a75e29f29d38f09c879f971c11beb5368affa084313474a5ecafa2896180b9e47ea1995c2733ec46f421e395a1d9cffe -8e8c3dd3e7196ef0b4996b531ec79e4a1f211db5d5635e48ceb80ff7568b2ff587e845f97ee703bb23a60945ad64314a -8e7f32f4a3e3c584af5e3d406924a0aa34024c42eca74ef6cc2a358fd3c9efaf25f1c03aa1e66bb94b023a2ee2a1cace -ab7dce05d59c10a84feb524fcb62478906b3fa045135b23afbede3bb32e0c678d8ebe59feabccb5c8f3550ea76cae44b -b38bb4b44d827f6fd3bd34e31f9186c59e312dbfadd4a7a88e588da10146a78b1f8716c91ad8b806beb8da65cab80c4c -9490ce9442bbbd05438c7f5c4dea789f74a7e92b1886a730544b55ba377840740a3ae4f2f146ee73f47c9278b0e233bc -83c003fab22a7178eed1a668e0f65d4fe38ef3900044e9ec63070c23f2827d36a1e73e5c2b883ec6a2afe2450171b3b3 -9982f02405978ddc4fca9063ebbdb152f524c84e79398955e66fe51bc7c1660ec1afc3a86ec49f58d7b7dde03505731c -ab337bd83ccdd2322088ffa8d005f450ced6b35790f37ab4534313315ee84312adc25e99cce052863a8bedee991729ed -8312ce4bec94366d88f16127a17419ef64285cd5bf9e5eda010319b48085966ed1252ed2f5a9fd3e0259b91bb65f1827 -a60d5a6327c4041b0c00a1aa2f0af056520f83c9ce9d9ccd03a0bd4d9e6a1511f26a422ea86bd858a1f77438adf07e6c -b84a0a0b030bdad83cf5202aa9afe58c9820e52483ab41f835f8c582c129ee3f34aa096d11c1cd922eda02ea1196a882 -8077d105317f4a8a8f1aadeb05e0722bb55f11abcb490c36c0904401107eb3372875b0ac233144829e734f0c538d8c1d -9202503bd29a6ec198823a1e4e098f9cfe359ed51eb5174d1ca41368821bfeebcbd49debfd02952c41359d1c7c06d2b1 -abc28c155e09365cb77ffead8dc8f602335ef93b2f44e4ef767ce8fc8ef9dd707400f3a722e92776c2e0b40192c06354 -b0f6d1442533ca45c9399e0a63a11f85ff288d242cea6cb3b68c02e77bd7d158047cae2d25b3bcd9606f8f66d9b32855 -b01c3d56a0db84dc94575f4b6ee2de4beca3230e86bed63e2066beb22768b0a8efb08ebaf8ac3dedb5fe46708b084807 -8c8634b0432159f66feaabb165842d1c8ac378f79565b1b90c381aa8450eb4231c3dad11ec9317b9fc2b155c3a771e32 -8e67f623d69ecd430c9ee0888520b6038f13a2b6140525b056dc0951f0cfed2822e62cf11d952a483107c5c5acac4826 -9590bb1cba816dd6acd5ac5fba5142c0a19d53573e422c74005e0bcf34993a8138c83124cad35a3df65879dba6134edd -801cd96cde0749021a253027118d3ea135f3fcdbe895db08a6c145641f95ebd368dd6a1568d995e1d0084146aebe224a -848b5d196427f6fc1f762ee3d36e832b64a76ec1033cfedc8b985dea93932a7892b8ef1035c653fb9dcd9ab2d9a44ac8 -a1017eb83d5c4e2477e7bd2241b2b98c4951a3b391081cae7d75965cadc1acaec755cf350f1f3d29741b0828e36fedea -8d6d2785e30f3c29aad17bd677914a752f831e96d46caf54446d967cb2432be2c849e26f0d193a60bee161ea5c6fe90a -935c0ba4290d4595428e034b5c8001cbd400040d89ab00861108e8f8f4af4258e41f34a7e6b93b04bc253d3b9ffc13bf -aac02257146246998477921cef2e9892228590d323b839f3e64ea893b991b463bc2f47e1e5092ddb47e70b2f5bce7622 -b921fde9412970a5d4c9a908ae8ce65861d06c7679af577cf0ad0d5344c421166986bee471fd6a6cecb7d591f06ec985 -8ef4c37487b139d6756003060600bb6ebac7ea810b9c4364fc978e842f13ac196d1264fbe5af60d76ff6d9203d8e7d3f -94b65e14022b5cf6a9b95f94be5ace2711957c96f4211c3f7bb36206bd39cfbd0ea82186cab5ad0577a23214a5c86e9e -a31c166d2a2ca1d5a75a5920fef7532681f62191a50d8555fdaa63ba4581c3391cc94a536fc09aac89f64eafceec3f90 -919a8cc128de01e9e10f5d83b08b52293fdd41bde2b5ae070f3d95842d4a16e5331cf2f3d61c765570c8022403610fa4 -b23d6f8331eef100152d60483cfa14232a85ee712c8538c9b6417a5a7c5b353c2ac401390c6c215cb101f5cee6b5f43e -ab357160c08a18319510a571eafff154298ce1020de8e1dc6138a09fcb0fcbcdd8359f7e9386bda00b7b9cdea745ffdc -ab55079aea34afa5c0bd1124b9cdfe01f325b402fdfa017301bf87812eaa811ea5798c3aaf818074d420d1c782b10ada -ade616010dc5009e7fc4f8d8b00dc716686a5fa0a7816ad9e503e15839d3b909b69d9dd929b7575376434ffec0d2bea8 -863997b97ed46898a8a014599508fa3079f414b1f4a0c4fdc6d74ae8b444afa350f327f8bfc2a85d27f9e2d049c50135 -8d602ff596334efd4925549ed95f2aa762b0629189f0df6dbb162581657cf3ea6863cd2287b4d9c8ad52813d87fcd235 -b70f68c596dcdeed92ad5c6c348578b26862a51eb5364237b1221e840c47a8702f0fbc56eb520a22c0eed99795d3903e -9628088f8e0853cefadee305a8bf47fa990c50fa96a82511bbe6e5dc81ef4b794e7918a109070f92fc8384d77ace226f -97e26a46e068b605ce96007197ecd943c9a23881862f4797a12a3e96ba2b8d07806ad9e2a0646796b1889c6b7d75188c -b1edf467c068cc163e2d6413cc22b16751e78b3312fe47b7ea82b08a1206d64415b2c8f2a677fa89171e82cc49797150 -a44d15ef18745b251429703e3cab188420e2d974de07251501799b016617f9630643fcd06f895634d8ecdd579e1bf000 -abd126df3917ba48c618ee4dbdf87df506193462f792874439043fa1b844466f6f4e0ff2e42516e63b5b23c0892b2695 -a2a67f57c4aa3c2aa1eeddbfd5009a89c26c2ce8fa3c96a64626aba19514beb125f27df8559506f737de3eae0f1fc18f -a633e0132197e6038197304b296ab171f1d8e0d0f34dcf66fe9146ac385b0239232a8470b9205a4802ab432389f4836d -a914b3a28509a906c3821463b936455d58ff45dcbe158922f9efb2037f2eb0ce8e92532d29b5d5a3fcd0d23fa773f272 -a0e1412ce4505daf1a2e59ce4f0fc0e0023e335b50d2b204422f57cd65744cc7a8ed35d5ef131a42c70b27111d3115b7 -a2339e2f2b6072e88816224fdd612c04d64e7967a492b9f8829db15367f565745325d361fd0607b0def1be384d010d9e -a7309fc41203cb99382e8193a1dcf03ac190a7ce04835304eb7e341d78634e83ea47cb15b885601956736d04cdfcaa01 -81f3ccd6c7f5b39e4e873365f8c37b214e8ab122d04a606fbb7339dc3298c427e922ec7418002561d4106505b5c399ee -92c121cf914ca549130e352eb297872a63200e99b148d88fbc9506ad882bec9d0203d65f280fb5b0ba92e336b7f932e8 -a4b330cf3f064f5b131578626ad7043ce2a433b6f175feb0b52d36134a454ca219373fd30d5e5796410e005b69082e47 -86fe5774112403ad83f9c55d58317eeb17ad8e1176d9f2f69c2afb7ed83bc718ed4e0245ceab4b377f5f062dcd4c00e7 -809d152a7e2654c7fd175b57f7928365a521be92e1ed06c05188a95864ddb25f7cab4c71db7d61bbf4cae46f3a1d96ce -b82d663e55c2a5ada7e169e9b1a87bc1c0177baf1ec1c96559b4cb1c5214ce1ddf2ab8d345014cab6402f3774235cf5a -86580af86df1bd2c385adb8f9a079e925981b7184db66fc5fe5b14cddb82e7d836b06eaeef14924ac529487b23dae111 -b5f5f4c5c94944ecc804df6ab8687d64e27d988cbfeae1ba7394e0f6adbf778c5881ead7cd8082dd7d68542b9bb4ecd5 -a6016916146c2685c46e8fdd24186394e2d5496e77e08c0c6a709d4cd7dfa97f1efcef94922b89196819076a91ad37b5 -b778e7367ded3b6eab53d5fc257f7a87e8faf74a593900f2f517220add2125be3f6142022660d8181df8d164ad9441ce -8581b2d36abe6f553add4d24be761bec1b8efaa2929519114346615380b3c55b59e6ad86990e312f7e234d0203bdf59b -9917e74fd45c3f71a829ff5498a7f6b5599b48c098dda2339bf04352bfc7f368ccf1a407f5835901240e76452ae807d7 -afd196ce6f9335069138fd2e3d133134da253978b4ce373152c0f26affe77a336505787594022e610f8feb722f7cc1fb -a477491a1562e329764645e8f24d8e228e5ef28c9f74c6b5b3abc4b6a562c15ffb0f680d372aed04d9e1bf944dece7be -9767440d58c57d3077319d3a330e5322b9ba16981ec74a5a14d53462eab59ae7fd2b14025bfc63b268862094acb444e6 -80986d921be3513ef69264423f351a61cb48390c1be8673aee0f089076086aaebea7ebe268fd0aa7182695606116f679 -a9554c5c921c07b450ee04e34ec58e054ac1541b26ce2ce5a393367a97348ba0089f53db6660ad76b60278b66fd12e3e -95097e7d2999b3e84bf052c775581cf361325325f4a50192521d8f4693c830bed667d88f482dc1e3f833aa2bd22d2cbf -9014c91d0f85aefd28436b5228c12f6353c055a9326c7efbf5e071e089e2ee7c070fcbc84c5fafc336cbb8fa6fec1ca1 -90f57ba36ee1066b55d37384942d8b57ae00f3cf9a3c1d6a3dfee1d1af42d4b5fa9baeb0cd7e46687d1d6d090ddb931d -8e4b1db12fd760a17214c9e47f1fce6e43c0dbb4589a827a13ac61aaae93759345697bb438a00edab92e0b7b62414683 -8022a959a513cdc0e9c705e0fc04eafd05ff37c867ae0f31f6d01cddd5df86138a426cab2ff0ac8ff03a62e20f7e8f51 -914e9a38829834c7360443b8ed86137e6f936389488eccf05b4b4db7c9425611705076ecb3f27105d24b85c852be7511 -957fb10783e2bd0db1ba66b18e794df710bc3b2b05776be146fa5863c15b1ebdd39747b1a95d9564e1772cdfc4f37b8a -b6307028444daed8ed785ac9d0de76bc3fe23ff2cc7e48102553613bbfb5afe0ebe45e4212a27021c8eb870721e62a1f -8f76143597777d940b15a01b39c5e1b045464d146d9a30a6abe8b5d3907250e6c7f858ff2308f8591e8b0a7b3f3c568a -96163138ac0ce5fd00ae9a289648fd9300a0ca0f63a88481d703ecd281c06a52a3b5178e849e331f9c85ca4ba398f4cc -a63ef47c3e18245b0482596a09f488a716df3cbd0f9e5cfabed0d742843e65db8961c556f45f49762f3a6ac8b627b3ef -8cb595466552e7c4d42909f232d4063e0a663a8ef6f6c9b7ce3a0542b2459cde04e0e54c7623d404acb5b82775ac04f6 -b47fe69960eb45f399368807cff16d941a5a4ebad1f5ec46e3dc8a2e4d598a7e6114d8f0ca791e9720fd786070524e2b -89eb5ff83eea9df490e5beca1a1fbbbbcf7184a37e2c8c91ede7a1e654c81e8cd41eceece4042ea7918a4f4646b67fd6 -a84f5d155ed08b9054eecb15f689ba81e44589e6e7207a99790c598962837ca99ec12344105b16641ca91165672f7153 -a6cc8f25c2d5b2d2f220ec359e6a37a52b95fa6af6e173c65e7cd55299eff4aa9e6d9e6f2769e6459313f1f2aecb0fab -afcde944411f017a9f7979755294981e941cc41f03df5e10522ef7c7505e5f1babdd67b3bf5258e8623150062eb41d9b -8fab39f39c0f40182fcd996ade2012643fe7731808afbc53f9b26900b4d4d1f0f5312d9d40b3df8baa4739970a49c732 -ae193af9726da0ebe7df1f9ee1c4846a5b2a7621403baf8e66c66b60f523e719c30c6b4f897bb14b27d3ff3da8392eeb -8ac5adb82d852eba255764029f42e6da92dcdd0e224d387d1ef94174038db9709ac558d90d7e7c57ad4ce7f89bbfc38c -a2066b3458fdf678ee487a55dd5bfb74fde03b54620cb0e25412a89ee28ad0d685e309a51e3e4694be2fa6f1593a344c -88d031745dd0ae07d61a15b594be5d4b2e2a29e715d081649ad63605e3404b0c3a5353f0fd9fad9c05c18e93ce674fa1 -8283cfb0ef743a043f2b77ecaeba3005e2ca50435585b5dd24777ee6bce12332f85e21b446b536da38508807f0f07563 -b376de22d5f6b0af0b59f7d9764561f4244cf8ffe22890ecd3dcf2ff1832130c9b821e068c9d8773136f4796721e5963 -ae3afc50c764f406353965363840bf28ee85e7064eb9d5f0bb3c31c64ab10f48c853e942ee2c9b51bae59651eaa08c2f -948b204d103917461a01a6c57a88f2d66b476eae5b00be20ec8c747650e864bc8a83aee0aff59cb7584b7a3387e0ee48 -81ab098a082b07f896c5ffd1e4446cb7fb44804cbbf38d125208b233fc82f8ec9a6a8d8dd1c9a1162dc28ffeec0dde50 -a149c6f1312821ced2969268789a3151bdda213451760b397139a028da609c4134ac083169feb0ee423a0acafd10eceb -b0ac9e27a5dadaf523010f730b28f0ebac01f460d3bbbe277dc9d44218abb5686f4fac89ae462682fef9edbba663520a -8d0e0073cca273daaaa61b6fc54bfe5a009bc3e20ae820f6c93ba77b19eca517d457e948a2de5e77678e4241807157cb -ad61d3a2edf7c7533a04964b97499503fd8374ca64286dba80465e68fe932e96749b476f458c6fc57cb1a7ca85764d11 -90eb5e121ae46bc01a30881eaa556f46bd8457a4e80787cf634aab355082de34ac57d7f497446468225f7721e68e2a47 -8cdac557de7c42d1f3780e33dec1b81889f6352279be81c65566cdd4952d4c15d79e656cbd46035ab090b385e90245ef -82b67e61b88b84f4f4d4f65df37b3e3dcf8ec91ea1b5c008fdccd52da643adbe6468a1cfdb999e87d195afe2883a3b46 -8503b467e8f5d6048a4a9b78496c58493a462852cab54a70594ae3fd064cfd0deb4b8f336a262155d9fedcaa67d2f6fd -8db56c5ac763a57b6ce6832930c57117058e3e5a81532b7d19346346205e2ec614eb1a2ee836ef621de50a7bc9b7f040 -ad344699198f3c6e8c0a3470f92aaffc805b76266734414c298e10b5b3797ca53578de7ccb2f458f5e0448203f55282b -80602032c43c9e2a09154cc88b83238343b7a139f566d64cb482d87436b288a98f1ea244fd3bff8da3c398686a900c14 -a6385bd50ecd548cfb37174cdbb89e10025b5cadaf3cff164c95d7aef5a33e3d6a9bf0c681b9e11db9ef54ebeee2a0c1 -abf2d95f4aa34b0581eb9257a0cc8462b2213941a5deb8ba014283293e8b36613951b61261cc67bbd09526a54cbbff76 -a3d5de52f48df72c289ff713e445991f142390798cd42bd9d9dbefaee4af4f5faf09042d126b975cf6b98711c3072553 -8e627302ff3d686cff8872a1b7c2a57b35f45bf2fc9aa42b049d8b4d6996a662b8e7cbac6597f0cb79b0cc4e29fbf133 -8510702e101b39a1efbf4e504e6123540c34b5689645e70d0bac1ecc1baf47d86c05cef6c4317a4e99b4edaeb53f2d00 -aa173f0ecbcc6088f878f8726d317748c81ebf501bba461f163b55d66099b191ec7c55f7702f351a9c8eb42cfa3280e2 -b560a697eafab695bcef1416648a0a664a71e311ecbe5823ae903bd0ed2057b9d7574b9a86d3fe22aa3e6ddce38ea513 -8df6304a3d9cf40100f3f687575419c998cd77e5cc27d579cf4f8e98642de3609af384a0337d145dd7c5635172d26a71 -8105c7f3e4d30a29151849673853b457c1885c186c132d0a98e63096c3774bc9deb956cf957367e633d0913680bda307 -95373fc22c0917c3c2044ac688c4f29a63ed858a45c0d6d2d0fe97afd6f532dcb648670594290c1c89010ecc69259bef -8c2fae9bcadab341f49b55230310df93cac46be42d4caa0d42e45104148a91e527af1b4209c0d972448162aed28fab64 -b05a77baab70683f76209626eaefdda2d36a0b66c780a20142d23c55bd479ddd4ad95b24579384b6cf62c8eb4c92d021 -8e6bc6a7ea2755b4aaa19c1c1dee93811fcde514f03485fdc3252f0ab7f032c315614f6336e57cea25dcfb8fb6084eeb -b656a27d06aade55eadae2ad2a1059198918ea6cc3fd22c0ed881294d34d5ac7b5e4700cc24350e27d76646263b223aa -a296469f24f6f56da92d713afcd4dd606e7da1f79dc4e434593c53695847eefc81c7c446486c4b3b8c8d00c90c166f14 -87a326f57713ac2c9dffeb3af44b9f3c613a8f952676fc46343299122b47ee0f8d792abaa4b5db6451ced5dd153aabd0 -b689e554ba9293b9c1f6344a3c8fcb6951d9f9eac4a2e2df13de021aade7c186be27500e81388e5b8bcab4c80f220a31 -87ae0aa0aa48eac53d1ca5a7b93917de12db9e40ceabf8fdb40884ae771cfdf095411deef7c9f821af0b7070454a2608 -a71ffa7eae8ace94e6c3581d4cb2ad25d48cbd27edc9ec45baa2c8eb932a4773c3272b2ffaf077b40f76942a1f3af7f2 -94c218c91a9b73da6b7a495b3728f3028df8ad9133312fc0c03e8c5253b7ccb83ed14688fd4602e2fd41f29a0bc698bd -ae1e77b90ca33728af07a4c03fb2ef71cd92e2618e7bf8ed4d785ce90097fc4866c29999eb84a6cf1819d75285a03af2 -b7a5945b277dab9993cf761e838b0ac6eaa903d7111fca79f9fde3d4285af7a89bf6634a71909d095d7619d913972c9c -8c43b37be02f39b22029b20aca31bff661abce4471dca88aa3bddefd9c92304a088b2dfc8c4795acc301ca3160656af2 -b32e5d0fba024554bd5fe8a793ebe8003335ddd7f585876df2048dcf759a01285fecb53daae4950ba57f3a282a4d8495 -85ea7fd5e10c7b659df5289b2978b2c89e244f269e061b9a15fcab7983fc1962b63546e82d5731c97ec74b6804be63ef -96b89f39181141a7e32986ac02d7586088c5a9662cec39843f397f3178714d02f929af70630c12cbaba0268f8ba2d4fa -929ab1a2a009b1eb37a2817c89696a06426529ebe3f306c586ab717bd34c35a53eca2d7ddcdef36117872db660024af9 -a696dccf439e9ca41511e16bf3042d7ec0e2f86c099e4fc8879d778a5ea79e33aa7ce96b23dc4332b7ba26859d8e674d -a8fe69a678f9a194b8670a41e941f0460f6e2dbc60470ab4d6ae2679cc9c6ce2c3a39df2303bee486dbfde6844e6b31a -95f58f5c82de2f2a927ca99bf63c9fc02e9030c7e46d0bf6b67fe83a448d0ae1c99541b59caf0e1ccab8326231af09a5 -a57badb2c56ca2c45953bd569caf22968f76ed46b9bac389163d6fe22a715c83d5e94ae8759b0e6e8c2f27bff7748f3f -868726fd49963b24acb5333364dffea147e98f33aa19c7919dc9aca0fd26661cfaded74ede7418a5fadbe7f5ae67b67b -a8d8550dcc64d9f1dd7bcdab236c4122f2b65ea404bb483256d712c7518f08bb028ff8801f1da6aed6cbfc5c7062e33b -97e25a87dae23155809476232178538d4bc05d4ff0882916eb29ae515f2a62bfce73083466cc0010ca956aca200aeacc -b4ea26be3f4bd04aa82d7c4b0913b97bcdf5e88b76c57eb1a336cbd0a3eb29de751e1bc47c0e8258adec3f17426d0c71 -99ee555a4d9b3cf2eb420b2af8e3bc99046880536116d0ce7193464ac40685ef14e0e3c442f604e32f8338cb0ef92558 -8c64efa1da63cd08f319103c5c7a761221080e74227bbc58b8fb35d08aa42078810d7af3e60446cbaff160c319535648 -8d9fd88040076c28420e3395cbdfea402e4077a3808a97b7939d49ecbcf1418fe50a0460e1c1b22ac3f6e7771d65169a -ae3c19882d7a9875d439265a0c7003c8d410367627d21575a864b9cb4918de7dbdb58a364af40c5e045f3df40f95d337 -b4f7bfacab7b2cafe393f1322d6dcc6f21ffe69cd31edc8db18c06f1a2b512c27bd0618091fd207ba8df1808e9d45914 -94f134acd0007c623fb7934bcb65ef853313eb283a889a3ffa79a37a5c8f3665f3d5b4876bc66223610c21dc9b919d37 -aa15f74051171daacdc1f1093d3f8e2d13da2833624b80a934afec86fc02208b8f55d24b7d66076444e7633f46375c6a -a32d6bb47ef9c836d9d2371807bafbbbbb1ae719530c19d6013f1d1f813c49a60e4fa51d83693586cba3a840b23c0404 -b61b3599145ea8680011aa2366dc511a358b7d67672d5b0c5be6db03b0efb8ca5a8294cf220ea7409621f1664e00e631 -859cafc3ee90b7ececa1ed8ef2b2fc17567126ff10ca712d5ffdd16aa411a5a7d8d32c9cab1fbf63e87dce1c6e2f5f53 -a2fef1b0b2874387010e9ae425f3a9676d01a095d017493648bcdf3b31304b087ccddb5cf76abc4e1548b88919663b6b -939e18c73befc1ba2932a65ede34c70e4b91e74cc2129d57ace43ed2b3af2a9cc22a40fbf50d79a63681b6d98852866d -b3b4259d37b1b14aee5b676c9a0dd2d7f679ab95c120cb5f09f9fbf10b0a920cb613655ddb7b9e2ba5af4a221f31303c -997255fe51aaca6e5a9cb3359bcbf25b2bb9e30649bbd53a8a7c556df07e441c4e27328b38934f09c09d9500b5fabf66 -abb91be2a2d860fd662ed4f1c6edeefd4da8dc10e79251cf87f06029906e7f0be9b486462718f0525d5e049472692cb7 -b2398e593bf340a15f7801e1d1fbda69d93f2a32a889ec7c6ae5e8a37567ac3e5227213c1392ee86cfb3b56ec2787839 -8ddf10ccdd72922bed36829a36073a460c2118fc7a56ff9c1ac72581c799b15c762cb56cb78e3d118bb9f6a7e56cb25e -93e6bc0a4708d16387cacd44cf59363b994dc67d7ada7b6d6dbd831c606d975247541b42b2a309f814c1bfe205681fc6 -b93fc35c05998cffda2978e12e75812122831523041f10d52f810d34ff71944979054b04de0117e81ddf5b0b4b3e13c0 -92221631c44d60d68c6bc7b287509f37ee44cbe5fdb6935cee36b58b17c7325098f98f7910d2c3ca5dc885ad1d6dabc7 -a230124424a57fad3b1671f404a94d7c05f4c67b7a8fbacfccea28887b78d7c1ed40b92a58348e4d61328891cd2f6cee -a6a230edb8518a0f49d7231bc3e0bceb5c2ac427f045819f8584ba6f3ae3d63ed107a9a62aad543d7e1fcf1f20605706 -845be1fe94223c7f1f97d74c49d682472585d8f772762baad8a9d341d9c3015534cc83d102113c51a9dea2ab10d8d27b -b44262515e34f2db597c8128c7614d33858740310a49cdbdf9c8677c5343884b42c1292759f55b8b4abc4c86e4728033 -805592e4a3cd07c1844bc23783408310accfdb769cca882ad4d07d608e590a288b7370c2cb327f5336e72b7083a0e30f -95153e8b1140df34ee864f4ca601cb873cdd3efa634af0c4093fbaede36f51b55571ab271e6a133020cd34db8411241f -82878c1285cfa5ea1d32175c9401f3cc99f6bb224d622d3fd98cc7b0a27372f13f7ab463ce3a33ec96f9be38dbe2dfe3 -b7588748f55783077c27fc47d33e20c5c0f5a53fc0ac10194c003aa09b9f055d08ec971effa4b7f760553997a56967b3 -b36b4de6d1883b6951f59cfae381581f9c6352fcfcf1524fccdab1571a20f80441d9152dc6b48bcbbf00371337ca0bd5 -89c5523f2574e1c340a955cbed9c2f7b5fbceb260cb1133160dabb7d41c2f613ec3f6e74bbfab3c4a0a6f0626dbe068f -a52f58cc39f968a9813b1a8ddc4e83f4219e4dd82c7aa1dd083bea7edf967151d635aa9597457f879771759b876774e4 -8300a67c2e2e123f89704abfde095463045dbd97e20d4c1157bab35e9e1d3d18f1f4aaba9cbe6aa2d544e92578eaa1b6 -ac6a7f2918768eb6a43df9d3a8a04f8f72ee52f2e91c064c1c7d75cad1a3e83e5aba9fe55bb94f818099ac91ccf2e961 -8d64a2b0991cf164e29835c8ddef6069993a71ec2a7de8157bbfa2e00f6367be646ed74cbaf524f0e9fe13fb09fa15fd -8b2ffe5a545f9f680b49d0a9797a4a11700a2e2e348c34a7a985fc278f0f12def6e06710f40f9d48e4b7fbb71e072229 -8ab8f71cd337fa19178924e961958653abf7a598e3f022138b55c228440a2bac4176cea3aea393549c03cd38a13eb3fc -8419d28318c19ea4a179b7abb43669fe96347426ef3ac06b158d79c0acf777a09e8e770c2fb10e14b3a0421705990b23 -8bacdac310e1e49660359d0a7a17fe3d334eb820e61ae25e84cb52f863a2f74cbe89c2e9fc3283745d93a99b79132354 -b57ace3fa2b9f6b2db60c0d861ace7d7e657c5d35d992588aeed588c6ce3a80b6f0d49f8a26607f0b17167ab21b675e4 -83e265cde477f2ecc164f49ddc7fb255bb05ff6adc347408353b7336dc3a14fdedc86d5a7fb23f36b8423248a7a67ed1 -a60ada971f9f2d79d436de5d3d045f5ab05308cae3098acaf5521115134b2a40d664828bb89895840db7f7fb499edbc5 -a63eea12efd89b62d3952bf0542a73890b104dd1d7ff360d4755ebfa148fd62de668edac9eeb20507967ea37fb220202 -a0275767a270289adc991cc4571eff205b58ad6d3e93778ddbf95b75146d82517e8921bd0d0564e5b75fa0ccdab8e624 -b9b03fd3bf07201ba3a039176a965d736b4ef7912dd9e9bf69fe1b57c330a6aa170e5521fe8be62505f3af81b41d7806 -a95f640e26fb1106ced1729d6053e41a16e4896acac54992279ff873e5a969aad1dcfa10311e28b8f409ac1dab7f03bb -b144778921742418053cb3c70516c63162c187f00db2062193bb2c14031075dbe055d020cde761b26e8c58d0ea6df2c1 -8432fbb799e0435ef428d4fefc309a05dd589bce74d7a87faf659823e8c9ed51d3e42603d878e80f439a38be4321c2fa -b08ddef14e42d4fd5d8bf39feb7485848f0060d43b51ed5bdda39c05fe154fb111d29719ee61a23c392141358c0cfcff -8ae3c5329a5e025b86b5370e06f5e61177df4bda075856fade20a17bfef79c92f54ed495f310130021ba94fb7c33632b -92b6d3c9444100b4d7391febfc1dddaa224651677c3695c47a289a40d7a96d200b83b64e6d9df51f534564f272a2c6c6 -b432bc2a3f93d28b5e506d68527f1efeb2e2570f6be0794576e2a6ef9138926fdad8dd2eabfa979b79ab7266370e86bc -8bc315eacedbcfc462ece66a29662ca3dcd451f83de5c7626ef8712c196208fb3d8a0faf80b2e80384f0dd9772f61a23 -a72375b797283f0f4266dec188678e2b2c060dfed5880fc6bb0c996b06e91a5343ea2b695adaab0a6fd183b040b46b56 -a43445036fbaa414621918d6a897d3692fdae7b2961d87e2a03741360e45ebb19fcb1703d23f1e15bb1e2babcafc56ac -b9636b2ffe305e63a1a84bd44fb402442b1799bd5272638287aa87ca548649b23ce8ce7f67be077caed6aa2dbc454b78 -99a30bf0921d854c282b83d438a79f615424f28c2f99d26a05201c93d10378ab2cd94a792b571ddae5d4e0c0013f4006 -8648e3c2f93d70b392443be116b48a863e4b75991bab5db656a4ef3c1e7f645e8d536771dfe4e8d1ceda3be8d32978b0 -ab50dc9e6924c1d2e9d2e335b2d679fc7d1a7632e84964d3bac0c9fe57e85aa5906ec2e7b0399d98ddd022e9b19b5904 -ab729328d98d295f8f3272afaf5d8345ff54d58ff9884da14f17ecbdb7371857fdf2f3ef58080054e9874cc919b46224 -83fa5da7592bd451cad3ad7702b4006332b3aae23beab4c4cb887fa6348317d234bf62a359e665b28818e5410c278a09 -8bdbff566ae9d368f114858ef1f009439b3e9f4649f73efa946e678d6c781d52c69af195df0a68170f5f191b2eac286b -91245e59b4425fd4edb2a61d0d47c1ccc83d3ced8180de34887b9655b5dcda033d48cde0bdc3b7de846d246c053a02e8 -a2cb00721e68f1cad8933947456f07144dc69653f96ceed845bd577d599521ba99cdc02421118971d56d7603ed118cbf -af8cd66d303e808b22ec57860dd909ca64c27ec2c60e26ffecfdc1179d8762ffd2739d87b43959496e9fee4108df71df -9954136812dffcd5d3f167a500e7ab339c15cfc9b3398d83f64b0daa3dd5b9a851204f424a3493b4e326d3de81e50a62 -93252254d12511955f1aa464883ad0da793f84d900fea83e1df8bca0f2f4cf5b5f9acbaec06a24160d33f908ab5fea38 -997cb55c26996586ba436a95566bd535e9c22452ca5d2a0ded2bd175376557fa895f9f4def4519241ff386a063f2e526 -a12c78ad451e0ac911260ade2927a768b50cb4125343025d43474e7f465cdc446e9f52a84609c5e7e87ae6c9b3f56cda -a789d4ca55cbba327086563831b34487d63d0980ba8cf55197c016702ed6da9b102b1f0709ce3da3c53ff925793a3d73 -a5d76acbb76741ce85be0e655b99baa04f7f587347947c0a30d27f8a49ae78cce06e1cde770a8b618d3db402be1c0c4b -873c0366668c8faddb0eb7c86f485718d65f8c4734020f1a18efd5fa123d3ea8a990977fe13592cd01d17e60809cb5ff -b659b71fe70f37573ff7c5970cc095a1dc0da3973979778f80a71a347ef25ad5746b2b9608bad4ab9a4a53a4d7df42d7 -a34cbe05888e5e5f024a2db14cb6dcdc401a9cbd13d73d3c37b348f68688f87c24ca790030b8f84fef9e74b4eab5e412 -94ce8010f85875c045b0f014db93ef5ab9f1f6842e9a5743dce9e4cb872c94affd9e77c1f1d1ab8b8660b52345d9acb9 -adefa9b27a62edc0c5b019ddd3ebf45e4de846165256cf6329331def2e088c5232456d3de470fdce3fa758bfdd387512 -a6b83821ba7c1f83cc9e4529cf4903adb93b26108e3d1f20a753070db072ad5a3689643144bdd9c5ea06bb9a7a515cd0 -a3a9ddedc2a1b183eb1d52de26718151744db6050f86f3580790c51d09226bf05f15111691926151ecdbef683baa992c -a64bac89e7686932cdc5670d07f0b50830e69bfb8c93791c87c7ffa4913f8da881a9d8a8ce8c1a9ce5b6079358c54136 -a77b5a63452cb1320b61ab6c7c2ef9cfbcade5fd4727583751fb2bf3ea330b5ca67757ec1f517bf4d503ec924fe32fbd -8746fd8d8eb99639d8cd0ca34c0d9c3230ed5a312aab1d3d925953a17973ee5aeb66e68667e93caf9cb817c868ea8f3d -88a2462a26558fc1fbd6e31aa8abdc706190a17c27fdc4217ffd2297d1b1f3321016e5c4b2384c5454d5717dc732ed03 -b78893a97e93d730c8201af2e0d3b31cb923d38dc594ffa98a714e627c473d42ea82e0c4d2eeb06862ee22a9b2c54588 -920cc8b5f1297cf215a43f6fc843e379146b4229411c44c0231f6749793d40f07b9af7699fd5d21fd69400b97febe027 -a0f0eafce1e098a6b58c7ad8945e297cd93aaf10bc55e32e2e32503f02e59fc1d5776936577d77c0b1162cb93b88518b -98480ba0064e97a2e7a6c4769b4d8c2a322cfc9a3b2ca2e67e9317e2ce04c6e1108169a20bd97692e1cb1f1423b14908 -83dbbb2fda7e287288011764a00b8357753a6a44794cc8245a2275237f11affdc38977214e463ad67aec032f3dfa37e9 -86442fff37598ce2b12015ff19b01bb8a780b40ad353d143a0f30a06f6d23afd5c2b0a1253716c855dbf445cc5dd6865 -b8a4c60c5171189414887847b9ed9501bff4e4c107240f063e2d254820d2906b69ef70406c585918c4d24f1dd052142b -919f33a98e84015b2034b57b5ffe9340220926b2c6e45f86fd79ec879dbe06a148ae68b77b73bf7d01bd638a81165617 -95c13e78d89474a47fbc0664f6f806744b75dede95a479bbf844db4a7f4c3ae410ec721cb6ffcd9fa9c323da5740d5ae -ab7151acc41fffd8ec6e90387700bcd7e1cde291ea669567295bea1b9dd3f1df2e0f31f3588cd1a1c08af8120aca4921 -80e74c5c47414bd6eeef24b6793fb1fa2d8fb397467045fcff887c52476741d5bc4ff8b6d3387cb53ad285485630537f -a296ad23995268276aa351a7764d36df3a5a3cffd7dbeddbcea6b1f77adc112629fdeffa0918b3242b3ccd5e7587e946 -813d2506a28a2b01cb60f49d6bd5e63c9b056aa56946faf2f33bd4f28a8d947569cfead3ae53166fc65285740b210f86 -924b265385e1646287d8c09f6c855b094daaee74b9e64a0dddcf9ad88c6979f8280ba30c8597b911ef58ddb6c67e9fe3 -8d531513c70c2d3566039f7ca47cd2352fd2d55b25675a65250bdb8b06c3843db7b2d29c626eed6391c238fc651cf350 -82b338181b62fdc81ceb558a6843df767b6a6e3ceedc5485664b4ea2f555904b1a45fbb35f6cf5d96f27da10df82a325 -92e62faaedea83a37f314e1d3cb4faaa200178371d917938e59ac35090be1db4b4f4e0edb78b9c991de202efe4f313d8 -99d645e1b642c2dc065bac9aaa0621bc648c9a8351efb6891559c3a41ba737bd155fb32d7731950514e3ecf4d75980e4 -b34a13968b9e414172fb5d5ece9a39cf2eb656128c3f2f6cc7a9f0c69c6bae34f555ecc8f8837dc34b5e470e29055c78 -a2a0bb7f3a0b23a2cbc6585d59f87cd7e56b2bbcb0ae48f828685edd9f7af0f5edb4c8e9718a0aaf6ef04553ba71f3b7 -8e1a94bec053ed378e524b6685152d2b52d428266f2b6eadd4bcb7c4e162ed21ab3e1364879673442ee2162635b7a4d8 -9944adaff14a85eab81c73f38f386701713b52513c4d4b838d58d4ffa1d17260a6d056b02334850ea9a31677c4b078bd -a450067c7eceb0854b3eca3db6cf38669d72cb7143c3a68787833cbca44f02c0be9bfbe082896f8a57debb13deb2afb1 -8be4ad3ac9ef02f7df09254d569939757101ee2eda8586fefcd8c847adc1efe5bdcb963a0cafa17651befaafb376a531 -90f6de91ea50255f148ac435e08cf2ac00c772a466e38155bd7e8acf9197af55662c7b5227f88589b71abe9dcf7ba343 -86e5a24f0748b106dee2d4d54e14a3b0af45a96cbee69cac811a4196403ebbee17fd24946d7e7e1b962ac7f66dbaf610 -afdd96fbcda7aa73bf9eeb2292e036c25753d249caee3b9c013009cc22e10d3ec29e2aa6ddbb21c4e949b0c0bccaa7f4 -b5a4e7436d5473647c002120a2cb436b9b28e27ad4ebdd7c5f122b91597c507d256d0cbd889d65b3a908531936e53053 -b632414c3da704d80ac2f3e5e0e9f18a3637cdc2ebeb613c29300745582427138819c4e7b0bec3099c1b8739dac1807b -a28df1464d3372ce9f37ef1db33cc010f752156afae6f76949d98cd799c0cf225c20228ae86a4da592d65f0cffe3951b -898b93d0a31f7d3f11f253cb7a102db54b669fd150da302d8354d8e02b1739a47cb9bd88015f3baf12b00b879442464e -96fb88d89a12049091070cb0048a381902965e67a8493e3991eaabe5d3b7ff7eecd5c94493a93b174df3d9b2c9511755 -b899cb2176f59a5cfba3e3d346813da7a82b03417cad6342f19cc8f12f28985b03bf031e856a4743fd7ebe16324805b0 -a60e2d31bc48e0c0579db15516718a03b73f5138f15037491f4dae336c904e312eda82d50862f4debd1622bb0e56d866 -979fc8b987b5cef7d4f4b58b53a2c278bd25a5c0ea6f41c715142ea5ff224c707de38451b0ad3aa5e749aa219256650a -b2a75bff18e1a6b9cf2a4079572e41205741979f57e7631654a3c0fcec57c876c6df44733c9da3d863db8dff392b44a3 -b7a0f0e811222c91e3df98ff7f286b750bc3b20d2083966d713a84a2281744199e664879401e77470d44e5a90f3e5181 -82b74ba21c9d147fbc338730e8f1f8a6e7fc847c3110944eb17a48bea5e06eecded84595d485506d15a3e675fd0e5e62 -a7f44eef817d5556f0d1abcf420301217d23c69dd2988f44d91ea1f1a16c322263cbacd0f190b9ba22b0f141b9267b4f -aadb68164ede84fc1cb3334b3194d84ba868d5a88e4c9a27519eef4923bc4abf81aab8114449496c073c2a6a0eb24114 -b5378605fabe9a8c12a5dc55ef2b1de7f51aedb61960735c08767a565793cea1922a603a6983dc25f7cea738d0f7c40d -a97a4a5cd8d51302e5e670aee78fe6b5723f6cc892902bbb4f131e82ca1dfd5de820731e7e3367fb0c4c1922a02196e3 -8bdfeb15c29244d4a28896f2b2cb211243cd6a1984a3f5e3b0ebe5341c419beeab3304b390a009ffb47588018034b0ea -a9af3022727f2aa2fca3b096968e97edad3f08edcbd0dbca107b892ae8f746a9c0485e0d6eb5f267999b23a845923ed0 -8e7594034feef412f055590fbb15b6322dc4c6ab7a4baef4685bd13d71a83f7d682b5781bdfa0d1c659489ce9c2b8000 -84977ca6c865ebee021c58106c1a4ad0c745949ecc5332948002fd09bd9b890524878d0c29da96fd11207621136421fe -8687551a79158e56b2375a271136756313122132a6670fa51f99a1b5c229ed8eea1655a734abae13228b3ebfd2a825dd -a0227d6708979d99edfc10f7d9d3719fd3fc68b0d815a7185b60307e4c9146ad2f9be2b8b4f242e320d4288ceeb9504c -89f75583a16735f9dd8b7782a130437805b34280ccea8dac6ecaee4b83fe96947e7b53598b06fecfffdf57ffc12cc445 -a0056c3353227f6dd9cfc8e3399aa5a8f1d71edf25d3d64c982910f50786b1e395c508d3e3727ac360e3e040c64b5298 -b070e61a6d813626144b312ded1788a6d0c7cec650a762b2f8df6e4743941dd82a2511cd956a3f141fc81e15f4e092da -b4e6db232e028a1f989bb5fc13416711f42d389f63564d60851f009dcffac01acfd54efa307aa6d4c0f932892d4e62b0 -89b5991a67db90024ddd844e5e1a03ef9b943ad54194ae0a97df775dde1addf31561874f4e40fbc37a896630f3bbda58 -ad0e8442cb8c77d891df49cdb9efcf2b0d15ac93ec9be1ad5c3b3cca1f4647b675e79c075335c1f681d56f14dc250d76 -b5d55a6ae65bb34dd8306806cb49b5ccb1c83a282ee47085cf26c4e648e19a52d9c422f65c1cd7e03ca63e926c5e92ea -b749501347e5ec07e13a79f0cb112f1b6534393458b3678a77f02ca89dca973fa7b30e55f0b25d8b92b97f6cb0120056 -94144b4a3ffc5eec6ba35ce9c245c148b39372d19a928e236a60e27d7bc227d18a8cac9983851071935d8ffb64b3a34f -92bb4f9f85bc8c028a3391306603151c6896673135f8a7aefedd27acb322c04ef5dac982fc47b455d6740023e0dd3ea3 -b9633a4a101461a782fc2aa092e9dbe4e2ad00987578f18cd7cf0021a909951d60fe79654eb7897806795f93c8ff4d1c -809f0196753024821b48a016eca5dbb449a7c55750f25981bb7a4b4c0e0846c09b8f6128137905055fc43a3f0deb4a74 -a27dc9cdd1e78737a443570194a03d89285576d3d7f3a3cf15cc55b3013e42635d4723e2e8fe1d0b274428604b630db9 -861f60f0462e04cd84924c36a28163def63e777318d00884ab8cb64c8df1df0bce5900342163edb60449296484a6c5bf -b7bc23fb4e14af4c4704a944253e760adefeca8caee0882b6bbd572c84434042236f39ae07a8f21a560f486b15d82819 -b9a6eb492d6dd448654214bd01d6dc5ff12067a11537ab82023fc16167507ee25eed2c91693912f4155d1c07ed9650b3 -97678af29c68f9a5e213bf0fb85c265303714482cfc4c2c00b4a1e8a76ed08834ee6af52357b143a1ca590fb0265ea5a -8a15b499e9eca5b6cac3070b5409e8296778222018ad8b53a5d1f6b70ad9bb10c68a015d105c941ed657bf3499299e33 -b487fefede2e8091f2c7bfe85770db2edff1db83d4effe7f7d87bff5ab1ace35e9b823a71adfec6737fede8d67b3c467 -8b51b916402aa2c437fce3bcad6dad3be8301a1a7eab9d163085b322ffb6c62abf28637636fe6114573950117fc92898 -b06a2106d031a45a494adec0881cb2f82275dff9dcdd2bc16807e76f3bec28a6734edd3d54f0be8199799a78cd6228ad -af0a185391bbe2315eb97feac98ad6dd2e5d931d012c621abd6e404a31cc188b286fef14871762190acf086482b2b5e2 -8e78ee8206506dd06eb7729e32fceda3bebd8924a64e4d8621c72e36758fda3d0001af42443851d6c0aea58562870b43 -a1ba52a569f0461aaf90b49b92be976c0e73ec4a2c884752ee52ffb62dd137770c985123d405dfb5de70692db454b54a -8d51b692fa1543c51f6b62b9acb8625ed94b746ef96c944ca02859a4133a5629da2e2ce84e111a7af8d9a5b836401c64 -a7a20d45044cf6492e0531d0b8b26ffbae6232fa05a96ed7f06bdb64c2b0f5ca7ec59d5477038096a02579e633c7a3ff -84df867b98c53c1fcd4620fef133ee18849c78d3809d6aca0fb6f50ff993a053a455993f216c42ab6090fa5356b8d564 -a7227c439f14c48e2577d5713c97a5205feb69acb0b449152842e278fa71e8046adfab468089c8b2288af1fc51fa945b -855189b3a105670779997690876dfaa512b4a25a24931a912c2f0f1936971d2882fb4d9f0b3d9daba77eaf660e9d05d5 -b5696bd6706de51c502f40385f87f43040a5abf99df705d6aac74d88c913b8ecf7a99a63d7a37d9bdf3a941b9e432ff5 -ab997beb0d6df9c98d5b49864ef0b41a2a2f407e1687dfd6089959757ba30ed02228940b0e841afe6911990c74d536c4 -b36b65f85546ebfdbe98823d5555144f96b4ab39279facd19c0de3b8919f105ba0315a0784dce4344b1bc62d8bb4a5a3 -b8371f0e4450788720ac5e0f6cd3ecc5413d33895083b2c168d961ec2b5c3de411a4cc0712481cbe8df8c2fa1a7af006 -98325d8026b810a8b7a114171ae59a57e8bbc9848e7c3df992efc523621729fd8c9f52114ce01d7730541a1ada6f1df1 -8d0e76dbd37806259486cd9a31bc8b2306c2b95452dc395546a1042d1d17863ef7a74c636b782e214d3aa0e8d717f94a -a4e15ead76da0214d702c859fb4a8accdcdad75ed08b865842bd203391ec4cba2dcc916455e685f662923b96ee0c023f -8618190972086ebb0c4c1b4a6c94421a13f378bc961cc8267a301de7390c5e73c3333864b3b7696d81148f9d4843fd02 -85369d6cc7342e1aa15b59141517d8db8baaaeb7ab9670f3ba3905353948d575923d283b7e5a05b13a30e7baf1208a86 -87c51ef42233c24a6da901f28c9a075d9ba3c625687c387ad6757b72ca6b5a8885e6902a3082da7281611728b1e45f26 -aa6348a4f71927a3106ad0ea8b02fc8d8c65531e4ab0bd0a17243e66f35afe252e40ab8eef9f13ae55a72566ffdaff5c -96a3bc976e9d03765cc3fee275fa05b4a84c94fed6b767e23ca689394501e96f56f7a97cffddc579a6abff632bf153be -97dbf96c6176379fdb2b888be4e757b2bca54e74124bd068d3fa1dbd82a011bbeb75079da38e0cd22a761fe208ecad9b -b70cf0a1d14089a4129ec4e295313863a59da8c7e26bf74cc0e704ed7f0ee4d7760090d0ddf7728180f1bf2c5ac64955 -882d664714cc0ffe53cbc9bef21f23f3649824f423c4dbad1f893d22c4687ab29583688699efc4d5101aa08b0c3e267a -80ecb7cc963e677ccaddbe3320831dd6ee41209acf4ed41b16dc4817121a3d86a1aac9c4db3d8c08a55d28257088af32 -a25ba667d832b145f9ce18c3f9b1bd00737aa36db020e1b99752c8ef7d27c6c448982bd8d352e1b6df266b8d8358a8d5 -83734841c13dee12759d40bdd209b277e743b0d08cc0dd1e0b7afd2d65bfa640400eefcf6be4a52e463e5b3d885eeac6 -848d16505b04804afc773aebabb51b36fd8aacfbb0e09b36c0d5d57df3c0a3b92f33e7d5ad0a7006ec46ebb91df42b8c -909a8d793f599e33bb9f1dc4792a507a97169c87cd5c087310bc05f30afcd247470b4b56dec59894c0fb1d48d39bb54e -8e558a8559df84a1ba8b244ece667f858095c50bb33a5381e60fcc6ba586b69693566d8819b4246a27287f16846c1dfa -84d6b69729f5aaa000cd710c2352087592cfbdf20d5e1166977e195818e593fa1a50d1e04566be23163a2523dc1612f1 -9536d262b7a42125d89f4f32b407d737ba8d9242acfc99d965913ab3e043dcac9f7072a43708553562cac4cba841df30 -9598548923ca119d6a15fd10861596601dd1dedbcccca97bb208cdc1153cf82991ea8cc17686fbaa867921065265970c -b87f2d4af6d026e4d2836bc3d390a4a18e98a6e386282ce96744603bab74974272e97ac2da281afa21885e2cbb3a8001 -991ece62bf07d1a348dd22191868372904b9f8cf065ae7aa4e44fd24a53faf6d851842e35fb472895963aa1992894918 -a8c53dea4c665b30e51d22ca6bc1bc78aaf172b0a48e64a1d4b93439b053877ec26cb5221c55efd64fa841bbf7d5aff4 -93487ec939ed8e740f15335b58617c3f917f72d07b7a369befd479ae2554d04deb240d4a14394b26192efae4d2f4f35d -a44793ab4035443f8f2968a40e043b4555960193ffa3358d22112093aadfe2c136587e4139ffd46d91ed4107f61ea5e0 -b13fe033da5f0d227c75927d3dacb06dbaf3e1322f9d5c7c009de75cdcba5e308232838785ab69a70f0bedea755e003f -970a29b075faccd0700fe60d1f726bdebf82d2cc8252f4a84543ebd3b16f91be42a75c9719a39c4096139f0f31393d58 -a4c3eb1f7160f8216fc176fb244df53008ff32f2892363d85254002e66e2de21ccfe1f3b1047589abee50f29b9d507e3 -8c552885eab04ba40922a8f0c3c38c96089c95ff1405258d3f1efe8d179e39e1295cbf67677894c607ae986e4e6b1fb0 -b3671746fa7f848c4e2ae6946894defadd815230b906b419143523cc0597bc1d6c0a4c1e09d49b66b4a2c11cde3a4de3 -937a249a95813a5e2ef428e355efd202e15a37d73e56cfb7e57ea9f943f2ce5ca8026f2f1fd25bf164ba89d07077d858 -83646bdf6053a04aa9e2f112499769e5bd5d0d10f2e13db3ca89bd45c0b3b7a2d752b7d137fb3909f9c62b78166c9339 -b4eac4b91e763666696811b7ed45e97fd78310377ebea1674b58a2250973f80492ac35110ed1240cd9bb2d17493d708c -82db43a99bc6573e9d92a3fd6635dbbb249ac66ba53099c3c0c8c8080b121dd8243cd5c6e36ba0a4d2525bae57f5c89c -a64d6a264a681b49d134c655d5fc7756127f1ee7c93d328820f32bca68869f53115c0d27fef35fe71f7bc4fdaed97348 -8739b7a9e2b4bc1831e7f04517771bc7cde683a5e74e052542517f8375a2f64e53e0d5ac925ef722327e7bb195b4d1d9 -8f337cdd29918a2493515ebb5cf702bbe8ecb23b53c6d18920cc22f519e276ca9b991d3313e2d38ae17ae8bdfa4f8b7e -b0edeab9850e193a61f138ef2739fc42ceec98f25e7e8403bfd5fa34a7bc956b9d0898250d18a69fa4625a9b3d6129da -a9920f26fe0a6d51044e623665d998745c9eca5bce12051198b88a77d728c8238f97d4196f26e43b24f8841500b998d0 -86e655d61502b979eeeeb6f9a7e1d0074f936451d0a1b0d2fa4fb3225b439a3770767b649256fe481361f481a8dbc276 -84d3b32fa62096831cc3bf013488a9f3f481dfe293ae209ed19585a03f7db8d961a7a9dd0db82bd7f62d612707575d9c -81c827826ec9346995ffccf62a241e3b2d32f7357acd1b1f8f7a7dbc97022d3eb51b8a1230e23ce0b401d2e535e8cd78 -94a1e40c151191c5b055b21e86f32e69cbc751dcbdf759a48580951834b96a1eed75914c0d19a38aefd21fb6c8d43d0c -ab890222b44bc21b71f7c75e15b6c6e16bb03371acce4f8d4353ff3b8fcd42a14026589c5ed19555a3e15e4d18bfc3a3 -accb0be851e93c6c8cc64724cdb86887eea284194b10e7a43c90528ed97e9ec71ca69c6fac13899530593756dd49eab2 -b630220aa9e1829c233331413ee28c5efe94ea8ea08d0c6bfd781955078b43a4f92915257187d8526873e6c919c6a1de -add389a4d358c585f1274b73f6c3c45b58ef8df11f9d11221f620e241bf3579fba07427b288c0c682885a700cc1fa28d -a9fe6ca8bf2961a3386e8b8dcecc29c0567b5c0b3bcf3b0f9169f88e372b80151af883871fc5229815f94f43a6f5b2b0 -ad839ae003b92b37ea431fa35998b46a0afc3f9c0dd54c3b3bf7a262467b13ff3c323ada1c1ae02ac7716528bdf39e3e -9356d3fd0edcbbb65713c0f2a214394f831b26f792124b08c5f26e7f734b8711a87b7c4623408da6a091c9aef1f6af3c -896b25b083c35ac67f0af3784a6a82435b0e27433d4d74cd6d1eafe11e6827827799490fb1c77c11de25f0d75f14e047 -8bfa019391c9627e8e5f05c213db625f0f1e51ec68816455f876c7e55b8f17a4f13e5aae9e3fb9e1cf920b1402ee2b40 -8ba3a6faa6a860a8f3ce1e884aa8769ceded86380a86520ab177ab83043d380a4f535fe13884346c5e51bee68da6ab41 -a8292d0844084e4e3bb7af92b1989f841a46640288c5b220fecfad063ee94e86e13d3d08038ec2ac82f41c96a3bfe14d -8229bb030b2fc566e11fd33c7eab7a1bb7b49fed872ea1f815004f7398cb03b85ea14e310ec19e1f23e0bdaf60f8f76c -8cfbf869ade3ec551562ff7f63c2745cc3a1f4d4dc853a0cd42dd5f6fe54228f86195ea8fe217643b32e9f513f34a545 -ac52a3c8d3270ddfe1b5630159da9290a5ccf9ccbdef43b58fc0a191a6c03b8a5974cf6e2bbc7bd98d4a40a3581482d7 -ab13decb9e2669e33a7049b8eca3ca327c40dea15ad6e0e7fa63ed506db1d258bc36ac88b35f65cae0984e937eb6575d -b5e748eb1a7a1e274ff0cc56311c198f2c076fe4b7e73e5f80396fe85358549df906584e6bb2c8195b3e2be7736850a5 -b5cb911325d8f963c41f691a60c37831c7d3bbd92736efa33d1f77a22b3fde7f283127256c2f47e197571e6fe0b46149 -8a01dc6ed1b55f26427a014faa347130738b191a06b800e32042a46c13f60b49534520214359d68eb2e170c31e2b8672 -a72fa874866e19b2efb8e069328362bf7921ec375e3bcd6b1619384c3f7ee980f6cf686f3544e9374ff54b4d17a1629c -8db21092f7c5f110fba63650b119e82f4b42a997095d65f08f8237b02dd66fdf959f788df2c35124db1dbd330a235671 -8c65d50433d9954fe28a09fa7ba91a70a590fe7ba6b3060f5e4be0f6cef860b9897fa935fb4ebc42133524eb071dd169 -b4614058e8fa21138fc5e4592623e78b8982ed72aa35ee4391b164f00c68d277fa9f9eba2eeefc890b4e86eba5124591 -ab2ad3a1bce2fbd55ca6b7c23786171fe1440a97d99d6df4d80d07dd56ac2d7203c294b32fc9e10a6c259381a73f24a1 -812ae3315fdc18774a8da3713a4679e8ed10b9405edc548c00cacbe25a587d32040566676f135e4723c5dc25df5a22e9 -a464b75f95d01e5655b54730334f443c8ff27c3cb79ec7af4b2f9da3c2039c609908cd128572e1fd0552eb597e8cef8d -a0db3172e93ca5138fe419e1c49a1925140999f6eff7c593e5681951ee0ec1c7e454c851782cbd2b8c9bc90d466e90e0 -806db23ba7d00b87d544eed926b3443f5f9c60da6b41b1c489fba8f73593b6e3b46ebfcab671ee009396cd77d5e68aa1 -8bfdf2c0044cc80260994e1c0374588b6653947b178e8b312be5c2a05e05767e98ea15077278506aee7df4fee1aaf89e -827f6558c16841b5592ff089c9c31e31eb03097623524394813a2e4093ad2d3f8f845504e2af92195aaa8a1679d8d692 -925c4f8eab2531135cd71a4ec88e7035b5eea34ba9d799c5898856080256b4a15ed1a746e002552e2a86c9c157e22e83 -a9f9a368f0e0b24d00a35b325964c85b69533013f9c2cfad9708be5fb87ff455210f8cb8d2ce3ba58ca3f27495552899 -8ac0d3bebc1cae534024187e7c71f8927ba8fcc6a1926cb61c2b6c8f26bb7831019e635a376146c29872a506784a4aaa -97c577be2cbbfdb37ad754fae9df2ada5fc5889869efc7e18a13f8e502fbf3f4067a509efbd46fd990ab47ce9a70f5a8 -935e7d82bca19f16614aa43b4a3474e4d20d064e4bfdf1cea2909e5c9ab72cfe3e54dc50030e41ee84f3588cebc524e9 -941aafc08f7c0d94cebfbb1f0aad5202c02e6e37f2c12614f57e727efa275f3926348f567107ee6d8914dd71e6060271 -af0fbc1ba05b4b5b63399686df3619968be5d40073de0313cbf5f913d3d4b518d4c249cdd2176468ccaa36040a484f58 -a0c414f23f46ca6d69ce74c6f8a00c036cb0edd098af0c1a7d39c802b52cfb2d5dbdf93fb0295453d4646e2af7954d45 -909cf39e11b3875bb63b39687ae1b5d1f5a15445e39bf164a0b14691b4ddb39a8e4363f584ef42213616abc4785b5d66 -a92bac085d1194fbd1c88299f07a061d0bdd3f980b663e81e6254dbb288bf11478c0ee880e28e01560f12c5ccb3c0103 -841705cd5cd76b943e2b7c5e845b9dd3c8defe8ef67e93078d6d5e67ade33ad4b0fd413bc196f93b0a4073c855cd97d4 -8e7eb8364f384a9161e81d3f1d52ceca9b65536ae49cc35b48c3e2236322ba4ae9973e0840802d9fa4f4d82ea833544f -aed3ab927548bc8bec31467ba80689c71a168e34f50dcb6892f19a33a099f5aa6b3f9cb79f5c0699e837b9a8c7f27efe -b8fbf7696210a36e20edabd77839f4dfdf50d6d015cdf81d587f90284a9bcef7d2a1ff520728d7cc69a4843d6c20dedd -a9d533769ce6830211c884ae50a82a7bf259b44ac71f9fb11f0296fdb3981e6b4c1753fe744647b247ebc433a5a61436 -8b4bdf90d33360b7f428c71cde0a49fb733badba8c726876945f58c620ce7768ae0e98fc8c31fa59d8955a4823336bb1 -808d42238e440e6571c59e52a35ae32547d502dc24fd1759d8ea70a7231a95859baf30b490a4ba55fa2f3aaa11204597 -85594701f1d2fee6dc1956bc44c7b31db93bdeec2f3a7d622c1a08b26994760773e3d57521a44cfd7e407ac3fd430429 -a66de045ce7173043a6825e9dc440ac957e2efb6df0a337f4f8003eb0c719d873a52e6eba3cb0d69d977ca37d9187674 -87a1c6a1fdff993fa51efa5c3ba034c079c0928a7d599b906336af7c2dcab9721ceaf3108c646490af9dff9a754f54b3 -926424223e462ceb75aed7c22ade8a7911a903b7e5dd4bc49746ddce8657f4616325cd12667d4393ac52cdd866396d0e -b5dc96106593b42b30f06f0b0a1e0c1aafc70432e31807252d3674f0b1ea5e58eac8424879d655c9488d85a879a3e572 -997ca0987735cc716507cb0124b1d266d218b40c9d8e0ecbf26a1d65719c82a637ce7e8be4b4815d307df717bde7c72a -92994d3f57a569b7760324bb5ae4e8e14e1633d175dab06aa57b8e391540e05f662fdc08b8830f489a063f59b689a688 -a8087fcc6aa4642cb998bea11facfe87eb33b90a9aa428ab86a4124ad032fc7d2e57795311a54ec9f55cc120ebe42df1 -a9bd7d1de6c0706052ca0b362e2e70e8c8f70f1f026ea189b4f87a08ce810297ebfe781cc8004430776c54c1a05ae90c -856d33282e8a8e33a3d237fb0a0cbabaf77ba9edf2fa35a831fdafcadf620561846aa6cbb6bdc5e681118e1245834165 -9524a7aa8e97a31a6958439c5f3339b19370f03e86b89b1d02d87e4887309dbbe9a3a8d2befd3b7ed5143c8da7e0a8ad -824fdf433e090f8acbd258ac7429b21f36f9f3b337c6d0b71d1416a5c88a767883e255b2888b7c906dd2e9560c4af24c -88c7fee662ca7844f42ed5527996b35723abffd0d22d4ca203b9452c639a5066031207a5ae763dbc0865b3299d19b1ec -919dca5c5595082c221d5ab3a5bc230f45da7f6dec4eb389371e142c1b9c6a2c919074842479c2844b72c0d806170c0c -b939be8175715e55a684578d8be3ceff3087f60fa875fff48e52a6e6e9979c955efef8ff67cfa2b79499ea23778e33b0 -873b6db725e7397d11bc9bed9ac4468e36619135be686790a79bc6ed4249058f1387c9a802ea86499f692cf635851066 -aeae06db3ec47e9e5647323fa02fac44e06e59b885ad8506bf71b184ab3895510c82f78b6b22a5d978e8218e7f761e9f -b99c0a8359c72ab88448bae45d4bf98797a26bca48b0d4460cd6cf65a4e8c3dd823970ac3eb774ae5d0cea4e7fadf33e -8f10c8ec41cdfb986a1647463076a533e6b0eec08520c1562401b36bb063ac972aa6b28a0b6ce717254e35940b900e3c -a106d9be199636d7add43b942290269351578500d8245d4aae4c083954e4f27f64740a3138a66230391f2d0e6043a8de -a469997908244578e8909ff57cffc070f1dbd86f0098df3cfeb46b7a085cfecc93dc69ee7cad90ff1dc5a34d50fe580c -a4ef087bea9c20eb0afc0ee4caba7a9d29dfa872137828c721391273e402fb6714afc80c40e98bbd8276d3836bffa080 -b07a013f73cd5b98dae0d0f9c1c0f35bff8a9f019975c4e1499e9bee736ca6fcd504f9bc32df1655ff333062382cff04 -b0a77188673e87cc83348c4cc5db1eecf6b5184e236220c8eeed7585e4b928db849944a76ec60ef7708ef6dac02d5592 -b1284b37e59b529f0084c0dacf0af6c0b91fc0f387bf649a8c74819debf606f7b07fc3e572500016fb145ec2b24e9f17 -97b20b5b4d6b9129da185adfbf0d3d0b0faeba5b9715f10299e48ea0521709a8296a9264ce77c275a59c012b50b6519a -b9d37e946fae5e4d65c1fbfacc8a62e445a1c9d0f882e60cca649125af303b3b23af53c81d7bac544fb7fcfc7a314665 -8e5acaac379f4bb0127efbef26180f91ff60e4c525bc9b798fc50dfaf4fe8a5aa84f18f3d3cfb8baead7d1e0499af753 -b0c0b8ab1235bf1cda43d4152e71efc1a06c548edb964eb4afceb201c8af24240bf8ab5cae30a08604e77432b0a5faf0 -8cc28d75d5c8d062d649cbc218e31c4d327e067e6dbd737ec0a35c91db44fbbd0d40ec424f5ed79814add16947417572 -95ae6219e9fd47efaa9cb088753df06bc101405ba50a179d7c9f7c85679e182d3033f35b00dbba71fdcd186cd775c52e -b5d28fa09f186ebc5aa37453c9b4d9474a7997b8ae92748ecb940c14868792292ac7d10ade01e2f8069242b308cf97e5 -8c922a0faa14cc6b7221f302df3342f38fc8521ec6c653f2587890192732c6da289777a6cd310747ea7b7d104af95995 -b9ad5f660b65230de54de535d4c0fcae5bc6b59db21dea5500fdc12eea4470fb8ea003690fdd16d052523418d5e01e8c -a39a9dd41a0ff78c82979483731f1cd68d3921c3e9965869662c22e02dde3877802e180ba93f06e7346f96d9fa9261d2 -8b32875977ec372c583b24234c27ed73aef00cdff61eb3c3776e073afbdeade548de9497c32ec6d703ff8ad0a5cb7fe4 -9644cbe755a5642fe9d26cfecf170d3164f1848c2c2e271d5b6574a01755f3980b3fc870b98cf8528fef6ecef4210c16 -81ea9d1fdd9dd66d60f40ce0712764b99da9448ae0b300f8324e1c52f154e472a086dda840cb2e0b9813dc8ce8afd4b5 -906aaa4a7a7cdf01909c5cfbc7ded2abc4b869213cbf7c922d4171a4f2e637e56f17020b852ad339d83b8ac92f111666 -939b5f11acbdeff998f2a080393033c9b9d8d5c70912ea651c53815c572d36ee822a98d6dfffb2e339f29201264f2cf4 -aba4898bf1ccea9b9e2df1ff19001e05891581659c1cbbde7ee76c349c7fc7857261d9785823c9463a8aea3f40e86b38 -83ca1a56b8a0be4820bdb5a9346357c68f9772e43f0b887729a50d2eb2a326bbcede676c8bf2e51d7c89bbd8fdb778a6 -94e86e9fe6addfe2c3ee3a547267ed921f4230d877a85bb4442c2d9350c2fa9a9c54e6fe662de82d1a2407e4ab1691c2 -a0cc3bdef671a59d77c6984338b023fa2b431b32e9ed2abe80484d73edc6540979d6f10812ecc06d4d0c5d4eaca7183c -b5343413c1b5776b55ea3c7cdd1f3af1f6bd802ea95effe3f2b91a523817719d2ecc3f8d5f3cc2623ace7e35f99ca967 -92085d1ed0ed28d8cabe3e7ff1905ed52c7ceb1eac5503760c52fb5ee3a726aba7c90b483c032acc3f166b083d7ec370 -8ec679520455275cd957fca8122724d287db5df7d29f1702a322879b127bff215e5b71d9c191901465d19c86c8d8d404 -b65eb2c63d8a30332eb24ee8a0c70156fc89325ebbb38bacac7cf3f8636ad8a472d81ccca80423772abc00192d886d8a -a9fe1c060b974bee4d590f2873b28635b61bfcf614e61ff88b1be3eee4320f4874e21e8d666d8ac8c9aba672efc6ecae -b3fe2a9a389c006a831dea7e777062df84b5c2803f9574d7fbe10b7e1c125817986af8b6454d6be9d931a5ac94cfe963 -95418ad13b734b6f0d33822d9912c4c49b558f68d08c1b34a0127fcfa666bcae8e6fda8832d2c75bb9170794a20e4d7c -a9a7df761e7f18b79494bf429572140c8c6e9d456c4d4e336184f3f51525a65eb9582bea1e601bdb6ef8150b7ca736a5 -a0de03b1e75edf7998c8c1ac69b4a1544a6fa675a1941950297917366682e5644a4bda9cdeedfaf9473d7fccd9080b0c -a61838af8d95c95edf32663a68f007d95167bf6e41b0c784a30b22d8300cfdd5703bd6d16e86396638f6db6ae7e42a85 -8866d62084d905c145ff2d41025299d8b702ac1814a7dec4e277412c161bc9a62fed735536789cb43c88693c6b423882 -91da22c378c81497fe363e7f695c0268443abee50f8a6625b8a41e865638a643f07b157ee566de09ba09846934b4e2d7 -941d21dd57c9496aa68f0c0c05507405fdd413acb59bc668ce7e92e1936c68ec4b065c3c30123319884149e88228f0b2 -a77af9b094bc26966ddf2bf9e1520c898194a5ccb694915950dadc204facbe3066d3d89f50972642d76b14884cfbaa21 -8e76162932346869f4618bde744647f7ab52ab498ad654bdf2a4feeb986ac6e51370841e5acbb589e38b6e7142bb3049 -b60979ace17d6937ece72e4f015da4657a443dd01cebc7143ef11c09e42d4aa8855999a65a79e2ea0067f31c9fc2ab0f -b3e2ffdd5ee6fd110b982fd4fad4b93d0fca65478f986d086eeccb0804960bfaa1919afa743c2239973ea65091fe57d2 -8ce0ce05e7d7160d44574011da687454dbd3c8b8290aa671731b066e2c82f8cf2d63cb8e932d78c6122ec610e44660e6 -ab005dd8d297045c39e2f72fb1c48edb501ccf3575d3d04b9817b3afee3f0bb0f3f53f64bda37d1d9cde545aae999bae -95bd7edb4c4cd60e3cb8a72558845a3cce6bb7032ccdf33d5a49ebb6ddf203bc3c79e7b7e550735d2d75b04c8b2441e8 -889953ee256206284094e4735dbbb17975bafc7c3cb94c9fbfee4c3e653857bfd49e818f64a47567f721b98411a3b454 -b188423e707640ab0e75a061e0b62830cde8afab8e1ad3dae30db69ffae4e2fc005bababbdcbd7213b918ed4f70e0c14 -a97e0fafe011abd70d4f99a0b36638b3d6e7354284588f17a88970ed48f348f88392779e9a038c6cbc9208d998485072 -87db11014a91cb9b63e8dfaa82cdebca98272d89eb445ee1e3ff9dbaf2b3fad1a03b888cffc128e4fe208ed0dddece0f -aad2e40364edd905d66ea4ac9d51f9640d6fda9a54957d26ba233809851529b32c85660fa401dbee3679ec54fa6dd966 -863e99336ca6edf03a5a259e59a2d0f308206e8a2fb320cfc0be06057366df8e0f94b33a28f574092736b3c5ada84270 -b34bcc56a057589f34939a1adc51de4ff6a9f4fee9c7fa9aa131e28d0cf0759a0c871b640162acdfbf91f3f1b59a3703 -935dd28f2896092995c5eff1618e5b6efe7a40178888d7826da9b0503c2d6e68a28e7fac1a334e166d0205f0695ef614 -b842cd5f8f5de5ca6c68cb4a5c1d7b451984930eb4cc18fd0934d52fdc9c3d2d451b1c395594d73bc3451432bfba653f -9014537885ce2debad736bc1926b25fdab9f69b216bf024f589c49dc7e6478c71d595c3647c9f65ff980b14f4bb2283b -8e827ccca1dd4cd21707140d10703177d722be0bbe5cac578db26f1ef8ad2909103af3c601a53795435b27bf95d0c9ed -8a0b8ad4d466c09d4f1e9167410dbe2edc6e0e6229d4b3036d30f85eb6a333a18b1c968f6ca6d6889bb08fecde017ef4 -9241ee66c0191b06266332dc9161dede384c4bb4e116dbd0890f3c3790ec5566da4568243665c4725b718ac0f6b5c179 -aeb4d5fad81d2b505d47958a08262b6f1b1de9373c2c9ba6362594194dea3e002ab03b8cbb43f867be83065d3d370f19 -8781bc83bb73f7760628629fe19e4714b494dbed444c4e4e4729b7f6a8d12ee347841a199888794c2234f51fa26fc2b9 -b58864f0acd1c2afa29367e637cbde1968d18589245d9936c9a489c6c495f54f0113ecdcbe4680ac085dd3c397c4d0c3 -94a24284afaeead61e70f3e30f87248d76e9726759445ca18cdb9360586c60cc9f0ec1c397f9675083e0b56459784e2e -aed358853f2b54dcbddf865e1816c2e89be12e940e1abfa661e2ee63ffc24a8c8096be2072fa83556482c0d89e975124 -b95374e6b4fc0765708e370bc881e271abf2e35c08b056a03b847e089831ef4fe3124b9c5849d9c276eb2e35b3daf264 -b834cdbcfb24c8f84bfa4c552e7fadc0028a140952fd69ed13a516e1314a4cd35d4b954a77d51a1b93e1f5d657d0315d -8fb6d09d23bfa90e7443753d45a918d91d75d8e12ec7d016c0dfe94e5c592ba6aaf483d2f16108d190822d955ad9cdc3 -aa315cd3c60247a6ad4b04f26c5404c2713b95972843e4b87b5a36a89f201667d70f0adf20757ebe1de1b29ae27dda50 -a116862dca409db8beff5b1ccd6301cdd0c92ca29a3d6d20eb8b87f25965f42699ca66974dd1a355200157476b998f3b -b4c2f5fe173c4dc8311b60d04a65ce1be87f070ac42e13cd19c6559a2931c6ee104859cc2520edebbc66a13dc7d30693 -8d4a02bf99b2260c334e7d81775c5cf582b00b0c982ce7745e5a90624919028278f5e9b098573bad5515ce7fa92a80c8 -8543493bf564ce6d97bd23be9bff1aba08bd5821ca834f311a26c9139c92a48f0c2d9dfe645afa95fec07d675d1fd53b -9344239d13fde08f98cb48f1f87d34cf6abe8faecd0b682955382a975e6eed64e863fa19043290c0736261622e00045c -aa49d0518f343005ca72b9e6c7dcaa97225ce6bb8b908ebbe7b1a22884ff8bfb090890364e325a0d414ad180b8f161d1 -907d7fd3e009355ab326847c4a2431f688627faa698c13c03ffdd476ecf988678407f029b8543a475dcb3dafdf2e7a9c -845f1f10c6c5dad2adc7935f5cd2e2b32f169a99091d4f1b05babe7317b9b1cdce29b5e62f947dc621b9acbfe517a258 -8f3be8e3b380ea6cdf9e9c237f5e88fd5a357e5ded80ea1fc2019810814de82501273b4da38916881125b6fa0cfd4459 -b9c7f487c089bf1d20c822e579628db91ed9c82d6ca652983aa16d98b4270c4da19757f216a71b9c13ddee3e6e43705f -8ba2d8c88ad2b872db104ea8ddbb006ec2f3749fd0e19298a804bb3a5d94de19285cc7fb19fee58a66f7851d1a66c39f -9375ecd3ed16786fe161af5d5c908f56eeb467a144d3bbddfc767e90065b7c94fc53431adebecba2b6c9b5821184d36e -a49e069bfadb1e2e8bff6a4286872e2a9765d62f0eaa4fcb0e5af4bbbed8be3510fb19849125a40a8a81d1e33e81c3eb -9522cc66757b386aa6b88619525c8ce47a5c346d590bb3647d12f991e6c65c3ab3c0cfc28f0726b6756c892eae1672be -a9a0f1f51ff877406fa83a807aeb17b92a283879f447b8a2159653db577848cc451cbadd01f70441e351e9ed433c18bc -8ff7533dcff6be8714df573e33f82cf8e9f2bcaaa43e939c4759d52b754e502717950de4b4252fb904560fc31dce94a4 -959724671e265a28d67c29d95210e97b894b360da55e4cf16e6682e7912491ed8ca14bfaa4dce9c25a25b16af580494f -92566730c3002f4046c737032487d0833c971e775de59fe02d9835c9858e2e3bc37f157424a69764596c625c482a2219 -a84b47ceff13ed9c3e5e9cdf6739a66d3e7c2bd8a6ba318fefb1a9aecf653bb2981da6733ddb33c4b0a4523acc429d23 -b4ddf571317e44f859386d6140828a42cf94994e2f1dcbcc9777f4eebbfc64fc1e160b49379acc27c4672b8e41835c5d -8ab95c94072b853d1603fdd0a43b30db617d13c1d1255b99075198e1947bfa5f59aed2b1147548a1b5e986cd9173d15c -89511f2eab33894fd4b3753d24249f410ff7263052c1fef6166fc63a79816656b0d24c529e45ccce6be28de6e375d916 -a0866160ca63d4f2be1b4ea050dac6b59db554e2ebb4e5b592859d8df339b46fd7cb89aaed0951c3ee540aee982c238a -8fcc5cbba1b94970f5ff2eb1922322f5b0aa7d918d4b380c9e7abfd57afd8b247c346bff7b87af82efbce3052511cd1b -99aeb2a5e846b0a2874cca02c66ed40d5569eb65ab2495bc3f964a092e91e1517941f2688e79f8cca49cd3674c4e06dc -b7a096dc3bad5ca49bee94efd884aa3ff5615cf3825cf95fbe0ce132e35f46581d6482fa82666c7ef5f1643eaee8f1ca -94393b1da6eaac2ffd186b7725eca582f1ddc8cdd916004657f8a564a7c588175cb443fc6943b39029f5bbe0add3fad8 -884b85fe012ccbcd849cb68c3ad832d83b3ef1c40c3954ffdc97f103b1ed582c801e1a41d9950f6bddc1d11f19d5ec76 -b00061c00131eded8305a7ce76362163deb33596569afb46fe499a7c9d7a0734c084d336b38d168024c2bb42b58e7660 -a439153ac8e6ca037381e3240e7ba08d056c83d7090f16ed538df25901835e09e27de2073646e7d7f3c65056af6e4ce7 -830fc9ca099097d1f38b90e6843dc86f702be9d20bdacc3e52cae659dc41df5b8d2c970effa6f83a5229b0244a86fe22 -b81ea2ffaaff2bb00dd59a9ab825ba5eed4db0d8ac9c8ed1a632ce8f086328a1cddd045fbe1ace289083c1325881b7e7 -b51ea03c58daf2db32c99b9c4789b183365168cb5019c72c4cc91ac30b5fb7311d3db76e6fa41b7cd4a8c81e2f6cdc94 -a4170b2c6d09ca5beb08318730419b6f19215ce6c631c854116f904be3bc30dd85a80c946a8ab054d3e307afaa3f8fbc -897cc42ff28971ff54d2a55dd6b35cfb8610ac902f3c06e3a5cea0e0a257e870c471236a8e84709211c742a09c5601a6 -a18f2e98d389dace36641621488664ecbb422088ab03b74e67009b8b8acacaaa24fdcf42093935f355207d934adc52a8 -92adcfb678cc2ba19c866f3f2b988fdcb4610567f3ab436cc0cb9acaf5a88414848d71133ebdbec1983e38e6190f1b5f -a86d43c2ce01b366330d3b36b3ca85f000c3548b8297e48478da1ee7d70d8576d4650cba7852ed125c0d7cb6109aa7f3 -8ed31ceed9445437d7732dce78a762d72ff32a7636bfb3fd7974b7ae15db414d8184a1766915244355deb354fbc5803b -9268f70032584f416e92225d65af9ea18c466ebc7ae30952d56a4e36fd9ea811dde0a126da9220ba3c596ec54d8a335e -9433b99ee94f2d3fbdd63b163a2bdf440379334c52308bd24537f7defd807145a062ff255a50d119a7f29f4b85d250e3 -90ce664f5e4628a02278f5cf5060d1a34f123854634b1870906e5723ac9afd044d48289be283b267d45fcbf3f4656aaf -aaf21c4d59378bb835d42ae5c5e5ab7a3c8c36a59e75997989313197752b79a472d866a23683b329ea69b048b87fa13e -b83c0589b304cec9ede549fde54f8a7c2a468c6657da8c02169a6351605261202610b2055c639b9ed2d5b8c401fb8f56 -9370f326ea0f170c2c05fe2c5a49189f20aec93b6b18a5572a818cd4c2a6adb359e68975557b349fb54f065d572f4c92 -ac3232fa5ce6f03fca238bef1ce902432a90b8afce1c85457a6bee5571c033d4bceefafc863af04d4e85ac72a4d94d51 -80d9ea168ff821b22c30e93e4c7960ce3ad3c1e6deeebedd342a36d01bd942419b187e2f382dbfd8caa34cca08d06a48 -a387a3c61676fb3381eefa2a45d82625635a666e999aba30e3b037ec9e040f414f9e1ad9652abd3bcad63f95d85038db -a1b229fe32121e0b391b0f6e0180670b9dc89d79f7337de4c77ea7ad0073e9593846f06797c20e923092a08263204416 -92164a9d841a2b828cedf2511213268b698520f8d1285852186644e9a0c97512cafa4bfbe29af892c929ebccd102e998 -82ee2fa56308a67c7db4fd7ef539b5a9f26a1c2cc36da8c3206ba4b08258fbb3cec6fe5cdbd111433fb1ba2a1e275927 -8c77bfe9e191f190a49d46f05600603fa42345592539b82923388d72392404e0b29a493a15e75e8b068dddcd444c2928 -80b927f93ccf79dcf5c5b20bcf5a7d91d7a17bc0401bb7cc9b53a6797feac31026eb114257621f5a64a52876e4474cc1 -b6b68b6501c37804d4833d5a063dd108a46310b1400549074e3cac84acc6d88f73948b7ad48d686de89c1ec043ae8c1a -ab3da00f9bdc13e3f77624f58a3a18fc3728956f84b5b549d62f1033ae4b300538e53896e2d943f160618e05af265117 -b6830e87233b8eace65327fdc764159645b75d2fd4024bf8f313b2dd5f45617d7ecfb4a0b53ccafb5429815a9a1adde6 -b9251cfe32a6dc0440615aadcd98b6b1b46e3f4e44324e8f5142912b597ee3526bea2431e2b0282bb58f71be5b63f65e -af8d70711e81cdddfb39e67a1b76643292652584c1ce7ce4feb1641431ad596e75c9120e85f1a341e7a4da920a9cdd94 -98cd4e996594e89495c078bfd52a4586b932c50a449a7c8dfdd16043ca4cda94dafbaa8ad1b44249c99bbcc52152506e -b9fc6d1c24f48404a4a64fbe3e43342738797905db46e4132aee5f086aaa4c704918ad508aaefa455cfe1b36572e6242 -a365e871d30ba9291cedaba1be7b04e968905d003e9e1af7e3b55c5eb048818ae5b913514fb08b24fb4fbdccbb35d0b8 -93bf99510971ea9af9f1e364f1234c898380677c8e8de9b0dd24432760164e46c787bc9ec42a7ad450500706cf247b2d -b872f825a5b6e7b9c7a9ddfeded3516f0b1449acc9b4fd29fc6eba162051c17416a31e5be6d3563f424d28e65bab8b8f -b06b780e5a5e8eb4f4c9dc040f749cf9709c8a4c9ef15e925f442b696e41e5095db0778a6c73bcd329b265f2c6955c8b -848f1a981f5fc6cd9180cdddb8d032ad32cdfa614fc750d690dbae36cc0cd355cbf1574af9b3ffc8b878f1b2fafb9544 -a03f48cbff3e9e8a3a655578051a5ae37567433093ac500ed0021c6250a51b767afac9bdb194ee1e3eac38a08c0eaf45 -b5be78ce638ff8c4aa84352b536628231d3f7558c5be3bf010b28feac3022e64691fa672f358c8b663904aebe24a54ed -a9d4da70ff676fa55d1728ba6ab03b471fa38b08854d99e985d88c2d050102d8ccffbe1c90249a5607fa7520b15fe791 -8fe9f7092ffb0b69862c8e972fb1ecf54308c96d41354ed0569638bb0364f1749838d6d32051fff1599112978c6e229c -ae6083e95f37770ecae0df1e010456f165d96cfe9a7278c85c15cffd61034081ce5723e25e2bede719dc9341ec8ed481 -a260891891103089a7afbd9081ea116cfd596fd1015f5b65e10b0961eb37fab7d09c69b7ce4be8bf35e4131848fb3fe4 -8d729fa32f6eb9fd2f6a140bef34e8299a2f3111bffd0fe463aa8622c9d98bfd31a1df3f3e87cd5abc52a595f96b970e -a30ec6047ae4bc7da4daa7f4c28c93aedb1112cfe240e681d07e1a183782c9ff6783ac077c155af23c69643b712a533f -ac830726544bfe7b5467339e5114c1a75f2a2a8d89453ce86115e6a789387e23551cd64620ead6283dfa4538eb313d86 -8445c135b7a48068d8ed3e011c6d818cfe462b445095e2fbf940301e50ded23f272d799eea47683fc027430ce14613ef -95785411715c9ae9d8293ce16a693a2aa83e3cb1b4aa9f76333d0da2bf00c55f65e21e42e50e6c5772ce213dd7b4f7a0 -b273b024fa18b7568c0d1c4d2f0c4e79ec509dafac8c5951f14192d63ddbcf2d8a7512c1c1b615cc38fa3e336618e0c5 -a78b9d3ea4b6a90572eb27956f411f1d105fdb577ee2ffeec9f221da9b45db84bfe866af1f29597220c75e0c37a628d8 -a4be2bf058c36699c41513c4d667681ce161a437c09d81383244fc55e1c44e8b1363439d0cce90a3e44581fb31d49493 -b6eef13040f17dd4eba22aaf284d2f988a4a0c4605db44b8d2f4bf9567ac794550b543cc513c5f3e2820242dd704152e -87eb00489071fa95d008c5244b88e317a3454652dcb1c441213aa16b28cd3ecaa9b22fec0bdd483c1df71c37119100b1 -92d388acdcb49793afca329cd06e645544d2269234e8b0b27d2818c809c21726bc9cf725651b951e358a63c83dedee24 -ae27e219277a73030da27ab5603c72c8bd81b6224b7e488d7193806a41343dff2456132274991a4722fdb0ef265d04cd -97583e08ecb82bbc27c0c8476d710389fa9ffbead5c43001bd36c1b018f29faa98de778644883e51870b69c5ffb558b5 -90a799a8ce73387599babf6b7da12767c0591cadd36c20a7990e7c05ea1aa2b9645654ec65308ee008816623a2757a6a -a1b47841a0a2b06efd9ab8c111309cc5fc9e1d5896b3e42ed531f6057e5ade8977c29831ce08dbda40348386b1dcc06d -b92b8ef59bbddb50c9457691bc023d63dfcc54e0fd88bd5d27a09e0d98ac290fc90e6a8f6b88492043bf7c87fac8f3e4 -a9d6240b07d62e22ec8ab9b1f6007c975a77b7320f02504fc7c468b4ee9cfcfd945456ff0128bc0ef2174d9e09333f8d -8e96534c94693226dc32bca79a595ca6de503af635f802e86442c67e77564829756961d9b701187fe91318da515bf0e6 -b6ba290623cd8dd5c2f50931c0045d1cfb0c30877bc8fe58cbc3ff61ee8da100045a39153916efa1936f4aee0892b473 -b43baa7717fac02d4294f5b3bb5e58a65b3557747e3188b482410388daac7a9c177f762d943fd5dcf871273921213da8 -b9cf00f8fb5e2ef2b836659fece15e735060b2ea39b8e901d3dcbdcf612be8bf82d013833718c04cd46ffaa70b85f42e -8017d0c57419e414cbba504368723e751ef990cc6f05dad7b3c2de6360adc774ad95512875ab8337d110bf39a42026fa -ae7401048b838c0dcd4b26bb6c56d79d51964a0daba780970b6c97daee4ea45854ea0ac0e4139b3fe60dac189f84df65 -887b237b0cd0f816b749b21db0b40072f9145f7896c36916296973f9e6990ede110f14e5976c906d08987c9836cca57f -a88c3d5770148aee59930561ca1223aceb2c832fb5417e188dca935905301fc4c6c2c9270bc1dff7add490a125eb81c6 -b6cf9b02c0cd91895ad209e38c54039523f137b5848b9d3ad33ae43af6c20c98434952db375fe378de7866f2d0e8b18a -84ef3d322ff580c8ad584b1fe4fe346c60866eb6a56e982ba2cf3b021ecb1fdb75ecc6c29747adda86d9264430b3f816 -a0561c27224baf0927ad144cb71e31e54a064c598373fcf0d66aebf98ab7af1d8e2f343f77baefff69a6da750a219e11 -aa5cc43f5b8162b016f5e1b61214c0c9d15b1078911c650b75e6cdfb49b85ee04c6739f5b1687d15908444f691f732de -ad4ac099b935589c7b8fdfdf3db332b7b82bb948e13a5beb121ebd7db81a87d278024a1434bcf0115c54ca5109585c3d -8a00466abf3f109a1dcd19e643b603d3af23d42794ef8ca2514dd507ecea44a031ac6dbc18bd02f99701168b25c1791e -b00b5900dfad79645f8bee4e5adc7b84eb22e5b1e67df77ccb505b7fc044a6c08a8ea5faca662414eb945f874f884cea -950e204e5f17112250b22ea6bb8423baf522fc0af494366f18fe0f949f51d6e6812074a80875cf1ed9c8e7420058d541 -91e5cbf8bb1a1d50c81608c9727b414d0dd2fb467ebc92f100882a3772e54f94979cfdf8e373fdef7c7fcdd60fec9e00 -a093f6a857b8caaff80599c2e89c962b415ecbaa70d8fd973155fa976a284c6b29a855f5f7a3521134d00d2972755188 -b4d55a3551b00da54cc010f80d99ddd2544bde9219a3173dfaadf3848edc7e4056ab532fb75ac26f5f7141e724267663 -a03ea050fc9b011d1b04041b5765d6f6453a93a1819cd9bd6328637d0b428f08526466912895dcc2e3008ee58822e9a7 -99b12b3665e473d01bc6985844f8994fb65cb15745024fb7af518398c4a37ff215da8f054e8fdf3286984ae36a73ca5e -9972c7e7a7fb12e15f78d55abcaf322c11249cd44a08f62c95288f34f66b51f146302bce750ff4d591707075d9123bd2 -a64b4a6d72354e596d87cda213c4fc2814009461570ccb27d455bbe131f8d948421a71925425b546d8cf63d5458cd64b -91c215c73b195795ede2228b7ed1f6e37892e0c6b0f4a0b5a16c57aa1100c84df9239054a173b6110d6c2b7f4bf1ce52 -88807198910ec1303480f76a3683870246a995e36adaeadc29c22f0bdba8152fe705bd070b75de657b04934f7d0ccf80 -b37c0026c7b32eb02cacac5b55cb5fe784b8e48b2945c64d3037af83ece556a117f0ff053a5968c2f5fa230e291c1238 -94c768384ce212bc2387e91ce8b45e4ff120987e42472888a317abc9dcdf3563b62e7a61c8e98d7cdcbe272167d91fc6 -a10c2564936e967a390cb14ef6e8f8b04ea9ece5214a38837eda09e79e0c7970b1f83adf017c10efd6faa8b7ffa2c567 -a5085eed3a95f9d4b1269182ea1e0d719b7809bf5009096557a0674bde4201b0ddc1f0f16a908fc468846b3721748ce3 -87468eb620b79a0a455a259a6b4dfbc297d0d53336537b771254dd956b145dc816b195b7002647ea218552e345818a3f -ace2b77ffb87366af0a9cb5d27d6fc4a14323dbbf1643f5f3c4559306330d86461bb008894054394cbfaefeaa0bc2745 -b27f56e840a54fbd793f0b7a7631aa4cee64b5947e4382b2dfb5eb1790270288884c2a19afebe5dc0c6ef335d4531c1c -876e438633931f7f895062ee16c4b9d10428875f7bc79a8e156a64d379a77a2c45bf5430c5ab94330f03da352f1e9006 -a2512a252587d200d2092b44c914df54e04ff8bcef36bf631f84bde0cf5a732e3dc7f00f662842cfd74b0b0f7f24180e -827f1bc8f54a35b7a4bd8154f79bcc055e45faed2e74adf7cf21cca95df44d96899e847bd70ead6bb27b9c0ed97bbd8b -a0c92cf5a9ed843714f3aea9fe7b880f622d0b4a3bf66de291d1b745279accf6ba35097849691370f41732ba64b5966b -a63f5c1e222775658421c487b1256b52626c6f79cb55a9b7deb2352622cedffb08502042d622eb3b02c97f9c09f9c957 -8cc093d52651e65fb390e186db6cc4de559176af4624d1c44cb9b0e836832419dacac7b8db0627b96288977b738d785d -aa7b6a17dfcec146134562d32a12f7bd7fe9522e300859202a02939e69dbd345ed7ff164a184296268f9984f9312e8fc -8ac76721f0d2b679f023d06cbd28c85ae5f4b43c614867ccee88651d4101d4fd352dbdb65bf36bfc3ebc0109e4b0c6f9 -8d350f7c05fc0dcd9a1170748846fb1f5d39453e4cb31e6d1457bed287d96fc393b2ecc53793ca729906a33e59c6834a -b9913510dfc5056d7ec5309f0b631d1ec53e3a776412ada9aefdaf033c90da9a49fdde6719e7c76340e86599b1f0eec2 -94955626bf4ce87612c5cfffcf73bf1c46a4c11a736602b9ba066328dc52ad6d51e6d4f53453d4ed55a51e0aad810271 -b0fcab384fd4016b2f1e53f1aafd160ae3b1a8865cd6c155d7073ecc1664e05b1d8bca1def39c158c7086c4e1103345e -827de3f03edfbde08570b72de6662c8bfa499b066a0a27ebad9b481c273097d17a5a0a67f01553da5392ec3f149b2a78 -ab7940384c25e9027c55c40df20bd2a0d479a165ced9b1046958353cd69015eeb1e44ed2fd64e407805ba42df10fc7bf -8ad456f6ff8cd58bd57567d931f923d0c99141978511b17e03cab7390a72b9f62498b2893e1b05c7c22dd274e9a31919 -ac75399e999effe564672db426faa17a839e57c5ef735985c70cd559a377adec23928382767b55ed5a52f7b11b54b756 -b17f975a00b817299ac7af5f2024ea820351805df58b43724393bfb3920a8cd747a3bbd4b8286e795521489db3657168 -a2bed800a6d95501674d9ee866e7314063407231491d794f8cf57d5be020452729c1c7cefd8c50dc1540181f5caab248 -9743f5473171271ffdd3cc59a3ae50545901a7b45cd4bc3570db487865f3b73c0595bebabbfe79268809ee1862e86e4a -b7eab77c2d4687b60d9d7b04e842b3880c7940140012583898d39fcc22d9b9b0a9be2c2e3788b3e6f30319b39c338f09 -8e2b8f797a436a1b661140e9569dcf3e1eea0a77c7ff2bc4ff0f3e49af04ed2de95e255df8765f1d0927fb456a9926b1 -8aefea201d4a1f4ff98ffce94e540bb313f2d4dfe7e9db484a41f13fc316ed02b282e1acc9bc6f56cad2dc2e393a44c9 -b950c17c0e5ca6607d182144aa7556bb0efe24c68f06d79d6413a973b493bfdf04fd147a4f1ab03033a32004cc3ea66f -b7b8dcbb179a07165f2dc6aa829fad09f582a71b05c3e3ea0396bf9e6fe73076f47035c031c2101e8e38e0d597eadd30 -a9d77ed89c77ec1bf8335d08d41c3c94dcca9fd1c54f22837b4e54506b212aa38d7440126c80648ab7723ff18e65ed72 -a819d6dfd4aef70e52b8402fe5d135f8082d40eb7d3bb5c4d7997395b621e2bb10682a1bad2c9caa33dd818550fc3ec6 -8f6ee34128fac8bbf13ce2d68b2bb363eb4fd65b297075f88e1446ddeac242500eeb4ef0735e105882ff5ba8c44c139b -b4440e48255c1644bcecf3a1e9958f1ec4901cb5b1122ee5b56ffd02cad1c29c4266999dbb85aa2605c1b125490074d4 -a43304a067bede5f347775d5811cf65a6380a8d552a652a0063580b5c5ef12a0867a39c7912fa219e184f4538eba1251 -a891ad67a790089ffc9f6d53e6a3d63d3556f5f693e0cd8a7d0131db06fd4520e719cfcc3934f0a8f62a95f90840f1d4 -aea6df8e9bb871081aa0fc5a9bafb00be7d54012c5baf653791907d5042a326aeee966fd9012a582cc16695f5baf7042 -8ffa2660dc52ed1cd4eff67d6a84a8404f358a5f713d04328922269bee1e75e9d49afeec0c8ad751620f22352a438e25 -87ec6108e2d63b06abed350f8b363b7489d642486f879a6c3aa90e5b0f335efc2ff2834eef9353951a42136f8e6a1b32 -865619436076c2760d9e87ddc905023c6de0a8d56eef12c98a98c87837f2ca3f27fd26a2ad752252dbcbe2b9f1d5a032 -980437dce55964293cb315c650c5586ffd97e7a944a83f6618af31c9d92c37b53ca7a21bb5bc557c151b9a9e217e7098 -95d128fc369df4ad8316b72aea0ca363cbc7b0620d6d7bb18f7076a8717a6a46956ff140948b0cc4f6d2ce33b5c10054 -8c7212d4a67b9ec70ebbca04358ad2d36494618d2859609163526d7b3acc2fc935ca98519380f55e6550f70a9bc76862 -893a2968819401bf355e85eee0f0ed0406a6d4a7d7f172d0017420f71e00bb0ba984f6020999a3cdf874d3cd8ebcd371 -9103c1af82dece25d87274e89ea0acd7e68c2921c4af3d8d7c82ab0ed9990a5811231b5b06113e7fa43a6bd492b4564f -99cfd87a94eab7d35466caa4ed7d7bb45e5c932b2ec094258fb14bf205659f83c209b83b2f2c9ccb175974b2a33e7746 -874b6b93e4ee61be3f00c32dd84c897ccd6855c4b6251eb0953b4023634490ed17753cd3223472873cbc6095b2945075 -84a32c0dc4ea60d33aac3e03e70d6d639cc9c4cc435c539eff915017be3b7bdaba33349562a87746291ebe9bc5671f24 -a7057b24208928ad67914e653f5ac1792c417f413d9176ba635502c3f9c688f7e2ee81800d7e3dc0a340c464da2fd9c5 -a03fb9ed8286aacfa69fbd5d953bec591c2ae4153400983d5dbb6cd9ea37fff46ca9e5cceb9d117f73e9992a6c055ad2 -863b2de04e89936c9a4a2b40380f42f20aefbae18d03750fd816c658aee9c4a03df7b12121f795c85d01f415baaeaa59 -8526eb9bd31790fe8292360d7a4c3eed23be23dd6b8b8f01d2309dbfdc0cfd33ad1568ddd7f8a610f3f85a9dfafc6a92 -b46ab8c5091a493d6d4d60490c40aa27950574a338ea5bbc045be3a114af87bdcb160a8c80435a9b7ad815f3cb56a3f3 -aeadc47b41a8d8b4176629557646202f868b1d728b2dda58a347d937e7ffc8303f20d26d6c00b34c851b8aeec547885d -aebb19fc424d72c1f1822aa7adc744cd0ef7e55727186f8df8771c784925058c248406ebeeaf3c1a9ee005a26e9a10c6 -8ff96e81c1a4a2ab1b4476c21018fae0a67e92129ee36120cae8699f2d7e57e891f5c624902cb1b845b944926a605cc3 -8251b8d2c43fadcaa049a9e7aff838dae4fb32884018d58d46403ac5f3beb5c518bfd45f03b8abb710369186075eb71c -a8b2a64f865f51a5e5e86a66455c093407933d9d255d6b61e1fd81ffafc9538d73caaf342338a66ba8ee166372a3d105 -aad915f31c6ba7fdc04e2aaac62e84ef434b7ee76a325f07dc430d12c84081999720181067b87d792efd0117d7ee1eab -a13db3bb60389883fd41d565c54fb5180d9c47ce2fe7a169ae96e01d17495f7f4fa928d7e556e7c74319c4c25d653eb2 -a4491b0198459b3f552855d680a59214eb74e6a4d6c5fa3b309887dc50ebea2ecf6d26c040550f7dc478b452481466fb -8f017f13d4b1e3f0c087843582b52d5f8d13240912254d826dd11f8703a99a2f3166dfbdfdffd9a3492979d77524276b -96c3d5dcd032660d50d7cd9db2914f117240a63439966162b10c8f1f3cf74bc83b0f15451a43b31dbd85e4a7ce0e4bb1 -b479ec4bb79573d32e0ec93b92bdd7ec8c26ddb5a2d3865e7d4209d119fd3499eaac527615ffac78c440e60ef3867ae0 -b2c49c4a33aa94b52b6410b599e81ff15490aafa7e43c8031c865a84e4676354a9c81eb4e7b8be6825fdcefd1e317d44 -906dc51d6a90c089b6704b47592805578a6eed106608eeb276832f127e1b8e858b72e448edcbefb497d152447e0e68ff -b0e81c63b764d7dfbe3f3fddc9905aef50f3633e5d6a4af6b340495124abedcff5700dfd1577bbbed7b6bf97d02719cb -9304c64701e3b4ed6d146e48a881f7d83a17f58357cca0c073b2bb593afd2d94f6e2a7a1ec511d0a67ad6ff4c3be5937 -b6fdbd12ba05aa598d80b83f70a15ef90e5cba7e6e75fa038540ee741b644cd1f408a6cecfd2a891ef8d902de586c6b5 -b80557871a6521b1b3c74a1ba083ae055b575df607f1f7b04c867ba8c8c181ea68f8d90be6031f4d25002cca27c44da2 -aa7285b8e9712e06b091f64163f1266926a36607f9d624af9996856ed2aaf03a580cb22ce407d1ade436c28b44ca173f -8148d72b975238b51e6ea389e5486940d22641b48637d7dfadfa603a605bfc6d74a016480023945d0b85935e396aea5d -8a014933a6aea2684b5762af43dcf4bdbb633cd0428d42d71167a2b6fc563ece5e618bff22f1db2ddb69b845b9a2db19 -990d91740041db770d0e0eb9d9d97d826f09fd354b91c41e0716c29f8420e0e8aac0d575231efba12fe831091ec38d5a -9454d0d32e7e308ddec57cf2522fb1b67a2706e33fb3895e9e1f18284129ab4f4c0b7e51af25681d248d7832c05eb698 -a5bd434e75bac105cb3e329665a35bce6a12f71dd90c15165777d64d4c13a82bceedb9b48e762bd24034e0fc9fbe45f4 -b09e3b95e41800d4dc29c6ffdaab2cd611a0050347f6414f154a47ee20ee59bf8cf7181454169d479ebce1eb5c777c46 -b193e341d6a047d15eea33766d656d807b89393665a783a316e9ba10518e5515c8e0ade3d6e15641d917a8a172a5a635 -ade435ec0671b3621dde69e07ead596014f6e1daa1152707a8c18877a8b067bde2895dd47444ffa69db2bbef1f1d8816 -a7fd3d6d87522dfc56fb47aef9ce781a1597c56a8bbfd796baba907afdc872f753d732bfda1d3402aee6c4e0c189f52d -a298cb4f4218d0464b2fab393e512bbc477c3225aa449743299b2c3572f065bc3a42d07e29546167ed9e1b6b3b3a3af3 -a9ee57540e1fd9c27f4f0430d194b91401d0c642456c18527127d1f95e2dba41c2c86d1990432eb38a692fda058fafde -81d6c1a5f93c04e6d8e5a7e0678c1fc89a1c47a5c920bcd36180125c49fcf7c114866b90e90a165823560b19898a7c16 -a4b7a1ec9e93c899b9fd9aaf264c50e42c36c0788d68296a471f7a3447af4dbc81e4fa96070139941564083ec5b5b5a1 -b3364e327d381f46940c0e11e29f9d994efc6978bf37a32586636c0070b03e4e23d00650c1440f448809e1018ef9f6d8 -8056e0913a60155348300e3a62e28b5e30629a90f7dd4fe11289097076708110a1d70f7855601782a3cdc5bdb1ca9626 -b4980fd3ea17bac0ba9ee1c470b17e575bb52e83ebdd7d40c93f4f87bebeaff1c8a679f9d3d09d635f068d37d5bd28bd -905a9299e7e1853648e398901dfcd437aa575c826551f83520df62984f5679cb5f0ea86aa45ed3e18b67ddc0dfafe809 -ab99553bf31a84f2e0264eb34a08e13d8d15e2484aa9352354becf9a15999c76cc568d68274b70a65e49703fc23540d0 -a43681597bc574d2dae8964c9a8dc1a07613d7a1272bdcb818d98c85d44e16d744250c33f3b5e4d552d97396b55e601f -a54e5a31716fccb50245898c99865644405b8dc920ded7a11f3d19bdc255996054b268e16f2e40273f11480e7145f41e -8134f3ad5ef2ad4ba12a8a4e4d8508d91394d2bcdc38b7c8c8c0b0a820357ac9f79d286c65220f471eb1adca1d98fc68 -94e2f755e60471578ab2c1adb9e9cea28d4eec9b0e92e0140770bca7002c365fcabfe1e5fb4fe6cfe79a0413712aa3ef -ad48f8d0ce7eb3cc6e2a3086ad96f562e5bed98a360721492ae2e74dc158586e77ec8c35d5fd5927376301b7741bad2b -8614f0630bdd7fbad3a31f55afd9789f1c605dc85e7dc67e2edfd77f5105f878bb79beded6e9f0b109e38ea7da67e8d5 -9804c284c4c5e77dabb73f655b12181534ca877c3e1e134aa3f47c23b7ec92277db34d2b0a5d38d2b69e5d1c3008a3e3 -a51b99c3088e473afdaa9e0a9f7e75a373530d3b04e44e1148da0726b95e9f5f0c7e571b2da000310817c36f84b19f7f -ac4ff909933b3b76c726b0a382157cdc74ab851a1ac6cef76953c6444441804cc43abb883363f416592e8f6cfbc4550b -ae7d915eb9fc928b65a29d6edbc75682d08584d0014f7bcf17d59118421ae07d26a02137d1e4de6938bcd1ab8ef48fad -852f7e453b1af89b754df6d11a40d5d41ea057376e8ecacd705aacd2f917457f4a093d6b9a8801837fa0f62986ad7149 -92c6bf5ada5d0c3d4dd8058483de36c215fa98edab9d75242f3eff9db07c734ad67337da6f0eefe23a487bf75a600dee -a2b42c09d0db615853763552a48d2e704542bbd786aae016eb58acbf6c0226c844f5fb31e428cb6450b9db855f8f2a6f -880cc07968266dbfdcfbc21815cd69e0eddfee239167ac693fb0413912d816f2578a74f7716eecd6deefa68c6eccd394 -b885b3ace736cd373e8098bf75ba66fa1c6943ca1bc4408cd98ac7074775c4478594f91154b8a743d9c697e1b29f5840 -a51ce78de512bd87bfa0835de819941dffbf18bec23221b61d8096fc9436af64e0693c335b54e7bfc763f287bdca2db6 -a3c76166a3bdb9b06ef696e57603b58871bc72883ee9d45171a30fe6e1d50e30bc9c51b4a0f5a7270e19a77b89733850 -acefc5c6f8a1e7c24d7b41e0fc7f6f3dc0ede6cf3115ffb9a6e54b1d954cbca9bda8ad7a084be9be245a1b8e9770d141 -b420ed079941842510e31cfad117fa11fb6b4f97dfbc6298cb840f27ebaceba23eeaf3f513bcffbf5e4aae946310182d -95c3bb5ef26c5ed2f035aa5d389c6b3c15a6705b9818a3fefaed28922158b35642b2e8e5a1a620fdad07e75ad4b43af4 -825149f9081ecf07a2a4e3e8b5d21bade86c1a882475d51c55ee909330b70c5a2ac63771c8600c6f38df716af61a3ea1 -873b935aae16d9f08adbc25353cee18af2f1b8d5f26dec6538d6bbddc515f2217ed7d235dcfea59ae61b428798b28637 -9294150843a2bedcedb3bb74c43eb28e759cf9499582c5430bccefb574a8ddd4f11f9929257ff4c153990f9970a2558f -b619563a811cc531da07f4f04e5c4c6423010ff9f8ed7e6ec9449162e3d501b269fb1c564c09c0429431879b0f45df02 -91b509b87eb09f007d839627514658c7341bc76d468920fe8a740a8cb96a7e7e631e0ea584a7e3dc1172266f641d0f5c -8b8aceace9a7b9b4317f1f01308c3904d7663856946afbcea141a1c615e21ccad06b71217413e832166e9dd915fbe098 -87b3b36e725833ea0b0f54753c3728c0dbc87c52d44d705ffc709f2d2394414c652d3283bab28dcce09799504996cee0 -b2670aad5691cbf308e4a6a77a075c4422e6cbe86fdba24e9f84a313e90b0696afb6a067eebb42ba2d10340d6a2f6e51 -876784a9aff3d54faa89b2bacd3ff5862f70195d0b2edc58e8d1068b3c9074c0da1cfa23671fe12f35e33b8a329c0ccd -8b48b9e758e8a8eae182f5cbec96f67d20cca6d3eee80a2d09208eb1d5d872e09ef23d0df8ebbb9b01c7449d0e3e3650 -b79303453100654c04a487bdcadc9e3578bc80930c489a7069a52e8ca1dba36c492c8c899ce025f8364599899baa287d -961b35a6111da54ece6494f24dacd5ea46181f55775b5f03df0e370c34a5046ac2b4082925855325bb42bc2a2c98381d -a31feb1be3f5a0247a1f7d487987eb622e34fca817832904c6ee3ee60277e5847945a6f6ea1ac24542c72e47bdf647df -a12a2aa3e7327e457e1aae30e9612715dd2cfed32892c1cd6dcda4e9a18203af8a44afb46d03b2eed89f6b9c5a2c0c23 -a08265a838e69a2ca2f80fead6ccf16f6366415b920c0b22ee359bcd8d4464ecf156f400a16a7918d52e6d733dd64211 -b723d6344e938d801cca1a00032af200e541d4471fd6cbd38fb9130daa83f6a1dffbbe7e67fc20f9577f884acd7594b2 -a6733d83ec78ba98e72ddd1e7ff79b7adb0e559e256760d0c590a986e742445e8cdf560d44b29439c26d87edd0b07c8c -a61c2c27d3f7b9ff4695a17afedf63818d4bfba390507e1f4d0d806ce8778d9418784430ce3d4199fd3bdbc2504d2af3 -8332f3b63a6dc985376e8b1b25eeae68be6160fbe40053ba7bcf6f073204f682da72321786e422d3482fd60c9e5aa034 -a280f44877583fbb6b860d500b1a3f572e3ee833ec8f06476b3d8002058e25964062feaa1e5bec1536d734a5cfa09145 -a4026a52d277fcea512440d2204f53047718ebfcae7b48ac57ea7f6bfbc5de9d7304db9a9a6cbb273612281049ddaec5 -95cdf69c831ab2fad6c2535ede9c07e663d2ddccc936b64e0843d2df2a7b1c31f1759c3c20f1e7a57b1c8f0dbb21b540 -95c96cec88806469c277ab567863c5209027cecc06c7012358e5f555689c0d9a5ffb219a464f086b45817e8536b86d2f -afe38d4684132a0f03d806a4c8df556bf589b25271fbc6fe2e1ed16de7962b341c5003755da758d0959d2e6499b06c68 -a9b77784fda64987f97c3a23c5e8f61b918be0f7c59ba285084116d60465c4a2aaafc8857eb16823282cc83143eb9126 -a830f05881ad3ce532a55685877f529d32a5dbe56cea57ffad52c4128ee0fad0eeaf0da4362b55075e77eda7babe70e5 -992b3ad190d6578033c13ed5abfee4ef49cbc492babb90061e3c51ee4b5790cdd4c8fc1abff1fa2c00183b6b64f0bbbe -b1015424d9364aeff75de191652dc66484fdbec3e98199a9eb9671ec57bec6a13ff4b38446e28e4d8aedb58dd619cd90 -a745304604075d60c9db36cada4063ac7558e7ec2835d7da8485e58d8422e817457b8da069f56511b02601289fbb8981 -a5ba4330bc5cb3dbe0486ddf995632a7260a46180a08f42ae51a2e47778142132463cc9f10021a9ad36986108fefa1a9 -b419e9fd4babcaf8180d5479db188bb3da232ae77a1c4ed65687c306e6262f8083070a9ac32220cddb3af2ec73114092 -a49e23dc5f3468f3bf3a0bb7e4a114a788b951ff6f23a3396ae9e12cbff0abd1240878a3d1892105413dbc38818e807c -b7ecc7b4831f650202987e85b86bc0053f40d983f252e9832ef503aea81c51221ce93279da4aa7466c026b2d2070e55d -96a8c35cb87f84fa84dcd6399cc2a0fd79cc9158ef4bdde4bae31a129616c8a9f2576cd19baa3f497ca34060979aed7d -8681b2c00aa62c2b519f664a95dcb8faef601a3b961bb4ce5d85a75030f40965e2983871d41ea394aee934e859581548 -85c229a07efa54a713d0790963a392400f55fbb1a43995a535dc6c929f20d6a65cf4efb434e0ad1cb61f689b8011a3bc -90856f7f3444e5ad44651c28e24cc085a5db4d2ffe79aa53228c26718cf53a6e44615f3c5cda5aa752d5f762c4623c66 -978999b7d8aa3f28a04076f74d11c41ef9c89fdfe514936c4238e0f13c38ec97e51a5c078ebc6409e517bfe7ccb42630 -a099914dd7ed934d8e0d363a648e9038eb7c1ec03fa04dbcaa40f7721c618c3ef947afef7a16b4d7ac8c12aa46637f03 -ab2a104fed3c83d16f2cda06878fa5f30c8c9411de71bfb67fd2fc9aa454dcbcf3d299d72f8cc12e919466a50fcf7426 -a4471d111db4418f56915689482f6144efc4664cfb0311727f36c864648d35734351becc48875df96f4abd3cfcf820f9 -83be11727cd30ea94ccc8fa31b09b81c9d6a9a5d3a4686af9da99587332fe78c1f94282f9755854bafd6033549afec91 -88020ff971dc1a01a9e993cd50a5d2131ffdcbb990c1a6aaa54b20d8f23f9546a70918ea57a21530dcc440c1509c24ad -ae24547623465e87905eaffa1fa5d52bb7c453a8dbd89614fa8819a2abcedaf455c2345099b7324ae36eb0ad7c8ef977 -b59b0c60997de1ee00b7c388bc7101d136c9803bf5437b1d589ba57c213f4f835a3e4125b54738e78abbc21b000f2016 -a584c434dfe194546526691b68fa968c831c31da42303a1d735d960901c74011d522246f37f299555416b8cf25c5a548 -80408ce3724f4837d4d52376d255e10f69eb8558399ae5ca6c11b78b98fe67d4b93157d2b9b639f1b5b64198bfe87713 -abb941e8d406c2606e0ddc35c113604fdd9d249eacc51cb64e2991e551b8639ce44d288cc92afa7a1e7fc599cfc84b22 -b223173f560cacb1c21dba0f1713839e348ad02cbfdef0626748604c86f89e0f4c919ed40b583343795bdd519ba952c8 -af1c70512ec3a19d98b8a1fc3ff7f7f5048a27d17d438d43f561974bbdd116fcd5d5c21040f3447af3f0266848d47a15 -8a44809568ebe50405bede19b4d2607199159b26a1b33e03d180e6840c5cf59d991a4fb150d111443235d75ecad085b7 -b06207cdca46b125a27b3221b5b50cf27af4c527dd7c80e2dbcebbb09778a96df3af67e50f07725239ce3583dad60660 -993352d9278814ec89b26a11c4a7c4941bf8f0e6781ae79559d14749ee5def672259792db4587f85f0100c7bb812f933 -9180b8a718b971fd27bc82c8582d19c4b4f012453e8c0ffeeeffe745581fc6c07875ab28be3af3fa3896d19f0c89ac5b -8b8e1263eb48d0fe304032dd5ea1f30e73f0121265f7458ba9054d3626894e8a5fef665340abd2ede9653045c2665938 -99a2beee4a10b7941c24b2092192faf52b819afd033e4a2de050fd6c7f56d364d0cf5f99764c3357cf32399e60fc5d74 -946a4aad7f8647ea60bee2c5fcdeb6f9a58fb2cfca70c4d10e458027a04846e13798c66506151be3df9454b1e417893f -a672a88847652d260b5472d6908d1d57e200f1e492d30dd1cecc441cdfc9b76e016d9bab560efd4d7f3c30801de884a9 -9414e1959c156cde1eb24e628395744db75fc24b9df4595350aaad0bc38e0246c9b4148f6443ef68b8e253a4a6bcf11c -9316e9e4ec5fab4f80d6540df0e3a4774db52f1d759d2e5b5bcd3d7b53597bb007eb1887cb7dc61f62497d51ffc8d996 -902d6d77bb49492c7a00bc4b70277bc28c8bf9888f4307bb017ac75a962decdedf3a4e2cf6c1ea9f9ba551f4610cbbd7 -b07025a18b0e32dd5e12ec6a85781aa3554329ea12c4cd0d3b2c22e43d777ef6f89876dd90a9c8fb097ddf61cf18adc5 -b355a849ad3227caa4476759137e813505ec523cbc2d4105bc7148a4630f9e81918d110479a2d5f5e4cd9ccec9d9d3e3 -b49532cfdf02ee760109881ad030b89c48ee3bb7f219ccafc13c93aead754d29bdafe345be54c482e9d5672bd4505080 -9477802410e263e4f938d57fa8f2a6cac7754c5d38505b73ee35ea3f057aad958cb9722ba6b7b3cfc4524e9ca93f9cdc -9148ea83b4436339580f3dbc9ba51509e9ab13c03063587a57e125432dd0915f5d2a8f456a68f8fff57d5f08c8f34d6e -b00b6b5392b1930b54352c02b1b3b4f6186d20bf21698689bbfc7d13e86538a4397b90e9d5c93fd2054640c4dbe52a4f -926a9702500441243cd446e7cbf15dde16400259726794694b1d9a40263a9fc9e12f7bcbf12a27cb9aaba9e2d5848ddc -a0c6155f42686cbe7684a1dc327100962e13bafcf3db97971fc116d9f5c0c8355377e3d70979cdbd58fd3ea52440901c -a277f899f99edb8791889d0817ea6a96c24a61acfda3ad8c3379e7c62b9d4facc4b965020b588651672fd261a77f1bfc -8f528cebb866b501f91afa50e995234bef5bf20bff13005de99cb51eaac7b4f0bf38580cfd0470de40f577ead5d9ba0f -963fc03a44e9d502cc1d23250efef44d299befd03b898d07ce63ca607bb474b5cf7c965a7b9b0f32198b04a8393821f7 -ab087438d0a51078c378bf4a93bd48ef933ff0f1fa68d02d4460820df564e6642a663b5e50a5fe509527d55cb510ae04 -b0592e1f2c54746bb076be0fa480e1c4bebc4225e1236bcda3b299aa3853e3afb401233bdbcfc4a007b0523a720fbf62 -851613517966de76c1c55a94dc4595f299398a9808f2d2f0a84330ba657ab1f357701d0895f658c18a44cb00547f6f57 -a2fe9a1dd251e72b0fe4db27be508bb55208f8f1616b13d8be288363ec722826b1a1fd729fc561c3369bf13950bf1fd6 -b896cb2bc2d0c77739853bc59b0f89b2e008ba1f701c9cbe3bef035f499e1baee8f0ff1e794854a48c320586a2dfc81a -a1b60f98e5e5106785a9b81a85423452ee9ef980fa7fa8464f4366e73f89c50435a0c37b2906052b8e58e212ebd366cf -a853b0ebd9609656636df2e6acd5d8839c0fda56f7bf9288a943b06f0b67901a32b95e016ca8bc99bd7b5eab31347e72 -b290fa4c1346963bd5225235e6bdf7c542174dab4c908ab483d1745b9b3a6015525e398e1761c90e4b49968d05e30eea -b0f65a33ad18f154f1351f07879a183ad62e5144ad9f3241c2d06533dad09cbb2253949daff1bb02d24d16a3569f7ef0 -a00db59b8d4218faf5aeafcd39231027324408f208ec1f54d55a1c41228b463b88304d909d16b718cfc784213917b71e -b8d695dd33dc2c3bc73d98248c535b2770ad7fa31aa726f0aa4b3299efb0295ba9b4a51c71d314a4a1bd5872307534d1 -b848057cca2ca837ee49c42b88422303e58ea7d2fc76535260eb5bd609255e430514e927cc188324faa8e657396d63ec -92677836061364685c2aaf0313fa32322746074ed5666fd5f142a7e8f87135f45cd10e78a17557a4067a51dfde890371 -a854b22c9056a3a24ab164a53e5c5cf388616c33e67d8ebb4590cb16b2e7d88b54b1393c93760d154208b5ca822dc68f -86fff174920388bfab841118fb076b2b0cdec3fdb6c3d9a476262f82689fb0ed3f1897f7be9dbf0932bb14d346815c63 -99661cf4c94a74e182752bcc4b98a8c2218a8f2765642025048e12e88ba776f14f7be73a2d79bd21a61def757f47f904 -8a8893144d771dca28760cba0f950a5d634195fd401ec8cf1145146286caffb0b1a6ba0c4c1828d0a5480ce49073c64c -938a59ae761359ee2688571e7b7d54692848eb5dde57ffc572b473001ea199786886f8c6346a226209484afb61d2e526 -923f68a6aa6616714cf077cf548aeb845bfdd78f2f6851d8148cba9e33a374017f2f3da186c39b82d14785a093313222 -ac923a93d7da7013e73ce8b4a2b14b8fd0cc93dc29d5de941a70285bdd19be4740fedfe0c56b046689252a3696e9c5bc -b49b32c76d4ec1a2c68d4989285a920a805993bc6fcce6dacd3d2ddae73373050a5c44ba8422a3781050682fa0ef6ba2 -8a367941c07c3bdca5712524a1411bad7945c7c48ffc7103b1d4dff2c25751b0624219d1ccde8c3f70c465f954be5445 -b838f029df455efb6c530d0e370bbbf7d87d61a9aea3d2fe5474c5fe0a39cf235ceecf9693c5c6c5820b1ba8f820bd31 -a8983b7c715eaac7f13a001d2abc462dfc1559dab4a6b554119c271aa8fe00ffcf6b6949a1121f324d6d26cb877bcbae -a2afb24ad95a6f14a6796315fbe0d8d7700d08f0cfaf7a2abe841f5f18d4fecf094406cbd54da7232a159f9c5b6e805e -87e8e95ad2d62f947b2766ff405a23f7a8afba14e7f718a691d95369c79955cdebe24c54662553c60a3f55e6322c0f6f -87c2cbcecb754e0cc96128e707e5c5005c9de07ffd899efa3437cadc23362f5a1d3fcdd30a1f5bdc72af3fb594398c2a -91afd6ee04f0496dc633db88b9370d41c428b04fd991002502da2e9a0ef051bcd7b760e860829a44fbe5539fa65f8525 -8c50e5d1a24515a9dd624fe08b12223a75ca55196f769f24748686315329b337efadca1c63f88bee0ac292dd0a587440 -8a07e8f912a38d94309f317c32068e87f68f51bdfa082d96026f5f5f8a2211621f8a3856dda8069386bf15fb2d28c18f -94ad1dbe341c44eeaf4dc133eed47d8dbfe752575e836c075745770a6679ff1f0e7883b6aa917462993a7f469d74cab5 -8745f8bd86c2bb30efa7efb7725489f2654f3e1ac4ea95bd7ad0f3cfa223055d06c187a16192d9d7bdaea7b050c6a324 -900d149c8d79418cda5955974c450a70845e02e5a4ecbcc584a3ca64d237df73987c303e3eeb79da1af83bf62d9e579f -8f652ab565f677fb1a7ba03b08004e3cda06b86c6f1b0b9ab932e0834acf1370abb2914c15b0d08327b5504e5990681c -9103097d088be1f75ab9d3da879106c2f597e2cc91ec31e73430647bdd5c33bcfd771530d5521e7e14df6acda44f38a6 -b0fec7791cfb0f96e60601e1aeced9a92446b61fedab832539d1d1037558612d78419efa87ff5f6b7aab8fd697d4d9de -b9d2945bdb188b98958854ba287eb0480ef614199c4235ce5f15fc670b8c5ffe8eeb120c09c53ea8a543a022e6a321ac -a9461bb7d5490973ebaa51afc0bb4a5e42acdccb80e2f939e88b77ac28a98870e103e1042899750f8667a8cc9123bae9 -a37fdf11d4bcb2aed74b9f460a30aa34afea93386fa4cdb690f0a71bc58f0b8df60bec56e7a24f225978b862626fa00e -a214420e183e03d531cf91661466ea2187d84b6e814b8b20b3730a9400a7d25cf23181bb85589ebc982cec414f5c2923 -ad09a45a698a6beb3e0915f540ef16e9af7087f53328972532d6b5dfe98ce4020555ece65c6cbad8bd6be8a4dfefe6fd -ab6742800b02728c92d806976764cb027413d6f86edd08ad8bb5922a2969ee9836878cd39db70db0bd9a2646862acc4f -974ca9305bd5ea1dc1755dff3b63e8bfe9f744321046c1395659bcea2a987b528e64d5aa96ac7b015650b2253b37888d -84eee9d6bce039c52c2ebc4fccc0ad70e20c82f47c558098da4be2f386a493cbc76adc795b5488c8d11b6518c2c4fab8 -875d7bda46efcb63944e1ccf760a20144df3b00d53282b781e95f12bfc8f8316dfe6492c2efbf796f1150e36e436e9df -b68a2208e0c587b5c31b5f6cb32d3e6058a9642e2d9855da4f85566e1412db528475892060bb932c55b3a80877ad7b4a -ba006368ecab5febb6ab348644d9b63de202293085ed468df8bc24d992ae8ce468470aa37f36a73630c789fb9c819b30 -90a196035150846cd2b482c7b17027471372a8ce7d914c4d82b6ea7fa705d8ed5817bd42d63886242585baf7d1397a1c -a223b4c85e0daa8434b015fd9170b5561fe676664b67064974a1e9325066ecf88fc81f97ab5011c59fad28cedd04b240 -82e8ec43139cf15c6bbeed484b62e06cded8a39b5ce0389e4cbe9c9e9c02f2f0275d8d8d4e8dfec8f69a191bef220408 -81a3fc07a7b68d92c6ee4b6d28f5653ee9ec85f7e2ee1c51c075c1b130a8c5097dc661cf10c5aff1c7114b1a6a19f11a -8ed2ef8331546d98819a5dd0e6c9f8cb2630d0847671314a28f277faf68da080b53891dd75c82cbcf7788b255490785d -acecabf84a6f9bbed6b2fc2e7e4b48f02ef2f15e597538a73aea8f98addc6badda15e4695a67ecdb505c1554e8f345ec -b8f51019b2aa575f8476e03dcadf86cc8391f007e5f922c2a36b2daa63f5a503646a468990cd5c65148d323942193051 -aaa595a84b403ec65729bc1c8055a94f874bf9adddc6c507b3e1f24f79d3ad359595a672b93aab3394db4e2d4a7d8970 -895144c55fcbd0f64d7dd69e6855cfb956e02b5658eadf0f026a70703f3643037268fdd673b0d21b288578a83c6338dd -a2e92ae6d0d237d1274259a8f99d4ea4912a299816350b876fba5ebc60b714490e198a916e1c38c6e020a792496fa23c -a45795fda3b5bb0ad1d3c628f6add5b2a4473a1414c1a232e80e70d1cfffd7f8a8d9861f8df2946999d7dbb56bf60113 -b6659bf7f6f2fef61c39923e8c23b8c70e9c903028d8f62516d16755cd3fba2fe41c285aa9432dc75ab08f8a1d8a81fc -a735609a6bc5bfd85e58234fc439ff1f58f1ff1dd966c5921d8b649e21f006bf2b8642ad8a75063c159aaf6935789293 -a3c622eb387c9d15e7bda2e3e84d007cb13a6d50d655c3f2f289758e49d3b37b9a35e4535d3cc53d8efd51f407281f19 -8afe147b53ad99220f5ef9d763bfc91f9c20caecbcf823564236fb0e6ede49414c57d71eec4772c8715cc65a81af0047 -b5f0203233cf71913951e9c9c4e10d9243e3e4a1f2cb235bf3f42009120ba96e04aa414c9938ea8873b63148478927e8 -93c52493361b458d196172d7ba982a90a4f79f03aa8008edc322950de3ce6acf4c3977807a2ffa9e924047e02072b229 -b9e72b805c8ac56503f4a86c82720afbd5c73654408a22a2ac0b2e5caccdfb0e20b59807433a6233bc97ae58cf14c70a -af0475779b5cee278cca14c82da2a9f9c8ef222eb885e8c50cca2315fea420de6e04146590ed0dd5a29c0e0812964df5 -b430ccab85690db02c2d0eb610f3197884ca12bc5f23c51e282bf3a6aa7e4a79222c3d8761454caf55d6c01a327595f9 -830032937418b26ee6da9b5206f3e24dc76acd98589e37937e963a8333e5430abd6ce3dd93ef4b8997bd41440eed75d6 -8820a6d73180f3fe255199f3f175c5eb770461ad5cfdde2fb11508041ed19b8c4ce66ad6ecebf7d7e836cc2318df47ca -aef1393e7d97278e77bbf52ef6e1c1d5db721ccf75fe753cf47a881fa034ca61eaa5098ee5a344c156d2b14ff9e284ad -8a4a26c07218948c1196c45d927ef4d2c42ade5e29fe7a91eaebe34a29900072ce5194cf28d51f746f4c4c649daf4396 -84011dc150b7177abdcb715efbd8c201f9cb39c36e6069af5c50a096021768ba40cef45b659c70915af209f904ede3b6 -b1bd90675411389bb66910b21a4bbb50edce5330850c5ab0b682393950124252766fc81f5ecfc72fb7184387238c402e -8dfdcd30583b696d2c7744655f79809f451a60c9ad5bf1226dc078b19f4585d7b3ef7fa9d54e1ac09520d95cbfd20928 -b351b4dc6d98f75b8e5a48eb7c6f6e4b78451991c9ba630e5a1b9874c15ac450cd409c1a024713bf2cf82dc400e025ef -a462b8bc97ac668b97b28b3ae24b9f5de60e098d7b23ecb600d2194cd35827fb79f77c3e50d358f5bd72ee83fef18fa0 -a183753265c5f7890270821880cce5f9b2965b115ba783c6dba9769536f57a04465d7da5049c7cf8b3fcf48146173c18 -a8a771b81ed0d09e0da4d79f990e58eabcd2be3a2680419502dd592783fe52f657fe55125b385c41d0ba3b9b9cf54a83 -a71ec577db46011689d073245e3b1c3222a9b1fe6aa5b83629adec5733dd48617ebea91346f0dd0e6cdaa86e4931b168 -a334b8b244f0d598a02da6ae0f918a7857a54dce928376c4c85df15f3b0f2ba3ac321296b8b7c9dd47d770daf16c8f8c -a29037f8ef925c417c90c4df4f9fb27fb977d04e2b3dd5e8547d33e92ab72e7a00f5461de21e28835319eae5db145eb7 -b91054108ae78b00e3298d667b913ebc44d8f26e531eae78a8fe26fdfb60271c97efb2dee5f47ef5a3c15c8228138927 -926c13efbe90604f6244be9315a34f72a1f8d1aab7572df431998949c378cddbf2fe393502c930fff614ff06ae98a0ce -995c758fd5600e6537089b1baa4fbe0376ab274ff3e82a17768b40df6f91c2e443411de9cafa1e65ea88fb8b87d504f4 -9245ba307a7a90847da75fca8d77ec03fdfc812c871e7a2529c56a0a79a6de16084258e7a9ac4ae8a3756f394336e21c -99e0cfa2bb57a7e624231317044c15e52196ecce020db567c8e8cb960354a0be9862ee0c128c60b44777e65ac315e59f -ad4f6b3d27bbbb744126601053c3dc98c07ff0eb0b38a898bd80dce778372846d67e5ab8fb34fb3ad0ef3f235d77ba7f -a0f12cae3722bbbca2e539eb9cc7614632a2aefe51410430070a12b5bc5314ecec5857b7ff8f41e9980cac23064f7c56 -b487f1bc59485848c98222fd3bc36c8c9bb3d2912e2911f4ceca32c840a7921477f9b1fe00877e05c96c75d3eecae061 -a6033db53925654e18ecb3ce715715c36165d7035db9397087ac3a0585e587998a53973d011ac6d48af439493029cee6 -a6b4d09cd01c70a3311fd131d3710ccf97bde3e7b80efd5a8c0eaeffeb48cca0f951ced905290267b115b06d46f2693b -a9dff1df0a8f4f218a98b6f818a693fb0d611fed0fc3143537cbd6578d479af13a653a8155e535548a2a0628ae24fa58 -a58e469f65d366b519f9a394cacb7edaddac214463b7b6d62c2dbc1316e11c6c5184ce45c16de2d77f990dcdd8b55430 -989e71734f8119103586dc9a3c5f5033ddc815a21018b34c1f876cdfc112efa868d5751bf6419323e4e59fa6a03ece1c -a2da00e05036c884369e04cf55f3de7d659cd5fa3f849092b2519dd263694efe0f051953d9d94b7e121f0aee8b6174d7 -968f3c029f57ee31c4e1adea89a7f92e28483af9a74f30fbdb995dc2d40e8e657dff8f8d340d4a92bf65f54440f2859f -932778df6f60ac1639c1453ef0cbd2bf67592759dcccb3e96dcc743ff01679e4c7dd0ef2b0833dda548d32cb4eba49e2 -a805a31139f8e0d6dae1ac87d454b23a3dc9fc653d4ca18d4f8ebab30fc189c16e73981c2cb7dd6f8c30454a5208109d -a9ba0991296caa2aaa4a1ceacfb205544c2a2ec97088eace1d84ee5e2767656a172f75d2f0c4e16a3640a0e0dec316e0 -b1e49055c968dced47ec95ae934cf45023836d180702e20e2df57e0f62fb85d7ac60d657ba3ae13b8560b67210449459 -a94e1da570a38809c71e37571066acabff7bf5632737c9ab6e4a32856924bf6211139ab3cedbf083850ff2d0e0c0fcfc -88ef1bb322000c5a5515b310c838c9af4c1cdbb32eab1c83ac3b2283191cd40e9573747d663763a28dad0d64adc13840 -a987ce205f923100df0fbd5a85f22c9b99b9b9cbe6ddfa8dfda1b8fe95b4f71ff01d6c5b64ca02eb24edb2b255a14ef0 -84fe8221a9e95d9178359918a108de4763ebfa7a6487facb9c963406882a08a9a93f492f8e77cf9e7ea41ae079c45993 -aa1cf3dc7c5dcfa15bbbc811a4bb6dbac4fba4f97fb1ed344ab60264d7051f6eef19ea9773441d89929ee942ed089319 -8f6a7d610d59d9f54689bbe6a41f92d9f6096cde919c1ab94c3c7fcecf0851423bc191e5612349e10f855121c0570f56 -b5af1fa7894428a53ea520f260f3dc3726da245026b6d5d240625380bfb9c7c186df0204bb604efac5e613a70af5106e -a5bce6055ff812e72ce105f147147c7d48d7a2313884dd1f488b1240ee320f13e8a33f5441953a8e7a3209f65b673ce1 -b9b55b4a1422677d95821e1d042ab81bbf0bf087496504021ec2e17e238c2ca6b44fb3b635a5c9eac0871a724b8d47c3 -941c38e533ce4a673a3830845b56786585e5fe49c427f2e5c279fc6db08530c8f91db3e6c7822ec6bb4f956940052d18 -a38e191d66c625f975313c7007bbe7431b5a06ed2da1290a7d5d0f2ec73770d476efd07b8e632de64597d47df175cbb0 -94ba76b667abf055621db4c4145d18743a368d951565632ed4e743dd50dd3333507c0c34f286a5c5fdbf38191a2255cd -a5ca38c60be5602f2bfa6e00c687ac96ac36d517145018ddbee6f12eb0faa63dd57909b9eeed26085fe5ac44e55d10ab -b00fea3b825e60c1ed1c5deb4b551aa65a340e5af36b17d5262c9cd2c508711e4dc50dc2521a2c16c7c901902266e64a -971b86fc4033485e235ccb0997a236206ba25c6859075edbcdf3c943116a5030b7f75ebca9753d863a522ba21a215a90 -b3b31f52370de246ee215400975b674f6da39b2f32514fe6bd54e747752eedca22bb840493b44a67df42a3639c5f901f -affbbfac9c1ba7cbfa1839d2ae271dd6149869b75790bf103230637da41857fc326ef3552ff31c15bda0694080198143 -a95d42aa7ef1962520845aa3688f2752d291926f7b0d73ea2ee24f0612c03b43f2b0fe3c9a9a99620ffc8d487b981bc2 -914a266065caf64985e8c5b1cb2e3f4e3fe94d7d085a1881b1fefa435afef4e1b39a98551d096a62e4f5cc1a7f0fdc2e -81a0b4a96e2b75bc1bf2dbd165d58d55cfd259000a35504d1ffb18bc346a3e6f07602c683723864ffb980f840836fd8d -91c1556631cddd4c00b65b67962b39e4a33429029d311c8acf73a18600e362304fb68bccb56fde40f49e95b7829e0b87 -8befbacc19e57f7c885d1b7a6028359eb3d80792fe13b92a8400df21ce48deb0bb60f2ddb50e3d74f39f85d7eab23adc -92f9458d674df6e990789690ec9ca73dacb67fc9255b58c417c555a8cc1208ace56e8e538f86ba0f3615573a0fbac00d -b4b1b3062512d6ae7417850c08c13f707d5838e43d48eb98dd4621baf62eee9e82348f80fe9b888a12874bfa538771f8 -a13c4a3ac642ede37d9c883f5319e748d2b938f708c9d779714108a449b343f7b71a6e3ef4080fee125b416762920273 -af44983d5fc8cceee0551ef934e6e653f2d3efa385e5c8a27a272463a6f333e290378cc307c2b664eb923c78994e706e -a389fd6c59fe2b4031cc244e22d3991e541bd203dd5b5e73a6159e72df1ab41d49994961500dcde7989e945213184778 -8d2141e4a17836c548de9598d7b298b03f0e6c73b7364979a411c464e0628e21cff6ac3d6decdba5d1c4909eff479761 -980b22ef53b7bdf188a3f14bc51b0dbfdf9c758826daa3cbc1e3986022406a8aa9a6a79e400567120b88c67faa35ce5f -a28882f0a055f96df3711de5d0aa69473e71245f4f3e9aa944e9d1fb166e02caa50832e46da6d3a03b4801735fd01b29 -8db106a37d7b88f5d995c126abb563934dd8de516af48e85695d02b1aea07f79217e3cdd03c6f5ca57421830186c772b -b5a7e50da0559a675c472f7dfaee456caab6695ab7870541b2be8c2b118c63752427184aad81f0e1afc61aef1f28c46f -9962118780e20fe291d10b64f28d09442a8e1b5cffd0f3dd68d980d0614050a626c616b44e9807fbee7accecae00686a -b38ddf33745e8d2ad6a991aefaf656a33c5f8cbe5d5b6b6fd03bd962153d8fd0e01b5f8f96d80ae53ab28d593ab1d4e7 -857dc12c0544ff2c0c703761d901aba636415dee45618aba2e3454ff9cbc634a85c8b05565e88520ff9be2d097c8b2b1 -a80d465c3f8cc63af6d74a6a5086b626c1cb4a8c0fee425964c3bd203d9d7094e299f81ce96d58afc20c8c9a029d9dae -89e1c8fbde8563763be483123a3ed702efac189c6d8ab4d16c85e74bbaf856048cc42d5d6e138633a38572ba5ec3f594 -893a594cf495535f6d216508f8d03c317dcf03446668cba688da90f52d0111ac83d76ad09bf5ea47056846585ee5c791 -aadbd8be0ae452f7f9450c7d2957598a20cbf10139a4023a78b4438172d62b18b0de39754dd2f8862dbd50a3a0815e53 -ae7d39670ecca3eb6db2095da2517a581b0e8853bdfef619b1fad9aacd443e7e6a40f18209fadd44038a55085c5fe8b2 -866ef241520eacb6331593cfcb206f7409d2f33d04542e6e52cba5447934e02d44c471f6c9a45963f9307e9809ab91d9 -b1a09911ad3864678f7be79a9c3c3eb5c84a0a45f8dcb52c67148f43439aeaaa9fd3ed3471276b7e588b49d6ebe3033a -add07b7f0dbb34049cd8feeb3c18da5944bf706871cfd9f14ff72f6c59ad217ebb1f0258b13b167851929387e4e34cfe -ae048892d5c328eefbdd4fba67d95901e3c14d974bfc0a1fc68155ca9f0d59e61d7ba17c6c9948b120cf35fd26e6fee9 -9185b4f3b7da0ddb4e0d0f09b8a9e0d6943a4611e43f13c3e2a767ed8592d31e0ba3ebe1914026a3627680274291f6e5 -a9c022d4e37b0802284ce3b7ee9258628ab4044f0db4de53d1c3efba9de19d15d65cc5e608dbe149c21c2af47d0b07b5 -b24dbd5852f8f24921a4e27013b6c3fa8885b973266cb839b9c388efad95821d5d746348179dcc07542bd0d0aefad1ce -b5fb4f279300876a539a27a441348764908bc0051ebd66dc51739807305e73db3d2f6f0f294ffb91b508ab150eaf8527 -ace50841e718265b290c3483ed4b0fdd1175338c5f1f7530ae9a0e75d5f80216f4de37536adcbc8d8c95982e88808cd0 -b19cadcde0f63bd1a9c24bd9c2806f53c14c0b9735bf351601498408ba503ddbd2037c891041cbba47f58b8c483f3b21 -b6061e63558d312eb891b97b39aa552fa218568d79ee26fe6dd5b864aea9e3216d8f2e2f3b093503be274766dac41426 -89730fdb2876ab6f0fe780d695f6e12090259027e789b819956d786e977518057e5d1d7f5ab24a3ae3d5d4c97773bd2b -b6fa841e81f9f2cad0163a02a63ae96dc341f7ae803b616efc6e1da2fbea551c1b96b11ad02c4afbdf6d0cc9f23da172 -8fb66187182629c861ddb6896d7ed3caf2ad050c3dba8ab8eb0d7a2c924c3d44c48d1a148f9e33fb1f061b86972f8d21 -86022ac339c1f84a7fa9e05358c1a5b316b4fc0b83dbe9c8c7225dc514f709d66490b539359b084ce776e301024345fa -b50b9c321468da950f01480bb62b6edafd42f83c0001d6e97f2bd523a1c49a0e8574fb66380ea28d23a7c4d54784f9f0 -a31c05f7032f30d1dac06678be64d0250a071fd655e557400e4a7f4c152be4d5c7aa32529baf3e5be7c4bd49820054f6 -b95ac0848cd322684772119f5b682d90a66bbf9dac411d9d86d2c34844bbd944dbaf8e47aa41380455abd51687931a78 -ae4a6a5ce9553b65a05f7935e61e496a4a0f6fd8203367a2c627394c9ce1e280750297b74cdc48fd1d9a31e93f97bef4 -a22daf35f6e9b05e52e0b07f7bd1dbbebd2c263033fb0e1b2c804e2d964e2f11bc0ece6aca6af079dd3a9939c9c80674 -902150e0cb1f16b9b59690db35281e28998ce275acb313900da8b2d8dfd29fa1795f8ca3ff820c31d0697de29df347c1 -b17b5104a5dc665cdd7d47e476153d715eb78c6e5199303e4b5445c21a7fa7cf85fe7cfd08d7570f4e84e579b005428c -a03f49b81c15433f121680aa02d734bb9e363af2156654a62bcb5b2ba2218398ccb0ff61104ea5d7df5b16ea18623b1e -802101abd5d3c88876e75a27ffc2f9ddcce75e6b24f23dba03e5201281a7bd5cc7530b6a003be92d225093ca17d3c3bb -a4d183f63c1b4521a6b52226fc19106158fc8ea402461a5cccdaa35fee93669df6a8661f45c1750cd01308149b7bf08e -8d17c22e0c8403b69736364d460b3014775c591032604413d20a5096a94d4030d7c50b9fe3240e31d0311efcf9816a47 -947225acfcce5992eab96276f668c3cbe5f298b90a59f2bb213be9997d8850919e8f496f182689b5cbd54084a7332482 -8df6f4ed216fc8d1905e06163ba1c90d336ab991a18564b0169623eb39b84e627fa267397da15d3ed754d1f3423bff07 -83480007a88f1a36dea464c32b849a3a999316044f12281e2e1c25f07d495f9b1710b4ba0d88e9560e72433addd50bc2 -b3019d6e591cf5b33eb972e49e06c6d0a82a73a75d78d383dd6f6a4269838289e6e07c245f54fed67f5c9bb0fd5e1c5f -92e8ce05e94927a9fb02debadb99cf30a26172b2705003a2c0c47b3d8002bf1060edb0f6a5750aad827c98a656b19199 -ac2aff801448dbbfc13cca7d603fd9c69e82100d997faf11f465323b97255504f10c0c77401e4d1890339d8b224f5803 -b0453d9903d08f508ee27e577445dc098baed6cde0ac984b42e0f0efed62760bd58d5816cf1e109d204607b7b175e30c -ae68dc4ba5067e825d46d2c7c67f1009ceb49d68e8d3e4c57f4bcd299eb2de3575d42ea45e8722f8f28497a6e14a1cfe -b22486c2f5b51d72335ce819bbafb7fa25eb1c28a378a658f13f9fc79cd20083a7e573248d911231b45a5cf23b561ca7 -89d1201d1dbd6921867341471488b4d2fd0fc773ae1d4d074c78ae2eb779a59b64c00452c2a0255826fca6b3d03be2b1 -a2998977c91c7a53dc6104f5bc0a5b675e5350f835e2f0af69825db8af4aeb68435bdbcc795f3dd1f55e1dd50bc0507f -b0be4937a925b3c05056ed621910d535ccabf5ab99fd3b9335080b0e51d9607d0fd36cb5781ff340018f6acfca4a9736 -aea145a0f6e0ba9df8e52e84bb9c9de2c2dc822f70d2724029b153eb68ee9c17de7d35063dcd6a39c37c59fdd12138f7 -91cb4545d7165ee8ffbc74c874baceca11fdebbc7387908d1a25877ca3c57f2c5def424dab24148826832f1e880bede0 -b3b579cb77573f19c571ad5eeeb21f65548d7dff9d298b8d7418c11f3e8cd3727c5b467f013cb87d6861cfaceee0d2e3 -b98a1eeec2b19fecc8378c876d73645aa52fb99e4819903735b2c7a885b242787a30d1269a04bfb8573d72d9bbc5f0f0 -940c1f01ed362bd588b950c27f8cc1d52276c71bb153d47f07ec85b038c11d9a8424b7904f424423e714454d5e80d1cd -aa343a8ecf09ce11599b8cf22f7279cf80f06dbf9f6d62cb05308dbbb39c46fd0a4a1240b032665fbb488a767379b91b -87c3ac72084aca5974599d3232e11d416348719e08443acaba2b328923af945031f86432e170dcdd103774ec92e988c9 -91d6486eb5e61d2b9a9e742c20ec974a47627c6096b3da56209c2b4e4757f007e793ebb63b2b246857c9839b64dc0233 -aebcd3257d295747dd6fc4ff910d839dd80c51c173ae59b8b2ec937747c2072fa85e3017f9060aa509af88dfc7529481 -b3075ba6668ca04eff19efbfa3356b92f0ab12632dcda99cf8c655f35b7928c304218e0f9799d68ef9f809a1492ff7db -93ba7468bb325639ec2abd4d55179c69fd04eaaf39fc5340709227bbaa4ad0a54ea8b480a1a3c8d44684e3be0f8d1980 -a6aef86c8c0d92839f38544d91b767c582568b391071228ff5a5a6b859c87bf4f81a7d926094a4ada1993ddbd677a920 -91dcd6d14207aa569194aa224d1e5037b999b69ade52843315ca61ba26abe9a76412c9e88259bc5cf5d7b95b97d9c3bc -b3b483d31c88f78d49bd065893bc1e3d2aa637e27dedb46d9a7d60be7660ce7a10aaaa7deead362284a52e6d14021178 -8e5730070acf8371461ef301cc4523e8e672aa0e3d945d438a0e0aa6bdf8cb9c685dcf38df429037b0c8aff3955c6f5b -b8c6d769890a8ee18dc4f9e917993315877c97549549b34785a92543cbeec96a08ae3a28d6e809c4aacd69de356c0012 -95ca86cd384eaceaa7c077c5615736ca31f36824bd6451a16142a1edc129fa42b50724aeed7c738f08d7b157f78b569e -94df609c6d71e8eee7ab74226e371ccc77e01738fe0ef1a6424435b4570fe1e5d15797b66ed0f64eb88d4a3a37631f0e -89057b9783212add6a0690d6bb99097b182738deff2bd9e147d7fd7d6c8eacb4c219923633e6309ad993c24572289901 -83a0f9f5f265c5a0e54defa87128240235e24498f20965009fef664f505a360b6fb4020f2742565dfc7746eb185bcec0 -91170da5306128931349bc3ed50d7df0e48a68b8cc8420975170723ac79d8773e4fa13c5f14dc6e3fafcad78379050b1 -b7178484d1b55f7e56a4cc250b6b2ec6040437d96bdfddfa7b35ed27435860f3855c2eb86c636f2911b012eb83b00db8 -ac0b00c4322d1e4208e09cd977b4e54d221133ff09551f75b32b0b55d0e2be80941dda26257b0e288c162e63c7e9cf68 -9690ed9e7e53ed37ff362930e4096b878b12234c332fd19d5d064824084245952eda9f979e0098110d6963e468cf513e -b6fa547bb0bb83e5c5be0ed462a8783fba119041c136a250045c09d0d2af330c604331e7de960df976ff76d67f8000cd -814603907c21463bcf4e59cfb43066dfe1a50344ae04ef03c87c0f61b30836c3f4dea0851d6fa358c620045b7f9214c8 -9495639e3939fad2a3df00a88603a5a180f3c3a0fe4d424c35060e2043e0921788003689887b1ed5be424d9a89bb18bb -aba4c02d8d57f2c92d5bc765885849e9ff8393d6554f5e5f3e907e5bfac041193a0d8716d7861104a4295d5a03c36b03 -8ead0b56c1ca49723f94a998ba113b9058059321da72d9e395a667e6a63d5a9dac0f5717cec343f021695e8ced1f72af -b43037f7e3852c34ed918c5854cd74e9d5799eeddfe457d4f93bb494801a064735e326a76e1f5e50a339844a2f4a8ec9 -99db8422bb7302199eb0ff3c3d08821f8c32f53a600c5b6fb43e41205d96adae72be5b460773d1280ad1acb806af9be8 -8a9be08eae0086c0f020838925984df345c5512ff32e37120b644512b1d9d4fecf0fd30639ca90fc6cf334a86770d536 -81b43614f1c28aa3713a309a88a782fb2bdfc4261dd52ddc204687791a40cf5fd6a263a8179388596582cccf0162efc2 -a9f3a8b76912deb61d966c75daf5ddb868702ebec91bd4033471c8e533183df548742a81a2671de5be63a502d827437d -902e2415077f063e638207dc7e14109652e42ab47caccd6204e2870115791c9defac5425fd360b37ac0f7bd8fe7011f8 -aa18e4fdc1381b59c18503ae6f6f2d6943445bd00dd7d4a2ad7e5adad7027f2263832690be30d456e6d772ad76f22350 -a348b40ba3ba7d81c5d4631f038186ebd5e5f314f1ea737259151b07c3cc8cf0c6ed4201e71bcc1c22fefda81a20cde6 -aa1306f7ac1acbfc47dc6f7a0cb6d03786cec8c8dc8060388ccda777bca24bdc634d03e53512c23dba79709ff64f8620 -818ccfe46e700567b7f3eb400e5a35f6a5e39b3db3aa8bc07f58ace35d9ae5a242faf8dbccd08d9a9175bbce15612155 -b7e3da2282b65dc8333592bb345a473f03bd6df69170055fec60222de9897184536bf22b9388b08160321144d0940279 -a4d976be0f0568f4e57de1460a1729129252b44c552a69fceec44e5b97c96c711763360d11f9e5bf6d86b4976bf40d69 -85d185f0397c24c2b875b09b6328a23b87982b84ee880f2677a22ff4c9a1ba9f0fea000bb3f7f66375a00d98ebafce17 -b4ccbb8c3a2606bd9b87ce022704663af71d418351575f3b350d294f4efc68c26f9a2ce49ff81e6ff29c3b63d746294e -93ffd3265fddb63724dfde261d1f9e22f15ecf39df28e4d89e9fea03221e8e88b5dd9b77628bacaa783c6f91802d47cc -b1fd0f8d7a01378e693da98d03a2d2fda6b099d03454b6f2b1fa6472ff6bb092751ce6290059826b74ac0361eab00e1e -a89f440c71c561641589796994dd2769616b9088766e983c873fae0716b95c386c8483ab8a4f367b6a68b72b7456dd32 -af4fe92b01d42d03dd5d1e7fa55e96d4bbcb7bf7d4c8c197acd16b3e0f3455807199f683dcd263d74547ef9c244b35cc -a8227f6e0a344dfe76bfbe7a1861be32c4f4bed587ccce09f9ce2cf481b2dda8ae4f566154bc663d15f962f2d41761bd -a7b361663f7495939ed7f518ba45ea9ff576c4e628995b7aea026480c17a71d63fc2c922319f0502eb7ef8f14a406882 -8ddcf382a9f39f75777160967c07012cfa89e67b19714a7191f0c68eaf263935e5504e1104aaabd0899348c972a8d3c6 -98c95b9f6f5c91f805fb185eedd06c6fc4457d37dd248d0be45a6a168a70031715165ea20606245cbdf8815dc0ac697f -805b44f96e001e5909834f70c09be3efcd3b43632bcac5b6b66b6d227a03a758e4b1768ce2a723045681a1d34562aaeb -b0e81b07cdc45b3dca60882676d9badb99f25c461b7efe56e3043b80100bb62d29e1873ae25eb83087273160ece72a55 -b0c53f0abe78ee86c7b78c82ae1f7c070bb0b9c45c563a8b3baa2c515d482d7507bb80771e60b38ac13f78b8af92b4a9 -a7838ef6696a9e4d2e5dfd581f6c8d6a700467e8fd4e85adabb5f7a56f514785dd4ab64f6f1b48366f7d94728359441b -88c76f7700a1d23c30366a1d8612a796da57b2500f97f88fdf2d76b045a9d24e7426a8ffa2f4e86d3046937a841dad58 -ad8964baf98c1f02e088d1d9fcb3af6b1dfa44cdfe0ed2eae684e7187c33d3a3c28c38e8f4e015f9c04d451ed6f85ff6 -90e9d00a098317ececaa9574da91fc149eda5b772dedb3e5a39636da6603aa007804fa86358550cfeff9be5a2cb7845e -a56ff4ddd73d9a6f5ab23bb77efa25977917df63571b269f6a999e1ad6681a88387fcc4ca3b26d57badf91b236503a29 -97ad839a6302c410a47e245df84c01fb9c4dfef86751af3f9340e86ff8fc3cd52fa5ff0b9a0bd1d9f453e02ca80658a6 -a4c8c44cbffa804129e123474854645107d1f0f463c45c30fd168848ebea94880f7c0c5a45183e9eb837f346270bdb35 -a72e53d0a1586d736e86427a93569f52edd2f42b01e78aee7e1961c2b63522423877ae3ac1227a2cf1e69f8e1ff15bc3 -8559f88a7ef13b4f09ac82ae458bbae6ab25671cfbf52dae7eac7280d6565dd3f0c3286aec1a56a8a16dc3b61d78ce47 -8221503f4cdbed550876c5dc118a3f2f17800c04e8be000266633c83777b039a432d576f3a36c8a01e8fd18289ebc10b -99bfbe5f3e46d4d898a578ba86ed26de7ed23914bd3bcdf3c791c0bcd49398a52419077354a5ab75cea63b6c871c6e96 -aa134416d8ff46f2acd866c1074af67566cfcf4e8be8d97329dfa0f603e1ff208488831ce5948ac8d75bfcba058ddcaa -b02609d65ebfe1fe8e52f21224a022ea4b5ea8c1bd6e7b9792eed8975fc387cdf9e3b419b8dd5bcce80703ab3a12a45f -a4f14798508698fa3852e5cac42a9db9797ecee7672a54988aa74037d334819aa7b2ac7b14efea6b81c509134a6b7ad2 -884f01afecbcb987cb3e7c489c43155c416ed41340f61ecb651d8cba884fb9274f6d9e7e4a46dd220253ae561614e44c -a05523c9e71dce1fe5307cc71bd721feb3e1a0f57a7d17c7d1c9fb080d44527b7dbaa1f817b1af1c0b4322e37bc4bb1e -8560aec176a4242b39f39433dd5a02d554248c9e49d3179530815f5031fee78ba9c71a35ceeb2b9d1f04c3617c13d8f0 -996aefd402748d8472477cae76d5a2b92e3f092fc834d5222ae50194dd884c9fb8b6ed8e5ccf8f6ed483ddbb4e80c747 -8fd09900320000cbabc40e16893e2fcf08815d288ec19345ad7b6bb22f7d78a52b6575a3ca1ca2f8bc252d2eafc928ec -939e51f73022bc5dc6862a0adf8fb8a3246b7bfb9943cbb4b27c73743926cc20f615a036c7e5b90c80840e7f1bfee0e7 -a0a6258700cadbb9e241f50766573bf9bdb7ad380b1079dc3afb4054363d838e177b869cad000314186936e40359b1f2 -972699a4131c8ed27a2d0e2104d54a65a7ff1c450ad9da3a325c662ab26869c21b0a84d0700b98c8b5f6ce3b746873d7 -a454c7fe870cb8aa6491eafbfb5f7872d6e696033f92e4991d057b59d70671f2acdabef533e229878b60c7fff8f748b1 -a167969477214201f09c79027b10221e4707662e0c0fde81a0f628249f2f8a859ce3d30a7dcc03b8ecca8f7828ad85c7 -8ff6b7265175beb8a63e1dbf18c9153fb2578c207c781282374f51b40d57a84fd2ef2ea2b9c6df4a54646788a62fd17f -a3d7ebeccde69d73d8b3e76af0da1a30884bb59729503ff0fb0c3bccf9221651b974a6e72ea33b7956fc3ae758226495 -b71ef144c9a98ce5935620cb86c1590bd4f48e5a2815d25c0cdb008fde628cf628c31450d3d4f67abbfeb16178a74cfd -b5e0a16d115134f4e2503990e3f2035ed66b9ccf767063fe6747870d97d73b10bc76ed668550cb82eedc9a2ca6f75524 -b30ffaaf94ee8cbc42aa2c413175b68afdb207dbf351fb20be3852cb7961b635c22838da97eaf43b103aff37e9e725cc -98aa7d52284f6c1f22e272fbddd8c8698cf8f5fbb702d5de96452141fafb559622815981e50b87a72c2b1190f59a7deb -81fbacda3905cfaf7780bb4850730c44166ed26a7c8d07197a5d4dcd969c09e94a0461638431476c16397dd7bdc449f9 -95e47021c1726eac2e5853f570d6225332c6e48e04c9738690d53e07c6b979283ebae31e2af1fc9c9b3e59f87e5195b1 -ac024a661ba568426bb8fce21780406537f518075c066276197300841e811860696f7588188bc01d90bace7bc73d56e3 -a4ebcaf668a888dd404988ab978594dee193dad2d0aec5cdc0ccaf4ec9a7a8228aa663db1da8ddc52ec8472178e40c32 -a20421b8eaf2199d93b083f2aff37fb662670bd18689d046ae976d1db1fedd2c2ff897985ecc6277b396db7da68bcb27 -8bc33d4b40197fd4d49d1de47489d10b90d9b346828f53a82256f3e9212b0cbc6930b895e879da9cec9fedf026aadb3e -aaafdd1bec8b757f55a0433eddc0a39f818591954fd4e982003437fcceb317423ad7ee74dbf17a2960380e7067a6b4e2 -aad34277ebaed81a6ec154d16736866f95832803af28aa5625bf0461a71d02b1faba02d9d9e002be51c8356425a56867 -976e9c8b150d08706079945bd0e84ab09a648ecc6f64ded9eb5329e57213149ae409ae93e8fbd8eda5b5c69f5212b883 -8097fae1653247d2aed4111533bc378171d6b2c6d09cbc7baa9b52f188d150d645941f46d19f7f5e27b7f073c1ebd079 -83905f93b250d3184eaba8ea7d727c4464b6bdb027e5cbe4f597d8b9dc741dcbea709630bd4fd59ce24023bec32fc0f3 -8095030b7045cff28f34271386e4752f9a9a0312f8df75de4f424366d78534be2b8e1720a19cb1f9a2d21105d790a225 -a7b7b73a6ae2ed1009c49960374b0790f93c74ee03b917642f33420498c188a169724945a975e5adec0a1e83e07fb1b2 -856a41c54df393b6660b7f6354572a4e71c8bfca9cabaffb3d4ef2632c015e7ee2bc10056f3eccb3dbed1ad17d939178 -a8f7a55cf04b38cd4e330394ee6589da3a07dc9673f74804fdf67b364e0b233f14aec42e783200a2e4666f7c5ff62490 -82c529f4e543c6bca60016dc93232c115b359eaee2798a9cf669a654b800aafe6ab4ba58ea8b9cdda2b371c8d62fa845 -8caab020c1baddce77a6794113ef1dfeafc5f5000f48e97f4351b588bf02f1f208101745463c480d37f588d5887e6d8c -8fa91b3cc400f48b77b6fd77f3b3fbfb3f10cdff408e1fd22d38f77e087b7683adad258804409ba099f1235b4b4d6fea -8aa02787663d6be9a35677d9d8188b725d5fcd770e61b11b64e3def8808ea5c71c0a9afd7f6630c48634546088fcd8e2 -b5635b7b972e195cab878b97dea62237c7f77eb57298538582a330b1082f6207a359f2923864630136d8b1f27c41b9aa -8257bb14583551a65975946980c714ecd6e5b629672bb950b9caacd886fbd22704bc9e3ba7d30778adab65dc74f0203a -ab5fe1cd12634bfa4e5c60d946e2005cbd38f1063ec9a5668994a2463c02449a0a185ef331bd86b68b6e23a8780cb3ba -a7d3487da56cda93570cc70215d438204f6a2709bfb5fda6c5df1e77e2efc80f4235c787e57fbf2c74aaff8cbb510a14 -b61cff7b4c49d010e133319fb828eb900f8a7e55114fc86b39c261a339c74f630e1a7d7e1350244ada566a0ff3d46c4b -8d4d1d55d321d278db7a85522ccceca09510374ca81d4d73e3bb5249ace7674b73900c35a531ec4fa6448fabf7ad00dc -966492248aee24f0f56c8cfca3c8ec6ba3b19abb69ae642041d4c3be8523d22c65c4dafcab4c58989ccc4e0bd2f77919 -b20c320a90cb220b86e1af651cdc1e21315cd215da69f6787e28157172f93fc8285dcd59b039c626ed8ca4633cba1a47 -aae9e6b22f018ceb5c0950210bb8182cb8cb61014b7e14581a09d36ebd1bbfebdb2b82afb7fdb0cf75e58a293d9c456d -875547fb67951ad37b02466b79f0c9b985ccbc500cfb431b17823457dc79fb9597ec42cd9f198e15523fcd88652e63a4 -92afce49773cb2e20fb21e4f86f18e0959ebb9c33361547ddb30454ee8e36b1e234019cbdca0e964cb292f7f77df6b90 -8af85343dfe1821464c76ba11c216cbef697b5afc69c4d821342e55afdac047081ec2e3f7b09fc14b518d9a23b78c003 -b7de4a1648fd63f3a918096ea669502af5357438e69dac77cb8102b6e6c15c76e033cfaa80dafc806e535ede5c1a20aa -ac80e9b545e8bd762951d96c9ce87f629d01ffcde07efc2ef7879ca011f1d0d8a745abf26c9d452541008871304fac00 -a4cf0f7ed724e481368016c38ea5816698a5f68eb21af4d3c422d2ba55f96a33e427c2aa40de1b56a7cfac7f7cf43ab0 -899b0a678bb2db2cae1b44e75a661284844ebcdd87abf308fedeb2e4dbe5c5920c07db4db7284a7af806a2382e8b111a -af0588a2a4afce2b1b13c1230816f59e8264177e774e4a341b289a101dcf6af813638fed14fb4d09cb45f35d5d032609 -a4b8df79e2be76e9f5fc5845f06fe745a724cf37c82fcdb72719b77bdebea3c0e763f37909373e3a94480cc5e875cba0 -83e42c46d88930c8f386b19fd999288f142d325e2ebc86a74907d6d77112cb0d449bc511c95422cc810574031a8cbba9 -b5e39534070de1e5f6e27efbdd3dc917d966c2a9b8cf2d893f964256e95e954330f2442027dc148c776d63a95bcde955 -958607569dc28c075e658cd4ae3927055c6bc456eef6212a6fea8205e48ed8777a8064f584cda38fe5639c371e2e7fba -812adf409fa63575113662966f5078a903212ffb65c9b0bbe62da0f13a133443a7062cb8fd70f5e5dd5559a32c26d2c8 -a679f673e5ce6a3cce7fa31f22ee3785e96bcb55e5a776e2dd3467bef7440e3555d1a9b87cb215e86ee9ed13a090344b -afedbb34508b159eb25eb2248d7fe328f86ef8c7d84c62d5b5607d74aae27cc2cc45ee148eb22153b09898a835c58df4 -b75505d4f6b67d31e665cfaf5e4acdb5838ae069166b7fbcd48937c0608a59e40a25302fcc1873d2e81c1782808c70f0 -b62515d539ec21a155d94fc00ea3c6b7e5f6636937bce18ed5b618c12257fb82571886287fd5d1da495296c663ebc512 -ab8e1a9446bbdd588d1690243b1549d230e6149c28f59662b66a8391a138d37ab594df38e7720fae53217e5c3573b5be -b31e8abf4212e03c3287bb2c0a153065a7290a16764a0bac8f112a72e632185a654bb4e88fdd6053e6c7515d9719fadb -b55165477fe15b6abd2d0f4fddaa9c411710dcc4dd712daba3d30e303c9a3ee5415c256f9dc917ecf18c725b4dbab059 -a0939d4f57cacaae549b78e87cc234de4ff6a35dc0d9cd5d7410abc30ebcd34c135e008651c756e5a9d2ca79c40ef42b -8cf10e50769f3443340844aad4d56ec790850fed5a41fcbd739abac4c3015f0a085a038fbe7fae9f5ad899cce5069f6b -924055e804d82a99ea4bb160041ea4dc14b568abf379010bc1922fde5d664718c31d103b8b807e3a1ae809390e708c73 -8ec0f9d26f71b0f2e60a179e4fd1778452e2ffb129d50815e5d7c7cb9415fa69ae5890578086e8ef6bfde35ad2a74661 -98c7f12b15ec4426b59f737f73bf5faea4572340f4550b7590dfb7f7ffedb2372e3e555977c63946d579544c53210ad0 -8a935f7a955c78f69d66f18eee0092e5e833fa621781c9581058e219af4d7ceee48b84e472e159dda6199715fb2f9acf -b78d4219f95a2dbfaa7d0c8a610c57c358754f4f43c2af312ab0fe8f10a5f0177e475332fb8fd23604e474fc2abeb051 -8d086a14803392b7318c28f1039a17e3cfdcece8abcaca3657ec3d0ac330842098a85c0212f889fabb296dfb133ce9aa -a53249f417aac82f2c2a50c244ce21d3e08a5e5a8bd33bec2a5ab0d6cd17793e34a17edfa3690899244ce201e2fb9986 -8619b0264f9182867a1425be514dc4f1ababc1093138a728a28bd7e4ecc99b9faaff68c23792264bc6e4dce5f52a5c52 -8c171edbbbde551ec19e31b2091eb6956107dd9b1f853e1df23bff3c10a3469ac77a58335eee2b79112502e8e163f3de -a9d19ec40f0ca07c238e9337c6d6a319190bdba2db76fb63902f3fb459aeeb50a1ac30db5b25ee1b4201f3ca7164a7f4 -b9c6ec14b1581a03520b8d2c1fbbc31fb8ceaef2c0f1a0d0080b6b96e18442f1734bea7ef7b635d787c691de4765d469 -8cb437beb4cfa013096f40ccc169a713dc17afee6daa229a398e45fd5c0645a9ad2795c3f0cd439531a7151945d7064d -a6e8740cc509126e146775157c2eb278003e5bb6c48465c160ed27888ca803fa12eee1f6a8dd7f444f571664ed87fdc1 -b75c1fecc85b2732e96b3f23aefb491dbd0206a21d682aee0225838dc057d7ed3b576176353e8e90ae55663f79e986e4 -ad8d249b0aea9597b08358bce6c77c1fd552ef3fbc197d6a1cfe44e5e6f89b628b12a6fb04d5dcfcbacc51f46e4ae7bb -b998b2269932cbd58d04b8e898d373ac4bb1a62e8567484f4f83e224061bc0f212459f1daae95abdbc63816ae6486a55 -827988ef6c1101cddc96b98f4a30365ff08eea2471dd949d2c0a9b35c3bbfa8c07054ad1f4c88c8fbf829b20bb5a9a4f -8692e638dd60babf7d9f2f2d2ce58e0ac689e1326d88311416357298c6a2bffbfebf55d5253563e7b3fbbf5072264146 -a685d75b91aea04dbc14ab3c1b1588e6de96dae414c8e37b8388766029631b28dd860688079b12d09cd27f2c5af11adf -b57eced93eec3371c56679c259b34ac0992286be4f4ff9489d81cf9712403509932e47404ddd86f89d7c1c3b6391b28c -a1c8b4e42ebcbd8927669a97f1b72e236fb19249325659e72be7ddaaa1d9e81ca2abb643295d41a8c04a2c01f9c0efd7 -877c33de20d4ed31674a671ba3e8f01a316581e32503136a70c9c15bf0b7cb7b1cba6cd4eb641fad165fb3c3c6c235fd -a2a469d84ec478da40838f775d11ad38f6596eb41caa139cc190d6a10b5108c09febae34ffdafac92271d2e73c143693 -972f817caedb254055d52e963ed28c206848b6c4cfdb69dbc961c891f8458eaf582a6d4403ce1177d87bc2ea410ef60a -accbd739e138007422f28536381decc54bb6bd71d93edf3890e54f9ef339f83d2821697d1a4ac1f5a98175f9a9ecb9b5 -8940f8772e05389f823b62b3adc3ed541f91647f0318d7a0d3f293aeeb421013de0d0a3664ea53dd24e5fbe02d7efef6 -8ecce20f3ef6212edef07ec4d6183fda8e0e8cad2c6ccd0b325e75c425ee1faba00b5c26b4d95204238931598d78f49d -97cc72c36335bd008afbed34a3b0c7225933faba87f7916d0a6d2161e6f82e0cdcda7959573a366f638ca75d30e9dab1 -9105f5de8699b5bdb6bd3bb6cc1992d1eac23929c29837985f83b22efdda92af64d9c574aa9640475087201bbbe5fd73 -8ffb33c4f6d05c413b9647eb6933526a350ed2e4278ca2ecc06b0e8026d8dbe829c476a40e45a6df63a633090a3f82ef -8bfc6421fdc9c2d2aaa68d2a69b1a2728c25b84944cc3e6a57ff0c94bfd210d1cbf4ff3f06702d2a8257024d8be7de63 -a80e1dc1dddfb41a70220939b96dc6935e00b32fb8be5dff4eed1f1c650002ff95e4af481c43292e3827363b7ec4768a -96f714ebd54617198bd636ba7f7a7f8995a61db20962f2165078d9ed8ee764d5946ef3cbdc7ebf8435bb8d5dd4c1deac -8cdb0890e33144d66391d2ae73f5c71f5a861f72bc93bff6cc399fc25dd1f9e17d8772592b44593429718784802ac377 -8ccf9a7f80800ee770b92add734ed45a73ecc31e2af0e04364eefc6056a8223834c7c0dc9dfc52495bdec6e74ce69994 -aa0875f423bd68b5f10ba978ddb79d3b96ec093bfbac9ff366323193e339ed7c4578760fb60f60e93598bdf1e5cc4995 -a9214f523957b59c7a4cb61a40251ad72aba0b57573163b0dc0f33e41d2df483fb9a1b85a5e7c080e9376c866790f8cb -b6224b605028c6673a536cc8ff9aeb94e7a22e686fda82cf16068d326469172f511219b68b2b3affb7933af0c1f80d07 -b6d58968d8a017c6a34e24c2c09852f736515a2c50f37232ac6b43a38f8faa7572cc31dade543b594b61b5761c4781d0 -8a97cefe5120020c38deeb861d394404e6c993c6cbd5989b6c9ebffe24f46ad11b4ba6348e2991cbf3949c28cfc3c99d -95bf046f8c3a9c0ce2634be4de3713024daec3fc4083e808903b25ce3ac971145af90686b451efcc72f6b22df0216667 -a6a4e2f71b8fa28801f553231eff2794c0f10d12e7e414276995e21195abc9c2983a8997e41af41e78d19ff6fbb2680b -8e5e62a7ca9c2f58ebaab63db2ff1fb1ff0877ae94b7f5e2897f273f684ae639dff44cc65718f78a9c894787602ab26a -8542784383eec4f565fcb8b9fc2ad8d7a644267d8d7612a0f476fc8df3aff458897a38003d506d24142ad18f93554f2b -b7db68ba4616ea072b37925ec4fb39096358c2832cc6d35169e032326b2d6614479f765ae98913c267105b84afcb9bf2 -8b31dbb9457d23d416c47542c786e07a489af35c4a87dadb8ee91bea5ac4a5315e65625d78dad2cf8f9561af31b45390 -a8545a1d91ac17257732033d89e6b7111db8242e9c6ebb0213a88906d5ef407a2c6fdb444e29504b06368b6efb4f4839 -b1bd85d29ebb28ccfb05779aad8674906b267c2bf8cdb1f9a0591dd621b53a4ee9f2942687ee3476740c0b4a7621a3ae -a2b54534e152e46c50d91fff03ae9cd019ff7cd9f4168b2fe7ac08ef8c3bbc134cadd3f9d6bd33d20ae476c2a8596c8a -b19b571ff4ae3e9f5d95acda133c455e72c9ea9973cae360732859836c0341c4c29ab039224dc5bc3deb824e031675d8 -940b5f80478648bac025a30f3efeb47023ce20ee98be833948a248bca6979f206bb28fc0f17b90acf3bb4abd3d14d731 -8f106b40588586ac11629b96d57808ad2808915d89539409c97414aded90b4ff23286a692608230a52bff696055ba5d6 -ae6bda03aa10da3d2abbc66d764ca6c8d0993e7304a1bdd413eb9622f3ca1913baa6da1e9f4f9e6cf847f14f44d6924d -a18e7796054a340ef826c4d6b5a117b80927afaf2ebd547794c400204ae2caf277692e2eabb55bc2f620763c9e9da66d -8d2d25180dc2c65a4844d3e66819ccfcf48858f0cc89e1c77553b463ec0f7feb9a4002ce26bc618d1142549b9850f232 -863f413a394de42cc8166c1c75d513b91d545fff1de6b359037a742c70b008d34bf8e587afa2d62c844d0c6f0ea753e7 -83cd0cf62d63475e7fcad18a2e74108499cdbf28af2113cfe005e3b5887794422da450b1944d0a986eb7e1f4c3b18f25 -b4f8b350a6d88fea5ab2e44715a292efb12eb52df738c9b2393da3f1ddee68d0a75b476733ccf93642154bceb208f2b8 -b3f52aaa4cd4221cb9fc45936cc67fd3864bf6d26bf3dd86aa85aa55ecfc05f5e392ecce5e7cf9406b4b1c4fce0398c8 -b33137084422fb643123f40a6df2b498065e65230fc65dc31791c330e898c51c3a65ff738930f32c63d78f3c9315f85b -91452bfa75019363976bb7337fe3a73f1c10f01637428c135536b0cdc7da5ce558dae3dfc792aa55022292600814a8ef -ad6ba94c787cd4361ca642c20793ea44f1f127d4de0bb4a77c7fbfebae0fcadbf28e2cb6f0c12c12a07324ec8c19761d -890aa6248b17f1501b0f869c556be7bf2b1d31a176f9978bb97ab7a6bd4138eed32467951c5ef1871944b7f620542f43 -82111db2052194ee7dd22ff1eafffac0443cf969d3762cceae046c9a11561c0fdce9c0711f88ac01d1bed165f8a7cee3 -b1527b71df2b42b55832f72e772a466e0fa05743aacc7814f4414e4bcc8d42a4010c9e0fd940e6f254cafedff3cd6543 -922370fa49903679fc565f09c16a5917f8125e72acfeb060fcdbadbd1644eb9f4016229756019c93c6d609cda5d5d174 -aa4c7d98a96cab138d2a53d4aee8ebff6ef903e3b629a92519608d88b3bbd94de5522291a1097e6acf830270e64c8ee1 -b3dc21608a389a72d3a752883a382baaafc61ecc44083b832610a237f6a2363f24195acce529eb4aed4ef0e27a12b66e -94619f5de05e07b32291e1d7ab1d8b7337a2235e49d4fb5f3055f090a65e932e829efa95db886b32b153bdd05a53ec8c -ade1e92722c2ffa85865d2426fb3d1654a16477d3abf580cfc45ea4b92d5668afc9d09275d3b79283e13e6b39e47424d -b7201589de7bed094911dd62fcd25c459a8e327ac447b69f541cdba30233063e5ddffad0b67e9c3e34adcffedfd0e13d -809d325310f862d6549e7cb40f7e5fc9b7544bd751dd28c4f363c724a0378c0e2adcb5e42ec8f912f5f49f18f3365c07 -a79c20aa533de7a5d671c99eb9eb454803ba54dd4f2efa3c8fec1a38f8308e9905c71e9282955225f686146388506ff6 -a85eeacb5e8fc9f3ed06a3fe2dc3108ab9f8c5877b148c73cf26e4e979bf5795edbe2e63a8d452565fd1176ed40402b2 -97ef55662f8a1ec0842b22ee21391227540adf7708f491436044f3a2eb18c471525e78e1e14fa292507c99d74d7437c6 -93110d64ed5886f3d16ce83b11425576a3a7a9bb831cd0de3f9a0b0f2270a730d68136b4ef7ff035ede004358f419b5c -ac9ed0a071517f0ae4f61ce95916a90ba9a77a3f84b0ec50ef7298acdcd44d1b94525d191c39d6bd1bb68f4471428760 -98abd6a02c7690f5a339adf292b8c9368dfc12e0f8069cf26a5e0ce54b4441638f5c66ea735142f3c28e00a0024267e6 -b51efb73ba6d44146f047d69b19c0722227a7748b0e8f644d0fc9551324cf034c041a2378c56ce8b58d06038fb8a78de -8f115af274ef75c1662b588b0896b97d71f8d67986ae846792702c4742ab855952865ce236b27e2321967ce36ff93357 -b3c4548f14d58b3ab03c222da09e4381a0afe47a72d18d50a94e0008797f78e39e99990e5b4757be62310d400746e35a -a9b1883bd5f31f909b8b1b6dcb48c1c60ed20aa7374b3ffa7f5b2ed036599b5bef33289d23c80a5e6420d191723b92f7 -85d38dffd99487ae5bb41ab4a44d80a46157bbbe8ef9497e68f061721f74e4da513ccc3422936b059575975f6787c936 -adf870fcb96e972c033ab7a35d28ae79ee795f82bc49c3bd69138f0e338103118d5529c53f2d72a9c0d947bf7d312af2 -ab4c7a44e2d9446c6ff303eb49aef0e367a58b22cc3bb27b4e69b55d1d9ee639c9234148d2ee95f9ca8079b1457d5a75 -a386420b738aba2d7145eb4cba6d643d96bda3f2ca55bb11980b318d43b289d55a108f4bc23a9606fb0bccdeb3b3bb30 -847020e0a440d9c4109773ecca5d8268b44d523389993b1f5e60e541187f7c597d79ebd6e318871815e26c96b4a4dbb1 -a530aa7e5ca86fcd1bec4b072b55cc793781f38a666c2033b510a69e110eeabb54c7d8cbcb9c61fee531a6f635ffa972 -87364a5ea1d270632a44269d686b2402da737948dac27f51b7a97af80b66728b0256547a5103d2227005541ca4b7ed04 -8816fc6e16ea277de93a6d793d0eb5c15e9e93eb958c5ef30adaf8241805adeb4da8ce19c3c2167f971f61e0b361077d -8836a72d301c42510367181bb091e4be377777aed57b73c29ef2ce1d475feedd7e0f31676284d9a94f6db01cc4de81a2 -b0d9d8b7116156d9dde138d28aa05a33e61f8a85839c1e9071ccd517b46a5b4b53acb32c2edd7150c15bc1b4bd8db9e3 -ae931b6eaeda790ba7f1cd674e53dc87f6306ff44951fa0df88d506316a5da240df9794ccbd7215a6470e6b31c5ea193 -8c6d5bdf87bd7f645419d7c6444e244fe054d437ed1ba0c122fde7800603a5fadc061e5b836cb22a6cfb2b466f20f013 -90d530c6d0cb654999fa771b8d11d723f54b8a8233d1052dc1e839ea6e314fbed3697084601f3e9bbb71d2b4eaa596df -b0d341a1422588c983f767b1ed36c18b141774f67ef6a43cff8e18b73a009da10fc12120938b8bba27f225bdfd3138f9 -a131b56f9537f460d304e9a1dd75702ace8abd68cb45419695cb8dee76998139058336c87b7afd6239dc20d7f8f940cc -aa6c51fa28975f709329adee1bbd35d49c6b878041841a94465e8218338e4371f5cb6c17f44a63ac93644bf28f15d20f -88440fb584a99ebd7f9ea04aaf622f6e44e2b43bbb49fb5de548d24a238dc8f26c8da2ccf03dd43102bda9f16623f609 -9777b8695b790e702159a4a750d5e7ff865425b95fa0a3c15495af385b91c90c00a6bd01d1b77bffe8c47d01baae846f -8b9d764ece7799079e63c7f01690c8eff00896a26a0d095773dea7a35967a8c40db7a6a74692f0118bf0460c26739af4 -85808c65c485520609c9e61fa1bb67b28f4611d3608a9f7a5030ee61c3aa3c7e7dc17fff48af76b4aecee2cb0dbd22ac -ad2783a76f5b3db008ef5f7e67391fda4e7e36abde6b3b089fc4835b5c339370287935af6bd53998bed4e399eda1136d -96f18ec03ae47c205cc4242ca58e2eff185c9dca86d5158817e2e5dc2207ab84aadda78725f8dc080a231efdc093b940 -97de1ab6c6cc646ae60cf7b86df73b9cf56cc0cd1f31b966951ebf79fc153531af55ca643b20b773daa7cab784b832f7 -870ba266a9bfa86ef644b1ef025a0f1b7609a60de170fe9508de8fd53170c0b48adb37f19397ee8019b041ce29a16576 -ad990e888d279ac4e8db90619d663d5ae027f994a3992c2fbc7d262b5990ae8a243e19157f3565671d1cb0de17fe6e55 -8d9d5adcdd94c5ba3be4d9a7428133b42e485f040a28d16ee2384758e87d35528f7f9868de9bd23d1a42a594ce50a567 -85a33ed75d514ece6ad78440e42f7fcdb59b6f4cff821188236d20edae9050b3a042ce9bc7d2054296e133d033e45022 -92afd2f49a124aaba90de59be85ff269457f982b54c91b06650c1b8055f9b4b0640fd378df02a00e4fc91f7d226ab980 -8c0ee09ec64bd831e544785e3d65418fe83ed9c920d9bb4d0bf6dd162c1264eb9d6652d2def0722e223915615931581c -8369bedfa17b24e9ad48ebd9c5afea4b66b3296d5770e09b00446c5b0a8a373d39d300780c01dcc1c6752792bccf5fd0 -8b9e960782576a59b2eb2250d346030daa50bbbec114e95cdb9e4b1ba18c3d34525ae388f859708131984976ca439d94 -b682bface862008fea2b5a07812ca6a28a58fd151a1d54c708fc2f8572916e0d678a9cb8dc1c10c0470025c8a605249e -a38d5e189bea540a824b36815fc41e3750760a52be0862c4cac68214febdc1a754fb194a7415a8fb7f96f6836196d82a -b9e7fbda650f18c7eb8b40e42cc42273a7298e65e8be524292369581861075c55299ce69309710e5b843cb884de171bd -b6657e5e31b3193874a1bace08f42faccbd3c502fb73ad87d15d18a1b6c2a146f1baa929e6f517db390a5a47b66c0acf -ae15487312f84ed6265e4c28327d24a8a0f4d2d17d4a5b7c29b974139cf93223435aaebe3af918f5b4bb20911799715f -8bb4608beb06bc394e1a70739b872ce5a2a3ffc98c7547bf2698c893ca399d6c13686f6663f483894bccaabc3b9c56ad -b58ac36bc6847077584308d952c5f3663e3001af5ecf2e19cb162e1c58bd6c49510205d453cffc876ca1dc6b8e04a578 -924f65ced61266a79a671ffb49b300f0ea44c50a0b4e3b02064faa99fcc3e4f6061ea8f38168ab118c5d47bd7804590e -8d67d43b8a06b0ff4fafd7f0483fa9ed1a9e3e658a03fb49d9d9b74e2e24858dc1bed065c12392037b467f255d4e5643 -b4d4f87813125a6b355e4519a81657fa97c43a6115817b819a6caf4823f1d6a1169683fd68f8d025cdfa40ebf3069acb -a7fd4d2c8e7b59b8eed3d4332ae94b77a89a2616347402f880bc81bde072220131e6dbec8a605be3a1c760b775375879 -8d4a7d8fa6f55a30df37bcf74952e2fa4fd6676a2e4606185cf154bdd84643fd01619f8fb8813a564f72e3f574f8ce30 -8086fb88e6260e9a9c42e9560fde76315ff5e5680ec7140f2a18438f15bc2cc7d7d43bfb5880b180b738c20a834e6134 -916c4c54721de03934fee6f43de50bb04c81f6f8dd4f6781e159e71c40c60408aa54251d457369d133d4ba3ed7c12cb4 -902e5bf468f11ed9954e2a4a595c27e34abe512f1d6dc08bbca1c2441063f9af3dc5a8075ab910a10ff6c05c1c644a35 -a1302953015e164bf4c15f7d4d35e3633425a78294406b861675667eec77765ff88472306531e5d3a4ec0a2ff0dd6a9e -87874461df3c9aa6c0fa91325576c0590f367075f2f0ecfeb34afe162c04c14f8ce9d608c37ac1adc8b9985bc036e366 -84b50a8a61d3cc609bfb0417348133e698fe09a6d37357ce3358de189efcf35773d78c57635c2d26c3542b13cc371752 -acaed2cff8633d12c1d12bb7270c54d65b0b0733ab084fd47f81d0a6e1e9b6f300e615e79538239e6160c566d8bb8d29 -889e6a0e136372ca4bac90d1ab220d4e1cad425a710e8cdd48b400b73bb8137291ceb36a39440fa84305783b1d42c72f -90952e5becec45b2b73719c228429a2c364991cf1d5a9d6845ae5b38018c2626f4308daa322cab1c72e0f6c621bb2b35 -8f5a97a801b6e9dcd66ccb80d337562c96f7914e7169e8ff0fda71534054c64bf2a9493bb830623d612cfe998789be65 -84f3df8b9847dcf1d63ca470dc623154898f83c25a6983e9b78c6d2d90a97bf5e622445be835f32c1e55e6a0a562ea78 -91d12095cd7a88e7f57f254f02fdb1a1ab18984871dead2f107404bcf8069fe68258c4e6f6ebd2477bddf738135400bb -b771a28bc04baef68604d4723791d3712f82b5e4fe316d7adc2fc01b935d8e644c06d59b83bcb542afc40ebafbee0683 -872f6341476e387604a7e93ae6d6117e72d164e38ebc2b825bc6df4fcce815004d7516423c190c1575946b5de438c08d -90d6b4aa7d40a020cdcd04e8b016d041795961a8e532a0e1f4041252131089114a251791bf57794cadb7d636342f5d1c -899023ba6096a181448d927fed7a0fe858be4eac4082a42e30b3050ee065278d72fa9b9d5ce3bc1372d4cbd30a2f2976 -a28f176571e1a9124f95973f414d5bdbf5794d41c3839d8b917100902ac4e2171eb940431236cec93928a60a77ede793 -838dbe5bcd29c4e465d02350270fa0036cd46f8730b13d91e77afb7f5ed16525d0021d3b2ae173a76c378516a903e0cb -8e105d012dd3f5d20f0f1c4a7e7f09f0fdd74ce554c3032e48da8cce0a77260d7d47a454851387770f5c256fa29bcb88 -8f4df0f9feeb7a487e1d138d13ea961459a6402fd8f8cabb226a92249a0d04ded5971f3242b9f90d08da5ff66da28af6 -ad1cfda4f2122a20935aa32fb17c536a3653a18617a65c6836700b5537122af5a8206befe9eaea781c1244c43778e7f1 -832c6f01d6571964ea383292efc8c8fa11e61c0634a25fa180737cc7ab57bc77f25e614aac9a2a03d98f27b3c1c29de2 -903f89cc13ec6685ac7728521898781fecb300e9094ef913d530bf875c18bcc3ceed7ed51e7b482d45619ab4b025c2e9 -a03c474bb915aad94f171e8d96f46abb2a19c9470601f4c915512ec8b9e743c3938450a2a5b077b4618b9df8809e1dc1 -83536c8456f306045a5f38ae4be2e350878fa7e164ea408d467f8c3bc4c2ee396bd5868008c089183868e4dfad7aa50b -88f26b4ea1b236cb326cd7ad7e2517ec8c4919598691474fe15d09cabcfc37a8d8b1b818f4d112432ee3a716b0f37871 -a44324e3fe96e9c12b40ded4f0f3397c8c7ee8ff5e96441118d8a6bfad712d3ac990b2a6a23231a8f691491ac1fd480f -b0de4693b4b9f932191a21ee88629964878680152a82996c0019ffc39f8d9369bbe2fe5844b68d6d9589ace54af947e4 -8e5d8ba948aea5fd26035351a960e87f0d23efddd8e13236cc8e4545a3dda2e9a85e6521efb8577e03772d3637d213d9 -93efc82d2017e9c57834a1246463e64774e56183bb247c8fc9dd98c56817e878d97b05f5c8d900acf1fbbbca6f146556 -8731176363ad7658a2862426ee47a5dce9434216cef60e6045fa57c40bb3ce1e78dac4510ae40f1f31db5967022ced32 -b10c9a96745722c85bdb1a693100104d560433d45b9ac4add54c7646a7310d8e9b3ca9abd1039d473ae768a18e489845 -a2ac374dfbb464bf850b4a2caf15b112634a6428e8395f9c9243baefd2452b4b4c61b0cb2836d8eae2d57d4900bf407e -b69fe3ded0c4f5d44a09a0e0f398221b6d1bf5dbb8bc4e338b93c64f1a3cac1e4b5f73c2b8117158030ec03787f4b452 -8852cdbaf7d0447a8c6f211b4830711b3b5c105c0f316e3a6a18dcfbb9be08bd6f4e5c8ae0c3692da08a2dfa532f9d5c -93bbf6d7432a7d98ade3f94b57bf9f4da9bc221a180a370b113066dd42601bb9e09edd79e2e6e04e00423399339eebda -a80941c391f1eeafc1451c59e4775d6a383946ff22997aeaadf806542ba451d3b0f0c6864eeba954174a296efe2c1550 -a045fe2bb011c2a2f71a0181a8f457a3078470fb74c628eab8b59aef69ffd0d649723bf74d6885af3f028bc5a104fb39 -b9d8c35911009c4c8cad64692139bf3fc16b78f5a19980790cb6a7aea650a25df4231a4437ae0c351676a7e42c16134f -94c79501ded0cfcbab99e1841abe4a00a0252b3870e20774c3da16c982d74c501916ec28304e71194845be6e3113c7ab -900a66418b082a24c6348d8644ddb1817df5b25cb33044a519ef47cc8e1f7f1e38d2465b7b96d32ed472d2d17f8414c6 -b26f45d393b8b2fcb29bdbb16323dc7f4b81c09618519ab3a39f8ee5bd148d0d9f3c0b5dfab55b5ce14a1cb9206d777b -aa1a87735fc493a80a96a9a57ca40a6d9c32702bfcaa9869ce1a116ae65d69cefe2f3e79a12454b4590353e96f8912b4 -a922b188d3d0b69b4e4ea2a2aa076566962844637da12c0832105d7b31dea4a309eee15d12b7a336be3ea36fcbd3e3b7 -8f3841fcf4105131d8c4d9885e6e11a46c448226401cf99356c291fadb864da9fa9d30f3a73c327f23f9fd99a11d633e -9791d1183fae270e226379af6c497e7da803ea854bb20afa74b253239b744c15f670ee808f708ede873e78d79a626c9a -a4cad52e3369491ada61bf28ada9e85de4516d21c882e5f1cd845bea9c06e0b2887b0c5527fcff6fc28acd3c04f0a796 -b9ac86a900899603452bd11a7892a9bfed8054970bfcbeaa8c9d1930db891169e38d6977f5258c25734f96c8462eee3b -a3a154c28e5580656a859f4efc2f5ebfa7eaa84ca40e3f134fa7865e8581586db74992dbfa4036aa252fba103773ddde -95cc2a0c1885a029e094f5d737e3ecf4d26b99036453a8773c77e360101f9f98676ee246f6f732a377a996702d55691f -842651bbe99720438d8d4b0218feb60481280c05beb17750e9ca0d8c0599a60f873b7fbdcc7d8835ba9a6d57b16eec03 -81ee54699da98f5620307893dcea8f64670609fa20e5622265d66283adeac122d458b3308c5898e6c57c298db2c8b24f -b97868b0b2bc98032d68352a535a1b341b9ff3c7af4e3a7f3ebc82d3419daa1b5859d6aedc39994939623c7cd878bd9b -b60325cd5d36461d07ef253d826f37f9ee6474a760f2fff80f9873d01fd2b57711543cdc8d7afa1c350aa753c2e33dea -8c205326c11d25a46717b780c639d89714c7736c974ae71287e3f4b02e6605ac2d9b4928967b1684f12be040b7bf2dd3 -95a392d82db51e26ade6c2ccd3396d7e40aff68fa570b5951466580d6e56dda51775dce5cf3a74a7f28c3cb2eb551c4d -8f2cc8071eb56dffb70bda6dd433b556221dc8bba21c53353c865f00e7d4d86c9e39f119ea9a8a12ef583e9a55d9a6b6 -9449a71af9672aaf8856896d7e3d788b22991a7103f75b08c0abbcc2bfe60fda4ed8ce502cea4511ff0ea52a93e81222 -857090ab9fdb7d59632d068f3cc8cf27e61f0d8322d30e6b38e780a1f05227199b4cd746aac1311c36c659ef20931f28 -98a891f4973e7d9aaf9ac70854608d4f7493dffc7e0987d7be9dd6029f6ea5636d24ef3a83205615ca1ff403750058e1 -a486e1365bbc278dd66a2a25d258dc82f46b911103cb16aab3945b9c95ae87b386313a12b566df5b22322ede0afe25ad -a9a1eb399ed95d396dccd8d1ac718043446f8b979ec62bdce51c617c97a312f01376ab7fb87d27034e5f5570797b3c33 -b7abc3858d7a74bb446218d2f5a037e0fae11871ed9caf44b29b69c500c1fa1dcfad64c9cdccc9d80d5e584f06213deb -8cfb09fe2e202faa4cebad932b1d35f5ca204e1c2a0c740a57812ac9a6792130d1312aabd9e9d4c58ca168bfebd4c177 -a90a305c2cd0f184787c6be596fa67f436afd1f9b93f30e875f817ac2aae8bdd2e6e656f6be809467e6b3ad84adb86b1 -80a9ef993c2b009ae172cc8f7ec036f5734cf4f4dfa06a7db4d54725e7fbfae5e3bc6f22687bdbb6961939d6f0c87537 -848ade1901931e72b955d7db1893f07003e1708ff5d93174bac5930b9a732640f0578839203e9b77eb27965c700032d3 -93fdf4697609c5ae9c33b9ca2f5f1af44abeb2b98dc4fdf732cf7388de086f410730dc384d9b7a7f447bb009653c8381 -89ce3fb805aea618b5715c0d22a9f46da696b6fa86794f56fdf1d44155a33d42daf1920bcbe36cbacf3cf4c92df9cbc7 -829ce2c342cf82aa469c65f724f308f7a750bd1494adc264609cd790c8718b8b25b5cab5858cf4ee2f8f651d569eea67 -af2f0cee7bf413204be8b9df59b9e4991bc9009e0d6dbe6815181df0ec2ca93ab8f4f3135b1c14d8f53d74bff0bd6f27 -b87998cecf7b88cde93d1779f10a521edd5574a2fbd240102978639ec57433ba08cdb53849038a329cebbe74657268d2 -a64542a1261a6ed3d720c2c3a802303aad8c4c110c95d0f12e05c1065e66f42da494792b6bfc5b9272363f3b1d457f58 -86a6fd042e4f282fadf07a4bfee03fc96a3aea49f7a00f52bf249a20f1ec892326855410e61f37fbb27d9305eb2fc713 -967ea5bc403b6db269682f7fd0df90659350d7e1aa66bc4fab4c9dfcd75ed0bba4b52f1cebc5f34dc8ba810793727629 -a52990f9f3b8616ce3cdc2c74cd195029e6a969753dcf2d1630438700e7d6ebde36538532b3525ac516f5f2ce9dd27a3 -a64f7ff870bab4a8bf0d4ef6f5c744e9bf1021ed08b4c80903c7ad318e80ba1817c3180cc45cb5a1cae1170f0241655f -b00f706fa4de1f663f021e8ad3d155e84ce6084a409374b6e6cd0f924a0a0b51bebaaaf1d228c77233a73b0a5a0df0e9 -8b882cc3bff3e42babdb96df95fb780faded84887a0a9bab896bef371cdcf169d909f5658649e93006aa3c6e1146d62e -9332663ef1d1dcf805c3d0e4ce7a07d9863fb1731172e766b3cde030bf81682cc011e26b773fb9c68e0477b4ae2cfb79 -a8aa8151348dbd4ef40aaeb699b71b4c4bfd3218560c120d85036d14f678f6736f0ec68e80ce1459d3d35feccc575164 -a16cd8b729768f51881c213434aa28301fa78fcb554ddd5f9012ee1e4eae7b5cb3dd88d269d53146dea92d10790faf0b -86844f0ef9d37142faf3b1e196e44fbe280a3ba4189aa05c356778cb9e3b388a2bff95eed305ada8769935c9974e4c57 -ae2eec6b328fccf3b47bcdac32901ac2744a51beb410b04c81dea34dee4912b619466a4f5e2780d87ecefaebbe77b46d -915df4c38d301c8a4eb2dc5b1ba0ffaad67cbb177e0a80095614e9c711f4ef24a4cef133f9d982a63d2a943ba6c8669d -ae6a2a4dedfc2d1811711a8946991fede972fdf2a389b282471280737536ffc0ac3a6d885b1f8bda0366eb0b229b9979 -a9b628c63d08b8aba6b1317f6e91c34b2382a6c85376e8ef2410a463c6796740ae936fc4e9e0737cb9455d1daa287bd8 -848e30bf7edf2546670b390d5cf9ab71f98fcb6add3c0b582cb34996c26a446dee5d1bde4fdcde4fc80c10936e117b29 -907d6096c7c8c087d1808dd995d5d2b9169b3768c3f433475b50c2e2bd4b082f4d543afd8b0b0ddffa9c66222a72d51d -a59970a2493b07339124d763ac9d793c60a03354539ecbcf6035bc43d1ea6e35718202ae6d7060b7d388f483d971573c -b9cfef2af9681b2318f119d8611ff6d9485a68d8044581b1959ab1840cbca576dbb53eec17863d2149966e9feb21122f -ad47271806161f61d3afa45cdfe2babceef5e90031a21779f83dc8562e6076680525b4970b2f11fe9b2b23c382768323 -8e425a99b71677b04fe044625d338811fbb8ee32368a424f6ab2381c52e86ee7a6cecedf777dc97181519d41c351bc22 -86b55b54d7adefc12954a9252ee23ae83efe8b5b4b9a7dc307904413e5d69868c7087a818b2833f9b004213d629be8ad -a14fda6b93923dd11e564ae4457a66f397741527166e0b16a8eb91c6701c244fd1c4b63f9dd3515193ec88fa6c266b35 -a9b17c36ae6cd85a0ed7f6cabc5b47dc8f80ced605db327c47826476dc1fb8f8669aa7a7dc679fbd4ee3d8e8b4bd6a6f -82a0829469c1458d959c821148f15dacae9ea94bf56c59a6ab2d4dd8b3d16d73e313b5a3912a6c1f131d73a8f06730c4 -b22d56d549a53eaef549595924bdb621ff807aa4513feedf3fdcbf7ba8b6b9cfa4481c2f67fc642db397a6b794a8b63a -974c59c24392e2cb9294006cbe3c52163e255f3bd0c2b457bdc68a6338e6d5b6f87f716854492f8d880a6b896ccf757c -b70d247ba7cad97c50b57f526c2ba915786e926a94e8f8c3eebc2e1be6f4255411b9670e382060049c8f4184302c40b2 -ad80201fe75ef21c3ddbd98cf23591e0d7a3ba1036dfe77785c32f44755a212c31f0ceb0a0b6f5ee9b6dc81f358d30c3 -8c656e841f9bb90b9a42d425251f3fdbc022a604d75f5845f479ed4be23e02aaf9e6e56cde351dd7449c50574818a199 -8b88dd3fa209d3063b7c5b058f7249ee9900fbc2287d16da61a0704a0a1d71e45d9c96e1cda7fdf9654534ec44558b22 -961da00cc8750bd84d253c08f011970ae1b1158ad6778e8ed943d547bceaf52d6d5a212a7de3bf2706688c4389b827d2 -a5dd379922549a956033e3d51a986a4b1508e575042b8eaa1df007aa77cf0b8c2ab23212f9c075702788fa9c53696133 -ac8fcfde3a349d1e93fc8cf450814e842005c545c4844c0401bc80e6b96cdb77f29285a14455e167c191d4f312e866cd -ac63d79c799783a8466617030c59dd5a8f92ee6c5204676fd8d881ce5f7f8663bdbeb0379e480ea9b6340ab0dc88e574 -805874fde19ce359041ae2bd52a39e2841acabfd31f965792f2737d7137f36d4e4722ede8340d8c95afa6af278af8acb -8d2f323a228aa8ba7b7dc1399138f9e6b41df1a16a7069003ab8104b8b68506a45141bc5fe66acf430e23e13a545190b -a1610c721a2d9af882bb6b39bea97cff1527a3aea041d25934de080214ae77c959e79957164440686d15ab301e897d4d -aba16d29a47fc36f12b654fde513896723e2c700c4190f11b26aa4011da57737ad717daa02794aa3246e4ae5f0b0cc3a -a406db2f15fdd135f346cc4846623c47edd195e80ba8c7cb447332095314d565e4040694ca924696bb5ee7f8996ea0ba -8b30e2cd9b47d75ba57b83630e40f832249af6c058d4f490416562af451993eec46f3e1f90bc4d389e4c06abd1b32a46 -aacf9eb7036e248e209adbfc3dd7ce386569ea9b312caa4b240726549db3c68c4f1c8cbf8ed5ea9ea60c7e57c9df3b8e -b20fcac63bf6f5ee638a42d7f89be847f348c085ddcbec3fa318f4323592d136c230495f188ef2022aa355cc2b0da6f9 -811eff750456a79ec1b1249d76d7c1547065b839d8d4aaad860f6d4528eb5b669473dcceeeea676cddbc3980b68461b7 -b52d14ae33f4ab422f953392ae76a19c618cc31afc96290bd3fe2fb44c954b5c92c4789f3f16e8793f2c0c1691ade444 -a7826dafeeba0db5b66c4dfcf2b17fd7b40507a5a53ac2e42942633a2cb30b95ba1739a6e9f3b7a0e0f1ec729bf274e2 -8acfd83ddf7c60dd7c8b20c706a3b972c65d336b8f9b3d907bdd8926ced271430479448100050b1ef17578a49c8fa616 -af0c69f65184bb06868029ad46f8465d75c36814c621ac20a5c0b06a900d59305584f5a6709683d9c0e4b6cd08d650a6 -b6cc8588191e00680ee6c3339bd0f0a17ad8fd7f4be57d5d7075bede0ea593a19e67f3d7c1a20114894ee5bfcab71063 -a82fd4f58635129dbb6cc3eb9391cf2d28400018b105fc41500fbbd12bd890b918f97d3d359c29dd3b4c4e34391dfab0 -92fc544ed65b4a3625cf03c41ddff7c039bc22d22c0d59dcc00efd5438401f2606adb125a1d5de294cca216ec8ac35a3 -906f67e4a32582b71f15940523c0c7ce370336935e2646bdaea16a06995256d25e99df57297e39d6c39535e180456407 -97510337ea5bbd5977287339197db55c60533b2ec35c94d0a460a416ae9f60e85cee39be82abeeacd5813cf54df05862 -87e6894643815c0ea48cb96c607266c5ee4f1f82ba5fe352fb77f9b6ed14bfc2b8e09e80a99ac9047dfcf62b2ae26795 -b6fd55dd156622ad7d5d51b7dde75e47bd052d4e542dd6449e72411f68275775c846dde301e84613312be8c7bce58b07 -b98461ac71f554b2f03a94e429b255af89eec917e208a8e60edf5fc43b65f1d17a20de3f31d2ce9f0cb573c25f2f4d98 -96f0dea40ca61cefbee41c4e1fe9a7d81fbe1f49bb153d083ab70f5d0488a1f717fd28cedcf6aa18d07cce2c62801898 -8d7c3ab310184f7dc34b6ce4684e4d29a31e77b09940448ea4daac730b7eb308063125d4dd229046cf11bfd521b771e0 -96f0564898fe96687918bbf0a6adead99cf72e3a35ea3347e124af9d006221f8e82e5a9d2fe80094d5e8d48e610f415e -ad50fcb92c2675a398cf07d4c40a579e44bf8d35f27cc330b57e54d5ea59f7d898af0f75dccfe3726e5471133d70f92b -828beed62020361689ae7481dd8f116902b522fb0c6c122678e7f949fdef70ead011e0e6bffd25678e388744e17cdb69 -8349decac1ca16599eee2efc95bcaabf67631107da1d34a2f917884bd70dfec9b4b08ab7bc4379d6c73b19c0b6e54fb8 -b2a6a2e50230c05613ace9e58bb2e98d94127f196f02d9dddc53c43fc68c184549ca12d713cb1b025d8260a41e947155 -94ff52181aadae832aed52fc3b7794536e2a31a21fc8be3ea312ca5c695750d37f08002f286b33f4023dba1e3253ecfa -a21d56153c7e5972ee9a319501be4faff199fdf09bb821ea9ce64aa815289676c00f105e6f00311b3a5b627091b0d0fc -a27a60d219f1f0c971db73a7f563b371b5c9fc3ed1f72883b2eac8a0df6698400c9954f4ca17d7e94e44bd4f95532afb -a2fc56fae99b1f18ba5e4fe838402164ce82f8a7f3193d0bbd360c2bac07c46f9330c4c7681ffb47074c6f81ee6e7ac6 -b748e530cd3afb96d879b83e89c9f1a444f54e55372ab1dcd46a0872f95ce8f49cf2363fc61be82259e04f555937ed16 -8bf8993e81080c7cbba1e14a798504af1e4950b2f186ab3335b771d6acaee4ffe92131ae9c53d74379d957cb6344d9cd -96774d0ef730d22d7ab6d9fb7f90b9ead44285219d076584a901960542756700a2a1603cdf72be4708b267200f6c36a9 -b47703c2ab17be1e823cc7bf3460db1d6760c0e33862c90ca058845b2ff234b0f9834ddba2efb2ee1770eb261e7d8ffd -84319e67c37a9581f8b09b5e4d4ae88d0a7fb4cbb6908971ab5be28070c3830f040b1de83ee663c573e0f2f6198640e4 -96811875fa83133e0b3c0e0290f9e0e28bca6178b77fdf5350eb19344d453dbd0d71e55a0ef749025a5a2ca0ad251e81 -81a423423e9438343879f2bfd7ee9f1c74ebebe7ce3cfffc8a11da6f040cc4145c3b527bd3cf63f9137e714dbcb474ef -b8c3535701ddbeec2db08e17a4fa99ba6752d32ece5331a0b8743676f421fcb14798afc7c783815484f14693d2f70db8 -81aee980c876949bf40782835eec8817d535f6f3f7e00bf402ddd61101fdcd60173961ae90a1cf7c5d060339a18c959d -87e67b928d97b62c49dac321ce6cb680233f3a394d4c9a899ac2e8db8ccd8e00418e66cdfd68691aa3cb8559723b580c -8eac204208d99a2b738648df96353bbb1b1065e33ee4f6bba174b540bbbd37d205855e1f1e69a6b7ff043ca377651126 -848e6e7a54ad64d18009300b93ea6f459ce855971dddb419b101f5ac4c159215626fadc20cc3b9ab1701d8f6dfaddd8b -88aa123d9e0cf309d46dddb6acf634b1ade3b090a2826d6e5e78669fa1220d6df9a6697d7778cd9b627db17eea846126 -9200c2a629b9144d88a61151b661b6c4256cc5dadfd1e59a8ce17a013c2d8f7e754aabe61663c3b30f1bc47784c1f8cf -b6e1a2827c3bdda91715b0e1b1f10dd363cef337e7c80cac1f34165fc0dea7c8b69747e310563db5818390146ce3e231 -92c333e694f89f0d306d54105b2a5dcc912dbe7654d9e733edab12e8537350815be472b063e56cfde5286df8922fdecb -a6fac04b6d86091158ebb286586ccfec2a95c9786e14d91a9c743f5f05546073e5e3cc717635a0c602cad8334e922346 -a581b4af77feebc1fb897d49b5b507c6ad513d8f09b273328efbb24ef0d91eb740d01b4d398f2738125dacfe550330cd -81c4860cccf76a34f8a2bc3f464b7bfd3e909e975cce0d28979f457738a56e60a4af8e68a3992cf273b5946e8d7f76e2 -8d1eaa09a3180d8af1cbaee673db5223363cc7229a69565f592fa38ba0f9d582cedf91e15dabd06ebbf2862fc0feba54 -9832f49b0147f4552402e54593cfa51f99540bffada12759b71fcb86734be8e500eea2d8b3d036710bdf04c901432de9 -8bdb0e8ec93b11e5718e8c13cb4f5de545d24829fd76161216340108098dfe5148ed25e3b57a89a516f09fa79043734d -ab96f06c4b9b0b2c0571740b24fca758e6976315053a7ecb20119150a9fa416db2d3a2e0f8168b390bb063f0c1caf785 -ab777f5c52acd62ecf4d1f168b9cc8e1a9b45d4ec6a8ff52c583e867c2239aba98d7d3af977289b367edce03d9c2dfb1 -a09d3ce5e748da84802436951acc3d3ea5d8ec1d6933505ed724d6b4b0d69973ab0930daec9c6606960f6e541e4a3ce2 -8ef94f7be4d85d5ad3d779a5cf4d7b2fc3e65c52fb8e1c3c112509a4af77a0b5be994f251e5e40fabeeb1f7d5615c22b -a7406a5bf5708d9e10922d3c5c45c03ef891b8d0d74ec9f28328a72be4cdc05b4f2703fa99366426659dfca25d007535 -b7f52709669bf92a2e070bfe740f422f0b7127392c5589c7f0af71bb5a8428697c762d3c0d74532899da24ea7d8695c2 -b9dfb0c8df84104dbf9239ccefa4672ef95ddabb8801b74997935d1b81a78a6a5669a3c553767ec19a1281f6e570f4ff -ae4d5c872156061ce9195ac640190d8d71dd406055ee43ffa6f9893eb24b870075b74c94d65bc1d5a07a6573282b5520 -afe6bd3eb72266d333f1807164900dcfa02a7eb5b1744bb3c86b34b3ee91e3f05e38fa52a50dc64eeb4bdb1dd62874b8 -948043cf1bc2ef3c01105f6a78dc06487f57548a3e6ef30e6ebc51c94b71e4bf3ff6d0058c72b6f3ecc37efd7c7fa8c0 -a22fd17c2f7ffe552bb0f23fa135584e8d2d8d75e3f742d94d04aded2a79e22a00dfe7acbb57d44e1cdb962fb22ae170 -8cd0f4e9e4fb4a37c02c1bde0f69359c43ab012eb662d346487be0c3758293f1ca560122b059b091fddce626383c3a8f -90499e45f5b9c81426f3d735a52a564cafbed72711d9279fdd88de8038e953bc48c57b58cba85c3b2e4ce56f1ddb0e11 -8c30e4c034c02958384564cac4f85022ef36ab5697a3d2feaf6bf105049675bbf23d01b4b6814711d3d9271abff04cac -81f7999e7eeea30f3e1075e6780bbf054f2fb6f27628a2afa4d41872a385b4216dd5f549da7ce6cf39049b2251f27fb7 -b36a7191f82fc39c283ffe53fc1f5a9a00b4c64eee7792a8443475da9a4d226cf257f226ea9d66e329af15d8f04984ec -aad4da528fdbb4db504f3041c747455baff5fcd459a2efd78f15bdf3aea0bdb808343e49df88fe7a7c8620009b7964a3 -99ebd8c6dd5dd299517fb6381cfc2a7f443e6e04a351440260dd7c2aee3f1d8ef06eb6c18820b394366ecdfd2a3ce264 -8873725b81871db72e4ec3643084b1cdce3cbf80b40b834b092767728605825c19b6847ad3dcf328438607e8f88b4410 -b008ee2f895daa6abd35bd39b6f7901ae4611a11a3271194e19da1cdcc7f1e1ea008fe5c5440e50d2c273784541ad9c5 -9036feafb4218d1f576ef89d0e99124e45dacaa6d816988e34d80f454d10e96809791d5b78f7fd65f569e90d4d7238c5 -92073c1d11b168e4fa50988b0288638b4868e48bbc668c5a6dddf5499875d53be23a285acb5e4bad60114f6cf6c556e9 -88c87dfcb8ba6cbfe7e1be081ccfadbd589301db2cb7c99f9ee5d7db90aa297ed1538d5a867678a763f2deede5fd219a -b42a562805c661a50f5dea63108002c0f27c0da113da6a9864c9feb5552225417c0356c4209e8e012d9bcc9d182c7611 -8e6317d00a504e3b79cd47feb4c60f9df186467fe9ca0f35b55c0364db30528f5ff071109dabb2fc80bb9cd4949f0c24 -b7b1ea6a88694f8d2f539e52a47466695e39e43a5eb9c6f23bca15305fe52939d8755cc3ac9d6725e60f82f994a3772f -a3cd55161befe795af93a38d33290fb642b8d80da8b786c6e6fb02d393ea308fbe87f486994039cbd7c7b390414594b6 -b416d2d45b44ead3b1424e92c73c2cf510801897b05d1724ff31cbd741920cd858282fb5d6040fe1f0aa97a65bc49424 -950ee01291754feace97c2e933e4681e7ddfbc4fcd079eb6ff830b0e481d929c93d0c7fb479c9939c28ca1945c40da09 -869bd916aee8d86efe362a49010382674825d49195b413b4b4018e88ce43fe091b475d0b863ff0ba2259400f280c2b23 -9782f38cd9c9d3385ec286ebbc7cba5b718d2e65a5890b0a5906b10a89dc8ed80d417d71d7c213bf52f2af1a1f513ea7 -91cd33bc2628d096269b23faf47ee15e14cb7fdc6a8e3a98b55e1031ea0b68d10ba30d97e660f7e967d24436d40fad73 -8becc978129cc96737034c577ae7225372dd855da8811ae4e46328e020c803833b5bdbc4a20a93270e2b8bd1a2feae52 -a36b1d8076783a9522476ce17f799d78008967728ce920531fdaf88303321bcaf97ecaa08e0c01f77bc32e53c5f09525 -b4720e744943f70467983aa34499e76de6d59aa6fadf86f6b787fdce32a2f5b535b55db38fe2da95825c51002cfe142d -91ad21fc502eda3945f6de874d1b6bf9a9a7711f4d61354f9e5634fc73f9c06ada848de15ab0a75811d3250be862827d -84f78e2ebf5fc077d78635f981712daf17e2475e14c2a96d187913006ad69e234746184a51a06ef510c9455b38acb0d7 -960aa7906e9a2f11db64a26b5892ac45f20d2ccb5480f4888d89973beb6fa0dfdc06d68d241ff5ffc7f1b82b1aac242d -a99365dcd1a00c66c9db6924b97c920f5c723380e823b250db85c07631b320ec4e92e586f7319e67a522a0578f7b6d6c -a25d92d7f70cf6a88ff317cfec071e13774516da664f5fac0d4ecaa65b8bf4eb87a64a4d5ef2bd97dfae98d388dbf5cc -a7af47cd0041295798f9779020a44653007444e8b4ef0712982b06d0dcdd434ec4e1f7c5f7a049326602cb605c9105b7 -aefe172eac5568369a05980931cc476bebd9dea573ba276d59b9d8c4420784299df5a910033b7e324a6c2dfc62e3ef05 -b69bc9d22ffa645baa55e3e02522e9892bb2daa7fff7c15846f13517d0799766883ee09ae0869df4139150c5b843ca8a -95a10856140e493354fdd12722c7fdded21b6a2ffbc78aa2697104af8ad0c8e2206f44b0bfee077ef3949d46bbf7c16b -891f2fcd2c47cbea36b7fa715968540c233313f05333f09d29aba23c193f462ed490dd4d00969656e89c53155fdfe710 -a6c33e18115e64e385c843dde34e8a228222795c7ca90bc2cc085705d609025f3351d9be61822c69035a49fb3e48f2d5 -b87fb12f12c0533b005adad0487f03393ff682e13575e3cb57280c3873b2c38ba96a63c49eef7a442753d26b7005230b -b905c02ba451bfd411c135036d92c27af3b0b1c9c2f1309d6948544a264b125f39dd41afeff4666b12146c545adc168a -8b29c513f43a78951cf742231cf5457a6d9d55edf45df5481a0f299a418d94effef561b15d2c1a01d1b8067e7153fda9 -b9941cccd51dc645920d2781c81a317e5a33cb7cf76427b60396735912cb6d2ca9292bb4d36b6392467d390d2c58d9f3 -a8546b627c76b6ef5c93c6a98538d8593dbe21cb7673fd383d5401b0c935eea0bdeeefeb1af6ad41bad8464fb87bbc48 -aa286b27de2812de63108a1aec29d171775b69538dc6198640ac1e96767c2b83a50391f49259195957d457b493b667c9 -a932fb229f641e9abbd8eb2bd874015d97b6658ab6d29769fc23b7db9e41dd4f850382d4c1f08af8f156c5937d524473 -a1412840fcc86e2aeec175526f2fb36e8b3b8d21a78412b7266daf81e51b3f68584ed8bd42a66a43afdd8c297b320520 -89c78be9efb624c97ebca4fe04c7704fa52311d183ffd87737f76b7dadc187c12c982bd8e9ed7cd8beb48cdaafd2fd01 -a3f5ddec412a5bec0ce15e3bcb41c6214c2b05d4e9135a0d33c8e50a78eaba71e0a5a6ea8b45854dec5c2ed300971fc2 -9721f9cec7a68b7758e3887548790de49fa6a442d0396739efa20c2f50352a7f91d300867556d11a703866def2d5f7b5 -a23764e140a87e5991573521af039630dd28128bf56eed2edbed130fd4278e090b60cf5a1dca9de2910603d44b9f6d45 -a1a6494a994215e48ab55c70efa8ffdddce6e92403c38ae7e8dd2f8288cad460c6c7db526bbdf578e96ca04d9fe12797 -b1705ea4cb7e074efe0405fc7b8ee2ec789af0426142f3ec81241cacd4f7edcd88e39435e4e4d8e7b1df64f3880d6613 -85595d061d677116089a6064418b93eb44ff79e68d12bd9625078d3bbc440a60d0b02944eff6054433ee34710ae6fbb4 -9978d5e30bedb7526734f9a1febd973a70bfa20890490e7cc6f2f9328feab1e24f991285dbc3711d892514e2d7d005ad -af30243c66ea43b9f87a061f947f7bce745f09194f6e95f379c7582b9fead920e5d6957eaf05c12ae1282ada4670652f -a1930efb473f88001e47aa0b2b2a7566848cccf295792e4544096ecd14ee5d7927c173a8576b405bfa2eec551cd67eb5 -b0446d1c590ee5a45f7e22d269c044f3848c97aec1d226b44bfd0e94d9729c28a38bccddc3a1006cc5fe4e3c24f001f2 -b8a8380172df3d84b06176df916cf557966d4f2f716d3e9437e415d75b646810f79f2b2b71d857181b7fc944018883a3 -a563afec25b7817bfa26e19dc9908bc00aa8fc3d19be7d6de23648701659009d10e3e4486c28e9c6b13d48231ae29ac5 -a5a8e80579de886fb7d6408f542791876885947b27ad6fa99a8a26e381f052598d7b4e647b0115d4b5c64297e00ce28e -8f87afcc7ad33c51ac719bade3cd92da671a37a82c14446b0a2073f4a0a23085e2c8d31913ed2d0be928f053297de8f6 -a43c455ce377e0bc434386c53c752880687e017b2f5ae7f8a15c044895b242dffde4c92fb8f8bb50b18470b17351b156 -8368f8b12a5bceb1dba25adb3a2e9c7dc9b1a77a1f328e5a693f5aec195cd1e06b0fe9476b554c1c25dac6c4a5b640a3 -919878b27f3671fc78396f11531c032f3e2bd132d04cc234fa4858676b15fb1db3051c0b1db9b4fc49038216f11321ce -b48cd67fb7f1242696c1f877da4bdf188eac676cd0e561fbac1a537f7b8229aff5a043922441d603a26aae56a15faee4 -a3e0fdfd4d29ea996517a16f0370b54787fefe543c2fe73bfc6f9e560c1fd30dad8409859e2d7fa2d44316f24746c712 -8bb156ade8faf149df7bea02c140c7e392a4742ae6d0394d880a849127943e6f26312033336d3b9fdc0092d71b5efe87 -8845e5d5cc555ca3e0523244300f2c8d7e4d02aaebcb5bd749d791208856c209a6f84dd99fd55968c9f0ab5f82916707 -a3e90bb5c97b07789c2f32dff1aec61d0a2220928202f5ad5355ae71f8249237799d6c8a22602e32e572cb12eabe0c17 -b150bcc391884c996149dc3779ce71f15dda63a759ee9cc05871f5a8379dcb62b047098922c0f26c7bd04deb394c33f9 -95cd4ad88d51f0f2efcfd0c2df802fe252bb9704d1afbf9c26a248df22d55da87bdfaf41d7bc6e5df38bd848f0b13f42 -a05a49a31e91dff6a52ac8b9c2cfdd646a43f0d488253f9e3cfbce52f26667166bbb9b608fc358763a65cbf066cd6d05 -a59c3c1227fdd7c2e81f5e11ef5c406da44662987bac33caed72314081e2eed66055d38137e01b2268e58ec85dd986c0 -b7020ec3bd73a99861f0f1d88cf5a19abab1cbe14b7de77c9868398c84bb8e18dbbe9831838a96b6d6ca06e82451c67b -98d1ff2525e9718ee59a21d8900621636fcd873d9a564b8dceb4be80a194a0148daf1232742730b3341514b2e5a5436c -886d97b635975fc638c1b6afc493e5998ca139edba131b75b65cfe5a8e814f11bb678e0eeee5e6e5cd913ad3f2fefdfc -8fb9fd928d38d5d813b671c924edd56601dd7163b686c13f158645c2f869d9250f3859aa5463a39258c90fef0f41190a -aac35e1cd655c94dec3580bb3800bd9c2946c4a9856f7d725af15fbea6a2d8ca51c8ad2772abed60ee0e3fb9cb24046b -b8d71fa0fa05ac9e443c9b4929df9e7f09a919be679692682e614d24227e04894bfc14a5c73a62fb927fedff4a0e4aa7 -a45a19f11fbbb531a704badbb813ed8088ab827c884ee4e4ebf363fa1132ff7cfa9d28be9c85b143e4f7cdbc94e7cf1a -82b54703a4f295f5471b255ab59dce00f0fe90c9fb6e06b9ee48b15c91d43f4e2ef4a96c3118aeb03b08767be58181bb -8283264c8e6d2a36558f0d145c18576b6600ff45ff99cc93eca54b6c6422993cf392668633e5df396b9331e873d457e5 -8c549c03131ead601bc30eb6b9537b5d3beb7472f5bb1bcbbfd1e9f3704477f7840ab3ab7f7dc13bbbbcdff886a462d4 -afbb0c520ac1b5486513587700ad53e314cb74bfbc12e0b5fbdcfdaac36d342e8b59856196a0d84a25cff6e6e1d17e76 -89e4c22ffb51f2829061b3c7c1983c5c750cad158e3a825d46f7cf875677da5d63f653d8a297022b5db5845c9271b32b -afb27a86c4c2373088c96b9adf4433f2ebfc78ac5c526e9f0510670b6e4e5e0057c0a4f75b185e1a30331b9e805c1c15 -a18e16b57445f88730fc5d3567bf5a176861dc14c7a08ed2996fe80eed27a0e7628501bcb78a1727c5e9ac55f29c12c4 -93d61bf88b192d6825cf4e1120af1c17aa0f994d158b405e25437eaeefae049f7b721a206e7cc8a04fdc29d3c42580a1 -a99f2995a2e3ed2fd1228d64166112038de2f516410aa439f4c507044e2017ea388604e2d0f7121256fadf7fbe7023d1 -914fd91cffc23c32f1c6d0e98bf660925090d873367d543034654389916f65f552e445b0300b71b61b721a72e9a5983c -b42a578a7787b71f924e7def425d849c1c777156b1d4170a8ee7709a4a914e816935131afd9a0412c4cb952957b20828 -82fb30590e84b9e45db1ec475a39971cf554dc01bcc7050bc89265740725c02e2be5a972168c5170c86ae83e5b0ad2c0 -b14f8d8e1e93a84976289e0cf0dfa6f3a1809e98da16ee5c4932d0e1ed6bf8a07697fdd4dd86a3df84fb0003353cdcc0 -85d7a2f4bda31aa2cb208b771fe03291a4ebdaf6f1dc944c27775af5caec412584c1f45bc741fca2a6a85acb3f26ad7d -af02e56ce886ff2253bc0a68faad76f25ead84b2144e5364f3fb9b648f03a50ee9dc0b2c33ebacf7c61e9e43201ef9ef -87e025558c8a0b0abd06dfc350016847ea5ced7af2d135a5c9eec9324a4858c4b21510fb0992ec52a73447f24945058e -80fff0bafcd058118f5e7a4d4f1ae0912efeb281d2cbe4d34ba8945cc3dbe5d8baf47fb077343b90b8d895c90b297aca -b6edcf3a40e7b1c3c0148f47a263cd819e585a51ef31c2e35a29ce6f04c53e413f743034c0d998d9c00a08ba00166f31 -abb87ed86098c0c70a76e557262a494ff51a30fb193f1c1a32f8e35eafa34a43fcc07aa93a3b7a077d9e35afa07b1a3d -a280214cd3bb0fb7ecd2d8bcf518cbd9078417f2b91d2533ec2717563f090fb84f2a5fcfdbbeb2a2a1f8a71cc5aa5941 -a63083ca7238ea2b57d15a475963cf1d4f550d8cd76db290014a0461b90351f1f26a67d674c837b0b773b330c7c3d534 -a8fa39064cb585ece5263e2f42f430206476bf261bd50f18d2b694889bd79d04d56410664cecad62690e5c5a20b3f6ff -85ba52ce9d700a5dcf6c5b00559acbe599d671ce5512467ff4b6179d7fad550567ce2a9c126a50964e3096458ea87920 -b913501e1008f076e5eac6d883105174f88b248e1c9801e568fefaffa1558e4909364fc6d9512aa4d125cbd7cc895f05 -8eb33b5266c8f2ed4725a6ad147a322e44c9264cf261c933cbbe230a43d47fca0f29ec39756b20561dabafadd5796494 -850ebc8b661a04318c9db5a0515066e6454fa73865aa4908767a837857ecd717387f614acb614a88e075d4edc53a2f5a -a08d6b92d866270f29f4ce23a3f5d99b36b1e241a01271ede02817c8ec3f552a5c562db400766c07b104a331835c0c64 -8131804c89bb3e74e9718bfc4afa547c1005ff676bd4db9604335032b203390cfa54478d45c6c78d1fe31a436ed4be9f -9106d94f23cc1eacec8316f16d6f0a1cc160967c886f51981fdb9f3f12ee1182407d2bb24e5b873de58cb1a3ee915a6b -a13806bfc3eae7a7000c9d9f1bd25e10218d4e67f59ae798b145b098bca3edad2b1040e3fc1e6310e612fb8818f459ac -8c69fbca502046cb5f6db99900a47b34117aef3f4b241690cdb3b84ca2a2fc7833e149361995dc41fa78892525bce746 -852c473150c91912d58ecb05769222fa18312800c3f56605ad29eec9e2d8667b0b81c379048d3d29100ed2773bb1f3c5 -b1767f6074426a00e01095dbb1795beb4e4050c6411792cbad6537bc444c3165d1058bafd1487451f9c5ddd209e0ae7e -80c600a5fe99354ce59ff0f84c760923dc8ff66a30bf47dc0a086181785ceb01f9b951c4e66df800ea6d705e8bc47055 -b5cf19002fbc88a0764865b82afcb4d64a50196ea361e5c71dff7de084f4dcbbc34ec94a45cc9e0247bd51da565981aa -93e67a254ea8ce25e112d93cc927fadaa814152a2c4ec7d9a56eaa1ed47aec99b7e9916b02e64452cc724a6641729bbb -ace70b32491bda18eee4a4d041c3bc9effae9340fe7e6c2f5ad975ee0874c17f1a7da7c96bd85fccff9312c518fac6e9 -ab4cfa02065017dd7f1aadc66f2c92f78f0f11b8597c03a5d69d82cb2eaf95a4476a836ac102908f137662472c8d914b -a40b8cd8deb8ae503d20364d64cab7c2801b7728a9646ed19c65edea6a842756a2f636283494299584ad57f4bb12cd0b -8594e11d5fc2396bcd9dbf5509ce4816dbb2b7305168021c426171fb444d111da5a152d6835ad8034542277011c26c0e -8024de98c26b4c994a66628dc304bb737f4b6859c86ded552c5abb81fd4c6c2e19d5a30beed398a694b9b2fdea1dd06a -8843f5872f33f54df8d0e06166c1857d733995f67bc54abb8dfa94ad92407cf0179bc91b0a50bbb56cdc2b350d950329 -b8bab44c7dd53ef9edf497dcb228e2a41282c90f00ba052fc52d57e87b5c8ab132d227af1fcdff9a12713d1f980bcaae -982b4d7b29aff22d527fd82d2a52601d95549bfb000429bb20789ed45e5abf1f4b7416c7b7c4b79431eb3574b29be658 -8eb1f571b6a1878e11e8c1c757e0bc084bab5e82e897ca9be9b7f4b47b91679a8190bf0fc8f799d9b487da5442415857 -a6e74b588e5af935c8b243e888582ef7718f8714569dd4992920740227518305eb35fab674d21a5551cca44b3e511ef2 -a30fc2f3a4cb4f50566e82307de73cd7bd8fe2c1184e9293c136a9b9e926a018d57c6e4f308c95b9eb8299e94d90a2a1 -a50c5869ca5d2b40722c056a32f918d47e0b65ca9d7863ca7d2fb4a7b64fe523fe9365cf0573733ceaadebf20b48fff8 -83bbdd32c04d17581418cf360749c7a169b55d54f2427390defd9f751f100897b2d800ce6636c5bbc046c47508d60c8c -a82904bdf614de5d8deaff688c8a5e7ac5b3431687acbcda8fa53960b7c417a39c8b2e462d7af91ce6d79260f412db8e -a4362e31ff4b05d278b033cf5eebea20de01714ae16d4115d04c1da4754269873afc8171a6f56c5104bfd7b0db93c3e7 -b5b8daa63a3735581e74a021b684a1038cea77168fdb7fdf83c670c2cfabcfc3ab2fc7359069b5f9048188351aef26b5 -b48d723894b7782d96ac8433c48faca1bdfa5238019c451a7f47d958097cce3ae599b876cf274269236b9d6ff8b6d7ca -98ffff6a61a3a6205c7820a91ca2e7176fab5dba02bc194c4d14942ac421cb254183c705506ab279e4f8db066f941c6c -ae7db24731da2eaa6efc4f7fcba2ecc26940ddd68038dce43acf2cee15b72dc4ef42a7bfdd32946d1ed78786dd7696b3 -a656db14f1de9a7eb84f6301b4acb2fbf78bfe867f48a270e416c974ab92821eb4df1cb881b2d600cfed0034ac784641 -aa315f8ecba85a5535e9a49e558b15f39520fce5d4bf43131bfbf2e2c9dfccc829074f9083e8d49f405fb221d0bc4c3c -90bffba5d9ff40a62f6c8e9fc402d5b95f6077ed58d030c93e321b8081b77d6b8dac3f63a92a7ddc01585cf2c127d66c -abdd733a36e0e0f05a570d0504e73801bf9b5a25ff2c78786f8b805704997acb2e6069af342538c581144d53149fa6d3 -b4a723bb19e8c18a01bd449b1bb3440ddb2017f10bb153da27deb7a6a60e9bb37619d6d5435fbb1ba617687838e01dd0 -870016b4678bab3375516db0187a2108b2e840bae4d264b9f4f27dbbc7cc9cac1d7dc582d7a04d6fd1ed588238e5e513 -80d33d2e20e8fc170aa3cb4f69fffb72aeafb3b5bb4ea0bc79ab55da14142ca19b2d8b617a6b24d537366e3b49cb67c3 -a7ee76aec273aaae03b3b87015789289551969fb175c11557da3ab77e39ab49d24634726f92affae9f4d24003050d974 -8415ea4ab69d779ebd42d0fe0c6aef531d6a465a5739e429b1fcf433ec45aa8296c527e965a20f0ec9f340c9273ea3cf -8c7662520794e8b4405d0b33b5cac839784bc86a5868766c06cbc1fa306dbe334978177417b31baf90ce7b0052a29c56 -902b2abecc053a3dbdea9897ee21e74821f3a1b98b2d560a514a35799f4680322550fd3a728d4f6d64e1de98033c32b8 -a05e84ed9ecab8d508d670c39f2db61ad6e08d2795ec32a3c9d0d3737ef3801618f4fc2a95f90ec2f068606131e076c5 -8b9208ff4d5af0c2e3f53c9375da666773ac57197dfabb0d25b1c8d0588ba7f3c15ee9661bb001297f322ea2fbf6928b -a3c827741b34a03254d4451b5ab74a96f2b9f7fb069e2f5adaf54fd97cc7a4d516d378db5ca07da87d8566d6eef13726 -8509d8a3f4a0ed378e0a1e28ea02f6bf1d7f6c819c6c2f5297c7df54c895b848f841653e32ba2a2c22c2ff739571acb8 -a0ce988b7d3c40b4e496aa83a09e4b5472a2d98679622f32bea23e6d607bc7de1a5374fb162bce0549a67dad948519be -aa8a3dd12bd60e3d2e05f9c683cdcb8eab17fc59134815f8d197681b1bcf65108cba63ac5c58ee632b1e5ed6bba5d474 -8b955f1d894b3aefd883fb4b65f14cd37fc2b9db77db79273f1700bef9973bf3fd123897ea2b7989f50003733f8f7f21 -ac79c00ddac47f5daf8d9418d798d8af89fc6f1682e7e451f71ea3a405b0d36af35388dd2a332af790bc83ca7b819328 -a0d44dd2a4438b809522b130d0938c3fe7c5c46379365dbd1810a170a9aa5818e1c783470dd5d0b6d4ac7edbb7330910 -a30b69e39ad43dd540a43c521f05b51b5f1b9c4eed54b8162374ae11eac25da4f5756e7b70ce9f3c92c2eeceee7431ed -ac43220b762c299c7951222ea19761ab938bf38e4972deef58ed84f4f9c68c230647cf7506d7cbfc08562fcca55f0485 -b28233b46a8fb424cfa386a845a3b5399d8489ceb83c8f3e05c22c934798d639c93718b7b68ab3ce24c5358339e41cbb -ac30d50ee8ce59a10d4b37a3a35e62cdb2273e5e52232e202ca7d7b8d09d28958ee667fae41a7bb6cdc6fe8f6e6c9c85 -b199842d9141ad169f35cc7ff782b274cbaa645fdb727761e0a89edbf0d781a15f8218b4bf4eead326f2903dd88a9cc1 -85e018c7ddcad34bb8285a737c578bf741ccd547e68c734bdb3808380e12c5d4ef60fc896b497a87d443ff9abd063b38 -8c856e6ba4a815bdb891e1276f93545b7072f6cb1a9aa6aa5cf240976f29f4dee01878638500a6bf1daf677b96b54343 -b8a47555fa8710534150e1a3f13eab33666017be6b41005397afa647ea49708565f2b86b77ad4964d140d9ced6b4d585 -8cd1f1db1b2f4c85a3f46211599caf512d5439e2d8e184663d7d50166fd3008f0e9253272f898d81007988435f715881 -b1f34b14612c973a3eceb716dc102b82ab18afef9de7630172c2780776679a7706a4874e1df3eaadf541fb009731807f -b25464af9cff883b55be2ff8daf610052c02df9a5e147a2cf4df6ce63edcdee6dc535c533590084cc177da85c5dc0baa -91c3c4b658b42d8d3448ae1415d4541d02379a40dc51e36a59bd6e7b9ba3ea51533f480c7c6e8405250ee9b96a466c29 -86dc027b95deb74c36a58a1333a03e63cb5ae22d3b29d114cfd2271badb05268c9d0c819a977f5e0c6014b00c1512e3a -ae0e6ff58eb5fa35da5107ebeacf222ab8f52a22bb1e13504247c1dfa65320f40d97b0e6b201cb6613476687cb2f0681 -8f13415d960b9d7a1d93ef28afc2223e926639b63bdefce0f85e945dfc81670a55df288893a0d8b3abe13c5708f82f91 -956f67ca49ad27c1e3a68c1faad5e7baf0160c459094bf6b7baf36b112de935fdfd79fa4a9ea87ea8de0ac07272969f4 -835e45e4a67df9fb51b645d37840b3a15c171d571a10b03a406dd69d3c2f22df3aa9c5cbe1e73f8d767ce01c4914ea9a -919b938e56d4b32e2667469d0bdccb95d9dda3341aa907683ee70a14bbbe623035014511c261f4f59b318b610ac90aa3 -96b48182121ccd9d689bf1dfdc228175564cd68dc904a99c808a7f0053a6f636c9d953e12198bdf2ea49ea92772f2e18 -ac5e5a941d567fa38fdbcfa8cf7f85bb304e3401c52d88752bcd516d1fa9bac4572534ea2205e38423c1df065990790f -ac0bd594fb85a8d4fc26d6df0fa81f11919401f1ecf9168b891ec7f061a2d9368af99f7fd8d9b43b2ce361e7b8482159 -83d92c69ca540d298fe80d8162a1c7af3fa9b49dfb69e85c1d136a3ec39fe419c9fa78e0bb6d96878771fbd37fe92e40 -b35443ae8aa66c763c2db9273f908552fe458e96696b90e41dd509c17a5c04ee178e3490d9c6ba2dc0b8f793c433c134 -923b2d25aa45b2e580ffd94cbb37dc8110f340f0f011217ee1bd81afb0714c0b1d5fb4db86006cdd2457563276f59c59 -96c9125d38fca1a61ac21257b696f8ac3dae78def50285e44d90ea293d591d1c58f703540a7e4e99e070afe4646bbe15 -b57946b2332077fbcdcb406b811779aefd54473b5559a163cd65cb8310679b7e2028aa55c12a1401fdcfcac0e6fae29a -845daedc5cf972883835d7e13c937b63753c2200324a3b8082a6c4abb4be06c5f7c629d4abe4bfaf1d80a1f073eb6ce6 -91a55dfd0efefcd03dc6dacc64ec93b8d296cb83c0ee72400a36f27246e7f2a60e73b7b70ba65819e9cfb73edb7bd297 -8874606b93266455fe8fdd25df9f8d2994e927460af06f2e97dd4d2d90db1e6b06d441b72c2e76504d753badca87fb37 -8ee99e6d231274ff9252c0f4e84549da173041299ad1230929c3e3d32399731c4f20a502b4a307642cac9306ccd49d3c -8836497714a525118e20849d6933bb8535fb6f72b96337d49e3133d936999c90a398a740f42e772353b5f1c63581df6d -a6916945e10628f7497a6cdc5e2de113d25f7ade3e41e74d3de48ccd4fce9f2fa9ab69645275002e6f49399b798c40af -9597706983107eb23883e0812e1a2c58af7f3499d50c6e29b455946cb9812fde1aa323d9ed30d1c0ffd455abe32303cd -a24ee89f7f515cc33bdbdb822e7d5c1877d337f3b2162303cfc2dae028011c3a267c5cb4194afa63a4856a6e1c213448 -8cd25315e4318801c2776824ae6e7d543cb85ed3bc2498ba5752df2e8142b37653cf9e60104d674be3aeb0a66912e97a -b5085ecbe793180b40dbeb879f4c976eaaccaca3a5246807dced5890e0ed24d35f3f86955e2460e14fb44ff5081c07ba -960188cc0b4f908633a6840963a6fa2205fc42c511c6c309685234911c5304ef4c304e3ae9c9c69daa2fb6a73560c256 -a32d0a70bf15d569b4cda5aebe3e41e03c28bf99cdd34ffa6c5d58a097f322772acca904b3a47addb6c7492a7126ebac -977f72d06ad72d4aa4765e0f1f9f4a3231d9f030501f320fe7714cc5d329d08112789fa918c60dd7fdb5837d56bb7fc6 -99fa038bb0470d45852bb871620d8d88520adb701712fcb1f278fed2882722b9e729e6cdce44c82caafad95e37d0e6f7 -b855e8f4fc7634ada07e83b6c719a1e37acb06394bc8c7dcab7747a8c54e5df3943915f021364bd019fdea103864e55f -88bc2cd7458532e98c596ef59ea2cf640d7cc31b4c33cef9ed065c078d1d4eb49677a67de8e6229cc17ea48bace8ee5a -aaa78a3feaa836d944d987d813f9b9741afb076e6aca1ffa42682ab06d46d66e0c07b8f40b9dbd63e75e81efa1ef7b08 -b7b080420cc4d808723b98b2a5b7b59c81e624ab568ecdfdeb8bf3aa151a581b6f56e983ef1b6f909661e25db40b0c69 -abee85c462ac9a2c58e54f06c91b3e5cd8c5f9ab5b5deb602b53763c54826ed6deb0d6db315a8d7ad88733407e8d35e2 -994d075c1527407547590df53e9d72dd31f037c763848d1662eebd4cefec93a24328c986802efa80e038cb760a5300f5 -ab8777640116dfb6678e8c7d5b36d01265dfb16321abbfc277da71556a34bb3be04bc4ae90124ed9c55386d2bfb3bda0 -967e3a828bc59409144463bcf883a3a276b5f24bf3cbfdd7a42343348cba91e00b46ac285835a9b91eef171202974204 -875a9f0c4ffe5bb1d8da5e3c8e41d0397aa6248422a628bd60bfae536a651417d4e8a7d2fb98e13f2dad3680f7bd86d3 -acaa330c3e8f95d46b1880126572b238dbb6d04484d2cd4f257ab9642d8c9fc7b212188b9c7ac9e0fd135c520d46b1bf -aceb762edbb0f0c43dfcdb01ea7a1ac5918ca3882b1e7ebc4373521742f1ed5250d8966b498c00b2b0f4d13212e6dd0b -81d072b4ad258b3646f52f399bced97c613b22e7ad76373453d80b1650c0ca87edb291a041f8253b649b6e5429bb4cff -980a47d27416ac39c7c3a0ebe50c492f8c776ea1de44d5159ac7d889b6d554357f0a77f0e5d9d0ff41aae4369eba1fc2 -8b4dfd5ef5573db1476d5e43aacfb5941e45d6297794508f29c454fe50ea622e6f068b28b3debe8635cf6036007de2e3 -a60831559d6305839515b68f8c3bc7abbd8212cc4083502e19dd682d56ca37c9780fc3ce4ec2eae81ab23b221452dc57 -951f6b2c1848ced9e8a2339c65918e00d3d22d3e59a0a660b1eca667d18f8430d737884e9805865ef3ed0fe1638a22d9 -b02e38fe790b492aa5e89257c4986c9033a8b67010fa2add9787de857d53759170fdd67715ca658220b4e14b0ca48124 -a51007e4346060746e6b0e4797fc08ef17f04a34fe24f307f6b6817edbb8ce2b176f40771d4ae8a60d6152cbebe62653 -a510005b05c0b305075b27b243c9d64bcdce85146b6ed0e75a3178b5ff9608213f08c8c9246f2ca6035a0c3e31619860 -aaff4ef27a7a23be3419d22197e13676d6e3810ceb06a9e920d38125745dc68a930f1741c9c2d9d5c875968e30f34ab5 -864522a9af9857de9814e61383bebad1ba9a881696925a0ea6bfc6eff520d42c506bbe5685a9946ed710e889765be4a0 -b63258c080d13f3b7d5b9f3ca9929f8982a6960bdb1b0f8676f4dca823971601672f15e653917bf5d3746bb220504913 -b51ce0cb10869121ae310c7159ee1f3e3a9f8ad498827f72c3d56864808c1f21fa2881788f19ece884d3f705cd7bd0c5 -95d9cecfc018c6ed510e441cf84c712d9909c778c16734706c93222257f64dcd2a9f1bd0b400ca271e22c9c487014274 -8beff4d7d0140b86380ff4842a9bda94c2d2be638e20ac68a4912cb47dbe01a261857536375208040c0554929ced1ddc -891ff49258749e2b57c1e9b8e04b12c77d79c3308b1fb615a081f2aacdfb4b39e32d53e069ed136fdbd43c53b87418fa -9625cad224e163d387738825982d1e40eeff35fe816d10d7541d15fdc4d3eee48009090f3faef4024b249205b0b28f72 -8f3947433d9bd01aa335895484b540a9025a19481a1c40b4f72dd676bfcf332713714fd4010bde936eaf9470fd239ed0 -a00ec2d67789a7054b53f0e858a8a232706ccc29a9f3e389df7455f1a51a2e75801fd78469a13dbc25d28399ae4c6182 -a3f65884506d4a62b8775a0ea0e3d78f5f46bc07910a93cd604022154eabdf1d73591e304d61edc869e91462951975e1 -a14eef4fd5dfac311713f0faa9a60415e3d30b95a4590cbf95f2033dffb4d16c02e7ceff3dcd42148a4e3bc49cce2dd4 -8afa11c0eef3c540e1e3460bc759bb2b6ea90743623f88e62950c94e370fe4fd01c22b6729beba4dcd4d581198d9358f -afb05548a69f0845ffcc5f5dc63e3cdb93cd270f5655173b9a950394b0583663f2b7164ba6df8d60c2e775c1d9f120af -97f179e01a947a906e1cbeafa083960bc9f1bade45742a3afee488dfb6011c1c6e2db09a355d77f5228a42ccaa7bdf8e -8447fca4d35f74b3efcbd96774f41874ca376bf85b79b6e66c92fa3f14bdd6e743a051f12a7fbfd87f319d1c6a5ce217 -a57ca39c23617cd2cf32ff93b02161bd7baf52c4effb4679d9d5166406e103bc8f3c6b5209e17c37dbb02deb8bc72ddd -9667c7300ff80f0140be002b0e36caab07aaee7cce72679197c64d355e20d96196acaf54e06e1382167d081fe6f739c1 -828126bb0559ce748809b622677267ca896fa2ee76360fd2c02990e6477e06a667241379ca7e65d61a5b64b96d7867de -8b8835dea6ba8cf61c91f01a4b3d2f8150b687a4ee09b45f2e5fc8f80f208ae5d142d8e3a18153f0722b90214e60c5a7 -a98e8ff02049b4da386e3ee93db23bbb13dfeb72f1cfde72587c7e6d962780b7671c63e8ac3fbaeb1a6605e8d79e2f29 -87a4892a0026d7e39ef3af632172b88337cb03669dea564bcdb70653b52d744730ebb5d642e20cb627acc9dbb547a26b -877352a22fc8052878a57effc159dac4d75fe08c84d3d5324c0bab6d564cdf868f33ceee515eee747e5856b62cfa0cc7 -8b801ba8e2ff019ee62f64b8cb8a5f601fc35423eb0f9494b401050103e1307dc584e4e4b21249cd2c686e32475e96c3 -a9e7338d6d4d9bfec91b2af28a8ed13b09415f57a3a00e5e777c93d768fdb3f8e4456ae48a2c6626b264226e911a0e28 -99c05fedf40ac4726ed585d7c1544c6e79619a0d3fb6bda75a08c7f3c0008e8d5e19ed4da48de3216135f34a15eba17c -a61cce8a1a8b13a4a650fdbec0eeea8297c352a8238fb7cac95a0df18ed16ee02a3daa2de108fa122aca733bd8ad7855 -b97f37da9005b440b4cb05870dd881bf8491fe735844f2d5c8281818583b38e02286e653d9f2e7fa5e74c3c3eb616540 -a72164a8554da8e103f692ac5ebb4aece55d5194302b9f74b6f2a05335b6e39beede0bf7bf8c5bfd4d324a784c5fb08c -b87e8221c5341cd9cc8bb99c10fe730bc105550f25ed4b96c0d45e6142193a1b2e72f1b3857373a659b8c09be17b3d91 -a41fb1f327ef91dcb7ac0787918376584890dd9a9675c297c45796e32d6e5985b12f9b80be47fc3a8596c245f419d395 -90dafa3592bdbb3465c92e2a54c2531822ba0459d45d3e7a7092fa6b823f55af28357cb51896d4ec2d66029c82f08e26 -a0a9adc872ebc396557f484f1dd21954d4f4a21c4aa5eec543f5fa386fe590839735c01f236574f7ff95407cd12de103 -b8c5c940d58be7538acf8672852b5da3af34f82405ef2ce8e4c923f1362f97fc50921568d0fd2fe846edfb0823e62979 -85aaf06a8b2d0dac89dafd00c28533f35dbd074978c2aaa5bef75db44a7b12aeb222e724f395513b9a535809a275e30b -81f3cbe82fbc7028c26a6c1808c604c63ba023a30c9f78a4c581340008dbda5ec07497ee849a2183fcd9124f7936af32 -a11ac738de75fd60f15a34209d3825d5e23385796a4c7fc5931822f3f380af977dd0f7b59fbd58eed7777a071e21b680 -85a279c493de03db6fa6c3e3c1b1b29adc9a8c4effc12400ae1128da8421954fa8b75ad19e5388fe4543b76fb0812813 -83a217b395d59ab20db6c4adb1e9713fc9267f5f31a6c936042fe051ce8b541f579442f3dcf0fa16b9e6de9fd3518191 -83a0b86e7d4ed8f9ccdc6dfc8ff1484509a6378fa6f09ed908e6ab9d1073f03011dc497e14304e4e3d181b57de06a5ab -a63ad69c9d25704ce1cc8e74f67818e5ed985f8f851afa8412248b2df5f833f83b95b27180e9e7273833ed0d07113d3b -99b1bc2021e63b561fe44ddd0af81fcc8627a91bfeecbbc989b642bc859abc0c8d636399701aad7bbaf6a385d5f27d61 -b53434adb66f4a807a6ad917c6e856321753e559b1add70824e5c1e88191bf6993fccb9b8b911fc0f473fb11743acacd -97ed3b9e6fb99bf5f945d4a41f198161294866aa23f2327818cdd55cb5dc4c1a8eff29dd8b8d04902d6cd43a71835c82 -b1e808260e368a18d9d10bdea5d60223ba1713b948c782285a27a99ae50cc5fc2c53d407de07155ecc16fb8a36d744a0 -a3eb4665f18f71833fec43802730e56b3ee5a357ea30a888ad482725b169d6f1f6ade6e208ee081b2e2633079b82ba7d -ab8beb2c8353fc9f571c18fdd02bdb977fc883313469e1277b0372fbbb33b80dcff354ca41de436d98d2ed710faa467e -aa9071cfa971e4a335a91ad634c98f2be51544cb21f040f2471d01bb97e1df2277ae1646e1ea8f55b7ba9f5c8c599b39 -80b7dbfdcaf40f0678012acc634eba44ea51181475180d9deb2050dc4f2de395289edd0223018c81057ec79b04b04c49 -89623d7f6cb17aa877af14de842c2d4ab7fd576d61ddd7518b5878620a01ded40b6010de0da3cdf31d837eecf30e9847 -a773bb024ae74dd24761f266d4fb27d6fd366a8634febe8235376b1ae9065c2fe12c769f1d0407867dfbe9f5272c352f -8455a561c3aaa6ba64c881a5e13921c592b3a02e968f4fb24a2243c36202795d0366d9cc1a24e916f84d6e158b7aeac7 -81d8bfc4b283cf702a40b87a2b96b275bdbf0def17e67d04842598610b67ea08c804d400c3e69fa09ea001eaf345b276 -b8f8f82cb11fea1c99467013d7e167ff03deb0c65a677fab76ded58826d1ba29aa7cf9fcd7763615735ea3ad38e28719 -89a6a04baf9cccc1db55179e1650b1a195dd91fb0aebc197a25143f0f393524d2589975e3fbfc2547126f0bced7fd6f2 -b81b2162df045390f04df07cbd0962e6b6ca94275a63edded58001a2f28b2ae2af2c7a6cba4ecd753869684e77e7e799 -a3757f722776e50de45c62d9c4a2ee0f5655a512344c4cbec542d8045332806568dd626a719ef21a4eb06792ca70f204 -8c5590df96ec22179a4e8786de41beb44f987a1dcc508eb341eecbc0b39236fdfad47f108f852e87179ccf4e10091e59 -87502f026ed4e10167419130b88c3737635c5b9074c364e1dd247cef5ef0fc064b4ae99b187e33301e438bbd2fe7d032 -af925a2165e980ced620ff12289129fe17670a90ae0f4db9d4b39bd887ccb1f5d2514ac9ecf910f6390a8fc66bd5be17 -857fca899828cf5c65d26e3e8a6e658542782fc72762b3b9c73514919f83259e0f849a9d4838b40dc905fe43024d0d23 -87ffebdbfb69a9e1007ebac4ffcb4090ff13705967b73937063719aa97908986effcb7262fdadc1ae0f95c3690e3245d -a9ff6c347ac6f4c6ab993b748802e96982eaf489dc69032269568412fc9a79e7c2850dfc991b28211b3522ee4454344b -a65b3159df4ec48bebb67cb3663cd744027ad98d970d620e05bf6c48f230fa45bf17527fe726fdf705419bb7a1bb913e -84b97b1e6408b6791831997b03cd91f027e7660fd492a93d95daafe61f02427371c0e237c75706412f442991dfdff989 -ab761c26527439b209af0ae6afccd9340bbed5fbe098734c3145b76c5d2cd7115d9227b2eb523882b7317fbb09180498 -a0479a8da06d7a69c0b0fee60df4e691c19c551f5e7da286dab430bfbcabf31726508e20d26ea48c53365a7f00a3ad34 -a732dfc9baa0f4f40b5756d2e8d8937742999623477458e0bc81431a7b633eefc6f53b3b7939fe0a020018549c954054 -901502436a1169ba51dc479a5abe7c8d84e0943b16bc3c6a627b49b92cd46263c0005bc324c67509edd693f28e612af1 -b627aee83474e7f84d1bab9b7f6b605e33b26297ac6bbf52d110d38ba10749032bd551641e73a383a303882367af429b -95108866745760baef4a46ef56f82da6de7e81c58b10126ebd2ba2cd13d339f91303bf2fb4dd104a6956aa3b13739503 -899ed2ade37236cec90056f3569bc50f984f2247792defafcceb49ad0ca5f6f8a2f06573705300e07f0de0c759289ff5 -a9f5eee196d608efe4bcef9bf71c646d27feb615e21252cf839a44a49fd89da8d26a758419e0085a05b1d59600e2dc42 -b36c6f68fed6e6c85f1f4a162485f24817f2843ec5cbee45a1ebfa367d44892e464949c6669f7972dc7167af08d55d25 -aaaede243a9a1b6162afbc8f571a52671a5a4519b4062e3f26777664e245ba873ed13b0492c5dbf0258c788c397a0e9e -972b4fb39c31cbe127bf9a32a5cc10d621ebdd9411df5e5da3d457f03b2ab2cd1f6372d8284a4a9400f0b06ecdbfd38e -8f6ca1e110e959a4b1d9a5ce5f212893cec21db40d64d5ac4d524f352d72198f923416a850bf845bc5a22a79c0ea2619 -a0f3c93b22134f66f04b2553a53b738644d1665ceb196b8494b315a4c28236fb492017e4a0de4224827c78e42f9908b7 -807fb5ee74f6c8735b0b5ca07e28506214fe4047dbeb00045d7c24f7849e98706aea79771241224939cb749cf1366c7d -915eb1ff034224c0b645442cdb7d669303fdc00ca464f91aaf0b6fde0b220a3a74ff0cb043c26c9f3a5667b3fdaa9420 -8fda6cef56ed33fefffa9e6ac8e6f76b1af379f89761945c63dd448801f7bb8ca970504a7105fac2f74f652ccff32327 -87380cffdcffb1d0820fa36b63cc081e72187f86d487315177d4d04da4533eb19a0e2ff6115ceab528887819c44a5164 -8cd89e03411a18e7f16f968b89fb500c36d47d229f6487b99e62403a980058db5925ce249206743333538adfad168330 -974451b1df33522ce7056de9f03e10c70bf302c44b0741a59df3d6877d53d61a7394dcee1dd46e013d7cb9d73419c092 -98c35ddf645940260c490f384a49496a7352bb8e3f686feed815b1d38f59ded17b1ad6e84a209e773ed08f7b8ff1e4c2 -963f386cf944bb9b2ddebb97171b64253ea0a2894ac40049bdd86cda392292315f3a3d490ca5d9628c890cfb669f0acb -8d507712152babd6d142ee682638da8495a6f3838136088df9424ef50d5ec28d815a198c9a4963610b22e49b4cdf95e9 -83d4bc6b0be87c8a4f1e9c53f257719de0c73d85b490a41f7420e777311640937320557ff2f1d9bafd1daaa54f932356 -82f5381c965b7a0718441131c4d13999f4cdce637698989a17ed97c8ea2e5bdb5d07719c5f7be8688edb081b23ede0f4 -a6ebecab0b72a49dfd01d69fa37a7f74d34fb1d4fef0aa10e3d6fceb9eccd671225c230af89f6eb514250e41a5f91f52 -846d185bdad6e11e604df7f753b7a08a28b643674221f0e750ebdb6b86ec584a29c869e131bca868972a507e61403f6a -85a98332292acb744bd1c0fd6fdcf1f889a78a2c9624d79413ffa194cc8dfa7821a4b60cde8081d4b5f71f51168dd67f -8f7d97c3b4597880d73200d074eb813d95432306e82dafc70b580b8e08cb8098b70f2d07b4b3ac6a4d77e92d57035031 -8185439c8751e595825d7053518cbe121f191846a38d4dbcb558c3f9d7a3104f3153401adaaaf27843bbe2edb504bfe3 -b3c00d8ece1518fca6b1215a139b0a0e26d9cba1b3a424f7ee59f30ce800a5db967279ed60958dd1f3ee69cf4dd1b204 -a2e6cb6978e883f9719c3c0d44cfe8de0cc6f644b98f98858433bea8bbe7b612c8aca5952fccce4f195f9d54f9722dc2 -99663087e3d5000abbec0fbda4e7342ec38846cc6a1505191fb3f1a337cb369455b7f8531a6eb8b0f7b2c4baf83cbe2b -ab0836c6377a4dbc7ca6a4d6cf021d4cd60013877314dd05f351706b128d4af6337711ed3443cb6ca976f40d74070a9a -87abfd5126152fd3bac3c56230579b489436755ea89e0566aa349490b36a5d7b85028e9fb0710907042bcde6a6f5d7e3 -974ba1033f75f60e0cf7c718a57ae1da3721cf9d0fb925714c46f027632bdd84cd9e6de4cf4d00bc55465b1c5ebb7384 -a607b49d73689ac64f25cec71221d30d53e781e1100d19a2114a21da6507a60166166369d860bd314acb226596525670 -a7c2b0b915d7beba94954f2aa7dd08ec075813661e2a3ecca5d28a0733e59583247fed9528eb28aba55b972cdbaf06eb -b8b3123e44128cc8efbe3270f2f94e50ca214a4294c71c3b851f8cbb70cb67fe9536cf07d04bf7fe380e5e3a29dd3c15 -a59a07e343b62ad6445a0859a32b58c21a593f9ddbfe52049650f59628c93715aa1f4e1f45b109321756d0eeec8a5429 -94f51f8a4ed18a6030d0aaa8899056744bd0e9dc9ac68f62b00355cddab11da5da16798db75f0bfbce0e5bdfe750c0b6 -97460a97ca1e1fa5ce243b81425edc0ec19b7448e93f0b55bc9785eedeeafe194a3c8b33a61a5c72990edf375f122777 -8fa859a089bc17d698a7ee381f37ce9beadf4e5b44fce5f6f29762bc04f96faff5d58c48c73631290325f05e9a1ecf49 -abdf38f3b20fc95eff31de5aa9ef1031abfa48f1305ee57e4d507594570401503476d3bcc493838fc24d6967a3082c7f -b8914bfb82815abb86da35c64d39ab838581bc0bf08967192697d9663877825f2b9d6fbdcf9b410463482b3731361aef -a8187f9d22b193a5f578999954d6ec9aa9b32338ccadb8a3e1ce5bad5ea361d69016e1cdfac44e9d6c54e49dd88561b9 -aac262cb7cba7fd62c14daa7b39677cabc1ef0947dd06dd89cac8570006a200f90d5f0353e84f5ff03179e3bebe14231 -a630ef5ece9733b8c46c0a2df14a0f37647a85e69c63148e79ffdcc145707053f9f9d305c3f1cf3c7915cb46d33abd07 -b102c237cb2e254588b6d53350dfda6901bd99493a3fbddb4121d45e0b475cf2663a40d7b9a75325eda83e4ba1e68cb3 -86a930dd1ddcc16d1dfa00aa292cb6c2607d42c367e470aa920964b7c17ab6232a7108d1c2c11fc40fb7496547d0bbf8 -a832fdc4500683e72a96cce61e62ac9ee812c37fe03527ad4cf893915ca1962cee80e72d4f82b20c8fc0b764376635a1 -88ad985f448dabb04f8808efd90f273f11f5e6d0468b5489a1a6a3d77de342992a73eb842d419034968d733f101ff683 -98a8538145f0d86f7fbf9a81c9140f6095c5bdd8960b1c6f3a1716428cd9cca1bf8322e6d0af24e6169abcf7df2b0ff6 -9048c6eba5e062519011e177e955a200b2c00b3a0b8615bdecdebc217559d41058d3315f6d05617be531ef0f6aef0e51 -833bf225ab6fc68cdcacf1ec1b50f9d05f5410e6cdcd8d56a3081dc2be8a8d07b81534d1ec93a25c2e270313dfb99e3b -a84bcd24c3da5e537e64a811b93c91bfc84d7729b9ead7f79078989a6eb76717d620c1fad17466a0519208651e92f5ff -b7cdd0a3fbd79aed93e1b5a44ca44a94e7af5ed911e4492f332e3a5ed146c7286bde01b52276a2fcc02780d2109874dd -8a19a09854e627cb95750d83c20c67442b66b35896a476358f993ba9ac114d32c59c1b3d0b8787ee3224cf3888b56c64 -a9abd5afb8659ee52ada8fa5d57e7dd355f0a7350276f6160bec5fbf70d5f99234dd179eb221c913e22a49ec6d267846 -8c13c4274c0d30d184e73eaf812200094bbbd57293780bdadbceb262e34dee5b453991e7f37c7333a654fc71c69d6445 -a4320d73296ff8176ce0127ca1921c450e2a9c06eff936681ebaffb5a0b05b17fded24e548454de89aca2dcf6d7a9de4 -b2b8b3e15c1f645f07783e5628aba614e60157889db41d8161d977606788842b67f83f361eae91815dc0abd84e09abd5 -ad26c3aa35ddfddc15719b8bb6c264aaec7065e88ac29ba820eb61f220fef451609a7bb037f3722d022e6c86e4f1dc88 -b8615bf43e13ae5d7b8dd903ce37190800cd490f441c09b22aa29d7a29ed2c0417b7a08ead417868f1de2589deaadd80 -8d3425e1482cd1e76750a76239d33c06b3554c3c3c87c15cb7ab58b1cee86a4c5c4178b44e23f36928365a1b484bde02 -806893a62e38c941a7dd6f249c83af16596f69877cc737d8f73f6b8cd93cbc01177a7a276b2b8c6b0e5f2ad864db5994 -86618f17fa4b0d65496b661bbb5ba3bc3a87129d30a4b7d4f515b904f4206ca5253a41f49fd52095861e5e065ec54f21 -9551915da1304051e55717f4c31db761dcdcf3a1366c89a4af800a9e99aca93a357bf928307f098e62b44a02cb689a46 -8f79c4ec0ec1146cb2a523b52fe33def90d7b5652a0cb9c2d1c8808a32293e00aec6969f5b1538e3a94cd1efa3937f86 -a0c03e329a707300081780f1e310671315b4c6a4cedcb29697aedfabb07a9d5df83f27b20e9c44cf6b16e39d9ded5b98 -86a7cfa7c8e7ce2c01dd0baec2139e97e8e090ad4e7b5f51518f83d564765003c65968f85481bbb97cb18f005ccc7d9f -a33811770c6dfda3f7f74e6ad0107a187fe622d61b444bbd84fd7ef6e03302e693b093df76f6ab39bb4e02afd84a575a -85480f5c10d4162a8e6702b5e04f801874d572a62a130be94b0c02b58c3c59bdcd48cd05f0a1c2839f88f06b6e3cd337 -8e181011564b17f7d787fe0e7f3c87f6b62da9083c54c74fd6c357a1f464c123c1d3d8ade3cf72475000b464b14e2be3 -8ee178937294b8c991337e0621ab37e9ffa4ca2bdb3284065c5e9c08aad6785d50cf156270ff9daf9a9127289710f55b -8bd1e8e2d37379d4b172f1aec96f2e41a6e1393158d7a3dbd9a95c8dd4f8e0b05336a42efc11a732e5f22b47fc5c271d -8f3da353cd487c13136a85677de8cedf306faae0edec733cf4f0046f82fa4639db4745b0095ff33a9766aba50de0cbcf -8d187c1e97638df0e4792b78e8c23967dac43d98ea268ca4aabea4e0fa06cb93183fd92d4c9df74118d7cc27bf54415e -a4c992f08c2f8bac0b74b3702fb0c75c9838d2ce90b28812019553d47613c14d8ce514d15443159d700b218c5a312c49 -a6fd1874034a34c3ea962a316c018d9493d2b3719bb0ec4edbc7c56b240802b2228ab49bee6f04c8a3e9f6f24a48c1c2 -b2efed8e799f8a15999020900dc2c58ece5a3641c90811b86a5198e593d7318b9d53b167818ccdfbe7df2414c9c34011 -995ff7de6181ddf95e3ead746089c6148da3508e4e7a2323c81785718b754d356789b902e7e78e2edc6b0cbd4ff22c78 -944073d24750a9068cbd020b834afc72d2dde87efac04482b3287b40678ad07588519a4176b10f2172a2c463d063a5cd -99db4b1bb76475a6fd75289986ef40367960279524378cc917525fb6ba02a145a218c1e9caeb99332332ab486a125ac0 -89fce4ecd420f8e477af4353b16faabb39e063f3f3c98fde2858b1f2d1ef6eed46f0975a7c08f233b97899bf60ccd60a -8c09a4f07a02b80654798bc63aada39fd638d3e3c4236ccd8a5ca280350c31e4a89e5f4c9aafb34116e71da18c1226b8 -85325cfa7ded346cc51a2894257eab56e7488dbff504f10f99f4cd2b630d913003761a50f175ed167e8073f1b6b63fb0 -b678b4fbec09a8cc794dcbca185f133578f29e354e99c05f6d07ac323be20aecb11f781d12898168e86f2e0f09aca15e -a249cfcbca4d9ba0a13b5f6aac72bf9b899adf582f9746bb2ad043742b28915607467eb794fca3704278f9136f7642be -9438e036c836a990c5e17af3d78367a75b23c37f807228362b4d13e3ddcb9e431348a7b552d09d11a2e9680704a4514f -925ab70450af28c21a488bfb5d38ac994f784cf249d7fd9ad251bb7fd897a23e23d2528308c03415074d43330dc37ef4 -a290563904d5a8c0058fc8330120365bdd2ba1fdbaef7a14bc65d4961bb4217acfaed11ab82669e359531f8bf589b8db -a7e07a7801b871fc9b981a71e195a3b4ba6b6313bc132b04796a125157e78fe5c11a3a46cf731a255ac2d78a4ae78cd0 -b26cd2501ee72718b0eebab6fb24d955a71f363f36e0f6dff0ab1d2d7836dab88474c0cef43a2cc32701fca7e82f7df3 -a1dc3b6c968f3de00f11275092290afab65b2200afbcfa8ddc70e751fa19dbbc300445d6d479a81bda3880729007e496 -a9bc213e28b630889476a095947d323b9ac6461dea726f2dc9084473ae8e196d66fb792a21905ad4ec52a6d757863e7d -b25d178df8c2df8051e7c888e9fa677fde5922e602a95e966db9e4a3d6b23ce043d7dc48a5b375c6b7c78e966893e8c3 -a1c8d88d72303692eaa7adf68ea41de4febec40cc14ae551bb4012afd786d7b6444a3196b5d9d5040655a3366d96b7cd -b22bd44f9235a47118a9bbe2ba5a2ba9ec62476061be2e8e57806c1a17a02f9a51403e849e2e589520b759abd0117683 -b8add766050c0d69fe81d8d9ea73e1ed05f0135d093ff01debd7247e42dbb86ad950aceb3b50b9af6cdc14ab443b238f -af2cf95f30ef478f018cf81d70d47d742120b09193d8bb77f0d41a5d2e1a80bfb467793d9e2471b4e0ad0cb2c3b42271 -8af5ef2107ad284e246bb56e20fef2a255954f72de791cbdfd3be09f825298d8466064f3c98a50496c7277af32b5c0bc -85dc19558572844c2849e729395a0c125096476388bd1b14fa7f54a7c38008fc93e578da3aac6a52ff1504d6ca82db05 -ae8c9b43c49572e2e166d704caf5b4b621a3b47827bb2a3bcd71cdc599bba90396fd9a405261b13e831bb5d44c0827d7 -a7ba7efede25f02e88f6f4cbf70643e76784a03d97e0fbd5d9437c2485283ad7ca3abb638a5f826cd9f6193e5dec0b6c -94a9d122f2f06ef709fd8016fd4b712d88052245a65a301f5f177ce22992f74ad05552b1f1af4e70d1eac62cef309752 -82d999b3e7cf563833b8bc028ff63a6b26eb357dfdb3fd5f10e33a1f80a9b2cfa7814d871b32a7ebfbaa09e753e37c02 -aec6edcde234df502a3268dd2c26f4a36a2e0db730afa83173f9c78fcb2b2f75510a02b80194327b792811caefda2725 -94c0bfa66c9f91d462e9194144fdd12d96f9bbe745737e73bab8130607ee6ea9d740e2cfcbbd00a195746edb6369ee61 -ab7573dab8c9d46d339e3f491cb2826cabe8b49f85f1ede78d845fc3995537d1b4ab85140b7d0238d9c24daf0e5e2a7e -87e8b16832843251fe952dadfd01d41890ed4bb4b8fa0254550d92c8cced44368225eca83a6c3ad47a7f81ff8a80c984 -9189d2d9a7c64791b19c0773ad4f0564ce6bea94aa275a917f78ad987f150fdb3e5e26e7fef9982ac184897ecc04683f -b3661bf19e2da41415396ae4dd051a9272e8a2580b06f1a1118f57b901fa237616a9f8075af1129af4eabfefedbe2f1c -af43c86661fb15daf5d910a4e06837225e100fb5680bd3e4b10f79a2144c6ec48b1f8d6e6b98e067d36609a5d038889a -82ac0c7acaa83ddc86c5b4249aae12f28155989c7c6b91e5137a4ce05113c6cbc16f6c44948b0efd8665362d3162f16a -8f268d1195ab465beeeb112cd7ffd5d5548559a8bc01261106d3555533fc1971081b25558d884d552df0db1cddda89d8 -8ef7caa5521f3e037586ce8ac872a4182ee20c7921c0065ed9986c047e3dda08294da1165f385d008b40d500f07d895f -8c2f98f6880550573fad46075d3eba26634b5b025ce25a0b4d6e0193352c8a1f0661064027a70fe8190b522405f9f4e3 -b7653f353564feb164f0f89ec7949da475b8dad4a4d396d252fc2a884f6932d027b7eb2dc4d280702c74569319ed701a -a026904f4066333befd9b87a8fad791d014096af60cdd668ef919c24dbe295ff31f7a790e1e721ba40cf5105abca67f4 -988f982004ada07a22dd345f2412a228d7a96b9cae2c487de42e392afe1e35c2655f829ce07a14629148ce7079a1f142 -9616add009067ed135295fb74d5b223b006b312bf14663e547a0d306694ff3a8a7bb9cfc466986707192a26c0bce599f -ad4c425de9855f6968a17ee9ae5b15e0a5b596411388cf976df62ecc6c847a6e2ddb2cea792a5f6e9113c2445dba3e5c -b698ac9d86afa3dc69ff8375061f88e3b0cff92ff6dfe747cebaf142e813c011851e7a2830c10993b715e7fd594604a9 -a386fa189847bb3b798efca917461e38ead61a08b101948def0f82cd258b945ed4d45b53774b400af500670149e601b7 -905c95abda2c68a6559d8a39b6db081c68cef1e1b4be63498004e1b2f408409be9350b5b5d86a30fd443e2b3e445640a -9116dade969e7ce8954afcdd43e5cab64dc15f6c1b8da9d2d69de3f02ba79e6c4f6c7f54d6bf586d30256ae405cd1e41 -a3084d173eacd08c9b5084a196719b57e47a0179826fda73466758235d7ecdb87cbcf097bd6b510517d163a85a7c7edd -85bb00415ad3c9be99ff9ba83672cc59fdd24356b661ab93713a3c8eab34e125d8867f628a3c3891b8dc056e69cd0e83 -8d58541f9f39ed2ee4478acce5d58d124031338ec11b0d55551f00a5a9a6351faa903a5d7c132dc5e4bb026e9cbd18e4 -a622adf72dc250e54f672e14e128c700166168dbe0474cecb340da175346e89917c400677b1bc1c11fcc4cc26591d9db -b3f865014754b688ca8372e8448114fff87bf3ca99856ab9168894d0c4679782c1ced703f5b74e851b370630f5e6ee86 -a7e490b2c40c2446fcd91861c020da9742c326a81180e38110558bb5d9f2341f1c1885e79b364e6419023d1cbdc47380 -b3748d472b1062e54572badbb8e87ac36534407f74932e7fc5b8392d008e8e89758f1671d1e4d30ab0fa40551b13bb5e -89898a5c5ec4313aabc607b0049fd1ebad0e0c074920cf503c9275b564d91916c2c446d3096491c950b7af3ac5e4b0ed -8eb8c83fef2c9dd30ea44e286e9599ec5c20aba983f702e5438afe2e5b921884327ad8d1566c72395587efac79ca7d56 -b92479599e806516ce21fb0bd422a1d1d925335ebe2b4a0a7e044dd275f30985a72b97292477053ac5f00e081430da80 -a34ae450a324fe8a3c25a4d653a654f9580ed56bbea213b8096987bbad0f5701d809a17076435e18017fea4d69f414bc -81381afe6433d62faf62ea488f39675e0091835892ecc238e02acf1662669c6d3962a71a3db652f6fe3bc5f42a0e5dc5 -a430d475bf8580c59111103316fe1aa79c523ea12f1d47a976bbfae76894717c20220e31cf259f08e84a693da6688d70 -b842814c359754ece614deb7d184d679d05d16f18a14b288a401cef5dad2cf0d5ee90bad487b80923fc5573779d4e4e8 -971d9a2627ff2a6d0dcf2af3d895dfbafca28b1c09610c466e4e2bff2746f8369de7f40d65b70aed135fe1d72564aa88 -8f4ce1c59e22b1ce7a0664caaa7e53735b154cfba8d2c5cc4159f2385843de82ab58ed901be876c6f7fce69cb4130950 -86cc9dc321b6264297987000d344fa297ef45bcc2a4df04e458fe2d907ad304c0ea2318e32c3179af639a9a56f3263cf -8229e0876dfe8f665c3fb19b250bd89d40f039bbf1b331468b403655be7be2e104c2fd07b9983580c742d5462ca39a43 -99299d73066e8eb128f698e56a9f8506dfe4bd014931e86b6b487d6195d2198c6c5bf15cccb40ccf1f8ddb57e9da44a2 -a3a3be37ac554c574b393b2f33d0a32a116c1a7cfeaf88c54299a4da2267149a5ecca71f94e6c0ef6e2f472b802f5189 -a91700d1a00387502cdba98c90f75fbc4066fefe7cc221c8f0e660994c936badd7d2695893fde2260c8c11d5bdcdd951 -8e03cae725b7f9562c5c5ab6361644b976a68bada3d7ca508abca8dfc80a469975689af1fba1abcf21bc2a190dab397d -b01461ad23b2a8fa8a6d241e1675855d23bc977dbf4714add8c4b4b7469ccf2375cec20e80cedfe49361d1a30414ac5b -a2673bf9bc621e3892c3d7dd4f1a9497f369add8cbaa3472409f4f86bd21ac67cfac357604828adfee6ada1835365029 -a042dff4bf0dfc33c178ba1b335e798e6308915128de91b12e5dbbab7c4ac8d60a01f6aea028c3a6d87b9b01e4e74c01 -86339e8a75293e4b3ae66b5630d375736b6e6b6b05c5cda5e73fbf7b2f2bd34c18a1d6cefede08625ce3046e77905cb8 -af2ebe1b7d073d03e3d98bc61af83bf26f7a8c130fd607aa92b75db22d14d016481b8aa231e2c9757695f55b7224a27f -a00ee882c9685e978041fd74a2c465f06e2a42ffd3db659053519925be5b454d6f401e3c12c746e49d910e4c5c9c5e8c -978a781c0e4e264e0dad57e438f1097d447d891a1e2aa0d5928f79a9d5c3faae6f258bc94fdc530b7b2fa6a9932bb193 -aa4b7ce2e0c2c9e9655bf21e3e5651c8503bce27483017b0bf476be743ba06db10228b3a4c721219c0779747f11ca282 -b003d1c459dacbcf1a715551311e45d7dbca83a185a65748ac74d1800bbeaba37765d9f5a1a221805c571910b34ebca8 -95b6e531b38648049f0d19de09b881baa1f7ea3b2130816b006ad5703901a05da57467d1a3d9d2e7c73fb3f2e409363c -a6cf9c06593432d8eba23a4f131bb7f72b9bd51ab6b4b772a749fe03ed72b5ced835a349c6d9920dba2a39669cb7c684 -aa3d59f6e2e96fbb66195bc58c8704e139fa76cd15e4d61035470bd6e305db9f98bcbf61ac1b95e95b69ba330454c1b3 -b57f97959c208361de6d7e86dff2b873068adb0f158066e646f42ae90e650079798f165b5cd713141cd3a2a90a961d9a -a76ee8ed9052f6a7a8c69774bb2597be182942f08115baba03bf8faaeaee526feba86120039fe8ca7b9354c3b6e0a8e6 -95689d78c867724823f564627d22d25010f278674c6d2d0cdb10329169a47580818995d1d727ce46c38a1e47943ebb89 -ab676d2256c6288a88e044b3d9ffd43eb9d5aaee00e8fc60ac921395fb835044c71a26ca948e557fed770f52d711e057 -96351c72785c32e5d004b6f4a1259fb8153d631f0c93fed172f18e8ba438fbc5585c1618deeabd0d6d0b82173c2e6170 -93dd8d3db576418e22536eba45ab7f56967c6c97c64260d6cddf38fb19c88f2ec5cd0e0156f50e70855eee8a2b879ffd -ad6ff16f40f6de3d7a737f8e6cebd8416920c4ff89dbdcd75eabab414af9a6087f83ceb9aff7680aa86bff98bd09c8cc -84de53b11671abc9c38710e19540c5c403817562aeb22a88404cdaff792c1180f717dbdfe8f54940c062c4d032897429 -872231b9efa1cdd447b312099a5c164c560440a9441d904e70f5abfc3b2a0d16be9a01aca5e0a2599a61e19407587e3d -88f44ac27094a2aa14e9dc40b099ee6d68f97385950f303969d889ee93d4635e34dff9239103bdf66a4b7cbba3e7eb7a -a59afebadf0260e832f6f44468443562f53fbaf7bcb5e46e1462d3f328ac437ce56edbca617659ac9883f9e13261fad7 -b1990e42743a88de4deeacfd55fafeab3bc380cb95de43ed623d021a4f2353530bcab9594389c1844b1c5ea6634c4555 -85051e841149a10e83f56764e042182208591396d0ce78c762c4a413e6836906df67f38c69793e158d64fef111407ba3 -9778172bbd9b1f2ec6bbdd61829d7b39a7df494a818e31c654bf7f6a30139899c4822c1bf418dd4f923243067759ce63 -9355005b4878c87804fc966e7d24f3e4b02bed35b4a77369d01f25a3dcbff7621b08306b1ac85b76fe7b4a3eb5f839b1 -8f9dc6a54fac052e236f8f0e1f571ac4b5308a43acbe4cc8183bce26262ddaf7994e41cf3034a4cbeca2c505a151e3b1 -8cc59c17307111723fe313046a09e0e32ea0cce62c13814ab7c6408c142d6a0311d801be4af53fc9240523f12045f9ef -8e6057975ed40a1932e47dd3ac778f72ee2a868d8540271301b1aa6858de1a5450f596466494a3e0488be4fbeb41c840 -812145efbd6559ae13325d56a15940ca4253b17e72a9728986b563bb5acc13ec86453796506ac1a8f12bd6f9e4a288c3 -911da0a6d6489eb3dab2ec4a16e36127e8a291ae68a6c2c9de33e97f3a9b1f00da57a94e270a0de79ecc5ecb45d19e83 -b72ea85973f4b2a7e6e71962b0502024e979a73c18a9111130e158541fa47bbaaf53940c8f846913a517dc69982ba9e1 -a7a56ad1dbdc55f177a7ad1d0af78447dc2673291e34e8ab74b26e2e2e7d8c5fe5dc89e7ef60f04a9508847b5b3a8188 -b52503f6e5411db5d1e70f5fb72ccd6463fa0f197b3e51ca79c7b5a8ab2e894f0030476ada72534fa4eb4e06c3880f90 -b51c7957a3d18c4e38f6358f2237b3904618d58b1de5dec53387d25a63772e675a5b714ad35a38185409931157d4b529 -b86b4266e719d29c043d7ec091547aa6f65bbf2d8d831d1515957c5c06513b72aa82113e9645ad38a7bc3f5383504fa6 -b95b547357e6601667b0f5f61f261800a44c2879cf94e879def6a105b1ad2bbf1795c3b98a90d588388e81789bd02681 -a58fd4c5ae4673fa350da6777e13313d5d37ed1dafeeb8f4f171549765b84c895875d9d3ae6a9741f3d51006ef81d962 -9398dc348d078a604aadc154e6eef2c0be1a93bb93ba7fe8976edc2840a3a318941338cc4d5f743310e539d9b46613d2 -902c9f0095014c4a2f0dccaaab543debba6f4cc82c345a10aaf4e72511725dbed7a34cd393a5f4e48a3e5142b7be84ed -a7c0447849bb44d04a0393a680f6cd390093484a79a147dd238f5d878030d1c26646d88211108e59fe08b58ad20c6fbd -80db045535d6e67a422519f5c89699e37098449d249698a7cc173a26ccd06f60238ae6cc7242eb780a340705c906790c -8e52b451a299f30124505de2e74d5341e1b5597bdd13301cc39b05536c96e4380e7f1b5c7ef076f5b3005a868657f17c -824499e89701036037571761e977654d2760b8ce21f184f2879fda55d3cda1e7a95306b8abacf1caa79d3cc075b9d27f -9049b956b77f8453d2070607610b79db795588c0cec12943a0f5fe76f358dea81e4f57a4692112afda0e2c05c142b26f -81911647d818a4b5f4990bfd4bc13bf7be7b0059afcf1b6839333e8569cdb0172fd2945410d88879349f677abaed5eb3 -ad4048f19b8194ed45b6317d9492b71a89a66928353072659f5ce6c816d8f21e69b9d1817d793effe49ca1874daa1096 -8d22f7b2ddb31458661abd34b65819a374a1f68c01fc6c9887edeba8b80c65bceadb8f57a3eb686374004b836261ef67 -92637280c259bc6842884db3d6e32602a62252811ae9b019b3c1df664e8809ffe86db88cfdeb8af9f46435c9ee790267 -a2f416379e52e3f5edc21641ea73dc76c99f7e29ea75b487e18bd233856f4c0183429f378d2bfc6cd736d29d6cadfa49 -882cb6b76dbdc188615dcf1a8439eba05ffca637dd25197508156e03c930b17b9fed2938506fdd7b77567cb488f96222 -b68b621bb198a763fb0634eddb93ed4b5156e59b96c88ca2246fd1aea3e6b77ed651e112ac41b30cd361fadc011d385e -a3cb22f6b675a29b2d1f827cacd30df14d463c93c3502ef965166f20d046af7f9ab7b2586a9c64f4eae4fad2d808a164 -8302d9ce4403f48ca217079762ce42cee8bc30168686bb8d3a945fbd5acd53b39f028dce757b825eb63af2d5ae41169d -b2eef1fbd1a176f1f4cd10f2988c7329abe4eb16c7405099fb92baa724ab397bc98734ef7d4b24c0f53dd90f57520d04 -a1bbef0bd684a3f0364a66bde9b29326bac7aa3dde4caed67f14fb84fed3de45c55e406702f1495a3e2864d4ee975030 -976acdb0efb73e3a3b65633197692dedc2adaed674291ae3df76b827fc866d214e9cac9ca46baefc4405ff13f953d936 -b9fbf71cc7b6690f601f0b1c74a19b7d14254183a2daaafec7dc3830cba5ae173d854bbfebeca985d1d908abe5ef0cda -90591d7b483598c94e38969c4dbb92710a1a894bcf147807f1bcbd8aa3ac210b9f2be65519aa829f8e1ccdc83ad9b8cf -a30568577c91866b9c40f0719d46b7b3b2e0b4a95e56196ac80898a2d89cc67880e1229933f2cd28ee3286f8d03414d7 -97589a88c3850556b359ec5e891f0937f922a751ac7c95949d3bbc7058c172c387611c0f4cb06351ef02e5178b3dd9e4 -98e7bbe27a1711f4545df742f17e3233fbcc63659d7419e1ca633f104cb02a32c84f2fac23ca2b84145c2672f68077ab -a7ddb91636e4506d8b7e92aa9f4720491bb71a72dadc47c7f4410e15f93e43d07d2b371951a0e6a18d1bd087aa96a5c4 -a7c006692227a06db40bceac3d5b1daae60b5692dd9b54772bedb5fea0bcc91cbcdb530cac31900ffc70c5b3ffadc969 -8d3ec6032778420dfa8be52066ba0e623467df33e4e1901dbadd586c5d750f4ccde499b5197e26b9ea43931214060f69 -8d9a8410518ea64f89df319bfd1fc97a0971cdb9ad9b11d1f8fe834042ea7f8dce4db56eeaf179ff8dda93b6db93e5ce -a3c533e9b3aa04df20b9ff635cb1154ce303e045278fcf3f10f609064a5445552a1f93989c52ce852fd0bbd6e2b6c22e -81934f3a7f8c1ae60ec6e4f212986bcc316118c760a74155d06ce0a8c00a9b9669ec4e143ca214e1b995e41271774fd9 -ab8e2d01a71192093ef8fafa7485e795567cc9db95a93fb7cc4cf63a391ef89af5e2bfad4b827fffe02b89271300407f -83064a1eaa937a84e392226f1a60b7cfad4efaa802f66de5df7498962f7b2649924f63cd9962d47906380b97b9fe80e1 -b4f5e64a15c6672e4b55417ee5dc292dcf93d7ea99965a888b1cc4f5474a11e5b6520eacbcf066840b343f4ceeb6bf33 -a63d278b842456ef15c278b37a6ea0f27c7b3ffffefca77c7a66d2ea06c33c4631eb242bbb064d730e70a8262a7b848a -83a41a83dbcdf0d22dc049de082296204e848c453c5ab1ba75aa4067984e053acf6f8b6909a2e1f0009ed051a828a73b -819485b036b7958508f15f3c19436da069cbe635b0318ebe8c014cf1ef9ab2df038c81161b7027475bcfa6fff8dd9faf -aa40e38172806e1e045e167f3d1677ef12d5dcdc89b43639a170f68054bd196c4fae34c675c1644d198907a03f76ba57 -969bae484883a9ed1fbed53b26b3d4ee4b0e39a6c93ece5b3a49daa01444a1c25727dabe62518546f36b047b311b177c -80a9e73a65da99664988b238096a090d313a0ee8e4235bc102fa79bb337b51bb08c4507814eb5baec22103ec512eaab0 -86604379aec5bddda6cbe3ef99c0ac3a3c285b0b1a15b50451c7242cd42ae6b6c8acb717dcca7917838432df93a28502 -a23407ee02a495bed06aa7e15f94cfb05c83e6d6fba64456a9bbabfa76b2b68c5c47de00ba169e710681f6a29bb41a22 -98cff5ecc73b366c6a01b34ac9066cb34f7eeaf4f38a5429bad2d07e84a237047e2a065c7e8a0a6581017dadb4695deb -8de9f68a938f441f3b7ab84bb1f473c5f9e5c9e139e42b7ccee1d254bd57d0e99c2ccda0f3198f1fc5737f6023dd204e -b0ce48d815c2768fb472a315cad86aa033d0e9ca506f146656e2941829e0acb735590b4fbc713c2d18d3676db0a954ac -82f485cdefd5642a6af58ac6817991c49fac9c10ace60f90b27f1788cc026c2fe8afc83cf499b3444118f9f0103598a8 -82c24550ed512a0d53fc56f64cc36b553823ae8766d75d772dacf038c460f16f108f87a39ceef7c66389790f799dbab3 -859ffcf1fe9166388316149b9acc35694c0ea534d43f09dae9b86f4aa00a23b27144dda6a352e74b9516e8c8d6fc809c -b8f7f353eec45da77fb27742405e5ad08d95ec0f5b6842025be9def3d9892f85eb5dd0921b41e6eff373618dba215bca -8ccca4436f9017e426229290f5cd05eac3f16571a4713141a7461acfe8ae99cd5a95bf5b6df129148693c533966145da -a2c67ecc19c0178b2994846fea4c34c327a5d786ac4b09d1d13549d5be5996d8a89021d63d65cb814923388f47cc3a03 -aa0ff87d676b418ec08f5cbf577ac7e744d1d0e9ebd14615b550eb86931eafd2a36d4732cc5d6fab1713fd7ab2f6f7c0 -8aef4730bb65e44efd6bb9441c0ae897363a2f3054867590a2c2ecf4f0224e578c7a67f10b40f8453d9f492ac15a9b2d -86a187e13d8fba5addcfdd5b0410cedd352016c930f913addd769ee09faa6be5ca3e4b1bdb417a965c643a99bd92be42 -a0a4e9632a7a094b14b29b78cd9c894218cdf6783e61671e0203865dc2a835350f465fbaf86168f28af7c478ca17bc89 -a8c7b02d8deff2cd657d8447689a9c5e2cd74ef57c1314ac4d69084ac24a7471954d9ff43fe0907d875dcb65fd0d3ce5 -97ded38760aa7be6b6960b5b50e83b618fe413cbf2bcc1da64c05140bcc32f5e0e709cd05bf8007949953fac5716bad9 -b0d293835a24d64c2ae48ce26e550b71a8c94a0883103757fb6b07e30747f1a871707d23389ba2b2065fa6bafe220095 -8f9e291bf849feaa575592e28e3c8d4b7283f733d41827262367ea1c40f298c7bcc16505255a906b62bf15d9f1ba85fb -998f4e2d12708b4fd85a61597ca2eddd750f73c9e0c9b3cf0825d8f8e01f1628fd19797dcaed3b16dc50331fc6b8b821 -b30d1f8c115d0e63bf48f595dd10908416774c78b3bbb3194192995154d80ea042d2e94d858de5f8aa0261b093c401fd -b5d9c75bb41f964cbff3f00e96d9f1480c91df8913f139f0d385d27a19f57a820f838eb728e46823cbff00e21c660996 -a6edec90b5d25350e2f5f0518777634f9e661ec9d30674cf5b156c4801746d62517751d90074830ac0f4b09911c262f1 -82f98da1264b6b75b8fbeb6a4d96d6a05b25c24db0d57ba3a38efe3a82d0d4e331b9fc4237d6494ccfe4727206457519 -b89511843453cf4ecd24669572d6371b1e529c8e284300c43e0d5bb6b3aaf35aeb634b3cb5c0a2868f0d5e959c1d0772 -a82bf065676583e5c1d3b81987aaae5542f522ba39538263a944bb33ea5b514c649344a96c0205a3b197a3f930fcda6c -a37b47ea527b7e06c460776aa662d9a49ff4149d3993f1a974b0dd165f7171770d189b0e2ea54fd5fccb6a14b116e68a -a1017677f97dda818274d47556d09d0e4ccacb23a252f82a6cfe78c630ad46fb9806307445a59fb61262182de3a2b29c -b01e9fcac239ba270e6877b79273ddd768bf8a51d2ed8a051b1c11e18eff3de5920e2fcbfbd26f06d381eddd3b1f1e1b -82fcd53d803b1c8e4ed76adc339b7f3a5962d37042b9683aabac7513ac68775d4a566a9460183926a6a95dbe7d551a1f -a763e78995d55cd21cdb7ef75d9642d6e1c72453945e346ab6690c20a4e1eeec61bb848ef830ae4b56182535e3c71d8f -b769f4db602251d4b0a1186782799bdcef66de33c110999a5775c50b349666ffd83d4c89714c4e376f2efe021a5cfdb2 -a59cbd1b785efcfa6e83fc3b1d8cf638820bc0c119726b5368f3fba9dce8e3414204fb1f1a88f6c1ff52e87961252f97 -95c8c458fd01aa23ecf120481a9c6332ebec2e8bb70a308d0576926a858457021c277958cf79017ddd86a56cacc2d7db -82eb41390800287ae56e77f2e87709de5b871c8bdb67c10a80fc65f3acb9f7c29e8fa43047436e8933f27449ea61d94d -b3ec25e3545eb83aed2a1f3558d1a31c7edde4be145ecc13b33802654b77dc049b4f0065069dd9047b051e52ab11dcdd -b78a0c715738f56f0dc459ab99e252e3b579b208142836b3c416b704ca1de640ca082f29ebbcee648c8c127df06f6b1e -a4083149432eaaf9520188ebf4607d09cf664acd1f471d4fb654476e77a9eaae2251424ffda78d09b6cb880df35c1219 -8c52857d68d6e9672df3db2df2dbf46b516a21a0e8a18eec09a6ae13c1ef8f369d03233320dd1c2c0bbe00abfc1ea18b -8c856089488803066bff3f8d8e09afb9baf20cecc33c8823c1c0836c3d45498c3de37e87c016b705207f60d2b00f8609 -831a3df39be959047b2aead06b4dcd3012d7b29417f642b83c9e8ce8de24a3dbbd29c6fdf55e2db3f7ea04636c94e403 -aed84d009f66544addabe404bf6d65af7779ce140dc561ff0c86a4078557b96b2053b7b8a43432ffb18cd814f143b9da -93282e4d72b0aa85212a77b336007d8ba071eea17492da19860f1ad16c1ea8867ccc27ef5c37c74b052465cc11ea4f52 -a7b78b8c8d057194e8d68767f1488363f77c77bddd56c3da2bc70b6354c7aa76247c86d51f7371aa38a4aa7f7e3c0bb7 -b1c77283d01dcd1bde649b5b044eac26befc98ff57cbee379fb5b8e420134a88f2fc7f0bf04d15e1fbd45d29e7590fe6 -a4aa8de70330a73b2c6458f20a1067eed4b3474829b36970a8df125d53bbdda4f4a2c60063b7cccb0c80fc155527652f -948a6c79ba1b8ad7e0bed2fae2f0481c4e41b4d9bbdd9b58164e28e9065700e83f210c8d5351d0212e0b0b68b345b3a5 -86a48c31dcbbf7b082c92d28e1f613a2378a910677d7db3a349dc089e4a1e24b12eee8e8206777a3a8c64748840b7387 -976adb1af21e0fc34148917cf43d933d7bfd3fd12ed6c37039dcd5a4520e3c6cf5868539ba5bf082326430deb8a4458d -b93e1a4476f2c51864bb4037e7145f0635eb2827ab91732b98d49b6c07f6ac443111aa1f1da76d1888665cb897c3834e -8afd46fb23bf869999fa19784b18a432a1f252d09506b8dbb756af900518d3f5f244989b3d7c823d9029218c655d3dc6 -83f1e59e3abeed18cdc632921672673f1cb6e330326e11c4e600e13e0d5bc11bdc970ae12952e15103a706fe720bf4d6 -90ce4cc660714b0b673d48010641c09c00fc92a2c596208f65c46073d7f349dd8e6e077ba7dcef9403084971c3295b76 -8b09b0f431a7c796561ecf1549b85048564de428dac0474522e9558b6065fede231886bc108539c104ce88ebd9b5d1b0 -85d6e742e2fb16a7b0ba0df64bc2c0dbff9549be691f46a6669bca05e89c884af16822b85faefefb604ec48c8705a309 -a87989ee231e468a712c66513746fcf03c14f103aadca0eac28e9732487deb56d7532e407953ab87a4bf8961588ef7b0 -b00da10efe1c29ee03c9d37d5918e391ae30e48304e294696b81b434f65cf8c8b95b9d1758c64c25e534d045ba28696f -91c0e1fb49afe46c7056400baa06dbb5f6e479db78ee37e2d76c1f4e88994357e257b83b78624c4ef6091a6c0eb8254d -883fb797c498297ccbf9411a3e727c3614af4eccde41619b773dc7f3259950835ee79453debf178e11dec4d3ada687a0 -a14703347e44eb5059070b2759297fcfcfc60e6893c0373eea069388eba3950aa06f1c57cd2c30984a2d6f9e9c92c79e -afebc7585b304ceba9a769634adff35940e89cd32682c78002822aab25eec3edc29342b7f5a42a56a1fec67821172ad5 -aea3ff3822d09dba1425084ca95fd359718d856f6c133c5fabe2b2eed8303b6e0ba0d8698b48b93136a673baac174fd9 -af2456a09aa777d9e67aa6c7c49a1845ea5cdda2e39f4c935c34a5f8280d69d4eec570446998cbbe31ede69a91e90b06 -82cada19fed16b891ef3442bafd49e1f07c00c2f57b2492dd4ee36af2bd6fd877d6cb41188a4d6ce9ec8d48e8133d697 -82a21034c832287f616619a37c122cee265cc34ae75e881fcaea4ea7f689f3c2bc8150bbf7dbcfd123522bfb7f7b1d68 -86877217105f5d0ec3eeff0289fc2a70d505c9fdf7862e8159553ef60908fb1a27bdaf899381356a4ef4649072a9796c -82b196e49c6e861089a427c0b4671d464e9d15555ffb90954cd0d630d7ae02eb3d98ceb529d00719c2526cd96481355a -a29b41d0d43d26ce76d4358e0db2b77df11f56e389f3b084d8af70a636218bd3ac86b36a9fe46ec9058c26a490f887f7 -a4311c4c20c4d7dd943765099c50f2fd423e203ccfe98ff00087d205467a7873762510cac5fdce7a308913ed07991ed7 -b1f040fc5cc51550cb2c25cf1fd418ecdd961635a11f365515f0cb4ffb31da71f48128c233e9cc7c0cf3978d757ec84e -a9ebae46f86d3bd543c5f207ed0d1aed94b8375dc991161d7a271f01592912072e083e2daf30c146430894e37325a1b9 -826418c8e17ad902b5fe88736323a47e0ca7a44bce4cbe27846ec8fe81de1e8942455dda6d30e192cdcc73e11df31256 -85199db563427c5edcbac21f3d39fec2357be91fb571982ddcdc4646b446ad5ced84410de008cb47b3477ee0d532daf8 -b7eed9cd400b2ca12bf1d9ae008214b8561fb09c8ad9ff959e626ffde00fee5ff2f5b6612e231f2a1a9b1646fcc575e3 -8b40bf12501dcbac78f5a314941326bfcddf7907c83d8d887d0bb149207f85d80cd4dfbd7935439ea7b14ea39a3fded7 -83e3041af302485399ba6cd5120e17af61043977083887e8d26b15feec4a6b11171ac5c06e6ad0971d4b58a81ff12af3 -8f5b9a0eecc589dbf8c35a65d5e996a659277ef6ea509739c0cb7b3e2da9895e8c8012de662e5b23c5fa85d4a8f48904 -835d71ed5e919d89d8e6455f234f3ff215462c4e3720c371ac8c75e83b19dfe3ae15a81547e4dc1138e5f5997f413cc9 -8b7d2e4614716b1db18e9370176ea483e6abe8acdcc3dcdf5fb1f4d22ca55d652feebdccc171c6de38398d9f7bfdec7a -93eace72036fe57d019676a02acf3d224cf376f166658c1bf705db4f24295881d477d6fdd7916efcfceff8c7a063deda -b1ac460b3d516879a84bc886c54f020a9d799e7c49af3e4d7de5bf0d2793c852254c5d8fe5616147e6659512e5ccb012 -acd0947a35cb167a48bcd9667620464b54ac0e78f9316b4aa92dcaab5422d7a732087e52e1c827faa847c6b2fe6e7766 -94ac33d21c3d12ff762d32557860e911cd94d666609ddcc42161b9c16f28d24a526e8b10bb03137257a92cec25ae637d -832e02058b6b994eadd8702921486241f9a19e68ed1406dad545e000a491ae510f525ccf9d10a4bba91c68f2c53a0f58 -9471035d14f78ff8f463b9901dd476b587bb07225c351161915c2e9c6114c3c78a501379ab6fb4eb03194c457cbd22bf -ab64593e034c6241d357fcbc32d8ea5593445a5e7c24cac81ad12bd2ef01843d477a36dc1ba21dbe63b440750d72096a -9850f3b30045e927ad3ec4123a32ed2eb4c911f572b6abb79121873f91016f0d80268de8b12e2093a4904f6e6cab7642 -987212c36b4722fe2e54fa30c52b1e54474439f9f35ca6ad33c5130cd305b8b54b532dd80ffd2c274105f20ce6d79f6e -8b4d0c6abcb239b5ed47bef63bc17efe558a27462c8208fa652b056e9eae9665787cd1aee34fbb55beb045c8bfdb882b -a9f3483c6fee2fe41312d89dd4355d5b2193ac413258993805c5cbbf0a59221f879386d3e7a28e73014f10e65dd503d9 -a2225da3119b9b7c83d514b9f3aeb9a6d9e32d9cbf9309cbb971fd53c4b2c001d10d880a8ad8a7c281b21d85ceca0b7c -a050be52e54e676c151f7a54453bbb707232f849beab4f3bf504b4d620f59ed214409d7c2bd3000f3ff13184ccda1c35 -adbccf681e15b3edb6455a68d292b0a1d0f5a4cb135613f5e6db9943f02181341d5755875db6ee474e19ace1c0634a28 -8b6eff675632a6fad0111ec72aacc61c7387380eb87933fd1d098856387d418bd38e77d897e65d6fe35951d0627c550b -aabe2328ddf90989b15e409b91ef055cb02757d34987849ae6d60bef2c902bf8251ed21ab30acf39e500d1d511e90845 -92ba4eb1f796bc3d8b03515f65c045b66e2734c2da3fc507fdd9d6b5d1e19ab3893726816a32141db7a31099ca817d96 -8a98b3cf353138a1810beb60e946183803ef1d39ac4ea92f5a1e03060d35a4774a6e52b14ead54f6794d5f4022b8685c -909f8a5c13ec4a59b649ed3bee9f5d13b21d7f3e2636fd2bb3413c0646573fdf9243d63083356f12f5147545339fcd55 -9359d914d1267633141328ed0790d81c695fea3ddd2d406c0df3d81d0c64931cf316fe4d92f4353c99ff63e2aefc4e34 -b88302031681b54415fe8fbfa161c032ea345c6af63d2fb8ad97615103fd4d4281c5a9cae5b0794c4657b97571a81d3b -992c80192a519038082446b1fb947323005b275e25f2c14c33cc7269e0ec038581cc43705894f94bad62ae33a8b7f965 -a78253e3e3eece124bef84a0a8807ce76573509f6861d0b6f70d0aa35a30a123a9da5e01e84969708c40b0669eb70aa6 -8d5724de45270ca91c94792e8584e676547d7ac1ac816a6bb9982ee854eb5df071d20545cdfd3771cd40f90e5ba04c8e -825a6f586726c68d45f00ad0f5a4436523317939a47713f78fd4fe81cd74236fdac1b04ecd97c2d0267d6f4981d7beb1 -93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 -b5bfd7dd8cdeb128843bc287230af38926187075cbfbefa81009a2ce615ac53d2914e5870cb452d2afaaab24f3499f72185cbfee53492714734429b7b38608e23926c911cceceac9a36851477ba4c60b087041de621000edc98edada20c1def2 -b5337ba0ce5d37224290916e268e2060e5c14f3f9fc9e1ec3af5a958e7a0303122500ce18f1a4640bf66525bd10e763501fe986d86649d8d45143c08c3209db3411802c226e9fe9a55716ac4a0c14f9dcef9e70b2bb309553880dc5025eab3cc -b3c1dcdc1f62046c786f0b82242ef283e7ed8f5626f72542aa2c7a40f14d9094dd1ebdbd7457ffdcdac45fd7da7e16c51200b06d791e5e43e257e45efdf0bd5b06cd2333beca2a3a84354eb48662d83aef5ecf4e67658c851c10b13d8d87c874 -954d91c7688983382609fca9e211e461f488a5971fd4e40d7e2892037268eacdfd495cfa0a7ed6eb0eb11ac3ae6f651716757e7526abe1e06c64649d80996fd3105c20c4c94bc2b22d97045356fe9d791f21ea6428ac48db6f9e68e30d875280 -88a6b6bb26c51cf9812260795523973bb90ce80f6820b6c9048ab366f0fb96e48437a7f7cb62aedf64b11eb4dfefebb0147608793133d32003cb1f2dc47b13b5ff45f1bb1b2408ea45770a08dbfaec60961acb8119c47b139a13b8641e2c9487 -85cd7be9728bd925d12f47fb04b32d9fad7cab88788b559f053e69ca18e463113ecc8bbb6dbfb024835f901b3a957d3108d6770fb26d4c8be0a9a619f6e3a4bf15cbfd48e61593490885f6cee30e4300c5f9cf5e1c08e60a2d5b023ee94fcad0 -80477dba360f04399821a48ca388c0fa81102dd15687fea792ee8c1114e00d1bc4839ad37ac58900a118d863723acfbe08126ea883be87f50e4eabe3b5e72f5d9e041db8d9b186409fd4df4a7dde38c0e0a3b1ae29b098e5697e7f110b6b27e4 -b7a6aec08715a9f8672a2b8c367e407be37e59514ac19dd4f0942a68007bba3923df22da48702c63c0d6b3efd3c2d04e0fe042d8b5a54d562f9f33afc4865dcbcc16e99029e25925580e87920c399e710d438ac1ce3a6dc9b0d76c064a01f6f7 -ac1b001edcea02c8258aeffbf9203114c1c874ad88dae1184fadd7d94cd09053649efd0ca413400e6e9b5fa4eac33261000af88b6bd0d2abf877a4f0355d2fb4d6007adb181695201c5432e50b850b51b3969f893bddf82126c5a71b042b7686 -90043fda4de53fb364fab2c04be5296c215599105ecff0c12e4917c549257125775c29f2507124d15f56e30447f367db0596c33237242c02d83dfd058735f1e3c1ff99069af55773b6d51d32a68bf75763f59ec4ee7267932ae426522b8aaab6 -a8660ce853e9dc08271bf882e29cd53397d63b739584dda5263da4c7cc1878d0cf6f3e403557885f557e184700575fee016ee8542dec22c97befe1d10f414d22e84560741cdb3e74c30dda9b42eeaaf53e27822de2ee06e24e912bf764a9a533 -8fe3921a96d0d065e8aa8fce9aa42c8e1461ca0470688c137be89396dd05103606dab6cdd2a4591efd6addf72026c12e065da7be276dee27a7e30afa2bd81c18f1516e7f068f324d0bad9570b95f6bd02c727cd2343e26db0887c3e4e26dceda -8ae1ad97dcb9c192c9a3933541b40447d1dc4eebf380151440bbaae1e120cc5cdf1bcea55180b128d8e180e3af623815191d063cc0d7a47d55fb7687b9d87040bf7bc1a7546b07c61db5ccf1841372d7c2fe4a5431ffff829f3c2eb590b0b710 -8c2fa96870a88150f7876c931e2d3cc2adeaaaf5c73ef5fa1cf9dfa0991ae4819f9321af7e916e5057d87338e630a2f21242c29d76963cf26035b548d2a63d8ad7bd6efefa01c1df502cbdfdfe0334fb21ceb9f686887440f713bf17a89b8081 -b9aa98e2f02bb616e22ee5dd74c7d1049321ac9214d093a738159850a1dbcc7138cb8d26ce09d8296368fd5b291d74fa17ac7cc1b80840fdd4ee35e111501e3fa8485b508baecda7c1ab7bd703872b7d64a2a40b3210b6a70e8a6ffe0e5127e3 -9292db67f8771cdc86854a3f614a73805bf3012b48f1541e704ea4015d2b6b9c9aaed36419769c87c49f9e3165f03edb159c23b3a49c4390951f78e1d9b0ad997129b17cdb57ea1a6638794c0cca7d239f229e589c5ae4f9fe6979f7f8cba1d7 -91cd9e86550f230d128664f7312591fee6a84c34f5fc7aed557bcf986a409a6de722c4330453a305f06911d2728626e611acfdf81284f77f60a3a1595053a9479964fd713117e27c0222cc679674b03bc8001501aaf9b506196c56de29429b46 -a9516b73f605cc31b89c68b7675dc451e6364595243d235339437f556cf22d745d4250c1376182273be2d99e02c10eee047410a43eff634d051aeb784e76cb3605d8e079b9eb6ad1957dfdf77e1cd32ce4a573c9dfcc207ca65af6eb187f6c3d -a9667271f7d191935cc8ad59ef3ec50229945faea85bfdfb0d582090f524436b348aaa0183b16a6231c00332fdac2826125b8c857a2ed9ec66821cfe02b3a2279be2412441bc2e369b255eb98614e4be8490799c4df22f18d47d24ec70bba5f7 -a4371144d2aa44d70d3cb9789096d3aa411149a6f800cb46f506461ee8363c8724667974252f28aea61b6030c05930ac039c1ee64bb4bd56532a685cae182bf2ab935eee34718cffcb46cae214c77aaca11dbb1320faf23c47247db1da04d8dc -89a7eb441892260b7e81168c386899cd84ffc4a2c5cad2eae0d1ab9e8b5524662e6f660fe3f8bfe4c92f60b060811bc605b14c5631d16709266886d7885a5eb5930097127ec6fb2ebbaf2df65909cf48f253b3d5e22ae48d3e9a2fd2b01f447e -9648c42ca97665b5eccb49580d8532df05eb5a68db07f391a2340769b55119eaf4c52fe4f650c09250fa78a76c3a1e271799b8333cc2628e3d4b4a6a3e03da1f771ecf6516dd63236574a7864ff07e319a6f11f153406280d63af9e2b5713283 -9663bf6dd446ea7a90658ee458578d4196dc0b175ef7fcfa75f44d41670850774c2e46c5a6be132a2c072a3c0180a24f0305d1acac49d2d79878e5cda80c57feda3d01a6af12e78b5874e2a4b3717f11c97503b41a4474e2e95b179113726199 -b212aeb4814e0915b432711b317923ed2b09e076aaf558c3ae8ef83f9e15a83f9ea3f47805b2750ab9e8106cb4dc6ad003522c84b03dc02829978a097899c773f6fb31f7fe6b8f2d836d96580f216fec20158f1590c3e0d7850622e15194db05 -925f005059bf07e9ceccbe66c711b048e236ade775720d0fe479aebe6e23e8af281225ad18e62458dc1b03b42ad4ca290d4aa176260604a7aad0d9791337006fbdebe23746f8060d42876f45e4c83c3643931392fde1cd13ff8bddf8111ef974 -9553edb22b4330c568e156a59ef03b26f5c326424f830fe3e8c0b602f08c124730ffc40bc745bec1a22417adb22a1a960243a10565c2be3066bfdb841d1cd14c624cd06e0008f4beb83f972ce6182a303bee3fcbcabc6cfe48ec5ae4b7941bfc -935f5a404f0a78bdcce709899eda0631169b366a669e9b58eacbbd86d7b5016d044b8dfc59ce7ed8de743ae16c2343b50e2f925e88ba6319e33c3fc76b314043abad7813677b4615c8a97eb83cc79de4fedf6ccbcfa4d4cbf759a5a84e4d9742 -a5b014ab936eb4be113204490e8b61cd38d71da0dec7215125bcd131bf3ab22d0a32ce645bca93e7b3637cf0c2db3d6601a0ddd330dc46f9fae82abe864ffc12d656c88eb50c20782e5bb6f75d18760666f43943abb644b881639083e122f557 -935b7298ae52862fa22bf03bfc1795b34c70b181679ae27de08a9f5b4b884f824ef1b276b7600efa0d2f1d79e4a470d51692fd565c5cf8343dd80e5d3336968fc21c09ba9348590f6206d4424eb229e767547daefa98bc3aa9f421158dee3f2a -9830f92446e708a8f6b091cc3c38b653505414f8b6507504010a96ffda3bcf763d5331eb749301e2a1437f00e2415efb01b799ad4c03f4b02de077569626255ac1165f96ea408915d4cf7955047620da573e5c439671d1fa5c833fb11de7afe6 -840dcc44f673fff3e387af2bb41e89640f2a70bcd2b92544876daa92143f67c7512faf5f90a04b7191de01f3e2b1bde00622a20dc62ca23bbbfaa6ad220613deff43908382642d4d6a86999f662efd64b1df448b68c847cfa87630a3ffd2ec76 -92950c895ed54f7f876b2fda17ecc9c41b7accfbdd42c210cc5b475e0737a7279f558148531b5c916e310604a1de25a80940c94fe5389ae5d6a5e9c371be67bceea1877f5401725a6595bcf77ece60905151b6dfcb68b75ed2e708c73632f4fd -8010246bf8e94c25fd029b346b5fbadb404ef6f44a58fd9dd75acf62433d8cc6db66974f139a76e0c26dddc1f329a88214dbb63276516cf325c7869e855d07e0852d622c332ac55609ba1ec9258c45746a2aeb1af0800141ee011da80af175d4 -b0f1bad257ebd187bdc3f37b23f33c6a5d6a8e1f2de586080d6ada19087b0e2bf23b79c1b6da1ee82271323f5bdf3e1b018586b54a5b92ab6a1a16bb3315190a3584a05e6c37d5ca1e05d702b9869e27f513472bcdd00f4d0502a107773097da -9636d24f1ede773ce919f309448dd7ce023f424afd6b4b69cb98c2a988d849a283646dc3e469879daa1b1edae91ae41f009887518e7eb5578f88469321117303cd3ac2d7aee4d9cb5f82ab9ae3458e796dfe7c24284b05815acfcaa270ff22e2 -b373feb5d7012fd60578d7d00834c5c81df2a23d42794fed91aa9535a4771fde0341c4da882261785e0caca40bf83405143085e7f17e55b64f6c5c809680c20b050409bf3702c574769127c854d27388b144b05624a0e24a1cbcc4d08467005b -b15680648949ce69f82526e9b67d9b55ce5c537dc6ab7f3089091a9a19a6b90df7656794f6edc87fb387d21573ffc847062623685931c2790a508cbc8c6b231dd2c34f4d37d4706237b1407673605a604bcf6a50cc0b1a2db20485e22b02c17e -8817e46672d40c8f748081567b038a3165f87994788ec77ee8daea8587f5540df3422f9e120e94339be67f186f50952504cb44f61e30a5241f1827e501b2de53c4c64473bcc79ab887dd277f282fbfe47997a930dd140ac08b03efac88d81075 -a6e4ef6c1d1098f95aae119905f87eb49b909d17f9c41bcfe51127aa25fee20782ea884a7fdf7d5e9c245b5a5b32230b07e0dbf7c6743bf52ee20e2acc0b269422bd6cf3c07115df4aa85b11b2c16630a07c974492d9cdd0ec325a3fabd95044 -8634aa7c3d00e7f17150009698ce440d8e1b0f13042b624a722ace68ead870c3d2212fbee549a2c190e384d7d6ac37ce14ab962c299ea1218ef1b1489c98906c91323b94c587f1d205a6edd5e9d05b42d591c26494a6f6a029a2aadb5f8b6f67 -821a58092900bdb73decf48e13e7a5012a3f88b06288a97b855ef51306406e7d867d613d9ec738ebacfa6db344b677d21509d93f3b55c2ebf3a2f2a6356f875150554c6fff52e62e3e46f7859be971bf7dd9d5b3e1d799749c8a97c2e04325df -8dba356577a3a388f782e90edb1a7f3619759f4de314ad5d95c7cc6e197211446819c4955f99c5fc67f79450d2934e3c09adefc91b724887e005c5190362245eec48ce117d0a94d6fa6db12eda4ba8dde608fbbd0051f54dcf3bb057adfb2493 -a32a690dc95c23ed9fb46443d9b7d4c2e27053a7fcc216d2b0020a8cf279729c46114d2cda5772fd60a97016a07d6c5a0a7eb085a18307d34194596f5b541cdf01b2ceb31d62d6b55515acfd2b9eec92b27d082fbc4dc59fc63b551eccdb8468 -a040f7f4be67eaf0a1d658a3175d65df21a7dbde99bfa893469b9b43b9d150fc2e333148b1cb88cfd0447d88fa1a501d126987e9fdccb2852ecf1ba907c2ca3d6f97b055e354a9789854a64ecc8c2e928382cf09dda9abde42bbdf92280cdd96 -864baff97fa60164f91f334e0c9be00a152a416556b462f96d7c43b59fe1ebaff42f0471d0bf264976f8aa6431176eb905bd875024cf4f76c13a70bede51dc3e47e10b9d5652d30d2663b3af3f08d5d11b9709a0321aba371d2ef13174dcfcaf -95a46f32c994133ecc22db49bad2c36a281d6b574c83cfee6680b8c8100466ca034b815cfaedfbf54f4e75188e661df901abd089524e1e0eb0bf48d48caa9dd97482d2e8c1253e7e8ac250a32fd066d5b5cb08a8641bdd64ecfa48289dca83a3 -a2cce2be4d12144138cb91066e0cd0542c80b478bf467867ebef9ddaf3bd64e918294043500bf5a9f45ee089a8d6ace917108d9ce9e4f41e7e860cbce19ac52e791db3b6dde1c4b0367377b581f999f340e1d6814d724edc94cb07f9c4730774 -b145f203eee1ac0a1a1731113ffa7a8b0b694ef2312dabc4d431660f5e0645ef5838e3e624cfe1228cfa248d48b5760501f93e6ab13d3159fc241427116c4b90359599a4cb0a86d0bb9190aa7fabff482c812db966fd2ce0a1b48cb8ac8b3bca -adabe5d215c608696e03861cbd5f7401869c756b3a5aadc55f41745ad9478145d44393fec8bb6dfc4ad9236dc62b9ada0f7ca57fe2bae1b71565dbf9536d33a68b8e2090b233422313cc96afc7f1f7e0907dc7787806671541d6de8ce47c4cd0 -ae7845fa6b06db53201c1080e01e629781817f421f28956589c6df3091ec33754f8a4bd4647a6bb1c141ac22731e3c1014865d13f3ed538dcb0f7b7576435133d9d03be655f8fbb4c9f7d83e06d1210aedd45128c2b0c9bab45a9ddde1c862a5 -9159eaa826a24adfa7adf6e8d2832120ebb6eccbeb3d0459ffdc338548813a2d239d22b26451fda98cc0c204d8e1ac69150b5498e0be3045300e789bcb4e210d5cd431da4bdd915a21f407ea296c20c96608ded0b70d07188e96e6c1a7b9b86b -a9fc6281e2d54b46458ef564ffaed6944bff71e389d0acc11fa35d3fcd8e10c1066e0dde5b9b6516f691bb478e81c6b20865281104dcb640e29dc116daae2e884f1fe6730d639dbe0e19a532be4fb337bf52ae8408446deb393d224eee7cfa50 -84291a42f991bfb36358eedead3699d9176a38f6f63757742fdbb7f631f2c70178b1aedef4912fed7b6cf27e88ddc7eb0e2a6aa4b999f3eb4b662b93f386c8d78e9ac9929e21f4c5e63b12991fcde93aa64a735b75b535e730ff8dd2abb16e04 -a1b7fcacae181495d91765dfddf26581e8e39421579c9cbd0dd27a40ea4c54af3444a36bf85a11dda2114246eaddbdd619397424bb1eb41b5a15004b902a590ede5742cd850cf312555be24d2df8becf48f5afba5a8cd087cb7be0a521728386 -92feaaf540dbd84719a4889a87cdd125b7e995a6782911931fef26da9afcfbe6f86aaf5328fe1f77631491ce6239c5470f44c7791506c6ef1626803a5794e76d2be0af92f7052c29ac6264b7b9b51f267ad820afc6f881460521428496c6a5f1 -a525c925bfae1b89320a5054acc1fa11820f73d0cf28d273092b305467b2831fab53b6daf75fb926f332782d50e2522a19edcd85be5eb72f1497193c952d8cd0bcc5d43b39363b206eae4cb1e61668bde28a3fb2fc1e0d3d113f6dfadb799717 -98752bb6f5a44213f40eda6aa4ff124057c1b13b6529ab42fe575b9afa66e59b9c0ed563fb20dff62130c436c3e905ee17dd8433ba02c445b1d67182ab6504a90bbe12c26a754bbf734665c622f76c62fe2e11dd43ce04fd2b91a8463679058b -a9aa9a84729f7c44219ff9e00e651e50ddea3735ef2a73fdf8ed8cd271961d8ed7af5cd724b713a89a097a3fe65a3c0202f69458a8b4c157c62a85668b12fc0d3957774bc9b35f86c184dd03bfefd5c325da717d74192cc9751c2073fe9d170e -b221c1fd335a4362eff504cd95145f122bf93ea02ae162a3fb39c75583fc13a932d26050e164da97cff3e91f9a7f6ff80302c19dd1916f24acf6b93b62f36e9665a8785413b0c7d930c7f1668549910f849bca319b00e59dd01e5dec8d2edacc -a71e2b1e0b16d754b848f05eda90f67bedab37709550171551050c94efba0bfc282f72aeaaa1f0330041461f5e6aa4d11537237e955e1609a469d38ed17f5c2a35a1752f546db89bfeff9eab78ec944266f1cb94c1db3334ab48df716ce408ef -b990ae72768779ba0b2e66df4dd29b3dbd00f901c23b2b4a53419226ef9232acedeb498b0d0687c463e3f1eead58b20b09efcefa566fbfdfe1c6e48d32367936142d0a734143e5e63cdf86be7457723535b787a9cfcfa32fe1d61ad5a2617220 -8d27e7fbff77d5b9b9bbc864d5231fecf817238a6433db668d5a62a2c1ee1e5694fdd90c3293c06cc0cb15f7cbeab44d0d42be632cb9ff41fc3f6628b4b62897797d7b56126d65b694dcf3e298e3561ac8813fbd7296593ced33850426df42db -a92039a08b5502d5b211a7744099c9f93fa8c90cedcb1d05e92f01886219dd464eb5fb0337496ad96ed09c987da4e5f019035c5b01cc09b2a18b8a8dd419bc5895388a07e26958f6bd26751929c25f89b8eb4a299d822e2d26fec9ef350e0d3c -92dcc5a1c8c3e1b28b1524e3dd6dbecd63017c9201da9dbe077f1b82adc08c50169f56fc7b5a3b28ec6b89254de3e2fd12838a761053437883c3e01ba616670cea843754548ef84bcc397de2369adcca2ab54cd73c55dc68d87aec3fc2fe4f10 -97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb -ad3eb50121139aa34db1d545093ac9374ab7bca2c0f3bf28e27c8dcd8fc7cb42d25926fc0c97b336e9f0fb35e5a04c81 -8029c8ce0d2dce761a7f29c2df2290850c85bdfaec2955626d7acc8864aeb01fe16c9e156863dc63b6c22553910e27c1 -b1386c995d3101d10639e49b9e5d39b9a280dcf0f135c2e6c6928bb3ab8309a9da7178f33925768c324f11c3762cfdd5 -9596d929610e6d2ed3502b1bb0f1ea010f6b6605c95d4859f5e53e09fa68dc71dfd5874905447b5ec6cd156a76d6b6e8 -851e3c3d4b5b7cdbba25d72abf9812cf3d7c5a9dbdec42b6635e2add706cbeea18f985afe5247459f6c908620322f434 -b10f4cf8ec6e02491bbe6d9084d88c16306fdaf399fef3cd1453f58a4f7633f80dc60b100f9236c3103eaf727468374f -ade11ec630127e04d17e70db0237d55f2ff2a2094881a483797e8cddb98b622245e1f608e5dcd1172b9870e733b4a32f -af58c8a2f58f904ce20db81005331bf2d251e227e7d1bef575d691bdca842e6233eb2e26c2e116a61a78594772b38d25 -b3c1313c31ec82da5a7a09e9cf6656ca598c243345fe8d4828e520ade91787ffb8b9867db789b34ad67cef47b26ff86d -a8ed8a235355948e0b04be080b7b3e145293accefb4704d1da9050796b2f6870516c1ebf77ae6a65359edcfd016c0f36 -80e792d5ba24b8058f6d7291a2ec5cb68aab1e16e96d793128e86815631baf42c56b6205c19e25ce9727bd1fd6f9defb -816288c5d726b094e3fdf95cb8882f442c4d9d1101b92c7938a7dfd49bc50636d73ea1b05f75eb731c908c8fd8dee717 -ae009128d128ba2e1519bfa7a0c01ed494a7d461c3aba60f8a301701fed61fe4e31d6c79ce189542ae51df91e73ce1b3 -96a866d60a9007d05825c332476a83e869e15b11d7257172a67690ea9bd3efea44bf9c8d42191454eb04fcf110b16396 -8b250a2a06419adb9b611e89f7f8f2990aa301949b533ad3bf17c4a61ab5f5be0b1d5e2b571864d13f1bb75805c7795d -8450f49facf2e620fa45ee90e1801178842d927a2a25fc6ed7ba99a4eec7ae40eebfee41028eaa84f107f4a777694976 -91049080cf659c0985a22d1366e59191bb89663f922e8168b9b7d85c8a73d74a6d9dceefd855d3d858b493670c750581 -a1e167aeb2008087f3195926f1985c0a459d6ec57237255b1473a96de4e2c1cf766127c862c7dc853a6909e67cb06cf7 -b667c0d4e26e20698b07567358625d5f003839c92de8088e12dbd74a6f6a3156b4ea8d252c9ad62af5f6c4fec1cf6cc7 -8e4b5e304c0b1b161ae3e4b68b5e3ac66c42acd7c1ee2458044f6527c508a93995e50894d72d57c1350f91afe72775ff -8c642640aa7915421cdc21fd639f88a42052b1cfa358ff7702e60793a92b7b5926dae15a0c8f8f59cd3013f01c159ba3 -a356f35e713cfc283056bf539de54a21731e61efb4c47319f20de4a4b723d76a33b65f4a67d298b9ec5c2a1579418657 -93ce204146ce95f484dc79c27919a16c9e3fc14a9111c6c63d44491158d5838117d20851cc3227a5e8ba6ccf79e77f39 -b585664cbb9a84b52f89114e1cf0cf1171bea78a136dc1404ac88a11210b2debc3b7a55e702da93ff629095c134a295e -b6dfd444ec7fdceb14c6328f26ca12c3f9fc4327d8d8c68948e92e7e61262b82d833a65a9e3af6353ffa832b6da25705 -b4d4b8eb9ecfffe3f0d48fb4149c7b31aec1da7041ec03bd0750c52a2a7cbc3a7cfbf09d5bfdc56e3860826a62d0bb91 -a4e248e3d61db52da9683fef188579c470d65e2df9064726847b1599fc774049ffdc6ef2ae578d5ed7874f1298ecdf69 -a68a0fffc2e37d3183feb01b42234c0f4e510f9dc29d09c571e6da00fecad9da224cd0f31550070148667e226c4ca413 -86adda2ffecb77236c18005051f31f9657a0d50fef2a1175dfda32e74d5d53df825c10f289eb0ad39df0c64fc9bc7729 -998266d5c9c3764ed97d66fa9ed176af043999652bae19f0657c8328629d30af453230e3681c5a38e2f01e389ed8d825 -a05261554d3c620af0c914cf27ab98f5d3593c33ab313c198e0c40d6c72022eb5943778cd4f73e9fe8383392a7004976 -ad243fb3631bf90fedb9d679fd71fc0cf06bda028591ded2bd4c634ea7b3c2bd22eca2ab318fcdaa6c2cda1e63e1c57b -89b9859a04f903c95e97fb2951f01cc6418a2505eee0b5bc7266b4d33e01b69b9fe7dc56fa9ebb5856095be0925a422d -a68d118343a5bbfbbab95ff9bfe53aeb7fdbaf16db983e6f4456366df2aa01fbdb6ee9901cb102fc7d2bd099be2f1f3e -b49301f25d5a9dd2ec60ddb0b4b477291958487efea9e54dc0e4ef388f03b8bbadd13259d191f7a0b7513876767d8282 -8b93df7fb4513f67749905fd43db78f7026589b704ebb9ea3255d0ad6415437799f40f02e07efccda1e6fd5e8cd0a721 -ad88769ace96455da37c3c9019a9f523c694643be3f6b37b1e9dcc5053d1fe8e463abebdb1b3ef2f2fb801528a01c47c -80f0eb5dcbfaaf421bf59a8b9bd5245c4823c94510093e23e0b0534647fb5525a25ea3aeea0a927a1ee20c057f2c9234 -b10ad82ea6a5aeabe345d00eb17910d6942b6862f7f3773c7d321194e67c9cced0b3310425662606634dcd7f8b976c04 -82f6fd91f87822f6cc977808eeac77889f4a32fb0d618e784b2331263d0ffa820b3f70b069d32e0319c9e033ab75d3b4 -9436d3dc6b5e25b1f695f8c6c1c553dab312ccace4dac3afddc141d3506467cd50cb04a49ea96ea7f5a8a7b0fc65ef37 -8e0a9491651d52be8ebf4315fbbb410272f9a74b965d33b79ff1b9e1be3be59e43d9566773560e43280549c348e48f01 -8809137e5d3a22400d6e645a9bd84e21c492371736c7e62c51cef50fee3aa7f2405724367a83fd051ff702d971167f67 -b536a24f31a346de7f9863fc351fa602158404d2f94747eebe43abf1f21bf8f95a64146c02a4bec27b503f546789a388 -b5cdf5a04fc12a0e0ef7545830061dff7fd8abea46e48fbe6235109e6c36ee6bffcb9529e2f3d0d701cf58bbfb6a4197 -ab15377525753467d042b7931f66f862cbbb77464212c9aa72d4e5c04375ef55f619b3a446091c1ba1a3b5d9f05e538f -905a75b943ad017ff78ea6ddd1d28a45c7273ee1c2e5e3353685813793ead3370c09cabd903fcab9d8b1c6961372d486 -8147df4324faddc02fb0896367a7647b719b6499a361aecfdd3a34296fa6768ad31c34f9e873fd1e683386c44651883e -ac91d08570dd91f89d2e01dca67cdc83b640e20f073ea9f0734759c92182bb66c5d645f15ebd91ed705b66486ed2088d -ac6295ef2513bbea7ef4cdcf37d280300c34e63c4b9704663d55891a61bf5c91b04cc1d202a3a0a7c4520c30edc277c7 -b604be776a012095c0d4ebc77797dd8dec62a54c0559fb2185d7bac6b50d4e5fd471ac2d7f4523206d5d8178eabd9a87 -80ead68def272ce3f57951145e71ed6dc26da98e5825ef439af577c0c5de766d4e39207f205d5d21db903d89f37bbb02 -9950b4a830388c897158c7fe3921e2fe24beedc7c84e2024e8b92b9775f8f99593b54a86b8870ec5087734295ba06032 -b89ba714adabf94e658a7d14ac8fc197376a416841c2a80e1a6dde4f438d5f747d1fb90b39e8ea435c59d6ecda13dea1 -b0c78e7cc60bd05be46d48fbb0421a678c7f14b8d93730deb66fbe1647613b2c62b5075126d917047820c57fc3509cb9 -a860c4acc5444e9ae987e8c93cb9a5f17d954d63c060cc616f724e26bc73d2c54cd36e0492d1fde173847278e55942ba -8fb8269c9d5c15428e8d45da1251e4c4a4b600d47da0caea29fef246854d8fb6acae86a8e6440d0c429d8dd9c2dfee0c -96c5d8eb6fd5c525b348ee4335d200139e437e4be83690af0f35b7f336a7cda8c6d2958647988b84da9f2dd7bbb7710b -a7f62141c4346cc14e9823dc38ac7d587b0427022afc1498d12ee2c43f6ac3a82167057e670dd524b74137f8c3ceb56d -956aac50d06b46a3e94397f163f593f5010d366aa2d816c2205c7d0f47f90cf0f36c169e964f9bcf698d49182d47d91f -b812899bcdc0e70d79ca729cb01104bf60e1357b9085a10f64f3ba9865d57e9abd0a505a502d4de07afb46f4d266be2f -abce02c7e1372e25d40944dc9ece2904a8f59c8854c5f2875fe63ace8ce37d97881f4f9ab4f7bad070ec8e0daee58d3f -8fb13c515b2d6abb4e14ed753fad5cc36c3631dfe21a23d0f603aad719423dd5423157eefcbd9a9c6074e155b79eb38d -a9ef67304dc297ab5af778cf8afa849eeac27db4b6978963e97b95ef7a8d3264d0d07775f728c298a2b6daed2ecf5053 -a9b975520adb066e2ff2a4cde53284c23bc84261a22dc43b1634d99eff8e7892e46bb6e6da7319c9e72788aa9ea7a1ea -a6eaea4ab4206294474d9b956d9d3188d558a5633de2bd05df0d3bac03dbcbe4ed85406349c1d2e660b77c6da1f5bf8c -af4a19f77290dddee762e1e0d4bc9945aacea3f75756ae46cd3e58a8f74d1b5db73e4834687946b0f39191e32f2fed0c -aafa6523f58f1a4cabc924c86d842816d606afeea21fa4b2b8b9573425810fdcc41c98888318e868f9c05e2be12178a3 -8ef38fba0a3fa4ebe985239c8b759c22aaef0c57e6f39050a651c869487803b0d1e389c3d958fb5a7f37740f050ac69e -b07dfc9f85913c608ca7596a2e361f05e4853fad00e796fd492d247de6414892ce160f627669b1ba933b6ad726415d4e -94da679ad1d78b2bff5283c938f17b2a7d6e9cbcdf59d340e6dfb652951c7a9e852ac0590f99cfee9631b9410f6f00ea -98a907c9c021a5b034d3720197c160a82c4b7146cb73d48efeed99b9d0c6b831812cf80ac7e19e85a676a8cd3ead72de -adb746595466a12929019d0048cea33236b05c1229d2eba73b259a18a786f2bc3f05fc0598d8ce253cecb80bdf679aaf -a2fbac016996d68f9027a157b0a3f6a336144a798d6113adfcda3a5d05b62c31f108f112aa915906aef22b7f83b9228b -81841dea1904406d1b6fa49b4b3f7f6cb40b7646cf44d36c9fa07e3dee29f8e47324b40d8356ddf653109673c3374e9b -a3edbb8aac5e60c775775cbdb19067341b2e2530de48738e84c2c07151241ee31f0d8333bf20c2bc9dcb7b2e638a6b5e -b8aa6890e22964828787ce86460d3a32f12a655bb5c28de500f2fcf6b61e3334640ec6ba96029a4912af0d18df4b4139 -8ca43169f04243ad0fdb0152de17c60d9e31ee0ab520970fccd98590e05508821a183b4b367967e60d53c2c826ec5dbd -b179fffd9df8c00486c5a8b9327d599f5a11745ef564f06e126849b06fe2f99273c81f65bc941efb0debaadfecbfec1c -acf068f1c2b1926279cc82750ce21b0d6b0bfd0406f0d8bbfa959bd83935932957c7f6b8de318315bf0b75f6ee41a0f2 -b97831da260919c856e9f71a41687f5979bc16f8a53b1037285b4a2f9ce93af5cfe70bf0ad484744827fb55c847b58eb -aff50b0bd907383b0c241727af364fe084d021221bfb1b09fb6c1a7752eeba45d662493d590f1f182764b90b25f17906 -aeeef044c14e3ad41e1235c9e816e1eb49087fd3abe877b89b3bade74459186126e160bb569bcd77779e701b19b5f71a -8483deb2b7001ca7c438fcdca8ca6aba96c9cbc4becfd9b16a6062705eae270011bcaedcae69bb54630d8c78129e57c7 -aeee8d24be4ac0d9784c029e239fb5e64316ce29b88f47394cfaaa8bb966a72061bff72f99d02dc51c9705854686e77f -90ae09525a16bb2422169e15d6831c87968a14ebc0d1d27e11a759839c73c655b9d33ee5b12f275d6f440688146fbd2f -a3a41fc7fefef101422465e506bea7f3ff23c26fe35f5732b86f5f2471fb93b37ebc339f84c6be1e8d22abc812c2e212 -86f4b5293e8aea4af1f1fb05dcf99714cb3aff1cfc849b1bb73524061c921c9da9ad92579a852e1889da29d952f02fe5 -8932ef39d4050a1e9dc0fd8afeaf159472d71c5c27f458c69d2730836606ea56e19c8c4febf2535f930d3260e9bc7637 -86307b9f3696bb21c20e4558e30310389e7367803c353d437e9b696039a0ff054d9a4953b75237ab1d1dd6f71118c189 -96e57730e683ef5b550c91de18b19ac73879f3e26234297db68d28747ed0953beb0f3913cfb720c602720bf9330685d8 -b04a19ee70123782e47b238abde55baf60ac0c66292a998af0d14afc8bbeb1134e557b94cd17a020084631c09a0d3c02 -829abc8718be8139569fcb2c398962f38f4201114d30e2b2fb23566f8a27a5c380f5605cec543415202a12ed859e33f6 -a0744fa488c8fa92a722c5fc4ef5a47dfe824eccd87d26c8bab9c174cbb151d44b1b29082c48652f03d3177e5ec86001 -81d4035ae9fd28bdcd78b135cb54955d3b685a527319df6ee7e904b8e6d796f5f5a5f5035ee1de750c4cb6050e452b9e -b205e8c2ec24d7104fa0106c09ad34b5a912c1adef553fb718838dd627355993c2ec01055c11d00b2c75b68e9516d44b -b12d09da7968fa7394e449624fc7174d1d76c069ccb03e140d4d87a2d3f6d1f7b9cfc930f0c80becc673406ebe63f08e -b23752c158695da85048fdf38b395681cc0e8998630af8a9ed41efbda08c9964c2dc8ae6e53377264be4467d702c0de4 -b0d84582fd73628d96b8c1ec96197697c41a963542451a2ade0890af0d33c7161d0f18e1a1ce2c168ca2dc1e9119d55e -8b877e618b469aa187632e410b125d2999d5738fd66d482000706b51fd904a0c7e7daa8c9b729fa33817bbc4154cba2a -b1cfc8a7551b601723b937d497d01dec3ee7614c2bf13d430b1058d5ebc1406045009ff02c2ac15bf8cf16f860193d1e -b6d9da84f97b21e13175bbb0b5cc8e79e88b470c87a3e115726c1bd98e0288526c58f3faaa8aa170ace0cd6a60852525 -ad2e773c2d527671ca5fab7085dde4da31cd35f45d4315dd95d8893ff5fb900494dca08eccfc1a2fc7bf7c7fd2fcab97 -8d5a79b34aeb761d4a0c73f09f02e9548e6d382c33ee6887a759ab05762b490b8a549ef2933c7e3a46415c154c0221c0 -b6f2cbe81bd0a7298403be392f8456bed30aed7ef30216959357698f789affd2942ae5fbaf3f48ecebeb7c273b20cb57 -b5b6c45d99cea7ce6a1dc134aff4a8f630f299b42bd59592a7592345f8cd35bcbee944e61b0723de732fcad6e4425b63 -8077d64dfcb2418974e956ea6dbf8a4c05b25d2a025333ad7e2a379f1976dc036771403383a51bfa3476c9c619ef8bef -ad2e0a9d479c77a5fb73b3613a177fdaad50dcb50fed50e756ba18164c153af30b07fb2565e80ff7469f1b0338b7b5de -81017d1d80a6b6df4e99d0d7f85a8180b5523e8fa2ea2672fddff604933f8a113cab27fce098dcb454d7d1f7ed266e04 -852355479d68e76c7febf6dfe2ef8e80d575c0d3bd52c983803592021cfa898c571c0b884412c21e66f0dbfe03167b53 -98e1bf8ad48421467c93b9f72b47dded7c41b4fcd36ea55ca43ab24b0d0b876f5a731f422579b7167c7138fad2121266 -803369314abd5422019ed4b0ef652b4dbe97ef5a87b0ea373eec9628b64a12120b2c3d4eb53db405131ff786d14c7ac6 -adf2613fc34f73e1160975c140e925ed84d254e03cc3bc7fc1d19957b499c9ba9d9e4c1639981b594a7095c0a52c6757 -a2f6a68efdff6e4173c00692abcfdfcdaf6f8b62369afad3dafaae4f2f38c4860780b4624d185e20e4f4498b75b5fe94 -8b1658aa0e119fb8401d486ed08d60240d26a8623ef9788e3b45ad09ae31259395b021bd16be395139cbb7149714e764 -a7dd8bf21121285e00672ee8bb84e0cb39b2496fb53a26e35dfbca7f2b04e9a9ff9db15f53fe63fcbeafeb2deeaf2ca4 -b6d8d709e44bc18f3b41d69608edce60c02bcba48d3b7e2fd420842657f0665a7343246dea149a25e8f3416284abae66 -aaf744ca5e9bcb63e3e2939b7a1e96e4a93c88c76bec0cf4294dd7db95cdd3f6a7d92196e352d08680e2328bc4592899 -84434b015a7c398d35f1ec71fce455d62ba4ed4f62da042ec31bb2b4db47073314354cd50bc322297a1cfe35138bf490 -8d70b3a3cd9d5dfefdacfa418c0b775a112a47ce538d33a560a519660009c3f141fd6221c18539129e9c0acdaceeeb80 -b8c6903412a800ec78a4c15f31c24385a267b0c0ece32fd31bbbb557fd70c3b2d60d8fc0f90fbd70f43baa1928ea30ba -8e391dd445ea06cabb433f057853f8159511b2f9bef41aed9ccd14e0a6fcd912bbaebd38fd5fb736cfde0fa34b7a4874 -a40cd988f70613df32babbd1bbc2f1b29ff1ab0147b01161555a81d56c9621657999bcdb1df38485f687afc51d5d0f23 -b6a008b4426b3d7b28ae04eee4698fc8ef6a35d89008ef5394da39ce582ce1a45dcfae9a33b90f6fa4237f3667803873 -8987280debfb175c3b44a2f152ea82548e4f680966f1fcbee9bf7d714e31bf8080c33f52705ef3aeee70544b22516aba -a78a51a2c11eea7680a5a0ae417a2981f8c69c396e06da621eadd7510a3664ade49d065617bec67b3de779548a4f4509 -a4d9163f0a1bc048385e94d5e0bcafeee1b18f28eb23505623b9e8ef16f3df76408254dfbe790e45f2884198060d388d -83dcae2568a0c518793c0f6e38b42f9ceb50673d100b556a17ec8bd9faeec84afe50b8d72422c6b2356959667bb8e2de -874731941be4474b4576226e5906b5dee89fc9b56a9870dcc7289c1a7d494d345ba6aba31f7546a16f9963283c05f744 -82c1cfab1f501189ac20147fc4631075dbf1abf9125b7d42fcb4f31cf73f3d6461b1bd08fdf6e45cc54bc08a7d5d51d1 -b978228286f5d4a10ce027b6bea3021affcaa805340ca4b5192c69e8c56db59f48e4a14a284ec015f53baf97389f62b2 -af125f4fdccd1c1b64fdffecb5ec7cf8c7392bbe476e1b89a5b5329c5ba4a526e58c11e72ab9de8a38d60af648d75adc -8411a41ec14295acab0d36389013535a80dfff6e024bffeb32fb3070762f61256419e8c51b2ad6de9dbe4f1e8e286912 -8ea67a91112a41f9c65515cd496f4b0cdefa1400fc06568eef000c9eae6dc250fb7622eb3f2deca10b37287cd96fa463 -8da99b6c55c31dee6a49aabb54da249d348a31d4416201a10c45a3b04b11e99d4ae9813632f0ee36c523b5cca62f6f49 -8b44656341e039e2bd83a19c3bb9a88f6209482e274f8cd4f8557b728e5948dd80b5745f621b96f4562928689314e8c2 -a02d424a615ba0dce8ed91f477e79852215a3a39d025059826fa278e7eebef19824b2a2844f5b3865a0f471b609a23f5 -a1f115cebc3fff3bcf233da27cef19eae791660f155d088003460f75567a550bef0722885010ddc384acdeac635939dc -b61a55ce9d143c17876776e064b58a10baf0ba13553c785c1e47f57b5f94c0cda8bc89d43d73386e57816c15b61a8ec8 -b4073f47041e20a8e548c7fb00e07ba3b9056c34eb4ab63bb0e7b48f8e338e8b56a17611a1b5f4c03b352450b86f1d69 -a7b1a07b213205b682fc5b6acb7e76fdf97b280c26621d8f3b76b7c1deb3511957da33a4e358c8e8f3d98b2a8855d67e -b797e67c2670fbd9844e8a68c585f404b035dc14bd4ec75c3f95f932c777f9db5d5f5df7629164af488fc1213035cc5f -99618200797b945f595794d6468e5c618649554ad9ba896330f1cc844090eb956ae9fc23132912f9047085c5f0c3bf7b -81194aa1319abf534cb3927af9adfb178a99d0e3e8c99ab1105f1d3b4fed40ec2971caf1d6647acb0c8d681eca53097b -80673f18e4978dbc226a6cd4b128a1259d9a7f833879c6e2fbe24d69fef2c3c23a51a4f3e8d88fa4533434bbb0723661 -8125bf6c7dbb2fb63aaa3f53283559f172c788223674adbeb6d5bd17cfe888e6b87a79aec774917f20ce911c1f85f8e7 -884bcdb1878b14fc38adc9fb8b4dd0b3afde404fbeb664f26ddfebc81736018551f23e75ce4cfe4865f610bcd454fbd7 -aec65c8d4be8316e98aa54888af01bc6703a0c5d04b69756ff39a0a947b66817ec59d76afe9f61a25749b5e890f03e02 -aa457aaa1b014a4c5a8992847a187a23321bb43452c98745987d038e3b04046102ae859b7a8e980eea978a39d76a88ef -a9832ee63b08e19123f719bfe2fe742125f32463efa966c7709a98ebfc65277670e9ea1fa2d2d78b96bdc7523b0c4c3e -a87b6b1b7858f96d55064274f29fbde56067064962cf3c3e2ba3110b22ea633bc037a74d23543ce3307a46208855d74f -897cbe4ab68a753020fec732dfcc052c7ed9905342b5a6fe0aa25c631f9ad9b659e0ee75d46f0df6507b6720675ee28c -97c3b5f0d54c1fc45e79445c3ff30458959e406a069f5bbf7979d684195b4fa0406b87c1c008f4075bc9e602ed863152 -921e65d582ea9322ddfad1c855331c3cac81f53c700b96db5305a643c084eb6793094e07944bfd41dc02c3b3cf671530 -8f23ef1aca02a260a3b65d25b110f28d3bafca44727448c8f2d03c5e77eda620c1721b06681bd816ee6027664d76352a -946a89b132ec0795aea9ff9dde7b77e7feafffe6e4a2f093042a7e6c71cd6ab87ce0ca914a1b5fabad4e1f96a795f163 -a01e2de9db33df6511172123ad6f7c64074237471df646b32dd9aff8c15278e2723108e4facaedca97e9f49503f8c792 -99dcdcde45b2ea3f15279936feede5f7d3b63ca4972f335b0559c2fa6f9faabd8127aa892a36deb114357ca906553ed8 -a3f8af37bfcf66b04d1896a4bd5d343f4733d4c3305369ac7e75a08f20f2004c10c642d2c7577f4e5c4d1f2cd851ac3b -b7294d15a3d674a56099f97a1adc9e82c15e90832eaf1722df110fc2abc8634c51515e5ad8522015498a3753b1fa8c49 -b4f27f5062ba7a04ea0048b3025b5e3d5b5d319a9e80310c808a5fb4e8e77b38c10a0f3172cb805cadbcc8bc66d36ec7 -aefe5decee0ae2dc372cc6cf4217daf97c4c908d145f100f0daf1ccdfdf641c78432c2e473e7e4b77dcdf2d4c2bb05f0 -acc84af7648a535ffd218c0cc95c8f7b092418c548815f1bafc286b1fe14f6ccb51b2044db3bff864d0bb70e88604084 -84d8e3dac0df6a22beb03742e1d4af684f139f07e2ea0f7fb27fc2d7d4f1e89b5e89f71af32ff115ed5e6092133535f0 -8ada001e1a03a823c4c056f636e77adc0f9dc08689d28de0d99e0feecab5db13abf37b41ec268dbdb42c75419a046c68 -87dac6c798d1744dff81d8bc3e0e04f3c9bf260e811685ddb9a9a8d6eda73927439b344f9a818d2103fad633de5a4a17 -ad9929a7d8a7d5d5954e48281a87e5c84f67e19110d73296b9989a09c76767a57a8115629239ffb4d99dfdf9c52ef6d9 -81ac7cbeef8ec35a5c3b61cc887080c29e6cd3e08af37e45830d17400dbacfb374dd07bf370b979828c3875b2027d5c6 -97f92c9182953b7e10f7a1bbb6b5b5c40b8275eb5a6eec1e29874c4712814749aa8c409651380216e1ff01d7b8511041 -a09794d0bbe7db013045d3fd857c1544fe6231d21afa3495fa300371f6301a3a0f4b8ea175b281503dd06078ff371ae4 -839bb58d320aa08116dd387a57a2b9bd9efc89c4cdfd82d0e47a00cabe644631d09be5436bd485df3b61b75ddf81a3ef -b1cdaa344f783757e8b9c1f84421da3c5be4c69f019a8fd4c1aa5bf1a63e8970c99e35c22cf3b48a0e6738bc6ba7ce8d -92af68e3216c78998208fb24b5ba0e645d0d3f5e28222b805668d7e9cdd6c033d3b22fd6df4c2d745d7f910d133cd226 -87640a4ea4e605e2204e5232b29a6c1c31152d83547eef14122cb76a0da52b8653801af48455a3ed713b9dcfee7b1ef1 -8147e5bf0c8f4731155ca0517ef3fae5a32b4d5d2d98ed0007b23893d8dbb7f8a1199c50c1750c2fa7c9cebe594b1bb0 -a76b4473c63c3ab6103c729afd2482822e4150f3155af39983b0ff0766c71cb622455ce6304e23853661eaa322219d18 -b3e2f05ca551bc3adec0067e4034aaffd72e0b64ac18ae25452c996927976c6727966e26d213b032521889be2170800d -a8414cd14cb3be658e9e0004ce511ef7063439b1cbc3166a11de030613fde4b59caad4e91d426927863c55382afbf476 -b2f0f8ab99f4d0ea785ac84fdbc00b20217b1df59b30b51d9d209d489d53b69dd5d82cdacc16fd1dd15c3a4001595f50 -8b2025d5fd658c9bbed619f3e3f6ac8efe7aeff8aa9401bd66a7ceb0062c44b353608ca073f95be99204f0a913bb77eb -94a46bc5a87291b42024b2137e623c70115b9c6b196604106bfbfa20f3f56ac7779763f56b580190d3cb2f1c648cada1 -aca9355545118d0769cacf69c4b23d6d68d229cd8f68f1bc0c847c05569c5af6bbbd8c4dceb637b4a6b3b5c83841bf5e -b0731992cab87c7116406b283a84707a34838bfa3284b0f6082dfabeaf41c5ac2b0ddc1b420547a1b0955aee92de2dc0 -b671f77588c0f69f6830a5b28e7d07ed161b81fa9791bb3a24aae6638e3aa5e186df74978a82549c370c18ebee04d4f0 -b5621ed841780f3e6681d880a76cf519cdd20d35197b112eeaa686764d57b5dfa78ffe1a294b6bc76b6e3949cd2a2369 -afeba2524659d00caecf089645611553187a6ed7102050f6dd20f5a19bed08ac7065912d88371ee06242897d58d652a4 -b78bfb83d44ced14a20135804aba3f00128c3ce1f302e95567ce4097b0d973414153fb305b9f156882a5a0554bf25973 -98510aede95d26b1adf214053eae051ffaf24894e2fa37961a91d0ff5392dd09388196648d95b73e90bd88f2587cc4bf -b35c682d49c295946b9f120fbc47b95abd9ee86d294abb003a92139fb825b509209562575015856a270eb3eea86397a7 -b9641bf685571dd9c478dd2033a1f1b11cd3a662b26502c78595863b8e536a189674a9a85f7a253453ebfd1b99fbd841 -b2ad37036a59b1c9b8457972665720a6868422ed8157b6810a9c0783006103be34ab732d7aeb8629653edd18fd0f1717 -af0920cff05179a3896ea6ea322c39adf91ada5bc40fe3f6fb1b1b4e121e907c904bbaa8ca00468b3749f3da144d71f3 -8e269672818ef1e2f9e0c8aa65c84442fcd9151d74bb8e870cee8c0e3fe24526e1a5388b430cef47b67f79b4e4056bcc -aa29a16fe00ea3d143b1032b1dd26b8ce638f37f95c085c7e777e8e2784bd724bd5c38b1583c61a6ec7c451dd78fd3fb -87452b7435911cc5f513b0c81b15aa04972ecbe3d7bbd0a5d676c96a8a311301c0e07fac925c53a350b46fbd3d4d0fc1 -869a81c351096f47748e41566ae7b77a454b1cdfaa41d34a5742f80df38fbf5cbb08924b6fdff58e3b18f05c62bbbbb1 -8b7bc1b0486300981147a40a449ada9a41afc06d735cce8bf0fab3ee94ba2e2ea57b1397e3cd31bc295352beb8334ef7 -93e93fc41adb2df279d95654921b4c2edf0d293dab58d0afefb221f777349ef88d0985b3447e3b935954a81f1580a92c -970fa7cdca8324faf3e62348bb50d78f580b4f43f2e1c11bd8382d48d0074a3c55c6407203a0c9cb1c5f2163ba421ef4 -924983929e608d27e4a36d4ed919297869e3c64de51aca794d32d6e90aea546bf898d98ceca28a0b2187734821b78504 -8d395332529c703d943d68415d443332b5c1342ca9d9a59bfa8bd4ab63e93358c4b0dde6ce1f2e8ea9dc8f52ad7ebd95 -80200dda853e588256599e7f905add5d5ee7c74272780317694fbae39318ae9be05d5bcd7b20cf460069743f3d4ef240 -a287d51d6359c9ef7c7ac1b20e479ce7d0146dba5606397bd04b7a622cec642508d5b45d51b31de71f9763595b6ac88e -a320396c075175d6599225cf2e1de8c7cab549f6316c07feb0f6eaa21f06b2dd29ab14fbdf2af4543b4890ec0fd08a4d -b1e9fe230418d20368691058adcbbe30011bab3000422f0371015ff8bd09c60fb5fa85d18550d35b1c900977ca48f58b -9718fc26a51783b971744933f20490e9b5cd9162f86b84788c4c5217f5409e37b5a39d628b18e5b35a757acf67596321 -a0cf81fdb161f4f1b419c5e4caa36d4bdca2325f0cd25b119a30178016f171bd6fb88403e4e3aec026c4089f180d540e -8ab1e36bd04625ee794ef04c4dcb8e004d61aceb2b62438377f49ad95dcf025ba25eb799280004941e555bf7172af6fe -9257b9e3d14d37fc7efae49b0c68d36eaac546035f4a2654d566b3ce1b2c4564cbb03dc8ec66efceb768559a8a507a18 -945d1123b839637ab5154a1972c3c83a0ff34a3b1a3465de6ef0416b1950f649869a3ef88d7f1036648ee385265ce2df -81449639d708860fc0229c94f754f7262e8a3c7f67960ff12dfd15df95f57a9ffcee2013e81978b7703dd42bd5d0816f -a865481deaae5a690fd53892791e5fa729db283b75a525a11cdfee1ce17e8e7f0b449d25f20b3c1b43da128dbdf98a8b -98766812a65fcd25b853546e3bba618a3edc9fd61510e4f8ab60c038a7fa50d197abeec8776109df0f2119be9445ad00 -b1b8dd5379d903dc41d74e999b1ab693607a0d2905692f4fb96adf08f738e5d31f9d00df28ccb8b5856145ca552c3e3c -99d20be7b511bec78a8ed03c207aa4aa9097ba39d85e18f1b8d52f65431ab7e9a773c7b9ac3e8d8b25458bc91bd00703 -b1b7c3563fe8cb33c7d3e0b89d00bdd13e86452ff507c2e69db7b3af06f247f139155396e9b0278753310dc63940a10b -b3dc9c08451b1de7c9969b1e47574bffff50490f4a16c51e12390195d9e9c72f794790caf7b0a835d64e01fec995d3ac -aaaa4761a00022ede0809d7063d3532b7bfae90ff16f45e17a340ad4ebaa2fbac40728ccc5fbe36a67ab0e707566c5dc -8319a1903314eab01f5442d2aee6ae9c3f6edfda0d9a88b416d0f874d7d1d05d08bb482102f8ca70a4fa34836d0840c1 -932949a6e9edfec344932a74d4f81eec3667ece1e8b8ca840ce07ffd4b5d6d8f01657c764d64ac1b9190f876b136490e -904db1568128487e312fe629dd8bb920cecafd3bb9cad8b63e269ae0129f2f5c80cd82f0d81e7feca9835c3945a72d28 -a17280693d30dcd43c85de8f6b02d5f30cb9097274ad680cede1ef105c903615b4c40f3c6aaca478642de324972514e0 -8d5f76e093aee71d0cdeb017fdfcb13bd068039746de90690ce150a0bfdbe7ddc4d539df0f82c2d2890a40b191900594 -96fa1f2196a3883cdd73c66d28403cbbb58f6a939a3697ee0d308d8a076393cbb4be86255af986869230ee410c01bcfa -a8b74438dc5cabd70a91bf25601af915c4418d074327a9b01e0190c27d3922c89bb9b41e0b366e82e313edda8f21983d -ac9fdc1a9b2e3ff379eb2370979372e13c4177bf4574f1490fadf05a7073e6d61e703e2d8eed9ce984aba317d411e219 -a45a6c9b958169f2f8df70143e6ac3e2f6f969a4eed6fd9f1c620711bc2454739bb69f0094079464790c5429c0d8aedd -8901cbdd1009864386577842c1e3d37835fddf834064d9613b4559ea9aef3084204e1f863c4306f874141f4374f449ff -b6c582161691e3635536686825be9c4d7399d668a7675738417e0363e064dfd28acdbd8dbc9e34c1dab8a1990f1f0eba -89e89ddaf3cacc78428f3168549c161283ca8337345750667c98212717b21e7d994eae4e45bbddacc832a18df1d79276 -84be275627eed8e1a73c7af8a20cee1ef5cc568cfeea7ec323d7f91b44e9653e9aeed47c1896a8240b99dde545f0e1fa -a779a54ab4f40228f6e2539595fb8d509b70aab7c19e1928c1be69ec1dc19285c3898cf15e5f8b8bc725e13af177fe17 -92e2a49d2b9b36349d442283b17d46f8f9bf5932c34223015ce62d2f285e7363b2c12232be4a838b5b6cf08e694c094c -8b4e28c6f3f36caa2cfb82ba88066c830f8017bd35608b077143dff236f3181230166f5a5c02fa0e5272297331726aed -85fd77d46162ffac4b8adb25baff0eb0512a53a3d01638b3a376ea34702279ce21c8e7d8884308c03e00c9bcc1a9fd29 -aad5e46916ff1be29009b595d1d8fa160cc7aa01c7fbf3a68f445c87615790dcab1fcdbdceda533d182b6541f09f2f73 -948df7654726250dae393325addd3c0a20431c81f00470962190335ea4b6d9f7463d6f308cda46b92084c1f24390b1da -8f577474dea132676504376c5542b730b6604fe3d965eaa194659fd11c52233bd0b11ab62e198c0f442327ff1c00e501 -ae2f1001546db3e0c19700adad997cd9f765fe7a51a502cbcd9a2a07a3a5db79c8f603e05cf96d80b688cb6c9b6cd3ae -953b68e5d9561088dd20406ea7fb6894cba33868a38ace38fc30b5813140cb15dd6dd2171befae5b4df2e4a9658889d8 -86c52901655ff11419b084a04da8fc3596eae59d81d3461601c0baff59ba59e3d1dd0b7ce719e741a3e97c013e898579 -b9a72dd5eff73f9912a28b55de073568efb3eb0241a10b77a2bfd4f30c2aa4fbfe0c89eb345c9f07fb725660873cb515 -8e7353f5f2932e4ffd95811caf46c9bd1a53643c27eb41a4ebd211f230955cd71a8b27e17cfe8aa708d8514c0de67a66 -a096b8e66312a92fb10839ebe60189a8d1bd34dff55f7dfae85e4d2f53a1a4a88211c19fc84494f066358ddce82be131 -931c5cd82719d76596832b007969b5f75d65cffabb41b9dac7910300db677c1309abe77eeb9837a68c760bb72013b73a -8ba10f5118d778085122065b55dd1918fddb650cce7854d15a8f0da747da44d7b12d44fc29ad7dc38f174be803db74c6 -8c971deec679372a328587d91fd24ab91043e936ca709c333453d7afd43ee256d08c71cb89f0ab0e89ae119831df6d86 -a2ac28a58034fbd8fd518f409221bad0efec52670880f202e09c0530e2aabc2171ed95e99891790596ffad163d86c110 -b3354e3dfa8068aba4f3741152b9204baa4e342c1cc77e6dd1419cbaf8da1d118be605846b8609e997d6a62a11f3423a -a12ab65a213c9d95c24865fddc2dffe0cf9fc527dd6bcdacc1bd7271e79929a4ab3427a231f4f49d0530474e6cbc88f9 -90afd65b7e6973f8aafbe74da0f42441840d3c93bd69bc1bec8fa56824e7ca97ad1b427c8a85da7d588469bd4ccc50c3 -a09175940c59489bac3d3da3a4091270d9118948cbbdd57f2bcc63fbf45b8010651c801d3e58dccf42733ce1d6b446a3 -a843bbf286e3cecc1fe370ff1bcf5f1001bc2e95b34246625ff50d48ee62343e82fba2d25b8a4bd5f7b5ffe90920efa2 -a3c4d1003219157fdbee2707ce07afa6c2a64ae8e450182c307ed7f070024071f30b12c4b0032960ff913c74e73a9976 -b24af3f68d66f825d06fc3ff94fcccebe28b1a0d4ba29c48d3a3c953b9bf7ae6707f193fef25e2dcbd2b74e483c774f0 -b0f657f7723184ef7d7e4381143f1ac8020d8c6c6f2dcbebb0eaf9870d61a81f2d452596503311e46d1b38f625d4756b -b90091004fc8f6205c51bec68547ac82dba0f5525631e7632cf6efe54eecd9020729fbee6105d1b8012402d3b79c54aa -8e3fa187713c60eb0a416d6900a894cdf81e6b6b69dae0bb64f6287f3c3f030cfa85c665f7aace1eab4937f380b8f728 -879bf0784ccf6725c9cd1ea8c49fde31c91c605de1ea664a33c2ce24c277ee45d20b66309f98d989acb2ff3b77e13101 -af3f3a3ddc4e11abd627d5aef8adffa91c25df5f0c68b4d2b5d51e7d9af3395ba4f6f7ae2325a6672847e1ecc6cad628 -973e667289e796d3a40f072e6fea575a9b371a9997cf8961677f8dd934619ddc47c1a3efe91bae9ef95acb11a8fe6d09 -afa81c5606de82f46b93f4bb6db3fc0670f4e0d1091388b138a66b3827322d95a56168c951c30831d59eeadc227500bd -b83eff77db5b4c18574662942eb36f6261c59f655f8a9c3d3731412d0f257c8e80aacc995c4b2303058a1ba32522a434 -912e5ac9234b9445be8260393ff08e4859a7a385e800b74d1534eeb971f58f74cfb518dfdb89f8705d89fbf721439129 -ab27c8ece4a51d23e22c2e22efa43487c941139b37ea1182e96efb54ca4809d8245eae0ebe8ba94f0ed4457896fe11b1 -a6630585d104a745bc79dba266d9292bbdad346449c8ee8140a5e6e8a6194411df9cdbf3d3ef83468a536d4f052e9335 -8b8c128244da48e7fec641a882d0005a2d05c7138d86a293e6a0a97c76bf632b44767d0ce44663c975e7f9f9679e25e3 -87dbcaca67351a4e7d2297d7cdba4796d12f58857e7ee4abd0645563577ff33544a44cd84e50b3a3b420d6998de9b57c -b859ba43df259d7f8e7fac70bfd7aae546d57a5dc90e107b174a95bf7fd3cf00f740c4434848e69b2a7e6061f66c1ef1 -99d6e20978fefc40c6d310187eb2ad3a39296f189ee122ed64d74f81033c3069d44f7a9d3988a1df635b609603a17272 -99a5ddf3420cc0c92b21f71a805245608d4995ead447d8f73a670d26d33e26920d5f07bfe1f6230bd5f15978055b4253 -b936ac0944d3c5e4b494f48f158000abb37b80b5c763f77fe856398c664b0f1ddbcc0a9a2a672db9278f08b4bafbe2ec -b4af85fbf4040e35a686dd016adec037c99b47cc2e4dfccaf7870ee9e8c97bff30f3035992def2a9d4af323c0b3af8ae -a5ee32b8bd5f8fa9000da4da0bf00565659a43285393d37080b555d0166bde64d87317b2eab2d48a0e7b287caa989be2 -894d4ad58ecb1c9ebc4f5a97407082e56cb7358d7a881ba7da72321c5027498454f2c7fa2bd5f67a4b11d38c7f14344a -965be9eeaa0d450dacc1b1cc2fbf0d5d4b0dd188f2c89aaa9260e7307a2a1eb22db6092fccb662269e9a1abfc547cabb -805893c424aec206260c1c2d2509d2cb9e67ee528bd5179a8417a667aa216a3f318ed118b50d28da18e36c01f0805e3f -972d7040d4963b35260ef0cc37cd01746f1a2a87cedc0dc7b0ee7e838c9e4573784ea743f563b5267eb3905d4fa961ba -8c7156991d4c2e561888feaecf501f721b4174e7d14109e9deeac5a9d748301c07e11fb2b04b09799f0d34ff42cb77d1 -894722ac35af3d507e81d737d21e16c5ba04686f8f004aa75934aae5e17acd3e065b96e229eb011c2f34096f4c62048b -81237937c247c88e8e31e2c72412189fe59c1daf65c5513489d86cf29ee922c0bb08e5f7890f09f4ada7e5262083d266 -8cf62cda2fe0d9a6b42aa2a1c483f4ad26378c7cc2c2d1510a76df7560b07dba8528b33aaacb15f7f20b9d4c7c9f61f6 -aaf0921fb3e1920eee5d0acb59dcc268b42f4b435d60d25d30357edd7dd758d035919691bd15311d85489dfa2e5ee696 -92cec07be2247ef42002ebcaf65ec855611b8e893a5675796f2225f55412201b0bf9f4761924d0c8377b9f131e09e39f -8e514a62ac1e91773d99588415426c97ad63e917c10d762fe06ace5277a5c3bf3730e4b9e5d116f8493b9ab8687b70e3 -83932df2d923a5052468a3ea87f7b55c6a80ede3594046ee4fe233046570921822bc16555b92ba6aeabaef9b1dc0805a -a2b5bfb249de3472113fd3f35bfabf3c21d5609da62a27ea6aab5f309c9068d94bc58ba03efb4ec11be06306d59e60e8 -8106cf3ebe6f0507be8c6e8d137987315fe3689ecb75bb27980f36ba5efac504baccea0e7603549b6d126beccc278804 -a73ee70b6fe8c082443972102c453fc0e386852476cf22224fc0bfe554735c12f96037fbf10922795f4502c4f052b5f4 -932b27e175440169958504f3ed6400e7d6dcd5e716c19dcd0f15c56c04503ed133d5a993e111c016f141e32d68b29886 -96f7ce4595318e0b4a6b368f788ff82226aac676aed4ace343867f751de414453a9aaaabef6e6224ce5aedc3d5cf77c4 -a950c1e3bc9a14484997013d44d876374b939af437ae7c821c131fb886063ee9fe7214a25a0c7084f0b07b99412eff75 -a9dba3886ed6855303106a1bdd26010f294218684e1c178afcfea3f37a2f04fd01724a31d82de3449046617e3507a115 -87a2f776b32a6b550cf3ceeaf78db02819be74968d228b1d14e0d74a1cdf994bb500b7abef6619455e98d728701fac5c -8cd887b07e335edc0b27e6a660cebb64d210741395be431d79d570139687b056557159407459799a8197b6079644f666 -b81a61fce00588909c13a90c1caa150f15788786af443ff60ce654b57147601f7e70b95659e01f470334a220b547611b -8aebc51141544c5f3d3b99422250424b9800031a8fdfbf22c430907a3a446fecaa2392105d66d64b1c8e847240da4a6a -90db7dc12baa02f3f86d3edadf9434e2b9318d4f6f0eca08276b765dbb38d8eb0d08be2fe70adf2bf16ceda5db08d3ca -aa1839894152d548cc6ad963de20fb6fcc843bc9af2a2bf967c63626b8ad19e900894d6106265f38f3afccca317c22f0 -848e27b741496988a582515c0c8847b2bfc6a001259396cdeea1e1b1d2828ca3a626693a1bf4adf3a3d7f8b1fa3d75fe -a0aa11754d4ee136ac3ca609b17bcae77758763b2016544ca7921dddedd8aafcc7ad5f2b337c8bf53084eb8e43ea41fb -b8713b7aa1c112178195fdcc9b7024f46e6bc04c4e76c41abe620aa265287809200d98eaed6c9703fa97e81d6964f0ec -8605b5b33309e9ea6823542b85383c496794b8481c577497aaf99ba90496e794dce405be615bf92c7b6361460e6b82e3 -826fa34faa7f83e063a7bf172addfc07badabada59cfc6604fdf481d29085251c0a67a1355b2cbd374e2975934b84cb6 -b45d131082dc16fa53af010d43eefb79200dc23d2f3ee26af95ac6a5cebc49c84a9ed293e534ed16ff3ef9a4a25456ec -91bd6ce3c5396a7a0de489e49f0cdf6dce1cd2d0be7a410326423c3185bd1125ce1e610768be7f15f4e44b62f8834fc3 -903ffbe3d33fbf106c01c727dc3a385201a67ded70d4df623934882f69a3a96c909b027a124f3d70cb072b0046a149e8 -b405359db9d9ef4821a181b440ef2918c240595141d861d19a85867a5afa74d2972d22c988775eab441e734700bae4a3 -8abb756d027233c83751910a832b0ef4d28d100077f1c5d656720c94906f91d85dd0ea94b1cc0ed95b692efee14c786e -a78ee77ab476a41a3454160ba7ca4085d8b1f7057c63e76db8b07cf20afdeddd2250cd00771a6329133bb4ad48ccc20a -a41810271d8c37197aa9b3dfcefe3498e42f5978d3f3d59defff4676d6402d8575b40683834f184f143b6cfbfc859b3a -90c24a0750242660bcc6d487358a3cc015730538a0a8beb00ad5ac2ef33cb8ca8a62121e50bec8f3d2f43900f8e3134a -8b96c39695d864ef5796941754978a1fd612b369f6b77fe5ae6587beac936ee28190af8f0a3822b63060af35e49a5c8b -acde2548883d0e63c0fc257bb9dadd919aba60a985b69ebcfa1bca78acca42fc1322ec30bcc8e7c188818f858d04ad33 -895c86ae9ff8d95f2707d4838a3bc8ddb05b2611f0476f014b9c150d0e8332bc73285037a747426f09ac8179ba4e19fc -821761fe406e18bd86fa9ca9db99d382cd3b5c70c456f471fa3706d57763d147706304c75d54f51ce8f3115aa26e59d9 -a803a80e3e8f47dc3c59ea23eafdec017458eac648b360cd42cbd075e0dde6f6f450b48c7646fb1e178c04f82ae51a12 -91f40e1b6f588bd592829ce937996452c40be0fd6c43793c607866701ac6a8c7227e0891d45c6e7b1599382b0a3fbdbb -9408246d996a634a58689337f2526dfb3ba9ffef1d3ff91c32aa8cbbed900861ef25d6477308b67d76491edfcc70d65e -a492325a427f3df1c9c690c5b553daa8ac41f62f5ae55f425539222bacf959e2f67afabbba1732e120d3e7a6dcdf7049 -8fd0c3e15477cae228613a171b6e9ec29ddc63ef74854d99b638adeffe39f89f34346a42851e8445e855a9f2bbef0f57 -b735ed01fafa051004dbaad5e8c9e2faca8f6049ef9b590f256ea4d75b04594af12764ad4e6031735eae36f83179db93 -a7d35f43fca06c86b3425dcb68a87186834ba9740664fd657915771beca4cdc0fa2fc9b4c2e9d9bdad8ec33543ddfa59 -a1156e71e2db1b17df5da28747c88e091bd687bfee59d89096437ab4dc9a543fe5c5272d5023d72adbaab397a6fc94d1 -ab06a58bd81b33a411bade8d8c5232d38fadc2e38507159edea6e2e104b8ebd65ca02b05335118f691d44197b847a4dd -848b67a10f1e6ff8f5c228f226ef2ffeb67fb8f50925fc94cbb588d61896d9dc79726959e649898fd3354fe3ff7b7ee3 -aa933397361f32b388edcf832f0db172a38e756b34d5f7a4a050fa7325058006c22cede26ee27917e8f1b0f301792bd7 -89e49e7f02cfaae4a4b9c4180c9f6559d76e3a45774955859d4147970b1470dac37bdc9aedca1c32a20b045049161590 -adc1825d5ab94fc719f25d8c9773f4d518134ed88eb13ac33cb910b2be3523ef9ef88d9e4aea2418b806e20108317bf6 -96c4b444c8a023da644f3a343ebeeed19a8392d2ce175992461451c318a54273b76c3574d8f2dceda2947ddd34d1a674 -8aa7e97e87c8c5b29bbd51a6d30396a6be1fb82b716ef83800f2c36d5b85467ade7e0f59d2db82c310fa92a9265f0b03 -9146c32d99f02c3a6f764dcd9b4807f1585f528ac69dc4f84e4380f6fda4f9d5057c375671d51e7aca2b2b4140e83da0 -a10760a533d9bc57536bcaf65f080302086aa50225437efd64e176841544711828c23a15c49c0dd1f357d3f10722ab72 -acb0811777e17f7ae7aaba5f6fce81b759c067a4908730916195a2505c7450d0e6e2194c2ef0f241090597d58e70de47 -b24f161e9bcdbad56665e2490b5e4c7768390d4668cd69a04ed74739062dbe832636dd33cda89e9b0afa8c77e93fc641 -96b4d01106b831868a88ef016500ef2fa42d0ce87a37ca8ca4194a92a22c113edfe04eb2ca037329f3c1acc635148f55 -aebbb95fb4f7adcc8e7a217aeb73f9e037cbb873d08c1cd9d68c6c6834511adf1af8b44567fee84327599bdcb734dedb -a9bd8b17300532fb94d028659bcafbe7bbdf32f8945baf5db4cfaa1bac09e57c94cad0ba046b4514044b8fe81ea8596d -a5557cbda599857c512533e7cadcf27bf8444daa0602aa7499cafc1cf1cf21f9d16429915db7485f0e9a1b5046cf01c5 -8810307c40bc661c478a9747ebf2a30e5a5ead942d1ac0418db36ba5db0709c476f7d19685cabe6959e33ec1f3bff914 -8829b741f41f2c32e10b252d9338deb486dba2f23996a44cf1dd888ad967a589d51329be34d764139f372a1043f6c2e5 -a6b4728d18857c5fa082fa67bfb3b1d801e76b251b1e211a19c87cea5fe7ce757f943c85071f7a03a718388cd5690e95 -86da7f397e2533cd487f962ae58e87bea2cd50af70ef2df9ea0f29f70b5843cde664d30ec207ab84fc817f3851277e02 -8085776ef4ac6d42ab85b9d9135ecc6380720efd274f966544eeedf4684028197de76ecab919fa5414302597e1962bca -b05a065c733033d223ba13d16baa7a97bd8c8b8b1f0e59a9bdd36ee17e9922d48eb39bd180c168b122088a77f0bf321a -a89343fe44a93023dcc7ef71bd3bcb6786f68e1885ad260edc56a52445d34757f476395ba7ad35437f89bc573c7618dc -a114a9cd6105b524f3969c69faa2e09afe21753a93361a296f9e0e3b4e3e63726ddf2e6bfd3ddc046043e50bd44e539e -8a5611fec539cf681c05636bb580f29acc06f628bb012649ffa41ea6c1521194a5643d5dd843f09b6eb2c3bdb4d41acd -ade247c4011ec73ec90b72f35afa59a999e64ba5a7e664a4b30874fea53ba6a14a76a41b58a5f891a20d019e5f091bdb -905b5d96df388160ade1ffe210d0c6d1979081bc3de3b8d93ac0d677cc2fc2dc1ef6dcd49d3947055514292a3fa2932e -a9520796ca9fccd11b7524d866507f731f0f88976f0de04286e68d7cf6dbd192d0d269f0cd60fd3d34011a9fe9e144c2 -989a1edf4d7dae811eb57a865c8e64297837ffeeaae6ee6ac3af0f1044f023f1ca552bf00f1642491f0f0f20e820632e -879c8e63713f4935ed6e020559e140ea3073ced79d3096c152c430141272117b4fd9a9fc3eef012e81262df02ea14bd7 -95074738ac1540c0312274333acd1ecad9c5509fee883c4d9295fa8d8200f6e637c363de395f9fa612f05c0dc58fae88 -a770e4fc595269eb806b113ab3187ea75c8f96b57bf9fcfaf535f3eedc1d4d7e6285a20990575de0ff09f62d06ed0692 -81283e5dfb6423439ff513eca1cc316941d196df8da2d1069d2d0b63f5289e630af2fd4119bc0144c002d33313372dab -abd1b108e743887b78f698f2aba9d5492f87a22868d1351d705d93a1084fd45be67170c68a6e18b07f400d9a01cda8c2 -8509c3f67b92908cea8144f4e2a71631a66a61ac3547601c788907e52e380e5fe8ae4110aed95d13c67d3bcdd5b55a61 -8fa5a790ec5cce6d4114128c295390120869aac5490a82feebd3c37a167120df2e7fdfaf2a4050a7dfebf48fb093212f -944753e1ea7d8bc727d46a7702077dc01dc0c6574e8263a16579b57ee155ca5901f71bb347a01a9a922b329d3ff75135 -b46bc1fd4590b7a6275e20036d247c5909fc549c78e95b64ae7ed96e3b05bb044840f19f7650ebfe7008ba09fa83c3c9 -b1e47e4d88e59a06c465348c6cc4181d40f45b91e5e883966d370c26622c328415c6144aa2f61ddb88ec752482c550ca -8bd4f8e293e3f1815c7e67167618fb3b0ea76424bc0985908957cfcede36109378e41b4d89555b8c2541b4c447e00461 -a70589a867b2bfb63d0106083d58475d506637148549ed35c83f14e5c8de996e1b1f3447ecc80cf5cd134ef4db9d2fb6 -8048b80ba6131d07370162724127b0f7cb17fa7f71855e55e5a75bd0a9e4fd71b0d0ea2d16ec98858e458528df8d06b5 -97326cb94bae7530f4ec3235770c5a7ba042759e789d91c31fedbd979e3c0e6a2c69e2af3c1979c6fe0094274dbd53ce -a18e9c1d3eabd62af4e31a4b8e08494f4167fd4598c95d0123f39c46c53f9e93f76615900246e81a286c782ac37c569f -80309c59d4522b15aba617cd3c6238663e8b1c7ad84456346082c8f281140fc0edf9caa19de411c7e7fb809ca4fa3f4d -8e450c0990e2f65923f252311623038899eeff7b5c2da85b3a224e0ef7132588b291b782d53c477ecb70f34501466178 -87843f96f41484e254e754c681a65681b9ae5c96c292140368743df9e60f7e2ada58ca2bb95fa39abe064b2ebf21eeba -858e8d5bf2a1cf26d8af5036b28b831d450a446026f58a1734b696c18f1f41482796b91cab0e5b443dd2f0b9cffa52b4 -99627dd6bad8c05c5904cd23aa667d664da846496dbbb8452705c4ec01e1480e9c7295504a5a8529e4a0c842306b038d -b64b33256c18b2c886a837a0c0730fdfe73befb0e2796207c4dc592c5a33cd51f8c2ef47c584dd5773abf9ce9c1b0082 -944f6da2a1546f0bfc4d98c3e73c79e935e33d208b6be26b0b5f8df6d0e3b74a5bda649853b99281bd3a3ec799a7dd04 -a266d165435784d4e884640155e35b2a911b3f89e1e715986de419b166a36a341ba724877d80583fa3da566f6a828971 -adff2698409d0756e78c534032ee926560c13d578cb178d5073172d049ebbce32a92692f7e2033ec781b9b0d894ddce0 -a91933f110756c699c28bf9e24fd405bf432002a28c4349e0ca995528e56a5a2d101b8d78afa90a178ff1a9bf2ba515c -8e77839c0eb4da2d01e4053912cd823eddffbdc6b9c42199fba707ca6ab49fc324288b57be959fbfb11d59085d49324a -aa124517c76692036c737e987f27c2660514e12a953e63ff4bcb269dd18fc44dae95e282de8444bed09639ef6577af88 -b285deae99688f1bd80f338772472fa2b35e68887c7eb52c4ef30fc733812444c5cd110050275ad999d5a9b57f782911 -8877b0fa85b44ef31f50bdb70b879fa6df5eb1940e2b304fd0c8f08abb65f3118fa3d97ff93919038c1e452fb1160334 -8a89f3b50dcbca655024542ca7d93df17deff5c7d01c7da2bdb69e76b3e0b4490d85c800fb3debb4b0b4d20c9527f7ad -b7e5dbe36e985354ac2f4ab7730fea01b850af00767a6c4d8ee72e884d0fe539bb81f2e34638fcf5d07b7c8d605f4c06 -a85a1d78f6d4f9d5d83ec0f2a426708342d4e4a5d15625554e8452f6a843d9aa4db0c7e68caebdaf767c5b3a6a6b2124 -a518078a9dac63c5bf511b21ed8e50d1ccede27ebfe9d240937be813f5ee56aef93dc3bf7c08606be1e6172f13f352ce -91144eedebda4d1ad801654ef4ecd46683489b177ba1de7259f7dd8242c8c1700e15938e06c5d29aa69f4660564209a0 -a16c4657bc29d1d3271f507847b5a4f6401cee4ad35583ad6b7a68e6c2b9b462d77b5dd359fd88ea91ce93bb99130173 -85b855778f4b506880a2833b8468871c700440a87112fa6a83fd3ddb7e294b3a232d045dc37dfc7100b36f910d93c2ae -8d86bb149d31bfbf1fabcae1b8183d19087fd601c3826a72a95d2f9cedb8bb0203d1136a754aa2dd61f84b7f515acfa9 -acfe7264eee24e14e9f95251cbcfdd7e7f7112955a1972058444df3c2d2a1070627baefada3574ebd39600f7f2ea7595 -906bd14ecca20ac4ae44bff77cc94eb5a4ecc61eba130de9838e066e8766ed3b58705f32c650e1e222b3100691b3806b -8f2cbc7b8593c4be941dd01b80dc406fe9dfdf813ef87df911763f644f6309d659ea9e3830ff9155e21b195fc3c01c57 -a68eb15ed78fae0060c6d20852db78f31bebb59d4ddc3c5bdd9a38dbe4efa99141b311473033ff8f8ea23af219bc8125 -a95cb76c9d23fc478c7e8a73161f2ff409c1e28a2624c7d5e026e3cee9e488f22225a0c5907264545a73e83260e3a4ec -b76f90e55fa37c9e2732fd6eba890dd9f1958c1a3e990bd0ce26055e22fe422d6f0bcc57a8a9890585717f0479180905 -b80cc95f365fabd9602ec370ca67aa4fb1219a46e44adf039d63c432e786835bb6b80756b38f80d0864ecb80e4acb453 -b753c86c82d98a5b04e89de8d005f513f5ea5ea5cf281a561d881ed9ad9d9a4be5febb6438e0dba3d377a7509d839df0 -a664733f3b902fac4d1a65ea0d479bb2b54a4f0e2140ed258570da2e5907746e2ac173ace9120d8de4a5e29657ae6e05 -9479722da1a53446e2559bb0e70c4e5bf3f86c0ce478eede6f686db23be97fcd496f00a9e174ceb89ab27f80621f9b80 -b707fd21b75a8d244d8d578f3302d1b32bb2d09f2bd5247dff638d8b8b678c87d4feab83fe275c5553720a059d403836 -93214c16831c6e1d6e5a1266f09f435bbed5030c3c4c96794b38d4a70871782002e558d960778e4465b1ff296ffedad8 -8648f84e18eb63dad624e5fa0e7a28af2ee6d47c28f191be0918c412bf24b5460c04bf2b7a127c472914a0741843f78b -b67f61e75d6b773a6b58b847d87084b94f3cdac3daa7bef75c2238903a84250355a986b158ff96ba276ca13a6035fdd6 -ae9b094b7b5359ee4239d0858d3755a51aba19fce8ad82b0936cca48017523319c3309409ea6e9883a41bece2077e4d8 -8d1d8e1fba8cebd7a0e1effea785a35e16b1a10842f43e2b161d75add11eccf8f942d2ae91c20eef6c1a0c813731ea9a -b82bd387458e3603782d5e2dec32ae03890a3fc156d7138d953f98eff4200de27c224f626e3648e80cd3dfc684c4790f -a6dd02a89ad1c84e25e91176c26355e21a01b126c1df4d22546159dab9d502dbc69bc0d793a017c1456516e4aa5fa53f -a9ab74a5c5459b8500beb0ad13e9cfe2656e966dc9b4f3f98bec7588023b4ddebf74e4fc722d30423f639f4ee1b2587f -b03e5f33ab7ecec12cbc547038d3fa4f7ea0437e571891c39660c38d148212d191be29e04eb2dc001b674219b7a15a9c -925df4fc6e898ca55090ad1a8f756cc5014167a042affda5b24896eeb6aac408545134920586a8e1a2b997de9758b78a -98c8580fb56ed329fad9665bdf5b1676934ddfb701a339cc52c2c051e006f8202e1b2b0f5de01127c2cacf3b84deb384 -afc3765d374c60fac209abd976fe2c6f03ce5cc5c392f664bb8fac01be6d5a6e6251ac5fb54cfcd73e3b2db6af587cbb -8e7e98fb5a0b5b50d1a64a411f216c6738baaca97e06d1eba1c561e5c52809b9dab1da9f378b5f7d56a01af077e4f8cf -b724bf90309651afb2c5babaa62dc6eac2b8a565701520fe0508cee937f4f7b6f483fc164b15d4be4e29414ce5d3c7d4 -9665160e7bf73c94f956ecb8ba8c46fe43ae55c354ce36da40ccc7594beae21d48d9c34d1af15228c42d062a84353a0c -8600ab3aa86b408ee6e477c55572573ed8cfb23689bbdadf9fccb00161b921ec66427d9988763a7009b823fa79f8a187 -b0d8d19fd1022e7bc628d456b9bd1a2584dce504eb0bf0802bdb1abd7a069abbeeccdb97ce688f3f84a229342dbc1c33 -8f447d5e5a65bb4b717d6939cbd06485b1d9870fe43d12f2da93ca3bb636133a96e49f46d2658b6c59f0436d4eede857 -b94e327d408d8553a54e263f6daa5f150f9067364ded7406dcb5c32db3c2dffd81d466ee65378db78d1c90bc20b08ab3 -b58c02781b74ef6f57f9d0714a96161d6bfa04aa758473fb4d67cc02094cd0c0f29d0527c37679a62b98771420cf638b -8cfa0a687ea51561713e928271c43324b938aa11bb90f7ffaa0e4a779b3e98899f2af59364ce67b73a46a88748c76efa -95d6d39c814c5362df69116558d81ce6f1c65fb400fc62de037f670d85f23f392c1451d43341c59bc342bc31842c8582 -af888b384c52d9e04e4db6c4e507c2037eb5857e9bcc33acf84fc3a02d93cbde8cce32141fce9f5fec715b5f24d56356 -a7822bbc3c236fd58bd978f0fc15fe0b60933a0c953db6436a233441219418090ae0c07c490a6548e319029771cdaba7 -8c53729f750922e5eb461774be8851a3f40fe42eed170881cc8024d590bf0a161d861f5c967144d15cdcdc3dc6b5cf88 -a052a25a4aeab0d5bb79bc92a6ae14b5ad07d1baca73f4f6684ccecfc7ea69bc21eadeb9510452fdba116c0502dd698f -923946b83d37f60555dbac99f141f5a232728c6eb819a37e568c8c6e4d9e97a4229fb75d1de7e9d81f3356f69e6d36f1 -8cab82cf7e415b64a63bd272fe514d8b1fa03ba29852ec8ef04e9c73d02a2b0d12092a8937756fdec02d27c8080fb125 -b1123314852495e8d2789260e7b3c6f3e38cb068a47bdf54ed05f963258d8bcabaa36ccbea095ba008e07a2678ec85a7 -a685b779514961e2652155af805996ceb15fb45c7af89c5896f161cac18e07b78c9776047c95b196362c9ad5430bcb22 -b734dd88f6cc6329c1cb0316c08ade03369a11dc33191086c6a177cf24540c7ceee8199b7afa86c344d78d513f828e81 -b0bf492fb136ecdb602c37636ed4deef44560ab752c0af5080a79c9f76a1f954eba60a0bf6ba8bd7b8cac21848c29741 -a5c74682323e85ac20f912ab9c1d6e1b9246c4c829dca40c8a7d58ec07ea0ad3524be30623f351269552f49b65a1245c -837403b9cf830fb33ecc11a7c8433e07745973c36acdeb3fc9ea8f7d8d690d462e1250b7410f79f2f4180fe8f3962a4f -b03d64b944d49c83608f2c5b9c14070c025f7568c4c33d4eeb1da31d07f0bc5897e498b35b50d557ee129f0c3c68e254 -827272aab8bf757e2483156e00fbebe1093a58070dd3af9855bbf946c7abfb9c8a850a6a8acda8c620902f391f968b8f -84c4eb863a865282d321302d06b362f8bd11c2bb0090f90ebffedd3eb3e7af704cff00d39a6d48cbea4262942e95200b -b044eb91653dc55dce75c8d636308a5a0dae1298de4382d318e934140a21ca90e8a210e06fdf93aadbbeab1c2ef3904a -a8c08955a4378522e09a351ecb21b54025a90f2936b974068e80862803e7da2b5380c4b83b4b4aad0409df8d6c8cc0cb -a763a5fb32bd6cb7d7c6199041f429782deacac22b6a8467077fab68824dd69343ebca63a11004c637b9cb3129dbf493 -8c44c8afa9a623f05c2e2aba12e381abdb6753bb494da81f238452f24c758c0a0d517982f3999d2537b7279d381625ed -8613f47fda577cd3bda7c99b80cf4b2dd40699edfd3df78acb5e456dd41fd0773bc8da6c5e8cbf726a519b9fb7646ccc -b21a30d49d7e1c52068482b837a4475568d0923d38e813cea429c1000b5f79b8905b08f6db237e2eccf7ef3e29848162 -b9bdf4915f3fbb8d84cdfd0deedf2c9dc5b14f52bf299ef5dca2f816988e66322df078da2c54b934b69728fd3bef40b5 -993b45f389f55eba8e5ba1042d9a87242c383a066cbf19bc871b090abe04de9ff6c1438cb091875d21b8c10fac51db58 -a85a95d14633d52d499727f3939979a498c154fd7ebb444b08f637b32c1caf5cca5e933a2f5d94f26851ae162707b77d -b9874c7c4be1c88a9646e0c2f467cd76bc21765b5ab85d551305f5ec0b4419e39d90703d4ac1bb01feb3b160517e97b7 -ad6771177fc78812904c90594712956357de1533a07fec3082ba707f19c5866596d624efc3e11773b3100547d8f6c202 -a79f31921134f7197f79c43a4b5d5b86736a8d3ad5af1bdf4ad8789c2bfe1c905199c5e9f21e9f446247224f82b334f8 -a7f1b6c45321222a350a86543162c6e4e3d2a7c2dce41aeb94c42c02418f0892dbd70c31700245d78c4d125163b2cd5e -92abafe3ec9dbe55c193fb69042500067eb8f776e9bf0f1cb5ab8eb12e3d34986d1204136856fb115c12784c3b8dea6e -89bc761238a4d989006ca5af5303c910c584fe7e6f22aa9f65f0718a1bc171e452c43695e9f5a591725e870770c0eceb -aa0e44c2b006a27d35e8087779411ba2f9f1966a0f5646ff6871bcf63a8b1a4a7638751b94c9b9798ccd491c940bc53f -8736fe82862b8106e7fdab7b5a964d87ec291a74b8eb1cb5a6c046a648c1b686064ef3d52297043b8940bfe870c712f8 -956a3def1942f05144d8e9c3a82fd2d3610064b53b9eefde3d5594a8f705bf8f6849eb2c22181796beffeba43cc74ee4 -af27416d00cf97d5a1f4a1b6b51c010884cceca294f1151c3b684a3f83c3c8a3c30771df1166d833cbddf6c873c400c3 -aac3b8dca2336fc4ffc63c362df461289e4bbd3418c621bde6c581d3ecedf66e2b3e523d4db39e3d8ba014577bf85efd -94c3a8167f62074e5b28c2bffe4b6ce645439a9a0c5da3ca1b3ee956590a465d6f84a8a4dbbe9070ffbd6bbc734e4d62 -95e23ba6986d25ed4451215da05bd72c5491528271726d79a94c8cb16aef1c85b190d6c5b8a3a1191c7cafbab1dccf0c -953e3dadb5ad68f7de31ac09692948655d174fe16d88b96930ef35b331da7f1dbc4c17863cd07b4ec3135b5205891a27 -915d018f18b5d63cb3301c2bb5c6e85e75a88ba80663c964d06575b6bacbbe59139d030b218ce0998271d5b28c00b26d -8c871ba3dd138a908b2f7effeea0e71df096b23e0dd47cab10b9762b250abfd1221da94a8ee884e05bdf02271fb85a04 -96bad5c6ebc3080ecbe337409ae398bbeada651221c42a43ea3b7c08c21841ddbcfde544c9b8d4772de6f2ce92c0b963 -b5dbcd0b1c44c62108841558ec0a48df4b327a741e208c38b1c052321eda6e6ad01af71d49dfcdd445ab6fa6f0c34e6d -97dba59219b69e8aef2659d1f10bbea98d74aefff1f6451de3f41be39acbac0122b8ff58b02e90554469e88911ec3547 -b7e5682ec306478be4858296f5d03364a61f3260636a4242f984d351a02e8723378496beb30c4ca22def9c9ca193ea70 -9656a7a3df4d11df3d8bc35930dff70a5e78a488ca57bba20bb06814fc390fc6c7cb3f39b22134992aad196cced577de -8b269695aa63eb56d0324ba984279dc4c88e565321f1d61d553622bd4f1910d5eff68393d3a830eb924472bd478c2aa3 -9177bcd04b28c87bc0440268b4c8995c6790cad6039594971b2c177f0e197055231e776927d3fa30d98fb897a2ba401f -ae0e943973482001c4f214b9da82e1c27e38aa254d0555e016095c537c835d3702bc2de5c67b234ab151e02b3b7a43a6 -82fc719a7d38bf4787fe1888019ad89fbf29beb951d2fece8686d2beb9119d0c8c6d13bc598748c72c70d73d488140ca -b716dc66f87eb16b95df8066877353962d91bf98cf7346a7f27056c2a4956fb65e55cb512af278783887ab269e91cd76 -81d58cd8bc6657362d724b966321cd29a1b5cdc4601a49fa06e07e1ad13b05e9f387ca4f053ed42396c508cd065c5219 -b32ad0280df6651c27bb6ddbdc61d5eb8246722140a2e29c02b8b52127de57a970e1ded5c2a67f9491ae9667349f4c46 -b68a2eb64cc43f423be8985b1a068e3814b0d6217837fb8fbfd9c786db9cca91885c86899c50a1242040b53bf304ced9 -85887515d4e371eabb81194cbc070e0c422179e01dbda050b359bd5870449c7950e6b3947b7a4a0eb68199341cc89fc3 -ac5fff3c27dfbab78eb8aad37ac31cc747a82401ebf3644a4f4f5aa98d37b8bf3b3f4bd8a3428b32a127c25c9e19d239 -86fceaa6fbf8913553a9e1e907fcb1f1986d5e401a7eafd353beefd1899d571454fea96ff5b2a21254d9fb693ec94951 -b6778bb296d3f0de2531b67d36fdbfa21475be0ca48b9dfcc38f396c41b557823735ed0b583e525a2bae1fe06e04058c -898088babeb5b9866537d6489f7514524c118704abd66b54210dc40a1c1ddb0a1edf7fe0b6e0db53b836f1828ecf939e -b27854364b97274765f0fb8d1f80d3660d469785d1b68da05e2bd1e4b8cbbe04304804d4c8aabb44cf030eba6c496510 -8c55bbf3603dc11cb78b6395ccbc01e08afcef13611f7c52956b7a65ccf9c70551bff3ae274367200be9fc2d5cb26506 -947726f73cd6281cd448d94f21d3b91b96de7ad3ff039f9153befbb5f172db9f53cacb4f88c80a3db26e6a0f7a846eb0 -a7b733a05e97528812d71cecb4f638a90d51acf6b8fcbc054787d6deb7e2595b7b8d1cbe1aa09d78375b5e684a2019bc -8d5ca6d161341461544c533314fe0a6655cde032c2d96f0e4ea7e41098b8b39fa075d38e2d8c74e2d0308f250d6cf353 -b960e9f081393e2260b41f988935285586a26657a3d00b0692ea85420373b9f279b2f1bb2da2caae72dd2e314045f1bd -852a49c7388c10821b387c6d51617add97ba72485f52be95d347bac44c638c92e9c6a44ba0d32afc4d59178a497d944a -8412162a65147e1334ad5af512982b2b48eef565682b3f3e0bbe93fbc5e1103db9375a0c486bdb1b2c57e4cb3a8e7851 -8f52c3eb5d4f1e1e82cfd2b291d4910195427603b796f6c311deb35ef14a01a57a9e6cad39619ad108f3e86f384f9e1c -88d221088f2bf0103c53e44d0d96cd7881ec2b0a965db9121a47481771a8b796edd5ac23c4f9c208a171dab301f7d3bb -b49c3235e8b3617ed08a1891b9e2bcb33dbdacceb94ca96330555b7e00904fe6a749ced9312b8634f88bcb4e76f91cb1 -a85834215e32f284d6dfb0cbfd97f6cffc7b9d354e8f8126d54598bb42d7f858a2b914cf84fa664069632db2ff89a332 -aa3d48eb483c6120c27d9b3e3d0178c1c942632ff54b69f5b3cfbc6ad4ff5b2b9ce6eb771fd1eea8edf4a74c97027265 -a446cfded353cdd9487783b45846402b973cdeddf87e2bf10cf4661610fff35743cc25e8d3b5771dcedfb46b018a5d18 -80998377b3b393ef3073f1a655ad9d1e34980750e9a5cfb95f53a221b053ddb4d6985747217e9c920735b0c851d7551f -a35ac469790fac6b8b07b486f36d0c02421a5f74ea2f0a20ffc5da8b622ac45dfccabfb737efa6e1689b4bd908234536 -8fb1f6d8e9c463b16ac1d0f36e04544320d5a482dd6ffaec90ea0f02b4611aaca984828bf67f84dcc3506b69af0a00a1 -b6e818d61aea62c5ed39c0a22ccbb327178feebdabda0c9927aa1549d2c5bb0637785c4aed2a6d9a7b4989fa8634c64a -b4e7208d16018bf67caafe996d436113eac619732e3f529a6efb7e6f094d8ebea55b7be0e122be075770f5957b6ea6f0 -b691d38b552befac61f6d367287c38d01fec73b7f2efdb6713ca30314a37fb7c177eb111fe6bee657f2681014e07630a -9817587e418e6e7e8e97ae27067f17b55d25dfb14e98f63f530620c855d9a348c9fa571c8508e2741f902f8b9fdc0c5c -b6a6e5ca779ba140bf1d84cd5394ede8262f7479637ec0087a4b152243a1774ba916d8115ce759a3bebd1b409de5f2fc -b53d1c84ad766ff794bf497db3228efd2cc8ed5fc1958d89c1126efdff361610ecb45ea8e329b39035ab00a66c1259c7 -adc31333c507c8e0f4aa2934fcdca57fd9c786722a50dbd5404e129541f7ac182cc7373bf14e1e4e06e6cf94b31b90eb -a82b7fde4642d982d95cec669efee140ad797a2442c7f6620580527d163accbf021b893446cbb8038ea82fe25b15d029 -91f7acf8a8903979afa281646fdecb54aa4d2ed905748e156e92f0910de268fa29d67107d40863935d677d1de8039be2 -86fea71c6d43a7d93216a92fc24dfce8521fd4534a9558b33762d002081247867a6eff54cad7116023277fb4049403ad -8ae5369a7f9f4c91f3be44b98089efd9c97c08f5bb4cd8b3150c115ecd86288fa0865a046a489c782973a111eb93966e -b6fb9e829aa2c81c2d9eac72bb2fd7f3a08e0cd763532c2ce3287444d33cf48b3621f205e9603ec58525934b61a795a9 -83e35ca808d84e41fc92115e9f6e283e928c3a614e6dfc48fe78c33b6411262e7bfa731eadb1e1937bc03cff60032e1d -832fca5196c95098ad47b7d24ba2f9d042e1c73ad2273edd1c2ce36386796ccc26e8567847697f3fcc2a0536a2a2087a -8fdb7038bc8f462ab2b76bf7053362f9c030019f1b6105cf42219a4e620ecc961e3eacb16a8e581a562a97f1418b0128 -8d3a5a404b51b1ad8ce3b23970e0d5cc57b573922341008e3a952a1dd24a135e19e55b79d86a70cfd82e1c0e9630f874 -ba00c025c1c21c57c03cdfc0bfd094b35422281ff0a64b68b240617aa58c6b18800af5f2047d3ff9068bbe987d6c7980 -b468f0dd51964b3806b0aa04f3fe28a035e8f5567fc7d27555be33d02701a838b8dbfe1348b6422c4eac46d2c75c40c7 -8a73a18c97da9958903c38584b08d0e7e26993a5d9b068a5e0e1ee0d8a873942745cf795f94f7a3d3ba88790a9fbb2f6 -953a0a40c2c8102723736854d13b228698c14a02d85c8d2e61db1a768019ac305faf0d5db62ac976430ce087a5b20f1e -8998219da6b34f657cb8a621c890a52cb98c2bc0f26f26e2af666eebeadadc5e8bdf4f830a91d04aca8ce186190152c8 -8941e08c3155ad432236ed05460420a05dd0aaab30477493ffb364b14c00ea5b9183d30d3442b6321d2d20c36e4f5c7e -93f293ff7fb56cf5b03aee6f3ad2ad78444398ed5b3be56d7bf5b56b5aa5a2b980d13895dd57a5726d1b067c20cc55e2 -84a16f313e3f75e31824f58d19ab24c6611fb4c75140a7cadc3c166f68819547c1d0ff7f7d13f5d8ae30dff1d80e2aa4 -b6e3e830b15039d3e28b08f5465bb089eade11ee3bd80afe39e010df7db1fcf0c56d698717677a41ddbc91eeaf6544d3 -95e928e6dfff51351281568ae72da7d1edeb6e9fe01f30af0499e7505ba35a22b5bb919d41bb809a432dce83f3977663 -aabeeb60ca46f9b0232ff82ea7766dcab8cc5aaf9d23539f30174f9486640bc9312868ca493b59b314519fc399973e47 -b393a11e957d0bbb3ecf617b075b5906a3450b348e62916c04791b366f0a7397cccd6648440ac544bc30526e1f95aad8 -abb5bfc3964a6d246da60bd809d0ea6daf4f8222efdc12ceb6730194e85f413ee7eb03bae300abf7ea900dbbc3d08971 -96c1bd1d1d216a4bfbcf000c123f296c0d31e1684e9e3884c14df23bf528c8d599f82bb98fcea491716b617216a8e0be -92d1e570a56f1741fd9f3d9f488cc336421c6256c14a08d340a63720be49b0029e3780e3e193a2e22bf66cc652fa22a3 -8769c08551e3a730e46f8e5d0db9cf38e565a001dfb50db3c30fa7fa0e98b19438edc23c6e03c8c144581b720d7b33a4 -b850bd67fdf5d77d9288680b2f6b3bc0f210580447fb6c404eb01139a43fccb7ed20051999ae2323ea5a58de9676bfb4 -80285da7a0aaf72c4528a137182d89a4db22a446e6c4a488cf3411937f4e83f7b00ec7549b0b4417682e283f91225dfe -80520368a80b97d80feb09dbc6908096c40ff7120f415702c1614d7112b0b57f6729581c71f4a3ce794ac959a46494ff -9817b4c27a490b1cd5a6337e7bc7e8005fa075dd980c6bf075ddfa46cd51cc307ad1d9f24e613b762a20fc6c877eab41 -ad66bda1a3034ec5e420b78107896ecf36126ce3ef9705163db259072dfa438c6107717a33572272062b9f60cb89557c -876114ef078c2915288e29c9abe6b0ad6a756b5ee2930ba1b8a17257f3f0557602d1225e8aa41ce8606af71ada2a971b -aa3d6cde4c3b9d3d5d0c77a33e67f182a3e1cf89b0921423b2024236171955b34afc52b1f25b1dad9da9b001371771d7 -984d3e3a72412d290e3459339757af7520d1739c7af0cbcf659c71999328db44f407d92e8a69fea11625612c49eac927 -ae890d0faf5bd3280dcad20a5f90e23a206661be8842375fea2ab22aadc500849ffbc52fe743b376d46bb926cedae6a6 -b1f231f3f4d710c3fe80099faeb56dac67c1baf53b8fe67a9920fe4f90e52cb9a4bf19211249a6456613b28efe337f18 -8caa54b418ba609d16520af3dff2e96d5f2eeb162c065a1763beb926547b2cfb3ae41d738db2c5681a9bc8bc9e6b9a1a -932157ff56c5ac29cf6cf44f450c882b3acfbb9f43d12d118da3d6256bde4e6eb3183aea304ab6967f37baa718ffec99 -9360bed8fc5b6aac36aa69473040689bfc30411d20ffb7275ef39b9ff5789f9055d149383ce9f0f7709a1f9d683adbfe -98b5b33209068335da72782179d0c7aeeabe94b5560a19d72088fe8323e56db7ce65debe37a97536b6b8a0ca3b840b61 -89a385c11be40064160b030a1bb28c3921fc8078522618a238c7ea0f86f34717ed9af9b4e2e20f5128e5f7fc66ad841e -b615703cbc64b4192990cc7e4903b74aed6a0076ce113b59ef7719197ffa46fb29eb78ca56b49873487432d0625c0faa -90f0d77abae9d3ad73a218e5ccec505ad108ea098451461567ae8ef9661606ca8e78df53b5d628b20b7037bd24622330 -92e0e7cc4dfadc5fa0ee6da0c8de0493030db6e54ba0317f52f232a6708b732068b6077bd13a17eb7eb40b88368085b5 -a24dad20094985bfccc6df1343506ed3bf9dcbdf4b2085a87627a5d71f7568db067304e465f8f380c5c88e8a27291a01 -8629a45a10619354c84bdc2f6c42f540eab5a46f53f2ae11970433d7a2aef007897590bf31dfba1c921614c6d6fe1687 -84ac64040d4206f82b08c771f375da4b7d752e41d2aa0da20ce845f6bc1b880a855d3ee966bca19b8ec327b4b43e7f0e -9608e6050c25996c052509f43f24a85cdf184135f46eaac520a9a6e78e0d44a6cee50ebc054048c708aefde8cd6651c2 -a32032b0e0d7cc35e480c328f315327f9385adb102a708c9ba637878deb74582ae26bb6d6e5f8c9e3a839b0e0154b82a -b7e3c78d63acc6564a49e9f00b0a820b56d4f37a2374af1f7f1d016268011df9e7af0670ed2b0eee961f15aa948328dd -8b88bfdd353acc91ad0d308a43e5fb40da22c228f2fe093c6d6904d70f69c6203f56636ed898b05df51d33f1095ef609 -b1d7a430c51fc857af55047683fc18c453b013527196c5e1bf776819a3dffca802217e9249ae03f084e2ea03ad67fcc2 -80558e28a819ddb5e72e97c54be0f57c173ccf78038d360d190b7f1350a19577b8e3f43fa2f7bf113a228cd3b965b2e4 -b4b2ec44e746c00dfc5661ba2514930934fc805cdc29adc531c02d28ce3cc754414b0485d4ee593232cd1175f357ad66 -b57cee5d32835f76572330f61ccd25a203f0e4a7e5053d32965db283aad92f287645533e8e615137208383ec51b1fd99 -930256086b419a8a6581c52590d0dbd9f8a3564c79424198fca3866b786df2f6098a18c50dc4abd20853a7184b1ce15d -8e75fd01181cffcd618a983492390f486e8c889972a46c1f34a4e1b38f384e8e4efc7e3c18533aa2057da9f9623e2238 -b375d927dd988429f9e2764e5943916131092c394fce13b311baa10f34b023dd3571da02553176091a0738cc23771b9a -b9e28e4c0d0477518034d000e32464852e6951c8db6f64ccdb1d2566f5094716213fbf2fc0e29ac88d0e79f725e3c926 -963981e99392afbd2b8318d5a6b2b0cc69c7f2f2f13f4b38dddbfedb2b0eaf0584aecfcbda20a4c60789c15d77970a58 -a7804e1977aa77c263c7c001afa6cf568032dea940e350d6a58ce4614f1a91c13ae1c78bfea740c229dce2444556976a -8787204177da3cde6d35cd3497fa8774d244f9faa9f4bd91b636a613a32ce2ea0326378cf9c4cf475e73ef751b355c4b -895aeef46a07152a04ec812f1aa1fd431389fa0ef6c6e96a5b833e70ea14073bc9984757a8ee456dbec9788e74e6f0ca -8d17f0e5826783440d1f0ec868003510a4d9952bfe4a638e44a36d94482ac18ba70ef7ff773bdf7a3b62d714dcf0fcba -810d5e36b31310b2e054a666d3b3f7ed16dfcb1765532d87ca2a3920316f0187303c27dd113db145d47e8961062a6c03 -b4e2fb48ae04cf8580bb6a28095076c9b95e5f13122b917328f334d4ac8a8648ce442919e28319a40148987350ab5303 -b85549a313544fa1eb3ceb78473b7d3d717fc85b808de7b79db7dbd0af838ebb020622a7503f1cbacab688dddb648f84 -80665adee057088eae827a5fe904ec3ad77d8843cdce0322d535e0659b4abc74a4d7ddd8a94c27f2def5c34ac2c038ee -ad72fc19c2ce99b5b717e35528fe7d3ac8add340b02ebeb4889d9a94c32f312a0b45ea84d21c54f84cc40ee4958b72e1 -99d530c843dff89a47a5ee8c87303ab18f8a82b0d5b808fca050354b35da5c5a5594d55921c6362d6cc917d75bdc18dc -99c7286c293e1be21c5b2a669dfdfcd5aa587105d2886fc5a8eaf8984da4e907f7d7b8c2362d64a4f1621b077a2a08a0 -b4a39e1a9ed5d80c9563c3ca3fadf76f5478c63a98f4346a61b930c9c733e002f3ff02bc16abfdb53d776184cc3f87ba -9378ea71b941979404c92d01fb70b33fa68d085bf15d60eb1c9fc2b5fcdee6379f5583389a3660a756a50019a2f19a69 -b68e17344a2bc45b8e2e19466b86dc139afefbf9bad2e2e28276a725099ebac7f5763f3cb52002261e3abe45ef51eb1a -819e64dc412b2d194d693b9b3157c1070a226af35c629837df145ea12ad52fa8eabd65b025a63c1fb0726207a58cdde8 -a5e8ff8748419466ff6df5d389125f3d46aedacf44eaf12cbfe2f68d218c7d5ab6de4a8279d13aecc25f3b1d98230894 -91560d54a9715cfda9cf7133ae51c432d0bf7fcbaeb468004994e6838bfc5ddcfa30e4e780667d0c4c0376780b083017 -ae8adb3309cc89d79a55ff74f129bb311fe4f5351a8b87600a87e0c3ba60825f71fccf67eadcf7e4b243c619417540fd -8d92cc1a6baa7bfa96fbce9940e7187b3d142f1888bdcb09bb5c8abf63355e9fb942ac4b4819d9be0e0e822d3e8e2e08 -a6e8b79fdd90c34735bb8fbef02165ccbe55ea726dc203b15e7a015bf311c9cac56efd84d221cc55eaa710ee749dbdfe -a409b151de37bddf39ce5f8aa3def60ee91d6f03ddd533fce9bf7bdbeac618cc982c4f1ffbf6e302b8353d8f28f8c479 -b9693975ef82171b3b9fc318ca296e4fe6110b26cbdfd653418f7754563fa7b6e22d64f8025ee4243483fa321572bfe4 -a039ebe0d9ee4a03ade08e2104ffd7169975b224061924cca2aae71464d250851e9f5f6f6cb288b5bf15df9e252712a6 -b27834db422395bd330e53736a001341ce02c9b148c277dabac67dc422741bfa983c28d47c27e8214cd861f2bad8c6f6 -a2bafaf4e2daf629fd27d7d5ac09fb5efc930ff2ae610f37519808683aa583fe1c6f37207daf73de1d8a164f79a0c981 -b856cee1cfcf5e50db9af4ab0aed3db2f43c936eaea369b5bba65582f61f383c285efbda97b1c068c5d230cbe94f7722 -a61ab205554c0550fa267e46a3d454cd1b0a631646b3df140623ff1bfffaa118e9abe6b62814968cc2a506e9c03ea9a0 -8c78edcd106377b9cbdfa2abd5278724aed0d9e4ae5869b5d2b568fdabb7804c953bae96294fcc70ef3cd52ba2cbe4ed -8570869a9bbf6cc84966545a36586a60be4d694839f367b73dfc40b5f623fc4e246b39b9a3090694aa2e17e652d07fd1 -a905b82c4da8d866a894da72315a95dc98faa3c7b3d809aef18f3b2be4801e736a1b79a406179e8cac8f74d27e71ac52 -a8eb8679ff1a64908515f6720ff69434cb33d63aeb22d565fde506618908b1d37585e3bd4d044fd0838b55787af06b42 -af4d86b2fbd1684a657dffe4210321a71e6ae560c144d44668d1f324dc9630e98348c3d444622a689327c1a59cc169dd -80359c6eab16954559ab0e6a1fee9a0526c45d3cae1a371159a2e3aa9b893afdc3a785c9559a5fd9cd8cd774234bf819 -8d4e5ff81eb5d17bbe8ae6416538ca51a9427ce142b311f5cbb14febbbbb9c1ffc6489fd625b9266264c366c12a9d997 -92e181c66489c5fa063ba2a1a354b6fd3439b8b4365a8c90e42e169bfaa1fb5766bf3e0fe804399d18bc8fbcafb5c3b1 -a9ddf229360a095393885083716cb69c819b2d7cfb100e459c2e6beb999ff04446d1e4a0534832ae3b178cbe29f4f1d3 -8e085ef7d919302a1cc797857b75cff194bdbc1c5216434fa808c3dea0cf666f39d9b00f6d12b409693d7a9bd50a912c -916dc4dc89e5e6acf69e4485a09fc66968f9b292eac61a146df1b750aa3da2425a0743d492179f90a543a0d4cd72c980 -b9cbf17e32c43d7863150d4811b974882da338cf0ed1313765b431b89457021dd1e421eeaa52840ef00551bb630962dc -a6fb875786daec1a91484481787093d8d691dd07e15c9c0c6ae0404bf9dc26083ed15d03c6d3fe03e29f28e20da21269 -a870fcb54b9a029e8086de9b08da8782c64ad2cc2e7fdf955b913d294038bb8136193256b85267e75a4ca205808a76b4 -99883f057e09b88bf0e316f9814c091837fd5c26eeb16fec108c9fed4b7a2bd1c783dac0e4242b5a906621ab606c1e50 -85d89069ca3190577dab39bbec43c16bf6dbca439ad3eebd8f5e9f507d84c3c43e77fd6323224582566a3aa2c8018951 -9363ba219e0003f6e8a9d8937b9e1449e4b2c5cd57194563b758bea39deab88778e8f8e4f7816970a617fb077e1e1d42 -820622f25553c035326145c1d2d537dc9cfd064c2f5bdf6d4ec97814de5fe9a0fbd443345fa2ea0a9d40d81d3936aa56 -87e31110aaf447e70c3316459250e4f7f8c24420c97828f9eb33b22107542c5535bdb48b0e58682dd842edea2886ff08 -95bf80cac6f42029d843d1246588acb40a74802f9e94b2bf69b1833936767e701ef7b0e099e22ab9f20f8c0c4a794b6c -a46ecf612b2763d099b27fb814bd8fdbaee51d6b9ac277ad6f28350b843ce91d701371adfaaf4509400dc11628089b58 -8604decf299fb17e073969708be5befeb1090ab688ad9f3f97a0847a40ea9a11bbcfc7a91e8dc27bc67a155123f3bd02 -8eb765c8dc509061825f3688cb2d78b6fef90cf44db33783d256f09be284bc7282205279725b78882688a514247c4976 -b5c30b2244fa109d66b3a5270b178960fdec47d31e63db0b374b80d2b626409eb76d2e8d1ebf47ef96c166743032fc5e -aab01e76290a7e936989530221646160bf8f64e61e79282e980c8c5dcaaa805ff096efd01d075a2c75917a3f4bf15041 -b9d79671debd0b83d0c7c7c3e64c0fb1274300564b262771f839b49218501e7f38ef80cae1f7e5a3c34acdc74c89dab6 -92c0eaceadf036b3b9dfd2712013aba3dd7c30b7760f501f52141618265baa31840fe77850a7014dc528f71f8cf39ce6 -b3cdd098059980455dd5b1c04182df1bd12fa844a866f02a9f8a86aab95b59945baa9af99f687410bffc5b07153cb23c -b361b73a62f71256b7f6ea8e0f6615e14fc5a06ee98b928ab3c9dd3eef9d9d30070e9855c82b7facb639cacb3401e01f -b9c85fc0f25a3271cf28b1ca900078eaaa66cbab0a3e677606e898ac32781a2dfce4d9cbd07404599e2c3c02fa161c9d -ac5b4fdac2a0b2e6430d9fc72bde4249d72183b197fc7347bb1546ae6f544426686bbe0caec3ee973b6836da5e831c44 -b675aebf24b92e398e166f171a6df442b3f5919b6bee192f31675a5e8eeb77d34c6590a6f0c0857417e0f78cfb085db8 -a9bef942044d8d62e6a40169f7dc7b49e40cd0d77f8678dd7c7bae6f46c46786f9b1e319a3fa408f22a54fd2a4d70804 -a20d19cd917d5102ae9ca0cf532127d2b953aa3303310e8a8c4b3da025dded993a47e3a28e6b02acfadb6d65dc2d41a3 -a47fdb04059b83b2afb86a47b2368bbd7247c337a36d3333b6e5ef2cc9476a92c4907e4c58a845c9ef9b497621e0b714 -94a9e9ffc14b411e11a4ffa59878d59460263589003dc7b6915247c549f67feede279bf3645fdd92379022fb21e3caeb -b92e1177dd9ecdaf1370c71b14954219cf0851f309bc216d5907a4e2e84e0df3457018224150c142cc6bf86644bb4b73 -8bc57fadd68a265b7df9b42227a9c0968db7b1bb50dc12f7d755505779f1ff2c408672b3091e903366acc9ce15d19fb6 -b6b5efbe1ac4e1bd2e8447c45000d09397b772ca5496acc447b881022608a41c4f60388814607a01890190105bee7be3 -95f7c85fd614df968f8ccf8d086579c9e1cec4644ecf06da26e3511cb39635a7326b3cec47bd51cf5646f1c660425e9c -b81765fb319bcdc74b4d608383ccb4af7dd84413b23af637be12e2827a75f7e4bcd14441cf979ed9038ae366fbb6f022 -a120ea76cda8c6c50c97035078f6648afe6537809bdba26e7c9e61de8f3070d2347160f9d34010effbf2ec7e94f5749f -92c1b8631953b40d3cc77eee2c72a064b999c09a9b92c11d8fa7b4072966273901c9dba25f9f79f384d9f11a56f3fc7a -a4b00dc0ab67b2300abc9c516e34daf444d6497b066a90cfe3381ed2812304ed37b14f3b948990443dc6c1cf1bed460c -a9e9f7e13c9f031bc7b9e6f1417c7abcc38894fe7d3f54869ee277afd2efa3e6fb50757dd36c8c94d591e0abdea322cc -84f3e98f831792b5ad14bcfe62a4c9f296476c6087c4c1ec7767fc642fbca141ff6a3deeb8b4d4106a9cda5a9937eea0 -8eb1a7931bbea9a714226fd74b0100ab88355287d9b0a349c095e9b5809b98f237ffd706bce7d67a770da355fb9cec7b -9738ef8739e1742c1f26b51a1621be0b89d37406a370c531e236f635c7064c661818817bb3858908986aa687b28b21be -a9cf3ce8501b003ccaf57552a4c4ec31081e44526d3aa3791d3dc4a7e438a357c0956f93c500356186d8fd4588ffac5e -a7af6a219cca59225839a9de5b19263cb23d75557d448bc7d677b62591a2e068c45e5f4457cceb3e9efa01d0601fc18a -972a24ece5eda7692cbb6fb727f92740451bc1281835e2a02931b2b05824a16b01dbe5edd03a0ed5b441ff25a5cc0188 -b21d1ec7597ce95a42f759c9a8d79c8275d7e29047a22e08150f0f65014702f10b7edce8c03f6e7ab578ce8c3b0ec665 -a13a1c7df341bd689e1f8116b7afc149c1ef39161e778aa7903e3df2569356ad31834fa58ceb191485585ce5ef6835c3 -a57bdb08119dc3bc089b5b2b5383455c4de0c2fcdac2dcfa21c7ac5071a61635ff83eceb7412f53fab42d1a01991de32 -b2968748fa4a6921ee752d97aa225d289f599a7db7a222450e69706533573ded450380c87f8cdd4a8b8c8db1b42b5c97 -8718ec04e0d5f38e3034ecd2f13dfde840add500f43a5e13457a1c73db0d18138f938690c8c315b5bcbeb51e8b9a2781 -82094789e26c4a04f2f30bdb97b9aecca9b756cbd28d22ab3c8bed8afc5b2963340ddfc5a5f505e679bf058cbc5dcbb8 -a35b8a566dd6ab67eddc2467906bffc76c345d508e52e9e4bb407b4f2b2c5f39b31d5a4bf5022f87bf7181dc6be2fe41 -a8c93b1e893d4777c0e3a1b4bef3be90c215781501407c4011457fc3240e13524b4d2bea64a6d0a3efe3f3b0dae9b8ab -877095ad18b1e5870818f7a606127ba1736a0b55b0dbcd281ec307c84b08afc0c9117e3a880fe48bfc225fbf37671a97 -84405ee0421ed2db1add3593df8426a9c1fcc8063e875f5311a917febc193748678dd63171d0c21665fb68b6d786c378 -a52cdc8209c3c310bed15a5db260c4f4d4857f19c10e4c4a4cfe9dfc324dfac851421bb801509cf8147f65068d21603c -8f8a028a70dda7285b664722387666274db92230b09b0672f1ead0d778cee79aae60688c3dfd3a8ed1efdeda5784c9d4 -a0be42fecc86f245a45a8ed132d6efc4a0c4e404e1880d14601f5dce3f1c087d8480bad850d18b61629cf0d7b98e0ae0 -83d157445fc45cb963b063f11085746e93ab40ece64648d3d05e33e686770c035022c14fdf3024b32b321abf498689ad -8a72bbf5a732e2d4f02e05f311027c509f228aef3561fc5edac3ef4f93313845d3a9f43c69f42e36f508efcc64a20be0 -b9ca29b0ec8e41c6a02f54d8c16aebf377982488cbe2ed1753090f2db4f804f6269af03e015d647a82ef06ffaa8cba6c -b4df3858d61bbb5ded1cf0be22a79df65ae956e961fbb56c883e1881c4c21fe642e3f5a0c108a882e553ac59595e3241 -86457d8890ac8858d7bab180ef66851247c2bf5e52bf69a4051d1d015252c389684fcc30bb4b664d42fbf670574ab3a3 -86d5576ea6dfa06d9ebce4cd885450f270c88a283e1e0d29cab27851c14ed2f00355e167b52e1539f1218ad11d8f13dd -883ad1364dc2a92388bfafaa9bc943c55b2f813525831e817a6208c666829a40455dde494eba054b2495a95f7ce69e8a -8942371e6925231c2c603b5f5a882d8404d39f0c7c4232557c2610b21c2c07f145466da798ea78b7932da2b774aa3128 -a799eb71496783cc7faf12c9d9804bf6180699a004b2f07fc5cc36840f63ce7eee7dde9275819a9aa3f8d92dc0d47557 -8eb3fb5c769548ee38c7882f51b959c5d5a42b5935269ccf987d6ddbb25a206e80c6000bcc328af149e0727c0b7c02c0 -8f3910d64e421a8f2d8db4c7b352ba5b3fc519d5663973fea5962efe4364fb74448770df944ef37ffe0382648fb56946 -b41413e0c26ff124cf334dab0dc8e538293d8d519d11cc2d10895a96b2064ac60c7da39f08589b38726cffa4c3f0bfef -b46ef2eb10abae0f35fa4c9c7ee2665e8044b8d9f91988a241da40fd5bbc63166925582151941b400006e28bbc5ba22a -b8baa8b4c420bb572a3b6b85479b67d994c49a7ebfe1274687d946a0d0b36dfed7630cfb897350fa166f5e2eff8f9809 -964b46d359c687e0dcfbdab0c2797fc2bd1042af79b7418795b43d32ffca4de89358cee97b9b30401392ff54c7834f9f -8410d0203d382ebf07f200fd02c89b80676957b31d561b76563e4412bebce42ca7cafe795039f46baf5e701171360a85 -b1a8d5d473c1a912ed88ea5cfa37c2aea5c459967546d8f2f5177e04e0813b8d875b525a79c29cb3009c20e7e7292626 -afaab9a1637429251d075e0ba883380043eaf668e001f16d36737028fded6faa6eeed6b5bb340f710961cee1f8801c41 -aef17650003b5185d28d1e2306b2f304279da50925f2704a6a3a68312f29fe5c2f2939f14e08b0ba9dee06ea950ad001 -97bcc442f370804aa4c48c2f8318d6f3452da8389af9335e187482d2e2b83b9382e5c297dce1a0f02935e227b74e09a3 -8a67a27b199f0bcd02d52a3e32f9b76a486b830ec481a49a4e11807e98408b7052b48581b5dd9f0b3e93052ec45dfb68 -b113bf15f430923c9805a5df2709082ab92dcdf686431bbad8c5888ca71cc749290fa4d4388a955c6d6ee3a3b9bc3c53 -8629ca24440740ce86c212afed406026f4ea077e7aa369c4151b6fa57bca7f33f9d026900e5e6e681ae669fd2bd6c186 -933a528371dcecc1ec6ded66b1c7b516bd691b3b8f127c13f948bfbcda3f2c774c7e4a8fbee72139c152064232103bdf -8568ddd01f81a4df34e5fa69c7f4bb8c3c04274147498156aec2e3bd98ea3e57c8a23503925de8fa3de4184563a2b79e -8160874ec030f30fda8f55bcf62613994ff7ed831e4901c7560eac647182b4a9b43bfaff74b916602b9d6ae3bfcaf929 -ae71c48d48cf9459800cdf9f8e96bc22e2d4e37259e5c92a2b24fbe2c6ca42675e312288603c81762f6ceb15400bc4c9 -b05f39bb83fda73e0559db1fd4a71423938a87ad9f060d616d4f4a6c64bf99472a2cbfb95f88b9257c9630fc21a0b81f -80c8479a640ed7a39e67f2db5ad8dfd28979f5443e8e6c23da8087fc24134d4b9e7c94320ffa4154163270f621188c27 -9969ba20ee29c64cb3285a3433a7e56a0fe4ddc6f3d93e147f49fe021bed4a9315266ebb2fb0eb3036bb02001ae015e6 -a198c89fef2ab88e498703b9021becc940a80e32eb897563d65db57cc714eaa0e79092b09dd3a84cfab199250186edcc -8df14a3db8fe558a54d6120bad87405ba9415a92b08c498812c20416c291b09fed33d1e2fcf698eb14471f451e396089 -81e245ef2649b8a5c8d4b27188dd7e985ef6639090bdc03462c081396cf7fc86ed7d01bfe7e649d2b399255e842bdc21 -8659f622c7ab7b40061bcf7a10144b51ad3ab5348567195924f2944e8c4ce137a37f1ba328e4716c10806f3fb7271689 -a575d610fc8fe09334ca619ecdadf02d468ca71dd158a5a913252ca55ea8d8f9ce4548937c239b9cb8ab752a4d5af24a -94744549cd9f29d99f4c8c663997bdfa90e975b31f1086214245de9c87b0c32209f515a0de64d72d5ef49c09b0a031fa -80a8677862b056df59e350c967a27436c671b65d58854e100115bac9824ba177e94c2a1bfcaa191a071b9cefdbee3989 -91be9a5504ec99922440f92a43fe97ddce2f21b9d94cd3a94c085a89b70c903696cec203bbab6d0a70693ba4e558fb01 -8c5a0087bcd370734d12d9b3ab7bc19e9a336d4b49fc42825b2bfedcd73bb85eb47bf8bb8552b9097cc0790e8134d08c -933aa9e6bd86df5d043e0577a48e17eea3352e23befdbb7d7dcac33b5703d5ace230443ac0a40e23bf95da4cc2313478 -984b7ee4bd081ee06c484db6114c2ce0ba356988efb90f4c46ff85ed2865fb37f56a730166c29ef0ae3345a39cdeae7a -ae830f908ea60276c6c949fb8813e2386cf8d1df26dcf8206aa8c849e4467243e074471380ed433465dc8925c138ea4c -874c1df98d45b510b4f22feff46a7e8ed22cfc3fad2ac4094b53b9e6477c8dfc604976ca3cee16c07906dece471aa6c6 -a603eb60d4c0fb90fa000d2913689126849c0261e6a8649218270e22a994902965a4e7f8c9462447259495fe17296093 -a7c73d759a8ad5e3a64c6d050740d444e8d6b6c9ade6fb31cb660fa93dc4a79091230baccb51c888da05c28cb26f6f3f -a4411b79b6a85c79ea173bd9c23d49d19e736475f3d7d53213c5349ebb94a266d510d12ba52b2ac7a62deaaaec7339b8 -943b84f8bbcee53b06266b5c4cd24d649d972593837fe82b0bf5d5e1bbc1a2bf148e1426c366d7c39ab566b10224cadc -8300012096a8b4cefecc080054bf3ceb0918162ba263c6848860423407796b5eb517170c0bad8e4905ac69a383055a21 -8244a1e3ad41908c6f037e2f8db052e81f281646141334829f36c707f307448b9ab79a7f382a1e8d86f877c90b59271c -8eca1b74687802ecc36a5d39e4516a9dee3de61a2047252d9ed737b49e0090c386e9d792ac004c96337681c7f29a16ad -b70fa47535f0524835039a20036c61e77f66146ad79d3d339214d8744742db41ceeb577c829d000011aeafbb12e09579 -84b3abbce48689f3adbb99889c7fd1f3e15ab455d477e34f5151c5c1c358ed77a5b6a581879f7e0f1f34106e0792e547 -ab45ecb58c0ef0dbce3d16afc6ac281e0d90ec48741ea96a141152647e98fcc87f3a3ff07ba81f3179118453ce123156 -90d231a145ba36a59087e259bbfc019fa369201fcfeaa4347d5fd0a22cd8a716e5a797f3cc357f2779edb08f3b666169 -a4f6074d23c6c97e00130bc05f25213ca4fa76c69ca1ace9dece904a2bdd9d987661f5d55023b50028c444af47ff7a08 -933af884939ad0241f3f1f8e8be65f91d77ac0fb234e1134d92713b7cfb927f1933f164aec39177daa13b39c1370fac8 -80d1db6933ce72091332ae47dc691acb2a9038f1239327b26d08ea9d40aa8f2e44410bbda64f2842a398cbe8f74f770f -a7a08605be2241ccc00151b00b3196d9c0717c4150909a2e9cd05538781231762b6cc6994bebbd4cddae7164d048e7b2 -96db0d839765a8fdbbac03430fa800519e11e06c9b402039e9ae8b6503840c7ecac44123df37e3d220ac03e77612f4e4 -96d70f8e9acd5a3151a8a9100ad94f16c289a31d61df681c23b17f21749c9062622d0a90f6d12c52397b609c6e997f76 -8cf8e22273f7459396ff674749ab7e24c94fe8ab36d45d8235e83be98d556f2b8668ba3a4ec1cb98fac3c0925335c295 -97b7e796a822262abc1a1f5a54cb72a1ea12c6c5824ac34cd1310be02d858a3c3aa56a80f340439b60d100e59c25097d -a48208328b08769737aa1a30482563a4a052aea736539eceab148fa6653a80cb6a80542e8b453f1f92a33d0480c20961 -b612184941413fd6c85ff6aa517b58303b9938958aa85a85911e53ed308778624d77eadb27ccf970573e25d3dfd83df7 -b3717068011648c7d03bbd1e2fc9521a86d2c3ae69113d732c2468880a3b932ebec93596957026477b02842ed71a331b -a0ad363e1352dcf035b03830fef4e27d5fd6481d29d5e8c9d51e851e3862d63cdcbaf8e330d61c1b90886921dac2c6fd -8db409fdacfa4bfdaf01cc87c8e97b53ca3a6e3a526d794eaad1c2023f3df4b888f1bf19fee9a990fe6d5c7c3063f30c -b34d6975310ab15938b75ef15020a165fc849949065d32d912554b51ffa1d3f428a6d1a396cb9329367670391de33842 -9117285e9e6762853fc074b8a92b3923864de2c88c13cea7bab574aaf8cdd324843455d2c3f83c00f91f27c7ecc5592a -b4b2e8f190ea0b60819894710c866bf8578dd1b231ae701d430797cc7ede6e216e8ca6a304f3af9484061563645bf2ab -8c493c6853ab135d96a464815dd06cad8b3e8b163849cdefc23d1f20211685753b3d3e147be43e61e92e35d35a0a0697 -9864d7880f778c42d33cf102c425e380d999d55a975a29c2774cad920dfddb80087a446c4f32ed9a6ab5f22ec6f82af0 -90f67fe26f11ca13e0c72b2c2798c0d0569ed6bc4ce5bbaf517c096e7296d5dd5685a25012f6c6d579af5b4f5d400b37 -a228872348966f26e28a962af32e8fa7388d04bc07cfc0224a12be10757ac7ab16a3387c0b8318fcb0c67384b0e8c1a4 -a9d9d64bba3c03b51acf70aeb746a2712ddafe3b3667ae3c25622df377c2b5504e7ab598263bec835ab972283c9a168b -932128971c9d333f32939a1b46c4f7cf7e9d8417bd08dc5bd4573ccbd6ec5b460ac8880fb7f142f7ef8a40eef76d0c6d -964115e7838f2f197d6f09c06fbb2301d6e27c0ecdf208350cf3b36c748436dac50f47f9f9ac651c09ab7ad7221c7e43 -a5941f619e5f55a9cf6e7f1499b1f1bcddcc7cf5e274efedaaad73a75bc71b1fc5c29cd903f6c69dc9a366a6933ca9d1 -a154bf5eaec096029e5fe7c8bf6c695ae51ace356bb1ad234747776c7e1b406dee2d58864c3f4af84ed69f310974125e -b504e6209d48b0338ab1e4bdab663bac343bb6e0433466b70e49dc4464c1ec05f4a98111fd4450393607510ae467c915 -813411918ea79bdde295393284dc378b9bdc6cfcb34678b9733ea8c041ac9a32c1e7906e814887469f2c1e39287e80f8 -8be0369f94e4d72c561e6edb891755368660208853988647c55a8eed60275f2dd6ee27db976de6ecf54ac5c66aaf0ae6 -a7e2701e55b1e7ea9294994c8ad1c080db06a6fc8710cd0c9f804195dce2a97661c566089c80652f27b39018f774f85e -956b537703133b6ddf620d873eac67af058805a8cc4beb70f9c16c6787bf3cc9765e430d57a84a4c3c9fbdd11a007257 -835ae5b3bb3ee5e52e048626e3ddaa49e28a65cb94b7ecdc2e272ff603b7058f1f90b4c75b4b9558f23851f1a5547a35 -85d67c371d1bf6dc72cca7887fa7c886ce988b5d77dc176d767be3205e80f6af2204d6530f7060b1f65d360a0eaeff30 -a84a6647a10fcef8353769ef5f55a701c53870054691a6e9d7e748cbe417b3b41dbb881bae67adc12cb6596c0d8be376 -87ffe271fc0964cb225551c7a61008d8bcb8b3d3942970dbcc2b9f4f9045a767971880368ea254e2038a3a0b94ecf236 -964bb721c51d43ee7dd67c1a2b7dd2cc672ce8fad78c22dcddb43e6aab48d9a4a7dc595d702aa54a6fb0ffabf01f2780 -a89b3f84bb7dcbe3741749776f5b78a269f6b1bebb8e95d3cc80b834fd2177c6be058d16cacfd0d5e1e35e85cde8b811 -b4314538e003a1587b5592ff07355ea03239f17e75c49d51f32babe8e048b90b046a73357bcb9ce382d3e8fbe2f8e68b -86daf4bf201ae5537b5d4f4d734ed2934b9cf74de30513e3280402078f1787871b6973aa60f75858bdf696f19935a0e2 -b1adf5d4f83f089dc4f5dae9dbd215322fa98c964e2eaa409bf8ca3fa5c627880a014ed209492c3894b3df1c117236c4 -b508d52382c5bac5749bc8c89f70c650bb2ed3ef9dc99619468c387c1b6c9ff530a906dfa393f78f34c4f2f31478508a -a8349a5865cb1f191bebb845dfbc25c747681d769dbffd40d8cedf9c9a62fa2cbc14b64bb6121120dab4e24bef8e6b37 -af0500d4af99c83db8890a25f0be1de267a382ec5e9835e2f3503e1bac9412acf9ff83a7b9385708ef8187a38a37bc77 -b76d57a1c1f85b8a8e1722a47057b4c572800957a6b48882d1fc21309c2e45f648a8db0fcff760d1dbc7732cf37c009b -b93c996cec0d3714667b5a5a5f7c05a7dc00bbc9f95ac8e310626b9e41ae4cc5707fac3e5bd86e1e1f2f6d9627b0da94 -93216fdb864217b4c761090a0921cf8d42649ab7c4da1e009ec5450432564cb5a06cb6e8678579202d3985bd9e941cef -8b8be41105186a339987ae3a5f075fbc91f34b9984d222dfed0f0f85d2f684b56a56ab5dc812a411570491743d6c8b18 -959b72782a6b2469e77fe4d492674cc51db148119b0671bd5d1765715f49fa8a87e907646671161586e84979ef16d631 -86b7fc72fb7e7904ea71d5e66ba0d5d898ace7850985c8cc4a1c4902c5bf94351d23ce62eed45e24321fb02adfa49fc8 -a2f244e7c9aa272cb0d067d81d25e5a3045b80b5a520b49fd5996ece267a7f1bea42e53147bbf153d9af215ea605fc9e -81aa2efa5520eebc894ce909ba5ce3250f2d96baa5f4f186a0637a1eea0080dd3a96c2f9fadf92262c1c5566ddb79bab -b607dd110cfe510d087bcff9a18480ba2912662256d0ab7b1d8120b22db4ad036b2266f46152754664c4e08d0fc583f6 -8f588d5f4837e41312744caac5eee9ddc3ad7085871041694f0b5813edf83dc13af7970f7c9b6d234a886e07fa676a04 -924921b903207783b31016cbec4e6c99e70f5244e775755c90d03a8b769738be3ba61577aca70f706a9c2b80040c9485 -ae0a42a222f1a71cd0d3c69ffb2f04c13e1940cce8efabe032629f650be3ceed6abb79651dbb81cb39a33286eb517639 -a07d7d76460f31f5f0e32e40a5ea908d9d2aebf111ac4fadee67ef6540b916733c35a777dcdc05f6417726ca1f2d57dd -88d7f8a31f8c99794291847d28745e5d0b5d3b9684ca4170b686ffbb5bb521a3ef6746c3c8db22e4250a0cdff7939d96 -849573071fd98c020dc9a8622a9eff221cb9f889bde259e7127a8886b73bef7ad430b87750915658918dcfb6b7b4d8d3 -b12d59f732fa47fad175d6263734da8db89230fd340a46ad1cdee51e577041a5c80bf24cd195593e637daf1a66ef5a98 -abbcfb8a4a6d5e269ee1ac5e277df84416c73ca55ec88317f73608201af25af0cb65b943c54684a5651df3a26e3daca2 -ab157f589bdbaf067a6a7ba7513df0492933855d39f3a081196cf2352e0ddc0162d476c433320366e3df601e0556278d -a86c0619b92e5ae4f7daa876a2abc5ba189156afc2fa05eef464dfa342ba37fc670d0dc308ad3822fcb461ab001bac30 -a3f292946476cfe8d5e544a5325439a00e0165a5f9bf3bb6a53f477baeac7697cc0377745536681aa116f326ce911390 -8aecbbfd442a6a0f01c1c09db5d9d50213eb6f1ff6fab674cde3da06a4edff3ed317e804f78300c22ef70c336123e05d -834ed4b58211fcd647d7bf7c0a3ba9085184c5c856b085e8a0fcd5215c661ef43d36f3f0f6329a9f1370501b4e73b6e4 -a114ea5ad2b402a0de6105e5730907f2f1e458d28ae35144cf49836e0ad21325fe3e755cfb67984ae0a32e65402aad1e -a005f12bed97d71cee288b59afe9affb4d256888727343944a99913980df2c963fe02f218e6ea992f88db693a4498066 -a010f286ab06b966e3b91ff8f1bdbe2fe9ab41a27bc392d5787aa02a46e5080e58c62c7d907818caae9f6a8b8123e381 -857bd6df2ddef04dbc7c4f923e0b1696d3016c8bfed07fdfa28a3a3bd62d89b0f9df49aae81cbb6883d5e7b4fadae280 -b3927030da445bc4756ac7230a5d87412a4f7510581fb422212ce2e8cf49689aca7ba71678743af06d4de4914c5aa4a0 -b86403182c98fcce558d995f86752af316b3b2d53ba32075f71c7da2596747b7284c34a1a87de604fcc71e7e117a8add -98dd19b5527733041689b2a4568edaf6aa0fe1a3dd800c290cda157b171e053648a5772c5d3d4c80e5a795bc49adf12e -88a3c227bb7c9bff383f9ad3f7762245939a718ab85ae6e5e13180b12bf724d42054d3852b421c1cd1b3670baddecb63 -b3cfd9ad66b52bbe57b5fff0fad723434d23761409b92c4893124a574acc1e6b1e14b4ec507661551cbbe05e16db362e -923e1bb482cf421dd77801f9780f49c3672b88508a389b94015fd907888dc647ee9ea8ec8d97131d235d066daf1f42b7 -8d5e16240f04f92aa948181d421006bdbc7b215648fb6554193224d00cf337ebbb958f7548cf01b4d828acffb9fbc452 -8b2b8f18ad0559746f6cda3acca294a1467fb1a3bc6b6371bc3a61a3bfe59418934fa8706f78b56005d85d9cb7f90454 -a9316e2a94d6e31426d2ae7312878ba6baaac40f43e2b8a2fa3ab5a774c6918551554b2dbb23dc82f70ba3e0f60b5b0d -9593116d92cf06b8cd6905a2ce569ee6e69a506c897911f43ae80fc66c4914da209fc9347962034eebbc6e3e0fe59517 -887d89d2b2d3c82b30e8f0acf15f0335532bd598b1861755498610cb2dd41ff5376b2a0bb757cb477add0ce8cfe7a9fc -b514cfe17875ecb790ad055271cc240ea4bda39b6cfa6a212908849c0875cb10c3a07826550b24c4b94ea68c6bb9e614 -a563d5187966d1257d2ed71d53c945308f709bcc98e3b13a2a07a1933dc17bcb34b30796bd68c156d91811fbd49da2cb -a7195ccc53b58e65d1088868aeeb9ee208103e8197ad4c317235bb2d0ad3dc56cb7d9a7186416e0b23c226078095d44c -a838e7a368e75b73b5c50fbfedde3481d82c977c3d5a95892ac1b1a3ea6234b3344ad9d9544b5a532ccdef166e861011 -9468ed6942e6b117d76d12d3a36138f5e5fb46e3b87cf6bb830c9b67d73e8176a1511780f55570f52d8cdb51dcf38e8c -8d2fc1899bc3483a77298de0e033085b195caf0e91c8be209fd4f27b60029cbe1f9a801fbd0458b4a686609762108560 -8f4e44f8ca752a56aa96f3602e9234ad905ad9582111daf96a8c4d6f203bf3948f7ce467c555360ad58376ee8effd2ba -8fb88640b656e8f1c7c966c729eb2ba5ccf780c49873f8b873c6971840db7d986bdf1332ba80f8a0bb4b4ee7401468fa -b72aa3235868186913fb5f1d324e748cd3ce1a17d3d6e6ea7639a5076430fe0b08841c95feb19bb94181fe59c483a9eb -b8b102690ebb94fc4148742e7e3fd00f807b745b02cbe92cd92992c9143b6db7bb23a70da64a8b2233e4a6e572fc2054 -8c9ae291f6cd744e2c6afe0719a7fc3e18d79307f781921fb848a0bf222e233879c1eca8236b4b1be217f9440859b6ce -a658ede47e14b3aad789e07f5374402f60e9cacb56b1b57a7c6044ca2418b82c98874e5c8c461898ebd69e38fecd5770 -89c0cb423580e333923eb66bda690f5aca6ec6cba2f92850e54afd882ba608465a7dbb5aa077cd0ca65d9d00909348ab -aed8e28d98d5508bd3818804cf20d296fe050b023db2ed32306f19a7a3f51c7aaafed9d0847a3d2cd5ba5b4dabbc5401 -96a0fcd6235f87568d24fb57269a94402c23d4aa5602572ad361f3f915a5f01be4e6945d576d51be0d37c24b8b0f3d72 -935d0c69edd5dfa8ed07c49661b3e725b50588f814eb38ea31bcc1d36b262fae40d038a90feff42329930f8310348a50 -900518288aa8ea824c7042f76710f2ea358c8bb7657f518a6e13de9123be891fa847c61569035df64605a459dad2ecc8 -947d743a570e84831b4fb5e786024bd752630429d0673bf12028eb4642beb452e133214aff1cfa578a8856c5ebcb1758 -a787266f34d48c13a01b44e02f34a0369c36f7ec0aae3ec92d27a5f4a15b3f7be9b30b8d9dd1217d4eeedff5fd71b2e5 -a24b797214707ccc9e7a7153e94521900c01a1acd7359d4c74b343bfa11ea2cdf96f149802f4669312cd58d5ab159c93 -97f5ee9c743b6845f15c7f0951221468b40e1edaef06328653a0882793f91e8146c26ac76dd613038c5fdcf5448e2948 -80abd843693aed1949b4ea93e0188e281334163a1de150c080e56ca1f655c53eb4e5d65a67bc3fc546ed4445a3c71d00 -908e499eb3d44836808dacff2f6815f883aeced9460913cf8f2fbbb8fe8f5428c6fc9875f60b9996445a032fd514c70f -ae1828ef674730066dc83da8d4dd5fa76fc6eb6fa2f9d91e3a6d03a9e61d7c3a74619f4483fe14cddf31941e5f65420a -a9f4dbe658cd213d77642e4d11385a8f432245b098fccd23587d7b168dbeebe1cca4f37ee8d1725adb0d60af85f8c12f -93e20ee8a314b7772b2439be9d15d0bf30cd612719b64aa2b4c3db48e6df46cea0a22db08ca65a36299a48d547e826a7 -a8746a3e24b08dffa57ae78e53825a9ddbbe12af6e675269d48bff4720babdc24f907fde5f1880a6b31c5d5a51fbb00e -b5e94dfab3c2f5d3aea74a098546aa6a465aa1e3f5989377d0759d1899babf543ad688bb84811d3e891c8713c45886c5 -a3929bada828bd0a72cda8417b0d057ecb2ddd8454086de235540a756e8032f2f47f52001eb1d7b1355339a128f0a53b -b684231711a1612866af1f0b7a9a185a3f8a9dac8bde75c101f3a1022947ceddc472beb95db9d9d42d9f6ccef315edbc -af7809309edbb8eb61ef9e4b62f02a474c04c7c1ffa89543d8c6bf2e4c3d3e5ecbd39ec2fc1a4943a3949b8a09d315a6 -b6f6e224247d9528ef0da4ad9700bee6e040bbf63e4d4c4b5989d0b29a0c17f7b003c60f74332fefa3c8ddbd83cd95c1 -adbcec190a6ac2ddd7c59c6933e5b4e8507ce5fd4e230effc0bd0892fc00e6ac1369a2115f3398dfc074987b3b005c77 -8a735b1bd7f2246d3fa1b729aecf2b1df8e8c3f86220a3a265c23444bdf540d9d6fe9b18ed8e6211fad2e1f25d23dd57 -96b1bf31f46766738c0c687af3893d098d4b798237524cb2c867ed3671775651d5852da6803d0ea7356a6546aa9b33f2 -8036e4c2b4576c9dcf98b810b5739051de4b5dde1e3e734a8e84ab52bc043e2e246a7f6046b07a9a95d8523ec5f7b851 -8a4f4c32ee2203618af3bb603bf10245be0f57f1cfec71037d327fa11c1283b833819cb83b6b522252c39de3ce599fa5 -ad06ed0742c9838e3abaaffdb0ac0a64bad85b058b5be150e4d97d0346ed64fd6e761018d51d4498599669e25a6e3148 -8d91cb427db262b6f912c693db3d0939b5df16bf7d2ab6a7e1bc47f5384371747db89c161b78ff9587259fdb3a49ad91 -ae0a3f84b5acb54729bcd7ef0fbfdcf9ed52da595636777897268d66db3de3f16a9cf237c9f8f6028412d37f73f2dfad -8f774109272dc387de0ca26f434e26bc5584754e71413e35fa4d517ee0f6e845b83d4f503f777fe31c9ec05796b3b4bc -a8670e0db2c537ad387cf8d75c6e42724fae0f16eca8b34018a59a6d539d3c0581e1066053a2ec8a5280ffabad2ca51f -ac4929ed4ecad8124f2a2a482ec72e0ef86d6a4c64ac330dab25d61d1a71e1ee1009d196586ce46293355146086cabba -845d222cb018207976cc2975a9aa3543e46c861486136d57952494eb18029a1ebb0d08b6d7c67c0f37ee82a5c754f26f -b99fa4a29090eac44299f0e4b5a1582eb89b26ed2d4988b36338b9f073851d024b4201cd39a2b176d324f12903c38bee -9138823bc45640b8f77a6464c171af2fe1700bdc2b7b88f4d66b1370b3eafe12f5fbb7b528a7e1d55d9a70ca2f9fc8e6 -8ac387dc4cf52bc48a240f2965ab2531ae3b518d4d1f99c0f520a3d6eb3d5123a35ef96bed8fa71ee2f46793fa5b33b3 -864adec6339d4c2ba2525621fceabd4c455902f6f690f31a26e55413e0722e5711c509dc47ce0bcc27bbdc7651768d2d -a0a52edb72268a15201a968dabc26a22909620bda824bd548fb8c26cc848f704166ed730d958f0173bd3b0a672f367bd -949e445b0459983abd399571a1a7150aab3dd79f4b52a1cd5d733e436c71c1d4b74287c6b0ce6cc90c6711ba4c541586 -858966355dac11369e3b6552f2b381665181693d5a32e596984da3314021710b25a37d8c548b08700eea13d86cb22f21 -974bcbb8d38c5e6518745cc03ad436e585b61f31d705e7e2e5085da9655d768ac4d800904f892c3dab65d6223e3f1fd6 -8092b6506b01308bf6187fde5ebd4fa7448c9a640961ba231be22ac5fa2c7635ef01e8b357722c7695d09b723101ea2a -a5b8ef360bf28533ee17d8cd131fff661d265f609db49599085c0c7d83b0af409a1b5c28e3a5e5d7f8459a368aa121e8 -b031b6d5e3ceab0f0c93314b3b675f55cf18cbc86f70444af266fe39cb22fd7dad75d8c84e07f1c1bfa2cb8283e1361a -93ad489e4f74658320c1cceed0137c023d3001a2c930ed87e6a21dbf02f2eb6ad1c1d8bcb3739c85dcfbecb040928707 -b15e4ec2cdab0d34aec8d6c50338812eb6ecd588cf123a3e9d22a7ca23b5a98662af18289f09e6cdd85a39a2863c945c -b304f71a9717cf40c22073f942618b44bf27cd5e2ed4a386ad45d75b0fcb5a8dafd35158211eaf639495c6f1a651cedb -b82d78d3eaaa7c5101b7a5aae02bd4f002cd5802d18c3abcda0dd53b036661c6d3c8b79e0abe591eab90b6fdc5fef5e3 -abbd1884243a35578b80914a5084449c237ee4e4660c279d1073a4d4217d1b55c6b7e9c087dfd08d94ac1416273d8d07 -92f4b61c62502745e3e198ec29bca2e18696c69dcb914d1f3a73f4998d012b90caf99df46e9bb59942e43cce377fe8fd -906e79df98185820c8208844e1ba6bd86cb96965814b01310bd62f22cbec9b5d379b2ef16772d6fc45a421b60cfd68fe -a0eae2784ef596e2eb270dd40c48d6c508e4394c7d6d08d4cc1b56fde42b604d10ba752b3a80f2c4a737e080ef51b44f -94c084985e276dc249b09029e49a4ef8a369cd1737b51c1772fbb458d61e3fe120d0f517976eba8ffa5711ba93e46976 -83619a0157eff3f480ab91d1d6225fead74c96a6fd685333f1e8e4d746f6273e226bad14232f1d1168a274e889f202f1 -a724fe6a83d05dbbf9bb3f626e96db2c10d6d5c650c0a909415fbda9b5711c8b26e377201fb9ce82e94fa2ab0bf99351 -a8a10c1b91a3a1fa2d7fd1f78a141191987270b13004600601d0f1f357042891010717319489f681aa8a1da79f7f00d5 -a398a2e95b944940b1f8a8e5d697c50e7aa03994a8a640dfad4ea65cfb199a4d97861a3ec62d1c7b2b8d6e26488ca909 -a2eedfe5452513b2a938fffd560798ef81379c5a5032d5b0da7b3bb812addbaad51f564c15d9acbbfc59bb7eddd0b798 -ab31c572f6f145a53e13b962f11320a1f4d411739c86c88989f8f21ab629639905b3eedb0628067942b0dc1814b678ca -ad032736dd0e25652d3566f6763b48b34ea1507922ed162890cd050b1125ec03b6d41d34fccba36ec90336f7cdf788ed -83028a558a5847293147c483b74173eca28578186137df220df747fccd7d769528d7277336ea03c5d9cdd0bc5ae3d666 -ab5d182cd1181de8e14d3ef615580217c165e470b7a094a276b78a3003089123db75c6e1650bf57d23e587c587cd7472 -a4793e089fbdb1597654f43b4f7e02d843d4ab99ee54099c3d9f0bd5c0c5657c90bb076379a055b00c01b12843415251 -98bdc52ee062035356fb2b5c3b41673198ddc60b2d1e546cb44e3bb36094ef3c9cf2e12bbc890feb7d9b15925439d1ea -a4f90cca6f48024a0341bd231797b03693b34e23d3e5b712eb24aba37a27827319b2c16188f97c0636a0c115381dc659 -8888e6c2e4a574d04ba5f4264e77abc24ccc195f1a7e3194169b8a2ceded493740c52db4f9833b3dbf4d67a3c5b252cb -83dc4e302b8b0a76dc0292366520b7d246d73c6aebe1bdd16a02f645c082197bcff24a4369deda60336172cefbcf09af -a4eb2741699febfeb793914da3054337cc05c6fa00d740e5f97cb749ae16802c6256c9d4f0f7297dcdbb8b9f22fc0afa -8b65557d5be273d1cb992a25cfce40d460c3f288d5cb0a54bdef25cbd17cdea5c32ec966e493addf5a74fd8e95b23e63 -97c6577e76c73837bcb398b947cb4d3323d511141e0ddd0b456f59fbb1e8f920a5c20d7827a24309145efddee786140f -abcc0849ffe2a6a72157de907907b0a52deece04cf8317bee6fe1d999444b96e461eac95b6afde3d4fe530344086a625 -9385c0115cb826a49df1917556efa47b5b5e4022b6a0d2082053d498ec9681da904ecf375368bb4e385833116ea61414 -8b868c1841f0cdc175c90a81e610b0652c181db06731f5c8e72f8fafa0191620742e61a00db8215a991d60567b6a81ca -a8df15406f31b8fcf81f8ff98c01f3df73bf9ec84544ddec396bdf7fafa6fe084b3237bf7ef08ad43b26517de8c3cd26 -a9943d21e35464ce54d4cc8b135731265a5d82f9ccf66133effa460ffdb443cdb694a25320506923eede88d972241bf2 -a1378ee107dd7a3abcf269fd828887c288363e9b9ca2711377f2e96d2ed5e7c5ec8d3f1da995a3dcbedf1752d9c088fc -8a230856f9227b834c75bdebc1a57c7298a8351874bf39805c3e0255d6fd0e846f7ad49709b65ec1fd1a309331a83935 -877bcf42549d42610e1780e721f5800972b51ba3b45c95c12b34cb35eeaf7eac8fa752edd7b342411820cf9093fea003 -84c7a0b63842e50905624f1d2662506b16d1f3ea201877dfc76c79181c338b498eceb7cad24c2142c08919120e62f915 -8e18b1bd04b1d65f6ed349b5d33a26fe349219043ead0e350b50ae7a65d6ff5f985dd9d318d3b807d29faa1a7de4fe42 -8ea7b5a7503e1f0b3c3cd01f8e50207044b0a9c50ed1697794048bbe8efd6659e65134d172fb22f95439e1644f662e23 -b1954a2818cad1dad6d343a7b23afa9aa8ad4463edc4eb51e26e087c2010927535020d045d97d44086d76acdb5818cbf -a5271ea85d0d21fa1ff59b027cf88847c0f999bbf578599083ff789a9b5228bc161e1c81deb97e74db1a82a0afd61c50 -aa2fa4c05af3387e2c799315781d1910f69977ec1cfea57a25f1a37c63c4daaa3f0ecd400884a1673e17dd5300853bcf -b1cd2a74ca0b8e6090da29787aef9b037b03b96607983a308b790133bd21297b21ca4e2edec890874096dbf54e9d04c3 -801931607ec66a81272feaa984f0b949ad12d75ecf324ba96627bd4dc5ddead8ebf088f78e836b6587c2b6c0b3366b6c -95d79504710bdf0ad9b9c3da79068c30665818c2f0cdbba02cc0a5e46e29d596032ac984441b429bd62e34535c8d55b0 -9857d41e25e67876510ff8dadf0162019590f902da1897da0ef6fc8556e3c98961edb1eb3a3a5c000f6c494413ded15e -8740c9ffe6bd179c19a400137c3bd3a593b85bd4c264e26b4dfb9e2e17ac73e5b52dfacc1dcb4033cfc0cd04785f4363 -977f98f29d948b4097a4abdf9345f4c1fb0aa94ba0c6bf6faa13b76f3a3efc8f688e1fe96099b71b3e1c05041118c8d1 -a364422b1239126e3e8d7b84953ce2181f9856319b0a29fcab81e17ac27d35798088859c1cfc9fc12b2dbbf54d4f70b3 -a0f6ba637f0db7a48e07439bb92ddb20d590ce9e2ed5bab08d73aa22d82c32a9a370fe934cbe9c08aeb84b11adcf2e0e -a2c548641bd5b677c7748327cca598a98a03a031945276be6d5c4357b6d04f8f40dd1c942ee6ec8499d56a1290ac134d -9863e9cc5fbcdbd105a41d9778d7c402686bfd2d81d9ed107b4fda15e728871c38647529693306855bee33a00d257a7e -a54173bf47b976290c88fd41f99300135de222f1f76293757a438450880e6f13dbde3d5fe7afc687bdfbcfc4fbc1fc47 -b8db413917c60907b73a997b5ab42939abd05552c56a13525e3253eb72b83f0d5cc52b695968a10005c2e2fe13290e61 -a1f8388ef21697c94ba90b1a1c157f0dc138e502379e6fc5dc47890d284563e5db7716266e1b91927e5adf3cde4c0a72 -9949013a59d890eb358eab12e623b2b5edb1acbee238dfad8b7253102abc6173922e188d5b89ec405aa377be8be5f16d -a00fdb7710db992041f6ddb3c00099e1ce311dea43c252c58f560c0d499983a89de67803a8e57baa01ee9d0ee6fa1e44 -a8b1bcbed1951c9cdb974b61078412881b830b48cd6b384db0c00fa68bcc3f4312f8e56c892ea99d3511857ef79d3db9 -8f3ee78404edc08af23b1a28c2012cee0bdf3599a6cb4ea689fc47df4a765ef519191819a72562b91a0fbcdb896a937e -8155bbb7fa8d386848b0a87caae4da3dec1f3dade95c750a64a8e3555166ccc8799f638bd80ed116c74e3a995541587a -abfe30adbc0a6f1fd95c630ed5dac891b85384fa9331e86b83217f29dff0bd7cad19d328485715a7e3df9a19069d4d2f -89d0783e496ee8dbb695764b87fb04cee14d4e96c4ba613a19736971c577d312079048142c12ce5b32b21e4d491d281b -856b8dbc9c5d8f56b6bb7d909f339ca6da9a8787bba91f09130a025ab6d29b64dbf728ba6ed26e160a23c1cdb9bc037b -8a30dd2ea24491141047a7dfe1a4af217661c693edf70b534d52ca547625c7397a0d721e568d5b8398595856e80e9730 -ae7e1412feb68c5721922ed9279fb05549b7ef6812a4fd33dbbbd7effab756ab74634f195d0c072143c9f1fd0e1ee483 -b7ce970e06fa9832b82eef572f2902c263fda29fdce9676f575860aae20863046243558ede2c92343616be5184944844 -85ed0531f0e5c1a5d0bfe819d1aa29d6d5ff7f64ad8a0555560f84b72dee78e66931a594c72e1c01b36a877d48e017ca -b8595be631dc5b7ea55b7eb8f2982c74544b1e5befc4984803b1c69727eac0079558182f109e755df3fd64bee00fcaa5 -99e15a66e5b32468ef8813e106271df4f8ba43a57629162832835b8b89402eb32169f3d2c8de1eb40201ce10e346a025 -844c6f5070a8c73fdfb3ed78d1eddca1be31192797ad53d47f98b10b74cc47a325d2bc07f6ee46f05e26cf46a6433efb -974059da7f13da3694ad33f95829eb1e95f3f3bfc35ef5ef0247547d3d8ee919926c3bd473ab8b877ff4faa07fcc8580 -b6f025aecc5698f6243cc531782b760f946efebe0c79b9a09fe99de1da9986d94fa0057003d0f3631c39783e6d84c7d5 -b0c5358bc9c6dfe181c5fdf853b16149536fbb70f82c3b00db8d854aefe4db26f87332c6117f017386af8b40288d08f9 -a3106be5e52b63119040b167ff9874e2670bd059b924b9817c78199317deb5905ae7bff24a8ff170de54a02c34ff40a4 -ad846eb8953a41c37bcd80ad543955942a47953cbc8fb4d766eac5307892d34e17e5549dc14467724205255bc14e9b39 -b16607e7f0f9d3636e659e907af4a086ad4731488f5703f0917c4ce71a696072a14a067db71a3d103530920e1ec50c16 -8ed820e27116e60c412c608582e9bb262eaaf197197c9b7df6d62b21a28b26d49ea6c8bb77dfde821869d9b58025f939 -97bc25201d98cde389dd5c0c223a6f844393b08f75d3b63326343073e467ac23aacef630ddc68545ea874299ba4a3b4f -b73c9695ad2eefd6cc989a251c433fab7d431f5e19f11d415a901762717d1004bb61e0cc4497af5a8abf2d567e59fef4 -adaabe331eea932533a7cc0cf642e2a5e9d60bbc92dd2924d9b429571cbf0d62d32c207b346607a40643c6909b8727e2 -a7b1bbfe2a5e9e8950c7cb4daab44a40c3ffab01dc012ed7fe445f4af47fa56d774a618fafe332ab99cac4dfb5cf4794 -b4a3c454dcd5af850212e8b9ba5fe5c0d958d6b1cabbf6c6cfe3ccbc4d4c943309c18b047256867daf359006a23f3667 -a5c0b32f6cef993834c1381ec57ad1b6f26ae7a8190dd26af0116e73dadc53bb0eeb1911419d609b79ce98b51fdc33bc -ac2f52de3ecf4c437c06c91f35f7ac7d171121d0b16d294a317897918679f3b9db1cef3dd0f43adb6b89fe3030728415 -94722ae6d328b1f8feaf6f0f78804e9b0219de85d6f14e8626c2845681841b2261d3e6a2c5b124086b7931bf89e26b46 -a841a0602385d17afabca3a1bb6039167d75e5ec870fea60cfcaec4863039b4d745f1a008b40ec07bca4e42cb73f0d21 -8c355f0a1886ffced584b4a002607e58ff3f130e9de827e36d38e57cb618c0cb0b2d2dea2966c461cb3a3887ede9aef1 -a6a9817b0fc2fd1786f5ba1a7b3d8595310987fb8d62f50a752c6bb0b2a95b67d03a4adfd13e10aa6190a280b7ee9a67 -a1d2e552581ecbafeaef08e389eaa0b600a139d446e7d0648ac5db8bbbf3c438d59497e3a2874fc692b4924b87ff2f83 -a1b271c55389f25639fe043e831e2c33a8ba045e07683d1468c6edd81fedb91684e4869becfb164330451cfe699c31a8 -8c263426e7f7e52f299d57d047a09b5eeb893644b86f4d149535a5046afd655a36d9e3fdb35f3201c2ccac2323a9582e -b41c242a7f7880c714241a97d56cce658ee6bcb795aec057a7b7c358d65f809eb901e0d51256826727dc0dc1d1887045 -93001b9445813c82f692f94c0dc1e55298f609936b743cf7aae5ebfa86204f38833d3a73f7b67314be67c06a1de5682d -82087536dc5e78422ad631af6c64c8d44f981c195ddea07d5af9bb0e014cdc949c6fa6e42fce823e0087fdb329d50a34 -8e071861ceba2737792741c031f57e0294c4892684506b7c4a0fc8b2f9a0a6b0a5635de3d1e8716c34df0194d789ae86 -b471c997e1e11774bd053f15609d58838a74073a6c089a7a32c37dd3f933badf98c7e5833263f3e77bc0d156a62dd750 -8d2d8686fb065b61714414bb6878fff3f9e1e303c8e02350fd79e2a7f0555ded05557628152c00166ce71c62c4d2feaa -ae4c75274d21c02380730e91de2056c0262ffcecf0cbdb519f0bdb0b5a10ae2d4996b3dc4b3e16dbaea7f0c63d497fef -97140d819e8ca6330e589c6debdee77041c5a9cedb9b8cbd9c541a49207eeb7f6e6b1c7e736ec8ba6b3ab10f7fcd443a -af6659f31f820291a160be452e64d1293aa68b5074b4c066dac169b8d01d0179139504df867dc56e2a6120354fc1f5be -a5e5d8088a368024617bfde6b731bf9eee35fc362bed3f5dfdd399e23a2495f97f17728fec99ca945b3282d1858aa338 -a59cfc79d15dbdde51ab8e5129c97d3baba5a0a09272e6d2f3862370fdbaf90994e522e8bd99d6b14b3bb2e9e5545c6f -a30499b068083b28d6c7ddcc22f6b39b5ec84c8ee31c5630822c50ea736bb9dca41c265cffc6239f1c9ef2fd21476286 -88ffe103eca84bbe7d1e39a1aa599a5c7c9d5533204d5c4e085402a51441bb8efb8971efe936efbbfa05e5cb0d4b8017 -b202356fbf95a4d699154639e8cb03d02112c3e0128aab54d604645d8510a9ba98936028349b661672c3a4b36b9cb45d -8b89bb6574bf3524473cff1ff743abcf1406bd11fb0a72070ccd7d8fce9493b0069fb0c6655252a5164aee9e446ea772 -93247b1038fa7e26667ee6446561d4882dc808d1015daafb705935ddc3598bb1433182c756465960480f7b2de391649e -b027f94d3358cbb8b6c8c227300293a0dee57bf2fee190a456ad82ecfb6c32f8090afa783e2ab16f8139805e1fb69534 -a18bb1849b2f06c1d2214371031d41c76ffa803ee3aa60920d29dbf3db5fbfac2b7383d5d0080ba29ce25c7baa7c306b -827bf9fd647e238d5ac961c661e5bbf694b4c80b3af8079f94a2484cb8fba2c8cf60e472ebcd0b0024d98ae80ad2ff5a -838e891218c626a7f39b8fd546b013587408e8e366ecc636b54f97fa76f0a758bc1effa1d0f9b6b3bc1a7fcc505970a0 -836523b5e8902d6e430c6a12cff01e417d2bd7b402e03904034e3b39755dee540d382778c1abe851d840d318ebedce7f -850a77dda9ac6c217e2ef00bf386a1adec18b7f462f52801c4f541215690502a77ef7519b690e22fdf54dc2109e0ca38 -a8265c6ae7b29fc2bda6a2f99ced0c1945dd514b1c6ca19da84b5269514f48a4f7b2ccbab65c9107cfd5b30b26e5462f -ab3d02ee1f1267e8d9d8f27cc388e218f3af728f1de811242b10e01de83471a1c8f623e282da5a284d77884d9b8cde0e -831edaf4397e22871ea5ddee1e7036bab9cc72f8d955c7d8a97f5e783f40532edbbb444d0520fefcffeab75677864644 -80484487977e4877738744d67b9a35b6c96be579a9faa4a263e692295bb6e01f6e5a059181f3dd0278e2c3c24d10a451 -aae65a18f28c8812617c11ecf30ad525421f31fb389b8b52d7892415e805a133f46d1feca89923f8f5b8234bd233486a -b3a36fd78979e94288b4cefed82f043a7e24a4a8025479cc7eb39591e34603048a41ee606ee03c0b5781ebe26a424399 -b748b3fc0d1e12e876d626a1ba8ad6ad0c1f41ea89c3948e9f7d2666e90173eb9438027fadcd741d3ae0696bd13840f1 -acdd252d7c216c470683a140a808e011c4d5f1b4e91aeb947f099c717b6a3bad6651142cde988330827eb7d19d5fb25c -b9a25556a6ca35db1ed59a1ec6f23343eab207a3146e4fc3324136e411c8dba77efd567938c63a39c2f1c676b07d8cdb -a8db6aef8f5680d2bdb415d7bcaae11de1458678dcb8c90c441d5986c44f83a9e5855662d0c1aace999172d8628d8fe1 -af58147108e9909c3a9710cc186eab598682dca4bfd22481e040b8c000593ecb22c4ede4253ac9504e964dfa95a9b150 -8dd8bb70f1c9aec0fcc9478f24dfc9c3c36c0bf5ff7a67c017fa4dab2ec633fbd7bc9d8aa41ea63e2696971ed7e375f5 -aa98d600b22aff993a4d7a3ccabd314e1825b200cb598f6b797d7e4d6a76d89e34a4d156c06bddfc62f2ef9b4c809d1d -8a8fc960d6c51294b8205d1dabe430bef59bda69824fa5c3c3105bef22ac77c36d2d0f38ffc95ce63731de5544ccbeff -b6d1020efe01dc8032bd1b35e622325d7b9af9dcd5c9c87c48d7d6ebc58644454294c59b7f4b209204b5b1f899f473bf -8a750dc9fe4891f2dfe5759fb985939810e4cdc0b4e243ff324b6143f87676d8cb4bcb9dfb01b550801cedcaaa5349e2 -98c13142d3a9c5f8d452245c40c6dae4327dd958e0fda85255ea0f87e0bcbaa42a3a0bd50407ed2b23f9f6317a8a4bc5 -99f2b83d9ec4fc46085a6d2a70fd0345df10f4a724c1ba4dee082a1fde9e642e3091992ebf5f90a731abcb6ec11f6d9b -b218546ab2db565b2489ea4205b79daa19ef2acbf772ccaaa5e40150e67ea466090d07198444b48e7109939aa2319148 -84f9d1d868e4b55e535f1016558f1789df0daa0ead2d13153e02f715fe8049b1ce79f5bc1b0bbbb0b7e4dd3c04783f3f -80d870d212fbddfdda943e90d35a5a8aa0509a7a1e7f8909f2fcb09c51c3026be47cc7a22620a3063406872105b4f81a -b5b15138ff6551fac535d4bbce2ea6adc516b6b7734b4601c66ec029da2615e3119dc9ad6a937344acfd7b50e4a1a2ae -95d2f97652086e7ceb54e1d32692b1c867ffba23c4325740c7f10d369283d1b389e8afa0df967831ade55696931e7934 -8a5b580403e1a99cd208f707e8ce0d3f658c8280417683f69008d09cc74d835a85f7380f391b36ead9ac66d9eedd1cbe -a8b0c90bff34c86720637b5a2081f0f144cfe2205c1176cacd87d348609bc67af68aed72414dc9aa6f44a82c92c2a890 -865abbdd96c496892c165a8de0f9e73348bf24fce361d7a9048710178a3625881afb0006e9f5ee39124866b87904c904 -ace67bb994adef4b6f841cdf349195608030044562780a7e9b00b58a4ff117268a03ff01e5a3a9d9d7eff1dd01f5f4bf -b9371d59185b3d2d320d3fefeadb06ba2aa7d164352fb8dc37571509509fa214d736d244ac625a09a033a10d51611e2e -a8ef992771422dcf2d6d84386fde9fe5dba88bfded3dfcd14074ca04331b4fd53a7f316615cdfaf10ed932cbb424a153 -868cbc75f8f789ea45eded2768a1dac0763347e0d8e8028d316a21005f17be179d26d5965903e51b037f2f57fe41765d -b607111bcdfd05fa144aa0281b13ee736079ebbbf384d938a60e5e3579639ed8ef8eb9ca184868cdb220a8e130d4a952 -aca55702af5cae4cae65576769effd98858307a71b011841c563b97c2aa5aeb5c4f8645d254f631ed1582df3dbbf17da -b9b5cbace76246e80c20dfcc6f1e2c757a22ab53f7fd9ff8a1d309538b55174e55e557a13bf68f095ff6a4fa637ef21a -8571b0a96871f254e2397c9be495c76379faf347801cb946b94e63212d6a0da61c80e5d7bebbabcd6eaa7f1029172fe5 -902540326281e6dc9c20d9c4deaaf6fbbbcc3d1869bd0cf7f081c0525bea33df5cfa24ead61430fda47fb964fcc7994b -841af09279d3536a666fa072278950fabf27c59fc15f79bd52acb078675f8087f657929c97b4bc761cbade0ecb955541 -a1f958b147ddf80ab2c0746ba11685c4bae37eb25bfa0442e7e1078a00d5311d25499da30f6d168cb9302ea1f2e35091 -863d939381db37d5a5866964be3392a70be460f0353af799d6b3ed6307176972686bd378f8ad457435a4094d27e8dfb7 -835cd4d7f36eff553d17483eb6c041b14280beb82c7c69bca115929658455a1931212976c619bafb8179aed9940a8cc6 -8d0770e3cb8225e39c454a1fc76954118491b59d97193c72c174ecc7613051e5aed48a534016a8cf0795c524f771a010 -91aa4edb82f6f40db2b7bd4789cc08786f6996ebed3cb6f06248e4884bc949793f04a4c5ea6eefe77984b1cc2a45d699 -8fb494ca2449f659ff4838833507a55500a016be9293e76598bbae0a7cb5687e4693757c2b6d76e62bd6c7f19ed080bb -b59b104449a880a282c1dd6a3d8debb1d8814ef35aab5673c1e500ee4cb0e840fb23e05fa5a0af92509c26b97f098f90 -aca908e3bad65e854ae6be6c5db441a06bcd47f5abafdfa8f5a83c8cd3c6e08c33cab139c45887887a478338e19ceb9f -806f5d802040313a31964fc3eb0ee18ac91b348685bed93c13440984ee46f3d2da7194af18c63dea4196549129660a4e -ae4b2dca75c28d8f23b3ab760b19d839f39ff5a3112e33cb44cff22492604a63c382b88ec67be4b0266924dd438c3183 -99d1c29c6bd8bf384e79cd46e30b8f79f9cbc7d3bf980e9d6ffba048f0fc487cac45c364a8a44bb6027ad90721475482 -a16e861c1af76d35528c25bf804bfc41c4e1e91b2927d07d8e96bffe3a781b4934e9d131ecf173be9399800b8269efac -a253303234fb74f5829060cdcef1d98652441ab6db7344b1e470d195a95722675988048d840201c3b98e794b1e8b037c -905ac8a0ea9ce0eb373fb0f83dd4cbe20afb45b9d21ae307846fd4757d4d891b26a6711924e081e2b8151e14a496da18 -b485315791e775b9856cc5a820b10f1fa5028d5b92c2f0e003ba55134e1eddb3eb25f985f2611a2257acf3e7cfdfab5e -b6189c0458b9a043ebc500abc4d88083a3487b7ac47ed5e13ab2a41e0a1bee50d54a406063f92bc96959f19e822a89a7 -a30e15f995fd099a223fc6dc30dad4b8d40bee00caa2bc3223ba6d53cd717c4968a3e90c4618c711ed37cc4cd4c56cf3 -a1b1ed07fcc350bb12a09cd343768d208fc51a6b3486f0ece8f5a52f8a5810b4bc7ab75582ec0bc2770aed52f68eace5 -88aa739fbae4bece147ba51a863e45d5f7203dbc3138975dc5aef1c32656feb35f014d626e0d5b3d8b1a2bda6f547509 -ab570f3c8eabfca325b3a2ea775ef6b0c6e6138c39d53c2310329e8fb162869fde22b0e55688de9eb63d65c37598fca3 -89d274762c02158e27cb37052e296a78f2b643eb7f9ae409f8dac5c587d8b4d82be4ef7c79344a08ebec16ac4a895714 -99c411d2ad531e64f06e604d44c71c7c384424498ecd0a567d31ec380727fb605af76643d0d5513dd0a8d018076dd087 -80d0777fa9f79f4a0f0f937d6de277eec22b3507e2e398f44b16e11e40edf5feff55b3b07a69e95e7e3a1621add5ed58 -b2430a460783f44feb6e4e342106571ef81ad36e3ddd908ec719febeb7acaf4b833de34998f83a1dab8f0137a3744c11 -b8f38ccfc7279e1e30ad7cefc3ea146b0e2dff62430c50a5c72649a4f38f2bac2996124b03af2079d942b47b078cc4f8 -a178a450a62f30ec2832ac13bbc48789549c64fc9d607b766f6d7998558a0e2fad007ae0148fc5747189b713f654e6ba -98c5ede296f3016f6597f7ccc5f82c88fd38ed6dc3d6da3e4a916bfd7c4c95928722a1d02534fe89387c201d70aa6fd2 -a8cc5e98573705d396576e022b2ba2c3e7c7ece45cd8605cb534b511763682582299e91b4bb4100c967019d9f15bbfaf -848480ea7b7d9536e469da721236d932870b7bbee31ccf7ae31b4d98d91413f59b94a1e0d1786ee7342295aa3734969c -b88ea38f9ee432f49e09e4e013b19dff5a50b65453e17caf612155fff6622198f3cba43b2ea493a87e160935aaaf20a9 -949376934a61e0ef8894339c8913b5f3b228fa0ae5c532ad99b8d783b9e4451e4588541f223d87273c0e96c0020d5372 -96f90bb65ca6b476527d32c415814b9e09061648d34993f72f28fae7dc9c197e04ef979f804076d107bb218dfd9cb299 -a4402da95d9942c8f26617e02a7cef0ebc4b757fac72f222a7958e554c82cc216444de93f659e4a1d643b3e55a95d526 -81179cbc26a33f6d339b05ea3e1d6b9e1190bd44e94161ae36357b9cdf1e37d745d45c61735feed64371fe5384102366 -ad4dc22bdbd60e147fdac57d98166de37c727f090059cfc33e5ee6cf85e23c2643996b75cf1b37c63f3dc9d3c57ffa18 -8a9b1b93dc56e078ce3bb61c2b0088fd6c3e303ba6b943231cc79d4a8e8572f4109bbde5f5aa7333aae3287909cb0fe2 -8876ef583bc1513322457a4807d03381ba1f4d13e179260eaa3bddfede8df677b02b176c6c9f74c8e6eab0e5edee6de6 -b6c67e228bf190fbaeb2b7ec34d4717ce710829c3e4964f56ebb7e64dc85058c30be08030fa87cc94f1734c5206aef5f -a00cb53b804ee9e85ce12c0103f12450d977bc54a41195819973c8a06dcb3f46f2bf83c3102db62c92c57ab4dd1e9218 -a7675a64772eefddf8e94636fb7d1d28f277074327c02eea8fae88989de0c5f2dc1efed010f4992d57b5f59a0ab40d69 -8d42bb915e0bf6a62bcdf2d9330eca9b64f9ec36c21ae14bf1d9b0805e5e0228b8a5872be61be8133ad06f11cb77c363 -a5b134de0d76df71af3001f70e65c6d78bed571bc06bfddf40d0baad7ea2767608b1777b7ef4c836a8445949877eeb34 -aeadbc771eaa5de3a353229d33ed8c66e85efbd498e5be467709cb7ff70d3f1a7640002568b0940e3abd7b2da81d2821 -8c28da8e57a388007bd2620106f6226b011ee716a795c5d9f041c810edf9cf7345b2e2e7d06d8a6b6afa1ee01a5badc1 -8ed070626a4d39ffd952ddb177bc68fd35b325312e7c11694c99b691f92a8ea7734aeb96cf9cc73e05b3c1b1dcad6978 -ada83e18e4842f3d8871881d5dbc81aed88a1328298bfdc9e28275094bd88d71b02e7b8501c380fa8d93096cbc62f4fb -8befc3bec82dcf000a94603b4a35c1950ba5d00d4bed12661e4237afa75062aa5dcef8eac0b9803136c76d2dd424a689 -97c6f36c91ca5ca9230bfcbf109d813728b965a29b62e5f54c8e602d14a52ac38fa1270de8bfe1ab365426f3fc3654c7 -b01d192af3d8dbce2fe2fece231449e70eb9ac194ec98e758da11ca53294a0fa8c29b1d23a5d9064b938b259ea3b4fb5 -819a2c20646178f2f02865340db1c3c6ebc18f4e6559dd93aa604388796a34bd9fed28ad3ccc8afc57a5b60bb5c4e4ec -a9ffc877470afc169fecf9ec2dc33253b677371938b0c4ffa10f77bb80089afa2b4488437be90bb1bcf7586a6f4286e3 -b533051c7ce7107176bcb34ad49fdb41fac32d145854d2fe0a561c200dcf242da484156177e2c8f411c3fdf1559ecf83 -8fe2caff2e4241d353110a3618832f1443f7afe171fd14607009a4a0aa18509a4f1367b67913e1235ac19de15e732eb1 -84705c6370619403b9f498059f9869fdf5f188d9d9231a0cb67b1da2e8c906ead51b934286497293698bba269c48aa59 -899dddf312a37e3b10bdaaacc1789d71d710994b6ee2928ac982ad3fd8a4f6167672bc8bf3419412711c591afe801c28 -b2f7916d946b903ded57b9d57025386143410a41a139b183b70aeca09cf43f5089ead1450fce4e6eb4fba2c8f5c5bbe5 -8d5f742fe27a41623b5820914c5ca59f82246010fa974304204839880e5d0db8bc45ebab2ad19287f0de4ac6af25c09e -b93d4a1f6f73ac34da5ffbd2a4199cf1d51888bc930dc3e481b78806f454fcb700b4021af7525b108d49ebbbaa936309 -8606f8d9121512e0217a70249937e5c7f35fbfe019f02248b035fa3a87d607bc23ae66d0443e26a4324f1f8e57fd6a25 -b21312cdec9c2c30dd7e06e9d3151f3c1aceeb0c2f47cf9800cce41521b9d835cb501f98b410dc1d49a310fdda9bc250 -a56420b64286bdddda1e212bba268e9d1ba6bdb7132484bf7f0b9e38099b94a540884079b07c501c519b0813c184f6b4 -80b2cf0e010118cb2260f9c793cef136f8fa7b5e2711703735524e71d43bce2d296c093be41f2f59118cac71f1c5a2ff -adcb12d65163804d2f66b53f313f97152841c3625dbbda765e889b9937195c6fcd55d45cc48ebffabb56a5e5fe041611 -8b8a42e50dc6b08ab2f69fc0f6d45e1ea3f11ba0c1008ee48448d79d1897356599e84f7f9d8a100329ed384d6787cfc4 -aaa9c74afa2dec7eccfbd8bb0fc6f24ed04e74c9e2566c0755a00afdfdf3c4c7c59e2a037ec89c2f20af3fae1dd83b46 -aa9f6e8fd59187171c6083ae433627d702eb78084f59010ff07aff8f821f7022ef5fbbe23d76814d811b720a8bfa6cc3 -a56a3ded501659ad006d679af3287080b7ee8449e579406c2cae9706ef8bf19c1fc2eb2a6f9eaf2d3c7582cded73e477 -81971e077c1da25845840222b4191e65f6d242b264af4e86800f80072d97d2a27a6adc87c3a1cb1b0dd63d233fbafa81 -a6fa5453c4aaad2947969ee856616bf6448224f7c5bf578f440bcfc85a55beb40bef79df8096c4db59d1bd8ef33293ea -87c545adbfaaf71e0ab4bac9ae4e1419718f52b0060e8bb16b33db6d71b7248ae259d8dd4795b36a4bbb17f8fae9fd86 -b4c7a9bc0910e905713291d549cec5309e2d6c9b5ea96954489b1dff2e490a6c8b1fa1e392232575f0a424ba94202f61 -802350b761bcaba21b7afe82c8c6d36ee892b4524ab67e2161a91bbfa1d8e92e7e771efb1f22c14126218dd2cb583957 -b4e7ddb9143d4d78ea8ea54f1c908879877d3c96ee8b5e1cb738949dcfceb3012a464506d8ae97aa99ea1de2abf34e3d -a49a214065c512ad5b7cc45154657a206ef3979aa753b352f8b334411f096d28fd42bca17e57d4baaafb014ac798fc10 -8a80c70a06792678a97fe307520c0bf8ed3669f2617308752a2ab3c76fdf3726b014335a9b4c9cbcfc1df3b9e983c56f -a34721d9e2a0e4d08995a9d986dc9c266c766296d8d85e7b954651ad2ca07e55abb1b215898ee300da9b67114b036e0d -8cfce4564a526d7dca31e013e0531a9510b63845bbbd868d5783875ed45f92c1c369ce4a01d9d541f55f83c2c0a94f03 -ab3f5f03a5afc727778eb3edf70e4249061810eba06dc3b96b718e194c89429c5bfbec4b06f8bce8a2118a2fdce67b59 -aa80c2529fc19d428342c894d4a30cb876169b1a2df81a723ab313a071cba28321de3511a4de7846207e916b395abcc9 -82b7828249bf535ef24547d6618164b3f72691c17ca1268a5ee9052dba0db2fdd9987c8e083307a54399eab11b0f76b1 -8fbcb56b687adad8655a6cf43364a18a434bf635e60512fad2c435cf046f914228fb314f7d8d24d7e5e774fb5ffb1735 -a3010a61a2642f5ebbce7b4bc5d6ecb3df98722a49eb1655fe43c1d4b08f11dfad4bcec3e3f162d4cc7af6a504f4d47c -b3dcc0fdf531478e7c9ef53190aa5607fd053a7d2af6c24a15d74c279dbb47e3c803a1c6517d7e45d6534bb59e3527f5 -8648f6316c898baaca534dff577c38e046b8dfa8f5a14ee7c7bc95d93ae42aa7794ba0f95688a13b554eeb58aeedf9ba -89fca6fc50407695e9315483b24f8b4e75936edf1475bcf609eed1c4370819abac0e6a7c3c44f669560367d805d9ba63 -a367a17db374f34cd50f66fb31ba5b7de9dbe040f23db2dcc1d6811c0e863606f6c51850af203956f3399000f284d05f -91030f9ca0fff3e2dbd5947dcf2eba95eb3dbca92ee2df0ed83a1f73dbf274611af7daf1bb0c5c2ee46893ab87013771 -84d56181f304ce94015ea575afeef1f84ea0c5dbb5d29fb41f25c7f26077b1a495aff74bd713b83bce48c62d7c36e42d -8fe2f84f178739c3e2a2f7dcac5351c52cbed5fa30255c29b9ae603ffd0c1a181da7fb5da40a4a39eec6ce971c328fcf -a6f9b77b2fdf0b9ee98cb6ff61073260b134eb7a428e14154b3aa34f57628e8980c03664c20f65becfe50d2bdd2751d4 -8c6760865445b9327c34d2a1247583694fbeb876055a6a0a9e5cb460e35d0b2c419e7b14768f1cc388a6468c94fd0a0f -af0350672488a96fe0089d633311ac308978a2b891b6dbb40a73882f1bda7381a1a24a03e115ead2937bf9dcd80572ad -a8e528ec2ee78389dd31d8280e07c3fdd84d49556a0969d9d5c134d9a55cd79e1d65463367b9512389f125ed956bc36a -942c66589b24f93e81fe3a3be3db0cd4d15a93fb75260b1f7419f58d66afaa57c8d2d8e6571536790e2b415eec348fd9 -83fe4184b4b277d8bf65fb747b3c944170824b5832751057e43465526560f60da6e5bbee2f183cb20b896a20197168c7 -88a71aada494e22c48db673d9e203eef7a4e551d25063b126017066c7c241ee82bedaa35741de4bd78a3dd8e21a8af44 -8c642a3186ca264aac16ee5e27bd8da7e40e9c67ae159b5d32daa87b7de394bf2d7e80e7efb1a5506c53bfd6edd8c2c3 -81855d6de9a59cef51bef12c72f07f1e0e8fe324fcc7ec3f850a532e96dcd434c247130610aaee413956f56b31cbb0dc -a01e61390dcd56a58ad2fcdb3275704ddfbedef3ba8b7c5fce4814a6cdd03d19d985dba6fd3383d4db089444ea9b9b4d -96494e89cbf3f9b69488a875434302000c2c49b5d07e5ff048a5b4a8147c98291ae222529b61bb66f1903b2e988e5425 -b9689b3e8dddc6ec9d5c42ba9877f02c1779b2c912bba5183778dc2f022b49aed21c61c8ec7e3c02d74fe3f020a15986 -a2a85e213b80b0511395da318cbb9935c87b82c305f717a264155a28a2ea204e9e726bae04ce6f012e331bd6730cbb9d -91b70f44c7d8c5980ce77e9033a34b05781cbe773854d3f49d2905cc711a3d87c20d5d496801ad6fd82438874ce732b8 -884596417ff741bb4d11925d73852ffeea7161c7f232be3bdce9e6bbe7884c3a784f8f1807356ae49d336b7b53a2b495 -ae2aed8ab6951d8d768789f5bc5d638838d290d33ccc152edfb123e88ba04c6272b44294b0c460880451ad7b3868cc6a -89d8ebfb9beebc77189d27de31c55f823da87798a50bca21622cbf871e5d9f1d3182cf32ee9b90f157e6ce298e9efccf -afd00a4db4c2ed93cf047378c9402914b6b3255779f3bb47ded4ab206acb7eaebba0fd7762928e681b1aebcfee994adc -a2e49b6cd32e95d141ebc29f8c0b398bb5e1a04945f09e7e30a4062142111cd7aa712ac0e3e6394cfb73dd854f41ad77 -ae8e714ab6e01812a4de5828d84060f626358bb2b955f6fb99ae887b0d5ce4f67ebc079ab9e27d189bf1d3f24f7c2014 -a3100c1eebf46d604e75ebf78569c25acf938d112b29ccbe1a91582f6bd8ef5548ae3961c808d3fb73936ac244e28dbc -a9a02dcff0e93d47ead9cdddc4759971c2d848580bf50e117eb100cafca6afeaa7b87208513d5f96b1e1440ffc1b0212 -894ab01462137e1b0db7b84920a3b677fbb46c52b6f4c15320ef64f985e0fc05cec84cd48f389ce039779d5376966ea3 -b1e40e8399ee793e5f501c9c43bde23538e3ce473c20a9f914f4a64f5b565748d13ab2406efe40a048965ee4476113e4 -a5a7d97a19e636238968670a916d007bf2ce6ae8e352345d274101d0bbe3ac9b898f5b85814a7e4c433dd22ac2e000ff -b6394c43b82923231d93fd0aa8124b757163ba62df369898b9481f0118cb85375d0caac979a198ece432dbb4eb7cc357 -82d522ae3ff4fe2c607b34b42af6f39c0cf96fcfe1f5b1812fca21c8d20cece78376da86dcbd6cdb140e23c93ae0bcb2 -b6e0d986383bc4955508d35af92f2993e7e89db745f4525948c5274cfd500880cb5a9d58a5b13d96f6368bb266a4433e -b0b4325772ec156571d740c404e1add233fb693579f653b0fae0042b03157d3b904838f05c321d2d30f2dbd27c4d08ad -ac41367250263a2099006ef80c30bac1d2f25731d4874be623b6e315c45b0dc9a65f530fce82fb3dc25bd0610008c760 -b6c0b1ed7df53da04a6f3e796d3bfa186f9551c523bc67898bc0ecfc6b4a4a22f8c4d3bfc740ebf7b9fa5b0ea9431808 -8e78fca17346601219d01e5cd6a4837161a7c8f86fe2a8d93574d8006da5f06ae7c48eea7d2b70992c2a69184619663c -a21f91f47e04fafbfafacf3185b6863766a2d0c324ccac2c3853a4748af5897dbbe31d91473b480f646121339c9bae2d -a464d68786ab1fc64bd8734fce0be6fbe8dc021d3e771ff492ada76eedff466577c25e282b7c8ab4c1fd95ef5ff3631e -829a24badc7714081e03509ccfb00818ce40430682c1c0e4a399cd10b690bda1f921aabcbf1edfb1d8a2e98e6c0cedd6 -87ccf7e4bbcb818ef525435e7a7f039ecbb9c6670b0af163173da38cbdb07f18bc0b40b7e0c771a74e5a4bc8f12dfe2c -94087bd2af9dbeb449eb7f014cfbf3ee4348c0f47cde7dc0ad401a3c18481a8a33b89322227dee0822244965ae5a2abb -896b83ed78724dac8a3d5a75a99de8e056a083690152c303326aa833618b93ef9ec19ab8c6ef0efe9da2dbcccac54431 -821e6a0d7ccf3c7bd6a6cc67cde6c5b92fb96542cb6b4e65a44bbc90bbc40c51ff9e04702cb69dd2452f39a2ff562898 -b35b2096cda729090663a49cb09656c019fef1fc69a88496028d3a258ad2b3fd6d91ab832163eaa0077989f647e85e7e -b7857ef62c56d8bce62476cdb2ab965eddff24d932e20fc992bd820598686defe6cc0a7232d2be342696c2990d80721a -b343d974dfda3f6589043acd25d53aecf7c34b1e980ae135a55cda554ff55e531bc7c2dfe89b0d2c30e523c7b065dad1 -8d139e16a73cd892b75f3f4e445a10d55d1118f8eeafc75b259d098338419e72e950df6ca49cb45677a3c4e16fb19cdc -817b8535bd759da392b2c5760c51b3952ecf663662a137c997f595c533cd561ed7e655673c11144242160e41d1f2dd71 -817ee0f0819b0ccb794df17982d5b4332abff5fec5e23b69579db2767855642156d9b9acccf6ceab43332ccc8d2744dc -9835d2b652aec9b0eba0c8e3b6169567e257a6a3f274ec705dbc250ee63f0f8e4b342e47b9e0c280c778208483d47af8 -b78c40177f54f0e6d03083a4f50d8e56b5aafdb90f1b047bb504777d6e27be5a58170330aee12fbaa5f1e9d4f944acfc -ab8eebacf3806fac7ab951f6a9f3695545e2e3b839ca399a4ef360a73e77f089bb53d3d31dbd84ddfde55e5f013626e0 -96c411fc6aecca39d07d2aff44d94b40814d8cfc4ee5a192fd23b54589b2801694d820a0dd217e44863ccff31dda891b -8249c424a0caf87d4f7ff255950bbc64064d4d1b093324bfe99583e8457c1f50e6996e3517bf281aa9b252c2a7c5a83a -acf6ed86121821a3dd63f3875b185c5ebe024bdb37878c8a8d558943d36db0616545a60db90789c0925295f45d021225 -a37f155621a789f774dd13e57016b8e91b3a2512b5c75377ec8871b22a66db99655d101f57acaecd93115297caabfc21 -92e60ee245bd4d349f1c656e034b1a7f0c6415a39ac4c54d383112734305488b3b90b0145024255735e0a32f38dba656 -acec614e562ccfc93366309cfdc78c7d7ee0a23e3a7782a4fc4807b8803e6ebfb894a489d03e9a3c817ff2ec14813eba -b912f9dd26ed552cb14b007b893e6ed2494d12517e5761dbeb88521270144f8c3eb9571a0ad444b30a8a65e80bd95996 -8375408dae79c547a29e9a9e5d4ec8241b36b82e45e4ca3b0c36d2227c02d17bb171528d3778eac3bbdc75d6c4e8a367 -8c2d0e6e4406836da112edbbb63996408bb3cda4a2712fd245e4bb29a0100fdc89a2746d859b84a94565bc1cfa681813 -a7431bf59e111c072d28c97626cd54fcdf018421d053a787d2aef454b91251ee8ff9d3702d06b088f92b9ad2bbebff15 -8f3659b0fbeb90b7f30b7a49233325e806551a32911a654dca86e290b314483bbb33fe6482387bc48c35d85c1dd0441c -8dca5ba23f0bb76f7dacabf12886053552ba829a72827b472a2f01e19a893155cdce65f1fb670000f43e8c75ba015a31 -8c1514c083c77624eeb5d995d60994a2866192e15c4474d0be4189fae0e9dbd62494ebb4c02fbc176b53be548abbc5a1 -80498d2ed153381baf3b0f81da839ed0eea6af5796c422b8e59be805dba48c4395bb97824ac308170bb4f14f319c5ddf -84f5ebc3bf96362457993e9fa31493c31c4283075e2403f63d581b6b0db8a3df294b2085643f2007f4de38cb5d627776 -958e6e38774da518193a98397978dbc73d1c3827b4996ec00b4183da2c305a187a0ada9aa306242814b229a395be83c9 -ab8b8fbf73845615e7fab3e09e96cc181159eab09f36b4c1239b3c03313c9aeb4bbb51e16316fe338b2319ed2571b810 -977e4e33b33bd53394e591eba4f9a183e13704c61e467d74b28f4ad0b69aa51501a5221cb1e0e42bcb548ca518caa619 -a9bb7ecb9846cc30d04aad56d253c3df7004cebb272f6adf7b40a84adef9f57291e0d08d64c961b9fc406cdb198aab9b -8d2b72dc36406a545a9da44e1fddfb953d4894710ca026d6421a4ac91e02d0373a599f2acfe41d8258bc9679cf6f43d3 -904192fc8fe250f61ecb8a36abbbccae85f592bbf00c10039c30b5a1c733d752a04e4fd8a1000c6578616f8a16aa83a3 -87f5fdfe20bbbf931b529ec9be77bbfcc398cad9d932d29f62c846e08a91d2f47ae56ad5345122d62a56f629f9a76c4d -84cc3a53b2e7b7e03015f796b6cb7c32d6ded95c5b49c233ac27fafa792994b43c93cda6e618b66fce381f3db69838ba -aab58da10d7bbe091788988d43d66a335644f3d0897bbc98df27dcc0c0fcee0ac72e24f1abdd77e25196a1d0d0728e98 -a10ea8677c2b7da563d84aa91a314a54cab27bb417c257826ebdd3b045d2a0f12729fe630bbbf785d04874f99f26bee8 -acc4970ef2a4435937a9b8a5a5a311226ca188d8f26af1adfcd6efb2376a59155b9a9ff1cff591bde4b684887d5da6e5 -8dc7cf6fcca483c44eb55e7fb924bf3f76cf79b411ae4b01c6c968910877ac9c166b71350f4d935f19bdffb056477961 -ac2dd1182ded2054c2f4dbf27b71a0b517fb57193733a4e4e56aca8a069cff5078ffd3fd033683d076c1c639a4de63c7 -932ec87c450cd0dc678daf8c63cd1bf46124fa472934e517fbbfb78199f288ff7f354b36e0cc6c8739d3f496cfe0913b -b0d631ced213e8492be60ea334dbe3b7799b86d85d5e8e70d02beef3ae87b1d76e1df3bdb5f7ba8a41904c96f6a64455 -929d7239ead7575867e26b536b8badf2e11ca37840034d0e5c77039f8cce122eff5a1bf6e0bcadde6b3858e9f483d475 -aaae5d372d02ee25b14de585af6fbc48f2c7cd2a6af4f08352951b45aa469599eff41e820df642ca1a0f881120e89dbe -b23c411741a6b059f04fa4f5fd9dd10e2a64915f2de6ea31e39c32f2f347a776a953320e5f7613fcb1167efe502f5c5c -a4581b0ae633fe29c6f09928e5efb16db019eeac57f79fef2fa1d3c9bee42ce0e852bc60b9d0133265373747e52a67a4 -81b33afffd7b2575d4a9a1c5dd6eee675c084f82e06b9b3a52a3c9f76e087f12dca6e0ffddc42fb81ce1adb559d47a38 -89cc890f06b424591556aabdfdbb36d7a23700425e90c9cfed7d3da226b4debe414ac5bdf175273828ce6c5355712514 -a4399438be75cfae2bf825496704da5ed9001bed8538d8ac346c8cf0d4407808e9ee67573eb95fe1c6872ac21f639aaa -ad537f7ce74a1ca9a46fc06f15c1c8a6c32363bd6ac78a3c579ed8f84252e38a914cac16709fe65360e822ef47896de4 -8e53b69f5e3e86b86299452e20ea8068b49565d0d0ab5d50ce00158a18403ae44e1b078a3cfd3f919aa81eb049a30c6e -a59f2542c67a430fd3526215c60c02353ee18af2ff87cb6231a2564fe59b8efec421f18d8b8cc7f084675ecf57b3fd05 -b8d9bac93ef56cb4026dd1c731d92260a608fd55b8321e39166678e1dab834d0efddb717685da87786caeb1aaf258089 -aa2df56f4c6fe9e0f899116c37302675f796a1608338700f05a13e779eb7cf278e01947864a8c2c74cc9d9a763804446 -b0108ff2e327dcb6982961232bf7a9a0356d4297902f4b38d380ff1b954bfbcae0093df0f133dd9e84d5966c7b1aada7 -b06b813b01fe7f8cf05b79dc95006f0c01d73101583d456278d71cd78638df2b1115897072b20947943fa263ddab0cd6 -aa41e6c4d50da8abf0ea3c3901412fe9c9dff885383e2c0c0c50ed2f770ada888a27ea08bbb5342b5ff402e7b1230f12 -a48635dbb7debac10cb93d422c2910e5358ba0c584b73f9845028af4a763fd20da8f928b54b27782b27ca47e631ebf38 -80a574c208e994799e4fa9ef895163f33153bc6487491d817c4049e376054c641c4717bda8efbeb09152fa421a7268a7 -b592bfd78ae228afc219c186589b9b0b5c571e314976d1ed5c1642db9159d577679a73c049cfc3dcfefcd5a4f174eeea -aa1f08af3918c61eadf567a5b1a3cdcdfb1b925f23f1f9e3c47889762f4d979d64686ce1ce990055ef8c1030d98daa3b -857df4cfd56d41c6d0c7fcc1c657e83c888253bae58d33b86e0803a37461be5a57140a77fb4b61108d1d8565091ada1c -8fae66a72361df509d253012a94160d84d0b2260822c788927d32fd3c89500500908c8f850ef70df68ddaeb077fd0820 -aa1dbefc9aef1e7b896ff7303837053c63cfb5c8a3d8204680d3228ac16c23636748fe59286468c99699ae668e769a0c -b64b1cb2ba28665ed10bad1dddc42f3f97383c39bad463c6615b527302e2aaf93eb6062946d2150bd41c329697d101be -b6d35e3b524186e9065cee73ea17c082feff1811b5ab5519dd7991cdff2f397e3a79655969755309bd08c7d5a66f5d78 -a4dae7f584270743bbba8bb633bdb8bc4dcc43580e53d3e9e509ff6c327e384f14104b5bdfe5c662dc6568806950da37 -aae84d3d9ad4e237b07c199813a42ed2af3bf641339c342d9abf7ebec29b5bd06249c4488ce5c9277d87f7b71b3ddd37 -b82a463cf643821618a058bddf9f2acb34ac86a8de42a0fa18c9626e51c20351d27a9575398a31227e21e291b0da183e -8b6c921e8707aded3ea693f490322971b1a7f64786ef071bc9826c73a06bd8ae6bf21bc980425769627b529d30b253ce -80724937b27fc50f033c11c50835c632369f0905f413b1713a2b0a2274bec5d7a30438e94193d479ba6679dbe09a65ef -a1d9b259a2ca9cff8af6678b3af0a290c2f51e9cf26d5fe3c6a4fa3d28cbf33cb709b7f78b4f61cb9419427983c61925 -96a3e69a5ed7a98ce59c4481f2ffb75be9542122ad0eb4952c84d4536760df217854d4ec561ce2f4a79d3793c22fa4f4 -990c4d9a4a22d63a8976d34833cafc35936b165f04aed3504e9b435f0de1be4c83b097bbaa062483cf3dee3833b4f5b6 -b9bf5e4b270aec4a0dc219457b5fed984b548892c4b700482525ba1a7df19284464f841dab94abfabcaa9a7b7a757484 -acaecf49cb4786d17cf867d7a93bd4ffee0781766e11b5c1b29089ae0024c859d11b45828fbff5330b888543264d74a9 -b0e1a0865b1e6f9e4a0e31d0c885526ac06678acc526fda5124742a2c303bd0e8871a0cb7951ec8ed9540fc247c8d844 -82b3d327b3d1a631758451e12870816956cd0cef91fcf313a90dd533d5291193a0ff3cc447054564ce68c9b027a7ffd7 -a2843602abb98f0f83e000f3415039788da1e9a096bfe8fed6b99bab96df948c814560424ffebe755cb72f40436fb590 -ab1c7b43cf838798d1e314bc26e04fc021e99a7bfbfc8ffde62fa8d7f92139de86a377289d5177021154229de01ede15 -95e5cf5dd87ae3aed41b03c6c55f9dfad38dc126b17e7e587c156f7745c8da0bd1d60acb718fc1a03b61344f01e3de4d -86f021a3762bb47167f80d4ef1b1c873a91fe83409f9704f192efeebbc3ece0729cd2f92f63419907ea38ae47bc907d2 -aaa1445dafbbcd645d4332d9806225e9346ee5ac6b22ad45e8922134fe12f3d433f567a6a4c19efdd9d5775a7de1e92f -8fd7e15688eef75df7b8bca3d61bc9fca4f56e047cdb6d0b864e7d1c4966eac27d6094b0c8482b49739f83ec51050198 -80aab8b4d394eb011d4ec6a4c2815617308c9b847c6fa6a3d7e6af1c79420ef6ff2a13934a398581c40ee4cf1cac02ac -8970b97ac076a1d8a321ce00eada0edf974a46bf3cc26f6854e4218cdfc8d2b0c32199d9658f254b4fbae5a2c5535f41 -a1aa2ec5b03df0a630e73dd048680ed6d3032c324941423f45cd1f16038789e5e75b876a13948732e9079a422f66a9fc -b5fe5f5e2f2ae2beeb8e95859a02fc45f01f9fb0ebb2bd8ec9ec976b3e806228821a9775096d341d662bc536c4d89452 -a2bc1f170b62d0d5788b02391337b2ab157c38e725694e80aeead7383e05599be0e2f0fa27ef05db007061809356e147 -a8a69701d4a8d0d972390e9f831fd8e9f424b2c2ef069e56bd763e9e835b3ce5f7cf5de5e5c297c06ace4aa74df1067c -b43d551af4ff3873557efe3f3fb98e5ede9008492f181f4796dd1a6bcda8b9445c155e8146966baa812afae1abe06b48 -b4b1dae44fd596813f30602ab20e9b1fb20cb1bd650daacc97b7e054e5c0178b8131d439a9e5b142ca483cc012a362b3 -b95b8a94c30a831eaaebea98c65cc5d0228c78afd6603d4aa426d8186aecc951f1a11c33951f51df04c7e6fa43ffb5ae -b100059624cf9db371bec80013a57a8f296d006c139a8766308f1ea821c7eccc26cad65bc640ab3f6cef9062653bf17d -8e5a2cb76716e0000d13bce5ef87acac307362a6096f090f5f64e5c5c71a10fddfdee8435e7166ba8c3ad8c3f540f3e4 -93d2c43e21588c1e83c4255c52604b4ac3f40e656352d1827e95dd5222a45aebff9674e34fbbe7ed21eca77bd9b8dcbc -8aeaed611546bb9073b07512a9a1f38a7f436ab45e11775a0f9754baaf63e9bcc7bb59b47546a5ded5e4ba2f698e3b5f -af9e6792e74a1163fe27612f999a2f3cfa9048914c5bef69e3b2a75162bb0ce6ece81af699ad7f0c5278a8df0ba000d2 -850bf2d5d34791c371a36404036ad6fdcd8fb62d1bb17a57e88bda7a78ea322397ce24d1abf4d0c89b9cf0b4cc42feb3 -87f7e2a1625e2b7861b11d593aaac933ed08a7c768aebd00a45d893ed295bbb6ed865037b152bb574d70be006ddc1791 -8dcce8f4ad163b29a2348ea15431c2c6ea1189ece88d2790e9f46b9125bd790b22503ec391bc2dee8f35419863b2c50c -b4bf5266c37f12421dd684b29517982d5e4b65dfdfba5fc7bd7479fd854aabf250627498f1e1188a51c0a88d848ec951 -8651623c690247f747af8fdffdc3e5f73d0662bc3279fa2423a3c654af9b6433b9e5e0155f1ce53857e67388e7e3401d -b155120f196d52760129dde2e2b1990039b99484cdc948fa98095cd23da87679850f522e5955eae34ac267d2144160d3 -aec8115e8d7b6601fbceeccf92e35845a06706d46acd188452c9f7d49abef14c6b3a9a9369a8bab2fd4eb9288e2aaca5 -998a8ca4dc0f145f67a8c456f1d6a7323c4836fe036dcbb0f27eb1c596d121eb97369638a9908cfaf218c7706f266245 -b235fbafac62802742ee3d26b1f4e887f7d2da4d711ba7f9bb6ca024de7beec1de66bb830ce96d69538f7dcb93c51b26 -9258d2ddc21ab4e3edcde7eb7f6a382a29f1b626003cc6fdd8858be90f4ad13240072d8a8d44ef8de51ca4f477fa6c45 -99d038487821c948142c678acd8c792960993dd8cb5e02cb229153a1ee9f88249f4ad9007f08e5d82e2a71fb96bb5f32 -a88ee9dbc73d3d8e0f447b76fdb3a27936bde479a58d5799176885583dc93830ac58bca9087075950ea75100cf51af23 -88b9b15816e5a0387153c1f4b90f613beb3ea4596037da01a81fdd2bcbd0baf5598db99f77e7694e5a0d35e822758108 -907ae4b637d06b15846ee27d08c9c9af42df261c5bdd10cf5bc71f8e5ca34b33ac2405307023c50bdb8dc7b98a2cd5fe -9393d6900e1d2d1a1e42412fefd99578d9ac1d855c90a3e7930a739085496448609d674ca9b34016ad91f22d1cac538e -a28ac56b216730b7dcdb5ab3fc22d424c21a677db99a9897a89ed253ea83acfd9d83125133f5be6d9cd92298df110af8 -b027590ee8766f1e352f831fda732adbaf77152485223ad5489ef3b0ce2d2e9f98d547c111fe133847ebb738987fb928 -a9cc08fbd5c3fee8f77cf6eb996a5cafa195df5134dab000e4d0312f970a5577942ee89794e618074f49841f1f933a42 -a8b3535c3df0b1a409d3fc740527ee7dd5ac21756115cde6f87f98cc7623f50cfcf16790689cab113ee7c35a5bd4879f -b61420227b97e5603ae8a716c6759b619f02b8fdc48acbf854352aa6519dad74b97bacc1723ca564cbf3ca48539ed773 -853762498de80eebf955a6c8ddd259af463e4e25f0b6ba7b6a27b19bdbf4c585de55760a16e2d9345cdba6b2a02610f3 -a711c1b13fc6c30745203c5d06390e6c82bd7c50f61734aa8d99c626faba30119bc910be63ec916c91ba53f8483c05a8 -b488c0a793f4481f46b5875d96eecd73e46209a91677769f0890c5e002ecd7d4b1c9f4ba68c47fbed40e3857b1d8717a -a651c5e812ae65b1c66d92c607e80be330737ea49c1dcfe019c0ecea0f41a320406935bb09206a4abff0d1c24599b9ad -85e34e7d96e4b97db98a43247b6c244383b11ca10bf4777364acf509a6faa618bc973e2136a4693fbc8ab597e308fd5a -99837214102b394fffa7f3883759554c6bb7a070f5c809303595a44195e02b9a169460dc6bbffb62bdc0e7ced5f0a5c1 -a952f89c0afb4bdae8c62b89cc3cfb60d0576ba4fe01a5d99534792f38d8848d919b3fc7577435d8443a044d2ee0bcfa -a1ac1f81acb29798acdfc493854663519e2d1b0e9d23d286ce33882c34b4c1c0bb43dd9638166d8026315a44d9ec92a8 -ac9c58aa38219ae659d23007cc7b97fd25b7b610b2d81a8f9f94ddb089efc49c049a8ea4c56e6eaf7b6498f422a97b3c -87e61d501c242b484fb9a937ef21d485f6678d75257fc8fe831b528979068cadbe7e12b49c34058ec96d70a9d179ab14 -aa45f6852f35cc8b65a4a8b5380641d2602a4fa4e3a035db9664df3ac2e170b1280c4a8b7b55161430063e54de4158a6 -a46975614ddde6d134753c8d82c381966f87203d6e5a5fb99a93b0d43aa461466b37f07b8d0973a1abd6ee2b40f24348 -8d35f97297773422351f4d99564c1359ef1a10cfb60aa0e6c8985a78f39b4268486312c8ebf9dd2ef50a771aa03158eb -8497c6242102d21e8b3ade9a9896c96308ab39171ab74cbd94e304c47598e2c2a7b0a0822492ac5c076ba91d4176481d -973f8fcb5f26915b3a3ef6fe58cc44bc7f4e115cd0ad9727d8d1b8113e126ae2e253a19922c5433be4ab2311a839c214 -ae3ee9f1d765a9baf54b4617a289c3b24930aa8d57658a6b0b113bbf9b000c4a78499296c6f428bbb64755dfd4f795d2 -a5be7a8e522ef3dcf9d2951220faf22bb865d050f4af2880b8483222ff7aad7c0866219fcc573df9d829c6efbb517f98 -a5f3c7fabd7853a57695c5ad6d5b99167d08b5414e35ed1068ae386e0cb1ee2afbbe4d2b9024379b6fc3b10c39024d36 -978d5592d4798c9e6baceff095413589461267d6a5b56cd558ec85011342da16f4365d879b905168256f61d36d891b1f -b7b6eaffa095ecbd76d6e1e88ceebabaf674d9ef7e331e875c6d9b9faa1762c800ff1ea597c214c28080f67a50a96c1e -8a1ab53ae5ceaa42e06e58dd8faf6c215fc09ba111ca9eeb800612334d30d5971448be90fec62ed194328aadd8c8eecc -a9ca532cac8ace9a9e845382f8a7840bf40cb426f2fcad8a2f40aadbb400b3a74021627cc9351b0966b841b30284962e -8dddeda8854c8e7ddc52676dd1d0fed1da610ed5415ddd7d25b835bd8420a6f83d7b67ec682270c9648b2e2186343591 -888906aac64fd41d5c518a832d4e044fdc430cfe142fd431caf4676cafc58853ce576f098910d729011be0a9d50d67b5 -96a3f886a2824e750b1e2ea5c587132f52a0c5e3ff192260d8783c666206bd8ebd539933816d7cdd97e4bc374e0b1edf -a150a29ffb2632cc7ec560983d9804cd6da3596c0c25956d27eb04776508eae809659fc883834269437871735de5f9ed -81f7ad4d2959d9d4009d1dfbc6fee38f930f163eb5eac11e98dc38bd2f7f224e3f5c767583f8e52d58d34f3417a6cf90 -97ccac905ea7d9c6349132dd0397b6a2de9e57fd2d70f55e50860e019de15c20171a50b28a5c00ef90d43b838253b3d1 -95694f00c21e8a205d6cbda09956b5b6ec9242ec8c799a91f515b07dcc7de3b6f573e2c0ba149f5a83700cda2d1df0f5 -82bbc3c4a3b3997584903db30fffd182a266c7d1df3e913f908d5a53122fa12cf5acd11d915d85d5bd110fcc43cee736 -8d3f24b4949aa1b4162c28dfbb9f813dd1d8b330f71325448dc45ea34d59b69ca95059402aae011e1b5aba6e536bc6ec -92c734c19752d24782331e74c9af97a8399ddfdd32954e91cda7363dba876aca4f730b451c50a8913950420682da8121 -8653d2c79f77b8c7dcdf7e8dee42433998aeedf1b583abfca686d47a854de1b75e9a4351580c96d1a2a9532659203361 -886f0e414cb558c1a534a1916d3531320a9b6024639712ffe18164ce6313993a553e2b9aafe9c0716318f81a5d0bb1da -b31b5efaba5a5020c3bcea0f54860e0688c2c3f27b9b0e44b45d745158f484e474d5d3b1a0044dd6753c7fb4bf8ace34 -b2d615bbdfdc042d6f67a6170127392d99f0e77ae17b0e1be6786ff2f281795f1bf11f83f2e0f8723b5cdd1db1856e09 -a6e014cca531e6ac2922239b5bee39d69d9ba6d0fa96a4b812217dd342657d35606f0b9c5a317efd423cdb1047815e3d -a8921736b69c9fbb29f443715174bac753e908251804620c542fad6cfbfda7bdfe287f2902f30b043a8a4b4818cfdeef -8d73a9949a042ec2dcefa476e454cd9877eee543b1a6b3b96a78ffcff87421e8b26dd54d5b3192ac32073cb36497acc3 -b936a71ee8df0e48867f3790adf55dc8efc6585024128de2495f8873bd00fd9fa0984472125e801ed9c3cdce6698f160 -82f69c06209c28f64874e850601dda56af44ffc864f42efa8f9c6a0758207bf0a00f583840982dec0a517ab899a98e5b -b7a0a14411101473406f30e82f14b13e6efc9699e7193c0be04bb43d1b49e8c54812ce0f9b39131a20379c4c39d3bbe3 -81159c969f38107af3b858d7582b22925a7ccced02fae3698482d7e9cdc6c568e959651991c6cf16c53a997442054b61 -8bf1116a206e0ce9199fcab6ed2b44a9e46e8143bff3ed3f1431f8d55508fe2728b8902670cfd8d9b316f575f288ed9d -a279b2149824b64144eb92f5a36b22036d34a52bd5a66e5da4b61fbc95af6eda8e485c7914f448abd8674fc14d268d9d -8b98279b5f3588d1a2f8589d2756458690a502728800f8d94b28e00df842a101c96ab9c5aee87c5bbe65552c0c383b80 -b4a27a351ec54420f94e0a0a79d7c7a7337940399646631baca93eeab5fd429d7fb39428be77dcbce64a13eaa3c8ca1d -90c08baa29ec8338ffce381eae3d23ce3f6ba54e5242dec21dc3caaed69cac13f2ab5e8d9d719bc95720fa182eee399c -85156d65bb4fef69ffd539ab918b3286105ca6f1c36a74351ab3310b339727483433e8f8784791f47b4ba35ca933c379 -923005013c27209d07c06a6b92b0cbb248a69c5e15c600bbcc643e8dcd2402adebd94dd4cafb44ec422a127e9780aaec -863b23eb5463a6ef5a12039edc2f8e18e3c97b244841bc50af02459b1bcc558367edf2f6e4fe69f45f37887469dd536d -87a4a7708a112724ff9b69ebb25d623b5cae362ae0946daed2ec80e917800dbfcd69f999c253542533242e7b9a5cc959 -8bf4347ceea7f94b53564f26b1a4749a16f13bf71a9e03a546f906f7c423089820ff217066159b0637d9d6824e9c101c -ab07eef925d264145971628a39e4dd93ff849767f68ed06065802cf22756fc6bf384cf6d9ab174bfc1a87bcc37b037aa -8e3f10a42fad43887d522dc76b1480063267991c2457c39f1e790e0c16c03e38a4c8e79a0b7622892464957bf517ebd8 -a8722fc7b1acf0be18f6ddf3ee97a5a9b02a98da5bc1126a8b7bf10d18ee415be9a85668eb604ef5a1f48659bc447eb5 -878d6b2a9c0aca8e2bc2a5eb7dd8d842aa839bbd7754860c396a641d5794eab88a55f8448de7dbddf9e201cbc54fe481 -ada881c167d39d368c1e9b283cf50491c6bfc66072815608ba23ab468cfbd31ca1bd7f140e158e0d9e4d7ebfa670bc2d -a2b48578fa899d77a7ee1b9cb1e228b40c20b303b3d403fd6612649c81e7db5a7313ba9702adc89627b5fd7439f8b754 -8e051280e10551558dcb5522120ac9216281c29071c0371aaa9bde52961fe26b21d78de3f98cb8cd63e65cff86d1b25c -a7c5022047930c958e499e8051056c5244ae03beb60d4ba9fe666ab77a913a067324dfb6debcb4da4694645145716c9d -95cff6ec03e38c5ab0f6f8dccde252d91856093d8429b7494efc7772996e7985d2d6965307c7fdfa484559c129cca9f9 -993eb550d5e8661791f63e2fa259ab1f78a0e3edad467eb419b076a70923fede2e00ddc48a961d20001aaae89fad11e8 -abb2826e4d4b381d64787a09934b9c4fe1d5f5742f90858228e484f3c546e16ee8a2a0b0a952d834a93154a8b18f3d16 -a922ca9f2061996e65ef38a7c5c7755e59d8d5ce27d577abcdd8165b23b4877398d735f9cb470a771335fc7d99ecb7fc -90f22862216f6bc1bbf5437740a47605d1ff5147b1f06f7b13fec446e4c5a4a4a84792cb244a1905f3478a36f8d7065b -87f3d9a86afef5b79ea1ca690ee1ee4bb9754b66f7c50a42ad6b99af7c222c853ca161f440a0a2a60b3b5a54e3493240 -80a9ca9a2d33b9cf61976b3860d79f5d00de89a06ef043d2a52931809018aeb4ce70423cbef375b29c2c750c2c8704c2 -b4e798ef1d615896108dae37ac50c1e859216ab6dbac11653e44d06ce5209057b4b0dd6d31dcfcda87664a23c8ef1cbd -aaed6d1e7c5b1db06f80dae6c24857daadfb0268f20e48a98fba4b76de1ebf65fb84c3be95fd6a418b498f8285ec63bd -aeceaa316c6369492c939f94809bc80e0857abac86c0d85be8066bbf61afbaaec67e28c572437a8d35c49dd596b3134f -b791c3d53ed34a7d1c8aa89b7953e3684c3cd529230824dc529739a5fbe74b58b87f01e56e7a169f61c508237ef67160 -9351f8c80634386c45c0050d2f813193f9d839173be941e2092d729be5403632a2f18dffdc323d69eb0dc31fa31c5866 -97693184d5c0056ae244dfb6709cafa23a795dc22d497a307a7f9cf442d7452024023c54a8d6bda5d90a355ba2c84f3a -85362daa003d23511ca174a8caafe83d52b6436dc4e43c4c049e5388d9211b5cbef3885896914d86d39be0dd1f910511 -a2511b5fa34b24eeb0e1bcbcf872a569d1ff5570fe7b0fb48f5542f7fe57bad808d34b50afa87580866a6cb0eba02f27 -b382e3327eb1401f2d378dbb56ac7250adde0961bd718575a64d264ffd44772c20752d4035c3ba60eb435e160b375e20 -afad8a5d40b536c0720556845a6b257ed42165c14fb4b4a874717d107752f49ed9380c5b048df3aca67287bb8fc411a8 -8fad0c98434ca5373c2d767868f679b76b4a8d04bca8240ea3f388558262c2d61b73b16fc1160932652b5688c25fffcf -83898008b5cbb6f08f8ef3ec179427869682bb4e8d38f6e6a687a214d4a307436afc64ee67d70a5a8ba9730bf839aecc -b85232e79913785fd82b06890706972b4ad7a309489930ae23390d51aa5189731f8a2df24800409a8c36b3dd6fc91275 -a24ff26ec792f3701da4c5638c1fca4fa4dae95b01827d6200d583c4caf17ea3171393ba2a8c23d1ee8b88402916f176 -adc5c7a7ff6b41d6cc386b7fc69d7bb04179bdf267864f9aa577f0f6a88438191fa81ebaf13055c2f2d7290be6421ace -a05e835abd502d31454d40a019010ff90b6b0b1f993075a35c9907aeab7a342ac0ba6144dc9379aada6119157970e9b2 -85ff07ba58463e7f153fc83f11302e9061e648a5cbd272bb0545030b20e11facd8b3ff90c9ac8c280a704fbda5c9d1b0 -a6c735ada8f4587da8cdad7ea3ada01650b5a3ecab8d81daa7a5f5de51ef4a6592b524692584306f06be3f6701f2870c -b138deee4e53ae8d677fae104f713ef1b8babfecec16b6a85785a66a72784eb09d44c3b63567222ade714e98f7d1604e -ae79c1a49dafcdd972acd95d8ad0a35c02adc7fd736d4c44c3cd13df5789d339b5ea16bddbbd43e486a061ab31baa5c0 -ab3cf2371a1d7dcd0ffe3869a0178230964b06694bf258b2073ea66a2afccd845b38485da83d02e1d607d4c5c36b78a8 -ab9609f28a325fd01cb39540e3a714506c44e52ef28ee640f361deb5760aadbb23e804663b0fa20a66e239c33f8d8bb8 -8ed95ea8e76e1b42823d7915a6aae77d93746f846bf602841dfce0e47543a36efb9ee7e5b42c73c3209d911225cc471b -a80b6162036d43811482323f0ce59eb18740e33a63d7c7bbbf3be206985919e5342d53a69df537d43e8b7d7f51e8892f -93c03d0a5083408ba00c125a8a9385213d4c860072f0297857b1235045819b904e07f2425c13a661d0a01d2e53347f4b -a6581200f00f96c461621e1d26b14a23687dd97eb9f7df4ba641a84340ee7306dc1796248fba4804f185947ad13b4385 -8be174018fa40f7e0cedc5ae68f38969eb7695f2205e9c573641e533d56f68c20abf38a23d2f0dcac371e60b21b18615 -857ad4ee3218c647c58f09b8ab22bcc8976f00a768ab1f708618e868e6143474be846422ce2710a0ed39b5155b6f13a1 -a490bec40f322d599f26bcefcdddd8f2ef6576aa737d5ce7e8d5d422741abe749e3e6a48489aed8c560633f72857e3c2 -a9c0ee339621f1c4a2410f9b4d2f03f1b558dae2973807b8bccd920e8feb7f65dfde3e79986b72ad21fcc4567240381d -8592251568e750a430f7d2c6ddbb3ec82a4dd9fd83efe389e69aa177fd97ac2c96c59a6e86db20d8e6f125d65b46c4d3 -a4e2f4aa6a682913b423b097c4069c4e46a1f3af9556b1bfd0580d0fc01e3991488458049e0735b2a629684a79271c8f -8c4f6a3e738cf74112b08b1680be08158013ef8a515a81215d8a36c9b756786d1b4cb4563923463f3329292f4b48bf6d -8bace547353c02ea00dd547eeda7259aa354d4772dd5e0c486c723cf88627b7112e196b879c3c92a9561b674d9fc486d -8d372f4901e25e8db64fa098148d4a4e709b0e9dcb756d0f90dad99dea393054193ae1a33d292a3dd772ff7ba05e4b71 -a8c7ea6a6a031ed23d65639f01f5423190775558f479700597df7ae7e338a6ae5e9b32f470aff20787ac8b7eec84df6c -b6e9dcba240fdbbf66033410a79a2dd3e9e1ffdf2eae949b3a9ed720e939d92339991dc3e70a5ac7d5253f317daf0b7d -974dec4cd61af75721071752c664d9c2a5121f06ff1515c56139a177a3ca825f763b69d431d4607e393fa74dcc91cc58 -958863e6ad583a9d370a6db3639066982e44766904e7afa849b132f6666b7d08ab931131b3bec7a506d6583e93d56767 -8b93a33b5da9b3300c20a96d80b894e3789c77041183c2cb21751579c8c96857f60cfc2f075201b64e95a78985c5b321 -b726cb9f7ef34ddbc2fad82b3b0af0b30cc913e26c5a614ae5c19cc9c55c8e6dae069db5315a8dcb6d987415bb550ca8 -a730f515398a71bddd66cab2ff996659d4e47dfbb08ce7958a41021f76d269b91c7498b708cd14b183a8ef469c772803 -a4eb3b18132eb0f5337f14e01d63ca0bec0db6a43870f800e5491db756c2f5fce519d8dba5528b4bcef550d06b33699c -b1ab6621eec1ee6784e632e214693f39a14f3715991996b883d66200963e065c86fa0667f7bc36b93b40b5d90ff708c2 -80486a26c3532ad6e19f76d8c9344e2626c07363fd495264927cb5935fa9565ece670dc98767afb04af6a9a5c9231075 -8ee20e0df3c84a1c6b0e21bcc325cf99235b747ffe47f17fdfba548a358ca75cbcc331dd50db2311b400ae882256a608 -aef4268959e5541e7ec69c921a1e81a8374d7e44bf1bb2debf4101cf3cd6b7d6ca7f441758b388de96b3e0edb5b97be9 -8793629bd29d689ec94b016de8886cac6e2ca6638911babb22db4a787661422da0639a4e4089ebeb689d173abfe75950 -b487b3551c20a29e9a5abbda8c50ff594826283e443c09e3ae09b914e46060b3f9abf70434444ce1487e2a74e562616b -8f11531cfc5997dd04b997cb87ba1831aa7041d5434fe72de66304e3f165d882fac891391fbb1eb955c65319e65293b6 -b195136875fd02a75676c33cb3e60504d5964f7a9e81f4c8c8fd38af62e2145c55f765b3158664566191188ac678f381 -b374174b0b3eb04fa49eb4ece45173f0db5d829eac370a20a62309566e0f98b18f72f3633626893c053b7be6bfbd2366 -b2a2f6b0cf652775679b2d677048f2ed8c31a3269e6cddcc7a10e3e6fee89e486b50d9d55fbe452b79c4157c0270fb77 -892177c364dc59032594e7a6fd032286ffdf4fa0b9e3baeb37ec839faebfd2fd46c57b2c9bfe9977b59c93a9cc0ead1d -8ab7c0038a7dbb2ef200dbbe9acbc875829ecad4883792d5c6ce283de67ccd9aa935a9cc7b30b2bd9de7fca7bf2a9a05 -83745cfc78ca709835aa6c6a233c2b86fb31e3f9f6a8becf63e501f2841c4366fb7d131b746c9d3291afda714ff05579 -a723dcb67925ef007e8339dc578d2622d9bb77cfda87cca0088854a59414c02338752c56116a6c1281917842e8467c38 -8a098142da0af2254c425fdbbd0d1b1a17b2bd781391ab37f181775524b8563c64ab8a1602aee2ac6c0a82ba11a8b1d1 -b13bd7529a9b351c5d395c794c28bcb0a3167f1c992e8c062eef47be9be27895945231d249c73a0b6949daa295e14944 -a20dcd2fc2222eaae467d9f5db861040f58bcb991a26e5663ac3aa5e1ff13d0010657c5af586cc4621757add2b905073 -b818f660c3cc4e9f273c25ceeabe562c8afa8ff88529c26f2cf45ae6b2813cca5f350e3cbd56f6257c4df41722dabd25 -b225d5987108b24411bc389276f12509a45e86d5ad6b6d929af5274df0be11109c0fed329669a0acafdf3b0beaa8f2ec -91fcb6d04576d3c6bae947bb7843b430e5fb0592ae49b0a65dfa5791f4eaa4bf2c7f436c8de7360f217001c2b4e5c67a -8821f7a1424ca3fdc5d4a5606ad10dfaba6094cf36669fa9f84cf7617e50425405d14980780e1e18a1ecea7913cda896 -990dcb7f38f56521a70cb71bf4522649fcd46ac052c7feabb0748dfcac9f9c0f95d29e070d32af3cd0adbf869535e17b -b0fac1029fe2c1100f24e2f4bf10c7672199fce53513c7dde2e8d9b00702edf0143e0e1dc7ceae7dcc6994edc2422b6f -a514ebb1a33451b4915c05114db0b10168393613744df848b24e43e09f0bda23baefd9d731075198aace586615ac7911 -8b77f7953c2e67049fdca3653b8d8cf3f799677f79b954da02bdad8cc4d6c855c1c7c16b4f6f9ba35f46426ec28b2d84 -875520cfbda16ec5b1d1d00f578a910d0fc052f17870ba093e22e310bb07648d34817cc2b8811b6f52de535f7046a0d0 -b8c77b4be0b430851c4ff69e91cb770db1935d848198601393810ef395efab52deb9d5c6525472bab720273d5e0e7a79 -b6d4d437146671bdea62fb6545395ea3df39f1cdef21b8476b68e7a25aa7354f847740576d6c9f187bbae9941f0ae450 -95c642f1bccdb62cd6a2212dcdd6ff8d49aee426ca08b7cf3a9d15249d24a9eed5533f92a70c84498c0797f8a57efa27 -b617978047ed0f748c305aa7f30c2dacd0db00baa67fe0c5ce346ef0e6991dc7e05f18dcb2702467421f8390f27aa815 -86411c7a00b3e8b43bf22fb061b1f54ad9bbf632cd74395a478218389c0f544668acf3dd7726532d080ca7da9a5f8608 -97bf684a8849626c4710a6992f6c11f6b5406fd4dfe9e6aa502425aaafe9827e2c435aaf9a5d3d2ba3a4c0e8aec79ba4 -8b178e2a125b461d3180906ffba0af3dce614c64058501fdd35243ababf892d6fcdea4834ce42c25d5569452b782a709 -8ebed2c8a25c61da6a6a8cb0d8f5ea179e28869753eacc728f2c076f7aed8598cd3aa0981f120f9e7ea55b3a689ae882 -a6f235b8e655ca3d634740b53d8c0a757ecc75d2b8838b7948997c1985473d01943d935f687b86cee56cd47c8e773443 -a7959c465a9646908b9d8032a589e41a7dd999f2ffc54bb42f22e5f8a4d8c493a31bcc7ea2cac6c8dbcc59acace7181b -96d0532df2e12da20a57cadb6cf5f6c4ee1aa4775629358c25f1d51677a3e96d1fe3b232532324b4f02f941952d4cc68 -90f493473d686b639a30d1ddc9c72eae6e983f1236e162e58e967a477c0654973ea2e1bdf4ba1a44d7247bc1befc2cab -8b2d87876d9c4085102a07ebb41c565ba69acab99ffc03efc18f20e48d3f3bbe4fc6ddab9c78fe479d9ada80504d85ba -829a0fb3200a28e09cacd6c5346000e7786116ddfd898f37dfd17bef454a8abc0fe939ed8735c00769f7f2f33cd4f906 -86194ec9e88ddb7150e8b03e7a535b6e99863fc6762835601efd03615aa97aaeb413cb210e86035086ed852b39c9d019 -b02efd116a7189cb317ceae392bc301ae55470f0489fa89934e182aeb8c67e280299b975786fe9a470bff46827defb9b -87d7c3903bd22b12d815506f150373f518d47dfc6e5fd74347d88b518124c9923d1e4c98defeb3a45d53d50b423e2175 -a1a430406b28254a7d6348bc98e697e9bab43839aa05d53faee97546f84541ea0b559162619b2045182938f69bf61cae -99d243c226c61c6697fb3d2594f3533fa5dfd7cfc87107908cacde337d7a077fa5a9dc702d26081b065edb1227498e65 -800ee5006ab6217161f42db0cfc552a81728bb4fbd7af6e4620ea099a65ef6664184af3f65a07fcec7e965529c5b49bf -91bfd307579cadc8f81009558605be3edbcb8dbba271475803484017f40130b2b216aef4f620d960193be681877d3a53 -96a060459dec458d19a6f8af6e49dc6c7c58c55dd18915c5fce5e0f4b4a422fce3b9632f6059388fe760289abf70f173 -9921a37f3e657222c7fda3588418a9071409711d9f1fccede7494429f02a45fbc52d79fbb64e9ccd518f60d06d0520d3 -81052b0d15773cb75975ca9230ebb2579700e489c7e3f07cd9cde206fef38b8139bd4976d2b4a7840495fc645f96df03 -88ac37ba66d1de5e23878c992e4d54023729e97e77351f50dc5918d738b5a73faf1dc6feec7e85784761836ba1c6f778 -ae1e6072c13060775f6086d1ae1f88b627ffcb810fc0e0e97deea1f3a15ef0aaa52a6dce2563e4beedadc131af2a8281 -8b60a340f5e4f90badf83001b495ac9f13974c3d2054ddcb3e6b8ca99dec5cd63a263e05c282454191ab2e087d5a2911 -832e2d56ba69dbf817b2b9dbd25c1538d5b8dbf5d9bc05e6be85054a423ebb66a71b157e166e0b9444ac171b34b7ccc9 -8586036fc7dde1e7e3ecb61663130c4529866ae9f5f5095b9fccd24a4c70eea899aae5f10ea1ba66d1665b2d83be35b0 -a77969453b5c083a207913272b5b69d4ccbd8718bdf54be8fbe11b4bd0a2168aae3ba8f9362afa69c0ffa28d7e5a2340 -b7fe9568c214baad0ac5f83745611b481f744ec1c4fa78a549b180dcf79633e5ba75dc20055012a13d849eb7a9be57d3 -b01cad1d2a6c51c0ce88243d1f52f95fb5ee315a905079688027511f0c4ecd0563a3a81846709d272fa5ccb9665e8043 -8eae0a21adfc569aa57237654021c2bdb2c6f0f52ccc90a126682c21a1f9413c63d285f92b2b2f8649150a9284bf70b7 -942acc947192b5f3cf60e92383e5d35f79e7a5904e8e9fd1c8a351676c83ad29b0afb6578d555457cf909f8f4d27adfd -a74e092f8628fba9abcabc27e2e9f3d5a9a941dfe50a2dfde2ad179aabc73afd196676925c2d98643ab8b3d02bdb66ad -896159daa2afd757cf3f9d34af248ad68bb3c62e4c9ac49919422727479cf669098f270b9e645607a7d11adad4c889b2 -a428d8370813d78e7a2a24eebd36e9da2f8bb3605e5a39b5fcda939b531c35a8ebaaa642ba556250a37bddeec90326fb -a5fa04eb60a1d5ee9820e78f42f7be15e1c02757b539aead995768c6209684d6c183c71d282e0c12a4c15c03f9a89d4d -93c77d5d220e40affa7269a6915c076c9aef4db552c643ae5d560a79c955b491c6346ca4cf11cbb7fe1894e28d47b065 -802e605d2de745eef6981d88e7a57ef4046a2062725e8080995374cea2b3273c27f35b7774d0dcba014710d8d6c501f2 -82f7169e6ec9b3e2bd450f35ea2e66d06bcf900acf5b73139677b48e078ce2e16599103027b2326770c99c0a690f2015 -b0c8581879439f9b997551233fe2de71aa03604f9cec37a7b18c5854342d9b67be468f3cac4bf6f64fe8a0066248c498 -a3f626848a4db6e9fb01cac90d3362ec521e969ebd5228af694ea3671061476149f13d652942ac1e39f65591fed740f9 -88a8e759b9cbe16a7c16e43f4afa2de6100d2eafa4dee75ccd653ec38c919013d0a6b35c1ee1eaee7c1985b58bcc9e92 -a3d5fc7aaea072798490616552d947e95f49cf02a420314307aafb555287ec607d75589ba24b009cd68299dc6f7942fa -a809cceeb84f9bcf3c3ddafde3041e7bc3b1d14df8830ab849002176a0725e6f16f70774d8962cb0b8ac0dc43c4ac66f -b8f2e46c031cc8fa160a08c2ebdfa85345ed14771b06daa9636b0e7792b7fddbc501dfc85cc626a01104a43a7d3230c3 -b5367e2a521c318b802ce16ceac80c4b8139f73ddb10ddf38433397cda70a86ea1f051cc55626a4e99d27f30f3975ff5 -96d963660121c1441cd13141279cd371a6a0aa18b6a20761b18df60aa9c14e13489afd83695a0921d5232efe72045f07 -80818d492fd85d666bd91aaf6257b86527fdd796773c793407df1d4a0f91d74649a6bab4d15155c36ed4c6e0a32c5636 -931e22918905fd6c230d3d867ea42861f3074d320d14e1929031924c8ac209a5c552b679b24563bb12f9749b4ee983bd -a4de2c333e74ed9bfa3c0bf6a0beb90427abd9aa4221294cda74331646b58ef46ed57cccc8798ba2b9309894b17cfd69 -883881554c1d88c0ed8d3b6dec3d200f6fea69a77ace3e4d6f86b41506a23724b4394ec8384075f9c75c3868ba8a8e8e -aa0539ecf6ec9bf06f24443027f8f24b6b3d8c5b2084248eecd4bcad3c9a69716e1a0d01057f09a65bff1006ac5e157a -856d74d44c943c9e809b42dc493dff20eca03cb0cf5ed45108c69b1f90d8592a53ae8100e99380a274fafad23e74cdfc -9188257446661c88da093b7c5ce998135913f63842d7c1586065377b169ee35b062d925367fb9b909ca971f1188667b1 -8d3aa57cdafbe998938787479f5d590c1484c6dbe94e6c487e57a746ef5252be0eaa5976d6270de7db64b6b92e57a0f7 -b8f4d6997240f9eda5aca0c43323a828d1563c491b3db2087f60ac4120a3fcd06075fb42bb19d0339ab5ee3fb7db25d2 -ad247ea94b8ae1e81eae4c9fd7b39e6601b53cff47b2547ff90a3cca87192eae28408082774a1fd14bf9ab459b7a4f1f -9598598070f8bdbcc49056c40971e673726cd8c1bc4baa0b5124dfb5fb750e7baa7a7df18eae2bd91955ddcb1ec67955 -b874131ab1608667fa60ea29092d090859eed1812e90c609afff96d79e82c5ba546f617f4c96fc32c9bba97431c1e9af -b00750a9cdc75c2a54f0d3cc99b0fe02300754f25166f7ac85ff41ab5e9cfcca33a29be76a480f12a2d410c7cd5032e5 -84b5bd1c90bb6c66755b28ba4af493ca1b0c3a4df9f436aac67d2e07289053f925cf6a149a84e74e1027dc8758150179 -99caf64bd9d193ff306e8ab5da3f1bb2a190a60c3a82099b8d03d17fa810dc53d176c21379f479e828f60d25beb3ffd0 -a8fd9de502f1c261d5733430e5a18d8b7892a98c9529a016fc2ee53892ae965dcd9c75850bcda4c7edb980b8d88e60ea -848c02cac636e047028a3fe8c1bf4066fb7591b96b0340f8fbd476ff01b35fa3e37d309333771a134f24800e5f3f9289 -a1eab1a06dcca3439f0166441e7e7f2f5b56f5f8aa9f45e411c561f556e0fb71c514c06c26ac53b49a576caca5faac3d -aa603f970dcbe953e700e61c151182c8d32cbbb53ceef572ac93383db33a4b098b5c7b267e42d514ca66b740c0925efe -b55fd5301bd700ddb0b4f72fabe9a91ad49759506101fa802ed1677e9553595aa4d2c66f7574e78d21ce882ce0120ae7 -829137bc4da7b4886d3d04d2c39cbf4b1dc40c813ac1adb425c7b9abf9142b516314cab79c68454df5d71994ce416144 -b83a3a22735001f783dd48a01c4fb3598a51ff3987e842b8045c71c035b9e43645a55254ca5911a5676ef4a8af12d056 -8ca8d463deb13f9eef5e533bc39efaeb0c15631282c5c0deee1673b0053a7cccd514af09801dd6c158caa159fe9351ac -a9ffb1427828f3c456b9c8cc50782de1ab0029b9233a0fd998bad0fd014d27e15c4a32d1e16ad41bff748378b5abdf49 -9627e29f725ddd86456aff813976bbc4a836f4deabf5ad9f73d1a260ceb30948824df9c8841e6b3c529652202be181b3 -b52c988647fe3d9276eed3c262e1044f57fbb116c64cf4f207235c205b3fda0f3d789bf90f5217401b468d85fdfda404 -833bbd6e2924f5c4446cb76b881d1434a5badce9eb9b003f85d076e297ad7ef45b822069fe54d17427a348c3263fb838 -a067a36352db6f82a116cb87d3db5f60b18576852409e2076cbbfc7843af78866313a4969385a40271051dd195d51116 -902b99545971f9a103f99d7399acc347ac46fe156166e51deefc0e92aebf5893460c69aeeae11f5af9f49418e289ce6c -9206a0e9ce9b9880f29ef0417c96931985f5d83bb17cebdbba4ff2af81a3d37155b04649426f698aed372e4f669599e6 -b54a5d7c976e45c0b1d44433595eae9d1ae9aeabfd58cd5ecb0c5804756a7b01c9a517754423b4714a3695533a3114c8 -91b612131e84580ece228b81ace83da0269b53f94d3c02a1a0879ebbd81bdc252064b3d03a7e140b43a90f237d9a45a0 -a6cead3b8607eaeafe37135bd6de8fbd16f806c131eb71c8d36bfbe295d45b070255e50dabf076e2c3f6b8699be71d6a -931da21e67b11ba6ce438546a24d063bcd51aebe39b4220a78d9c0aab88b2d37969b5ef3502d835507f9c8d6d006714c -8fda408caa9daf01122a2308b7b9d328f52e1e2f138a8bec30492488f4d710e5e52524a6455a3a2ae2818ec8a610b650 -ad8ad5c189644352d90c462731c46145410e5adf38682bb80f95495dd64d9d13782537d68690847bbb06c6be7175dbc7 -87bb5cc466ade60feb0961421c3fabdc8a7e20f11df8437bfff63d3f8bd25305002a396c9d0fa4fb9a9986d4717f12c4 -827cff72870ba00c29064a7d2b4973f322d6b6de7924c93d8bf8825e7a0e8478c7748f90f5c716bf83c55b2795d315d8 -a225895a8e94229776ceb51b05356291f2dce748be17a60d5aeb33ef8507c368bafe5d1d6eea927f28b9d1422b661b9a -8e011323ce670ff51c964241a6b72e0e0ffbb3ff9bb2762492323fc3a4abf4718091be0945287c7329850e4f74462cde -a2c03c2e5f4e9d3ef361f68b188451994ad1b24de9f323370559c8abfcdc7bffd289d92e78a5f6b104b0a12c84dab2ef -a22b4771116ce22276fab1fec6826610707ce8a342f9f60b079c4e0259dac3cc41c96c560dfd0ada6edd2828f7c0e8d6 -97c17441d0af9be83b42097aa8b7cec84a253b9a2b957214b8fa93c26d2add46144faffa7b8a55312059b10690f711f1 -94bdf348849f31a2737cbae5e5848aee711067bac85c11c2e68b44c398cfafbf3493a3226cd1ddf7a916e7613fc7b6f6 -838f59c6e8469a8ec6fd40b978a3607439aaebe1e50ff707eec72c0b8278af05b477bf12a384b56d03e3d4eb91e56f67 -a1940f0db58185e2b3aedd2b0bc2b73b4a65c68e09b046f38e9dcd4e13c94f5406bea92635190bf315e48ec64eceef2f -b2f4e0ae44e1f1210a91d8f280f17091fa994034ba8c991583f8182a323e9b3001a712e3584fc2d64ecbf2d319d076b2 -9342b89c721338d02c7854cd7466fb24d93d7313b6114ea591e6607439c8ddb911d1cf35f01898e9c557982bdff8f9b6 -8583fcab15be1dd14d5a415f4b14d706c8c62f058500f1344b37730c8be6741779691f87ded3cbcf6516468b373cafb0 -8fa9587c7989646571ad9032f34cedd353caee14f5be5cde1e9e0a1710f90c08faf6fa96a60e1f150f761c9c8ae7417d -8d9ff904cc08141f5a9879f5f77dc600e6edbe859082231a4d819953890199bcc5f940b730ea688332f07e5279d49e1c -b5f82b46e5ef9a2df8d144202d6e2e4f3bdae8e2048d2af5ea7deb3f722fbe6d370401954e74ff0d8cb1010ffb1f38d5 -a3b5b57d435b06ed70530e060002a8fea71746ad07d969ca23f22b5e52624527595b6a6d54b4e953fb7b7596bac378f0 -b90f89390df6d4b7879b915aa3c29b8d779d035033f8873bb7ac54a14ec98f0d08c0e3bf696e2ffa7b5730d736f571f8 -8e81e371b92887e43d95c0dbdcc9575282b26ccebdc8cbf46587e4f2a83b61e9bc0c6d7d1f114b9d21e04fd6c180b12a -8d682947c51dffc6e0fe0a486293c9ed121f441805168236393087cf62f2a429cca60bf0e472564844347d32c6bea27e -a8341ec7dd189fa7168759240224192c58209b53fc961c18082deba217928c399bde08ceae42bffd37c1135b4d14a845 -a94bb076dcc5ee5ec82fac57c5b384c690df12631882bd1b960e1eb8c04f787bc22b7bac315b9dc5a8a098f17f051a0b -ab64e1c6f01b87706c88a3bd974454a438722768de7340b834ccf93ea9880c14ee7c2181432acf51f980d56de73832ee -b7b0058bb724d879e5ad7aed6230297c54cb599ef659e86bf2cc84c38225899fb388391df9b2e6fdf063171937fd8c72 -ae856f4fb74c27cc98b67429186e7df4feb01278cd57bfd3170af6e52e0a23b9e926bf9565a890cfb4ae8f2d590b2cd5 -804b9c6702f0596d328f92fc1ed5a30a7ba17b9204524135001b569233fc4937035031d079f52fd04968f37c24013898 -84274ed1af6bd6a968583995622b4d18c6a2bc703ce0d0edce45bb736529b4836343dcd11911a94a134dca7877e6cab8 -88808098463f7505034c3b6328c8a08186b33f7a981c08376e429dd64b79b97753170531ed078dd265ded4ec0a1ed8d5 -92823bfb23a4eb84d3759e7d717f0c8641ece0927cd2ba8c728c26bb35df2629a838002f353c8d3d75eb19520aab5f25 -8db36bae4d960cdb9c51f419d7ddc81f372e56be605bc96a9d4072b829f05527c37c8f255cc6115300a2a0d2e6568d89 -a8fcdbd7f3b4d7ff04149a209feb75e97149e7efceaa42d66a6b8e432590fe7bd01f1a77fa8b47108f670b612e33fee9 -a9f4c53c62db7e5dbdea6918862d3c6d24b5bd8732a218edf0ba61e9d1861182323d8ecd7bef8f895b42970b492f6e40 -8b95bc7f07818f4d7b409aff8da0b2c2ae136cde386f53a71565cae9fd14c73c13cc1cfd79c0f97cd77839fb738c5b9a -adbd1d11adc756b51a571ddbcbf4392415231ddad93da09acfafee03a9e4f9e1ce3826110619e5271feadfaffce3e793 -95d327c8bb195cdf25fd79c98f9406a6b0316214b1630ebcce95bdaeffafa36fc1accc6882e0e5d13a8db5c0f3c0e61c -8cb2f1e2fb25558869afdacc7bb866544cfdd566cefcd048b48d458a886130bd086ecb7600a960a7f2563c61cb326510 -b3aa8c4bf5b933d89cd74ca7f7176d6624d562d7d58b041328b49d7562a30b489cb606abb3c49e85baf04c28e9cd1f44 -97f9053a85250c420599827297453c2cfde087065b823d9e43139e6a9cac3a2ec40a1b6e2f0726bdc870fff215462f0b -878d5dbe6b881389c2ca126ff66d87127c9aaa3f62f0d2c1ec0ea2b279ac95f8a06710dce166415db227655e2345a04d -b2c33a6b4203e3ca5247f0890e475518317ffc44cfbb1da9a1ba02114e8b752bea618050b876de5cf3b1906140a64471 -a56170c8313d2b5541a795bea9934d4425b185b5c409f0484df6f44f0e4bcbf50b860ff46b7245cd99c1cfa8fc1965b7 -96e2b658e2876a14147385fc423d2702a3cb76962b6b437222cf9cea39ebf4bdc03bbf434b747866d4bf72b4ceefa639 -89c4a74fa2f067e7ae49c84ef782c331bcc9245db7e941804e2e99d12e987b4d25cb827778ad4c3566c4fc68018650b6 -a01d30cea7d01c80ff26650020fab02e78fc3842e2398a81b44b21d58d4e9816166ff4ed2418831fa995a28ff35cb6f1 -b960c80b55a8845bbf24bc3f23b0110ca701f9544ab6a5bb7929330213cb471321e55c390ceca3e24bff69bdb0d331c0 -802c5b13f22be7be0e5db11eb3be0f0ea7f9182c932265060ba05fba20ea093dd2810d3b969ee3e387e60fe6ee834e8d -92478f88ef7435d15e39a97916c736abb28ea318394b88678fddbbaab3eaf31776110936abad116a8ff6ca632dd12043 -a6d3da0370c303001d5ed99d1db8bce1f26b0e442f0f042e36db9674e92dcd6e80465e772f1e669f99221caee3392fe9 -938f04f70a8f947d6df2f0c0e9af3cce0c06edbb3c131970dd60884fc0b0a0959c504a2a36c3ff76dfe919905671626a -a7117e55224230822e9983df2132347eb7208cb6798f291df926ab51e04b1a1f78d5568c9a8924ee6f57426134360f20 -b91074c77ad93fe48dc2b10c0c5a62ca3ab7d98345b919c52d84a9dc419b59fc1b267e1c2d4b2e120016ef84bbdb0cbe -aa175c6b6edf02fe8778762c9575581c0ee6efc9dbf99c291a41444a23a056b893be6c45333d907d0bbe9fb0eef84d08 -ad36dcb4e2ab425aa339ae464b038d550cb11186741dcf257f1b8b80ed4f32ffabbece45e2dc1525d4c3eeed819ea04f -91cb35c1ffa9cd5aebef523edb8325078da3eb5cf9e95c675a76446fc7692aaee6f949de064ca2f3e0f082cc3fa93e20 -82622f9410c143a86bc4d756b3c7b324dc295231ce865de020d61cc0868f2c150a473cea3a5b756b36771ce1032415a5 -a5c29996ad3a53468ece9356a5b4ccb68971ea1c89cf39644f1da2d4a477c2ea99bf791ef902b87c225d8c53d67c4c92 -92893eceed1af34fa92b23dcbab175b6a0188a27dbac9ad3317c4e39955a763cb383ab13fb1c519cde311d8a4d12e8b3 -8a093cb191b94b0200e38d31955f9d240e2be1edcd6810a2396a061f17c3ddc9c4f4d56766ddff4e121be7110e03b869 -93981473df0cb1f4b47c7d9b64e3123dcf1593845b401e619f5d7c70b5dbea375d1ca43fca65845fcf0a6b2e0af43791 -a6beb6b0697070f9562910add88d9ba91992f8da127b27be81868b1596d1012f09ea7ed601b4a6474c921a1a1a6d866c -92026b1ee30f2ed61c9f30337c3356844217926aabdff383c19ca3c21e0bc49811ca5b308012bee4ef250cfae1615800 -ac0ebaea6d35f84dac4ce648af096305ba68a7a0aea0a11ab2fbe3162075444a158433c98141bc92ef3b3400d6deb46a -83046f482dee24ac3ca83373f0d1b82ac1c4beda0f229a9011a81ec659ff5fc1fb105e219975b5c744308c77a24f71e4 -aa5a312c47ff7248dcb9c6ffbe5a0628ccd565c07365c4413734d415cd4fb35772622ed833862dddff520a67c509c6a5 -a02fb88805c34018ac33582e19ed0a7e4616acc3dd0867e5f21914c2031c05c6dca30b8b35b57c2b137750f3878a6f8c -a60528f1f14bf0c496491d46a0fbbd6c343e4eb3f1631e92f96a3c5e5c684091aabe5801df7a67f7c6dfd1b0d35269d4 -a1fd8e7fad8ca05a340c05a051bb0eb4197eed345f4104629a9e38e234b09d789cc5537024615feb4a6177d32d39e39e -8e70e36c1aa070815440e19443f1f04aae23b1b59fdbcba43b47b94a026c82c8f66c5dfe54f826f4d95ee1930cdb8008 -8234c1969fa7e9079661e4ca309b71b1aaa10f4372be0b963205c23a81f5a3d52ec08ba9ff65b37f832b52d631580d61 -a18cb4134127fb37c4abca328cd0047378a2e1423490af2bd3eba9ffcc99ca81a3c22404c0886f21f65c7b93c41d7981 -b46fa45fe538816de776eec086e040005706cb3eca097e290abfb6864e745c879868aac8361894f3c3564373ef9ad55c -b96ca43b96c59e95439f75d1e726a35a9362f0dbd34963b156e103e080a8126a8dc3501f9fd541ff3bcf4677f5c4a86b -a8e8c87c7301613818d57387009e601a7ab5cbdc2890f63d985c30c74f9cea2d0584c116baf0d9cd5594386ee93fc661 -b47e4f1b9153ef0981f813948150f283b47a7346fd9921d51fe8e4daedaef78ddeb4fd467c2ccb7cebd9816243da1c6e -a370c202a99c8441ffe96fad0f801086d4d7cc7b960f6e98cca29ceedf492afddfd0f351c9c4d29ac008bc255ec1a2a8 -8f5e6ce1655d1c059b006174e3f5a55c88e1821c97f9702ad8e8455d46c2a83ae4482f2d43edda74a835686ec45a8a15 -a30421e694930a3b65d397b2720d5f8e1eec2b6e2bb5a28d3f9b0a84db9aabd83850268bae64c2b10e313cccf120151b -8abe87163046f7a9b18e2a3c0b66e258facc1b31431420e0b70354b7a60ebd250a784634a76692e7d6f4330b62114945 -894f033cf077d4eb312e3258d9dca414356271abce1d6094ecce6d018c5fadb1c15d8d69451574ad0701a2876db191c5 -b0923d64f88ffc872654e1a294bb1af8681689c21cf08f39afe51448a68e60a9a0a74ccce9969276a932a52c07d095a3 -b9ca23b5be8725fae7fa710eefd45522889c50c29c26384e00b78a962384f0aeff9d15cb5910e9565da12a577eb7e5ba -b242ccf292757197a9f470f2d80ccddc48c7f1235ba026bc68a93be2738bc968e8a200aff3e2f4807216442eb3fc50dc -adc2c3b375b308524b79a024ff87d122055440643fea6fc0a651bdb312c7cbe6a456afa9d342bc76446d77d8daf08bc2 -ab645955356c2ebf2f3df9da275e01daf0b44a52afc309277d6d9ad1b05484e5ae0d9d41ad485fe481e5e362826a86ae -8de96ac587a4449fcc8b7fd0a51b4b5185d9c2eb3434f94cbadd092de1e26b0f6b3f7b15a37e8424b1429121ddca0ecd -94c70ad4e9b871566f3da98170b665a09788d421818299857cde0853789fb943cbcf7d4b2c95246ea7b72edc56a8e36c -b2574be63497843340700b701d5cc8be6d23125bd62058802ee67cce1f3b5f5602b27c93fea5611f27dc695ac563f042 -869ec89da7850cedd88bcb3a50a15cece233119b31b64a61bf6b2310892ce42d8b473b584b11e61db29ed24ce8033f83 -8fbaa269da8e28e9adf4c1b08f109da786dbe9cba871c32eecbfb10619b7a5d65a26f9bb33e201a8ed20b3de94003fbb -8bf7a059c37242caf7f821a6314e4e4adf799e0dd86b37892a7172598892c07272acebd05b534755c57b51556b2d610f -b4e72645fca459898cdd9214892ed08b5c99f82049c0a30d72bac0b9717caa9c6cc16c3dc7aa6ea4d42dcd2a6c175df6 -a39170da87a3495da55bbb9701c5461f3403447174ed6a4af75712f7ba4ac35f51a4234bc4b94da888a0959ee109c0c7 -b45675b2774ea7696089dbf7a0afe6c22e85fd0e4ef3db508fbaf96c9d07f700c991789206da9309fd291be696357c5f -b52899e3e3f6341eefcbe1291db6664bf3b6e8021d32fb9c3e37b6258a35c1da927747b2ce990937d6f4c6c3e7d020d2 -84e5bdb3dfe19700d79dd3fabb0159ccfa084f7288db836c855b827613ce8071067c8d7ac5cc2b4e88ed7f84b690f6e1 -801477d200b6d12fc6e0a9bab1c8211193ab06e44551e037a9b4c36fc2d4f67760b9ff4eba9a3bc7b6e177e891f64ff6 -b6b71a5116d3c22af26a7530f535e9b7851f25a84e562a8f17a125d55b9b3fc1bd8cfe65bdcbeeb328409521e802051c -8687e21c34d7804c12489d30680d131ce2133e2981bfa993afd8a8eeda958ebd5e6881d342d725338659882d9f21cf98 -a024e97a7c4de32b6383c34431994abc533ecdbd6be9bff836ec1af022f5a86773bf345c6f33273797a61fb70a8fd5d6 -83f784f095da20ce5b31f54d6cb14b32a8a12675f0029289c9cd036b7c87a8077be2d04a62618685720e6ee69c875e97 -b4e9dfe7cb9d9efd3fe00d99ae5e48769d4af4bf43d4e05c0b54c9cfd8bc854de96b8d3ebf4dcc06b9dac66b7471a0de -a08b79f9d4673afcf7f38b57f484f88feb7c908f597663a2417f92c348150c2be6b5603f914eba0d9d5bdd4e5c5572c1 -b0eaf919589988798cb01ba0610cd1b7fa3c08715675ece8ecd5f9ef6d5d7b2c4c8ae1ea7dfd202237171aa3e6f9de74 -abff99a98baae4dd0954052503ce81827781694a5ea8c1149f96a3adde75dc2d630e138598cd2ae7fdc7a654aa17df8f -83e369b8680d8b9d995222b033b4f4f3e3b20e782113c941325c7fa9c742feef8747e4a212d9aa23285a259cc4faef8d -b16d5855dd2716613697eba36e2fae0872aaea6999e91cf6552f93f9a0b85ed4f6ff922a91b50816bd6cf8e7a4513fc9 -848373db600e32e741aa1d37726bbb28956783f89ce2d781e95fb1ee1adf4359968a141678af268077eae4c25503204e -93a0dd0fdac18a31875564505b4e28f9e8bb2915faae666538597731ac56cd77f23f2456461e2f672983fb24ad91f6e0 -ab1ebbe49fa56524b564bc2e43784147073e6ea5d27a9540fbf2e04d0f87c645ed2fd28b3e4982cc4c0af1734ee47a6f -b3ee30b733839edab6f61f0738e3f4afaeccf700d8dc7415684f193b36d70d07acd5780cf539f12e0fbf8d4683be773a -88388f2cbdec47a6b3ae460b69eb0d2130ac14de950c22fd86de03e40d02292bb93cebe62432da39d509c1289f785fef -9370c41a54b68ff486b4cc6329c3a851716ebf1d088d77a6c56dec93a18b8a77b596cde74cc17d2adb2b2f411a2e4bbb -b9083b60dc16531f77b05a955b51a237a8f8c0173d72c352c5ca441b55abbc890b14937e457aaec4be5cbbf80cae0099 -aafff8f6c6ebaad952c65054dfc7c829453ec735331bf8135e06406b7a9f740c9a200dc48bb2175516b41f77dc160121 -b43d31fbbaf10526809e9e5bd8bb47a76e0fabd7852ee7744404559ab89f0f215ff518f3271a6aa972a459cab82ac558 -b581ede48c6ef34e678f91dc4b89507413e00e70712e3e8c32a80eed770ec8d8b98caee9702d068aeaca6f704be57bd8 -8cb0a137e68b001a5ccac61de27cac9fb78d4af7b2f5a00b8d95d33ac19cc50c69e760c5e0330a85c0ded1edce0fe6f9 -b947fca07c7aa6c2bf13048275402b00b77b28f1d0ba4b589fbcede13f93b5b931c588560ab8ceba23bb8e748031b55d -81753cced5ff819901740a9a584334e355b497cb699f0be5a52cd555a4c9f149535c7bb355b54407f7f0ec27de6c2e19 -b3d59273951ce97838c4853ec329782a255b5fc7c848e7992ded1be28a5ada7fa3254123afe32607b9991ec6e0659b08 -86b253de246f82be1cb0cef01e87c3d022ca1829d2cc7e6a160a5afbd3ca6b94d75739b122e3bb16f8bde28a8f3223ba -b728b659fa2d8487e061a37f7d14a4c2d70cc37497a8715695d8d332cb274deee2ce23b9b5f6a7408516c02c3d526a49 -81277b46d98848a45abfbe39842495659dcbb80dee985a4fc91d77d52b815487aa8bb455f411fcce4c3879c7a075a93f -b05b6f1fb4a6e654f0ee6b83e08b58b57059bb0b7c490405bc8d963c4a2d6be39c558917977e554e1e9e3169961cbf3e -88f75fa7d016fb6442551ec071cc1e2beeb3ccd213d16d744f573a82f5d70f41dd1b18af71d5f9e73d87f2f6b7dbe889 -81a46434f1bbd65a661a0ff45a0295b8fd8a42a7969c5953721bc98698b64bddee3f806876d1e9983063fdd0c11f99df -8b4f6d33c510a4c9c7d623d9ae0c9aa631fcb987704726b2a4d8519372123bce3c439202f25b5b47045ec14ce39a21a8 -8d5112b330fb63cf6ef3d2164b404c14ff9907d685015701399a260951912b19b8f270f869df317e9050a127763d7980 -aadab394e84dfb82db15ecd2427f39b62352c3e1647c3bcd14fb24ae830ad0116f0fed87ddb63963b424a4741961386e -81ca4e5600d00a3bda24cbdea7a532a4cbbd893c10e7ff10667c15ffa8138b91667abe5466b31a3dcdd60155c48538c1 -ad943af1b8a5fcfcf309ed8f2f916339f254cd555c71a407a47365a139306286a05a8314e1c70e20a65fccd75d36fa12 -b16597a0b437060a390467bbfab94c0bdd695ae898894f4689f939e30cc2119cc08ecb594546304adf876f4e275ebcd9 -a44a4e0a6693be356065891c27eefa040a1a79475be53d54d5fdcea7e0668ff9b35f850974000ed119f6865aa6faa721 -adef27d1b6e6921f4eaf69c79e2e01f5174f7033eaafdd33edcfa5119af23f3a834ffe1bdf19576581b797abd1865b34 -90c1e9202f3ffe28f8e1f58e9650dc4ff4dbc158005b6f2296ec36147e524b4f2f87f8aafc39db5b006fe0c491c92f45 -ac817cd54288b6f7fe6338415344fc9e7b669414051631ab2f27851c052c044be06bf7235d668e194bef695923256368 -ab14944ef653a14456d4ebc12e3196df3f1b4707c4e50b317b5ccc8ca3a0720f0330609f0e7e71793f6ca01583f38c70 -ad5353f2f380837e5ffdf079350b3d42935a0517861d03af98db5ed3ea8501abd68885c8c65f5a66e944b1874826a450 -8b5583863f84af8443ce8970b02e26cc5d959e47efbf8a66a54106ab165f1f76b36423aee74c7b5402fd1c4d7c1adfe6 -b3b46037eed9fc30e4f8f0da8bdbdcc40a38e22e876ce9fde981883017854aba82c18eb00887d92ad847d30082fe7271 -98a2b6fc90b7ad172e4368c1e54675b75c8bf2096d91c9f2b60b3397d3be3b705aed5389845dbd68f0f84438cd0f7687 -b155e800852a5f90a2eac69cc4483428da1dc2c31588a13c924e60a7616ce9baeb7d4b829c772b260277cadd8ed84719 -b8b92c520a1302b0cf7d993a52e1dacd7f27bda9868d59c55687d995ae676b7070af4c0792a9bc1c2635d44a4fee01bb -96dfe9bde526b8fc829eda825f55168b88e8f4e43d4d708cc3060df03437b46e12a8ac70d7788aa75760f6294d3e84d8 -a3fa66c54e2fa084ced3bd838614c6c33042f492a5745d167a723c60d5e7d6020ffd1747981a23f8b68df21ad8f0fa77 -b573ca10cc41fc04a642f6f62c355a4fda69b94b8e95dbb02fd1ccce4bce1191356e1fd66d372159944eb36a7071f005 -acd0a1c9abddfd0ea223eda1722aaada362d34234455bd1c6be115d41e535b16f12ca428da7820a757fa4c98884a385d -96f242eee99c4db383b8754fa7987c0c159652e1866faec905a8d3f010e0a1ad05bd77b9ea8dfd653738959180f58430 -9215a9b672a5d6e435e0e0a45156e0e20f75cbbdf1d14940fed3ddb63d433bef643796c7a4fff881829ebb2b2eba9460 -b8ad9bfceaf08dc5a874387219ddd1170bc3a5e25ed72d321d59ae713be5ddf9fdfbd3aa7ab163be28dfa0dd14614e19 -a19a1050590bc500b32c502f393e407abc3d8e683d6f6b978873aff3e3299b18b1f6b59e2b0fe237d819dbdfcfdc98ca -a6870fb11d4429686e52e1f44c8dcfc7ea24a020df9570c021578dbc1f9bdc8cf797cb3a72d7fc52805dba35d59f2cd0 -a7be733b64d5c06c127bd1c87250e42bfe30ca91ed8ce51e0b6e377f454e8f6fef7f99bff650695df2fd10c375da349b -a1b97145dab30330eea2cdc8739b2446a3704b64505fcea3dd8a9b4a72edf222e98d967d6fd7f76794acfd97aa091065 -b2127049907d2a3b654d1c940b740bfba3dbaf660f86ea79c2f909af7c9fe2a07a1caeb1be12370aeffaf8faa50f1582 -8a207701214bb28e99b0784e9228b1c34afa701966267fe7110f6f29f5bb41eaae6cdb98844d0400787978fabd224de8 -9925147a383b6f5f814520220ffdbf20b214225882c3ef49b1a1ca677709176ec82466fb9c4be2dfbe5640afb63b014a -8416ad93871623fb555b5390b80de99edaaf317350cc0c1ae9d54d59517074d40061f315cce8ba2026d9c1e6f6a1009f -a315f943deebbf0a2cdbcf3f8323e215a406e9cbfbcc3f6288714cb3a6befb1bf71b2a21ff7a2ec4731c65044c45b6b5 -8213e0c2539c24efd186ffa8b6dd401ad2233bc19166a0623b26dd1e93614bbf792823f5599ac116231e2efde9885709 -8e5cafd2f34a127a4a896f05e4d929eef06972a1826b3566446942198df26d62f7679b987db2b3765d9d8058b1cd85c2 -b5302b399c9cdf912fd59007ad4737255552663b1e56dbe64a7b2ddd88d2093c73ea319b45db2dd49d1e03f5bef1a0ae -a0c2bcfbed4b008e1a56e5d2f2419aa59d7dd0ebd990f1c18588de702ad0fa79f445d69965fa9381e700eda13b309378 -80a44eea1ffe24c26b16b8e2e70ee519258b9ad4b3e83cc4e5cca88ebc48d0160066f8b91d0581095b0de2428390c8b3 -84a90cb9c7d2f799f1c4ed060387a4b793ab41c5c3eaffd3b60face9b9c3bae93cd2017283bf3de1e3dac63d0d84dd42 -81d22febca276a05ba9bbc5591ee087b0491beb35b4d9f8fc0d041d642a574667ddc57660b20f5c568f7d61fdcb41bda -a3ac965ac27a28e102a439b74fbfc157e75fd57620e4c0750a466165f8aeecb2191dcf8e656f7525aa50d9c7c69b0b5c -913c17434ff0d9fc52e2ece4fec71b37d4474a18f3ea26925c1be2b250434d49759f58033ba0fce1c6862c6197930dc4 -ac430559c151a5e461f67b49c7786c97e1653fa8698e9759ddbdd99f5daf17fc5a012ae6330739440880728f24eba7c9 -b10d8e9f8aed9361b042d1398ec74364f7c7c1cc5c7f917060572761138bdbe89bf409389ee3879f93bc8032dd67b308 -937271005a4cc6a6ec134870c1b56471aa84ed4f4af1b3d5f334bc0c42762fae0c9a6a2828d3de6151a76dad7b72781c -a10e4dcf51889f69e6bd4c052f8d4036b9571ced98a3d7d779cbcb9fa5c3a82228566ea7cc1d012bf56dea0a40c5a64c -a0ed026528d9a8bb3201bc9dcd20598933e8c72fd315deea8da63d06e97392aa729d98a55a8a60fa4d5573513ba5c9fe -b723fcd04cddbd4c36feae827a03746ffef251c4f4c55a88beedaeeee194430a99f566f483668a0d88b13e7a4a37f1de -84a2cdceed44828c7c05a6a762edec0165e434e7029df617d6646aba48776e6c3b823f40689cee136536f8c93e08a629 -b786264e3a237ac3a1d56c9f4e87438dfed620c867100fd38b01287f5b755c7820937403bfb86644e082094d3e410a00 -92cc35b2065fca157c7bba54410f8bd85907a01c9f760aa0ddb7a82cb55811d24cb4dc6b725367a6a1c293b809a48ead -a12bbf22b117f00164a42515bc57cc9e6c43cc77fb737ee3d0c0cad94cb50cd3847d61cab469cf8ca76f7958bdcfc771 -85985b00de533bde2a757eddf53be79ea39091d16af3fc92327bcd1cd59bf2bf4411a334da29ad775e8ffaf3cea7d7b8 -af9eb24185b0d330d0ea1d0b0fa78af0dcf42ced81cb0128f16cafdea687a9c5582bb6d7c5744117b271cd0b3303f0b5 -8c8aaa1d85ed6327f85d579767c7a9158d209171b3efcb3e8a9d9e534c078e821b6aade255101d2c9ef6d67ba66f10be -a450518a03ffb40e1df89e0f88fd55b5b06f4872cdfb7ec55f40dc40d9424b3b289866336c195bdd54597d95569e0096 -81e61cc69f93c435bd77f155e80626a9c764dd92b6c76af15c41346527948d8a6ca87d6351a0fe7987e2ee3aa66a9625 -b615e0cebf4fdff4cb23a20c8389c370915ba26aa703b28efe4ab070b1603d1c5b6541684acf46b52a915f6aee447539 -a7f51885c7a71885cc84ef734ecd107e8bf5f7a25131415f671d143cc1de92859e65001125323c7985799993af6c410d -abfbf7a46f32066989c32f774edcc68163f085ca81e94fe8c9fb32f8d451bbb2c20ac45cd8d97f9e618ab40186933b1a -8cf35a522b5cac1934004aa9dd236bc77198d43272888afa860cfc79b4b28dabf7a3c74098f84510897566fdd609aa45 -86aa927df78f7a06a4985eb0a4f0b93529cef14f9fd2812d46abffbf25e618ead14d99c70e3c3bb2e17f3f7fabc9c264 -860f1b4f4a398e9a8bb4739587cf96979cfbbe1687b7e91e5bd1198db726391b09b1a261bf12e96698818f60b5bd3537 -8e7c4ee19ff115881051e8637dce1f5d6c65e865d0c757e8ce41b6d7bcd86c7070cce60649692bbf28c868c7e2e1e2f4 -acf7ba01b0220419f09169ac8d16e5cc13dce08e88c90b8fdfaa33aab417f011a20b79a178d8a9f7211589d2e0affd7d -b404bde8e715aefbb9f20a353b911b79173ef3e2cf0aba98b5ae6190b90597d65043b0b4e014ad9ea6c77da2d213ea12 -97e3615d1c77a402253bb55da2d1cdf82de316cefffe42b1022c94b4818d6dc4a313731db85321c537914bdf716a875c -940e950b96a4096a578c6874d747515936652b9b113a5f27f5a834a610867b05f9881e2679b0b289b8527baa0009b6dd -8de15a13ca236a3a285ce6e6826c502ae7365bbe468b6e8ac67b15b0bb49be0e996f1eec81ef69e4b7f54f8e4779a054 -a12244777eacb08ecd42b5676b3a51153022ab97e9353ace0f47c6054c22de9ba60d2a60f59a36841c2a791cb1b7c288 -94f7580203e39a2642ee2e7c969b9911f011d7f3a90c398e1302d26edb3df03df1d0c43baa1c6cf90dde95296d49e742 -82ead33144aaecab965faf63af384565992f38fc1066e71e33d53f43ac93892e27fe78c4eaca1cccbc53364e26ff31e9 -a0c129e9706d354249a7f8aa664ccd7ede89aa1445c5547410814b56d10dc086720953363ab1da8ff5f1ed5d8e575104 -93b3057bf3f74edc95237781ae012cc4b1d3fd0455565ceaac7110290aa518ac32478ba4eb9851555fa87270fcc84f1f -949c2fd0b94f31f7cbf00c679bd3f6ec1a2f4056654708d39edf1a450b4e19a6e251d0bb24eb765087e698f61d3fca2c -99fd2e50e211ccb66b895eb2fc42f260f3ad5767f04c2fe238b81dae98aa6e3977443a51f4fe7b43f499caabe45699a5 -84fe19626503218f327b5325bfd7c0c3d2614b47d34964aa0259d564e769c6c81502132cc1765b0b31fbe39852706927 -b43287ec29d9010bec4284de58fed48dd1e129bac79f09d45153c9949131782f77b11b0c9f8ee06a39e5e9bbaa8e2c6d -908902f3ed45482df2f94415fc8e5a308057a40c8905d7cbbd58ec4848e19276577b7f7e69e5e684a8b981738e10f7ef -85cc7d9c1eae372b4f88758cd6e21604b4bc9f0794e1e74b6d9de96347f81944d01331385fae7a38e5f6096c1dc23465 -af60288c702082fc258b3dbd6952c6b75c1641a623905f491b1e72f49b9d39b33d150a336450abd3911a4c128166acdf -a7d8ac7e589558c4014369ab6f4c1f2196205b03e4278152ec0dbbd7ba54e803c3369a71d364a773aac8dbbd117e4a13 -9833aed34e48c206e9328073597aee1123f5bec085339b4e6839a389a429bf3042798a31fac1464ce963204adface76b -84631a4f012bbb62133030224b57deb32dcf464cacc8ffde7775adbe68707263ab5527a1c75e597e03aa703ba658b889 -a686a61f6467858a2a4c13e70ad81b1901290d3e51bbc0c6e366f9e652f575e91b11c75f640ccef8b0c6c1b05a43c9a0 -b585f0ffd5144907703b41539bfad7f9f058f5985f63db911064ba6b07af8da2796b84b16db42b8d11135c3f846cd9e2 -b525539516c7bb25f1d7e165f269dc8c9eedbba74df44887e178ab8fd798e2a31f39812ca922d6b64d91564f14012a64 -91e480d7568fd2fae39c35b0a8d623e66a3160fee1dd4e9097255004938b11ac1cd3918dc6a1e5fbcb700c95a547e5e8 -936ef55c69b842b6177de71fa48dc5442bf5132116b214302f8f242ca36a273a6bbfbfaf373777104dadbe8e7da5e970 -8e950c0f6688abdff8a3b8bd77be6da6f2565c7b55711f5860ea62a3ab1d51aac31821c602bc11a45e33c69e7dde3ea4 -90eed4595104a0527f8db1e028ff622ff70db4eae99cf47f6c2a0246ec7b103570a6a9a877e32e9647cc74969006743d -b756344f6c4ea05b792e416d9bd9ce9dd4bd904e7622761f28a85628506bfc9d88a25e5f04db62fad30a92fb1d8d8556 -ad79ba76534c1a02ac3e9b7308d390792984cd75b7e1d0e5e4ff123642d99d4ea1825643091aa8117336333c40d5bd94 -832b08144887de0c0341d84f6945450af8d7a4eb32367d7703118186c1be525df9382ce61fed5f3b65a0bb3449185f7f -a322fb944e46d8e47994820890c94af423674716da810ea1da71e0a7733ad72c22114ca39a4b59c98ce4291a5684c154 -b982851a65140dbea79bd3b5487e236feccee051deddcc17c2853032efca289ddb6eaf64be3dd85a73012fdbe9d2d4f3 -8eed5e230e201830b44b9fadca4e156fe1a16bf840cf29da0f381ea0587b20c226de2465c67e6268973e776809af68e1 -81c8f1c04490f36e41a53ee1b5185cb8adbb37c258fd6c3be8c56835bf574c37183a94d55b6554fca35d6e6dd9af0133 -8c4928724107cc16d36f2976677eac0b852fc4c3c0bb2f9cd4d59cd24a113faf33b2faf405c3fcce25be51d41e42c2c4 -8e4ba842636fdfc4d71f0983538ea5037d420acd26abd12efca48c252eea85544b2fa9fccdfec4e7c2a6359baffa112d -b4315b84700e26dec26f3488d308430fdff4809c10d4c24309627911cbb769ffaad0d1ecccd622dd02194eaf5ba59f91 -ab888308f757faef32648c1db01650dbc9aea248b09d06e6efcc996d395f48ec96f2d54a02de441d753fe8737862d991 -805094cfd77e207d5c75f3cad99f41f763ec15443052cfd758c6a82ba422d831a1103a7f9b100da49c28198279c3d3dc -ad857f33243e4a2cd2a773700def21fc7f94939d1a6d2c2125ecd58fc206ccafb07a2c02a1cfce19857d3654aca2c70c -a4d12d40149953daa70b89a329e918e9d93efb4e8004a9357fe76682dab9662c8507e16db83e849340f05cdb4933a373 -a0dbac2ed4b5d03606524245e8a31080eb5bd3e9a0c51dad88c3b18e3e6bc5d64953a81c8e60425b80107ee6b62b1fb4 -86da05355900f327164a78901f6e3db857531b33b1e855df1a67a9ba222c6b05fdb6b0ffbacaeb1ba5b45ff8979b6b68 -932c9873aa3e226dd922b5a616c75153bd0390ce8f332a414b9c8cb6606c2501a37a2aa88097bc7d8e2c4261706eb38c -accd9cdf07ccdd42033ce3b105e00bfd39e2304b1e3d66f8b1128645634452c20f759ec45adcef2fdf04408f62c4cc04 -b75cfdfc1cb48918752eab17eb579820ee6e71e6667abdb64df834ffc8c1362fbbc23ca2c80dee248fe1fbb72d87dfc8 -88b998c73b00638fde7d3dd650a08c5ab996dac6ac34251337fbff3fb5ae4a25dd20c1a16c987ad7ded19eca23cea891 -8afef0956c942571a27f504553fb312cca9e50ce41b44e0466d0516c5abe4d8acf4594cdb03b1ccdbe3f2e6a9093b713 -9042cd83c5ff261e9ebda26398caa16cac2cb840d19062fa8ae50e044c27104972948318f4c866dc4d578798272d3e49 -ad536719a64570a2cd1d72b6590ea1d02c8c49f259a7867be26c8191445165954bcfad50ea12688ace3fdfb0e98143bd -97c86328d63d297b6bc9718dc1ad5a05b908a750d1c455c700d84315589128ce4eea958aef2bcf0fcf4adbd8e3ce58d1 -8e592cf0802e6a9541eeb654dc55055e11f3d757847285197132935ca35bbb1a9156829a39384dfa6f645ff89eb36738 -ac16c614998944f77590bf3913a010e13f2d3bbf6a172293baf5983506c1a2d89989fb72e598f5bba1ea10a691377c93 -ab8e6f5b46baa6632de3621497bcbdd584decb999fe7d8a3364843a1e0b76497600630b6a24dd30119d8bcbfca29f335 -abe1d3af5279e60122d9cea8cc6581c819d7a0e20e3715da0f6da7e02d13a7653db643bd946e2fa9ba338eca81fbe140 -8c33bd831ecfb18d1d0713e16beba768e9c42df62170c1f8a16764912be77f2ac5915623d1d25e8c462aa9c2f6669ca4 -903692becae4a6409f7bdb127d9b11de57a5739fe24218dcbaa0092648d5332dfeef29a908ee9e43e5e0a51a4c3639bc -92591e90347ae286acd365eba32cd9ad8f20f4c9cad2dc579b195147ff290adf0d776bcb3d4b04a25d68a941fc0c781b -b64bbccf860299aec16e1f95c768a1f337c740bde612e6ba260e393edb8b04540127194761c42597abb9bcb771c576c3 -9194f056ccfdfeb78a11c5347e2255d7a7ebd1251f9aebc0b58feb68d3e03a7dbbb74e3ef7309455853adfb4694bd01a -aa4f15f6d6a53ae65b7f6f91e8981d07a5919d2138679a561f7bb608dc4596e45ca06c9441d51fb678b2ad89ae7a17ae -90e3d18507beb30bde08c5001faf489a19ab545c177efb3f73fbf5605f9a0abcdc8bfbc44f832d6028e3e0a834bea98f -8f31dc0118c8c88a6e79e502d10e57652b7aba8409a5bf572ca63fed6b7cbad7f28bbc92ac2264f649792fc1d0715085 -a307d1067ea4c56437b6f8913aa8fcbf4a24580fc1e3336e7f6518f0f3adb9c4733090e459a3f737414ec0048179c30a -b7cc41fdf89595cd81a821669be712cd75f3a6c7a18f95da7d7a73de4f51bb0b44771c1f7cd3cd949e6f711313308716 -a9dc74e197fe60e8c0db06b18f8fe536381946edecdf31e9bd90e1ebfcad7f361544884e2fe83c23b5632912ec284faf -8b3e1e81326d611567e26ed29108f33ddb838c45bbd1355b3ae7e5d463612af64b63fff9fa8e6f2c14c8806021a5a080 -92f6537bca12778866335acc1eb4c3dfc2c8e7e5cf03399743dcea46aa66cac92ac2963b0892784263ad0ebe26ffdbf6 -b5cc0061f7a3e41513199c7dd91ac60d727366482a4c7328527f7bd4fc3509412f711bb722b4413b3736a219b843d15d -b3e9711d68d2c6f6e2cc27e385d5f603d9a1c9a96edeefa1ffdf390439954d19504d6aadc566b47e229ad4940ef020d2 -a09d0d3f0e5dc73a4a0827b72710b514bbfce4a7fcd5141d498a5aad6c38071077f50d3f91af897d9ab677b7041dedda -b177fe260f3b86e9ac21f1bfbe2682ae5dd8c9aecebb84f37054bdab6e39094e611ce582210ceeddde66adf759dadb6d -b0ac6595eba9f5dc4b2fd21856267cfbcfb5b12aa34ec69ca32b80071c5b652e85c25a224d80443d503bf25fbbfe07e9 -81f3c0e11b196bd4a2e8f07f8c037002566dc9037da81f3988add458a520c24dd1be3d43d851e28c0c6a85de4b57a542 -a44308c95615f7fedb2d2127012924468c015df9f48359cc2e36ab4223870b0bfc1e9040baabefdf5266f93afaad896b -8493ec4c32d5a13b81039f1b436eb83f259945dc950e3c6c2ccf5087ec56dd2f60890ed4edf01728b6a54950e19b35c6 -a1a439ec2a6a95bdac9aaa925ff337ba956c0d236ab5318354270e73ed6b73b4ae2d27b4c1686cf97b6526d04e65be81 -b4659b7b53c55a4b2bbe210b53520b392f893500e18990d843b72d7379d45fb44dd1dd2184348d6fd853d6b9ecc6b7c6 -afb2c68d75d00130b0e1b4f250001920213121791698ec04262db714cf7b1408d39f6cc10421f954845aad5b8250b77e -b22b843b40a97210f94043b552f348f66743055a3f274856a738e7d90a625b80e9bbb80cbbb450e1666eb56b8bd5c60f -800895ced82fe13d5fff65a93b0051c3df698bf1221b682accfdb63e3970f669ca37025750697f4e8ff2a3322ad57be4 -b21f598c50d7b9f4a584d548f85e42055ef8e24991906d973749090261584c7f4f5e984b528926f7e75375dd84d51af8 -849b1c68192d18274598dd6d0bf48fb5ee3b1ba25b331cff2d06f345bef3bed49760ca5690848cf33388f6a9a32cd646 -aeb6fd9478b10ef456f6bbb1e6dd19b14475e65497772d12cfc097948383d3fbd191bf95f046b8bf1989954118e483d0 -b1b5e0ea2835f7fc8b66e7731e392b43d16cbce04b52906b6751ab1b91978899db5fecbdabc23a19dabb253005468136 -91b6b1284770cf6f7ef35bc0b872b76c7763ffcfa68f9c8cfabcb2f264a66d47598bb9293f6a40f4c3dd33c265f45176 -b9ffed029846487c2cfb8a4bb61782bd8a878f3afdb73c377a0ebe63139fa070e3fcdc583eec3a53fdc5a421ff1fa877 -998007249d041b0b40ff546131cfc86d0b3598dcedf9a8778a223f7ed68ba4833b97324cbb1de91292b8ff51beab44b3 -8eb77ce9e0e406bf6f002870fb2fd1447646dd240df9bd485f8e0869298a1fc799d8a41b130c04370e9a9cc5c7540ca5 -853db8157462c46f2af7e8f94f2ed1c9b9a7ba2896b4973296898ff3d523d6e29e0b63a5d26cecd5e490b33c87a4cecf -b1436b6f3278768f0979ee852944258f2599977d255bea6fc912ba17c5dff5bdc850cf3e1fc52be9d6d188e868670f4f -a76acbc5832019b3b35667ab027feff49f01199a80016620f5c463dfcbfb51bf276ed17b7b683158ba450660cc7973eb -94540cdb051faf3ae8b8c52662868c2dab66bd02505c4f5f8eb4d6b2e2e5fd9a610890c5dcf8fd887eee796d2b5753a8 -aa35099666bceccf4eb3b65b13bba88e30a8be93693ab6761d8e5523343e8d6dd42d977e66499352fe4e9e9784a1dd0d -894471aad17be54319083c4b5e40adcfacf7c36c4aab0b671030b7ef321c53590a25eccd836efd20f32a93185fd315bb -8f52a9f705bb0dea958fcfbd52e2b6c08ad0f89a07a6b2942c1b4c37eead0d97a38a9e9aeb08d5d59b7fa2a9347f738b -9031c16b4f936c9cab55585dc5064739f696c3347ee2c0792320c9f749e760d120e396e8485ffc79d81c9f3337ad3d1c -82090a0d0d9b05459ec1c328ecd4707c333b784e3aaa0ef0072cee1eac83f9a653a75d83b9f63512a8c41200494826b4 -92c3a9553001f9ea4d67236b8ad1a33275378202cc1babc03f313895458f4b2549bfbbbdd37bfb8fbff0decb6b9f820a -88651868f4da37338a22bc553388df5dd1dd0cb78c4d7d07c637d8f6faef4bed72476fdcd4304d5bedf3514011135f08 -83fa0141bfebd88063f1d787719721b4c6b19ecf565b866de9d7d5d1a890e0e3d859b364bb65f8f8e688654456a40263 -90a7fab753e5d56dfc0e53a6b4e6ab14508220f3a62b3f3f30570c4c9ad225e74122635826c92e8e3227ec45e551432a -8fa375b0345bf6e5e062d108f9feaec91029345ecac67ccf1264eac77b8654cbfdda1f10579f481889c0e210254eadde -b83f06116da9daebdb013b26724523f077debaf6bc618b48a7a68858a98d275f7899c4ec73a0a827219b9248dd81c8c9 -8be1cada55e0c5ebb4fd460b2d209ae5326285a20c8bdd54ed9d1a87302f4063c8730bfda52d9d40e0d6fe43a0628465 -a68ad6f813743ec13a811f2ef3982c82d9d9ac1f7733936aa1e122f8dc7f4a305cc221579ab8fc170c3f123a1576f9ab -8878f1128214fdbbb8a0edd85223741e021508ab6d36c50d38680f2951ee713ea056ed03f62b9461897963d50ceefe0b -acc0d43d1b0260528b7425b260a5dea445b232b37240759fc65fe26f7c9d8e51569c5722bc33e94de6492f4ba1783504 -ad80b1dd717b076910ee5ceabcb762e75e4d094dc83b93b65c16de1f75bc712cef223c05d5579c1561829406c07a97d9 -a6fc9803f9c09d95fc326cc284f42ea5566255eb215dba8a9afb0be155ea11bcc55938b2d16f01cd2f2eda218c715efb -83ad733dbdfbaae8095a403dbf09130513f4ed4f08dcf8dd76ce83d1ea72999b7eea3a7b731da0d2bc80a83c6ee0e3e0 -8748912fbd08cb34a85416b0937d9c4327e9eed20d6e30aeb024a7253f14f1e0d774f3326e54738d71aae080e28da0fe -8997e78d8acf23051428af67183ae9b2c4aa42b503745ffe33df35a35103c589987e1473ab14dcd28ee78ebcb10d8e95 -a2f340502a7eb3c4a36412e6f028321372c4fa18a4743945607424e932af1271fa3e6598a162c872072529576eba6283 -868ccf19b5044ab93b45c9ed3ae34fcb504fe1453d6c4a1d12c325032cf01eb90356de82080ed897e97dba13cae33a02 -ac8867005fe4354d67aa37b866a7e581d2f94f7bd0b9f4efb5c2d1370ec13147a60692051b02fd00ae60b512bce9b1ff -8fd01886b046819c83c12bb779e432b25ba13713f9227be702074ec3abb2bba6be37220a0a26a4bd4171b99b14e32bc4 -a128981ed199f92b5959975c150a93a62fec50b61c80a3fa0634d90fc8058f76f5cbee77aae6889af12d296b30e613cd -81fe618552ff7a36c9235c6d4066cf2f930b5b38de4089e18166e4a06ca5723eadd1976d25e34b74b3ce942300b23e5b -ab1223ea049e6e0fbf9b611de7fd7c15e5e9637cbd73aa0e36aea08a7503ba6804f2aa807186fdc9aa7f4f9195f72e24 -b97285286981b2665f898abc13f3243b63005bef8db4cab3f658bf6167036b61af400f08db0fc3c640a9c623b760690d -ae3ddff7c1f0fbb6a13dbbc667a61e863c2c7c51c2051e33cd61620142e7e30a7e0c4c1f8fbb512aa3a8640267c6ac26 -99c2a89d5bef236060e51c4f952664094c20fbfca647e5d24a55c1fb8df2f3df58244fbbf3635db07b1c29ee3234fa6f -a5010764d4b9cd3b410638334d1f70c5f4843f45b4f4a9316aaea5fbb2c510a97449dd7a07b49f47334a69d37d9955d3 -86706d011dcdc9e9d165d01fea1df68dd74bedaf15a39f92893c030cafe96f4498c4c1fec2d2136354341b3f440a1462 -88fd57eb62bd7dc35722f3a0576c2138403a2f663a2603482e8974a895cf56ddbb02657dc6b89eb2cf5c1f9d1aff6426 -b0dfd4c68e3acb6bb8a776adaa421fc5e268ed4d5964bb90a727091e5113b55b3f9c6d33cedb3ee47ff7acc5df8b1749 -93b92bc942e1a636fc5c2dc1840de5faf158a113d640d5a475b48e2c56ccccaf9db0e37e90ce74c4b3f5c9ac3b2eb523 -b29a16fa1ea95cbfc1873c435ad40dc8495ba6341801b72bd95d908147dcffb1b4bb426dd635f3af4c88984f56594dd8 -b8f367105e1a2d554ac30200c66aeb579d3d30a8953d20fb6ebba2d876ec39c52ea5d654f1bb89b8ddf3d9d651f31cdf -b5fbc228c983d08adf8612eba5b3db3acff604439226f86aa133b02cce4ffde2f977c8dbb8b446b4375673f71634c89d -a399bea37d3056e0559f6644faa0af93063b4b545d504d7e228d3dbbc294af83d3c4cf37fe026b63899b4e7d50fd08f5 -928ef411a36414b24aea26fdbed4bdb1bb6bdc2d967e2553ce54c7c4e077e76869cea590257645c9129dd55ce025295c -9684a4adeed416a9ce82ad79b55c4a3adcfbd43950bc442ed8a340381caedb70f4baaaf821e3a152f483f965d8f56162 -92558a37f214d6f4cb6d72cd2f4ad24dff9d17611b9e4a41ee5c741a5d1ca9e4053b0584533ef4da206110b5dc3e2a35 -973bf0724d1785cc5e85d2a8ee8c354ad4cf557217ced0b7940f6f064024c20b2bfc5b144c820b5083da4bf70690de4d -adaf1389dfa528210ca9c2657c5ff10d51f7e3b18e93a59c37211be0506c3576cb2c04ec80cd0f82605e53c5a3556620 -85b58b223b09fda6f3ab674d75e780c49eb2167837243df049281e8f4fed653811138b398db9cdfe7405fdb8485602fe -849504d3db408d80745a07e850b0a804607b91a59922a5d3bc40da2748c029c029419cda38d2a4485cc0824c6b2504f0 -a3f4afcb353bc2582a02be758ebf0cd18752410ca2e64231176bfa23828423e0a450a65f241a9ed8eab36cae8d9c567b -ae362786cdf121206537af9590d330abbc6dc328b53cdd145dbed0e5df1364c816aae757c4c81f9d619e3698dd32bcdf -9024cfa5b0101eb02ab97866d5a3832944e5aa6888484cfba3d856576b920787b364fba5956bd7c68a305afedc958201 -8a116df09fed923acefb2aecf38a4fbc4b973ee964d67f03791d70bee6356af43ffca117d4e9463ffaf0e0d5d5e5a69f -9163016175c73f1bbc912ddfe03bd4e1db19c64951c8909ee6befe71a1249d838e0db49f03670bb4c5c9b2ab0fb4fef3 -8f6357318d8d16e7240a02b05ce5a4976b6079d49daa258789c6dbf4a47950ebe9de6411780fab06c7c1f35651433380 -8e63cbae8be7341892dbedee3111adf0307c4ee9e375181aa53478f5ba9cdce164d6ae890e5f480119a3a51c6e989165 -a9782f30674a4874d91bfba7eda63aeb5dbe66b040c768d6a925d8ee135f0655ea56276b105239cc0668fc91ddb68cd1 -8d9d94b61ab84ec08665cbe0244ea41756785df019e453ef078c19380bd44c39d2958e8465c72eacf41eed5696037805 -b1470e6f5d2e314474937cb5a3bc30c8bf5fc3f79014945f6ee895fe20028ffc272f9d3a7320aac93e36c96d8a5454e3 -a444911bbafc71179766594f3606b6eaff041826607fd3192f62dec05cd0f01b78598609a530f6930e8440db66f76713 -a9823d44e2638fca7bcc8796cc91c3eb17f46ad6db9f7f6510e093727614aa3a4f9b2c4011ef91dc1c2d224d08d8d05b -ab86020972c359ab98294212558b4b14862040139876c67fc494184b5c9bcea1dbe32fe0c8dd9e60be9daa304acd599a -b7e5cb685bbdcfdb1e48259a5d68d047846c8a35c5b3f90172fb183d1df40d22eaf0edaca2761a07c29c577000ccfed0 -8c88319dae4b28989817e79e6667fd891181e8d2ed91b9c6b614985bca14b12982462ec58b17be0463c24bbb79dd62a1 -8c1c6867e7107fb2178157c991b9c8b0f90c8d57a51220bf3650438ccabccf62da4db8a9916491e730ff3d0c106496e3 -a00a79bd58da6528b9af033087260f9f3d00519eafb4746b355204ee994e89481591b508eaa5402821083e250d38467b -8785abd7c37690f6aa870ee5c799eef72e398a7898b6767f698515be277b9c2fc1af12ea89b0620a848221343a3b5ec3 -8aadae68543db65cef71d0e230a09508d72061398ef2fabec0f856aacff2125b79c70e620744aaf331faf3dfc8afb9bc -8ff0cd437fcad9630b8a2333176a55e178db4142ec841581590594d74d5b53baeac5fb903fdf7bcf83e245b95b58285e -af274e8fad6b190be4e5dc92d2705ba6ac0d7e1ea29e958a5cdd4cb764de46a56d9eef62c999a16e7c50a50b2d9fe3a8 -865e6ec7d1aa848786d6a7a4e87a24d442311f0810b01ef5a74928ab59fdfd651e48880b49680047e5b0df6b3c7c2ecc -800706baaeb35bf3bc33bdea9a8b5cb00d82df407b3b7e1b781a9359cf44fb410ed311591080181b768aae223d9246aa -a9496389d0780b309c6998374ae159f58a8d0fe9a1c24c36cebcb45b27d818e653b51a8ee1f01e30a9b2c46a548126ef -b5fccf4fc3186661939fbee2e89c2aa0e3a6ad4907bcc98c7750520540c4c183b1bbfcdf47f2f1c5e75c3a30cdf30c75 -a90028e39081b736e628c2230cc1338f9210ed01309a40fdf08d39c10cced2cdf71271013bea6dba3a0444fe47963106 -a0815cbb325a8fecf2e1bcc5046644be32d43a8001bd5d8cf0022e4572cd0d481b3e717002f7ab21e16da5f5d16886d6 -b2024787fcda52abc4138150f15e81f4a5be442929b1651ddccbfd558029912be4d61c3c9b467605fff640edf7392494 -ab5aa60032304a584cc9245a33f528eae7157808dedd1ad83ebae00aadc25dbe1cd5917eb8b6b2c800df15e67bdd4c4d -866643847ef512c5119f2f6e4e3b8d3f4abb885f530bb16fcef0edb698a5b0768905e51536283925b6795a5e68b60ddc -806aa99c9a46ee11cc3ebf0db2344b7515db8c45b09a46a85f8b2082940a6f7263f3c9b12214116c88310e706f8e973a -a6eada8b9ff3cd010f3174f3d894eb8bb19efdbff4c6d88976514a5b9968b0f1827d8ac4fe510fb0ba92b64583734a1e -98480db817c3abbc8b7baedf9bf5674ec4afcfd0cd0fd670363510a426dad1bcf1b1cb3bf0f1860e54530deb99460291 -81ab480187af4a3dfbc87be29eca39b342a7e8e1d1df3fc61985e0e43d8d116b8eac2f1021bde4ae4e5e3606c1b67a21 -8a37df12dc997bf9b800f8fd581a614a1d5e32b843f067d63d1ca7fde2e229d24413d3a8308ec1e8389bf88154adb517 -b045a55ca0bb505bd5e8fcc4cfdd5e9af1a7d5fe7a797c7ede3f0b09712b37f493d3fcf6ef0e759d7e0157db1f583c95 -ad502e53a50691238323642e1d8b519b3c2c2f0fd6a0dd29de231f453be730cf1adc672887d97df42af0a300f7631087 -80597648f10c6d8fcd7421caf4e7f126179633078a1724817d2adc41b783723f302eabc947a7ba7767166dacf4ce8fa1 -aefb56427966c81081999dffbe89f8a0c402041929cd4e83d6612866cfbb97744f4ab802578349fbecc641fa9955e81b -a340e493fb3fb604eab864d4b18a6e40ba657003f1f88787e88e48b995da3d0ab4926ce438bdc8d100a41912a47dace0 -a6d777bfc0895eac541a092e14499ff8bf7156689d916a678b50a1460583b38e68158984bea113a0a8e970d8a6799a85 -90ce469410f0e8cfff40472817eb445770833cdcf2895a69bc32bcf959854d41712599ceb2b0422008d7300b05e62e02 -815c51be91d8516d5adc2fd61b6600957ed07cf5fdc809aa652b059bea8ed179638a19077a3f040334032f0e7900ac8b -b3ec6c0c3c007c49c6b7f7fc2ffd3d3a41cdff5ad3ac40831f53bfc0c799ffeed5f440a27acc5f64432e847cc17dd82e -823637abeab5fb19e4810b045254558d98828126e9a2d5895a34b9e4b4f49ab0a5b3ee2422f1f378995ea05df5516057 -ac05412bcf46c254f6548d8107a63928bba19ab6889de5d331eb68cf4d8ce206055b83af4cb7c6c23b50188391e93f84 -88514163c587068178302bc56e9a8b3ad2fa62afd405db92f2478bb730101358c99c0fe40020eeed818c4e251007de9c -b1e657d0f7772795b3f5a84317b889e8ded7a08ea5beb2ab437bebf56bcb508ae7215742819ed1e4ae3969995fe3b35d -a727d4f03027fe858656ca5c51240a65924915bd8bd7ffa3cfc8314a03594738234df717e78bb55a7add61a0a4501836 -b601682830fc4d48ece2bdc9f1a1d5b9a2879c40c46135f00c2c3ae1187c821412f0f0cfbc83d4e144ddd7b702ca8e78 -b5cfea436aa1f29c4446979272a8637cb277f282825674ddb3acac2c280662fb119e6b2bdd52c4b8dbf2c39b1d2070d6 -85c211645ff746669f60aa314093703b9045966604c6aa75aae28422621b256c0c2be835b87e87a00d3f144e8ab7b5f0 -867628d25bab4cb85d448fd50fdd117be1decdd57292e194a8baa0655978fae551912851660a1d5b9de7a2afbb88ef5c -a4e79c55d1b13c959ff93ddcf1747722c6312a7941a3b49f79006b3165334bab369e5469f1bddebadb12bfaff53806d5 -ac61f0973e84546487c5da7991209526c380e3731925b93228d93a93bce1283a3e0807152354f5fe7f3ea44fc447f8fe -a1aa676735a73a671a4e10de2078fd2725660052aa344ca2eb4d56ee0fd04552fe9873ee14a85b09c55708443182183a -8e2f13269f0a264ef2b772d24425bef5b9aa7ea5bbfbefbcc5fd2a5efd4927641c3d2374d0548439a9f6302d7e4ba149 -b0aacdaf27548d4f9de6e1ec3ad80e196761e3fb07c440909524a83880d78c93465aea13040e99de0e60340e5a5503cd -a41b25ae64f66de4726013538411d0ac10fdb974420352f2adb6ce2dcad7b762fd7982c8062a9bac85cdfcc4b577fd18 -b32d87d5d551f93a16ec983fd4ef9c0efcdae4f5e242ce558e77bcde8e472a0df666875af0aeec1a7c10daebebab76ea -b8515795775856e25899e487bf4e5c2b49e04b7fbe40cb3b5c25378bcccde11971da280e8b7ba44d72b8436e2066e20f -91769a608c9a32f39ca9d14d5451e10071de2fd6b0baec9a541c8fad22da75ed4946e7f8b081f79cc2a67bd2452066a9 -87b1e6dbca2b9dbc8ce67fd2f54ffe96dfcce9609210a674a4cb47dd71a8d95a5a24191d87ba4effa4a84d7db51f9ba0 -a95accf3dbcbf3798bab280cabe46e3e3688c5db29944dbe8f9bd8559d70352b0cfac023852adc67c73ce203cbb00a81 -a835f8ce7a8aa772c3d7cfe35971c33fc36aa3333b8fae5225787533a1e4839a36c84c0949410bb6aace6d4085588b1e -8ef7faa2cf93889e7a291713ab39b3a20875576a34a8072a133fed01046f8093ace6b858463e1e8a7f923d57e4e1bc38 -969ecd85643a16d937f148e15fb56c9550aefd68a638425de5058333e8c0f94b1df338eaab1bd683190bfde68460622b -8982f4c76b782b9b47a9c5aeb135278e5c991b1558e47b79328c4fae4b30b2b20c01204ff1afb62b7797879d9dee48e2 -b5098b7ba813178ced68f873c8c223e23a3283d9f1a061c95b68f37310bca4b2934a3a725fff1de1341c79bb3ba6007e -97b160787009f7b9649ed63db9387d48a669e17b2aba8656792eb4f5685bb8e6386f275476b4dfbb1b4cb0c2a69bc752 -88b69369c71daad6b84fa51a0f64a6962d8c77e555b13c035ad6fa1038e7190af455b1bd61ae328b65d6a14cf3d5f0d5 -af88b87801361f0de26bd2533554ee6f4d8067e3122b54161c313c52cc9eafea00661c5c43e2d533485d1f26da4e5510 -98ab18e3bbcb23ac1e34439849e56009bb765ab2f2558ebfd0a57cbe742169f114bceb930533fb911b22cb5a8fe172bc -9027507f1725d81e5ac0f0854c89ab627df3020fe928cb8745f887bf3310086c58fca1119fd5cd18a7d3561c042d58de -a676583f8a26e6f8991a0791916ce785b596ce372812f5eb7b4243ba9367ea95c797170fdac5b0c5e6b7f6519cc2b026 -b91b0ab32638aef3365035a41c6068e36d2303bfee8640565e16c9a56c21703270fd45946ce663238a72c053eb3f2230 -aaf4cd1ac0a30906dcd2b66b37848c6cc443da511e0b0367fd792887fdaf1500551590440e61d837dbee9d24c9801108 -a06f20a02d3cd76029baad5a12592f181738378a83a95e90470fa7cc82a5ae9d2ed824a20eeb1e96e6edc0619f298688 -a465d379c3481b294efc3f2f940b651c45579607cf72d143b99705eae42103a0279eb3595966453130e18935265e35d6 -892a8af7816a806295278027a956663ea1297118ede0f2a7e670483b81fb14dccacc7a652e12f160e531d806ca5f2861 -b480917c0e8b6e00de11b4416a20af6c48a343450a32ee43224559d30e1fecdece52cc699493e1754c0571b84f6c02c2 -b3182da84c81e5a52e22cebed985b0efc3056350ec59e8646e7fd984cdb32e6ac14e76609d0ffaca204a7a3c20e9f95d -a04ea6392f3b5a176fa797ddec3214946962b84a8f729ffbd01ca65767ff6237da8147fc9dc7dd88662ad0faefdb538c -95c0d10a9ba2b0eb1fd7aa60c743b6cf333bb7f3d7adedce055d6cd35b755d326bf9102afabb1634f209d8dacfd47f1a -a1a583d28b07601541fa666767f4f45c954431f8f3cc3f96380364c5044ff9f64114160e5002fb2bbc20812b8cbd36cb -a1a0708af5034545e8fcc771f41e14dff421eed08b4606f6d051f2d7799efd00d3a59a1b9a811fa4eddf5682e63102ea -ab27c7f54096483dd85c866cfb347166abe179dc5ffaca0c29cf3bfe5166864c7fa5f954c919b3ba00bdbab38e03407d -ac8c82271c8ca71125b380ed6c61b326c1cfe5664ccd7f52820e11f2bea334b6f60b1cf1d31599ed94d8218aa6fbf546 -a015ea84237d6aa2adb677ce1ff8a137ef48b460afaca20ae826a53d7e731320ebdd9ee836de7d812178bec010dd6799 -925418cda78a56c5b15d0f2dc66f720bda2885f15ffafb02ce9c9eed7167e68c04ad6ae5aa09c8c1c2f387aa39ad6d1b -87c00bba80a965b3742deacafb269ca94ead4eb57fdb3ed28e776b1d0989e1b1dba289019cfb1a0f849e58668a4f1552 -948d492db131ca194f4e6f9ae1ea6ebc46ebbed5d11f1f305d3d90d6b4995b1218b9606d114f48282a15661a8a8051ca -8179617d64306417d6865add8b7be8452f1759721f97d737ef8a3c90da6551034049af781b6686b2ea99f87d376bce64 -918e3da425b7c41e195ed7b726fa26b15a64299fe12a3c22f51a2a257e847611ac6cfcc99294317523fc491e1cbe60c4 -a339682a37844d15ca37f753599d0a71eedfbbf7b241f231dd93e5d349c6f7130e0d0b97e6abd2d894f8b701da37cb11 -8fc284f37bee79067f473bc8b6de4258930a21c28ac54aaf00b36f5ac28230474250f3aa6a703b6057f7fb79a203c2c1 -a2c474e3a52a48cd1928e755f610fefa52d557eb67974d02287dbb935c4b9aab7227a325424fed65f8f6d556d8a46812 -99b88390fa856aa1b8e615a53f19c83e083f9b50705d8a15922e7c3e8216f808a4cc80744ca12506b1661d31d8d962e4 -a1cbd03e4d4f58fc4d48fa165d824b77838c224765f35d976d3107d44a6cf41e13f661f0e86f87589292721f4de703fb -b3a5dde8a40e55d8d5532beaa5f734ee8e91eafad3696df92399ae10793a8a10319b6dc53495edcc9b5cfd50a389a086 -996e25e1df5c2203647b9a1744bd1b1811857f742aee0801508457a3575666fcc8fc0c047c2b4341d4b507008cd674c2 -93e0a66039e74e324ee6c38809b3608507c492ef752202fff0b2c0e1261ca28f1790b3af4fdb236f0ed7e963e05c1ec0 -b6084e5818d2d860ac1606d3858329fbad4708f79d51a6f072dc370a21fdb1e1b207b74bc265a8547658bfb6a9569bb3 -a5336126a99c0ecfc890584b2a167922a26cae652dfc96a96ab2faf0bf9842f166b39ceaf396cd3d300d0ebb2e6e0ebf -b8b6f13ce9201decaba76d4eca9b9fa2e7445f9bc7dc9f82c262f49b15a40d45d5335819b71ff2ee40465da47d015c47 -b45df257b40c68b7916b768092e91c72b37d3ed2a44b09bf23102a4f33348849026cb3f9fbb484adfea149e2d2a180ff -a50d38ee017e28021229c4bb7d83dd9cdad27ab3aa38980b2423b96aa3f7dc618e3b23895b0e1379ca20299ff1919bbf -97542cf600d34e4fdc07d074e8054e950708284ed99c96c7f15496937242365c66e323b0e09c49c9c38113096640a1b6 -822d198629697dcd663be9c95ff1b39419eae2463fa7e6d996b2c009d746bedc8333be241850153d16c5276749c10b20 -9217bc14974766ebdfbf6b434dd84b32b04658c8d8d3c31b5ff04199795d1cfad583782fd0c7438df865b81b2f116f9c -93477879fa28a89471a2c65ef6e253f30911da44260833dd51030b7a2130a923770ebd60b9120f551ab373f7d9ed80aa -87d89ff7373f795a3a798f03e58a0f0f0e7deab8db2802863fab84a7be64ae4dcf82ece18c4ddbefccd356262c2e8176 -a3ba26bd31d3cc53ceeced422eb9a63c0383cde9476b5f1902b7fe2b19e0bbf420a2172ac5c8c24f1f5c466eecc615d4 -a0fe061c76c90d84bd4353e52e1ef4b0561919769dbabe1679b08ef6c98dcfb6258f122bb440993d976c0ab38854386b -b3070aa470185cb574b3af6c94b4069068b89bb9f7ea7db0a668df0b5e6aabdfe784581f13f0cf35cd4c67726f139a8c -9365e4cdf25e116cbc4a55de89d609bba0eaf0df2a078e624765509f8f5a862e5da41b81883df086a0e5005ce1576223 -a9036081945e3072fa3b5f022df698a8f78e62ab1e9559c88f9c54e00bc091a547467d5e2c7cbf6bc7396acb96dd2c46 -8309890959fcc2a4b3d7232f9062ee51ece20c7e631a00ec151d6b4d5dfccf14c805ce5f9aa569d74fb13ae25f9a6bbe -b1dc43f07303634157f78e213c2fae99435661cc56a24be536ccbd345ef666798b3ac53c438209b47eb62b91d6fea90a -84eb451e0a74ef14a2c2266ff01bd33d9a91163c71f89d0a9c0b8edfcfe918fc549565509cd96eed5720a438ff55f7f2 -9863b85a10db32c4317b19cc9245492b9389b318cf128d9bbc7ec80a694fcbbd3c0d3189a8cad00cc9290e67e5b361ee -8a150ee474ebe48bdfcac1b29e46ac90dcded8abbe4807a165214e66f780f424be367df5ef1e94b09acf4a00cd2e614d -a6677a373130b83e30849af12475e192f817ba4f3226529a9cca8baaefb8811db376e4a044b42bf1481268c249b1a66e -b969cbf444c1297aa50d1dfa0894de4565161cb1fc59ba03af9655c5bf94775006fe8659d3445b546538a22a43be6b93 -8383167e5275e0707e391645dc9dea9e8a19640ecfa23387f7f6fcaddff5cde0b4090dfad7af3c36f8d5c7705568e8d8 -a353ddbc6b6837773e49bb1e33a3e00ca2fb5f7e1dba3a004b0de75f94a4e90860d082a455968851ef050ae5904452e0 -adeccf320d7d2831b495479b4db4aa0e25c5f3574f65a978c112e9981b2663f59de4c2fa88974fdcabb2eedb7adab452 -afa0eacc9fdbe27fb5e640ecad7ecc785df0daf00fc1325af716af61786719dd7f2d9e085a71d8dc059e54fd68a41f24 -a5b803a5bbe0ca77c8b95e1e7bacfd22feae9f053270a191b4fd9bca850ef21a2d4bd9bcd50ecfb971bb458ff2354840 -b023c9c95613d9692a301ef33176b655ba11769a364b787f02b42ceb72338642655ea7a3a55a3eec6e1e3b652c3a179e -8fa616aa7196fc2402f23a19e54620d4cf4cf48e1adfb7ea1f3711c69705481ddcc4c97236d47a92e974984d124589e5 -a49e11e30cb81cb7617935e8a30110b8d241b67df2d603e5acc66af53702cf1e9c3ef4a9b777be49a9f0f576c65dcc30 -8df70b0f19381752fe327c81cce15192389e695586050f26344f56e451df2be0b1cdf7ec0cba7ce5b911dcff2b9325ae -8fbbc21a59d5f5a14ff455ca78a9a393cab91deb61cf1c25117db2714d752e0054ed3e7e13dd36ad423815344140f443 -a9a03285488668ab97836a713c6e608986c571d6a6c21e1adbd99ae4009b3dde43721a705d751f1bd4ebf1ea7511dfed -b2f32b8e19e296e8402251df67bae6066aeefd89047586d887ffa2eacdf38e83d4f9dc32e553799024c7a41818945755 -942cf596b2278ad478be5c0ab6a2ad0ceafe110263cc93d15b9a3f420932104e462cf37586c374f10b1040cb83b862e0 -aaa077a55f501c875ceae0a27ef2b180be9de660ef3d6b2132eb17256771ce609d9bc8aaf687f2b56ae46af34ad12b30 -90ac74885be1448101cf3b957d4486e379673328a006ea42715c39916e9334ea77117ff4a60d858e2ccce9694547a14f -9256cdfc2339e89db56fd04bd9b0611be0eefc5ee30711bcece4aadf2efcc5a6dcc0cfd5f733e0e307e3a58055dff612 -a4c7384e208a0863f4c056248f595473dcde70f019ddaede45b8caf0752575c241bac6e436439f380ac88eee23a858e9 -a3aa67391781e0736dddc389f86b430b2fc293b7bd56bfd5a8ec01d1dd52ed940593c3ad4ce25905061936da062b0af6 -80299275ec322fbb66cc7dce4482ddd846534e92121186b6906c9a5d5834346b7de75909b22b98d73120caec964e7012 -aa3a6cd88e5f98a12738b6688f54478815e26778357bcc2bc9f2648db408d6076ef73cced92a0a6b8b486453c9379f18 -b07c444681dc87b08a7d7c86708b82e82f8f2dbd4001986027b82cfbed17b9043e1104ade612e8e7993a00a4f8128c93 -af40e01b68d908ac2a55dca9b07bb46378c969839c6c822d298a01bc91540ea7a0c07720a098be9a3cfe9c27918e80e8 -abd8947c3bbc3883c80d8c873f8e2dc9b878cbbb4fc4a753a68f5027de6d8c26aa8fbbafeb85519ac94e2db660f31f26 -a234f9d1a8f0cb5d017ccca30b591c95ec416c1cb906bd3e71b13627f27960f61f41ed603ffbcf043fd79974ec3169a8 -835aaf52a6af2bc7da4cf1586c1a27c72ad9de03c88922ad172dce7550d70f6f3efcc3820d38cd56ae3f7fc2f901f7a0 -ae75db982a45ad01f4aa7bc50d642ff188219652bb8d521d13a9877049425d57852f3c9e4d340ffec12a4d0c639e7062 -b88884aa9187c33dc784a96832c86a44d24e9ffe6315544d47fc25428f11337b9ffd56eb0a03ad709d1bf86175059096 -8492ca5afcc6c0187b06453f01ed45fd57eb56facbeea30c93686b9e1dab8eaabd89e0ccb24b5f35d3d19cd7a58b5338 -9350623b6e1592b7ea31b1349724114512c3cce1e5459cd5bddd3d0a9b2accc64ab2bf67a71382d81190c3ab7466ba08 -98e8bf9bed6ae33b7c7e0e49fc43de135bffdba12b5dcb9ff38cb2d2a5368bb570fe7ee8e7fbe68220084d1d3505d5be -ab56144393f55f4c6f80c67e0ab68f445568d68b5aa0118c0c666664a43ba6307ee6508ba0bb5eb17664817bc9749af0 -827d5717a41b8592cfd1b796a30d6b2c3ca2cdc92455f9f4294b051c4c97b7ad6373f692ddafda67884102e6c2a16113 -8445ce2bb81598067edaa2a9e356eda42fb6dc5dd936ccf3d1ff847139e6020310d43d0fec1fe70296e8f9e41a40eb20 -9405178d965ee51e8d76d29101933837a85710961bb61f743d563ef17263f3c2e161d57e133afac209cdb5c46b105e31 -b209f9ed324c0daa68f79800c0a1338bbaf6d37b539871cb7570f2c235caca238a2c4407961fcb7471a103545495ef2c -92ae6437af6bbd97e729b82f5b0d8fb081ca822f340e20fae1875bdc65694cd9b8c037a5a1d49aa9cae3d33f5bad414e -9445bdb666eae03449a38e00851629e29a7415c8274e93343dc0020f439a5df0009cd3c4f5b9ce5c0f79aefa53ceac99 -93fdab5f9f792eada28f75e9ac6042a2c7f3142ba416bfdb1f90aa8461dbe4af524eee6db4f421cb70c7bc204684d043 -a7f4dc949af4c3163953320898104a2b17161f7be5a5615da684f881633174fb0b712d0b7584b76302e811f3fac3c12f -a8ac84da817b3066ba9789bf2a566ccf84ab0a374210b8a215a9dcf493656a3fa0ecf07c4178920245fee0e46de7c3ec -8e6a0ae1273acda3aa50d07d293d580414110a63bc3fb6330bb2ee6f824aff0d8f42b7375a1a5ba85c05bfbe9da88cb5 -a5dea98852bd6f51a84fa06e331ea73a08d9d220cda437f694ad9ad02cf10657882242e20bdf21acbbaa545047da4ce5 -b13f410bf4cfce0827a5dfd1d6b5d8eabc60203b26f4c88238b8000f5b3aaf03242cdeadc2973b33109751da367069e1 -a334315a9d61b692ad919b616df0aa75a9f73e4ea6fc27d216f48964e7daebd84b796418580cf97d4f08d4a4b51037cd -8901ba9e963fcd2f7e08179b6d19c7a3b8193b78ca0e5cf0175916de873ca0d000cd7ac678c0473be371e0ac132f35a2 -b11a445433745f6cb14c9a65314bbf78b852f7b00786501b05d66092b871111cd7bee25f702d9e550d7dd91601620abb -8c2f7b8e7b906c71f2f154cc9f053e8394509c37c07b9d4f21b4495e80484fc5fc8ab4bdc525bd6cfa9518680ba0d1a2 -b9733cebe92b43b899d3d1bfbf4b71d12f40d1853b2c98e36e635fdd8a0603ab03119890a67127e6bc79afae35b0bef2 -a560f6692e88510d9ba940371e1ada344caf0c36440f492a3067ba38e9b7011caac37ba096a8a4accb1c8656d3c019b3 -ac18624339c1487b2626eef00d66b302bdb1526b6340d6847befe2fdfb2b410be5555f82939f8707f756db0e021ed398 -afd9a3b8866a7fe4f7bc13470c0169b9705fcd3073685f5a6dcff3bdbbc2be50ac6d9908f9a10c5104b0bffc2bc14dad -97f15c92fe1f10949ed9def5dd238bc1429706e5037a0e0afb71c2d0e5845e2fed95a171c393e372077a7c7059f8c0e0 -9453a1d4d09c309b70968ea527007d34df9c4cfd3048e5391aac5f9b64ca0c05dde5b8c949c481cfc83ef2e57b687595 -b80e4b7c379ad435c91b20b3706253b763cbc980db78f782f955d2516af44c07bbfa5888cbf3a8439dc3907320feb25a -8939f458d28fefe45320b95d75b006e98330254056d063e4a2f20f04bcb25936024efe8d436d491ed34b482f9b9ae49c -a9ead2e833f71f7e574c766440c4b3c9c3363698c7ade14499a56003a272832ee6d99440887fa43ccdf80265b9d56b97 -b6547a36934f05ce7b779e68049d61351cf229ae72dc211cc96a2a471b2724782f9355fdb415ea6f0ea1eb84fe00e785 -828bfb3099b7b650b29b0f21279f829391f64520a6ab916d1056f647088f1e50fac9253ef7464eceab5380035c5a59c4 -8d714b9ea650be4342ff06c0256189e85c5c125adf6c7aeca3dba9b21d5e01a28b688fc2116ce285a0714a8f1425c0b8 -8a82eda041b2e72a3d73d70d85a568e035fbd6dc32559b6c6cfdf6f4edcb59a6ba85b6294a721aa0a71b07714e0b99ae -af5665ebc83d027173b14ffb0e05af0a192b719177889fadc9ac8c082fda721e9a75d9ce3f5602dbfd516600ee3b6405 -a68fdddf03d77bebdb676e40d93e59bd854408793df2935d0a5600601f7691b879981a398d02658c2da39dbbf61ef96c -8c001ebc84fcf0470b837a08a7b6125126b73a2762db47bbdc38c0e7992b1c66bac7a64faa1bf1020d1c63b40adc3082 -8553889b49f9491109792db0a69347880a9cf2911b4f16f59f7f424e5e6b553687d51282e8f95be6a543635247e2e2c2 -a2c269d6370b541daf1f23cc6b5d2b03a5fa0c7538d53ae500ef875952fe215e74a5010329ff41461f4c58b32ad97b3d -a5dae097285392b4eba83a9fd24baa03d42d0a157a37fae4b6efc3f45be86024b1182e4a6b6eadcf5efe37704c0a1ae5 -89871a77d2032387d19369933cd50a26bda643e40cfd0ce73febe717a51b39fae981406fd41e50f4a837c02a99524ef9 -8a76d495e90093ec2ac22f53759dc1cf36fbb8370fb586acbd3895c56a90bbf3796bcc4fc422ca4058adf337ead1402e -ad4eb7576c4954d20623c1336c63662c2a6fb46ec6ef99b7f8e946aa47488dcb136eab60b35600f98c78c16c10c99013 -894c2b120cec539feb1d281baaadde1e44beafedeeec29b804473fe024e25c1db652f151c956e88d9081fb39d27e0b19 -9196bd5c100878792444c573d02b380a69e1b4b30cb59a48114852085058a5fd952df4afee3ecceb5c4ede21e1ed4a1a -a996fffc910764ea87a1eedc3a3d600e6e0ff70e6a999cb435c9b713a89600fc130d1850174efe9fc18244bb7c6c5936 -8591bb8826befa8bee9663230d9a864a5068589f059e37b450e8c85e15ce9a1992f0ce1ead1d9829b452997727edcf9d -9465e20bb22c41bf1fa728be8e069e25cda3f7c243381ca9973cbedad0c7b07d3dd3e85719d77cf80b1058ce60e16d68 -926b5ce39b6e60b94878ffeae9ff20178656c375fb9cfe160b82318ca500eb3e2e3144608b6c3f8d6c856b8fe1e2fbcf -a1ef29cbc83c45eb28ad468d0ce5d0fdd6b9d8191ba5ffa1a781c2b232ed23db6b7b04de06ef31763a6bfe377fa2f408 -9328e63a3c8acf457c9f1f28b32d90d0eeadb0f650b5d43486a61d7374757a7ada5fc1def2a1e600fa255d8b3f48036f -a9c64880fcb7654f4dd08f4c90baac95712dd6dd407e17ea60606e9a97dc8e54dd25cb72a9bf3fc61f8d0ad569fe369d -a908eb7b940c1963f73046d6b35d40e09013bfbfbeb2ccd64df441867e202b0f3b625fa32dd04987c3d7851360abdffc -b3947b5ed6d59e59e4472cdb1c3261de1b5278fb7cb9b5fca553f328b3b3e094596861ea526eca02395f7b7358155b7b -99da7f190d37bc58945f981cf484d40fcf0855cf8178e2ce8d057c7f0a9d9f77425fdbce9ef8366f44f671b20fd27d0b -913976d77d80e3657977df39571577fdf0be68ba846883705b454f8493578baa741cfaede53783e2c97cc08964395d83 -8d754a61e5164a80b5090c13f3e936056812d4ae8dc5cc649e6c7f37464777249bc4ae760a9806939131f39d92cca5bf -82ffd098480828a90cb221a8c28584e15904bad477c13b2e2d6ef0b96a861ce4a309a328fe44342365349456ad7c654f -89ae3ce4b0357044579ca17be85d8361bb1ce3941f87e82077dd67e43ec0f95edd4bd3426225c90994a81a99e79490b7 -a170892074016d57c9d8e5a529379d7e08d2c1158b9ac4487ac9b95266c4fd51cb18ae768a2f74840137eec05000dd5a -aafd8acd1071103c7af8828a7a08076324d41ea530df90f7d98fafb19735fc27ead91b50c2ca45851545b41d589d0f77 -8623c849e61d8f1696dc9752116a26c8503fd36e2cbbc9650feffdd3a083d8cdbb3b2a4e9743a84b9b2ad91ac33083f2 -ac7166ddd253bb22cdbd8f15b0933c001d1e8bc295e7c38dc1d2be30220e88e2155ecd2274e79848087c05e137e64d01 -a5276b216d3df3273bbfa46210b63b84cfe1e599e9e5d87c4e2e9d58666ecf1af66cb7ae65caebbe74b6806677215bd0 -88792f4aa3597bb0aebadb70f52ee8e9db0f7a9d74f398908024ddda4431221a7783e060e0a93bf1f6338af3d9b18f68 -8f5fafff3ecb3aad94787d1b358ab7d232ded49b15b3636b585aa54212f97dc1d6d567c180682cca895d9876cacb7833 -ab7cb1337290842b33e936162c781aa1093565e1a5b618d1c4d87dd866daea5cebbcc486aaa93d8b8542a27d2f8694c7 -88480a6827699da98642152ebc89941d54b4791fbc66110b7632fb57a5b7d7e79943c19a4b579177c6cf901769563f2f -a725ee6d201b3a610ede3459660658ee391803f770acc639cfc402d1667721089fb24e7598f00e49e81e50d9fd8c2423 -98924372da8aca0f67c8c5cad30fa5324519b014fae7849001dcd51b6286118f12b6c49061219c37714e11142b4d46de -a62c27360221b1a7c99697010dfe1fb31ceb17d3291cf2172624ebeff090cbaa3c3b01ec89fe106dace61d934711d42d -825173c3080be62cfdc50256c3f06fe190bc5f190d0eb827d0af5b99d80936e284a4155b46c0d462ee574fe31d60983d -a28980b97023f9595fadf404ed4aa36898d404fe611c32fd66b70252f01618896f5f3fda71aea5595591176aabf0c619 -a50f5f9def2114f6424ff298f3b128068438f40860c2b44e9a6666f43c438f1780be73cf3de884846f1ba67f9bef0802 -b1eee2d730da715543aeb87f104aff6122cb2bf11de15d2519ff082671330a746445777924521ec98568635f26988d0c -862f6994a1ff4adfd9fb021925cccf542fca4d4b0b80fb794f97e1eb2964ef355608a98eec6e07aadd4b45ee625b2a21 -8ce69a18df2f9b9f6e94a456a7d94842c61dea9b00892da7cf5c08144de9be39b8c304aeca8b2e4222f87ba367e61006 -b5f325b1cecd435f5346b6bc562d92f264f1a6d91be41d612df012684fdd69e86063db077bc11ea4e22c5f2a13ae7bee -85526870a911127835446cb83db8986b12d5637d59e0f139ad6501ac949a397a6c73bd2e7fba731b1bb357efe068242c -8552247d3f7778697f77389717def5a149fc20f677914048e1ed41553b039b5427badc930491c0bae663e67668038fd1 -a545640ee5e51f3fe5de7050e914cfe216202056cd9d642c90e89a166566f909ee575353cb43a331fde17f1c9021414e -8b51229b53cff887d4cab573ba32ec52668d197c084414a9ee5589b285481cea0c3604a50ec133105f661321c3ca50f5 -8cdc0b960522bed284d5c88b1532142863d97bbb7dc344a846dc120397570f7bd507ceb15ed97964d6a80eccfef0f28e -a40683961b0812d9d53906e795e6470addc1f30d09affebf5d4fbbd21ddfa88ce441ca5ea99c33fd121405be3f7a3757 -a527875eb2b99b4185998b5d4cf97dd0d4a937724b6ad170411fc8e2ec80f6cee2050f0dd2e6fee9a2b77252d98b9e64 -84f3a75f477c4bc4574f16ebc21aaa32924c41ced435703c4bf07c9119dd2b6e066e0c276ff902069887793378f779e0 -a3544bc22d1d0cab2d22d44ced8f7484bfe391b36991b87010394bfd5012f75d580596ffd4f42b00886749457bb6334b -b81f6eb26934b920285acc20ceef0220dd23081ba1b26e22b365d3165ce2fbae733bbc896bd0932f63dcc84f56428c68 -95e94d40a4f41090185a77bf760915a90b6a3e3ace5e53f0cb08386d438d3aa3479f0cd81081b47a9b718698817265cd -b69bd1625b3d6c17fd1f87ac6e86efa0d0d8abb69f8355a08739109831baeec03fd3cd4c765b5ff8b1e449d33d050504 -8448f4e4c043519d98552c2573b76eebf2483b82d32abb3e2bfc64a538e79e4f59c6ca92adff1e78b2f9d0a91f19e619 -8f11c42d6a221d1fda50887fb68b15acdb46979ab21d909ed529bcad6ae10a66228ff521a54a42aca0dad6547a528233 -a3adb18d7e4a882b13a067784cf80ea96a1d90f5edc61227d1f6e4da560c627688bdf6555d33fe54cab1bca242986871 -a24d333d807a48dc851932ed21cbdd7e255bad2699909234f1706ba55dea4bb6b6f8812ffc0be206755868ba8a4af3f9 -a322de66c22a606e189f7734dbb7fda5d75766d5e69ec04b4e1671d4477f5bcb9ff139ccc18879980ebc3b64ab4a2c49 -88f54b6b410a1edbf125db738d46ee1a507e69bc5a8f2f443eb787b9aa7dbd6e55014ec1e946aabeb3e27a788914fb04 -b32ee6da1dcd8d0a7fd7c1821bb1f1fe919c8922b4c1eeed56e5b068a5a6e68457c42b192cbaef5dc6d49b17fa45bc0f -8a44402da0b3a15c97b0f15db63e460506cb8bef56c457166aea5e8881087d8202724c539ef0feb97131919a73aefca8 -b967e3fead6171fa1d19fd976535d428b501baff59e118050f9901a54b12cc8e4606348454c8f0fc25bd6644e0a5532e -b7a0c9e9371c3efbbb2c6783ce2cc5f149135175f25b6d79b09c808bce74139020e77f0c616fa6dcb3d87a378532529d -a54207782ffc909cd1bb685a3aafabbc4407cda362d7b3c1b14608b6427e1696817aeb4f3f85304ac36e86d3d8caa65b -98c1da056813a7bfebc81d8db7206e3ef9b51f147d9948c088976755826cc5123c239ca5e3fe59bed18b5d0a982f3c3f -ae1c86174dfafa9c9546b17b8201719aecd359f5bbeb1900475041f2d5b8a9600d54d0000c43dd061cfda390585726ff -a8ee5a8be0bd1372a35675c87bfd64221c6696dc16e2d5e0996e481fec5cdbcb222df466c24740331d60f0521285f7d3 -8ddadbe3cf13af50d556ce8fc0dd77971ac83fad9985c3d089b1b02d1e3afc330628635a31707b32595626798ea22d45 -a5c80254baf8a1628dc77c2445ebe21fbda0de09dd458f603e6a9851071b2b7438fe74214df293dfa242c715d4375c95 -b9d83227ed2600a55cb74a7052003a317a85ca4bea50aa3e0570f4982b6fe678e464cc5156be1bd5e7bba722f95e92c5 -b56085f9f3a72bea9aa3a8dc143a96dd78513fa327b4b9ba26d475c088116cab13843c2bff80996bf3b43d3e2bddb1d6 -8fa9b39558c69a9757f1e7bc3f07295e4a433da3e6dd8c0282397d26f64c1ecd8eb3ba9824a7cacfb87496ebbb45d962 -879c6d0cb675812ed9dee68c3479a499f088068501e2677caeae035e6f538da91a49e245f5fcce135066169649872bee -91aa9fd3fed0c2a23d1edda8a6542188aeb8abee8772818769bdee4b512d431e4625a343af5d59767c468779222cf234 -a6be0bb2348c35c4143482c7ef6da9a93a5356f8545e8e9d791d6c08ed55f14d790d21ee61d3a56a2ae7f888a8fd46ca -808ee396a94e1b8755f2b13a6ffbedef9e0369e6c2e53627c9f60130c137299d0e4924d8ef367e0a7fad7f68a8c9193c -ad1086028fcdac94d5f1e7629071e7e47e30ad0190ae59aaebfb7a7ef6202ab91323a503c527e3226a23d7937af41a52 -9102bdaf79b907d1b25b2ec6b497e2d301c8eac305e848c6276b392f0ad734131a39cc02ed42989a53ca8da3d6839172 -8c976c48a45b6bc7cd7a7acea3c2d7c5f43042863b0661d5cd8763e8b50730552187a8eecf6b3d17be89110208808e77 -a2624c7e917e8297faa3af89b701953006bf02b7c95dfba00c9f3de77748bc0b13d6e15bb8d01377f4d98fb189538142 -a405f1e66783cdcfe20081bce34623ec3660950222d50b7255f8b3cc5d4369aeb366e265e5224c0204911539f0fa165e -8d69bdcaa5d883b5636ac8f8842026fcc58c5e2b71b7349844a3f5d6fbecf44443ef4f768eac376f57fb763606e92c9f -82fce0643017d16ec1c3543db95fb57bfa4855cc325f186d109539fcacf8ea15539be7c4855594d4f6dc628f5ad8a7b0 -8860e6ff58b3e8f9ae294ff2487f0d3ffae4cf54fd3e69931662dabc8efd5b237b26b3def3bcd4042869d5087d22afcf -88c80c442251e11c558771f0484f56dc0ed1b7340757893a49acbf96006aa73dfc3668208abea6f65375611278afb02a -8be3d18c6b4aa8e56fcd74a2aacb76f80b518a360814f71edb9ccf3d144bfd247c03f77500f728a62fca7a2e45e504c5 -8b8ebf0df95c3f9b1c9b80469dc0d323784fd4a53f5c5357bb3f250a135f4619498af5700fe54ad08744576588b3dfff -a8d88abdaadd9c2a66bc8db3072032f63ed8f928d64fdb5f810a65074efc7e830d56e0e738175579f6660738b92d0c65 -a0a10b5d1a525eb846b36357983c6b816b8c387d3890af62efb20f50b1cb6dd69549bbef14dab939f1213118a1ae8ec2 -8aadf9b895aeb8fdc9987daa937e25d6964cbd5ec5d176f5cdf2f0c73f6f145f0f9759e7560ab740bf623a3279736c37 -99aeda8a495031cc5bdf9b842a4d7647c55004576a0edc0bd9b985d60182608361ed5459a9d4b21aa8e2bd353d10a086 -832c8b3bfcd6e68eee4b100d58014522de9d4cefa99498bc06c6dca83741e4572e20778e0d846884b33439f160932bca -841f56ebefc0823ab484fc445d62f914e13957e47904419e42771aa605e33ab16c44f781f6f9aa42e3a1baf377f54b42 -a6e40271d419e295a182725d3a9b541ffd343f23e37549c51ecaa20d13cf0c8d282d6d15b24def5702bfee8ba10b12ac -8ac00925ac6187a4c5cde48ea2a4eaf99a607e58b2c617ee6f01df30d03fafada2f0469178dd960d9d64cbd33a0087d8 -b6b80916b540f8a0fe4f23b1a06e2b830008ad138271d5ba3cd16d6619e521fe2a7623c16c41cba48950793386eea942 -8412c0857b96a650e73af9d93087d4109dd092ddf82188e514f18fcac644f44d4d62550bfa63947f2d574a2e9d995bbb -b871395baa28b857e992a28ac7f6d95ec461934b120a688a387e78498eb26a15913b0228488c3e2360391c6b7260b504 -926e2d25c58c679be77d0e27ec3b580645956ba6f13adcbc2ea548ee1b7925c61fcf74c582337a3b999e5427b3f752f2 -a165fa43fecae9b913d5dcfc232568e3e7b8b320ce96b13800035d52844c38fd5dbf7c4d564241d860c023049de4bcbc -b4976d7572fd9cc0ee3f24888634433f725230a7a2159405946a79315bc19e2fc371448c1c9d52bf91539fd1fe39574b -a6b461eb72e07a9e859b9e16dfa5907f4ac92a5a7ca4368b518e4a508dc43f9b4be59db6849739f3ef4c44967b63b103 -b976606d3089345d0bc501a43525d9dca59cf0b25b50dfc8a61c5bd30fac2467331f0638fab2dc68838aa6ee8d2b6bc9 -b16ea61c855da96e180abf7647fa4d9dd6fd90adebadb4c5ed4d7cd24737e500212628fca69615d89cb40e9826e5a214 -95a3e3162eb5ea27a613f8c188f2e0dcc5cbd5b68c239858b989b004d87113e6aa3209fa9fad0ee6ecef42814ba9db1a -b6a026ab56d3224220e5bce8275d023c8d39d1bdf7eec3b0923429b7d5ef18cf613a3591d364be8727bb1fa0ba11eabb -949f117e2e141e25972ee9ccdd0b7a21150de7bbf92bbd89624a0c5f5a88da7b2b172ba2e9e94e1768081f260c2a2f8d -b7c5e9e6630287d2a20a2dfb783ffe6a6ff104ff627c6e4e4342acc2f3eb6e60e9c22f465f8a8dc58c42f49840eca435 -872be5a75c3b85de21447bb06ac9eb610f3a80759f516a2f99304930ddf921f34cbffc7727989cdd7181d5fc62483954 -a50976ea5297d797d220932856afdd214d1248230c9dcd840469ecc28ea9f305b6d7b38339fedb0c00b5251d77af8c95 -80b360f8b44914ff6f0ffbd8b5360e3cabe08639f6fe06d0c1526b1fe9fe9f18c497f1752580b30e950abd3e538ad416 -a2f98f9bf7fac78c9da6bb41de267742a9d31cf5a04b2fb74f551084ec329b376f651a59e1ae919b2928286fb566e495 -8b9d218a8a6c150631548e7f24bbd43f132431ae275c2b72676abbea752f554789c5ff4aac5c0eeee5529af7f2b509ef -aa21a243b07e9c7b169598bf0b102c3c280861780f83121b2ef543b780d47aaa4b1850430ee7927f33ece9847c4e0e1a -8a6f90f4ce58c8aa5d3656fe4e05acccf07a6ec188a5f3cde7bf59a8ae468e66f055ac6dfc50b6e8e98f2490d8deedc5 -8e39f77ca4b5149ffe9945ceac35d068760ba338d469d57c14f626dd8c96dbe993dd7011beff727c32117298c95ee854 -83bd641c76504222880183edd42267e0582642c4993fe2c7a20ce7168e4c3cbf7586e1d2d4b08c84d9b0bf2f6b8800b8 -a9d332993cf0c1c55130e5cf3a478eb5e0bfb49c25c07538accc692ef03d82b458750a7b991cc0b41b813d361a5d31e3 -a0fc60e6a6015df9bee04cea8f20f01d02b14b6f7aa03123ab8d65da071b2d0df5012c2a69e7290baae6ed6dd29ebe07 -a2949dde2e48788ceaac7ec7243f287ffe7c3e788cdba97a4ab0772202aeef2d50382bed8bf7eff5478243f7eabe0bda -a7879373ea18572dba6cf29868ca955ffa55b8af627f29862f6487ee398b81fe3771d8721ca8e06716c5d91b9ac587cb -b3c7081e2c5306303524fbe9fe5645111a57dffd4ec25b7384da12e56376a0150ab52f9d9cc6ca7bdd950695e39b766d -a634a6a19d52dcb9f823352b36c345d2de54b75197bcd90528d27830bd6606d1a9971170de0849ed5010afa9f031d5be -88f2062f405fa181cfdb8475eaf52906587382c666ca09a9522537cfebbc7de8337be12a7fd0db6d6f2f7ab5aefab892 -b1f0058c1f273191247b98783b2a6f5aa716cf799a8370627fc3456683f03a624d0523b63a154fe9243c0dfd5b37c460 -ae39a227cc05852437d87be6a446782c3d7fbe6282e25cf57b6b6e12b189bdc0d4a6e2c3a60b3979256b6b5baf8f1c5f -802a1af228ab0c053b940e695e7ef3338f5be7acf4e5ed01ac8498e55b492d3a9f07996b1700a84e22f0b589638909cd -a36490832f20e4b2f9e79ee358b66d413f034d6a387534b264cdeac2bca96e8b5bcbdd28d1e98c44498032a8e63d94d2 -8728c9a87db2d006855cb304bba54c3c704bf8f1228ae53a8da66ca93b2dac7e980a2a74f402f22b9bc40cd726e9c438 -a08f08ab0c0a1340e53b3592635e256d0025c4700559939aeb9010ed63f7047c8021b4210088f3605f5c14fb51d1c613 -9670fd7e2d90f241e8e05f9f0b475aa260a5fb99aa1c9e61cd023cbad8ed1270ae912f168e1170e62a0f6d319cf45f49 -a35e60f2dd04f098bf274d2999c3447730fe3e54a8aff703bc5a3c274d22f97db4104d61a37417d93d52276b27ef8f31 -859df7a21bc35daec5695201bd69333dc4f0f9e4328f2b75a223e6615b22b29d63b44d338413ca97eb74f15563628cb7 -b2b44ad3e93bc076548acdf2477803203108b89ecc1d0a19c3fb9814d6b342afc420c20f75e9c2188ad75fdb0d34bb2d -941173ee2c87765d10758746d103b667b1227301e1bcfecef2f38f9ab612496a9abd3050cef5537bf28cfecd2aacc449 -92b0bea30ebed20ac30648efb37bac2b865daaa514316e6f5470e1de6cb84651ff77c127aa7beed4521bda5e8fc81122 -af17bf813bb238cf8bb437433f816786612209180a6c0a1d5141292dc2d2c37164ef13bfc50c718bfcc6ce26369298a2 -8461fd951bdfda099318e05cc6f75698784b033f15a71bce26165f0ce421fd632d50df9eeced474838c0050b596e672c -83281aa18ae4b01e8201e1f64248cc6444c92ee846ae72adb178cef356531558597d84ff93a05abf76bfe313eb7dbe86 -b62b150f73999c341daa4d2f7328d2f6ca1ef3b549e01df58182e42927537fc7971c360fe8264af724f4c0247850ef12 -a7022a201f79c012f982b574c714d813064838a04f56964d1186691413757befeeaada063e7884297606e0eea1b1ed43 -a42ac9e8be88e143853fd8e6a9ff21a0461801f0ac76b69cca669597f9af17ecb62cccdcdcbe7f19b62ab93d7f838406 -80f1ca73b6ba3a2fbae6b79b39c0be8c39df81862d46c4990c87cbf45b87996db7859d833abc20af2fcb4faf059c436a -b355943e04132d5521d7bbe49aea26f6aa1c32f5d0853e77cc2400595325e923a82e0ff7601d1aee79f45fd8a254f6ae -87142c891d93e539b31d0b5ead9ea600b9c84db9be9369ff150a8312fe3d10513f4c5b4d483a82b42bc65c45dd9dd3bd -823c3d7f6dda98a9d8c42b3fee28d3154a95451402accadb6cf75fc45d2653c46a569be75a433094fa9e09c0d5cf1c90 -b3c3497fe7356525c1336435976e79ec59c5624c2fb6185ee09ca0510d58b1e392965e25df8a74d90d464c4e8bb1422b -88c48d83e8ddc0d7eea051f3d0e21bc0d3a0bb2b6a39ece76750c1c90c382a538c9a35dc9478b8ceb8157dcccbbf187a -93da81a8939f5f58b668fefdc6f5f7eca6dc1133054de4910b651f8b4a3267af1e44d5a1c9e5964dc7ab741eb146894b -8b396e64985451ac337f16be61105106e262e381ea04660add0b032409b986e1ac64da3bc2feae788e24e9cb431d8668 -9472068b6e331ea67e9b5fbf8057672da93c209d7ded51e2914dbb98dccd8c72b7079b51fd97a7190f8fc8712c431538 -ac47e1446cb92b0a7406f45c708567f520900dfa0070d5e91783139d1bfc946d6e242e2c7b3bf4020500b9f867139709 -896053706869fb26bb6f7933b3d9c7dd6db5c6bd1269c7a0e222b73039e2327d44bda7d7ae82bf5988808b9831d78bcd -a55e397fa7a02321a9fe686654c86083ecedb5757586d7c0250ec813ca6d37151a12061d5feca4691a0fd59d2f0fdd81 -ae23f08ac2b370d845036518f1bddb7fea8dc59371c288a6af310486effeb61963f2eef031ca90f9bdbcf0e475b67068 -b5462921597a79f66c0fec8d4c7cfd89f427692a7ce30d787e6fd6acd2377f238ec74689a0fdbe8ef3c9c9bd24b908dc -ae67e8ea7c46e29e6aae6005131c29472768326819aa294aaf5a280d877de377b44959adb1348fa3e929dcbc3ae1f2c0 -84962b4c66500a20c4424191bdfb619a46cda35bdb34c2d61edcb0b0494f7f61dd5bf8f743302842026b7b7d49edd4b5 -846f76286dc3cc59cb15e5dabb72a54a27c78190631df832d3649b2952fa0408ecde7d4dfdae7046c728efa29879fb51 -8f76c854eaee8b699547e07ad286f7dadfa6974c1328d12502bd7630ae619f6129272fdd15e2137ffef0143c42730977 -8007b163d4ea4ec6d79e7a2aa19d06f388da0b3a56f3ee121441584e22a246c0e792431655632bf6e5e02cb86914eebf -ac4d2cecc1f33e6fb73892980b61e62095ddff5fd6167f53ca93d507328b3c05440729a277dc3649302045b734398af1 -92d2a88f2e9c9875abaff0d42624ccb6d65401de7127b5d42c25e6adccd7a664504c5861618f9031ced8aeb08b779f06 -a832c1821c1b220eb003fc532af02c81196e98df058cdcc9c9748832558362915ea77526937f30a2f74f25073cb89afb -b6f947ab4cc2baec100ed8ec7739a2fd2f9504c982b39ab84a4516015ca56aea8eef5545cfc057dd44c69b42125fb718 -b24afacf2e90da067e5c050d2a63878ee17aaf8fd446536f2462da4f162de87b7544e92c410d35bf2172465940c19349 -b7a0aa92deac71eaab07be8fa43086e071e5580f5dbf9b624427bdd7764605d27303ae86e5165bed30229c0c11958c38 -b0d1d5bfa1823392c5cf6ed927c1b9e84a09a24b284c2cd8fcb5fda8e392c7c59412d8f74eb7c48c6851dff23ae66f58 -a24125ef03a92d2279fb384186ca0274373509cfec90b34a575490486098438932ee1be0334262d22d5f7d3db91efe67 -83e08e5fba9e8e11c164373794f4067b9b472d54f57f4dbe3c241cf7b5b7374102de9d458018a8c51ab3aed1dddf146f -9453101b77bb915ed40990e1e1d2c08ea8ec5deb5b571b0c50d45d1c55c2e2512ec0ceca616ff0376a65678a961d344d -92a0516e9eb6ad233d6b165a8d64a062ce189b25f95d1b3264d6b58da9c8d17da2cd1f534800c43efcf2be73556cd2ff -958d0b5d7d8faf25d2816aa6a2c5770592ad448db778dd9b374085baa66c755b129822632eaabcb65ee35f0bf4b73634 -90a749de8728b301ad2a6b044e8c5fd646ccd8d20220e125cba97667e0bb1d0a62f6e3143b28f3d93f69cdc6aa04122a -84bd34c8d8f74dec07595812058db24d62133c11afed5eb2a8320d3bfc28e442c7f0cfd51011b7b0bb3e5409cb7b6290 -aecc250b556115d97b553ad7b2153f1d69e543e087890000eaa60f4368b736921d0342ce5563124f129096f5d5e2ca9d -977f17ac82ed1fbf422f9b95feb3047a182a27b00960296d804fd74d54bb39ad2c055e665c1240d2ad2e06a3d7501b00 -af5be9846bd4879ebe0af5e7ad253a632f05aedfe306d31fe6debe701ba5aa4e33b65efc05043bc73aadb199f94baed4 -9199e12ec5f2aaaeed6db5561d2dcc1a8fe9c0854f1a069cba090d2dff5e5ba52b10c841ccbd49006a91d881f206150d -8f4a96a96ed8ceaf3beba026c89848c9ca4e6452ce23b7cf34d12f9cc532984a498e051de77745bdc17c7c44c31b7c30 -af3f2a3dbe8652c4bfca0d37fb723f0e66aab4f91b91a625114af1377ad923da8d36da83f75deb7a3219cd63135a3118 -a6d46963195df8962f7aa791d104c709c38caa438ddd192f7647a884282e81f748c94cdf0bb25d38a7b0dc1b1d7bbcf7 -86f3de4b22c42d3e4b24b16e6e8033e60120af341781ab70ae390cb7b5c5216f6e7945313c2e04261a51814a8cb5db92 -b9f86792e3922896cfd847d8ff123ff8d69ecf34968fb3de3f54532f6cd1112b5d34eeabdca46ae64ad9f6e7e5b55edc -83edfbcbc4968381d1e91ab813b3c74ab940eaf6358c226f79182f8b21148ec130685fd91b0ea65916b0a50bccf524ea -93b61daca7a8880b7926398760f50016f2558b0bab74c21181280a1baf3414fc539911bb0b79c4288d29d3c4ad0f4417 -ad541aeb83a47526d38f2e47a5ce7e23a9adabe5efeae03541026881e6d5ef07da3ac1a6ed466ca924fa8e7a91fcff88 -ac4bba31723875025640ed6426003ed8529215a44c9ffd44f37e928feef9fc4dfa889088131c9be3da87e8f3fdf55975 -88fa4d49096586bc9d29592909c38ea3def24629feacd378cc5335b70d13814d6dac415f8c699ee1bf4fe8b85eb89b38 -b67d0b76cbd0d79b71f4673b96e77b6cda516b8faa1510cfe58ff38cc19000bb5d73ff8418b3dab8c1c7960cb9c81e36 -98b4f8766810f0cfecf67bd59f8c58989eb66c07d3dfeee4f4bbce8fd1fce7cc4f69468372eaec7d690748543bd9691d -8445891af3c298b588dec443beacdf41536adb84c812c413a2b843fd398e484eb379075c64066b460839b5fe8f80177c -b603635c3ed6fdc013e2a091fc5164e09acf5f6a00347d87c6ebadb1f44e52ff1a5f0466b91f3f7ffc47d25753e44b75 -87ec2fc928174599a9dafe7538fec7dcf72e6873b17d953ed50708afff0da37653758b52b7cafa0bf50dfcf1eafbb46c -b9dbd0e704d047a457d60efe6822dc679e79846e4cbcb11fa6c02079d65673ee19bbf0d14e8b7b200b9205f4738df7c7 -9591ec7080f3f5ba11197a41f476f9ba17880f414d74f821a072ec5061eab040a2acba3d9856ff8555dfe5eaeb14ca19 -b34c9d1805b5f1ce38a42b800dec4e7f3eb8c38e7d2b0a525378e048426fed150dbfe9cc61f5db82b406d1b9ff2d10bf -a36fdc649dc08f059dfa361e3969d96b4cc4a1ebf10b0cd01a7dd708430979e8d870961fef85878f8779b8e23caafb18 -88dfc739a80c16c95d9d6f73c3357a92d82fa8c3c670c72bee0f1e4bac9ec338e1751eb786eda3e10f747dd7a686900f -84a535ad04f0961756c61c70001903a9adf13126983c11709430a18133c4b4040d17a33765b4a06968f5d536f4bfb5c5 -8c86d695052a2d2571c5ace744f2239840ef21bb88e742f050c7fa737cd925418ecef0971333eb89daa6b3ddfede268c -8e9a700157069dc91e08ddcbdde3a9ad570272ad225844238f1015004239c542fceb0acce6d116c292a55f0d55b6175e -84d659e7f94e4c1d15526f47bc5877a4ef761c2a5f76ec8b09c3a9a30992d41b0e2e38ed0c0106a6b6c86d670c4235f3 -a99253d45d7863db1d27c0ab561fb85da8c025ba578b4b165528d0f20c511a9ca9aff722f4ff7004843f618eb8fced95 -89a3cacb15b84b20e95cd6135550146bbe6c47632cc6d6e14d825a0c79b1e02b66f05d57d1260cb947dc4ae5b0283882 -8385b1555e794801226c44bd5e878cbe68aeac0a19315625a8e5ea0c3526b58cdd4f53f9a14a167a5e8a293b530d615a -b68c729e9df66c5cd22af4909fb3b0057b6a231c4a31cd6bf0fa0e53c5809419d15feb483de6e9408b052458e819b097 -924f56eda269ec7ec2fc20c5731bf7f521546ddf573ccbe145592f1c9fee5134747eb648d9335119a8066ca50a1f7e50 -b2100a26b9c3bec7ec5a53f0febbf56303f199be2f26b2d564cfee2adc65483b84192354f2865c2f4c035fa16252ae55 -8f64dbed62e638563967ec1605a83216aed17eb99aa618c0543d74771ea8f60bbb850c88608d4f8584f922e30a8a0a72 -b31b9e1ffe8d7260479c9413f8e680f3fe391ae8fcf44fcca3000d9b2473a40c1d32299f8f63865a57579a2d6c7e9f08 -a5b1d136142eb23e322c6c07cb838a3f58ab6925472352ebd0bb47041a0d8729e1074ca223922f3a7a672ced7a1e562d -8d9470a5a15d833a447b5f108333d50f30aa7659e331c3f8080b1e928a99922edc650466a2f54f3d48afdb34bff42142 -866368f5891564e5b2de37ad21ff0345c01129a14ea5667f9b64aad12d13ec034622872e414743af0bf20adb2041b497 -88ef9c2ebf25fd0c04b7cfa35fbac2e4156d2f1043fa9f98998b2aa402c8f9a4f1039e782451a46840f3e0e4b3fa47d3 -94ba04a4859273697e264a2d238dc5c9ff573ebc91e4796ea58eebe4080c1bf991255ab2ad8fb1e0301ce7b79cc6e69b -86b6bd0953309a086e526211bf1a99327269304aa74d8cdc994cee63c3a2d4b883e832b0635888dff2a13f1b02eb8df4 -843ea6ea5f2c7a1fd50be56a5765dcce3ea61c99b77c1a729ee0cd8ec706385ac7062e603479d4c8d3527f030762d049 -8d3675195a3b06f2d935d45becc59f9fa8fa440c8df80c029775e47fe9c90e20f7c8e4cc9a2542dd6bfe87536c428f0d -8978580b0c9b0aa3ab2d47e3cfd92fa891d3ddee57829ee4f9780e8e651900457d8e759d1a9b3e8f6ae366e4b57f2865 -890112ec81d0f24b0dfbb4d228e418eff02ae63dc691caf59c1d103e1d194e6e2550e1bec41c0bfdb74fed454f621d0c -97da00bd4b19d1e88caff7f95b8b9a7d29bc0afe85d0c6a163b4b9ef336f0e90e2c49ce6777024bb08df908cc04ea1ca -b458268d275a5211106ccaa8333ce796ef2939b1c4517e502b6462e1f904b41184a89c3954e7c4f933d68b87427a7bfd -aac9c043ba8ba9283e8428044e6459f982413380ee7005a996dc3cc468f6a21001ecaa3b845ce2e73644c2e721940033 -82145013c2155a1200246a1e8720adf8a1d1436b10d0854369d5b1b6208353e484dd16ce59280c6be84a223f2d45e5e2 -b301bafa041f9b203a46beab5f16160d463aa92117c77a3dc6a9261a35645991b9bafcc186c8891ca95021bd35f7f971 -a531b8d2ac3de09b92080a8d8857efa48fb6a048595279110e5104fee7db1dd7f3cfb8a9c45c0ed981cbad101082e335 -a22ac1d627d08a32a8abd41504b5222047c87d558ffae4232cefdeb6a3dc2a8671a4d8ddfba2ff9068a9a3ffb0fe99b1 -b8d9f0e383c35afb6d69be7ff04f31e25c74dd5751f0e51290c18814fbb49ee1486649e64355c80e93a3d9278bd21229 -8165babccd13033a3614c878be749dfa1087ecbeee8e95abcfffe3aa06695711122cb94477a4d55cffd2febf0c1173de -a4c1bc84ecb9d995d1d21c2804adf25621676d60334bd359dac3a2ec5dc8de567aa2831c10147034025fb3e3afb33c4b -b77307cab8e7cb21e4038493058fb6db9e2ec91dda9d7f96f25acbc90309daf7b6d8a205682143ee35d675e9800c3b08 -aaf7466083cd1f325ba860efe3faf4cebe6a5eecf52c3e8375d72043a5cfc8e6cb4b40f8e48f97266e84f0d488e8badf -9264a05a3abc2a5b4958f957f3a486a5eb3ddd10ff57aa6943c9430d0cfa01d63b72695b1ade50ac1b302d312175e702 -b3f9e4c589ad28b1eceed99dc9980fac832524cfcbe4a486dfeedb4b97c080e24bdb3967e9ca63d2240e77f9addfaefd -b2c1e253a78e7179e5d67204422e0debfa09c231970b1bfb70f31a8d77c7f5059a095ca79d2e9830f12c4a8f88881516 -81865a8a25913d1072cb5fd9505c73e0fde45e4c781ddd20fb0a7560d8b1cd5e1f63881c6efc05360e9204dfa6c3ce16 -ab71c2ea7fa7853469a2236dedb344a19a6130dc96d5fd6d87d42d3fffda172557d203b7688ce0f86acd913ce362e6cd -8aa2051bc3926c7bd63565f3782e6f77da824cb3b22bb056aa1c5bccfa274c0d9e49a91df62d0e88876e2bd7776e44b9 -b94e7074167745323d1d353efe7cfb71f40a390e0232354d5dfd041ef523ac8f118fb6dcc42bf16c796e3f61258f36f8 -8210fcf01267300cb1ccf650679cf6e1ee46df24ae4be5364c5ff715332746c113d680c9a8be3f17cacaeb3a7ba226ce -905ac223568eedc5acd8b54e892be05a21abbb4083c5dbec919129f9d9ffa2c4661d78d43bf5656d8d7aafa06f89d647 -a6e93da7e0c998e6ce2592d1aa87d12bf44e71bec12b825139d56682cdce8f0ba6dbfe9441a9989e10578479351a3d9d -acde928a5e2df0d65de595288f2b81838155d5673013100a49b0cb0eb3d633237af1378148539e33ccd1b9a897f0fec3 -a6e1a47e77f0114be6ae7acd2a51e6a9e38415cce7726373988153cdd5d4f86ef58f3309adc5681af4a159300ed4e5b5 -ad2b6a0d72f454054cb0c2ebc42cd59ff2da7990526bd4c9886003ba63b1302a8343628b8fe3295d3a15aa85150e0969 -b0bc3aea89428d7918c2ee0cc57f159fba134dad224d0e72d21a359ca75b08fbb4373542f57a6408352033e1769f72c6 -aad0497525163b572f135fad23fdd8763631f11deeaf61dea5c423f784fe1449c866040f303555920dc25e39cdb2e9b4 -8ce5d8310d2e17342bf881d517c9afc484d12e1f4b4b08ad026b023d98cba410cd9a7cc8e2c3c63456652a19278b6960 -8d9d57dbb24d68b6152337872bd5d422198da773174ade94b633f7c7f27670ff91969579583532ae7d8fe662c6d8a3b0 -855a1c2d83becb3f02a8f9a83519d1cb112102b61d4cdd396844b5206e606b3fefdbcc5aa8751da2b256d987d74d9506 -90eb7e6f938651f733cf81fcd2e7e8f611b627f8d94d4ac17ac00de6c2b841e4f80cada07f4063a13ae87b4a7736ca28 -8161459a21d55e7f5f1cecfc1595c7f468406a82080bfa46d7fb1af4b5ec0cd2064c2c851949483db2aa376e9df418e6 -8344ccd322b2072479f8db2ab3e46df89f536408cba0596f1e4ec6c1957ff0c73f3840990f9028ae0f21c1e9a729d7df -929be2190ddd54a5afe98c3b77591d1eae0ab2c9816dc6fe47508d9863d58f1ea029d503938c8d9e387c5e80047d6f1e -856e3d1f701688c650c258fecd78139ce68e19de5198cf1cd7bb11eba9d0f1c5af958884f58df10e3f9a08d8843f3406 -8490ae5221e27a45a37ca97d99a19a8867bcc026a94f08bdccfbb4b6fa09b83c96b37ec7e0fd6ee05f4ae6141b6b64a8 -b02dbd4d647a05ac248fda13708bba0d6a9cd00cae5634c1938b4c0abbb3a1e4f00f47aa416dcd00ffcdf166330bff9a -9076164bb99ca7b1a98d1e11cb2f965f5c22866658e8259445589b80e3cb3119c8710ede18f396ba902696785619079c -aacf016920936dae63778ad171386f996f65fe98e83cfcdd75e23774f189303e65cc8ad334a7a62f9230ed2c6b7f6fa4 -a8031d46c7f2474789123469ef42e81c9c35eb245d38d8f4796bba406c02b57053f5ec554d45373ab437869a0b1af3f0 -a4b76cd82dc1f305a0ee053e9a4212b67f5acc5e69962a8640d190a176b73fbc2b0644f896ff3927cd708d524668ed09 -b00b029c74e6fdf7fb94df95ef1ccad025c452c19cddb5dccfb91efdcb8a9a1c17847cfa4486eae4f510e8a6c1f0791a -9455e5235f29a73e9f1a707a97ddb104c55b9d6a92cc9952600d49f0447d38ea073ee5cf0d13f7f55f12b4a5132f4b10 -ae118847542ed1084d269e8f3b503d0b6571a2c077def116ad685dcca2fca3dcb3f86e3f244284bdcd5ae7ac968d08a5 -8dcb4965cd57e8b89cd71d6fc700d66caa805bfd29ab71357961527a7894e082d49145c2614b670dcb231ab9050d0663 -add6ed14f3183f4acc73feea19b22c9a330e431c674e5034924da31b69e8c02d79b570d12ef771a04215c4809e0f8a80 -96ae7e110412ee87d0478fdbdbaab290eb0b6edd741bb864961845e87fd44bcbe630371060b8104d8bf17c41f2e3fca0 -a20db17f384e9573ca0928af61affab6ff9dd244296b69b026d737f0c6cd28568846eca8dadf903ee0eecbb47368351d -937bfdf5feb0797863bc7c1be4dcc4f2423787952a3c77dfa3bfe7356f5dbcc4daebde976b84fc6bd97d5124fb8f85c9 -a7050cc780445c124e46bba1acc0347ddcfa09a85b35a52cc5808bf412c859c0c680c0a82218f15a6daeefe73f0d0309 -a9d9b93450e7630f1c018ea4e6a5ca4c19baa4b662eadfbe5c798fe798d8a3775ed1eb12bd96a458806b37ab82bdc10a -a52a4d5639e718380915daaefad7de60764d2d795443a3db7aeab5e16a1b8faa9441a4ccc6e809d8f78b0ac13eef3409 -8e6f72b6664a8433b032849b03af68f9376b3c16c0bc86842c43fc7bf31e40bc9fc105952d5c5780c4afa19d7b802caa -a107ae72f037000c6ee14093de8e9f2c92aa5f89a0a20007f4126419e5cb982469c32187e51a820f94805c9fccd51365 -9708218f9a984fe03abc4e699a4f3378a06530414a2e95e12ca657f031ef2e839c23fd83f96a4ba72f8203d54a1a1e82 -b9129770f4c5fcac999e98c171d67e148abd145e0bf2a36848eb18783bb98dff2c5cef8b7407f2af188de1fae9571b1c -88cc9db8ff27eb583871eeeb517db83039b85404d735517c0c850bdfa99ae1b57fd24cf661ab60b4726878c17e047f37 -a358c9aadc705a11722df49f90b17a2a6ba057b2e652246dc6131aaf23af66c1ca4ac0d5f11073a304f1a1b006bc0aa5 -ac79f25af6364a013ba9b82175ccee143309832df8f9c3f62c193660253679284624e38196733fb2af733488ab1a556e -82338e3ed162274d41a1783f44ae53329610134e6c62565353fbcc81131e88ce9f8a729d01e59e6d73695a378315111b -aa5ddcabf580fd43b6b0c3c8be45ffd26c9de8fa8d4546bb92d34f05469642b92a237d0806a1ad354f3046a4fcf14a92 -b308d2c292052a8e17862c52710140ffafa0b3dbedd6a1b6334934b059fe03e49883529d6baf8b361c6e67b3fbf70100 -96d870a15c833dddd8545b695139733d4a4c07d6206771a1524500c12607048731c49ec4ac26f5acc92dd9b974b2172c -8e99ee9ed51956d05faaf5038bffd48a2957917a76d9974a78df6c1ff3c5423c5d346778f55de07098b578ad623a390e -a19052d0b4b89b26172c292bbf6fd73e7486e7fd3a63c7a501bbd5cf7244e8e8ce3c1113624086b7cdf1a7693fdad8b5 -958957caf99dc4bb6d3c0bc4821be10e3a816bd0ba18094603b56d9d2d1383ccc3ee8bc36d2d0aea90c8a119d4457eb4 -8482589af6c3fc4aa0a07db201d8c0d750dd21ae5446ff7a2f44decf5bff50965fd6338745d179c67ea54095ecd3add4 -8a088cc12cf618761eaa93da12c9158b050c86f10cd9f865b451c69e076c7e5b5a023e2f91c2e1eed2b40746ca06a643 -85e81101590597d7671f606bd1d7d6220c80d3c62e9f20423e734482c94547714a6ac0307e86847cce91de46503c6a8a -b1bd39b481fc452d9abf0fcb73b48c501aaae1414c1c073499e079f719c4e034da1118da4ff5e0ce1c5a71d8af3f4279 -942ae5f64ac7a5353e1deb2213f68aa39daa16bff63eb5c69fc8d9260e59178c0452227b982005f720a3c858542246c8 -99fea18230e39df925f98e26ff03ab959cae7044d773de84647d105dfa75fd602b4f519c8e9d9f226ec0e0de0140e168 -97b9841af4efd2bfd56b9e7cd2275bc1b4ff5606728f1f2b6e24630dbe44bc96f4f2132f7103bca6c37057fc792aeaab -94cdad044a6ab29e646ed30022c6f9a30d259f38043afcea0feceef0edc5f45297770a30718cbfec5ae7d6137f55fe08 -a533a5efa74e67e429b736bb60f2ccab74d3919214351fe01f40a191e3ec321c61f54dd236f2d606c623ad556d9a8b63 -b7bd0bb72cd537660e081f420545f50a6751bb4dd25fde25e8218cab2885dd81ffe3b888d608a396dfcb78d75ba03f3f -b1479e7aa34594ec8a45a97611d377206597149ece991a8cef1399738e99c3fa124a40396a356ab2ea135550a9f6a89f -b75570fc94b491aef11f70ef82aeb00b351c17d216770f9f3bd87f3b5ac90893d70f319b8e0d2450dc8e21b57e26df94 -a5e3f3ab112530fe5c3b41167f7db5708e65479b765b941ce137d647adb4f03781f7821bb4de80c5dc282c6d2680a13d -b9b9c81b4cac7aca7e7c7baac2369d763dd9846c9821536d7467b1a7ec2e2a87b22637ab8bbeddb61879a64d111aa345 -b1e3ee2c4dd03a60b2991d116c372de18f18fe279f712829b61c904103a2bd66202083925bc816d07884982e52a03212 -a13f0593791dbbd360b4f34af42d5cc275816a8db4b82503fe7c2ff6acc22ae4bd9581a1c8c236f682d5c4c02cc274cc -86ba8238d3ed490abcc3f9ecc541305876315fb71bca8aaf87538012daab019992753bf1e10f8670e33bff0d36db0bf0 -b65fbb89fafb0e2a66fe547a60246d00b98fe2cb65db4922d9cef6668de7b2f4bb6c25970f1e112df06b4d1d953d3f34 -abb2d413e6f9e3c5f582e6020f879104473a829380b96a28123eb2bdd41a7a195f769b6ac70b35ba52a9fee9d6a289c3 -88ec764573e501c9d69098a11ea1ad20cdc171362f76eb215129cfcca43460140741ea06cee65a1f21b708afb6f9d5b0 -a7aaec27246a3337911b0201f4c5b746e45780598004dac15d9d15e5682b4c688158adffdef7179abb654f686e4c6adc -a1128589258f1fbfa33341604c3cb07f2a30c651086f90dce63ae48b4f01782e27c3829de5102f847cde140374567c58 -aaf2b149c1ca9352c94cc201125452b1ed7ca7c361ed022d626899426cb2d4cc915d76c58fa58b3ad4a6284a9ae1bc45 -aaf5c71b18b27cd8fe1a9028027f2293f0753d400481655c0d88b081f150d0292fb9bd3e6acabb343a6afb4afdb103b5 -947c0257d1fb29ecc26c4dc5eab977ebb47d698b48f9357ce8ff2d2ed461c5725228cc354a285d2331a60d20de09ff67 -b73e996fa30f581699052ed06054c474ebdf3ae662c4dc6f889e827b8b6263df67aeff7f2c7f2919df319a99bdfdceb1 -b696355d3f742dd1bf5f6fbb8eee234e74653131278861bf5a76db85768f0988a73084e1ae03c2100644a1fa86a49688 -b0abca296a8898ac5897f61c50402bd96b59a7932de61b6e3c073d880d39fc8e109998c9dba666b774415edddcff1997 -b7abe07643a82a7cb409ee4177616e4f91ec1cf733699bf24dec90da0617fe3b52622edec6e12f54897c4b288278e4f3 -8a3fae76993edbc81d7b47f049279f4dd5c408133436605d934dee0eadde187d03e6483409713db122a2a412cd631647 -82eb8e48becfdf06b2d1b93bf072c35df210cf64ed6086267033ad219bf130c55ee60718f28a0e1cad7bc0a39d940260 -a88f783e32944a82ea1ea4206e52c4bcf9962b4232e3c3b45bd72932ee1082527bf80864ce82497e5a8e40f2a60962d0 -830cf6b1e99430ae93a3f26fbfb92c741c895b017924dcd9e418c3dc4a5b21105850a8dd2536fa052667e508b90738f2 -990dce4c2c6f44bb6870328fba6aa2a26b0b8b2d57bfb24acf398b1edc0f3790665275f650884bd438d5403973469fa2 -a2e5b6232d81c94bcb7fed782e2d00ff70fc86a3abddbe4332cb0544b4e109ae9639a180ae4c1f416752ed668d918420 -b4cdf7c2b3753c8d96d92eb3d5fa984fef5d346a76dc5016552069e3f110356b82e9585b9c2f5313c76ffaecef3d6fd8 -83b23b87f91d8d602bff3a4aa1ead39fcc04b26cf113a9da6d2bd08ba7ea827f10b69a699c16911605b0126a9132140f -8aae7a2d9daa8a2b14f9168fe82933b35587a3e9ebf0f9c37bf1f8aa015f18fb116b7fba85a25c0b5e9f4b91ba1d350b -80d1163675145cc1fab9203d5581e4cd2bed26ad49f077a7927dec88814e0bed7912e6bbe6507613b8e393d5ee3be9be -93ddeb77b6a4c62f69b11cf36646ed089dcaa491590450456a525faf5659d810323b3effa0b908000887c20ac6b12c80 -9406360a2b105c44c45ba440055e40da5c41f64057e6b35a3786526869b853472e615e6beb957b62698a2e8a93608e13 -93bfc435ab9183d11e9ad17dac977a5b7e518db720e79a99072ce7e1b8fcb13a738806f414df5a3caa3e0b8a6ce38625 -8a12402c2509053500e8456d8b77470f1bbb9785dd7995ebbbe32fd7171406c7ce7bd89a96d0f41dbc6194e8f7442f42 -aab901e35bf17e6422722c52a9da8b7062d065169bf446ef0cbf8d68167a8b92dab57320c1470fee1f4fc6100269c6e2 -8cad277d9e2ba086378190d33f1116ba40071d2cb78d41012ec605c23f13009e187d094d785012b9c55038ec96324001 -85511c72e2894e75075436a163418279f660c417e1d7792edce5f95f2a52024d1b5677e2e150bf4339ad064f70420c60 -85549ca8dcbe49d16d4b3e2b8a30495f16c0de35711978ada1e2d88ad28e80872fca3fb02deb951b8bcb01b6555492e4 -8d379ab35194fe5edf98045a088db240a643509ddc2794c9900aa6b50535476daa92fd2b0a3d3d638c2069e535cd783b -b45cfebe529556b110392cb64059f4eb4d88aaf10f1000fdd986f7f140fdd878ce529c3c69dfd2c9d06f7b1e426e38f3 -ac009efd11f0c4cdd07dd4283a8181420a2ba6a4155b32c2fed6b9f913d98e057d0f5f85e6af82efc19eb4e2a97a82df -b2c2cdffa82f614e9cb5769b7c33c7d555e264e604e9b6138e19bcfc49284721180b0781ecbf321d7e60259174da9c3c -95789960f848797abbe1c66ef05d01d920228ca1f698130c7b1e6ca73bfda82cee672d30a9787688620554e8886554ee -98444018fa01b7273d3370eeb01adc8db902d5a69b9afc0aa9eadfeb43c4356863f19078d3c0d74e80f06ecf5a5223f4 -87d20b058050542f497c6645de59b8310f6eeec53acbc084e38b85414c3ea3016da3da690853498bde1c14de1db6f391 -a5c12b3a40e54bee82a315c503c1ce431309a862458030dde02376745ec1d6b9c1dbeea481ae6883425e9dae608e444e -b9daa3bf33f0a2979785067dcece83250e7bf6deb75bb1dbbab4af9e95ddfb3d38c288cbef3f80519a8916a77a43b56c -b682ec3118f71bde6c08f06ea53378ea404f8a1c4c273dd08989f2df39d6634f6463be1d172ac0e06f0fa19ac4a62366 -a4f94fd51ecf9d2065177593970854d3dce745eebb2a6d49c573cbf64a586ae949ddfa60466aaef0c0afb22bd92e0b57 -86cd5609efd570c51adbc606c1c63759c5f4f025fcbefab6bc3045b6ad2423628c68f5931ff56fdda985168ce993cc24 -981192e31e62e45572f933e86cdd5b1d28b1790b255c491c79bd9bb4964359b0e5f94f2ae0e00ef7fe7891b5c3904932 -9898f52b57472ebc7053f7bf7ab6695ce8df6213fc7f2d6f6ea68b5baad86ec1371a29304cae1baadf15083296958d27 -b676c4a8a791ae00a2405a0c88b9544878749a7235d3a5a9f53a3f822e0c5c1b147a7f3f0fc228049dc46e87aa6b6368 -9976e10beff544e5c1645c81a807739eff90449df58ffdd8d1aa45dd50b4c62f9370538b9855a00dd596480f38ebe7a5 -a0e91404894187ec23c16d39d647ada912a2c4febfd050a1ea433c4bfdc1568b4e97a78a89ba643aca3e2782033c3c58 -91a6ea9a80476ed137eb81558ff1d55b8581663cccd41db4fc286876226b6515fd38661557419e1e46b6a3bc9cda3741 -b9e8a1e23c60335a37a16f8085f80178a17d5e055d87ffe8cf63c532af923e5a5a2d76cf078164fb577996683796caa6 -ad8e151d87a37e8df438d0a6a7c02c3f511143efb93fde8aef334d218cb25932baf9e97c2f36c633620a024a5626af3d -978f942f210e8a482015e6fdc35a4c967c67b66e6e2a17a05cc7a0f2163aed227b775d4352b0c3cca6cbf4bd5bafaf75 -b5e2e3d8b2e871c07f5899e108e133f87479959b80cb8a103fbecde00ccdbfbd997540eef33079c5cc14b1c00c009fd1 -88a164b3fefd36857f429ab10002243b053f5d386466dbb9e5135ed3c72dd369a5a25e5e2aaa11f25488535e044e2f12 -a66091c0db4e7cf05a089ec2b9ff74744354d0196968201f5e201699144b52bb13b4e68e12502727163e6db96e3565f2 -8e65aff8e37240461b7374c20bfd1d58b73a525c28994a98f723daed9486130b3189f8efe5c5efcd7f5390cc366038da -8b37c21dd7304c3aa366959ba8c77ea8b22164a67e136808b6f8e48604297f7429a6c6ecf67b1d09b8b7ec083eacd7e0 -b689b1277ad050f53da91a702516a06d7406ff33a4714ea859b3b2b69f8d0aa8f983c7e039b19c0759a3815d841fa409 -b17f7a0a182ed4937f88489e4c4e6163dcf49fd2ea4d9efbba8126c743bea951cd769752acd02e921774dc8ebcfae33b -8b7fab4f90be825ac5d782a438e55c0a86be1c314a5dbc3cc6ed60760a8a94ef296391f1f6363652200cce4c188dae67 -ab8410c4eaa2bb43b0dd271aa2836061bc95cb600b0be331dada76ddb46711ff7a4ad8c466cc1078b9f9131f0dc9d879 -9194bd7b3cc218624459d51c4d6dbc13da5d3de313448f8175650fa4cfab7cc4afcda5427b6676c3c13897dc638b401e -980f61a0f01349acd8fc9fdc88fc2c5813610c07eecb6ab14af0845a980792a60dadf13bb4437b0169ae3eff8f5984ce -b783bee24acea9c99d16434195c6940cf01fc2db135e21f16acae45a509eca3af6b9232a8aa3a86f9715c5f6a85cb1c3 -a3079931c4b90966d1faa948db847741878b5828bc60325f5ebe554dcab4adcc19ee8bce645e48a8f4a9413bb3c6a093 -801f61ac9318f6e033a99071a46ae06ed249394638c19720831fff850226363a4ae8486dd00967746298ee9f1d65462f -b34dbbed4f3bb91f28285c40f64ce60c691737cc2b2d2be5c7d0210611cd58341bb5bda51bb642d3ee2d80882e642a13 -8750af19abfb915e63c81542b13d84526a0c809179bbcc1cd8a52b29f3aba3ae0f7cf6f4f01790bf64ef7db01d8ee887 -a6ea10000eb2dd4efc242ac95bc3b3873cdd882fbeb7c9538c87e3143a263ca3a2e192b2159316a625cfb5fb0b6cdcb3 -aa40ca54bc758a6c64cb932924917581062e088b3ad43976b28f2e11d8a7dea73f1fb50aeaa0e70182bb2dc07d805bb9 -a4779dfd25b5ec9d75dfb54a4bb030364899a5e75c1492403acb19f2adc782c7ac4daeb66d2f5aeb74135afe9f318e3f -b4551e2805d63ca453f4f38b1921ac87ff687e1d70575ad38f3469d6f0608ef76b7b1b98ae1e6b1e7d928773aaab6e3b -99490ee722f96aad2743b08dd37bfeb75a8c59efaee4c9b694eaa05eb8a6bb23861a4480544c7617d04d23fd5e2543b4 -8a7050d964d295fff98ae30d77ce730a055719313457e773fcce94c4d71a9b7cf63db67e54a8aab20fb1335b0130b5d5 -903144e6bbee0a4fec17ff80fef0d2103981140c3d41776cfb184ced17f480a687dd093f6b538584327e6142812e3cd5 -a5b30f7c6939bdc24a84ae784add927fec798b5a5ee3dd156c652df020728dd6d43898be364cf5ee181725fbcffc0964 -b43d97ec2bc66af92d921a5c5c20a03ef2be2bc2c9b345f46d8287409fcbfd88ebc49d4509d64468222cd1d2021bf236 -82dc23c7f5086c9ac6b4566359bfb830d203544b0d8332a210775670f899cd9ff48b94bfeba40040c25664ebdd5cfad8 -9294cd017fea581dabb73dcc8c619904d7e022b664b0a8502c9d30f3807668af279948e7e41030ae296d492225297e95 -8d6c9dc636c8e884f9a4299e5cff06d044ebc94ad783a4b71788347ea4a336d4d048b8a9ecabae789e8fcdc459723dfb -801a80bc49e882ec81b04e37407713f033f7bdac79252dfa3dc8c5bd0229fcbd4019890e402cf843b9378df08f72ab84 -b4313ca32569d973900f6196363c0b280ddfa1b47c88d019e5f399b805b444a777950fc21ae198fc23ece52674b94abf -96f06056fd255fdabf78986e315e7c4fdf5495cf850536b7976baa97a994cc6a99c34609c33a0f2facba5e6f1026dce6 -983ed80220a5545ffd70ef5e6ac10217d82ec9cd8f9a27ee77a5ff4074092308c0e6396fc4e9932a77ddd474e61f8b55 -872a059aa630af73c4abbd076e8b333a973ffc5bdecf5dcc0600b00162184213cb19d4f601795030033beb808d5810ce -b040f318d9d3b8833da854014a44296dbd6762dd17cab13f91987256c54353b7f0800547cb645a7cc231997454209fdd -a8c4731a555308e8ce0b8325eb7a4cbf6113d07e9f41932df04480b72628d313b941c7055f1cc2ac45c7353b56e96ca9 -8c24031440b77637e045a52e5ea3f488926ab0b426148975edf066c40a4581beecc1bfb18fc4cf5f9f96dc6681b4bd28 -b39254b475abf342f301298feaa17a4b3051f30ea23a18acf59e003e2704ac96fe40691f1da387913bdf7aee6389f9a8 -a1dbf938b604ccc6d60881cc71f38df568aa02752aa44d123514154017503f6c1c335ae43e359f1487bc8934073cd9c1 -8d52aa1be9f429ece0580498d8fe9fef46d4a11f49436a82b8927f9503dacc41245907f126594c1cd30701286f8c092c -b826f396486942c0326d16f30a01b00a682c30a75553dc6ac34fd5b3e96b13c33b94738f522eebaffb59ff8c571c76e9 -aa89f51cbf6e6c3e2aa2806187b69ab3361c84e89f393f3ed284fe84db46fc3944aa44f8928e3964f9c1a1ec27048f68 -a254df0efa4203fb92b42a1cd81ca955922e14bf408262c8f7cb7dc703da0ca2c71556bd2d05b22ce9a90ad77309833d -93263c507e4d5f4e5df88e85b3d85c46ea729fb542a718b196333e2d9fb8a2e62dc1347cf146466a54ba12d200ef09d9 -922e3c4a84246d89a07aa3e90f02e04b2cea9bebc0e68b742156f702aed31b28c6dfa7ac936ea2fc2e029adf68361f98 -9a00628eeeda4ccbed3ef7834149aec4c77aac1a14bc2491ba5d1a4a2c5d29afb82ceaa5aac1c5ce1e42cdcaf53e30ba -ab3a88df36d703920f6648a295a70ffa5316c96044f39ff132937bfda768937cb6a479e9ba4a4e66b377f3a9996a88c4 -966b11526ab099d550ab33c6a9667e5cfdedf255da17a80a519d09acd78d2ea24ec18bd1ea7d8d63cf0a408f1c1fe0b3 -b5c21b9817dc32f3df9d9988aa3560e1e840d586d01cd596bc0f850ab416b6013cbf7dbfd05ac981f26014c74bd2d2b2 -9040abef5e2523e7f139c9f744a64b98fea3a57952059ffe4d5ed77fa87068203c090ef4e7f52c88fb82ea8a6fdca33e -a0dcdaeb7d3f5d30d49c004c5f478818c470187f4b0b4856812dcd1b3a86de58a99acb8ceb44c6b80c3060cf967c43a4 -b5f4be9a69e4a6719ea91104820df8623b6d1073e8ee4168de10a7e49c8babea772bcbc6b0908185e98d607e49cd3609 -8634020a5a78650015763c06121c606d2dd7b324aa17387910513dd6480fb797df541fc15b70d269b2794ad190595084 -9504d1d0fb31ff1926c89040c04d51fd1f5cddf9d7ca3d036e7fd17e7a0f767ef33cee1d8bf7e17e2bc40949e7630417 -812c72846ef6d692cf11d8f8c3de8fa78cc287303315114492667b19c702cd24d462020f1276895df26e937c38f361f8 -8c97aa5e9ef2aa9a1435ef9ddfe62e850f0360864ed5fb82bf9fef4ef04d8fb4f827dc078bc911ee275e4501edd6617c -ac5f7af5e23c8e429aaa6b6825129922b59d25b4608f07b65f21388a9ac3aa89096712f320afe6d56e44e1f0d51a4eb9 -a8c84d9a8593a0cb5be1e450960f59878a4e6b70da54a7613dfc25911b7cc9e6d789d39401b0a0d6471ab9dcdc707976 -8c9d5fd89611392c0f085ffa4fa642a181f0b9b23593deb5e10fdd1642722ca75ef34a037e88a8d03f2888fe7461f27c -8c74b05f91fb95c85e7bd41f6d9a1e41e667e68f3d19b325c1f25df1767019919edab89b92af237896cbc4e6d6dc1854 -a3caecb91640821f0b2c4981b23f2069df8d2b98ce026c1538bc096b292f5f956a5d52c1c8d6a8165a1608083ba6494b -8ae8e0c36f8b79a69176ff29855df45d0fcd9e4d1dbaed8899f8fcdece676e418ec034a6c161e2a894f0c834aaecbfd1 -b88d18c67dc3b1b6ed60ee437c441c1ed14ecddebccf43683605716f30058b1aa4ba05ff10cd8171ee97d8f58d70c094 -94f43d84dcdfd9cd19115c7d8e9c1e856828eafbfdec93b876cf0007e317e30b2ad951dbabc186aa6ef90fdee4d91990 -b44e4723f41fc1d5b0057f371e3381ae02566590b3f964b6eb07b2104f66ff78410c407235fa98d04f635694f3baca09 -addd8390173d29ca0811534d389253831fed75fed135398617836b6e70767269eacb1560b39a58f02042ca3b97fe59c4 -80bdbdacc0c358c7ea52aeacdc5f9ceb6928bcf6e7dee7c17d8ae3bf7c2372aa7a0372363888968fc0921aaf4776d5d0 -a486e2b6f04f403f9e609d69dfb3cfb992af56ecad1683271df3e3faa3b86638b81e73b39978fb829ee7133d72901f2d -a19472da57457e10c6a6307895393ddaec8f523760d66937fe26a025817319e234eaf69756ffdf1b84c81733424a96d7 -ad6a195397cbc2d75171f5e82090441eed60bd1ba42c39ef565b8b5a8281b04400678625b1dc46d617f694a7652a8e5d -8f98e721c06cec432e2221f2e1b06bb1469d916a8d88d6973acf68d1e003441d00390dafcead8ecdbf9eae4509baf5aa -91d62a0f9d13c59adfe1376ed6d057eae244d13c6b3d99be49a49e0075cf20f4085cf127774644ac93615be9ac9e5db6 -af45dec199245e2b326a0d79c4899ed44b1c0219db42602a4a6184ace0ff831a3276297af28f92e8b008ba412318e33e -8754bde54e8d2d169e6a7d6f0eae6097bc0461c395192bd00dd6f105677ea56ab384c02553ea5eeac0a65adcb0df77ee -b676afd2f5afc37a314c943d496e31b4885efcbcc2061036e370a74cfde5642bb035622d78d693bfc3136fc036c7edb4 -aab6ffe6cc234397cf1822e02912bc282dfb314e92fb5a9e10d0c34ee9b5856d4b76e166bc2bb6fcdd66aabea35ec4ef -ada6e62f90ee6b852ec4b72b22367acac2896f0df2c105beda27096583ddbedddc710d171330569f111c6e44a5b57ae7 -802139dd15241a6de663d9b810121bdd9cf11f7f8c8ca6de63f4f8e731409e40d1fd3558b4f619ed42ee54929dff1c7e -ad8e70531cec21b4e6f55be1751c2d025bd2d7d8158269b054cfe57fa29252d052ce4478ec7db6ec705789e2118d63b3 -a8e4a4271769480e1b33a28c87a150ecc0b48bfe8a15ae04152197881de4ce4b03453aefe574842424edbbe4173e1a3a -b98c65726296610cef16c5b58da5491acd33bd5c5c5af4d934a9840649ef85730fbce8018dee09ded14e278009ed094a -8e213a7861223287b860f040e5caaa563daa0b681e4e09ec79ad00cc459238e70bbeaf7486bbe182fc12650700034ec5 -a2879f9e1a556cf89b9b5b3bd8646a8cce6b60bcbc8095df44637f66a2da5858eee2dc9091475a8f64bb5aff849389cd -8a17cdb4077b9b0bcf28b93294ac5ae4c8bba8839fce0f1012b53187ac008f9858b02925fbfc421f1123afcdbd8b7753 -86fd9c11528aa43946e4415ff64a3ca6409ee6f807368c68997b18605da65e415ccd85ad913820d450cb386593de666d -8ed55923b963c3d85a91aca11c40ff9c6c7f1e2b9bc199d1a270e5fb16aa62dec0136e97866145ae9d58a493e8b1cbbb -ae32af5b5d418668ae123c639b149e5eed602404e8516da4a61db944b537a3620545e8e3d38cf10cdaea980ab2f80973 -95cb8d9e9d6762d78dde0ad73869ffaca904a7d763a378b8cc11a7933d3e7d1c8aec4271a079b1b00f8887ee5b1ea21f -b5ea20b42a3ca247f00ab5328c05f0cf194973d5f7271c66c41c5055b1ffdca136be179709e0c1de209fbe07b9820bf3 -98682f7cce471c92a8d6d15fee4ddf4d43dd97c3e3811d2913618ecacc6440b737717c07736ae4558c910e11ee98104e -a67da2c7cbba48e929ca4e4b9a6299fe01ef79eff8cc5cd3fdbdc0721a68130e4079f30ae151a573a7dcca8ecf2e684e -a9981c9f9dcbb3b0f6996f664fb2acd7573189f203be37b2b714662aa273551396abfb1f612ccde4e4c8127a050dbe4b -92d55eff8da600f886da9bf68e8eecf482faa4b268f3f286b3b3e5cc91b19604081498d4905b201bb4ec68e32b5591d9 -963e3f1728de9d719c86d390f3eb9c3f99d1928347fab0abf10dbb37d76b59ddb64d4734c977863a6cd03ffece5ca895 -93480e2de83c921056b6d8628ac37cd5ef7555ba43b0308fc13386cb0515d42c12ecd06057137aa71a7931beaf90b9ce -8feae57ff0e6a162cc81c99f45c6187d268fc0bee8c2bffc92142ef76c253d201f0e932943cf2fa312982b281ce1066b -8f8f4bd4200fb87afcd743274480220d77571928000d4197410dbb75439d368df6a06d941a6152206371d2ca9cac99e4 -8ee7f11e79af4478e0a70eb424fe8078237ad99ba6d7e6bf1a8d5e44e40abd22d404bd39b718ad6fdf4c6601f2a47665 -a98acfcec612b574943195b9ba95bebcc9c0b945c9f6b3e8760b2a4635909246a9d73b0b095c27b4ecb3339704e389b7 -b520efd19f65e81dc285031ea3593f8c5dad793e4426beb9196ab46e45346f265fd71e50adb0da657977c60ed5724128 -a3d9d0b7415280ce4dfa2429d47b2b8e37604a5157280a72cc81d541ffe44612dbb3ef7d03693fc42a569169d5842dc3 -8c29e2d0b33801f6d9a9c065a76c5cad1fb0a001506b970307e21765ee97c732a4cbf1d7c1b72d95e0ad340b3b075224 -839e21f292892a6eb596b9b1e9c4bd7c22a6fe71d3d04487c77840028d48392c5cbe73140a4e742338e0c8475cd0c1ad -8bea5c68e7743998619185bb662e958f1b4d3ca81019d84ac43c88911aab3abe4ee9bcc73cb95aa3ae87c0138801bde3 -b8f262d21a94604049e008ce03dc857848168e1efca4522acb0ccc827ffb37f545e1947843a356563a76bc6489605b66 -a7bd0842b0bb38d9943b82aa883f36f4eb8a6e8a7790d4f87faf306608f51d250a19b73984f1156cef5dd2581664614b -a993e649bd953627a88a2539dac3a12ec7f37a4c65b01425d9d34edf7ee10a71aa98f65c9e013107f824faf8aee041a9 -8e07eced75c67cb4d2ec01857f6ac1408482e6b31cb2faa249e8cf99f180575587df530c7782a7539b5221121ef48aa0 -b2f4578f26c05ecb9e2669ca744eb19d4f737321ac7d04fafd18beb7866e0fec9dd063953ae1f077b44b9c6f54db1279 -b6b3788a6c7bcaf467d19daf6ab884d549aa866970c05a9181f544ff190d043192c84fe437a75a30b78b425461cca062 -a270684903c61544b85a7041e81f65e787e1c1e23e57538fa8a69836bed0ca1673861dd29f743a1280f2f38eddd3aa83 -a9c2397c4773dcad2821266dadfd2401d013d9f35de6744f2ec201f3507700adb1e6ec4f5a453be4764da8bf68543f26 -83a3025ed6fd5df9d98be32a74e10a0d9728b560942d33ba028536fb148fc34ae87e92be2df3e420a8dfec08da495982 -90dc70c183a90bab988b4a85b7b921c8070af0e5f220364fe11afa0722990b2c971e1e98eef62d3287fedfd9411f1df7 -82d940937a6c636224d04f8e2536f93dcf20dc97a5f188875ad76c21b804aef9af10839419b61143c1f88a695959a6b4 -8017f9473ce49d498d6f168137e77e62fe553e5a51e75b519cf2cbd1ab9afdafad80fd5e6fd0860e640b0d78ca8ed947 -80573a0ec049fe1f7b3013b2839e145cd87e07c0e43826a29ef8c92516f9a30896c2ffcf3ed77ed22a6cf3101b1789d5 -953349abd2559f9824db07cec857ad54f1a05018f3076425f8dbae37f8d92a46af2c04ab7c8ec0250449541187696e98 -ab7bd2c4f05ee9a9f252c4e16a20993a12c535c3809d124bae24642616521a9768d3f19eceaf8524583f47ae1f527684 -9883b77ee834ee0112ca2f366d2a6fc213e0cf454e061438c2901a5ba35b7378f64da8adf6a476eb1562991ef5b4a5bc -89291811db308637356dbf7ed22cf07bfce33eb977734ee346e8c15a231b35d8b4443574f3fa97a40867b3e23b0bbfa4 -93d753849d7d9588d39e38217500b123a6b628a873876612d9f98b5d611f52c89c573432d2176752b5d1cc2d94899b8b -a45add3c4844db3b7a237295fc85fddc788ac1ec395a0524d2fc90a539571a247146aea4aa10eec30a95e9617c85b98d -90f94578842db7a4de672da1e483858ece5e466c73c12f725a0fc71f42ff880c9447a33fa9096839bee817536f2591e2 -b2c1b6fb031bb30460f157356562b44b4de096a0a112eab4fb3cc500aad38bc770da1fc2e73caf687a0da5e8537049c0 -afb15e15fd930929c0e3c66482068a5afe0c7b7f82e216a76c5eb1113625bfa0b045a52259d472284cfbaf4796c71456 -ad222a9a3d907713418c151b8793d5e37634354322068f8206b9d0da1a3f53b0004193713d23ec35990639a1b6c2e075 -b44a128dce97e8c4b178cdbca0a5c1b3f6e164490fac0fd68dbfe0aafa89920bb4ea420a8527e06c80dd19c2f135e3ef -8596e993ef18b8d94e9c42a90cb7060affc586b8e9b526820d25124285de5590134e2e86592e9dc4dd45ccf5d578fa60 -b71bb0ad138141ed506b2253e84110d2db97cc2d24a3fd0d096b0022d9f38f87aa74e2f505074632d64e90bcc491aa30 -84841eafd357309de47b92ca5ec163dec094a2e5271bc65898c31932e0160bee165e4decb23af339cfe09c83e1cc5441 -8a2915ee39a6fd4a240b98533d7690ef1773ce578ed1fb05ed414ebe36f7ef289fa46f41768df57190438c356331e329 -90bb337165386f1990cbd8ed2e8321ef21bc18125b015b4da0c37e5fcc446b26005379ee4fad8ce9348ceb4ab49e82e2 -b707b50ea2ab05c6d183671587f25fe29eef23fe569d731459a1ac111a0b83a2cd65b88242876b34aeead3b05a15d745 -ae1f159f79b7996315c4f9acce7e21a6ed59d4ef76331196fc86911fda3035edd5c11d568b105175a36c948d0263b382 -922bc525bace05e5dff6b5cabde5469ddd2c1c601f7131abc04ecefdd35095e6ac015b1aec3c3b25c5dee8d139baf60d -a7b060405b2740f82db64683187b1bb89e5f40c8438663c7cbc8ef2513929fe5f92625667a7f2f599a72a96b1fc8f08a -b9dfe94a08651db5efefbb813269bce80d814e3089b80c0654491e438d820bf521f8a4a4477909344ba88f7683eebb43 -841817a9729465743576950b6e8eea32ebf39cca99ace86c4792f9f35926e2d6830c52854a3b2eaeb61694e6845008bd -934128034bde8fc7b93b952aa56e0ed28b36cfa04cfa1f0d5b38266dd40beedff5e0bab86e4717b0fb56c56be2eae26b -aee9d64caf28596308782cd8f3cf819506daf3378f86157ff775e618596411adf94efd0e9542787ca942066f02cbd332 -85871184db314411a49575fee088c52ed5dba4e916ee001ec24d90898a0154d9790a06aa8a707ca7a8b986c0293b8d89 -8d3d87edcc0187a099c97b581a598d357a41ac152303bb27c849eb78e72e15cb97cf9a0468fc36f245c3e152c76bb7dd -900475d165dec18b99eb7b5f9e9ad1d2d4f632e55fdcc4c5ecd7775fed462990e6aaafe9c669f40508f9b15f00bda31f -a25b5954edd57e7811a0d18532043d975c7b44b80f65cd630935d7b16ada05f30fe2b7be7ae8a2f54c25957faf3f1950 -a089019afa3a7a15f7e7874e73b6773c0a824e6d3379b4c928e173321fb165ad979a6be004d394c28d19d410b2655d3e -b28f46797dee0c538bd3de815df641a0ef718ad3e52b2764aec380d6905b38b50ad6f60d0f68e096ca39960ba7734355 -b0ac155d3d05851b04104e6b459f1a68e9e155437c92421a7c0e4dd511ef89cf71dfa3cc920769492ee283a65ebf029e -813c69a810745580d43d5b5480f0ba81000fbef0071e6b655c7346bef5ed774e9214a7816d40eb1774a5bd033767a046 -b176345ca75c64f10ec33daa0dcf1f282b66a862fcd3d8d66c913f9a02db4c9d283dadc02eff13aaab94bc932a42234e -92560f67e5b995db4a489bb86ee78b4aee0800143b3535ad557a53e9e08716bd0202d9f5714722c2a5e8310046e3f5b3 -8adb427bad9cc15fc6c457a96a6750dda8c46d859c5f69bf0e7ab8fc0964430b33967fd47cf0675b6ba1757f91255e6e -b120f723b80389a025b2daa891b140b3d7b8d520ae2a6a313f6e3d365a217af73292dcb249dca1f414ec05e865e3cdc7 -a61a5d261a8dfe5996c42ea0a5ae703a2adcfda80e86837074d868eee16f87d38da19596c48b55dbd7a7cbec1a9b4996 -99dc921eacc6bb867c5825ad4c83bc4af9dd78a18b3d0e1a60ad493e3805b8fb9b7922b577da1adb3d805edfc128d51d -85455fa165a07282aaab4a5bfb88027f47b9532e4af8195c048515f88b0db7e80f42e7a385fd4944faaa7f2a6544ad17 -96dff2d1c8a879d443fe576d46bcceaf5f4551d2e8aad9c1a30883637c91090de99ad5eec228eb5febf93911502d3cbb -a87eb7f439377fb26c6bfe779701f4aea78dd7980b452a386afec62905e75217a1996c5234853432a62ef8bab21c31c3 -b598278293823e9ccb638232a799211173b906444376337fdf044d0227d28fcc4c5867e6ecb3200e59ca0b139e71cac9 -aa6fe147edc95027654d68140f428ec53cede3552c5f49c09d18bc6f6ae8c739a63042eb7291d14d717a4e1f0778abcb -ae8ee18913d328b2fba71efe65526d3ee9c81beda53cf776baec4019ea30212010758cbb5dc85ed6620ce04b189f01f2 -ae9fb686777e88dffdd42805fe4114aa0da1b350d92a27ff3f8a817fb25af1fcfc9a06155affe0273bf13caad16a5351 -95d372ba3a2ee38371538f34aae91b4844488e273f70c02f1992370f89fc2343eff95692d52ce9f21206abbee4959958 -b15260376f0a34ca2827ff53acd7eaaef94c9acc2f244b36500423069cb1cdaa57ac8dd74adb5b53d0fd4265fcbb28ea -b0ffce6a8059537ef6affdbbc300547ef86e00109289239b0c6930456c562b4ed97f2e523963af17736dd71b46c44ac7 -b5499a1277d34f9892f7579731ff53f423f2ffffa9ea43a6e929df8c525e301396249a2324818a6a03daa0e71fcd47b3 -98dbfb8e97a377a25605a7665d4d53e66146204d8953afda661ae506858c5cd77ff7f21f5f10232e06dbc37378638948 -84177e27e6da0e900c51f17077f5991e0e61bff00ca62c1623e627c5aea1b743f86eef6d55b13219a1947515150bade6 -b50407bb5c61b057ab8935df94fd43ca04870015705b4f30ceac85c1035db0eb8293babc3d40e513b6fb6792ecbc27a9 -988699a16917514e37f41ab5c24f4835ed8a2ca85d99972646fcc47c7e2a83c2816011144a8968a119657c4cda78d517 -920c43fdcb738239ad542cb6504ab34498bce892311c781971d7db4dec70e288676de4d8697024b108cfa8757fa74035 -aaa106329aac882e8d46b523f126a86d3cee2d888035ce65c0be4eaae3e92fd862f6ac2da458a835539cccafaba9e626 -96e4c1562d14b7556f3d3e8a1b34ea4addc5a8170e1df541dc344728bcb74cd1630eb7ba4c70e9c68fd23c5c5d5a729b -a616ac5016d4e68e03074273cd3df9693ee0ce3458e8758b117a5c1bc6306dd2c7fad96b1bb37219c57ac62c78ad7a3e -8db7d9b20abfb1445babd484ae9e38ff9153ac8492230d7591e14e3fca7388a5ca6ef7d92ed445c8943cf5263e4a6ad7 -88464134221aa7134878eb10928f31c8bd752ab68c27c9061c1de3f145c85731a4b76acdc7e939b399b6e497f9e6c136 -a5f7c794f70b7c191c835dded21d442b6514bab5e4d19b56f630b6a2f1a84a1d69102d7a0dcca256aab5882d3f30f3ca -b96b6f98b6817b5fa6b1b1044e2411bdf08bf3ffaa9f38915d59e1d2b9bed8b3d645eee322ee611102ce308be19dbc15 -92c26ade2e57257f498ac4ff0672d60b7ea26dad3eb39ed9a265162ccd205c36b882dba3689758c675f29e20836b62d9 -8379a0299e75774930577071d258e89e471951642b98e5e664c148af584d80df4caa4bd370174dae258848c306f44be5 -a0e53beda02bd82bf3d24bd1b65b656238128e734b6c7a65e3e45d3658d934f909c86ca4c3f2d19e0ac3c7aae58b342e -8ca5ceaeaf139188afd48f9bf034d8baf77bbf9669791c7e56ebf783394d7fcdf2a25fa4bdfcddfde649aa0dc67ccccd -a8060e6448844e9db4e9fb4da1c04bcf88fda4542def5d223f62c161490cf1408a85b7c484341929c0f9ce2a1d63e84b -af6e1a5ecf50b754bb9eb2723096c9e9a8e82c29e9dcaa8856ab70074430534c5395534e1c0ed9ce98f4b84d4082fa67 -81c8dbbef98f1b561e531683d5ae0f9b27b7f45dc6b2f6d61119ca0d559bf4ceb676d320afc5aba1811eeef7547a59d8 -85b46cd64d605c7090a2faf1a2aadf22403b3692b3de1d83e38b2de0108d90ac56be35b0dca92c7a41c4b179a3567268 -8dd3cc3062ddbe17fd962c2452c2968c73739608f007ad81fa1788931c0e0dda65032f344a12249d743852eb1a6d52a9 -8630f1707aea9c90937b915f1f3d9d7ba6bda6d7fdef7a40877a40c1ee52471fd888f84c2b2c30b125451b2834f90d3b -b4a747e0bd4e1e0357861184dacec6714b2b7e4ee52fa227724369334cf54861d2f61724a4666dae249aa967d8e3972f -a72de682e6f9490b808d58f34a0d67f25db393c6941f9342a375de9ca560e4c5825c83797d7df6ed812b71a25e582fff -8d5ea7d5c01f1f41fffe282a334262cc4c31b5dcf31f42cc31d6c8e37c9bd2f1620a45519dab71e108fe21211c275b6c -8ccdc7e3642c2894acbf9367f3e99c85963cea46dc5473d175339a2391be57dd8815feacadec766e13645971213b9eb8 -858e9b5fc8c13b651ff8eb92324bdda281db4cf39f7e7bd0472908b3e50b761fa06687f3d46f4047643029dc3e0ceeaa -ae20d36c70cd754128c07cbc18dcb8d58b17d7e83416e84964b71ccff9701f63d93b2b44ec3fddc13bbe42ebdd66221e -860dbf7013da7709e24b491de198cb2fa2ffd49a392a7714ad2ab69a656ca23f6eafa90d6fdc2aa04a70f2c056af2703 -8f809e5119429840cb464ed0a1428762ba5e177a16c92581679d7a63f59e510fdc651c6cc84d11e3f663834fcafeafdd -8d8a8dce82c3c8ea7d1cb771865c618d1e3da2348e5d216c4cbbd0ac541107e19b8f8c826220ca631d6f0a329215a8d6 -86e3115c895ae965b819e9161511540445e887815502562930cedc040b162ecb1e8bdc1b6705f74d52bf3e927bc6b057 -b9833b81a14115865ca48c9c6a3855f985228e04cbc285f59bf163dca5e966d69579ea4dba530b1e53f20bd4dccdc919 -a71f5801838a6dbb162aa6f0be7beea56fadac1a4bcd8113a0a74ab14fc470a03775908c76822d64eb52a79b35530c05 -a77ab73ae94b6d3378884f57eee400eff4a2969aa26e76281f577a61257347de704794761ea1465dd22a6cc6304fbc4a -acd1c5df3c487c04cf27f002e81f2348a0119349b3691012526a7b0d3bf911cdd3accbc9883112ed2ba852145e57fe68 -8a28515a48832ac9eaf8a3fb3ad0829c46c944b4cb28acbcdbca1d0d4c3c623a36cda53a29291b8f2e0ea8ee056b1dee -846bafca11a7f45b674237359b2966b7bf5161916a18cf69f3ec42c855792d967d3bf3f3799b72d008766206bb7a1aa3 -b24b341675b1db9a72c3405bbe4a95ccdfd18fa96f876ec946ccb5108f73e8816019998218a036b005ef9a458e75aeb3 -b99c267b4a09193f3448bc8c323e91ef5b97e23aeff227033fe5f00e19bab5583f6e5fcb472ec84f12b13a54d5c0e286 -a088aa478dbe45973b04ecafbcbd7ee85c9a77f594046545cdb83697a0c2b01b22b1af0b97dd75d387bb889e17f17aa7 -a0c6b0cdff2d69964134a014e36c3709d9e63f6463c5cd7b01b6f0be673731b202d577539d89dd57a888326da1df95af -b4e6dc4ef11b2b41794ece70a8968e56705199d183366759568b6fa845d2cae127486e926b5b27ae9118bb21d1682c1d -a007804353f174098f02540a57e96227232444d5ae0a24232c244647148b6c049848cbd2b50d0a25af3ca9164bfff8ee -873fb034cc39c9cee553ece908fbf315f62efbc412b9afdde6a1889326b7f6f813e050b0601ba9921688e958cb75942e -b5676c90f0106c40d8683299e59d564f505ec990230cb076caef3ae33f2021e6aa5c9b27bb8fead05fc076df034c28f5 -b5a67fc4c5539ad1ddf946a063110f824f7f08d2e4d30762c9d437748c96c9147a88efc22260573803ab545c18b108f2 -817ff2b748a949973a91b69b0ec38efbd945aeb26a176d19f0fb76e261c7526c759e6f5516f9ed34de6eb1ac7838c9cb -99b76bda3526a5d841e059010fdb14eb2fa035a7d10463373a062a98c3c1a123e2da0848421dd7546d776438fd05e304 -aa0d363270f90d56bbee7ea577b0c358532bda36d9247af6c57d000044a97ba41e35bb0db438f4c94551c6350e4e0674 -acdae205d05f54b9544be96c9032350511895ccf413dbbc56d1f03053185df22a6d5b7ffcc3fbe96c3e2ce898ccfa73e -b091c220a1de18d384f50dd071dca4648ca4e708162c52a60e2cedc0188e77c54639f75bce9a468a64b2549119c07ded -878676133e5c700b1d4844564fa92a9930badb5293d882aa25ee6721a9f2cfab02088c31d62cf1342ae3edaea99a1ea0 -9756d0793e6aba3b4dff48100bb49a5ec08ec733f966cb438379b91caf52fc2a5930830ec3f49aa15a02c82c1914dc7a -9722f760184d3b2d67cb2cea7fa41b1ff920a63446006bd98c6347c03d224d2d8328fa20ccd057690093d284b9a80360 -b5a68489de4f253715a67f0879437bfe8f4dfc4e655ca344848980e6153b1d728acde028bb66fd626fa72eedd46ff683 -a8cfc900b34835d9fd3add08044636f69614eff9ae929eac616c39bd760fd275ee89bf24b0f275dd77a66e54fd6b94e5 -89967479bebf70b2893cad993bf7236a9efe4042d4408022fdbb47788fabedcec27d3bba99db778fcde41e43887e45af -889235938fcec60275c2cf0f19d73a44d03877d817b60bb26f4cbce09db0afae86d42d6847b21f07b650af9b9381fa82 -b7fc321fa94557d8fbdd9fff55ab5c8788764614c1300d5ef1024290b2dbb9216bce15cb125da541f47b411a2e7e3c2d -b11b0c4dc9477176b3cda6b17858dbd8c35a933ed31364801093f310af082cb5a61700f36851e94835c5d4625bf89e32 -9874e54d2939ee0600f4194f183877c30da26d7515e9e268fea8d24a675dd2945d1565d9016b62b1baab875ac892f4d2 -90df3a77280d6f1fa25a986309bba9d5b89c3cf13656c933069bc78e6c314058716b62eacfa7ab4aff43518b8b815698 -962b08299a287d77f28d3609f39fd31bc0069f7d478de17539e61fcc517045050644b0307c917208b300ce5d32affcca -b30eedca41afb6f083442aaa00f2e4d5dc0fda58e66aaf0f44e93d4af5c4bf8ea22afec888cacbf3fae26d88e8d344cc -847747a22fab3fe3c8cd67f3f1d54440f0b34ce7b513225dc8eb4fa789d7d9f3577631c0890a3d251e782a78418fecfa -8d1ef3cb5836e4039b34ee4e1b4820128eb1e8540e350309e4b8fea80f3ae803d1f25f4b9c115482b324adf7c8178bc7 -8f8a2b0b0f24f09920b58c76f7d99ec2eb2e780b5a66f2f30a9ed267dcaea0ec63b472282076c7bf8548211376c72f6e -831ee6dc8889bbf4d345eaeb2f425959c112d2190764abbbe33bc44e1d9698af87ff5a54d01fac00cfee5878dee7c0f6 -a7eb2479ac80d0ee23f2648fd46c5e819ad3a1f4752b613607ae712961b300e37f98704880ac0a75f700f87d67853c7a -aa4d1b9cec62db549833000d51e83b930db21af1d37c250fdc15d97bc98de7a5af60dbf7268c8ec9c194d5d5ccda3c1d -87396fd7e78c4bcf270369c23bc533b7fb363ca50d67262937dab40c7f15bd8448a8ba42e93cf35fb8b22af76740d5e1 -a958b2a9ffccbca13c0c408f41afcfc14d3c7a4d30ea496ce786927399baaf3514ff70970ef4b2a72740105b8a304509 -a5963a9dd3fe5507e3453b3b8ed4b593a4d2ced75293aee21bfed7280283348d9e08bf8244c1fce459aa2470211d41ea -8b06ddc3359827558b2bb57caf78b3e5a319504f8047735fcc8ec0becf099c0104a60d4d86773e7b841eb5b6b3c0cc03 -9437e7278283f6d4d1a53d976c3c2c85c5fe9b5aec7e29d54a5423e425b4be15400ed314f72e22e7c44ee4bacf0e681c -b56067ee26a485ed532c16ec622bb09135a36c29b0451949aa36fee0b0954d4bf012e30d7e3fc56e9f153616b19349bc -a5c72f7f5d9f5b35e789830a064a59c10175093a0ce17654da7048827d0b9709b443a947346b0e5d96b5ea89b8d7c575 -a8318d01182d4c9af2847a29a6b947feef5795fc12e487a30001cc1ec482b48450c77af4837edfa1aedf69f0642c7e5e -82ea421c091552d3dafa7da161420cb5601b819e861dd2ba1a788c3d1b5e8fa75cc3f2b0db125dde8742eb45b335efa2 -8679fd1c7771ea3b12006d4a972f4f2892e61f108107d4586f58ee7f2533d95d89b9695d369cdace665f19c6bc3bc85e -b5ab3e8adee4c950fce4d33a0e2f85d3d886e60a6e2f4454b57bc68725f0cf246372d863167482cce1ea10a7c67c3af2 -a85696927075ec188979180326c689016a0dc7a2f14ae02ea27c39ef91418cd44177d3fca5752cf6b298fd75fa012e26 -a44f87b7232f102cd092f86c952a88afb635484a984da90a41a57a3d883c9469064bf105b9026024090486b6c6baa939 -866ac91a437db945bbfdc11fcee583f3669fa0a78a7cecf50fbfa6ed1026d63ad6125deba8291452bf0c04f2a50e5981 -b780d5a1e278fd4eef6139982e093ceafea16cb71d930768dea07c9689369ff589d0c7f47d5821d75fe93b28c5f41575 -b025d0046e643506e66642c2c6a5397a8117bbfe086cee4175ff8b7120e4f1e6794e1e3f6ec11390993cca26d207ae43 -a04a22b6e28c959ab265c7f48cde42bb6a00832c6beb2595b5df2879080a9424890960417d7d7ceb013d697d0ebf7267 -81de9c656ac27f54d60d0252e33aff4e9e9e9c3363a50740baf15a2b9061f730a51ae1704e8c4a626153cf66d47f19b1 -a15fab90599df889df11fa60c752948b68fba54005491180dafb66c5775547976d0eef33945e55d4818653e0818c6f92 -b06f9be44ddb103a72fa4ebc242c8ee1975fe9bf9ef7124afeda9967ff3db644dbf31440151b824869406851a90984a2 -99abdfe6806ae5efa2d11577da17bd874d847c5f810460148bc045bcf38c4fd564917eacb6ed61bb9164ed58055cd684 -ac53231077f83f0ae5f25e52b70bb6105d561c0ba178040c11c3df8450c508ed5df34f067fdaacf716f90b4926f36df5 -99e3f509af44fc8d4ebc693d3682db45fd282971659f142c1b9c61592573a008fc00502c6af296c59c2e3e43ed31ec7a -98f2f5819670aff9a344e1c401f9faf5db83f5c0953d3244cfa760762560e1c3a3c7692bb7107ea6eaf5247ac6fd7cc8 -b5b9f90391cec935db8d2b142571650fcbb6f6eb65b89c9329e84b10bfa1c656026674d70280ade4ba87eeaf9333714d -b0696b77ca8a0cdbe86cad12f358880926906fb50e14f55b1afc1e08478ae6376215cbb79bc9035de2808c7cd2b13b85 -a51d746833062a65fd458a48a390631d5d59e98e2230b80d8f852cfc57d77f05eefcfd3c395ade1e86d4a39c2141365c -812d67654319f4ef3c9e4a2d4f027a4cb7768f1ea3f5fdde8d1b79187a4b874ff9a5c70f15b7efa079c2dc69d1b9b1fe -968978b653c6416bf810f6c2ffa3d1abbefbd06f66b6686e9a4fdce3f869e0ab1e43cce14dc83786596761c100ae17e1 -98e1e6ab562ca7743783b802faeb0a24f1341abfb9655f106920aef08964a3c0e8083e1acda7ae28fed7cdd5478decb6 -a91c0b982a0a7085a103600edf99e9d0bee4c4e7db6d9f8f376c215c7d42476218462a3765f2928e12c3dd49d688e4fd -8a43395b3124fab9e2438635bf88952e8e3084dad7ecb3a9927f9af0e0887bce4707084043671fc98ad03621e40a149e -b0b37626143d4a8c6f5693d5f1fe871525b4dd946c4239cde032b91f60a4d7a930d7ba28959737550d71c4a870a3a3be -b01c74acae1715c19df08d5f4a10e0c19d1356264eb17938d97127bf57e09ced05ba30d0fc1a9f32d6cff8b0d5f91c9a -b4c2328eb8a5a673406faed8f0aebb8540d2791646e37ce46e0e382506570ca276eb6f8e166dbbf9e0a84064873473b9 -85cb9f769a185e3538e4a4beda9a008694e1bf8dfeea9dc07c5c40a9ceb1d31fcb13cacfaa52849ba1894b5027cb8c30 -8742f91cddc9a115ddc73982f980f750d82d3760f2d46ee4490d5b17c6c3bb57c7d4c7b8d6311b7b41e59464c009b6a5 -948ef86d17128a061e1bdd3ea7fcc7348e3ec87ec35dc20a58dd757d5d18037fe5e052bb359e27ab4c2320d9a52a6a0b -a70f6a214097c271e0d2d95e30fce72d38c30a2f186271fdff0e38e005aff5baed53739b8c4f9501aa7f529c5cb2da59 -892a7574cf6704ad75b346c95ae6f2668904f1218c35b89b07a0c2dbf3c62173c348f6fd9473926eef56a37c0f635c04 -837e85a41f39b4ded1420aa8fc3be46a7adb99305e0928c6d7643b7c44434b72984cea08eb68f5f803661df0db78c87d -94e495329f2aab3eeb68f347961d1006e69d990095877a4dcc376546233adf29a14bf6b16a0c39aa477e15368e87014c -851860a8fdf76a97048396553262637dade27f1f63f926997e74c7c72b14b10293eae7824e8dedffad1aead57c124f79 -90481017a250972055ab1cf45ff17d2469517f10f18c9d4ef79a9bdc97a49093289bbacfefa8a1e491bbb75388b34ac0 -983db15f7463df28091c691608ca9c51095530fa6b1b7b5b099c612e673d29e16787cc9ae1c64370ba6560582ce623c0 -a477dab41014c778a1b78a7ce5936b7b842124509424e3bfc02cc58878c841c45f9e04ccc58b4f2ff8231488fff0b627 -868ebba1c85d1f2a3bf34c0ab18721ea725378b24f6b6785637ee4019e65d4850e051c8408fe94a995cc918c7b193089 -93cbf4238a37ccd4c8654f01a96af809a7d5b81b9e1eab04be2f861d9d2470996fb67367e5bf9dcd602dc11a3e4cf185 -83113f4e696030cca9fdc2efc96ba179cf26887c677f76cde13820940ad6891cb106bb5b436d6b0f8867f2fd03933f7d -90c709f4e3359a6d215d03f45ad5cf8067aedd4aab03512dd62229696485a41dcd64e2acce327fda390e0352152fce13 -9945cfced107a36f3cf028ba04c653360afc5013858b9a12fac48802efcbc198c9baf3a7f9b23dfdd5036e88bc7274c8 -832ae60192b47fc735a8ddeaf68314b16256c90ab68099f58e43073e249c6939895c544a02fa34e40805bc6b5db33461 -8b12c335818b643c1d22cbc2869606cf64e7ae54a7713617fc4dd3b2f052ebd6b920ca59ba2e9c7aa8cf71bb4f40f9e8 -a2033eb7a373931c65d66989644aa0892ac3778b9a811b2f413d8bf534e282c339717979f9aa742162abb3468c195f87 -aba2b4c37dea36bed6d39323e5f628ab607699c66767f9bf24ef5df1bfcad00c2664123c0d8d5bd782f1e14a06f4c769 -b71963777535b4d407286d08f6f55da8f50418486392a0018ee10f9ae007a377b8b8336f33386b0eb01c45695c3ed2da -88dc87826941340913b564a4f9b74985a311371c8e7b47881235d81c081f1682bef313c2f86561a038757fb7d6a1a8dc -869e13e3fcf91396750150f9dc9307460494c1d365f57893fd06fb8acf87ac7dddc24e4320d9cad0414119013ea739b8 -92194e292303d32b91ae9cecb8d6367c8799c2d928b2e2846dab1b901371a4e522fc4089aad8f4ee676f0614ff8b19d7 -aa589a3e512cb4f8589bc61e826a06d9f9cb9fdfd57cf5c8a5a63841435b0548e30a424ca3d9ef52bf82cc83c6cb1134 -81802e0194bc351b9a5e7a0a47911d3a0a331b280cf1936c6cf86b839d3a4ab64e800a3fe80ea6c72c3751356005a38b -88e5e9e3c802314ddd21cb86f2014948b7618502a70321c1caf72401654e361aac6990a674239afa1f46698545614c93 -abac1e0f85d5c3ff6d54ed94930c81716d0ac92be49e3d393bed858833f4796c2b80bf7c943e7110de7b2d148463bfbf -b7eb416004febd574aef281745464f93ef835fd65b77d460b6ad5d5a85a24b536b4dec800cfe80ae98489e54447e8bb6 -b3fd8ed1c30e7c15b0bc0baf0d9d1ecad266bafb281cd4e37c55edc76c202fb1e4ea315a91a2848f40f481793ae35058 -86ef674ddf4b7d303c68bbfb53db00b925ccbf11d7d775ca09e458f4ecd868ca828103e8e7cd9d99672a193e81b83923 -95ef414e9f7e93f0aaaeb63cd84eb37fc059eb8b6eced2f01b24835b043b1afb3458069c45218da790c44de7246860c9 -93ec8f84c20b7752bfc84bb88c11d5f76456136377272b9ac95d46c34fce6dcfc54c0e4f45186dd8df6e2f924f7726ab -95df5f3f677c03a238a76582d7cb22ed998b9f89aecf701475467616335c18e435283764fb733fb7099810fec35932ae -8cda640695c6bc1497d19b9edc5ff4ea94c1c135d86f573d744358758f6066c1458901f9367190dcd24432ae41684cf0 -b19aedf5569435ff62019d71baa5e0a970c6d95fe4758081604f16b8e6120e6b557209cdea0ccd2efec6ff9e902d6ce6 -b3041f21f07d52e6bd723068df610aa894dfdde88094897593e50c5694c23025e412ef87a9d16cadd1adbb1c6e89ced4 -a7f8d6ab0a7beb4f8d1cfef6960ebdaa364239eca949b535607dee5caeff8e5dfc2a9cfb880cc4466780c696cff2c3a6 -99a565b4796e2b990bfcb234772d93c5ffdbe10453b5aa94662272009a606ba6ea30cc0c3c26aa22982c1e90738418a5 -90c54b55ff19157c1e679d8d4f7f0687a70a27d88f123179a973c62565adfcc9347cfe31f54539038cf2f34556c86870 -8612f34bcd018d742202d77d7ce26cf9bc4e0d78e50ddf75250b9944583b2c6648f992b635ea13fdaae119764e7c28d5 -a04fb38e5529bf9c76ec2b5e3a1ef3c6f9effb6246c7f67301cfed707356ba1bf774f2867c77a5805933f0c8ad0ec644 -b4800e7b503da0164885d253135c3b989690794d145182572181995e6fa1989f3d0324993e871bbd5f48fadd869d8a18 -9981cd4f28ae7b7dadf454fb3aec29746dc2e0ca3bd371b2a57cd2135a7d93559e02132528ccd2d305b639d7ac51613d -a3ceec012dd1fbad3ef9f9f1d6fe7618e13d4d59e3f50540d2a57010d651092979c75442ec8b38a1ab678505e30b710d -8b97b8654d067fb4319a6e4ee439fb8de0f22fd9db5569ba0935a02235cb4edd40a4740836c303ec2394c59a0b96308b -b3d1bf4410fec669a269622c3ce63282c9ac864620d7b46c9dfcec52d8e79b90c4c90a69c32763136a7f2d148493524e -93174eba1e03f879e44921084aa0ee3562e48c2be49085de96ed7621c768ff52324d14c8cc81f17d7ed50c38ffb2c964 -aa2194cd0fb7aec3dac9a1bd8ea08be785926ed6812538be6d3c54218ea4b563646af1f5c5f95cb914f37edfae55137d -93f2c0dd59364f6061d3da189e04d6c64389a3563b062e8f969a982cd68cc55b4f38b21546c8a67c8df466ff4f61f9c5 -aa7dd497cc949c10209c7010ba4ce8a1efd3cd806a849971e3e01716ea06a62e9d5e122ad1d2b8e5a535fae0a01a7761 -ad402424b2a32bca775a66aa087580d7a81f0867f293f1c35580b9e87ccc5a2bab00c29a50fd0d7bd711085ae2248965 -96237843d8e29ac77fc6ebf4acc12946ad11697de8e5f152fe5776f2475b790226a7d156ac48968dd68b89512dc55943 -a45c25cdbb9fc327cc49a1666988af9ab4c5f79cea751437d576793a01c3eeea4c962c05c0947852fe0e4c63e1c84771 -93dcf834a614a6f5484cc4ba059e733ab5dcc54253229df65ff5ad57b447353ebbc930736a4c96322e264e65736948dc -b9a94f82a82c0c5a26f2c1d5381afec3645e8ee04c947dc3b7ad59a73018db1e9965ab3642f2bbf60f32c430b074fb22 -94eab29b3524ccbe0c4b928e5fa5dd8f684074b332fcf301c634d11083653ffee4f7e92ddbcb87ed038024954ad1747b -b8dca5f679931d6abef0674bad0639aefad64c2b80572d646aaab17adf5ca1ab2ebeecd5a526cadc230bec92ed933fc2 -944d394958e539251b475c4304f103a09f62448b7d8a8eaef2f58e7de4f6e2e657d58d5b38e8513474115f323f6ec601 -8a5ae1f13d433962d05df79d049b28e63fe72688fc3e6660aa28e0876a860c3dbc5fc889d79f5c4dec4b3a34cdf89277 -afa5278724998eced338bb5932ecf1043d2be5dd93f4d231d05d2ea05b4455f2ffdc0eadcb335dcace96dd8b2b4926fb -b91153a2f4647ae82fc4ee7396d2ca23270ec7f8884ce9eead7e9376270678edd42dd3d4d6c003dfc2dde9fd88cc6e7c -adc932f1c679bf7889cb1ff4a2d2897d7973483fa283979a0ea3640c80ed106ea0934c1961dd42d74b22504be49851f2 -a82e90761fae684d1415cee0649bb031bcb325ae0b28f128ab8e3650bccedd302a70de1a341ca8decfdda76f3349cad0 -8ae353188b4b98835f4ef0333cccb9e29e1ac3ec11d554bc96f5880c101cb3c84b8eefe72f2287b0812735339fe66cfa -b8b41135bb1a1ffb64afbd83e2189e755f2c350e1273cf47c38ae9b8c4800d831436a69458b8ef9fa8b95a148d8ec9fd -96f75a04d8752fa93dc1eaf85ad333cff4eeec902a345576139e16de3a88eeb71b6726224349bb9844065cc454d959e9 -ab82b05e3923ad4c26f5727c60dc0d23063c03f5a4fd8077da66aa87042cad1bd99586d4ab35aa5e4ce6f4da6fecf3c1 -a50c83db91c26ef7bf1720d8815b41bd056b49fd99710943679a162ccf46097a7a24585750ece886e38eb4fdb866fa37 -a719f667914a84f62350dcc6f4f30b9ab428eac6837b70318c3ac491c1e69d48af5e1656c021818f377d911fe947c113 -a148807aafddfa0a5624c7cb9e42468219e4bdb9994ec36bc19b6e6d7c4a54d3a0763d13ca80624af48bbd96d73afca5 -aa012f205daf22a03e9fb13a63783dda7666f788a237232598d02a4d4becec7a699ab493f78d722ce68519262924c708 -97fc15fab5952c5a2d698fd6f7ad48aff1c8aa589f7d3b14285fea5e858c471cf72f09a892e814104fa2b27eb9771e73 -8da8840236812667c4c51c8fc8ab96d20dae8e2025290b9cde0147570a03384370b0fcbe20339c6aff09cca5d63e726f -b477d85359a8e423fed73409f61417a806cb89c9a401967622aba32bf85b569e82bca1b3394c79e180114a0d60b97316 -b3d6ee2ed1e4c5cf8ba2c3a4f329832e41c7fdcbcda8a3fcbe8f60967fdb1717665610b7c1ac65582534d269d762aa09 -a0b3b30b1b830b8331ee19f96b4a4321a6b93a3395b95d3a895682c65ec6ea64774b878b93514eaf353f2e4be28617b8 -a2b88e9617f4d30ef4e686d1932ad43cd555fadcb5102e51bea19e6fca649284ccf4debb37b5cb2090ef386fa5bf5327 -8a4446f7e8463ea977a68d6217a9046ad4356d6fc1c18d46c5d2ab681ea977b8faff136d65abea6bbf8936369cb33117 -91e7464bc56e03f436228104939ddd50caace5a38f68817bb2991e193b57adf6835152bbf3dbcdebf0382ac9823f60c9 -961a441e6cdf8106c4f45e5b47190d35644faec701c9cfc41ced40cfdd1fa83752fd56c1ac49131a47f1970a8f825904 -94b7b165cc71c2ae82976b8f03c035fb70e90028992b853aa902c0467b384c7bcf01d56166bec5def4453e4d0c907e52 -a5d32cffabbf547f900026b34ef46f08075b7a244565f615370d2f04edf50b094c95088a4a139ce07caf55bcd99afa07 -b4e06e73660745f75ab2f34d9f6d2675b58f80f911ab6dd4c5a6ce1095f9a2b50d86f6ff9a05394190bdf96af0827920 -ad3fd8f83c0103b29d41319209dffca201d2b98094362da08da3fd6ff0ba96796b49d6bed525c9adb96c2954858e7f48 -b0c27430695f0fd20ae31e1ec621da090094f2203e17411db9384695ffcf5c7c6badf461ba49ba70164aacebd6f278ee -b9bc6e972fc3b532fd2b1eeafc4bceb77604885f32132af6a9a842fa2440df452f49ec0cd9d86da1180e8deb0723b260 -9729e22d6104b0174c136a854920f542b384d375040adcebe36acc253bdb55845eb43e34dc5a7cc27d22c417973c24d0 -a8b420b36d48786c9231d454468a6e855dd7f71dcfd095efc9855ee70dbece0f06ad277f7829c5813fc30524c3e40308 -8757dff5499668c93fc5d9cea0a8db61817b8ed407200d623030b5849a913d12f8371b667cfde8d8082026eda7407e8c -b859ad747ca5af661fbd03a1a282df6e84c224ecea645bc2d4ba5e35fa06cbf047387319fca0cbc76b712398c0798968 -8e3173c27875f1460297af0fa736c945dc842ec3e476a973d3d5f790bf183ad3ffe96ac13868c5101d8e299890791864 -a9d725e2b92c878be42b5eecc2c3081c63c7231ccc7e2dee17ca6a4caaeae22788fab1f1465fcbd7fc236613fc2bae4c -86f6c4f04a354cb2470ef91914816fd740f8d5795ce7ff981f55a2634695fde5951bbae7a4bbc4c63747040f8644170a -851773cb26f320f0c3f252d95ea7e058ffcc795dd0dc35e459aa1b6b448238909230d809e82022e64b7fca5d40b8324c -8962641e0306220d9892fe2d452caa286301a3c465185757be7bce2d9b2c9beb3040280099606cc86773e43941fd3439 -8beb6e08c440b0de5fb85251d39d9e72db4e556a2dfe3dae59efd8b359d08492064cebd8d8993254b43bde8bd67d969a -a7e047894466ffe3dec4ab8d5462f2b1d8ac0df006b1d2dd26caf499ea857d93a811cf42233f9e948c9cb903beec004c -92eedd95557a91691a5e2835170390ce2401e223da43b78615a804c49566f9d31cbb7f10c8a8390c4bdcf691544fdba9 -a5e5b5d8fa65824e958bbae98d146b4b332f97ed50e0bc2c58851dc2c174ab71bcbb1ae015cd2955c26b368487dd862f -853a494eafb308175629d581ed04bed71bbc3af9ca4c0dc483d03d27c993a2bbd88cea47c2085a6928d166fe6938fb77 -83f06b88d29afbfbe8f61811690322ac4fdd6abb9a23612162e7a2dd6bcbb5f14cee298ebebc1a382484f7346dc51e60 -8c9cf05735ea5a0e563490bdc7ed29a4426643711c651e35c8551ca6f855c8458ae8f0933a022d0bb9a952edfed411f6 -b906b48d807748a26cc2a8848455a76ce502261afe31f61777b71917bdf7de2fece419db636439478c7582058f626c29 -97efe1fa7c9b25d8bea79d74b6cdcf88f63f1e865f54b58512a2e60428630b0b40b8b6af1b5f71df47520507548c3cad -8ef5ca6e753818906bb3fc71405928d8e4108854ef0ef01c1009071b353bc2852e771fcb619d5fea45590e8f61003d7f -8e4d901661e2913740d70ba4d0745df5e8c9c0a260149d9362beadc7e669630ba909ff0e8a6cc85c54d6b7435d0d351e -b7c6ba3bebbd9592967954e3a480ee8df1d9f5965f04e7d78a5415b645128deae7ddaf6ed507c8877bfca91ce078e529 -840bedb0ad4e25acf6cd25dee4f98fea495b2312dc5cb7a8388c5ab00b2acb9cd25da08e9fbead145a3107972b1ccd5d -a8d4578dbafdb27f3911af59962d89e75dea74db55346720357790da677312c203107d9c7911535aa563446fde7d4c47 -86d3b77f231bfa09251b7fd2ce09c27ac520ec35d783e912476f9a4863f83d269eb175790d6e735da9260293d707f8ee -b34909f1cc033232652da0c34051a769dc76adb1aee00674a59dc1b860f6e610974c3b4bb69a69ccc73e01f042431242 -90799854d0cf34e1d91ff8e101bc7c5007423d34d2f3bd9adea2ecac57e83f3a65a506bb93d4caea49b29f6d18149957 -8ef94cde29b037e19a1ce7bf4418ad3c95cd9457412796ea385750c19a6690f13a3bb5bb6a9ee81e7a40face1e0a8bca -97053d21ae8d75972fb37f6fe516c38c32ab162fb56b9f510f954858f4e3ef6ac8c3a9557ed3f41b7b6aef05fe97f931 -90a9f9f0f40991f3bddc58b92d40382147db22cce50d092d4a05aad251b46b94e71ec9f7107a180243288059fcc5ce29 -a14265b1344ac2921b0f890d13bcfc432e4f648ce403e261fce4d3bb32ffee9e2794c02830346054f998e82784c77040 -91928402ae121e56a3e64cd6f390127e6e92fbfb1967ec6efa4f52f3e8058f1f41a0f4fe96b5bcc11641c1139e790b2b -921c8c92b6d40da6c5a7b592acc74fc0f577d93767b9aa4a1cd302a72dbf503a1ea5b2c29fa0d0359bff3b8f252246d1 -93ae0ebe0e8e133fd80cf67a499047e30ec4c4660ccec9d49098717ef57721a030f423e00c5e74af4ff4acf014a10497 -82c865e21905aebfe0496af1c6ac7e342b5f446a9edb4f7da0f2fb0340abfd8e6fc545da874459d9aabe6bce0dd9bfcb -aee3961d8d2687c0f134b9c28b920bdc4021d925fbe14323c84224a9fe161248789249fb85436a5891d0bbff42c2a3e9 -91aee420b98b6949482b8ff4be996b97245b4e8f583a6e085226539074f42aa89818395efd1a6699735a569bfe19d623 -a48eec22c192e495b01722d0016a54acc45ff837e2a95c4294ce81d5a4e43e0053a6f0ead8a4fb3ddd35faf6607275b0 -a26e15937c11faa30ffa64817f035e294cab0e839f73d29de8a244ad039be4e221eb47ea08d9a4658b0152fc3caf6110 -b84450f948aa7c8682fccb9cae84d8e3558adf2d0ca5fb81eb200415291158720f8f3470542ab5b88c6873ad08e7fa9a -a8e8ec27d0608d020169a85d6ecdb40eb402f006a3b97afe32cc01987721b3a68a92ec693aeb4d357e189e05fadf699e -ac87cd535ef5699312cc26f86adb71baa0be42e858bd5a2d94ac05737dac63430691e29b9a30d2559ad581a172519b2c -a4481e67b524f8cddf2046625efd3d75efee6aab87ddd2c1b22835647e918157e5e924ac760db2195c86d326f3db1615 -891f29ded231486ee826840c8895cb325f7e84a5a6d2eac246cb3573612cde274720233b1978318a57ed337a046330a6 -906b6e750e6178289012769807d2598925d7e51c260c14497d8af978b1695990e3352e6e809a752f376597a68083870c -b7a056898ee1e46f7f29702fb39232f678ec173eccd170303b3b0a30c8d8cf1a5321384e3513e3b03bb742c238deaa54 -8f2f035fd96c3a336354c89ec9b8222803bf42e95fb2412c28d4e75eec99c1d4d402501ccae17357b757db8bdb0bfeab -81228625ffcedf977fba9cfa13f6edead3985e2651d5974789c394a69401cd7face9e20ae6694be4c0d4bab5e99c61a8 -885a83eae25e61439ad809567a2ab148583402e01cfdd77b0e37ab4038935425c64b4e0886949bf06438c35e80aa13f4 -8926387f48752f6933899c48e038cf14e7941ec6a58bcc0a436614b396296a17aa53e6873803dd3041dae470bd493fcb -95d0d3fa061f4d856eca78a569aa132db14cede7646f97e2aceb6da0c8ea53195d3b7a566fe5ec8c41b95ecdd89a1c6b -a3c817f4062ed6aa94064ea695d76c1825f3bf77b310fe1db28b8bedc9aaacbf1019dbd128adfd53042fb943d863a2b7 -af1208417aa584052da309169854149ede38a3ad63c76cad6e43afb6f1a7b854edf8310a0b00088c039259cedf0f859b -8b713fc3196bad35dbf364089049ada5477e540d78d76a5f0a9df98f7ba4a0e65dd0644509c149f9b07887298bf74b04 -89c09c43c5b733c4a417cd9ebc0795cc3348b72778d31828a9171427779a82ef023c1a4fcfcdc919ae25056f9c826fde -a0759c850ed320c8c874435e90ace6edfb8e7b3f2a09d942b8ad8339c508044ee2ee26c70f1b626ec49a77971433b6a8 -b85cbc58d4fd52286e714ac4eaaa0b2743a1de06fa03ddf8f6668ec6f1d204acccce93b10620272afb8c0b49bc4b0a43 -814e0a87384e159892a8d23036985fa3f489c53bce192e107bd2d64f57b1bf5ea0acc1ef46c7a42bbc5cd0924d92b4a0 -aa6821da96ad89d7881b878e141076522f104ea9a5bbdd1fce9f641898f7d6232c518a87a0f666871d7e3165c26081e4 -a9041d714bfc067b5427252186fa3557bad598fc0067dc8521aa9bc1ae298f6e96113db5ac9f6bade9a85d5a950c9755 -b8669340f3064692625e1bf682d34fbe69a61689e3aa6d6a3e822c781d406b0300dba9c3f7b8152a8c2513f1310d4291 -a78c53316ce768a1dc5968030bf4fc885f4029b1ddb6a5d84a61c85af686c73727f62823891edfcb6ccf4545de366cff -ad1d3aa29ea28292ddd438c865e2b5d93f32cdf009e6d5f5dc726de996583925727e6348bf1c28c22dec0bd86aaf867f -ae1447a2062e9e28af5f38aecc60fe150cd10c2edeaf2110034aa144f6235ed7fbce432a58805d4fe1f6b12652d6e1cd -a32146634332d3303934550705353c6d4fae5fa5985105bba35041e74cd71e2aad67b45da171221f6ed80f36bf6dffa3 -a232e8286184196ea77427b53d8b52c44d758ecc42d22556529db3136379b4989dec61cff610cc6cf6700a450a847a94 -8a72c7255125a736da52dff5f77e44c3de29f88fc05f5ff9227c69df296930caaa11446595e6bea3bd946baac5ef957c -9688a981a9457678067f629f8efa6b522e7318b529f88d37ef56c5bf8f1c34fb9bb3a918ab73caab82bf5abb0c03518b -88286f3eabd71115fc3b17a6bf6981340a81cf7e5f96b0a1a016d4ec8c18fb486d46c70919123d0c189a6f5d6ff29a1e -b535e701b40d793c02ac0d625ca91620d3f4a512aa9741f71389e58381008b2f93d597586d06213c4e103d67d0ddf6c5 -80d0c9dd941e8d8d3700cc51a434a5aaa3308cf8ebfd14128ccfd258f826b27cc3cf5c3ad7851340393abb1eeab3a157 -87049225fa2380d93f18d3d90cb0697a56b373b66d7f24ab209966aed8b55a2790194d5885399db29dd5b1f189eda64f -a52df158ce8670e0290551e8878d63dd33b4759d6f50e448e63fc7fe6ea99dddb6f180be5fc0fc3918ce54c05f80b356 -8b2a728b39c465fb0f60b0c486e5dc8d5845ccec03d3dd93b393cedeeb3fe1b44518359f1ed55fc770a8f74bfeb9923d -91fc05419dba718fa4a910dcf256ebea356bbea00522d8d5ec3e7ba4271a26035aac15e8d9f707969df1d655d92dac55 -97c8779ae80c24c1f82d5a714762d6ee81069224e39515e41d8a71c9310dc5d1c55cc92bc5c6a4bd391ae4c321d1d4d2 -b5e5aedba378c4484e3a7a4ed41b75b0844f674261c2501497de6f91f7274b5a4c1be0e055f2e0c0cab843d891169fbf -8a26212f27211b295beea500abc8e9d430a8500d3a350cc62f895d39e8b4668aa638c17633804ba353010000165637ae -864a95118e5d394e00e99efebd505df0125525c9ebe165764c453b80ad3edc730feebde3d93850745dfd88a27bb8f20b -a092e0b78290e826cc1ae56afffdd08f7c10954f549a3ea6666f3db1b6cdaeb7df53db28dd2a92446342930fe60a27ce -a1720224c0626a081b6c637b2a6d37da85d9a82241e5efef3bc15699b02a69f6304e43d8ff3144d60c16e00225d6b39e -a7b3d098cebea9cf32e19c5195608182b6afe9d4af6b9df532c047eb7a941a971279b2ae6a4b80f2f9d9313a6d788ce3 -a3d2451e6788944802c5077a778d7b7299dbb9d1612676bb6baae78f39976e0fd879493cc4a4d737b8174b472a456850 -930121b73da844571b1411d56760e80923a4ee09917b3e9cff4d3dcb0bc27026ff2c4e2c44e7aca7d3f8383f129c7f9b -b4b0119d163ee00a2b74bdf188a5cdcf054daaa48c483b94bbb4d09ff615afb4a91347db6363bc7535e2af9054ec2214 -a5846decee706780201095a8cdd48fbf3d3a2eac8d089a818e5e22c29457494bbfb4399323b067f3d2be2197c33dbd98 -96ba600df10ee7af5a9df29c0ca31dbed275d647faf9c66c7342de927ceb25b5bdd852dd7aae0228b27897f90fdd5d62 -b6ac51ddc98edd9fb9f54ef84bf372a041d58dfdf0dfdbdc4b08ddc1a7ba93ddbb1413dda3c1545a3fd7386c6b85975c -b35f3efd91a0723e0d486188ea9675a3462106470455118392d7610470b623caca2fa33829721c05fbeb0fabcf570bfc -87f49e85df5f8055714a8ce7adf37f6a278e64e76ed74c60abe3edfc3611ef5b0426d4c6da45e5f3b74d30be1dc6f539 -8ff8bb06902a71b1e9177a77367318b2e3e0a88f5d74d6907ca9943f4f9f1ceb5f297132c2a025259d17a67e880d1bad -85eb6de6c70fe5c53ab0ab27aa0fec439f136c979c557d317337cafa6e6c5cb3169679c9169567dec5f6c72b3c057d83 -ac18715ed1080771d760cb7066c6328faf65d9b30517903f8a5cad8d66d5c6381156b521107d7cd75ebb8c30e250706c -b95b9eae4703727e4ac9ddf2ae675906487bb78905a5f9cba74a4cbfd118d96b7afb6ef3ed5edf14fd963b830d71338c -a3b47b52fda16b62b11c8aa4daa56b0b669c4d5c56a3059b7d063284d8a91f6fff9ccccab23d6ceb9650483b2d353039 -96a95b3f327df94c85e92f2e406f1649ac621533c256b062738f3c3ee137059a735a3e6072247acf57b1b0d8c219bd7f -b19b33cc04570be94eae8e943d5bb17bb0c96e9de4ca84f9f41b37320a1a03d397d53747dc13275fef1b356de557214f -a1faa3dcb931dd91507f3f12a17c43f6627fa2bc5c71fbdd27548e091eaaaba262477949cd51290e81196bffb954a492 -b060a16079dca1d28a1fb33cbc26f368630ee042d980ce305230005d5b9ab533a7a695281ab76e9214458303932d8bbc -b303783196a858fe45d67e0520c30576da605fd69964449c20009fbd5099cf1de52a32d326d7c3b864de07440195ef40 -aa550a4c20d1003d137ffd8fbdc1196d09ad53cfa0e202302093a80fa3bbc4c9aff83f34f2151785cc1ce5f30255693b -a7f8585f45566a351058e10c6f1ff4a7ba24811f1482a47202f581525615ca770da93f2f58878788b45b92cb446ef4ec -8206f63a9a5b59bd68e64a843e68fcdf706f4c13bbfcdfa9928298e5b9251006ae0bbd80c715aa3c9957d2c0148b5059 -ac9490abe1241319658f1c2c645cfa01296f5d4106020c7894b7ba4a65cdd52f6c5401bd3b3cf1c9863e088cd8c9a16f -85dd6d9c80a1b58c24c4d2cb7590d33d2454f381f58e820979948e5831972360cde67bbd56e1860077ef5192fcacb904 -8b0285944c676fe2519cb68da0973275fa29c0718d838d363ce46651b068d29f867cf9fe579ff8da0bb8b37d202bb23c -95147275da658d43a758b203b9ca1f1c1478853e9bf77b5218593142e2bd9c0bf46d2206ab64cef99295de6e9a268edc -b8efa187fdd3e1f46c15cd596e9567690c10e253b5beaa5be8074b6ea4e6d3d06e0f2b05323453239e419ae1e7128521 -8340464f52c92e31806fd3e8e65f56e27194d1f6daa4a0f0b3831e8102aba16f88bb5a621633ddb7dd0342e1d2d12343 -8615d87dcab85a78dc052f05a01e751176b756b5dc9985014347454ce5752f459dd6464e1c5aff36cb6c51b783fa2692 -80c6e35c0d3defbe4d3968792724a23f0b8830dd2fac58663583a49339ea20f1812cc4140e3ee867c7e716177319bbbe -a7aa63dbfc201dde8f29bb6e23d7aa5020dd35bd18a0cc93c8a10c35d695913fe25b9e8cf9b5fd1899e9657b22bc8863 -97c2a4ba80c4caba2e729a603d2faa0120915e3fe64cbb065f7ff33de5f877f1ec9461cf455e88ec9e9ded9393939dba -a54bd1419f0e2d2d87757870f37c476c7e3a13502f1ada82fd7394fd29f8a00c4986473d753034d0954a2550badbac0b -8d3e2bf900d0d2b9b46e6e2f37620f0cc90526dbbcfaad4e4a37ed53f39fdd23bd3a6f21aa7e800eaec937d9710dd6e3 -a88d2b1c7802b2dc216c2b6532406c091bfb12f29121b9a82c1154470e250188413ddd3e79f7e009ea987a4c45b332e5 -8c552c2101dfdc3f99c2da436115452e4d364eefe029b12946f05673c5ce1cfb48d39a579625849236dc6c8e7277dd30 -8415c252d52a26a6400c3189c928a98559bf24162ecf3eef1d10e439269c31d854b0b4f6ec7a2430e3f11b5d77de78d6 -8b38905bad93a8d42339dbdb5e510003c51fcaf05e04f88fd7083753353bc1c4c00a5dd4a67431cd4456d0669c7040e2 -b1d0ed8862250d0f0d9ef9dcf0cd16d84313d1a795dc0c08e0b150dadf9ce73d32d735e04632b289cafa69a6ee75dc89 -9434e18a5fb631b10edb02057f2d1fe16000ee55ada3c26a079c9fc3943e29d6de99e52829fe7b333e962270c712e51e -b1b9f3914007e6fca8ad3e7e848a1108988cb2318da36df24767d804e95d1272943fda948451135cc1b5052a3953b081 -8c02947a76d7b6c0a700a83dfb971dc105bfe996e18c521445f036310914b349ab28e57571e36ae08d13a46fb01c2f43 -893472fbc225f973a0ac6a0a0130b9cfb7ab6869dff80df71a62b1f6beb4afd069bbf35b4f327165bc31dff39e4fcaa4 -a7c176c0903175f3540d62f9afee994d5d9bf37081e094644b22f017e94c515afefde7bb07f638342abef7de657f8848 -860186c2b1d3b1e657729bc804275fb5f5ee89eaa60848fcabd3871289665ea9f0efc8a95792d884972bcfa2de96223b -865b38aea6386d0ac8f501a7d934e23d01dc50105324e354d4c4fa3cb1d4c29c26f4566df7b1a728e10cfaa9d24552e6 -b4eea5548de6969dada658df604b5d9c49002e2258352838003e0fdf7b299d81fb025807a7f37cf5b547cebd7f2c1f93 -8982de11ba68d63a649a3b296d4d56c71e3c3eec016db250d733ab7c3b9a620c09c5a5d0b64fd30d3bc03037ca4b17c9 -84d8b8a10d67eda4716673167c360fc9b95717cf36ef1d5bc6f2ef5b9d2624f0e76c2a704d016adf03e775ea8e28d83a -834d03ebd51aff4d777714783e750b84c16cb6627f8311bd8ff17c3b97fc4a5bba57d6c8f6d74f195d3030bcb5f07612 -aaf49e0def0c4d5f2c1e9c17b51e931d2f754b19e80070954980b6c160178349f6d3c8d4808801d362e77f41a0008918 -8ef4115edec841854e89f2bbd11498dac7396bca35dda554290d3db1c459ffc17be671f4a46d29fa78cbd6064cc2da20 -9641dc8a64f4acd38e343a3062787c48c312f1382f7e310ccea3e95e066ab6dc980f6ed90a633236a435e68bf6b3c625 -8a84cfc2cbeb18a11dd6c2a0aebb3f6fd58a33bb4b26101e826add03748595022e816afac79a4e7c20b3805252839dca -9770782d729017659844421e1639ffcda66a2044df9e19769b90292df87dcb146b20c6b9141bb2302029d84a5310665d -98c7ec9696454868ac52799d1c098c15ec4e08b34884dda186ebfe87d32840b81fd3282295df141c91137faf4cc02da8 -a3f6eb921247617292162dfc8eec5b830ddc294a0fb92f5b4828a541091ffdaff34c392c1d7168259d6204405d90ec72 -b185f77a468f07a54222d968a95635234e74fc942485604909308a9028ed2753b15902b9134749f381f7cd6b89cc8c3d -867608a682d53bd691dbc92eeb460d1c300b362ca49c11a280f6768ccec217f1145f9d59fe50d994f715ce89d38a74e1 -afaad630ad8827cd71aade80edf3d7aeb65a344878db12fa848759e6233f6fceca563aa437e506ea9e0f1e47b126d45b -a12afbc84e3441594aecf85d089423dd3bb8bb33a1a384ddf7cc14caa72284caaa56aa179c15e3140fd56bb532491a67 -98757b0b5e5837ddc156a4a01ce78f33bb1fce51e0c1254ee9b6d3942268d0feb50b93edbf6aa88f9ea7b3c0309830d8 -89573f4a4ae752e9f964e42bec77d28a41840c28e4bcdf86a98a131d0b85367b885077823a6f916972de6ac110821bd2 -a17f2745052de5de9c059307308fc49f56cb5230e7a41cb7e14a61c9efa742ee14c41023ce90c7f2261adc71e31045f8 -914b07c53a41c0d480083f41a61c10429ea42dafea9a0db93862d2269ff69c41db8b110b4768687b88089b5e095523cf -b380cc3e0d26370976fe891d24ea4eeb1b6be8cfce01f47fd68838a27190e644fd57b049d3aa0a9589370de20e276944 -906385fdfad60feec79eb1c303e750c659ceb22d9c16a95faaae093daadd53e7aa039a45d57e20951d6e1ca0dc899ef2 -b5211ceee31b194dba60b616bfd91536e71b9213a3aaaf5aaf9b2f4cbdeb05191861d78b97eec58e3c81abe4f0488c04 -97878e9e38c2f69d697800e7a2f132fc4babaacf471c79c26a757f771606e55fe696ece68a3163a0ffeb2f72274cf214 -959431c1f54c46500c05aaa9a2bc4230531dad97ae768fa92bb85436c0ecc6374cf20fb0ef82d122db116820a943b401 -b69e5a1c6798f30d33e42cb8d124f025d2c77c993c4c7107a539aacddf44d8d4d2239e802ece32e60ee4dbfdce201bdb -a8b09e5e9f802ad273b2efa02bcbc3d4a65ac68510510b9400a08d75b47b31c6f61ffdb3704abf535a3d6d9362fc6244 -a41ace7f1efa930564544af9aa7d42a9f50f8ba834badcaf64b0801aaed0f1616b295284e74ca00c29a1e10c3de68996 -a8f2aa0bbbc19420a7c7cec3e8d4229129b4eb08fff814d959300cd7a017ddb6548c9a6efebad567d5a6fde679a6ac6a -9683da74490a2161252d671d0bc16eb07110f7af171a1080dc4d9e4684854336a44c022efe3074eb29958ae8a1a14ace -8ef44d78d10795050c161b36afa9ab2f2f004ccf50fdeef42fe9cdc72ebb15a09389ca72a00001cd6d9b1d7b3bb766c3 -adca54f3b14fb18298098970b0267301b7312afb75894deea1b2afa3e85b7a3b4efac9971ab54c5cbecba2da9f18507e -ac5d4528f06fdccfc1370d5c3d03ed982fed0861a93a3f6453aa64e99360b124926d1892faaf72d89459e663721dfa99 -98aa1c801bd615b8cba728fa993021e181e0ad717ba01c0290e7355694155407083eb53cb70819c4775da39d33224db7 -8b3aea4c7c2bfe1020de3261ec085d79c7bf8a7903b825d2c70ebbb84af197bcc54e3653c5373a2045c3021526b63b66 -a29f3de4cb3d99afff1daf7d431b38a33a9804fedc41626618928ed059df6f6fe9f298a046b594ffee951ed4d4e1400f -803fd346be540c5242667c18ee41b26bc812456ab13ff117196ed69b90ee608c8cb6554396b64066a546ec87a71ed6a9 -a9c18d81ffd029c0339c72c499bb51685392253b996b6eabd8b76f05c6191ed8444a1397d63b9923743661a319517f7e -a048d5c390d08f07161faac71c5994baf152c883b205f3bb10d3501709d6516ae54d491b486303a11b751857a31f0052 -9156fb4803e40e28d8d57d928481a8de4373687288da44fe88c5676a8ae013ed1fcc09d56a31140bf74e7f767253810e -98e289c725b18e0085afdfaf2acbc674dae7b0a2ecc2537a7d0b87e20eb785404ab05973a787f0495d2adb3e5565c09b -8a7237b249325bd67cdc1f9fb278710069033c304afbf270b7ea24dbc10c8eabe559a484d3edc733c77b4384932deb41 -9056f2e5b02e5c2e04a69fa1323bbf1859d143761268d18e74632e43800a2a9c76fd681e924a19bc141de0e128d3e462 -b9f2bf9e4e7263014296a82b9ecbb05d3f1efa4b2e675e3b38d3eace59da06a89c859256e1b77847886d6aa15f98f649 -83b22949cca19030289bbf7cd2a0d8b84e1d468e78bc85271a6753241b89122627632723bc293cf904a5eb2b5dc6c3ae -a919aaf35dd0116168d2ee845122026416bec9633df113fbd913d8db5996221e234f98470d029a8ff182825b59fda20a -91726901f49d32b41afa15219073842278f60dcee223640903d871e318a1c2b541136b7b38a7b2ab7d31e4242fc29674 -942b77666545bc9a858d36cfe857ab1a787c9528f4a0b87918a06bf510793264dcafd12ae6bd3ee300179dab7f40aed0 -80adc1f2f9c47a96d416e44fcba41628abc0fae1f88f6a26aea4648419ab726f7fcc2187c7d5145e3d8f5a75c03937f4 -8041e0f66ba9dcee01e336dd4d16ae5e4e1618512fc147cc8230003aa2940848162dc2187d4130bf550dc1f3559849d4 -999e8adc51bab54386af1c5e8822986ad1b7ecaf1f8a4c2baa5bb2fe9d10710e49545c5a8bd89ed0e61a3d73a908e5ef -89272ffd39b6e9f99fafdd58bd9dc00f66f26a1d36b38a1ac6215e3546d966739eecda7fc236335479207cef95cce484 -b8e0b7532af13f15dc04a0eb4ea8abd67e58f1b1c6ad2e70c0ffa04a5c18ec2018b5d7f4be2f9f86db5e0b3986f639d9 -b96bd11b0f6ead4abd5fe1e4c6e995da7583b901afd01cc05e87d04663fb997997d6d39dd9fb067c62cb1b1cbb67516f -94ab08914088b973e8dbd5685decb95f3bf9e7e4700d50a05dbf5aaac9aea4be2c10c83096c02252e9238ceea1351d05 -a188de419b062af21275d976494c131ba18d2b2ead8bdbfa38a777832448e64d4d9725c6a1d530ffb6513f18d5b68d9d -8f73c8c118fa25c76a4ec5611351953c491452743056a819c8c82ba4737a37d88da0b55f837e7239a5f46d2c05a1bbba -894a44769e0be1c26648b0d89c4c9f46dbdeb3a71b90c493093bee372bb9f2d3f319850fd886d51f4f58db0de5641742 -87d239923b0db024a8d9b0281111d47b0761d81c50652268b074efa3ea70d793e30f874a91ce33a4acecd0cf38c01951 -b1b48b75a97f9fc2dc9530dc69f6268829dd0ddd574516e7eb1b9f5c3a90058889a7bcf3d378738e6d4b02f5fbfa44db -83e3ee9526ffcb60c6e75b75550fc017912ec0daf96d0a0d5f58c1b229cce90c684ac7c3e17fb998def8e7e2e155d750 -b9b7bba579e474b0abdc7775ff5f84c9f117c6ca17788cf5a5f01b2c35a14aa39036031c8d799fec2cfb371d9f7471fd -90d7faf4891fbc368a32f575dfb69f13e37161ab4f63a7139be103285a49490c2851a907f8d36e09e7d1a190dddbc6cd -968c8b9affe18fc34a4e21f0d8c5518341c566099e6b45b8721c9912bab3693c9cc343406fe90279692a1eef2a3f7311 -8735baaf4704207550f77df73fb701d9a63329993a8cb355ccc0d80daf950145f37e9b4b22be2aba29898e974f9fd552 -90f52b2dccf525b9191d836b205ffe966d9a94f6c5800f8f51f51f6c822619e5abdf1257ee523597858032d2e21014ec -831209f8f5257bb3eb452d3ee643d5f063299f8e4bfea91b47fc27453ac49fd0ba3cf9d493c24f2ca10d3c06d7c51cd6 -a5a4db4571f69b0f60fb3e63af37c3c2f99b2add4fc0e5baf1a22de24f456e6146c8dc66a2ecaafeb71dce970083cd68 -b63da69108fad437e48bd5c4fc6f7a06c4274afc904b77e3993db4575d3275fce6cffa1246de1346c10a617074b57c07 -a449448d4156b6b701b1fa6e0fe334d7d5dd758432a0f91d785b4d45fb8a78e29d42631bc22aaa4ea26f8669e531fed7 -aabe43de1350b6831ef03b0eef52c49ffb0ccd6189cce6f87f97c57a510ac0440806700ce2902e2e0b7a57b851405845 -91015f144fe12d5d0b0808c61fa03efe0249058e1829bb18770242f5fb3811e4c8b57ff9cb43deccfc70552e4993892f -8e9c570811ce44133ce3e0a208053acb2493ef18aade57c319276ad532578a60d939ed0bde92f98b0e6a8d8aabd60111 -8b21839b5dc1c9a38515c1076b45cedec245d1c185c0faac1d3d317f71f1bfebba57c2559bcdb413d9d7f0a2b07f3563 -90413bbd162be1b711e9355d83769e6aac52fdfa74802d628ff009325aa174c68f5329ddd552ef93e8fdcb9b03b34af3 -8b6b02e3f9dd1031ebd3df9a30432a3c86e64306062ef00a6d1243620d0cb66dc76f8d0d412eceff877ff8768c2696ce -9894b41d9fc715f8f6addace65451f41dc5ce7b983dd8cb33757b4d7259bef12f144e0077d0b662aa847d5a45f33c563 -a353a9740f6188d73aa4175a6c5f97898a05ed7aae9d2a365f15b91dfa7c28b921fdef0a32d90b6fb82718b33d3ddb8d -984eab8faed87c403c9979f2d2340fb090cc26d00cb4092aeb187c3f4ee1df3f57cb8363f7764073188790b16dfc464b -a5c5ae0ba435fb7f3ddd5ad962358da326239ff236fc3b51bd22e88296236b109951cee1b98f444302badc58d1b5bfbe -880be1006b0156f2788813432f450f613d235f41aba52a6000d2ad310408ad73d86b79f6081aef1e8c51010d404ba670 -937da751aae68f865c7a33fa38d718f20e2a1c65cb18c8e08f8441f0cdc77662789d2793794dd0a427cad30cd0b33f42 -9496fde66c834ff86f205897db12bbf9a9bb78d9ba8b5fb539cd0a2c927cc6b4120c017b0a652750b45edbe5f650e5dd -97a6f409ffeb593e149307a14bc47befb632412d70565c5f13d6b7d032acd2e3ed0f7b6af701b387f11d69ee4a8094d7 -97ed94934263dc0260f4f7513745ed3483cdddb9adb85dc33193c3a8b4d52affaf1ded23b59c34651afbffe80d40dc36 -b2b26378d44f916bcf999db218b9892e06de8075f205c7dafd6d37a252185c2d1b58e2e809c717963d25627e31f068e4 -b8f9fa1fb45fb19a45223f7be06c37d3a3501dd227c3e15999d1c34b605f888123026590697d0ae24d6c421df8112520 -997aa71e3b2e8c780f6855e94453c682bee1356b5ce804619ef14834475511105b1e4d01470fe4e2215dc72182d9909c -ac2cb2a7cf55aaf990cfada0218453853047e813d3f51f5a623d09f4714da79de6592671358a5edf938a67f905b6cb5b -8d8340d0c3081cd30d34f3ff6191e1ff6ad7994b4ebac19e5936f1157ca84e1813228b7605ee226366d6bab1e2bf62a2 -9693b17669086003cb46c75fed26ea83914a54901a145e18c799a777db1df9c9ca6b2ea3ee91e7b0ab848dc89cf77f19 -a6b6b2a6cd8c4922d78c8ba379373b375d66ac6ea04b830a23d5a496cf714a9439d81c865da92d52600aa4e2e43afcf1 -89cb665020abc3f5e11a03c7ba5ec9d890fa9ed2630f1443a8e45a28c32786ed980b5343ffffaea60eeff5b313bc0d66 -b37b989106594221bc6cf33a1a83c3e65ecdef279e90333a9e105b8139dc28384bb2277edd4b77c9e59d15e6afe074c5 -98ce5aee5918d18b2326b30c1ba41669cce20bc7a1d1b585363305fbdea66055164a7ac398ca0f0e670291a3061022eb -b57f472d5f34beb4cf430d7c0f8ac5bd1c0621a284633ed36e6f7804bc2b7847f54b469c7ea163a436510d9e3b32f97e -ae673a6579dbf0504c8fd0c8fc0252d2f7ae8da615a06f4d215c2f8a8f516201f24e5cc42967630c252905e5dbbd6377 -97c1501835a31091a5a83f0546e01c85ee847a0ca52fb3cc0653f6a826e13d25ddc623a5dea139108f7270a1fd7043ea -9376ee667f3834f6c0da4324fdcca5c04712e0649877ee19da79a2d23be24640c38758fce562470ce2134ca34148ffe3 -818af89c40379a10074cfaba6d5968ecf667f1a68a7edaa18e8977ccb34e0829f237c5634fbd079e7f22928b277f1096 -b8e0af0be0a252b28df25d4a509f31878bcddf702af0e5553393c3dfd4a1f1247ad8dc2668bc8dedc9b41f6ad8e71b15 -811667ffb60bc4316e44bd04573503f5b4dc44d1ec824393a699c950e5fa085b146537ddd6a08a3fede7700396a0df7d -ad834cbf850b2f61ce799c4a0f8ab0c57039d4e1113933c50b0c00175171aadee84894d1376cf325bfd434c3deb44315 -a8b7dfcdb40373ba4d55e751ccfb9070554434df9e359fc165284ee3dc35db6fb6055657ecf5a9e9b7b8e2e1abea4375 -b56a5b9fd41c9d3f65532aa58bf71a38fcf07782e1ae0084dc537862fa02e6d66658b19d6f71c39cd5dbfac418da1837 -a935af5ed224b9533b41a7e79f872f6851591da9e9d906050ccd1b2c772a1d6d010c5fc7160c4f8cd7d3aa14c3bcdc26 -a81e580fc98692567b28323fc746f70c3139d989fb6aabf3529504d42d0620f05327e3385c2bd5faea010d60dd5c8bdf -a8b352054cdcde8ddb24989329a249b71498a5593a13edad1e913c795dcad3d24789abca9c7ed1d57efcc9e3156da479 -b0de8a2bd7f93284b2bc700e442f52ada16a22ad8d86329591547411c23fff0333b2ab0c9edf82bf7903ebf69916eed1 -843e9781b653d1a427f3534b2e86add49d308ca247546f9fcf565f9e08df921e4d969e1b8ed83f3f849e98c0f63e39be -84a4098c5dca9f73e827d44025473096101affd7193c40a0307e3215e850e753e9a08e6e74a442d57626ff26df77faac -b463eaaa2f3315b511c22a97fad353014d840a6a95fe0d457d0677e63e571407d7f5268f8775381a5e7adc3b4163eb88 -ad0417edaa16cfddc288eef4173aa7057ca4f81e815541ac588ef5f24b98d56fed6845deb6ae1a9740a28bb1cd8780a7 -9271963b8fb2288a96e07eac13c0543ec41abdc6d978bd7c44ae08251ea49994412b542c77c8208cd71fd8e7852d4a70 -8b68b6db9044d8bafc155d69e0daba95cd59d6afebb085791e999afed4f33a2479c633d31d534ff767b8cd433d591a23 -a6a06a0e433e385437d9996ce823abda9848754aa9cdd25ec8701af35c9ec15df999825669bbc2e17cedb597a96e8eeb -94d414bff8b6b8597634b77a77d1060db8e1af0d0ddfb737a9bf1c66c8430e93a425510af2464bce4a7b29bc66cf325b -b6514049562af1c6fb7d0e8df6987b020f0b7a6e721f4862e36b1ba0e19af19414ede04b346be22d348b50875803d1bf -a42c7fb34f2fbee8aaccd1d86672d0acdf4e6bb083ff0456512d7e1e43be041cc0924322fcd986e6e1bce5d5ecce6f92 -867cbdd169a52440ae0a75d33a28c7d00aa92b4b65aaac5e62aa53a8fc367c08ab8828cc8fa18b6e7d1f908d158e3382 -a6fe0b768fff3e4a6153e59a7b7508eb2ee8165eaf5274d41ac2812bd4563c4ca2b132f0e27ea2f1c98759cc3589b61c -b3eb1dba43d10b9e17ffec8def053fc96f9883bacb49330a089a0ca5b9ab0182e8b5111ad4aa55c1ce1b6f4afa5c70a3 -a1531351098bdfcda566ff4d811301c0305626c77f954a38420c490e7c684f517eb1a4e4bd2c3904a10bac889cba314a -92278d106ad2f27eacdb86bdb1faa0a07a93765bb79dcff191873c52253af83480114b2299ffe5324f9c31d0abbdbbd1 -8900ba95a90c447fb6fa1f528af3d7a378aec25feb0620516b6b97e54b328fc31af42e46a8ad5e6e3029d83a6f2bbe5f -86053d481179c1ac910d5e7b9a5de82794b442f20e854583512ce1f9c3f09e71d1bf97d6700fe776debfe1527ab97a82 -a32a60de492fc4340336416bccbd2591b5e414fca0aead82281212e24490acc01747537b3da783684e27aeb987245cc8 -9820fe8e0338f21797143f368177e3669a1f3894b40ae9fa3b353125f7c8e85cc424dcf89878f2c7667f65db3b1e4165 -934d64711b4348ac5e1395cc6a3215e5643b540f591380d254165486b0ec2a1d0d21c7d2c6310f9e0eed3d08ecf4b57c -b9fd32d589432eddcb66dc30ad78981360915854cc44b2afeb826b5d48a08e377dc91be66f5bf1e783d1a8bb320f7ccb -98c972cf01efff4fc2e485b47572e2d8dde22461d127ef401b71a111b0603203971e3cde40912643affd7341cd27e57a -8db6c1620760063edabd376f4399b6e1355462e04f5c81cdcb3989fdc00f9a466bc85ed899e886c89c149adad69edbad -ad7b7fda0aa6e2aa66a27235ac5cc680aa04b85dce329fc4be84f75c9c961120a3d9e446aa44539aaac8ea203eecb4eb -8ccb01eaf41d816ce69ebd57754859e263530915e775c4e7d9dac37b2457a9099b9ae9b4c6cb09eb5ff246e3c9320c59 -b895b83b5f7ca46e02697dbaa6157df6c7571864c83e504a8c77d965bc2ba97bf9353a71c56a020df64498bd40e30b21 -8018c07a81c522fbc25f2cb14f2321c61b98bd8962ed8eb7d5823dbe5d1958a5ec2fb5622fd0868e991bcb6cae016ea1 -95b16364e94d01b3664812264d7185032722a4afc23bdd33bc16ae87ee61816c741657c37138d9312cebfb5fcfbb3b2d -94a709209990a8b09bfb4b9581ab471aae3a29526eae861108b28edb84aab6d28f1d7a25dddd8150b70af34bee4ca2e4 -ae06c80839c5a13269b984ff4d8a5938c6f4d8d647b1b1daa8cf7f6145340b76a286cd615ec251a65501e6290162da50 -875cbd0694eeb90d3567da9dc7f570d97b02bd9cf17bfa011efdd48f1d580608a3213bff4006603b8b4079fa66bded10 -b27f88c455f025e1cd902097d6a224d76bdf9c9195adee30bef4a0b0411fff980787285896e1943a62271d0aca531446 -8024880cde783cdb2b863e3dd856be92bacc5b2a1347e96e039fe34279ce528560d2df7d4d1624a4595dbafb40529697 -8883d02c2a5c0e026d941c785128d4ac6f7a9de625ea735b7d6ff27a5ba10fa4d6370d450d99a855d919f40d64f86afc -a1beb985c45fdc30ac536f1c385b40b6113ef6fabc2f76d255490fe529468847a776efa674ba8fed72180f07d3f701f1 -ab83bd9b007561695210e3276fde72e507456ba277ad4c348a2aec7a6e9ebdc2277cb4bd0bca73bd79bd2240a1fc4456 -8db27f516153812149854fd6bb1250e843a3ae1c9637df818b08bd016a769d0497ab6087fe3b2fd4080882713607bf46 -b3891dde4e00d60386aeff161b4a0fbc30bb31ee7918ce5fc0b49aac3238a000ced192c9c4c08d90de3a0ba973d7cfd6 -90a2049a15c02e59024a7a1cb0adea97501c60b1c7442fbbe560054c3d69264e69627ac57b7d9be01bef498bb2a60198 -87df67a4bd72444b5faa4f3b067204c4927c869dd3b29ad192d859589a9b2c1d6d35ed68310081e140add254a9463092 -8f80986a8dc8a0d6408ebbcb4f234e76413c11cb0d66067f9436bb232373100f20a4fded60f08dec3525315abfaa8523 -b061e10beb12ba3683688a4ae3a91600d14878ef78a308d01b93e4918efc666450e3f7b0e56283468e218934231df98c -86b9e55f3783d62e381659d3e06699d788b88aab1ff99848db328a83c97d223f602201bf2127c5ecf419752fed0a224d -858d878e29925c87243e010020007f96fa33264e89c8693af12857b362aee3fac2244057e159651c476ebe1dfbd67bcb -8fd47cdef87d7a569ffce806d2c2dad100692d6c53e5f5dfc6e274f897dccadcee30fc6c6e61373961bbc1f3ecbfa698 -892f2822daf3df3a759bef03168c1cb07408df62e024747a788e94d2da325f880bb9c6e136c7f6643f45b021c6ccb654 -8714e37ac24f5a198f219e7c88a92172fc3db129e044e914663ac708d8101851e7c53fce79d32d0e6da74f2ccd1d30ff -ae95e1dbba8b9e2c8dfbe1c202e9ccfd04fa396470035a699b902fbd86d5e6a31732a7c8cae00b9a4f6e51c8d560c7c3 -b0cd058e77498e860fa20c5f8d9bd09bb249add1badf84ba8d1bd49e704b9b4bcd67a5c3d211840a2c8fefab3fea639b -b78e468d3a7da0dd481f333ae56534e2ef97587be2e259a458e25aa37952aed1cc5f835640f812d8052f5bada8f57b12 -835de7965c6b26e7ad1b92eb6f0261d1f376fa12d61eb618d9b342b597c9c117a5a8f6a36269aeea88072b4641e6b5bf -b4d0eb99136b3643468c9c48a20fad62785a60fbdd3c054efac4bd1fa7979b4c9ca6c2c0b18069c0912bea2f19832790 -a00c47315dc0700a850966836a95f3cebfde04dd094bde0742dee77b89a05b5ad655921f86fafd1e902938ff34d4c58d -ab13fa0afaa92229a71ee91efae6d1b15f14b6eacefffb7401d41d0d6db24e24a8dbe8ee19b4680ecb69d2a0cb4e84e7 -aa56c0fb18401210062dbc653df8e3732aa8921a1280e9737e99b26a0100a13a9cba8ad0317a69bba16193362ee0f030 -8b410324a6406b345df0fa25f541ac20b7313fa55832752f70cf4c79f43b0bd3d5b4cdc447e6ba7bca08d0edffa8e29c -893362241ae412d9e5df46506407595c58ffbd7fb1fdaf0694c3432470599291238997abe118bf7737e56a4f5c9dc292 -921618194a756be81cb49d6357cb392b32cc62d96c8ffb7e16d9659a0f226a0436bd378da7b835054dbe0de2c6372ef2 -94a2904f10994928ff5367b777e1430047736fbece33442cf452018bfdeae62e84cd75cf80f8468285e347d504c94111 -b4b81545b767f380bfe10e0fea9c3cc62ca8db40b43c83ffb245259378731298e3eb6c3bdc3a16932f88f5d8a86edc4d -936203c2453ff01c6fc635e4d54320d69e60047d805daae3b75633c2259108497b778f011e5a057249f11b2b888ea76c -b90bf6378d29339443c3f2008b1e2b5f0345f86e393027f14a295e583bf6e6c2b10f54b6dcc42079ff0d356c405b03bb -916913f550d327de2d8d6c7723dcef2e3869efaf95fd963d95c8980b97748c61ad8e2e629cead8577266d93fe39203bd -a033c6f3d5ecbabeb83eb363e54e5faa7ed2d7f4fb771b161762c4f003eac4e1afb236806b784baf2222cad54e2d3cd9 -ab289d4a5771147e6c29ff9ac2bf65d70081ea6c6af2d9b728c3c144574a31b5fd8632af57c18c389aa2cd994938bb0b -9488da2019ff13e290eeac132b491df58b5b7b23c2898ff1a67bffd7e9c9464c39bc8177a57950fd28589e3d9ff9c6c4 -a5abe42b2e0891851440fb2aa6c1d8a86b571bce8b80c8e9e2692e5cb6d45a1b2f055c9fc4c74a7cd292871604129ea9 -90bfef698e83c2ba4dc9304aa01edd274169a978b7154bca518daef394f55857d0d1922ebef3d91fc5ecb3b895d9e0ec -92328f1372b6406ec80786041b6d57018b8507e3881a08727aadfecfdfcfb0824394cbb1150117ac5da5d71b89e895ae -9719751c5f7a65ae2bed8aff7b4b8c34539ff011b259b7ff54f63f9d987b3fbdce5c99534ed561aadaf07bb6e939e208 -a151816774aa9379fccec21cf212429a1c68cf91b055cbb9d931f461a8d5616c693331a11ac5c6fcfbd17d84ee0b44e4 -a72977b1285618a45943ad00f33f37102e2885eccd2f76785254eeca495068fb1d8d49865343e9e8313c6c2c3b2024da -a6f5ad2e023a1585d90625c9f7094f0e8851c79f0eede8ec582ee8e063407cc5b8298e5fdc4c786e4fbbcecaf33e787e -82901e008febcea0c0a14ae21d985a397630e18ee6e346f4a449f23be228e8f338df567d30211a11180b94fbc5204bec -b9b57fdb8d14d1be87a25f89553b3966eb7869e0519ffdf4cc4d51f4cec90d68f7b81cdc0450e04207276e9c63ace721 -a06eabcf43585a001448f3dc30411f3d5b74fd0a695c81eda9981842ba2bb0081d3f5a8360aa18b6d43ef13ea78b293d -926fe48a7e8f07559b7237beff9504476dd97b5b4d67acd01a3633358a6ba4c7abed5c87683a11209aa2ee759888e00e -a716cd3a84a963e2a5a46145b6ef4ebce705de52bf2945c374152a1e41c228a9c4eae0b6d1e222c1eea8b9c13c002177 -8a9b5985df6fb32cdb06ba1591a977545444478f2fe985ed1b10de61c630f0a4693c2185d63f0dc0256b208072c43b17 -a8eab26ae0ebcdf96a59fad1dc2d5e83b94abb2ea1774b607023f9d9e0fe065853b1e2242e794f989a80a47f550c0bd9 -84adbf38164cd04f3d770a7f4b8eae7a5d25b4a803fb63c02b95b71b33e454319c44e07a760d22bf5f58e7e372d09a16 -90f443a3ba1b9129a0bee400b5b29d42e50bb2aa56b0022bbfc3c6f8d69db40299871ec7c1b68421cc89e1af6b13a39a -81c5a94b379eb98c494a8d0067c748ba47e87a2ada0105202ed7651eb4e5111a0cd8569b06ae68d392c4fd74a37833d2 -8f92324b14a1549ee0b186073a26691088e41556d33b54258fc6e0b000e9624156db4e97861a0ec22960e6c47ca8a1dd -8b021cd0fffe055068cc460aec3cc455952e2ac32be5fa060e0d1b6cf30ed15381618f801249e893b1b9f10dd82077b0 -b3e9f0dcb3d6f0b138f589fa54dfb01f849890ab97016372d004aac55103f363a64bc0e606ddf75430f1534a30fc522d -8fdfe64af891db89b25daa859864d479cb7599486bd6f36e593f8f2f839f942261ffc3eed5001a93fde44cbcdc24c583 -a9e4554373c5073e135874e2bacbee69c65308eb0785532fec6a37834e8d0b437b77a2f11cc63c87d7183b82cd9b6bc9 -b4c47daca723ad7193ac5098cad4dcab654186ec5ea5c0fd014a3ac39726be954565a901694ba211820c011fa1c59e18 -8835427e86cdceb4c11cbea331ed724e4e78af15e3bab5be54f6b926bf66b5d99bcc40dbc456d86342c9fa83a033c2d5 -8ea84590a400cedba047c2661378921a42f5ca0421da58c1bcb37bc686a2aed98afab3fa5e6ba3a51029390ef3cdf4d4 -b48551170fc479d69fffb00fae4fba301e92e37cae08f596db6f6489c3b7020edc074f9e8d7465b84e9dcef1b6b3aecc -a6f318b1eaab00836a330710e88bfe400395b3081485f6a212e3cba9463f6fe7864ba4f71e57a411ecdf2bcb4d189f96 -848d5137a39999141a79f4bdf91150796ba36352d8525821bf3bd6e070b352792d79147341b8254dd60fa8c36e9e2618 -a8526f8904b1eac4ae2a25534aa91e8031e9aac7b8f58d8f49897e920c36c0232f4a30aa6eed305deb0f7793c115b267 -b8b6a727c44c37a8388383e959d195d1d0e51a657d4ba360633d219d43c5df645383e2406c25f1d418e72b862c3a6e9b -92e64adf65b42c978f36dd03ab22ba983bfbb61944efccdb45b337ceb486beda99818bf20d32a545503c4572bb0a4983 -9653bb83df66260a0bd059cd4244ef7c661b089e403d26ba777d2090783ff31f963f5d3a9c125b1ad1a1d19134f3fc8d -a74e72355e71ae5eb36dc75191643500ca3e67f18833ee981010e7e7e60a68e1b01b05901eff05014b9ef29aa4829f45 -8b2139a5da14524cf6acc593144db23db424b95b8c7041d8f6c7a14a6725dda1cd09c42bb3ae26a5a3650affaa742800 -a60ddff4300ca44a7c7a00a1f98441ad1438e07c30275bc46551cee1b681926d2c825cc8f90399ee5f36bb9fbd07d3dd -a04e5e9958867a5acc15fdea0d88951cfebd37c657102f6ba1dcdaa5e46cf1c823ad0d98718e88e436f260b770599102 -95e977abeb70d46fe8d7584204770f14c856a77680607304ce58077550152733758e7a8b98b11b378540542b1175fecd -8c9ec93ed35a25ce00d61609e92d567459a45e39922ccd1c64ab512e292787125bd4164c00af4cf89fd3cf9deddcd8bb -819819ad0338250d9c89aceda9e217df12ac54e940c77fb8420575caa3fa78930689d0377ba88f16d38179a807135dc6 -8baafb379d4150ac382b14a64788d819146480d7a1dccd3deef6889686ded375900f5df069843ef14d754ad3d7540401 -ab827236996bb79b447714c6993af941c5ae66248df4d9a6f3650d44b853badb5c0cb67804210e07a7b9d66ca43092f6 -927656c3eac8d2eb575e3daeb77f9605771170c325bee6aeade10c083d42bd8dcbf3bcc3d929ea437001c7cf9a95e2da -af22b212d5ee44fd4197966b9690487c38a119cd6536cfb8c181f38a94610dd9e057f95774047a446504dd96dd11e326 -a44bd94b9e01e3ba36340f2ac2201ecb477495d4f1fb6726a6b439302deabb5a35d237c6a6aeb7e3b0a65649f8656716 -af367aeeae3bba14fbdb05bcc1a521000dd9d37f5c34ae56fb306d3dfda201d0329a8b6e89d98e15825cb3c6bfdb1194 -abcc4fbdea43e50ded9e2fb01464f4e87fb136e960141e8d39214f92794cfab5634f22cd40b18d8c0e501f2307aad23e -920786cbd674348b9853689915dfcab02cce2a4596d117962bce36aadddf4bdd143891e22f2c8015517039a64e8aede3 -8cde63b9bd57cb3ef743f1f3e8250669eed739e5fbd68c500a3cc0c12f93862a69aebcdbc69dd8f476c2eb307f572a53 -b967e65a5f1cd8d5d570f5e87e7e186fba51b9504f8e466392a76d8a971fb91fd9b7565bcc1647f50d7d15e48b93bc95 -8d5a87b25fedf5edd57d870304bfd9081dc78c3e3e3b38b997260a92edac7feccdaf24feb51822d2edc223b70bb4ed5f -b6cd5d340a57f8ec73723c4f3ecd6601620dc8137a3e75a5d3c578bc79a9cae86b379950c644dee2ff99dad780d025c1 -b6f0a8e754b7f52a85a2a2e6512cfd017f7fb0418d19bb318308951c4e242d3c65bbcb9748da9cbc91a738f9ca577332 -a89dcf7d410bccec385400dd96b1cc6af89026a431d0f531aa992cbd7bc8bfd7c5f360bcb665bda1d72efa17bb982551 -97788e7522427a46c4b6258d15623ef7a565712812fa80d001e1de8dc1791392702f3fa3cce5a8cd1c5755625a0ad10a -b5338fb5e137ff625b27c5148298f27ce8f493e2527c5d0facaa49f29cae34580d0d6c3c1074a2e46cd8db3f56004ea9 -8962f006d7b1095dd0dd132ffe7e87e328510c95ad893cf3b2ab21c177c5cf2c27f47d8856f87e9762c547be009d25c0 -87fee9ce9c26aa476e67e0791a809e0a06a8a98facf3faea730d438d3e516cdf75d645fa75c906e4e44ab9237a22c016 -b75ab972e1a1214bab0b38cc3e973d44bb233acda5b4291f5e110b6fb78fdcab93dc63f01168debd898e165f615be1f7 -b5a0fb52bca279d3853761a94b206acaf313df33ae6303d9b71edae90b66fc507adbc60fb11e758888736c81d5d80c0a -849b8f0005010e684701cd3a4e59e8c89e5fec59af6d2de5b6332cde03b865ea84f07f0b80ec3404380b0e148fbd2c24 -96e2b0b6fe78408f9208f809f5c40398100b2dac202c8c5c33c2189560dea868270a598c419871a5a2b67783354f6014 -b234b81f996142d0df2c719760bf996544820a03195a6dc0ff6a72543692f5a369bf63d1f0b477ef2fe7b3234e41f685 -b85e39bcf40da1a12a535740176f4de749a93824079deb5fdaa004f3282fdefaf5275e3418c88c419bd42a3dd2ed2b3b -a27279304b89a18a4e2b443246f2368fb8b15f46a34533179b6bd2ef683f6e98e222b7a32880b39b8fac1afa90133803 -8923c22cf15c9c1964213d725b337ece9ea854775a06f75f232c4859c7142a3942f418354e33066298aedfba3cb27e62 -b109f714311fb9bc431ef57911e2cad6a3949455b9f23255cd7edea35be629e07f845fe53e2b12a32305ee2f4f264f27 -b51e82ae5c7d48050e405897d0053e9ea4b2714d002e88f78c9a307cd50b9c6b3ee7cb86f86527be9d964b01895fab20 -90db256931c7f98bcf3bffff4d496739185e7a20f329ee7bffd4e0850a37739948ec745285703967f4ca50ec370cf68b -a0485ac0445d88dafac56bfba2563b020cfc370f54c1606c89d12cfd8a4d1336d2ba50306e476155a6f5b0e0a1f2d092 -a00754c3462e74bda928da855bbf90f9077db395e32f03cce9b2955546d900b72330d247b7d607b65e130f5b0d883de0 -8547d56727c3ad8b5c8ce622ed9ad86fe8cd78e6e4848c9845914b5063b17330bd10b46d8d3f18f83ca09ecb28d1afb2 -95b937b2a979bce0e159ac75c7d5d659be8599c92305e73e942aab414793364a3ec28c7c1c8491a5750ba84a29828d8d -b011e150f0294e45a0f4c69409999d0c2e602449dbd67ab95e8258466687cd733a0329083a31b03722f4e2580ddc95e9 -924651a733ad5e5d9adadad3ea6a6babb8e455c8d5f2cb5bdc83fa422e7752592190ccedaa827b866861e73506a6968e -a4d5180122f8e31503ae027e54da50f72f5cfb910a6f7309bd882b5cd666f454672591f1f20e461e182a47d03b47052a -ab19ae659c4f73ea3d21895269dbec583c7029955a36469124ebe295027010faab56c4a475973497f28e9a77c03b8fd0 -ae7ea1a803d0f439e91494f8f35fc1167dae23834c0c699ffe65d3da8b09f8df5a53195a99ca7b8558242279e69578fa -b9d63cf0e30f9800101b43b980bcd2f229758e74b21ad5354866b4e684791c08a184330dc316228a0d67fe0210f2bc4d -8c41629744391ddb96dcbbf9cd99b13d36e57d65962e0aeb92ebccf1c4cc769626feb3ec0363def08eceb102b3dd4ad6 -b2848ff24faf9e667a8c19d050a93896e9e75b86595f7b762c7c74ccdfb9db126ae094961fee7f5d1192776c1ac1a524 -af013bc29206743ce934d5887b8d0fb3667c89bda465d2321835a3618513fba6a459dd7566268220ffce7e0c97e22b2c -8bb799e36db1132da8e8b028ea8487dd3266b4628c56dfae4ea275f3c47c78e3d7445ab8d0aaee4cbf42148b3a148175 -ae2b81fd47c038b5195a52ab8431f0d3cab4cf24c4237252d955aad2156adc16dda9d3270157e0bfe5a44022e5c051ef -8e0129213b1698d2ec6df132356805a8633ba79e672e586dfef664ffccca71834253ba14f296da962651fcba2c002622 -a1ae30b500ae77cd9bbb803d737b4a5991cc780618ac22b5cc179efd8fe10afb8c135457f2e7b86ded485ea12eae70e5 -8a39723077b7c0df6e3bf6548afa3910c214ee275951fbe5155a39473be98099626ea14d844630a6fa90292b9594665d -a628386c79b61aa7314b01d9814aeec20c2a66e3deda322a39957e7135c2e52b1da486d1b9cd61c87afb22c1d10f6462 -97867f469b01249820aadd9a54e12d4fdadd4555f2d530450e1f8f6d2dae57360578e2c2c8ba41e3b5950df596537a98 -97f192d0457c217affa5a24267dd16cb4c01de8fefde9df4884e1906d2f22e73382dcee6c7d910bf6430bb03f4a4f1e1 -86d5b5739de8442dc74d0d8dc78e49210fe11bf8c6ff0f0faecbc47b64812d6b28c8afddf6d9c0212f1988451d6ccb1c -8ff3312ce9693cd4a9f4b8e75bd805f65b0790ee43fd9e075fe4cebc87185bdf161335049819f22530f54fed2779a5b9 -8dc41d85548bee5d51941d55752a500bde3c5a8f3b362da4eec307a963968e26605048a111c9166d448b8dddf6f53892 -996bdfd004b534151e309ac925fa5ee7801c9da4f6b4c43e156d1158b134535a2a3956e1255e0dd72ac2af6bddaebcaf -aead652704b788bf4983c8f725c644c327a6e9f6683215f5c826c09f82fd2e40631791f51d14e6aded91fdc018d45501 -991ffab58a82b98ed8fc7b00c3faca153589fe09cebf6a137ad506387a1ca4dba475b0e4a1b9bdad829f1422facaec39 -9652e6c4ae084221d6bad855ec0bc11b5f855c6efba67f644e0902ab790a98861cecc6ce047c68273c3aa7eeb2f4c7d9 -b88b816507aaeea6dc92b861eabdc96988b74d7883f20a4b30ba249158acaff3c50d261742fc9ad2e9eba888a8d59065 -acd028a51e16c07a10d2073b9d03070457ac5f1246365295a1359d015c460b92b4861125fabe6f114de8197045df408d -806d3cd9d02d41c49179fe7dac5b05dcfc9a205a283135d4f008d0771c58e6f963d7ad0f6798606edda718eb5c7ff3ed -b9b71f1657a6b206fc40159a941e127f252a7b324dea864ecd804f48c0ed86da9778a925fb65491204a92bc2a26fef32 -80ed67bd0e74350c875abedc0e07fd42ce7cb926f0f3fb1949c6ac73f2300b5a14a5c6f6ff8aed99d5ea5029bb8e7ae6 -9875f67a7a473714e4dd75ee0c763ddf88101532d9680724b3848fef69e218b04a96b90f88e0f4409aa40b9a21507ecc -b4a2bb1b421e5243e5e7576a0672dc19f9f70315a03f6411c19f76616ffbb70fc5dc0e57fd4ab85e24ea2261b7ce38ab -879723002ce43e6c75ba2246f51436efe3376242beff987d025c3c4476495af32d52a54fad5d9ec329a442b93bcff1ce -a4121efbefd9c3eb143619afa52a916f199c75024908047763b29466cdfc837c2fcc894aca63044c33c41c777e529b5b -895f637b497a9766714a3d9e3c275a1f0c9ddab105bf4c8b7e663f36cd79492022415bb4938c1a4849bda73106ace77c -b119acb8b161ce4384a924645a248a656a831af526cd337d97e08405415b9dd22060849c76b88a4785eb5e7214961759 -802e712f4c0a17009c4be6c1e5ba2ca3b82adcb68793ec81f4489b7985babd8a3873d544de63d5e5de0cb4dc5048c030 -ab111051e4651b910c68ecfdc33f2d99e7bf4182df68cedbdbbcac219a543e04d93ecb2763fe32b40c095c7ca193c331 -855c73ef6afc6bcaab4c1e6388519fd5cbb682f91995bebd558167715db454f38012291beccea8186a3fb7045c685b67 -a29d02ec6d9baf84c19dfd0eb378307703bfafc0744b73335550f3cd1b647275e70215f02d1f4ab82a5df4d4e12dd938 -91510a45b8a50cac982d2db8faf8318352418c3f1c59bc6bc95eab0089d5d3a3a215533c415380e50b7928b9d388ff89 -8286e7a2751ca4e23ea7a15851ad96d2cadf5b47f39f43165dde40d38ddb33f63a07bc00600c22e41d68a66fd8a0fa51 -a413d4e619b63799dd0f42ac57e99628d338b676d52aec2bb0d1bb39155ad9344b50cdfe1fe643ff041f1bc9e2cec833 -85524e5bb43ae58784d7e0966a664717289e541c8fcaff651541718d79a718f040a70aa8daf735f6635dabfc85c00663 -97f0d48a4028ff4266faf1c6997b6ad27404daa50ca4420c00b90f0b3e2d82ef8134d0a04108a74955e61e8dfeac082c -8df6145c6cc39034c2f7331d488b8a411931c8faa25d99c5432831292637fd983d4f6b1a6f55522b4a42a462d63c6845 -98c2060f67a916991b391e67fcf23e5f305112807fe95bdddb8ce6c4084126557e4c5f003afb32e30bc6808b30d4b526 -8964246b3c2b8f7312f0a99647c38ef41daf70d2b99b112412356e680185da6810ab8ee0855ad7409d334173bcc4438f -b56c2c416a7069c14bdb3f2e208c5a6ad5aac1cbe5b1faf99dc89c7141d0259d1c6250be9d9195500c4a41182ad2ec3d -b7864583a4cae3b1083dcdcff7f123d24a69920a57d6594d0b7219e31bf0e236682442b6499a1f6795cfeb4f5f236695 -a064f94139bf1b70d476bde97099631b1284aa6b4d87f16bfc65c075e58b2f1b3c2d057605259f806e545674a1169881 -80d1bc4acf14c0f487cd57c5d6157b7f38917e93cb660f1c25e474fcdcac3c3dfda50f6bcccfd6676bae25c4b6b5014e -8ad9a4976c4e3e282843518149fcf5d454240740f4b91466f6310b7216d23d70b9b47c42870293252f29f092f330967a -914197593d2d99d784c704cad7ecd3f0b9f55dce03fc928d13e1a1034566c4de754f1c2a5ade047b0956415fe40399ec -8d77f5e29c572ec3c0ca39cbae2072ba4102403265b3d8c347a00386da9c0b8688d6e3280c96037c300d57b3545f3773 -abfdf79d935fd4f06a04938d6580a8cbf9735f0d498f49677f26e73d3b34b7075d525afcb4f14ef1632cb375bef7dd55 -a97a8c446e3edc86efac7bda5e2e5d0158c909552a3bf86151df20ece63b8d18b608f477286fb1c7f05605ab7e6a7c2c -8618d946c7fd62486551c35486fa466bdfcdc63c941e4cff5a01fbbe566b7ea9dc763cbe73e2acae063060b619a212a9 -8d03ee468070936004b06acf64b868963f721f37faa09887f8a82c155ad5c5732572a6855b531db58af03b1afe034a18 -8d3247f75966ea63935ef6049f7c889c1651374adb446f49499fc9191dbcde7ea33cbc1f1e2d3d1756b6e69870404643 -afc853c3a3facb4ba0267512b8242327cd88007cef3bf549184ee891b5ddc8c27267bae7700758ad5bc32753ebf55dae -80df863eaea289de5a2101f2288046fdbfaa64f2cf1d6419a0e0eb8c93e3880d3a3fdf4940f7524ea1514eef77fb514e -8434b5888c2b51d12d57da6fb7392fff29393c2e3bfee8e3f9d395e23ddc016f10ebe3e3182d9584fddbd93a6effcefc -b78cbb4c9e80e3808c8f006dc3148a59a9cace55bcbb20dd27597557f931e5df7eb3efd18d880fe63466636701a8925e -acb140e44098414ae513b6ef38480e4f6180c6d5f9d1ca40ae7fbadb8b046829f79c97fe2cc663cbccd5ccf3994180c6 -936cb8dc959e1fc574f6bb31f28b756499532ebb79b2c97ff58b720d1cd50dc24b1c17d3beb853ba76cb8334106ce807 -adda2116d9fab2c214ec10c0b75f7f1d75e0dd01e9c3e295a0a126af0ea2c66373d977f0aefdda2e569c0a25f4921d0e -89a5cefb80c92dcad7653b1545f11701d6312aef392986835d048f39d5bc062cabc8a9501c5439c2b922efc5f04954d0 -b9acb52747ce7f759b9cdc781f54938968c7eeacb27c1a080474e59394a55ae1d5734caf22d80289d3392aab76441e89 -8564f72ce60f15a4225f1a223d757ebd19300e341fd9c1fe5a8ece8776c69c601938fa2d5c21b0935bd2bb593293272b -a5567d7b277c4ebf80e09c7e200c20d6cb27acbaa118c66ef71cbccb33ee3ddce0e0f57b77277ae1db9c66ed6e2d8f30 -b82e9c2d8df1cdd3b2417bf316d53e9f3cb58473c4cb5383f521ef53e0af961ef916e4f6557a6d8b4655ec01415231cd -aa816dfd2814c8a25bd2cbaf66303ee49784df471bac4b3188074ea30816f00f425234454d40d8ad8035aa925d74da36 -9919f384df20faaa2d226b521cab207dd2b62420d25ebbda28c9b2ca76a2a52203b2ad7844c1a25f5c75f005c5a83149 -b24a6aa35c2d0f87e36598b36224c64427cd69642b6f9c1bd478a62c70f8ee69f85028648f6603b4f04fb21355f2afb1 -892e044bdb1276b455eac2204be105e1821f987c2570494b1f32aa09506caba7ed343cd09b1bc126fed5e0fda3d0eaad -af0e01a3ad954dc048de18bc46bb1c4971db2467e839698e4dd05cd1adcb9261013fe9fd0cafb946c0b586f6aad86d4e -ac152f0a9ace425378daf02510eb7923ff1ed2c0f8d1deb918e4efb63655de1ba58c96438e9aa23abdf2431dc771370d -ad8c7419c097709347e2394195924e09617b47ac5c7a84aeb9deab8975f22155de0f70cf20d8a976551b14e3a2683a2b -808f14f67ae801536fb70a5898ab86e50ad35340cffd0648daed2f2c4564c9ad538034b2a179a6a8bfa27e9d93b4cbe0 -80a74ab7ce4769db93cfa695a166db95f0a9c47885ff826ad5d93310f36d6b18b5351c67c858b9837b925e85a1995b63 -95b88c3cdd64401c345828f4e4754b1a88b4875a14c08a668b90acd499b3b858842669ecd73a46c5d9f1de32ec1a0120 -8ddbd770b7b18a5917eb43926fa05004e819f1d1ead05b915269e4a86b53e0633a90559007e59f6705a3769e2126ac56 -ab6db5fc220754f19948bef98844e6e38dd623565d1695e1198040c228ac4fd863c1f168cac1d036bbfb718d9d8dd036 -97bef628e977c069e60c395a17740e0e1bc1828f5607ae7f30ce5a0c95f02b53af2ad062700a75212e462aa22c3c5465 -b68d465e04fd17ca98501e61eccb0ce30401855e98046e0c1debba71c2153d6a7a704aa36a6f12454696e78e87181cdc -a79cfdd048f4181e005bd0fbac0a8424495474956b58ce858d2b700fb0f931c406282bd33bfa25c8991bc528d12a69c1 -843f55fa0a6a0969daf2b48080738f30b269b2e7ec123a799e5b203c0b3b4b956dc95d095bc6550b0013918cdff8a225 -b683cdf2823036827e5b454bfe04af9bec1850d25a7a7a44aee7696b6ff0468b7ed6885a41dde2b8f3ecc4aec880c3d2 -8b500796e82acdc89778e0c0f230f744fb05f762000fee877bcf57e8fb703d212dbc2374887bdc2e7b7a273d83a85798 -ac35a8ee87bafecb1a87f15abc7ccf4109aab4ac91d357821e417f9b1474d196c38cc41cd13667f68d1ffab5e79a6e92 -b6e517739390cfed5b395d33b14bce7cd7aaece57fe79a7eb3cbf150dc10765c3ea9fef7976a21a2243687e6eea38ef6 -b53901eeee26692273365b789f2a60afc9b5f0df229c6d21b07016cf4c0e7985beec748aeca52262f68084393ab038e1 -ac4804f33d8ba2b4854ca3537bd8bf2dda72d4e94ff7ecaaf9bd3b7f098343d74d765471ef80072ae34f860b052cbfb1 -8c6a30a93f1dde18039bbdd1ef294552bf79856e20bce863e4b8dd72d906be3ff22468ff3610e06b5a7d1745dde7ead9 -88f0607fa3b7cefe20a02115572b16fc3222be86bb19e592c86c48afbe7e0dd523492b0c29a3bceb9a20f5538bc3134c -a660b801bbddad725975ddf9a8f606f76ecef831f954be224d6178c368e1c72d346f00c4a4c95c289b62d36f2af323cf -a75b9a6aea9542b698938dcd6cc2f6fe0c43e29f64b2f54aeb05d35fac73d41aa7fd750af4fa9333644aab8db90775b9 -83e1b7129d963d1cd076c3baa5fe422148e939273db173e4d59d1858a7d841eacac7fe817d15ab8f8a493bf46c2045e6 -9060a2e9c24de11f9c70e039b5ffe9e6d32f1ae39f3dda263610df2265d917679e689898e4a8bd84ad34613dca5e3761 -b42fc8b863a2af15e04d1fe6693c09b46007c0b8298973fb4762b45b4590ad7fe0aa758918b2fe5ed1ed0359754fd955 -83e6de7860fb256ecf7b47506a5e557d0fb0aefe57fb513c7dee2bd9604712d08ca26adca7ba9a54b712372a7c585a26 -90586e9cbbf71475ecd3e7b5753b286804dcce61e165502a82b960099e79272de8b7494b8877b54ae838eb5d0f71af2f -b2e4b0d21208f73b7b75e08df80cde20c4578e117d37092a490af82354e2afd3a7dbab46fa2d12fcb731cdaece69c2ba -a010961239bb8809fc7fb4aa08fa30d33a130f9f417ee9ea60f587dcc5ef4e1b7abcdcbf8e848ecdcb7972ef6af46e78 -8f511fd58d1e3403a5eefdc0a4ba6b8af848c7efddbf9575ee84449facde05ae9a24aa41a5725416467f6fbd11369c52 -b24ebbd2d4482eb618cea1ac4fbfd9ed8c46c0988a27259300a7ce5ce1bb256aeca0357828cbbc4cf0dfafbf586040e1 -b3ea29e9cca55250e9b7b9bd854edae40f0f0cc65fe478cd468795d1288cc20d7b34ced33bd1356f1f54a4291faa877d -8a8b20f222d9e65bbde33638033972e7d44c6a310b92a9d9c5273b324c4ad1a94f2a10cbce8300c34dbd9beb618c877d -b2436a9a647dc3f12c550e4ddc5b010e6f9cb3f3504742d377384b625fc38f5b71710a49fb73ffaf95b9856047c98201 -a13f8b77c70621e421be94c7412454adc1937b9e09845c2853ef72cdbe500e5c1bf08e3c8b8d6b8eff4bce5b8dec9213 -b25de8780c80d779e6c2e3c4e839a5a107d55b9cccc3ad7c575f9fe37ef44b35db4c1b58f6114a5f2f9ca11e1eb9c5fa -96ba6ad4358c7a645e5edb07d23836cbd35c47d9a66937d09486570e68da3c8f72a578bd2e14188d3acc17e563a652d7 -a7f55989814051fda73f83b5f1a3d5385cd31dc34baf94b37c208b3eaca008ff696fd7f41e2ecffc2dd586de905bf613 -882d0c7c81e58eb9560349f35c35e4498dcde7af7be8d7974b79d262304c26ab67ffa5ed287bb193d5f0ab46b4096015 -a607158f0c1fd0377a8ee5e9715ac230abf97406c19b233d22f5911ebe716967cc10425546dc44e40c38bd6c2b4bca2e -87e8cde50e5d852d3f073a43d652f7186bac7354612517cfaecd4a1b942f06fef6f14546279c0dc0262e2997b835b2a4 -a1c93acc6db9d5ee426fb4a0b846bb7a7b8d5915bec777a9fe6907246b0beafb8938941c8c79ed6082155f75dbc1e332 -b1e4f61457b86f76cd93eafd7536f72baf239ce5a62bd5a8085a34e90576b1e118e25002d2de49b01d6e9a245ee7d3a2 -a0435fe9a4bd1031ec5973a103ec9396b2ce9fd982f6d9ed780fa80ac06a6e47a0a6eb2daf52df1dc9292db622ee9fa3 -b66d8e8a1717e4bfa42083b6ef4490e090a73168b2912f2111743e089027be0a4945a229ecf5d0b5eec11b23f0e11303 -8eb764f26904eea4f4169be6e75beaa6a39e4eb524625a15a78befe3d8e3cc82692d9b135590c20ed460d6e4ba630ef7 -b7e4aea6bb09829e53fe83e53f49a7a331a6d7bf76e0073d758577e6d6fbe63dab642b23657355cad48896ad8715119c -8f94207982373a99ffa282673f192aa98d0c4461fb77c31dc4549628bd9687a249f1b3c66b1840929341e42516c5c64a -a9c673cb247b13e17fa5e616f0399b7f5c7ad043e143e44ae68855a840870ab3d2aad737ebcf74c2cc9688d17ef3a794 -b02635104dd28c02068985256975c0af783899eb996e37d021d9a35238deeea9e836760db21869be7b6c82aa687ded29 -b33bc0966389710812b5f6698afa3e9c84839a1b85492ba11e6ded26695260abf66be6fb355d12d3a8524966f0f89e0f -a79c0dd09506951c33da3cbc23843fd02d641fc24c640a205e6e8150240372847312b9381fb03c5d301fe4dbee8d0da2 -b74de6f3a2c502b5b658ebe8a9b7edd78afd036f5a2736aa06502863b6865d131b9e3542e72a86fa2e1d2db4927661ed -99e365def1452ff9fb4b9eccd36ff4154d128469ba5bd73e83ae457ab53977cf6fc04a5d05bdcde357ab539e34bd9fe0 -b4f2bfb95abb47c67870aa6ca38ac8f3ae1b1a2bed064b1be7ff90865ea12e4930fcf66429c7ecd1183fae4a01539386 -ae4bde87f36b912e92398bf72e11d5389e93b2de1b277d7ed4b6fb5a9ab9f71a959ec3bcb734c11079440fe42b86fafd -b826459e568efdeeb66688482b67ef5020787275123fd3192f979b6175e3b0ed59e17cb734a0a052bf13f0afc7bd237c -a99dd735f4a7c85cb23dcc7f4835f9ab32026886909aaa95876b98029c37dc4d621726c872d3a9e50403443c958f4029 -99083545034768010988bf8a9f34486c2cd9da27a1d10db3ab86eb69a1dd9c8ee723e7da4ef2aced63c1dbd53ccc52cb -8ac3209349f0142546c714ef7e9d1b094aab5469b8f080c0a37cb0362da5349e108760f272fbba770aa468e48d9a34c4 -af5f48ed74b21e3f2c1430192adb4b804dc873cd7e8f07130c556c30e7b78df0ef5a14b205368848fa9185e5a68dee0d -b8b741b65d68df89443523ba74203226f1e0d13bab073d183662d124e83e76cd318b2bfff09879c04d81b577ac895638 -914abe4282d11176d4f2f08c6f15e6c2d0cde1ab4de00bbe888015c205f51929d97296a0a8d3ca5641f085a29ea89505 -83ec306b2a9a6780efafe799df90b1aebdbff7d47921a136ea8a5648b9708a97231245a1082fea38e47ecafbbe000528 -95d6b58d70b388dfcee4eda0c9805362ccfb60a87603add565b175b2c14ed92999dfdb0d3724ee3e5d30535f282641e9 -97eeb4de607c8306e1d4e494f0d5db126d53fd04983ab5674ec5996b971899e734fa4011f2c889da21154ea1e76dbd2f -84ff21977fbd873ea06bec444d4ec9ff0e3902edc29dfa25f3bed269b3709e3116e99dc06cc3e77f53c53b736bf8fc29 -8ecf483874a040a4a1c293af145094fedf203a5eb37c3e165857e108cce3e1210e0bfc0f26f4ae5e2194024929ba034d -97d9b92b2ef34609d69402167f81bce225ed3a95718a3b403f702b93e96a121a8f7f072d0ff47e8b25164e204d1576bf -ab87c39cca1803b4e84b32e40ff30289e3cbbcfbe16a70f9e025643824752359be1f10c3e5398df402b6fec64d5a3537 -af84ca57e6944332884b5c84750afe0d5950015e127acec161853d55d48fd864c7da8d59cc5aba4ceceac650b813fcc0 -b1d23d98edbe7089ce0a8432e0eb3b427c350fb4bb39eb2aca3c2bef68c432078cb9b4b2c4966255e00e734fa616638b -8e2b5252e0ea96d40835ebfb5693af49946509975682d68651396d6bb1463f09e75fd0afa04ccea49893b5b9c3e77e40 -8db25e762f1d4a89a9a1cbc61c01698e775906bc88a921b2905735457a35df9ab84bae12e1b1b8dafadd50212f1acda1 -b5f7cd163a801770a4034e2b837e00191b0ac63a2b91032ae9a99ec182d748798df48a14644935fabdbac9a43a26749a -998e7232e5906843d6272d4e04f3f00ca41a57e6dcc393c68b5b5899e6d3f23001913a24383ed00955d5ec823dbd3844 -ab2110a5174ae55ebb0a788f753597bd060ee8d6beafc5f7ce25046ea036dba939d67104bba91103d7838b50e36703d1 -a211972a4f6a0303bec6c86f5c23c0d25ab4df0ba25876cbaad66ae010b5a00aa0c5daded85e4326261a17a563508a25 -a49f53496a4041a01e07f2c2cf1e84e2ee726917bb103fd267451b9b7bb1331c0afde85a79a55409bfde27328b2a4745 -934e915c67c7fc47adeabdde49f63f04644fe234672003be2aa0a2454dc8d9288f94293478936a450f2e3f249d395b5b -b6e69e9d6808ff7f60a01b7aea6781495d7a20f5b547852d3f0af727a7434209d3015a9dd04cbe3e272918e32e345508 -b348d3462092b5c6fead7e515e09611438db8d69650876dd3b56226e303252bbeb9e9f3b888fb911445b0c87132a1d0e -8d6510334a905efe5a32001e167f1ba06f9bc4af7ffbf11b7f7bf3c0076b5cca373d8c47e98c1ba8755bb22632bfe0e7 -a2d5200f20985dcd473d119ee97e1c0fafafa0f191185bfed9cac429cef8198d17665dac4f70342eea66e6e4a7370d58 -8dd7eb6b1841b3f33425a158d33a172b79b2dc8a01378e4174e67a1a4c8f4b887f02c7c3a8f354ed9eac718155bcdf37 -b16ca19388642f71afcd9f7007b490d82f83210ac1a989da9d4bf4c419de07af8c048cd301ec7e01b9d06abda7c169d5 -93cb2d847d1a88de8c1c9d5b3c83efd0b7afb3682942bd2c8ab5ef35b33dc31a097a3e181daab8630d4e840b677216dc -a8b648c769e77a7b41c0c689fe2fba9bc585067e004bcb1732cb7b1618e97b317781c36c23a00680fc780b58c301a789 -918c321100d57712866bdae84edf7e42df30a32853af257e0cb4da028842a43b49e775f3cecb85cd817269c728de7319 -a7b0f6ce42e00c519e69b2c78fd9b75a2e7103e5892d3c1afd70c9b5b9e706180a4bf73dbb2d3eed52bfd521103ec5b3 -90041994af3322b010891356afd8115340bd7fd7ba328716fbc4fe458236c8cad8c7564ae473d6091ec3a54bdab524c0 -acb1ac83809573846231f9be2dc5f3e986cc36dd9574a620b1cced45bad0b11ea957ce8c6cbf964a0af916781c574f05 -ac54677dc002698fc4d454c7beb862ad085d0514f92576f3485a44c0cb47afb9db2c085058918a3508f9b3de0137d97c -8dea56e1bfa150e442f8484b2952b116781d08cfa3072d08657cc09b0217276efc4ab6f5fd726bfd826f6976ced8da29 -a2b09e25baf01d4364b5205fa0c4dea84ef8fe03709113b034f88a0f0a502a81bf92c1d4641e2ac9f3a6f4203d3645ee -b95fe37aa351b4292691a9c2e547224c37ec2751a31ecce59810cb2ae0993da6fbe5efe0ab82f164462fa3764b6eb20f -a3498947e91a3a540e86940be664fc82f1e83ff41a0d95eb84b925e820602a41b7393c8b458bd4ebbe574a754586787a -aa2516d3620c832e5728fefdb1af0be30c871cbad4b166a7a4565af676e73bddc2f2f51acc603b3a022056daad2b330e -a9251b56467fb55f64c70729e2ec77a59d7eac79cc0b4b25ee405ac02aea46bf1cbc858bc773934a6d9bea57cb528185 -ae8c0a4ca7ba6bdca8764bac98df0581f00358db904e57867e6ffdf15542e55f7bad2dedac152ef88038b466ed901934 -b0881e27e52cc6a57c4f3f278dffc7f63a9174b68bc867c16d8a151d9cc4d0aeb703d1074d1927faa9ffb43e10912c9a -b67138465d6654ded486d18e682f11a238d6a65d90f23d6b13eb6a1b7471efbac9ada6345dfb13e5432196d2a256829a -944c69a6f1126edd38f6eef60b8a5bd17147ab511e44e8e0a442e87244d8f35236ee0b8d3dac0631f8598f16486a5f74 -995679dbe03dec775da26708cb9200dabcad983825f1ba601eb9395f9da350ca71e8af61dbff4c668fd0eebac7e4e356 -89de362f02dc14de6995d43cdea3c854a0986c605ba5eb5dacf24e3a85983229bc99a2fcf50aba3df59f0fb20daffe29 -84607f0e2d078df22d0866285614f5d78cf7697c94a7d1b5e02b770101ceecbfd53806b377b124a7320d9fed65000b97 -93e3faab60050dac76ab44a29bcd521813e76ec8e4ae22712d77bb489bb49f98f9087acfd6a77016a09a42ddedab2d73 -b7d64a7a35f21747b8e6a874be31ba770c0d13cbd41448411994e8cebb59591295a26bacbf74ee91e248a5b111aacca0 -8dcad429a2b0d66b9eb8c1c3924d7a72979727db6a535526a3518bed2a9532d12aad1c5a778824ca4cb98e3e513f85f8 -980882895faa347bd2fd1dda7b8ee7ed49e69843afe646f677b371eecc7a10e0f4e40bb55f28995a40080df471876816 -89e8e7fb51df79971e2f7bf65783614abbb0d7f3f1b4a15d3f0d160deafa7ed1c446d9a5ae1a77160d4dd94ceed8af13 -93fda8d350392e9c4d4ffe6534f7e7be53f32483d9319093e8436fbb8166a3c01085dc858373e65c7f4d014e0dc2bab7 -897521a87b7ebf7152de5260c0875e3c7df1c53e734c672569219ee6f9bd196c5ecef159b6a1d3b7cd95e91b9b8803ff -b59affa408a0f7bd7930fa3b88750fd043ce672c10a3adeba95a12f23f0dda1793f761a86f7409ce1e6fd3b3b7195381 -b4422ccc12f4fe99c530cda610053af9ffe635b633d52492fd81271d1f6f91b87171d572d5bd0e46ff63e221fb2fc4a5 -a4542cdf3346ee0867c08d630c2aefc57442f1c05c0eba52d223bfdca5e9d0bb80775cff6ce2e28aa2730231fd7b1bb1 -a7d297bb09118b914d286e5d1e87bdf13f7d174b988e38fb5427902e8e8c674072f36b19055a1070abcf357f8668f35b -9213b0ae24b7cb43ae95e25c09fead8bdbac55141694137d67eb5eab5e90a348a13d4d4d2cbc6436fc4f4f9f7334ced2 -8aed71a0d116d832a372b42a0bb92a1980f3edf8189bdbaed7cde89fc0418b3ab21a04f5c6e1d3b8edf73f1f62bd6b15 -a6c47d77d714c285c84c6b9458cbec5e3b191c0502dffd10ce049cf1ea27ddf868ef0cff13a2377289fa6c932b8e4f28 -92f45622ec02483f2c1e07075a6695416d3768c8984856f284f40734346d56cb5b3322f20c2c9f0ef8e58ddc294a309a -af6450d02b79ac9fc79f35655b58fd3619cd5d38c5317564b453f5f2d79d7a030bf767e399fe01b658a72fbd2cac2356 -a3c01fed5240eb8a61ffa8ff4a120dbcebb53b8e19845949c77fb4f9b2c3dd52c7001df6219ad2f76c785a4ee0f64a2a -af3136bfe8f774187bdf87555a1ac505322a956229a285d28bab1c88d4f4d12245af8dff35914a62e90e49f3dce6acb0 -b20e21d28444fc96737958cd951858fda324b924b4d3d08932540fd4b87150f053db6985b96903906ce83dde0578cbb2 -b7978101071268d1f485134b4dfd1e35f89b82c7d99ae91f58b6745f5e0273b7e06f3b23009033ecc3e41b2e9e85219b -9104b7d75245b784187175912cc0ad869e12f1983b98e052710fb33663224362bffd69ceed43e7d4ad7f998c0a699eb7 -a7624cd71b92699ce3fde0e747976ee04ee820032ac45dd27d769edf3b3379a4b8db358e50c9d057c63b5a9b13d76bcd -9354a76f294005de8c59db10e638ae6e8c6d6b86a699d8da93143da8478d36116211c788d8285d8e01ea6647dfcaa1aa -b85935c04cae14af9848db5339ab6420122c041075ec1549314e3c9c5a610d9b794ea3617c50ca7af6b4aec8b06bc7dd -ad6835a62311c84b30ce90e86c91c0f31c4a44bf0a1db65bf331b7cf530cca0488efaac009ab9ed14c1d487da9e88feb -80339f0245cc37a42bd14cd58d2a8d50c554364d3a8485d0520ea6d2c83db3597bf51a858b10c838bfc8b6bc35619638 -b370420ac1a011f6d8f930511b788708ccf2fe23ca7b775b65faa5f5a15c112a4667ed6496ae452baf2204e9ce0dbf09 -8ceab3dadca807a1c8de58ac5788313419c37bc89603692c7a4d96e2311b7fe9e813cc691a7e25a242828cdf98f8bbcd -ac1526ebc6bd4ac92ee1b239f915e494d0279fbd065e4cab1f1b8a1663f67daa89560f6c99bbc3e63fa845520316d2e6 -8240ab0bc36a29d43ec3059c7e6355ff39567e135f93b243145d3ada97fd1c970743819e0d58bd5171967daec144e7a1 -a99743192a6f1967511b2d3038cc73edacb7e85f84b2926d8880d932d2fa12f5215592311a7548494b68a87ec70c93eb -8ffffc31c235997e59ab33c2f79f468399eb52b776fd7968f37a73e41949111957434f2c0a27645ab34c741eb627cd1f -8949d955309415d6d2cf6ee682ccd0427565142c1bfe43b17c38de05cd7185c48549a35b67665a0380f51aef10b62a8e -9614f727a9dac8ecd22b5b81b6e14d34f516db23a1a7d81771ddaa11f516ed04d4e78b78fda5dc9c276a55372f44c4d4 -aa85d3ef157407bd8aa74032f66bc375fddaff90c612470b5ff5d93659f8c3523b2d1b6937b3cc4201c2aa339621180e -86f8fe8bf4c262dc6a04620a848e3844f5e39a2e1700c960f20ee66d4a559a90141ef4e5091d0f32acb1e915af1e0472 -b3af2eb785b00588371beb3b49536b7919a3f2175d4817de5dcbf7fcc20c512852ef0f313327fd0589b10173f77b92e0 -8388703c512eea59190351f3bd2cce83ff8bcb3c5aefc114cccf9e9b3f78200d8034c3ebe60448aaf6c912f0ff8f0cc4 -95d0dbbbf08ec1ed3975fe7dd542be0a05156a2b3db5092825d918a849411ee536ed958201f74a5513e9743674d6658d -8d1a48802f1a2db247e633ddf61d3ef7a2c062c48dda59bf858916e04f56651a7d51e367d6535964ebf3ae6d2b21b421 -971436871bfe868f25247145a55802945409b3150008535b372c949760d7949dd2fdb40d9b96ae7473bc8f6e9b83ecdb -8ca431728ac0f156763090828a7b6d860bf591e5b9dd3bb3b7f3ba0ca74191f9710ee55efd32db7d18eab5b479cee8a4 -81e28f1a506e84c2b9aba1df720cb50e0b597b2c22f98acc34e710c934cc6f97dcaf33d589e845c2c1f6d8716d05ccac -8f43b11d3f00c41d16c9bc9bc0c44227c056bd77de4f1ca9a799418c5601e744f99066bef47da2d9088ae88eb259327c -8d330aa52744c08ef98cc5599eec8b9b4dd18aa01b803f1d1ca0e29b74f1aa2886ed0224390fc377af25852851fbee03 -a06f5b203b67134c685039ec2bdbcc787353e2575ce73a415db24a517c0c31b59d1de89f12b97cbef0219fb6a1e90a20 -9269a5f49bbb8fec1a387b5d105df88a027de615d5ca6afae20fe89b11746f8d23880db78dac238c955fc8bb3de18046 -af5074b3bc0656421c314547b45b5abd3045ca1b17f5e34ba39d8c1f7928a55d4ca5ea9c2ab59a55909b25255233e04e -8e7ee5d733c8e08f3fb7d85f0628de3de6835121672c65374905dc6d19e02fa2df14c13d5e9835dacd609a4df09abd26 -a9b9aaf83d31e879dfb8e73a0708801b4dbdb5d7c8654b27d2c0f5797ebcacc8d00a82143e2060f0917c9d41f1a03de6 -904872aa1c093cb00e1c8e369a3bdae6931c5b1ed705dd3bffba243dc4f42df3e7d7cf70303d513b34d2245743d765cf -8a4d6b3b1d6afe67383c66693f70b397e510be28e3d97dbc8ec543d699b6cbb0e72eb90a7f65e83cf9f7ef50fb18b128 -a914de13916e6a0dc0e0fefecb3a443cca80d83276513b70c22c6e566a2d41acbd33a0e2836ee09abeffd3a4894e437e -b9c408f5f05934b0aefab301ba22f8254c5ebbf5405b6aa788f76e4b328c150b395f441e3566015a0deb3eca89afe9ff -8d32aa2c81b2a8b89f347c2e0b6567b2117ddbb778fda8a3f19004b7f5aa9dd814b9b3ad35f9223715d2447b2d12f159 -8230e8b9c84cada1bf14ea6aa9ecdadd978d893cf5962fee6c7167ed21239210ea491987f2c8f2e8cfea8c140704ca28 -a5d7b6285fea51c6f21d0976a7c3a97baa3d733a201bfaac0994db6c65611d91c5fc0ebc2a7724ee02b371e575573649 -a54f00a9530f6930069f5e3a8b8b1d52ee1def0aad1763e3c609ec07f25410969b43d5943a94c235ed5eb207b33a402e -a8dc6e96399b81397734c61c3a8154e55a670fa25fa5854b3c66734cbb4ec0d8f6ba650ee3c71da3773ffc9e37abf8bd -8841fbfae1af4d400d49f74495f864804f043416c09c64705251d021b3ab7881f134a00b0241e61010617d04979d747d -95acea7ff4861cc969c1d8cc8775c5eae014ad6e2e0e2d0a911dd916c34ae69f53eef779cc24ff1eac18c2b478d3ba2b -a5dce74abcfb8c68031b47364bd9baf71a91db01e45514ab6216f5eb582ef8fe9b06aaa02f17be8b93392d9b19ab9c06 -89e111169e4ae2f4016c07c574a3bdacd8d2f359561fbbdaa3474de9bc24ef8936784dfe6fe0e29a13cac85a3e622b61 -a4c511af6bdf3892939aab651828259e4ef6ebecfdd503ecc14e61001575b313a89e209cb55a77ec19a64d29ada066ef -923c62156fbf3a44926ffb5dc71f7cef602dbe941a98c61f019a27a18a50c16b6135b6099fe04a2e1dc88a6cad989fb7 -afb9191c541b61afa0ef14652e563cc5a557842ce2afea13e21507dde0ebbe6da5233af949c998c00865c79bb3d45ec8 -8a1f0ad65cb2b225931f41dc53547d756111ecbf5bc57c5ee2cc1ffd61b126d0389d311ffe26cf06eaead95af09c5ca3 -9040b20b5ac2e1a9d30abf7a4eea1ec2db8f3077cb2cfc8736b37222d8d3937f5d9f421167086dc5551e9f0bd2522d07 -b6d888b8c6bd448dccaf99c3f690d47f802e134709ce102fb6f6fc68156943c0762be6f386338163e01eed2d1dd5f734 -b94f0e27bbcda793e4a272603b3dcc739d3bf3207798df7319f8dc9d37cbd850e3724bdd30498c929debad971950223c -9769827767be9d7bacba1b687289e0794c6fe630d33c9b607da1f6a65e3f34cb8bd65327d9287c8c5f3c8b5f6d3d133e -aaac72c993aa2356c9a6a030950441de42b2d746bace29865382f0ef54835bc96958b2f00237d805ee6a69ca82117c1b -a2b1f027d80c1b0e79bfc7dd252e095b436fba23a97a1b2b16cdd39fd39a49e06a1ca9a1345c4dbb3d601ffa99f42bdc -b3fa0ad1478ca571e8aa230921f95d81aed7eca00275a51b33aadabd5cb9c530030691d1242a6ff24e2d4cfd72a47203 -a43ed4368e78daad51b9bf1a685b1e1bfe05bed7340d4a00df718133f686690c99198b60031513328fc353c6825a5f2f -965e145711ecf998b01a18843cbb8db6b91ff46f668229281d4ca52236c4d40804ebc54276e9c168d2a2bfc299bcf397 -ae18e6efc6f54c1d9230210ac859c2f19180f31d2e37a94da2983a4264dbb58ad328ab3cbc6884ce4637c8c2390f7fc1 -83a9200486d4d85f5671643b6daf3d0290b2e41520fb7ea7030e7e342d7789023da6a293a3984308b27eb55f879ad99d -b925fb6ca83479355a44abbcdf182bfac8a3c7cce6cfc7962be277ce34460eb837c561257569be3cb28023208dea80dd -9583dd991b62ae4bd5f379ccd3cec72cfae1c08137ddfbacc659a9641e7d5a82083de60005f74fc807bd2acd218d0789 -ae73bc32e9ff5926e1e06c07a3963080881b976c9875777f8e4cf96af91bf41bdbed4bd77e91253b8ec3c15b4a6d3977 -b2a3ea90aa398717ba7d8c46743e4c487b63c5abb140555d8d20e5115df2f70d3c84a2cb9a5e0536b2d93d24f271b38d -91d119d3bf1d34cd839eb69c6de998b78482ab66bc93fa97e31fb9592f36cdfcd673f52366f8c8e8877e313b92d4a2ad -a1907e20120902cf68912cc3046f8806cabbd7673e80218814cb088e080dd93b5dccba395b13e0025f5755c183276c3a -b2e2011df72504065ec4c12cbc2137b95cfcd1355509671feb7b00dbf7f8d500476a49754cb7fb9219cb5cba7c8afe01 -a48589fb7a74a3dfd782cb3503e6294a81dbb6adb412887569f9408e9079371edbd9822388e0b7ec8d3297ba270f53ef -a203909bfe196ac65ed3e6800d577b6ca5c8fe1d40f7f925a43852951e38883f2ffd250a9e16fab3ed3dc1249650247b -997ac293722a8b98f7e819f8e6c2d4c5bd1103b82d489d8b8aabeb905e95450b9b75bd61442cf68cc957212ec1c55617 -9895a3de62395c33509b153b7820bd94fd2b011f0cac135fcf916482f1eda272ecc79f83a61837e99c3a3c4ab2c5c2a2 -98c2ece4d49a64ec8e06407a0585081003bcef88af35210e22eab91169f8f0c044d611494b755e5bd915804b1d857747 -8bc6dd083b36d076ddf0e0bb1bb87cfd059283ddabb3886f02eb7e27f1f0539b2819527b56b5c13436523c4603ac1d12 -85ab8b7a696333c82dd5e179e12b2e127e67d911de609ff9a03cab95cbeedb1f364aa1f2b5e59353e4ba0d177f996151 -a9478e214afa68c395aa2c7daf8ba1627feb71ad6d8bc7339734cdcdd5a42838e032736c28e6251c808d5a4875ef0d06 -8c53f62cf06a35321c8af3871ee4459768d0745ebf48942b9f464206309f42fc7b2c50f196ae1e43b664f0e2e718a23a -8ba80662f6642d8866e832ec8082a4204ebc993fc304c4b794666856de0407620131a18dc053597bb40a3de0bf8aca22 -8c8fac6b911785d1561a985580c03fb2ebc613ae33e486a92638aa7d4493374118d9a6d9d99121e29c68c3d67ee4e3f3 -90f2c793eee07ad90157040b30558bb3b0164e8ddf856389d6742cf5bd1c712e4c6a8e5678da70a8e9e242ec7864117e -954abed8f6d58896b7f6438c9780236c1c83b02d60a29fa7361559e619e5bc9d67b3646ee39ffafe2b3019bb3357fb50 -b79874f757a33085e1e751544de8fe3afbea92e0234f9c00254c2b36115a16ee46f085f22aa66e0c9177e5106f51b03b -aa148b287cf4f60c64f774282b421aae075f0eaa93a45aab4927750f47e2ef0b811d1846bbb15eeb2f293c80a7612e83 -a588d8825e7b0168d45499dcff6faf0dfe1ba4f090fdc7c06d50344960c0121f10ad109b0b9d13b06ef22de5a04eef87 -8f61ec93d14ebfa9c31731f9ef0fb8907505fedc79378e9a3f65c27bed4d74b41e129c97672ce5f567d897befbceec8c -a008218633f1da10efd01c155f7ed739faec902da6dc48e9f19ccbc8d32bb318d71806285cf2003de2c907bbdd4f8b22 -88ad82c66f7085632d7e348d69da84200c53594553acf5432b50dd1e87f410c802dfea91be3cf804e3117ce13103f23e -8498dba17de0318af227a3f9ed86df37a5c33f9a538be9823f8dce4efc3579e8296cb3b7200cee7c5e0bfd9da23a4b69 -b3c0342231dffe4c9bc7d9265597bc8cc4a82e2980ac6d1407108db5b00349dc91d5116fab51cf2802d58f05f653861d -b3f2730455f9bf5a058598bc60f47740117ba51f6a767e1134516a4e42338b513f377027acf8825da5c4d047a62984fd -816360914fbc9d8b865157bfab07aeb7b90bb5a7c5cd64847b1c3184a52266cd3f8f8f3ef99309ba2edc4622304bacc0 -8fd21b2315b44a52d60b39ebc45970a47b9495f42b88217ae057bebcd3ea0e2476c0c3d13de7f72016ae12ae966a008d -b62014485bc217a0fe892ef1aef0e59604ad5a868face7a93f77a70ba3d7413443fbe7a44552a784d8eae1acb1d1c52b -a905822507e431b35f56724f6c8d2e93b0607ed7a4533073a99cce2b7c1c35367382447073a53036dfdb0d04978ccf2a -81672e39c2b31845142963351de3d9cd04c67c806fdfe77467867463dbbd8a9b0e2400ccc55016e57cbedb02d83a0544 -90919c970ec668de8ec48a2a73bb75cb94f0f8380c79a7909fd8084df61ecd631476ddd474b27103c6817c8f3f260db9 -8fbe37dfb04bf1d3029f8070fd988fc5e4b585e61eab6a8b66caf0ffef979d3ed6a662cd99468ce98ec802e985da5fad -950939aabb90b57a3d667f9820880eb0c4fee5c27fe211ce8ecd34663c21b5543c810b3676111d079ac98644c75ee0ae -b06201ec3c3cfdaf864a66af128effee8ec42d25f1e173c1edf9207979fa52c871757000c591d71a9b6cde40f5001a06 -a79054e8febd0450c96ac7a5fd6bf419c4b17a5926f3bc23a8616f0cfbc2849d97470174cd1baa7c739b12615334b6b7 -81c7391b2a1844ed26a84f054b5f03865b442b7a8d614cd44805b5705fe6a356ac182b66a3c8d415132e389efac5f6b2 -825af1563d0fe53925ec9ac0df65d8211b333474e59359bf1bde8861eecd03f2ac74534d34b7e61031227c2fa7a74e1e -b60dd9bf036f1825295cd2014ef1f6d520cf729b4d6cee0b42cb871b60ae539b27c83aa3f96ee3d490ec27ce7e915115 -89ca43d5b7f3622b42df7887572297a7f52d5204d85e2e1ac6e5d7aa7f8aaea5e3a07280477d910db025d17cd2e7373b -b93a2bc9b1b597f0e514fde76ce5bfb6e61eee39cbf1971ea6db38c3ecb055e7913ec8cd07fb0b0ffae3ca345883101c -8d45546bc30266b20c6c59fc4339eb633155aa58f115a8f976d13789eaae20a95b064fedead247c46665cc13ba856663 -aa8eacfe00e8a4d9815de3f7619d9c420629ada6489933ca66a571bf6c044d08b391e0d9eec7d1cbebe8def1e7523f1e -b32fefc59a0d0319ccb1946b351ed70445d78d9fbb536fa710d3162b9659f10288f12d82b32ecc026d55f16cbad55441 -99c7c45c34044c056b24e8f57123ba5e2c2c039e9f038a66899362840cffe021733e078866a8708504cdc35816cb335d -80def162c134540d5ec071b25ccc3eef4efe158be453af41a310b7916c49ec0ce06bb43dfee96b6d77339e11587de448 -b5f2fa4f68f6a26bcb70d8eab62ad73509c08ee7aa622a14b3d16973ffff508ce6f1aff9ced77b8dcfef7319245cf2de -b4d0436019e779c789464716e1741c189e8945dab7f3072720bd9aa89882fa5b085a1755c48da21541f3cd70a41b0a71 -931e798ef672e1472f4f84c727a101e70d77b3a9f0c0803a5220958d6bbeb8aeeb56c769ab472a3d6451249a13a3f56e -918c10a84de268aa8f1ba24b38fe55ff907be07b1e86b4a4adbf305c0d705c1cf5f65ce99e03e11676cedc89f1a4f331 -8e55a8413b823715ccd92daee357cedd797e69a0e78b6fcdacb7318646b9903dfe05e5501f47b3c52e74055b9eb619a4 -8b329bb63e6c985d7d072dff4680b3f8b1217ed20543277386bd30ec25240d9dc378837dcd5cf4fd9548658635f4c537 -8c2be5386052b22986b33dbc63c5afacb6d0095495564ba4aa28fc8c880a3c78242fb083248d788ed928deb1e30a82c2 -83a2b7bdfcbd25d6b059f27218e009ecb5ecc4da68ead885e00216411d8222062ca42f21c4d9cfa19c31522080af677b -9620334d2633e85646b2e2fc48dc6c3f09c64ef1706ed78a3bb6ce1f6b274a727364df71e97531dfdcb392f70f27f536 -b6c84970ec04545121ec3b79376f4e45053c97e8bf2b11922cc2490a429c38735466097ecb81cc9d9692c74d2fb8abc8 -8e55d707dcf265c5ae29a32c27ce66f200fddb724faa5bbf145ef42280ef645fa2f0cc3cfe2db8599b26c83b91e077df -b910b96b763966402bbebd68a32c15a225ec21e1357fa298478c5981a4310e556103fef0c73bd8903e11c4ed2c065647 -a8fd933a0e9fe8c459809bd93b8ce153e2af55df94b61a1490736b19c89469954da8b72dbd072d798fc06fc3d7a3d60a -811b279c113828e114fd82c2070caa7eb089a46c8cabf865f9c77354a77ebebe0c4c6400dda0e66dd017cfc44d76851d -8ed03e91c331afb3ad6e42767e1b3e8d3a35fb831805ff1b5fd3e91878e04027ff5af1165a3ac295f1578faf2c83b581 -95bf53683d64a0621bf1ca6ee17446783f6c535b7a54d6ea57723487a215759a54f886597a55dfdd560424e368ab2759 -a9bea378768fb1d7ba365a16531c51fc1975f1c73caf2a0891da28509805fa84e2a8db7c6ccfbc620e9002317abf174c -b8308250891015deaf851c4e5a4cf4704d104f94064418488d7e3076d49f36240dcf6fdcf83f45fe8a1d97fb02e3db59 -adcda6b63da21f4074f142f8e7f3a2274f624c733e3a4001054a1809711529c61356aa087f73aed877a58ccb41d38d12 -b80e7869239ae26d1da2e6683f064d1dc93cf4a2b66e9439b3ad9b25324e969bf98014760d29e6b8de7ff152ef498d0f -8e9bf968911df3bb5e3a7655e9d8143e91ee87f14464d7ba9c86e1e31b03ab31b91eda121281b79cd974d9ed2657e33e -9007277e8335a43e6bc3c2f5f98c0ba7024a679b7156aeefe964f1a962e5ac82154ac39d1ffbad85a8f2440f3c1e354b -9422b9d670e997b7c919a429499f38e863c69c6a4d2bb28d85e36ae0895c620f68b71e39eba785e3d39a45be91507757 -926094e01132938000d82dd9a571fef5ef104cd25b4015a25e3442af0329e585aaad5472f0e7a69899ba2d6f734b40aa -95552d8057f7e32c24d69e4d6c51c98403f198a20c5be8826254d19cab2f84d5758e2220cea7e38b7c8a7a23178fd564 -8abcf8dcc8488bcc9ab23c51b9e7a0d91dfc7bebe88b7ed370ee68eceba643e939c5eae66a4aa5fe85120751780e351c -a91bf8198f029e6a4cf6f0cc39b629e9aeff1c77b8739e1d5c73d8c1d3fb5c8f6f23e27b435bf10b5b4ec1cf6a7249ed -b932d87ee3a4b81341511f90fe5aa36c571e8b914f25abcc33dd40ca67a3f6444fe9362c1434744e4af18d6e045c54a3 -a8e960c2be9b1d805d387b3ebe2134d421a65f1fd4c1b4cccdce78f9926f139eea78e3afb449b3d6dd19b5d16ace48fe -a7e2f57cce509fe66707eaba9b4c042c1be93fd6034a9b51d1d30c45c4363eac79d54663d525c9873ab0eec0b1cc4ed3 -aa162a31c2078f4b080199debf24494a8dfdfb9d8fc85b198a861b12a629c73128c55a883e4c2de3dfed6e0e1b83eeab -b5a4d075433eaf4115717a84b4dc37f843d44bba0bf820c92ecdedd5afb61be60f7708c8a151a678d9d5c0ae531bffb7 -b56ab96f7a463c0079e05dc766f3a6a31cae5c5044947734ebe0a26e01367c6763cc8de6c2ee2f3b8218f05bef217474 -b60792ac506b901065a8bc0180a86e028fe34b62ceae1ad640c759538ebf3a2ad9c8c927d662deed6f489ff3ff7813c4 -8c8c2cdf075504d12d441a58542e1f8e4bdf92b3ee4775e836b2734c5ec1e3df919b931386417d04489a1dca806c87d2 -8ed78e91e5c4a68894cefc2f7fa71f02e5e12d40f1bb74332139bc7be4d92c24e07d5ece0e82150ed474aa1337af4c18 -87119c22ff8aa31150bde537d863cad661cc5159b12f084cc319224c533f0deb28526ed8568d00a1441e7d8bb4f05673 -83a60ba5a9cccf22cebadf7318b706c9f29abd25db0e2fc1c802965351b53cbf316df72ee3e9b2d3ae7f3c4494cfdff1 -b73b6a9fdd3e7463fbdaabc9a885b7c82201ad867d1bced1c2484300a01cbbb3f1e21afa95d4c7cbb6cb983416b63b90 -b1d89ad16981ff9217708090d4017662d8838f21f3a3296cffe14590b533905fa06a20e40dd497bd291fa4dfd1bfc511 -8abde560083e071a402e3c7bf31930f537f67d2a7bbc734a7480b1b760aa712ebd1cbcb65b00e11e384e980222fe14a9 -89c731d8f31afea8bdc9c32527bdca257f2a840764d40f6e49403b8e75ae51017d505ea4fff91bf28b6f3a1bc65b8bbc -80e9ac8e077e86ad050ee73dfce268a69564ff1b8419e9c236d981fe7a5f0c2bc756e8603ec604b3b9e36da8fe10a49c -b4f1eea0f304898b1323c6382732e6f40e556bfc68af9ce73f6d54e92f5f23cc4f78eb3f43d578d81e7627fb40f092b3 -a0e3a8d1348f8f153e08ac4839232d75d1d6e81b5de184ec4724f8213baf98d3fe739a96f6b39d79a053b628c3a09981 -a6915ba0b52ffe4a381bbb8ff3791d9d3b848bf89b3bacbb2a7d2e5ae21f1353cdc304b3cb6e82416f7e604035c27d7e -b2c4c9cdfdd2fc9a340ba3ade9423344b9f429e8c7e20a8abbf26400376e312f3ae35d1c456be99dfb5c02fc8a36cbfa -9657d57ca0641825a0aa5687f3f87659d893f33aee819bafa5b1ca1db554811c1c844f971e278606e3a2f096defdc67c -a4ad24d0a557704ada24d8e27a15604bca28679e260b2c69ccc8e6cae5499866724b700605a90df7dfb35130756939b9 -b18d9ea6682f73a1f99a9a4fc98c38fcda02c1a18e8c5fc080cf935a2ac877dc5223fca273dcde190b906178d0fd05bc -8ea5fefad0799c885f50ff10d94bd0af5b99b0a446cd1f367ae5ff529cc47e09f3018115f3c0ccac2fa05bb65b84945e -92450d52e6c7d13ebfcdf5674d6761bbae2fc5aabc865d35d031b588c383e0a64cf69a73dc93948632e2b98f74a5ed86 -a356f171a98df4ec5a96d556eaccc6ad34b4238aafcf0e94ece27cdbb491749fc9692e78b84dfe80bdef2914079d34b5 -b918703a4d3507d266414712ba8eb7ad17da07cc5f952b5c62ef130cc6ed1ae3bf01237fc8848c179725bdddd465b301 -ad2b0554570bfc9d97510cf59bc38e10ca54a93649c30ac9919bd0255e43bf525ab11b74f78a51ac0973cd0c5a5dcb54 -a7ecaf4b631d179d32ac1632390d95196a0035e00da6c0e6e13b5c09ae44b15ae6c21538b5a31b73bc5f650ecd979b59 -a37704eb4d728df2a367e59fcb6c26023136230e37f3b8a2f3ceeb1467f5cd30186fc0116f98b64a8146fd2c5903e8d9 -b09373ce92314678299ae10ec1f93c702911beb4115c6b5ba6efbcab9c7afb599f59793912df70a98868bce6545a33dd -b52a878a1393094fd2b93f2d1eccabf2830ab10800ba4cc24dcc7849cd0978733263aef2fcb766a7cb575a7a99383db8 -8dac097e006fda4fb9d6d7ae52adabd9448ebc8d5bd5b38ac0c4ed38ceb510763174f7adfb0b473c38e52147ccab4239 -86b19c41efb949937d74a7875549ee5e997f9fdac7f7198085afda233cf74341a38d0ca3767c76cd35f875b89a35f78c -99f0d927e5ad25cd134f1c70b72631cc6b5cb4ddb86c0642b900464e33d971213a5239dddaf71f7a42f2d6d02a12dcc6 -8355c38806c335d747d4e97f0083fb96585677da18b409a85175ec35dc3f74671817b34203eb18c2f729717ce083ede8 -abb3603adb061a036eae0afa5f23d79c3b62442e0e3bcdeef896f88995585c1105cd3065410368456a4d36b5b0485a83 -9051c5c0011784885187d04749f774b9b4f6bc594b0e4e18226de79dedc4d7aefa3529c3d2c728e180f96f3e204d578b -91888213e7d321d0bfac884edbd5cb756b280753bb5f8bc6acfc208f525757beca24bdf86fc68d3d8736ef176a960b49 -91258bd7ce6e3b7516fe2f5391a368d826da299e0e99b1f82eaa44b62b110ab696adc92debab8ba098a52f38dfb3c5d8 -96e3907340dffa9da3602d3b94bacff7e1bb8649edd3b9bbd06e1bc6781e78f91ababab12c0b9be7c66dfedc7001b66e -9513555688fcfb12ba63952ab36a67b36affdd71f7b843e8eb99ccbd45421698024608233efbdc905eaeb26b334b33af -9913ca9bcf11eeb408da02e4317c5ca0010fb2f4490b282ddb758001c08b438c3b35351a8cbe10b7fffc1293ccd22d4b -85dc2471860ebca88e5a2766161fdd77f926d2a34825d1134a30418f91a741759668e32fd1e37c415d07ab5824338e8a -8b128917e828a0b5eb6fa8ed72b52fae2dfaf74febee69a2e2f87e8df702f0c5bc0fb620c8d1d2a07f35a15ec9c0f5a8 -964c39e7840c130b01bb481ae7bfc92682b0f124c9c383f9dbf3027f2249151925f4faf36905af476a54778d69da3f48 -80671ece658cf850e522d46d25678f934ce6df043f25f8707235125765d40c2eaaf39eda6092f75039b22cb58bf2c29d -ad4bb0e79fdaa340b1347a46b0f64e801c72a89770dda0a6e4bfd35f2df5146fce9934e4baecb1c2671077c771eb8089 -80b3bd3adc6cf198fcd997f8867d2839a2eb28f57390352ec423b8a14cc1f2ab21c6e286505d6a21fb134dcd8d8f11cf -a26d46a6b8a75748895a1d599e7fd120d896340e79813167a400b2fe463452532a4cab419074663fe1d29fa716b76a33 -82b1f3a8a1df29207d7ff020809113ab06080a7f0c631f76ad33f47cdfb6a567143144df97b4ed7f676d929195b04bba -ad96633a3744648ff0a2e4491e8219c9c6ba6e655cb058c36320a8f72cd5f72c00bddf97083d07650ea9ddc005fc1ff4 -91d0783788626c91662359dc3ff36a8bcc6831e3f4114f85c99910256b1d8f88a8612f53c7c417d55581dea486f38926 -84edd9e87ff3d193ebb25f43474c33fe502a1e2100fd3f93fda6520f5e42214cc12e9f8045f99aa2423a0ee35e671854 -b55e06a4b1fc3ff9a5520e0b7c8b5ac11b28385cce78d91ce93b82f1bd7f7afdd4195d0c13a76e80d0ed5a4f12325fa7 -b0b15c7ddede2b81d9c835ecaa887650622e75d0d85f81b8bbec7ef24e9a31a9c9e3de1f382d8c76d878d1b01373f6c8 -b1adb47c20f29784116b80f3670182d01b17612d5d91bd6502b0dcecdcf072541f582aafc5e7dd9a765cad52151684f4 -8efd1018df9c9e9814a9c48f68c168551b999914a6719229f0c5bf0f20a288a2f5ba4a48ba966c5bffb0fbd346a4fcc6 -b34ea2bd3269a4ddb2fbf2514401d2712fc46c22642f3557e3b9c7acbce9b454dcf789573ede9aa14f39605fdd03f8c4 -a9e1428ce24eacfc460aec2e787c053327ba612f50d93510d58b2cb0f13291ca3d16358325ab3e86693fe686e4f526f7 -91eac7361af4c66f725c153da665a3c55aca9ae73ead84ca2662cf736fe6a348a301be1954723206dda4a2120202954b -a6f02db89739c686407825fa7e84000ceedb9bd943e8a0908fef6f0d35dbc33c336072ba65e33e15ecfcd5714d01c2f0 -a25666faa12e843a80365c0fef7d328a480c6e3cb7f224763c11d8cbabd0e7e91a5b647585ee905cc036afca14842bae -b4348576439cd2e48c01cb9cded7cc4a0ea364ab936dd679ddc7d58b48807e7fab070f2f1ea88595b11af4500849026a -a8c6c731e0d0464ef7e4fc1b049065eb4ce100c01e1a376365c636a0b23851022bf55805963bc15eb57434a837e81167 -b0952937b154e3a4c206f96cd96c76ba37624956b0e4d43470bdd97b4af878326b589e3eaee82fc192437123096799a2 -97d07ec31ecc9923192e48d37df2cf08750050fb452dcfbdb350fbc43e146bae3590c5b732b31ebfa1ce5d884ad5ad57 -a69359aebbfe4cbc4d39d178150039fbf284cbc0edc68a6bd635ee3a1c76569a4a575c907fff691b2a4d82a384c2945f -b321c2c0f6b5902ee9056cce7404d858da9a573d27348c1a6bfea29b2746f2aee7abcb6192504e5a583b0caeaba117d7 -a74e738aa6eb4eea58855ae6f422af22812fb388c83aacca5bd5fa4a88d4c01463174a229aea2830c348dd9ab9307854 -94306a3b106bc1644346bc45c05cdc8287811d5c86cad691bde0c65d6a686eb9c0ce79ad91baa4547e5d058ae8bf7310 -b64140fd77a07633e4ca8d60786452311dcdb8ce7095ba51dad8486f57c3bf4e69bced92603f71da992a48ad817ab275 -affe7f4310f1dc68e5e3cd640bedf864f51bfb46bb752063bfc18e95930021f784e509261ff9c560f53000c361b142d1 -b0d2fee222c6f963ba3385547f921a48964da031d737892604f8f2677d4905dbf615046db57eae6c6dd756709ae6932a -81700c66aad7c2e51168e028b0fe086dea75d3b17d93a4dc1f47a6a0f025df0bae1c8c997901837ad859a84197e7bb00 -aa4ac5fdd602f8b79cace18690e67bad557a93d00c0e295074185e8c6b4059a65495d9971685de2fc01d2171ac8b706a -a8becb3a64fdf35d65d2857898dcf8053b5057a73ab8c5bb5324af1a8015cff47efb85dc3eae7364cd5c850b7962bedf -b72ea09bd0b72f8cde3466f359ea69b194ede93dced534efba1b9ebc6f3bd53942fe2965e992e82edb6050cac4ed88dd -85bb8dd7eef023a251fb6f220af54687747f4c91983ff728163c4618ffac40ee6edc29a0aa6d455276bbe017f63757c2 -85a485254a11b4c4a943d9ec509c0dd1cbfc0ff5273a00cf5c9f0babec973efb15348e5d9451b548293d778e3a2b62a5 -b109f3ac809391e772b589c196b013db69a9b2b10ac3898feb70b986973731f30722b573cd0c9324158ec20416825385 -8a4eb579a840d438bed008644f373ea9ba2f28470d50cf1d70af38ba0e17326c948527b1719dd1bd9ac656ebd5aedd10 -a52e9d66ead5ee1e02ce6108e4ded790d8ec83164a0fa275ab1f89a32200726c8e988d66df131df9e62dd80203c13dce -b541cee9febf15d252475507e11d65c4b7819c26cf6d90352f5e8a8f5c63e254eddf22df0c35a7be5b244233e8e4ee5e -8153c297772adf4603c39349142f98cc15baeccaeae10c3230ee87d62255f6814d88d6ed208c368d2c02332426589748 -970dc9782f1828474e9fab7dcdec19aa106725465a5844caed948eef5c9e48199c1b6bc1a637ed7864116927e84bc65a -a975a920624967f4ecc77ea5d9869c434caa64c330024194615a8d0640c5d4d4fb139ea11a0c73a5c6ae6dd3fbf0ab5d -811f0f9e0c12acfb4b9dca359eaef3bed18083bad96188befc036ad3143b121fff4777ca6dc70a835bbc4921bd25f5ff -82341c6ebdb97c8b72910da95c7eebccd1308b6a92999886aab552f0642882d5c7cc60931577d200efd6066530c998dd -860f7162c2f5fd1c0953c6ce75bd8c52eaa48032b914410681b8cc05e00b64130d1f96ec5a52df66a04c78a9f9f42981 -8a578e674875571fe1a0459843495a5ee1d9fb6cd684b244feb9488f999a46f43363938cd0542879ea18ed14fba10a6e -8df217aba4da6781f0f5139aced472025523ed6e17e504511c04b677ca8197488e237d8bb5dff7b6b3898cd5a6393dd5 -b2c9230ad35d7b471d3aee6f771517cf3145ad26200bd6fe9c7cf28120e2945fed402e212d2330a692f97bb9ac4dcf12 -b78b89e29e8b782603b222cc8724eeb83b2d9d56bc02f59a3c899ab76429dc721358b07dcdaf422f59520b7e7ab4fb55 -82682a5617843c4ac8d4efb4c3ce715c76c1da2c3bab1ede387db503f3489c1bfdfc07d9231d96f955df84fd225bc81b -b0f53725cc610e78b8e8a4e6823a2ffe44dd15a9a5bc8151ab7a3787ddd97e1d7f2f0e6efd2876e5f96417157143e3bf -92c5a93233085e2b244519078770c7192af62f3562113abc8902f9d72591eacf52bd15ce78653ab9170d5067606287f8 -a43ef97dcd9b6ad288846bf31fccf78df72f94bc7ad768baf5bf0d5dfa27bd74ffcc6b6c6ed1d1f09e09be3afa5eaedf -817d43bd684a261fb30f709f7926cc4e1a31fd3a1a5e7e53ba4d664856827b340d7867e23d55617ab3514c8a26a7040d -a599e22d3286b32fafaaf79bd5b0c5b72f6bf266ec68948478f055391336d756b58f9afea0167b961fd94234989f0f02 -b70db7d8e8356df2e2070f8d658e560081442f3f3b95e20f4bf30106835d76161101163659d5d12cc0f335fb042dc66e -b8f725b70c957aa3cd6b4bef0d9647393f7c9e0b7343e92439372f0e9aa3ceddd0cb9c30be331742b87c53f2eb030593 -b2fb5e7762f26036e7e966f4454f886758804d1f4c2da17f3d13b0b67ca337f1fd89fd3cc798b07da6e05e8582c9537b -a377f944dccc300921e238ed67989872338137fe57f04cb5a913c787842e08b8a1adcfb4d2200abdc911fc1c766a7092 -b82e98a606071c2a33f2ad44e7ace6d9471d5434500de8307b5d4e0083e3a5cbc67f0609ca8055f0ea0ee7501b9ed916 -8e58f9a04d33a41ace4944615041662dc35057e645f63e127cf0d70f96ac307d33a62ce98f164d6eed8536c1a747dcbe -b5b11388071ffbf57ac47fc195736613b964ebb91cc8e2c17b32646f91d64ea506282b881897fca96c317364d3290de2 -a40ee9b7551133856cfb3904837f9949a9558e59a418898affb78adf1500fd6ef6328fc4422161909aea2c79ad08c14b -81f9eb4ef28aacdb43e11dfc9aa92ba990be4d3c14b484fa677edad3a3fbfeaa859a7f9322b5e95818240d7326215abf -84939b2b6bc859437d1a7a8d6ec9a357c6b716c4b4cc22abc274af872655940cfc72c99f5d0283d90e05191fcdb1c232 -b78a5b74a90a805410b6225fb9576d6d73752520f25cc3fd1edf8ea9f6559d3080f9acaa2246809b6a66879cd2ae446b -8d0a92baa88bf38dce5385ccf15d345b28e2e5d0a2d469e689353d80eaed8e8408933816d70ad752f226c59a0d5b5f0c -a7e15f8a8c1655b7b346c9488cff278c793505379b781b31b273b4bf09b3bdfca1c8ab2334746075d636b2e05859f215 -b70daf14f2adce03c7b92d6aa181f0c507a80a37493d8dd12419d5ed5f943a98099fefb46ac827d6e4efb9b8233c99d6 -8c2480814661744d116fba7355bc6b1914975e44cf0e976d50b6a20092bb1c636b7b44ed3fe8d63b5555ffc89fa759d6 -a6059528a4fed36abb74ab992b22a4f9bf1d05c5de2bfe6837b9af1adfed98bc37ed7481b5a99675d432743021fcfdb3 -b7e19f1b25bc159e5a769811e773c3a8ffe8be8ac77ed0b711540915e5c6e7bafdb407cf9b85c551f67fd621ce8142a5 -a2f66d4f7d16ed3e7ef5fc90b42676c61a98ff18bd26ccce91de03b6a0130c1db17a6bc57be135e410a76d2255b15813 -a139c916927dc3d3fb83598da9217ca64f0ae127215332e9a7ed82be923b89a801c44580d5617297175f9dafb1c4eaf3 -af08e1e1b04ec95366a12d99c80a9a9ac40ac984a575dd0230cdf4eb346a7686da55ef0a276f3356f814af31f9cbf1aa -98840aefe287369221c0721cd7c1b15b1d670c3cbbfda191cdb5434bcad757e59c30ec82b2d8c75947405888d44da435 -b7c61c8d42daf2e278a12d8f6eed76090b71c82275f8b33504aba75d95103840e8acd083e97a5a5aa79897876a68940d -a0264048d2a2061d32eee4f661957ff351e78436bf49ef973c059612874ce9c91970869d011dc13a5b7c754476880a68 -897199a4d8db8aa2db5d9be3d4f4312e41fa0739eb06c62e2e046c4b9be829a447e5d47227e2d96195d3b7b66eb59da6 -b512a9082881f5dc90b02f8bc4f38b133348c2e933813852f6a8e7d8c270c9ce68a5524af7d1d3123e53b2d02a53d465 -80b332469254a96f53c95ec79bb5a8bb1c387d40e58b73d72f84384c696ba0d3c81d6ac90be2979c364c44294e90432e -ab680c2e547ea5cbf95bf813020beb461d50ee4341dea944eb48f6a8584d35682d20186e3b190b849a1ba25625a7f499 -9070581993a0531d6be372d370c2e4ab2ee53f30e04a75ae61ea0fc2c320914506c4d2d4b4487c1f8fa88356fc45c895 -8424303dad6b4051ab633ad27ee51783b2ead61c5a6dae1eb3ed72fc1f36e2a9b1f315504a4bd90f9664091f2f403d4c -82225611eee626556553b9316dab4043aff241a81826a33aebd9864a91e299b765ba1fb43eea2c2047e6b75b6d7fe3de -8a3fb221c616ad55c352dd5e0c09ee892022013d6965aef40d4f277a42e9fa01226fe973cb99aaf6ffe4f4f348fb54d1 -b07c07679aa51713e8a7d7bc304dc15ed5664b66bd371877023f3b110b3927e09e259ef22895c4001421a69c6c013cc6 -83556c76bdac0dd8db6da231b863c335be076e7299802eebc259e0818c369f933a4a4b18e2df8ca07e82f60767b462e0 -a516f659b7915d2f7cd0f0f5ea2491b15f0c84dcb191e7671b28adf7cf14a56d42cfc0da94b3c269b45c535f6eeded49 -80d7cc6f26066f753041b17ff1bd27f6d4b5603a43729d33d596e21a67356db84ca9710158089def425f6afaf3207f9e -b802a47f9009dbd48851209ea1e2739020e717f0ae80671d9f97a0e43de923273f66b7fcc136a064c8467372a5b02d28 -ac92fec1864a8a911633f377df87aab56713876316d48240fefeee49ab97f7406c22e70f4938b5912c5c4e766146b7a5 -89224225b9835d04428b0a74edbff53dee2be285ddd1e5a3a8c37307c0500578155f0c4052e4bc8be04c56862fac099d -b1d3c8492fbf22ea60732745edd3b0163ba5a20d1a3315e3773f2540ee38cf308d42ec72cbb3e3dcea457d1d132c3904 -8bd00e38ec30ee6c44a0e5b222f1f737c9ed2a4bb9225f1741d6334df966318c8a0fd2fbb109557fe8c9479694b8d8dc -a930ce5454efc0b247dc148aff869963fc5c240241d5590415cbd36634801a04d3873d93635911bb9c0c42ecb005cc63 -b83d4f80e9e0fa47b42175df74935ba8aad2e559b80e84478ab1685bc3eb65d51b93e5738d5ca968cc055ca0c552a03c -b3ae21258f98051f13af3878b8103bc541fe6f20b1c3f8fb4689ddb8800b3c25cca9b55f0a4104bdf15dc4d5844abb8c -831ef8684c1cd446c58c59d0152aeade5cc305bca6aa296b92162615f052ba280fe289edd62fda6d9f0667c186445f52 -97bf9659b14f133885916733b7d4ac7e215495953caba970fa259f7bf6b79e661090ec8d79e1c9ce8dfb17e8552f93af -84d5a89cc2332baaaf3d19627a65f4b107f8dd9228a1434b327732f59883bb54fb8ce60d6acd026ed4b0e94e545d1c33 -8e66cb743f95ca5486400b0d89d02e20b98044be1e3a12983ff9fe086179e5a0ebf4dcd5098703191552e9aa660a6de5 -87b4cfb35bacec805f8148786788db84eb8f4bcecdd0570ecb592c705450ce1a90b6d183d37ef58780ede3995be67497 -a72a4fece5478011973afa543f6d8a8ea06a64b241cf7d8bd81fa3740ac2a4cf10e5120abcc1c1101f94da89507a40ca -89dc6001a96adcd2679916f43dd19ea00508c8d5dd6b0090eab7982fd2f3571b62f3029588a0649e73f49124525407ea -8ca75edf1259599e873530eff6151c822a4018e71a340534219ef8641cb6683215891df41d4e3c0ca2560e57a7aa913e -9282d32f868e5ee6f7fc229dda5b94b603476de30cec0a44a30edf396b52dc0ebd472b8f726d4b67d76179fecc1666a1 -afa24704223707db89690bcf9761f07a093f6009ca9fc945e0a8801fc29f9f51292bf95243e466fe736088af36c55ca6 -b51332508ddd9a2610edd2b0ad120272ca342e96c28baae37a2c4f07e689303a46c237712d07e446b1d67c75aa8ce32f -9219249f3799dfa4eb4770ee323f821e559e7406bb11b1f1889286221b22c8b40ccacbd9ac50ea3fa9ed754860bc24f0 -993515270c128ede64fe6f06755259105d0ec74947b7eb05924a375fa5c6d14822f3d7d41dd04fa5df8aa2aa205a1dec -a83be4c2511bae430034ab15b194ac719d7b7041f9c0e321317f513a97db39e97b9ee1df92a1962f265b7a3e98cdd753 -8ac7feaecd26f7b99fda3ed0b8a08bd6dd33ed5ba687c913ec0ffc64bbbefcda6f265072add4d944f2005634601ce68b -b4e3ac6b09299db9e1a469f3a0b2d8d724ee47a417a517bebc4c2ac3efc5cde086b57b9aa4efccdef2bcf8f456d973f6 -9262a24a84fb7b2a84d700f98dcf3fefab8b47293778c20bfc356860cb84e0bf102bae9facd9986d92d1762e0a955836 -97be2041c42bd25e5eb519279163b0857f8bef627492c27b1182f8bf0033769246be5886422cbd2409c08a2615352465 -b0b87d059a00e3effa2e5e4925da913b245785f2932ac3ed364ad19a064d3561b8aa6afea22c951316074f0df179af36 -891644b7b3321b06a2a40cd96c2b8b29d81cde5b48546483fdda439000982a9cbf1f6333fb6c089d39da6492cdfaefe9 -8da9149b7f4783a24240b7b9c7e6df4abf8d699d3834e31ee591489bf4744141ab199c173db64397c1f9bd5f9c862ca1 -8ad7f9fb2742654aa2964fd468e7645436cefd1308b064fd63fdf0d3adb4caf6cfe5426354f6cc284f208b03d6b2d918 -8435e4668f7aeb027100d21e4e0b6ee22b401d21966a3736b95610de86c7e2f2c9ee5d0f901353675eee5ff458dad69e -9010895f045538bd11b47bb8996f27198c8d6cffd3220569e6b7407f68f35c47d1efdbcecbf9b5e241c3c2879a4f6936 -92a9aa443b5ee7bf13b6f43f2d8d8db7f6f33fd4073a606ec5772421a55f464831419726130dd97829a7d4bfeb1ab078 -843f3266560be6dcbe0258c3c7d7e332330e10630c069892954290288eda301e247f479505a8a1bf7e59c99ccafd104f -915bd1dad808f8a568725bd243f80b5476a2999d0ef60ea3ef6e754155bc4121b2b879d01570725b510c5a3f09cd83ef -97250d781815b1825be192714884630e9f564b9bd737d55b8ac79ab48d0fb3ca53bd21ead7b2fa82a05f24083f25645d -81e2d52333391ff2faab39611689a62d6ead77039e8703f4e012d53eea17a4d46f2e3342e44b6edbe73a542b461bda45 -89c9f9fd5f638156b018831c1bb70c91215f4a2f5a73c84b1208bdf6ad652a55df7213336ce12bd910a0e1a726474f95 -92bd02984d090ea7e2f3eb7d36d1e7b9d731b6b047e3cdd4af7cc4ee177415fea7a145205e484b366d84191f06af85c9 -85a86fc61d5d916ccbb219db52953e1495230aaaca63237e9165276405f07ad9644e253ae394f1ccdd231944e7143313 -a2ca5b3fbc9f3530f88c0ed7071ec3d89b272174c366eedb5d15d2b648c65d23c0faa4e92c776357e7c6883a0084d03c -ad171f5badcc99c8ffc9d8b707d792046f86cd0aa478e0e2fbb32fe095f96cd134ca548d1f7713057694dc6b26465315 -96bd15d57da9980870fbadc98c68db76824407dff2700c45b859bb70d98374d4a4ba99e3ed0b0c17f480fe08f16c6b8a -8300bac69ca088c3ff35749b437215e9e35a16393e9dc094f520516ba57a485def7029d30adfc72bca36eeb285c19301 -8a09e20be64f346668fcc7b07fee9c0ea8094c935cbf4f3a4cdbb613d4b936c1edb9256b7c884efb72393d97c0da00e1 -b1f85827ee6f041f93ab174d847a55710824fa131c9ade9561168c3962a25c617475ebc4105eba6e738961a754442bc8 -a131558f92e215969f41b6a57d1e2f424149eea531723821dd4cf8c54325cbe66b002de2c8287de6b41ab4b5c35f060a -81ba492b8956f73557f361a856c6c884ebb300d828287d5699e22e0cfa75c8e77a61616551d0be5178263898c461d6f7 -b2608f44d3c22fac8e13cb59e4ade8b9a98c4eb1ec0959ea400c97eb937ae3f66837e91917057148befade8389af2f6a -a6ff0323b5a18a4becb2cc6b376086b47cb2baffbfd1b0f2229ef2286fb4a34c5cd83a5faed5def7bbad519fcab8a856 -857d879cb9eff22501d883071382832730704bfcc5cd5b07cdce7ab8dc41c565a1eb0e7e4befce8e0e03a4975d3f11ef -a2879a20c0360c516811c490289be7dfbf7dbd41d2f172c9239f99e3d091957e0446854f9d0f753d90384a80feb6fa56 -83518624f33f19f87096a47d7b8e5f2d019b927e935a9021823fac6564c4f2328dcb172e25bb052748191e75ac682bd0 -817ec79132faa4e2950665712b2c503d7fb542aa57b7b36e324f77cda79f8b77bde12314e2df65c5b5296a6bca9bb0b4 -b2abf8fb7c3690816fa133d5b4aa509cd5a6e3257cfeb7513d1408b12371c4d58c44d123ac07360be0d0dd378e5bcf99 -a9fe1e4fb1574c1affac5560939face1af6657f5d6abce08d32fc9d98ef03186dbb2dbb9fd1decd6d8f4e4687afecce9 -89b2f41e51f33c3ca3e44b692e8a6681eb42a7f90b81c9e0a0bc538341df9e2039ee61f26d2ebe9e68df5ed1bccf8cdf -8b35aa7b1d9e2135b35a1d801f6c9f47c08a80e48603f3850b425f64e7fb9860d1adda04f92a1ba22d00dd0a26e781ca -960574978cadedbd4cd9f764bee92f94e08b7af65403de36b21bffc9424bcee845b3b028af2e9e545dd77cf1e69a6a7d -840aa0f34b5b6c39471f54d9e85f1eb946468c4fc01963a9027cd7864df01f73c2e864f1f07aeed4b1b1af72808dfa07 -834464a84a11200e3c60f816044c254a7d9baed64aed45a17325cef7fd62338e0a26da78d199d30ac3411714dc813223 -b4ac6fe2f5059546f4ad9a361426ead33237b6b9030b129bf0122085c85fe4ccb33cf90f5a7f23c5b708a5ac64b487f6 -a12aa9035464795f2a67f3eaba478d5ebc838ed9e997c7dfa241e1ed60a94b367d3f969ccf0ef02028c35215698b309f -ac8d926492ec2bb68c6d8aa9bce49085d3d266f3d5f1f924032b87c42b44e41da7c047eeb01e4618f9d0f123dcaa537d -a5142425825d813ed8ce1849d81aa40b11f1cc3daa89a9f798dd83065c74820b4da6122b3308f528b074531df66e1a5e -87ff55c9f5aae079e7bf24084dd9c6b3bc260727d942d79cbe8dc13341d98525b4ece3ed8169994b56a387642f09134a -88e680f148ef2ecdcfed33b61f9e0224790fddc9069bd6999e9bede1791e761637c0fd60b52990b6c93e6e5429e483ce -94bc20bf5aac6e9f1060d02eacd06c42aeac9a1c5635b15a83985dfb03938ddb4999a822e865635201489c7f75601b29 -849221cab7599f25f0b114df092bd5e8c2430503ae959bef1543a101de0790a78245db6a145e26f40b5f9bcf533219a3 -88b6f2c2e7a7954fad11009d839ce50780921f80292320868d481e38d26aecd80fa607e82219a99532d88cf33b39f562 -b0d82947dc23c0b88b86c321b582c15decdb825ed909a731b42d46bc895009515a3dc646c98dbec7d71b0722df82392e -a2cfb9f7c1a76c8073363c1c3bebe5dc29fa76533caea41046c51ea9bbdc693a121b957cd96be5b6da18704d1865cff7 -8f0ffab9a83355a22683a9d998d1c1089449eb308711eaad4265f05927ec6d0d1ca39217082a0b372e02234e78dbaaad -ab024661e2b2937ad374c8cf2e3669f1dc55558a3a881e9ec4d461f27e0fa92e2bc88230f038bfb051cf2145ca747a07 -b98d9b9ec9eefa56d38cca959ce1aee7b6d4b41a8dbbd34b3f50c0a5f97f84ed2502ded1ce8cdb5895872360d4ba6d61 -851244158b3184a62d2c98d148e2b1102cf0d5500906bbc2deda95acc5e3bc4b4a3344febbb31ce05a56dfee86a74913 -860d9e2cb886bd3620b5d7499d14b415532482569bd45fd76e3e8052d78a73ae4b2b41f139f9cfb136564108cd93c0f3 -8305a052a0fb2bcd41f3aca075c5f7f233bd8f861451d03f3a6e6e31f7d08dd89fe1eb4dd7b238a78b12ddceaad9768c -adb703e4778c7e14fb83541ab00b5fc344108243ec6827c5d9b302ee68321aa569da1718424e6a57979ab7536d5eb43b -b1a754b87b9e21aeb86217ec5b4fadb7535344567f1bd15e88ec12a833fed68e26bfbe03b7709ce24ba6c925ea0a0e07 -8c1e2f6bf820e1653f3b8213e9d959d8649196223c2aab57b7ebda094f4919f88d883bcc6a0cd0be335f26f5a2a9c962 -a082deb9865fe8668e91db0e4fd7fb50fb3fdae3e7bf1217ce0aa6f286a624624cf936d762bb2b6c3fead6826694f846 -a10540ca05fbcccdd0a2a66aabab3b36e9bb525794cbae68bc3dace6116f58942218e9d5e9af10d67b5f6fb6c774fdd4 -b81d22c4ab0ccaf447cc5fc2ff3bd21746617e6773bf43257c0d80331be2e8437b88c9c45309ee46402b38d3d4911caf -84c7c6e924713cab3b149f641dabf63ad5abbc17c1d8ee7802a6630507aa1137f7e034ba1d12ec13f1e31efbab79bf13 -8773b9d236e5fcfa8c32e471b555264692006bf9a869a3c327aed33da22dfbf5780ecea7158904d4d6ac4acfe9789388 -a4c2c1bb7290eb7af2013f7dde78282148593f066b09faf42e61a3fcf81297caa5a00fdbf6b93609c8c5782a0f25341a -a7bfa6e3f273da3dcfac7cb9906bbe9fa4fc2872b184d79813ee273e6cc4d7f37f46164362707a1976f5b6a2c5d7ed1a -8b71502019e4263fcda354a0fd10aaa7da47f4abb7a0c715c7b017e9eea14f2b64009b29b467394668c7ca995adedf82 -ad7460fba7deccc3f9a7d204233de47ce30ffa55e1e164975cdf06480a6108720bc397b93ca8c959df77d44a1e1f05f4 -a5b8df96ccb7b078a3918e74b1b10da21df982538d2c9313f5129b2797c8a6db9ff8707241ff72d3e9d5983397321736 -aa6cfa6386660c01879656da6c4e72497690708bae6c5cd1d088f443cb5bbbe75561d6eec256a72b9728377eb83ef973 -b9699ce7c5c878e44114ab7a598646c6c7616b8e08a9ef8ec291189ef9945c1a538d2abf1ce3b0da0f8eecb303b81b43 -b8d0fd1d278f53c455de92ec4357885fc6648dc5f276930263da7dc885b4a9628a2113e28b66b1e64fd08189427c614f -84ad8d262f6ef5d93e82ff6f4af995148eedf6d8e079124daee9b99f506e2968922eac2c7d4aea741fceb7733f20b2d2 -ab5e30ab54641e3a44450118b8235554e0fcfffdfbe1430ceb3f7ef33325725741995fbbbb0c16f0875aef0f1e0c98ec -80e2cf8bf386ebda46045852751611f2af80eca2e910d9ec5f6e2c7376611534604ceafa639272b3d503b02bd66525a6 -aaac69af8fbb87da1c1b7c1b9e59942887ae839a91f0c1d191c40fe8163d7f1dbe984e4fd33619c73e63abfa7058f1e3 -a6194224ad838ab86e84dc80e9b8abb121ae6c3c7fddc476463d81f14168131e429a9757e18219b3896a667edda2c751 -b68f36aa57aedc7d65752b74761e49127afa65466005a42556230dd608ecc8f5efdb2ce90bb445a8466e1fc780eea8c3 -886c3fa235d6977822846b3d6eccb77f1e2cd8ba3dc04780666cf070cae208b7513dc4525d19a3fb6385cb55f5048e2a -a9801273ef850b99eb28f3dee84ba4c4017c95398730c447efe8c1146b0719f252709d3397ce60509e05da74ed0f373f -a58c2a5dd13e08ffa26a6c5e5eb18bd8f761ab64a711e928e6101512401ef2b1c41f67ba6d0823e16e89395d6b03ebb7 -91318b564ec8b2d8c347ca827d4d3a060272aec585e1acd693b2bafa750565c72fec6a52c73bb3ae964fdaa479700532 -a058db5d76f329c7e6873e80c7b6a088974522390ccaf171896066f0476742fd87a12fe9606c20d80920786a88d42cec -9838e07f9ed8b3fbca701be0ef32a3f90752bbe325aca4eaea5150d99eb2243332745c9e544fd1bb17e7e917202edab9 -85a9ae7dd354f36e73baa5ecf8465d03f0c53b24caf510036b3e796e4764a2bc17f0373013af5b9f1b8973226eb58cd1 -896a4ff4508d069a7da6ef7bed66e1080991daee8b227f3c959b4f47feaf75fd1b9e03d0917b247c2db11e105395d685 -a36d9a6a037bf498dfc0e535f2034e6cd433c7b52e520469811eb2e9f04499a6ce40257d2905300df7d81f38d1bba075 -97aac3c5492aca879b4c06db1834b30b8850a244d29296046a84c637d9580c8521ab4752ef814c96f255a139660d7639 -8552bf592a84ab4b356d01643c90347377ebf1f2b38a8c2e55a3f34537b8c7dcbd62e6776d6c2114f2bc2d4344d1567c -84474ad163db8e590943ccd1dc50b4f444beb8275919b33f53d42cba89831e9d42ce2de52b26f4412e2a0676ce913277 -900799dfaf5eafeb297c7b4f892438bf2a65ce04034d66f8e5cc3836e4eaffe782fba4f4455a0fcab49102a240d1780e -817176415e35ad4a204b9fd5771bae6cc270f6ff050996cec89efbe461b2940ae5dd3c6c7d7e31b1da5285b207efed27 -965e5791c927d47569bc54ec9b4c5305788aecd87a26e402aabeaeccc03480df46f0586ca2e2a9918885cd03332af166 -b96d9ada4b5a04a94807d71726bd557de94fbd44042d7dba40560eebe8658d1da49eba54499360619f3b2c38e8b5ed6a -a07b6d641a43e02e7868f30db4dd5069a2f221b4f122ce9b11eac04abadc4f25f3207f1d2d86c7935b1a3d9992ea9814 -8250d4d8ccac846a4b1a9fa392d9279b5bf2283c8b95d8164c3c0d199fec8849eab85755f2a2a99d584a0407742e3200 -8324cf49f56fc14162f9a9ebda1ebda0388d09d8688f1938aef7dbf9505fc119069efc552f68cc7cd9213f96fda2c6de -a98e6f1e85268dccbe3bf4e92c9f455c58dcb53de1dba3b78589adf2e50e79f8e245f956e0d098eb46f5d3746826c6dd -b103ec12f266b4153d67b54d8fc079357ee342cbe5008adc3e0689a7f788534c4601e60e939731f49e4a1e24fd589f82 -b2d7681e866420413cc98eae67614d383943e3762d5742cb3c57e26157633c20880eea1209feaf68402d5d33dd699708 -99fed0ae4112ec9ed74baac70d202a885aa51cb555a3886b49016744dd4017640dd5dd564998c4d842a9f38f3e004e68 -95c35401314467219c8bfb1ccd1f1eae6ef4fa9e48fbea14f70d5315e67b16c46cd03554471840e4a5030b077d2a3856 -8d029380e0c294400d6b8673a23aed43697cb6460fc1bcf217aca3b47cf240886644ed09521d6a05f6abf56f99722d84 -8ef54d1dc0b84575d3a01ecba8a249739edfd25513714dd4d1941fbde99dbbc392f7eb9fb96690d7052609af23aa57f7 -b8ad2b7af4812417aa8de8f33a26547f84bb84f39501d4b7c484cc8bb54c7e166c849b95240fbe459a4719a6e3bf1651 -9858545de898721d19930d8b360cacc5ce262c8e004867a050f849f7a2f2aba968c28d51f24a9af56aaba23a9ded4349 -94ea5043b70df1db63f9b66b4f9d8082776f721b559f27d37b45e0a84faf47f948d7c4532dfd854a4bac49fb2ec8e69e -a2fd88d7b15e3c2778f6c74470d0f9e1a1f979a4d58bd205361eacadab9973d585a6508e685e640b272d6f8a448eae05 -88defd6bccd55db8ca84e3c8d0fc55a3456b41788f1e209d0aec19c9c70febebf3ae32cacaa1dbbf796d7ddea4b17995 -88b8cde2449d5ee7de2ee2f32e845d27e171a51ef64f1d3d8a5fd7dbb9f898ea70eb7f6410cddfd7b7ae70ea8073cc2e -8e044fff6ec557824866ac76301b6d93ed19b7177aa6baa95046330f5d69b572b59200e3653cf2f2b559455e782e8960 -b5446b4d6741c824885790d2d26258729dc0ba2f469c85a47d38886d933b785a4f38a951d37f3ef4bd5091c03fa3a071 -956c8afa8056e9a71ab2e8be5241ddbb3a8b3cff2110cb0e7389493d9fa45e6c4b769ebef540a952db6dcd8bd55baf64 -925950cae25615246e29d594ebf34fa7d52f78a9867338648158f2131e6eb4dc17e18f9db8a5fdd76d017b3a9798b3a7 -a17ea4b43211ba990270c21562690b3ef154a46c3d669c4674c80bd424cdfa95d8850c8e882b8d06504f929cba3d93af -b315ec723973a138508afc387ef651fd8a8804f93975fc36c2eeb796a304eeb1508518d8703e666a74d14318253f526f -a995742d7433b3f230e622de23cb2d81cac76de54831491cc29768eb4a56da60a5cbd573e1da81fddc359b489a98f85c -adb2e89f0d15294d7118fc06d4fdbd9c51d3ecbcc23c69797e5b8197eea0d6cd1240910cf22fcab4ef1e2dc2dd99da91 -b5ec9f9fcd0b5d176b643df989bb4c4c1c167112373d662fb414875662d1a93160dc0b5cdf540e8a30e5fcbe6cfbbd49 -b1291b53f90aed275df8b540c74a1f9c6f582e16c5df9f5393a453a3e95624ab7552e93d6e2999784e164046e92ef219 -8bc7b7b1a584a12d5ae63d0bbe4dc1b63c9df9c89bdd1095ff4b8e7c822bf8c1994c92310a3644033c7c9689f4b7d2b0 -ad7fc45506a10ca48f991714ecc055cea376c0cbe667f3b40ee8dad8446218835439ae59bccc474cf47b053748ceba6d -b134756828a5f5725c0b95109e09ca450e3834b127163a0aeeb544e63cc0cdcdf66f8ed98c331c7c98758f46af369a84 -94535bf1636be0974b112fcec480ed8eafc529933f3065c40e417e608e43a392206cfde8bb5a87b720263446c90de663 -a4df4f6efbc3701000fb072e5cbed2754b9ef5618386c51ff12f95d281d1b700fea81fc1365f4afc66a7c83bd0228fbf -b0336b3552b721087c7e2194976a9119aee13ebed9f1c3c494353707fffde52d004a712965f460062ec9443620716302 -99a39d1d1ee4283b75fa8c1fa42b6a3836b734be48bdd48050f9b05e48db6354fef509623c6ec8d447d630a9b3352b77 -8e3dc3583d40956f9e784e8bbd0b5e65671d2ff2a7c387b20fcb7da9b969f2d122aaf7f054d450dc611737604548c03a -b5068ec5b7bcb5d8583d51cb25345990f50d1f7b82fe535a6a6b17756355885047916f466ea3ab09eef5516bbf2dda90 -a8284ec1eb1d21e693f31a6c074199ee85d8a8da2167bffab5fe240defa2773971c8437e358a18f7e58d1e2954f57f6f -aa7415639d29081acbaac3e9c6b059d68e8702db3f430b86bb6e220d476fa74841c875e9d471c8a5423c58b6fee3cb54 -8afcfe6f65fa6e07c2cb3e1756c0ef2c589830be96edd50c3c248e3b17f51a4b08ba92ef7eed7991d81667ddfbf2bf7f -83b9c8dec8ca8f9b85f0e36c08c5523cfeafb15a544398e6f93b48b5fc4b15a0bd05c0f176a9c2469664acab8dffb0a8 -82a128a89ea46b9debe5c903b950c0ab30cd7570b979ca911500b5c2cca5c4ee6b2c2fa414b5f28e367f4671ffce60f4 -b79fd0ccd2629a361cd6f9307c02ecd4d1f07e4ee03ce4b542997e055b07a026cbc0ba05fe3da309efc58db2e401a8fe -b190751141093823b4b5324cc26c4f3258552f7893241201f2fca1ae9b1a1d4d4964a9abdde8642cf308ded61ce5ef09 -935fd48b95aa6f9eada0cf9a25a573f0ffe039888b3410788c41d173747bf384c0ec40371bb4383ddcc7d9f2db3d386b -b9affe100d878491ff345636ffd874ce1f27852a92417694afce4163e6a80c78b2f28d78102fd06c3283ef273ad37642 -a877670276d49ec1d16c9f1671e43ade11c0c1a1413755f6b92be9ad56bc283e4bd2ad860367c675d5b32ff567301fc4 -8c660d16464878590761bd1990fd0fc30766e7e49e97b82ec24346937856f43990e45aa8ad37283cb83fa16080d4a818 -ae1412087da5a88f3ccc45b1483096aeb4dcf4f519ff3dbe613f63712f484bdd8b2c98a152a9db54cf1a239ae808f075 -ad83cead97a9c3d26a141604268f8a627a100c3db7e5eefaf55a1787ddc1dd5ffc7544e4947784cb73b90d1729003c8f -97c3140ce435512a509e6ff3150da385fdf9e0883a5dc7cb83d616ec8d0a0014e4e0fa57a4d12c7997cd84e07d49a303 -a353773ff68f1615454555bf658eabdcca40a9c7bced8537ea6fa8d54764fd1f032889e910d2a2a342835513352e2d2e -89e8df0c17a36ffe08149c2ef8b27306d04cdf437135aaeba697abc65e3c8e91bcf1817919a8a826acdbbe7dce79a18a -9928c2da15ac6cb20b15859c22508cfcd452c5643cd22eb84abf5f0a1a694fdefcd8fc329c9b40babc52630743d6b65a -99d837b556f8d13108eef6c26333a183f59383b39958dd807b10590c3d37f62ade6c4a320ca2e70567e0218b0ad5807d -9272da080e4aa18720b634640b01bf1fe506c7c8a89dee8759a53e2ca5cdbbd4a4f3aca54924c46b935362cf1eca066e -b4d39752c882de1c1daf3854202c1d58c2bcf35c882006eb640fe54a97be2655281cdb91c30d1a41c698617c2cf64b01 -8bf827f4a7d47e07374d338a3d8b5c2cc3183015b5a474b64b6086fcf0cdcf4852046c9e34d7917d69caa65a9f80346c -901bffc7db9c9416e06f593a76d14f6d9e5dea1c5f9557bd8c93b9e70aa4782bab3518775c2a5b285739323579f7cf0a -af7e204388568627ca23e517bcf95112ca8afd4c6056b7f2c77c4da4b838c48791191565fd38398587761c8047d11c47 -ab2576b5366e6bd88b347703f9549da7947520d4e9de95d7e49966d98249406ed9270fe69347c7752dad47e42c4ea2f4 -b12e3b228b761dedd99d02928105494ded6d4fea3026d73d65ebffa2e85e2cd75b6d091135d418dd95ac102c22b5ee31 -a20b4a752685d5e31ee7e2353c8a1b9a5265f12bb775004d282a3ecd9deda44831bac1ac5151646428b66909b2a423f5 -91a1d4bc0062a86cc6786a96fd3eb4436d8a4a187b7cbba02190d1cd6ed3c3797d9ae7d6ddc413f1c94a21f62bd04ef5 -977f18da1a5df5cfdd0276f583cfba2b2a0fc6139520664e20068f8dfdde33e29d179abfd722f142448f4677aa47be6c -abc3ece90f0f7b1d80fd917de27ab0d88cca584ef959da520825e54cb5a71336b15f8b348532d08d47a6fa600527ef25 -888d36a2c7cc13a1c1aa338a183a74a1f57713e76cb825f9837f43279ce4741999b76a16928147537bcc20f2e0195b0f -af3f5dfdc2dcfe19de893f385f39f550cb1dab67c2e97f1d5fa735e5ec96d6680066803e8a0eb010dd4399f654195513 -a0fb4e08ff56530a940a86c28830956eb6dec2f020f7faaea7566faf0a4fafe0cffe01480e87763ec22f201be51a6451 -92343c5b107910b203c64a79c93d354f7ee5b7d1e62e56732386776e275285561cb887019cc00d3fdbe3b5d54460bec1 -acfe7df83c4624188a1011ad88c1e1490d31a8a8c8016b40aebcdd7590d9c0793e80d2d7ce6a7048876621c252a06a5e -a7da001dc1e33e0e129c192d469d2bd6e5d2982eb38f3ba78bae0670690c8e70f40e8114a57bd0718c870ca5dd25b648 -a903de5ff97dc83628290d781e206ef9d7c6b6d00cadc5bacffb31dc8935623ab96ade616413cb196a50f533e63641d6 -8f9658d42ad14a60bbf7263f6bd516cfee6b37b91a8f53715d69f718a090ad92484061c2cef999816760a78552fae45b -8c15b72b3d5fcb9ffd377fd67d9dfbdd706593fba9629002639973db12aac987bd1db70250ded31c88e19efff612cdb8 -88a2a4034decd854fb557960194ff3404e239953818a8a891bf72a0b26a8e570a65c4a630884de991ae7452b3234f31a -a09cae5c4c190537bf1dd75bd7bce56f7b799762af865bb9d1ee970f6a133c27cce0dd0f14a0e0516ceac41054e6998f -9760ebb1b40f9a97530c3b940d4ef772a225e5b63bf18283f8e302b9436c5209f6294980fd37058060e429fb7fdc3a56 -adaa9400eb86d857dc591b25dbe3bc8f207b69e77b03cb5ee01f7e4b006b5c8f6ba2b51b5a45687479885708509363de -949efe6b00b3248846747a9ad4a934d6e4255994c2b540a59fbbde395fe96d69bb67908441cfadd8c8bbb561fe52da03 -a19a45504b6b1dc3a0fe0e6a1384734a3dcd5a7cb8fb59eb70e49426c4fc44946547443d558e5719a04884ab3a2811ca -8934c9ee21e8d1435426fd0f64232a0670a7946ec524c054cd4f2cc8b1be9f89cc11002ca8aebae646a2050d91716b10 -b1150ff8ffb34ffdcf7d603348c0aed61e5f90ee0a1b814079fc2a41325c75f2f9ee81542797ede3f947884266a772e0 -86ce8cc7c1f92af68de2bca96ccb732f9b3374dad6657dfd523a95e8a931a0af2a80df74098514a06174406a40c16ba5 -90faabb9ace9e13fd9584932846ab28a618f50958d2ce0d50310a50c3bc6b0da4338288e06e5fcbaa499f24a42c000d5 -af4a935c2d8df73332a16dc6da490075cf93365bd0e53e2374ef397514c30c250bcac569b6df443985cf3720a4534889 -b7f948ee90f394789eb0644d9f5ad0b700c8e44e5e9ed0e49da4cc18483676d25740710b1c15a557965da635f425b62e -a917913091245beed6a997ff7043ecf60c4d655c4db0b1ef1c704fd9b0e1ea1335ce8b9f45d6e120f81805ce31555e30 -a48099da8406399bfb1ba834f6f7d864111d0036969a5cb64089947a63dd9467d3857b605e9f57f5ad5f4ec915088d9b -9784c3f9be42eed354542b1446d734521f8e3f01cd9d495ae98f2e4a3a16767fe2ad909e0def5d9a6267f3fc6a172cd2 -8d9afaa323847a3226ad7d7b60d87322ffcda2e4a8df89f58a076f7972d896588de685a2e155e243bcf9456b0a0d6d1f -994413faf0b843f4ec1842c706c45ea5f24351c68674a27887bc8b182eda756856e507a4e8bbfd937e2c4c581b629ee6 -b3e72d9d1ddaa00c7d22f25462d6e9f2faf55e30d138dce8bb1517eb0b67132db758668aac26164fd934d732633bdea5 -8e95875e338f714e9e293df104f0ad66833bbd7a49d53a4f7f5fd5b18a66a61aa0a0f65cc31d55e0c075e0d3e412cb90 -b980091862b1a9f9334b428eae14bbf1cecb4849e3a5809773b0d071d609727270f6ad97f329eca896c178ce65883db9 -915d7ae5ae780bdba27ba51a9788a8852a15355b569581d1f18f0d94bcdfed2c1ed5a4f58e049e9825cda11f92b2c2d4 -83e581058edf9259d0b06128282327cacbb6afc939578223cbf93544599f799a8dce1fb21d52464f990a877086f42506 -803612a38b6f6efb97941997e101ac1878e192456f8fbddb3359aa7f3023434ed8fa92e60ec8e7b4473b1948850e4311 -864a1bf4ac046161617dde282e44ab3cc1843da01a09ca58aa00ed00eaea9351a07a9ec16d910819e7dcc28b8d2c8ada -922eb142845975d5f6f7dcfee6cac8c299b3730400e6bf82cc0bdd9888de21de9d9f1530640f702c003e1ed63b140cc7 -a7db03c5be647dce1385ebc02f4825a654447fa8c4c8d4b22e635dbdd2b3ccdf219384e49a80cfb1e9e6182b6e4227ed -a167289ff0f0967bbab6479e4a8a6f508b001bbe0d16cad36ab4c105ad44f3f180e39a6694e6cd53bc300fe64dac1e8c -b7766431f6379ce62cba22ab938cdbb1b0c7903dfb43980a417e0ee96c10b86b447241e9dd4722fa716283061b847fb3 -90cda18c5d66f5945c07c8c7dc453dee1370217ccb851bbea32578599aa669b4dd245dd8a9711b27c5df918eadf9746c -ac690cd2af39932874385fbf73c22b5d0162f371c2d818ec8a83761e0a57d2db2fca1d757343e141e1a0348016d5fc44 -abac820f170ae9daa820661f32a603ed81013c6130d1ca1659137d94835e1546c39a2be898b187108662cdcbb99d24fe -b2ea5a5950096772f2b210d9f562f1a4cfacc021c2e3801ac3a935f2120d537471307d27b13d538dcbf877a35ff79a2e -ad94af4d0699cd49ba8ca3f15945bd09f3f7d20c3aa282a3113cdf89f943d7793e59468386b067e3c1d53425dfe84db4 -83788367ec97cc4bbc18241cbed465b19baa76fab51759355d5618067009298c79d0a62a22e2a1e6dc63c7b90f21a4a5 -a3e142d879096d90b1e0a778e726351fa71996466c39ee58a964e6b5a29855123d4a8af47e159027e8e6be0ca93d9955 -860831f8d3edaabd41be5d4d79c94921625252aaec806251fb508e364e39fde8808d38b10d557e487603a1b274c9bc3a -88da39f334bd656a73c414ec17dda532059183664bbbac44eb4686c2601629ef8ff9da992c337a842e3885b684dd0032 -b50addbdf7164e8303f33de5ce854d6f023d39c1c1984b214d9e5fb6f6001cd5bdda816f048a438ff3d696872672f805 -999e58c4c69a912b84561cb09610e415b43832beeb95897eca8c403ef4754f4277754d492eef3673afd4362f50060fc9 -b88ea0f60f8119c5a1fd9294796d387472dfad22442b29659713d1d88e7d854cb7cf5c9ef773627781188626bb2fb573 -a068b3844e9dbcf74b54fd55904d56af754d8ce4c619fead7a07f9bfb9d02118db7c512ccec2489d2a84374ec1d1fb6d -871dee023768636003c799e6f6fd8d31315a4c0da7286345cd64264a016693b3485e0732be1bbd34dd5fa04dfa58a983 -8021e8f508680df12e4a5a1bd49f2d7142df65158b0a7198ffa83abd16053a542fb93ffc33e5279020ba8c6a26feacf2 -b5d3cd64df5bc965228b0bd4ce9e5797c409f7b64a172ba165e44a8e4b38e3d5fabc3e0b9a19afbfe427f887c40a315d -a54fdebbb594bafcefb1a03697711e0091c072e1cc24fb441fefd4e0a0518675a1d7b0966cb8294051d7ec0ac175d0cd -93922202337f72969d6d6e14a29c9c75e0420dfba712029941d1504b9f6f9761d706cbc0652cd09a1aa5d22aec766af1 -9711ebf1c7c7426190d4afd5dd03b014a456bbd9d90ed101623866a280550df26a629dde400c03ee3699f7d827dc0bb9 -b4d686d8bc5c1e822a50124c1cc23c6bc3a1577a3d0b8d4b70d1797418aaa763283c09e8a0d31ae6d4e6115f39e713c4 -a533ea2ac683e4ba07e320501a5d82a1cfc4fa1d65451000c3043f0fdac0a765cc1125d6cc14fe69975f3b346be0fdde -94ee563134fe233a4a48cf1380df55ead2a8ec3bf58313c208659003fb615a71477e5c994dc4dcfb2a8c6f2d0cb27594 -93e97d3f3f70664d0925be7aee3a358e95ae7da394220928ae48da7251e287a6dfbd3e04003a31fab771c874328ae005 -b57440d34615e2e7b1f676f2a8e379e1d961209fe00a0cf6798f42b7c28dbd03172fce689305e5b83e54424bc3f4a47c -97644084c6f7b4162bc098bed781dd3af6e49e7661db510975528f1dea8154f3d87e979bcae90c3df3a7752eb0752889 -a923b27b225b2a6dd5bdc2e3d295b101cac5b629a86c483577e073cea1c7d942c457d7ff66b42fcf33e26c510b180bc2 -86698d3b3873ed3f8ab3269556f03ac8d53c6e2c47e5174ec5d14b3ed5c939750245441c00e2e9bb4d6f604179f255ef -87946826d3aa6c7d53435c78005509b178fdb9befc191c107aee0b48fbe4c88a54cebf1aae08c32c3df103c678bad0ca -860864896c32b5d4cb075176f4755ea87fea6b9cb541c255a83d56c0a4092f92396a3e2b357c71833979b23508865457 -b78fa75d687349e28b4ddfe9e2d32bb6a3be13220b8f3ff1ded712088bd0643da9b72778bcca9e3b103b80097f48bdd0 -8a188b940446598d1f0e8c6d81d3cada34c4c1ae0118ec7e0eacc70d1bced28ae34b99667d5793d9d315a414601c3b22 -842ac6f7dc14191ab6dddffcbc7cb9effba42700a77584aa6a8e17a855cd444c5d138f9d61bf55f43c6ffbcc83f92bc9 -b6742902c3d145a6af9738c01cf9880dd05c85f0d0ef7dbe93c06fdd6493333d218339ebc2a02be1895436a2f734a866 -98bf18488483c627b7181b049d3e6f849fce1f15794de59dcde6e5a9b0d76fd484a46e48822a6a93001d3aa12f48bc6d -8769cac10bda8c53a1c19419ef073a5998f73dcf2ba1b849561615a17cbc0a49bfe3eb4ff8801dd36a22fa34b9a3a7e2 -b45c084d58028fdfae792210fcd183abc4ffddeb4cf52ebf3f8a50e4c4eec2a2758f1241b0920bebcb24b757c778577c -85c1216eec8e1fbc1af9b36b93c5d073a81d5fba86a6daae38748ec1573eacc6bef209e76c87a6efbd7a3f80e11d4c3c -b8007e34bb3f927ec06a050b51e633d7eb9e9a44715d5b39712e69c36177a03cd68391090cc3293098e54f6cf65f6caf -8e85527b27c9152b1ba3fdd532a76a79064ab097570508f233e09978761dfe3012d537411b47d0e4b65265eb32cea2ae -899779f3c31a20b76068ec8d59d97a64d2249588ddfd69dcbaac6bfaee8ce0ff3c5afc4e17c934ae7cd041b760eb555d -a5dac3d8f5fbef018509612e25d179f60d2a62451c76426bf546e9666fcdc73263d34aa6fa7e2bfd4c9947bbf5095eff -896900eeef9be2b2e755128e7b1c436af6fb3984f1e66c444bc15fcf3959013b4902c381f0eab1247f878a6ebd1f4ee0 -8cb17f4b0af2e9b2cbb56f46e6a5d6874ea0daf147aae77303020b4e592ddc92e0dd058def7da96258b3a68b223bf22d -a1b6d3f09a9fa7ecc021ab7c5396541895da6e9bf1f9a156c08fc6f2b815a57f18c337ccfe540b62d79e0d261facb2be -ae70888811434ef93da60aeee44f113510069fd21161e5bb787295492eb8df85103794663fc9305f04adcbcf11ff0c5e -a84bbc8624100acfae080ba8cfb48fd4d0229a60b62d070bd08fade709efc6914dc232d3f7bed76a59204f9252321aad -aea47d54652abd8ca213cfc623c8e30780f37b095b59ac4795252a29c2b6bc703a5203acff8831314478b8ee8771d4d7 -8dd438eb8be14935f759aa93021c2b24e1d588f7a162c42c90ec3a647b0ff857f60e24c0a8953eb7bb04e04be70f11ce -922b07b5469680a10e7532766e099896f4dc3d70c522d8add18f5f7765d4ddb840df109146607b51ceddd2189fa7b9c0 -83ef6ebd0ae6c569d580093e8b0b78daa964760556272d202d343e824c38eccb424262e5b7809d3c586f9e2e9c5c5f22 -97f98bd357db6e093e967fe180cf67ed09fa711580a5ad48f07cf095b2e8fabbe6319f97d1f15d62c0ec2227569d8dbf -a1953a4a22fe6c2beaf2a5e39666b0eb53018af6976e3a7aab5515550ff2efa89400605a43fb2c4ac1e51961dbd271d8 -a5cbd67f4c0bc98e20aa74c09e6f5fb6f42c08e59aaa477b4b4e61434c8884bc14f17cf11faecf46dc4b6c055affbad2 -87d96818f2c4f12fd7705cf4060a97bd28037c5ac0f0cc38f71189ec49361e438ce863e6617651977708094d5336d1da -85e7c2daae5fe59f8a1541c94df50402a671a17dbb8838113fa4b7aaff6114cf2bb5969410cf21e6a162857f2f7a83a8 -a19575083e1731bb04bb4a49414e97aaadb36d883aa993d1f6847db50007315444814740e67e10177a14e0e074fd4c7d -a00ebfb5bcc3a6da835078189038a1e56b7dab6be74332b5ff7440e53b0f9e1eb9973effecbbf37000021fcf50c7c1ff -8969d7943abd3b1375fdfc7d6124dde82b0f7193068ed6ec83bcf908734daf3487a6a30f7b322e54a4818ae5f86d91c0 -b959c8d210fa43af9b20d1fe0ea8c4921280eb4544ef6ea913309ff9d61c9327096707e84dc1662960519be8e7d080a4 -9011d8ac651c42e0cb03931a9e960f58e02524c6b666047525e3b9097e9f35fb2b4b278efcce2bd5ad463c6d7fd56694 -937e3b22ed0fcdbd9ea5a1b97b84bbe86b7f5b2de3866a930611112f2217f4ee7d9822c4ab1253823f77bceeae0c8e10 -828997e5d121f4c305e018a0a0ba338bd6a34a7b4dc3c5ceab098ee57490311c130e2c045b9238a83908d07098d9fc32 -8d114808eac0f2e1a942d80dad16756ec24f0276763cd6771acb6049472e05a9bb1d3bbd5957f092936b415d25c746b0 -a063c5c26267ae12887387cbebbe51fd31bc604630b3a6e8e177e71d4f26263be89112cd12d139dd4c39f55f0e496be0 -ab1e1582c8d67196d10f969eeb44e6e16214f1316aa4a2a821f65ba5834326da6cba04373eabfd3b3072e79e5c9717e6 -a17b1dbaa11d41457e71a9d45d032448091df7a006c1a7836557923ab1a8d7290ec92a7a02b7e2a29fcea8f8e374c096 -a1ed7198da3591771c7c6802a1d547cf4fcd055ca9010756d2a89a49a3581dfe9886e02ee08c4a2f00b2688d0600509a -af09aa60c0a185e19b3d99ffdc8c6196d8806169086c8ff577bf3801c8ab371e74165ba0f7329981e9252bfe965be617 -98c04cc8bb26ffce187fa0051d068977c8f09303a08a575175072744e0a5fb61191b1769f663a426c30d405515329986 -a542bf1c9c3262d488ea896f973d62923be982e572172e2461e0146190f2a531f62acd44a5e955a9f1e242b3e46d63ae -aef7b7f30efd50e4a66c87482386f39f095bff6108e68f74fd3bb92156c71c75757912b111060cdee46a6b3452eed657 -8afe1e0ccd00079702f16ab364a23bbbd3da1889d07c4f8cb04fd994bf9353216360dbd364492932bfe20b8b69ae8028 -9896c690999db3c08cd7b25efb1b912c3e0f976db98a3e830f086aef93222d06ce570a7b2babcd7c81d8f9955169669c -ac7bcab6a281468907ef1ea8a6c1cd624159c88839131bef6aa0c22f331fc87ec6128a2c2a333fb79df549e4587e1a12 -987935c08a30b099d19f96901315a2e60591baf898581c40bf5eddcda806ff24a4536e30ed1e6c0b128a83fc77b6e81d -a0a6945bbede3bb09a4a09ef27baa20619d3e15af5673b9350601bcebe952597c989870746cf75767ffb73b32c6c9c6f -b0f5590079f0a0302b08a0cc1b7a5f39cc6900c2a5cdc7baa333d8328a731b2df5dbb67e27a154d3c44ed1a795fc4adb -a7294bdeea210e528f277f3d50e89e6d79950494478998181ecb38de675020130256f2f2a075899170be964d478458b0 -8ab3041b895a631869b439d5599a66facba919226ca9b39d915f19d59f9fc82393ea781377e9bd3bcc5a310e41376914 -8da399b59151fd48b2579948bb82698e3c9804d70ec7d6f3cc7e82901f9f2de5ee850349a7d6f43e5e9ebd47bd78620f -80e8c32de83d1083916d768b11a982955614a345d26d85b457f2280ff6c52bb776958add7c1c8878f7d520d815b8e014 -81bbec7bd99d2917d2dcd8a288722fb33ad5a4bf5416fba8609fa215fb80e0f873535349e7dc287f892aa56eb9e39c4a -9665796fe04c8519206fba58496bc84a8b9113e7ea8e152b65f7f732e88beea271dc97b1ea420dbc8257cc4b18a77463 -a97e342aaaf693ddc87e02790278e4bb50117af4413cd703bdf3b7cad2d1facf31fde1303b43ab2e0265467474f97a8a -925549ebebed348886e37773b05cd8ad04906eca4536bfed951d1ee41b3d362ddc6e1a302c21ff3a2d1e70e95117922c -818fdf74d7903502101551bbf48d3c7819786b04b192d9e94362d2fcb85760d8b6f45165a5443aa5221bef400525ddb4 -a9d29de7e8fd31b59f4a087168d062a478b1329cd3c81c31e56de4fb40de7a5be9a5269ef0be452c487443a0b097dd50 -a85286ad573db4c9aa56221135da1e31d742e0f6ff01d6b159086d7258f78b08dad55ec8eb5c91ee9d3404b2eeb67e1e -92a79b37db5e777f9ebbebde24a95430a199e866e56597c7d0b0e7fb54c7b092c2f6cf61fb24470ddf250cf609898281 -8d79f5ca67ed67d52c82949af342a9fc60fb793c47c76d84b4863c550796fcae2dd59e285897c6fb96fe31cee1efa62c -8ad2e0bda03415ab86324992bb62dfa3612d2d003765bcad1468087c27971d08bdbae5252681f0115a184f4885d444e4 -a08815af979286538c31b4aa5ec805053790af1ca58a8c4341be51136d094a8a05e569d876a079033298ad355ccb7ca8 -b96c2978d0165d619d08281d295e90df78bc2375d0afbc3142ebff9c2cd4b0f0aa97a9a0e3740bc4dce0ff8a9fac8252 -b7752cd0e582f35ab0d0036ca9c0a9fe893a6ad325164d78d865a604a85d3d23729e0362553e8b8a3d51816beeaa30cf -99cef1fafc29e7adfe247c753c475ad4bda7a5f9558b79c86e8a65968ede67adb38dc30071925c9d66a13860027a6735 -b9f6c65af178c791b6137d71980651fb09cb5b42f268999c728c6e129985a9c7d77b3dc3b50751bd29ec9ee0b3111dfc -8d73ae61fff5be883a281782698075c5650083f00399992688738856d76d159803be0059fbd9dec48f4f0432f0590bbb -a8a4a2865226de9bbf19e12c7e75318439fa6cf1cbf344d5e79a8f363439d3bc5bcf4df91b54581e7866e46db04eaf0d -894582aeff222e145f092ba15c60d3207340c38f2c6792ee2ab4d82d50fb544ae366c2985cc2b6c2f970bcc5f4b46385 -956014ba2d20a056fd86cb8c7ceeab9a2c6f905dae24fc1c5278fa5b84335148ebdefec5dcde8eb9b084700724fc93d7 -af217fe2b654eff6d11a2a79fe0339a1d4cb3708b7be9f09d852158b5a44b4f9b04406d6d67c4f144fb6b69a41ae9d0f -a90752a784bc00df94d960e523f5596695d16a534fc806179e0f878fc0e82a91b25e758e91a165debd815dd1af5f1028 -a697606fb32979549ad822b31df8eaaf50de4ead984439a0a33e955937d326519bb9f62c8243ad37f764655f8d32cc80 -a3ad4a30922e45a3e665551e5611384f1c2d414f6fa806184b0c826af05f014dc872585e255543794ee41e43cdadd856 -b29c255843a82ea74a013bac6c36a694646e61e6b9cefc4c130e2ee261e3bb5da3e0fe3ee7e6fbb009deed0530bc1c82 -87e1cc7febefa829cf050aa2aea59385d1048f8617abba691f7ea9ef58eb90ad12eeb9c439af228b0e34897ba1cf1b47 -994d3222f89e9c8c154362190be7167c8c2662f0cfa9d50eb4d8175b255ff0de09dc548ee312fc8226963c8c16f43e8b -8f1a980be640820f2d1e953264ca4c30330878971669852be3d5d6b41c488be1628b935388bfa2bd4de484acb0fe661d -854d90d0721579c8c88e147a4aa83553c960617b18075f8224b975562dccb30b0e02e81fa9df7070f356a0eeffc3b14f -8e156da9d4330a03e32a25a2f0b861fd3ea5c719fa4f834119baab6e5fa5236a9baaf0d44147bf0841418900037f6eac -96586fc49e53a6799242ddf617000db5a0ad20c6cb1686af2102623d64a71aaddb8e468b15fa6d100d0384e448548db4 -b44d8d85c8df95d504f82d597f8c515866d4d4a326fa1b816dcc5bb0cc4ef1a52647aa5d2e84c62e194c01cae0885d21 -b75c43e676a7efd199f8b32ae31f176ec667e714df355e9eecee97246f72af5bef9c5b04c11e7e90fc37bb9163f957ec -a49835ac0565a79f6a9078cf0443c5be20561a68b448289589721fded55188583f1d301925a34eea647f90a6e66c6774 -b47c17ff6824a00b8f29df0adb7f06223208d062bd703b0f763c6eee4ae62d4217eef2da4f4dde33f0b469c2f2db9e42 -957cf039cea6f6d41e368e2bd0cf77315938a0738f15ed9ca342f0a28658b763659ac1d1a85ecb362f13de12b77bb582 -903a52f8d2439fa63f59e1e9aba864d87b0464ded63814474947112375236a6f84e8fa003cc4433c8208d80e05fbd1b0 -8afd524209ff08d1eb6312b078f7afeb8e1155af649e930ab711dedda226dc2db6b0354aab9652eea7f433f90015bf7b -a95c3c9277b11bc8fe191773bf567641be57c0549913b973fb18740ff9cd7b3f7ce198fa4dc1086b2b8a446012459193 -9455ce8163fce04aeff61e7808ef3aac4725e51404f0858fe5d39d7344f55dcc7871ca332aa5cb1a63a4399529e48907 -809fa35b6958f94e781f2c584438b33f5ed528a6b492d08960cf22ecf63ea3aa1e2d29bc879e17296e0a6cc495439cb6 -b0f50774de212dd33e5837f6b496556215c665437e657f674fc5117e5c07dadbd0d057e6ac4c42d50a8eb81edfebf315 -844c65e263891d0b2fea7db6934cc4b7fb6bee2c1d0b9ab4c47f2eb3e9c5d7197dad828d38c54139123740151420280b -b13c78c9efcbb3b28eb3fe0b971380b7d5151c80948a99cd93c78b4c3ab0e86df6226a64d91e0a2ea4a1c0a46bc0404e -90300a541decad460c348b8f4257f7a29687b2362ebee8d92fd03cc0e85b285ccb0ab1cb2ff5e29c5cc5295e351017cd -ac49b409ded770c6d74f6e70104c2cdc95b7b90609da0743c9923179e8e5201ead03becc0ab10d65b3d91a5be0d52371 -a257b815bd8289dfdfc21af218aaba12ccfd84ebf77642cc4cf744d9b0174ca0b0d7ab2a545c2a314fd5f63c140f41ab -a34778d8446e4d74d8fe33de64b2694ef1e50bc140e252af6eff3ce7b57acf8b6577a02ba94b74a8ae32e5113cf0a29b -ab9e935bcf0d8607e3d66f013d9bce7909962cb7a81174923db02dc89e485c2b1c33d6065bdc7bbbe0450b5c49fbe640 -94d2c5c5c309c9eac04be4636f61bc47fd9579b47aded57cc6c736fefb8dfd8f8a5de32210f7baf2052d04c0219d3b4b -b8dda9046ae265214086355101be3460421f7cd0ed01bde9c1621da510941d42bc93cd8060fd73f374fb1b0a5f38d45e -a6674649dab5f92ab9fa811d9da1d342cf89ff6eff13ad49f4d81de45438e81a384098d3ae5ccce4c67bda5dbe246d95 -8d619f7564677bacba29c346c4ef67c211f7a3a14c73433dd1a7692e16a7e2562f1d0532454af62fc04c2fd2bb1789b0 -a2b93d2fd4c707f5908f624a0fc889e20164d3c61850af9125f47a1719757a6ce6375aa1910eafa4c1e8b6e20c312775 -a07d5585447654d82817ef4d199984542328b238157976eb9a267f0bdb2229acc25aee510be68f65a312b68fdd9e0447 -8ef55cf95e2b24d8ec88e4136399a7763bd1b73d5e90ea45e9845123e9d39a625cc336e9b67988374b8ebcbc75f2ed21 -b62c1fc32e27c767c461411b02fe9aa44a86586e1427406f4ef0b346d077db91952abce79318b382ec75b7be23058cac -b252900345f5fa15a4b77fb6af6a2d04db16e878b7bd98005333f7f6e3c8e6e46cf38fc5d1b2bc399c5c2ff4af730dc6 -a4ab5ac0cc15d3d17b1747c6e3133d586870eae0a0d9c8fa7fd990ebd4fbb62e9090557ca2792a6bc6271856aa3c9a05 -8e706b3f2e902faee10b22742c6c33bea6f670a8937c243db96885143c1db5c979e33ab73a38359b52b8d668ccd092a9 -8a6792190ee6c959d79f60c22980ca140c638d88d75660adaf9bcbe6dc4692ab5f01e0c460170f09f74d5e582e85ff1f -97ffeedfc94c98ec85ea937e064d7b290a326838e62cebd407facd1ab4f08d9c0c109d79af7cb6170fccfa6c8243c127 -b79970b67c09453614ffd83a0c923c17f857c6ce3c87a356298f8351cab0def7ed83efd4f6638f48df67e07bef4ad9d8 -b90f1931c7cf1822cc0a97401119910cdfd0482daf09a4d7612e4e05046295cfb4cc50d5214b31676bb1a1c9d15f9c7f -922921ad813c01fb5d12fa7fb7ed8e0b0abbf7b19affa190b36013c55b88fe3c7df0ae663c970eec7725ba37b95a7cb7 -a124f33e7f28feabb4089a063a08d52b7395d24eecd06857a720439dd9414b7073bb86fbd0b04e7bfac62d3dc0fdb2f2 -b252fe50bc6677c004550f240fe670974a33ffe7191ed7675da6ac36c780c2f8d02be7da5d92cbe2d0ce90147847f8b1 -ae5f8c9c56070f919f3df2d2284348fa4b2e39881f7bc42c9b2f5b7cb1ebeef8ecac000f37329bbe04cc1680cefc7f4e -b432a4575caf7337f11eecfcbd34a6705d0f82c216301725ceae2b3c9df20fa53d1ebef65513e305013d1e0c2df522b6 -b7c016fbbc4614cdbb12db1c9ac41f9a45d5e5ce82594d568a30cd2c66c3cc9d91a2c959697b67c582a0913de661505d -8f6f3e5e0347dddc1b2a34ec0dbbbb7cafbf976f19c9c902efb5c1427d1bbd4b71abd9f3fba20dda75c35a39393c989f -b0042a1d33a1ee9fdf3fad2299b8d70c4f1862d8393b5ebe3ac2189a2c5a58bb826128cd7a39b70d524a6dd976097e26 -85297c4e8ae8d9b44c3fe51aa926c77d55db766c2a9f91b659040de36e34c9a4fc6f44380f8d61704498f6fd52395a49 -8c61a988b6a00fe5a277450f30bf6daa932e42a2eae844568e3babf8815e09311f3c352dae6eb2d57a98d16b7beb2d22 -990be28aaecd932e7edb2a97b9be2789a3905cb88737b1c79881302585801c69a3dd5fb230808b39db1352fc06e0b4a8 -82fd14bdb335aa46f022dfe0ed4d631911e6b6f5eefb10d11e9e2e02a7df55012ed8162249d10b58eb76ced5a7b06cda -ac39cb058df764e161db9c39b185f09aa210bddbd66f681f1697ddbe6b305735612d5dd321d3ffbb4876771bdb321e2f -858a3f7e57ccb81387caf8e89f9b6039e9aadeab06886d8688fe6427151a59ab2e77e85ba850c67d099965426c97779a -b57fb9ea623cec432946819937c6bded0b5d03c8c67b52b44a4b67d34adfb055e6cabca67a48e4d859b4be45162c5083 -b84d2990b563d6d7fe1f4c1894989db25b81745090b94b1fe2ef708ac3b2110ef93d647820b2a51fcf78e3f00fef5412 -817d85b9f5e1521733d2b1fa6d4f4957ac445dc803f97fc495e20b819b14e651332f9e0573d684b854fd47824c53f0e8 -b09e18e97e93a8523101af594422fb71afc5b8826002314269016fcc1b44002d91bcb7c90d923d460f0cc03bddfe9af1 -b867cbede82102de7cf6cd0dae68506869576eaa66c3fc806e73585310602682fc912dc37adf5ff6f0f34a07831735b1 -b1126255798368b692f2796a3470ed16e5ffdee2d8c9e0f7ee3d2e92950c3e6365c32895171c3494aff2a6d6356f7e25 -b05f0a0996dec16335c770a5df3f0b08e20020c838c2caaa1d3a4a2490ede98552f5de349de2ce6e4c4a839731d80919 -98c512bb91c8fa191120ddf5d63c88076581cf41e15eec3c168822f12b3dd0ce4d6df74a7e3093d3e35cad1cb3135421 -84ce38fd97f7f90012c2c1e59a67bf9f465a7ccfb6f308bdd0446cc82b8a26ff7c30e5c7cc375011718cad1b31adaa9f -93139db52c9fb96dee97a0825f21e34c5d6d36838e1e42f4d12d01eacbe94426c85a811fe16ca78e89e08f1c27383d28 -81454037b1e7a1765f67e4288b8742eebf6d864d9b0f508ab44fa3243168ce0ed30cb5f33dfcdb995cd2c2710ff97a6d -828deb2a26efb2ff1842f735e2cc27162360f619b6e3e27a85bedf384912d4726bb2759a3016937973092ece1bf90540 -87e5a7d4e7bd301078f625d9a99b99e6e8e1207c9f8a679f8ebbbfb467bfa0b5f7ef4a4d577c7d2670efa88221153012 -b9dc9d0ea48deee201e34379447bec789c8924aecd030eeb93db159af77eff230976ef60ea9f4b4a9e9e95c1f9f4284e -aa6528268d46bf0627d87d58e243d3ac34b863513c725908a2617e4c6a46ccb1d8c8334bd6dd0eea7ffebec44259dae5 -8d26c9ce07293f6a32a664d31e6df9a7ace47e6c38001635918efd9872aceab62de7757b13b783d422eb67bd28ce7bbb -b0d3ca88d9829a7459b89b0dcbdb8bbb5180b00d750bd959bd110f53c2dd5d4db554b6005c4765fbe7ec5903669e5ebc -a94d1c72bf3b2dc6bfebc9dee40f6a89a516b252bd9f4fad96f156e3dbfc151a9b8a02324d764c7656d59230a18eb61f -88996e79171e30b16505638d8ecb25afd875e5f3cc3e29860937f2b5e751c66e78dc77f744a0cc454a8a655142a93ffb -af4d94f342665fe7ecda318de6cf1bc1c40c37dd83d060fedaf827459728152b5f0e280286ff5e6a0012036f6715f53f -96beaa7a2d565ec14a4e5cb895d33624c69da56b75c8d06ac729cb6d0cb64470ed4f9b0387083cd827b1609c8cabde8c -96b773fa2fcb7377bf71a7e286f37f1f24ee42cba5b4f33903c4566e5e5bcc501ea360e3c8435749107c3de84e272d8e -a69ac6218454c3f40ad0beb48821a218fb0a4f33ebade986d2fffd9a3900d8cfa613bc71676c46cfeaa5f644d1f239a9 -857f139c08fcc45370f448ce3e4915bcb30f23daa4134407fc6d78efac7d718b2cd89e9a743eec7bf2cc0eccf55eb907 -adeeba36af137fd3c371a2adbefea614c3ae3a69f8755ce892d0dd7102fb60717f5245d30119c69c582804e7e56f1626 -afa97ca3548b35aeda6bfed7fbb39af907ed82a09348004d5705b4bb000173270ce44eb5d181819088aa5a2f20a547a2 -8423bd2d07073b0e87819b4e81997e4d3188b0a5592621a30981dc0a5a9d0578fde1638a364f015078a001afb00891c2 -b92e9d4ec3966981ee574695d6e4865810b8e75313e48c1e4bc5eebae77eb28740e97ecc3e5c42040f9eb1ee4b13b0ea -b07b218321d54cecfcd2ed54a5fd588a6be8d7a5b6a66dff7facfe061222c40553e076e57cbdfa0bdb08e0a009c94ba5 -a71e1ae4d6096eac9ea4c21f621c875423de7c620544e520fb6ec3cb41a78554aedd79493cbd2c2ba4f0387f902ddd2a -807cdac291246a02f60c8937532c8969e689b1cfe811f239bfdee0791e7aa0545e9686cfb9ed0c1df84748e5efa5e3da -a1faeb4504c057304d27d54fb3ec681462384a354a4f0b6c759d4fa313253a789250c6b0f44f751b0718592637438a19 -996bcd3215182d49f1cd15a05e1e0a4bf57e264400bf14f7253c6611d2571de7130cce81fd28e0411e0a80e9054f4f98 -89d15b38f14bcd46f4b2dcae82b0e7bf9a35e40bf57aa947e9c4a8f87a440b5cea95229708de08ca596762062c34aaa0 -8d8ddcaf79374c750b8b0b3d196acb6bb921e51b4619876a29d09161ba82a42271066187211ef746f9f40a5ca17b75f7 -a3dc7f70f3a6c7edc483e712770abbaa94bfa3174cfee872b2cc011b267e0ef9baa1ab49e4a6c6c30dbba0e0a1237117 -aa9e958bbdcb192b19c43fc6fd34afcd754949fdada98e9f4848e8db0e23acb27d19dd073c951a8819000f2356aa22e1 -a4714e45ec853eadfe5c3bee7f683b81f97857bbd7833192a48936dd1460aee68f700a21658658b74b737c4fecf90c7f -a1ecab4215c1892e4a8ff3405d710163875e5dfef8a8cb84f5cac4e317d89c7696e3f496ed1747ca6f52b304190f4ba1 -b9b48943eca3686219575026d395b969e6ff8159dc5317005df090e79d26901984e40ae4b1af060ed3ff6f42e0417d76 -9644b9f90a66edb0396abd8c00066886f978ebf56fc22081031fbc9ce371bf9b04aa5a4ef59e59319b3a05bb7fb88b43 -b2bb14f1c055a78596488e4e2d4135a6470c1ee43961952160b8498f674a4d23040606e937c02c1fc23dbd47e9bd4633 -8c61f2fce9a42b94a389c7e52d7d093fc011099d0f4914f6d6f05b631df7b88182826edf9bbb1225971a080ca5c0d15a -aa6a7b8499cc7d256043eacad18528d38bf3be970bea4c6d4cb886690280bdb373688ceba3e506471e1d9493dc76f3f4 -8127703363b3b35b06762c2353d4de82b7b85bb860db1028d3640f46bdb78f2d104fa77ee3e0d9db83833d2b12a966f8 -b7b01f5909f2c66ae0fab156be5d79954e3a304615e1fe55945049dd4bd95f973bb3821117eb54db7e9ed1ee9a527652 -8be47ba5dfe212420649193490838670c40540e0ea24adbab18c4a66e7ac3dcf94f068dec2533b60e08c1f64e7533e54 -905a6c7e24b86aa54a05c329a6b4616d335bb0b1f1e9987562eee0acf82ad302c7c44981a1dd6b24c6121ca12fb92996 -86969ccfd91deed93b355a2c21319e3bb08cc652b741463bf68c626b7ba2afce3f7cc397f2fb74588c2893477c948ae2 -b5a9d20eb12c331d0d300fd4b85b0ac0bb74573178a5fac8ec9dce5e95acba07fab444260355ece442a846737a2dcd1c -a13497c11df21b11fc1a63b0ffdcf7f432da4dc2c98f8d07d36da4fa68aceb57af2158088e5b05e334fe0f264aeb7a97 -882e4597cc66498a45e86a2ed9ee24652da4699af00ad35f73b5e74fde6ac3cee70630962d5ddd86162d4aaf11bbc11c -b748858c2bafa4a14ce44af35195e9c52aa75e109719243bbe278095acbfd6a7ae7e084caf8dae6939039b5a4e8fd675 -83a2e0524507e74f51fe976441108f8226ba1b3a33f4e16ec45c5661ce80cb1840a93d17122cb8ca9e0f80d14f69877d -846cd2946c93ee5f24243d9ebc69936b3a1a6d59f45fec6c79b1eddf15ce30a8e73ad03cf606ee66baea3d8ff115f70f -8d98d0a3a94f6efe158f8423c041b546416145c5c2254bfa157efea0d1c99fe58acc7df6424ef29f75960b18d664ea4e -a39fa47e4b79f54dbf59d0b1726f1e78bc219fcfc56ad238c84b4b610e7892ff1e65d537baf5118a32f5e2eb80d5ee0c -8c30969a4519131de5e30121c84c04f67b98c8ad109fa4710dd3149cae303d51778add3f258f0482f1c89c169824dffc -af7f80d141ceb78b4762015de17fef49d7ff6202d292e9604deb508272ee7569f7fd5be3b2438da1dfecf0c26533ef86 -97cf82f70128251944d79b8845506975405bd720e150d836205b048ff36ba8801eb74cdcc6425f28f6bc0acec0a81463 -8c276c876eb88688957d1868bf3a1462375e608ff72b49870a5dac82cbf6584e00e3f36f236f732348a47502ccf9539d -964765f1a5c8a41d8025ddf56dc01b78424703d8a64a4e5539e477cb2445cb541c70127c561e717256d13f91a830ba83 -a2aacd9e21b8c8efaf2319611addea1b9f41430aee42e7f2a640cc693aa395287cc8fdc2806b76b577d84fbd05378ead -ab11eabbf5be4345a77323a3b75f9ee93b011fd2a9d0154e88183cafe47f82a7888666af16b40d3cb677c94bcc755ff7 -a0bfe715a7af5a29b1b6148b8cbee585d2b49fa6ce59bcd173ea3bbc60d71a62f9da27ffcbbd5a6da75502112fe44d70 -902e6cc38ee42245103d90b65028a471bc7a48b825599d361aa81d8c56e0fcf9fbe8d4c13802040d2cfb85b7e022eea1 -8832e2b5014fdef4003bdbb87e3298fdbdbbe49673f6b66e2373f1cb2605f9c4af2cdf9bfd45d1993208681d29ee1c9d -a7d39d3fa1ec1e0c87730fa43d4900e91932d1cafb36c76b2934907becf7d15a1d84d7234591ad4c322b5a24673bba8d -836ed5f09d99624204aa3aa7ac601980fda223f3b4b96b4a8fb235c574a3545d518787c12f81bd5851987f2860d41886 -94235e94445e6086f6e9331923262070a4c2ed930ec519eabb8a30133bd4fc6debb99185f4b668431fae1b485c5c81b7 -9828ffe20b9405f117dac044159be2d3c6e2b50ecdd1651d6a73f7633e6e2a7ba3d783ae939973604446d3a1ef0fb20f -92f03dc365dfe9154743ca70e6dd2758f064e3286fc543cf8c50f68effdf7c554bd17b3507c6ff4127046d9bbb5522ef -91ed07df479d8eb3d31292a0e987672a7f3d45ecafe72935b7abbc3f23493605134ce573f309e226c9efe830b6868220 -93bee582661e6d6cefeff29002afc2f36dd2c13dbf33f0574c35b290ddc426170a5f7f196369ad592efcd72cfb6f8fc0 -89a51467d966f48fed15dea5a12dda54d0015f69e2169b5e34f44c7b5a5d4c282d6f138116a0cd06a8476980e420f8d8 -b8ccebc14b6679ba2399370848864f15f63512fd6139df7359b7b93e82c1007fd85137ecb0597294b46643e1a9e7ab5e -841fa301567fc57b2cd09508ce75326684e12bfb8add671dc208f579b2500b93d5b641e9f59bba798ed4ed1259757f7d -b3cb45c15eb00b4ccb7013299f761cb8fefc17adf6db50e9ecb8abe927a3bc7f28e359e64693813e078e1dac800ad55b -96e55d3b9f445f5679e34fa5425b3e87cb221cfbdd07f8353868c7f7f4ba388ee3841cb9a1d638583bc20d03a9d071f2 -a7dee9377de740270c5b57cf86699004ba8dc2766af56b388b5cb0814ec71bb99ecf43ee3d82a552733854ecc7def0fe -b129dfff23b3c1c95ddb214c4711961fcb129efe2b6557ec9e116ada909593d0d2eec2c628434493393c58c52aa86847 -aed2670e201cb3e38a8be3c86735a4d76255e1e5a4c67b91df6ed262d09c8d10b0a3891da3e6ab934058cc9a7178931b -b20b8921ae52e5b3c94fa3a8b46489044174f7b897779e7763d6eb419e808d76705b7e7ba5131576f425aa81b6b0de53 -a7e45bbc3ba1bc36617291ba7663806e247f1b57a89e31520c64a90cbf8d426cac2e2f381338baf78c8f92fdbbcb7026 -a99e651e73a507e9e663e2364fcc193ec77e8afdc08c2bed6ad864e49b537ec31e9114ee72291a7657899f2033a849e2 -af966033636c2e9e8280d173f556fe07f8b6940bbcf6b2df7e2165c30bea66cced2596f6c17ca7c1aa0e614174953ba9 -b69ca7a79e3d55ef21e0ebdc6f0c4bd17182d30cf6290cccca7d2551c91c12b966020d8e40e4ee4179488c9809c03ae4 -b981cd36244e035fef043f70b1d7188d7cd045b4de0581c459fc5730e10eb7f3d5893b54cc4243849c0855e4e621167a -b20fea858a36921b35a3051ce787b73f70fdecd3fef283c15a2eb1bffb1dcba5991eee4a047ce4e87802da923fd9457b -b040e6f2e56dc1860274c263d4045837456f74b354a679f6b5ea70919835ebe5d32bf1f519e218730096c98ff396dc9d -8d2dd60e702c923a7204b530e7d6c193c6f93ca648c4f7bb38f4edbeb0aaed84184213afafb8db6aeb9197c24364276c -95dfa7348709e43d71285b28a0bfad3ca805b6ed4ae99753e9f736c79d58a35a3a50b42760ccdd03eda50f6e59494968 -b8585632a13f18c139a411bb2f02df809591834d127cd1ff081e26d0abfe0e3fbb54abea26538b25a0dcb4d7e969590e -b46ba47858a29c6d523c9982660949567666daf2582b93393a4802a9e077eedbc0d49d454731696bc8e46ca50c7caa40 -84b756b901b98a4404e58d70f39f6ccac877146c866732ae65e7e82727448d1550343bf7cdff1bfd4ee1ed73793db255 -83e5be888eaf877a2c755897410865f64a6d1169a8ccf0336092f3932abab915e542ab75a35ffe016042340d581ee987 -8cb274fc39285aed451a7def72cfbf73168ee10be02affe355a2bf87cf361a81ad284e9334cf00c5bf99a13d9f75e116 -91ff6220924b94ae13f50eeac16a159232e4f16a73fbd5c22c0e185cd1998403904d36bad203baa82b85819ee4a8ac10 -87f46e08e09aea2ab37b55fc300689d9b58ff3e72f1cffe023386035888f714fac4673c7c5193d3f3f3c568c640694f0 -835d7d84ca7641e1b15095830114aa6072fe12260d2202456cafe2308c22651af9ffbcf6b7e56af97167dd0c4e2a4cf2 -91202183f79794f114fd9e3b9bd05553c0e8985919965101a57d97ef666b028863e6cea9735af016dc1864f1542dee51 -81ab2b02a9b0a490a74ae615ddd4fe560734c1bfdde6b8dd13303c1481ba0e8ab14473535a93cfe4e824a0ab29445f8c -8a32d73f4fc006551d4e2c61eec6130355ec9b8c39a65c24ec1edc00e80155ca83a8ef2455e892521a3d47634d82a987 -af70d7b8f13bc90193cc1cfb0c400c4224cf10f1887848aa93e6380f7087782fc41a159926ab53c53eb95c2383b1a849 -989bf42f9d357c51774f1c7c0f7c0c46a8cb7398a74497141c32685be098e38b4230ffe833a6d880ec391a35b1a747b6 -94cb6715ee95700020c630b8c19e35f231de970219bd7e6ba7ced01899197da473b6c45cacfab0d652ddaf547b4ea58c -b12e3331f1f7d7458393a785e22e9a5e1d1daea521b4e78c0ee8ca59b41ade1735a29820e18f6afb2f2c3c56fecc16b6 -ad4b7cf654349d136fb41fb0dd65b588199f68b462b05f5c4e5c2b468bfaa6c26329033e3c3f7873dc8ace89cf873ea5 -a3279969e1ab596df0559ffc5ac7a6dc849680354e01c3f4fd34c6413a3f9f046f89c1e1be0b315d8b6dfab3d23d5c14 -ac74cc5562836ed89d09a9ae6a3644c936d64bdda9e77659d9982f1be29541b03ef2723236d5465e398373ea19a4ccc6 -98138ebce1af531dd8b631b3e74c84f0c700355a2a9bde31e5e51bb10c8bbd766559c63f6041f4002568803fe08438e0 -9006445da131349fe5714e0777a4f82a82da343612589a0c1596393e8b6894ce1cf42784f95ff67a8384ffe1f1a4ad76 -88502a84a85e4ce54cfed297b5d355867cc770a8ffd0714a6f23b1ab320a9903c6e42809e034bb67dbf94c4fc0d9c790 -aa8b4bf123d1a6ccaa44b86be8f980005f2a0a388a76cb111b0e85cd072ef64167fb0c097c7b23c4bca64c0260f6cce0 -ad49eb35dfea9feabb513a78dd1152ad7eba22fbb02a80cefc494a7037699c8df81202dfec12acc1b9e33ad680cb72d2 -8694da730231b29afd5196371ddcb15b4dcc499574bdd063f4864ab80749833ea38ab8b0ca1629a367fe378e87a60a86 -8eca7b488e810c479e7e32e24b8afcd837f7df183fe4f621a0336b53a9ed77603c84bdc365d8be68179a32b71a1deb7e -8875cd3e23c7e1af55af1b091025a08255743984186770bcd43f30b4a58d175cfdf1984bad97a15e08dac2da27198c3d -abdafcf58ec72997e494d4714645f40d09dcd0fbd0733e640eca44eeea67c25bb0c270299c459991f2fae59d13b4f4d5 -8f040970141e61489284f3efd907705eae6ec757fe8e1d284eac123d313e9ac1e8dc14ae3f04d281e1effc49d5d2f51d -a7ff115f0d2dbf66c0e8770b3d05157b37357b9e33e9a447f0f3fa9da69ad04e371fd1e4848cfb9e8d05e3165bd969d8 -a39b1a8c39d317fcc97bf6c396e6ed4a85640aeeadbf45166bd02bc3bdfb6266509159c03afd492e642384c635b824c0 -a2e1b90f3dd2d0038eaa5be52127844ccf35d997143179d95ffd3749c0896398b130094d01eb1bb31ffe80ef34b42b48 -a2bbe31f89b0c3c375ffaf63c8b7831860a921d5e388eb7907dbf61f2601ea40db86bb3952ecaa26a5eca4317a848ff9 -87d885bb0f2ce04b40ce94d2557c15f1698dc652e938f9a2d69a73ccf4899e08eafa1a59a20cae92823795f5b94f04b9 -8f7746370f8a24a2889d351f3e36b8a7d60e75e50e8f5abeea7dafc75441e95915721654e61ceac51bb6f112780d352c -a7272847526ed3d9e0d0fea1d8685b07b5b908971490bf8a46748c8b1783c629b8644feb5bac772ae615daae383d5e72 -978c9aa2996d8bd6fda7e0393fa8b38747f8f99712427705c00f6e9a12c36f8d8b4cedb03fcb9867155cbddb5200e6e1 -a4dec4a2354b2b32434c5bcdc380bf84580c6f9940f94dc0498a5bfe89c675a0921e66b807a3d859a6059a464cb2a9ac -99459ddecc7abce437f68722dae556d8ffaf8ed974f459e52e6d4a64f176caa4d42c2f2ec57e8a5b5f2034638e8acb0a -928c68c0c9213fe6258ab5bb0c693d97203d15da359784de7824dec143212da57d062a1fc70a79172cee31adc7aff382 -aad3f318f1622ea87e12541dfd982d71629b8f1ded4c301f9f6b6af9432716ad057773c33bdaa6f15dc151b0ee4505ea -8eb8e978f149a983fd6ad01773f9aacf57bd0cc622d8a301e404184b37e610123dd081faeda571a0ab1f149a3960af10 -851e7191d7b94bd422bcece5b92609fc1b1c8556229bc53e32963b2d2fd1cacd8ce5da9040b599eca6e610540f8a7987 -9414157fe9d50e5a0b5a7397417681bcb3a651eec1cab63f2a88d5df68ab1fef6e4c1d7ba657cbaf241a7cb790297633 -b5cb2dafdc5408959780754a58b2da55b2a9136672ebca42f34da4e329ddc89360e7218cde3efdbf784ddb390deacc57 -ac6b70f65503a8e94b773fda3e72615745824930114fe72b6d833484285462392617c1b2eea4a250fedbee88f503f3ba -b0829a5312f9ac6c06fddee2f835a3452fe994f6d42c9edfc390d7d5b3240ca544433b544cbbddd6516b38a6d5d7c21d -95f8e2c59905957e34d53be3d6fb85732f834e2cb9ab4c333fea2f502452a87ccd035fc9075d7c0bd8530bb0a0c96527 -b93f279b7045f2d97c674495f6e69a3e352f32f43cc60300193b936c2850b2805c15457251f7e3f633f435cb2b60405c -915abf16cba1a0b655b92a8a70c03e7fb306b86f3bbfb66967ca63e64c003b59c7a5953675efa4fa0bce9bed536b6700 -ac2047f50a319d09df1ec44d71afdcec5ac3bd2765dc98aba347734aa780863545df9f6d71214d443e3f37edc0dae45a -ad49c74ddb24c8a26b14ec08bc807313c77c5967fbb36237f55994d7511bbac8d7e7b9b8ec53eb1b3b066989f078dbd9 -961483105f605e959213fe9e8a52b76dac62d7efd2319ec71fc4e92d68fbe44cd2f65d7adefb2eb64d591b91648b8085 -b67fcafc97d8df2b3075bbff7b3d7471dbf1f3048f309e55d5e2c5bcbc7a73aebcb0697859be9f387cbc7ce98041e154 -8da70ac16468cab6066992389cb37c79ff5e0babbe67d76878aef9408b9597a3dc2eb5de87428bc761a0d78957b0eb28 -aec0ce89770d299b631f15ae12f94b1e1014ac57d38fcf037c2c7712d770d074affa06e97c60691bad8733874b6ad2ed -8b702c85fa4c915a09fc86507f44d7aeda0993b77af87780d70cc98d580c6e996b64b7c16cdb4dd4562cb0f75da36ee7 -aaeb43aa472aac2253e211fd1066c3a5422ea041cef20168702d0618a1a742a44f7fb30a76677640fea1a24e7fae1996 -a8820e92825d6e02b9b4ad5ebc86161d3244cddd3d244333ba1576b6ae10948145b68d9e926bf6b7a2c25dab4cf43f3e -8ffdae28a1f1d15d7ffa473628a66ee9a739073f59ba781248286b39cb8f7255f66d62337064246713cbb5017e615174 -adfc5dd142b7911326d8424881d5d92006f3b17de4cce91674d6ea37f00fbb266c791ac13f6c7a0f61d04f2a952e6a04 -87f98982444bf661f539bec73a10256f079a4baa88a1cea0351ae3de929e1c500485b2d1b5d933063cd7d9123d5050e4 -8f217ba4dd404c5ee384f0c9a126686db001ff0344c01c82174c5e5ef89d1a241b146008c534b13a0da6c8afe7450fbb -afc85476dddaf1cbb4ba8b22186789f3818c7964f9f613e55010278800cd95422702248bdf9c73760702ef24854795ec -a59e0f6ac2ccdfbd01f002008034390c0ea78716f5e0de4e474e3558755705c9c7afb6e3c5c4370e7bbc85958a9c7a63 -97c0695c58d792ec31d9b86d3b2fc1382f0855057b24d5f6a54c41f76f9e2f52882cadc89a8b2f121530e7f1393faa95 -8e49112de0b2649c08a96cf737af68fa8055f1af594846a2d0534c94df6f926f200405edaa6e6ac9db7e380707a2571d -99a1bd83a7ac5f8d77ddf044c80ebfc5745b998714696d67b94d185c97e9d6db989bacac646d9def463127a8b2febc00 -aba80725f9f9f7abe10760eca73ba427ca8df864a157122eb9af828a05b0199de3add02019a297750bdab5380e505c58 -ae18f62573275c1eb268f74c5e54e8958547f9e7d1d36a05b084eb53e5704fafe2200b8aff95cc7e9af5be2391c42b7c -908b8031d09d22b2aefeaa876a998e0a97c7a1070aad9e9c97836cc5aa6d2d5ef94230e1222074837b5e21b4e6490f01 -b3132282e8b41ca6789ec5c43c1fecf3a65b8eefbc2f3d10f746a843b9ba4ce6db664678e75e424f7b11a00c1440de15 -a1eb49440cc106ebc09cf198c93e8070271eb5a936d31c04858a2b311a037350100c7957d5545c9653f396aa968b91f4 -81df6ad1bdd5eee4cc2f94318467b8602d15cc1be2b48b09ade12cc46ee05cbaaf77a20397e5015030b1f1db5dd9dac0 -87236c68a2a93c8442d15d7f1d1dc01d1fd123439c183e1d843f4ddd2bcf638c128f66f1ef9b710e5d1f64a52726007a -84f2e7f85563bb2f61b10a712c7605d63f79af5be0dba056814fd3efebc20e9c53227c56577b72c68d185571b775eff6 -a36d4ae06688ece2927aeb2c7f058a3cd2aa1de1601282d4e688e1d76ef20728b892928deda2314eba41675eba3912f1 -b8326dcbcdcfce017b263c456c47692fb476c4225c95981666fff0b7d4522fc23b7f12273f0f47cf0442662124e6648f -84c66463ab277cda2cc7007d0509269e89cdd41c5e0d3773a92615f0fc5da63811186b05d7a11088048a5d4834a7e0df -b20d3571d970712ef4699b0e7034fd269c361f53e1572e2ea2676b4245e992d43b8b5931a801439a44d977a988cc360b -94dba6007e6d4998ca1eb84aa8e2a7e9f5c164b9d80df2825f2208ce5640a05aacac2e4f08918268990f43ae1ccab69a -a1c25f0b3ef9d1982153207570d9ce8d692e1b6963b509958dc4d9bcd80074bb221c46804a6d9a29e76149cc7787c282 -8857748fcdab1199fc96084323a81d3bd8b5a7f0b1abc5bc3b5252a19268344e2e7d2d086c90fc9b5fa4b92feedb93a4 -8b9c1d841447354b6c086549e4d1d435ab64c13933488c34bc30f0f6eb36c5c5b838b7b6bb018542247edd1ada091045 -8f5b655416da0e719a204fc567e93792c301acb4374cf7bbabc6ce51dbeaaadfd75c2db0e16ce073ab8e91fd3d7ea9d4 -90f2846b19be46a75c5cd0cafefcf9192e6fd80c479e8d6320c4b8d8d7d96703c9e77ff31a67afa9858e6b7bde1f7cce -a53e383947fd98aa1a55ac956214b46b20a52758461e8ba41341a23a835ebb713038bf048edb1202bbfd0b56a96bf292 -9542d7debbcfb9cda6fa279c699a7b655c03b9a9b456a5d3cfc41a826c94eafa43e01155a29e39ff0bcd965f4c0c512d -a43792864ec5fc549f7afc02622454afc0e425c310c4039ba615067243ebb26a4c7ebfd19bd4d57ff412a4bb2a7958a0 -b85123950e30c048465bf32365d24a5d4b21fffc6183cdbf71643a07b87463989b72dd9a6a47f134856f704909a6b38f -944ea689aec1376f855c0bc9c51378ad06ff758a2c075b95a60b535b88b36eca0be11e4edb5152e98cb2137d6e749f27 -a6bef52cda22325e4c62d323e2a0e3fa91c5552fcfce951edfd52ad6f652bfdcc2341f1cd349e6b5d447924dc569bfe2 -b56bff8ffe981bfcb30791836da10b87f2ccbe17ed969e7f7a650af07d27ae0223805b1264d985148208483be50578a6 -8b209cac898dd580c82d854a553e2517497ad1a4cd198e1360b8b50639b380aee70ee4b87625d9b2278228ff644cd25c -877cce233fec74c7158b3c5bf108365e98238418b8a71f058f1aca44a0fd3a1021e3e9025bd11fe244d9fe0f5034ce7f -b1b871aeedb03d6f6accc99816b89f5958178738d8d8cd9717527d04363c80fdb5f6848122ae19fdbc450cfa11e753c8 -858aca51b9e5b0a724e88688d5124eb24c9faf01a3d465e74d31de6da315f311143f22f60201ea09f62c92f61f09d889 -8521d409615dfc8c8289e00f6aaa6297c2c4e1439b25952afd76aac641b81c70b9cef07cd58c1c0198382bddd2bd8544 -88647c3e41666b88acca42505f1f5da226937e0522b538fe0cebb724e9a99730ca2522989e94a96cac94109aef675c0f -b417fdaf719caf38854e89ce52031b30ce61a632e6c3135adec9002280e022d82ab0ea4ac5ebdb21f1f0169e4c37bcda -9367a6feb5e23ea2eab8ddd5e7bdf32b4d2419fad1c71a1ed327b77362d8942dad971a1c2e6f7073885149cdf0a0c339 -a71c5c08d50c57d094d6a4f02e97d3799bada92f238ffc07bd223bbe8379507b7310d20b28f5bbbf331e5e153515e491 -9630a9a3bcb044b51299c4d3d3388a4ff47308dd27be3229601985478c0f6b55faa7e20815d8694f910611396a9d0d45 -b0bfaf56a5aa59b48960aa7c1617e832e65c823523fb2a5cd44ba606800501cf873e8db1d0dda64065285743dc40786e \ No newline at end of file diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index b419809795c..dce2cc7d105 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -95,9 +95,6 @@ public class PrecompiledContractsTest extends BaseTest { private static final DataWord totalAcquiredResourceAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000001000015"); - private static final DataWord kzgPointEvaluationAddr = new DataWord( - "000000000000000000000000000000000000000000000000000000000002000a"); - private static final String ACCOUNT_NAME = "account"; private static final String OWNER_ADDRESS; private static final String WITNESS_NAME = "witness"; @@ -1168,54 +1165,4 @@ private static byte[] encodeMultiWord(byte[]... words) { return res; } - @Test - public void kzgPointEvaluationTest() { - VMConfig.initAllowTvmBlob(1); - - PrecompiledContract contract = - createPrecompiledContract(kzgPointEvaluationAddr, OWNER_ADDRESS); - Repository tempRepository = RepositoryImpl.createRoot(StoreFactory.getInstance()); - contract.setRepository(tempRepository); - - byte[] versionedHash = - Hex.decode("015a4cab4911426699ed34483de6640cf55a568afc5c5edffdcbd8bcd4452f68"); - byte[] z = Hex.decode("0000000000000000000000000000000000000000000000000000000000000065"); - byte[] y = Hex.decode("60f557194475973322b33dc989896381844508234bfa6fbeefe5fa165ae15a0a"); - byte[] commitment = Hex.decode("a70477b56251e8770969c83eaed665d3ab99b96b72270a4" - + "1009f2752b5c06a06bd089ad48952c12b1dbf83dccd9d373f"); - byte[] proof = Hex.decode("879f9a41956deae578bc65e7133f164394b8677bc2e7b1356be61" - + "d47720ed2a3326bfddebc67cd37ee9e7537d7814afe"); - - byte[] data = new byte[192]; - System.arraycopy(versionedHash, 0, data, 0, 32); - System.arraycopy(z, 0, data, 32, 32); - System.arraycopy(y, 0, data, 64, 32); - System.arraycopy(commitment, 0, data, 96, 48); - System.arraycopy(proof, 0, data, 144, 48); - - Pair res = contract.execute(null); - Assert.assertFalse(res.getLeft()); - Assert.assertArrayEquals(DataWord.ZERO().getData(), res.getRight()); - - byte[] data1 = Arrays.copyOf(data, data.length); - data1[0] = 0x02; - res = contract.execute(data1); - Assert.assertFalse(res.getLeft()); - Assert.assertArrayEquals(DataWord.ZERO().getData(), res.getRight()); - - byte[] data2 = Arrays.copyOf(data, data.length); - byte[] z2 = Hex.decode("0000000000000000000000000000000000000000000000000000000000000066"); - System.arraycopy(z2, 0, data2, 32, 32); - res = contract.execute(data2); - Assert.assertFalse(res.getLeft()); - Assert.assertArrayEquals(DataWord.ZERO().getData(), res.getRight()); - - res = contract.execute(data); - byte[] expected = Hex.decode( - "0000000000000000000000000000000000000000000000000000000000001000" - + "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); - Assert.assertTrue(res.getLeft()); - Assert.assertArrayEquals(expected, res.getRight()); - VMConfig.initAllowTvmBlob(0); - } } diff --git a/framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java b/framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java deleted file mode 100644 index 8cabd7825ef..00000000000 --- a/framework/src/test/java/org/tron/core/zksnark/KZGPointEvaluationTest.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.tron.core.zksnark; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThrows; -import static org.mockito.Mockito.mockStatic; - -import java.util.Arrays; -import lombok.extern.slf4j.Slf4j; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.MockedStatic; -import org.tron.common.crypto.ckzg4844.CKZG4844JNI; -import org.tron.common.crypto.ckzg4844.CKZGException; -import org.tron.common.crypto.ckzg4844.CellsAndProofs; -import org.tron.common.crypto.ckzg4844.ProofAndY; -import org.tron.core.exception.TronError; -import org.tron.core.zen.KZGPointEvaluationInitService; - -@Slf4j -public class KZGPointEvaluationTest { - - @Test - public void testVerifyBlobKzgProof() { - KZGPointEvaluationInitService.initCKZG4844(); - - byte[] blob = new byte[131072]; - blob[0] = 0x01; - byte[] commitment = CKZG4844JNI.blobToKzgCommitment(blob); - byte[] expectedCommitment = - Hex.decode("a70477b56251e8770969c83eaed665d3ab99b96b72270a41009f27" - + "52b5c06a06bd089ad48952c12b1dbf83dccd9d373f"); - Assert.assertArrayEquals(expectedCommitment, commitment); - - byte[] proof = CKZG4844JNI.computeBlobKzgProof(blob, commitment); - byte[] expectedProof = - Hex.decode("b7f576f2442febaa035d3c6f34bbdad6acebcaec70236ff40b3373b" - + "d2ca00547d3ca7bb1d0ed3e728ca9dab610a4cfa4"); - Assert.assertArrayEquals(expectedProof, proof); - - boolean isValidProof = CKZG4844JNI.verifyBlobKzgProof(blob, commitment, proof); - Assert.assertTrue(isValidProof); - - byte[] z = - Hex.decode("0000000000000000000000000000000000000000000000000000000000000065"); - byte[] y = - Hex.decode("60f557194475973322b33dc989896381844508234bfa6fbeefe5fa165ae15a0a"); - ProofAndY proofAndY = CKZG4844JNI.computeKzgProof(blob, z); - byte[] expectedZProof = - Hex.decode("879f9a41956deae578bc65e7133f164394b8677bc2e7b1356be61" - + "d47720ed2a3326bfddebc67cd37ee9e7537d7814afe"); - Assert.assertArrayEquals(y, proofAndY.getY()); - Assert.assertArrayEquals(expectedZProof, proofAndY.getProof()); - - CellsAndProofs cellsAndProofs = CKZG4844JNI.computeCellsAndKzgProofs(blob); - byte[] blockCells = Arrays.copyOfRange(cellsAndProofs.getCells(), 0, 2048); - byte[] blockProof = Arrays.copyOfRange(cellsAndProofs.getProofs(), 0, 48); - long[] cellIndices = new long[1]; - boolean isValid = - CKZG4844JNI.verifyCellKzgProofBatch(commitment, cellIndices, blockCells, blockProof); - Assert.assertTrue(isValid); - - long[] errorCellIndices = new long[2]; - errorCellIndices[1] = 1; - CKZGException expectedE = new CKZGException(1, - "Invalid cellIndices size. Expected 1 bytes but got 2."); - try { - CKZG4844JNI.verifyCellKzgProofBatch(commitment, errorCellIndices, blockCells, blockProof); - } catch (Exception e) { - Assert.assertEquals(CKZGException.class, e.getClass()); - CKZGException exception = (CKZGException) e; - Assert.assertEquals(expectedE.getError(), exception.getError()); - Assert.assertEquals(expectedE.getErrorMessage(), exception.getErrorMessage()); - } - - try { - String testSetupResource = "/kzg-trusted-setups/test.txt"; - CKZG4844JNI.loadTrustedSetupFromResource( - testSetupResource, KZGPointEvaluationTest.class, 0); - } catch (Exception e) { - Assert.assertEquals(RuntimeException.class, e.getClass()); - Assert.assertEquals( - "Trusted Setup is already loaded. Free it before loading a new one.", - e.getMessage()); - } - - KZGPointEvaluationInitService.freeSetup(); - - try (MockedStatic mock = mockStatic(CKZG4844JNI.class)) { - mock.when(CKZG4844JNI::loadNativeLibrary).thenThrow(new RuntimeException()); - TronError thrown = assertThrows(TronError.class, - KZGPointEvaluationInitService::initCKZG4844); - assertEquals(TronError.ErrCode.CKZG_INIT, thrown.getErrCode()); - } - } -} diff --git a/framework/src/test/resources/kzg-trusted-setups/test.txt b/framework/src/test/resources/kzg-trusted-setups/test.txt deleted file mode 100644 index 5ecccf5e5e5..00000000000 --- a/framework/src/test/resources/kzg-trusted-setups/test.txt +++ /dev/null @@ -1,8259 +0,0 @@ -4096 -65 -a0413c0dcafec6dbc9f47d66785cf1e8c981044f7d13cfe3e4fcbb71b5408dfde6312493cb3c1d30516cb3ca88c03654 -8b997fb25730d661918371bb41f2a6e899cac23f04fc5365800b75433c0a953250e15e7a98fb5ca5cc56a8cd34c20c57 -83302852db89424d5699f3f157e79e91dc1380f8d5895c5a772bb4ea3a5928e7c26c07db6775203ce33e62a114adaa99 -a759c48b7e4a685e735c01e5aa6ef9c248705001f470f9ad856cd87806983e917a8742a3bd5ee27db8d76080269b7c83 -967f8dc45ebc3be14c8705f43249a30ff48e96205fb02ae28daeab47b72eb3f45df0625928582aa1eb4368381c33e127 -a418eb1e9fb84cb32b370610f56f3cb470706a40ac5a47c411c464299c45c91f25b63ae3fcd623172aa0f273c0526c13 -8f44e3f0387293bc7931e978165abbaed08f53acd72a0a23ac85f6da0091196b886233bcee5b4a194db02f3d5a9b3f78 -97173434b336be73c89412a6d70d416e170ea355bf1956c32d464090b107c090ef2d4e1a467a5632fbc332eeb679bf2d -a24052ad8d55ad04bc5d951f78e14213435681594110fd18173482609d5019105b8045182d53ffce4fc29fc8810516c1 -b950768136b260277590b5bec3f56bbc2f7a8bc383d44ce8600e85bf8cf19f479898bcc999d96dfbd2001ede01d94949 -92ab8077871037bd3b57b95cbb9fb10eb11efde9191690dcac655356986fd02841d8fdb25396faa0feadfe3f50baf56d -a79b096dff98038ac30f91112dd14b78f8ad428268af36d20c292e2b3b6d9ed4fb28480bb04e465071cc67d05786b6d1 -b9ff71461328f370ce68bf591aa7fb13027044f42a575517f3319e2be4aa4843fa281e756d0aa5645428d6dfa857cef2 -8d765808c00b3543ff182e2d159c38ae174b12d1314da88ea08e13bd9d1c37184cb515e6bf6420531b5d41767987d7ce -b8c9a837d20c3b53e6f578e4a257bb7ef8fc43178614ec2a154915b267ad2be135981d01ed2ee1b5fbd9d9bb27f0800a -a9773d92cf23f65f98ef68f6cf95c72b53d0683af2f9bf886bb9036e4a38184b1131b26fd24397910b494fbef856f3aa -b41ebe38962d112da4a01bf101cb248d808fbd50aaf749fc7c151cf332032eb3e3bdbd716db899724b734d392f26c412 -90fbb030167fb47dcc13d604a726c0339418567c1d287d1d87423fa0cb92eec3455fbb46bcbe2e697144a2d3972142e4 -b11d298bd167464b35fb923520d14832bd9ed50ed841bf6d7618424fd6f3699190af21759e351b89142d355952149da1 -8bc36066f69dc89f7c4d1e58d67497675050c6aa002244cebd9fc957ec5e364c46bab4735ea3db02b73b3ca43c96e019 -ab7ab92c5d4d773068e485aa5831941ebd63db7118674ca38089635f3b4186833af2455a6fb9ed2b745df53b3ce96727 -af191ca3089892cb943cd97cf11a51f38e38bd9be50844a4e8da99f27e305e876f9ed4ab0628e8ae3939066b7d34a15f -a3204c1747feabc2c11339a542195e7cb6628fd3964f846e71e2e3f2d6bb379a5e51700682ea1844eba12756adb13216 -903a29883846b7c50c15968b20e30c471aeac07b872c40a4d19eb1a42da18b649d5bbfde4b4cf6225d215a461b0deb6d -8e6e9c15ffbf1e16e5865a5fef7ed751dc81957a9757b535cb38b649e1098cda25d42381dc4f776778573cdf90c3e6e0 -a8f6dd26100b512a8c96c52e00715c4b2cb9ac457f17aed8ffe1cf1ea524068fe5a1ddf218149845fc1417b789ecfc98 -a5b0ffc819451ea639cfd1c18cbc9365cc79368d3b2e736c0ae54eba2f0801e6eb0ee14a5f373f4a70ca463bdb696c09 -879f91ccd56a1b9736fbfd20d8747354da743fb121f0e308a0d298ff0d9344431890e41da66b5009af3f442c636b4f43 -81bf3a2d9755e206b515a508ac4d1109bf933c282a46a4ae4a1b4cb4a94e1d23642fad6bd452428845afa155742ade7e -8de778d4742f945df40004964e165592f9c6b1946263adcdd5a88b00244bda46c7bb49098c8eb6b3d97a0dd46148a8ca -b7a57b21d13121907ee28c5c1f80ee2e3e83a3135a8101e933cf57171209a96173ff5037f5af606e9fd6d066de6ed693 -b0877d1963fd9200414a38753dffd9f23a10eb3198912790d7eddbc9f6b477019d52ddd4ebdcb9f60818db076938a5a9 -88da2d7a6611bc16adc55fc1c377480c828aba4496c645e3efe0e1a67f333c05a0307f7f1d2df8ac013602c655c6e209 -95719eb02e8a9dede1a888c656a778b1c69b7716fbe3d1538fe8afd4a1bc972183c7d32aa7d6073376f7701df80116d8 -8e8a1ca971f2444b35af3376e85dccda3abb8e8e11d095d0a4c37628dfe5d3e043a377c3de68289ef142e4308e9941a0 -b720caaff02f6d798ac84c4f527203e823ff685869e3943c979e388e1c34c3f77f5c242c6daa7e3b30e511aab917b866 -86040d55809afeec10e315d1ad950d269d37cfee8c144cd8dd4126459e3b15a53b3e68df5981df3c2346d23c7b4baaf4 -82d8cabf13ab853db0377504f0aec00dba3a5cd3119787e8ad378ddf2c40b022ecfc67c642b7acc8c1e3dd03ab50993e -b8d873927936719d2484cd03a6687d65697e17dcf4f0d5aed6f5e4750f52ef2133d4645894e7ebfc4ef6ce6788d404c8 -b1235594dbb15b674a419ff2b2deb644ad2a93791ca05af402823f87114483d6aa1689b7a9bea0f547ad12fe270e4344 -a53fda86571b0651f5affb74312551a082fffc0385cfd24c1d779985b72a5b1cf7c78b42b4f7e51e77055f8e5e915b00 -b579adcfd9c6ef916a5a999e77a0cb21d378c4ea67e13b7c58709d5da23a56c2e54218691fc4ac39a4a3d74f88cc31f7 -ab79e584011713e8a2f583e483a91a0c2a40771b77d91475825b5acbea82db4262132901cb3e4a108c46d7c9ee217a4e -a0fe58ea9eb982d7654c8aaf9366230578fc1362f6faae0594f8b9e659bcb405dff4aac0c7888bbe07f614ecf0d800a6 -867e50e74281f28ecd4925560e2e7a6f8911b135557b688254623acce0dbc41e23ac3e706a184a45d54c586edc416eb0 -89f81b61adda20ea9d0b387a36d0ab073dc7c7cbff518501962038be19867042f11fcc7ff78096e5d3b68c6d8dc04d9b -a58ee91bb556d43cf01f1398c5811f76dc0f11efdd569eed9ef178b3b0715e122060ec8f945b4dbf6eebfa2b90af6fa6 -ac460be540f4c840def2eef19fc754a9af34608d107cbadb53334cf194cc91138d53b9538fcd0ec970b5d4aa455b224a -b09b91f929de52c09d48ca0893be6eb44e2f5210a6c394689dc1f7729d4be4e11d0474b178e80cea8c2ac0d081f0e811 -8d37a442a76b06a02a4e64c2504aea72c8b9b020ab7bcc94580fe2b9603c7c50d7b1e9d70d2a7daea19c68667e8f8c31 -a9838d4c4e3f3a0075a952cf7dd623307ec633fcc81a7cf9e52e66c31780de33dbb3d74c320dc7f0a4b72f7a49949515 -a44766b6251af458fe4f5f9ed1e02950f35703520b8656f09fc42d9a2d38a700c11a7c8a0436ac2e5e9f053d0bb8ff91 -ad78d9481c840f5202546bea0d13c776826feb8b1b7c72e83d99a947622f0bf38a4208551c4c41beb1270d7792075457 -b619ffa8733b470039451e224b777845021e8dc1125f247a4ff2476cc774657d0ff9c5279da841fc1236047de9d81c60 -af760b0a30a1d6af3bc5cd6686f396bd41779aeeb6e0d70a09349bd5da17ca2e7965afc5c8ec22744198fbe3f02fb331 -a0cc209abdb768b589fcb7b376b6e1cac07743288c95a1cf1a0354b47f0cf91fca78a75c1fcafa6f5926d6c379116608 -864add673c89c41c754eeb3cd8dcff5cdde1d739fce65c30e474a082bb5d813cba6412e61154ce88fdb6c12c5d9be35b -b091443b0ce279327dc37cb484e9a5b69b257a714ce21895d67539172f95ffa326903747b64a3649e99aea7bb10d03f7 -a8c452b8c4ca8e0a61942a8e08e28f17fb0ef4c5b018b4e6d1a64038280afa2bf1169202f05f14af24a06ca72f448ccd -a23c24721d18bc48d5dcf70effcbef89a7ae24e67158d70ae1d8169ee75d9a051d34b14e9cf06488bac324fe58549f26 -92a730e30eb5f3231feb85f6720489dbb1afd42c43f05a1610c6b3c67bb949ec8fde507e924498f4ffc646f7b07d9123 -8dbe5abf4031ec9ba6bb06d1a47dd1121fb9e03b652804069250967fd5e9577d0039e233441b7f837a7c9d67ba18c28e -aa456bcfef6a21bb88181482b279df260297b3778e84594ebddbdf337e85d9e3d46ca1d0b516622fb0b103df8ec519b7 -a3b31ae621bd210a2b767e0e6f22eb28fe3c4943498a7e91753225426168b9a26da0e02f1dc5264da53a5ad240d9f51b -aa8d66857127e6e71874ce2202923385a7d2818b84cb73a6c42d71afe70972a70c6bdd2aad1a6e8c5e4ca728382a8ea8 -ac7e8e7a82f439127a5e40558d90d17990f8229852d21c13d753c2e97facf077cf59582b603984c3dd3faebd80aff4f5 -93a8bcf4159f455d1baa73d2ef2450dcd4100420de84169bbe28b8b7a5d1746273f870091a87a057e834f754f34204b1 -89d0ebb287c3613cdcae7f5acc43f17f09c0213fc40c074660120b755d664109ffb9902ed981ede79e018ddb0c845698 -a87ccbfad431406aadbee878d9cf7d91b13649d5f7e19938b7dfd32645a43b114eef64ff3a13201398bd9b0337832e5a -833c51d0d0048f70c3eefb4e70e4ff66d0809c41838e8d2c21c288dd3ae9d9dfaf26d1742bf4976dab83a2b381677011 -8bcd6b1c3b02fffead432e8b1680bad0a1ac5a712d4225e220690ee18df3e7406e2769e1f309e2e803b850bc96f0e768 -b61e3dbd88aaf4ff1401521781e2eea9ef8b66d1fac5387c83b1da9e65c2aa2a56c262dea9eceeb4ad86c90211672db0 -866d3090db944ecf190dd0651abf67659caafd31ae861bab9992c1e3915cb0952da7c561cc7e203560a610f48fae633b -a5e8971543c14274a8dc892b0be188c1b4fbc75c692ed29f166e0ea80874bc5520c2791342b7c1d2fb5dd454b03b8a5b -8f2f9fc50471bae9ea87487ebd1bc8576ef844cc42d606af5c4c0969670fdf2189afd643e4de3145864e7773d215f37f -b1bb0f2527db6d51f42b9224383c0f96048bbc03d469bf01fe1383173ef8b1cc9455d9dd8ba04d46057f46949bfc92b5 -aa7c99d906b4d7922296cfe2520473fc50137c03d68b7865c5bfb8adbc316b1034310ec4b5670c47295f4a80fb8d61e9 -a5d1da4d6aba555919df44cbaa8ff79378a1c9e2cfdfbf9d39c63a4a00f284c5a5724e28ecbc2d9dba27fe4ee5018bd5 -a8db53224f70af4d991b9aae4ffe92d2aa5b618ad9137784b55843e9f16cefbfd25ada355d308e9bbf55f6d2f7976fb3 -b6536c4232bb20e22af1a8bb12de76d5fec2ad9a3b48af1f38fa67e0f8504ef60f305a73d19385095bb6a9603fe29889 -87f7e371a1817a63d6838a8cf4ab3a8473d19ce0d4f40fd013c03d5ddd5f4985df2956531cc9f187928ef54c68f4f9a9 -ae13530b1dbc5e4dced9d909ea61286ec09e25c12f37a1ed2f309b0eb99863d236c3b25ed3484acc8c076ad2fa8cd430 -98928d850247c6f7606190e687d5c94a627550198dbdbea0161ef9515eacdb1a0f195cae3bb293112179082daccf8b35 -918528bb8e6a055ad4db6230d3a405e9e55866da15c4721f5ddd1f1f37962d4904aad7a419218fe6d906fe191a991806 -b71e31a06afe065773dd3f4a6e9ef81c3292e27a3b7fdfdd452d03e05af3b6dd654c355f7516b2a93553360c6681a73a -8870b83ab78a98820866f91ac643af9f3ff792a2b7fda34185a9456a63abdce42bfe8ad4dc67f08a6392f250d4062df4 -91eea1b668e52f7a7a5087fabf1cab803b0316f78d9fff469fbfde2162f660c250e4336a9eea4cb0450bd30ac067bc8b -8b74990946de7b72a92147ceac1bd9d55999a8b576e8df68639e40ed5dc2062cfcd727903133de482b6dca19d0aaed82 -8ebad537fece090ebbab662bdf2618e21ca30cf6329c50935e8346d1217dcbe3c1fe1ea28efca369c6003ce0a94703c1 -a8640479556fb59ebd1c40c5f368fbd960932fdbb782665e4a0e24e2bdb598fc0164ce8c0726d7759cfc59e60a62e182 -a9a52a6bf98ee4d749f6d38be2c60a6d54b64d5cbe4e67266633dc096cf28c97fe998596707d31968cbe2064b72256bf -847953c48a4ce6032780e9b39d0ed4384e0be202c2bbe2dfda3910f5d87aa5cd3c2ffbfcfae4dddce16d6ab657599b95 -b6f6e1485d3ec2a06abaecd23028b200b2e4a0096c16144d07403e1720ff8f9ba9d919016b5eb8dc5103880a7a77a1d3 -98dfc2065b1622f596dbe27131ea60bef7a193b12922cecb27f8c571404f483014f8014572e86ae2e341ab738e4887ef -acb0d205566bacc87bbe2e25d10793f63f7a1f27fd9e58f4f653ceae3ffeba511eaf658e068fad289eeb28f9edbeb35b -ae4411ed5b263673cee894c11fe4abc72a4bf642d94022a5c0f3369380fcdfc1c21e277f2902972252503f91ada3029a -ac4a7a27ba390a75d0a247d93d4a8ef1f0485f8d373a4af4e1139369ec274b91b3464d9738eeaceb19cd6f509e2f8262 -87379c3bf231fdafcf6472a79e9e55a938d851d4dd662ab6e0d95fd47a478ed99e2ad1e6e39be3c0fc4f6d996a7dd833 -81316904b035a8bcc2041199a789a2e6879486ba9fddcba0a82c745cc8dd8374a39e523b91792170cd30be7aa3005b85 -b8206809c6cd027ed019f472581b45f7e12288f89047928ba32b4856b6560ad30395830d71e5e30c556f6f182b1fe690 -88d76c028f534a62e019b4a52967bb8642ede6becfa3807be68fdd36d366fc84a4ac8dc176e80a68bc59eb62caf5dff9 -8c3b8be685b0f8aad131ee7544d0e12f223f08a6f8edaf464b385ac644e0ddc9eff7cc7cb5c1b50ab5d71ea0f41d2213 -8d91410e004f76c50fdc05784157b4d839cb5090022c629c7c97a5e0c3536eeafee17a527b54b1165c3cd81774bb54ce -b25c2863bc28ec5281ce800ddf91a7e1a53f4c6d5da1e6c86ef4616e93bcf55ed49e297216d01379f5c6e7b3c1e46728 -865f7b09ac3ca03f20be90c48f6975dd2588838c2536c7a3532a6aa5187ed0b709cd03d91ff4048061c10d0aa72b69ce -b3f7477c90c11596eb4f8bbf34adbcb832638c4ff3cdd090d4d477ee50472ac9ddaf5be9ad7eca3f148960d362bbd098 -8db35fd53fca04faecd1c76a8227160b3ab46ac1af070f2492445a19d8ff7c25bbaef6c9fa0c8c088444561e9f7e4eb2 -a478b6e9d058a2e01d2fc053b739092e113c23a6a2770a16afbef044a3709a9e32f425ace9ba7981325f02667c3f9609 -98caa6bd38916c08cf221722a675a4f7577f33452623de801d2b3429595f988090907a7e99960fff7c076d6d8e877b31 -b79aaaacefc49c3038a14d2ac468cfec8c2161e88bdae91798d63552cdbe39e0e02f9225717436b9b8a40a022c633c6e -845a31006c680ee6a0cc41d3dc6c0c95d833fcf426f2e7c573fa15b2c4c641fbd6fe5ebb0e23720cc3467d6ee1d80dc4 -a1bc287e272cf8b74dbf6405b3a5190883195806aa351f1dc8e525aa342283f0a35ff687e3b434324dedee74946dd185 -a4fd2dc8db75d3783a020856e2b3aa266dc6926e84f5c491ef739a3bddd46dc8e9e0fc1177937839ef1b18d062ffbb9e -acbf0d3c697f57c202bb8c5dc4f3fc341b8fc509a455d44bd86acc67cad2a04495d5537bcd3e98680185e8aa286f2587 -a5caf423a917352e1b8e844f5968a6da4fdeae467d10c6f4bbd82b5eea46a660b82d2f5440d3641c717b2c3c9ed0be52 -8a39d763c08b926599ab1233219c49c825368fad14d9afc7c0c039224d37c00d8743293fd21645bf0b91eaf579a99867 -b2b53a496def0ba06e80b28f36530fbe0fb5d70a601a2f10722e59abee529369c1ae8fd0f2db9184dd4a2519bb832d94 -a73980fcef053f1b60ebbb5d78ba6332a475e0b96a0c724741a3abf3b59dd344772527f07203cf4c9cb5155ebed81fa0 -a070d20acce42518ece322c9db096f16aed620303a39d8d5735a0df6e70fbeceb940e8d9f5cc38f3314b2240394ec47b -a50cf591f522f19ca337b73089557f75929d9f645f3e57d4f241e14cdd1ea3fb48d84bcf05e4f0377afbb789fbdb5d20 -82a5ffce451096aca8eeb0cd2ae9d83db3ed76da3f531a80d9a70a346359bf05d74863ce6a7c848522b526156a5e20cd -88e0e84d358cbb93755a906f329db1537c3894845f32b9b0b691c29cbb455373d9452fadd1e77e20a623f6eaf624de6f -aa07ac7b84a6d6838826e0b9e350d8ec75e398a52e9824e6b0da6ae4010e5943fec4f00239e96433f291fef9d1d1e609 -ac8887bf39366034bc63f6cc5db0c26fd27307cbc3d6cce47894a8a019c22dd51322fb5096edc018227edfafc053a8f6 -b7d26c26c5b33f77422191dca94977588ab1d4b9ce7d0e19c4a3b4cd1c25211b78c328dbf81e755e78cd7d1d622ad23e -99a676d5af49f0ba44047009298d8474cabf2d5bca1a76ba21eff7ee3c4691a102fdefea27bc948ccad8894a658abd02 -b0d09a91909ab3620c183bdf1d53d43d39eb750dc7a722c661c3de3a1a5d383ad221f71bae374f8a71867505958a3f76 -84681a883de8e4b93d68ac10e91899c2bbb815ce2de74bb48a11a6113b2a3f4df8aceabda1f5f67bc5aacac8c9da7221 -9470259957780fa9b43521fab3644f555f5343281c72582b56d2efd11991d897b3b481cafa48681c5aeb80c9663b68f7 -ab1b29f7ece686e6fa968a4815da1d64f3579fed3bc92e1f3e51cd13a3c076b6cf695ed269d373300a62463dc98a4234 -8ab415bfcd5f1061f7687597024c96dd9c7cb4942b5989379a7a3b5742f7d394337886317659cbeacaf030234a24f972 -b9b524aad924f9acc63d002d617488f31b0016e0f0548f050cada285ce7491b74a125621638f19e9c96eabb091d945be -8c4c373e79415061837dd0def4f28a2d5d74d21cb13a76c9049ad678ca40228405ab0c3941df49249847ecdefc1a5b78 -a8edf4710b5ab2929d3db6c1c0e3e242261bbaa8bcec56908ddadd7d2dad2dca9d6eb9de630b960b122ebeea41040421 -8d66bb3b50b9df8f373163629f9221b3d4b6980a05ea81dc3741bfe9519cf3ebba7ab98e98390bae475e8ede5821bd5c -8d3c21bae7f0cfb97c56952bb22084b58e7bb718890935b73103f33adf5e4d99cd262f929c6eeab96209814f0dbae50a -a5c66cfab3d9ebf733c4af24bebc97070e7989fe3c73e79ac85fb0e4d40ae44fb571e0fad4ad72560e13ed453900d14f -9362e6b50b43dbefbc3254471372297b5dcce809cd3b60bf74a1268ab68bdb50e46e462cbd78f0d6c056330e982846af -854630d08e3f0243d570cc2e856234cb4c1a158d9c1883bf028a76525aaa34be897fe918d5f6da9764a3735fa9ebd24a -8c7d246985469ff252c3f4df6c7c9196fc79f05c1c66a609d84725c78001d0837c7a7049394ba5cf7e863e2d58af8417 -ae050271e01b528925302e71903f785b782f7bf4e4e7a7f537140219bc352dc7540c657ed03d3a297ad36798ecdb98cd -8d2ae9179fcf2b0c69850554580b52c1f4a5bd865af5f3028f222f4acad9c1ad69a8ef6c7dc7b03715ee5c506b74325e -b8ef8de6ce6369a8851cd36db0ccf00a85077e816c14c4e601f533330af9e3acf0743a95d28962ed8bfcfc2520ef3cfe -a6ecad6fdfb851b40356a8b1060f38235407a0f2706e7b8bb4a13465ca3f81d4f5b99466ac2565c60af15f022d26732e -819ff14cdea3ab89d98e133cd2d0379361e2e2c67ad94eeddcdb9232efd509f51d12f4f03ebd4dd953bd262a886281f7 -8561cd0f7a6dbcddd83fcd7f472d7dbcba95b2d4fb98276f48fccf69f76d284e626d7e41314b633352df8e6333fd52a1 -b42557ccce32d9a894d538c48712cb3e212d06ac05cd5e0527ccd2db1078ee6ae399bf6a601ffdab1f5913d35fc0b20c -89b4008d767aad3c6f93c349d3b956e28307311a5b1cec237e8d74bb0dee7e972c24f347fd56afd915a2342bd7bc32f0 -877487384b207e53f5492f4e36c832c2227f92d1bb60542cfeb35e025a4a7afc2b885fae2528b33b40ab09510398f83e -8c411050b63c9053dd0cd81dacb48753c3d7f162028098e024d17cd6348482703a69df31ad6256e3d25a8bbf7783de39 -a8506b54a88d17ac10fb1b0d1fe4aa40eae7553a064863d7f6b52ccc4236dd4b82d01dca6ba87da9a239e3069ba879fb -b1a24caef9df64750c1350789bb8d8a0db0f39474a1c74ea9ba064b1516db6923f00af8d57c632d58844fb8786c3d47a -959d6e255f212b0708c58a2f75cb1fe932248c9d93424612c1b8d1e640149656059737e4db2139afd5556bcdacf3eda2 -84525af21a8d78748680b6535bbc9dc2f0cf9a1d1740d12f382f6ecb2e73811d6c1da2ad9956070b1a617c61fcff9fe5 -b74417d84597a485d0a8e1be07bf78f17ebb2e7b3521b748f73935b9afbbd82f34b710fb7749e7d4ab55b0c7f9de127d -a4a9aecb19a6bab167af96d8b9d9aa5308eab19e6bfb78f5a580f9bf89bdf250a7b52a09b75f715d651cb73febd08e84 -9777b30be2c5ffe7d29cc2803a562a32fb43b59d8c3f05a707ab60ec05b28293716230a7d264d7cd9dd358fc031cc13e -95dce7a3d4f23ac0050c510999f5fbf8042f771e8f8f94192e17bcbfa213470802ebdbe33a876cb621cf42e275cbfc8b -b0b963ebcbbee847ab8ae740478544350b3ac7e86887e4dfb2299ee5096247cd2b03c1de74c774d9bde94ae2ee2dcd59 -a4ab20bafa316030264e13f7ef5891a2c3b29ab62e1668fcb5881f50a9acac6adbe3d706c07e62f2539715db768f6c43 -901478a297669d608e406fe4989be75264b6c8be12169aa9e0ad5234f459ca377f78484ffd2099a2fe2db5e457826427 -88c76e5c250810c057004a03408b85cd918e0c8903dc55a0dd8bb9b4fc2b25c87f9b8cf5943eb19fbbe99d36490050c5 -91607322bbad4a4f03fc0012d0821eff5f8c516fda45d1ec1133bface6f858bf04b25547be24159cab931a7aa08344d4 -843203e07fce3c6c81f84bc6dc5fb5e9d1c50c8811ace522dc66e8658433a0ef9784c947e6a62c11bf705307ef05212e -91dd8813a5d6dddcda7b0f87f672b83198cd0959d8311b2b26fb1fae745185c01f796fbd03aad9db9b58482483fdadd8 -8d15911aacf76c8bcd7136e958febd6963104addcd751ce5c06b6c37213f9c4fb0ffd4e0d12c8e40c36d658999724bfd -8a36c5732d3f1b497ebe9250610605ee62a78eaa9e1a45f329d09aaa1061131cf1d9df00f3a7d0fe8ad614a1ff9caaae -a407d06affae03660881ce20dab5e2d2d6cddc23cd09b95502a9181c465e57597841144cb34d22889902aff23a76d049 -b5fd856d0578620a7e25674d9503be7d97a2222900e1b4738c1d81ff6483b144e19e46802e91161e246271f90270e6cf -91b7708869cdb5a7317f88c0312d103f8ce90be14fb4f219c2e074045a2a83636fdc3e69e862049fc7c1ef000e832541 -b64719cc5480709d1dae958f1d3082b32a43376da446c8f9f64cb02a301effc9c34d9102051733315a8179aed94d53cc -94347a9542ff9d18f7d9eaa2f4d9b832d0e535fe49d52aa2de08aa8192400eddabdb6444a2a78883e27c779eed7fdf5a -840ef44a733ff1376466698cd26f82cf56bb44811e196340467f932efa3ae1ef9958a0701b3b032f50fd9c1d2aed9ab5 -90ab3f6f67688888a31ffc2a882bb37adab32d1a4b278951a21646f90d03385fc976715fc639a785d015751171016f10 -b56f35d164c24b557dbcbc8a4bfa681ec916f8741ffcb27fb389c164f4e3ed2be325210ef5bdaeae7a172ca9599ab442 -a7921a5a80d7cf6ae81ba9ee05e0579b18c20cd2852762c89d6496aa4c8ca9d1ca2434a67b2c16d333ea8e382cdab1e3 -a506bcfbd7e7e5a92f68a1bd87d07ad5fe3b97aeee40af2bf2cae4efcd77fff03f872732c5b7883aa6584bee65d6f8cb -a8c46cff58931a1ce9cbe1501e1da90b174cddd6d50f3dfdfb759d1d4ad4673c0a8feed6c1f24c7af32865a7d6c984e5 -b45686265a83bff69e312c5149db7bb70ac3ec790dc92e392b54d9c85a656e2bf58596ce269f014a906eafc97461aa5f -8d4009a75ccb2f29f54a5f16684b93202c570d7a56ec1a8b20173269c5f7115894f210c26b41e8d54d4072de2d1c75d0 -aef8810af4fc676bf84a0d57b189760ddc3375c64e982539107422e3de2580b89bd27aa6da44e827b56db1b5555e4ee8 -888f0e1e4a34f48eb9a18ef4de334c27564d72f2cf8073e3d46d881853ac1424d79e88d8ddb251914890588937c8f711 -b64b0aa7b3a8f6e0d4b3499fe54e751b8c3e946377c0d5a6dbb677be23736b86a7e8a6be022411601dd75012012c3555 -8d57776f519f0dd912ea14f79fbab53a30624e102f9575c0bad08d2dc754e6be54f39b11278c290977d9b9c7c0e1e0ad -a018fc00d532ceb2e4de908a15606db9b6e0665dd77190e2338da7c87a1713e6b9b61554e7c1462f0f6d4934b960b15c -8c932be83ace46f65c78e145b384f58e41546dc0395270c1397874d88626fdeda395c8a289d602b4c312fe98c1311856 -89174838e21639d6bdd91a0621f04dc056907b88e305dd66e46a08f6d65f731dea72ae87ca5e3042d609e8de8de9aa26 -b7b7f508bb74f7a827ac8189daa855598ff1d96fa3a02394891fd105d8f0816224cd50ac4bf2ed1cf469ace516c48184 -b31877ad682583283baadd68dc1bebd83f5748b165aadd7fe9ef61a343773b88bcd3a022f36d6c92f339b7bfd72820a9 -b79d77260b25daf9126dab7a193df2d7d30542786fa1733ffaf6261734770275d3ca8bae1d9915d1181a78510b3439db -91894fb94cd4c1dd2ceaf9c53a7020c5799ba1217cf2d251ea5bc91ed26e1159dd758e98282ebe35a0395ef9f1ed15a0 -ab59895cdafd33934ceedfc3f0d5d89880482cba6c99a6db93245f9e41987efd76e0640e80aef31782c9a8c7a83fccec -aa22ea63654315e033e09d4d4432331904a6fc5fb1732557987846e3c564668ca67c60a324b4af01663a23af11a9ce4b -b53ba3ef342601467e1f71aa280e100fbabbd38518fa0193e0099505036ee517c1ac78e96e9baeb549bb6879bb698fb0 -943fd69fd656f37487cca3605dc7e5a215fddd811caf228595ec428751fc1de484a0cb84c667fe4d7c35599bfa0e5e34 -9353128b5ebe0dddc555093cf3e5942754f938173541033e8788d7331fafc56f68d9f97b4131e37963ab7f1c8946f5f1 -a76cd3c566691f65cfb86453b5b31dbaf3cab8f84fe1f795dd1e570784b9b01bdd5f0b3c1e233942b1b5838290e00598 -983d84b2e53ffa4ae7f3ba29ef2345247ea2377686b74a10479a0ef105ecf90427bf53b74c96dfa346d0f842b6ffb25b -92e0fe9063306894a2c6970c001781cff416c87e87cb5fbac927a3192655c3da4063e6fa93539f6ff58efac6adcc5514 -b00a81f03c2b8703acd4e2e4c21e06973aba696415d0ea1a648ace2b0ea19b242fede10e4f9d7dcd61c546ab878bc8f9 -b0d08d880f3b456a10bf65cff983f754f545c840c413aea90ce7101a66eb0a0b9b1549d6c4d57725315828607963f15a -90cb64d03534f913b411375cce88a9e8b1329ce67a9f89ca5df8a22b8c1c97707fec727dbcbb9737f20c4cf751359277 -8327c2d42590dfcdb78477fc18dcf71608686ad66c49bce64d7ee874668be7e1c17cc1042a754bbc77c9daf50b2dae07 -8532171ea13aa7e37178e51a6c775da469d2e26ec854eb16e60f3307db4acec110d2155832c202e9ba525fc99174e3b0 -83ca44b15393d021de2a511fa5511c5bd4e0ac7d67259dce5a5328f38a3cce9c3a269405959a2486016bc27bb140f9ff -b1d36e8ca812be545505c8214943b36cabee48112cf0de369957afa796d37f86bf7249d9f36e8e990f26f1076f292b13 -9803abf45be5271e2f3164c328d449efc4b8fc92dfc1225d38e09630909fe92e90a5c77618daa5f592d23fc3ad667094 -b268ad68c7bf432a01039cd889afae815c3e120f57930d463aece10af4fd330b5bd7d8869ef1bcf6b2e78e4229922edc -a4c91a0d6f16b1553264592b4cbbbf3ca5da32ab053ffbdd3dbb1aed1afb650fb6e0dc5274f71a51d7160856477228db -ad89d043c2f0f17806277ffdf3ecf007448e93968663f8a0b674254f36170447b7527d5906035e5e56f4146b89b5af56 -8b6964f757a72a22a642e4d69102951897e20c21449184e44717bd0681d75f7c5bfa5ee5397f6e53febf85a1810d6ed1 -b08f5cdaabec910856920cd6e836c830b863eb578423edf0b32529488f71fe8257d90aed4a127448204df498b6815d79 -af26bb3358be9d280d39b21d831bb53145c4527a642446073fee5a86215c4c89ff49a3877a7a549486262f6f57a0f476 -b4010b37ec4d7c2af20800e272539200a6b623ae4636ecbd0e619484f4ab9240d02bc5541ace3a3fb955dc0a3d774212 -82752ab52bdcc3cc2fc405cb05a2e694d3df4a3a68f2179ec0652536d067b43660b96f85f573f26fbd664a9ef899f650 -96d392dde067473a81faf2d1fea55b6429126b88b160e39b4210d31d0a82833ffd3a80e07d24d495aea2d96be7251547 -a76d8236d6671204d440c33ac5b8deb71fa389f6563d80e73be8b043ec77d4c9b06f9a586117c7f957f4af0331cbc871 -b6c90961f68b5e385d85c9830ec765d22a425f506904c4d506b87d8944c2b2c09615e740ed351df0f9321a7b93979cae -a6ec5ea80c7558403485b3b1869cdc63bde239bafdf936d9b62a37031628402a36a2cfa5cfbb8e26ac922cb0a209b3ba -8c3195bbdbf9bc0fc95fa7e3d7f739353c947f7767d1e3cb24d8c8602d8ea0a1790ac30b815be2a2ba26caa5227891e2 -a7f8a63d809f1155722c57f375ea00412b00147776ae4444f342550279ef4415450d6f400000a326bf11fea6c77bf941 -97fa404df48433a00c85793440e89bb1af44c7267588ae937a1f5d53e01e1c4d4fc8e4a6d517f3978bfdd6c2dfde012f -a984a0a3836de3d8d909c4629a2636aacb85393f6f214a2ef68860081e9db05ad608024762db0dc35e895dc00e2d4cdd -9526cf088ab90335add1db4d3a4ac631b58cbfbe88fa0845a877d33247d1cfeb85994522e1eb8f8874651bfb1df03e2a -ac83443fd0afe99ad49de9bf8230158c118e2814c9c89db5ac951c240d6c2ce45e7677221279d9e97848ec466b99aafe -aeeefdbaba612e971697798ceaf63b247949dc823a0ad771ae5b988a5e882b338a98d3d0796230f49d533ec5ba411b39 -ae3f248b5a7b0f92b7820a6c5ae21e5bd8f4265d4f6e21a22512079b8ee9be06393fd3133ce8ebac0faf23f4f8517e36 -a64a831b908eee784b8388b45447d2885ec0551b26b0c2b15e5f417d0a12c79e867fb7bd3d008d0af98b44336f8ec1ad -b242238cd8362b6e440ba21806905714dd55172db25ec7195f3fc4937b2aba146d5cbf3cf691a1384b4752dc3b54d627 -819f97f337eea1ffb2a678cc25f556f1aab751c6b048993a1d430fe1a3ddd8bb411c152e12ca60ec6e057c190cd1db9a -b9d7d187407380df54ee9fef224c54eec1bfabf17dc8abf60765b7951f538f59aa26fffd5846cfe05546c35f59b573f4 -aa6e3c14efa6a5962812e3f94f8ce673a433f4a82d07a67577285ea0eaa07f8be7115853122d12d6d4e1fdf64c504be1 -82268bee9c1662d3ddb5fb785abfae6fb8b774190f30267f1d47091d2cd4b3874db4372625aa36c32f27b0eee986269b -b236459565b7b966166c4a35b2fa71030b40321821b8e96879d95f0e83a0baf33fa25721f30af4a631df209e25b96061 -8708d752632d2435d2d5b1db4ad1fa2558d776a013655f88e9a3556d86b71976e7dfe5b8834fdec97682cd94560d0d0d -ae1424a68ae2dbfb0f01211f11773732a50510b5585c1fb005cb892b2c6a58f4a55490b5c5b4483c6fce40e9d3236a52 -b3f5f722af9dddb07293c871ce97abbccba0093ca98c8d74b1318fa21396fc1b45b69c15084f63d728f9908442024506 -9606f3ce5e63886853ca476dc0949e7f1051889d529365c0cb0296fdc02abd088f0f0318ecd2cf36740a3634132d36f6 -b11a833a49fa138db46b25ff8cdda665295226595bc212c0931b4931d0a55c99da972c12b4ef753f7e37c6332356e350 -afede34e7dab0a9e074bc19a7daddb27df65735581ca24ad70c891c98b1349fcebbcf3ba6b32c2617fe06a5818dabc2d -97993d456e459e66322d01f8eb13918979761c3e8590910453944bdff90b24091bb018ac6499792515c9923be289f99f -977e3e967eff19290a192cd11df3667d511b398fb3ac9a5114a0f3707e25a0edcb56105648b1b85a8b7519fc529fc6f6 -b873a7c88bf58731fe1bf61ff6828bf114cf5228f254083304a4570e854e83748fc98683ddba62d978fff7909f2c5c47 -ad4b2691f6f19da1d123aaa23cca3e876247ed9a4ab23c599afdbc0d3aa49776442a7ceaa996ac550d0313d9b9a36cee -b9210713c78e19685608c6475bfa974b57ac276808a443f8b280945c5d5f9c39da43effa294bfb1a6c6f7b6b9f85bf6c -a65152f376113e61a0e468759de38d742caa260291b4753391ee408dea55927af08a4d4a9918600a3bdf1df462dffe76 -8bf8c27ad5140dde7f3d2280fd4cc6b29ab76537e8d7aa7011a9d2796ee3e56e9a60c27b5c2da6c5e14fc866301dc195 -92fde8effc9f61393a2771155812b863cff2a0c5423d7d40aa04d621d396b44af94ddd376c28e7d2f53c930aea947484 -97a01d1dd9ee30553ce676011aea97fa93d55038ada95f0057d2362ae9437f3ed13de8290e2ff21e3167dd7ba10b9c3f -89affffaa63cb2df3490f76f0d1e1d6ca35c221dd34057176ba739fa18d492355e6d2a5a5ad93a136d3b1fed0bb8aa19 -928b8e255a77e1f0495c86d3c63b83677b4561a5fcbbe5d3210f1e0fc947496e426d6bf3b49394a5df796c9f25673fc4 -842a0af91799c9b533e79ee081efe2a634cac6c584c2f054fb7d1db67dde90ae36de36cbf712ec9cd1a0c7ee79e151ea -a65b946cf637e090baf2107c9a42f354b390e7316beb8913638130dbc67c918926eb87bec3b1fe92ef72bc77a170fa3b -aafc0f19bfd71ab5ae4a8510c7861458b70ad062a44107b1b1dbacbfa44ba3217028c2824bd7058e2fa32455f624040b -95269dc787653814e0be899c95dba8cfa384f575a25e671c0806fd80816ad6797dc819d30ae06e1d0ed9cb01c3950d47 -a1e760f7fa5775a1b2964b719ff961a92083c5c617f637fc46e0c9c20ab233f8686f7f38c3cb27d825c54dd95e93a59b -ac3b8a7c2317ea967f229eddc3e23e279427f665c4705c7532ed33443f1243d33453c1088f57088d2ab1e3df690a9cc9 -b787beeddfbfe36dd51ec4efd9cf83e59e84d354c3353cc9c447be53ae53d366ed1c59b686e52a92f002142c8652bfe0 -b7a64198300cb6716aa7ac6b25621f8bdec46ad5c07a27e165b3f774cdf65bcfdbf31e9bae0c16b44de4b00ada7a4244 -b8ae9f1452909e0c412c7a7fe075027691ea8df1347f65a5507bc8848f1d2c833d69748076db1129e5b4fb912f65c86c -9682e41872456b9fa67def89e71f06d362d6c8ca85c9c48536615bc401442711e1c9803f10ab7f8ab5feaec0f9df20a6 -88889ff4e271dc1c7e21989cc39f73cde2f0475acd98078281591ff6c944fadeb9954e72334319050205d745d4df73df -8f79b5b8159e7fd0d93b0645f3c416464f39aec353b57d99ecf24f96272df8a068ad67a6c90c78d82c63b40bb73989bb -838c01a009a3d8558a3f0bdd5e22de21af71ca1aefc8423c91dc577d50920e9516880e87dce3e6d086e11cd45c9052d9 -b97f1c6eee8a78f137c840667cc288256e39294268a3009419298a04a1d0087c9c9077b33c917c65caf76637702dda8a -972284ce72f96a61c899260203dfa06fc3268981732bef74060641c1a5068ead723e3399431c247ca034b0dae861e8df -945a8d52d6d3db6663dbd3110c6587f9e9c44132045eeffba15621576d178315cb52870fa5861669f84f0bee646183fe -a0a547b5f0967b1c3e5ec6c6a9a99f0578521489180dfdfbb5561f4d166baac43a2f06f950f645ce991664e167537eed -a0592cda5cdddf1340033a745fd13a6eff2021f2e26587116c61c60edead067e0f217bc2bef4172a3c9839b0b978ab35 -b9c223b65a3281587fa44ec829e609154b32f801fd1de6950e01eafb07a8324243b960d5735288d0f89f0078b2c42b5b -99ebfc3b8f9f98249f4d37a0023149ed85edd7a5abe062c8fb30c8c84555258b998bdcdd1d400bc0fa2a4aaa8b224466 -955b68526e6cb3937b26843270f4e60f9c6c8ece2fa9308fe3e23afa433309c068c66a4bc16ee2cf04220f095e9afce4 -b766caeafcc00378135ae53397f8a67ed586f5e30795462c4a35853de6681b1f17401a1c40958de32b197c083b7279c1 -921bf87cad947c2c33fa596d819423c10337a76fe5a63813c0a9dc78a728207ae7b339407a402fc4d0f7cba3af6da6fc -a74ba1f3bc3e6c025db411308f49b347ec91da1c916bda9da61e510ec8d71d25e0ac0f124811b7860e5204f93099af27 -a29b4d144e0bf17a7e8353f2824cef0ce85621396babe8a0b873ca1e8a5f8d508b87866cf86da348470649fceefd735c -a8040e12ffc3480dd83a349d06741d1572ef91932c46f5cf03aee8454254156ee95786fd013d5654725e674c920cec32 -8c4cf34ca60afd33923f219ffed054f90cd3f253ffeb2204a3b61b0183417e366c16c07fae860e362b0f2bfe3e1a1d35 -8195eede4ddb1c950459df6c396b2e99d83059f282b420acc34220cadeed16ab65c856f2c52568d86d3c682818ed7b37 -91fff19e54c15932260aa990c7fcb3c3c3da94845cc5aa8740ef56cf9f58d19b4c3c55596f8d6c877f9f4d22921d93aa -a3e0bf7e5d02a80b75cf75f2db7e66cb625250c45436e3c136d86297d652590ec97c2311bafe407ad357c79ab29d107b -81917ff87e5ed2ae4656b481a63ced9e6e5ff653b8aa6b7986911b8bc1ee5b8ef4f4d7882c3f250f2238e141b227e510 -915fdbe5e7de09c66c0416ae14a8750db9412e11dc576cf6158755fdcaf67abdbf0fa79b554cac4fe91c4ec245be073f -8df27eafb5c3996ba4dc5773c1a45ca77e626b52e454dc1c4058aa94c2067c18332280630cc3d364821ee53bf2b8c130 -934f8a17c5cbb827d7868f5c8ca00cb027728a841000a16a3428ab16aa28733f16b52f58c9c4fbf75ccc45df72d9c4df -b83f4da811f9183c25de8958bc73b504cf790e0f357cbe74ef696efa7aca97ad3b7ead1faf76e9f982c65b6a4d888fc2 -87188213c8b5c268dc2b6da413f0501c95749e953791b727450af3e43714149c115b596b33b63a2f006a1a271b87efd0 -83e9e888ab9c3e30761de635d9aabd31248cdd92f7675fc43e4b21fd96a03ec1dc4ad2ec94fec857ffb52683ac98e360 -b4b9a1823fe2d983dc4ec4e3aaea297e581c3fc5ab4b4af5fa1370caa37af2d1cc7fc6bfc5e7da60ad8fdce27dfe4b24 -856388bc78aef465dbcdd1f559252e028c9e9a2225c37d645c138e78f008f764124522705822a61326a6d1c79781e189 -a6431b36db93c3b47353ba22e7c9592c9cdfb9cbdd052ecf2cc3793f5b60c1e89bc96e6bae117bfd047f2308da00dd2f -b619972d48e7e4291542dcde08f7a9cdc883c892986ded2f23ccb216e245cd8d9ad1d285347b0f9d7611d63bf4cee2bc -8845cca6ff8595955f37440232f8e61d5351500bd016dfadd182b9d39544db77a62f4e0102ff74dd4173ae2c181d24ef -b2f5f7fa26dcd3b6550879520172db2d64ee6aaa213cbef1a12befbce03f0973a22eb4e5d7b977f466ac2bf8323dcedd -858b7f7e2d44bdf5235841164aa8b4f3d33934e8cb122794d90e0c1cac726417b220529e4f896d7b77902ab0ccd35b3a -80b0408a092dae2b287a5e32ea1ad52b78b10e9c12f49282976cd738f5d834e03d1ad59b09c5ccaccc39818b87d06092 -b996b0a9c6a2d14d984edcd6ab56bc941674102980d65b3ad9733455f49473d3f587c8cbf661228a7e125ddbe07e3198 -90224fcebb36865293bd63af786e0c5ade6b67c4938d77eb0cbae730d514fdd0fe2d6632788e858afd29d46310cf86df -b71351fdfff7168b0a5ec48397ecc27ac36657a8033d9981e97002dcca0303e3715ce6dd3f39423bc8ef286fa2e9e669 -ae2a3f078b89fb753ce4ed87e0c1a58bb19b4f0cfb6586dedb9fcab99d097d659a489fb40e14651741e1375cfc4b6c5f -8ef476b118e0b868caed297c161f4231bbeb863cdfa5e2eaa0fc6b6669425ce7af50dc374abceac154c287de50c22307 -92e46ab472c56cfc6458955270d3c72b7bde563bb32f7d4ab4d959db6f885764a3d864e1aa19802fefaa5e16b0cb0b54 -96a3f68323d1c94e73d5938a18a377af31b782f56212de3f489d22bc289cf24793a95b37f1d6776edf88114b5c1fa695 -962cc068cfce6faaa27213c4e43e44eeff0dfbb6d25b814e82c7da981fb81d7d91868fa2344f05fb552362f98cfd4a72 -895d4e4c4ad670abf66d43d59675b1add7afad7438ada8f42a0360c704cee2060f9ac15b4d27e9b9d0996bb801276fe3 -b3ad18d7ece71f89f2ef749b853c45dc56bf1c796250024b39a1e91ed11ca32713864049c9aaaea60cde309b47486bbf -8f05404e0c0258fdbae50e97ccb9b72ee17e0bd2400d9102c0dad981dac8c4c71585f03e9b5d50086d0a2d3334cb55d1 -8bd877e9d4591d02c63c6f9fc9976c109de2d0d2df2bfa5f6a3232bab5b0b8b46e255679520480c2d7a318545efa1245 -8d4c16b5d98957c9da13d3f36c46f176e64e5be879f22be3179a2c0e624fe4758a82bf8c8027410002f973a3b84cd55a -86e2a8dea86427b424fa8eada881bdff896907084a495546e66556cbdf070b78ba312bf441eb1be6a80006d25d5097a3 -8608b0c117fd8652fdab0495b08fadbeba95d9c37068e570de6fddfef1ba4a1773b42ac2be212836141d1bdcdef11a17 -a13d6febf5fb993ae76cae08423ca28da8b818d6ef0fde32976a4db57839cd45b085026b28ee5795f10a9a8e3098c683 -8e261967fa6de96f00bc94a199d7f72896a6ad8a7bbb1d6187cca8fad824e522880e20f766620f4f7e191c53321d70f9 -8b8e8972ac0218d7e3d922c734302803878ad508ca19f5f012bc047babd8a5c5a53deb5fe7c15a4c00fd6d1cb9b1dbd0 -b5616b233fb3574a2717d125a434a2682ff68546dccf116dd8a3b750a096982f185614b9fb6c7678107ff40a451f56fa -aa6adf9b0c3334b0d0663f583a4914523b2ac2e7adffdb026ab9109295ff6af003ef8357026dbcf789896d2afded8d73 -acb72df56a0b65496cd534448ed4f62950bb1e11e50873b6ed349c088ee364441821294ce0f7c61bd7d38105bea3b442 -abae12df83e01ec947249fedd0115dc501d2b03ff7232092979eda531dbbca29ace1d46923427c7dde4c17bdf3fd7708 -820b4fc2b63a9fda7964acf5caf19a2fc4965007cb6d6b511fcafcb1f71c3f673a1c0791d3f86e3a9a1eb6955b191cc0 -af277259d78c6b0f4f030a10c53577555df5e83319ddbad91afbd7c30bc58e7671c56d00d66ec3ab5ef56470cd910cee -ad4a861c59f1f5ca1beedd488fb3d131dea924fffd8e038741a1a7371fad7370ca5cf80dc01f177fbb9576713bb9a5b3 -b67a5162982ce6a55ccfb2f177b1ec26b110043cf18abd6a6c451cf140b5af2d634591eb4f28ad92177d8c7e5cd0a5e8 -96176d0a83816330187798072d449cbfccff682561e668faf6b1220c9a6535b32a6e4f852e8abb00f79abb87493df16b -b0afe6e7cb672e18f0206e4423f51f8bd0017bf464c4b186d46332c5a5847647f89ff7fa4801a41c1b0b42f6135bcc92 -8fc5e7a95ef20c1278c645892811f6fe3f15c431ebc998a32ec0da44e7213ea934ed2be65239f3f49b8ec471e9914160 -b7793e41adda6c82ba1f2a31f656f6205f65bf8a3d50d836ee631bc7ce77c153345a2d0fc5c60edf8b37457c3729c4ec -a504dd7e4d6b2f4379f22cc867c65535079c75ccc575955f961677fa63ecb9f74026fa2f60c9fb6323c1699259e5e9c8 -ab899d00ae693649cc1afdf30fb80d728973d2177c006e428bf61c7be01e183866614e05410041bc82cb14a33330e69c -8a3bd8b0b1be570b65c4432a0f6dc42f48a2000e30ab089cf781d38f4090467b54f79c0d472fcbf18ef6a00df69cc6f3 -b4d7028f7f76a96a3d7803fca7f507ae11a77c5346e9cdfccb120a833a59bda1f4264e425aa588e7a16f8e7638061d84 -b9c7511a76ea5fb105de905d44b02edb17008335766ee357ed386b7b3cf19640a98b38785cb14603c1192bee5886c9b6 -8563afb12e53aed71ac7103ab8602bfa8371ae095207cb0d59e8fd389b6ad1aff0641147e53cb6a7ca16c7f37c9c5e6b -8e108be614604e09974a9ed90960c28c4ea330a3d9a0cb4af6dd6f193f84ab282b243ecdf549b3131036bebc8905690c -b794d127fbedb9c5b58e31822361706ffac55ce023fbfe55716c3c48c2fd2f2c7660a67346864dfe588812d369cb50b6 -b797a3442fc3b44f41baefd30346f9ac7f96e770d010d53c146ce74ce424c10fb62758b7e108b8abfdc5fafd89d745cb -993bb71e031e8096442e6205625e1bfddfe6dd6a83a81f3e2f84fafa9e5082ab4cad80a099f21eff2e81c83457c725c3 -8711ab833fc03e37acf2e1e74cfd9133b101ff4144fe30260654398ae48912ab46549d552eb9d15d2ea57760d35ac62e -b21321fd2a12083863a1576c5930e1aecb330391ef83326d9d92e1f6f0d066d1394519284ddab55b2cb77417d4b0292f -877d98f731ffe3ee94b0b5b72d127630fa8a96f6ca4f913d2aa581f67732df6709493693053b3e22b0181632ac6c1e3b -ae391c12e0eb8c145103c62ea64f41345973311c3bf7281fa6bf9b7faafac87bcf0998e5649b9ef81e288c369c827e07 -b83a2842f36998890492ab1cd5a088d9423d192681b9a3a90ec518d4c541bce63e6c5f4df0f734f31fbfdd87785a2463 -a21b6a790011396e1569ec5b2a423857b9bec16f543e63af28024e116c1ea24a3b96e8e4c75c6537c3e4611fd265e896 -b4251a9c4aab3a495da7a42e684ba4860dbcf940ad1da4b6d5ec46050cbe8dab0ab9ae6b63b5879de97b905723a41576 -8222f70aebfe6ac037f8543a08498f4cadb3edaac00336fc00437eb09f2cba758f6c38e887cc634b4d5b7112b6334836 -86f05038e060594c46b5d94621a1d9620aa8ba59a6995baf448734e21f58e23c1ea2993d3002ad5250d6edd5ba59b34f -a7c0c749baef811ab31b973c39ceb1d94750e2bc559c90dc5eeb20d8bb6b78586a2b363c599ba2107d6be65cd435f24e -861d46a5d70b38d6c1cd72817a2813803d9f34c00320c8b62f8b9deb67f5b5687bc0b37c16d28fd017367b92e05da9ca -b3365d3dab639bffbe38e35383686a435c8c88b397b717cd4aeced2772ea1053ceb670f811f883f4e02975e5f1c4ac58 -a5750285f61ab8f64cd771f6466e2c0395e01b692fd878f2ef2d5c78bdd8212a73a3b1dfa5e4c8d9e1afda7c84857d3b -835a10809ccf939bc46cf950a33b36d71be418774f51861f1cd98a016ade30f289114a88225a2c11e771b8b346cbe6ef -a4f59473a037077181a0a62f1856ec271028546ca9452b45cedfcb229d0f4d1aabfc13062b07e536cc8a0d4b113156a2 -95cd14802180b224d44a73cc1ed599d6c4ca62ddcaa503513ccdc80aaa8be050cc98bd4b4f3b639549beb4587ac6caf9 -973b731992a3e69996253d7f36dd7a0af1982b5ed21624b77a7965d69e9a377b010d6dabf88a8a97eec2a476259859cc -af8a1655d6f9c78c8eb9a95051aa3baaf9c811adf0ae8c944a8d3fcba87b15f61021f3baf6996fa0aa51c81b3cb69de1 -835aad5c56872d2a2d6c252507b85dd742bf9b8c211ccb6b25b52d15c07245b6d89b2a40f722aeb5083a47cca159c947 -abf4e970b02bef8a102df983e22e97e2541dd3650b46e26be9ee394a3ea8b577019331857241d3d12b41d4eacd29a3ac -a13c32449dbedf158721c13db9539ae076a6ce5aeaf68491e90e6ad4e20e20d1cdcc4a89ed9fd49cb8c0dd50c17633c1 -8c8f78f88b7e22dd7e9150ab1c000f10c28e696e21d85d6469a6fe315254740f32e73d81ab1f3c1cf8f544c86df506e8 -b4b77f2acfe945abf81f2605f906c10b88fb4d28628487fb4feb3a09f17f28e9780445dfcee4878349d4c6387a9d17d4 -8d255c235f3812c6ecc646f855fa3832be5cb4dbb9c9e544989fafdf3f69f05bfd370732eaf954012f0044aa013fc9c6 -b982efd3f34b47df37c910148ac56a84e8116647bea24145a49e34e0a6c0176e3284d838dae6230cb40d0be91c078b85 -983f365aa09bd85df2a6a2ad8e4318996b1e27d02090755391d4486144e40d80b1fbfe1c798d626db92f52e33aa634da -95fd1981271f3ea3a41d654cf497e6696730d9ff7369f26bc4d7d15c7adb4823dd0c42e4a005a810af12d234065e5390 -a9f5219bd4b913c186ef30c02f995a08f0f6f1462614ea5f236964e02bdaa33db9d9b816c4aee5829947840a9a07ba60 -9210e6ceb05c09b46fd09d036287ca33c45124ab86315e5d6911ff89054f1101faaa3e83d123b7805056d388bcec6664 -8ed9cbf69c6ff3a5c62dd9fe0d7264578c0f826a29e614bc2fb4d621d90c8c9992438accdd7a614b1dca5d1bb73dc315 -85cf2a8cca93e00da459e3cecd22c342d697eee13c74d5851634844fc215f60053cf84b0e03c327cb395f48d1c71a8a4 -8818a18e9a2ec90a271b784400c1903089ffb0e0b40bc5abbbe12fbebe0f731f91959d98c5519ef1694543e31e2016d4 -8dabc130f296fa7a82870bf9a8405aaf542b222ed9276bba9bd3c3555a0f473acb97d655ee7280baff766a827a8993f0 -ac7952b84b0dc60c4d858f034093b4d322c35959605a3dad2b806af9813a4680cb038c6d7f4485b4d6b2ff502aaeca25 -ad65cb6d57b48a2602568d2ec8010baed0eb440eec7638c5ec8f02687d764e9de5b5d42ad5582934e592b48471c22d26 -a02ab8bd4c3d114ea23aebdd880952f9495912817da8c0c08eabc4e6755439899d635034413d51134c72a6320f807f1c -8319567764b8295402ec1ebef4c2930a138480b37e6d7d01c8b4c9cd1f2fc3f6e9a44ae6e380a0c469b25b06db23305f -afec53b2301dc0caa8034cd9daef78c48905e6068d692ca23d589b84a6fa9ddc2ed24a39480597e19cb3e83eec213b3f -ac0b4ffdb5ae08e586a9cdb98f9fe56f4712af3a97065e89e274feacfb52b53c839565aee93c4cfaaccfe51432c4fab0 -8972cbf07a738549205b1094c5987818124144bf187bc0a85287c94fdb22ce038c0f11df1aa16ec5992e91b44d1af793 -b7267aa6f9e3de864179b7da30319f1d4cb2a3560f2ea980254775963f1523b44c680f917095879bebfa3dc2b603efcf -80f68f4bfc337952e29504ee5149f15093824ea7ab02507efd1317a670f6cbc3611201848560312e3e52e9d9af72eccf -8897fee93ce8fc1e1122e46b6d640bba309384dbd92e46e185e6364aa8210ebf5f9ee7e5e604b6ffba99aa80a10dd7d0 -b58ea6c02f2360be60595223d692e82ee64874fda41a9f75930f7d28586f89be34b1083e03bbc1575bbfdda2d30db1ea -85a523a33d903280d70ac5938770453a58293480170c84926457ac2df45c10d5ff34322ab130ef4a38c916e70d81af53 -a2cbf045e1bed38937492c1f2f93a5ba41875f1f262291914bc1fc40c60bd0740fb3fea428faf6da38b7c180fe8ac109 -8c09328770ed8eb17afc6ac7ddd87bb476de18ed63cab80027234a605806895959990c47bd10d259d7f3e2ecb50074c9 -b4b9e19edb4a33bde8b7289956568a5b6b6557404e0a34584b5721fe6f564821091013fbb158e2858c6d398293bb4b59 -8a47377df61733a2aa5a0e945fce00267f8e950f37e109d4487d92d878fb8b573317bb382d902de515b544e9e233458d -b5804c9d97efeff5ca94f3689b8088c62422d92a1506fd1d8d3b1b30e8a866ad0d6dad4abfa051dfc4471250cac4c5d9 -9084a6ee8ec22d4881e9dcc8a9eb3c2513523d8bc141942370fd191ad2601bf9537a0b1e84316f3209b3d8a54368051e -85447eea2fa26656a649f8519fa67279183044791d61cf8563d0783d46d747d96af31d0a93507bbb2242666aa87d3720 -97566a84481027b60116c751aec552adfff2d9038e68d48c4db9811fb0cbfdb3f1d91fc176a0b0d988a765f8a020bce1 -ae87e5c1b9e86c49a23dceda4ecfd1dcf08567f1db8e5b6ec752ebd45433c11e7da4988573cdaebbb6f4135814fc059e -abee05cf9abdbc52897ac1ce9ed157f5466ed6c383d6497de28616238d60409e5e92619e528af8b62cc552bf09970dc2 -ae6d31cd7bf9599e5ee0828bab00ceb4856d829bba967278a73706b5f388465367aa8a6c7da24b5e5f1fdd3256ef8e63 -ac33e7b1ee47e1ee4af472e37ab9e9175260e506a4e5ce449788075da1b53c44cb035f3792d1eea2aa24b1f688cc6ed3 -80f65b205666b0e089bb62152251c48c380a831e5f277f11f3ef4f0d52533f0851c1b612267042802f019ec900dc0e8f -858520ad7aa1c9fed738e3b583c84168f2927837ad0e1d326afe9935c26e9b473d7f8c382e82ef1fe37d2b39bb40a1ee -b842dd4af8befe00a97c2d0f0c33c93974761e2cb9e5ab8331b25170318ddd5e4bdbc02d8f90cbfdd5f348f4f371c1f7 -8bf2cb79bc783cb57088aae7363320cbeaabd078ffdec9d41bc74ff49e0043d0dad0086a30e5112b689fd2f5a606365d -982eb03bbe563e8850847cd37e6a3306d298ab08c4d63ab6334e6b8c1fa13fce80cf2693b09714c7621d74261a0ff306 -b143edb113dec9f1e5105d4a93fbe502b859e587640d3db2f628c09a17060e6aec9e900e2c8c411cda99bc301ff96625 -af472d9befa750dcebc5428fe1a024f18ec1c07bca0f95643ce6b5f4189892a910285afb03fd7ed7068fbe614e80d33c -a97e3bc57ede73ecd1bbf02de8f51b4e7c1a067da68a3cd719f4ba26a0156cbf1cef2169fd35a18c5a4cced50d475998 -a862253c937cf3d75d7183e5f5be6a4385d526aeda5171c1c60a8381fea79f88f5f52a4fab244ecc70765d5765e6dfd5 -90cb776f8e5a108f1719df4a355bebb04bf023349356382cae55991b31720f0fd03206b895fa10c56c98f52453be8778 -a7614e8d0769dccd520ea4b46f7646e12489951efaef5176bc889e9eb65f6e31758df136b5bf1e9107e68472fa9b46ec -ac3a9b80a3254c42e5ed3a090a0dd7aee2352f480de96ad187027a3bb6c791eddfc3074b6ffd74eea825188f107cda4d -82a01d0168238ef04180d4b6e0a0e39024c02c2d75b065017c2928039e154d093e1af4503f4d1f3d8a948917abb5d09f -8fab000a2b0eef851a483aec8d2dd85fe60504794411a2f73ed82e116960547ac58766cb73df71aea71079302630258d -872451a35c6db61c63e9b8bb9f16b217f985c20be4451c14282c814adb29d7fb13f201367c664435c7f1d4d9375d7a58 -887d9ff54cc96b35d562df4a537ff972d7c4b3fd91ab06354969a4cfede0b9fc68bbffb61d0dbf1a58948dc701e54f5a -8cb5c2a6bd956875d88f41ae24574434f1308514d44057b55c9c70f13a3366ed054150eed0955a38fda3f757be73d55f -89ad0163cad93e24129d63f8e38422b7674632a8d0a9016ee8636184cab177659a676c4ee7efba3abe1a68807c656d60 -b9ec01c7cab6d00359b5a0b4a1573467d09476e05ca51a9227cd16b589a9943d161eef62dcc73f0de2ec504d81f4d252 -8031d17635d39dfe9705c485d2c94830b6fc9bc67b91300d9d2591b51e36a782e77ab5904662effa9382d9cca201f525 -8be5a5f6bc8d680e5092d6f9a6585acbaaaa2ddc671da560dcf5cfa4472f4f184b9597b5b539438accd40dda885687cc -b1fc0f052fae038a2e3de3b3a96b0a1024b009de8457b8b3adb2d315ae68a89af905720108a30038e5ab8d0d97087785 -8b8bdc77bd3a6bc7ca5492b6f8c614852c39a70d6c8a74916eaca0aeb4533b11898b8820a4c2620a97bf35e275480029 -af35f4dc538d4ad5cdf710caa38fd1eb496c3fa890a047b6a659619c5ad3054158371d1e88e0894428282eed9f47f76b -8166454a7089cc07758ad78724654f4e7a1a13e305bbf88ddb86f1a4b2904c4fc8ab872d7da364cdd6a6c0365239e2ad -ab287c7d3addce74ce40491871c768abe01daaa0833481276ff2e56926b38a7c6d2681ffe837d2cc323045ad1a4414f9 -b90317f4505793094d89365beb35537f55a6b5618904236258dd04ca61f21476837624a2f45fef8168acf732cab65579 -98ae5ea27448e236b6657ab5ef7b1cccb5372f92ab25f5fa651fbac97d08353a1dae1b280b1cd42b17d2c6a70a63ab9d -adcf54e752d32cbaa6cb98fbca48d8cd087b1db1d131d465705a0d8042c8393c8f4d26b59006eb50129b21e6240f0c06 -b591a3e4db18a7345fa935a8dd7994bbac5cc270b8ebd84c8304c44484c7a74afb45471fdbe4ab22156a30fae1149b40 -806b53ac049a42f1dcc1d6335505371da0bf27c614f441b03bbf2e356be7b2fb4eed7117eabcce9e427a542eaa2bf7d8 -800482e7a772d49210b81c4a907f5ce97f270b959e745621ee293cf8c71e8989363d61f66a98f2d16914439544ca84c7 -99de9eafdad3617445312341644f2bb888680ff01ce95ca9276b1d2e5ef83fa02dab5e948ebf66c17df0752f1bd37b70 -961ee30810aa4c93ae157fbe9009b8e443c082192bd36a73a6764ff9b2ad8b0948fe9a73344556e01399dd77badb4257 -ae0a361067c52efbe56c8adf982c00432cd478929459fc7f74052c8ee9531cd031fe1335418fde53f7c2ef34254eb7ac -a3503d16b6b27eb20c1b177bcf90d13706169220523a6271b85b2ce35a9a2b9c5bed088540031c0a4ebfdae3a4c6ab04 -909420122c3e723289ca4e7b81c2df5aff312972a2203f4c45821b176e7c862bf9cac7f7df3adf1d59278f02694d06e7 -989f42380ae904b982f85d0c6186c1aef5d6bcba29bcfbb658e811b587eb2749c65c6e4a8cc6409c229a107499a4f5d7 -8037a6337195c8e26a27ea4ef218c6e7d79a9720aaab43932d343192abc2320fe72955f5e431c109093bda074103330a -b312e168663842099b88445e940249cc508f080ab0c94331f672e7760258dbd86be5267e4cf25ea25facb80bff82a7e9 -aaa3ff8639496864fcdbfdda1ac97edc4f08e3c9288b768f6c8073038c9fbbf7e1c4bea169b4d45c31935cdf0680d45e -97dbd3df37f0b481a311dfc5f40e59227720f367912200d71908ef6650f32cc985cb05b981e3eea38958f7e48d10a15d -a89d49d1e267bb452d6cb621b9a90826fe55e9b489c0427b94442d02a16f390eed758e209991687f73f6b5a032321f42 -9530dea4e0e19d6496f536f2e75cf7d814d65fde567055eb20db48fd8d20d501cd2a22fb506db566b94c9ee10f413d43 -81a7009b9e67f1965fa7da6a57591c307de91bf0cd35ab4348dc4a98a4961e096d004d7e7ad318000011dc4342c1b809 -83440a9402b766045d7aca61a58bba2aa29cac1cf718199e472ba086f5d48093d9dda4d135292ba51d049a23964eceae -a06c9ce5e802df14f6b064a3d1a0735d429b452f0e2e276042800b0a4f16df988fd94cf3945921d5dd3802ab2636f867 -b1359e358b89936dee9e678a187aad3e9ab14ac40e96a0a68f70ee2583cdcf467ae03bef4215e92893f4e12f902adec8 -835304f8619188b4d14674d803103d5a3fa594d48e96d9699e653115dd05fdc2dda6ba3641cf7ad53994d448da155f02 -8327cba5a9ff0d3f5cd0ae55e77167448926d5fcf76550c0ad978092a14122723090c51c415e88e42a2b62eb07cc3981 -b373dcdaea85f85ce9978b1426a7ef4945f65f2d3467a9f1cc551a99766aac95df4a09e2251d3f89ca8c9d1a7cfd7b0e -ab1422dc41af2a227b973a6fd124dfcb2367e2a11a21faa1d381d404f51b7257e5bc82e9cf20cd7fe37d7ae761a2ab37 -a93774a03519d2f20fdf2ef46547b0a5b77c137d6a3434b48d56a2cbef9e77120d1b85d0092cf8842909213826699477 -8eb967a495a38130ea28711580b7e61bcd1d051cd9e4f2dbf62f1380bd86e0d60e978d72f6f31e909eb97b3b9a2b867c -ae8213378da1287ba1fe4242e1acaec19b877b6fe872400013c6eac1084b8d03156792fa3020201725b08228a1e80f49 -b143daf6893d674d607772b3b02d8ac48f294237e2f2c87963c0d4e26d9227d94a2a13512457c3d5883544bbc259f0ef -b343bd2aca8973888e42542218924e2dda2e938fd1150d06878af76f777546213912b7c7a34a0f94186817d80ffa185c -b188ebc6a8c3007001aa347ae72cc0b15d09bc6c19a80e386ee4b334734ec0cc2fe8b493c2422f38d1e6d133cc3db6fe -b795f6a8b9b826aaeee18ccd6baf6c5adeeec85f95eb5b6d19450085ec7217e95a2d9e221d77f583b297d0872073ba0e -b1c7dbd998ad32ae57bfa95deafa147024afd57389e98992c36b6e52df915d3d5a39db585141ec2423173e85d212fed8 -812bcdeb9fe5f12d0e1df9964798056e1f1c3de3b17b6bd2919b6356c4b86d8e763c01933efbe0224c86a96d5198a4be -b19ebeda61c23d255cbf472ef0b8a441f4c55b70f0d8ed47078c248b1d3c7c62e076b43b95c00a958ec8b16d5a7cb0d7 -b02adc9aaa20e0368a989c2af14ff48b67233d28ebee44ff3418bb0473592e6b681af1cc45450bd4b175df9051df63d9 -8d87f0714acee522eb58cec00360e762adc411901dba46adc9227124fa70ee679f9a47e91a6306d6030dd4eb8de2f3c1 -8be54cec21e74bcc71de29dc621444263737db15f16d0bb13670f64e42f818154e04b484593d19ef95f2ee17e4b3fe21 -ab8e20546c1db38d31493b5d5f535758afb17e459645c1b70813b1cf7d242fd5d1f4354a7c929e8f7259f6a25302e351 -89f035a1ed8a1e302ac893349ba8ddf967580fcb6e73d44af09e3929cde445e97ff60c87dafe489e2c0ab9c9986cfa00 -8b2b0851a795c19191a692af55f7e72ad2474efdc5401bc3733cfdd910e34c918aaebe69d5ea951bdddf3c01cabbfc67 -a4edb52c2b51495ccd1ee6450fc14b7b3ede8b3d106808929d02fb31475bacb403e112ba9c818d2857651e508b3a7dd1 -9569341fded45d19f00bcf3cbf3f20eb2b4d82ef92aba3c8abd95866398438a2387437e580d8b646f17cf6fde8c5af23 -aa4b671c6d20f72f2f18a939a6ff21cc37e0084b44b4a717f1be859a80b39fb1be026b3205adec2a66a608ec2bcd578f -94902e980de23c4de394ad8aec91b46f888d18f045753541492bfbb92c59d3daa8de37ae755a6853744af8472ba7b72b -af651ef1b2a0d30a7884557edfad95b6b5d445a7561caebdc46a485aedd25932c62c0798465c340a76f6feaa196dd712 -b7b669b8e5a763452128846dd46b530dca4893ace5cc5881c7ddcd3d45969d7e73fbebdb0e78aa81686e5f7b22ec5759 -82507fd4ebe9fa656a7f2e084d64a1fa6777a2b0bc106d686e2d9d2edafc58997e58cb6bfd0453b2bf415704aa82ae62 -b40bce2b42b88678400ecd52955bbdadd15f8b9e1b3751a1a3375dc0efb5ca3ee258cf201e1140b3c09ad41217d1d49e -b0210d0cbb3fbf3b8cdb39e862f036b0ff941cd838e7aaf3a8354e24246e64778d22f3de34572e6b2a580614fb6425be -876693cba4301b251523c7d034108831df3ce133d8be5a514e7a2ca494c268ca0556fa2ad8310a1d92a16b55bcd99ea9 -8660281406d22a4950f5ef050bf71dd3090edb16eff27fa29ef600cdea628315e2054211ed2cc6eaf8f2a1771ef689fd -a610e7e41e41ab66955b809ba4ade0330b8e9057d8efc9144753caed81995edeb1a42a53f93ce93540feca1fae708dac -a49e2c176a350251daef1218efaccc07a1e06203386ede59c136699d25ca5cb2ac1b800c25b28dd05678f14e78e51891 -83e0915aa2b09359604566080d411874af8c993beba97d4547782fdbe1a68e59324b800ff1f07b8db30c71adcbd102a8 -a19e84e3541fb6498e9bb8a099c495cbfcad113330e0262a7e4c6544495bb8a754b2208d0c2d895c93463558013a5a32 -87f2bd49859a364912023aca7b19a592c60214b8d6239e2be887ae80b69ebdeb59742bdebcfa73a586ab23b2c945586c -b8e8fdddae934a14b57bc274b8dcd0d45ebb95ddbaabef4454e0f6ce7d3a5a61c86181929546b3d60c447a15134d08e1 -87e0c31dcb736ea4604727e92dc1d9a3cf00adcff79df3546e02108355260f3dd171531c3c0f57be78d8b28058fcc8c0 -9617d74e8f808a4165a8ac2e30878c349e1c3d40972006f0787b31ea62d248c2d9f3fc3da83181c6e57e95feedfd0e8c -8949e2cee582a2f8db86e89785a6e46bc1565c2d8627d5b6bf43ba71ffadfab7e3c5710f88dcb5fb2fc6edf6f4fae216 -ad3fa7b0edceb83118972a2935a09f409d09a8db3869f30be3a76f67aa9fb379cabb3a3aff805ba023a331cad7d7eb64 -8c95718a4112512c4efbd496be38bf3ca6cdcaad8a0d128f32a3f9aae57f3a57bdf295a3b372a8c549fda8f4707cffed -88f3261d1e28a58b2dee3fcc799777ad1c0eb68b3560f9b4410d134672d9533532a91ea7be28a041784872632d3c9d80 -b47472a41d72dd2e8b72f5c4f8ad626737dde3717f63d6bc776639ab299e564cbad0a2ad5452a07f02ff49a359c437e5 -9896d21dc2e8aad87b76d6df1654f10cd7bceed4884159d50a818bea391f8e473e01e14684814c7780235f28e69dca6e -82d47c332bbd31bbe83b5eb44a23da76d4a7a06c45d7f80f395035822bc27f62f59281d5174e6f8e77cc9b5c3193d6f0 -95c74cd46206e7f70c9766117c34c0ec45c2b0f927a15ea167901a160e1530d8522943c29b61e03568aa0f9c55926c53 -a89d7757825ae73a6e81829ff788ea7b3d7409857b378ebccd7df73fdbe62c8d9073741cf038314971b39af6c29c9030 -8c1cd212d0b010905d560688cfc036ae6535bc334fa8b812519d810b7e7dcf1bb7c5f43deaa40f097158358987324a7f -b86993c383c015ed8d847c6b795164114dd3e9efd25143f509da318bfba89389ea72a420699e339423afd68b6512fafb -8d06bd379c6d87c6ed841d8c6e9d2d0de21653a073725ff74be1934301cc3a79b81ef6dd0aad4e7a9dc6eac9b73019bc -81af4d2d87219985b9b1202d724fe39ef988f14fef07dfe3c3b11714e90ffba2a97250838e8535eb63f107abfe645e96 -8c5e0af6330a8becb787e4b502f34f528ef5756e298a77dc0c7467433454347f3a2e0bd2641fbc2a45b95e231c6e1c02 -8e2a8f0f04562820dc8e7da681d5cad9fe2e85dd11c785fb6fba6786c57a857e0b3bd838fb849b0376c34ce1665e4837 -a39be8269449bfdfc61b1f62077033649f18dae9bef7c6163b9314ca8923691fb832f42776f0160b9e8abd4d143aa4e1 -8c154e665706355e1cc98e0a4cabf294ab019545ba9c4c399d666e6ec5c869ca9e1faf8fb06cd9c0a5c2f51a7d51b70a -a046a7d4de879d3ebd4284f08f24398e9e3bf006cd4e25b5c67273ade248689c69affff92ae810c07941e4904296a563 -afd94c1cb48758e5917804df03fb38a6da0e48cd9b6262413ea13b26973f9e266690a1b7d9d24bbaf7e82718e0e594b0 -859e21080310c8d6a38e12e2ac9f90a156578cdeb4bb2e324700e97d9a5511cd6045dc39d1d0de3f94aeed043a24119d -a219fb0303c379d0ab50893264919f598e753aac9065e1f23ef2949abc992577ab43c636a1d2c089203ec9ddb941e27d -b0fdb639d449588a2ca730afcba59334e7c387342d56defdfb7ef79c493f7fd0e5277eff18e7203e756c7bdda5803047 -87f9c3b7ed01f54368aca6dbcf2f6e06bff96e183c4b2c65f8baa23b377988863a0a125d5cdd41a072da8462ced4c070 -99ef7a5d5ac2f1c567160e1f8c95f2f38d41881850f30c461a205f7b1b9fb181277311333839b13fb3ae203447e17727 -aeaca9b1c2afd24e443326cc68de67b4d9cedb22ad7b501a799d30d39c85bb2ea910d4672673e39e154d699e12d9b3dc -a11675a1721a4ba24dd3d0e4c3c33a6edf4cd1b9f6b471070b4386c61f77452266eae6e3f566a40cfc885eada9a29f23 -b228334445e37b9b49cb4f2cc56b454575e92173ddb01370a553bba665adadd52df353ad74470d512561c2c3473c7bb9 -a18177087c996572d76f81178d18ed1ceebc8362a396348ce289f1d8bd708b9e99539be6fccd4acb1112381cfc5749b4 -8e7b8bf460f0d3c99abb19803b9e43422e91507a1c0c22b29ee8b2c52d1a384da4b87c292e28eff040db5be7b1f8641f -b03d038d813e29688b6e6f444eb56fec3abba64c3d6f890a6bcf2e916507091cdb2b9d2c7484617be6b26552ed1c56cb -a1c88ccd30e934adfc5494b72655f8afe1865a84196abfb376968f22ddc07761210b6a9fb7638f1413d1b4073d430290 -961b714faebf172ad2dbc11902461e286e4f24a99a939152a53406117767682a571057044decbeb3d3feef81f4488497 -a03dc4059b46effdd786a0a03cc17cfee8585683faa35bb07936ded3fa3f3a097f518c0b8e2db92fd700149db1937789 -adf60180c99ca574191cbcc23e8d025b2f931f98ca7dfcebfc380226239b6329347100fcb8b0fcb12db108c6ad101c07 -805d4f5ef24d46911cbf942f62cb84b0346e5e712284f82b0db223db26d51aabf43204755eb19519b00e665c7719fcaa -8dea7243e9c139662a7fe3526c6c601eee72fd8847c54c8e1f2ad93ef7f9e1826b170afe58817dac212427164a88e87f -a2ba42356606d651b077983de1ad643650997bb2babb188c9a3b27245bb65d2036e46667c37d4ce02cb1be5ae8547abe -af2ae50b392bdc013db2d12ce2544883472d72424fc767d3f5cb0ca2d973fc7d1f425880101e61970e1a988d0670c81b -98e6bec0568d3939b31d00eb1040e9b8b2a35db46ddf4369bdaee41bbb63cc84423d29ee510a170fb5b0e2df434ba589 -822ff3cd12fbef4f508f3ca813c04a2e0b9b799c99848e5ad3563265979e753ee61a48f6adc2984a850f1b46c1a43d35 -891e8b8b92a394f36653d55725ef514bd2e2a46840a0a2975c76c2a935577f85289026aaa74384da0afe26775cbddfb9 -b2a3131a5d2fe7c8967047aa66e4524babae941d90552171cc109527f345f42aa0df06dcbb2fa01b33d0043917bbed69 -80c869469900431f3eeefafdbe07b8afd8cee7739e659e6d0109b397cacff85a88247698f87dc4e2fe39a592f250ac64 -9091594f488b38f9d2bb5df49fd8b4f8829d9c2f11a197dd1431ed5abbc5c954bbde3387088f9ee3a5a834beb7619bce -b472e241e6956146cca57b97a8a204668d050423b4e76f857bad5b47f43b203a04c8391ba9d9c3e95093c071f9d376a1 -b7dd2de0284844392f7dfb56fe7ca3ede41e27519753ffc579a0a8d2d65ceb8108d06b6b0d4c3c1a2588951297bd1a1e -902116ce70d0a079ac190321c1f48701318c05f8e69ee09694754885d33a835a849cafe56f499a2f49f6cda413ddf9a7 -b18105cc736787fafaf7c3c11c448bce9466e683159dff52723b7951dff429565e466e4841d982e3aaa9ee2066838666 -97ab9911f3f659691762d568ae0b7faa1047b0aed1009c319fa79d15d0db8db9f808fc385dc9a68fa388c10224985379 -b2a2cba65f5b927e64d2904ba412e2bac1cf18c9c3eda9c72fb70262497ecf505b640827e2afebecf10eebbcf48ccd3e -b36a3fd677baa0d3ef0dac4f1548ff50a1730286b8c99d276a0a45d576e17b39b3cbadd2fe55e003796d370d4be43ce3 -a5dfec96ca3c272566e89dc453a458909247e3895d3e44831528130bc47cc9d0a0dac78dd3cad680a4351d399d241967 -8029382113909af6340959c3e61db27392531d62d90f92370a432aec3eb1e4c36ae1d4ef2ba8ec6edb4d7320c7a453f6 -971d85121ea108e6769d54f9c51299b0381ece8b51d46d49c89f65bedc123bab4d5a8bc14d6f67f4f680077529cbae4c -98ff6afc01d0bec80a278f25912e1b1ebff80117adae72e31d5b9fa4d9624db4ba2065b444df49b489b0607c45e26c4c -8fa29be10fb3ab30ce25920fec0187e6e91e458947009dabb869aade7136c8ba23602682b71e390c251f3743164cbdaa -b3345c89eb1653418fe3940cf3e56a9a9c66526389b98f45ca02dd62bfb37baa69a4baaa7132d7320695f8ea6ad1fd94 -b72c7f5541c9ac6b60a7ec9f5415e7fb14da03f7164ea529952a29399f3a071576608dbbcc0d45994f21f92ddbeb1e19 -aa3450bb155a5f9043d0ef95f546a2e6ade167280bfb75c9f09c6f9cdb1fffb7ce8181436161a538433afa3681c7a141 -92a18fecaded7854b349f441e7102b638ababa75b1b0281dd0bded6541abe7aa37d96693595be0b01fe0a2e2133d50f9 -980756ddf9d2253cfe6c94960b516c94889d09e612810935150892627d2ecee9a2517e04968eea295d0106850c04ca44 -ae68c6ccc454318cdd92f32b11d89116a3b8350207a36d22a0f626718cad671d960090e054c0c77ac3162ae180ecfd4b -99f31f66eaaa551749ad91d48a0d4e3ff4d82ef0e8b28f3184c54e852422ba1bdafd53b1e753f3a070f3b55f3c23b6a2 -a44eaeaa6589206069e9c0a45ff9fc51c68da38d4edff1d15529b7932e6f403d12b9387019c44a1488a5d5f27782a51f -b80b5d54d4b344840e45b79e621bd77a3f83fb4ce6d8796b7d6915107b3f3c34d2e7d95bdafd120f285669e5acf2437a -b36c069ec085a612b5908314d6b84c00a83031780261d1c77a0384c406867c9847d5b0845deddfa512cc04a8df2046fb -b09dbe501583220f640d201acea7ee3e39bf9eda8b91aa07b5c50b7641d86d71acb619b38d27835ce97c3759787f08e9 -87403d46a2bf63170fff0b857acacf42ee801afe9ccba8e5b4aea967b68eac73a499a65ca46906c2eb4c8f27bc739faa -82b93669f42a0a2aa5e250ffe6097269da06a9c02fcd1801abbad415a7729a64f830754bafc702e64600ba47671c2208 -8e3a3029be7edb8dd3ab1f8216664c8dc50d395f603736061d802cef77627db7b859ef287ed850382c13b4d22d6a2d80 -968e9ec7194ff424409d182ce0259acd950c384c163c04463bc8700a40b79beba6146d22b7fa7016875a249b7b31c602 -8b42c984bbe4996e0c20862059167c6bdc5164b1ffcd928f29512664459212d263e89f0f0e30eed4e672ffa5ed0b01b5 -96bac54062110dada905363211133f1f15dc7e4fd80a4c6e4a83bc9a0bcbbaba11cd2c7a13debcf0985e1a954c1da66b -a16dc8a653d67a7cd7ae90b2fffac0bf1ca587005430fe5ba9403edd70ca33e38ba5661d2ed6e9d2864400d997626a62 -a68ab11a570a27853c8d67e491591dcba746bfbee08a2e75ae0790399130d027ed387f41ef1d7de8df38b472df309161 -92532b74886874447c0300d07eda9bbe4b41ed25349a3da2e072a93fe32c89d280f740d8ff70d5816793d7f2b97373cc -88e35711b471e89218fd5f4d0eadea8a29405af1cd81974427bc4a5fb26ed60798daaf94f726c96e779b403a2cd82820 -b5c72aa4147c19f8c4f3a0a62d32315b0f4606e0a7025edc5445571eaf4daff64f4b7a585464821574dd50dbe1b49d08 -9305d9b4095258e79744338683fd93f9e657367b3ab32d78080e51d54eec331edbc224fad5093ebf8ee4bd4286757eb8 -b2a17abb3f6a05bcb14dc7b98321fa8b46d299626c73d7c6eb12140bf4c3f8e1795250870947af817834f033c88a59d6 -b3477004837dbd8ba594e4296f960fc91ab3f13551458445e6c232eb04b326da803c4d93e2e8dcd268b4413305ff84da -924b4b2ebaafdcfdfedb2829a8bf46cd32e1407d8d725a5bd28bdc821f1bafb3614f030ea4352c671076a63494275a3f -8b81b9ef6125c82a9bece6fdcb9888a767ac16e70527753428cc87c56a1236e437da8be4f7ecfe57b9296dc3ae7ba807 -906e19ec8b8edd58bdf9ae05610a86e4ea2282b1bbc1e8b00b7021d093194e0837d74cf27ac9916bdb8ec308b00da3da -b41c5185869071760ac786078a57a2ab4e2af60a890037ac0c0c28d6826f15c2cf028fddd42a9b6de632c3d550bfbc14 -a646e5dec1b713ae9dfdf7bdc6cd474d5731a320403c7dfcfd666ffc9ae0cff4b5a79530e8df3f4aa9cb80568cb138e9 -b0efad22827e562bd3c3e925acbd0d9425d19057868608d78c2209a531cccd0f2c43dc5673acf9822247428ffa2bb821 -a94c19468d14b6f99002fc52ac06bbe59e5c472e4a0cdb225144a62f8870b3f10593749df7a2de0bd3c9476ce682e148 -803864a91162f0273d49271dafaab632d93d494d1af935aefa522768af058fce52165018512e8d6774976d52bd797e22 -a08711c2f7d45c68fb340ac23597332e1bcaec9198f72967b9921204b9d48a7843561ff318f87908c05a44fc35e3cc9d -91c3cad94a11a3197ae4f9461faab91a669e0dddb0371d3cab3ed9aeb1267badc797d8375181130e461eadd05099b2a2 -81bdaaf48aae4f7b480fc13f1e7f4dd3023a41439ba231760409ce9292c11128ab2b0bdbbf28b98af4f97b3551f363af -8d60f9df9fd303f625af90e8272c4ecb95bb94e6efc5da17b8ab663ee3b3f673e9f6420d890ccc94acf4d2cae7a860d8 -a7b75901520c06e9495ab983f70b61483504c7ff2a0980c51115d11e0744683ce022d76e3e09f4e99e698cbd21432a0d -82956072df0586562fda7e7738226f694e1c73518dd86e0799d2e820d7f79233667192c9236dcb27637e4c65ef19d493 -a586beb9b6ffd06ad200957490803a7cd8c9bf76e782734e0f55e04a3dc38949de75dc607822ec405736c576cf83bca3 -a179a30d00def9b34a7e85607a447eea0401e32ab5abeee1a281f2acd1cf6ec81a178020666f641d9492b1bdf66f05a3 -83e129705c538787ed8e0fdc1275e6466a3f4ee21a1e6abedd239393b1df72244723b92f9d9d9339a0cab6ebf28f5a16 -811bd8d1e3722b64cd2f5b431167e7f91456e8bba2cc669d3fbbce7d553e29c3c19f629fcedd2498bc26d33a24891d17 -a243c030c858f1f60cccd26b45b024698cc6d9d9e6198c1ed4964a235d9f8d0baf9cde10c8e63dfaa47f8e74e51a6e85 -ab839eb82e23ca52663281f863b55b0a3d6d4425c33ffb4eeb1d7979488ab068bf99e2a60e82cea4dc42c56c26cbfebe -8b896f9bb21d49343e67aec6ad175b58c0c81a3ca73d44d113ae4354a0065d98eb1a5cafedaf232a2bb9cdc62152f309 -af6230340cc0b66f5bf845540ed4fc3e7d6077f361d60762e488d57834c3e7eb7eacc1b0ed73a7d134f174a01410e50c -88975e1b1af678d1b5179f72300a30900736af580dd748fd9461ef7afccc91ccd9bed33f9da55c8711a7635b800e831f -a97486bb9047391661718a54b8dd5a5e363964e495eae6c692730264478c927cf3e66dd3602413189a3699fbeae26e15 -a5973c161ab38732885d1d2785fd74bf156ba34881980cba27fe239caef06b24a533ffe6dbbbeca5e6566682cc00300a -a24776e9a840afda0003fa73b415d5bd6ecd9b5c2cc842b643ee51b8c6087f4eead4d0bfbd987eb174c489a7b952ff2a -a8a6ee06e3af053b705a12b59777267c546f33ba8a0f49493af8e6df4e15cf8dd2d4fb4daf7e84c6b5d3a7363118ff03 -a28e59ce6ad02c2ce725067c0123117e12ac5a52c8f5af13eec75f4a9efc4f696777db18a374fa33bcae82e0734ebd16 -86dfc3b78e841c708aff677baa8ee654c808e5d257158715097c1025d46ece94993efe12c9d188252ad98a1e0e331fec -a88d0275510f242eab11fdb0410ff6e1b9d7a3cbd3658333539815f1b450a84816e6613d15aa8a8eb15d87cdad4b27a2 -8440acea2931118a5b481268ff9f180ee4ede85d14a52c026adc882410825b8275caa44aff0b50c2b88d39f21b1a0696 -a7c3182eab25bd6785bacf12079d0afb0a9b165d6ed327814e2177148539f249eb9b5b2554538f54f3c882d37c0a8abe -85291fbe10538d7da38efdd55a7acebf03b1848428a2f664c3ce55367aece60039f4f320b1771c9c89a35941797f717c -a2c6414eeb1234728ab0de94aa98fc06433a58efa646ca3fcbd97dbfb8d98ae59f7ce6d528f669c8149e1e13266f69c9 -840c8462785591ee93aee2538d9f1ec44ba2ca61a569ab51d335ac873f5d48099ae8d7a7efa0725d9ff8f9475bfa4f56 -a7065a9d02fb3673acf7702a488fbc01aa69580964932f6f40b6c2d1c386b19e50b0e104fcac24ea26c4e723611d0238 -b72db6d141267438279e032c95e6106c2ccb3164b842ba857a2018f3a35f4b040da92680881eb17cd61d0920d5b8f006 -a8005d6c5960e090374747307ef0be2871a7a43fa4e76a16c35d2baab808e9777b496e9f57a4218b23390887c33a0b55 -8e152cea1e00a451ca47c20a1e8875873419700af15a5f38ee2268d3fbc974d4bd5f4be38008fa6f404dbdedd6e6e710 -a3391aed1fcd68761f06a7d1008ec62a09b1cb3d0203cd04e300a0c91adfed1812d8bc1e4a3fd7976dc0aae0e99f52f1 -967eb57bf2aa503ee0c6e67438098149eac305089c155f1762cf5e84e31f0fbf27c34a9af05621e34645c1ec96afaec8 -88af97ddc4937a95ec0dcd25e4173127260f91c8db2f6eac84afb789b363705fb3196235af631c70cafd09411d233589 -a32df75b3f2c921b8767638fd289bcfc61e08597170186637a7128ffedd52c798c434485ac2c7de07014f9e895c2c3d8 -b0a783832153650aa0d766a3a73ec208b6ce5caeb40b87177ffc035ab03c7705ecdd1090b6456a29f5fb7e90e2fa8930 -b59c8e803b4c3486777d15fc2311b97f9ded1602fa570c7b0200bada36a49ee9ef4d4c1474265af8e1c38a93eb66b18b -982f2c85f83e852022998ff91bafbb6ff093ef22cf9d5063e083a48b29175ccbd51b9c6557151409e439096300981a6c -939e3b5989fefebb9d272a954659a4eb125b98c9da6953f5e628d26266bd0525ec38304b8d56f08d65abc4d6da4a8dbb -8898212fe05bc8de7d18503cb84a1c1337cc2c09d1eeef2b475aa79185b7322bf1f8e065f1bf871c0c927dd19faf1f6d -94b0393a41cd00f724aee2d4bc72103d626a5aecb4b5486dd1ef8ac27528398edf56df9db5c3d238d8579af368afeb09 -96ac564450d998e7445dd2ea8e3fc7974d575508fa19e1c60c308d83b645864c029f2f6b7396d4ff4c1b24e92e3bac37 -8adf6638e18aff3eb3b47617da696eb6c4bdfbecbbc3c45d3d0ab0b12cbad00e462fdfbe0c35780d21aa973fc150285e -b53f94612f818571b5565bbb295e74bada9b5f9794b3b91125915e44d6ddcc4da25510eab718e251a09c99534d6042d9 -8b96462508d77ee083c376cd90807aebad8de96bca43983c84a4a6f196d5faf6619a2351f43bfeec101864c3bf255519 -aeadf34657083fc71df33bd44af73bf5281c9ca6d906b9c745536e1819ea90b56107c55e2178ebad08f3ba75b3f81c86 -9784ba29b2f0057b5af1d3ab2796d439b8753f1f749c73e791037461bdfc3f7097394283105b8ab01788ea5255a96710 -8756241bda159d4a33bf74faba0d4594d963c370fb6a18431f279b4a865b070b0547a6d1613cf45b8cfb5f9236bbf831 -b03ebfd6b71421dfd49a30460f9f57063eebfe31b9ceaa2a05c37c61522b35bdc09d7db3ad75c76c253c00ba282d3cd2 -b34e7e6341fa9d854b2d3153bdda0c4ae2b2f442ab7af6f99a0975d45725aa48e36ae5f7011edd249862e91f499687d4 -b462ee09dc3963a14354244313e3444de5cc37ea5ccfbf14cd9aca8027b59c4cb2a949bc30474497cab8123e768460e6 -aea753290e51e2f6a21a9a0ee67d3a2713f95c2a5c17fe41116c87d3aa77b1683761264d704df1ac34f8b873bc88ef7b -98430592afd414394f98ddfff9f280fcb1c322dbe3510f45e1e9c4bb8ee306b3e0cf0282c0ee73ebb8ba087d4d9e0858 -b95d3b5aaf54ffca11f4be8d57f76e14afdb20afc859dc7c7471e0b42031e8f3d461b726ecb979bdb2f353498dfe95ea -984d17f9b11a683132e0b5a9ee5945e3ff7054c2d5c716be73b29078db1d36f54c6e652fd2f52a19da313112e97ade07 -ab232f756b3fff3262be418a1af61a7e0c95ceebbc775389622a8e10610508cd6784ab7960441917a83cc191c58829ea -a28f41678d6e60de76b0e36ab10e4516e53e02e9c77d2b5af3cfeee3ce94cfa30c5797bd1daab20c98e1cad83ad0f633 -b55395fca84dd3ccc05dd480cb9b430bf8631ff06e24cb51d54519703d667268c2f8afcde4ba4ed16bece8cc7bc8c6e0 -8a8a5392a0e2ea3c7a8c51328fab11156004e84a9c63483b64e8f8ebf18a58b6ffa8fe8b9d95af0a2f655f601d096396 -ab480000fe194d23f08a7a9ec1c392334e9c687e06851f083845121ce502c06b54dda8c43092bcc1035df45cc752fe9b -b265644c29f628d1c7e8e25a5e845cabb21799371814730a41a363e1bda8a7be50fee7c3996a365b7fcba4642add10db -b8a915a3c685c2d4728f6931c4d29487cad764c5ce23c25e64b1a3259ac27235e41b23bfe7ae982921b4cb84463097df -8efa7338442a4b6318145a5440fc213b97869647eeae41b9aa3c0a27ee51285b73e3ae3b4a9423df255e6add58864aa9 -9106d65444f74d217f4187dfc8fcf3810b916d1e4275f94f6a86d1c4f3565b131fd6cde1fa708bc05fe183c49f14941a -948252dac8026bbbdb0a06b3c9d66ec4cf9532163bab68076fda1bd2357b69e4b514729c15aaa83b5618b1977bbc60c4 -ae6596ccfdf5cbbc5782efe3bb0b101bb132dbe1d568854ca24cacc0b2e0e9fabcb2ca7ab42aecec412efd15cf8cb7a2 -84a0b6c198ff64fd7958dfd1b40eac9638e8e0b2c4cd8cf5d8cdf80419baee76a05184bce6c5b635f6bf2d30055476a7 -8893118be4a055c2b3da593dbca51b1ae2ea2469911acfb27ee42faf3e6c3ad0693d3914c508c0b05b36a88c8b312b76 -b097479e967504deb6734785db7e60d1d8034d6ca5ba9552887e937f5e17bb413fccac2c1d1082154ed76609127860ad -a0294e6b9958f244d29943debf24b00b538b3da1116269b6e452bb12dc742226712fd1a15b9c88195afeb5d2415f505c -b3cc15f635080bc038f61b615f62b5b5c6f2870586191f59476e8368a73641d6ac2f7d0c1f54621982defdb318020230 -99856f49b9fe1604d917c94d09cc0ed753d13d015d30587a94e6631ffd964b214e607deb8a69a8b5e349a7edf4309206 -a8571e113ea22b4b4fce41a094da8c70de37830ae32e62c65c2fa5ad06a9bc29e884b945e73d448c72b176d6ecebfb58 -a9e9c6e52beb0013273c29844956b3ce291023678107cdc785f7b44eff5003462841ad8780761b86aefc6b734adde7cf -80a784b0b27edb51ef2bad3aee80e51778dcaa0f3f5d3dcb5dc5d4f4b2cf7ae35b08de6680ea9dac53f8438b92eb09ef -827b543e609ea328e97e373f70ad72d4915a2d1daae0c60d44ac637231070e164c43a2a58db80a64df1c624a042b38f9 -b449c65e8195202efdcb9bdb4e869a437313b118fef8b510cbbf8b79a4e99376adb749b37e9c20b51b31ed3310169e27 -8ea3028f4548a79a94c717e1ed28ad4d8725b8d6ab18b021063ce46f665c79da3c49440c6577319dab2d036b7e08f387 -897798431cfb17fe39f08f5f854005dc37b1c1ec1edba6c24bc8acb3b88838d0534a75475325a5ea98b326ad47dbad75 -89cf232e6303b0751561960fd4dea5754a28c594daf930326b4541274ffb03c7dd75938e411eb9a375006a70ce38097f -9727c6ae7f0840f0b6c8bfb3a1a5582ceee705e0b5c59b97def7a7a2283edd4d3f47b7971e902a3a2079e40b53ff69b8 -b76ed72b122c48679d221072efc0eeea063cb205cbf5f9ef0101fd10cb1075b8628166c83577cced654e1c001c7882f7 -ae908c42d208759da5ee9b405df85a6532ea35c6f0f6a1288d22870f59d98edc896841b8ac890a538e6c8d1e8b02d359 -809d12fe4039a0ec80dc9be6a89acaab7797e5f7f9b163378f52f9a75a1d73b2e9ae6e3dd49e32ced439783c1cabbef5 -a4149530b7f85d1098ba534d69548c6c612c416e8d35992fc1f64f4deeb41e09e49c6cf7aadbed7e846b91299358fe2d -a49342eacd1ec1148b8df1e253b1c015f603c39de11fa0a364ccb86ea32d69c34fd7aa6980a1fadcd8e785a57fa46f60 -87d43eff5a006dc4dddcf76cc96c656a1f3a68f19f124181feab86c6cc9a52cb9189cdbb423414defdd9bb0ca8ff1ddc -861367e87a9aa2f0f68296ba50aa5dbc5713008d260cc2c7e62d407c2063064749324c4e8156dc21b749656cfebce26b -b5303c2f72e84e170e66ae1b0fbd51b8c7a6f27476eaf5694b64e8737d5c84b51fe90100b256465a4c4156dd873cddb0 -b62849a4f891415d74f434cdc1d23c4a69074487659ca96e1762466b2b7a5d8525b056b891d0feea6fe6845cba8bc7fb -923dd9e0d6590a9307e8c4c23f13bae3306b580e297a937711a8b13e8de85e41a61462f25b7d352b682e8437bf2b4ab3 -9147379860cd713cd46c94b8cdf75125d36c37517fbecf81ace9680b98ce6291cd1c3e472f84249cc3b2b445e314b1b6 -a808a4f17ac21e3fb5cfef404e61fae3693ca3e688d375f99b6116779696059a146c27b06de3ac36da349b0649befd56 -87787e9322e1b75e66c1f0d9ea0915722a232770930c2d2a95e9478c4b950d15ab767e30cea128f9ed65893bfc2d0743 -9036a6ee2577223be105defe1081c48ea7319e112fff9110eb9f61110c319da25a6cea0464ce65e858635b079691ef1f -af5548c7c24e1088c23b57ee14d26c12a83484c9fd9296edf1012d8dcf88243f20039b43c8c548c265ef9a1ffe9c1c88 -a0fff520045e14065965fb8accd17e878d3fcaf9e0af2962c8954e50be6683d31fa0bf4816ab68f08630dbac6bfce52a -b4c1b249e079f6ae1781af1d97a60b15855f49864c50496c09c91fe1946266915b799f0406084d7783f5b1039116dd8b -8b0ffa5e7c498cb3879dddca34743b41eee8e2dea3d4317a6e961b58adb699ef0c92400c068d5228881a2b08121226bf -852ae8b19a1d80aa8ae5382e7ee5c8e7670ceb16640871c56b20b96b66b3b60e00015a3dde039446972e57b49a999ddd -a49942f04234a7d8492169da232cfff8051df86e8e1ba3db46aede02422c689c87dc1d99699c25f96cb763f5ca0983e5 -b04b597b7760cf5dcf411ef896d1661e6d5b0db3257ac2cf64b20b60c6cc18fa10523bb958a48d010b55bac7b02ab3b1 -a494591b51ea8285daecc194b5e5bd45ae35767d0246ac94fae204d674ee180c8e97ff15f71f28b7aeb175b8aea59710 -97d2624919e78406e7460730680dea8e71c8571cf988e11441aeea54512b95bd820e78562c99372d535d96f7e200d20d -ac693ddb00e48f76e667243b9b6a7008424043fb779e4f2252330285232c3fccac4da25cbd6d95fe9ad959ff305a91f6 -8d20ca0a71a64a3f702a0825bb46bd810d03bebfb227683680d474a52f965716ff99e19a165ebaf6567987f4f9ee3c94 -a5c516a438f916d1d68ca76996404792e0a66e97b7f18fc54c917bf10cf3211b62387932756e39e67e47b0bd6e88385a -b089614d830abc0afa435034cec7f851f2f095d479cacf1a3fb57272da826c499a52e7dcbc0eb85f4166fb94778e18e9 -a8dacc943765d930848288192f4c69e2461c4b9bc6e79e30eeef9a543318cf9ae9569d6986c65c5668a89d49993f8e07 -ab5a9361fa339eec8c621bdad0a58078983abd8942d4282b22835d7a3a47e132d42414b7c359694986f7db39386c2e19 -94230517fb57bd8eb26c6f64129b8b2abd0282323bf7b94b8bac7fab27b4ecc2c4290c294275e1a759de19f2216134f3 -b8f158ea5006bc3b90b285246625faaa6ac9b5f5030dc69701b12f3b79a53ec7e92eeb5a63bbd1f9509a0a3469ff3ffc -8b6944fd8cb8540957a91a142fdcda827762aa777a31e8810ca6d026e50370ee1636fc351724767e817ca38804ebe005 -82d1ee40fe1569c29644f79fa6c4033b7ed45cd2c3b343881f6eb0de2e79548fded4787fae19bed6ee76ed76ff9f2f11 -a8924c7035e99eaed244ca165607e7e568b6c8085510dcdbaf6ebdbed405af2e6c14ee27d94ffef10d30aa52a60bf66d -956f82a6c2ae044635e85812581e4866c5fa2f427b01942047d81f6d79a14192f66fbbe77c9ffeaef4e6147097fdd2b5 -b1100255a1bcf5e05b6aff1dfeb6e1d55b5d68d43a7457ba10cc76b61885f67f4d0d5179abda786e037ae95deb8eea45 -99510799025e3e5e8fbf06dedb14c060c6548ba2bda824f687d3999dc395e794b1fb6514b9013f3892b6cf65cb0d65aa -8f9091cebf5e9c809aab415942172258f894e66e625d7388a05289183f01b8d994d52e05a8e69f784fba41db9ea357f0 -a13d2eeb0776bdee9820ecb6693536720232848c51936bb4ef4fe65588d3f920d08a21907e1fdb881c1ad70b3725e726 -a68b8f18922d550284c5e5dc2dda771f24c21965a6a4d5e7a71678178f46df4d8a421497aad8fcb4c7e241aba26378a0 -8b7601f0a3c6ad27f03f2d23e785c81c1460d60100f91ea9d1cab978aa03b523150206c6d52ce7c7769c71d2c8228e9e -a8e02926430813caa851bb2b46de7f0420f0a64eb5f6b805401c11c9091d3b6d67d841b5674fa2b1dce0867714124cd8 -b7968ecba568b8193b3058400af02c183f0a6df995a744450b3f7e0af7a772454677c3857f99c140bbdb2a09e832e8e0 -8f20b1e9ba87d0a3f35309b985f3c18d2e8800f1ca7f0c52cadef773f1496b6070c936eea48c4a1cae83fd2524e9d233 -88aef260042db0d641a51f40639dbeeefa9e9811df30bee695f3791f88a2f84d318f04e8926b7f47bf25956cb9e3754f -9725345893b647e9ba4e6a29e12f96751f1ae25fcaec2173e9a259921a1a7edb7a47159b3c8767e44d9e2689f5aa0f72 -8c281e6f72752cb11e239e4df9341c45106eb7993c160e54423c2bffe10bc39d42624b45a1f673936ef2e1a02fc92f1a -90aba2f68bddb2fcce6c51430dacdfeec43ea8dc379660c99095df11017691ccf5faa27665cf4b9f0eea7728ae53c327 -b7022695c16521c5704f49b7ddbdbec9b5f57ce0ceebe537bc0ebb0906d8196cc855a9afeb8950a1710f6a654464d93f -8fe1b9dd3c6a258116415d36e08374e094b22f0afb104385a5da48be17123e86fb8327baacc4f0d9ebae923d55d99bb5 -817e85d8e3d19a4cbc1dec31597142c2daa4871bda89c2177fa719c00eda3344eb08b82eb92d4aa91a9eaacb3fc09783 -b59053e1081d2603f1ca0ba553804d6fa696e1fd996631db8f62087b26a40dfef02098b0326bb75f99ec83b9267ca738 -990a173d857d3ba81ff3789b931bfc9f5609cde0169b7f055fa3cb56451748d593d62d46ba33f80f9cafffe02b68dd14 -b0c538dbba4954b809ab26f9f94a3cf1dcb77ce289eaec1d19f556c0ae4be1fa03af4a9b7057837541c3cc0a80538736 -ac3ba42f5f44f9e1fc453ce49c4ab79d0e1d5c42d3b30b1e098f3ab3f414c4c262fa12fb2be249f52d4aaf3c5224beb9 -af47467eb152e59870e21f0d4da2f43e093daf40180ab01438030684b114d025326928eaab12c41b81a066d94fce8436 -98d1b58ba22e7289b1c45c79a24624f19b1d89e00f778eef327ec4856a9a897278e6f1a9a7e673844b31dde949153000 -97ccb15dfadc7c59dca08cfe0d22df2e52c684cf97de1d94bc00d7ba24e020025130b0a39c0f4d46e4fc872771ee7875 -b699e4ed9a000ff96ca296b2f09dce278832bc8ac96851ff3cff99ed3f6f752cfc0fea8571be28cd9b5a7ec36f1a08ee -b9f49f0edb7941cc296435ff0a912e3ad16848ee8765ab5f60a050b280d6ea585e5b34051b15f6b8934ef01ceb85f648 -ac3893df7b4ceab23c6b9054e48e8ba40d6e5beda8fbe90b814f992f52494186969b35d8c4cdc3c99890a222c9c09008 -a41293ad22fae81dea94467bc1488c3707f3d4765059173980be93995fa4fcc3c9340796e3eed0beeb0ba0d9bb4fa3aa -a0543e77acd2aeecde13d18d258aeb2c7397b77f17c35a1992e8666ea7abcd8a38ec6c2741bd929abba2f766138618cc -92e79b22bc40e69f6527c969500ca543899105837b6b1075fa1796755c723462059b3d1b028e0b3df2559fa440e09175 -a1fa1eac8f41a5197a6fb4aa1eae1a031c89f9c13ff9448338b222780cf9022e0b0925d930c37501a0ef7b2b00fdaf83 -b3cb29ff73229f0637335f28a08ad8c5f166066f27c6c175164d0f26766a927f843b987ee9b309ed71cbf0a65d483831 -84d4ab787f0ac00f104f4a734dc693d62d48c2aeb03913153da62c2ae2c27d11b1110dcef8980368dd84682ea2c1a308 -ab6a8e4bbc78d4a7b291ad3e9a8fe2d65f640524ba3181123b09d2d18a9e300e2509ccf7000fe47e75b65f3e992a2e7e -b7805ebe4f1a4df414003dc10bca805f2ab86ca75820012653e8f9b79c405196b0e2cab099f2ab953d67f0d60d31a0f9 -b12c582454148338ea605d22bd00a754109063e22617f1f8ac8ddf5502c22a181c50c216c3617b9852aa5f26af56b323 -86333ad9f898947e31ce747728dc8c887479e18d36ff3013f69ebef807d82c6981543b5c3788af93c4d912ba084d3cba -b514efa310dc4ad1258add138891e540d8c87142a881b5f46563cc58ecd1488e6d3a2fca54c0b72a929f3364ca8c333e -aa0a30f92843cf2f484066a783a1d75a7aa6f41f00b421d4baf20a6ac7886c468d0eea7ca8b17dd22f4f74631b62b640 -b3b7dc63baec9a752e8433c0cdee4d0f9bc41f66f2b8d132faf925eef9cf89aae756fc132c45910f057122462605dc10 -b9b8190dac5bfdeb59fd44f4da41a57e7f1e7d2c21faba9da91fa45cbeca06dcf299c9ae22f0c89ece11ac46352d619f -89f8cf36501ad8bdfeab863752a9090e3bfda57cf8fdeca2944864dc05925f501e252c048221bcc57136ab09a64b64b2 -b0cbfaf317f05f97be47fc9d69eda2dd82500e00d42612f271a1fe24626408c28881f171e855bd5bd67409f9847502b4 -a7c21a8fcede581bfd9847b6835eda62ba250bea81f1bb17372c800a19c732abe03064e64a2f865d974fb636cab4b859 -95f9df524ba7a4667351696c4176b505d8ea3659f5ff2701173064acc624af69a0fad4970963736383b979830cb32260 -856a74fe8b37a2e3afeac858c8632200485d438422a16ae3b29f359e470e8244995c63ad79c7e007ed063f178d0306fd -b37faa4d78fdc0bb9d403674dbea0176c2014a171c7be8527b54f7d1a32a76883d3422a3e7a5f5fcc5e9b31b57822eeb -8d37234d8594ec3fe75670b5c9cc1ec3537564d4739b2682a75b18b08401869a4264c0f264354219d8d896cded715db4 -b5289ee5737f0e0bde485d32096d23387d68dab8f01f47821ab4f06cc79a967afe7355e72dc0c751d96b2747b26f6255 -9085e1fdf9f813e9c3b8232d3c8863cd84ab30d45e8e0d3d6a0abd9ebc6fd70cdf749ff4d04390000e14c7d8c6655fc7 -93a388c83630331eca4da37ea4a97b3b453238af474817cc0a0727fd3138dcb4a22de38c04783ec829c22cb459cb4e8e -a5377116027c5d061dbe24c240b891c08cdd8cd3f0899e848d682c873aff5b8132c1e7cfe76d2e5ed97ee0eb1d42cb68 -a274c84b04338ed28d74683e2a7519c2591a3ce37c294d6f6e678f7d628be2db8eff253ede21823e2df7183e6552f622 -8bc201147a842453a50bec3ac97671397bc086d6dfc9377fa38c2124cdc286abda69b7324f47d64da094ae011d98d9d9 -9842d0c066c524592b76fbec5132bc628e5e1d21c424bec4555efca8619cc1fd8ea3161febcb8b9e8ab54702f4e815e2 -a19191b713a07efe85c266f839d14e25660ee74452e6c691cd9997d85ae4f732052d802d3deb018bdd847caa298a894b -a24f71fc0db504da4e287dd118a4a74301cbcd16033937ba2abc8417956fcb4ae19b8e63b931795544a978137eff51cb -a90eec4a6a3a4b8f9a5b93d978b5026fcf812fe65585b008d7e08c4aaf21195a1d0699f12fc16f79b6a18a369af45771 -8b551cf89737d7d06d9b3b9c4c1c73b41f2ea0af4540999c70b82dabff8580797cf0a3caf34c86c59a7069eb2e38f087 -b8d312e6c635e7a216a1cda075ae77ba3e1d2fd501dc31e83496e6e81ed5d9c7799f8e578869c2e0e256fb29f5de10a7 -8d144bdb8cae0b2cdb5b33d44bbc96984a5925202506a8cc65eb67ac904b466f5a7fe3e1cbf04aa785bbb7348c4bb73c -a101b3d58b7a98659244b88de0b478b3fb87dc5fc6031f6e689b99edf498abd43e151fd32bd4bbd240e0b3e59c440359 -907453abca7d8e7151a05cc3d506c988007692fe7401395dc93177d0d07d114ab6cca0cc658eb94c0223fe8658295cad -825329ffbe2147ddb68f63a0a67f32d7f309657b8e5d9ab5bb34b3730bfa2c77a23eaaadb05def7d9f94a9e08fdc1e96 -88ee923c95c1dac99ae7ed6067906d734d793c5dc5d26339c1bb3314abe201c5dccb33b9007351885eb2754e9a8ea06c -98bc9798543f5f1adc9f2cfcfa72331989420e9c3f6598c45269f0dc9b7c8607bbeaf03faa0aea2ddde2b8f17fdceff5 -8ee87877702a79aef923ab970db6fa81561b3c07d5bf1a072af0a7bad765b4cbaec910afe1a91703feacc7822fa38a94 -8060b9584aa294fe8adc2b22f67e988bc6da768eae91e429dcc43ddc53cfcc5d6753fdc1b420b268c7eb2fb50736a970 -b344a5524d80a2f051870c7001f74fcf348a70fcf78dbd20c6ff9ca85d81567d2318c8b8089f2c4f195d6aec9fc15fa6 -8f5a5d893e1936ed062149d20eb73d98b62b7f50ab5d93a6429c03656b36688d1c80cb5010e4977491e51fa0d7dd35d5 -86fa32ebbf97328c5f5f15564e1238297e289ec3219b9a741724e9f3ae8d5c15277008f555863a478b247ba5dc601d44 -9557e55377e279f4b6b5e0ffe01eca037cc13aac242d67dfcd0374a1e775c5ed5cb30c25fe21143fee54e3302d34a3ea -8cb6bcbc39372d23464a416ea7039f57ba8413cf3f00d9a7a5b356ab20dcb8ed11b3561f7bce372b8534d2870c7ee270 -b5d59075cb5abde5391f64b6c3b8b50adc6e1f654e2a580b6d6d6eff3f4fbdd8fffc92e06809c393f5c8eab37f774c4b -afcfb6903ef13e493a1f7308675582f15af0403b6553e8c37afb8b2808ad21b88b347dc139464367dc260df075fea1ad -810fbbe808375735dd22d5bc7fc3828dc49fdd22cc2d7661604e7ac9c4535c1df578780affb3b895a0831640a945bcad -8056b0c678803b416f924e09a6299a33cf9ad7da6fe1ad7accefe95c179e0077da36815fde3716711c394e2c5ea7127f -8b67403702d06979be19f1d6dc3ec73cc2e81254d6b7d0cc49cd4fdda8cd51ab0835c1d2d26fc0ecab5df90585c2f351 -87f97f9e6d4be07e8db250e5dd2bffdf1390665bc5709f2b631a6fa69a7fca958f19bd7cc617183da1f50ee63e9352b5 -ae151310985940471e6803fcf37600d7fa98830613e381e00dab943aec32c14162d51c4598e8847148148000d6e5af5c -81eb537b35b7602c45441cfc61b27fa9a30d3998fad35a064e05bc9479e9f10b62eba2b234b348219eea3cadcaac64bb -8a441434934180ab6f5bc541f86ebd06eadbee01f438836d797e930fa803a51510e005c9248cecc231a775b74d12b5e9 -81f3c250a27ba14d8496a5092b145629eb2c2e6a5298438670375363f57e2798207832c8027c3e9238ad94ecdadfc4df -a6217c311f2f3db02ceaa5b6096849fe92b6f4b6f1491535ef8525f6ccee6130bed2809e625073ecbaddd4a3eb3df186 -82d1c396f0388b942cf22b119d7ef1ad03d3dad49a74d9d01649ee284f377c8daddd095d596871669e16160299a210db -a40ddf7043c5d72a7246bd727b07f7fff1549f0e443d611de6f9976c37448b21664c5089c57f20105102d935ab82f27b -b6c03c1c97adf0c4bf4447ec71366c6c1bff401ba46236cd4a33d39291e7a1f0bb34bd078ba3a18d15c98993b153a279 -8a94f5f632068399c359c4b3a3653cb6df2b207379b3d0cdace51afdf70d6d5cce6b89a2b0fee66744eba86c98fb21c2 -b2f19e78ee85073f680c3bba1f07fd31b057c00b97040357d97855b54a0b5accb0d3b05b2a294568fcd6a4be6f266950 -a74632d13bbe2d64b51d7a9c3ae0a5a971c19f51cf7596a807cea053e6a0f3719700976d4e394b356c0329a2dced9aa2 -afef616d341a9bc94393b8dfba68ff0581436aa3a3adb7c26a1bbf2cf19fa877066191681f71f17f3cd6f9cf6bf70b5a -8ce96d93ae217408acf7eb0f9cbb9563363e5c7002e19bbe1e80760bc9d449daee2118f3878b955163ed664516b97294 -8414f79b496176bc8b8e25f8e4cfee28f4f1c2ddab099d63d2aca1b6403d26a571152fc3edb97794767a7c4686ad557c -b6c61d01fd8ce087ef9f079bf25bf10090db483dd4f88c4a786d31c1bdf52065651c1f5523f20c21e75cea17df69ab73 -a5790fd629be70545093631efadddc136661f63b65ec682609c38ef7d3d7fa4e56bdf94f06e263bc055b90cb1c6bcefe -b515a767e95704fb7597bca9e46f1753abacdc0e56e867ee3c6f4cd382643c2a28e65312c05ad040eaa3a8cbe7217a65 -8135806a02ead6aa92e9adb6fefb91349837ab73105aaa7be488ef966aa8dfaafdfa64bbae30fcbfa55dd135a036a863 -8f22435702716d76b1369750694540742d909d5e72b54d0878245fab7c269953b1c6f2b29c66f08d5e0263ca3a731771 -8e0f8a8e8753e077dac95848212aeffd51c23d9b6d611df8b102f654089401954413ecbedc6367561ca599512ae5dda7 -815a9084e3e2345f24c5fa559deec21ee1352fb60f4025c0779be65057f2d528a3d91593bd30d3a185f5ec53a9950676 -967e6555ccba395b2cc1605f8484c5112c7b263f41ce8439a99fd1c71c5ed14ad02684d6f636364199ca48afbbde13be -8cd0ccf17682950b34c796a41e2ea7dd5367aba5e80a907e01f4cdc611e4a411918215e5aebf4292f8b24765d73314a6 -a58bf1bbb377e4b3915df6f058a0f53b8fb8130fdec8c391f6bc82065694d0be59bb67ffb540e6c42cc8b380c6e36359 -92af3151d9e6bfb3383d85433e953c0160859f759b0988431ec5893542ba40288f65db43c78a904325ef8d324988f09d -8011bbb05705167afb47d4425065630f54cb86cd462095e83b81dfebf348f846e4d8fbcf1c13208f5de1931f81da40b9 -81c743c104fc3cb047885c9fa0fb9705c3a83ee24f690f539f4985509c3dafd507af3f6a2128276f45d5939ef70c167f -a2c9679b151c041aaf5efeac5a737a8f70d1631d931609fca16be1905682f35e291292874cb3b03f14994f98573c6f44 -a4949b86c4e5b1d5c82a337e5ce6b2718b1f7c215148c8bfb7e7c44ec86c5c9476048fc5c01f57cb0920876478c41ad6 -86c2495088bd1772152e527a1da0ef473f924ea9ab0e5b8077df859c28078f73c4e22e3a906b507fdf217c3c80808b5c -892e0a910dcf162bcea379763c3e2349349e4cda9402949255ac4a78dd5a47e0bf42f5bd0913951576b1d206dc1e536a -a7009b2c6b396138afe4754b7cc10dee557c51c7f1a357a11486b3253818531f781ea8107360c8d4c3b1cd96282353c0 -911763ef439c086065cc7b4e57484ed6d693ea44acee4b18c9fd998116da55fbe7dcb8d2a0f0f9b32132fca82d73dff6 -a722000b95a4a2d40bed81870793f15ba2af633f9892df507f2842e52452e02b5ea8dea6a043c2b2611d82376e33742a -9387ac49477bd719c2f92240d0bdfcf9767aad247ca93dc51e56106463206bc343a8ec855eb803471629a66fffb565d6 -92819a1fa48ab4902939bb72a0a4e6143c058ea42b42f9bc6cea5df45f49724e2530daf3fc4f097cceefa2a8b9db0076 -98eac7b04537653bc0f4941aae732e4b1f84bd276c992c64a219b8715eb1fb829b5cbd997d57feb15c7694c468f95f70 -b275e7ba848ce21bf7996e12dbeb8dadb5d0e4f1cb5a0248a4f8f9c9fe6c74e3c93f4b61edbcb0a51af5a141e1c14bc7 -97243189285aba4d49c53770c242f2faf5fd3914451da4931472e3290164f7663c726cf86020f8f181e568c72fd172d1 -839b0b3c25dd412bee3dc24653b873cc65454f8f16186bb707bcd58259c0b6765fa4c195403209179192a4455c95f3b8 -8689d1a870514568a074a38232e2ceb4d7df30fabeb76cff0aed5b42bf7f02baea12c5fadf69f4713464dbd52aafa55f -8958ae7b290f0b00d17c3e9fdb4dbf168432b457c7676829299dd428984aba892de1966fc106cfc58a772862ecce3976 -a422bc6bd68b8870cfa5bc4ce71781fd7f4368b564d7f1e0917f6013c8bbb5b240a257f89ecfdbecb40fe0f3aa31d310 -aa61f78130cebe09bc9a2c0a37f0dd57ed2d702962e37d38b1df7f17dc554b1d4b7a39a44182a452ce4c5eb31fa4cfcc -b7918bd114f37869bf1a459023386825821bfadce545201929d13ac3256d92a431e34f690a55d944f77d0b652cefeffc -819bba35fb6ace1510920d4dcff30aa682a3c9af9022e287751a6a6649b00c5402f14b6309f0aeef8fce312a0402915e -8b7c9ad446c6f63c11e1c24e24014bd570862b65d53684e107ba9ad381e81a2eaa96731b4b33536efd55e0f055071274 -8fe79b53f06d33386c0ec7d6d521183c13199498594a46d44a8a716932c3ec480c60be398650bbfa044fa791c4e99b65 -9558e10fb81250b9844c99648cf38fa05ec1e65d0ccbb18aa17f2d1f503144baf59d802c25be8cc0879fff82ed5034ad -b538a7b97fbd702ba84645ca0a63725be1e2891c784b1d599e54e3480e4670d0025526674ef5cf2f87dddf2290ba09f0 -92eafe2e869a3dd8519bbbceb630585c6eb21712b2f31e1b63067c0acb5f9bdbbcbdb612db4ea7f9cc4e7be83d31973f -b40d21390bb813ab7b70a010dff64c57178418c62685761784e37d327ba3cb9ef62df87ecb84277c325a637fe3709732 -b349e6fbf778c4af35fbed33130bd8a7216ed3ba0a79163ebb556e8eb8e1a7dad3456ddd700dad9d08d202491c51b939 -a8fdaedecb251f892b66c669e34137f2650509ade5d38fbe8a05d9b9184bb3b2d416186a3640429bd1f3e4b903c159dd -ac6167ebfee1dbab338eff7642f5e785fc21ef0b4ddd6660333fe398068cbd6c42585f62e81e4edbb72161ce852a1a4f -874b1fbf2ebe140c683bd7e4e0ab017afa5d4ad38055aaa83ee6bbef77dbc88a6ce8eb0dcc48f0155244af6f86f34c2d -903c58e57ddd9c446afab8256a6bb6c911121e6ccfb4f9b4ed3e2ed922a0e500a5cb7fa379d5285bc16e11dac90d1fda -8dae7a0cffa2fd166859cd1bf10ff82dd1932e488af377366b7efc0d5dec85f85fe5e8150ff86a79a39cefc29631733a -aa047857a47cc4dfc08585f28640420fcf105b881fd59a6cf7890a36516af0644d143b73f3515ab48faaa621168f8c31 -864508f7077c266cc0cb3f7f001cb6e27125ebfe79ab57a123a8195f2e27d3799ff98413e8483c533b46a816a3557f1f -8bcd45ab1f9cbab36937a27e724af819838f66dfeb15923f8113654ff877bd8667c54f6307aaf0c35027ca11b6229bfd -b21aa34da9ab0a48fcfdd291df224697ce0c1ebc0e9b022fdee8750a1a4b5ba421c419541ed5c98b461eecf363047471 -a9a18a2ab2fae14542dc336269fe612e9c1af6cf0c9ac933679a2f2cb77d3c304114f4d219ca66fe288adde30716775b -b5205989b92c58bdda71817f9a897e84100b5c4e708de1fced5c286f7a6f01ae96b1c8d845f3a320d77c8e2703c0e8b1 -a364059412bbcc17b8907d43ac8e5df90bc87fd1724b5f99832d0d24559fae6fa76a74cff1d1eac8cbac6ec80b44af20 -ae709f2c339886b31450834cf29a38b26eb3b0779bd77c9ac269a8a925d1d78ea3837876c654b61a8fe834b3b6940808 -8802581bba66e1952ac4dab36af371f66778958f4612901d95e5cac17f59165e6064371d02de8fb6fccf89c6dc8bd118 -a313252df653e29c672cbcfd2d4f775089cb77be1077381cf4dc9533790e88af6cedc8a119158e7da5bf6806ad9b91a1 -992a065b4152c7ef11515cd54ba9d191fda44032a01aed954acff3443377ee16680c7248d530b746b8c6dee2d634e68c -b627b683ee2b32c1ab4ccd27b9f6cce2fe097d96386fa0e5c182ad997c4c422ab8dfc03870cd830b8c774feb66537282 -b823cf8a9aee03dadd013eb9efe40a201b4b57ef67efaae9f99683005f5d1bf55e950bf4af0774f50859d743642d3fea -b8a7449ffac0a3f206677097baf7ce00ca07a4d2bd9b5356fbcb83f3649b0fda07cfebad220c1066afba89e5a52abf4b -b2dd1a2f986395bb4e3e960fbbe823dbb154f823284ebc9068502c19a7609790ec0073d08bfa63f71e30c7161b6ef966 -98e5236de4281245234f5d40a25b503505af140b503a035fc25a26159a9074ec81512b28f324c56ea2c9a5aa7ce90805 -89070847dc8bbf5bc4ed073aa2e2a1f699cf0c2ca226f185a0671cecc54e7d3e14cd475c7752314a7a8e7476829da4bc -a9402dc9117fdb39c4734c0688254f23aed3dce94f5f53f5b7ef2b4bf1b71a67f85ab1a38ec224a59691f3bee050aeb3 -957288f9866a4bf56a4204218ccc583f717d7ce45c01ea27142a7e245ad04a07f289cc044f8cf1f21d35e67e39299e9c -b2fb31ccb4e69113763d7247d0fc8edaae69b550c5c56aecacfd780c7217dc672f9fb7496edf4aba65dacf3361268e5b -b44a4526b2f1d6eb2aa8dba23bfa385ff7634572ab2afddd0546c3beb630fbfe85a32f42dd287a7fec069041411537f7 -8db5a6660c3ac7fd7a093573940f068ee79a82bc17312af900b51c8c439336bc86ca646c6b7ab13aaaa008a24ca508ab -8f9899a6d7e8eb4367beb5c060a1f8e94d8a21099033ae582118477265155ba9e72176a67f7f25d7bad75a152b56e21a -a67de0e91ade8d69a0e00c9ff33ee2909b8a609357095fa12319e6158570c232e5b6f4647522efb7345ce0052aa9d489 -82eb2414898e9c3023d57907a2b17de8e7eea5269029d05a94bfd7bf5685ac4a799110fbb375eb5e0e2bd16acf6458ae -94451fc7fea3c5a89ba701004a9693bab555cb622caf0896b678faba040409fdfd14a978979038b2a81e8f0abc4994d2 -ac879a5bb433998e289809a4a966bd02b4bf6a9c1cc276454e39c886efcf4fc68baebed575826bde577ab5aa71d735a9 -880c0f8f49c875dfd62b4ddedde0f5c8b19f5687e693717f7e5c031bc580e58e13ab497d48b4874130a18743c59fdce3 -b582af8d8ff0bf76f0a3934775e0b54c0e8fed893245d7d89cae65b03c8125b7237edc29dc45b4fe1a3fe6db45d280ee -89f337882ed3ae060aaee98efa20d79b6822bde9708c1c5fcee365d0ec9297f694cae37d38fd8e3d49717c1e86f078e7 -826d2c1faea54061848b484e288a5f4de0d221258178cf87f72e14baaa4acc21322f8c9eab5dde612ef497f2d2e1d60b -a5333d4f227543e9cd741ccf3b81db79f2f03ca9e649e40d6a6e8ff9073e06da83683566d3b3c8d7b258c62970fb24d1 -a28f08c473db06aaf4c043a2fae82b3c8cfaa160bce793a4c208e4e168fb1c65115ff8139dea06453c5963d95e922b94 -8162546135cc5e124e9683bdfaa45833c18553ff06a0861c887dc84a5b12ae8cd4697f6794c7ef6230492c32faba7014 -b23f0d05b74c08d6a7df1760792be83a761b36e3f8ae360f3c363fb196e2a9dd2de2e492e49d36561366e14daa77155c -b6f70d6c546722d3907c708d630dbe289771d2c8bf059c2e32b77f224696d750b4dda9b3a014debda38e7d02c9a77585 -83bf4c4a9f3ca022c631017e7a30ea205ba97f7f5927cba8fc8489a4646eac6712cb821c5668c9ffe94d69d524374a27 -b0371475425a8076d0dd5f733f55aabbe42d20a7c8ea7da352e736d4d35a327b2beb370dfcb05284e22cfd69c5f6c4cc -a0031ba7522c79211416c2cca3aa5450f96f8fee711552a30889910970ba13608646538781a2c08b834b140aadd7166f -99d273c80c7f2dc6045d4ed355d9fc6f74e93549d961f4a3b73cd38683f905934d359058cd1fc4da8083c7d75070487f -b0e4b0efa3237793e9dcce86d75aafe9879c5fa23f0d628649aef2130454dcf72578f9bf227b9d2b9e05617468e82588 -a5ab076fa2e1c5c51f3ae101afdd596ad9d106bba7882b359c43d8548b64f528af19afa76cd6f40da1e6c5fca4def3fa -8ce2299e570331d60f6a6eff1b271097cd5f1c0e1113fc69b89c6a0f685dabea3e5bc2ac6bd789aa492ab189f89be494 -91b829068874d911a310a5f9dee001021f97471307b5a3de9ec336870ec597413e1d92010ce320b619f38bed7c4f7910 -b14fe91f4b07bf33b046e9285b66cb07927f3a8da0af548ac2569b4c4fb1309d3ced76d733051a20814e90dd5b75ffd1 -abaab92ea6152d40f82940277c725aa768a631ee0b37f5961667f82fb990fc11e6d3a6a2752b0c6f94563ed9bb28265c -b7fe28543eca2a716859a76ab9092f135337e28109544f6bd2727728d0a7650428af5713171ea60bfc273d1c821d992c -8a4917b2ab749fc7343fc64bdf51b6c0698ff15d740cc7baf248c030475c097097d5a473bcc00d8c25817563fe0447b4 -aa96156d1379553256350a0a3250166add75948fb9cde62aa555a0a9dc0a9cb7f2f7b8428aff66097bf6bfedaf14bbe2 -ae4ffeb9bdc76830d3eca2b705f30c1bdede6412fa064260a21562c8850c7fb611ec62bc68479fe48f692833e6f66d8d -b96543caaba9d051600a14997765d49e4ab10b07c7a92cccf0c90b309e6da334fdd6d18c96806cbb67a7801024fbd3c7 -97b2b9ad76f19f500fcc94ca8e434176249f542ac66e5881a3dccd07354bdab6a2157018b19f8459437a68d8b86ba8e0 -a8d206f6c5a14c80005849474fde44b1e7bcf0b2d52068f5f97504c3c035b09e65e56d1cf4b5322791ae2c2fdbd61859 -936bad397ad577a70cf99bf9056584a61bd7f02d2d5a6cf219c05d770ae30a5cd902ba38366ce636067fc1dd10108d31 -a77e30195ee402b84f3882e2286bf5380c0ed374a112dbd11e16cef6b6b61ab209d4635e6f35cdaaa72c1a1981d5dabe -a46ba4d3947188590a43c180757886a453a0503f79cc435322d92490446f37419c7b999fdf868a023601078070e03346 -80d8d4c5542f223d48240b445d4d8cf6a75d120b060bc08c45e99a13028b809d910b534d2ac47fb7068930c54efd8da9 -803be9c68c91b42b68e1f55e58917a477a9a6265e679ca44ee30d3eb92453f8c89c64eafc04c970d6831edd33d066902 -b14b2b3d0dfe2bb57cee4cd72765b60ac33c1056580950be005790176543826c1d4fbd737f6cfeada6c735543244ab57 -a9e480188bba1b8fb7105ff12215706665fd35bf1117bacfb6ab6985f4dbc181229873b82e5e18323c2b8f5de03258e0 -a66a0f0779436a9a3999996d1e6d3000f22c2cac8e0b29cddef9636393c7f1457fb188a293b6c875b05d68d138a7cc4a -848397366300ab40c52d0dbbdafbafef6cd3dadf1503bb14b430f52bb9724188928ac26f6292a2412bc7d7aa620763c8 -95466cc1a78c9f33a9aaa3829a4c8a690af074916b56f43ae46a67a12bb537a5ac6dbe61590344a25b44e8512355a4a7 -8b5f7a959f818e3baf0887f140f4575cac093d0aece27e23b823cf421f34d6e4ff4bb8384426e33e8ec7b5eed51f6b5c -8d5e1368ec7e3c65640d216bcc5d076f3d9845924c734a34f3558ac0f16e40597c1a775a25bf38b187213fbdba17c93b -b4647c1b823516880f60d20c5cc38c7f80b363c19d191e8992226799718ee26b522a12ecb66556ed3d483aa4824f3326 -ac3abaea9cd283eb347efda4ed9086ea3acf495043e08d0d19945876329e8675224b685612a6badf8fd72fb6274902b1 -8eae1ce292d317aaa71bcf6e77e654914edd5090e2e1ebab78b18bb41b9b1bc2e697439f54a44c0c8aa0d436ebe6e1a9 -94dc7d1aec2c28eb43d93b111fa59aaa0d77d5a09501220bd411768c3e52208806abf973c6a452fd8292ff6490e0c9e2 -8fd8967f8e506fef27d17b435d6b86b232ec71c1036351f12e6fb8a2e12daf01d0ee04451fb944d0f1bf7fd20e714d02 -824e6865be55d43032f0fec65b3480ea89b0a2bf860872237a19a54bc186a85d2f8f9989cc837fbb325b7c72d9babe2c -8bd361f5adb27fd6f4e3f5de866e2befda6a8454efeb704aacc606f528c03f0faae888f60310e49440496abd84083ce2 -b098a3c49f2aaa28b6b3e85bc40ce6a9cdd02134ee522ae73771e667ad7629c8d82c393fba9f27f5416986af4c261438 -b385f5ca285ff2cfe64dcaa32dcde869c28996ed091542600a0b46f65f3f5a38428cca46029ede72b6cf43e12279e3d3 -8196b03d011e5be5288196ef7d47137d6f9237a635ab913acdf9c595fa521d9e2df722090ec7eb0203544ee88178fc5f -8ed1270211ef928db18e502271b7edf24d0bbd11d97f2786aee772d70c2029e28095cf8f650b0328cc8a4c38d045316d -a52ab60e28d69b333d597a445884d44fd2a7e1923dd60f763951e1e45f83e27a4dac745f3b9eff75977b3280e132c15d -91e9fe78cdac578f4a4687f71b800b35da54b824b1886dafec073a3c977ce7a25038a2f3a5b1e35c2c8c9d1a7312417c -a42832173f9d9491c7bd93b21497fbfa4121687cd4d2ab572e80753d7edcbb42cfa49f460026fbde52f420786751a138 -97b947126d84dcc70c97be3c04b3de3f239b1c4914342fa643b1a4bb8c4fe45c0fcb585700d13a7ed50784790c54bef9 -860e407d353eac070e2418ef6cb80b96fc5f6661d6333e634f6f306779651588037be4c2419562c89c61f9aa2c4947f5 -b2c9d93c3ba4e511b0560b55d3501bf28a510745fd666b3cb532db051e6a8617841ea2f071dda6c9f15619c7bfd2737f -8596f4d239aeeac78311207904d1bd863ef68e769629cc379db60e019aaf05a9d5cd31dc8e630b31e106a3a93e47cbc5 -8b26e14e2e136b65c5e9e5c2022cee8c255834ea427552f780a6ca130a6446102f2a6f334c3f9a0308c53df09e3dba7e -b54724354eb515a3c8bed0d0677ff1db94ac0a07043459b4358cb90e3e1aa38ac23f2caa3072cf9647275d7cd61d0e80 -b7ce9fe0e515e7a6b2d7ddcb92bc0196416ff04199326aea57996eef8c5b1548bd8569012210da317f7c0074691d01b7 -a1a13549c82c877253ddefa36a29ea6a23695ee401fdd48e65f6f61e5ebd956d5e0edeff99484e9075cb35071fec41e2 -838ba0c1e5bd1a6da05611ff1822b8622457ebd019cb065ece36a2d176bd2d889511328120b8a357e44569e7f640c1e6 -b916eccff2a95519400bbf76b5f576cbe53cf200410370a19d77734dc04c05b585cfe382e8864e67142d548cd3c4c2f4 -a610447cb7ca6eea53a6ff1f5fe562377dcb7f4aaa7300f755a4f5e8eba61e863c51dc2aa9a29b35525b550fbc32a0fe -9620e8f0f0ee9a4719aa9685eeb1049c5c77659ba6149ec4c158f999cfd09514794b23388879931fe26fea03fa471fd3 -a9dcf8b679e276583cf5b9360702a185470d09aea463dc474ee9c8aee91ef089dacb073e334e47fbc78ec5417c90465c -8c9adee8410bdd99e5b285744cee61e2593b6300ff31a8a83b0ec28da59475a5c6fb9346fe43aadea2e6c3dad2a8e30a -97d5afe9b3897d7b8bb628b7220cf02d8ee4e9d0b78f5000d500aaf4c1df9251aaaabfd1601626519f9d66f00a821d4e -8a382418157b601ce4c3501d3b8409ca98136a4ef6abcbf62885e16e215b76b035c94d149cc41ff92e42ccd7c43b9b3d -b64b8d11fb3b01abb2646ac99fdb9c02b804ce15d98f9fe0fbf1c9df8440c71417487feb6cdf51e3e81d37104b19e012 -849d7d044f9d8f0aab346a9374f0b3a5d14a9d1faa83dbacccbdc629ad1ef903a990940255564770537f8567521d17f0 -829dbb0c76b996c2a91b4cbbe93ba455ca0d5729755e5f0c92aaee37dff7f36fcdc06f33aca41f1b609c784127b67d88 -85a7c0069047b978422d264d831ab816435f63938015d2e977222b6b5746066c0071b7f89267027f8a975206ed25c1b0 -84b9fbc1cfb302df1acdcf3dc5d66fd1edfe7839f7a3b2fb3a0d5548656249dd556104d7c32b73967bccf0f5bdcf9e3b -972220ac5b807f53eac37dccfc2ad355d8b21ea6a9c9b011c09fe440ddcdf7513e0b43d7692c09ded80d7040e26aa28f -855885ed0b21350baeca890811f344c553cf9c21024649c722453138ba29193c6b02c4b4994cd414035486f923472e28 -841874783ae6d9d0e59daea03e96a01cbbe4ecaced91ae4f2c8386e0d87b3128e6d893c98d17c59e4de1098e1ad519dd -827e50fc9ce56f97a4c3f2f4cbaf0b22f1c3ce6f844ff0ef93a9c57a09b8bf91ebfbd2ba9c7f83c442920bffdaf288cc -a441f9136c7aa4c08d5b3534921b730e41ee91ab506313e1ba5f7c6f19fd2d2e1594e88c219834e92e6fb95356385aa7 -97d75b144471bf580099dd6842b823ec0e6c1fb86dd0da0db195e65524129ea8b6fd4a7a9bbf37146269e938a6956596 -a4b6fa87f09d5a29252efb2b3aaab6b3b6ea9fab343132a651630206254a25378e3e9d6c96c3d14c150d01817d375a8e -a31a671876d5d1e95fe2b8858dc69967231190880529d57d3cab7f9f4a2b9b458ac9ee5bdaa3289158141bf18f559efb -90bee6fff4338ba825974021b3b2a84e36d617e53857321f13d2b3d4a28954e6de3b3c0e629d61823d18a9763313b3bf -96b622a63153f393bb419bfcf88272ea8b3560dbd46b0aa07ada3a6223990d0abdd6c2adb356ef4be5641688c8d83941 -84c202adeaff9293698022bc0381adba2cd959f9a35a4e8472288fd68f96f6de8be9da314c526d88e291c96b1f3d6db9 -8ca01a143b8d13809e5a8024d03e6bc9492e22226073ef6e327edf1328ef4aff82d0bcccee92cb8e212831fa35fe1204 -b2f970dbad15bfbefb38903c9bcc043d1367055c55dc1100a850f5eb816a4252c8c194b3132c929105511e14ea10a67d -a5e36556472a95ad57eb90c3b6623671b03eafd842238f01a081997ffc6e2401f76e781d049bb4aa94d899313577a9cf -8d1057071051772f7c8bedce53a862af6fd530dd56ae6321eaf2b9fc6a68beff5ed745e1c429ad09d5a118650bfd420a -8aadc4f70ace4fcb8d93a78610779748dcffc36182d45b932c226dc90e48238ea5daa91f137c65ed532352c4c4d57416 -a2ea05ae37e673b4343232ae685ee14e6b88b867aef6dfac35db3589cbcd76f99540fed5c2641d5bb5a4a9f808e9bf0d -947f1abad982d65648ae4978e094332b4ecb90f482c9be5741d5d1cf5a28acf4680f1977bf6e49dd2174c37f11e01296 -a27b144f1565e4047ba0e3f4840ef19b5095d1e281eaa463c5358f932114cbd018aa6dcf97546465cf2946d014d8e6d6 -8574e1fc3acade47cd4539df578ce9205e745e161b91e59e4d088711a7ab5aa3b410d517d7304b92109924d9e2af8895 -a48ee6b86b88015d6f0d282c1ae01d2a5b9e8c7aa3d0c18b35943dceb1af580d08a65f54dc6903cde82fd0d73ce94722 -8875650cec543a7bf02ea4f2848a61d167a66c91ffaefe31a9e38dc8511c6a25bde431007eefe27a62af3655aca208dc -999b0a6e040372e61937bf0d68374e230346b654b5a0f591a59d33a4f95bdb2f3581db7c7ccb420cd7699ed709c50713 -878c9e56c7100c5e47bbe77dc8da5c5fe706cec94d37fa729633bca63cace7c40102eee780fcdabb655f5fa47a99600e -865006fb5b475ada5e935f27b96f9425fc2d5449a3c106aa366e55ebed3b4ee42adc3c3f0ac19fd129b40bc7d6bc4f63 -b7a7da847f1202e7bc1672553e68904715e84fd897d529243e3ecda59faa4e17ba99c649a802d53f6b8dfdd51f01fb74 -8b2fb4432c05653303d8c8436473682933a5cb604da10c118ecfcd2c8a0e3132e125afef562bdbcc3df936164e5ce4f2 -808d95762d33ddfa5d0ee3d7d9f327de21a994d681a5f372e2e3632963ea974da7f1f9e5bac8ccce24293509d1f54d27 -932946532e3c397990a1df0e94c90e1e45133e347a39b6714c695be21aeb2d309504cb6b1dde7228ff6f6353f73e1ca2 -9705e7c93f0cdfaa3fa96821f830fe53402ad0806036cd1b48adc2f022d8e781c1fbdab60215ce85c653203d98426da3 -aa180819531c3ec1feb829d789cb2092964c069974ae4faad60e04a6afcce5c3a59aec9f11291e6d110a788d22532bc6 -88f755097f7e25cb7dd3c449520c89b83ae9e119778efabb54fbd5c5714b6f37c5f9e0346c58c6ab09c1aef2483f895d -99fc03ab7810e94104c494f7e40b900f475fde65bdec853e60807ffd3f531d74de43335c3b2646b5b8c26804a7448898 -af2dea9683086bed1a179110efb227c9c00e76cd00a2015b089ccbcee46d1134aa18bda5d6cab6f82ae4c5cd2461ac21 -a500f87ba9744787fdbb8e750702a3fd229de6b8817594348dec9a723b3c4240ddfa066262d002844b9e38240ce55658 -924d0e45c780f5bc1c1f35d15dfc3da28036bdb59e4c5440606750ecc991b85be18bc9a240b6c983bc5430baa4c68287 -865b11e0157b8bf4c5f336024b016a0162fc093069d44ac494723f56648bc4ded13dfb3896e924959ea11c96321afefc -93672d8607d4143a8f7894f1dcca83fb84906dc8d6dd7dd063bb0049cfc20c1efd933e06ca7bd03ea4cb5a5037990bfe -826891efbdff0360446825a61cd1fa04326dd90dae8c33dfb1ed97b045e165766dd070bd7105560994d0b2044bdea418 -93c4a4a8bcbc8b190485cc3bc04175b7c0ed002c28c98a540919effd6ed908e540e6594f6db95cd65823017258fb3b1c -aeb2a0af2d2239fda9aa6b8234b019708e8f792834ff0dd9c487fa09d29800ddceddd6d7929faa9a3edcb9e1b3aa0d6b -87f11de7236d387863ec660d2b04db9ac08143a9a2c4dfff87727c95b4b1477e3bc473a91e5797313c58754905079643 -80dc1db20067a844fe8baceca77f80db171a5ca967acb24e2d480eae9ceb91a3343c31ad1c95b721f390829084f0eae6 -9825c31f1c18da0de3fa84399c8b40f8002c3cae211fb6a0623c76b097b4d39f5c50058f57a16362f7a575909d0a44a2 -a99fc8de0c38dbf7b9e946de83943a6b46a762167bafe2a603fb9b86f094da30d6de7ed55d639aafc91936923ee414b3 -ad594678b407db5d6ea2e90528121f84f2b96a4113a252a30d359a721429857c204c1c1c4ff71d8bb5768c833f82e80e -b33d985e847b54510b9b007e31053732c8a495e43be158bd2ffcea25c6765bcbc7ca815f7c60b36ad088b955dd6e9350 -815f8dfc6f90b3342ca3fbd968c67f324dae8f74245cbf8bc3bef10e9440c65d3a2151f951e8d18959ba01c1b50b0ec1 -94c608a362dd732a1abc56e338637c900d59013db8668e49398b3c7a0cae3f7e2f1d1bf94c0299eeafe6af7f76c88618 -8ebd8446b23e5adfcc393adc5c52fe172f030a73e63cd2d515245ca0dd02782ceed5bcdd9ccd9c1b4c5953dfac9c340c -820437f3f6f9ad0f5d7502815b221b83755eb8dc56cd92c29e9535eb0b48fb8d08c9e4fcc26945f9c8cca60d89c44710 -8910e4e8a56bf4be9cc3bbf0bf6b1182a2f48837a2ed3c2aaec7099bfd7f0c83e14e608876b17893a98021ff4ab2f20d -9633918fde348573eec15ce0ad53ac7e1823aac86429710a376ad661002ae6d049ded879383faaa139435122f64047c6 -a1f5e3fa558a9e89318ca87978492f0fb4f6e54a9735c1b8d2ecfb1d1c57194ded6e0dd82d077b2d54251f3bee1279e1 -b208e22d04896abfd515a95c429ff318e87ff81a5d534c8ac2c33c052d6ffb73ef1dccd39c0bbe0734b596c384014766 -986d5d7d2b5bde6d16336f378bd13d0e671ad23a8ec8a10b3fc09036faeeb069f60662138d7a6df3dfb8e0d36180f770 -a2d4e6c5f5569e9cef1cddb569515d4b6ace38c8aed594f06da7434ba6b24477392cc67ba867c2b079545ca0c625c457 -b5ac32b1d231957d91c8b7fc43115ce3c5c0d8c13ca633374402fa8000b6d9fb19499f9181844f0c10b47357f3f757ce -96b8bf2504b4d28fa34a4ec378e0e0b684890c5f44b7a6bb6e19d7b3db2ab27b1e2686389d1de9fbd981962833a313ea -953bfd7f6c3a0469ad432072b9679a25486f5f4828092401eff494cfb46656c958641a4e6d0d97d400bc59d92dba0030 -876ab3cea7484bbfd0db621ec085b9ac885d94ab55c4bb671168d82b92e609754b86aaf472c55df3d81421d768fd108a -885ff4e67d9ece646d02dd425aa5a087e485c3f280c3471b77532b0db6145b69b0fbefb18aa2e3fa5b64928b43a94e57 -b91931d93f806d0b0e6cc62a53c718c099526140f50f45d94b8bbb57d71e78647e06ee7b42aa5714aed9a5c05ac8533f -a0313eeadd39c720c9c27b3d671215331ab8d0a794e71e7e690f06bcd87722b531d6525060c358f35f5705dbb7109ccb -874c0944b7fedc6701e53344100612ddcb495351e29305c00ec40a7276ea5455465ffb7bded898886c1853139dfb1fc7 -8dc31701a01ee8137059ca1874a015130d3024823c0576aa9243e6942ec99d377e7715ed1444cd9b750a64b85dcaa3e5 -836d2a757405e922ec9a2dfdcf489a58bd48b5f9683dd46bf6047688f778c8dee9bc456de806f70464df0b25f3f3d238 -b30b0a1e454a503ea3e2efdec7483eaf20b0a5c3cefc42069e891952b35d4b2c955cf615f3066285ed8fafd9fcfbb8f6 -8e6d4044b55ab747e83ec8762ea86845f1785cc7be0279c075dadf08aca3ccc5a096c015bb3c3f738f647a4eadea3ba5 -ad7735d16ab03cbe09c029610aa625133a6daecfc990b297205b6da98eda8c136a7c50db90f426d35069708510d5ae9c -8d62d858bbb59ec3c8cc9acda002e08addab4d3ad143b3812098f3d9087a1b4a1bb255dcb1635da2402487d8d0249161 -805beec33238b832e8530645a3254aeef957e8f7ea24bcfc1054f8b9c69421145ebb8f9d893237e8a001c857fedfc77e -b1005644be4b085e3f5775aa9bd3e09a283e87ddada3082c04e7a62d303dcef3b8cf8f92944c200c7ae6bb6bdf63f832 -b4ba0e0790dc29063e577474ffe3b61f5ea2508169f5adc1e394934ebb473e356239413a17962bc3e5d3762d72cce8c2 -a157ba9169c9e3e6748d9f1dd67fbe08b9114ade4c5d8fc475f87a764fb7e6f1d21f66d7905cd730f28a1c2d8378682a -913e52b5c93989b5d15e0d91aa0f19f78d592bc28bcfdfddc885a9980c732b1f4debb8166a7c4083c42aeda93a702898 -90fbfc1567e7cd4e096a38433704d3f96a2de2f6ed3371515ccc30bc4dd0721a704487d25a97f3c3d7e4344472702d8d -89646043028ffee4b69d346907586fd12c2c0730f024acb1481abea478e61031966e72072ff1d5e65cb8c64a69ad4eb1 -b125a45e86117ee11d2fb42f680ab4a7894edd67ff927ae2c808920c66c3e55f6a9d4588eee906f33a05d592e5ec3c04 -aad47f5b41eae9be55fb4f67674ff1e4ae2482897676f964a4d2dcb6982252ee4ff56aac49578b23f72d1fced707525e -b9ddff8986145e33851b4de54d3e81faa3352e8385895f357734085a1616ef61c692d925fe62a5ed3be8ca49f5d66306 -b3cb0963387ed28c0c0adf7fe645f02606e6e1780a24d6cecef5b7c642499109974c81a7c2a198b19862eedcea2c2d8c -ac9c53c885457aaf5cb36c717a6f4077af701e0098eebd7aa600f5e4b14e6c1067255b3a0bc40e4a552025231be7de60 -8e1a8d823c4603f6648ec21d064101094f2a762a4ed37dd2f0a2d9aa97b2d850ce1e76f4a4b8cae58819b058180f7031 -b268b73bf7a179b6d22bd37e5e8cb514e9f5f8968c78e14e4f6d5700ca0d0ca5081d0344bb73b028970eebde3cb4124e -a7f57d71940f0edbd29ed8473d0149cae71d921dd15d1ff589774003e816b54b24de2620871108cec1ab9fa956ad6ce6 -8053e6416c8b120e2b999cc2fc420a6a55094c61ac7f2a6c6f0a2c108a320890e389af96cbe378936132363c0d551277 -b3823f4511125e5aa0f4269e991b435a0d6ceb523ebd91c04d7add5534e3df5fc951c504b4fd412a309fd3726b7f940b -ae6eb04674d04e982ca9a6add30370ab90e303c71486f43ed3efbe431af1b0e43e9d06c11c3412651f304c473e7dbf39 -96ab55e641ed2e677591f7379a3cd126449614181fce403e93e89b1645d82c4af524381ff986cae7f9cebe676878646d -b52423b4a8c37d3c3e2eca8f0ddbf7abe0938855f33a0af50f117fab26415fb0a3da5405908ec5fdc22a2c1f2ca64892 -82a69ce1ee92a09cc709d0e3cd22116c9f69d28ea507fe5901f5676000b5179b9abe4c1875d052b0dd42d39925e186bb -a84c8cb84b9d5cfb69a5414f0a5283a5f2e90739e9362a1e8c784b96381b59ac6c18723a4aa45988ee8ef5c1f45cc97d -afd7efce6b36813082eb98257aae22a4c1ae97d51cac7ea9c852d4a66d05ef2732116137d8432e3f117119725a817d24 -a0f5fe25af3ce021b706fcff05f3d825384a272284d04735574ce5fb256bf27100fad0b1f1ba0e54ae9dcbb9570ecad3 -8751786cb80e2e1ff819fc7fa31c2833d25086534eb12b373d31f826382430acfd87023d2a688c65b5e983927e146336 -8cf5c4b17fa4f3d35c78ce41e1dc86988fd1135cd5e6b2bb0c108ee13538d0d09ae7102609c6070f39f937b439b31e33 -a9108967a2fedd7c322711eca8159c533dd561bedcb181b646de98bf5c3079449478eab579731bee8d215ae8852c7e21 -b54c5171704f42a6f0f4e70767cdb3d96ffc4888c842eece343a01557da405961d53ffdc34d2f902ea25d3e1ed867cad -ae8d4b764a7a25330ba205bf77e9f46182cd60f94a336bbd96773cf8064e3d39caf04c310680943dc89ed1fbad2c6e0d -aa5150e911a8e1346868e1b71c5a01e2a4bb8632c195861fb6c3038a0e9b85f0e09b3822e9283654a4d7bb17db2fc5f4 -9685d3756ce9069bf8bb716cf7d5063ebfafe37e15b137fc8c3159633c4e006ff4887ddd0ae90360767a25c3f90cba7f -82155fd70f107ab3c8e414eadf226c797e07b65911508c76c554445422325e71af8c9a8e77fd52d94412a6fc29417cd3 -abfae52f53a4b6e00760468d973a267f29321997c3dbb5aee36dc1f20619551229c0c45b9d9749f410e7f531b73378e8 -81a76d921f8ef88e774fd985e786a4a330d779b93fad7def718c014685ca0247379e2e2a007ad63ee7f729cd9ed6ce1b -81947c84bc5e28e26e2e533af5ae8fe10407a7b77436dbf8f1d5b0bbe86fc659eae10f974659dc7c826c6dabd03e3a4b -92b8c07050d635b8dd4fd09df9054efe4edae6b86a63c292e73cc819a12a21dd7d104ce51fa56af6539dedf6dbe6f7b6 -b44c579e3881f32b32d20c82c207307eca08e44995dd2aac3b2692d2c8eb2a325626c80ac81c26eeb38c4137ff95add5 -97efab8941c90c30860926dea69a841f2dcd02980bf5413b9fd78d85904588bf0c1021798dbc16c8bbb32cce66c82621 -913363012528b50698e904de0588bf55c8ec5cf6f0367cfd42095c4468fcc64954fbf784508073e542fee242d0743867 -8ed203cf215148296454012bd10fddaf119203db1919a7b3d2cdc9f80e66729464fdfae42f1f2fc5af1ed53a42b40024 -ab84312db7b87d711e9a60824f4fe50e7a6190bf92e1628688dfcb38930fe87b2d53f9e14dd4de509b2216856d8d9188 -880726def069c160278b12d2258eac8fa63f729cd351a710d28b7e601c6712903c3ac1e7bbd0d21e4a15f13ca49db5aa -980699cd51bac6283959765f5174e543ed1e5f5584b5127980cbc2ef18d984ecabba45042c6773b447b8e694db066028 -aeb019cb80dc4cb4207430d0f2cd24c9888998b6f21d9bf286cc638449668d2eec0018a4cf3fe6448673cd6729335e2b -b29852f6aa6c60effdffe96ae88590c88abae732561d35cc19e82d3a51e26cb35ea00986193e07f90060756240f5346e -a0fa855adc5ba469f35800c48414b8921455950a5c0a49945d1ef6e8f2a1881f2e2dfae47de6417270a6bf49deeb091d -b6c7332e3b14813641e7272d4f69ecc7e09081df0037d6dab97ce13a9e58510f5c930d300633f208181d9205c5534001 -85a6c050f42fce560b5a8d54a11c3bbb8407abbadd859647a7b0c21c4b579ec65671098b74f10a16245dc779dff7838e -8f3eb34bb68759d53c6677de4de78a6c24dd32c8962a7fb355ed362572ef8253733e6b52bc21c9f92ecd875020a9b8de -a17dd44181e5dab4dbc128e1af93ec22624b57a448ca65d2d9e246797e4af7d079e09c6e0dfb62db3a9957ce92f098d5 -a56a1b854c3183082543a8685bb34cae1289f86cfa8123a579049dbd059e77982886bfeb61bf6e05b4b1fe4e620932e7 -aedae3033cb2fb7628cb4803435bdd7757370a86f808ae4cecb9a268ad0e875f308c048c80cbcac523de16b609683887 -9344905376aa3982b1179497fac5a1d74b14b7038fd15e3b002db4c11c8bfc7c39430db492cdaf58b9c47996c9901f28 -a3bfafdae011a19f030c749c3b071f83580dee97dd6f949e790366f95618ca9f828f1daaeabad6dcd664fcef81b6556d -81c03d8429129e7e04434dee2c529194ddb01b414feda3adee2271eb680f6c85ec872a55c9fa9d2096f517e13ed5abcc -98205ef3a72dff54c5a9c82d293c3e45d908946fa74bb749c3aabe1ab994ea93c269bcce1a266d2fe67a8f02133c5985 -85a70aeed09fda24412fadbafbbbf5ba1e00ac92885df329e147bfafa97b57629a3582115b780d8549d07d19b7867715 -b0fbe81c719f89a57d9ea3397705f898175808c5f75f8eb81c2193a0b555869ba7bd2e6bc54ee8a60cea11735e21c68c -b03a0bd160495ee626ff3a5c7d95bc79d7da7e5a96f6d10116600c8fa20bedd1132f5170f25a22371a34a2d763f2d6d0 -a90ab04091fbca9f433b885e6c1d60ab45f6f1daf4b35ec22b09909d493a6aab65ce41a6f30c98239cbca27022f61a8b -b66f92aa3bf2549f9b60b86f99a0bd19cbdd97036d4ae71ca4b83d669607f275260a497208f6476cde1931d9712c2402 -b08e1fdf20e6a9b0b4942f14fa339551c3175c1ffc5d0ab5b226b6e6a322e9eb0ba96adc5c8d59ca4259e2bdd04a7eb0 -a2812231e92c1ce74d4f5ac3ab6698520288db6a38398bb38a914ac9326519580af17ae3e27cde26607e698294022c81 -abfcbbcf1d3b9e84c02499003e490a1d5d9a2841a9e50c7babbef0b2dd20d7483371d4dc629ba07faf46db659459d296 -b0fe9f98c3da70927c23f2975a9dc4789194d81932d2ad0f3b00843dd9cbd7fb60747a1da8fe5a79f136a601becf279d -b130a6dba7645165348cb90f023713bed0eefbd90a976b313521c60a36d34f02032e69a2bdcf5361e343ed46911297ec -862f0cffe3020cea7a5fd4703353aa1eb1be335e3b712b29d079ff9f7090d1d8b12013011e1bdcbaa80c44641fd37c9f -8c6f11123b26633e1abb9ed857e0bce845b2b3df91cc7b013b2fc77b477eee445da0285fc6fc793e29d5912977f40916 -91381846126ea819d40f84d3005e9fb233dc80071d1f9bb07f102bf015f813f61e5884ffffb4f5cd333c1b1e38a05a58 -8add7d908de6e1775adbd39c29a391f06692b936518db1f8fde74eb4f533fc510673a59afb86e3a9b52ade96e3004c57 -8780e086a244a092206edcde625cafb87c9ab1f89cc3e0d378bc9ee776313836160960a82ec397bc3800c0a0ec3da283 -a6cb4cd9481e22870fdd757fae0785edf4635e7aacb18072fe8dc5876d0bab53fb99ce40964a7d3e8bcfff6f0ab1332f -af30ff47ecc5b543efba1ba4706921066ca8bb625f40e530fb668aea0551c7647a9d126e8aba282fbcce168c3e7e0130 -91b0bcf408ce3c11555dcb80c4410b5bc2386d3c05caec0b653352377efdcb6bab4827f2018671fc8e4a0e90d772acc1 -a9430b975ef138b6b2944c7baded8fe102d31da4cfe3bd3d8778bda79189c99d38176a19c848a19e2d1ee0bddd9a13c1 -aa5a4eef849d7c9d2f4b018bd01271c1dd83f771de860c4261f385d3bdcc130218495860a1de298f14b703ec32fa235f -b0ce79e7f9ae57abe4ff366146c3b9bfb38b0dee09c28c28f5981a5d234c6810ad4d582751948affb480d6ae1c8c31c4 -b75122748560f73d15c01a8907d36d06dc068e82ce22b84b322ac1f727034493572f7907dec34ebc3ddcc976f2f89ed7 -b0fc7836369a3e4411d34792d6bd5617c14f61d9bba023dda64e89dc5fb0f423244e9b48ee64869258931daa9753a56f -8956d7455ae9009d70c6e4a0bcd7610e55f37494cf9897a8f9e1b904cc8febc3fd2d642ebd09025cfff4609ad7e3bc52 -ad741efe9e472026aa49ae3d9914cb9c1a6f37a54f1a6fe6419bebd8c7d68dca105a751c7859f4389505ede40a0de786 -b52f418797d719f0d0d0ffb0846788b5cba5d0454a69a2925de4b0b80fa4dd7e8c445e5eac40afd92897ed28ca650566 -a0ab65fb9d42dd966cd93b1de01d7c822694669dd2b7a0c04d99cd0f3c3de795f387b9c92da11353412f33af5c950e9a -a0052f44a31e5741a331f7cac515a08b3325666d388880162d9a7b97598fde8b61f9ff35ff220df224eb5c4e40ef0567 -a0101cfdc94e42b2b976c0d89612a720e55d145a5ef6ef6f1f78cf6de084a49973d9b5d45915349c34ce712512191e3c -a0dd99fcf3f5cead5aaf08e82212df3a8bb543c407a4d6fab88dc5130c1769df3f147e934a46f291d6c1a55d92b86917 -a5939153f0d1931bbda5cf6bdf20562519ea55fbfa978d6dbc6828d298260c0da7a50c37c34f386e59431301a96c2232 -9568269f3f5257200f9ca44afe1174a5d3cf92950a7f553e50e279c239e156a9faaa2a67f288e3d5100b4142efe64856 -b746b0832866c23288e07f24991bbf687cad794e7b794d3d3b79367566ca617d38af586cdc8d6f4a85a34835be41d54f -a871ce28e39ab467706e32fec1669fda5a4abba2f8c209c6745df9f7a0fa36bbf1919cf14cb89ea26fa214c4c907ae03 -a08dacdd758e523cb8484f6bd070642c0c20e184abdf8e2a601f61507e93952d5b8b0c723c34fcbdd70a8485eec29db2 -85bdb78d501382bb95f1166b8d032941005661aefd17a5ac32df9a3a18e9df2fc5dc2c1f07075f9641af10353cecc0c9 -98d730c28f6fa692a389e97e368b58f4d95382fad8f0baa58e71a3d7baaea1988ead47b13742ce587456f083636fa98e -a557198c6f3d5382be9fb363feb02e2e243b0c3c61337b3f1801c4a0943f18e38ce1a1c36b5c289c8fa2aa9d58742bab -89174f79201742220ac689c403fc7b243eed4f8e3f2f8aba0bf183e6f5d4907cb55ade3e238e3623d9885f03155c4d2b -b891d600132a86709e06f3381158db300975f73ea4c1f7c100358e14e98c5fbe792a9af666b85c4e402707c3f2db321e -b9e5b2529ef1043278c939373fc0dbafe446def52ddd0a8edecd3e4b736de87e63e187df853c54c28d865de18a358bb6 -8589b2e9770340c64679062c5badb7bbef68f55476289b19511a158a9a721f197da03ece3309e059fc4468b15ac33aa3 -aad8c6cd01d785a881b446f06f1e9cd71bca74ba98674c2dcddc8af01c40aa7a6d469037498b5602e76e9c91a58d3dbd -abaccb1bd918a8465f1bf8dbe2c9ad4775c620b055550b949a399f30cf0d9eb909f3851f5b55e38f9e461e762f88f499 -ae62339d26db46e85f157c0151bd29916d5cc619bd4b832814b3fd2f00af8f38e7f0f09932ffe5bba692005dab2d9a74 -93a6ff30a5c0edf8058c89aba8c3259e0f1b1be1b80e67682de651e5346f7e1b4b4ac3d87cbaebf198cf779524aff6bf -8980a2b1d8f574af45b459193c952400b10a86122b71fca2acb75ee0dbd492e7e1ef5b959baf609a5172115e371f3177 -8c2f49f3666faee6940c75e8c7f6f8edc3f704cca7a858bbb7ee5e96bba3b0cf0993996f781ba6be3b0821ef4cb75039 -b14b9e348215b278696018330f63c38db100b0542cfc5be11dc33046e3bca6a13034c4ae40d9cef9ea8b34fef0910c4e -b59bc3d0a30d66c16e6a411cb641f348cb1135186d5f69fda8b0a0934a5a2e7f6199095ba319ec87d3fe8f1ec4a06368 -8874aca2a3767aa198e4c3fec2d9c62d496bc41ff71ce242e9e082b7f38cdf356089295f80a301a3cf1182bde5308c97 -b1820ebd61376d91232423fc20bf008b2ba37e761199f4ef0648ea2bd70282766799b4de814846d2f4d516d525c8daa7 -a6b202e5dedc16a4073e04a11af3a8509b23dfe5a1952f899adeb240e75c3f5bde0c424f811a81ea48d343591faffe46 -a69becee9c93734805523b92150a59a62eed4934f66056b645728740d42223f2925a1ad38359ba644da24d9414f4cdda -ad72f0f1305e37c7e6b48c272323ee883320994cb2e0d850905d6655fafc9f361389bcb9c66b3ff8d2051dbb58c8aa96 -b563600bd56fad7c8853af21c6a02a16ed9d8a8bbeea2c31731d63b976d83cb05b9779372d898233e8fd597a75424797 -b0abb78ce465bf7051f563c62e8be9c57a2cc997f47c82819300f36e301fefd908894bb2053a9d27ce2d0f8c46d88b5b -a071a85fb8274bac2202e0cb8e0e2028a5e138a82d6e0374d39ca1884a549c7c401312f00071b91f455c3a2afcfe0cda -b931c271513a0f267b9f41444a5650b1918100b8f1a64959c552aff4e2193cc1b9927906c6fa7b8a8c68ef13d79aaa52 -a6a1bb9c7d32cb0ca44d8b75af7e40479fbce67d216b48a2bb680d3f3a772003a49d3cd675fc64e9e0f8fabeb86d6d61 -b98d609858671543e1c3b8564162ad828808bb50ded261a9f8690ded5b665ed8368c58f947365ed6e84e5a12e27b423d -b3dca58cd69ec855e2701a1d66cad86717ff103ef862c490399c771ad28f675680f9500cb97be48de34bcdc1e4503ffd -b34867c6735d3c49865e246ddf6c3b33baf8e6f164db3406a64ebce4768cb46b0309635e11be985fee09ab7a31d81402 -acb966c554188c5b266624208f31fab250b3aa197adbdd14aee5ab27d7fb886eb4350985c553b20fdf66d5d332bfd3fe -943c36a18223d6c870d54c3b051ef08d802b85e9dd6de37a51c932f90191890656c06adfa883c87b906557ae32d09da0 -81bca7954d0b9b6c3d4528aadf83e4bc2ef9ea143d6209bc45ae9e7ae9787dbcd8333c41f12c0b6deee8dcb6805e826a -aba176b92256efb68f574e543479e5cf0376889fb48e3db4ebfb7cba91e4d9bcf19dcfec444c6622d9398f06de29e2b9 -b9f743691448053216f6ece7cd699871fff4217a1409ceb8ab7bdf3312d11696d62c74b0664ba0a631b1e0237a8a0361 -a383c2b6276fa9af346b21609326b53fb14fdf6f61676683076e80f375b603645f2051985706d0401e6fbed7eb0666b6 -a9ef2f63ec6d9beb8f3d04e36807d84bda87bdd6b351a3e4a9bf7edcb5618c46c1f58cfbf89e64b40f550915c6988447 -a141b2d7a82f5005eaea7ae7d112c6788b9b95121e5b70b7168d971812f3381de8b0082ac1f0a82c7d365922ebd2d26a -b1b76ef8120e66e1535c17038b75255a07849935d3128e3e99e56567b842fb1e8d56ef932d508d2fb18b82f7868fe1a9 -8e2e234684c81f21099f5c54f6bbe2dd01e3b172623836c77668a0c49ce1fe218786c3827e4d9ae2ea25c50a8924fb3c -a5caf5ff948bfd3c4ca3ffbdfcd91eec83214a6c6017235f309a0bbf7061d3b0b466307c00b44a1009cf575163898b43 -986415a82ca16ebb107b4c50b0c023c28714281db0bcdab589f6cb13d80e473a3034b7081b3c358e725833f6d845cb14 -b94836bf406ac2cbacb10e6df5bcdfcc9d9124ae1062767ca4e322d287fd5e353fdcebd0e52407cb3cd68571258a8900 -83c6d70a640b33087454a4788dfd9ef3ed00272da084a8d36be817296f71c086b23b576f98178ab8ca6a74f04524b46b -ad4115182ad784cfe11bcfc5ce21fd56229cc2ce77ac82746e91a2f0aa53ca6593a22efd2dc4ed8d00f84542643d9c58 -ab1434c5e5065da826d10c2a2dba0facccab0e52b506ce0ce42fbe47ced5a741797151d9ecc99dc7d6373cfa1779bbf6 -8a8b591d82358d55e6938f67ea87a89097ab5f5496f7260adb9f649abb289da12b498c5b2539c2f9614fb4e21b1f66b0 -964f355d603264bc1f44c64d6d64debca66f37dff39c971d9fc924f2bc68e6c187b48564a6dc82660a98b035f8addb5d -b66235eaaf47456bc1dc4bde454a028e2ce494ece6b713a94cd6bf27cf18c717fd0c57a5681caaa2ad73a473593cdd7a -9103e3bb74304186fa4e3e355a02da77da4aca9b7e702982fc2082af67127ebb23a455098313c88465bc9b7d26820dd5 -b6a42ff407c9dd132670cdb83cbad4b20871716e44133b59a932cd1c3f97c7ac8ff7f61acfaf8628372508d8dc8cad7c -883a9c21c16a167a4171b0f084565c13b6f28ba7c4977a0de69f0a25911f64099e7bbb4da8858f2e93068f4155d04e18 -8dbb3220abc6a43220adf0331e3903d3bfd1d5213aadfbd8dfcdf4b2864ce2e96a71f35ecfb7a07c3bbabf0372b50271 -b4ad08aee48e176bda390b7d9acf2f8d5eb008f30d20994707b757dc6a3974b2902d29cd9b4d85e032810ad25ac49e97 -865bb0f33f7636ec501bb634e5b65751c8a230ae1fa807a961a8289bbf9c7fe8c59e01fbc4c04f8d59b7f539cf79ddd5 -86a54d4c12ad1e3605b9f93d4a37082fd26e888d2329847d89afa7802e815f33f38185c5b7292293d788ad7d7da1df97 -b26c8615c5e47691c9ff3deca3021714662d236c4d8401c5d27b50152ce7e566266b9d512d14eb63e65bc1d38a16f914 -827639d5ce7db43ba40152c8a0eaad443af21dc92636cc8cc2b35f10647da7d475a1e408901cd220552fddad79db74df -a2b79a582191a85dbe22dc384c9ca3de345e69f6aa370aa6d3ff1e1c3de513e30b72df9555b15a46586bd27ea2854d9d -ae0d74644aba9a49521d3e9553813bcb9e18f0b43515e4c74366e503c52f47236be92dfbd99c7285b3248c267b1de5a0 -80fb0c116e0fd6822a04b9c25f456bdca704e2be7bdc5d141dbf5d1c5eeb0a2c4f5d80db583b03ef3e47517e4f9a1b10 -ac3a1fa3b4a2f30ea7e0a114cdc479eb51773573804c2a158d603ad9902ae8e39ffe95df09c0d871725a5d7f9ba71a57 -b56b2b0d601cba7f817fa76102c68c2e518c6f20ff693aad3ff2e07d6c4c76203753f7f91686b1801e8c4659e4d45c48 -89d50c1fc56e656fb9d3915964ebce703cb723fe411ab3c9eaa88ccc5d2b155a9b2e515363d9c600d3c0cee782c43f41 -b24207e61462f6230f3cd8ccf6828357d03e725769f7d1de35099ef9ee4dca57dbce699bb49ed994462bee17059d25ce -b886f17fcbcbfcd08ac07f04bb9543ef58510189decaccea4b4158c9174a067cb67d14b6be3c934e6e2a18c77efa9c9c -b9c050ad9cafd41c6e2e192b70d080076eed59ed38ea19a12bd92fa17b5d8947d58d5546aaf5e8e27e1d3b5481a6ce51 -aaf7a34d3267e3b1ddbc54c641e3922e89303f7c86ebebc7347ebca4cffad5b76117dac0cbae1a133053492799cd936f -a9ee604ada50adef82e29e893070649d2d4b7136cc24fa20e281ce1a07bd736bf0de7c420369676bcbcecff26fb6e900 -9855315a12a4b4cf80ab90b8bd13003223ba25206e52fd4fe6a409232fbed938f30120a3db23eab9c53f308bd8b9db81 -8cd488dd7a24f548a3cf03c54dec7ff61d0685cb0f6e5c46c2d728e3500d8c7bd6bba0156f4bf600466fda53e5b20444 -890ad4942ebac8f5b16c777701ab80c68f56fa542002b0786f8fea0fb073154369920ac3dbfc07ea598b82f4985b8ced -8de0cf9ddc84c9b92c59b9b044387597799246b30b9f4d7626fc12c51f6e423e08ee4cbfe9289984983c1f9521c3e19d -b474dfb5b5f4231d7775b3c3a8744956b3f0c7a871d835d7e4fd9cc895222c7b868d6c6ce250de568a65851151fac860 -86433b6135d9ed9b5ee8cb7a6c40e5c9d30a68774cec04988117302b8a02a11a71a1e03fd8e0264ef6611d219f103007 -80b9ed4adbe9538fb1ef69dd44ec0ec5b57cbfea820054d8d445b4261962624b4c70ac330480594bc5168184378379c3 -8b2e83562ccd23b7ad2d17f55b1ab7ef5fbef64b3a284e6725b800f3222b8bdf49937f4a873917ada9c4ddfb090938c2 -abe78cebc0f5a45d754140d1f685e387489acbfa46d297a8592aaa0d676a470654f417a4f7d666fc0b2508fab37d908e -a9c5f8ff1f8568e252b06d10e1558326db9901840e6b3c26bbd0cd5e850cb5fb3af3f117dbb0f282740276f6fd84126f -975f8dc4fb55032a5df3b42b96c8c0ffecb75456f01d4aef66f973cb7270d4eff32c71520ceefc1adcf38d77b6b80c67 -b043306ed2c3d8a5b9a056565afd8b5e354c8c4569fda66b0d797a50a3ce2c08cffbae9bbe292da69f39e89d5dc7911e -8d2afc36b1e44386ba350c14a6c1bb31ff6ea77128a0c5287584ac3584282d18516901ce402b4644a53db1ed8e7fa581 -8c294058bed53d7290325c363fe243f6ec4f4ea2343692f4bac8f0cb86f115c069ccb8334b53d2e42c067691ad110dba -b92157b926751aaf7ef82c1aa8c654907dccab6376187ee8b3e8c0c82811eae01242832de953faa13ebaff7da8698b3e -a780c4bdd9e4ba57254b09d745075cecab87feda78c88ffee489625c5a3cf96aa6b3c9503a374a37927d9b78de9bd22b -811f548ef3a2e6a654f7dcb28ac9378de9515ed61e5a428515d9594a83e80b35c60f96a5cf743e6fab0d3cb526149f49 -85a4dccf6d90ee8e094731eec53bd00b3887aec6bd81a0740efddf812fd35e3e4fe4f983afb49a8588691c202dabf942 -b152c2da6f2e01c8913079ae2b40a09b1f361a80f5408a0237a8131b429677c3157295e11b365b1b1841924b9efb922e -849b9efee8742502ffd981c4517c88ed33e4dd518a330802caff168abae3cd09956a5ee5eda15900243bc2e829016b74 -955a933f3c18ec0f1c0e38fa931e4427a5372c46a3906ebe95082bcf878c35246523c23f0266644ace1fa590ffa6d119 -911989e9f43e580c886656377c6f856cdd4ff1bd001b6db3bbd86e590a821d34a5c6688a29b8d90f28680e9fdf03ba69 -b73b8b4f1fd6049fb68d47cd96a18fcba3f716e0a1061aa5a2596302795354e0c39dea04d91d232aec86b0bf2ba10522 -90f87456d9156e6a1f029a833bf3c7dbed98ca2f2f147a8564922c25ae197a55f7ea9b2ee1f81bf7383197c4bad2e20c -903cba8b1e088574cb04a05ca1899ab00d8960580c884bd3c8a4c98d680c2ad11410f2b75739d6050f91d7208cac33a5 -9329987d42529c261bd15ecedd360be0ea8966e7838f32896522c965adfc4febf187db392bd441fb43bbd10c38fdf68b -8178ee93acf5353baa349285067b20e9bb41aa32d77b5aeb7384fe5220c1fe64a2461bd7a83142694fe673e8bbf61b7c -a06a8e53abcff271b1394bcc647440f81fb1c1a5f29c27a226e08f961c3353f4891620f2d59b9d1902bf2f5cc07a4553 -aaf5fe493b337810889e777980e6bbea6cac39ac66bc0875c680c4208807ac866e9fda9b5952aa1d04539b9f4a4bec57 -aa058abb1953eceac14ccfa7c0cc482a146e1232905dcecc86dd27f75575285f06bbae16a8c9fe8e35d8713717f5f19f -8f15dd732799c879ca46d2763453b359ff483ca33adb1d0e0a57262352e0476c235987dc3a8a243c74bc768f93d3014c -a61cc8263e9bc03cce985f1663b8a72928a607121005a301b28a278e9654727fd1b22bc8a949af73929c56d9d3d4a273 -98d6dc78502d19eb9f921225475a6ebcc7b44f01a2df6f55ccf6908d65b27af1891be2a37735f0315b6e0f1576c1f8d8 -8bd258b883f3b3793ec5be9472ad1ff3dc4b51bc5a58e9f944acfb927349ead8231a523cc2175c1f98e7e1e2b9f363b8 -aeacc2ecb6e807ad09bedd99654b097a6f39840e932873ace02eabd64ccfbb475abdcb62939a698abf17572d2034c51e -b8ccf78c08ccd8df59fd6eda2e01de328bc6d8a65824d6f1fc0537654e9bc6bf6f89c422dd3a295cce628749da85c864 -8f91fd8cb253ba2e71cc6f13da5e05f62c2c3b485c24f5d68397d04665673167fce1fc1aec6085c69e87e66ec555d3fd -a254baa10cb26d04136886073bb4c159af8a8532e3fd36b1e9c3a2e41b5b2b6a86c4ebc14dbe624ee07b7ccdaf59f9ab -94e3286fe5cd68c4c7b9a7d33ae3d714a7f265cf77cd0e9bc19fc51015b1d1c34ad7e3a5221c459e89f5a043ee84e3a9 -a279da8878af8d449a9539bec4b17cea94f0242911f66fab275b5143ab040825f78c89cb32a793930609415cfa3a1078 -ac846ceb89c9e5d43a2991c8443079dc32298cd63e370e64149cec98cf48a6351c09c856f2632fd2f2b3d685a18bbf8b -a847b27995c8a2e2454aaeb983879fb5d3a23105c33175839f7300b7e1e8ec3efd6450e9fa3f10323609dee7b98c6fd5 -a2f432d147d904d185ff4b2de8c6b82fbea278a2956bc406855b44c18041854c4f0ecccd472d1d0dff1d8aa8e281cb1d -94a48ad40326f95bd63dff4755f863a1b79e1df771a1173b17937f9baba57b39e651e7695be9f66a472f098b339364fc -a12a0ccd8f96e96e1bc6494341f7ebce959899341b3a084aa1aa87d1c0d489ac908552b7770b887bb47e7b8cbc3d8e66 -81a1f1681bda923bd274bfe0fbb9181d6d164fe738e54e25e8d4849193d311e2c4253614ed673c98af2c798f19a93468 -abf71106a05d501e84cc54610d349d7d5eae21a70bd0250f1bebbf412a130414d1c8dbe673ffdb80208fd72f1defa4d4 -96266dc2e0df18d8136d79f5b59e489978eee0e6b04926687fe389d4293c14f36f055c550657a8e27be4118b64254901 -8df5dcbefbfb4810ae3a413ca6b4bf08619ca53cd50eb1dde2a1c035efffc7b7ac7dff18d403253fd80104bd83dc029e -9610b87ff02e391a43324a7122736876d5b3af2a137d749c52f75d07b17f19900b151b7f439d564f4529e77aa057ad12 -a90a5572198b40fe2fcf47c422274ff36c9624df7db7a89c0eb47eb48a73a03c985f4ac5016161c76ca317f64339bce1 -98e5e61a6ab6462ba692124dba7794b6c6bde4249ab4fcc98c9edd631592d5bc2fb5e38466691a0970a38e48d87c2e43 -918cefb8f292f78d4db81462c633daf73b395e772f47b3a7d2cea598025b1d8c3ec0cbff46cdb23597e74929981cde40 -a98918a5dc7cf610fe55f725e4fd24ce581d594cb957bb9b4e888672e9c0137003e1041f83e3f1d7b9caab06462c87d4 -b92b74ac015262ca66c33f2d950221e19d940ba3bf4cf17845f961dc1729ae227aa9e1f2017829f2135b489064565c29 -a053ee339f359665feb178b4e7ee30a85df37debd17cacc5a27d6b3369d170b0114e67ad1712ed26d828f1df641bcd99 -8c3c8bad510b35da5ce5bd84b35c958797fbea024ad1c97091d2ff71d9b962e9222f65a9b776e5b3cc29c36e1063d2ee -af99dc7330fe7c37e850283eb47cc3257888e7c197cb0d102edf94439e1e02267b6a56306d246c326c4c79f9dc8c6986 -afecb2dc34d57a725efbd7eb93d61eb29dbe8409b668ab9ea040791f5b796d9be6d4fc10d7f627bf693452f330cf0435 -93334fedf19a3727a81a6b6f2459db859186227b96fe7a391263f69f1a0884e4235de64d29edebc7b99c44d19e7c7d7a -89579c51ac405ad7e9df13c904061670ce4b38372492764170e4d3d667ed52e5d15c7cd5c5991bbfa3a5e4e3fa16363e -9778f3e8639030f7ef1c344014f124e375acb8045bd13d8e97a92c5265c52de9d1ffebaa5bc3e1ad2719da0083222991 -88f77f34ee92b3d36791bdf3326532524a67d544297dcf1a47ff00b47c1b8219ff11e34034eab7d23b507caa2fd3c6b9 -a699c1e654e7c484431d81d90657892efeb4adcf72c43618e71ca7bd7c7a7ebbb1db7e06e75b75dc4c74efd306b5df3f -81d13153baebb2ef672b5bdb069d3cd669ce0be96b742c94e04038f689ff92a61376341366b286eee6bf3ae85156f694 -81efb17de94400fdacc1deec2550cbe3eecb27c7af99d8207e2f9be397e26be24a40446d2a09536bb5172c28959318d9 -989b21ebe9ceab02488992673dc071d4d5edec24bff0e17a4306c8cb4b3c83df53a2063d1827edd8ed16d6e837f0d222 -8d6005d6536825661b13c5fdce177cb37c04e8b109b7eb2b6d82ea1cb70efecf6a0022b64f84d753d165edc2bba784a3 -a32607360a71d5e34af2271211652d73d7756d393161f4cf0da000c2d66a84c6826e09e759bd787d4fd0305e2439d342 -aaad8d6f6e260db45d51b2da723be6fa832e76f5fbcb77a9a31e7f090dd38446d3b631b96230d78208cae408c288ac4e -abcfe425255fd3c5cffd3a818af7650190c957b6b07b632443f9e33e970a8a4c3bf79ac9b71f4d45f238a04d1c049857 -aeabf026d4c783adc4414b5923dbd0be4b039cc7201219f7260d321f55e9a5b166d7b5875af6129c034d0108fdc5d666 -af49e740c752d7b6f17048014851f437ffd17413c59797e5078eaaa36f73f0017c3e7da020310cfe7d3c85f94a99f203 -8854ca600d842566e3090040cd66bb0b3c46dae6962a13946f0024c4a8aca447e2ccf6f240045f1ceee799a88cb9210c -b6c03b93b1ab1b88ded8edfa1b487a1ed8bdce8535244dddb558ffb78f89b1c74058f80f4db2320ad060d0c2a9c351cc -b5bd7d17372faff4898a7517009b61a7c8f6f0e7ed4192c555db264618e3f6e57fb30a472d169fea01bf2bf0362a19a8 -96eb1d38319dc74afe7e7eb076fcd230d19983f645abd14a71e6103545c01301b31c47ae931e025f3ecc01fb3d2f31fa -b55a8d30d4403067def9b65e16f867299f8f64c9b391d0846d4780bc196569622e7e5b64ce799b5aefac8f965b2a7a7b -8356d199a991e5cbbff608752b6291731b6b6771aed292f8948b1f41c6543e4ab1bedc82dd26d10206c907c03508df06 -97f4137445c2d98b0d1d478049de952610ad698c91c9d0f0e7227d2aae690e9935e914ec4a2ea1fbf3fc1dddfeeacebb -af5621707e0938320b15ddfc87584ab325fbdfd85c30efea36f8f9bd0707d7ec12c344eff3ec21761189518d192df035 -8ac7817e71ea0825b292687928e349da7140285d035e1e1abff0c3704fa8453faaae343a441b7143a74ec56539687cc4 -8a5e0a9e4758449489df10f3386029ada828d1762e4fb0a8ffe6b79e5b6d5d713cb64ed95960e126398b0cdb89002bc9 -81324be4a71208bbb9bca74b77177f8f1abb9d3d5d9db195d1854651f2cf333cd618d35400da0f060f3e1b025124e4b2 -849971d9d095ae067525b3cbc4a7dfae81f739537ade6d6cec1b42fb692d923176197a8770907c58069754b8882822d6 -89f830825416802477cc81fdf11084885865ee6607aa15aa4eb28e351c569c49b8a1b9b5e95ddc04fa0ebafe20071313 -9240aeeaff37a91af55f860b9badd466e8243af9e8c96a7aa8cf348cd270685ab6301bc135b246dca9eda696f8b0e350 -acf74db78cc33138273127599eba35b0fb4e7b9a69fe02dae18fc6692d748ca332bd00b22afa8e654ed587aab11833f3 -b091e6d37b157b50d76bd297ad752220cd5c9390fac16dc838f8557aed6d9833fc920b61519df21265406216315e883f -a6446c429ebf1c7793c622250e23594c836b2fbcaf6c5b3d0995e1595a37f50ea643f3e549b0be8bbdadd69044d72ab9 -93e675353bd60e996bf1c914d5267eeaa8a52fc3077987ccc796710ef9becc6b7a00e3d82671a6bdfb8145ee3c80245a -a2f731e43251d04ed3364aa2f072d05355f299626f2d71a8a38b6f76cf08c544133f7d72dd0ab4162814b674b9fc7fa6 -97a8b791a5a8f6e1d0de192d78615d73d0c38f1e557e4e15d15adc663d649e655bc8da3bcc499ef70112eafe7fb45c7a -98cd624cbbd6c53a94469be4643c13130916b91143425bcb7d7028adbbfede38eff7a21092af43b12d4fab703c116359 -995783ce38fd5f6f9433027f122d4cf1e1ff3caf2d196ce591877f4a544ce9113ead60de2de1827eaff4dd31a20d79a8 -8cf251d6f5229183b7f3fe2f607a90b4e4b6f020fb4ba2459d28eb8872426e7be8761a93d5413640a661d73e34a5b81f -b9232d99620652a3aa7880cad0876f153ff881c4ed4c0c2e7b4ea81d5d42b70daf1a56b869d752c3743c6d4c947e6641 -849716f938f9d37250cccb1bf77f5f9fde53096cdfc6f2a25536a6187029a8f1331cdbed08909184b201f8d9f04b792f -80c7c4de098cbf9c6d17b14eba1805e433b5bc905f6096f8f63d34b94734f2e4ebf4bce8a177efd1186842a61204a062 -b790f410cf06b9b8daadceeb4fd5ff40a2deda820c8df2537e0a7554613ae3948e149504e3e79aa84889df50c8678eeb -813aab8bd000299cd37485b73cd7cba06e205f8efb87f1efc0bae8b70f6db2bc7702eb39510ad734854fb65515fe9d0f -94f0ab7388ac71cdb67f6b85dfd5945748afb2e5abb622f0b5ad104be1d4d0062b651f134ba22385c9e32c2dfdcccce1 -ab6223dca8bd6a4f969e21ccd9f8106fc5251d321f9e90cc42cea2424b3a9c4e5060a47eeef6b23c7976109b548498e8 -859c56b71343fce4d5c5b87814c47bf55d581c50fd1871a17e77b5e1742f5af639d0e94d19d909ec7dfe27919e954e0c -aae0d632b6191b8ad71b027791735f1578e1b89890b6c22e37de0e4a6074886126988fe8319ae228ac9ef3b3bcccb730 -8ca9f32a27a024c3d595ecfaf96b0461de57befa3b331ab71dc110ec3be5824fed783d9516597537683e77a11d334338 -a061df379fb3f4b24816c9f6cd8a94ecb89b4c6dc6cd81e4b8096fa9784b7f97ab3540259d1de9c02eb91d9945af4823 -998603102ac63001d63eb7347a4bb2bf4cf33b28079bb48a169076a65c20d511ccd3ef696d159e54cc8e772fb5d65d50 -94444d96d39450872ac69e44088c252c71f46be8333a608a475147752dbb99db0e36acfc5198f158509401959c12b709 -ac1b51b6c09fe055c1d7c9176eea9adc33f710818c83a1fbfa073c8dc3a7eb3513cbdd3f5960b7845e31e3e83181e6ba -803d530523fc9e1e0f11040d2412d02baef3f07eeb9b177fa9bfa396af42eea898a4276d56e1db998dc96ae47b644cb2 -85a3c9fc7638f5bf2c3e15ba8c2fa1ae87eb1ceb44c6598c67a2948667a9dfa41e61f66d535b4e7fda62f013a5a8b885 -a961cf5654c46a1a22c29baf7a4e77837a26b7f138f410e9d1883480ed5fa42411d522aba32040b577046c11f007388e -ad1154142344f494e3061ef45a34fab1aaacf5fdf7d1b26adbb5fbc3d795655fa743444e39d9a4119b4a4f82a6f30441 -b1d6c30771130c77806e7ab893b73d4deb590b2ff8f2f8b5e54c2040c1f3e060e2bd99afc668cf706a2df666a508bbf6 -a00361fd440f9decabd98d96c575cd251dc94c60611025095d1201ef2dedde51cb4de7c2ece47732e5ed9b3526c2012c -a85c5ab4d17d328bda5e6d839a9a6adcc92ff844ec25f84981e4f44a0e8419247c081530f8d9aa629c7eb4ca21affba6 -a4ddd3eab4527a2672cf9463db38bc29f61460e2a162f426b7852b7a7645fbd62084fd39a8e4d60e1958cce436dd8f57 -811648140080fe55b8618f4cf17f3c5a250adb0cd53d885f2ddba835d2b4433188e41fc0661faac88e4ff910b16278c0 -b85c7f1cfb0ed29addccf7546023a79249e8f15ac2d14a20accbfef4dd9dc11355d599815fa09d2b6b4e966e6ea8cff1 -a10b5d8c260b159043b020d5dd62b3467df2671afea6d480ca9087b7e60ed170c82b121819d088315902842d66c8fb45 -917e191df1bcf3f5715419c1e2191da6b8680543b1ba41fe84ed07ef570376e072c081beb67b375fca3565a2565bcabb -881fd967407390bfd7badc9ab494e8a287559a01eb07861f527207c127eadea626e9bcc5aa9cca2c5112fbac3b3f0e9c -959fd71149af82cc733619e0e5bf71760ca2650448c82984b3db74030d0e10f8ab1ce1609a6de6f470fe8b5bd90df5b3 -a3370898a1c5f33d15adb4238df9a6c945f18b9ada4ce2624fc32a844f9ece4c916a64e9442225b6592afa06d2e015f2 -817efb8a791435e4236f7d7b278181a5fa34587578c629dbc14fbf9a5c26772290611395eecd20222a4c58649fc256d8 -a04c9876acf2cfdc8ef96de4879742709270fa1d03fe4c8511fbef2d59eb0aaf0336fa2c7dfe41a651157377fa217813 -81e15875d7ea7f123e418edf14099f2e109d4f3a6ce0eb65f67fe9fb10d2f809a864a29f60ad3fc949f89e2596b21783 -b49f529975c09e436e6bc202fdc16e3fdcbe056db45178016ad6fdece9faad4446343e83aed096209690b21a6910724f -879e8eda589e1a279f7f49f6dd0580788c040d973748ec4942dbe51ea8fbd05983cc919b78f0c6b92ef3292ae29db875 -81a2b74b2118923f34139a102f3d95e7eee11c4c2929c2576dee200a5abfd364606158535a6c9e4178a6a83dbb65f3c4 -8913f281d8927f2b45fc815d0f7104631cb7f5f7278a316f1327d670d15868daadd2a64e3eb98e1f53fe7e300338cc80 -a6f815fba7ef9af7fbf45f93bc952e8b351f5de6568a27c7c47a00cb39a254c6b31753794f67940fc7d2e9cc581529f4 -b3722a15c66a0014ce4d082de118def8d39190c15678a472b846225585f3a83756ae1b255b2e3f86a26168878e4773b2 -817ae61ab3d0dd5b6e24846b5a5364b1a7dc2e77432d9fed587727520ae2f307264ea0948c91ad29f0aea3a11ff38624 -b3db467464415fcad36dc1de2d6ba7686772a577cc2619242ac040d6734881a45d3b40ed4588db124e4289cfeec4bbf6 -ad66a14f5a54ac69603b16e5f1529851183da77d3cc60867f10aea41339dd5e06a5257982e9e90a352cdd32750f42ee4 -adafa3681ef45d685555601a25a55cf23358319a17f61e2179e704f63df83a73bdd298d12cf6cef86db89bd17119e11d -a379dc44cb6dd3b9d378c07b2ec654fec7ca2f272de6ba895e3d00d20c9e4c5550498a843c8ac67e4221db2115bedc1c -b7bf81c267a78efc6b9e5a904574445a6487678d7ef70054e3e93ea6a23f966c2b68787f9164918e3b16d2175459ed92 -b41d66a13a4afafd5760062b77f79de7e6ab8ccacde9c6c5116a6d886912fb491dc027af435b1b44aacc6af7b3c887f2 -9904d23a7c1c1d2e4bab85d69f283eb0a8e26d46e8b7b30224438015c936729b2f0af7c7c54c03509bb0500acb42d8a4 -ae30d65e9e20c3bfd603994ae2b175ff691d51f3e24b2d058b3b8556d12ca4c75087809062dddd4aaac81c94d15d8a17 -9245162fab42ac01527424f6013310c3eb462982518debef6c127f46ba8a06c705d7dc9f0a41e796ba8d35d60ae6cc64 -87fab853638d7a29a20f3ba2b1a7919d023e9415bfa78ebb27973d8cbc7626f584dc5665d2e7ad71f1d760eba9700d88 -85aac46ecd330608e5272430970e6081ff02a571e8ea444f1e11785ea798769634a22a142d0237f67b75369d3c484a8a -938c85ab14894cc5dfce3d80456f189a2e98eddbc8828f4ff6b1df1dcb7b42b17ca2ff40226a8a1390a95d63dca698dd -a18ce1f846e3e3c4d846822f60271eecf0f5d7d9f986385ac53c5ace9589dc7c0188910448c19b91341a1ef556652fa9 -8611608a9d844f0e9d7584ad6ccf62a5087a64f764caf108db648a776b5390feb51e5120f0ef0e9e11301af3987dd7dc -8106333ba4b4de8d1ae43bc9735d3fea047392e88efd6a2fa6f7b924a18a7a265ca6123c3edc0f36307dd7fb7fe89257 -a91426fa500951ff1b051a248c050b7139ca30dde8768690432d597d2b3c4357b11a577be6b455a1c5d145264dcf81fc -b7f9f90e0e450f37b081297f7f651bad0496a8b9afd2a4cf4120a2671aaaa8536dce1af301258bfbfdb122afa44c5048 -84126da6435699b0c09fa4032dec73d1fca21d2d19f5214e8b0bea43267e9a8dd1fc44f8132d8315e734c8e2e04d7291 -aff064708103884cb4f1a3c1718b3fc40a238d35cf0a7dc24bdf9823693b407c70da50df585bf5bc4e9c07d1c2d203e8 -a8b40fc6533752983a5329c31d376c7a5c13ce6879cc7faee648200075d9cd273537001fb4c86e8576350eaac6ba60c2 -a02db682bdc117a84dcb9312eb28fcbde12d49f4ce915cc92c610bb6965ec3cc38290f8c5b5ec70afe153956692cda95 -86decd22b25d300508472c9ce75d3e465b737e7ce13bc0fcce32835e54646fe12322ba5bc457be18bfd926a1a6ca4a38 -a18666ef65b8c2904fd598791f5627207165315a85ee01d5fb0e6b2e10bdd9b00babc447da5bd63445e3337de33b9b89 -89bb0c06effadefdaf34ffe4b123e1678a90d4451ee856c863df1e752eef41fd984689ded8f0f878bf8916d5dd8e8024 -97cfcba08ebec05d0073992a66b1d7d6fb9d95871f2cdc36db301f78bf8069294d1c259efef5c93d20dc937eedae3a1a -ac2643b14ece79dcb2e289c96776a47e2bebd40dd6dc74fd035df5bb727b5596f40e3dd2d2202141e69b0993717ede09 -a5e6fd88a2f9174d9bd4c6a55d9c30974be414992f22aa852f552c7648f722ed8077acf5aba030abd47939bb451b2c60 -8ad40a612824a7994487731a40b311b7349038c841145865539c6ada75c56de6ac547a1c23df190e0caaafecddd80ccc -953a7cea1d857e09202c438c6108060961f195f88c32f0e012236d7a4b39d840c61b162ec86436e8c38567328bea0246 -80d8b47a46dae1868a7b8ccfe7029445bbe1009dad4a6c31f9ef081be32e8e1ac1178c3c8fb68d3e536c84990cc035b1 -81ecd99f22b3766ce0aca08a0a9191793f68c754fdec78b82a4c3bdc2db122bbb9ebfd02fc2dcc6e1567a7d42d0cc16a -b1dd0446bccc25846fb95d08c1c9cc52fb51c72c4c5d169ffde56ecfe800f108dc1106d65d5c5bd1087c656de3940b63 -b87547f0931e164e96de5c550ca5aa81273648fe34f6e193cd9d69cf729cb432e17aa02e25b1c27a8a0d20a3b795e94e -820a94e69a927e077082aae66f6b292cfbe4589d932edf9e68e268c9bd3d71ef76cf7d169dd445b93967c25db11f58f1 -b0d07ddf2595270c39adfa0c8cf2ab1322979b0546aa4d918f641be53cd97f36c879bb75d205e457c011aca3bbd9f731 -8700b876b35b4b10a8a9372c5230acecd39539c1bb87515640293ad4464a9e02929d7d6a6a11112e8a29564815ac0de4 -a61a601c5bb27dcb97e37c8e2b9ce479c6b192a5e04d9ed5e065833c5a1017ee5f237b77d1a17be5d48f8e7cc0bcacf6 -92fb88fe774c1ba1d4a08cae3c0e05467ad610e7a3f1d2423fd47751759235fe0a3036db4095bd6404716aa03820f484 -b274f140d77a3ce0796f5e09094b516537ccaf27ae1907099bff172e6368ba85e7c3ef8ea2a07457cac48ae334da95b3 -b2292d9181f16581a9a9142490b2bdcdfb218ca6315d1effc8592100d792eb89d5356996c890441f04f2b4a95763503e -8897e73f576d86bc354baa3bd96e553107c48cf5889dcc23c5ba68ab8bcd4e81f27767be2233fdfa13d39f885087e668 -a29eac6f0829791c728d71abc49569df95a4446ecbfc534b39f24f56c88fe70301838dfc1c19751e7f3c5c1b8c6af6a0 -9346dc3720adc5df500a8df27fd9c75ef38dc5c8f4e8ed66983304750e66d502c3c59b8e955be781b670a0afc70a2167 -9566d534e0e30a5c5f1428665590617e95fd05d45f573715f58157854ad596ece3a3cfec61356aee342308d623e029d5 -a464fb8bffe6bd65f71938c1715c6e296cc6d0311a83858e4e7eb5873b7f2cf0c584d2101e3407b85b64ca78b2ac93ce -b54088f7217987c87e9498a747569ac5b2f8afd5348f9c45bf3fd9fbf713a20f495f49c8572d087efe778ac7313ad6d3 -91fa9f5f8000fe050f5b224d90b59fcce13c77e903cbf98ded752e5b3db16adb2bc1f8c94be48b69f65f1f1ad81d6264 -92d04a5b0ac5d8c8e313709b432c9434ecd3e73231f01e9b4e7952b87df60cbfa97b5dedd2200bd033b4b9ea8ba45cc1 -a94b90ad3c3d6c4bbe169f8661a790c40645b40f0a9d1c7220f01cf7fc176e04d80bab0ced9323fcafb93643f12b2760 -94d86149b9c8443b46196f7e5a3738206dd6f3be7762df488bcbb9f9ee285a64c997ed875b7b16b26604fa59020a8199 -82efe4ae2c50a2d7645240c173a047f238536598c04a2c0b69c96e96bd18e075a99110f1206bc213f39edca42ba00cc1 -ab8667685f831bc14d4610f84a5da27b4ea5b133b4d991741a9e64dceb22cb64a3ce8f1b6e101d52af6296df7127c9ad -83ba433661c05dcc5d562f4a9a261c8110dac44b8d833ae1514b1fc60d8b4ee395b18804baea04cb10adb428faf713c3 -b5748f6f660cc5277f1211d2b8649493ed8a11085b871cd33a5aea630abd960a740f08c08be5f9c21574600ac9bf5737 -a5c8dd12af48fb710642ad65ebb97ca489e8206741807f7acfc334f8035d3c80593b1ff2090c9bb7bd138f0c48714ca8 -a2b382fd5744e3babf454b1d806cc8783efeb4761bc42b6914ea48a46a2eae835efbe0a18262b6bc034379e03cf1262b -b3145ffaf603f69f15a64936d32e3219eea5ed49fdfd2f5bf40ea0dfd974b36fb6ff12164d4c2282d892db4cf3ff3ce1 -87a316fb213f4c5e30c5e3face049db66be4f28821bd96034714ec23d3e97849d7b301930f90a4323c7ccf53de23050c -b9de09a919455070fed6220fc179c8b7a4c753062bcd27acf28f5b9947a659c0b364298daf7c85c4ca6fca7f945add1f -806fbd98d411b76979464c40ad88bc07a151628a27fcc1012ba1dfbaf5b5cc9d962fb9b3386008978a12515edce934bc -a15268877fae0d21610ae6a31061ed7c20814723385955fac09fdc9693a94c33dea11db98bb89fdfe68f933490f5c381 -8d633fb0c4da86b2e0b37d8fad5972d62bff2ac663c5ec815d095cd4b7e1fe66ebef2a2590995b57eaf941983c7ad7a4 -8139e5dd9cf405e8ef65f11164f0440827d98389ce1b418b0c9628be983a9ddd6cf4863036ccb1483b40b8a527acd9ed -88b15fa94a08eac291d2b94a2b30eb851ff24addf2cc30b678e72e32cfcb3424cf4b33aa395d741803f3e578ddf524de -b5eaf0c8506e101f1646bcf049ee38d99ea1c60169730da893fd6020fd00a289eb2f415947e44677af49e43454a7b1be -8489822ad0647a7e06aa2aa5595960811858ddd4542acca419dd2308a8c5477648f4dd969a6740bb78aa26db9bfcc555 -b1e9a7b9f3423c220330d45f69e45fa03d7671897cf077f913c252e3e99c7b1b1cf6d30caad65e4228d5d7b80eb86e5e -b28fe9629592b9e6a55a1406903be76250b1c50c65296c10c5e48c64b539fb08fe11f68cf462a6edcbba71b0cee3feb2 -a41acf96a02c96cd8744ff6577c244fc923810d17ade133587e4c223beb7b4d99fa56eae311a500d7151979267d0895c -880798938fe4ba70721be90e666dfb62fcab4f3556fdb7b0dc8ec5bc34f6b4513df965eae78527136eb391889fe2caf9 -98d4d89d358e0fb7e212498c73447d94a83c1b66e98fc81427ab13acddb17a20f52308983f3a5a8e0aaacec432359604 -81430b6d2998fc78ba937a1639c6020199c52da499f68109da227882dc26d005b73d54c5bdcac1a04e8356a8ca0f7017 -a8d906a4786455eb74613aba4ce1c963c60095ffb8658d368df9266fdd01e30269ce10bf984e7465f34b4fd83beba26a -af54167ac1f954d10131d44a8e0045df00d581dd9e93596a28d157543fbe5fb25d213806ed7fb3cba6b8f5b5423562db -8511e373a978a12d81266b9afbd55035d7bc736835cfa921903a92969eeba3624437d1346b55382e61415726ab84a448 -8cf43eea93508ae586fa9a0f1354a1e16af659782479c2040874a46317f9e8d572a23238efa318fdfb87cc63932602b7 -b0bdd3bacff077173d302e3a9678d1d37936188c7ecc34950185af6b462b7c679815176f3cce5db19aac8b282f2d60ad -a355e9b87f2f2672052f5d4d65b8c1c827d24d89b0d8594641fccfb69aef1b94009105f3242058bb31c8bf51caae5a41 -b8baa9e4b950b72ff6b88a6509e8ed1304bc6fd955748b2e59a523a1e0c5e99f52aec3da7fa9ff407a7adf259652466c -840bc3dbb300ea6f27d1d6dd861f15680bd098be5174f45d6b75b094d0635aced539fa03ddbccb453879de77fb5d1fe9 -b4bc7e7e30686303856472bae07e581a0c0bfc815657c479f9f5931cff208d5c12930d2fd1ff413ebd8424bcd7a9b571 -89b5d514155d7999408334a50822508b9d689add55d44a240ff2bdde2eee419d117031f85e924e2a2c1ca77db9b91eea -a8604b6196f87a04e1350302e8aa745bba8dc162115d22657b37a1d1a98cb14876ddf7f65840b5dbd77e80cd22b4256c -83cb7acdb9e03247515bb2ce0227486ccf803426717a14510f0d59d45e998b245797d356f10abca94f7a14e1a2f0d552 -aeb3266a9f16649210ab2df0e1908ac259f34ce1f01162c22b56cf1019096ee4ea5854c36e30bb2feb06c21a71e8a45c -89e72e86edf2aa032a0fc9acf4d876a40865fbb2c8f87cb7e4d88856295c4ac14583e874142fd0c314a49aba68c0aa3c -8c3576eba0583c2a7884976b4ed11fe1fda4f6c32f6385d96c47b0e776afa287503b397fa516a455b4b8c3afeedc76db -a31e5b633bda9ffa174654fee98b5d5930a691c3c42fcf55673d927dbc8d91c58c4e42e615353145431baa646e8bbb30 -89f2f3f7a8da1544f24682f41c68114a8f78c86bd36b066e27da13acb70f18d9f548773a16bd8e24789420e17183f137 -ada27fa4e90a086240c9164544d2528621a415a5497badb79f8019dc3dce4d12eb6b599597e47ec6ac39c81efda43520 -90dc1eb21bf21c0187f359566fc4bf5386abea52799306a0e5a1151c0817c5f5bc60c86e76b1929c092c0f3ff48cedd2 -b702a53ebcc17ae35d2e735a347d2c700e9cbef8eadbece33cac83df483b2054c126593e1f462cfc00a3ce9d737e2af5 -9891b06455ec925a6f8eafffba05af6a38cc5e193acaaf74ffbf199df912c5197106c5e06d72942bbb032ce277b6417f -8c0ee71eb01197b019275bcf96cae94e81d2cdc3115dbf2d8e3080074260318bc9303597e8f72b18f965ad601d31ec43 -8aaf580aaf75c1b7a5f99ccf60503506e62058ef43b28b02f79b8536a96be3f019c9f71caf327b4e6730134730d1bef5 -ae6f9fc21dd7dfa672b25a87eb0a41644f7609fab5026d5cedb6e43a06dbbfd6d6e30322a2598c8dedde88c52eaed626 -8159b953ffece5693edadb2e906ebf76ff080ee1ad22698950d2d3bfc36ac5ea78f58284b2ca180664452d55bd54716c -ab7647c32ca5e9856ac283a2f86768d68de75ceeba9e58b74c5324f8298319e52183739aba4340be901699d66ac9eb3f -a4d85a5701d89bcfaf1572db83258d86a1a0717603d6f24ac2963ffcf80f1265e5ab376a4529ca504f4396498791253c -816080c0cdbfe61b4d726c305747a9eb58ac26d9a35f501dd32ba43c098082d20faf3ccd41aad24600aa73bfa453dfac -84f3afac024f576b0fd9acc6f2349c2fcefc3f77dbe5a2d4964d14b861b88e9b1810334b908cf3427d9b67a8aee74b18 -94b390655557b1a09110018e9b5a14490681ade275bdc83510b6465a1218465260d9a7e2a6e4ec700f58c31dc3659962 -a8c66826b1c04a2dd4c682543242e7a57acae37278bd09888a3d17747c5b5fec43548101e6f46d703638337e2fd3277b -86e6f4608a00007fa533c36a5b054c5768ccafe41ad52521d772dcae4c8a4bcaff8f7609be30d8fab62c5988cbbb6830 -837da4cf09ae8aa0bceb16f8b3bfcc3b3367aecac9eed6b4b56d7b65f55981ef066490764fb4c108792623ecf8cad383 -941ff3011462f9b5bf97d8cbdb0b6f5d37a1b1295b622f5485b7d69f2cb2bcabc83630dae427f0259d0d9539a77d8424 -b99e5d6d82aa9cf7d5970e7f710f4039ac32c2077530e4c2779250c6b9b373bc380adb0a03b892b652f649720672fc8c -a791c78464b2d65a15440b699e1e30ebd08501d6f2720adbc8255d989a82fcded2f79819b5f8f201bed84a255211b141 -84af7ad4a0e31fcbb3276ab1ad6171429cf39adcf78dc03750dc5deaa46536d15591e26d53e953dfb31e1622bc0743ab -a833e62fe97e1086fae1d4917fbaf09c345feb6bf1975b5cb863d8b66e8d621c7989ab3dbecda36bc9eaffc5eaa6fa66 -b4ef79a46a2126f53e2ebe62770feb57fd94600be29459d70a77c5e9cc260fa892be06cd60f886bf48459e48eb50d063 -b43b8f61919ea380bf151c294e54d3a3ff98e20d1ee5efbfe38aa2b66fafbc6a49739793bd5cb1c809f8b30466277c3a -ab37735af2412d2550e62df9d8b3b5e6f467f20de3890bf56faf1abf2bf3bd1d98dc3fa0ad5e7ab3fce0fa20409eb392 -82416b74b1551d484250d85bb151fabb67e29cce93d516125533df585bc80779ab057ea6992801a3d7d5c6dcff87a018 -8145d0787f0e3b5325190ae10c1d6bee713e6765fb6a0e9214132c6f78f4582bb2771aaeae40d3dad4bafb56bf7e36d8 -b6935886349ecbdd5774e12196f4275c97ec8279fdf28ccf940f6a022ebb6de8e97d6d2173c3fe402cbe9643bed3883b -87ef9b4d3dc71ac86369f8ed17e0dd3b91d16d14ae694bc21a35b5ae37211b043d0e36d8ff07dcc513fb9e6481a1f37f -ae1d0ded32f7e6f1dc8fef495879c1d9e01826f449f903c1e5034aeeabc5479a9e323b162b688317d46d35a42d570d86 -a40d16497004db4104c6794e2f4428d75bdf70352685944f3fbe17526df333e46a4ca6de55a4a48c02ecf0bde8ba03c0 -8d45121efba8cc308a498e8ee39ea6fa5cae9fb2e4aab1c2ff9d448aa8494ccbec9a078f978a86fcd97b5d5e7be7522a -a8173865c64634ba4ac2fa432740f5c05056a9deaf6427cb9b4b8da94ca5ddbc8c0c5d3185a89b8b28878194de9cdfcd -b6ec06a74d690f6545f0f0efba236e63d1fdfba54639ca2617408e185177ece28901c457d02b849fd00f1a53ae319d0a -b69a12df293c014a40070e3e760169b6f3c627caf9e50b35a93f11ecf8df98b2bc481b410eecb7ab210bf213bbe944de -97e7dc121795a533d4224803e591eef3e9008bab16f12472210b73aaf77890cf6e3877e0139403a0d3003c12c8f45636 -acdfa6fdd4a5acb7738cc8768f7cba84dbb95c639399b291ae8e4e63df37d2d4096900a84d2f0606bf534a9ccaa4993f -86ee253f3a9446a33e4d1169719b7d513c6b50730988415382faaf751988c10a421020609f7bcdef91be136704b906e2 -aac9438382a856caf84c5a8a234282f71b5fc5f65219103b147e7e6cf565522285fbfd7417b513bdad8277a00f652ca1 -83f3799d8e5772527930f5dc071a2e0a65471618993ec8990a96ccdeee65270e490bda9d26bb877612475268711ffd80 -93f28a81ac8c0ec9450b9d762fae9c7f8feaace87a6ee6bd141ef1d2d0697ef1bbd159fe6e1de640dbdab2b0361fca8a -a0825c95ba69999b90eac3a31a3fd830ea4f4b2b7409bde5f202b61d741d6326852ce790f41de5cb0eccec7af4db30c1 -83924b0e66233edd603c3b813d698daa05751fc34367120e3cf384ea7432e256ccee4d4daf13858950549d75a377107d -956fd9fa58345277e06ba2ec72f49ed230b8d3d4ff658555c52d6cddeb84dd4e36f1a614f5242d5ca0192e8daf0543c2 -944869912476baae0b114cced4ff65c0e4c90136f73ece5656460626599051b78802df67d7201c55d52725a97f5f29fe -865cb25b64b4531fb6fe4814d7c8cd26b017a6c6b72232ff53defc18a80fe3b39511b23f9e4c6c7249d06e03b2282ed2 -81e09ff55214960775e1e7f2758b9a6c4e4cd39edf7ec1adfaad51c52141182b79fe2176b23ddc7df9fd153e5f82d668 -b31006896f02bc90641121083f43c3172b1039334501fbaf1672f7bf5d174ddd185f945adf1a9c6cf77be34c5501483d -88b92f6f42ae45e9f05b16e52852826e933efd0c68b0f2418ac90957fd018df661bc47c8d43c2a7d7bfcf669dab98c3c -92fc68f595853ee8683930751789b799f397135d002eda244fe63ecef2754e15849edde3ba2f0cc8b865c9777230b712 -99ca06a49c5cd0bb097c447793fcdd809869b216a34c66c78c7e41e8c22f05d09168d46b8b1f3390db9452d91bc96dea -b48b9490a5d65296802431852d548d81047bbefc74fa7dc1d4e2a2878faacdfcb365ae59209cb0ade01901a283cbd15d -aff0fdbef7c188b120a02bc9085d7b808e88f73973773fef54707bf2cd772cd066740b1b6f4127b5c349f657bd97e738 -966fd4463b4f43dd8ccba7ad50baa42292f9f8b2e70da23bb6780e14155d9346e275ef03ddaf79e47020dcf43f3738bd -9330c3e1fadd9e08ac85f4839121ae20bbeb0a5103d84fa5aadbd1213805bdcda67bf2fb75fc301349cbc851b5559d20 -993bb99867bd9041a71a55ad5d397755cfa7ab6a4618fc526179bfc10b7dc8b26e4372fe9a9b4a15d64f2b63c1052dda -a29b59bcfab51f9b3c490a3b96f0bf1934265c315349b236012adbd64a56d7f6941b2c8cc272b412044bc7731f71e1dc -a65c9cefe1fc35d089fe8580c2e7671ebefdb43014ac291528ff4deefd4883fd4df274af83711dad610dad0d615f9d65 -944c78c56fb227ae632805d448ca3884cd3d2a89181cead3d2b7835e63297e6d740aa79a112edb1d4727824991636df5 -a73d782da1db7e4e65d7b26717a76e16dd9fab4df65063310b8e917dc0bc24e0d6755df5546c58504d04d9e68c3b474a -af80f0b87811ae3124f68108b4ca1937009403f87928bbc53480e7c5408d072053ace5eeaf5a5aba814dab8a45502085 -88aaf1acfc6e2e19b8387c97da707cb171c69812fefdd4650468e9b2c627bd5ccfb459f4d8e56bdfd84b09ddf87e128f -92c97276ff6f72bab6e9423d02ad6dc127962dbce15a0dd1e4a393b4510c555df6aa27be0f697c0d847033a9ca8b8dfd -a0e07d43d96e2d85b6276b3c60aadb48f0aedf2de8c415756dc597249ea64d2093731d8735231dadc961e5682ac59479 -adc9e6718a8f9298957d1da3842a7751c5399bbdf56f8de6c1c4bc39428f4aee6f1ba6613d37bf46b9403345e9d6fc81 -951da434da4b20d949b509ceeba02e24da7ed2da964c2fcdf426ec787779c696b385822c7dbea4df3e4a35921f1e912c -a04cbce0d2b2e87bbf038c798a12ec828423ca6aca08dc8d481cf6466e3c9c73d4d4a7fa47df9a7e2e15aae9e9f67208 -8f855cca2e440d248121c0469de1f94c2a71b8ee2682bbad3a78243a9e03da31d1925e6760dbc48a1957e040fae9abe8 -b642e5b17c1df4a4e101772d73851180b3a92e9e8b26c918050f51e6dd3592f102d20b0a1e96f0e25752c292f4c903ff -a92454c300781f8ae1766dbbb50a96192da7d48ef4cbdd72dd8cbb44c6eb5913c112cc38e9144615fdc03684deb99420 -8b74f7e6c2304f8e780df4649ef8221795dfe85fdbdaa477a1542d135b75c8be45bf89adbbb6f3ddf54ca40f02e733e9 -85cf66292cbb30cec5fd835ab10c9fcb3aea95e093aebf123e9a83c26f322d76ebc89c4e914524f6c5f6ee7d74fc917d -ae0bfe0cdc97c09542a7431820015f2d16067b30dca56288013876025e81daa8c519e5e347268e19aa1a85fa1dc28793 -921322fc6a47dc091afa0ad6df18ed14cde38e48c6e71550aa513918b056044983aee402de21051235eecf4ce8040fbe -96c030381e97050a45a318d307dcb3c8377b79b4dd5daf6337cded114de26eb725c14171b9b8e1b3c08fe1f5ea6b49e0 -90c23b86b6111818c8baaf53a13eaee1c89203b50e7f9a994bf0edf851919b48edbac7ceef14ac9414cf70c486174a77 -8bf6c301240d2d1c8d84c71d33a6dfc6d9e8f1cfae66d4d0f7a256d98ae12b0bcebfa94a667735ee89f810bcd7170cff -a41a4ffbbea0e36874d65c009ee4c3feffff322f6fc0e30d26ee4dbc1f46040d05e25d9d0ecb378cef0d24a7c2c4b850 -a8d4cdd423986bb392a0a92c12a8bd4da3437eec6ef6af34cf5310944899287452a2eb92eb5386086d5063381189d10e -a81dd26ec057c4032a4ed7ad54d926165273ed51d09a1267b2e477535cf6966835a257c209e4e92d165d74fa75695fa3 -8d7f708c3ee8449515d94fc26b547303b53d8dd55f177bc3b25d3da2768accd9bc8e9f09546090ebb7f15c66e6c9c723 -839ba65cffcd24cfffa7ab3b21faabe3c66d4c06324f07b2729c92f15cad34e474b0f0ddb16cd652870b26a756b731d3 -87f1a3968afec354d92d77e2726b702847c6afcabb8438634f9c6f7766de4c1504317dc4fa9a4a735acdbf985e119564 -91a8a7fd6542f3e0673f07f510d850864b34ac087eb7eef8845a1d14b2b1b651cbdc27fa4049bdbf3fea54221c5c8549 -aef3cf5f5e3a2385ead115728d7059e622146c3457d266c612e778324b6e06fbfb8f98e076624d2f3ce1035d65389a07 -819915d6232e95ccd7693fdd78d00492299b1983bc8f96a08dcb50f9c0a813ed93ae53c0238345d5bea0beda2855a913 -8e9ba68ded0e94935131b392b28218315a185f63bf5e3c1a9a9dd470944509ca0ba8f6122265f8da851b5cc2abce68f1 -b28468e9b04ee9d69003399a3cf4457c9bf9d59f36ab6ceeb8e964672433d06b58beeea198fedc7edbaa1948577e9fa2 -a633005e2c9f2fd94c8bce2dd5bb708fe946b25f1ec561ae65e54e15cdd88dc339f1a083e01f0d39610c8fe24151aaf0 -841d0031e22723f9328dd993805abd13e0c99b0f59435d2426246996b08d00ce73ab906f66c4eab423473b409e972ce0 -85758d1b084263992070ec8943f33073a2d9b86a8606672550c17545507a5b3c88d87382b41916a87ee96ff55a7aa535 -8581b06b0fc41466ef94a76a1d9fb8ae0edca6d018063acf6a8ca5f4b02d76021902feba58972415691b4bdbc33ae3b4 -83539597ff5e327357ee62bc6bf8c0bcaec2f227c55c7c385a4806f0d37fb461f1690bad5066b8a5370950af32fafbef -aee3557290d2dc10827e4791d00e0259006911f3f3fce4179ed3c514b779160613eca70f720bff7804752715a1266ffa -b48d2f0c4e90fc307d5995464e3f611a9b0ef5fe426a289071f4168ed5cc4f8770c9332960c2ca5c8c427f40e6bb389f -847af8973b4e300bb06be69b71b96183fd1a0b9d51b91701bef6fcfde465068f1eb2b1503b07afda380f18d69de5c9e1 -a70a6a80ce407f07804c0051ac21dc24d794b387be94eb24e1db94b58a78e1bcfb48cd0006db8fc1f9bedaece7a44fbe -b40e942b8fa5336910ff0098347df716bff9d1fa236a1950c16eeb966b3bc1a50b8f7b0980469d42e75ae13ced53cead -b208fabaa742d7db3148515330eb7a3577487845abdb7bd9ed169d0e081db0a5816595c33d375e56aeac5b51e60e49d3 -b7c8194b30d3d6ef5ab66ec88ad7ebbc732a3b8a41731b153e6f63759a93f3f4a537eab9ad369705bd730184bdbbdc34 -9280096445fe7394d04aa1bc4620c8f9296e991cc4d6c131bd703cb1cc317510e6e5855ac763f4d958c5edfe7eebeed7 -abc2aa4616a521400af1a12440dc544e3c821313d0ab936c86af28468ef8bbe534837e364598396a81cf8d06274ed5a6 -b18ca8a3325adb0c8c18a666d4859535397a1c3fe08f95eebfac916a7a99bbd40b3c37b919e8a8ae91da38bc00fa56c0 -8a40c33109ecea2a8b3558565877082f79121a432c45ec2c5a5e0ec4d1c203a6788e6b69cb37f1fd5b8c9a661bc5476d -88c47301dd30998e903c84e0b0f2c9af2e1ce6b9f187dab03528d44f834dc991e4c86d0c474a2c63468cf4020a1e24a0 -920c832853e6ab4c851eecfa9c11d3acc7da37c823be7aa1ab15e14dfd8beb5d0b91d62a30cec94763bd8e4594b66600 -98e1addbe2a6b8edc7f12ecb9be81c3250aeeca54a1c6a7225772ca66549827c15f3950d01b8eb44aecb56fe0fff901a -8cfb0fa1068be0ec088402f5950c4679a2eb9218c729da67050b0d1b2d7079f3ddf4bf0f57d95fe2a8db04bc6bcdb20c -b70f381aafe336b024120453813aeab70baac85b9c4c0f86918797b6aee206e6ed93244a49950f3d8ec9f81f4ac15808 -a4c8edf4aa33b709a91e1062939512419711c1757084e46f8f4b7ed64f8e682f4e78b7135920c12f0eb0422fe9f87a6a -b4817e85fd0752d7ebb662d3a51a03367a84bac74ebddfba0e5af5e636a979500f72b148052d333b3dedf9edd2b4031b -a87430169c6195f5d3e314ff2d1c2f050e766fd5d2de88f5207d72dba4a7745bb86d0baca6e9ae156582d0d89e5838c7 -991b00f8b104566b63a12af4826b61ce7aa40f4e5b8fff3085e7a99815bdb4471b6214da1e480214fac83f86a0b93cc5 -b39966e3076482079de0678477df98578377a094054960ee518ef99504d6851f8bcd3203e8da5e1d4f6f96776e1fe6eb -a448846d9dc2ab7a0995fa44b8527e27f6b3b74c6e03e95edb64e6baa4f1b866103f0addb97c84bef1d72487b2e21796 -894bec21a453ae84b592286e696c35bc30e820e9c2fd3e63dd4fbe629e07df16439c891056070faa490155f255bf7187 -a9ec652a491b11f6a692064e955f3f3287e7d2764527e58938571469a1e29b5225b9415bd602a45074dfbfe9c131d6ca -b39d37822e6cbe28244b5f42ce467c65a23765bd16eb6447c5b3e942278069793763483dafd8c4dd864f8917aad357fe -88dba51133f2019cb266641c56101e3e5987d3b77647a2e608b5ff9113dfc5f85e2b7c365118723131fbc0c9ca833c9c -b566579d904b54ecf798018efcb824dccbebfc6753a0fd2128ac3b4bd3b038c2284a7c782b5ca6f310eb7ea4d26a3f0a -a97a55c0a492e53c047e7d6f9d5f3e86fb96f3dddc68389c0561515343b66b4bc02a9c0d5722dff1e3445308240b27f7 -a044028ab4bcb9e1a2b9b4ca4efbf04c5da9e4bf2fff0e8bd57aa1fc12a71e897999c25d9117413faf2f45395dee0f13 -a78dc461decbeaeed8ebd0909369b491a5e764d6a5645a7dac61d3140d7dc0062526f777b0eb866bff27608429ebbdde -b2c2a8991f94c39ca35fea59f01a92cb3393e0eccb2476dfbf57261d406a68bd34a6cff33ed80209991688c183609ef4 -84189eefb521aff730a4fd3fd5b10ddfd29f0d365664caef63bb015d07e689989e54c33c2141dd64427805d37a7e546e -85ac80bd734a52235da288ff042dea9a62e085928954e8eacd2c751013f61904ed110e5b3afe1ab770a7e6485efb7b5e -9183a560393dcb22d0d5063e71182020d0fbabb39e32493eeffeb808df084aa243eb397027f150b55a247d1ed0c8513e -81c940944df7ecc58d3c43c34996852c3c7915ed185d7654627f7af62abae7e0048dd444a6c09961756455000bd96d09 -aa8c34e164019743fd8284b84f06c3b449aae7996e892f419ee55d82ad548cb300fd651de329da0384243954c0ef6a60 -89a7b7bdfc7e300d06a14d463e573d6296d8e66197491900cc9ae49504c4809ff6e61b758579e9091c61085ba1237b83 -878d21809ba540f50bd11f4c4d9590fb6f3ab9de5692606e6e2ef4ed9d18520119e385be5e1f4b3f2e2b09c319f0e8fc -8eb248390193189cf0355365e630b782cd15751e672dc478b39d75dc681234dcd9309df0d11f4610dbb249c1e6be7ef9 -a1d7fb3aecb896df3a52d6bd0943838b13f1bd039c936d76d03de2044c371d48865694b6f532393b27fd10a4cf642061 -a34bca58a24979be442238cbb5ece5bee51ae8c0794dd3efb3983d4db713bc6f28a96e976ac3bd9a551d3ed9ba6b3e22 -817c608fc8cacdd178665320b5a7587ca21df8bdd761833c3018b967575d25e3951cf3d498a63619a3cd2ad4406f5f28 -86c95707db0495689afd0c2e39e97f445f7ca0edffad5c8b4cacd1421f2f3cc55049dfd504f728f91534e20383955582 -99c3b0bb15942c301137765d4e19502f65806f3b126dc01a5b7820c87e8979bce6a37289a8f6a4c1e4637227ad5bf3bf -8aa1518a80ea8b074505a9b3f96829f5d4afa55a30efe7b4de4e5dbf666897fdd2cf31728ca45921e21a78a80f0e0f10 -8d74f46361c79e15128ac399e958a91067ef4cec8983408775a87eca1eed5b7dcbf0ddf30e66f51780457413496c7f07 -a41cde4a786b55387458a1db95171aca4fd146507b81c4da1e6d6e495527c3ec83fc42fad1dfe3d92744084a664fd431 -8c352852c906fae99413a84ad11701f93f292fbf7bd14738814f4c4ceab32db02feb5eb70bc73898b0bc724a39d5d017 -a5993046e8f23b71ba87b7caa7ace2d9023fb48ce4c51838813174880d918e9b4d2b0dc21a2b9c6f612338c31a289df8 -83576d3324bf2d8afbfb6eaecdc5d767c8e22e7d25160414924f0645491df60541948a05e1f4202e612368e78675de8a -b43749b8df4b15bc9a3697e0f1c518e6b04114171739ef1a0c9c65185d8ec18e40e6954d125cbc14ebc652cf41ad3109 -b4eebd5d80a7327a040cafb9ccdb12b2dfe1aa86e6bc6d3ac8a57fadfb95a5b1a7332c66318ff72ba459f525668af056 -9198be7f1d413c5029b0e1c617bcbc082d21abe2c60ec8ce9b54ca1a85d3dba637b72fda39dae0c0ae40d047eab9f55a -8d96a0232832e24d45092653e781e7a9c9520766c3989e67bbe86b3a820c4bf621ea911e7cd5270a4bfea78b618411f6 -8d7160d0ea98161a2d14d46ef01dff72d566c330cd4fabd27654d300e1bc7644c68dc8eabf2a20a59bfe7ba276545f9b -abb60fce29dec7ba37e3056e412e0ec3e05538a1fc0e2c68877378c867605966108bc5742585ab6a405ce0c962b285b6 -8fabffa3ed792f05e414f5839386f6449fd9f7b41a47595c5d71074bd1bb3784cc7a1a7e1ad6b041b455035957e5b2dc -90ff017b4804c2d0533b72461436b10603ab13a55f86fd4ec11b06a70ef8166f958c110519ca1b4cc7beba440729fe2d -b340cfd120f6a4623e3a74cf8c32bfd7cd61a280b59dfd17b15ca8fae4d82f64a6f15fbde4c02f424debc72b7db5fe67 -871311c9c7220c932e738d59f0ecc67a34356d1429fe570ca503d340c9996cb5ee2cd188fad0e3bd16e4c468ec1dbebd -a772470262186e7b94239ba921b29f2412c148d6f97c4412e96d21e55f3be73f992f1ad53c71008f0558ec3f84e2b5a7 -b2a897dcb7ffd6257f3f2947ec966f2077d57d5191a88840b1d4f67effebe8c436641be85524d0a21be734c63ab5965d -a044f6eacc48a4a061fa149500d96b48cbf14853469aa4d045faf3dca973be1bd4b4ce01646d83e2f24f7c486d03205d -981af5dc2daa73f7fa9eae35a93d81eb6edba4a7f673b55d41f6ecd87a37685d31bb40ef4f1c469b3d72f2f18b925a17 -912d2597a07864de9020ac77083eff2f15ceb07600f15755aba61251e8ce3c905a758453b417f04d9c38db040954eb65 -9642b7f6f09394ba5e0805734ef6702c3eddf9eea187ba98c676d5bbaec0e360e3e51dc58433aaa1e2da6060c8659cb7 -8ab3836e0a8ac492d5e707d056310c4c8e0489ca85eb771bff35ba1d658360084e836a6f51bb990f9e3d2d9aeb18fbb5 -879e058e72b73bb1f4642c21ffdb90544b846868139c6511f299aafe59c2d0f0b944dffc7990491b7c4edcd6a9889250 -b9e60b737023f61479a4a8fd253ed0d2a944ea6ba0439bbc0a0d3abf09b0ad1f18d75555e4a50405470ae4990626f390 -b9c2535d362796dcd673640a9fa2ebdaec274e6f8b850b023153b0a7a30fffc87f96e0b72696f647ebe7ab63099a6963 -94aeff145386a087b0e91e68a84a5ede01f978f9dd9fe7bebca78941938469495dc30a96bba9508c0d017873aeea9610 -98b179f8a3d9f0d0a983c30682dd425a2ddc7803be59bd626c623c8951a5179117d1d2a68254c95c9952989877d0ee55 -889ecf5f0ee56938273f74eb3e9ecfb5617f04fb58e83fe4c0e4aef51615cf345bc56f3f61b17f6eed3249d4afd54451 -a0f2b2c39bcea4b50883e2587d16559e246248a66ecb4a4b7d9ab3b51fb39fe98d83765e087eee37a0f86b0ba4144c02 -b2a61e247ed595e8a3830f7973b07079cbda510f28ad8c78c220b26cb6acde4fbb5ee90c14a665f329168ee951b08cf0 -95bd0fcfb42f0d6d8a8e73d7458498a85bcddd2fb132fd7989265648d82ac2707d6d203fac045504977af4f0a2aca4b7 -843e5a537c298666e6cf50fcc044f13506499ef83c802e719ff2c90e85003c132024e04711be7234c04d4b0125512d5d -a46d1797c5959dcd3a5cfc857488f4d96f74277c3d13b98b133620192f79944abcb3a361d939a100187f1b0856eae875 -a1c7786736d6707a48515c38660615fcec67eb8a2598f46657855215f804fd72ab122d17f94fcffad8893f3be658dca7 -b23dc9e610abc7d8bd21d147e22509a0fa49db5be6ea7057b51aae38e31654b3aa044df05b94b718153361371ba2f622 -b00cc8f257d659c22d30e6d641f79166b1e752ea8606f558e4cad6fc01532e8319ea4ee12265ba4140ac45aa4613c004 -ac7019af65221b0cc736287b32d7f1a3561405715ba9a6a122342e04e51637ba911c41573de53e4781f2230fdcb2475f -81a630bc41b3da8b3eb4bf56cba10cd9f93153c3667f009dc332287baeb707d505fb537e6233c8e53d299ec0f013290c -a6b7aea5c545bb76df0f230548539db92bc26642572cb7dd3d5a30edca2b4c386f44fc8466f056b42de2a452b81aff5b -8271624ff736b7b238e43943c81de80a1612207d32036d820c11fc830c737972ccc9c60d3c2359922b06652311e3c994 -8a684106458cb6f4db478170b9ad595d4b54c18bf63b9058f095a2fa1b928c15101472c70c648873d5887880059ed402 -a5cc3c35228122f410184e4326cf61a37637206e589fcd245cb5d0cec91031f8f7586b80503070840fdfd8ce75d3c88b -9443fc631aed8866a7ed220890911057a1f56b0afe0ba15f0a0e295ab97f604b134b1ed9a4245e46ee5f9a93aa74f731 -984b6f7d79835dffde9558c6bb912d992ca1180a2361757bdba4a7b69dc74b056e303adc69fe67414495dd9c2dd91e64 -b15a5c8cba5de080224c274d31c68ed72d2a7126d347796569aef0c4e97ed084afe3da4d4b590b9dda1a07f0c2ff3dfb -991708fe9650a1f9a4e43938b91d45dc68c230e05ee999c95dbff3bf79b1c1b2bb0e7977de454237c355a73b8438b1d9 -b4f7edc7468b176a4a7c0273700c444fa95c726af6697028bed4f77eee887e3400f9c42ee15b782c0ca861c4c3b8c98a -8c60dcc16c51087eb477c13e837031d6c6a3dc2b8bf8cb43c23f48006bc7173151807e866ead2234b460c2de93b31956 -83ad63e9c910d1fc44bc114accfb0d4d333b7ebe032f73f62d25d3e172c029d5e34a1c9d547273bf6c0fead5c8801007 -85de73213cc236f00777560756bdbf2b16841ba4b55902cf2cad9742ecaf5d28209b012ceb41f337456dfeca93010cd7 -a7561f8827ccd75b6686ba5398bb8fc3083351c55a589b18984e186820af7e275af04bcd4c28e1dc11be1e8617a0610b -88c0a4febd4068850557f497ea888035c7fc9f404f6cc7794e7cc8722f048ad2f249e7dc62743e7a339eb7473ad3b0cd -932b22b1d3e6d5a6409c34980d176feb85ada1bf94332ef5c9fc4d42b907dabea608ceef9b5595ef3feee195151f18d8 -a2867bb3f5ab88fbdae3a16c9143ab8a8f4f476a2643c505bb9f37e5b1fd34d216cab2204c9a017a5a67b7ad2dda10e8 -b573d5f38e4e9e8a3a6fd82f0880dc049efa492a946d00283019bf1d5e5516464cf87039e80aef667cb86fdea5075904 -b948f1b5ab755f3f5f36af27d94f503b070696d793b1240c1bdfd2e8e56890d69e6904688b5f8ff5a4bdf5a6abfe195f -917eae95ebc4109a2e99ddd8fec7881d2f7aaa0e25fda44dec7ce37458c2ee832f1829db7d2dcfa4ca0f06381c7fe91d -95751d17ed00a3030bce909333799bb7f4ab641acf585807f355b51d6976dceee410798026a1a004ef4dcdff7ec0f5b8 -b9b7bd266f449a79bbfe075e429613e76c5a42ac61f01c8f0bbbd34669650682efe01ff9dbbc400a1e995616af6aa278 -ac1722d097ce9cd7617161f8ec8c23d68f1fb1c9ca533e2a8b4f78516c2fd8fb38f23f834e2b9a03bb06a9d655693ca9 -a7ad9e96ffd98db2ecdb6340c5d592614f3c159abfd832fe27ee9293519d213a578e6246aae51672ee353e3296858873 -989b8814d5de7937c4acafd000eec2b4cd58ba395d7b25f98cafd021e8efa37029b29ad8303a1f6867923f5852a220eb -a5bfe6282c771bc9e453e964042d44eff4098decacb89aecd3be662ea5b74506e1357ab26f3527110ba377711f3c9f41 -8900a7470b656639721d2abbb7b06af0ac4222ab85a1976386e2a62eb4b88bfb5b72cf7921ddb3cf3a395d7eeb192a2e -95a71b55cd1f35a438cf5e75f8ff11c5ec6a2ebf2e4dba172f50bfad7d6d5dca5de1b1afc541662c81c858f7604c1163 -82b5d62fea8db8d85c5bc3a76d68dedd25794cf14d4a7bc368938ffca9e09f7e598fdad2a5aac614e0e52f8112ae62b9 -997173f07c729202afcde3028fa7f52cefc90fda2d0c8ac2b58154a5073140683e54c49ed1f254481070d119ce0ce02a -aeffb91ccc7a72bbd6ffe0f9b99c9e66e67d59cec2e02440465e9636a613ab3017278cfa72ea8bc4aba9a8dc728cb367 -952743b06e8645894aeb6440fc7a5f62dd3acf96dab70a51e20176762c9751ea5f2ba0b9497ccf0114dc4892dc606031 -874c63baeddc56fbbca2ff6031f8634b745f6e34ea6791d7c439201aee8f08ef5ee75f7778700a647f3b21068513fce6 -85128fec9c750c1071edfb15586435cc2f317e3e9a175bb8a9697bcda1eb9375478cf25d01e7fed113483b28f625122d -85522c9576fd9763e32af8495ae3928ed7116fb70d4378448926bc9790e8a8d08f98cf47648d7da1b6e40d6a210c7924 -97d0f37a13cfb723b848099ca1c14d83e9aaf2f7aeb71829180e664b7968632a08f6a85f557d74b55afe6242f2a36e7c -abaa472d6ad61a5fccd1a57c01aa1bc081253f95abbcba7f73923f1f11c4e79b904263890eeb66926de3e2652f5d1c70 -b3c04945ba727a141e5e8aec2bf9aa3772b64d8fd0e2a2b07f3a91106a95cbcb249adcd074cbe498caf76fffac20d4ef -82c46781a3d730d9931bcabd7434a9171372dde57171b6180e5516d4e68db8b23495c8ac3ab96994c17ddb1cf249b9fb -a202d8b65613c42d01738ccd68ed8c2dbc021631f602d53f751966e04182743ebc8e0747d600b8a8676b1da9ae7f11ab -ae73e7256e9459db04667a899e0d3ea5255211fb486d084e6550b6dd64ca44af6c6b2d59d7aa152de9f96ce9b58d940d -b67d87b176a9722945ec7593777ee461809861c6cfd1b945dde9ee4ff009ca4f19cf88f4bbb5c80c9cbab2fe25b23ac8 -8f0b7a317a076758b0dac79959ee4a06c08b07d0f10538a4b53d3da2eda16e2af26922feb32c090330dc4d969cf69bd3 -90b36bf56adbd8c4b6cb32febc3a8d5f714370c2ac3305c10fa6d168dffb2a026804517215f9a2d4ec8310cdb6bb459b -aa80c19b0682ead69934bf18cf476291a0beddd8ef4ed75975d0a472e2ab5c70f119722a8574ae4973aceb733d312e57 -a3fc9abb12574e5c28dcb51750b4339b794b8e558675eef7d26126edf1de920c35e992333bcbffcbf6a5f5c0d383ce62 -a1573ff23ab972acdcd08818853b111fc757fdd35aa070186d3e11e56b172fb49d840bf297ac0dd222e072fc09f26a81 -98306f2be4caa92c2b4392212d0cbf430b409b19ff7d5b899986613bd0e762c909fc01999aa94be3bd529d67f0113d7f -8c1fc42482a0819074241746d17dc89c0304a2acdae8ed91b5009e9e3e70ff725ba063b4a3e68fdce05b74f5180c545e -a6c6113ebf72d8cf3163b2b8d7f3fa24303b13f55752522c660a98cd834d85d8c79214d900fa649499365e2e7641f77a -ab95eea424f8a2cfd9fb1c78bb724e5b1d71a0d0d1e4217c5d0f98b0d8bbd3f8400a2002abc0a0e4576d1f93f46fefad -823c5a4fd8cf4a75fdc71d5f2dd511b6c0f189b82affeacd2b7cfcad8ad1a5551227dcc9bfdb2e34b2097eaa00efbb51 -b97314dfff36d80c46b53d87a61b0e124dc94018a0bb680c32765b9a2d457f833a7c42bbc90b3b1520c33a182580398d -b17566ee3dcc6bb3b004afe4c0136dfe7dd27df9045ae896dca49fb36987501ae069eb745af81ba3fc19ff037e7b1406 -b0bdc0f55cfd98d331e3a0c4fbb776a131936c3c47c6bffdc3aaf7d8c9fa6803fbc122c2fefbb532e634228687d52174 -aa5d9e60cc9f0598559c28bb9bdd52aa46605ab4ffe3d192ba982398e72cec9a2a44c0d0d938ce69935693cabc0887ea -802b6459d2354fa1d56c592ac1346c428dadea6b6c0a87bf7d309bab55c94e1cf31dd98a7a86bd92a840dd51f218b91b -a526914efdc190381bf1a73dd33f392ecf01350b9d3f4ae96b1b1c3d1d064721c7d6eec5788162c933245a3943f5ee51 -b3b8fcf637d8d6628620a1a99dbe619eabb3e5c7ce930d6efd2197e261bf394b74d4e5c26b96c4b8009c7e523ccfd082 -8f7510c732502a93e095aba744535f3928f893f188adc5b16008385fb9e80f695d0435bfc5b91cdad4537e87e9d2551c -97b90beaa56aa936c3ca45698f79273a68dd3ccd0076eab48d2a4db01782665e63f33c25751c1f2e070f4d1a8525bf96 -b9fb798324b1d1283fdc3e48288e3861a5449b2ab5e884b34ebb8f740225324af86e4711da6b5cc8361c1db15466602f -b6d52b53cea98f1d1d4c9a759c25bf9d8a50b604b144e4912acbdbdc32aab8b9dbb10d64a29aa33a4f502121a6fb481c -9174ffff0f2930fc228f0e539f5cfd82c9368d26b074467f39c07a774367ff6cccb5039ac63f107677d77706cd431680 -a33b6250d4ac9e66ec51c063d1a6a31f253eb29bbaed12a0d67e2eccfffb0f3a52750fbf52a1c2aaba8c7692346426e7 -a97025fd5cbcebe8ef865afc39cd3ea707b89d4e765ec817fd021d6438e02fa51e3544b1fd45470c58007a08efac6edd -b32a78480edd9ff6ba2f1eec4088db5d6ceb2d62d7e59e904ecaef7bb4a2e983a4588e51692b3be76e6ffbc0b5f911a5 -b5ab590ef0bb77191f00495b33d11c53c65a819f7d0c1f9dc4a2caa147a69c77a4fff7366a602d743ee1f395ce934c1e -b3fb0842f9441fb1d0ee0293b6efbc70a8f58d12d6f769b12872db726b19e16f0f65efbc891cf27a28a248b0ef9c7e75 -9372ad12856fefb928ccb0d34e198df99e2f8973b07e9d417a3134d5f69e12e79ff572c4e03ccd65415d70639bc7c73e -aa8d6e83d09ce216bfe2009a6b07d0110d98cf305364d5529c170a23e693aabb768b2016befb5ada8dabdd92b4d012bb -a954a75791eeb0ce41c85200c3763a508ed8214b5945a42c79bfdcfb1ec4f86ad1dd7b2862474a368d4ac31911a2b718 -8e2081cfd1d062fe3ab4dab01f68062bac802795545fede9a188f6c9f802cb5f884e60dbe866710baadbf55dc77c11a4 -a2f06003b9713e7dd5929501ed485436b49d43de80ea5b15170763fd6346badf8da6de8261828913ee0dacd8ff23c0e1 -98eecc34b838e6ffd1931ca65eec27bcdb2fdcb61f33e7e5673a93028c5865e0d1bf6d3bec040c5e96f9bd08089a53a4 -88cc16019741b341060b95498747db4377100d2a5bf0a5f516f7dec71b62bcb6e779de2c269c946d39040e03b3ae12b7 -ad1135ccbc3019d5b2faf59a688eef2500697642be8cfbdf211a1ab59abcc1f24483e50d653b55ff1834675ac7b4978f -a946f05ed9972f71dfde0020bbb086020fa35b482cce8a4cc36dd94355b2d10497d7f2580541bb3e81b71ac8bba3c49f -a83aeed488f9a19d8cfd743aa9aa1982ab3723560b1cd337fc2f91ad82f07afa412b3993afb845f68d47e91ba4869840 -95eebe006bfc316810cb71da919e5d62c2cebb4ac99d8e8ef67be420302320465f8b69873470982de13a7c2e23516be9 -a55f8961295a11e91d1e5deadc0c06c15dacbfc67f04ccba1d069cba89d72aa3b3d64045579c3ea8991b150ac29366ae -b321991d12f6ac07a5de3c492841d1a27b0d3446082fbce93e7e1f9e8d8fe3b45d41253556261c21b70f5e189e1a7a6f -a0b0822f15f652ce7962a4f130104b97bf9529797c13d6bd8e24701c213cc37f18157bd07f3d0f3eae6b7cd1cb40401f -96e2fa4da378aa782cc2d5e6e465fc9e49b5c805ed01d560e9b98abb5c0de8b74a2e7bec3aa5e2887d25cccb12c66f0c -97e4ab610d414f9210ed6f35300285eb3ccff5b0b6a95ed33425100d7725e159708ea78704497624ca0a2dcabce3a2f9 -960a375b17bdb325761e01e88a3ea57026b2393e1d887b34b8fa5d2532928079ce88dc9fd06a728b26d2bb41b12b9032 -8328a1647398e832aadc05bd717487a2b6fcdaa0d4850d2c4da230c6a2ed44c3e78ec4837b6094f3813f1ee99414713f -aa283834ebd18e6c99229ce4b401eda83f01d904f250fedd4e24f1006f8fa0712a6a89a7296a9bf2ce8de30e28d1408e -b29e097f2caadae3e0f0ae3473c072b0cd0206cf6d2e9b22c1a5ad3e07d433e32bd09ed1f4e4276a2da4268633357b7f -9539c5cbba14538b2fe077ecf67694ef240da5249950baaabea0340718b882a966f66d97f08556b08a4320ceb2cc2629 -b4529f25e9b42ae8cf8338d2eface6ba5cd4b4d8da73af502d081388135c654c0b3afb3aa779ffc80b8c4c8f4425dd2b -95be0739c4330619fbe7ee2249c133c91d6c07eab846c18c5d6c85fc21ac5528c5d56dcb0145af68ed0c6a79f68f2ccd -ac0c83ea802227bfc23814a24655c9ff13f729619bcffdb487ccbbf029b8eaee709f8bddb98232ef33cd70e30e45ca47 -b503becb90acc93b1901e939059f93e671900ca52c6f64ae701d11ac891d3a050b505d89324ce267bc43ab8275da6ffe -98e3811b55b1bacb70aa409100abb1b870f67e6d059475d9f278c751b6e1e2e2d6f2e586c81a9fb6597fda06e7923274 -b0b0f61a44053fa6c715dbb0731e35d48dba257d134f851ee1b81fd49a5c51a90ebf5459ec6e489fce25da4f184fbdb1 -b1d2117fe811720bb997c7c93fe9e4260dc50fca8881b245b5e34f724aaf37ed970cdad4e8fcb68e05ac8cf55a274a53 -a10f502051968f14b02895393271776dee7a06db9de14effa0b3471825ba94c3f805302bdddac4d397d08456f620999d -a3dbad2ef060ae0bb7b02eaa4a13594f3f900450faa1854fc09620b01ac94ab896321dfb1157cf2374c27e5718e8026a -b550fdec503195ecb9e079dcdf0cad559d64d3c30818ef369b4907e813e689da316a74ad2422e391b4a8c2a2bef25fc0 -a25ba865e2ac8f28186cea497294c8649a201732ecb4620c4e77b8e887403119910423df061117e5f03fc5ba39042db1 -b3f88174e03fdb443dd6addd01303cf88a4369352520187c739fc5ae6b22fa99629c63c985b4383219dab6acc5f6f532 -97a7503248e31e81b10eb621ba8f5210c537ad11b539c96dfb7cf72b846c7fe81bd7532c5136095652a9618000b7f8d3 -a8bcdc1ce5aa8bfa683a2fc65c1e79de8ff5446695dcb8620f7350c26d2972a23da22889f9e2b1cacb3f688c6a2953dc -8458c111df2a37f5dd91a9bee6c6f4b79f4f161c93fe78075b24a35f9817da8dde71763218d627917a9f1f0c4709c1ed -ac5f061a0541152b876cbc10640f26f1cc923c9d4ae1b6621e4bb3bf2cec59bbf87363a4eb72fb0e5b6d4e1c269b52d5 -a9a25ca87006e8a9203cbb78a93f50a36694aa4aad468b8d80d3feff9194455ca559fcc63838128a0ab75ad78c07c13a -a450b85f5dfffa8b34dfd8bc985f921318efacf8857cf7948f93884ba09fb831482ee90a44224b1a41e859e19b74962f -8ed91e7f92f5c6d7a71708b6132f157ac226ecaf8662af7d7468a4fa25627302efe31e4620ad28719318923e3a59bf82 -ab524165fd4c71b1fd395467a14272bd2b568592deafa039d8492e9ef36c6d3f96927c95c72d410a768dc0b6d1fbbc9b -b662144505aa8432c75ffb8d10318526b6d5777ac7af9ebfad87d9b0866c364f7905a6352743bd8fd79ffd9d5dd4f3e6 -a48f1677550a5cd40663bb3ba8f84caaf8454f332d0ceb1d94dbea52d0412fe69c94997f7749929712fd3995298572f7 -8391cd6e2f6b0c242de1117a612be99776c3dc95cb800b187685ea5bf7e2722275eddb79fd7dfc8be8e389c4524cdf70 -875d3acb9af47833b72900bc0a2448999d638f153c5e97e8a14ec02d0c76f6264353a7e275e1f1a5855daced523d243b -91f1823657d30b59b2f627880a9a9cb530f5aca28a9fd217fe6f2f5133690dfe7ad5a897872e400512db2e788b3f7628 -ad3564332aa56cea84123fc7ca79ea70bb4fef2009fa131cb44e4b15e8613bd11ca1d83b9d9bf456e4b7fee9f2e8b017 -8c530b84001936d5ab366c84c0b105241a26d1fb163669f17c8f2e94776895c2870edf3e1bc8ccd04d5e65531471f695 -932d01fa174fdb0c366f1230cffde2571cc47485f37f23ba5a1825532190cc3b722aeb1f15aed62cf83ccae9403ba713 -88b28c20585aca50d10752e84b901b5c2d58efef5131479fbbe53de7bce2029e1423a494c0298e1497669bd55be97a5d -b914148ca717721144ebb3d3bf3fcea2cd44c30c5f7051b89d8001502f3856fef30ec167174d5b76265b55d70f8716b5 -81d0173821c6ddd2a068d70766d9103d1ee961c475156e0cbd67d54e668a796310474ef698c7ab55abe6f2cf76c14679 -8f28e8d78e2fe7fa66340c53718e0db4b84823c8cfb159c76eac032a62fb53da0a5d7e24ca656cf9d2a890cb2a216542 -8a26360335c73d1ab51cec3166c3cf23b9ea51e44a0ad631b0b0329ef55aaae555420348a544e18d5760969281759b61 -94f326a32ed287545b0515be9e08149eb0a565025074796d72387cc3a237e87979776410d78339e23ef3172ca43b2544 -a785d2961a2fa5e70bffa137858a92c48fe749fee91b02599a252b0cd50d311991a08efd7fa5e96b78d07e6e66ffe746 -94af9030b5ac792dd1ce517eaadcec1482206848bea4e09e55cc7f40fd64d4c2b3e9197027c5636b70d6122c51d2235d -9722869f7d1a3992850fe7be405ec93aa17dc4d35e9e257d2e469f46d2c5a59dbd504056c85ab83d541ad8c13e8bcd54 -b13c4088b61a06e2c03ac9813a75ff1f68ffdfee9df6a8f65095179a475e29cc49119cad2ce05862c3b1ac217f3aace9 -8c64d51774753623666b10ca1b0fe63ae42f82ed6aa26b81dc1d48c86937c5772eb1402624c52a154b86031854e1fb9f -b47e4df18002b7dac3fee945bf9c0503159e1b8aafcce2138818e140753011b6d09ef1b20894e08ba3006b093559061b -93cb5970076522c5a0483693f6a35ffd4ea2aa7aaf3730c4eccd6af6d1bebfc1122fc4c67d53898ae13eb6db647be7e2 -a68873ef80986795ea5ed1a597d1cd99ed978ec25e0abb57fdcc96e89ef0f50aeb779ff46e3dce21dc83ada3157a8498 -8cab67f50949cc8eee6710e27358aea373aae3c92849f8f0b5531c080a6300cdf2c2094fe6fecfef6148de0d28446919 -993e932bcb616dbaa7ad18a4439e0565211d31071ef1b85a0627db74a05d978c60d507695eaeea5c7bd9868a21d06923 -acdadff26e3132d9478a818ef770e9fa0d2b56c6f5f48bd3bd674436ccce9bdfc34db884a73a30c04c5f5e9764cb2218 -a0d3e64c9c71f84c0eef9d7a9cb4fa184224b969db5514d678e93e00f98b41595588ca802643ea225512a4a272f5f534 -91c9140c9e1ba6e330cb08f6b2ce4809cd0d5a0f0516f70032bf30e912b0ed684d07b413b326ab531ee7e5b4668c799b -87bc2ee7a0c21ba8334cd098e35cb703f9af57f35e091b8151b9b63c3a5b0f89bd7701dbd44f644ea475901fa6d9ef08 -9325ccbf64bf5d71b303e31ee85d486298f9802c5e55b2c3d75427097bf8f60fa2ab4fcaffa9b60bf922c3e24fbd4b19 -95d0506e898318f3dc8d28d16dfd9f0038b54798838b3c9be2a2ae3c2bf204eb496166353fc042220b0bd4f6673b9285 -811de529416331fe9c416726d45df9434c29dcd7e949045eb15740f47e97dde8f31489242200e19922cac2a8b7c6fd1f -ade632d04a4c8bbab6ca7df370b2213cb9225023e7973f0e29f4f5e52e8aeaabc65171306bbdd12a67b195dfbb96d48f -88b7f029e079b6ae956042c0ea75d53088c5d0efd750dd018adaeacf46be21bf990897c58578c491f41afd3978d08073 -91f477802de507ffd2be3f4319903119225b277ad24f74eb50f28b66c14d32fae53c7edb8c7590704741af7f7f3e3654 -809838b32bb4f4d0237e98108320d4b079ee16ed80c567e7548bd37e4d7915b1192880f4812ac0e00476d246aec1dbc8 -84183b5fc4a7997a8ae5afedb4d21dce69c480d5966b5cbdafd6dd10d29a9a6377f3b90ce44da0eb8b176ac3af0253bb -8508abbf6d3739a16b9165caf0f95afb3b3ac1b8c38d6d374cf0c91296e2c1809a99772492b539cda184510bce8a0271 -8722054e59bab2062e6419a6e45fc803af77fde912ef2cd23055ad0484963de65a816a2debe1693d93c18218d2b8e81a -8e895f80e485a7c4f56827bf53d34b956281cdc74856c21eb3b51f6288c01cc3d08565a11cc6f3e2604775885490e8c5 -afc92714771b7aa6e60f3aee12efd9c2595e9659797452f0c1e99519f67c8bc3ac567119c1ddfe82a3e961ee9defea9a -818ff0fd9cefd32db87b259e5fa32967201016fc02ef44116cdca3c63ce5e637756f60477a408709928444a8ad69c471 -8251e29af4c61ae806fc5d032347fb332a94d472038149225298389495139ce5678fae739d02dfe53a231598a992e728 -a0ea39574b26643f6f1f48f99f276a8a64b5481989cfb2936f9432a3f8ef5075abfe5c067dc5512143ce8bf933984097 -af67a73911b372bf04e57e21f289fc6c3dfac366c6a01409b6e76fea4769bdb07a6940e52e8d7d3078f235c6d2f632c6 -b5291484ef336024dd2b9b4cf4d3a6b751133a40656d0a0825bcc6d41c21b1c79cb50b0e8f4693f90c29c8f4358641f9 -8bc0d9754d70f2cb9c63f991902165a87c6535a763d5eece43143b5064ae0bcdce7c7a8f398f2c1c29167b2d5a3e6867 -8d7faff53579ec8f6c92f661c399614cc35276971752ce0623270f88be937c414eddcb0997e14724a783905a026c8883 -9310b5f6e675fdf60796f814dbaa5a6e7e9029a61c395761e330d9348a7efab992e4e115c8be3a43d08e90d21290c892 -b5eb4f3eb646038ad2a020f0a42202532d4932e766da82b2c1002bf9c9c2e5336b54c8c0ffcc0e02d19dde2e6a35b6cc -91dabfd30a66710f1f37a891136c9be1e23af4abf8cb751f512a40c022a35f8e0a4fb05b17ec36d4208de02d56f0d53a -b3ded14e82d62ac7a5a036122a62f00ff8308498f3feae57d861babaff5a6628d43f0a0c5fc903f10936bcf4e2758ceb -a88e8348fed2b26acca6784d19ef27c75963450d99651d11a950ea81d4b93acd2c43e0ecce100eaf7e78508263d5baf3 -b1f5bbf7c4756877b87bb42163ac570e08c6667c4528bf68b5976680e19beeff7c5effd17009b0718797077e2955457a -ad2e7b516243f915d4d1415326e98b1a7390ae88897d0b03b66c2d9bd8c3fba283d7e8fe44ed3333296a736454cef6d8 -8f82eae096d5b11f995de6724a9af895f5e1c58d593845ad16ce8fcae8507e0d8e2b2348a0f50a1f66a17fd6fac51a5c -890e4404d0657c6c1ee14e1aac132ecf7a568bb3e04137b85ac0f84f1d333bd94993e8750f88eee033a33fb00f85dcc7 -82ac7d3385e035115f1d39a99fc73e5919de44f5e6424579776d118d711c8120b8e5916372c6f27bed4cc64cac170b6c -85ee16d8901c272cfbbe966e724b7a891c1bd5e68efd5d863043ad8520fc409080af61fd726adc680b3f1186fe0ac8b8 -86dc564c9b545567483b43a38f24c41c6551a49cabeebb58ce86404662a12dbfafd0778d30d26e1c93ce222e547e3898 -a29f5b4522db26d88f5f95f18d459f8feefab02e380c2edb65aa0617a82a3c1a89474727a951cef5f15050bcf7b380fb -a1ce039c8f6cac53352899edb0e3a72c76da143564ad1a44858bd7ee88552e2fe6858d1593bbd74aeee5a6f8034b9b9d -97f10d77983f088286bd7ef3e7fdd8fa275a56bec19919adf33cf939a90c8f2967d2b1b6fc51195cb45ad561202a3ed7 -a25e2772e8c911aaf8712bdac1dd40ee061c84d3d224c466cfaae8e5c99604053f940cde259bd1c3b8b69595781dbfec -b31bb95a0388595149409c48781174c340960d59032ab2b47689911d03c68f77a2273576fbe0c2bf4553e330656058c7 -b8b2e9287ad803fb185a13f0d7456b397d4e3c8ad5078f57f49e8beb2e85f661356a3392dbd7bcf6a900baa5582b86a1 -a3d0893923455eb6e96cc414341cac33d2dbc88fba821ac672708cce131761d85a0e08286663a32828244febfcae6451 -82310cb42f647d99a136014a9f881eb0b9791efd2e01fc1841907ad3fc8a9654d3d1dab6689c3607214b4dc2aca01cee -874022d99c16f60c22de1b094532a0bc6d4de700ad01a31798fac1d5088b9a42ad02bef8a7339af7ed9c0d4f16b186ee -94981369e120265aed40910eebc37eded481e90f4596b8d57c3bec790ab7f929784bd33ddd05b7870aad6c02e869603b -a4f1f50e1e2a73f07095e0dd31cb45154f24968dae967e38962341c1241bcd473102fff1ff668b20c6547e9732d11701 -ae2328f3b0ad79fcda807e69a1b5278145225083f150f67511dafc97e079f860c3392675f1752ae7e864c056e592205b -875d8c971e593ca79552c43d55c8c73b17cd20c81ff2c2fed1eb19b1b91e4a3a83d32df150dbfd5db1092d0aebde1e1f -add2e80aa46aae95da73a11f130f4bda339db028e24c9b11e5316e75ba5e63bc991d2a1da172c7c8e8fee038baae3433 -b46dbe1cb3424002aa7de51e82f600852248e251465c440695d52538d3f36828ff46c90ed77fc1d11534fe3c487df8ef -a5e5045d28b4e83d0055863c30c056628c58d4657e6176fd0536f5933f723d60e851bb726d5bf3c546b8ce4ac4a57ef8 -91fec01e86dd1537e498fff7536ea3ca012058b145f29d9ada49370cd7b7193ac380e116989515df1b94b74a55c45df3 -a7428176d6918cd916a310bdc75483c72de660df48cac4e6e7478eef03205f1827ea55afc0df5d5fa7567d14bbea7fc9 -851d89bef45d9761fe5fdb62972209335193610015e16a675149519f9911373bac0919add226ef118d9f3669cfdf4734 -b74acf5c149d0042021cb2422ea022be4c4f72a77855f42393e71ffd12ebb3eec16bdf16f812159b67b79a9706e7156d -99f35dce64ec99aa595e7894b55ce7b5a435851b396e79036ffb249c28206087db4c85379df666c4d95857db02e21ff9 -b6b9a384f70db9e298415b8ab394ee625dafff04be2886476e59df8d052ca832d11ac68a9b93fba7ab055b7bc36948a4 -898ee4aefa923ffec9e79f2219c7389663eb11eb5b49014e04ed4a336399f6ea1691051d86991f4c46ca65bcd4fdf359 -b0f948217b0d65df7599a0ba4654a5e43c84db477936276e6f11c8981efc6eaf14c90d3650107ed4c09af4cc8ec11137 -aa6286e27ac54f73e63dbf6f41865dd94d24bc0cf732262fcaff67319d162bb43af909f6f8ee27b1971939cfbba08141 -8bca7cdf730cf56c7b2c8a2c4879d61361a6e1dba5a3681a1a16c17a56e168ace0e99cf0d15826a1f5e67e6b8a8a049a -a746d876e8b1ce225fcafca603b099b36504846961526589af977a88c60d31ba2cc56e66a3dec8a77b3f3531bf7524c9 -a11e2e1927e6704cdb8874c75e4f1842cef84d7d43d7a38e339e61dc8ba90e61bbb20dd3c12e0b11d2471d58eed245be -a36395e22bc1d1ba8b0459a235203177737397da5643ce54ded3459d0869ff6d8d89f50c73cb62394bf66a959cde9b90 -8b49f12ba2fdf9aca7e5f81d45c07d47f9302a2655610e7634d1e4bd16048381a45ef2c95a8dd5b0715e4b7cf42273af -91cffa2a17e64eb7f76bccbe4e87280ee1dd244e04a3c9eac12e15d2d04845d876eb24fe2ec6d6d266cce9efb281077f -a6b8afabf65f2dee01788114e33a2f3ce25376fb47a50b74da7c3c25ff1fdc8aa9f41307534abbf48acb6f7466068f69 -8d13db896ccfea403bd6441191995c1a65365cab7d0b97fbe9526da3f45a877bd1f4ef2edef160e8a56838cd1586330e -98c717de9e01bef8842c162a5e757fe8552d53269c84862f4d451e7c656ae6f2ae473767b04290b134773f63be6fdb9d -8c2036ace1920bd13cf018e82848c49eb511fad65fd0ff51f4e4b50cf3bfc294afb63cba682c16f52fb595a98fa84970 -a3520fdff05dbad9e12551b0896922e375f9e5589368bcb2cc303bde252743b74460cb5caf99629325d3620f13adc796 -8d4f83a5bfec05caf5910e0ce538ee9816ee18d0bd44c1d0da2a87715a23cd2733ad4d47552c6dc0eb397687d611dd19 -a7b39a0a6a02823452d376533f39d35029867b3c9a6ad6bca181f18c54132d675613a700f9db2440fb1b4fa13c8bf18a -80bcb114b2544b80f404a200fc36860ed5e1ad31fe551acd4661d09730c452831751baa9b19d7d311600d267086a70bc -90dcce03c6f88fc2b08f2b42771eedde90cc5330fe0336e46c1a7d1b5a6c1641e5fcc4e7b3d5db00bd8afca9ec66ed81 -aec15f40805065c98e2965b1ae12a6c9020cfdb094c2d0549acfc7ea2401a5fb48d3ea7d41133cf37c4e096e7ff53eb9 -80e129b735dba49fa627a615d6c273119acec8e219b2f2c4373a332b5f98d66cbbdd688dfbe72a8f8bfefaccc02c50c1 -a9b596da3bdfe23e6799ece5f7975bf7a1979a75f4f546deeaf8b34dfe3e0d623217cb4cf4ccd504cfa3625b88cd53f1 -abcbbb70b16f6e517c0ab4363ab76b46e4ff58576b5f8340e5c0e8cc0e02621b6e23d742d73b015822a238b17cfd7665 -a046937cc6ea6a2e1adae543353a9fe929c1ae4ad655be1cc051378482cf88b041e28b1e9a577e6ccff2d3570f55e200 -831279437282f315e65a60184ef158f0a3dddc15a648dc552bdc88b3e6fe8288d3cfe9f0031846d81350f5e7874b4b33 -993d7916fa213c6d66e7c4cafafc1eaec9a2a86981f91c31eb8a69c5df076c789cbf498a24c84e0ee77af95b42145026 -823907a3b6719f8d49b3a4b7c181bd9bb29fcf842d7c70660c4f351852a1e197ca46cf5e879b47fa55f616fa2b87ce5e -8d228244e26132b234930ee14c75d88df0943cdb9c276a8faf167d259b7efc1beec2a87c112a6c608ad1600a239e9aae -ab6e55766e5bfb0cf0764ed909a8473ab5047d3388b4f46faeba2d1425c4754c55c6daf6ad4751e634c618b53e549529 -ab0cab6860e55a84c5ad2948a7e0989e2b4b1fd637605634b118361497332df32d9549cb854b2327ca54f2bcb85eed8f -b086b349ae03ef34f4b25a57bcaa5d1b29bd94f9ebf87e22be475adfe475c51a1230c1ebe13506cb72c4186192451658 -8a0b49d8a254ca6d91500f449cbbfbb69bb516c6948ac06808c65595e46773e346f97a5ce0ef7e5a5e0de278af22709c -ac49de11edaaf04302c73c578cc0824bdd165c0d6321be1c421c1950e68e4f3589aa3995448c9699e93c6ebae8803e27 -884f02d841cb5d8f4c60d1402469216b114ab4e93550b5bc1431756e365c4f870a9853449285384a6fa49e12ce6dc654 -b75f3a28fa2cc8d36b49130cb7448a23d73a7311d0185ba803ad55c8219741d451c110f48b786e96c728bc525903a54f -80ae04dbd41f4a35e33f9de413b6ad518af0919e5a30cb0fa1b061b260420780bb674f828d37fd3b52b5a31673cbd803 -b9a8011eb5fcea766907029bf743b45262db3e49d24f84503687e838651ed11cb64c66281e20a0ae9f6aa51acc552263 -90bfdd75e2dc9cf013e22a5d55d2d2b8a754c96103a17524488e01206e67f8b6d52b1be8c4e3d5307d4fe06d0e51f54c -b4af353a19b06203a815ec43e79a88578cc678c46f5a954b85bc5c53b84059dddba731f3d463c23bfd5273885c7c56a4 -aa125e96d4553b64f7140e5453ff5d2330318b69d74d37d283e84c26ad672fa00e3f71e530eb7e28be1e94afb9c4612e -a18e060aee3d49cde2389b10888696436bb7949a79ca7d728be6456a356ea5541b55492b2138da90108bd1ce0e6f5524 -93e55f92bdbccc2de655d14b1526836ea2e52dba65eb3f87823dd458a4cb5079bf22ce6ef625cb6d6bfdd0995ab9a874 -89f5a683526b90c1c3ceebbb8dc824b21cff851ce3531b164f6626e326d98b27d3e1d50982e507d84a99b1e04e86a915 -83d1c38800361633a3f742b1cb2bfc528129496e80232611682ddbe403e92c2ac5373aea0bca93ecb5128b0b2b7a719e -8ecba560ac94905e19ce8d9c7af217bf0a145d8c8bd38e2db82f5e94cc3f2f26f55819176376b51f154b4aab22056059 -a7e2a4a002b60291924850642e703232994acb4cfb90f07c94d1e0ecd2257bb583443283c20fc6017c37e6bfe85b7366 -93ed7316fa50b528f1636fc6507683a672f4f4403e55e94663f91221cc198199595bd02eef43d609f451acc9d9b36a24 -a1220a8ebc5c50ceed76a74bc3b7e0aa77f6884c71b64b67c4310ac29ce5526cb8992d6abc13ef6c8413ce62486a6795 -b2f6eac5c869ad7f4a25161d3347093e2f70e66cd925032747e901189355022fab3038bca4d610d2f68feb7e719c110b -b703fa11a4d511ca01c7462979a94acb40b5d933759199af42670eb48f83df202fa0c943f6ab3b4e1cc54673ea3aab1e -b5422912afbfcb901f84791b04f1ddb3c3fbdc76d961ee2a00c5c320e06d3cc5b5909c3bb805df66c5f10c47a292b13d -ad0934368da823302e1ac08e3ede74b05dfdbfffca203e97ffb0282c226814b65c142e6e15ec1e754518f221f01b30f7 -a1dd302a02e37df15bf2f1147efe0e3c06933a5a767d2d030e1132f5c3ce6b98e216b6145eb39e1e2f74e76a83165b8d -a346aab07564432f802ae44738049a36f7ca4056df2d8f110dbe7fef4a3e047684dea609b2d03dc6bf917c9c2a47608f -b96c5f682a5f5d02123568e50f5d0d186e4b2c4c9b956ec7aabac1b3e4a766d78d19bd111adb5176b898e916e49be2aa -8a96676d56876fc85538db2e806e1cba20fd01aeb9fa3cb43ca6ca94a2c102639f65660db330e5d74a029bb72d6a0b39 -ab0048336bd5c3def1a4064eadd49e66480c1f2abb4df46e03afbd8a3342c2c9d74ee35d79f08f4768c1646681440984 -888427bdf76caec90814c57ee1c3210a97d107dd88f7256f14f883ad0f392334b82be11e36dd8bfec2b37935177c7831 -b622b282becf0094a1916fa658429a5292ba30fb48a4c8066ce1ddcefb71037948262a01c95bab6929ed3a76ba5db9fe -b5b9e005c1f456b6a368a3097634fb455723abe95433a186e8278dceb79d4ca2fbe21f8002e80027b3c531e5bf494629 -a3c6707117a1e48697ed41062897f55d8119403eea6c2ee88f60180f6526f45172664bfee96bf61d6ec0b7fbae6aa058 -b02a9567386a4fbbdb772d8a27057b0be210447348efe6feb935ceec81f361ed2c0c211e54787dc617cdffed6b4a6652 -a9b8364e40ef15c3b5902e5534998997b8493064fa2bea99600def58279bb0f64574c09ba11e9f6f669a8354dd79dc85 -9998a2e553a9aa9a206518fae2bc8b90329ee59ab23005b10972712389f2ec0ee746033c733092ffe43d73d33abbb8ef -843a4b34d9039bf79df96d79f2d15e8d755affb4d83d61872daf540b68c0a3888cf8fc00d5b8b247b38524bcb3b5a856 -84f7128920c1b0bb40eee95701d30e6fc3a83b7bb3709f16d97e72acbb6057004ee7ac8e8f575936ca9dcb7866ab45f7 -918d3e2222e10e05edb34728162a899ad5ada0aaa491aeb7c81572a9c0d506e31d5390e1803a91ff3bd8e2bb15d47f31 -9442d18e2489613a7d47bb1cb803c8d6f3259d088cd079460976d87f7905ee07dea8f371b2537f6e1d792d36d7e42723 -b491976970fe091995b2ed86d629126523ccf3e9daf8145302faca71b5a71a5da92e0e05b62d7139d3efac5c4e367584 -aa628006235dc77c14cef4c04a308d66b07ac92d377df3de1a2e6ecfe3144f2219ad6d7795e671e1cb37a3641910b940 -99d386adaea5d4981d7306feecac9a555b74ffdc218c907c5aa7ac04abaead0ec2a8237300d42a3fbc464673e417ceed -8f78e8b1556f9d739648ea3cab9606f8328b52877fe72f9305545a73b74d49884044ba9c1f1c6db7d9b7c7b7c661caba -8fb357ae49932d0babdf74fc7aa7464a65d3b6a2b3acf4f550b99601d3c0215900cfd67f2b6651ef94cfc323bac79fae -9906f2fa25c0290775aa001fb6198113d53804262454ae8b83ef371b5271bde189c0460a645829cb6c59f9ee3a55ce4d -8f4379b3ebb50e052325b27655ca6a82e6f00b87bf0d2b680d205dd2c7afdc9ff32a9047ae71a1cdf0d0ce6b9474d878 -a85534e88c2bd43c043792eaa75e50914b21741a566635e0e107ae857aed0412035f7576cf04488ade16fd3f35fdbb87 -b4ce93199966d3c23251ca7f28ec5af7efea1763d376b0385352ffb2e0a462ef95c69940950278cf0e3dafd638b7bd36 -b10cb3d0317dd570aa73129f4acf63c256816f007607c19b423fb42f65133ce21f2f517e0afb41a5378cccf893ae14d0 -a9b231c9f739f7f914e5d943ed9bff7eba9e2c333fbd7c34eb1648a362ee01a01af6e2f7c35c9fe962b11152cddf35de -99ff6a899e156732937fb81c0cced80ae13d2d44c40ba99ac183aa246103b31ec084594b1b7feb96da58f4be2dd5c0ed -8748d15d18b75ff2596f50d6a9c4ce82f61ecbcee123a6ceae0e43cab3012a29b6f83cf67b48c22f6f9d757c6caf76b2 -b88ab05e4248b7fb634cf640a4e6a945d13e331237410f7217d3d17e3e384ddd48897e7a91e4516f1b9cbd30f35f238b -8d826deaeeb84a3b2d2c04c2300ca592501f992810582d6ae993e0d52f6283a839dba66c6c72278cff5871802b71173b -b36fed027c2f05a5ef625ca00b0364b930901e9e4420975b111858d0941f60e205546474bb25d6bfa6928d37305ae95f -af2fcfc6b87967567e8b8a13a4ed914478185705724e56ce68fb2df6d1576a0cf34a61e880997a0d35dc2c3276ff7501 -ac351b919cd1fbf106feb8af2c67692bfcddc84762d18cea681cfa7470a5644839caace27efee5f38c87d3df306f4211 -8d6665fb1d4d8d1fa23bd9b8a86e043b8555663519caac214d1e3e3effbc6bee7f2bcf21e645f77de0ced279d69a8a8b -a9fc1c2061756b2a1a169c1b149f212ff7f0d2488acd1c5a0197eba793cffa593fc6d1d1b40718aa75ca3ec77eff10e1 -aff64f0fa009c7a6cf0b8d7a22ddb2c8170c3cb3eec082e60d5aadb00b0040443be8936d728d99581e33c22178c41c87 -82e0b181adc5e3b1c87ff8598447260e839d53debfae941ebea38265575546c3a74a14b4325a030833a62ff6c52d9365 -b7ad43cbb22f6f892c2a1548a41dc120ab1f4e1b8dea0cb6272dd9cb02054c542ecabc582f7e16de709d48f5166cae86 -985e0c61094281532c4afb788ecb2dfcba998e974b5d4257a22040a161883908cdd068fe80f8eb49b8953cfd11acf43a -ae46895c6d67ea6d469b6c9c07b9e5d295d9ae73b22e30da4ba2c973ba83a130d7eef39717ec9d0f36e81d56bf742671 -8600177ea1f7e7ef90514b38b219a37dedfc39cb83297e4c7a5b479817ef56479d48cf6314820960c751183f6edf8b0e -b9208ec1c1d7a1e99b59c62d3e4e61dfb706b0e940d09d3abfc3454c19749083260614d89cfd7e822596c3cdbcc6bb95 -a1e94042c796c2b48bc724352d2e9f3a22291d9a34705993357ddb6adabd76da6fc25dac200a8cb0b5bbd99ecddb7af6 -b29c3adedd0bcad8a930625bc4dfdc3552a9afd5ca6dd9c0d758f978068c7982b50b711aa0eb5b97f2b84ee784637835 -af0632a238bb1f413c7ea8e9b4c3d68f2827bd2e38cd56024391fba6446ac5d19a780d0cfd4a78fe497d537b766a591a -aaf6e7f7d54f8ef5e2e45dd59774ecbeecf8683aa70483b2a75be6a6071b5981bbaf1627512a65d212817acdfab2e428 -8c751496065da2e927cf492aa5ca9013b24f861d5e6c24b30bbf52ec5aaf1905f40f9a28175faef283dd4ed4f2182a09 -8952377d8e80a85cf67d6b45499f3bad5fd452ea7bcd99efc1b066c4720d8e5bff1214cea90fd1f972a7f0baac3d29be -a1946ee543d1a6e21f380453be4d446e4130950c5fc3d075794eb8260f6f52d0a795c1ff91d028a648dc1ce7d9ab6b47 -89f3fefe37af31e0c17533d2ca1ce0884cc1dc97c15cbfab9c331b8debd94781c9396abef4bb2f163d09277a08d6adf0 -a2753f1e6e1a154fb117100a5bd9052137add85961f8158830ac20541ab12227d83887d10acf7fd36dcaf7c2596d8d23 -814955b4198933ee11c3883863b06ff98c7eceb21fc3e09df5f916107827ccf3323141983e74b025f46ae00284c9513b -8cc5c6bb429073bfef47cae7b3bfccb0ffa076514d91a1862c6bda4d581e0df87db53cc6c130bf8a7826304960f5a34e -909f22c1f1cdc87f7be7439c831a73484a49acbf8f23d47087d7cf867c64ef61da3bde85dc57d705682b4c3fc710d36e -8048fee7f276fcd504aed91284f28e73693615e0eb3858fa44bcf79d7285a9001c373b3ef71d9a3054817ba293ebe28c -94400e5cf5d2700ca608c5fe35ce14623f71cc24959f2bc27ca3684092850f76b67fb1f07ca9e5b2ca3062cf8ad17bd4 -81c2ae7d4d1b17f8b6de6a0430acc0d58260993980fe48dc2129c4948269cdc74f9dbfbf9c26b19360823fd913083d48 -8c41fe765128e63f6889d6a979f6a4342300327c8b245a8cfe3ecfbcac1e09c3da30e2a1045b24b78efc6d6d50c8c6ac -a5dd4ae51ae48c8be4b218c312ade226cffce671cf121cb77810f6c0990768d6dd767badecb5c69921d5574d5e8433d3 -b7642e325f4ba97ae2a39c1c9d97b35aafd49d53dba36aed3f3cb0ca816480b3394079f46a48252d46596559c90f4d58 -ae87375b40f35519e7bd4b1b2f73cd0b329b0c2cb9d616629342a71c6c304338445eda069b78ea0fbe44087f3de91e09 -b08918cb6f736855e11d3daca1ddfbdd61c9589b203b5493143227bf48e2c77c2e8c94b0d1aa2fab2226e0eae83f2681 -ac36b84a4ac2ebd4d6591923a449c564e3be8a664c46092c09e875c2998eba16b5d32bfd0882fd3851762868e669f0b1 -a44800a3bb192066fa17a3f29029a23697240467053b5aa49b9839fb9b9b8b12bcdcbfc557f024b61f4f51a9aacdefcb -9064c688fec23441a274cdf2075e5a449caf5c7363cc5e8a5dc9747183d2e00a0c69f2e6b3f6a7057079c46014c93b3b -aa367b021469af9f5b764a79bb3afbe2d87fe1e51862221672d1a66f954b165778b7c27a705e0f93841fab4c8468344d -a1a8bfc593d4ab71f91640bc824de5c1380ab2591cfdafcbc78a14b32de3c0e15f9d1b461d85c504baa3d4232c16bb53 -97df48da1799430f528184d30b6baa90c2a2f88f34cdfb342d715339c5ebd6d019aa693cea7c4993daafc9849063a3aa -abd923831fbb427e06e0dd335253178a9e5791395c84d0ab1433c07c53c1209161097e9582fb8736f8a60bde62d8693e -84cd1a43f1a438b43dc60ffc775f646937c4f6871438163905a3cebf1115f814ccd38a6ccb134130bff226306e412f32 -91426065996b0743c5f689eb3ca68a9f7b9e4d01f6c5a2652b57fa9a03d8dc7cd4bdbdab0ca5a891fee1e97a7f00cf02 -a4bee50249db3df7fd75162b28f04e57c678ba142ce4d3def2bc17bcb29e4670284a45f218dad3969af466c62a903757 -83141ebcc94d4681404e8b67a12a46374fded6df92b506aff3490d875919631408b369823a08b271d006d5b93136f317 -a0ea1c8883d58d5a784da3d8c8a880061adea796d7505c1f903d07c287c5467f71e4563fc0faafbc15b5a5538b0a7559 -89d9d480574f201a87269d26fb114278ed2c446328df431dc3556e3500e80e4cd01fcac196a2459d8646361ebda840df -8bf302978973632dd464bec819bdb91304712a3ec859be071e662040620422c6e75eba6f864f764cffa2799272efec39 -922f666bc0fd58b6d7d815c0ae4f66d193d32fc8382c631037f59eeaeae9a8ca6c72d08e72944cf9e800b8d639094e77 -81ad8714f491cdff7fe4399f2eb20e32650cff2999dd45b9b3d996d54a4aba24cc6c451212e78c9e5550368a1a38fb3f -b58fcf4659d73edb73175bd9139d18254e94c3e32031b5d4b026f2ed37aa19dca17ec2eb54c14340231615277a9d347e -b365ac9c2bfe409b710928c646ea2fb15b28557e0f089d39878e365589b9d1c34baf5566d20bb28b33bb60fa133f6eff -8fcae1d75b53ab470be805f39630d204853ca1629a14158bac2f52632277d77458dec204ff84b7b2d77e641c2045be65 -a03efa6bebe84f4f958a56e2d76b5ba4f95dd9ed7eb479edc7cc5e646c8d4792e5b0dfc66cc86aa4b4afe2f7a4850760 -af1c823930a3638975fb0cc5c59651771b2719119c3cd08404fbd4ce77a74d708cefbe3c56ea08c48f5f10e6907f338f -8260c8299b17898032c761c325ac9cabb4c5b7e735de81eacf244f647a45fb385012f4f8df743128888c29aefcaaad16 -ab2f37a573c82e96a8d46198691cd694dfa860615625f477e41f91b879bc58a745784fccd8ffa13065834ffd150d881d -986c746c9b4249352d8e5c629e8d7d05e716b3c7aab5e529ca969dd1e984a14b5be41528baef4c85d2369a42d7209216 -b25e32da1a8adddf2a6080725818b75bc67240728ad1853d90738485d8924ea1e202df0a3034a60ffae6f965ec55cf63 -a266e627afcebcefea6b6b44cbc50f5c508f7187e87d047b0450871c2a030042c9e376f3ede0afcf9d1952f089582f71 -86c3bbca4c0300606071c0a80dbdec21ce1dd4d8d4309648151c420854032dff1241a1677d1cd5de4e4de4385efda986 -b9a21a1fe2d1f3273a8e4a9185abf2ff86448cc98bfa435e3d68306a2b8b4a6a3ea33a155be3cb62a2170a86f77679a5 -b117b1ea381adce87d8b342cba3a15d492ff2d644afa28f22424cb9cbc820d4f7693dfc1a4d1b3697046c300e1c9b4c8 -9004c425a2e68870d6c69b658c344e3aa3a86a8914ee08d72b2f95c2e2d8a4c7bb0c6e7e271460c0e637cec11117bf8e -86a18aa4783b9ebd9131580c8b17994825f27f4ac427b0929a1e0236907732a1c8139e98112c605488ee95f48bbefbfc -84042243b955286482ab6f0b5df4c2d73571ada00716d2f737ca05a0d2e88c6349e8ee9e67934cfee4a1775dbf7f4800 -92c2153a4733a62e4e1d5b60369f3c26777c7d01cd3c8679212660d572bd3bac9b8a8a64e1f10f7dbf5eaa7579c4e423 -918454b6bb8e44a2afa144695ba8d48ae08d0cdfef4ad078f67709eddf3bb31191e8b006f04e82ea45a54715ef4d5817 -acf0b54f6bf34cf6ed6c2b39cf43194a40d68de6bcf1e4b82c34c15a1343e9ac3737885e1a30b78d01fa3a5125463db8 -a7d60dbe4b6a7b054f7afe9ee5cbbfeca0d05dc619e6041fa2296b549322529faddb8a11e949562309aecefb842ac380 -91ffb53e6d7e5f11159eaf13e783d6dbdfdb1698ed1e6dbf3413c6ea23492bbb9e0932230a9e2caac8fe899a17682795 -b6e8d7be5076ee3565d5765a710c5ecf17921dd3cf555c375d01e958a365ae087d4a88da492a5fb81838b7b92bf01143 -a8c6b763de2d4b2ed42102ef64eccfef31e2fb2a8a2776241c82912fa50fc9f77f175b6d109a97ede331307c016a4b1a -99839f86cb700c297c58bc33e28d46b92931961548deac29ba8df91d3e11721b10ea956c8e16984f9e4acf1298a79b37 -8c2e2c338f25ea5c25756b7131cde0d9a2b35abf5d90781180a00fe4b8e64e62590dc63fe10a57fba3a31c76d784eb01 -9687d7df2f41319ca5469d91978fed0565a5f11f829ebadaa83db92b221755f76c6eacd7700735e75c91e257087512e3 -8795fdfb7ff8439c58b9bf58ed53873d2780d3939b902b9ddaaa4c99447224ced9206c3039a23c2c44bcc461e2bb637f -a803697b744d2d087f4e2307218d48fa88620cf25529db9ce71e2e3bbcc65bac5e8bb9be04777ef7bfb5ed1a5b8e6170 -80f3d3efbbb9346ddd413f0a8e36b269eb5d7ff6809d5525ff9a47c4bcab2c01b70018b117f6fe05253775612ff70c6b -9050e0e45bcc83930d4c505af35e5e4d7ca01cd8681cba92eb55821aececcebe32bb692ebe1a4daac4e7472975671067 -8d206812aac42742dbaf233e0c080b3d1b30943b54b60283515da005de05ea5caa90f91fedcfcba72e922f64d7040189 -a2d44faaeb2eff7915c83f32b13ca6f31a6847b1c1ce114ea240bac3595eded89f09b2313b7915ad882292e2b586d5b4 -961776c8576030c39f214ea6e0a3e8b3d32f023d2600958c098c95c8a4e374deeb2b9dc522adfbd6bda5949bdc09e2a2 -993fa7d8447407af0fbcd9e6d77f815fa5233ab00674efbcf74a1f51c37481445ae291cc7b76db7c178f9cb0e570e0fc -abd5b1c78e05f9d7c8cc99bdaef8b0b6a57f2daf0f02bf492bec48ea4a27a8f1e38b5854da96efff11973326ff980f92 -8f15af4764bc275e6ccb892b3a4362cacb4e175b1526a9a99944e692fe6ccb1b4fc19abf312bb2a089cb1f344d91a779 -a09b27ccd71855512aba1d0c30a79ffbe7f6707a55978f3ced50e674b511a79a446dbc6d7946add421ce111135a460af -94b2f98ce86a9271fbd4153e1fc37de48421fe3490fb3840c00f2d5a4d0ba8810c6a32880b002f6374b59e0a7952518b -8650ac644f93bbcb88a6a0f49fee2663297fd4bc6fd47b6a89b9d8038d32370438ab3a4775ec9b58cb10aea8a95ef7b6 -95e5c2f2e84eed88c6980bbba5a1c0bb375d5a628bff006f7516d45bb7d723da676add4fdd45956f312e7bab0f052644 -b3278a3fa377ac93af7cfc9453f8cb594aae04269bbc99d2e0e45472ff4b6a2f97a26c4c57bf675b9d86f5e77a5d55d1 -b4bcbe6eb666a206e2ea2f877912c1d3b5bdbd08a989fc4490eb06013e1a69ad1ba08bcdac048bf29192312be399077b -a76d70b78c99fffcbf9bb9886eab40f1ea4f99a309710b660b64cbf86057cbcb644d243f6e341711bb7ef0fedf0435a7 -b2093c1ee945dca7ac76ad5aed08eae23af31dd5a77c903fd7b6f051f4ab84425d33a03c3d45bf2907bc93c02d1f3ad8 -904b1f7534e053a265b22d20be859912b9c9ccb303af9a8d6f1d8f6ccdc5c53eb4a45a1762b880d8444d9be0cd55e7f9 -8f664a965d65bc730c9ef1ec7467be984d4b8eb46bd9b0d64e38e48f94e6e55dda19aeac82cbcf4e1473440e64c4ca18 -8bcee65c4cc7a7799353d07b114c718a2aae0cd10a3f22b7eead5185d159dafd64852cb63924bf87627d176228878bce -8c78f2e3675096fef7ebaa898d2615cd50d39ca3d8f02b9bdfb07e67da648ae4be3da64838dffc5935fd72962c4b96c7 -8c40afd3701629421fec1df1aac4e849384ef2e80472c0e28d36cb1327acdf2826f99b357f3d7afdbc58a6347fc40b3c -a197813b1c65a8ea5754ef782522a57d63433ef752215ecda1e7da76b0412ee619f58d904abd2e07e0c097048b6ae1dd -a670542629e4333884ad7410f9ea3bd6f988df4a8f8a424ca74b9add2312586900cf9ae8bd50411f9146e82626b4af56 -a19875cc07ab84e569d98b8b67fb1dbbdfb59093c7b748fae008c8904a6fd931a63ca8d03ab5fea9bc8d263568125a9b -b57e7f68e4eb1bd04aafa917b1db1bdab759a02aa8a9cdb1cba34ba8852b5890f655645c9b4e15d5f19bf37e9f2ffe9f -8abe4e2a4f6462b6c64b3f10e45db2a53c2b0d3c5d5443d3f00a453e193df771eda635b098b6c8604ace3557514027af -8459e4fb378189b22b870a6ef20183deb816cefbf66eca1dc7e86d36a2e011537db893729f500dc154f14ce24633ba47 -930851df4bc7913c0d8c0f7bd3b071a83668987ed7c397d3d042fdc0d9765945a39a3bae83da9c88cb6b686ed8aeeb26 -8078c9e5cd05e1a8c932f8a1d835f61a248b6e7133fcbb3de406bf4ffc0e584f6f9f95062740ba6008d98348886cf76b -addff62bb29430983fe578e3709b0949cdc0d47a13a29bc3f50371a2cb5c822ce53e2448cfaa01bcb6e0aa850d5a380e -9433add687b5a1e12066721789b1db2edf9b6558c3bdc0f452ba33b1da67426abe326e9a34d207bfb1c491c18811bde1 -822beda3389963428cccc4a2918fa9a8a51cf0919640350293af70821967108cded5997adae86b33cb917780b097f1ca -a7a9f52bda45e4148ed56dd176df7bd672e9b5ed18888ccdb405f47920fdb0844355f8565cefb17010b38324edd8315f -b35c3a872e18e607b2555c51f9696a17fa18da1f924d503b163b4ec9fe22ed0c110925275cb6c93ce2d013e88f173d6a -adf34b002b2b26ab84fc1bf94e05bd8616a1d06664799ab149363c56a6e0c807fdc473327d25632416e952ea327fcd95 -ae4a6b9d22a4a3183fac29e2551e1124a8ce4a561a9a2afa9b23032b58d444e6155bb2b48f85c7b6d70393274e230db7 -a2ea3be4fc17e9b7ce3110284038d46a09e88a247b6971167a7878d9dcf36925d613c382b400cfa4f37a3ebea3699897 -8e5863786b641ce3140fbfe37124d7ad3925472e924f814ebfc45959aaf3f61dc554a597610b5defaecc85b59a99b50f -aefde3193d0f700d0f515ab2aaa43e2ef1d7831c4f7859f48e52693d57f97fa9e520090f3ed700e1c966f4b76048e57f -841a50f772956622798e5cd208dc7534d4e39eddee30d8ce133383d66e5f267e389254a0cdae01b770ecd0a9ca421929 -8fbc2bfd28238c7d47d4c03b1b910946c0d94274a199575e5b23242619b1de3497784e646a92aa03e3e24123ae4fcaba -926999579c8eec1cc47d7330112586bdca20b4149c8b2d066f527c8b9f609e61ce27feb69db67eea382649c6905efcf9 -b09f31f305efcc65589adf5d3690a76cf339efd67cd43a4e3ced7b839507466e4be72dd91f04e89e4bbef629d46e68c0 -b917361f6b95f759642638e0b1d2b3a29c3bdef0b94faa30de562e6078c7e2d25976159df3edbacbf43614635c2640b4 -8e7e8a1253bbda0e134d62bfe003a2669d471b47bd2b5cde0ff60d385d8e62279d54022f5ac12053b1e2d3aaa6910b4c -b69671a3c64e0a99d90b0ed108ce1912ff8ed983e4bddd75a370e9babde25ee1f5efb59ec707edddd46793207a8b1fe7 -910b2f4ebd37b7ae94108922b233d0920b4aba0bd94202c70f1314418b548d11d8e9caa91f2cd95aff51b9432d122b7f -82f645c90dfb52d195c1020346287c43a80233d3538954548604d09fbab7421241cde8593dbc4acc4986e0ea39a27dd9 -8fee895f0a140d88104ce442fed3966f58ff9d275e7373483f6b4249d64a25fb5374bbdc6bce6b5ab0270c2847066f83 -84f5bd7aab27b2509397aeb86510dd5ac0a53f2c8f73799bf720f2f87a52277f8d6b0f77f17bc80739c6a7119b7eb062 -9903ceced81099d7e146e661bcf01cbaccab5ba54366b85e2177f07e2d8621e19d9c9c3eee14b9266de6b3f9b6ea75ae -b9c16ea2a07afa32dd6c7c06df0dec39bca2067a9339e45475c98917f47e2320f6f235da353fd5e15b477de97ddc68dd -9820a9bbf8b826bec61ebf886de2c4f404c1ebdc8bab82ee1fea816d9de29127ce1852448ff717a3fe8bbfe9e92012e5 -817224d9359f5da6f2158c2c7bf9165501424f063e67ba9859a07ab72ee2ee62eb00ca6da821cfa19065c3282ca72c74 -94b95c465e6cb00da400558a3c60cfec4b79b27e602ca67cbc91aead08de4b6872d8ea096b0dc06dca4525c8992b8547 -a2b539a5bccd43fa347ba9c15f249b417997c6a38c63517ca38394976baa08e20be384a360969ff54e7e721db536b3e5 -96caf707e34f62811ee8d32ccf28d8d6ec579bc33e424d0473529af5315c456fd026aa910c1fed70c91982d51df7d3ca -8a77b73e890b644c6a142bdbac59b22d6a676f3b63ddafb52d914bb9d395b8bf5aedcbcc90429337df431ebd758a07a6 -8857830a7351025617a08bc44caec28d2fae07ebf5ffc9f01d979ce2a53839a670e61ae2783e138313929129790a51a1 -aa3e420321ed6f0aa326d28d1a10f13facec6f605b6218a6eb9cbc074801f3467bf013a456d1415a5536f12599efa3d3 -824aed0951957b00ea2f3d423e30328a3527bf6714cf9abbae84cf27e58e5c35452ba89ccc011de7c68c75d6e021d8f1 -a2e87cc06bf202e953fb1081933d8b4445527dde20e38ed1a4f440144fd8fa464a2b73e068b140562e9045e0f4bd3144 -ae3b8f06ad97d7ae3a5e5ca839efff3e4824dc238c0c03fc1a8d2fc8aa546cdfd165b784a31bb4dec7c77e9305b99a4b -b30c3e12395b1fb8b776f3ec9f87c70e35763a7b2ddc68f0f60a4982a84017f27c891a98561c830038deb033698ed7fc -874e507757cd1177d0dff0b0c62ce90130324442a33da3b2c8ee09dbca5d543e3ecfe707e9f1361e7c7db641c72794bb -b53012dd10b5e7460b57c092eaa06d6502720df9edbbe3e3f61a9998a272bf5baaac4a5a732ad4efe35d6fac6feca744 -85e6509d711515534d394e6cacbed6c81da710074d16ef3f4950bf2f578d662a494d835674f79c4d6315bced4defc5f0 -b6132b2a34b0905dcadc6119fd215419a7971fe545e52f48b768006944b4a9d7db1a74b149e2951ea48c083b752d0804 -989867da6415036d19b4bacc926ce6f4df7a556f50a1ba5f3c48eea9cefbb1c09da81481c8009331ee83f0859185e164 -960a6c36542876174d3fbc1505413e29f053ed87b8d38fef3af180491c7eff25200b45dd5fe5d4d8e63c7e8c9c00f4c8 -9040b59bd739d9cc2e8f6e894683429e4e876a8106238689ff4c22770ae5fdae1f32d962b30301fa0634ee163b524f35 -af3fcd0a45fe9e8fe256dc7eab242ef7f582dd832d147444483c62787ac820fafc6ca55d639a73f76bfa5e7f5462ab8f -b934c799d0736953a73d91e761767fdb78454355c4b15c680ce08accb57ccf941b13a1236980001f9e6195801cffd692 -8871e8e741157c2c326b22cf09551e78da3c1ec0fc0543136f581f1550f8bab03b0a7b80525c1e99812cdbf3a9698f96 -a8a977f51473a91d178ee8cfa45ffef8d6fd93ab1d6e428f96a3c79816d9c6a93cd70f94d4deda0125fd6816e30f3bea -a7688b3b0a4fc1dd16e8ba6dc758d3cfe1b7cf401c31739484c7fa253cce0967df1b290769bcefc9d23d3e0cb19e6218 -8ae84322662a57c6d729e6ff9d2737698cc2da2daeb1f39e506618750ed23442a6740955f299e4a15dda6db3e534d2c6 -a04a961cdccfa4b7ef83ced17ab221d6a043b2c718a0d6cc8e6f798507a31f10bf70361f70a049bc8058303fa7f96864 -b463e39732a7d9daec8a456fb58e54b30a6e160aa522a18b9a9e836488cce3342bcbb2e1deab0f5e6ec0a8796d77197d -b1434a11c6750f14018a2d3bcf94390e2948f4f187e93bb22070ca3e5393d339dc328cbfc3e48815f51929465ffe7d81 -84ff81d73f3828340623d7e3345553610aa22a5432217ef0ebd193cbf4a24234b190c65ca0873c22d10ea7b63bd1fbed -b6fe2723f0c47757932c2ddde7a4f8434f665612f7b87b4009c2635d56b6e16b200859a8ade49276de0ef27a2b6c970a -9742884ed7cd52b4a4a068a43d3faa02551a424136c85a9313f7cb58ea54c04aa83b0728fd741d1fe39621e931e88f8f -b7d2d65ea4d1ad07a5dee39e40d6c03a61264a56b1585b4d76fc5b2a68d80a93a42a0181d432528582bf08d144c2d6a9 -88c0f66bada89f8a43e5a6ead2915088173d106c76f724f4a97b0f6758aed6ae5c37c373c6b92cdd4aea8f6261f3a374 -81f9c43582cb42db3900747eb49ec94edb2284999a499d1527f03315fd330e5a509afa3bff659853570e9886aab5b28b -821f9d27d6beb416abf9aa5c79afb65a50ed276dbda6060103bc808bcd34426b82da5f23e38e88a55e172f5c294b4d40 -8ba307b9e7cb63a6c4f3851b321aebfdb6af34a5a4c3bd949ff7d96603e59b27ff4dc4970715d35f7758260ff942c9e9 -b142eb6c5f846de33227d0bda61d445a7c33c98f0a8365fe6ab4c1fabdc130849be597ef734305894a424ea715372d08 -a732730ae4512e86a741c8e4c87fee8a05ee840fec0e23b2e037d58dba8dde8d10a9bc5191d34d00598941becbbe467f -adce6f7c30fd221f6b10a0413cc76435c4bb36c2d60bca821e5c67409fe9dbb2f4c36ef85eb3d734695e4be4827e9fd3 -a74f00e0f9b23aff7b2527ce69852f8906dab9d6abe62ecd497498ab21e57542e12af9918d4fd610bb09e10b0929c510 -a593b6b0ef26448ce4eb3ab07e84238fc020b3cb10d542ff4b16d4e2be1bcde3797e45c9cf753b8dc3b0ffdb63984232 -aed3913afccf1aa1ac0eb4980eb8426d0baccebd836d44651fd72af00d09fac488a870223c42aca3ceb39752070405ae -b2c44c66a5ea7fde626548ba4cef8c8710191343d3dadfd3bb653ce715c0e03056a5303a581d47dde66e70ea5a2d2779 -8e5029b2ccf5128a12327b5103f7532db599846e422531869560ceaff392236434d87159f597937dbf4054f810c114f4 -82beed1a2c4477e5eb39fc5b0e773b30cfec77ef2b1bf17eadaf60eb35b6d0dd9d8cf06315c48d3546badb3f21cd0cca -90077bd6cc0e4be5fff08e5d07a5a158d36cebd1d1363125bc4fae0866ffe825b26f933d4ee5427ba5cd0c33c19a7b06 -a7ec0d8f079970e8e34f0ef3a53d3e0e45428ddcef9cc776ead5e542ef06f3c86981644f61c5a637e4faf001fb8c6b3e -ae6d4add6d1a6f90b22792bc9d40723ee6850c27d0b97eefafd5b7fd98e424aa97868b5287cc41b4fbd7023bca6a322c -831aa917533d077da07c01417feaa1408846363ba2b8d22c6116bb858a95801547dd88b7d7fa1d2e3f0a02bdeb2e103d -96511b860b07c8a5ed773f36d4aa9d02fb5e7882753bf56303595bcb57e37ccc60288887eb83bef08c657ec261a021a2 -921d2a3e7e9790f74068623de327443666b634c8443aba80120a45bba450df920b2374d96df1ce3fb1b06dd06f8cf6e3 -aa74451d51fe82b4581ead8e506ec6cd881010f7e7dd51fc388eb9a557db5d3c6721f81c151d08ebd9c2591689fbc13e -a972bfbcf4033d5742d08716c927c442119bdae336bf5dff914523b285ccf31953da2733759aacaa246a9af9f698342c -ad1fcd0cae0e76840194ce4150cb8a56ebed728ec9272035f52a799d480dfc85840a4d52d994a18b6edb31e79be6e8ad -a2c69fe1d36f235215432dad48d75887a44c99dfa0d78149acc74087da215a44bdb5f04e6eef88ff7eff80a5a7decc77 -a94ab2af2b6ee1bc6e0d4e689ca45380d9fbd3c5a65b9bd249d266a4d4c07bf5d5f7ef2ae6000623aee64027892bf8fe -881ec1fc514e926cdc66480ac59e139148ff8a2a7895a49f0dff45910c90cdda97b66441a25f357d6dd2471cddd99bb3 -884e6d3b894a914c8cef946a76d5a0c8351843b2bffa2d1e56c6b5b99c84104381dd1320c451d551c0b966f4086e60f9 -817c6c10ce2677b9fc5223500322e2b880583254d0bb0d247d728f8716f5e05c9ff39f135854342a1afecd9fbdcf7c46 -aaf4a9cb686a14619aa1fc1ac285dd3843ac3dd99f2b2331c711ec87b03491c02f49101046f3c5c538dc9f8dba2a0ac2 -97ecea5ce53ca720b5d845227ae61d70269a2f53540089305c86af35f0898bfd57356e74a8a5e083fa6e1ea70080bd31 -a22d811e1a20a75feac0157c418a4bfe745ccb5d29466ffa854dca03e395b6c3504a734341746b2846d76583a780b32e -940cbaa0d2b2db94ae96b6b9cf2deefbfd059e3e5745de9aec4a25f0991b9721e5cd37ef71c631575d1a0c280b01cd5b -ae33cb4951191258a11044682de861bf8d92d90ce751b354932dd9f3913f542b6a0f8a4dc228b3cd9244ac32c4582832 -a580df5e58c4274fe0f52ac2da1837e32f5c9db92be16c170187db4c358f43e5cfdda7c5911dcc79d77a5764e32325f5 -81798178cb9d8affa424f8d3be67576ba94d108a28ccc01d330c51d5a63ca45bb8ca63a2f569b5c5fe1303cecd2d777f -89975b91b94c25c9c3660e4af4047a8bacf964783010820dbc91ff8281509379cb3b24c25080d5a01174dd9a049118d5 -a7327fcb3710ed3273b048650bde40a32732ef40a7e58cf7f2f400979c177944c8bc54117ba6c80d5d4260801dddab79 -92b475dc8cb5be4b90c482f122a51bcb3b6c70593817e7e2459c28ea54a7845c50272af38119406eaadb9bcb993368d0 -9645173e9ecefc4f2eae8363504f7c0b81d85f8949a9f8a6c01f2d49e0a0764f4eacecf3e94016dd407fc14494fce9f9 -9215fd8983d7de6ae94d35e6698226fc1454977ae58d42d294be9aad13ac821562ad37d5e7ee5cdfe6e87031d45cd197 -810360a1c9b88a9e36f520ab5a1eb8bed93f52deefbe1312a69225c0a08edb10f87cc43b794aced9c74220cefcc57e7d -ad7e810efd61ed4684aeda9ed8bb02fb9ae4b4b63fda8217d37012b94ff1b91c0087043bfa4e376f961fff030c729f3b -8b07c95c6a06db8738d10bb03ec11b89375c08e77f0cab7e672ce70b2685667ca19c7e1c8b092821d31108ea18dfd4c7 -968825d025ded899ff7c57245250535c732836f7565eab1ae23ee7e513201d413c16e1ba3f5166e7ac6cf74de8ceef4f -908243370c5788200703ade8164943ad5f8c458219186432e74dbc9904a701ea307fd9b94976c866e6c58595fd891c4b -959969d16680bc535cdc6339e6186355d0d6c0d53d7bbfb411641b9bf4b770fd5f575beef5deec5c4fa4d192d455c350 -ad177f4f826a961adeac76da40e2d930748effff731756c797eddc4e5aa23c91f070fb69b19221748130b0961e68a6bb -82f8462bcc25448ef7e0739425378e9bb8a05e283ce54aae9dbebaf7a3469f57833c9171672ad43a79778366c72a5e37 -a28fb275b1845706c2814d9638573e9bc32ff552ebaed761fe96fdbce70395891ca41c400ae438369264e31a2713b15f -8a9c613996b5e51dadb587a787253d6081ea446bf5c71096980bf6bd3c4b69905062a8e8a3792de2d2ece3b177a71089 -8d5aefef9f60cb27c1db2c649221204dda48bb9bf8bf48f965741da051340e8e4cab88b9d15c69f3f84f4c854709f48a -93ebf2ca6ad85ab6deace6de1a458706285b31877b1b4d7dcb9d126b63047efaf8c06d580115ec9acee30c8a7212fa55 -b3ee46ce189956ca298057fa8223b7fd1128cf52f39159a58bca03c71dd25161ac13f1472301f72aef3e1993fe1ab269 -a24d7a8d066504fc3f5027ccb13120e2f22896860e02c45b5eba1dbd512d6a17c28f39155ea581619f9d33db43a96f92 -ae9ceacbfe12137db2c1a271e1b34b8f92e4816bad1b3b9b6feecc34df0f8b3b0f7ed0133acdf59c537d43d33fc8d429 -83967e69bf2b361f86361bd705dce0e1ad26df06da6c52b48176fe8dfcbeb03c462c1a4c9e649eff8c654b18c876fdef -9148e6b814a7d779c19c31e33a068e97b597de1f8100513db3c581190513edc4d544801ce3dd2cf6b19e0cd6daedd28a -94ccdafc84920d320ed22de1e754adea072935d3c5f8c2d1378ebe53d140ea29853f056fb3fb1e375846061a038cc9bc -afb43348498c38b0fa5f971b8cdd3a62c844f0eb52bc33daf2f67850af0880fce84ecfb96201b308d9e6168a0d443ae3 -86d5736520a83538d4cd058cc4b4e84213ed00ebd6e7af79ae787adc17a92ba5359e28ba6c91936d967b4b28d24c3070 -b5210c1ff212c5b1e9ef9126e08fe120a41e386bb12c22266f7538c6d69c7fd8774f11c02b81fd4e88f9137b020801fe -b78cfd19f94d24e529d0f52e18ce6185cb238edc6bd43086270fd51dd99f664f43dd4c7d2fe506762fbd859028e13fcf -a6e7220598c554abdcc3fdc587b988617b32c7bb0f82c06205467dbedb58276cc07cae317a190f19d19078773f4c2bbb -b88862809487ee430368dccd85a5d72fa4d163ca4aad15c78800e19c1a95be2192719801e315d86cff7795e0544a77e4 -87ecb13a03921296f8c42ceb252d04716f10e09c93962239fcaa0a7fef93f19ab3f2680bc406170108bc583e9ff2e721 -a810cd473832b6581c36ec4cb403f2849357ba2d0b54df98ef3004b8a530c078032922a81d40158f5fb0043d56477f6e -a247b45dd85ca7fbb718b328f30a03f03c84aef2c583fbdc9fcc9eb8b52b34529e8c8f535505c10598b1b4dac3d7c647 -96ee0b91313c68bac4aa9e065ce9e1d77e51ca4cff31d6a438718c58264dee87674bd97fc5c6b8008be709521e4fd008 -837567ad073e42266951a9a54750919280a2ac835a73c158407c3a2b1904cf0d17b7195a393c71a18ad029cbd9cf79ee -a6a469c44b67ebf02196213e7a63ad0423aab9a6e54acc6fcbdbb915bc043586993454dc3cd9e4be8f27d67c1050879b -8712d380a843b08b7b294f1f06e2f11f4ad6bcc655fdde86a4d8bc739c23916f6fad2b902fe47d6212f03607907e9f0e -920adfb644b534789943cdae1bdd6e42828dda1696a440af2f54e6b97f4f97470a1c6ea9fa6a2705d8f04911d055acd1 -a161c73adf584a0061e963b062f59d90faac65c9b3a936b837a10d817f02fcabfa748824607be45a183dd40f991fe83f -874f4ecd408c76e625ea50bc59c53c2d930ee25baf4b4eca2440bfbffb3b8bc294db579caa7c68629f4d9ec24187c1ba -8bff18087f112be7f4aa654e85c71fef70eee8ae480f61d0383ff6f5ab1a0508f966183bb3fc4d6f29cb7ca234aa50d3 -b03b46a3ca3bc743a173cbc008f92ab1aedd7466b35a6d1ca11e894b9482ea9dc75f8d6db2ddd1add99bfbe7657518b7 -8b4f3691403c3a8ad9e097f02d130769628feddfa8c2b3dfe8cff64e2bed7d6e5d192c1e2ba0ac348b8585e94acd5fa1 -a0d9ca4a212301f97591bf65d5ef2b2664766b427c9dd342e23cb468426e6a56be66b1cb41fea1889ac5d11a8e3c50a5 -8c93ed74188ca23b3df29e5396974b9cc135c91fdefdea6c0df694c8116410e93509559af55533a3776ac11b228d69b1 -82dd331fb3f9e344ebdeeb557769b86a2cc8cc38f6c298d7572a33aea87c261afa9dbd898989139b9fc16bc1e880a099 -a65faedf326bcfd8ef98a51410c78b021d39206704e8291cd1f09e096a66b9b0486be65ff185ca224c45918ac337ddeb -a188b37d363ac072a766fd5d6fa27df07363feff1342217b19e3c37385e42ffde55e4be8355aceaa2f267b6d66b4ac41 -810fa3ba3e96d843e3bafd3f2995727f223d3567c8ba77d684c993ba1773c66551eb5009897c51b3fe9b37196984f5ec -87631537541852da323b4353af45a164f68b304d24c01183bf271782e11687f3fcf528394e1566c2a26cb527b3148e64 -b721cb2b37b3c477a48e3cc0044167d51ff568a5fd2fb606e5aec7a267000f1ddc07d3db919926ae12761a8e017c767c -904dfad4ba2cc1f6e60d1b708438a70b1743b400164cd981f13c064b8328d5973987d4fb9cf894068f29d3deaf624dfb -a70491538893552c20939fae6be2f07bfa84d97e2534a6bbcc0f1729246b831103505e9f60e97a8fa7d2e6c1c2384579 -8726cf1b26b41f443ff7485adcfddc39ace2e62f4d65dd0bb927d933e262b66f1a9b367ded5fbdd6f3b0932553ac1735 -ae8a11cfdf7aa54c08f80cb645e3339187ab3886babe9fae5239ba507bb3dd1c0d161ca474a2df081dcd3d63e8fe445e -92328719e97ce60e56110f30a00ac5d9c7a2baaf5f8d22355d53c1c77941e3a1fec7d1405e6fbf8959665fe2ba7a8cad -8d9d6255b65798d0018a8cccb0b6343efd41dc14ff2058d3eed9451ceaad681e4a0fa6af67b0a04318aa628024e5553d -b70209090055459296006742d946a513f0cba6d83a05249ee8e7a51052b29c0ca9722dc4af5f9816a1b7938a5dac7f79 -aab7b766b9bf91786dfa801fcef6d575dc6f12b77ecc662eb4498f0312e54d0de9ea820e61508fc8aeee5ab5db529349 -a8104b462337748b7f086a135d0c3f87f8e51b7165ca6611264b8fb639d9a2f519926cb311fa2055b5fadf03da70c678 -b0d2460747d5d8b30fc6c6bd0a87cb343ddb05d90a51b465e8f67d499cfc5e3a9e365da05ae233bbee792cdf90ec67d5 -aa55f5bf3815266b4a149f85ed18e451c93de9163575e3ec75dd610381cc0805bb0a4d7c4af5b1f94d10231255436d2c -8d4c6a1944ff94426151909eb5b99cfd92167b967dabe2bf3aa66bb3c26c449c13097de881b2cfc1bf052862c1ef7b03 -8862296162451b9b6b77f03bf32e6df71325e8d7485cf3335d66fd48b74c2a8334c241db8263033724f26269ad95b395 -901aa96deb26cda5d9321190ae6624d357a41729d72ef1abfd71bebf6139af6d690798daba53b7bc5923462115ff748a -96c195ec4992728a1eb38cdde42d89a7bce150db43adbc9e61e279ea839e538deec71326b618dd39c50d589f78fc0614 -b6ff8b8aa0837b99a1a8b46fb37f20ad4aecc6a98381b1308697829a59b8442ffc748637a88cb30c9b1f0f28a926c4f6 -8d807e3dca9e7bef277db1d2cfb372408dd587364e8048b304eff00eacde2c723bfc84be9b98553f83cba5c7b3cba248 -8800c96adb0195c4fc5b24511450dee503c32bf47044f5e2e25bd6651f514d79a2dd9b01cd8c09f3c9d3859338490f57 -89fe366096097e38ec28dd1148887112efa5306cc0c3da09562aafa56f4eb000bf46ff79bf0bdd270cbde6bf0e1c8957 -af409a90c2776e1e7e3760b2042507b8709e943424606e31e791d42f17873a2710797f5baaab4cc4a19998ef648556b0 -8d761863c9b6edbd232d35ab853d944f5c950c2b643f84a1a1327ebb947290800710ff01dcfa26dc8e9828481240e8b1 -90b95e9be1e55c463ed857c4e0617d6dc3674e99b6aa62ed33c8e79d6dfcf7d122f4f4cc2ee3e7c5a49170cb617d2e2e -b3ff381efefabc4db38cc4727432e0301949ae4f16f8d1dea9b4f4de611cf5a36d84290a0bef160dac4e1955e516b3b0 -a8a84564b56a9003adcadb3565dc512239fc79572762cda7b5901a255bc82656bb9c01212ad33d6bef4fbbce18dacc87 -90a081890364b222eef54bf0075417f85e340d2fec8b7375995f598aeb33f26b44143ebf56fca7d8b4ebb36b5747b0eb -ade6ee49e1293224ddf2d8ab7f14bb5be6bc6284f60fd5b3a1e0cf147b73cff57cf19763b8a36c5083badc79c606b103 -b2fa99806dd2fa3de09320b615a2570c416c9bcdb052e592b0aead748bbe407ec9475a3d932ae48b71c2627eb81986a6 -91f3b7b73c8ccc9392542711c45fe6f236057e6efad587d661ad5cb4d6e88265f86b807bb1151736b1009ab74fd7acb4 -8800e2a46af96696dfbdcbf2ca2918b3dcf28ad970170d2d1783b52b8d945a9167d052beeb55f56c126da7ffa7059baa -9862267a1311c385956b977c9aa08548c28d758d7ba82d43dbc3d0a0fd1b7a221d39e8399997fea9014ac509ff510ac4 -b7d24f78886fd3e2d283e18d9ad5a25c1a904e7d9b9104bf47da469d74f34162e27e531380dbbe0a9d051e6ffd51d6e7 -b0f445f9d143e28b9df36b0f2c052da87ee2ca374d9d0fbe2eff66ca6fe5fe0d2c1951b428d58f7314b7e74e45d445ea -b63fc4083eabb8437dafeb6a904120691dcb53ce2938b820bb553da0e1eecd476f72495aacb72600cf9cad18698fd3db -b9ffd8108eaebd582d665f8690fe8bb207fd85185e6dd9f0b355a09bac1bbff26e0fdb172bc0498df025414e88fe2eda -967ed453e1f1a4c5b7b6834cc9f75c13f6889edc0cc91dc445727e9f408487bbf05c337103f61397a10011dfbe25d61d -98ceb673aff36e1987d5521a3984a07079c3c6155974bb8b413e8ae1ce84095fe4f7862fba7aefa14753eb26f2a5805f -85f01d28603a8fdf6ce6a50cb5c44f8a36b95b91302e3f4cd95c108ce8f4d212e73aec1b8d936520d9226802a2bd9136 -88118e9703200ca07910345fbb789e7a8f92bd80bbc79f0a9e040e8767d33df39f6eded403a9b636eabf9101e588482a -90833a51eef1b10ed74e8f9bbd6197e29c5292e469c854eed10b0da663e2bceb92539710b1858bbb21887bd538d28d89 -b513b905ec19191167c6193067b5cfdf5a3d3828375360df1c7e2ced5815437dfd37f0c4c8f009d7fb29ff3c8793f560 -b1b6d405d2d18f9554b8a358cc7e2d78a3b34269737d561992c8de83392ac9a2857be4bf15de5a6c74e0c9d0f31f393c -b828bd3e452b797323b798186607849f85d1fb20c616833c0619360dfd6b3e3aa000fd09dafe4b62d74abc41072ff1a9 -8efde67d0cca56bb2c464731879c9ac46a52e75bac702a63200a5e192b4f81c641f855ca6747752b84fe469cb7113b6c -b2762ba1c89ac3c9a983c242e4d1c2610ff0528585ed5c0dfc8a2c0253551142af9b59f43158e8915a1da7cc26b9df67 -8a3f1157fb820d1497ef6b25cd70b7e16bb8b961b0063ad340d82a79ee76eb2359ca9e15e6d42987ed7f154f5eeaa2da -a75e29f29d38f09c879f971c11beb5368affa084313474a5ecafa2896180b9e47ea1995c2733ec46f421e395a1d9cffe -8e8c3dd3e7196ef0b4996b531ec79e4a1f211db5d5635e48ceb80ff7568b2ff587e845f97ee703bb23a60945ad64314a -8e7f32f4a3e3c584af5e3d406924a0aa34024c42eca74ef6cc2a358fd3c9efaf25f1c03aa1e66bb94b023a2ee2a1cace -ab7dce05d59c10a84feb524fcb62478906b3fa045135b23afbede3bb32e0c678d8ebe59feabccb5c8f3550ea76cae44b -b38bb4b44d827f6fd3bd34e31f9186c59e312dbfadd4a7a88e588da10146a78b1f8716c91ad8b806beb8da65cab80c4c -9490ce9442bbbd05438c7f5c4dea789f74a7e92b1886a730544b55ba377840740a3ae4f2f146ee73f47c9278b0e233bc -83c003fab22a7178eed1a668e0f65d4fe38ef3900044e9ec63070c23f2827d36a1e73e5c2b883ec6a2afe2450171b3b3 -9982f02405978ddc4fca9063ebbdb152f524c84e79398955e66fe51bc7c1660ec1afc3a86ec49f58d7b7dde03505731c -ab337bd83ccdd2322088ffa8d005f450ced6b35790f37ab4534313315ee84312adc25e99cce052863a8bedee991729ed -8312ce4bec94366d88f16127a17419ef64285cd5bf9e5eda010319b48085966ed1252ed2f5a9fd3e0259b91bb65f1827 -a60d5a6327c4041b0c00a1aa2f0af056520f83c9ce9d9ccd03a0bd4d9e6a1511f26a422ea86bd858a1f77438adf07e6c -b84a0a0b030bdad83cf5202aa9afe58c9820e52483ab41f835f8c582c129ee3f34aa096d11c1cd922eda02ea1196a882 -8077d105317f4a8a8f1aadeb05e0722bb55f11abcb490c36c0904401107eb3372875b0ac233144829e734f0c538d8c1d -9202503bd29a6ec198823a1e4e098f9cfe359ed51eb5174d1ca41368821bfeebcbd49debfd02952c41359d1c7c06d2b1 -abc28c155e09365cb77ffead8dc8f602335ef93b2f44e4ef767ce8fc8ef9dd707400f3a722e92776c2e0b40192c06354 -b0f6d1442533ca45c9399e0a63a11f85ff288d242cea6cb3b68c02e77bd7d158047cae2d25b3bcd9606f8f66d9b32855 -b01c3d56a0db84dc94575f4b6ee2de4beca3230e86bed63e2066beb22768b0a8efb08ebaf8ac3dedb5fe46708b084807 -8c8634b0432159f66feaabb165842d1c8ac378f79565b1b90c381aa8450eb4231c3dad11ec9317b9fc2b155c3a771e32 -8e67f623d69ecd430c9ee0888520b6038f13a2b6140525b056dc0951f0cfed2822e62cf11d952a483107c5c5acac4826 -9590bb1cba816dd6acd5ac5fba5142c0a19d53573e422c74005e0bcf34993a8138c83124cad35a3df65879dba6134edd -801cd96cde0749021a253027118d3ea135f3fcdbe895db08a6c145641f95ebd368dd6a1568d995e1d0084146aebe224a -848b5d196427f6fc1f762ee3d36e832b64a76ec1033cfedc8b985dea93932a7892b8ef1035c653fb9dcd9ab2d9a44ac8 -a1017eb83d5c4e2477e7bd2241b2b98c4951a3b391081cae7d75965cadc1acaec755cf350f1f3d29741b0828e36fedea -8d6d2785e30f3c29aad17bd677914a752f831e96d46caf54446d967cb2432be2c849e26f0d193a60bee161ea5c6fe90a -935c0ba4290d4595428e034b5c8001cbd400040d89ab00861108e8f8f4af4258e41f34a7e6b93b04bc253d3b9ffc13bf -aac02257146246998477921cef2e9892228590d323b839f3e64ea893b991b463bc2f47e1e5092ddb47e70b2f5bce7622 -b921fde9412970a5d4c9a908ae8ce65861d06c7679af577cf0ad0d5344c421166986bee471fd6a6cecb7d591f06ec985 -8ef4c37487b139d6756003060600bb6ebac7ea810b9c4364fc978e842f13ac196d1264fbe5af60d76ff6d9203d8e7d3f -94b65e14022b5cf6a9b95f94be5ace2711957c96f4211c3f7bb36206bd39cfbd0ea82186cab5ad0577a23214a5c86e9e -a31c166d2a2ca1d5a75a5920fef7532681f62191a50d8555fdaa63ba4581c3391cc94a536fc09aac89f64eafceec3f90 -919a8cc128de01e9e10f5d83b08b52293fdd41bde2b5ae070f3d95842d4a16e5331cf2f3d61c765570c8022403610fa4 -b23d6f8331eef100152d60483cfa14232a85ee712c8538c9b6417a5a7c5b353c2ac401390c6c215cb101f5cee6b5f43e -ab357160c08a18319510a571eafff154298ce1020de8e1dc6138a09fcb0fcbcdd8359f7e9386bda00b7b9cdea745ffdc -ab55079aea34afa5c0bd1124b9cdfe01f325b402fdfa017301bf87812eaa811ea5798c3aaf818074d420d1c782b10ada -ade616010dc5009e7fc4f8d8b00dc716686a5fa0a7816ad9e503e15839d3b909b69d9dd929b7575376434ffec0d2bea8 -863997b97ed46898a8a014599508fa3079f414b1f4a0c4fdc6d74ae8b444afa350f327f8bfc2a85d27f9e2d049c50135 -8d602ff596334efd4925549ed95f2aa762b0629189f0df6dbb162581657cf3ea6863cd2287b4d9c8ad52813d87fcd235 -b70f68c596dcdeed92ad5c6c348578b26862a51eb5364237b1221e840c47a8702f0fbc56eb520a22c0eed99795d3903e -9628088f8e0853cefadee305a8bf47fa990c50fa96a82511bbe6e5dc81ef4b794e7918a109070f92fc8384d77ace226f -97e26a46e068b605ce96007197ecd943c9a23881862f4797a12a3e96ba2b8d07806ad9e2a0646796b1889c6b7d75188c -b1edf467c068cc163e2d6413cc22b16751e78b3312fe47b7ea82b08a1206d64415b2c8f2a677fa89171e82cc49797150 -a44d15ef18745b251429703e3cab188420e2d974de07251501799b016617f9630643fcd06f895634d8ecdd579e1bf000 -abd126df3917ba48c618ee4dbdf87df506193462f792874439043fa1b844466f6f4e0ff2e42516e63b5b23c0892b2695 -a2a67f57c4aa3c2aa1eeddbfd5009a89c26c2ce8fa3c96a64626aba19514beb125f27df8559506f737de3eae0f1fc18f -a633e0132197e6038197304b296ab171f1d8e0d0f34dcf66fe9146ac385b0239232a8470b9205a4802ab432389f4836d -a914b3a28509a906c3821463b936455d58ff45dcbe158922f9efb2037f2eb0ce8e92532d29b5d5a3fcd0d23fa773f272 -a0e1412ce4505daf1a2e59ce4f0fc0e0023e335b50d2b204422f57cd65744cc7a8ed35d5ef131a42c70b27111d3115b7 -a2339e2f2b6072e88816224fdd612c04d64e7967a492b9f8829db15367f565745325d361fd0607b0def1be384d010d9e -a7309fc41203cb99382e8193a1dcf03ac190a7ce04835304eb7e341d78634e83ea47cb15b885601956736d04cdfcaa01 -81f3ccd6c7f5b39e4e873365f8c37b214e8ab122d04a606fbb7339dc3298c427e922ec7418002561d4106505b5c399ee -92c121cf914ca549130e352eb297872a63200e99b148d88fbc9506ad882bec9d0203d65f280fb5b0ba92e336b7f932e8 -a4b330cf3f064f5b131578626ad7043ce2a433b6f175feb0b52d36134a454ca219373fd30d5e5796410e005b69082e47 -86fe5774112403ad83f9c55d58317eeb17ad8e1176d9f2f69c2afb7ed83bc718ed4e0245ceab4b377f5f062dcd4c00e7 -809d152a7e2654c7fd175b57f7928365a521be92e1ed06c05188a95864ddb25f7cab4c71db7d61bbf4cae46f3a1d96ce -b82d663e55c2a5ada7e169e9b1a87bc1c0177baf1ec1c96559b4cb1c5214ce1ddf2ab8d345014cab6402f3774235cf5a -86580af86df1bd2c385adb8f9a079e925981b7184db66fc5fe5b14cddb82e7d836b06eaeef14924ac529487b23dae111 -b5f5f4c5c94944ecc804df6ab8687d64e27d988cbfeae1ba7394e0f6adbf778c5881ead7cd8082dd7d68542b9bb4ecd5 -a6016916146c2685c46e8fdd24186394e2d5496e77e08c0c6a709d4cd7dfa97f1efcef94922b89196819076a91ad37b5 -b778e7367ded3b6eab53d5fc257f7a87e8faf74a593900f2f517220add2125be3f6142022660d8181df8d164ad9441ce -8581b2d36abe6f553add4d24be761bec1b8efaa2929519114346615380b3c55b59e6ad86990e312f7e234d0203bdf59b -9917e74fd45c3f71a829ff5498a7f6b5599b48c098dda2339bf04352bfc7f368ccf1a407f5835901240e76452ae807d7 -afd196ce6f9335069138fd2e3d133134da253978b4ce373152c0f26affe77a336505787594022e610f8feb722f7cc1fb -a477491a1562e329764645e8f24d8e228e5ef28c9f74c6b5b3abc4b6a562c15ffb0f680d372aed04d9e1bf944dece7be -9767440d58c57d3077319d3a330e5322b9ba16981ec74a5a14d53462eab59ae7fd2b14025bfc63b268862094acb444e6 -80986d921be3513ef69264423f351a61cb48390c1be8673aee0f089076086aaebea7ebe268fd0aa7182695606116f679 -a9554c5c921c07b450ee04e34ec58e054ac1541b26ce2ce5a393367a97348ba0089f53db6660ad76b60278b66fd12e3e -95097e7d2999b3e84bf052c775581cf361325325f4a50192521d8f4693c830bed667d88f482dc1e3f833aa2bd22d2cbf -9014c91d0f85aefd28436b5228c12f6353c055a9326c7efbf5e071e089e2ee7c070fcbc84c5fafc336cbb8fa6fec1ca1 -90f57ba36ee1066b55d37384942d8b57ae00f3cf9a3c1d6a3dfee1d1af42d4b5fa9baeb0cd7e46687d1d6d090ddb931d -8e4b1db12fd760a17214c9e47f1fce6e43c0dbb4589a827a13ac61aaae93759345697bb438a00edab92e0b7b62414683 -8022a959a513cdc0e9c705e0fc04eafd05ff37c867ae0f31f6d01cddd5df86138a426cab2ff0ac8ff03a62e20f7e8f51 -914e9a38829834c7360443b8ed86137e6f936389488eccf05b4b4db7c9425611705076ecb3f27105d24b85c852be7511 -957fb10783e2bd0db1ba66b18e794df710bc3b2b05776be146fa5863c15b1ebdd39747b1a95d9564e1772cdfc4f37b8a -b6307028444daed8ed785ac9d0de76bc3fe23ff2cc7e48102553613bbfb5afe0ebe45e4212a27021c8eb870721e62a1f -8f76143597777d940b15a01b39c5e1b045464d146d9a30a6abe8b5d3907250e6c7f858ff2308f8591e8b0a7b3f3c568a -96163138ac0ce5fd00ae9a289648fd9300a0ca0f63a88481d703ecd281c06a52a3b5178e849e331f9c85ca4ba398f4cc -a63ef47c3e18245b0482596a09f488a716df3cbd0f9e5cfabed0d742843e65db8961c556f45f49762f3a6ac8b627b3ef -8cb595466552e7c4d42909f232d4063e0a663a8ef6f6c9b7ce3a0542b2459cde04e0e54c7623d404acb5b82775ac04f6 -b47fe69960eb45f399368807cff16d941a5a4ebad1f5ec46e3dc8a2e4d598a7e6114d8f0ca791e9720fd786070524e2b -89eb5ff83eea9df490e5beca1a1fbbbbcf7184a37e2c8c91ede7a1e654c81e8cd41eceece4042ea7918a4f4646b67fd6 -a84f5d155ed08b9054eecb15f689ba81e44589e6e7207a99790c598962837ca99ec12344105b16641ca91165672f7153 -a6cc8f25c2d5b2d2f220ec359e6a37a52b95fa6af6e173c65e7cd55299eff4aa9e6d9e6f2769e6459313f1f2aecb0fab -afcde944411f017a9f7979755294981e941cc41f03df5e10522ef7c7505e5f1babdd67b3bf5258e8623150062eb41d9b -8fab39f39c0f40182fcd996ade2012643fe7731808afbc53f9b26900b4d4d1f0f5312d9d40b3df8baa4739970a49c732 -ae193af9726da0ebe7df1f9ee1c4846a5b2a7621403baf8e66c66b60f523e719c30c6b4f897bb14b27d3ff3da8392eeb -8ac5adb82d852eba255764029f42e6da92dcdd0e224d387d1ef94174038db9709ac558d90d7e7c57ad4ce7f89bbfc38c -a2066b3458fdf678ee487a55dd5bfb74fde03b54620cb0e25412a89ee28ad0d685e309a51e3e4694be2fa6f1593a344c -88d031745dd0ae07d61a15b594be5d4b2e2a29e715d081649ad63605e3404b0c3a5353f0fd9fad9c05c18e93ce674fa1 -8283cfb0ef743a043f2b77ecaeba3005e2ca50435585b5dd24777ee6bce12332f85e21b446b536da38508807f0f07563 -b376de22d5f6b0af0b59f7d9764561f4244cf8ffe22890ecd3dcf2ff1832130c9b821e068c9d8773136f4796721e5963 -ae3afc50c764f406353965363840bf28ee85e7064eb9d5f0bb3c31c64ab10f48c853e942ee2c9b51bae59651eaa08c2f -948b204d103917461a01a6c57a88f2d66b476eae5b00be20ec8c747650e864bc8a83aee0aff59cb7584b7a3387e0ee48 -81ab098a082b07f896c5ffd1e4446cb7fb44804cbbf38d125208b233fc82f8ec9a6a8d8dd1c9a1162dc28ffeec0dde50 -a149c6f1312821ced2969268789a3151bdda213451760b397139a028da609c4134ac083169feb0ee423a0acafd10eceb -b0ac9e27a5dadaf523010f730b28f0ebac01f460d3bbbe277dc9d44218abb5686f4fac89ae462682fef9edbba663520a -8d0e0073cca273daaaa61b6fc54bfe5a009bc3e20ae820f6c93ba77b19eca517d457e948a2de5e77678e4241807157cb -ad61d3a2edf7c7533a04964b97499503fd8374ca64286dba80465e68fe932e96749b476f458c6fc57cb1a7ca85764d11 -90eb5e121ae46bc01a30881eaa556f46bd8457a4e80787cf634aab355082de34ac57d7f497446468225f7721e68e2a47 -8cdac557de7c42d1f3780e33dec1b81889f6352279be81c65566cdd4952d4c15d79e656cbd46035ab090b385e90245ef -82b67e61b88b84f4f4d4f65df37b3e3dcf8ec91ea1b5c008fdccd52da643adbe6468a1cfdb999e87d195afe2883a3b46 -8503b467e8f5d6048a4a9b78496c58493a462852cab54a70594ae3fd064cfd0deb4b8f336a262155d9fedcaa67d2f6fd -8db56c5ac763a57b6ce6832930c57117058e3e5a81532b7d19346346205e2ec614eb1a2ee836ef621de50a7bc9b7f040 -ad344699198f3c6e8c0a3470f92aaffc805b76266734414c298e10b5b3797ca53578de7ccb2f458f5e0448203f55282b -80602032c43c9e2a09154cc88b83238343b7a139f566d64cb482d87436b288a98f1ea244fd3bff8da3c398686a900c14 -a6385bd50ecd548cfb37174cdbb89e10025b5cadaf3cff164c95d7aef5a33e3d6a9bf0c681b9e11db9ef54ebeee2a0c1 -abf2d95f4aa34b0581eb9257a0cc8462b2213941a5deb8ba014283293e8b36613951b61261cc67bbd09526a54cbbff76 -a3d5de52f48df72c289ff713e445991f142390798cd42bd9d9dbefaee4af4f5faf09042d126b975cf6b98711c3072553 -8e627302ff3d686cff8872a1b7c2a57b35f45bf2fc9aa42b049d8b4d6996a662b8e7cbac6597f0cb79b0cc4e29fbf133 -8510702e101b39a1efbf4e504e6123540c34b5689645e70d0bac1ecc1baf47d86c05cef6c4317a4e99b4edaeb53f2d00 -aa173f0ecbcc6088f878f8726d317748c81ebf501bba461f163b55d66099b191ec7c55f7702f351a9c8eb42cfa3280e2 -b560a697eafab695bcef1416648a0a664a71e311ecbe5823ae903bd0ed2057b9d7574b9a86d3fe22aa3e6ddce38ea513 -8df6304a3d9cf40100f3f687575419c998cd77e5cc27d579cf4f8e98642de3609af384a0337d145dd7c5635172d26a71 -8105c7f3e4d30a29151849673853b457c1885c186c132d0a98e63096c3774bc9deb956cf957367e633d0913680bda307 -95373fc22c0917c3c2044ac688c4f29a63ed858a45c0d6d2d0fe97afd6f532dcb648670594290c1c89010ecc69259bef -8c2fae9bcadab341f49b55230310df93cac46be42d4caa0d42e45104148a91e527af1b4209c0d972448162aed28fab64 -b05a77baab70683f76209626eaefdda2d36a0b66c780a20142d23c55bd479ddd4ad95b24579384b6cf62c8eb4c92d021 -8e6bc6a7ea2755b4aaa19c1c1dee93811fcde514f03485fdc3252f0ab7f032c315614f6336e57cea25dcfb8fb6084eeb -b656a27d06aade55eadae2ad2a1059198918ea6cc3fd22c0ed881294d34d5ac7b5e4700cc24350e27d76646263b223aa -a296469f24f6f56da92d713afcd4dd606e7da1f79dc4e434593c53695847eefc81c7c446486c4b3b8c8d00c90c166f14 -87a326f57713ac2c9dffeb3af44b9f3c613a8f952676fc46343299122b47ee0f8d792abaa4b5db6451ced5dd153aabd0 -b689e554ba9293b9c1f6344a3c8fcb6951d9f9eac4a2e2df13de021aade7c186be27500e81388e5b8bcab4c80f220a31 -87ae0aa0aa48eac53d1ca5a7b93917de12db9e40ceabf8fdb40884ae771cfdf095411deef7c9f821af0b7070454a2608 -a71ffa7eae8ace94e6c3581d4cb2ad25d48cbd27edc9ec45baa2c8eb932a4773c3272b2ffaf077b40f76942a1f3af7f2 -94c218c91a9b73da6b7a495b3728f3028df8ad9133312fc0c03e8c5253b7ccb83ed14688fd4602e2fd41f29a0bc698bd -ae1e77b90ca33728af07a4c03fb2ef71cd92e2618e7bf8ed4d785ce90097fc4866c29999eb84a6cf1819d75285a03af2 -b7a5945b277dab9993cf761e838b0ac6eaa903d7111fca79f9fde3d4285af7a89bf6634a71909d095d7619d913972c9c -8c43b37be02f39b22029b20aca31bff661abce4471dca88aa3bddefd9c92304a088b2dfc8c4795acc301ca3160656af2 -b32e5d0fba024554bd5fe8a793ebe8003335ddd7f585876df2048dcf759a01285fecb53daae4950ba57f3a282a4d8495 -85ea7fd5e10c7b659df5289b2978b2c89e244f269e061b9a15fcab7983fc1962b63546e82d5731c97ec74b6804be63ef -96b89f39181141a7e32986ac02d7586088c5a9662cec39843f397f3178714d02f929af70630c12cbaba0268f8ba2d4fa -929ab1a2a009b1eb37a2817c89696a06426529ebe3f306c586ab717bd34c35a53eca2d7ddcdef36117872db660024af9 -a696dccf439e9ca41511e16bf3042d7ec0e2f86c099e4fc8879d778a5ea79e33aa7ce96b23dc4332b7ba26859d8e674d -a8fe69a678f9a194b8670a41e941f0460f6e2dbc60470ab4d6ae2679cc9c6ce2c3a39df2303bee486dbfde6844e6b31a -95f58f5c82de2f2a927ca99bf63c9fc02e9030c7e46d0bf6b67fe83a448d0ae1c99541b59caf0e1ccab8326231af09a5 -a57badb2c56ca2c45953bd569caf22968f76ed46b9bac389163d6fe22a715c83d5e94ae8759b0e6e8c2f27bff7748f3f -868726fd49963b24acb5333364dffea147e98f33aa19c7919dc9aca0fd26661cfaded74ede7418a5fadbe7f5ae67b67b -a8d8550dcc64d9f1dd7bcdab236c4122f2b65ea404bb483256d712c7518f08bb028ff8801f1da6aed6cbfc5c7062e33b -97e25a87dae23155809476232178538d4bc05d4ff0882916eb29ae515f2a62bfce73083466cc0010ca956aca200aeacc -b4ea26be3f4bd04aa82d7c4b0913b97bcdf5e88b76c57eb1a336cbd0a3eb29de751e1bc47c0e8258adec3f17426d0c71 -99ee555a4d9b3cf2eb420b2af8e3bc99046880536116d0ce7193464ac40685ef14e0e3c442f604e32f8338cb0ef92558 -8c64efa1da63cd08f319103c5c7a761221080e74227bbc58b8fb35d08aa42078810d7af3e60446cbaff160c319535648 -8d9fd88040076c28420e3395cbdfea402e4077a3808a97b7939d49ecbcf1418fe50a0460e1c1b22ac3f6e7771d65169a -ae3c19882d7a9875d439265a0c7003c8d410367627d21575a864b9cb4918de7dbdb58a364af40c5e045f3df40f95d337 -b4f7bfacab7b2cafe393f1322d6dcc6f21ffe69cd31edc8db18c06f1a2b512c27bd0618091fd207ba8df1808e9d45914 -94f134acd0007c623fb7934bcb65ef853313eb283a889a3ffa79a37a5c8f3665f3d5b4876bc66223610c21dc9b919d37 -aa15f74051171daacdc1f1093d3f8e2d13da2833624b80a934afec86fc02208b8f55d24b7d66076444e7633f46375c6a -a32d6bb47ef9c836d9d2371807bafbbbbb1ae719530c19d6013f1d1f813c49a60e4fa51d83693586cba3a840b23c0404 -b61b3599145ea8680011aa2366dc511a358b7d67672d5b0c5be6db03b0efb8ca5a8294cf220ea7409621f1664e00e631 -859cafc3ee90b7ececa1ed8ef2b2fc17567126ff10ca712d5ffdd16aa411a5a7d8d32c9cab1fbf63e87dce1c6e2f5f53 -a2fef1b0b2874387010e9ae425f3a9676d01a095d017493648bcdf3b31304b087ccddb5cf76abc4e1548b88919663b6b -939e18c73befc1ba2932a65ede34c70e4b91e74cc2129d57ace43ed2b3af2a9cc22a40fbf50d79a63681b6d98852866d -b3b4259d37b1b14aee5b676c9a0dd2d7f679ab95c120cb5f09f9fbf10b0a920cb613655ddb7b9e2ba5af4a221f31303c -997255fe51aaca6e5a9cb3359bcbf25b2bb9e30649bbd53a8a7c556df07e441c4e27328b38934f09c09d9500b5fabf66 -abb91be2a2d860fd662ed4f1c6edeefd4da8dc10e79251cf87f06029906e7f0be9b486462718f0525d5e049472692cb7 -b2398e593bf340a15f7801e1d1fbda69d93f2a32a889ec7c6ae5e8a37567ac3e5227213c1392ee86cfb3b56ec2787839 -8ddf10ccdd72922bed36829a36073a460c2118fc7a56ff9c1ac72581c799b15c762cb56cb78e3d118bb9f6a7e56cb25e -93e6bc0a4708d16387cacd44cf59363b994dc67d7ada7b6d6dbd831c606d975247541b42b2a309f814c1bfe205681fc6 -b93fc35c05998cffda2978e12e75812122831523041f10d52f810d34ff71944979054b04de0117e81ddf5b0b4b3e13c0 -92221631c44d60d68c6bc7b287509f37ee44cbe5fdb6935cee36b58b17c7325098f98f7910d2c3ca5dc885ad1d6dabc7 -a230124424a57fad3b1671f404a94d7c05f4c67b7a8fbacfccea28887b78d7c1ed40b92a58348e4d61328891cd2f6cee -a6a230edb8518a0f49d7231bc3e0bceb5c2ac427f045819f8584ba6f3ae3d63ed107a9a62aad543d7e1fcf1f20605706 -845be1fe94223c7f1f97d74c49d682472585d8f772762baad8a9d341d9c3015534cc83d102113c51a9dea2ab10d8d27b -b44262515e34f2db597c8128c7614d33858740310a49cdbdf9c8677c5343884b42c1292759f55b8b4abc4c86e4728033 -805592e4a3cd07c1844bc23783408310accfdb769cca882ad4d07d608e590a288b7370c2cb327f5336e72b7083a0e30f -95153e8b1140df34ee864f4ca601cb873cdd3efa634af0c4093fbaede36f51b55571ab271e6a133020cd34db8411241f -82878c1285cfa5ea1d32175c9401f3cc99f6bb224d622d3fd98cc7b0a27372f13f7ab463ce3a33ec96f9be38dbe2dfe3 -b7588748f55783077c27fc47d33e20c5c0f5a53fc0ac10194c003aa09b9f055d08ec971effa4b7f760553997a56967b3 -b36b4de6d1883b6951f59cfae381581f9c6352fcfcf1524fccdab1571a20f80441d9152dc6b48bcbbf00371337ca0bd5 -89c5523f2574e1c340a955cbed9c2f7b5fbceb260cb1133160dabb7d41c2f613ec3f6e74bbfab3c4a0a6f0626dbe068f -a52f58cc39f968a9813b1a8ddc4e83f4219e4dd82c7aa1dd083bea7edf967151d635aa9597457f879771759b876774e4 -8300a67c2e2e123f89704abfde095463045dbd97e20d4c1157bab35e9e1d3d18f1f4aaba9cbe6aa2d544e92578eaa1b6 -ac6a7f2918768eb6a43df9d3a8a04f8f72ee52f2e91c064c1c7d75cad1a3e83e5aba9fe55bb94f818099ac91ccf2e961 -8d64a2b0991cf164e29835c8ddef6069993a71ec2a7de8157bbfa2e00f6367be646ed74cbaf524f0e9fe13fb09fa15fd -8b2ffe5a545f9f680b49d0a9797a4a11700a2e2e348c34a7a985fc278f0f12def6e06710f40f9d48e4b7fbb71e072229 -8ab8f71cd337fa19178924e961958653abf7a598e3f022138b55c228440a2bac4176cea3aea393549c03cd38a13eb3fc -8419d28318c19ea4a179b7abb43669fe96347426ef3ac06b158d79c0acf777a09e8e770c2fb10e14b3a0421705990b23 -8bacdac310e1e49660359d0a7a17fe3d334eb820e61ae25e84cb52f863a2f74cbe89c2e9fc3283745d93a99b79132354 -b57ace3fa2b9f6b2db60c0d861ace7d7e657c5d35d992588aeed588c6ce3a80b6f0d49f8a26607f0b17167ab21b675e4 -83e265cde477f2ecc164f49ddc7fb255bb05ff6adc347408353b7336dc3a14fdedc86d5a7fb23f36b8423248a7a67ed1 -a60ada971f9f2d79d436de5d3d045f5ab05308cae3098acaf5521115134b2a40d664828bb89895840db7f7fb499edbc5 -a63eea12efd89b62d3952bf0542a73890b104dd1d7ff360d4755ebfa148fd62de668edac9eeb20507967ea37fb220202 -a0275767a270289adc991cc4571eff205b58ad6d3e93778ddbf95b75146d82517e8921bd0d0564e5b75fa0ccdab8e624 -b9b03fd3bf07201ba3a039176a965d736b4ef7912dd9e9bf69fe1b57c330a6aa170e5521fe8be62505f3af81b41d7806 -a95f640e26fb1106ced1729d6053e41a16e4896acac54992279ff873e5a969aad1dcfa10311e28b8f409ac1dab7f03bb -b144778921742418053cb3c70516c63162c187f00db2062193bb2c14031075dbe055d020cde761b26e8c58d0ea6df2c1 -8432fbb799e0435ef428d4fefc309a05dd589bce74d7a87faf659823e8c9ed51d3e42603d878e80f439a38be4321c2fa -b08ddef14e42d4fd5d8bf39feb7485848f0060d43b51ed5bdda39c05fe154fb111d29719ee61a23c392141358c0cfcff -8ae3c5329a5e025b86b5370e06f5e61177df4bda075856fade20a17bfef79c92f54ed495f310130021ba94fb7c33632b -92b6d3c9444100b4d7391febfc1dddaa224651677c3695c47a289a40d7a96d200b83b64e6d9df51f534564f272a2c6c6 -b432bc2a3f93d28b5e506d68527f1efeb2e2570f6be0794576e2a6ef9138926fdad8dd2eabfa979b79ab7266370e86bc -8bc315eacedbcfc462ece66a29662ca3dcd451f83de5c7626ef8712c196208fb3d8a0faf80b2e80384f0dd9772f61a23 -a72375b797283f0f4266dec188678e2b2c060dfed5880fc6bb0c996b06e91a5343ea2b695adaab0a6fd183b040b46b56 -a43445036fbaa414621918d6a897d3692fdae7b2961d87e2a03741360e45ebb19fcb1703d23f1e15bb1e2babcafc56ac -b9636b2ffe305e63a1a84bd44fb402442b1799bd5272638287aa87ca548649b23ce8ce7f67be077caed6aa2dbc454b78 -99a30bf0921d854c282b83d438a79f615424f28c2f99d26a05201c93d10378ab2cd94a792b571ddae5d4e0c0013f4006 -8648e3c2f93d70b392443be116b48a863e4b75991bab5db656a4ef3c1e7f645e8d536771dfe4e8d1ceda3be8d32978b0 -ab50dc9e6924c1d2e9d2e335b2d679fc7d1a7632e84964d3bac0c9fe57e85aa5906ec2e7b0399d98ddd022e9b19b5904 -ab729328d98d295f8f3272afaf5d8345ff54d58ff9884da14f17ecbdb7371857fdf2f3ef58080054e9874cc919b46224 -83fa5da7592bd451cad3ad7702b4006332b3aae23beab4c4cb887fa6348317d234bf62a359e665b28818e5410c278a09 -8bdbff566ae9d368f114858ef1f009439b3e9f4649f73efa946e678d6c781d52c69af195df0a68170f5f191b2eac286b -91245e59b4425fd4edb2a61d0d47c1ccc83d3ced8180de34887b9655b5dcda033d48cde0bdc3b7de846d246c053a02e8 -a2cb00721e68f1cad8933947456f07144dc69653f96ceed845bd577d599521ba99cdc02421118971d56d7603ed118cbf -af8cd66d303e808b22ec57860dd909ca64c27ec2c60e26ffecfdc1179d8762ffd2739d87b43959496e9fee4108df71df -9954136812dffcd5d3f167a500e7ab339c15cfc9b3398d83f64b0daa3dd5b9a851204f424a3493b4e326d3de81e50a62 -93252254d12511955f1aa464883ad0da793f84d900fea83e1df8bca0f2f4cf5b5f9acbaec06a24160d33f908ab5fea38 -997cb55c26996586ba436a95566bd535e9c22452ca5d2a0ded2bd175376557fa895f9f4def4519241ff386a063f2e526 -a12c78ad451e0ac911260ade2927a768b50cb4125343025d43474e7f465cdc446e9f52a84609c5e7e87ae6c9b3f56cda -a789d4ca55cbba327086563831b34487d63d0980ba8cf55197c016702ed6da9b102b1f0709ce3da3c53ff925793a3d73 -a5d76acbb76741ce85be0e655b99baa04f7f587347947c0a30d27f8a49ae78cce06e1cde770a8b618d3db402be1c0c4b -873c0366668c8faddb0eb7c86f485718d65f8c4734020f1a18efd5fa123d3ea8a990977fe13592cd01d17e60809cb5ff -b659b71fe70f37573ff7c5970cc095a1dc0da3973979778f80a71a347ef25ad5746b2b9608bad4ab9a4a53a4d7df42d7 -a34cbe05888e5e5f024a2db14cb6dcdc401a9cbd13d73d3c37b348f68688f87c24ca790030b8f84fef9e74b4eab5e412 -94ce8010f85875c045b0f014db93ef5ab9f1f6842e9a5743dce9e4cb872c94affd9e77c1f1d1ab8b8660b52345d9acb9 -adefa9b27a62edc0c5b019ddd3ebf45e4de846165256cf6329331def2e088c5232456d3de470fdce3fa758bfdd387512 -a6b83821ba7c1f83cc9e4529cf4903adb93b26108e3d1f20a753070db072ad5a3689643144bdd9c5ea06bb9a7a515cd0 -a3a9ddedc2a1b183eb1d52de26718151744db6050f86f3580790c51d09226bf05f15111691926151ecdbef683baa992c -a64bac89e7686932cdc5670d07f0b50830e69bfb8c93791c87c7ffa4913f8da881a9d8a8ce8c1a9ce5b6079358c54136 -a77b5a63452cb1320b61ab6c7c2ef9cfbcade5fd4727583751fb2bf3ea330b5ca67757ec1f517bf4d503ec924fe32fbd -8746fd8d8eb99639d8cd0ca34c0d9c3230ed5a312aab1d3d925953a17973ee5aeb66e68667e93caf9cb817c868ea8f3d -88a2462a26558fc1fbd6e31aa8abdc706190a17c27fdc4217ffd2297d1b1f3321016e5c4b2384c5454d5717dc732ed03 -b78893a97e93d730c8201af2e0d3b31cb923d38dc594ffa98a714e627c473d42ea82e0c4d2eeb06862ee22a9b2c54588 -920cc8b5f1297cf215a43f6fc843e379146b4229411c44c0231f6749793d40f07b9af7699fd5d21fd69400b97febe027 -a0f0eafce1e098a6b58c7ad8945e297cd93aaf10bc55e32e2e32503f02e59fc1d5776936577d77c0b1162cb93b88518b -98480ba0064e97a2e7a6c4769b4d8c2a322cfc9a3b2ca2e67e9317e2ce04c6e1108169a20bd97692e1cb1f1423b14908 -83dbbb2fda7e287288011764a00b8357753a6a44794cc8245a2275237f11affdc38977214e463ad67aec032f3dfa37e9 -86442fff37598ce2b12015ff19b01bb8a780b40ad353d143a0f30a06f6d23afd5c2b0a1253716c855dbf445cc5dd6865 -b8a4c60c5171189414887847b9ed9501bff4e4c107240f063e2d254820d2906b69ef70406c585918c4d24f1dd052142b -919f33a98e84015b2034b57b5ffe9340220926b2c6e45f86fd79ec879dbe06a148ae68b77b73bf7d01bd638a81165617 -95c13e78d89474a47fbc0664f6f806744b75dede95a479bbf844db4a7f4c3ae410ec721cb6ffcd9fa9c323da5740d5ae -ab7151acc41fffd8ec6e90387700bcd7e1cde291ea669567295bea1b9dd3f1df2e0f31f3588cd1a1c08af8120aca4921 -80e74c5c47414bd6eeef24b6793fb1fa2d8fb397467045fcff887c52476741d5bc4ff8b6d3387cb53ad285485630537f -a296ad23995268276aa351a7764d36df3a5a3cffd7dbeddbcea6b1f77adc112629fdeffa0918b3242b3ccd5e7587e946 -813d2506a28a2b01cb60f49d6bd5e63c9b056aa56946faf2f33bd4f28a8d947569cfead3ae53166fc65285740b210f86 -924b265385e1646287d8c09f6c855b094daaee74b9e64a0dddcf9ad88c6979f8280ba30c8597b911ef58ddb6c67e9fe3 -8d531513c70c2d3566039f7ca47cd2352fd2d55b25675a65250bdb8b06c3843db7b2d29c626eed6391c238fc651cf350 -82b338181b62fdc81ceb558a6843df767b6a6e3ceedc5485664b4ea2f555904b1a45fbb35f6cf5d96f27da10df82a325 -92e62faaedea83a37f314e1d3cb4faaa200178371d917938e59ac35090be1db4b4f4e0edb78b9c991de202efe4f313d8 -99d645e1b642c2dc065bac9aaa0621bc648c9a8351efb6891559c3a41ba737bd155fb32d7731950514e3ecf4d75980e4 -b34a13968b9e414172fb5d5ece9a39cf2eb656128c3f2f6cc7a9f0c69c6bae34f555ecc8f8837dc34b5e470e29055c78 -a2a0bb7f3a0b23a2cbc6585d59f87cd7e56b2bbcb0ae48f828685edd9f7af0f5edb4c8e9718a0aaf6ef04553ba71f3b7 -8e1a94bec053ed378e524b6685152d2b52d428266f2b6eadd4bcb7c4e162ed21ab3e1364879673442ee2162635b7a4d8 -9944adaff14a85eab81c73f38f386701713b52513c4d4b838d58d4ffa1d17260a6d056b02334850ea9a31677c4b078bd -a450067c7eceb0854b3eca3db6cf38669d72cb7143c3a68787833cbca44f02c0be9bfbe082896f8a57debb13deb2afb1 -8be4ad3ac9ef02f7df09254d569939757101ee2eda8586fefcd8c847adc1efe5bdcb963a0cafa17651befaafb376a531 -90f6de91ea50255f148ac435e08cf2ac00c772a466e38155bd7e8acf9197af55662c7b5227f88589b71abe9dcf7ba343 -86e5a24f0748b106dee2d4d54e14a3b0af45a96cbee69cac811a4196403ebbee17fd24946d7e7e1b962ac7f66dbaf610 -afdd96fbcda7aa73bf9eeb2292e036c25753d249caee3b9c013009cc22e10d3ec29e2aa6ddbb21c4e949b0c0bccaa7f4 -b5a4e7436d5473647c002120a2cb436b9b28e27ad4ebdd7c5f122b91597c507d256d0cbd889d65b3a908531936e53053 -b632414c3da704d80ac2f3e5e0e9f18a3637cdc2ebeb613c29300745582427138819c4e7b0bec3099c1b8739dac1807b -a28df1464d3372ce9f37ef1db33cc010f752156afae6f76949d98cd799c0cf225c20228ae86a4da592d65f0cffe3951b -898b93d0a31f7d3f11f253cb7a102db54b669fd150da302d8354d8e02b1739a47cb9bd88015f3baf12b00b879442464e -96fb88d89a12049091070cb0048a381902965e67a8493e3991eaabe5d3b7ff7eecd5c94493a93b174df3d9b2c9511755 -b899cb2176f59a5cfba3e3d346813da7a82b03417cad6342f19cc8f12f28985b03bf031e856a4743fd7ebe16324805b0 -a60e2d31bc48e0c0579db15516718a03b73f5138f15037491f4dae336c904e312eda82d50862f4debd1622bb0e56d866 -979fc8b987b5cef7d4f4b58b53a2c278bd25a5c0ea6f41c715142ea5ff224c707de38451b0ad3aa5e749aa219256650a -b2a75bff18e1a6b9cf2a4079572e41205741979f57e7631654a3c0fcec57c876c6df44733c9da3d863db8dff392b44a3 -b7a0f0e811222c91e3df98ff7f286b750bc3b20d2083966d713a84a2281744199e664879401e77470d44e5a90f3e5181 -82b74ba21c9d147fbc338730e8f1f8a6e7fc847c3110944eb17a48bea5e06eecded84595d485506d15a3e675fd0e5e62 -a7f44eef817d5556f0d1abcf420301217d23c69dd2988f44d91ea1f1a16c322263cbacd0f190b9ba22b0f141b9267b4f -aadb68164ede84fc1cb3334b3194d84ba868d5a88e4c9a27519eef4923bc4abf81aab8114449496c073c2a6a0eb24114 -b5378605fabe9a8c12a5dc55ef2b1de7f51aedb61960735c08767a565793cea1922a603a6983dc25f7cea738d0f7c40d -a97a4a5cd8d51302e5e670aee78fe6b5723f6cc892902bbb4f131e82ca1dfd5de820731e7e3367fb0c4c1922a02196e3 -8bdfeb15c29244d4a28896f2b2cb211243cd6a1984a3f5e3b0ebe5341c419beeab3304b390a009ffb47588018034b0ea -a9af3022727f2aa2fca3b096968e97edad3f08edcbd0dbca107b892ae8f746a9c0485e0d6eb5f267999b23a845923ed0 -8e7594034feef412f055590fbb15b6322dc4c6ab7a4baef4685bd13d71a83f7d682b5781bdfa0d1c659489ce9c2b8000 -84977ca6c865ebee021c58106c1a4ad0c745949ecc5332948002fd09bd9b890524878d0c29da96fd11207621136421fe -8687551a79158e56b2375a271136756313122132a6670fa51f99a1b5c229ed8eea1655a734abae13228b3ebfd2a825dd -a0227d6708979d99edfc10f7d9d3719fd3fc68b0d815a7185b60307e4c9146ad2f9be2b8b4f242e320d4288ceeb9504c -89f75583a16735f9dd8b7782a130437805b34280ccea8dac6ecaee4b83fe96947e7b53598b06fecfffdf57ffc12cc445 -a0056c3353227f6dd9cfc8e3399aa5a8f1d71edf25d3d64c982910f50786b1e395c508d3e3727ac360e3e040c64b5298 -b070e61a6d813626144b312ded1788a6d0c7cec650a762b2f8df6e4743941dd82a2511cd956a3f141fc81e15f4e092da -b4e6db232e028a1f989bb5fc13416711f42d389f63564d60851f009dcffac01acfd54efa307aa6d4c0f932892d4e62b0 -89b5991a67db90024ddd844e5e1a03ef9b943ad54194ae0a97df775dde1addf31561874f4e40fbc37a896630f3bbda58 -ad0e8442cb8c77d891df49cdb9efcf2b0d15ac93ec9be1ad5c3b3cca1f4647b675e79c075335c1f681d56f14dc250d76 -b5d55a6ae65bb34dd8306806cb49b5ccb1c83a282ee47085cf26c4e648e19a52d9c422f65c1cd7e03ca63e926c5e92ea -b749501347e5ec07e13a79f0cb112f1b6534393458b3678a77f02ca89dca973fa7b30e55f0b25d8b92b97f6cb0120056 -94144b4a3ffc5eec6ba35ce9c245c148b39372d19a928e236a60e27d7bc227d18a8cac9983851071935d8ffb64b3a34f -92bb4f9f85bc8c028a3391306603151c6896673135f8a7aefedd27acb322c04ef5dac982fc47b455d6740023e0dd3ea3 -b9633a4a101461a782fc2aa092e9dbe4e2ad00987578f18cd7cf0021a909951d60fe79654eb7897806795f93c8ff4d1c -809f0196753024821b48a016eca5dbb449a7c55750f25981bb7a4b4c0e0846c09b8f6128137905055fc43a3f0deb4a74 -a27dc9cdd1e78737a443570194a03d89285576d3d7f3a3cf15cc55b3013e42635d4723e2e8fe1d0b274428604b630db9 -861f60f0462e04cd84924c36a28163def63e777318d00884ab8cb64c8df1df0bce5900342163edb60449296484a6c5bf -b7bc23fb4e14af4c4704a944253e760adefeca8caee0882b6bbd572c84434042236f39ae07a8f21a560f486b15d82819 -b9a6eb492d6dd448654214bd01d6dc5ff12067a11537ab82023fc16167507ee25eed2c91693912f4155d1c07ed9650b3 -97678af29c68f9a5e213bf0fb85c265303714482cfc4c2c00b4a1e8a76ed08834ee6af52357b143a1ca590fb0265ea5a -8a15b499e9eca5b6cac3070b5409e8296778222018ad8b53a5d1f6b70ad9bb10c68a015d105c941ed657bf3499299e33 -b487fefede2e8091f2c7bfe85770db2edff1db83d4effe7f7d87bff5ab1ace35e9b823a71adfec6737fede8d67b3c467 -8b51b916402aa2c437fce3bcad6dad3be8301a1a7eab9d163085b322ffb6c62abf28637636fe6114573950117fc92898 -b06a2106d031a45a494adec0881cb2f82275dff9dcdd2bc16807e76f3bec28a6734edd3d54f0be8199799a78cd6228ad -af0a185391bbe2315eb97feac98ad6dd2e5d931d012c621abd6e404a31cc188b286fef14871762190acf086482b2b5e2 -8e78ee8206506dd06eb7729e32fceda3bebd8924a64e4d8621c72e36758fda3d0001af42443851d6c0aea58562870b43 -a1ba52a569f0461aaf90b49b92be976c0e73ec4a2c884752ee52ffb62dd137770c985123d405dfb5de70692db454b54a -8d51b692fa1543c51f6b62b9acb8625ed94b746ef96c944ca02859a4133a5629da2e2ce84e111a7af8d9a5b836401c64 -a7a20d45044cf6492e0531d0b8b26ffbae6232fa05a96ed7f06bdb64c2b0f5ca7ec59d5477038096a02579e633c7a3ff -84df867b98c53c1fcd4620fef133ee18849c78d3809d6aca0fb6f50ff993a053a455993f216c42ab6090fa5356b8d564 -a7227c439f14c48e2577d5713c97a5205feb69acb0b449152842e278fa71e8046adfab468089c8b2288af1fc51fa945b -855189b3a105670779997690876dfaa512b4a25a24931a912c2f0f1936971d2882fb4d9f0b3d9daba77eaf660e9d05d5 -b5696bd6706de51c502f40385f87f43040a5abf99df705d6aac74d88c913b8ecf7a99a63d7a37d9bdf3a941b9e432ff5 -ab997beb0d6df9c98d5b49864ef0b41a2a2f407e1687dfd6089959757ba30ed02228940b0e841afe6911990c74d536c4 -b36b65f85546ebfdbe98823d5555144f96b4ab39279facd19c0de3b8919f105ba0315a0784dce4344b1bc62d8bb4a5a3 -b8371f0e4450788720ac5e0f6cd3ecc5413d33895083b2c168d961ec2b5c3de411a4cc0712481cbe8df8c2fa1a7af006 -98325d8026b810a8b7a114171ae59a57e8bbc9848e7c3df992efc523621729fd8c9f52114ce01d7730541a1ada6f1df1 -8d0e76dbd37806259486cd9a31bc8b2306c2b95452dc395546a1042d1d17863ef7a74c636b782e214d3aa0e8d717f94a -a4e15ead76da0214d702c859fb4a8accdcdad75ed08b865842bd203391ec4cba2dcc916455e685f662923b96ee0c023f -8618190972086ebb0c4c1b4a6c94421a13f378bc961cc8267a301de7390c5e73c3333864b3b7696d81148f9d4843fd02 -85369d6cc7342e1aa15b59141517d8db8baaaeb7ab9670f3ba3905353948d575923d283b7e5a05b13a30e7baf1208a86 -87c51ef42233c24a6da901f28c9a075d9ba3c625687c387ad6757b72ca6b5a8885e6902a3082da7281611728b1e45f26 -aa6348a4f71927a3106ad0ea8b02fc8d8c65531e4ab0bd0a17243e66f35afe252e40ab8eef9f13ae55a72566ffdaff5c -96a3bc976e9d03765cc3fee275fa05b4a84c94fed6b767e23ca689394501e96f56f7a97cffddc579a6abff632bf153be -97dbf96c6176379fdb2b888be4e757b2bca54e74124bd068d3fa1dbd82a011bbeb75079da38e0cd22a761fe208ecad9b -b70cf0a1d14089a4129ec4e295313863a59da8c7e26bf74cc0e704ed7f0ee4d7760090d0ddf7728180f1bf2c5ac64955 -882d664714cc0ffe53cbc9bef21f23f3649824f423c4dbad1f893d22c4687ab29583688699efc4d5101aa08b0c3e267a -80ecb7cc963e677ccaddbe3320831dd6ee41209acf4ed41b16dc4817121a3d86a1aac9c4db3d8c08a55d28257088af32 -a25ba667d832b145f9ce18c3f9b1bd00737aa36db020e1b99752c8ef7d27c6c448982bd8d352e1b6df266b8d8358a8d5 -83734841c13dee12759d40bdd209b277e743b0d08cc0dd1e0b7afd2d65bfa640400eefcf6be4a52e463e5b3d885eeac6 -848d16505b04804afc773aebabb51b36fd8aacfbb0e09b36c0d5d57df3c0a3b92f33e7d5ad0a7006ec46ebb91df42b8c -909a8d793f599e33bb9f1dc4792a507a97169c87cd5c087310bc05f30afcd247470b4b56dec59894c0fb1d48d39bb54e -8e558a8559df84a1ba8b244ece667f858095c50bb33a5381e60fcc6ba586b69693566d8819b4246a27287f16846c1dfa -84d6b69729f5aaa000cd710c2352087592cfbdf20d5e1166977e195818e593fa1a50d1e04566be23163a2523dc1612f1 -9536d262b7a42125d89f4f32b407d737ba8d9242acfc99d965913ab3e043dcac9f7072a43708553562cac4cba841df30 -9598548923ca119d6a15fd10861596601dd1dedbcccca97bb208cdc1153cf82991ea8cc17686fbaa867921065265970c -b87f2d4af6d026e4d2836bc3d390a4a18e98a6e386282ce96744603bab74974272e97ac2da281afa21885e2cbb3a8001 -991ece62bf07d1a348dd22191868372904b9f8cf065ae7aa4e44fd24a53faf6d851842e35fb472895963aa1992894918 -a8c53dea4c665b30e51d22ca6bc1bc78aaf172b0a48e64a1d4b93439b053877ec26cb5221c55efd64fa841bbf7d5aff4 -93487ec939ed8e740f15335b58617c3f917f72d07b7a369befd479ae2554d04deb240d4a14394b26192efae4d2f4f35d -a44793ab4035443f8f2968a40e043b4555960193ffa3358d22112093aadfe2c136587e4139ffd46d91ed4107f61ea5e0 -b13fe033da5f0d227c75927d3dacb06dbaf3e1322f9d5c7c009de75cdcba5e308232838785ab69a70f0bedea755e003f -970a29b075faccd0700fe60d1f726bdebf82d2cc8252f4a84543ebd3b16f91be42a75c9719a39c4096139f0f31393d58 -a4c3eb1f7160f8216fc176fb244df53008ff32f2892363d85254002e66e2de21ccfe1f3b1047589abee50f29b9d507e3 -8c552885eab04ba40922a8f0c3c38c96089c95ff1405258d3f1efe8d179e39e1295cbf67677894c607ae986e4e6b1fb0 -b3671746fa7f848c4e2ae6946894defadd815230b906b419143523cc0597bc1d6c0a4c1e09d49b66b4a2c11cde3a4de3 -937a249a95813a5e2ef428e355efd202e15a37d73e56cfb7e57ea9f943f2ce5ca8026f2f1fd25bf164ba89d07077d858 -83646bdf6053a04aa9e2f112499769e5bd5d0d10f2e13db3ca89bd45c0b3b7a2d752b7d137fb3909f9c62b78166c9339 -b4eac4b91e763666696811b7ed45e97fd78310377ebea1674b58a2250973f80492ac35110ed1240cd9bb2d17493d708c -82db43a99bc6573e9d92a3fd6635dbbb249ac66ba53099c3c0c8c8080b121dd8243cd5c6e36ba0a4d2525bae57f5c89c -a64d6a264a681b49d134c655d5fc7756127f1ee7c93d328820f32bca68869f53115c0d27fef35fe71f7bc4fdaed97348 -8739b7a9e2b4bc1831e7f04517771bc7cde683a5e74e052542517f8375a2f64e53e0d5ac925ef722327e7bb195b4d1d9 -8f337cdd29918a2493515ebb5cf702bbe8ecb23b53c6d18920cc22f519e276ca9b991d3313e2d38ae17ae8bdfa4f8b7e -b0edeab9850e193a61f138ef2739fc42ceec98f25e7e8403bfd5fa34a7bc956b9d0898250d18a69fa4625a9b3d6129da -a9920f26fe0a6d51044e623665d998745c9eca5bce12051198b88a77d728c8238f97d4196f26e43b24f8841500b998d0 -86e655d61502b979eeeeb6f9a7e1d0074f936451d0a1b0d2fa4fb3225b439a3770767b649256fe481361f481a8dbc276 -84d3b32fa62096831cc3bf013488a9f3f481dfe293ae209ed19585a03f7db8d961a7a9dd0db82bd7f62d612707575d9c -81c827826ec9346995ffccf62a241e3b2d32f7357acd1b1f8f7a7dbc97022d3eb51b8a1230e23ce0b401d2e535e8cd78 -94a1e40c151191c5b055b21e86f32e69cbc751dcbdf759a48580951834b96a1eed75914c0d19a38aefd21fb6c8d43d0c -ab890222b44bc21b71f7c75e15b6c6e16bb03371acce4f8d4353ff3b8fcd42a14026589c5ed19555a3e15e4d18bfc3a3 -accb0be851e93c6c8cc64724cdb86887eea284194b10e7a43c90528ed97e9ec71ca69c6fac13899530593756dd49eab2 -b630220aa9e1829c233331413ee28c5efe94ea8ea08d0c6bfd781955078b43a4f92915257187d8526873e6c919c6a1de -add389a4d358c585f1274b73f6c3c45b58ef8df11f9d11221f620e241bf3579fba07427b288c0c682885a700cc1fa28d -a9fe6ca8bf2961a3386e8b8dcecc29c0567b5c0b3bcf3b0f9169f88e372b80151af883871fc5229815f94f43a6f5b2b0 -ad839ae003b92b37ea431fa35998b46a0afc3f9c0dd54c3b3bf7a262467b13ff3c323ada1c1ae02ac7716528bdf39e3e -9356d3fd0edcbbb65713c0f2a214394f831b26f792124b08c5f26e7f734b8711a87b7c4623408da6a091c9aef1f6af3c -896b25b083c35ac67f0af3784a6a82435b0e27433d4d74cd6d1eafe11e6827827799490fb1c77c11de25f0d75f14e047 -8bfa019391c9627e8e5f05c213db625f0f1e51ec68816455f876c7e55b8f17a4f13e5aae9e3fb9e1cf920b1402ee2b40 -8ba3a6faa6a860a8f3ce1e884aa8769ceded86380a86520ab177ab83043d380a4f535fe13884346c5e51bee68da6ab41 -a8292d0844084e4e3bb7af92b1989f841a46640288c5b220fecfad063ee94e86e13d3d08038ec2ac82f41c96a3bfe14d -8229bb030b2fc566e11fd33c7eab7a1bb7b49fed872ea1f815004f7398cb03b85ea14e310ec19e1f23e0bdaf60f8f76c -8cfbf869ade3ec551562ff7f63c2745cc3a1f4d4dc853a0cd42dd5f6fe54228f86195ea8fe217643b32e9f513f34a545 -ac52a3c8d3270ddfe1b5630159da9290a5ccf9ccbdef43b58fc0a191a6c03b8a5974cf6e2bbc7bd98d4a40a3581482d7 -ab13decb9e2669e33a7049b8eca3ca327c40dea15ad6e0e7fa63ed506db1d258bc36ac88b35f65cae0984e937eb6575d -b5e748eb1a7a1e274ff0cc56311c198f2c076fe4b7e73e5f80396fe85358549df906584e6bb2c8195b3e2be7736850a5 -b5cb911325d8f963c41f691a60c37831c7d3bbd92736efa33d1f77a22b3fde7f283127256c2f47e197571e6fe0b46149 -8a01dc6ed1b55f26427a014faa347130738b191a06b800e32042a46c13f60b49534520214359d68eb2e170c31e2b8672 -a72fa874866e19b2efb8e069328362bf7921ec375e3bcd6b1619384c3f7ee980f6cf686f3544e9374ff54b4d17a1629c -8db21092f7c5f110fba63650b119e82f4b42a997095d65f08f8237b02dd66fdf959f788df2c35124db1dbd330a235671 -8c65d50433d9954fe28a09fa7ba91a70a590fe7ba6b3060f5e4be0f6cef860b9897fa935fb4ebc42133524eb071dd169 -b4614058e8fa21138fc5e4592623e78b8982ed72aa35ee4391b164f00c68d277fa9f9eba2eeefc890b4e86eba5124591 -ab2ad3a1bce2fbd55ca6b7c23786171fe1440a97d99d6df4d80d07dd56ac2d7203c294b32fc9e10a6c259381a73f24a1 -812ae3315fdc18774a8da3713a4679e8ed10b9405edc548c00cacbe25a587d32040566676f135e4723c5dc25df5a22e9 -a464b75f95d01e5655b54730334f443c8ff27c3cb79ec7af4b2f9da3c2039c609908cd128572e1fd0552eb597e8cef8d -a0db3172e93ca5138fe419e1c49a1925140999f6eff7c593e5681951ee0ec1c7e454c851782cbd2b8c9bc90d466e90e0 -806db23ba7d00b87d544eed926b3443f5f9c60da6b41b1c489fba8f73593b6e3b46ebfcab671ee009396cd77d5e68aa1 -8bfdf2c0044cc80260994e1c0374588b6653947b178e8b312be5c2a05e05767e98ea15077278506aee7df4fee1aaf89e -827f6558c16841b5592ff089c9c31e31eb03097623524394813a2e4093ad2d3f8f845504e2af92195aaa8a1679d8d692 -925c4f8eab2531135cd71a4ec88e7035b5eea34ba9d799c5898856080256b4a15ed1a746e002552e2a86c9c157e22e83 -a9f9a368f0e0b24d00a35b325964c85b69533013f9c2cfad9708be5fb87ff455210f8cb8d2ce3ba58ca3f27495552899 -8ac0d3bebc1cae534024187e7c71f8927ba8fcc6a1926cb61c2b6c8f26bb7831019e635a376146c29872a506784a4aaa -97c577be2cbbfdb37ad754fae9df2ada5fc5889869efc7e18a13f8e502fbf3f4067a509efbd46fd990ab47ce9a70f5a8 -935e7d82bca19f16614aa43b4a3474e4d20d064e4bfdf1cea2909e5c9ab72cfe3e54dc50030e41ee84f3588cebc524e9 -941aafc08f7c0d94cebfbb1f0aad5202c02e6e37f2c12614f57e727efa275f3926348f567107ee6d8914dd71e6060271 -af0fbc1ba05b4b5b63399686df3619968be5d40073de0313cbf5f913d3d4b518d4c249cdd2176468ccaa36040a484f58 -a0c414f23f46ca6d69ce74c6f8a00c036cb0edd098af0c1a7d39c802b52cfb2d5dbdf93fb0295453d4646e2af7954d45 -909cf39e11b3875bb63b39687ae1b5d1f5a15445e39bf164a0b14691b4ddb39a8e4363f584ef42213616abc4785b5d66 -a92bac085d1194fbd1c88299f07a061d0bdd3f980b663e81e6254dbb288bf11478c0ee880e28e01560f12c5ccb3c0103 -841705cd5cd76b943e2b7c5e845b9dd3c8defe8ef67e93078d6d5e67ade33ad4b0fd413bc196f93b0a4073c855cd97d4 -8e7eb8364f384a9161e81d3f1d52ceca9b65536ae49cc35b48c3e2236322ba4ae9973e0840802d9fa4f4d82ea833544f -aed3ab927548bc8bec31467ba80689c71a168e34f50dcb6892f19a33a099f5aa6b3f9cb79f5c0699e837b9a8c7f27efe -b8fbf7696210a36e20edabd77839f4dfdf50d6d015cdf81d587f90284a9bcef7d2a1ff520728d7cc69a4843d6c20dedd -a9d533769ce6830211c884ae50a82a7bf259b44ac71f9fb11f0296fdb3981e6b4c1753fe744647b247ebc433a5a61436 -8b4bdf90d33360b7f428c71cde0a49fb733badba8c726876945f58c620ce7768ae0e98fc8c31fa59d8955a4823336bb1 -808d42238e440e6571c59e52a35ae32547d502dc24fd1759d8ea70a7231a95859baf30b490a4ba55fa2f3aaa11204597 -85594701f1d2fee6dc1956bc44c7b31db93bdeec2f3a7d622c1a08b26994760773e3d57521a44cfd7e407ac3fd430429 -a66de045ce7173043a6825e9dc440ac957e2efb6df0a337f4f8003eb0c719d873a52e6eba3cb0d69d977ca37d9187674 -87a1c6a1fdff993fa51efa5c3ba034c079c0928a7d599b906336af7c2dcab9721ceaf3108c646490af9dff9a754f54b3 -926424223e462ceb75aed7c22ade8a7911a903b7e5dd4bc49746ddce8657f4616325cd12667d4393ac52cdd866396d0e -b5dc96106593b42b30f06f0b0a1e0c1aafc70432e31807252d3674f0b1ea5e58eac8424879d655c9488d85a879a3e572 -997ca0987735cc716507cb0124b1d266d218b40c9d8e0ecbf26a1d65719c82a637ce7e8be4b4815d307df717bde7c72a -92994d3f57a569b7760324bb5ae4e8e14e1633d175dab06aa57b8e391540e05f662fdc08b8830f489a063f59b689a688 -a8087fcc6aa4642cb998bea11facfe87eb33b90a9aa428ab86a4124ad032fc7d2e57795311a54ec9f55cc120ebe42df1 -a9bd7d1de6c0706052ca0b362e2e70e8c8f70f1f026ea189b4f87a08ce810297ebfe781cc8004430776c54c1a05ae90c -856d33282e8a8e33a3d237fb0a0cbabaf77ba9edf2fa35a831fdafcadf620561846aa6cbb6bdc5e681118e1245834165 -9524a7aa8e97a31a6958439c5f3339b19370f03e86b89b1d02d87e4887309dbbe9a3a8d2befd3b7ed5143c8da7e0a8ad -824fdf433e090f8acbd258ac7429b21f36f9f3b337c6d0b71d1416a5c88a767883e255b2888b7c906dd2e9560c4af24c -88c7fee662ca7844f42ed5527996b35723abffd0d22d4ca203b9452c639a5066031207a5ae763dbc0865b3299d19b1ec -919dca5c5595082c221d5ab3a5bc230f45da7f6dec4eb389371e142c1b9c6a2c919074842479c2844b72c0d806170c0c -b939be8175715e55a684578d8be3ceff3087f60fa875fff48e52a6e6e9979c955efef8ff67cfa2b79499ea23778e33b0 -873b6db725e7397d11bc9bed9ac4468e36619135be686790a79bc6ed4249058f1387c9a802ea86499f692cf635851066 -aeae06db3ec47e9e5647323fa02fac44e06e59b885ad8506bf71b184ab3895510c82f78b6b22a5d978e8218e7f761e9f -b99c0a8359c72ab88448bae45d4bf98797a26bca48b0d4460cd6cf65a4e8c3dd823970ac3eb774ae5d0cea4e7fadf33e -8f10c8ec41cdfb986a1647463076a533e6b0eec08520c1562401b36bb063ac972aa6b28a0b6ce717254e35940b900e3c -a106d9be199636d7add43b942290269351578500d8245d4aae4c083954e4f27f64740a3138a66230391f2d0e6043a8de -a469997908244578e8909ff57cffc070f1dbd86f0098df3cfeb46b7a085cfecc93dc69ee7cad90ff1dc5a34d50fe580c -a4ef087bea9c20eb0afc0ee4caba7a9d29dfa872137828c721391273e402fb6714afc80c40e98bbd8276d3836bffa080 -b07a013f73cd5b98dae0d0f9c1c0f35bff8a9f019975c4e1499e9bee736ca6fcd504f9bc32df1655ff333062382cff04 -b0a77188673e87cc83348c4cc5db1eecf6b5184e236220c8eeed7585e4b928db849944a76ec60ef7708ef6dac02d5592 -b1284b37e59b529f0084c0dacf0af6c0b91fc0f387bf649a8c74819debf606f7b07fc3e572500016fb145ec2b24e9f17 -97b20b5b4d6b9129da185adfbf0d3d0b0faeba5b9715f10299e48ea0521709a8296a9264ce77c275a59c012b50b6519a -b9d37e946fae5e4d65c1fbfacc8a62e445a1c9d0f882e60cca649125af303b3b23af53c81d7bac544fb7fcfc7a314665 -8e5acaac379f4bb0127efbef26180f91ff60e4c525bc9b798fc50dfaf4fe8a5aa84f18f3d3cfb8baead7d1e0499af753 -b0c0b8ab1235bf1cda43d4152e71efc1a06c548edb964eb4afceb201c8af24240bf8ab5cae30a08604e77432b0a5faf0 -8cc28d75d5c8d062d649cbc218e31c4d327e067e6dbd737ec0a35c91db44fbbd0d40ec424f5ed79814add16947417572 -95ae6219e9fd47efaa9cb088753df06bc101405ba50a179d7c9f7c85679e182d3033f35b00dbba71fdcd186cd775c52e -b5d28fa09f186ebc5aa37453c9b4d9474a7997b8ae92748ecb940c14868792292ac7d10ade01e2f8069242b308cf97e5 -8c922a0faa14cc6b7221f302df3342f38fc8521ec6c653f2587890192732c6da289777a6cd310747ea7b7d104af95995 -b9ad5f660b65230de54de535d4c0fcae5bc6b59db21dea5500fdc12eea4470fb8ea003690fdd16d052523418d5e01e8c -a39a9dd41a0ff78c82979483731f1cd68d3921c3e9965869662c22e02dde3877802e180ba93f06e7346f96d9fa9261d2 -8b32875977ec372c583b24234c27ed73aef00cdff61eb3c3776e073afbdeade548de9497c32ec6d703ff8ad0a5cb7fe4 -9644cbe755a5642fe9d26cfecf170d3164f1848c2c2e271d5b6574a01755f3980b3fc870b98cf8528fef6ecef4210c16 -81ea9d1fdd9dd66d60f40ce0712764b99da9448ae0b300f8324e1c52f154e472a086dda840cb2e0b9813dc8ce8afd4b5 -906aaa4a7a7cdf01909c5cfbc7ded2abc4b869213cbf7c922d4171a4f2e637e56f17020b852ad339d83b8ac92f111666 -939b5f11acbdeff998f2a080393033c9b9d8d5c70912ea651c53815c572d36ee822a98d6dfffb2e339f29201264f2cf4 -aba4898bf1ccea9b9e2df1ff19001e05891581659c1cbbde7ee76c349c7fc7857261d9785823c9463a8aea3f40e86b38 -83ca1a56b8a0be4820bdb5a9346357c68f9772e43f0b887729a50d2eb2a326bbcede676c8bf2e51d7c89bbd8fdb778a6 -94e86e9fe6addfe2c3ee3a547267ed921f4230d877a85bb4442c2d9350c2fa9a9c54e6fe662de82d1a2407e4ab1691c2 -a0cc3bdef671a59d77c6984338b023fa2b431b32e9ed2abe80484d73edc6540979d6f10812ecc06d4d0c5d4eaca7183c -b5343413c1b5776b55ea3c7cdd1f3af1f6bd802ea95effe3f2b91a523817719d2ecc3f8d5f3cc2623ace7e35f99ca967 -92085d1ed0ed28d8cabe3e7ff1905ed52c7ceb1eac5503760c52fb5ee3a726aba7c90b483c032acc3f166b083d7ec370 -8ec679520455275cd957fca8122724d287db5df7d29f1702a322879b127bff215e5b71d9c191901465d19c86c8d8d404 -b65eb2c63d8a30332eb24ee8a0c70156fc89325ebbb38bacac7cf3f8636ad8a472d81ccca80423772abc00192d886d8a -a9fe1c060b974bee4d590f2873b28635b61bfcf614e61ff88b1be3eee4320f4874e21e8d666d8ac8c9aba672efc6ecae -b3fe2a9a389c006a831dea7e777062df84b5c2803f9574d7fbe10b7e1c125817986af8b6454d6be9d931a5ac94cfe963 -95418ad13b734b6f0d33822d9912c4c49b558f68d08c1b34a0127fcfa666bcae8e6fda8832d2c75bb9170794a20e4d7c -a9a7df761e7f18b79494bf429572140c8c6e9d456c4d4e336184f3f51525a65eb9582bea1e601bdb6ef8150b7ca736a5 -a0de03b1e75edf7998c8c1ac69b4a1544a6fa675a1941950297917366682e5644a4bda9cdeedfaf9473d7fccd9080b0c -a61838af8d95c95edf32663a68f007d95167bf6e41b0c784a30b22d8300cfdd5703bd6d16e86396638f6db6ae7e42a85 -8866d62084d905c145ff2d41025299d8b702ac1814a7dec4e277412c161bc9a62fed735536789cb43c88693c6b423882 -91da22c378c81497fe363e7f695c0268443abee50f8a6625b8a41e865638a643f07b157ee566de09ba09846934b4e2d7 -941d21dd57c9496aa68f0c0c05507405fdd413acb59bc668ce7e92e1936c68ec4b065c3c30123319884149e88228f0b2 -a77af9b094bc26966ddf2bf9e1520c898194a5ccb694915950dadc204facbe3066d3d89f50972642d76b14884cfbaa21 -8e76162932346869f4618bde744647f7ab52ab498ad654bdf2a4feeb986ac6e51370841e5acbb589e38b6e7142bb3049 -b60979ace17d6937ece72e4f015da4657a443dd01cebc7143ef11c09e42d4aa8855999a65a79e2ea0067f31c9fc2ab0f -b3e2ffdd5ee6fd110b982fd4fad4b93d0fca65478f986d086eeccb0804960bfaa1919afa743c2239973ea65091fe57d2 -8ce0ce05e7d7160d44574011da687454dbd3c8b8290aa671731b066e2c82f8cf2d63cb8e932d78c6122ec610e44660e6 -ab005dd8d297045c39e2f72fb1c48edb501ccf3575d3d04b9817b3afee3f0bb0f3f53f64bda37d1d9cde545aae999bae -95bd7edb4c4cd60e3cb8a72558845a3cce6bb7032ccdf33d5a49ebb6ddf203bc3c79e7b7e550735d2d75b04c8b2441e8 -889953ee256206284094e4735dbbb17975bafc7c3cb94c9fbfee4c3e653857bfd49e818f64a47567f721b98411a3b454 -b188423e707640ab0e75a061e0b62830cde8afab8e1ad3dae30db69ffae4e2fc005bababbdcbd7213b918ed4f70e0c14 -a97e0fafe011abd70d4f99a0b36638b3d6e7354284588f17a88970ed48f348f88392779e9a038c6cbc9208d998485072 -87db11014a91cb9b63e8dfaa82cdebca98272d89eb445ee1e3ff9dbaf2b3fad1a03b888cffc128e4fe208ed0dddece0f -aad2e40364edd905d66ea4ac9d51f9640d6fda9a54957d26ba233809851529b32c85660fa401dbee3679ec54fa6dd966 -863e99336ca6edf03a5a259e59a2d0f308206e8a2fb320cfc0be06057366df8e0f94b33a28f574092736b3c5ada84270 -b34bcc56a057589f34939a1adc51de4ff6a9f4fee9c7fa9aa131e28d0cf0759a0c871b640162acdfbf91f3f1b59a3703 -935dd28f2896092995c5eff1618e5b6efe7a40178888d7826da9b0503c2d6e68a28e7fac1a334e166d0205f0695ef614 -b842cd5f8f5de5ca6c68cb4a5c1d7b451984930eb4cc18fd0934d52fdc9c3d2d451b1c395594d73bc3451432bfba653f -9014537885ce2debad736bc1926b25fdab9f69b216bf024f589c49dc7e6478c71d595c3647c9f65ff980b14f4bb2283b -8e827ccca1dd4cd21707140d10703177d722be0bbe5cac578db26f1ef8ad2909103af3c601a53795435b27bf95d0c9ed -8a0b8ad4d466c09d4f1e9167410dbe2edc6e0e6229d4b3036d30f85eb6a333a18b1c968f6ca6d6889bb08fecde017ef4 -9241ee66c0191b06266332dc9161dede384c4bb4e116dbd0890f3c3790ec5566da4568243665c4725b718ac0f6b5c179 -aeb4d5fad81d2b505d47958a08262b6f1b1de9373c2c9ba6362594194dea3e002ab03b8cbb43f867be83065d3d370f19 -8781bc83bb73f7760628629fe19e4714b494dbed444c4e4e4729b7f6a8d12ee347841a199888794c2234f51fa26fc2b9 -b58864f0acd1c2afa29367e637cbde1968d18589245d9936c9a489c6c495f54f0113ecdcbe4680ac085dd3c397c4d0c3 -94a24284afaeead61e70f3e30f87248d76e9726759445ca18cdb9360586c60cc9f0ec1c397f9675083e0b56459784e2e -aed358853f2b54dcbddf865e1816c2e89be12e940e1abfa661e2ee63ffc24a8c8096be2072fa83556482c0d89e975124 -b95374e6b4fc0765708e370bc881e271abf2e35c08b056a03b847e089831ef4fe3124b9c5849d9c276eb2e35b3daf264 -b834cdbcfb24c8f84bfa4c552e7fadc0028a140952fd69ed13a516e1314a4cd35d4b954a77d51a1b93e1f5d657d0315d -8fb6d09d23bfa90e7443753d45a918d91d75d8e12ec7d016c0dfe94e5c592ba6aaf483d2f16108d190822d955ad9cdc3 -aa315cd3c60247a6ad4b04f26c5404c2713b95972843e4b87b5a36a89f201667d70f0adf20757ebe1de1b29ae27dda50 -a116862dca409db8beff5b1ccd6301cdd0c92ca29a3d6d20eb8b87f25965f42699ca66974dd1a355200157476b998f3b -b4c2f5fe173c4dc8311b60d04a65ce1be87f070ac42e13cd19c6559a2931c6ee104859cc2520edebbc66a13dc7d30693 -8d4a02bf99b2260c334e7d81775c5cf582b00b0c982ce7745e5a90624919028278f5e9b098573bad5515ce7fa92a80c8 -8543493bf564ce6d97bd23be9bff1aba08bd5821ca834f311a26c9139c92a48f0c2d9dfe645afa95fec07d675d1fd53b -9344239d13fde08f98cb48f1f87d34cf6abe8faecd0b682955382a975e6eed64e863fa19043290c0736261622e00045c -aa49d0518f343005ca72b9e6c7dcaa97225ce6bb8b908ebbe7b1a22884ff8bfb090890364e325a0d414ad180b8f161d1 -907d7fd3e009355ab326847c4a2431f688627faa698c13c03ffdd476ecf988678407f029b8543a475dcb3dafdf2e7a9c -845f1f10c6c5dad2adc7935f5cd2e2b32f169a99091d4f1b05babe7317b9b1cdce29b5e62f947dc621b9acbfe517a258 -8f3be8e3b380ea6cdf9e9c237f5e88fd5a357e5ded80ea1fc2019810814de82501273b4da38916881125b6fa0cfd4459 -b9c7f487c089bf1d20c822e579628db91ed9c82d6ca652983aa16d98b4270c4da19757f216a71b9c13ddee3e6e43705f -8ba2d8c88ad2b872db104ea8ddbb006ec2f3749fd0e19298a804bb3a5d94de19285cc7fb19fee58a66f7851d1a66c39f -9375ecd3ed16786fe161af5d5c908f56eeb467a144d3bbddfc767e90065b7c94fc53431adebecba2b6c9b5821184d36e -a49e069bfadb1e2e8bff6a4286872e2a9765d62f0eaa4fcb0e5af4bbbed8be3510fb19849125a40a8a81d1e33e81c3eb -9522cc66757b386aa6b88619525c8ce47a5c346d590bb3647d12f991e6c65c3ab3c0cfc28f0726b6756c892eae1672be -a9a0f1f51ff877406fa83a807aeb17b92a283879f447b8a2159653db577848cc451cbadd01f70441e351e9ed433c18bc -8ff7533dcff6be8714df573e33f82cf8e9f2bcaaa43e939c4759d52b754e502717950de4b4252fb904560fc31dce94a4 -959724671e265a28d67c29d95210e97b894b360da55e4cf16e6682e7912491ed8ca14bfaa4dce9c25a25b16af580494f -92566730c3002f4046c737032487d0833c971e775de59fe02d9835c9858e2e3bc37f157424a69764596c625c482a2219 -a84b47ceff13ed9c3e5e9cdf6739a66d3e7c2bd8a6ba318fefb1a9aecf653bb2981da6733ddb33c4b0a4523acc429d23 -b4ddf571317e44f859386d6140828a42cf94994e2f1dcbcc9777f4eebbfc64fc1e160b49379acc27c4672b8e41835c5d -8ab95c94072b853d1603fdd0a43b30db617d13c1d1255b99075198e1947bfa5f59aed2b1147548a1b5e986cd9173d15c -89511f2eab33894fd4b3753d24249f410ff7263052c1fef6166fc63a79816656b0d24c529e45ccce6be28de6e375d916 -a0866160ca63d4f2be1b4ea050dac6b59db554e2ebb4e5b592859d8df339b46fd7cb89aaed0951c3ee540aee982c238a -8fcc5cbba1b94970f5ff2eb1922322f5b0aa7d918d4b380c9e7abfd57afd8b247c346bff7b87af82efbce3052511cd1b -99aeb2a5e846b0a2874cca02c66ed40d5569eb65ab2495bc3f964a092e91e1517941f2688e79f8cca49cd3674c4e06dc -b7a096dc3bad5ca49bee94efd884aa3ff5615cf3825cf95fbe0ce132e35f46581d6482fa82666c7ef5f1643eaee8f1ca -94393b1da6eaac2ffd186b7725eca582f1ddc8cdd916004657f8a564a7c588175cb443fc6943b39029f5bbe0add3fad8 -884b85fe012ccbcd849cb68c3ad832d83b3ef1c40c3954ffdc97f103b1ed582c801e1a41d9950f6bddc1d11f19d5ec76 -b00061c00131eded8305a7ce76362163deb33596569afb46fe499a7c9d7a0734c084d336b38d168024c2bb42b58e7660 -a439153ac8e6ca037381e3240e7ba08d056c83d7090f16ed538df25901835e09e27de2073646e7d7f3c65056af6e4ce7 -830fc9ca099097d1f38b90e6843dc86f702be9d20bdacc3e52cae659dc41df5b8d2c970effa6f83a5229b0244a86fe22 -b81ea2ffaaff2bb00dd59a9ab825ba5eed4db0d8ac9c8ed1a632ce8f086328a1cddd045fbe1ace289083c1325881b7e7 -b51ea03c58daf2db32c99b9c4789b183365168cb5019c72c4cc91ac30b5fb7311d3db76e6fa41b7cd4a8c81e2f6cdc94 -a4170b2c6d09ca5beb08318730419b6f19215ce6c631c854116f904be3bc30dd85a80c946a8ab054d3e307afaa3f8fbc -897cc42ff28971ff54d2a55dd6b35cfb8610ac902f3c06e3a5cea0e0a257e870c471236a8e84709211c742a09c5601a6 -a18f2e98d389dace36641621488664ecbb422088ab03b74e67009b8b8acacaaa24fdcf42093935f355207d934adc52a8 -92adcfb678cc2ba19c866f3f2b988fdcb4610567f3ab436cc0cb9acaf5a88414848d71133ebdbec1983e38e6190f1b5f -a86d43c2ce01b366330d3b36b3ca85f000c3548b8297e48478da1ee7d70d8576d4650cba7852ed125c0d7cb6109aa7f3 -8ed31ceed9445437d7732dce78a762d72ff32a7636bfb3fd7974b7ae15db414d8184a1766915244355deb354fbc5803b -9268f70032584f416e92225d65af9ea18c466ebc7ae30952d56a4e36fd9ea811dde0a126da9220ba3c596ec54d8a335e -9433b99ee94f2d3fbdd63b163a2bdf440379334c52308bd24537f7defd807145a062ff255a50d119a7f29f4b85d250e3 -90ce664f5e4628a02278f5cf5060d1a34f123854634b1870906e5723ac9afd044d48289be283b267d45fcbf3f4656aaf -aaf21c4d59378bb835d42ae5c5e5ab7a3c8c36a59e75997989313197752b79a472d866a23683b329ea69b048b87fa13e -b83c0589b304cec9ede549fde54f8a7c2a468c6657da8c02169a6351605261202610b2055c639b9ed2d5b8c401fb8f56 -9370f326ea0f170c2c05fe2c5a49189f20aec93b6b18a5572a818cd4c2a6adb359e68975557b349fb54f065d572f4c92 -ac3232fa5ce6f03fca238bef1ce902432a90b8afce1c85457a6bee5571c033d4bceefafc863af04d4e85ac72a4d94d51 -80d9ea168ff821b22c30e93e4c7960ce3ad3c1e6deeebedd342a36d01bd942419b187e2f382dbfd8caa34cca08d06a48 -a387a3c61676fb3381eefa2a45d82625635a666e999aba30e3b037ec9e040f414f9e1ad9652abd3bcad63f95d85038db -a1b229fe32121e0b391b0f6e0180670b9dc89d79f7337de4c77ea7ad0073e9593846f06797c20e923092a08263204416 -92164a9d841a2b828cedf2511213268b698520f8d1285852186644e9a0c97512cafa4bfbe29af892c929ebccd102e998 -82ee2fa56308a67c7db4fd7ef539b5a9f26a1c2cc36da8c3206ba4b08258fbb3cec6fe5cdbd111433fb1ba2a1e275927 -8c77bfe9e191f190a49d46f05600603fa42345592539b82923388d72392404e0b29a493a15e75e8b068dddcd444c2928 -80b927f93ccf79dcf5c5b20bcf5a7d91d7a17bc0401bb7cc9b53a6797feac31026eb114257621f5a64a52876e4474cc1 -b6b68b6501c37804d4833d5a063dd108a46310b1400549074e3cac84acc6d88f73948b7ad48d686de89c1ec043ae8c1a -ab3da00f9bdc13e3f77624f58a3a18fc3728956f84b5b549d62f1033ae4b300538e53896e2d943f160618e05af265117 -b6830e87233b8eace65327fdc764159645b75d2fd4024bf8f313b2dd5f45617d7ecfb4a0b53ccafb5429815a9a1adde6 -b9251cfe32a6dc0440615aadcd98b6b1b46e3f4e44324e8f5142912b597ee3526bea2431e2b0282bb58f71be5b63f65e -af8d70711e81cdddfb39e67a1b76643292652584c1ce7ce4feb1641431ad596e75c9120e85f1a341e7a4da920a9cdd94 -98cd4e996594e89495c078bfd52a4586b932c50a449a7c8dfdd16043ca4cda94dafbaa8ad1b44249c99bbcc52152506e -b9fc6d1c24f48404a4a64fbe3e43342738797905db46e4132aee5f086aaa4c704918ad508aaefa455cfe1b36572e6242 -a365e871d30ba9291cedaba1be7b04e968905d003e9e1af7e3b55c5eb048818ae5b913514fb08b24fb4fbdccbb35d0b8 -93bf99510971ea9af9f1e364f1234c898380677c8e8de9b0dd24432760164e46c787bc9ec42a7ad450500706cf247b2d -b872f825a5b6e7b9c7a9ddfeded3516f0b1449acc9b4fd29fc6eba162051c17416a31e5be6d3563f424d28e65bab8b8f -b06b780e5a5e8eb4f4c9dc040f749cf9709c8a4c9ef15e925f442b696e41e5095db0778a6c73bcd329b265f2c6955c8b -848f1a981f5fc6cd9180cdddb8d032ad32cdfa614fc750d690dbae36cc0cd355cbf1574af9b3ffc8b878f1b2fafb9544 -a03f48cbff3e9e8a3a655578051a5ae37567433093ac500ed0021c6250a51b767afac9bdb194ee1e3eac38a08c0eaf45 -b5be78ce638ff8c4aa84352b536628231d3f7558c5be3bf010b28feac3022e64691fa672f358c8b663904aebe24a54ed -a9d4da70ff676fa55d1728ba6ab03b471fa38b08854d99e985d88c2d050102d8ccffbe1c90249a5607fa7520b15fe791 -8fe9f7092ffb0b69862c8e972fb1ecf54308c96d41354ed0569638bb0364f1749838d6d32051fff1599112978c6e229c -ae6083e95f37770ecae0df1e010456f165d96cfe9a7278c85c15cffd61034081ce5723e25e2bede719dc9341ec8ed481 -a260891891103089a7afbd9081ea116cfd596fd1015f5b65e10b0961eb37fab7d09c69b7ce4be8bf35e4131848fb3fe4 -8d729fa32f6eb9fd2f6a140bef34e8299a2f3111bffd0fe463aa8622c9d98bfd31a1df3f3e87cd5abc52a595f96b970e -a30ec6047ae4bc7da4daa7f4c28c93aedb1112cfe240e681d07e1a183782c9ff6783ac077c155af23c69643b712a533f -ac830726544bfe7b5467339e5114c1a75f2a2a8d89453ce86115e6a789387e23551cd64620ead6283dfa4538eb313d86 -8445c135b7a48068d8ed3e011c6d818cfe462b445095e2fbf940301e50ded23f272d799eea47683fc027430ce14613ef -95785411715c9ae9d8293ce16a693a2aa83e3cb1b4aa9f76333d0da2bf00c55f65e21e42e50e6c5772ce213dd7b4f7a0 -b273b024fa18b7568c0d1c4d2f0c4e79ec509dafac8c5951f14192d63ddbcf2d8a7512c1c1b615cc38fa3e336618e0c5 -a78b9d3ea4b6a90572eb27956f411f1d105fdb577ee2ffeec9f221da9b45db84bfe866af1f29597220c75e0c37a628d8 -a4be2bf058c36699c41513c4d667681ce161a437c09d81383244fc55e1c44e8b1363439d0cce90a3e44581fb31d49493 -b6eef13040f17dd4eba22aaf284d2f988a4a0c4605db44b8d2f4bf9567ac794550b543cc513c5f3e2820242dd704152e -87eb00489071fa95d008c5244b88e317a3454652dcb1c441213aa16b28cd3ecaa9b22fec0bdd483c1df71c37119100b1 -92d388acdcb49793afca329cd06e645544d2269234e8b0b27d2818c809c21726bc9cf725651b951e358a63c83dedee24 -ae27e219277a73030da27ab5603c72c8bd81b6224b7e488d7193806a41343dff2456132274991a4722fdb0ef265d04cd -97583e08ecb82bbc27c0c8476d710389fa9ffbead5c43001bd36c1b018f29faa98de778644883e51870b69c5ffb558b5 -90a799a8ce73387599babf6b7da12767c0591cadd36c20a7990e7c05ea1aa2b9645654ec65308ee008816623a2757a6a -a1b47841a0a2b06efd9ab8c111309cc5fc9e1d5896b3e42ed531f6057e5ade8977c29831ce08dbda40348386b1dcc06d -b92b8ef59bbddb50c9457691bc023d63dfcc54e0fd88bd5d27a09e0d98ac290fc90e6a8f6b88492043bf7c87fac8f3e4 -a9d6240b07d62e22ec8ab9b1f6007c975a77b7320f02504fc7c468b4ee9cfcfd945456ff0128bc0ef2174d9e09333f8d -8e96534c94693226dc32bca79a595ca6de503af635f802e86442c67e77564829756961d9b701187fe91318da515bf0e6 -b6ba290623cd8dd5c2f50931c0045d1cfb0c30877bc8fe58cbc3ff61ee8da100045a39153916efa1936f4aee0892b473 -b43baa7717fac02d4294f5b3bb5e58a65b3557747e3188b482410388daac7a9c177f762d943fd5dcf871273921213da8 -b9cf00f8fb5e2ef2b836659fece15e735060b2ea39b8e901d3dcbdcf612be8bf82d013833718c04cd46ffaa70b85f42e -8017d0c57419e414cbba504368723e751ef990cc6f05dad7b3c2de6360adc774ad95512875ab8337d110bf39a42026fa -ae7401048b838c0dcd4b26bb6c56d79d51964a0daba780970b6c97daee4ea45854ea0ac0e4139b3fe60dac189f84df65 -887b237b0cd0f816b749b21db0b40072f9145f7896c36916296973f9e6990ede110f14e5976c906d08987c9836cca57f -a88c3d5770148aee59930561ca1223aceb2c832fb5417e188dca935905301fc4c6c2c9270bc1dff7add490a125eb81c6 -b6cf9b02c0cd91895ad209e38c54039523f137b5848b9d3ad33ae43af6c20c98434952db375fe378de7866f2d0e8b18a -84ef3d322ff580c8ad584b1fe4fe346c60866eb6a56e982ba2cf3b021ecb1fdb75ecc6c29747adda86d9264430b3f816 -a0561c27224baf0927ad144cb71e31e54a064c598373fcf0d66aebf98ab7af1d8e2f343f77baefff69a6da750a219e11 -aa5cc43f5b8162b016f5e1b61214c0c9d15b1078911c650b75e6cdfb49b85ee04c6739f5b1687d15908444f691f732de -ad4ac099b935589c7b8fdfdf3db332b7b82bb948e13a5beb121ebd7db81a87d278024a1434bcf0115c54ca5109585c3d -8a00466abf3f109a1dcd19e643b603d3af23d42794ef8ca2514dd507ecea44a031ac6dbc18bd02f99701168b25c1791e -b00b5900dfad79645f8bee4e5adc7b84eb22e5b1e67df77ccb505b7fc044a6c08a8ea5faca662414eb945f874f884cea -950e204e5f17112250b22ea6bb8423baf522fc0af494366f18fe0f949f51d6e6812074a80875cf1ed9c8e7420058d541 -91e5cbf8bb1a1d50c81608c9727b414d0dd2fb467ebc92f100882a3772e54f94979cfdf8e373fdef7c7fcdd60fec9e00 -a093f6a857b8caaff80599c2e89c962b415ecbaa70d8fd973155fa976a284c6b29a855f5f7a3521134d00d2972755188 -b4d55a3551b00da54cc010f80d99ddd2544bde9219a3173dfaadf3848edc7e4056ab532fb75ac26f5f7141e724267663 -a03ea050fc9b011d1b04041b5765d6f6453a93a1819cd9bd6328637d0b428f08526466912895dcc2e3008ee58822e9a7 -99b12b3665e473d01bc6985844f8994fb65cb15745024fb7af518398c4a37ff215da8f054e8fdf3286984ae36a73ca5e -9972c7e7a7fb12e15f78d55abcaf322c11249cd44a08f62c95288f34f66b51f146302bce750ff4d591707075d9123bd2 -a64b4a6d72354e596d87cda213c4fc2814009461570ccb27d455bbe131f8d948421a71925425b546d8cf63d5458cd64b -91c215c73b195795ede2228b7ed1f6e37892e0c6b0f4a0b5a16c57aa1100c84df9239054a173b6110d6c2b7f4bf1ce52 -88807198910ec1303480f76a3683870246a995e36adaeadc29c22f0bdba8152fe705bd070b75de657b04934f7d0ccf80 -b37c0026c7b32eb02cacac5b55cb5fe784b8e48b2945c64d3037af83ece556a117f0ff053a5968c2f5fa230e291c1238 -94c768384ce212bc2387e91ce8b45e4ff120987e42472888a317abc9dcdf3563b62e7a61c8e98d7cdcbe272167d91fc6 -a10c2564936e967a390cb14ef6e8f8b04ea9ece5214a38837eda09e79e0c7970b1f83adf017c10efd6faa8b7ffa2c567 -a5085eed3a95f9d4b1269182ea1e0d719b7809bf5009096557a0674bde4201b0ddc1f0f16a908fc468846b3721748ce3 -87468eb620b79a0a455a259a6b4dfbc297d0d53336537b771254dd956b145dc816b195b7002647ea218552e345818a3f -ace2b77ffb87366af0a9cb5d27d6fc4a14323dbbf1643f5f3c4559306330d86461bb008894054394cbfaefeaa0bc2745 -b27f56e840a54fbd793f0b7a7631aa4cee64b5947e4382b2dfb5eb1790270288884c2a19afebe5dc0c6ef335d4531c1c -876e438633931f7f895062ee16c4b9d10428875f7bc79a8e156a64d379a77a2c45bf5430c5ab94330f03da352f1e9006 -a2512a252587d200d2092b44c914df54e04ff8bcef36bf631f84bde0cf5a732e3dc7f00f662842cfd74b0b0f7f24180e -827f1bc8f54a35b7a4bd8154f79bcc055e45faed2e74adf7cf21cca95df44d96899e847bd70ead6bb27b9c0ed97bbd8b -a0c92cf5a9ed843714f3aea9fe7b880f622d0b4a3bf66de291d1b745279accf6ba35097849691370f41732ba64b5966b -a63f5c1e222775658421c487b1256b52626c6f79cb55a9b7deb2352622cedffb08502042d622eb3b02c97f9c09f9c957 -8cc093d52651e65fb390e186db6cc4de559176af4624d1c44cb9b0e836832419dacac7b8db0627b96288977b738d785d -aa7b6a17dfcec146134562d32a12f7bd7fe9522e300859202a02939e69dbd345ed7ff164a184296268f9984f9312e8fc -8ac76721f0d2b679f023d06cbd28c85ae5f4b43c614867ccee88651d4101d4fd352dbdb65bf36bfc3ebc0109e4b0c6f9 -8d350f7c05fc0dcd9a1170748846fb1f5d39453e4cb31e6d1457bed287d96fc393b2ecc53793ca729906a33e59c6834a -b9913510dfc5056d7ec5309f0b631d1ec53e3a776412ada9aefdaf033c90da9a49fdde6719e7c76340e86599b1f0eec2 -94955626bf4ce87612c5cfffcf73bf1c46a4c11a736602b9ba066328dc52ad6d51e6d4f53453d4ed55a51e0aad810271 -b0fcab384fd4016b2f1e53f1aafd160ae3b1a8865cd6c155d7073ecc1664e05b1d8bca1def39c158c7086c4e1103345e -827de3f03edfbde08570b72de6662c8bfa499b066a0a27ebad9b481c273097d17a5a0a67f01553da5392ec3f149b2a78 -ab7940384c25e9027c55c40df20bd2a0d479a165ced9b1046958353cd69015eeb1e44ed2fd64e407805ba42df10fc7bf -8ad456f6ff8cd58bd57567d931f923d0c99141978511b17e03cab7390a72b9f62498b2893e1b05c7c22dd274e9a31919 -ac75399e999effe564672db426faa17a839e57c5ef735985c70cd559a377adec23928382767b55ed5a52f7b11b54b756 -b17f975a00b817299ac7af5f2024ea820351805df58b43724393bfb3920a8cd747a3bbd4b8286e795521489db3657168 -a2bed800a6d95501674d9ee866e7314063407231491d794f8cf57d5be020452729c1c7cefd8c50dc1540181f5caab248 -9743f5473171271ffdd3cc59a3ae50545901a7b45cd4bc3570db487865f3b73c0595bebabbfe79268809ee1862e86e4a -b7eab77c2d4687b60d9d7b04e842b3880c7940140012583898d39fcc22d9b9b0a9be2c2e3788b3e6f30319b39c338f09 -8e2b8f797a436a1b661140e9569dcf3e1eea0a77c7ff2bc4ff0f3e49af04ed2de95e255df8765f1d0927fb456a9926b1 -8aefea201d4a1f4ff98ffce94e540bb313f2d4dfe7e9db484a41f13fc316ed02b282e1acc9bc6f56cad2dc2e393a44c9 -b950c17c0e5ca6607d182144aa7556bb0efe24c68f06d79d6413a973b493bfdf04fd147a4f1ab03033a32004cc3ea66f -b7b8dcbb179a07165f2dc6aa829fad09f582a71b05c3e3ea0396bf9e6fe73076f47035c031c2101e8e38e0d597eadd30 -a9d77ed89c77ec1bf8335d08d41c3c94dcca9fd1c54f22837b4e54506b212aa38d7440126c80648ab7723ff18e65ed72 -a819d6dfd4aef70e52b8402fe5d135f8082d40eb7d3bb5c4d7997395b621e2bb10682a1bad2c9caa33dd818550fc3ec6 -8f6ee34128fac8bbf13ce2d68b2bb363eb4fd65b297075f88e1446ddeac242500eeb4ef0735e105882ff5ba8c44c139b -b4440e48255c1644bcecf3a1e9958f1ec4901cb5b1122ee5b56ffd02cad1c29c4266999dbb85aa2605c1b125490074d4 -a43304a067bede5f347775d5811cf65a6380a8d552a652a0063580b5c5ef12a0867a39c7912fa219e184f4538eba1251 -a891ad67a790089ffc9f6d53e6a3d63d3556f5f693e0cd8a7d0131db06fd4520e719cfcc3934f0a8f62a95f90840f1d4 -aea6df8e9bb871081aa0fc5a9bafb00be7d54012c5baf653791907d5042a326aeee966fd9012a582cc16695f5baf7042 -8ffa2660dc52ed1cd4eff67d6a84a8404f358a5f713d04328922269bee1e75e9d49afeec0c8ad751620f22352a438e25 -87ec6108e2d63b06abed350f8b363b7489d642486f879a6c3aa90e5b0f335efc2ff2834eef9353951a42136f8e6a1b32 -865619436076c2760d9e87ddc905023c6de0a8d56eef12c98a98c87837f2ca3f27fd26a2ad752252dbcbe2b9f1d5a032 -980437dce55964293cb315c650c5586ffd97e7a944a83f6618af31c9d92c37b53ca7a21bb5bc557c151b9a9e217e7098 -95d128fc369df4ad8316b72aea0ca363cbc7b0620d6d7bb18f7076a8717a6a46956ff140948b0cc4f6d2ce33b5c10054 -8c7212d4a67b9ec70ebbca04358ad2d36494618d2859609163526d7b3acc2fc935ca98519380f55e6550f70a9bc76862 -893a2968819401bf355e85eee0f0ed0406a6d4a7d7f172d0017420f71e00bb0ba984f6020999a3cdf874d3cd8ebcd371 -9103c1af82dece25d87274e89ea0acd7e68c2921c4af3d8d7c82ab0ed9990a5811231b5b06113e7fa43a6bd492b4564f -99cfd87a94eab7d35466caa4ed7d7bb45e5c932b2ec094258fb14bf205659f83c209b83b2f2c9ccb175974b2a33e7746 -874b6b93e4ee61be3f00c32dd84c897ccd6855c4b6251eb0953b4023634490ed17753cd3223472873cbc6095b2945075 -84a32c0dc4ea60d33aac3e03e70d6d639cc9c4cc435c539eff915017be3b7bdaba33349562a87746291ebe9bc5671f24 -a7057b24208928ad67914e653f5ac1792c417f413d9176ba635502c3f9c688f7e2ee81800d7e3dc0a340c464da2fd9c5 -a03fb9ed8286aacfa69fbd5d953bec591c2ae4153400983d5dbb6cd9ea37fff46ca9e5cceb9d117f73e9992a6c055ad2 -863b2de04e89936c9a4a2b40380f42f20aefbae18d03750fd816c658aee9c4a03df7b12121f795c85d01f415baaeaa59 -8526eb9bd31790fe8292360d7a4c3eed23be23dd6b8b8f01d2309dbfdc0cfd33ad1568ddd7f8a610f3f85a9dfafc6a92 -b46ab8c5091a493d6d4d60490c40aa27950574a338ea5bbc045be3a114af87bdcb160a8c80435a9b7ad815f3cb56a3f3 -aeadc47b41a8d8b4176629557646202f868b1d728b2dda58a347d937e7ffc8303f20d26d6c00b34c851b8aeec547885d -aebb19fc424d72c1f1822aa7adc744cd0ef7e55727186f8df8771c784925058c248406ebeeaf3c1a9ee005a26e9a10c6 -8ff96e81c1a4a2ab1b4476c21018fae0a67e92129ee36120cae8699f2d7e57e891f5c624902cb1b845b944926a605cc3 -8251b8d2c43fadcaa049a9e7aff838dae4fb32884018d58d46403ac5f3beb5c518bfd45f03b8abb710369186075eb71c -a8b2a64f865f51a5e5e86a66455c093407933d9d255d6b61e1fd81ffafc9538d73caaf342338a66ba8ee166372a3d105 -aad915f31c6ba7fdc04e2aaac62e84ef434b7ee76a325f07dc430d12c84081999720181067b87d792efd0117d7ee1eab -a13db3bb60389883fd41d565c54fb5180d9c47ce2fe7a169ae96e01d17495f7f4fa928d7e556e7c74319c4c25d653eb2 -a4491b0198459b3f552855d680a59214eb74e6a4d6c5fa3b309887dc50ebea2ecf6d26c040550f7dc478b452481466fb -8f017f13d4b1e3f0c087843582b52d5f8d13240912254d826dd11f8703a99a2f3166dfbdfdffd9a3492979d77524276b -96c3d5dcd032660d50d7cd9db2914f117240a63439966162b10c8f1f3cf74bc83b0f15451a43b31dbd85e4a7ce0e4bb1 -b479ec4bb79573d32e0ec93b92bdd7ec8c26ddb5a2d3865e7d4209d119fd3499eaac527615ffac78c440e60ef3867ae0 -b2c49c4a33aa94b52b6410b599e81ff15490aafa7e43c8031c865a84e4676354a9c81eb4e7b8be6825fdcefd1e317d44 -906dc51d6a90c089b6704b47592805578a6eed106608eeb276832f127e1b8e858b72e448edcbefb497d152447e0e68ff -b0e81c63b764d7dfbe3f3fddc9905aef50f3633e5d6a4af6b340495124abedcff5700dfd1577bbbed7b6bf97d02719cb -9304c64701e3b4ed6d146e48a881f7d83a17f58357cca0c073b2bb593afd2d94f6e2a7a1ec511d0a67ad6ff4c3be5937 -b6fdbd12ba05aa598d80b83f70a15ef90e5cba7e6e75fa038540ee741b644cd1f408a6cecfd2a891ef8d902de586c6b5 -b80557871a6521b1b3c74a1ba083ae055b575df607f1f7b04c867ba8c8c181ea68f8d90be6031f4d25002cca27c44da2 -aa7285b8e9712e06b091f64163f1266926a36607f9d624af9996856ed2aaf03a580cb22ce407d1ade436c28b44ca173f -8148d72b975238b51e6ea389e5486940d22641b48637d7dfadfa603a605bfc6d74a016480023945d0b85935e396aea5d -8a014933a6aea2684b5762af43dcf4bdbb633cd0428d42d71167a2b6fc563ece5e618bff22f1db2ddb69b845b9a2db19 -990d91740041db770d0e0eb9d9d97d826f09fd354b91c41e0716c29f8420e0e8aac0d575231efba12fe831091ec38d5a -9454d0d32e7e308ddec57cf2522fb1b67a2706e33fb3895e9e1f18284129ab4f4c0b7e51af25681d248d7832c05eb698 -a5bd434e75bac105cb3e329665a35bce6a12f71dd90c15165777d64d4c13a82bceedb9b48e762bd24034e0fc9fbe45f4 -b09e3b95e41800d4dc29c6ffdaab2cd611a0050347f6414f154a47ee20ee59bf8cf7181454169d479ebce1eb5c777c46 -b193e341d6a047d15eea33766d656d807b89393665a783a316e9ba10518e5515c8e0ade3d6e15641d917a8a172a5a635 -ade435ec0671b3621dde69e07ead596014f6e1daa1152707a8c18877a8b067bde2895dd47444ffa69db2bbef1f1d8816 -a7fd3d6d87522dfc56fb47aef9ce781a1597c56a8bbfd796baba907afdc872f753d732bfda1d3402aee6c4e0c189f52d -a298cb4f4218d0464b2fab393e512bbc477c3225aa449743299b2c3572f065bc3a42d07e29546167ed9e1b6b3b3a3af3 -a9ee57540e1fd9c27f4f0430d194b91401d0c642456c18527127d1f95e2dba41c2c86d1990432eb38a692fda058fafde -81d6c1a5f93c04e6d8e5a7e0678c1fc89a1c47a5c920bcd36180125c49fcf7c114866b90e90a165823560b19898a7c16 -a4b7a1ec9e93c899b9fd9aaf264c50e42c36c0788d68296a471f7a3447af4dbc81e4fa96070139941564083ec5b5b5a1 -b3364e327d381f46940c0e11e29f9d994efc6978bf37a32586636c0070b03e4e23d00650c1440f448809e1018ef9f6d8 -8056e0913a60155348300e3a62e28b5e30629a90f7dd4fe11289097076708110a1d70f7855601782a3cdc5bdb1ca9626 -b4980fd3ea17bac0ba9ee1c470b17e575bb52e83ebdd7d40c93f4f87bebeaff1c8a679f9d3d09d635f068d37d5bd28bd -905a9299e7e1853648e398901dfcd437aa575c826551f83520df62984f5679cb5f0ea86aa45ed3e18b67ddc0dfafe809 -ab99553bf31a84f2e0264eb34a08e13d8d15e2484aa9352354becf9a15999c76cc568d68274b70a65e49703fc23540d0 -a43681597bc574d2dae8964c9a8dc1a07613d7a1272bdcb818d98c85d44e16d744250c33f3b5e4d552d97396b55e601f -a54e5a31716fccb50245898c99865644405b8dc920ded7a11f3d19bdc255996054b268e16f2e40273f11480e7145f41e -8134f3ad5ef2ad4ba12a8a4e4d8508d91394d2bcdc38b7c8c8c0b0a820357ac9f79d286c65220f471eb1adca1d98fc68 -94e2f755e60471578ab2c1adb9e9cea28d4eec9b0e92e0140770bca7002c365fcabfe1e5fb4fe6cfe79a0413712aa3ef -ad48f8d0ce7eb3cc6e2a3086ad96f562e5bed98a360721492ae2e74dc158586e77ec8c35d5fd5927376301b7741bad2b -8614f0630bdd7fbad3a31f55afd9789f1c605dc85e7dc67e2edfd77f5105f878bb79beded6e9f0b109e38ea7da67e8d5 -9804c284c4c5e77dabb73f655b12181534ca877c3e1e134aa3f47c23b7ec92277db34d2b0a5d38d2b69e5d1c3008a3e3 -a51b99c3088e473afdaa9e0a9f7e75a373530d3b04e44e1148da0726b95e9f5f0c7e571b2da000310817c36f84b19f7f -ac4ff909933b3b76c726b0a382157cdc74ab851a1ac6cef76953c6444441804cc43abb883363f416592e8f6cfbc4550b -ae7d915eb9fc928b65a29d6edbc75682d08584d0014f7bcf17d59118421ae07d26a02137d1e4de6938bcd1ab8ef48fad -852f7e453b1af89b754df6d11a40d5d41ea057376e8ecacd705aacd2f917457f4a093d6b9a8801837fa0f62986ad7149 -92c6bf5ada5d0c3d4dd8058483de36c215fa98edab9d75242f3eff9db07c734ad67337da6f0eefe23a487bf75a600dee -a2b42c09d0db615853763552a48d2e704542bbd786aae016eb58acbf6c0226c844f5fb31e428cb6450b9db855f8f2a6f -880cc07968266dbfdcfbc21815cd69e0eddfee239167ac693fb0413912d816f2578a74f7716eecd6deefa68c6eccd394 -b885b3ace736cd373e8098bf75ba66fa1c6943ca1bc4408cd98ac7074775c4478594f91154b8a743d9c697e1b29f5840 -a51ce78de512bd87bfa0835de819941dffbf18bec23221b61d8096fc9436af64e0693c335b54e7bfc763f287bdca2db6 -a3c76166a3bdb9b06ef696e57603b58871bc72883ee9d45171a30fe6e1d50e30bc9c51b4a0f5a7270e19a77b89733850 -acefc5c6f8a1e7c24d7b41e0fc7f6f3dc0ede6cf3115ffb9a6e54b1d954cbca9bda8ad7a084be9be245a1b8e9770d141 -b420ed079941842510e31cfad117fa11fb6b4f97dfbc6298cb840f27ebaceba23eeaf3f513bcffbf5e4aae946310182d -95c3bb5ef26c5ed2f035aa5d389c6b3c15a6705b9818a3fefaed28922158b35642b2e8e5a1a620fdad07e75ad4b43af4 -825149f9081ecf07a2a4e3e8b5d21bade86c1a882475d51c55ee909330b70c5a2ac63771c8600c6f38df716af61a3ea1 -873b935aae16d9f08adbc25353cee18af2f1b8d5f26dec6538d6bbddc515f2217ed7d235dcfea59ae61b428798b28637 -9294150843a2bedcedb3bb74c43eb28e759cf9499582c5430bccefb574a8ddd4f11f9929257ff4c153990f9970a2558f -b619563a811cc531da07f4f04e5c4c6423010ff9f8ed7e6ec9449162e3d501b269fb1c564c09c0429431879b0f45df02 -91b509b87eb09f007d839627514658c7341bc76d468920fe8a740a8cb96a7e7e631e0ea584a7e3dc1172266f641d0f5c -8b8aceace9a7b9b4317f1f01308c3904d7663856946afbcea141a1c615e21ccad06b71217413e832166e9dd915fbe098 -87b3b36e725833ea0b0f54753c3728c0dbc87c52d44d705ffc709f2d2394414c652d3283bab28dcce09799504996cee0 -b2670aad5691cbf308e4a6a77a075c4422e6cbe86fdba24e9f84a313e90b0696afb6a067eebb42ba2d10340d6a2f6e51 -876784a9aff3d54faa89b2bacd3ff5862f70195d0b2edc58e8d1068b3c9074c0da1cfa23671fe12f35e33b8a329c0ccd -8b48b9e758e8a8eae182f5cbec96f67d20cca6d3eee80a2d09208eb1d5d872e09ef23d0df8ebbb9b01c7449d0e3e3650 -b79303453100654c04a487bdcadc9e3578bc80930c489a7069a52e8ca1dba36c492c8c899ce025f8364599899baa287d -961b35a6111da54ece6494f24dacd5ea46181f55775b5f03df0e370c34a5046ac2b4082925855325bb42bc2a2c98381d -a31feb1be3f5a0247a1f7d487987eb622e34fca817832904c6ee3ee60277e5847945a6f6ea1ac24542c72e47bdf647df -a12a2aa3e7327e457e1aae30e9612715dd2cfed32892c1cd6dcda4e9a18203af8a44afb46d03b2eed89f6b9c5a2c0c23 -a08265a838e69a2ca2f80fead6ccf16f6366415b920c0b22ee359bcd8d4464ecf156f400a16a7918d52e6d733dd64211 -b723d6344e938d801cca1a00032af200e541d4471fd6cbd38fb9130daa83f6a1dffbbe7e67fc20f9577f884acd7594b2 -a6733d83ec78ba98e72ddd1e7ff79b7adb0e559e256760d0c590a986e742445e8cdf560d44b29439c26d87edd0b07c8c -a61c2c27d3f7b9ff4695a17afedf63818d4bfba390507e1f4d0d806ce8778d9418784430ce3d4199fd3bdbc2504d2af3 -8332f3b63a6dc985376e8b1b25eeae68be6160fbe40053ba7bcf6f073204f682da72321786e422d3482fd60c9e5aa034 -a280f44877583fbb6b860d500b1a3f572e3ee833ec8f06476b3d8002058e25964062feaa1e5bec1536d734a5cfa09145 -a4026a52d277fcea512440d2204f53047718ebfcae7b48ac57ea7f6bfbc5de9d7304db9a9a6cbb273612281049ddaec5 -95cdf69c831ab2fad6c2535ede9c07e663d2ddccc936b64e0843d2df2a7b1c31f1759c3c20f1e7a57b1c8f0dbb21b540 -95c96cec88806469c277ab567863c5209027cecc06c7012358e5f555689c0d9a5ffb219a464f086b45817e8536b86d2f -afe38d4684132a0f03d806a4c8df556bf589b25271fbc6fe2e1ed16de7962b341c5003755da758d0959d2e6499b06c68 -a9b77784fda64987f97c3a23c5e8f61b918be0f7c59ba285084116d60465c4a2aaafc8857eb16823282cc83143eb9126 -a830f05881ad3ce532a55685877f529d32a5dbe56cea57ffad52c4128ee0fad0eeaf0da4362b55075e77eda7babe70e5 -992b3ad190d6578033c13ed5abfee4ef49cbc492babb90061e3c51ee4b5790cdd4c8fc1abff1fa2c00183b6b64f0bbbe -b1015424d9364aeff75de191652dc66484fdbec3e98199a9eb9671ec57bec6a13ff4b38446e28e4d8aedb58dd619cd90 -a745304604075d60c9db36cada4063ac7558e7ec2835d7da8485e58d8422e817457b8da069f56511b02601289fbb8981 -a5ba4330bc5cb3dbe0486ddf995632a7260a46180a08f42ae51a2e47778142132463cc9f10021a9ad36986108fefa1a9 -b419e9fd4babcaf8180d5479db188bb3da232ae77a1c4ed65687c306e6262f8083070a9ac32220cddb3af2ec73114092 -a49e23dc5f3468f3bf3a0bb7e4a114a788b951ff6f23a3396ae9e12cbff0abd1240878a3d1892105413dbc38818e807c -b7ecc7b4831f650202987e85b86bc0053f40d983f252e9832ef503aea81c51221ce93279da4aa7466c026b2d2070e55d -96a8c35cb87f84fa84dcd6399cc2a0fd79cc9158ef4bdde4bae31a129616c8a9f2576cd19baa3f497ca34060979aed7d -8681b2c00aa62c2b519f664a95dcb8faef601a3b961bb4ce5d85a75030f40965e2983871d41ea394aee934e859581548 -85c229a07efa54a713d0790963a392400f55fbb1a43995a535dc6c929f20d6a65cf4efb434e0ad1cb61f689b8011a3bc -90856f7f3444e5ad44651c28e24cc085a5db4d2ffe79aa53228c26718cf53a6e44615f3c5cda5aa752d5f762c4623c66 -978999b7d8aa3f28a04076f74d11c41ef9c89fdfe514936c4238e0f13c38ec97e51a5c078ebc6409e517bfe7ccb42630 -a099914dd7ed934d8e0d363a648e9038eb7c1ec03fa04dbcaa40f7721c618c3ef947afef7a16b4d7ac8c12aa46637f03 -ab2a104fed3c83d16f2cda06878fa5f30c8c9411de71bfb67fd2fc9aa454dcbcf3d299d72f8cc12e919466a50fcf7426 -a4471d111db4418f56915689482f6144efc4664cfb0311727f36c864648d35734351becc48875df96f4abd3cfcf820f9 -83be11727cd30ea94ccc8fa31b09b81c9d6a9a5d3a4686af9da99587332fe78c1f94282f9755854bafd6033549afec91 -88020ff971dc1a01a9e993cd50a5d2131ffdcbb990c1a6aaa54b20d8f23f9546a70918ea57a21530dcc440c1509c24ad -ae24547623465e87905eaffa1fa5d52bb7c453a8dbd89614fa8819a2abcedaf455c2345099b7324ae36eb0ad7c8ef977 -b59b0c60997de1ee00b7c388bc7101d136c9803bf5437b1d589ba57c213f4f835a3e4125b54738e78abbc21b000f2016 -a584c434dfe194546526691b68fa968c831c31da42303a1d735d960901c74011d522246f37f299555416b8cf25c5a548 -80408ce3724f4837d4d52376d255e10f69eb8558399ae5ca6c11b78b98fe67d4b93157d2b9b639f1b5b64198bfe87713 -abb941e8d406c2606e0ddc35c113604fdd9d249eacc51cb64e2991e551b8639ce44d288cc92afa7a1e7fc599cfc84b22 -b223173f560cacb1c21dba0f1713839e348ad02cbfdef0626748604c86f89e0f4c919ed40b583343795bdd519ba952c8 -af1c70512ec3a19d98b8a1fc3ff7f7f5048a27d17d438d43f561974bbdd116fcd5d5c21040f3447af3f0266848d47a15 -8a44809568ebe50405bede19b4d2607199159b26a1b33e03d180e6840c5cf59d991a4fb150d111443235d75ecad085b7 -b06207cdca46b125a27b3221b5b50cf27af4c527dd7c80e2dbcebbb09778a96df3af67e50f07725239ce3583dad60660 -993352d9278814ec89b26a11c4a7c4941bf8f0e6781ae79559d14749ee5def672259792db4587f85f0100c7bb812f933 -9180b8a718b971fd27bc82c8582d19c4b4f012453e8c0ffeeeffe745581fc6c07875ab28be3af3fa3896d19f0c89ac5b -8b8e1263eb48d0fe304032dd5ea1f30e73f0121265f7458ba9054d3626894e8a5fef665340abd2ede9653045c2665938 -99a2beee4a10b7941c24b2092192faf52b819afd033e4a2de050fd6c7f56d364d0cf5f99764c3357cf32399e60fc5d74 -946a4aad7f8647ea60bee2c5fcdeb6f9a58fb2cfca70c4d10e458027a04846e13798c66506151be3df9454b1e417893f -a672a88847652d260b5472d6908d1d57e200f1e492d30dd1cecc441cdfc9b76e016d9bab560efd4d7f3c30801de884a9 -9414e1959c156cde1eb24e628395744db75fc24b9df4595350aaad0bc38e0246c9b4148f6443ef68b8e253a4a6bcf11c -9316e9e4ec5fab4f80d6540df0e3a4774db52f1d759d2e5b5bcd3d7b53597bb007eb1887cb7dc61f62497d51ffc8d996 -902d6d77bb49492c7a00bc4b70277bc28c8bf9888f4307bb017ac75a962decdedf3a4e2cf6c1ea9f9ba551f4610cbbd7 -b07025a18b0e32dd5e12ec6a85781aa3554329ea12c4cd0d3b2c22e43d777ef6f89876dd90a9c8fb097ddf61cf18adc5 -b355a849ad3227caa4476759137e813505ec523cbc2d4105bc7148a4630f9e81918d110479a2d5f5e4cd9ccec9d9d3e3 -b49532cfdf02ee760109881ad030b89c48ee3bb7f219ccafc13c93aead754d29bdafe345be54c482e9d5672bd4505080 -9477802410e263e4f938d57fa8f2a6cac7754c5d38505b73ee35ea3f057aad958cb9722ba6b7b3cfc4524e9ca93f9cdc -9148ea83b4436339580f3dbc9ba51509e9ab13c03063587a57e125432dd0915f5d2a8f456a68f8fff57d5f08c8f34d6e -b00b6b5392b1930b54352c02b1b3b4f6186d20bf21698689bbfc7d13e86538a4397b90e9d5c93fd2054640c4dbe52a4f -926a9702500441243cd446e7cbf15dde16400259726794694b1d9a40263a9fc9e12f7bcbf12a27cb9aaba9e2d5848ddc -a0c6155f42686cbe7684a1dc327100962e13bafcf3db97971fc116d9f5c0c8355377e3d70979cdbd58fd3ea52440901c -a277f899f99edb8791889d0817ea6a96c24a61acfda3ad8c3379e7c62b9d4facc4b965020b588651672fd261a77f1bfc -8f528cebb866b501f91afa50e995234bef5bf20bff13005de99cb51eaac7b4f0bf38580cfd0470de40f577ead5d9ba0f -963fc03a44e9d502cc1d23250efef44d299befd03b898d07ce63ca607bb474b5cf7c965a7b9b0f32198b04a8393821f7 -ab087438d0a51078c378bf4a93bd48ef933ff0f1fa68d02d4460820df564e6642a663b5e50a5fe509527d55cb510ae04 -b0592e1f2c54746bb076be0fa480e1c4bebc4225e1236bcda3b299aa3853e3afb401233bdbcfc4a007b0523a720fbf62 -851613517966de76c1c55a94dc4595f299398a9808f2d2f0a84330ba657ab1f357701d0895f658c18a44cb00547f6f57 -a2fe9a1dd251e72b0fe4db27be508bb55208f8f1616b13d8be288363ec722826b1a1fd729fc561c3369bf13950bf1fd6 -b896cb2bc2d0c77739853bc59b0f89b2e008ba1f701c9cbe3bef035f499e1baee8f0ff1e794854a48c320586a2dfc81a -a1b60f98e5e5106785a9b81a85423452ee9ef980fa7fa8464f4366e73f89c50435a0c37b2906052b8e58e212ebd366cf -a853b0ebd9609656636df2e6acd5d8839c0fda56f7bf9288a943b06f0b67901a32b95e016ca8bc99bd7b5eab31347e72 -b290fa4c1346963bd5225235e6bdf7c542174dab4c908ab483d1745b9b3a6015525e398e1761c90e4b49968d05e30eea -b0f65a33ad18f154f1351f07879a183ad62e5144ad9f3241c2d06533dad09cbb2253949daff1bb02d24d16a3569f7ef0 -a00db59b8d4218faf5aeafcd39231027324408f208ec1f54d55a1c41228b463b88304d909d16b718cfc784213917b71e -b8d695dd33dc2c3bc73d98248c535b2770ad7fa31aa726f0aa4b3299efb0295ba9b4a51c71d314a4a1bd5872307534d1 -b848057cca2ca837ee49c42b88422303e58ea7d2fc76535260eb5bd609255e430514e927cc188324faa8e657396d63ec -92677836061364685c2aaf0313fa32322746074ed5666fd5f142a7e8f87135f45cd10e78a17557a4067a51dfde890371 -a854b22c9056a3a24ab164a53e5c5cf388616c33e67d8ebb4590cb16b2e7d88b54b1393c93760d154208b5ca822dc68f -86fff174920388bfab841118fb076b2b0cdec3fdb6c3d9a476262f82689fb0ed3f1897f7be9dbf0932bb14d346815c63 -99661cf4c94a74e182752bcc4b98a8c2218a8f2765642025048e12e88ba776f14f7be73a2d79bd21a61def757f47f904 -8a8893144d771dca28760cba0f950a5d634195fd401ec8cf1145146286caffb0b1a6ba0c4c1828d0a5480ce49073c64c -938a59ae761359ee2688571e7b7d54692848eb5dde57ffc572b473001ea199786886f8c6346a226209484afb61d2e526 -923f68a6aa6616714cf077cf548aeb845bfdd78f2f6851d8148cba9e33a374017f2f3da186c39b82d14785a093313222 -ac923a93d7da7013e73ce8b4a2b14b8fd0cc93dc29d5de941a70285bdd19be4740fedfe0c56b046689252a3696e9c5bc -b49b32c76d4ec1a2c68d4989285a920a805993bc6fcce6dacd3d2ddae73373050a5c44ba8422a3781050682fa0ef6ba2 -8a367941c07c3bdca5712524a1411bad7945c7c48ffc7103b1d4dff2c25751b0624219d1ccde8c3f70c465f954be5445 -b838f029df455efb6c530d0e370bbbf7d87d61a9aea3d2fe5474c5fe0a39cf235ceecf9693c5c6c5820b1ba8f820bd31 -a8983b7c715eaac7f13a001d2abc462dfc1559dab4a6b554119c271aa8fe00ffcf6b6949a1121f324d6d26cb877bcbae -a2afb24ad95a6f14a6796315fbe0d8d7700d08f0cfaf7a2abe841f5f18d4fecf094406cbd54da7232a159f9c5b6e805e -87e8e95ad2d62f947b2766ff405a23f7a8afba14e7f718a691d95369c79955cdebe24c54662553c60a3f55e6322c0f6f -87c2cbcecb754e0cc96128e707e5c5005c9de07ffd899efa3437cadc23362f5a1d3fcdd30a1f5bdc72af3fb594398c2a -91afd6ee04f0496dc633db88b9370d41c428b04fd991002502da2e9a0ef051bcd7b760e860829a44fbe5539fa65f8525 -8c50e5d1a24515a9dd624fe08b12223a75ca55196f769f24748686315329b337efadca1c63f88bee0ac292dd0a587440 -8a07e8f912a38d94309f317c32068e87f68f51bdfa082d96026f5f5f8a2211621f8a3856dda8069386bf15fb2d28c18f -94ad1dbe341c44eeaf4dc133eed47d8dbfe752575e836c075745770a6679ff1f0e7883b6aa917462993a7f469d74cab5 -8745f8bd86c2bb30efa7efb7725489f2654f3e1ac4ea95bd7ad0f3cfa223055d06c187a16192d9d7bdaea7b050c6a324 -900d149c8d79418cda5955974c450a70845e02e5a4ecbcc584a3ca64d237df73987c303e3eeb79da1af83bf62d9e579f -8f652ab565f677fb1a7ba03b08004e3cda06b86c6f1b0b9ab932e0834acf1370abb2914c15b0d08327b5504e5990681c -9103097d088be1f75ab9d3da879106c2f597e2cc91ec31e73430647bdd5c33bcfd771530d5521e7e14df6acda44f38a6 -b0fec7791cfb0f96e60601e1aeced9a92446b61fedab832539d1d1037558612d78419efa87ff5f6b7aab8fd697d4d9de -b9d2945bdb188b98958854ba287eb0480ef614199c4235ce5f15fc670b8c5ffe8eeb120c09c53ea8a543a022e6a321ac -a9461bb7d5490973ebaa51afc0bb4a5e42acdccb80e2f939e88b77ac28a98870e103e1042899750f8667a8cc9123bae9 -a37fdf11d4bcb2aed74b9f460a30aa34afea93386fa4cdb690f0a71bc58f0b8df60bec56e7a24f225978b862626fa00e -a214420e183e03d531cf91661466ea2187d84b6e814b8b20b3730a9400a7d25cf23181bb85589ebc982cec414f5c2923 -ad09a45a698a6beb3e0915f540ef16e9af7087f53328972532d6b5dfe98ce4020555ece65c6cbad8bd6be8a4dfefe6fd -ab6742800b02728c92d806976764cb027413d6f86edd08ad8bb5922a2969ee9836878cd39db70db0bd9a2646862acc4f -974ca9305bd5ea1dc1755dff3b63e8bfe9f744321046c1395659bcea2a987b528e64d5aa96ac7b015650b2253b37888d -84eee9d6bce039c52c2ebc4fccc0ad70e20c82f47c558098da4be2f386a493cbc76adc795b5488c8d11b6518c2c4fab8 -875d7bda46efcb63944e1ccf760a20144df3b00d53282b781e95f12bfc8f8316dfe6492c2efbf796f1150e36e436e9df -b68a2208e0c587b5c31b5f6cb32d3e6058a9642e2d9855da4f85566e1412db528475892060bb932c55b3a80877ad7b4a -ba006368ecab5febb6ab348644d9b63de202293085ed468df8bc24d992ae8ce468470aa37f36a73630c789fb9c819b30 -90a196035150846cd2b482c7b17027471372a8ce7d914c4d82b6ea7fa705d8ed5817bd42d63886242585baf7d1397a1c -a223b4c85e0daa8434b015fd9170b5561fe676664b67064974a1e9325066ecf88fc81f97ab5011c59fad28cedd04b240 -82e8ec43139cf15c6bbeed484b62e06cded8a39b5ce0389e4cbe9c9e9c02f2f0275d8d8d4e8dfec8f69a191bef220408 -81a3fc07a7b68d92c6ee4b6d28f5653ee9ec85f7e2ee1c51c075c1b130a8c5097dc661cf10c5aff1c7114b1a6a19f11a -8ed2ef8331546d98819a5dd0e6c9f8cb2630d0847671314a28f277faf68da080b53891dd75c82cbcf7788b255490785d -acecabf84a6f9bbed6b2fc2e7e4b48f02ef2f15e597538a73aea8f98addc6badda15e4695a67ecdb505c1554e8f345ec -b8f51019b2aa575f8476e03dcadf86cc8391f007e5f922c2a36b2daa63f5a503646a468990cd5c65148d323942193051 -aaa595a84b403ec65729bc1c8055a94f874bf9adddc6c507b3e1f24f79d3ad359595a672b93aab3394db4e2d4a7d8970 -895144c55fcbd0f64d7dd69e6855cfb956e02b5658eadf0f026a70703f3643037268fdd673b0d21b288578a83c6338dd -a2e92ae6d0d237d1274259a8f99d4ea4912a299816350b876fba5ebc60b714490e198a916e1c38c6e020a792496fa23c -a45795fda3b5bb0ad1d3c628f6add5b2a4473a1414c1a232e80e70d1cfffd7f8a8d9861f8df2946999d7dbb56bf60113 -b6659bf7f6f2fef61c39923e8c23b8c70e9c903028d8f62516d16755cd3fba2fe41c285aa9432dc75ab08f8a1d8a81fc -a735609a6bc5bfd85e58234fc439ff1f58f1ff1dd966c5921d8b649e21f006bf2b8642ad8a75063c159aaf6935789293 -a3c622eb387c9d15e7bda2e3e84d007cb13a6d50d655c3f2f289758e49d3b37b9a35e4535d3cc53d8efd51f407281f19 -8afe147b53ad99220f5ef9d763bfc91f9c20caecbcf823564236fb0e6ede49414c57d71eec4772c8715cc65a81af0047 -b5f0203233cf71913951e9c9c4e10d9243e3e4a1f2cb235bf3f42009120ba96e04aa414c9938ea8873b63148478927e8 -93c52493361b458d196172d7ba982a90a4f79f03aa8008edc322950de3ce6acf4c3977807a2ffa9e924047e02072b229 -b9e72b805c8ac56503f4a86c82720afbd5c73654408a22a2ac0b2e5caccdfb0e20b59807433a6233bc97ae58cf14c70a -af0475779b5cee278cca14c82da2a9f9c8ef222eb885e8c50cca2315fea420de6e04146590ed0dd5a29c0e0812964df5 -b430ccab85690db02c2d0eb610f3197884ca12bc5f23c51e282bf3a6aa7e4a79222c3d8761454caf55d6c01a327595f9 -830032937418b26ee6da9b5206f3e24dc76acd98589e37937e963a8333e5430abd6ce3dd93ef4b8997bd41440eed75d6 -8820a6d73180f3fe255199f3f175c5eb770461ad5cfdde2fb11508041ed19b8c4ce66ad6ecebf7d7e836cc2318df47ca -aef1393e7d97278e77bbf52ef6e1c1d5db721ccf75fe753cf47a881fa034ca61eaa5098ee5a344c156d2b14ff9e284ad -8a4a26c07218948c1196c45d927ef4d2c42ade5e29fe7a91eaebe34a29900072ce5194cf28d51f746f4c4c649daf4396 -84011dc150b7177abdcb715efbd8c201f9cb39c36e6069af5c50a096021768ba40cef45b659c70915af209f904ede3b6 -b1bd90675411389bb66910b21a4bbb50edce5330850c5ab0b682393950124252766fc81f5ecfc72fb7184387238c402e -8dfdcd30583b696d2c7744655f79809f451a60c9ad5bf1226dc078b19f4585d7b3ef7fa9d54e1ac09520d95cbfd20928 -b351b4dc6d98f75b8e5a48eb7c6f6e4b78451991c9ba630e5a1b9874c15ac450cd409c1a024713bf2cf82dc400e025ef -a462b8bc97ac668b97b28b3ae24b9f5de60e098d7b23ecb600d2194cd35827fb79f77c3e50d358f5bd72ee83fef18fa0 -a183753265c5f7890270821880cce5f9b2965b115ba783c6dba9769536f57a04465d7da5049c7cf8b3fcf48146173c18 -a8a771b81ed0d09e0da4d79f990e58eabcd2be3a2680419502dd592783fe52f657fe55125b385c41d0ba3b9b9cf54a83 -a71ec577db46011689d073245e3b1c3222a9b1fe6aa5b83629adec5733dd48617ebea91346f0dd0e6cdaa86e4931b168 -a334b8b244f0d598a02da6ae0f918a7857a54dce928376c4c85df15f3b0f2ba3ac321296b8b7c9dd47d770daf16c8f8c -a29037f8ef925c417c90c4df4f9fb27fb977d04e2b3dd5e8547d33e92ab72e7a00f5461de21e28835319eae5db145eb7 -b91054108ae78b00e3298d667b913ebc44d8f26e531eae78a8fe26fdfb60271c97efb2dee5f47ef5a3c15c8228138927 -926c13efbe90604f6244be9315a34f72a1f8d1aab7572df431998949c378cddbf2fe393502c930fff614ff06ae98a0ce -995c758fd5600e6537089b1baa4fbe0376ab274ff3e82a17768b40df6f91c2e443411de9cafa1e65ea88fb8b87d504f4 -9245ba307a7a90847da75fca8d77ec03fdfc812c871e7a2529c56a0a79a6de16084258e7a9ac4ae8a3756f394336e21c -99e0cfa2bb57a7e624231317044c15e52196ecce020db567c8e8cb960354a0be9862ee0c128c60b44777e65ac315e59f -ad4f6b3d27bbbb744126601053c3dc98c07ff0eb0b38a898bd80dce778372846d67e5ab8fb34fb3ad0ef3f235d77ba7f -a0f12cae3722bbbca2e539eb9cc7614632a2aefe51410430070a12b5bc5314ecec5857b7ff8f41e9980cac23064f7c56 -b487f1bc59485848c98222fd3bc36c8c9bb3d2912e2911f4ceca32c840a7921477f9b1fe00877e05c96c75d3eecae061 -a6033db53925654e18ecb3ce715715c36165d7035db9397087ac3a0585e587998a53973d011ac6d48af439493029cee6 -a6b4d09cd01c70a3311fd131d3710ccf97bde3e7b80efd5a8c0eaeffeb48cca0f951ced905290267b115b06d46f2693b -a9dff1df0a8f4f218a98b6f818a693fb0d611fed0fc3143537cbd6578d479af13a653a8155e535548a2a0628ae24fa58 -a58e469f65d366b519f9a394cacb7edaddac214463b7b6d62c2dbc1316e11c6c5184ce45c16de2d77f990dcdd8b55430 -989e71734f8119103586dc9a3c5f5033ddc815a21018b34c1f876cdfc112efa868d5751bf6419323e4e59fa6a03ece1c -a2da00e05036c884369e04cf55f3de7d659cd5fa3f849092b2519dd263694efe0f051953d9d94b7e121f0aee8b6174d7 -968f3c029f57ee31c4e1adea89a7f92e28483af9a74f30fbdb995dc2d40e8e657dff8f8d340d4a92bf65f54440f2859f -932778df6f60ac1639c1453ef0cbd2bf67592759dcccb3e96dcc743ff01679e4c7dd0ef2b0833dda548d32cb4eba49e2 -a805a31139f8e0d6dae1ac87d454b23a3dc9fc653d4ca18d4f8ebab30fc189c16e73981c2cb7dd6f8c30454a5208109d -a9ba0991296caa2aaa4a1ceacfb205544c2a2ec97088eace1d84ee5e2767656a172f75d2f0c4e16a3640a0e0dec316e0 -b1e49055c968dced47ec95ae934cf45023836d180702e20e2df57e0f62fb85d7ac60d657ba3ae13b8560b67210449459 -a94e1da570a38809c71e37571066acabff7bf5632737c9ab6e4a32856924bf6211139ab3cedbf083850ff2d0e0c0fcfc -88ef1bb322000c5a5515b310c838c9af4c1cdbb32eab1c83ac3b2283191cd40e9573747d663763a28dad0d64adc13840 -a987ce205f923100df0fbd5a85f22c9b99b9b9cbe6ddfa8dfda1b8fe95b4f71ff01d6c5b64ca02eb24edb2b255a14ef0 -84fe8221a9e95d9178359918a108de4763ebfa7a6487facb9c963406882a08a9a93f492f8e77cf9e7ea41ae079c45993 -aa1cf3dc7c5dcfa15bbbc811a4bb6dbac4fba4f97fb1ed344ab60264d7051f6eef19ea9773441d89929ee942ed089319 -8f6a7d610d59d9f54689bbe6a41f92d9f6096cde919c1ab94c3c7fcecf0851423bc191e5612349e10f855121c0570f56 -b5af1fa7894428a53ea520f260f3dc3726da245026b6d5d240625380bfb9c7c186df0204bb604efac5e613a70af5106e -a5bce6055ff812e72ce105f147147c7d48d7a2313884dd1f488b1240ee320f13e8a33f5441953a8e7a3209f65b673ce1 -b9b55b4a1422677d95821e1d042ab81bbf0bf087496504021ec2e17e238c2ca6b44fb3b635a5c9eac0871a724b8d47c3 -941c38e533ce4a673a3830845b56786585e5fe49c427f2e5c279fc6db08530c8f91db3e6c7822ec6bb4f956940052d18 -a38e191d66c625f975313c7007bbe7431b5a06ed2da1290a7d5d0f2ec73770d476efd07b8e632de64597d47df175cbb0 -94ba76b667abf055621db4c4145d18743a368d951565632ed4e743dd50dd3333507c0c34f286a5c5fdbf38191a2255cd -a5ca38c60be5602f2bfa6e00c687ac96ac36d517145018ddbee6f12eb0faa63dd57909b9eeed26085fe5ac44e55d10ab -b00fea3b825e60c1ed1c5deb4b551aa65a340e5af36b17d5262c9cd2c508711e4dc50dc2521a2c16c7c901902266e64a -971b86fc4033485e235ccb0997a236206ba25c6859075edbcdf3c943116a5030b7f75ebca9753d863a522ba21a215a90 -b3b31f52370de246ee215400975b674f6da39b2f32514fe6bd54e747752eedca22bb840493b44a67df42a3639c5f901f -affbbfac9c1ba7cbfa1839d2ae271dd6149869b75790bf103230637da41857fc326ef3552ff31c15bda0694080198143 -a95d42aa7ef1962520845aa3688f2752d291926f7b0d73ea2ee24f0612c03b43f2b0fe3c9a9a99620ffc8d487b981bc2 -914a266065caf64985e8c5b1cb2e3f4e3fe94d7d085a1881b1fefa435afef4e1b39a98551d096a62e4f5cc1a7f0fdc2e -81a0b4a96e2b75bc1bf2dbd165d58d55cfd259000a35504d1ffb18bc346a3e6f07602c683723864ffb980f840836fd8d -91c1556631cddd4c00b65b67962b39e4a33429029d311c8acf73a18600e362304fb68bccb56fde40f49e95b7829e0b87 -8befbacc19e57f7c885d1b7a6028359eb3d80792fe13b92a8400df21ce48deb0bb60f2ddb50e3d74f39f85d7eab23adc -92f9458d674df6e990789690ec9ca73dacb67fc9255b58c417c555a8cc1208ace56e8e538f86ba0f3615573a0fbac00d -b4b1b3062512d6ae7417850c08c13f707d5838e43d48eb98dd4621baf62eee9e82348f80fe9b888a12874bfa538771f8 -a13c4a3ac642ede37d9c883f5319e748d2b938f708c9d779714108a449b343f7b71a6e3ef4080fee125b416762920273 -af44983d5fc8cceee0551ef934e6e653f2d3efa385e5c8a27a272463a6f333e290378cc307c2b664eb923c78994e706e -a389fd6c59fe2b4031cc244e22d3991e541bd203dd5b5e73a6159e72df1ab41d49994961500dcde7989e945213184778 -8d2141e4a17836c548de9598d7b298b03f0e6c73b7364979a411c464e0628e21cff6ac3d6decdba5d1c4909eff479761 -980b22ef53b7bdf188a3f14bc51b0dbfdf9c758826daa3cbc1e3986022406a8aa9a6a79e400567120b88c67faa35ce5f -a28882f0a055f96df3711de5d0aa69473e71245f4f3e9aa944e9d1fb166e02caa50832e46da6d3a03b4801735fd01b29 -8db106a37d7b88f5d995c126abb563934dd8de516af48e85695d02b1aea07f79217e3cdd03c6f5ca57421830186c772b -b5a7e50da0559a675c472f7dfaee456caab6695ab7870541b2be8c2b118c63752427184aad81f0e1afc61aef1f28c46f -9962118780e20fe291d10b64f28d09442a8e1b5cffd0f3dd68d980d0614050a626c616b44e9807fbee7accecae00686a -b38ddf33745e8d2ad6a991aefaf656a33c5f8cbe5d5b6b6fd03bd962153d8fd0e01b5f8f96d80ae53ab28d593ab1d4e7 -857dc12c0544ff2c0c703761d901aba636415dee45618aba2e3454ff9cbc634a85c8b05565e88520ff9be2d097c8b2b1 -a80d465c3f8cc63af6d74a6a5086b626c1cb4a8c0fee425964c3bd203d9d7094e299f81ce96d58afc20c8c9a029d9dae -89e1c8fbde8563763be483123a3ed702efac189c6d8ab4d16c85e74bbaf856048cc42d5d6e138633a38572ba5ec3f594 -893a594cf495535f6d216508f8d03c317dcf03446668cba688da90f52d0111ac83d76ad09bf5ea47056846585ee5c791 -aadbd8be0ae452f7f9450c7d2957598a20cbf10139a4023a78b4438172d62b18b0de39754dd2f8862dbd50a3a0815e53 -ae7d39670ecca3eb6db2095da2517a581b0e8853bdfef619b1fad9aacd443e7e6a40f18209fadd44038a55085c5fe8b2 -866ef241520eacb6331593cfcb206f7409d2f33d04542e6e52cba5447934e02d44c471f6c9a45963f9307e9809ab91d9 -b1a09911ad3864678f7be79a9c3c3eb5c84a0a45f8dcb52c67148f43439aeaaa9fd3ed3471276b7e588b49d6ebe3033a -add07b7f0dbb34049cd8feeb3c18da5944bf706871cfd9f14ff72f6c59ad217ebb1f0258b13b167851929387e4e34cfe -ae048892d5c328eefbdd4fba67d95901e3c14d974bfc0a1fc68155ca9f0d59e61d7ba17c6c9948b120cf35fd26e6fee9 -9185b4f3b7da0ddb4e0d0f09b8a9e0d6943a4611e43f13c3e2a767ed8592d31e0ba3ebe1914026a3627680274291f6e5 -a9c022d4e37b0802284ce3b7ee9258628ab4044f0db4de53d1c3efba9de19d15d65cc5e608dbe149c21c2af47d0b07b5 -b24dbd5852f8f24921a4e27013b6c3fa8885b973266cb839b9c388efad95821d5d746348179dcc07542bd0d0aefad1ce -b5fb4f279300876a539a27a441348764908bc0051ebd66dc51739807305e73db3d2f6f0f294ffb91b508ab150eaf8527 -ace50841e718265b290c3483ed4b0fdd1175338c5f1f7530ae9a0e75d5f80216f4de37536adcbc8d8c95982e88808cd0 -b19cadcde0f63bd1a9c24bd9c2806f53c14c0b9735bf351601498408ba503ddbd2037c891041cbba47f58b8c483f3b21 -b6061e63558d312eb891b97b39aa552fa218568d79ee26fe6dd5b864aea9e3216d8f2e2f3b093503be274766dac41426 -89730fdb2876ab6f0fe780d695f6e12090259027e789b819956d786e977518057e5d1d7f5ab24a3ae3d5d4c97773bd2b -b6fa841e81f9f2cad0163a02a63ae96dc341f7ae803b616efc6e1da2fbea551c1b96b11ad02c4afbdf6d0cc9f23da172 -8fb66187182629c861ddb6896d7ed3caf2ad050c3dba8ab8eb0d7a2c924c3d44c48d1a148f9e33fb1f061b86972f8d21 -86022ac339c1f84a7fa9e05358c1a5b316b4fc0b83dbe9c8c7225dc514f709d66490b539359b084ce776e301024345fa -b50b9c321468da950f01480bb62b6edafd42f83c0001d6e97f2bd523a1c49a0e8574fb66380ea28d23a7c4d54784f9f0 -a31c05f7032f30d1dac06678be64d0250a071fd655e557400e4a7f4c152be4d5c7aa32529baf3e5be7c4bd49820054f6 -b95ac0848cd322684772119f5b682d90a66bbf9dac411d9d86d2c34844bbd944dbaf8e47aa41380455abd51687931a78 -ae4a6a5ce9553b65a05f7935e61e496a4a0f6fd8203367a2c627394c9ce1e280750297b74cdc48fd1d9a31e93f97bef4 -a22daf35f6e9b05e52e0b07f7bd1dbbebd2c263033fb0e1b2c804e2d964e2f11bc0ece6aca6af079dd3a9939c9c80674 -902150e0cb1f16b9b59690db35281e28998ce275acb313900da8b2d8dfd29fa1795f8ca3ff820c31d0697de29df347c1 -b17b5104a5dc665cdd7d47e476153d715eb78c6e5199303e4b5445c21a7fa7cf85fe7cfd08d7570f4e84e579b005428c -a03f49b81c15433f121680aa02d734bb9e363af2156654a62bcb5b2ba2218398ccb0ff61104ea5d7df5b16ea18623b1e -802101abd5d3c88876e75a27ffc2f9ddcce75e6b24f23dba03e5201281a7bd5cc7530b6a003be92d225093ca17d3c3bb -a4d183f63c1b4521a6b52226fc19106158fc8ea402461a5cccdaa35fee93669df6a8661f45c1750cd01308149b7bf08e -8d17c22e0c8403b69736364d460b3014775c591032604413d20a5096a94d4030d7c50b9fe3240e31d0311efcf9816a47 -947225acfcce5992eab96276f668c3cbe5f298b90a59f2bb213be9997d8850919e8f496f182689b5cbd54084a7332482 -8df6f4ed216fc8d1905e06163ba1c90d336ab991a18564b0169623eb39b84e627fa267397da15d3ed754d1f3423bff07 -83480007a88f1a36dea464c32b849a3a999316044f12281e2e1c25f07d495f9b1710b4ba0d88e9560e72433addd50bc2 -b3019d6e591cf5b33eb972e49e06c6d0a82a73a75d78d383dd6f6a4269838289e6e07c245f54fed67f5c9bb0fd5e1c5f -92e8ce05e94927a9fb02debadb99cf30a26172b2705003a2c0c47b3d8002bf1060edb0f6a5750aad827c98a656b19199 -ac2aff801448dbbfc13cca7d603fd9c69e82100d997faf11f465323b97255504f10c0c77401e4d1890339d8b224f5803 -b0453d9903d08f508ee27e577445dc098baed6cde0ac984b42e0f0efed62760bd58d5816cf1e109d204607b7b175e30c -ae68dc4ba5067e825d46d2c7c67f1009ceb49d68e8d3e4c57f4bcd299eb2de3575d42ea45e8722f8f28497a6e14a1cfe -b22486c2f5b51d72335ce819bbafb7fa25eb1c28a378a658f13f9fc79cd20083a7e573248d911231b45a5cf23b561ca7 -89d1201d1dbd6921867341471488b4d2fd0fc773ae1d4d074c78ae2eb779a59b64c00452c2a0255826fca6b3d03be2b1 -a2998977c91c7a53dc6104f5bc0a5b675e5350f835e2f0af69825db8af4aeb68435bdbcc795f3dd1f55e1dd50bc0507f -b0be4937a925b3c05056ed621910d535ccabf5ab99fd3b9335080b0e51d9607d0fd36cb5781ff340018f6acfca4a9736 -aea145a0f6e0ba9df8e52e84bb9c9de2c2dc822f70d2724029b153eb68ee9c17de7d35063dcd6a39c37c59fdd12138f7 -91cb4545d7165ee8ffbc74c874baceca11fdebbc7387908d1a25877ca3c57f2c5def424dab24148826832f1e880bede0 -b3b579cb77573f19c571ad5eeeb21f65548d7dff9d298b8d7418c11f3e8cd3727c5b467f013cb87d6861cfaceee0d2e3 -b98a1eeec2b19fecc8378c876d73645aa52fb99e4819903735b2c7a885b242787a30d1269a04bfb8573d72d9bbc5f0f0 -940c1f01ed362bd588b950c27f8cc1d52276c71bb153d47f07ec85b038c11d9a8424b7904f424423e714454d5e80d1cd -aa343a8ecf09ce11599b8cf22f7279cf80f06dbf9f6d62cb05308dbbb39c46fd0a4a1240b032665fbb488a767379b91b -87c3ac72084aca5974599d3232e11d416348719e08443acaba2b328923af945031f86432e170dcdd103774ec92e988c9 -91d6486eb5e61d2b9a9e742c20ec974a47627c6096b3da56209c2b4e4757f007e793ebb63b2b246857c9839b64dc0233 -aebcd3257d295747dd6fc4ff910d839dd80c51c173ae59b8b2ec937747c2072fa85e3017f9060aa509af88dfc7529481 -b3075ba6668ca04eff19efbfa3356b92f0ab12632dcda99cf8c655f35b7928c304218e0f9799d68ef9f809a1492ff7db -93ba7468bb325639ec2abd4d55179c69fd04eaaf39fc5340709227bbaa4ad0a54ea8b480a1a3c8d44684e3be0f8d1980 -a6aef86c8c0d92839f38544d91b767c582568b391071228ff5a5a6b859c87bf4f81a7d926094a4ada1993ddbd677a920 -91dcd6d14207aa569194aa224d1e5037b999b69ade52843315ca61ba26abe9a76412c9e88259bc5cf5d7b95b97d9c3bc -b3b483d31c88f78d49bd065893bc1e3d2aa637e27dedb46d9a7d60be7660ce7a10aaaa7deead362284a52e6d14021178 -8e5730070acf8371461ef301cc4523e8e672aa0e3d945d438a0e0aa6bdf8cb9c685dcf38df429037b0c8aff3955c6f5b -b8c6d769890a8ee18dc4f9e917993315877c97549549b34785a92543cbeec96a08ae3a28d6e809c4aacd69de356c0012 -95ca86cd384eaceaa7c077c5615736ca31f36824bd6451a16142a1edc129fa42b50724aeed7c738f08d7b157f78b569e -94df609c6d71e8eee7ab74226e371ccc77e01738fe0ef1a6424435b4570fe1e5d15797b66ed0f64eb88d4a3a37631f0e -89057b9783212add6a0690d6bb99097b182738deff2bd9e147d7fd7d6c8eacb4c219923633e6309ad993c24572289901 -83a0f9f5f265c5a0e54defa87128240235e24498f20965009fef664f505a360b6fb4020f2742565dfc7746eb185bcec0 -91170da5306128931349bc3ed50d7df0e48a68b8cc8420975170723ac79d8773e4fa13c5f14dc6e3fafcad78379050b1 -b7178484d1b55f7e56a4cc250b6b2ec6040437d96bdfddfa7b35ed27435860f3855c2eb86c636f2911b012eb83b00db8 -ac0b00c4322d1e4208e09cd977b4e54d221133ff09551f75b32b0b55d0e2be80941dda26257b0e288c162e63c7e9cf68 -9690ed9e7e53ed37ff362930e4096b878b12234c332fd19d5d064824084245952eda9f979e0098110d6963e468cf513e -b6fa547bb0bb83e5c5be0ed462a8783fba119041c136a250045c09d0d2af330c604331e7de960df976ff76d67f8000cd -814603907c21463bcf4e59cfb43066dfe1a50344ae04ef03c87c0f61b30836c3f4dea0851d6fa358c620045b7f9214c8 -9495639e3939fad2a3df00a88603a5a180f3c3a0fe4d424c35060e2043e0921788003689887b1ed5be424d9a89bb18bb -aba4c02d8d57f2c92d5bc765885849e9ff8393d6554f5e5f3e907e5bfac041193a0d8716d7861104a4295d5a03c36b03 -8ead0b56c1ca49723f94a998ba113b9058059321da72d9e395a667e6a63d5a9dac0f5717cec343f021695e8ced1f72af -b43037f7e3852c34ed918c5854cd74e9d5799eeddfe457d4f93bb494801a064735e326a76e1f5e50a339844a2f4a8ec9 -99db8422bb7302199eb0ff3c3d08821f8c32f53a600c5b6fb43e41205d96adae72be5b460773d1280ad1acb806af9be8 -8a9be08eae0086c0f020838925984df345c5512ff32e37120b644512b1d9d4fecf0fd30639ca90fc6cf334a86770d536 -81b43614f1c28aa3713a309a88a782fb2bdfc4261dd52ddc204687791a40cf5fd6a263a8179388596582cccf0162efc2 -a9f3a8b76912deb61d966c75daf5ddb868702ebec91bd4033471c8e533183df548742a81a2671de5be63a502d827437d -902e2415077f063e638207dc7e14109652e42ab47caccd6204e2870115791c9defac5425fd360b37ac0f7bd8fe7011f8 -aa18e4fdc1381b59c18503ae6f6f2d6943445bd00dd7d4a2ad7e5adad7027f2263832690be30d456e6d772ad76f22350 -a348b40ba3ba7d81c5d4631f038186ebd5e5f314f1ea737259151b07c3cc8cf0c6ed4201e71bcc1c22fefda81a20cde6 -aa1306f7ac1acbfc47dc6f7a0cb6d03786cec8c8dc8060388ccda777bca24bdc634d03e53512c23dba79709ff64f8620 -818ccfe46e700567b7f3eb400e5a35f6a5e39b3db3aa8bc07f58ace35d9ae5a242faf8dbccd08d9a9175bbce15612155 -b7e3da2282b65dc8333592bb345a473f03bd6df69170055fec60222de9897184536bf22b9388b08160321144d0940279 -a4d976be0f0568f4e57de1460a1729129252b44c552a69fceec44e5b97c96c711763360d11f9e5bf6d86b4976bf40d69 -85d185f0397c24c2b875b09b6328a23b87982b84ee880f2677a22ff4c9a1ba9f0fea000bb3f7f66375a00d98ebafce17 -b4ccbb8c3a2606bd9b87ce022704663af71d418351575f3b350d294f4efc68c26f9a2ce49ff81e6ff29c3b63d746294e -93ffd3265fddb63724dfde261d1f9e22f15ecf39df28e4d89e9fea03221e8e88b5dd9b77628bacaa783c6f91802d47cc -b1fd0f8d7a01378e693da98d03a2d2fda6b099d03454b6f2b1fa6472ff6bb092751ce6290059826b74ac0361eab00e1e -a89f440c71c561641589796994dd2769616b9088766e983c873fae0716b95c386c8483ab8a4f367b6a68b72b7456dd32 -af4fe92b01d42d03dd5d1e7fa55e96d4bbcb7bf7d4c8c197acd16b3e0f3455807199f683dcd263d74547ef9c244b35cc -a8227f6e0a344dfe76bfbe7a1861be32c4f4bed587ccce09f9ce2cf481b2dda8ae4f566154bc663d15f962f2d41761bd -a7b361663f7495939ed7f518ba45ea9ff576c4e628995b7aea026480c17a71d63fc2c922319f0502eb7ef8f14a406882 -8ddcf382a9f39f75777160967c07012cfa89e67b19714a7191f0c68eaf263935e5504e1104aaabd0899348c972a8d3c6 -98c95b9f6f5c91f805fb185eedd06c6fc4457d37dd248d0be45a6a168a70031715165ea20606245cbdf8815dc0ac697f -805b44f96e001e5909834f70c09be3efcd3b43632bcac5b6b66b6d227a03a758e4b1768ce2a723045681a1d34562aaeb -b0e81b07cdc45b3dca60882676d9badb99f25c461b7efe56e3043b80100bb62d29e1873ae25eb83087273160ece72a55 -b0c53f0abe78ee86c7b78c82ae1f7c070bb0b9c45c563a8b3baa2c515d482d7507bb80771e60b38ac13f78b8af92b4a9 -a7838ef6696a9e4d2e5dfd581f6c8d6a700467e8fd4e85adabb5f7a56f514785dd4ab64f6f1b48366f7d94728359441b -88c76f7700a1d23c30366a1d8612a796da57b2500f97f88fdf2d76b045a9d24e7426a8ffa2f4e86d3046937a841dad58 -ad8964baf98c1f02e088d1d9fcb3af6b1dfa44cdfe0ed2eae684e7187c33d3a3c28c38e8f4e015f9c04d451ed6f85ff6 -90e9d00a098317ececaa9574da91fc149eda5b772dedb3e5a39636da6603aa007804fa86358550cfeff9be5a2cb7845e -a56ff4ddd73d9a6f5ab23bb77efa25977917df63571b269f6a999e1ad6681a88387fcc4ca3b26d57badf91b236503a29 -97ad839a6302c410a47e245df84c01fb9c4dfef86751af3f9340e86ff8fc3cd52fa5ff0b9a0bd1d9f453e02ca80658a6 -a4c8c44cbffa804129e123474854645107d1f0f463c45c30fd168848ebea94880f7c0c5a45183e9eb837f346270bdb35 -a72e53d0a1586d736e86427a93569f52edd2f42b01e78aee7e1961c2b63522423877ae3ac1227a2cf1e69f8e1ff15bc3 -8559f88a7ef13b4f09ac82ae458bbae6ab25671cfbf52dae7eac7280d6565dd3f0c3286aec1a56a8a16dc3b61d78ce47 -8221503f4cdbed550876c5dc118a3f2f17800c04e8be000266633c83777b039a432d576f3a36c8a01e8fd18289ebc10b -99bfbe5f3e46d4d898a578ba86ed26de7ed23914bd3bcdf3c791c0bcd49398a52419077354a5ab75cea63b6c871c6e96 -aa134416d8ff46f2acd866c1074af67566cfcf4e8be8d97329dfa0f603e1ff208488831ce5948ac8d75bfcba058ddcaa -b02609d65ebfe1fe8e52f21224a022ea4b5ea8c1bd6e7b9792eed8975fc387cdf9e3b419b8dd5bcce80703ab3a12a45f -a4f14798508698fa3852e5cac42a9db9797ecee7672a54988aa74037d334819aa7b2ac7b14efea6b81c509134a6b7ad2 -884f01afecbcb987cb3e7c489c43155c416ed41340f61ecb651d8cba884fb9274f6d9e7e4a46dd220253ae561614e44c -a05523c9e71dce1fe5307cc71bd721feb3e1a0f57a7d17c7d1c9fb080d44527b7dbaa1f817b1af1c0b4322e37bc4bb1e -8560aec176a4242b39f39433dd5a02d554248c9e49d3179530815f5031fee78ba9c71a35ceeb2b9d1f04c3617c13d8f0 -996aefd402748d8472477cae76d5a2b92e3f092fc834d5222ae50194dd884c9fb8b6ed8e5ccf8f6ed483ddbb4e80c747 -8fd09900320000cbabc40e16893e2fcf08815d288ec19345ad7b6bb22f7d78a52b6575a3ca1ca2f8bc252d2eafc928ec -939e51f73022bc5dc6862a0adf8fb8a3246b7bfb9943cbb4b27c73743926cc20f615a036c7e5b90c80840e7f1bfee0e7 -a0a6258700cadbb9e241f50766573bf9bdb7ad380b1079dc3afb4054363d838e177b869cad000314186936e40359b1f2 -972699a4131c8ed27a2d0e2104d54a65a7ff1c450ad9da3a325c662ab26869c21b0a84d0700b98c8b5f6ce3b746873d7 -a454c7fe870cb8aa6491eafbfb5f7872d6e696033f92e4991d057b59d70671f2acdabef533e229878b60c7fff8f748b1 -a167969477214201f09c79027b10221e4707662e0c0fde81a0f628249f2f8a859ce3d30a7dcc03b8ecca8f7828ad85c7 -8ff6b7265175beb8a63e1dbf18c9153fb2578c207c781282374f51b40d57a84fd2ef2ea2b9c6df4a54646788a62fd17f -a3d7ebeccde69d73d8b3e76af0da1a30884bb59729503ff0fb0c3bccf9221651b974a6e72ea33b7956fc3ae758226495 -b71ef144c9a98ce5935620cb86c1590bd4f48e5a2815d25c0cdb008fde628cf628c31450d3d4f67abbfeb16178a74cfd -b5e0a16d115134f4e2503990e3f2035ed66b9ccf767063fe6747870d97d73b10bc76ed668550cb82eedc9a2ca6f75524 -b30ffaaf94ee8cbc42aa2c413175b68afdb207dbf351fb20be3852cb7961b635c22838da97eaf43b103aff37e9e725cc -98aa7d52284f6c1f22e272fbddd8c8698cf8f5fbb702d5de96452141fafb559622815981e50b87a72c2b1190f59a7deb -81fbacda3905cfaf7780bb4850730c44166ed26a7c8d07197a5d4dcd969c09e94a0461638431476c16397dd7bdc449f9 -95e47021c1726eac2e5853f570d6225332c6e48e04c9738690d53e07c6b979283ebae31e2af1fc9c9b3e59f87e5195b1 -ac024a661ba568426bb8fce21780406537f518075c066276197300841e811860696f7588188bc01d90bace7bc73d56e3 -a4ebcaf668a888dd404988ab978594dee193dad2d0aec5cdc0ccaf4ec9a7a8228aa663db1da8ddc52ec8472178e40c32 -a20421b8eaf2199d93b083f2aff37fb662670bd18689d046ae976d1db1fedd2c2ff897985ecc6277b396db7da68bcb27 -8bc33d4b40197fd4d49d1de47489d10b90d9b346828f53a82256f3e9212b0cbc6930b895e879da9cec9fedf026aadb3e -aaafdd1bec8b757f55a0433eddc0a39f818591954fd4e982003437fcceb317423ad7ee74dbf17a2960380e7067a6b4e2 -aad34277ebaed81a6ec154d16736866f95832803af28aa5625bf0461a71d02b1faba02d9d9e002be51c8356425a56867 -976e9c8b150d08706079945bd0e84ab09a648ecc6f64ded9eb5329e57213149ae409ae93e8fbd8eda5b5c69f5212b883 -8097fae1653247d2aed4111533bc378171d6b2c6d09cbc7baa9b52f188d150d645941f46d19f7f5e27b7f073c1ebd079 -83905f93b250d3184eaba8ea7d727c4464b6bdb027e5cbe4f597d8b9dc741dcbea709630bd4fd59ce24023bec32fc0f3 -8095030b7045cff28f34271386e4752f9a9a0312f8df75de4f424366d78534be2b8e1720a19cb1f9a2d21105d790a225 -a7b7b73a6ae2ed1009c49960374b0790f93c74ee03b917642f33420498c188a169724945a975e5adec0a1e83e07fb1b2 -856a41c54df393b6660b7f6354572a4e71c8bfca9cabaffb3d4ef2632c015e7ee2bc10056f3eccb3dbed1ad17d939178 -a8f7a55cf04b38cd4e330394ee6589da3a07dc9673f74804fdf67b364e0b233f14aec42e783200a2e4666f7c5ff62490 -82c529f4e543c6bca60016dc93232c115b359eaee2798a9cf669a654b800aafe6ab4ba58ea8b9cdda2b371c8d62fa845 -8caab020c1baddce77a6794113ef1dfeafc5f5000f48e97f4351b588bf02f1f208101745463c480d37f588d5887e6d8c -8fa91b3cc400f48b77b6fd77f3b3fbfb3f10cdff408e1fd22d38f77e087b7683adad258804409ba099f1235b4b4d6fea -8aa02787663d6be9a35677d9d8188b725d5fcd770e61b11b64e3def8808ea5c71c0a9afd7f6630c48634546088fcd8e2 -b5635b7b972e195cab878b97dea62237c7f77eb57298538582a330b1082f6207a359f2923864630136d8b1f27c41b9aa -8257bb14583551a65975946980c714ecd6e5b629672bb950b9caacd886fbd22704bc9e3ba7d30778adab65dc74f0203a -ab5fe1cd12634bfa4e5c60d946e2005cbd38f1063ec9a5668994a2463c02449a0a185ef331bd86b68b6e23a8780cb3ba -a7d3487da56cda93570cc70215d438204f6a2709bfb5fda6c5df1e77e2efc80f4235c787e57fbf2c74aaff8cbb510a14 -b61cff7b4c49d010e133319fb828eb900f8a7e55114fc86b39c261a339c74f630e1a7d7e1350244ada566a0ff3d46c4b -8d4d1d55d321d278db7a85522ccceca09510374ca81d4d73e3bb5249ace7674b73900c35a531ec4fa6448fabf7ad00dc -966492248aee24f0f56c8cfca3c8ec6ba3b19abb69ae642041d4c3be8523d22c65c4dafcab4c58989ccc4e0bd2f77919 -b20c320a90cb220b86e1af651cdc1e21315cd215da69f6787e28157172f93fc8285dcd59b039c626ed8ca4633cba1a47 -aae9e6b22f018ceb5c0950210bb8182cb8cb61014b7e14581a09d36ebd1bbfebdb2b82afb7fdb0cf75e58a293d9c456d -875547fb67951ad37b02466b79f0c9b985ccbc500cfb431b17823457dc79fb9597ec42cd9f198e15523fcd88652e63a4 -92afce49773cb2e20fb21e4f86f18e0959ebb9c33361547ddb30454ee8e36b1e234019cbdca0e964cb292f7f77df6b90 -8af85343dfe1821464c76ba11c216cbef697b5afc69c4d821342e55afdac047081ec2e3f7b09fc14b518d9a23b78c003 -b7de4a1648fd63f3a918096ea669502af5357438e69dac77cb8102b6e6c15c76e033cfaa80dafc806e535ede5c1a20aa -ac80e9b545e8bd762951d96c9ce87f629d01ffcde07efc2ef7879ca011f1d0d8a745abf26c9d452541008871304fac00 -a4cf0f7ed724e481368016c38ea5816698a5f68eb21af4d3c422d2ba55f96a33e427c2aa40de1b56a7cfac7f7cf43ab0 -899b0a678bb2db2cae1b44e75a661284844ebcdd87abf308fedeb2e4dbe5c5920c07db4db7284a7af806a2382e8b111a -af0588a2a4afce2b1b13c1230816f59e8264177e774e4a341b289a101dcf6af813638fed14fb4d09cb45f35d5d032609 -a4b8df79e2be76e9f5fc5845f06fe745a724cf37c82fcdb72719b77bdebea3c0e763f37909373e3a94480cc5e875cba0 -83e42c46d88930c8f386b19fd999288f142d325e2ebc86a74907d6d77112cb0d449bc511c95422cc810574031a8cbba9 -b5e39534070de1e5f6e27efbdd3dc917d966c2a9b8cf2d893f964256e95e954330f2442027dc148c776d63a95bcde955 -958607569dc28c075e658cd4ae3927055c6bc456eef6212a6fea8205e48ed8777a8064f584cda38fe5639c371e2e7fba -812adf409fa63575113662966f5078a903212ffb65c9b0bbe62da0f13a133443a7062cb8fd70f5e5dd5559a32c26d2c8 -a679f673e5ce6a3cce7fa31f22ee3785e96bcb55e5a776e2dd3467bef7440e3555d1a9b87cb215e86ee9ed13a090344b -afedbb34508b159eb25eb2248d7fe328f86ef8c7d84c62d5b5607d74aae27cc2cc45ee148eb22153b09898a835c58df4 -b75505d4f6b67d31e665cfaf5e4acdb5838ae069166b7fbcd48937c0608a59e40a25302fcc1873d2e81c1782808c70f0 -b62515d539ec21a155d94fc00ea3c6b7e5f6636937bce18ed5b618c12257fb82571886287fd5d1da495296c663ebc512 -ab8e1a9446bbdd588d1690243b1549d230e6149c28f59662b66a8391a138d37ab594df38e7720fae53217e5c3573b5be -b31e8abf4212e03c3287bb2c0a153065a7290a16764a0bac8f112a72e632185a654bb4e88fdd6053e6c7515d9719fadb -b55165477fe15b6abd2d0f4fddaa9c411710dcc4dd712daba3d30e303c9a3ee5415c256f9dc917ecf18c725b4dbab059 -a0939d4f57cacaae549b78e87cc234de4ff6a35dc0d9cd5d7410abc30ebcd34c135e008651c756e5a9d2ca79c40ef42b -8cf10e50769f3443340844aad4d56ec790850fed5a41fcbd739abac4c3015f0a085a038fbe7fae9f5ad899cce5069f6b -924055e804d82a99ea4bb160041ea4dc14b568abf379010bc1922fde5d664718c31d103b8b807e3a1ae809390e708c73 -8ec0f9d26f71b0f2e60a179e4fd1778452e2ffb129d50815e5d7c7cb9415fa69ae5890578086e8ef6bfde35ad2a74661 -98c7f12b15ec4426b59f737f73bf5faea4572340f4550b7590dfb7f7ffedb2372e3e555977c63946d579544c53210ad0 -8a935f7a955c78f69d66f18eee0092e5e833fa621781c9581058e219af4d7ceee48b84e472e159dda6199715fb2f9acf -b78d4219f95a2dbfaa7d0c8a610c57c358754f4f43c2af312ab0fe8f10a5f0177e475332fb8fd23604e474fc2abeb051 -8d086a14803392b7318c28f1039a17e3cfdcece8abcaca3657ec3d0ac330842098a85c0212f889fabb296dfb133ce9aa -a53249f417aac82f2c2a50c244ce21d3e08a5e5a8bd33bec2a5ab0d6cd17793e34a17edfa3690899244ce201e2fb9986 -8619b0264f9182867a1425be514dc4f1ababc1093138a728a28bd7e4ecc99b9faaff68c23792264bc6e4dce5f52a5c52 -8c171edbbbde551ec19e31b2091eb6956107dd9b1f853e1df23bff3c10a3469ac77a58335eee2b79112502e8e163f3de -a9d19ec40f0ca07c238e9337c6d6a319190bdba2db76fb63902f3fb459aeeb50a1ac30db5b25ee1b4201f3ca7164a7f4 -b9c6ec14b1581a03520b8d2c1fbbc31fb8ceaef2c0f1a0d0080b6b96e18442f1734bea7ef7b635d787c691de4765d469 -8cb437beb4cfa013096f40ccc169a713dc17afee6daa229a398e45fd5c0645a9ad2795c3f0cd439531a7151945d7064d -a6e8740cc509126e146775157c2eb278003e5bb6c48465c160ed27888ca803fa12eee1f6a8dd7f444f571664ed87fdc1 -b75c1fecc85b2732e96b3f23aefb491dbd0206a21d682aee0225838dc057d7ed3b576176353e8e90ae55663f79e986e4 -ad8d249b0aea9597b08358bce6c77c1fd552ef3fbc197d6a1cfe44e5e6f89b628b12a6fb04d5dcfcbacc51f46e4ae7bb -b998b2269932cbd58d04b8e898d373ac4bb1a62e8567484f4f83e224061bc0f212459f1daae95abdbc63816ae6486a55 -827988ef6c1101cddc96b98f4a30365ff08eea2471dd949d2c0a9b35c3bbfa8c07054ad1f4c88c8fbf829b20bb5a9a4f -8692e638dd60babf7d9f2f2d2ce58e0ac689e1326d88311416357298c6a2bffbfebf55d5253563e7b3fbbf5072264146 -a685d75b91aea04dbc14ab3c1b1588e6de96dae414c8e37b8388766029631b28dd860688079b12d09cd27f2c5af11adf -b57eced93eec3371c56679c259b34ac0992286be4f4ff9489d81cf9712403509932e47404ddd86f89d7c1c3b6391b28c -a1c8b4e42ebcbd8927669a97f1b72e236fb19249325659e72be7ddaaa1d9e81ca2abb643295d41a8c04a2c01f9c0efd7 -877c33de20d4ed31674a671ba3e8f01a316581e32503136a70c9c15bf0b7cb7b1cba6cd4eb641fad165fb3c3c6c235fd -a2a469d84ec478da40838f775d11ad38f6596eb41caa139cc190d6a10b5108c09febae34ffdafac92271d2e73c143693 -972f817caedb254055d52e963ed28c206848b6c4cfdb69dbc961c891f8458eaf582a6d4403ce1177d87bc2ea410ef60a -accbd739e138007422f28536381decc54bb6bd71d93edf3890e54f9ef339f83d2821697d1a4ac1f5a98175f9a9ecb9b5 -8940f8772e05389f823b62b3adc3ed541f91647f0318d7a0d3f293aeeb421013de0d0a3664ea53dd24e5fbe02d7efef6 -8ecce20f3ef6212edef07ec4d6183fda8e0e8cad2c6ccd0b325e75c425ee1faba00b5c26b4d95204238931598d78f49d -97cc72c36335bd008afbed34a3b0c7225933faba87f7916d0a6d2161e6f82e0cdcda7959573a366f638ca75d30e9dab1 -9105f5de8699b5bdb6bd3bb6cc1992d1eac23929c29837985f83b22efdda92af64d9c574aa9640475087201bbbe5fd73 -8ffb33c4f6d05c413b9647eb6933526a350ed2e4278ca2ecc06b0e8026d8dbe829c476a40e45a6df63a633090a3f82ef -8bfc6421fdc9c2d2aaa68d2a69b1a2728c25b84944cc3e6a57ff0c94bfd210d1cbf4ff3f06702d2a8257024d8be7de63 -a80e1dc1dddfb41a70220939b96dc6935e00b32fb8be5dff4eed1f1c650002ff95e4af481c43292e3827363b7ec4768a -96f714ebd54617198bd636ba7f7a7f8995a61db20962f2165078d9ed8ee764d5946ef3cbdc7ebf8435bb8d5dd4c1deac -8cdb0890e33144d66391d2ae73f5c71f5a861f72bc93bff6cc399fc25dd1f9e17d8772592b44593429718784802ac377 -8ccf9a7f80800ee770b92add734ed45a73ecc31e2af0e04364eefc6056a8223834c7c0dc9dfc52495bdec6e74ce69994 -aa0875f423bd68b5f10ba978ddb79d3b96ec093bfbac9ff366323193e339ed7c4578760fb60f60e93598bdf1e5cc4995 -a9214f523957b59c7a4cb61a40251ad72aba0b57573163b0dc0f33e41d2df483fb9a1b85a5e7c080e9376c866790f8cb -b6224b605028c6673a536cc8ff9aeb94e7a22e686fda82cf16068d326469172f511219b68b2b3affb7933af0c1f80d07 -b6d58968d8a017c6a34e24c2c09852f736515a2c50f37232ac6b43a38f8faa7572cc31dade543b594b61b5761c4781d0 -8a97cefe5120020c38deeb861d394404e6c993c6cbd5989b6c9ebffe24f46ad11b4ba6348e2991cbf3949c28cfc3c99d -95bf046f8c3a9c0ce2634be4de3713024daec3fc4083e808903b25ce3ac971145af90686b451efcc72f6b22df0216667 -a6a4e2f71b8fa28801f553231eff2794c0f10d12e7e414276995e21195abc9c2983a8997e41af41e78d19ff6fbb2680b -8e5e62a7ca9c2f58ebaab63db2ff1fb1ff0877ae94b7f5e2897f273f684ae639dff44cc65718f78a9c894787602ab26a -8542784383eec4f565fcb8b9fc2ad8d7a644267d8d7612a0f476fc8df3aff458897a38003d506d24142ad18f93554f2b -b7db68ba4616ea072b37925ec4fb39096358c2832cc6d35169e032326b2d6614479f765ae98913c267105b84afcb9bf2 -8b31dbb9457d23d416c47542c786e07a489af35c4a87dadb8ee91bea5ac4a5315e65625d78dad2cf8f9561af31b45390 -a8545a1d91ac17257732033d89e6b7111db8242e9c6ebb0213a88906d5ef407a2c6fdb444e29504b06368b6efb4f4839 -b1bd85d29ebb28ccfb05779aad8674906b267c2bf8cdb1f9a0591dd621b53a4ee9f2942687ee3476740c0b4a7621a3ae -a2b54534e152e46c50d91fff03ae9cd019ff7cd9f4168b2fe7ac08ef8c3bbc134cadd3f9d6bd33d20ae476c2a8596c8a -b19b571ff4ae3e9f5d95acda133c455e72c9ea9973cae360732859836c0341c4c29ab039224dc5bc3deb824e031675d8 -940b5f80478648bac025a30f3efeb47023ce20ee98be833948a248bca6979f206bb28fc0f17b90acf3bb4abd3d14d731 -8f106b40588586ac11629b96d57808ad2808915d89539409c97414aded90b4ff23286a692608230a52bff696055ba5d6 -ae6bda03aa10da3d2abbc66d764ca6c8d0993e7304a1bdd413eb9622f3ca1913baa6da1e9f4f9e6cf847f14f44d6924d -a18e7796054a340ef826c4d6b5a117b80927afaf2ebd547794c400204ae2caf277692e2eabb55bc2f620763c9e9da66d -8d2d25180dc2c65a4844d3e66819ccfcf48858f0cc89e1c77553b463ec0f7feb9a4002ce26bc618d1142549b9850f232 -863f413a394de42cc8166c1c75d513b91d545fff1de6b359037a742c70b008d34bf8e587afa2d62c844d0c6f0ea753e7 -83cd0cf62d63475e7fcad18a2e74108499cdbf28af2113cfe005e3b5887794422da450b1944d0a986eb7e1f4c3b18f25 -b4f8b350a6d88fea5ab2e44715a292efb12eb52df738c9b2393da3f1ddee68d0a75b476733ccf93642154bceb208f2b8 -b3f52aaa4cd4221cb9fc45936cc67fd3864bf6d26bf3dd86aa85aa55ecfc05f5e392ecce5e7cf9406b4b1c4fce0398c8 -b33137084422fb643123f40a6df2b498065e65230fc65dc31791c330e898c51c3a65ff738930f32c63d78f3c9315f85b -91452bfa75019363976bb7337fe3a73f1c10f01637428c135536b0cdc7da5ce558dae3dfc792aa55022292600814a8ef -ad6ba94c787cd4361ca642c20793ea44f1f127d4de0bb4a77c7fbfebae0fcadbf28e2cb6f0c12c12a07324ec8c19761d -890aa6248b17f1501b0f869c556be7bf2b1d31a176f9978bb97ab7a6bd4138eed32467951c5ef1871944b7f620542f43 -82111db2052194ee7dd22ff1eafffac0443cf969d3762cceae046c9a11561c0fdce9c0711f88ac01d1bed165f8a7cee3 -b1527b71df2b42b55832f72e772a466e0fa05743aacc7814f4414e4bcc8d42a4010c9e0fd940e6f254cafedff3cd6543 -922370fa49903679fc565f09c16a5917f8125e72acfeb060fcdbadbd1644eb9f4016229756019c93c6d609cda5d5d174 -aa4c7d98a96cab138d2a53d4aee8ebff6ef903e3b629a92519608d88b3bbd94de5522291a1097e6acf830270e64c8ee1 -b3dc21608a389a72d3a752883a382baaafc61ecc44083b832610a237f6a2363f24195acce529eb4aed4ef0e27a12b66e -94619f5de05e07b32291e1d7ab1d8b7337a2235e49d4fb5f3055f090a65e932e829efa95db886b32b153bdd05a53ec8c -ade1e92722c2ffa85865d2426fb3d1654a16477d3abf580cfc45ea4b92d5668afc9d09275d3b79283e13e6b39e47424d -b7201589de7bed094911dd62fcd25c459a8e327ac447b69f541cdba30233063e5ddffad0b67e9c3e34adcffedfd0e13d -809d325310f862d6549e7cb40f7e5fc9b7544bd751dd28c4f363c724a0378c0e2adcb5e42ec8f912f5f49f18f3365c07 -a79c20aa533de7a5d671c99eb9eb454803ba54dd4f2efa3c8fec1a38f8308e9905c71e9282955225f686146388506ff6 -a85eeacb5e8fc9f3ed06a3fe2dc3108ab9f8c5877b148c73cf26e4e979bf5795edbe2e63a8d452565fd1176ed40402b2 -97ef55662f8a1ec0842b22ee21391227540adf7708f491436044f3a2eb18c471525e78e1e14fa292507c99d74d7437c6 -93110d64ed5886f3d16ce83b11425576a3a7a9bb831cd0de3f9a0b0f2270a730d68136b4ef7ff035ede004358f419b5c -ac9ed0a071517f0ae4f61ce95916a90ba9a77a3f84b0ec50ef7298acdcd44d1b94525d191c39d6bd1bb68f4471428760 -98abd6a02c7690f5a339adf292b8c9368dfc12e0f8069cf26a5e0ce54b4441638f5c66ea735142f3c28e00a0024267e6 -b51efb73ba6d44146f047d69b19c0722227a7748b0e8f644d0fc9551324cf034c041a2378c56ce8b58d06038fb8a78de -8f115af274ef75c1662b588b0896b97d71f8d67986ae846792702c4742ab855952865ce236b27e2321967ce36ff93357 -b3c4548f14d58b3ab03c222da09e4381a0afe47a72d18d50a94e0008797f78e39e99990e5b4757be62310d400746e35a -a9b1883bd5f31f909b8b1b6dcb48c1c60ed20aa7374b3ffa7f5b2ed036599b5bef33289d23c80a5e6420d191723b92f7 -85d38dffd99487ae5bb41ab4a44d80a46157bbbe8ef9497e68f061721f74e4da513ccc3422936b059575975f6787c936 -adf870fcb96e972c033ab7a35d28ae79ee795f82bc49c3bd69138f0e338103118d5529c53f2d72a9c0d947bf7d312af2 -ab4c7a44e2d9446c6ff303eb49aef0e367a58b22cc3bb27b4e69b55d1d9ee639c9234148d2ee95f9ca8079b1457d5a75 -a386420b738aba2d7145eb4cba6d643d96bda3f2ca55bb11980b318d43b289d55a108f4bc23a9606fb0bccdeb3b3bb30 -847020e0a440d9c4109773ecca5d8268b44d523389993b1f5e60e541187f7c597d79ebd6e318871815e26c96b4a4dbb1 -a530aa7e5ca86fcd1bec4b072b55cc793781f38a666c2033b510a69e110eeabb54c7d8cbcb9c61fee531a6f635ffa972 -87364a5ea1d270632a44269d686b2402da737948dac27f51b7a97af80b66728b0256547a5103d2227005541ca4b7ed04 -8816fc6e16ea277de93a6d793d0eb5c15e9e93eb958c5ef30adaf8241805adeb4da8ce19c3c2167f971f61e0b361077d -8836a72d301c42510367181bb091e4be377777aed57b73c29ef2ce1d475feedd7e0f31676284d9a94f6db01cc4de81a2 -b0d9d8b7116156d9dde138d28aa05a33e61f8a85839c1e9071ccd517b46a5b4b53acb32c2edd7150c15bc1b4bd8db9e3 -ae931b6eaeda790ba7f1cd674e53dc87f6306ff44951fa0df88d506316a5da240df9794ccbd7215a6470e6b31c5ea193 -8c6d5bdf87bd7f645419d7c6444e244fe054d437ed1ba0c122fde7800603a5fadc061e5b836cb22a6cfb2b466f20f013 -90d530c6d0cb654999fa771b8d11d723f54b8a8233d1052dc1e839ea6e314fbed3697084601f3e9bbb71d2b4eaa596df -b0d341a1422588c983f767b1ed36c18b141774f67ef6a43cff8e18b73a009da10fc12120938b8bba27f225bdfd3138f9 -a131b56f9537f460d304e9a1dd75702ace8abd68cb45419695cb8dee76998139058336c87b7afd6239dc20d7f8f940cc -aa6c51fa28975f709329adee1bbd35d49c6b878041841a94465e8218338e4371f5cb6c17f44a63ac93644bf28f15d20f -88440fb584a99ebd7f9ea04aaf622f6e44e2b43bbb49fb5de548d24a238dc8f26c8da2ccf03dd43102bda9f16623f609 -9777b8695b790e702159a4a750d5e7ff865425b95fa0a3c15495af385b91c90c00a6bd01d1b77bffe8c47d01baae846f -8b9d764ece7799079e63c7f01690c8eff00896a26a0d095773dea7a35967a8c40db7a6a74692f0118bf0460c26739af4 -85808c65c485520609c9e61fa1bb67b28f4611d3608a9f7a5030ee61c3aa3c7e7dc17fff48af76b4aecee2cb0dbd22ac -ad2783a76f5b3db008ef5f7e67391fda4e7e36abde6b3b089fc4835b5c339370287935af6bd53998bed4e399eda1136d -96f18ec03ae47c205cc4242ca58e2eff185c9dca86d5158817e2e5dc2207ab84aadda78725f8dc080a231efdc093b940 -97de1ab6c6cc646ae60cf7b86df73b9cf56cc0cd1f31b966951ebf79fc153531af55ca643b20b773daa7cab784b832f7 -870ba266a9bfa86ef644b1ef025a0f1b7609a60de170fe9508de8fd53170c0b48adb37f19397ee8019b041ce29a16576 -ad990e888d279ac4e8db90619d663d5ae027f994a3992c2fbc7d262b5990ae8a243e19157f3565671d1cb0de17fe6e55 -8d9d5adcdd94c5ba3be4d9a7428133b42e485f040a28d16ee2384758e87d35528f7f9868de9bd23d1a42a594ce50a567 -85a33ed75d514ece6ad78440e42f7fcdb59b6f4cff821188236d20edae9050b3a042ce9bc7d2054296e133d033e45022 -92afd2f49a124aaba90de59be85ff269457f982b54c91b06650c1b8055f9b4b0640fd378df02a00e4fc91f7d226ab980 -8c0ee09ec64bd831e544785e3d65418fe83ed9c920d9bb4d0bf6dd162c1264eb9d6652d2def0722e223915615931581c -8369bedfa17b24e9ad48ebd9c5afea4b66b3296d5770e09b00446c5b0a8a373d39d300780c01dcc1c6752792bccf5fd0 -8b9e960782576a59b2eb2250d346030daa50bbbec114e95cdb9e4b1ba18c3d34525ae388f859708131984976ca439d94 -b682bface862008fea2b5a07812ca6a28a58fd151a1d54c708fc2f8572916e0d678a9cb8dc1c10c0470025c8a605249e -a38d5e189bea540a824b36815fc41e3750760a52be0862c4cac68214febdc1a754fb194a7415a8fb7f96f6836196d82a -b9e7fbda650f18c7eb8b40e42cc42273a7298e65e8be524292369581861075c55299ce69309710e5b843cb884de171bd -b6657e5e31b3193874a1bace08f42faccbd3c502fb73ad87d15d18a1b6c2a146f1baa929e6f517db390a5a47b66c0acf -ae15487312f84ed6265e4c28327d24a8a0f4d2d17d4a5b7c29b974139cf93223435aaebe3af918f5b4bb20911799715f -8bb4608beb06bc394e1a70739b872ce5a2a3ffc98c7547bf2698c893ca399d6c13686f6663f483894bccaabc3b9c56ad -b58ac36bc6847077584308d952c5f3663e3001af5ecf2e19cb162e1c58bd6c49510205d453cffc876ca1dc6b8e04a578 -924f65ced61266a79a671ffb49b300f0ea44c50a0b4e3b02064faa99fcc3e4f6061ea8f38168ab118c5d47bd7804590e -8d67d43b8a06b0ff4fafd7f0483fa9ed1a9e3e658a03fb49d9d9b74e2e24858dc1bed065c12392037b467f255d4e5643 -b4d4f87813125a6b355e4519a81657fa97c43a6115817b819a6caf4823f1d6a1169683fd68f8d025cdfa40ebf3069acb -a7fd4d2c8e7b59b8eed3d4332ae94b77a89a2616347402f880bc81bde072220131e6dbec8a605be3a1c760b775375879 -8d4a7d8fa6f55a30df37bcf74952e2fa4fd6676a2e4606185cf154bdd84643fd01619f8fb8813a564f72e3f574f8ce30 -8086fb88e6260e9a9c42e9560fde76315ff5e5680ec7140f2a18438f15bc2cc7d7d43bfb5880b180b738c20a834e6134 -916c4c54721de03934fee6f43de50bb04c81f6f8dd4f6781e159e71c40c60408aa54251d457369d133d4ba3ed7c12cb4 -902e5bf468f11ed9954e2a4a595c27e34abe512f1d6dc08bbca1c2441063f9af3dc5a8075ab910a10ff6c05c1c644a35 -a1302953015e164bf4c15f7d4d35e3633425a78294406b861675667eec77765ff88472306531e5d3a4ec0a2ff0dd6a9e -87874461df3c9aa6c0fa91325576c0590f367075f2f0ecfeb34afe162c04c14f8ce9d608c37ac1adc8b9985bc036e366 -84b50a8a61d3cc609bfb0417348133e698fe09a6d37357ce3358de189efcf35773d78c57635c2d26c3542b13cc371752 -acaed2cff8633d12c1d12bb7270c54d65b0b0733ab084fd47f81d0a6e1e9b6f300e615e79538239e6160c566d8bb8d29 -889e6a0e136372ca4bac90d1ab220d4e1cad425a710e8cdd48b400b73bb8137291ceb36a39440fa84305783b1d42c72f -90952e5becec45b2b73719c228429a2c364991cf1d5a9d6845ae5b38018c2626f4308daa322cab1c72e0f6c621bb2b35 -8f5a97a801b6e9dcd66ccb80d337562c96f7914e7169e8ff0fda71534054c64bf2a9493bb830623d612cfe998789be65 -84f3df8b9847dcf1d63ca470dc623154898f83c25a6983e9b78c6d2d90a97bf5e622445be835f32c1e55e6a0a562ea78 -91d12095cd7a88e7f57f254f02fdb1a1ab18984871dead2f107404bcf8069fe68258c4e6f6ebd2477bddf738135400bb -b771a28bc04baef68604d4723791d3712f82b5e4fe316d7adc2fc01b935d8e644c06d59b83bcb542afc40ebafbee0683 -872f6341476e387604a7e93ae6d6117e72d164e38ebc2b825bc6df4fcce815004d7516423c190c1575946b5de438c08d -90d6b4aa7d40a020cdcd04e8b016d041795961a8e532a0e1f4041252131089114a251791bf57794cadb7d636342f5d1c -899023ba6096a181448d927fed7a0fe858be4eac4082a42e30b3050ee065278d72fa9b9d5ce3bc1372d4cbd30a2f2976 -a28f176571e1a9124f95973f414d5bdbf5794d41c3839d8b917100902ac4e2171eb940431236cec93928a60a77ede793 -838dbe5bcd29c4e465d02350270fa0036cd46f8730b13d91e77afb7f5ed16525d0021d3b2ae173a76c378516a903e0cb -8e105d012dd3f5d20f0f1c4a7e7f09f0fdd74ce554c3032e48da8cce0a77260d7d47a454851387770f5c256fa29bcb88 -8f4df0f9feeb7a487e1d138d13ea961459a6402fd8f8cabb226a92249a0d04ded5971f3242b9f90d08da5ff66da28af6 -ad1cfda4f2122a20935aa32fb17c536a3653a18617a65c6836700b5537122af5a8206befe9eaea781c1244c43778e7f1 -832c6f01d6571964ea383292efc8c8fa11e61c0634a25fa180737cc7ab57bc77f25e614aac9a2a03d98f27b3c1c29de2 -903f89cc13ec6685ac7728521898781fecb300e9094ef913d530bf875c18bcc3ceed7ed51e7b482d45619ab4b025c2e9 -a03c474bb915aad94f171e8d96f46abb2a19c9470601f4c915512ec8b9e743c3938450a2a5b077b4618b9df8809e1dc1 -83536c8456f306045a5f38ae4be2e350878fa7e164ea408d467f8c3bc4c2ee396bd5868008c089183868e4dfad7aa50b -88f26b4ea1b236cb326cd7ad7e2517ec8c4919598691474fe15d09cabcfc37a8d8b1b818f4d112432ee3a716b0f37871 -a44324e3fe96e9c12b40ded4f0f3397c8c7ee8ff5e96441118d8a6bfad712d3ac990b2a6a23231a8f691491ac1fd480f -b0de4693b4b9f932191a21ee88629964878680152a82996c0019ffc39f8d9369bbe2fe5844b68d6d9589ace54af947e4 -8e5d8ba948aea5fd26035351a960e87f0d23efddd8e13236cc8e4545a3dda2e9a85e6521efb8577e03772d3637d213d9 -93efc82d2017e9c57834a1246463e64774e56183bb247c8fc9dd98c56817e878d97b05f5c8d900acf1fbbbca6f146556 -8731176363ad7658a2862426ee47a5dce9434216cef60e6045fa57c40bb3ce1e78dac4510ae40f1f31db5967022ced32 -b10c9a96745722c85bdb1a693100104d560433d45b9ac4add54c7646a7310d8e9b3ca9abd1039d473ae768a18e489845 -a2ac374dfbb464bf850b4a2caf15b112634a6428e8395f9c9243baefd2452b4b4c61b0cb2836d8eae2d57d4900bf407e -b69fe3ded0c4f5d44a09a0e0f398221b6d1bf5dbb8bc4e338b93c64f1a3cac1e4b5f73c2b8117158030ec03787f4b452 -8852cdbaf7d0447a8c6f211b4830711b3b5c105c0f316e3a6a18dcfbb9be08bd6f4e5c8ae0c3692da08a2dfa532f9d5c -93bbf6d7432a7d98ade3f94b57bf9f4da9bc221a180a370b113066dd42601bb9e09edd79e2e6e04e00423399339eebda -a80941c391f1eeafc1451c59e4775d6a383946ff22997aeaadf806542ba451d3b0f0c6864eeba954174a296efe2c1550 -a045fe2bb011c2a2f71a0181a8f457a3078470fb74c628eab8b59aef69ffd0d649723bf74d6885af3f028bc5a104fb39 -b9d8c35911009c4c8cad64692139bf3fc16b78f5a19980790cb6a7aea650a25df4231a4437ae0c351676a7e42c16134f -94c79501ded0cfcbab99e1841abe4a00a0252b3870e20774c3da16c982d74c501916ec28304e71194845be6e3113c7ab -900a66418b082a24c6348d8644ddb1817df5b25cb33044a519ef47cc8e1f7f1e38d2465b7b96d32ed472d2d17f8414c6 -b26f45d393b8b2fcb29bdbb16323dc7f4b81c09618519ab3a39f8ee5bd148d0d9f3c0b5dfab55b5ce14a1cb9206d777b -aa1a87735fc493a80a96a9a57ca40a6d9c32702bfcaa9869ce1a116ae65d69cefe2f3e79a12454b4590353e96f8912b4 -a922b188d3d0b69b4e4ea2a2aa076566962844637da12c0832105d7b31dea4a309eee15d12b7a336be3ea36fcbd3e3b7 -8f3841fcf4105131d8c4d9885e6e11a46c448226401cf99356c291fadb864da9fa9d30f3a73c327f23f9fd99a11d633e -9791d1183fae270e226379af6c497e7da803ea854bb20afa74b253239b744c15f670ee808f708ede873e78d79a626c9a -a4cad52e3369491ada61bf28ada9e85de4516d21c882e5f1cd845bea9c06e0b2887b0c5527fcff6fc28acd3c04f0a796 -b9ac86a900899603452bd11a7892a9bfed8054970bfcbeaa8c9d1930db891169e38d6977f5258c25734f96c8462eee3b -a3a154c28e5580656a859f4efc2f5ebfa7eaa84ca40e3f134fa7865e8581586db74992dbfa4036aa252fba103773ddde -95cc2a0c1885a029e094f5d737e3ecf4d26b99036453a8773c77e360101f9f98676ee246f6f732a377a996702d55691f -842651bbe99720438d8d4b0218feb60481280c05beb17750e9ca0d8c0599a60f873b7fbdcc7d8835ba9a6d57b16eec03 -81ee54699da98f5620307893dcea8f64670609fa20e5622265d66283adeac122d458b3308c5898e6c57c298db2c8b24f -b97868b0b2bc98032d68352a535a1b341b9ff3c7af4e3a7f3ebc82d3419daa1b5859d6aedc39994939623c7cd878bd9b -b60325cd5d36461d07ef253d826f37f9ee6474a760f2fff80f9873d01fd2b57711543cdc8d7afa1c350aa753c2e33dea -8c205326c11d25a46717b780c639d89714c7736c974ae71287e3f4b02e6605ac2d9b4928967b1684f12be040b7bf2dd3 -95a392d82db51e26ade6c2ccd3396d7e40aff68fa570b5951466580d6e56dda51775dce5cf3a74a7f28c3cb2eb551c4d -8f2cc8071eb56dffb70bda6dd433b556221dc8bba21c53353c865f00e7d4d86c9e39f119ea9a8a12ef583e9a55d9a6b6 -9449a71af9672aaf8856896d7e3d788b22991a7103f75b08c0abbcc2bfe60fda4ed8ce502cea4511ff0ea52a93e81222 -857090ab9fdb7d59632d068f3cc8cf27e61f0d8322d30e6b38e780a1f05227199b4cd746aac1311c36c659ef20931f28 -98a891f4973e7d9aaf9ac70854608d4f7493dffc7e0987d7be9dd6029f6ea5636d24ef3a83205615ca1ff403750058e1 -a486e1365bbc278dd66a2a25d258dc82f46b911103cb16aab3945b9c95ae87b386313a12b566df5b22322ede0afe25ad -a9a1eb399ed95d396dccd8d1ac718043446f8b979ec62bdce51c617c97a312f01376ab7fb87d27034e5f5570797b3c33 -b7abc3858d7a74bb446218d2f5a037e0fae11871ed9caf44b29b69c500c1fa1dcfad64c9cdccc9d80d5e584f06213deb -8cfb09fe2e202faa4cebad932b1d35f5ca204e1c2a0c740a57812ac9a6792130d1312aabd9e9d4c58ca168bfebd4c177 -a90a305c2cd0f184787c6be596fa67f436afd1f9b93f30e875f817ac2aae8bdd2e6e656f6be809467e6b3ad84adb86b1 -80a9ef993c2b009ae172cc8f7ec036f5734cf4f4dfa06a7db4d54725e7fbfae5e3bc6f22687bdbb6961939d6f0c87537 -848ade1901931e72b955d7db1893f07003e1708ff5d93174bac5930b9a732640f0578839203e9b77eb27965c700032d3 -93fdf4697609c5ae9c33b9ca2f5f1af44abeb2b98dc4fdf732cf7388de086f410730dc384d9b7a7f447bb009653c8381 -89ce3fb805aea618b5715c0d22a9f46da696b6fa86794f56fdf1d44155a33d42daf1920bcbe36cbacf3cf4c92df9cbc7 -829ce2c342cf82aa469c65f724f308f7a750bd1494adc264609cd790c8718b8b25b5cab5858cf4ee2f8f651d569eea67 -af2f0cee7bf413204be8b9df59b9e4991bc9009e0d6dbe6815181df0ec2ca93ab8f4f3135b1c14d8f53d74bff0bd6f27 -b87998cecf7b88cde93d1779f10a521edd5574a2fbd240102978639ec57433ba08cdb53849038a329cebbe74657268d2 -a64542a1261a6ed3d720c2c3a802303aad8c4c110c95d0f12e05c1065e66f42da494792b6bfc5b9272363f3b1d457f58 -86a6fd042e4f282fadf07a4bfee03fc96a3aea49f7a00f52bf249a20f1ec892326855410e61f37fbb27d9305eb2fc713 -967ea5bc403b6db269682f7fd0df90659350d7e1aa66bc4fab4c9dfcd75ed0bba4b52f1cebc5f34dc8ba810793727629 -a52990f9f3b8616ce3cdc2c74cd195029e6a969753dcf2d1630438700e7d6ebde36538532b3525ac516f5f2ce9dd27a3 -a64f7ff870bab4a8bf0d4ef6f5c744e9bf1021ed08b4c80903c7ad318e80ba1817c3180cc45cb5a1cae1170f0241655f -b00f706fa4de1f663f021e8ad3d155e84ce6084a409374b6e6cd0f924a0a0b51bebaaaf1d228c77233a73b0a5a0df0e9 -8b882cc3bff3e42babdb96df95fb780faded84887a0a9bab896bef371cdcf169d909f5658649e93006aa3c6e1146d62e -9332663ef1d1dcf805c3d0e4ce7a07d9863fb1731172e766b3cde030bf81682cc011e26b773fb9c68e0477b4ae2cfb79 -a8aa8151348dbd4ef40aaeb699b71b4c4bfd3218560c120d85036d14f678f6736f0ec68e80ce1459d3d35feccc575164 -a16cd8b729768f51881c213434aa28301fa78fcb554ddd5f9012ee1e4eae7b5cb3dd88d269d53146dea92d10790faf0b -86844f0ef9d37142faf3b1e196e44fbe280a3ba4189aa05c356778cb9e3b388a2bff95eed305ada8769935c9974e4c57 -ae2eec6b328fccf3b47bcdac32901ac2744a51beb410b04c81dea34dee4912b619466a4f5e2780d87ecefaebbe77b46d -915df4c38d301c8a4eb2dc5b1ba0ffaad67cbb177e0a80095614e9c711f4ef24a4cef133f9d982a63d2a943ba6c8669d -ae6a2a4dedfc2d1811711a8946991fede972fdf2a389b282471280737536ffc0ac3a6d885b1f8bda0366eb0b229b9979 -a9b628c63d08b8aba6b1317f6e91c34b2382a6c85376e8ef2410a463c6796740ae936fc4e9e0737cb9455d1daa287bd8 -848e30bf7edf2546670b390d5cf9ab71f98fcb6add3c0b582cb34996c26a446dee5d1bde4fdcde4fc80c10936e117b29 -907d6096c7c8c087d1808dd995d5d2b9169b3768c3f433475b50c2e2bd4b082f4d543afd8b0b0ddffa9c66222a72d51d -a59970a2493b07339124d763ac9d793c60a03354539ecbcf6035bc43d1ea6e35718202ae6d7060b7d388f483d971573c -b9cfef2af9681b2318f119d8611ff6d9485a68d8044581b1959ab1840cbca576dbb53eec17863d2149966e9feb21122f -ad47271806161f61d3afa45cdfe2babceef5e90031a21779f83dc8562e6076680525b4970b2f11fe9b2b23c382768323 -8e425a99b71677b04fe044625d338811fbb8ee32368a424f6ab2381c52e86ee7a6cecedf777dc97181519d41c351bc22 -86b55b54d7adefc12954a9252ee23ae83efe8b5b4b9a7dc307904413e5d69868c7087a818b2833f9b004213d629be8ad -a14fda6b93923dd11e564ae4457a66f397741527166e0b16a8eb91c6701c244fd1c4b63f9dd3515193ec88fa6c266b35 -a9b17c36ae6cd85a0ed7f6cabc5b47dc8f80ced605db327c47826476dc1fb8f8669aa7a7dc679fbd4ee3d8e8b4bd6a6f -82a0829469c1458d959c821148f15dacae9ea94bf56c59a6ab2d4dd8b3d16d73e313b5a3912a6c1f131d73a8f06730c4 -b22d56d549a53eaef549595924bdb621ff807aa4513feedf3fdcbf7ba8b6b9cfa4481c2f67fc642db397a6b794a8b63a -974c59c24392e2cb9294006cbe3c52163e255f3bd0c2b457bdc68a6338e6d5b6f87f716854492f8d880a6b896ccf757c -b70d247ba7cad97c50b57f526c2ba915786e926a94e8f8c3eebc2e1be6f4255411b9670e382060049c8f4184302c40b2 -ad80201fe75ef21c3ddbd98cf23591e0d7a3ba1036dfe77785c32f44755a212c31f0ceb0a0b6f5ee9b6dc81f358d30c3 -8c656e841f9bb90b9a42d425251f3fdbc022a604d75f5845f479ed4be23e02aaf9e6e56cde351dd7449c50574818a199 -8b88dd3fa209d3063b7c5b058f7249ee9900fbc2287d16da61a0704a0a1d71e45d9c96e1cda7fdf9654534ec44558b22 -961da00cc8750bd84d253c08f011970ae1b1158ad6778e8ed943d547bceaf52d6d5a212a7de3bf2706688c4389b827d2 -a5dd379922549a956033e3d51a986a4b1508e575042b8eaa1df007aa77cf0b8c2ab23212f9c075702788fa9c53696133 -ac8fcfde3a349d1e93fc8cf450814e842005c545c4844c0401bc80e6b96cdb77f29285a14455e167c191d4f312e866cd -ac63d79c799783a8466617030c59dd5a8f92ee6c5204676fd8d881ce5f7f8663bdbeb0379e480ea9b6340ab0dc88e574 -805874fde19ce359041ae2bd52a39e2841acabfd31f965792f2737d7137f36d4e4722ede8340d8c95afa6af278af8acb -8d2f323a228aa8ba7b7dc1399138f9e6b41df1a16a7069003ab8104b8b68506a45141bc5fe66acf430e23e13a545190b -a1610c721a2d9af882bb6b39bea97cff1527a3aea041d25934de080214ae77c959e79957164440686d15ab301e897d4d -aba16d29a47fc36f12b654fde513896723e2c700c4190f11b26aa4011da57737ad717daa02794aa3246e4ae5f0b0cc3a -a406db2f15fdd135f346cc4846623c47edd195e80ba8c7cb447332095314d565e4040694ca924696bb5ee7f8996ea0ba -8b30e2cd9b47d75ba57b83630e40f832249af6c058d4f490416562af451993eec46f3e1f90bc4d389e4c06abd1b32a46 -aacf9eb7036e248e209adbfc3dd7ce386569ea9b312caa4b240726549db3c68c4f1c8cbf8ed5ea9ea60c7e57c9df3b8e -b20fcac63bf6f5ee638a42d7f89be847f348c085ddcbec3fa318f4323592d136c230495f188ef2022aa355cc2b0da6f9 -811eff750456a79ec1b1249d76d7c1547065b839d8d4aaad860f6d4528eb5b669473dcceeeea676cddbc3980b68461b7 -b52d14ae33f4ab422f953392ae76a19c618cc31afc96290bd3fe2fb44c954b5c92c4789f3f16e8793f2c0c1691ade444 -a7826dafeeba0db5b66c4dfcf2b17fd7b40507a5a53ac2e42942633a2cb30b95ba1739a6e9f3b7a0e0f1ec729bf274e2 -8acfd83ddf7c60dd7c8b20c706a3b972c65d336b8f9b3d907bdd8926ced271430479448100050b1ef17578a49c8fa616 -af0c69f65184bb06868029ad46f8465d75c36814c621ac20a5c0b06a900d59305584f5a6709683d9c0e4b6cd08d650a6 -b6cc8588191e00680ee6c3339bd0f0a17ad8fd7f4be57d5d7075bede0ea593a19e67f3d7c1a20114894ee5bfcab71063 -a82fd4f58635129dbb6cc3eb9391cf2d28400018b105fc41500fbbd12bd890b918f97d3d359c29dd3b4c4e34391dfab0 -92fc544ed65b4a3625cf03c41ddff7c039bc22d22c0d59dcc00efd5438401f2606adb125a1d5de294cca216ec8ac35a3 -906f67e4a32582b71f15940523c0c7ce370336935e2646bdaea16a06995256d25e99df57297e39d6c39535e180456407 -97510337ea5bbd5977287339197db55c60533b2ec35c94d0a460a416ae9f60e85cee39be82abeeacd5813cf54df05862 -87e6894643815c0ea48cb96c607266c5ee4f1f82ba5fe352fb77f9b6ed14bfc2b8e09e80a99ac9047dfcf62b2ae26795 -b6fd55dd156622ad7d5d51b7dde75e47bd052d4e542dd6449e72411f68275775c846dde301e84613312be8c7bce58b07 -b98461ac71f554b2f03a94e429b255af89eec917e208a8e60edf5fc43b65f1d17a20de3f31d2ce9f0cb573c25f2f4d98 -96f0dea40ca61cefbee41c4e1fe9a7d81fbe1f49bb153d083ab70f5d0488a1f717fd28cedcf6aa18d07cce2c62801898 -8d7c3ab310184f7dc34b6ce4684e4d29a31e77b09940448ea4daac730b7eb308063125d4dd229046cf11bfd521b771e0 -96f0564898fe96687918bbf0a6adead99cf72e3a35ea3347e124af9d006221f8e82e5a9d2fe80094d5e8d48e610f415e -ad50fcb92c2675a398cf07d4c40a579e44bf8d35f27cc330b57e54d5ea59f7d898af0f75dccfe3726e5471133d70f92b -828beed62020361689ae7481dd8f116902b522fb0c6c122678e7f949fdef70ead011e0e6bffd25678e388744e17cdb69 -8349decac1ca16599eee2efc95bcaabf67631107da1d34a2f917884bd70dfec9b4b08ab7bc4379d6c73b19c0b6e54fb8 -b2a6a2e50230c05613ace9e58bb2e98d94127f196f02d9dddc53c43fc68c184549ca12d713cb1b025d8260a41e947155 -94ff52181aadae832aed52fc3b7794536e2a31a21fc8be3ea312ca5c695750d37f08002f286b33f4023dba1e3253ecfa -a21d56153c7e5972ee9a319501be4faff199fdf09bb821ea9ce64aa815289676c00f105e6f00311b3a5b627091b0d0fc -a27a60d219f1f0c971db73a7f563b371b5c9fc3ed1f72883b2eac8a0df6698400c9954f4ca17d7e94e44bd4f95532afb -a2fc56fae99b1f18ba5e4fe838402164ce82f8a7f3193d0bbd360c2bac07c46f9330c4c7681ffb47074c6f81ee6e7ac6 -b748e530cd3afb96d879b83e89c9f1a444f54e55372ab1dcd46a0872f95ce8f49cf2363fc61be82259e04f555937ed16 -8bf8993e81080c7cbba1e14a798504af1e4950b2f186ab3335b771d6acaee4ffe92131ae9c53d74379d957cb6344d9cd -96774d0ef730d22d7ab6d9fb7f90b9ead44285219d076584a901960542756700a2a1603cdf72be4708b267200f6c36a9 -b47703c2ab17be1e823cc7bf3460db1d6760c0e33862c90ca058845b2ff234b0f9834ddba2efb2ee1770eb261e7d8ffd -84319e67c37a9581f8b09b5e4d4ae88d0a7fb4cbb6908971ab5be28070c3830f040b1de83ee663c573e0f2f6198640e4 -96811875fa83133e0b3c0e0290f9e0e28bca6178b77fdf5350eb19344d453dbd0d71e55a0ef749025a5a2ca0ad251e81 -81a423423e9438343879f2bfd7ee9f1c74ebebe7ce3cfffc8a11da6f040cc4145c3b527bd3cf63f9137e714dbcb474ef -b8c3535701ddbeec2db08e17a4fa99ba6752d32ece5331a0b8743676f421fcb14798afc7c783815484f14693d2f70db8 -81aee980c876949bf40782835eec8817d535f6f3f7e00bf402ddd61101fdcd60173961ae90a1cf7c5d060339a18c959d -87e67b928d97b62c49dac321ce6cb680233f3a394d4c9a899ac2e8db8ccd8e00418e66cdfd68691aa3cb8559723b580c -8eac204208d99a2b738648df96353bbb1b1065e33ee4f6bba174b540bbbd37d205855e1f1e69a6b7ff043ca377651126 -848e6e7a54ad64d18009300b93ea6f459ce855971dddb419b101f5ac4c159215626fadc20cc3b9ab1701d8f6dfaddd8b -88aa123d9e0cf309d46dddb6acf634b1ade3b090a2826d6e5e78669fa1220d6df9a6697d7778cd9b627db17eea846126 -9200c2a629b9144d88a61151b661b6c4256cc5dadfd1e59a8ce17a013c2d8f7e754aabe61663c3b30f1bc47784c1f8cf -b6e1a2827c3bdda91715b0e1b1f10dd363cef337e7c80cac1f34165fc0dea7c8b69747e310563db5818390146ce3e231 -92c333e694f89f0d306d54105b2a5dcc912dbe7654d9e733edab12e8537350815be472b063e56cfde5286df8922fdecb -a6fac04b6d86091158ebb286586ccfec2a95c9786e14d91a9c743f5f05546073e5e3cc717635a0c602cad8334e922346 -a581b4af77feebc1fb897d49b5b507c6ad513d8f09b273328efbb24ef0d91eb740d01b4d398f2738125dacfe550330cd -81c4860cccf76a34f8a2bc3f464b7bfd3e909e975cce0d28979f457738a56e60a4af8e68a3992cf273b5946e8d7f76e2 -8d1eaa09a3180d8af1cbaee673db5223363cc7229a69565f592fa38ba0f9d582cedf91e15dabd06ebbf2862fc0feba54 -9832f49b0147f4552402e54593cfa51f99540bffada12759b71fcb86734be8e500eea2d8b3d036710bdf04c901432de9 -8bdb0e8ec93b11e5718e8c13cb4f5de545d24829fd76161216340108098dfe5148ed25e3b57a89a516f09fa79043734d -ab96f06c4b9b0b2c0571740b24fca758e6976315053a7ecb20119150a9fa416db2d3a2e0f8168b390bb063f0c1caf785 -ab777f5c52acd62ecf4d1f168b9cc8e1a9b45d4ec6a8ff52c583e867c2239aba98d7d3af977289b367edce03d9c2dfb1 -a09d3ce5e748da84802436951acc3d3ea5d8ec1d6933505ed724d6b4b0d69973ab0930daec9c6606960f6e541e4a3ce2 -8ef94f7be4d85d5ad3d779a5cf4d7b2fc3e65c52fb8e1c3c112509a4af77a0b5be994f251e5e40fabeeb1f7d5615c22b -a7406a5bf5708d9e10922d3c5c45c03ef891b8d0d74ec9f28328a72be4cdc05b4f2703fa99366426659dfca25d007535 -b7f52709669bf92a2e070bfe740f422f0b7127392c5589c7f0af71bb5a8428697c762d3c0d74532899da24ea7d8695c2 -b9dfb0c8df84104dbf9239ccefa4672ef95ddabb8801b74997935d1b81a78a6a5669a3c553767ec19a1281f6e570f4ff -ae4d5c872156061ce9195ac640190d8d71dd406055ee43ffa6f9893eb24b870075b74c94d65bc1d5a07a6573282b5520 -afe6bd3eb72266d333f1807164900dcfa02a7eb5b1744bb3c86b34b3ee91e3f05e38fa52a50dc64eeb4bdb1dd62874b8 -948043cf1bc2ef3c01105f6a78dc06487f57548a3e6ef30e6ebc51c94b71e4bf3ff6d0058c72b6f3ecc37efd7c7fa8c0 -a22fd17c2f7ffe552bb0f23fa135584e8d2d8d75e3f742d94d04aded2a79e22a00dfe7acbb57d44e1cdb962fb22ae170 -8cd0f4e9e4fb4a37c02c1bde0f69359c43ab012eb662d346487be0c3758293f1ca560122b059b091fddce626383c3a8f -90499e45f5b9c81426f3d735a52a564cafbed72711d9279fdd88de8038e953bc48c57b58cba85c3b2e4ce56f1ddb0e11 -8c30e4c034c02958384564cac4f85022ef36ab5697a3d2feaf6bf105049675bbf23d01b4b6814711d3d9271abff04cac -81f7999e7eeea30f3e1075e6780bbf054f2fb6f27628a2afa4d41872a385b4216dd5f549da7ce6cf39049b2251f27fb7 -b36a7191f82fc39c283ffe53fc1f5a9a00b4c64eee7792a8443475da9a4d226cf257f226ea9d66e329af15d8f04984ec -aad4da528fdbb4db504f3041c747455baff5fcd459a2efd78f15bdf3aea0bdb808343e49df88fe7a7c8620009b7964a3 -99ebd8c6dd5dd299517fb6381cfc2a7f443e6e04a351440260dd7c2aee3f1d8ef06eb6c18820b394366ecdfd2a3ce264 -8873725b81871db72e4ec3643084b1cdce3cbf80b40b834b092767728605825c19b6847ad3dcf328438607e8f88b4410 -b008ee2f895daa6abd35bd39b6f7901ae4611a11a3271194e19da1cdcc7f1e1ea008fe5c5440e50d2c273784541ad9c5 -9036feafb4218d1f576ef89d0e99124e45dacaa6d816988e34d80f454d10e96809791d5b78f7fd65f569e90d4d7238c5 -92073c1d11b168e4fa50988b0288638b4868e48bbc668c5a6dddf5499875d53be23a285acb5e4bad60114f6cf6c556e9 -88c87dfcb8ba6cbfe7e1be081ccfadbd589301db2cb7c99f9ee5d7db90aa297ed1538d5a867678a763f2deede5fd219a -b42a562805c661a50f5dea63108002c0f27c0da113da6a9864c9feb5552225417c0356c4209e8e012d9bcc9d182c7611 -8e6317d00a504e3b79cd47feb4c60f9df186467fe9ca0f35b55c0364db30528f5ff071109dabb2fc80bb9cd4949f0c24 -b7b1ea6a88694f8d2f539e52a47466695e39e43a5eb9c6f23bca15305fe52939d8755cc3ac9d6725e60f82f994a3772f -a3cd55161befe795af93a38d33290fb642b8d80da8b786c6e6fb02d393ea308fbe87f486994039cbd7c7b390414594b6 -b416d2d45b44ead3b1424e92c73c2cf510801897b05d1724ff31cbd741920cd858282fb5d6040fe1f0aa97a65bc49424 -950ee01291754feace97c2e933e4681e7ddfbc4fcd079eb6ff830b0e481d929c93d0c7fb479c9939c28ca1945c40da09 -869bd916aee8d86efe362a49010382674825d49195b413b4b4018e88ce43fe091b475d0b863ff0ba2259400f280c2b23 -9782f38cd9c9d3385ec286ebbc7cba5b718d2e65a5890b0a5906b10a89dc8ed80d417d71d7c213bf52f2af1a1f513ea7 -91cd33bc2628d096269b23faf47ee15e14cb7fdc6a8e3a98b55e1031ea0b68d10ba30d97e660f7e967d24436d40fad73 -8becc978129cc96737034c577ae7225372dd855da8811ae4e46328e020c803833b5bdbc4a20a93270e2b8bd1a2feae52 -a36b1d8076783a9522476ce17f799d78008967728ce920531fdaf88303321bcaf97ecaa08e0c01f77bc32e53c5f09525 -b4720e744943f70467983aa34499e76de6d59aa6fadf86f6b787fdce32a2f5b535b55db38fe2da95825c51002cfe142d -91ad21fc502eda3945f6de874d1b6bf9a9a7711f4d61354f9e5634fc73f9c06ada848de15ab0a75811d3250be862827d -84f78e2ebf5fc077d78635f981712daf17e2475e14c2a96d187913006ad69e234746184a51a06ef510c9455b38acb0d7 -960aa7906e9a2f11db64a26b5892ac45f20d2ccb5480f4888d89973beb6fa0dfdc06d68d241ff5ffc7f1b82b1aac242d -a99365dcd1a00c66c9db6924b97c920f5c723380e823b250db85c07631b320ec4e92e586f7319e67a522a0578f7b6d6c -a25d92d7f70cf6a88ff317cfec071e13774516da664f5fac0d4ecaa65b8bf4eb87a64a4d5ef2bd97dfae98d388dbf5cc -a7af47cd0041295798f9779020a44653007444e8b4ef0712982b06d0dcdd434ec4e1f7c5f7a049326602cb605c9105b7 -aefe172eac5568369a05980931cc476bebd9dea573ba276d59b9d8c4420784299df5a910033b7e324a6c2dfc62e3ef05 -b69bc9d22ffa645baa55e3e02522e9892bb2daa7fff7c15846f13517d0799766883ee09ae0869df4139150c5b843ca8a -95a10856140e493354fdd12722c7fdded21b6a2ffbc78aa2697104af8ad0c8e2206f44b0bfee077ef3949d46bbf7c16b -891f2fcd2c47cbea36b7fa715968540c233313f05333f09d29aba23c193f462ed490dd4d00969656e89c53155fdfe710 -a6c33e18115e64e385c843dde34e8a228222795c7ca90bc2cc085705d609025f3351d9be61822c69035a49fb3e48f2d5 -b87fb12f12c0533b005adad0487f03393ff682e13575e3cb57280c3873b2c38ba96a63c49eef7a442753d26b7005230b -b905c02ba451bfd411c135036d92c27af3b0b1c9c2f1309d6948544a264b125f39dd41afeff4666b12146c545adc168a -8b29c513f43a78951cf742231cf5457a6d9d55edf45df5481a0f299a418d94effef561b15d2c1a01d1b8067e7153fda9 -b9941cccd51dc645920d2781c81a317e5a33cb7cf76427b60396735912cb6d2ca9292bb4d36b6392467d390d2c58d9f3 -a8546b627c76b6ef5c93c6a98538d8593dbe21cb7673fd383d5401b0c935eea0bdeeefeb1af6ad41bad8464fb87bbc48 -aa286b27de2812de63108a1aec29d171775b69538dc6198640ac1e96767c2b83a50391f49259195957d457b493b667c9 -a932fb229f641e9abbd8eb2bd874015d97b6658ab6d29769fc23b7db9e41dd4f850382d4c1f08af8f156c5937d524473 -a1412840fcc86e2aeec175526f2fb36e8b3b8d21a78412b7266daf81e51b3f68584ed8bd42a66a43afdd8c297b320520 -89c78be9efb624c97ebca4fe04c7704fa52311d183ffd87737f76b7dadc187c12c982bd8e9ed7cd8beb48cdaafd2fd01 -a3f5ddec412a5bec0ce15e3bcb41c6214c2b05d4e9135a0d33c8e50a78eaba71e0a5a6ea8b45854dec5c2ed300971fc2 -9721f9cec7a68b7758e3887548790de49fa6a442d0396739efa20c2f50352a7f91d300867556d11a703866def2d5f7b5 -a23764e140a87e5991573521af039630dd28128bf56eed2edbed130fd4278e090b60cf5a1dca9de2910603d44b9f6d45 -a1a6494a994215e48ab55c70efa8ffdddce6e92403c38ae7e8dd2f8288cad460c6c7db526bbdf578e96ca04d9fe12797 -b1705ea4cb7e074efe0405fc7b8ee2ec789af0426142f3ec81241cacd4f7edcd88e39435e4e4d8e7b1df64f3880d6613 -85595d061d677116089a6064418b93eb44ff79e68d12bd9625078d3bbc440a60d0b02944eff6054433ee34710ae6fbb4 -9978d5e30bedb7526734f9a1febd973a70bfa20890490e7cc6f2f9328feab1e24f991285dbc3711d892514e2d7d005ad -af30243c66ea43b9f87a061f947f7bce745f09194f6e95f379c7582b9fead920e5d6957eaf05c12ae1282ada4670652f -a1930efb473f88001e47aa0b2b2a7566848cccf295792e4544096ecd14ee5d7927c173a8576b405bfa2eec551cd67eb5 -b0446d1c590ee5a45f7e22d269c044f3848c97aec1d226b44bfd0e94d9729c28a38bccddc3a1006cc5fe4e3c24f001f2 -b8a8380172df3d84b06176df916cf557966d4f2f716d3e9437e415d75b646810f79f2b2b71d857181b7fc944018883a3 -a563afec25b7817bfa26e19dc9908bc00aa8fc3d19be7d6de23648701659009d10e3e4486c28e9c6b13d48231ae29ac5 -a5a8e80579de886fb7d6408f542791876885947b27ad6fa99a8a26e381f052598d7b4e647b0115d4b5c64297e00ce28e -8f87afcc7ad33c51ac719bade3cd92da671a37a82c14446b0a2073f4a0a23085e2c8d31913ed2d0be928f053297de8f6 -a43c455ce377e0bc434386c53c752880687e017b2f5ae7f8a15c044895b242dffde4c92fb8f8bb50b18470b17351b156 -8368f8b12a5bceb1dba25adb3a2e9c7dc9b1a77a1f328e5a693f5aec195cd1e06b0fe9476b554c1c25dac6c4a5b640a3 -919878b27f3671fc78396f11531c032f3e2bd132d04cc234fa4858676b15fb1db3051c0b1db9b4fc49038216f11321ce -b48cd67fb7f1242696c1f877da4bdf188eac676cd0e561fbac1a537f7b8229aff5a043922441d603a26aae56a15faee4 -a3e0fdfd4d29ea996517a16f0370b54787fefe543c2fe73bfc6f9e560c1fd30dad8409859e2d7fa2d44316f24746c712 -8bb156ade8faf149df7bea02c140c7e392a4742ae6d0394d880a849127943e6f26312033336d3b9fdc0092d71b5efe87 -8845e5d5cc555ca3e0523244300f2c8d7e4d02aaebcb5bd749d791208856c209a6f84dd99fd55968c9f0ab5f82916707 -a3e90bb5c97b07789c2f32dff1aec61d0a2220928202f5ad5355ae71f8249237799d6c8a22602e32e572cb12eabe0c17 -b150bcc391884c996149dc3779ce71f15dda63a759ee9cc05871f5a8379dcb62b047098922c0f26c7bd04deb394c33f9 -95cd4ad88d51f0f2efcfd0c2df802fe252bb9704d1afbf9c26a248df22d55da87bdfaf41d7bc6e5df38bd848f0b13f42 -a05a49a31e91dff6a52ac8b9c2cfdd646a43f0d488253f9e3cfbce52f26667166bbb9b608fc358763a65cbf066cd6d05 -a59c3c1227fdd7c2e81f5e11ef5c406da44662987bac33caed72314081e2eed66055d38137e01b2268e58ec85dd986c0 -b7020ec3bd73a99861f0f1d88cf5a19abab1cbe14b7de77c9868398c84bb8e18dbbe9831838a96b6d6ca06e82451c67b -98d1ff2525e9718ee59a21d8900621636fcd873d9a564b8dceb4be80a194a0148daf1232742730b3341514b2e5a5436c -886d97b635975fc638c1b6afc493e5998ca139edba131b75b65cfe5a8e814f11bb678e0eeee5e6e5cd913ad3f2fefdfc -8fb9fd928d38d5d813b671c924edd56601dd7163b686c13f158645c2f869d9250f3859aa5463a39258c90fef0f41190a -aac35e1cd655c94dec3580bb3800bd9c2946c4a9856f7d725af15fbea6a2d8ca51c8ad2772abed60ee0e3fb9cb24046b -b8d71fa0fa05ac9e443c9b4929df9e7f09a919be679692682e614d24227e04894bfc14a5c73a62fb927fedff4a0e4aa7 -a45a19f11fbbb531a704badbb813ed8088ab827c884ee4e4ebf363fa1132ff7cfa9d28be9c85b143e4f7cdbc94e7cf1a -82b54703a4f295f5471b255ab59dce00f0fe90c9fb6e06b9ee48b15c91d43f4e2ef4a96c3118aeb03b08767be58181bb -8283264c8e6d2a36558f0d145c18576b6600ff45ff99cc93eca54b6c6422993cf392668633e5df396b9331e873d457e5 -8c549c03131ead601bc30eb6b9537b5d3beb7472f5bb1bcbbfd1e9f3704477f7840ab3ab7f7dc13bbbbcdff886a462d4 -afbb0c520ac1b5486513587700ad53e314cb74bfbc12e0b5fbdcfdaac36d342e8b59856196a0d84a25cff6e6e1d17e76 -89e4c22ffb51f2829061b3c7c1983c5c750cad158e3a825d46f7cf875677da5d63f653d8a297022b5db5845c9271b32b -afb27a86c4c2373088c96b9adf4433f2ebfc78ac5c526e9f0510670b6e4e5e0057c0a4f75b185e1a30331b9e805c1c15 -a18e16b57445f88730fc5d3567bf5a176861dc14c7a08ed2996fe80eed27a0e7628501bcb78a1727c5e9ac55f29c12c4 -93d61bf88b192d6825cf4e1120af1c17aa0f994d158b405e25437eaeefae049f7b721a206e7cc8a04fdc29d3c42580a1 -a99f2995a2e3ed2fd1228d64166112038de2f516410aa439f4c507044e2017ea388604e2d0f7121256fadf7fbe7023d1 -914fd91cffc23c32f1c6d0e98bf660925090d873367d543034654389916f65f552e445b0300b71b61b721a72e9a5983c -b42a578a7787b71f924e7def425d849c1c777156b1d4170a8ee7709a4a914e816935131afd9a0412c4cb952957b20828 -82fb30590e84b9e45db1ec475a39971cf554dc01bcc7050bc89265740725c02e2be5a972168c5170c86ae83e5b0ad2c0 -b14f8d8e1e93a84976289e0cf0dfa6f3a1809e98da16ee5c4932d0e1ed6bf8a07697fdd4dd86a3df84fb0003353cdcc0 -85d7a2f4bda31aa2cb208b771fe03291a4ebdaf6f1dc944c27775af5caec412584c1f45bc741fca2a6a85acb3f26ad7d -af02e56ce886ff2253bc0a68faad76f25ead84b2144e5364f3fb9b648f03a50ee9dc0b2c33ebacf7c61e9e43201ef9ef -87e025558c8a0b0abd06dfc350016847ea5ced7af2d135a5c9eec9324a4858c4b21510fb0992ec52a73447f24945058e -80fff0bafcd058118f5e7a4d4f1ae0912efeb281d2cbe4d34ba8945cc3dbe5d8baf47fb077343b90b8d895c90b297aca -b6edcf3a40e7b1c3c0148f47a263cd819e585a51ef31c2e35a29ce6f04c53e413f743034c0d998d9c00a08ba00166f31 -abb87ed86098c0c70a76e557262a494ff51a30fb193f1c1a32f8e35eafa34a43fcc07aa93a3b7a077d9e35afa07b1a3d -a280214cd3bb0fb7ecd2d8bcf518cbd9078417f2b91d2533ec2717563f090fb84f2a5fcfdbbeb2a2a1f8a71cc5aa5941 -a63083ca7238ea2b57d15a475963cf1d4f550d8cd76db290014a0461b90351f1f26a67d674c837b0b773b330c7c3d534 -a8fa39064cb585ece5263e2f42f430206476bf261bd50f18d2b694889bd79d04d56410664cecad62690e5c5a20b3f6ff -85ba52ce9d700a5dcf6c5b00559acbe599d671ce5512467ff4b6179d7fad550567ce2a9c126a50964e3096458ea87920 -b913501e1008f076e5eac6d883105174f88b248e1c9801e568fefaffa1558e4909364fc6d9512aa4d125cbd7cc895f05 -8eb33b5266c8f2ed4725a6ad147a322e44c9264cf261c933cbbe230a43d47fca0f29ec39756b20561dabafadd5796494 -850ebc8b661a04318c9db5a0515066e6454fa73865aa4908767a837857ecd717387f614acb614a88e075d4edc53a2f5a -a08d6b92d866270f29f4ce23a3f5d99b36b1e241a01271ede02817c8ec3f552a5c562db400766c07b104a331835c0c64 -8131804c89bb3e74e9718bfc4afa547c1005ff676bd4db9604335032b203390cfa54478d45c6c78d1fe31a436ed4be9f -9106d94f23cc1eacec8316f16d6f0a1cc160967c886f51981fdb9f3f12ee1182407d2bb24e5b873de58cb1a3ee915a6b -a13806bfc3eae7a7000c9d9f1bd25e10218d4e67f59ae798b145b098bca3edad2b1040e3fc1e6310e612fb8818f459ac -8c69fbca502046cb5f6db99900a47b34117aef3f4b241690cdb3b84ca2a2fc7833e149361995dc41fa78892525bce746 -852c473150c91912d58ecb05769222fa18312800c3f56605ad29eec9e2d8667b0b81c379048d3d29100ed2773bb1f3c5 -b1767f6074426a00e01095dbb1795beb4e4050c6411792cbad6537bc444c3165d1058bafd1487451f9c5ddd209e0ae7e -80c600a5fe99354ce59ff0f84c760923dc8ff66a30bf47dc0a086181785ceb01f9b951c4e66df800ea6d705e8bc47055 -b5cf19002fbc88a0764865b82afcb4d64a50196ea361e5c71dff7de084f4dcbbc34ec94a45cc9e0247bd51da565981aa -93e67a254ea8ce25e112d93cc927fadaa814152a2c4ec7d9a56eaa1ed47aec99b7e9916b02e64452cc724a6641729bbb -ace70b32491bda18eee4a4d041c3bc9effae9340fe7e6c2f5ad975ee0874c17f1a7da7c96bd85fccff9312c518fac6e9 -ab4cfa02065017dd7f1aadc66f2c92f78f0f11b8597c03a5d69d82cb2eaf95a4476a836ac102908f137662472c8d914b -a40b8cd8deb8ae503d20364d64cab7c2801b7728a9646ed19c65edea6a842756a2f636283494299584ad57f4bb12cd0b -8594e11d5fc2396bcd9dbf5509ce4816dbb2b7305168021c426171fb444d111da5a152d6835ad8034542277011c26c0e -8024de98c26b4c994a66628dc304bb737f4b6859c86ded552c5abb81fd4c6c2e19d5a30beed398a694b9b2fdea1dd06a -8843f5872f33f54df8d0e06166c1857d733995f67bc54abb8dfa94ad92407cf0179bc91b0a50bbb56cdc2b350d950329 -b8bab44c7dd53ef9edf497dcb228e2a41282c90f00ba052fc52d57e87b5c8ab132d227af1fcdff9a12713d1f980bcaae -982b4d7b29aff22d527fd82d2a52601d95549bfb000429bb20789ed45e5abf1f4b7416c7b7c4b79431eb3574b29be658 -8eb1f571b6a1878e11e8c1c757e0bc084bab5e82e897ca9be9b7f4b47b91679a8190bf0fc8f799d9b487da5442415857 -a6e74b588e5af935c8b243e888582ef7718f8714569dd4992920740227518305eb35fab674d21a5551cca44b3e511ef2 -a30fc2f3a4cb4f50566e82307de73cd7bd8fe2c1184e9293c136a9b9e926a018d57c6e4f308c95b9eb8299e94d90a2a1 -a50c5869ca5d2b40722c056a32f918d47e0b65ca9d7863ca7d2fb4a7b64fe523fe9365cf0573733ceaadebf20b48fff8 -83bbdd32c04d17581418cf360749c7a169b55d54f2427390defd9f751f100897b2d800ce6636c5bbc046c47508d60c8c -a82904bdf614de5d8deaff688c8a5e7ac5b3431687acbcda8fa53960b7c417a39c8b2e462d7af91ce6d79260f412db8e -a4362e31ff4b05d278b033cf5eebea20de01714ae16d4115d04c1da4754269873afc8171a6f56c5104bfd7b0db93c3e7 -b5b8daa63a3735581e74a021b684a1038cea77168fdb7fdf83c670c2cfabcfc3ab2fc7359069b5f9048188351aef26b5 -b48d723894b7782d96ac8433c48faca1bdfa5238019c451a7f47d958097cce3ae599b876cf274269236b9d6ff8b6d7ca -98ffff6a61a3a6205c7820a91ca2e7176fab5dba02bc194c4d14942ac421cb254183c705506ab279e4f8db066f941c6c -ae7db24731da2eaa6efc4f7fcba2ecc26940ddd68038dce43acf2cee15b72dc4ef42a7bfdd32946d1ed78786dd7696b3 -a656db14f1de9a7eb84f6301b4acb2fbf78bfe867f48a270e416c974ab92821eb4df1cb881b2d600cfed0034ac784641 -aa315f8ecba85a5535e9a49e558b15f39520fce5d4bf43131bfbf2e2c9dfccc829074f9083e8d49f405fb221d0bc4c3c -90bffba5d9ff40a62f6c8e9fc402d5b95f6077ed58d030c93e321b8081b77d6b8dac3f63a92a7ddc01585cf2c127d66c -abdd733a36e0e0f05a570d0504e73801bf9b5a25ff2c78786f8b805704997acb2e6069af342538c581144d53149fa6d3 -b4a723bb19e8c18a01bd449b1bb3440ddb2017f10bb153da27deb7a6a60e9bb37619d6d5435fbb1ba617687838e01dd0 -870016b4678bab3375516db0187a2108b2e840bae4d264b9f4f27dbbc7cc9cac1d7dc582d7a04d6fd1ed588238e5e513 -80d33d2e20e8fc170aa3cb4f69fffb72aeafb3b5bb4ea0bc79ab55da14142ca19b2d8b617a6b24d537366e3b49cb67c3 -a7ee76aec273aaae03b3b87015789289551969fb175c11557da3ab77e39ab49d24634726f92affae9f4d24003050d974 -8415ea4ab69d779ebd42d0fe0c6aef531d6a465a5739e429b1fcf433ec45aa8296c527e965a20f0ec9f340c9273ea3cf -8c7662520794e8b4405d0b33b5cac839784bc86a5868766c06cbc1fa306dbe334978177417b31baf90ce7b0052a29c56 -902b2abecc053a3dbdea9897ee21e74821f3a1b98b2d560a514a35799f4680322550fd3a728d4f6d64e1de98033c32b8 -a05e84ed9ecab8d508d670c39f2db61ad6e08d2795ec32a3c9d0d3737ef3801618f4fc2a95f90ec2f068606131e076c5 -8b9208ff4d5af0c2e3f53c9375da666773ac57197dfabb0d25b1c8d0588ba7f3c15ee9661bb001297f322ea2fbf6928b -a3c827741b34a03254d4451b5ab74a96f2b9f7fb069e2f5adaf54fd97cc7a4d516d378db5ca07da87d8566d6eef13726 -8509d8a3f4a0ed378e0a1e28ea02f6bf1d7f6c819c6c2f5297c7df54c895b848f841653e32ba2a2c22c2ff739571acb8 -a0ce988b7d3c40b4e496aa83a09e4b5472a2d98679622f32bea23e6d607bc7de1a5374fb162bce0549a67dad948519be -aa8a3dd12bd60e3d2e05f9c683cdcb8eab17fc59134815f8d197681b1bcf65108cba63ac5c58ee632b1e5ed6bba5d474 -8b955f1d894b3aefd883fb4b65f14cd37fc2b9db77db79273f1700bef9973bf3fd123897ea2b7989f50003733f8f7f21 -ac79c00ddac47f5daf8d9418d798d8af89fc6f1682e7e451f71ea3a405b0d36af35388dd2a332af790bc83ca7b819328 -a0d44dd2a4438b809522b130d0938c3fe7c5c46379365dbd1810a170a9aa5818e1c783470dd5d0b6d4ac7edbb7330910 -a30b69e39ad43dd540a43c521f05b51b5f1b9c4eed54b8162374ae11eac25da4f5756e7b70ce9f3c92c2eeceee7431ed -ac43220b762c299c7951222ea19761ab938bf38e4972deef58ed84f4f9c68c230647cf7506d7cbfc08562fcca55f0485 -b28233b46a8fb424cfa386a845a3b5399d8489ceb83c8f3e05c22c934798d639c93718b7b68ab3ce24c5358339e41cbb -ac30d50ee8ce59a10d4b37a3a35e62cdb2273e5e52232e202ca7d7b8d09d28958ee667fae41a7bb6cdc6fe8f6e6c9c85 -b199842d9141ad169f35cc7ff782b274cbaa645fdb727761e0a89edbf0d781a15f8218b4bf4eead326f2903dd88a9cc1 -85e018c7ddcad34bb8285a737c578bf741ccd547e68c734bdb3808380e12c5d4ef60fc896b497a87d443ff9abd063b38 -8c856e6ba4a815bdb891e1276f93545b7072f6cb1a9aa6aa5cf240976f29f4dee01878638500a6bf1daf677b96b54343 -b8a47555fa8710534150e1a3f13eab33666017be6b41005397afa647ea49708565f2b86b77ad4964d140d9ced6b4d585 -8cd1f1db1b2f4c85a3f46211599caf512d5439e2d8e184663d7d50166fd3008f0e9253272f898d81007988435f715881 -b1f34b14612c973a3eceb716dc102b82ab18afef9de7630172c2780776679a7706a4874e1df3eaadf541fb009731807f -b25464af9cff883b55be2ff8daf610052c02df9a5e147a2cf4df6ce63edcdee6dc535c533590084cc177da85c5dc0baa -91c3c4b658b42d8d3448ae1415d4541d02379a40dc51e36a59bd6e7b9ba3ea51533f480c7c6e8405250ee9b96a466c29 -86dc027b95deb74c36a58a1333a03e63cb5ae22d3b29d114cfd2271badb05268c9d0c819a977f5e0c6014b00c1512e3a -ae0e6ff58eb5fa35da5107ebeacf222ab8f52a22bb1e13504247c1dfa65320f40d97b0e6b201cb6613476687cb2f0681 -8f13415d960b9d7a1d93ef28afc2223e926639b63bdefce0f85e945dfc81670a55df288893a0d8b3abe13c5708f82f91 -956f67ca49ad27c1e3a68c1faad5e7baf0160c459094bf6b7baf36b112de935fdfd79fa4a9ea87ea8de0ac07272969f4 -835e45e4a67df9fb51b645d37840b3a15c171d571a10b03a406dd69d3c2f22df3aa9c5cbe1e73f8d767ce01c4914ea9a -919b938e56d4b32e2667469d0bdccb95d9dda3341aa907683ee70a14bbbe623035014511c261f4f59b318b610ac90aa3 -96b48182121ccd9d689bf1dfdc228175564cd68dc904a99c808a7f0053a6f636c9d953e12198bdf2ea49ea92772f2e18 -ac5e5a941d567fa38fdbcfa8cf7f85bb304e3401c52d88752bcd516d1fa9bac4572534ea2205e38423c1df065990790f -ac0bd594fb85a8d4fc26d6df0fa81f11919401f1ecf9168b891ec7f061a2d9368af99f7fd8d9b43b2ce361e7b8482159 -83d92c69ca540d298fe80d8162a1c7af3fa9b49dfb69e85c1d136a3ec39fe419c9fa78e0bb6d96878771fbd37fe92e40 -b35443ae8aa66c763c2db9273f908552fe458e96696b90e41dd509c17a5c04ee178e3490d9c6ba2dc0b8f793c433c134 -923b2d25aa45b2e580ffd94cbb37dc8110f340f0f011217ee1bd81afb0714c0b1d5fb4db86006cdd2457563276f59c59 -96c9125d38fca1a61ac21257b696f8ac3dae78def50285e44d90ea293d591d1c58f703540a7e4e99e070afe4646bbe15 -b57946b2332077fbcdcb406b811779aefd54473b5559a163cd65cb8310679b7e2028aa55c12a1401fdcfcac0e6fae29a -845daedc5cf972883835d7e13c937b63753c2200324a3b8082a6c4abb4be06c5f7c629d4abe4bfaf1d80a1f073eb6ce6 -91a55dfd0efefcd03dc6dacc64ec93b8d296cb83c0ee72400a36f27246e7f2a60e73b7b70ba65819e9cfb73edb7bd297 -8874606b93266455fe8fdd25df9f8d2994e927460af06f2e97dd4d2d90db1e6b06d441b72c2e76504d753badca87fb37 -8ee99e6d231274ff9252c0f4e84549da173041299ad1230929c3e3d32399731c4f20a502b4a307642cac9306ccd49d3c -8836497714a525118e20849d6933bb8535fb6f72b96337d49e3133d936999c90a398a740f42e772353b5f1c63581df6d -a6916945e10628f7497a6cdc5e2de113d25f7ade3e41e74d3de48ccd4fce9f2fa9ab69645275002e6f49399b798c40af -9597706983107eb23883e0812e1a2c58af7f3499d50c6e29b455946cb9812fde1aa323d9ed30d1c0ffd455abe32303cd -a24ee89f7f515cc33bdbdb822e7d5c1877d337f3b2162303cfc2dae028011c3a267c5cb4194afa63a4856a6e1c213448 -8cd25315e4318801c2776824ae6e7d543cb85ed3bc2498ba5752df2e8142b37653cf9e60104d674be3aeb0a66912e97a -b5085ecbe793180b40dbeb879f4c976eaaccaca3a5246807dced5890e0ed24d35f3f86955e2460e14fb44ff5081c07ba -960188cc0b4f908633a6840963a6fa2205fc42c511c6c309685234911c5304ef4c304e3ae9c9c69daa2fb6a73560c256 -a32d0a70bf15d569b4cda5aebe3e41e03c28bf99cdd34ffa6c5d58a097f322772acca904b3a47addb6c7492a7126ebac -977f72d06ad72d4aa4765e0f1f9f4a3231d9f030501f320fe7714cc5d329d08112789fa918c60dd7fdb5837d56bb7fc6 -99fa038bb0470d45852bb871620d8d88520adb701712fcb1f278fed2882722b9e729e6cdce44c82caafad95e37d0e6f7 -b855e8f4fc7634ada07e83b6c719a1e37acb06394bc8c7dcab7747a8c54e5df3943915f021364bd019fdea103864e55f -88bc2cd7458532e98c596ef59ea2cf640d7cc31b4c33cef9ed065c078d1d4eb49677a67de8e6229cc17ea48bace8ee5a -aaa78a3feaa836d944d987d813f9b9741afb076e6aca1ffa42682ab06d46d66e0c07b8f40b9dbd63e75e81efa1ef7b08 -b7b080420cc4d808723b98b2a5b7b59c81e624ab568ecdfdeb8bf3aa151a581b6f56e983ef1b6f909661e25db40b0c69 -abee85c462ac9a2c58e54f06c91b3e5cd8c5f9ab5b5deb602b53763c54826ed6deb0d6db315a8d7ad88733407e8d35e2 -994d075c1527407547590df53e9d72dd31f037c763848d1662eebd4cefec93a24328c986802efa80e038cb760a5300f5 -ab8777640116dfb6678e8c7d5b36d01265dfb16321abbfc277da71556a34bb3be04bc4ae90124ed9c55386d2bfb3bda0 -967e3a828bc59409144463bcf883a3a276b5f24bf3cbfdd7a42343348cba91e00b46ac285835a9b91eef171202974204 -875a9f0c4ffe5bb1d8da5e3c8e41d0397aa6248422a628bd60bfae536a651417d4e8a7d2fb98e13f2dad3680f7bd86d3 -acaa330c3e8f95d46b1880126572b238dbb6d04484d2cd4f257ab9642d8c9fc7b212188b9c7ac9e0fd135c520d46b1bf -aceb762edbb0f0c43dfcdb01ea7a1ac5918ca3882b1e7ebc4373521742f1ed5250d8966b498c00b2b0f4d13212e6dd0b -81d072b4ad258b3646f52f399bced97c613b22e7ad76373453d80b1650c0ca87edb291a041f8253b649b6e5429bb4cff -980a47d27416ac39c7c3a0ebe50c492f8c776ea1de44d5159ac7d889b6d554357f0a77f0e5d9d0ff41aae4369eba1fc2 -8b4dfd5ef5573db1476d5e43aacfb5941e45d6297794508f29c454fe50ea622e6f068b28b3debe8635cf6036007de2e3 -a60831559d6305839515b68f8c3bc7abbd8212cc4083502e19dd682d56ca37c9780fc3ce4ec2eae81ab23b221452dc57 -951f6b2c1848ced9e8a2339c65918e00d3d22d3e59a0a660b1eca667d18f8430d737884e9805865ef3ed0fe1638a22d9 -b02e38fe790b492aa5e89257c4986c9033a8b67010fa2add9787de857d53759170fdd67715ca658220b4e14b0ca48124 -a51007e4346060746e6b0e4797fc08ef17f04a34fe24f307f6b6817edbb8ce2b176f40771d4ae8a60d6152cbebe62653 -a510005b05c0b305075b27b243c9d64bcdce85146b6ed0e75a3178b5ff9608213f08c8c9246f2ca6035a0c3e31619860 -aaff4ef27a7a23be3419d22197e13676d6e3810ceb06a9e920d38125745dc68a930f1741c9c2d9d5c875968e30f34ab5 -864522a9af9857de9814e61383bebad1ba9a881696925a0ea6bfc6eff520d42c506bbe5685a9946ed710e889765be4a0 -b63258c080d13f3b7d5b9f3ca9929f8982a6960bdb1b0f8676f4dca823971601672f15e653917bf5d3746bb220504913 -b51ce0cb10869121ae310c7159ee1f3e3a9f8ad498827f72c3d56864808c1f21fa2881788f19ece884d3f705cd7bd0c5 -95d9cecfc018c6ed510e441cf84c712d9909c778c16734706c93222257f64dcd2a9f1bd0b400ca271e22c9c487014274 -8beff4d7d0140b86380ff4842a9bda94c2d2be638e20ac68a4912cb47dbe01a261857536375208040c0554929ced1ddc -891ff49258749e2b57c1e9b8e04b12c77d79c3308b1fb615a081f2aacdfb4b39e32d53e069ed136fdbd43c53b87418fa -9625cad224e163d387738825982d1e40eeff35fe816d10d7541d15fdc4d3eee48009090f3faef4024b249205b0b28f72 -8f3947433d9bd01aa335895484b540a9025a19481a1c40b4f72dd676bfcf332713714fd4010bde936eaf9470fd239ed0 -a00ec2d67789a7054b53f0e858a8a232706ccc29a9f3e389df7455f1a51a2e75801fd78469a13dbc25d28399ae4c6182 -a3f65884506d4a62b8775a0ea0e3d78f5f46bc07910a93cd604022154eabdf1d73591e304d61edc869e91462951975e1 -a14eef4fd5dfac311713f0faa9a60415e3d30b95a4590cbf95f2033dffb4d16c02e7ceff3dcd42148a4e3bc49cce2dd4 -8afa11c0eef3c540e1e3460bc759bb2b6ea90743623f88e62950c94e370fe4fd01c22b6729beba4dcd4d581198d9358f -afb05548a69f0845ffcc5f5dc63e3cdb93cd270f5655173b9a950394b0583663f2b7164ba6df8d60c2e775c1d9f120af -97f179e01a947a906e1cbeafa083960bc9f1bade45742a3afee488dfb6011c1c6e2db09a355d77f5228a42ccaa7bdf8e -8447fca4d35f74b3efcbd96774f41874ca376bf85b79b6e66c92fa3f14bdd6e743a051f12a7fbfd87f319d1c6a5ce217 -a57ca39c23617cd2cf32ff93b02161bd7baf52c4effb4679d9d5166406e103bc8f3c6b5209e17c37dbb02deb8bc72ddd -9667c7300ff80f0140be002b0e36caab07aaee7cce72679197c64d355e20d96196acaf54e06e1382167d081fe6f739c1 -828126bb0559ce748809b622677267ca896fa2ee76360fd2c02990e6477e06a667241379ca7e65d61a5b64b96d7867de -8b8835dea6ba8cf61c91f01a4b3d2f8150b687a4ee09b45f2e5fc8f80f208ae5d142d8e3a18153f0722b90214e60c5a7 -a98e8ff02049b4da386e3ee93db23bbb13dfeb72f1cfde72587c7e6d962780b7671c63e8ac3fbaeb1a6605e8d79e2f29 -87a4892a0026d7e39ef3af632172b88337cb03669dea564bcdb70653b52d744730ebb5d642e20cb627acc9dbb547a26b -877352a22fc8052878a57effc159dac4d75fe08c84d3d5324c0bab6d564cdf868f33ceee515eee747e5856b62cfa0cc7 -8b801ba8e2ff019ee62f64b8cb8a5f601fc35423eb0f9494b401050103e1307dc584e4e4b21249cd2c686e32475e96c3 -a9e7338d6d4d9bfec91b2af28a8ed13b09415f57a3a00e5e777c93d768fdb3f8e4456ae48a2c6626b264226e911a0e28 -99c05fedf40ac4726ed585d7c1544c6e79619a0d3fb6bda75a08c7f3c0008e8d5e19ed4da48de3216135f34a15eba17c -a61cce8a1a8b13a4a650fdbec0eeea8297c352a8238fb7cac95a0df18ed16ee02a3daa2de108fa122aca733bd8ad7855 -b97f37da9005b440b4cb05870dd881bf8491fe735844f2d5c8281818583b38e02286e653d9f2e7fa5e74c3c3eb616540 -a72164a8554da8e103f692ac5ebb4aece55d5194302b9f74b6f2a05335b6e39beede0bf7bf8c5bfd4d324a784c5fb08c -b87e8221c5341cd9cc8bb99c10fe730bc105550f25ed4b96c0d45e6142193a1b2e72f1b3857373a659b8c09be17b3d91 -a41fb1f327ef91dcb7ac0787918376584890dd9a9675c297c45796e32d6e5985b12f9b80be47fc3a8596c245f419d395 -90dafa3592bdbb3465c92e2a54c2531822ba0459d45d3e7a7092fa6b823f55af28357cb51896d4ec2d66029c82f08e26 -a0a9adc872ebc396557f484f1dd21954d4f4a21c4aa5eec543f5fa386fe590839735c01f236574f7ff95407cd12de103 -b8c5c940d58be7538acf8672852b5da3af34f82405ef2ce8e4c923f1362f97fc50921568d0fd2fe846edfb0823e62979 -85aaf06a8b2d0dac89dafd00c28533f35dbd074978c2aaa5bef75db44a7b12aeb222e724f395513b9a535809a275e30b -81f3cbe82fbc7028c26a6c1808c604c63ba023a30c9f78a4c581340008dbda5ec07497ee849a2183fcd9124f7936af32 -a11ac738de75fd60f15a34209d3825d5e23385796a4c7fc5931822f3f380af977dd0f7b59fbd58eed7777a071e21b680 -85a279c493de03db6fa6c3e3c1b1b29adc9a8c4effc12400ae1128da8421954fa8b75ad19e5388fe4543b76fb0812813 -83a217b395d59ab20db6c4adb1e9713fc9267f5f31a6c936042fe051ce8b541f579442f3dcf0fa16b9e6de9fd3518191 -83a0b86e7d4ed8f9ccdc6dfc8ff1484509a6378fa6f09ed908e6ab9d1073f03011dc497e14304e4e3d181b57de06a5ab -a63ad69c9d25704ce1cc8e74f67818e5ed985f8f851afa8412248b2df5f833f83b95b27180e9e7273833ed0d07113d3b -99b1bc2021e63b561fe44ddd0af81fcc8627a91bfeecbbc989b642bc859abc0c8d636399701aad7bbaf6a385d5f27d61 -b53434adb66f4a807a6ad917c6e856321753e559b1add70824e5c1e88191bf6993fccb9b8b911fc0f473fb11743acacd -97ed3b9e6fb99bf5f945d4a41f198161294866aa23f2327818cdd55cb5dc4c1a8eff29dd8b8d04902d6cd43a71835c82 -b1e808260e368a18d9d10bdea5d60223ba1713b948c782285a27a99ae50cc5fc2c53d407de07155ecc16fb8a36d744a0 -a3eb4665f18f71833fec43802730e56b3ee5a357ea30a888ad482725b169d6f1f6ade6e208ee081b2e2633079b82ba7d -ab8beb2c8353fc9f571c18fdd02bdb977fc883313469e1277b0372fbbb33b80dcff354ca41de436d98d2ed710faa467e -aa9071cfa971e4a335a91ad634c98f2be51544cb21f040f2471d01bb97e1df2277ae1646e1ea8f55b7ba9f5c8c599b39 -80b7dbfdcaf40f0678012acc634eba44ea51181475180d9deb2050dc4f2de395289edd0223018c81057ec79b04b04c49 -89623d7f6cb17aa877af14de842c2d4ab7fd576d61ddd7518b5878620a01ded40b6010de0da3cdf31d837eecf30e9847 -a773bb024ae74dd24761f266d4fb27d6fd366a8634febe8235376b1ae9065c2fe12c769f1d0407867dfbe9f5272c352f -8455a561c3aaa6ba64c881a5e13921c592b3a02e968f4fb24a2243c36202795d0366d9cc1a24e916f84d6e158b7aeac7 -81d8bfc4b283cf702a40b87a2b96b275bdbf0def17e67d04842598610b67ea08c804d400c3e69fa09ea001eaf345b276 -b8f8f82cb11fea1c99467013d7e167ff03deb0c65a677fab76ded58826d1ba29aa7cf9fcd7763615735ea3ad38e28719 -89a6a04baf9cccc1db55179e1650b1a195dd91fb0aebc197a25143f0f393524d2589975e3fbfc2547126f0bced7fd6f2 -b81b2162df045390f04df07cbd0962e6b6ca94275a63edded58001a2f28b2ae2af2c7a6cba4ecd753869684e77e7e799 -a3757f722776e50de45c62d9c4a2ee0f5655a512344c4cbec542d8045332806568dd626a719ef21a4eb06792ca70f204 -8c5590df96ec22179a4e8786de41beb44f987a1dcc508eb341eecbc0b39236fdfad47f108f852e87179ccf4e10091e59 -87502f026ed4e10167419130b88c3737635c5b9074c364e1dd247cef5ef0fc064b4ae99b187e33301e438bbd2fe7d032 -af925a2165e980ced620ff12289129fe17670a90ae0f4db9d4b39bd887ccb1f5d2514ac9ecf910f6390a8fc66bd5be17 -857fca899828cf5c65d26e3e8a6e658542782fc72762b3b9c73514919f83259e0f849a9d4838b40dc905fe43024d0d23 -87ffebdbfb69a9e1007ebac4ffcb4090ff13705967b73937063719aa97908986effcb7262fdadc1ae0f95c3690e3245d -a9ff6c347ac6f4c6ab993b748802e96982eaf489dc69032269568412fc9a79e7c2850dfc991b28211b3522ee4454344b -a65b3159df4ec48bebb67cb3663cd744027ad98d970d620e05bf6c48f230fa45bf17527fe726fdf705419bb7a1bb913e -84b97b1e6408b6791831997b03cd91f027e7660fd492a93d95daafe61f02427371c0e237c75706412f442991dfdff989 -ab761c26527439b209af0ae6afccd9340bbed5fbe098734c3145b76c5d2cd7115d9227b2eb523882b7317fbb09180498 -a0479a8da06d7a69c0b0fee60df4e691c19c551f5e7da286dab430bfbcabf31726508e20d26ea48c53365a7f00a3ad34 -a732dfc9baa0f4f40b5756d2e8d8937742999623477458e0bc81431a7b633eefc6f53b3b7939fe0a020018549c954054 -901502436a1169ba51dc479a5abe7c8d84e0943b16bc3c6a627b49b92cd46263c0005bc324c67509edd693f28e612af1 -b627aee83474e7f84d1bab9b7f6b605e33b26297ac6bbf52d110d38ba10749032bd551641e73a383a303882367af429b -95108866745760baef4a46ef56f82da6de7e81c58b10126ebd2ba2cd13d339f91303bf2fb4dd104a6956aa3b13739503 -899ed2ade37236cec90056f3569bc50f984f2247792defafcceb49ad0ca5f6f8a2f06573705300e07f0de0c759289ff5 -a9f5eee196d608efe4bcef9bf71c646d27feb615e21252cf839a44a49fd89da8d26a758419e0085a05b1d59600e2dc42 -b36c6f68fed6e6c85f1f4a162485f24817f2843ec5cbee45a1ebfa367d44892e464949c6669f7972dc7167af08d55d25 -aaaede243a9a1b6162afbc8f571a52671a5a4519b4062e3f26777664e245ba873ed13b0492c5dbf0258c788c397a0e9e -972b4fb39c31cbe127bf9a32a5cc10d621ebdd9411df5e5da3d457f03b2ab2cd1f6372d8284a4a9400f0b06ecdbfd38e -8f6ca1e110e959a4b1d9a5ce5f212893cec21db40d64d5ac4d524f352d72198f923416a850bf845bc5a22a79c0ea2619 -a0f3c93b22134f66f04b2553a53b738644d1665ceb196b8494b315a4c28236fb492017e4a0de4224827c78e42f9908b7 -807fb5ee74f6c8735b0b5ca07e28506214fe4047dbeb00045d7c24f7849e98706aea79771241224939cb749cf1366c7d -915eb1ff034224c0b645442cdb7d669303fdc00ca464f91aaf0b6fde0b220a3a74ff0cb043c26c9f3a5667b3fdaa9420 -8fda6cef56ed33fefffa9e6ac8e6f76b1af379f89761945c63dd448801f7bb8ca970504a7105fac2f74f652ccff32327 -87380cffdcffb1d0820fa36b63cc081e72187f86d487315177d4d04da4533eb19a0e2ff6115ceab528887819c44a5164 -8cd89e03411a18e7f16f968b89fb500c36d47d229f6487b99e62403a980058db5925ce249206743333538adfad168330 -974451b1df33522ce7056de9f03e10c70bf302c44b0741a59df3d6877d53d61a7394dcee1dd46e013d7cb9d73419c092 -98c35ddf645940260c490f384a49496a7352bb8e3f686feed815b1d38f59ded17b1ad6e84a209e773ed08f7b8ff1e4c2 -963f386cf944bb9b2ddebb97171b64253ea0a2894ac40049bdd86cda392292315f3a3d490ca5d9628c890cfb669f0acb -8d507712152babd6d142ee682638da8495a6f3838136088df9424ef50d5ec28d815a198c9a4963610b22e49b4cdf95e9 -83d4bc6b0be87c8a4f1e9c53f257719de0c73d85b490a41f7420e777311640937320557ff2f1d9bafd1daaa54f932356 -82f5381c965b7a0718441131c4d13999f4cdce637698989a17ed97c8ea2e5bdb5d07719c5f7be8688edb081b23ede0f4 -a6ebecab0b72a49dfd01d69fa37a7f74d34fb1d4fef0aa10e3d6fceb9eccd671225c230af89f6eb514250e41a5f91f52 -846d185bdad6e11e604df7f753b7a08a28b643674221f0e750ebdb6b86ec584a29c869e131bca868972a507e61403f6a -85a98332292acb744bd1c0fd6fdcf1f889a78a2c9624d79413ffa194cc8dfa7821a4b60cde8081d4b5f71f51168dd67f -8f7d97c3b4597880d73200d074eb813d95432306e82dafc70b580b8e08cb8098b70f2d07b4b3ac6a4d77e92d57035031 -8185439c8751e595825d7053518cbe121f191846a38d4dbcb558c3f9d7a3104f3153401adaaaf27843bbe2edb504bfe3 -b3c00d8ece1518fca6b1215a139b0a0e26d9cba1b3a424f7ee59f30ce800a5db967279ed60958dd1f3ee69cf4dd1b204 -a2e6cb6978e883f9719c3c0d44cfe8de0cc6f644b98f98858433bea8bbe7b612c8aca5952fccce4f195f9d54f9722dc2 -99663087e3d5000abbec0fbda4e7342ec38846cc6a1505191fb3f1a337cb369455b7f8531a6eb8b0f7b2c4baf83cbe2b -ab0836c6377a4dbc7ca6a4d6cf021d4cd60013877314dd05f351706b128d4af6337711ed3443cb6ca976f40d74070a9a -87abfd5126152fd3bac3c56230579b489436755ea89e0566aa349490b36a5d7b85028e9fb0710907042bcde6a6f5d7e3 -974ba1033f75f60e0cf7c718a57ae1da3721cf9d0fb925714c46f027632bdd84cd9e6de4cf4d00bc55465b1c5ebb7384 -a607b49d73689ac64f25cec71221d30d53e781e1100d19a2114a21da6507a60166166369d860bd314acb226596525670 -a7c2b0b915d7beba94954f2aa7dd08ec075813661e2a3ecca5d28a0733e59583247fed9528eb28aba55b972cdbaf06eb -b8b3123e44128cc8efbe3270f2f94e50ca214a4294c71c3b851f8cbb70cb67fe9536cf07d04bf7fe380e5e3a29dd3c15 -a59a07e343b62ad6445a0859a32b58c21a593f9ddbfe52049650f59628c93715aa1f4e1f45b109321756d0eeec8a5429 -94f51f8a4ed18a6030d0aaa8899056744bd0e9dc9ac68f62b00355cddab11da5da16798db75f0bfbce0e5bdfe750c0b6 -97460a97ca1e1fa5ce243b81425edc0ec19b7448e93f0b55bc9785eedeeafe194a3c8b33a61a5c72990edf375f122777 -8fa859a089bc17d698a7ee381f37ce9beadf4e5b44fce5f6f29762bc04f96faff5d58c48c73631290325f05e9a1ecf49 -abdf38f3b20fc95eff31de5aa9ef1031abfa48f1305ee57e4d507594570401503476d3bcc493838fc24d6967a3082c7f -b8914bfb82815abb86da35c64d39ab838581bc0bf08967192697d9663877825f2b9d6fbdcf9b410463482b3731361aef -a8187f9d22b193a5f578999954d6ec9aa9b32338ccadb8a3e1ce5bad5ea361d69016e1cdfac44e9d6c54e49dd88561b9 -aac262cb7cba7fd62c14daa7b39677cabc1ef0947dd06dd89cac8570006a200f90d5f0353e84f5ff03179e3bebe14231 -a630ef5ece9733b8c46c0a2df14a0f37647a85e69c63148e79ffdcc145707053f9f9d305c3f1cf3c7915cb46d33abd07 -b102c237cb2e254588b6d53350dfda6901bd99493a3fbddb4121d45e0b475cf2663a40d7b9a75325eda83e4ba1e68cb3 -86a930dd1ddcc16d1dfa00aa292cb6c2607d42c367e470aa920964b7c17ab6232a7108d1c2c11fc40fb7496547d0bbf8 -a832fdc4500683e72a96cce61e62ac9ee812c37fe03527ad4cf893915ca1962cee80e72d4f82b20c8fc0b764376635a1 -88ad985f448dabb04f8808efd90f273f11f5e6d0468b5489a1a6a3d77de342992a73eb842d419034968d733f101ff683 -98a8538145f0d86f7fbf9a81c9140f6095c5bdd8960b1c6f3a1716428cd9cca1bf8322e6d0af24e6169abcf7df2b0ff6 -9048c6eba5e062519011e177e955a200b2c00b3a0b8615bdecdebc217559d41058d3315f6d05617be531ef0f6aef0e51 -833bf225ab6fc68cdcacf1ec1b50f9d05f5410e6cdcd8d56a3081dc2be8a8d07b81534d1ec93a25c2e270313dfb99e3b -a84bcd24c3da5e537e64a811b93c91bfc84d7729b9ead7f79078989a6eb76717d620c1fad17466a0519208651e92f5ff -b7cdd0a3fbd79aed93e1b5a44ca44a94e7af5ed911e4492f332e3a5ed146c7286bde01b52276a2fcc02780d2109874dd -8a19a09854e627cb95750d83c20c67442b66b35896a476358f993ba9ac114d32c59c1b3d0b8787ee3224cf3888b56c64 -a9abd5afb8659ee52ada8fa5d57e7dd355f0a7350276f6160bec5fbf70d5f99234dd179eb221c913e22a49ec6d267846 -8c13c4274c0d30d184e73eaf812200094bbbd57293780bdadbceb262e34dee5b453991e7f37c7333a654fc71c69d6445 -a4320d73296ff8176ce0127ca1921c450e2a9c06eff936681ebaffb5a0b05b17fded24e548454de89aca2dcf6d7a9de4 -b2b8b3e15c1f645f07783e5628aba614e60157889db41d8161d977606788842b67f83f361eae91815dc0abd84e09abd5 -ad26c3aa35ddfddc15719b8bb6c264aaec7065e88ac29ba820eb61f220fef451609a7bb037f3722d022e6c86e4f1dc88 -b8615bf43e13ae5d7b8dd903ce37190800cd490f441c09b22aa29d7a29ed2c0417b7a08ead417868f1de2589deaadd80 -8d3425e1482cd1e76750a76239d33c06b3554c3c3c87c15cb7ab58b1cee86a4c5c4178b44e23f36928365a1b484bde02 -806893a62e38c941a7dd6f249c83af16596f69877cc737d8f73f6b8cd93cbc01177a7a276b2b8c6b0e5f2ad864db5994 -86618f17fa4b0d65496b661bbb5ba3bc3a87129d30a4b7d4f515b904f4206ca5253a41f49fd52095861e5e065ec54f21 -9551915da1304051e55717f4c31db761dcdcf3a1366c89a4af800a9e99aca93a357bf928307f098e62b44a02cb689a46 -8f79c4ec0ec1146cb2a523b52fe33def90d7b5652a0cb9c2d1c8808a32293e00aec6969f5b1538e3a94cd1efa3937f86 -a0c03e329a707300081780f1e310671315b4c6a4cedcb29697aedfabb07a9d5df83f27b20e9c44cf6b16e39d9ded5b98 -86a7cfa7c8e7ce2c01dd0baec2139e97e8e090ad4e7b5f51518f83d564765003c65968f85481bbb97cb18f005ccc7d9f -a33811770c6dfda3f7f74e6ad0107a187fe622d61b444bbd84fd7ef6e03302e693b093df76f6ab39bb4e02afd84a575a -85480f5c10d4162a8e6702b5e04f801874d572a62a130be94b0c02b58c3c59bdcd48cd05f0a1c2839f88f06b6e3cd337 -8e181011564b17f7d787fe0e7f3c87f6b62da9083c54c74fd6c357a1f464c123c1d3d8ade3cf72475000b464b14e2be3 -8ee178937294b8c991337e0621ab37e9ffa4ca2bdb3284065c5e9c08aad6785d50cf156270ff9daf9a9127289710f55b -8bd1e8e2d37379d4b172f1aec96f2e41a6e1393158d7a3dbd9a95c8dd4f8e0b05336a42efc11a732e5f22b47fc5c271d -8f3da353cd487c13136a85677de8cedf306faae0edec733cf4f0046f82fa4639db4745b0095ff33a9766aba50de0cbcf -8d187c1e97638df0e4792b78e8c23967dac43d98ea268ca4aabea4e0fa06cb93183fd92d4c9df74118d7cc27bf54415e -a4c992f08c2f8bac0b74b3702fb0c75c9838d2ce90b28812019553d47613c14d8ce514d15443159d700b218c5a312c49 -a6fd1874034a34c3ea962a316c018d9493d2b3719bb0ec4edbc7c56b240802b2228ab49bee6f04c8a3e9f6f24a48c1c2 -b2efed8e799f8a15999020900dc2c58ece5a3641c90811b86a5198e593d7318b9d53b167818ccdfbe7df2414c9c34011 -995ff7de6181ddf95e3ead746089c6148da3508e4e7a2323c81785718b754d356789b902e7e78e2edc6b0cbd4ff22c78 -944073d24750a9068cbd020b834afc72d2dde87efac04482b3287b40678ad07588519a4176b10f2172a2c463d063a5cd -99db4b1bb76475a6fd75289986ef40367960279524378cc917525fb6ba02a145a218c1e9caeb99332332ab486a125ac0 -89fce4ecd420f8e477af4353b16faabb39e063f3f3c98fde2858b1f2d1ef6eed46f0975a7c08f233b97899bf60ccd60a -8c09a4f07a02b80654798bc63aada39fd638d3e3c4236ccd8a5ca280350c31e4a89e5f4c9aafb34116e71da18c1226b8 -85325cfa7ded346cc51a2894257eab56e7488dbff504f10f99f4cd2b630d913003761a50f175ed167e8073f1b6b63fb0 -b678b4fbec09a8cc794dcbca185f133578f29e354e99c05f6d07ac323be20aecb11f781d12898168e86f2e0f09aca15e -a249cfcbca4d9ba0a13b5f6aac72bf9b899adf582f9746bb2ad043742b28915607467eb794fca3704278f9136f7642be -9438e036c836a990c5e17af3d78367a75b23c37f807228362b4d13e3ddcb9e431348a7b552d09d11a2e9680704a4514f -925ab70450af28c21a488bfb5d38ac994f784cf249d7fd9ad251bb7fd897a23e23d2528308c03415074d43330dc37ef4 -a290563904d5a8c0058fc8330120365bdd2ba1fdbaef7a14bc65d4961bb4217acfaed11ab82669e359531f8bf589b8db -a7e07a7801b871fc9b981a71e195a3b4ba6b6313bc132b04796a125157e78fe5c11a3a46cf731a255ac2d78a4ae78cd0 -b26cd2501ee72718b0eebab6fb24d955a71f363f36e0f6dff0ab1d2d7836dab88474c0cef43a2cc32701fca7e82f7df3 -a1dc3b6c968f3de00f11275092290afab65b2200afbcfa8ddc70e751fa19dbbc300445d6d479a81bda3880729007e496 -a9bc213e28b630889476a095947d323b9ac6461dea726f2dc9084473ae8e196d66fb792a21905ad4ec52a6d757863e7d -b25d178df8c2df8051e7c888e9fa677fde5922e602a95e966db9e4a3d6b23ce043d7dc48a5b375c6b7c78e966893e8c3 -a1c8d88d72303692eaa7adf68ea41de4febec40cc14ae551bb4012afd786d7b6444a3196b5d9d5040655a3366d96b7cd -b22bd44f9235a47118a9bbe2ba5a2ba9ec62476061be2e8e57806c1a17a02f9a51403e849e2e589520b759abd0117683 -b8add766050c0d69fe81d8d9ea73e1ed05f0135d093ff01debd7247e42dbb86ad950aceb3b50b9af6cdc14ab443b238f -af2cf95f30ef478f018cf81d70d47d742120b09193d8bb77f0d41a5d2e1a80bfb467793d9e2471b4e0ad0cb2c3b42271 -8af5ef2107ad284e246bb56e20fef2a255954f72de791cbdfd3be09f825298d8466064f3c98a50496c7277af32b5c0bc -85dc19558572844c2849e729395a0c125096476388bd1b14fa7f54a7c38008fc93e578da3aac6a52ff1504d6ca82db05 -ae8c9b43c49572e2e166d704caf5b4b621a3b47827bb2a3bcd71cdc599bba90396fd9a405261b13e831bb5d44c0827d7 -a7ba7efede25f02e88f6f4cbf70643e76784a03d97e0fbd5d9437c2485283ad7ca3abb638a5f826cd9f6193e5dec0b6c -94a9d122f2f06ef709fd8016fd4b712d88052245a65a301f5f177ce22992f74ad05552b1f1af4e70d1eac62cef309752 -82d999b3e7cf563833b8bc028ff63a6b26eb357dfdb3fd5f10e33a1f80a9b2cfa7814d871b32a7ebfbaa09e753e37c02 -aec6edcde234df502a3268dd2c26f4a36a2e0db730afa83173f9c78fcb2b2f75510a02b80194327b792811caefda2725 -94c0bfa66c9f91d462e9194144fdd12d96f9bbe745737e73bab8130607ee6ea9d740e2cfcbbd00a195746edb6369ee61 -ab7573dab8c9d46d339e3f491cb2826cabe8b49f85f1ede78d845fc3995537d1b4ab85140b7d0238d9c24daf0e5e2a7e -87e8b16832843251fe952dadfd01d41890ed4bb4b8fa0254550d92c8cced44368225eca83a6c3ad47a7f81ff8a80c984 -9189d2d9a7c64791b19c0773ad4f0564ce6bea94aa275a917f78ad987f150fdb3e5e26e7fef9982ac184897ecc04683f -b3661bf19e2da41415396ae4dd051a9272e8a2580b06f1a1118f57b901fa237616a9f8075af1129af4eabfefedbe2f1c -af43c86661fb15daf5d910a4e06837225e100fb5680bd3e4b10f79a2144c6ec48b1f8d6e6b98e067d36609a5d038889a -82ac0c7acaa83ddc86c5b4249aae12f28155989c7c6b91e5137a4ce05113c6cbc16f6c44948b0efd8665362d3162f16a -8f268d1195ab465beeeb112cd7ffd5d5548559a8bc01261106d3555533fc1971081b25558d884d552df0db1cddda89d8 -8ef7caa5521f3e037586ce8ac872a4182ee20c7921c0065ed9986c047e3dda08294da1165f385d008b40d500f07d895f -8c2f98f6880550573fad46075d3eba26634b5b025ce25a0b4d6e0193352c8a1f0661064027a70fe8190b522405f9f4e3 -b7653f353564feb164f0f89ec7949da475b8dad4a4d396d252fc2a884f6932d027b7eb2dc4d280702c74569319ed701a -a026904f4066333befd9b87a8fad791d014096af60cdd668ef919c24dbe295ff31f7a790e1e721ba40cf5105abca67f4 -988f982004ada07a22dd345f2412a228d7a96b9cae2c487de42e392afe1e35c2655f829ce07a14629148ce7079a1f142 -9616add009067ed135295fb74d5b223b006b312bf14663e547a0d306694ff3a8a7bb9cfc466986707192a26c0bce599f -ad4c425de9855f6968a17ee9ae5b15e0a5b596411388cf976df62ecc6c847a6e2ddb2cea792a5f6e9113c2445dba3e5c -b698ac9d86afa3dc69ff8375061f88e3b0cff92ff6dfe747cebaf142e813c011851e7a2830c10993b715e7fd594604a9 -a386fa189847bb3b798efca917461e38ead61a08b101948def0f82cd258b945ed4d45b53774b400af500670149e601b7 -905c95abda2c68a6559d8a39b6db081c68cef1e1b4be63498004e1b2f408409be9350b5b5d86a30fd443e2b3e445640a -9116dade969e7ce8954afcdd43e5cab64dc15f6c1b8da9d2d69de3f02ba79e6c4f6c7f54d6bf586d30256ae405cd1e41 -a3084d173eacd08c9b5084a196719b57e47a0179826fda73466758235d7ecdb87cbcf097bd6b510517d163a85a7c7edd -85bb00415ad3c9be99ff9ba83672cc59fdd24356b661ab93713a3c8eab34e125d8867f628a3c3891b8dc056e69cd0e83 -8d58541f9f39ed2ee4478acce5d58d124031338ec11b0d55551f00a5a9a6351faa903a5d7c132dc5e4bb026e9cbd18e4 -a622adf72dc250e54f672e14e128c700166168dbe0474cecb340da175346e89917c400677b1bc1c11fcc4cc26591d9db -b3f865014754b688ca8372e8448114fff87bf3ca99856ab9168894d0c4679782c1ced703f5b74e851b370630f5e6ee86 -a7e490b2c40c2446fcd91861c020da9742c326a81180e38110558bb5d9f2341f1c1885e79b364e6419023d1cbdc47380 -b3748d472b1062e54572badbb8e87ac36534407f74932e7fc5b8392d008e8e89758f1671d1e4d30ab0fa40551b13bb5e -89898a5c5ec4313aabc607b0049fd1ebad0e0c074920cf503c9275b564d91916c2c446d3096491c950b7af3ac5e4b0ed -8eb8c83fef2c9dd30ea44e286e9599ec5c20aba983f702e5438afe2e5b921884327ad8d1566c72395587efac79ca7d56 -b92479599e806516ce21fb0bd422a1d1d925335ebe2b4a0a7e044dd275f30985a72b97292477053ac5f00e081430da80 -a34ae450a324fe8a3c25a4d653a654f9580ed56bbea213b8096987bbad0f5701d809a17076435e18017fea4d69f414bc -81381afe6433d62faf62ea488f39675e0091835892ecc238e02acf1662669c6d3962a71a3db652f6fe3bc5f42a0e5dc5 -a430d475bf8580c59111103316fe1aa79c523ea12f1d47a976bbfae76894717c20220e31cf259f08e84a693da6688d70 -b842814c359754ece614deb7d184d679d05d16f18a14b288a401cef5dad2cf0d5ee90bad487b80923fc5573779d4e4e8 -971d9a2627ff2a6d0dcf2af3d895dfbafca28b1c09610c466e4e2bff2746f8369de7f40d65b70aed135fe1d72564aa88 -8f4ce1c59e22b1ce7a0664caaa7e53735b154cfba8d2c5cc4159f2385843de82ab58ed901be876c6f7fce69cb4130950 -86cc9dc321b6264297987000d344fa297ef45bcc2a4df04e458fe2d907ad304c0ea2318e32c3179af639a9a56f3263cf -8229e0876dfe8f665c3fb19b250bd89d40f039bbf1b331468b403655be7be2e104c2fd07b9983580c742d5462ca39a43 -99299d73066e8eb128f698e56a9f8506dfe4bd014931e86b6b487d6195d2198c6c5bf15cccb40ccf1f8ddb57e9da44a2 -a3a3be37ac554c574b393b2f33d0a32a116c1a7cfeaf88c54299a4da2267149a5ecca71f94e6c0ef6e2f472b802f5189 -a91700d1a00387502cdba98c90f75fbc4066fefe7cc221c8f0e660994c936badd7d2695893fde2260c8c11d5bdcdd951 -8e03cae725b7f9562c5c5ab6361644b976a68bada3d7ca508abca8dfc80a469975689af1fba1abcf21bc2a190dab397d -b01461ad23b2a8fa8a6d241e1675855d23bc977dbf4714add8c4b4b7469ccf2375cec20e80cedfe49361d1a30414ac5b -a2673bf9bc621e3892c3d7dd4f1a9497f369add8cbaa3472409f4f86bd21ac67cfac357604828adfee6ada1835365029 -a042dff4bf0dfc33c178ba1b335e798e6308915128de91b12e5dbbab7c4ac8d60a01f6aea028c3a6d87b9b01e4e74c01 -86339e8a75293e4b3ae66b5630d375736b6e6b6b05c5cda5e73fbf7b2f2bd34c18a1d6cefede08625ce3046e77905cb8 -af2ebe1b7d073d03e3d98bc61af83bf26f7a8c130fd607aa92b75db22d14d016481b8aa231e2c9757695f55b7224a27f -a00ee882c9685e978041fd74a2c465f06e2a42ffd3db659053519925be5b454d6f401e3c12c746e49d910e4c5c9c5e8c -978a781c0e4e264e0dad57e438f1097d447d891a1e2aa0d5928f79a9d5c3faae6f258bc94fdc530b7b2fa6a9932bb193 -aa4b7ce2e0c2c9e9655bf21e3e5651c8503bce27483017b0bf476be743ba06db10228b3a4c721219c0779747f11ca282 -b003d1c459dacbcf1a715551311e45d7dbca83a185a65748ac74d1800bbeaba37765d9f5a1a221805c571910b34ebca8 -95b6e531b38648049f0d19de09b881baa1f7ea3b2130816b006ad5703901a05da57467d1a3d9d2e7c73fb3f2e409363c -a6cf9c06593432d8eba23a4f131bb7f72b9bd51ab6b4b772a749fe03ed72b5ced835a349c6d9920dba2a39669cb7c684 -aa3d59f6e2e96fbb66195bc58c8704e139fa76cd15e4d61035470bd6e305db9f98bcbf61ac1b95e95b69ba330454c1b3 -b57f97959c208361de6d7e86dff2b873068adb0f158066e646f42ae90e650079798f165b5cd713141cd3a2a90a961d9a -a76ee8ed9052f6a7a8c69774bb2597be182942f08115baba03bf8faaeaee526feba86120039fe8ca7b9354c3b6e0a8e6 -95689d78c867724823f564627d22d25010f278674c6d2d0cdb10329169a47580818995d1d727ce46c38a1e47943ebb89 -ab676d2256c6288a88e044b3d9ffd43eb9d5aaee00e8fc60ac921395fb835044c71a26ca948e557fed770f52d711e057 -96351c72785c32e5d004b6f4a1259fb8153d631f0c93fed172f18e8ba438fbc5585c1618deeabd0d6d0b82173c2e6170 -93dd8d3db576418e22536eba45ab7f56967c6c97c64260d6cddf38fb19c88f2ec5cd0e0156f50e70855eee8a2b879ffd -ad6ff16f40f6de3d7a737f8e6cebd8416920c4ff89dbdcd75eabab414af9a6087f83ceb9aff7680aa86bff98bd09c8cc -84de53b11671abc9c38710e19540c5c403817562aeb22a88404cdaff792c1180f717dbdfe8f54940c062c4d032897429 -872231b9efa1cdd447b312099a5c164c560440a9441d904e70f5abfc3b2a0d16be9a01aca5e0a2599a61e19407587e3d -88f44ac27094a2aa14e9dc40b099ee6d68f97385950f303969d889ee93d4635e34dff9239103bdf66a4b7cbba3e7eb7a -a59afebadf0260e832f6f44468443562f53fbaf7bcb5e46e1462d3f328ac437ce56edbca617659ac9883f9e13261fad7 -b1990e42743a88de4deeacfd55fafeab3bc380cb95de43ed623d021a4f2353530bcab9594389c1844b1c5ea6634c4555 -85051e841149a10e83f56764e042182208591396d0ce78c762c4a413e6836906df67f38c69793e158d64fef111407ba3 -9778172bbd9b1f2ec6bbdd61829d7b39a7df494a818e31c654bf7f6a30139899c4822c1bf418dd4f923243067759ce63 -9355005b4878c87804fc966e7d24f3e4b02bed35b4a77369d01f25a3dcbff7621b08306b1ac85b76fe7b4a3eb5f839b1 -8f9dc6a54fac052e236f8f0e1f571ac4b5308a43acbe4cc8183bce26262ddaf7994e41cf3034a4cbeca2c505a151e3b1 -8cc59c17307111723fe313046a09e0e32ea0cce62c13814ab7c6408c142d6a0311d801be4af53fc9240523f12045f9ef -8e6057975ed40a1932e47dd3ac778f72ee2a868d8540271301b1aa6858de1a5450f596466494a3e0488be4fbeb41c840 -812145efbd6559ae13325d56a15940ca4253b17e72a9728986b563bb5acc13ec86453796506ac1a8f12bd6f9e4a288c3 -911da0a6d6489eb3dab2ec4a16e36127e8a291ae68a6c2c9de33e97f3a9b1f00da57a94e270a0de79ecc5ecb45d19e83 -b72ea85973f4b2a7e6e71962b0502024e979a73c18a9111130e158541fa47bbaaf53940c8f846913a517dc69982ba9e1 -a7a56ad1dbdc55f177a7ad1d0af78447dc2673291e34e8ab74b26e2e2e7d8c5fe5dc89e7ef60f04a9508847b5b3a8188 -b52503f6e5411db5d1e70f5fb72ccd6463fa0f197b3e51ca79c7b5a8ab2e894f0030476ada72534fa4eb4e06c3880f90 -b51c7957a3d18c4e38f6358f2237b3904618d58b1de5dec53387d25a63772e675a5b714ad35a38185409931157d4b529 -b86b4266e719d29c043d7ec091547aa6f65bbf2d8d831d1515957c5c06513b72aa82113e9645ad38a7bc3f5383504fa6 -b95b547357e6601667b0f5f61f261800a44c2879cf94e879def6a105b1ad2bbf1795c3b98a90d588388e81789bd02681 -a58fd4c5ae4673fa350da6777e13313d5d37ed1dafeeb8f4f171549765b84c895875d9d3ae6a9741f3d51006ef81d962 -9398dc348d078a604aadc154e6eef2c0be1a93bb93ba7fe8976edc2840a3a318941338cc4d5f743310e539d9b46613d2 -902c9f0095014c4a2f0dccaaab543debba6f4cc82c345a10aaf4e72511725dbed7a34cd393a5f4e48a3e5142b7be84ed -a7c0447849bb44d04a0393a680f6cd390093484a79a147dd238f5d878030d1c26646d88211108e59fe08b58ad20c6fbd -80db045535d6e67a422519f5c89699e37098449d249698a7cc173a26ccd06f60238ae6cc7242eb780a340705c906790c -8e52b451a299f30124505de2e74d5341e1b5597bdd13301cc39b05536c96e4380e7f1b5c7ef076f5b3005a868657f17c -824499e89701036037571761e977654d2760b8ce21f184f2879fda55d3cda1e7a95306b8abacf1caa79d3cc075b9d27f -9049b956b77f8453d2070607610b79db795588c0cec12943a0f5fe76f358dea81e4f57a4692112afda0e2c05c142b26f -81911647d818a4b5f4990bfd4bc13bf7be7b0059afcf1b6839333e8569cdb0172fd2945410d88879349f677abaed5eb3 -ad4048f19b8194ed45b6317d9492b71a89a66928353072659f5ce6c816d8f21e69b9d1817d793effe49ca1874daa1096 -8d22f7b2ddb31458661abd34b65819a374a1f68c01fc6c9887edeba8b80c65bceadb8f57a3eb686374004b836261ef67 -92637280c259bc6842884db3d6e32602a62252811ae9b019b3c1df664e8809ffe86db88cfdeb8af9f46435c9ee790267 -a2f416379e52e3f5edc21641ea73dc76c99f7e29ea75b487e18bd233856f4c0183429f378d2bfc6cd736d29d6cadfa49 -882cb6b76dbdc188615dcf1a8439eba05ffca637dd25197508156e03c930b17b9fed2938506fdd7b77567cb488f96222 -b68b621bb198a763fb0634eddb93ed4b5156e59b96c88ca2246fd1aea3e6b77ed651e112ac41b30cd361fadc011d385e -a3cb22f6b675a29b2d1f827cacd30df14d463c93c3502ef965166f20d046af7f9ab7b2586a9c64f4eae4fad2d808a164 -8302d9ce4403f48ca217079762ce42cee8bc30168686bb8d3a945fbd5acd53b39f028dce757b825eb63af2d5ae41169d -b2eef1fbd1a176f1f4cd10f2988c7329abe4eb16c7405099fb92baa724ab397bc98734ef7d4b24c0f53dd90f57520d04 -a1bbef0bd684a3f0364a66bde9b29326bac7aa3dde4caed67f14fb84fed3de45c55e406702f1495a3e2864d4ee975030 -976acdb0efb73e3a3b65633197692dedc2adaed674291ae3df76b827fc866d214e9cac9ca46baefc4405ff13f953d936 -b9fbf71cc7b6690f601f0b1c74a19b7d14254183a2daaafec7dc3830cba5ae173d854bbfebeca985d1d908abe5ef0cda -90591d7b483598c94e38969c4dbb92710a1a894bcf147807f1bcbd8aa3ac210b9f2be65519aa829f8e1ccdc83ad9b8cf -a30568577c91866b9c40f0719d46b7b3b2e0b4a95e56196ac80898a2d89cc67880e1229933f2cd28ee3286f8d03414d7 -97589a88c3850556b359ec5e891f0937f922a751ac7c95949d3bbc7058c172c387611c0f4cb06351ef02e5178b3dd9e4 -98e7bbe27a1711f4545df742f17e3233fbcc63659d7419e1ca633f104cb02a32c84f2fac23ca2b84145c2672f68077ab -a7ddb91636e4506d8b7e92aa9f4720491bb71a72dadc47c7f4410e15f93e43d07d2b371951a0e6a18d1bd087aa96a5c4 -a7c006692227a06db40bceac3d5b1daae60b5692dd9b54772bedb5fea0bcc91cbcdb530cac31900ffc70c5b3ffadc969 -8d3ec6032778420dfa8be52066ba0e623467df33e4e1901dbadd586c5d750f4ccde499b5197e26b9ea43931214060f69 -8d9a8410518ea64f89df319bfd1fc97a0971cdb9ad9b11d1f8fe834042ea7f8dce4db56eeaf179ff8dda93b6db93e5ce -a3c533e9b3aa04df20b9ff635cb1154ce303e045278fcf3f10f609064a5445552a1f93989c52ce852fd0bbd6e2b6c22e -81934f3a7f8c1ae60ec6e4f212986bcc316118c760a74155d06ce0a8c00a9b9669ec4e143ca214e1b995e41271774fd9 -ab8e2d01a71192093ef8fafa7485e795567cc9db95a93fb7cc4cf63a391ef89af5e2bfad4b827fffe02b89271300407f -83064a1eaa937a84e392226f1a60b7cfad4efaa802f66de5df7498962f7b2649924f63cd9962d47906380b97b9fe80e1 -b4f5e64a15c6672e4b55417ee5dc292dcf93d7ea99965a888b1cc4f5474a11e5b6520eacbcf066840b343f4ceeb6bf33 -a63d278b842456ef15c278b37a6ea0f27c7b3ffffefca77c7a66d2ea06c33c4631eb242bbb064d730e70a8262a7b848a -83a41a83dbcdf0d22dc049de082296204e848c453c5ab1ba75aa4067984e053acf6f8b6909a2e1f0009ed051a828a73b -819485b036b7958508f15f3c19436da069cbe635b0318ebe8c014cf1ef9ab2df038c81161b7027475bcfa6fff8dd9faf -aa40e38172806e1e045e167f3d1677ef12d5dcdc89b43639a170f68054bd196c4fae34c675c1644d198907a03f76ba57 -969bae484883a9ed1fbed53b26b3d4ee4b0e39a6c93ece5b3a49daa01444a1c25727dabe62518546f36b047b311b177c -80a9e73a65da99664988b238096a090d313a0ee8e4235bc102fa79bb337b51bb08c4507814eb5baec22103ec512eaab0 -86604379aec5bddda6cbe3ef99c0ac3a3c285b0b1a15b50451c7242cd42ae6b6c8acb717dcca7917838432df93a28502 -a23407ee02a495bed06aa7e15f94cfb05c83e6d6fba64456a9bbabfa76b2b68c5c47de00ba169e710681f6a29bb41a22 -98cff5ecc73b366c6a01b34ac9066cb34f7eeaf4f38a5429bad2d07e84a237047e2a065c7e8a0a6581017dadb4695deb -8de9f68a938f441f3b7ab84bb1f473c5f9e5c9e139e42b7ccee1d254bd57d0e99c2ccda0f3198f1fc5737f6023dd204e -b0ce48d815c2768fb472a315cad86aa033d0e9ca506f146656e2941829e0acb735590b4fbc713c2d18d3676db0a954ac -82f485cdefd5642a6af58ac6817991c49fac9c10ace60f90b27f1788cc026c2fe8afc83cf499b3444118f9f0103598a8 -82c24550ed512a0d53fc56f64cc36b553823ae8766d75d772dacf038c460f16f108f87a39ceef7c66389790f799dbab3 -859ffcf1fe9166388316149b9acc35694c0ea534d43f09dae9b86f4aa00a23b27144dda6a352e74b9516e8c8d6fc809c -b8f7f353eec45da77fb27742405e5ad08d95ec0f5b6842025be9def3d9892f85eb5dd0921b41e6eff373618dba215bca -8ccca4436f9017e426229290f5cd05eac3f16571a4713141a7461acfe8ae99cd5a95bf5b6df129148693c533966145da -a2c67ecc19c0178b2994846fea4c34c327a5d786ac4b09d1d13549d5be5996d8a89021d63d65cb814923388f47cc3a03 -aa0ff87d676b418ec08f5cbf577ac7e744d1d0e9ebd14615b550eb86931eafd2a36d4732cc5d6fab1713fd7ab2f6f7c0 -8aef4730bb65e44efd6bb9441c0ae897363a2f3054867590a2c2ecf4f0224e578c7a67f10b40f8453d9f492ac15a9b2d -86a187e13d8fba5addcfdd5b0410cedd352016c930f913addd769ee09faa6be5ca3e4b1bdb417a965c643a99bd92be42 -a0a4e9632a7a094b14b29b78cd9c894218cdf6783e61671e0203865dc2a835350f465fbaf86168f28af7c478ca17bc89 -a8c7b02d8deff2cd657d8447689a9c5e2cd74ef57c1314ac4d69084ac24a7471954d9ff43fe0907d875dcb65fd0d3ce5 -97ded38760aa7be6b6960b5b50e83b618fe413cbf2bcc1da64c05140bcc32f5e0e709cd05bf8007949953fac5716bad9 -b0d293835a24d64c2ae48ce26e550b71a8c94a0883103757fb6b07e30747f1a871707d23389ba2b2065fa6bafe220095 -8f9e291bf849feaa575592e28e3c8d4b7283f733d41827262367ea1c40f298c7bcc16505255a906b62bf15d9f1ba85fb -998f4e2d12708b4fd85a61597ca2eddd750f73c9e0c9b3cf0825d8f8e01f1628fd19797dcaed3b16dc50331fc6b8b821 -b30d1f8c115d0e63bf48f595dd10908416774c78b3bbb3194192995154d80ea042d2e94d858de5f8aa0261b093c401fd -b5d9c75bb41f964cbff3f00e96d9f1480c91df8913f139f0d385d27a19f57a820f838eb728e46823cbff00e21c660996 -a6edec90b5d25350e2f5f0518777634f9e661ec9d30674cf5b156c4801746d62517751d90074830ac0f4b09911c262f1 -82f98da1264b6b75b8fbeb6a4d96d6a05b25c24db0d57ba3a38efe3a82d0d4e331b9fc4237d6494ccfe4727206457519 -b89511843453cf4ecd24669572d6371b1e529c8e284300c43e0d5bb6b3aaf35aeb634b3cb5c0a2868f0d5e959c1d0772 -a82bf065676583e5c1d3b81987aaae5542f522ba39538263a944bb33ea5b514c649344a96c0205a3b197a3f930fcda6c -a37b47ea527b7e06c460776aa662d9a49ff4149d3993f1a974b0dd165f7171770d189b0e2ea54fd5fccb6a14b116e68a -a1017677f97dda818274d47556d09d0e4ccacb23a252f82a6cfe78c630ad46fb9806307445a59fb61262182de3a2b29c -b01e9fcac239ba270e6877b79273ddd768bf8a51d2ed8a051b1c11e18eff3de5920e2fcbfbd26f06d381eddd3b1f1e1b -82fcd53d803b1c8e4ed76adc339b7f3a5962d37042b9683aabac7513ac68775d4a566a9460183926a6a95dbe7d551a1f -a763e78995d55cd21cdb7ef75d9642d6e1c72453945e346ab6690c20a4e1eeec61bb848ef830ae4b56182535e3c71d8f -b769f4db602251d4b0a1186782799bdcef66de33c110999a5775c50b349666ffd83d4c89714c4e376f2efe021a5cfdb2 -a59cbd1b785efcfa6e83fc3b1d8cf638820bc0c119726b5368f3fba9dce8e3414204fb1f1a88f6c1ff52e87961252f97 -95c8c458fd01aa23ecf120481a9c6332ebec2e8bb70a308d0576926a858457021c277958cf79017ddd86a56cacc2d7db -82eb41390800287ae56e77f2e87709de5b871c8bdb67c10a80fc65f3acb9f7c29e8fa43047436e8933f27449ea61d94d -b3ec25e3545eb83aed2a1f3558d1a31c7edde4be145ecc13b33802654b77dc049b4f0065069dd9047b051e52ab11dcdd -b78a0c715738f56f0dc459ab99e252e3b579b208142836b3c416b704ca1de640ca082f29ebbcee648c8c127df06f6b1e -a4083149432eaaf9520188ebf4607d09cf664acd1f471d4fb654476e77a9eaae2251424ffda78d09b6cb880df35c1219 -8c52857d68d6e9672df3db2df2dbf46b516a21a0e8a18eec09a6ae13c1ef8f369d03233320dd1c2c0bbe00abfc1ea18b -8c856089488803066bff3f8d8e09afb9baf20cecc33c8823c1c0836c3d45498c3de37e87c016b705207f60d2b00f8609 -831a3df39be959047b2aead06b4dcd3012d7b29417f642b83c9e8ce8de24a3dbbd29c6fdf55e2db3f7ea04636c94e403 -aed84d009f66544addabe404bf6d65af7779ce140dc561ff0c86a4078557b96b2053b7b8a43432ffb18cd814f143b9da -93282e4d72b0aa85212a77b336007d8ba071eea17492da19860f1ad16c1ea8867ccc27ef5c37c74b052465cc11ea4f52 -a7b78b8c8d057194e8d68767f1488363f77c77bddd56c3da2bc70b6354c7aa76247c86d51f7371aa38a4aa7f7e3c0bb7 -b1c77283d01dcd1bde649b5b044eac26befc98ff57cbee379fb5b8e420134a88f2fc7f0bf04d15e1fbd45d29e7590fe6 -a4aa8de70330a73b2c6458f20a1067eed4b3474829b36970a8df125d53bbdda4f4a2c60063b7cccb0c80fc155527652f -948a6c79ba1b8ad7e0bed2fae2f0481c4e41b4d9bbdd9b58164e28e9065700e83f210c8d5351d0212e0b0b68b345b3a5 -86a48c31dcbbf7b082c92d28e1f613a2378a910677d7db3a349dc089e4a1e24b12eee8e8206777a3a8c64748840b7387 -976adb1af21e0fc34148917cf43d933d7bfd3fd12ed6c37039dcd5a4520e3c6cf5868539ba5bf082326430deb8a4458d -b93e1a4476f2c51864bb4037e7145f0635eb2827ab91732b98d49b6c07f6ac443111aa1f1da76d1888665cb897c3834e -8afd46fb23bf869999fa19784b18a432a1f252d09506b8dbb756af900518d3f5f244989b3d7c823d9029218c655d3dc6 -83f1e59e3abeed18cdc632921672673f1cb6e330326e11c4e600e13e0d5bc11bdc970ae12952e15103a706fe720bf4d6 -90ce4cc660714b0b673d48010641c09c00fc92a2c596208f65c46073d7f349dd8e6e077ba7dcef9403084971c3295b76 -8b09b0f431a7c796561ecf1549b85048564de428dac0474522e9558b6065fede231886bc108539c104ce88ebd9b5d1b0 -85d6e742e2fb16a7b0ba0df64bc2c0dbff9549be691f46a6669bca05e89c884af16822b85faefefb604ec48c8705a309 -a87989ee231e468a712c66513746fcf03c14f103aadca0eac28e9732487deb56d7532e407953ab87a4bf8961588ef7b0 -b00da10efe1c29ee03c9d37d5918e391ae30e48304e294696b81b434f65cf8c8b95b9d1758c64c25e534d045ba28696f -91c0e1fb49afe46c7056400baa06dbb5f6e479db78ee37e2d76c1f4e88994357e257b83b78624c4ef6091a6c0eb8254d -883fb797c498297ccbf9411a3e727c3614af4eccde41619b773dc7f3259950835ee79453debf178e11dec4d3ada687a0 -a14703347e44eb5059070b2759297fcfcfc60e6893c0373eea069388eba3950aa06f1c57cd2c30984a2d6f9e9c92c79e -afebc7585b304ceba9a769634adff35940e89cd32682c78002822aab25eec3edc29342b7f5a42a56a1fec67821172ad5 -aea3ff3822d09dba1425084ca95fd359718d856f6c133c5fabe2b2eed8303b6e0ba0d8698b48b93136a673baac174fd9 -af2456a09aa777d9e67aa6c7c49a1845ea5cdda2e39f4c935c34a5f8280d69d4eec570446998cbbe31ede69a91e90b06 -82cada19fed16b891ef3442bafd49e1f07c00c2f57b2492dd4ee36af2bd6fd877d6cb41188a4d6ce9ec8d48e8133d697 -82a21034c832287f616619a37c122cee265cc34ae75e881fcaea4ea7f689f3c2bc8150bbf7dbcfd123522bfb7f7b1d68 -86877217105f5d0ec3eeff0289fc2a70d505c9fdf7862e8159553ef60908fb1a27bdaf899381356a4ef4649072a9796c -82b196e49c6e861089a427c0b4671d464e9d15555ffb90954cd0d630d7ae02eb3d98ceb529d00719c2526cd96481355a -a29b41d0d43d26ce76d4358e0db2b77df11f56e389f3b084d8af70a636218bd3ac86b36a9fe46ec9058c26a490f887f7 -a4311c4c20c4d7dd943765099c50f2fd423e203ccfe98ff00087d205467a7873762510cac5fdce7a308913ed07991ed7 -b1f040fc5cc51550cb2c25cf1fd418ecdd961635a11f365515f0cb4ffb31da71f48128c233e9cc7c0cf3978d757ec84e -a9ebae46f86d3bd543c5f207ed0d1aed94b8375dc991161d7a271f01592912072e083e2daf30c146430894e37325a1b9 -826418c8e17ad902b5fe88736323a47e0ca7a44bce4cbe27846ec8fe81de1e8942455dda6d30e192cdcc73e11df31256 -85199db563427c5edcbac21f3d39fec2357be91fb571982ddcdc4646b446ad5ced84410de008cb47b3477ee0d532daf8 -b7eed9cd400b2ca12bf1d9ae008214b8561fb09c8ad9ff959e626ffde00fee5ff2f5b6612e231f2a1a9b1646fcc575e3 -8b40bf12501dcbac78f5a314941326bfcddf7907c83d8d887d0bb149207f85d80cd4dfbd7935439ea7b14ea39a3fded7 -83e3041af302485399ba6cd5120e17af61043977083887e8d26b15feec4a6b11171ac5c06e6ad0971d4b58a81ff12af3 -8f5b9a0eecc589dbf8c35a65d5e996a659277ef6ea509739c0cb7b3e2da9895e8c8012de662e5b23c5fa85d4a8f48904 -835d71ed5e919d89d8e6455f234f3ff215462c4e3720c371ac8c75e83b19dfe3ae15a81547e4dc1138e5f5997f413cc9 -8b7d2e4614716b1db18e9370176ea483e6abe8acdcc3dcdf5fb1f4d22ca55d652feebdccc171c6de38398d9f7bfdec7a -93eace72036fe57d019676a02acf3d224cf376f166658c1bf705db4f24295881d477d6fdd7916efcfceff8c7a063deda -b1ac460b3d516879a84bc886c54f020a9d799e7c49af3e4d7de5bf0d2793c852254c5d8fe5616147e6659512e5ccb012 -acd0947a35cb167a48bcd9667620464b54ac0e78f9316b4aa92dcaab5422d7a732087e52e1c827faa847c6b2fe6e7766 -94ac33d21c3d12ff762d32557860e911cd94d666609ddcc42161b9c16f28d24a526e8b10bb03137257a92cec25ae637d -832e02058b6b994eadd8702921486241f9a19e68ed1406dad545e000a491ae510f525ccf9d10a4bba91c68f2c53a0f58 -9471035d14f78ff8f463b9901dd476b587bb07225c351161915c2e9c6114c3c78a501379ab6fb4eb03194c457cbd22bf -ab64593e034c6241d357fcbc32d8ea5593445a5e7c24cac81ad12bd2ef01843d477a36dc1ba21dbe63b440750d72096a -9850f3b30045e927ad3ec4123a32ed2eb4c911f572b6abb79121873f91016f0d80268de8b12e2093a4904f6e6cab7642 -987212c36b4722fe2e54fa30c52b1e54474439f9f35ca6ad33c5130cd305b8b54b532dd80ffd2c274105f20ce6d79f6e -8b4d0c6abcb239b5ed47bef63bc17efe558a27462c8208fa652b056e9eae9665787cd1aee34fbb55beb045c8bfdb882b -a9f3483c6fee2fe41312d89dd4355d5b2193ac413258993805c5cbbf0a59221f879386d3e7a28e73014f10e65dd503d9 -a2225da3119b9b7c83d514b9f3aeb9a6d9e32d9cbf9309cbb971fd53c4b2c001d10d880a8ad8a7c281b21d85ceca0b7c -a050be52e54e676c151f7a54453bbb707232f849beab4f3bf504b4d620f59ed214409d7c2bd3000f3ff13184ccda1c35 -adbccf681e15b3edb6455a68d292b0a1d0f5a4cb135613f5e6db9943f02181341d5755875db6ee474e19ace1c0634a28 -8b6eff675632a6fad0111ec72aacc61c7387380eb87933fd1d098856387d418bd38e77d897e65d6fe35951d0627c550b -aabe2328ddf90989b15e409b91ef055cb02757d34987849ae6d60bef2c902bf8251ed21ab30acf39e500d1d511e90845 -92ba4eb1f796bc3d8b03515f65c045b66e2734c2da3fc507fdd9d6b5d1e19ab3893726816a32141db7a31099ca817d96 -8a98b3cf353138a1810beb60e946183803ef1d39ac4ea92f5a1e03060d35a4774a6e52b14ead54f6794d5f4022b8685c -909f8a5c13ec4a59b649ed3bee9f5d13b21d7f3e2636fd2bb3413c0646573fdf9243d63083356f12f5147545339fcd55 -9359d914d1267633141328ed0790d81c695fea3ddd2d406c0df3d81d0c64931cf316fe4d92f4353c99ff63e2aefc4e34 -b88302031681b54415fe8fbfa161c032ea345c6af63d2fb8ad97615103fd4d4281c5a9cae5b0794c4657b97571a81d3b -992c80192a519038082446b1fb947323005b275e25f2c14c33cc7269e0ec038581cc43705894f94bad62ae33a8b7f965 -a78253e3e3eece124bef84a0a8807ce76573509f6861d0b6f70d0aa35a30a123a9da5e01e84969708c40b0669eb70aa6 -8d5724de45270ca91c94792e8584e676547d7ac1ac816a6bb9982ee854eb5df071d20545cdfd3771cd40f90e5ba04c8e -825a6f586726c68d45f00ad0f5a4436523317939a47713f78fd4fe81cd74236fdac1b04ecd97c2d0267d6f4981d7beb1 -93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 -b5bfd7dd8cdeb128843bc287230af38926187075cbfbefa81009a2ce615ac53d2914e5870cb452d2afaaab24f3499f72185cbfee53492714734429b7b38608e23926c911cceceac9a36851477ba4c60b087041de621000edc98edada20c1def2 -b5337ba0ce5d37224290916e268e2060e5c14f3f9fc9e1ec3af5a958e7a0303122500ce18f1a4640bf66525bd10e763501fe986d86649d8d45143c08c3209db3411802c226e9fe9a55716ac4a0c14f9dcef9e70b2bb309553880dc5025eab3cc -b3c1dcdc1f62046c786f0b82242ef283e7ed8f5626f72542aa2c7a40f14d9094dd1ebdbd7457ffdcdac45fd7da7e16c51200b06d791e5e43e257e45efdf0bd5b06cd2333beca2a3a84354eb48662d83aef5ecf4e67658c851c10b13d8d87c874 -954d91c7688983382609fca9e211e461f488a5971fd4e40d7e2892037268eacdfd495cfa0a7ed6eb0eb11ac3ae6f651716757e7526abe1e06c64649d80996fd3105c20c4c94bc2b22d97045356fe9d791f21ea6428ac48db6f9e68e30d875280 -88a6b6bb26c51cf9812260795523973bb90ce80f6820b6c9048ab366f0fb96e48437a7f7cb62aedf64b11eb4dfefebb0147608793133d32003cb1f2dc47b13b5ff45f1bb1b2408ea45770a08dbfaec60961acb8119c47b139a13b8641e2c9487 -85cd7be9728bd925d12f47fb04b32d9fad7cab88788b559f053e69ca18e463113ecc8bbb6dbfb024835f901b3a957d3108d6770fb26d4c8be0a9a619f6e3a4bf15cbfd48e61593490885f6cee30e4300c5f9cf5e1c08e60a2d5b023ee94fcad0 -80477dba360f04399821a48ca388c0fa81102dd15687fea792ee8c1114e00d1bc4839ad37ac58900a118d863723acfbe08126ea883be87f50e4eabe3b5e72f5d9e041db8d9b186409fd4df4a7dde38c0e0a3b1ae29b098e5697e7f110b6b27e4 -b7a6aec08715a9f8672a2b8c367e407be37e59514ac19dd4f0942a68007bba3923df22da48702c63c0d6b3efd3c2d04e0fe042d8b5a54d562f9f33afc4865dcbcc16e99029e25925580e87920c399e710d438ac1ce3a6dc9b0d76c064a01f6f7 -ac1b001edcea02c8258aeffbf9203114c1c874ad88dae1184fadd7d94cd09053649efd0ca413400e6e9b5fa4eac33261000af88b6bd0d2abf877a4f0355d2fb4d6007adb181695201c5432e50b850b51b3969f893bddf82126c5a71b042b7686 -90043fda4de53fb364fab2c04be5296c215599105ecff0c12e4917c549257125775c29f2507124d15f56e30447f367db0596c33237242c02d83dfd058735f1e3c1ff99069af55773b6d51d32a68bf75763f59ec4ee7267932ae426522b8aaab6 -a8660ce853e9dc08271bf882e29cd53397d63b739584dda5263da4c7cc1878d0cf6f3e403557885f557e184700575fee016ee8542dec22c97befe1d10f414d22e84560741cdb3e74c30dda9b42eeaaf53e27822de2ee06e24e912bf764a9a533 -8fe3921a96d0d065e8aa8fce9aa42c8e1461ca0470688c137be89396dd05103606dab6cdd2a4591efd6addf72026c12e065da7be276dee27a7e30afa2bd81c18f1516e7f068f324d0bad9570b95f6bd02c727cd2343e26db0887c3e4e26dceda -8ae1ad97dcb9c192c9a3933541b40447d1dc4eebf380151440bbaae1e120cc5cdf1bcea55180b128d8e180e3af623815191d063cc0d7a47d55fb7687b9d87040bf7bc1a7546b07c61db5ccf1841372d7c2fe4a5431ffff829f3c2eb590b0b710 -8c2fa96870a88150f7876c931e2d3cc2adeaaaf5c73ef5fa1cf9dfa0991ae4819f9321af7e916e5057d87338e630a2f21242c29d76963cf26035b548d2a63d8ad7bd6efefa01c1df502cbdfdfe0334fb21ceb9f686887440f713bf17a89b8081 -b9aa98e2f02bb616e22ee5dd74c7d1049321ac9214d093a738159850a1dbcc7138cb8d26ce09d8296368fd5b291d74fa17ac7cc1b80840fdd4ee35e111501e3fa8485b508baecda7c1ab7bd703872b7d64a2a40b3210b6a70e8a6ffe0e5127e3 -9292db67f8771cdc86854a3f614a73805bf3012b48f1541e704ea4015d2b6b9c9aaed36419769c87c49f9e3165f03edb159c23b3a49c4390951f78e1d9b0ad997129b17cdb57ea1a6638794c0cca7d239f229e589c5ae4f9fe6979f7f8cba1d7 -91cd9e86550f230d128664f7312591fee6a84c34f5fc7aed557bcf986a409a6de722c4330453a305f06911d2728626e611acfdf81284f77f60a3a1595053a9479964fd713117e27c0222cc679674b03bc8001501aaf9b506196c56de29429b46 -a9516b73f605cc31b89c68b7675dc451e6364595243d235339437f556cf22d745d4250c1376182273be2d99e02c10eee047410a43eff634d051aeb784e76cb3605d8e079b9eb6ad1957dfdf77e1cd32ce4a573c9dfcc207ca65af6eb187f6c3d -a9667271f7d191935cc8ad59ef3ec50229945faea85bfdfb0d582090f524436b348aaa0183b16a6231c00332fdac2826125b8c857a2ed9ec66821cfe02b3a2279be2412441bc2e369b255eb98614e4be8490799c4df22f18d47d24ec70bba5f7 -a4371144d2aa44d70d3cb9789096d3aa411149a6f800cb46f506461ee8363c8724667974252f28aea61b6030c05930ac039c1ee64bb4bd56532a685cae182bf2ab935eee34718cffcb46cae214c77aaca11dbb1320faf23c47247db1da04d8dc -89a7eb441892260b7e81168c386899cd84ffc4a2c5cad2eae0d1ab9e8b5524662e6f660fe3f8bfe4c92f60b060811bc605b14c5631d16709266886d7885a5eb5930097127ec6fb2ebbaf2df65909cf48f253b3d5e22ae48d3e9a2fd2b01f447e -9648c42ca97665b5eccb49580d8532df05eb5a68db07f391a2340769b55119eaf4c52fe4f650c09250fa78a76c3a1e271799b8333cc2628e3d4b4a6a3e03da1f771ecf6516dd63236574a7864ff07e319a6f11f153406280d63af9e2b5713283 -9663bf6dd446ea7a90658ee458578d4196dc0b175ef7fcfa75f44d41670850774c2e46c5a6be132a2c072a3c0180a24f0305d1acac49d2d79878e5cda80c57feda3d01a6af12e78b5874e2a4b3717f11c97503b41a4474e2e95b179113726199 -b212aeb4814e0915b432711b317923ed2b09e076aaf558c3ae8ef83f9e15a83f9ea3f47805b2750ab9e8106cb4dc6ad003522c84b03dc02829978a097899c773f6fb31f7fe6b8f2d836d96580f216fec20158f1590c3e0d7850622e15194db05 -925f005059bf07e9ceccbe66c711b048e236ade775720d0fe479aebe6e23e8af281225ad18e62458dc1b03b42ad4ca290d4aa176260604a7aad0d9791337006fbdebe23746f8060d42876f45e4c83c3643931392fde1cd13ff8bddf8111ef974 -9553edb22b4330c568e156a59ef03b26f5c326424f830fe3e8c0b602f08c124730ffc40bc745bec1a22417adb22a1a960243a10565c2be3066bfdb841d1cd14c624cd06e0008f4beb83f972ce6182a303bee3fcbcabc6cfe48ec5ae4b7941bfc -935f5a404f0a78bdcce709899eda0631169b366a669e9b58eacbbd86d7b5016d044b8dfc59ce7ed8de743ae16c2343b50e2f925e88ba6319e33c3fc76b314043abad7813677b4615c8a97eb83cc79de4fedf6ccbcfa4d4cbf759a5a84e4d9742 -a5b014ab936eb4be113204490e8b61cd38d71da0dec7215125bcd131bf3ab22d0a32ce645bca93e7b3637cf0c2db3d6601a0ddd330dc46f9fae82abe864ffc12d656c88eb50c20782e5bb6f75d18760666f43943abb644b881639083e122f557 -935b7298ae52862fa22bf03bfc1795b34c70b181679ae27de08a9f5b4b884f824ef1b276b7600efa0d2f1d79e4a470d51692fd565c5cf8343dd80e5d3336968fc21c09ba9348590f6206d4424eb229e767547daefa98bc3aa9f421158dee3f2a -9830f92446e708a8f6b091cc3c38b653505414f8b6507504010a96ffda3bcf763d5331eb749301e2a1437f00e2415efb01b799ad4c03f4b02de077569626255ac1165f96ea408915d4cf7955047620da573e5c439671d1fa5c833fb11de7afe6 -840dcc44f673fff3e387af2bb41e89640f2a70bcd2b92544876daa92143f67c7512faf5f90a04b7191de01f3e2b1bde00622a20dc62ca23bbbfaa6ad220613deff43908382642d4d6a86999f662efd64b1df448b68c847cfa87630a3ffd2ec76 -92950c895ed54f7f876b2fda17ecc9c41b7accfbdd42c210cc5b475e0737a7279f558148531b5c916e310604a1de25a80940c94fe5389ae5d6a5e9c371be67bceea1877f5401725a6595bcf77ece60905151b6dfcb68b75ed2e708c73632f4fd -8010246bf8e94c25fd029b346b5fbadb404ef6f44a58fd9dd75acf62433d8cc6db66974f139a76e0c26dddc1f329a88214dbb63276516cf325c7869e855d07e0852d622c332ac55609ba1ec9258c45746a2aeb1af0800141ee011da80af175d4 -b0f1bad257ebd187bdc3f37b23f33c6a5d6a8e1f2de586080d6ada19087b0e2bf23b79c1b6da1ee82271323f5bdf3e1b018586b54a5b92ab6a1a16bb3315190a3584a05e6c37d5ca1e05d702b9869e27f513472bcdd00f4d0502a107773097da -9636d24f1ede773ce919f309448dd7ce023f424afd6b4b69cb98c2a988d849a283646dc3e469879daa1b1edae91ae41f009887518e7eb5578f88469321117303cd3ac2d7aee4d9cb5f82ab9ae3458e796dfe7c24284b05815acfcaa270ff22e2 -b373feb5d7012fd60578d7d00834c5c81df2a23d42794fed91aa9535a4771fde0341c4da882261785e0caca40bf83405143085e7f17e55b64f6c5c809680c20b050409bf3702c574769127c854d27388b144b05624a0e24a1cbcc4d08467005b -b15680648949ce69f82526e9b67d9b55ce5c537dc6ab7f3089091a9a19a6b90df7656794f6edc87fb387d21573ffc847062623685931c2790a508cbc8c6b231dd2c34f4d37d4706237b1407673605a604bcf6a50cc0b1a2db20485e22b02c17e -8817e46672d40c8f748081567b038a3165f87994788ec77ee8daea8587f5540df3422f9e120e94339be67f186f50952504cb44f61e30a5241f1827e501b2de53c4c64473bcc79ab887dd277f282fbfe47997a930dd140ac08b03efac88d81075 -a6e4ef6c1d1098f95aae119905f87eb49b909d17f9c41bcfe51127aa25fee20782ea884a7fdf7d5e9c245b5a5b32230b07e0dbf7c6743bf52ee20e2acc0b269422bd6cf3c07115df4aa85b11b2c16630a07c974492d9cdd0ec325a3fabd95044 -8634aa7c3d00e7f17150009698ce440d8e1b0f13042b624a722ace68ead870c3d2212fbee549a2c190e384d7d6ac37ce14ab962c299ea1218ef1b1489c98906c91323b94c587f1d205a6edd5e9d05b42d591c26494a6f6a029a2aadb5f8b6f67 -821a58092900bdb73decf48e13e7a5012a3f88b06288a97b855ef51306406e7d867d613d9ec738ebacfa6db344b677d21509d93f3b55c2ebf3a2f2a6356f875150554c6fff52e62e3e46f7859be971bf7dd9d5b3e1d799749c8a97c2e04325df -8dba356577a3a388f782e90edb1a7f3619759f4de314ad5d95c7cc6e197211446819c4955f99c5fc67f79450d2934e3c09adefc91b724887e005c5190362245eec48ce117d0a94d6fa6db12eda4ba8dde608fbbd0051f54dcf3bb057adfb2493 -a32a690dc95c23ed9fb46443d9b7d4c2e27053a7fcc216d2b0020a8cf279729c46114d2cda5772fd60a97016a07d6c5a0a7eb085a18307d34194596f5b541cdf01b2ceb31d62d6b55515acfd2b9eec92b27d082fbc4dc59fc63b551eccdb8468 -a040f7f4be67eaf0a1d658a3175d65df21a7dbde99bfa893469b9b43b9d150fc2e333148b1cb88cfd0447d88fa1a501d126987e9fdccb2852ecf1ba907c2ca3d6f97b055e354a9789854a64ecc8c2e928382cf09dda9abde42bbdf92280cdd96 -864baff97fa60164f91f334e0c9be00a152a416556b462f96d7c43b59fe1ebaff42f0471d0bf264976f8aa6431176eb905bd875024cf4f76c13a70bede51dc3e47e10b9d5652d30d2663b3af3f08d5d11b9709a0321aba371d2ef13174dcfcaf -95a46f32c994133ecc22db49bad2c36a281d6b574c83cfee6680b8c8100466ca034b815cfaedfbf54f4e75188e661df901abd089524e1e0eb0bf48d48caa9dd97482d2e8c1253e7e8ac250a32fd066d5b5cb08a8641bdd64ecfa48289dca83a3 -a2cce2be4d12144138cb91066e0cd0542c80b478bf467867ebef9ddaf3bd64e918294043500bf5a9f45ee089a8d6ace917108d9ce9e4f41e7e860cbce19ac52e791db3b6dde1c4b0367377b581f999f340e1d6814d724edc94cb07f9c4730774 -b145f203eee1ac0a1a1731113ffa7a8b0b694ef2312dabc4d431660f5e0645ef5838e3e624cfe1228cfa248d48b5760501f93e6ab13d3159fc241427116c4b90359599a4cb0a86d0bb9190aa7fabff482c812db966fd2ce0a1b48cb8ac8b3bca -adabe5d215c608696e03861cbd5f7401869c756b3a5aadc55f41745ad9478145d44393fec8bb6dfc4ad9236dc62b9ada0f7ca57fe2bae1b71565dbf9536d33a68b8e2090b233422313cc96afc7f1f7e0907dc7787806671541d6de8ce47c4cd0 -ae7845fa6b06db53201c1080e01e629781817f421f28956589c6df3091ec33754f8a4bd4647a6bb1c141ac22731e3c1014865d13f3ed538dcb0f7b7576435133d9d03be655f8fbb4c9f7d83e06d1210aedd45128c2b0c9bab45a9ddde1c862a5 -9159eaa826a24adfa7adf6e8d2832120ebb6eccbeb3d0459ffdc338548813a2d239d22b26451fda98cc0c204d8e1ac69150b5498e0be3045300e789bcb4e210d5cd431da4bdd915a21f407ea296c20c96608ded0b70d07188e96e6c1a7b9b86b -a9fc6281e2d54b46458ef564ffaed6944bff71e389d0acc11fa35d3fcd8e10c1066e0dde5b9b6516f691bb478e81c6b20865281104dcb640e29dc116daae2e884f1fe6730d639dbe0e19a532be4fb337bf52ae8408446deb393d224eee7cfa50 -84291a42f991bfb36358eedead3699d9176a38f6f63757742fdbb7f631f2c70178b1aedef4912fed7b6cf27e88ddc7eb0e2a6aa4b999f3eb4b662b93f386c8d78e9ac9929e21f4c5e63b12991fcde93aa64a735b75b535e730ff8dd2abb16e04 -a1b7fcacae181495d91765dfddf26581e8e39421579c9cbd0dd27a40ea4c54af3444a36bf85a11dda2114246eaddbdd619397424bb1eb41b5a15004b902a590ede5742cd850cf312555be24d2df8becf48f5afba5a8cd087cb7be0a521728386 -92feaaf540dbd84719a4889a87cdd125b7e995a6782911931fef26da9afcfbe6f86aaf5328fe1f77631491ce6239c5470f44c7791506c6ef1626803a5794e76d2be0af92f7052c29ac6264b7b9b51f267ad820afc6f881460521428496c6a5f1 -a525c925bfae1b89320a5054acc1fa11820f73d0cf28d273092b305467b2831fab53b6daf75fb926f332782d50e2522a19edcd85be5eb72f1497193c952d8cd0bcc5d43b39363b206eae4cb1e61668bde28a3fb2fc1e0d3d113f6dfadb799717 -98752bb6f5a44213f40eda6aa4ff124057c1b13b6529ab42fe575b9afa66e59b9c0ed563fb20dff62130c436c3e905ee17dd8433ba02c445b1d67182ab6504a90bbe12c26a754bbf734665c622f76c62fe2e11dd43ce04fd2b91a8463679058b -a9aa9a84729f7c44219ff9e00e651e50ddea3735ef2a73fdf8ed8cd271961d8ed7af5cd724b713a89a097a3fe65a3c0202f69458a8b4c157c62a85668b12fc0d3957774bc9b35f86c184dd03bfefd5c325da717d74192cc9751c2073fe9d170e -b221c1fd335a4362eff504cd95145f122bf93ea02ae162a3fb39c75583fc13a932d26050e164da97cff3e91f9a7f6ff80302c19dd1916f24acf6b93b62f36e9665a8785413b0c7d930c7f1668549910f849bca319b00e59dd01e5dec8d2edacc -a71e2b1e0b16d754b848f05eda90f67bedab37709550171551050c94efba0bfc282f72aeaaa1f0330041461f5e6aa4d11537237e955e1609a469d38ed17f5c2a35a1752f546db89bfeff9eab78ec944266f1cb94c1db3334ab48df716ce408ef -b990ae72768779ba0b2e66df4dd29b3dbd00f901c23b2b4a53419226ef9232acedeb498b0d0687c463e3f1eead58b20b09efcefa566fbfdfe1c6e48d32367936142d0a734143e5e63cdf86be7457723535b787a9cfcfa32fe1d61ad5a2617220 -8d27e7fbff77d5b9b9bbc864d5231fecf817238a6433db668d5a62a2c1ee1e5694fdd90c3293c06cc0cb15f7cbeab44d0d42be632cb9ff41fc3f6628b4b62897797d7b56126d65b694dcf3e298e3561ac8813fbd7296593ced33850426df42db -a92039a08b5502d5b211a7744099c9f93fa8c90cedcb1d05e92f01886219dd464eb5fb0337496ad96ed09c987da4e5f019035c5b01cc09b2a18b8a8dd419bc5895388a07e26958f6bd26751929c25f89b8eb4a299d822e2d26fec9ef350e0d3c -92dcc5a1c8c3e1b28b1524e3dd6dbecd63017c9201da9dbe077f1b82adc08c50169f56fc7b5a3b28ec6b89254de3e2fd12838a761053437883c3e01ba616670cea843754548ef84bcc397de2369adcca2ab54cd73c55dc68d87aec3fc2fe4f10 -97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb -ad3eb50121139aa34db1d545093ac9374ab7bca2c0f3bf28e27c8dcd8fc7cb42d25926fc0c97b336e9f0fb35e5a04c81 -8029c8ce0d2dce761a7f29c2df2290850c85bdfaec2955626d7acc8864aeb01fe16c9e156863dc63b6c22553910e27c1 -b1386c995d3101d10639e49b9e5d39b9a280dcf0f135c2e6c6928bb3ab8309a9da7178f33925768c324f11c3762cfdd5 -9596d929610e6d2ed3502b1bb0f1ea010f6b6605c95d4859f5e53e09fa68dc71dfd5874905447b5ec6cd156a76d6b6e8 -851e3c3d4b5b7cdbba25d72abf9812cf3d7c5a9dbdec42b6635e2add706cbeea18f985afe5247459f6c908620322f434 -b10f4cf8ec6e02491bbe6d9084d88c16306fdaf399fef3cd1453f58a4f7633f80dc60b100f9236c3103eaf727468374f -ade11ec630127e04d17e70db0237d55f2ff2a2094881a483797e8cddb98b622245e1f608e5dcd1172b9870e733b4a32f -af58c8a2f58f904ce20db81005331bf2d251e227e7d1bef575d691bdca842e6233eb2e26c2e116a61a78594772b38d25 -b3c1313c31ec82da5a7a09e9cf6656ca598c243345fe8d4828e520ade91787ffb8b9867db789b34ad67cef47b26ff86d -a8ed8a235355948e0b04be080b7b3e145293accefb4704d1da9050796b2f6870516c1ebf77ae6a65359edcfd016c0f36 -80e792d5ba24b8058f6d7291a2ec5cb68aab1e16e96d793128e86815631baf42c56b6205c19e25ce9727bd1fd6f9defb -816288c5d726b094e3fdf95cb8882f442c4d9d1101b92c7938a7dfd49bc50636d73ea1b05f75eb731c908c8fd8dee717 -ae009128d128ba2e1519bfa7a0c01ed494a7d461c3aba60f8a301701fed61fe4e31d6c79ce189542ae51df91e73ce1b3 -96a866d60a9007d05825c332476a83e869e15b11d7257172a67690ea9bd3efea44bf9c8d42191454eb04fcf110b16396 -8b250a2a06419adb9b611e89f7f8f2990aa301949b533ad3bf17c4a61ab5f5be0b1d5e2b571864d13f1bb75805c7795d -8450f49facf2e620fa45ee90e1801178842d927a2a25fc6ed7ba99a4eec7ae40eebfee41028eaa84f107f4a777694976 -91049080cf659c0985a22d1366e59191bb89663f922e8168b9b7d85c8a73d74a6d9dceefd855d3d858b493670c750581 -a1e167aeb2008087f3195926f1985c0a459d6ec57237255b1473a96de4e2c1cf766127c862c7dc853a6909e67cb06cf7 -b667c0d4e26e20698b07567358625d5f003839c92de8088e12dbd74a6f6a3156b4ea8d252c9ad62af5f6c4fec1cf6cc7 -8e4b5e304c0b1b161ae3e4b68b5e3ac66c42acd7c1ee2458044f6527c508a93995e50894d72d57c1350f91afe72775ff -8c642640aa7915421cdc21fd639f88a42052b1cfa358ff7702e60793a92b7b5926dae15a0c8f8f59cd3013f01c159ba3 -a356f35e713cfc283056bf539de54a21731e61efb4c47319f20de4a4b723d76a33b65f4a67d298b9ec5c2a1579418657 -93ce204146ce95f484dc79c27919a16c9e3fc14a9111c6c63d44491158d5838117d20851cc3227a5e8ba6ccf79e77f39 -b585664cbb9a84b52f89114e1cf0cf1171bea78a136dc1404ac88a11210b2debc3b7a55e702da93ff629095c134a295e -b6dfd444ec7fdceb14c6328f26ca12c3f9fc4327d8d8c68948e92e7e61262b82d833a65a9e3af6353ffa832b6da25705 -b4d4b8eb9ecfffe3f0d48fb4149c7b31aec1da7041ec03bd0750c52a2a7cbc3a7cfbf09d5bfdc56e3860826a62d0bb91 -a4e248e3d61db52da9683fef188579c470d65e2df9064726847b1599fc774049ffdc6ef2ae578d5ed7874f1298ecdf69 -a68a0fffc2e37d3183feb01b42234c0f4e510f9dc29d09c571e6da00fecad9da224cd0f31550070148667e226c4ca413 -86adda2ffecb77236c18005051f31f9657a0d50fef2a1175dfda32e74d5d53df825c10f289eb0ad39df0c64fc9bc7729 -998266d5c9c3764ed97d66fa9ed176af043999652bae19f0657c8328629d30af453230e3681c5a38e2f01e389ed8d825 -a05261554d3c620af0c914cf27ab98f5d3593c33ab313c198e0c40d6c72022eb5943778cd4f73e9fe8383392a7004976 -ad243fb3631bf90fedb9d679fd71fc0cf06bda028591ded2bd4c634ea7b3c2bd22eca2ab318fcdaa6c2cda1e63e1c57b -89b9859a04f903c95e97fb2951f01cc6418a2505eee0b5bc7266b4d33e01b69b9fe7dc56fa9ebb5856095be0925a422d -a68d118343a5bbfbbab95ff9bfe53aeb7fdbaf16db983e6f4456366df2aa01fbdb6ee9901cb102fc7d2bd099be2f1f3e -b49301f25d5a9dd2ec60ddb0b4b477291958487efea9e54dc0e4ef388f03b8bbadd13259d191f7a0b7513876767d8282 -8b93df7fb4513f67749905fd43db78f7026589b704ebb9ea3255d0ad6415437799f40f02e07efccda1e6fd5e8cd0a721 -ad88769ace96455da37c3c9019a9f523c694643be3f6b37b1e9dcc5053d1fe8e463abebdb1b3ef2f2fb801528a01c47c -80f0eb5dcbfaaf421bf59a8b9bd5245c4823c94510093e23e0b0534647fb5525a25ea3aeea0a927a1ee20c057f2c9234 -b10ad82ea6a5aeabe345d00eb17910d6942b6862f7f3773c7d321194e67c9cced0b3310425662606634dcd7f8b976c04 -82f6fd91f87822f6cc977808eeac77889f4a32fb0d618e784b2331263d0ffa820b3f70b069d32e0319c9e033ab75d3b4 -9436d3dc6b5e25b1f695f8c6c1c553dab312ccace4dac3afddc141d3506467cd50cb04a49ea96ea7f5a8a7b0fc65ef37 -8e0a9491651d52be8ebf4315fbbb410272f9a74b965d33b79ff1b9e1be3be59e43d9566773560e43280549c348e48f01 -8809137e5d3a22400d6e645a9bd84e21c492371736c7e62c51cef50fee3aa7f2405724367a83fd051ff702d971167f67 -b536a24f31a346de7f9863fc351fa602158404d2f94747eebe43abf1f21bf8f95a64146c02a4bec27b503f546789a388 -b5cdf5a04fc12a0e0ef7545830061dff7fd8abea46e48fbe6235109e6c36ee6bffcb9529e2f3d0d701cf58bbfb6a4197 -ab15377525753467d042b7931f66f862cbbb77464212c9aa72d4e5c04375ef55f619b3a446091c1ba1a3b5d9f05e538f -905a75b943ad017ff78ea6ddd1d28a45c7273ee1c2e5e3353685813793ead3370c09cabd903fcab9d8b1c6961372d486 -8147df4324faddc02fb0896367a7647b719b6499a361aecfdd3a34296fa6768ad31c34f9e873fd1e683386c44651883e -ac91d08570dd91f89d2e01dca67cdc83b640e20f073ea9f0734759c92182bb66c5d645f15ebd91ed705b66486ed2088d -ac6295ef2513bbea7ef4cdcf37d280300c34e63c4b9704663d55891a61bf5c91b04cc1d202a3a0a7c4520c30edc277c7 -b604be776a012095c0d4ebc77797dd8dec62a54c0559fb2185d7bac6b50d4e5fd471ac2d7f4523206d5d8178eabd9a87 -80ead68def272ce3f57951145e71ed6dc26da98e5825ef439af577c0c5de766d4e39207f205d5d21db903d89f37bbb02 -9950b4a830388c897158c7fe3921e2fe24beedc7c84e2024e8b92b9775f8f99593b54a86b8870ec5087734295ba06032 -b89ba714adabf94e658a7d14ac8fc197376a416841c2a80e1a6dde4f438d5f747d1fb90b39e8ea435c59d6ecda13dea1 -b0c78e7cc60bd05be46d48fbb0421a678c7f14b8d93730deb66fbe1647613b2c62b5075126d917047820c57fc3509cb9 -a860c4acc5444e9ae987e8c93cb9a5f17d954d63c060cc616f724e26bc73d2c54cd36e0492d1fde173847278e55942ba -8fb8269c9d5c15428e8d45da1251e4c4a4b600d47da0caea29fef246854d8fb6acae86a8e6440d0c429d8dd9c2dfee0c -96c5d8eb6fd5c525b348ee4335d200139e437e4be83690af0f35b7f336a7cda8c6d2958647988b84da9f2dd7bbb7710b -a7f62141c4346cc14e9823dc38ac7d587b0427022afc1498d12ee2c43f6ac3a82167057e670dd524b74137f8c3ceb56d -956aac50d06b46a3e94397f163f593f5010d366aa2d816c2205c7d0f47f90cf0f36c169e964f9bcf698d49182d47d91f -b812899bcdc0e70d79ca729cb01104bf60e1357b9085a10f64f3ba9865d57e9abd0a505a502d4de07afb46f4d266be2f -abce02c7e1372e25d40944dc9ece2904a8f59c8854c5f2875fe63ace8ce37d97881f4f9ab4f7bad070ec8e0daee58d3f -8fb13c515b2d6abb4e14ed753fad5cc36c3631dfe21a23d0f603aad719423dd5423157eefcbd9a9c6074e155b79eb38d -a9ef67304dc297ab5af778cf8afa849eeac27db4b6978963e97b95ef7a8d3264d0d07775f728c298a2b6daed2ecf5053 -a9b975520adb066e2ff2a4cde53284c23bc84261a22dc43b1634d99eff8e7892e46bb6e6da7319c9e72788aa9ea7a1ea -a6eaea4ab4206294474d9b956d9d3188d558a5633de2bd05df0d3bac03dbcbe4ed85406349c1d2e660b77c6da1f5bf8c -af4a19f77290dddee762e1e0d4bc9945aacea3f75756ae46cd3e58a8f74d1b5db73e4834687946b0f39191e32f2fed0c -aafa6523f58f1a4cabc924c86d842816d606afeea21fa4b2b8b9573425810fdcc41c98888318e868f9c05e2be12178a3 -8ef38fba0a3fa4ebe985239c8b759c22aaef0c57e6f39050a651c869487803b0d1e389c3d958fb5a7f37740f050ac69e -b07dfc9f85913c608ca7596a2e361f05e4853fad00e796fd492d247de6414892ce160f627669b1ba933b6ad726415d4e -94da679ad1d78b2bff5283c938f17b2a7d6e9cbcdf59d340e6dfb652951c7a9e852ac0590f99cfee9631b9410f6f00ea -98a907c9c021a5b034d3720197c160a82c4b7146cb73d48efeed99b9d0c6b831812cf80ac7e19e85a676a8cd3ead72de -adb746595466a12929019d0048cea33236b05c1229d2eba73b259a18a786f2bc3f05fc0598d8ce253cecb80bdf679aaf -a2fbac016996d68f9027a157b0a3f6a336144a798d6113adfcda3a5d05b62c31f108f112aa915906aef22b7f83b9228b -81841dea1904406d1b6fa49b4b3f7f6cb40b7646cf44d36c9fa07e3dee29f8e47324b40d8356ddf653109673c3374e9b -a3edbb8aac5e60c775775cbdb19067341b2e2530de48738e84c2c07151241ee31f0d8333bf20c2bc9dcb7b2e638a6b5e -b8aa6890e22964828787ce86460d3a32f12a655bb5c28de500f2fcf6b61e3334640ec6ba96029a4912af0d18df4b4139 -8ca43169f04243ad0fdb0152de17c60d9e31ee0ab520970fccd98590e05508821a183b4b367967e60d53c2c826ec5dbd -b179fffd9df8c00486c5a8b9327d599f5a11745ef564f06e126849b06fe2f99273c81f65bc941efb0debaadfecbfec1c -acf068f1c2b1926279cc82750ce21b0d6b0bfd0406f0d8bbfa959bd83935932957c7f6b8de318315bf0b75f6ee41a0f2 -b97831da260919c856e9f71a41687f5979bc16f8a53b1037285b4a2f9ce93af5cfe70bf0ad484744827fb55c847b58eb -aff50b0bd907383b0c241727af364fe084d021221bfb1b09fb6c1a7752eeba45d662493d590f1f182764b90b25f17906 -aeeef044c14e3ad41e1235c9e816e1eb49087fd3abe877b89b3bade74459186126e160bb569bcd77779e701b19b5f71a -8483deb2b7001ca7c438fcdca8ca6aba96c9cbc4becfd9b16a6062705eae270011bcaedcae69bb54630d8c78129e57c7 -aeee8d24be4ac0d9784c029e239fb5e64316ce29b88f47394cfaaa8bb966a72061bff72f99d02dc51c9705854686e77f -90ae09525a16bb2422169e15d6831c87968a14ebc0d1d27e11a759839c73c655b9d33ee5b12f275d6f440688146fbd2f -a3a41fc7fefef101422465e506bea7f3ff23c26fe35f5732b86f5f2471fb93b37ebc339f84c6be1e8d22abc812c2e212 -86f4b5293e8aea4af1f1fb05dcf99714cb3aff1cfc849b1bb73524061c921c9da9ad92579a852e1889da29d952f02fe5 -8932ef39d4050a1e9dc0fd8afeaf159472d71c5c27f458c69d2730836606ea56e19c8c4febf2535f930d3260e9bc7637 -86307b9f3696bb21c20e4558e30310389e7367803c353d437e9b696039a0ff054d9a4953b75237ab1d1dd6f71118c189 -96e57730e683ef5b550c91de18b19ac73879f3e26234297db68d28747ed0953beb0f3913cfb720c602720bf9330685d8 -b04a19ee70123782e47b238abde55baf60ac0c66292a998af0d14afc8bbeb1134e557b94cd17a020084631c09a0d3c02 -829abc8718be8139569fcb2c398962f38f4201114d30e2b2fb23566f8a27a5c380f5605cec543415202a12ed859e33f6 -a0744fa488c8fa92a722c5fc4ef5a47dfe824eccd87d26c8bab9c174cbb151d44b1b29082c48652f03d3177e5ec86001 -81d4035ae9fd28bdcd78b135cb54955d3b685a527319df6ee7e904b8e6d796f5f5a5f5035ee1de750c4cb6050e452b9e -b205e8c2ec24d7104fa0106c09ad34b5a912c1adef553fb718838dd627355993c2ec01055c11d00b2c75b68e9516d44b -b12d09da7968fa7394e449624fc7174d1d76c069ccb03e140d4d87a2d3f6d1f7b9cfc930f0c80becc673406ebe63f08e -b23752c158695da85048fdf38b395681cc0e8998630af8a9ed41efbda08c9964c2dc8ae6e53377264be4467d702c0de4 -b0d84582fd73628d96b8c1ec96197697c41a963542451a2ade0890af0d33c7161d0f18e1a1ce2c168ca2dc1e9119d55e -8b877e618b469aa187632e410b125d2999d5738fd66d482000706b51fd904a0c7e7daa8c9b729fa33817bbc4154cba2a -b1cfc8a7551b601723b937d497d01dec3ee7614c2bf13d430b1058d5ebc1406045009ff02c2ac15bf8cf16f860193d1e -b6d9da84f97b21e13175bbb0b5cc8e79e88b470c87a3e115726c1bd98e0288526c58f3faaa8aa170ace0cd6a60852525 -ad2e773c2d527671ca5fab7085dde4da31cd35f45d4315dd95d8893ff5fb900494dca08eccfc1a2fc7bf7c7fd2fcab97 -8d5a79b34aeb761d4a0c73f09f02e9548e6d382c33ee6887a759ab05762b490b8a549ef2933c7e3a46415c154c0221c0 -b6f2cbe81bd0a7298403be392f8456bed30aed7ef30216959357698f789affd2942ae5fbaf3f48ecebeb7c273b20cb57 -b5b6c45d99cea7ce6a1dc134aff4a8f630f299b42bd59592a7592345f8cd35bcbee944e61b0723de732fcad6e4425b63 -8077d64dfcb2418974e956ea6dbf8a4c05b25d2a025333ad7e2a379f1976dc036771403383a51bfa3476c9c619ef8bef -ad2e0a9d479c77a5fb73b3613a177fdaad50dcb50fed50e756ba18164c153af30b07fb2565e80ff7469f1b0338b7b5de -81017d1d80a6b6df4e99d0d7f85a8180b5523e8fa2ea2672fddff604933f8a113cab27fce098dcb454d7d1f7ed266e04 -852355479d68e76c7febf6dfe2ef8e80d575c0d3bd52c983803592021cfa898c571c0b884412c21e66f0dbfe03167b53 -98e1bf8ad48421467c93b9f72b47dded7c41b4fcd36ea55ca43ab24b0d0b876f5a731f422579b7167c7138fad2121266 -803369314abd5422019ed4b0ef652b4dbe97ef5a87b0ea373eec9628b64a12120b2c3d4eb53db405131ff786d14c7ac6 -adf2613fc34f73e1160975c140e925ed84d254e03cc3bc7fc1d19957b499c9ba9d9e4c1639981b594a7095c0a52c6757 -a2f6a68efdff6e4173c00692abcfdfcdaf6f8b62369afad3dafaae4f2f38c4860780b4624d185e20e4f4498b75b5fe94 -8b1658aa0e119fb8401d486ed08d60240d26a8623ef9788e3b45ad09ae31259395b021bd16be395139cbb7149714e764 -a7dd8bf21121285e00672ee8bb84e0cb39b2496fb53a26e35dfbca7f2b04e9a9ff9db15f53fe63fcbeafeb2deeaf2ca4 -b6d8d709e44bc18f3b41d69608edce60c02bcba48d3b7e2fd420842657f0665a7343246dea149a25e8f3416284abae66 -aaf744ca5e9bcb63e3e2939b7a1e96e4a93c88c76bec0cf4294dd7db95cdd3f6a7d92196e352d08680e2328bc4592899 -84434b015a7c398d35f1ec71fce455d62ba4ed4f62da042ec31bb2b4db47073314354cd50bc322297a1cfe35138bf490 -8d70b3a3cd9d5dfefdacfa418c0b775a112a47ce538d33a560a519660009c3f141fd6221c18539129e9c0acdaceeeb80 -b8c6903412a800ec78a4c15f31c24385a267b0c0ece32fd31bbbb557fd70c3b2d60d8fc0f90fbd70f43baa1928ea30ba -8e391dd445ea06cabb433f057853f8159511b2f9bef41aed9ccd14e0a6fcd912bbaebd38fd5fb736cfde0fa34b7a4874 -a40cd988f70613df32babbd1bbc2f1b29ff1ab0147b01161555a81d56c9621657999bcdb1df38485f687afc51d5d0f23 -b6a008b4426b3d7b28ae04eee4698fc8ef6a35d89008ef5394da39ce582ce1a45dcfae9a33b90f6fa4237f3667803873 -8987280debfb175c3b44a2f152ea82548e4f680966f1fcbee9bf7d714e31bf8080c33f52705ef3aeee70544b22516aba -a78a51a2c11eea7680a5a0ae417a2981f8c69c396e06da621eadd7510a3664ade49d065617bec67b3de779548a4f4509 -a4d9163f0a1bc048385e94d5e0bcafeee1b18f28eb23505623b9e8ef16f3df76408254dfbe790e45f2884198060d388d -83dcae2568a0c518793c0f6e38b42f9ceb50673d100b556a17ec8bd9faeec84afe50b8d72422c6b2356959667bb8e2de -874731941be4474b4576226e5906b5dee89fc9b56a9870dcc7289c1a7d494d345ba6aba31f7546a16f9963283c05f744 -82c1cfab1f501189ac20147fc4631075dbf1abf9125b7d42fcb4f31cf73f3d6461b1bd08fdf6e45cc54bc08a7d5d51d1 -b978228286f5d4a10ce027b6bea3021affcaa805340ca4b5192c69e8c56db59f48e4a14a284ec015f53baf97389f62b2 -af125f4fdccd1c1b64fdffecb5ec7cf8c7392bbe476e1b89a5b5329c5ba4a526e58c11e72ab9de8a38d60af648d75adc -8411a41ec14295acab0d36389013535a80dfff6e024bffeb32fb3070762f61256419e8c51b2ad6de9dbe4f1e8e286912 -8ea67a91112a41f9c65515cd496f4b0cdefa1400fc06568eef000c9eae6dc250fb7622eb3f2deca10b37287cd96fa463 -8da99b6c55c31dee6a49aabb54da249d348a31d4416201a10c45a3b04b11e99d4ae9813632f0ee36c523b5cca62f6f49 -8b44656341e039e2bd83a19c3bb9a88f6209482e274f8cd4f8557b728e5948dd80b5745f621b96f4562928689314e8c2 -a02d424a615ba0dce8ed91f477e79852215a3a39d025059826fa278e7eebef19824b2a2844f5b3865a0f471b609a23f5 -a1f115cebc3fff3bcf233da27cef19eae791660f155d088003460f75567a550bef0722885010ddc384acdeac635939dc -b61a55ce9d143c17876776e064b58a10baf0ba13553c785c1e47f57b5f94c0cda8bc89d43d73386e57816c15b61a8ec8 -b4073f47041e20a8e548c7fb00e07ba3b9056c34eb4ab63bb0e7b48f8e338e8b56a17611a1b5f4c03b352450b86f1d69 -a7b1a07b213205b682fc5b6acb7e76fdf97b280c26621d8f3b76b7c1deb3511957da33a4e358c8e8f3d98b2a8855d67e -b797e67c2670fbd9844e8a68c585f404b035dc14bd4ec75c3f95f932c777f9db5d5f5df7629164af488fc1213035cc5f -99618200797b945f595794d6468e5c618649554ad9ba896330f1cc844090eb956ae9fc23132912f9047085c5f0c3bf7b -81194aa1319abf534cb3927af9adfb178a99d0e3e8c99ab1105f1d3b4fed40ec2971caf1d6647acb0c8d681eca53097b -80673f18e4978dbc226a6cd4b128a1259d9a7f833879c6e2fbe24d69fef2c3c23a51a4f3e8d88fa4533434bbb0723661 -8125bf6c7dbb2fb63aaa3f53283559f172c788223674adbeb6d5bd17cfe888e6b87a79aec774917f20ce911c1f85f8e7 -884bcdb1878b14fc38adc9fb8b4dd0b3afde404fbeb664f26ddfebc81736018551f23e75ce4cfe4865f610bcd454fbd7 -aec65c8d4be8316e98aa54888af01bc6703a0c5d04b69756ff39a0a947b66817ec59d76afe9f61a25749b5e890f03e02 -aa457aaa1b014a4c5a8992847a187a23321bb43452c98745987d038e3b04046102ae859b7a8e980eea978a39d76a88ef -a9832ee63b08e19123f719bfe2fe742125f32463efa966c7709a98ebfc65277670e9ea1fa2d2d78b96bdc7523b0c4c3e -a87b6b1b7858f96d55064274f29fbde56067064962cf3c3e2ba3110b22ea633bc037a74d23543ce3307a46208855d74f -897cbe4ab68a753020fec732dfcc052c7ed9905342b5a6fe0aa25c631f9ad9b659e0ee75d46f0df6507b6720675ee28c -97c3b5f0d54c1fc45e79445c3ff30458959e406a069f5bbf7979d684195b4fa0406b87c1c008f4075bc9e602ed863152 -921e65d582ea9322ddfad1c855331c3cac81f53c700b96db5305a643c084eb6793094e07944bfd41dc02c3b3cf671530 -8f23ef1aca02a260a3b65d25b110f28d3bafca44727448c8f2d03c5e77eda620c1721b06681bd816ee6027664d76352a -946a89b132ec0795aea9ff9dde7b77e7feafffe6e4a2f093042a7e6c71cd6ab87ce0ca914a1b5fabad4e1f96a795f163 -a01e2de9db33df6511172123ad6f7c64074237471df646b32dd9aff8c15278e2723108e4facaedca97e9f49503f8c792 -99dcdcde45b2ea3f15279936feede5f7d3b63ca4972f335b0559c2fa6f9faabd8127aa892a36deb114357ca906553ed8 -a3f8af37bfcf66b04d1896a4bd5d343f4733d4c3305369ac7e75a08f20f2004c10c642d2c7577f4e5c4d1f2cd851ac3b -b7294d15a3d674a56099f97a1adc9e82c15e90832eaf1722df110fc2abc8634c51515e5ad8522015498a3753b1fa8c49 -b4f27f5062ba7a04ea0048b3025b5e3d5b5d319a9e80310c808a5fb4e8e77b38c10a0f3172cb805cadbcc8bc66d36ec7 -aefe5decee0ae2dc372cc6cf4217daf97c4c908d145f100f0daf1ccdfdf641c78432c2e473e7e4b77dcdf2d4c2bb05f0 -acc84af7648a535ffd218c0cc95c8f7b092418c548815f1bafc286b1fe14f6ccb51b2044db3bff864d0bb70e88604084 -84d8e3dac0df6a22beb03742e1d4af684f139f07e2ea0f7fb27fc2d7d4f1e89b5e89f71af32ff115ed5e6092133535f0 -8ada001e1a03a823c4c056f636e77adc0f9dc08689d28de0d99e0feecab5db13abf37b41ec268dbdb42c75419a046c68 -87dac6c798d1744dff81d8bc3e0e04f3c9bf260e811685ddb9a9a8d6eda73927439b344f9a818d2103fad633de5a4a17 -ad9929a7d8a7d5d5954e48281a87e5c84f67e19110d73296b9989a09c76767a57a8115629239ffb4d99dfdf9c52ef6d9 -81ac7cbeef8ec35a5c3b61cc887080c29e6cd3e08af37e45830d17400dbacfb374dd07bf370b979828c3875b2027d5c6 -97f92c9182953b7e10f7a1bbb6b5b5c40b8275eb5a6eec1e29874c4712814749aa8c409651380216e1ff01d7b8511041 -a09794d0bbe7db013045d3fd857c1544fe6231d21afa3495fa300371f6301a3a0f4b8ea175b281503dd06078ff371ae4 -839bb58d320aa08116dd387a57a2b9bd9efc89c4cdfd82d0e47a00cabe644631d09be5436bd485df3b61b75ddf81a3ef -b1cdaa344f783757e8b9c1f84421da3c5be4c69f019a8fd4c1aa5bf1a63e8970c99e35c22cf3b48a0e6738bc6ba7ce8d -92af68e3216c78998208fb24b5ba0e645d0d3f5e28222b805668d7e9cdd6c033d3b22fd6df4c2d745d7f910d133cd226 -87640a4ea4e605e2204e5232b29a6c1c31152d83547eef14122cb76a0da52b8653801af48455a3ed713b9dcfee7b1ef1 -8147e5bf0c8f4731155ca0517ef3fae5a32b4d5d2d98ed0007b23893d8dbb7f8a1199c50c1750c2fa7c9cebe594b1bb0 -a76b4473c63c3ab6103c729afd2482822e4150f3155af39983b0ff0766c71cb622455ce6304e23853661eaa322219d18 -b3e2f05ca551bc3adec0067e4034aaffd72e0b64ac18ae25452c996927976c6727966e26d213b032521889be2170800d -a8414cd14cb3be658e9e0004ce511ef7063439b1cbc3166a11de030613fde4b59caad4e91d426927863c55382afbf476 -b2f0f8ab99f4d0ea785ac84fdbc00b20217b1df59b30b51d9d209d489d53b69dd5d82cdacc16fd1dd15c3a4001595f50 -8b2025d5fd658c9bbed619f3e3f6ac8efe7aeff8aa9401bd66a7ceb0062c44b353608ca073f95be99204f0a913bb77eb -94a46bc5a87291b42024b2137e623c70115b9c6b196604106bfbfa20f3f56ac7779763f56b580190d3cb2f1c648cada1 -aca9355545118d0769cacf69c4b23d6d68d229cd8f68f1bc0c847c05569c5af6bbbd8c4dceb637b4a6b3b5c83841bf5e -b0731992cab87c7116406b283a84707a34838bfa3284b0f6082dfabeaf41c5ac2b0ddc1b420547a1b0955aee92de2dc0 -b671f77588c0f69f6830a5b28e7d07ed161b81fa9791bb3a24aae6638e3aa5e186df74978a82549c370c18ebee04d4f0 -b5621ed841780f3e6681d880a76cf519cdd20d35197b112eeaa686764d57b5dfa78ffe1a294b6bc76b6e3949cd2a2369 -afeba2524659d00caecf089645611553187a6ed7102050f6dd20f5a19bed08ac7065912d88371ee06242897d58d652a4 -b78bfb83d44ced14a20135804aba3f00128c3ce1f302e95567ce4097b0d973414153fb305b9f156882a5a0554bf25973 -98510aede95d26b1adf214053eae051ffaf24894e2fa37961a91d0ff5392dd09388196648d95b73e90bd88f2587cc4bf -b35c682d49c295946b9f120fbc47b95abd9ee86d294abb003a92139fb825b509209562575015856a270eb3eea86397a7 -b9641bf685571dd9c478dd2033a1f1b11cd3a662b26502c78595863b8e536a189674a9a85f7a253453ebfd1b99fbd841 -b2ad37036a59b1c9b8457972665720a6868422ed8157b6810a9c0783006103be34ab732d7aeb8629653edd18fd0f1717 -af0920cff05179a3896ea6ea322c39adf91ada5bc40fe3f6fb1b1b4e121e907c904bbaa8ca00468b3749f3da144d71f3 -8e269672818ef1e2f9e0c8aa65c84442fcd9151d74bb8e870cee8c0e3fe24526e1a5388b430cef47b67f79b4e4056bcc -aa29a16fe00ea3d143b1032b1dd26b8ce638f37f95c085c7e777e8e2784bd724bd5c38b1583c61a6ec7c451dd78fd3fb -87452b7435911cc5f513b0c81b15aa04972ecbe3d7bbd0a5d676c96a8a311301c0e07fac925c53a350b46fbd3d4d0fc1 -869a81c351096f47748e41566ae7b77a454b1cdfaa41d34a5742f80df38fbf5cbb08924b6fdff58e3b18f05c62bbbbb1 -8b7bc1b0486300981147a40a449ada9a41afc06d735cce8bf0fab3ee94ba2e2ea57b1397e3cd31bc295352beb8334ef7 -93e93fc41adb2df279d95654921b4c2edf0d293dab58d0afefb221f777349ef88d0985b3447e3b935954a81f1580a92c -970fa7cdca8324faf3e62348bb50d78f580b4f43f2e1c11bd8382d48d0074a3c55c6407203a0c9cb1c5f2163ba421ef4 -924983929e608d27e4a36d4ed919297869e3c64de51aca794d32d6e90aea546bf898d98ceca28a0b2187734821b78504 -8d395332529c703d943d68415d443332b5c1342ca9d9a59bfa8bd4ab63e93358c4b0dde6ce1f2e8ea9dc8f52ad7ebd95 -80200dda853e588256599e7f905add5d5ee7c74272780317694fbae39318ae9be05d5bcd7b20cf460069743f3d4ef240 -a287d51d6359c9ef7c7ac1b20e479ce7d0146dba5606397bd04b7a622cec642508d5b45d51b31de71f9763595b6ac88e -a320396c075175d6599225cf2e1de8c7cab549f6316c07feb0f6eaa21f06b2dd29ab14fbdf2af4543b4890ec0fd08a4d -b1e9fe230418d20368691058adcbbe30011bab3000422f0371015ff8bd09c60fb5fa85d18550d35b1c900977ca48f58b -9718fc26a51783b971744933f20490e9b5cd9162f86b84788c4c5217f5409e37b5a39d628b18e5b35a757acf67596321 -a0cf81fdb161f4f1b419c5e4caa36d4bdca2325f0cd25b119a30178016f171bd6fb88403e4e3aec026c4089f180d540e -8ab1e36bd04625ee794ef04c4dcb8e004d61aceb2b62438377f49ad95dcf025ba25eb799280004941e555bf7172af6fe -9257b9e3d14d37fc7efae49b0c68d36eaac546035f4a2654d566b3ce1b2c4564cbb03dc8ec66efceb768559a8a507a18 -945d1123b839637ab5154a1972c3c83a0ff34a3b1a3465de6ef0416b1950f649869a3ef88d7f1036648ee385265ce2df -81449639d708860fc0229c94f754f7262e8a3c7f67960ff12dfd15df95f57a9ffcee2013e81978b7703dd42bd5d0816f -a865481deaae5a690fd53892791e5fa729db283b75a525a11cdfee1ce17e8e7f0b449d25f20b3c1b43da128dbdf98a8b -98766812a65fcd25b853546e3bba618a3edc9fd61510e4f8ab60c038a7fa50d197abeec8776109df0f2119be9445ad00 -b1b8dd5379d903dc41d74e999b1ab693607a0d2905692f4fb96adf08f738e5d31f9d00df28ccb8b5856145ca552c3e3c -99d20be7b511bec78a8ed03c207aa4aa9097ba39d85e18f1b8d52f65431ab7e9a773c7b9ac3e8d8b25458bc91bd00703 -b1b7c3563fe8cb33c7d3e0b89d00bdd13e86452ff507c2e69db7b3af06f247f139155396e9b0278753310dc63940a10b -b3dc9c08451b1de7c9969b1e47574bffff50490f4a16c51e12390195d9e9c72f794790caf7b0a835d64e01fec995d3ac -aaaa4761a00022ede0809d7063d3532b7bfae90ff16f45e17a340ad4ebaa2fbac40728ccc5fbe36a67ab0e707566c5dc -8319a1903314eab01f5442d2aee6ae9c3f6edfda0d9a88b416d0f874d7d1d05d08bb482102f8ca70a4fa34836d0840c1 -932949a6e9edfec344932a74d4f81eec3667ece1e8b8ca840ce07ffd4b5d6d8f01657c764d64ac1b9190f876b136490e -904db1568128487e312fe629dd8bb920cecafd3bb9cad8b63e269ae0129f2f5c80cd82f0d81e7feca9835c3945a72d28 -a17280693d30dcd43c85de8f6b02d5f30cb9097274ad680cede1ef105c903615b4c40f3c6aaca478642de324972514e0 -8d5f76e093aee71d0cdeb017fdfcb13bd068039746de90690ce150a0bfdbe7ddc4d539df0f82c2d2890a40b191900594 -96fa1f2196a3883cdd73c66d28403cbbb58f6a939a3697ee0d308d8a076393cbb4be86255af986869230ee410c01bcfa -a8b74438dc5cabd70a91bf25601af915c4418d074327a9b01e0190c27d3922c89bb9b41e0b366e82e313edda8f21983d -ac9fdc1a9b2e3ff379eb2370979372e13c4177bf4574f1490fadf05a7073e6d61e703e2d8eed9ce984aba317d411e219 -a45a6c9b958169f2f8df70143e6ac3e2f6f969a4eed6fd9f1c620711bc2454739bb69f0094079464790c5429c0d8aedd -8901cbdd1009864386577842c1e3d37835fddf834064d9613b4559ea9aef3084204e1f863c4306f874141f4374f449ff -b6c582161691e3635536686825be9c4d7399d668a7675738417e0363e064dfd28acdbd8dbc9e34c1dab8a1990f1f0eba -89e89ddaf3cacc78428f3168549c161283ca8337345750667c98212717b21e7d994eae4e45bbddacc832a18df1d79276 -84be275627eed8e1a73c7af8a20cee1ef5cc568cfeea7ec323d7f91b44e9653e9aeed47c1896a8240b99dde545f0e1fa -a779a54ab4f40228f6e2539595fb8d509b70aab7c19e1928c1be69ec1dc19285c3898cf15e5f8b8bc725e13af177fe17 -92e2a49d2b9b36349d442283b17d46f8f9bf5932c34223015ce62d2f285e7363b2c12232be4a838b5b6cf08e694c094c -8b4e28c6f3f36caa2cfb82ba88066c830f8017bd35608b077143dff236f3181230166f5a5c02fa0e5272297331726aed -85fd77d46162ffac4b8adb25baff0eb0512a53a3d01638b3a376ea34702279ce21c8e7d8884308c03e00c9bcc1a9fd29 -aad5e46916ff1be29009b595d1d8fa160cc7aa01c7fbf3a68f445c87615790dcab1fcdbdceda533d182b6541f09f2f73 -948df7654726250dae393325addd3c0a20431c81f00470962190335ea4b6d9f7463d6f308cda46b92084c1f24390b1da -8f577474dea132676504376c5542b730b6604fe3d965eaa194659fd11c52233bd0b11ab62e198c0f442327ff1c00e501 -ae2f1001546db3e0c19700adad997cd9f765fe7a51a502cbcd9a2a07a3a5db79c8f603e05cf96d80b688cb6c9b6cd3ae -953b68e5d9561088dd20406ea7fb6894cba33868a38ace38fc30b5813140cb15dd6dd2171befae5b4df2e4a9658889d8 -86c52901655ff11419b084a04da8fc3596eae59d81d3461601c0baff59ba59e3d1dd0b7ce719e741a3e97c013e898579 -b9a72dd5eff73f9912a28b55de073568efb3eb0241a10b77a2bfd4f30c2aa4fbfe0c89eb345c9f07fb725660873cb515 -8e7353f5f2932e4ffd95811caf46c9bd1a53643c27eb41a4ebd211f230955cd71a8b27e17cfe8aa708d8514c0de67a66 -a096b8e66312a92fb10839ebe60189a8d1bd34dff55f7dfae85e4d2f53a1a4a88211c19fc84494f066358ddce82be131 -931c5cd82719d76596832b007969b5f75d65cffabb41b9dac7910300db677c1309abe77eeb9837a68c760bb72013b73a -8ba10f5118d778085122065b55dd1918fddb650cce7854d15a8f0da747da44d7b12d44fc29ad7dc38f174be803db74c6 -8c971deec679372a328587d91fd24ab91043e936ca709c333453d7afd43ee256d08c71cb89f0ab0e89ae119831df6d86 -a2ac28a58034fbd8fd518f409221bad0efec52670880f202e09c0530e2aabc2171ed95e99891790596ffad163d86c110 -b3354e3dfa8068aba4f3741152b9204baa4e342c1cc77e6dd1419cbaf8da1d118be605846b8609e997d6a62a11f3423a -a12ab65a213c9d95c24865fddc2dffe0cf9fc527dd6bcdacc1bd7271e79929a4ab3427a231f4f49d0530474e6cbc88f9 -90afd65b7e6973f8aafbe74da0f42441840d3c93bd69bc1bec8fa56824e7ca97ad1b427c8a85da7d588469bd4ccc50c3 -a09175940c59489bac3d3da3a4091270d9118948cbbdd57f2bcc63fbf45b8010651c801d3e58dccf42733ce1d6b446a3 -a843bbf286e3cecc1fe370ff1bcf5f1001bc2e95b34246625ff50d48ee62343e82fba2d25b8a4bd5f7b5ffe90920efa2 -a3c4d1003219157fdbee2707ce07afa6c2a64ae8e450182c307ed7f070024071f30b12c4b0032960ff913c74e73a9976 -b24af3f68d66f825d06fc3ff94fcccebe28b1a0d4ba29c48d3a3c953b9bf7ae6707f193fef25e2dcbd2b74e483c774f0 -b0f657f7723184ef7d7e4381143f1ac8020d8c6c6f2dcbebb0eaf9870d61a81f2d452596503311e46d1b38f625d4756b -b90091004fc8f6205c51bec68547ac82dba0f5525631e7632cf6efe54eecd9020729fbee6105d1b8012402d3b79c54aa -8e3fa187713c60eb0a416d6900a894cdf81e6b6b69dae0bb64f6287f3c3f030cfa85c665f7aace1eab4937f380b8f728 -879bf0784ccf6725c9cd1ea8c49fde31c91c605de1ea664a33c2ce24c277ee45d20b66309f98d989acb2ff3b77e13101 -af3f3a3ddc4e11abd627d5aef8adffa91c25df5f0c68b4d2b5d51e7d9af3395ba4f6f7ae2325a6672847e1ecc6cad628 -973e667289e796d3a40f072e6fea575a9b371a9997cf8961677f8dd934619ddc47c1a3efe91bae9ef95acb11a8fe6d09 -afa81c5606de82f46b93f4bb6db3fc0670f4e0d1091388b138a66b3827322d95a56168c951c30831d59eeadc227500bd -b83eff77db5b4c18574662942eb36f6261c59f655f8a9c3d3731412d0f257c8e80aacc995c4b2303058a1ba32522a434 -912e5ac9234b9445be8260393ff08e4859a7a385e800b74d1534eeb971f58f74cfb518dfdb89f8705d89fbf721439129 -ab27c8ece4a51d23e22c2e22efa43487c941139b37ea1182e96efb54ca4809d8245eae0ebe8ba94f0ed4457896fe11b1 -a6630585d104a745bc79dba266d9292bbdad346449c8ee8140a5e6e8a6194411df9cdbf3d3ef83468a536d4f052e9335 -8b8c128244da48e7fec641a882d0005a2d05c7138d86a293e6a0a97c76bf632b44767d0ce44663c975e7f9f9679e25e3 -87dbcaca67351a4e7d2297d7cdba4796d12f58857e7ee4abd0645563577ff33544a44cd84e50b3a3b420d6998de9b57c -b859ba43df259d7f8e7fac70bfd7aae546d57a5dc90e107b174a95bf7fd3cf00f740c4434848e69b2a7e6061f66c1ef1 -99d6e20978fefc40c6d310187eb2ad3a39296f189ee122ed64d74f81033c3069d44f7a9d3988a1df635b609603a17272 -99a5ddf3420cc0c92b21f71a805245608d4995ead447d8f73a670d26d33e26920d5f07bfe1f6230bd5f15978055b4253 -b936ac0944d3c5e4b494f48f158000abb37b80b5c763f77fe856398c664b0f1ddbcc0a9a2a672db9278f08b4bafbe2ec -b4af85fbf4040e35a686dd016adec037c99b47cc2e4dfccaf7870ee9e8c97bff30f3035992def2a9d4af323c0b3af8ae -a5ee32b8bd5f8fa9000da4da0bf00565659a43285393d37080b555d0166bde64d87317b2eab2d48a0e7b287caa989be2 -894d4ad58ecb1c9ebc4f5a97407082e56cb7358d7a881ba7da72321c5027498454f2c7fa2bd5f67a4b11d38c7f14344a -965be9eeaa0d450dacc1b1cc2fbf0d5d4b0dd188f2c89aaa9260e7307a2a1eb22db6092fccb662269e9a1abfc547cabb -805893c424aec206260c1c2d2509d2cb9e67ee528bd5179a8417a667aa216a3f318ed118b50d28da18e36c01f0805e3f -972d7040d4963b35260ef0cc37cd01746f1a2a87cedc0dc7b0ee7e838c9e4573784ea743f563b5267eb3905d4fa961ba -8c7156991d4c2e561888feaecf501f721b4174e7d14109e9deeac5a9d748301c07e11fb2b04b09799f0d34ff42cb77d1 -894722ac35af3d507e81d737d21e16c5ba04686f8f004aa75934aae5e17acd3e065b96e229eb011c2f34096f4c62048b -81237937c247c88e8e31e2c72412189fe59c1daf65c5513489d86cf29ee922c0bb08e5f7890f09f4ada7e5262083d266 -8cf62cda2fe0d9a6b42aa2a1c483f4ad26378c7cc2c2d1510a76df7560b07dba8528b33aaacb15f7f20b9d4c7c9f61f6 -aaf0921fb3e1920eee5d0acb59dcc268b42f4b435d60d25d30357edd7dd758d035919691bd15311d85489dfa2e5ee696 -92cec07be2247ef42002ebcaf65ec855611b8e893a5675796f2225f55412201b0bf9f4761924d0c8377b9f131e09e39f -8e514a62ac1e91773d99588415426c97ad63e917c10d762fe06ace5277a5c3bf3730e4b9e5d116f8493b9ab8687b70e3 -83932df2d923a5052468a3ea87f7b55c6a80ede3594046ee4fe233046570921822bc16555b92ba6aeabaef9b1dc0805a -a2b5bfb249de3472113fd3f35bfabf3c21d5609da62a27ea6aab5f309c9068d94bc58ba03efb4ec11be06306d59e60e8 -8106cf3ebe6f0507be8c6e8d137987315fe3689ecb75bb27980f36ba5efac504baccea0e7603549b6d126beccc278804 -a73ee70b6fe8c082443972102c453fc0e386852476cf22224fc0bfe554735c12f96037fbf10922795f4502c4f052b5f4 -932b27e175440169958504f3ed6400e7d6dcd5e716c19dcd0f15c56c04503ed133d5a993e111c016f141e32d68b29886 -96f7ce4595318e0b4a6b368f788ff82226aac676aed4ace343867f751de414453a9aaaabef6e6224ce5aedc3d5cf77c4 -a950c1e3bc9a14484997013d44d876374b939af437ae7c821c131fb886063ee9fe7214a25a0c7084f0b07b99412eff75 -a9dba3886ed6855303106a1bdd26010f294218684e1c178afcfea3f37a2f04fd01724a31d82de3449046617e3507a115 -87a2f776b32a6b550cf3ceeaf78db02819be74968d228b1d14e0d74a1cdf994bb500b7abef6619455e98d728701fac5c -8cd887b07e335edc0b27e6a660cebb64d210741395be431d79d570139687b056557159407459799a8197b6079644f666 -b81a61fce00588909c13a90c1caa150f15788786af443ff60ce654b57147601f7e70b95659e01f470334a220b547611b -8aebc51141544c5f3d3b99422250424b9800031a8fdfbf22c430907a3a446fecaa2392105d66d64b1c8e847240da4a6a -90db7dc12baa02f3f86d3edadf9434e2b9318d4f6f0eca08276b765dbb38d8eb0d08be2fe70adf2bf16ceda5db08d3ca -aa1839894152d548cc6ad963de20fb6fcc843bc9af2a2bf967c63626b8ad19e900894d6106265f38f3afccca317c22f0 -848e27b741496988a582515c0c8847b2bfc6a001259396cdeea1e1b1d2828ca3a626693a1bf4adf3a3d7f8b1fa3d75fe -a0aa11754d4ee136ac3ca609b17bcae77758763b2016544ca7921dddedd8aafcc7ad5f2b337c8bf53084eb8e43ea41fb -b8713b7aa1c112178195fdcc9b7024f46e6bc04c4e76c41abe620aa265287809200d98eaed6c9703fa97e81d6964f0ec -8605b5b33309e9ea6823542b85383c496794b8481c577497aaf99ba90496e794dce405be615bf92c7b6361460e6b82e3 -826fa34faa7f83e063a7bf172addfc07badabada59cfc6604fdf481d29085251c0a67a1355b2cbd374e2975934b84cb6 -b45d131082dc16fa53af010d43eefb79200dc23d2f3ee26af95ac6a5cebc49c84a9ed293e534ed16ff3ef9a4a25456ec -91bd6ce3c5396a7a0de489e49f0cdf6dce1cd2d0be7a410326423c3185bd1125ce1e610768be7f15f4e44b62f8834fc3 -903ffbe3d33fbf106c01c727dc3a385201a67ded70d4df623934882f69a3a96c909b027a124f3d70cb072b0046a149e8 -b405359db9d9ef4821a181b440ef2918c240595141d861d19a85867a5afa74d2972d22c988775eab441e734700bae4a3 -8abb756d027233c83751910a832b0ef4d28d100077f1c5d656720c94906f91d85dd0ea94b1cc0ed95b692efee14c786e -a78ee77ab476a41a3454160ba7ca4085d8b1f7057c63e76db8b07cf20afdeddd2250cd00771a6329133bb4ad48ccc20a -a41810271d8c37197aa9b3dfcefe3498e42f5978d3f3d59defff4676d6402d8575b40683834f184f143b6cfbfc859b3a -90c24a0750242660bcc6d487358a3cc015730538a0a8beb00ad5ac2ef33cb8ca8a62121e50bec8f3d2f43900f8e3134a -8b96c39695d864ef5796941754978a1fd612b369f6b77fe5ae6587beac936ee28190af8f0a3822b63060af35e49a5c8b -acde2548883d0e63c0fc257bb9dadd919aba60a985b69ebcfa1bca78acca42fc1322ec30bcc8e7c188818f858d04ad33 -895c86ae9ff8d95f2707d4838a3bc8ddb05b2611f0476f014b9c150d0e8332bc73285037a747426f09ac8179ba4e19fc -821761fe406e18bd86fa9ca9db99d382cd3b5c70c456f471fa3706d57763d147706304c75d54f51ce8f3115aa26e59d9 -a803a80e3e8f47dc3c59ea23eafdec017458eac648b360cd42cbd075e0dde6f6f450b48c7646fb1e178c04f82ae51a12 -91f40e1b6f588bd592829ce937996452c40be0fd6c43793c607866701ac6a8c7227e0891d45c6e7b1599382b0a3fbdbb -9408246d996a634a58689337f2526dfb3ba9ffef1d3ff91c32aa8cbbed900861ef25d6477308b67d76491edfcc70d65e -a492325a427f3df1c9c690c5b553daa8ac41f62f5ae55f425539222bacf959e2f67afabbba1732e120d3e7a6dcdf7049 -8fd0c3e15477cae228613a171b6e9ec29ddc63ef74854d99b638adeffe39f89f34346a42851e8445e855a9f2bbef0f57 -b735ed01fafa051004dbaad5e8c9e2faca8f6049ef9b590f256ea4d75b04594af12764ad4e6031735eae36f83179db93 -a7d35f43fca06c86b3425dcb68a87186834ba9740664fd657915771beca4cdc0fa2fc9b4c2e9d9bdad8ec33543ddfa59 -a1156e71e2db1b17df5da28747c88e091bd687bfee59d89096437ab4dc9a543fe5c5272d5023d72adbaab397a6fc94d1 -ab06a58bd81b33a411bade8d8c5232d38fadc2e38507159edea6e2e104b8ebd65ca02b05335118f691d44197b847a4dd -848b67a10f1e6ff8f5c228f226ef2ffeb67fb8f50925fc94cbb588d61896d9dc79726959e649898fd3354fe3ff7b7ee3 -aa933397361f32b388edcf832f0db172a38e756b34d5f7a4a050fa7325058006c22cede26ee27917e8f1b0f301792bd7 -89e49e7f02cfaae4a4b9c4180c9f6559d76e3a45774955859d4147970b1470dac37bdc9aedca1c32a20b045049161590 -adc1825d5ab94fc719f25d8c9773f4d518134ed88eb13ac33cb910b2be3523ef9ef88d9e4aea2418b806e20108317bf6 -96c4b444c8a023da644f3a343ebeeed19a8392d2ce175992461451c318a54273b76c3574d8f2dceda2947ddd34d1a674 -8aa7e97e87c8c5b29bbd51a6d30396a6be1fb82b716ef83800f2c36d5b85467ade7e0f59d2db82c310fa92a9265f0b03 -9146c32d99f02c3a6f764dcd9b4807f1585f528ac69dc4f84e4380f6fda4f9d5057c375671d51e7aca2b2b4140e83da0 -a10760a533d9bc57536bcaf65f080302086aa50225437efd64e176841544711828c23a15c49c0dd1f357d3f10722ab72 -acb0811777e17f7ae7aaba5f6fce81b759c067a4908730916195a2505c7450d0e6e2194c2ef0f241090597d58e70de47 -b24f161e9bcdbad56665e2490b5e4c7768390d4668cd69a04ed74739062dbe832636dd33cda89e9b0afa8c77e93fc641 -96b4d01106b831868a88ef016500ef2fa42d0ce87a37ca8ca4194a92a22c113edfe04eb2ca037329f3c1acc635148f55 -aebbb95fb4f7adcc8e7a217aeb73f9e037cbb873d08c1cd9d68c6c6834511adf1af8b44567fee84327599bdcb734dedb -a9bd8b17300532fb94d028659bcafbe7bbdf32f8945baf5db4cfaa1bac09e57c94cad0ba046b4514044b8fe81ea8596d -a5557cbda599857c512533e7cadcf27bf8444daa0602aa7499cafc1cf1cf21f9d16429915db7485f0e9a1b5046cf01c5 -8810307c40bc661c478a9747ebf2a30e5a5ead942d1ac0418db36ba5db0709c476f7d19685cabe6959e33ec1f3bff914 -8829b741f41f2c32e10b252d9338deb486dba2f23996a44cf1dd888ad967a589d51329be34d764139f372a1043f6c2e5 -a6b4728d18857c5fa082fa67bfb3b1d801e76b251b1e211a19c87cea5fe7ce757f943c85071f7a03a718388cd5690e95 -86da7f397e2533cd487f962ae58e87bea2cd50af70ef2df9ea0f29f70b5843cde664d30ec207ab84fc817f3851277e02 -8085776ef4ac6d42ab85b9d9135ecc6380720efd274f966544eeedf4684028197de76ecab919fa5414302597e1962bca -b05a065c733033d223ba13d16baa7a97bd8c8b8b1f0e59a9bdd36ee17e9922d48eb39bd180c168b122088a77f0bf321a -a89343fe44a93023dcc7ef71bd3bcb6786f68e1885ad260edc56a52445d34757f476395ba7ad35437f89bc573c7618dc -a114a9cd6105b524f3969c69faa2e09afe21753a93361a296f9e0e3b4e3e63726ddf2e6bfd3ddc046043e50bd44e539e -8a5611fec539cf681c05636bb580f29acc06f628bb012649ffa41ea6c1521194a5643d5dd843f09b6eb2c3bdb4d41acd -ade247c4011ec73ec90b72f35afa59a999e64ba5a7e664a4b30874fea53ba6a14a76a41b58a5f891a20d019e5f091bdb -905b5d96df388160ade1ffe210d0c6d1979081bc3de3b8d93ac0d677cc2fc2dc1ef6dcd49d3947055514292a3fa2932e -a9520796ca9fccd11b7524d866507f731f0f88976f0de04286e68d7cf6dbd192d0d269f0cd60fd3d34011a9fe9e144c2 -989a1edf4d7dae811eb57a865c8e64297837ffeeaae6ee6ac3af0f1044f023f1ca552bf00f1642491f0f0f20e820632e -879c8e63713f4935ed6e020559e140ea3073ced79d3096c152c430141272117b4fd9a9fc3eef012e81262df02ea14bd7 -95074738ac1540c0312274333acd1ecad9c5509fee883c4d9295fa8d8200f6e637c363de395f9fa612f05c0dc58fae88 -a770e4fc595269eb806b113ab3187ea75c8f96b57bf9fcfaf535f3eedc1d4d7e6285a20990575de0ff09f62d06ed0692 -81283e5dfb6423439ff513eca1cc316941d196df8da2d1069d2d0b63f5289e630af2fd4119bc0144c002d33313372dab -abd1b108e743887b78f698f2aba9d5492f87a22868d1351d705d93a1084fd45be67170c68a6e18b07f400d9a01cda8c2 -8509c3f67b92908cea8144f4e2a71631a66a61ac3547601c788907e52e380e5fe8ae4110aed95d13c67d3bcdd5b55a61 -8fa5a790ec5cce6d4114128c295390120869aac5490a82feebd3c37a167120df2e7fdfaf2a4050a7dfebf48fb093212f -944753e1ea7d8bc727d46a7702077dc01dc0c6574e8263a16579b57ee155ca5901f71bb347a01a9a922b329d3ff75135 -b46bc1fd4590b7a6275e20036d247c5909fc549c78e95b64ae7ed96e3b05bb044840f19f7650ebfe7008ba09fa83c3c9 -b1e47e4d88e59a06c465348c6cc4181d40f45b91e5e883966d370c26622c328415c6144aa2f61ddb88ec752482c550ca -8bd4f8e293e3f1815c7e67167618fb3b0ea76424bc0985908957cfcede36109378e41b4d89555b8c2541b4c447e00461 -a70589a867b2bfb63d0106083d58475d506637148549ed35c83f14e5c8de996e1b1f3447ecc80cf5cd134ef4db9d2fb6 -8048b80ba6131d07370162724127b0f7cb17fa7f71855e55e5a75bd0a9e4fd71b0d0ea2d16ec98858e458528df8d06b5 -97326cb94bae7530f4ec3235770c5a7ba042759e789d91c31fedbd979e3c0e6a2c69e2af3c1979c6fe0094274dbd53ce -a18e9c1d3eabd62af4e31a4b8e08494f4167fd4598c95d0123f39c46c53f9e93f76615900246e81a286c782ac37c569f -80309c59d4522b15aba617cd3c6238663e8b1c7ad84456346082c8f281140fc0edf9caa19de411c7e7fb809ca4fa3f4d -8e450c0990e2f65923f252311623038899eeff7b5c2da85b3a224e0ef7132588b291b782d53c477ecb70f34501466178 -87843f96f41484e254e754c681a65681b9ae5c96c292140368743df9e60f7e2ada58ca2bb95fa39abe064b2ebf21eeba -858e8d5bf2a1cf26d8af5036b28b831d450a446026f58a1734b696c18f1f41482796b91cab0e5b443dd2f0b9cffa52b4 -99627dd6bad8c05c5904cd23aa667d664da846496dbbb8452705c4ec01e1480e9c7295504a5a8529e4a0c842306b038d -b64b33256c18b2c886a837a0c0730fdfe73befb0e2796207c4dc592c5a33cd51f8c2ef47c584dd5773abf9ce9c1b0082 -944f6da2a1546f0bfc4d98c3e73c79e935e33d208b6be26b0b5f8df6d0e3b74a5bda649853b99281bd3a3ec799a7dd04 -a266d165435784d4e884640155e35b2a911b3f89e1e715986de419b166a36a341ba724877d80583fa3da566f6a828971 -adff2698409d0756e78c534032ee926560c13d578cb178d5073172d049ebbce32a92692f7e2033ec781b9b0d894ddce0 -a91933f110756c699c28bf9e24fd405bf432002a28c4349e0ca995528e56a5a2d101b8d78afa90a178ff1a9bf2ba515c -8e77839c0eb4da2d01e4053912cd823eddffbdc6b9c42199fba707ca6ab49fc324288b57be959fbfb11d59085d49324a -aa124517c76692036c737e987f27c2660514e12a953e63ff4bcb269dd18fc44dae95e282de8444bed09639ef6577af88 -b285deae99688f1bd80f338772472fa2b35e68887c7eb52c4ef30fc733812444c5cd110050275ad999d5a9b57f782911 -8877b0fa85b44ef31f50bdb70b879fa6df5eb1940e2b304fd0c8f08abb65f3118fa3d97ff93919038c1e452fb1160334 -8a89f3b50dcbca655024542ca7d93df17deff5c7d01c7da2bdb69e76b3e0b4490d85c800fb3debb4b0b4d20c9527f7ad -b7e5dbe36e985354ac2f4ab7730fea01b850af00767a6c4d8ee72e884d0fe539bb81f2e34638fcf5d07b7c8d605f4c06 -a85a1d78f6d4f9d5d83ec0f2a426708342d4e4a5d15625554e8452f6a843d9aa4db0c7e68caebdaf767c5b3a6a6b2124 -a518078a9dac63c5bf511b21ed8e50d1ccede27ebfe9d240937be813f5ee56aef93dc3bf7c08606be1e6172f13f352ce -91144eedebda4d1ad801654ef4ecd46683489b177ba1de7259f7dd8242c8c1700e15938e06c5d29aa69f4660564209a0 -a16c4657bc29d1d3271f507847b5a4f6401cee4ad35583ad6b7a68e6c2b9b462d77b5dd359fd88ea91ce93bb99130173 -85b855778f4b506880a2833b8468871c700440a87112fa6a83fd3ddb7e294b3a232d045dc37dfc7100b36f910d93c2ae -8d86bb149d31bfbf1fabcae1b8183d19087fd601c3826a72a95d2f9cedb8bb0203d1136a754aa2dd61f84b7f515acfa9 -acfe7264eee24e14e9f95251cbcfdd7e7f7112955a1972058444df3c2d2a1070627baefada3574ebd39600f7f2ea7595 -906bd14ecca20ac4ae44bff77cc94eb5a4ecc61eba130de9838e066e8766ed3b58705f32c650e1e222b3100691b3806b -8f2cbc7b8593c4be941dd01b80dc406fe9dfdf813ef87df911763f644f6309d659ea9e3830ff9155e21b195fc3c01c57 -a68eb15ed78fae0060c6d20852db78f31bebb59d4ddc3c5bdd9a38dbe4efa99141b311473033ff8f8ea23af219bc8125 -a95cb76c9d23fc478c7e8a73161f2ff409c1e28a2624c7d5e026e3cee9e488f22225a0c5907264545a73e83260e3a4ec -b76f90e55fa37c9e2732fd6eba890dd9f1958c1a3e990bd0ce26055e22fe422d6f0bcc57a8a9890585717f0479180905 -b80cc95f365fabd9602ec370ca67aa4fb1219a46e44adf039d63c432e786835bb6b80756b38f80d0864ecb80e4acb453 -b753c86c82d98a5b04e89de8d005f513f5ea5ea5cf281a561d881ed9ad9d9a4be5febb6438e0dba3d377a7509d839df0 -a664733f3b902fac4d1a65ea0d479bb2b54a4f0e2140ed258570da2e5907746e2ac173ace9120d8de4a5e29657ae6e05 -9479722da1a53446e2559bb0e70c4e5bf3f86c0ce478eede6f686db23be97fcd496f00a9e174ceb89ab27f80621f9b80 -b707fd21b75a8d244d8d578f3302d1b32bb2d09f2bd5247dff638d8b8b678c87d4feab83fe275c5553720a059d403836 -93214c16831c6e1d6e5a1266f09f435bbed5030c3c4c96794b38d4a70871782002e558d960778e4465b1ff296ffedad8 -8648f84e18eb63dad624e5fa0e7a28af2ee6d47c28f191be0918c412bf24b5460c04bf2b7a127c472914a0741843f78b -b67f61e75d6b773a6b58b847d87084b94f3cdac3daa7bef75c2238903a84250355a986b158ff96ba276ca13a6035fdd6 -ae9b094b7b5359ee4239d0858d3755a51aba19fce8ad82b0936cca48017523319c3309409ea6e9883a41bece2077e4d8 -8d1d8e1fba8cebd7a0e1effea785a35e16b1a10842f43e2b161d75add11eccf8f942d2ae91c20eef6c1a0c813731ea9a -b82bd387458e3603782d5e2dec32ae03890a3fc156d7138d953f98eff4200de27c224f626e3648e80cd3dfc684c4790f -a6dd02a89ad1c84e25e91176c26355e21a01b126c1df4d22546159dab9d502dbc69bc0d793a017c1456516e4aa5fa53f -a9ab74a5c5459b8500beb0ad13e9cfe2656e966dc9b4f3f98bec7588023b4ddebf74e4fc722d30423f639f4ee1b2587f -b03e5f33ab7ecec12cbc547038d3fa4f7ea0437e571891c39660c38d148212d191be29e04eb2dc001b674219b7a15a9c -925df4fc6e898ca55090ad1a8f756cc5014167a042affda5b24896eeb6aac408545134920586a8e1a2b997de9758b78a -98c8580fb56ed329fad9665bdf5b1676934ddfb701a339cc52c2c051e006f8202e1b2b0f5de01127c2cacf3b84deb384 -afc3765d374c60fac209abd976fe2c6f03ce5cc5c392f664bb8fac01be6d5a6e6251ac5fb54cfcd73e3b2db6af587cbb -8e7e98fb5a0b5b50d1a64a411f216c6738baaca97e06d1eba1c561e5c52809b9dab1da9f378b5f7d56a01af077e4f8cf -b724bf90309651afb2c5babaa62dc6eac2b8a565701520fe0508cee937f4f7b6f483fc164b15d4be4e29414ce5d3c7d4 -9665160e7bf73c94f956ecb8ba8c46fe43ae55c354ce36da40ccc7594beae21d48d9c34d1af15228c42d062a84353a0c -8600ab3aa86b408ee6e477c55572573ed8cfb23689bbdadf9fccb00161b921ec66427d9988763a7009b823fa79f8a187 -b0d8d19fd1022e7bc628d456b9bd1a2584dce504eb0bf0802bdb1abd7a069abbeeccdb97ce688f3f84a229342dbc1c33 -8f447d5e5a65bb4b717d6939cbd06485b1d9870fe43d12f2da93ca3bb636133a96e49f46d2658b6c59f0436d4eede857 -b94e327d408d8553a54e263f6daa5f150f9067364ded7406dcb5c32db3c2dffd81d466ee65378db78d1c90bc20b08ab3 -b58c02781b74ef6f57f9d0714a96161d6bfa04aa758473fb4d67cc02094cd0c0f29d0527c37679a62b98771420cf638b -8cfa0a687ea51561713e928271c43324b938aa11bb90f7ffaa0e4a779b3e98899f2af59364ce67b73a46a88748c76efa -95d6d39c814c5362df69116558d81ce6f1c65fb400fc62de037f670d85f23f392c1451d43341c59bc342bc31842c8582 -af888b384c52d9e04e4db6c4e507c2037eb5857e9bcc33acf84fc3a02d93cbde8cce32141fce9f5fec715b5f24d56356 -a7822bbc3c236fd58bd978f0fc15fe0b60933a0c953db6436a233441219418090ae0c07c490a6548e319029771cdaba7 -8c53729f750922e5eb461774be8851a3f40fe42eed170881cc8024d590bf0a161d861f5c967144d15cdcdc3dc6b5cf88 -a052a25a4aeab0d5bb79bc92a6ae14b5ad07d1baca73f4f6684ccecfc7ea69bc21eadeb9510452fdba116c0502dd698f -923946b83d37f60555dbac99f141f5a232728c6eb819a37e568c8c6e4d9e97a4229fb75d1de7e9d81f3356f69e6d36f1 -8cab82cf7e415b64a63bd272fe514d8b1fa03ba29852ec8ef04e9c73d02a2b0d12092a8937756fdec02d27c8080fb125 -b1123314852495e8d2789260e7b3c6f3e38cb068a47bdf54ed05f963258d8bcabaa36ccbea095ba008e07a2678ec85a7 -a685b779514961e2652155af805996ceb15fb45c7af89c5896f161cac18e07b78c9776047c95b196362c9ad5430bcb22 -b734dd88f6cc6329c1cb0316c08ade03369a11dc33191086c6a177cf24540c7ceee8199b7afa86c344d78d513f828e81 -b0bf492fb136ecdb602c37636ed4deef44560ab752c0af5080a79c9f76a1f954eba60a0bf6ba8bd7b8cac21848c29741 -a5c74682323e85ac20f912ab9c1d6e1b9246c4c829dca40c8a7d58ec07ea0ad3524be30623f351269552f49b65a1245c -837403b9cf830fb33ecc11a7c8433e07745973c36acdeb3fc9ea8f7d8d690d462e1250b7410f79f2f4180fe8f3962a4f -b03d64b944d49c83608f2c5b9c14070c025f7568c4c33d4eeb1da31d07f0bc5897e498b35b50d557ee129f0c3c68e254 -827272aab8bf757e2483156e00fbebe1093a58070dd3af9855bbf946c7abfb9c8a850a6a8acda8c620902f391f968b8f -84c4eb863a865282d321302d06b362f8bd11c2bb0090f90ebffedd3eb3e7af704cff00d39a6d48cbea4262942e95200b -b044eb91653dc55dce75c8d636308a5a0dae1298de4382d318e934140a21ca90e8a210e06fdf93aadbbeab1c2ef3904a -a8c08955a4378522e09a351ecb21b54025a90f2936b974068e80862803e7da2b5380c4b83b4b4aad0409df8d6c8cc0cb -a763a5fb32bd6cb7d7c6199041f429782deacac22b6a8467077fab68824dd69343ebca63a11004c637b9cb3129dbf493 -8c44c8afa9a623f05c2e2aba12e381abdb6753bb494da81f238452f24c758c0a0d517982f3999d2537b7279d381625ed -8613f47fda577cd3bda7c99b80cf4b2dd40699edfd3df78acb5e456dd41fd0773bc8da6c5e8cbf726a519b9fb7646ccc -b21a30d49d7e1c52068482b837a4475568d0923d38e813cea429c1000b5f79b8905b08f6db237e2eccf7ef3e29848162 -b9bdf4915f3fbb8d84cdfd0deedf2c9dc5b14f52bf299ef5dca2f816988e66322df078da2c54b934b69728fd3bef40b5 -993b45f389f55eba8e5ba1042d9a87242c383a066cbf19bc871b090abe04de9ff6c1438cb091875d21b8c10fac51db58 -a85a95d14633d52d499727f3939979a498c154fd7ebb444b08f637b32c1caf5cca5e933a2f5d94f26851ae162707b77d -b9874c7c4be1c88a9646e0c2f467cd76bc21765b5ab85d551305f5ec0b4419e39d90703d4ac1bb01feb3b160517e97b7 -ad6771177fc78812904c90594712956357de1533a07fec3082ba707f19c5866596d624efc3e11773b3100547d8f6c202 -a79f31921134f7197f79c43a4b5d5b86736a8d3ad5af1bdf4ad8789c2bfe1c905199c5e9f21e9f446247224f82b334f8 -a7f1b6c45321222a350a86543162c6e4e3d2a7c2dce41aeb94c42c02418f0892dbd70c31700245d78c4d125163b2cd5e -92abafe3ec9dbe55c193fb69042500067eb8f776e9bf0f1cb5ab8eb12e3d34986d1204136856fb115c12784c3b8dea6e -89bc761238a4d989006ca5af5303c910c584fe7e6f22aa9f65f0718a1bc171e452c43695e9f5a591725e870770c0eceb -aa0e44c2b006a27d35e8087779411ba2f9f1966a0f5646ff6871bcf63a8b1a4a7638751b94c9b9798ccd491c940bc53f -8736fe82862b8106e7fdab7b5a964d87ec291a74b8eb1cb5a6c046a648c1b686064ef3d52297043b8940bfe870c712f8 -956a3def1942f05144d8e9c3a82fd2d3610064b53b9eefde3d5594a8f705bf8f6849eb2c22181796beffeba43cc74ee4 -af27416d00cf97d5a1f4a1b6b51c010884cceca294f1151c3b684a3f83c3c8a3c30771df1166d833cbddf6c873c400c3 -aac3b8dca2336fc4ffc63c362df461289e4bbd3418c621bde6c581d3ecedf66e2b3e523d4db39e3d8ba014577bf85efd -94c3a8167f62074e5b28c2bffe4b6ce645439a9a0c5da3ca1b3ee956590a465d6f84a8a4dbbe9070ffbd6bbc734e4d62 -95e23ba6986d25ed4451215da05bd72c5491528271726d79a94c8cb16aef1c85b190d6c5b8a3a1191c7cafbab1dccf0c -953e3dadb5ad68f7de31ac09692948655d174fe16d88b96930ef35b331da7f1dbc4c17863cd07b4ec3135b5205891a27 -915d018f18b5d63cb3301c2bb5c6e85e75a88ba80663c964d06575b6bacbbe59139d030b218ce0998271d5b28c00b26d -8c871ba3dd138a908b2f7effeea0e71df096b23e0dd47cab10b9762b250abfd1221da94a8ee884e05bdf02271fb85a04 -96bad5c6ebc3080ecbe337409ae398bbeada651221c42a43ea3b7c08c21841ddbcfde544c9b8d4772de6f2ce92c0b963 -b5dbcd0b1c44c62108841558ec0a48df4b327a741e208c38b1c052321eda6e6ad01af71d49dfcdd445ab6fa6f0c34e6d -97dba59219b69e8aef2659d1f10bbea98d74aefff1f6451de3f41be39acbac0122b8ff58b02e90554469e88911ec3547 -b7e5682ec306478be4858296f5d03364a61f3260636a4242f984d351a02e8723378496beb30c4ca22def9c9ca193ea70 -9656a7a3df4d11df3d8bc35930dff70a5e78a488ca57bba20bb06814fc390fc6c7cb3f39b22134992aad196cced577de -8b269695aa63eb56d0324ba984279dc4c88e565321f1d61d553622bd4f1910d5eff68393d3a830eb924472bd478c2aa3 -9177bcd04b28c87bc0440268b4c8995c6790cad6039594971b2c177f0e197055231e776927d3fa30d98fb897a2ba401f -ae0e943973482001c4f214b9da82e1c27e38aa254d0555e016095c537c835d3702bc2de5c67b234ab151e02b3b7a43a6 -82fc719a7d38bf4787fe1888019ad89fbf29beb951d2fece8686d2beb9119d0c8c6d13bc598748c72c70d73d488140ca -b716dc66f87eb16b95df8066877353962d91bf98cf7346a7f27056c2a4956fb65e55cb512af278783887ab269e91cd76 -81d58cd8bc6657362d724b966321cd29a1b5cdc4601a49fa06e07e1ad13b05e9f387ca4f053ed42396c508cd065c5219 -b32ad0280df6651c27bb6ddbdc61d5eb8246722140a2e29c02b8b52127de57a970e1ded5c2a67f9491ae9667349f4c46 -b68a2eb64cc43f423be8985b1a068e3814b0d6217837fb8fbfd9c786db9cca91885c86899c50a1242040b53bf304ced9 -85887515d4e371eabb81194cbc070e0c422179e01dbda050b359bd5870449c7950e6b3947b7a4a0eb68199341cc89fc3 -ac5fff3c27dfbab78eb8aad37ac31cc747a82401ebf3644a4f4f5aa98d37b8bf3b3f4bd8a3428b32a127c25c9e19d239 -86fceaa6fbf8913553a9e1e907fcb1f1986d5e401a7eafd353beefd1899d571454fea96ff5b2a21254d9fb693ec94951 -b6778bb296d3f0de2531b67d36fdbfa21475be0ca48b9dfcc38f396c41b557823735ed0b583e525a2bae1fe06e04058c -898088babeb5b9866537d6489f7514524c118704abd66b54210dc40a1c1ddb0a1edf7fe0b6e0db53b836f1828ecf939e -b27854364b97274765f0fb8d1f80d3660d469785d1b68da05e2bd1e4b8cbbe04304804d4c8aabb44cf030eba6c496510 -8c55bbf3603dc11cb78b6395ccbc01e08afcef13611f7c52956b7a65ccf9c70551bff3ae274367200be9fc2d5cb26506 -947726f73cd6281cd448d94f21d3b91b96de7ad3ff039f9153befbb5f172db9f53cacb4f88c80a3db26e6a0f7a846eb0 -a7b733a05e97528812d71cecb4f638a90d51acf6b8fcbc054787d6deb7e2595b7b8d1cbe1aa09d78375b5e684a2019bc -8d5ca6d161341461544c533314fe0a6655cde032c2d96f0e4ea7e41098b8b39fa075d38e2d8c74e2d0308f250d6cf353 -b960e9f081393e2260b41f988935285586a26657a3d00b0692ea85420373b9f279b2f1bb2da2caae72dd2e314045f1bd -852a49c7388c10821b387c6d51617add97ba72485f52be95d347bac44c638c92e9c6a44ba0d32afc4d59178a497d944a -8412162a65147e1334ad5af512982b2b48eef565682b3f3e0bbe93fbc5e1103db9375a0c486bdb1b2c57e4cb3a8e7851 -8f52c3eb5d4f1e1e82cfd2b291d4910195427603b796f6c311deb35ef14a01a57a9e6cad39619ad108f3e86f384f9e1c -88d221088f2bf0103c53e44d0d96cd7881ec2b0a965db9121a47481771a8b796edd5ac23c4f9c208a171dab301f7d3bb -b49c3235e8b3617ed08a1891b9e2bcb33dbdacceb94ca96330555b7e00904fe6a749ced9312b8634f88bcb4e76f91cb1 -a85834215e32f284d6dfb0cbfd97f6cffc7b9d354e8f8126d54598bb42d7f858a2b914cf84fa664069632db2ff89a332 -aa3d48eb483c6120c27d9b3e3d0178c1c942632ff54b69f5b3cfbc6ad4ff5b2b9ce6eb771fd1eea8edf4a74c97027265 -a446cfded353cdd9487783b45846402b973cdeddf87e2bf10cf4661610fff35743cc25e8d3b5771dcedfb46b018a5d18 -80998377b3b393ef3073f1a655ad9d1e34980750e9a5cfb95f53a221b053ddb4d6985747217e9c920735b0c851d7551f -a35ac469790fac6b8b07b486f36d0c02421a5f74ea2f0a20ffc5da8b622ac45dfccabfb737efa6e1689b4bd908234536 -8fb1f6d8e9c463b16ac1d0f36e04544320d5a482dd6ffaec90ea0f02b4611aaca984828bf67f84dcc3506b69af0a00a1 -b6e818d61aea62c5ed39c0a22ccbb327178feebdabda0c9927aa1549d2c5bb0637785c4aed2a6d9a7b4989fa8634c64a -b4e7208d16018bf67caafe996d436113eac619732e3f529a6efb7e6f094d8ebea55b7be0e122be075770f5957b6ea6f0 -b691d38b552befac61f6d367287c38d01fec73b7f2efdb6713ca30314a37fb7c177eb111fe6bee657f2681014e07630a -9817587e418e6e7e8e97ae27067f17b55d25dfb14e98f63f530620c855d9a348c9fa571c8508e2741f902f8b9fdc0c5c -b6a6e5ca779ba140bf1d84cd5394ede8262f7479637ec0087a4b152243a1774ba916d8115ce759a3bebd1b409de5f2fc -b53d1c84ad766ff794bf497db3228efd2cc8ed5fc1958d89c1126efdff361610ecb45ea8e329b39035ab00a66c1259c7 -adc31333c507c8e0f4aa2934fcdca57fd9c786722a50dbd5404e129541f7ac182cc7373bf14e1e4e06e6cf94b31b90eb -a82b7fde4642d982d95cec669efee140ad797a2442c7f6620580527d163accbf021b893446cbb8038ea82fe25b15d029 -91f7acf8a8903979afa281646fdecb54aa4d2ed905748e156e92f0910de268fa29d67107d40863935d677d1de8039be2 -86fea71c6d43a7d93216a92fc24dfce8521fd4534a9558b33762d002081247867a6eff54cad7116023277fb4049403ad -8ae5369a7f9f4c91f3be44b98089efd9c97c08f5bb4cd8b3150c115ecd86288fa0865a046a489c782973a111eb93966e -b6fb9e829aa2c81c2d9eac72bb2fd7f3a08e0cd763532c2ce3287444d33cf48b3621f205e9603ec58525934b61a795a9 -83e35ca808d84e41fc92115e9f6e283e928c3a614e6dfc48fe78c33b6411262e7bfa731eadb1e1937bc03cff60032e1d -832fca5196c95098ad47b7d24ba2f9d042e1c73ad2273edd1c2ce36386796ccc26e8567847697f3fcc2a0536a2a2087a -8fdb7038bc8f462ab2b76bf7053362f9c030019f1b6105cf42219a4e620ecc961e3eacb16a8e581a562a97f1418b0128 -8d3a5a404b51b1ad8ce3b23970e0d5cc57b573922341008e3a952a1dd24a135e19e55b79d86a70cfd82e1c0e9630f874 -ba00c025c1c21c57c03cdfc0bfd094b35422281ff0a64b68b240617aa58c6b18800af5f2047d3ff9068bbe987d6c7980 -b468f0dd51964b3806b0aa04f3fe28a035e8f5567fc7d27555be33d02701a838b8dbfe1348b6422c4eac46d2c75c40c7 -8a73a18c97da9958903c38584b08d0e7e26993a5d9b068a5e0e1ee0d8a873942745cf795f94f7a3d3ba88790a9fbb2f6 -953a0a40c2c8102723736854d13b228698c14a02d85c8d2e61db1a768019ac305faf0d5db62ac976430ce087a5b20f1e -8998219da6b34f657cb8a621c890a52cb98c2bc0f26f26e2af666eebeadadc5e8bdf4f830a91d04aca8ce186190152c8 -8941e08c3155ad432236ed05460420a05dd0aaab30477493ffb364b14c00ea5b9183d30d3442b6321d2d20c36e4f5c7e -93f293ff7fb56cf5b03aee6f3ad2ad78444398ed5b3be56d7bf5b56b5aa5a2b980d13895dd57a5726d1b067c20cc55e2 -84a16f313e3f75e31824f58d19ab24c6611fb4c75140a7cadc3c166f68819547c1d0ff7f7d13f5d8ae30dff1d80e2aa4 -b6e3e830b15039d3e28b08f5465bb089eade11ee3bd80afe39e010df7db1fcf0c56d698717677a41ddbc91eeaf6544d3 -95e928e6dfff51351281568ae72da7d1edeb6e9fe01f30af0499e7505ba35a22b5bb919d41bb809a432dce83f3977663 -aabeeb60ca46f9b0232ff82ea7766dcab8cc5aaf9d23539f30174f9486640bc9312868ca493b59b314519fc399973e47 -b393a11e957d0bbb3ecf617b075b5906a3450b348e62916c04791b366f0a7397cccd6648440ac544bc30526e1f95aad8 -abb5bfc3964a6d246da60bd809d0ea6daf4f8222efdc12ceb6730194e85f413ee7eb03bae300abf7ea900dbbc3d08971 -96c1bd1d1d216a4bfbcf000c123f296c0d31e1684e9e3884c14df23bf528c8d599f82bb98fcea491716b617216a8e0be -92d1e570a56f1741fd9f3d9f488cc336421c6256c14a08d340a63720be49b0029e3780e3e193a2e22bf66cc652fa22a3 -8769c08551e3a730e46f8e5d0db9cf38e565a001dfb50db3c30fa7fa0e98b19438edc23c6e03c8c144581b720d7b33a4 -b850bd67fdf5d77d9288680b2f6b3bc0f210580447fb6c404eb01139a43fccb7ed20051999ae2323ea5a58de9676bfb4 -80285da7a0aaf72c4528a137182d89a4db22a446e6c4a488cf3411937f4e83f7b00ec7549b0b4417682e283f91225dfe -80520368a80b97d80feb09dbc6908096c40ff7120f415702c1614d7112b0b57f6729581c71f4a3ce794ac959a46494ff -9817b4c27a490b1cd5a6337e7bc7e8005fa075dd980c6bf075ddfa46cd51cc307ad1d9f24e613b762a20fc6c877eab41 -ad66bda1a3034ec5e420b78107896ecf36126ce3ef9705163db259072dfa438c6107717a33572272062b9f60cb89557c -876114ef078c2915288e29c9abe6b0ad6a756b5ee2930ba1b8a17257f3f0557602d1225e8aa41ce8606af71ada2a971b -aa3d6cde4c3b9d3d5d0c77a33e67f182a3e1cf89b0921423b2024236171955b34afc52b1f25b1dad9da9b001371771d7 -984d3e3a72412d290e3459339757af7520d1739c7af0cbcf659c71999328db44f407d92e8a69fea11625612c49eac927 -ae890d0faf5bd3280dcad20a5f90e23a206661be8842375fea2ab22aadc500849ffbc52fe743b376d46bb926cedae6a6 -b1f231f3f4d710c3fe80099faeb56dac67c1baf53b8fe67a9920fe4f90e52cb9a4bf19211249a6456613b28efe337f18 -8caa54b418ba609d16520af3dff2e96d5f2eeb162c065a1763beb926547b2cfb3ae41d738db2c5681a9bc8bc9e6b9a1a -932157ff56c5ac29cf6cf44f450c882b3acfbb9f43d12d118da3d6256bde4e6eb3183aea304ab6967f37baa718ffec99 -9360bed8fc5b6aac36aa69473040689bfc30411d20ffb7275ef39b9ff5789f9055d149383ce9f0f7709a1f9d683adbfe -98b5b33209068335da72782179d0c7aeeabe94b5560a19d72088fe8323e56db7ce65debe37a97536b6b8a0ca3b840b61 -89a385c11be40064160b030a1bb28c3921fc8078522618a238c7ea0f86f34717ed9af9b4e2e20f5128e5f7fc66ad841e -b615703cbc64b4192990cc7e4903b74aed6a0076ce113b59ef7719197ffa46fb29eb78ca56b49873487432d0625c0faa -90f0d77abae9d3ad73a218e5ccec505ad108ea098451461567ae8ef9661606ca8e78df53b5d628b20b7037bd24622330 -92e0e7cc4dfadc5fa0ee6da0c8de0493030db6e54ba0317f52f232a6708b732068b6077bd13a17eb7eb40b88368085b5 -a24dad20094985bfccc6df1343506ed3bf9dcbdf4b2085a87627a5d71f7568db067304e465f8f380c5c88e8a27291a01 -8629a45a10619354c84bdc2f6c42f540eab5a46f53f2ae11970433d7a2aef007897590bf31dfba1c921614c6d6fe1687 -84ac64040d4206f82b08c771f375da4b7d752e41d2aa0da20ce845f6bc1b880a855d3ee966bca19b8ec327b4b43e7f0e -9608e6050c25996c052509f43f24a85cdf184135f46eaac520a9a6e78e0d44a6cee50ebc054048c708aefde8cd6651c2 -a32032b0e0d7cc35e480c328f315327f9385adb102a708c9ba637878deb74582ae26bb6d6e5f8c9e3a839b0e0154b82a -b7e3c78d63acc6564a49e9f00b0a820b56d4f37a2374af1f7f1d016268011df9e7af0670ed2b0eee961f15aa948328dd -8b88bfdd353acc91ad0d308a43e5fb40da22c228f2fe093c6d6904d70f69c6203f56636ed898b05df51d33f1095ef609 -b1d7a430c51fc857af55047683fc18c453b013527196c5e1bf776819a3dffca802217e9249ae03f084e2ea03ad67fcc2 -80558e28a819ddb5e72e97c54be0f57c173ccf78038d360d190b7f1350a19577b8e3f43fa2f7bf113a228cd3b965b2e4 -b4b2ec44e746c00dfc5661ba2514930934fc805cdc29adc531c02d28ce3cc754414b0485d4ee593232cd1175f357ad66 -b57cee5d32835f76572330f61ccd25a203f0e4a7e5053d32965db283aad92f287645533e8e615137208383ec51b1fd99 -930256086b419a8a6581c52590d0dbd9f8a3564c79424198fca3866b786df2f6098a18c50dc4abd20853a7184b1ce15d -8e75fd01181cffcd618a983492390f486e8c889972a46c1f34a4e1b38f384e8e4efc7e3c18533aa2057da9f9623e2238 -b375d927dd988429f9e2764e5943916131092c394fce13b311baa10f34b023dd3571da02553176091a0738cc23771b9a -b9e28e4c0d0477518034d000e32464852e6951c8db6f64ccdb1d2566f5094716213fbf2fc0e29ac88d0e79f725e3c926 -963981e99392afbd2b8318d5a6b2b0cc69c7f2f2f13f4b38dddbfedb2b0eaf0584aecfcbda20a4c60789c15d77970a58 -a7804e1977aa77c263c7c001afa6cf568032dea940e350d6a58ce4614f1a91c13ae1c78bfea740c229dce2444556976a -8787204177da3cde6d35cd3497fa8774d244f9faa9f4bd91b636a613a32ce2ea0326378cf9c4cf475e73ef751b355c4b -895aeef46a07152a04ec812f1aa1fd431389fa0ef6c6e96a5b833e70ea14073bc9984757a8ee456dbec9788e74e6f0ca -8d17f0e5826783440d1f0ec868003510a4d9952bfe4a638e44a36d94482ac18ba70ef7ff773bdf7a3b62d714dcf0fcba -810d5e36b31310b2e054a666d3b3f7ed16dfcb1765532d87ca2a3920316f0187303c27dd113db145d47e8961062a6c03 -b4e2fb48ae04cf8580bb6a28095076c9b95e5f13122b917328f334d4ac8a8648ce442919e28319a40148987350ab5303 -b85549a313544fa1eb3ceb78473b7d3d717fc85b808de7b79db7dbd0af838ebb020622a7503f1cbacab688dddb648f84 -80665adee057088eae827a5fe904ec3ad77d8843cdce0322d535e0659b4abc74a4d7ddd8a94c27f2def5c34ac2c038ee -ad72fc19c2ce99b5b717e35528fe7d3ac8add340b02ebeb4889d9a94c32f312a0b45ea84d21c54f84cc40ee4958b72e1 -99d530c843dff89a47a5ee8c87303ab18f8a82b0d5b808fca050354b35da5c5a5594d55921c6362d6cc917d75bdc18dc -99c7286c293e1be21c5b2a669dfdfcd5aa587105d2886fc5a8eaf8984da4e907f7d7b8c2362d64a4f1621b077a2a08a0 -b4a39e1a9ed5d80c9563c3ca3fadf76f5478c63a98f4346a61b930c9c733e002f3ff02bc16abfdb53d776184cc3f87ba -9378ea71b941979404c92d01fb70b33fa68d085bf15d60eb1c9fc2b5fcdee6379f5583389a3660a756a50019a2f19a69 -b68e17344a2bc45b8e2e19466b86dc139afefbf9bad2e2e28276a725099ebac7f5763f3cb52002261e3abe45ef51eb1a -819e64dc412b2d194d693b9b3157c1070a226af35c629837df145ea12ad52fa8eabd65b025a63c1fb0726207a58cdde8 -a5e8ff8748419466ff6df5d389125f3d46aedacf44eaf12cbfe2f68d218c7d5ab6de4a8279d13aecc25f3b1d98230894 -91560d54a9715cfda9cf7133ae51c432d0bf7fcbaeb468004994e6838bfc5ddcfa30e4e780667d0c4c0376780b083017 -ae8adb3309cc89d79a55ff74f129bb311fe4f5351a8b87600a87e0c3ba60825f71fccf67eadcf7e4b243c619417540fd -8d92cc1a6baa7bfa96fbce9940e7187b3d142f1888bdcb09bb5c8abf63355e9fb942ac4b4819d9be0e0e822d3e8e2e08 -a6e8b79fdd90c34735bb8fbef02165ccbe55ea726dc203b15e7a015bf311c9cac56efd84d221cc55eaa710ee749dbdfe -a409b151de37bddf39ce5f8aa3def60ee91d6f03ddd533fce9bf7bdbeac618cc982c4f1ffbf6e302b8353d8f28f8c479 -b9693975ef82171b3b9fc318ca296e4fe6110b26cbdfd653418f7754563fa7b6e22d64f8025ee4243483fa321572bfe4 -a039ebe0d9ee4a03ade08e2104ffd7169975b224061924cca2aae71464d250851e9f5f6f6cb288b5bf15df9e252712a6 -b27834db422395bd330e53736a001341ce02c9b148c277dabac67dc422741bfa983c28d47c27e8214cd861f2bad8c6f6 -a2bafaf4e2daf629fd27d7d5ac09fb5efc930ff2ae610f37519808683aa583fe1c6f37207daf73de1d8a164f79a0c981 -b856cee1cfcf5e50db9af4ab0aed3db2f43c936eaea369b5bba65582f61f383c285efbda97b1c068c5d230cbe94f7722 -a61ab205554c0550fa267e46a3d454cd1b0a631646b3df140623ff1bfffaa118e9abe6b62814968cc2a506e9c03ea9a0 -8c78edcd106377b9cbdfa2abd5278724aed0d9e4ae5869b5d2b568fdabb7804c953bae96294fcc70ef3cd52ba2cbe4ed -8570869a9bbf6cc84966545a36586a60be4d694839f367b73dfc40b5f623fc4e246b39b9a3090694aa2e17e652d07fd1 -a905b82c4da8d866a894da72315a95dc98faa3c7b3d809aef18f3b2be4801e736a1b79a406179e8cac8f74d27e71ac52 -a8eb8679ff1a64908515f6720ff69434cb33d63aeb22d565fde506618908b1d37585e3bd4d044fd0838b55787af06b42 -af4d86b2fbd1684a657dffe4210321a71e6ae560c144d44668d1f324dc9630e98348c3d444622a689327c1a59cc169dd -80359c6eab16954559ab0e6a1fee9a0526c45d3cae1a371159a2e3aa9b893afdc3a785c9559a5fd9cd8cd774234bf819 -8d4e5ff81eb5d17bbe8ae6416538ca51a9427ce142b311f5cbb14febbbbb9c1ffc6489fd625b9266264c366c12a9d997 -92e181c66489c5fa063ba2a1a354b6fd3439b8b4365a8c90e42e169bfaa1fb5766bf3e0fe804399d18bc8fbcafb5c3b1 -a9ddf229360a095393885083716cb69c819b2d7cfb100e459c2e6beb999ff04446d1e4a0534832ae3b178cbe29f4f1d3 -8e085ef7d919302a1cc797857b75cff194bdbc1c5216434fa808c3dea0cf666f39d9b00f6d12b409693d7a9bd50a912c -916dc4dc89e5e6acf69e4485a09fc66968f9b292eac61a146df1b750aa3da2425a0743d492179f90a543a0d4cd72c980 -b9cbf17e32c43d7863150d4811b974882da338cf0ed1313765b431b89457021dd1e421eeaa52840ef00551bb630962dc -a6fb875786daec1a91484481787093d8d691dd07e15c9c0c6ae0404bf9dc26083ed15d03c6d3fe03e29f28e20da21269 -a870fcb54b9a029e8086de9b08da8782c64ad2cc2e7fdf955b913d294038bb8136193256b85267e75a4ca205808a76b4 -99883f057e09b88bf0e316f9814c091837fd5c26eeb16fec108c9fed4b7a2bd1c783dac0e4242b5a906621ab606c1e50 -85d89069ca3190577dab39bbec43c16bf6dbca439ad3eebd8f5e9f507d84c3c43e77fd6323224582566a3aa2c8018951 -9363ba219e0003f6e8a9d8937b9e1449e4b2c5cd57194563b758bea39deab88778e8f8e4f7816970a617fb077e1e1d42 -820622f25553c035326145c1d2d537dc9cfd064c2f5bdf6d4ec97814de5fe9a0fbd443345fa2ea0a9d40d81d3936aa56 -87e31110aaf447e70c3316459250e4f7f8c24420c97828f9eb33b22107542c5535bdb48b0e58682dd842edea2886ff08 -95bf80cac6f42029d843d1246588acb40a74802f9e94b2bf69b1833936767e701ef7b0e099e22ab9f20f8c0c4a794b6c -a46ecf612b2763d099b27fb814bd8fdbaee51d6b9ac277ad6f28350b843ce91d701371adfaaf4509400dc11628089b58 -8604decf299fb17e073969708be5befeb1090ab688ad9f3f97a0847a40ea9a11bbcfc7a91e8dc27bc67a155123f3bd02 -8eb765c8dc509061825f3688cb2d78b6fef90cf44db33783d256f09be284bc7282205279725b78882688a514247c4976 -b5c30b2244fa109d66b3a5270b178960fdec47d31e63db0b374b80d2b626409eb76d2e8d1ebf47ef96c166743032fc5e -aab01e76290a7e936989530221646160bf8f64e61e79282e980c8c5dcaaa805ff096efd01d075a2c75917a3f4bf15041 -b9d79671debd0b83d0c7c7c3e64c0fb1274300564b262771f839b49218501e7f38ef80cae1f7e5a3c34acdc74c89dab6 -92c0eaceadf036b3b9dfd2712013aba3dd7c30b7760f501f52141618265baa31840fe77850a7014dc528f71f8cf39ce6 -b3cdd098059980455dd5b1c04182df1bd12fa844a866f02a9f8a86aab95b59945baa9af99f687410bffc5b07153cb23c -b361b73a62f71256b7f6ea8e0f6615e14fc5a06ee98b928ab3c9dd3eef9d9d30070e9855c82b7facb639cacb3401e01f -b9c85fc0f25a3271cf28b1ca900078eaaa66cbab0a3e677606e898ac32781a2dfce4d9cbd07404599e2c3c02fa161c9d -ac5b4fdac2a0b2e6430d9fc72bde4249d72183b197fc7347bb1546ae6f544426686bbe0caec3ee973b6836da5e831c44 -b675aebf24b92e398e166f171a6df442b3f5919b6bee192f31675a5e8eeb77d34c6590a6f0c0857417e0f78cfb085db8 -a9bef942044d8d62e6a40169f7dc7b49e40cd0d77f8678dd7c7bae6f46c46786f9b1e319a3fa408f22a54fd2a4d70804 -a20d19cd917d5102ae9ca0cf532127d2b953aa3303310e8a8c4b3da025dded993a47e3a28e6b02acfadb6d65dc2d41a3 -a47fdb04059b83b2afb86a47b2368bbd7247c337a36d3333b6e5ef2cc9476a92c4907e4c58a845c9ef9b497621e0b714 -94a9e9ffc14b411e11a4ffa59878d59460263589003dc7b6915247c549f67feede279bf3645fdd92379022fb21e3caeb -b92e1177dd9ecdaf1370c71b14954219cf0851f309bc216d5907a4e2e84e0df3457018224150c142cc6bf86644bb4b73 -8bc57fadd68a265b7df9b42227a9c0968db7b1bb50dc12f7d755505779f1ff2c408672b3091e903366acc9ce15d19fb6 -b6b5efbe1ac4e1bd2e8447c45000d09397b772ca5496acc447b881022608a41c4f60388814607a01890190105bee7be3 -95f7c85fd614df968f8ccf8d086579c9e1cec4644ecf06da26e3511cb39635a7326b3cec47bd51cf5646f1c660425e9c -b81765fb319bcdc74b4d608383ccb4af7dd84413b23af637be12e2827a75f7e4bcd14441cf979ed9038ae366fbb6f022 -a120ea76cda8c6c50c97035078f6648afe6537809bdba26e7c9e61de8f3070d2347160f9d34010effbf2ec7e94f5749f -92c1b8631953b40d3cc77eee2c72a064b999c09a9b92c11d8fa7b4072966273901c9dba25f9f79f384d9f11a56f3fc7a -a4b00dc0ab67b2300abc9c516e34daf444d6497b066a90cfe3381ed2812304ed37b14f3b948990443dc6c1cf1bed460c -a9e9f7e13c9f031bc7b9e6f1417c7abcc38894fe7d3f54869ee277afd2efa3e6fb50757dd36c8c94d591e0abdea322cc -84f3e98f831792b5ad14bcfe62a4c9f296476c6087c4c1ec7767fc642fbca141ff6a3deeb8b4d4106a9cda5a9937eea0 -8eb1a7931bbea9a714226fd74b0100ab88355287d9b0a349c095e9b5809b98f237ffd706bce7d67a770da355fb9cec7b -9738ef8739e1742c1f26b51a1621be0b89d37406a370c531e236f635c7064c661818817bb3858908986aa687b28b21be -a9cf3ce8501b003ccaf57552a4c4ec31081e44526d3aa3791d3dc4a7e438a357c0956f93c500356186d8fd4588ffac5e -a7af6a219cca59225839a9de5b19263cb23d75557d448bc7d677b62591a2e068c45e5f4457cceb3e9efa01d0601fc18a -972a24ece5eda7692cbb6fb727f92740451bc1281835e2a02931b2b05824a16b01dbe5edd03a0ed5b441ff25a5cc0188 -b21d1ec7597ce95a42f759c9a8d79c8275d7e29047a22e08150f0f65014702f10b7edce8c03f6e7ab578ce8c3b0ec665 -a13a1c7df341bd689e1f8116b7afc149c1ef39161e778aa7903e3df2569356ad31834fa58ceb191485585ce5ef6835c3 -a57bdb08119dc3bc089b5b2b5383455c4de0c2fcdac2dcfa21c7ac5071a61635ff83eceb7412f53fab42d1a01991de32 -b2968748fa4a6921ee752d97aa225d289f599a7db7a222450e69706533573ded450380c87f8cdd4a8b8c8db1b42b5c97 -8718ec04e0d5f38e3034ecd2f13dfde840add500f43a5e13457a1c73db0d18138f938690c8c315b5bcbeb51e8b9a2781 -82094789e26c4a04f2f30bdb97b9aecca9b756cbd28d22ab3c8bed8afc5b2963340ddfc5a5f505e679bf058cbc5dcbb8 -a35b8a566dd6ab67eddc2467906bffc76c345d508e52e9e4bb407b4f2b2c5f39b31d5a4bf5022f87bf7181dc6be2fe41 -a8c93b1e893d4777c0e3a1b4bef3be90c215781501407c4011457fc3240e13524b4d2bea64a6d0a3efe3f3b0dae9b8ab -877095ad18b1e5870818f7a606127ba1736a0b55b0dbcd281ec307c84b08afc0c9117e3a880fe48bfc225fbf37671a97 -84405ee0421ed2db1add3593df8426a9c1fcc8063e875f5311a917febc193748678dd63171d0c21665fb68b6d786c378 -a52cdc8209c3c310bed15a5db260c4f4d4857f19c10e4c4a4cfe9dfc324dfac851421bb801509cf8147f65068d21603c -8f8a028a70dda7285b664722387666274db92230b09b0672f1ead0d778cee79aae60688c3dfd3a8ed1efdeda5784c9d4 -a0be42fecc86f245a45a8ed132d6efc4a0c4e404e1880d14601f5dce3f1c087d8480bad850d18b61629cf0d7b98e0ae0 -83d157445fc45cb963b063f11085746e93ab40ece64648d3d05e33e686770c035022c14fdf3024b32b321abf498689ad -8a72bbf5a732e2d4f02e05f311027c509f228aef3561fc5edac3ef4f93313845d3a9f43c69f42e36f508efcc64a20be0 -b9ca29b0ec8e41c6a02f54d8c16aebf377982488cbe2ed1753090f2db4f804f6269af03e015d647a82ef06ffaa8cba6c -b4df3858d61bbb5ded1cf0be22a79df65ae956e961fbb56c883e1881c4c21fe642e3f5a0c108a882e553ac59595e3241 -86457d8890ac8858d7bab180ef66851247c2bf5e52bf69a4051d1d015252c389684fcc30bb4b664d42fbf670574ab3a3 -86d5576ea6dfa06d9ebce4cd885450f270c88a283e1e0d29cab27851c14ed2f00355e167b52e1539f1218ad11d8f13dd -883ad1364dc2a92388bfafaa9bc943c55b2f813525831e817a6208c666829a40455dde494eba054b2495a95f7ce69e8a -8942371e6925231c2c603b5f5a882d8404d39f0c7c4232557c2610b21c2c07f145466da798ea78b7932da2b774aa3128 -a799eb71496783cc7faf12c9d9804bf6180699a004b2f07fc5cc36840f63ce7eee7dde9275819a9aa3f8d92dc0d47557 -8eb3fb5c769548ee38c7882f51b959c5d5a42b5935269ccf987d6ddbb25a206e80c6000bcc328af149e0727c0b7c02c0 -8f3910d64e421a8f2d8db4c7b352ba5b3fc519d5663973fea5962efe4364fb74448770df944ef37ffe0382648fb56946 -b41413e0c26ff124cf334dab0dc8e538293d8d519d11cc2d10895a96b2064ac60c7da39f08589b38726cffa4c3f0bfef -b46ef2eb10abae0f35fa4c9c7ee2665e8044b8d9f91988a241da40fd5bbc63166925582151941b400006e28bbc5ba22a -b8baa8b4c420bb572a3b6b85479b67d994c49a7ebfe1274687d946a0d0b36dfed7630cfb897350fa166f5e2eff8f9809 -964b46d359c687e0dcfbdab0c2797fc2bd1042af79b7418795b43d32ffca4de89358cee97b9b30401392ff54c7834f9f -8410d0203d382ebf07f200fd02c89b80676957b31d561b76563e4412bebce42ca7cafe795039f46baf5e701171360a85 -b1a8d5d473c1a912ed88ea5cfa37c2aea5c459967546d8f2f5177e04e0813b8d875b525a79c29cb3009c20e7e7292626 -afaab9a1637429251d075e0ba883380043eaf668e001f16d36737028fded6faa6eeed6b5bb340f710961cee1f8801c41 -aef17650003b5185d28d1e2306b2f304279da50925f2704a6a3a68312f29fe5c2f2939f14e08b0ba9dee06ea950ad001 -97bcc442f370804aa4c48c2f8318d6f3452da8389af9335e187482d2e2b83b9382e5c297dce1a0f02935e227b74e09a3 -8a67a27b199f0bcd02d52a3e32f9b76a486b830ec481a49a4e11807e98408b7052b48581b5dd9f0b3e93052ec45dfb68 -b113bf15f430923c9805a5df2709082ab92dcdf686431bbad8c5888ca71cc749290fa4d4388a955c6d6ee3a3b9bc3c53 -8629ca24440740ce86c212afed406026f4ea077e7aa369c4151b6fa57bca7f33f9d026900e5e6e681ae669fd2bd6c186 -933a528371dcecc1ec6ded66b1c7b516bd691b3b8f127c13f948bfbcda3f2c774c7e4a8fbee72139c152064232103bdf -8568ddd01f81a4df34e5fa69c7f4bb8c3c04274147498156aec2e3bd98ea3e57c8a23503925de8fa3de4184563a2b79e -8160874ec030f30fda8f55bcf62613994ff7ed831e4901c7560eac647182b4a9b43bfaff74b916602b9d6ae3bfcaf929 -ae71c48d48cf9459800cdf9f8e96bc22e2d4e37259e5c92a2b24fbe2c6ca42675e312288603c81762f6ceb15400bc4c9 -b05f39bb83fda73e0559db1fd4a71423938a87ad9f060d616d4f4a6c64bf99472a2cbfb95f88b9257c9630fc21a0b81f -80c8479a640ed7a39e67f2db5ad8dfd28979f5443e8e6c23da8087fc24134d4b9e7c94320ffa4154163270f621188c27 -9969ba20ee29c64cb3285a3433a7e56a0fe4ddc6f3d93e147f49fe021bed4a9315266ebb2fb0eb3036bb02001ae015e6 -a198c89fef2ab88e498703b9021becc940a80e32eb897563d65db57cc714eaa0e79092b09dd3a84cfab199250186edcc -8df14a3db8fe558a54d6120bad87405ba9415a92b08c498812c20416c291b09fed33d1e2fcf698eb14471f451e396089 -81e245ef2649b8a5c8d4b27188dd7e985ef6639090bdc03462c081396cf7fc86ed7d01bfe7e649d2b399255e842bdc21 -8659f622c7ab7b40061bcf7a10144b51ad3ab5348567195924f2944e8c4ce137a37f1ba328e4716c10806f3fb7271689 -a575d610fc8fe09334ca619ecdadf02d468ca71dd158a5a913252ca55ea8d8f9ce4548937c239b9cb8ab752a4d5af24a -94744549cd9f29d99f4c8c663997bdfa90e975b31f1086214245de9c87b0c32209f515a0de64d72d5ef49c09b0a031fa -80a8677862b056df59e350c967a27436c671b65d58854e100115bac9824ba177e94c2a1bfcaa191a071b9cefdbee3989 -91be9a5504ec99922440f92a43fe97ddce2f21b9d94cd3a94c085a89b70c903696cec203bbab6d0a70693ba4e558fb01 -8c5a0087bcd370734d12d9b3ab7bc19e9a336d4b49fc42825b2bfedcd73bb85eb47bf8bb8552b9097cc0790e8134d08c -933aa9e6bd86df5d043e0577a48e17eea3352e23befdbb7d7dcac33b5703d5ace230443ac0a40e23bf95da4cc2313478 -984b7ee4bd081ee06c484db6114c2ce0ba356988efb90f4c46ff85ed2865fb37f56a730166c29ef0ae3345a39cdeae7a -ae830f908ea60276c6c949fb8813e2386cf8d1df26dcf8206aa8c849e4467243e074471380ed433465dc8925c138ea4c -874c1df98d45b510b4f22feff46a7e8ed22cfc3fad2ac4094b53b9e6477c8dfc604976ca3cee16c07906dece471aa6c6 -a603eb60d4c0fb90fa000d2913689126849c0261e6a8649218270e22a994902965a4e7f8c9462447259495fe17296093 -a7c73d759a8ad5e3a64c6d050740d444e8d6b6c9ade6fb31cb660fa93dc4a79091230baccb51c888da05c28cb26f6f3f -a4411b79b6a85c79ea173bd9c23d49d19e736475f3d7d53213c5349ebb94a266d510d12ba52b2ac7a62deaaaec7339b8 -943b84f8bbcee53b06266b5c4cd24d649d972593837fe82b0bf5d5e1bbc1a2bf148e1426c366d7c39ab566b10224cadc -8300012096a8b4cefecc080054bf3ceb0918162ba263c6848860423407796b5eb517170c0bad8e4905ac69a383055a21 -8244a1e3ad41908c6f037e2f8db052e81f281646141334829f36c707f307448b9ab79a7f382a1e8d86f877c90b59271c -8eca1b74687802ecc36a5d39e4516a9dee3de61a2047252d9ed737b49e0090c386e9d792ac004c96337681c7f29a16ad -b70fa47535f0524835039a20036c61e77f66146ad79d3d339214d8744742db41ceeb577c829d000011aeafbb12e09579 -84b3abbce48689f3adbb99889c7fd1f3e15ab455d477e34f5151c5c1c358ed77a5b6a581879f7e0f1f34106e0792e547 -ab45ecb58c0ef0dbce3d16afc6ac281e0d90ec48741ea96a141152647e98fcc87f3a3ff07ba81f3179118453ce123156 -90d231a145ba36a59087e259bbfc019fa369201fcfeaa4347d5fd0a22cd8a716e5a797f3cc357f2779edb08f3b666169 -a4f6074d23c6c97e00130bc05f25213ca4fa76c69ca1ace9dece904a2bdd9d987661f5d55023b50028c444af47ff7a08 -933af884939ad0241f3f1f8e8be65f91d77ac0fb234e1134d92713b7cfb927f1933f164aec39177daa13b39c1370fac8 -80d1db6933ce72091332ae47dc691acb2a9038f1239327b26d08ea9d40aa8f2e44410bbda64f2842a398cbe8f74f770f -a7a08605be2241ccc00151b00b3196d9c0717c4150909a2e9cd05538781231762b6cc6994bebbd4cddae7164d048e7b2 -96db0d839765a8fdbbac03430fa800519e11e06c9b402039e9ae8b6503840c7ecac44123df37e3d220ac03e77612f4e4 -96d70f8e9acd5a3151a8a9100ad94f16c289a31d61df681c23b17f21749c9062622d0a90f6d12c52397b609c6e997f76 -8cf8e22273f7459396ff674749ab7e24c94fe8ab36d45d8235e83be98d556f2b8668ba3a4ec1cb98fac3c0925335c295 -97b7e796a822262abc1a1f5a54cb72a1ea12c6c5824ac34cd1310be02d858a3c3aa56a80f340439b60d100e59c25097d -a48208328b08769737aa1a30482563a4a052aea736539eceab148fa6653a80cb6a80542e8b453f1f92a33d0480c20961 -b612184941413fd6c85ff6aa517b58303b9938958aa85a85911e53ed308778624d77eadb27ccf970573e25d3dfd83df7 -b3717068011648c7d03bbd1e2fc9521a86d2c3ae69113d732c2468880a3b932ebec93596957026477b02842ed71a331b -a0ad363e1352dcf035b03830fef4e27d5fd6481d29d5e8c9d51e851e3862d63cdcbaf8e330d61c1b90886921dac2c6fd -8db409fdacfa4bfdaf01cc87c8e97b53ca3a6e3a526d794eaad1c2023f3df4b888f1bf19fee9a990fe6d5c7c3063f30c -b34d6975310ab15938b75ef15020a165fc849949065d32d912554b51ffa1d3f428a6d1a396cb9329367670391de33842 -9117285e9e6762853fc074b8a92b3923864de2c88c13cea7bab574aaf8cdd324843455d2c3f83c00f91f27c7ecc5592a -b4b2e8f190ea0b60819894710c866bf8578dd1b231ae701d430797cc7ede6e216e8ca6a304f3af9484061563645bf2ab -8c493c6853ab135d96a464815dd06cad8b3e8b163849cdefc23d1f20211685753b3d3e147be43e61e92e35d35a0a0697 -9864d7880f778c42d33cf102c425e380d999d55a975a29c2774cad920dfddb80087a446c4f32ed9a6ab5f22ec6f82af0 -90f67fe26f11ca13e0c72b2c2798c0d0569ed6bc4ce5bbaf517c096e7296d5dd5685a25012f6c6d579af5b4f5d400b37 -a228872348966f26e28a962af32e8fa7388d04bc07cfc0224a12be10757ac7ab16a3387c0b8318fcb0c67384b0e8c1a4 -a9d9d64bba3c03b51acf70aeb746a2712ddafe3b3667ae3c25622df377c2b5504e7ab598263bec835ab972283c9a168b -932128971c9d333f32939a1b46c4f7cf7e9d8417bd08dc5bd4573ccbd6ec5b460ac8880fb7f142f7ef8a40eef76d0c6d -964115e7838f2f197d6f09c06fbb2301d6e27c0ecdf208350cf3b36c748436dac50f47f9f9ac651c09ab7ad7221c7e43 -a5941f619e5f55a9cf6e7f1499b1f1bcddcc7cf5e274efedaaad73a75bc71b1fc5c29cd903f6c69dc9a366a6933ca9d1 -a154bf5eaec096029e5fe7c8bf6c695ae51ace356bb1ad234747776c7e1b406dee2d58864c3f4af84ed69f310974125e -b504e6209d48b0338ab1e4bdab663bac343bb6e0433466b70e49dc4464c1ec05f4a98111fd4450393607510ae467c915 -813411918ea79bdde295393284dc378b9bdc6cfcb34678b9733ea8c041ac9a32c1e7906e814887469f2c1e39287e80f8 -8be0369f94e4d72c561e6edb891755368660208853988647c55a8eed60275f2dd6ee27db976de6ecf54ac5c66aaf0ae6 -a7e2701e55b1e7ea9294994c8ad1c080db06a6fc8710cd0c9f804195dce2a97661c566089c80652f27b39018f774f85e -956b537703133b6ddf620d873eac67af058805a8cc4beb70f9c16c6787bf3cc9765e430d57a84a4c3c9fbdd11a007257 -835ae5b3bb3ee5e52e048626e3ddaa49e28a65cb94b7ecdc2e272ff603b7058f1f90b4c75b4b9558f23851f1a5547a35 -85d67c371d1bf6dc72cca7887fa7c886ce988b5d77dc176d767be3205e80f6af2204d6530f7060b1f65d360a0eaeff30 -a84a6647a10fcef8353769ef5f55a701c53870054691a6e9d7e748cbe417b3b41dbb881bae67adc12cb6596c0d8be376 -87ffe271fc0964cb225551c7a61008d8bcb8b3d3942970dbcc2b9f4f9045a767971880368ea254e2038a3a0b94ecf236 -964bb721c51d43ee7dd67c1a2b7dd2cc672ce8fad78c22dcddb43e6aab48d9a4a7dc595d702aa54a6fb0ffabf01f2780 -a89b3f84bb7dcbe3741749776f5b78a269f6b1bebb8e95d3cc80b834fd2177c6be058d16cacfd0d5e1e35e85cde8b811 -b4314538e003a1587b5592ff07355ea03239f17e75c49d51f32babe8e048b90b046a73357bcb9ce382d3e8fbe2f8e68b -86daf4bf201ae5537b5d4f4d734ed2934b9cf74de30513e3280402078f1787871b6973aa60f75858bdf696f19935a0e2 -b1adf5d4f83f089dc4f5dae9dbd215322fa98c964e2eaa409bf8ca3fa5c627880a014ed209492c3894b3df1c117236c4 -b508d52382c5bac5749bc8c89f70c650bb2ed3ef9dc99619468c387c1b6c9ff530a906dfa393f78f34c4f2f31478508a -a8349a5865cb1f191bebb845dfbc25c747681d769dbffd40d8cedf9c9a62fa2cbc14b64bb6121120dab4e24bef8e6b37 -af0500d4af99c83db8890a25f0be1de267a382ec5e9835e2f3503e1bac9412acf9ff83a7b9385708ef8187a38a37bc77 -b76d57a1c1f85b8a8e1722a47057b4c572800957a6b48882d1fc21309c2e45f648a8db0fcff760d1dbc7732cf37c009b -b93c996cec0d3714667b5a5a5f7c05a7dc00bbc9f95ac8e310626b9e41ae4cc5707fac3e5bd86e1e1f2f6d9627b0da94 -93216fdb864217b4c761090a0921cf8d42649ab7c4da1e009ec5450432564cb5a06cb6e8678579202d3985bd9e941cef -8b8be41105186a339987ae3a5f075fbc91f34b9984d222dfed0f0f85d2f684b56a56ab5dc812a411570491743d6c8b18 -959b72782a6b2469e77fe4d492674cc51db148119b0671bd5d1765715f49fa8a87e907646671161586e84979ef16d631 -86b7fc72fb7e7904ea71d5e66ba0d5d898ace7850985c8cc4a1c4902c5bf94351d23ce62eed45e24321fb02adfa49fc8 -a2f244e7c9aa272cb0d067d81d25e5a3045b80b5a520b49fd5996ece267a7f1bea42e53147bbf153d9af215ea605fc9e -81aa2efa5520eebc894ce909ba5ce3250f2d96baa5f4f186a0637a1eea0080dd3a96c2f9fadf92262c1c5566ddb79bab -b607dd110cfe510d087bcff9a18480ba2912662256d0ab7b1d8120b22db4ad036b2266f46152754664c4e08d0fc583f6 -8f588d5f4837e41312744caac5eee9ddc3ad7085871041694f0b5813edf83dc13af7970f7c9b6d234a886e07fa676a04 -924921b903207783b31016cbec4e6c99e70f5244e775755c90d03a8b769738be3ba61577aca70f706a9c2b80040c9485 -ae0a42a222f1a71cd0d3c69ffb2f04c13e1940cce8efabe032629f650be3ceed6abb79651dbb81cb39a33286eb517639 -a07d7d76460f31f5f0e32e40a5ea908d9d2aebf111ac4fadee67ef6540b916733c35a777dcdc05f6417726ca1f2d57dd -88d7f8a31f8c99794291847d28745e5d0b5d3b9684ca4170b686ffbb5bb521a3ef6746c3c8db22e4250a0cdff7939d96 -849573071fd98c020dc9a8622a9eff221cb9f889bde259e7127a8886b73bef7ad430b87750915658918dcfb6b7b4d8d3 -b12d59f732fa47fad175d6263734da8db89230fd340a46ad1cdee51e577041a5c80bf24cd195593e637daf1a66ef5a98 -abbcfb8a4a6d5e269ee1ac5e277df84416c73ca55ec88317f73608201af25af0cb65b943c54684a5651df3a26e3daca2 -ab157f589bdbaf067a6a7ba7513df0492933855d39f3a081196cf2352e0ddc0162d476c433320366e3df601e0556278d -a86c0619b92e5ae4f7daa876a2abc5ba189156afc2fa05eef464dfa342ba37fc670d0dc308ad3822fcb461ab001bac30 -a3f292946476cfe8d5e544a5325439a00e0165a5f9bf3bb6a53f477baeac7697cc0377745536681aa116f326ce911390 -8aecbbfd442a6a0f01c1c09db5d9d50213eb6f1ff6fab674cde3da06a4edff3ed317e804f78300c22ef70c336123e05d -834ed4b58211fcd647d7bf7c0a3ba9085184c5c856b085e8a0fcd5215c661ef43d36f3f0f6329a9f1370501b4e73b6e4 -a114ea5ad2b402a0de6105e5730907f2f1e458d28ae35144cf49836e0ad21325fe3e755cfb67984ae0a32e65402aad1e -a005f12bed97d71cee288b59afe9affb4d256888727343944a99913980df2c963fe02f218e6ea992f88db693a4498066 -a010f286ab06b966e3b91ff8f1bdbe2fe9ab41a27bc392d5787aa02a46e5080e58c62c7d907818caae9f6a8b8123e381 -857bd6df2ddef04dbc7c4f923e0b1696d3016c8bfed07fdfa28a3a3bd62d89b0f9df49aae81cbb6883d5e7b4fadae280 -b3927030da445bc4756ac7230a5d87412a4f7510581fb422212ce2e8cf49689aca7ba71678743af06d4de4914c5aa4a0 -b86403182c98fcce558d995f86752af316b3b2d53ba32075f71c7da2596747b7284c34a1a87de604fcc71e7e117a8add -98dd19b5527733041689b2a4568edaf6aa0fe1a3dd800c290cda157b171e053648a5772c5d3d4c80e5a795bc49adf12e -88a3c227bb7c9bff383f9ad3f7762245939a718ab85ae6e5e13180b12bf724d42054d3852b421c1cd1b3670baddecb63 -b3cfd9ad66b52bbe57b5fff0fad723434d23761409b92c4893124a574acc1e6b1e14b4ec507661551cbbe05e16db362e -923e1bb482cf421dd77801f9780f49c3672b88508a389b94015fd907888dc647ee9ea8ec8d97131d235d066daf1f42b7 -8d5e16240f04f92aa948181d421006bdbc7b215648fb6554193224d00cf337ebbb958f7548cf01b4d828acffb9fbc452 -8b2b8f18ad0559746f6cda3acca294a1467fb1a3bc6b6371bc3a61a3bfe59418934fa8706f78b56005d85d9cb7f90454 -a9316e2a94d6e31426d2ae7312878ba6baaac40f43e2b8a2fa3ab5a774c6918551554b2dbb23dc82f70ba3e0f60b5b0d -9593116d92cf06b8cd6905a2ce569ee6e69a506c897911f43ae80fc66c4914da209fc9347962034eebbc6e3e0fe59517 -887d89d2b2d3c82b30e8f0acf15f0335532bd598b1861755498610cb2dd41ff5376b2a0bb757cb477add0ce8cfe7a9fc -b514cfe17875ecb790ad055271cc240ea4bda39b6cfa6a212908849c0875cb10c3a07826550b24c4b94ea68c6bb9e614 -a563d5187966d1257d2ed71d53c945308f709bcc98e3b13a2a07a1933dc17bcb34b30796bd68c156d91811fbd49da2cb -a7195ccc53b58e65d1088868aeeb9ee208103e8197ad4c317235bb2d0ad3dc56cb7d9a7186416e0b23c226078095d44c -a838e7a368e75b73b5c50fbfedde3481d82c977c3d5a95892ac1b1a3ea6234b3344ad9d9544b5a532ccdef166e861011 -9468ed6942e6b117d76d12d3a36138f5e5fb46e3b87cf6bb830c9b67d73e8176a1511780f55570f52d8cdb51dcf38e8c -8d2fc1899bc3483a77298de0e033085b195caf0e91c8be209fd4f27b60029cbe1f9a801fbd0458b4a686609762108560 -8f4e44f8ca752a56aa96f3602e9234ad905ad9582111daf96a8c4d6f203bf3948f7ce467c555360ad58376ee8effd2ba -8fb88640b656e8f1c7c966c729eb2ba5ccf780c49873f8b873c6971840db7d986bdf1332ba80f8a0bb4b4ee7401468fa -b72aa3235868186913fb5f1d324e748cd3ce1a17d3d6e6ea7639a5076430fe0b08841c95feb19bb94181fe59c483a9eb -b8b102690ebb94fc4148742e7e3fd00f807b745b02cbe92cd92992c9143b6db7bb23a70da64a8b2233e4a6e572fc2054 -8c9ae291f6cd744e2c6afe0719a7fc3e18d79307f781921fb848a0bf222e233879c1eca8236b4b1be217f9440859b6ce -a658ede47e14b3aad789e07f5374402f60e9cacb56b1b57a7c6044ca2418b82c98874e5c8c461898ebd69e38fecd5770 -89c0cb423580e333923eb66bda690f5aca6ec6cba2f92850e54afd882ba608465a7dbb5aa077cd0ca65d9d00909348ab -aed8e28d98d5508bd3818804cf20d296fe050b023db2ed32306f19a7a3f51c7aaafed9d0847a3d2cd5ba5b4dabbc5401 -96a0fcd6235f87568d24fb57269a94402c23d4aa5602572ad361f3f915a5f01be4e6945d576d51be0d37c24b8b0f3d72 -935d0c69edd5dfa8ed07c49661b3e725b50588f814eb38ea31bcc1d36b262fae40d038a90feff42329930f8310348a50 -900518288aa8ea824c7042f76710f2ea358c8bb7657f518a6e13de9123be891fa847c61569035df64605a459dad2ecc8 -947d743a570e84831b4fb5e786024bd752630429d0673bf12028eb4642beb452e133214aff1cfa578a8856c5ebcb1758 -a787266f34d48c13a01b44e02f34a0369c36f7ec0aae3ec92d27a5f4a15b3f7be9b30b8d9dd1217d4eeedff5fd71b2e5 -a24b797214707ccc9e7a7153e94521900c01a1acd7359d4c74b343bfa11ea2cdf96f149802f4669312cd58d5ab159c93 -97f5ee9c743b6845f15c7f0951221468b40e1edaef06328653a0882793f91e8146c26ac76dd613038c5fdcf5448e2948 -80abd843693aed1949b4ea93e0188e281334163a1de150c080e56ca1f655c53eb4e5d65a67bc3fc546ed4445a3c71d00 -908e499eb3d44836808dacff2f6815f883aeced9460913cf8f2fbbb8fe8f5428c6fc9875f60b9996445a032fd514c70f -ae1828ef674730066dc83da8d4dd5fa76fc6eb6fa2f9d91e3a6d03a9e61d7c3a74619f4483fe14cddf31941e5f65420a -a9f4dbe658cd213d77642e4d11385a8f432245b098fccd23587d7b168dbeebe1cca4f37ee8d1725adb0d60af85f8c12f -93e20ee8a314b7772b2439be9d15d0bf30cd612719b64aa2b4c3db48e6df46cea0a22db08ca65a36299a48d547e826a7 -a8746a3e24b08dffa57ae78e53825a9ddbbe12af6e675269d48bff4720babdc24f907fde5f1880a6b31c5d5a51fbb00e -b5e94dfab3c2f5d3aea74a098546aa6a465aa1e3f5989377d0759d1899babf543ad688bb84811d3e891c8713c45886c5 -a3929bada828bd0a72cda8417b0d057ecb2ddd8454086de235540a756e8032f2f47f52001eb1d7b1355339a128f0a53b -b684231711a1612866af1f0b7a9a185a3f8a9dac8bde75c101f3a1022947ceddc472beb95db9d9d42d9f6ccef315edbc -af7809309edbb8eb61ef9e4b62f02a474c04c7c1ffa89543d8c6bf2e4c3d3e5ecbd39ec2fc1a4943a3949b8a09d315a6 -b6f6e224247d9528ef0da4ad9700bee6e040bbf63e4d4c4b5989d0b29a0c17f7b003c60f74332fefa3c8ddbd83cd95c1 -adbcec190a6ac2ddd7c59c6933e5b4e8507ce5fd4e230effc0bd0892fc00e6ac1369a2115f3398dfc074987b3b005c77 -8a735b1bd7f2246d3fa1b729aecf2b1df8e8c3f86220a3a265c23444bdf540d9d6fe9b18ed8e6211fad2e1f25d23dd57 -96b1bf31f46766738c0c687af3893d098d4b798237524cb2c867ed3671775651d5852da6803d0ea7356a6546aa9b33f2 -8036e4c2b4576c9dcf98b810b5739051de4b5dde1e3e734a8e84ab52bc043e2e246a7f6046b07a9a95d8523ec5f7b851 -8a4f4c32ee2203618af3bb603bf10245be0f57f1cfec71037d327fa11c1283b833819cb83b6b522252c39de3ce599fa5 -ad06ed0742c9838e3abaaffdb0ac0a64bad85b058b5be150e4d97d0346ed64fd6e761018d51d4498599669e25a6e3148 -8d91cb427db262b6f912c693db3d0939b5df16bf7d2ab6a7e1bc47f5384371747db89c161b78ff9587259fdb3a49ad91 -ae0a3f84b5acb54729bcd7ef0fbfdcf9ed52da595636777897268d66db3de3f16a9cf237c9f8f6028412d37f73f2dfad -8f774109272dc387de0ca26f434e26bc5584754e71413e35fa4d517ee0f6e845b83d4f503f777fe31c9ec05796b3b4bc -a8670e0db2c537ad387cf8d75c6e42724fae0f16eca8b34018a59a6d539d3c0581e1066053a2ec8a5280ffabad2ca51f -ac4929ed4ecad8124f2a2a482ec72e0ef86d6a4c64ac330dab25d61d1a71e1ee1009d196586ce46293355146086cabba -845d222cb018207976cc2975a9aa3543e46c861486136d57952494eb18029a1ebb0d08b6d7c67c0f37ee82a5c754f26f -b99fa4a29090eac44299f0e4b5a1582eb89b26ed2d4988b36338b9f073851d024b4201cd39a2b176d324f12903c38bee -9138823bc45640b8f77a6464c171af2fe1700bdc2b7b88f4d66b1370b3eafe12f5fbb7b528a7e1d55d9a70ca2f9fc8e6 -8ac387dc4cf52bc48a240f2965ab2531ae3b518d4d1f99c0f520a3d6eb3d5123a35ef96bed8fa71ee2f46793fa5b33b3 -864adec6339d4c2ba2525621fceabd4c455902f6f690f31a26e55413e0722e5711c509dc47ce0bcc27bbdc7651768d2d -a0a52edb72268a15201a968dabc26a22909620bda824bd548fb8c26cc848f704166ed730d958f0173bd3b0a672f367bd -949e445b0459983abd399571a1a7150aab3dd79f4b52a1cd5d733e436c71c1d4b74287c6b0ce6cc90c6711ba4c541586 -858966355dac11369e3b6552f2b381665181693d5a32e596984da3314021710b25a37d8c548b08700eea13d86cb22f21 -974bcbb8d38c5e6518745cc03ad436e585b61f31d705e7e2e5085da9655d768ac4d800904f892c3dab65d6223e3f1fd6 -8092b6506b01308bf6187fde5ebd4fa7448c9a640961ba231be22ac5fa2c7635ef01e8b357722c7695d09b723101ea2a -a5b8ef360bf28533ee17d8cd131fff661d265f609db49599085c0c7d83b0af409a1b5c28e3a5e5d7f8459a368aa121e8 -b031b6d5e3ceab0f0c93314b3b675f55cf18cbc86f70444af266fe39cb22fd7dad75d8c84e07f1c1bfa2cb8283e1361a -93ad489e4f74658320c1cceed0137c023d3001a2c930ed87e6a21dbf02f2eb6ad1c1d8bcb3739c85dcfbecb040928707 -b15e4ec2cdab0d34aec8d6c50338812eb6ecd588cf123a3e9d22a7ca23b5a98662af18289f09e6cdd85a39a2863c945c -b304f71a9717cf40c22073f942618b44bf27cd5e2ed4a386ad45d75b0fcb5a8dafd35158211eaf639495c6f1a651cedb -b82d78d3eaaa7c5101b7a5aae02bd4f002cd5802d18c3abcda0dd53b036661c6d3c8b79e0abe591eab90b6fdc5fef5e3 -abbd1884243a35578b80914a5084449c237ee4e4660c279d1073a4d4217d1b55c6b7e9c087dfd08d94ac1416273d8d07 -92f4b61c62502745e3e198ec29bca2e18696c69dcb914d1f3a73f4998d012b90caf99df46e9bb59942e43cce377fe8fd -906e79df98185820c8208844e1ba6bd86cb96965814b01310bd62f22cbec9b5d379b2ef16772d6fc45a421b60cfd68fe -a0eae2784ef596e2eb270dd40c48d6c508e4394c7d6d08d4cc1b56fde42b604d10ba752b3a80f2c4a737e080ef51b44f -94c084985e276dc249b09029e49a4ef8a369cd1737b51c1772fbb458d61e3fe120d0f517976eba8ffa5711ba93e46976 -83619a0157eff3f480ab91d1d6225fead74c96a6fd685333f1e8e4d746f6273e226bad14232f1d1168a274e889f202f1 -a724fe6a83d05dbbf9bb3f626e96db2c10d6d5c650c0a909415fbda9b5711c8b26e377201fb9ce82e94fa2ab0bf99351 -a8a10c1b91a3a1fa2d7fd1f78a141191987270b13004600601d0f1f357042891010717319489f681aa8a1da79f7f00d5 -a398a2e95b944940b1f8a8e5d697c50e7aa03994a8a640dfad4ea65cfb199a4d97861a3ec62d1c7b2b8d6e26488ca909 -a2eedfe5452513b2a938fffd560798ef81379c5a5032d5b0da7b3bb812addbaad51f564c15d9acbbfc59bb7eddd0b798 -ab31c572f6f145a53e13b962f11320a1f4d411739c86c88989f8f21ab629639905b3eedb0628067942b0dc1814b678ca -ad032736dd0e25652d3566f6763b48b34ea1507922ed162890cd050b1125ec03b6d41d34fccba36ec90336f7cdf788ed -83028a558a5847293147c483b74173eca28578186137df220df747fccd7d769528d7277336ea03c5d9cdd0bc5ae3d666 -ab5d182cd1181de8e14d3ef615580217c165e470b7a094a276b78a3003089123db75c6e1650bf57d23e587c587cd7472 -a4793e089fbdb1597654f43b4f7e02d843d4ab99ee54099c3d9f0bd5c0c5657c90bb076379a055b00c01b12843415251 -98bdc52ee062035356fb2b5c3b41673198ddc60b2d1e546cb44e3bb36094ef3c9cf2e12bbc890feb7d9b15925439d1ea -a4f90cca6f48024a0341bd231797b03693b34e23d3e5b712eb24aba37a27827319b2c16188f97c0636a0c115381dc659 -8888e6c2e4a574d04ba5f4264e77abc24ccc195f1a7e3194169b8a2ceded493740c52db4f9833b3dbf4d67a3c5b252cb -83dc4e302b8b0a76dc0292366520b7d246d73c6aebe1bdd16a02f645c082197bcff24a4369deda60336172cefbcf09af -a4eb2741699febfeb793914da3054337cc05c6fa00d740e5f97cb749ae16802c6256c9d4f0f7297dcdbb8b9f22fc0afa -8b65557d5be273d1cb992a25cfce40d460c3f288d5cb0a54bdef25cbd17cdea5c32ec966e493addf5a74fd8e95b23e63 -97c6577e76c73837bcb398b947cb4d3323d511141e0ddd0b456f59fbb1e8f920a5c20d7827a24309145efddee786140f -abcc0849ffe2a6a72157de907907b0a52deece04cf8317bee6fe1d999444b96e461eac95b6afde3d4fe530344086a625 -9385c0115cb826a49df1917556efa47b5b5e4022b6a0d2082053d498ec9681da904ecf375368bb4e385833116ea61414 -8b868c1841f0cdc175c90a81e610b0652c181db06731f5c8e72f8fafa0191620742e61a00db8215a991d60567b6a81ca -a8df15406f31b8fcf81f8ff98c01f3df73bf9ec84544ddec396bdf7fafa6fe084b3237bf7ef08ad43b26517de8c3cd26 -a9943d21e35464ce54d4cc8b135731265a5d82f9ccf66133effa460ffdb443cdb694a25320506923eede88d972241bf2 -a1378ee107dd7a3abcf269fd828887c288363e9b9ca2711377f2e96d2ed5e7c5ec8d3f1da995a3dcbedf1752d9c088fc -8a230856f9227b834c75bdebc1a57c7298a8351874bf39805c3e0255d6fd0e846f7ad49709b65ec1fd1a309331a83935 -877bcf42549d42610e1780e721f5800972b51ba3b45c95c12b34cb35eeaf7eac8fa752edd7b342411820cf9093fea003 -84c7a0b63842e50905624f1d2662506b16d1f3ea201877dfc76c79181c338b498eceb7cad24c2142c08919120e62f915 -8e18b1bd04b1d65f6ed349b5d33a26fe349219043ead0e350b50ae7a65d6ff5f985dd9d318d3b807d29faa1a7de4fe42 -8ea7b5a7503e1f0b3c3cd01f8e50207044b0a9c50ed1697794048bbe8efd6659e65134d172fb22f95439e1644f662e23 -b1954a2818cad1dad6d343a7b23afa9aa8ad4463edc4eb51e26e087c2010927535020d045d97d44086d76acdb5818cbf -a5271ea85d0d21fa1ff59b027cf88847c0f999bbf578599083ff789a9b5228bc161e1c81deb97e74db1a82a0afd61c50 -aa2fa4c05af3387e2c799315781d1910f69977ec1cfea57a25f1a37c63c4daaa3f0ecd400884a1673e17dd5300853bcf -b1cd2a74ca0b8e6090da29787aef9b037b03b96607983a308b790133bd21297b21ca4e2edec890874096dbf54e9d04c3 -801931607ec66a81272feaa984f0b949ad12d75ecf324ba96627bd4dc5ddead8ebf088f78e836b6587c2b6c0b3366b6c -95d79504710bdf0ad9b9c3da79068c30665818c2f0cdbba02cc0a5e46e29d596032ac984441b429bd62e34535c8d55b0 -9857d41e25e67876510ff8dadf0162019590f902da1897da0ef6fc8556e3c98961edb1eb3a3a5c000f6c494413ded15e -8740c9ffe6bd179c19a400137c3bd3a593b85bd4c264e26b4dfb9e2e17ac73e5b52dfacc1dcb4033cfc0cd04785f4363 -977f98f29d948b4097a4abdf9345f4c1fb0aa94ba0c6bf6faa13b76f3a3efc8f688e1fe96099b71b3e1c05041118c8d1 -a364422b1239126e3e8d7b84953ce2181f9856319b0a29fcab81e17ac27d35798088859c1cfc9fc12b2dbbf54d4f70b3 -a0f6ba637f0db7a48e07439bb92ddb20d590ce9e2ed5bab08d73aa22d82c32a9a370fe934cbe9c08aeb84b11adcf2e0e -a2c548641bd5b677c7748327cca598a98a03a031945276be6d5c4357b6d04f8f40dd1c942ee6ec8499d56a1290ac134d -9863e9cc5fbcdbd105a41d9778d7c402686bfd2d81d9ed107b4fda15e728871c38647529693306855bee33a00d257a7e -a54173bf47b976290c88fd41f99300135de222f1f76293757a438450880e6f13dbde3d5fe7afc687bdfbcfc4fbc1fc47 -b8db413917c60907b73a997b5ab42939abd05552c56a13525e3253eb72b83f0d5cc52b695968a10005c2e2fe13290e61 -a1f8388ef21697c94ba90b1a1c157f0dc138e502379e6fc5dc47890d284563e5db7716266e1b91927e5adf3cde4c0a72 -9949013a59d890eb358eab12e623b2b5edb1acbee238dfad8b7253102abc6173922e188d5b89ec405aa377be8be5f16d -a00fdb7710db992041f6ddb3c00099e1ce311dea43c252c58f560c0d499983a89de67803a8e57baa01ee9d0ee6fa1e44 -a8b1bcbed1951c9cdb974b61078412881b830b48cd6b384db0c00fa68bcc3f4312f8e56c892ea99d3511857ef79d3db9 -8f3ee78404edc08af23b1a28c2012cee0bdf3599a6cb4ea689fc47df4a765ef519191819a72562b91a0fbcdb896a937e -8155bbb7fa8d386848b0a87caae4da3dec1f3dade95c750a64a8e3555166ccc8799f638bd80ed116c74e3a995541587a -abfe30adbc0a6f1fd95c630ed5dac891b85384fa9331e86b83217f29dff0bd7cad19d328485715a7e3df9a19069d4d2f -89d0783e496ee8dbb695764b87fb04cee14d4e96c4ba613a19736971c577d312079048142c12ce5b32b21e4d491d281b -856b8dbc9c5d8f56b6bb7d909f339ca6da9a8787bba91f09130a025ab6d29b64dbf728ba6ed26e160a23c1cdb9bc037b -8a30dd2ea24491141047a7dfe1a4af217661c693edf70b534d52ca547625c7397a0d721e568d5b8398595856e80e9730 -ae7e1412feb68c5721922ed9279fb05549b7ef6812a4fd33dbbbd7effab756ab74634f195d0c072143c9f1fd0e1ee483 -b7ce970e06fa9832b82eef572f2902c263fda29fdce9676f575860aae20863046243558ede2c92343616be5184944844 -85ed0531f0e5c1a5d0bfe819d1aa29d6d5ff7f64ad8a0555560f84b72dee78e66931a594c72e1c01b36a877d48e017ca -b8595be631dc5b7ea55b7eb8f2982c74544b1e5befc4984803b1c69727eac0079558182f109e755df3fd64bee00fcaa5 -99e15a66e5b32468ef8813e106271df4f8ba43a57629162832835b8b89402eb32169f3d2c8de1eb40201ce10e346a025 -844c6f5070a8c73fdfb3ed78d1eddca1be31192797ad53d47f98b10b74cc47a325d2bc07f6ee46f05e26cf46a6433efb -974059da7f13da3694ad33f95829eb1e95f3f3bfc35ef5ef0247547d3d8ee919926c3bd473ab8b877ff4faa07fcc8580 -b6f025aecc5698f6243cc531782b760f946efebe0c79b9a09fe99de1da9986d94fa0057003d0f3631c39783e6d84c7d5 -b0c5358bc9c6dfe181c5fdf853b16149536fbb70f82c3b00db8d854aefe4db26f87332c6117f017386af8b40288d08f9 -a3106be5e52b63119040b167ff9874e2670bd059b924b9817c78199317deb5905ae7bff24a8ff170de54a02c34ff40a4 -ad846eb8953a41c37bcd80ad543955942a47953cbc8fb4d766eac5307892d34e17e5549dc14467724205255bc14e9b39 -b16607e7f0f9d3636e659e907af4a086ad4731488f5703f0917c4ce71a696072a14a067db71a3d103530920e1ec50c16 -8ed820e27116e60c412c608582e9bb262eaaf197197c9b7df6d62b21a28b26d49ea6c8bb77dfde821869d9b58025f939 -97bc25201d98cde389dd5c0c223a6f844393b08f75d3b63326343073e467ac23aacef630ddc68545ea874299ba4a3b4f -b73c9695ad2eefd6cc989a251c433fab7d431f5e19f11d415a901762717d1004bb61e0cc4497af5a8abf2d567e59fef4 -adaabe331eea932533a7cc0cf642e2a5e9d60bbc92dd2924d9b429571cbf0d62d32c207b346607a40643c6909b8727e2 -a7b1bbfe2a5e9e8950c7cb4daab44a40c3ffab01dc012ed7fe445f4af47fa56d774a618fafe332ab99cac4dfb5cf4794 -b4a3c454dcd5af850212e8b9ba5fe5c0d958d6b1cabbf6c6cfe3ccbc4d4c943309c18b047256867daf359006a23f3667 -a5c0b32f6cef993834c1381ec57ad1b6f26ae7a8190dd26af0116e73dadc53bb0eeb1911419d609b79ce98b51fdc33bc -ac2f52de3ecf4c437c06c91f35f7ac7d171121d0b16d294a317897918679f3b9db1cef3dd0f43adb6b89fe3030728415 -94722ae6d328b1f8feaf6f0f78804e9b0219de85d6f14e8626c2845681841b2261d3e6a2c5b124086b7931bf89e26b46 -a841a0602385d17afabca3a1bb6039167d75e5ec870fea60cfcaec4863039b4d745f1a008b40ec07bca4e42cb73f0d21 -8c355f0a1886ffced584b4a002607e58ff3f130e9de827e36d38e57cb618c0cb0b2d2dea2966c461cb3a3887ede9aef1 -a6a9817b0fc2fd1786f5ba1a7b3d8595310987fb8d62f50a752c6bb0b2a95b67d03a4adfd13e10aa6190a280b7ee9a67 -a1d2e552581ecbafeaef08e389eaa0b600a139d446e7d0648ac5db8bbbf3c438d59497e3a2874fc692b4924b87ff2f83 -a1b271c55389f25639fe043e831e2c33a8ba045e07683d1468c6edd81fedb91684e4869becfb164330451cfe699c31a8 -8c263426e7f7e52f299d57d047a09b5eeb893644b86f4d149535a5046afd655a36d9e3fdb35f3201c2ccac2323a9582e -b41c242a7f7880c714241a97d56cce658ee6bcb795aec057a7b7c358d65f809eb901e0d51256826727dc0dc1d1887045 -93001b9445813c82f692f94c0dc1e55298f609936b743cf7aae5ebfa86204f38833d3a73f7b67314be67c06a1de5682d -82087536dc5e78422ad631af6c64c8d44f981c195ddea07d5af9bb0e014cdc949c6fa6e42fce823e0087fdb329d50a34 -8e071861ceba2737792741c031f57e0294c4892684506b7c4a0fc8b2f9a0a6b0a5635de3d1e8716c34df0194d789ae86 -b471c997e1e11774bd053f15609d58838a74073a6c089a7a32c37dd3f933badf98c7e5833263f3e77bc0d156a62dd750 -8d2d8686fb065b61714414bb6878fff3f9e1e303c8e02350fd79e2a7f0555ded05557628152c00166ce71c62c4d2feaa -ae4c75274d21c02380730e91de2056c0262ffcecf0cbdb519f0bdb0b5a10ae2d4996b3dc4b3e16dbaea7f0c63d497fef -97140d819e8ca6330e589c6debdee77041c5a9cedb9b8cbd9c541a49207eeb7f6e6b1c7e736ec8ba6b3ab10f7fcd443a -af6659f31f820291a160be452e64d1293aa68b5074b4c066dac169b8d01d0179139504df867dc56e2a6120354fc1f5be -a5e5d8088a368024617bfde6b731bf9eee35fc362bed3f5dfdd399e23a2495f97f17728fec99ca945b3282d1858aa338 -a59cfc79d15dbdde51ab8e5129c97d3baba5a0a09272e6d2f3862370fdbaf90994e522e8bd99d6b14b3bb2e9e5545c6f -a30499b068083b28d6c7ddcc22f6b39b5ec84c8ee31c5630822c50ea736bb9dca41c265cffc6239f1c9ef2fd21476286 -88ffe103eca84bbe7d1e39a1aa599a5c7c9d5533204d5c4e085402a51441bb8efb8971efe936efbbfa05e5cb0d4b8017 -b202356fbf95a4d699154639e8cb03d02112c3e0128aab54d604645d8510a9ba98936028349b661672c3a4b36b9cb45d -8b89bb6574bf3524473cff1ff743abcf1406bd11fb0a72070ccd7d8fce9493b0069fb0c6655252a5164aee9e446ea772 -93247b1038fa7e26667ee6446561d4882dc808d1015daafb705935ddc3598bb1433182c756465960480f7b2de391649e -b027f94d3358cbb8b6c8c227300293a0dee57bf2fee190a456ad82ecfb6c32f8090afa783e2ab16f8139805e1fb69534 -a18bb1849b2f06c1d2214371031d41c76ffa803ee3aa60920d29dbf3db5fbfac2b7383d5d0080ba29ce25c7baa7c306b -827bf9fd647e238d5ac961c661e5bbf694b4c80b3af8079f94a2484cb8fba2c8cf60e472ebcd0b0024d98ae80ad2ff5a -838e891218c626a7f39b8fd546b013587408e8e366ecc636b54f97fa76f0a758bc1effa1d0f9b6b3bc1a7fcc505970a0 -836523b5e8902d6e430c6a12cff01e417d2bd7b402e03904034e3b39755dee540d382778c1abe851d840d318ebedce7f -850a77dda9ac6c217e2ef00bf386a1adec18b7f462f52801c4f541215690502a77ef7519b690e22fdf54dc2109e0ca38 -a8265c6ae7b29fc2bda6a2f99ced0c1945dd514b1c6ca19da84b5269514f48a4f7b2ccbab65c9107cfd5b30b26e5462f -ab3d02ee1f1267e8d9d8f27cc388e218f3af728f1de811242b10e01de83471a1c8f623e282da5a284d77884d9b8cde0e -831edaf4397e22871ea5ddee1e7036bab9cc72f8d955c7d8a97f5e783f40532edbbb444d0520fefcffeab75677864644 -80484487977e4877738744d67b9a35b6c96be579a9faa4a263e692295bb6e01f6e5a059181f3dd0278e2c3c24d10a451 -aae65a18f28c8812617c11ecf30ad525421f31fb389b8b52d7892415e805a133f46d1feca89923f8f5b8234bd233486a -b3a36fd78979e94288b4cefed82f043a7e24a4a8025479cc7eb39591e34603048a41ee606ee03c0b5781ebe26a424399 -b748b3fc0d1e12e876d626a1ba8ad6ad0c1f41ea89c3948e9f7d2666e90173eb9438027fadcd741d3ae0696bd13840f1 -acdd252d7c216c470683a140a808e011c4d5f1b4e91aeb947f099c717b6a3bad6651142cde988330827eb7d19d5fb25c -b9a25556a6ca35db1ed59a1ec6f23343eab207a3146e4fc3324136e411c8dba77efd567938c63a39c2f1c676b07d8cdb -a8db6aef8f5680d2bdb415d7bcaae11de1458678dcb8c90c441d5986c44f83a9e5855662d0c1aace999172d8628d8fe1 -af58147108e9909c3a9710cc186eab598682dca4bfd22481e040b8c000593ecb22c4ede4253ac9504e964dfa95a9b150 -8dd8bb70f1c9aec0fcc9478f24dfc9c3c36c0bf5ff7a67c017fa4dab2ec633fbd7bc9d8aa41ea63e2696971ed7e375f5 -aa98d600b22aff993a4d7a3ccabd314e1825b200cb598f6b797d7e4d6a76d89e34a4d156c06bddfc62f2ef9b4c809d1d -8a8fc960d6c51294b8205d1dabe430bef59bda69824fa5c3c3105bef22ac77c36d2d0f38ffc95ce63731de5544ccbeff -b6d1020efe01dc8032bd1b35e622325d7b9af9dcd5c9c87c48d7d6ebc58644454294c59b7f4b209204b5b1f899f473bf -8a750dc9fe4891f2dfe5759fb985939810e4cdc0b4e243ff324b6143f87676d8cb4bcb9dfb01b550801cedcaaa5349e2 -98c13142d3a9c5f8d452245c40c6dae4327dd958e0fda85255ea0f87e0bcbaa42a3a0bd50407ed2b23f9f6317a8a4bc5 -99f2b83d9ec4fc46085a6d2a70fd0345df10f4a724c1ba4dee082a1fde9e642e3091992ebf5f90a731abcb6ec11f6d9b -b218546ab2db565b2489ea4205b79daa19ef2acbf772ccaaa5e40150e67ea466090d07198444b48e7109939aa2319148 -84f9d1d868e4b55e535f1016558f1789df0daa0ead2d13153e02f715fe8049b1ce79f5bc1b0bbbb0b7e4dd3c04783f3f -80d870d212fbddfdda943e90d35a5a8aa0509a7a1e7f8909f2fcb09c51c3026be47cc7a22620a3063406872105b4f81a -b5b15138ff6551fac535d4bbce2ea6adc516b6b7734b4601c66ec029da2615e3119dc9ad6a937344acfd7b50e4a1a2ae -95d2f97652086e7ceb54e1d32692b1c867ffba23c4325740c7f10d369283d1b389e8afa0df967831ade55696931e7934 -8a5b580403e1a99cd208f707e8ce0d3f658c8280417683f69008d09cc74d835a85f7380f391b36ead9ac66d9eedd1cbe -a8b0c90bff34c86720637b5a2081f0f144cfe2205c1176cacd87d348609bc67af68aed72414dc9aa6f44a82c92c2a890 -865abbdd96c496892c165a8de0f9e73348bf24fce361d7a9048710178a3625881afb0006e9f5ee39124866b87904c904 -ace67bb994adef4b6f841cdf349195608030044562780a7e9b00b58a4ff117268a03ff01e5a3a9d9d7eff1dd01f5f4bf -b9371d59185b3d2d320d3fefeadb06ba2aa7d164352fb8dc37571509509fa214d736d244ac625a09a033a10d51611e2e -a8ef992771422dcf2d6d84386fde9fe5dba88bfded3dfcd14074ca04331b4fd53a7f316615cdfaf10ed932cbb424a153 -868cbc75f8f789ea45eded2768a1dac0763347e0d8e8028d316a21005f17be179d26d5965903e51b037f2f57fe41765d -b607111bcdfd05fa144aa0281b13ee736079ebbbf384d938a60e5e3579639ed8ef8eb9ca184868cdb220a8e130d4a952 -aca55702af5cae4cae65576769effd98858307a71b011841c563b97c2aa5aeb5c4f8645d254f631ed1582df3dbbf17da -b9b5cbace76246e80c20dfcc6f1e2c757a22ab53f7fd9ff8a1d309538b55174e55e557a13bf68f095ff6a4fa637ef21a -8571b0a96871f254e2397c9be495c76379faf347801cb946b94e63212d6a0da61c80e5d7bebbabcd6eaa7f1029172fe5 -902540326281e6dc9c20d9c4deaaf6fbbbcc3d1869bd0cf7f081c0525bea33df5cfa24ead61430fda47fb964fcc7994b -841af09279d3536a666fa072278950fabf27c59fc15f79bd52acb078675f8087f657929c97b4bc761cbade0ecb955541 -a1f958b147ddf80ab2c0746ba11685c4bae37eb25bfa0442e7e1078a00d5311d25499da30f6d168cb9302ea1f2e35091 -863d939381db37d5a5866964be3392a70be460f0353af799d6b3ed6307176972686bd378f8ad457435a4094d27e8dfb7 -835cd4d7f36eff553d17483eb6c041b14280beb82c7c69bca115929658455a1931212976c619bafb8179aed9940a8cc6 -8d0770e3cb8225e39c454a1fc76954118491b59d97193c72c174ecc7613051e5aed48a534016a8cf0795c524f771a010 -91aa4edb82f6f40db2b7bd4789cc08786f6996ebed3cb6f06248e4884bc949793f04a4c5ea6eefe77984b1cc2a45d699 -8fb494ca2449f659ff4838833507a55500a016be9293e76598bbae0a7cb5687e4693757c2b6d76e62bd6c7f19ed080bb -b59b104449a880a282c1dd6a3d8debb1d8814ef35aab5673c1e500ee4cb0e840fb23e05fa5a0af92509c26b97f098f90 -aca908e3bad65e854ae6be6c5db441a06bcd47f5abafdfa8f5a83c8cd3c6e08c33cab139c45887887a478338e19ceb9f -806f5d802040313a31964fc3eb0ee18ac91b348685bed93c13440984ee46f3d2da7194af18c63dea4196549129660a4e -ae4b2dca75c28d8f23b3ab760b19d839f39ff5a3112e33cb44cff22492604a63c382b88ec67be4b0266924dd438c3183 -99d1c29c6bd8bf384e79cd46e30b8f79f9cbc7d3bf980e9d6ffba048f0fc487cac45c364a8a44bb6027ad90721475482 -a16e861c1af76d35528c25bf804bfc41c4e1e91b2927d07d8e96bffe3a781b4934e9d131ecf173be9399800b8269efac -a253303234fb74f5829060cdcef1d98652441ab6db7344b1e470d195a95722675988048d840201c3b98e794b1e8b037c -905ac8a0ea9ce0eb373fb0f83dd4cbe20afb45b9d21ae307846fd4757d4d891b26a6711924e081e2b8151e14a496da18 -b485315791e775b9856cc5a820b10f1fa5028d5b92c2f0e003ba55134e1eddb3eb25f985f2611a2257acf3e7cfdfab5e -b6189c0458b9a043ebc500abc4d88083a3487b7ac47ed5e13ab2a41e0a1bee50d54a406063f92bc96959f19e822a89a7 -a30e15f995fd099a223fc6dc30dad4b8d40bee00caa2bc3223ba6d53cd717c4968a3e90c4618c711ed37cc4cd4c56cf3 -a1b1ed07fcc350bb12a09cd343768d208fc51a6b3486f0ece8f5a52f8a5810b4bc7ab75582ec0bc2770aed52f68eace5 -88aa739fbae4bece147ba51a863e45d5f7203dbc3138975dc5aef1c32656feb35f014d626e0d5b3d8b1a2bda6f547509 -ab570f3c8eabfca325b3a2ea775ef6b0c6e6138c39d53c2310329e8fb162869fde22b0e55688de9eb63d65c37598fca3 -89d274762c02158e27cb37052e296a78f2b643eb7f9ae409f8dac5c587d8b4d82be4ef7c79344a08ebec16ac4a895714 -99c411d2ad531e64f06e604d44c71c7c384424498ecd0a567d31ec380727fb605af76643d0d5513dd0a8d018076dd087 -80d0777fa9f79f4a0f0f937d6de277eec22b3507e2e398f44b16e11e40edf5feff55b3b07a69e95e7e3a1621add5ed58 -b2430a460783f44feb6e4e342106571ef81ad36e3ddd908ec719febeb7acaf4b833de34998f83a1dab8f0137a3744c11 -b8f38ccfc7279e1e30ad7cefc3ea146b0e2dff62430c50a5c72649a4f38f2bac2996124b03af2079d942b47b078cc4f8 -a178a450a62f30ec2832ac13bbc48789549c64fc9d607b766f6d7998558a0e2fad007ae0148fc5747189b713f654e6ba -98c5ede296f3016f6597f7ccc5f82c88fd38ed6dc3d6da3e4a916bfd7c4c95928722a1d02534fe89387c201d70aa6fd2 -a8cc5e98573705d396576e022b2ba2c3e7c7ece45cd8605cb534b511763682582299e91b4bb4100c967019d9f15bbfaf -848480ea7b7d9536e469da721236d932870b7bbee31ccf7ae31b4d98d91413f59b94a1e0d1786ee7342295aa3734969c -b88ea38f9ee432f49e09e4e013b19dff5a50b65453e17caf612155fff6622198f3cba43b2ea493a87e160935aaaf20a9 -949376934a61e0ef8894339c8913b5f3b228fa0ae5c532ad99b8d783b9e4451e4588541f223d87273c0e96c0020d5372 -96f90bb65ca6b476527d32c415814b9e09061648d34993f72f28fae7dc9c197e04ef979f804076d107bb218dfd9cb299 -a4402da95d9942c8f26617e02a7cef0ebc4b757fac72f222a7958e554c82cc216444de93f659e4a1d643b3e55a95d526 -81179cbc26a33f6d339b05ea3e1d6b9e1190bd44e94161ae36357b9cdf1e37d745d45c61735feed64371fe5384102366 -ad4dc22bdbd60e147fdac57d98166de37c727f090059cfc33e5ee6cf85e23c2643996b75cf1b37c63f3dc9d3c57ffa18 -8a9b1b93dc56e078ce3bb61c2b0088fd6c3e303ba6b943231cc79d4a8e8572f4109bbde5f5aa7333aae3287909cb0fe2 -8876ef583bc1513322457a4807d03381ba1f4d13e179260eaa3bddfede8df677b02b176c6c9f74c8e6eab0e5edee6de6 -b6c67e228bf190fbaeb2b7ec34d4717ce710829c3e4964f56ebb7e64dc85058c30be08030fa87cc94f1734c5206aef5f -a00cb53b804ee9e85ce12c0103f12450d977bc54a41195819973c8a06dcb3f46f2bf83c3102db62c92c57ab4dd1e9218 -a7675a64772eefddf8e94636fb7d1d28f277074327c02eea8fae88989de0c5f2dc1efed010f4992d57b5f59a0ab40d69 -8d42bb915e0bf6a62bcdf2d9330eca9b64f9ec36c21ae14bf1d9b0805e5e0228b8a5872be61be8133ad06f11cb77c363 -a5b134de0d76df71af3001f70e65c6d78bed571bc06bfddf40d0baad7ea2767608b1777b7ef4c836a8445949877eeb34 -aeadbc771eaa5de3a353229d33ed8c66e85efbd498e5be467709cb7ff70d3f1a7640002568b0940e3abd7b2da81d2821 -8c28da8e57a388007bd2620106f6226b011ee716a795c5d9f041c810edf9cf7345b2e2e7d06d8a6b6afa1ee01a5badc1 -8ed070626a4d39ffd952ddb177bc68fd35b325312e7c11694c99b691f92a8ea7734aeb96cf9cc73e05b3c1b1dcad6978 -ada83e18e4842f3d8871881d5dbc81aed88a1328298bfdc9e28275094bd88d71b02e7b8501c380fa8d93096cbc62f4fb -8befc3bec82dcf000a94603b4a35c1950ba5d00d4bed12661e4237afa75062aa5dcef8eac0b9803136c76d2dd424a689 -97c6f36c91ca5ca9230bfcbf109d813728b965a29b62e5f54c8e602d14a52ac38fa1270de8bfe1ab365426f3fc3654c7 -b01d192af3d8dbce2fe2fece231449e70eb9ac194ec98e758da11ca53294a0fa8c29b1d23a5d9064b938b259ea3b4fb5 -819a2c20646178f2f02865340db1c3c6ebc18f4e6559dd93aa604388796a34bd9fed28ad3ccc8afc57a5b60bb5c4e4ec -a9ffc877470afc169fecf9ec2dc33253b677371938b0c4ffa10f77bb80089afa2b4488437be90bb1bcf7586a6f4286e3 -b533051c7ce7107176bcb34ad49fdb41fac32d145854d2fe0a561c200dcf242da484156177e2c8f411c3fdf1559ecf83 -8fe2caff2e4241d353110a3618832f1443f7afe171fd14607009a4a0aa18509a4f1367b67913e1235ac19de15e732eb1 -84705c6370619403b9f498059f9869fdf5f188d9d9231a0cb67b1da2e8c906ead51b934286497293698bba269c48aa59 -899dddf312a37e3b10bdaaacc1789d71d710994b6ee2928ac982ad3fd8a4f6167672bc8bf3419412711c591afe801c28 -b2f7916d946b903ded57b9d57025386143410a41a139b183b70aeca09cf43f5089ead1450fce4e6eb4fba2c8f5c5bbe5 -8d5f742fe27a41623b5820914c5ca59f82246010fa974304204839880e5d0db8bc45ebab2ad19287f0de4ac6af25c09e -b93d4a1f6f73ac34da5ffbd2a4199cf1d51888bc930dc3e481b78806f454fcb700b4021af7525b108d49ebbbaa936309 -8606f8d9121512e0217a70249937e5c7f35fbfe019f02248b035fa3a87d607bc23ae66d0443e26a4324f1f8e57fd6a25 -b21312cdec9c2c30dd7e06e9d3151f3c1aceeb0c2f47cf9800cce41521b9d835cb501f98b410dc1d49a310fdda9bc250 -a56420b64286bdddda1e212bba268e9d1ba6bdb7132484bf7f0b9e38099b94a540884079b07c501c519b0813c184f6b4 -80b2cf0e010118cb2260f9c793cef136f8fa7b5e2711703735524e71d43bce2d296c093be41f2f59118cac71f1c5a2ff -adcb12d65163804d2f66b53f313f97152841c3625dbbda765e889b9937195c6fcd55d45cc48ebffabb56a5e5fe041611 -8b8a42e50dc6b08ab2f69fc0f6d45e1ea3f11ba0c1008ee48448d79d1897356599e84f7f9d8a100329ed384d6787cfc4 -aaa9c74afa2dec7eccfbd8bb0fc6f24ed04e74c9e2566c0755a00afdfdf3c4c7c59e2a037ec89c2f20af3fae1dd83b46 -aa9f6e8fd59187171c6083ae433627d702eb78084f59010ff07aff8f821f7022ef5fbbe23d76814d811b720a8bfa6cc3 -a56a3ded501659ad006d679af3287080b7ee8449e579406c2cae9706ef8bf19c1fc2eb2a6f9eaf2d3c7582cded73e477 -81971e077c1da25845840222b4191e65f6d242b264af4e86800f80072d97d2a27a6adc87c3a1cb1b0dd63d233fbafa81 -a6fa5453c4aaad2947969ee856616bf6448224f7c5bf578f440bcfc85a55beb40bef79df8096c4db59d1bd8ef33293ea -87c545adbfaaf71e0ab4bac9ae4e1419718f52b0060e8bb16b33db6d71b7248ae259d8dd4795b36a4bbb17f8fae9fd86 -b4c7a9bc0910e905713291d549cec5309e2d6c9b5ea96954489b1dff2e490a6c8b1fa1e392232575f0a424ba94202f61 -802350b761bcaba21b7afe82c8c6d36ee892b4524ab67e2161a91bbfa1d8e92e7e771efb1f22c14126218dd2cb583957 -b4e7ddb9143d4d78ea8ea54f1c908879877d3c96ee8b5e1cb738949dcfceb3012a464506d8ae97aa99ea1de2abf34e3d -a49a214065c512ad5b7cc45154657a206ef3979aa753b352f8b334411f096d28fd42bca17e57d4baaafb014ac798fc10 -8a80c70a06792678a97fe307520c0bf8ed3669f2617308752a2ab3c76fdf3726b014335a9b4c9cbcfc1df3b9e983c56f -a34721d9e2a0e4d08995a9d986dc9c266c766296d8d85e7b954651ad2ca07e55abb1b215898ee300da9b67114b036e0d -8cfce4564a526d7dca31e013e0531a9510b63845bbbd868d5783875ed45f92c1c369ce4a01d9d541f55f83c2c0a94f03 -ab3f5f03a5afc727778eb3edf70e4249061810eba06dc3b96b718e194c89429c5bfbec4b06f8bce8a2118a2fdce67b59 -aa80c2529fc19d428342c894d4a30cb876169b1a2df81a723ab313a071cba28321de3511a4de7846207e916b395abcc9 -82b7828249bf535ef24547d6618164b3f72691c17ca1268a5ee9052dba0db2fdd9987c8e083307a54399eab11b0f76b1 -8fbcb56b687adad8655a6cf43364a18a434bf635e60512fad2c435cf046f914228fb314f7d8d24d7e5e774fb5ffb1735 -a3010a61a2642f5ebbce7b4bc5d6ecb3df98722a49eb1655fe43c1d4b08f11dfad4bcec3e3f162d4cc7af6a504f4d47c -b3dcc0fdf531478e7c9ef53190aa5607fd053a7d2af6c24a15d74c279dbb47e3c803a1c6517d7e45d6534bb59e3527f5 -8648f6316c898baaca534dff577c38e046b8dfa8f5a14ee7c7bc95d93ae42aa7794ba0f95688a13b554eeb58aeedf9ba -89fca6fc50407695e9315483b24f8b4e75936edf1475bcf609eed1c4370819abac0e6a7c3c44f669560367d805d9ba63 -a367a17db374f34cd50f66fb31ba5b7de9dbe040f23db2dcc1d6811c0e863606f6c51850af203956f3399000f284d05f -91030f9ca0fff3e2dbd5947dcf2eba95eb3dbca92ee2df0ed83a1f73dbf274611af7daf1bb0c5c2ee46893ab87013771 -84d56181f304ce94015ea575afeef1f84ea0c5dbb5d29fb41f25c7f26077b1a495aff74bd713b83bce48c62d7c36e42d -8fe2f84f178739c3e2a2f7dcac5351c52cbed5fa30255c29b9ae603ffd0c1a181da7fb5da40a4a39eec6ce971c328fcf -a6f9b77b2fdf0b9ee98cb6ff61073260b134eb7a428e14154b3aa34f57628e8980c03664c20f65becfe50d2bdd2751d4 -8c6760865445b9327c34d2a1247583694fbeb876055a6a0a9e5cb460e35d0b2c419e7b14768f1cc388a6468c94fd0a0f -af0350672488a96fe0089d633311ac308978a2b891b6dbb40a73882f1bda7381a1a24a03e115ead2937bf9dcd80572ad -a8e528ec2ee78389dd31d8280e07c3fdd84d49556a0969d9d5c134d9a55cd79e1d65463367b9512389f125ed956bc36a -942c66589b24f93e81fe3a3be3db0cd4d15a93fb75260b1f7419f58d66afaa57c8d2d8e6571536790e2b415eec348fd9 -83fe4184b4b277d8bf65fb747b3c944170824b5832751057e43465526560f60da6e5bbee2f183cb20b896a20197168c7 -88a71aada494e22c48db673d9e203eef7a4e551d25063b126017066c7c241ee82bedaa35741de4bd78a3dd8e21a8af44 -8c642a3186ca264aac16ee5e27bd8da7e40e9c67ae159b5d32daa87b7de394bf2d7e80e7efb1a5506c53bfd6edd8c2c3 -81855d6de9a59cef51bef12c72f07f1e0e8fe324fcc7ec3f850a532e96dcd434c247130610aaee413956f56b31cbb0dc -a01e61390dcd56a58ad2fcdb3275704ddfbedef3ba8b7c5fce4814a6cdd03d19d985dba6fd3383d4db089444ea9b9b4d -96494e89cbf3f9b69488a875434302000c2c49b5d07e5ff048a5b4a8147c98291ae222529b61bb66f1903b2e988e5425 -b9689b3e8dddc6ec9d5c42ba9877f02c1779b2c912bba5183778dc2f022b49aed21c61c8ec7e3c02d74fe3f020a15986 -a2a85e213b80b0511395da318cbb9935c87b82c305f717a264155a28a2ea204e9e726bae04ce6f012e331bd6730cbb9d -91b70f44c7d8c5980ce77e9033a34b05781cbe773854d3f49d2905cc711a3d87c20d5d496801ad6fd82438874ce732b8 -884596417ff741bb4d11925d73852ffeea7161c7f232be3bdce9e6bbe7884c3a784f8f1807356ae49d336b7b53a2b495 -ae2aed8ab6951d8d768789f5bc5d638838d290d33ccc152edfb123e88ba04c6272b44294b0c460880451ad7b3868cc6a -89d8ebfb9beebc77189d27de31c55f823da87798a50bca21622cbf871e5d9f1d3182cf32ee9b90f157e6ce298e9efccf -afd00a4db4c2ed93cf047378c9402914b6b3255779f3bb47ded4ab206acb7eaebba0fd7762928e681b1aebcfee994adc -a2e49b6cd32e95d141ebc29f8c0b398bb5e1a04945f09e7e30a4062142111cd7aa712ac0e3e6394cfb73dd854f41ad77 -ae8e714ab6e01812a4de5828d84060f626358bb2b955f6fb99ae887b0d5ce4f67ebc079ab9e27d189bf1d3f24f7c2014 -a3100c1eebf46d604e75ebf78569c25acf938d112b29ccbe1a91582f6bd8ef5548ae3961c808d3fb73936ac244e28dbc -a9a02dcff0e93d47ead9cdddc4759971c2d848580bf50e117eb100cafca6afeaa7b87208513d5f96b1e1440ffc1b0212 -894ab01462137e1b0db7b84920a3b677fbb46c52b6f4c15320ef64f985e0fc05cec84cd48f389ce039779d5376966ea3 -b1e40e8399ee793e5f501c9c43bde23538e3ce473c20a9f914f4a64f5b565748d13ab2406efe40a048965ee4476113e4 -a5a7d97a19e636238968670a916d007bf2ce6ae8e352345d274101d0bbe3ac9b898f5b85814a7e4c433dd22ac2e000ff -b6394c43b82923231d93fd0aa8124b757163ba62df369898b9481f0118cb85375d0caac979a198ece432dbb4eb7cc357 -82d522ae3ff4fe2c607b34b42af6f39c0cf96fcfe1f5b1812fca21c8d20cece78376da86dcbd6cdb140e23c93ae0bcb2 -b6e0d986383bc4955508d35af92f2993e7e89db745f4525948c5274cfd500880cb5a9d58a5b13d96f6368bb266a4433e -b0b4325772ec156571d740c404e1add233fb693579f653b0fae0042b03157d3b904838f05c321d2d30f2dbd27c4d08ad -ac41367250263a2099006ef80c30bac1d2f25731d4874be623b6e315c45b0dc9a65f530fce82fb3dc25bd0610008c760 -b6c0b1ed7df53da04a6f3e796d3bfa186f9551c523bc67898bc0ecfc6b4a4a22f8c4d3bfc740ebf7b9fa5b0ea9431808 -8e78fca17346601219d01e5cd6a4837161a7c8f86fe2a8d93574d8006da5f06ae7c48eea7d2b70992c2a69184619663c -a21f91f47e04fafbfafacf3185b6863766a2d0c324ccac2c3853a4748af5897dbbe31d91473b480f646121339c9bae2d -a464d68786ab1fc64bd8734fce0be6fbe8dc021d3e771ff492ada76eedff466577c25e282b7c8ab4c1fd95ef5ff3631e -829a24badc7714081e03509ccfb00818ce40430682c1c0e4a399cd10b690bda1f921aabcbf1edfb1d8a2e98e6c0cedd6 -87ccf7e4bbcb818ef525435e7a7f039ecbb9c6670b0af163173da38cbdb07f18bc0b40b7e0c771a74e5a4bc8f12dfe2c -94087bd2af9dbeb449eb7f014cfbf3ee4348c0f47cde7dc0ad401a3c18481a8a33b89322227dee0822244965ae5a2abb -896b83ed78724dac8a3d5a75a99de8e056a083690152c303326aa833618b93ef9ec19ab8c6ef0efe9da2dbcccac54431 -821e6a0d7ccf3c7bd6a6cc67cde6c5b92fb96542cb6b4e65a44bbc90bbc40c51ff9e04702cb69dd2452f39a2ff562898 -b35b2096cda729090663a49cb09656c019fef1fc69a88496028d3a258ad2b3fd6d91ab832163eaa0077989f647e85e7e -b7857ef62c56d8bce62476cdb2ab965eddff24d932e20fc992bd820598686defe6cc0a7232d2be342696c2990d80721a -b343d974dfda3f6589043acd25d53aecf7c34b1e980ae135a55cda554ff55e531bc7c2dfe89b0d2c30e523c7b065dad1 -8d139e16a73cd892b75f3f4e445a10d55d1118f8eeafc75b259d098338419e72e950df6ca49cb45677a3c4e16fb19cdc -817b8535bd759da392b2c5760c51b3952ecf663662a137c997f595c533cd561ed7e655673c11144242160e41d1f2dd71 -817ee0f0819b0ccb794df17982d5b4332abff5fec5e23b69579db2767855642156d9b9acccf6ceab43332ccc8d2744dc -9835d2b652aec9b0eba0c8e3b6169567e257a6a3f274ec705dbc250ee63f0f8e4b342e47b9e0c280c778208483d47af8 -b78c40177f54f0e6d03083a4f50d8e56b5aafdb90f1b047bb504777d6e27be5a58170330aee12fbaa5f1e9d4f944acfc -ab8eebacf3806fac7ab951f6a9f3695545e2e3b839ca399a4ef360a73e77f089bb53d3d31dbd84ddfde55e5f013626e0 -96c411fc6aecca39d07d2aff44d94b40814d8cfc4ee5a192fd23b54589b2801694d820a0dd217e44863ccff31dda891b -8249c424a0caf87d4f7ff255950bbc64064d4d1b093324bfe99583e8457c1f50e6996e3517bf281aa9b252c2a7c5a83a -acf6ed86121821a3dd63f3875b185c5ebe024bdb37878c8a8d558943d36db0616545a60db90789c0925295f45d021225 -a37f155621a789f774dd13e57016b8e91b3a2512b5c75377ec8871b22a66db99655d101f57acaecd93115297caabfc21 -92e60ee245bd4d349f1c656e034b1a7f0c6415a39ac4c54d383112734305488b3b90b0145024255735e0a32f38dba656 -acec614e562ccfc93366309cfdc78c7d7ee0a23e3a7782a4fc4807b8803e6ebfb894a489d03e9a3c817ff2ec14813eba -b912f9dd26ed552cb14b007b893e6ed2494d12517e5761dbeb88521270144f8c3eb9571a0ad444b30a8a65e80bd95996 -8375408dae79c547a29e9a9e5d4ec8241b36b82e45e4ca3b0c36d2227c02d17bb171528d3778eac3bbdc75d6c4e8a367 -8c2d0e6e4406836da112edbbb63996408bb3cda4a2712fd245e4bb29a0100fdc89a2746d859b84a94565bc1cfa681813 -a7431bf59e111c072d28c97626cd54fcdf018421d053a787d2aef454b91251ee8ff9d3702d06b088f92b9ad2bbebff15 -8f3659b0fbeb90b7f30b7a49233325e806551a32911a654dca86e290b314483bbb33fe6482387bc48c35d85c1dd0441c -8dca5ba23f0bb76f7dacabf12886053552ba829a72827b472a2f01e19a893155cdce65f1fb670000f43e8c75ba015a31 -8c1514c083c77624eeb5d995d60994a2866192e15c4474d0be4189fae0e9dbd62494ebb4c02fbc176b53be548abbc5a1 -80498d2ed153381baf3b0f81da839ed0eea6af5796c422b8e59be805dba48c4395bb97824ac308170bb4f14f319c5ddf -84f5ebc3bf96362457993e9fa31493c31c4283075e2403f63d581b6b0db8a3df294b2085643f2007f4de38cb5d627776 -958e6e38774da518193a98397978dbc73d1c3827b4996ec00b4183da2c305a187a0ada9aa306242814b229a395be83c9 -ab8b8fbf73845615e7fab3e09e96cc181159eab09f36b4c1239b3c03313c9aeb4bbb51e16316fe338b2319ed2571b810 -977e4e33b33bd53394e591eba4f9a183e13704c61e467d74b28f4ad0b69aa51501a5221cb1e0e42bcb548ca518caa619 -a9bb7ecb9846cc30d04aad56d253c3df7004cebb272f6adf7b40a84adef9f57291e0d08d64c961b9fc406cdb198aab9b -8d2b72dc36406a545a9da44e1fddfb953d4894710ca026d6421a4ac91e02d0373a599f2acfe41d8258bc9679cf6f43d3 -904192fc8fe250f61ecb8a36abbbccae85f592bbf00c10039c30b5a1c733d752a04e4fd8a1000c6578616f8a16aa83a3 -87f5fdfe20bbbf931b529ec9be77bbfcc398cad9d932d29f62c846e08a91d2f47ae56ad5345122d62a56f629f9a76c4d -84cc3a53b2e7b7e03015f796b6cb7c32d6ded95c5b49c233ac27fafa792994b43c93cda6e618b66fce381f3db69838ba -aab58da10d7bbe091788988d43d66a335644f3d0897bbc98df27dcc0c0fcee0ac72e24f1abdd77e25196a1d0d0728e98 -a10ea8677c2b7da563d84aa91a314a54cab27bb417c257826ebdd3b045d2a0f12729fe630bbbf785d04874f99f26bee8 -acc4970ef2a4435937a9b8a5a5a311226ca188d8f26af1adfcd6efb2376a59155b9a9ff1cff591bde4b684887d5da6e5 -8dc7cf6fcca483c44eb55e7fb924bf3f76cf79b411ae4b01c6c968910877ac9c166b71350f4d935f19bdffb056477961 -ac2dd1182ded2054c2f4dbf27b71a0b517fb57193733a4e4e56aca8a069cff5078ffd3fd033683d076c1c639a4de63c7 -932ec87c450cd0dc678daf8c63cd1bf46124fa472934e517fbbfb78199f288ff7f354b36e0cc6c8739d3f496cfe0913b -b0d631ced213e8492be60ea334dbe3b7799b86d85d5e8e70d02beef3ae87b1d76e1df3bdb5f7ba8a41904c96f6a64455 -929d7239ead7575867e26b536b8badf2e11ca37840034d0e5c77039f8cce122eff5a1bf6e0bcadde6b3858e9f483d475 -aaae5d372d02ee25b14de585af6fbc48f2c7cd2a6af4f08352951b45aa469599eff41e820df642ca1a0f881120e89dbe -b23c411741a6b059f04fa4f5fd9dd10e2a64915f2de6ea31e39c32f2f347a776a953320e5f7613fcb1167efe502f5c5c -a4581b0ae633fe29c6f09928e5efb16db019eeac57f79fef2fa1d3c9bee42ce0e852bc60b9d0133265373747e52a67a4 -81b33afffd7b2575d4a9a1c5dd6eee675c084f82e06b9b3a52a3c9f76e087f12dca6e0ffddc42fb81ce1adb559d47a38 -89cc890f06b424591556aabdfdbb36d7a23700425e90c9cfed7d3da226b4debe414ac5bdf175273828ce6c5355712514 -a4399438be75cfae2bf825496704da5ed9001bed8538d8ac346c8cf0d4407808e9ee67573eb95fe1c6872ac21f639aaa -ad537f7ce74a1ca9a46fc06f15c1c8a6c32363bd6ac78a3c579ed8f84252e38a914cac16709fe65360e822ef47896de4 -8e53b69f5e3e86b86299452e20ea8068b49565d0d0ab5d50ce00158a18403ae44e1b078a3cfd3f919aa81eb049a30c6e -a59f2542c67a430fd3526215c60c02353ee18af2ff87cb6231a2564fe59b8efec421f18d8b8cc7f084675ecf57b3fd05 -b8d9bac93ef56cb4026dd1c731d92260a608fd55b8321e39166678e1dab834d0efddb717685da87786caeb1aaf258089 -aa2df56f4c6fe9e0f899116c37302675f796a1608338700f05a13e779eb7cf278e01947864a8c2c74cc9d9a763804446 -b0108ff2e327dcb6982961232bf7a9a0356d4297902f4b38d380ff1b954bfbcae0093df0f133dd9e84d5966c7b1aada7 -b06b813b01fe7f8cf05b79dc95006f0c01d73101583d456278d71cd78638df2b1115897072b20947943fa263ddab0cd6 -aa41e6c4d50da8abf0ea3c3901412fe9c9dff885383e2c0c0c50ed2f770ada888a27ea08bbb5342b5ff402e7b1230f12 -a48635dbb7debac10cb93d422c2910e5358ba0c584b73f9845028af4a763fd20da8f928b54b27782b27ca47e631ebf38 -80a574c208e994799e4fa9ef895163f33153bc6487491d817c4049e376054c641c4717bda8efbeb09152fa421a7268a7 -b592bfd78ae228afc219c186589b9b0b5c571e314976d1ed5c1642db9159d577679a73c049cfc3dcfefcd5a4f174eeea -aa1f08af3918c61eadf567a5b1a3cdcdfb1b925f23f1f9e3c47889762f4d979d64686ce1ce990055ef8c1030d98daa3b -857df4cfd56d41c6d0c7fcc1c657e83c888253bae58d33b86e0803a37461be5a57140a77fb4b61108d1d8565091ada1c -8fae66a72361df509d253012a94160d84d0b2260822c788927d32fd3c89500500908c8f850ef70df68ddaeb077fd0820 -aa1dbefc9aef1e7b896ff7303837053c63cfb5c8a3d8204680d3228ac16c23636748fe59286468c99699ae668e769a0c -b64b1cb2ba28665ed10bad1dddc42f3f97383c39bad463c6615b527302e2aaf93eb6062946d2150bd41c329697d101be -b6d35e3b524186e9065cee73ea17c082feff1811b5ab5519dd7991cdff2f397e3a79655969755309bd08c7d5a66f5d78 -a4dae7f584270743bbba8bb633bdb8bc4dcc43580e53d3e9e509ff6c327e384f14104b5bdfe5c662dc6568806950da37 -aae84d3d9ad4e237b07c199813a42ed2af3bf641339c342d9abf7ebec29b5bd06249c4488ce5c9277d87f7b71b3ddd37 -b82a463cf643821618a058bddf9f2acb34ac86a8de42a0fa18c9626e51c20351d27a9575398a31227e21e291b0da183e -8b6c921e8707aded3ea693f490322971b1a7f64786ef071bc9826c73a06bd8ae6bf21bc980425769627b529d30b253ce -80724937b27fc50f033c11c50835c632369f0905f413b1713a2b0a2274bec5d7a30438e94193d479ba6679dbe09a65ef -a1d9b259a2ca9cff8af6678b3af0a290c2f51e9cf26d5fe3c6a4fa3d28cbf33cb709b7f78b4f61cb9419427983c61925 -96a3e69a5ed7a98ce59c4481f2ffb75be9542122ad0eb4952c84d4536760df217854d4ec561ce2f4a79d3793c22fa4f4 -990c4d9a4a22d63a8976d34833cafc35936b165f04aed3504e9b435f0de1be4c83b097bbaa062483cf3dee3833b4f5b6 -b9bf5e4b270aec4a0dc219457b5fed984b548892c4b700482525ba1a7df19284464f841dab94abfabcaa9a7b7a757484 -acaecf49cb4786d17cf867d7a93bd4ffee0781766e11b5c1b29089ae0024c859d11b45828fbff5330b888543264d74a9 -b0e1a0865b1e6f9e4a0e31d0c885526ac06678acc526fda5124742a2c303bd0e8871a0cb7951ec8ed9540fc247c8d844 -82b3d327b3d1a631758451e12870816956cd0cef91fcf313a90dd533d5291193a0ff3cc447054564ce68c9b027a7ffd7 -a2843602abb98f0f83e000f3415039788da1e9a096bfe8fed6b99bab96df948c814560424ffebe755cb72f40436fb590 -ab1c7b43cf838798d1e314bc26e04fc021e99a7bfbfc8ffde62fa8d7f92139de86a377289d5177021154229de01ede15 -95e5cf5dd87ae3aed41b03c6c55f9dfad38dc126b17e7e587c156f7745c8da0bd1d60acb718fc1a03b61344f01e3de4d -86f021a3762bb47167f80d4ef1b1c873a91fe83409f9704f192efeebbc3ece0729cd2f92f63419907ea38ae47bc907d2 -aaa1445dafbbcd645d4332d9806225e9346ee5ac6b22ad45e8922134fe12f3d433f567a6a4c19efdd9d5775a7de1e92f -8fd7e15688eef75df7b8bca3d61bc9fca4f56e047cdb6d0b864e7d1c4966eac27d6094b0c8482b49739f83ec51050198 -80aab8b4d394eb011d4ec6a4c2815617308c9b847c6fa6a3d7e6af1c79420ef6ff2a13934a398581c40ee4cf1cac02ac -8970b97ac076a1d8a321ce00eada0edf974a46bf3cc26f6854e4218cdfc8d2b0c32199d9658f254b4fbae5a2c5535f41 -a1aa2ec5b03df0a630e73dd048680ed6d3032c324941423f45cd1f16038789e5e75b876a13948732e9079a422f66a9fc -b5fe5f5e2f2ae2beeb8e95859a02fc45f01f9fb0ebb2bd8ec9ec976b3e806228821a9775096d341d662bc536c4d89452 -a2bc1f170b62d0d5788b02391337b2ab157c38e725694e80aeead7383e05599be0e2f0fa27ef05db007061809356e147 -a8a69701d4a8d0d972390e9f831fd8e9f424b2c2ef069e56bd763e9e835b3ce5f7cf5de5e5c297c06ace4aa74df1067c -b43d551af4ff3873557efe3f3fb98e5ede9008492f181f4796dd1a6bcda8b9445c155e8146966baa812afae1abe06b48 -b4b1dae44fd596813f30602ab20e9b1fb20cb1bd650daacc97b7e054e5c0178b8131d439a9e5b142ca483cc012a362b3 -b95b8a94c30a831eaaebea98c65cc5d0228c78afd6603d4aa426d8186aecc951f1a11c33951f51df04c7e6fa43ffb5ae -b100059624cf9db371bec80013a57a8f296d006c139a8766308f1ea821c7eccc26cad65bc640ab3f6cef9062653bf17d -8e5a2cb76716e0000d13bce5ef87acac307362a6096f090f5f64e5c5c71a10fddfdee8435e7166ba8c3ad8c3f540f3e4 -93d2c43e21588c1e83c4255c52604b4ac3f40e656352d1827e95dd5222a45aebff9674e34fbbe7ed21eca77bd9b8dcbc -8aeaed611546bb9073b07512a9a1f38a7f436ab45e11775a0f9754baaf63e9bcc7bb59b47546a5ded5e4ba2f698e3b5f -af9e6792e74a1163fe27612f999a2f3cfa9048914c5bef69e3b2a75162bb0ce6ece81af699ad7f0c5278a8df0ba000d2 -850bf2d5d34791c371a36404036ad6fdcd8fb62d1bb17a57e88bda7a78ea322397ce24d1abf4d0c89b9cf0b4cc42feb3 -87f7e2a1625e2b7861b11d593aaac933ed08a7c768aebd00a45d893ed295bbb6ed865037b152bb574d70be006ddc1791 -8dcce8f4ad163b29a2348ea15431c2c6ea1189ece88d2790e9f46b9125bd790b22503ec391bc2dee8f35419863b2c50c -b4bf5266c37f12421dd684b29517982d5e4b65dfdfba5fc7bd7479fd854aabf250627498f1e1188a51c0a88d848ec951 -8651623c690247f747af8fdffdc3e5f73d0662bc3279fa2423a3c654af9b6433b9e5e0155f1ce53857e67388e7e3401d -b155120f196d52760129dde2e2b1990039b99484cdc948fa98095cd23da87679850f522e5955eae34ac267d2144160d3 -aec8115e8d7b6601fbceeccf92e35845a06706d46acd188452c9f7d49abef14c6b3a9a9369a8bab2fd4eb9288e2aaca5 -998a8ca4dc0f145f67a8c456f1d6a7323c4836fe036dcbb0f27eb1c596d121eb97369638a9908cfaf218c7706f266245 -b235fbafac62802742ee3d26b1f4e887f7d2da4d711ba7f9bb6ca024de7beec1de66bb830ce96d69538f7dcb93c51b26 -9258d2ddc21ab4e3edcde7eb7f6a382a29f1b626003cc6fdd8858be90f4ad13240072d8a8d44ef8de51ca4f477fa6c45 -99d038487821c948142c678acd8c792960993dd8cb5e02cb229153a1ee9f88249f4ad9007f08e5d82e2a71fb96bb5f32 -a88ee9dbc73d3d8e0f447b76fdb3a27936bde479a58d5799176885583dc93830ac58bca9087075950ea75100cf51af23 -88b9b15816e5a0387153c1f4b90f613beb3ea4596037da01a81fdd2bcbd0baf5598db99f77e7694e5a0d35e822758108 -907ae4b637d06b15846ee27d08c9c9af42df261c5bdd10cf5bc71f8e5ca34b33ac2405307023c50bdb8dc7b98a2cd5fe -9393d6900e1d2d1a1e42412fefd99578d9ac1d855c90a3e7930a739085496448609d674ca9b34016ad91f22d1cac538e -a28ac56b216730b7dcdb5ab3fc22d424c21a677db99a9897a89ed253ea83acfd9d83125133f5be6d9cd92298df110af8 -b027590ee8766f1e352f831fda732adbaf77152485223ad5489ef3b0ce2d2e9f98d547c111fe133847ebb738987fb928 -a9cc08fbd5c3fee8f77cf6eb996a5cafa195df5134dab000e4d0312f970a5577942ee89794e618074f49841f1f933a42 -a8b3535c3df0b1a409d3fc740527ee7dd5ac21756115cde6f87f98cc7623f50cfcf16790689cab113ee7c35a5bd4879f -b61420227b97e5603ae8a716c6759b619f02b8fdc48acbf854352aa6519dad74b97bacc1723ca564cbf3ca48539ed773 -853762498de80eebf955a6c8ddd259af463e4e25f0b6ba7b6a27b19bdbf4c585de55760a16e2d9345cdba6b2a02610f3 -a711c1b13fc6c30745203c5d06390e6c82bd7c50f61734aa8d99c626faba30119bc910be63ec916c91ba53f8483c05a8 -b488c0a793f4481f46b5875d96eecd73e46209a91677769f0890c5e002ecd7d4b1c9f4ba68c47fbed40e3857b1d8717a -a651c5e812ae65b1c66d92c607e80be330737ea49c1dcfe019c0ecea0f41a320406935bb09206a4abff0d1c24599b9ad -85e34e7d96e4b97db98a43247b6c244383b11ca10bf4777364acf509a6faa618bc973e2136a4693fbc8ab597e308fd5a -99837214102b394fffa7f3883759554c6bb7a070f5c809303595a44195e02b9a169460dc6bbffb62bdc0e7ced5f0a5c1 -a952f89c0afb4bdae8c62b89cc3cfb60d0576ba4fe01a5d99534792f38d8848d919b3fc7577435d8443a044d2ee0bcfa -a1ac1f81acb29798acdfc493854663519e2d1b0e9d23d286ce33882c34b4c1c0bb43dd9638166d8026315a44d9ec92a8 -ac9c58aa38219ae659d23007cc7b97fd25b7b610b2d81a8f9f94ddb089efc49c049a8ea4c56e6eaf7b6498f422a97b3c -87e61d501c242b484fb9a937ef21d485f6678d75257fc8fe831b528979068cadbe7e12b49c34058ec96d70a9d179ab14 -aa45f6852f35cc8b65a4a8b5380641d2602a4fa4e3a035db9664df3ac2e170b1280c4a8b7b55161430063e54de4158a6 -a46975614ddde6d134753c8d82c381966f87203d6e5a5fb99a93b0d43aa461466b37f07b8d0973a1abd6ee2b40f24348 -8d35f97297773422351f4d99564c1359ef1a10cfb60aa0e6c8985a78f39b4268486312c8ebf9dd2ef50a771aa03158eb -8497c6242102d21e8b3ade9a9896c96308ab39171ab74cbd94e304c47598e2c2a7b0a0822492ac5c076ba91d4176481d -973f8fcb5f26915b3a3ef6fe58cc44bc7f4e115cd0ad9727d8d1b8113e126ae2e253a19922c5433be4ab2311a839c214 -ae3ee9f1d765a9baf54b4617a289c3b24930aa8d57658a6b0b113bbf9b000c4a78499296c6f428bbb64755dfd4f795d2 -a5be7a8e522ef3dcf9d2951220faf22bb865d050f4af2880b8483222ff7aad7c0866219fcc573df9d829c6efbb517f98 -a5f3c7fabd7853a57695c5ad6d5b99167d08b5414e35ed1068ae386e0cb1ee2afbbe4d2b9024379b6fc3b10c39024d36 -978d5592d4798c9e6baceff095413589461267d6a5b56cd558ec85011342da16f4365d879b905168256f61d36d891b1f -b7b6eaffa095ecbd76d6e1e88ceebabaf674d9ef7e331e875c6d9b9faa1762c800ff1ea597c214c28080f67a50a96c1e -8a1ab53ae5ceaa42e06e58dd8faf6c215fc09ba111ca9eeb800612334d30d5971448be90fec62ed194328aadd8c8eecc -a9ca532cac8ace9a9e845382f8a7840bf40cb426f2fcad8a2f40aadbb400b3a74021627cc9351b0966b841b30284962e -8dddeda8854c8e7ddc52676dd1d0fed1da610ed5415ddd7d25b835bd8420a6f83d7b67ec682270c9648b2e2186343591 -888906aac64fd41d5c518a832d4e044fdc430cfe142fd431caf4676cafc58853ce576f098910d729011be0a9d50d67b5 -96a3f886a2824e750b1e2ea5c587132f52a0c5e3ff192260d8783c666206bd8ebd539933816d7cdd97e4bc374e0b1edf -a150a29ffb2632cc7ec560983d9804cd6da3596c0c25956d27eb04776508eae809659fc883834269437871735de5f9ed -81f7ad4d2959d9d4009d1dfbc6fee38f930f163eb5eac11e98dc38bd2f7f224e3f5c767583f8e52d58d34f3417a6cf90 -97ccac905ea7d9c6349132dd0397b6a2de9e57fd2d70f55e50860e019de15c20171a50b28a5c00ef90d43b838253b3d1 -95694f00c21e8a205d6cbda09956b5b6ec9242ec8c799a91f515b07dcc7de3b6f573e2c0ba149f5a83700cda2d1df0f5 -82bbc3c4a3b3997584903db30fffd182a266c7d1df3e913f908d5a53122fa12cf5acd11d915d85d5bd110fcc43cee736 -8d3f24b4949aa1b4162c28dfbb9f813dd1d8b330f71325448dc45ea34d59b69ca95059402aae011e1b5aba6e536bc6ec -92c734c19752d24782331e74c9af97a8399ddfdd32954e91cda7363dba876aca4f730b451c50a8913950420682da8121 -8653d2c79f77b8c7dcdf7e8dee42433998aeedf1b583abfca686d47a854de1b75e9a4351580c96d1a2a9532659203361 -886f0e414cb558c1a534a1916d3531320a9b6024639712ffe18164ce6313993a553e2b9aafe9c0716318f81a5d0bb1da -b31b5efaba5a5020c3bcea0f54860e0688c2c3f27b9b0e44b45d745158f484e474d5d3b1a0044dd6753c7fb4bf8ace34 -b2d615bbdfdc042d6f67a6170127392d99f0e77ae17b0e1be6786ff2f281795f1bf11f83f2e0f8723b5cdd1db1856e09 -a6e014cca531e6ac2922239b5bee39d69d9ba6d0fa96a4b812217dd342657d35606f0b9c5a317efd423cdb1047815e3d -a8921736b69c9fbb29f443715174bac753e908251804620c542fad6cfbfda7bdfe287f2902f30b043a8a4b4818cfdeef -8d73a9949a042ec2dcefa476e454cd9877eee543b1a6b3b96a78ffcff87421e8b26dd54d5b3192ac32073cb36497acc3 -b936a71ee8df0e48867f3790adf55dc8efc6585024128de2495f8873bd00fd9fa0984472125e801ed9c3cdce6698f160 -82f69c06209c28f64874e850601dda56af44ffc864f42efa8f9c6a0758207bf0a00f583840982dec0a517ab899a98e5b -b7a0a14411101473406f30e82f14b13e6efc9699e7193c0be04bb43d1b49e8c54812ce0f9b39131a20379c4c39d3bbe3 -81159c969f38107af3b858d7582b22925a7ccced02fae3698482d7e9cdc6c568e959651991c6cf16c53a997442054b61 -8bf1116a206e0ce9199fcab6ed2b44a9e46e8143bff3ed3f1431f8d55508fe2728b8902670cfd8d9b316f575f288ed9d -a279b2149824b64144eb92f5a36b22036d34a52bd5a66e5da4b61fbc95af6eda8e485c7914f448abd8674fc14d268d9d -8b98279b5f3588d1a2f8589d2756458690a502728800f8d94b28e00df842a101c96ab9c5aee87c5bbe65552c0c383b80 -b4a27a351ec54420f94e0a0a79d7c7a7337940399646631baca93eeab5fd429d7fb39428be77dcbce64a13eaa3c8ca1d -90c08baa29ec8338ffce381eae3d23ce3f6ba54e5242dec21dc3caaed69cac13f2ab5e8d9d719bc95720fa182eee399c -85156d65bb4fef69ffd539ab918b3286105ca6f1c36a74351ab3310b339727483433e8f8784791f47b4ba35ca933c379 -923005013c27209d07c06a6b92b0cbb248a69c5e15c600bbcc643e8dcd2402adebd94dd4cafb44ec422a127e9780aaec -863b23eb5463a6ef5a12039edc2f8e18e3c97b244841bc50af02459b1bcc558367edf2f6e4fe69f45f37887469dd536d -87a4a7708a112724ff9b69ebb25d623b5cae362ae0946daed2ec80e917800dbfcd69f999c253542533242e7b9a5cc959 -8bf4347ceea7f94b53564f26b1a4749a16f13bf71a9e03a546f906f7c423089820ff217066159b0637d9d6824e9c101c -ab07eef925d264145971628a39e4dd93ff849767f68ed06065802cf22756fc6bf384cf6d9ab174bfc1a87bcc37b037aa -8e3f10a42fad43887d522dc76b1480063267991c2457c39f1e790e0c16c03e38a4c8e79a0b7622892464957bf517ebd8 -a8722fc7b1acf0be18f6ddf3ee97a5a9b02a98da5bc1126a8b7bf10d18ee415be9a85668eb604ef5a1f48659bc447eb5 -878d6b2a9c0aca8e2bc2a5eb7dd8d842aa839bbd7754860c396a641d5794eab88a55f8448de7dbddf9e201cbc54fe481 -ada881c167d39d368c1e9b283cf50491c6bfc66072815608ba23ab468cfbd31ca1bd7f140e158e0d9e4d7ebfa670bc2d -a2b48578fa899d77a7ee1b9cb1e228b40c20b303b3d403fd6612649c81e7db5a7313ba9702adc89627b5fd7439f8b754 -8e051280e10551558dcb5522120ac9216281c29071c0371aaa9bde52961fe26b21d78de3f98cb8cd63e65cff86d1b25c -a7c5022047930c958e499e8051056c5244ae03beb60d4ba9fe666ab77a913a067324dfb6debcb4da4694645145716c9d -95cff6ec03e38c5ab0f6f8dccde252d91856093d8429b7494efc7772996e7985d2d6965307c7fdfa484559c129cca9f9 -993eb550d5e8661791f63e2fa259ab1f78a0e3edad467eb419b076a70923fede2e00ddc48a961d20001aaae89fad11e8 -abb2826e4d4b381d64787a09934b9c4fe1d5f5742f90858228e484f3c546e16ee8a2a0b0a952d834a93154a8b18f3d16 -a922ca9f2061996e65ef38a7c5c7755e59d8d5ce27d577abcdd8165b23b4877398d735f9cb470a771335fc7d99ecb7fc -90f22862216f6bc1bbf5437740a47605d1ff5147b1f06f7b13fec446e4c5a4a4a84792cb244a1905f3478a36f8d7065b -87f3d9a86afef5b79ea1ca690ee1ee4bb9754b66f7c50a42ad6b99af7c222c853ca161f440a0a2a60b3b5a54e3493240 -80a9ca9a2d33b9cf61976b3860d79f5d00de89a06ef043d2a52931809018aeb4ce70423cbef375b29c2c750c2c8704c2 -b4e798ef1d615896108dae37ac50c1e859216ab6dbac11653e44d06ce5209057b4b0dd6d31dcfcda87664a23c8ef1cbd -aaed6d1e7c5b1db06f80dae6c24857daadfb0268f20e48a98fba4b76de1ebf65fb84c3be95fd6a418b498f8285ec63bd -aeceaa316c6369492c939f94809bc80e0857abac86c0d85be8066bbf61afbaaec67e28c572437a8d35c49dd596b3134f -b791c3d53ed34a7d1c8aa89b7953e3684c3cd529230824dc529739a5fbe74b58b87f01e56e7a169f61c508237ef67160 -9351f8c80634386c45c0050d2f813193f9d839173be941e2092d729be5403632a2f18dffdc323d69eb0dc31fa31c5866 -97693184d5c0056ae244dfb6709cafa23a795dc22d497a307a7f9cf442d7452024023c54a8d6bda5d90a355ba2c84f3a -85362daa003d23511ca174a8caafe83d52b6436dc4e43c4c049e5388d9211b5cbef3885896914d86d39be0dd1f910511 -a2511b5fa34b24eeb0e1bcbcf872a569d1ff5570fe7b0fb48f5542f7fe57bad808d34b50afa87580866a6cb0eba02f27 -b382e3327eb1401f2d378dbb56ac7250adde0961bd718575a64d264ffd44772c20752d4035c3ba60eb435e160b375e20 -afad8a5d40b536c0720556845a6b257ed42165c14fb4b4a874717d107752f49ed9380c5b048df3aca67287bb8fc411a8 -8fad0c98434ca5373c2d767868f679b76b4a8d04bca8240ea3f388558262c2d61b73b16fc1160932652b5688c25fffcf -83898008b5cbb6f08f8ef3ec179427869682bb4e8d38f6e6a687a214d4a307436afc64ee67d70a5a8ba9730bf839aecc -b85232e79913785fd82b06890706972b4ad7a309489930ae23390d51aa5189731f8a2df24800409a8c36b3dd6fc91275 -a24ff26ec792f3701da4c5638c1fca4fa4dae95b01827d6200d583c4caf17ea3171393ba2a8c23d1ee8b88402916f176 -adc5c7a7ff6b41d6cc386b7fc69d7bb04179bdf267864f9aa577f0f6a88438191fa81ebaf13055c2f2d7290be6421ace -a05e835abd502d31454d40a019010ff90b6b0b1f993075a35c9907aeab7a342ac0ba6144dc9379aada6119157970e9b2 -85ff07ba58463e7f153fc83f11302e9061e648a5cbd272bb0545030b20e11facd8b3ff90c9ac8c280a704fbda5c9d1b0 -a6c735ada8f4587da8cdad7ea3ada01650b5a3ecab8d81daa7a5f5de51ef4a6592b524692584306f06be3f6701f2870c -b138deee4e53ae8d677fae104f713ef1b8babfecec16b6a85785a66a72784eb09d44c3b63567222ade714e98f7d1604e -ae79c1a49dafcdd972acd95d8ad0a35c02adc7fd736d4c44c3cd13df5789d339b5ea16bddbbd43e486a061ab31baa5c0 -ab3cf2371a1d7dcd0ffe3869a0178230964b06694bf258b2073ea66a2afccd845b38485da83d02e1d607d4c5c36b78a8 -ab9609f28a325fd01cb39540e3a714506c44e52ef28ee640f361deb5760aadbb23e804663b0fa20a66e239c33f8d8bb8 -8ed95ea8e76e1b42823d7915a6aae77d93746f846bf602841dfce0e47543a36efb9ee7e5b42c73c3209d911225cc471b -a80b6162036d43811482323f0ce59eb18740e33a63d7c7bbbf3be206985919e5342d53a69df537d43e8b7d7f51e8892f -93c03d0a5083408ba00c125a8a9385213d4c860072f0297857b1235045819b904e07f2425c13a661d0a01d2e53347f4b -a6581200f00f96c461621e1d26b14a23687dd97eb9f7df4ba641a84340ee7306dc1796248fba4804f185947ad13b4385 -8be174018fa40f7e0cedc5ae68f38969eb7695f2205e9c573641e533d56f68c20abf38a23d2f0dcac371e60b21b18615 -857ad4ee3218c647c58f09b8ab22bcc8976f00a768ab1f708618e868e6143474be846422ce2710a0ed39b5155b6f13a1 -a490bec40f322d599f26bcefcdddd8f2ef6576aa737d5ce7e8d5d422741abe749e3e6a48489aed8c560633f72857e3c2 -a9c0ee339621f1c4a2410f9b4d2f03f1b558dae2973807b8bccd920e8feb7f65dfde3e79986b72ad21fcc4567240381d -8592251568e750a430f7d2c6ddbb3ec82a4dd9fd83efe389e69aa177fd97ac2c96c59a6e86db20d8e6f125d65b46c4d3 -a4e2f4aa6a682913b423b097c4069c4e46a1f3af9556b1bfd0580d0fc01e3991488458049e0735b2a629684a79271c8f -8c4f6a3e738cf74112b08b1680be08158013ef8a515a81215d8a36c9b756786d1b4cb4563923463f3329292f4b48bf6d -8bace547353c02ea00dd547eeda7259aa354d4772dd5e0c486c723cf88627b7112e196b879c3c92a9561b674d9fc486d -8d372f4901e25e8db64fa098148d4a4e709b0e9dcb756d0f90dad99dea393054193ae1a33d292a3dd772ff7ba05e4b71 -a8c7ea6a6a031ed23d65639f01f5423190775558f479700597df7ae7e338a6ae5e9b32f470aff20787ac8b7eec84df6c -b6e9dcba240fdbbf66033410a79a2dd3e9e1ffdf2eae949b3a9ed720e939d92339991dc3e70a5ac7d5253f317daf0b7d -974dec4cd61af75721071752c664d9c2a5121f06ff1515c56139a177a3ca825f763b69d431d4607e393fa74dcc91cc58 -958863e6ad583a9d370a6db3639066982e44766904e7afa849b132f6666b7d08ab931131b3bec7a506d6583e93d56767 -8b93a33b5da9b3300c20a96d80b894e3789c77041183c2cb21751579c8c96857f60cfc2f075201b64e95a78985c5b321 -b726cb9f7ef34ddbc2fad82b3b0af0b30cc913e26c5a614ae5c19cc9c55c8e6dae069db5315a8dcb6d987415bb550ca8 -a730f515398a71bddd66cab2ff996659d4e47dfbb08ce7958a41021f76d269b91c7498b708cd14b183a8ef469c772803 -a4eb3b18132eb0f5337f14e01d63ca0bec0db6a43870f800e5491db756c2f5fce519d8dba5528b4bcef550d06b33699c -b1ab6621eec1ee6784e632e214693f39a14f3715991996b883d66200963e065c86fa0667f7bc36b93b40b5d90ff708c2 -80486a26c3532ad6e19f76d8c9344e2626c07363fd495264927cb5935fa9565ece670dc98767afb04af6a9a5c9231075 -8ee20e0df3c84a1c6b0e21bcc325cf99235b747ffe47f17fdfba548a358ca75cbcc331dd50db2311b400ae882256a608 -aef4268959e5541e7ec69c921a1e81a8374d7e44bf1bb2debf4101cf3cd6b7d6ca7f441758b388de96b3e0edb5b97be9 -8793629bd29d689ec94b016de8886cac6e2ca6638911babb22db4a787661422da0639a4e4089ebeb689d173abfe75950 -b487b3551c20a29e9a5abbda8c50ff594826283e443c09e3ae09b914e46060b3f9abf70434444ce1487e2a74e562616b -8f11531cfc5997dd04b997cb87ba1831aa7041d5434fe72de66304e3f165d882fac891391fbb1eb955c65319e65293b6 -b195136875fd02a75676c33cb3e60504d5964f7a9e81f4c8c8fd38af62e2145c55f765b3158664566191188ac678f381 -b374174b0b3eb04fa49eb4ece45173f0db5d829eac370a20a62309566e0f98b18f72f3633626893c053b7be6bfbd2366 -b2a2f6b0cf652775679b2d677048f2ed8c31a3269e6cddcc7a10e3e6fee89e486b50d9d55fbe452b79c4157c0270fb77 -892177c364dc59032594e7a6fd032286ffdf4fa0b9e3baeb37ec839faebfd2fd46c57b2c9bfe9977b59c93a9cc0ead1d -8ab7c0038a7dbb2ef200dbbe9acbc875829ecad4883792d5c6ce283de67ccd9aa935a9cc7b30b2bd9de7fca7bf2a9a05 -83745cfc78ca709835aa6c6a233c2b86fb31e3f9f6a8becf63e501f2841c4366fb7d131b746c9d3291afda714ff05579 -a723dcb67925ef007e8339dc578d2622d9bb77cfda87cca0088854a59414c02338752c56116a6c1281917842e8467c38 -8a098142da0af2254c425fdbbd0d1b1a17b2bd781391ab37f181775524b8563c64ab8a1602aee2ac6c0a82ba11a8b1d1 -b13bd7529a9b351c5d395c794c28bcb0a3167f1c992e8c062eef47be9be27895945231d249c73a0b6949daa295e14944 -a20dcd2fc2222eaae467d9f5db861040f58bcb991a26e5663ac3aa5e1ff13d0010657c5af586cc4621757add2b905073 -b818f660c3cc4e9f273c25ceeabe562c8afa8ff88529c26f2cf45ae6b2813cca5f350e3cbd56f6257c4df41722dabd25 -b225d5987108b24411bc389276f12509a45e86d5ad6b6d929af5274df0be11109c0fed329669a0acafdf3b0beaa8f2ec -91fcb6d04576d3c6bae947bb7843b430e5fb0592ae49b0a65dfa5791f4eaa4bf2c7f436c8de7360f217001c2b4e5c67a -8821f7a1424ca3fdc5d4a5606ad10dfaba6094cf36669fa9f84cf7617e50425405d14980780e1e18a1ecea7913cda896 -990dcb7f38f56521a70cb71bf4522649fcd46ac052c7feabb0748dfcac9f9c0f95d29e070d32af3cd0adbf869535e17b -b0fac1029fe2c1100f24e2f4bf10c7672199fce53513c7dde2e8d9b00702edf0143e0e1dc7ceae7dcc6994edc2422b6f -a514ebb1a33451b4915c05114db0b10168393613744df848b24e43e09f0bda23baefd9d731075198aace586615ac7911 -8b77f7953c2e67049fdca3653b8d8cf3f799677f79b954da02bdad8cc4d6c855c1c7c16b4f6f9ba35f46426ec28b2d84 -875520cfbda16ec5b1d1d00f578a910d0fc052f17870ba093e22e310bb07648d34817cc2b8811b6f52de535f7046a0d0 -b8c77b4be0b430851c4ff69e91cb770db1935d848198601393810ef395efab52deb9d5c6525472bab720273d5e0e7a79 -b6d4d437146671bdea62fb6545395ea3df39f1cdef21b8476b68e7a25aa7354f847740576d6c9f187bbae9941f0ae450 -95c642f1bccdb62cd6a2212dcdd6ff8d49aee426ca08b7cf3a9d15249d24a9eed5533f92a70c84498c0797f8a57efa27 -b617978047ed0f748c305aa7f30c2dacd0db00baa67fe0c5ce346ef0e6991dc7e05f18dcb2702467421f8390f27aa815 -86411c7a00b3e8b43bf22fb061b1f54ad9bbf632cd74395a478218389c0f544668acf3dd7726532d080ca7da9a5f8608 -97bf684a8849626c4710a6992f6c11f6b5406fd4dfe9e6aa502425aaafe9827e2c435aaf9a5d3d2ba3a4c0e8aec79ba4 -8b178e2a125b461d3180906ffba0af3dce614c64058501fdd35243ababf892d6fcdea4834ce42c25d5569452b782a709 -8ebed2c8a25c61da6a6a8cb0d8f5ea179e28869753eacc728f2c076f7aed8598cd3aa0981f120f9e7ea55b3a689ae882 -a6f235b8e655ca3d634740b53d8c0a757ecc75d2b8838b7948997c1985473d01943d935f687b86cee56cd47c8e773443 -a7959c465a9646908b9d8032a589e41a7dd999f2ffc54bb42f22e5f8a4d8c493a31bcc7ea2cac6c8dbcc59acace7181b -96d0532df2e12da20a57cadb6cf5f6c4ee1aa4775629358c25f1d51677a3e96d1fe3b232532324b4f02f941952d4cc68 -90f493473d686b639a30d1ddc9c72eae6e983f1236e162e58e967a477c0654973ea2e1bdf4ba1a44d7247bc1befc2cab -8b2d87876d9c4085102a07ebb41c565ba69acab99ffc03efc18f20e48d3f3bbe4fc6ddab9c78fe479d9ada80504d85ba -829a0fb3200a28e09cacd6c5346000e7786116ddfd898f37dfd17bef454a8abc0fe939ed8735c00769f7f2f33cd4f906 -86194ec9e88ddb7150e8b03e7a535b6e99863fc6762835601efd03615aa97aaeb413cb210e86035086ed852b39c9d019 -b02efd116a7189cb317ceae392bc301ae55470f0489fa89934e182aeb8c67e280299b975786fe9a470bff46827defb9b -87d7c3903bd22b12d815506f150373f518d47dfc6e5fd74347d88b518124c9923d1e4c98defeb3a45d53d50b423e2175 -a1a430406b28254a7d6348bc98e697e9bab43839aa05d53faee97546f84541ea0b559162619b2045182938f69bf61cae -99d243c226c61c6697fb3d2594f3533fa5dfd7cfc87107908cacde337d7a077fa5a9dc702d26081b065edb1227498e65 -800ee5006ab6217161f42db0cfc552a81728bb4fbd7af6e4620ea099a65ef6664184af3f65a07fcec7e965529c5b49bf -91bfd307579cadc8f81009558605be3edbcb8dbba271475803484017f40130b2b216aef4f620d960193be681877d3a53 -96a060459dec458d19a6f8af6e49dc6c7c58c55dd18915c5fce5e0f4b4a422fce3b9632f6059388fe760289abf70f173 -9921a37f3e657222c7fda3588418a9071409711d9f1fccede7494429f02a45fbc52d79fbb64e9ccd518f60d06d0520d3 -81052b0d15773cb75975ca9230ebb2579700e489c7e3f07cd9cde206fef38b8139bd4976d2b4a7840495fc645f96df03 -88ac37ba66d1de5e23878c992e4d54023729e97e77351f50dc5918d738b5a73faf1dc6feec7e85784761836ba1c6f778 -ae1e6072c13060775f6086d1ae1f88b627ffcb810fc0e0e97deea1f3a15ef0aaa52a6dce2563e4beedadc131af2a8281 -8b60a340f5e4f90badf83001b495ac9f13974c3d2054ddcb3e6b8ca99dec5cd63a263e05c282454191ab2e087d5a2911 -832e2d56ba69dbf817b2b9dbd25c1538d5b8dbf5d9bc05e6be85054a423ebb66a71b157e166e0b9444ac171b34b7ccc9 -8586036fc7dde1e7e3ecb61663130c4529866ae9f5f5095b9fccd24a4c70eea899aae5f10ea1ba66d1665b2d83be35b0 -a77969453b5c083a207913272b5b69d4ccbd8718bdf54be8fbe11b4bd0a2168aae3ba8f9362afa69c0ffa28d7e5a2340 -b7fe9568c214baad0ac5f83745611b481f744ec1c4fa78a549b180dcf79633e5ba75dc20055012a13d849eb7a9be57d3 -b01cad1d2a6c51c0ce88243d1f52f95fb5ee315a905079688027511f0c4ecd0563a3a81846709d272fa5ccb9665e8043 -8eae0a21adfc569aa57237654021c2bdb2c6f0f52ccc90a126682c21a1f9413c63d285f92b2b2f8649150a9284bf70b7 -942acc947192b5f3cf60e92383e5d35f79e7a5904e8e9fd1c8a351676c83ad29b0afb6578d555457cf909f8f4d27adfd -a74e092f8628fba9abcabc27e2e9f3d5a9a941dfe50a2dfde2ad179aabc73afd196676925c2d98643ab8b3d02bdb66ad -896159daa2afd757cf3f9d34af248ad68bb3c62e4c9ac49919422727479cf669098f270b9e645607a7d11adad4c889b2 -a428d8370813d78e7a2a24eebd36e9da2f8bb3605e5a39b5fcda939b531c35a8ebaaa642ba556250a37bddeec90326fb -a5fa04eb60a1d5ee9820e78f42f7be15e1c02757b539aead995768c6209684d6c183c71d282e0c12a4c15c03f9a89d4d -93c77d5d220e40affa7269a6915c076c9aef4db552c643ae5d560a79c955b491c6346ca4cf11cbb7fe1894e28d47b065 -802e605d2de745eef6981d88e7a57ef4046a2062725e8080995374cea2b3273c27f35b7774d0dcba014710d8d6c501f2 -82f7169e6ec9b3e2bd450f35ea2e66d06bcf900acf5b73139677b48e078ce2e16599103027b2326770c99c0a690f2015 -b0c8581879439f9b997551233fe2de71aa03604f9cec37a7b18c5854342d9b67be468f3cac4bf6f64fe8a0066248c498 -a3f626848a4db6e9fb01cac90d3362ec521e969ebd5228af694ea3671061476149f13d652942ac1e39f65591fed740f9 -88a8e759b9cbe16a7c16e43f4afa2de6100d2eafa4dee75ccd653ec38c919013d0a6b35c1ee1eaee7c1985b58bcc9e92 -a3d5fc7aaea072798490616552d947e95f49cf02a420314307aafb555287ec607d75589ba24b009cd68299dc6f7942fa -a809cceeb84f9bcf3c3ddafde3041e7bc3b1d14df8830ab849002176a0725e6f16f70774d8962cb0b8ac0dc43c4ac66f -b8f2e46c031cc8fa160a08c2ebdfa85345ed14771b06daa9636b0e7792b7fddbc501dfc85cc626a01104a43a7d3230c3 -b5367e2a521c318b802ce16ceac80c4b8139f73ddb10ddf38433397cda70a86ea1f051cc55626a4e99d27f30f3975ff5 -96d963660121c1441cd13141279cd371a6a0aa18b6a20761b18df60aa9c14e13489afd83695a0921d5232efe72045f07 -80818d492fd85d666bd91aaf6257b86527fdd796773c793407df1d4a0f91d74649a6bab4d15155c36ed4c6e0a32c5636 -931e22918905fd6c230d3d867ea42861f3074d320d14e1929031924c8ac209a5c552b679b24563bb12f9749b4ee983bd -a4de2c333e74ed9bfa3c0bf6a0beb90427abd9aa4221294cda74331646b58ef46ed57cccc8798ba2b9309894b17cfd69 -883881554c1d88c0ed8d3b6dec3d200f6fea69a77ace3e4d6f86b41506a23724b4394ec8384075f9c75c3868ba8a8e8e -aa0539ecf6ec9bf06f24443027f8f24b6b3d8c5b2084248eecd4bcad3c9a69716e1a0d01057f09a65bff1006ac5e157a -856d74d44c943c9e809b42dc493dff20eca03cb0cf5ed45108c69b1f90d8592a53ae8100e99380a274fafad23e74cdfc -9188257446661c88da093b7c5ce998135913f63842d7c1586065377b169ee35b062d925367fb9b909ca971f1188667b1 -8d3aa57cdafbe998938787479f5d590c1484c6dbe94e6c487e57a746ef5252be0eaa5976d6270de7db64b6b92e57a0f7 -b8f4d6997240f9eda5aca0c43323a828d1563c491b3db2087f60ac4120a3fcd06075fb42bb19d0339ab5ee3fb7db25d2 -ad247ea94b8ae1e81eae4c9fd7b39e6601b53cff47b2547ff90a3cca87192eae28408082774a1fd14bf9ab459b7a4f1f -9598598070f8bdbcc49056c40971e673726cd8c1bc4baa0b5124dfb5fb750e7baa7a7df18eae2bd91955ddcb1ec67955 -b874131ab1608667fa60ea29092d090859eed1812e90c609afff96d79e82c5ba546f617f4c96fc32c9bba97431c1e9af -b00750a9cdc75c2a54f0d3cc99b0fe02300754f25166f7ac85ff41ab5e9cfcca33a29be76a480f12a2d410c7cd5032e5 -84b5bd1c90bb6c66755b28ba4af493ca1b0c3a4df9f436aac67d2e07289053f925cf6a149a84e74e1027dc8758150179 -99caf64bd9d193ff306e8ab5da3f1bb2a190a60c3a82099b8d03d17fa810dc53d176c21379f479e828f60d25beb3ffd0 -a8fd9de502f1c261d5733430e5a18d8b7892a98c9529a016fc2ee53892ae965dcd9c75850bcda4c7edb980b8d88e60ea -848c02cac636e047028a3fe8c1bf4066fb7591b96b0340f8fbd476ff01b35fa3e37d309333771a134f24800e5f3f9289 -a1eab1a06dcca3439f0166441e7e7f2f5b56f5f8aa9f45e411c561f556e0fb71c514c06c26ac53b49a576caca5faac3d -aa603f970dcbe953e700e61c151182c8d32cbbb53ceef572ac93383db33a4b098b5c7b267e42d514ca66b740c0925efe -b55fd5301bd700ddb0b4f72fabe9a91ad49759506101fa802ed1677e9553595aa4d2c66f7574e78d21ce882ce0120ae7 -829137bc4da7b4886d3d04d2c39cbf4b1dc40c813ac1adb425c7b9abf9142b516314cab79c68454df5d71994ce416144 -b83a3a22735001f783dd48a01c4fb3598a51ff3987e842b8045c71c035b9e43645a55254ca5911a5676ef4a8af12d056 -8ca8d463deb13f9eef5e533bc39efaeb0c15631282c5c0deee1673b0053a7cccd514af09801dd6c158caa159fe9351ac -a9ffb1427828f3c456b9c8cc50782de1ab0029b9233a0fd998bad0fd014d27e15c4a32d1e16ad41bff748378b5abdf49 -9627e29f725ddd86456aff813976bbc4a836f4deabf5ad9f73d1a260ceb30948824df9c8841e6b3c529652202be181b3 -b52c988647fe3d9276eed3c262e1044f57fbb116c64cf4f207235c205b3fda0f3d789bf90f5217401b468d85fdfda404 -833bbd6e2924f5c4446cb76b881d1434a5badce9eb9b003f85d076e297ad7ef45b822069fe54d17427a348c3263fb838 -a067a36352db6f82a116cb87d3db5f60b18576852409e2076cbbfc7843af78866313a4969385a40271051dd195d51116 -902b99545971f9a103f99d7399acc347ac46fe156166e51deefc0e92aebf5893460c69aeeae11f5af9f49418e289ce6c -9206a0e9ce9b9880f29ef0417c96931985f5d83bb17cebdbba4ff2af81a3d37155b04649426f698aed372e4f669599e6 -b54a5d7c976e45c0b1d44433595eae9d1ae9aeabfd58cd5ecb0c5804756a7b01c9a517754423b4714a3695533a3114c8 -91b612131e84580ece228b81ace83da0269b53f94d3c02a1a0879ebbd81bdc252064b3d03a7e140b43a90f237d9a45a0 -a6cead3b8607eaeafe37135bd6de8fbd16f806c131eb71c8d36bfbe295d45b070255e50dabf076e2c3f6b8699be71d6a -931da21e67b11ba6ce438546a24d063bcd51aebe39b4220a78d9c0aab88b2d37969b5ef3502d835507f9c8d6d006714c -8fda408caa9daf01122a2308b7b9d328f52e1e2f138a8bec30492488f4d710e5e52524a6455a3a2ae2818ec8a610b650 -ad8ad5c189644352d90c462731c46145410e5adf38682bb80f95495dd64d9d13782537d68690847bbb06c6be7175dbc7 -87bb5cc466ade60feb0961421c3fabdc8a7e20f11df8437bfff63d3f8bd25305002a396c9d0fa4fb9a9986d4717f12c4 -827cff72870ba00c29064a7d2b4973f322d6b6de7924c93d8bf8825e7a0e8478c7748f90f5c716bf83c55b2795d315d8 -a225895a8e94229776ceb51b05356291f2dce748be17a60d5aeb33ef8507c368bafe5d1d6eea927f28b9d1422b661b9a -8e011323ce670ff51c964241a6b72e0e0ffbb3ff9bb2762492323fc3a4abf4718091be0945287c7329850e4f74462cde -a2c03c2e5f4e9d3ef361f68b188451994ad1b24de9f323370559c8abfcdc7bffd289d92e78a5f6b104b0a12c84dab2ef -a22b4771116ce22276fab1fec6826610707ce8a342f9f60b079c4e0259dac3cc41c96c560dfd0ada6edd2828f7c0e8d6 -97c17441d0af9be83b42097aa8b7cec84a253b9a2b957214b8fa93c26d2add46144faffa7b8a55312059b10690f711f1 -94bdf348849f31a2737cbae5e5848aee711067bac85c11c2e68b44c398cfafbf3493a3226cd1ddf7a916e7613fc7b6f6 -838f59c6e8469a8ec6fd40b978a3607439aaebe1e50ff707eec72c0b8278af05b477bf12a384b56d03e3d4eb91e56f67 -a1940f0db58185e2b3aedd2b0bc2b73b4a65c68e09b046f38e9dcd4e13c94f5406bea92635190bf315e48ec64eceef2f -b2f4e0ae44e1f1210a91d8f280f17091fa994034ba8c991583f8182a323e9b3001a712e3584fc2d64ecbf2d319d076b2 -9342b89c721338d02c7854cd7466fb24d93d7313b6114ea591e6607439c8ddb911d1cf35f01898e9c557982bdff8f9b6 -8583fcab15be1dd14d5a415f4b14d706c8c62f058500f1344b37730c8be6741779691f87ded3cbcf6516468b373cafb0 -8fa9587c7989646571ad9032f34cedd353caee14f5be5cde1e9e0a1710f90c08faf6fa96a60e1f150f761c9c8ae7417d -8d9ff904cc08141f5a9879f5f77dc600e6edbe859082231a4d819953890199bcc5f940b730ea688332f07e5279d49e1c -b5f82b46e5ef9a2df8d144202d6e2e4f3bdae8e2048d2af5ea7deb3f722fbe6d370401954e74ff0d8cb1010ffb1f38d5 -a3b5b57d435b06ed70530e060002a8fea71746ad07d969ca23f22b5e52624527595b6a6d54b4e953fb7b7596bac378f0 -b90f89390df6d4b7879b915aa3c29b8d779d035033f8873bb7ac54a14ec98f0d08c0e3bf696e2ffa7b5730d736f571f8 -8e81e371b92887e43d95c0dbdcc9575282b26ccebdc8cbf46587e4f2a83b61e9bc0c6d7d1f114b9d21e04fd6c180b12a -8d682947c51dffc6e0fe0a486293c9ed121f441805168236393087cf62f2a429cca60bf0e472564844347d32c6bea27e -a8341ec7dd189fa7168759240224192c58209b53fc961c18082deba217928c399bde08ceae42bffd37c1135b4d14a845 -a94bb076dcc5ee5ec82fac57c5b384c690df12631882bd1b960e1eb8c04f787bc22b7bac315b9dc5a8a098f17f051a0b -ab64e1c6f01b87706c88a3bd974454a438722768de7340b834ccf93ea9880c14ee7c2181432acf51f980d56de73832ee -b7b0058bb724d879e5ad7aed6230297c54cb599ef659e86bf2cc84c38225899fb388391df9b2e6fdf063171937fd8c72 -ae856f4fb74c27cc98b67429186e7df4feb01278cd57bfd3170af6e52e0a23b9e926bf9565a890cfb4ae8f2d590b2cd5 -804b9c6702f0596d328f92fc1ed5a30a7ba17b9204524135001b569233fc4937035031d079f52fd04968f37c24013898 -84274ed1af6bd6a968583995622b4d18c6a2bc703ce0d0edce45bb736529b4836343dcd11911a94a134dca7877e6cab8 -88808098463f7505034c3b6328c8a08186b33f7a981c08376e429dd64b79b97753170531ed078dd265ded4ec0a1ed8d5 -92823bfb23a4eb84d3759e7d717f0c8641ece0927cd2ba8c728c26bb35df2629a838002f353c8d3d75eb19520aab5f25 -8db36bae4d960cdb9c51f419d7ddc81f372e56be605bc96a9d4072b829f05527c37c8f255cc6115300a2a0d2e6568d89 -a8fcdbd7f3b4d7ff04149a209feb75e97149e7efceaa42d66a6b8e432590fe7bd01f1a77fa8b47108f670b612e33fee9 -a9f4c53c62db7e5dbdea6918862d3c6d24b5bd8732a218edf0ba61e9d1861182323d8ecd7bef8f895b42970b492f6e40 -8b95bc7f07818f4d7b409aff8da0b2c2ae136cde386f53a71565cae9fd14c73c13cc1cfd79c0f97cd77839fb738c5b9a -adbd1d11adc756b51a571ddbcbf4392415231ddad93da09acfafee03a9e4f9e1ce3826110619e5271feadfaffce3e793 -95d327c8bb195cdf25fd79c98f9406a6b0316214b1630ebcce95bdaeffafa36fc1accc6882e0e5d13a8db5c0f3c0e61c -8cb2f1e2fb25558869afdacc7bb866544cfdd566cefcd048b48d458a886130bd086ecb7600a960a7f2563c61cb326510 -b3aa8c4bf5b933d89cd74ca7f7176d6624d562d7d58b041328b49d7562a30b489cb606abb3c49e85baf04c28e9cd1f44 -97f9053a85250c420599827297453c2cfde087065b823d9e43139e6a9cac3a2ec40a1b6e2f0726bdc870fff215462f0b -878d5dbe6b881389c2ca126ff66d87127c9aaa3f62f0d2c1ec0ea2b279ac95f8a06710dce166415db227655e2345a04d -b2c33a6b4203e3ca5247f0890e475518317ffc44cfbb1da9a1ba02114e8b752bea618050b876de5cf3b1906140a64471 -a56170c8313d2b5541a795bea9934d4425b185b5c409f0484df6f44f0e4bcbf50b860ff46b7245cd99c1cfa8fc1965b7 -96e2b658e2876a14147385fc423d2702a3cb76962b6b437222cf9cea39ebf4bdc03bbf434b747866d4bf72b4ceefa639 -89c4a74fa2f067e7ae49c84ef782c331bcc9245db7e941804e2e99d12e987b4d25cb827778ad4c3566c4fc68018650b6 -a01d30cea7d01c80ff26650020fab02e78fc3842e2398a81b44b21d58d4e9816166ff4ed2418831fa995a28ff35cb6f1 -b960c80b55a8845bbf24bc3f23b0110ca701f9544ab6a5bb7929330213cb471321e55c390ceca3e24bff69bdb0d331c0 -802c5b13f22be7be0e5db11eb3be0f0ea7f9182c932265060ba05fba20ea093dd2810d3b969ee3e387e60fe6ee834e8d -92478f88ef7435d15e39a97916c736abb28ea318394b88678fddbbaab3eaf31776110936abad116a8ff6ca632dd12043 -a6d3da0370c303001d5ed99d1db8bce1f26b0e442f0f042e36db9674e92dcd6e80465e772f1e669f99221caee3392fe9 -938f04f70a8f947d6df2f0c0e9af3cce0c06edbb3c131970dd60884fc0b0a0959c504a2a36c3ff76dfe919905671626a -a7117e55224230822e9983df2132347eb7208cb6798f291df926ab51e04b1a1f78d5568c9a8924ee6f57426134360f20 -b91074c77ad93fe48dc2b10c0c5a62ca3ab7d98345b919c52d84a9dc419b59fc1b267e1c2d4b2e120016ef84bbdb0cbe -aa175c6b6edf02fe8778762c9575581c0ee6efc9dbf99c291a41444a23a056b893be6c45333d907d0bbe9fb0eef84d08 -ad36dcb4e2ab425aa339ae464b038d550cb11186741dcf257f1b8b80ed4f32ffabbece45e2dc1525d4c3eeed819ea04f -91cb35c1ffa9cd5aebef523edb8325078da3eb5cf9e95c675a76446fc7692aaee6f949de064ca2f3e0f082cc3fa93e20 -82622f9410c143a86bc4d756b3c7b324dc295231ce865de020d61cc0868f2c150a473cea3a5b756b36771ce1032415a5 -a5c29996ad3a53468ece9356a5b4ccb68971ea1c89cf39644f1da2d4a477c2ea99bf791ef902b87c225d8c53d67c4c92 -92893eceed1af34fa92b23dcbab175b6a0188a27dbac9ad3317c4e39955a763cb383ab13fb1c519cde311d8a4d12e8b3 -8a093cb191b94b0200e38d31955f9d240e2be1edcd6810a2396a061f17c3ddc9c4f4d56766ddff4e121be7110e03b869 -93981473df0cb1f4b47c7d9b64e3123dcf1593845b401e619f5d7c70b5dbea375d1ca43fca65845fcf0a6b2e0af43791 -a6beb6b0697070f9562910add88d9ba91992f8da127b27be81868b1596d1012f09ea7ed601b4a6474c921a1a1a6d866c -92026b1ee30f2ed61c9f30337c3356844217926aabdff383c19ca3c21e0bc49811ca5b308012bee4ef250cfae1615800 -ac0ebaea6d35f84dac4ce648af096305ba68a7a0aea0a11ab2fbe3162075444a158433c98141bc92ef3b3400d6deb46a -83046f482dee24ac3ca83373f0d1b82ac1c4beda0f229a9011a81ec659ff5fc1fb105e219975b5c744308c77a24f71e4 -aa5a312c47ff7248dcb9c6ffbe5a0628ccd565c07365c4413734d415cd4fb35772622ed833862dddff520a67c509c6a5 -a02fb88805c34018ac33582e19ed0a7e4616acc3dd0867e5f21914c2031c05c6dca30b8b35b57c2b137750f3878a6f8c -a60528f1f14bf0c496491d46a0fbbd6c343e4eb3f1631e92f96a3c5e5c684091aabe5801df7a67f7c6dfd1b0d35269d4 -a1fd8e7fad8ca05a340c05a051bb0eb4197eed345f4104629a9e38e234b09d789cc5537024615feb4a6177d32d39e39e -8e70e36c1aa070815440e19443f1f04aae23b1b59fdbcba43b47b94a026c82c8f66c5dfe54f826f4d95ee1930cdb8008 -8234c1969fa7e9079661e4ca309b71b1aaa10f4372be0b963205c23a81f5a3d52ec08ba9ff65b37f832b52d631580d61 -a18cb4134127fb37c4abca328cd0047378a2e1423490af2bd3eba9ffcc99ca81a3c22404c0886f21f65c7b93c41d7981 -b46fa45fe538816de776eec086e040005706cb3eca097e290abfb6864e745c879868aac8361894f3c3564373ef9ad55c -b96ca43b96c59e95439f75d1e726a35a9362f0dbd34963b156e103e080a8126a8dc3501f9fd541ff3bcf4677f5c4a86b -a8e8c87c7301613818d57387009e601a7ab5cbdc2890f63d985c30c74f9cea2d0584c116baf0d9cd5594386ee93fc661 -b47e4f1b9153ef0981f813948150f283b47a7346fd9921d51fe8e4daedaef78ddeb4fd467c2ccb7cebd9816243da1c6e -a370c202a99c8441ffe96fad0f801086d4d7cc7b960f6e98cca29ceedf492afddfd0f351c9c4d29ac008bc255ec1a2a8 -8f5e6ce1655d1c059b006174e3f5a55c88e1821c97f9702ad8e8455d46c2a83ae4482f2d43edda74a835686ec45a8a15 -a30421e694930a3b65d397b2720d5f8e1eec2b6e2bb5a28d3f9b0a84db9aabd83850268bae64c2b10e313cccf120151b -8abe87163046f7a9b18e2a3c0b66e258facc1b31431420e0b70354b7a60ebd250a784634a76692e7d6f4330b62114945 -894f033cf077d4eb312e3258d9dca414356271abce1d6094ecce6d018c5fadb1c15d8d69451574ad0701a2876db191c5 -b0923d64f88ffc872654e1a294bb1af8681689c21cf08f39afe51448a68e60a9a0a74ccce9969276a932a52c07d095a3 -b9ca23b5be8725fae7fa710eefd45522889c50c29c26384e00b78a962384f0aeff9d15cb5910e9565da12a577eb7e5ba -b242ccf292757197a9f470f2d80ccddc48c7f1235ba026bc68a93be2738bc968e8a200aff3e2f4807216442eb3fc50dc -adc2c3b375b308524b79a024ff87d122055440643fea6fc0a651bdb312c7cbe6a456afa9d342bc76446d77d8daf08bc2 -ab645955356c2ebf2f3df9da275e01daf0b44a52afc309277d6d9ad1b05484e5ae0d9d41ad485fe481e5e362826a86ae -8de96ac587a4449fcc8b7fd0a51b4b5185d9c2eb3434f94cbadd092de1e26b0f6b3f7b15a37e8424b1429121ddca0ecd -94c70ad4e9b871566f3da98170b665a09788d421818299857cde0853789fb943cbcf7d4b2c95246ea7b72edc56a8e36c -b2574be63497843340700b701d5cc8be6d23125bd62058802ee67cce1f3b5f5602b27c93fea5611f27dc695ac563f042 -869ec89da7850cedd88bcb3a50a15cece233119b31b64a61bf6b2310892ce42d8b473b584b11e61db29ed24ce8033f83 -8fbaa269da8e28e9adf4c1b08f109da786dbe9cba871c32eecbfb10619b7a5d65a26f9bb33e201a8ed20b3de94003fbb -8bf7a059c37242caf7f821a6314e4e4adf799e0dd86b37892a7172598892c07272acebd05b534755c57b51556b2d610f -b4e72645fca459898cdd9214892ed08b5c99f82049c0a30d72bac0b9717caa9c6cc16c3dc7aa6ea4d42dcd2a6c175df6 -a39170da87a3495da55bbb9701c5461f3403447174ed6a4af75712f7ba4ac35f51a4234bc4b94da888a0959ee109c0c7 -b45675b2774ea7696089dbf7a0afe6c22e85fd0e4ef3db508fbaf96c9d07f700c991789206da9309fd291be696357c5f -b52899e3e3f6341eefcbe1291db6664bf3b6e8021d32fb9c3e37b6258a35c1da927747b2ce990937d6f4c6c3e7d020d2 -84e5bdb3dfe19700d79dd3fabb0159ccfa084f7288db836c855b827613ce8071067c8d7ac5cc2b4e88ed7f84b690f6e1 -801477d200b6d12fc6e0a9bab1c8211193ab06e44551e037a9b4c36fc2d4f67760b9ff4eba9a3bc7b6e177e891f64ff6 -b6b71a5116d3c22af26a7530f535e9b7851f25a84e562a8f17a125d55b9b3fc1bd8cfe65bdcbeeb328409521e802051c -8687e21c34d7804c12489d30680d131ce2133e2981bfa993afd8a8eeda958ebd5e6881d342d725338659882d9f21cf98 -a024e97a7c4de32b6383c34431994abc533ecdbd6be9bff836ec1af022f5a86773bf345c6f33273797a61fb70a8fd5d6 -83f784f095da20ce5b31f54d6cb14b32a8a12675f0029289c9cd036b7c87a8077be2d04a62618685720e6ee69c875e97 -b4e9dfe7cb9d9efd3fe00d99ae5e48769d4af4bf43d4e05c0b54c9cfd8bc854de96b8d3ebf4dcc06b9dac66b7471a0de -a08b79f9d4673afcf7f38b57f484f88feb7c908f597663a2417f92c348150c2be6b5603f914eba0d9d5bdd4e5c5572c1 -b0eaf919589988798cb01ba0610cd1b7fa3c08715675ece8ecd5f9ef6d5d7b2c4c8ae1ea7dfd202237171aa3e6f9de74 -abff99a98baae4dd0954052503ce81827781694a5ea8c1149f96a3adde75dc2d630e138598cd2ae7fdc7a654aa17df8f -83e369b8680d8b9d995222b033b4f4f3e3b20e782113c941325c7fa9c742feef8747e4a212d9aa23285a259cc4faef8d -b16d5855dd2716613697eba36e2fae0872aaea6999e91cf6552f93f9a0b85ed4f6ff922a91b50816bd6cf8e7a4513fc9 -848373db600e32e741aa1d37726bbb28956783f89ce2d781e95fb1ee1adf4359968a141678af268077eae4c25503204e -93a0dd0fdac18a31875564505b4e28f9e8bb2915faae666538597731ac56cd77f23f2456461e2f672983fb24ad91f6e0 -ab1ebbe49fa56524b564bc2e43784147073e6ea5d27a9540fbf2e04d0f87c645ed2fd28b3e4982cc4c0af1734ee47a6f -b3ee30b733839edab6f61f0738e3f4afaeccf700d8dc7415684f193b36d70d07acd5780cf539f12e0fbf8d4683be773a -88388f2cbdec47a6b3ae460b69eb0d2130ac14de950c22fd86de03e40d02292bb93cebe62432da39d509c1289f785fef -9370c41a54b68ff486b4cc6329c3a851716ebf1d088d77a6c56dec93a18b8a77b596cde74cc17d2adb2b2f411a2e4bbb -b9083b60dc16531f77b05a955b51a237a8f8c0173d72c352c5ca441b55abbc890b14937e457aaec4be5cbbf80cae0099 -aafff8f6c6ebaad952c65054dfc7c829453ec735331bf8135e06406b7a9f740c9a200dc48bb2175516b41f77dc160121 -b43d31fbbaf10526809e9e5bd8bb47a76e0fabd7852ee7744404559ab89f0f215ff518f3271a6aa972a459cab82ac558 -b581ede48c6ef34e678f91dc4b89507413e00e70712e3e8c32a80eed770ec8d8b98caee9702d068aeaca6f704be57bd8 -8cb0a137e68b001a5ccac61de27cac9fb78d4af7b2f5a00b8d95d33ac19cc50c69e760c5e0330a85c0ded1edce0fe6f9 -b947fca07c7aa6c2bf13048275402b00b77b28f1d0ba4b589fbcede13f93b5b931c588560ab8ceba23bb8e748031b55d -81753cced5ff819901740a9a584334e355b497cb699f0be5a52cd555a4c9f149535c7bb355b54407f7f0ec27de6c2e19 -b3d59273951ce97838c4853ec329782a255b5fc7c848e7992ded1be28a5ada7fa3254123afe32607b9991ec6e0659b08 -86b253de246f82be1cb0cef01e87c3d022ca1829d2cc7e6a160a5afbd3ca6b94d75739b122e3bb16f8bde28a8f3223ba -b728b659fa2d8487e061a37f7d14a4c2d70cc37497a8715695d8d332cb274deee2ce23b9b5f6a7408516c02c3d526a49 -81277b46d98848a45abfbe39842495659dcbb80dee985a4fc91d77d52b815487aa8bb455f411fcce4c3879c7a075a93f -b05b6f1fb4a6e654f0ee6b83e08b58b57059bb0b7c490405bc8d963c4a2d6be39c558917977e554e1e9e3169961cbf3e -88f75fa7d016fb6442551ec071cc1e2beeb3ccd213d16d744f573a82f5d70f41dd1b18af71d5f9e73d87f2f6b7dbe889 -81a46434f1bbd65a661a0ff45a0295b8fd8a42a7969c5953721bc98698b64bddee3f806876d1e9983063fdd0c11f99df -8b4f6d33c510a4c9c7d623d9ae0c9aa631fcb987704726b2a4d8519372123bce3c439202f25b5b47045ec14ce39a21a8 -8d5112b330fb63cf6ef3d2164b404c14ff9907d685015701399a260951912b19b8f270f869df317e9050a127763d7980 -aadab394e84dfb82db15ecd2427f39b62352c3e1647c3bcd14fb24ae830ad0116f0fed87ddb63963b424a4741961386e -81ca4e5600d00a3bda24cbdea7a532a4cbbd893c10e7ff10667c15ffa8138b91667abe5466b31a3dcdd60155c48538c1 -ad943af1b8a5fcfcf309ed8f2f916339f254cd555c71a407a47365a139306286a05a8314e1c70e20a65fccd75d36fa12 -b16597a0b437060a390467bbfab94c0bdd695ae898894f4689f939e30cc2119cc08ecb594546304adf876f4e275ebcd9 -a44a4e0a6693be356065891c27eefa040a1a79475be53d54d5fdcea7e0668ff9b35f850974000ed119f6865aa6faa721 -adef27d1b6e6921f4eaf69c79e2e01f5174f7033eaafdd33edcfa5119af23f3a834ffe1bdf19576581b797abd1865b34 -90c1e9202f3ffe28f8e1f58e9650dc4ff4dbc158005b6f2296ec36147e524b4f2f87f8aafc39db5b006fe0c491c92f45 -ac817cd54288b6f7fe6338415344fc9e7b669414051631ab2f27851c052c044be06bf7235d668e194bef695923256368 -ab14944ef653a14456d4ebc12e3196df3f1b4707c4e50b317b5ccc8ca3a0720f0330609f0e7e71793f6ca01583f38c70 -ad5353f2f380837e5ffdf079350b3d42935a0517861d03af98db5ed3ea8501abd68885c8c65f5a66e944b1874826a450 -8b5583863f84af8443ce8970b02e26cc5d959e47efbf8a66a54106ab165f1f76b36423aee74c7b5402fd1c4d7c1adfe6 -b3b46037eed9fc30e4f8f0da8bdbdcc40a38e22e876ce9fde981883017854aba82c18eb00887d92ad847d30082fe7271 -98a2b6fc90b7ad172e4368c1e54675b75c8bf2096d91c9f2b60b3397d3be3b705aed5389845dbd68f0f84438cd0f7687 -b155e800852a5f90a2eac69cc4483428da1dc2c31588a13c924e60a7616ce9baeb7d4b829c772b260277cadd8ed84719 -b8b92c520a1302b0cf7d993a52e1dacd7f27bda9868d59c55687d995ae676b7070af4c0792a9bc1c2635d44a4fee01bb -96dfe9bde526b8fc829eda825f55168b88e8f4e43d4d708cc3060df03437b46e12a8ac70d7788aa75760f6294d3e84d8 -a3fa66c54e2fa084ced3bd838614c6c33042f492a5745d167a723c60d5e7d6020ffd1747981a23f8b68df21ad8f0fa77 -b573ca10cc41fc04a642f6f62c355a4fda69b94b8e95dbb02fd1ccce4bce1191356e1fd66d372159944eb36a7071f005 -acd0a1c9abddfd0ea223eda1722aaada362d34234455bd1c6be115d41e535b16f12ca428da7820a757fa4c98884a385d -96f242eee99c4db383b8754fa7987c0c159652e1866faec905a8d3f010e0a1ad05bd77b9ea8dfd653738959180f58430 -9215a9b672a5d6e435e0e0a45156e0e20f75cbbdf1d14940fed3ddb63d433bef643796c7a4fff881829ebb2b2eba9460 -b8ad9bfceaf08dc5a874387219ddd1170bc3a5e25ed72d321d59ae713be5ddf9fdfbd3aa7ab163be28dfa0dd14614e19 -a19a1050590bc500b32c502f393e407abc3d8e683d6f6b978873aff3e3299b18b1f6b59e2b0fe237d819dbdfcfdc98ca -a6870fb11d4429686e52e1f44c8dcfc7ea24a020df9570c021578dbc1f9bdc8cf797cb3a72d7fc52805dba35d59f2cd0 -a7be733b64d5c06c127bd1c87250e42bfe30ca91ed8ce51e0b6e377f454e8f6fef7f99bff650695df2fd10c375da349b -a1b97145dab30330eea2cdc8739b2446a3704b64505fcea3dd8a9b4a72edf222e98d967d6fd7f76794acfd97aa091065 -b2127049907d2a3b654d1c940b740bfba3dbaf660f86ea79c2f909af7c9fe2a07a1caeb1be12370aeffaf8faa50f1582 -8a207701214bb28e99b0784e9228b1c34afa701966267fe7110f6f29f5bb41eaae6cdb98844d0400787978fabd224de8 -9925147a383b6f5f814520220ffdbf20b214225882c3ef49b1a1ca677709176ec82466fb9c4be2dfbe5640afb63b014a -8416ad93871623fb555b5390b80de99edaaf317350cc0c1ae9d54d59517074d40061f315cce8ba2026d9c1e6f6a1009f -a315f943deebbf0a2cdbcf3f8323e215a406e9cbfbcc3f6288714cb3a6befb1bf71b2a21ff7a2ec4731c65044c45b6b5 -8213e0c2539c24efd186ffa8b6dd401ad2233bc19166a0623b26dd1e93614bbf792823f5599ac116231e2efde9885709 -8e5cafd2f34a127a4a896f05e4d929eef06972a1826b3566446942198df26d62f7679b987db2b3765d9d8058b1cd85c2 -b5302b399c9cdf912fd59007ad4737255552663b1e56dbe64a7b2ddd88d2093c73ea319b45db2dd49d1e03f5bef1a0ae -a0c2bcfbed4b008e1a56e5d2f2419aa59d7dd0ebd990f1c18588de702ad0fa79f445d69965fa9381e700eda13b309378 -80a44eea1ffe24c26b16b8e2e70ee519258b9ad4b3e83cc4e5cca88ebc48d0160066f8b91d0581095b0de2428390c8b3 -84a90cb9c7d2f799f1c4ed060387a4b793ab41c5c3eaffd3b60face9b9c3bae93cd2017283bf3de1e3dac63d0d84dd42 -81d22febca276a05ba9bbc5591ee087b0491beb35b4d9f8fc0d041d642a574667ddc57660b20f5c568f7d61fdcb41bda -a3ac965ac27a28e102a439b74fbfc157e75fd57620e4c0750a466165f8aeecb2191dcf8e656f7525aa50d9c7c69b0b5c -913c17434ff0d9fc52e2ece4fec71b37d4474a18f3ea26925c1be2b250434d49759f58033ba0fce1c6862c6197930dc4 -ac430559c151a5e461f67b49c7786c97e1653fa8698e9759ddbdd99f5daf17fc5a012ae6330739440880728f24eba7c9 -b10d8e9f8aed9361b042d1398ec74364f7c7c1cc5c7f917060572761138bdbe89bf409389ee3879f93bc8032dd67b308 -937271005a4cc6a6ec134870c1b56471aa84ed4f4af1b3d5f334bc0c42762fae0c9a6a2828d3de6151a76dad7b72781c -a10e4dcf51889f69e6bd4c052f8d4036b9571ced98a3d7d779cbcb9fa5c3a82228566ea7cc1d012bf56dea0a40c5a64c -a0ed026528d9a8bb3201bc9dcd20598933e8c72fd315deea8da63d06e97392aa729d98a55a8a60fa4d5573513ba5c9fe -b723fcd04cddbd4c36feae827a03746ffef251c4f4c55a88beedaeeee194430a99f566f483668a0d88b13e7a4a37f1de -84a2cdceed44828c7c05a6a762edec0165e434e7029df617d6646aba48776e6c3b823f40689cee136536f8c93e08a629 -b786264e3a237ac3a1d56c9f4e87438dfed620c867100fd38b01287f5b755c7820937403bfb86644e082094d3e410a00 -92cc35b2065fca157c7bba54410f8bd85907a01c9f760aa0ddb7a82cb55811d24cb4dc6b725367a6a1c293b809a48ead -a12bbf22b117f00164a42515bc57cc9e6c43cc77fb737ee3d0c0cad94cb50cd3847d61cab469cf8ca76f7958bdcfc771 -85985b00de533bde2a757eddf53be79ea39091d16af3fc92327bcd1cd59bf2bf4411a334da29ad775e8ffaf3cea7d7b8 -af9eb24185b0d330d0ea1d0b0fa78af0dcf42ced81cb0128f16cafdea687a9c5582bb6d7c5744117b271cd0b3303f0b5 -8c8aaa1d85ed6327f85d579767c7a9158d209171b3efcb3e8a9d9e534c078e821b6aade255101d2c9ef6d67ba66f10be -a450518a03ffb40e1df89e0f88fd55b5b06f4872cdfb7ec55f40dc40d9424b3b289866336c195bdd54597d95569e0096 -81e61cc69f93c435bd77f155e80626a9c764dd92b6c76af15c41346527948d8a6ca87d6351a0fe7987e2ee3aa66a9625 -b615e0cebf4fdff4cb23a20c8389c370915ba26aa703b28efe4ab070b1603d1c5b6541684acf46b52a915f6aee447539 -a7f51885c7a71885cc84ef734ecd107e8bf5f7a25131415f671d143cc1de92859e65001125323c7985799993af6c410d -abfbf7a46f32066989c32f774edcc68163f085ca81e94fe8c9fb32f8d451bbb2c20ac45cd8d97f9e618ab40186933b1a -8cf35a522b5cac1934004aa9dd236bc77198d43272888afa860cfc79b4b28dabf7a3c74098f84510897566fdd609aa45 -86aa927df78f7a06a4985eb0a4f0b93529cef14f9fd2812d46abffbf25e618ead14d99c70e3c3bb2e17f3f7fabc9c264 -860f1b4f4a398e9a8bb4739587cf96979cfbbe1687b7e91e5bd1198db726391b09b1a261bf12e96698818f60b5bd3537 -8e7c4ee19ff115881051e8637dce1f5d6c65e865d0c757e8ce41b6d7bcd86c7070cce60649692bbf28c868c7e2e1e2f4 -acf7ba01b0220419f09169ac8d16e5cc13dce08e88c90b8fdfaa33aab417f011a20b79a178d8a9f7211589d2e0affd7d -b404bde8e715aefbb9f20a353b911b79173ef3e2cf0aba98b5ae6190b90597d65043b0b4e014ad9ea6c77da2d213ea12 -97e3615d1c77a402253bb55da2d1cdf82de316cefffe42b1022c94b4818d6dc4a313731db85321c537914bdf716a875c -940e950b96a4096a578c6874d747515936652b9b113a5f27f5a834a610867b05f9881e2679b0b289b8527baa0009b6dd -8de15a13ca236a3a285ce6e6826c502ae7365bbe468b6e8ac67b15b0bb49be0e996f1eec81ef69e4b7f54f8e4779a054 -a12244777eacb08ecd42b5676b3a51153022ab97e9353ace0f47c6054c22de9ba60d2a60f59a36841c2a791cb1b7c288 -94f7580203e39a2642ee2e7c969b9911f011d7f3a90c398e1302d26edb3df03df1d0c43baa1c6cf90dde95296d49e742 -82ead33144aaecab965faf63af384565992f38fc1066e71e33d53f43ac93892e27fe78c4eaca1cccbc53364e26ff31e9 -a0c129e9706d354249a7f8aa664ccd7ede89aa1445c5547410814b56d10dc086720953363ab1da8ff5f1ed5d8e575104 -93b3057bf3f74edc95237781ae012cc4b1d3fd0455565ceaac7110290aa518ac32478ba4eb9851555fa87270fcc84f1f -949c2fd0b94f31f7cbf00c679bd3f6ec1a2f4056654708d39edf1a450b4e19a6e251d0bb24eb765087e698f61d3fca2c -99fd2e50e211ccb66b895eb2fc42f260f3ad5767f04c2fe238b81dae98aa6e3977443a51f4fe7b43f499caabe45699a5 -84fe19626503218f327b5325bfd7c0c3d2614b47d34964aa0259d564e769c6c81502132cc1765b0b31fbe39852706927 -b43287ec29d9010bec4284de58fed48dd1e129bac79f09d45153c9949131782f77b11b0c9f8ee06a39e5e9bbaa8e2c6d -908902f3ed45482df2f94415fc8e5a308057a40c8905d7cbbd58ec4848e19276577b7f7e69e5e684a8b981738e10f7ef -85cc7d9c1eae372b4f88758cd6e21604b4bc9f0794e1e74b6d9de96347f81944d01331385fae7a38e5f6096c1dc23465 -af60288c702082fc258b3dbd6952c6b75c1641a623905f491b1e72f49b9d39b33d150a336450abd3911a4c128166acdf -a7d8ac7e589558c4014369ab6f4c1f2196205b03e4278152ec0dbbd7ba54e803c3369a71d364a773aac8dbbd117e4a13 -9833aed34e48c206e9328073597aee1123f5bec085339b4e6839a389a429bf3042798a31fac1464ce963204adface76b -84631a4f012bbb62133030224b57deb32dcf464cacc8ffde7775adbe68707263ab5527a1c75e597e03aa703ba658b889 -a686a61f6467858a2a4c13e70ad81b1901290d3e51bbc0c6e366f9e652f575e91b11c75f640ccef8b0c6c1b05a43c9a0 -b585f0ffd5144907703b41539bfad7f9f058f5985f63db911064ba6b07af8da2796b84b16db42b8d11135c3f846cd9e2 -b525539516c7bb25f1d7e165f269dc8c9eedbba74df44887e178ab8fd798e2a31f39812ca922d6b64d91564f14012a64 -91e480d7568fd2fae39c35b0a8d623e66a3160fee1dd4e9097255004938b11ac1cd3918dc6a1e5fbcb700c95a547e5e8 -936ef55c69b842b6177de71fa48dc5442bf5132116b214302f8f242ca36a273a6bbfbfaf373777104dadbe8e7da5e970 -8e950c0f6688abdff8a3b8bd77be6da6f2565c7b55711f5860ea62a3ab1d51aac31821c602bc11a45e33c69e7dde3ea4 -90eed4595104a0527f8db1e028ff622ff70db4eae99cf47f6c2a0246ec7b103570a6a9a877e32e9647cc74969006743d -b756344f6c4ea05b792e416d9bd9ce9dd4bd904e7622761f28a85628506bfc9d88a25e5f04db62fad30a92fb1d8d8556 -ad79ba76534c1a02ac3e9b7308d390792984cd75b7e1d0e5e4ff123642d99d4ea1825643091aa8117336333c40d5bd94 -832b08144887de0c0341d84f6945450af8d7a4eb32367d7703118186c1be525df9382ce61fed5f3b65a0bb3449185f7f -a322fb944e46d8e47994820890c94af423674716da810ea1da71e0a7733ad72c22114ca39a4b59c98ce4291a5684c154 -b982851a65140dbea79bd3b5487e236feccee051deddcc17c2853032efca289ddb6eaf64be3dd85a73012fdbe9d2d4f3 -8eed5e230e201830b44b9fadca4e156fe1a16bf840cf29da0f381ea0587b20c226de2465c67e6268973e776809af68e1 -81c8f1c04490f36e41a53ee1b5185cb8adbb37c258fd6c3be8c56835bf574c37183a94d55b6554fca35d6e6dd9af0133 -8c4928724107cc16d36f2976677eac0b852fc4c3c0bb2f9cd4d59cd24a113faf33b2faf405c3fcce25be51d41e42c2c4 -8e4ba842636fdfc4d71f0983538ea5037d420acd26abd12efca48c252eea85544b2fa9fccdfec4e7c2a6359baffa112d -b4315b84700e26dec26f3488d308430fdff4809c10d4c24309627911cbb769ffaad0d1ecccd622dd02194eaf5ba59f91 -ab888308f757faef32648c1db01650dbc9aea248b09d06e6efcc996d395f48ec96f2d54a02de441d753fe8737862d991 -805094cfd77e207d5c75f3cad99f41f763ec15443052cfd758c6a82ba422d831a1103a7f9b100da49c28198279c3d3dc -ad857f33243e4a2cd2a773700def21fc7f94939d1a6d2c2125ecd58fc206ccafb07a2c02a1cfce19857d3654aca2c70c -a4d12d40149953daa70b89a329e918e9d93efb4e8004a9357fe76682dab9662c8507e16db83e849340f05cdb4933a373 -a0dbac2ed4b5d03606524245e8a31080eb5bd3e9a0c51dad88c3b18e3e6bc5d64953a81c8e60425b80107ee6b62b1fb4 -86da05355900f327164a78901f6e3db857531b33b1e855df1a67a9ba222c6b05fdb6b0ffbacaeb1ba5b45ff8979b6b68 -932c9873aa3e226dd922b5a616c75153bd0390ce8f332a414b9c8cb6606c2501a37a2aa88097bc7d8e2c4261706eb38c -accd9cdf07ccdd42033ce3b105e00bfd39e2304b1e3d66f8b1128645634452c20f759ec45adcef2fdf04408f62c4cc04 -b75cfdfc1cb48918752eab17eb579820ee6e71e6667abdb64df834ffc8c1362fbbc23ca2c80dee248fe1fbb72d87dfc8 -88b998c73b00638fde7d3dd650a08c5ab996dac6ac34251337fbff3fb5ae4a25dd20c1a16c987ad7ded19eca23cea891 -8afef0956c942571a27f504553fb312cca9e50ce41b44e0466d0516c5abe4d8acf4594cdb03b1ccdbe3f2e6a9093b713 -9042cd83c5ff261e9ebda26398caa16cac2cb840d19062fa8ae50e044c27104972948318f4c866dc4d578798272d3e49 -ad536719a64570a2cd1d72b6590ea1d02c8c49f259a7867be26c8191445165954bcfad50ea12688ace3fdfb0e98143bd -97c86328d63d297b6bc9718dc1ad5a05b908a750d1c455c700d84315589128ce4eea958aef2bcf0fcf4adbd8e3ce58d1 -8e592cf0802e6a9541eeb654dc55055e11f3d757847285197132935ca35bbb1a9156829a39384dfa6f645ff89eb36738 -ac16c614998944f77590bf3913a010e13f2d3bbf6a172293baf5983506c1a2d89989fb72e598f5bba1ea10a691377c93 -ab8e6f5b46baa6632de3621497bcbdd584decb999fe7d8a3364843a1e0b76497600630b6a24dd30119d8bcbfca29f335 -abe1d3af5279e60122d9cea8cc6581c819d7a0e20e3715da0f6da7e02d13a7653db643bd946e2fa9ba338eca81fbe140 -8c33bd831ecfb18d1d0713e16beba768e9c42df62170c1f8a16764912be77f2ac5915623d1d25e8c462aa9c2f6669ca4 -903692becae4a6409f7bdb127d9b11de57a5739fe24218dcbaa0092648d5332dfeef29a908ee9e43e5e0a51a4c3639bc -92591e90347ae286acd365eba32cd9ad8f20f4c9cad2dc579b195147ff290adf0d776bcb3d4b04a25d68a941fc0c781b -b64bbccf860299aec16e1f95c768a1f337c740bde612e6ba260e393edb8b04540127194761c42597abb9bcb771c576c3 -9194f056ccfdfeb78a11c5347e2255d7a7ebd1251f9aebc0b58feb68d3e03a7dbbb74e3ef7309455853adfb4694bd01a -aa4f15f6d6a53ae65b7f6f91e8981d07a5919d2138679a561f7bb608dc4596e45ca06c9441d51fb678b2ad89ae7a17ae -90e3d18507beb30bde08c5001faf489a19ab545c177efb3f73fbf5605f9a0abcdc8bfbc44f832d6028e3e0a834bea98f -8f31dc0118c8c88a6e79e502d10e57652b7aba8409a5bf572ca63fed6b7cbad7f28bbc92ac2264f649792fc1d0715085 -a307d1067ea4c56437b6f8913aa8fcbf4a24580fc1e3336e7f6518f0f3adb9c4733090e459a3f737414ec0048179c30a -b7cc41fdf89595cd81a821669be712cd75f3a6c7a18f95da7d7a73de4f51bb0b44771c1f7cd3cd949e6f711313308716 -a9dc74e197fe60e8c0db06b18f8fe536381946edecdf31e9bd90e1ebfcad7f361544884e2fe83c23b5632912ec284faf -8b3e1e81326d611567e26ed29108f33ddb838c45bbd1355b3ae7e5d463612af64b63fff9fa8e6f2c14c8806021a5a080 -92f6537bca12778866335acc1eb4c3dfc2c8e7e5cf03399743dcea46aa66cac92ac2963b0892784263ad0ebe26ffdbf6 -b5cc0061f7a3e41513199c7dd91ac60d727366482a4c7328527f7bd4fc3509412f711bb722b4413b3736a219b843d15d -b3e9711d68d2c6f6e2cc27e385d5f603d9a1c9a96edeefa1ffdf390439954d19504d6aadc566b47e229ad4940ef020d2 -a09d0d3f0e5dc73a4a0827b72710b514bbfce4a7fcd5141d498a5aad6c38071077f50d3f91af897d9ab677b7041dedda -b177fe260f3b86e9ac21f1bfbe2682ae5dd8c9aecebb84f37054bdab6e39094e611ce582210ceeddde66adf759dadb6d -b0ac6595eba9f5dc4b2fd21856267cfbcfb5b12aa34ec69ca32b80071c5b652e85c25a224d80443d503bf25fbbfe07e9 -81f3c0e11b196bd4a2e8f07f8c037002566dc9037da81f3988add458a520c24dd1be3d43d851e28c0c6a85de4b57a542 -a44308c95615f7fedb2d2127012924468c015df9f48359cc2e36ab4223870b0bfc1e9040baabefdf5266f93afaad896b -8493ec4c32d5a13b81039f1b436eb83f259945dc950e3c6c2ccf5087ec56dd2f60890ed4edf01728b6a54950e19b35c6 -a1a439ec2a6a95bdac9aaa925ff337ba956c0d236ab5318354270e73ed6b73b4ae2d27b4c1686cf97b6526d04e65be81 -b4659b7b53c55a4b2bbe210b53520b392f893500e18990d843b72d7379d45fb44dd1dd2184348d6fd853d6b9ecc6b7c6 -afb2c68d75d00130b0e1b4f250001920213121791698ec04262db714cf7b1408d39f6cc10421f954845aad5b8250b77e -b22b843b40a97210f94043b552f348f66743055a3f274856a738e7d90a625b80e9bbb80cbbb450e1666eb56b8bd5c60f -800895ced82fe13d5fff65a93b0051c3df698bf1221b682accfdb63e3970f669ca37025750697f4e8ff2a3322ad57be4 -b21f598c50d7b9f4a584d548f85e42055ef8e24991906d973749090261584c7f4f5e984b528926f7e75375dd84d51af8 -849b1c68192d18274598dd6d0bf48fb5ee3b1ba25b331cff2d06f345bef3bed49760ca5690848cf33388f6a9a32cd646 -aeb6fd9478b10ef456f6bbb1e6dd19b14475e65497772d12cfc097948383d3fbd191bf95f046b8bf1989954118e483d0 -b1b5e0ea2835f7fc8b66e7731e392b43d16cbce04b52906b6751ab1b91978899db5fecbdabc23a19dabb253005468136 -91b6b1284770cf6f7ef35bc0b872b76c7763ffcfa68f9c8cfabcb2f264a66d47598bb9293f6a40f4c3dd33c265f45176 -b9ffed029846487c2cfb8a4bb61782bd8a878f3afdb73c377a0ebe63139fa070e3fcdc583eec3a53fdc5a421ff1fa877 -998007249d041b0b40ff546131cfc86d0b3598dcedf9a8778a223f7ed68ba4833b97324cbb1de91292b8ff51beab44b3 -8eb77ce9e0e406bf6f002870fb2fd1447646dd240df9bd485f8e0869298a1fc799d8a41b130c04370e9a9cc5c7540ca5 -853db8157462c46f2af7e8f94f2ed1c9b9a7ba2896b4973296898ff3d523d6e29e0b63a5d26cecd5e490b33c87a4cecf -b1436b6f3278768f0979ee852944258f2599977d255bea6fc912ba17c5dff5bdc850cf3e1fc52be9d6d188e868670f4f -a76acbc5832019b3b35667ab027feff49f01199a80016620f5c463dfcbfb51bf276ed17b7b683158ba450660cc7973eb -94540cdb051faf3ae8b8c52662868c2dab66bd02505c4f5f8eb4d6b2e2e5fd9a610890c5dcf8fd887eee796d2b5753a8 -aa35099666bceccf4eb3b65b13bba88e30a8be93693ab6761d8e5523343e8d6dd42d977e66499352fe4e9e9784a1dd0d -894471aad17be54319083c4b5e40adcfacf7c36c4aab0b671030b7ef321c53590a25eccd836efd20f32a93185fd315bb -8f52a9f705bb0dea958fcfbd52e2b6c08ad0f89a07a6b2942c1b4c37eead0d97a38a9e9aeb08d5d59b7fa2a9347f738b -9031c16b4f936c9cab55585dc5064739f696c3347ee2c0792320c9f749e760d120e396e8485ffc79d81c9f3337ad3d1c -82090a0d0d9b05459ec1c328ecd4707c333b784e3aaa0ef0072cee1eac83f9a653a75d83b9f63512a8c41200494826b4 -92c3a9553001f9ea4d67236b8ad1a33275378202cc1babc03f313895458f4b2549bfbbbdd37bfb8fbff0decb6b9f820a -88651868f4da37338a22bc553388df5dd1dd0cb78c4d7d07c637d8f6faef4bed72476fdcd4304d5bedf3514011135f08 -83fa0141bfebd88063f1d787719721b4c6b19ecf565b866de9d7d5d1a890e0e3d859b364bb65f8f8e688654456a40263 -90a7fab753e5d56dfc0e53a6b4e6ab14508220f3a62b3f3f30570c4c9ad225e74122635826c92e8e3227ec45e551432a -8fa375b0345bf6e5e062d108f9feaec91029345ecac67ccf1264eac77b8654cbfdda1f10579f481889c0e210254eadde -b83f06116da9daebdb013b26724523f077debaf6bc618b48a7a68858a98d275f7899c4ec73a0a827219b9248dd81c8c9 -8be1cada55e0c5ebb4fd460b2d209ae5326285a20c8bdd54ed9d1a87302f4063c8730bfda52d9d40e0d6fe43a0628465 -a68ad6f813743ec13a811f2ef3982c82d9d9ac1f7733936aa1e122f8dc7f4a305cc221579ab8fc170c3f123a1576f9ab -8878f1128214fdbbb8a0edd85223741e021508ab6d36c50d38680f2951ee713ea056ed03f62b9461897963d50ceefe0b -acc0d43d1b0260528b7425b260a5dea445b232b37240759fc65fe26f7c9d8e51569c5722bc33e94de6492f4ba1783504 -ad80b1dd717b076910ee5ceabcb762e75e4d094dc83b93b65c16de1f75bc712cef223c05d5579c1561829406c07a97d9 -a6fc9803f9c09d95fc326cc284f42ea5566255eb215dba8a9afb0be155ea11bcc55938b2d16f01cd2f2eda218c715efb -83ad733dbdfbaae8095a403dbf09130513f4ed4f08dcf8dd76ce83d1ea72999b7eea3a7b731da0d2bc80a83c6ee0e3e0 -8748912fbd08cb34a85416b0937d9c4327e9eed20d6e30aeb024a7253f14f1e0d774f3326e54738d71aae080e28da0fe -8997e78d8acf23051428af67183ae9b2c4aa42b503745ffe33df35a35103c589987e1473ab14dcd28ee78ebcb10d8e95 -a2f340502a7eb3c4a36412e6f028321372c4fa18a4743945607424e932af1271fa3e6598a162c872072529576eba6283 -868ccf19b5044ab93b45c9ed3ae34fcb504fe1453d6c4a1d12c325032cf01eb90356de82080ed897e97dba13cae33a02 -ac8867005fe4354d67aa37b866a7e581d2f94f7bd0b9f4efb5c2d1370ec13147a60692051b02fd00ae60b512bce9b1ff -8fd01886b046819c83c12bb779e432b25ba13713f9227be702074ec3abb2bba6be37220a0a26a4bd4171b99b14e32bc4 -a128981ed199f92b5959975c150a93a62fec50b61c80a3fa0634d90fc8058f76f5cbee77aae6889af12d296b30e613cd -81fe618552ff7a36c9235c6d4066cf2f930b5b38de4089e18166e4a06ca5723eadd1976d25e34b74b3ce942300b23e5b -ab1223ea049e6e0fbf9b611de7fd7c15e5e9637cbd73aa0e36aea08a7503ba6804f2aa807186fdc9aa7f4f9195f72e24 -b97285286981b2665f898abc13f3243b63005bef8db4cab3f658bf6167036b61af400f08db0fc3c640a9c623b760690d -ae3ddff7c1f0fbb6a13dbbc667a61e863c2c7c51c2051e33cd61620142e7e30a7e0c4c1f8fbb512aa3a8640267c6ac26 -99c2a89d5bef236060e51c4f952664094c20fbfca647e5d24a55c1fb8df2f3df58244fbbf3635db07b1c29ee3234fa6f -a5010764d4b9cd3b410638334d1f70c5f4843f45b4f4a9316aaea5fbb2c510a97449dd7a07b49f47334a69d37d9955d3 -86706d011dcdc9e9d165d01fea1df68dd74bedaf15a39f92893c030cafe96f4498c4c1fec2d2136354341b3f440a1462 -88fd57eb62bd7dc35722f3a0576c2138403a2f663a2603482e8974a895cf56ddbb02657dc6b89eb2cf5c1f9d1aff6426 -b0dfd4c68e3acb6bb8a776adaa421fc5e268ed4d5964bb90a727091e5113b55b3f9c6d33cedb3ee47ff7acc5df8b1749 -93b92bc942e1a636fc5c2dc1840de5faf158a113d640d5a475b48e2c56ccccaf9db0e37e90ce74c4b3f5c9ac3b2eb523 -b29a16fa1ea95cbfc1873c435ad40dc8495ba6341801b72bd95d908147dcffb1b4bb426dd635f3af4c88984f56594dd8 -b8f367105e1a2d554ac30200c66aeb579d3d30a8953d20fb6ebba2d876ec39c52ea5d654f1bb89b8ddf3d9d651f31cdf -b5fbc228c983d08adf8612eba5b3db3acff604439226f86aa133b02cce4ffde2f977c8dbb8b446b4375673f71634c89d -a399bea37d3056e0559f6644faa0af93063b4b545d504d7e228d3dbbc294af83d3c4cf37fe026b63899b4e7d50fd08f5 -928ef411a36414b24aea26fdbed4bdb1bb6bdc2d967e2553ce54c7c4e077e76869cea590257645c9129dd55ce025295c -9684a4adeed416a9ce82ad79b55c4a3adcfbd43950bc442ed8a340381caedb70f4baaaf821e3a152f483f965d8f56162 -92558a37f214d6f4cb6d72cd2f4ad24dff9d17611b9e4a41ee5c741a5d1ca9e4053b0584533ef4da206110b5dc3e2a35 -973bf0724d1785cc5e85d2a8ee8c354ad4cf557217ced0b7940f6f064024c20b2bfc5b144c820b5083da4bf70690de4d -adaf1389dfa528210ca9c2657c5ff10d51f7e3b18e93a59c37211be0506c3576cb2c04ec80cd0f82605e53c5a3556620 -85b58b223b09fda6f3ab674d75e780c49eb2167837243df049281e8f4fed653811138b398db9cdfe7405fdb8485602fe -849504d3db408d80745a07e850b0a804607b91a59922a5d3bc40da2748c029c029419cda38d2a4485cc0824c6b2504f0 -a3f4afcb353bc2582a02be758ebf0cd18752410ca2e64231176bfa23828423e0a450a65f241a9ed8eab36cae8d9c567b -ae362786cdf121206537af9590d330abbc6dc328b53cdd145dbed0e5df1364c816aae757c4c81f9d619e3698dd32bcdf -9024cfa5b0101eb02ab97866d5a3832944e5aa6888484cfba3d856576b920787b364fba5956bd7c68a305afedc958201 -8a116df09fed923acefb2aecf38a4fbc4b973ee964d67f03791d70bee6356af43ffca117d4e9463ffaf0e0d5d5e5a69f -9163016175c73f1bbc912ddfe03bd4e1db19c64951c8909ee6befe71a1249d838e0db49f03670bb4c5c9b2ab0fb4fef3 -8f6357318d8d16e7240a02b05ce5a4976b6079d49daa258789c6dbf4a47950ebe9de6411780fab06c7c1f35651433380 -8e63cbae8be7341892dbedee3111adf0307c4ee9e375181aa53478f5ba9cdce164d6ae890e5f480119a3a51c6e989165 -a9782f30674a4874d91bfba7eda63aeb5dbe66b040c768d6a925d8ee135f0655ea56276b105239cc0668fc91ddb68cd1 -8d9d94b61ab84ec08665cbe0244ea41756785df019e453ef078c19380bd44c39d2958e8465c72eacf41eed5696037805 -b1470e6f5d2e314474937cb5a3bc30c8bf5fc3f79014945f6ee895fe20028ffc272f9d3a7320aac93e36c96d8a5454e3 -a444911bbafc71179766594f3606b6eaff041826607fd3192f62dec05cd0f01b78598609a530f6930e8440db66f76713 -a9823d44e2638fca7bcc8796cc91c3eb17f46ad6db9f7f6510e093727614aa3a4f9b2c4011ef91dc1c2d224d08d8d05b -ab86020972c359ab98294212558b4b14862040139876c67fc494184b5c9bcea1dbe32fe0c8dd9e60be9daa304acd599a -b7e5cb685bbdcfdb1e48259a5d68d047846c8a35c5b3f90172fb183d1df40d22eaf0edaca2761a07c29c577000ccfed0 -8c88319dae4b28989817e79e6667fd891181e8d2ed91b9c6b614985bca14b12982462ec58b17be0463c24bbb79dd62a1 -8c1c6867e7107fb2178157c991b9c8b0f90c8d57a51220bf3650438ccabccf62da4db8a9916491e730ff3d0c106496e3 -a00a79bd58da6528b9af033087260f9f3d00519eafb4746b355204ee994e89481591b508eaa5402821083e250d38467b -8785abd7c37690f6aa870ee5c799eef72e398a7898b6767f698515be277b9c2fc1af12ea89b0620a848221343a3b5ec3 -8aadae68543db65cef71d0e230a09508d72061398ef2fabec0f856aacff2125b79c70e620744aaf331faf3dfc8afb9bc -8ff0cd437fcad9630b8a2333176a55e178db4142ec841581590594d74d5b53baeac5fb903fdf7bcf83e245b95b58285e -af274e8fad6b190be4e5dc92d2705ba6ac0d7e1ea29e958a5cdd4cb764de46a56d9eef62c999a16e7c50a50b2d9fe3a8 -865e6ec7d1aa848786d6a7a4e87a24d442311f0810b01ef5a74928ab59fdfd651e48880b49680047e5b0df6b3c7c2ecc -800706baaeb35bf3bc33bdea9a8b5cb00d82df407b3b7e1b781a9359cf44fb410ed311591080181b768aae223d9246aa -a9496389d0780b309c6998374ae159f58a8d0fe9a1c24c36cebcb45b27d818e653b51a8ee1f01e30a9b2c46a548126ef -b5fccf4fc3186661939fbee2e89c2aa0e3a6ad4907bcc98c7750520540c4c183b1bbfcdf47f2f1c5e75c3a30cdf30c75 -a90028e39081b736e628c2230cc1338f9210ed01309a40fdf08d39c10cced2cdf71271013bea6dba3a0444fe47963106 -a0815cbb325a8fecf2e1bcc5046644be32d43a8001bd5d8cf0022e4572cd0d481b3e717002f7ab21e16da5f5d16886d6 -b2024787fcda52abc4138150f15e81f4a5be442929b1651ddccbfd558029912be4d61c3c9b467605fff640edf7392494 -ab5aa60032304a584cc9245a33f528eae7157808dedd1ad83ebae00aadc25dbe1cd5917eb8b6b2c800df15e67bdd4c4d -866643847ef512c5119f2f6e4e3b8d3f4abb885f530bb16fcef0edb698a5b0768905e51536283925b6795a5e68b60ddc -806aa99c9a46ee11cc3ebf0db2344b7515db8c45b09a46a85f8b2082940a6f7263f3c9b12214116c88310e706f8e973a -a6eada8b9ff3cd010f3174f3d894eb8bb19efdbff4c6d88976514a5b9968b0f1827d8ac4fe510fb0ba92b64583734a1e -98480db817c3abbc8b7baedf9bf5674ec4afcfd0cd0fd670363510a426dad1bcf1b1cb3bf0f1860e54530deb99460291 -81ab480187af4a3dfbc87be29eca39b342a7e8e1d1df3fc61985e0e43d8d116b8eac2f1021bde4ae4e5e3606c1b67a21 -8a37df12dc997bf9b800f8fd581a614a1d5e32b843f067d63d1ca7fde2e229d24413d3a8308ec1e8389bf88154adb517 -b045a55ca0bb505bd5e8fcc4cfdd5e9af1a7d5fe7a797c7ede3f0b09712b37f493d3fcf6ef0e759d7e0157db1f583c95 -ad502e53a50691238323642e1d8b519b3c2c2f0fd6a0dd29de231f453be730cf1adc672887d97df42af0a300f7631087 -80597648f10c6d8fcd7421caf4e7f126179633078a1724817d2adc41b783723f302eabc947a7ba7767166dacf4ce8fa1 -aefb56427966c81081999dffbe89f8a0c402041929cd4e83d6612866cfbb97744f4ab802578349fbecc641fa9955e81b -a340e493fb3fb604eab864d4b18a6e40ba657003f1f88787e88e48b995da3d0ab4926ce438bdc8d100a41912a47dace0 -a6d777bfc0895eac541a092e14499ff8bf7156689d916a678b50a1460583b38e68158984bea113a0a8e970d8a6799a85 -90ce469410f0e8cfff40472817eb445770833cdcf2895a69bc32bcf959854d41712599ceb2b0422008d7300b05e62e02 -815c51be91d8516d5adc2fd61b6600957ed07cf5fdc809aa652b059bea8ed179638a19077a3f040334032f0e7900ac8b -b3ec6c0c3c007c49c6b7f7fc2ffd3d3a41cdff5ad3ac40831f53bfc0c799ffeed5f440a27acc5f64432e847cc17dd82e -823637abeab5fb19e4810b045254558d98828126e9a2d5895a34b9e4b4f49ab0a5b3ee2422f1f378995ea05df5516057 -ac05412bcf46c254f6548d8107a63928bba19ab6889de5d331eb68cf4d8ce206055b83af4cb7c6c23b50188391e93f84 -88514163c587068178302bc56e9a8b3ad2fa62afd405db92f2478bb730101358c99c0fe40020eeed818c4e251007de9c -b1e657d0f7772795b3f5a84317b889e8ded7a08ea5beb2ab437bebf56bcb508ae7215742819ed1e4ae3969995fe3b35d -a727d4f03027fe858656ca5c51240a65924915bd8bd7ffa3cfc8314a03594738234df717e78bb55a7add61a0a4501836 -b601682830fc4d48ece2bdc9f1a1d5b9a2879c40c46135f00c2c3ae1187c821412f0f0cfbc83d4e144ddd7b702ca8e78 -b5cfea436aa1f29c4446979272a8637cb277f282825674ddb3acac2c280662fb119e6b2bdd52c4b8dbf2c39b1d2070d6 -85c211645ff746669f60aa314093703b9045966604c6aa75aae28422621b256c0c2be835b87e87a00d3f144e8ab7b5f0 -867628d25bab4cb85d448fd50fdd117be1decdd57292e194a8baa0655978fae551912851660a1d5b9de7a2afbb88ef5c -a4e79c55d1b13c959ff93ddcf1747722c6312a7941a3b49f79006b3165334bab369e5469f1bddebadb12bfaff53806d5 -ac61f0973e84546487c5da7991209526c380e3731925b93228d93a93bce1283a3e0807152354f5fe7f3ea44fc447f8fe -a1aa676735a73a671a4e10de2078fd2725660052aa344ca2eb4d56ee0fd04552fe9873ee14a85b09c55708443182183a -8e2f13269f0a264ef2b772d24425bef5b9aa7ea5bbfbefbcc5fd2a5efd4927641c3d2374d0548439a9f6302d7e4ba149 -b0aacdaf27548d4f9de6e1ec3ad80e196761e3fb07c440909524a83880d78c93465aea13040e99de0e60340e5a5503cd -a41b25ae64f66de4726013538411d0ac10fdb974420352f2adb6ce2dcad7b762fd7982c8062a9bac85cdfcc4b577fd18 -b32d87d5d551f93a16ec983fd4ef9c0efcdae4f5e242ce558e77bcde8e472a0df666875af0aeec1a7c10daebebab76ea -b8515795775856e25899e487bf4e5c2b49e04b7fbe40cb3b5c25378bcccde11971da280e8b7ba44d72b8436e2066e20f -91769a608c9a32f39ca9d14d5451e10071de2fd6b0baec9a541c8fad22da75ed4946e7f8b081f79cc2a67bd2452066a9 -87b1e6dbca2b9dbc8ce67fd2f54ffe96dfcce9609210a674a4cb47dd71a8d95a5a24191d87ba4effa4a84d7db51f9ba0 -a95accf3dbcbf3798bab280cabe46e3e3688c5db29944dbe8f9bd8559d70352b0cfac023852adc67c73ce203cbb00a81 -a835f8ce7a8aa772c3d7cfe35971c33fc36aa3333b8fae5225787533a1e4839a36c84c0949410bb6aace6d4085588b1e -8ef7faa2cf93889e7a291713ab39b3a20875576a34a8072a133fed01046f8093ace6b858463e1e8a7f923d57e4e1bc38 -969ecd85643a16d937f148e15fb56c9550aefd68a638425de5058333e8c0f94b1df338eaab1bd683190bfde68460622b -8982f4c76b782b9b47a9c5aeb135278e5c991b1558e47b79328c4fae4b30b2b20c01204ff1afb62b7797879d9dee48e2 -b5098b7ba813178ced68f873c8c223e23a3283d9f1a061c95b68f37310bca4b2934a3a725fff1de1341c79bb3ba6007e -97b160787009f7b9649ed63db9387d48a669e17b2aba8656792eb4f5685bb8e6386f275476b4dfbb1b4cb0c2a69bc752 -88b69369c71daad6b84fa51a0f64a6962d8c77e555b13c035ad6fa1038e7190af455b1bd61ae328b65d6a14cf3d5f0d5 -af88b87801361f0de26bd2533554ee6f4d8067e3122b54161c313c52cc9eafea00661c5c43e2d533485d1f26da4e5510 -98ab18e3bbcb23ac1e34439849e56009bb765ab2f2558ebfd0a57cbe742169f114bceb930533fb911b22cb5a8fe172bc -9027507f1725d81e5ac0f0854c89ab627df3020fe928cb8745f887bf3310086c58fca1119fd5cd18a7d3561c042d58de -a676583f8a26e6f8991a0791916ce785b596ce372812f5eb7b4243ba9367ea95c797170fdac5b0c5e6b7f6519cc2b026 -b91b0ab32638aef3365035a41c6068e36d2303bfee8640565e16c9a56c21703270fd45946ce663238a72c053eb3f2230 -aaf4cd1ac0a30906dcd2b66b37848c6cc443da511e0b0367fd792887fdaf1500551590440e61d837dbee9d24c9801108 -a06f20a02d3cd76029baad5a12592f181738378a83a95e90470fa7cc82a5ae9d2ed824a20eeb1e96e6edc0619f298688 -a465d379c3481b294efc3f2f940b651c45579607cf72d143b99705eae42103a0279eb3595966453130e18935265e35d6 -892a8af7816a806295278027a956663ea1297118ede0f2a7e670483b81fb14dccacc7a652e12f160e531d806ca5f2861 -b480917c0e8b6e00de11b4416a20af6c48a343450a32ee43224559d30e1fecdece52cc699493e1754c0571b84f6c02c2 -b3182da84c81e5a52e22cebed985b0efc3056350ec59e8646e7fd984cdb32e6ac14e76609d0ffaca204a7a3c20e9f95d -a04ea6392f3b5a176fa797ddec3214946962b84a8f729ffbd01ca65767ff6237da8147fc9dc7dd88662ad0faefdb538c -95c0d10a9ba2b0eb1fd7aa60c743b6cf333bb7f3d7adedce055d6cd35b755d326bf9102afabb1634f209d8dacfd47f1a -a1a583d28b07601541fa666767f4f45c954431f8f3cc3f96380364c5044ff9f64114160e5002fb2bbc20812b8cbd36cb -a1a0708af5034545e8fcc771f41e14dff421eed08b4606f6d051f2d7799efd00d3a59a1b9a811fa4eddf5682e63102ea -ab27c7f54096483dd85c866cfb347166abe179dc5ffaca0c29cf3bfe5166864c7fa5f954c919b3ba00bdbab38e03407d -ac8c82271c8ca71125b380ed6c61b326c1cfe5664ccd7f52820e11f2bea334b6f60b1cf1d31599ed94d8218aa6fbf546 -a015ea84237d6aa2adb677ce1ff8a137ef48b460afaca20ae826a53d7e731320ebdd9ee836de7d812178bec010dd6799 -925418cda78a56c5b15d0f2dc66f720bda2885f15ffafb02ce9c9eed7167e68c04ad6ae5aa09c8c1c2f387aa39ad6d1b -87c00bba80a965b3742deacafb269ca94ead4eb57fdb3ed28e776b1d0989e1b1dba289019cfb1a0f849e58668a4f1552 -948d492db131ca194f4e6f9ae1ea6ebc46ebbed5d11f1f305d3d90d6b4995b1218b9606d114f48282a15661a8a8051ca -8179617d64306417d6865add8b7be8452f1759721f97d737ef8a3c90da6551034049af781b6686b2ea99f87d376bce64 -918e3da425b7c41e195ed7b726fa26b15a64299fe12a3c22f51a2a257e847611ac6cfcc99294317523fc491e1cbe60c4 -a339682a37844d15ca37f753599d0a71eedfbbf7b241f231dd93e5d349c6f7130e0d0b97e6abd2d894f8b701da37cb11 -8fc284f37bee79067f473bc8b6de4258930a21c28ac54aaf00b36f5ac28230474250f3aa6a703b6057f7fb79a203c2c1 -a2c474e3a52a48cd1928e755f610fefa52d557eb67974d02287dbb935c4b9aab7227a325424fed65f8f6d556d8a46812 -99b88390fa856aa1b8e615a53f19c83e083f9b50705d8a15922e7c3e8216f808a4cc80744ca12506b1661d31d8d962e4 -a1cbd03e4d4f58fc4d48fa165d824b77838c224765f35d976d3107d44a6cf41e13f661f0e86f87589292721f4de703fb -b3a5dde8a40e55d8d5532beaa5f734ee8e91eafad3696df92399ae10793a8a10319b6dc53495edcc9b5cfd50a389a086 -996e25e1df5c2203647b9a1744bd1b1811857f742aee0801508457a3575666fcc8fc0c047c2b4341d4b507008cd674c2 -93e0a66039e74e324ee6c38809b3608507c492ef752202fff0b2c0e1261ca28f1790b3af4fdb236f0ed7e963e05c1ec0 -b6084e5818d2d860ac1606d3858329fbad4708f79d51a6f072dc370a21fdb1e1b207b74bc265a8547658bfb6a9569bb3 -a5336126a99c0ecfc890584b2a167922a26cae652dfc96a96ab2faf0bf9842f166b39ceaf396cd3d300d0ebb2e6e0ebf -b8b6f13ce9201decaba76d4eca9b9fa2e7445f9bc7dc9f82c262f49b15a40d45d5335819b71ff2ee40465da47d015c47 -b45df257b40c68b7916b768092e91c72b37d3ed2a44b09bf23102a4f33348849026cb3f9fbb484adfea149e2d2a180ff -a50d38ee017e28021229c4bb7d83dd9cdad27ab3aa38980b2423b96aa3f7dc618e3b23895b0e1379ca20299ff1919bbf -97542cf600d34e4fdc07d074e8054e950708284ed99c96c7f15496937242365c66e323b0e09c49c9c38113096640a1b6 -822d198629697dcd663be9c95ff1b39419eae2463fa7e6d996b2c009d746bedc8333be241850153d16c5276749c10b20 -9217bc14974766ebdfbf6b434dd84b32b04658c8d8d3c31b5ff04199795d1cfad583782fd0c7438df865b81b2f116f9c -93477879fa28a89471a2c65ef6e253f30911da44260833dd51030b7a2130a923770ebd60b9120f551ab373f7d9ed80aa -87d89ff7373f795a3a798f03e58a0f0f0e7deab8db2802863fab84a7be64ae4dcf82ece18c4ddbefccd356262c2e8176 -a3ba26bd31d3cc53ceeced422eb9a63c0383cde9476b5f1902b7fe2b19e0bbf420a2172ac5c8c24f1f5c466eecc615d4 -a0fe061c76c90d84bd4353e52e1ef4b0561919769dbabe1679b08ef6c98dcfb6258f122bb440993d976c0ab38854386b -b3070aa470185cb574b3af6c94b4069068b89bb9f7ea7db0a668df0b5e6aabdfe784581f13f0cf35cd4c67726f139a8c -9365e4cdf25e116cbc4a55de89d609bba0eaf0df2a078e624765509f8f5a862e5da41b81883df086a0e5005ce1576223 -a9036081945e3072fa3b5f022df698a8f78e62ab1e9559c88f9c54e00bc091a547467d5e2c7cbf6bc7396acb96dd2c46 -8309890959fcc2a4b3d7232f9062ee51ece20c7e631a00ec151d6b4d5dfccf14c805ce5f9aa569d74fb13ae25f9a6bbe -b1dc43f07303634157f78e213c2fae99435661cc56a24be536ccbd345ef666798b3ac53c438209b47eb62b91d6fea90a -84eb451e0a74ef14a2c2266ff01bd33d9a91163c71f89d0a9c0b8edfcfe918fc549565509cd96eed5720a438ff55f7f2 -9863b85a10db32c4317b19cc9245492b9389b318cf128d9bbc7ec80a694fcbbd3c0d3189a8cad00cc9290e67e5b361ee -8a150ee474ebe48bdfcac1b29e46ac90dcded8abbe4807a165214e66f780f424be367df5ef1e94b09acf4a00cd2e614d -a6677a373130b83e30849af12475e192f817ba4f3226529a9cca8baaefb8811db376e4a044b42bf1481268c249b1a66e -b969cbf444c1297aa50d1dfa0894de4565161cb1fc59ba03af9655c5bf94775006fe8659d3445b546538a22a43be6b93 -8383167e5275e0707e391645dc9dea9e8a19640ecfa23387f7f6fcaddff5cde0b4090dfad7af3c36f8d5c7705568e8d8 -a353ddbc6b6837773e49bb1e33a3e00ca2fb5f7e1dba3a004b0de75f94a4e90860d082a455968851ef050ae5904452e0 -adeccf320d7d2831b495479b4db4aa0e25c5f3574f65a978c112e9981b2663f59de4c2fa88974fdcabb2eedb7adab452 -afa0eacc9fdbe27fb5e640ecad7ecc785df0daf00fc1325af716af61786719dd7f2d9e085a71d8dc059e54fd68a41f24 -a5b803a5bbe0ca77c8b95e1e7bacfd22feae9f053270a191b4fd9bca850ef21a2d4bd9bcd50ecfb971bb458ff2354840 -b023c9c95613d9692a301ef33176b655ba11769a364b787f02b42ceb72338642655ea7a3a55a3eec6e1e3b652c3a179e -8fa616aa7196fc2402f23a19e54620d4cf4cf48e1adfb7ea1f3711c69705481ddcc4c97236d47a92e974984d124589e5 -a49e11e30cb81cb7617935e8a30110b8d241b67df2d603e5acc66af53702cf1e9c3ef4a9b777be49a9f0f576c65dcc30 -8df70b0f19381752fe327c81cce15192389e695586050f26344f56e451df2be0b1cdf7ec0cba7ce5b911dcff2b9325ae -8fbbc21a59d5f5a14ff455ca78a9a393cab91deb61cf1c25117db2714d752e0054ed3e7e13dd36ad423815344140f443 -a9a03285488668ab97836a713c6e608986c571d6a6c21e1adbd99ae4009b3dde43721a705d751f1bd4ebf1ea7511dfed -b2f32b8e19e296e8402251df67bae6066aeefd89047586d887ffa2eacdf38e83d4f9dc32e553799024c7a41818945755 -942cf596b2278ad478be5c0ab6a2ad0ceafe110263cc93d15b9a3f420932104e462cf37586c374f10b1040cb83b862e0 -aaa077a55f501c875ceae0a27ef2b180be9de660ef3d6b2132eb17256771ce609d9bc8aaf687f2b56ae46af34ad12b30 -90ac74885be1448101cf3b957d4486e379673328a006ea42715c39916e9334ea77117ff4a60d858e2ccce9694547a14f -9256cdfc2339e89db56fd04bd9b0611be0eefc5ee30711bcece4aadf2efcc5a6dcc0cfd5f733e0e307e3a58055dff612 -a4c7384e208a0863f4c056248f595473dcde70f019ddaede45b8caf0752575c241bac6e436439f380ac88eee23a858e9 -a3aa67391781e0736dddc389f86b430b2fc293b7bd56bfd5a8ec01d1dd52ed940593c3ad4ce25905061936da062b0af6 -80299275ec322fbb66cc7dce4482ddd846534e92121186b6906c9a5d5834346b7de75909b22b98d73120caec964e7012 -aa3a6cd88e5f98a12738b6688f54478815e26778357bcc2bc9f2648db408d6076ef73cced92a0a6b8b486453c9379f18 -b07c444681dc87b08a7d7c86708b82e82f8f2dbd4001986027b82cfbed17b9043e1104ade612e8e7993a00a4f8128c93 -af40e01b68d908ac2a55dca9b07bb46378c969839c6c822d298a01bc91540ea7a0c07720a098be9a3cfe9c27918e80e8 -abd8947c3bbc3883c80d8c873f8e2dc9b878cbbb4fc4a753a68f5027de6d8c26aa8fbbafeb85519ac94e2db660f31f26 -a234f9d1a8f0cb5d017ccca30b591c95ec416c1cb906bd3e71b13627f27960f61f41ed603ffbcf043fd79974ec3169a8 -835aaf52a6af2bc7da4cf1586c1a27c72ad9de03c88922ad172dce7550d70f6f3efcc3820d38cd56ae3f7fc2f901f7a0 -ae75db982a45ad01f4aa7bc50d642ff188219652bb8d521d13a9877049425d57852f3c9e4d340ffec12a4d0c639e7062 -b88884aa9187c33dc784a96832c86a44d24e9ffe6315544d47fc25428f11337b9ffd56eb0a03ad709d1bf86175059096 -8492ca5afcc6c0187b06453f01ed45fd57eb56facbeea30c93686b9e1dab8eaabd89e0ccb24b5f35d3d19cd7a58b5338 -9350623b6e1592b7ea31b1349724114512c3cce1e5459cd5bddd3d0a9b2accc64ab2bf67a71382d81190c3ab7466ba08 -98e8bf9bed6ae33b7c7e0e49fc43de135bffdba12b5dcb9ff38cb2d2a5368bb570fe7ee8e7fbe68220084d1d3505d5be -ab56144393f55f4c6f80c67e0ab68f445568d68b5aa0118c0c666664a43ba6307ee6508ba0bb5eb17664817bc9749af0 -827d5717a41b8592cfd1b796a30d6b2c3ca2cdc92455f9f4294b051c4c97b7ad6373f692ddafda67884102e6c2a16113 -8445ce2bb81598067edaa2a9e356eda42fb6dc5dd936ccf3d1ff847139e6020310d43d0fec1fe70296e8f9e41a40eb20 -9405178d965ee51e8d76d29101933837a85710961bb61f743d563ef17263f3c2e161d57e133afac209cdb5c46b105e31 -b209f9ed324c0daa68f79800c0a1338bbaf6d37b539871cb7570f2c235caca238a2c4407961fcb7471a103545495ef2c -92ae6437af6bbd97e729b82f5b0d8fb081ca822f340e20fae1875bdc65694cd9b8c037a5a1d49aa9cae3d33f5bad414e -9445bdb666eae03449a38e00851629e29a7415c8274e93343dc0020f439a5df0009cd3c4f5b9ce5c0f79aefa53ceac99 -93fdab5f9f792eada28f75e9ac6042a2c7f3142ba416bfdb1f90aa8461dbe4af524eee6db4f421cb70c7bc204684d043 -a7f4dc949af4c3163953320898104a2b17161f7be5a5615da684f881633174fb0b712d0b7584b76302e811f3fac3c12f -a8ac84da817b3066ba9789bf2a566ccf84ab0a374210b8a215a9dcf493656a3fa0ecf07c4178920245fee0e46de7c3ec -8e6a0ae1273acda3aa50d07d293d580414110a63bc3fb6330bb2ee6f824aff0d8f42b7375a1a5ba85c05bfbe9da88cb5 -a5dea98852bd6f51a84fa06e331ea73a08d9d220cda437f694ad9ad02cf10657882242e20bdf21acbbaa545047da4ce5 -b13f410bf4cfce0827a5dfd1d6b5d8eabc60203b26f4c88238b8000f5b3aaf03242cdeadc2973b33109751da367069e1 -a334315a9d61b692ad919b616df0aa75a9f73e4ea6fc27d216f48964e7daebd84b796418580cf97d4f08d4a4b51037cd -8901ba9e963fcd2f7e08179b6d19c7a3b8193b78ca0e5cf0175916de873ca0d000cd7ac678c0473be371e0ac132f35a2 -b11a445433745f6cb14c9a65314bbf78b852f7b00786501b05d66092b871111cd7bee25f702d9e550d7dd91601620abb -8c2f7b8e7b906c71f2f154cc9f053e8394509c37c07b9d4f21b4495e80484fc5fc8ab4bdc525bd6cfa9518680ba0d1a2 -b9733cebe92b43b899d3d1bfbf4b71d12f40d1853b2c98e36e635fdd8a0603ab03119890a67127e6bc79afae35b0bef2 -a560f6692e88510d9ba940371e1ada344caf0c36440f492a3067ba38e9b7011caac37ba096a8a4accb1c8656d3c019b3 -ac18624339c1487b2626eef00d66b302bdb1526b6340d6847befe2fdfb2b410be5555f82939f8707f756db0e021ed398 -afd9a3b8866a7fe4f7bc13470c0169b9705fcd3073685f5a6dcff3bdbbc2be50ac6d9908f9a10c5104b0bffc2bc14dad -97f15c92fe1f10949ed9def5dd238bc1429706e5037a0e0afb71c2d0e5845e2fed95a171c393e372077a7c7059f8c0e0 -9453a1d4d09c309b70968ea527007d34df9c4cfd3048e5391aac5f9b64ca0c05dde5b8c949c481cfc83ef2e57b687595 -b80e4b7c379ad435c91b20b3706253b763cbc980db78f782f955d2516af44c07bbfa5888cbf3a8439dc3907320feb25a -8939f458d28fefe45320b95d75b006e98330254056d063e4a2f20f04bcb25936024efe8d436d491ed34b482f9b9ae49c -a9ead2e833f71f7e574c766440c4b3c9c3363698c7ade14499a56003a272832ee6d99440887fa43ccdf80265b9d56b97 -b6547a36934f05ce7b779e68049d61351cf229ae72dc211cc96a2a471b2724782f9355fdb415ea6f0ea1eb84fe00e785 -828bfb3099b7b650b29b0f21279f829391f64520a6ab916d1056f647088f1e50fac9253ef7464eceab5380035c5a59c4 -8d714b9ea650be4342ff06c0256189e85c5c125adf6c7aeca3dba9b21d5e01a28b688fc2116ce285a0714a8f1425c0b8 -8a82eda041b2e72a3d73d70d85a568e035fbd6dc32559b6c6cfdf6f4edcb59a6ba85b6294a721aa0a71b07714e0b99ae -af5665ebc83d027173b14ffb0e05af0a192b719177889fadc9ac8c082fda721e9a75d9ce3f5602dbfd516600ee3b6405 -a68fdddf03d77bebdb676e40d93e59bd854408793df2935d0a5600601f7691b879981a398d02658c2da39dbbf61ef96c -8c001ebc84fcf0470b837a08a7b6125126b73a2762db47bbdc38c0e7992b1c66bac7a64faa1bf1020d1c63b40adc3082 -8553889b49f9491109792db0a69347880a9cf2911b4f16f59f7f424e5e6b553687d51282e8f95be6a543635247e2e2c2 -a2c269d6370b541daf1f23cc6b5d2b03a5fa0c7538d53ae500ef875952fe215e74a5010329ff41461f4c58b32ad97b3d -a5dae097285392b4eba83a9fd24baa03d42d0a157a37fae4b6efc3f45be86024b1182e4a6b6eadcf5efe37704c0a1ae5 -89871a77d2032387d19369933cd50a26bda643e40cfd0ce73febe717a51b39fae981406fd41e50f4a837c02a99524ef9 -8a76d495e90093ec2ac22f53759dc1cf36fbb8370fb586acbd3895c56a90bbf3796bcc4fc422ca4058adf337ead1402e -ad4eb7576c4954d20623c1336c63662c2a6fb46ec6ef99b7f8e946aa47488dcb136eab60b35600f98c78c16c10c99013 -894c2b120cec539feb1d281baaadde1e44beafedeeec29b804473fe024e25c1db652f151c956e88d9081fb39d27e0b19 -9196bd5c100878792444c573d02b380a69e1b4b30cb59a48114852085058a5fd952df4afee3ecceb5c4ede21e1ed4a1a -a996fffc910764ea87a1eedc3a3d600e6e0ff70e6a999cb435c9b713a89600fc130d1850174efe9fc18244bb7c6c5936 -8591bb8826befa8bee9663230d9a864a5068589f059e37b450e8c85e15ce9a1992f0ce1ead1d9829b452997727edcf9d -9465e20bb22c41bf1fa728be8e069e25cda3f7c243381ca9973cbedad0c7b07d3dd3e85719d77cf80b1058ce60e16d68 -926b5ce39b6e60b94878ffeae9ff20178656c375fb9cfe160b82318ca500eb3e2e3144608b6c3f8d6c856b8fe1e2fbcf -a1ef29cbc83c45eb28ad468d0ce5d0fdd6b9d8191ba5ffa1a781c2b232ed23db6b7b04de06ef31763a6bfe377fa2f408 -9328e63a3c8acf457c9f1f28b32d90d0eeadb0f650b5d43486a61d7374757a7ada5fc1def2a1e600fa255d8b3f48036f -a9c64880fcb7654f4dd08f4c90baac95712dd6dd407e17ea60606e9a97dc8e54dd25cb72a9bf3fc61f8d0ad569fe369d -a908eb7b940c1963f73046d6b35d40e09013bfbfbeb2ccd64df441867e202b0f3b625fa32dd04987c3d7851360abdffc -b3947b5ed6d59e59e4472cdb1c3261de1b5278fb7cb9b5fca553f328b3b3e094596861ea526eca02395f7b7358155b7b -99da7f190d37bc58945f981cf484d40fcf0855cf8178e2ce8d057c7f0a9d9f77425fdbce9ef8366f44f671b20fd27d0b -913976d77d80e3657977df39571577fdf0be68ba846883705b454f8493578baa741cfaede53783e2c97cc08964395d83 -8d754a61e5164a80b5090c13f3e936056812d4ae8dc5cc649e6c7f37464777249bc4ae760a9806939131f39d92cca5bf -82ffd098480828a90cb221a8c28584e15904bad477c13b2e2d6ef0b96a861ce4a309a328fe44342365349456ad7c654f -89ae3ce4b0357044579ca17be85d8361bb1ce3941f87e82077dd67e43ec0f95edd4bd3426225c90994a81a99e79490b7 -a170892074016d57c9d8e5a529379d7e08d2c1158b9ac4487ac9b95266c4fd51cb18ae768a2f74840137eec05000dd5a -aafd8acd1071103c7af8828a7a08076324d41ea530df90f7d98fafb19735fc27ead91b50c2ca45851545b41d589d0f77 -8623c849e61d8f1696dc9752116a26c8503fd36e2cbbc9650feffdd3a083d8cdbb3b2a4e9743a84b9b2ad91ac33083f2 -ac7166ddd253bb22cdbd8f15b0933c001d1e8bc295e7c38dc1d2be30220e88e2155ecd2274e79848087c05e137e64d01 -a5276b216d3df3273bbfa46210b63b84cfe1e599e9e5d87c4e2e9d58666ecf1af66cb7ae65caebbe74b6806677215bd0 -88792f4aa3597bb0aebadb70f52ee8e9db0f7a9d74f398908024ddda4431221a7783e060e0a93bf1f6338af3d9b18f68 -8f5fafff3ecb3aad94787d1b358ab7d232ded49b15b3636b585aa54212f97dc1d6d567c180682cca895d9876cacb7833 -ab7cb1337290842b33e936162c781aa1093565e1a5b618d1c4d87dd866daea5cebbcc486aaa93d8b8542a27d2f8694c7 -88480a6827699da98642152ebc89941d54b4791fbc66110b7632fb57a5b7d7e79943c19a4b579177c6cf901769563f2f -a725ee6d201b3a610ede3459660658ee391803f770acc639cfc402d1667721089fb24e7598f00e49e81e50d9fd8c2423 -98924372da8aca0f67c8c5cad30fa5324519b014fae7849001dcd51b6286118f12b6c49061219c37714e11142b4d46de -a62c27360221b1a7c99697010dfe1fb31ceb17d3291cf2172624ebeff090cbaa3c3b01ec89fe106dace61d934711d42d -825173c3080be62cfdc50256c3f06fe190bc5f190d0eb827d0af5b99d80936e284a4155b46c0d462ee574fe31d60983d -a28980b97023f9595fadf404ed4aa36898d404fe611c32fd66b70252f01618896f5f3fda71aea5595591176aabf0c619 -a50f5f9def2114f6424ff298f3b128068438f40860c2b44e9a6666f43c438f1780be73cf3de884846f1ba67f9bef0802 -b1eee2d730da715543aeb87f104aff6122cb2bf11de15d2519ff082671330a746445777924521ec98568635f26988d0c -862f6994a1ff4adfd9fb021925cccf542fca4d4b0b80fb794f97e1eb2964ef355608a98eec6e07aadd4b45ee625b2a21 -8ce69a18df2f9b9f6e94a456a7d94842c61dea9b00892da7cf5c08144de9be39b8c304aeca8b2e4222f87ba367e61006 -b5f325b1cecd435f5346b6bc562d92f264f1a6d91be41d612df012684fdd69e86063db077bc11ea4e22c5f2a13ae7bee -85526870a911127835446cb83db8986b12d5637d59e0f139ad6501ac949a397a6c73bd2e7fba731b1bb357efe068242c -8552247d3f7778697f77389717def5a149fc20f677914048e1ed41553b039b5427badc930491c0bae663e67668038fd1 -a545640ee5e51f3fe5de7050e914cfe216202056cd9d642c90e89a166566f909ee575353cb43a331fde17f1c9021414e -8b51229b53cff887d4cab573ba32ec52668d197c084414a9ee5589b285481cea0c3604a50ec133105f661321c3ca50f5 -8cdc0b960522bed284d5c88b1532142863d97bbb7dc344a846dc120397570f7bd507ceb15ed97964d6a80eccfef0f28e -a40683961b0812d9d53906e795e6470addc1f30d09affebf5d4fbbd21ddfa88ce441ca5ea99c33fd121405be3f7a3757 -a527875eb2b99b4185998b5d4cf97dd0d4a937724b6ad170411fc8e2ec80f6cee2050f0dd2e6fee9a2b77252d98b9e64 -84f3a75f477c4bc4574f16ebc21aaa32924c41ced435703c4bf07c9119dd2b6e066e0c276ff902069887793378f779e0 -a3544bc22d1d0cab2d22d44ced8f7484bfe391b36991b87010394bfd5012f75d580596ffd4f42b00886749457bb6334b -b81f6eb26934b920285acc20ceef0220dd23081ba1b26e22b365d3165ce2fbae733bbc896bd0932f63dcc84f56428c68 -95e94d40a4f41090185a77bf760915a90b6a3e3ace5e53f0cb08386d438d3aa3479f0cd81081b47a9b718698817265cd -b69bd1625b3d6c17fd1f87ac6e86efa0d0d8abb69f8355a08739109831baeec03fd3cd4c765b5ff8b1e449d33d050504 -8448f4e4c043519d98552c2573b76eebf2483b82d32abb3e2bfc64a538e79e4f59c6ca92adff1e78b2f9d0a91f19e619 -8f11c42d6a221d1fda50887fb68b15acdb46979ab21d909ed529bcad6ae10a66228ff521a54a42aca0dad6547a528233 -a3adb18d7e4a882b13a067784cf80ea96a1d90f5edc61227d1f6e4da560c627688bdf6555d33fe54cab1bca242986871 -a24d333d807a48dc851932ed21cbdd7e255bad2699909234f1706ba55dea4bb6b6f8812ffc0be206755868ba8a4af3f9 -a322de66c22a606e189f7734dbb7fda5d75766d5e69ec04b4e1671d4477f5bcb9ff139ccc18879980ebc3b64ab4a2c49 -88f54b6b410a1edbf125db738d46ee1a507e69bc5a8f2f443eb787b9aa7dbd6e55014ec1e946aabeb3e27a788914fb04 -b32ee6da1dcd8d0a7fd7c1821bb1f1fe919c8922b4c1eeed56e5b068a5a6e68457c42b192cbaef5dc6d49b17fa45bc0f -8a44402da0b3a15c97b0f15db63e460506cb8bef56c457166aea5e8881087d8202724c539ef0feb97131919a73aefca8 -b967e3fead6171fa1d19fd976535d428b501baff59e118050f9901a54b12cc8e4606348454c8f0fc25bd6644e0a5532e -b7a0c9e9371c3efbbb2c6783ce2cc5f149135175f25b6d79b09c808bce74139020e77f0c616fa6dcb3d87a378532529d -a54207782ffc909cd1bb685a3aafabbc4407cda362d7b3c1b14608b6427e1696817aeb4f3f85304ac36e86d3d8caa65b -98c1da056813a7bfebc81d8db7206e3ef9b51f147d9948c088976755826cc5123c239ca5e3fe59bed18b5d0a982f3c3f -ae1c86174dfafa9c9546b17b8201719aecd359f5bbeb1900475041f2d5b8a9600d54d0000c43dd061cfda390585726ff -a8ee5a8be0bd1372a35675c87bfd64221c6696dc16e2d5e0996e481fec5cdbcb222df466c24740331d60f0521285f7d3 -8ddadbe3cf13af50d556ce8fc0dd77971ac83fad9985c3d089b1b02d1e3afc330628635a31707b32595626798ea22d45 -a5c80254baf8a1628dc77c2445ebe21fbda0de09dd458f603e6a9851071b2b7438fe74214df293dfa242c715d4375c95 -b9d83227ed2600a55cb74a7052003a317a85ca4bea50aa3e0570f4982b6fe678e464cc5156be1bd5e7bba722f95e92c5 -b56085f9f3a72bea9aa3a8dc143a96dd78513fa327b4b9ba26d475c088116cab13843c2bff80996bf3b43d3e2bddb1d6 -8fa9b39558c69a9757f1e7bc3f07295e4a433da3e6dd8c0282397d26f64c1ecd8eb3ba9824a7cacfb87496ebbb45d962 -879c6d0cb675812ed9dee68c3479a499f088068501e2677caeae035e6f538da91a49e245f5fcce135066169649872bee -91aa9fd3fed0c2a23d1edda8a6542188aeb8abee8772818769bdee4b512d431e4625a343af5d59767c468779222cf234 -a6be0bb2348c35c4143482c7ef6da9a93a5356f8545e8e9d791d6c08ed55f14d790d21ee61d3a56a2ae7f888a8fd46ca -808ee396a94e1b8755f2b13a6ffbedef9e0369e6c2e53627c9f60130c137299d0e4924d8ef367e0a7fad7f68a8c9193c -ad1086028fcdac94d5f1e7629071e7e47e30ad0190ae59aaebfb7a7ef6202ab91323a503c527e3226a23d7937af41a52 -9102bdaf79b907d1b25b2ec6b497e2d301c8eac305e848c6276b392f0ad734131a39cc02ed42989a53ca8da3d6839172 -8c976c48a45b6bc7cd7a7acea3c2d7c5f43042863b0661d5cd8763e8b50730552187a8eecf6b3d17be89110208808e77 -a2624c7e917e8297faa3af89b701953006bf02b7c95dfba00c9f3de77748bc0b13d6e15bb8d01377f4d98fb189538142 -a405f1e66783cdcfe20081bce34623ec3660950222d50b7255f8b3cc5d4369aeb366e265e5224c0204911539f0fa165e -8d69bdcaa5d883b5636ac8f8842026fcc58c5e2b71b7349844a3f5d6fbecf44443ef4f768eac376f57fb763606e92c9f -82fce0643017d16ec1c3543db95fb57bfa4855cc325f186d109539fcacf8ea15539be7c4855594d4f6dc628f5ad8a7b0 -8860e6ff58b3e8f9ae294ff2487f0d3ffae4cf54fd3e69931662dabc8efd5b237b26b3def3bcd4042869d5087d22afcf -88c80c442251e11c558771f0484f56dc0ed1b7340757893a49acbf96006aa73dfc3668208abea6f65375611278afb02a -8be3d18c6b4aa8e56fcd74a2aacb76f80b518a360814f71edb9ccf3d144bfd247c03f77500f728a62fca7a2e45e504c5 -8b8ebf0df95c3f9b1c9b80469dc0d323784fd4a53f5c5357bb3f250a135f4619498af5700fe54ad08744576588b3dfff -a8d88abdaadd9c2a66bc8db3072032f63ed8f928d64fdb5f810a65074efc7e830d56e0e738175579f6660738b92d0c65 -a0a10b5d1a525eb846b36357983c6b816b8c387d3890af62efb20f50b1cb6dd69549bbef14dab939f1213118a1ae8ec2 -8aadf9b895aeb8fdc9987daa937e25d6964cbd5ec5d176f5cdf2f0c73f6f145f0f9759e7560ab740bf623a3279736c37 -99aeda8a495031cc5bdf9b842a4d7647c55004576a0edc0bd9b985d60182608361ed5459a9d4b21aa8e2bd353d10a086 -832c8b3bfcd6e68eee4b100d58014522de9d4cefa99498bc06c6dca83741e4572e20778e0d846884b33439f160932bca -841f56ebefc0823ab484fc445d62f914e13957e47904419e42771aa605e33ab16c44f781f6f9aa42e3a1baf377f54b42 -a6e40271d419e295a182725d3a9b541ffd343f23e37549c51ecaa20d13cf0c8d282d6d15b24def5702bfee8ba10b12ac -8ac00925ac6187a4c5cde48ea2a4eaf99a607e58b2c617ee6f01df30d03fafada2f0469178dd960d9d64cbd33a0087d8 -b6b80916b540f8a0fe4f23b1a06e2b830008ad138271d5ba3cd16d6619e521fe2a7623c16c41cba48950793386eea942 -8412c0857b96a650e73af9d93087d4109dd092ddf82188e514f18fcac644f44d4d62550bfa63947f2d574a2e9d995bbb -b871395baa28b857e992a28ac7f6d95ec461934b120a688a387e78498eb26a15913b0228488c3e2360391c6b7260b504 -926e2d25c58c679be77d0e27ec3b580645956ba6f13adcbc2ea548ee1b7925c61fcf74c582337a3b999e5427b3f752f2 -a165fa43fecae9b913d5dcfc232568e3e7b8b320ce96b13800035d52844c38fd5dbf7c4d564241d860c023049de4bcbc -b4976d7572fd9cc0ee3f24888634433f725230a7a2159405946a79315bc19e2fc371448c1c9d52bf91539fd1fe39574b -a6b461eb72e07a9e859b9e16dfa5907f4ac92a5a7ca4368b518e4a508dc43f9b4be59db6849739f3ef4c44967b63b103 -b976606d3089345d0bc501a43525d9dca59cf0b25b50dfc8a61c5bd30fac2467331f0638fab2dc68838aa6ee8d2b6bc9 -b16ea61c855da96e180abf7647fa4d9dd6fd90adebadb4c5ed4d7cd24737e500212628fca69615d89cb40e9826e5a214 -95a3e3162eb5ea27a613f8c188f2e0dcc5cbd5b68c239858b989b004d87113e6aa3209fa9fad0ee6ecef42814ba9db1a -b6a026ab56d3224220e5bce8275d023c8d39d1bdf7eec3b0923429b7d5ef18cf613a3591d364be8727bb1fa0ba11eabb -949f117e2e141e25972ee9ccdd0b7a21150de7bbf92bbd89624a0c5f5a88da7b2b172ba2e9e94e1768081f260c2a2f8d -b7c5e9e6630287d2a20a2dfb783ffe6a6ff104ff627c6e4e4342acc2f3eb6e60e9c22f465f8a8dc58c42f49840eca435 -872be5a75c3b85de21447bb06ac9eb610f3a80759f516a2f99304930ddf921f34cbffc7727989cdd7181d5fc62483954 -a50976ea5297d797d220932856afdd214d1248230c9dcd840469ecc28ea9f305b6d7b38339fedb0c00b5251d77af8c95 -80b360f8b44914ff6f0ffbd8b5360e3cabe08639f6fe06d0c1526b1fe9fe9f18c497f1752580b30e950abd3e538ad416 -a2f98f9bf7fac78c9da6bb41de267742a9d31cf5a04b2fb74f551084ec329b376f651a59e1ae919b2928286fb566e495 -8b9d218a8a6c150631548e7f24bbd43f132431ae275c2b72676abbea752f554789c5ff4aac5c0eeee5529af7f2b509ef -aa21a243b07e9c7b169598bf0b102c3c280861780f83121b2ef543b780d47aaa4b1850430ee7927f33ece9847c4e0e1a -8a6f90f4ce58c8aa5d3656fe4e05acccf07a6ec188a5f3cde7bf59a8ae468e66f055ac6dfc50b6e8e98f2490d8deedc5 -8e39f77ca4b5149ffe9945ceac35d068760ba338d469d57c14f626dd8c96dbe993dd7011beff727c32117298c95ee854 -83bd641c76504222880183edd42267e0582642c4993fe2c7a20ce7168e4c3cbf7586e1d2d4b08c84d9b0bf2f6b8800b8 -a9d332993cf0c1c55130e5cf3a478eb5e0bfb49c25c07538accc692ef03d82b458750a7b991cc0b41b813d361a5d31e3 -a0fc60e6a6015df9bee04cea8f20f01d02b14b6f7aa03123ab8d65da071b2d0df5012c2a69e7290baae6ed6dd29ebe07 -a2949dde2e48788ceaac7ec7243f287ffe7c3e788cdba97a4ab0772202aeef2d50382bed8bf7eff5478243f7eabe0bda -a7879373ea18572dba6cf29868ca955ffa55b8af627f29862f6487ee398b81fe3771d8721ca8e06716c5d91b9ac587cb -b3c7081e2c5306303524fbe9fe5645111a57dffd4ec25b7384da12e56376a0150ab52f9d9cc6ca7bdd950695e39b766d -a634a6a19d52dcb9f823352b36c345d2de54b75197bcd90528d27830bd6606d1a9971170de0849ed5010afa9f031d5be -88f2062f405fa181cfdb8475eaf52906587382c666ca09a9522537cfebbc7de8337be12a7fd0db6d6f2f7ab5aefab892 -b1f0058c1f273191247b98783b2a6f5aa716cf799a8370627fc3456683f03a624d0523b63a154fe9243c0dfd5b37c460 -ae39a227cc05852437d87be6a446782c3d7fbe6282e25cf57b6b6e12b189bdc0d4a6e2c3a60b3979256b6b5baf8f1c5f -802a1af228ab0c053b940e695e7ef3338f5be7acf4e5ed01ac8498e55b492d3a9f07996b1700a84e22f0b589638909cd -a36490832f20e4b2f9e79ee358b66d413f034d6a387534b264cdeac2bca96e8b5bcbdd28d1e98c44498032a8e63d94d2 -8728c9a87db2d006855cb304bba54c3c704bf8f1228ae53a8da66ca93b2dac7e980a2a74f402f22b9bc40cd726e9c438 -a08f08ab0c0a1340e53b3592635e256d0025c4700559939aeb9010ed63f7047c8021b4210088f3605f5c14fb51d1c613 -9670fd7e2d90f241e8e05f9f0b475aa260a5fb99aa1c9e61cd023cbad8ed1270ae912f168e1170e62a0f6d319cf45f49 -a35e60f2dd04f098bf274d2999c3447730fe3e54a8aff703bc5a3c274d22f97db4104d61a37417d93d52276b27ef8f31 -859df7a21bc35daec5695201bd69333dc4f0f9e4328f2b75a223e6615b22b29d63b44d338413ca97eb74f15563628cb7 -b2b44ad3e93bc076548acdf2477803203108b89ecc1d0a19c3fb9814d6b342afc420c20f75e9c2188ad75fdb0d34bb2d -941173ee2c87765d10758746d103b667b1227301e1bcfecef2f38f9ab612496a9abd3050cef5537bf28cfecd2aacc449 -92b0bea30ebed20ac30648efb37bac2b865daaa514316e6f5470e1de6cb84651ff77c127aa7beed4521bda5e8fc81122 -af17bf813bb238cf8bb437433f816786612209180a6c0a1d5141292dc2d2c37164ef13bfc50c718bfcc6ce26369298a2 -8461fd951bdfda099318e05cc6f75698784b033f15a71bce26165f0ce421fd632d50df9eeced474838c0050b596e672c -83281aa18ae4b01e8201e1f64248cc6444c92ee846ae72adb178cef356531558597d84ff93a05abf76bfe313eb7dbe86 -b62b150f73999c341daa4d2f7328d2f6ca1ef3b549e01df58182e42927537fc7971c360fe8264af724f4c0247850ef12 -a7022a201f79c012f982b574c714d813064838a04f56964d1186691413757befeeaada063e7884297606e0eea1b1ed43 -a42ac9e8be88e143853fd8e6a9ff21a0461801f0ac76b69cca669597f9af17ecb62cccdcdcbe7f19b62ab93d7f838406 -80f1ca73b6ba3a2fbae6b79b39c0be8c39df81862d46c4990c87cbf45b87996db7859d833abc20af2fcb4faf059c436a -b355943e04132d5521d7bbe49aea26f6aa1c32f5d0853e77cc2400595325e923a82e0ff7601d1aee79f45fd8a254f6ae -87142c891d93e539b31d0b5ead9ea600b9c84db9be9369ff150a8312fe3d10513f4c5b4d483a82b42bc65c45dd9dd3bd -823c3d7f6dda98a9d8c42b3fee28d3154a95451402accadb6cf75fc45d2653c46a569be75a433094fa9e09c0d5cf1c90 -b3c3497fe7356525c1336435976e79ec59c5624c2fb6185ee09ca0510d58b1e392965e25df8a74d90d464c4e8bb1422b -88c48d83e8ddc0d7eea051f3d0e21bc0d3a0bb2b6a39ece76750c1c90c382a538c9a35dc9478b8ceb8157dcccbbf187a -93da81a8939f5f58b668fefdc6f5f7eca6dc1133054de4910b651f8b4a3267af1e44d5a1c9e5964dc7ab741eb146894b -8b396e64985451ac337f16be61105106e262e381ea04660add0b032409b986e1ac64da3bc2feae788e24e9cb431d8668 -9472068b6e331ea67e9b5fbf8057672da93c209d7ded51e2914dbb98dccd8c72b7079b51fd97a7190f8fc8712c431538 -ac47e1446cb92b0a7406f45c708567f520900dfa0070d5e91783139d1bfc946d6e242e2c7b3bf4020500b9f867139709 -896053706869fb26bb6f7933b3d9c7dd6db5c6bd1269c7a0e222b73039e2327d44bda7d7ae82bf5988808b9831d78bcd -a55e397fa7a02321a9fe686654c86083ecedb5757586d7c0250ec813ca6d37151a12061d5feca4691a0fd59d2f0fdd81 -ae23f08ac2b370d845036518f1bddb7fea8dc59371c288a6af310486effeb61963f2eef031ca90f9bdbcf0e475b67068 -b5462921597a79f66c0fec8d4c7cfd89f427692a7ce30d787e6fd6acd2377f238ec74689a0fdbe8ef3c9c9bd24b908dc -ae67e8ea7c46e29e6aae6005131c29472768326819aa294aaf5a280d877de377b44959adb1348fa3e929dcbc3ae1f2c0 -84962b4c66500a20c4424191bdfb619a46cda35bdb34c2d61edcb0b0494f7f61dd5bf8f743302842026b7b7d49edd4b5 -846f76286dc3cc59cb15e5dabb72a54a27c78190631df832d3649b2952fa0408ecde7d4dfdae7046c728efa29879fb51 -8f76c854eaee8b699547e07ad286f7dadfa6974c1328d12502bd7630ae619f6129272fdd15e2137ffef0143c42730977 -8007b163d4ea4ec6d79e7a2aa19d06f388da0b3a56f3ee121441584e22a246c0e792431655632bf6e5e02cb86914eebf -ac4d2cecc1f33e6fb73892980b61e62095ddff5fd6167f53ca93d507328b3c05440729a277dc3649302045b734398af1 -92d2a88f2e9c9875abaff0d42624ccb6d65401de7127b5d42c25e6adccd7a664504c5861618f9031ced8aeb08b779f06 -a832c1821c1b220eb003fc532af02c81196e98df058cdcc9c9748832558362915ea77526937f30a2f74f25073cb89afb -b6f947ab4cc2baec100ed8ec7739a2fd2f9504c982b39ab84a4516015ca56aea8eef5545cfc057dd44c69b42125fb718 -b24afacf2e90da067e5c050d2a63878ee17aaf8fd446536f2462da4f162de87b7544e92c410d35bf2172465940c19349 -b7a0aa92deac71eaab07be8fa43086e071e5580f5dbf9b624427bdd7764605d27303ae86e5165bed30229c0c11958c38 -b0d1d5bfa1823392c5cf6ed927c1b9e84a09a24b284c2cd8fcb5fda8e392c7c59412d8f74eb7c48c6851dff23ae66f58 -a24125ef03a92d2279fb384186ca0274373509cfec90b34a575490486098438932ee1be0334262d22d5f7d3db91efe67 -83e08e5fba9e8e11c164373794f4067b9b472d54f57f4dbe3c241cf7b5b7374102de9d458018a8c51ab3aed1dddf146f -9453101b77bb915ed40990e1e1d2c08ea8ec5deb5b571b0c50d45d1c55c2e2512ec0ceca616ff0376a65678a961d344d -92a0516e9eb6ad233d6b165a8d64a062ce189b25f95d1b3264d6b58da9c8d17da2cd1f534800c43efcf2be73556cd2ff -958d0b5d7d8faf25d2816aa6a2c5770592ad448db778dd9b374085baa66c755b129822632eaabcb65ee35f0bf4b73634 -90a749de8728b301ad2a6b044e8c5fd646ccd8d20220e125cba97667e0bb1d0a62f6e3143b28f3d93f69cdc6aa04122a -84bd34c8d8f74dec07595812058db24d62133c11afed5eb2a8320d3bfc28e442c7f0cfd51011b7b0bb3e5409cb7b6290 -aecc250b556115d97b553ad7b2153f1d69e543e087890000eaa60f4368b736921d0342ce5563124f129096f5d5e2ca9d -977f17ac82ed1fbf422f9b95feb3047a182a27b00960296d804fd74d54bb39ad2c055e665c1240d2ad2e06a3d7501b00 -af5be9846bd4879ebe0af5e7ad253a632f05aedfe306d31fe6debe701ba5aa4e33b65efc05043bc73aadb199f94baed4 -9199e12ec5f2aaaeed6db5561d2dcc1a8fe9c0854f1a069cba090d2dff5e5ba52b10c841ccbd49006a91d881f206150d -8f4a96a96ed8ceaf3beba026c89848c9ca4e6452ce23b7cf34d12f9cc532984a498e051de77745bdc17c7c44c31b7c30 -af3f2a3dbe8652c4bfca0d37fb723f0e66aab4f91b91a625114af1377ad923da8d36da83f75deb7a3219cd63135a3118 -a6d46963195df8962f7aa791d104c709c38caa438ddd192f7647a884282e81f748c94cdf0bb25d38a7b0dc1b1d7bbcf7 -86f3de4b22c42d3e4b24b16e6e8033e60120af341781ab70ae390cb7b5c5216f6e7945313c2e04261a51814a8cb5db92 -b9f86792e3922896cfd847d8ff123ff8d69ecf34968fb3de3f54532f6cd1112b5d34eeabdca46ae64ad9f6e7e5b55edc -83edfbcbc4968381d1e91ab813b3c74ab940eaf6358c226f79182f8b21148ec130685fd91b0ea65916b0a50bccf524ea -93b61daca7a8880b7926398760f50016f2558b0bab74c21181280a1baf3414fc539911bb0b79c4288d29d3c4ad0f4417 -ad541aeb83a47526d38f2e47a5ce7e23a9adabe5efeae03541026881e6d5ef07da3ac1a6ed466ca924fa8e7a91fcff88 -ac4bba31723875025640ed6426003ed8529215a44c9ffd44f37e928feef9fc4dfa889088131c9be3da87e8f3fdf55975 -88fa4d49096586bc9d29592909c38ea3def24629feacd378cc5335b70d13814d6dac415f8c699ee1bf4fe8b85eb89b38 -b67d0b76cbd0d79b71f4673b96e77b6cda516b8faa1510cfe58ff38cc19000bb5d73ff8418b3dab8c1c7960cb9c81e36 -98b4f8766810f0cfecf67bd59f8c58989eb66c07d3dfeee4f4bbce8fd1fce7cc4f69468372eaec7d690748543bd9691d -8445891af3c298b588dec443beacdf41536adb84c812c413a2b843fd398e484eb379075c64066b460839b5fe8f80177c -b603635c3ed6fdc013e2a091fc5164e09acf5f6a00347d87c6ebadb1f44e52ff1a5f0466b91f3f7ffc47d25753e44b75 -87ec2fc928174599a9dafe7538fec7dcf72e6873b17d953ed50708afff0da37653758b52b7cafa0bf50dfcf1eafbb46c -b9dbd0e704d047a457d60efe6822dc679e79846e4cbcb11fa6c02079d65673ee19bbf0d14e8b7b200b9205f4738df7c7 -9591ec7080f3f5ba11197a41f476f9ba17880f414d74f821a072ec5061eab040a2acba3d9856ff8555dfe5eaeb14ca19 -b34c9d1805b5f1ce38a42b800dec4e7f3eb8c38e7d2b0a525378e048426fed150dbfe9cc61f5db82b406d1b9ff2d10bf -a36fdc649dc08f059dfa361e3969d96b4cc4a1ebf10b0cd01a7dd708430979e8d870961fef85878f8779b8e23caafb18 -88dfc739a80c16c95d9d6f73c3357a92d82fa8c3c670c72bee0f1e4bac9ec338e1751eb786eda3e10f747dd7a686900f -84a535ad04f0961756c61c70001903a9adf13126983c11709430a18133c4b4040d17a33765b4a06968f5d536f4bfb5c5 -8c86d695052a2d2571c5ace744f2239840ef21bb88e742f050c7fa737cd925418ecef0971333eb89daa6b3ddfede268c -8e9a700157069dc91e08ddcbdde3a9ad570272ad225844238f1015004239c542fceb0acce6d116c292a55f0d55b6175e -84d659e7f94e4c1d15526f47bc5877a4ef761c2a5f76ec8b09c3a9a30992d41b0e2e38ed0c0106a6b6c86d670c4235f3 -a99253d45d7863db1d27c0ab561fb85da8c025ba578b4b165528d0f20c511a9ca9aff722f4ff7004843f618eb8fced95 -89a3cacb15b84b20e95cd6135550146bbe6c47632cc6d6e14d825a0c79b1e02b66f05d57d1260cb947dc4ae5b0283882 -8385b1555e794801226c44bd5e878cbe68aeac0a19315625a8e5ea0c3526b58cdd4f53f9a14a167a5e8a293b530d615a -b68c729e9df66c5cd22af4909fb3b0057b6a231c4a31cd6bf0fa0e53c5809419d15feb483de6e9408b052458e819b097 -924f56eda269ec7ec2fc20c5731bf7f521546ddf573ccbe145592f1c9fee5134747eb648d9335119a8066ca50a1f7e50 -b2100a26b9c3bec7ec5a53f0febbf56303f199be2f26b2d564cfee2adc65483b84192354f2865c2f4c035fa16252ae55 -8f64dbed62e638563967ec1605a83216aed17eb99aa618c0543d74771ea8f60bbb850c88608d4f8584f922e30a8a0a72 -b31b9e1ffe8d7260479c9413f8e680f3fe391ae8fcf44fcca3000d9b2473a40c1d32299f8f63865a57579a2d6c7e9f08 -a5b1d136142eb23e322c6c07cb838a3f58ab6925472352ebd0bb47041a0d8729e1074ca223922f3a7a672ced7a1e562d -8d9470a5a15d833a447b5f108333d50f30aa7659e331c3f8080b1e928a99922edc650466a2f54f3d48afdb34bff42142 -866368f5891564e5b2de37ad21ff0345c01129a14ea5667f9b64aad12d13ec034622872e414743af0bf20adb2041b497 -88ef9c2ebf25fd0c04b7cfa35fbac2e4156d2f1043fa9f98998b2aa402c8f9a4f1039e782451a46840f3e0e4b3fa47d3 -94ba04a4859273697e264a2d238dc5c9ff573ebc91e4796ea58eebe4080c1bf991255ab2ad8fb1e0301ce7b79cc6e69b -86b6bd0953309a086e526211bf1a99327269304aa74d8cdc994cee63c3a2d4b883e832b0635888dff2a13f1b02eb8df4 -843ea6ea5f2c7a1fd50be56a5765dcce3ea61c99b77c1a729ee0cd8ec706385ac7062e603479d4c8d3527f030762d049 -8d3675195a3b06f2d935d45becc59f9fa8fa440c8df80c029775e47fe9c90e20f7c8e4cc9a2542dd6bfe87536c428f0d -8978580b0c9b0aa3ab2d47e3cfd92fa891d3ddee57829ee4f9780e8e651900457d8e759d1a9b3e8f6ae366e4b57f2865 -890112ec81d0f24b0dfbb4d228e418eff02ae63dc691caf59c1d103e1d194e6e2550e1bec41c0bfdb74fed454f621d0c -97da00bd4b19d1e88caff7f95b8b9a7d29bc0afe85d0c6a163b4b9ef336f0e90e2c49ce6777024bb08df908cc04ea1ca -b458268d275a5211106ccaa8333ce796ef2939b1c4517e502b6462e1f904b41184a89c3954e7c4f933d68b87427a7bfd -aac9c043ba8ba9283e8428044e6459f982413380ee7005a996dc3cc468f6a21001ecaa3b845ce2e73644c2e721940033 -82145013c2155a1200246a1e8720adf8a1d1436b10d0854369d5b1b6208353e484dd16ce59280c6be84a223f2d45e5e2 -b301bafa041f9b203a46beab5f16160d463aa92117c77a3dc6a9261a35645991b9bafcc186c8891ca95021bd35f7f971 -a531b8d2ac3de09b92080a8d8857efa48fb6a048595279110e5104fee7db1dd7f3cfb8a9c45c0ed981cbad101082e335 -a22ac1d627d08a32a8abd41504b5222047c87d558ffae4232cefdeb6a3dc2a8671a4d8ddfba2ff9068a9a3ffb0fe99b1 -b8d9f0e383c35afb6d69be7ff04f31e25c74dd5751f0e51290c18814fbb49ee1486649e64355c80e93a3d9278bd21229 -8165babccd13033a3614c878be749dfa1087ecbeee8e95abcfffe3aa06695711122cb94477a4d55cffd2febf0c1173de -a4c1bc84ecb9d995d1d21c2804adf25621676d60334bd359dac3a2ec5dc8de567aa2831c10147034025fb3e3afb33c4b -b77307cab8e7cb21e4038493058fb6db9e2ec91dda9d7f96f25acbc90309daf7b6d8a205682143ee35d675e9800c3b08 -aaf7466083cd1f325ba860efe3faf4cebe6a5eecf52c3e8375d72043a5cfc8e6cb4b40f8e48f97266e84f0d488e8badf -9264a05a3abc2a5b4958f957f3a486a5eb3ddd10ff57aa6943c9430d0cfa01d63b72695b1ade50ac1b302d312175e702 -b3f9e4c589ad28b1eceed99dc9980fac832524cfcbe4a486dfeedb4b97c080e24bdb3967e9ca63d2240e77f9addfaefd -b2c1e253a78e7179e5d67204422e0debfa09c231970b1bfb70f31a8d77c7f5059a095ca79d2e9830f12c4a8f88881516 -81865a8a25913d1072cb5fd9505c73e0fde45e4c781ddd20fb0a7560d8b1cd5e1f63881c6efc05360e9204dfa6c3ce16 -ab71c2ea7fa7853469a2236dedb344a19a6130dc96d5fd6d87d42d3fffda172557d203b7688ce0f86acd913ce362e6cd -8aa2051bc3926c7bd63565f3782e6f77da824cb3b22bb056aa1c5bccfa274c0d9e49a91df62d0e88876e2bd7776e44b9 -b94e7074167745323d1d353efe7cfb71f40a390e0232354d5dfd041ef523ac8f118fb6dcc42bf16c796e3f61258f36f8 -8210fcf01267300cb1ccf650679cf6e1ee46df24ae4be5364c5ff715332746c113d680c9a8be3f17cacaeb3a7ba226ce -905ac223568eedc5acd8b54e892be05a21abbb4083c5dbec919129f9d9ffa2c4661d78d43bf5656d8d7aafa06f89d647 -a6e93da7e0c998e6ce2592d1aa87d12bf44e71bec12b825139d56682cdce8f0ba6dbfe9441a9989e10578479351a3d9d -acde928a5e2df0d65de595288f2b81838155d5673013100a49b0cb0eb3d633237af1378148539e33ccd1b9a897f0fec3 -a6e1a47e77f0114be6ae7acd2a51e6a9e38415cce7726373988153cdd5d4f86ef58f3309adc5681af4a159300ed4e5b5 -ad2b6a0d72f454054cb0c2ebc42cd59ff2da7990526bd4c9886003ba63b1302a8343628b8fe3295d3a15aa85150e0969 -b0bc3aea89428d7918c2ee0cc57f159fba134dad224d0e72d21a359ca75b08fbb4373542f57a6408352033e1769f72c6 -aad0497525163b572f135fad23fdd8763631f11deeaf61dea5c423f784fe1449c866040f303555920dc25e39cdb2e9b4 -8ce5d8310d2e17342bf881d517c9afc484d12e1f4b4b08ad026b023d98cba410cd9a7cc8e2c3c63456652a19278b6960 -8d9d57dbb24d68b6152337872bd5d422198da773174ade94b633f7c7f27670ff91969579583532ae7d8fe662c6d8a3b0 -855a1c2d83becb3f02a8f9a83519d1cb112102b61d4cdd396844b5206e606b3fefdbcc5aa8751da2b256d987d74d9506 -90eb7e6f938651f733cf81fcd2e7e8f611b627f8d94d4ac17ac00de6c2b841e4f80cada07f4063a13ae87b4a7736ca28 -8161459a21d55e7f5f1cecfc1595c7f468406a82080bfa46d7fb1af4b5ec0cd2064c2c851949483db2aa376e9df418e6 -8344ccd322b2072479f8db2ab3e46df89f536408cba0596f1e4ec6c1957ff0c73f3840990f9028ae0f21c1e9a729d7df -929be2190ddd54a5afe98c3b77591d1eae0ab2c9816dc6fe47508d9863d58f1ea029d503938c8d9e387c5e80047d6f1e -856e3d1f701688c650c258fecd78139ce68e19de5198cf1cd7bb11eba9d0f1c5af958884f58df10e3f9a08d8843f3406 -8490ae5221e27a45a37ca97d99a19a8867bcc026a94f08bdccfbb4b6fa09b83c96b37ec7e0fd6ee05f4ae6141b6b64a8 -b02dbd4d647a05ac248fda13708bba0d6a9cd00cae5634c1938b4c0abbb3a1e4f00f47aa416dcd00ffcdf166330bff9a -9076164bb99ca7b1a98d1e11cb2f965f5c22866658e8259445589b80e3cb3119c8710ede18f396ba902696785619079c -aacf016920936dae63778ad171386f996f65fe98e83cfcdd75e23774f189303e65cc8ad334a7a62f9230ed2c6b7f6fa4 -a8031d46c7f2474789123469ef42e81c9c35eb245d38d8f4796bba406c02b57053f5ec554d45373ab437869a0b1af3f0 -a4b76cd82dc1f305a0ee053e9a4212b67f5acc5e69962a8640d190a176b73fbc2b0644f896ff3927cd708d524668ed09 -b00b029c74e6fdf7fb94df95ef1ccad025c452c19cddb5dccfb91efdcb8a9a1c17847cfa4486eae4f510e8a6c1f0791a -9455e5235f29a73e9f1a707a97ddb104c55b9d6a92cc9952600d49f0447d38ea073ee5cf0d13f7f55f12b4a5132f4b10 -ae118847542ed1084d269e8f3b503d0b6571a2c077def116ad685dcca2fca3dcb3f86e3f244284bdcd5ae7ac968d08a5 -8dcb4965cd57e8b89cd71d6fc700d66caa805bfd29ab71357961527a7894e082d49145c2614b670dcb231ab9050d0663 -add6ed14f3183f4acc73feea19b22c9a330e431c674e5034924da31b69e8c02d79b570d12ef771a04215c4809e0f8a80 -96ae7e110412ee87d0478fdbdbaab290eb0b6edd741bb864961845e87fd44bcbe630371060b8104d8bf17c41f2e3fca0 -a20db17f384e9573ca0928af61affab6ff9dd244296b69b026d737f0c6cd28568846eca8dadf903ee0eecbb47368351d -937bfdf5feb0797863bc7c1be4dcc4f2423787952a3c77dfa3bfe7356f5dbcc4daebde976b84fc6bd97d5124fb8f85c9 -a7050cc780445c124e46bba1acc0347ddcfa09a85b35a52cc5808bf412c859c0c680c0a82218f15a6daeefe73f0d0309 -a9d9b93450e7630f1c018ea4e6a5ca4c19baa4b662eadfbe5c798fe798d8a3775ed1eb12bd96a458806b37ab82bdc10a -a52a4d5639e718380915daaefad7de60764d2d795443a3db7aeab5e16a1b8faa9441a4ccc6e809d8f78b0ac13eef3409 -8e6f72b6664a8433b032849b03af68f9376b3c16c0bc86842c43fc7bf31e40bc9fc105952d5c5780c4afa19d7b802caa -a107ae72f037000c6ee14093de8e9f2c92aa5f89a0a20007f4126419e5cb982469c32187e51a820f94805c9fccd51365 -9708218f9a984fe03abc4e699a4f3378a06530414a2e95e12ca657f031ef2e839c23fd83f96a4ba72f8203d54a1a1e82 -b9129770f4c5fcac999e98c171d67e148abd145e0bf2a36848eb18783bb98dff2c5cef8b7407f2af188de1fae9571b1c -88cc9db8ff27eb583871eeeb517db83039b85404d735517c0c850bdfa99ae1b57fd24cf661ab60b4726878c17e047f37 -a358c9aadc705a11722df49f90b17a2a6ba057b2e652246dc6131aaf23af66c1ca4ac0d5f11073a304f1a1b006bc0aa5 -ac79f25af6364a013ba9b82175ccee143309832df8f9c3f62c193660253679284624e38196733fb2af733488ab1a556e -82338e3ed162274d41a1783f44ae53329610134e6c62565353fbcc81131e88ce9f8a729d01e59e6d73695a378315111b -aa5ddcabf580fd43b6b0c3c8be45ffd26c9de8fa8d4546bb92d34f05469642b92a237d0806a1ad354f3046a4fcf14a92 -b308d2c292052a8e17862c52710140ffafa0b3dbedd6a1b6334934b059fe03e49883529d6baf8b361c6e67b3fbf70100 -96d870a15c833dddd8545b695139733d4a4c07d6206771a1524500c12607048731c49ec4ac26f5acc92dd9b974b2172c -8e99ee9ed51956d05faaf5038bffd48a2957917a76d9974a78df6c1ff3c5423c5d346778f55de07098b578ad623a390e -a19052d0b4b89b26172c292bbf6fd73e7486e7fd3a63c7a501bbd5cf7244e8e8ce3c1113624086b7cdf1a7693fdad8b5 -958957caf99dc4bb6d3c0bc4821be10e3a816bd0ba18094603b56d9d2d1383ccc3ee8bc36d2d0aea90c8a119d4457eb4 -8482589af6c3fc4aa0a07db201d8c0d750dd21ae5446ff7a2f44decf5bff50965fd6338745d179c67ea54095ecd3add4 -8a088cc12cf618761eaa93da12c9158b050c86f10cd9f865b451c69e076c7e5b5a023e2f91c2e1eed2b40746ca06a643 -85e81101590597d7671f606bd1d7d6220c80d3c62e9f20423e734482c94547714a6ac0307e86847cce91de46503c6a8a -b1bd39b481fc452d9abf0fcb73b48c501aaae1414c1c073499e079f719c4e034da1118da4ff5e0ce1c5a71d8af3f4279 -942ae5f64ac7a5353e1deb2213f68aa39daa16bff63eb5c69fc8d9260e59178c0452227b982005f720a3c858542246c8 -99fea18230e39df925f98e26ff03ab959cae7044d773de84647d105dfa75fd602b4f519c8e9d9f226ec0e0de0140e168 -97b9841af4efd2bfd56b9e7cd2275bc1b4ff5606728f1f2b6e24630dbe44bc96f4f2132f7103bca6c37057fc792aeaab -94cdad044a6ab29e646ed30022c6f9a30d259f38043afcea0feceef0edc5f45297770a30718cbfec5ae7d6137f55fe08 -a533a5efa74e67e429b736bb60f2ccab74d3919214351fe01f40a191e3ec321c61f54dd236f2d606c623ad556d9a8b63 -b7bd0bb72cd537660e081f420545f50a6751bb4dd25fde25e8218cab2885dd81ffe3b888d608a396dfcb78d75ba03f3f -b1479e7aa34594ec8a45a97611d377206597149ece991a8cef1399738e99c3fa124a40396a356ab2ea135550a9f6a89f -b75570fc94b491aef11f70ef82aeb00b351c17d216770f9f3bd87f3b5ac90893d70f319b8e0d2450dc8e21b57e26df94 -a5e3f3ab112530fe5c3b41167f7db5708e65479b765b941ce137d647adb4f03781f7821bb4de80c5dc282c6d2680a13d -b9b9c81b4cac7aca7e7c7baac2369d763dd9846c9821536d7467b1a7ec2e2a87b22637ab8bbeddb61879a64d111aa345 -b1e3ee2c4dd03a60b2991d116c372de18f18fe279f712829b61c904103a2bd66202083925bc816d07884982e52a03212 -a13f0593791dbbd360b4f34af42d5cc275816a8db4b82503fe7c2ff6acc22ae4bd9581a1c8c236f682d5c4c02cc274cc -86ba8238d3ed490abcc3f9ecc541305876315fb71bca8aaf87538012daab019992753bf1e10f8670e33bff0d36db0bf0 -b65fbb89fafb0e2a66fe547a60246d00b98fe2cb65db4922d9cef6668de7b2f4bb6c25970f1e112df06b4d1d953d3f34 -abb2d413e6f9e3c5f582e6020f879104473a829380b96a28123eb2bdd41a7a195f769b6ac70b35ba52a9fee9d6a289c3 -88ec764573e501c9d69098a11ea1ad20cdc171362f76eb215129cfcca43460140741ea06cee65a1f21b708afb6f9d5b0 -a7aaec27246a3337911b0201f4c5b746e45780598004dac15d9d15e5682b4c688158adffdef7179abb654f686e4c6adc -a1128589258f1fbfa33341604c3cb07f2a30c651086f90dce63ae48b4f01782e27c3829de5102f847cde140374567c58 -aaf2b149c1ca9352c94cc201125452b1ed7ca7c361ed022d626899426cb2d4cc915d76c58fa58b3ad4a6284a9ae1bc45 -aaf5c71b18b27cd8fe1a9028027f2293f0753d400481655c0d88b081f150d0292fb9bd3e6acabb343a6afb4afdb103b5 -947c0257d1fb29ecc26c4dc5eab977ebb47d698b48f9357ce8ff2d2ed461c5725228cc354a285d2331a60d20de09ff67 -b73e996fa30f581699052ed06054c474ebdf3ae662c4dc6f889e827b8b6263df67aeff7f2c7f2919df319a99bdfdceb1 -b696355d3f742dd1bf5f6fbb8eee234e74653131278861bf5a76db85768f0988a73084e1ae03c2100644a1fa86a49688 -b0abca296a8898ac5897f61c50402bd96b59a7932de61b6e3c073d880d39fc8e109998c9dba666b774415edddcff1997 -b7abe07643a82a7cb409ee4177616e4f91ec1cf733699bf24dec90da0617fe3b52622edec6e12f54897c4b288278e4f3 -8a3fae76993edbc81d7b47f049279f4dd5c408133436605d934dee0eadde187d03e6483409713db122a2a412cd631647 -82eb8e48becfdf06b2d1b93bf072c35df210cf64ed6086267033ad219bf130c55ee60718f28a0e1cad7bc0a39d940260 -a88f783e32944a82ea1ea4206e52c4bcf9962b4232e3c3b45bd72932ee1082527bf80864ce82497e5a8e40f2a60962d0 -830cf6b1e99430ae93a3f26fbfb92c741c895b017924dcd9e418c3dc4a5b21105850a8dd2536fa052667e508b90738f2 -990dce4c2c6f44bb6870328fba6aa2a26b0b8b2d57bfb24acf398b1edc0f3790665275f650884bd438d5403973469fa2 -a2e5b6232d81c94bcb7fed782e2d00ff70fc86a3abddbe4332cb0544b4e109ae9639a180ae4c1f416752ed668d918420 -b4cdf7c2b3753c8d96d92eb3d5fa984fef5d346a76dc5016552069e3f110356b82e9585b9c2f5313c76ffaecef3d6fd8 -83b23b87f91d8d602bff3a4aa1ead39fcc04b26cf113a9da6d2bd08ba7ea827f10b69a699c16911605b0126a9132140f -8aae7a2d9daa8a2b14f9168fe82933b35587a3e9ebf0f9c37bf1f8aa015f18fb116b7fba85a25c0b5e9f4b91ba1d350b -80d1163675145cc1fab9203d5581e4cd2bed26ad49f077a7927dec88814e0bed7912e6bbe6507613b8e393d5ee3be9be -93ddeb77b6a4c62f69b11cf36646ed089dcaa491590450456a525faf5659d810323b3effa0b908000887c20ac6b12c80 -9406360a2b105c44c45ba440055e40da5c41f64057e6b35a3786526869b853472e615e6beb957b62698a2e8a93608e13 -93bfc435ab9183d11e9ad17dac977a5b7e518db720e79a99072ce7e1b8fcb13a738806f414df5a3caa3e0b8a6ce38625 -8a12402c2509053500e8456d8b77470f1bbb9785dd7995ebbbe32fd7171406c7ce7bd89a96d0f41dbc6194e8f7442f42 -aab901e35bf17e6422722c52a9da8b7062d065169bf446ef0cbf8d68167a8b92dab57320c1470fee1f4fc6100269c6e2 -8cad277d9e2ba086378190d33f1116ba40071d2cb78d41012ec605c23f13009e187d094d785012b9c55038ec96324001 -85511c72e2894e75075436a163418279f660c417e1d7792edce5f95f2a52024d1b5677e2e150bf4339ad064f70420c60 -85549ca8dcbe49d16d4b3e2b8a30495f16c0de35711978ada1e2d88ad28e80872fca3fb02deb951b8bcb01b6555492e4 -8d379ab35194fe5edf98045a088db240a643509ddc2794c9900aa6b50535476daa92fd2b0a3d3d638c2069e535cd783b -b45cfebe529556b110392cb64059f4eb4d88aaf10f1000fdd986f7f140fdd878ce529c3c69dfd2c9d06f7b1e426e38f3 -ac009efd11f0c4cdd07dd4283a8181420a2ba6a4155b32c2fed6b9f913d98e057d0f5f85e6af82efc19eb4e2a97a82df -b2c2cdffa82f614e9cb5769b7c33c7d555e264e604e9b6138e19bcfc49284721180b0781ecbf321d7e60259174da9c3c -95789960f848797abbe1c66ef05d01d920228ca1f698130c7b1e6ca73bfda82cee672d30a9787688620554e8886554ee -98444018fa01b7273d3370eeb01adc8db902d5a69b9afc0aa9eadfeb43c4356863f19078d3c0d74e80f06ecf5a5223f4 -87d20b058050542f497c6645de59b8310f6eeec53acbc084e38b85414c3ea3016da3da690853498bde1c14de1db6f391 -a5c12b3a40e54bee82a315c503c1ce431309a862458030dde02376745ec1d6b9c1dbeea481ae6883425e9dae608e444e -b9daa3bf33f0a2979785067dcece83250e7bf6deb75bb1dbbab4af9e95ddfb3d38c288cbef3f80519a8916a77a43b56c -b682ec3118f71bde6c08f06ea53378ea404f8a1c4c273dd08989f2df39d6634f6463be1d172ac0e06f0fa19ac4a62366 -a4f94fd51ecf9d2065177593970854d3dce745eebb2a6d49c573cbf64a586ae949ddfa60466aaef0c0afb22bd92e0b57 -86cd5609efd570c51adbc606c1c63759c5f4f025fcbefab6bc3045b6ad2423628c68f5931ff56fdda985168ce993cc24 -981192e31e62e45572f933e86cdd5b1d28b1790b255c491c79bd9bb4964359b0e5f94f2ae0e00ef7fe7891b5c3904932 -9898f52b57472ebc7053f7bf7ab6695ce8df6213fc7f2d6f6ea68b5baad86ec1371a29304cae1baadf15083296958d27 -b676c4a8a791ae00a2405a0c88b9544878749a7235d3a5a9f53a3f822e0c5c1b147a7f3f0fc228049dc46e87aa6b6368 -9976e10beff544e5c1645c81a807739eff90449df58ffdd8d1aa45dd50b4c62f9370538b9855a00dd596480f38ebe7a5 -a0e91404894187ec23c16d39d647ada912a2c4febfd050a1ea433c4bfdc1568b4e97a78a89ba643aca3e2782033c3c58 -91a6ea9a80476ed137eb81558ff1d55b8581663cccd41db4fc286876226b6515fd38661557419e1e46b6a3bc9cda3741 -b9e8a1e23c60335a37a16f8085f80178a17d5e055d87ffe8cf63c532af923e5a5a2d76cf078164fb577996683796caa6 -ad8e151d87a37e8df438d0a6a7c02c3f511143efb93fde8aef334d218cb25932baf9e97c2f36c633620a024a5626af3d -978f942f210e8a482015e6fdc35a4c967c67b66e6e2a17a05cc7a0f2163aed227b775d4352b0c3cca6cbf4bd5bafaf75 -b5e2e3d8b2e871c07f5899e108e133f87479959b80cb8a103fbecde00ccdbfbd997540eef33079c5cc14b1c00c009fd1 -88a164b3fefd36857f429ab10002243b053f5d386466dbb9e5135ed3c72dd369a5a25e5e2aaa11f25488535e044e2f12 -a66091c0db4e7cf05a089ec2b9ff74744354d0196968201f5e201699144b52bb13b4e68e12502727163e6db96e3565f2 -8e65aff8e37240461b7374c20bfd1d58b73a525c28994a98f723daed9486130b3189f8efe5c5efcd7f5390cc366038da -8b37c21dd7304c3aa366959ba8c77ea8b22164a67e136808b6f8e48604297f7429a6c6ecf67b1d09b8b7ec083eacd7e0 -b689b1277ad050f53da91a702516a06d7406ff33a4714ea859b3b2b69f8d0aa8f983c7e039b19c0759a3815d841fa409 -b17f7a0a182ed4937f88489e4c4e6163dcf49fd2ea4d9efbba8126c743bea951cd769752acd02e921774dc8ebcfae33b -8b7fab4f90be825ac5d782a438e55c0a86be1c314a5dbc3cc6ed60760a8a94ef296391f1f6363652200cce4c188dae67 -ab8410c4eaa2bb43b0dd271aa2836061bc95cb600b0be331dada76ddb46711ff7a4ad8c466cc1078b9f9131f0dc9d879 -9194bd7b3cc218624459d51c4d6dbc13da5d3de313448f8175650fa4cfab7cc4afcda5427b6676c3c13897dc638b401e -980f61a0f01349acd8fc9fdc88fc2c5813610c07eecb6ab14af0845a980792a60dadf13bb4437b0169ae3eff8f5984ce -b783bee24acea9c99d16434195c6940cf01fc2db135e21f16acae45a509eca3af6b9232a8aa3a86f9715c5f6a85cb1c3 -a3079931c4b90966d1faa948db847741878b5828bc60325f5ebe554dcab4adcc19ee8bce645e48a8f4a9413bb3c6a093 -801f61ac9318f6e033a99071a46ae06ed249394638c19720831fff850226363a4ae8486dd00967746298ee9f1d65462f -b34dbbed4f3bb91f28285c40f64ce60c691737cc2b2d2be5c7d0210611cd58341bb5bda51bb642d3ee2d80882e642a13 -8750af19abfb915e63c81542b13d84526a0c809179bbcc1cd8a52b29f3aba3ae0f7cf6f4f01790bf64ef7db01d8ee887 -a6ea10000eb2dd4efc242ac95bc3b3873cdd882fbeb7c9538c87e3143a263ca3a2e192b2159316a625cfb5fb0b6cdcb3 -aa40ca54bc758a6c64cb932924917581062e088b3ad43976b28f2e11d8a7dea73f1fb50aeaa0e70182bb2dc07d805bb9 -a4779dfd25b5ec9d75dfb54a4bb030364899a5e75c1492403acb19f2adc782c7ac4daeb66d2f5aeb74135afe9f318e3f -b4551e2805d63ca453f4f38b1921ac87ff687e1d70575ad38f3469d6f0608ef76b7b1b98ae1e6b1e7d928773aaab6e3b -99490ee722f96aad2743b08dd37bfeb75a8c59efaee4c9b694eaa05eb8a6bb23861a4480544c7617d04d23fd5e2543b4 -8a7050d964d295fff98ae30d77ce730a055719313457e773fcce94c4d71a9b7cf63db67e54a8aab20fb1335b0130b5d5 -903144e6bbee0a4fec17ff80fef0d2103981140c3d41776cfb184ced17f480a687dd093f6b538584327e6142812e3cd5 -a5b30f7c6939bdc24a84ae784add927fec798b5a5ee3dd156c652df020728dd6d43898be364cf5ee181725fbcffc0964 -b43d97ec2bc66af92d921a5c5c20a03ef2be2bc2c9b345f46d8287409fcbfd88ebc49d4509d64468222cd1d2021bf236 -82dc23c7f5086c9ac6b4566359bfb830d203544b0d8332a210775670f899cd9ff48b94bfeba40040c25664ebdd5cfad8 -9294cd017fea581dabb73dcc8c619904d7e022b664b0a8502c9d30f3807668af279948e7e41030ae296d492225297e95 -8d6c9dc636c8e884f9a4299e5cff06d044ebc94ad783a4b71788347ea4a336d4d048b8a9ecabae789e8fcdc459723dfb -801a80bc49e882ec81b04e37407713f033f7bdac79252dfa3dc8c5bd0229fcbd4019890e402cf843b9378df08f72ab84 -b4313ca32569d973900f6196363c0b280ddfa1b47c88d019e5f399b805b444a777950fc21ae198fc23ece52674b94abf -96f06056fd255fdabf78986e315e7c4fdf5495cf850536b7976baa97a994cc6a99c34609c33a0f2facba5e6f1026dce6 -983ed80220a5545ffd70ef5e6ac10217d82ec9cd8f9a27ee77a5ff4074092308c0e6396fc4e9932a77ddd474e61f8b55 -872a059aa630af73c4abbd076e8b333a973ffc5bdecf5dcc0600b00162184213cb19d4f601795030033beb808d5810ce -b040f318d9d3b8833da854014a44296dbd6762dd17cab13f91987256c54353b7f0800547cb645a7cc231997454209fdd -a8c4731a555308e8ce0b8325eb7a4cbf6113d07e9f41932df04480b72628d313b941c7055f1cc2ac45c7353b56e96ca9 -8c24031440b77637e045a52e5ea3f488926ab0b426148975edf066c40a4581beecc1bfb18fc4cf5f9f96dc6681b4bd28 -b39254b475abf342f301298feaa17a4b3051f30ea23a18acf59e003e2704ac96fe40691f1da387913bdf7aee6389f9a8 -a1dbf938b604ccc6d60881cc71f38df568aa02752aa44d123514154017503f6c1c335ae43e359f1487bc8934073cd9c1 -8d52aa1be9f429ece0580498d8fe9fef46d4a11f49436a82b8927f9503dacc41245907f126594c1cd30701286f8c092c -b826f396486942c0326d16f30a01b00a682c30a75553dc6ac34fd5b3e96b13c33b94738f522eebaffb59ff8c571c76e9 -aa89f51cbf6e6c3e2aa2806187b69ab3361c84e89f393f3ed284fe84db46fc3944aa44f8928e3964f9c1a1ec27048f68 -a254df0efa4203fb92b42a1cd81ca955922e14bf408262c8f7cb7dc703da0ca2c71556bd2d05b22ce9a90ad77309833d -93263c507e4d5f4e5df88e85b3d85c46ea729fb542a718b196333e2d9fb8a2e62dc1347cf146466a54ba12d200ef09d9 -922e3c4a84246d89a07aa3e90f02e04b2cea9bebc0e68b742156f702aed31b28c6dfa7ac936ea2fc2e029adf68361f98 -9a00628eeeda4ccbed3ef7834149aec4c77aac1a14bc2491ba5d1a4a2c5d29afb82ceaa5aac1c5ce1e42cdcaf53e30ba -ab3a88df36d703920f6648a295a70ffa5316c96044f39ff132937bfda768937cb6a479e9ba4a4e66b377f3a9996a88c4 -966b11526ab099d550ab33c6a9667e5cfdedf255da17a80a519d09acd78d2ea24ec18bd1ea7d8d63cf0a408f1c1fe0b3 -b5c21b9817dc32f3df9d9988aa3560e1e840d586d01cd596bc0f850ab416b6013cbf7dbfd05ac981f26014c74bd2d2b2 -9040abef5e2523e7f139c9f744a64b98fea3a57952059ffe4d5ed77fa87068203c090ef4e7f52c88fb82ea8a6fdca33e -a0dcdaeb7d3f5d30d49c004c5f478818c470187f4b0b4856812dcd1b3a86de58a99acb8ceb44c6b80c3060cf967c43a4 -b5f4be9a69e4a6719ea91104820df8623b6d1073e8ee4168de10a7e49c8babea772bcbc6b0908185e98d607e49cd3609 -8634020a5a78650015763c06121c606d2dd7b324aa17387910513dd6480fb797df541fc15b70d269b2794ad190595084 -9504d1d0fb31ff1926c89040c04d51fd1f5cddf9d7ca3d036e7fd17e7a0f767ef33cee1d8bf7e17e2bc40949e7630417 -812c72846ef6d692cf11d8f8c3de8fa78cc287303315114492667b19c702cd24d462020f1276895df26e937c38f361f8 -8c97aa5e9ef2aa9a1435ef9ddfe62e850f0360864ed5fb82bf9fef4ef04d8fb4f827dc078bc911ee275e4501edd6617c -ac5f7af5e23c8e429aaa6b6825129922b59d25b4608f07b65f21388a9ac3aa89096712f320afe6d56e44e1f0d51a4eb9 -a8c84d9a8593a0cb5be1e450960f59878a4e6b70da54a7613dfc25911b7cc9e6d789d39401b0a0d6471ab9dcdc707976 -8c9d5fd89611392c0f085ffa4fa642a181f0b9b23593deb5e10fdd1642722ca75ef34a037e88a8d03f2888fe7461f27c -8c74b05f91fb95c85e7bd41f6d9a1e41e667e68f3d19b325c1f25df1767019919edab89b92af237896cbc4e6d6dc1854 -a3caecb91640821f0b2c4981b23f2069df8d2b98ce026c1538bc096b292f5f956a5d52c1c8d6a8165a1608083ba6494b -8ae8e0c36f8b79a69176ff29855df45d0fcd9e4d1dbaed8899f8fcdece676e418ec034a6c161e2a894f0c834aaecbfd1 -b88d18c67dc3b1b6ed60ee437c441c1ed14ecddebccf43683605716f30058b1aa4ba05ff10cd8171ee97d8f58d70c094 -94f43d84dcdfd9cd19115c7d8e9c1e856828eafbfdec93b876cf0007e317e30b2ad951dbabc186aa6ef90fdee4d91990 -b44e4723f41fc1d5b0057f371e3381ae02566590b3f964b6eb07b2104f66ff78410c407235fa98d04f635694f3baca09 -addd8390173d29ca0811534d389253831fed75fed135398617836b6e70767269eacb1560b39a58f02042ca3b97fe59c4 -80bdbdacc0c358c7ea52aeacdc5f9ceb6928bcf6e7dee7c17d8ae3bf7c2372aa7a0372363888968fc0921aaf4776d5d0 -a486e2b6f04f403f9e609d69dfb3cfb992af56ecad1683271df3e3faa3b86638b81e73b39978fb829ee7133d72901f2d -a19472da57457e10c6a6307895393ddaec8f523760d66937fe26a025817319e234eaf69756ffdf1b84c81733424a96d7 -ad6a195397cbc2d75171f5e82090441eed60bd1ba42c39ef565b8b5a8281b04400678625b1dc46d617f694a7652a8e5d -8f98e721c06cec432e2221f2e1b06bb1469d916a8d88d6973acf68d1e003441d00390dafcead8ecdbf9eae4509baf5aa -91d62a0f9d13c59adfe1376ed6d057eae244d13c6b3d99be49a49e0075cf20f4085cf127774644ac93615be9ac9e5db6 -af45dec199245e2b326a0d79c4899ed44b1c0219db42602a4a6184ace0ff831a3276297af28f92e8b008ba412318e33e -8754bde54e8d2d169e6a7d6f0eae6097bc0461c395192bd00dd6f105677ea56ab384c02553ea5eeac0a65adcb0df77ee -b676afd2f5afc37a314c943d496e31b4885efcbcc2061036e370a74cfde5642bb035622d78d693bfc3136fc036c7edb4 -aab6ffe6cc234397cf1822e02912bc282dfb314e92fb5a9e10d0c34ee9b5856d4b76e166bc2bb6fcdd66aabea35ec4ef -ada6e62f90ee6b852ec4b72b22367acac2896f0df2c105beda27096583ddbedddc710d171330569f111c6e44a5b57ae7 -802139dd15241a6de663d9b810121bdd9cf11f7f8c8ca6de63f4f8e731409e40d1fd3558b4f619ed42ee54929dff1c7e -ad8e70531cec21b4e6f55be1751c2d025bd2d7d8158269b054cfe57fa29252d052ce4478ec7db6ec705789e2118d63b3 -a8e4a4271769480e1b33a28c87a150ecc0b48bfe8a15ae04152197881de4ce4b03453aefe574842424edbbe4173e1a3a -b98c65726296610cef16c5b58da5491acd33bd5c5c5af4d934a9840649ef85730fbce8018dee09ded14e278009ed094a -8e213a7861223287b860f040e5caaa563daa0b681e4e09ec79ad00cc459238e70bbeaf7486bbe182fc12650700034ec5 -a2879f9e1a556cf89b9b5b3bd8646a8cce6b60bcbc8095df44637f66a2da5858eee2dc9091475a8f64bb5aff849389cd -8a17cdb4077b9b0bcf28b93294ac5ae4c8bba8839fce0f1012b53187ac008f9858b02925fbfc421f1123afcdbd8b7753 -86fd9c11528aa43946e4415ff64a3ca6409ee6f807368c68997b18605da65e415ccd85ad913820d450cb386593de666d -8ed55923b963c3d85a91aca11c40ff9c6c7f1e2b9bc199d1a270e5fb16aa62dec0136e97866145ae9d58a493e8b1cbbb -ae32af5b5d418668ae123c639b149e5eed602404e8516da4a61db944b537a3620545e8e3d38cf10cdaea980ab2f80973 -95cb8d9e9d6762d78dde0ad73869ffaca904a7d763a378b8cc11a7933d3e7d1c8aec4271a079b1b00f8887ee5b1ea21f -b5ea20b42a3ca247f00ab5328c05f0cf194973d5f7271c66c41c5055b1ffdca136be179709e0c1de209fbe07b9820bf3 -98682f7cce471c92a8d6d15fee4ddf4d43dd97c3e3811d2913618ecacc6440b737717c07736ae4558c910e11ee98104e -a67da2c7cbba48e929ca4e4b9a6299fe01ef79eff8cc5cd3fdbdc0721a68130e4079f30ae151a573a7dcca8ecf2e684e -a9981c9f9dcbb3b0f6996f664fb2acd7573189f203be37b2b714662aa273551396abfb1f612ccde4e4c8127a050dbe4b -92d55eff8da600f886da9bf68e8eecf482faa4b268f3f286b3b3e5cc91b19604081498d4905b201bb4ec68e32b5591d9 -963e3f1728de9d719c86d390f3eb9c3f99d1928347fab0abf10dbb37d76b59ddb64d4734c977863a6cd03ffece5ca895 -93480e2de83c921056b6d8628ac37cd5ef7555ba43b0308fc13386cb0515d42c12ecd06057137aa71a7931beaf90b9ce -8feae57ff0e6a162cc81c99f45c6187d268fc0bee8c2bffc92142ef76c253d201f0e932943cf2fa312982b281ce1066b -8f8f4bd4200fb87afcd743274480220d77571928000d4197410dbb75439d368df6a06d941a6152206371d2ca9cac99e4 -8ee7f11e79af4478e0a70eb424fe8078237ad99ba6d7e6bf1a8d5e44e40abd22d404bd39b718ad6fdf4c6601f2a47665 -a98acfcec612b574943195b9ba95bebcc9c0b945c9f6b3e8760b2a4635909246a9d73b0b095c27b4ecb3339704e389b7 -b520efd19f65e81dc285031ea3593f8c5dad793e4426beb9196ab46e45346f265fd71e50adb0da657977c60ed5724128 -a3d9d0b7415280ce4dfa2429d47b2b8e37604a5157280a72cc81d541ffe44612dbb3ef7d03693fc42a569169d5842dc3 -8c29e2d0b33801f6d9a9c065a76c5cad1fb0a001506b970307e21765ee97c732a4cbf1d7c1b72d95e0ad340b3b075224 -839e21f292892a6eb596b9b1e9c4bd7c22a6fe71d3d04487c77840028d48392c5cbe73140a4e742338e0c8475cd0c1ad -8bea5c68e7743998619185bb662e958f1b4d3ca81019d84ac43c88911aab3abe4ee9bcc73cb95aa3ae87c0138801bde3 -b8f262d21a94604049e008ce03dc857848168e1efca4522acb0ccc827ffb37f545e1947843a356563a76bc6489605b66 -a7bd0842b0bb38d9943b82aa883f36f4eb8a6e8a7790d4f87faf306608f51d250a19b73984f1156cef5dd2581664614b -a993e649bd953627a88a2539dac3a12ec7f37a4c65b01425d9d34edf7ee10a71aa98f65c9e013107f824faf8aee041a9 -8e07eced75c67cb4d2ec01857f6ac1408482e6b31cb2faa249e8cf99f180575587df530c7782a7539b5221121ef48aa0 -b2f4578f26c05ecb9e2669ca744eb19d4f737321ac7d04fafd18beb7866e0fec9dd063953ae1f077b44b9c6f54db1279 -b6b3788a6c7bcaf467d19daf6ab884d549aa866970c05a9181f544ff190d043192c84fe437a75a30b78b425461cca062 -a270684903c61544b85a7041e81f65e787e1c1e23e57538fa8a69836bed0ca1673861dd29f743a1280f2f38eddd3aa83 -a9c2397c4773dcad2821266dadfd2401d013d9f35de6744f2ec201f3507700adb1e6ec4f5a453be4764da8bf68543f26 -83a3025ed6fd5df9d98be32a74e10a0d9728b560942d33ba028536fb148fc34ae87e92be2df3e420a8dfec08da495982 -90dc70c183a90bab988b4a85b7b921c8070af0e5f220364fe11afa0722990b2c971e1e98eef62d3287fedfd9411f1df7 -82d940937a6c636224d04f8e2536f93dcf20dc97a5f188875ad76c21b804aef9af10839419b61143c1f88a695959a6b4 -8017f9473ce49d498d6f168137e77e62fe553e5a51e75b519cf2cbd1ab9afdafad80fd5e6fd0860e640b0d78ca8ed947 -80573a0ec049fe1f7b3013b2839e145cd87e07c0e43826a29ef8c92516f9a30896c2ffcf3ed77ed22a6cf3101b1789d5 -953349abd2559f9824db07cec857ad54f1a05018f3076425f8dbae37f8d92a46af2c04ab7c8ec0250449541187696e98 -ab7bd2c4f05ee9a9f252c4e16a20993a12c535c3809d124bae24642616521a9768d3f19eceaf8524583f47ae1f527684 -9883b77ee834ee0112ca2f366d2a6fc213e0cf454e061438c2901a5ba35b7378f64da8adf6a476eb1562991ef5b4a5bc -89291811db308637356dbf7ed22cf07bfce33eb977734ee346e8c15a231b35d8b4443574f3fa97a40867b3e23b0bbfa4 -93d753849d7d9588d39e38217500b123a6b628a873876612d9f98b5d611f52c89c573432d2176752b5d1cc2d94899b8b -a45add3c4844db3b7a237295fc85fddc788ac1ec395a0524d2fc90a539571a247146aea4aa10eec30a95e9617c85b98d -90f94578842db7a4de672da1e483858ece5e466c73c12f725a0fc71f42ff880c9447a33fa9096839bee817536f2591e2 -b2c1b6fb031bb30460f157356562b44b4de096a0a112eab4fb3cc500aad38bc770da1fc2e73caf687a0da5e8537049c0 -afb15e15fd930929c0e3c66482068a5afe0c7b7f82e216a76c5eb1113625bfa0b045a52259d472284cfbaf4796c71456 -ad222a9a3d907713418c151b8793d5e37634354322068f8206b9d0da1a3f53b0004193713d23ec35990639a1b6c2e075 -b44a128dce97e8c4b178cdbca0a5c1b3f6e164490fac0fd68dbfe0aafa89920bb4ea420a8527e06c80dd19c2f135e3ef -8596e993ef18b8d94e9c42a90cb7060affc586b8e9b526820d25124285de5590134e2e86592e9dc4dd45ccf5d578fa60 -b71bb0ad138141ed506b2253e84110d2db97cc2d24a3fd0d096b0022d9f38f87aa74e2f505074632d64e90bcc491aa30 -84841eafd357309de47b92ca5ec163dec094a2e5271bc65898c31932e0160bee165e4decb23af339cfe09c83e1cc5441 -8a2915ee39a6fd4a240b98533d7690ef1773ce578ed1fb05ed414ebe36f7ef289fa46f41768df57190438c356331e329 -90bb337165386f1990cbd8ed2e8321ef21bc18125b015b4da0c37e5fcc446b26005379ee4fad8ce9348ceb4ab49e82e2 -b707b50ea2ab05c6d183671587f25fe29eef23fe569d731459a1ac111a0b83a2cd65b88242876b34aeead3b05a15d745 -ae1f159f79b7996315c4f9acce7e21a6ed59d4ef76331196fc86911fda3035edd5c11d568b105175a36c948d0263b382 -922bc525bace05e5dff6b5cabde5469ddd2c1c601f7131abc04ecefdd35095e6ac015b1aec3c3b25c5dee8d139baf60d -a7b060405b2740f82db64683187b1bb89e5f40c8438663c7cbc8ef2513929fe5f92625667a7f2f599a72a96b1fc8f08a -b9dfe94a08651db5efefbb813269bce80d814e3089b80c0654491e438d820bf521f8a4a4477909344ba88f7683eebb43 -841817a9729465743576950b6e8eea32ebf39cca99ace86c4792f9f35926e2d6830c52854a3b2eaeb61694e6845008bd -934128034bde8fc7b93b952aa56e0ed28b36cfa04cfa1f0d5b38266dd40beedff5e0bab86e4717b0fb56c56be2eae26b -aee9d64caf28596308782cd8f3cf819506daf3378f86157ff775e618596411adf94efd0e9542787ca942066f02cbd332 -85871184db314411a49575fee088c52ed5dba4e916ee001ec24d90898a0154d9790a06aa8a707ca7a8b986c0293b8d89 -8d3d87edcc0187a099c97b581a598d357a41ac152303bb27c849eb78e72e15cb97cf9a0468fc36f245c3e152c76bb7dd -900475d165dec18b99eb7b5f9e9ad1d2d4f632e55fdcc4c5ecd7775fed462990e6aaafe9c669f40508f9b15f00bda31f -a25b5954edd57e7811a0d18532043d975c7b44b80f65cd630935d7b16ada05f30fe2b7be7ae8a2f54c25957faf3f1950 -a089019afa3a7a15f7e7874e73b6773c0a824e6d3379b4c928e173321fb165ad979a6be004d394c28d19d410b2655d3e -b28f46797dee0c538bd3de815df641a0ef718ad3e52b2764aec380d6905b38b50ad6f60d0f68e096ca39960ba7734355 -b0ac155d3d05851b04104e6b459f1a68e9e155437c92421a7c0e4dd511ef89cf71dfa3cc920769492ee283a65ebf029e -813c69a810745580d43d5b5480f0ba81000fbef0071e6b655c7346bef5ed774e9214a7816d40eb1774a5bd033767a046 -b176345ca75c64f10ec33daa0dcf1f282b66a862fcd3d8d66c913f9a02db4c9d283dadc02eff13aaab94bc932a42234e -92560f67e5b995db4a489bb86ee78b4aee0800143b3535ad557a53e9e08716bd0202d9f5714722c2a5e8310046e3f5b3 -8adb427bad9cc15fc6c457a96a6750dda8c46d859c5f69bf0e7ab8fc0964430b33967fd47cf0675b6ba1757f91255e6e -b120f723b80389a025b2daa891b140b3d7b8d520ae2a6a313f6e3d365a217af73292dcb249dca1f414ec05e865e3cdc7 -a61a5d261a8dfe5996c42ea0a5ae703a2adcfda80e86837074d868eee16f87d38da19596c48b55dbd7a7cbec1a9b4996 -99dc921eacc6bb867c5825ad4c83bc4af9dd78a18b3d0e1a60ad493e3805b8fb9b7922b577da1adb3d805edfc128d51d -85455fa165a07282aaab4a5bfb88027f47b9532e4af8195c048515f88b0db7e80f42e7a385fd4944faaa7f2a6544ad17 -96dff2d1c8a879d443fe576d46bcceaf5f4551d2e8aad9c1a30883637c91090de99ad5eec228eb5febf93911502d3cbb -a87eb7f439377fb26c6bfe779701f4aea78dd7980b452a386afec62905e75217a1996c5234853432a62ef8bab21c31c3 -b598278293823e9ccb638232a799211173b906444376337fdf044d0227d28fcc4c5867e6ecb3200e59ca0b139e71cac9 -aa6fe147edc95027654d68140f428ec53cede3552c5f49c09d18bc6f6ae8c739a63042eb7291d14d717a4e1f0778abcb -ae8ee18913d328b2fba71efe65526d3ee9c81beda53cf776baec4019ea30212010758cbb5dc85ed6620ce04b189f01f2 -ae9fb686777e88dffdd42805fe4114aa0da1b350d92a27ff3f8a817fb25af1fcfc9a06155affe0273bf13caad16a5351 -95d372ba3a2ee38371538f34aae91b4844488e273f70c02f1992370f89fc2343eff95692d52ce9f21206abbee4959958 -b15260376f0a34ca2827ff53acd7eaaef94c9acc2f244b36500423069cb1cdaa57ac8dd74adb5b53d0fd4265fcbb28ea -b0ffce6a8059537ef6affdbbc300547ef86e00109289239b0c6930456c562b4ed97f2e523963af17736dd71b46c44ac7 -b5499a1277d34f9892f7579731ff53f423f2ffffa9ea43a6e929df8c525e301396249a2324818a6a03daa0e71fcd47b3 -98dbfb8e97a377a25605a7665d4d53e66146204d8953afda661ae506858c5cd77ff7f21f5f10232e06dbc37378638948 -84177e27e6da0e900c51f17077f5991e0e61bff00ca62c1623e627c5aea1b743f86eef6d55b13219a1947515150bade6 -b50407bb5c61b057ab8935df94fd43ca04870015705b4f30ceac85c1035db0eb8293babc3d40e513b6fb6792ecbc27a9 -988699a16917514e37f41ab5c24f4835ed8a2ca85d99972646fcc47c7e2a83c2816011144a8968a119657c4cda78d517 -920c43fdcb738239ad542cb6504ab34498bce892311c781971d7db4dec70e288676de4d8697024b108cfa8757fa74035 -aaa106329aac882e8d46b523f126a86d3cee2d888035ce65c0be4eaae3e92fd862f6ac2da458a835539cccafaba9e626 -96e4c1562d14b7556f3d3e8a1b34ea4addc5a8170e1df541dc344728bcb74cd1630eb7ba4c70e9c68fd23c5c5d5a729b -a616ac5016d4e68e03074273cd3df9693ee0ce3458e8758b117a5c1bc6306dd2c7fad96b1bb37219c57ac62c78ad7a3e -8db7d9b20abfb1445babd484ae9e38ff9153ac8492230d7591e14e3fca7388a5ca6ef7d92ed445c8943cf5263e4a6ad7 -88464134221aa7134878eb10928f31c8bd752ab68c27c9061c1de3f145c85731a4b76acdc7e939b399b6e497f9e6c136 -a5f7c794f70b7c191c835dded21d442b6514bab5e4d19b56f630b6a2f1a84a1d69102d7a0dcca256aab5882d3f30f3ca -b96b6f98b6817b5fa6b1b1044e2411bdf08bf3ffaa9f38915d59e1d2b9bed8b3d645eee322ee611102ce308be19dbc15 -92c26ade2e57257f498ac4ff0672d60b7ea26dad3eb39ed9a265162ccd205c36b882dba3689758c675f29e20836b62d9 -8379a0299e75774930577071d258e89e471951642b98e5e664c148af584d80df4caa4bd370174dae258848c306f44be5 -a0e53beda02bd82bf3d24bd1b65b656238128e734b6c7a65e3e45d3658d934f909c86ca4c3f2d19e0ac3c7aae58b342e -8ca5ceaeaf139188afd48f9bf034d8baf77bbf9669791c7e56ebf783394d7fcdf2a25fa4bdfcddfde649aa0dc67ccccd -a8060e6448844e9db4e9fb4da1c04bcf88fda4542def5d223f62c161490cf1408a85b7c484341929c0f9ce2a1d63e84b -af6e1a5ecf50b754bb9eb2723096c9e9a8e82c29e9dcaa8856ab70074430534c5395534e1c0ed9ce98f4b84d4082fa67 -81c8dbbef98f1b561e531683d5ae0f9b27b7f45dc6b2f6d61119ca0d559bf4ceb676d320afc5aba1811eeef7547a59d8 -85b46cd64d605c7090a2faf1a2aadf22403b3692b3de1d83e38b2de0108d90ac56be35b0dca92c7a41c4b179a3567268 -8dd3cc3062ddbe17fd962c2452c2968c73739608f007ad81fa1788931c0e0dda65032f344a12249d743852eb1a6d52a9 -8630f1707aea9c90937b915f1f3d9d7ba6bda6d7fdef7a40877a40c1ee52471fd888f84c2b2c30b125451b2834f90d3b -b4a747e0bd4e1e0357861184dacec6714b2b7e4ee52fa227724369334cf54861d2f61724a4666dae249aa967d8e3972f -a72de682e6f9490b808d58f34a0d67f25db393c6941f9342a375de9ca560e4c5825c83797d7df6ed812b71a25e582fff -8d5ea7d5c01f1f41fffe282a334262cc4c31b5dcf31f42cc31d6c8e37c9bd2f1620a45519dab71e108fe21211c275b6c -8ccdc7e3642c2894acbf9367f3e99c85963cea46dc5473d175339a2391be57dd8815feacadec766e13645971213b9eb8 -858e9b5fc8c13b651ff8eb92324bdda281db4cf39f7e7bd0472908b3e50b761fa06687f3d46f4047643029dc3e0ceeaa -ae20d36c70cd754128c07cbc18dcb8d58b17d7e83416e84964b71ccff9701f63d93b2b44ec3fddc13bbe42ebdd66221e -860dbf7013da7709e24b491de198cb2fa2ffd49a392a7714ad2ab69a656ca23f6eafa90d6fdc2aa04a70f2c056af2703 -8f809e5119429840cb464ed0a1428762ba5e177a16c92581679d7a63f59e510fdc651c6cc84d11e3f663834fcafeafdd -8d8a8dce82c3c8ea7d1cb771865c618d1e3da2348e5d216c4cbbd0ac541107e19b8f8c826220ca631d6f0a329215a8d6 -86e3115c895ae965b819e9161511540445e887815502562930cedc040b162ecb1e8bdc1b6705f74d52bf3e927bc6b057 -b9833b81a14115865ca48c9c6a3855f985228e04cbc285f59bf163dca5e966d69579ea4dba530b1e53f20bd4dccdc919 -a71f5801838a6dbb162aa6f0be7beea56fadac1a4bcd8113a0a74ab14fc470a03775908c76822d64eb52a79b35530c05 -a77ab73ae94b6d3378884f57eee400eff4a2969aa26e76281f577a61257347de704794761ea1465dd22a6cc6304fbc4a -acd1c5df3c487c04cf27f002e81f2348a0119349b3691012526a7b0d3bf911cdd3accbc9883112ed2ba852145e57fe68 -8a28515a48832ac9eaf8a3fb3ad0829c46c944b4cb28acbcdbca1d0d4c3c623a36cda53a29291b8f2e0ea8ee056b1dee -846bafca11a7f45b674237359b2966b7bf5161916a18cf69f3ec42c855792d967d3bf3f3799b72d008766206bb7a1aa3 -b24b341675b1db9a72c3405bbe4a95ccdfd18fa96f876ec946ccb5108f73e8816019998218a036b005ef9a458e75aeb3 -b99c267b4a09193f3448bc8c323e91ef5b97e23aeff227033fe5f00e19bab5583f6e5fcb472ec84f12b13a54d5c0e286 -a088aa478dbe45973b04ecafbcbd7ee85c9a77f594046545cdb83697a0c2b01b22b1af0b97dd75d387bb889e17f17aa7 -a0c6b0cdff2d69964134a014e36c3709d9e63f6463c5cd7b01b6f0be673731b202d577539d89dd57a888326da1df95af -b4e6dc4ef11b2b41794ece70a8968e56705199d183366759568b6fa845d2cae127486e926b5b27ae9118bb21d1682c1d -a007804353f174098f02540a57e96227232444d5ae0a24232c244647148b6c049848cbd2b50d0a25af3ca9164bfff8ee -873fb034cc39c9cee553ece908fbf315f62efbc412b9afdde6a1889326b7f6f813e050b0601ba9921688e958cb75942e -b5676c90f0106c40d8683299e59d564f505ec990230cb076caef3ae33f2021e6aa5c9b27bb8fead05fc076df034c28f5 -b5a67fc4c5539ad1ddf946a063110f824f7f08d2e4d30762c9d437748c96c9147a88efc22260573803ab545c18b108f2 -817ff2b748a949973a91b69b0ec38efbd945aeb26a176d19f0fb76e261c7526c759e6f5516f9ed34de6eb1ac7838c9cb -99b76bda3526a5d841e059010fdb14eb2fa035a7d10463373a062a98c3c1a123e2da0848421dd7546d776438fd05e304 -aa0d363270f90d56bbee7ea577b0c358532bda36d9247af6c57d000044a97ba41e35bb0db438f4c94551c6350e4e0674 -acdae205d05f54b9544be96c9032350511895ccf413dbbc56d1f03053185df22a6d5b7ffcc3fbe96c3e2ce898ccfa73e -b091c220a1de18d384f50dd071dca4648ca4e708162c52a60e2cedc0188e77c54639f75bce9a468a64b2549119c07ded -878676133e5c700b1d4844564fa92a9930badb5293d882aa25ee6721a9f2cfab02088c31d62cf1342ae3edaea99a1ea0 -9756d0793e6aba3b4dff48100bb49a5ec08ec733f966cb438379b91caf52fc2a5930830ec3f49aa15a02c82c1914dc7a -9722f760184d3b2d67cb2cea7fa41b1ff920a63446006bd98c6347c03d224d2d8328fa20ccd057690093d284b9a80360 -b5a68489de4f253715a67f0879437bfe8f4dfc4e655ca344848980e6153b1d728acde028bb66fd626fa72eedd46ff683 -a8cfc900b34835d9fd3add08044636f69614eff9ae929eac616c39bd760fd275ee89bf24b0f275dd77a66e54fd6b94e5 -89967479bebf70b2893cad993bf7236a9efe4042d4408022fdbb47788fabedcec27d3bba99db778fcde41e43887e45af -889235938fcec60275c2cf0f19d73a44d03877d817b60bb26f4cbce09db0afae86d42d6847b21f07b650af9b9381fa82 -b7fc321fa94557d8fbdd9fff55ab5c8788764614c1300d5ef1024290b2dbb9216bce15cb125da541f47b411a2e7e3c2d -b11b0c4dc9477176b3cda6b17858dbd8c35a933ed31364801093f310af082cb5a61700f36851e94835c5d4625bf89e32 -9874e54d2939ee0600f4194f183877c30da26d7515e9e268fea8d24a675dd2945d1565d9016b62b1baab875ac892f4d2 -90df3a77280d6f1fa25a986309bba9d5b89c3cf13656c933069bc78e6c314058716b62eacfa7ab4aff43518b8b815698 -962b08299a287d77f28d3609f39fd31bc0069f7d478de17539e61fcc517045050644b0307c917208b300ce5d32affcca -b30eedca41afb6f083442aaa00f2e4d5dc0fda58e66aaf0f44e93d4af5c4bf8ea22afec888cacbf3fae26d88e8d344cc -847747a22fab3fe3c8cd67f3f1d54440f0b34ce7b513225dc8eb4fa789d7d9f3577631c0890a3d251e782a78418fecfa -8d1ef3cb5836e4039b34ee4e1b4820128eb1e8540e350309e4b8fea80f3ae803d1f25f4b9c115482b324adf7c8178bc7 -8f8a2b0b0f24f09920b58c76f7d99ec2eb2e780b5a66f2f30a9ed267dcaea0ec63b472282076c7bf8548211376c72f6e -831ee6dc8889bbf4d345eaeb2f425959c112d2190764abbbe33bc44e1d9698af87ff5a54d01fac00cfee5878dee7c0f6 -a7eb2479ac80d0ee23f2648fd46c5e819ad3a1f4752b613607ae712961b300e37f98704880ac0a75f700f87d67853c7a -aa4d1b9cec62db549833000d51e83b930db21af1d37c250fdc15d97bc98de7a5af60dbf7268c8ec9c194d5d5ccda3c1d -87396fd7e78c4bcf270369c23bc533b7fb363ca50d67262937dab40c7f15bd8448a8ba42e93cf35fb8b22af76740d5e1 -a958b2a9ffccbca13c0c408f41afcfc14d3c7a4d30ea496ce786927399baaf3514ff70970ef4b2a72740105b8a304509 -a5963a9dd3fe5507e3453b3b8ed4b593a4d2ced75293aee21bfed7280283348d9e08bf8244c1fce459aa2470211d41ea -8b06ddc3359827558b2bb57caf78b3e5a319504f8047735fcc8ec0becf099c0104a60d4d86773e7b841eb5b6b3c0cc03 -9437e7278283f6d4d1a53d976c3c2c85c5fe9b5aec7e29d54a5423e425b4be15400ed314f72e22e7c44ee4bacf0e681c -b56067ee26a485ed532c16ec622bb09135a36c29b0451949aa36fee0b0954d4bf012e30d7e3fc56e9f153616b19349bc -a5c72f7f5d9f5b35e789830a064a59c10175093a0ce17654da7048827d0b9709b443a947346b0e5d96b5ea89b8d7c575 -a8318d01182d4c9af2847a29a6b947feef5795fc12e487a30001cc1ec482b48450c77af4837edfa1aedf69f0642c7e5e -82ea421c091552d3dafa7da161420cb5601b819e861dd2ba1a788c3d1b5e8fa75cc3f2b0db125dde8742eb45b335efa2 -8679fd1c7771ea3b12006d4a972f4f2892e61f108107d4586f58ee7f2533d95d89b9695d369cdace665f19c6bc3bc85e -b5ab3e8adee4c950fce4d33a0e2f85d3d886e60a6e2f4454b57bc68725f0cf246372d863167482cce1ea10a7c67c3af2 -a85696927075ec188979180326c689016a0dc7a2f14ae02ea27c39ef91418cd44177d3fca5752cf6b298fd75fa012e26 -a44f87b7232f102cd092f86c952a88afb635484a984da90a41a57a3d883c9469064bf105b9026024090486b6c6baa939 -866ac91a437db945bbfdc11fcee583f3669fa0a78a7cecf50fbfa6ed1026d63ad6125deba8291452bf0c04f2a50e5981 -b780d5a1e278fd4eef6139982e093ceafea16cb71d930768dea07c9689369ff589d0c7f47d5821d75fe93b28c5f41575 -b025d0046e643506e66642c2c6a5397a8117bbfe086cee4175ff8b7120e4f1e6794e1e3f6ec11390993cca26d207ae43 -a04a22b6e28c959ab265c7f48cde42bb6a00832c6beb2595b5df2879080a9424890960417d7d7ceb013d697d0ebf7267 -81de9c656ac27f54d60d0252e33aff4e9e9e9c3363a50740baf15a2b9061f730a51ae1704e8c4a626153cf66d47f19b1 -a15fab90599df889df11fa60c752948b68fba54005491180dafb66c5775547976d0eef33945e55d4818653e0818c6f92 -b06f9be44ddb103a72fa4ebc242c8ee1975fe9bf9ef7124afeda9967ff3db644dbf31440151b824869406851a90984a2 -99abdfe6806ae5efa2d11577da17bd874d847c5f810460148bc045bcf38c4fd564917eacb6ed61bb9164ed58055cd684 -ac53231077f83f0ae5f25e52b70bb6105d561c0ba178040c11c3df8450c508ed5df34f067fdaacf716f90b4926f36df5 -99e3f509af44fc8d4ebc693d3682db45fd282971659f142c1b9c61592573a008fc00502c6af296c59c2e3e43ed31ec7a -98f2f5819670aff9a344e1c401f9faf5db83f5c0953d3244cfa760762560e1c3a3c7692bb7107ea6eaf5247ac6fd7cc8 -b5b9f90391cec935db8d2b142571650fcbb6f6eb65b89c9329e84b10bfa1c656026674d70280ade4ba87eeaf9333714d -b0696b77ca8a0cdbe86cad12f358880926906fb50e14f55b1afc1e08478ae6376215cbb79bc9035de2808c7cd2b13b85 -a51d746833062a65fd458a48a390631d5d59e98e2230b80d8f852cfc57d77f05eefcfd3c395ade1e86d4a39c2141365c -812d67654319f4ef3c9e4a2d4f027a4cb7768f1ea3f5fdde8d1b79187a4b874ff9a5c70f15b7efa079c2dc69d1b9b1fe -968978b653c6416bf810f6c2ffa3d1abbefbd06f66b6686e9a4fdce3f869e0ab1e43cce14dc83786596761c100ae17e1 -98e1e6ab562ca7743783b802faeb0a24f1341abfb9655f106920aef08964a3c0e8083e1acda7ae28fed7cdd5478decb6 -a91c0b982a0a7085a103600edf99e9d0bee4c4e7db6d9f8f376c215c7d42476218462a3765f2928e12c3dd49d688e4fd -8a43395b3124fab9e2438635bf88952e8e3084dad7ecb3a9927f9af0e0887bce4707084043671fc98ad03621e40a149e -b0b37626143d4a8c6f5693d5f1fe871525b4dd946c4239cde032b91f60a4d7a930d7ba28959737550d71c4a870a3a3be -b01c74acae1715c19df08d5f4a10e0c19d1356264eb17938d97127bf57e09ced05ba30d0fc1a9f32d6cff8b0d5f91c9a -b4c2328eb8a5a673406faed8f0aebb8540d2791646e37ce46e0e382506570ca276eb6f8e166dbbf9e0a84064873473b9 -85cb9f769a185e3538e4a4beda9a008694e1bf8dfeea9dc07c5c40a9ceb1d31fcb13cacfaa52849ba1894b5027cb8c30 -8742f91cddc9a115ddc73982f980f750d82d3760f2d46ee4490d5b17c6c3bb57c7d4c7b8d6311b7b41e59464c009b6a5 -948ef86d17128a061e1bdd3ea7fcc7348e3ec87ec35dc20a58dd757d5d18037fe5e052bb359e27ab4c2320d9a52a6a0b -a70f6a214097c271e0d2d95e30fce72d38c30a2f186271fdff0e38e005aff5baed53739b8c4f9501aa7f529c5cb2da59 -892a7574cf6704ad75b346c95ae6f2668904f1218c35b89b07a0c2dbf3c62173c348f6fd9473926eef56a37c0f635c04 -837e85a41f39b4ded1420aa8fc3be46a7adb99305e0928c6d7643b7c44434b72984cea08eb68f5f803661df0db78c87d -94e495329f2aab3eeb68f347961d1006e69d990095877a4dcc376546233adf29a14bf6b16a0c39aa477e15368e87014c -851860a8fdf76a97048396553262637dade27f1f63f926997e74c7c72b14b10293eae7824e8dedffad1aead57c124f79 -90481017a250972055ab1cf45ff17d2469517f10f18c9d4ef79a9bdc97a49093289bbacfefa8a1e491bbb75388b34ac0 -983db15f7463df28091c691608ca9c51095530fa6b1b7b5b099c612e673d29e16787cc9ae1c64370ba6560582ce623c0 -a477dab41014c778a1b78a7ce5936b7b842124509424e3bfc02cc58878c841c45f9e04ccc58b4f2ff8231488fff0b627 -868ebba1c85d1f2a3bf34c0ab18721ea725378b24f6b6785637ee4019e65d4850e051c8408fe94a995cc918c7b193089 -93cbf4238a37ccd4c8654f01a96af809a7d5b81b9e1eab04be2f861d9d2470996fb67367e5bf9dcd602dc11a3e4cf185 -83113f4e696030cca9fdc2efc96ba179cf26887c677f76cde13820940ad6891cb106bb5b436d6b0f8867f2fd03933f7d -90c709f4e3359a6d215d03f45ad5cf8067aedd4aab03512dd62229696485a41dcd64e2acce327fda390e0352152fce13 -9945cfced107a36f3cf028ba04c653360afc5013858b9a12fac48802efcbc198c9baf3a7f9b23dfdd5036e88bc7274c8 -832ae60192b47fc735a8ddeaf68314b16256c90ab68099f58e43073e249c6939895c544a02fa34e40805bc6b5db33461 -8b12c335818b643c1d22cbc2869606cf64e7ae54a7713617fc4dd3b2f052ebd6b920ca59ba2e9c7aa8cf71bb4f40f9e8 -a2033eb7a373931c65d66989644aa0892ac3778b9a811b2f413d8bf534e282c339717979f9aa742162abb3468c195f87 -aba2b4c37dea36bed6d39323e5f628ab607699c66767f9bf24ef5df1bfcad00c2664123c0d8d5bd782f1e14a06f4c769 -b71963777535b4d407286d08f6f55da8f50418486392a0018ee10f9ae007a377b8b8336f33386b0eb01c45695c3ed2da -88dc87826941340913b564a4f9b74985a311371c8e7b47881235d81c081f1682bef313c2f86561a038757fb7d6a1a8dc -869e13e3fcf91396750150f9dc9307460494c1d365f57893fd06fb8acf87ac7dddc24e4320d9cad0414119013ea739b8 -92194e292303d32b91ae9cecb8d6367c8799c2d928b2e2846dab1b901371a4e522fc4089aad8f4ee676f0614ff8b19d7 -aa589a3e512cb4f8589bc61e826a06d9f9cb9fdfd57cf5c8a5a63841435b0548e30a424ca3d9ef52bf82cc83c6cb1134 -81802e0194bc351b9a5e7a0a47911d3a0a331b280cf1936c6cf86b839d3a4ab64e800a3fe80ea6c72c3751356005a38b -88e5e9e3c802314ddd21cb86f2014948b7618502a70321c1caf72401654e361aac6990a674239afa1f46698545614c93 -abac1e0f85d5c3ff6d54ed94930c81716d0ac92be49e3d393bed858833f4796c2b80bf7c943e7110de7b2d148463bfbf -b7eb416004febd574aef281745464f93ef835fd65b77d460b6ad5d5a85a24b536b4dec800cfe80ae98489e54447e8bb6 -b3fd8ed1c30e7c15b0bc0baf0d9d1ecad266bafb281cd4e37c55edc76c202fb1e4ea315a91a2848f40f481793ae35058 -86ef674ddf4b7d303c68bbfb53db00b925ccbf11d7d775ca09e458f4ecd868ca828103e8e7cd9d99672a193e81b83923 -95ef414e9f7e93f0aaaeb63cd84eb37fc059eb8b6eced2f01b24835b043b1afb3458069c45218da790c44de7246860c9 -93ec8f84c20b7752bfc84bb88c11d5f76456136377272b9ac95d46c34fce6dcfc54c0e4f45186dd8df6e2f924f7726ab -95df5f3f677c03a238a76582d7cb22ed998b9f89aecf701475467616335c18e435283764fb733fb7099810fec35932ae -8cda640695c6bc1497d19b9edc5ff4ea94c1c135d86f573d744358758f6066c1458901f9367190dcd24432ae41684cf0 -b19aedf5569435ff62019d71baa5e0a970c6d95fe4758081604f16b8e6120e6b557209cdea0ccd2efec6ff9e902d6ce6 -b3041f21f07d52e6bd723068df610aa894dfdde88094897593e50c5694c23025e412ef87a9d16cadd1adbb1c6e89ced4 -a7f8d6ab0a7beb4f8d1cfef6960ebdaa364239eca949b535607dee5caeff8e5dfc2a9cfb880cc4466780c696cff2c3a6 -99a565b4796e2b990bfcb234772d93c5ffdbe10453b5aa94662272009a606ba6ea30cc0c3c26aa22982c1e90738418a5 -90c54b55ff19157c1e679d8d4f7f0687a70a27d88f123179a973c62565adfcc9347cfe31f54539038cf2f34556c86870 -8612f34bcd018d742202d77d7ce26cf9bc4e0d78e50ddf75250b9944583b2c6648f992b635ea13fdaae119764e7c28d5 -a04fb38e5529bf9c76ec2b5e3a1ef3c6f9effb6246c7f67301cfed707356ba1bf774f2867c77a5805933f0c8ad0ec644 -b4800e7b503da0164885d253135c3b989690794d145182572181995e6fa1989f3d0324993e871bbd5f48fadd869d8a18 -9981cd4f28ae7b7dadf454fb3aec29746dc2e0ca3bd371b2a57cd2135a7d93559e02132528ccd2d305b639d7ac51613d -a3ceec012dd1fbad3ef9f9f1d6fe7618e13d4d59e3f50540d2a57010d651092979c75442ec8b38a1ab678505e30b710d -8b97b8654d067fb4319a6e4ee439fb8de0f22fd9db5569ba0935a02235cb4edd40a4740836c303ec2394c59a0b96308b -b3d1bf4410fec669a269622c3ce63282c9ac864620d7b46c9dfcec52d8e79b90c4c90a69c32763136a7f2d148493524e -93174eba1e03f879e44921084aa0ee3562e48c2be49085de96ed7621c768ff52324d14c8cc81f17d7ed50c38ffb2c964 -aa2194cd0fb7aec3dac9a1bd8ea08be785926ed6812538be6d3c54218ea4b563646af1f5c5f95cb914f37edfae55137d -93f2c0dd59364f6061d3da189e04d6c64389a3563b062e8f969a982cd68cc55b4f38b21546c8a67c8df466ff4f61f9c5 -aa7dd497cc949c10209c7010ba4ce8a1efd3cd806a849971e3e01716ea06a62e9d5e122ad1d2b8e5a535fae0a01a7761 -ad402424b2a32bca775a66aa087580d7a81f0867f293f1c35580b9e87ccc5a2bab00c29a50fd0d7bd711085ae2248965 -96237843d8e29ac77fc6ebf4acc12946ad11697de8e5f152fe5776f2475b790226a7d156ac48968dd68b89512dc55943 -a45c25cdbb9fc327cc49a1666988af9ab4c5f79cea751437d576793a01c3eeea4c962c05c0947852fe0e4c63e1c84771 -93dcf834a614a6f5484cc4ba059e733ab5dcc54253229df65ff5ad57b447353ebbc930736a4c96322e264e65736948dc -b9a94f82a82c0c5a26f2c1d5381afec3645e8ee04c947dc3b7ad59a73018db1e9965ab3642f2bbf60f32c430b074fb22 -94eab29b3524ccbe0c4b928e5fa5dd8f684074b332fcf301c634d11083653ffee4f7e92ddbcb87ed038024954ad1747b -b8dca5f679931d6abef0674bad0639aefad64c2b80572d646aaab17adf5ca1ab2ebeecd5a526cadc230bec92ed933fc2 -944d394958e539251b475c4304f103a09f62448b7d8a8eaef2f58e7de4f6e2e657d58d5b38e8513474115f323f6ec601 -8a5ae1f13d433962d05df79d049b28e63fe72688fc3e6660aa28e0876a860c3dbc5fc889d79f5c4dec4b3a34cdf89277 -afa5278724998eced338bb5932ecf1043d2be5dd93f4d231d05d2ea05b4455f2ffdc0eadcb335dcace96dd8b2b4926fb -b91153a2f4647ae82fc4ee7396d2ca23270ec7f8884ce9eead7e9376270678edd42dd3d4d6c003dfc2dde9fd88cc6e7c -adc932f1c679bf7889cb1ff4a2d2897d7973483fa283979a0ea3640c80ed106ea0934c1961dd42d74b22504be49851f2 -a82e90761fae684d1415cee0649bb031bcb325ae0b28f128ab8e3650bccedd302a70de1a341ca8decfdda76f3349cad0 -8ae353188b4b98835f4ef0333cccb9e29e1ac3ec11d554bc96f5880c101cb3c84b8eefe72f2287b0812735339fe66cfa -b8b41135bb1a1ffb64afbd83e2189e755f2c350e1273cf47c38ae9b8c4800d831436a69458b8ef9fa8b95a148d8ec9fd -96f75a04d8752fa93dc1eaf85ad333cff4eeec902a345576139e16de3a88eeb71b6726224349bb9844065cc454d959e9 -ab82b05e3923ad4c26f5727c60dc0d23063c03f5a4fd8077da66aa87042cad1bd99586d4ab35aa5e4ce6f4da6fecf3c1 -a50c83db91c26ef7bf1720d8815b41bd056b49fd99710943679a162ccf46097a7a24585750ece886e38eb4fdb866fa37 -a719f667914a84f62350dcc6f4f30b9ab428eac6837b70318c3ac491c1e69d48af5e1656c021818f377d911fe947c113 -a148807aafddfa0a5624c7cb9e42468219e4bdb9994ec36bc19b6e6d7c4a54d3a0763d13ca80624af48bbd96d73afca5 -aa012f205daf22a03e9fb13a63783dda7666f788a237232598d02a4d4becec7a699ab493f78d722ce68519262924c708 -97fc15fab5952c5a2d698fd6f7ad48aff1c8aa589f7d3b14285fea5e858c471cf72f09a892e814104fa2b27eb9771e73 -8da8840236812667c4c51c8fc8ab96d20dae8e2025290b9cde0147570a03384370b0fcbe20339c6aff09cca5d63e726f -b477d85359a8e423fed73409f61417a806cb89c9a401967622aba32bf85b569e82bca1b3394c79e180114a0d60b97316 -b3d6ee2ed1e4c5cf8ba2c3a4f329832e41c7fdcbcda8a3fcbe8f60967fdb1717665610b7c1ac65582534d269d762aa09 -a0b3b30b1b830b8331ee19f96b4a4321a6b93a3395b95d3a895682c65ec6ea64774b878b93514eaf353f2e4be28617b8 -a2b88e9617f4d30ef4e686d1932ad43cd555fadcb5102e51bea19e6fca649284ccf4debb37b5cb2090ef386fa5bf5327 -8a4446f7e8463ea977a68d6217a9046ad4356d6fc1c18d46c5d2ab681ea977b8faff136d65abea6bbf8936369cb33117 -91e7464bc56e03f436228104939ddd50caace5a38f68817bb2991e193b57adf6835152bbf3dbcdebf0382ac9823f60c9 -961a441e6cdf8106c4f45e5b47190d35644faec701c9cfc41ced40cfdd1fa83752fd56c1ac49131a47f1970a8f825904 -94b7b165cc71c2ae82976b8f03c035fb70e90028992b853aa902c0467b384c7bcf01d56166bec5def4453e4d0c907e52 -a5d32cffabbf547f900026b34ef46f08075b7a244565f615370d2f04edf50b094c95088a4a139ce07caf55bcd99afa07 -b4e06e73660745f75ab2f34d9f6d2675b58f80f911ab6dd4c5a6ce1095f9a2b50d86f6ff9a05394190bdf96af0827920 -ad3fd8f83c0103b29d41319209dffca201d2b98094362da08da3fd6ff0ba96796b49d6bed525c9adb96c2954858e7f48 -b0c27430695f0fd20ae31e1ec621da090094f2203e17411db9384695ffcf5c7c6badf461ba49ba70164aacebd6f278ee -b9bc6e972fc3b532fd2b1eeafc4bceb77604885f32132af6a9a842fa2440df452f49ec0cd9d86da1180e8deb0723b260 -9729e22d6104b0174c136a854920f542b384d375040adcebe36acc253bdb55845eb43e34dc5a7cc27d22c417973c24d0 -a8b420b36d48786c9231d454468a6e855dd7f71dcfd095efc9855ee70dbece0f06ad277f7829c5813fc30524c3e40308 -8757dff5499668c93fc5d9cea0a8db61817b8ed407200d623030b5849a913d12f8371b667cfde8d8082026eda7407e8c -b859ad747ca5af661fbd03a1a282df6e84c224ecea645bc2d4ba5e35fa06cbf047387319fca0cbc76b712398c0798968 -8e3173c27875f1460297af0fa736c945dc842ec3e476a973d3d5f790bf183ad3ffe96ac13868c5101d8e299890791864 -a9d725e2b92c878be42b5eecc2c3081c63c7231ccc7e2dee17ca6a4caaeae22788fab1f1465fcbd7fc236613fc2bae4c -86f6c4f04a354cb2470ef91914816fd740f8d5795ce7ff981f55a2634695fde5951bbae7a4bbc4c63747040f8644170a -851773cb26f320f0c3f252d95ea7e058ffcc795dd0dc35e459aa1b6b448238909230d809e82022e64b7fca5d40b8324c -8962641e0306220d9892fe2d452caa286301a3c465185757be7bce2d9b2c9beb3040280099606cc86773e43941fd3439 -8beb6e08c440b0de5fb85251d39d9e72db4e556a2dfe3dae59efd8b359d08492064cebd8d8993254b43bde8bd67d969a -a7e047894466ffe3dec4ab8d5462f2b1d8ac0df006b1d2dd26caf499ea857d93a811cf42233f9e948c9cb903beec004c -92eedd95557a91691a5e2835170390ce2401e223da43b78615a804c49566f9d31cbb7f10c8a8390c4bdcf691544fdba9 -a5e5b5d8fa65824e958bbae98d146b4b332f97ed50e0bc2c58851dc2c174ab71bcbb1ae015cd2955c26b368487dd862f -853a494eafb308175629d581ed04bed71bbc3af9ca4c0dc483d03d27c993a2bbd88cea47c2085a6928d166fe6938fb77 -83f06b88d29afbfbe8f61811690322ac4fdd6abb9a23612162e7a2dd6bcbb5f14cee298ebebc1a382484f7346dc51e60 -8c9cf05735ea5a0e563490bdc7ed29a4426643711c651e35c8551ca6f855c8458ae8f0933a022d0bb9a952edfed411f6 -b906b48d807748a26cc2a8848455a76ce502261afe31f61777b71917bdf7de2fece419db636439478c7582058f626c29 -97efe1fa7c9b25d8bea79d74b6cdcf88f63f1e865f54b58512a2e60428630b0b40b8b6af1b5f71df47520507548c3cad -8ef5ca6e753818906bb3fc71405928d8e4108854ef0ef01c1009071b353bc2852e771fcb619d5fea45590e8f61003d7f -8e4d901661e2913740d70ba4d0745df5e8c9c0a260149d9362beadc7e669630ba909ff0e8a6cc85c54d6b7435d0d351e -b7c6ba3bebbd9592967954e3a480ee8df1d9f5965f04e7d78a5415b645128deae7ddaf6ed507c8877bfca91ce078e529 -840bedb0ad4e25acf6cd25dee4f98fea495b2312dc5cb7a8388c5ab00b2acb9cd25da08e9fbead145a3107972b1ccd5d -a8d4578dbafdb27f3911af59962d89e75dea74db55346720357790da677312c203107d9c7911535aa563446fde7d4c47 -86d3b77f231bfa09251b7fd2ce09c27ac520ec35d783e912476f9a4863f83d269eb175790d6e735da9260293d707f8ee -b34909f1cc033232652da0c34051a769dc76adb1aee00674a59dc1b860f6e610974c3b4bb69a69ccc73e01f042431242 -90799854d0cf34e1d91ff8e101bc7c5007423d34d2f3bd9adea2ecac57e83f3a65a506bb93d4caea49b29f6d18149957 -8ef94cde29b037e19a1ce7bf4418ad3c95cd9457412796ea385750c19a6690f13a3bb5bb6a9ee81e7a40face1e0a8bca -97053d21ae8d75972fb37f6fe516c38c32ab162fb56b9f510f954858f4e3ef6ac8c3a9557ed3f41b7b6aef05fe97f931 -90a9f9f0f40991f3bddc58b92d40382147db22cce50d092d4a05aad251b46b94e71ec9f7107a180243288059fcc5ce29 -a14265b1344ac2921b0f890d13bcfc432e4f648ce403e261fce4d3bb32ffee9e2794c02830346054f998e82784c77040 -91928402ae121e56a3e64cd6f390127e6e92fbfb1967ec6efa4f52f3e8058f1f41a0f4fe96b5bcc11641c1139e790b2b -921c8c92b6d40da6c5a7b592acc74fc0f577d93767b9aa4a1cd302a72dbf503a1ea5b2c29fa0d0359bff3b8f252246d1 -93ae0ebe0e8e133fd80cf67a499047e30ec4c4660ccec9d49098717ef57721a030f423e00c5e74af4ff4acf014a10497 -82c865e21905aebfe0496af1c6ac7e342b5f446a9edb4f7da0f2fb0340abfd8e6fc545da874459d9aabe6bce0dd9bfcb -aee3961d8d2687c0f134b9c28b920bdc4021d925fbe14323c84224a9fe161248789249fb85436a5891d0bbff42c2a3e9 -91aee420b98b6949482b8ff4be996b97245b4e8f583a6e085226539074f42aa89818395efd1a6699735a569bfe19d623 -a48eec22c192e495b01722d0016a54acc45ff837e2a95c4294ce81d5a4e43e0053a6f0ead8a4fb3ddd35faf6607275b0 -a26e15937c11faa30ffa64817f035e294cab0e839f73d29de8a244ad039be4e221eb47ea08d9a4658b0152fc3caf6110 -b84450f948aa7c8682fccb9cae84d8e3558adf2d0ca5fb81eb200415291158720f8f3470542ab5b88c6873ad08e7fa9a -a8e8ec27d0608d020169a85d6ecdb40eb402f006a3b97afe32cc01987721b3a68a92ec693aeb4d357e189e05fadf699e -ac87cd535ef5699312cc26f86adb71baa0be42e858bd5a2d94ac05737dac63430691e29b9a30d2559ad581a172519b2c -a4481e67b524f8cddf2046625efd3d75efee6aab87ddd2c1b22835647e918157e5e924ac760db2195c86d326f3db1615 -891f29ded231486ee826840c8895cb325f7e84a5a6d2eac246cb3573612cde274720233b1978318a57ed337a046330a6 -906b6e750e6178289012769807d2598925d7e51c260c14497d8af978b1695990e3352e6e809a752f376597a68083870c -b7a056898ee1e46f7f29702fb39232f678ec173eccd170303b3b0a30c8d8cf1a5321384e3513e3b03bb742c238deaa54 -8f2f035fd96c3a336354c89ec9b8222803bf42e95fb2412c28d4e75eec99c1d4d402501ccae17357b757db8bdb0bfeab -81228625ffcedf977fba9cfa13f6edead3985e2651d5974789c394a69401cd7face9e20ae6694be4c0d4bab5e99c61a8 -885a83eae25e61439ad809567a2ab148583402e01cfdd77b0e37ab4038935425c64b4e0886949bf06438c35e80aa13f4 -8926387f48752f6933899c48e038cf14e7941ec6a58bcc0a436614b396296a17aa53e6873803dd3041dae470bd493fcb -95d0d3fa061f4d856eca78a569aa132db14cede7646f97e2aceb6da0c8ea53195d3b7a566fe5ec8c41b95ecdd89a1c6b -a3c817f4062ed6aa94064ea695d76c1825f3bf77b310fe1db28b8bedc9aaacbf1019dbd128adfd53042fb943d863a2b7 -af1208417aa584052da309169854149ede38a3ad63c76cad6e43afb6f1a7b854edf8310a0b00088c039259cedf0f859b -8b713fc3196bad35dbf364089049ada5477e540d78d76a5f0a9df98f7ba4a0e65dd0644509c149f9b07887298bf74b04 -89c09c43c5b733c4a417cd9ebc0795cc3348b72778d31828a9171427779a82ef023c1a4fcfcdc919ae25056f9c826fde -a0759c850ed320c8c874435e90ace6edfb8e7b3f2a09d942b8ad8339c508044ee2ee26c70f1b626ec49a77971433b6a8 -b85cbc58d4fd52286e714ac4eaaa0b2743a1de06fa03ddf8f6668ec6f1d204acccce93b10620272afb8c0b49bc4b0a43 -814e0a87384e159892a8d23036985fa3f489c53bce192e107bd2d64f57b1bf5ea0acc1ef46c7a42bbc5cd0924d92b4a0 -aa6821da96ad89d7881b878e141076522f104ea9a5bbdd1fce9f641898f7d6232c518a87a0f666871d7e3165c26081e4 -a9041d714bfc067b5427252186fa3557bad598fc0067dc8521aa9bc1ae298f6e96113db5ac9f6bade9a85d5a950c9755 -b8669340f3064692625e1bf682d34fbe69a61689e3aa6d6a3e822c781d406b0300dba9c3f7b8152a8c2513f1310d4291 -a78c53316ce768a1dc5968030bf4fc885f4029b1ddb6a5d84a61c85af686c73727f62823891edfcb6ccf4545de366cff -ad1d3aa29ea28292ddd438c865e2b5d93f32cdf009e6d5f5dc726de996583925727e6348bf1c28c22dec0bd86aaf867f -ae1447a2062e9e28af5f38aecc60fe150cd10c2edeaf2110034aa144f6235ed7fbce432a58805d4fe1f6b12652d6e1cd -a32146634332d3303934550705353c6d4fae5fa5985105bba35041e74cd71e2aad67b45da171221f6ed80f36bf6dffa3 -a232e8286184196ea77427b53d8b52c44d758ecc42d22556529db3136379b4989dec61cff610cc6cf6700a450a847a94 -8a72c7255125a736da52dff5f77e44c3de29f88fc05f5ff9227c69df296930caaa11446595e6bea3bd946baac5ef957c -9688a981a9457678067f629f8efa6b522e7318b529f88d37ef56c5bf8f1c34fb9bb3a918ab73caab82bf5abb0c03518b -88286f3eabd71115fc3b17a6bf6981340a81cf7e5f96b0a1a016d4ec8c18fb486d46c70919123d0c189a6f5d6ff29a1e -b535e701b40d793c02ac0d625ca91620d3f4a512aa9741f71389e58381008b2f93d597586d06213c4e103d67d0ddf6c5 -80d0c9dd941e8d8d3700cc51a434a5aaa3308cf8ebfd14128ccfd258f826b27cc3cf5c3ad7851340393abb1eeab3a157 -87049225fa2380d93f18d3d90cb0697a56b373b66d7f24ab209966aed8b55a2790194d5885399db29dd5b1f189eda64f -a52df158ce8670e0290551e8878d63dd33b4759d6f50e448e63fc7fe6ea99dddb6f180be5fc0fc3918ce54c05f80b356 -8b2a728b39c465fb0f60b0c486e5dc8d5845ccec03d3dd93b393cedeeb3fe1b44518359f1ed55fc770a8f74bfeb9923d -91fc05419dba718fa4a910dcf256ebea356bbea00522d8d5ec3e7ba4271a26035aac15e8d9f707969df1d655d92dac55 -97c8779ae80c24c1f82d5a714762d6ee81069224e39515e41d8a71c9310dc5d1c55cc92bc5c6a4bd391ae4c321d1d4d2 -b5e5aedba378c4484e3a7a4ed41b75b0844f674261c2501497de6f91f7274b5a4c1be0e055f2e0c0cab843d891169fbf -8a26212f27211b295beea500abc8e9d430a8500d3a350cc62f895d39e8b4668aa638c17633804ba353010000165637ae -864a95118e5d394e00e99efebd505df0125525c9ebe165764c453b80ad3edc730feebde3d93850745dfd88a27bb8f20b -a092e0b78290e826cc1ae56afffdd08f7c10954f549a3ea6666f3db1b6cdaeb7df53db28dd2a92446342930fe60a27ce -a1720224c0626a081b6c637b2a6d37da85d9a82241e5efef3bc15699b02a69f6304e43d8ff3144d60c16e00225d6b39e -a7b3d098cebea9cf32e19c5195608182b6afe9d4af6b9df532c047eb7a941a971279b2ae6a4b80f2f9d9313a6d788ce3 -a3d2451e6788944802c5077a778d7b7299dbb9d1612676bb6baae78f39976e0fd879493cc4a4d737b8174b472a456850 -930121b73da844571b1411d56760e80923a4ee09917b3e9cff4d3dcb0bc27026ff2c4e2c44e7aca7d3f8383f129c7f9b -b4b0119d163ee00a2b74bdf188a5cdcf054daaa48c483b94bbb4d09ff615afb4a91347db6363bc7535e2af9054ec2214 -a5846decee706780201095a8cdd48fbf3d3a2eac8d089a818e5e22c29457494bbfb4399323b067f3d2be2197c33dbd98 -96ba600df10ee7af5a9df29c0ca31dbed275d647faf9c66c7342de927ceb25b5bdd852dd7aae0228b27897f90fdd5d62 -b6ac51ddc98edd9fb9f54ef84bf372a041d58dfdf0dfdbdc4b08ddc1a7ba93ddbb1413dda3c1545a3fd7386c6b85975c -b35f3efd91a0723e0d486188ea9675a3462106470455118392d7610470b623caca2fa33829721c05fbeb0fabcf570bfc -87f49e85df5f8055714a8ce7adf37f6a278e64e76ed74c60abe3edfc3611ef5b0426d4c6da45e5f3b74d30be1dc6f539 -8ff8bb06902a71b1e9177a77367318b2e3e0a88f5d74d6907ca9943f4f9f1ceb5f297132c2a025259d17a67e880d1bad -85eb6de6c70fe5c53ab0ab27aa0fec439f136c979c557d317337cafa6e6c5cb3169679c9169567dec5f6c72b3c057d83 -ac18715ed1080771d760cb7066c6328faf65d9b30517903f8a5cad8d66d5c6381156b521107d7cd75ebb8c30e250706c -b95b9eae4703727e4ac9ddf2ae675906487bb78905a5f9cba74a4cbfd118d96b7afb6ef3ed5edf14fd963b830d71338c -a3b47b52fda16b62b11c8aa4daa56b0b669c4d5c56a3059b7d063284d8a91f6fff9ccccab23d6ceb9650483b2d353039 -96a95b3f327df94c85e92f2e406f1649ac621533c256b062738f3c3ee137059a735a3e6072247acf57b1b0d8c219bd7f -b19b33cc04570be94eae8e943d5bb17bb0c96e9de4ca84f9f41b37320a1a03d397d53747dc13275fef1b356de557214f -a1faa3dcb931dd91507f3f12a17c43f6627fa2bc5c71fbdd27548e091eaaaba262477949cd51290e81196bffb954a492 -b060a16079dca1d28a1fb33cbc26f368630ee042d980ce305230005d5b9ab533a7a695281ab76e9214458303932d8bbc -b303783196a858fe45d67e0520c30576da605fd69964449c20009fbd5099cf1de52a32d326d7c3b864de07440195ef40 -aa550a4c20d1003d137ffd8fbdc1196d09ad53cfa0e202302093a80fa3bbc4c9aff83f34f2151785cc1ce5f30255693b -a7f8585f45566a351058e10c6f1ff4a7ba24811f1482a47202f581525615ca770da93f2f58878788b45b92cb446ef4ec -8206f63a9a5b59bd68e64a843e68fcdf706f4c13bbfcdfa9928298e5b9251006ae0bbd80c715aa3c9957d2c0148b5059 -ac9490abe1241319658f1c2c645cfa01296f5d4106020c7894b7ba4a65cdd52f6c5401bd3b3cf1c9863e088cd8c9a16f -85dd6d9c80a1b58c24c4d2cb7590d33d2454f381f58e820979948e5831972360cde67bbd56e1860077ef5192fcacb904 -8b0285944c676fe2519cb68da0973275fa29c0718d838d363ce46651b068d29f867cf9fe579ff8da0bb8b37d202bb23c -95147275da658d43a758b203b9ca1f1c1478853e9bf77b5218593142e2bd9c0bf46d2206ab64cef99295de6e9a268edc -b8efa187fdd3e1f46c15cd596e9567690c10e253b5beaa5be8074b6ea4e6d3d06e0f2b05323453239e419ae1e7128521 -8340464f52c92e31806fd3e8e65f56e27194d1f6daa4a0f0b3831e8102aba16f88bb5a621633ddb7dd0342e1d2d12343 -8615d87dcab85a78dc052f05a01e751176b756b5dc9985014347454ce5752f459dd6464e1c5aff36cb6c51b783fa2692 -80c6e35c0d3defbe4d3968792724a23f0b8830dd2fac58663583a49339ea20f1812cc4140e3ee867c7e716177319bbbe -a7aa63dbfc201dde8f29bb6e23d7aa5020dd35bd18a0cc93c8a10c35d695913fe25b9e8cf9b5fd1899e9657b22bc8863 -97c2a4ba80c4caba2e729a603d2faa0120915e3fe64cbb065f7ff33de5f877f1ec9461cf455e88ec9e9ded9393939dba -a54bd1419f0e2d2d87757870f37c476c7e3a13502f1ada82fd7394fd29f8a00c4986473d753034d0954a2550badbac0b -8d3e2bf900d0d2b9b46e6e2f37620f0cc90526dbbcfaad4e4a37ed53f39fdd23bd3a6f21aa7e800eaec937d9710dd6e3 -a88d2b1c7802b2dc216c2b6532406c091bfb12f29121b9a82c1154470e250188413ddd3e79f7e009ea987a4c45b332e5 -8c552c2101dfdc3f99c2da436115452e4d364eefe029b12946f05673c5ce1cfb48d39a579625849236dc6c8e7277dd30 -8415c252d52a26a6400c3189c928a98559bf24162ecf3eef1d10e439269c31d854b0b4f6ec7a2430e3f11b5d77de78d6 -8b38905bad93a8d42339dbdb5e510003c51fcaf05e04f88fd7083753353bc1c4c00a5dd4a67431cd4456d0669c7040e2 -b1d0ed8862250d0f0d9ef9dcf0cd16d84313d1a795dc0c08e0b150dadf9ce73d32d735e04632b289cafa69a6ee75dc89 -9434e18a5fb631b10edb02057f2d1fe16000ee55ada3c26a079c9fc3943e29d6de99e52829fe7b333e962270c712e51e -b1b9f3914007e6fca8ad3e7e848a1108988cb2318da36df24767d804e95d1272943fda948451135cc1b5052a3953b081 -8c02947a76d7b6c0a700a83dfb971dc105bfe996e18c521445f036310914b349ab28e57571e36ae08d13a46fb01c2f43 -893472fbc225f973a0ac6a0a0130b9cfb7ab6869dff80df71a62b1f6beb4afd069bbf35b4f327165bc31dff39e4fcaa4 -a7c176c0903175f3540d62f9afee994d5d9bf37081e094644b22f017e94c515afefde7bb07f638342abef7de657f8848 -860186c2b1d3b1e657729bc804275fb5f5ee89eaa60848fcabd3871289665ea9f0efc8a95792d884972bcfa2de96223b -865b38aea6386d0ac8f501a7d934e23d01dc50105324e354d4c4fa3cb1d4c29c26f4566df7b1a728e10cfaa9d24552e6 -b4eea5548de6969dada658df604b5d9c49002e2258352838003e0fdf7b299d81fb025807a7f37cf5b547cebd7f2c1f93 -8982de11ba68d63a649a3b296d4d56c71e3c3eec016db250d733ab7c3b9a620c09c5a5d0b64fd30d3bc03037ca4b17c9 -84d8b8a10d67eda4716673167c360fc9b95717cf36ef1d5bc6f2ef5b9d2624f0e76c2a704d016adf03e775ea8e28d83a -834d03ebd51aff4d777714783e750b84c16cb6627f8311bd8ff17c3b97fc4a5bba57d6c8f6d74f195d3030bcb5f07612 -aaf49e0def0c4d5f2c1e9c17b51e931d2f754b19e80070954980b6c160178349f6d3c8d4808801d362e77f41a0008918 -8ef4115edec841854e89f2bbd11498dac7396bca35dda554290d3db1c459ffc17be671f4a46d29fa78cbd6064cc2da20 -9641dc8a64f4acd38e343a3062787c48c312f1382f7e310ccea3e95e066ab6dc980f6ed90a633236a435e68bf6b3c625 -8a84cfc2cbeb18a11dd6c2a0aebb3f6fd58a33bb4b26101e826add03748595022e816afac79a4e7c20b3805252839dca -9770782d729017659844421e1639ffcda66a2044df9e19769b90292df87dcb146b20c6b9141bb2302029d84a5310665d -98c7ec9696454868ac52799d1c098c15ec4e08b34884dda186ebfe87d32840b81fd3282295df141c91137faf4cc02da8 -a3f6eb921247617292162dfc8eec5b830ddc294a0fb92f5b4828a541091ffdaff34c392c1d7168259d6204405d90ec72 -b185f77a468f07a54222d968a95635234e74fc942485604909308a9028ed2753b15902b9134749f381f7cd6b89cc8c3d -867608a682d53bd691dbc92eeb460d1c300b362ca49c11a280f6768ccec217f1145f9d59fe50d994f715ce89d38a74e1 -afaad630ad8827cd71aade80edf3d7aeb65a344878db12fa848759e6233f6fceca563aa437e506ea9e0f1e47b126d45b -a12afbc84e3441594aecf85d089423dd3bb8bb33a1a384ddf7cc14caa72284caaa56aa179c15e3140fd56bb532491a67 -98757b0b5e5837ddc156a4a01ce78f33bb1fce51e0c1254ee9b6d3942268d0feb50b93edbf6aa88f9ea7b3c0309830d8 -89573f4a4ae752e9f964e42bec77d28a41840c28e4bcdf86a98a131d0b85367b885077823a6f916972de6ac110821bd2 -a17f2745052de5de9c059307308fc49f56cb5230e7a41cb7e14a61c9efa742ee14c41023ce90c7f2261adc71e31045f8 -914b07c53a41c0d480083f41a61c10429ea42dafea9a0db93862d2269ff69c41db8b110b4768687b88089b5e095523cf -b380cc3e0d26370976fe891d24ea4eeb1b6be8cfce01f47fd68838a27190e644fd57b049d3aa0a9589370de20e276944 -906385fdfad60feec79eb1c303e750c659ceb22d9c16a95faaae093daadd53e7aa039a45d57e20951d6e1ca0dc899ef2 -b5211ceee31b194dba60b616bfd91536e71b9213a3aaaf5aaf9b2f4cbdeb05191861d78b97eec58e3c81abe4f0488c04 -97878e9e38c2f69d697800e7a2f132fc4babaacf471c79c26a757f771606e55fe696ece68a3163a0ffeb2f72274cf214 -959431c1f54c46500c05aaa9a2bc4230531dad97ae768fa92bb85436c0ecc6374cf20fb0ef82d122db116820a943b401 -b69e5a1c6798f30d33e42cb8d124f025d2c77c993c4c7107a539aacddf44d8d4d2239e802ece32e60ee4dbfdce201bdb -a8b09e5e9f802ad273b2efa02bcbc3d4a65ac68510510b9400a08d75b47b31c6f61ffdb3704abf535a3d6d9362fc6244 -a41ace7f1efa930564544af9aa7d42a9f50f8ba834badcaf64b0801aaed0f1616b295284e74ca00c29a1e10c3de68996 -a8f2aa0bbbc19420a7c7cec3e8d4229129b4eb08fff814d959300cd7a017ddb6548c9a6efebad567d5a6fde679a6ac6a -9683da74490a2161252d671d0bc16eb07110f7af171a1080dc4d9e4684854336a44c022efe3074eb29958ae8a1a14ace -8ef44d78d10795050c161b36afa9ab2f2f004ccf50fdeef42fe9cdc72ebb15a09389ca72a00001cd6d9b1d7b3bb766c3 -adca54f3b14fb18298098970b0267301b7312afb75894deea1b2afa3e85b7a3b4efac9971ab54c5cbecba2da9f18507e -ac5d4528f06fdccfc1370d5c3d03ed982fed0861a93a3f6453aa64e99360b124926d1892faaf72d89459e663721dfa99 -98aa1c801bd615b8cba728fa993021e181e0ad717ba01c0290e7355694155407083eb53cb70819c4775da39d33224db7 -8b3aea4c7c2bfe1020de3261ec085d79c7bf8a7903b825d2c70ebbb84af197bcc54e3653c5373a2045c3021526b63b66 -a29f3de4cb3d99afff1daf7d431b38a33a9804fedc41626618928ed059df6f6fe9f298a046b594ffee951ed4d4e1400f -803fd346be540c5242667c18ee41b26bc812456ab13ff117196ed69b90ee608c8cb6554396b64066a546ec87a71ed6a9 -a9c18d81ffd029c0339c72c499bb51685392253b996b6eabd8b76f05c6191ed8444a1397d63b9923743661a319517f7e -a048d5c390d08f07161faac71c5994baf152c883b205f3bb10d3501709d6516ae54d491b486303a11b751857a31f0052 -9156fb4803e40e28d8d57d928481a8de4373687288da44fe88c5676a8ae013ed1fcc09d56a31140bf74e7f767253810e -98e289c725b18e0085afdfaf2acbc674dae7b0a2ecc2537a7d0b87e20eb785404ab05973a787f0495d2adb3e5565c09b -8a7237b249325bd67cdc1f9fb278710069033c304afbf270b7ea24dbc10c8eabe559a484d3edc733c77b4384932deb41 -9056f2e5b02e5c2e04a69fa1323bbf1859d143761268d18e74632e43800a2a9c76fd681e924a19bc141de0e128d3e462 -b9f2bf9e4e7263014296a82b9ecbb05d3f1efa4b2e675e3b38d3eace59da06a89c859256e1b77847886d6aa15f98f649 -83b22949cca19030289bbf7cd2a0d8b84e1d468e78bc85271a6753241b89122627632723bc293cf904a5eb2b5dc6c3ae -a919aaf35dd0116168d2ee845122026416bec9633df113fbd913d8db5996221e234f98470d029a8ff182825b59fda20a -91726901f49d32b41afa15219073842278f60dcee223640903d871e318a1c2b541136b7b38a7b2ab7d31e4242fc29674 -942b77666545bc9a858d36cfe857ab1a787c9528f4a0b87918a06bf510793264dcafd12ae6bd3ee300179dab7f40aed0 -80adc1f2f9c47a96d416e44fcba41628abc0fae1f88f6a26aea4648419ab726f7fcc2187c7d5145e3d8f5a75c03937f4 -8041e0f66ba9dcee01e336dd4d16ae5e4e1618512fc147cc8230003aa2940848162dc2187d4130bf550dc1f3559849d4 -999e8adc51bab54386af1c5e8822986ad1b7ecaf1f8a4c2baa5bb2fe9d10710e49545c5a8bd89ed0e61a3d73a908e5ef -89272ffd39b6e9f99fafdd58bd9dc00f66f26a1d36b38a1ac6215e3546d966739eecda7fc236335479207cef95cce484 -b8e0b7532af13f15dc04a0eb4ea8abd67e58f1b1c6ad2e70c0ffa04a5c18ec2018b5d7f4be2f9f86db5e0b3986f639d9 -b96bd11b0f6ead4abd5fe1e4c6e995da7583b901afd01cc05e87d04663fb997997d6d39dd9fb067c62cb1b1cbb67516f -94ab08914088b973e8dbd5685decb95f3bf9e7e4700d50a05dbf5aaac9aea4be2c10c83096c02252e9238ceea1351d05 -a188de419b062af21275d976494c131ba18d2b2ead8bdbfa38a777832448e64d4d9725c6a1d530ffb6513f18d5b68d9d -8f73c8c118fa25c76a4ec5611351953c491452743056a819c8c82ba4737a37d88da0b55f837e7239a5f46d2c05a1bbba -894a44769e0be1c26648b0d89c4c9f46dbdeb3a71b90c493093bee372bb9f2d3f319850fd886d51f4f58db0de5641742 -87d239923b0db024a8d9b0281111d47b0761d81c50652268b074efa3ea70d793e30f874a91ce33a4acecd0cf38c01951 -b1b48b75a97f9fc2dc9530dc69f6268829dd0ddd574516e7eb1b9f5c3a90058889a7bcf3d378738e6d4b02f5fbfa44db -83e3ee9526ffcb60c6e75b75550fc017912ec0daf96d0a0d5f58c1b229cce90c684ac7c3e17fb998def8e7e2e155d750 -b9b7bba579e474b0abdc7775ff5f84c9f117c6ca17788cf5a5f01b2c35a14aa39036031c8d799fec2cfb371d9f7471fd -90d7faf4891fbc368a32f575dfb69f13e37161ab4f63a7139be103285a49490c2851a907f8d36e09e7d1a190dddbc6cd -968c8b9affe18fc34a4e21f0d8c5518341c566099e6b45b8721c9912bab3693c9cc343406fe90279692a1eef2a3f7311 -8735baaf4704207550f77df73fb701d9a63329993a8cb355ccc0d80daf950145f37e9b4b22be2aba29898e974f9fd552 -90f52b2dccf525b9191d836b205ffe966d9a94f6c5800f8f51f51f6c822619e5abdf1257ee523597858032d2e21014ec -831209f8f5257bb3eb452d3ee643d5f063299f8e4bfea91b47fc27453ac49fd0ba3cf9d493c24f2ca10d3c06d7c51cd6 -a5a4db4571f69b0f60fb3e63af37c3c2f99b2add4fc0e5baf1a22de24f456e6146c8dc66a2ecaafeb71dce970083cd68 -b63da69108fad437e48bd5c4fc6f7a06c4274afc904b77e3993db4575d3275fce6cffa1246de1346c10a617074b57c07 -a449448d4156b6b701b1fa6e0fe334d7d5dd758432a0f91d785b4d45fb8a78e29d42631bc22aaa4ea26f8669e531fed7 -aabe43de1350b6831ef03b0eef52c49ffb0ccd6189cce6f87f97c57a510ac0440806700ce2902e2e0b7a57b851405845 -91015f144fe12d5d0b0808c61fa03efe0249058e1829bb18770242f5fb3811e4c8b57ff9cb43deccfc70552e4993892f -8e9c570811ce44133ce3e0a208053acb2493ef18aade57c319276ad532578a60d939ed0bde92f98b0e6a8d8aabd60111 -8b21839b5dc1c9a38515c1076b45cedec245d1c185c0faac1d3d317f71f1bfebba57c2559bcdb413d9d7f0a2b07f3563 -90413bbd162be1b711e9355d83769e6aac52fdfa74802d628ff009325aa174c68f5329ddd552ef93e8fdcb9b03b34af3 -8b6b02e3f9dd1031ebd3df9a30432a3c86e64306062ef00a6d1243620d0cb66dc76f8d0d412eceff877ff8768c2696ce -9894b41d9fc715f8f6addace65451f41dc5ce7b983dd8cb33757b4d7259bef12f144e0077d0b662aa847d5a45f33c563 -a353a9740f6188d73aa4175a6c5f97898a05ed7aae9d2a365f15b91dfa7c28b921fdef0a32d90b6fb82718b33d3ddb8d -984eab8faed87c403c9979f2d2340fb090cc26d00cb4092aeb187c3f4ee1df3f57cb8363f7764073188790b16dfc464b -a5c5ae0ba435fb7f3ddd5ad962358da326239ff236fc3b51bd22e88296236b109951cee1b98f444302badc58d1b5bfbe -880be1006b0156f2788813432f450f613d235f41aba52a6000d2ad310408ad73d86b79f6081aef1e8c51010d404ba670 -937da751aae68f865c7a33fa38d718f20e2a1c65cb18c8e08f8441f0cdc77662789d2793794dd0a427cad30cd0b33f42 -9496fde66c834ff86f205897db12bbf9a9bb78d9ba8b5fb539cd0a2c927cc6b4120c017b0a652750b45edbe5f650e5dd -97a6f409ffeb593e149307a14bc47befb632412d70565c5f13d6b7d032acd2e3ed0f7b6af701b387f11d69ee4a8094d7 -97ed94934263dc0260f4f7513745ed3483cdddb9adb85dc33193c3a8b4d52affaf1ded23b59c34651afbffe80d40dc36 -b2b26378d44f916bcf999db218b9892e06de8075f205c7dafd6d37a252185c2d1b58e2e809c717963d25627e31f068e4 -b8f9fa1fb45fb19a45223f7be06c37d3a3501dd227c3e15999d1c34b605f888123026590697d0ae24d6c421df8112520 -997aa71e3b2e8c780f6855e94453c682bee1356b5ce804619ef14834475511105b1e4d01470fe4e2215dc72182d9909c -ac2cb2a7cf55aaf990cfada0218453853047e813d3f51f5a623d09f4714da79de6592671358a5edf938a67f905b6cb5b -8d8340d0c3081cd30d34f3ff6191e1ff6ad7994b4ebac19e5936f1157ca84e1813228b7605ee226366d6bab1e2bf62a2 -9693b17669086003cb46c75fed26ea83914a54901a145e18c799a777db1df9c9ca6b2ea3ee91e7b0ab848dc89cf77f19 -a6b6b2a6cd8c4922d78c8ba379373b375d66ac6ea04b830a23d5a496cf714a9439d81c865da92d52600aa4e2e43afcf1 -89cb665020abc3f5e11a03c7ba5ec9d890fa9ed2630f1443a8e45a28c32786ed980b5343ffffaea60eeff5b313bc0d66 -b37b989106594221bc6cf33a1a83c3e65ecdef279e90333a9e105b8139dc28384bb2277edd4b77c9e59d15e6afe074c5 -98ce5aee5918d18b2326b30c1ba41669cce20bc7a1d1b585363305fbdea66055164a7ac398ca0f0e670291a3061022eb -b57f472d5f34beb4cf430d7c0f8ac5bd1c0621a284633ed36e6f7804bc2b7847f54b469c7ea163a436510d9e3b32f97e -ae673a6579dbf0504c8fd0c8fc0252d2f7ae8da615a06f4d215c2f8a8f516201f24e5cc42967630c252905e5dbbd6377 -97c1501835a31091a5a83f0546e01c85ee847a0ca52fb3cc0653f6a826e13d25ddc623a5dea139108f7270a1fd7043ea -9376ee667f3834f6c0da4324fdcca5c04712e0649877ee19da79a2d23be24640c38758fce562470ce2134ca34148ffe3 -818af89c40379a10074cfaba6d5968ecf667f1a68a7edaa18e8977ccb34e0829f237c5634fbd079e7f22928b277f1096 -b8e0af0be0a252b28df25d4a509f31878bcddf702af0e5553393c3dfd4a1f1247ad8dc2668bc8dedc9b41f6ad8e71b15 -811667ffb60bc4316e44bd04573503f5b4dc44d1ec824393a699c950e5fa085b146537ddd6a08a3fede7700396a0df7d -ad834cbf850b2f61ce799c4a0f8ab0c57039d4e1113933c50b0c00175171aadee84894d1376cf325bfd434c3deb44315 -a8b7dfcdb40373ba4d55e751ccfb9070554434df9e359fc165284ee3dc35db6fb6055657ecf5a9e9b7b8e2e1abea4375 -b56a5b9fd41c9d3f65532aa58bf71a38fcf07782e1ae0084dc537862fa02e6d66658b19d6f71c39cd5dbfac418da1837 -a935af5ed224b9533b41a7e79f872f6851591da9e9d906050ccd1b2c772a1d6d010c5fc7160c4f8cd7d3aa14c3bcdc26 -a81e580fc98692567b28323fc746f70c3139d989fb6aabf3529504d42d0620f05327e3385c2bd5faea010d60dd5c8bdf -a8b352054cdcde8ddb24989329a249b71498a5593a13edad1e913c795dcad3d24789abca9c7ed1d57efcc9e3156da479 -b0de8a2bd7f93284b2bc700e442f52ada16a22ad8d86329591547411c23fff0333b2ab0c9edf82bf7903ebf69916eed1 -843e9781b653d1a427f3534b2e86add49d308ca247546f9fcf565f9e08df921e4d969e1b8ed83f3f849e98c0f63e39be -84a4098c5dca9f73e827d44025473096101affd7193c40a0307e3215e850e753e9a08e6e74a442d57626ff26df77faac -b463eaaa2f3315b511c22a97fad353014d840a6a95fe0d457d0677e63e571407d7f5268f8775381a5e7adc3b4163eb88 -ad0417edaa16cfddc288eef4173aa7057ca4f81e815541ac588ef5f24b98d56fed6845deb6ae1a9740a28bb1cd8780a7 -9271963b8fb2288a96e07eac13c0543ec41abdc6d978bd7c44ae08251ea49994412b542c77c8208cd71fd8e7852d4a70 -8b68b6db9044d8bafc155d69e0daba95cd59d6afebb085791e999afed4f33a2479c633d31d534ff767b8cd433d591a23 -a6a06a0e433e385437d9996ce823abda9848754aa9cdd25ec8701af35c9ec15df999825669bbc2e17cedb597a96e8eeb -94d414bff8b6b8597634b77a77d1060db8e1af0d0ddfb737a9bf1c66c8430e93a425510af2464bce4a7b29bc66cf325b -b6514049562af1c6fb7d0e8df6987b020f0b7a6e721f4862e36b1ba0e19af19414ede04b346be22d348b50875803d1bf -a42c7fb34f2fbee8aaccd1d86672d0acdf4e6bb083ff0456512d7e1e43be041cc0924322fcd986e6e1bce5d5ecce6f92 -867cbdd169a52440ae0a75d33a28c7d00aa92b4b65aaac5e62aa53a8fc367c08ab8828cc8fa18b6e7d1f908d158e3382 -a6fe0b768fff3e4a6153e59a7b7508eb2ee8165eaf5274d41ac2812bd4563c4ca2b132f0e27ea2f1c98759cc3589b61c -b3eb1dba43d10b9e17ffec8def053fc96f9883bacb49330a089a0ca5b9ab0182e8b5111ad4aa55c1ce1b6f4afa5c70a3 -a1531351098bdfcda566ff4d811301c0305626c77f954a38420c490e7c684f517eb1a4e4bd2c3904a10bac889cba314a -92278d106ad2f27eacdb86bdb1faa0a07a93765bb79dcff191873c52253af83480114b2299ffe5324f9c31d0abbdbbd1 -8900ba95a90c447fb6fa1f528af3d7a378aec25feb0620516b6b97e54b328fc31af42e46a8ad5e6e3029d83a6f2bbe5f -86053d481179c1ac910d5e7b9a5de82794b442f20e854583512ce1f9c3f09e71d1bf97d6700fe776debfe1527ab97a82 -a32a60de492fc4340336416bccbd2591b5e414fca0aead82281212e24490acc01747537b3da783684e27aeb987245cc8 -9820fe8e0338f21797143f368177e3669a1f3894b40ae9fa3b353125f7c8e85cc424dcf89878f2c7667f65db3b1e4165 -934d64711b4348ac5e1395cc6a3215e5643b540f591380d254165486b0ec2a1d0d21c7d2c6310f9e0eed3d08ecf4b57c -b9fd32d589432eddcb66dc30ad78981360915854cc44b2afeb826b5d48a08e377dc91be66f5bf1e783d1a8bb320f7ccb -98c972cf01efff4fc2e485b47572e2d8dde22461d127ef401b71a111b0603203971e3cde40912643affd7341cd27e57a -8db6c1620760063edabd376f4399b6e1355462e04f5c81cdcb3989fdc00f9a466bc85ed899e886c89c149adad69edbad -ad7b7fda0aa6e2aa66a27235ac5cc680aa04b85dce329fc4be84f75c9c961120a3d9e446aa44539aaac8ea203eecb4eb -8ccb01eaf41d816ce69ebd57754859e263530915e775c4e7d9dac37b2457a9099b9ae9b4c6cb09eb5ff246e3c9320c59 -b895b83b5f7ca46e02697dbaa6157df6c7571864c83e504a8c77d965bc2ba97bf9353a71c56a020df64498bd40e30b21 -8018c07a81c522fbc25f2cb14f2321c61b98bd8962ed8eb7d5823dbe5d1958a5ec2fb5622fd0868e991bcb6cae016ea1 -95b16364e94d01b3664812264d7185032722a4afc23bdd33bc16ae87ee61816c741657c37138d9312cebfb5fcfbb3b2d -94a709209990a8b09bfb4b9581ab471aae3a29526eae861108b28edb84aab6d28f1d7a25dddd8150b70af34bee4ca2e4 -ae06c80839c5a13269b984ff4d8a5938c6f4d8d647b1b1daa8cf7f6145340b76a286cd615ec251a65501e6290162da50 -875cbd0694eeb90d3567da9dc7f570d97b02bd9cf17bfa011efdd48f1d580608a3213bff4006603b8b4079fa66bded10 -b27f88c455f025e1cd902097d6a224d76bdf9c9195adee30bef4a0b0411fff980787285896e1943a62271d0aca531446 -8024880cde783cdb2b863e3dd856be92bacc5b2a1347e96e039fe34279ce528560d2df7d4d1624a4595dbafb40529697 -8883d02c2a5c0e026d941c785128d4ac6f7a9de625ea735b7d6ff27a5ba10fa4d6370d450d99a855d919f40d64f86afc -a1beb985c45fdc30ac536f1c385b40b6113ef6fabc2f76d255490fe529468847a776efa674ba8fed72180f07d3f701f1 -ab83bd9b007561695210e3276fde72e507456ba277ad4c348a2aec7a6e9ebdc2277cb4bd0bca73bd79bd2240a1fc4456 -8db27f516153812149854fd6bb1250e843a3ae1c9637df818b08bd016a769d0497ab6087fe3b2fd4080882713607bf46 -b3891dde4e00d60386aeff161b4a0fbc30bb31ee7918ce5fc0b49aac3238a000ced192c9c4c08d90de3a0ba973d7cfd6 -90a2049a15c02e59024a7a1cb0adea97501c60b1c7442fbbe560054c3d69264e69627ac57b7d9be01bef498bb2a60198 -87df67a4bd72444b5faa4f3b067204c4927c869dd3b29ad192d859589a9b2c1d6d35ed68310081e140add254a9463092 -8f80986a8dc8a0d6408ebbcb4f234e76413c11cb0d66067f9436bb232373100f20a4fded60f08dec3525315abfaa8523 -b061e10beb12ba3683688a4ae3a91600d14878ef78a308d01b93e4918efc666450e3f7b0e56283468e218934231df98c -86b9e55f3783d62e381659d3e06699d788b88aab1ff99848db328a83c97d223f602201bf2127c5ecf419752fed0a224d -858d878e29925c87243e010020007f96fa33264e89c8693af12857b362aee3fac2244057e159651c476ebe1dfbd67bcb -8fd47cdef87d7a569ffce806d2c2dad100692d6c53e5f5dfc6e274f897dccadcee30fc6c6e61373961bbc1f3ecbfa698 -892f2822daf3df3a759bef03168c1cb07408df62e024747a788e94d2da325f880bb9c6e136c7f6643f45b021c6ccb654 -8714e37ac24f5a198f219e7c88a92172fc3db129e044e914663ac708d8101851e7c53fce79d32d0e6da74f2ccd1d30ff -ae95e1dbba8b9e2c8dfbe1c202e9ccfd04fa396470035a699b902fbd86d5e6a31732a7c8cae00b9a4f6e51c8d560c7c3 -b0cd058e77498e860fa20c5f8d9bd09bb249add1badf84ba8d1bd49e704b9b4bcd67a5c3d211840a2c8fefab3fea639b -b78e468d3a7da0dd481f333ae56534e2ef97587be2e259a458e25aa37952aed1cc5f835640f812d8052f5bada8f57b12 -835de7965c6b26e7ad1b92eb6f0261d1f376fa12d61eb618d9b342b597c9c117a5a8f6a36269aeea88072b4641e6b5bf -b4d0eb99136b3643468c9c48a20fad62785a60fbdd3c054efac4bd1fa7979b4c9ca6c2c0b18069c0912bea2f19832790 -a00c47315dc0700a850966836a95f3cebfde04dd094bde0742dee77b89a05b5ad655921f86fafd1e902938ff34d4c58d -ab13fa0afaa92229a71ee91efae6d1b15f14b6eacefffb7401d41d0d6db24e24a8dbe8ee19b4680ecb69d2a0cb4e84e7 -aa56c0fb18401210062dbc653df8e3732aa8921a1280e9737e99b26a0100a13a9cba8ad0317a69bba16193362ee0f030 -8b410324a6406b345df0fa25f541ac20b7313fa55832752f70cf4c79f43b0bd3d5b4cdc447e6ba7bca08d0edffa8e29c -893362241ae412d9e5df46506407595c58ffbd7fb1fdaf0694c3432470599291238997abe118bf7737e56a4f5c9dc292 -921618194a756be81cb49d6357cb392b32cc62d96c8ffb7e16d9659a0f226a0436bd378da7b835054dbe0de2c6372ef2 -94a2904f10994928ff5367b777e1430047736fbece33442cf452018bfdeae62e84cd75cf80f8468285e347d504c94111 -b4b81545b767f380bfe10e0fea9c3cc62ca8db40b43c83ffb245259378731298e3eb6c3bdc3a16932f88f5d8a86edc4d -936203c2453ff01c6fc635e4d54320d69e60047d805daae3b75633c2259108497b778f011e5a057249f11b2b888ea76c -b90bf6378d29339443c3f2008b1e2b5f0345f86e393027f14a295e583bf6e6c2b10f54b6dcc42079ff0d356c405b03bb -916913f550d327de2d8d6c7723dcef2e3869efaf95fd963d95c8980b97748c61ad8e2e629cead8577266d93fe39203bd -a033c6f3d5ecbabeb83eb363e54e5faa7ed2d7f4fb771b161762c4f003eac4e1afb236806b784baf2222cad54e2d3cd9 -ab289d4a5771147e6c29ff9ac2bf65d70081ea6c6af2d9b728c3c144574a31b5fd8632af57c18c389aa2cd994938bb0b -9488da2019ff13e290eeac132b491df58b5b7b23c2898ff1a67bffd7e9c9464c39bc8177a57950fd28589e3d9ff9c6c4 -a5abe42b2e0891851440fb2aa6c1d8a86b571bce8b80c8e9e2692e5cb6d45a1b2f055c9fc4c74a7cd292871604129ea9 -90bfef698e83c2ba4dc9304aa01edd274169a978b7154bca518daef394f55857d0d1922ebef3d91fc5ecb3b895d9e0ec -92328f1372b6406ec80786041b6d57018b8507e3881a08727aadfecfdfcfb0824394cbb1150117ac5da5d71b89e895ae -9719751c5f7a65ae2bed8aff7b4b8c34539ff011b259b7ff54f63f9d987b3fbdce5c99534ed561aadaf07bb6e939e208 -a151816774aa9379fccec21cf212429a1c68cf91b055cbb9d931f461a8d5616c693331a11ac5c6fcfbd17d84ee0b44e4 -a72977b1285618a45943ad00f33f37102e2885eccd2f76785254eeca495068fb1d8d49865343e9e8313c6c2c3b2024da -a6f5ad2e023a1585d90625c9f7094f0e8851c79f0eede8ec582ee8e063407cc5b8298e5fdc4c786e4fbbcecaf33e787e -82901e008febcea0c0a14ae21d985a397630e18ee6e346f4a449f23be228e8f338df567d30211a11180b94fbc5204bec -b9b57fdb8d14d1be87a25f89553b3966eb7869e0519ffdf4cc4d51f4cec90d68f7b81cdc0450e04207276e9c63ace721 -a06eabcf43585a001448f3dc30411f3d5b74fd0a695c81eda9981842ba2bb0081d3f5a8360aa18b6d43ef13ea78b293d -926fe48a7e8f07559b7237beff9504476dd97b5b4d67acd01a3633358a6ba4c7abed5c87683a11209aa2ee759888e00e -a716cd3a84a963e2a5a46145b6ef4ebce705de52bf2945c374152a1e41c228a9c4eae0b6d1e222c1eea8b9c13c002177 -8a9b5985df6fb32cdb06ba1591a977545444478f2fe985ed1b10de61c630f0a4693c2185d63f0dc0256b208072c43b17 -a8eab26ae0ebcdf96a59fad1dc2d5e83b94abb2ea1774b607023f9d9e0fe065853b1e2242e794f989a80a47f550c0bd9 -84adbf38164cd04f3d770a7f4b8eae7a5d25b4a803fb63c02b95b71b33e454319c44e07a760d22bf5f58e7e372d09a16 -90f443a3ba1b9129a0bee400b5b29d42e50bb2aa56b0022bbfc3c6f8d69db40299871ec7c1b68421cc89e1af6b13a39a -81c5a94b379eb98c494a8d0067c748ba47e87a2ada0105202ed7651eb4e5111a0cd8569b06ae68d392c4fd74a37833d2 -8f92324b14a1549ee0b186073a26691088e41556d33b54258fc6e0b000e9624156db4e97861a0ec22960e6c47ca8a1dd -8b021cd0fffe055068cc460aec3cc455952e2ac32be5fa060e0d1b6cf30ed15381618f801249e893b1b9f10dd82077b0 -b3e9f0dcb3d6f0b138f589fa54dfb01f849890ab97016372d004aac55103f363a64bc0e606ddf75430f1534a30fc522d -8fdfe64af891db89b25daa859864d479cb7599486bd6f36e593f8f2f839f942261ffc3eed5001a93fde44cbcdc24c583 -a9e4554373c5073e135874e2bacbee69c65308eb0785532fec6a37834e8d0b437b77a2f11cc63c87d7183b82cd9b6bc9 -b4c47daca723ad7193ac5098cad4dcab654186ec5ea5c0fd014a3ac39726be954565a901694ba211820c011fa1c59e18 -8835427e86cdceb4c11cbea331ed724e4e78af15e3bab5be54f6b926bf66b5d99bcc40dbc456d86342c9fa83a033c2d5 -8ea84590a400cedba047c2661378921a42f5ca0421da58c1bcb37bc686a2aed98afab3fa5e6ba3a51029390ef3cdf4d4 -b48551170fc479d69fffb00fae4fba301e92e37cae08f596db6f6489c3b7020edc074f9e8d7465b84e9dcef1b6b3aecc -a6f318b1eaab00836a330710e88bfe400395b3081485f6a212e3cba9463f6fe7864ba4f71e57a411ecdf2bcb4d189f96 -848d5137a39999141a79f4bdf91150796ba36352d8525821bf3bd6e070b352792d79147341b8254dd60fa8c36e9e2618 -a8526f8904b1eac4ae2a25534aa91e8031e9aac7b8f58d8f49897e920c36c0232f4a30aa6eed305deb0f7793c115b267 -b8b6a727c44c37a8388383e959d195d1d0e51a657d4ba360633d219d43c5df645383e2406c25f1d418e72b862c3a6e9b -92e64adf65b42c978f36dd03ab22ba983bfbb61944efccdb45b337ceb486beda99818bf20d32a545503c4572bb0a4983 -9653bb83df66260a0bd059cd4244ef7c661b089e403d26ba777d2090783ff31f963f5d3a9c125b1ad1a1d19134f3fc8d -a74e72355e71ae5eb36dc75191643500ca3e67f18833ee981010e7e7e60a68e1b01b05901eff05014b9ef29aa4829f45 -8b2139a5da14524cf6acc593144db23db424b95b8c7041d8f6c7a14a6725dda1cd09c42bb3ae26a5a3650affaa742800 -a60ddff4300ca44a7c7a00a1f98441ad1438e07c30275bc46551cee1b681926d2c825cc8f90399ee5f36bb9fbd07d3dd -a04e5e9958867a5acc15fdea0d88951cfebd37c657102f6ba1dcdaa5e46cf1c823ad0d98718e88e436f260b770599102 -95e977abeb70d46fe8d7584204770f14c856a77680607304ce58077550152733758e7a8b98b11b378540542b1175fecd -8c9ec93ed35a25ce00d61609e92d567459a45e39922ccd1c64ab512e292787125bd4164c00af4cf89fd3cf9deddcd8bb -819819ad0338250d9c89aceda9e217df12ac54e940c77fb8420575caa3fa78930689d0377ba88f16d38179a807135dc6 -8baafb379d4150ac382b14a64788d819146480d7a1dccd3deef6889686ded375900f5df069843ef14d754ad3d7540401 -ab827236996bb79b447714c6993af941c5ae66248df4d9a6f3650d44b853badb5c0cb67804210e07a7b9d66ca43092f6 -927656c3eac8d2eb575e3daeb77f9605771170c325bee6aeade10c083d42bd8dcbf3bcc3d929ea437001c7cf9a95e2da -af22b212d5ee44fd4197966b9690487c38a119cd6536cfb8c181f38a94610dd9e057f95774047a446504dd96dd11e326 -a44bd94b9e01e3ba36340f2ac2201ecb477495d4f1fb6726a6b439302deabb5a35d237c6a6aeb7e3b0a65649f8656716 -af367aeeae3bba14fbdb05bcc1a521000dd9d37f5c34ae56fb306d3dfda201d0329a8b6e89d98e15825cb3c6bfdb1194 -abcc4fbdea43e50ded9e2fb01464f4e87fb136e960141e8d39214f92794cfab5634f22cd40b18d8c0e501f2307aad23e -920786cbd674348b9853689915dfcab02cce2a4596d117962bce36aadddf4bdd143891e22f2c8015517039a64e8aede3 -8cde63b9bd57cb3ef743f1f3e8250669eed739e5fbd68c500a3cc0c12f93862a69aebcdbc69dd8f476c2eb307f572a53 -b967e65a5f1cd8d5d570f5e87e7e186fba51b9504f8e466392a76d8a971fb91fd9b7565bcc1647f50d7d15e48b93bc95 -8d5a87b25fedf5edd57d870304bfd9081dc78c3e3e3b38b997260a92edac7feccdaf24feb51822d2edc223b70bb4ed5f -b6cd5d340a57f8ec73723c4f3ecd6601620dc8137a3e75a5d3c578bc79a9cae86b379950c644dee2ff99dad780d025c1 -b6f0a8e754b7f52a85a2a2e6512cfd017f7fb0418d19bb318308951c4e242d3c65bbcb9748da9cbc91a738f9ca577332 -a89dcf7d410bccec385400dd96b1cc6af89026a431d0f531aa992cbd7bc8bfd7c5f360bcb665bda1d72efa17bb982551 -97788e7522427a46c4b6258d15623ef7a565712812fa80d001e1de8dc1791392702f3fa3cce5a8cd1c5755625a0ad10a -b5338fb5e137ff625b27c5148298f27ce8f493e2527c5d0facaa49f29cae34580d0d6c3c1074a2e46cd8db3f56004ea9 -8962f006d7b1095dd0dd132ffe7e87e328510c95ad893cf3b2ab21c177c5cf2c27f47d8856f87e9762c547be009d25c0 -87fee9ce9c26aa476e67e0791a809e0a06a8a98facf3faea730d438d3e516cdf75d645fa75c906e4e44ab9237a22c016 -b75ab972e1a1214bab0b38cc3e973d44bb233acda5b4291f5e110b6fb78fdcab93dc63f01168debd898e165f615be1f7 -b5a0fb52bca279d3853761a94b206acaf313df33ae6303d9b71edae90b66fc507adbc60fb11e758888736c81d5d80c0a -849b8f0005010e684701cd3a4e59e8c89e5fec59af6d2de5b6332cde03b865ea84f07f0b80ec3404380b0e148fbd2c24 -96e2b0b6fe78408f9208f809f5c40398100b2dac202c8c5c33c2189560dea868270a598c419871a5a2b67783354f6014 -b234b81f996142d0df2c719760bf996544820a03195a6dc0ff6a72543692f5a369bf63d1f0b477ef2fe7b3234e41f685 -b85e39bcf40da1a12a535740176f4de749a93824079deb5fdaa004f3282fdefaf5275e3418c88c419bd42a3dd2ed2b3b -a27279304b89a18a4e2b443246f2368fb8b15f46a34533179b6bd2ef683f6e98e222b7a32880b39b8fac1afa90133803 -8923c22cf15c9c1964213d725b337ece9ea854775a06f75f232c4859c7142a3942f418354e33066298aedfba3cb27e62 -b109f714311fb9bc431ef57911e2cad6a3949455b9f23255cd7edea35be629e07f845fe53e2b12a32305ee2f4f264f27 -b51e82ae5c7d48050e405897d0053e9ea4b2714d002e88f78c9a307cd50b9c6b3ee7cb86f86527be9d964b01895fab20 -90db256931c7f98bcf3bffff4d496739185e7a20f329ee7bffd4e0850a37739948ec745285703967f4ca50ec370cf68b -a0485ac0445d88dafac56bfba2563b020cfc370f54c1606c89d12cfd8a4d1336d2ba50306e476155a6f5b0e0a1f2d092 -a00754c3462e74bda928da855bbf90f9077db395e32f03cce9b2955546d900b72330d247b7d607b65e130f5b0d883de0 -8547d56727c3ad8b5c8ce622ed9ad86fe8cd78e6e4848c9845914b5063b17330bd10b46d8d3f18f83ca09ecb28d1afb2 -95b937b2a979bce0e159ac75c7d5d659be8599c92305e73e942aab414793364a3ec28c7c1c8491a5750ba84a29828d8d -b011e150f0294e45a0f4c69409999d0c2e602449dbd67ab95e8258466687cd733a0329083a31b03722f4e2580ddc95e9 -924651a733ad5e5d9adadad3ea6a6babb8e455c8d5f2cb5bdc83fa422e7752592190ccedaa827b866861e73506a6968e -a4d5180122f8e31503ae027e54da50f72f5cfb910a6f7309bd882b5cd666f454672591f1f20e461e182a47d03b47052a -ab19ae659c4f73ea3d21895269dbec583c7029955a36469124ebe295027010faab56c4a475973497f28e9a77c03b8fd0 -ae7ea1a803d0f439e91494f8f35fc1167dae23834c0c699ffe65d3da8b09f8df5a53195a99ca7b8558242279e69578fa -b9d63cf0e30f9800101b43b980bcd2f229758e74b21ad5354866b4e684791c08a184330dc316228a0d67fe0210f2bc4d -8c41629744391ddb96dcbbf9cd99b13d36e57d65962e0aeb92ebccf1c4cc769626feb3ec0363def08eceb102b3dd4ad6 -b2848ff24faf9e667a8c19d050a93896e9e75b86595f7b762c7c74ccdfb9db126ae094961fee7f5d1192776c1ac1a524 -af013bc29206743ce934d5887b8d0fb3667c89bda465d2321835a3618513fba6a459dd7566268220ffce7e0c97e22b2c -8bb799e36db1132da8e8b028ea8487dd3266b4628c56dfae4ea275f3c47c78e3d7445ab8d0aaee4cbf42148b3a148175 -ae2b81fd47c038b5195a52ab8431f0d3cab4cf24c4237252d955aad2156adc16dda9d3270157e0bfe5a44022e5c051ef -8e0129213b1698d2ec6df132356805a8633ba79e672e586dfef664ffccca71834253ba14f296da962651fcba2c002622 -a1ae30b500ae77cd9bbb803d737b4a5991cc780618ac22b5cc179efd8fe10afb8c135457f2e7b86ded485ea12eae70e5 -8a39723077b7c0df6e3bf6548afa3910c214ee275951fbe5155a39473be98099626ea14d844630a6fa90292b9594665d -a628386c79b61aa7314b01d9814aeec20c2a66e3deda322a39957e7135c2e52b1da486d1b9cd61c87afb22c1d10f6462 -97867f469b01249820aadd9a54e12d4fdadd4555f2d530450e1f8f6d2dae57360578e2c2c8ba41e3b5950df596537a98 -97f192d0457c217affa5a24267dd16cb4c01de8fefde9df4884e1906d2f22e73382dcee6c7d910bf6430bb03f4a4f1e1 -86d5b5739de8442dc74d0d8dc78e49210fe11bf8c6ff0f0faecbc47b64812d6b28c8afddf6d9c0212f1988451d6ccb1c -8ff3312ce9693cd4a9f4b8e75bd805f65b0790ee43fd9e075fe4cebc87185bdf161335049819f22530f54fed2779a5b9 -8dc41d85548bee5d51941d55752a500bde3c5a8f3b362da4eec307a963968e26605048a111c9166d448b8dddf6f53892 -996bdfd004b534151e309ac925fa5ee7801c9da4f6b4c43e156d1158b134535a2a3956e1255e0dd72ac2af6bddaebcaf -aead652704b788bf4983c8f725c644c327a6e9f6683215f5c826c09f82fd2e40631791f51d14e6aded91fdc018d45501 -991ffab58a82b98ed8fc7b00c3faca153589fe09cebf6a137ad506387a1ca4dba475b0e4a1b9bdad829f1422facaec39 -9652e6c4ae084221d6bad855ec0bc11b5f855c6efba67f644e0902ab790a98861cecc6ce047c68273c3aa7eeb2f4c7d9 -b88b816507aaeea6dc92b861eabdc96988b74d7883f20a4b30ba249158acaff3c50d261742fc9ad2e9eba888a8d59065 -acd028a51e16c07a10d2073b9d03070457ac5f1246365295a1359d015c460b92b4861125fabe6f114de8197045df408d -806d3cd9d02d41c49179fe7dac5b05dcfc9a205a283135d4f008d0771c58e6f963d7ad0f6798606edda718eb5c7ff3ed -b9b71f1657a6b206fc40159a941e127f252a7b324dea864ecd804f48c0ed86da9778a925fb65491204a92bc2a26fef32 -80ed67bd0e74350c875abedc0e07fd42ce7cb926f0f3fb1949c6ac73f2300b5a14a5c6f6ff8aed99d5ea5029bb8e7ae6 -9875f67a7a473714e4dd75ee0c763ddf88101532d9680724b3848fef69e218b04a96b90f88e0f4409aa40b9a21507ecc -b4a2bb1b421e5243e5e7576a0672dc19f9f70315a03f6411c19f76616ffbb70fc5dc0e57fd4ab85e24ea2261b7ce38ab -879723002ce43e6c75ba2246f51436efe3376242beff987d025c3c4476495af32d52a54fad5d9ec329a442b93bcff1ce -a4121efbefd9c3eb143619afa52a916f199c75024908047763b29466cdfc837c2fcc894aca63044c33c41c777e529b5b -895f637b497a9766714a3d9e3c275a1f0c9ddab105bf4c8b7e663f36cd79492022415bb4938c1a4849bda73106ace77c -b119acb8b161ce4384a924645a248a656a831af526cd337d97e08405415b9dd22060849c76b88a4785eb5e7214961759 -802e712f4c0a17009c4be6c1e5ba2ca3b82adcb68793ec81f4489b7985babd8a3873d544de63d5e5de0cb4dc5048c030 -ab111051e4651b910c68ecfdc33f2d99e7bf4182df68cedbdbbcac219a543e04d93ecb2763fe32b40c095c7ca193c331 -855c73ef6afc6bcaab4c1e6388519fd5cbb682f91995bebd558167715db454f38012291beccea8186a3fb7045c685b67 -a29d02ec6d9baf84c19dfd0eb378307703bfafc0744b73335550f3cd1b647275e70215f02d1f4ab82a5df4d4e12dd938 -91510a45b8a50cac982d2db8faf8318352418c3f1c59bc6bc95eab0089d5d3a3a215533c415380e50b7928b9d388ff89 -8286e7a2751ca4e23ea7a15851ad96d2cadf5b47f39f43165dde40d38ddb33f63a07bc00600c22e41d68a66fd8a0fa51 -a413d4e619b63799dd0f42ac57e99628d338b676d52aec2bb0d1bb39155ad9344b50cdfe1fe643ff041f1bc9e2cec833 -85524e5bb43ae58784d7e0966a664717289e541c8fcaff651541718d79a718f040a70aa8daf735f6635dabfc85c00663 -97f0d48a4028ff4266faf1c6997b6ad27404daa50ca4420c00b90f0b3e2d82ef8134d0a04108a74955e61e8dfeac082c -8df6145c6cc39034c2f7331d488b8a411931c8faa25d99c5432831292637fd983d4f6b1a6f55522b4a42a462d63c6845 -98c2060f67a916991b391e67fcf23e5f305112807fe95bdddb8ce6c4084126557e4c5f003afb32e30bc6808b30d4b526 -8964246b3c2b8f7312f0a99647c38ef41daf70d2b99b112412356e680185da6810ab8ee0855ad7409d334173bcc4438f -b56c2c416a7069c14bdb3f2e208c5a6ad5aac1cbe5b1faf99dc89c7141d0259d1c6250be9d9195500c4a41182ad2ec3d -b7864583a4cae3b1083dcdcff7f123d24a69920a57d6594d0b7219e31bf0e236682442b6499a1f6795cfeb4f5f236695 -a064f94139bf1b70d476bde97099631b1284aa6b4d87f16bfc65c075e58b2f1b3c2d057605259f806e545674a1169881 -80d1bc4acf14c0f487cd57c5d6157b7f38917e93cb660f1c25e474fcdcac3c3dfda50f6bcccfd6676bae25c4b6b5014e -8ad9a4976c4e3e282843518149fcf5d454240740f4b91466f6310b7216d23d70b9b47c42870293252f29f092f330967a -914197593d2d99d784c704cad7ecd3f0b9f55dce03fc928d13e1a1034566c4de754f1c2a5ade047b0956415fe40399ec -8d77f5e29c572ec3c0ca39cbae2072ba4102403265b3d8c347a00386da9c0b8688d6e3280c96037c300d57b3545f3773 -abfdf79d935fd4f06a04938d6580a8cbf9735f0d498f49677f26e73d3b34b7075d525afcb4f14ef1632cb375bef7dd55 -a97a8c446e3edc86efac7bda5e2e5d0158c909552a3bf86151df20ece63b8d18b608f477286fb1c7f05605ab7e6a7c2c -8618d946c7fd62486551c35486fa466bdfcdc63c941e4cff5a01fbbe566b7ea9dc763cbe73e2acae063060b619a212a9 -8d03ee468070936004b06acf64b868963f721f37faa09887f8a82c155ad5c5732572a6855b531db58af03b1afe034a18 -8d3247f75966ea63935ef6049f7c889c1651374adb446f49499fc9191dbcde7ea33cbc1f1e2d3d1756b6e69870404643 -afc853c3a3facb4ba0267512b8242327cd88007cef3bf549184ee891b5ddc8c27267bae7700758ad5bc32753ebf55dae -80df863eaea289de5a2101f2288046fdbfaa64f2cf1d6419a0e0eb8c93e3880d3a3fdf4940f7524ea1514eef77fb514e -8434b5888c2b51d12d57da6fb7392fff29393c2e3bfee8e3f9d395e23ddc016f10ebe3e3182d9584fddbd93a6effcefc -b78cbb4c9e80e3808c8f006dc3148a59a9cace55bcbb20dd27597557f931e5df7eb3efd18d880fe63466636701a8925e -acb140e44098414ae513b6ef38480e4f6180c6d5f9d1ca40ae7fbadb8b046829f79c97fe2cc663cbccd5ccf3994180c6 -936cb8dc959e1fc574f6bb31f28b756499532ebb79b2c97ff58b720d1cd50dc24b1c17d3beb853ba76cb8334106ce807 -adda2116d9fab2c214ec10c0b75f7f1d75e0dd01e9c3e295a0a126af0ea2c66373d977f0aefdda2e569c0a25f4921d0e -89a5cefb80c92dcad7653b1545f11701d6312aef392986835d048f39d5bc062cabc8a9501c5439c2b922efc5f04954d0 -b9acb52747ce7f759b9cdc781f54938968c7eeacb27c1a080474e59394a55ae1d5734caf22d80289d3392aab76441e89 -8564f72ce60f15a4225f1a223d757ebd19300e341fd9c1fe5a8ece8776c69c601938fa2d5c21b0935bd2bb593293272b -a5567d7b277c4ebf80e09c7e200c20d6cb27acbaa118c66ef71cbccb33ee3ddce0e0f57b77277ae1db9c66ed6e2d8f30 -b82e9c2d8df1cdd3b2417bf316d53e9f3cb58473c4cb5383f521ef53e0af961ef916e4f6557a6d8b4655ec01415231cd -aa816dfd2814c8a25bd2cbaf66303ee49784df471bac4b3188074ea30816f00f425234454d40d8ad8035aa925d74da36 -9919f384df20faaa2d226b521cab207dd2b62420d25ebbda28c9b2ca76a2a52203b2ad7844c1a25f5c75f005c5a83149 -b24a6aa35c2d0f87e36598b36224c64427cd69642b6f9c1bd478a62c70f8ee69f85028648f6603b4f04fb21355f2afb1 -892e044bdb1276b455eac2204be105e1821f987c2570494b1f32aa09506caba7ed343cd09b1bc126fed5e0fda3d0eaad -af0e01a3ad954dc048de18bc46bb1c4971db2467e839698e4dd05cd1adcb9261013fe9fd0cafb946c0b586f6aad86d4e -ac152f0a9ace425378daf02510eb7923ff1ed2c0f8d1deb918e4efb63655de1ba58c96438e9aa23abdf2431dc771370d -ad8c7419c097709347e2394195924e09617b47ac5c7a84aeb9deab8975f22155de0f70cf20d8a976551b14e3a2683a2b -808f14f67ae801536fb70a5898ab86e50ad35340cffd0648daed2f2c4564c9ad538034b2a179a6a8bfa27e9d93b4cbe0 -80a74ab7ce4769db93cfa695a166db95f0a9c47885ff826ad5d93310f36d6b18b5351c67c858b9837b925e85a1995b63 -95b88c3cdd64401c345828f4e4754b1a88b4875a14c08a668b90acd499b3b858842669ecd73a46c5d9f1de32ec1a0120 -8ddbd770b7b18a5917eb43926fa05004e819f1d1ead05b915269e4a86b53e0633a90559007e59f6705a3769e2126ac56 -ab6db5fc220754f19948bef98844e6e38dd623565d1695e1198040c228ac4fd863c1f168cac1d036bbfb718d9d8dd036 -97bef628e977c069e60c395a17740e0e1bc1828f5607ae7f30ce5a0c95f02b53af2ad062700a75212e462aa22c3c5465 -b68d465e04fd17ca98501e61eccb0ce30401855e98046e0c1debba71c2153d6a7a704aa36a6f12454696e78e87181cdc -a79cfdd048f4181e005bd0fbac0a8424495474956b58ce858d2b700fb0f931c406282bd33bfa25c8991bc528d12a69c1 -843f55fa0a6a0969daf2b48080738f30b269b2e7ec123a799e5b203c0b3b4b956dc95d095bc6550b0013918cdff8a225 -b683cdf2823036827e5b454bfe04af9bec1850d25a7a7a44aee7696b6ff0468b7ed6885a41dde2b8f3ecc4aec880c3d2 -8b500796e82acdc89778e0c0f230f744fb05f762000fee877bcf57e8fb703d212dbc2374887bdc2e7b7a273d83a85798 -ac35a8ee87bafecb1a87f15abc7ccf4109aab4ac91d357821e417f9b1474d196c38cc41cd13667f68d1ffab5e79a6e92 -b6e517739390cfed5b395d33b14bce7cd7aaece57fe79a7eb3cbf150dc10765c3ea9fef7976a21a2243687e6eea38ef6 -b53901eeee26692273365b789f2a60afc9b5f0df229c6d21b07016cf4c0e7985beec748aeca52262f68084393ab038e1 -ac4804f33d8ba2b4854ca3537bd8bf2dda72d4e94ff7ecaaf9bd3b7f098343d74d765471ef80072ae34f860b052cbfb1 -8c6a30a93f1dde18039bbdd1ef294552bf79856e20bce863e4b8dd72d906be3ff22468ff3610e06b5a7d1745dde7ead9 -88f0607fa3b7cefe20a02115572b16fc3222be86bb19e592c86c48afbe7e0dd523492b0c29a3bceb9a20f5538bc3134c -a660b801bbddad725975ddf9a8f606f76ecef831f954be224d6178c368e1c72d346f00c4a4c95c289b62d36f2af323cf -a75b9a6aea9542b698938dcd6cc2f6fe0c43e29f64b2f54aeb05d35fac73d41aa7fd750af4fa9333644aab8db90775b9 -83e1b7129d963d1cd076c3baa5fe422148e939273db173e4d59d1858a7d841eacac7fe817d15ab8f8a493bf46c2045e6 -9060a2e9c24de11f9c70e039b5ffe9e6d32f1ae39f3dda263610df2265d917679e689898e4a8bd84ad34613dca5e3761 -b42fc8b863a2af15e04d1fe6693c09b46007c0b8298973fb4762b45b4590ad7fe0aa758918b2fe5ed1ed0359754fd955 -83e6de7860fb256ecf7b47506a5e557d0fb0aefe57fb513c7dee2bd9604712d08ca26adca7ba9a54b712372a7c585a26 -90586e9cbbf71475ecd3e7b5753b286804dcce61e165502a82b960099e79272de8b7494b8877b54ae838eb5d0f71af2f -b2e4b0d21208f73b7b75e08df80cde20c4578e117d37092a490af82354e2afd3a7dbab46fa2d12fcb731cdaece69c2ba -a010961239bb8809fc7fb4aa08fa30d33a130f9f417ee9ea60f587dcc5ef4e1b7abcdcbf8e848ecdcb7972ef6af46e78 -8f511fd58d1e3403a5eefdc0a4ba6b8af848c7efddbf9575ee84449facde05ae9a24aa41a5725416467f6fbd11369c52 -b24ebbd2d4482eb618cea1ac4fbfd9ed8c46c0988a27259300a7ce5ce1bb256aeca0357828cbbc4cf0dfafbf586040e1 -b3ea29e9cca55250e9b7b9bd854edae40f0f0cc65fe478cd468795d1288cc20d7b34ced33bd1356f1f54a4291faa877d -8a8b20f222d9e65bbde33638033972e7d44c6a310b92a9d9c5273b324c4ad1a94f2a10cbce8300c34dbd9beb618c877d -b2436a9a647dc3f12c550e4ddc5b010e6f9cb3f3504742d377384b625fc38f5b71710a49fb73ffaf95b9856047c98201 -a13f8b77c70621e421be94c7412454adc1937b9e09845c2853ef72cdbe500e5c1bf08e3c8b8d6b8eff4bce5b8dec9213 -b25de8780c80d779e6c2e3c4e839a5a107d55b9cccc3ad7c575f9fe37ef44b35db4c1b58f6114a5f2f9ca11e1eb9c5fa -96ba6ad4358c7a645e5edb07d23836cbd35c47d9a66937d09486570e68da3c8f72a578bd2e14188d3acc17e563a652d7 -a7f55989814051fda73f83b5f1a3d5385cd31dc34baf94b37c208b3eaca008ff696fd7f41e2ecffc2dd586de905bf613 -882d0c7c81e58eb9560349f35c35e4498dcde7af7be8d7974b79d262304c26ab67ffa5ed287bb193d5f0ab46b4096015 -a607158f0c1fd0377a8ee5e9715ac230abf97406c19b233d22f5911ebe716967cc10425546dc44e40c38bd6c2b4bca2e -87e8cde50e5d852d3f073a43d652f7186bac7354612517cfaecd4a1b942f06fef6f14546279c0dc0262e2997b835b2a4 -a1c93acc6db9d5ee426fb4a0b846bb7a7b8d5915bec777a9fe6907246b0beafb8938941c8c79ed6082155f75dbc1e332 -b1e4f61457b86f76cd93eafd7536f72baf239ce5a62bd5a8085a34e90576b1e118e25002d2de49b01d6e9a245ee7d3a2 -a0435fe9a4bd1031ec5973a103ec9396b2ce9fd982f6d9ed780fa80ac06a6e47a0a6eb2daf52df1dc9292db622ee9fa3 -b66d8e8a1717e4bfa42083b6ef4490e090a73168b2912f2111743e089027be0a4945a229ecf5d0b5eec11b23f0e11303 -8eb764f26904eea4f4169be6e75beaa6a39e4eb524625a15a78befe3d8e3cc82692d9b135590c20ed460d6e4ba630ef7 -b7e4aea6bb09829e53fe83e53f49a7a331a6d7bf76e0073d758577e6d6fbe63dab642b23657355cad48896ad8715119c -8f94207982373a99ffa282673f192aa98d0c4461fb77c31dc4549628bd9687a249f1b3c66b1840929341e42516c5c64a -a9c673cb247b13e17fa5e616f0399b7f5c7ad043e143e44ae68855a840870ab3d2aad737ebcf74c2cc9688d17ef3a794 -b02635104dd28c02068985256975c0af783899eb996e37d021d9a35238deeea9e836760db21869be7b6c82aa687ded29 -b33bc0966389710812b5f6698afa3e9c84839a1b85492ba11e6ded26695260abf66be6fb355d12d3a8524966f0f89e0f -a79c0dd09506951c33da3cbc23843fd02d641fc24c640a205e6e8150240372847312b9381fb03c5d301fe4dbee8d0da2 -b74de6f3a2c502b5b658ebe8a9b7edd78afd036f5a2736aa06502863b6865d131b9e3542e72a86fa2e1d2db4927661ed -99e365def1452ff9fb4b9eccd36ff4154d128469ba5bd73e83ae457ab53977cf6fc04a5d05bdcde357ab539e34bd9fe0 -b4f2bfb95abb47c67870aa6ca38ac8f3ae1b1a2bed064b1be7ff90865ea12e4930fcf66429c7ecd1183fae4a01539386 -ae4bde87f36b912e92398bf72e11d5389e93b2de1b277d7ed4b6fb5a9ab9f71a959ec3bcb734c11079440fe42b86fafd -b826459e568efdeeb66688482b67ef5020787275123fd3192f979b6175e3b0ed59e17cb734a0a052bf13f0afc7bd237c -a99dd735f4a7c85cb23dcc7f4835f9ab32026886909aaa95876b98029c37dc4d621726c872d3a9e50403443c958f4029 -99083545034768010988bf8a9f34486c2cd9da27a1d10db3ab86eb69a1dd9c8ee723e7da4ef2aced63c1dbd53ccc52cb -8ac3209349f0142546c714ef7e9d1b094aab5469b8f080c0a37cb0362da5349e108760f272fbba770aa468e48d9a34c4 -af5f48ed74b21e3f2c1430192adb4b804dc873cd7e8f07130c556c30e7b78df0ef5a14b205368848fa9185e5a68dee0d -b8b741b65d68df89443523ba74203226f1e0d13bab073d183662d124e83e76cd318b2bfff09879c04d81b577ac895638 -914abe4282d11176d4f2f08c6f15e6c2d0cde1ab4de00bbe888015c205f51929d97296a0a8d3ca5641f085a29ea89505 -83ec306b2a9a6780efafe799df90b1aebdbff7d47921a136ea8a5648b9708a97231245a1082fea38e47ecafbbe000528 -95d6b58d70b388dfcee4eda0c9805362ccfb60a87603add565b175b2c14ed92999dfdb0d3724ee3e5d30535f282641e9 -97eeb4de607c8306e1d4e494f0d5db126d53fd04983ab5674ec5996b971899e734fa4011f2c889da21154ea1e76dbd2f -84ff21977fbd873ea06bec444d4ec9ff0e3902edc29dfa25f3bed269b3709e3116e99dc06cc3e77f53c53b736bf8fc29 -8ecf483874a040a4a1c293af145094fedf203a5eb37c3e165857e108cce3e1210e0bfc0f26f4ae5e2194024929ba034d -97d9b92b2ef34609d69402167f81bce225ed3a95718a3b403f702b93e96a121a8f7f072d0ff47e8b25164e204d1576bf -ab87c39cca1803b4e84b32e40ff30289e3cbbcfbe16a70f9e025643824752359be1f10c3e5398df402b6fec64d5a3537 -af84ca57e6944332884b5c84750afe0d5950015e127acec161853d55d48fd864c7da8d59cc5aba4ceceac650b813fcc0 -b1d23d98edbe7089ce0a8432e0eb3b427c350fb4bb39eb2aca3c2bef68c432078cb9b4b2c4966255e00e734fa616638b -8e2b5252e0ea96d40835ebfb5693af49946509975682d68651396d6bb1463f09e75fd0afa04ccea49893b5b9c3e77e40 -8db25e762f1d4a89a9a1cbc61c01698e775906bc88a921b2905735457a35df9ab84bae12e1b1b8dafadd50212f1acda1 -b5f7cd163a801770a4034e2b837e00191b0ac63a2b91032ae9a99ec182d748798df48a14644935fabdbac9a43a26749a -998e7232e5906843d6272d4e04f3f00ca41a57e6dcc393c68b5b5899e6d3f23001913a24383ed00955d5ec823dbd3844 -ab2110a5174ae55ebb0a788f753597bd060ee8d6beafc5f7ce25046ea036dba939d67104bba91103d7838b50e36703d1 -a211972a4f6a0303bec6c86f5c23c0d25ab4df0ba25876cbaad66ae010b5a00aa0c5daded85e4326261a17a563508a25 -a49f53496a4041a01e07f2c2cf1e84e2ee726917bb103fd267451b9b7bb1331c0afde85a79a55409bfde27328b2a4745 -934e915c67c7fc47adeabdde49f63f04644fe234672003be2aa0a2454dc8d9288f94293478936a450f2e3f249d395b5b -b6e69e9d6808ff7f60a01b7aea6781495d7a20f5b547852d3f0af727a7434209d3015a9dd04cbe3e272918e32e345508 -b348d3462092b5c6fead7e515e09611438db8d69650876dd3b56226e303252bbeb9e9f3b888fb911445b0c87132a1d0e -8d6510334a905efe5a32001e167f1ba06f9bc4af7ffbf11b7f7bf3c0076b5cca373d8c47e98c1ba8755bb22632bfe0e7 -a2d5200f20985dcd473d119ee97e1c0fafafa0f191185bfed9cac429cef8198d17665dac4f70342eea66e6e4a7370d58 -8dd7eb6b1841b3f33425a158d33a172b79b2dc8a01378e4174e67a1a4c8f4b887f02c7c3a8f354ed9eac718155bcdf37 -b16ca19388642f71afcd9f7007b490d82f83210ac1a989da9d4bf4c419de07af8c048cd301ec7e01b9d06abda7c169d5 -93cb2d847d1a88de8c1c9d5b3c83efd0b7afb3682942bd2c8ab5ef35b33dc31a097a3e181daab8630d4e840b677216dc -a8b648c769e77a7b41c0c689fe2fba9bc585067e004bcb1732cb7b1618e97b317781c36c23a00680fc780b58c301a789 -918c321100d57712866bdae84edf7e42df30a32853af257e0cb4da028842a43b49e775f3cecb85cd817269c728de7319 -a7b0f6ce42e00c519e69b2c78fd9b75a2e7103e5892d3c1afd70c9b5b9e706180a4bf73dbb2d3eed52bfd521103ec5b3 -90041994af3322b010891356afd8115340bd7fd7ba328716fbc4fe458236c8cad8c7564ae473d6091ec3a54bdab524c0 -acb1ac83809573846231f9be2dc5f3e986cc36dd9574a620b1cced45bad0b11ea957ce8c6cbf964a0af916781c574f05 -ac54677dc002698fc4d454c7beb862ad085d0514f92576f3485a44c0cb47afb9db2c085058918a3508f9b3de0137d97c -8dea56e1bfa150e442f8484b2952b116781d08cfa3072d08657cc09b0217276efc4ab6f5fd726bfd826f6976ced8da29 -a2b09e25baf01d4364b5205fa0c4dea84ef8fe03709113b034f88a0f0a502a81bf92c1d4641e2ac9f3a6f4203d3645ee -b95fe37aa351b4292691a9c2e547224c37ec2751a31ecce59810cb2ae0993da6fbe5efe0ab82f164462fa3764b6eb20f -a3498947e91a3a540e86940be664fc82f1e83ff41a0d95eb84b925e820602a41b7393c8b458bd4ebbe574a754586787a -aa2516d3620c832e5728fefdb1af0be30c871cbad4b166a7a4565af676e73bddc2f2f51acc603b3a022056daad2b330e -a9251b56467fb55f64c70729e2ec77a59d7eac79cc0b4b25ee405ac02aea46bf1cbc858bc773934a6d9bea57cb528185 -ae8c0a4ca7ba6bdca8764bac98df0581f00358db904e57867e6ffdf15542e55f7bad2dedac152ef88038b466ed901934 -b0881e27e52cc6a57c4f3f278dffc7f63a9174b68bc867c16d8a151d9cc4d0aeb703d1074d1927faa9ffb43e10912c9a -b67138465d6654ded486d18e682f11a238d6a65d90f23d6b13eb6a1b7471efbac9ada6345dfb13e5432196d2a256829a -944c69a6f1126edd38f6eef60b8a5bd17147ab511e44e8e0a442e87244d8f35236ee0b8d3dac0631f8598f16486a5f74 -995679dbe03dec775da26708cb9200dabcad983825f1ba601eb9395f9da350ca71e8af61dbff4c668fd0eebac7e4e356 -89de362f02dc14de6995d43cdea3c854a0986c605ba5eb5dacf24e3a85983229bc99a2fcf50aba3df59f0fb20daffe29 -84607f0e2d078df22d0866285614f5d78cf7697c94a7d1b5e02b770101ceecbfd53806b377b124a7320d9fed65000b97 -93e3faab60050dac76ab44a29bcd521813e76ec8e4ae22712d77bb489bb49f98f9087acfd6a77016a09a42ddedab2d73 -b7d64a7a35f21747b8e6a874be31ba770c0d13cbd41448411994e8cebb59591295a26bacbf74ee91e248a5b111aacca0 -8dcad429a2b0d66b9eb8c1c3924d7a72979727db6a535526a3518bed2a9532d12aad1c5a778824ca4cb98e3e513f85f8 -980882895faa347bd2fd1dda7b8ee7ed49e69843afe646f677b371eecc7a10e0f4e40bb55f28995a40080df471876816 -89e8e7fb51df79971e2f7bf65783614abbb0d7f3f1b4a15d3f0d160deafa7ed1c446d9a5ae1a77160d4dd94ceed8af13 -93fda8d350392e9c4d4ffe6534f7e7be53f32483d9319093e8436fbb8166a3c01085dc858373e65c7f4d014e0dc2bab7 -897521a87b7ebf7152de5260c0875e3c7df1c53e734c672569219ee6f9bd196c5ecef159b6a1d3b7cd95e91b9b8803ff -b59affa408a0f7bd7930fa3b88750fd043ce672c10a3adeba95a12f23f0dda1793f761a86f7409ce1e6fd3b3b7195381 -b4422ccc12f4fe99c530cda610053af9ffe635b633d52492fd81271d1f6f91b87171d572d5bd0e46ff63e221fb2fc4a5 -a4542cdf3346ee0867c08d630c2aefc57442f1c05c0eba52d223bfdca5e9d0bb80775cff6ce2e28aa2730231fd7b1bb1 -a7d297bb09118b914d286e5d1e87bdf13f7d174b988e38fb5427902e8e8c674072f36b19055a1070abcf357f8668f35b -9213b0ae24b7cb43ae95e25c09fead8bdbac55141694137d67eb5eab5e90a348a13d4d4d2cbc6436fc4f4f9f7334ced2 -8aed71a0d116d832a372b42a0bb92a1980f3edf8189bdbaed7cde89fc0418b3ab21a04f5c6e1d3b8edf73f1f62bd6b15 -a6c47d77d714c285c84c6b9458cbec5e3b191c0502dffd10ce049cf1ea27ddf868ef0cff13a2377289fa6c932b8e4f28 -92f45622ec02483f2c1e07075a6695416d3768c8984856f284f40734346d56cb5b3322f20c2c9f0ef8e58ddc294a309a -af6450d02b79ac9fc79f35655b58fd3619cd5d38c5317564b453f5f2d79d7a030bf767e399fe01b658a72fbd2cac2356 -a3c01fed5240eb8a61ffa8ff4a120dbcebb53b8e19845949c77fb4f9b2c3dd52c7001df6219ad2f76c785a4ee0f64a2a -af3136bfe8f774187bdf87555a1ac505322a956229a285d28bab1c88d4f4d12245af8dff35914a62e90e49f3dce6acb0 -b20e21d28444fc96737958cd951858fda324b924b4d3d08932540fd4b87150f053db6985b96903906ce83dde0578cbb2 -b7978101071268d1f485134b4dfd1e35f89b82c7d99ae91f58b6745f5e0273b7e06f3b23009033ecc3e41b2e9e85219b -9104b7d75245b784187175912cc0ad869e12f1983b98e052710fb33663224362bffd69ceed43e7d4ad7f998c0a699eb7 -a7624cd71b92699ce3fde0e747976ee04ee820032ac45dd27d769edf3b3379a4b8db358e50c9d057c63b5a9b13d76bcd -9354a76f294005de8c59db10e638ae6e8c6d6b86a699d8da93143da8478d36116211c788d8285d8e01ea6647dfcaa1aa -b85935c04cae14af9848db5339ab6420122c041075ec1549314e3c9c5a610d9b794ea3617c50ca7af6b4aec8b06bc7dd -ad6835a62311c84b30ce90e86c91c0f31c4a44bf0a1db65bf331b7cf530cca0488efaac009ab9ed14c1d487da9e88feb -80339f0245cc37a42bd14cd58d2a8d50c554364d3a8485d0520ea6d2c83db3597bf51a858b10c838bfc8b6bc35619638 -b370420ac1a011f6d8f930511b788708ccf2fe23ca7b775b65faa5f5a15c112a4667ed6496ae452baf2204e9ce0dbf09 -8ceab3dadca807a1c8de58ac5788313419c37bc89603692c7a4d96e2311b7fe9e813cc691a7e25a242828cdf98f8bbcd -ac1526ebc6bd4ac92ee1b239f915e494d0279fbd065e4cab1f1b8a1663f67daa89560f6c99bbc3e63fa845520316d2e6 -8240ab0bc36a29d43ec3059c7e6355ff39567e135f93b243145d3ada97fd1c970743819e0d58bd5171967daec144e7a1 -a99743192a6f1967511b2d3038cc73edacb7e85f84b2926d8880d932d2fa12f5215592311a7548494b68a87ec70c93eb -8ffffc31c235997e59ab33c2f79f468399eb52b776fd7968f37a73e41949111957434f2c0a27645ab34c741eb627cd1f -8949d955309415d6d2cf6ee682ccd0427565142c1bfe43b17c38de05cd7185c48549a35b67665a0380f51aef10b62a8e -9614f727a9dac8ecd22b5b81b6e14d34f516db23a1a7d81771ddaa11f516ed04d4e78b78fda5dc9c276a55372f44c4d4 -aa85d3ef157407bd8aa74032f66bc375fddaff90c612470b5ff5d93659f8c3523b2d1b6937b3cc4201c2aa339621180e -86f8fe8bf4c262dc6a04620a848e3844f5e39a2e1700c960f20ee66d4a559a90141ef4e5091d0f32acb1e915af1e0472 -b3af2eb785b00588371beb3b49536b7919a3f2175d4817de5dcbf7fcc20c512852ef0f313327fd0589b10173f77b92e0 -8388703c512eea59190351f3bd2cce83ff8bcb3c5aefc114cccf9e9b3f78200d8034c3ebe60448aaf6c912f0ff8f0cc4 -95d0dbbbf08ec1ed3975fe7dd542be0a05156a2b3db5092825d918a849411ee536ed958201f74a5513e9743674d6658d -8d1a48802f1a2db247e633ddf61d3ef7a2c062c48dda59bf858916e04f56651a7d51e367d6535964ebf3ae6d2b21b421 -971436871bfe868f25247145a55802945409b3150008535b372c949760d7949dd2fdb40d9b96ae7473bc8f6e9b83ecdb -8ca431728ac0f156763090828a7b6d860bf591e5b9dd3bb3b7f3ba0ca74191f9710ee55efd32db7d18eab5b479cee8a4 -81e28f1a506e84c2b9aba1df720cb50e0b597b2c22f98acc34e710c934cc6f97dcaf33d589e845c2c1f6d8716d05ccac -8f43b11d3f00c41d16c9bc9bc0c44227c056bd77de4f1ca9a799418c5601e744f99066bef47da2d9088ae88eb259327c -8d330aa52744c08ef98cc5599eec8b9b4dd18aa01b803f1d1ca0e29b74f1aa2886ed0224390fc377af25852851fbee03 -a06f5b203b67134c685039ec2bdbcc787353e2575ce73a415db24a517c0c31b59d1de89f12b97cbef0219fb6a1e90a20 -9269a5f49bbb8fec1a387b5d105df88a027de615d5ca6afae20fe89b11746f8d23880db78dac238c955fc8bb3de18046 -af5074b3bc0656421c314547b45b5abd3045ca1b17f5e34ba39d8c1f7928a55d4ca5ea9c2ab59a55909b25255233e04e -8e7ee5d733c8e08f3fb7d85f0628de3de6835121672c65374905dc6d19e02fa2df14c13d5e9835dacd609a4df09abd26 -a9b9aaf83d31e879dfb8e73a0708801b4dbdb5d7c8654b27d2c0f5797ebcacc8d00a82143e2060f0917c9d41f1a03de6 -904872aa1c093cb00e1c8e369a3bdae6931c5b1ed705dd3bffba243dc4f42df3e7d7cf70303d513b34d2245743d765cf -8a4d6b3b1d6afe67383c66693f70b397e510be28e3d97dbc8ec543d699b6cbb0e72eb90a7f65e83cf9f7ef50fb18b128 -a914de13916e6a0dc0e0fefecb3a443cca80d83276513b70c22c6e566a2d41acbd33a0e2836ee09abeffd3a4894e437e -b9c408f5f05934b0aefab301ba22f8254c5ebbf5405b6aa788f76e4b328c150b395f441e3566015a0deb3eca89afe9ff -8d32aa2c81b2a8b89f347c2e0b6567b2117ddbb778fda8a3f19004b7f5aa9dd814b9b3ad35f9223715d2447b2d12f159 -8230e8b9c84cada1bf14ea6aa9ecdadd978d893cf5962fee6c7167ed21239210ea491987f2c8f2e8cfea8c140704ca28 -a5d7b6285fea51c6f21d0976a7c3a97baa3d733a201bfaac0994db6c65611d91c5fc0ebc2a7724ee02b371e575573649 -a54f00a9530f6930069f5e3a8b8b1d52ee1def0aad1763e3c609ec07f25410969b43d5943a94c235ed5eb207b33a402e -a8dc6e96399b81397734c61c3a8154e55a670fa25fa5854b3c66734cbb4ec0d8f6ba650ee3c71da3773ffc9e37abf8bd -8841fbfae1af4d400d49f74495f864804f043416c09c64705251d021b3ab7881f134a00b0241e61010617d04979d747d -95acea7ff4861cc969c1d8cc8775c5eae014ad6e2e0e2d0a911dd916c34ae69f53eef779cc24ff1eac18c2b478d3ba2b -a5dce74abcfb8c68031b47364bd9baf71a91db01e45514ab6216f5eb582ef8fe9b06aaa02f17be8b93392d9b19ab9c06 -89e111169e4ae2f4016c07c574a3bdacd8d2f359561fbbdaa3474de9bc24ef8936784dfe6fe0e29a13cac85a3e622b61 -a4c511af6bdf3892939aab651828259e4ef6ebecfdd503ecc14e61001575b313a89e209cb55a77ec19a64d29ada066ef -923c62156fbf3a44926ffb5dc71f7cef602dbe941a98c61f019a27a18a50c16b6135b6099fe04a2e1dc88a6cad989fb7 -afb9191c541b61afa0ef14652e563cc5a557842ce2afea13e21507dde0ebbe6da5233af949c998c00865c79bb3d45ec8 -8a1f0ad65cb2b225931f41dc53547d756111ecbf5bc57c5ee2cc1ffd61b126d0389d311ffe26cf06eaead95af09c5ca3 -9040b20b5ac2e1a9d30abf7a4eea1ec2db8f3077cb2cfc8736b37222d8d3937f5d9f421167086dc5551e9f0bd2522d07 -b6d888b8c6bd448dccaf99c3f690d47f802e134709ce102fb6f6fc68156943c0762be6f386338163e01eed2d1dd5f734 -b94f0e27bbcda793e4a272603b3dcc739d3bf3207798df7319f8dc9d37cbd850e3724bdd30498c929debad971950223c -9769827767be9d7bacba1b687289e0794c6fe630d33c9b607da1f6a65e3f34cb8bd65327d9287c8c5f3c8b5f6d3d133e -aaac72c993aa2356c9a6a030950441de42b2d746bace29865382f0ef54835bc96958b2f00237d805ee6a69ca82117c1b -a2b1f027d80c1b0e79bfc7dd252e095b436fba23a97a1b2b16cdd39fd39a49e06a1ca9a1345c4dbb3d601ffa99f42bdc -b3fa0ad1478ca571e8aa230921f95d81aed7eca00275a51b33aadabd5cb9c530030691d1242a6ff24e2d4cfd72a47203 -a43ed4368e78daad51b9bf1a685b1e1bfe05bed7340d4a00df718133f686690c99198b60031513328fc353c6825a5f2f -965e145711ecf998b01a18843cbb8db6b91ff46f668229281d4ca52236c4d40804ebc54276e9c168d2a2bfc299bcf397 -ae18e6efc6f54c1d9230210ac859c2f19180f31d2e37a94da2983a4264dbb58ad328ab3cbc6884ce4637c8c2390f7fc1 -83a9200486d4d85f5671643b6daf3d0290b2e41520fb7ea7030e7e342d7789023da6a293a3984308b27eb55f879ad99d -b925fb6ca83479355a44abbcdf182bfac8a3c7cce6cfc7962be277ce34460eb837c561257569be3cb28023208dea80dd -9583dd991b62ae4bd5f379ccd3cec72cfae1c08137ddfbacc659a9641e7d5a82083de60005f74fc807bd2acd218d0789 -ae73bc32e9ff5926e1e06c07a3963080881b976c9875777f8e4cf96af91bf41bdbed4bd77e91253b8ec3c15b4a6d3977 -b2a3ea90aa398717ba7d8c46743e4c487b63c5abb140555d8d20e5115df2f70d3c84a2cb9a5e0536b2d93d24f271b38d -91d119d3bf1d34cd839eb69c6de998b78482ab66bc93fa97e31fb9592f36cdfcd673f52366f8c8e8877e313b92d4a2ad -a1907e20120902cf68912cc3046f8806cabbd7673e80218814cb088e080dd93b5dccba395b13e0025f5755c183276c3a -b2e2011df72504065ec4c12cbc2137b95cfcd1355509671feb7b00dbf7f8d500476a49754cb7fb9219cb5cba7c8afe01 -a48589fb7a74a3dfd782cb3503e6294a81dbb6adb412887569f9408e9079371edbd9822388e0b7ec8d3297ba270f53ef -a203909bfe196ac65ed3e6800d577b6ca5c8fe1d40f7f925a43852951e38883f2ffd250a9e16fab3ed3dc1249650247b -997ac293722a8b98f7e819f8e6c2d4c5bd1103b82d489d8b8aabeb905e95450b9b75bd61442cf68cc957212ec1c55617 -9895a3de62395c33509b153b7820bd94fd2b011f0cac135fcf916482f1eda272ecc79f83a61837e99c3a3c4ab2c5c2a2 -98c2ece4d49a64ec8e06407a0585081003bcef88af35210e22eab91169f8f0c044d611494b755e5bd915804b1d857747 -8bc6dd083b36d076ddf0e0bb1bb87cfd059283ddabb3886f02eb7e27f1f0539b2819527b56b5c13436523c4603ac1d12 -85ab8b7a696333c82dd5e179e12b2e127e67d911de609ff9a03cab95cbeedb1f364aa1f2b5e59353e4ba0d177f996151 -a9478e214afa68c395aa2c7daf8ba1627feb71ad6d8bc7339734cdcdd5a42838e032736c28e6251c808d5a4875ef0d06 -8c53f62cf06a35321c8af3871ee4459768d0745ebf48942b9f464206309f42fc7b2c50f196ae1e43b664f0e2e718a23a -8ba80662f6642d8866e832ec8082a4204ebc993fc304c4b794666856de0407620131a18dc053597bb40a3de0bf8aca22 -8c8fac6b911785d1561a985580c03fb2ebc613ae33e486a92638aa7d4493374118d9a6d9d99121e29c68c3d67ee4e3f3 -90f2c793eee07ad90157040b30558bb3b0164e8ddf856389d6742cf5bd1c712e4c6a8e5678da70a8e9e242ec7864117e -954abed8f6d58896b7f6438c9780236c1c83b02d60a29fa7361559e619e5bc9d67b3646ee39ffafe2b3019bb3357fb50 -b79874f757a33085e1e751544de8fe3afbea92e0234f9c00254c2b36115a16ee46f085f22aa66e0c9177e5106f51b03b -aa148b287cf4f60c64f774282b421aae075f0eaa93a45aab4927750f47e2ef0b811d1846bbb15eeb2f293c80a7612e83 -a588d8825e7b0168d45499dcff6faf0dfe1ba4f090fdc7c06d50344960c0121f10ad109b0b9d13b06ef22de5a04eef87 -8f61ec93d14ebfa9c31731f9ef0fb8907505fedc79378e9a3f65c27bed4d74b41e129c97672ce5f567d897befbceec8c -a008218633f1da10efd01c155f7ed739faec902da6dc48e9f19ccbc8d32bb318d71806285cf2003de2c907bbdd4f8b22 -88ad82c66f7085632d7e348d69da84200c53594553acf5432b50dd1e87f410c802dfea91be3cf804e3117ce13103f23e -8498dba17de0318af227a3f9ed86df37a5c33f9a538be9823f8dce4efc3579e8296cb3b7200cee7c5e0bfd9da23a4b69 -b3c0342231dffe4c9bc7d9265597bc8cc4a82e2980ac6d1407108db5b00349dc91d5116fab51cf2802d58f05f653861d -b3f2730455f9bf5a058598bc60f47740117ba51f6a767e1134516a4e42338b513f377027acf8825da5c4d047a62984fd -816360914fbc9d8b865157bfab07aeb7b90bb5a7c5cd64847b1c3184a52266cd3f8f8f3ef99309ba2edc4622304bacc0 -8fd21b2315b44a52d60b39ebc45970a47b9495f42b88217ae057bebcd3ea0e2476c0c3d13de7f72016ae12ae966a008d -b62014485bc217a0fe892ef1aef0e59604ad5a868face7a93f77a70ba3d7413443fbe7a44552a784d8eae1acb1d1c52b -a905822507e431b35f56724f6c8d2e93b0607ed7a4533073a99cce2b7c1c35367382447073a53036dfdb0d04978ccf2a -81672e39c2b31845142963351de3d9cd04c67c806fdfe77467867463dbbd8a9b0e2400ccc55016e57cbedb02d83a0544 -90919c970ec668de8ec48a2a73bb75cb94f0f8380c79a7909fd8084df61ecd631476ddd474b27103c6817c8f3f260db9 -8fbe37dfb04bf1d3029f8070fd988fc5e4b585e61eab6a8b66caf0ffef979d3ed6a662cd99468ce98ec802e985da5fad -950939aabb90b57a3d667f9820880eb0c4fee5c27fe211ce8ecd34663c21b5543c810b3676111d079ac98644c75ee0ae -b06201ec3c3cfdaf864a66af128effee8ec42d25f1e173c1edf9207979fa52c871757000c591d71a9b6cde40f5001a06 -a79054e8febd0450c96ac7a5fd6bf419c4b17a5926f3bc23a8616f0cfbc2849d97470174cd1baa7c739b12615334b6b7 -81c7391b2a1844ed26a84f054b5f03865b442b7a8d614cd44805b5705fe6a356ac182b66a3c8d415132e389efac5f6b2 -825af1563d0fe53925ec9ac0df65d8211b333474e59359bf1bde8861eecd03f2ac74534d34b7e61031227c2fa7a74e1e -b60dd9bf036f1825295cd2014ef1f6d520cf729b4d6cee0b42cb871b60ae539b27c83aa3f96ee3d490ec27ce7e915115 -89ca43d5b7f3622b42df7887572297a7f52d5204d85e2e1ac6e5d7aa7f8aaea5e3a07280477d910db025d17cd2e7373b -b93a2bc9b1b597f0e514fde76ce5bfb6e61eee39cbf1971ea6db38c3ecb055e7913ec8cd07fb0b0ffae3ca345883101c -8d45546bc30266b20c6c59fc4339eb633155aa58f115a8f976d13789eaae20a95b064fedead247c46665cc13ba856663 -aa8eacfe00e8a4d9815de3f7619d9c420629ada6489933ca66a571bf6c044d08b391e0d9eec7d1cbebe8def1e7523f1e -b32fefc59a0d0319ccb1946b351ed70445d78d9fbb536fa710d3162b9659f10288f12d82b32ecc026d55f16cbad55441 -99c7c45c34044c056b24e8f57123ba5e2c2c039e9f038a66899362840cffe021733e078866a8708504cdc35816cb335d -80def162c134540d5ec071b25ccc3eef4efe158be453af41a310b7916c49ec0ce06bb43dfee96b6d77339e11587de448 -b5f2fa4f68f6a26bcb70d8eab62ad73509c08ee7aa622a14b3d16973ffff508ce6f1aff9ced77b8dcfef7319245cf2de -b4d0436019e779c789464716e1741c189e8945dab7f3072720bd9aa89882fa5b085a1755c48da21541f3cd70a41b0a71 -931e798ef672e1472f4f84c727a101e70d77b3a9f0c0803a5220958d6bbeb8aeeb56c769ab472a3d6451249a13a3f56e -918c10a84de268aa8f1ba24b38fe55ff907be07b1e86b4a4adbf305c0d705c1cf5f65ce99e03e11676cedc89f1a4f331 -8e55a8413b823715ccd92daee357cedd797e69a0e78b6fcdacb7318646b9903dfe05e5501f47b3c52e74055b9eb619a4 -8b329bb63e6c985d7d072dff4680b3f8b1217ed20543277386bd30ec25240d9dc378837dcd5cf4fd9548658635f4c537 -8c2be5386052b22986b33dbc63c5afacb6d0095495564ba4aa28fc8c880a3c78242fb083248d788ed928deb1e30a82c2 -83a2b7bdfcbd25d6b059f27218e009ecb5ecc4da68ead885e00216411d8222062ca42f21c4d9cfa19c31522080af677b -9620334d2633e85646b2e2fc48dc6c3f09c64ef1706ed78a3bb6ce1f6b274a727364df71e97531dfdcb392f70f27f536 -b6c84970ec04545121ec3b79376f4e45053c97e8bf2b11922cc2490a429c38735466097ecb81cc9d9692c74d2fb8abc8 -8e55d707dcf265c5ae29a32c27ce66f200fddb724faa5bbf145ef42280ef645fa2f0cc3cfe2db8599b26c83b91e077df -b910b96b763966402bbebd68a32c15a225ec21e1357fa298478c5981a4310e556103fef0c73bd8903e11c4ed2c065647 -a8fd933a0e9fe8c459809bd93b8ce153e2af55df94b61a1490736b19c89469954da8b72dbd072d798fc06fc3d7a3d60a -811b279c113828e114fd82c2070caa7eb089a46c8cabf865f9c77354a77ebebe0c4c6400dda0e66dd017cfc44d76851d -8ed03e91c331afb3ad6e42767e1b3e8d3a35fb831805ff1b5fd3e91878e04027ff5af1165a3ac295f1578faf2c83b581 -95bf53683d64a0621bf1ca6ee17446783f6c535b7a54d6ea57723487a215759a54f886597a55dfdd560424e368ab2759 -a9bea378768fb1d7ba365a16531c51fc1975f1c73caf2a0891da28509805fa84e2a8db7c6ccfbc620e9002317abf174c -b8308250891015deaf851c4e5a4cf4704d104f94064418488d7e3076d49f36240dcf6fdcf83f45fe8a1d97fb02e3db59 -adcda6b63da21f4074f142f8e7f3a2274f624c733e3a4001054a1809711529c61356aa087f73aed877a58ccb41d38d12 -b80e7869239ae26d1da2e6683f064d1dc93cf4a2b66e9439b3ad9b25324e969bf98014760d29e6b8de7ff152ef498d0f -8e9bf968911df3bb5e3a7655e9d8143e91ee87f14464d7ba9c86e1e31b03ab31b91eda121281b79cd974d9ed2657e33e -9007277e8335a43e6bc3c2f5f98c0ba7024a679b7156aeefe964f1a962e5ac82154ac39d1ffbad85a8f2440f3c1e354b -9422b9d670e997b7c919a429499f38e863c69c6a4d2bb28d85e36ae0895c620f68b71e39eba785e3d39a45be91507757 -926094e01132938000d82dd9a571fef5ef104cd25b4015a25e3442af0329e585aaad5472f0e7a69899ba2d6f734b40aa -95552d8057f7e32c24d69e4d6c51c98403f198a20c5be8826254d19cab2f84d5758e2220cea7e38b7c8a7a23178fd564 -8abcf8dcc8488bcc9ab23c51b9e7a0d91dfc7bebe88b7ed370ee68eceba643e939c5eae66a4aa5fe85120751780e351c -a91bf8198f029e6a4cf6f0cc39b629e9aeff1c77b8739e1d5c73d8c1d3fb5c8f6f23e27b435bf10b5b4ec1cf6a7249ed -b932d87ee3a4b81341511f90fe5aa36c571e8b914f25abcc33dd40ca67a3f6444fe9362c1434744e4af18d6e045c54a3 -a8e960c2be9b1d805d387b3ebe2134d421a65f1fd4c1b4cccdce78f9926f139eea78e3afb449b3d6dd19b5d16ace48fe -a7e2f57cce509fe66707eaba9b4c042c1be93fd6034a9b51d1d30c45c4363eac79d54663d525c9873ab0eec0b1cc4ed3 -aa162a31c2078f4b080199debf24494a8dfdfb9d8fc85b198a861b12a629c73128c55a883e4c2de3dfed6e0e1b83eeab -b5a4d075433eaf4115717a84b4dc37f843d44bba0bf820c92ecdedd5afb61be60f7708c8a151a678d9d5c0ae531bffb7 -b56ab96f7a463c0079e05dc766f3a6a31cae5c5044947734ebe0a26e01367c6763cc8de6c2ee2f3b8218f05bef217474 -b60792ac506b901065a8bc0180a86e028fe34b62ceae1ad640c759538ebf3a2ad9c8c927d662deed6f489ff3ff7813c4 -8c8c2cdf075504d12d441a58542e1f8e4bdf92b3ee4775e836b2734c5ec1e3df919b931386417d04489a1dca806c87d2 -8ed78e91e5c4a68894cefc2f7fa71f02e5e12d40f1bb74332139bc7be4d92c24e07d5ece0e82150ed474aa1337af4c18 -87119c22ff8aa31150bde537d863cad661cc5159b12f084cc319224c533f0deb28526ed8568d00a1441e7d8bb4f05673 -83a60ba5a9cccf22cebadf7318b706c9f29abd25db0e2fc1c802965351b53cbf316df72ee3e9b2d3ae7f3c4494cfdff1 -b73b6a9fdd3e7463fbdaabc9a885b7c82201ad867d1bced1c2484300a01cbbb3f1e21afa95d4c7cbb6cb983416b63b90 -b1d89ad16981ff9217708090d4017662d8838f21f3a3296cffe14590b533905fa06a20e40dd497bd291fa4dfd1bfc511 -8abde560083e071a402e3c7bf31930f537f67d2a7bbc734a7480b1b760aa712ebd1cbcb65b00e11e384e980222fe14a9 -89c731d8f31afea8bdc9c32527bdca257f2a840764d40f6e49403b8e75ae51017d505ea4fff91bf28b6f3a1bc65b8bbc -80e9ac8e077e86ad050ee73dfce268a69564ff1b8419e9c236d981fe7a5f0c2bc756e8603ec604b3b9e36da8fe10a49c -b4f1eea0f304898b1323c6382732e6f40e556bfc68af9ce73f6d54e92f5f23cc4f78eb3f43d578d81e7627fb40f092b3 -a0e3a8d1348f8f153e08ac4839232d75d1d6e81b5de184ec4724f8213baf98d3fe739a96f6b39d79a053b628c3a09981 -a6915ba0b52ffe4a381bbb8ff3791d9d3b848bf89b3bacbb2a7d2e5ae21f1353cdc304b3cb6e82416f7e604035c27d7e -b2c4c9cdfdd2fc9a340ba3ade9423344b9f429e8c7e20a8abbf26400376e312f3ae35d1c456be99dfb5c02fc8a36cbfa -9657d57ca0641825a0aa5687f3f87659d893f33aee819bafa5b1ca1db554811c1c844f971e278606e3a2f096defdc67c -a4ad24d0a557704ada24d8e27a15604bca28679e260b2c69ccc8e6cae5499866724b700605a90df7dfb35130756939b9 -b18d9ea6682f73a1f99a9a4fc98c38fcda02c1a18e8c5fc080cf935a2ac877dc5223fca273dcde190b906178d0fd05bc -8ea5fefad0799c885f50ff10d94bd0af5b99b0a446cd1f367ae5ff529cc47e09f3018115f3c0ccac2fa05bb65b84945e -92450d52e6c7d13ebfcdf5674d6761bbae2fc5aabc865d35d031b588c383e0a64cf69a73dc93948632e2b98f74a5ed86 -a356f171a98df4ec5a96d556eaccc6ad34b4238aafcf0e94ece27cdbb491749fc9692e78b84dfe80bdef2914079d34b5 -b918703a4d3507d266414712ba8eb7ad17da07cc5f952b5c62ef130cc6ed1ae3bf01237fc8848c179725bdddd465b301 -ad2b0554570bfc9d97510cf59bc38e10ca54a93649c30ac9919bd0255e43bf525ab11b74f78a51ac0973cd0c5a5dcb54 -a7ecaf4b631d179d32ac1632390d95196a0035e00da6c0e6e13b5c09ae44b15ae6c21538b5a31b73bc5f650ecd979b59 -a37704eb4d728df2a367e59fcb6c26023136230e37f3b8a2f3ceeb1467f5cd30186fc0116f98b64a8146fd2c5903e8d9 -b09373ce92314678299ae10ec1f93c702911beb4115c6b5ba6efbcab9c7afb599f59793912df70a98868bce6545a33dd -b52a878a1393094fd2b93f2d1eccabf2830ab10800ba4cc24dcc7849cd0978733263aef2fcb766a7cb575a7a99383db8 -8dac097e006fda4fb9d6d7ae52adabd9448ebc8d5bd5b38ac0c4ed38ceb510763174f7adfb0b473c38e52147ccab4239 -86b19c41efb949937d74a7875549ee5e997f9fdac7f7198085afda233cf74341a38d0ca3767c76cd35f875b89a35f78c -99f0d927e5ad25cd134f1c70b72631cc6b5cb4ddb86c0642b900464e33d971213a5239dddaf71f7a42f2d6d02a12dcc6 -8355c38806c335d747d4e97f0083fb96585677da18b409a85175ec35dc3f74671817b34203eb18c2f729717ce083ede8 -abb3603adb061a036eae0afa5f23d79c3b62442e0e3bcdeef896f88995585c1105cd3065410368456a4d36b5b0485a83 -9051c5c0011784885187d04749f774b9b4f6bc594b0e4e18226de79dedc4d7aefa3529c3d2c728e180f96f3e204d578b -91888213e7d321d0bfac884edbd5cb756b280753bb5f8bc6acfc208f525757beca24bdf86fc68d3d8736ef176a960b49 -91258bd7ce6e3b7516fe2f5391a368d826da299e0e99b1f82eaa44b62b110ab696adc92debab8ba098a52f38dfb3c5d8 -96e3907340dffa9da3602d3b94bacff7e1bb8649edd3b9bbd06e1bc6781e78f91ababab12c0b9be7c66dfedc7001b66e -9513555688fcfb12ba63952ab36a67b36affdd71f7b843e8eb99ccbd45421698024608233efbdc905eaeb26b334b33af -9913ca9bcf11eeb408da02e4317c5ca0010fb2f4490b282ddb758001c08b438c3b35351a8cbe10b7fffc1293ccd22d4b -85dc2471860ebca88e5a2766161fdd77f926d2a34825d1134a30418f91a741759668e32fd1e37c415d07ab5824338e8a -8b128917e828a0b5eb6fa8ed72b52fae2dfaf74febee69a2e2f87e8df702f0c5bc0fb620c8d1d2a07f35a15ec9c0f5a8 -964c39e7840c130b01bb481ae7bfc92682b0f124c9c383f9dbf3027f2249151925f4faf36905af476a54778d69da3f48 -80671ece658cf850e522d46d25678f934ce6df043f25f8707235125765d40c2eaaf39eda6092f75039b22cb58bf2c29d -ad4bb0e79fdaa340b1347a46b0f64e801c72a89770dda0a6e4bfd35f2df5146fce9934e4baecb1c2671077c771eb8089 -80b3bd3adc6cf198fcd997f8867d2839a2eb28f57390352ec423b8a14cc1f2ab21c6e286505d6a21fb134dcd8d8f11cf -a26d46a6b8a75748895a1d599e7fd120d896340e79813167a400b2fe463452532a4cab419074663fe1d29fa716b76a33 -82b1f3a8a1df29207d7ff020809113ab06080a7f0c631f76ad33f47cdfb6a567143144df97b4ed7f676d929195b04bba -ad96633a3744648ff0a2e4491e8219c9c6ba6e655cb058c36320a8f72cd5f72c00bddf97083d07650ea9ddc005fc1ff4 -91d0783788626c91662359dc3ff36a8bcc6831e3f4114f85c99910256b1d8f88a8612f53c7c417d55581dea486f38926 -84edd9e87ff3d193ebb25f43474c33fe502a1e2100fd3f93fda6520f5e42214cc12e9f8045f99aa2423a0ee35e671854 -b55e06a4b1fc3ff9a5520e0b7c8b5ac11b28385cce78d91ce93b82f1bd7f7afdd4195d0c13a76e80d0ed5a4f12325fa7 -b0b15c7ddede2b81d9c835ecaa887650622e75d0d85f81b8bbec7ef24e9a31a9c9e3de1f382d8c76d878d1b01373f6c8 -b1adb47c20f29784116b80f3670182d01b17612d5d91bd6502b0dcecdcf072541f582aafc5e7dd9a765cad52151684f4 -8efd1018df9c9e9814a9c48f68c168551b999914a6719229f0c5bf0f20a288a2f5ba4a48ba966c5bffb0fbd346a4fcc6 -b34ea2bd3269a4ddb2fbf2514401d2712fc46c22642f3557e3b9c7acbce9b454dcf789573ede9aa14f39605fdd03f8c4 -a9e1428ce24eacfc460aec2e787c053327ba612f50d93510d58b2cb0f13291ca3d16358325ab3e86693fe686e4f526f7 -91eac7361af4c66f725c153da665a3c55aca9ae73ead84ca2662cf736fe6a348a301be1954723206dda4a2120202954b -a6f02db89739c686407825fa7e84000ceedb9bd943e8a0908fef6f0d35dbc33c336072ba65e33e15ecfcd5714d01c2f0 -a25666faa12e843a80365c0fef7d328a480c6e3cb7f224763c11d8cbabd0e7e91a5b647585ee905cc036afca14842bae -b4348576439cd2e48c01cb9cded7cc4a0ea364ab936dd679ddc7d58b48807e7fab070f2f1ea88595b11af4500849026a -a8c6c731e0d0464ef7e4fc1b049065eb4ce100c01e1a376365c636a0b23851022bf55805963bc15eb57434a837e81167 -b0952937b154e3a4c206f96cd96c76ba37624956b0e4d43470bdd97b4af878326b589e3eaee82fc192437123096799a2 -97d07ec31ecc9923192e48d37df2cf08750050fb452dcfbdb350fbc43e146bae3590c5b732b31ebfa1ce5d884ad5ad57 -a69359aebbfe4cbc4d39d178150039fbf284cbc0edc68a6bd635ee3a1c76569a4a575c907fff691b2a4d82a384c2945f -b321c2c0f6b5902ee9056cce7404d858da9a573d27348c1a6bfea29b2746f2aee7abcb6192504e5a583b0caeaba117d7 -a74e738aa6eb4eea58855ae6f422af22812fb388c83aacca5bd5fa4a88d4c01463174a229aea2830c348dd9ab9307854 -94306a3b106bc1644346bc45c05cdc8287811d5c86cad691bde0c65d6a686eb9c0ce79ad91baa4547e5d058ae8bf7310 -b64140fd77a07633e4ca8d60786452311dcdb8ce7095ba51dad8486f57c3bf4e69bced92603f71da992a48ad817ab275 -affe7f4310f1dc68e5e3cd640bedf864f51bfb46bb752063bfc18e95930021f784e509261ff9c560f53000c361b142d1 -b0d2fee222c6f963ba3385547f921a48964da031d737892604f8f2677d4905dbf615046db57eae6c6dd756709ae6932a -81700c66aad7c2e51168e028b0fe086dea75d3b17d93a4dc1f47a6a0f025df0bae1c8c997901837ad859a84197e7bb00 -aa4ac5fdd602f8b79cace18690e67bad557a93d00c0e295074185e8c6b4059a65495d9971685de2fc01d2171ac8b706a -a8becb3a64fdf35d65d2857898dcf8053b5057a73ab8c5bb5324af1a8015cff47efb85dc3eae7364cd5c850b7962bedf -b72ea09bd0b72f8cde3466f359ea69b194ede93dced534efba1b9ebc6f3bd53942fe2965e992e82edb6050cac4ed88dd -85bb8dd7eef023a251fb6f220af54687747f4c91983ff728163c4618ffac40ee6edc29a0aa6d455276bbe017f63757c2 -85a485254a11b4c4a943d9ec509c0dd1cbfc0ff5273a00cf5c9f0babec973efb15348e5d9451b548293d778e3a2b62a5 -b109f3ac809391e772b589c196b013db69a9b2b10ac3898feb70b986973731f30722b573cd0c9324158ec20416825385 -8a4eb579a840d438bed008644f373ea9ba2f28470d50cf1d70af38ba0e17326c948527b1719dd1bd9ac656ebd5aedd10 -a52e9d66ead5ee1e02ce6108e4ded790d8ec83164a0fa275ab1f89a32200726c8e988d66df131df9e62dd80203c13dce -b541cee9febf15d252475507e11d65c4b7819c26cf6d90352f5e8a8f5c63e254eddf22df0c35a7be5b244233e8e4ee5e -8153c297772adf4603c39349142f98cc15baeccaeae10c3230ee87d62255f6814d88d6ed208c368d2c02332426589748 -970dc9782f1828474e9fab7dcdec19aa106725465a5844caed948eef5c9e48199c1b6bc1a637ed7864116927e84bc65a -a975a920624967f4ecc77ea5d9869c434caa64c330024194615a8d0640c5d4d4fb139ea11a0c73a5c6ae6dd3fbf0ab5d -811f0f9e0c12acfb4b9dca359eaef3bed18083bad96188befc036ad3143b121fff4777ca6dc70a835bbc4921bd25f5ff -82341c6ebdb97c8b72910da95c7eebccd1308b6a92999886aab552f0642882d5c7cc60931577d200efd6066530c998dd -860f7162c2f5fd1c0953c6ce75bd8c52eaa48032b914410681b8cc05e00b64130d1f96ec5a52df66a04c78a9f9f42981 -8a578e674875571fe1a0459843495a5ee1d9fb6cd684b244feb9488f999a46f43363938cd0542879ea18ed14fba10a6e -8df217aba4da6781f0f5139aced472025523ed6e17e504511c04b677ca8197488e237d8bb5dff7b6b3898cd5a6393dd5 -b2c9230ad35d7b471d3aee6f771517cf3145ad26200bd6fe9c7cf28120e2945fed402e212d2330a692f97bb9ac4dcf12 -b78b89e29e8b782603b222cc8724eeb83b2d9d56bc02f59a3c899ab76429dc721358b07dcdaf422f59520b7e7ab4fb55 -82682a5617843c4ac8d4efb4c3ce715c76c1da2c3bab1ede387db503f3489c1bfdfc07d9231d96f955df84fd225bc81b -b0f53725cc610e78b8e8a4e6823a2ffe44dd15a9a5bc8151ab7a3787ddd97e1d7f2f0e6efd2876e5f96417157143e3bf -92c5a93233085e2b244519078770c7192af62f3562113abc8902f9d72591eacf52bd15ce78653ab9170d5067606287f8 -a43ef97dcd9b6ad288846bf31fccf78df72f94bc7ad768baf5bf0d5dfa27bd74ffcc6b6c6ed1d1f09e09be3afa5eaedf -817d43bd684a261fb30f709f7926cc4e1a31fd3a1a5e7e53ba4d664856827b340d7867e23d55617ab3514c8a26a7040d -a599e22d3286b32fafaaf79bd5b0c5b72f6bf266ec68948478f055391336d756b58f9afea0167b961fd94234989f0f02 -b70db7d8e8356df2e2070f8d658e560081442f3f3b95e20f4bf30106835d76161101163659d5d12cc0f335fb042dc66e -b8f725b70c957aa3cd6b4bef0d9647393f7c9e0b7343e92439372f0e9aa3ceddd0cb9c30be331742b87c53f2eb030593 -b2fb5e7762f26036e7e966f4454f886758804d1f4c2da17f3d13b0b67ca337f1fd89fd3cc798b07da6e05e8582c9537b -a377f944dccc300921e238ed67989872338137fe57f04cb5a913c787842e08b8a1adcfb4d2200abdc911fc1c766a7092 -b82e98a606071c2a33f2ad44e7ace6d9471d5434500de8307b5d4e0083e3a5cbc67f0609ca8055f0ea0ee7501b9ed916 -8e58f9a04d33a41ace4944615041662dc35057e645f63e127cf0d70f96ac307d33a62ce98f164d6eed8536c1a747dcbe -b5b11388071ffbf57ac47fc195736613b964ebb91cc8e2c17b32646f91d64ea506282b881897fca96c317364d3290de2 -a40ee9b7551133856cfb3904837f9949a9558e59a418898affb78adf1500fd6ef6328fc4422161909aea2c79ad08c14b -81f9eb4ef28aacdb43e11dfc9aa92ba990be4d3c14b484fa677edad3a3fbfeaa859a7f9322b5e95818240d7326215abf -84939b2b6bc859437d1a7a8d6ec9a357c6b716c4b4cc22abc274af872655940cfc72c99f5d0283d90e05191fcdb1c232 -b78a5b74a90a805410b6225fb9576d6d73752520f25cc3fd1edf8ea9f6559d3080f9acaa2246809b6a66879cd2ae446b -8d0a92baa88bf38dce5385ccf15d345b28e2e5d0a2d469e689353d80eaed8e8408933816d70ad752f226c59a0d5b5f0c -a7e15f8a8c1655b7b346c9488cff278c793505379b781b31b273b4bf09b3bdfca1c8ab2334746075d636b2e05859f215 -b70daf14f2adce03c7b92d6aa181f0c507a80a37493d8dd12419d5ed5f943a98099fefb46ac827d6e4efb9b8233c99d6 -8c2480814661744d116fba7355bc6b1914975e44cf0e976d50b6a20092bb1c636b7b44ed3fe8d63b5555ffc89fa759d6 -a6059528a4fed36abb74ab992b22a4f9bf1d05c5de2bfe6837b9af1adfed98bc37ed7481b5a99675d432743021fcfdb3 -b7e19f1b25bc159e5a769811e773c3a8ffe8be8ac77ed0b711540915e5c6e7bafdb407cf9b85c551f67fd621ce8142a5 -a2f66d4f7d16ed3e7ef5fc90b42676c61a98ff18bd26ccce91de03b6a0130c1db17a6bc57be135e410a76d2255b15813 -a139c916927dc3d3fb83598da9217ca64f0ae127215332e9a7ed82be923b89a801c44580d5617297175f9dafb1c4eaf3 -af08e1e1b04ec95366a12d99c80a9a9ac40ac984a575dd0230cdf4eb346a7686da55ef0a276f3356f814af31f9cbf1aa -98840aefe287369221c0721cd7c1b15b1d670c3cbbfda191cdb5434bcad757e59c30ec82b2d8c75947405888d44da435 -b7c61c8d42daf2e278a12d8f6eed76090b71c82275f8b33504aba75d95103840e8acd083e97a5a5aa79897876a68940d -a0264048d2a2061d32eee4f661957ff351e78436bf49ef973c059612874ce9c91970869d011dc13a5b7c754476880a68 -897199a4d8db8aa2db5d9be3d4f4312e41fa0739eb06c62e2e046c4b9be829a447e5d47227e2d96195d3b7b66eb59da6 -b512a9082881f5dc90b02f8bc4f38b133348c2e933813852f6a8e7d8c270c9ce68a5524af7d1d3123e53b2d02a53d465 -80b332469254a96f53c95ec79bb5a8bb1c387d40e58b73d72f84384c696ba0d3c81d6ac90be2979c364c44294e90432e -ab680c2e547ea5cbf95bf813020beb461d50ee4341dea944eb48f6a8584d35682d20186e3b190b849a1ba25625a7f499 -9070581993a0531d6be372d370c2e4ab2ee53f30e04a75ae61ea0fc2c320914506c4d2d4b4487c1f8fa88356fc45c895 -8424303dad6b4051ab633ad27ee51783b2ead61c5a6dae1eb3ed72fc1f36e2a9b1f315504a4bd90f9664091f2f403d4c -82225611eee626556553b9316dab4043aff241a81826a33aebd9864a91e299b765ba1fb43eea2c2047e6b75b6d7fe3de -8a3fb221c616ad55c352dd5e0c09ee892022013d6965aef40d4f277a42e9fa01226fe973cb99aaf6ffe4f4f348fb54d1 -b07c07679aa51713e8a7d7bc304dc15ed5664b66bd371877023f3b110b3927e09e259ef22895c4001421a69c6c013cc6 -83556c76bdac0dd8db6da231b863c335be076e7299802eebc259e0818c369f933a4a4b18e2df8ca07e82f60767b462e0 -a516f659b7915d2f7cd0f0f5ea2491b15f0c84dcb191e7671b28adf7cf14a56d42cfc0da94b3c269b45c535f6eeded49 -80d7cc6f26066f753041b17ff1bd27f6d4b5603a43729d33d596e21a67356db84ca9710158089def425f6afaf3207f9e -b802a47f9009dbd48851209ea1e2739020e717f0ae80671d9f97a0e43de923273f66b7fcc136a064c8467372a5b02d28 -ac92fec1864a8a911633f377df87aab56713876316d48240fefeee49ab97f7406c22e70f4938b5912c5c4e766146b7a5 -89224225b9835d04428b0a74edbff53dee2be285ddd1e5a3a8c37307c0500578155f0c4052e4bc8be04c56862fac099d -b1d3c8492fbf22ea60732745edd3b0163ba5a20d1a3315e3773f2540ee38cf308d42ec72cbb3e3dcea457d1d132c3904 -8bd00e38ec30ee6c44a0e5b222f1f737c9ed2a4bb9225f1741d6334df966318c8a0fd2fbb109557fe8c9479694b8d8dc -a930ce5454efc0b247dc148aff869963fc5c240241d5590415cbd36634801a04d3873d93635911bb9c0c42ecb005cc63 -b83d4f80e9e0fa47b42175df74935ba8aad2e559b80e84478ab1685bc3eb65d51b93e5738d5ca968cc055ca0c552a03c -b3ae21258f98051f13af3878b8103bc541fe6f20b1c3f8fb4689ddb8800b3c25cca9b55f0a4104bdf15dc4d5844abb8c -831ef8684c1cd446c58c59d0152aeade5cc305bca6aa296b92162615f052ba280fe289edd62fda6d9f0667c186445f52 -97bf9659b14f133885916733b7d4ac7e215495953caba970fa259f7bf6b79e661090ec8d79e1c9ce8dfb17e8552f93af -84d5a89cc2332baaaf3d19627a65f4b107f8dd9228a1434b327732f59883bb54fb8ce60d6acd026ed4b0e94e545d1c33 -8e66cb743f95ca5486400b0d89d02e20b98044be1e3a12983ff9fe086179e5a0ebf4dcd5098703191552e9aa660a6de5 -87b4cfb35bacec805f8148786788db84eb8f4bcecdd0570ecb592c705450ce1a90b6d183d37ef58780ede3995be67497 -a72a4fece5478011973afa543f6d8a8ea06a64b241cf7d8bd81fa3740ac2a4cf10e5120abcc1c1101f94da89507a40ca -89dc6001a96adcd2679916f43dd19ea00508c8d5dd6b0090eab7982fd2f3571b62f3029588a0649e73f49124525407ea -8ca75edf1259599e873530eff6151c822a4018e71a340534219ef8641cb6683215891df41d4e3c0ca2560e57a7aa913e -9282d32f868e5ee6f7fc229dda5b94b603476de30cec0a44a30edf396b52dc0ebd472b8f726d4b67d76179fecc1666a1 -afa24704223707db89690bcf9761f07a093f6009ca9fc945e0a8801fc29f9f51292bf95243e466fe736088af36c55ca6 -b51332508ddd9a2610edd2b0ad120272ca342e96c28baae37a2c4f07e689303a46c237712d07e446b1d67c75aa8ce32f -9219249f3799dfa4eb4770ee323f821e559e7406bb11b1f1889286221b22c8b40ccacbd9ac50ea3fa9ed754860bc24f0 -993515270c128ede64fe6f06755259105d0ec74947b7eb05924a375fa5c6d14822f3d7d41dd04fa5df8aa2aa205a1dec -a83be4c2511bae430034ab15b194ac719d7b7041f9c0e321317f513a97db39e97b9ee1df92a1962f265b7a3e98cdd753 -8ac7feaecd26f7b99fda3ed0b8a08bd6dd33ed5ba687c913ec0ffc64bbbefcda6f265072add4d944f2005634601ce68b -b4e3ac6b09299db9e1a469f3a0b2d8d724ee47a417a517bebc4c2ac3efc5cde086b57b9aa4efccdef2bcf8f456d973f6 -9262a24a84fb7b2a84d700f98dcf3fefab8b47293778c20bfc356860cb84e0bf102bae9facd9986d92d1762e0a955836 -97be2041c42bd25e5eb519279163b0857f8bef627492c27b1182f8bf0033769246be5886422cbd2409c08a2615352465 -b0b87d059a00e3effa2e5e4925da913b245785f2932ac3ed364ad19a064d3561b8aa6afea22c951316074f0df179af36 -891644b7b3321b06a2a40cd96c2b8b29d81cde5b48546483fdda439000982a9cbf1f6333fb6c089d39da6492cdfaefe9 -8da9149b7f4783a24240b7b9c7e6df4abf8d699d3834e31ee591489bf4744141ab199c173db64397c1f9bd5f9c862ca1 -8ad7f9fb2742654aa2964fd468e7645436cefd1308b064fd63fdf0d3adb4caf6cfe5426354f6cc284f208b03d6b2d918 -8435e4668f7aeb027100d21e4e0b6ee22b401d21966a3736b95610de86c7e2f2c9ee5d0f901353675eee5ff458dad69e -9010895f045538bd11b47bb8996f27198c8d6cffd3220569e6b7407f68f35c47d1efdbcecbf9b5e241c3c2879a4f6936 -92a9aa443b5ee7bf13b6f43f2d8d8db7f6f33fd4073a606ec5772421a55f464831419726130dd97829a7d4bfeb1ab078 -843f3266560be6dcbe0258c3c7d7e332330e10630c069892954290288eda301e247f479505a8a1bf7e59c99ccafd104f -915bd1dad808f8a568725bd243f80b5476a2999d0ef60ea3ef6e754155bc4121b2b879d01570725b510c5a3f09cd83ef -97250d781815b1825be192714884630e9f564b9bd737d55b8ac79ab48d0fb3ca53bd21ead7b2fa82a05f24083f25645d -81e2d52333391ff2faab39611689a62d6ead77039e8703f4e012d53eea17a4d46f2e3342e44b6edbe73a542b461bda45 -89c9f9fd5f638156b018831c1bb70c91215f4a2f5a73c84b1208bdf6ad652a55df7213336ce12bd910a0e1a726474f95 -92bd02984d090ea7e2f3eb7d36d1e7b9d731b6b047e3cdd4af7cc4ee177415fea7a145205e484b366d84191f06af85c9 -85a86fc61d5d916ccbb219db52953e1495230aaaca63237e9165276405f07ad9644e253ae394f1ccdd231944e7143313 -a2ca5b3fbc9f3530f88c0ed7071ec3d89b272174c366eedb5d15d2b648c65d23c0faa4e92c776357e7c6883a0084d03c -ad171f5badcc99c8ffc9d8b707d792046f86cd0aa478e0e2fbb32fe095f96cd134ca548d1f7713057694dc6b26465315 -96bd15d57da9980870fbadc98c68db76824407dff2700c45b859bb70d98374d4a4ba99e3ed0b0c17f480fe08f16c6b8a -8300bac69ca088c3ff35749b437215e9e35a16393e9dc094f520516ba57a485def7029d30adfc72bca36eeb285c19301 -8a09e20be64f346668fcc7b07fee9c0ea8094c935cbf4f3a4cdbb613d4b936c1edb9256b7c884efb72393d97c0da00e1 -b1f85827ee6f041f93ab174d847a55710824fa131c9ade9561168c3962a25c617475ebc4105eba6e738961a754442bc8 -a131558f92e215969f41b6a57d1e2f424149eea531723821dd4cf8c54325cbe66b002de2c8287de6b41ab4b5c35f060a -81ba492b8956f73557f361a856c6c884ebb300d828287d5699e22e0cfa75c8e77a61616551d0be5178263898c461d6f7 -b2608f44d3c22fac8e13cb59e4ade8b9a98c4eb1ec0959ea400c97eb937ae3f66837e91917057148befade8389af2f6a -a6ff0323b5a18a4becb2cc6b376086b47cb2baffbfd1b0f2229ef2286fb4a34c5cd83a5faed5def7bbad519fcab8a856 -857d879cb9eff22501d883071382832730704bfcc5cd5b07cdce7ab8dc41c565a1eb0e7e4befce8e0e03a4975d3f11ef -a2879a20c0360c516811c490289be7dfbf7dbd41d2f172c9239f99e3d091957e0446854f9d0f753d90384a80feb6fa56 -83518624f33f19f87096a47d7b8e5f2d019b927e935a9021823fac6564c4f2328dcb172e25bb052748191e75ac682bd0 -817ec79132faa4e2950665712b2c503d7fb542aa57b7b36e324f77cda79f8b77bde12314e2df65c5b5296a6bca9bb0b4 -b2abf8fb7c3690816fa133d5b4aa509cd5a6e3257cfeb7513d1408b12371c4d58c44d123ac07360be0d0dd378e5bcf99 -a9fe1e4fb1574c1affac5560939face1af6657f5d6abce08d32fc9d98ef03186dbb2dbb9fd1decd6d8f4e4687afecce9 -89b2f41e51f33c3ca3e44b692e8a6681eb42a7f90b81c9e0a0bc538341df9e2039ee61f26d2ebe9e68df5ed1bccf8cdf -8b35aa7b1d9e2135b35a1d801f6c9f47c08a80e48603f3850b425f64e7fb9860d1adda04f92a1ba22d00dd0a26e781ca -960574978cadedbd4cd9f764bee92f94e08b7af65403de36b21bffc9424bcee845b3b028af2e9e545dd77cf1e69a6a7d -840aa0f34b5b6c39471f54d9e85f1eb946468c4fc01963a9027cd7864df01f73c2e864f1f07aeed4b1b1af72808dfa07 -834464a84a11200e3c60f816044c254a7d9baed64aed45a17325cef7fd62338e0a26da78d199d30ac3411714dc813223 -b4ac6fe2f5059546f4ad9a361426ead33237b6b9030b129bf0122085c85fe4ccb33cf90f5a7f23c5b708a5ac64b487f6 -a12aa9035464795f2a67f3eaba478d5ebc838ed9e997c7dfa241e1ed60a94b367d3f969ccf0ef02028c35215698b309f -ac8d926492ec2bb68c6d8aa9bce49085d3d266f3d5f1f924032b87c42b44e41da7c047eeb01e4618f9d0f123dcaa537d -a5142425825d813ed8ce1849d81aa40b11f1cc3daa89a9f798dd83065c74820b4da6122b3308f528b074531df66e1a5e -87ff55c9f5aae079e7bf24084dd9c6b3bc260727d942d79cbe8dc13341d98525b4ece3ed8169994b56a387642f09134a -88e680f148ef2ecdcfed33b61f9e0224790fddc9069bd6999e9bede1791e761637c0fd60b52990b6c93e6e5429e483ce -94bc20bf5aac6e9f1060d02eacd06c42aeac9a1c5635b15a83985dfb03938ddb4999a822e865635201489c7f75601b29 -849221cab7599f25f0b114df092bd5e8c2430503ae959bef1543a101de0790a78245db6a145e26f40b5f9bcf533219a3 -88b6f2c2e7a7954fad11009d839ce50780921f80292320868d481e38d26aecd80fa607e82219a99532d88cf33b39f562 -b0d82947dc23c0b88b86c321b582c15decdb825ed909a731b42d46bc895009515a3dc646c98dbec7d71b0722df82392e -a2cfb9f7c1a76c8073363c1c3bebe5dc29fa76533caea41046c51ea9bbdc693a121b957cd96be5b6da18704d1865cff7 -8f0ffab9a83355a22683a9d998d1c1089449eb308711eaad4265f05927ec6d0d1ca39217082a0b372e02234e78dbaaad -ab024661e2b2937ad374c8cf2e3669f1dc55558a3a881e9ec4d461f27e0fa92e2bc88230f038bfb051cf2145ca747a07 -b98d9b9ec9eefa56d38cca959ce1aee7b6d4b41a8dbbd34b3f50c0a5f97f84ed2502ded1ce8cdb5895872360d4ba6d61 -851244158b3184a62d2c98d148e2b1102cf0d5500906bbc2deda95acc5e3bc4b4a3344febbb31ce05a56dfee86a74913 -860d9e2cb886bd3620b5d7499d14b415532482569bd45fd76e3e8052d78a73ae4b2b41f139f9cfb136564108cd93c0f3 -8305a052a0fb2bcd41f3aca075c5f7f233bd8f861451d03f3a6e6e31f7d08dd89fe1eb4dd7b238a78b12ddceaad9768c -adb703e4778c7e14fb83541ab00b5fc344108243ec6827c5d9b302ee68321aa569da1718424e6a57979ab7536d5eb43b -b1a754b87b9e21aeb86217ec5b4fadb7535344567f1bd15e88ec12a833fed68e26bfbe03b7709ce24ba6c925ea0a0e07 -8c1e2f6bf820e1653f3b8213e9d959d8649196223c2aab57b7ebda094f4919f88d883bcc6a0cd0be335f26f5a2a9c962 -a082deb9865fe8668e91db0e4fd7fb50fb3fdae3e7bf1217ce0aa6f286a624624cf936d762bb2b6c3fead6826694f846 -a10540ca05fbcccdd0a2a66aabab3b36e9bb525794cbae68bc3dace6116f58942218e9d5e9af10d67b5f6fb6c774fdd4 -b81d22c4ab0ccaf447cc5fc2ff3bd21746617e6773bf43257c0d80331be2e8437b88c9c45309ee46402b38d3d4911caf -84c7c6e924713cab3b149f641dabf63ad5abbc17c1d8ee7802a6630507aa1137f7e034ba1d12ec13f1e31efbab79bf13 -8773b9d236e5fcfa8c32e471b555264692006bf9a869a3c327aed33da22dfbf5780ecea7158904d4d6ac4acfe9789388 -a4c2c1bb7290eb7af2013f7dde78282148593f066b09faf42e61a3fcf81297caa5a00fdbf6b93609c8c5782a0f25341a -a7bfa6e3f273da3dcfac7cb9906bbe9fa4fc2872b184d79813ee273e6cc4d7f37f46164362707a1976f5b6a2c5d7ed1a -8b71502019e4263fcda354a0fd10aaa7da47f4abb7a0c715c7b017e9eea14f2b64009b29b467394668c7ca995adedf82 -ad7460fba7deccc3f9a7d204233de47ce30ffa55e1e164975cdf06480a6108720bc397b93ca8c959df77d44a1e1f05f4 -a5b8df96ccb7b078a3918e74b1b10da21df982538d2c9313f5129b2797c8a6db9ff8707241ff72d3e9d5983397321736 -aa6cfa6386660c01879656da6c4e72497690708bae6c5cd1d088f443cb5bbbe75561d6eec256a72b9728377eb83ef973 -b9699ce7c5c878e44114ab7a598646c6c7616b8e08a9ef8ec291189ef9945c1a538d2abf1ce3b0da0f8eecb303b81b43 -b8d0fd1d278f53c455de92ec4357885fc6648dc5f276930263da7dc885b4a9628a2113e28b66b1e64fd08189427c614f -84ad8d262f6ef5d93e82ff6f4af995148eedf6d8e079124daee9b99f506e2968922eac2c7d4aea741fceb7733f20b2d2 -ab5e30ab54641e3a44450118b8235554e0fcfffdfbe1430ceb3f7ef33325725741995fbbbb0c16f0875aef0f1e0c98ec -80e2cf8bf386ebda46045852751611f2af80eca2e910d9ec5f6e2c7376611534604ceafa639272b3d503b02bd66525a6 -aaac69af8fbb87da1c1b7c1b9e59942887ae839a91f0c1d191c40fe8163d7f1dbe984e4fd33619c73e63abfa7058f1e3 -a6194224ad838ab86e84dc80e9b8abb121ae6c3c7fddc476463d81f14168131e429a9757e18219b3896a667edda2c751 -b68f36aa57aedc7d65752b74761e49127afa65466005a42556230dd608ecc8f5efdb2ce90bb445a8466e1fc780eea8c3 -886c3fa235d6977822846b3d6eccb77f1e2cd8ba3dc04780666cf070cae208b7513dc4525d19a3fb6385cb55f5048e2a -a9801273ef850b99eb28f3dee84ba4c4017c95398730c447efe8c1146b0719f252709d3397ce60509e05da74ed0f373f -a58c2a5dd13e08ffa26a6c5e5eb18bd8f761ab64a711e928e6101512401ef2b1c41f67ba6d0823e16e89395d6b03ebb7 -91318b564ec8b2d8c347ca827d4d3a060272aec585e1acd693b2bafa750565c72fec6a52c73bb3ae964fdaa479700532 -a058db5d76f329c7e6873e80c7b6a088974522390ccaf171896066f0476742fd87a12fe9606c20d80920786a88d42cec -9838e07f9ed8b3fbca701be0ef32a3f90752bbe325aca4eaea5150d99eb2243332745c9e544fd1bb17e7e917202edab9 -85a9ae7dd354f36e73baa5ecf8465d03f0c53b24caf510036b3e796e4764a2bc17f0373013af5b9f1b8973226eb58cd1 -896a4ff4508d069a7da6ef7bed66e1080991daee8b227f3c959b4f47feaf75fd1b9e03d0917b247c2db11e105395d685 -a36d9a6a037bf498dfc0e535f2034e6cd433c7b52e520469811eb2e9f04499a6ce40257d2905300df7d81f38d1bba075 -97aac3c5492aca879b4c06db1834b30b8850a244d29296046a84c637d9580c8521ab4752ef814c96f255a139660d7639 -8552bf592a84ab4b356d01643c90347377ebf1f2b38a8c2e55a3f34537b8c7dcbd62e6776d6c2114f2bc2d4344d1567c -84474ad163db8e590943ccd1dc50b4f444beb8275919b33f53d42cba89831e9d42ce2de52b26f4412e2a0676ce913277 -900799dfaf5eafeb297c7b4f892438bf2a65ce04034d66f8e5cc3836e4eaffe782fba4f4455a0fcab49102a240d1780e -817176415e35ad4a204b9fd5771bae6cc270f6ff050996cec89efbe461b2940ae5dd3c6c7d7e31b1da5285b207efed27 -965e5791c927d47569bc54ec9b4c5305788aecd87a26e402aabeaeccc03480df46f0586ca2e2a9918885cd03332af166 -b96d9ada4b5a04a94807d71726bd557de94fbd44042d7dba40560eebe8658d1da49eba54499360619f3b2c38e8b5ed6a -a07b6d641a43e02e7868f30db4dd5069a2f221b4f122ce9b11eac04abadc4f25f3207f1d2d86c7935b1a3d9992ea9814 -8250d4d8ccac846a4b1a9fa392d9279b5bf2283c8b95d8164c3c0d199fec8849eab85755f2a2a99d584a0407742e3200 -8324cf49f56fc14162f9a9ebda1ebda0388d09d8688f1938aef7dbf9505fc119069efc552f68cc7cd9213f96fda2c6de -a98e6f1e85268dccbe3bf4e92c9f455c58dcb53de1dba3b78589adf2e50e79f8e245f956e0d098eb46f5d3746826c6dd -b103ec12f266b4153d67b54d8fc079357ee342cbe5008adc3e0689a7f788534c4601e60e939731f49e4a1e24fd589f82 -b2d7681e866420413cc98eae67614d383943e3762d5742cb3c57e26157633c20880eea1209feaf68402d5d33dd699708 -99fed0ae4112ec9ed74baac70d202a885aa51cb555a3886b49016744dd4017640dd5dd564998c4d842a9f38f3e004e68 -95c35401314467219c8bfb1ccd1f1eae6ef4fa9e48fbea14f70d5315e67b16c46cd03554471840e4a5030b077d2a3856 -8d029380e0c294400d6b8673a23aed43697cb6460fc1bcf217aca3b47cf240886644ed09521d6a05f6abf56f99722d84 -8ef54d1dc0b84575d3a01ecba8a249739edfd25513714dd4d1941fbde99dbbc392f7eb9fb96690d7052609af23aa57f7 -b8ad2b7af4812417aa8de8f33a26547f84bb84f39501d4b7c484cc8bb54c7e166c849b95240fbe459a4719a6e3bf1651 -9858545de898721d19930d8b360cacc5ce262c8e004867a050f849f7a2f2aba968c28d51f24a9af56aaba23a9ded4349 -94ea5043b70df1db63f9b66b4f9d8082776f721b559f27d37b45e0a84faf47f948d7c4532dfd854a4bac49fb2ec8e69e -a2fd88d7b15e3c2778f6c74470d0f9e1a1f979a4d58bd205361eacadab9973d585a6508e685e640b272d6f8a448eae05 -88defd6bccd55db8ca84e3c8d0fc55a3456b41788f1e209d0aec19c9c70febebf3ae32cacaa1dbbf796d7ddea4b17995 -88b8cde2449d5ee7de2ee2f32e845d27e171a51ef64f1d3d8a5fd7dbb9f898ea70eb7f6410cddfd7b7ae70ea8073cc2e -8e044fff6ec557824866ac76301b6d93ed19b7177aa6baa95046330f5d69b572b59200e3653cf2f2b559455e782e8960 -b5446b4d6741c824885790d2d26258729dc0ba2f469c85a47d38886d933b785a4f38a951d37f3ef4bd5091c03fa3a071 -956c8afa8056e9a71ab2e8be5241ddbb3a8b3cff2110cb0e7389493d9fa45e6c4b769ebef540a952db6dcd8bd55baf64 -925950cae25615246e29d594ebf34fa7d52f78a9867338648158f2131e6eb4dc17e18f9db8a5fdd76d017b3a9798b3a7 -a17ea4b43211ba990270c21562690b3ef154a46c3d669c4674c80bd424cdfa95d8850c8e882b8d06504f929cba3d93af -b315ec723973a138508afc387ef651fd8a8804f93975fc36c2eeb796a304eeb1508518d8703e666a74d14318253f526f -a995742d7433b3f230e622de23cb2d81cac76de54831491cc29768eb4a56da60a5cbd573e1da81fddc359b489a98f85c -adb2e89f0d15294d7118fc06d4fdbd9c51d3ecbcc23c69797e5b8197eea0d6cd1240910cf22fcab4ef1e2dc2dd99da91 -b5ec9f9fcd0b5d176b643df989bb4c4c1c167112373d662fb414875662d1a93160dc0b5cdf540e8a30e5fcbe6cfbbd49 -b1291b53f90aed275df8b540c74a1f9c6f582e16c5df9f5393a453a3e95624ab7552e93d6e2999784e164046e92ef219 -8bc7b7b1a584a12d5ae63d0bbe4dc1b63c9df9c89bdd1095ff4b8e7c822bf8c1994c92310a3644033c7c9689f4b7d2b0 -ad7fc45506a10ca48f991714ecc055cea376c0cbe667f3b40ee8dad8446218835439ae59bccc474cf47b053748ceba6d -b134756828a5f5725c0b95109e09ca450e3834b127163a0aeeb544e63cc0cdcdf66f8ed98c331c7c98758f46af369a84 -94535bf1636be0974b112fcec480ed8eafc529933f3065c40e417e608e43a392206cfde8bb5a87b720263446c90de663 -a4df4f6efbc3701000fb072e5cbed2754b9ef5618386c51ff12f95d281d1b700fea81fc1365f4afc66a7c83bd0228fbf -b0336b3552b721087c7e2194976a9119aee13ebed9f1c3c494353707fffde52d004a712965f460062ec9443620716302 -99a39d1d1ee4283b75fa8c1fa42b6a3836b734be48bdd48050f9b05e48db6354fef509623c6ec8d447d630a9b3352b77 -8e3dc3583d40956f9e784e8bbd0b5e65671d2ff2a7c387b20fcb7da9b969f2d122aaf7f054d450dc611737604548c03a -b5068ec5b7bcb5d8583d51cb25345990f50d1f7b82fe535a6a6b17756355885047916f466ea3ab09eef5516bbf2dda90 -a8284ec1eb1d21e693f31a6c074199ee85d8a8da2167bffab5fe240defa2773971c8437e358a18f7e58d1e2954f57f6f -aa7415639d29081acbaac3e9c6b059d68e8702db3f430b86bb6e220d476fa74841c875e9d471c8a5423c58b6fee3cb54 -8afcfe6f65fa6e07c2cb3e1756c0ef2c589830be96edd50c3c248e3b17f51a4b08ba92ef7eed7991d81667ddfbf2bf7f -83b9c8dec8ca8f9b85f0e36c08c5523cfeafb15a544398e6f93b48b5fc4b15a0bd05c0f176a9c2469664acab8dffb0a8 -82a128a89ea46b9debe5c903b950c0ab30cd7570b979ca911500b5c2cca5c4ee6b2c2fa414b5f28e367f4671ffce60f4 -b79fd0ccd2629a361cd6f9307c02ecd4d1f07e4ee03ce4b542997e055b07a026cbc0ba05fe3da309efc58db2e401a8fe -b190751141093823b4b5324cc26c4f3258552f7893241201f2fca1ae9b1a1d4d4964a9abdde8642cf308ded61ce5ef09 -935fd48b95aa6f9eada0cf9a25a573f0ffe039888b3410788c41d173747bf384c0ec40371bb4383ddcc7d9f2db3d386b -b9affe100d878491ff345636ffd874ce1f27852a92417694afce4163e6a80c78b2f28d78102fd06c3283ef273ad37642 -a877670276d49ec1d16c9f1671e43ade11c0c1a1413755f6b92be9ad56bc283e4bd2ad860367c675d5b32ff567301fc4 -8c660d16464878590761bd1990fd0fc30766e7e49e97b82ec24346937856f43990e45aa8ad37283cb83fa16080d4a818 -ae1412087da5a88f3ccc45b1483096aeb4dcf4f519ff3dbe613f63712f484bdd8b2c98a152a9db54cf1a239ae808f075 -ad83cead97a9c3d26a141604268f8a627a100c3db7e5eefaf55a1787ddc1dd5ffc7544e4947784cb73b90d1729003c8f -97c3140ce435512a509e6ff3150da385fdf9e0883a5dc7cb83d616ec8d0a0014e4e0fa57a4d12c7997cd84e07d49a303 -a353773ff68f1615454555bf658eabdcca40a9c7bced8537ea6fa8d54764fd1f032889e910d2a2a342835513352e2d2e -89e8df0c17a36ffe08149c2ef8b27306d04cdf437135aaeba697abc65e3c8e91bcf1817919a8a826acdbbe7dce79a18a -9928c2da15ac6cb20b15859c22508cfcd452c5643cd22eb84abf5f0a1a694fdefcd8fc329c9b40babc52630743d6b65a -99d837b556f8d13108eef6c26333a183f59383b39958dd807b10590c3d37f62ade6c4a320ca2e70567e0218b0ad5807d -9272da080e4aa18720b634640b01bf1fe506c7c8a89dee8759a53e2ca5cdbbd4a4f3aca54924c46b935362cf1eca066e -b4d39752c882de1c1daf3854202c1d58c2bcf35c882006eb640fe54a97be2655281cdb91c30d1a41c698617c2cf64b01 -8bf827f4a7d47e07374d338a3d8b5c2cc3183015b5a474b64b6086fcf0cdcf4852046c9e34d7917d69caa65a9f80346c -901bffc7db9c9416e06f593a76d14f6d9e5dea1c5f9557bd8c93b9e70aa4782bab3518775c2a5b285739323579f7cf0a -af7e204388568627ca23e517bcf95112ca8afd4c6056b7f2c77c4da4b838c48791191565fd38398587761c8047d11c47 -ab2576b5366e6bd88b347703f9549da7947520d4e9de95d7e49966d98249406ed9270fe69347c7752dad47e42c4ea2f4 -b12e3b228b761dedd99d02928105494ded6d4fea3026d73d65ebffa2e85e2cd75b6d091135d418dd95ac102c22b5ee31 -a20b4a752685d5e31ee7e2353c8a1b9a5265f12bb775004d282a3ecd9deda44831bac1ac5151646428b66909b2a423f5 -91a1d4bc0062a86cc6786a96fd3eb4436d8a4a187b7cbba02190d1cd6ed3c3797d9ae7d6ddc413f1c94a21f62bd04ef5 -977f18da1a5df5cfdd0276f583cfba2b2a0fc6139520664e20068f8dfdde33e29d179abfd722f142448f4677aa47be6c -abc3ece90f0f7b1d80fd917de27ab0d88cca584ef959da520825e54cb5a71336b15f8b348532d08d47a6fa600527ef25 -888d36a2c7cc13a1c1aa338a183a74a1f57713e76cb825f9837f43279ce4741999b76a16928147537bcc20f2e0195b0f -af3f5dfdc2dcfe19de893f385f39f550cb1dab67c2e97f1d5fa735e5ec96d6680066803e8a0eb010dd4399f654195513 -a0fb4e08ff56530a940a86c28830956eb6dec2f020f7faaea7566faf0a4fafe0cffe01480e87763ec22f201be51a6451 -92343c5b107910b203c64a79c93d354f7ee5b7d1e62e56732386776e275285561cb887019cc00d3fdbe3b5d54460bec1 -acfe7df83c4624188a1011ad88c1e1490d31a8a8c8016b40aebcdd7590d9c0793e80d2d7ce6a7048876621c252a06a5e -a7da001dc1e33e0e129c192d469d2bd6e5d2982eb38f3ba78bae0670690c8e70f40e8114a57bd0718c870ca5dd25b648 -a903de5ff97dc83628290d781e206ef9d7c6b6d00cadc5bacffb31dc8935623ab96ade616413cb196a50f533e63641d6 -8f9658d42ad14a60bbf7263f6bd516cfee6b37b91a8f53715d69f718a090ad92484061c2cef999816760a78552fae45b -8c15b72b3d5fcb9ffd377fd67d9dfbdd706593fba9629002639973db12aac987bd1db70250ded31c88e19efff612cdb8 -88a2a4034decd854fb557960194ff3404e239953818a8a891bf72a0b26a8e570a65c4a630884de991ae7452b3234f31a -a09cae5c4c190537bf1dd75bd7bce56f7b799762af865bb9d1ee970f6a133c27cce0dd0f14a0e0516ceac41054e6998f -9760ebb1b40f9a97530c3b940d4ef772a225e5b63bf18283f8e302b9436c5209f6294980fd37058060e429fb7fdc3a56 -adaa9400eb86d857dc591b25dbe3bc8f207b69e77b03cb5ee01f7e4b006b5c8f6ba2b51b5a45687479885708509363de -949efe6b00b3248846747a9ad4a934d6e4255994c2b540a59fbbde395fe96d69bb67908441cfadd8c8bbb561fe52da03 -a19a45504b6b1dc3a0fe0e6a1384734a3dcd5a7cb8fb59eb70e49426c4fc44946547443d558e5719a04884ab3a2811ca -8934c9ee21e8d1435426fd0f64232a0670a7946ec524c054cd4f2cc8b1be9f89cc11002ca8aebae646a2050d91716b10 -b1150ff8ffb34ffdcf7d603348c0aed61e5f90ee0a1b814079fc2a41325c75f2f9ee81542797ede3f947884266a772e0 -86ce8cc7c1f92af68de2bca96ccb732f9b3374dad6657dfd523a95e8a931a0af2a80df74098514a06174406a40c16ba5 -90faabb9ace9e13fd9584932846ab28a618f50958d2ce0d50310a50c3bc6b0da4338288e06e5fcbaa499f24a42c000d5 -af4a935c2d8df73332a16dc6da490075cf93365bd0e53e2374ef397514c30c250bcac569b6df443985cf3720a4534889 -b7f948ee90f394789eb0644d9f5ad0b700c8e44e5e9ed0e49da4cc18483676d25740710b1c15a557965da635f425b62e -a917913091245beed6a997ff7043ecf60c4d655c4db0b1ef1c704fd9b0e1ea1335ce8b9f45d6e120f81805ce31555e30 -a48099da8406399bfb1ba834f6f7d864111d0036969a5cb64089947a63dd9467d3857b605e9f57f5ad5f4ec915088d9b -9784c3f9be42eed354542b1446d734521f8e3f01cd9d495ae98f2e4a3a16767fe2ad909e0def5d9a6267f3fc6a172cd2 -8d9afaa323847a3226ad7d7b60d87322ffcda2e4a8df89f58a076f7972d896588de685a2e155e243bcf9456b0a0d6d1f -994413faf0b843f4ec1842c706c45ea5f24351c68674a27887bc8b182eda756856e507a4e8bbfd937e2c4c581b629ee6 -b3e72d9d1ddaa00c7d22f25462d6e9f2faf55e30d138dce8bb1517eb0b67132db758668aac26164fd934d732633bdea5 -8e95875e338f714e9e293df104f0ad66833bbd7a49d53a4f7f5fd5b18a66a61aa0a0f65cc31d55e0c075e0d3e412cb90 -b980091862b1a9f9334b428eae14bbf1cecb4849e3a5809773b0d071d609727270f6ad97f329eca896c178ce65883db9 -915d7ae5ae780bdba27ba51a9788a8852a15355b569581d1f18f0d94bcdfed2c1ed5a4f58e049e9825cda11f92b2c2d4 -83e581058edf9259d0b06128282327cacbb6afc939578223cbf93544599f799a8dce1fb21d52464f990a877086f42506 -803612a38b6f6efb97941997e101ac1878e192456f8fbddb3359aa7f3023434ed8fa92e60ec8e7b4473b1948850e4311 -864a1bf4ac046161617dde282e44ab3cc1843da01a09ca58aa00ed00eaea9351a07a9ec16d910819e7dcc28b8d2c8ada -922eb142845975d5f6f7dcfee6cac8c299b3730400e6bf82cc0bdd9888de21de9d9f1530640f702c003e1ed63b140cc7 -a7db03c5be647dce1385ebc02f4825a654447fa8c4c8d4b22e635dbdd2b3ccdf219384e49a80cfb1e9e6182b6e4227ed -a167289ff0f0967bbab6479e4a8a6f508b001bbe0d16cad36ab4c105ad44f3f180e39a6694e6cd53bc300fe64dac1e8c -b7766431f6379ce62cba22ab938cdbb1b0c7903dfb43980a417e0ee96c10b86b447241e9dd4722fa716283061b847fb3 -90cda18c5d66f5945c07c8c7dc453dee1370217ccb851bbea32578599aa669b4dd245dd8a9711b27c5df918eadf9746c -ac690cd2af39932874385fbf73c22b5d0162f371c2d818ec8a83761e0a57d2db2fca1d757343e141e1a0348016d5fc44 -abac820f170ae9daa820661f32a603ed81013c6130d1ca1659137d94835e1546c39a2be898b187108662cdcbb99d24fe -b2ea5a5950096772f2b210d9f562f1a4cfacc021c2e3801ac3a935f2120d537471307d27b13d538dcbf877a35ff79a2e -ad94af4d0699cd49ba8ca3f15945bd09f3f7d20c3aa282a3113cdf89f943d7793e59468386b067e3c1d53425dfe84db4 -83788367ec97cc4bbc18241cbed465b19baa76fab51759355d5618067009298c79d0a62a22e2a1e6dc63c7b90f21a4a5 -a3e142d879096d90b1e0a778e726351fa71996466c39ee58a964e6b5a29855123d4a8af47e159027e8e6be0ca93d9955 -860831f8d3edaabd41be5d4d79c94921625252aaec806251fb508e364e39fde8808d38b10d557e487603a1b274c9bc3a -88da39f334bd656a73c414ec17dda532059183664bbbac44eb4686c2601629ef8ff9da992c337a842e3885b684dd0032 -b50addbdf7164e8303f33de5ce854d6f023d39c1c1984b214d9e5fb6f6001cd5bdda816f048a438ff3d696872672f805 -999e58c4c69a912b84561cb09610e415b43832beeb95897eca8c403ef4754f4277754d492eef3673afd4362f50060fc9 -b88ea0f60f8119c5a1fd9294796d387472dfad22442b29659713d1d88e7d854cb7cf5c9ef773627781188626bb2fb573 -a068b3844e9dbcf74b54fd55904d56af754d8ce4c619fead7a07f9bfb9d02118db7c512ccec2489d2a84374ec1d1fb6d -871dee023768636003c799e6f6fd8d31315a4c0da7286345cd64264a016693b3485e0732be1bbd34dd5fa04dfa58a983 -8021e8f508680df12e4a5a1bd49f2d7142df65158b0a7198ffa83abd16053a542fb93ffc33e5279020ba8c6a26feacf2 -b5d3cd64df5bc965228b0bd4ce9e5797c409f7b64a172ba165e44a8e4b38e3d5fabc3e0b9a19afbfe427f887c40a315d -a54fdebbb594bafcefb1a03697711e0091c072e1cc24fb441fefd4e0a0518675a1d7b0966cb8294051d7ec0ac175d0cd -93922202337f72969d6d6e14a29c9c75e0420dfba712029941d1504b9f6f9761d706cbc0652cd09a1aa5d22aec766af1 -9711ebf1c7c7426190d4afd5dd03b014a456bbd9d90ed101623866a280550df26a629dde400c03ee3699f7d827dc0bb9 -b4d686d8bc5c1e822a50124c1cc23c6bc3a1577a3d0b8d4b70d1797418aaa763283c09e8a0d31ae6d4e6115f39e713c4 -a533ea2ac683e4ba07e320501a5d82a1cfc4fa1d65451000c3043f0fdac0a765cc1125d6cc14fe69975f3b346be0fdde -94ee563134fe233a4a48cf1380df55ead2a8ec3bf58313c208659003fb615a71477e5c994dc4dcfb2a8c6f2d0cb27594 -93e97d3f3f70664d0925be7aee3a358e95ae7da394220928ae48da7251e287a6dfbd3e04003a31fab771c874328ae005 -b57440d34615e2e7b1f676f2a8e379e1d961209fe00a0cf6798f42b7c28dbd03172fce689305e5b83e54424bc3f4a47c -97644084c6f7b4162bc098bed781dd3af6e49e7661db510975528f1dea8154f3d87e979bcae90c3df3a7752eb0752889 -a923b27b225b2a6dd5bdc2e3d295b101cac5b629a86c483577e073cea1c7d942c457d7ff66b42fcf33e26c510b180bc2 -86698d3b3873ed3f8ab3269556f03ac8d53c6e2c47e5174ec5d14b3ed5c939750245441c00e2e9bb4d6f604179f255ef -87946826d3aa6c7d53435c78005509b178fdb9befc191c107aee0b48fbe4c88a54cebf1aae08c32c3df103c678bad0ca -860864896c32b5d4cb075176f4755ea87fea6b9cb541c255a83d56c0a4092f92396a3e2b357c71833979b23508865457 -b78fa75d687349e28b4ddfe9e2d32bb6a3be13220b8f3ff1ded712088bd0643da9b72778bcca9e3b103b80097f48bdd0 -8a188b940446598d1f0e8c6d81d3cada34c4c1ae0118ec7e0eacc70d1bced28ae34b99667d5793d9d315a414601c3b22 -842ac6f7dc14191ab6dddffcbc7cb9effba42700a77584aa6a8e17a855cd444c5d138f9d61bf55f43c6ffbcc83f92bc9 -b6742902c3d145a6af9738c01cf9880dd05c85f0d0ef7dbe93c06fdd6493333d218339ebc2a02be1895436a2f734a866 -98bf18488483c627b7181b049d3e6f849fce1f15794de59dcde6e5a9b0d76fd484a46e48822a6a93001d3aa12f48bc6d -8769cac10bda8c53a1c19419ef073a5998f73dcf2ba1b849561615a17cbc0a49bfe3eb4ff8801dd36a22fa34b9a3a7e2 -b45c084d58028fdfae792210fcd183abc4ffddeb4cf52ebf3f8a50e4c4eec2a2758f1241b0920bebcb24b757c778577c -85c1216eec8e1fbc1af9b36b93c5d073a81d5fba86a6daae38748ec1573eacc6bef209e76c87a6efbd7a3f80e11d4c3c -b8007e34bb3f927ec06a050b51e633d7eb9e9a44715d5b39712e69c36177a03cd68391090cc3293098e54f6cf65f6caf -8e85527b27c9152b1ba3fdd532a76a79064ab097570508f233e09978761dfe3012d537411b47d0e4b65265eb32cea2ae -899779f3c31a20b76068ec8d59d97a64d2249588ddfd69dcbaac6bfaee8ce0ff3c5afc4e17c934ae7cd041b760eb555d -a5dac3d8f5fbef018509612e25d179f60d2a62451c76426bf546e9666fcdc73263d34aa6fa7e2bfd4c9947bbf5095eff -896900eeef9be2b2e755128e7b1c436af6fb3984f1e66c444bc15fcf3959013b4902c381f0eab1247f878a6ebd1f4ee0 -8cb17f4b0af2e9b2cbb56f46e6a5d6874ea0daf147aae77303020b4e592ddc92e0dd058def7da96258b3a68b223bf22d -a1b6d3f09a9fa7ecc021ab7c5396541895da6e9bf1f9a156c08fc6f2b815a57f18c337ccfe540b62d79e0d261facb2be -ae70888811434ef93da60aeee44f113510069fd21161e5bb787295492eb8df85103794663fc9305f04adcbcf11ff0c5e -a84bbc8624100acfae080ba8cfb48fd4d0229a60b62d070bd08fade709efc6914dc232d3f7bed76a59204f9252321aad -aea47d54652abd8ca213cfc623c8e30780f37b095b59ac4795252a29c2b6bc703a5203acff8831314478b8ee8771d4d7 -8dd438eb8be14935f759aa93021c2b24e1d588f7a162c42c90ec3a647b0ff857f60e24c0a8953eb7bb04e04be70f11ce -922b07b5469680a10e7532766e099896f4dc3d70c522d8add18f5f7765d4ddb840df109146607b51ceddd2189fa7b9c0 -83ef6ebd0ae6c569d580093e8b0b78daa964760556272d202d343e824c38eccb424262e5b7809d3c586f9e2e9c5c5f22 -97f98bd357db6e093e967fe180cf67ed09fa711580a5ad48f07cf095b2e8fabbe6319f97d1f15d62c0ec2227569d8dbf -a1953a4a22fe6c2beaf2a5e39666b0eb53018af6976e3a7aab5515550ff2efa89400605a43fb2c4ac1e51961dbd271d8 -a5cbd67f4c0bc98e20aa74c09e6f5fb6f42c08e59aaa477b4b4e61434c8884bc14f17cf11faecf46dc4b6c055affbad2 -87d96818f2c4f12fd7705cf4060a97bd28037c5ac0f0cc38f71189ec49361e438ce863e6617651977708094d5336d1da -85e7c2daae5fe59f8a1541c94df50402a671a17dbb8838113fa4b7aaff6114cf2bb5969410cf21e6a162857f2f7a83a8 -a19575083e1731bb04bb4a49414e97aaadb36d883aa993d1f6847db50007315444814740e67e10177a14e0e074fd4c7d -a00ebfb5bcc3a6da835078189038a1e56b7dab6be74332b5ff7440e53b0f9e1eb9973effecbbf37000021fcf50c7c1ff -8969d7943abd3b1375fdfc7d6124dde82b0f7193068ed6ec83bcf908734daf3487a6a30f7b322e54a4818ae5f86d91c0 -b959c8d210fa43af9b20d1fe0ea8c4921280eb4544ef6ea913309ff9d61c9327096707e84dc1662960519be8e7d080a4 -9011d8ac651c42e0cb03931a9e960f58e02524c6b666047525e3b9097e9f35fb2b4b278efcce2bd5ad463c6d7fd56694 -937e3b22ed0fcdbd9ea5a1b97b84bbe86b7f5b2de3866a930611112f2217f4ee7d9822c4ab1253823f77bceeae0c8e10 -828997e5d121f4c305e018a0a0ba338bd6a34a7b4dc3c5ceab098ee57490311c130e2c045b9238a83908d07098d9fc32 -8d114808eac0f2e1a942d80dad16756ec24f0276763cd6771acb6049472e05a9bb1d3bbd5957f092936b415d25c746b0 -a063c5c26267ae12887387cbebbe51fd31bc604630b3a6e8e177e71d4f26263be89112cd12d139dd4c39f55f0e496be0 -ab1e1582c8d67196d10f969eeb44e6e16214f1316aa4a2a821f65ba5834326da6cba04373eabfd3b3072e79e5c9717e6 -a17b1dbaa11d41457e71a9d45d032448091df7a006c1a7836557923ab1a8d7290ec92a7a02b7e2a29fcea8f8e374c096 -a1ed7198da3591771c7c6802a1d547cf4fcd055ca9010756d2a89a49a3581dfe9886e02ee08c4a2f00b2688d0600509a -af09aa60c0a185e19b3d99ffdc8c6196d8806169086c8ff577bf3801c8ab371e74165ba0f7329981e9252bfe965be617 -98c04cc8bb26ffce187fa0051d068977c8f09303a08a575175072744e0a5fb61191b1769f663a426c30d405515329986 -a542bf1c9c3262d488ea896f973d62923be982e572172e2461e0146190f2a531f62acd44a5e955a9f1e242b3e46d63ae -aef7b7f30efd50e4a66c87482386f39f095bff6108e68f74fd3bb92156c71c75757912b111060cdee46a6b3452eed657 -8afe1e0ccd00079702f16ab364a23bbbd3da1889d07c4f8cb04fd994bf9353216360dbd364492932bfe20b8b69ae8028 -9896c690999db3c08cd7b25efb1b912c3e0f976db98a3e830f086aef93222d06ce570a7b2babcd7c81d8f9955169669c -ac7bcab6a281468907ef1ea8a6c1cd624159c88839131bef6aa0c22f331fc87ec6128a2c2a333fb79df549e4587e1a12 -987935c08a30b099d19f96901315a2e60591baf898581c40bf5eddcda806ff24a4536e30ed1e6c0b128a83fc77b6e81d -a0a6945bbede3bb09a4a09ef27baa20619d3e15af5673b9350601bcebe952597c989870746cf75767ffb73b32c6c9c6f -b0f5590079f0a0302b08a0cc1b7a5f39cc6900c2a5cdc7baa333d8328a731b2df5dbb67e27a154d3c44ed1a795fc4adb -a7294bdeea210e528f277f3d50e89e6d79950494478998181ecb38de675020130256f2f2a075899170be964d478458b0 -8ab3041b895a631869b439d5599a66facba919226ca9b39d915f19d59f9fc82393ea781377e9bd3bcc5a310e41376914 -8da399b59151fd48b2579948bb82698e3c9804d70ec7d6f3cc7e82901f9f2de5ee850349a7d6f43e5e9ebd47bd78620f -80e8c32de83d1083916d768b11a982955614a345d26d85b457f2280ff6c52bb776958add7c1c8878f7d520d815b8e014 -81bbec7bd99d2917d2dcd8a288722fb33ad5a4bf5416fba8609fa215fb80e0f873535349e7dc287f892aa56eb9e39c4a -9665796fe04c8519206fba58496bc84a8b9113e7ea8e152b65f7f732e88beea271dc97b1ea420dbc8257cc4b18a77463 -a97e342aaaf693ddc87e02790278e4bb50117af4413cd703bdf3b7cad2d1facf31fde1303b43ab2e0265467474f97a8a -925549ebebed348886e37773b05cd8ad04906eca4536bfed951d1ee41b3d362ddc6e1a302c21ff3a2d1e70e95117922c -818fdf74d7903502101551bbf48d3c7819786b04b192d9e94362d2fcb85760d8b6f45165a5443aa5221bef400525ddb4 -a9d29de7e8fd31b59f4a087168d062a478b1329cd3c81c31e56de4fb40de7a5be9a5269ef0be452c487443a0b097dd50 -a85286ad573db4c9aa56221135da1e31d742e0f6ff01d6b159086d7258f78b08dad55ec8eb5c91ee9d3404b2eeb67e1e -92a79b37db5e777f9ebbebde24a95430a199e866e56597c7d0b0e7fb54c7b092c2f6cf61fb24470ddf250cf609898281 -8d79f5ca67ed67d52c82949af342a9fc60fb793c47c76d84b4863c550796fcae2dd59e285897c6fb96fe31cee1efa62c -8ad2e0bda03415ab86324992bb62dfa3612d2d003765bcad1468087c27971d08bdbae5252681f0115a184f4885d444e4 -a08815af979286538c31b4aa5ec805053790af1ca58a8c4341be51136d094a8a05e569d876a079033298ad355ccb7ca8 -b96c2978d0165d619d08281d295e90df78bc2375d0afbc3142ebff9c2cd4b0f0aa97a9a0e3740bc4dce0ff8a9fac8252 -b7752cd0e582f35ab0d0036ca9c0a9fe893a6ad325164d78d865a604a85d3d23729e0362553e8b8a3d51816beeaa30cf -99cef1fafc29e7adfe247c753c475ad4bda7a5f9558b79c86e8a65968ede67adb38dc30071925c9d66a13860027a6735 -b9f6c65af178c791b6137d71980651fb09cb5b42f268999c728c6e129985a9c7d77b3dc3b50751bd29ec9ee0b3111dfc -8d73ae61fff5be883a281782698075c5650083f00399992688738856d76d159803be0059fbd9dec48f4f0432f0590bbb -a8a4a2865226de9bbf19e12c7e75318439fa6cf1cbf344d5e79a8f363439d3bc5bcf4df91b54581e7866e46db04eaf0d -894582aeff222e145f092ba15c60d3207340c38f2c6792ee2ab4d82d50fb544ae366c2985cc2b6c2f970bcc5f4b46385 -956014ba2d20a056fd86cb8c7ceeab9a2c6f905dae24fc1c5278fa5b84335148ebdefec5dcde8eb9b084700724fc93d7 -af217fe2b654eff6d11a2a79fe0339a1d4cb3708b7be9f09d852158b5a44b4f9b04406d6d67c4f144fb6b69a41ae9d0f -a90752a784bc00df94d960e523f5596695d16a534fc806179e0f878fc0e82a91b25e758e91a165debd815dd1af5f1028 -a697606fb32979549ad822b31df8eaaf50de4ead984439a0a33e955937d326519bb9f62c8243ad37f764655f8d32cc80 -a3ad4a30922e45a3e665551e5611384f1c2d414f6fa806184b0c826af05f014dc872585e255543794ee41e43cdadd856 -b29c255843a82ea74a013bac6c36a694646e61e6b9cefc4c130e2ee261e3bb5da3e0fe3ee7e6fbb009deed0530bc1c82 -87e1cc7febefa829cf050aa2aea59385d1048f8617abba691f7ea9ef58eb90ad12eeb9c439af228b0e34897ba1cf1b47 -994d3222f89e9c8c154362190be7167c8c2662f0cfa9d50eb4d8175b255ff0de09dc548ee312fc8226963c8c16f43e8b -8f1a980be640820f2d1e953264ca4c30330878971669852be3d5d6b41c488be1628b935388bfa2bd4de484acb0fe661d -854d90d0721579c8c88e147a4aa83553c960617b18075f8224b975562dccb30b0e02e81fa9df7070f356a0eeffc3b14f -8e156da9d4330a03e32a25a2f0b861fd3ea5c719fa4f834119baab6e5fa5236a9baaf0d44147bf0841418900037f6eac -96586fc49e53a6799242ddf617000db5a0ad20c6cb1686af2102623d64a71aaddb8e468b15fa6d100d0384e448548db4 -b44d8d85c8df95d504f82d597f8c515866d4d4a326fa1b816dcc5bb0cc4ef1a52647aa5d2e84c62e194c01cae0885d21 -b75c43e676a7efd199f8b32ae31f176ec667e714df355e9eecee97246f72af5bef9c5b04c11e7e90fc37bb9163f957ec -a49835ac0565a79f6a9078cf0443c5be20561a68b448289589721fded55188583f1d301925a34eea647f90a6e66c6774 -b47c17ff6824a00b8f29df0adb7f06223208d062bd703b0f763c6eee4ae62d4217eef2da4f4dde33f0b469c2f2db9e42 -957cf039cea6f6d41e368e2bd0cf77315938a0738f15ed9ca342f0a28658b763659ac1d1a85ecb362f13de12b77bb582 -903a52f8d2439fa63f59e1e9aba864d87b0464ded63814474947112375236a6f84e8fa003cc4433c8208d80e05fbd1b0 -8afd524209ff08d1eb6312b078f7afeb8e1155af649e930ab711dedda226dc2db6b0354aab9652eea7f433f90015bf7b -a95c3c9277b11bc8fe191773bf567641be57c0549913b973fb18740ff9cd7b3f7ce198fa4dc1086b2b8a446012459193 -9455ce8163fce04aeff61e7808ef3aac4725e51404f0858fe5d39d7344f55dcc7871ca332aa5cb1a63a4399529e48907 -809fa35b6958f94e781f2c584438b33f5ed528a6b492d08960cf22ecf63ea3aa1e2d29bc879e17296e0a6cc495439cb6 -b0f50774de212dd33e5837f6b496556215c665437e657f674fc5117e5c07dadbd0d057e6ac4c42d50a8eb81edfebf315 -844c65e263891d0b2fea7db6934cc4b7fb6bee2c1d0b9ab4c47f2eb3e9c5d7197dad828d38c54139123740151420280b -b13c78c9efcbb3b28eb3fe0b971380b7d5151c80948a99cd93c78b4c3ab0e86df6226a64d91e0a2ea4a1c0a46bc0404e -90300a541decad460c348b8f4257f7a29687b2362ebee8d92fd03cc0e85b285ccb0ab1cb2ff5e29c5cc5295e351017cd -ac49b409ded770c6d74f6e70104c2cdc95b7b90609da0743c9923179e8e5201ead03becc0ab10d65b3d91a5be0d52371 -a257b815bd8289dfdfc21af218aaba12ccfd84ebf77642cc4cf744d9b0174ca0b0d7ab2a545c2a314fd5f63c140f41ab -a34778d8446e4d74d8fe33de64b2694ef1e50bc140e252af6eff3ce7b57acf8b6577a02ba94b74a8ae32e5113cf0a29b -ab9e935bcf0d8607e3d66f013d9bce7909962cb7a81174923db02dc89e485c2b1c33d6065bdc7bbbe0450b5c49fbe640 -94d2c5c5c309c9eac04be4636f61bc47fd9579b47aded57cc6c736fefb8dfd8f8a5de32210f7baf2052d04c0219d3b4b -b8dda9046ae265214086355101be3460421f7cd0ed01bde9c1621da510941d42bc93cd8060fd73f374fb1b0a5f38d45e -a6674649dab5f92ab9fa811d9da1d342cf89ff6eff13ad49f4d81de45438e81a384098d3ae5ccce4c67bda5dbe246d95 -8d619f7564677bacba29c346c4ef67c211f7a3a14c73433dd1a7692e16a7e2562f1d0532454af62fc04c2fd2bb1789b0 -a2b93d2fd4c707f5908f624a0fc889e20164d3c61850af9125f47a1719757a6ce6375aa1910eafa4c1e8b6e20c312775 -a07d5585447654d82817ef4d199984542328b238157976eb9a267f0bdb2229acc25aee510be68f65a312b68fdd9e0447 -8ef55cf95e2b24d8ec88e4136399a7763bd1b73d5e90ea45e9845123e9d39a625cc336e9b67988374b8ebcbc75f2ed21 -b62c1fc32e27c767c461411b02fe9aa44a86586e1427406f4ef0b346d077db91952abce79318b382ec75b7be23058cac -b252900345f5fa15a4b77fb6af6a2d04db16e878b7bd98005333f7f6e3c8e6e46cf38fc5d1b2bc399c5c2ff4af730dc6 -a4ab5ac0cc15d3d17b1747c6e3133d586870eae0a0d9c8fa7fd990ebd4fbb62e9090557ca2792a6bc6271856aa3c9a05 -8e706b3f2e902faee10b22742c6c33bea6f670a8937c243db96885143c1db5c979e33ab73a38359b52b8d668ccd092a9 -8a6792190ee6c959d79f60c22980ca140c638d88d75660adaf9bcbe6dc4692ab5f01e0c460170f09f74d5e582e85ff1f -97ffeedfc94c98ec85ea937e064d7b290a326838e62cebd407facd1ab4f08d9c0c109d79af7cb6170fccfa6c8243c127 -b79970b67c09453614ffd83a0c923c17f857c6ce3c87a356298f8351cab0def7ed83efd4f6638f48df67e07bef4ad9d8 -b90f1931c7cf1822cc0a97401119910cdfd0482daf09a4d7612e4e05046295cfb4cc50d5214b31676bb1a1c9d15f9c7f -922921ad813c01fb5d12fa7fb7ed8e0b0abbf7b19affa190b36013c55b88fe3c7df0ae663c970eec7725ba37b95a7cb7 -a124f33e7f28feabb4089a063a08d52b7395d24eecd06857a720439dd9414b7073bb86fbd0b04e7bfac62d3dc0fdb2f2 -b252fe50bc6677c004550f240fe670974a33ffe7191ed7675da6ac36c780c2f8d02be7da5d92cbe2d0ce90147847f8b1 -ae5f8c9c56070f919f3df2d2284348fa4b2e39881f7bc42c9b2f5b7cb1ebeef8ecac000f37329bbe04cc1680cefc7f4e -b432a4575caf7337f11eecfcbd34a6705d0f82c216301725ceae2b3c9df20fa53d1ebef65513e305013d1e0c2df522b6 -b7c016fbbc4614cdbb12db1c9ac41f9a45d5e5ce82594d568a30cd2c66c3cc9d91a2c959697b67c582a0913de661505d -8f6f3e5e0347dddc1b2a34ec0dbbbb7cafbf976f19c9c902efb5c1427d1bbd4b71abd9f3fba20dda75c35a39393c989f -b0042a1d33a1ee9fdf3fad2299b8d70c4f1862d8393b5ebe3ac2189a2c5a58bb826128cd7a39b70d524a6dd976097e26 -85297c4e8ae8d9b44c3fe51aa926c77d55db766c2a9f91b659040de36e34c9a4fc6f44380f8d61704498f6fd52395a49 -8c61a988b6a00fe5a277450f30bf6daa932e42a2eae844568e3babf8815e09311f3c352dae6eb2d57a98d16b7beb2d22 -990be28aaecd932e7edb2a97b9be2789a3905cb88737b1c79881302585801c69a3dd5fb230808b39db1352fc06e0b4a8 -82fd14bdb335aa46f022dfe0ed4d631911e6b6f5eefb10d11e9e2e02a7df55012ed8162249d10b58eb76ced5a7b06cda -ac39cb058df764e161db9c39b185f09aa210bddbd66f681f1697ddbe6b305735612d5dd321d3ffbb4876771bdb321e2f -858a3f7e57ccb81387caf8e89f9b6039e9aadeab06886d8688fe6427151a59ab2e77e85ba850c67d099965426c97779a -b57fb9ea623cec432946819937c6bded0b5d03c8c67b52b44a4b67d34adfb055e6cabca67a48e4d859b4be45162c5083 -b84d2990b563d6d7fe1f4c1894989db25b81745090b94b1fe2ef708ac3b2110ef93d647820b2a51fcf78e3f00fef5412 -817d85b9f5e1521733d2b1fa6d4f4957ac445dc803f97fc495e20b819b14e651332f9e0573d684b854fd47824c53f0e8 -b09e18e97e93a8523101af594422fb71afc5b8826002314269016fcc1b44002d91bcb7c90d923d460f0cc03bddfe9af1 -b867cbede82102de7cf6cd0dae68506869576eaa66c3fc806e73585310602682fc912dc37adf5ff6f0f34a07831735b1 -b1126255798368b692f2796a3470ed16e5ffdee2d8c9e0f7ee3d2e92950c3e6365c32895171c3494aff2a6d6356f7e25 -b05f0a0996dec16335c770a5df3f0b08e20020c838c2caaa1d3a4a2490ede98552f5de349de2ce6e4c4a839731d80919 -98c512bb91c8fa191120ddf5d63c88076581cf41e15eec3c168822f12b3dd0ce4d6df74a7e3093d3e35cad1cb3135421 -84ce38fd97f7f90012c2c1e59a67bf9f465a7ccfb6f308bdd0446cc82b8a26ff7c30e5c7cc375011718cad1b31adaa9f -93139db52c9fb96dee97a0825f21e34c5d6d36838e1e42f4d12d01eacbe94426c85a811fe16ca78e89e08f1c27383d28 -81454037b1e7a1765f67e4288b8742eebf6d864d9b0f508ab44fa3243168ce0ed30cb5f33dfcdb995cd2c2710ff97a6d -828deb2a26efb2ff1842f735e2cc27162360f619b6e3e27a85bedf384912d4726bb2759a3016937973092ece1bf90540 -87e5a7d4e7bd301078f625d9a99b99e6e8e1207c9f8a679f8ebbbfb467bfa0b5f7ef4a4d577c7d2670efa88221153012 -b9dc9d0ea48deee201e34379447bec789c8924aecd030eeb93db159af77eff230976ef60ea9f4b4a9e9e95c1f9f4284e -aa6528268d46bf0627d87d58e243d3ac34b863513c725908a2617e4c6a46ccb1d8c8334bd6dd0eea7ffebec44259dae5 -8d26c9ce07293f6a32a664d31e6df9a7ace47e6c38001635918efd9872aceab62de7757b13b783d422eb67bd28ce7bbb -b0d3ca88d9829a7459b89b0dcbdb8bbb5180b00d750bd959bd110f53c2dd5d4db554b6005c4765fbe7ec5903669e5ebc -a94d1c72bf3b2dc6bfebc9dee40f6a89a516b252bd9f4fad96f156e3dbfc151a9b8a02324d764c7656d59230a18eb61f -88996e79171e30b16505638d8ecb25afd875e5f3cc3e29860937f2b5e751c66e78dc77f744a0cc454a8a655142a93ffb -af4d94f342665fe7ecda318de6cf1bc1c40c37dd83d060fedaf827459728152b5f0e280286ff5e6a0012036f6715f53f -96beaa7a2d565ec14a4e5cb895d33624c69da56b75c8d06ac729cb6d0cb64470ed4f9b0387083cd827b1609c8cabde8c -96b773fa2fcb7377bf71a7e286f37f1f24ee42cba5b4f33903c4566e5e5bcc501ea360e3c8435749107c3de84e272d8e -a69ac6218454c3f40ad0beb48821a218fb0a4f33ebade986d2fffd9a3900d8cfa613bc71676c46cfeaa5f644d1f239a9 -857f139c08fcc45370f448ce3e4915bcb30f23daa4134407fc6d78efac7d718b2cd89e9a743eec7bf2cc0eccf55eb907 -adeeba36af137fd3c371a2adbefea614c3ae3a69f8755ce892d0dd7102fb60717f5245d30119c69c582804e7e56f1626 -afa97ca3548b35aeda6bfed7fbb39af907ed82a09348004d5705b4bb000173270ce44eb5d181819088aa5a2f20a547a2 -8423bd2d07073b0e87819b4e81997e4d3188b0a5592621a30981dc0a5a9d0578fde1638a364f015078a001afb00891c2 -b92e9d4ec3966981ee574695d6e4865810b8e75313e48c1e4bc5eebae77eb28740e97ecc3e5c42040f9eb1ee4b13b0ea -b07b218321d54cecfcd2ed54a5fd588a6be8d7a5b6a66dff7facfe061222c40553e076e57cbdfa0bdb08e0a009c94ba5 -a71e1ae4d6096eac9ea4c21f621c875423de7c620544e520fb6ec3cb41a78554aedd79493cbd2c2ba4f0387f902ddd2a -807cdac291246a02f60c8937532c8969e689b1cfe811f239bfdee0791e7aa0545e9686cfb9ed0c1df84748e5efa5e3da -a1faeb4504c057304d27d54fb3ec681462384a354a4f0b6c759d4fa313253a789250c6b0f44f751b0718592637438a19 -996bcd3215182d49f1cd15a05e1e0a4bf57e264400bf14f7253c6611d2571de7130cce81fd28e0411e0a80e9054f4f98 -89d15b38f14bcd46f4b2dcae82b0e7bf9a35e40bf57aa947e9c4a8f87a440b5cea95229708de08ca596762062c34aaa0 -8d8ddcaf79374c750b8b0b3d196acb6bb921e51b4619876a29d09161ba82a42271066187211ef746f9f40a5ca17b75f7 -a3dc7f70f3a6c7edc483e712770abbaa94bfa3174cfee872b2cc011b267e0ef9baa1ab49e4a6c6c30dbba0e0a1237117 -aa9e958bbdcb192b19c43fc6fd34afcd754949fdada98e9f4848e8db0e23acb27d19dd073c951a8819000f2356aa22e1 -a4714e45ec853eadfe5c3bee7f683b81f97857bbd7833192a48936dd1460aee68f700a21658658b74b737c4fecf90c7f -a1ecab4215c1892e4a8ff3405d710163875e5dfef8a8cb84f5cac4e317d89c7696e3f496ed1747ca6f52b304190f4ba1 -b9b48943eca3686219575026d395b969e6ff8159dc5317005df090e79d26901984e40ae4b1af060ed3ff6f42e0417d76 -9644b9f90a66edb0396abd8c00066886f978ebf56fc22081031fbc9ce371bf9b04aa5a4ef59e59319b3a05bb7fb88b43 -b2bb14f1c055a78596488e4e2d4135a6470c1ee43961952160b8498f674a4d23040606e937c02c1fc23dbd47e9bd4633 -8c61f2fce9a42b94a389c7e52d7d093fc011099d0f4914f6d6f05b631df7b88182826edf9bbb1225971a080ca5c0d15a -aa6a7b8499cc7d256043eacad18528d38bf3be970bea4c6d4cb886690280bdb373688ceba3e506471e1d9493dc76f3f4 -8127703363b3b35b06762c2353d4de82b7b85bb860db1028d3640f46bdb78f2d104fa77ee3e0d9db83833d2b12a966f8 -b7b01f5909f2c66ae0fab156be5d79954e3a304615e1fe55945049dd4bd95f973bb3821117eb54db7e9ed1ee9a527652 -8be47ba5dfe212420649193490838670c40540e0ea24adbab18c4a66e7ac3dcf94f068dec2533b60e08c1f64e7533e54 -905a6c7e24b86aa54a05c329a6b4616d335bb0b1f1e9987562eee0acf82ad302c7c44981a1dd6b24c6121ca12fb92996 -86969ccfd91deed93b355a2c21319e3bb08cc652b741463bf68c626b7ba2afce3f7cc397f2fb74588c2893477c948ae2 -b5a9d20eb12c331d0d300fd4b85b0ac0bb74573178a5fac8ec9dce5e95acba07fab444260355ece442a846737a2dcd1c -a13497c11df21b11fc1a63b0ffdcf7f432da4dc2c98f8d07d36da4fa68aceb57af2158088e5b05e334fe0f264aeb7a97 -882e4597cc66498a45e86a2ed9ee24652da4699af00ad35f73b5e74fde6ac3cee70630962d5ddd86162d4aaf11bbc11c -b748858c2bafa4a14ce44af35195e9c52aa75e109719243bbe278095acbfd6a7ae7e084caf8dae6939039b5a4e8fd675 -83a2e0524507e74f51fe976441108f8226ba1b3a33f4e16ec45c5661ce80cb1840a93d17122cb8ca9e0f80d14f69877d -846cd2946c93ee5f24243d9ebc69936b3a1a6d59f45fec6c79b1eddf15ce30a8e73ad03cf606ee66baea3d8ff115f70f -8d98d0a3a94f6efe158f8423c041b546416145c5c2254bfa157efea0d1c99fe58acc7df6424ef29f75960b18d664ea4e -a39fa47e4b79f54dbf59d0b1726f1e78bc219fcfc56ad238c84b4b610e7892ff1e65d537baf5118a32f5e2eb80d5ee0c -8c30969a4519131de5e30121c84c04f67b98c8ad109fa4710dd3149cae303d51778add3f258f0482f1c89c169824dffc -af7f80d141ceb78b4762015de17fef49d7ff6202d292e9604deb508272ee7569f7fd5be3b2438da1dfecf0c26533ef86 -97cf82f70128251944d79b8845506975405bd720e150d836205b048ff36ba8801eb74cdcc6425f28f6bc0acec0a81463 -8c276c876eb88688957d1868bf3a1462375e608ff72b49870a5dac82cbf6584e00e3f36f236f732348a47502ccf9539d -964765f1a5c8a41d8025ddf56dc01b78424703d8a64a4e5539e477cb2445cb541c70127c561e717256d13f91a830ba83 -a2aacd9e21b8c8efaf2319611addea1b9f41430aee42e7f2a640cc693aa395287cc8fdc2806b76b577d84fbd05378ead -ab11eabbf5be4345a77323a3b75f9ee93b011fd2a9d0154e88183cafe47f82a7888666af16b40d3cb677c94bcc755ff7 -a0bfe715a7af5a29b1b6148b8cbee585d2b49fa6ce59bcd173ea3bbc60d71a62f9da27ffcbbd5a6da75502112fe44d70 -902e6cc38ee42245103d90b65028a471bc7a48b825599d361aa81d8c56e0fcf9fbe8d4c13802040d2cfb85b7e022eea1 -8832e2b5014fdef4003bdbb87e3298fdbdbbe49673f6b66e2373f1cb2605f9c4af2cdf9bfd45d1993208681d29ee1c9d -a7d39d3fa1ec1e0c87730fa43d4900e91932d1cafb36c76b2934907becf7d15a1d84d7234591ad4c322b5a24673bba8d -836ed5f09d99624204aa3aa7ac601980fda223f3b4b96b4a8fb235c574a3545d518787c12f81bd5851987f2860d41886 -94235e94445e6086f6e9331923262070a4c2ed930ec519eabb8a30133bd4fc6debb99185f4b668431fae1b485c5c81b7 -9828ffe20b9405f117dac044159be2d3c6e2b50ecdd1651d6a73f7633e6e2a7ba3d783ae939973604446d3a1ef0fb20f -92f03dc365dfe9154743ca70e6dd2758f064e3286fc543cf8c50f68effdf7c554bd17b3507c6ff4127046d9bbb5522ef -91ed07df479d8eb3d31292a0e987672a7f3d45ecafe72935b7abbc3f23493605134ce573f309e226c9efe830b6868220 -93bee582661e6d6cefeff29002afc2f36dd2c13dbf33f0574c35b290ddc426170a5f7f196369ad592efcd72cfb6f8fc0 -89a51467d966f48fed15dea5a12dda54d0015f69e2169b5e34f44c7b5a5d4c282d6f138116a0cd06a8476980e420f8d8 -b8ccebc14b6679ba2399370848864f15f63512fd6139df7359b7b93e82c1007fd85137ecb0597294b46643e1a9e7ab5e -841fa301567fc57b2cd09508ce75326684e12bfb8add671dc208f579b2500b93d5b641e9f59bba798ed4ed1259757f7d -b3cb45c15eb00b4ccb7013299f761cb8fefc17adf6db50e9ecb8abe927a3bc7f28e359e64693813e078e1dac800ad55b -96e55d3b9f445f5679e34fa5425b3e87cb221cfbdd07f8353868c7f7f4ba388ee3841cb9a1d638583bc20d03a9d071f2 -a7dee9377de740270c5b57cf86699004ba8dc2766af56b388b5cb0814ec71bb99ecf43ee3d82a552733854ecc7def0fe -b129dfff23b3c1c95ddb214c4711961fcb129efe2b6557ec9e116ada909593d0d2eec2c628434493393c58c52aa86847 -aed2670e201cb3e38a8be3c86735a4d76255e1e5a4c67b91df6ed262d09c8d10b0a3891da3e6ab934058cc9a7178931b -b20b8921ae52e5b3c94fa3a8b46489044174f7b897779e7763d6eb419e808d76705b7e7ba5131576f425aa81b6b0de53 -a7e45bbc3ba1bc36617291ba7663806e247f1b57a89e31520c64a90cbf8d426cac2e2f381338baf78c8f92fdbbcb7026 -a99e651e73a507e9e663e2364fcc193ec77e8afdc08c2bed6ad864e49b537ec31e9114ee72291a7657899f2033a849e2 -af966033636c2e9e8280d173f556fe07f8b6940bbcf6b2df7e2165c30bea66cced2596f6c17ca7c1aa0e614174953ba9 -b69ca7a79e3d55ef21e0ebdc6f0c4bd17182d30cf6290cccca7d2551c91c12b966020d8e40e4ee4179488c9809c03ae4 -b981cd36244e035fef043f70b1d7188d7cd045b4de0581c459fc5730e10eb7f3d5893b54cc4243849c0855e4e621167a -b20fea858a36921b35a3051ce787b73f70fdecd3fef283c15a2eb1bffb1dcba5991eee4a047ce4e87802da923fd9457b -b040e6f2e56dc1860274c263d4045837456f74b354a679f6b5ea70919835ebe5d32bf1f519e218730096c98ff396dc9d -8d2dd60e702c923a7204b530e7d6c193c6f93ca648c4f7bb38f4edbeb0aaed84184213afafb8db6aeb9197c24364276c -95dfa7348709e43d71285b28a0bfad3ca805b6ed4ae99753e9f736c79d58a35a3a50b42760ccdd03eda50f6e59494968 -b8585632a13f18c139a411bb2f02df809591834d127cd1ff081e26d0abfe0e3fbb54abea26538b25a0dcb4d7e969590e -b46ba47858a29c6d523c9982660949567666daf2582b93393a4802a9e077eedbc0d49d454731696bc8e46ca50c7caa40 -84b756b901b98a4404e58d70f39f6ccac877146c866732ae65e7e82727448d1550343bf7cdff1bfd4ee1ed73793db255 -83e5be888eaf877a2c755897410865f64a6d1169a8ccf0336092f3932abab915e542ab75a35ffe016042340d581ee987 -8cb274fc39285aed451a7def72cfbf73168ee10be02affe355a2bf87cf361a81ad284e9334cf00c5bf99a13d9f75e116 -91ff6220924b94ae13f50eeac16a159232e4f16a73fbd5c22c0e185cd1998403904d36bad203baa82b85819ee4a8ac10 -87f46e08e09aea2ab37b55fc300689d9b58ff3e72f1cffe023386035888f714fac4673c7c5193d3f3f3c568c640694f0 -835d7d84ca7641e1b15095830114aa6072fe12260d2202456cafe2308c22651af9ffbcf6b7e56af97167dd0c4e2a4cf2 -91202183f79794f114fd9e3b9bd05553c0e8985919965101a57d97ef666b028863e6cea9735af016dc1864f1542dee51 -81ab2b02a9b0a490a74ae615ddd4fe560734c1bfdde6b8dd13303c1481ba0e8ab14473535a93cfe4e824a0ab29445f8c -8a32d73f4fc006551d4e2c61eec6130355ec9b8c39a65c24ec1edc00e80155ca83a8ef2455e892521a3d47634d82a987 -af70d7b8f13bc90193cc1cfb0c400c4224cf10f1887848aa93e6380f7087782fc41a159926ab53c53eb95c2383b1a849 -989bf42f9d357c51774f1c7c0f7c0c46a8cb7398a74497141c32685be098e38b4230ffe833a6d880ec391a35b1a747b6 -94cb6715ee95700020c630b8c19e35f231de970219bd7e6ba7ced01899197da473b6c45cacfab0d652ddaf547b4ea58c -b12e3331f1f7d7458393a785e22e9a5e1d1daea521b4e78c0ee8ca59b41ade1735a29820e18f6afb2f2c3c56fecc16b6 -ad4b7cf654349d136fb41fb0dd65b588199f68b462b05f5c4e5c2b468bfaa6c26329033e3c3f7873dc8ace89cf873ea5 -a3279969e1ab596df0559ffc5ac7a6dc849680354e01c3f4fd34c6413a3f9f046f89c1e1be0b315d8b6dfab3d23d5c14 -ac74cc5562836ed89d09a9ae6a3644c936d64bdda9e77659d9982f1be29541b03ef2723236d5465e398373ea19a4ccc6 -98138ebce1af531dd8b631b3e74c84f0c700355a2a9bde31e5e51bb10c8bbd766559c63f6041f4002568803fe08438e0 -9006445da131349fe5714e0777a4f82a82da343612589a0c1596393e8b6894ce1cf42784f95ff67a8384ffe1f1a4ad76 -88502a84a85e4ce54cfed297b5d355867cc770a8ffd0714a6f23b1ab320a9903c6e42809e034bb67dbf94c4fc0d9c790 -aa8b4bf123d1a6ccaa44b86be8f980005f2a0a388a76cb111b0e85cd072ef64167fb0c097c7b23c4bca64c0260f6cce0 -ad49eb35dfea9feabb513a78dd1152ad7eba22fbb02a80cefc494a7037699c8df81202dfec12acc1b9e33ad680cb72d2 -8694da730231b29afd5196371ddcb15b4dcc499574bdd063f4864ab80749833ea38ab8b0ca1629a367fe378e87a60a86 -8eca7b488e810c479e7e32e24b8afcd837f7df183fe4f621a0336b53a9ed77603c84bdc365d8be68179a32b71a1deb7e -8875cd3e23c7e1af55af1b091025a08255743984186770bcd43f30b4a58d175cfdf1984bad97a15e08dac2da27198c3d -abdafcf58ec72997e494d4714645f40d09dcd0fbd0733e640eca44eeea67c25bb0c270299c459991f2fae59d13b4f4d5 -8f040970141e61489284f3efd907705eae6ec757fe8e1d284eac123d313e9ac1e8dc14ae3f04d281e1effc49d5d2f51d -a7ff115f0d2dbf66c0e8770b3d05157b37357b9e33e9a447f0f3fa9da69ad04e371fd1e4848cfb9e8d05e3165bd969d8 -a39b1a8c39d317fcc97bf6c396e6ed4a85640aeeadbf45166bd02bc3bdfb6266509159c03afd492e642384c635b824c0 -a2e1b90f3dd2d0038eaa5be52127844ccf35d997143179d95ffd3749c0896398b130094d01eb1bb31ffe80ef34b42b48 -a2bbe31f89b0c3c375ffaf63c8b7831860a921d5e388eb7907dbf61f2601ea40db86bb3952ecaa26a5eca4317a848ff9 -87d885bb0f2ce04b40ce94d2557c15f1698dc652e938f9a2d69a73ccf4899e08eafa1a59a20cae92823795f5b94f04b9 -8f7746370f8a24a2889d351f3e36b8a7d60e75e50e8f5abeea7dafc75441e95915721654e61ceac51bb6f112780d352c -a7272847526ed3d9e0d0fea1d8685b07b5b908971490bf8a46748c8b1783c629b8644feb5bac772ae615daae383d5e72 -978c9aa2996d8bd6fda7e0393fa8b38747f8f99712427705c00f6e9a12c36f8d8b4cedb03fcb9867155cbddb5200e6e1 -a4dec4a2354b2b32434c5bcdc380bf84580c6f9940f94dc0498a5bfe89c675a0921e66b807a3d859a6059a464cb2a9ac -99459ddecc7abce437f68722dae556d8ffaf8ed974f459e52e6d4a64f176caa4d42c2f2ec57e8a5b5f2034638e8acb0a -928c68c0c9213fe6258ab5bb0c693d97203d15da359784de7824dec143212da57d062a1fc70a79172cee31adc7aff382 -aad3f318f1622ea87e12541dfd982d71629b8f1ded4c301f9f6b6af9432716ad057773c33bdaa6f15dc151b0ee4505ea -8eb8e978f149a983fd6ad01773f9aacf57bd0cc622d8a301e404184b37e610123dd081faeda571a0ab1f149a3960af10 -851e7191d7b94bd422bcece5b92609fc1b1c8556229bc53e32963b2d2fd1cacd8ce5da9040b599eca6e610540f8a7987 -9414157fe9d50e5a0b5a7397417681bcb3a651eec1cab63f2a88d5df68ab1fef6e4c1d7ba657cbaf241a7cb790297633 -b5cb2dafdc5408959780754a58b2da55b2a9136672ebca42f34da4e329ddc89360e7218cde3efdbf784ddb390deacc57 -ac6b70f65503a8e94b773fda3e72615745824930114fe72b6d833484285462392617c1b2eea4a250fedbee88f503f3ba -b0829a5312f9ac6c06fddee2f835a3452fe994f6d42c9edfc390d7d5b3240ca544433b544cbbddd6516b38a6d5d7c21d -95f8e2c59905957e34d53be3d6fb85732f834e2cb9ab4c333fea2f502452a87ccd035fc9075d7c0bd8530bb0a0c96527 -b93f279b7045f2d97c674495f6e69a3e352f32f43cc60300193b936c2850b2805c15457251f7e3f633f435cb2b60405c -915abf16cba1a0b655b92a8a70c03e7fb306b86f3bbfb66967ca63e64c003b59c7a5953675efa4fa0bce9bed536b6700 -ac2047f50a319d09df1ec44d71afdcec5ac3bd2765dc98aba347734aa780863545df9f6d71214d443e3f37edc0dae45a -ad49c74ddb24c8a26b14ec08bc807313c77c5967fbb36237f55994d7511bbac8d7e7b9b8ec53eb1b3b066989f078dbd9 -961483105f605e959213fe9e8a52b76dac62d7efd2319ec71fc4e92d68fbe44cd2f65d7adefb2eb64d591b91648b8085 -b67fcafc97d8df2b3075bbff7b3d7471dbf1f3048f309e55d5e2c5bcbc7a73aebcb0697859be9f387cbc7ce98041e154 -8da70ac16468cab6066992389cb37c79ff5e0babbe67d76878aef9408b9597a3dc2eb5de87428bc761a0d78957b0eb28 -aec0ce89770d299b631f15ae12f94b1e1014ac57d38fcf037c2c7712d770d074affa06e97c60691bad8733874b6ad2ed -8b702c85fa4c915a09fc86507f44d7aeda0993b77af87780d70cc98d580c6e996b64b7c16cdb4dd4562cb0f75da36ee7 -aaeb43aa472aac2253e211fd1066c3a5422ea041cef20168702d0618a1a742a44f7fb30a76677640fea1a24e7fae1996 -a8820e92825d6e02b9b4ad5ebc86161d3244cddd3d244333ba1576b6ae10948145b68d9e926bf6b7a2c25dab4cf43f3e -8ffdae28a1f1d15d7ffa473628a66ee9a739073f59ba781248286b39cb8f7255f66d62337064246713cbb5017e615174 -adfc5dd142b7911326d8424881d5d92006f3b17de4cce91674d6ea37f00fbb266c791ac13f6c7a0f61d04f2a952e6a04 -87f98982444bf661f539bec73a10256f079a4baa88a1cea0351ae3de929e1c500485b2d1b5d933063cd7d9123d5050e4 -8f217ba4dd404c5ee384f0c9a126686db001ff0344c01c82174c5e5ef89d1a241b146008c534b13a0da6c8afe7450fbb -afc85476dddaf1cbb4ba8b22186789f3818c7964f9f613e55010278800cd95422702248bdf9c73760702ef24854795ec -a59e0f6ac2ccdfbd01f002008034390c0ea78716f5e0de4e474e3558755705c9c7afb6e3c5c4370e7bbc85958a9c7a63 -97c0695c58d792ec31d9b86d3b2fc1382f0855057b24d5f6a54c41f76f9e2f52882cadc89a8b2f121530e7f1393faa95 -8e49112de0b2649c08a96cf737af68fa8055f1af594846a2d0534c94df6f926f200405edaa6e6ac9db7e380707a2571d -99a1bd83a7ac5f8d77ddf044c80ebfc5745b998714696d67b94d185c97e9d6db989bacac646d9def463127a8b2febc00 -aba80725f9f9f7abe10760eca73ba427ca8df864a157122eb9af828a05b0199de3add02019a297750bdab5380e505c58 -ae18f62573275c1eb268f74c5e54e8958547f9e7d1d36a05b084eb53e5704fafe2200b8aff95cc7e9af5be2391c42b7c -908b8031d09d22b2aefeaa876a998e0a97c7a1070aad9e9c97836cc5aa6d2d5ef94230e1222074837b5e21b4e6490f01 -b3132282e8b41ca6789ec5c43c1fecf3a65b8eefbc2f3d10f746a843b9ba4ce6db664678e75e424f7b11a00c1440de15 -a1eb49440cc106ebc09cf198c93e8070271eb5a936d31c04858a2b311a037350100c7957d5545c9653f396aa968b91f4 -81df6ad1bdd5eee4cc2f94318467b8602d15cc1be2b48b09ade12cc46ee05cbaaf77a20397e5015030b1f1db5dd9dac0 -87236c68a2a93c8442d15d7f1d1dc01d1fd123439c183e1d843f4ddd2bcf638c128f66f1ef9b710e5d1f64a52726007a -84f2e7f85563bb2f61b10a712c7605d63f79af5be0dba056814fd3efebc20e9c53227c56577b72c68d185571b775eff6 -a36d4ae06688ece2927aeb2c7f058a3cd2aa1de1601282d4e688e1d76ef20728b892928deda2314eba41675eba3912f1 -b8326dcbcdcfce017b263c456c47692fb476c4225c95981666fff0b7d4522fc23b7f12273f0f47cf0442662124e6648f -84c66463ab277cda2cc7007d0509269e89cdd41c5e0d3773a92615f0fc5da63811186b05d7a11088048a5d4834a7e0df -b20d3571d970712ef4699b0e7034fd269c361f53e1572e2ea2676b4245e992d43b8b5931a801439a44d977a988cc360b -94dba6007e6d4998ca1eb84aa8e2a7e9f5c164b9d80df2825f2208ce5640a05aacac2e4f08918268990f43ae1ccab69a -a1c25f0b3ef9d1982153207570d9ce8d692e1b6963b509958dc4d9bcd80074bb221c46804a6d9a29e76149cc7787c282 -8857748fcdab1199fc96084323a81d3bd8b5a7f0b1abc5bc3b5252a19268344e2e7d2d086c90fc9b5fa4b92feedb93a4 -8b9c1d841447354b6c086549e4d1d435ab64c13933488c34bc30f0f6eb36c5c5b838b7b6bb018542247edd1ada091045 -8f5b655416da0e719a204fc567e93792c301acb4374cf7bbabc6ce51dbeaaadfd75c2db0e16ce073ab8e91fd3d7ea9d4 -90f2846b19be46a75c5cd0cafefcf9192e6fd80c479e8d6320c4b8d8d7d96703c9e77ff31a67afa9858e6b7bde1f7cce -a53e383947fd98aa1a55ac956214b46b20a52758461e8ba41341a23a835ebb713038bf048edb1202bbfd0b56a96bf292 -9542d7debbcfb9cda6fa279c699a7b655c03b9a9b456a5d3cfc41a826c94eafa43e01155a29e39ff0bcd965f4c0c512d -a43792864ec5fc549f7afc02622454afc0e425c310c4039ba615067243ebb26a4c7ebfd19bd4d57ff412a4bb2a7958a0 -b85123950e30c048465bf32365d24a5d4b21fffc6183cdbf71643a07b87463989b72dd9a6a47f134856f704909a6b38f -944ea689aec1376f855c0bc9c51378ad06ff758a2c075b95a60b535b88b36eca0be11e4edb5152e98cb2137d6e749f27 -a6bef52cda22325e4c62d323e2a0e3fa91c5552fcfce951edfd52ad6f652bfdcc2341f1cd349e6b5d447924dc569bfe2 -b56bff8ffe981bfcb30791836da10b87f2ccbe17ed969e7f7a650af07d27ae0223805b1264d985148208483be50578a6 -8b209cac898dd580c82d854a553e2517497ad1a4cd198e1360b8b50639b380aee70ee4b87625d9b2278228ff644cd25c -877cce233fec74c7158b3c5bf108365e98238418b8a71f058f1aca44a0fd3a1021e3e9025bd11fe244d9fe0f5034ce7f -b1b871aeedb03d6f6accc99816b89f5958178738d8d8cd9717527d04363c80fdb5f6848122ae19fdbc450cfa11e753c8 -858aca51b9e5b0a724e88688d5124eb24c9faf01a3d465e74d31de6da315f311143f22f60201ea09f62c92f61f09d889 -8521d409615dfc8c8289e00f6aaa6297c2c4e1439b25952afd76aac641b81c70b9cef07cd58c1c0198382bddd2bd8544 -88647c3e41666b88acca42505f1f5da226937e0522b538fe0cebb724e9a99730ca2522989e94a96cac94109aef675c0f -b417fdaf719caf38854e89ce52031b30ce61a632e6c3135adec9002280e022d82ab0ea4ac5ebdb21f1f0169e4c37bcda -9367a6feb5e23ea2eab8ddd5e7bdf32b4d2419fad1c71a1ed327b77362d8942dad971a1c2e6f7073885149cdf0a0c339 -a71c5c08d50c57d094d6a4f02e97d3799bada92f238ffc07bd223bbe8379507b7310d20b28f5bbbf331e5e153515e491 -9630a9a3bcb044b51299c4d3d3388a4ff47308dd27be3229601985478c0f6b55faa7e20815d8694f910611396a9d0d45 -b0bfaf56a5aa59b48960aa7c1617e832e65c823523fb2a5cd44ba606800501cf873e8db1d0dda64065285743dc40786e \ No newline at end of file From d393930a3d306ad961e9d91f4ae61ce9c700c31d Mon Sep 17 00:00:00 2001 From: ramonliu Date: Tue, 29 Apr 2025 11:43:22 +0800 Subject: [PATCH 1197/1197] update a new version. version name:GreatVoyage-v4.7.7-243-gb3555dd655,version code:18631 --- framework/src/main/java/org/tron/program/Version.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index feff4d0f92f..4e9528ee50e 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -2,8 +2,8 @@ public class Version { - public static final String VERSION_NAME = "GreatVoyage-v4.7.6-12-gf4da4fafb1"; - public static final String VERSION_CODE = "18386"; + public static final String VERSION_NAME = "GreatVoyage-v4.7.7-243-gb3555dd655"; + public static final String VERSION_CODE = "18631"; private static final String VERSION = "4.8.0"; public static String getVersion() {

    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

pC+!1javOq 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